diff -druN linux-libre-3.1-gnu/arch/alpha/include/asm/fcntl.h linux-libre-3.2-gnu/arch/alpha/include/asm/fcntl.h
--- linux-libre-3.1-gnu/arch/alpha/include/asm/fcntl.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/alpha/include/asm/fcntl.h	2012-01-04 18:55:44.000000000 -0500
@@ -51,8 +51,6 @@
 #define F_EXLCK		16	/* or 3 */
 #define F_SHLCK		32	/* or 4 */
 
-#define F_INPROGRESS	64
-
 #include <asm-generic/fcntl.h>
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/alpha/include/asm/unistd.h linux-libre-3.2-gnu/arch/alpha/include/asm/unistd.h
--- linux-libre-3.1-gnu/arch/alpha/include/asm/unistd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/alpha/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -457,10 +457,12 @@
 #define __NR_clock_adjtime		499
 #define __NR_syncfs			500
 #define __NR_setns			501
+#define __NR_accept4			502
+#define __NR_sendmmsg			503
 
 #ifdef __KERNEL__
 
-#define NR_SYSCALLS			502
+#define NR_SYSCALLS			504
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff -druN linux-libre-3.1-gnu/arch/alpha/Kconfig linux-libre-3.2-gnu/arch/alpha/Kconfig
--- linux-libre-3.1-gnu/arch/alpha/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/alpha/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -445,11 +445,6 @@
 	  Is this a machine based on the EV67 core?  If in doubt, select N here
 	  and the machine will be treated as an EV6.
 
-config ALPHA_EV7
-	bool
-	depends on ALPHA_MARVEL
-	default y
-
 config ALPHA_MCPCIA
 	bool
 	depends on ALPHA_RAWHIDE
diff -druN linux-libre-3.1-gnu/arch/alpha/kernel/core_irongate.c linux-libre-3.2-gnu/arch/alpha/kernel/core_irongate.c
--- linux-libre-3.1-gnu/arch/alpha/kernel/core_irongate.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/alpha/kernel/core_irongate.c	2012-01-04 18:55:44.000000000 -0500
@@ -303,6 +303,7 @@
 #include <linux/vmalloc.h>
 #include <linux/agp_backend.h>
 #include <linux/agpgart.h>
+#include <linux/export.h>
 #include <asm/pgalloc.h>
 
 #define GET_PAGE_DIR_OFF(addr) (addr >> 22)
diff -druN linux-libre-3.1-gnu/arch/alpha/kernel/pci_iommu.c linux-libre-3.2-gnu/arch/alpha/kernel/pci_iommu.c
--- linux-libre-3.1-gnu/arch/alpha/kernel/pci_iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/alpha/kernel/pci_iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
 #include <linux/pci.h>
 #include <linux/gfp.h>
 #include <linux/bootmem.h>
+#include <linux/export.h>
 #include <linux/scatterlist.h>
 #include <linux/log2.h>
 #include <linux/dma-mapping.h>
diff -druN linux-libre-3.1-gnu/arch/alpha/kernel/pci-sysfs.c linux-libre-3.2-gnu/arch/alpha/kernel/pci-sysfs.c
--- linux-libre-3.1-gnu/arch/alpha/kernel/pci-sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/alpha/kernel/pci-sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <linux/sched.h>
+#include <linux/stat.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
 
diff -druN linux-libre-3.1-gnu/arch/alpha/kernel/setup.c linux-libre-3.2-gnu/arch/alpha/kernel/setup.c
--- linux-libre-3.1-gnu/arch/alpha/kernel/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/alpha/kernel/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@
 #include <asm/setup.h>
 #include <asm/io.h>
 #include <linux/log2.h>
+#include <linux/export.h>
 
 extern struct atomic_notifier_head panic_notifier_list;
 static int alpha_panic_event(struct notifier_block *, unsigned long, void *);
diff -druN linux-libre-3.1-gnu/arch/alpha/kernel/srm_env.c linux-libre-3.2-gnu/arch/alpha/kernel/srm_env.c
--- linux-libre-3.1-gnu/arch/alpha/kernel/srm_env.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/alpha/kernel/srm_env.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,9 +4,8 @@
  *
  * (C) 2001,2002,2006 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
  *
- * This driver is at all a modified version of Erik Mouw's
- * Documentation/DocBook/procfs_example.c, so: thank
- * you, Erik! He can be reached via email at
+ * This driver is a modified version of Erik Mouw's example proc
+ * interface, so: thank you, Erik! He can be reached via email at
  * <J.A.K.Mouw@its.tudelft.nl>. It is based on an idea
  * provided by DEC^WCompaq^WIntel's "Jumpstart" CD. They
  * included a patch like this as well. Thanks for idea!
diff -druN linux-libre-3.1-gnu/arch/alpha/kernel/systbls.S linux-libre-3.2-gnu/arch/alpha/kernel/systbls.S
--- linux-libre-3.1-gnu/arch/alpha/kernel/systbls.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/alpha/kernel/systbls.S	2012-01-04 18:55:44.000000000 -0500
@@ -520,6 +520,8 @@
 	.quad sys_clock_adjtime
 	.quad sys_syncfs			/* 500 */
 	.quad sys_setns
+	.quad sys_accept4
+	.quad sys_sendmmsg
 
 	.size sys_call_table, . - sys_call_table
 	.type sys_call_table, @object
diff -druN linux-libre-3.1-gnu/arch/arm/boot/compressed/atags_to_fdt.c linux-libre-3.2-gnu/arch/arm/boot/compressed/atags_to_fdt.c
--- linux-libre-3.1-gnu/arch/arm/boot/compressed/atags_to_fdt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/compressed/atags_to_fdt.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,97 @@
+#include <asm/setup.h>
+#include <libfdt.h>
+
+static int node_offset(void *fdt, const char *node_path)
+{
+	int offset = fdt_path_offset(fdt, node_path);
+	if (offset == -FDT_ERR_NOTFOUND)
+		offset = fdt_add_subnode(fdt, 0, node_path);
+	return offset;
+}
+
+static int setprop(void *fdt, const char *node_path, const char *property,
+		   uint32_t *val_array, int size)
+{
+	int offset = node_offset(fdt, node_path);
+	if (offset < 0)
+		return offset;
+	return fdt_setprop(fdt, offset, property, val_array, size);
+}
+
+static int setprop_string(void *fdt, const char *node_path,
+			  const char *property, const char *string)
+{
+	int offset = node_offset(fdt, node_path);
+	if (offset < 0)
+		return offset;
+	return fdt_setprop_string(fdt, offset, property, string);
+}
+
+static int setprop_cell(void *fdt, const char *node_path,
+			const char *property, uint32_t val)
+{
+	int offset = node_offset(fdt, node_path);
+	if (offset < 0)
+		return offset;
+	return fdt_setprop_cell(fdt, offset, property, val);
+}
+
+/*
+ * Convert and fold provided ATAGs into the provided FDT.
+ *
+ * REturn values:
+ *    = 0 -> pretend success
+ *    = 1 -> bad ATAG (may retry with another possible ATAG pointer)
+ *    < 0 -> error from libfdt
+ */
+int atags_to_fdt(void *atag_list, void *fdt, int total_space)
+{
+	struct tag *atag = atag_list;
+	uint32_t mem_reg_property[2 * NR_BANKS];
+	int memcount = 0;
+	int ret;
+
+	/* make sure we've got an aligned pointer */
+	if ((u32)atag_list & 0x3)
+		return 1;
+
+	/* if we get a DTB here we're done already */
+	if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC))
+	       return 0;
+
+	/* validate the ATAG */
+	if (atag->hdr.tag != ATAG_CORE ||
+	    (atag->hdr.size != tag_size(tag_core) &&
+	     atag->hdr.size != 2))
+		return 1;
+
+	/* let's give it all the room it could need */
+	ret = fdt_open_into(fdt, fdt, total_space);
+	if (ret < 0)
+		return ret;
+
+	for_each_tag(atag, atag_list) {
+		if (atag->hdr.tag == ATAG_CMDLINE) {
+			setprop_string(fdt, "/chosen", "bootargs",
+					atag->u.cmdline.cmdline);
+		} else if (atag->hdr.tag == ATAG_MEM) {
+			if (memcount >= sizeof(mem_reg_property)/4)
+				continue;
+			mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.start);
+			mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.size);
+		} else if (atag->hdr.tag == ATAG_INITRD2) {
+			uint32_t initrd_start, initrd_size;
+			initrd_start = atag->u.initrd.start;
+			initrd_size = atag->u.initrd.size;
+			setprop_cell(fdt, "/chosen", "linux,initrd-start",
+					initrd_start);
+			setprop_cell(fdt, "/chosen", "linux,initrd-end",
+					initrd_start + initrd_size);
+		}
+	}
+
+	if (memcount)
+		setprop(fdt, "/memory", "reg", mem_reg_property, 4*memcount);
+
+	return fdt_pack(fdt);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/boot/compressed/.gitignore linux-libre-3.2-gnu/arch/arm/boot/compressed/.gitignore
--- linux-libre-3.1-gnu/arch/arm/boot/compressed/.gitignore	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/boot/compressed/.gitignore	2012-01-04 18:55:44.000000000 -0500
@@ -5,3 +5,12 @@
 piggy.lzma
 vmlinux
 vmlinux.lds
+
+# borrowed libfdt files
+fdt.c
+fdt.h
+fdt_ro.c
+fdt_rw.c
+fdt_wip.c
+libfdt.h
+libfdt_internal.h
diff -druN linux-libre-3.1-gnu/arch/arm/boot/compressed/head.S linux-libre-3.2-gnu/arch/arm/boot/compressed/head.S
--- linux-libre-3.1-gnu/arch/arm/boot/compressed/head.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/boot/compressed/head.S	2012-01-04 18:55:44.000000000 -0500
@@ -216,6 +216,104 @@
 		mov	r10, r6
 #endif
 
+		mov	r5, #0			@ init dtb size to 0
+#ifdef CONFIG_ARM_APPENDED_DTB
+/*
+ *   r0  = delta
+ *   r2  = BSS start
+ *   r3  = BSS end
+ *   r4  = final kernel address
+ *   r5  = appended dtb size (still unknown)
+ *   r6  = _edata
+ *   r7  = architecture ID
+ *   r8  = atags/device tree pointer
+ *   r9  = size of decompressed image
+ *   r10 = end of this image, including  bss/stack/malloc space if non XIP
+ *   r11 = GOT start
+ *   r12 = GOT end
+ *   sp  = stack pointer
+ *
+ * if there are device trees (dtb) appended to zImage, advance r10 so that the
+ * dtb data will get relocated along with the kernel if necessary.
+ */
+
+		ldr	lr, [r6, #0]
+#ifndef __ARMEB__
+		ldr	r1, =0xedfe0dd0		@ sig is 0xd00dfeed big endian
+#else
+		ldr	r1, =0xd00dfeed
+#endif
+		cmp	lr, r1
+		bne	dtb_check_done		@ not found
+
+#ifdef CONFIG_ARM_ATAG_DTB_COMPAT
+		/*
+		 * OK... Let's do some funky business here.
+		 * If we do have a DTB appended to zImage, and we do have
+		 * an ATAG list around, we want the later to be translated
+		 * and folded into the former here.  To be on the safe side,
+		 * let's temporarily move  the stack away into the malloc
+		 * area.  No GOT fixup has occurred yet, but none of the
+		 * code we're about to call uses any global variable.
+		*/
+		add	sp, sp, #0x10000
+		stmfd	sp!, {r0-r3, ip, lr}
+		mov	r0, r8
+		mov	r1, r6
+		sub	r2, sp, r6
+		bl	atags_to_fdt
+
+		/*
+		 * If returned value is 1, there is no ATAG at the location
+		 * pointed by r8.  Try the typical 0x100 offset from start
+		 * of RAM and hope for the best.
+		 */
+		cmp	r0, #1
+		sub	r0, r4, #TEXT_OFFSET
+		add	r0, r0, #0x100
+		mov	r1, r6
+		sub	r2, sp, r6
+		blne	atags_to_fdt
+
+		ldmfd	sp!, {r0-r3, ip, lr}
+		sub	sp, sp, #0x10000
+#endif
+
+		mov	r8, r6			@ use the appended device tree
+
+		/*
+		 * Make sure that the DTB doesn't end up in the final
+		 * kernel's .bss area. To do so, we adjust the decompressed
+		 * kernel size to compensate if that .bss size is larger
+		 * than the relocated code.
+		 */
+		ldr	r5, =_kernel_bss_size
+		adr	r1, wont_overwrite
+		sub	r1, r6, r1
+		subs	r1, r5, r1
+		addhi	r9, r9, r1
+
+		/* Get the dtb's size */
+		ldr	r5, [r6, #4]
+#ifndef __ARMEB__
+		/* convert r5 (dtb size) to little endian */
+		eor	r1, r5, r5, ror #16
+		bic	r1, r1, #0x00ff0000
+		mov	r5, r5, ror #8
+		eor	r5, r5, r1, lsr #8
+#endif
+
+		/* preserve 64-bit alignment */
+		add	r5, r5, #7
+		bic	r5, r5, #7
+
+		/* relocate some pointers past the appended dtb */
+		add	r6, r6, r5
+		add	r10, r10, r5
+		add	sp, sp, r5
+dtb_check_done:
+#endif
+
 /*
  * Check to see if we will overwrite ourselves.
  *   r4  = final kernel address
@@ -223,15 +321,14 @@
  *   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
+ *   r4 + image length <= address of wont_overwrite -> 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		)
+		adr	r9, wont_overwrite
+		cmp	r10, r9
 		bls	wont_overwrite
 
 /*
@@ -285,14 +382,16 @@
  *   r2  = BSS start
  *   r3  = BSS end
  *   r4  = kernel execution address
+ *   r5  = appended dtb size (0 if not present)
  *   r7  = architecture ID
  *   r8  = atags pointer
  *   r11 = GOT start
  *   r12 = GOT end
  *   sp  = stack pointer
  */
-		teq	r0, #0
+		orrs	r1, r0, r5
 		beq	not_relocated
+
 		add	r11, r11, r0
 		add	r12, r12, r0
 
@@ -307,12 +406,21 @@
 
 		/*
 		 * Relocate all entries in the GOT table.
+		 * Bump bss entries to _edata + dtb size
 		 */
 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.
+		add	r1, r1, r0		@ This fixes up C references
+		cmp	r1, r2			@ if entry >= bss_start &&
+		cmphs	r3, r1			@       bss_end > entry
+		addhi	r1, r1, r5		@    entry += dtb size
+		str	r1, [r11], #4		@ next entry
 		cmp	r11, r12
 		blo	1b
+
+		/* bump our bss pointers too */
+		add	r2, r2, r5
+		add	r3, r3, r5
+
 #else
 
 		/*
diff -druN linux-libre-3.1-gnu/arch/arm/boot/compressed/libfdt_env.h linux-libre-3.2-gnu/arch/arm/boot/compressed/libfdt_env.h
--- linux-libre-3.1-gnu/arch/arm/boot/compressed/libfdt_env.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/compressed/libfdt_env.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,15 @@
+#ifndef _ARM_LIBFDT_ENV_H
+#define _ARM_LIBFDT_ENV_H
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/byteorder.h>
+
+#define fdt16_to_cpu(x)		be16_to_cpu(x)
+#define cpu_to_fdt16(x)		cpu_to_be16(x)
+#define fdt32_to_cpu(x)		be32_to_cpu(x)
+#define cpu_to_fdt32(x)		cpu_to_be32(x)
+#define fdt64_to_cpu(x)		be64_to_cpu(x)
+#define cpu_to_fdt64(x)		cpu_to_be64(x)
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/boot/compressed/Makefile linux-libre-3.2-gnu/arch/arm/boot/compressed/Makefile
--- linux-libre-3.1-gnu/arch/arm/boot/compressed/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/boot/compressed/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,10 @@
 OBJS	+= misc.o decompress.o
 FONTC	= $(srctree)/drivers/video/console/font_acorn_8x8.c
 
+# string library code (-Os is enforced to keep it much smaller)
+OBJS		+= string.o
+CFLAGS_string.o	:= -Os
+
 #
 # Architecture dependencies
 #
@@ -89,21 +93,41 @@
 suffix_$(CONFIG_KERNEL_LZO)  = lzo
 suffix_$(CONFIG_KERNEL_LZMA) = lzma
 
+# Borrowed libfdt files for the ATAG compatibility mode
+
+libfdt		:= fdt_rw.c fdt_ro.c fdt_wip.c fdt.c
+libfdt_hdrs	:= fdt.h libfdt.h libfdt_internal.h
+
+libfdt_objs	:= $(addsuffix .o, $(basename $(libfdt)))
+
+$(addprefix $(obj)/,$(libfdt) $(libfdt_hdrs)): $(obj)/%: $(srctree)/scripts/dtc/libfdt/%
+	$(call cmd,shipped)
+
+$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o): \
+	$(addprefix $(obj)/,$(libfdt_hdrs))
+
+ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y)
+OBJS	+= $(libfdt_objs) atags_to_fdt.o
+endif
+
 targets       := vmlinux vmlinux.lds \
 		 piggy.$(suffix_y) piggy.$(suffix_y).o \
-		 font.o font.c head.o misc.o $(OBJS)
+		 lib1funcs.o lib1funcs.S font.o font.c head.o misc.o $(OBJS)
 
 # Make sure files are removed during clean
-extra-y       += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S
+extra-y       += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S $(libfdt) $(libfdt_hdrs)
 
 ifeq ($(CONFIG_FUNCTION_TRACER),y)
 ORIG_CFLAGS := $(KBUILD_CFLAGS)
 KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
 endif
 
-ccflags-y := -fpic -fno-builtin
+ccflags-y := -fpic -fno-builtin -I$(obj)
 asflags-y := -Wa,-march=all
 
+# Supply kernel BSS size to the decompressor via a linker symbol.
+KBSS_SZ = $(shell size $(obj)/../../../../vmlinux | awk 'END{print $$3}')
+LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ)
 # Supply ZRELADDR to the decompressor via a linker symbol.
 ifneq ($(CONFIG_AUTO_ZRELADDR),y)
 LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR)
@@ -123,7 +147,7 @@
 # For __aeabi_uidivmod
 lib1funcs = $(obj)/lib1funcs.o
 
-$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE
+$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S
 	$(call cmd,shipped)
 
 # We need to prevent any GOTOFF relocs being used with references
@@ -139,8 +163,16 @@
   ( echo "following symbols must have non local/private scope:" >&2; \
     echo "$$bad_syms" >&2; rm -f $@; false )
 
+check_for_multiple_zreladdr = \
+if [ $(words $(ZRELADDR)) -gt 1 -a "$(CONFIG_AUTO_ZRELADDR)" = "" ]; then \
+	echo 'multiple zreladdrs: $(ZRELADDR)'; \
+	echo 'This needs CONFIG_AUTO_ZRELADDR to be set'; \
+	false; \
+fi
+
 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
 	 	$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
+	@$(check_for_multiple_zreladdr)
 	$(call if_changed,ld)
 	@$(check_for_bad_syms)
 
diff -druN linux-libre-3.1-gnu/arch/arm/boot/compressed/misc.c linux-libre-3.2-gnu/arch/arm/boot/compressed/misc.c
--- linux-libre-3.1-gnu/arch/arm/boot/compressed/misc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/boot/compressed/misc.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,14 +18,9 @@
 
 unsigned int __machine_arch_type;
 
-#define _LINUX_STRING_H_
-
 #include <linux/compiler.h>	/* for inline */
-#include <linux/types.h>	/* for size_t */
-#include <linux/stddef.h>	/* for NULL */
+#include <linux/types.h>
 #include <linux/linkage.h>
-#include <asm/string.h>
-
 
 static void putstr(const char *ptr);
 extern void error(char *x);
@@ -101,41 +96,6 @@
 	flush();
 }
 
-
-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;
-}
-
 /*
  * gzip declarations
  */
diff -druN linux-libre-3.1-gnu/arch/arm/boot/compressed/string.c linux-libre-3.2-gnu/arch/arm/boot/compressed/string.c
--- linux-libre-3.1-gnu/arch/arm/boot/compressed/string.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/compressed/string.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,127 @@
+/*
+ * arch/arm/boot/compressed/string.c
+ *
+ * Small subset of simple string routines
+ */
+
+#include <linux/string.h>
+
+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 *memmove(void *__dest, __const void *__src, size_t count)
+{
+	unsigned char *d = __dest;
+	const unsigned char *s = __src;
+
+	if (__dest == __src)
+		return __dest;
+
+	if (__dest < __src)
+		return memcpy(__dest, __src, count);
+
+	while (count--)
+		d[count] = s[count];
+	return __dest;
+}
+
+size_t strlen(const char *s)
+{
+	const char *sc = s;
+
+	while (*sc != '\0')
+		sc++;
+	return sc - s;
+}
+
+int memcmp(const void *cs, const void *ct, size_t count)
+{
+	const unsigned char *su1 = cs, *su2 = ct, *end = su1 + count;
+	int res = 0;
+
+	while (su1 < end) {
+		res = *su1++ - *su2++;
+		if (res)
+			break;
+	}
+	return res;
+}
+
+int strcmp(const char *cs, const char *ct)
+{
+	unsigned char c1, c2;
+	int res = 0;
+
+	do {
+		c1 = *cs++;
+		c2 = *ct++;
+		res = c1 - c2;
+		if (res)
+			break;
+	} while (c1);
+	return res;
+}
+
+void *memchr(const void *s, int c, size_t count)
+{
+	const unsigned char *p = s;
+
+	while (count--)
+		if ((unsigned char)c == *p++)
+			return (void *)(p - 1);
+	return NULL;
+}
+
+char *strchr(const char *s, int c)
+{
+	while (*s != (char)c)
+		if (*s++ == '\0')
+			return NULL;
+	return (char *)s;
+}
+
+#undef memset
+
+void *memset(void *s, int c, size_t count)
+{
+	char *xs = s;
+	while (count--)
+		*xs++ = c;
+	return s;
+}
+
+void __memzero(void *s, size_t count)
+{
+	memset(s, 0, count);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/boot/compressed/vmlinux.lds.in linux-libre-3.2-gnu/arch/arm/boot/compressed/vmlinux.lds.in
--- linux-libre-3.1-gnu/arch/arm/boot/compressed/vmlinux.lds.in	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/boot/compressed/vmlinux.lds.in	2012-01-04 18:55:44.000000000 -0500
@@ -51,6 +51,10 @@
   _got_start = .;
   .got			: { *(.got) }
   _got_end = .;
+
+  /* ensure the zImage file size is always a multiple of 64 bits */
+  /* (without a dummy byte, ld just ignores the empty section) */
+  .pad			: { BYTE(0); . = ALIGN(8); }
   _edata = .;
 
   . = BSS_START;
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/at91sam9g20.dtsi linux-libre-3.2-gnu/arch/arm/boot/dts/at91sam9g20.dtsi
--- linux-libre-3.1-gnu/arch/arm/boot/dts/at91sam9g20.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/at91sam9g20.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,119 @@
+/*
+ * at91sam9g20.dtsi - Device Tree Include file for AT91SAM9G20 family SoC
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>,
+ *                2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9G20 family SoC";
+	compatible = "atmel,at91sam9g20";
+	interrupt-parent = <&aic>;
+
+	aliases {
+		serial0 = &dbgu;
+		serial1 = &usart0;
+		serial2 = &usart1;
+		serial3 = &usart2;
+		serial4 = &usart3;
+		serial5 = &usart4;
+		serial6 = &usart5;
+	};
+	cpus {
+		cpu@0 {
+			compatible = "arm,arm926ejs";
+		};
+	};
+
+	memory@20000000 {
+		reg = <0x20000000 0x08000000>;
+	};
+
+	ahb {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			aic: interrupt-controller@fffff000 {
+				#interrupt-cells = <1>;
+				compatible = "atmel,at91rm9200-aic";
+				interrupt-controller;
+				interrupt-parent;
+				reg = <0xfffff000 0x200>;
+			};
+
+			dbgu: serial@fffff200 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffff200 0x200>;
+				interrupts = <1>;
+				status = "disabled";
+			};
+
+			usart0: serial@fffb0000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffb0000 0x200>;
+				interrupts = <6>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart1: serial@fffb4000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffb4000 0x200>;
+				interrupts = <7>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart2: serial@fffb8000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffb8000 0x200>;
+				interrupts = <8>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart3: serial@fffd0000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffd0000 0x200>;
+				interrupts = <23>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart4: serial@fffd4000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffd4000 0x200>;
+				interrupts = <24>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart5: serial@fffd8000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffd8000 0x200>;
+				interrupts = <25>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/at91sam9g45.dtsi linux-libre-3.2-gnu/arch/arm/boot/dts/at91sam9g45.dtsi
--- linux-libre-3.1-gnu/arch/arm/boot/dts/at91sam9g45.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/at91sam9g45.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,106 @@
+/*
+ * at91sam9g45.dtsi - Device Tree Include file for AT91SAM9G45 family SoC
+ *                    applies to AT91SAM9G45, AT91SAM9M10,
+ *                    AT91SAM9G46, AT91SAM9M11 SoC
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9G45 family SoC";
+	compatible = "atmel,at91sam9g45";
+	interrupt-parent = <&aic>;
+
+	aliases {
+		serial0 = &dbgu;
+		serial1 = &usart0;
+		serial2 = &usart1;
+		serial3 = &usart2;
+		serial4 = &usart3;
+	};
+	cpus {
+		cpu@0 {
+			compatible = "arm,arm926ejs";
+		};
+	};
+
+	memory@70000000 {
+		reg = <0x70000000 0x10000000>;
+	};
+
+	ahb {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			aic: interrupt-controller@fffff000 {
+				#interrupt-cells = <1>;
+				compatible = "atmel,at91rm9200-aic";
+				interrupt-controller;
+				interrupt-parent;
+				reg = <0xfffff000 0x200>;
+			};
+
+			dma: dma-controller@ffffec00 {
+				compatible = "atmel,at91sam9g45-dma";
+				reg = <0xffffec00 0x200>;
+				interrupts = <21>;
+			};
+
+			dbgu: serial@ffffee00 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xffffee00 0x200>;
+				interrupts = <1>;
+				status = "disabled";
+			};
+
+			usart0: serial@fff8c000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfff8c000 0x200>;
+				interrupts = <7>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart1: serial@fff90000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfff90000 0x200>;
+				interrupts = <8>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart2: serial@fff94000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfff94000 0x200>;
+				interrupts = <9>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart3: serial@fff98000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfff98000 0x200>;
+				interrupts = <10>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/at91sam9m10g45ek.dts linux-libre-3.2-gnu/arch/arm/boot/dts/at91sam9m10g45ek.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/at91sam9m10g45ek.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/at91sam9m10g45ek.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * at91sam9m10g45ek.dts - Device Tree file for AT91SAM9M10G45-EK board
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9g45.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9M10G45-EK";
+	compatible = "atmel,at91sam9m10g45ek", "atmel,at91sam9g45", "atmel,at91sam9";
+
+	chosen {
+		bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:4M(bootstrap/uboot/kernel)ro,60M(rootfs),-(data) root=/dev/mtdblock1 rw rootfstype=jffs2";
+	};
+
+	memory@70000000 {
+		reg = <0x70000000 0x4000000>;
+	};
+
+	ahb {
+		apb {
+			dbgu: serial@ffffee00 {
+				status = "okay";
+			};
+
+			usart1: serial@fff90000 {
+				status = "okay";
+			};
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/highbank.dts linux-libre-3.2-gnu/arch/arm/boot/dts/highbank.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/highbank.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/highbank.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/dts-v1/;
+
+/* First 4KB has pen for secondary cores. */
+/memreserve/ 0x00000000 0x0001000;
+
+/ {
+	model = "Calxeda Highbank";
+	compatible = "calxeda,highbank";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@2 {
+			compatible = "arm,cortex-a9";
+			reg = <2>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@3 {
+			compatible = "arm,cortex-a9";
+			reg = <3>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		name = "memory";
+		device_type = "memory";
+		reg = <0x00000000 0xff900000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyAMA0";
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&intc>;
+		ranges;
+
+		timer@fff10600 {
+			compatible = "arm,smp-twd";
+			reg = <0xfff10600 0x20>;
+			interrupts = <1 13 0xf04>;
+		};
+
+		watchdog@fff10620 {
+			compatible = "arm,cortex-a9-wdt";
+			reg = <0xfff10620 0x20>;
+			interrupts = <1 14 0xf04>;
+		};
+
+		intc: interrupt-controller@fff11000 {
+			compatible = "arm,cortex-a9-gic";
+			#interrupt-cells = <3>;
+			#size-cells = <0>;
+			#address-cells = <1>;
+			interrupt-controller;
+			interrupt-parent;
+			reg = <0xfff11000 0x1000>,
+			      <0xfff10100 0x100>;
+		};
+
+		L2: l2-cache {
+			compatible = "arm,pl310-cache";
+			reg = <0xfff12000 0x1000>;
+			interrupts = <0 70 4>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		pmu {
+			compatible = "arm,cortex-a9-pmu";
+			interrupts = <0 76 4  0 75 4  0 74 4  0 73 4>;
+		};
+
+		sata@ffe08000 {
+			compatible = "calxeda,hb-ahci";
+			reg = <0xffe08000 0x10000>;
+			interrupts = <0 83 4>;
+		};
+
+		sdhci@ffe0e000 {
+			compatible = "calxeda,hb-sdhci";
+			reg = <0xffe0e000 0x1000>;
+			interrupts = <0 90 4>;
+		};
+
+		ipc@fff20000 {
+			compatible = "arm,pl320", "arm,primecell";
+			reg = <0xfff20000 0x1000>;
+			interrupts = <0 7 4>;
+		};
+
+		gpioe: gpio@fff30000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0xfff30000 0x1000>;
+			interrupts = <0 14 4>;
+		};
+
+		gpiof: gpio@fff31000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0xfff31000 0x1000>;
+			interrupts = <0 15 4>;
+		};
+
+		gpiog: gpio@fff32000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0xfff32000 0x1000>;
+			interrupts = <0 16 4>;
+		};
+
+		gpioh: gpio@fff33000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0xfff33000 0x1000>;
+			interrupts = <0 17 4>;
+		};
+
+		timer {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0xfff34000 0x1000>;
+			interrupts = <0 18 4>;
+		};
+
+		rtc@fff35000 {
+			compatible = "arm,pl031", "arm,primecell";
+			reg = <0xfff35000 0x1000>;
+			interrupts = <0 19 4>;
+		};
+
+		serial@fff36000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0xfff36000 0x1000>;
+			interrupts = <0 20 4>;
+		};
+
+		smic@fff3a000 {
+			compatible = "ipmi-smic";
+			device_type = "ipmi";
+			reg = <0xfff3a000 0x1000>;
+			interrupts = <0 24 4>;
+			reg-size = <4>;
+			reg-spacing = <4>;
+		};
+
+		sregs@fff3c000 {
+			compatible = "calxeda,hb-sregs";
+			reg = <0xfff3c000 0x1000>;
+		};
+
+		dma@fff3d000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0xfff3d000 0x1000>;
+			interrupts = <0 92 4>;
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/imx51-babbage.dts linux-libre-3.2-gnu/arch/arm/boot/dts/imx51-babbage.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/imx51-babbage.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/imx51-babbage.dts	2012-03-19 21:32:53.000000000 -0400
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/dts-v1/;
+/include/ "imx51.dtsi"
+
+/ {
+	model = "Freescale i.MX51 Babbage Board";
+	compatible = "fsl,imx51-babbage", "fsl,imx51";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x90000000 0x20000000>;
+	};
+
+	soc {
+		aips@70000000 { /* aips-1 */
+			spba@70000000 {
+				esdhc@70004000 { /* ESDHC1 */
+					fsl,cd-internal;
+					fsl,wp-internal;
+					status = "okay";
+				};
+
+				esdhc@70008000 { /* ESDHC2 */
+					cd-gpios = <&gpio0 6 0>; /* GPIO1_6 */
+					wp-gpios = <&gpio0 5 0>; /* GPIO1_5 */
+					status = "okay";
+				};
+
+				uart2: uart@7000c000 { /* UART3 */
+					fsl,uart-has-rtscts;
+					status = "okay";
+				};
+
+				ecspi@70010000 { /* ECSPI1 */
+					fsl,spi-num-chipselects = <2>;
+					cs-gpios = <&gpio3 24 0>, /* GPIO4_24 */
+						   <&gpio3 25 0>; /* GPIO4_25 */
+					status = "okay";
+
+					pmic: mc13892@0 {
+						#address-cells = <1>;
+						#size-cells = <0>;
+						compatible = "fsl,mc13892";
+						spi-max-frequency = <6000000>;
+						reg = <0>;
+						mc13xxx-irq-gpios = <&gpio0 8 0>; /* GPIO1_8 */
+						fsl,mc13xxx-uses-regulator;
+					};
+
+					flash: at45db321d@1 {
+						#address-cells = <1>;
+						#size-cells = <1>;
+						compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+						spi-max-frequency = <25000000>;
+						reg = <1>;
+
+						partition@0 {
+							label = "U-Boot";
+							reg = <0x0 0x40000>;
+							read-only;
+						};
+
+						partition@40000 {
+							label = "Kernel";
+							reg = <0x40000 0x3c0000>;
+						};
+					};
+				};
+			};
+
+			wdog@73f98000 { /* WDOG1 */
+				status = "okay";
+			};
+
+			iomuxc@73fa8000 {
+				compatible = "fsl,imx51-iomuxc-babbage";
+				reg = <0x73fa8000 0x4000>;
+			};
+
+			uart0: uart@73fbc000 {
+				fsl,uart-has-rtscts;
+				status = "okay";
+			};
+
+			uart1: uart@73fc0000 {
+				status = "okay";
+			};
+		};
+
+		aips@80000000 {	/* aips-2 */
+			sdma@83fb0000 {
+				fsl,sdma-ram-script-name = "/*(DEBLOBBED)*/";
+			};
+
+			i2c@83fc4000 { /* I2C2 */
+				status = "okay";
+
+				codec: sgtl5000@0a {
+					compatible = "fsl,sgtl5000";
+					reg = <0x0a>;
+				};
+			};
+
+			fec@83fec000 {
+				phy-mode = "mii";
+				status = "okay";
+			};
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power {
+			label = "Power Button";
+			gpios = <&gpio1 21 0>;
+			linux,code = <116>; /* KEY_POWER */
+			gpio-key,wakeup;
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/imx51.dtsi linux-libre-3.2-gnu/arch/arm/boot/dts/imx51.dtsi
--- linux-libre-3.1-gnu/arch/arm/boot/dts/imx51.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/imx51.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/ "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+	tzic: tz-interrupt-controller@e0000000 {
+		compatible = "fsl,imx51-tzic", "fsl,tzic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0xe0000000 0x4000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ckil {
+			compatible = "fsl,imx-ckil", "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		ckih1 {
+			compatible = "fsl,imx-ckih1", "fixed-clock";
+			clock-frequency = <22579200>;
+		};
+
+		ckih2 {
+			compatible = "fsl,imx-ckih2", "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		osc {
+			compatible = "fsl,imx-osc", "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&tzic>;
+		ranges;
+
+		aips@70000000 { /* AIPS1 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x70000000 0x10000000>;
+			ranges;
+
+			spba@70000000 {
+				compatible = "fsl,spba-bus", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x70000000 0x40000>;
+				ranges;
+
+				esdhc@70004000 { /* ESDHC1 */
+					compatible = "fsl,imx51-esdhc";
+					reg = <0x70004000 0x4000>;
+					interrupts = <1>;
+					status = "disabled";
+				};
+
+				esdhc@70008000 { /* ESDHC2 */
+					compatible = "fsl,imx51-esdhc";
+					reg = <0x70008000 0x4000>;
+					interrupts = <2>;
+					status = "disabled";
+				};
+
+				uart2: uart@7000c000 { /* UART3 */
+					compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+					reg = <0x7000c000 0x4000>;
+					interrupts = <33>;
+					status = "disabled";
+				};
+
+				ecspi@70010000 { /* ECSPI1 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx51-ecspi";
+					reg = <0x70010000 0x4000>;
+					interrupts = <36>;
+					status = "disabled";
+				};
+
+				esdhc@70020000 { /* ESDHC3 */
+					compatible = "fsl,imx51-esdhc";
+					reg = <0x70020000 0x4000>;
+					interrupts = <3>;
+					status = "disabled";
+				};
+
+				esdhc@70024000 { /* ESDHC4 */
+					compatible = "fsl,imx51-esdhc";
+					reg = <0x70024000 0x4000>;
+					interrupts = <4>;
+					status = "disabled";
+				};
+			};
+
+			gpio0: gpio@73f84000 { /* GPIO1 */
+				compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+				reg = <0x73f84000 0x4000>;
+				interrupts = <50 51>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio1: gpio@73f88000 { /* GPIO2 */
+				compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+				reg = <0x73f88000 0x4000>;
+				interrupts = <52 53>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio2: gpio@73f8c000 { /* GPIO3 */
+				compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+				reg = <0x73f8c000 0x4000>;
+				interrupts = <54 55>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio3: gpio@73f90000 { /* GPIO4 */
+				compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+				reg = <0x73f90000 0x4000>;
+				interrupts = <56 57>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			wdog@73f98000 { /* WDOG1 */
+				compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
+				reg = <0x73f98000 0x4000>;
+				interrupts = <58>;
+				status = "disabled";
+			};
+
+			wdog@73f9c000 { /* WDOG2 */
+				compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
+				reg = <0x73f9c000 0x4000>;
+				interrupts = <59>;
+				status = "disabled";
+			};
+
+			uart0: uart@73fbc000 {
+				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+				reg = <0x73fbc000 0x4000>;
+				interrupts = <31>;
+				status = "disabled";
+			};
+
+			uart1: uart@73fc0000 {
+				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+				reg = <0x73fc0000 0x4000>;
+				interrupts = <32>;
+				status = "disabled";
+			};
+		};
+
+		aips@80000000 {	/* AIPS2 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x80000000 0x10000000>;
+			ranges;
+
+			ecspi@83fac000 { /* ECSPI2 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx51-ecspi";
+				reg = <0x83fac000 0x4000>;
+				interrupts = <37>;
+				status = "disabled";
+			};
+
+			sdma@83fb0000 {
+				compatible = "fsl,imx51-sdma", "fsl,imx35-sdma";
+				reg = <0x83fb0000 0x4000>;
+				interrupts = <6>;
+			};
+
+			cspi@83fc0000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx51-cspi", "fsl,imx35-cspi";
+				reg = <0x83fc0000 0x4000>;
+				interrupts = <38>;
+				status = "disabled";
+			};
+
+			i2c@83fc4000 { /* I2C2 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+				reg = <0x83fc4000 0x4000>;
+				interrupts = <63>;
+				status = "disabled";
+			};
+
+			i2c@83fc8000 { /* I2C1 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+				reg = <0x83fc8000 0x4000>;
+				interrupts = <62>;
+				status = "disabled";
+			};
+
+			fec@83fec000 {
+				compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+				reg = <0x83fec000 0x4000>;
+				interrupts = <87>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/imx53-ard.dts linux-libre-3.2-gnu/arch/arm/boot/dts/imx53-ard.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/imx53-ard.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/imx53-ard.dts	2012-03-19 21:32:59.000000000 -0400
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+	model = "Freescale i.MX53 Automotive Reference Design Board";
+	compatible = "fsl,imx53-ard", "fsl,imx53";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x70000000 0x40000000>;
+	};
+
+	soc {
+		aips@50000000 { /* AIPS1 */
+			spba@50000000 {
+				esdhc@50004000 { /* ESDHC1 */
+					cd-gpios = <&gpio0 1 0>; /* GPIO1_1 */
+					wp-gpios = <&gpio0 9 0>; /* GPIO1_9 */
+					status = "okay";
+				};
+			};
+
+			wdog@53f98000 { /* WDOG1 */
+				status = "okay";
+			};
+
+			iomuxc@53fa8000 {
+				compatible = "fsl,imx53-iomuxc-ard";
+				reg = <0x53fa8000 0x4000>;
+			};
+
+			uart0: uart@53fbc000 { /* UART1 */
+				status = "okay";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			sdma@63fb0000 {
+				fsl,sdma-ram-script-name = "/*(DEBLOBBED)*/";
+			};
+		};
+	};
+
+	eim-cs1@f4000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,eim-bus", "simple-bus";
+		reg = <0xf4000000 0x3ff0000>;
+		ranges;
+
+		lan9220@f4000000 {
+			compatible = "smsc,lan9220", "smsc,lan9115";
+			reg = <0xf4000000 0x2000000>;
+			phy-mode = "mii";
+			interrupt-parent = <&gpio1>;
+			interrupts = <31>;
+			reg-io-width = <4>;
+			smsc,irq-push-pull;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		home {
+			label = "Home";
+			gpios = <&gpio4 10 0>; /* GPIO5_10 */
+			linux,code = <102>; /* KEY_HOME */
+			gpio-key,wakeup;
+		};
+
+		back {
+			label = "Back";
+			gpios = <&gpio4 11 0>; /* GPIO5_11 */
+			linux,code = <158>; /* KEY_BACK */
+			gpio-key,wakeup;
+		};
+
+		program {
+			label = "Program";
+			gpios = <&gpio4 12 0>; /* GPIO5_12 */
+			linux,code = <362>; /* KEY_PROGRAM */
+			gpio-key,wakeup;
+		};
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio4 13 0>; /* GPIO5_13 */
+			linux,code = <115>; /* KEY_VOLUMEUP */
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio3 0 0>; /* GPIO4_0 */
+			linux,code = <114>; /* KEY_VOLUMEDOWN */
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/imx53.dtsi linux-libre-3.2-gnu/arch/arm/boot/dts/imx53.dtsi
--- linux-libre-3.1-gnu/arch/arm/boot/dts/imx53.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/imx53.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/ "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+	};
+
+	tzic: tz-interrupt-controller@0fffc000 {
+		compatible = "fsl,imx53-tzic", "fsl,tzic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0x0fffc000 0x4000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ckil {
+			compatible = "fsl,imx-ckil", "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		ckih1 {
+			compatible = "fsl,imx-ckih1", "fixed-clock";
+			clock-frequency = <22579200>;
+		};
+
+		ckih2 {
+			compatible = "fsl,imx-ckih2", "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		osc {
+			compatible = "fsl,imx-osc", "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&tzic>;
+		ranges;
+
+		aips@50000000 { /* AIPS1 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x50000000 0x10000000>;
+			ranges;
+
+			spba@50000000 {
+				compatible = "fsl,spba-bus", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x50000000 0x40000>;
+				ranges;
+
+				esdhc@50004000 { /* ESDHC1 */
+					compatible = "fsl,imx53-esdhc";
+					reg = <0x50004000 0x4000>;
+					interrupts = <1>;
+					status = "disabled";
+				};
+
+				esdhc@50008000 { /* ESDHC2 */
+					compatible = "fsl,imx53-esdhc";
+					reg = <0x50008000 0x4000>;
+					interrupts = <2>;
+					status = "disabled";
+				};
+
+				uart2: uart@5000c000 { /* UART3 */
+					compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+					reg = <0x5000c000 0x4000>;
+					interrupts = <33>;
+					status = "disabled";
+				};
+
+				ecspi@50010000 { /* ECSPI1 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
+					reg = <0x50010000 0x4000>;
+					interrupts = <36>;
+					status = "disabled";
+				};
+
+				esdhc@50020000 { /* ESDHC3 */
+					compatible = "fsl,imx53-esdhc";
+					reg = <0x50020000 0x4000>;
+					interrupts = <3>;
+					status = "disabled";
+				};
+
+				esdhc@50024000 { /* ESDHC4 */
+					compatible = "fsl,imx53-esdhc";
+					reg = <0x50024000 0x4000>;
+					interrupts = <4>;
+					status = "disabled";
+				};
+			};
+
+			gpio0: gpio@53f84000 { /* GPIO1 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53f84000 0x4000>;
+				interrupts = <50 51>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio1: gpio@53f88000 { /* GPIO2 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53f88000 0x4000>;
+				interrupts = <52 53>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio2: gpio@53f8c000 { /* GPIO3 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53f8c000 0x4000>;
+				interrupts = <54 55>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio3: gpio@53f90000 { /* GPIO4 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53f90000 0x4000>;
+				interrupts = <56 57>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			wdog@53f98000 { /* WDOG1 */
+				compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
+				reg = <0x53f98000 0x4000>;
+				interrupts = <58>;
+				status = "disabled";
+			};
+
+			wdog@53f9c000 { /* WDOG2 */
+				compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
+				reg = <0x53f9c000 0x4000>;
+				interrupts = <59>;
+				status = "disabled";
+			};
+
+			uart0: uart@53fbc000 { /* UART1 */
+				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+				reg = <0x53fbc000 0x4000>;
+				interrupts = <31>;
+				status = "disabled";
+			};
+
+			uart1: uart@53fc0000 { /* UART2 */
+				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+				reg = <0x53fc0000 0x4000>;
+				interrupts = <32>;
+				status = "disabled";
+			};
+
+			gpio4: gpio@53fdc000 { /* GPIO5 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53fdc000 0x4000>;
+				interrupts = <103 104>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio5: gpio@53fe0000 { /* GPIO6 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53fe0000 0x4000>;
+				interrupts = <105 106>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio6: gpio@53fe4000 { /* GPIO7 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53fe4000 0x4000>;
+				interrupts = <107 108>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			i2c@53fec000 { /* I2C3 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+				reg = <0x53fec000 0x4000>;
+				interrupts = <64>;
+				status = "disabled";
+			};
+
+			uart3: uart@53ff0000 { /* UART4 */
+				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+				reg = <0x53ff0000 0x4000>;
+				interrupts = <13>;
+				status = "disabled";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x60000000 0x10000000>;
+			ranges;
+
+			uart4: uart@63f90000 { /* UART5 */
+				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+				reg = <0x63f90000 0x4000>;
+				interrupts = <86>;
+				status = "disabled";
+			};
+
+			ecspi@63fac000 { /* ECSPI2 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
+				reg = <0x63fac000 0x4000>;
+				interrupts = <37>;
+				status = "disabled";
+			};
+
+			sdma@63fb0000 {
+				compatible = "fsl,imx53-sdma", "fsl,imx35-sdma";
+				reg = <0x63fb0000 0x4000>;
+				interrupts = <6>;
+			};
+
+			cspi@63fc0000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-cspi", "fsl,imx35-cspi";
+				reg = <0x63fc0000 0x4000>;
+				interrupts = <38>;
+				status = "disabled";
+			};
+
+			i2c@63fc4000 { /* I2C2 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+				reg = <0x63fc4000 0x4000>;
+				interrupts = <63>;
+				status = "disabled";
+			};
+
+			i2c@63fc8000 { /* I2C1 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+				reg = <0x63fc8000 0x4000>;
+				interrupts = <62>;
+				status = "disabled";
+			};
+
+			fec@63fec000 {
+				compatible = "fsl,imx53-fec", "fsl,imx25-fec";
+				reg = <0x63fec000 0x4000>;
+				interrupts = <87>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/imx53-evk.dts linux-libre-3.2-gnu/arch/arm/boot/dts/imx53-evk.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/imx53-evk.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/imx53-evk.dts	2012-03-19 21:33:06.000000000 -0400
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+	model = "Freescale i.MX53 Evaluation Kit";
+	compatible = "fsl,imx53-evk", "fsl,imx53";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x70000000 0x80000000>;
+	};
+
+	soc {
+		aips@50000000 { /* AIPS1 */
+			spba@50000000 {
+				esdhc@50004000 { /* ESDHC1 */
+					cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */
+					wp-gpios = <&gpio2 14 0>; /* GPIO3_14 */
+					status = "okay";
+				};
+
+				ecspi@50010000 { /* ECSPI1 */
+					fsl,spi-num-chipselects = <2>;
+					cs-gpios = <&gpio1 30 0>, /* GPIO2_30 */
+						   <&gpio2 19 0>; /* GPIO3_19 */
+					status = "okay";
+
+					flash: at45db321d@1 {
+						#address-cells = <1>;
+						#size-cells = <1>;
+						compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+						spi-max-frequency = <25000000>;
+						reg = <1>;
+
+						partition@0 {
+							label = "U-Boot";
+							reg = <0x0 0x40000>;
+							read-only;
+						};
+
+						partition@40000 {
+							label = "Kernel";
+							reg = <0x40000 0x3c0000>;
+						};
+					};
+				};
+
+				esdhc@50020000 { /* ESDHC3 */
+					cd-gpios = <&gpio2 11 0>; /* GPIO3_11 */
+					wp-gpios = <&gpio2 12 0>; /* GPIO3_12 */
+					status = "okay";
+				};
+			};
+
+			wdog@53f98000 { /* WDOG1 */
+				status = "okay";
+			};
+
+			iomuxc@53fa8000 {
+				compatible = "fsl,imx53-iomuxc-evk";
+				reg = <0x53fa8000 0x4000>;
+			};
+
+			uart0: uart@53fbc000 { /* UART1 */
+				status = "okay";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			sdma@63fb0000 {
+				fsl,sdma-ram-script-name = "/*(DEBLOBBED)*/";
+			};
+
+			i2c@63fc4000 { /* I2C2 */
+				status = "okay";
+
+				pmic: mc13892@08 {
+					compatible = "fsl,mc13892", "fsl,mc13xxx";
+					reg = <0x08>;
+				};
+
+				codec: sgtl5000@0a {
+					compatible = "fsl,sgtl5000";
+					reg = <0x0a>;
+				};
+			};
+
+			fec@63fec000 {
+				phy-mode = "rmii";
+				phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */
+				status = "okay";
+			};
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		green {
+			label = "Heartbeat";
+			gpios = <&gpio6 7 0>; /* GPIO7_7 */
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/imx53-qsb.dts linux-libre-3.2-gnu/arch/arm/boot/dts/imx53-qsb.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/imx53-qsb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/imx53-qsb.dts	2012-03-19 21:33:15.000000000 -0400
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+	model = "Freescale i.MX53 Quick Start Board";
+	compatible = "fsl,imx53-qsb", "fsl,imx53";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x70000000 0x40000000>;
+	};
+
+	soc {
+		aips@50000000 { /* AIPS1 */
+			spba@50000000 {
+				esdhc@50004000 { /* ESDHC1 */
+					cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */
+					status = "okay";
+				};
+
+				esdhc@50020000 { /* ESDHC3 */
+					cd-gpios = <&gpio2 11 0>; /* GPIO3_11 */
+					wp-gpios = <&gpio2 12 0>; /* GPIO3_12 */
+					status = "okay";
+				};
+			};
+
+			wdog@53f98000 { /* WDOG1 */
+				status = "okay";
+			};
+
+			iomuxc@53fa8000 {
+				compatible = "fsl,imx53-iomuxc-qsb";
+				reg = <0x53fa8000 0x4000>;
+			};
+
+			uart0: uart@53fbc000 { /* UART1 */
+				status = "okay";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			sdma@63fb0000 {
+				fsl,sdma-ram-script-name = "/*(DEBLOBBED)*/";
+			};
+
+			i2c@63fc4000 { /* I2C2 */
+				status = "okay";
+
+				codec: sgtl5000@0a {
+					compatible = "fsl,sgtl5000";
+					reg = <0x0a>;
+				};
+			};
+
+			i2c@63fc8000 { /* I2C1 */
+				status = "okay";
+
+				accelerometer: mma8450@1c {
+					compatible = "fsl,mma8450";
+					reg = <0x1c>;
+				};
+
+				pmic: dialog@48 {
+					compatible = "dialog,da9053", "dialog,da9052";
+					reg = <0x48>;
+				};
+			};
+
+			fec@63fec000 {
+				phy-mode = "rmii";
+				phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */
+				status = "okay";
+			};
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power {
+			label = "Power Button";
+			gpios = <&gpio0 8 0>; /* GPIO1_8 */
+			linux,code = <116>; /* KEY_POWER */
+			gpio-key,wakeup;
+		};
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio1 14 0>; /* GPIO2_14 */
+			linux,code = <115>; /* KEY_VOLUMEUP */
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio1 15 0>; /* GPIO2_15 */
+			linux,code = <114>; /* KEY_VOLUMEDOWN */
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		user {
+			label = "Heartbeat";
+			gpios = <&gpio6 7 0>; /* GPIO7_7 */
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/imx53-smd.dts linux-libre-3.2-gnu/arch/arm/boot/dts/imx53-smd.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/imx53-smd.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/imx53-smd.dts	2012-03-19 21:33:22.000000000 -0400
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+	model = "Freescale i.MX53 Smart Mobile Reference Design Board";
+	compatible = "fsl,imx53-smd", "fsl,imx53";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x70000000 0x40000000>;
+	};
+
+	soc {
+		aips@50000000 { /* AIPS1 */
+			spba@50000000 {
+				esdhc@50004000 { /* ESDHC1 */
+					cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */
+					wp-gpios = <&gpio3 11 0>; /* GPIO4_11 */
+					status = "okay";
+				};
+
+				esdhc@50008000 { /* ESDHC2 */
+					fsl,card-wired;
+					status = "okay";
+				};
+
+				uart2: uart@5000c000 { /* UART3 */
+					fsl,uart-has-rtscts;
+					status = "okay";
+				};
+
+				ecspi@50010000 { /* ECSPI1 */
+					fsl,spi-num-chipselects = <2>;
+					cs-gpios = <&gpio1 30 0>, /* GPIO2_30 */
+						   <&gpio2 19 0>; /* GPIO3_19 */
+					status = "okay";
+
+					zigbee: mc1323@0 {
+						compatible = "fsl,mc1323";
+						spi-max-frequency = <8000000>;
+						reg = <0>;
+					};
+
+					flash: m25p32@1 {
+						#address-cells = <1>;
+						#size-cells = <1>;
+						compatible = "st,m25p32", "st,m25p";
+						spi-max-frequency = <20000000>;
+						reg = <1>;
+
+						partition@0 {
+							label = "U-Boot";
+							reg = <0x0 0x40000>;
+							read-only;
+						};
+
+						partition@40000 {
+							label = "Kernel";
+							reg = <0x40000 0x3c0000>;
+						};
+					};
+				};
+
+				esdhc@50020000 { /* ESDHC3 */
+					fsl,card-wired;
+					status = "okay";
+				};
+			};
+
+			wdog@53f98000 { /* WDOG1 */
+				status = "okay";
+			};
+
+			iomuxc@53fa8000 {
+				compatible = "fsl,imx53-iomuxc-smd";
+				reg = <0x53fa8000 0x4000>;
+			};
+
+			uart0: uart@53fbc000 { /* UART1 */
+				status = "okay";
+			};
+
+			uart1: uart@53fc0000 { /* UART2 */
+				status = "okay";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			sdma@63fb0000 {
+				fsl,sdma-ram-script-name = "/*(DEBLOBBED)*/";
+			};
+
+			i2c@63fc4000 { /* I2C2 */
+				status = "okay";
+
+				codec: sgtl5000@0a {
+					compatible = "fsl,sgtl5000";
+					reg = <0x0a>;
+				};
+
+				magnetometer: mag3110@0e {
+					compatible = "fsl,mag3110";
+					reg = <0x0e>;
+				};
+
+				touchkey: mpr121@5a {
+					compatible = "fsl,mpr121";
+					reg = <0x5a>;
+				};
+			};
+
+			i2c@63fc8000 { /* I2C1 */
+				status = "okay";
+
+				accelerometer: mma8450@1c {
+					compatible = "fsl,mma8450";
+					reg = <0x1c>;
+				};
+
+				camera: ov5642@3c {
+					compatible = "ovti,ov5642";
+					reg = <0x3c>;
+				};
+
+				pmic: dialog@48 {
+					compatible = "dialog,da9053", "dialog,da9052";
+					reg = <0x48>;
+				};
+			};
+
+			fec@63fec000 {
+				phy-mode = "rmii";
+				phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */
+				status = "okay";
+			};
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio1 14 0>; /* GPIO2_14 */
+			linux,code = <115>; /* KEY_VOLUMEUP */
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio1 15 0>; /* GPIO2_15 */
+			linux,code = <114>; /* KEY_VOLUMEDOWN */
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/imx6q.dtsi linux-libre-3.2-gnu/arch/arm/boot/dts/imx6q.dtsi
--- linux-libre-3.1-gnu/arch/arm/boot/dts/imx6q.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/imx6q.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,575 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/ "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@2 {
+			compatible = "arm,cortex-a9";
+			reg = <2>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@3 {
+			compatible = "arm,cortex-a9";
+			reg = <3>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	intc: interrupt-controller@00a01000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		interrupt-controller;
+		reg = <0x00a01000 0x1000>,
+		      <0x00a00100 0x100>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ckil {
+			compatible = "fsl,imx-ckil", "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		ckih1 {
+			compatible = "fsl,imx-ckih1", "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		osc {
+			compatible = "fsl,imx-osc", "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&intc>;
+		ranges;
+
+		timer@00a00600 {
+			compatible = "arm,smp-twd";
+			reg = <0x00a00600 0x100>;
+			interrupts = <1 13 0xf4>;
+		};
+
+		L2: l2-cache@00a02000 {
+			compatible = "arm,pl310-cache";
+			reg = <0x00a02000 0x1000>;
+			interrupts = <0 92 0x04>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		aips-bus@02000000 { /* AIPS1 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x02000000 0x100000>;
+			ranges;
+
+			spba-bus@02000000 {
+				compatible = "fsl,spba-bus", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x02000000 0x40000>;
+				ranges;
+
+				spdif@02004000 {
+					reg = <0x02004000 0x4000>;
+					interrupts = <0 52 0x04>;
+				};
+
+				ecspi@02008000 { /* eCSPI1 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02008000 0x4000>;
+					interrupts = <0 31 0x04>;
+					status = "disabled";
+				};
+
+				ecspi@0200c000 { /* eCSPI2 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x0200c000 0x4000>;
+					interrupts = <0 32 0x04>;
+					status = "disabled";
+				};
+
+				ecspi@02010000 { /* eCSPI3 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02010000 0x4000>;
+					interrupts = <0 33 0x04>;
+					status = "disabled";
+				};
+
+				ecspi@02014000 { /* eCSPI4 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02014000 0x4000>;
+					interrupts = <0 34 0x04>;
+					status = "disabled";
+				};
+
+				ecspi@02018000 { /* eCSPI5 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02018000 0x4000>;
+					interrupts = <0 35 0x04>;
+					status = "disabled";
+				};
+
+				uart0: uart@02020000 { /* UART1 */
+					compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+					reg = <0x02020000 0x4000>;
+					interrupts = <0 26 0x04>;
+					status = "disabled";
+				};
+
+				esai@02024000 {
+					reg = <0x02024000 0x4000>;
+					interrupts = <0 51 0x04>;
+				};
+
+				ssi@02028000 { /* SSI1 */
+					reg = <0x02028000 0x4000>;
+					interrupts = <0 46 0x04>;
+				};
+
+				ssi@0202c000 { /* SSI2 */
+					reg = <0x0202c000 0x4000>;
+					interrupts = <0 47 0x04>;
+				};
+
+				ssi@02030000 { /* SSI3 */
+					reg = <0x02030000 0x4000>;
+					interrupts = <0 48 0x04>;
+				};
+
+				asrc@02034000 {
+					reg = <0x02034000 0x4000>;
+					interrupts = <0 50 0x04>;
+				};
+
+				spba@0203c000 {
+					reg = <0x0203c000 0x4000>;
+				};
+			};
+
+			vpu@02040000 {
+				reg = <0x02040000 0x3c000>;
+				interrupts = <0 3 0x04 0 12 0x04>;
+			};
+
+			aipstz@0207c000 { /* AIPSTZ1 */
+				reg = <0x0207c000 0x4000>;
+			};
+
+			pwm@02080000 { /* PWM1 */
+				reg = <0x02080000 0x4000>;
+				interrupts = <0 83 0x04>;
+			};
+
+			pwm@02084000 { /* PWM2 */
+				reg = <0x02084000 0x4000>;
+				interrupts = <0 84 0x04>;
+			};
+
+			pwm@02088000 { /* PWM3 */
+				reg = <0x02088000 0x4000>;
+				interrupts = <0 85 0x04>;
+			};
+
+			pwm@0208c000 { /* PWM4 */
+				reg = <0x0208c000 0x4000>;
+				interrupts = <0 86 0x04>;
+			};
+
+			flexcan@02090000 { /* CAN1 */
+				reg = <0x02090000 0x4000>;
+				interrupts = <0 110 0x04>;
+			};
+
+			flexcan@02094000 { /* CAN2 */
+				reg = <0x02094000 0x4000>;
+				interrupts = <0 111 0x04>;
+			};
+
+			gpt@02098000 {
+				compatible = "fsl,imx6q-gpt";
+				reg = <0x02098000 0x4000>;
+				interrupts = <0 55 0x04>;
+			};
+
+			gpio0: gpio@0209c000 { /* GPIO1 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x0209c000 0x4000>;
+				interrupts = <0 66 0x04 0 67 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio1: gpio@020a0000 { /* GPIO2 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020a0000 0x4000>;
+				interrupts = <0 68 0x04 0 69 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio2: gpio@020a4000 { /* GPIO3 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020a4000 0x4000>;
+				interrupts = <0 70 0x04 0 71 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio3: gpio@020a8000 { /* GPIO4 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020a8000 0x4000>;
+				interrupts = <0 72 0x04 0 73 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio4: gpio@020ac000 { /* GPIO5 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020ac000 0x4000>;
+				interrupts = <0 74 0x04 0 75 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio5: gpio@020b0000 { /* GPIO6 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020b0000 0x4000>;
+				interrupts = <0 76 0x04 0 77 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio6: gpio@020b4000 { /* GPIO7 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020b4000 0x4000>;
+				interrupts = <0 78 0x04 0 79 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			kpp@020b8000 {
+				reg = <0x020b8000 0x4000>;
+				interrupts = <0 82 0x04>;
+			};
+
+			wdog@020bc000 { /* WDOG1 */
+				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
+				reg = <0x020bc000 0x4000>;
+				interrupts = <0 80 0x04>;
+				status = "disabled";
+			};
+
+			wdog@020c0000 { /* WDOG2 */
+				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
+				reg = <0x020c0000 0x4000>;
+				interrupts = <0 81 0x04>;
+				status = "disabled";
+			};
+
+			ccm@020c4000 {
+				compatible = "fsl,imx6q-ccm";
+				reg = <0x020c4000 0x4000>;
+				interrupts = <0 87 0x04 0 88 0x04>;
+			};
+
+			anatop@020c8000 {
+				compatible = "fsl,imx6q-anatop";
+				reg = <0x020c8000 0x1000>;
+				interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
+			};
+
+			usbphy@020c9000 { /* USBPHY1 */
+				reg = <0x020c9000 0x1000>;
+				interrupts = <0 44 0x04>;
+			};
+
+			usbphy@020ca000 { /* USBPHY2 */
+				reg = <0x020ca000 0x1000>;
+				interrupts = <0 45 0x04>;
+			};
+
+			snvs@020cc000 {
+				reg = <0x020cc000 0x4000>;
+				interrupts = <0 19 0x04 0 20 0x04>;
+			};
+
+			epit@020d0000 { /* EPIT1 */
+				reg = <0x020d0000 0x4000>;
+				interrupts = <0 56 0x04>;
+			};
+
+			epit@020d4000 { /* EPIT2 */
+				reg = <0x020d4000 0x4000>;
+				interrupts = <0 57 0x04>;
+			};
+
+			src@020d8000 {
+				compatible = "fsl,imx6q-src";
+				reg = <0x020d8000 0x4000>;
+				interrupts = <0 91 0x04 0 96 0x04>;
+			};
+
+			gpc@020dc000 {
+				compatible = "fsl,imx6q-gpc";
+				reg = <0x020dc000 0x4000>;
+				interrupts = <0 89 0x04 0 90 0x04>;
+			};
+
+			iomuxc@020e0000 {
+				reg = <0x020e0000 0x4000>;
+			};
+
+			dcic@020e4000 { /* DCIC1 */
+				reg = <0x020e4000 0x4000>;
+				interrupts = <0 124 0x04>;
+			};
+
+			dcic@020e8000 { /* DCIC2 */
+				reg = <0x020e8000 0x4000>;
+				interrupts = <0 125 0x04>;
+			};
+
+			sdma@020ec000 {
+				compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
+				reg = <0x020ec000 0x4000>;
+				interrupts = <0 2 0x04>;
+			};
+		};
+
+		aips-bus@02100000 { /* AIPS2 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x02100000 0x100000>;
+			ranges;
+
+			caam@02100000 {
+				reg = <0x02100000 0x40000>;
+				interrupts = <0 105 0x04 0 106 0x04>;
+			};
+
+			aipstz@0217c000 { /* AIPSTZ2 */
+				reg = <0x0217c000 0x4000>;
+			};
+
+			enet@02188000 {
+				compatible = "fsl,imx6q-fec";
+				reg = <0x02188000 0x4000>;
+				interrupts = <0 118 0x04 0 119 0x04>;
+				status = "disabled";
+			};
+
+			mlb@0218c000 {
+				reg = <0x0218c000 0x4000>;
+				interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>;
+			};
+
+			usdhc@02190000 { /* uSDHC1 */
+				compatible = "fsl,imx6q-usdhc";
+				reg = <0x02190000 0x4000>;
+				interrupts = <0 22 0x04>;
+				status = "disabled";
+			};
+
+			usdhc@02194000 { /* uSDHC2 */
+				compatible = "fsl,imx6q-usdhc";
+				reg = <0x02194000 0x4000>;
+				interrupts = <0 23 0x04>;
+				status = "disabled";
+			};
+
+			usdhc@02198000 { /* uSDHC3 */
+				compatible = "fsl,imx6q-usdhc";
+				reg = <0x02198000 0x4000>;
+				interrupts = <0 24 0x04>;
+				status = "disabled";
+			};
+
+			usdhc@0219c000 { /* uSDHC4 */
+				compatible = "fsl,imx6q-usdhc";
+				reg = <0x0219c000 0x4000>;
+				interrupts = <0 25 0x04>;
+				status = "disabled";
+			};
+
+			i2c@021a0000 { /* I2C1 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+				reg = <0x021a0000 0x4000>;
+				interrupts = <0 36 0x04>;
+				status = "disabled";
+			};
+
+			i2c@021a4000 { /* I2C2 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+				reg = <0x021a4000 0x4000>;
+				interrupts = <0 37 0x04>;
+				status = "disabled";
+			};
+
+			i2c@021a8000 { /* I2C3 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+				reg = <0x021a8000 0x4000>;
+				interrupts = <0 38 0x04>;
+				status = "disabled";
+			};
+
+			romcp@021ac000 {
+				reg = <0x021ac000 0x4000>;
+			};
+
+			mmdc@021b0000 { /* MMDC0 */
+				compatible = "fsl,imx6q-mmdc";
+				reg = <0x021b0000 0x4000>;
+			};
+
+			mmdc@021b4000 { /* MMDC1 */
+				reg = <0x021b4000 0x4000>;
+			};
+
+			weim@021b8000 {
+				reg = <0x021b8000 0x4000>;
+				interrupts = <0 14 0x04>;
+			};
+
+			ocotp@021bc000 {
+				reg = <0x021bc000 0x4000>;
+			};
+
+			ocotp@021c0000 {
+				reg = <0x021c0000 0x4000>;
+				interrupts = <0 21 0x04>;
+			};
+
+			tzasc@021d0000 { /* TZASC1 */
+				reg = <0x021d0000 0x4000>;
+				interrupts = <0 108 0x04>;
+			};
+
+			tzasc@021d4000 { /* TZASC2 */
+				reg = <0x021d4000 0x4000>;
+				interrupts = <0 109 0x04>;
+			};
+
+			audmux@021d8000 {
+				reg = <0x021d8000 0x4000>;
+			};
+
+			mipi@021dc000 { /* MIPI-CSI */
+				reg = <0x021dc000 0x4000>;
+			};
+
+			mipi@021e0000 { /* MIPI-DSI */
+				reg = <0x021e0000 0x4000>;
+			};
+
+			vdoa@021e4000 {
+				reg = <0x021e4000 0x4000>;
+				interrupts = <0 18 0x04>;
+			};
+
+			uart1: uart@021e8000 { /* UART2 */
+				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+				reg = <0x021e8000 0x4000>;
+				interrupts = <0 27 0x04>;
+				status = "disabled";
+			};
+
+			uart2: uart@021ec000 { /* UART3 */
+				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+				reg = <0x021ec000 0x4000>;
+				interrupts = <0 28 0x04>;
+				status = "disabled";
+			};
+
+			uart3: uart@021f0000 { /* UART4 */
+				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+				reg = <0x021f0000 0x4000>;
+				interrupts = <0 29 0x04>;
+				status = "disabled";
+			};
+
+			uart4: uart@021f4000 { /* UART5 */
+				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+				reg = <0x021f4000 0x4000>;
+				interrupts = <0 30 0x04>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/imx6q-sabreauto.dts linux-libre-3.2-gnu/arch/arm/boot/dts/imx6q-sabreauto.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/imx6q-sabreauto.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/imx6q-sabreauto.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+
+/dts-v1/;
+/include/ "imx6q.dtsi"
+
+/ {
+	model = "Freescale i.MX6 Quad SABRE Automotive Board";
+	compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk3p3 rootwait";
+	};
+
+	memory {
+		reg = <0x10000000 0x80000000>;
+	};
+
+	soc {
+		aips-bus@02100000 { /* AIPS2 */
+			enet@02188000 {
+				phy-mode = "rgmii";
+				local-mac-address = [00 04 9F 01 1B 61];
+				status = "okay";
+			};
+
+			usdhc@02198000 { /* uSDHC3 */
+				cd-gpios = <&gpio5 11 0>; /* GPIO6_11 */
+				wp-gpios = <&gpio5 14 0>; /* GPIO6_14 */
+				status = "okay";
+			};
+
+			usdhc@0219c000 { /* uSDHC4 */
+				fsl,card-wired;
+				status = "okay";
+			};
+
+			uart3: uart@021f0000 { /* UART4 */
+				status = "okay";
+			};
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		debug-led {
+			label = "Heartbeat";
+			gpios = <&gpio2 25 0>; /* GPIO3_25 */
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/msm8660-surf.dts linux-libre-3.2-gnu/arch/arm/boot/dts/msm8660-surf.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/msm8660-surf.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/msm8660-surf.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,24 @@
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Qualcomm MSM8660 SURF";
+	compatible = "qcom,msm8660-surf", "qcom,msm8660";
+	interrupt-parent = <&intc>;
+
+	intc: interrupt-controller@02080000 {
+		compatible = "qcom,msm-8660-qgic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = < 0x02080000 0x1000 >,
+		      < 0x02081000 0x1000 >;
+	};
+
+	serial@19c400000 {
+		compatible = "qcom,msm-hsuart", "qcom,msm-uart";
+		reg = <0x19c40000 0x1000>,
+		      <0x19c00000 0x1000>;
+		interrupts = <195>;
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/omap3-beagle.dts linux-libre-3.2-gnu/arch/arm/boot/dts/omap3-beagle.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/omap3-beagle.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/omap3-beagle.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap3.dtsi"
+
+/ {
+	model = "TI OMAP3 BeagleBoard";
+	compatible = "ti,omap3-beagle", "ti,omap3";
+
+	/*
+	 * Since the initial device tree board file does not create any
+	 * devices (MMC, network...), the only way to boot is to provide a
+	 * ramdisk.
+	 */
+	chosen {
+		bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug earlyprintk";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>; /* 512 MB */
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/omap3.dtsi linux-libre-3.2-gnu/arch/arm/boot/dts/omap3.dtsi
--- linux-libre-3.1-gnu/arch/arm/boot/dts/omap3.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/omap3.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,63 @@
+/*
+ * Device Tree Source for OMAP3 SoC
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "ti,omap3430", "ti,omap3";
+
+	cpus {
+		cpu@0 {
+			compatible = "arm,cortex-a8";
+		};
+	};
+
+	/*
+	 * The soc node represents the soc top level view. It is uses for IPs
+	 * that are not memory mapped in the MPU view or for the MPU itself.
+	 */
+	soc {
+		compatible = "ti,omap-infra";
+		mpu {
+			compatible = "ti,omap3-mpu";
+			ti,hwmods = "mpu";
+		};
+
+		iva {
+			compatible = "ti,iva2.2";
+			ti,hwmods = "iva";
+
+			dsp {
+				compatible = "ti,omap3-c64";
+			};
+		};
+	};
+
+	/*
+	 * XXX: Use a flat representation of the OMAP3 interconnect.
+	 * The real OMAP interconnect network is quite complex.
+	 * Since that will not bring real advantage to represent that in DT for
+	 * the moment, just use a fake OCP bus entry to represent the whole bus
+	 * hierarchy.
+	 */
+	ocp {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		ti,hwmods = "l3_main";
+
+		intc: interrupt-controller@1 {
+			compatible = "ti,omap3-intc";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/omap4.dtsi linux-libre-3.2-gnu/arch/arm/boot/dts/omap4.dtsi
--- linux-libre-3.1-gnu/arch/arm/boot/dts/omap4.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/omap4.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Carveout for multimedia usecases
+ * It should be the last 48MB of the first 512MB memory part
+ * In theory, it should not even exist. That zone should be reserved
+ * dynamically during the .reserve callback.
+ */
+/memreserve/ 0x9d000000 0x03000000;
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "ti,omap4430", "ti,omap4";
+	interrupt-parent = <&gic>;
+
+	aliases {
+	};
+
+	cpus {
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+		};
+		cpu@1 {
+			compatible = "arm,cortex-a9";
+		};
+	};
+
+	/*
+	 * The soc node represents the soc top level view. It is uses for IPs
+	 * that are not memory mapped in the MPU view or for the MPU itself.
+	 */
+	soc {
+		compatible = "ti,omap-infra";
+		mpu {
+			compatible = "ti,omap4-mpu";
+			ti,hwmods = "mpu";
+		};
+
+		dsp {
+			compatible = "ti,omap3-c64";
+			ti,hwmods = "dsp";
+		};
+
+		iva {
+			compatible = "ti,ivahd";
+			ti,hwmods = "iva";
+		};
+	};
+
+	/*
+	 * XXX: Use a flat representation of the OMAP4 interconnect.
+	 * The real OMAP interconnect network is quite complex.
+	 *
+	 * MPU -+-- MPU_PRIVATE - GIC, L2
+	 *      |
+	 *      +----------------+----------+
+	 *      |                |          |
+	 *      +            +- EMIF - DDR  |
+	 *      |            |              |
+	 *      |            +     +--------+
+	 *      |            |     |
+	 *      |            +- L4_ABE - AESS, MCBSP, TIMERs...
+	 *      |            |
+	 *      +- L3_MAIN --+- L4_CORE - IPs...
+	 *                   |
+	 *                   +- L4_PER - IPs...
+	 *                   |
+	 *                   +- L4_CFG -+- L4_WKUP - IPs...
+	 *                   |          |
+	 *                   |          +- IPs...
+	 *                   +- IPU ----+
+	 *                   |          |
+	 *                   +- DSP ----+
+	 *                   |          |
+	 *                   +- DSS ----+
+	 *
+	 * Since that will not bring real advantage to represent that in DT for
+	 * the moment, just use a fake OCP bus entry to represent the whole bus
+	 * hierarchy.
+	 */
+	ocp {
+		compatible = "ti,omap4-l3-noc", "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3";
+
+		gic: interrupt-controller@48241000 {
+			compatible = "arm,cortex-a9-gic";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			reg = <0x48241000 0x1000>,
+			      <0x48240100 0x0100>;
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/omap4-panda.dts linux-libre-3.2-gnu/arch/arm/boot/dts/omap4-panda.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/omap4-panda.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/omap4-panda.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap4.dtsi"
+
+/ {
+	model = "TI OMAP4 PandaBoard";
+	compatible = "ti,omap4-panda", "ti,omap4430", "ti,omap4";
+
+	/*
+	 * Since the initial device tree board file does not create any
+	 * devices (MMC, network...), the only way to boot is to provide a
+	 * ramdisk.
+	 */
+	chosen {
+		bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x40000000>; /* 1 GB */
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/omap4-sdp.dts linux-libre-3.2-gnu/arch/arm/boot/dts/omap4-sdp.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/omap4-sdp.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/omap4-sdp.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap4.dtsi"
+
+/ {
+	model = "TI OMAP4 SDP board";
+	compatible = "ti,omap4-sdp", "ti,omap4430", "ti,omap4";
+
+	/*
+	 * Since the initial device tree board file does not create any
+	 * devices (MMC, network...), the only way to boot is to provide a
+	 * ramdisk.
+	 */
+	chosen {
+		bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x40000000>; /* 1 GB */
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/picoxcell-pc3x2.dtsi linux-libre-3.2-gnu/arch/arm/boot/dts/picoxcell-pc3x2.dtsi
--- linux-libre-3.1-gnu/arch/arm/boot/dts/picoxcell-pc3x2.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/picoxcell-pc3x2.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,249 @@
+/*
+ *  Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * 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/ "skeleton.dtsi"
+/ {
+	model = "Picochip picoXcell PC3X2";
+	compatible = "picochip,pc3x2";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,1176jz-s";
+			clock-frequency = <400000000>;
+			reg = <0>;
+			d-cache-line-size = <32>;
+			d-cache-size = <32768>;
+			i-cache-line-size = <32>;
+			i-cache-size = <32768>;
+		};
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		pclk: clock@0 {
+			compatible = "fixed-clock";
+			clock-outputs = "bus", "pclk";
+			clock-frequency = <200000000>;
+			ref-clock = <&ref_clk>, "ref";
+		};
+	};
+
+	paxi {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x80000000 0x400000>;
+
+		emac: gem@30000 {
+			compatible = "cadence,gem";
+			reg = <0x30000 0x10000>;
+			interrupts = <31>;
+		};
+
+		dmac1: dmac@40000 {
+			compatible = "snps,dw-dmac";
+			reg = <0x40000 0x10000>;
+			interrupts = <25>;
+		};
+
+		dmac2: dmac@50000 {
+			compatible = "snps,dw-dmac";
+			reg = <0x50000 0x10000>;
+			interrupts = <26>;
+		};
+
+		vic0: interrupt-controller@60000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0x60000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		vic1: interrupt-controller@64000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0x64000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		fuse: picoxcell-fuse@80000 {
+			compatible = "picoxcell,fuse-pc3x2";
+			reg = <0x80000 0x10000>;
+		};
+
+		ssi: picoxcell-spi@90000 {
+			compatible = "picoxcell,spi";
+			reg = <0x90000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <10>;
+		};
+
+		ipsec: spacc@100000 {
+			compatible = "picochip,spacc-ipsec";
+			reg = <0x100000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <24>;
+			ref-clock = <&pclk>, "ref";
+		};
+
+		srtp: spacc@140000 {
+			compatible = "picochip,spacc-srtp";
+			reg = <0x140000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <23>;
+		};
+
+		l2_engine: spacc@180000 {
+			compatible = "picochip,spacc-l2";
+			reg = <0x180000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <22>;
+			ref-clock = <&pclk>, "ref";
+		};
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x200000 0x80000>;
+
+			rtc0: rtc@00000 {
+				compatible = "picochip,pc3x2-rtc";
+				clock-freq = <200000000>;
+				reg = <0x00000 0xf>;
+				interrupt-parent = <&vic1>;
+				interrupts = <8>;
+			};
+
+			timer0: timer@10000 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <4>;
+				clock-freq = <200000000>;
+				reg = <0x10000 0x14>;
+			};
+
+			timer1: timer@10014 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <5>;
+				clock-freq = <200000000>;
+				reg = <0x10014 0x14>;
+			};
+
+			timer2: timer@10028 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <6>;
+				clock-freq = <200000000>;
+				reg = <0x10028 0x14>;
+			};
+
+			timer3: timer@1003c {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <7>;
+				clock-freq = <200000000>;
+				reg = <0x1003c 0x14>;
+			};
+
+			gpio: gpio@20000 {
+				compatible = "snps,dw-apb-gpio";
+				reg = <0x20000 0x1000>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg-io-width = <4>;
+
+				banka: gpio-controller@0 {
+					compatible = "snps,dw-apb-gpio-bank";
+					gpio-controller;
+					#gpio-cells = <2>;
+					gpio-generic,nr-gpio = <8>;
+
+					regoffset-dat = <0x50>;
+					regoffset-set = <0x00>;
+					regoffset-dirout = <0x04>;
+				};
+
+				bankb: gpio-controller@1 {
+					compatible = "snps,dw-apb-gpio-bank";
+					gpio-controller;
+					#gpio-cells = <2>;
+					gpio-generic,nr-gpio = <8>;
+
+					regoffset-dat = <0x54>;
+					regoffset-set = <0x0c>;
+					regoffset-dirout = <0x10>;
+				};
+			};
+
+			uart0: uart@30000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x30000 0x1000>;
+				interrupt-parent = <&vic1>;
+				interrupts = <10>;
+				clock-frequency = <3686400>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+			};
+
+			uart1: uart@40000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x40000 0x1000>;
+				interrupt-parent = <&vic1>;
+				interrupts = <9>;
+				clock-frequency = <3686400>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+			};
+
+			wdog: watchdog@50000 {
+				compatible = "snps,dw-apb-wdg";
+				reg = <0x50000 0x10000>;
+				interrupt-parent = <&vic0>;
+				interrupts = <11>;
+				bus-clock = <&pclk>, "bus";
+			};
+		};
+	};
+
+	rwid-axi {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+
+		ebi@50000000 {
+			compatible = "simple-bus";
+			#address-cells = <2>;
+			#size-cells = <1>;
+			ranges = <0 0 0x40000000 0x08000000
+				  1 0 0x48000000 0x08000000
+				  2 0 0x50000000 0x08000000
+				  3 0 0x58000000 0x08000000>;
+		};
+
+		axi2pico@c0000000 {
+			compatible = "picochip,axi2pico-pc3x2";
+			reg = <0xc0000000 0x10000>;
+			interrupts = <13 14 15 16 17 18 19 20 21>;
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/picoxcell-pc3x3.dtsi linux-libre-3.2-gnu/arch/arm/boot/dts/picoxcell-pc3x3.dtsi
--- linux-libre-3.1-gnu/arch/arm/boot/dts/picoxcell-pc3x3.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/picoxcell-pc3x3.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,365 @@
+/*
+ *  Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * 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/ "skeleton.dtsi"
+/ {
+	model = "Picochip picoXcell PC3X3";
+	compatible = "picochip,pc3x3";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,1176jz-s";
+			cpu-clock = <&arm_clk>, "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;
+			d-cache-size = <32768>;
+			i-cache-line-size = <32>;
+			i-cache-size = <32768>;
+		};
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		clkgate: clkgate@800a0048 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x800a0048 4>;
+			compatible = "picochip,pc3x3-clk-gate";
+
+			tzprot_clk: clock@0 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <0>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			spi_clk: clock@1 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <1>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			dmac0_clk: clock@2 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <2>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			dmac1_clk: clock@3 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <3>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			ebi_clk: clock@4 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <4>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			ipsec_clk: clock@5 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <5>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			l2_clk: clock@6 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <6>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			trng_clk: clock@7 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <7>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			fuse_clk: clock@8 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <8>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			otp_clk: clock@9 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <9>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+		};
+
+		arm_clk: clock@11 {
+			compatible = "picochip,pc3x3-pll";
+			reg = <0x800a0050 0x8>;
+			picochip,min-freq = <140000000>;
+			picochip,max-freq = <700000000>;
+			ref-clock = <&ref_clk>, "ref";
+			clock-outputs = "cpu";
+		};
+
+		pclk: clock@12 {
+			compatible = "fixed-clock";
+			clock-outputs = "bus", "pclk";
+			clock-frequency = <200000000>;
+			ref-clock = <&ref_clk>, "ref";
+		};
+	};
+
+	paxi {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x80000000 0x400000>;
+
+		emac: gem@30000 {
+			compatible = "cadence,gem";
+			reg = <0x30000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <31>;
+		};
+
+		dmac1: dmac@40000 {
+			compatible = "snps,dw-dmac";
+			reg = <0x40000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <25>;
+		};
+
+		dmac2: dmac@50000 {
+			compatible = "snps,dw-dmac";
+			reg = <0x50000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <26>;
+		};
+
+		vic0: interrupt-controller@60000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0x60000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		vic1: interrupt-controller@64000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0x64000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		fuse: picoxcell-fuse@80000 {
+			compatible = "picoxcell,fuse-pc3x3";
+			reg = <0x80000 0x10000>;
+		};
+
+		ssi: picoxcell-spi@90000 {
+			compatible = "picoxcell,spi";
+			reg = <0x90000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <10>;
+		};
+
+		ipsec: spacc@100000 {
+			compatible = "picochip,spacc-ipsec";
+			reg = <0x100000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <24>;
+			ref-clock = <&ipsec_clk>, "ref";
+		};
+
+		srtp: spacc@140000 {
+			compatible = "picochip,spacc-srtp";
+			reg = <0x140000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <23>;
+		};
+
+		l2_engine: spacc@180000 {
+			compatible = "picochip,spacc-l2";
+			reg = <0x180000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <22>;
+			ref-clock = <&l2_clk>, "ref";
+		};
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x200000 0x80000>;
+
+			rtc0: rtc@00000 {
+				compatible = "picochip,pc3x2-rtc";
+				clock-freq = <200000000>;
+				reg = <0x00000 0xf>;
+				interrupt-parent = <&vic0>;
+				interrupts = <8>;
+			};
+
+			timer0: timer@10000 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <4>;
+				clock-freq = <200000000>;
+				reg = <0x10000 0x14>;
+			};
+
+			timer1: timer@10014 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <5>;
+				clock-freq = <200000000>;
+				reg = <0x10014 0x14>;
+			};
+
+			gpio: gpio@20000 {
+				compatible = "snps,dw-apb-gpio";
+				reg = <0x20000 0x1000>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg-io-width = <4>;
+
+				banka: gpio-controller@0 {
+					compatible = "snps,dw-apb-gpio-bank";
+					gpio-controller;
+					#gpio-cells = <2>;
+					gpio-generic,nr-gpio = <8>;
+
+					regoffset-dat = <0x50>;
+					regoffset-set = <0x00>;
+					regoffset-dirout = <0x04>;
+				};
+
+				bankb: gpio-controller@1 {
+					compatible = "snps,dw-apb-gpio-bank";
+					gpio-controller;
+					#gpio-cells = <2>;
+					gpio-generic,nr-gpio = <16>;
+
+					regoffset-dat = <0x54>;
+					regoffset-set = <0x0c>;
+					regoffset-dirout = <0x10>;
+				};
+
+				bankd: gpio-controller@2 {
+					compatible = "snps,dw-apb-gpio-bank";
+					gpio-controller;
+					#gpio-cells = <2>;
+					gpio-generic,nr-gpio = <30>;
+
+					regoffset-dat = <0x5c>;
+					regoffset-set = <0x24>;
+					regoffset-dirout = <0x28>;
+				};
+			};
+
+			uart0: uart@30000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x30000 0x1000>;
+				interrupt-parent = <&vic1>;
+				interrupts = <10>;
+				clock-frequency = <3686400>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+			};
+
+			uart1: uart@40000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x40000 0x1000>;
+				interrupt-parent = <&vic1>;
+				interrupts = <9>;
+				clock-frequency = <3686400>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+			};
+
+			wdog: watchdog@50000 {
+				compatible = "snps,dw-apb-wdg";
+				reg = <0x50000 0x10000>;
+				interrupt-parent = <&vic0>;
+				interrupts = <11>;
+				bus-clock = <&pclk>, "bus";
+			};
+
+			timer2: timer@60000 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <6>;
+				clock-freq = <200000000>;
+				reg = <0x60000 0x14>;
+			};
+
+			timer3: timer@60014 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <7>;
+				clock-freq = <200000000>;
+				reg = <0x60014 0x14>;
+			};
+		};
+	};
+
+	rwid-axi {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+
+		ebi@50000000 {
+			compatible = "simple-bus";
+			#address-cells = <2>;
+			#size-cells = <1>;
+			ranges = <0 0 0x40000000 0x08000000
+				  1 0 0x48000000 0x08000000
+				  2 0 0x50000000 0x08000000
+				  3 0 0x58000000 0x08000000>;
+		};
+
+		axi2pico@c0000000 {
+			compatible = "picochip,axi2pico-pc3x3";
+			reg = <0xc0000000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <13 14 15 16 17 18 19 20 21>;
+		};
+
+		otp@ffff8000 {
+			compatible = "picochip,otp-pc3x3";
+			reg = <0xffff8000 0x8000>;
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts linux-libre-3.2-gnu/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,86 @@
+/*
+ *  Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * 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.
+ */
+
+/dts-v1/;
+/include/ "picoxcell-pc3x2.dtsi"
+/ {
+	model = "Picochip PC7302 (PC3X2)";
+	compatible = "picochip,pc7302-pc3x2", "picochip,pc3x2";
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x08000000>;
+	};
+
+	chosen {
+		linux,stdout-path = &uart0;
+	};
+
+	clocks {
+		ref_clk: clock@1 {
+			compatible = "fixed-clock";
+			clock-outputs = "ref";
+			clock-frequency = <20000000>;
+		};
+	};
+
+	rwid-axi {
+		ebi@50000000 {
+			nand: gpio-nand@2,0 {
+				compatible = "gpio-control-nand";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <2 0x0000 0x1000>;
+				bus-clock = <&pclk>, "bus";
+				gpio-control-nand,io-sync-reg =
+					<0x00000000 0x80220000>;
+
+				gpios = <&banka 1 0	/* rdy */
+					 &banka 2 0 	/* nce */
+					 &banka 3 0 	/* ale */
+					 &banka 4 0 	/* cle */
+					 0		/* nwp */>;
+
+				boot@100000 {
+					label = "Boot";
+					reg = <0x100000 0x80000>;
+				};
+
+				redundant-boot@200000 {
+					label = "Redundant Boot";
+					reg = <0x200000 0x80000>;
+				};
+
+				boot-env@300000 {
+					label = "Boot Evironment";
+					reg = <0x300000 0x20000>;
+				};
+
+				redundant-boot-env@320000 {
+					label = "Redundant Boot Environment";
+					reg = <0x300000 0x20000>;
+				};
+
+				kernel@380000 {
+					label = "Kernel";
+					reg = <0x380000 0x800000>;
+				};
+
+				fs@b80000 {
+					label = "File System";
+					reg = <0xb80000 0xf480000>;
+				};
+			};
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts linux-libre-3.2-gnu/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,92 @@
+/*
+ *  Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * 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.
+ */
+
+/dts-v1/;
+/include/ "picoxcell-pc3x3.dtsi"
+/ {
+	model = "Picochip PC7302 (PC3X3)";
+	compatible = "picochip,pc7302-pc3x3", "picochip,pc3x3";
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x08000000>;
+	};
+
+	chosen {
+		linux,stdout-path = &uart0;
+	};
+
+	clocks {
+		ref_clk: clock@10 {
+			compatible = "fixed-clock";
+			clock-outputs = "ref";
+			clock-frequency = <20000000>;
+		};
+
+		clkgate: clkgate@800a0048 {
+			clock@4 {
+				picochip,clk-no-disable;
+			};
+		};
+	};
+
+	rwid-axi {
+		ebi@50000000 {
+			nand: gpio-nand@2,0 {
+				compatible = "gpio-control-nand";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <2 0x0000 0x1000>;
+				bus-clock = <&ebi_clk>, "bus";
+				gpio-control-nand,io-sync-reg =
+					<0x00000000 0x80220000>;
+
+				gpios = <&banka 1 0	/* rdy */
+					 &banka 2 0 	/* nce */
+					 &banka 3 0 	/* ale */
+					 &banka 4 0 	/* cle */
+					 0		/* nwp */>;
+
+				boot@100000 {
+					label = "Boot";
+					reg = <0x100000 0x80000>;
+				};
+
+				redundant-boot@200000 {
+					label = "Redundant Boot";
+					reg = <0x200000 0x80000>;
+				};
+
+				boot-env@300000 {
+					label = "Boot Evironment";
+					reg = <0x300000 0x20000>;
+				};
+
+				redundant-boot-env@320000 {
+					label = "Redundant Boot Environment";
+					reg = <0x300000 0x20000>;
+				};
+
+				kernel@380000 {
+					label = "Kernel";
+					reg = <0x380000 0x800000>;
+				};
+
+				fs@b80000 {
+					label = "File System";
+					reg = <0xb80000 0xf480000>;
+				};
+			};
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/prima2-cb.dts linux-libre-3.2-gnu/arch/arm/boot/dts/prima2-cb.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/prima2-cb.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/prima2-cb.dts	2012-01-04 18:55:44.000000000 -0500
@@ -39,9 +39,12 @@
 		ranges = <0x40000000 0x40000000 0x80000000>;
 
 		l2-cache-controller@80040000 {
-			compatible = "arm,pl310-cache";
+			compatible = "arm,pl310-cache", "sirf,prima2-pl310-cache";
 			reg = <0x80040000 0x1000>;
 			interrupts = <59>;
+			arm,tag-latency = <1 1 1>;
+			arm,data-latency = <1 1 1>;
+			arm,filter-ranges = <0 0x40000000>;
 		};
 
 		intc: interrupt-controller@80020000 {
@@ -67,6 +70,11 @@
 				compatible = "sirf,prima2-rstc";
 				reg = <0x88010000 0x1000>;
 			};
+
+			rsc-controller@88020000 {
+				compatible = "sirf,prima2-rsc";
+				reg = <0x88020000 0x1000>;
+			};
 		};
 
 		mem-iobg {
@@ -274,7 +282,7 @@
 			gpio: gpio-controller@b0120000 {
 				#gpio-cells = <2>;
 				#interrupt-cells = <2>;
-				compatible = "sirf,prima2-gpio";
+				compatible = "sirf,prima2-gpio-pinmux";
 				reg = <0xb0120000 0x10000>;
 				gpio-controller;
 				interrupt-controller;
@@ -358,7 +366,7 @@
 		};
 
 		rtc-iobg {
-			compatible = "sirf,prima2-rtciobg", "simple-bus";
+			compatible = "sirf,prima2-rtciobg", "sirf-prima2-rtciobg-bus";
 			#address-cells = <1>;
 			#size-cells = <1>;
 			reg = <0x80030000 0x10000>;
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/tegra20.dtsi linux-libre-3.2-gnu/arch/arm/boot/dts/tegra20.dtsi
--- linux-libre-3.1-gnu/arch/arm/boot/dts/tegra20.dtsi	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/tegra20.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -77,6 +77,14 @@
 		gpio-controller;
 	};
 
+	pinmux: pinmux@70000000 {
+		compatible = "nvidia,tegra20-pinmux";
+		reg = < 0x70000014 0x10    /* Tri-state registers */
+			0x70000080 0x20    /* Mux registers */
+			0x700000a0 0x14    /* Pull-up/down registers */
+			0x70000868 0xa8 >; /* Pad control registers */
+	};
+
 	serial@70006000 {
 		compatible = "nvidia,tegra20-uart";
 		reg = <0x70006000 0x40>;
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/tegra-harmony.dts linux-libre-3.2-gnu/arch/arm/boot/dts/tegra-harmony.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/tegra-harmony.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/tegra-harmony.dts	2012-01-04 18:55:44.000000000 -0500
@@ -66,5 +66,6 @@
 		cd-gpios = <&gpio 58 0>; /* gpio PH2 */
 		wp-gpios = <&gpio 59 0>; /* gpio PH3 */
 		power-gpios = <&gpio 70 0>; /* gpio PI6 */
+		support-8bit;
 	};
 };
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/tegra-seaboard.dts linux-libre-3.2-gnu/arch/arm/boot/dts/tegra-seaboard.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/tegra-seaboard.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/tegra-seaboard.dts	2012-01-04 18:55:44.000000000 -0500
@@ -25,4 +25,8 @@
 		wp-gpios = <&gpio 57 0>; /* gpio PH1 */
 		power-gpios = <&gpio 70 0>; /* gpio PI6 */
 	};
+
+	sdhci@c8000600 {
+		support-8bit;
+	};
 };
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/tegra-ventana.dts linux-libre-3.2-gnu/arch/arm/boot/dts/tegra-ventana.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/tegra-ventana.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/tegra-ventana.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,31 @@
+/dts-v1/;
+
+/memreserve/ 0x1c000000 0x04000000;
+/include/ "tegra20.dtsi"
+
+/ {
+	model = "NVIDIA Tegra2 Ventana evaluation board";
+	compatible = "nvidia,ventana", "nvidia,tegra20";
+
+	chosen {
+		bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/ram rdinit=/sbin/init";
+	};
+
+	memory {
+		reg = < 0x00000000 0x40000000 >;
+	};
+
+	serial@70006300 {
+		clock-frequency = < 216000000 >;
+	};
+
+	sdhci@c8000400 {
+		cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+		wp-gpios = <&gpio 57 0>; /* gpio PH1 */
+		power-gpios = <&gpio 70 0>; /* gpio PI6 */
+	};
+
+	sdhci@c8000600 {
+		support-8bit;
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/dts/usb_a9g20.dts linux-libre-3.2-gnu/arch/arm/boot/dts/usb_a9g20.dts
--- linux-libre-3.1-gnu/arch/arm/boot/dts/usb_a9g20.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/boot/dts/usb_a9g20.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,30 @@
+/*
+ * usb_a9g20.dts - Device Tree file for Caloa USB A9G20 board
+ *
+ *  Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9g20.dtsi"
+
+/ {
+	model = "Calao USB A9G20";
+	compatible = "calao,usb-a9g20", "atmel,at91sam9g20", "atmel,at91sam9";
+
+	chosen {
+		bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:128k(at91bootstrap),256k(barebox)ro,128k(bareboxenv),128k(bareboxenv2),4M(kernel),120M(rootfs),-(data) root=/dev/mtdblock5 rw rootfstype=ubifs";
+	};
+
+	memory@20000000 {
+		reg = <0x20000000 0x4000000>;
+	};
+
+	ahb {
+		apb {
+			dbgu: serial@fffff200 {
+				status = "okay";
+			};
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/arm/boot/Makefile linux-libre-3.2-gnu/arch/arm/boot/Makefile
--- linux-libre-3.1-gnu/arch/arm/boot/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/boot/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -65,6 +65,8 @@
 
 $(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y))
 
+clean-files := *.dtb
+
 quiet_cmd_uimage = UIMAGE  $@
       cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \
 		   -C none -a $(LOADADDR) -e $(STARTADDR) \
@@ -78,7 +80,16 @@
 
 $(obj)/uImage: STARTADDR=$(LOADADDR)
 
+check_for_multiple_loadaddr = \
+if [ $(words $(LOADADDR)) -gt 1 ]; then \
+	echo 'multiple load addresses: $(LOADADDR)'; \
+	echo 'This is incompatible with uImages'; \
+	echo 'Specify LOADADDR on the commandline to build an uImage'; \
+	false; \
+fi
+
 $(obj)/uImage:	$(obj)/zImage FORCE
+	@$(check_for_multiple_loadaddr)
 	$(call if_changed,uimage)
 	@echo '  Image $@ is ready'
 
diff -druN linux-libre-3.1-gnu/arch/arm/common/gic.c linux-libre-3.2-gnu/arch/arm/common/gic.c
--- linux-libre-3.1-gnu/arch/arm/common/gic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/common/gic.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,16 +24,26 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
 #include <linux/list.h>
 #include <linux/smp.h>
+#include <linux/cpu_pm.h>
 #include <linux/cpumask.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+#include <linux/slab.h>
 
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 #include <asm/hardware/gic.h>
 
-static DEFINE_SPINLOCK(irq_controller_lock);
+static DEFINE_RAW_SPINLOCK(irq_controller_lock);
 
 /* Address of GIC 0 CPU interface */
 void __iomem *gic_cpu_base_addr __read_mostly;
@@ -71,8 +81,7 @@
 
 static inline unsigned int gic_irq(struct irq_data *d)
 {
-	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
-	return d->irq - gic_data->irq_offset;
+	return d->hwirq;
 }
 
 /*
@@ -80,32 +89,32 @@
  */
 static void gic_mask_irq(struct irq_data *d)
 {
-	u32 mask = 1 << (d->irq % 32);
+	u32 mask = 1 << (gic_irq(d) % 32);
 
-	spin_lock(&irq_controller_lock);
+	raw_spin_lock(&irq_controller_lock);
 	writel_relaxed(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);
+	raw_spin_unlock(&irq_controller_lock);
 }
 
 static void gic_unmask_irq(struct irq_data *d)
 {
-	u32 mask = 1 << (d->irq % 32);
+	u32 mask = 1 << (gic_irq(d) % 32);
 
-	spin_lock(&irq_controller_lock);
+	raw_spin_lock(&irq_controller_lock);
 	if (gic_arch_extn.irq_unmask)
 		gic_arch_extn.irq_unmask(d);
 	writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
-	spin_unlock(&irq_controller_lock);
+	raw_spin_unlock(&irq_controller_lock);
 }
 
 static void gic_eoi_irq(struct irq_data *d)
 {
 	if (gic_arch_extn.irq_eoi) {
-		spin_lock(&irq_controller_lock);
+		raw_spin_lock(&irq_controller_lock);
 		gic_arch_extn.irq_eoi(d);
-		spin_unlock(&irq_controller_lock);
+		raw_spin_unlock(&irq_controller_lock);
 	}
 
 	writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
@@ -129,7 +138,7 @@
 	if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
 		return -EINVAL;
 
-	spin_lock(&irq_controller_lock);
+	raw_spin_lock(&irq_controller_lock);
 
 	if (gic_arch_extn.irq_set_type)
 		gic_arch_extn.irq_set_type(d, type);
@@ -154,7 +163,7 @@
 	if (enabled)
 		writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
 
-	spin_unlock(&irq_controller_lock);
+	raw_spin_unlock(&irq_controller_lock);
 
 	return 0;
 }
@@ -172,7 +181,7 @@
 			    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 shift = (gic_irq(d) % 4) * 8;
 	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
 	u32 val, mask, bit;
 
@@ -180,12 +189,12 @@
 		return -EINVAL;
 
 	mask = 0xff << shift;
-	bit = 1 << (cpu + shift);
+	bit = 1 << (cpu_logical_map(cpu) + shift);
 
-	spin_lock(&irq_controller_lock);
+	raw_spin_lock(&irq_controller_lock);
 	val = readl_relaxed(reg) & ~mask;
 	writel_relaxed(val | bit, reg);
-	spin_unlock(&irq_controller_lock);
+	raw_spin_unlock(&irq_controller_lock);
 
 	return IRQ_SET_MASK_OK;
 }
@@ -215,15 +224,15 @@
 
 	chained_irq_enter(chip, desc);
 
-	spin_lock(&irq_controller_lock);
+	raw_spin_lock(&irq_controller_lock);
 	status = readl_relaxed(chip_data->cpu_base + GIC_CPU_INTACK);
-	spin_unlock(&irq_controller_lock);
+	raw_spin_unlock(&irq_controller_lock);
 
 	gic_irq = (status & 0x3ff);
 	if (gic_irq == 1023)
 		goto out;
 
-	cascade_irq = gic_irq + chip_data->irq_offset;
+	cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq);
 	if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS))
 		do_bad_IRQ(cascade_irq, desc);
 	else
@@ -255,28 +264,26 @@
 	irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
-static void __init gic_dist_init(struct gic_chip_data *gic,
-	unsigned int irq_start)
+static void __init gic_dist_init(struct gic_chip_data *gic)
 {
-	unsigned int gic_irqs, irq_limit, i;
+	unsigned int i, irq;
+	u32 cpumask;
+	unsigned int gic_irqs = gic->gic_irqs;
+	struct irq_domain *domain = &gic->domain;
 	void __iomem *base = gic->dist_base;
-	u32 cpumask = 1 << smp_processor_id();
+	u32 cpu = 0;
+
+#ifdef CONFIG_SMP
+	cpu = cpu_logical_map(smp_processor_id());
+#endif
 
+	cpumask = 1 << cpu;
 	cpumask |= cpumask << 8;
 	cpumask |= cpumask << 16;
 
 	writel_relaxed(0, base + GIC_DIST_CTRL);
 
 	/*
-	 * Find out how many interrupts are supported.
-	 * The GIC only supports up to 1020 interrupt sources.
-	 */
-	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
-	gic_irqs = (gic_irqs + 1) * 32;
-	if (gic_irqs > 1020)
-		gic_irqs = 1020;
-
-	/*
 	 * Set all global interrupts to be level triggered, active low.
 	 */
 	for (i = 32; i < gic_irqs; i += 16)
@@ -302,19 +309,20 @@
 		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
 
 	/*
-	 * Limit number of interrupts registered to the platform maximum
-	 */
-	irq_limit = gic->irq_offset + gic_irqs;
-	if (WARN_ON(irq_limit > NR_IRQS))
-		irq_limit = NR_IRQS;
-
-	/*
 	 * Setup the Linux IRQ subsystem.
 	 */
-	for (i = irq_start; i < irq_limit; i++) {
-		irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq);
-		irq_set_chip_data(i, gic);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	irq_domain_for_each_irq(domain, i, irq) {
+		if (i < 32) {
+			irq_set_percpu_devid(irq);
+			irq_set_chip_and_handler(irq, &gic_chip,
+						 handle_percpu_devid_irq);
+			set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
+		} else {
+			irq_set_chip_and_handler(irq, &gic_chip,
+						 handle_fasteoi_irq);
+			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+		}
+		irq_set_chip_data(irq, gic);
 	}
 
 	writel_relaxed(1, base + GIC_DIST_CTRL);
@@ -343,23 +351,274 @@
 	writel_relaxed(1, base + GIC_CPU_CTRL);
 }
 
-void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
+#ifdef CONFIG_CPU_PM
+/*
+ * Saves the GIC distributor registers during suspend or idle.  Must be called
+ * with interrupts disabled but before powering down the GIC.  After calling
+ * this function, no interrupts will be delivered by the GIC, and another
+ * platform-specific wakeup source must be enabled.
+ */
+static void gic_dist_save(unsigned int gic_nr)
+{
+	unsigned int gic_irqs;
+	void __iomem *dist_base;
+	int i;
+
+	if (gic_nr >= MAX_GIC_NR)
+		BUG();
+
+	gic_irqs = gic_data[gic_nr].gic_irqs;
+	dist_base = gic_data[gic_nr].dist_base;
+
+	if (!dist_base)
+		return;
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
+		gic_data[gic_nr].saved_spi_conf[i] =
+			readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+		gic_data[gic_nr].saved_spi_target[i] =
+			readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
+		gic_data[gic_nr].saved_spi_enable[i] =
+			readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
+}
+
+/*
+ * Restores the GIC distributor registers during resume or when coming out of
+ * idle.  Must be called before enabling interrupts.  If a level interrupt
+ * that occured while the GIC was suspended is still present, it will be
+ * handled normally, but any edge interrupts that occured will not be seen by
+ * the GIC and need to be handled by the platform-specific wakeup source.
+ */
+static void gic_dist_restore(unsigned int gic_nr)
+{
+	unsigned int gic_irqs;
+	unsigned int i;
+	void __iomem *dist_base;
+
+	if (gic_nr >= MAX_GIC_NR)
+		BUG();
+
+	gic_irqs = gic_data[gic_nr].gic_irqs;
+	dist_base = gic_data[gic_nr].dist_base;
+
+	if (!dist_base)
+		return;
+
+	writel_relaxed(0, dist_base + GIC_DIST_CTRL);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
+		writel_relaxed(gic_data[gic_nr].saved_spi_conf[i],
+			dist_base + GIC_DIST_CONFIG + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+		writel_relaxed(0xa0a0a0a0,
+			dist_base + GIC_DIST_PRI + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+		writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
+			dist_base + GIC_DIST_TARGET + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
+		writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
+			dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+	writel_relaxed(1, dist_base + GIC_DIST_CTRL);
+}
+
+static void gic_cpu_save(unsigned int gic_nr)
+{
+	int i;
+	u32 *ptr;
+	void __iomem *dist_base;
+	void __iomem *cpu_base;
+
+	if (gic_nr >= MAX_GIC_NR)
+		BUG();
+
+	dist_base = gic_data[gic_nr].dist_base;
+	cpu_base = gic_data[gic_nr].cpu_base;
+
+	if (!dist_base || !cpu_base)
+		return;
+
+	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
+	for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
+		ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
+	for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
+		ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
+
+}
+
+static void gic_cpu_restore(unsigned int gic_nr)
+{
+	int i;
+	u32 *ptr;
+	void __iomem *dist_base;
+	void __iomem *cpu_base;
+
+	if (gic_nr >= MAX_GIC_NR)
+		BUG();
+
+	dist_base = gic_data[gic_nr].dist_base;
+	cpu_base = gic_data[gic_nr].cpu_base;
+
+	if (!dist_base || !cpu_base)
+		return;
+
+	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
+	for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
+		writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
+	for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
+		writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);
+
+	for (i = 0; i < DIV_ROUND_UP(32, 4); i++)
+		writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4);
+
+	writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
+	writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
+}
+
+static int gic_notifier(struct notifier_block *self, unsigned long cmd,	void *v)
+{
+	int i;
+
+	for (i = 0; i < MAX_GIC_NR; i++) {
+		switch (cmd) {
+		case CPU_PM_ENTER:
+			gic_cpu_save(i);
+			break;
+		case CPU_PM_ENTER_FAILED:
+		case CPU_PM_EXIT:
+			gic_cpu_restore(i);
+			break;
+		case CPU_CLUSTER_PM_ENTER:
+			gic_dist_save(i);
+			break;
+		case CPU_CLUSTER_PM_ENTER_FAILED:
+		case CPU_CLUSTER_PM_EXIT:
+			gic_dist_restore(i);
+			break;
+		}
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block gic_notifier_block = {
+	.notifier_call = gic_notifier,
+};
+
+static void __init gic_pm_init(struct gic_chip_data *gic)
+{
+	gic->saved_ppi_enable = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
+		sizeof(u32));
+	BUG_ON(!gic->saved_ppi_enable);
+
+	gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
+		sizeof(u32));
+	BUG_ON(!gic->saved_ppi_conf);
+
+	if (gic == &gic_data[0])
+		cpu_pm_register_notifier(&gic_notifier_block);
+}
+#else
+static void __init gic_pm_init(struct gic_chip_data *gic)
+{
+}
+#endif
+
+#ifdef CONFIG_OF
+static int gic_irq_domain_dt_translate(struct irq_domain *d,
+				       struct device_node *controller,
+				       const u32 *intspec, unsigned int intsize,
+				       unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 3)
+		return -EINVAL;
+
+	/* Get the interrupt number and add 16 to skip over SGIs */
+	*out_hwirq = intspec[1] + 16;
+
+	/* For SPIs, we need to add 16 more to get the GIC irq ID number */
+	if (!intspec[0])
+		*out_hwirq += 16;
+
+	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+#endif
+
+const struct irq_domain_ops gic_irq_domain_ops = {
+#ifdef CONFIG_OF
+	.dt_translate = gic_irq_domain_dt_translate,
+#endif
+};
+
+void __init gic_init(unsigned int gic_nr, int irq_start,
 	void __iomem *dist_base, void __iomem *cpu_base)
 {
 	struct gic_chip_data *gic;
+	struct irq_domain *domain;
+	int gic_irqs;
 
 	BUG_ON(gic_nr >= MAX_GIC_NR);
 
 	gic = &gic_data[gic_nr];
+	domain = &gic->domain;
 	gic->dist_base = dist_base;
 	gic->cpu_base = cpu_base;
-	gic->irq_offset = (irq_start - 1) & ~31;
 
-	if (gic_nr == 0)
+	/*
+	 * For primary GICs, skip over SGIs.
+	 * For secondary GICs, skip over PPIs, too.
+	 */
+	domain->hwirq_base = 32;
+	if (gic_nr == 0) {
 		gic_cpu_base_addr = cpu_base;
 
-	gic_dist_init(gic, irq_start);
+		if ((irq_start & 31) > 0) {
+			domain->hwirq_base = 16;
+			if (irq_start != -1)
+				irq_start = (irq_start & ~31) + 16;
+		}
+	}
+
+	/*
+	 * Find out how many interrupts are supported.
+	 * The GIC only supports up to 1020 interrupt sources.
+	 */
+	gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
+	gic_irqs = (gic_irqs + 1) * 32;
+	if (gic_irqs > 1020)
+		gic_irqs = 1020;
+	gic->gic_irqs = gic_irqs;
+
+	domain->nr_irq = gic_irqs - domain->hwirq_base;
+	domain->irq_base = irq_alloc_descs(irq_start, 16, domain->nr_irq,
+					   numa_node_id());
+	if (IS_ERR_VALUE(domain->irq_base)) {
+		WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
+		     irq_start);
+		domain->irq_base = irq_start;
+	}
+	domain->priv = gic;
+	domain->ops = &gic_irq_domain_ops;
+	irq_domain_add(domain);
+
+	gic_chip.flags |= gic_arch_extn.flags;
+	gic_dist_init(gic);
 	gic_cpu_init(gic);
+	gic_pm_init(gic);
 }
 
 void __cpuinit gic_secondary_init(unsigned int gic_nr)
@@ -369,20 +628,15 @@
 	gic_cpu_init(&gic_data[gic_nr]);
 }
 
-void __cpuinit gic_enable_ppi(unsigned int irq)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	irq_set_status_flags(irq, IRQ_NOPROBE);
-	gic_unmask_irq(irq_get_irq_data(irq));
-	local_irq_restore(flags);
-}
-
 #ifdef CONFIG_SMP
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 {
-	unsigned long map = *cpus_addr(*mask);
+	int cpu;
+	unsigned long map = 0;
+
+	/* Convert our logical CPU mask into a physical one. */
+	for_each_cpu(cpu, mask)
+		map |= 1 << cpu_logical_map(cpu);
 
 	/*
 	 * Ensure that stores to Normal memory are visible to the
@@ -394,3 +648,35 @@
 	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
 }
 #endif
+
+#ifdef CONFIG_OF
+static int gic_cnt __initdata = 0;
+
+int __init gic_of_init(struct device_node *node, struct device_node *parent)
+{
+	void __iomem *cpu_base;
+	void __iomem *dist_base;
+	int irq;
+	struct irq_domain *domain = &gic_data[gic_cnt].domain;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	dist_base = of_iomap(node, 0);
+	WARN(!dist_base, "unable to map gic dist registers\n");
+
+	cpu_base = of_iomap(node, 1);
+	WARN(!cpu_base, "unable to map gic cpu registers\n");
+
+	domain->of_node = of_node_get(node);
+
+	gic_init(gic_cnt, -1, dist_base, cpu_base);
+
+	if (parent) {
+		irq = irq_of_parse_and_map(node, 0);
+		gic_cascade_irq(gic_cnt, irq);
+	}
+	gic_cnt++;
+	return 0;
+}
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/common/it8152.c linux-libre-3.2-gnu/arch/arm/common/it8152.c
--- linux-libre-3.1-gnu/arch/arm/common/it8152.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/common/it8152.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/ioport.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/export.h>
 
 #include <asm/mach/pci.h>
 #include <asm/hardware/it8152.h>
diff -druN linux-libre-3.1-gnu/arch/arm/common/Kconfig linux-libre-3.2-gnu/arch/arm/common/Kconfig
--- linux-libre-3.1-gnu/arch/arm/common/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/common/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,5 @@
 config ARM_GIC
+	select IRQ_DOMAIN
 	bool
 
 config ARM_VIC
diff -druN linux-libre-3.1-gnu/arch/arm/common/pl330.c linux-libre-3.2-gnu/arch/arm/common/pl330.c
--- linux-libre-3.1-gnu/arch/arm/common/pl330.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/common/pl330.c	2012-01-04 18:55:44.000000000 -0500
@@ -221,17 +221,6 @@
  */
 #define MCODE_BUFF_PER_REQ	256
 
-/*
- * Mark a _pl330_req as free.
- * We do it by writing DMAEND as the first instruction
- * because no valid request is going to have DMAEND as
- * its first instruction to execute.
- */
-#define MARK_FREE(req)	do { \
-				_emit_END(0, (req)->mc_cpu); \
-				(req)->mc_len = 0; \
-			} while (0)
-
 /* If the _pl330_req is available to the client */
 #define IS_FREE(req)	(*((u8 *)((req)->mc_cpu)) == CMD_DMAEND)
 
@@ -301,8 +290,10 @@
 	struct pl330_dmac *dmac;
 	/* Only two at a time */
 	struct _pl330_req req[2];
-	/* Index of the last submitted request */
+	/* Index of the last enqueued request */
 	unsigned lstenq;
+	/* Index of the last submitted request or -1 if the DMA is stopped */
+	int req_running;
 };
 
 enum pl330_dmac_state {
@@ -778,6 +769,22 @@
 	writel(0, regs + DBGCMD);
 }
 
+/*
+ * Mark a _pl330_req as free.
+ * We do it by writing DMAEND as the first instruction
+ * because no valid request is going to have DMAEND as
+ * its first instruction to execute.
+ */
+static void mark_free(struct pl330_thread *thrd, int idx)
+{
+	struct _pl330_req *req = &thrd->req[idx];
+
+	_emit_END(0, req->mc_cpu);
+	req->mc_len = 0;
+
+	thrd->req_running = -1;
+}
+
 static inline u32 _state(struct pl330_thread *thrd)
 {
 	void __iomem *regs = thrd->dmac->pinfo->base;
@@ -836,31 +843,6 @@
 	}
 }
 
-/* If the request 'req' of thread 'thrd' is currently active */
-static inline bool _req_active(struct pl330_thread *thrd,
-		struct _pl330_req *req)
-{
-	void __iomem *regs = thrd->dmac->pinfo->base;
-	u32 buf = req->mc_bus, pc = readl(regs + CPC(thrd->id));
-
-	if (IS_FREE(req))
-		return false;
-
-	return (pc >= buf && pc <= buf + req->mc_len) ? true : false;
-}
-
-/* Returns 0 if the thread is inactive, ID of active req + 1 otherwise */
-static inline unsigned _thrd_active(struct pl330_thread *thrd)
-{
-	if (_req_active(thrd, &thrd->req[0]))
-		return 1; /* First req active */
-
-	if (_req_active(thrd, &thrd->req[1]))
-		return 2; /* Second req active */
-
-	return 0;
-}
-
 static void _stop(struct pl330_thread *thrd)
 {
 	void __iomem *regs = thrd->dmac->pinfo->base;
@@ -892,17 +874,22 @@
 	struct _arg_GO go;
 	unsigned ns;
 	u8 insn[6] = {0, 0, 0, 0, 0, 0};
+	int idx;
 
 	/* Return if already ACTIVE */
 	if (_state(thrd) != PL330_STATE_STOPPED)
 		return true;
 
-	if (!IS_FREE(&thrd->req[1 - thrd->lstenq]))
-		req = &thrd->req[1 - thrd->lstenq];
-	else if (!IS_FREE(&thrd->req[thrd->lstenq]))
-		req = &thrd->req[thrd->lstenq];
-	else
-		req = NULL;
+	idx = 1 - thrd->lstenq;
+	if (!IS_FREE(&thrd->req[idx]))
+		req = &thrd->req[idx];
+	else {
+		idx = thrd->lstenq;
+		if (!IS_FREE(&thrd->req[idx]))
+			req = &thrd->req[idx];
+		else
+			req = NULL;
+	}
 
 	/* Return if no request */
 	if (!req || !req->r)
@@ -933,6 +920,8 @@
 	/* Only manager can execute GO */
 	_execute_DBGINSN(thrd, insn, true);
 
+	thrd->req_running = idx;
+
 	return true;
 }
 
@@ -1211,8 +1200,8 @@
 	ccr |= (rqc->brst_size << CC_SRCBRSTSIZE_SHFT);
 	ccr |= (rqc->brst_size << CC_DSTBRSTSIZE_SHFT);
 
-	ccr |= (rqc->dcctl << CC_SRCCCTRL_SHFT);
-	ccr |= (rqc->scctl << CC_DSTCCTRL_SHFT);
+	ccr |= (rqc->scctl << CC_SRCCCTRL_SHFT);
+	ccr |= (rqc->dcctl << CC_DSTCCTRL_SHFT);
 
 	ccr |= (rqc->swap << CC_SWAP_SHFT);
 
@@ -1382,8 +1371,8 @@
 
 			thrd->req[0].r = NULL;
 			thrd->req[1].r = NULL;
-			MARK_FREE(&thrd->req[0]);
-			MARK_FREE(&thrd->req[1]);
+			mark_free(thrd, 0);
+			mark_free(thrd, 1);
 
 			/* Clear the reset flag */
 			pl330->dmac_tbd.reset_chan &= ~(1 << i);
@@ -1461,14 +1450,12 @@
 
 			thrd = &pl330->channels[id];
 
-			active = _thrd_active(thrd);
-			if (!active) /* Aborted */
+			active = thrd->req_running;
+			if (active == -1) /* Aborted */
 				continue;
 
-			active -= 1;
-
 			rqdone = &thrd->req[active];
-			MARK_FREE(rqdone);
+			mark_free(thrd, active);
 
 			/* Get going again ASAP */
 			_start(thrd);
@@ -1509,7 +1496,7 @@
 	struct pl330_thread *thrd = ch_id;
 	struct pl330_dmac *pl330;
 	unsigned long flags;
-	int ret = 0, active;
+	int ret = 0, active = thrd->req_running;
 
 	if (!thrd || thrd->free || thrd->dmac->state == DYING)
 		return -EINVAL;
@@ -1525,28 +1512,24 @@
 
 		thrd->req[0].r = NULL;
 		thrd->req[1].r = NULL;
-		MARK_FREE(&thrd->req[0]);
-		MARK_FREE(&thrd->req[1]);
+		mark_free(thrd, 0);
+		mark_free(thrd, 1);
 		break;
 
 	case PL330_OP_ABORT:
-		active = _thrd_active(thrd);
-
 		/* Make sure the channel is stopped */
 		_stop(thrd);
 
 		/* ABORT is only for the active req */
-		if (!active)
+		if (active == -1)
 			break;
 
-		active--;
-
 		thrd->req[active].r = NULL;
-		MARK_FREE(&thrd->req[active]);
+		mark_free(thrd, active);
 
 		/* Start the next */
 	case PL330_OP_START:
-		if (!_start(thrd))
+		if ((active == -1) && !_start(thrd))
 			ret = -EIO;
 		break;
 
@@ -1587,14 +1570,13 @@
 	else
 		pstatus->faulting = false;
 
-	active = _thrd_active(thrd);
+	active = thrd->req_running;
 
-	if (!active) {
+	if (active == -1) {
 		/* Indicate that the thread is not running */
 		pstatus->top_req = NULL;
 		pstatus->wait_req = NULL;
 	} else {
-		active--;
 		pstatus->top_req = thrd->req[active].r;
 		pstatus->wait_req = !IS_FREE(&thrd->req[1 - active])
 					? thrd->req[1 - active].r : NULL;
@@ -1623,6 +1605,11 @@
 	return -1;
 }
 
+static bool _chan_ns(const struct pl330_info *pi, int i)
+{
+	return pi->pcfg.irq_ns & (1 << i);
+}
+
 /* Upon success, returns IdentityToken for the
  * allocated channel, NULL otherwise.
  */
@@ -1647,15 +1634,16 @@
 
 	for (i = 0; i < chans; i++) {
 		thrd = &pl330->channels[i];
-		if (thrd->free) {
+		if ((thrd->free) && (!_manager_ns(thrd) ||
+					_chan_ns(pi, i))) {
 			thrd->ev = _alloc_event(thrd);
 			if (thrd->ev >= 0) {
 				thrd->free = false;
 				thrd->lstenq = 1;
 				thrd->req[0].r = NULL;
-				MARK_FREE(&thrd->req[0]);
+				mark_free(thrd, 0);
 				thrd->req[1].r = NULL;
-				MARK_FREE(&thrd->req[1]);
+				mark_free(thrd, 1);
 				break;
 			}
 		}
@@ -1761,14 +1749,14 @@
 	thrd->req[0].mc_bus = pl330->mcode_bus
 				+ (thrd->id * pi->mcbufsz);
 	thrd->req[0].r = NULL;
-	MARK_FREE(&thrd->req[0]);
+	mark_free(thrd, 0);
 
 	thrd->req[1].mc_cpu = thrd->req[0].mc_cpu
 				+ pi->mcbufsz / 2;
 	thrd->req[1].mc_bus = thrd->req[0].mc_bus
 				+ pi->mcbufsz / 2;
 	thrd->req[1].r = NULL;
-	MARK_FREE(&thrd->req[1]);
+	mark_free(thrd, 1);
 }
 
 static int dmac_alloc_threads(struct pl330_dmac *pl330)
diff -druN linux-libre-3.1-gnu/arch/arm/common/sa1111.c linux-libre-3.2-gnu/arch/arm/common/sa1111.c
--- linux-libre-3.1-gnu/arch/arm/common/sa1111.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/common/sa1111.c	2012-01-04 18:55:44.000000000 -0500
@@ -718,6 +718,10 @@
 		goto err_free;
 	}
 
+	ret = clk_prepare(sachip->clk);
+	if (ret)
+		goto err_clkput;
+
 	spin_lock_init(&sachip->lock);
 
 	sachip->dev = me;
@@ -733,7 +737,7 @@
 	sachip->base = ioremap(mem->start, PAGE_SIZE * 2);
 	if (!sachip->base) {
 		ret = -ENOMEM;
-		goto err_clkput;
+		goto err_clk_unprep;
 	}
 
 	/*
@@ -809,6 +813,8 @@
 
  err_unmap:
 	iounmap(sachip->base);
+ err_clk_unprep:
+	clk_unprepare(sachip->clk);
  err_clkput:
 	clk_put(sachip->clk);
  err_free:
@@ -835,6 +841,7 @@
 	sa1111_writel(0, irqbase + SA1111_WAKEEN1);
 
 	clk_disable(sachip->clk);
+	clk_unprepare(sachip->clk);
 
 	if (sachip->irq != NO_IRQ) {
 		irq_set_chained_handler(sachip->irq, NULL);
diff -druN linux-libre-3.1-gnu/arch/arm/common/scoop.c linux-libre-3.2-gnu/arch/arm/common/scoop.c
--- linux-libre-3.1-gnu/arch/arm/common/scoop.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/common/scoop.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,11 +12,12 @@
  */
 
 #include <linux/device.h>
+#include <linux/gpio.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
+#include <linux/export.h>
 #include <linux/io.h>
-#include <asm/gpio.h>
 #include <asm/hardware/scoop.h>
 
 /* PCMCIA to Scoop linkage
diff -druN linux-libre-3.1-gnu/arch/arm/common/timer-sp.c linux-libre-3.2-gnu/arch/arm/common/timer-sp.c
--- linux-libre-3.1-gnu/arch/arm/common/timer-sp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/common/timer-sp.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,9 +41,17 @@
 		return PTR_ERR(clk);
 	}
 
+	err = clk_prepare(clk);
+	if (err) {
+		pr_err("sp804: %s clock failed to prepare: %d\n", name, err);
+		clk_put(clk);
+		return err;
+	}
+
 	err = clk_enable(clk);
 	if (err) {
 		pr_err("sp804: %s clock failed to enable: %d\n", name, err);
+		clk_unprepare(clk);
 		clk_put(clk);
 		return err;
 	}
@@ -52,6 +60,7 @@
 	if (rate < 0) {
 		pr_err("sp804: %s clock failed to get rate: %ld\n", name, rate);
 		clk_disable(clk);
+		clk_unprepare(clk);
 		clk_put(clk);
 	}
 
diff -druN linux-libre-3.1-gnu/arch/arm/common/vic.c linux-libre-3.2-gnu/arch/arm/common/vic.c
--- linux-libre-3.1-gnu/arch/arm/common/vic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/common/vic.c	2012-01-04 18:55:44.000000000 -0500
@@ -346,7 +346,8 @@
 
 	/* Identify which VIC cell this one is, by reading the ID */
 	for (i = 0; i < 4; i++) {
-		u32 addr = ((u32)base & PAGE_MASK) + 0xfe0 + (i * 4);
+		void __iomem *addr;
+		addr = (void __iomem *)((u32)base & PAGE_MASK) + 0xfe0 + (i * 4);
 		cellid |= (readl(addr) & 0xff) << (8 * i);
 	}
 	vendor = (cellid >> 12) & 0xff;
diff -druN linux-libre-3.1-gnu/arch/arm/configs/at91cap9adk_defconfig linux-libre-3.2-gnu/arch/arm/configs/at91cap9adk_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/at91cap9adk_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/at91cap9adk_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,115 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-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_ARCH_AT91=y
-CONFIG_ARCH_AT91CAP9=y
-CONFIG_MACH_AT91CAP9ADK=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_AEABI=y
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=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_UEVENT_HELPER_PATH="/sbin/hotplug"
-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_JEDECPROBE=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# 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_TOUCHSCREEN_ADS7846=y
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_FB=y
-CONFIG_FB_ATMEL=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_CLUT224 is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ETH=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_MMC=y
-CONFIG_MMC_AT91=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
diff -druN linux-libre-3.1-gnu/arch/arm/configs/at91cap9_defconfig linux-libre-3.2-gnu/arch/arm/configs/at91cap9_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/at91cap9_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/configs/at91cap9_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,108 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+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_ARCH_AT91=y
+CONFIG_ARCH_AT91CAP9=y
+CONFIG_MACH_AT91CAP9ADK=y
+CONFIG_MTD_AT91_DATAFLASH_CARD=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_AEABI=y
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=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_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+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_SCSI_MULTI_LUN=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=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_TOUCHSCREEN_ADS7846=y
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_FB=y
+CONFIG_FB_ATMEL=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ETH=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_MMC=y
+CONFIG_MMC_AT91=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
diff -druN linux-libre-3.1-gnu/arch/arm/configs/at91rm9200_defconfig linux-libre-3.2-gnu/arch/arm/configs/at91rm9200_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/at91rm9200_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/at91rm9200_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,6 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_MODULES=y
 CONFIG_MODULE_FORCE_LOAD=y
@@ -56,7 +55,6 @@
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -75,18 +73,8 @@
 CONFIG_BRIDGE=m
 CONFIG_VLAN_8021Q=m
 CONFIG_BT=m
-CONFIG_BT_L2CAP=m
-CONFIG_BT_SCO=m
-CONFIG_BT_RFCOMM=m
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=m
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_AFS_PARTS=y
 CONFIG_MTD_CHAR=y
@@ -108,8 +96,6 @@
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_TCLIB=y
-CONFIG_EEPROM_LEGACY=m
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=m
@@ -119,14 +105,23 @@
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 CONFIG_TUN=m
+CONFIG_ARM_AT91_ETHER=y
 CONFIG_PHYLIB=y
 CONFIG_DAVICOM_PHY=y
 CONFIG_SMSC_PHY=y
 CONFIG_MICREL_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=y
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
 CONFIG_USB_CATC=m
 CONFIG_USB_KAWETH=m
 CONFIG_USB_PEGASUS=m
@@ -139,18 +134,6 @@
 CONFIG_USB_ALI_M5632=y
 CONFIG_USB_AN2720=y
 CONFIG_USB_EPSON2888=y
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=y
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
@@ -158,9 +141,9 @@
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_LEGACY_PTY_COUNT=32
 CONFIG_SERIAL_ATMEL=y
 CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=32
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -290,7 +273,6 @@
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
-CONFIG_SMB_FS=m
 CONFIG_CIFS=m
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAC_PARTITION=y
@@ -335,7 +317,6 @@
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_FTRACE is not set
 CONFIG_CRYPTO_PCBC=y
 CONFIG_CRYPTO_SHA1=y
diff -druN linux-libre-3.1-gnu/arch/arm/configs/at91sam9260_defconfig linux-libre-3.2-gnu/arch/arm/configs/at91sam9260_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/at91sam9260_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/configs/at91sam9260_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,91 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+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_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9260=y
+CONFIG_ARCH_AT91SAM9260_SAM9XE=y
+CONFIG_MACH_AT91SAM9260EK=y
+CONFIG_MACH_CAM60=y
+CONFIG_MACH_SAM9_L9260=y
+CONFIG_MACH_AFEB9260=y
+CONFIG_MACH_USB_A9260=y
+CONFIG_MACH_QIL_A9260=y
+CONFIG_MACH_CPU9260=y
+CONFIG_MACH_FLEXIBITY=y
+CONFIG_MACH_SNAPPER_9260=y
+CONFIG_MACH_AT91SAM_DT=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=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_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_AT91SAM9X_WATCHDOG=y
+# CONFIG_USB_HID is not set
+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_GADGET=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
diff -druN linux-libre-3.1-gnu/arch/arm/configs/at91sam9260ek_defconfig linux-libre-3.2-gnu/arch/arm/configs/at91sam9260ek_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/at91sam9260ek_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/at91sam9260ek_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-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_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9260=y
-CONFIG_MACH_AT91SAM9260EK=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=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_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91SAM9X_WATCHDOG=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_USB_HID is not set
-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_GADGET=y
-CONFIG_USB_ZERO=m
-CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
diff -druN linux-libre-3.1-gnu/arch/arm/configs/at91sam9g20_defconfig linux-libre-3.2-gnu/arch/arm/configs/at91sam9g20_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/at91sam9g20_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/configs/at91sam9g20_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,124 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+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_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9G20=y
+CONFIG_MACH_AT91SAM9G20EK=y
+CONFIG_MACH_AT91SAM9G20EK_2MMC=y
+CONFIG_MACH_CPU9G20=y
+CONFIG_MACH_ACMENETUSFOXG20=y
+CONFIG_MACH_PORTUXG20=y
+CONFIG_MACH_STAMP9G20=y
+CONFIG_MACH_PCONTROL_G20=y
+CONFIG_MACH_GSIA18S=y
+CONFIG_MACH_USB_A9G20=y
+CONFIG_MACH_SNAPPER_9260=y
+CONFIG_MACH_AT91SAM_DT=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_AEABI=y
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=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_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+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_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_LEGACY_PTY_COUNT=16
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+CONFIG_SPI_SPIDEV=y
+# CONFIG_HWMON is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_VERBOSE_PROCFS is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_AT91=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_UTF8=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
diff -druN linux-libre-3.1-gnu/arch/arm/configs/at91sam9g20ek_defconfig linux-libre-3.2-gnu/arch/arm/configs/at91sam9g20ek_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/at91sam9g20ek_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/at91sam9g20ek_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,123 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-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_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9G20=y
-CONFIG_MACH_AT91SAM9G20EK=y
-CONFIG_MACH_AT91SAM9G20EK_2MMC=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_AEABI=y
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=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_IPV6 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_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=16
-CONFIG_HW_RANDOM=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-CONFIG_SPI_SPIDEV=y
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_SEQUENCER=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_VERBOSE_PROCFS is not set
-CONFIG_SND_AT73C213=y
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ZERO=m
-CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_MMC=y
-CONFIG_MMC_AT91=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
diff -druN linux-libre-3.1-gnu/arch/arm/configs/at91sam9g45_defconfig linux-libre-3.2-gnu/arch/arm/configs/at91sam9g45_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/at91sam9g45_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/configs/at91sam9g45_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,211 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=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_AT91=y
+CONFIG_ARCH_AT91SAM9G45=y
+CONFIG_MACH_AT91SAM9M10G45EK=y
+CONFIG_MACH_AT91SAM_DT=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+CONFIG_AT91_SLOW_CLOCK=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=128M console=ttyS0,115200 initrd=0x71100000,25165824 root=/dev/ram0 rw"
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_CFG80211=y
+CONFIG_LIB80211=y
+CONFIG_MAC80211=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_MISC_DEVICES=y
+CONFIG_ATMEL_PWM=y
+CONFIG_ATMEL_TCLIB=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_LIBERTAS_THINFIRM=m
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_AT76C50X_USB=m
+CONFIG_USB_ZD1201=m
+CONFIG_RTL8187=m
+CONFIG_ATH_COMMON=m
+CONFIG_ATH9K=m
+CONFIG_CARL9170=m
+CONFIG_B43=m
+CONFIG_B43_PHY_N=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_SPI=m
+CONFIG_RT2X00=m
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT53XX=y
+CONFIG_RT2800USB_UNKNOWN=y
+CONFIG_RTL8192CU=m
+CONFIG_WL1251=m
+CONFIG_WL1251_SDIO=m
+CONFIG_WL12XX_MENU=m
+CONFIG_WL12XX=m
+CONFIG_WL12XX_SDIO=m
+CONFIG_ZD1211RW=m
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
+CONFIG_INPUT_POLLDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=480
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=272
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_QT1070=m
+CONFIG_KEYBOARD_QT2160=m
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
+# CONFIG_SERIO is not set
+CONFIG_LEGACY_PTY_COUNT=4
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FB_ATMEL=y
+CONFIG_FB_UDL=m
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_ATMEL_LCDC=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_ATMEL_AC97C=y
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB_AUDIO=m
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ATMEL_USBA=m
+CONFIG_USB_ZERO=m
+CONFIG_USB_AUDIO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_CDC=y
+CONFIG_MMC=y
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_SDIO_UART=m
+CONFIG_MMC_ATMELMCI=y
+CONFIG_MMC_ATMELMCI_DMA=y
+CONFIG_LEDS_ATMEL_PWM=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91RM9200=y
+CONFIG_DMADEVICES=y
+CONFIG_AT_HDMAC=y
+CONFIG_DMATEST=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_FANOTIFY=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_EMBEDDED=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+# CONFIG_CRYPTO_HW is not set
diff -druN linux-libre-3.1-gnu/arch/arm/configs/at91sam9rl_defconfig linux-libre-3.2-gnu/arch/arm/configs/at91sam9rl_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/at91sam9rl_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/configs/at91sam9rl_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,79 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+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_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9RL=y
+CONFIG_MACH_AT91SAM9RLEK=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,17105363 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_UNIX=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=24576
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_AT91SAM9X_WATCHDOG=y
+CONFIG_FB=y
+CONFIG_FB_ATMEL=y
+CONFIG_MMC=y
+CONFIG_MMC_AT91=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_UTF8=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
diff -druN linux-libre-3.1-gnu/arch/arm/configs/at91sam9rlek_defconfig linux-libre-3.2-gnu/arch/arm/configs/at91sam9rlek_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/at91sam9rlek_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/at91sam9rlek_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,84 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-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_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9RL=y
-CONFIG_MACH_AT91SAM9RLEK=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,17105363 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_UNIX=y
-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_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=4
-CONFIG_BLK_DEV_RAM_SIZE=24576
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91SAM9X_WATCHDOG=y
-CONFIG_FB=y
-CONFIG_FB_ATMEL=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_MMC=y
-CONFIG_MMC_AT91=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
diff -druN linux-libre-3.1-gnu/arch/arm/configs/exynos4_defconfig linux-libre-3.2-gnu/arch/arm/configs/exynos4_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/exynos4_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/exynos4_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -4,18 +4,18 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_EXYNOS4=y
+CONFIG_ARCH_EXYNOS=y
 CONFIG_S3C_LOWLEVEL_UART_PORT=1
 CONFIG_MACH_SMDKC210=y
-CONFIG_MACH_SMDKV310=y
 CONFIG_MACH_ARMLEX4210=y
 CONFIG_MACH_UNIVERSAL_C210=y
 CONFIG_MACH_NURI=y
+CONFIG_MACH_ORIGEN=y
+CONFIG_MACH_SMDK4412=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"
@@ -60,13 +60,9 @@
 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-3.1-gnu/arch/arm/configs/ezx_defconfig linux-libre-3.2-gnu/arch/arm/configs/ezx_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/ezx_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/ezx_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -287,7 +287,7 @@
 # CONFIG_USB_DEVICE_CLASS is not set
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_MMC=y
diff -druN linux-libre-3.1-gnu/arch/arm/configs/imote2_defconfig linux-libre-3.2-gnu/arch/arm/configs/imote2_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/imote2_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/imote2_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -263,7 +263,7 @@
 # CONFIG_USB_DEVICE_CLASS is not set
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_MMC=y
diff -druN linux-libre-3.1-gnu/arch/arm/configs/imx_v4_v5_defconfig linux-libre-3.2-gnu/arch/arm/configs/imx_v4_v5_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/imx_v4_v5_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/configs/imx_v4_v5_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,172 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EXPERT=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
+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_ARCH_MXC=y
+CONFIG_ARCH_IMX_V4_V5=y
+CONFIG_ARCH_MX1ADS=y
+CONFIG_MACH_SCB9328=y
+CONFIG_MACH_APF9328=y
+CONFIG_MACH_MX21ADS=y
+CONFIG_MACH_MX25_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX25SD=y
+CONFIG_MACH_MX27ADS=y
+CONFIG_MACH_PCM038=y
+CONFIG_MACH_CPUIMX27=y
+CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2=y
+CONFIG_MACH_EUKREA_CPUIMX27_USEUART4=y
+CONFIG_MACH_MX27_3DS=y
+CONFIG_MACH_IMX27_VISSTRIM_M10=y
+CONFIG_MACH_IMX27LITE=y
+CONFIG_MACH_PCA100=y
+CONFIG_MACH_MXT_TD60=y
+CONFIG_MACH_IMX27IPCAM=y
+CONFIG_MXC_IRQ_PRIOR=y
+CONFIG_MXC_PWM=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+CONFIG_PM_DEBUG=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=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_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_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_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+# CONFIG_MTD_CFI_I2 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_MXC=y
+CONFIG_MTD_UBI=y
+CONFIG_MISC_DEVICES=y
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_NETDEVICES=y
+CONFIG_DM9000=y
+CONFIG_SMC91X=y
+CONFIG_SMC911X=y
+CONFIG_SMSC_PHY=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_TOUCHSCREEN_ADS7846=m
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_IMX=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_W1=y
+CONFIG_W1_MASTER_MXC=y
+CONFIG_W1_SLAVE_THERM=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_MC13XXX=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_MC13783=y
+CONFIG_REGULATOR_MC13892=y
+CONFIG_FB=y
+CONFIG_FB_IMX=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_SOC_MX27VIS_AIC32X4=y
+CONFIG_SND_SOC_PHYCORE_AC97=y
+CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_USB_HID=m
+CONFIG_USB=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_ULPI=y
+CONFIG_MMC=y
+CONFIG_MMC_MXC=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_MC13783=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PCF8563=y
+CONFIG_RTC_DRV_IMXDI=y
+CONFIG_RTC_MXC=y
+CONFIG_DMADEVICES=y
+CONFIG_IMX_SDMA=y
+CONFIG_IMX_DMA=y
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_UBIFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druN linux-libre-3.1-gnu/arch/arm/configs/integrator_defconfig linux-libre-3.2-gnu/arch/arm/configs/integrator_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/integrator_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/integrator_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_TINY_RCU=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -8,20 +9,29 @@
 CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_INTEGRATOR=y
 CONFIG_ARCH_INTEGRATOR_AP=y
+CONFIG_ARCH_INTEGRATOR_CP=y
 CONFIG_CPU_ARM720T=y
 CONFIG_CPU_ARM920T=y
+CONFIG_CPU_ARM922T=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_ARM1020=y
+CONFIG_CPU_ARM1022=y
+CONFIG_CPU_ARM1026=y
 CONFIG_PCI=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
 CONFIG_LEDS=y
 CONFIG_LEDS_CPU=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyAM0,38400n8 root=/dev/nfs ip=bootp mem=32M"
+CONFIG_CMDLINE="console=ttyAM0,38400n8 root=/dev/nfs ip=bootp"
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
 CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -32,7 +42,6 @@
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IPV6 is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_AFS_PARTS=y
 CONFIG_MTD_CHAR=y
@@ -40,6 +49,7 @@
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
@@ -56,6 +66,8 @@
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PL030=y
 CONFIG_EXT2_FS=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
@@ -68,4 +80,3 @@
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_ERRORS=y
diff -druN linux-libre-3.1-gnu/arch/arm/configs/magician_defconfig linux-libre-3.2-gnu/arch/arm/configs/magician_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/magician_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/magician_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -132,7 +132,7 @@
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_VBUS_DRAW=500
-CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_USB_GADGETFS=m
diff -druN linux-libre-3.1-gnu/arch/arm/configs/mx1_defconfig linux-libre-3.2-gnu/arch/arm/configs/mx1_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/mx1_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/mx1_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX1=y
-CONFIG_ARCH_MX1ADS=y
-CONFIG_MACH_SCB9328=y
-CONFIG_MACH_APF9328=y
-CONFIG_MXC_IRQ_PRIOR=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off"
-CONFIG_PM=y
-CONFIG_PM_DEBUG=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=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_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_FW_LOADER=m
-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_PHYSMAP=y
-# CONFIG_BLK_DEV is not set
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_PHYLIB=y
-CONFIG_SMSC_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_DM9000=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_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_IMX=y
-CONFIG_W1=y
-CONFIG_W1_MASTER_MXC=y
-CONFIG_W1_SLAVE_THERM=y
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_IMX=y
-CONFIG_USB_ETH=m
-CONFIG_MMC=y
-CONFIG_MMC_MXC=y
-# CONFIG_DNOTIFY is not set
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druN linux-libre-3.1-gnu/arch/arm/configs/mx21_defconfig linux-libre-3.2-gnu/arch/arm/configs/mx21_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/mx21_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/mx21_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,97 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_SLAB=y
-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_ARCH_MXC=y
-CONFIG_ARCH_MX2=y
-CONFIG_MACH_MX21ADS=y
-CONFIG_MXC_PWM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_NET=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=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 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_FW_LOADER is not set
-CONFIG_MTD=y
-CONFIG_MTD_DEBUG=y
-CONFIG_MTD_DEBUG_VERBOSE=3
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_CMDLINE_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_1 is not set
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_MXC=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# 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_CONSOLE_TRANSLATIONS is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=1
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_IMX=y
-CONFIG_SPI=y
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FB_IMX=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_LOGO=y
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_MMC=y
-CONFIG_MMC_MXC=y
-# CONFIG_DNOTIFY is not set
-CONFIG_MSDOS_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druN linux-libre-3.1-gnu/arch/arm/configs/mx27_defconfig linux-libre-3.2-gnu/arch/arm/configs/mx27_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/mx27_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/mx27_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,130 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_COMPAT_BRK is not set
-CONFIG_SLAB=y
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
-CONFIG_KPROBES=y
-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_ARCH_MXC=y
-CONFIG_ARCH_MX2=y
-CONFIG_MACH_MX27=y
-CONFIG_MACH_MX27ADS=y
-CONFIG_MACH_PCM038=y
-CONFIG_MACH_CPUIMX27=y
-CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2=y
-CONFIG_MACH_EUKREA_CPUIMX27_USEUART4=y
-CONFIG_MACH_MX27_3DS=y
-CONFIG_MACH_IMX27_VISSTRIM_M10=y
-CONFIG_MACH_IMX27LITE=y
-CONFIG_MACH_PCA100=y
-CONFIG_MACH_MXT_TD60=y
-CONFIG_MXC_IRQ_PRIOR=y
-CONFIG_MXC_PWM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_NWFPE=y
-CONFIG_FPE_NWFPE_XP=y
-CONFIG_PM=y
-CONFIG_PM_DEBUG=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=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_UEVENT_HELPER_PATH="/sbin/hotplug"
-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_ADV_OPTIONS=y
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
-# CONFIG_MTD_CFI_I2 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_MXC=y
-CONFIG_MTD_UBI=y
-CONFIG_EEPROM_AT24=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_FEC=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# 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_TOUCHSCREEN_ADS7846=m
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_IMX=y
-CONFIG_SPI=y
-CONFIG_SPI_IMX=y
-CONFIG_W1=y
-CONFIG_W1_MASTER_MXC=y
-CONFIG_W1_SLAVE_THERM=y
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FB_IMX=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=m
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_ULPI=y
-CONFIG_MMC=y
-CONFIG_MMC_MXC=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_PCF8563=y
-# CONFIG_DNOTIFY is not set
-# CONFIG_PROC_PAGE_MONITOR is not set
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_UBIFS_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS=y
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=m
-CONFIG_DEBUG_FS=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druN linux-libre-3.1-gnu/arch/arm/configs/mx3_defconfig linux-libre-3.2-gnu/arch/arm/configs/mx3_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/mx3_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/mx3_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,6 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -13,20 +12,21 @@
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_ARCH_MXC=y
 CONFIG_MACH_MX31ADS_WM1133_EV1=y
+CONFIG_MACH_MX31LILLY=y
+CONFIG_MACH_MX31LITE=y
 CONFIG_MACH_PCM037=y
 CONFIG_MACH_PCM037_EET=y
-CONFIG_MACH_MX31LITE=y
 CONFIG_MACH_MX31_3DS=y
 CONFIG_MACH_MX31MOBOARD=y
-CONFIG_MACH_MX31LILLY=y
 CONFIG_MACH_QONG=y
-CONFIG_MACH_PCM043=y
 CONFIG_MACH_ARMADILLO5X0=y
-CONFIG_MACH_MX35_3DS=y
 CONFIG_MACH_KZM_ARM11_01=y
+CONFIG_MACH_PCM043=y
+CONFIG_MACH_MX35_3DS=y
 CONFIG_MACH_EUKREA_CPUIMX35=y
 CONFIG_MXC_IRQ_PRIOR=y
 CONFIG_MXC_PWM=y
+CONFIG_ARM_ERRATA_411920=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT=y
@@ -35,7 +35,6 @@
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off"
 CONFIG_VFP=y
-CONFIG_PM=y
 CONFIG_PM_DEBUG=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -52,7 +51,6 @@
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_FW_LOADER=m
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
@@ -62,24 +60,27 @@
 CONFIG_MTD_NAND_MXC=y
 CONFIG_MTD_UBI=y
 # CONFIG_BLK_DEV is not set
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT24=y
 CONFIG_NETDEVICES=y
 CONFIG_SMSC_PHY=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMSC911X=y
 CONFIG_DNET=y
-CONFIG_FEC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_IMX=y
+# CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_8250=m
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_IMX=y
 CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -89,12 +90,15 @@
 CONFIG_W1_MASTER_MXC=y
 CONFIG_W1_SLAVE_THERM=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
 CONFIG_MFD_WM8350_I2C=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_WM8350=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
-# CONFIG_VIDEO_ALLOW_V4L1 is not set
+# CONFIG_RC_CORE is not set
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
 CONFIG_SOC_CAMERA=y
 CONFIG_SOC_CAMERA_MT9M001=y
 CONFIG_SOC_CAMERA_MT9M111=y
@@ -105,9 +109,26 @@
 CONFIG_VIDEO_MX3=y
 # CONFIG_RADIO_ADAPTERS is not set
 CONFIG_FB=y
-# CONFIG_USB_SUPPORT is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_MXC_SOC_WM1133_EV1=y
+CONFIG_SND_SOC_PHYCORE_AC97=y
+CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_GADGET=m
+CONFIG_USB_FSL_USB2=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_ULPI=y
 CONFIG_MMC=y
 CONFIG_MMC_MXC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_MXC=y
 CONFIG_DMADEVICES=y
 # CONFIG_DNOTIFY is not set
 CONFIG_TMPFS=y
@@ -119,6 +140,5 @@
 CONFIG_ROOT_NFS=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druN linux-libre-3.1-gnu/arch/arm/configs/mx51_defconfig linux-libre-3.2-gnu/arch/arm/configs/mx51_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/mx51_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/mx51_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,170 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=18
-CONFIG_RELAY=y
-CONFIG_EXPERT=y
-# CONFIG_SLUB_DEBUG is not set
-# CONFIG_COMPAT_BRK is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_LBDAF is not set
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX51=y
-CONFIG_MACH_MX51_BABBAGE=y
-CONFIG_MACH_MX51_3DS=y
-CONFIG_MACH_EUKREA_CPUIMX51=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT_VOLUNTARY=y
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
-CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.0.101:/shared/nfs ip=dhcp"
-CONFIG_VFP=y
-CONFIG_NEON=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PM=y
-CONFIG_PM_DEBUG=y
-CONFIG_PM_TEST_SUSPEND=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=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_IPV6 is not set
-# CONFIG_WIRELESS is not set
-# CONFIG_STANDALONE is not set
-CONFIG_CONNECTOR=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=65536
-# CONFIG_MISC_DEVICES is not set
-CONFIG_SCSI=y
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_ATA=m
-CONFIG_NETDEVICES=y
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-CONFIG_BROADCOM_PHY=y
-CONFIG_ICPLUS_PHY=y
-CONFIG_REALTEK_PHY=y
-CONFIG_NATIONAL_PHY=y
-CONFIG_STE10XP=y
-CONFIG_LSI_ET1011C_PHY=y
-CONFIG_MDIO_BITBANG=y
-CONFIG_MDIO_GPIO=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=m
-CONFIG_FEC=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_WLAN is not set
-CONFIG_INPUT_FF_MEMLESS=m
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-CONFIG_KEYBOARD_GPIO=y
-CONFIG_INPUT_EVBUG=m
-CONFIG_MOUSE_PS2=m
-CONFIG_MOUSE_PS2_ELANTECH=y
-CONFIG_SERIO_SERPORT=m
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-# CONFIG_I2C_COMPAT is not set
-CONFIG_I2C_CHARDEV=m
-# CONFIG_I2C_HELPER_AUTO is not set
-CONFIG_I2C_ALGOBIT=m
-CONFIG_I2C_ALGOPCF=m
-CONFIG_I2C_ALGOPCA=m
-CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_MXC=y
-CONFIG_USB_STORAGE=y
-CONFIG_MMC=y
-CONFIG_MMC_BLOCK=m
-CONFIG_MMC_SDHCI=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_INTF_DEV_UIE_EMUL=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_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_EXT4_FS=y
-CONFIG_EXT4_FS_POSIX_ACL=y
-CONFIG_EXT4_FS_SECURITY=y
-CONFIG_QUOTA=y
-CONFIG_QUOTA_NETLINK_INTERFACE=y
-# CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_FUSE_FS=y
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=m
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_DEFAULT="cp437"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_UTF8=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_FTRACE is not set
-# CONFIG_ARM_UNWIND is not set
-CONFIG_DEBUG_LL=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_SECURITYFS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_LZO=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_CCITT=m
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC7=m
-CONFIG_LIBCRC32C=m
diff -druN linux-libre-3.1-gnu/arch/arm/configs/mx5_defconfig linux-libre-3.2-gnu/arch/arm/configs/mx5_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/mx5_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/configs/mx5_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,184 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_RELAY=y
+CONFIG_EXPERT=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_MXC=y
+CONFIG_ARCH_MX5=y
+CONFIG_MACH_MX51_BABBAGE=y
+CONFIG_MACH_MX51_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX51=y
+CONFIG_MACH_EUKREA_CPUIMX51SD=y
+CONFIG_MACH_MX51_EFIKAMX=y
+CONFIG_MACH_MX51_EFIKASB=y
+CONFIG_MACH_MX53_EVK=y
+CONFIG_MACH_MX53_SMD=y
+CONFIG_MACH_MX53_LOCO=y
+CONFIG_MACH_MX53_ARD=y
+CONFIG_MXC_PWM=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=m
+CONFIG_PM_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=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_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_PATA_IMX=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=m
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+CONFIG_VITESSE_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_BROADCOM_PHY=y
+CONFIG_ICPLUS_PHY=y
+CONFIG_REALTEK_PHY=y
+CONFIG_NATIONAL_PHY=y
+CONFIG_STE10XP=y
+CONFIG_LSI_ET1011C_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_NET_ETHERNET=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MMA8450=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_IMX=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_MC13XXX=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_MC13892=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_MXC=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_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=m
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_SECURITYFS=y
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
diff -druN linux-libre-3.1-gnu/arch/arm/configs/mxs_defconfig linux-libre-3.2-gnu/arch/arm/configs/mxs_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/mxs_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/mxs_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 CONFIG_MACH_MX28EVK=y
 CONFIG_MACH_STMP378X_DEVB=y
 CONFIG_MACH_TX28=y
+CONFIG_MACH_M28EVK=y
 # CONFIG_ARM_THUMB is not set
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
diff -druN linux-libre-3.1-gnu/arch/arm/configs/omap1_defconfig linux-libre-3.2-gnu/arch/arm/configs/omap1_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/omap1_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/omap1_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -48,13 +48,7 @@
 CONFIG_MACH_NOKIA770=y
 CONFIG_MACH_AMS_DELTA=y
 CONFIG_MACH_OMAP_GENERIC=y
-CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER=y
-CONFIG_OMAP_ARM_216MHZ=y
-CONFIG_OMAP_ARM_195MHZ=y
-CONFIG_OMAP_ARM_192MHZ=y
 CONFIG_OMAP_ARM_182MHZ=y
-CONFIG_OMAP_ARM_168MHZ=y
-# CONFIG_OMAP_ARM_60MHZ is not set
 # CONFIG_ARM_THUMB is not set
 CONFIG_PCCARD=y
 CONFIG_OMAP_CF=y
diff -druN linux-libre-3.1-gnu/arch/arm/configs/tegra_defconfig linux-libre-3.2-gnu/arch/arm/configs/tegra_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/tegra_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/tegra_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 CONFIG_MACH_PAZ00=y
 CONFIG_MACH_TRIMSLICE=y
 CONFIG_MACH_WARIO=y
+CONFIG_MACH_VENTANA=y
 CONFIG_TEGRA_DEBUG_UARTD=y
 CONFIG_ARM_ERRATA_742230=y
 CONFIG_NO_HZ=y
@@ -38,7 +39,6 @@
 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
@@ -65,6 +65,7 @@
 CONFIG_IPV6_MULTIPLE_TABLES=y
 # CONFIG_WIRELESS is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_MISC_DEVICES=y
 CONFIG_AD525X_DPOT=y
@@ -72,34 +73,61 @@
 CONFIG_ICS932S401=y
 CONFIG_APDS9802ALS=y
 CONFIG_ISL29003=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_NET_ETHERNET=y
 CONFIG_R8169=y
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_WLAN is not set
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC75XX=y
+CONFIG_USB_NET_SMSC95XX=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_OF_PLATFORM=y
 # 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_SPI=y
+CONFIG_SPI_TEGRA=y
 CONFIG_SENSORS_LM90=y
 CONFIG_MFD_TPS6586X=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_TPS6586X=y
-# CONFIG_USB_SUPPORT is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_PCI is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_TEGRA=y
+CONFIG_SND_SOC_TEGRA_WM8903=y
+CONFIG_SND_SOC_TEGRA_TRIMSLICE=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_TEGRA=y
+CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_TEGRA=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_TEGRA=y
 CONFIG_STAGING=y
-# CONFIG_STAGING_EXCLUDE_BUILD is not set
 CONFIG_IIO=y
 CONFIG_SENSORS_ISL29018=y
 CONFIG_SENSORS_AK8975=y
@@ -123,18 +151,15 @@
 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
diff -druN linux-libre-3.1-gnu/arch/arm/configs/u300_defconfig linux-libre-3.2-gnu/arch/arm/configs/u300_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/u300_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/u300_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -14,8 +14,6 @@
 CONFIG_ARCH_U300=y
 CONFIG_MACH_U300=y
 CONFIG_MACH_U300_BS335=y
-CONFIG_MACH_U300_DUAL_RAM=y
-CONFIG_U300_DEBUG=y
 CONFIG_MACH_U300_SPIDUMMY=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -26,19 +24,21 @@
 CONFIG_CMDLINE="root=/dev/ram0 rw rootfstype=rootfs console=ttyAMA0,115200n8 lpj=515072"
 CONFIG_CPU_IDLE=y
 CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
 # CONFIG_SUSPEND is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_MISC_DEVICES is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSMC=y
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_LEGACY_PTY_COUNT=16
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 # CONFIG_HWMON is not set
@@ -51,6 +51,7 @@
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
 CONFIG_MMC_ARMMMCI=y
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_HCTOSYS is not set
@@ -65,10 +66,8 @@
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_CRC32 is not set
diff -druN linux-libre-3.1-gnu/arch/arm/configs/u8500_defconfig linux-libre-3.2-gnu/arch/arm/configs/u8500_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/u8500_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/u8500_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
 CONFIG_ARCH_U8500=y
 CONFIG_UX500_SOC_DB5500=y
 CONFIG_UX500_SOC_DB8500=y
-CONFIG_MACH_U8500=y
+CONFIG_MACH_HREFV60=y
 CONFIG_MACH_SNOWBALL=y
 CONFIG_MACH_U5500=y
 CONFIG_NO_HZ=y
@@ -24,6 +24,7 @@
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_VFP=y
 CONFIG_NEON=y
+CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -41,11 +42,8 @@
 CONFIG_AB8500_PWM=y
 CONFIG_SENSORS_BH1780=y
 CONFIG_NETDEVICES=y
-CONFIG_SMSC_PHY=y
-CONFIG_NET_ETHERNET=y
 CONFIG_SMSC911X=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+CONFIG_SMSC_PHY=y
 # CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_EVDEV=y
@@ -72,15 +70,12 @@
 CONFIG_SPI_PL022=y
 CONFIG_GPIO_STMPE=y
 CONFIG_GPIO_TC3589X=y
-# CONFIG_HWMON is not set
 CONFIG_MFD_STMPE=y
 CONFIG_MFD_TC3589X=y
+CONFIG_AB5500_CORE=y
 CONFIG_AB8500_CORE=y
 CONFIG_REGULATOR_AB8500=y
 # CONFIG_HID_SUPPORT is not set
-CONFIG_USB_MUSB_HDRC=y
-CONFIG_USB_GADGET_MUSB_HDRC=y
-CONFIG_MUSB_PIO_ONLY=y
 CONFIG_USB_GADGET=y
 CONFIG_AB8500_USB=y
 CONFIG_MMC=y
@@ -97,6 +92,7 @@
 CONFIG_STE_DMA40=y
 CONFIG_STAGING=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
+CONFIG_HSEM_U8500=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
diff -druN linux-libre-3.1-gnu/arch/arm/configs/zeus_defconfig linux-libre-3.2-gnu/arch/arm/configs/zeus_defconfig
--- linux-libre-3.1-gnu/arch/arm/configs/zeus_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/configs/zeus_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -140,7 +140,7 @@
 CONFIG_USB_SERIAL_GENERIC=y
 CONFIG_USB_SERIAL_MCT_U232=m
 CONFIG_USB_GADGET=m
-CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
 CONFIG_USB_FILE_STORAGE=m
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/auxvec.h linux-libre-3.2-gnu/arch/arm/include/asm/auxvec.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/auxvec.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/auxvec.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,4 +0,0 @@
-#ifndef __ASMARM_AUXVEC_H
-#define __ASMARM_AUXVEC_H
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/bitsperlong.h linux-libre-3.2-gnu/arch/arm/include/asm/bitsperlong.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/bitsperlong.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/bitsperlong.h>
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/bug.h linux-libre-3.2-gnu/arch/arm/include/asm/bug.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/bug.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/bug.h	2012-01-04 18:55:44.000000000 -0500
@@ -3,21 +3,58 @@
 
 
 #ifdef CONFIG_BUG
+
+/*
+ * Use a suitable undefined instruction to use for ARM/Thumb2 bug handling.
+ * We need to be careful not to conflict with those used by other modules and
+ * the register_undef_hook() system.
+ */
+#ifdef CONFIG_THUMB2_KERNEL
+#define BUG_INSTR_VALUE 0xde02
+#define BUG_INSTR_TYPE ".hword "
+#else
+#define BUG_INSTR_VALUE 0xe7f001f2
+#define BUG_INSTR_TYPE ".word "
+#endif
+
+
+#define BUG() _BUG(__FILE__, __LINE__, BUG_INSTR_VALUE)
+#define _BUG(file, line, value) __BUG(file, line, value)
+
 #ifdef CONFIG_DEBUG_BUGVERBOSE
-extern void __bug(const char *file, int line) __attribute__((noreturn));
 
-/* give file/line information */
-#define BUG()		__bug(__FILE__, __LINE__)
+/*
+ * The extra indirection is to ensure that the __FILE__ string comes through
+ * OK. Many version of gcc do not support the asm %c parameter which would be
+ * preferable to this unpleasantness. We use mergeable string sections to
+ * avoid multiple copies of the string appearing in the kernel image.
+ */
 
-#else
+#define __BUG(__file, __line, __value)				\
+do {								\
+	BUILD_BUG_ON(sizeof(struct bug_entry) != 12);		\
+	asm volatile("1:\t" BUG_INSTR_TYPE #__value "\n"	\
+		".pushsection .rodata.str, \"aMS\", %progbits, 1\n" \
+		"2:\t.asciz " #__file "\n" 			\
+		".popsection\n" 				\
+		".pushsection __bug_table,\"a\"\n"		\
+		"3:\t.word 1b, 2b\n"				\
+		"\t.hword " #__line ", 0\n"			\
+		".popsection");					\
+	unreachable();						\
+} while (0)
 
-/* this just causes an oops */
-#define BUG()		do { *(int *)0 = 0; } while (1)
+#else  /* not CONFIG_DEBUG_BUGVERBOSE */
 
-#endif
+#define __BUG(__file, __line, __value)				\
+do {								\
+	asm volatile(BUG_INSTR_TYPE #__value);			\
+	unreachable();						\
+} while (0)
+#endif  /* CONFIG_DEBUG_BUGVERBOSE */
 
 #define HAVE_ARCH_BUG
-#endif
+#endif  /* CONFIG_BUG */
 
 #include <asm-generic/bug.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/cachetype.h linux-libre-3.2-gnu/arch/arm/include/asm/cachetype.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/cachetype.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/cachetype.h	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
 #define CACHEID_VIPT			(CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING)
 #define CACHEID_ASID_TAGGED		(1 << 3)
 #define CACHEID_VIPT_I_ALIASING		(1 << 4)
+#define CACHEID_PIPT			(1 << 5)
 
 extern unsigned int cacheid;
 
@@ -16,6 +17,7 @@
 #define cache_is_vipt_aliasing()	cacheid_is(CACHEID_VIPT_ALIASING)
 #define icache_is_vivt_asid_tagged()	cacheid_is(CACHEID_ASID_TAGGED)
 #define icache_is_vipt_aliasing()	cacheid_is(CACHEID_VIPT_I_ALIASING)
+#define icache_is_pipt()		cacheid_is(CACHEID_PIPT)
 
 /*
  * __LINUX_ARM_ARCH__ is the minimum supported CPU architecture
@@ -26,7 +28,8 @@
 #if __LINUX_ARM_ARCH__ >= 7
 #define __CACHEID_ARCH_MIN	(CACHEID_VIPT_NONALIASING |\
 				 CACHEID_ASID_TAGGED |\
-				 CACHEID_VIPT_I_ALIASING)
+				 CACHEID_VIPT_I_ALIASING |\
+				 CACHEID_PIPT)
 #elif __LINUX_ARM_ARCH__ >= 6
 #define	__CACHEID_ARCH_MIN	(~CACHEID_VIVT)
 #else
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/cputime.h linux-libre-3.2-gnu/arch/arm/include/asm/cputime.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/cputime.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/cputime.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __ARM_CPUTIME_H
-#define __ARM_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __ARM_CPUTIME_H */
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/cputype.h linux-libre-3.2-gnu/arch/arm/include/asm/cputype.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/cputype.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/cputype.h	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 #define CPUID_CACHETYPE	1
 #define CPUID_TCM	2
 #define CPUID_TLBTYPE	3
+#define CPUID_MPIDR	5
 
 #define CPUID_EXT_PFR0	"c1, 0"
 #define CPUID_EXT_PFR1	"c1, 1"
@@ -70,6 +71,11 @@
 	return read_cpuid(CPUID_TCM);
 }
 
+static inline unsigned int __attribute_const__ read_cpuid_mpidr(void)
+{
+	return read_cpuid(CPUID_MPIDR);
+}
+
 /*
  * Intel's XScale3 core supports some v6 features (supersections, L2)
  * but advertises itself as v5 as it does not support the v6 ISA.  For
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/device.h linux-libre-3.2-gnu/arch/arm/include/asm/device.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/device.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/device.h	2012-01-04 18:55:44.000000000 -0500
@@ -10,9 +10,17 @@
 #ifdef CONFIG_DMABOUNCE
 	struct dmabounce_device_info *dmabounce;
 #endif
+#ifdef CONFIG_IOMMU_API
+	void *iommu; /* private IOMMU data */
+#endif
 };
 
+struct omap_device;
+
 struct pdev_archdata {
+#ifdef CONFIG_ARCH_OMAP
+	struct omap_device *od;
+#endif
 };
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/dma.h linux-libre-3.2-gnu/arch/arm/include/asm/dma.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -34,18 +34,18 @@
 #define DMA_MODE_CASCADE 0xc0
 #define DMA_AUTOINIT	 0x10
 
-extern spinlock_t  dma_spin_lock;
+extern raw_spinlock_t  dma_spin_lock;
 
 static inline unsigned long claim_dma_lock(void)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&dma_spin_lock, flags);
+	raw_spin_lock_irqsave(&dma_spin_lock, flags);
 	return flags;
 }
 
 static inline void release_dma_lock(unsigned long flags)
 {
-	spin_unlock_irqrestore(&dma_spin_lock, flags);
+	raw_spin_unlock_irqrestore(&dma_spin_lock, flags);
 }
 
 /* Clear the 'DMA Pointer Flip Flop'.
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/dma-mapping.h linux-libre-3.2-gnu/arch/arm/include/asm/dma-mapping.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/dma-mapping.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/dma-mapping.h	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,7 @@
 
 static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
 {
-	return (void *)__bus_to_virt(addr);
+	return (void *)__bus_to_virt((unsigned long)addr);
 }
 
 static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
@@ -205,6 +205,13 @@
 int dma_mmap_writecombine(struct device *, struct vm_area_struct *,
 		void *, dma_addr_t, size_t);
 
+/*
+ * This can be called during boot to increase the size of the consistent
+ * DMA region above it's default value of 2MB. It must be called before the
+ * memory allocator is initialised, i.e. before any core_initcall.
+ */
+extern void __init init_consistent_dma_size(unsigned long size);
+
 
 #ifdef CONFIG_DMABOUNCE
 /*
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/ecard.h linux-libre-3.2-gnu/arch/arm/include/asm/ecard.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/ecard.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/ecard.h	2012-01-04 18:55:44.000000000 -0500
@@ -161,7 +161,6 @@
 
 	/* Private internal data */
 	const char		*card_desc;	/* Card description		*/
-	CONST unsigned int	podaddr;	/* Base Linux address for card	*/
 	CONST loader_t		loader;		/* loader program */
 	u64			dma_mask;
 };
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/emergency-restart.h linux-libre-3.2-gnu/arch/arm/include/asm/emergency-restart.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/emergency-restart.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/emergency-restart.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/entry-macro-multi.S linux-libre-3.2-gnu/arch/arm/include/asm/entry-macro-multi.S
--- linux-libre-3.1-gnu/arch/arm/include/asm/entry-macro-multi.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/entry-macro-multi.S	2012-01-04 18:55:44.000000000 -0500
@@ -25,13 +25,6 @@
 	movne	r1, sp
 	adrne	lr, BSYM(1b)
 	bne	do_IPI
-
-#ifdef CONFIG_LOCAL_TIMERS
-	test_for_ltirq r0, r2, r6, lr
-	movne	r0, sp
-	adrne	lr, BSYM(1b)
-	bne	do_local_timer
-#endif
 #endif
 9997:
 	.endm
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/errno.h linux-libre-3.2-gnu/arch/arm/include/asm/errno.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/errno.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/errno.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ARM_ERRNO_H
-#define _ARM_ERRNO_H
-
-#include <asm-generic/errno.h>
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/exception.h linux-libre-3.2-gnu/arch/arm/include/asm/exception.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/exception.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/include/asm/exception.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+/*
+ * Annotations for marking C functions as exception handlers.
+ *
+ * These should only be used for C functions that are called from the low
+ * level exception entry code and not any intervening C code.
+ */
+#ifndef __ASM_ARM_EXCEPTION_H
+#define __ASM_ARM_EXCEPTION_H
+
+#include <linux/ftrace.h>
+
+#define __exception	__attribute__((section(".exception.text")))
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+#define __exception_irq_entry	__irq_entry
+#else
+#define __exception_irq_entry	__exception
+#endif
+
+#endif /* __ASM_ARM_EXCEPTION_H */
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/gpio.h linux-libre-3.2-gnu/arch/arm/include/asm/gpio.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -4,4 +4,23 @@
 /* not all ARM platforms necessarily support this API ... */
 #include <mach/gpio.h>
 
+#ifndef __ARM_GPIOLIB_COMPLEX
+/* Note: this may rely upon the value of ARCH_NR_GPIOS set in mach/gpio.h */
+#include <asm-generic/gpio.h>
+
+/* The trivial gpiolib dispatchers */
+#define gpio_get_value  __gpio_get_value
+#define gpio_set_value  __gpio_set_value
+#define gpio_cansleep   __gpio_cansleep
+#endif
+
+/*
+ * Provide a default gpio_to_irq() which should satisfy every case.
+ * However, some platforms want to do this differently, so allow them
+ * to override it.
+ */
+#ifndef gpio_to_irq
+#define gpio_to_irq	__gpio_to_irq
+#endif
+
 #endif /* _ARCH_ARM_GPIO_H */
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/hardirq.h linux-libre-3.2-gnu/arch/arm/include/asm/hardirq.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/hardirq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/hardirq.h	2012-01-04 18:55:44.000000000 -0500
@@ -9,9 +9,6 @@
 
 typedef struct {
 	unsigned int __softirq_pending;
-#ifdef CONFIG_LOCAL_TIMERS
-	unsigned int local_timer_irqs;
-#endif
 #ifdef CONFIG_SMP
 	unsigned int ipi_irqs[NR_IPI];
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/hardware/cache-l2x0.h linux-libre-3.2-gnu/arch/arm/include/asm/hardware/cache-l2x0.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/hardware/cache-l2x0.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/hardware/cache-l2x0.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,8 @@
 #ifndef __ASM_ARM_HARDWARE_L2X0_H
 #define __ASM_ARM_HARDWARE_L2X0_H
 
+#include <linux/errno.h>
+
 #define L2X0_CACHE_ID			0x000
 #define L2X0_CACHE_TYPE			0x004
 #define L2X0_CTRL			0x100
@@ -52,6 +54,8 @@
 #define L2X0_LOCKDOWN_WAY_D_BASE	0x900
 #define L2X0_LOCKDOWN_WAY_I_BASE	0x904
 #define L2X0_LOCKDOWN_STRIDE		0x08
+#define L2X0_ADDR_FILTER_START		0xC00
+#define L2X0_ADDR_FILTER_END		0xC04
 #define L2X0_TEST_OPERATION		0xF00
 #define L2X0_LINE_DATA			0xF10
 #define L2X0_LINE_TAG			0xF30
@@ -65,8 +69,23 @@
 #define L2X0_CACHE_ID_PART_MASK		(0xf << 6)
 #define L2X0_CACHE_ID_PART_L210		(1 << 6)
 #define L2X0_CACHE_ID_PART_L310		(3 << 6)
+#define L2X0_CACHE_ID_RTL_MASK          0x3f
+#define L2X0_CACHE_ID_RTL_R0P0          0x0
+#define L2X0_CACHE_ID_RTL_R1P0          0x2
+#define L2X0_CACHE_ID_RTL_R2P0          0x4
+#define L2X0_CACHE_ID_RTL_R3P0          0x5
+#define L2X0_CACHE_ID_RTL_R3P1          0x6
+#define L2X0_CACHE_ID_RTL_R3P2          0x8
 
 #define L2X0_AUX_CTRL_MASK			0xc0000fff
+#define L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT	0
+#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK	0x7
+#define L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT	3
+#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK	(0x7 << 3)
+#define L2X0_AUX_CTRL_TAG_LATENCY_SHIFT		6
+#define L2X0_AUX_CTRL_TAG_LATENCY_MASK		(0x7 << 6)
+#define L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT	9
+#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK	(0x7 << 9)
 #define L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT	16
 #define L2X0_AUX_CTRL_WAY_SIZE_SHIFT		17
 #define L2X0_AUX_CTRL_WAY_SIZE_MASK		(0x7 << 17)
@@ -77,8 +96,40 @@
 #define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT	29
 #define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT		30
 
+#define L2X0_LATENCY_CTRL_SETUP_SHIFT	0
+#define L2X0_LATENCY_CTRL_RD_SHIFT	4
+#define L2X0_LATENCY_CTRL_WR_SHIFT	8
+
+#define L2X0_ADDR_FILTER_EN		1
+
 #ifndef __ASSEMBLY__
 extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
+#if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_OF)
+extern int l2x0_of_init(__u32 aux_val, __u32 aux_mask);
+#else
+static inline int l2x0_of_init(__u32 aux_val, __u32 aux_mask)
+{
+	return -ENODEV;
+}
 #endif
 
+struct l2x0_regs {
+	unsigned long phy_base;
+	unsigned long aux_ctrl;
+	/*
+	 * Whether the following registers need to be saved/restored
+	 * depends on platform
+	 */
+	unsigned long tag_latency;
+	unsigned long data_latency;
+	unsigned long filter_start;
+	unsigned long filter_end;
+	unsigned long prefetch_ctrl;
+	unsigned long pwr_ctrl;
+};
+
+extern struct l2x0_regs l2x0_saved_regs;
+
+#endif /* __ASSEMBLY__ */
+
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/hardware/entry-macro-gic.S linux-libre-3.2-gnu/arch/arm/include/asm/hardware/entry-macro-gic.S
--- linux-libre-3.1-gnu/arch/arm/include/asm/hardware/entry-macro-gic.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/hardware/entry-macro-gic.S	2012-01-04 18:55:44.000000000 -0500
@@ -22,15 +22,11 @@
  * 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.
+ * 16-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).
@@ -43,7 +39,7 @@
 
 	ldr	\tmp, =1021
 	bic     \irqnr, \irqstat, #0x1c00
-	cmp     \irqnr, #29
+	cmp     \irqnr, #15
 	cmpcc	\irqnr, \irqnr
 	cmpne	\irqnr, \tmp
 	cmpcs	\irqnr, \irqnr
@@ -62,14 +58,3 @@
 	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-3.1-gnu/arch/arm/include/asm/hardware/gic.h linux-libre-3.2-gnu/arch/arm/include/asm/hardware/gic.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/hardware/gic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/hardware/gic.h	2012-01-04 18:55:44.000000000 -0500
@@ -33,19 +33,32 @@
 #define GIC_DIST_SOFTINT		0xf00
 
 #ifndef __ASSEMBLY__
+#include <linux/irqdomain.h>
+struct device_node;
+
 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_init(unsigned int, int, void __iomem *, void __iomem *);
+int gic_of_init(struct device_node *node, struct device_node *parent);
 void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
-void gic_enable_ppi(unsigned int);
 
 struct gic_chip_data {
-	unsigned int irq_offset;
 	void __iomem *dist_base;
 	void __iomem *cpu_base;
+#ifdef CONFIG_CPU_PM
+	u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
+	u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
+	u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
+	u32 __percpu *saved_ppi_enable;
+	u32 __percpu *saved_ppi_conf;
+#endif
+#ifdef CONFIG_IRQ_DOMAIN
+	struct irq_domain domain;
+#endif
+	unsigned int gic_irqs;
 };
 #endif
 
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/hardware/iop3xx-gpio.h linux-libre-3.2-gnu/arch/arm/include/asm/hardware/iop3xx-gpio.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/hardware/iop3xx-gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/hardware/iop3xx-gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,8 @@
 #include <mach/hardware.h>
 #include <asm-generic/gpio.h>
 
+#define __ARM_GPIOLIB_COMPLEX
+
 #define IOP3XX_N_GPIOS	8
 
 static inline int gpio_get_value(unsigned gpio)
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/hardware/it8152.h linux-libre-3.2-gnu/arch/arm/include/asm/hardware/it8152.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/hardware/it8152.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/hardware/it8152.h	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
 
 #ifndef __ASM_HARDWARE_IT8152_H
 #define __ASM_HARDWARE_IT8152_H
-extern unsigned long it8152_base_address;
+extern void __iomem *it8152_base_address;
 
 #define IT8152_IO_BASE			(it8152_base_address + 0x03e00000)
 #define IT8152_CFGREG_BASE		(it8152_base_address + 0x03f00000)
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/hardware/pl080.h linux-libre-3.2-gnu/arch/arm/include/asm/hardware/pl080.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/hardware/pl080.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/hardware/pl080.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,9 @@
  * OneNAND features.
 */
 
+#ifndef ASM_PL080_H
+#define ASM_PL080_H
+
 #define PL080_INT_STATUS			(0x00)
 #define PL080_TC_STATUS				(0x04)
 #define PL080_TC_CLEAR				(0x08)
@@ -138,3 +141,4 @@
 	u32	control1;
 };
 
+#endif /* ASM_PL080_H */
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/hw_breakpoint.h linux-libre-3.2-gnu/arch/arm/include/asm/hw_breakpoint.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/hw_breakpoint.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/hw_breakpoint.h	2012-01-04 18:55:44.000000000 -0500
@@ -50,6 +50,7 @@
 #define ARM_DEBUG_ARCH_V6_1	2
 #define ARM_DEBUG_ARCH_V7_ECP14	3
 #define ARM_DEBUG_ARCH_V7_MM	4
+#define ARM_DEBUG_ARCH_V7_1	5
 
 /* Breakpoint */
 #define ARM_BREAKPOINT_EXECUTE	0
@@ -57,6 +58,7 @@
 /* Watchpoints */
 #define ARM_BREAKPOINT_LOAD	1
 #define ARM_BREAKPOINT_STORE	2
+#define ARM_FSR_ACCESS_MASK	(1 << 11)
 
 /* Privilege Levels */
 #define ARM_BREAKPOINT_PRIV	1
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/ioctl.h linux-libre-3.2-gnu/arch/arm/include/asm/ioctl.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/ioctl.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/ioctl.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/io.h linux-libre-3.2-gnu/arch/arm/include/asm/io.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -80,6 +80,7 @@
 
 extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int);
 extern void __iomem *__arm_ioremap(unsigned long, size_t, unsigned int);
+extern void __iomem *__arm_ioremap_exec(unsigned long, size_t, bool cached);
 extern void __iounmap(volatile void __iomem *addr);
 
 /*
@@ -110,6 +111,27 @@
 #include <mach/io.h>
 
 /*
+ * This is the limit of PC card/PCI/ISA IO space, which is by default
+ * 64K if we have PC card, PCI or ISA support.  Otherwise, default to
+ * zero to prevent ISA/PCI drivers claiming IO space (and potentially
+ * oopsing.)
+ *
+ * Only set this larger if you really need inb() et.al. to operate over
+ * a larger address space.  Note that SOC_COMMON ioremaps each sockets
+ * IO space area, and so inb() et.al. must be defined to operate as per
+ * readb() et.al. on such platforms.
+ */
+#ifndef IO_SPACE_LIMIT
+#if defined(CONFIG_PCMCIA_SOC_COMMON) || defined(CONFIG_PCMCIA_SOC_COMMON_MODULE)
+#define IO_SPACE_LIMIT ((resource_size_t)0xffffffff)
+#elif defined(CONFIG_PCI) || defined(CONFIG_ISA) || defined(CONFIG_PCCARD)
+#define IO_SPACE_LIMIT ((resource_size_t)0xffff)
+#else
+#define IO_SPACE_LIMIT ((resource_size_t)0)
+#endif
+#endif
+
+/*
  *  IO port access primitives
  *  -------------------------
  *
@@ -189,11 +211,11 @@
  * IO port primitives for more information.
  */
 #ifdef __mem_pci
-#define readb_relaxed(c) ({ u8  __v = __raw_readb(__mem_pci(c)); __v; })
-#define readw_relaxed(c) ({ u16 __v = le16_to_cpu((__force __le16) \
-					__raw_readw(__mem_pci(c))); __v; })
-#define readl_relaxed(c) ({ u32 __v = le32_to_cpu((__force __le32) \
-					__raw_readl(__mem_pci(c))); __v; })
+#define readb_relaxed(c) ({ u8  __r = __raw_readb(__mem_pci(c)); __r; })
+#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \
+					__raw_readw(__mem_pci(c))); __r; })
+#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
+					__raw_readl(__mem_pci(c))); __r; })
 
 #define writeb_relaxed(v,c)	((void)__raw_writeb(v,__mem_pci(c)))
 #define writew_relaxed(v,c)	((void)__raw_writew((__force u16) \
@@ -238,7 +260,7 @@
  * ioremap and friends.
  *
  * ioremap takes a PCI memory address, as specified in
- * Documentation/IO-mapping.txt.
+ * Documentation/io-mapping.txt.
  *
  */
 #ifndef __arch_ioremap
@@ -260,10 +282,16 @@
 #define ioread16(p)	({ unsigned int __v = le16_to_cpu((__force __le16)__raw_readw(p)); __iormb(); __v; })
 #define ioread32(p)	({ unsigned int __v = le32_to_cpu((__force __le32)__raw_readl(p)); __iormb(); __v; })
 
+#define ioread16be(p)	({ unsigned int __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; })
+#define ioread32be(p)	({ unsigned int __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; })
+
 #define iowrite8(v,p)	({ __iowmb(); (void)__raw_writeb(v, p); })
 #define iowrite16(v,p)	({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_le16(v), p); })
 #define iowrite32(v,p)	({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_le32(v), p); })
 
+#define iowrite16be(v,p) ({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_be16(v), p); })
+#define iowrite32be(v,p) ({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_be32(v), p); })
+
 #define ioread8_rep(p,d,c)	__raw_readsb(p,d,c)
 #define ioread16_rep(p,d,c)	__raw_readsw(p,d,c)
 #define ioread32_rep(p,d,c)	__raw_readsl(p,d,c)
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/irq_regs.h linux-libre-3.2-gnu/arch/arm/include/asm/irq_regs.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/irq_regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/irq_regs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/Kbuild linux-libre-3.2-gnu/arch/arm/include/asm/Kbuild
--- linux-libre-3.1-gnu/arch/arm/include/asm/Kbuild	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/Kbuild	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,20 @@
 include include/asm-generic/Kbuild.asm
 
 header-y += hwcap.h
+
+generic-y += auxvec.h
+generic-y += bitsperlong.h
+generic-y += cputime.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += ioctl.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += local.h
+generic-y += local64.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += resource.h
+generic-y += sections.h
+generic-y += siginfo.h
+generic-y += sizes.h
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/kdebug.h linux-libre-3.2-gnu/arch/arm/include/asm/kdebug.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/kdebug.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/kdebug.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/local64.h linux-libre-3.2-gnu/arch/arm/include/asm/local64.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/local64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/local64.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/local.h linux-libre-3.2-gnu/arch/arm/include/asm/local.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/local.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/local.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/local.h>
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/localtimer.h linux-libre-3.2-gnu/arch/arm/include/asm/localtimer.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/localtimer.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/localtimer.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #define __ASM_ARM_LOCALTIMER_H
 
 #include <linux/errno.h>
+#include <linux/interrupt.h>
 
 struct clock_event_device;
 
@@ -19,27 +20,20 @@
  */
 void percpu_timer_setup(void);
 
-/*
- * Called from assembly, this is the local timer IRQ handler
- */
-asmlinkage void do_local_timer(struct pt_regs *);
-
-
 #ifdef CONFIG_LOCAL_TIMERS
 
 #ifdef CONFIG_HAVE_ARM_TWD
 
 #include "smp_twd.h"
 
-#define local_timer_ack()	twd_timer_ack()
+#define local_timer_stop(c)	twd_timer_stop((c))
 
 #else
 
 /*
- * Platform provides this to acknowledge a local timer IRQ.
- * Returns true if the local timer IRQ is to be processed.
+ * Stop the local timer
  */
-int local_timer_ack(void);
+void local_timer_stop(struct clock_event_device *);
 
 #endif
 
@@ -54,6 +48,10 @@
 {
 	return -ENXIO;
 }
+
+static inline void local_timer_stop(struct clock_event_device *evt)
+{
+}
 #endif
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/mach/arch.h linux-libre-3.2-gnu/arch/arm/include/asm/mach/arch.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/mach/arch.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/mach/arch.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,11 +13,12 @@
 struct tag;
 struct meminfo;
 struct sys_timer;
+struct pt_regs;
 
 struct machine_desc {
 	unsigned int		nr;		/* architecture number	*/
 	const char		*name;		/* architecture name	*/
-	unsigned long		boot_params;	/* tagged list		*/
+	unsigned long		atag_offset;	/* tagged list (relative) */
 	const char		**dt_compat;	/* array of device tree
 						 * 'compatible' strings	*/
 
@@ -34,8 +35,7 @@
 	unsigned int		reserve_lp1 :1;	/* never has lp1	*/
 	unsigned int		reserve_lp2 :1;	/* never has lp2	*/
 	unsigned int		soft_reboot :1;	/* soft reboot		*/
-	void			(*fixup)(struct machine_desc *,
-					 struct tag *, char **,
+	void			(*fixup)(struct tag *, char **,
 					 struct meminfo *);
 	void			(*reserve)(void);/* reserve mem blocks	*/
 	void			(*map_io)(void);/* IO mapping function	*/
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/mach/map.h linux-libre-3.2-gnu/arch/arm/include/asm/mach/map.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/mach/map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/mach/map.h	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #define MT_MEMORY_NONCACHED	11
 #define MT_MEMORY_DTCM		12
 #define MT_MEMORY_ITCM		13
+#define MT_MEMORY_SO		14
 
 #ifdef CONFIG_MMU
 extern void iotable_init(struct map_desc *, int);
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/memory.h linux-libre-3.2-gnu/arch/arm/include/asm/memory.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/memory.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,9 +16,12 @@
 #include <linux/compiler.h>
 #include <linux/const.h>
 #include <linux/types.h>
-#include <mach/memory.h>
 #include <asm/sizes.h>
 
+#ifdef CONFIG_NEED_MACH_MEMORY_H
+#include <mach/memory.h>
+#endif
+
 /*
  * Allow for constants defined here to be used from assembly code
  * by prepending the UL suffix only with actual C code compilation.
@@ -77,16 +80,7 @@
  */
 #define IOREMAP_MAX_ORDER	24
 
-/*
- * Size of DMA-consistent memory region.  Must be multiple of 2M,
- * between 2MB and 14MB inclusive.
- */
-#ifndef CONSISTENT_DMA_SIZE
-#define CONSISTENT_DMA_SIZE 	SZ_2M
-#endif
-
 #define CONSISTENT_END		(0xffe00000UL)
-#define CONSISTENT_BASE		(CONSISTENT_END - CONSISTENT_DMA_SIZE)
 
 #else /* CONFIG_MMU */
 
@@ -160,7 +154,6 @@
  * 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
@@ -178,9 +171,6 @@
 {
 	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;
 }
 
@@ -188,9 +178,6 @@
 {
 	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
@@ -200,7 +187,11 @@
 #endif
 
 #ifndef PHYS_OFFSET
+#ifdef PLAT_PHYS_OFFSET
 #define PHYS_OFFSET	PLAT_PHYS_OFFSET
+#else
+#define PHYS_OFFSET	UL(CONFIG_PHYS_OFFSET)
+#endif
 #endif
 
 /*
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/mmu.h linux-libre-3.2-gnu/arch/arm/include/asm/mmu.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/mmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/mmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 typedef struct {
 #ifdef CONFIG_CPU_HAS_ASID
 	unsigned int id;
-	spinlock_t id_lock;
+	raw_spinlock_t id_lock;
 #endif
 	unsigned int kvm_seq;
 } mm_context_t;
@@ -16,7 +16,7 @@
 
 /* init_mm.context.id_lock should be initialized. */
 #define INIT_MM_CONTEXT(name)                                                 \
-	.context.id_lock    = __SPIN_LOCK_UNLOCKED(name.context.id_lock),
+	.context.id_lock    = __RAW_SPIN_LOCK_UNLOCKED(name.context.id_lock),
 #else
 #define ASID(mm)	(0)
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/module.h linux-libre-3.2-gnu/arch/arm/include/asm/module.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/module.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/module.h	2012-01-04 18:55:44.000000000 -0500
@@ -31,11 +31,7 @@
 
 /* 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
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/outercache.h linux-libre-3.2-gnu/arch/arm/include/asm/outercache.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/outercache.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/outercache.h	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 	void (*sync)(void);
 #endif
 	void (*set_debug)(unsigned long);
+	void (*resume)(void);
 };
 
 #ifdef CONFIG_OUTER_CACHE
@@ -74,6 +75,12 @@
 		outer_cache.disable();
 }
 
+static inline void outer_resume(void)
+{
+	if (outer_cache.resume)
+		outer_cache.resume();
+}
+
 #else
 
 static inline void outer_inv_range(phys_addr_t start, phys_addr_t end)
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/page.h linux-libre-3.2-gnu/arch/arm/include/asm/page.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/page.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/page.h	2012-01-04 18:55:44.000000000 -0500
@@ -151,47 +151,7 @@
 #define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
 extern void copy_page(void *to, const void *from);
 
-typedef unsigned long pteval_t;
-
-#undef STRICT_MM_TYPECHECKS
-
-#ifdef STRICT_MM_TYPECHECKS
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { pteval_t pte; } pte_t;
-typedef struct { unsigned long pmd; } pmd_t;
-typedef struct { unsigned long pgd[2]; } pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-
-#define pte_val(x)      ((x).pte)
-#define pmd_val(x)      ((x).pmd)
-#define pgd_val(x)	((x).pgd[0])
-#define pgprot_val(x)   ((x).pgprot)
-
-#define __pte(x)        ((pte_t) { (x) } )
-#define __pmd(x)        ((pmd_t) { (x) } )
-#define __pgprot(x)     ((pgprot_t) { (x) } )
-
-#else
-/*
- * .. while these make it easier on the compiler
- */
-typedef pteval_t pte_t;
-typedef unsigned long pmd_t;
-typedef unsigned long pgd_t[2];
-typedef unsigned long pgprot_t;
-
-#define pte_val(x)      (x)
-#define pmd_val(x)      (x)
-#define pgd_val(x)	((x)[0])
-#define pgprot_val(x)   (x)
-
-#define __pte(x)        (x)
-#define __pmd(x)        (x)
-#define __pgprot(x)     (x)
-
-#endif /* STRICT_MM_TYPECHECKS */
+#include <asm/pgtable-2level-types.h>
 
 #endif /* CONFIG_MMU */
 
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/percpu.h linux-libre-3.2-gnu/arch/arm/include/asm/percpu.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/percpu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/percpu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __ARM_PERCPU
-#define __ARM_PERCPU
-
-#include <asm-generic/percpu.h>
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/pgalloc.h linux-libre-3.2-gnu/arch/arm/include/asm/pgalloc.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/pgalloc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/pgalloc.h	2012-01-04 18:55:44.000000000 -0500
@@ -105,9 +105,9 @@
 }
 
 static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte,
-	unsigned long prot)
+				  pmdval_t prot)
 {
-	unsigned long pmdval = (pte + PTE_HWTABLE_OFF) | prot;
+	pmdval_t pmdval = (pte + PTE_HWTABLE_OFF) | prot;
 	pmdp[0] = __pmd(pmdval);
 	pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
 	flush_pmd_entry(pmdp);
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/pgtable-2level.h linux-libre-3.2-gnu/arch/arm/include/asm/pgtable-2level.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/pgtable-2level.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/include/asm/pgtable-2level.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,143 @@
+/*
+ *  arch/arm/include/asm/pgtable-2level.h
+ *
+ *  Copyright (C) 1995-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_PGTABLE_2LEVEL_H
+#define _ASM_PGTABLE_2LEVEL_H
+
+/*
+ * Hardware-wise, we have a two level page table structure, where the first
+ * level has 4096 entries, and the second level has 256 entries.  Each entry
+ * is one 32-bit word.  Most of the bits in the second level entry are used
+ * by hardware, and there aren't any "accessed" and "dirty" bits.
+ *
+ * Linux on the other hand has a three level page table structure, which can
+ * be wrapped to fit a two level page table structure easily - using the PGD
+ * and PTE only.  However, Linux also expects one "PTE" table per page, and
+ * at least a "dirty" bit.
+ *
+ * Therefore, we tweak the implementation slightly - we tell Linux that we
+ * have 2048 entries in the first level, each of which is 8 bytes (iow, two
+ * hardware pointers to the second level.)  The second level contains two
+ * hardware PTE tables arranged contiguously, preceded by Linux versions
+ * which contain the state information Linux needs.  We, therefore, end up
+ * with 512 entries in the "PTE" level.
+ *
+ * This leads to the page tables having the following layout:
+ *
+ *    pgd             pte
+ * |        |
+ * +--------+
+ * |        |       +------------+ +0
+ * +- - - - +       | Linux pt 0 |
+ * |        |       +------------+ +1024
+ * +--------+ +0    | Linux pt 1 |
+ * |        |-----> +------------+ +2048
+ * +- - - - + +4    |  h/w pt 0  |
+ * |        |-----> +------------+ +3072
+ * +--------+ +8    |  h/w pt 1  |
+ * |        |       +------------+ +4096
+ *
+ * See L_PTE_xxx below for definitions of bits in the "Linux pt", and
+ * PTE_xxx for definitions of bits appearing in the "h/w pt".
+ *
+ * PMD_xxx definitions refer to bits in the first level page table.
+ *
+ * The "dirty" bit is emulated by only granting hardware write permission
+ * iff the page is marked "writable" and "dirty" in the Linux PTE.  This
+ * means that a write to a clean page will cause a permission fault, and
+ * the Linux MM layer will mark the page dirty via handle_pte_fault().
+ * For the hardware to notice the permission change, the TLB entry must
+ * be flushed, and ptep_set_access_flags() does that for us.
+ *
+ * The "accessed" or "young" bit is emulated by a similar method; we only
+ * allow accesses to the page if the "young" bit is set.  Accesses to the
+ * page will cause a fault, and handle_pte_fault() will set the young bit
+ * for us as long as the page is marked present in the corresponding Linux
+ * PTE entry.  Again, ptep_set_access_flags() will ensure that the TLB is
+ * up to date.
+ *
+ * However, when the "young" bit is cleared, we deny access to the page
+ * by clearing the hardware PTE.  Currently Linux does not flush the TLB
+ * for us in this case, which means the TLB will retain the transation
+ * until either the TLB entry is evicted under pressure, or a context
+ * switch which changes the user space mapping occurs.
+ */
+#define PTRS_PER_PTE		512
+#define PTRS_PER_PMD		1
+#define PTRS_PER_PGD		2048
+
+#define PTE_HWTABLE_PTRS	(PTRS_PER_PTE)
+#define PTE_HWTABLE_OFF		(PTE_HWTABLE_PTRS * sizeof(pte_t))
+#define PTE_HWTABLE_SIZE	(PTRS_PER_PTE * sizeof(u32))
+
+/*
+ * PMD_SHIFT determines the size of the area a second-level page table can map
+ * PGDIR_SHIFT determines what a third-level page table entry can map
+ */
+#define PMD_SHIFT		21
+#define PGDIR_SHIFT		21
+
+#define PMD_SIZE		(1UL << PMD_SHIFT)
+#define PMD_MASK		(~(PMD_SIZE-1))
+#define PGDIR_SIZE		(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK		(~(PGDIR_SIZE-1))
+
+/*
+ * section address mask and size definitions.
+ */
+#define SECTION_SHIFT		20
+#define SECTION_SIZE		(1UL << SECTION_SHIFT)
+#define SECTION_MASK		(~(SECTION_SIZE-1))
+
+/*
+ * ARMv6 supersection address mask and size definitions.
+ */
+#define SUPERSECTION_SHIFT	24
+#define SUPERSECTION_SIZE	(1UL << SUPERSECTION_SHIFT)
+#define SUPERSECTION_MASK	(~(SUPERSECTION_SIZE-1))
+
+#define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
+
+/*
+ * "Linux" PTE definitions.
+ *
+ * We keep two sets of PTEs - the hardware and the linux version.
+ * This allows greater flexibility in the way we map the Linux bits
+ * onto the hardware tables, and allows us to have YOUNG and DIRTY
+ * bits.
+ *
+ * The PTE table pointer refers to the hardware entries; the "Linux"
+ * entries are stored 1024 bytes below.
+ */
+#define L_PTE_PRESENT		(_AT(pteval_t, 1) << 0)
+#define L_PTE_YOUNG		(_AT(pteval_t, 1) << 1)
+#define L_PTE_FILE		(_AT(pteval_t, 1) << 2)	/* only when !PRESENT */
+#define L_PTE_DIRTY		(_AT(pteval_t, 1) << 6)
+#define L_PTE_RDONLY		(_AT(pteval_t, 1) << 7)
+#define L_PTE_USER		(_AT(pteval_t, 1) << 8)
+#define L_PTE_XN		(_AT(pteval_t, 1) << 9)
+#define L_PTE_SHARED		(_AT(pteval_t, 1) << 10)	/* shared(v6), coherent(xsc3) */
+
+/*
+ * These are the memory types, defined to be compatible with
+ * pre-ARMv6 CPUs cacheable and bufferable bits:   XXCB
+ */
+#define L_PTE_MT_UNCACHED	(_AT(pteval_t, 0x00) << 2)	/* 0000 */
+#define L_PTE_MT_BUFFERABLE	(_AT(pteval_t, 0x01) << 2)	/* 0001 */
+#define L_PTE_MT_WRITETHROUGH	(_AT(pteval_t, 0x02) << 2)	/* 0010 */
+#define L_PTE_MT_WRITEBACK	(_AT(pteval_t, 0x03) << 2)	/* 0011 */
+#define L_PTE_MT_MINICACHE	(_AT(pteval_t, 0x06) << 2)	/* 0110 (sa1100, xscale) */
+#define L_PTE_MT_WRITEALLOC	(_AT(pteval_t, 0x07) << 2)	/* 0111 */
+#define L_PTE_MT_DEV_SHARED	(_AT(pteval_t, 0x04) << 2)	/* 0100 */
+#define L_PTE_MT_DEV_NONSHARED	(_AT(pteval_t, 0x0c) << 2)	/* 1100 */
+#define L_PTE_MT_DEV_WC		(_AT(pteval_t, 0x09) << 2)	/* 1001 */
+#define L_PTE_MT_DEV_CACHED	(_AT(pteval_t, 0x0b) << 2)	/* 1011 */
+#define L_PTE_MT_MASK		(_AT(pteval_t, 0x0f) << 2)
+
+#endif /* _ASM_PGTABLE_2LEVEL_H */
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/pgtable-2level-hwdef.h linux-libre-3.2-gnu/arch/arm/include/asm/pgtable-2level-hwdef.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/pgtable-2level-hwdef.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/include/asm/pgtable-2level-hwdef.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,93 @@
+/*
+ *  arch/arm/include/asm/pgtable-2level-hwdef.h
+ *
+ *  Copyright (C) 1995-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_PGTABLE_2LEVEL_HWDEF_H
+#define _ASM_PGTABLE_2LEVEL_HWDEF_H
+
+/*
+ * Hardware page table definitions.
+ *
+ * + Level 1 descriptor (PMD)
+ *   - common
+ */
+#define PMD_TYPE_MASK		(_AT(pmdval_t, 3) << 0)
+#define PMD_TYPE_FAULT		(_AT(pmdval_t, 0) << 0)
+#define PMD_TYPE_TABLE		(_AT(pmdval_t, 1) << 0)
+#define PMD_TYPE_SECT		(_AT(pmdval_t, 2) << 0)
+#define PMD_BIT4		(_AT(pmdval_t, 1) << 4)
+#define PMD_DOMAIN(x)		(_AT(pmdval_t, (x)) << 5)
+#define PMD_PROTECTION		(_AT(pmdval_t, 1) << 9)		/* v5 */
+/*
+ *   - section
+ */
+#define PMD_SECT_BUFFERABLE	(_AT(pmdval_t, 1) << 2)
+#define PMD_SECT_CACHEABLE	(_AT(pmdval_t, 1) << 3)
+#define PMD_SECT_XN		(_AT(pmdval_t, 1) << 4)		/* v6 */
+#define PMD_SECT_AP_WRITE	(_AT(pmdval_t, 1) << 10)
+#define PMD_SECT_AP_READ	(_AT(pmdval_t, 1) << 11)
+#define PMD_SECT_TEX(x)		(_AT(pmdval_t, (x)) << 12)	/* v5 */
+#define PMD_SECT_APX		(_AT(pmdval_t, 1) << 15)	/* v6 */
+#define PMD_SECT_S		(_AT(pmdval_t, 1) << 16)	/* v6 */
+#define PMD_SECT_nG		(_AT(pmdval_t, 1) << 17)	/* v6 */
+#define PMD_SECT_SUPER		(_AT(pmdval_t, 1) << 18)	/* v6 */
+#define PMD_SECT_AF		(_AT(pmdval_t, 0))
+
+#define PMD_SECT_UNCACHED	(_AT(pmdval_t, 0))
+#define PMD_SECT_BUFFERED	(PMD_SECT_BUFFERABLE)
+#define PMD_SECT_WT		(PMD_SECT_CACHEABLE)
+#define PMD_SECT_WB		(PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
+#define PMD_SECT_MINICACHE	(PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE)
+#define PMD_SECT_WBWA		(PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
+#define PMD_SECT_NONSHARED_DEV	(PMD_SECT_TEX(2))
+
+/*
+ *   - coarse table (not used)
+ */
+
+/*
+ * + Level 2 descriptor (PTE)
+ *   - common
+ */
+#define PTE_TYPE_MASK		(_AT(pteval_t, 3) << 0)
+#define PTE_TYPE_FAULT		(_AT(pteval_t, 0) << 0)
+#define PTE_TYPE_LARGE		(_AT(pteval_t, 1) << 0)
+#define PTE_TYPE_SMALL		(_AT(pteval_t, 2) << 0)
+#define PTE_TYPE_EXT		(_AT(pteval_t, 3) << 0)		/* v5 */
+#define PTE_BUFFERABLE		(_AT(pteval_t, 1) << 2)
+#define PTE_CACHEABLE		(_AT(pteval_t, 1) << 3)
+
+/*
+ *   - extended small page/tiny page
+ */
+#define PTE_EXT_XN		(_AT(pteval_t, 1) << 0)		/* v6 */
+#define PTE_EXT_AP_MASK		(_AT(pteval_t, 3) << 4)
+#define PTE_EXT_AP0		(_AT(pteval_t, 1) << 4)
+#define PTE_EXT_AP1		(_AT(pteval_t, 2) << 4)
+#define PTE_EXT_AP_UNO_SRO	(_AT(pteval_t, 0) << 4)
+#define PTE_EXT_AP_UNO_SRW	(PTE_EXT_AP0)
+#define PTE_EXT_AP_URO_SRW	(PTE_EXT_AP1)
+#define PTE_EXT_AP_URW_SRW	(PTE_EXT_AP1|PTE_EXT_AP0)
+#define PTE_EXT_TEX(x)		(_AT(pteval_t, (x)) << 6)	/* v5 */
+#define PTE_EXT_APX		(_AT(pteval_t, 1) << 9)		/* v6 */
+#define PTE_EXT_COHERENT	(_AT(pteval_t, 1) << 9)		/* XScale3 */
+#define PTE_EXT_SHARED		(_AT(pteval_t, 1) << 10)	/* v6 */
+#define PTE_EXT_NG		(_AT(pteval_t, 1) << 11)	/* v6 */
+
+/*
+ *   - small page
+ */
+#define PTE_SMALL_AP_MASK	(_AT(pteval_t, 0xff) << 4)
+#define PTE_SMALL_AP_UNO_SRO	(_AT(pteval_t, 0x00) << 4)
+#define PTE_SMALL_AP_UNO_SRW	(_AT(pteval_t, 0x55) << 4)
+#define PTE_SMALL_AP_URO_SRW	(_AT(pteval_t, 0xaa) << 4)
+#define PTE_SMALL_AP_URW_SRW	(_AT(pteval_t, 0xff) << 4)
+
+#define PHYS_MASK		(~0UL)
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/pgtable-2level-types.h linux-libre-3.2-gnu/arch/arm/include/asm/pgtable-2level-types.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/pgtable-2level-types.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/include/asm/pgtable-2level-types.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,67 @@
+/*
+ * arch/arm/include/asm/pgtable-2level-types.h
+ *
+ * Copyright (C) 1995-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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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_PGTABLE_2LEVEL_TYPES_H
+#define _ASM_PGTABLE_2LEVEL_TYPES_H
+
+#include <asm/types.h>
+
+typedef u32 pteval_t;
+typedef u32 pmdval_t;
+
+#undef STRICT_MM_TYPECHECKS
+
+#ifdef STRICT_MM_TYPECHECKS
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { pteval_t pte; } pte_t;
+typedef struct { pmdval_t pmd; } pmd_t;
+typedef struct { pmdval_t pgd[2]; } pgd_t;
+typedef struct { pteval_t pgprot; } pgprot_t;
+
+#define pte_val(x)      ((x).pte)
+#define pmd_val(x)      ((x).pmd)
+#define pgd_val(x)	((x).pgd[0])
+#define pgprot_val(x)   ((x).pgprot)
+
+#define __pte(x)        ((pte_t) { (x) } )
+#define __pmd(x)        ((pmd_t) { (x) } )
+#define __pgprot(x)     ((pgprot_t) { (x) } )
+
+#else
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef pteval_t pte_t;
+typedef pmdval_t pmd_t;
+typedef pmdval_t pgd_t[2];
+typedef pteval_t pgprot_t;
+
+#define pte_val(x)      (x)
+#define pmd_val(x)      (x)
+#define pgd_val(x)	((x)[0])
+#define pgprot_val(x)   (x)
+
+#define __pte(x)        (x)
+#define __pmd(x)        (x)
+#define __pgprot(x)     (x)
+
+#endif /* STRICT_MM_TYPECHECKS */
+
+#endif	/* _ASM_PGTABLE_2LEVEL_TYPES_H */
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/pgtable.h linux-libre-3.2-gnu/arch/arm/include/asm/pgtable.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/pgtable.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/pgtable.h	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
 #include <mach/vmalloc.h>
 #include <asm/pgtable-hwdef.h>
 
+#include <asm/pgtable-2level.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
@@ -41,79 +43,6 @@
 #define VMALLOC_START		(((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #endif
 
-/*
- * Hardware-wise, we have a two level page table structure, where the first
- * level has 4096 entries, and the second level has 256 entries.  Each entry
- * is one 32-bit word.  Most of the bits in the second level entry are used
- * by hardware, and there aren't any "accessed" and "dirty" bits.
- *
- * Linux on the other hand has a three level page table structure, which can
- * be wrapped to fit a two level page table structure easily - using the PGD
- * and PTE only.  However, Linux also expects one "PTE" table per page, and
- * at least a "dirty" bit.
- *
- * Therefore, we tweak the implementation slightly - we tell Linux that we
- * have 2048 entries in the first level, each of which is 8 bytes (iow, two
- * hardware pointers to the second level.)  The second level contains two
- * hardware PTE tables arranged contiguously, preceded by Linux versions
- * which contain the state information Linux needs.  We, therefore, end up
- * with 512 entries in the "PTE" level.
- *
- * This leads to the page tables having the following layout:
- *
- *    pgd             pte
- * |        |
- * +--------+
- * |        |       +------------+ +0
- * +- - - - +       | Linux pt 0 |
- * |        |       +------------+ +1024
- * +--------+ +0    | Linux pt 1 |
- * |        |-----> +------------+ +2048
- * +- - - - + +4    |  h/w pt 0  |
- * |        |-----> +------------+ +3072
- * +--------+ +8    |  h/w pt 1  |
- * |        |       +------------+ +4096
- *
- * See L_PTE_xxx below for definitions of bits in the "Linux pt", and
- * PTE_xxx for definitions of bits appearing in the "h/w pt".
- *
- * PMD_xxx definitions refer to bits in the first level page table.
- *
- * The "dirty" bit is emulated by only granting hardware write permission
- * iff the page is marked "writable" and "dirty" in the Linux PTE.  This
- * means that a write to a clean page will cause a permission fault, and
- * the Linux MM layer will mark the page dirty via handle_pte_fault().
- * For the hardware to notice the permission change, the TLB entry must
- * be flushed, and ptep_set_access_flags() does that for us.
- *
- * The "accessed" or "young" bit is emulated by a similar method; we only
- * allow accesses to the page if the "young" bit is set.  Accesses to the
- * page will cause a fault, and handle_pte_fault() will set the young bit
- * for us as long as the page is marked present in the corresponding Linux
- * PTE entry.  Again, ptep_set_access_flags() will ensure that the TLB is
- * up to date.
- *
- * However, when the "young" bit is cleared, we deny access to the page
- * by clearing the hardware PTE.  Currently Linux does not flush the TLB
- * for us in this case, which means the TLB will retain the transation
- * until either the TLB entry is evicted under pressure, or a context
- * switch which changes the user space mapping occurs.
- */
-#define PTRS_PER_PTE		512
-#define PTRS_PER_PMD		1
-#define PTRS_PER_PGD		2048
-
-#define PTE_HWTABLE_PTRS	(PTRS_PER_PTE)
-#define PTE_HWTABLE_OFF		(PTE_HWTABLE_PTRS * sizeof(pte_t))
-#define PTE_HWTABLE_SIZE	(PTRS_PER_PTE * sizeof(u32))
-
-/*
- * PMD_SHIFT determines the size of the area a second-level page table can map
- * PGDIR_SHIFT determines what a third-level page table entry can map
- */
-#define PMD_SHIFT		21
-#define PGDIR_SHIFT		21
-
 #define LIBRARY_TEXT_START	0x0c000000
 
 #ifndef __ASSEMBLY__
@@ -124,12 +53,6 @@
 #define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte)
 #define pmd_ERROR(pmd)		__pmd_error(__FILE__, __LINE__, pmd)
 #define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd)
-#endif /* !__ASSEMBLY__ */
-
-#define PMD_SIZE		(1UL << PMD_SHIFT)
-#define PMD_MASK		(~(PMD_SIZE-1))
-#define PGDIR_SIZE		(1UL << PGDIR_SHIFT)
-#define PGDIR_MASK		(~(PGDIR_SIZE-1))
 
 /*
  * This is the lowest virtual address we can permit any user space
@@ -138,60 +61,6 @@
  */
 #define FIRST_USER_ADDRESS	PAGE_SIZE
 
-#define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
-
-/*
- * section address mask and size definitions.
- */
-#define SECTION_SHIFT		20
-#define SECTION_SIZE		(1UL << SECTION_SHIFT)
-#define SECTION_MASK		(~(SECTION_SIZE-1))
-
-/*
- * ARMv6 supersection address mask and size definitions.
- */
-#define SUPERSECTION_SHIFT	24
-#define SUPERSECTION_SIZE	(1UL << SUPERSECTION_SHIFT)
-#define SUPERSECTION_MASK	(~(SUPERSECTION_SIZE-1))
-
-/*
- * "Linux" PTE definitions.
- *
- * We keep two sets of PTEs - the hardware and the linux version.
- * This allows greater flexibility in the way we map the Linux bits
- * onto the hardware tables, and allows us to have YOUNG and DIRTY
- * bits.
- *
- * The PTE table pointer refers to the hardware entries; the "Linux"
- * entries are stored 1024 bytes below.
- */
-#define L_PTE_PRESENT		(_AT(pteval_t, 1) << 0)
-#define L_PTE_YOUNG		(_AT(pteval_t, 1) << 1)
-#define L_PTE_FILE		(_AT(pteval_t, 1) << 2)	/* only when !PRESENT */
-#define L_PTE_DIRTY		(_AT(pteval_t, 1) << 6)
-#define L_PTE_RDONLY		(_AT(pteval_t, 1) << 7)
-#define L_PTE_USER		(_AT(pteval_t, 1) << 8)
-#define L_PTE_XN		(_AT(pteval_t, 1) << 9)
-#define L_PTE_SHARED		(_AT(pteval_t, 1) << 10)	/* shared(v6), coherent(xsc3) */
-
-/*
- * These are the memory types, defined to be compatible with
- * pre-ARMv6 CPUs cacheable and bufferable bits:   XXCB
- */
-#define L_PTE_MT_UNCACHED	(_AT(pteval_t, 0x00) << 2)	/* 0000 */
-#define L_PTE_MT_BUFFERABLE	(_AT(pteval_t, 0x01) << 2)	/* 0001 */
-#define L_PTE_MT_WRITETHROUGH	(_AT(pteval_t, 0x02) << 2)	/* 0010 */
-#define L_PTE_MT_WRITEBACK	(_AT(pteval_t, 0x03) << 2)	/* 0011 */
-#define L_PTE_MT_MINICACHE	(_AT(pteval_t, 0x06) << 2)	/* 0110 (sa1100, xscale) */
-#define L_PTE_MT_WRITEALLOC	(_AT(pteval_t, 0x07) << 2)	/* 0111 */
-#define L_PTE_MT_DEV_SHARED	(_AT(pteval_t, 0x04) << 2)	/* 0100 */
-#define L_PTE_MT_DEV_NONSHARED	(_AT(pteval_t, 0x0c) << 2)	/* 1100 */
-#define L_PTE_MT_DEV_WC		(_AT(pteval_t, 0x09) << 2)	/* 1001 */
-#define L_PTE_MT_DEV_CACHED	(_AT(pteval_t, 0x0b) << 2)	/* 1011 */
-#define L_PTE_MT_MASK		(_AT(pteval_t, 0x0f) << 2)
-
-#ifndef __ASSEMBLY__
-
 /*
  * The pgprot_* and protection_map entries will be fixed up in runtime
  * to include the cachable and bufferable bits based on memory policy,
@@ -232,6 +101,9 @@
 #define pgprot_writecombine(prot) \
 	__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
 
+#define pgprot_stronglyordered(prot) \
+	__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
+
 #ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
 #define pgprot_dmacoherent(prot) \
 	__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE | L_PTE_XN)
@@ -327,10 +199,10 @@
 
 static inline pte_t *pmd_page_vaddr(pmd_t pmd)
 {
-	return __va(pmd_val(pmd) & PAGE_MASK);
+	return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK);
 }
 
-#define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd)))
+#define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
 
 /* we don't need complex calculations here as the pmd is folded into the pgd */
 #define pmd_addr_end(addr,end)	(end)
@@ -351,7 +223,7 @@
 #define pte_offset_map(pmd,addr)	(__pte_map(pmd) + pte_index(addr))
 #define pte_unmap(pte)			__pte_unmap(pte)
 
-#define pte_pfn(pte)		(pte_val(pte) >> PAGE_SHIFT)
+#define pte_pfn(pte)		((pte_val(pte) & PHYS_MASK) >> PAGE_SHIFT)
 #define pfn_pte(pfn,prot)	__pte(__pfn_to_phys(pfn) | pgprot_val(prot))
 
 #define pte_page(pte)		pfn_to_page(pte_pfn(pte))
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/pgtable-hwdef.h linux-libre-3.2-gnu/arch/arm/include/asm/pgtable-hwdef.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/pgtable-hwdef.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/pgtable-hwdef.h	2012-01-04 18:55:44.000000000 -0500
@@ -10,81 +10,6 @@
 #ifndef _ASMARM_PGTABLE_HWDEF_H
 #define _ASMARM_PGTABLE_HWDEF_H
 
-/*
- * Hardware page table definitions.
- *
- * + Level 1 descriptor (PMD)
- *   - common
- */
-#define PMD_TYPE_MASK		(3 << 0)
-#define PMD_TYPE_FAULT		(0 << 0)
-#define PMD_TYPE_TABLE		(1 << 0)
-#define PMD_TYPE_SECT		(2 << 0)
-#define PMD_BIT4		(1 << 4)
-#define PMD_DOMAIN(x)		((x) << 5)
-#define PMD_PROTECTION		(1 << 9)	/* v5 */
-/*
- *   - section
- */
-#define PMD_SECT_BUFFERABLE	(1 << 2)
-#define PMD_SECT_CACHEABLE	(1 << 3)
-#define PMD_SECT_XN		(1 << 4)	/* v6 */
-#define PMD_SECT_AP_WRITE	(1 << 10)
-#define PMD_SECT_AP_READ	(1 << 11)
-#define PMD_SECT_TEX(x)		((x) << 12)	/* v5 */
-#define PMD_SECT_APX		(1 << 15)	/* v6 */
-#define PMD_SECT_S		(1 << 16)	/* v6 */
-#define PMD_SECT_nG		(1 << 17)	/* v6 */
-#define PMD_SECT_SUPER		(1 << 18)	/* v6 */
-
-#define PMD_SECT_UNCACHED	(0)
-#define PMD_SECT_BUFFERED	(PMD_SECT_BUFFERABLE)
-#define PMD_SECT_WT		(PMD_SECT_CACHEABLE)
-#define PMD_SECT_WB		(PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
-#define PMD_SECT_MINICACHE	(PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE)
-#define PMD_SECT_WBWA		(PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
-#define PMD_SECT_NONSHARED_DEV	(PMD_SECT_TEX(2))
-
-/*
- *   - coarse table (not used)
- */
-
-/*
- * + Level 2 descriptor (PTE)
- *   - common
- */
-#define PTE_TYPE_MASK		(3 << 0)
-#define PTE_TYPE_FAULT		(0 << 0)
-#define PTE_TYPE_LARGE		(1 << 0)
-#define PTE_TYPE_SMALL		(2 << 0)
-#define PTE_TYPE_EXT		(3 << 0)	/* v5 */
-#define PTE_BUFFERABLE		(1 << 2)
-#define PTE_CACHEABLE		(1 << 3)
-
-/*
- *   - extended small page/tiny page
- */
-#define PTE_EXT_XN		(1 << 0)	/* v6 */
-#define PTE_EXT_AP_MASK		(3 << 4)
-#define PTE_EXT_AP0		(1 << 4)
-#define PTE_EXT_AP1		(2 << 4)
-#define PTE_EXT_AP_UNO_SRO	(0 << 4)
-#define PTE_EXT_AP_UNO_SRW	(PTE_EXT_AP0)
-#define PTE_EXT_AP_URO_SRW	(PTE_EXT_AP1)
-#define PTE_EXT_AP_URW_SRW	(PTE_EXT_AP1|PTE_EXT_AP0)
-#define PTE_EXT_TEX(x)		((x) << 6)	/* v5 */
-#define PTE_EXT_APX		(1 << 9)	/* v6 */
-#define PTE_EXT_COHERENT	(1 << 9)	/* XScale3 */
-#define PTE_EXT_SHARED		(1 << 10)	/* v6 */
-#define PTE_EXT_NG		(1 << 11)	/* v6 */
-
-/*
- *   - small page
- */
-#define PTE_SMALL_AP_MASK	(0xff << 4)
-#define PTE_SMALL_AP_UNO_SRO	(0x00 << 4)
-#define PTE_SMALL_AP_UNO_SRW	(0x55 << 4)
-#define PTE_SMALL_AP_URO_SRW	(0xaa << 4)
-#define PTE_SMALL_AP_URW_SRW	(0xff << 4)
+#include <asm/pgtable-2level-hwdef.h>
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/pmu.h linux-libre-3.2-gnu/arch/arm/include/asm/pmu.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/pmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/pmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,12 @@
 #define __ARM_PMU_H__
 
 #include <linux/interrupt.h>
+#include <linux/perf_event.h>
 
+/*
+ * Types of PMUs that can be accessed directly and require mutual
+ * exclusion between profiling tools.
+ */
 enum arm_pmu_type {
 	ARM_PMU_DEVICE_CPU	= 0,
 	ARM_NUM_PMU_DEVICES,
@@ -37,55 +42,95 @@
  * reserve_pmu() - reserve the hardware performance counters
  *
  * Reserve the hardware performance counters in the system for exclusive use.
- * The platform_device for the system is returned on success, ERR_PTR()
- * encoded error on failure.
+ * Returns 0 on success or -EBUSY if the lock is already held.
  */
-extern struct platform_device *
+extern int
 reserve_pmu(enum arm_pmu_type type);
 
 /**
  * release_pmu() - Relinquish control of the performance counters
  *
  * Release the performance counters and allow someone else to use them.
- * Callers must have disabled the counters and released IRQs before calling
- * this. The platform_device returned from reserve_pmu() must be passed as
- * a cookie.
  */
-extern int
+extern void
 release_pmu(enum arm_pmu_type type);
 
-/**
- * init_pmu() - Initialise the PMU.
- *
- * Initialise the system ready for PMU enabling. This should typically set the
- * IRQ affinity and nothing else. The users (oprofile/perf events etc) will do
- * the actual hardware initialisation.
- */
-extern int
-init_pmu(enum arm_pmu_type type);
-
 #else /* CONFIG_CPU_HAS_PMU */
 
 #include <linux/err.h>
 
-static inline struct platform_device *
-reserve_pmu(enum arm_pmu_type type)
-{
-	return ERR_PTR(-ENODEV);
-}
-
 static inline int
-release_pmu(enum arm_pmu_type type)
+reserve_pmu(enum arm_pmu_type type)
 {
 	return -ENODEV;
 }
 
-static inline int
-init_pmu(enum arm_pmu_type type)
-{
-	return -ENODEV;
-}
+static inline void
+release_pmu(enum arm_pmu_type type)	{ }
 
 #endif /* CONFIG_CPU_HAS_PMU */
 
+#ifdef CONFIG_HW_PERF_EVENTS
+
+/* The events for a given PMU register set. */
+struct pmu_hw_events {
+	/*
+	 * The events that are active on the PMU for the given index.
+	 */
+	struct perf_event	**events;
+
+	/*
+	 * A 1 bit for an index indicates that the counter is being used for
+	 * an event. A 0 means that the counter can be used.
+	 */
+	unsigned long           *used_mask;
+
+	/*
+	 * Hardware lock to serialize accesses to PMU registers. Needed for the
+	 * read/modify/write sequences.
+	 */
+	raw_spinlock_t		pmu_lock;
+};
+
+struct arm_pmu {
+	struct pmu	pmu;
+	enum arm_perf_pmu_ids id;
+	enum arm_pmu_type type;
+	cpumask_t	active_irqs;
+	const char	*name;
+	irqreturn_t	(*handle_irq)(int irq_num, void *dev);
+	void		(*enable)(struct hw_perf_event *evt, int idx);
+	void		(*disable)(struct hw_perf_event *evt, int idx);
+	int		(*get_event_idx)(struct pmu_hw_events *hw_events,
+					 struct hw_perf_event *hwc);
+	int		(*set_event_filter)(struct hw_perf_event *evt,
+					    struct perf_event_attr *attr);
+	u32		(*read_counter)(int idx);
+	void		(*write_counter)(int idx, u32 val);
+	void		(*start)(void);
+	void		(*stop)(void);
+	void		(*reset)(void *);
+	int		(*map_event)(struct perf_event *event);
+	int		num_events;
+	atomic_t	active_events;
+	struct mutex	reserve_mutex;
+	u64		max_period;
+	struct platform_device	*plat_device;
+	struct pmu_hw_events	*(*get_hw_events)(void);
+};
+
+#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
+
+int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type);
+
+u64 armpmu_event_update(struct perf_event *event,
+			struct hw_perf_event *hwc,
+			int idx, int overflow);
+
+int armpmu_event_set_period(struct perf_event *event,
+			    struct hw_perf_event *hwc,
+			    int idx);
+
+#endif /* CONFIG_HW_PERF_EVENTS */
+
 #endif /* __ARM_PMU_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/poll.h linux-libre-3.2-gnu/arch/arm/include/asm/poll.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/poll.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/poll.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/poll.h>
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/proc-fns.h linux-libre-3.2-gnu/arch/arm/include/asm/proc-fns.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/proc-fns.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/proc-fns.h	2012-01-04 18:55:44.000000000 -0500
@@ -81,6 +81,10 @@
 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));
+
+/* These three are private to arch/arm/kernel/suspend.c */
+extern void cpu_do_suspend(void *);
+extern void cpu_do_resume(void *);
 #else
 #define cpu_proc_init			processor._proc_init
 #define cpu_proc_fin			processor._proc_fin
@@ -89,6 +93,10 @@
 #define cpu_dcache_clean_area		processor.dcache_clean_area
 #define cpu_set_pte_ext			processor.set_pte_ext
 #define cpu_do_switch_mm		processor.switch_mm
+
+/* These three are private to arch/arm/kernel/suspend.c */
+#define cpu_do_suspend			processor.do_suspend
+#define cpu_do_resume			processor.do_resume
 #endif
 
 extern void cpu_resume(void);
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/resource.h linux-libre-3.2-gnu/arch/arm/include/asm/resource.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/resource.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/resource.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ARM_RESOURCE_H
-#define _ARM_RESOURCE_H
-
-#include <asm-generic/resource.h>
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/sections.h linux-libre-3.2-gnu/arch/arm/include/asm/sections.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/sections.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/sections.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/sections.h>
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/siginfo.h linux-libre-3.2-gnu/arch/arm/include/asm/siginfo.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/siginfo.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/siginfo.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASMARM_SIGINFO_H
-#define _ASMARM_SIGINFO_H
-
-#include <asm-generic/siginfo.h>
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/sizes.h linux-libre-3.2-gnu/arch/arm/include/asm/sizes.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/sizes.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/sizes.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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
- */
-/*  Size definitions
- *  Copyright (C) ARM Limited 1998. All rights reserved.
- */
-#include <asm-generic/sizes.h>
-
-#define SZ_48M	(SZ_32M + SZ_16M)
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/smp.h linux-libre-3.2-gnu/arch/arm/include/asm/smp.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/smp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/smp.h	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,11 @@
 asmlinkage void do_IPI(int ipinr, struct pt_regs *regs);
 
 /*
+ * Called from C code, this handles an IPI.
+ */
+void handle_IPI(int ipinr, struct pt_regs *regs);
+
+/*
  * Setup the set of possible CPUs (via set_cpu_possible)
  */
 extern void smp_init_cpus(void);
@@ -66,6 +71,12 @@
 extern void platform_smp_prepare_cpus(unsigned int);
 
 /*
+ * Logical CPU mapping.
+ */
+extern int __cpu_logical_map[NR_CPUS];
+#define cpu_logical_map(cpu)	__cpu_logical_map[cpu]
+
+/*
  * Initial data for bringing up a secondary CPU.
  */
 struct secondary_data {
@@ -88,9 +99,4 @@
 extern void arch_send_call_function_single_ipi(int cpu);
 extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
 
-/*
- * show local interrupt info
- */
-extern void show_local_irqs(struct seq_file *, int);
-
 #endif /* ifndef __ASM_ARM_SMP_H */
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/smp_twd.h linux-libre-3.2-gnu/arch/arm/include/asm/smp_twd.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/smp_twd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/smp_twd.h	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,7 @@
 
 extern void __iomem *twd_base;
 
-int twd_timer_ack(void);
 void twd_timer_setup(struct clock_event_device *);
+void twd_timer_stop(struct clock_event_device *);
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/suspend.h linux-libre-3.2-gnu/arch/arm/include/asm/suspend.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/suspend.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/suspend.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,22 +1,7 @@
 #ifndef __ASM_ARM_SUSPEND_H
 #define __ASM_ARM_SUSPEND_H
 
-#include <asm/memory.h>
-#include <asm/tlbflush.h>
-
 extern void cpu_resume(void);
-
-/*
- * Hide the first two arguments to __cpu_suspend - these are an implementation
- * detail which platform code shouldn't have to know about.
- */
-static inline int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
-{
-	extern int __cpu_suspend(int, long, unsigned long,
-				 int (*)(unsigned long));
-	int ret = __cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, arg, fn);
-	flush_tlb_all();
-	return ret;
-}
+extern int cpu_suspend(unsigned long, int (*)(unsigned long));
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/system.h linux-libre-3.2-gnu/arch/arm/include/asm/system.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -57,18 +57,12 @@
 
 #ifndef __ASSEMBLY__
 
+#include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/irqflags.h>
 
 #include <asm/outercache.h>
 
-#define __exception	__attribute__((section(".exception.text")))
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-#define __exception_irq_entry	__irq_entry
-#else
-#define __exception_irq_entry	__exception
-#endif
-
 struct thread_info;
 struct task_struct;
 
@@ -97,14 +91,13 @@
 #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 int __pure cpu_architecture(void);
 extern void cpu_init(void);
 
 void arm_machine_restart(char mode, const char *cmd);
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/tlbflush.h linux-libre-3.2-gnu/arch/arm/include/asm/tlbflush.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/tlbflush.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/tlbflush.h	2012-01-04 18:55:44.000000000 -0500
@@ -471,7 +471,7 @@
  *	these operations.  This is typically used when we are removing
  *	PMD entries.
  */
-static inline void flush_pmd_entry(pmd_t *pmd)
+static inline void flush_pmd_entry(void *pmd)
 {
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
@@ -487,7 +487,7 @@
 		dsb();
 }
 
-static inline void clean_pmd_entry(pmd_t *pmd)
+static inline void clean_pmd_entry(void *pmd)
 {
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/topology.h linux-libre-3.2-gnu/arch/arm/include/asm/topology.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/topology.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/topology.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,39 @@
 #ifndef _ASM_ARM_TOPOLOGY_H
 #define _ASM_ARM_TOPOLOGY_H
 
+#ifdef CONFIG_ARM_CPU_TOPOLOGY
+
+#include <linux/cpumask.h>
+
+struct cputopo_arm {
+	int thread_id;
+	int core_id;
+	int socket_id;
+	cpumask_t thread_sibling;
+	cpumask_t core_sibling;
+};
+
+extern struct cputopo_arm cpu_topology[NR_CPUS];
+
+#define topology_physical_package_id(cpu)	(cpu_topology[cpu].socket_id)
+#define topology_core_id(cpu)		(cpu_topology[cpu].core_id)
+#define topology_core_cpumask(cpu)	(&cpu_topology[cpu].core_sibling)
+#define topology_thread_cpumask(cpu)	(&cpu_topology[cpu].thread_sibling)
+
+#define mc_capable()	(cpu_topology[0].socket_id != -1)
+#define smt_capable()	(cpu_topology[0].thread_id != -1)
+
+void init_cpu_topology(void);
+void store_cpu_topology(unsigned int cpuid);
+const struct cpumask *cpu_coregroup_mask(int cpu);
+
+#else
+
+static inline void init_cpu_topology(void) { }
+static inline void store_cpu_topology(unsigned int cpuid) { }
+
+#endif
+
 #include <asm-generic/topology.h>
 
 #endif /* _ASM_ARM_TOPOLOGY_H */
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/unistd.h linux-libre-3.2-gnu/arch/arm/include/asm/unistd.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/unistd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -402,6 +402,8 @@
 #define __NR_syncfs			(__NR_SYSCALL_BASE+373)
 #define __NR_sendmmsg			(__NR_SYSCALL_BASE+374)
 #define __NR_setns			(__NR_SYSCALL_BASE+375)
+#define __NR_process_vm_readv		(__NR_SYSCALL_BASE+376)
+#define __NR_process_vm_writev		(__NR_SYSCALL_BASE+377)
 
 /*
  * The following SWIs are ARM private.
diff -druN linux-libre-3.1-gnu/arch/arm/include/asm/unwind.h linux-libre-3.2-gnu/arch/arm/include/asm/unwind.h
--- linux-libre-3.1-gnu/arch/arm/include/asm/unwind.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/include/asm/unwind.h	2012-01-04 18:55:44.000000000 -0500
@@ -30,14 +30,15 @@
 };
 
 struct unwind_idx {
-	unsigned long addr;
+	unsigned long addr_offset;
 	unsigned long insn;
 };
 
 struct unwind_table {
 	struct list_head list;
-	struct unwind_idx *start;
-	struct unwind_idx *stop;
+	const struct unwind_idx *start;
+	const struct unwind_idx *origin;
+	const struct unwind_idx *stop;
 	unsigned long begin_addr;
 	unsigned long end_addr;
 };
@@ -49,15 +50,6 @@
 extern void unwind_table_del(struct unwind_table *tab);
 extern void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk);
 
-#ifdef CONFIG_ARM_UNWIND
-extern int __init unwind_init(void);
-#else
-static inline int __init unwind_init(void)
-{
-	return 0;
-}
-#endif
-
 #endif	/* !__ASSEMBLY__ */
 
 #ifdef CONFIG_ARM_UNWIND
diff -druN linux-libre-3.1-gnu/arch/arm/Kconfig linux-libre-3.2-gnu/arch/arm/Kconfig
--- linux-libre-3.1-gnu/arch/arm/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
 	default y
 	select HAVE_AOUT
 	select HAVE_DMA_API_DEBUG
-	select HAVE_IDE
+	select HAVE_IDE if PCI || ISA || PCMCIA
 	select HAVE_MEMBLOCK
 	select RTC_LIB
 	select SYS_SUPPORTS_APM_EMULATION
@@ -29,6 +29,7 @@
 	select HAVE_GENERIC_HARDIRQS
 	select HAVE_SPARSE_IRQ
 	select GENERIC_IRQ_SHOW
+	select CPU_PM if (SUSPEND || CPU_IDLE)
 	help
 	  The ARM series is a line of low-power-consumption RISC chip designs
 	  licensed by ARM Ltd and targeted at embedded applications and
@@ -195,7 +196,8 @@
 	  The base address of exception vectors.
 
 config ARM_PATCH_PHYS_VIRT
-	bool "Patch physical to virtual translations at runtime"
+	bool "Patch physical to virtual translations at runtime" if EMBEDDED
+	default y
 	depends on !XIP_KERNEL && MMU
 	depends on !ARCH_REALVIEW || !SPARSEMEM
 	help
@@ -204,16 +206,30 @@
 	  kernel in system memory.
 
 	  This can only be used with non-XIP MMU kernels where the base
-	  of physical memory is at a 16MB boundary, or theoretically 64K
-	  for the MSM machine class.
+	  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
+	  Only disable this option if you know that you do not require
+	  this feature (eg, building a kernel for a single machine) and
+	  you need to shrink the kernel to the minimal size.
+
+config NEED_MACH_MEMORY_H
+	bool
 	help
-	  This option extends the physical to virtual translation patching
-	  to allow physical memory down to a theoretical minimum of 64K
-	  boundaries.
+	  Select this when mach/memory.h is required to provide special
+	  definitions for this platform.  The need for mach/memory.h should
+	  be avoided when possible.
+
+config PHYS_OFFSET
+	hex "Physical address of main memory" if MMU
+	depends on !ARM_PATCH_PHYS_VIRT && !NEED_MACH_MEMORY_H
+	default DRAM_BASE if !MMU
+	help
+	  Please provide the physical address corresponding to the
+	  location of main memory in your system.
+
+config GENERIC_BUG
+	def_bool y
+	depends on BUG
 
 source "init/Kconfig"
 
@@ -246,6 +262,7 @@
 	select GENERIC_CLOCKEVENTS
 	select PLAT_VERSATILE
 	select PLAT_VERSATILE_FPGA_IRQ
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for ARM's Integrator platform.
 
@@ -261,6 +278,7 @@
 	select PLAT_VERSATILE_CLCD
 	select ARM_TIMER_SP804
 	select GPIO_PL061 if GPIOLIB
+	select NEED_MACH_MEMORY_H
 	help
 	  This enables support for ARM Ltd RealView boards.
 
@@ -301,7 +319,6 @@
 	select ARCH_REQUIRE_GPIOLIB
 	select HAVE_CLK
 	select CLKDEV_LOOKUP
-	select ARM_PATCH_PHYS_VIRT if MMU
 	help
 	  This enables support for systems based on the Atmel AT91RM9200,
 	  AT91SAM9 and AT91CAP9 processors.
@@ -318,10 +335,25 @@
 	help
 	  Support for Broadcom's BCMRing platform.
 
+config ARCH_HIGHBANK
+	bool "Calxeda Highbank-based"
+	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select ARM_AMBA
+	select ARM_GIC
+	select ARM_TIMER_SP804
+	select CLKDEV_LOOKUP
+	select CPU_V7
+	select GENERIC_CLOCKEVENTS
+	select HAVE_ARM_SCU
+	select USE_OF
+	help
+	  Support for the Calxeda Highbank SoC based boards.
+
 config ARCH_CLPS711X
 	bool "Cirrus Logic CLPS711x/EP721x-based"
 	select CPU_ARM720T
 	select ARCH_USES_GETTIMEOFFSET
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for Cirrus Logic 711x/721x based boards.
 
@@ -346,7 +378,6 @@
 config ARCH_PRIMA2
 	bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform"
 	select CPU_V7
-	select GENERIC_TIME
 	select NO_IOPORT
 	select GENERIC_CLOCKEVENTS
 	select CLKDEV_LOOKUP
@@ -362,6 +393,7 @@
 	select ISA
 	select NO_IOPORT
 	select ARCH_USES_GETTIMEOFFSET
+	select NEED_MACH_MEMORY_H
 	help
 	  This is an evaluation board for the StrongARM processor available
 	  from Digital. It has limited hardware on-board, including an
@@ -377,6 +409,7 @@
 	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_HAS_HOLES_MEMORYMODEL
 	select ARCH_USES_GETTIMEOFFSET
+	select NEED_MACH_MEMORY_H
 	help
 	  This enables support for the Cirrus EP93xx series of CPUs.
 
@@ -385,6 +418,8 @@
 	select CPU_SA110
 	select FOOTBRIDGE
 	select GENERIC_CLOCKEVENTS
+	select HAVE_IDE
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for systems based on the DC21285 companion chip
 	  ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
@@ -397,6 +432,7 @@
 	select CLKSRC_MMIO
 	select GENERIC_IRQ_CHIP
 	select HAVE_SCHED_CLOCK
+	select MULTI_IRQ_HANDLER
 	help
 	  Support for Freescale MXC/iMX-based family of processors
 
@@ -434,6 +470,7 @@
 	select PCI
 	select ARCH_SUPPORTS_MSI
 	select VMSPLIT_1G
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for Intel's IOP13XX (XScale) family of processors.
 
@@ -464,6 +501,7 @@
 	select CPU_XSC3
  	select PCI
 	select ARCH_USES_GETTIMEOFFSET
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for Intel's IXP23xx (XScale) family of processors.
 
@@ -473,6 +511,7 @@
 	select CPU_XSCALE
 	select PCI
 	select ARCH_USES_GETTIMEOFFSET
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for Intel's IXP2400/2800 (XScale) family of processors.
 
@@ -519,7 +558,6 @@
 	select ARM_AMBA
 	select USB_ARCH_HAS_OHCI
 	select CLKDEV_LOOKUP
-	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	help
 	  Support for the NXP LPC32XX family of processors
@@ -558,6 +596,7 @@
 	select TICK_ONESHOT
 	select PLAT_PXA
 	select SPARSE_IRQ
+	select GENERIC_ALLOCATOR
 	help
 	  Support for Marvell's PXA168/PXA910(MMP) and MMP2 processor line.
 
@@ -566,6 +605,7 @@
 	select CPU_ARM922T
 	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_USES_GETTIMEOFFSET
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based
 	  System-on-Chip devices.
@@ -586,19 +626,10 @@
 	  <http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/
 		ConsumerElectronicsIC/ARMMicrocontroller/ARMMicrocontroller>
 
-config ARCH_NUC93X
-	bool "Nuvoton NUC93X CPU"
-	select CPU_ARM926T
-	select CLKDEV_LOOKUP
-	help
-	  Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a
-	  low-power and high performance MPEG-4/JPEG multimedia controller chip.
-
 config ARCH_TEGRA
 	bool "NVIDIA Tegra"
 	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
-	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_GPIO
 	select HAVE_CLK
@@ -608,6 +639,24 @@
 	  This enables support for NVIDIA Tegra based systems (Tegra APX,
 	  Tegra 6xx and Tegra 2 series).
 
+config ARCH_PICOXCELL
+	bool "Picochip picoXcell"
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_PATCH_PHYS_VIRT
+	select ARM_VIC
+	select CPU_V6K
+	select DW_APB_TIMER
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_GPIO
+	select HAVE_SCHED_CLOCK
+	select HAVE_TCM
+	select NO_IOPORT
+	select USE_OF
+	help
+	  This enables support for systems based on the Picochip picoXcell
+	  family of Femtocell devices.  The picoxcell support requires device tree
+	  for all boards.
+
 config ARCH_PNX4008
 	bool "Philips Nexperia PNX4008 Mobile"
 	select CPU_ARM926T
@@ -631,6 +680,8 @@
 	select SPARSE_IRQ
 	select AUTO_ZRELADDR
 	select MULTI_IRQ_HANDLER
+	select ARM_CPU_SUSPEND if PM
+	select HAVE_IDE
 	help
 	  Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
 
@@ -657,6 +708,7 @@
 	select SPARSE_IRQ
 	select MULTI_IRQ_HANDLER
 	select PM_GENERIC_DOMAINS if PM
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for Renesas's SH-Mobile and R-Mobile ARM platforms.
 
@@ -671,6 +723,8 @@
 	select NO_IOPORT
 	select ARCH_SPARSEMEM_ENABLE
 	select ARCH_USES_GETTIMEOFFSET
+	select HAVE_IDE
+	select NEED_MACH_MEMORY_H
 	help
 	  On the Acorn Risc-PC, Linux can support the internal IDE disk and
 	  CD-ROM interface, serial and parallel port, and the floppy drive.
@@ -689,6 +743,8 @@
 	select HAVE_SCHED_CLOCK
 	select TICK_ONESHOT
 	select ARCH_REQUIRE_GPIOLIB
+	select HAVE_IDE
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for StrongARM 11x0 based boards.
 
@@ -715,6 +771,7 @@
 	select CPU_V6
 	select ARM_VIC
 	select HAVE_CLK
+	select HAVE_TCM
 	select CLKDEV_LOOKUP
 	select NO_IOPORT
 	select ARCH_USES_GETTIMEOFFSET
@@ -722,11 +779,7 @@
 	select ARCH_REQUIRE_GPIOLIB
 	select SAMSUNG_CLKSRC
 	select SAMSUNG_IRQ_VIC_TIMER
-	select SAMSUNG_IRQ_UART
 	select S3C_GPIO_TRACK
-	select S3C_GPIO_PULL_UPDOWN
-	select S3C_GPIO_CFG_S3C24XX
-	select S3C_GPIO_CFG_S3C64XX
 	select S3C_DEV_NAND
 	select USB_ARCH_HAS_OHCI
 	select SAMSUNG_GPIOLIB_4BIT
@@ -781,11 +834,12 @@
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C_RTC if RTC_CLASS
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
+	select NEED_MACH_MEMORY_H
 	help
 	  Samsung S5PV210/S5PC110 series based systems
 
-config ARCH_EXYNOS4
-	bool "Samsung EXYNOS4"
+config ARCH_EXYNOS
+	bool "SAMSUNG EXYNOS"
 	select CPU_V7
 	select ARCH_SPARSEMEM_ENABLE
 	select ARCH_HAS_HOLES_MEMORYMODEL
@@ -797,8 +851,9 @@
 	select HAVE_S3C_RTC if RTC_CLASS
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
+	select NEED_MACH_MEMORY_H
 	help
-	  Samsung EXYNOS4 series based systems
+	  Support for SAMSUNG's EXYNOS SoCs (EXYNOS4/5)
 
 config ARCH_SHARK
 	bool "Shark"
@@ -808,6 +863,7 @@
 	select ZONE_DMA
 	select PCI
 	select ARCH_USES_GETTIMEOFFSET
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for the StrongARM based Digital DNARD machine, also known
 	  as "Shark" (<http://www.shark-linux.de/shark.html>).
@@ -830,11 +886,14 @@
 	select HAVE_SCHED_CLOCK
 	select HAVE_TCM
 	select ARM_AMBA
+	select ARM_PATCH_PHYS_VIRT
 	select ARM_VIC
 	select GENERIC_CLOCKEVENTS
 	select CLKDEV_LOOKUP
 	select HAVE_MACH_CLKDEV
 	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select NEED_MACH_MEMORY_H
 	help
 	  Support for ST-Ericsson U300 series mobile platforms.
 
@@ -910,7 +969,6 @@
 config ARCH_ZYNQ
 	bool "Xilinx Zynq ARM Cortex A9 Platform"
 	select CPU_V7
-	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	select CLKDEV_LOOKUP
 	select ARM_GIC
@@ -979,8 +1037,6 @@
 source "arch/arm/mach-nomadik/Kconfig"
 source "arch/arm/plat-nomadik/Kconfig"
 
-source "arch/arm/mach-nuc93x/Kconfig"
-
 source "arch/arm/plat-omap/Kconfig"
 
 source "arch/arm/mach-omap1/Kconfig"
@@ -1024,7 +1080,7 @@
 
 source "arch/arm/mach-s5pv210/Kconfig"
 
-source "arch/arm/mach-exynos4/Kconfig"
+source "arch/arm/mach-exynos/Kconfig"
 
 source "arch/arm/mach-shmobile/Kconfig"
 
@@ -1176,7 +1232,7 @@
 	  capabilities of the processor.
 
 config PL310_ERRATA_588369
-	bool "Clean & Invalidate maintenance operations do not invalidate clean lines"
+	bool "PL310 errata: Clean & Invalidate maintenance operations do not invalidate clean lines"
 	depends on CACHE_L2X0
 	help
 	   The PL310 L2 cache controller implements three types of Clean &
@@ -1190,7 +1246,7 @@
 
 config ARM_ERRATA_720789
 	bool "ARM errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID"
-	depends on CPU_V7 && SMP
+	depends on CPU_V7
 	help
 	  This option enables the workaround for the 720789 Cortex-A9 (prior to
 	  r2p0) erratum. A faulty ASID can be sent to the other CPUs for the
@@ -1201,7 +1257,7 @@
 	  entries regardless of the ASID.
 
 config PL310_ERRATA_727915
-	bool "Background Clean & Invalidate by Way operation can cause data corruption"
+	bool "PL310 errata: 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
@@ -1226,7 +1282,7 @@
 
 config ARM_ERRATA_751472
 	bool "ARM errata: Interrupted ICIALLUIS may prevent completion of broadcasted operation"
-	depends on CPU_V7 && SMP
+	depends on CPU_V7
 	help
 	  This option enables the workaround for the 751472 Cortex-A9 (prior
 	  to r3p0) erratum. An interrupted ICIALLUIS operation may prevent the
@@ -1234,8 +1290,8 @@
 	  operation is received by a CPU before the ICIALLUIS has completed,
 	  potentially leading to corrupted entries in the cache or TLB.
 
-config ARM_ERRATA_753970
-	bool "ARM errata: cache sync operation may be faulty"
+config PL310_ERRATA_753970
+	bool "PL310 errata: cache sync operation may be faulty"
 	depends on CACHE_PL310
 	help
 	  This option enables the workaround for the 753970 PL310 (r3p0) erratum.
@@ -1297,6 +1353,18 @@
 	  relevant cache maintenance functions and sets a specific bit
 	  in the diagnostic control register of the SCU.
 
+config PL310_ERRATA_769419
+	bool "PL310 errata: no automatic Store Buffer drain"
+	depends on CACHE_L2X0
+	help
+	  On revisions of the PL310 prior to r3p2, the Store Buffer does
+	  not automatically drain. This can cause normal, non-cacheable
+	  writes to be retained when the memory system is idle, leading
+	  to suboptimal I/O performance for drivers using coherent DMA.
+	  This option adds a write barrier to the cpu_idle loop so that,
+	  on systems with an outer cache, the store buffer is drained
+	  explicitly.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
@@ -1374,7 +1442,8 @@
 	depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \
 		 MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
 		 ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
-		 ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE
+		 ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE || ARCH_HIGHBANK || SOC_IMX6Q
+	depends on MMU
 	select USE_GENERIC_SMP_HELPERS
 	select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP
 	help
@@ -1388,7 +1457,7 @@
 	  processor machines. On a single processor machine, the kernel will
 	  run faster if you say N here.
 
-	  See also <file:Documentation/i386/IO-APIC.txt>,
+	  See also <file:Documentation/x86/i386/IO-APIC.txt>,
 	  <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
 	  <http://tldp.org/HOWTO/SMP-HOWTO.html>.
 
@@ -1407,6 +1476,31 @@
 
 	  If you don't know what to do here, say Y.
 
+config ARM_CPU_TOPOLOGY
+	bool "Support cpu topology definition"
+	depends on SMP && CPU_V7
+	default y
+	help
+	  Support ARM cpu topology definition. The MPIDR register defines
+	  affinity between processors which is then used to describe the cpu
+	  topology of an ARM System.
+
+config SCHED_MC
+	bool "Multi-core scheduler support"
+	depends on ARM_CPU_TOPOLOGY
+	help
+	  Multi-core scheduler support improves the CPU scheduler's decision
+	  making when dealing with multi-core CPU chips at a cost of slightly
+	  increased overhead in some places. If unsure say N here.
+
+config SCHED_SMT
+	bool "SMT scheduler support"
+	depends on ARM_CPU_TOPOLOGY
+	help
+	  Improves the CPU scheduler's decision making when dealing with
+	  MultiThreading at a cost of slightly increased overhead in some
+	  places. If unsure say N here.
+
 config HAVE_ARM_SCU
 	bool
 	help
@@ -1482,6 +1576,7 @@
 	depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL
 	select AEABI
 	select ARM_ASM_UNIFIED
+	select ARM_UNWIND
 	help
 	  By enabling this option, the kernel will be compiled in
 	  Thumb-2 mode. A compiler/assembler that understand the unified
@@ -1807,6 +1902,38 @@
 
 endchoice
 
+config ARM_APPENDED_DTB
+	bool "Use appended device tree blob to zImage (EXPERIMENTAL)"
+	depends on OF && !ZBOOT_ROM && EXPERIMENTAL
+	help
+	  With this option, the boot code will look for a device tree binary
+	  (DTB) appended to zImage
+	  (e.g. cat zImage <filename>.dtb > zImage_w_dtb).
+
+	  This is meant as a backward compatibility convenience for those
+	  systems with a bootloader that can't be upgraded to accommodate
+	  the documented boot protocol using a device tree.
+
+	  Beware that there is very little in terms of protection against
+	  this option being confused by leftover garbage in memory that might
+	  look like a DTB header after a reboot if no actual DTB is appended
+	  to zImage.  Do not leave this option active in a production kernel
+	  if you don't intend to always append a DTB.  Proper passing of the
+	  location into r2 of a bootloader provided DTB is always preferable
+	  to this option.
+
+config ARM_ATAG_DTB_COMPAT
+	bool "Supplement the appended DTB with traditional ATAG information"
+	depends on ARM_APPENDED_DTB
+	help
+	  Some old bootloaders can't be updated to a DTB capable one, yet
+	  they provide ATAGs with memory configuration, the ramdisk address,
+	  the kernel cmdline string, etc.  Such information is dynamically
+	  provided by the bootloader and can't always be stored in a static
+	  DTB.  To allow a device tree enabled kernel to be used with such
+	  bootloaders, this option allows zImage to extract the information
+	  from the ATAG list and store it at run time into the appended DTB.
+
 config CMDLINE
 	string "Default kernel command string"
 	default ""
@@ -1953,6 +2080,7 @@
 	bool
 	depends on CPU_FREQ && ARCH_PXA && PXA25x
 	default y
+	select CPU_FREQ_TABLE
 	select CPU_FREQ_DEFAULT_GOV_USERSPACE
 
 config CPU_FREQ_S3C
@@ -2096,11 +2224,14 @@
 source "kernel/power/Kconfig"
 
 config ARCH_SUSPEND_POSSIBLE
-	depends on !ARCH_S5P64X0 && !ARCH_S5PC100
+	depends on !ARCH_S5PC100
 	depends on CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || \
 		CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE
 	def_bool y
 
+config ARM_CPU_SUSPEND
+	def_bool PM_SLEEP
+
 endmenu
 
 source "net/Kconfig"
diff -druN linux-libre-3.1-gnu/arch/arm/Kconfig.debug linux-libre-3.2-gnu/arch/arm/Kconfig.debug
--- linux-libre-3.1-gnu/arch/arm/Kconfig.debug	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/Kconfig.debug	2012-01-04 18:55:44.000000000 -0500
@@ -65,13 +65,190 @@
 
 # These options are only for real kernel hackers who want to get their hands dirty.
 config DEBUG_LL
-	bool "Kernel low-level debugging functions"
+	bool "Kernel low-level debugging functions (read help!)"
 	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.
 
+	  Note that selecting this option will limit the kernel to a single
+	  UART definition, as specified below. Attempting to boot the kernel
+	  image on a different platform *will not work*, so this option should
+	  not be enabled for kernels that are intended to be portable.
+
+choice
+	prompt "Kernel low-level debugging port"
+	depends on DEBUG_LL
+
+	config DEBUG_LL_UART_NONE
+		bool "No low-level debugging UART"
+		help
+		  Say Y here if your platform doesn't provide a UART option
+		  below. This relies on your platform choosing the right UART
+		  definition internally in order for low-level debugging to
+		  work.
+
+	config DEBUG_ICEDCC
+		bool "Kernel low-level debugging via EmbeddedICE DCC channel"
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the EmbeddedICE macrocell's DCC channel using
+		  co-processor 14. This is known to work on the ARM9 style ICE
+		  channel and on the XScale with the PEEDI.
+
+		  Note that the system will appear to hang during boot if there
+		  is nothing connected to read from the DCC.
+
+	config DEBUG_FOOTBRIDGE_COM1
+		bool "Kernel low-level debugging messages via footbridge 8250 at PCI COM1"
+		depends on FOOTBRIDGE
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the 8250 at PCI COM1.
+
+	config DEBUG_DC21285_PORT
+		bool "Kernel low-level debugging messages via footbridge serial port"
+		depends on FOOTBRIDGE
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the serial port in the DC21285 (Footbridge).
+
+	config DEBUG_CLPS711X_UART1
+		bool "Kernel low-level debugging messages via UART1"
+		depends on ARCH_CLPS711X
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the first serial port on these devices.
+
+	config DEBUG_CLPS711X_UART2
+		bool "Kernel low-level debugging messages via UART2"
+		depends on ARCH_CLPS711X
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the second serial port on these devices.
+
+	config DEBUG_HIGHBANK_UART
+		bool "Kernel low-level debugging messages via Highbank UART"
+		depends on ARCH_HIGHBANK
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the UART on Highbank based devices.
+
+	config DEBUG_IMX1_UART
+		bool "i.MX1 Debug UART"
+		depends on SOC_IMX1
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX1.
+
+	config DEBUG_IMX23_UART
+		bool "i.MX23 Debug UART"
+		depends on SOC_IMX23
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX23.
+
+	config DEBUG_IMX25_UART
+		bool "i.MX25 Debug UART"
+		depends on SOC_IMX25
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX25.
+
+	config DEBUG_IMX21_IMX27_UART
+		bool "i.MX21 and i.MX27 Debug UART"
+		depends on SOC_IMX21 || SOC_IMX27
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX21 or i.MX27.
+
+	config DEBUG_IMX28_UART
+		bool "i.MX28 Debug UART"
+		depends on SOC_IMX28
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX28.
+
+	config DEBUG_IMX31_IMX35_UART
+		bool "i.MX31 and i.MX35 Debug UART"
+		depends on SOC_IMX31 || SOC_IMX35
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX31 or i.MX35.
+
+	config DEBUG_IMX51_UART
+		bool "i.MX51 Debug UART"
+		depends on SOC_IMX51
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX51.
+
+	config DEBUG_IMX50_IMX53_UART
+		bool "i.MX50 and i.MX53 Debug UART"
+		depends on SOC_IMX50 || SOC_IMX53
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX50 or i.MX53.
+
+	config DEBUG_IMX6Q_UART
+		bool "i.MX6Q Debug UART"
+		depends on SOC_IMX6Q
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX6Q.
+
+	config DEBUG_S3C_UART0
+		depends on PLAT_SAMSUNG
+		bool "Use S3C UART 0 for low-level debug"
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to UART 0. The port must have been initialised
+		  by the boot-loader before use.
+
+		  The uncompressor code port configuration is now handled
+		  by CONFIG_S3C_LOWLEVEL_UART_PORT.
+
+	config DEBUG_S3C_UART1
+		depends on PLAT_SAMSUNG
+		bool "Use S3C UART 1 for low-level debug"
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to UART 1. The port must have been initialised
+		  by the boot-loader before use.
+
+		  The uncompressor code port configuration is now handled
+		  by CONFIG_S3C_LOWLEVEL_UART_PORT.
+
+	config DEBUG_S3C_UART2
+		depends on PLAT_SAMSUNG
+		bool "Use S3C UART 2 for low-level debug"
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to UART 2. The port must have been initialised
+		  by the boot-loader before use.
+
+		  The uncompressor code port configuration is now handled
+		  by CONFIG_S3C_LOWLEVEL_UART_PORT.
+
+	config DEBUG_REALVIEW_STD_PORT
+		bool "RealView Default UART"
+		depends on ARCH_REALVIEW
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the serial port on RealView EB, PB11MP, PBA8
+		  and PBX platforms.
+
+	config DEBUG_REALVIEW_PB1176_PORT
+		bool "RealView PB1176 UART"
+		depends on MACH_REALVIEW_PB1176
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the standard serial port on the RealView
+		  PB1176 platform.
+
+endchoice
+
 config EARLY_PRINTK
 	bool "Early printk"
 	depends on DEBUG_LL
@@ -80,53 +257,18 @@
 	  kernel low-level debugging functions. Add earlyprintk to your
 	  kernel parameters to enable this console.
 
-config DEBUG_ICEDCC
-	bool "Kernel low-level debugging via EmbeddedICE DCC channel"
-	depends on DEBUG_LL
-	help
-	  Say Y here if you want the debug print routines to direct their
-	  output to the EmbeddedICE macrocell's DCC channel using
-	  co-processor 14. This is known to work on the ARM9 style ICE
-	  channel and on the XScale with the PEEDI.
-
-	  It does include a timeout to ensure that the system does not
-	  totally freeze when there is nothing connected to read.
-
 config OC_ETM
 	bool "On-chip ETM and ETB"
-	select ARM_AMBA
+	depends on ARM_AMBA
 	help
 	  Enables the on-chip embedded trace macrocell and embedded trace
 	  buffer driver that will allow you to collect traces of the
 	  kernel code.
 
-config DEBUG_DC21285_PORT
-	bool "Kernel low-level debugging messages via footbridge serial port"
-	depends on DEBUG_LL && FOOTBRIDGE
-	help
-	  Say Y here if you want the debug print routines to direct their
-	  output to the serial port in the DC21285 (Footbridge). Saying N
-	  will cause the debug messages to appear on the first 16550
-	  serial port.
-
-config DEBUG_CLPS711X_UART2
-	bool "Kernel low-level debugging messages via UART2"
-	depends on DEBUG_LL && ARCH_CLPS711X
-	help
-	  Say Y here if you want the debug print routines to direct their
-	  output to the second serial port on these devices.  Saying N will
-	  cause the debug messages to appear on the first serial port.
-
-config DEBUG_S3C_UART
-	depends on PLAT_SAMSUNG
-	int "S3C UART to use for low-level debug"
-	default "0"
+config ARM_KPROBES_TEST
+	tristate "Kprobes test module"
+	depends on KPROBES && MODULES
 	help
-	  Choice for UART for kernel low-level using S3C UARTS,
-	  should be between zero and two. The port must have been
-	  initialised by the boot-loader before use.
-
-	  The uncompressor code port configuration is now handled
-	  by CONFIG_S3C_LOWLEVEL_UART_PORT.
+	  Perform tests of kprobes API and instruction set simulation.
 
 endmenu
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/armksyms.c linux-libre-3.2-gnu/arch/arm/kernel/armksyms.c
--- linux-libre-3.1-gnu/arch/arm/kernel/armksyms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/armksyms.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * 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/export.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/cryptohash.h>
@@ -49,9 +49,6 @@
 
 extern void fpundefinstr(void);
 
-
-EXPORT_SYMBOL(__backtrace);
-
 	/* platform dependent support */
 EXPORT_SYMBOL(__udelay);
 EXPORT_SYMBOL(__const_udelay);
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/asm-offsets.c linux-libre-3.2-gnu/arch/arm/kernel/asm-offsets.c
--- linux-libre-3.1-gnu/arch/arm/kernel/asm-offsets.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/asm-offsets.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <asm/thread_info.h>
 #include <asm/memory.h>
 #include <asm/procinfo.h>
+#include <asm/hardware/cache-l2x0.h>
 #include <linux/kbuild.h>
 
 /*
@@ -92,6 +93,17 @@
   DEFINE(S_OLD_R0,		offsetof(struct pt_regs, ARM_ORIG_r0));
   DEFINE(S_FRAME_SIZE,		sizeof(struct pt_regs));
   BLANK();
+#ifdef CONFIG_CACHE_L2X0
+  DEFINE(L2X0_R_PHY_BASE,	offsetof(struct l2x0_regs, phy_base));
+  DEFINE(L2X0_R_AUX_CTRL,	offsetof(struct l2x0_regs, aux_ctrl));
+  DEFINE(L2X0_R_TAG_LATENCY,	offsetof(struct l2x0_regs, tag_latency));
+  DEFINE(L2X0_R_DATA_LATENCY,	offsetof(struct l2x0_regs, data_latency));
+  DEFINE(L2X0_R_FILTER_START,	offsetof(struct l2x0_regs, filter_start));
+  DEFINE(L2X0_R_FILTER_END,	offsetof(struct l2x0_regs, filter_end));
+  DEFINE(L2X0_R_PREFETCH_CTRL,	offsetof(struct l2x0_regs, prefetch_ctrl));
+  DEFINE(L2X0_R_PWR_CTRL,	offsetof(struct l2x0_regs, pwr_ctrl));
+  BLANK();
+#endif
 #ifdef CONFIG_CPU_HAS_ASID
   DEFINE(MM_CONTEXT_ID,		offsetof(struct mm_struct, context.id));
   BLANK();
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/bios32.c linux-libre-3.2-gnu/arch/arm/kernel/bios32.c
--- linux-libre-3.1-gnu/arch/arm/kernel/bios32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/bios32.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
  *
  *  Bits taken from various places.
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
@@ -412,6 +412,9 @@
 	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
 
 /*
  * Convert from Linux-centric to bus-centric addresses for bridge devices.
@@ -431,6 +434,7 @@
 	region->start = res->start - offset;
 	region->end   = res->end - offset;
 }
+EXPORT_SYMBOL(pcibios_resource_to_bus);
 
 void __devinit
 pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
@@ -447,12 +451,7 @@
 	res->start = region->start + offset;
 	res->end   = region->end + offset;
 }
-
-#ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL(pcibios_fixup_bus);
-EXPORT_SYMBOL(pcibios_resource_to_bus);
 EXPORT_SYMBOL(pcibios_bus_to_resource);
-#endif
 
 /*
  * Swizzle the device pin each time we cross a bridge.
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/calls.S linux-libre-3.2-gnu/arch/arm/kernel/calls.S
--- linux-libre-3.1-gnu/arch/arm/kernel/calls.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/calls.S	2012-01-04 18:55:44.000000000 -0500
@@ -385,6 +385,8 @@
 		CALL(sys_syncfs)
 		CALL(sys_sendmmsg)
 /* 375 */	CALL(sys_setns)
+		CALL(sys_process_vm_readv)
+		CALL(sys_process_vm_writev)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/debug.S linux-libre-3.2-gnu/arch/arm/kernel/debug.S
--- linux-libre-3.1-gnu/arch/arm/kernel/debug.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/debug.S	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,7 @@
 #if defined(CONFIG_DEBUG_ICEDCC)
 		@@ debug using ARM EmbeddedICE DCC channel
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		.endm
 
 #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
@@ -106,7 +106,7 @@
 
 #ifdef CONFIG_MMU
 		.macro	addruart_current, rx, tmp1, tmp2
-		addruart	\tmp1, \tmp2
+		addruart	\tmp1, \tmp2, \rx
 		mrc		p15, 0, \rx, c1, c0
 		tst		\rx, #1
 		moveq		\rx, \tmp1
@@ -151,6 +151,8 @@
 		b	printascii
 ENDPROC(printhex2)
 
+hexbuf:		.space 16
+
 		.ltorg
 
 ENTRY(printascii)
@@ -175,5 +177,3 @@
 		mov	r0, #0
 		b	1b
 ENDPROC(printch)
-
-hexbuf:		.space 16
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/devtree.c linux-libre-3.2-gnu/arch/arm/kernel/devtree.c
--- linux-libre-3.1-gnu/arch/arm/kernel/devtree.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/devtree.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/bootmem.h>
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/dma.c linux-libre-3.2-gnu/arch/arm/kernel/dma.c
--- linux-libre-3.1-gnu/arch/arm/kernel/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,7 @@
 
 #include <asm/mach/dma.h>
 
-DEFINE_SPINLOCK(dma_spin_lock);
+DEFINE_RAW_SPINLOCK(dma_spin_lock);
 EXPORT_SYMBOL(dma_spin_lock);
 
 static dma_t *dma_chan[MAX_DMA_CHANNELS];
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/ecard.c linux-libre-3.2-gnu/arch/arm/kernel/ecard.c
--- linux-libre-3.1-gnu/arch/arm/kernel/ecard.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/ecard.c	2012-01-04 18:55:44.000000000 -0500
@@ -237,7 +237,7 @@
 
 	memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (IO_SIZE / PGDIR_SIZE));
 
-	src_pgd = pgd_offset(mm, EASI_BASE);
+	src_pgd = pgd_offset(mm, (unsigned long)EASI_BASE);
 	dst_pgd = pgd_offset(mm, EASI_START);
 
 	memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (EASI_SIZE / PGDIR_SIZE));
@@ -674,44 +674,37 @@
 #define ecard_probeirqhw() (0)
 #endif
 
-#ifndef IO_EC_MEMC8_BASE
-#define IO_EC_MEMC8_BASE 0
-#endif
-
-static unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
+static void __iomem *__ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
 {
-	unsigned long address = 0;
+	void __iomem *address = NULL;
 	int slot = ec->slot_no;
 
 	if (ec->slot_no == 8)
-		return IO_EC_MEMC8_BASE;
+		return ECARD_MEMC8_BASE;
 
 	ectcr &= ~(1 << slot);
 
 	switch (type) {
 	case ECARD_MEMC:
 		if (slot < 4)
-			address = IO_EC_MEMC_BASE + (slot << 12);
+			address = ECARD_MEMC_BASE + (slot << 14);
 		break;
 
 	case ECARD_IOC:
 		if (slot < 4)
-			address = IO_EC_IOC_BASE + (slot << 12);
-#ifdef IO_EC_IOC4_BASE
+			address = ECARD_IOC_BASE + (slot << 14);
 		else
-			address = IO_EC_IOC4_BASE + ((slot - 4) << 12);
-#endif
+			address = ECARD_IOC4_BASE + ((slot - 4) << 14);
 		if (address)
-			address +=  speed << 17;
+			address += speed << 19;
 		break;
 
-#ifdef IO_EC_EASI_BASE
 	case ECARD_EASI:
-		address = IO_EC_EASI_BASE + (slot << 22);
+		address = ECARD_EASI_BASE + (slot << 24);
 		if (speed == ECARD_FAST)
 			ectcr |= 1 << slot;
 		break;
-#endif
+
 	default:
 		break;
 	}
@@ -990,6 +983,7 @@
 	ecard_t **ecp;
 	ecard_t *ec;
 	struct ex_ecid cid;
+	void __iomem *addr;
 	int i, rc;
 
 	ec = ecard_alloc_card(type, slot);
@@ -999,7 +993,7 @@
 	}
 
 	rc = -ENODEV;
-	if ((ec->podaddr = __ecard_address(ec, type, ECARD_SYNC)) == 0)
+	if ((addr = __ecard_address(ec, type, ECARD_SYNC)) == NULL)
 		goto nodev;
 
 	cid.r_zero = 1;
@@ -1019,7 +1013,7 @@
 	ec->cid.fiqmask = cid.r_fiqmask;
 	ec->cid.fiqoff  = ecard_gets24(cid.r_fiqoff);
 	ec->fiqaddr	=
-	ec->irqaddr	= (void __iomem *)ioaddr(ec->podaddr);
+	ec->irqaddr	= addr;
 
 	if (ec->cid.is) {
 		ec->irqmask = ec->cid.irqmask;
@@ -1048,10 +1042,8 @@
 		set_irq_flags(ec->irq, IRQF_VALID);
 	}
 
-#ifdef IO_EC_MEMC8_BASE
 	if (slot == 8)
 		ec->irq = 11;
-#endif
 #ifdef CONFIG_ARCH_RPC
 	/* On RiscPC, only first two slots have DMA capability */
 	if (slot < 2)
@@ -1097,9 +1089,7 @@
 			ecard_probe(slot, ECARD_IOC);
 	}
 
-#ifdef IO_EC_MEMC8_BASE
 	ecard_probe(8, ECARD_IOC);
-#endif
 
 	irqhw = ecard_probeirqhw();
 
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/elf.c linux-libre-3.2-gnu/arch/arm/kernel/elf.c
--- linux-libre-3.1-gnu/arch/arm/kernel/elf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/elf.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/personality.h>
 #include <linux/binfmts.h>
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/entry-armv.S linux-libre-3.2-gnu/arch/arm/kernel/entry-armv.S
--- linux-libre-3.1-gnu/arch/arm/kernel/entry-armv.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/entry-armv.S	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <asm/unwind.h>
 #include <asm/unistd.h>
 #include <asm/tls.h>
+#include <asm/system.h>
 
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
@@ -262,8 +263,7 @@
 	ldr	r0, [r4, #-4]
 #else
 	ldrh	r0, [r4, #-2]			@ Thumb instruction at LR - 2
-	and	r9, r0, #0xf800
-	cmp	r9, #0xe800			@ 32-bit instruction if xx >= 0
+	cmp	r0, #0xe800			@ 32-bit instruction if xx >= 0
 	ldrhhs	r9, [r4]			@ bottom 16 bits
 	orrhs	r0, r9, r0, lsl #16
 #endif
@@ -440,18 +440,46 @@
 #endif
 	beq	call_fpe
 	@ Thumb instruction
-#if __LINUX_ARM_ARCH__ >= 7
+#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7
+/*
+ * Thumb-2 instruction handling.  Note that because pre-v6 and >= v6 platforms
+ * can never be supported in a single kernel, this code is not applicable at
+ * all when __LINUX_ARM_ARCH__ < 6.  This allows simplifying assumptions to be
+ * made about .arch directives.
+ */
+#if __LINUX_ARM_ARCH__ < 7
+/* If the target CPU may not be Thumb-2-capable, a run-time check is needed: */
+#define NEED_CPU_ARCHITECTURE
+	ldr	r5, .LCcpu_architecture
+	ldr	r5, [r5]
+	cmp	r5, #CPU_ARCH_ARMv7
+	blo	__und_usr_unknown
+/*
+ * The following code won't get run unless the running CPU really is v7, so
+ * coding round the lack of ldrht on older arches is pointless.  Temporarily
+ * override the assembler target arch with the minimum required instead:
+ */
+	.arch	armv6t2
+#endif
 2:
  ARM(	ldrht	r5, [r4], #2	)
  THUMB(	ldrht	r5, [r4]	)
  THUMB(	add	r4, r4, #2	)
-	and	r0, r5, #0xf800			@ mask bits 111x x... .... ....
-	cmp	r0, #0xe800			@ 32bit instruction if xx != 0
+	cmp	r5, #0xe800			@ 32bit instruction if xx != 0
 	blo	__und_usr_unknown
 3:	ldrht	r0, [r4]
 	add	r2, r2, #2			@ r2 is PC + 2, make it PC + 4
 	orr	r0, r0, r5, lsl #16
+
+#if __LINUX_ARM_ARCH__ < 7
+/* If the target arch was overridden, change it back: */
+#ifdef CONFIG_CPU_32v6K
+	.arch	armv6k
 #else
+	.arch	armv6
+#endif
+#endif /* __LINUX_ARM_ARCH__ < 7 */
+#else /* !(CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7) */
 	b	__und_usr_unknown
 #endif
  UNWIND(.fnend		)
@@ -469,7 +497,7 @@
 	.popsection
 	.pushsection __ex_table,"a"
 	.long	1b, 4b
-#if __LINUX_ARM_ARCH__ >= 7
+#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7
 	.long	2b, 4b
 	.long	3b, 4b
 #endif
@@ -578,6 +606,12 @@
 	movw_pc	lr				@ CP#14 (Debug)
 	movw_pc	lr				@ CP#15 (Control)
 
+#ifdef NEED_CPU_ARCHITECTURE
+	.align	2
+.LCcpu_architecture:
+	.word	__cpu_architecture
+#endif
+
 #ifdef CONFIG_NEON
 	.align	6
 
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/etm.c linux-libre-3.2-gnu/arch/arm/kernel/etm.c
--- linux-libre-3.1-gnu/arch/arm/kernel/etm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/etm.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/miscdevice.h>
 #include <linux/vmalloc.h>
 #include <linux/mutex.h>
+#include <linux/module.h>
 #include <asm/hardware/coresight.h>
 #include <asm/sections.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/head.S linux-libre-3.2-gnu/arch/arm/kernel/head.S
--- linux-libre-3.1-gnu/arch/arm/kernel/head.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/head.S	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <asm/memory.h>
 #include <asm/thread_info.h>
 #include <asm/system.h>
+#include <asm/pgtable.h>
 
 #ifdef CONFIG_DEBUG_LL
 #include <mach/debug-macro.S>
@@ -38,11 +39,14 @@
 #error KERNEL_RAM_VADDR must start at 0xXXXX8000
 #endif
 
+#define PG_DIR_SIZE	0x4000
+#define PMD_ORDER	2
+
 	.globl	swapper_pg_dir
-	.equ	swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000
+	.equ	swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE
 
 	.macro	pgtbl, rd, phys
-	add	\rd, \phys, #TEXT_OFFSET - 0x4000
+	add	\rd, \phys, #TEXT_OFFSET - PG_DIR_SIZE
 	.endm
 
 #ifdef CONFIG_XIP_KERNEL
@@ -95,7 +99,7 @@
 	sub	r4, r3, r4			@ (PHYS_OFFSET - PAGE_OFFSET)
 	add	r8, r8, r4			@ PHYS_OFFSET
 #else
-	ldr	r8, =PLAT_PHYS_OFFSET
+	ldr	r8, =PHYS_OFFSET		@ always constant in this case
 #endif
 
 	/*
@@ -148,11 +152,11 @@
 	pgtbl	r4, r8				@ page table address
 
 	/*
-	 * Clear the 16K level 1 swapper page table
+	 * Clear the swapper page table
 	 */
 	mov	r0, r4
 	mov	r3, #0
-	add	r6, r0, #0x4000
+	add	r6, r0, #PG_DIR_SIZE
 1:	str	r3, [r0], #4
 	str	r3, [r0], #4
 	str	r3, [r0], #4
@@ -171,30 +175,30 @@
 	sub	r0, r0, r3			@ virt->phys offset
 	add	r5, r5, r0			@ phys __enable_mmu
 	add	r6, r6, r0			@ phys __enable_mmu_end
-	mov	r5, r5, lsr #20
-	mov	r6, r6, lsr #20
+	mov	r5, r5, lsr #SECTION_SHIFT
+	mov	r6, r6, lsr #SECTION_SHIFT
 
-1:	orr	r3, r7, r5, lsl #20		@ flags + kernel base
-	str	r3, [r4, r5, lsl #2]		@ identity mapping
-	teq	r5, r6
-	addne	r5, r5, #1			@ next section
-	bne	1b
+1:	orr	r3, r7, r5, lsl #SECTION_SHIFT	@ flags + kernel base
+	str	r3, [r4, r5, lsl #PMD_ORDER]	@ identity mapping
+	cmp	r5, r6
+	addlo	r5, r5, #1			@ next section
+	blo	1b
 
 	/*
 	 * Now setup the pagetables for our kernel direct
 	 * mapped region.
 	 */
 	mov	r3, pc
-	mov	r3, r3, lsr #20
-	orr	r3, r7, r3, lsl #20
-	add	r0, r4,  #(KERNEL_START & 0xff000000) >> 18
-	str	r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]!
+	mov	r3, r3, lsr #SECTION_SHIFT
+	orr	r3, r7, r3, lsl #SECTION_SHIFT
+	add	r0, r4,  #(KERNEL_START & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER)
+	str	r3, [r0, #((KERNEL_START & 0x00f00000) >> SECTION_SHIFT) << PMD_ORDER]!
 	ldr	r6, =(KERNEL_END - 1)
-	add	r0, r0, #4
-	add	r6, r4, r6, lsr #18
+	add	r0, r0, #1 << PMD_ORDER
+	add	r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER)
 1:	cmp	r0, r6
-	add	r3, r3, #1 << 20
-	strls	r3, [r0], #4
+	add	r3, r3, #1 << SECTION_SHIFT
+	strls	r3, [r0], #1 << PMD_ORDER
 	bls	1b
 
 #ifdef CONFIG_XIP_KERNEL
@@ -203,11 +207,11 @@
 	 */
 	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]!
+	add	r0, r4,  #(KERNEL_RAM_VADDR & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER)
+	str	r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> (SECTION_SHIFT - PMD_ORDER)]!
 	ldr	r6, =(_end - 1)
 	add	r0, r0, #4
-	add	r6, r4, r6, lsr #18
+	add	r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER)
 1:	cmp	r0, r6
 	add	r3, r3, #1 << 20
 	strls	r3, [r0], #4
@@ -218,12 +222,12 @@
 	 * Then map boot params address in r2 or
 	 * the first 1MB of ram if boot params address is not specified.
 	 */
-	mov	r0, r2, lsr #20
-	movs	r0, r0, lsl #20
+	mov	r0, r2, lsr #SECTION_SHIFT
+	movs	r0, r0, lsl #SECTION_SHIFT
 	moveq	r0, r8
 	sub	r3, r0, r8
 	add	r3, r3, #PAGE_OFFSET
-	add	r3, r4, r3, lsr #18
+	add	r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER)
 	orr	r6, r7, r0
 	str	r6, [r3]
 
@@ -234,23 +238,23 @@
 	 * This allows debug messages to be output
 	 * via a serial console before paging_init.
 	 */
-	addruart r7, r3
+	addruart r7, r3, r0
 
-	mov	r3, r3, lsr #20
-	mov	r3, r3, lsl #2
+	mov	r3, r3, lsr #SECTION_SHIFT
+	mov	r3, r3, lsl #PMD_ORDER
 
 	add	r0, r4, r3
 	rsb	r3, r3, #0x4000			@ PTRS_PER_PGD*sizeof(long)
 	cmp	r3, #0x0800			@ limit to 512MB
 	movhi	r3, #0x0800
 	add	r6, r0, r3
-	mov	r3, r7, lsr #20
+	mov	r3, r7, lsr #SECTION_SHIFT
 	ldr	r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
-	orr	r3, r7, r3, lsl #20
+	orr	r3, r7, r3, lsl #SECTION_SHIFT
 1:	str	r3, [r0], #4
-	add	r3, r3, #1 << 20
-	teq	r0, r6
-	bne	1b
+	add	r3, r3, #1 << SECTION_SHIFT
+	cmp	r0, r6
+	blo	1b
 
 #else /* CONFIG_DEBUG_ICEDCC */
 	/* we don't need any serial debugging mappings for ICEDCC */
@@ -262,7 +266,7 @@
 	 * If we're using the NetWinder or CATS, we also need to map
 	 * in the 16550-type serial port for the debug messages
 	 */
-	add	r0, r4, #0xff000000 >> 18
+	add	r0, r4, #0xff000000 >> (SECTION_SHIFT - PMD_ORDER)
 	orr	r3, r7, #0x7c000000
 	str	r3, [r0]
 #endif
@@ -272,10 +276,10 @@
 	 * Similar reasons here - for debug.  This is
 	 * only for Acorn RiscPC architectures.
 	 */
-	add	r0, r4, #0x02000000 >> 18
+	add	r0, r4, #0x02000000 >> (SECTION_SHIFT - PMD_ORDER)
 	orr	r3, r7, #0x02000000
 	str	r3, [r0]
-	add	r0, r4, #0xd8000000 >> 18
+	add	r0, r4, #0xd8000000 >> (SECTION_SHIFT - PMD_ORDER)
 	str	r3, [r0]
 #endif
 #endif
@@ -356,7 +360,7 @@
  *  r13 = *virtual* address to jump to upon completion
  */
 __enable_mmu:
-#ifdef CONFIG_ALIGNMENT_TRAP
+#if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6
 	orr	r0, r0, #CR_A
 #else
 	bic	r0, r0, #CR_A
@@ -488,13 +492,8 @@
 	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
@@ -510,20 +509,8 @@
 	.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
+	lsls	r6, #24
+	beq	2f
 	clz	r7, r6
 	lsr	r6, #24
 	lsl	r6, r7
@@ -532,43 +519,25 @@
 	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]
+	b	2f
+1:	add     r7, r3
+	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
+	orr	ip, r6	@ mask in offset bits 31-24
 	strh	ip, [r7, #2]
-4:	cmp	r4, r5
+2:	cmp	r4, r5
 	ldrcc	r7, [r4], #4	@ use branch for delay slot
-	bcc	2b
+	bcc	1b
 	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]
+	b	2f
+1:	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
+	orr	ip, ip, r6	@ mask in offset bits 31-24
 	str	ip, [r7, r3]
-3:	cmp	r4, r5
+2:	cmp	r4, r5
 	ldrcc	r7, [r4], #4	@ use branch for delay slot
-	bcc	2b
+	bcc	1b
 	mov	pc, lr
 #endif
 ENDPROC(__fixup_a_pv_table)
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/hw_breakpoint.c linux-libre-3.2-gnu/arch/arm/kernel/hw_breakpoint.c
--- linux-libre-3.1-gnu/arch/arm/kernel/hw_breakpoint.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/hw_breakpoint.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,7 +45,6 @@
 
 /* Number of BRP/WRP registers on this CPU. */
 static int core_num_brps;
-static int core_num_reserved_brps;
 static int core_num_wrps;
 
 /* Debug architecture version. */
@@ -137,10 +136,11 @@
 	u32 didr;
 
 	/* Do we implement the extended CPUID interface? */
-	if (WARN_ONCE((((read_cpuid_id() >> 16) & 0xf) != 0xf),
-	    "CPUID feature registers not supported. "
-	    "Assuming v6 debug is present.\n"))
+	if (((read_cpuid_id() >> 16) & 0xf) != 0xf) {
+		pr_warning("CPUID feature registers not supported. "
+			   "Assuming v6 debug is present.\n");
 		return ARM_DEBUG_ARCH_V6;
+	}
 
 	ARM_DBG_READ(c0, 0, didr);
 	return (didr >> 16) & 0xf;
@@ -154,10 +154,21 @@
 static int debug_arch_supported(void)
 {
 	u8 arch = get_debug_arch();
-	return arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14;
+
+	/* We don't support the memory-mapped interface. */
+	return (arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14) ||
+		arch >= ARM_DEBUG_ARCH_V7_1;
 }
 
-/* Determine number of BRP register available. */
+/* Determine number of WRP registers available. */
+static int get_num_wrp_resources(void)
+{
+	u32 didr;
+	ARM_DBG_READ(c0, 0, didr);
+	return ((didr >> 28) & 0xf) + 1;
+}
+
+/* Determine number of BRP registers available. */
 static int get_num_brp_resources(void)
 {
 	u32 didr;
@@ -176,9 +187,10 @@
 static int get_num_wrps(void)
 {
 	/*
-	 * FIXME: When a watchpoint fires, the only way to work out which
-	 * watchpoint it was is by disassembling the faulting instruction
-	 * and working out the address of the memory access.
+	 * On debug architectures prior to 7.1, when a watchpoint fires, the
+	 * only way to work out which watchpoint it was is by disassembling
+	 * the faulting instruction and working out the address of the memory
+	 * access.
 	 *
 	 * Furthermore, we can only do this if the watchpoint was precise
 	 * since imprecise watchpoints prevent us from calculating register
@@ -192,36 +204,17 @@
 	 * [the ARM ARM states that the DFAR is UNKNOWN, but experience shows
 	 * that it is set on some implementations].
 	 */
+	if (get_debug_arch() < ARM_DEBUG_ARCH_V7_1)
+		return 1;
 
-#if 0
-	int wrps;
-	u32 didr;
-	ARM_DBG_READ(c0, 0, didr);
-	wrps = ((didr >> 28) & 0xf) + 1;
-#endif
-	int wrps = 1;
-
-	if (core_has_mismatch_brps() && wrps >= get_num_brp_resources())
-		wrps = get_num_brp_resources() - 1;
-
-	return wrps;
-}
-
-/* We reserve one breakpoint for each watchpoint. */
-static int get_num_reserved_brps(void)
-{
-	if (core_has_mismatch_brps())
-		return get_num_wrps();
-	return 0;
+	return get_num_wrp_resources();
 }
 
 /* Determine number of usable BRPs available. */
 static int get_num_brps(void)
 {
 	int brps = get_num_brp_resources();
-	if (core_has_mismatch_brps())
-		brps -= get_num_reserved_brps();
-	return brps;
+	return core_has_mismatch_brps() ? brps - 1 : brps;
 }
 
 /*
@@ -239,7 +232,7 @@
 
 	/* Ensure that halting mode is disabled. */
 	if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN,
-			"halting debug mode enabled. Unable to access hardware resources.\n")) {
+		"halting debug mode enabled. Unable to access hardware resources.\n")) {
 		ret = -EPERM;
 		goto out;
 	}
@@ -255,6 +248,7 @@
 		ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN));
 		break;
 	case ARM_DEBUG_ARCH_V7_ECP14:
+	case ARM_DEBUG_ARCH_V7_1:
 		ARM_DBG_WRITE(c2, 2, (dscr | ARM_DSCR_MDBGEN));
 		break;
 	default:
@@ -346,24 +340,10 @@
 		val_base = ARM_BASE_BVR;
 		slots = (struct perf_event **)__get_cpu_var(bp_on_reg);
 		max_slots = core_num_brps;
-		if (info->step_ctrl.enabled) {
-			/* Override the breakpoint data with the step data. */
-			addr = info->trigger & ~0x3;
-			ctrl = encode_ctrl_reg(info->step_ctrl);
-		}
 	} else {
 		/* Watchpoint */
-		if (info->step_ctrl.enabled) {
-			/* Install into the reserved breakpoint region. */
-			ctrl_base = ARM_BASE_BCR + core_num_brps;
-			val_base = ARM_BASE_BVR + core_num_brps;
-			/* Override the watchpoint data with the step data. */
-			addr = info->trigger & ~0x3;
-			ctrl = encode_ctrl_reg(info->step_ctrl);
-		} else {
-			ctrl_base = ARM_BASE_WCR;
-			val_base = ARM_BASE_WVR;
-		}
+		ctrl_base = ARM_BASE_WCR;
+		val_base = ARM_BASE_WVR;
 		slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
 		max_slots = core_num_wrps;
 	}
@@ -382,6 +362,17 @@
 		goto out;
 	}
 
+	/* Override the breakpoint data with the step data. */
+	if (info->step_ctrl.enabled) {
+		addr = info->trigger & ~0x3;
+		ctrl = encode_ctrl_reg(info->step_ctrl);
+		if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE) {
+			i = 0;
+			ctrl_base = ARM_BASE_BCR + core_num_brps;
+			val_base = ARM_BASE_BVR + core_num_brps;
+		}
+	}
+
 	/* Setup the address register. */
 	write_wb_reg(val_base + i, addr);
 
@@ -405,10 +396,7 @@
 		max_slots = core_num_brps;
 	} else {
 		/* Watchpoint */
-		if (info->step_ctrl.enabled)
-			base = ARM_BASE_BCR + core_num_brps;
-		else
-			base = ARM_BASE_WCR;
+		base = ARM_BASE_WCR;
 		slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
 		max_slots = core_num_wrps;
 	}
@@ -426,6 +414,13 @@
 	if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n"))
 		return;
 
+	/* Ensure that we disable the mismatch breakpoint. */
+	if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE &&
+	    info->step_ctrl.enabled) {
+		i = 0;
+		base = ARM_BASE_BCR + core_num_brps;
+	}
+
 	/* Reset the control register. */
 	write_wb_reg(base + i, 0);
 }
@@ -632,10 +627,9 @@
 	 * we can use the mismatch feature as a poor-man's hardware
 	 * single-step, but this only works for per-task breakpoints.
 	 */
-	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\n")) {
+	if (!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) ||
+	    !core_has_mismatch_brps() || !bp->hw.bp_target)) {
+		pr_warning("overflow handler required but none found\n");
 		ret = -EINVAL;
 	}
 out:
@@ -666,34 +660,62 @@
 	arch_install_hw_breakpoint(bp);
 }
 
-static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs)
+static void watchpoint_handler(unsigned long addr, unsigned int fsr,
+			       struct pt_regs *regs)
 {
-	int i;
+	int i, access;
+	u32 val, ctrl_reg, alignment_mask;
 	struct perf_event *wp, **slots;
 	struct arch_hw_breakpoint *info;
+	struct arch_hw_breakpoint_ctrl ctrl;
 
 	slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
 
-	/* Without a disassembler, we can only handle 1 watchpoint. */
-	BUG_ON(core_num_wrps > 1);
-
 	for (i = 0; i < core_num_wrps; ++i) {
 		rcu_read_lock();
 
 		wp = slots[i];
 
-		if (wp == NULL) {
-			rcu_read_unlock();
-			continue;
-		}
+		if (wp == NULL)
+			goto unlock;
 
+		info = counter_arch_bp(wp);
 		/*
-		 * The DFAR is an unknown value. Since we only allow a
-		 * single watchpoint, we can set the trigger to the lowest
-		 * possible faulting address.
+		 * The DFAR is an unknown value on debug architectures prior
+		 * to 7.1. Since we only allow a single watchpoint on these
+		 * older CPUs, we can set the trigger to the lowest possible
+		 * faulting address.
 		 */
-		info = counter_arch_bp(wp);
-		info->trigger = wp->attr.bp_addr;
+		if (debug_arch < ARM_DEBUG_ARCH_V7_1) {
+			BUG_ON(i > 0);
+			info->trigger = wp->attr.bp_addr;
+		} else {
+			if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
+				alignment_mask = 0x7;
+			else
+				alignment_mask = 0x3;
+
+			/* Check if the watchpoint value matches. */
+			val = read_wb_reg(ARM_BASE_WVR + i);
+			if (val != (addr & ~alignment_mask))
+				goto unlock;
+
+			/* Possible match, check the byte address select. */
+			ctrl_reg = read_wb_reg(ARM_BASE_WCR + i);
+			decode_ctrl_reg(ctrl_reg, &ctrl);
+			if (!((1 << (addr & alignment_mask)) & ctrl.len))
+				goto unlock;
+
+			/* Check that the access type matches. */
+			access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W :
+				 HW_BREAKPOINT_R;
+			if (!(access & hw_breakpoint_type(wp)))
+				goto unlock;
+
+			/* We have a winner. */
+			info->trigger = addr;
+		}
+
 		pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
 		perf_bp_event(wp, regs);
 
@@ -705,6 +727,7 @@
 		if (!wp->overflow_handler)
 			enable_single_step(wp, instruction_pointer(regs));
 
+unlock:
 		rcu_read_unlock();
 	}
 }
@@ -717,7 +740,7 @@
 
 	slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
 
-	for (i = 0; i < core_num_reserved_brps; ++i) {
+	for (i = 0; i < core_num_wrps; ++i) {
 		rcu_read_lock();
 
 		wp = slots[i];
@@ -820,7 +843,7 @@
 	case ARM_ENTRY_ASYNC_WATCHPOINT:
 		WARN(1, "Asynchronous watchpoint exception taken. Debugging results may be unreliable\n");
 	case ARM_ENTRY_SYNC_WATCHPOINT:
-		watchpoint_handler(addr, regs);
+		watchpoint_handler(addr, fsr, regs);
 		break;
 	default:
 		ret = 1; /* Unhandled fault. */
@@ -834,11 +857,31 @@
 /*
  * One-time initialisation.
  */
-static void reset_ctrl_regs(void *info)
+static cpumask_t debug_err_mask;
+
+static int debug_reg_trap(struct pt_regs *regs, unsigned int instr)
 {
-	int i, cpu = smp_processor_id();
+	int cpu = smp_processor_id();
+
+	pr_warning("Debug register access (0x%x) caused undefined instruction on CPU %d\n",
+		   instr, cpu);
+
+	/* Set the error flag for this CPU and skip the faulting instruction. */
+	cpumask_set_cpu(cpu, &debug_err_mask);
+	instruction_pointer(regs) += 4;
+	return 0;
+}
+
+static struct undef_hook debug_reg_hook = {
+	.instr_mask	= 0x0fe80f10,
+	.instr_val	= 0x0e000e10,
+	.fn		= debug_reg_trap,
+};
+
+static void reset_ctrl_regs(void *unused)
+{
+	int i, raw_num_brps, err = 0, cpu = smp_processor_id();
 	u32 dbg_power;
-	cpumask_t *cpumask = info;
 
 	/*
 	 * v7 debug contains save and restore registers so that debug state
@@ -848,38 +891,57 @@
 	 * Access Register to avoid taking undefined instruction exceptions
 	 * later on.
 	 */
-	if (debug_arch >= ARM_DEBUG_ARCH_V7_ECP14) {
+	switch (debug_arch) {
+	case ARM_DEBUG_ARCH_V6:
+	case ARM_DEBUG_ARCH_V6_1:
+		/* ARMv6 cores just need to reset the registers. */
+		goto reset_regs;
+	case ARM_DEBUG_ARCH_V7_ECP14:
 		/*
 		 * Ensure sticky power-down is clear (i.e. debug logic is
 		 * powered up).
 		 */
 		asm volatile("mrc p14, 0, %0, c1, c5, 4" : "=r" (dbg_power));
-		if ((dbg_power & 0x1) == 0) {
-			pr_warning("CPU %d debug is powered down!\n", cpu);
-			cpumask_or(cpumask, cpumask, cpumask_of(cpu));
-			return;
-		}
-
+		if ((dbg_power & 0x1) == 0)
+			err = -EPERM;
+		break;
+	case ARM_DEBUG_ARCH_V7_1:
 		/*
-		 * Unconditionally clear the lock by writing a value
-		 * other than 0xC5ACCE55 to the access register.
+		 * Ensure the OS double lock is clear.
 		 */
-		asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));
-		isb();
+		asm volatile("mrc p14, 0, %0, c1, c3, 4" : "=r" (dbg_power));
+		if ((dbg_power & 0x1) == 1)
+			err = -EPERM;
+		break;
+	}
 
-		/*
-		 * Clear any configured vector-catch events before
-		 * enabling monitor mode.
-		 */
-		asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0));
-		isb();
+	if (err) {
+		pr_warning("CPU %d debug is powered down!\n", cpu);
+		cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu));
+		return;
 	}
 
+	/*
+	 * Unconditionally clear the lock by writing a value
+	 * other than 0xC5ACCE55 to the access register.
+	 */
+	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();
+
+reset_regs:
 	if (enable_monitor_mode())
 		return;
 
 	/* We must also reset any reserved registers. */
-	for (i = 0; i < core_num_brps + core_num_reserved_brps; ++i) {
+	raw_num_brps = get_num_brp_resources();
+	for (i = 0; i < raw_num_brps; ++i) {
 		write_wb_reg(ARM_BASE_BCR + i, 0UL);
 		write_wb_reg(ARM_BASE_BVR + i, 0UL);
 	}
@@ -895,6 +957,7 @@
 {
 	if (action == CPU_ONLINE)
 		smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1);
+
 	return NOTIFY_OK;
 }
 
@@ -905,7 +968,6 @@
 static int __init arch_hw_breakpoint_init(void)
 {
 	u32 dscr;
-	cpumask_t cpumask = { CPU_BITS_NONE };
 
 	debug_arch = get_debug_arch();
 
@@ -916,28 +978,31 @@
 
 	/* Determine how many BRPs/WRPs are available. */
 	core_num_brps = get_num_brps();
-	core_num_reserved_brps = get_num_reserved_brps();
 	core_num_wrps = get_num_wrps();
 
-	pr_info("found %d breakpoint and %d watchpoint registers.\n",
-		core_num_brps + core_num_reserved_brps, core_num_wrps);
-
-	if (core_num_reserved_brps)
-		pr_info("%d breakpoint(s) reserved for watchpoint "
-				"single-step.\n", core_num_reserved_brps);
+	/*
+	 * We need to tread carefully here because DBGSWENABLE may be
+	 * driven low on this core and there isn't an architected way to
+	 * determine that.
+	 */
+	register_undef_hook(&debug_reg_hook);
 
 	/*
 	 * Reset the breakpoint resources. We assume that a halting
 	 * debugger will leave the world in a nice state for us.
 	 */
-	on_each_cpu(reset_ctrl_regs, &cpumask, 1);
-	if (!cpumask_empty(&cpumask)) {
+	on_each_cpu(reset_ctrl_regs, NULL, 1);
+	unregister_undef_hook(&debug_reg_hook);
+	if (!cpumask_empty(&debug_err_mask)) {
 		core_num_brps = 0;
-		core_num_reserved_brps = 0;
 		core_num_wrps = 0;
 		return 0;
 	}
 
+	pr_info("found %d " "%s" "breakpoint and %d watchpoint registers.\n",
+		core_num_brps, core_has_mismatch_brps() ? "(+1 reserved) " :
+		"", core_num_wrps);
+
 	ARM_DBG_READ(c1, 0, dscr);
 	if (dscr & ARM_DSCR_HDBGEN) {
 		max_watchpoint_len = 4;
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/io.c linux-libre-3.2-gnu/arch/arm/kernel/io.c
--- linux-libre-3.1-gnu/arch/arm/kernel/io.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/io.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/irq.c linux-libre-3.2-gnu/arch/arm/kernel/irq.c
--- linux-libre-3.1-gnu/arch/arm/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,6 @@
  *  Naturally it's not a 1:1 relation, but there are similarities.
  */
 #include <linux/kernel_stat.h>
-#include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
@@ -35,8 +34,8 @@
 #include <linux/list.h>
 #include <linux/kallsyms.h>
 #include <linux/proc_fs.h>
-#include <linux/ftrace.h>
 
+#include <asm/exception.h>
 #include <asm/system.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
@@ -59,9 +58,6 @@
 #ifdef CONFIG_SMP
 	show_ipi_list(p, prec);
 #endif
-#ifdef CONFIG_LOCAL_TIMERS
-	show_local_irqs(p, prec);
-#endif
 	seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/kprobes-arm.c linux-libre-3.2-gnu/arch/arm/kernel/kprobes-arm.c
--- linux-libre-3.1-gnu/arch/arm/kernel/kprobes-arm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/kprobes-arm.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,6 +60,7 @@
 
 #include <linux/kernel.h>
 #include <linux/kprobes.h>
+#include <linux/module.h>
 
 #include "kprobes.h"
 
@@ -518,10 +519,12 @@
 static const union decode_item arm_cccc_0001_____1001_table[] = {
 	/* Synchronization primitives					*/
 
+#if __LINUX_ARM_ARCH__ < 6
+	/* Deprecated on ARMv6 and may be UNDEFINED on v7		*/
 	/* SMP/SWPB		cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */
 	DECODE_EMULATEX	(0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc,
 						 REGS(NOPC, NOPC, 0, 0, NOPC)),
-
+#endif
 	/* LDREX/STREX{,D,B,H}	cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */
 	/* And unallocated instructions...				*/
 	DECODE_END
@@ -971,6 +974,9 @@
 
 	DECODE_END
 };
+#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
+EXPORT_SYMBOL_GPL(kprobe_decode_arm_table);
+#endif
 
 static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs)
 {
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/kprobes.h linux-libre-3.2-gnu/arch/arm/kernel/kprobes.h
--- linux-libre-3.1-gnu/arch/arm/kernel/kprobes.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/kprobes.h	2012-01-04 18:55:44.000000000 -0500
@@ -413,6 +413,14 @@
 	DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0)
 
 
+#ifdef CONFIG_THUMB2_KERNEL
+extern const union decode_item kprobe_decode_thumb16_table[];
+extern const union decode_item kprobe_decode_thumb32_table[];
+#else
+extern const union decode_item kprobe_decode_arm_table[];
+#endif
+
+
 int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
 			const union decode_item *table, bool thumb16);
 
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/kprobes-test-arm.c linux-libre-3.2-gnu/arch/arm/kernel/kprobes-test-arm.c
--- linux-libre-3.1-gnu/arch/arm/kernel/kprobes-test-arm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/kernel/kprobes-test-arm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1330 @@
+/*
+ * arch/arm/kernel/kprobes-test-arm.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "kprobes-test.h"
+
+
+#define TEST_ISA "32"
+
+#define TEST_ARM_TO_THUMB_INTERWORK_R(code1, reg, val, code2)	\
+	TESTCASE_START(code1 #reg code2)			\
+	TEST_ARG_REG(reg, val)					\
+	TEST_ARG_REG(14, 99f)					\
+	TEST_ARG_END("")					\
+	"50:	nop			\n\t"			\
+	"1:	"code1 #reg code2"	\n\t"			\
+	"	bx	lr		\n\t"			\
+	".thumb				\n\t"			\
+	"3:	adr	lr, 2f		\n\t"			\
+	"	bx	lr		\n\t"			\
+	".arm				\n\t"			\
+	"2:	nop			\n\t"			\
+	TESTCASE_END
+
+#define TEST_ARM_TO_THUMB_INTERWORK_P(code1, reg, val, code2)	\
+	TESTCASE_START(code1 #reg code2)			\
+	TEST_ARG_PTR(reg, val)					\
+	TEST_ARG_REG(14, 99f)					\
+	TEST_ARG_MEM(15, 3f+1)					\
+	TEST_ARG_END("")					\
+	"50:	nop			\n\t"			\
+	"1:	"code1 #reg code2"	\n\t"			\
+	"	bx	lr		\n\t"			\
+	".thumb				\n\t"			\
+	"3:	adr	lr, 2f		\n\t"			\
+	"	bx	lr		\n\t"			\
+	".arm				\n\t"			\
+	"2:	nop			\n\t"			\
+	TESTCASE_END
+
+
+void kprobe_arm_test_cases(void)
+{
+	kprobe_test_flags = 0;
+
+	TEST_GROUP("Data-processing (register), (register-shifted register), (immediate)")
+
+#define _DATA_PROCESSING_DNM(op,s,val)						\
+	TEST_RR(  op "eq" s "	r0,  r",1, VAL1,", r",2, val, "")		\
+	TEST_RR(  op "ne" s "	r1,  r",1, VAL1,", r",2, val, ", lsl #3")	\
+	TEST_RR(  op "cs" s "	r2,  r",3, VAL1,", r",2, val, ", lsr #4")	\
+	TEST_RR(  op "cc" s "	r3,  r",3, VAL1,", r",2, val, ", asr #5")	\
+	TEST_RR(  op "mi" s "	r4,  r",5, VAL1,", r",2, N(val),", asr #6")	\
+	TEST_RR(  op "pl" s "	r5,  r",5, VAL1,", r",2, val, ", ror #7")	\
+	TEST_RR(  op "vs" s "	r6,  r",7, VAL1,", r",2, val, ", rrx")		\
+	TEST_R(   op "vc" s "	r6,  r",7, VAL1,", pc, lsl #3")			\
+	TEST_R(   op "vc" s "	r6,  r",7, VAL1,", sp, lsr #4")			\
+	TEST_R(   op "vc" s "	r6,  pc, r",7, VAL1,", asr #5")			\
+	TEST_R(   op "vc" s "	r6,  sp, r",7, VAL1,", ror #6")			\
+	TEST_RRR( op "hi" s "	r8,  r",9, VAL1,", r",14,val, ", lsl r",0, 3,"")\
+	TEST_RRR( op "ls" s "	r9,  r",9, VAL1,", r",14,val, ", lsr r",7, 4,"")\
+	TEST_RRR( op "ge" s "	r10, r",11,VAL1,", r",14,val, ", asr r",7, 5,"")\
+	TEST_RRR( op "lt" s "	r11, r",11,VAL1,", r",14,N(val),", asr r",7, 6,"")\
+	TEST_RR(  op "gt" s "	r12, r13"       ", r",14,val, ", ror r",14,7,"")\
+	TEST_RR(  op "le" s "	r14, r",0, val, ", r13"       ", lsl r",14,8,"")\
+	TEST_RR(  op s "	r12, pc"        ", r",14,val, ", ror r",14,7,"")\
+	TEST_RR(  op s "	r14, r",0, val, ", pc"        ", lsl r",14,8,"")\
+	TEST_R(   op "eq" s "	r0,  r",11,VAL1,", #0xf5")			\
+	TEST_R(   op "ne" s "	r11, r",0, VAL1,", #0xf5000000")		\
+	TEST_R(   op s "	r7,  r",8, VAL2,", #0x000af000")		\
+	TEST(     op s "	r4,  pc"        ", #0x00005a00")
+
+#define DATA_PROCESSING_DNM(op,val)		\
+	_DATA_PROCESSING_DNM(op,"",val)		\
+	_DATA_PROCESSING_DNM(op,"s",val)
+
+#define DATA_PROCESSING_NM(op,val)						\
+	TEST_RR(  op "ne	r",1, VAL1,", r",2, val, "")			\
+	TEST_RR(  op "eq	r",1, VAL1,", r",2, val, ", lsl #3")		\
+	TEST_RR(  op "cc	r",3, VAL1,", r",2, val, ", lsr #4")		\
+	TEST_RR(  op "cs	r",3, VAL1,", r",2, val, ", asr #5")		\
+	TEST_RR(  op "pl	r",5, VAL1,", r",2, N(val),", asr #6")		\
+	TEST_RR(  op "mi	r",5, VAL1,", r",2, val, ", ror #7")		\
+	TEST_RR(  op "vc	r",7, VAL1,", r",2, val, ", rrx")		\
+	TEST_R (  op "vs	r",7, VAL1,", pc, lsl #3")			\
+	TEST_R (  op "vs	r",7, VAL1,", sp, lsr #4")			\
+	TEST_R(   op "vs	pc, r",7, VAL1,", asr #5")			\
+	TEST_R(   op "vs	sp, r",7, VAL1,", ror #6")			\
+	TEST_RRR( op "ls	r",9, VAL1,", r",14,val, ", lsl r",0, 3,"")	\
+	TEST_RRR( op "hi	r",9, VAL1,", r",14,val, ", lsr r",7, 4,"")	\
+	TEST_RRR( op "lt	r",11,VAL1,", r",14,val, ", asr r",7, 5,"")	\
+	TEST_RRR( op "ge	r",11,VAL1,", r",14,N(val),", asr r",7, 6,"")	\
+	TEST_RR(  op "le	r13"       ", r",14,val, ", ror r",14,7,"")	\
+	TEST_RR(  op "gt	r",0, val, ", r13"       ", lsl r",14,8,"")	\
+	TEST_RR(  op "	pc"        ", r",14,val, ", ror r",14,7,"")		\
+	TEST_RR(  op "	r",0, val, ", pc"        ", lsl r",14,8,"")		\
+	TEST_R(   op "eq	r",11,VAL1,", #0xf5")				\
+	TEST_R(   op "ne	r",0, VAL1,", #0xf5000000")			\
+	TEST_R(   op "	r",8, VAL2,", #0x000af000")
+
+#define _DATA_PROCESSING_DM(op,s,val)					\
+	TEST_R(   op "eq" s "	r0,  r",1, val, "")			\
+	TEST_R(   op "ne" s "	r1,  r",1, val, ", lsl #3")		\
+	TEST_R(   op "cs" s "	r2,  r",3, val, ", lsr #4")		\
+	TEST_R(   op "cc" s "	r3,  r",3, val, ", asr #5")		\
+	TEST_R(   op "mi" s "	r4,  r",5, N(val),", asr #6")		\
+	TEST_R(   op "pl" s "	r5,  r",5, val, ", ror #7")		\
+	TEST_R(   op "vs" s "	r6,  r",10,val, ", rrx")		\
+	TEST(     op "vs" s "	r7,  pc, lsl #3")			\
+	TEST(     op "vs" s "	r7,  sp, lsr #4")			\
+	TEST_RR(  op "vc" s "	r8,  r",7, val, ", lsl r",0, 3,"")	\
+	TEST_RR(  op "hi" s "	r9,  r",9, val, ", lsr r",7, 4,"")	\
+	TEST_RR(  op "ls" s "	r10, r",9, val, ", asr r",7, 5,"")	\
+	TEST_RR(  op "ge" s "	r11, r",11,N(val),", asr r",7, 6,"")	\
+	TEST_RR(  op "lt" s "	r12, r",11,val, ", ror r",14,7,"")	\
+	TEST_R(   op "gt" s "	r14, r13"       ", lsl r",14,8,"")	\
+	TEST_R(   op "le" s "	r14, pc"        ", lsl r",14,8,"")	\
+	TEST(     op "eq" s "	r0,  #0xf5")				\
+	TEST(     op "ne" s "	r11, #0xf5000000")			\
+	TEST(     op s "	r7,  #0x000af000")			\
+	TEST(     op s "	r4,  #0x00005a00")
+
+#define DATA_PROCESSING_DM(op,val)		\
+	_DATA_PROCESSING_DM(op,"",val)		\
+	_DATA_PROCESSING_DM(op,"s",val)
+
+	DATA_PROCESSING_DNM("and",0xf00f00ff)
+	DATA_PROCESSING_DNM("eor",0xf00f00ff)
+	DATA_PROCESSING_DNM("sub",VAL2)
+	DATA_PROCESSING_DNM("rsb",VAL2)
+	DATA_PROCESSING_DNM("add",VAL2)
+	DATA_PROCESSING_DNM("adc",VAL2)
+	DATA_PROCESSING_DNM("sbc",VAL2)
+	DATA_PROCESSING_DNM("rsc",VAL2)
+	DATA_PROCESSING_NM("tst",0xf00f00ff)
+	DATA_PROCESSING_NM("teq",0xf00f00ff)
+	DATA_PROCESSING_NM("cmp",VAL2)
+	DATA_PROCESSING_NM("cmn",VAL2)
+	DATA_PROCESSING_DNM("orr",0xf00f00ff)
+	DATA_PROCESSING_DM("mov",VAL2)
+	DATA_PROCESSING_DNM("bic",0xf00f00ff)
+	DATA_PROCESSING_DM("mvn",VAL2)
+
+	TEST("mov	ip, sp") /* This has special case emulation code */
+
+	TEST_SUPPORTED("mov	pc, #0x1000");
+	TEST_SUPPORTED("mov	sp, #0x1000");
+	TEST_SUPPORTED("cmp	pc, #0x1000");
+	TEST_SUPPORTED("cmp	sp, #0x1000");
+
+	/* Data-processing with PC as shift*/
+	TEST_UNSUPPORTED(".word 0xe15c0f1e	@ cmp	r12, r14, asl pc")
+	TEST_UNSUPPORTED(".word 0xe1a0cf1e	@ mov	r12, r14, asl pc")
+	TEST_UNSUPPORTED(".word 0xe08caf1e	@ add	r10, r12, r14, asl pc")
+
+	/* Data-processing with PC as shift*/
+	TEST_UNSUPPORTED("movs	pc, r1")
+	TEST_UNSUPPORTED("movs	pc, r1, lsl r2")
+	TEST_UNSUPPORTED("movs	pc, #0x10000")
+	TEST_UNSUPPORTED("adds	pc, lr, r1")
+	TEST_UNSUPPORTED("adds	pc, lr, r1, lsl r2")
+	TEST_UNSUPPORTED("adds	pc, lr, #4")
+
+	/* Data-processing with SP as target */
+	TEST("add	sp, sp, #16")
+	TEST("sub	sp, sp, #8")
+	TEST("bic	sp, sp, #0x20")
+	TEST("orr	sp, sp, #0x20")
+	TEST_PR( "add	sp, r",10,0,", r",11,4,"")
+	TEST_PRR("add	sp, r",10,0,", r",11,4,", asl r",12,1,"")
+	TEST_P(  "mov	sp, r",10,0,"")
+	TEST_PR( "mov	sp, r",10,0,", asl r",12,0,"")
+
+	/* Data-processing with PC as target */
+	TEST_BF(   "add	pc, pc, #2f-1b-8")
+	TEST_BF_R ("add	pc, pc, r",14,2f-1f-8,"")
+	TEST_BF_R ("add	pc, r",14,2f-1f-8,", pc")
+	TEST_BF_R ("mov	pc, r",0,2f,"")
+	TEST_BF_RR("mov	pc, r",0,2f,", asl r",1,0,"")
+	TEST_BB(   "sub	pc, pc, #1b-2b+8")
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_BB(   "sub	pc, pc, #1b-2b+8-2") /* UNPREDICTABLE before ARMv6 */
+#endif
+	TEST_BB_R( "sub	pc, pc, r",14, 1f-2f+8,"")
+	TEST_BB_R( "rsb	pc, r",14,1f-2f+8,", pc")
+	TEST_RR(   "add	pc, pc, r",10,-2,", asl r",11,1,"")
+#ifdef CONFIG_THUMB2_KERNEL
+	TEST_ARM_TO_THUMB_INTERWORK_R("add	pc, pc, r",0,3f-1f-8+1,"")
+	TEST_ARM_TO_THUMB_INTERWORK_R("sub	pc, r",0,3f+8+1,", #8")
+#endif
+	TEST_GROUP("Miscellaneous instructions")
+
+	TEST("mrs	r0, cpsr")
+	TEST("mrspl	r7, cpsr")
+	TEST("mrs	r14, cpsr")
+	TEST_UNSUPPORTED(".word 0xe10ff000	@ mrs r15, cpsr")
+	TEST_UNSUPPORTED("mrs	r0, spsr")
+	TEST_UNSUPPORTED("mrs	lr, spsr")
+
+	TEST_UNSUPPORTED("msr	cpsr, r0")
+	TEST_UNSUPPORTED("msr	cpsr_f, lr")
+	TEST_UNSUPPORTED("msr	spsr, r0")
+
+	TEST_BF_R("bx	r",0,2f,"")
+	TEST_BB_R("bx	r",7,2f,"")
+	TEST_BF_R("bxeq	r",14,2f,"")
+
+	TEST_R("clz	r0, r",0, 0x0,"")
+	TEST_R("clzeq	r7, r",14,0x1,"")
+	TEST_R("clz	lr, r",7, 0xffffffff,"")
+	TEST(  "clz	r4, sp")
+	TEST_UNSUPPORTED(".word 0x016fff10	@ clz pc, r0")
+	TEST_UNSUPPORTED(".word 0x016f0f1f	@ clz r0, pc")
+
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_UNSUPPORTED("bxj	r0")
+#endif
+
+	TEST_BF_R("blx	r",0,2f,"")
+	TEST_BB_R("blx	r",7,2f,"")
+	TEST_BF_R("blxeq	r",14,2f,"")
+	TEST_UNSUPPORTED(".word 0x0120003f	@ blx pc")
+
+	TEST_RR(   "qadd	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(   "qaddvs	lr, r",9, VAL2,", r",8, VAL1,"")
+	TEST_R(    "qadd	lr, r",9, VAL2,", r13")
+	TEST_RR(   "qsub	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(   "qsubvs	lr, r",9, VAL2,", r",8, VAL1,"")
+	TEST_R(    "qsub	lr, r",9, VAL2,", r13")
+	TEST_RR(   "qdadd	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(   "qdaddvs	lr, r",9, VAL2,", r",8, VAL1,"")
+	TEST_R(    "qdadd	lr, r",9, VAL2,", r13")
+	TEST_RR(   "qdsub	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(   "qdsubvs	lr, r",9, VAL2,", r",8, VAL1,"")
+	TEST_R(    "qdsub	lr, r",9, VAL2,", r13")
+	TEST_UNSUPPORTED(".word 0xe101f050	@ qadd pc, r0, r1")
+	TEST_UNSUPPORTED(".word 0xe121f050	@ qsub pc, r0, r1")
+	TEST_UNSUPPORTED(".word 0xe141f050	@ qdadd pc, r0, r1")
+	TEST_UNSUPPORTED(".word 0xe161f050	@ qdsub pc, r0, r1")
+	TEST_UNSUPPORTED(".word 0xe16f2050	@ qdsub r2, r0, pc")
+	TEST_UNSUPPORTED(".word 0xe161205f	@ qdsub r2, pc, r1")
+
+	TEST_UNSUPPORTED("bkpt	0xffff")
+	TEST_UNSUPPORTED("bkpt	0x0000")
+
+	TEST_UNSUPPORTED(".word 0xe1600070 @ smc #0")
+
+	TEST_GROUP("Halfword multiply and multiply-accumulate")
+
+	TEST_RRR(    "smlabb	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(    "smlabbge	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(     "smlabb	lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe10f3281 @ smlabb pc, r1, r2, r3")
+	TEST_RRR(    "smlatb	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(    "smlatbge	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(     "smlatb	lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe10f32a1 @ smlatb pc, r1, r2, r3")
+	TEST_RRR(    "smlabt	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(    "smlabtge	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(     "smlabt	lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe10f32c1 @ smlabt pc, r1, r2, r3")
+	TEST_RRR(    "smlatt	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(    "smlattge	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(     "smlatt	lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe10f32e1 @ smlatt pc, r1, r2, r3")
+
+	TEST_RRR(    "smlawb	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(    "smlawbge	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(     "smlawb	lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe12f3281 @ smlawb pc, r1, r2, r3")
+	TEST_RRR(    "smlawt	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(    "smlawtge	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(     "smlawt	lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe12f32c1 @ smlawt pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe12032cf @ smlawt r0, pc, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe1203fc1 @ smlawt r0, r1, pc, r3")
+	TEST_UNSUPPORTED(".word 0xe120f2c1 @ smlawt r0, r1, r2, pc")
+
+	TEST_RR(    "smulwb	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulwbge	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_R(     "smulwb	lr, r",1, VAL2,", r13")
+	TEST_UNSUPPORTED(".word 0xe12f02a1 @ smulwb pc, r1, r2")
+	TEST_RR(    "smulwt	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulwtge	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_R(     "smulwt	lr, r",1, VAL2,", r13")
+	TEST_UNSUPPORTED(".word 0xe12f02e1 @ smulwt pc, r1, r2")
+
+	TEST_RRRR(  "smlalbb	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR(  "smlalbble	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRR(   "smlalbb	r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+	TEST_UNSUPPORTED(".word 0xe14f1382 @ smlalbb pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe141f382 @ smlalbb r1, pc, r2, r3")
+	TEST_RRRR(  "smlaltb	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR(  "smlaltble	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRR(   "smlaltb	r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+	TEST_UNSUPPORTED(".word 0xe14f13a2 @ smlaltb pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe141f3a2 @ smlaltb r1, pc, r2, r3")
+	TEST_RRRR(  "smlalbt	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR(  "smlalbtle	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRR(   "smlalbt	r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+	TEST_UNSUPPORTED(".word 0xe14f13c2 @ smlalbt pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe141f3c2 @ smlalbt r1, pc, r2, r3")
+	TEST_RRRR(  "smlaltt	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR(  "smlalttle	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRR(   "smlaltt	r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+	TEST_UNSUPPORTED(".word 0xe14f13e2 @ smlalbb pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe140f3e2 @ smlalbb r0, pc, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe14013ef @ smlalbb r0, r1, pc, r3")
+	TEST_UNSUPPORTED(".word 0xe1401fe2 @ smlalbb r0, r1, r2, pc")
+
+	TEST_RR(    "smulbb	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulbbge	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_R(     "smulbb	lr, r",1, VAL2,", r13")
+	TEST_UNSUPPORTED(".word 0xe16f0281 @ smulbb pc, r1, r2")
+	TEST_RR(    "smultb	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smultbge	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_R(     "smultb	lr, r",1, VAL2,", r13")
+	TEST_UNSUPPORTED(".word 0xe16f02a1 @ smultb pc, r1, r2")
+	TEST_RR(    "smulbt	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulbtge	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_R(     "smulbt	lr, r",1, VAL2,", r13")
+	TEST_UNSUPPORTED(".word 0xe16f02c1 @ smultb pc, r1, r2")
+	TEST_RR(    "smultt	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulttge	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_R(     "smultt	lr, r",1, VAL2,", r13")
+	TEST_UNSUPPORTED(".word 0xe16f02e1 @ smultt pc, r1, r2")
+	TEST_UNSUPPORTED(".word 0xe16002ef @ smultt r0, pc, r2")
+	TEST_UNSUPPORTED(".word 0xe1600fe1 @ smultt r0, r1, pc")
+
+	TEST_GROUP("Multiply and multiply-accumulate")
+
+	TEST_RR(    "mul	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "mulls	r7, r",8, VAL2,", r",9, VAL2,"")
+	TEST_R(     "mul	lr, r",4, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe00f0291 @ mul pc, r1, r2")
+	TEST_UNSUPPORTED(".word 0xe000029f @ mul r0, pc, r2")
+	TEST_UNSUPPORTED(".word 0xe0000f91 @ mul r0, r1, pc")
+	TEST_RR(    "muls	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "mullss	r7, r",8, VAL2,", r",9, VAL2,"")
+	TEST_R(     "muls	lr, r",4, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe01f0291 @ muls pc, r1, r2")
+
+	TEST_RRR(    "mla	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(    "mlahi	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(     "mla	lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe02f3291 @ mla pc, r1, r2, r3")
+	TEST_RRR(    "mlas	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(    "mlahis	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(     "mlas	lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe03f3291 @ mlas pc, r1, r2, r3")
+
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_RR(  "umaal	r0, r1, r",2, VAL1,", r",3, VAL2,"")
+	TEST_RR(  "umaalls	r7, r8, r",9, VAL2,", r",10, VAL1,"")
+	TEST_R(   "umaal	lr, r12, r",11,VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe041f392 @ umaal pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe04f0392 @ umaal r0, pc, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0500090 @ undef")
+	TEST_UNSUPPORTED(".word 0xe05fff9f @ undef")
+
+	TEST_RRR(  "mls		r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(  "mlshi	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(   "mls		lr, r",1, VAL2,", r",2, VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe06f3291 @ mls pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe060329f @ mls r0, pc, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0603f91 @ mls r0, r1, pc, r3")
+	TEST_UNSUPPORTED(".word 0xe060f291 @ mls r0, r1, r2, pc")
+#endif
+
+	TEST_UNSUPPORTED(".word 0xe0700090 @ undef")
+	TEST_UNSUPPORTED(".word 0xe07fff9f @ undef")
+
+	TEST_RR(  "umull	r0, r1, r",2, VAL1,", r",3, VAL2,"")
+	TEST_RR(  "umullls	r7, r8, r",9, VAL2,", r",10, VAL1,"")
+	TEST_R(   "umull	lr, r12, r",11,VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe081f392 @ umull pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe08f1392 @ umull r1, pc, r2, r3")
+	TEST_RR(  "umulls	r0, r1, r",2, VAL1,", r",3, VAL2,"")
+	TEST_RR(  "umulllss	r7, r8, r",9, VAL2,", r",10, VAL1,"")
+	TEST_R(   "umulls	lr, r12, r",11,VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe091f392 @ umulls pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe09f1392 @ umulls r1, pc, r2, r3")
+
+	TEST_RRRR(  "umlal	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR(  "umlalle	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRR(   "umlal	r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+	TEST_UNSUPPORTED(".word 0xe0af1392 @ umlal pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0a1f392 @ umlal r1, pc, r2, r3")
+	TEST_RRRR(  "umlals	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR(  "umlalles	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRR(   "umlals	r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+	TEST_UNSUPPORTED(".word 0xe0bf1392 @ umlals pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0b1f392 @ umlals r1, pc, r2, r3")
+
+	TEST_RR(  "smull	r0, r1, r",2, VAL1,", r",3, VAL2,"")
+	TEST_RR(  "smullls	r7, r8, r",9, VAL2,", r",10, VAL1,"")
+	TEST_R(   "smull	lr, r12, r",11,VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe0c1f392 @ smull pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0cf1392 @ smull r1, pc, r2, r3")
+	TEST_RR(  "smulls	r0, r1, r",2, VAL1,", r",3, VAL2,"")
+	TEST_RR(  "smulllss	r7, r8, r",9, VAL2,", r",10, VAL1,"")
+	TEST_R(   "smulls	lr, r12, r",11,VAL3,", r13")
+	TEST_UNSUPPORTED(".word 0xe0d1f392 @ smulls pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0df1392 @ smulls r1, pc, r2, r3")
+
+	TEST_RRRR(  "smlal	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR(  "smlalle	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRR(   "smlal	r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+	TEST_UNSUPPORTED(".word 0xe0ef1392 @ smlal pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0e1f392 @ smlal r1, pc, r2, r3")
+	TEST_RRRR(  "smlals	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR(  "smlalles	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRR(   "smlals	r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13")
+	TEST_UNSUPPORTED(".word 0xe0ff1392 @ smlals pc, r1, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0f0f392 @ smlals r0, pc, r2, r3")
+	TEST_UNSUPPORTED(".word 0xe0f0139f @ smlals r0, r1, pc, r3")
+	TEST_UNSUPPORTED(".word 0xe0f01f92 @ smlals r0, r1, r2, pc")
+
+	TEST_GROUP("Synchronization primitives")
+
+#if __LINUX_ARM_ARCH__ < 6
+	TEST_RP("swp	lr, r",7,VAL2,", [r",8,0,"]")
+	TEST_R( "swpvs	r0, r",1,VAL1,", [sp]")
+	TEST_RP("swp	sp, r",14,VAL2,", [r",12,13*4,"]")
+#else
+	TEST_UNSUPPORTED(".word 0xe108e097 @ swp	lr, r7, [r8]")
+	TEST_UNSUPPORTED(".word 0x610d0091 @ swpvs	r0, r1, [sp]")
+	TEST_UNSUPPORTED(".word 0xe10cd09e @ swp	sp, r14 [r12]")
+#endif
+	TEST_UNSUPPORTED(".word 0xe102f091 @ swp pc, r1, [r2]")
+	TEST_UNSUPPORTED(".word 0xe102009f @ swp r0, pc, [r2]")
+	TEST_UNSUPPORTED(".word 0xe10f0091 @ swp r0, r1, [pc]")
+#if __LINUX_ARM_ARCH__ < 6
+	TEST_RP("swpb	lr, r",7,VAL2,", [r",8,0,"]")
+	TEST_R( "swpvsb	r0, r",1,VAL1,", [sp]")
+#else
+	TEST_UNSUPPORTED(".word 0xe148e097 @ swpb	lr, r7, [r8]")
+	TEST_UNSUPPORTED(".word 0x614d0091 @ swpvsb	r0, r1, [sp]")
+#endif
+	TEST_UNSUPPORTED(".word 0xe142f091 @ swpb pc, r1, [r2]")
+
+	TEST_UNSUPPORTED(".word	0xe1100090") /* Unallocated space */
+	TEST_UNSUPPORTED(".word	0xe1200090") /* Unallocated space */
+	TEST_UNSUPPORTED(".word	0xe1300090") /* Unallocated space */
+	TEST_UNSUPPORTED(".word	0xe1500090") /* Unallocated space */
+	TEST_UNSUPPORTED(".word	0xe1600090") /* Unallocated space */
+	TEST_UNSUPPORTED(".word	0xe1700090") /* Unallocated space */
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_UNSUPPORTED("ldrex	r2, [sp]")
+	TEST_UNSUPPORTED("strexd	r0, r2, r3, [sp]")
+	TEST_UNSUPPORTED("ldrexd	r2, r3, [sp]")
+	TEST_UNSUPPORTED("strexb	r0, r2, [sp]")
+	TEST_UNSUPPORTED("ldrexb	r2, [sp]")
+	TEST_UNSUPPORTED("strexh	r0, r2, [sp]")
+	TEST_UNSUPPORTED("ldrexh	r2, [sp]")
+#endif
+	TEST_GROUP("Extra load/store instructions")
+
+	TEST_RPR(  "strh	r",0, VAL1,", [r",1, 48,", -r",2, 24,"]")
+	TEST_RPR(  "streqh	r",14,VAL2,", [r",13,0, ", r",12, 48,"]")
+	TEST_RPR(  "strh	r",1, VAL1,", [r",2, 24,", r",3,  48,"]!")
+	TEST_RPR(  "strneh	r",12,VAL2,", [r",11,48,", -r",10,24,"]!")
+	TEST_RPR(  "strh	r",2, VAL1,", [r",3, 24,"], r",4, 48,"")
+	TEST_RPR(  "strh	r",10,VAL2,", [r",9, 48,"], -r",11,24,"")
+	TEST_UNSUPPORTED(".word 0xe1afc0ba	@ strh r12, [pc, r10]!")
+	TEST_UNSUPPORTED(".word 0xe089f0bb	@ strh pc, [r9], r11")
+	TEST_UNSUPPORTED(".word 0xe089a0bf	@ strh r10, [r9], pc")
+
+	TEST_PR(   "ldrh	r0, [r",0,  48,", -r",2, 24,"]")
+	TEST_PR(   "ldrcsh	r14, [r",13,0, ", r",12, 48,"]")
+	TEST_PR(   "ldrh	r1, [r",2,  24,", r",3,  48,"]!")
+	TEST_PR(   "ldrcch	r12, [r",11,48,", -r",10,24,"]!")
+	TEST_PR(   "ldrh	r2, [r",3,  24,"], r",4, 48,"")
+	TEST_PR(   "ldrh	r10, [r",9, 48,"], -r",11,24,"")
+	TEST_UNSUPPORTED(".word 0xe1bfc0ba	@ ldrh r12, [pc, r10]!")
+	TEST_UNSUPPORTED(".word 0xe099f0bb	@ ldrh pc, [r9], r11")
+	TEST_UNSUPPORTED(".word 0xe099a0bf	@ ldrh r10, [r9], pc")
+
+	TEST_RP(   "strh	r",0, VAL1,", [r",1, 24,", #-2]")
+	TEST_RP(   "strmih	r",14,VAL2,", [r",13,0, ", #2]")
+	TEST_RP(   "strh	r",1, VAL1,", [r",2, 24,", #4]!")
+	TEST_RP(   "strplh	r",12,VAL2,", [r",11,24,", #-4]!")
+	TEST_RP(   "strh	r",2, VAL1,", [r",3, 24,"], #48")
+	TEST_RP(   "strh	r",10,VAL2,", [r",9, 64,"], #-48")
+	TEST_UNSUPPORTED(".word 0xe1efc3b0	@ strh r12, [pc, #48]!")
+	TEST_UNSUPPORTED(".word 0xe0c9f3b0	@ strh pc, [r9], #48")
+
+	TEST_P(	   "ldrh	r0, [r",0,  24,", #-2]")
+	TEST_P(	   "ldrvsh	r14, [r",13,0, ", #2]")
+	TEST_P(	   "ldrh	r1, [r",2,  24,", #4]!")
+	TEST_P(	   "ldrvch	r12, [r",11,24,", #-4]!")
+	TEST_P(	   "ldrh	r2, [r",3,  24,"], #48")
+	TEST_P(	   "ldrh	r10, [r",9, 64,"], #-48")
+	TEST(      "ldrh	r0, [pc, #0]")
+	TEST_UNSUPPORTED(".word 0xe1ffc3b0	@ ldrh r12, [pc, #48]!")
+	TEST_UNSUPPORTED(".word 0xe0d9f3b0	@ ldrh pc, [r9], #48")
+
+	TEST_PR(   "ldrsb	r0, [r",0,  48,", -r",2, 24,"]")
+	TEST_PR(   "ldrhisb	r14, [r",13,0,", r",12,  48,"]")
+	TEST_PR(   "ldrsb	r1, [r",2,  24,", r",3,  48,"]!")
+	TEST_PR(   "ldrlssb	r12, [r",11,48,", -r",10,24,"]!")
+	TEST_PR(   "ldrsb	r2, [r",3,  24,"], r",4, 48,"")
+	TEST_PR(   "ldrsb	r10, [r",9, 48,"], -r",11,24,"")
+	TEST_UNSUPPORTED(".word 0xe1bfc0da	@ ldrsb r12, [pc, r10]!")
+	TEST_UNSUPPORTED(".word 0xe099f0db	@ ldrsb pc, [r9], r11")
+
+	TEST_P(	   "ldrsb	r0, [r",0,  24,", #-1]")
+	TEST_P(	   "ldrgesb	r14, [r",13,0, ", #1]")
+	TEST_P(	   "ldrsb	r1, [r",2,  24,", #4]!")
+	TEST_P(	   "ldrltsb	r12, [r",11,24,", #-4]!")
+	TEST_P(	   "ldrsb	r2, [r",3,  24,"], #48")
+	TEST_P(	   "ldrsb	r10, [r",9, 64,"], #-48")
+	TEST(      "ldrsb	r0, [pc, #0]")
+	TEST_UNSUPPORTED(".word 0xe1ffc3d0	@ ldrsb r12, [pc, #48]!")
+	TEST_UNSUPPORTED(".word 0xe0d9f3d0	@ ldrsb pc, [r9], #48")
+
+	TEST_PR(   "ldrsh	r0, [r",0,  48,", -r",2, 24,"]")
+	TEST_PR(   "ldrgtsh	r14, [r",13,0, ", r",12, 48,"]")
+	TEST_PR(   "ldrsh	r1, [r",2,  24,", r",3,  48,"]!")
+	TEST_PR(   "ldrlesh	r12, [r",11,48,", -r",10,24,"]!")
+	TEST_PR(   "ldrsh	r2, [r",3,  24,"], r",4, 48,"")
+	TEST_PR(   "ldrsh	r10, [r",9, 48,"], -r",11,24,"")
+	TEST_UNSUPPORTED(".word 0xe1bfc0fa	@ ldrsh r12, [pc, r10]!")
+	TEST_UNSUPPORTED(".word 0xe099f0fb	@ ldrsh pc, [r9], r11")
+
+	TEST_P(	   "ldrsh	r0, [r",0,  24,", #-1]")
+	TEST_P(	   "ldreqsh	r14, [r",13,0 ,", #1]")
+	TEST_P(	   "ldrsh	r1, [r",2,  24,", #4]!")
+	TEST_P(	   "ldrnesh	r12, [r",11,24,", #-4]!")
+	TEST_P(	   "ldrsh	r2, [r",3,  24,"], #48")
+	TEST_P(	   "ldrsh	r10, [r",9, 64,"], #-48")
+	TEST(      "ldrsh	r0, [pc, #0]")
+	TEST_UNSUPPORTED(".word 0xe1ffc3f0	@ ldrsh r12, [pc, #48]!")
+	TEST_UNSUPPORTED(".word 0xe0d9f3f0	@ ldrsh pc, [r9], #48")
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST_UNSUPPORTED("strht	r1, [r2], r3")
+	TEST_UNSUPPORTED("ldrht	r1, [r2], r3")
+	TEST_UNSUPPORTED("strht	r1, [r2], #48")
+	TEST_UNSUPPORTED("ldrht	r1, [r2], #48")
+	TEST_UNSUPPORTED("ldrsbt	r1, [r2], r3")
+	TEST_UNSUPPORTED("ldrsbt	r1, [r2], #48")
+	TEST_UNSUPPORTED("ldrsht	r1, [r2], r3")
+	TEST_UNSUPPORTED("ldrsht	r1, [r2], #48")
+#endif
+
+	TEST_RPR(  "strd	r",0, VAL1,", [r",1, 48,", -r",2,24,"]")
+	TEST_RPR(  "strccd	r",8, VAL2,", [r",13,0, ", r",12,48,"]")
+	TEST_RPR(  "strd	r",4, VAL1,", [r",2, 24,", r",3, 48,"]!")
+	TEST_RPR(  "strcsd	r",12,VAL2,", [r",11,48,", -r",10,24,"]!")
+	TEST_RPR(  "strd	r",2, VAL1,", [r",5, 24,"], r",4,48,"")
+	TEST_RPR(  "strd	r",10,VAL2,", [r",9, 48,"], -r",7,24,"")
+	TEST_UNSUPPORTED(".word 0xe1afc0fa	@ strd r12, [pc, r10]!")
+
+	TEST_PR(   "ldrd	r0, [r",0, 48,", -r",2,24,"]")
+	TEST_PR(   "ldrmid	r8, [r",13,0, ", r",12,48,"]")
+	TEST_PR(   "ldrd	r4, [r",2, 24,", r",3, 48,"]!")
+	TEST_PR(   "ldrpld	r6, [r",11,48,", -r",10,24,"]!")
+	TEST_PR(   "ldrd	r2, [r",5, 24,"], r",4,48,"")
+	TEST_PR(   "ldrd	r10, [r",9,48,"], -r",7,24,"")
+	TEST_UNSUPPORTED(".word 0xe1afc0da	@ ldrd r12, [pc, r10]!")
+	TEST_UNSUPPORTED(".word 0xe089f0db	@ ldrd pc, [r9], r11")
+	TEST_UNSUPPORTED(".word 0xe089e0db	@ ldrd lr, [r9], r11")
+	TEST_UNSUPPORTED(".word 0xe089c0df	@ ldrd r12, [r9], pc")
+
+	TEST_RP(   "strd	r",0, VAL1,", [r",1, 24,", #-8]")
+	TEST_RP(   "strvsd	r",8, VAL2,", [r",13,0, ", #8]")
+	TEST_RP(   "strd	r",4, VAL1,", [r",2, 24,", #16]!")
+	TEST_RP(   "strvcd	r",12,VAL2,", [r",11,24,", #-16]!")
+	TEST_RP(   "strd	r",2, VAL1,", [r",4, 24,"], #48")
+	TEST_RP(   "strd	r",10,VAL2,", [r",9, 64,"], #-48")
+	TEST_UNSUPPORTED(".word 0xe1efc3f0	@ strd r12, [pc, #48]!")
+
+	TEST_P(	   "ldrd	r0, [r",0, 24,", #-8]")
+	TEST_P(	   "ldrhid	r8, [r",13,0, ", #8]")
+	TEST_P(	   "ldrd	r4, [r",2, 24,", #16]!")
+	TEST_P(	   "ldrlsd	r6, [r",11,24,", #-16]!")
+	TEST_P(	   "ldrd	r2, [r",5, 24,"], #48")
+	TEST_P(	   "ldrd	r10, [r",9,6,"], #-48")
+	TEST_UNSUPPORTED(".word 0xe1efc3d0	@ ldrd r12, [pc, #48]!")
+	TEST_UNSUPPORTED(".word 0xe0c9f3d0	@ ldrd pc, [r9], #48")
+	TEST_UNSUPPORTED(".word 0xe0c9e3d0	@ ldrd lr, [r9], #48")
+
+	TEST_GROUP("Miscellaneous")
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST("movw	r0, #0")
+	TEST("movw	r0, #0xffff")
+	TEST("movw	lr, #0xffff")
+	TEST_UNSUPPORTED(".word 0xe300f000	@ movw pc, #0")
+	TEST_R("movt	r",0, VAL1,", #0")
+	TEST_R("movt	r",0, VAL2,", #0xffff")
+	TEST_R("movt	r",14,VAL1,", #0xffff")
+	TEST_UNSUPPORTED(".word 0xe340f000	@ movt pc, #0")
+#endif
+
+	TEST_UNSUPPORTED("msr	cpsr, 0x13")
+	TEST_UNSUPPORTED("msr	cpsr_f, 0xf0000000")
+	TEST_UNSUPPORTED("msr	spsr, 0x13")
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST_SUPPORTED("yield")
+	TEST("sev")
+	TEST("nop")
+	TEST("wfi")
+	TEST_SUPPORTED("wfe")
+	TEST_UNSUPPORTED("dbg #0")
+#endif
+
+	TEST_GROUP("Load/store word and unsigned byte")
+
+#define LOAD_STORE(byte)							\
+	TEST_RP( "str"byte"	r",0, VAL1,", [r",1, 24,", #-2]")		\
+	TEST_RP( "str"byte"	r",14,VAL2,", [r",13,0, ", #2]")		\
+	TEST_RP( "str"byte"	r",1, VAL1,", [r",2, 24,", #4]!")		\
+	TEST_RP( "str"byte"	r",12,VAL2,", [r",11,24,", #-4]!")		\
+	TEST_RP( "str"byte"	r",2, VAL1,", [r",3, 24,"], #48")		\
+	TEST_RP( "str"byte"	r",10,VAL2,", [r",9, 64,"], #-48")		\
+	TEST_RPR("str"byte"	r",0, VAL1,", [r",1, 48,", -r",2, 24,"]")	\
+	TEST_RPR("str"byte"	r",14,VAL2,", [r",13,0, ", r",12, 48,"]")	\
+	TEST_RPR("str"byte"	r",1, VAL1,", [r",2, 24,", r",3,  48,"]!")	\
+	TEST_RPR("str"byte"	r",12,VAL2,", [r",11,48,", -r",10,24,"]!")	\
+	TEST_RPR("str"byte"	r",2, VAL1,", [r",3, 24,"], r",4, 48,"")	\
+	TEST_RPR("str"byte"	r",10,VAL2,", [r",9, 48,"], -r",11,24,"")	\
+	TEST_RPR("str"byte"	r",0, VAL1,", [r",1, 24,", r",2,  32,", asl #1]")\
+	TEST_RPR("str"byte"	r",14,VAL2,", [r",13,0, ", r",12, 32,", lsr #2]")\
+	TEST_RPR("str"byte"	r",1, VAL1,", [r",2, 24,", r",3,  32,", asr #3]!")\
+	TEST_RPR("str"byte"	r",12,VAL2,", [r",11,24,", r",10, 4,", ror #31]!")\
+	TEST_P(  "ldr"byte"	r0, [r",0,  24,", #-2]")			\
+	TEST_P(  "ldr"byte"	r14, [r",13,0, ", #2]")				\
+	TEST_P(  "ldr"byte"	r1, [r",2,  24,", #4]!")			\
+	TEST_P(  "ldr"byte"	r12, [r",11,24,", #-4]!")			\
+	TEST_P(  "ldr"byte"	r2, [r",3,  24,"], #48")			\
+	TEST_P(  "ldr"byte"	r10, [r",9, 64,"], #-48")			\
+	TEST_PR( "ldr"byte"	r0, [r",0,  48,", -r",2, 24,"]")		\
+	TEST_PR( "ldr"byte"	r14, [r",13,0, ", r",12, 48,"]")		\
+	TEST_PR( "ldr"byte"	r1, [r",2,  24,", r",3, 48,"]!")		\
+	TEST_PR( "ldr"byte"	r12, [r",11,48,", -r",10,24,"]!")		\
+	TEST_PR( "ldr"byte"	r2, [r",3,  24,"], r",4, 48,"")			\
+	TEST_PR( "ldr"byte"	r10, [r",9, 48,"], -r",11,24,"")		\
+	TEST_PR( "ldr"byte"	r0, [r",0,  24,", r",2,  32,", asl #1]")	\
+	TEST_PR( "ldr"byte"	r14, [r",13,0, ", r",12, 32,", lsr #2]")	\
+	TEST_PR( "ldr"byte"	r1, [r",2,  24,", r",3,  32,", asr #3]!")	\
+	TEST_PR( "ldr"byte"	r12, [r",11,24,", r",10, 4,", ror #31]!")	\
+	TEST(    "ldr"byte"	r0, [pc, #0]")					\
+	TEST_R(  "ldr"byte"	r12, [pc, r",14,0,"]")
+
+	LOAD_STORE("")
+	TEST_P(   "str	pc, [r",0,0,", #15*4]")
+	TEST_R(   "str	pc, [sp, r",2,15*4,"]")
+	TEST_BF(  "ldr	pc, [sp, #15*4]")
+	TEST_BF_R("ldr	pc, [sp, r",2,15*4,"]")
+
+	TEST_P(   "str	sp, [r",0,0,", #13*4]")
+	TEST_R(   "str	sp, [sp, r",2,13*4,"]")
+	TEST_BF(  "ldr	sp, [sp, #13*4]")
+	TEST_BF_R("ldr	sp, [sp, r",2,13*4,"]")
+
+#ifdef CONFIG_THUMB2_KERNEL
+	TEST_ARM_TO_THUMB_INTERWORK_P("ldr	pc, [r",0,0,", #15*4]")
+#endif
+	TEST_UNSUPPORTED(".word 0xe5af6008	@ str r6, [pc, #8]!")
+	TEST_UNSUPPORTED(".word 0xe7af6008	@ str r6, [pc, r8]!")
+	TEST_UNSUPPORTED(".word 0xe5bf6008	@ ldr r6, [pc, #8]!")
+	TEST_UNSUPPORTED(".word 0xe7bf6008	@ ldr r6, [pc, r8]!")
+	TEST_UNSUPPORTED(".word 0xe788600f	@ str r6, [r8, pc]")
+	TEST_UNSUPPORTED(".word 0xe798600f	@ ldr r6, [r8, pc]")
+
+	LOAD_STORE("b")
+	TEST_UNSUPPORTED(".word 0xe5f7f008	@ ldrb pc, [r7, #8]!")
+	TEST_UNSUPPORTED(".word 0xe7f7f008	@ ldrb pc, [r7, r8]!")
+	TEST_UNSUPPORTED(".word 0xe5ef6008	@ strb r6, [pc, #8]!")
+	TEST_UNSUPPORTED(".word 0xe7ef6008	@ strb r6, [pc, r3]!")
+	TEST_UNSUPPORTED(".word 0xe5ff6008	@ ldrb r6, [pc, #8]!")
+	TEST_UNSUPPORTED(".word 0xe7ff6008	@ ldrb r6, [pc, r3]!")
+
+	TEST_UNSUPPORTED("ldrt	r0, [r1], #4")
+	TEST_UNSUPPORTED("ldrt	r1, [r2], r3")
+	TEST_UNSUPPORTED("strt	r2, [r3], #4")
+	TEST_UNSUPPORTED("strt	r3, [r4], r5")
+	TEST_UNSUPPORTED("ldrbt	r4, [r5], #4")
+	TEST_UNSUPPORTED("ldrbt	r5, [r6], r7")
+	TEST_UNSUPPORTED("strbt	r6, [r7], #4")
+	TEST_UNSUPPORTED("strbt	r7, [r8], r9")
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST_GROUP("Parallel addition and subtraction, signed")
+
+	TEST_UNSUPPORTED(".word 0xe6000010") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe60fffff") /* Unallocated space */
+
+	TEST_RR(    "sadd16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sadd16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe61cff1a	@ sadd16	pc, r12, r10")
+	TEST_RR(    "sasx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sasx	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe61cff3a	@ sasx	pc, r12, r10")
+	TEST_RR(    "ssax	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "ssax	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe61cff5a	@ ssax	pc, r12, r10")
+	TEST_RR(    "ssub16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "ssub16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe61cff7a	@ ssub16	pc, r12, r10")
+	TEST_RR(    "sadd8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sadd8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe61cff9a	@ sadd8	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe61000b0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe61fffbf") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe61000d0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe61fffdf") /* Unallocated space */
+	TEST_RR(    "ssub8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "ssub8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe61cfffa	@ ssub8	pc, r12, r10")
+
+	TEST_RR(    "qadd16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "qadd16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe62cff1a	@ qadd16	pc, r12, r10")
+	TEST_RR(    "qasx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "qasx	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe62cff3a	@ qasx	pc, r12, r10")
+	TEST_RR(    "qsax	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "qsax	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe62cff5a	@ qsax	pc, r12, r10")
+	TEST_RR(    "qsub16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "qsub16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe62cff7a	@ qsub16	pc, r12, r10")
+	TEST_RR(    "qadd8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "qadd8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe62cff9a	@ qadd8	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe62000b0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe62fffbf") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe62000d0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe62fffdf") /* Unallocated space */
+	TEST_RR(    "qsub8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "qsub8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe62cfffa	@ qsub8	pc, r12, r10")
+
+	TEST_RR(    "shadd16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "shadd16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe63cff1a	@ shadd16	pc, r12, r10")
+	TEST_RR(    "shasx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "shasx	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe63cff3a	@ shasx	pc, r12, r10")
+	TEST_RR(    "shsax	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "shsax	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe63cff5a	@ shsax	pc, r12, r10")
+	TEST_RR(    "shsub16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "shsub16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe63cff7a	@ shsub16	pc, r12, r10")
+	TEST_RR(    "shadd8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "shadd8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe63cff9a	@ shadd8	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe63000b0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe63fffbf") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe63000d0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe63fffdf") /* Unallocated space */
+	TEST_RR(    "shsub8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "shsub8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe63cfffa	@ shsub8	pc, r12, r10")
+
+	TEST_GROUP("Parallel addition and subtraction, unsigned")
+
+	TEST_UNSUPPORTED(".word 0xe6400010") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe64fffff") /* Unallocated space */
+
+	TEST_RR(    "uadd16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uadd16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe65cff1a	@ uadd16	pc, r12, r10")
+	TEST_RR(    "uasx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uasx	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe65cff3a	@ uasx	pc, r12, r10")
+	TEST_RR(    "usax	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "usax	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe65cff5a	@ usax	pc, r12, r10")
+	TEST_RR(    "usub16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "usub16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe65cff7a	@ usub16	pc, r12, r10")
+	TEST_RR(    "uadd8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uadd8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe65cff9a	@ uadd8	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe65000b0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe65fffbf") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe65000d0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe65fffdf") /* Unallocated space */
+	TEST_RR(    "usub8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "usub8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe65cfffa	@ usub8	pc, r12, r10")
+
+	TEST_RR(    "uqadd16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uqadd16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe66cff1a	@ uqadd16	pc, r12, r10")
+	TEST_RR(    "uqasx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uqasx	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe66cff3a	@ uqasx	pc, r12, r10")
+	TEST_RR(    "uqsax	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uqsax	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe66cff5a	@ uqsax	pc, r12, r10")
+	TEST_RR(    "uqsub16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uqsub16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe66cff7a	@ uqsub16	pc, r12, r10")
+	TEST_RR(    "uqadd8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uqadd8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe66cff9a	@ uqadd8	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe66000b0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe66fffbf") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe66000d0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe66fffdf") /* Unallocated space */
+	TEST_RR(    "uqsub8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uqsub8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe66cfffa	@ uqsub8	pc, r12, r10")
+
+	TEST_RR(    "uhadd16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uhadd16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe67cff1a	@ uhadd16	pc, r12, r10")
+	TEST_RR(    "uhasx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uhasx	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe67cff3a	@ uhasx	pc, r12, r10")
+	TEST_RR(    "uhsax	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uhsax	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe67cff5a	@ uhsax	pc, r12, r10")
+	TEST_RR(    "uhsub16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uhsub16	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe67cff7a	@ uhsub16	pc, r12, r10")
+	TEST_RR(    "uhadd8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uhadd8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe67cff9a	@ uhadd8	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe67000b0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe67fffbf") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe67000d0") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe67fffdf") /* Unallocated space */
+	TEST_RR(    "uhsub8	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uhsub8	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe67cfffa	@ uhsub8	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe67feffa	@ uhsub8	r14, pc, r10")
+	TEST_UNSUPPORTED(".word 0xe67cefff	@ uhsub8	r14, r12, pc")
+#endif /* __LINUX_ARM_ARCH__ >= 7 */
+
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_GROUP("Packing, unpacking, saturation, and reversal")
+
+	TEST_RR(    "pkhbt	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "pkhbt	r14,r",12, HH1,", r",10,HH2,", lsl #2")
+	TEST_UNSUPPORTED(".word 0xe68cf11a	@ pkhbt	pc, r12, r10, lsl #2")
+	TEST_RR(    "pkhtb	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "pkhtb	r14,r",12, HH1,", r",10,HH2,", asr #2")
+	TEST_UNSUPPORTED(".word 0xe68cf15a	@ pkhtb	pc, r12, r10, asr #2")
+	TEST_UNSUPPORTED(".word 0xe68fe15a	@ pkhtb	r14, pc, r10, asr #2")
+	TEST_UNSUPPORTED(".word 0xe68ce15f	@ pkhtb	r14, r12, pc, asr #2")
+	TEST_UNSUPPORTED(".word 0xe6900010") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe69fffdf") /* Unallocated space */
+
+	TEST_R(     "ssat	r0, #24, r",0,   VAL1,"")
+	TEST_R(     "ssat	r14, #24, r",12, VAL2,"")
+	TEST_R(     "ssat	r0, #24, r",0,   VAL1,", lsl #8")
+	TEST_R(     "ssat	r14, #24, r",12, VAL2,", asr #8")
+	TEST_UNSUPPORTED(".word 0xe6b7f01c	@ ssat	pc, #24, r12")
+
+	TEST_R(     "usat	r0, #24, r",0,   VAL1,"")
+	TEST_R(     "usat	r14, #24, r",12, VAL2,"")
+	TEST_R(     "usat	r0, #24, r",0,   VAL1,", lsl #8")
+	TEST_R(     "usat	r14, #24, r",12, VAL2,", asr #8")
+	TEST_UNSUPPORTED(".word 0xe6f7f01c	@ usat	pc, #24, r12")
+
+	TEST_RR(    "sxtab16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sxtab16	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "sxtb16	r8, r",7,  HH1,"")
+	TEST_UNSUPPORTED(".word 0xe68cf47a	@ sxtab16	pc,r12, r10, ror #8")
+
+	TEST_RR(    "sel	r0, r",0,  VAL1,", r",1, VAL2,"")
+	TEST_RR(    "sel	r14, r",12,VAL1,", r",10, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe68cffba	@ sel	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe68fefba	@ sel	r14, pc, r10")
+	TEST_UNSUPPORTED(".word 0xe68cefbf	@ sel	r14, r12, pc")
+
+	TEST_R(     "ssat16	r0, #12, r",0,   HH1,"")
+	TEST_R(     "ssat16	r14, #12, r",12, HH2,"")
+	TEST_UNSUPPORTED(".word 0xe6abff3c	@ ssat16	pc, #12, r12")
+
+	TEST_RR(    "sxtab	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sxtab	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "sxtb	r8, r",7,  HH1,"")
+	TEST_UNSUPPORTED(".word 0xe6acf47a	@ sxtab	pc,r12, r10, ror #8")
+
+	TEST_R(     "rev	r0, r",0,   VAL1,"")
+	TEST_R(     "rev	r14, r",12, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe6bfff3c	@ rev	pc, r12")
+
+	TEST_RR(    "sxtah	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sxtah	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "sxth	r8, r",7,  HH1,"")
+	TEST_UNSUPPORTED(".word 0xe6bcf47a	@ sxtah	pc,r12, r10, ror #8")
+
+	TEST_R(     "rev16	r0, r",0,   VAL1,"")
+	TEST_R(     "rev16	r14, r",12, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe6bfffbc	@ rev16	pc, r12")
+
+	TEST_RR(    "uxtab16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uxtab16	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "uxtb16	r8, r",7,  HH1,"")
+	TEST_UNSUPPORTED(".word 0xe6ccf47a	@ uxtab16	pc,r12, r10, ror #8")
+
+	TEST_R(     "usat16	r0, #12, r",0,   HH1,"")
+	TEST_R(     "usat16	r14, #12, r",12, HH2,"")
+	TEST_UNSUPPORTED(".word 0xe6ecff3c	@ usat16	pc, #12, r12")
+	TEST_UNSUPPORTED(".word 0xe6ecef3f	@ usat16	r14, #12, pc")
+
+	TEST_RR(    "uxtab	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uxtab	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "uxtb	r8, r",7,  HH1,"")
+	TEST_UNSUPPORTED(".word 0xe6ecf47a	@ uxtab	pc,r12, r10, ror #8")
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST_R(     "rbit	r0, r",0,   VAL1,"")
+	TEST_R(     "rbit	r14, r",12, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe6ffff3c	@ rbit	pc, r12")
+#endif
+
+	TEST_RR(    "uxtah	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uxtah	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "uxth	r8, r",7,  HH1,"")
+	TEST_UNSUPPORTED(".word 0xe6fff077	@ uxth	pc, r7")
+	TEST_UNSUPPORTED(".word 0xe6ff807f	@ uxth	r8, pc")
+	TEST_UNSUPPORTED(".word 0xe6fcf47a	@ uxtah	pc, r12, r10, ror #8")
+	TEST_UNSUPPORTED(".word 0xe6fce47f	@ uxtah	r14, r12, pc, ror #8")
+
+	TEST_R(     "revsh	r0, r",0,   VAL1,"")
+	TEST_R(     "revsh	r14, r",12, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe6ffff3c	@ revsh	pc, r12")
+	TEST_UNSUPPORTED(".word 0xe6ffef3f	@ revsh	r14, pc")
+
+	TEST_UNSUPPORTED(".word 0xe6900070") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe69fff7f") /* Unallocated space */
+
+	TEST_UNSUPPORTED(".word 0xe6d00070") /* Unallocated space */
+	TEST_UNSUPPORTED(".word 0xe6dfff7f") /* Unallocated space */
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_GROUP("Signed multiplies")
+
+	TEST_RRR(   "smlad	r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+	TEST_RRR(   "smlad	r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe70f8a1c	@ smlad	pc, r12, r10, r8")
+	TEST_RRR(   "smladx	r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+	TEST_RRR(   "smladx	r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe70f8a3c	@ smladx	pc, r12, r10, r8")
+
+	TEST_RR(   "smuad	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(   "smuad	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe70ffa1c	@ smuad	pc, r12, r10")
+	TEST_RR(   "smuadx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(   "smuadx	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe70ffa3c	@ smuadx	pc, r12, r10")
+
+	TEST_RRR(   "smlsd	r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+	TEST_RRR(   "smlsd	r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe70f8a5c	@ smlsd	pc, r12, r10, r8")
+	TEST_RRR(   "smlsdx	r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+	TEST_RRR(   "smlsdx	r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe70f8a7c	@ smlsdx	pc, r12, r10, r8")
+
+	TEST_RR(   "smusd	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(   "smusd	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe70ffa5c	@ smusd	pc, r12, r10")
+	TEST_RR(   "smusdx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(   "smusdx	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_UNSUPPORTED(".word 0xe70ffa7c	@ smusdx	pc, r12, r10")
+
+	TEST_RRRR( "smlald	r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+	TEST_RRRR( "smlald	r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+	TEST_UNSUPPORTED(".word 0xe74af819	@ smlald	pc, r10, r9, r8")
+	TEST_UNSUPPORTED(".word 0xe74fb819	@ smlald	r11, pc, r9, r8")
+	TEST_UNSUPPORTED(".word 0xe74ab81f	@ smlald	r11, r10, pc, r8")
+	TEST_UNSUPPORTED(".word 0xe74abf19	@ smlald	r11, r10, r9, pc")
+
+	TEST_RRRR( "smlaldx	r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+	TEST_RRRR( "smlaldx	r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+	TEST_UNSUPPORTED(".word 0xe74af839	@ smlaldx	pc, r10, r9, r8")
+	TEST_UNSUPPORTED(".word 0xe74fb839	@ smlaldx	r11, pc, r9, r8")
+
+	TEST_RRR(  "smmla	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+	TEST_RRR(  "smmla	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe75f8a1c	@ smmla	pc, r12, r10, r8")
+	TEST_RRR(  "smmlar	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+	TEST_RRR(  "smmlar	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe75f8a3c	@ smmlar	pc, r12, r10, r8")
+
+	TEST_RR(   "smmul	r0, r",0,  VAL1,", r",1, VAL2,"")
+	TEST_RR(   "smmul	r14, r",12,VAL2,", r",10,VAL1,"")
+	TEST_UNSUPPORTED(".word 0xe75ffa1c	@ smmul	pc, r12, r10")
+	TEST_RR(   "smmulr	r0, r",0,  VAL1,", r",1, VAL2,"")
+	TEST_RR(   "smmulr	r14, r",12,VAL2,", r",10,VAL1,"")
+	TEST_UNSUPPORTED(".word 0xe75ffa3c	@ smmulr	pc, r12, r10")
+
+	TEST_RRR(  "smmls	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+	TEST_RRR(  "smmls	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe75f8adc	@ smmls	pc, r12, r10, r8")
+	TEST_RRR(  "smmlsr	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+	TEST_RRR(  "smmlsr	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+	TEST_UNSUPPORTED(".word 0xe75f8afc	@ smmlsr	pc, r12, r10, r8")
+	TEST_UNSUPPORTED(".word 0xe75e8aff	@ smmlsr	r14, pc, r10, r8")
+	TEST_UNSUPPORTED(".word 0xe75e8ffc	@ smmlsr	r14, r12, pc, r8")
+	TEST_UNSUPPORTED(".word 0xe75efafc	@ smmlsr	r14, r12, r10, pc")
+
+	TEST_RR(   "usad8	r0, r",0,  VAL1,", r",1, VAL2,"")
+	TEST_RR(   "usad8	r14, r",12,VAL2,", r",10,VAL1,"")
+	TEST_UNSUPPORTED(".word 0xe75ffa1c	@ usad8	pc, r12, r10")
+	TEST_UNSUPPORTED(".word 0xe75efa1f	@ usad8	r14, pc, r10")
+	TEST_UNSUPPORTED(".word 0xe75eff1c	@ usad8	r14, r12, pc")
+
+	TEST_RRR(  "usada8	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL3,"")
+	TEST_RRR(  "usada8	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL3,"")
+	TEST_UNSUPPORTED(".word 0xe78f8a1c	@ usada8	pc, r12, r10, r8")
+	TEST_UNSUPPORTED(".word 0xe78e8a1f	@ usada8	r14, pc, r10, r8")
+	TEST_UNSUPPORTED(".word 0xe78e8f1c	@ usada8	r14, r12, pc, r8")
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST_GROUP("Bit Field")
+
+	TEST_R(     "sbfx	r0, r",0  , VAL1,", #0, #31")
+	TEST_R(     "sbfxeq	r14, r",12, VAL2,", #8, #16")
+	TEST_R(     "sbfx	r4, r",10,  VAL1,", #16, #15")
+	TEST_UNSUPPORTED(".word 0xe7aff45c	@ sbfx	pc, r12, #8, #16")
+
+	TEST_R(     "ubfx	r0, r",0  , VAL1,", #0, #31")
+	TEST_R(     "ubfxcs	r14, r",12, VAL2,", #8, #16")
+	TEST_R(     "ubfx	r4, r",10,  VAL1,", #16, #15")
+	TEST_UNSUPPORTED(".word 0xe7eff45c	@ ubfx	pc, r12, #8, #16")
+	TEST_UNSUPPORTED(".word 0xe7efc45f	@ ubfx	r12, pc, #8, #16")
+
+	TEST_R(     "bfc	r",0, VAL1,", #4, #20")
+	TEST_R(     "bfcvs	r",14,VAL2,", #4, #20")
+	TEST_R(     "bfc	r",7, VAL1,", #0, #31")
+	TEST_R(     "bfc	r",8, VAL2,", #0, #31")
+	TEST_UNSUPPORTED(".word 0xe7def01f	@ bfc	pc, #0, #31");
+
+	TEST_RR(    "bfi	r",0, VAL1,", r",0  , VAL2,", #0, #31")
+	TEST_RR(    "bfipl	r",12,VAL1,", r",14 , VAL2,", #4, #20")
+	TEST_UNSUPPORTED(".word 0xe7d7f21e	@ bfi	pc, r14, #4, #20")
+
+	TEST_UNSUPPORTED(".word 0x07f000f0")  /* Permanently UNDEFINED */
+	TEST_UNSUPPORTED(".word 0x07ffffff")  /* Permanently UNDEFINED */
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+	TEST_GROUP("Branch, branch with link, and block data transfer")
+
+	TEST_P(   "stmda	r",0, 16*4,", {r0}")
+	TEST_P(   "stmeqda	r",4, 16*4,", {r0-r15}")
+	TEST_P(   "stmneda	r",8, 16*4,"!, {r8-r15}")
+	TEST_P(   "stmda	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_P(   "stmda	r",13,0,   "!, {pc}")
+
+	TEST_P(   "ldmda	r",0, 16*4,", {r0}")
+	TEST_BF_P("ldmcsda	r",4, 15*4,", {r0-r15}")
+	TEST_BF_P("ldmccda	r",7, 15*4,"!, {r8-r15}")
+	TEST_P(   "ldmda	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_BF_P("ldmda	r",14,15*4,"!, {pc}")
+
+	TEST_P(   "stmia	r",0, 16*4,", {r0}")
+	TEST_P(   "stmmiia	r",4, 16*4,", {r0-r15}")
+	TEST_P(   "stmplia	r",8, 16*4,"!, {r8-r15}")
+	TEST_P(   "stmia	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_P(   "stmia	r",14,0,   "!, {pc}")
+
+	TEST_P(   "ldmia	r",0, 16*4,", {r0}")
+	TEST_BF_P("ldmvsia	r",4, 0,   ", {r0-r15}")
+	TEST_BF_P("ldmvcia	r",7, 8*4, "!, {r8-r15}")
+	TEST_P(   "ldmia	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_BF_P("ldmia	r",14,15*4,"!, {pc}")
+
+	TEST_P(   "stmdb	r",0, 16*4,", {r0}")
+	TEST_P(   "stmhidb	r",4, 16*4,", {r0-r15}")
+	TEST_P(   "stmlsdb	r",8, 16*4,"!, {r8-r15}")
+	TEST_P(   "stmdb	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_P(   "stmdb	r",13,4,   "!, {pc}")
+
+	TEST_P(   "ldmdb	r",0, 16*4,", {r0}")
+	TEST_BF_P("ldmgedb	r",4, 16*4,", {r0-r15}")
+	TEST_BF_P("ldmltdb	r",7, 16*4,"!, {r8-r15}")
+	TEST_P(   "ldmdb	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_BF_P("ldmdb	r",14,16*4,"!, {pc}")
+
+	TEST_P(   "stmib	r",0, 16*4,", {r0}")
+	TEST_P(   "stmgtib	r",4, 16*4,", {r0-r15}")
+	TEST_P(   "stmleib	r",8, 16*4,"!, {r8-r15}")
+	TEST_P(   "stmib	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_P(   "stmib	r",13,-4,  "!, {pc}")
+
+	TEST_P(   "ldmib	r",0, 16*4,", {r0}")
+	TEST_BF_P("ldmeqib	r",4, -4,", {r0-r15}")
+	TEST_BF_P("ldmneib	r",7, 7*4,"!, {r8-r15}")
+	TEST_P(   "ldmib	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_BF_P("ldmib	r",14,14*4,"!, {pc}")
+
+	TEST_P(   "stmdb	r",13,16*4,"!, {r3-r12,lr}")
+	TEST_P(	  "stmeqdb	r",13,16*4,"!, {r3-r12}")
+	TEST_P(   "stmnedb	r",2, 16*4,", {r3-r12,lr}")
+	TEST_P(   "stmdb	r",13,16*4,"!, {r2-r12,lr}")
+	TEST_P(   "stmdb	r",0, 16*4,", {r0-r12}")
+	TEST_P(   "stmdb	r",0, 16*4,", {r0-r12,lr}")
+
+	TEST_BF_P("ldmia	r",13,5*4, "!, {r3-r12,pc}")
+	TEST_P(	  "ldmccia	r",13,5*4, "!, {r3-r12}")
+	TEST_BF_P("ldmcsia	r",2, 5*4, "!, {r3-r12,pc}")
+	TEST_BF_P("ldmia	r",13,4*4, "!, {r2-r12,pc}")
+	TEST_P(   "ldmia	r",0, 16*4,", {r0-r12}")
+	TEST_P(   "ldmia	r",0, 16*4,", {r0-r12,lr}")
+
+#ifdef CONFIG_THUMB2_KERNEL
+	TEST_ARM_TO_THUMB_INTERWORK_P("ldmplia	r",0,15*4,", {pc}")
+	TEST_ARM_TO_THUMB_INTERWORK_P("ldmmiia	r",13,0,", {r0-r15}")
+#endif
+	TEST_BF("b	2f")
+	TEST_BF("bl	2f")
+	TEST_BB("b	2b")
+	TEST_BB("bl	2b")
+
+	TEST_BF("beq	2f")
+	TEST_BF("bleq	2f")
+	TEST_BB("bne	2b")
+	TEST_BB("blne	2b")
+
+	TEST_BF("bgt	2f")
+	TEST_BF("blgt	2f")
+	TEST_BB("blt	2b")
+	TEST_BB("bllt	2b")
+
+	TEST_GROUP("Supervisor Call, and coprocessor instructions")
+
+	/*
+	 * We can't really test these by executing them, so all
+	 * we can do is check that probes are, or are not allowed.
+	 * At the moment none are allowed...
+	 */
+#define TEST_COPROCESSOR(code) TEST_UNSUPPORTED(code)
+
+#define COPROCESSOR_INSTRUCTIONS_ST_LD(two,cc)					\
+	TEST_COPROCESSOR("stc"two"	0, cr0, [r13, #4]")			\
+	TEST_COPROCESSOR("stc"two"	0, cr0, [r13, #-4]")			\
+	TEST_COPROCESSOR("stc"two"	0, cr0, [r13, #4]!")			\
+	TEST_COPROCESSOR("stc"two"	0, cr0, [r13, #-4]!")			\
+	TEST_COPROCESSOR("stc"two"	0, cr0, [r13], #4")			\
+	TEST_COPROCESSOR("stc"two"	0, cr0, [r13], #-4")			\
+	TEST_COPROCESSOR("stc"two"	0, cr0, [r13], {1}")			\
+	TEST_COPROCESSOR("stc"two"l	0, cr0, [r13, #4]")			\
+	TEST_COPROCESSOR("stc"two"l	0, cr0, [r13, #-4]")			\
+	TEST_COPROCESSOR("stc"two"l	0, cr0, [r13, #4]!")			\
+	TEST_COPROCESSOR("stc"two"l	0, cr0, [r13, #-4]!")			\
+	TEST_COPROCESSOR("stc"two"l	0, cr0, [r13], #4")			\
+	TEST_COPROCESSOR("stc"two"l	0, cr0, [r13], #-4")			\
+	TEST_COPROCESSOR("stc"two"l	0, cr0, [r13], {1}")			\
+	TEST_COPROCESSOR("ldc"two"	0, cr0, [r13, #4]")			\
+	TEST_COPROCESSOR("ldc"two"	0, cr0, [r13, #-4]")			\
+	TEST_COPROCESSOR("ldc"two"	0, cr0, [r13, #4]!")			\
+	TEST_COPROCESSOR("ldc"two"	0, cr0, [r13, #-4]!")			\
+	TEST_COPROCESSOR("ldc"two"	0, cr0, [r13], #4")			\
+	TEST_COPROCESSOR("ldc"two"	0, cr0, [r13], #-4")			\
+	TEST_COPROCESSOR("ldc"two"	0, cr0, [r13], {1}")			\
+	TEST_COPROCESSOR("ldc"two"l	0, cr0, [r13, #4]")			\
+	TEST_COPROCESSOR("ldc"two"l	0, cr0, [r13, #-4]")			\
+	TEST_COPROCESSOR("ldc"two"l	0, cr0, [r13, #4]!")			\
+	TEST_COPROCESSOR("ldc"two"l	0, cr0, [r13, #-4]!")			\
+	TEST_COPROCESSOR("ldc"two"l	0, cr0, [r13], #4")			\
+	TEST_COPROCESSOR("ldc"two"l	0, cr0, [r13], #-4")			\
+	TEST_COPROCESSOR("ldc"two"l	0, cr0, [r13], {1}")			\
+										\
+	TEST_COPROCESSOR( "stc"two"	0, cr0, [r15, #4]")			\
+	TEST_COPROCESSOR( "stc"two"	0, cr0, [r15, #-4]")			\
+	TEST_UNSUPPORTED(".word 0x"cc"daf0001	@ stc"two"	0, cr0, [r15, #4]!")	\
+	TEST_UNSUPPORTED(".word 0x"cc"d2f0001	@ stc"two"	0, cr0, [r15, #-4]!")	\
+	TEST_UNSUPPORTED(".word 0x"cc"caf0001	@ stc"two"	0, cr0, [r15], #4")	\
+	TEST_UNSUPPORTED(".word 0x"cc"c2f0001	@ stc"two"	0, cr0, [r15], #-4")	\
+	TEST_COPROCESSOR( "stc"two"	0, cr0, [r15], {1}")			\
+	TEST_COPROCESSOR( "stc"two"l	0, cr0, [r15, #4]")			\
+	TEST_COPROCESSOR( "stc"two"l	0, cr0, [r15, #-4]")			\
+	TEST_UNSUPPORTED(".word 0x"cc"def0001	@ stc"two"l	0, cr0, [r15, #4]!")	\
+	TEST_UNSUPPORTED(".word 0x"cc"d6f0001	@ stc"two"l	0, cr0, [r15, #-4]!")	\
+	TEST_UNSUPPORTED(".word 0x"cc"cef0001	@ stc"two"l	0, cr0, [r15], #4")	\
+	TEST_UNSUPPORTED(".word 0x"cc"c6f0001	@ stc"two"l	0, cr0, [r15], #-4")	\
+	TEST_COPROCESSOR( "stc"two"l	0, cr0, [r15], {1}")			\
+	TEST_COPROCESSOR( "ldc"two"	0, cr0, [r15, #4]")			\
+	TEST_COPROCESSOR( "ldc"two"	0, cr0, [r15, #-4]")			\
+	TEST_UNSUPPORTED(".word 0x"cc"dbf0001	@ ldc"two"	0, cr0, [r15, #4]!")	\
+	TEST_UNSUPPORTED(".word 0x"cc"d3f0001	@ ldc"two"	0, cr0, [r15, #-4]!")	\
+	TEST_UNSUPPORTED(".word 0x"cc"cbf0001	@ ldc"two"	0, cr0, [r15], #4")	\
+	TEST_UNSUPPORTED(".word 0x"cc"c3f0001	@ ldc"two"	0, cr0, [r15], #-4")	\
+	TEST_COPROCESSOR( "ldc"two"	0, cr0, [r15], {1}")			\
+	TEST_COPROCESSOR( "ldc"two"l	0, cr0, [r15, #4]")			\
+	TEST_COPROCESSOR( "ldc"two"l	0, cr0, [r15, #-4]")			\
+	TEST_UNSUPPORTED(".word 0x"cc"dff0001	@ ldc"two"l	0, cr0, [r15, #4]!")	\
+	TEST_UNSUPPORTED(".word 0x"cc"d7f0001	@ ldc"two"l	0, cr0, [r15, #-4]!")	\
+	TEST_UNSUPPORTED(".word 0x"cc"cff0001	@ ldc"two"l	0, cr0, [r15], #4")	\
+	TEST_UNSUPPORTED(".word 0x"cc"c7f0001	@ ldc"two"l	0, cr0, [r15], #-4")	\
+	TEST_COPROCESSOR( "ldc"two"l	0, cr0, [r15], {1}")
+
+#define COPROCESSOR_INSTRUCTIONS_MC_MR(two,cc)					\
+										\
+	TEST_COPROCESSOR( "mcrr"two"	0, 15, r0, r14, cr0")			\
+	TEST_COPROCESSOR( "mcrr"two"	15, 0, r14, r0, cr15")			\
+	TEST_UNSUPPORTED(".word 0x"cc"c4f00f0	@ mcrr"two"	0, 15, r0, r15, cr0")	\
+	TEST_UNSUPPORTED(".word 0x"cc"c40ff0f	@ mcrr"two"	15, 0, r15, r0, cr15")	\
+	TEST_COPROCESSOR( "mrrc"two"	0, 15, r0, r14, cr0")			\
+	TEST_COPROCESSOR( "mrrc"two"	15, 0, r14, r0, cr15")			\
+	TEST_UNSUPPORTED(".word 0x"cc"c5f00f0	@ mrrc"two"	0, 15, r0, r15, cr0")	\
+	TEST_UNSUPPORTED(".word 0x"cc"c50ff0f	@ mrrc"two"	15, 0, r15, r0, cr15")	\
+	TEST_COPROCESSOR( "cdp"two"	15, 15, cr15, cr15, cr15, 7")		\
+	TEST_COPROCESSOR( "cdp"two"	0, 0, cr0, cr0, cr0, 0")		\
+	TEST_COPROCESSOR( "mcr"two"	15, 7, r15, cr15, cr15, 7")		\
+	TEST_COPROCESSOR( "mcr"two"	0, 0, r0, cr0, cr0, 0")			\
+	TEST_COPROCESSOR( "mrc"two"	15, 7, r15, cr15, cr15, 7")		\
+	TEST_COPROCESSOR( "mrc"two"	0, 0, r0, cr0, cr0, 0")
+
+	COPROCESSOR_INSTRUCTIONS_ST_LD("","e")
+	COPROCESSOR_INSTRUCTIONS_MC_MR("","e")
+	TEST_UNSUPPORTED("svc	0")
+	TEST_UNSUPPORTED("svc	0xffffff")
+
+	TEST_UNSUPPORTED("svc	0")
+
+	TEST_GROUP("Unconditional instruction")
+
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_UNSUPPORTED("srsda	sp, 0x13")
+	TEST_UNSUPPORTED("srsdb	sp, 0x13")
+	TEST_UNSUPPORTED("srsia	sp, 0x13")
+	TEST_UNSUPPORTED("srsib	sp, 0x13")
+	TEST_UNSUPPORTED("srsda	sp!, 0x13")
+	TEST_UNSUPPORTED("srsdb	sp!, 0x13")
+	TEST_UNSUPPORTED("srsia	sp!, 0x13")
+	TEST_UNSUPPORTED("srsib	sp!, 0x13")
+
+	TEST_UNSUPPORTED("rfeda	sp")
+	TEST_UNSUPPORTED("rfedb	sp")
+	TEST_UNSUPPORTED("rfeia	sp")
+	TEST_UNSUPPORTED("rfeib	sp")
+	TEST_UNSUPPORTED("rfeda	sp!")
+	TEST_UNSUPPORTED("rfedb	sp!")
+	TEST_UNSUPPORTED("rfeia	sp!")
+	TEST_UNSUPPORTED("rfeib	sp!")
+	TEST_UNSUPPORTED(".word 0xf81d0a00	@ rfeda	pc")
+	TEST_UNSUPPORTED(".word 0xf91d0a00	@ rfedb	pc")
+	TEST_UNSUPPORTED(".word 0xf89d0a00	@ rfeia	pc")
+	TEST_UNSUPPORTED(".word 0xf99d0a00	@ rfeib	pc")
+	TEST_UNSUPPORTED(".word 0xf83d0a00	@ rfeda	pc!")
+	TEST_UNSUPPORTED(".word 0xf93d0a00	@ rfedb	pc!")
+	TEST_UNSUPPORTED(".word 0xf8bd0a00	@ rfeia	pc!")
+	TEST_UNSUPPORTED(".word 0xf9bd0a00	@ rfeib	pc!")
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_X(	"blx	__dummy_thumb_subroutine_even",
+		".thumb				\n\t"
+		".space 4			\n\t"
+		".type __dummy_thumb_subroutine_even, %%function \n\t"
+		"__dummy_thumb_subroutine_even:	\n\t"
+		"mov	r0, pc			\n\t"
+		"bx	lr			\n\t"
+		".arm				\n\t"
+	)
+	TEST(	"blx	__dummy_thumb_subroutine_even")
+
+	TEST_X(	"blx	__dummy_thumb_subroutine_odd",
+		".thumb				\n\t"
+		".space 2			\n\t"
+		".type __dummy_thumb_subroutine_odd, %%function	\n\t"
+		"__dummy_thumb_subroutine_odd:	\n\t"
+		"mov	r0, pc			\n\t"
+		"bx	lr			\n\t"
+		".arm				\n\t"
+	)
+	TEST(	"blx	__dummy_thumb_subroutine_odd")
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+	COPROCESSOR_INSTRUCTIONS_ST_LD("2","f")
+#if __LINUX_ARM_ARCH__ >= 6
+	COPROCESSOR_INSTRUCTIONS_MC_MR("2","f")
+#endif
+
+	TEST_GROUP("Miscellaneous instructions, memory hints, and Advanced SIMD instructions")
+
+#if __LINUX_ARM_ARCH__ >= 6
+	TEST_UNSUPPORTED("cps	0x13")
+	TEST_UNSUPPORTED("cpsie	i")
+	TEST_UNSUPPORTED("cpsid	i")
+	TEST_UNSUPPORTED("cpsie	i,0x13")
+	TEST_UNSUPPORTED("cpsid	i,0x13")
+	TEST_UNSUPPORTED("setend	le")
+	TEST_UNSUPPORTED("setend	be")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST_P("pli	[r",0,0b,", #16]")
+	TEST(  "pli	[pc, #0]")
+	TEST_RR("pli	[r",12,0b,", r",0, 16,"]")
+	TEST_RR("pli	[r",0, 0b,", -r",12,16,", lsl #4]")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 5
+	TEST_P("pld	[r",0,32,", #-16]")
+	TEST(  "pld	[pc, #0]")
+	TEST_PR("pld	[r",7, 24, ", r",0, 16,"]")
+	TEST_PR("pld	[r",8, 24, ", -r",12,16,", lsl #4]")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST_SUPPORTED(  ".word 0xf590f000	@ pldw [r0, #0]")
+	TEST_SUPPORTED(  ".word 0xf797f000	@ pldw	[r7, r0]")
+	TEST_SUPPORTED(  ".word 0xf798f18c	@ pldw	[r8, r12, lsl #3]");
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+	TEST_UNSUPPORTED("clrex")
+	TEST_UNSUPPORTED("dsb")
+	TEST_UNSUPPORTED("dmb")
+	TEST_UNSUPPORTED("isb")
+#endif
+
+	verbose("\n");
+}
+
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/kprobes-test.c linux-libre-3.2-gnu/arch/arm/kernel/kprobes-test.c
--- linux-libre-3.1-gnu/arch/arm/kernel/kprobes-test.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/kernel/kprobes-test.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1748 @@
+/*
+ * arch/arm/kernel/kprobes-test.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.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.
+ */
+
+/*
+ * This file contains test code for ARM kprobes.
+ *
+ * The top level function run_all_tests() executes tests for all of the
+ * supported instruction sets: ARM, 16-bit Thumb, and 32-bit Thumb. These tests
+ * fall into two categories; run_api_tests() checks basic functionality of the
+ * kprobes API, and run_test_cases() is a comprehensive test for kprobes
+ * instruction decoding and simulation.
+ *
+ * run_test_cases() first checks the kprobes decoding table for self consistency
+ * (using table_test()) then executes a series of test cases for each of the CPU
+ * instruction forms. coverage_start() and coverage_end() are used to verify
+ * that these test cases cover all of the possible combinations of instructions
+ * described by the kprobes decoding tables.
+ *
+ * The individual test cases are in kprobes-test-arm.c and kprobes-test-thumb.c
+ * which use the macros defined in kprobes-test.h. The rest of this
+ * documentation will describe the operation of the framework used by these
+ * test cases.
+ */
+
+/*
+ * TESTING METHODOLOGY
+ * -------------------
+ *
+ * The methodology used to test an ARM instruction 'test_insn' is to use
+ * inline assembler like:
+ *
+ * test_before: nop
+ * test_case:	test_insn
+ * test_after:	nop
+ *
+ * When the test case is run a kprobe is placed of each nop. The
+ * post-handler of the test_before probe is used to modify the saved CPU
+ * register context to that which we require for the test case. The
+ * pre-handler of the of the test_after probe saves a copy of the CPU
+ * register context. In this way we can execute test_insn with a specific
+ * register context and see the results afterwards.
+ *
+ * To actually test the kprobes instruction emulation we perform the above
+ * step a second time but with an additional kprobe on the test_case
+ * instruction itself. If the emulation is accurate then the results seen
+ * by the test_after probe will be identical to the first run which didn't
+ * have a probe on test_case.
+ *
+ * Each test case is run several times with a variety of variations in the
+ * flags value of stored in CPSR, and for Thumb code, different ITState.
+ *
+ * For instructions which can modify PC, a second test_after probe is used
+ * like this:
+ *
+ * test_before: nop
+ * test_case:	test_insn
+ * test_after:	nop
+ *		b test_done
+ * test_after2: nop
+ * test_done:
+ *
+ * The test case is constructed such that test_insn branches to
+ * test_after2, or, if testing a conditional instruction, it may just
+ * continue to test_after. The probes inserted at both locations let us
+ * determine which happened. A similar approach is used for testing
+ * backwards branches...
+ *
+ *		b test_before
+ *		b test_done  @ helps to cope with off by 1 branches
+ * test_after2: nop
+ *		b test_done
+ * test_before: nop
+ * test_case:	test_insn
+ * test_after:	nop
+ * test_done:
+ *
+ * The macros used to generate the assembler instructions describe above
+ * are TEST_INSTRUCTION, TEST_BRANCH_F (branch forwards) and TEST_BRANCH_B
+ * (branch backwards). In these, the local variables numbered 1, 50, 2 and
+ * 99 represent: test_before, test_case, test_after2 and test_done.
+ *
+ * FRAMEWORK
+ * ---------
+ *
+ * Each test case is wrapped between the pair of macros TESTCASE_START and
+ * TESTCASE_END. As well as performing the inline assembler boilerplate,
+ * these call out to the kprobes_test_case_start() and
+ * kprobes_test_case_end() functions which drive the execution of the test
+ * case. The specific arguments to use for each test case are stored as
+ * inline data constructed using the various TEST_ARG_* macros. Putting
+ * this all together, a simple test case may look like:
+ *
+ *	TESTCASE_START("Testing mov r0, r7")
+ *	TEST_ARG_REG(7, 0x12345678) // Set r7=0x12345678
+ *	TEST_ARG_END("")
+ *	TEST_INSTRUCTION("mov r0, r7")
+ *	TESTCASE_END
+ *
+ * Note, in practice the single convenience macro TEST_R would be used for this
+ * instead.
+ *
+ * The above would expand to assembler looking something like:
+ *
+ *	@ TESTCASE_START
+ *	bl	__kprobes_test_case_start
+ *	@ start of inline data...
+ *	.ascii "mov r0, r7"	@ text title for test case
+ *	.byte	0
+ *	.align	2
+ *
+ *	@ TEST_ARG_REG
+ *	.byte	ARG_TYPE_REG
+ *	.byte	7
+ *	.short	0
+ *	.word	0x1234567
+ *
+ *	@ TEST_ARG_END
+ *	.byte	ARG_TYPE_END
+ *	.byte	TEST_ISA	@ flags, including ISA being tested
+ *	.short	50f-0f		@ offset of 'test_before'
+ *	.short	2f-0f		@ offset of 'test_after2' (if relevent)
+ *	.short	99f-0f		@ offset of 'test_done'
+ *	@ start of test case code...
+ *	0:
+ *	.code	TEST_ISA	@ switch to ISA being tested
+ *
+ *	@ TEST_INSTRUCTION
+ *	50:	nop		@ location for 'test_before' probe
+ *	1:	mov r0, r7	@ the test case instruction 'test_insn'
+ *		nop		@ location for 'test_after' probe
+ *
+ *	// TESTCASE_END
+ *	2:
+ *	99:	bl __kprobes_test_case_end_##TEST_ISA
+ *	.code	NONMAL_ISA
+ *
+ * When the above is execute the following happens...
+ *
+ * __kprobes_test_case_start() is an assembler wrapper which sets up space
+ * for a stack buffer and calls the C function kprobes_test_case_start().
+ * This C function will do some initial processing of the inline data and
+ * setup some global state. It then inserts the test_before and test_after
+ * kprobes and returns a value which causes the assembler wrapper to jump
+ * to the start of the test case code, (local label '0').
+ *
+ * When the test case code executes, the test_before probe will be hit and
+ * test_before_post_handler will call setup_test_context(). This fills the
+ * stack buffer and CPU registers with a test pattern and then processes
+ * the test case arguments. In our example there is one TEST_ARG_REG which
+ * indicates that R7 should be loaded with the value 0x12345678.
+ *
+ * When the test_before probe ends, the test case continues and executes
+ * the "mov r0, r7" instruction. It then hits the test_after probe and the
+ * pre-handler for this (test_after_pre_handler) will save a copy of the
+ * CPU register context. This should now have R0 holding the same value as
+ * R7.
+ *
+ * Finally we get to the call to __kprobes_test_case_end_{32,16}. This is
+ * an assembler wrapper which switches back to the ISA used by the test
+ * code and calls the C function kprobes_test_case_end().
+ *
+ * For each run through the test case, test_case_run_count is incremented
+ * by one. For even runs, kprobes_test_case_end() saves a copy of the
+ * register and stack buffer contents from the test case just run. It then
+ * inserts a kprobe on the test case instruction 'test_insn' and returns a
+ * value to cause the test case code to be re-run.
+ *
+ * For odd numbered runs, kprobes_test_case_end() compares the register and
+ * stack buffer contents to those that were saved on the previous even
+ * numbered run (the one without the kprobe on test_insn). These should be
+ * the same if the kprobe instruction simulation routine is correct.
+ *
+ * The pair of test case runs is repeated with different combinations of
+ * flag values in CPSR and, for Thumb, different ITState. This is
+ * controlled by test_context_cpsr().
+ *
+ * BUILDING TEST CASES
+ * -------------------
+ *
+ *
+ * As an aid to building test cases, the stack buffer is initialised with
+ * some special values:
+ *
+ *   [SP+13*4]	Contains SP+120. This can be used to test instructions
+ *		which load a value into SP.
+ *
+ *   [SP+15*4]	When testing branching instructions using TEST_BRANCH_{F,B},
+ *		this holds the target address of the branch, 'test_after2'.
+ *		This can be used to test instructions which load a PC value
+ *		from memory.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kprobes.h>
+
+#include "kprobes.h"
+#include "kprobes-test.h"
+
+
+#define BENCHMARKING	1
+
+
+/*
+ * Test basic API
+ */
+
+static bool test_regs_ok;
+static int test_func_instance;
+static int pre_handler_called;
+static int post_handler_called;
+static int jprobe_func_called;
+static int kretprobe_handler_called;
+
+#define FUNC_ARG1 0x12345678
+#define FUNC_ARG2 0xabcdef
+
+
+#ifndef CONFIG_THUMB2_KERNEL
+
+long arm_func(long r0, long r1);
+
+static void __used __naked __arm_kprobes_test_func(void)
+{
+	__asm__ __volatile__ (
+		".arm					\n\t"
+		".type arm_func, %%function		\n\t"
+		"arm_func:				\n\t"
+		"adds	r0, r0, r1			\n\t"
+		"bx	lr				\n\t"
+		".code "NORMAL_ISA	 /* Back to Thumb if necessary */
+		: : : "r0", "r1", "cc"
+	);
+}
+
+#else /* CONFIG_THUMB2_KERNEL */
+
+long thumb16_func(long r0, long r1);
+long thumb32even_func(long r0, long r1);
+long thumb32odd_func(long r0, long r1);
+
+static void __used __naked __thumb_kprobes_test_funcs(void)
+{
+	__asm__ __volatile__ (
+		".type thumb16_func, %%function		\n\t"
+		"thumb16_func:				\n\t"
+		"adds.n	r0, r0, r1			\n\t"
+		"bx	lr				\n\t"
+
+		".align					\n\t"
+		".type thumb32even_func, %%function	\n\t"
+		"thumb32even_func:			\n\t"
+		"adds.w	r0, r0, r1			\n\t"
+		"bx	lr				\n\t"
+
+		".align					\n\t"
+		"nop.n					\n\t"
+		".type thumb32odd_func, %%function	\n\t"
+		"thumb32odd_func:			\n\t"
+		"adds.w	r0, r0, r1			\n\t"
+		"bx	lr				\n\t"
+
+		: : : "r0", "r1", "cc"
+	);
+}
+
+#endif /* CONFIG_THUMB2_KERNEL */
+
+
+static int call_test_func(long (*func)(long, long), bool check_test_regs)
+{
+	long ret;
+
+	++test_func_instance;
+	test_regs_ok = false;
+
+	ret = (*func)(FUNC_ARG1, FUNC_ARG2);
+	if (ret != FUNC_ARG1 + FUNC_ARG2) {
+		pr_err("FAIL: call_test_func: func returned %lx\n", ret);
+		return false;
+	}
+
+	if (check_test_regs && !test_regs_ok) {
+		pr_err("FAIL: test regs not OK\n");
+		return false;
+	}
+
+	return true;
+}
+
+static int __kprobes pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	pre_handler_called = test_func_instance;
+	if (regs->ARM_r0 == FUNC_ARG1 && regs->ARM_r1 == FUNC_ARG2)
+		test_regs_ok = true;
+	return 0;
+}
+
+static void __kprobes post_handler(struct kprobe *p, struct pt_regs *regs,
+				unsigned long flags)
+{
+	post_handler_called = test_func_instance;
+	if (regs->ARM_r0 != FUNC_ARG1 + FUNC_ARG2 || regs->ARM_r1 != FUNC_ARG2)
+		test_regs_ok = false;
+}
+
+static struct kprobe the_kprobe = {
+	.addr		= 0,
+	.pre_handler	= pre_handler,
+	.post_handler	= post_handler
+};
+
+static int test_kprobe(long (*func)(long, long))
+{
+	int ret;
+
+	the_kprobe.addr = (kprobe_opcode_t *)func;
+	ret = register_kprobe(&the_kprobe);
+	if (ret < 0) {
+		pr_err("FAIL: register_kprobe failed with %d\n", ret);
+		return ret;
+	}
+
+	ret = call_test_func(func, true);
+
+	unregister_kprobe(&the_kprobe);
+	the_kprobe.flags = 0; /* Clear disable flag to allow reuse */
+
+	if (!ret)
+		return -EINVAL;
+	if (pre_handler_called != test_func_instance) {
+		pr_err("FAIL: kprobe pre_handler not called\n");
+		return -EINVAL;
+	}
+	if (post_handler_called != test_func_instance) {
+		pr_err("FAIL: kprobe post_handler not called\n");
+		return -EINVAL;
+	}
+	if (!call_test_func(func, false))
+		return -EINVAL;
+	if (pre_handler_called == test_func_instance ||
+				post_handler_called == test_func_instance) {
+		pr_err("FAIL: probe called after unregistering\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void __kprobes jprobe_func(long r0, long r1)
+{
+	jprobe_func_called = test_func_instance;
+	if (r0 == FUNC_ARG1 && r1 == FUNC_ARG2)
+		test_regs_ok = true;
+	jprobe_return();
+}
+
+static struct jprobe the_jprobe = {
+	.entry		= jprobe_func,
+};
+
+static int test_jprobe(long (*func)(long, long))
+{
+	int ret;
+
+	the_jprobe.kp.addr = (kprobe_opcode_t *)func;
+	ret = register_jprobe(&the_jprobe);
+	if (ret < 0) {
+		pr_err("FAIL: register_jprobe failed with %d\n", ret);
+		return ret;
+	}
+
+	ret = call_test_func(func, true);
+
+	unregister_jprobe(&the_jprobe);
+	the_jprobe.kp.flags = 0; /* Clear disable flag to allow reuse */
+
+	if (!ret)
+		return -EINVAL;
+	if (jprobe_func_called != test_func_instance) {
+		pr_err("FAIL: jprobe handler function not called\n");
+		return -EINVAL;
+	}
+	if (!call_test_func(func, false))
+		return -EINVAL;
+	if (jprobe_func_called == test_func_instance) {
+		pr_err("FAIL: probe called after unregistering\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int __kprobes
+kretprobe_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+	kretprobe_handler_called = test_func_instance;
+	if (regs_return_value(regs) == FUNC_ARG1 + FUNC_ARG2)
+		test_regs_ok = true;
+	return 0;
+}
+
+static struct kretprobe the_kretprobe = {
+	.handler	= kretprobe_handler,
+};
+
+static int test_kretprobe(long (*func)(long, long))
+{
+	int ret;
+
+	the_kretprobe.kp.addr = (kprobe_opcode_t *)func;
+	ret = register_kretprobe(&the_kretprobe);
+	if (ret < 0) {
+		pr_err("FAIL: register_kretprobe failed with %d\n", ret);
+		return ret;
+	}
+
+	ret = call_test_func(func, true);
+
+	unregister_kretprobe(&the_kretprobe);
+	the_kretprobe.kp.flags = 0; /* Clear disable flag to allow reuse */
+
+	if (!ret)
+		return -EINVAL;
+	if (kretprobe_handler_called != test_func_instance) {
+		pr_err("FAIL: kretprobe handler not called\n");
+		return -EINVAL;
+	}
+	if (!call_test_func(func, false))
+		return -EINVAL;
+	if (jprobe_func_called == test_func_instance) {
+		pr_err("FAIL: kretprobe called after unregistering\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int run_api_tests(long (*func)(long, long))
+{
+	int ret;
+
+	pr_info("    kprobe\n");
+	ret = test_kprobe(func);
+	if (ret < 0)
+		return ret;
+
+	pr_info("    jprobe\n");
+	ret = test_jprobe(func);
+	if (ret < 0)
+		return ret;
+
+	pr_info("    kretprobe\n");
+	ret = test_kretprobe(func);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+
+/*
+ * Benchmarking
+ */
+
+#if BENCHMARKING
+
+static void __naked benchmark_nop(void)
+{
+	__asm__ __volatile__ (
+		"nop		\n\t"
+		"bx	lr"
+	);
+}
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define wide ".w"
+#else
+#define wide
+#endif
+
+static void __naked benchmark_pushpop1(void)
+{
+	__asm__ __volatile__ (
+		"stmdb"wide"	sp!, {r3-r11,lr}  \n\t"
+		"ldmia"wide"	sp!, {r3-r11,pc}"
+	);
+}
+
+static void __naked benchmark_pushpop2(void)
+{
+	__asm__ __volatile__ (
+		"stmdb"wide"	sp!, {r0-r8,lr}  \n\t"
+		"ldmia"wide"	sp!, {r0-r8,pc}"
+	);
+}
+
+static void __naked benchmark_pushpop3(void)
+{
+	__asm__ __volatile__ (
+		"stmdb"wide"	sp!, {r4,lr}  \n\t"
+		"ldmia"wide"	sp!, {r4,pc}"
+	);
+}
+
+static void __naked benchmark_pushpop4(void)
+{
+	__asm__ __volatile__ (
+		"stmdb"wide"	sp!, {r0,lr}  \n\t"
+		"ldmia"wide"	sp!, {r0,pc}"
+	);
+}
+
+
+#ifdef CONFIG_THUMB2_KERNEL
+
+static void __naked benchmark_pushpop_thumb(void)
+{
+	__asm__ __volatile__ (
+		"push.n	{r0-r7,lr}  \n\t"
+		"pop.n	{r0-r7,pc}"
+	);
+}
+
+#endif
+
+static int __kprobes
+benchmark_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	return 0;
+}
+
+static int benchmark(void(*fn)(void))
+{
+	unsigned n, i, t, t0;
+
+	for (n = 1000; ; n *= 2) {
+		t0 = sched_clock();
+		for (i = n; i > 0; --i)
+			fn();
+		t = sched_clock() - t0;
+		if (t >= 250000000)
+			break; /* Stop once we took more than 0.25 seconds */
+	}
+	return t / n; /* Time for one iteration in nanoseconds */
+};
+
+static int kprobe_benchmark(void(*fn)(void), unsigned offset)
+{
+	struct kprobe k = {
+		.addr		= (kprobe_opcode_t *)((uintptr_t)fn + offset),
+		.pre_handler	= benchmark_pre_handler,
+	};
+
+	int ret = register_kprobe(&k);
+	if (ret < 0) {
+		pr_err("FAIL: register_kprobe failed with %d\n", ret);
+		return ret;
+	}
+
+	ret = benchmark(fn);
+
+	unregister_kprobe(&k);
+	return ret;
+};
+
+struct benchmarks {
+	void		(*fn)(void);
+	unsigned	offset;
+	const char	*title;
+};
+
+static int run_benchmarks(void)
+{
+	int ret;
+	struct benchmarks list[] = {
+		{&benchmark_nop, 0, "nop"},
+		/*
+		 * benchmark_pushpop{1,3} will have the optimised
+		 * instruction emulation, whilst benchmark_pushpop{2,4} will
+		 * be the equivalent unoptimised instructions.
+		 */
+		{&benchmark_pushpop1, 0, "stmdb	sp!, {r3-r11,lr}"},
+		{&benchmark_pushpop1, 4, "ldmia	sp!, {r3-r11,pc}"},
+		{&benchmark_pushpop2, 0, "stmdb	sp!, {r0-r8,lr}"},
+		{&benchmark_pushpop2, 4, "ldmia	sp!, {r0-r8,pc}"},
+		{&benchmark_pushpop3, 0, "stmdb	sp!, {r4,lr}"},
+		{&benchmark_pushpop3, 4, "ldmia	sp!, {r4,pc}"},
+		{&benchmark_pushpop4, 0, "stmdb	sp!, {r0,lr}"},
+		{&benchmark_pushpop4, 4, "ldmia	sp!, {r0,pc}"},
+#ifdef CONFIG_THUMB2_KERNEL
+		{&benchmark_pushpop_thumb, 0, "push.n	{r0-r7,lr}"},
+		{&benchmark_pushpop_thumb, 2, "pop.n	{r0-r7,pc}"},
+#endif
+		{0}
+	};
+
+	struct benchmarks *b;
+	for (b = list; b->fn; ++b) {
+		ret = kprobe_benchmark(b->fn, b->offset);
+		if (ret < 0)
+			return ret;
+		pr_info("    %dns for kprobe %s\n", ret, b->title);
+	}
+
+	pr_info("\n");
+	return 0;
+}
+
+#endif /* BENCHMARKING */
+
+
+/*
+ * Decoding table self-consistency tests
+ */
+
+static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
+	[DECODE_TYPE_TABLE]	= sizeof(struct decode_table),
+	[DECODE_TYPE_CUSTOM]	= sizeof(struct decode_custom),
+	[DECODE_TYPE_SIMULATE]	= sizeof(struct decode_simulate),
+	[DECODE_TYPE_EMULATE]	= sizeof(struct decode_emulate),
+	[DECODE_TYPE_OR]	= sizeof(struct decode_or),
+	[DECODE_TYPE_REJECT]	= sizeof(struct decode_reject)
+};
+
+static int table_iter(const union decode_item *table,
+			int (*fn)(const struct decode_header *, void *),
+			void *args)
+{
+	const struct decode_header *h = (struct decode_header *)table;
+	int result;
+
+	for (;;) {
+		enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+
+		if (type == DECODE_TYPE_END)
+			return 0;
+
+		result = fn(h, args);
+		if (result)
+			return result;
+
+		h = (struct decode_header *)
+			((uintptr_t)h + decode_struct_sizes[type]);
+
+	}
+}
+
+static int table_test_fail(const struct decode_header *h, const char* message)
+{
+
+	pr_err("FAIL: kprobes test failure \"%s\" (mask %08x, value %08x)\n",
+					message, h->mask.bits, h->value.bits);
+	return -EINVAL;
+}
+
+struct table_test_args {
+	const union decode_item *root_table;
+	u32			parent_mask;
+	u32			parent_value;
+};
+
+static int table_test_fn(const struct decode_header *h, void *args)
+{
+	struct table_test_args *a = (struct table_test_args *)args;
+	enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+
+	if (h->value.bits & ~h->mask.bits)
+		return table_test_fail(h, "Match value has bits not in mask");
+
+	if ((h->mask.bits & a->parent_mask) != a->parent_mask)
+		return table_test_fail(h, "Mask has bits not in parent mask");
+
+	if ((h->value.bits ^ a->parent_value) & a->parent_mask)
+		return table_test_fail(h, "Value is inconsistent with parent");
+
+	if (type == DECODE_TYPE_TABLE) {
+		struct decode_table *d = (struct decode_table *)h;
+		struct table_test_args args2 = *a;
+		args2.parent_mask = h->mask.bits;
+		args2.parent_value = h->value.bits;
+		return table_iter(d->table.table, table_test_fn, &args2);
+	}
+
+	return 0;
+}
+
+static int table_test(const union decode_item *table)
+{
+	struct table_test_args args = {
+		.root_table	= table,
+		.parent_mask	= 0,
+		.parent_value	= 0
+	};
+	return table_iter(args.root_table, table_test_fn, &args);
+}
+
+
+/*
+ * Decoding table test coverage analysis
+ *
+ * coverage_start() builds a coverage_table which contains a list of
+ * coverage_entry's to match each entry in the specified kprobes instruction
+ * decoding table.
+ *
+ * When test cases are run, coverage_add() is called to process each case.
+ * This looks up the corresponding entry in the coverage_table and sets it as
+ * being matched, as well as clearing the regs flag appropriate for the test.
+ *
+ * After all test cases have been run, coverage_end() is called to check that
+ * all entries in coverage_table have been matched and that all regs flags are
+ * cleared. I.e. that all possible combinations of instructions described by
+ * the kprobes decoding tables have had a test case executed for them.
+ */
+
+bool coverage_fail;
+
+#define MAX_COVERAGE_ENTRIES 256
+
+struct coverage_entry {
+	const struct decode_header	*header;
+	unsigned			regs;
+	unsigned			nesting;
+	char				matched;
+};
+
+struct coverage_table {
+	struct coverage_entry	*base;
+	unsigned		num_entries;
+	unsigned		nesting;
+};
+
+struct coverage_table coverage;
+
+#define COVERAGE_ANY_REG	(1<<0)
+#define COVERAGE_SP		(1<<1)
+#define COVERAGE_PC		(1<<2)
+#define COVERAGE_PCWB		(1<<3)
+
+static const char coverage_register_lookup[16] = {
+	[REG_TYPE_ANY]		= COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC,
+	[REG_TYPE_SAMEAS16]	= COVERAGE_ANY_REG,
+	[REG_TYPE_SP]		= COVERAGE_SP,
+	[REG_TYPE_PC]		= COVERAGE_PC,
+	[REG_TYPE_NOSP]		= COVERAGE_ANY_REG | COVERAGE_SP,
+	[REG_TYPE_NOSPPC]	= COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC,
+	[REG_TYPE_NOPC]		= COVERAGE_ANY_REG | COVERAGE_PC,
+	[REG_TYPE_NOPCWB]	= COVERAGE_ANY_REG | COVERAGE_PC | COVERAGE_PCWB,
+	[REG_TYPE_NOPCX]	= COVERAGE_ANY_REG,
+	[REG_TYPE_NOSPPCX]	= COVERAGE_ANY_REG | COVERAGE_SP,
+};
+
+unsigned coverage_start_registers(const struct decode_header *h)
+{
+	unsigned regs = 0;
+	int i;
+	for (i = 0; i < 20; i += 4) {
+		int r = (h->type_regs.bits >> (DECODE_TYPE_BITS + i)) & 0xf;
+		regs |= coverage_register_lookup[r] << i;
+	}
+	return regs;
+}
+
+static int coverage_start_fn(const struct decode_header *h, void *args)
+{
+	struct coverage_table *coverage = (struct coverage_table *)args;
+	enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+	struct coverage_entry *entry = coverage->base + coverage->num_entries;
+
+	if (coverage->num_entries == MAX_COVERAGE_ENTRIES - 1) {
+		pr_err("FAIL: Out of space for test coverage data");
+		return -ENOMEM;
+	}
+
+	++coverage->num_entries;
+
+	entry->header = h;
+	entry->regs = coverage_start_registers(h);
+	entry->nesting = coverage->nesting;
+	entry->matched = false;
+
+	if (type == DECODE_TYPE_TABLE) {
+		struct decode_table *d = (struct decode_table *)h;
+		int ret;
+		++coverage->nesting;
+		ret = table_iter(d->table.table, coverage_start_fn, coverage);
+		--coverage->nesting;
+		return ret;
+	}
+
+	return 0;
+}
+
+static int coverage_start(const union decode_item *table)
+{
+	coverage.base = kmalloc(MAX_COVERAGE_ENTRIES *
+				sizeof(struct coverage_entry), GFP_KERNEL);
+	coverage.num_entries = 0;
+	coverage.nesting = 0;
+	return table_iter(table, coverage_start_fn, &coverage);
+}
+
+static void
+coverage_add_registers(struct coverage_entry *entry, kprobe_opcode_t insn)
+{
+	int regs = entry->header->type_regs.bits >> DECODE_TYPE_BITS;
+	int i;
+	for (i = 0; i < 20; i += 4) {
+		enum decode_reg_type reg_type = (regs >> i) & 0xf;
+		int reg = (insn >> i) & 0xf;
+		int flag;
+
+		if (!reg_type)
+			continue;
+
+		if (reg == 13)
+			flag = COVERAGE_SP;
+		else if (reg == 15)
+			flag = COVERAGE_PC;
+		else
+			flag = COVERAGE_ANY_REG;
+		entry->regs &= ~(flag << i);
+
+		switch (reg_type) {
+
+		case REG_TYPE_NONE:
+		case REG_TYPE_ANY:
+		case REG_TYPE_SAMEAS16:
+			break;
+
+		case REG_TYPE_SP:
+			if (reg != 13)
+				return;
+			break;
+
+		case REG_TYPE_PC:
+			if (reg != 15)
+				return;
+			break;
+
+		case REG_TYPE_NOSP:
+			if (reg == 13)
+				return;
+			break;
+
+		case REG_TYPE_NOSPPC:
+		case REG_TYPE_NOSPPCX:
+			if (reg == 13 || reg == 15)
+				return;
+			break;
+
+		case REG_TYPE_NOPCWB:
+			if (!is_writeback(insn))
+				break;
+			if (reg == 15) {
+				entry->regs &= ~(COVERAGE_PCWB << i);
+				return;
+			}
+			break;
+
+		case REG_TYPE_NOPC:
+		case REG_TYPE_NOPCX:
+			if (reg == 15)
+				return;
+			break;
+		}
+
+	}
+}
+
+static void coverage_add(kprobe_opcode_t insn)
+{
+	struct coverage_entry *entry = coverage.base;
+	struct coverage_entry *end = coverage.base + coverage.num_entries;
+	bool matched = false;
+	unsigned nesting = 0;
+
+	for (; entry < end; ++entry) {
+		const struct decode_header *h = entry->header;
+		enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+
+		if (entry->nesting > nesting)
+			continue; /* Skip sub-table we didn't match */
+
+		if (entry->nesting < nesting)
+			break; /* End of sub-table we were scanning */
+
+		if (!matched) {
+			if ((insn & h->mask.bits) != h->value.bits)
+				continue;
+			entry->matched = true;
+		}
+
+		switch (type) {
+
+		case DECODE_TYPE_TABLE:
+			++nesting;
+			break;
+
+		case DECODE_TYPE_CUSTOM:
+		case DECODE_TYPE_SIMULATE:
+		case DECODE_TYPE_EMULATE:
+			coverage_add_registers(entry, insn);
+			return;
+
+		case DECODE_TYPE_OR:
+			matched = true;
+			break;
+
+		case DECODE_TYPE_REJECT:
+		default:
+			return;
+		}
+
+	}
+}
+
+static void coverage_end(void)
+{
+	struct coverage_entry *entry = coverage.base;
+	struct coverage_entry *end = coverage.base + coverage.num_entries;
+
+	for (; entry < end; ++entry) {
+		u32 mask = entry->header->mask.bits;
+		u32 value = entry->header->value.bits;
+
+		if (entry->regs) {
+			pr_err("FAIL: Register test coverage missing for %08x %08x (%05x)\n",
+				mask, value, entry->regs);
+			coverage_fail = true;
+		}
+		if (!entry->matched) {
+			pr_err("FAIL: Test coverage entry missing for %08x %08x\n",
+				mask, value);
+			coverage_fail = true;
+		}
+	}
+
+	kfree(coverage.base);
+}
+
+
+/*
+ * Framework for instruction set test cases
+ */
+
+void __naked __kprobes_test_case_start(void)
+{
+	__asm__ __volatile__ (
+		"stmdb	sp!, {r4-r11}				\n\t"
+		"sub	sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
+		"bic	r0, lr, #1  @ r0 = inline title string	\n\t"
+		"mov	r1, sp					\n\t"
+		"bl	kprobes_test_case_start			\n\t"
+		"bx	r0					\n\t"
+	);
+}
+
+#ifndef CONFIG_THUMB2_KERNEL
+
+void __naked __kprobes_test_case_end_32(void)
+{
+	__asm__ __volatile__ (
+		"mov	r4, lr					\n\t"
+		"bl	kprobes_test_case_end			\n\t"
+		"cmp	r0, #0					\n\t"
+		"movne	pc, r0					\n\t"
+		"mov	r0, r4					\n\t"
+		"add	sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
+		"ldmia	sp!, {r4-r11}				\n\t"
+		"mov	pc, r0					\n\t"
+	);
+}
+
+#else /* CONFIG_THUMB2_KERNEL */
+
+void __naked __kprobes_test_case_end_16(void)
+{
+	__asm__ __volatile__ (
+		"mov	r4, lr					\n\t"
+		"bl	kprobes_test_case_end			\n\t"
+		"cmp	r0, #0					\n\t"
+		"bxne	r0					\n\t"
+		"mov	r0, r4					\n\t"
+		"add	sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
+		"ldmia	sp!, {r4-r11}				\n\t"
+		"bx	r0					\n\t"
+	);
+}
+
+void __naked __kprobes_test_case_end_32(void)
+{
+	__asm__ __volatile__ (
+		".arm						\n\t"
+		"orr	lr, lr, #1  @ will return to Thumb code	\n\t"
+		"ldr	pc, 1f					\n\t"
+		"1:						\n\t"
+		".word	__kprobes_test_case_end_16		\n\t"
+	);
+}
+
+#endif
+
+
+int kprobe_test_flags;
+int kprobe_test_cc_position;
+
+static int test_try_count;
+static int test_pass_count;
+static int test_fail_count;
+
+static struct pt_regs initial_regs;
+static struct pt_regs expected_regs;
+static struct pt_regs result_regs;
+
+static u32 expected_memory[TEST_MEMORY_SIZE/sizeof(u32)];
+
+static const char *current_title;
+static struct test_arg *current_args;
+static u32 *current_stack;
+static uintptr_t current_branch_target;
+
+static uintptr_t current_code_start;
+static kprobe_opcode_t current_instruction;
+
+
+#define TEST_CASE_PASSED -1
+#define TEST_CASE_FAILED -2
+
+static int test_case_run_count;
+static bool test_case_is_thumb;
+static int test_instance;
+
+/*
+ * We ignore the state of the imprecise abort disable flag (CPSR.A) because this
+ * can change randomly as the kernel doesn't take care to preserve or initialise
+ * this across context switches. Also, with Security Extentions, the flag may
+ * not be under control of the kernel; for this reason we ignore the state of
+ * the FIQ disable flag CPSR.F as well.
+ */
+#define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT)
+
+static unsigned long test_check_cc(int cc, unsigned long cpsr)
+{
+	unsigned long temp;
+
+	switch (cc) {
+	case 0x0: /* eq */
+		return cpsr & PSR_Z_BIT;
+
+	case 0x1: /* ne */
+		return (~cpsr) & PSR_Z_BIT;
+
+	case 0x2: /* cs */
+		return cpsr & PSR_C_BIT;
+
+	case 0x3: /* cc */
+		return (~cpsr) & PSR_C_BIT;
+
+	case 0x4: /* mi */
+		return cpsr & PSR_N_BIT;
+
+	case 0x5: /* pl */
+		return (~cpsr) & PSR_N_BIT;
+
+	case 0x6: /* vs */
+		return cpsr & PSR_V_BIT;
+
+	case 0x7: /* vc */
+		return (~cpsr) & PSR_V_BIT;
+
+	case 0x8: /* hi */
+		cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+		return cpsr & PSR_C_BIT;
+
+	case 0x9: /* ls */
+		cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+		return (~cpsr) & PSR_C_BIT;
+
+	case 0xa: /* ge */
+		cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+		return (~cpsr) & PSR_N_BIT;
+
+	case 0xb: /* lt */
+		cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+		return cpsr & PSR_N_BIT;
+
+	case 0xc: /* gt */
+		temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+		temp |= (cpsr << 1);	   /* PSR_N_BIT |= PSR_Z_BIT */
+		return (~temp) & PSR_N_BIT;
+
+	case 0xd: /* le */
+		temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+		temp |= (cpsr << 1);	   /* PSR_N_BIT |= PSR_Z_BIT */
+		return temp & PSR_N_BIT;
+
+	case 0xe: /* al */
+	case 0xf: /* unconditional */
+		return true;
+	}
+	BUG();
+	return false;
+}
+
+static int is_last_scenario;
+static int probe_should_run; /* 0 = no, 1 = yes, -1 = unknown */
+static int memory_needs_checking;
+
+static unsigned long test_context_cpsr(int scenario)
+{
+	unsigned long cpsr;
+
+	probe_should_run = 1;
+
+	/* Default case is that we cycle through 16 combinations of flags */
+	cpsr  = (scenario & 0xf) << 28; /* N,Z,C,V flags */
+	cpsr |= (scenario & 0xf) << 16; /* GE flags */
+	cpsr |= (scenario & 0x1) << 27; /* Toggle Q flag */
+
+	if (!test_case_is_thumb) {
+		/* Testing ARM code */
+		probe_should_run = test_check_cc(current_instruction >> 28, cpsr) != 0;
+		if (scenario == 15)
+			is_last_scenario = true;
+
+	} else if (kprobe_test_flags & TEST_FLAG_NO_ITBLOCK) {
+		/* Testing Thumb code without setting ITSTATE */
+		if (kprobe_test_cc_position) {
+			int cc = (current_instruction >> kprobe_test_cc_position) & 0xf;
+			probe_should_run = test_check_cc(cc, cpsr) != 0;
+		}
+
+		if (scenario == 15)
+			is_last_scenario = true;
+
+	} else if (kprobe_test_flags & TEST_FLAG_FULL_ITBLOCK) {
+		/* Testing Thumb code with all combinations of ITSTATE */
+		unsigned x = (scenario >> 4);
+		unsigned cond_base = x % 7; /* ITSTATE<7:5> */
+		unsigned mask = x / 7 + 2;  /* ITSTATE<4:0>, bits reversed */
+
+		if (mask > 0x1f) {
+			/* Finish by testing state from instruction 'itt al' */
+			cond_base = 7;
+			mask = 0x4;
+			if ((scenario & 0xf) == 0xf)
+				is_last_scenario = true;
+		}
+
+		cpsr |= cond_base << 13;	/* ITSTATE<7:5> */
+		cpsr |= (mask & 0x1) << 12;	/* ITSTATE<4> */
+		cpsr |= (mask & 0x2) << 10;	/* ITSTATE<3> */
+		cpsr |= (mask & 0x4) << 8;	/* ITSTATE<2> */
+		cpsr |= (mask & 0x8) << 23;	/* ITSTATE<1> */
+		cpsr |= (mask & 0x10) << 21;	/* ITSTATE<0> */
+
+		probe_should_run = test_check_cc((cpsr >> 12) & 0xf, cpsr) != 0;
+
+	} else {
+		/* Testing Thumb code with several combinations of ITSTATE */
+		switch (scenario) {
+		case 16: /* Clear NZCV flags and 'it eq' state (false as Z=0) */
+			cpsr = 0x00000800;
+			probe_should_run = 0;
+			break;
+		case 17: /* Set NZCV flags and 'it vc' state (false as V=1) */
+			cpsr = 0xf0007800;
+			probe_should_run = 0;
+			break;
+		case 18: /* Clear NZCV flags and 'it ls' state (true as C=0) */
+			cpsr = 0x00009800;
+			break;
+		case 19: /* Set NZCV flags and 'it cs' state (true as C=1) */
+			cpsr = 0xf0002800;
+			is_last_scenario = true;
+			break;
+		}
+	}
+
+	return cpsr;
+}
+
+static void setup_test_context(struct pt_regs *regs)
+{
+	int scenario = test_case_run_count>>1;
+	unsigned long val;
+	struct test_arg *args;
+	int i;
+
+	is_last_scenario = false;
+	memory_needs_checking = false;
+
+	/* Initialise test memory on stack */
+	val = (scenario & 1) ? VALM : ~VALM;
+	for (i = 0; i < TEST_MEMORY_SIZE / sizeof(current_stack[0]); ++i)
+		current_stack[i] = val + (i << 8);
+	/* Put target of branch on stack for tests which load PC from memory */
+	if (current_branch_target)
+		current_stack[15] = current_branch_target;
+	/* Put a value for SP on stack for tests which load SP from memory */
+	current_stack[13] = (u32)current_stack + 120;
+
+	/* Initialise register values to their default state */
+	val = (scenario & 2) ? VALR : ~VALR;
+	for (i = 0; i < 13; ++i)
+		regs->uregs[i] = val ^ (i << 8);
+	regs->ARM_lr = val ^ (14 << 8);
+	regs->ARM_cpsr &= ~(APSR_MASK | PSR_IT_MASK);
+	regs->ARM_cpsr |= test_context_cpsr(scenario);
+
+	/* Perform testcase specific register setup  */
+	args = current_args;
+	for (; args[0].type != ARG_TYPE_END; ++args)
+		switch (args[0].type) {
+		case ARG_TYPE_REG: {
+			struct test_arg_regptr *arg =
+				(struct test_arg_regptr *)args;
+			regs->uregs[arg->reg] = arg->val;
+			break;
+		}
+		case ARG_TYPE_PTR: {
+			struct test_arg_regptr *arg =
+				(struct test_arg_regptr *)args;
+			regs->uregs[arg->reg] =
+				(unsigned long)current_stack + arg->val;
+			memory_needs_checking = true;
+			break;
+		}
+		case ARG_TYPE_MEM: {
+			struct test_arg_mem *arg = (struct test_arg_mem *)args;
+			current_stack[arg->index] = arg->val;
+			break;
+		}
+		default:
+			break;
+		}
+}
+
+struct test_probe {
+	struct kprobe	kprobe;
+	bool		registered;
+	int		hit;
+};
+
+static void unregister_test_probe(struct test_probe *probe)
+{
+	if (probe->registered) {
+		unregister_kprobe(&probe->kprobe);
+		probe->kprobe.flags = 0; /* Clear disable flag to allow reuse */
+	}
+	probe->registered = false;
+}
+
+static int register_test_probe(struct test_probe *probe)
+{
+	int ret;
+
+	if (probe->registered)
+		BUG();
+
+	ret = register_kprobe(&probe->kprobe);
+	if (ret >= 0) {
+		probe->registered = true;
+		probe->hit = -1;
+	}
+	return ret;
+}
+
+static int __kprobes
+test_before_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	container_of(p, struct test_probe, kprobe)->hit = test_instance;
+	return 0;
+}
+
+static void __kprobes
+test_before_post_handler(struct kprobe *p, struct pt_regs *regs,
+							unsigned long flags)
+{
+	setup_test_context(regs);
+	initial_regs = *regs;
+	initial_regs.ARM_cpsr &= ~PSR_IGNORE_BITS;
+}
+
+static int __kprobes
+test_case_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	container_of(p, struct test_probe, kprobe)->hit = test_instance;
+	return 0;
+}
+
+static int __kprobes
+test_after_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	if (container_of(p, struct test_probe, kprobe)->hit == test_instance)
+		return 0; /* Already run for this test instance */
+
+	result_regs = *regs;
+	result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS;
+
+	/* Undo any changes done to SP by the test case */
+	regs->ARM_sp = (unsigned long)current_stack;
+
+	container_of(p, struct test_probe, kprobe)->hit = test_instance;
+	return 0;
+}
+
+static struct test_probe test_before_probe = {
+	.kprobe.pre_handler	= test_before_pre_handler,
+	.kprobe.post_handler	= test_before_post_handler,
+};
+
+static struct test_probe test_case_probe = {
+	.kprobe.pre_handler	= test_case_pre_handler,
+};
+
+static struct test_probe test_after_probe = {
+	.kprobe.pre_handler	= test_after_pre_handler,
+};
+
+static struct test_probe test_after2_probe = {
+	.kprobe.pre_handler	= test_after_pre_handler,
+};
+
+static void test_case_cleanup(void)
+{
+	unregister_test_probe(&test_before_probe);
+	unregister_test_probe(&test_case_probe);
+	unregister_test_probe(&test_after_probe);
+	unregister_test_probe(&test_after2_probe);
+}
+
+static void print_registers(struct pt_regs *regs)
+{
+	pr_err("r0  %08lx | r1  %08lx | r2  %08lx | r3  %08lx\n",
+		regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
+	pr_err("r4  %08lx | r5  %08lx | r6  %08lx | r7  %08lx\n",
+		regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7);
+	pr_err("r8  %08lx | r9  %08lx | r10 %08lx | r11 %08lx\n",
+		regs->ARM_r8, regs->ARM_r9, regs->ARM_r10, regs->ARM_fp);
+	pr_err("r12 %08lx | sp  %08lx | lr  %08lx | pc  %08lx\n",
+		regs->ARM_ip, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc);
+	pr_err("cpsr %08lx\n", regs->ARM_cpsr);
+}
+
+static void print_memory(u32 *mem, size_t size)
+{
+	int i;
+	for (i = 0; i < size / sizeof(u32); i += 4)
+		pr_err("%08x %08x %08x %08x\n", mem[i], mem[i+1],
+						mem[i+2], mem[i+3]);
+}
+
+static size_t expected_memory_size(u32 *sp)
+{
+	size_t size = sizeof(expected_memory);
+	int offset = (uintptr_t)sp - (uintptr_t)current_stack;
+	if (offset > 0)
+		size -= offset;
+	return size;
+}
+
+static void test_case_failed(const char *message)
+{
+	test_case_cleanup();
+
+	pr_err("FAIL: %s\n", message);
+	pr_err("FAIL: Test %s\n", current_title);
+	pr_err("FAIL: Scenario %d\n", test_case_run_count >> 1);
+}
+
+static unsigned long next_instruction(unsigned long pc)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+	if ((pc & 1) && !is_wide_instruction(*(u16 *)(pc - 1)))
+		return pc + 2;
+	else
+#endif
+	return pc + 4;
+}
+
+static uintptr_t __used kprobes_test_case_start(const char *title, void *stack)
+{
+	struct test_arg *args;
+	struct test_arg_end *end_arg;
+	unsigned long test_code;
+
+	args = (struct test_arg *)PTR_ALIGN(title + strlen(title) + 1, 4);
+
+	current_title = title;
+	current_args = args;
+	current_stack = stack;
+
+	++test_try_count;
+
+	while (args->type != ARG_TYPE_END)
+		++args;
+	end_arg = (struct test_arg_end *)args;
+
+	test_code = (unsigned long)(args + 1); /* Code starts after args */
+
+	test_case_is_thumb = end_arg->flags & ARG_FLAG_THUMB;
+	if (test_case_is_thumb)
+		test_code |= 1;
+
+	current_code_start = test_code;
+
+	current_branch_target = 0;
+	if (end_arg->branch_offset != end_arg->end_offset)
+		current_branch_target = test_code + end_arg->branch_offset;
+
+	test_code += end_arg->code_offset;
+	test_before_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
+
+	test_code = next_instruction(test_code);
+	test_case_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
+
+	if (test_case_is_thumb) {
+		u16 *p = (u16 *)(test_code & ~1);
+		current_instruction = p[0];
+		if (is_wide_instruction(current_instruction)) {
+			current_instruction <<= 16;
+			current_instruction |= p[1];
+		}
+	} else {
+		current_instruction = *(u32 *)test_code;
+	}
+
+	if (current_title[0] == '.')
+		verbose("%s\n", current_title);
+	else
+		verbose("%s\t@ %0*x\n", current_title,
+					test_case_is_thumb ? 4 : 8,
+					current_instruction);
+
+	test_code = next_instruction(test_code);
+	test_after_probe.kprobe.addr = (kprobe_opcode_t *)test_code;
+
+	if (kprobe_test_flags & TEST_FLAG_NARROW_INSTR) {
+		if (!test_case_is_thumb ||
+			is_wide_instruction(current_instruction)) {
+				test_case_failed("expected 16-bit instruction");
+				goto fail;
+		}
+	} else {
+		if (test_case_is_thumb &&
+			!is_wide_instruction(current_instruction)) {
+				test_case_failed("expected 32-bit instruction");
+				goto fail;
+		}
+	}
+
+	coverage_add(current_instruction);
+
+	if (end_arg->flags & ARG_FLAG_UNSUPPORTED) {
+		if (register_test_probe(&test_case_probe) < 0)
+			goto pass;
+		test_case_failed("registered probe for unsupported instruction");
+		goto fail;
+	}
+
+	if (end_arg->flags & ARG_FLAG_SUPPORTED) {
+		if (register_test_probe(&test_case_probe) >= 0)
+			goto pass;
+		test_case_failed("couldn't register probe for supported instruction");
+		goto fail;
+	}
+
+	if (register_test_probe(&test_before_probe) < 0) {
+		test_case_failed("register test_before_probe failed");
+		goto fail;
+	}
+	if (register_test_probe(&test_after_probe) < 0) {
+		test_case_failed("register test_after_probe failed");
+		goto fail;
+	}
+	if (current_branch_target) {
+		test_after2_probe.kprobe.addr =
+				(kprobe_opcode_t *)current_branch_target;
+		if (register_test_probe(&test_after2_probe) < 0) {
+			test_case_failed("register test_after2_probe failed");
+			goto fail;
+		}
+	}
+
+	/* Start first run of test case */
+	test_case_run_count = 0;
+	++test_instance;
+	return current_code_start;
+pass:
+	test_case_run_count = TEST_CASE_PASSED;
+	return (uintptr_t)test_after_probe.kprobe.addr;
+fail:
+	test_case_run_count = TEST_CASE_FAILED;
+	return (uintptr_t)test_after_probe.kprobe.addr;
+}
+
+static bool check_test_results(void)
+{
+	size_t mem_size = 0;
+	u32 *mem = 0;
+
+	if (memcmp(&expected_regs, &result_regs, sizeof(expected_regs))) {
+		test_case_failed("registers differ");
+		goto fail;
+	}
+
+	if (memory_needs_checking) {
+		mem = (u32 *)result_regs.ARM_sp;
+		mem_size = expected_memory_size(mem);
+		if (memcmp(expected_memory, mem, mem_size)) {
+			test_case_failed("test memory differs");
+			goto fail;
+		}
+	}
+
+	return true;
+
+fail:
+	pr_err("initial_regs:\n");
+	print_registers(&initial_regs);
+	pr_err("expected_regs:\n");
+	print_registers(&expected_regs);
+	pr_err("result_regs:\n");
+	print_registers(&result_regs);
+
+	if (mem) {
+		pr_err("current_stack=%p\n", current_stack);
+		pr_err("expected_memory:\n");
+		print_memory(expected_memory, mem_size);
+		pr_err("result_memory:\n");
+		print_memory(mem, mem_size);
+	}
+
+	return false;
+}
+
+static uintptr_t __used kprobes_test_case_end(void)
+{
+	if (test_case_run_count < 0) {
+		if (test_case_run_count == TEST_CASE_PASSED)
+			/* kprobes_test_case_start did all the needed testing */
+			goto pass;
+		else
+			/* kprobes_test_case_start failed */
+			goto fail;
+	}
+
+	if (test_before_probe.hit != test_instance) {
+		test_case_failed("test_before_handler not run");
+		goto fail;
+	}
+
+	if (test_after_probe.hit != test_instance &&
+				test_after2_probe.hit != test_instance) {
+		test_case_failed("test_after_handler not run");
+		goto fail;
+	}
+
+	/*
+	 * Even numbered test runs ran without a probe on the test case so
+	 * we can gather reference results. The subsequent odd numbered run
+	 * will have the probe inserted.
+	*/
+	if ((test_case_run_count & 1) == 0) {
+		/* Save results from run without probe */
+		u32 *mem = (u32 *)result_regs.ARM_sp;
+		expected_regs = result_regs;
+		memcpy(expected_memory, mem, expected_memory_size(mem));
+
+		/* Insert probe onto test case instruction */
+		if (register_test_probe(&test_case_probe) < 0) {
+			test_case_failed("register test_case_probe failed");
+			goto fail;
+		}
+	} else {
+		/* Check probe ran as expected */
+		if (probe_should_run == 1) {
+			if (test_case_probe.hit != test_instance) {
+				test_case_failed("test_case_handler not run");
+				goto fail;
+			}
+		} else if (probe_should_run == 0) {
+			if (test_case_probe.hit == test_instance) {
+				test_case_failed("test_case_handler ran");
+				goto fail;
+			}
+		}
+
+		/* Remove probe for any subsequent reference run */
+		unregister_test_probe(&test_case_probe);
+
+		if (!check_test_results())
+			goto fail;
+
+		if (is_last_scenario)
+			goto pass;
+	}
+
+	/* Do next test run */
+	++test_case_run_count;
+	++test_instance;
+	return current_code_start;
+fail:
+	++test_fail_count;
+	goto end;
+pass:
+	++test_pass_count;
+end:
+	test_case_cleanup();
+	return 0;
+}
+
+
+/*
+ * Top level test functions
+ */
+
+static int run_test_cases(void (*tests)(void), const union decode_item *table)
+{
+	int ret;
+
+	pr_info("    Check decoding tables\n");
+	ret = table_test(table);
+	if (ret)
+		return ret;
+
+	pr_info("    Run test cases\n");
+	ret = coverage_start(table);
+	if (ret)
+		return ret;
+
+	tests();
+
+	coverage_end();
+	return 0;
+}
+
+
+static int __init run_all_tests(void)
+{
+	int ret = 0;
+
+	pr_info("Begining kprobe tests...\n");
+
+#ifndef CONFIG_THUMB2_KERNEL
+
+	pr_info("Probe ARM code\n");
+	ret = run_api_tests(arm_func);
+	if (ret)
+		goto out;
+
+	pr_info("ARM instruction simulation\n");
+	ret = run_test_cases(kprobe_arm_test_cases, kprobe_decode_arm_table);
+	if (ret)
+		goto out;
+
+#else /* CONFIG_THUMB2_KERNEL */
+
+	pr_info("Probe 16-bit Thumb code\n");
+	ret = run_api_tests(thumb16_func);
+	if (ret)
+		goto out;
+
+	pr_info("Probe 32-bit Thumb code, even halfword\n");
+	ret = run_api_tests(thumb32even_func);
+	if (ret)
+		goto out;
+
+	pr_info("Probe 32-bit Thumb code, odd halfword\n");
+	ret = run_api_tests(thumb32odd_func);
+	if (ret)
+		goto out;
+
+	pr_info("16-bit Thumb instruction simulation\n");
+	ret = run_test_cases(kprobe_thumb16_test_cases,
+				kprobe_decode_thumb16_table);
+	if (ret)
+		goto out;
+
+	pr_info("32-bit Thumb instruction simulation\n");
+	ret = run_test_cases(kprobe_thumb32_test_cases,
+				kprobe_decode_thumb32_table);
+	if (ret)
+		goto out;
+#endif
+
+	pr_info("Total instruction simulation tests=%d, pass=%d fail=%d\n",
+		test_try_count, test_pass_count, test_fail_count);
+	if (test_fail_count) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+#if BENCHMARKING
+	pr_info("Benchmarks\n");
+	ret = run_benchmarks();
+	if (ret)
+		goto out;
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+	/* We are able to run all test cases so coverage should be complete */
+	if (coverage_fail) {
+		pr_err("FAIL: Test coverage checks failed\n");
+		ret = -EINVAL;
+		goto out;
+	}
+#endif
+
+out:
+	if (ret == 0)
+		pr_info("Finished kprobe tests OK\n");
+	else
+		pr_err("kprobe tests failed\n");
+
+	return ret;
+}
+
+
+/*
+ * Module setup
+ */
+
+#ifdef MODULE
+
+static void __exit kprobe_test_exit(void)
+{
+}
+
+module_init(run_all_tests)
+module_exit(kprobe_test_exit)
+MODULE_LICENSE("GPL");
+
+#else /* !MODULE */
+
+late_initcall(run_all_tests);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/kprobes-test.h linux-libre-3.2-gnu/arch/arm/kernel/kprobes-test.h
--- linux-libre-3.1-gnu/arch/arm/kernel/kprobes-test.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/kernel/kprobes-test.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,432 @@
+/*
+ * arch/arm/kernel/kprobes-test.h
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define VERBOSE 0 /* Set to '1' for more logging of test cases */
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define NORMAL_ISA "16"
+#else
+#define NORMAL_ISA "32"
+#endif
+
+
+/* Flags used in kprobe_test_flags */
+#define TEST_FLAG_NO_ITBLOCK	(1<<0)
+#define TEST_FLAG_FULL_ITBLOCK	(1<<1)
+#define TEST_FLAG_NARROW_INSTR	(1<<2)
+
+extern int kprobe_test_flags;
+extern int kprobe_test_cc_position;
+
+
+#define TEST_MEMORY_SIZE 256
+
+
+/*
+ * Test case structures.
+ *
+ * The arguments given to test cases can be one of three types.
+ *
+ *   ARG_TYPE_REG
+ *	Load a register with the given value.
+ *
+ *   ARG_TYPE_PTR
+ *	Load a register with a pointer into the stack buffer (SP + given value).
+ *
+ *   ARG_TYPE_MEM
+ *	Store the given value into the stack buffer at [SP+index].
+ *
+ */
+
+#define	ARG_TYPE_END	0
+#define	ARG_TYPE_REG	1
+#define	ARG_TYPE_PTR	2
+#define	ARG_TYPE_MEM	3
+
+#define ARG_FLAG_UNSUPPORTED	0x01
+#define ARG_FLAG_SUPPORTED	0x02
+#define ARG_FLAG_THUMB		0x10	/* Must be 16 so TEST_ISA can be used */
+#define ARG_FLAG_ARM		0x20	/* Must be 32 so TEST_ISA can be used */
+
+struct test_arg {
+	u8	type;		/* ARG_TYPE_x */
+	u8	_padding[7];
+};
+
+struct test_arg_regptr {
+	u8	type;		/* ARG_TYPE_REG or ARG_TYPE_PTR */
+	u8	reg;
+	u8	_padding[2];
+	u32	val;
+};
+
+struct test_arg_mem {
+	u8	type;		/* ARG_TYPE_MEM */
+	u8	index;
+	u8	_padding[2];
+	u32	val;
+};
+
+struct test_arg_end {
+	u8	type;		/* ARG_TYPE_END */
+	u8	flags;		/* ARG_FLAG_x */
+	u16	code_offset;
+	u16	branch_offset;
+	u16	end_offset;
+};
+
+
+/*
+ * Building blocks for test cases.
+ *
+ * Each test case is wrapped between TESTCASE_START and TESTCASE_END.
+ *
+ * To specify arguments for a test case the TEST_ARG_{REG,PTR,MEM} macros are
+ * used followed by a terminating TEST_ARG_END.
+ *
+ * After this, the instruction to be tested is defined with TEST_INSTRUCTION.
+ * Or for branches, TEST_BRANCH_B and TEST_BRANCH_F (branch forwards/backwards).
+ *
+ * Some specific test cases may make use of other custom constructs.
+ */
+
+#if VERBOSE
+#define verbose(fmt, ...) pr_info(fmt, ##__VA_ARGS__)
+#else
+#define verbose(fmt, ...)
+#endif
+
+#define TEST_GROUP(title)					\
+	verbose("\n");						\
+	verbose(title"\n");					\
+	verbose("---------------------------------------------------------\n");
+
+#define TESTCASE_START(title)					\
+	__asm__ __volatile__ (					\
+	"bl	__kprobes_test_case_start		\n\t"	\
+	/* don't use .asciz here as 'title' may be */		\
+	/* multiple strings to be concatenated.  */		\
+	".ascii "#title"				\n\t"	\
+	".byte	0					\n\t"	\
+	".align	2					\n\t"
+
+#define	TEST_ARG_REG(reg, val)					\
+	".byte	"__stringify(ARG_TYPE_REG)"		\n\t"	\
+	".byte	"#reg"					\n\t"	\
+	".short	0					\n\t"	\
+	".word	"#val"					\n\t"
+
+#define	TEST_ARG_PTR(reg, val)					\
+	".byte	"__stringify(ARG_TYPE_PTR)"		\n\t"	\
+	".byte	"#reg"					\n\t"	\
+	".short	0					\n\t"	\
+	".word	"#val"					\n\t"
+
+#define	TEST_ARG_MEM(index, val)				\
+	".byte	"__stringify(ARG_TYPE_MEM)"		\n\t"	\
+	".byte	"#index"				\n\t"	\
+	".short	0					\n\t"	\
+	".word	"#val"					\n\t"
+
+#define	TEST_ARG_END(flags)					\
+	".byte	"__stringify(ARG_TYPE_END)"		\n\t"	\
+	".byte	"TEST_ISA flags"			\n\t"	\
+	".short	50f-0f					\n\t"	\
+	".short	2f-0f					\n\t"	\
+	".short	99f-0f					\n\t"	\
+	".code "TEST_ISA"				\n\t"	\
+	"0:						\n\t"
+
+#define TEST_INSTRUCTION(instruction)				\
+	"50:	nop					\n\t"	\
+	"1:	"instruction"				\n\t"	\
+	"	nop					\n\t"
+
+#define TEST_BRANCH_F(instruction)				\
+	TEST_INSTRUCTION(instruction)				\
+	"	b	99f				\n\t"	\
+	"2:	nop					\n\t"
+
+#define TEST_BRANCH_B(instruction)				\
+	"	b	50f				\n\t"	\
+	"	b	99f				\n\t"	\
+	"2:	nop					\n\t"	\
+	"	b	99f				\n\t"	\
+	TEST_INSTRUCTION(instruction)
+
+#define TEST_BRANCH_FX(instruction, codex)			\
+	TEST_INSTRUCTION(instruction)				\
+	"	b	99f				\n\t"	\
+	codex"						\n\t"	\
+	"	b	99f				\n\t"	\
+	"2:	nop					\n\t"
+
+#define TEST_BRANCH_BX(instruction, codex)			\
+	"	b	50f				\n\t"	\
+	"	b	99f				\n\t"	\
+	"2:	nop					\n\t"	\
+	"	b	99f				\n\t"	\
+	codex"						\n\t"	\
+	TEST_INSTRUCTION(instruction)
+
+#define TESTCASE_END						\
+	"2:						\n\t"	\
+	"99:						\n\t"	\
+	"	bl __kprobes_test_case_end_"TEST_ISA"	\n\t"	\
+	".code "NORMAL_ISA"				\n\t"	\
+	: :							\
+	: "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc"	\
+	);
+
+
+/*
+ * Macros to define test cases.
+ *
+ * Those of the form TEST_{R,P,M}* can be used to define test cases
+ * which take combinations of the three basic types of arguments. E.g.
+ *
+ *   TEST_R	One register argument
+ *   TEST_RR	Two register arguments
+ *   TEST_RPR	A register, a pointer, then a register argument
+ *
+ * For testing instructions which may branch, there are macros TEST_BF_*
+ * and TEST_BB_* for branching forwards and backwards.
+ *
+ * TEST_SUPPORTED and TEST_UNSUPPORTED don't cause the code to be executed,
+ * the just verify that a kprobe is or is not allowed on the given instruction.
+ */
+
+#define TEST(code)				\
+	TESTCASE_START(code)			\
+	TEST_ARG_END("")			\
+	TEST_INSTRUCTION(code)			\
+	TESTCASE_END
+
+#define TEST_UNSUPPORTED(code)					\
+	TESTCASE_START(code)					\
+	TEST_ARG_END("|"__stringify(ARG_FLAG_UNSUPPORTED))	\
+	TEST_INSTRUCTION(code)					\
+	TESTCASE_END
+
+#define TEST_SUPPORTED(code)					\
+	TESTCASE_START(code)					\
+	TEST_ARG_END("|"__stringify(ARG_FLAG_SUPPORTED))	\
+	TEST_INSTRUCTION(code)					\
+	TESTCASE_END
+
+#define TEST_R(code1, reg, val, code2)			\
+	TESTCASE_START(code1 #reg code2)		\
+	TEST_ARG_REG(reg, val)				\
+	TEST_ARG_END("")				\
+	TEST_INSTRUCTION(code1 #reg code2)		\
+	TESTCASE_END
+
+#define TEST_RR(code1, reg1, val1, code2, reg2, val2, code3)	\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3)		\
+	TEST_ARG_REG(reg1, val1)				\
+	TEST_ARG_REG(reg2, val2)				\
+	TEST_ARG_END("")					\
+	TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3)		\
+	TESTCASE_END
+
+#define TEST_RRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4)		\
+	TEST_ARG_REG(reg1, val1)						\
+	TEST_ARG_REG(reg2, val2)						\
+	TEST_ARG_REG(reg3, val3)						\
+	TEST_ARG_END("")							\
+	TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4)		\
+	TESTCASE_END
+
+#define TEST_RRRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4, reg4, val4)	\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4)		\
+	TEST_ARG_REG(reg1, val1)						\
+	TEST_ARG_REG(reg2, val2)						\
+	TEST_ARG_REG(reg3, val3)						\
+	TEST_ARG_REG(reg4, val4)						\
+	TEST_ARG_END("")							\
+	TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4)	\
+	TESTCASE_END
+
+#define TEST_P(code1, reg1, val1, code2)	\
+	TESTCASE_START(code1 #reg1 code2)	\
+	TEST_ARG_PTR(reg1, val1)		\
+	TEST_ARG_END("")			\
+	TEST_INSTRUCTION(code1 #reg1 code2)	\
+	TESTCASE_END
+
+#define TEST_PR(code1, reg1, val1, code2, reg2, val2, code3)	\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3)		\
+	TEST_ARG_PTR(reg1, val1)				\
+	TEST_ARG_REG(reg2, val2)				\
+	TEST_ARG_END("")					\
+	TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3)		\
+	TESTCASE_END
+
+#define TEST_RP(code1, reg1, val1, code2, reg2, val2, code3)	\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3)		\
+	TEST_ARG_REG(reg1, val1)				\
+	TEST_ARG_PTR(reg2, val2)				\
+	TEST_ARG_END("")					\
+	TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3)		\
+	TESTCASE_END
+
+#define TEST_PRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4)		\
+	TEST_ARG_PTR(reg1, val1)						\
+	TEST_ARG_REG(reg2, val2)						\
+	TEST_ARG_REG(reg3, val3)						\
+	TEST_ARG_END("")							\
+	TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4)		\
+	TESTCASE_END
+
+#define TEST_RPR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4)		\
+	TEST_ARG_REG(reg1, val1)						\
+	TEST_ARG_PTR(reg2, val2)						\
+	TEST_ARG_REG(reg3, val3)						\
+	TEST_ARG_END("")							\
+	TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4)		\
+	TESTCASE_END
+
+#define TEST_RRP(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4)		\
+	TEST_ARG_REG(reg1, val1)						\
+	TEST_ARG_REG(reg2, val2)						\
+	TEST_ARG_PTR(reg3, val3)						\
+	TEST_ARG_END("")							\
+	TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4)		\
+	TESTCASE_END
+
+#define TEST_BF_P(code1, reg1, val1, code2)	\
+	TESTCASE_START(code1 #reg1 code2)	\
+	TEST_ARG_PTR(reg1, val1)		\
+	TEST_ARG_END("")			\
+	TEST_BRANCH_F(code1 #reg1 code2)	\
+	TESTCASE_END
+
+#define TEST_BF(code)				\
+	TESTCASE_START(code)			\
+	TEST_ARG_END("")			\
+	TEST_BRANCH_F(code)			\
+	TESTCASE_END
+
+#define TEST_BB(code)				\
+	TESTCASE_START(code)			\
+	TEST_ARG_END("")			\
+	TEST_BRANCH_B(code)			\
+	TESTCASE_END
+
+#define TEST_BF_R(code1, reg, val, code2)	\
+	TESTCASE_START(code1 #reg code2)	\
+	TEST_ARG_REG(reg, val)			\
+	TEST_ARG_END("")			\
+	TEST_BRANCH_F(code1 #reg code2)		\
+	TESTCASE_END
+
+#define TEST_BB_R(code1, reg, val, code2)	\
+	TESTCASE_START(code1 #reg code2)	\
+	TEST_ARG_REG(reg, val)			\
+	TEST_ARG_END("")			\
+	TEST_BRANCH_B(code1 #reg code2)		\
+	TESTCASE_END
+
+#define TEST_BF_RR(code1, reg1, val1, code2, reg2, val2, code3)	\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3)		\
+	TEST_ARG_REG(reg1, val1)				\
+	TEST_ARG_REG(reg2, val2)				\
+	TEST_ARG_END("")					\
+	TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3)		\
+	TESTCASE_END
+
+#define TEST_BF_X(code, codex)			\
+	TESTCASE_START(code)			\
+	TEST_ARG_END("")			\
+	TEST_BRANCH_FX(code, codex)		\
+	TESTCASE_END
+
+#define TEST_BB_X(code, codex)			\
+	TESTCASE_START(code)			\
+	TEST_ARG_END("")			\
+	TEST_BRANCH_BX(code, codex)		\
+	TESTCASE_END
+
+#define TEST_BF_RX(code1, reg, val, code2, codex)	\
+	TESTCASE_START(code1 #reg code2)		\
+	TEST_ARG_REG(reg, val)				\
+	TEST_ARG_END("")				\
+	TEST_BRANCH_FX(code1 #reg code2, codex)		\
+	TESTCASE_END
+
+#define TEST_X(code, codex)			\
+	TESTCASE_START(code)			\
+	TEST_ARG_END("")			\
+	TEST_INSTRUCTION(code)			\
+	"	b	99f		\n\t"	\
+	"	"codex"			\n\t"	\
+	TESTCASE_END
+
+#define TEST_RX(code1, reg, val, code2, codex)		\
+	TESTCASE_START(code1 #reg code2)		\
+	TEST_ARG_REG(reg, val)				\
+	TEST_ARG_END("")				\
+	TEST_INSTRUCTION(code1 __stringify(reg) code2)	\
+	"	b	99f		\n\t"		\
+	"	"codex"			\n\t"		\
+	TESTCASE_END
+
+#define TEST_RRX(code1, reg1, val1, code2, reg2, val2, code3, codex)		\
+	TESTCASE_START(code1 #reg1 code2 #reg2 code3)				\
+	TEST_ARG_REG(reg1, val1)						\
+	TEST_ARG_REG(reg2, val2)						\
+	TEST_ARG_END("")							\
+	TEST_INSTRUCTION(code1 __stringify(reg1) code2 __stringify(reg2) code3)	\
+	"	b	99f		\n\t"					\
+	"	"codex"			\n\t"					\
+	TESTCASE_END
+
+
+/*
+ * Macros for defining space directives spread over multiple lines.
+ * These are required so the compiler guesses better the length of inline asm
+ * code and will spill the literal pool early enough to avoid generating PC
+ * relative loads with out of range offsets.
+ */
+#define TWICE(x)	x x
+#define SPACE_0x8	TWICE(".space 4\n\t")
+#define SPACE_0x10	TWICE(SPACE_0x8)
+#define SPACE_0x20	TWICE(SPACE_0x10)
+#define SPACE_0x40	TWICE(SPACE_0x20)
+#define SPACE_0x80	TWICE(SPACE_0x40)
+#define SPACE_0x100	TWICE(SPACE_0x80)
+#define SPACE_0x200	TWICE(SPACE_0x100)
+#define SPACE_0x400	TWICE(SPACE_0x200)
+#define SPACE_0x800	TWICE(SPACE_0x400)
+#define SPACE_0x1000	TWICE(SPACE_0x800)
+
+
+/* Various values used in test cases... */
+#define N(val)	(val ^ 0xffffffff)
+#define VAL1	0x12345678
+#define VAL2	N(VAL1)
+#define VAL3	0xa5f801
+#define VAL4	N(VAL3)
+#define VALM	0x456789ab
+#define VALR	0xdeaddead
+#define HH1	0x0123fecb
+#define HH2	0xa9874567
+
+
+#ifdef CONFIG_THUMB2_KERNEL
+void kprobe_thumb16_test_cases(void);
+void kprobe_thumb32_test_cases(void);
+#else
+void kprobe_arm_test_cases(void);
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/kprobes-test-thumb.c linux-libre-3.2-gnu/arch/arm/kernel/kprobes-test-thumb.c
--- linux-libre-3.1-gnu/arch/arm/kernel/kprobes-test-thumb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/kernel/kprobes-test-thumb.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1187 @@
+/*
+ * arch/arm/kernel/kprobes-test-thumb.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "kprobes-test.h"
+
+
+#define TEST_ISA "16"
+
+#define DONT_TEST_IN_ITBLOCK(tests)			\
+	kprobe_test_flags |= TEST_FLAG_NO_ITBLOCK;	\
+	tests						\
+	kprobe_test_flags &= ~TEST_FLAG_NO_ITBLOCK;
+
+#define CONDITION_INSTRUCTIONS(cc_pos, tests)		\
+	kprobe_test_cc_position = cc_pos;		\
+	DONT_TEST_IN_ITBLOCK(tests)			\
+	kprobe_test_cc_position = 0;
+
+#define TEST_ITBLOCK(code)				\
+	kprobe_test_flags |= TEST_FLAG_FULL_ITBLOCK;	\
+	TESTCASE_START(code)				\
+	TEST_ARG_END("")				\
+	"50:	nop			\n\t"		\
+	"1:	"code"			\n\t"		\
+	"	mov r1, #0x11		\n\t"		\
+	"	mov r2, #0x22		\n\t"		\
+	"	mov r3, #0x33		\n\t"		\
+	"2:	nop			\n\t"		\
+	TESTCASE_END					\
+	kprobe_test_flags &= ~TEST_FLAG_FULL_ITBLOCK;
+
+#define TEST_THUMB_TO_ARM_INTERWORK_P(code1, reg, val, code2)	\
+	TESTCASE_START(code1 #reg code2)			\
+	TEST_ARG_PTR(reg, val)					\
+	TEST_ARG_REG(14, 99f+1)					\
+	TEST_ARG_MEM(15, 3f)					\
+	TEST_ARG_END("")					\
+	"	nop			\n\t" /* To align 1f */	\
+	"50:	nop			\n\t"			\
+	"1:	"code1 #reg code2"	\n\t"			\
+	"	bx	lr		\n\t"			\
+	".arm				\n\t"			\
+	"3:	adr	lr, 2f+1	\n\t"			\
+	"	bx	lr		\n\t"			\
+	".thumb				\n\t"			\
+	"2:	nop			\n\t"			\
+	TESTCASE_END
+
+
+void kprobe_thumb16_test_cases(void)
+{
+	kprobe_test_flags = TEST_FLAG_NARROW_INSTR;
+
+	TEST_GROUP("Shift (immediate), add, subtract, move, and compare")
+
+	TEST_R(    "lsls	r7, r",0,VAL1,", #5")
+	TEST_R(    "lsls	r0, r",7,VAL2,", #11")
+	TEST_R(    "lsrs	r7, r",0,VAL1,", #5")
+	TEST_R(    "lsrs	r0, r",7,VAL2,", #11")
+	TEST_R(    "asrs	r7, r",0,VAL1,", #5")
+	TEST_R(    "asrs	r0, r",7,VAL2,", #11")
+	TEST_RR(   "adds	r2, r",0,VAL1,", r",7,VAL2,"")
+	TEST_RR(   "adds	r5, r",7,VAL2,", r",0,VAL2,"")
+	TEST_RR(   "subs	r2, r",0,VAL1,", r",7,VAL2,"")
+	TEST_RR(   "subs	r5, r",7,VAL2,", r",0,VAL2,"")
+	TEST_R(    "adds	r7, r",0,VAL1,", #5")
+	TEST_R(    "adds	r0, r",7,VAL2,", #2")
+	TEST_R(    "subs	r7, r",0,VAL1,", #5")
+	TEST_R(    "subs	r0, r",7,VAL2,", #2")
+	TEST(      "movs.n	r0, #0x5f")
+	TEST(      "movs.n	r7, #0xa0")
+	TEST_R(    "cmp.n	r",0,0x5e, ", #0x5f")
+	TEST_R(    "cmp.n	r",5,0x15f,", #0x5f")
+	TEST_R(    "cmp.n	r",7,0xa0, ", #0xa0")
+	TEST_R(    "adds.n	r",0,VAL1,", #0x5f")
+	TEST_R(    "adds.n	r",7,VAL2,", #0xa0")
+	TEST_R(    "subs.n	r",0,VAL1,", #0x5f")
+	TEST_R(    "subs.n	r",7,VAL2,", #0xa0")
+
+	TEST_GROUP("16-bit Thumb data-processing instructions")
+
+#define DATA_PROCESSING16(op,val)			\
+	TEST_RR(   op"	r",0,VAL1,", r",7,val,"")	\
+	TEST_RR(   op"	r",7,VAL2,", r",0,val,"")
+
+	DATA_PROCESSING16("ands",0xf00f00ff)
+	DATA_PROCESSING16("eors",0xf00f00ff)
+	DATA_PROCESSING16("lsls",11)
+	DATA_PROCESSING16("lsrs",11)
+	DATA_PROCESSING16("asrs",11)
+	DATA_PROCESSING16("adcs",VAL2)
+	DATA_PROCESSING16("sbcs",VAL2)
+	DATA_PROCESSING16("rors",11)
+	DATA_PROCESSING16("tst",0xf00f00ff)
+	TEST_R("rsbs	r",0,VAL1,", #0")
+	TEST_R("rsbs	r",7,VAL2,", #0")
+	DATA_PROCESSING16("cmp",0xf00f00ff)
+	DATA_PROCESSING16("cmn",0xf00f00ff)
+	DATA_PROCESSING16("orrs",0xf00f00ff)
+	DATA_PROCESSING16("muls",VAL2)
+	DATA_PROCESSING16("bics",0xf00f00ff)
+	DATA_PROCESSING16("mvns",VAL2)
+
+	TEST_GROUP("Special data instructions and branch and exchange")
+
+	TEST_RR(  "add	r",0, VAL1,", r",7,VAL2,"")
+	TEST_RR(  "add	r",3, VAL2,", r",8,VAL3,"")
+	TEST_RR(  "add	r",8, VAL3,", r",0,VAL1,"")
+	TEST_R(   "add	sp"        ", r",8,-8,  "")
+	TEST_R(   "add	r",14,VAL1,", pc")
+	TEST_BF_R("add	pc"        ", r",0,2f-1f-8,"")
+	TEST_UNSUPPORTED(".short 0x44ff	@ add pc, pc")
+
+	TEST_RR(  "cmp	r",3,VAL1,", r",8,VAL2,"")
+	TEST_RR(  "cmp	r",8,VAL2,", r",0,VAL1,"")
+	TEST_R(   "cmp	sp"       ", r",8,-8,  "")
+
+	TEST_R(   "mov	r0, r",7,VAL2,"")
+	TEST_R(   "mov	r3, r",8,VAL3,"")
+	TEST_R(   "mov	r8, r",0,VAL1,"")
+	TEST_P(   "mov	sp, r",8,-8,  "")
+	TEST(     "mov	lr, pc")
+	TEST_BF_R("mov	pc, r",0,2f,  "")
+
+	TEST_BF_R("bx	r",0, 2f+1,"")
+	TEST_BF_R("bx	r",14,2f+1,"")
+	TESTCASE_START("bx	pc")
+		TEST_ARG_REG(14, 99f+1)
+		TEST_ARG_END("")
+		"	nop			\n\t" /* To align the bx pc*/
+		"50:	nop			\n\t"
+		"1:	bx	pc		\n\t"
+		"	bx	lr		\n\t"
+		".arm				\n\t"
+		"	adr	lr, 2f+1	\n\t"
+		"	bx	lr		\n\t"
+		".thumb				\n\t"
+		"2:	nop			\n\t"
+	TESTCASE_END
+
+	TEST_BF_R("blx	r",0, 2f+1,"")
+	TEST_BB_R("blx	r",14,2f+1,"")
+	TEST_UNSUPPORTED(".short 0x47f8	@ blx pc")
+
+	TEST_GROUP("Load from Literal Pool")
+
+	TEST_X( "ldr	r0, 3f",
+		".align					\n\t"
+		"3:	.word	"__stringify(VAL1))
+	TEST_X( "ldr	r7, 3f",
+		".space 128				\n\t"
+		".align					\n\t"
+		"3:	.word	"__stringify(VAL2))
+
+	TEST_GROUP("16-bit Thumb Load/store instructions")
+
+	TEST_RPR("str	r",0, VAL1,", [r",1, 24,", r",2,  48,"]")
+	TEST_RPR("str	r",7, VAL2,", [r",6, 24,", r",5,  48,"]")
+	TEST_RPR("strh	r",0, VAL1,", [r",1, 24,", r",2,  48,"]")
+	TEST_RPR("strh	r",7, VAL2,", [r",6, 24,", r",5,  48,"]")
+	TEST_RPR("strb	r",0, VAL1,", [r",1, 24,", r",2,  48,"]")
+	TEST_RPR("strb	r",7, VAL2,", [r",6, 24,", r",5,  48,"]")
+	TEST_PR( "ldrsb	r0, [r",1, 24,", r",2,  48,"]")
+	TEST_PR( "ldrsb	r7, [r",6, 24,", r",5,  50,"]")
+	TEST_PR( "ldr	r0, [r",1, 24,", r",2,  48,"]")
+	TEST_PR( "ldr	r7, [r",6, 24,", r",5,  48,"]")
+	TEST_PR( "ldrh	r0, [r",1, 24,", r",2,  48,"]")
+	TEST_PR( "ldrh	r7, [r",6, 24,", r",5,  50,"]")
+	TEST_PR( "ldrb	r0, [r",1, 24,", r",2,  48,"]")
+	TEST_PR( "ldrb	r7, [r",6, 24,", r",5,  50,"]")
+	TEST_PR( "ldrsh	r0, [r",1, 24,", r",2,  48,"]")
+	TEST_PR( "ldrsh	r7, [r",6, 24,", r",5,  50,"]")
+
+	TEST_RP("str	r",0, VAL1,", [r",1, 24,", #120]")
+	TEST_RP("str	r",7, VAL2,", [r",6, 24,", #120]")
+	TEST_P( "ldr	r0, [r",1, 24,", #120]")
+	TEST_P( "ldr	r7, [r",6, 24,", #120]")
+	TEST_RP("strb	r",0, VAL1,", [r",1, 24,", #30]")
+	TEST_RP("strb	r",7, VAL2,", [r",6, 24,", #30]")
+	TEST_P( "ldrb	r0, [r",1, 24,", #30]")
+	TEST_P( "ldrb	r7, [r",6, 24,", #30]")
+	TEST_RP("strh	r",0, VAL1,", [r",1, 24,", #60]")
+	TEST_RP("strh	r",7, VAL2,", [r",6, 24,", #60]")
+	TEST_P( "ldrh	r0, [r",1, 24,", #60]")
+	TEST_P( "ldrh	r7, [r",6, 24,", #60]")
+
+	TEST_R( "str	r",0, VAL1,", [sp, #0]")
+	TEST_R( "str	r",7, VAL2,", [sp, #160]")
+	TEST(   "ldr	r0, [sp, #0]")
+	TEST(   "ldr	r7, [sp, #160]")
+
+	TEST_RP("str	r",0, VAL1,", [r",0, 24,"]")
+	TEST_P( "ldr	r0, [r",0, 24,"]")
+
+	TEST_GROUP("Generate PC-/SP-relative address")
+
+	TEST("add	r0, pc, #4")
+	TEST("add	r7, pc, #1020")
+	TEST("add	r0, sp, #4")
+	TEST("add	r7, sp, #1020")
+
+	TEST_GROUP("Miscellaneous 16-bit instructions")
+
+	TEST_UNSUPPORTED( "cpsie	i")
+	TEST_UNSUPPORTED( "cpsid	i")
+	TEST_UNSUPPORTED( "setend	le")
+	TEST_UNSUPPORTED( "setend	be")
+
+	TEST("add	sp, #"__stringify(TEST_MEMORY_SIZE)) /* Assumes TEST_MEMORY_SIZE < 0x400 */
+	TEST("sub	sp, #0x7f*4")
+
+DONT_TEST_IN_ITBLOCK(
+	TEST_BF_R(  "cbnz	r",0,0, ", 2f")
+	TEST_BF_R(  "cbz	r",2,-1,", 2f")
+	TEST_BF_RX( "cbnz	r",4,1, ", 2f", SPACE_0x20)
+	TEST_BF_RX( "cbz	r",7,0, ", 2f", SPACE_0x40)
+)
+	TEST_R("sxth	r0, r",7, HH1,"")
+	TEST_R("sxth	r7, r",0, HH2,"")
+	TEST_R("sxtb	r0, r",7, HH1,"")
+	TEST_R("sxtb	r7, r",0, HH2,"")
+	TEST_R("uxth	r0, r",7, HH1,"")
+	TEST_R("uxth	r7, r",0, HH2,"")
+	TEST_R("uxtb	r0, r",7, HH1,"")
+	TEST_R("uxtb	r7, r",0, HH2,"")
+	TEST_R("rev	r0, r",7, VAL1,"")
+	TEST_R("rev	r7, r",0, VAL2,"")
+	TEST_R("rev16	r0, r",7, VAL1,"")
+	TEST_R("rev16	r7, r",0, VAL2,"")
+	TEST_UNSUPPORTED(".short 0xba80")
+	TEST_UNSUPPORTED(".short 0xbabf")
+	TEST_R("revsh	r0, r",7, VAL1,"")
+	TEST_R("revsh	r7, r",0, VAL2,"")
+
+#define TEST_POPPC(code, offset)	\
+	TESTCASE_START(code)		\
+	TEST_ARG_PTR(13, offset)	\
+	TEST_ARG_END("")		\
+	TEST_BRANCH_F(code)		\
+	TESTCASE_END
+
+	TEST("push	{r0}")
+	TEST("push	{r7}")
+	TEST("push	{r14}")
+	TEST("push	{r0-r7,r14}")
+	TEST("push	{r0,r2,r4,r6,r14}")
+	TEST("push	{r1,r3,r5,r7}")
+	TEST("pop	{r0}")
+	TEST("pop	{r7}")
+	TEST("pop	{r0,r2,r4,r6}")
+	TEST_POPPC("pop	{pc}",15*4)
+	TEST_POPPC("pop	{r0-r7,pc}",7*4)
+	TEST_POPPC("pop	{r1,r3,r5,r7,pc}",11*4)
+	TEST_THUMB_TO_ARM_INTERWORK_P("pop	{pc}	@ ",13,15*4,"")
+	TEST_THUMB_TO_ARM_INTERWORK_P("pop	{r0-r7,pc}	@ ",13,7*4,"")
+
+	TEST_UNSUPPORTED("bkpt.n	0")
+	TEST_UNSUPPORTED("bkpt.n	255")
+
+	TEST_SUPPORTED("yield")
+	TEST("sev")
+	TEST("nop")
+	TEST("wfi")
+	TEST_SUPPORTED("wfe")
+	TEST_UNSUPPORTED(".short 0xbf50") /* Unassigned hints */
+	TEST_UNSUPPORTED(".short 0xbff0") /* Unassigned hints */
+
+#define TEST_IT(code, code2)			\
+	TESTCASE_START(code)			\
+	TEST_ARG_END("")			\
+	"50:	nop			\n\t"	\
+	"1:	"code"			\n\t"	\
+	"	"code2"			\n\t"	\
+	"2:	nop			\n\t"	\
+	TESTCASE_END
+
+DONT_TEST_IN_ITBLOCK(
+	TEST_IT("it	eq","moveq r0,#0")
+	TEST_IT("it	vc","movvc r0,#0")
+	TEST_IT("it	le","movle r0,#0")
+	TEST_IT("ite	eq","moveq r0,#0\n\t  movne r1,#1")
+	TEST_IT("itet	vc","movvc r0,#0\n\t  movvs r1,#1\n\t  movvc r2,#2")
+	TEST_IT("itete	le","movle r0,#0\n\t  movgt r1,#1\n\t  movle r2,#2\n\t  movgt r3,#3")
+	TEST_IT("itttt	le","movle r0,#0\n\t  movle r1,#1\n\t  movle r2,#2\n\t  movle r3,#3")
+	TEST_IT("iteee	le","movle r0,#0\n\t  movgt r1,#1\n\t  movgt r2,#2\n\t  movgt r3,#3")
+)
+
+	TEST_GROUP("Load and store multiple")
+
+	TEST_P("ldmia	r",4, 16*4,"!, {r0,r7}")
+	TEST_P("ldmia	r",7, 16*4,"!, {r0-r6}")
+	TEST_P("stmia	r",4, 16*4,"!, {r0,r7}")
+	TEST_P("stmia	r",0, 16*4,"!, {r0-r7}")
+
+	TEST_GROUP("Conditional branch and Supervisor Call instructions")
+
+CONDITION_INSTRUCTIONS(8,
+	TEST_BF("beq	2f")
+	TEST_BB("bne	2b")
+	TEST_BF("bgt	2f")
+	TEST_BB("blt	2b")
+)
+	TEST_UNSUPPORTED(".short 0xde00")
+	TEST_UNSUPPORTED(".short 0xdeff")
+	TEST_UNSUPPORTED("svc	#0x00")
+	TEST_UNSUPPORTED("svc	#0xff")
+
+	TEST_GROUP("Unconditional branch")
+
+	TEST_BF(  "b	2f")
+	TEST_BB(  "b	2b")
+	TEST_BF_X("b	2f", SPACE_0x400)
+	TEST_BB_X("b	2b", SPACE_0x400)
+
+	TEST_GROUP("Testing instructions in IT blocks")
+
+	TEST_ITBLOCK("subs.n r0, r0")
+
+	verbose("\n");
+}
+
+
+void kprobe_thumb32_test_cases(void)
+{
+	kprobe_test_flags = 0;
+
+	TEST_GROUP("Load/store multiple")
+
+	TEST_UNSUPPORTED("rfedb	sp")
+	TEST_UNSUPPORTED("rfeia	sp")
+	TEST_UNSUPPORTED("rfedb	sp!")
+	TEST_UNSUPPORTED("rfeia	sp!")
+
+	TEST_P(   "stmia	r",0, 16*4,", {r0,r8}")
+	TEST_P(   "stmia	r",4, 16*4,", {r0-r12,r14}")
+	TEST_P(   "stmia	r",7, 16*4,"!, {r8-r12,r14}")
+	TEST_P(   "stmia	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+
+	TEST_P(   "ldmia	r",0, 16*4,", {r0,r8}")
+	TEST_P(   "ldmia	r",4, 0,   ", {r0-r12,r14}")
+	TEST_BF_P("ldmia	r",5, 8*4, "!, {r6-r12,r15}")
+	TEST_P(   "ldmia	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_BF_P("ldmia	r",14,14*4,"!, {r4,pc}")
+
+	TEST_P(   "stmdb	r",0, 16*4,", {r0,r8}")
+	TEST_P(   "stmdb	r",4, 16*4,", {r0-r12,r14}")
+	TEST_P(   "stmdb	r",5, 16*4,"!, {r8-r12,r14}")
+	TEST_P(   "stmdb	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+
+	TEST_P(   "ldmdb	r",0, 16*4,", {r0,r8}")
+	TEST_P(   "ldmdb	r",4, 16*4,", {r0-r12,r14}")
+	TEST_BF_P("ldmdb	r",5, 16*4,"!, {r6-r12,r15}")
+	TEST_P(   "ldmdb	r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}")
+	TEST_BF_P("ldmdb	r",14,16*4,"!, {r4,pc}")
+
+	TEST_P(   "stmdb	r",13,16*4,"!, {r3-r12,lr}")
+	TEST_P(	  "stmdb	r",13,16*4,"!, {r3-r12}")
+	TEST_P(   "stmdb	r",2, 16*4,", {r3-r12,lr}")
+	TEST_P(   "stmdb	r",13,16*4,"!, {r2-r12,lr}")
+	TEST_P(   "stmdb	r",0, 16*4,", {r0-r12}")
+	TEST_P(   "stmdb	r",0, 16*4,", {r0-r12,lr}")
+
+	TEST_BF_P("ldmia	r",13,5*4, "!, {r3-r12,pc}")
+	TEST_P(	  "ldmia	r",13,5*4, "!, {r3-r12}")
+	TEST_BF_P("ldmia	r",2, 5*4, "!, {r3-r12,pc}")
+	TEST_BF_P("ldmia	r",13,4*4, "!, {r2-r12,pc}")
+	TEST_P(   "ldmia	r",0, 16*4,", {r0-r12}")
+	TEST_P(   "ldmia	r",0, 16*4,", {r0-r12,lr}")
+
+	TEST_THUMB_TO_ARM_INTERWORK_P("ldmia	r",0,14*4,", {r12,pc}")
+	TEST_THUMB_TO_ARM_INTERWORK_P("ldmia	r",13,2*4,", {r0-r12,pc}")
+
+	TEST_UNSUPPORTED(".short 0xe88f,0x0101	@ stmia	pc, {r0,r8}")
+	TEST_UNSUPPORTED(".short 0xe92f,0x5f00	@ stmdb	pc!, {r8-r12,r14}")
+	TEST_UNSUPPORTED(".short 0xe8bd,0xc000	@ ldmia	r13!, {r14,pc}")
+	TEST_UNSUPPORTED(".short 0xe93e,0xc000	@ ldmdb	r14!, {r14,pc}")
+	TEST_UNSUPPORTED(".short 0xe8a7,0x3f00	@ stmia	r7!, {r8-r12,sp}")
+	TEST_UNSUPPORTED(".short 0xe8a7,0x9f00	@ stmia	r7!, {r8-r12,pc}")
+	TEST_UNSUPPORTED(".short 0xe93e,0x2010	@ ldmdb	r14!, {r4,sp}")
+
+	TEST_GROUP("Load/store double or exclusive, table branch")
+
+	TEST_P(  "ldrd	r0, r1, [r",1, 24,", #-16]")
+	TEST(    "ldrd	r12, r14, [sp, #16]")
+	TEST_P(  "ldrd	r1, r0, [r",7, 24,", #-16]!")
+	TEST(    "ldrd	r14, r12, [sp, #16]!")
+	TEST_P(  "ldrd	r1, r0, [r",7, 24,"], #16")
+	TEST(    "ldrd	r7, r8, [sp], #-16")
+
+	TEST_X( "ldrd	r12, r14, 3f",
+		".align 3				\n\t"
+		"3:	.word	"__stringify(VAL1)"	\n\t"
+		"	.word	"__stringify(VAL2))
+
+	TEST_UNSUPPORTED(".short 0xe9ff,0xec04	@ ldrd	r14, r12, [pc, #16]!")
+	TEST_UNSUPPORTED(".short 0xe8ff,0xec04	@ ldrd	r14, r12, [pc], #16")
+	TEST_UNSUPPORTED(".short 0xe9d4,0xd800	@ ldrd	sp, r8, [r4]")
+	TEST_UNSUPPORTED(".short 0xe9d4,0xf800	@ ldrd	pc, r8, [r4]")
+	TEST_UNSUPPORTED(".short 0xe9d4,0x7d00	@ ldrd	r7, sp, [r4]")
+	TEST_UNSUPPORTED(".short 0xe9d4,0x7f00	@ ldrd	r7, pc, [r4]")
+
+	TEST_RRP("strd	r",0, VAL1,", r",1, VAL2,", [r",1, 24,", #-16]")
+	TEST_RR( "strd	r",12,VAL2,", r",14,VAL1,", [sp, #16]")
+	TEST_RRP("strd	r",1, VAL1,", r",0, VAL2,", [r",7, 24,", #-16]!")
+	TEST_RR( "strd	r",14,VAL2,", r",12,VAL1,", [sp, #16]!")
+	TEST_RRP("strd	r",1, VAL1,", r",0, VAL2,", [r",7, 24,"], #16")
+	TEST_RR( "strd	r",7, VAL2,", r",8, VAL1,", [sp], #-16")
+	TEST_UNSUPPORTED(".short 0xe9ef,0xec04	@ strd	r14, r12, [pc, #16]!")
+	TEST_UNSUPPORTED(".short 0xe8ef,0xec04	@ strd	r14, r12, [pc], #16")
+
+	TEST_RX("tbb	[pc, r",0, (9f-(1f+4)),"]",
+		"9:			\n\t"
+		".byte	(2f-1b-4)>>1	\n\t"
+		".byte	(3f-1b-4)>>1	\n\t"
+		"3:	mvn	r0, r0	\n\t"
+		"2:	nop		\n\t")
+
+	TEST_RX("tbb	[pc, r",4, (9f-(1f+4)+1),"]",
+		"9:			\n\t"
+		".byte	(2f-1b-4)>>1	\n\t"
+		".byte	(3f-1b-4)>>1	\n\t"
+		"3:	mvn	r0, r0	\n\t"
+		"2:	nop		\n\t")
+
+	TEST_RRX("tbb	[r",1,9f,", r",2,0,"]",
+		"9:			\n\t"
+		".byte	(2f-1b-4)>>1	\n\t"
+		".byte	(3f-1b-4)>>1	\n\t"
+		"3:	mvn	r0, r0	\n\t"
+		"2:	nop		\n\t")
+
+	TEST_RX("tbh	[pc, r",7, (9f-(1f+4))>>1,"]",
+		"9:			\n\t"
+		".short	(2f-1b-4)>>1	\n\t"
+		".short	(3f-1b-4)>>1	\n\t"
+		"3:	mvn	r0, r0	\n\t"
+		"2:	nop		\n\t")
+
+	TEST_RX("tbh	[pc, r",12, ((9f-(1f+4))>>1)+1,"]",
+		"9:			\n\t"
+		".short	(2f-1b-4)>>1	\n\t"
+		".short	(3f-1b-4)>>1	\n\t"
+		"3:	mvn	r0, r0	\n\t"
+		"2:	nop		\n\t")
+
+	TEST_RRX("tbh	[r",1,9f, ", r",14,1,"]",
+		"9:			\n\t"
+		".short	(2f-1b-4)>>1	\n\t"
+		".short	(3f-1b-4)>>1	\n\t"
+		"3:	mvn	r0, r0	\n\t"
+		"2:	nop		\n\t")
+
+	TEST_UNSUPPORTED(".short 0xe8d1,0xf01f	@ tbh [r1, pc]")
+	TEST_UNSUPPORTED(".short 0xe8d1,0xf01d	@ tbh [r1, sp]")
+	TEST_UNSUPPORTED(".short 0xe8dd,0xf012	@ tbh [sp, r2]")
+
+	TEST_UNSUPPORTED("strexb	r0, r1, [r2]")
+	TEST_UNSUPPORTED("strexh	r0, r1, [r2]")
+	TEST_UNSUPPORTED("strexd	r0, r1, [r2]")
+	TEST_UNSUPPORTED("ldrexb	r0, [r1]")
+	TEST_UNSUPPORTED("ldrexh	r0, [r1]")
+	TEST_UNSUPPORTED("ldrexd	r0, [r1]")
+
+	TEST_GROUP("Data-processing (shifted register) and (modified immediate)")
+
+#define _DATA_PROCESSING32_DNM(op,s,val)					\
+	TEST_RR(op s".w	r0,  r",1, VAL1,", r",2, val, "")			\
+	TEST_RR(op s"	r1,  r",1, VAL1,", r",2, val, ", lsl #3")		\
+	TEST_RR(op s"	r2,  r",3, VAL1,", r",2, val, ", lsr #4")		\
+	TEST_RR(op s"	r3,  r",3, VAL1,", r",2, val, ", asr #5")		\
+	TEST_RR(op s"	r4,  r",5, VAL1,", r",2, N(val),", asr #6")		\
+	TEST_RR(op s"	r5,  r",5, VAL1,", r",2, val, ", ror #7")		\
+	TEST_RR(op s"	r8,  r",9, VAL1,", r",10,val, ", rrx")			\
+	TEST_R( op s"	r0,  r",11,VAL1,", #0x00010001")			\
+	TEST_R( op s"	r11, r",0, VAL1,", #0xf5000000")			\
+	TEST_R( op s"	r7,  r",8, VAL2,", #0x000af000")
+
+#define DATA_PROCESSING32_DNM(op,val)		\
+	_DATA_PROCESSING32_DNM(op,"",val)	\
+	_DATA_PROCESSING32_DNM(op,"s",val)
+
+#define DATA_PROCESSING32_NM(op,val)					\
+	TEST_RR(op".w	r",1, VAL1,", r",2, val, "")			\
+	TEST_RR(op"	r",1, VAL1,", r",2, val, ", lsl #3")		\
+	TEST_RR(op"	r",3, VAL1,", r",2, val, ", lsr #4")		\
+	TEST_RR(op"	r",3, VAL1,", r",2, val, ", asr #5")		\
+	TEST_RR(op"	r",5, VAL1,", r",2, N(val),", asr #6")		\
+	TEST_RR(op"	r",5, VAL1,", r",2, val, ", ror #7")		\
+	TEST_RR(op"	r",9, VAL1,", r",10,val, ", rrx")		\
+	TEST_R( op"	r",11,VAL1,", #0x00010001")			\
+	TEST_R( op"	r",0, VAL1,", #0xf5000000")			\
+	TEST_R( op"	r",8, VAL2,", #0x000af000")
+
+#define _DATA_PROCESSING32_DM(op,s,val)				\
+	TEST_R( op s".w	r0,  r",14, val, "")			\
+	TEST_R( op s"	r1,  r",12, val, ", lsl #3")		\
+	TEST_R( op s"	r2,  r",11, val, ", lsr #4")		\
+	TEST_R( op s"	r3,  r",10, val, ", asr #5")		\
+	TEST_R( op s"	r4,  r",9, N(val),", asr #6")		\
+	TEST_R( op s"	r5,  r",8, val, ", ror #7")		\
+	TEST_R( op s"	r8,  r",7,val, ", rrx")			\
+	TEST(   op s"	r0,  #0x00010001")			\
+	TEST(   op s"	r11, #0xf5000000")			\
+	TEST(   op s"	r7,  #0x000af000")			\
+	TEST(   op s"	r4,  #0x00005a00")
+
+#define DATA_PROCESSING32_DM(op,val)		\
+	_DATA_PROCESSING32_DM(op,"",val)	\
+	_DATA_PROCESSING32_DM(op,"s",val)
+
+	DATA_PROCESSING32_DNM("and",0xf00f00ff)
+	DATA_PROCESSING32_NM("tst",0xf00f00ff)
+	DATA_PROCESSING32_DNM("bic",0xf00f00ff)
+	DATA_PROCESSING32_DNM("orr",0xf00f00ff)
+	DATA_PROCESSING32_DM("mov",VAL2)
+	DATA_PROCESSING32_DNM("orn",0xf00f00ff)
+	DATA_PROCESSING32_DM("mvn",VAL2)
+	DATA_PROCESSING32_DNM("eor",0xf00f00ff)
+	DATA_PROCESSING32_NM("teq",0xf00f00ff)
+	DATA_PROCESSING32_DNM("add",VAL2)
+	DATA_PROCESSING32_NM("cmn",VAL2)
+	DATA_PROCESSING32_DNM("adc",VAL2)
+	DATA_PROCESSING32_DNM("sbc",VAL2)
+	DATA_PROCESSING32_DNM("sub",VAL2)
+	DATA_PROCESSING32_NM("cmp",VAL2)
+	DATA_PROCESSING32_DNM("rsb",VAL2)
+
+	TEST_RR("pkhbt	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR("pkhbt	r14,r",12, HH1,", r",10,HH2,", lsl #2")
+	TEST_RR("pkhtb	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR("pkhtb	r14,r",12, HH1,", r",10,HH2,", asr #2")
+
+	TEST_UNSUPPORTED(".short 0xea17,0x0f0d	@ tst.w r7, sp")
+	TEST_UNSUPPORTED(".short 0xea17,0x0f0f	@ tst.w r7, pc")
+	TEST_UNSUPPORTED(".short 0xea1d,0x0f07	@ tst.w sp, r7")
+	TEST_UNSUPPORTED(".short 0xea1f,0x0f07	@ tst.w pc, r7")
+	TEST_UNSUPPORTED(".short 0xf01d,0x1f08	@ tst sp, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf01f,0x1f08	@ tst pc, #0x00080008")
+
+	TEST_UNSUPPORTED(".short 0xea97,0x0f0d	@ teq.w r7, sp")
+	TEST_UNSUPPORTED(".short 0xea97,0x0f0f	@ teq.w r7, pc")
+	TEST_UNSUPPORTED(".short 0xea9d,0x0f07	@ teq.w sp, r7")
+	TEST_UNSUPPORTED(".short 0xea9f,0x0f07	@ teq.w pc, r7")
+	TEST_UNSUPPORTED(".short 0xf09d,0x1f08	@ tst sp, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf09f,0x1f08	@ tst pc, #0x00080008")
+
+	TEST_UNSUPPORTED(".short 0xeb17,0x0f0d	@ cmn.w r7, sp")
+	TEST_UNSUPPORTED(".short 0xeb17,0x0f0f	@ cmn.w r7, pc")
+	TEST_P("cmn.w	sp, r",7,0,"")
+	TEST_UNSUPPORTED(".short 0xeb1f,0x0f07	@ cmn.w pc, r7")
+	TEST(  "cmn	sp, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf11f,0x1f08	@ cmn pc, #0x00080008")
+
+	TEST_UNSUPPORTED(".short 0xebb7,0x0f0d	@ cmp.w r7, sp")
+	TEST_UNSUPPORTED(".short 0xebb7,0x0f0f	@ cmp.w r7, pc")
+	TEST_P("cmp.w	sp, r",7,0,"")
+	TEST_UNSUPPORTED(".short 0xebbf,0x0f07	@ cmp.w pc, r7")
+	TEST(  "cmp	sp, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf1bf,0x1f08	@ cmp pc, #0x00080008")
+
+	TEST_UNSUPPORTED(".short 0xea5f,0x070d	@ movs.w r7, sp")
+	TEST_UNSUPPORTED(".short 0xea5f,0x070f	@ movs.w r7, pc")
+	TEST_UNSUPPORTED(".short 0xea5f,0x0d07	@ movs.w sp, r7")
+	TEST_UNSUPPORTED(".short 0xea4f,0x0f07	@ mov.w  pc, r7")
+	TEST_UNSUPPORTED(".short 0xf04f,0x1d08	@ mov sp, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf04f,0x1f08	@ mov pc, #0x00080008")
+
+	TEST_R("add.w	r0, sp, r",1, 4,"")
+	TEST_R("adds	r0, sp, r",1, 4,", asl #3")
+	TEST_R("add	r0, sp, r",1, 4,", asl #4")
+	TEST_R("add	r0, sp, r",1, 16,", ror #1")
+	TEST_R("add.w	sp, sp, r",1, 4,"")
+	TEST_R("add	sp, sp, r",1, 4,", asl #3")
+	TEST_UNSUPPORTED(".short 0xeb0d,0x1d01	@ add sp, sp, r1, asl #4")
+	TEST_UNSUPPORTED(".short 0xeb0d,0x0d71	@ add sp, sp, r1, ror #1")
+	TEST(  "add.w	r0, sp, #24")
+	TEST(  "add.w	sp, sp, #24")
+	TEST_UNSUPPORTED(".short 0xeb0d,0x0f01	@ add pc, sp, r1")
+	TEST_UNSUPPORTED(".short 0xeb0d,0x000f	@ add r0, sp, pc")
+	TEST_UNSUPPORTED(".short 0xeb0d,0x000d	@ add r0, sp, sp")
+	TEST_UNSUPPORTED(".short 0xeb0d,0x0d0f	@ add sp, sp, pc")
+	TEST_UNSUPPORTED(".short 0xeb0d,0x0d0d	@ add sp, sp, sp")
+
+	TEST_R("sub.w	r0, sp, r",1, 4,"")
+	TEST_R("subs	r0, sp, r",1, 4,", asl #3")
+	TEST_R("sub	r0, sp, r",1, 4,", asl #4")
+	TEST_R("sub	r0, sp, r",1, 16,", ror #1")
+	TEST_R("sub.w	sp, sp, r",1, 4,"")
+	TEST_R("sub	sp, sp, r",1, 4,", asl #3")
+	TEST_UNSUPPORTED(".short 0xebad,0x1d01	@ sub sp, sp, r1, asl #4")
+	TEST_UNSUPPORTED(".short 0xebad,0x0d71	@ sub sp, sp, r1, ror #1")
+	TEST_UNSUPPORTED(".short 0xebad,0x0f01	@ sub pc, sp, r1")
+	TEST(  "sub.w	r0, sp, #24")
+	TEST(  "sub.w	sp, sp, #24")
+
+	TEST_UNSUPPORTED(".short 0xea02,0x010f	@ and r1, r2, pc")
+	TEST_UNSUPPORTED(".short 0xea0f,0x0103	@ and r1, pc, r3")
+	TEST_UNSUPPORTED(".short 0xea02,0x0f03	@ and pc, r2, r3")
+	TEST_UNSUPPORTED(".short 0xea02,0x010d	@ and r1, r2, sp")
+	TEST_UNSUPPORTED(".short 0xea0d,0x0103	@ and r1, sp, r3")
+	TEST_UNSUPPORTED(".short 0xea02,0x0d03	@ and sp, r2, r3")
+	TEST_UNSUPPORTED(".short 0xf00d,0x1108	@ and r1, sp, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf00f,0x1108	@ and r1, pc, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf002,0x1d08	@ and sp, r8, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf002,0x1f08	@ and pc, r8, #0x00080008")
+
+	TEST_UNSUPPORTED(".short 0xeb02,0x010f	@ add r1, r2, pc")
+	TEST_UNSUPPORTED(".short 0xeb0f,0x0103	@ add r1, pc, r3")
+	TEST_UNSUPPORTED(".short 0xeb02,0x0f03	@ add pc, r2, r3")
+	TEST_UNSUPPORTED(".short 0xeb02,0x010d	@ add r1, r2, sp")
+	TEST_SUPPORTED(  ".short 0xeb0d,0x0103	@ add r1, sp, r3")
+	TEST_UNSUPPORTED(".short 0xeb02,0x0d03	@ add sp, r2, r3")
+	TEST_SUPPORTED(  ".short 0xf10d,0x1108	@ add r1, sp, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf10d,0x1f08	@ add pc, sp, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf10f,0x1108	@ add r1, pc, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf102,0x1d08	@ add sp, r8, #0x00080008")
+	TEST_UNSUPPORTED(".short 0xf102,0x1f08	@ add pc, r8, #0x00080008")
+
+	TEST_UNSUPPORTED(".short 0xeaa0,0x0000")
+	TEST_UNSUPPORTED(".short 0xeaf0,0x0000")
+	TEST_UNSUPPORTED(".short 0xeb20,0x0000")
+	TEST_UNSUPPORTED(".short 0xeb80,0x0000")
+	TEST_UNSUPPORTED(".short 0xebe0,0x0000")
+
+	TEST_UNSUPPORTED(".short 0xf0a0,0x0000")
+	TEST_UNSUPPORTED(".short 0xf0c0,0x0000")
+	TEST_UNSUPPORTED(".short 0xf0f0,0x0000")
+	TEST_UNSUPPORTED(".short 0xf120,0x0000")
+	TEST_UNSUPPORTED(".short 0xf180,0x0000")
+	TEST_UNSUPPORTED(".short 0xf1e0,0x0000")
+
+	TEST_GROUP("Coprocessor instructions")
+
+	TEST_UNSUPPORTED(".short 0xec00,0x0000")
+	TEST_UNSUPPORTED(".short 0xeff0,0x0000")
+	TEST_UNSUPPORTED(".short 0xfc00,0x0000")
+	TEST_UNSUPPORTED(".short 0xfff0,0x0000")
+
+	TEST_GROUP("Data-processing (plain binary immediate)")
+
+	TEST_R("addw	r0,  r",1, VAL1,", #0x123")
+	TEST(  "addw	r14, sp, #0xf5a")
+	TEST(  "addw	sp, sp, #0x20")
+	TEST(  "addw	r7,  pc, #0x888")
+	TEST_UNSUPPORTED(".short 0xf20f,0x1f20	@ addw pc, pc, #0x120")
+	TEST_UNSUPPORTED(".short 0xf20d,0x1f20	@ addw pc, sp, #0x120")
+	TEST_UNSUPPORTED(".short 0xf20f,0x1d20	@ addw sp, pc, #0x120")
+	TEST_UNSUPPORTED(".short 0xf200,0x1d20	@ addw sp, r0, #0x120")
+
+	TEST_R("subw	r0,  r",1, VAL1,", #0x123")
+	TEST(  "subw	r14, sp, #0xf5a")
+	TEST(  "subw	sp, sp, #0x20")
+	TEST(  "subw	r7,  pc, #0x888")
+	TEST_UNSUPPORTED(".short 0xf2af,0x1f20	@ subw pc, pc, #0x120")
+	TEST_UNSUPPORTED(".short 0xf2ad,0x1f20	@ subw pc, sp, #0x120")
+	TEST_UNSUPPORTED(".short 0xf2af,0x1d20	@ subw sp, pc, #0x120")
+	TEST_UNSUPPORTED(".short 0xf2a0,0x1d20	@ subw sp, r0, #0x120")
+
+	TEST("movw	r0, #0")
+	TEST("movw	r0, #0xffff")
+	TEST("movw	lr, #0xffff")
+	TEST_UNSUPPORTED(".short 0xf240,0x0d00	@ movw sp, #0")
+	TEST_UNSUPPORTED(".short 0xf240,0x0f00	@ movw pc, #0")
+
+	TEST_R("movt	r",0, VAL1,", #0")
+	TEST_R("movt	r",0, VAL2,", #0xffff")
+	TEST_R("movt	r",14,VAL1,", #0xffff")
+	TEST_UNSUPPORTED(".short 0xf2c0,0x0d00	@ movt sp, #0")
+	TEST_UNSUPPORTED(".short 0xf2c0,0x0f00	@ movt pc, #0")
+
+	TEST_R(     "ssat	r0, #24, r",0,   VAL1,"")
+	TEST_R(     "ssat	r14, #24, r",12, VAL2,"")
+	TEST_R(     "ssat	r0, #24, r",0,   VAL1,", lsl #8")
+	TEST_R(     "ssat	r14, #24, r",12, VAL2,", asr #8")
+	TEST_UNSUPPORTED(".short 0xf30c,0x0d17	@ ssat	sp, #24, r12")
+	TEST_UNSUPPORTED(".short 0xf30c,0x0f17	@ ssat	pc, #24, r12")
+	TEST_UNSUPPORTED(".short 0xf30d,0x0c17	@ ssat	r12, #24, sp")
+	TEST_UNSUPPORTED(".short 0xf30f,0x0c17	@ ssat	r12, #24, pc")
+
+	TEST_R(     "usat	r0, #24, r",0,   VAL1,"")
+	TEST_R(     "usat	r14, #24, r",12, VAL2,"")
+	TEST_R(     "usat	r0, #24, r",0,   VAL1,", lsl #8")
+	TEST_R(     "usat	r14, #24, r",12, VAL2,", asr #8")
+	TEST_UNSUPPORTED(".short 0xf38c,0x0d17	@ usat	sp, #24, r12")
+	TEST_UNSUPPORTED(".short 0xf38c,0x0f17	@ usat	pc, #24, r12")
+	TEST_UNSUPPORTED(".short 0xf38d,0x0c17	@ usat	r12, #24, sp")
+	TEST_UNSUPPORTED(".short 0xf38f,0x0c17	@ usat	r12, #24, pc")
+
+	TEST_R(     "ssat16	r0, #12, r",0,   HH1,"")
+	TEST_R(     "ssat16	r14, #12, r",12, HH2,"")
+	TEST_UNSUPPORTED(".short 0xf32c,0x0d0b	@ ssat16	sp, #12, r12")
+	TEST_UNSUPPORTED(".short 0xf32c,0x0f0b	@ ssat16	pc, #12, r12")
+	TEST_UNSUPPORTED(".short 0xf32d,0x0c0b	@ ssat16	r12, #12, sp")
+	TEST_UNSUPPORTED(".short 0xf32f,0x0c0b	@ ssat16	r12, #12, pc")
+
+	TEST_R(     "usat16	r0, #12, r",0,   HH1,"")
+	TEST_R(     "usat16	r14, #12, r",12, HH2,"")
+	TEST_UNSUPPORTED(".short 0xf3ac,0x0d0b	@ usat16	sp, #12, r12")
+	TEST_UNSUPPORTED(".short 0xf3ac,0x0f0b	@ usat16	pc, #12, r12")
+	TEST_UNSUPPORTED(".short 0xf3ad,0x0c0b	@ usat16	r12, #12, sp")
+	TEST_UNSUPPORTED(".short 0xf3af,0x0c0b	@ usat16	r12, #12, pc")
+
+	TEST_R(     "sbfx	r0, r",0  , VAL1,", #0, #31")
+	TEST_R(     "sbfx	r14, r",12, VAL2,", #8, #16")
+	TEST_R(     "sbfx	r4, r",10,  VAL1,", #16, #15")
+	TEST_UNSUPPORTED(".short 0xf34c,0x2d0f	@ sbfx	sp, r12, #8, #16")
+	TEST_UNSUPPORTED(".short 0xf34c,0x2f0f	@ sbfx	pc, r12, #8, #16")
+	TEST_UNSUPPORTED(".short 0xf34d,0x2c0f	@ sbfx	r12, sp, #8, #16")
+	TEST_UNSUPPORTED(".short 0xf34f,0x2c0f	@ sbfx	r12, pc, #8, #16")
+
+	TEST_R(     "ubfx	r0, r",0  , VAL1,", #0, #31")
+	TEST_R(     "ubfx	r14, r",12, VAL2,", #8, #16")
+	TEST_R(     "ubfx	r4, r",10,  VAL1,", #16, #15")
+	TEST_UNSUPPORTED(".short 0xf3cc,0x2d0f	@ ubfx	sp, r12, #8, #16")
+	TEST_UNSUPPORTED(".short 0xf3cc,0x2f0f	@ ubfx	pc, r12, #8, #16")
+	TEST_UNSUPPORTED(".short 0xf3cd,0x2c0f	@ ubfx	r12, sp, #8, #16")
+	TEST_UNSUPPORTED(".short 0xf3cf,0x2c0f	@ ubfx	r12, pc, #8, #16")
+
+	TEST_R(     "bfc	r",0, VAL1,", #4, #20")
+	TEST_R(     "bfc	r",14,VAL2,", #4, #20")
+	TEST_R(     "bfc	r",7, VAL1,", #0, #31")
+	TEST_R(     "bfc	r",8, VAL2,", #0, #31")
+	TEST_UNSUPPORTED(".short 0xf36f,0x0d1e	@ bfc	sp, #0, #31")
+	TEST_UNSUPPORTED(".short 0xf36f,0x0f1e	@ bfc	pc, #0, #31")
+
+	TEST_RR(    "bfi	r",0, VAL1,", r",0  , VAL2,", #0, #31")
+	TEST_RR(    "bfi	r",12,VAL1,", r",14 , VAL2,", #4, #20")
+	TEST_UNSUPPORTED(".short 0xf36e,0x1d17	@ bfi	sp, r14, #4, #20")
+	TEST_UNSUPPORTED(".short 0xf36e,0x1f17	@ bfi	pc, r14, #4, #20")
+	TEST_UNSUPPORTED(".short 0xf36d,0x1e17	@ bfi	r14, sp, #4, #20")
+
+	TEST_GROUP("Branches and miscellaneous control")
+
+CONDITION_INSTRUCTIONS(22,
+	TEST_BF("beq.w	2f")
+	TEST_BB("bne.w	2b")
+	TEST_BF("bgt.w	2f")
+	TEST_BB("blt.w	2b")
+	TEST_BF_X("bpl.w	2f", SPACE_0x1000)
+)
+
+	TEST_UNSUPPORTED("msr	cpsr, r0")
+	TEST_UNSUPPORTED("msr	cpsr_f, r1")
+	TEST_UNSUPPORTED("msr	spsr, r2")
+
+	TEST_UNSUPPORTED("cpsie.w	i")
+	TEST_UNSUPPORTED("cpsid.w	i")
+	TEST_UNSUPPORTED("cps	0x13")
+
+	TEST_SUPPORTED("yield.w")
+	TEST("sev.w")
+	TEST("nop.w")
+	TEST("wfi.w")
+	TEST_SUPPORTED("wfe.w")
+	TEST_UNSUPPORTED("dbg.w	#0")
+
+	TEST_UNSUPPORTED("clrex")
+	TEST_UNSUPPORTED("dsb")
+	TEST_UNSUPPORTED("dmb")
+	TEST_UNSUPPORTED("isb")
+
+	TEST_UNSUPPORTED("bxj	r0")
+
+	TEST_UNSUPPORTED("subs	pc, lr, #4")
+
+	TEST("mrs	r0, cpsr")
+	TEST("mrs	r14, cpsr")
+	TEST_UNSUPPORTED(".short 0xf3ef,0x8d00	@ mrs	sp, spsr")
+	TEST_UNSUPPORTED(".short 0xf3ef,0x8f00	@ mrs	pc, spsr")
+	TEST_UNSUPPORTED("mrs	r0, spsr")
+	TEST_UNSUPPORTED("mrs	lr, spsr")
+
+	TEST_UNSUPPORTED(".short 0xf7f0,0x8000 @ smc #0")
+
+	TEST_UNSUPPORTED(".short 0xf7f0,0xa000 @ undefeined")
+
+	TEST_BF(  "b.w	2f")
+	TEST_BB(  "b.w	2b")
+	TEST_BF_X("b.w	2f", SPACE_0x1000)
+
+	TEST_BF(  "bl.w	2f")
+	TEST_BB(  "bl.w	2b")
+	TEST_BB_X("bl.w	2b", SPACE_0x1000)
+
+	TEST_X(	"blx	__dummy_arm_subroutine",
+		".arm				\n\t"
+		".align				\n\t"
+		".type __dummy_arm_subroutine, %%function \n\t"
+		"__dummy_arm_subroutine:	\n\t"
+		"mov	r0, pc			\n\t"
+		"bx	lr			\n\t"
+		".thumb				\n\t"
+	)
+	TEST(	"blx	__dummy_arm_subroutine")
+
+	TEST_GROUP("Store single data item")
+
+#define SINGLE_STORE(size)							\
+	TEST_RP( "str"size"	r",0, VAL1,", [r",11,-1024,", #1024]")		\
+	TEST_RP( "str"size"	r",14,VAL2,", [r",1, -1024,", #1080]")		\
+	TEST_RP( "str"size"	r",0, VAL1,", [r",11,256,  ", #-120]")		\
+	TEST_RP( "str"size"	r",14,VAL2,", [r",1, 256,  ", #-128]")		\
+	TEST_RP( "str"size"	r",0, VAL1,", [r",11,24,  "], #120")		\
+	TEST_RP( "str"size"	r",14,VAL2,", [r",1, 24,  "], #128")		\
+	TEST_RP( "str"size"	r",0, VAL1,", [r",11,24,  "], #-120")		\
+	TEST_RP( "str"size"	r",14,VAL2,", [r",1, 24,  "], #-128")		\
+	TEST_RP( "str"size"	r",0, VAL1,", [r",11,24,   ", #120]!")		\
+	TEST_RP( "str"size"	r",14,VAL2,", [r",1, 24,   ", #128]!")		\
+	TEST_RP( "str"size"	r",0, VAL1,", [r",11,256,  ", #-120]!")		\
+	TEST_RP( "str"size"	r",14,VAL2,", [r",1, 256,  ", #-128]!")		\
+	TEST_RPR("str"size".w	r",0, VAL1,", [r",1, 0,", r",2, 4,"]")		\
+	TEST_RPR("str"size"	r",14,VAL2,", [r",10,0,", r",11,4,", lsl #1]")	\
+	TEST_R(  "str"size".w	r",7, VAL1,", [sp, #24]")			\
+	TEST_RP( "str"size".w	r",0, VAL2,", [r",0,0, "]")			\
+	TEST_UNSUPPORTED("str"size"t	r0, [r1, #4]")
+
+	SINGLE_STORE("b")
+	SINGLE_STORE("h")
+	SINGLE_STORE("")
+
+	TEST("str	sp, [sp]")
+	TEST_UNSUPPORTED(".short 0xf8cf,0xe000	@ str	r14, [pc]")
+	TEST_UNSUPPORTED(".short 0xf8ce,0xf000	@ str	pc, [r14]")
+
+	TEST_GROUP("Advanced SIMD element or structure load/store instructions")
+
+	TEST_UNSUPPORTED(".short 0xf900,0x0000")
+	TEST_UNSUPPORTED(".short 0xf92f,0xffff")
+	TEST_UNSUPPORTED(".short 0xf980,0x0000")
+	TEST_UNSUPPORTED(".short 0xf9ef,0xffff")
+
+	TEST_GROUP("Load single data item and memory hints")
+
+#define SINGLE_LOAD(size)						\
+	TEST_P( "ldr"size"	r0, [r",11,-1024, ", #1024]")		\
+	TEST_P( "ldr"size"	r14, [r",1, -1024,", #1080]")		\
+	TEST_P( "ldr"size"	r0, [r",11,256,   ", #-120]")		\
+	TEST_P( "ldr"size"	r14, [r",1, 256,  ", #-128]")		\
+	TEST_P( "ldr"size"	r0, [r",11,24,   "], #120")		\
+	TEST_P( "ldr"size"	r14, [r",1, 24,  "], #128")		\
+	TEST_P( "ldr"size"	r0, [r",11,24,   "], #-120")		\
+	TEST_P( "ldr"size"	r14, [r",1,24,   "], #-128")		\
+	TEST_P( "ldr"size"	r0, [r",11,24,    ", #120]!")		\
+	TEST_P( "ldr"size"	r14, [r",1, 24,   ", #128]!")		\
+	TEST_P( "ldr"size"	r0, [r",11,256,   ", #-120]!")		\
+	TEST_P( "ldr"size"	r14, [r",1, 256,  ", #-128]!")		\
+	TEST_PR("ldr"size".w	r0, [r",1, 0,", r",2, 4,"]")		\
+	TEST_PR("ldr"size"	r14, [r",10,0,", r",11,4,", lsl #1]")	\
+	TEST_X( "ldr"size".w	r0, 3f",				\
+		".align 3				\n\t"		\
+		"3:	.word	"__stringify(VAL1))			\
+	TEST_X( "ldr"size".w	r14, 3f",				\
+		".align 3				\n\t"		\
+		"3:	.word	"__stringify(VAL2))			\
+	TEST(   "ldr"size".w	r7, 3b")				\
+	TEST(   "ldr"size".w	r7, [sp, #24]")				\
+	TEST_P( "ldr"size".w	r0, [r",0,0, "]")			\
+	TEST_UNSUPPORTED("ldr"size"t	r0, [r1, #4]")
+
+	SINGLE_LOAD("b")
+	SINGLE_LOAD("sb")
+	SINGLE_LOAD("h")
+	SINGLE_LOAD("sh")
+	SINGLE_LOAD("")
+
+	TEST_BF_P("ldr	pc, [r",14, 15*4,"]")
+	TEST_P(   "ldr	sp, [r",14, 13*4,"]")
+	TEST_BF_R("ldr	pc, [sp, r",14, 15*4,"]")
+	TEST_R(   "ldr	sp, [sp, r",14, 13*4,"]")
+	TEST_THUMB_TO_ARM_INTERWORK_P("ldr	pc, [r",0,0,", #15*4]")
+	TEST_SUPPORTED("ldr	sp, 99f")
+	TEST_SUPPORTED("ldr	pc, 99f")
+
+	TEST_UNSUPPORTED(".short 0xf854,0x700d	@ ldr	r7, [r4, sp]")
+	TEST_UNSUPPORTED(".short 0xf854,0x700f	@ ldr	r7, [r4, pc]")
+	TEST_UNSUPPORTED(".short 0xf814,0x700d	@ ldrb	r7, [r4, sp]")
+	TEST_UNSUPPORTED(".short 0xf814,0x700f	@ ldrb	r7, [r4, pc]")
+	TEST_UNSUPPORTED(".short 0xf89f,0xd004	@ ldrb	sp, 99f")
+	TEST_UNSUPPORTED(".short 0xf814,0xd008	@ ldrb	sp, [r4, r8]")
+	TEST_UNSUPPORTED(".short 0xf894,0xd000	@ ldrb	sp, [r4]")
+
+	TEST_UNSUPPORTED(".short 0xf860,0x0000") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xf9ff,0xffff") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xf950,0x0000") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xf95f,0xffff") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xf800,0x0800") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xf97f,0xfaff") /* Unallocated space */
+
+	TEST(   "pli	[pc, #4]")
+	TEST(   "pli	[pc, #-4]")
+	TEST(   "pld	[pc, #4]")
+	TEST(   "pld	[pc, #-4]")
+
+	TEST_P( "pld	[r",0,-1024,", #1024]")
+	TEST(   ".short 0xf8b0,0xf400	@ pldw	[r0, #1024]")
+	TEST_P( "pli	[r",4, 0b,", #1024]")
+	TEST_P( "pld	[r",7, 120,", #-120]")
+	TEST(   ".short 0xf837,0xfc78	@ pldw	[r7, #-120]")
+	TEST_P( "pli	[r",11,120,", #-120]")
+	TEST(   "pld	[sp, #0]")
+
+	TEST_PR("pld	[r",7, 24, ", r",0, 16,"]")
+	TEST_PR("pld	[r",8, 24, ", r",12,16,", lsl #3]")
+	TEST_SUPPORTED(".short 0xf837,0xf000	@ pldw	[r7, r0]")
+	TEST_SUPPORTED(".short 0xf838,0xf03c	@ pldw	[r8, r12, lsl #3]");
+	TEST_RR("pli	[r",12,0b,", r",0, 16,"]")
+	TEST_RR("pli	[r",0, 0b,", r",12,16,", lsl #3]")
+	TEST_R( "pld	[sp, r",1, 16,"]")
+	TEST_UNSUPPORTED(".short 0xf817,0xf00d  @pld	[r7, sp]")
+	TEST_UNSUPPORTED(".short 0xf817,0xf00f  @pld	[r7, pc]")
+
+	TEST_GROUP("Data-processing (register)")
+
+#define SHIFTS32(op)					\
+	TEST_RR(op"	r0,  r",1, VAL1,", r",2, 3, "")	\
+	TEST_RR(op"	r14, r",12,VAL2,", r",11,10,"")
+
+	SHIFTS32("lsl")
+	SHIFTS32("lsls")
+	SHIFTS32("lsr")
+	SHIFTS32("lsrs")
+	SHIFTS32("asr")
+	SHIFTS32("asrs")
+	SHIFTS32("ror")
+	SHIFTS32("rors")
+
+	TEST_UNSUPPORTED(".short 0xfa01,0xff02	@ lsl	pc, r1, r2")
+	TEST_UNSUPPORTED(".short 0xfa01,0xfd02	@ lsl	sp, r1, r2")
+	TEST_UNSUPPORTED(".short 0xfa0f,0xf002	@ lsl	r0, pc, r2")
+	TEST_UNSUPPORTED(".short 0xfa0d,0xf002	@ lsl	r0, sp, r2")
+	TEST_UNSUPPORTED(".short 0xfa01,0xf00f	@ lsl	r0, r1, pc")
+	TEST_UNSUPPORTED(".short 0xfa01,0xf00d	@ lsl	r0, r1, sp")
+
+	TEST_RR(    "sxtah	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sxtah	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "sxth	r8, r",7,  HH1,"")
+
+	TEST_UNSUPPORTED(".short 0xfa0f,0xff87	@ sxth	pc, r7");
+	TEST_UNSUPPORTED(".short 0xfa0f,0xfd87	@ sxth	sp, r7");
+	TEST_UNSUPPORTED(".short 0xfa0f,0xf88f	@ sxth	r8, pc");
+	TEST_UNSUPPORTED(".short 0xfa0f,0xf88d	@ sxth	r8, sp");
+
+	TEST_RR(    "uxtah	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uxtah	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "uxth	r8, r",7,  HH1,"")
+
+	TEST_RR(    "sxtab16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sxtab16	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "sxtb16	r8, r",7,  HH1,"")
+
+	TEST_RR(    "uxtab16	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uxtab16	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "uxtb16	r8, r",7,  HH1,"")
+
+	TEST_RR(    "sxtab	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "sxtab	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "sxtb	r8, r",7,  HH1,"")
+
+	TEST_RR(    "uxtab	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "uxtab	r14,r",12, HH2,", r",10,HH1,", ror #8")
+	TEST_R(     "uxtb	r8, r",7,  HH1,"")
+
+	TEST_UNSUPPORTED(".short 0xfa60,0x00f0")
+	TEST_UNSUPPORTED(".short 0xfa7f,0xffff")
+
+#define PARALLEL_ADD_SUB(op)					\
+	TEST_RR(  op"add16	r0, r",0,  HH1,", r",1, HH2,"")	\
+	TEST_RR(  op"add16	r14, r",12,HH2,", r",10,HH1,"")	\
+	TEST_RR(  op"asx	r0, r",0,  HH1,", r",1, HH2,"")	\
+	TEST_RR(  op"asx	r14, r",12,HH2,", r",10,HH1,"")	\
+	TEST_RR(  op"sax	r0, r",0,  HH1,", r",1, HH2,"")	\
+	TEST_RR(  op"sax	r14, r",12,HH2,", r",10,HH1,"")	\
+	TEST_RR(  op"sub16	r0, r",0,  HH1,", r",1, HH2,"")	\
+	TEST_RR(  op"sub16	r14, r",12,HH2,", r",10,HH1,"")	\
+	TEST_RR(  op"add8	r0, r",0,  HH1,", r",1, HH2,"")	\
+	TEST_RR(  op"add8	r14, r",12,HH2,", r",10,HH1,"")	\
+	TEST_RR(  op"sub8	r0, r",0,  HH1,", r",1, HH2,"")	\
+	TEST_RR(  op"sub8	r14, r",12,HH2,", r",10,HH1,"")
+
+	TEST_GROUP("Parallel addition and subtraction, signed")
+
+	PARALLEL_ADD_SUB("s")
+	PARALLEL_ADD_SUB("q")
+	PARALLEL_ADD_SUB("sh")
+
+	TEST_GROUP("Parallel addition and subtraction, unsigned")
+
+	PARALLEL_ADD_SUB("u")
+	PARALLEL_ADD_SUB("uq")
+	PARALLEL_ADD_SUB("uh")
+
+	TEST_GROUP("Miscellaneous operations")
+
+	TEST_RR("qadd	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR("qadd	lr, r",9, VAL2,", r",8, VAL1,"")
+	TEST_RR("qsub	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR("qsub	lr, r",9, VAL2,", r",8, VAL1,"")
+	TEST_RR("qdadd	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR("qdadd	lr, r",9, VAL2,", r",8, VAL1,"")
+	TEST_RR("qdsub	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR("qdsub	lr, r",9, VAL2,", r",8, VAL1,"")
+
+	TEST_R("rev.w	r0, r",0,   VAL1,"")
+	TEST_R("rev	r14, r",12, VAL2,"")
+	TEST_R("rev16.w	r0, r",0,   VAL1,"")
+	TEST_R("rev16	r14, r",12, VAL2,"")
+	TEST_R("rbit	r0, r",0,   VAL1,"")
+	TEST_R("rbit	r14, r",12, VAL2,"")
+	TEST_R("revsh.w	r0, r",0,   VAL1,"")
+	TEST_R("revsh	r14, r",12, VAL2,"")
+
+	TEST_UNSUPPORTED(".short 0xfa9c,0xff8c	@ rev	pc, r12");
+	TEST_UNSUPPORTED(".short 0xfa9c,0xfd8c	@ rev	sp, r12");
+	TEST_UNSUPPORTED(".short 0xfa9f,0xfe8f	@ rev	r14, pc");
+	TEST_UNSUPPORTED(".short 0xfa9d,0xfe8d	@ rev	r14, sp");
+
+	TEST_RR("sel	r0, r",0,  VAL1,", r",1, VAL2,"")
+	TEST_RR("sel	r14, r",12,VAL1,", r",10, VAL2,"")
+
+	TEST_R("clz	r0, r",0, 0x0,"")
+	TEST_R("clz	r7, r",14,0x1,"")
+	TEST_R("clz	lr, r",7, 0xffffffff,"")
+
+	TEST_UNSUPPORTED(".short 0xfa80,0xf030") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xfaff,0xff7f") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xfab0,0xf000") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xfaff,0xff7f") /* Unallocated space */
+
+	TEST_GROUP("Multiply, multiply accumulate, and absolute difference operations")
+
+	TEST_RR(    "mul	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "mul	r7, r",8, VAL2,", r",9, VAL2,"")
+	TEST_UNSUPPORTED(".short 0xfb08,0xff09	@ mul	pc, r8, r9")
+	TEST_UNSUPPORTED(".short 0xfb08,0xfd09	@ mul	sp, r8, r9")
+	TEST_UNSUPPORTED(".short 0xfb0f,0xf709	@ mul	r7, pc, r9")
+	TEST_UNSUPPORTED(".short 0xfb0d,0xf709	@ mul	r7, sp, r9")
+	TEST_UNSUPPORTED(".short 0xfb08,0xf70f	@ mul	r7, r8, pc")
+	TEST_UNSUPPORTED(".short 0xfb08,0xf70d	@ mul	r7, r8, sp")
+
+	TEST_RRR(   "mla	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(   "mla	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_UNSUPPORTED(".short 0xfb08,0xaf09	@ mla	pc, r8, r9, r10");
+	TEST_UNSUPPORTED(".short 0xfb08,0xad09	@ mla	sp, r8, r9, r10");
+	TEST_UNSUPPORTED(".short 0xfb0f,0xa709	@ mla	r7, pc, r9, r10");
+	TEST_UNSUPPORTED(".short 0xfb0d,0xa709	@ mla	r7, sp, r9, r10");
+	TEST_UNSUPPORTED(".short 0xfb08,0xa70f	@ mla	r7, r8, pc, r10");
+	TEST_UNSUPPORTED(".short 0xfb08,0xa70d	@ mla	r7, r8, sp, r10");
+	TEST_UNSUPPORTED(".short 0xfb08,0xd709	@ mla	r7, r8, r9, sp");
+
+	TEST_RRR(   "mls	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(   "mls	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+
+	TEST_RRR(   "smlabb	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(   "smlabb	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RRR(   "smlatb	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(   "smlatb	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RRR(   "smlabt	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(   "smlabt	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RRR(   "smlatt	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(   "smlatt	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(    "smulbb	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulbb	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_RR(    "smultb	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smultb	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_RR(    "smulbt	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulbt	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_RR(    "smultt	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smultt	r7, r",8, VAL3,", r",9, VAL1,"")
+
+	TEST_RRR(   "smlad	r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+	TEST_RRR(   "smlad	r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+	TEST_RRR(   "smladx	r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+	TEST_RRR(   "smladx	r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+	TEST_RR(    "smuad	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "smuad	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_RR(    "smuadx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "smuadx	r14, r",12,HH2,", r",10,HH1,"")
+
+	TEST_RRR(   "smlawb	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(   "smlawb	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RRR(   "smlawt	r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
+	TEST_RRR(   "smlawt	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
+	TEST_RR(    "smulwb	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulwb	r7, r",8, VAL3,", r",9, VAL1,"")
+	TEST_RR(    "smulwt	r0, r",1, VAL1,", r",2, VAL2,"")
+	TEST_RR(    "smulwt	r7, r",8, VAL3,", r",9, VAL1,"")
+
+	TEST_RRR(   "smlsd	r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+	TEST_RRR(   "smlsd	r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+	TEST_RRR(   "smlsdx	r0, r",0,  HH1,", r",1, HH2,", r",2, VAL1,"")
+	TEST_RRR(   "smlsdx	r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"")
+	TEST_RR(    "smusd	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "smusd	r14, r",12,HH2,", r",10,HH1,"")
+	TEST_RR(    "smusdx	r0, r",0,  HH1,", r",1, HH2,"")
+	TEST_RR(    "smusdx	r14, r",12,HH2,", r",10,HH1,"")
+
+	TEST_RRR(   "smmla	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+	TEST_RRR(   "smmla	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+	TEST_RRR(   "smmlar	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+	TEST_RRR(   "smmlar	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+	TEST_RR(    "smmul	r0, r",0,  VAL1,", r",1, VAL2,"")
+	TEST_RR(    "smmul	r14, r",12,VAL2,", r",10,VAL1,"")
+	TEST_RR(    "smmulr	r0, r",0,  VAL1,", r",1, VAL2,"")
+	TEST_RR(    "smmulr	r14, r",12,VAL2,", r",10,VAL1,"")
+
+	TEST_RRR(   "smmls	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+	TEST_RRR(   "smmls	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+	TEST_RRR(   "smmlsr	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL1,"")
+	TEST_RRR(   "smmlsr	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"")
+
+	TEST_RRR(   "usada8	r0, r",0,  VAL1,", r",1, VAL2,", r",2, VAL3,"")
+	TEST_RRR(   "usada8	r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL3,"")
+	TEST_RR(    "usad8	r0, r",0,  VAL1,", r",1, VAL2,"")
+	TEST_RR(    "usad8	r14, r",12,VAL2,", r",10,VAL1,"")
+
+	TEST_UNSUPPORTED(".short 0xfb00,0xf010") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xfb0f,0xff1f") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xfb70,0xf010") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xfb7f,0xff1f") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xfb70,0x0010") /* Unallocated space */
+	TEST_UNSUPPORTED(".short 0xfb7f,0xff1f") /* Unallocated space */
+
+	TEST_GROUP("Long multiply, long multiply accumulate, and divide")
+
+	TEST_RR(   "smull	r0, r1, r",2, VAL1,", r",3, VAL2,"")
+	TEST_RR(   "smull	r7, r8, r",9, VAL2,", r",10, VAL1,"")
+	TEST_UNSUPPORTED(".short 0xfb89,0xf80a	@ smull	pc, r8, r9, r10");
+	TEST_UNSUPPORTED(".short 0xfb89,0xd80a	@ smull	sp, r8, r9, r10");
+	TEST_UNSUPPORTED(".short 0xfb89,0x7f0a	@ smull	r7, pc, r9, r10");
+	TEST_UNSUPPORTED(".short 0xfb89,0x7d0a	@ smull	r7, sp, r9, r10");
+	TEST_UNSUPPORTED(".short 0xfb8f,0x780a	@ smull	r7, r8, pc, r10");
+	TEST_UNSUPPORTED(".short 0xfb8d,0x780a	@ smull	r7, r8, sp, r10");
+	TEST_UNSUPPORTED(".short 0xfb89,0x780f	@ smull	r7, r8, r9, pc");
+	TEST_UNSUPPORTED(".short 0xfb89,0x780d	@ smull	r7, r8, r9, sp");
+
+	TEST_RR(   "umull	r0, r1, r",2, VAL1,", r",3, VAL2,"")
+	TEST_RR(   "umull	r7, r8, r",9, VAL2,", r",10, VAL1,"")
+
+	TEST_RRRR( "smlal	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR( "smlal	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+
+	TEST_RRRR( "smlalbb	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR( "smlalbb	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRRR( "smlalbt	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR( "smlalbt	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRRR( "smlaltb	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR( "smlaltb	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRRR( "smlaltt	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR( "smlaltt	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+
+	TEST_RRRR( "smlald	r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+	TEST_RRRR( "smlald	r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+	TEST_RRRR( "smlaldx	r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+	TEST_RRRR( "smlaldx	r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+
+	TEST_RRRR( "smlsld	r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+	TEST_RRRR( "smlsld	r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+	TEST_RRRR( "smlsldx	r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2)
+	TEST_RRRR( "smlsldx	r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1)
+
+	TEST_RRRR( "umlal	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR( "umlal	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+	TEST_RRRR( "umaal	r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4)
+	TEST_RRRR( "umaal	r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3)
+
+	TEST_GROUP("Coprocessor instructions")
+
+	TEST_UNSUPPORTED(".short 0xfc00,0x0000")
+	TEST_UNSUPPORTED(".short 0xffff,0xffff")
+
+	TEST_GROUP("Testing instructions in IT blocks")
+
+	TEST_ITBLOCK("sub.w	r0, r0")
+
+	verbose("\n");
+}
+
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/kprobes-thumb.c linux-libre-3.2-gnu/arch/arm/kernel/kprobes-thumb.c
--- linux-libre-3.1-gnu/arch/arm/kernel/kprobes-thumb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/kprobes-thumb.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/kprobes.h>
+#include <linux/module.h>
 
 #include "kprobes.h"
 
@@ -943,6 +944,9 @@
 	 */
 	DECODE_END
 };
+#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
+EXPORT_SYMBOL_GPL(kprobe_decode_thumb32_table);
+#endif
 
 static void __kprobes
 t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
@@ -1423,6 +1427,9 @@
 
 	DECODE_END
 };
+#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
+EXPORT_SYMBOL_GPL(kprobe_decode_thumb16_table);
+#endif
 
 static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
 {
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/leds.c linux-libre-3.2-gnu/arch/arm/kernel/leds.c
--- linux-libre-3.1-gnu/arch/arm/kernel/leds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/leds.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,10 +7,11 @@
  * 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/export.h>
 #include <linux/init.h>
 #include <linux/sysdev.h>
 #include <linux/syscore_ops.h>
+#include <linux/string.h>
 
 #include <asm/leds.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/Makefile linux-libre-3.2-gnu/arch/arm/kernel/Makefile
--- linux-libre-3.1-gnu/arch/arm/kernel/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +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_ARM_CPU_SUSPEND)	+= sleep.o suspend.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
@@ -43,6 +43,13 @@
 else
 obj-$(CONFIG_KPROBES)		+= kprobes-arm.o
 endif
+obj-$(CONFIG_ARM_KPROBES_TEST)	+= test-kprobes.o
+test-kprobes-objs		:= kprobes-test.o
+ifdef CONFIG_THUMB2_KERNEL
+test-kprobes-objs		+= kprobes-test-thumb.o
+else
+test-kprobes-objs		+= kprobes-test-arm.o
+endif
 obj-$(CONFIG_ATAGS_PROC)	+= atags.o
 obj-$(CONFIG_OABI_COMPAT)	+= sys_oabi-compat.o
 obj-$(CONFIG_ARM_THUMBEE)	+= thumbee.o
@@ -66,6 +73,7 @@
 obj-$(CONFIG_CPU_HAS_PMU)	+= pmu.o
 obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
 AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
+obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
 
 ifneq ($(CONFIG_ARCH_EBSA110),y)
   obj-y		+= io.o
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/module.c linux-libre-3.2-gnu/arch/arm/kernel/module.c
--- linux-libre-3.1-gnu/arch/arm/kernel/module.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/module.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,7 @@
  * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off.
  */
 #undef MODULES_VADDR
-#define MODULES_VADDR	(((unsigned long)_etext + ~PGDIR_MASK) & PGDIR_MASK)
+#define MODULES_VADDR	(((unsigned long)_etext + ~PMD_MASK) & PMD_MASK)
 #endif
 
 #ifdef CONFIG_MMU
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/perf_event.c linux-libre-3.2-gnu/arch/arm/kernel/perf_event.c
--- linux-libre-3.1-gnu/arch/arm/kernel/perf_event.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/perf_event.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,9 +12,10 @@
  */
 #define pr_fmt(fmt) "hw perfevents: " fmt
 
+#include <linux/bitmap.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/perf_event.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
@@ -26,16 +27,8 @@
 #include <asm/pmu.h>
 #include <asm/stacktrace.h>
 
-static struct platform_device *pmu_device;
-
-/*
- * Hardware lock to serialize accesses to PMU registers. Needed for the
- * read/modify/write sequences.
- */
-static DEFINE_RAW_SPINLOCK(pmu_lock);
-
 /*
- * ARMv6 supports a maximum of 3 events, starting from index 1. If we add
+ * ARMv6 supports a maximum of 3 events, starting from index 0. If we add
  * another platform that supports more, we need to increase this to be the
  * largest of all platforms.
  *
@@ -43,62 +36,24 @@
  *  cycle counter CCNT + 31 events counters CNT0..30.
  *  Cortex-A8 has 1+4 counters, Cortex-A9 has 1+6 counters.
  */
-#define ARMPMU_MAX_HWEVENTS		33
-
-/* The events for a given CPU. */
-struct cpu_hw_events {
-	/*
-	 * The events that are active on the CPU for the given index. Index 0
-	 * is reserved.
-	 */
-	struct perf_event	*events[ARMPMU_MAX_HWEVENTS];
-
-	/*
-	 * A 1 bit for an index indicates that the counter is being used for
-	 * an event. A 0 means that the counter can be used.
-	 */
-	unsigned long		used_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)];
+#define ARMPMU_MAX_HWEVENTS		32
 
-	/*
-	 * A 1 bit for an index indicates that the counter is actively being
-	 * used.
-	 */
-	unsigned long		active_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)];
-};
-static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
+static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
+static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
+static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
 
-struct arm_pmu {
-	enum arm_perf_pmu_ids id;
-	const char	*name;
-	irqreturn_t	(*handle_irq)(int irq_num, void *dev);
-	void		(*enable)(struct hw_perf_event *evt, int idx);
-	void		(*disable)(struct hw_perf_event *evt, int idx);
-	int		(*get_event_idx)(struct cpu_hw_events *cpuc,
-					 struct hw_perf_event *hwc);
-	u32		(*read_counter)(int idx);
-	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];
-	const unsigned	(*event_map)[PERF_COUNT_HW_MAX];
-	u32		raw_event_mask;
-	int		num_events;
-	u64		max_period;
-};
+#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
 
 /* Set at runtime when we know what CPU type we are. */
-static const struct arm_pmu *armpmu;
+static struct arm_pmu *cpu_pmu;
 
 enum arm_perf_pmu_ids
 armpmu_get_pmu_id(void)
 {
 	int id = -ENODEV;
 
-	if (armpmu != NULL)
-		id = armpmu->id;
+	if (cpu_pmu != NULL)
+		id = cpu_pmu->id;
 
 	return id;
 }
@@ -109,8 +64,8 @@
 {
 	int max_events = 0;
 
-	if (armpmu != NULL)
-		max_events = armpmu->num_events;
+	if (cpu_pmu != NULL)
+		max_events = cpu_pmu->num_events;
 
 	return max_events;
 }
@@ -130,7 +85,11 @@
 #define CACHE_OP_UNSUPPORTED		0xFFFF
 
 static int
-armpmu_map_cache_event(u64 config)
+armpmu_map_cache_event(const unsigned (*cache_map)
+				      [PERF_COUNT_HW_CACHE_MAX]
+				      [PERF_COUNT_HW_CACHE_OP_MAX]
+				      [PERF_COUNT_HW_CACHE_RESULT_MAX],
+		       u64 config)
 {
 	unsigned int cache_type, cache_op, cache_result, ret;
 
@@ -146,7 +105,7 @@
 	if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
 		return -EINVAL;
 
-	ret = (int)(*armpmu->cache_map)[cache_type][cache_op][cache_result];
+	ret = (int)(*cache_map)[cache_type][cache_op][cache_result];
 
 	if (ret == CACHE_OP_UNSUPPORTED)
 		return -ENOENT;
@@ -155,23 +114,46 @@
 }
 
 static int
-armpmu_map_event(u64 config)
+armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
 {
-	int mapping = (*armpmu->event_map)[config];
-	return mapping == HW_OP_UNSUPPORTED ? -EOPNOTSUPP : mapping;
+	int mapping = (*event_map)[config];
+	return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
 }
 
 static int
-armpmu_map_raw_event(u64 config)
+armpmu_map_raw_event(u32 raw_event_mask, u64 config)
 {
-	return (int)(config & armpmu->raw_event_mask);
+	return (int)(config & raw_event_mask);
 }
 
-static int
+static int map_cpu_event(struct perf_event *event,
+			 const unsigned (*event_map)[PERF_COUNT_HW_MAX],
+			 const unsigned (*cache_map)
+					[PERF_COUNT_HW_CACHE_MAX]
+					[PERF_COUNT_HW_CACHE_OP_MAX]
+					[PERF_COUNT_HW_CACHE_RESULT_MAX],
+			 u32 raw_event_mask)
+{
+	u64 config = event->attr.config;
+
+	switch (event->attr.type) {
+	case PERF_TYPE_HARDWARE:
+		return armpmu_map_event(event_map, config);
+	case PERF_TYPE_HW_CACHE:
+		return armpmu_map_cache_event(cache_map, config);
+	case PERF_TYPE_RAW:
+		return armpmu_map_raw_event(raw_event_mask, config);
+	}
+
+	return -ENOENT;
+}
+
+int
 armpmu_event_set_period(struct perf_event *event,
 			struct hw_perf_event *hwc,
 			int idx)
 {
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	s64 left = local64_read(&hwc->period_left);
 	s64 period = hwc->sample_period;
 	int ret = 0;
@@ -202,11 +184,12 @@
 	return ret;
 }
 
-static u64
+u64
 armpmu_event_update(struct perf_event *event,
 		    struct hw_perf_event *hwc,
 		    int idx, int overflow)
 {
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	u64 delta, prev_raw_count, new_raw_count;
 
 again:
@@ -246,11 +229,9 @@
 static void
 armpmu_stop(struct perf_event *event, int flags)
 {
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	struct hw_perf_event *hwc = &event->hw;
 
-	if (!armpmu)
-		return;
-
 	/*
 	 * ARM pmu always has to update the counter, so ignore
 	 * PERF_EF_UPDATE, see comments in armpmu_start().
@@ -266,11 +247,9 @@
 static void
 armpmu_start(struct perf_event *event, int flags)
 {
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	struct hw_perf_event *hwc = &event->hw;
 
-	if (!armpmu)
-		return;
-
 	/*
 	 * ARM pmu always has to reprogram the period, so ignore
 	 * PERF_EF_RELOAD, see the comment below.
@@ -293,16 +272,16 @@
 static void
 armpmu_del(struct perf_event *event, int flags)
 {
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	struct pmu_hw_events *hw_events = armpmu->get_hw_events();
 	struct hw_perf_event *hwc = &event->hw;
 	int idx = hwc->idx;
 
 	WARN_ON(idx < 0);
 
-	clear_bit(idx, cpuc->active_mask);
 	armpmu_stop(event, PERF_EF_UPDATE);
-	cpuc->events[idx] = NULL;
-	clear_bit(idx, cpuc->used_mask);
+	hw_events->events[idx] = NULL;
+	clear_bit(idx, hw_events->used_mask);
 
 	perf_event_update_userpage(event);
 }
@@ -310,7 +289,8 @@
 static int
 armpmu_add(struct perf_event *event, int flags)
 {
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	struct pmu_hw_events *hw_events = armpmu->get_hw_events();
 	struct hw_perf_event *hwc = &event->hw;
 	int idx;
 	int err = 0;
@@ -318,7 +298,7 @@
 	perf_pmu_disable(event->pmu);
 
 	/* If we don't have a space for the counter then finish early. */
-	idx = armpmu->get_event_idx(cpuc, hwc);
+	idx = armpmu->get_event_idx(hw_events, hwc);
 	if (idx < 0) {
 		err = idx;
 		goto out;
@@ -330,8 +310,7 @@
 	 */
 	event->hw.idx = idx;
 	armpmu->disable(hwc, idx);
-	cpuc->events[idx] = event;
-	set_bit(idx, cpuc->active_mask);
+	hw_events->events[idx] = event;
 
 	hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
 	if (flags & PERF_EF_START)
@@ -345,148 +324,166 @@
 	return err;
 }
 
-static struct pmu pmu;
-
 static int
-validate_event(struct cpu_hw_events *cpuc,
+validate_event(struct pmu_hw_events *hw_events,
 	       struct perf_event *event)
 {
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	struct hw_perf_event fake_event = event->hw;
+	struct pmu *leader_pmu = event->group_leader->pmu;
 
-	if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF)
+	if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
 		return 1;
 
-	return armpmu->get_event_idx(cpuc, &fake_event) >= 0;
+	return armpmu->get_event_idx(hw_events, &fake_event) >= 0;
 }
 
 static int
 validate_group(struct perf_event *event)
 {
 	struct perf_event *sibling, *leader = event->group_leader;
-	struct cpu_hw_events fake_pmu;
+	struct pmu_hw_events fake_pmu;
+	DECLARE_BITMAP(fake_used_mask, ARMPMU_MAX_HWEVENTS);
 
-	memset(&fake_pmu, 0, sizeof(fake_pmu));
+	/*
+	 * Initialise the fake PMU. We only need to populate the
+	 * used_mask for the purposes of validation.
+	 */
+	memset(fake_used_mask, 0, sizeof(fake_used_mask));
+	fake_pmu.used_mask = fake_used_mask;
 
 	if (!validate_event(&fake_pmu, leader))
-		return -ENOSPC;
+		return -EINVAL;
 
 	list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
 		if (!validate_event(&fake_pmu, sibling))
-			return -ENOSPC;
+			return -EINVAL;
 	}
 
 	if (!validate_event(&fake_pmu, event))
-		return -ENOSPC;
+		return -EINVAL;
 
 	return 0;
 }
 
 static irqreturn_t armpmu_platform_irq(int irq, void *dev)
 {
-	struct arm_pmu_platdata *plat = dev_get_platdata(&pmu_device->dev);
+	struct arm_pmu *armpmu = (struct arm_pmu *) dev;
+	struct platform_device *plat_device = armpmu->plat_device;
+	struct arm_pmu_platdata *plat = dev_get_platdata(&plat_device->dev);
 
 	return plat->handle_irq(irq, dev, armpmu->handle_irq);
 }
 
+static void
+armpmu_release_hardware(struct arm_pmu *armpmu)
+{
+	int i, irq, irqs;
+	struct platform_device *pmu_device = armpmu->plat_device;
+
+	irqs = min(pmu_device->num_resources, num_possible_cpus());
+
+	for (i = 0; i < irqs; ++i) {
+		if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs))
+			continue;
+		irq = platform_get_irq(pmu_device, i);
+		if (irq >= 0)
+			free_irq(irq, armpmu);
+	}
+
+	release_pmu(armpmu->type);
+}
+
 static int
-armpmu_reserve_hardware(void)
+armpmu_reserve_hardware(struct arm_pmu *armpmu)
 {
 	struct arm_pmu_platdata *plat;
 	irq_handler_t handle_irq;
-	int i, err = -ENODEV, irq;
+	int i, err, irq, irqs;
+	struct platform_device *pmu_device = armpmu->plat_device;
 
-	pmu_device = reserve_pmu(ARM_PMU_DEVICE_CPU);
-	if (IS_ERR(pmu_device)) {
+	if (!pmu_device)
+		return -ENODEV;
+
+	err = reserve_pmu(armpmu->type);
+	if (err) {
 		pr_warning("unable to reserve pmu\n");
-		return PTR_ERR(pmu_device);
+		return err;
 	}
 
-	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) {
+	irqs = min(pmu_device->num_resources, num_possible_cpus());
+	if (irqs < 1) {
 		pr_err("no irqs for PMUs defined\n");
 		return -ENODEV;
 	}
 
-	for (i = 0; i < pmu_device->num_resources; ++i) {
+	for (i = 0; i < irqs; ++i) {
+		err = 0;
 		irq = platform_get_irq(pmu_device, i);
 		if (irq < 0)
 			continue;
 
+		/*
+		 * If we have a single PMU interrupt that we can't shift,
+		 * assume that we're running on a uniprocessor machine and
+		 * continue. Otherwise, continue without this interrupt.
+		 */
+		if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) {
+			pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
+				    irq, i);
+			continue;
+		}
+
 		err = request_irq(irq, handle_irq,
 				  IRQF_DISABLED | IRQF_NOBALANCING,
-				  "armpmu", NULL);
+				  "arm-pmu", armpmu);
 		if (err) {
-			pr_warning("unable to request IRQ%d for ARM perf "
-				"counters\n", irq);
-			break;
+			pr_err("unable to request IRQ%d for ARM PMU counters\n",
+				irq);
+			armpmu_release_hardware(armpmu);
+			return err;
 		}
-	}
 
-	if (err) {
-		for (i = i - 1; i >= 0; --i) {
-			irq = platform_get_irq(pmu_device, i);
-			if (irq >= 0)
-				free_irq(irq, NULL);
-		}
-		release_pmu(ARM_PMU_DEVICE_CPU);
-		pmu_device = NULL;
+		cpumask_set_cpu(i, &armpmu->active_irqs);
 	}
 
-	return err;
+	return 0;
 }
 
 static void
-armpmu_release_hardware(void)
+hw_perf_event_destroy(struct perf_event *event)
 {
-	int i, irq;
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	atomic_t *active_events	 = &armpmu->active_events;
+	struct mutex *pmu_reserve_mutex = &armpmu->reserve_mutex;
 
-	for (i = pmu_device->num_resources - 1; i >= 0; --i) {
-		irq = platform_get_irq(pmu_device, i);
-		if (irq >= 0)
-			free_irq(irq, NULL);
+	if (atomic_dec_and_mutex_lock(active_events, pmu_reserve_mutex)) {
+		armpmu_release_hardware(armpmu);
+		mutex_unlock(pmu_reserve_mutex);
 	}
-	armpmu->stop();
-
-	release_pmu(ARM_PMU_DEVICE_CPU);
-	pmu_device = NULL;
 }
 
-static atomic_t active_events = ATOMIC_INIT(0);
-static DEFINE_MUTEX(pmu_reserve_mutex);
-
-static void
-hw_perf_event_destroy(struct perf_event *event)
+static int
+event_requires_mode_exclusion(struct perf_event_attr *attr)
 {
-	if (atomic_dec_and_mutex_lock(&active_events, &pmu_reserve_mutex)) {
-		armpmu_release_hardware();
-		mutex_unlock(&pmu_reserve_mutex);
-	}
+	return attr->exclude_idle || attr->exclude_user ||
+	       attr->exclude_kernel || attr->exclude_hv;
 }
 
 static int
 __hw_perf_event_init(struct perf_event *event)
 {
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	struct hw_perf_event *hwc = &event->hw;
 	int mapping, err;
 
-	/* Decode the generic type into an ARM event identifier. */
-	if (PERF_TYPE_HARDWARE == event->attr.type) {
-		mapping = armpmu_map_event(event->attr.config);
-	} else if (PERF_TYPE_HW_CACHE == event->attr.type) {
-		mapping = armpmu_map_cache_event(event->attr.config);
-	} else if (PERF_TYPE_RAW == event->attr.type) {
-		mapping = armpmu_map_raw_event(event->attr.config);
-	} else {
-		pr_debug("event type %x not supported\n", event->attr.type);
-		return -EOPNOTSUPP;
-	}
+	mapping = armpmu->map_event(event);
 
 	if (mapping < 0) {
 		pr_debug("event %x:%llx not supported\n", event->attr.type,
@@ -495,34 +492,31 @@
 	}
 
 	/*
+	 * We don't assign an index until we actually place the event onto
+	 * hardware. Use -1 to signify that we haven't decided where to put it
+	 * yet. For SMP systems, each core has it's own PMU so we can't do any
+	 * clever allocation or constraints checking at this point.
+	 */
+	hwc->idx		= -1;
+	hwc->config_base	= 0;
+	hwc->config		= 0;
+	hwc->event_base		= 0;
+
+	/*
 	 * Check whether we need to exclude the counter from certain modes.
-	 * The ARM performance counters are on all of the time so if someone
-	 * has asked us for some excludes then we have to fail.
 	 */
-	if (event->attr.exclude_kernel || event->attr.exclude_user ||
-	    event->attr.exclude_hv || event->attr.exclude_idle) {
+	if ((!armpmu->set_event_filter ||
+	     armpmu->set_event_filter(hwc, &event->attr)) &&
+	     event_requires_mode_exclusion(&event->attr)) {
 		pr_debug("ARM performance counters do not support "
 			 "mode exclusion\n");
 		return -EPERM;
 	}
 
 	/*
-	 * We don't assign an index until we actually place the event onto
-	 * hardware. Use -1 to signify that we haven't decided where to put it
-	 * yet. For SMP systems, each core has it's own PMU so we can't do any
-	 * clever allocation or constraints checking at this point.
-	 */
-	hwc->idx = -1;
-
-	/*
-	 * Store the event encoding into the config_base field. config and
-	 * event_base are unused as the only 2 things we need to know are
-	 * the event mapping and the counter to use. The counter to use is
-	 * also the indx and the config_base is the event type.
+	 * Store the event encoding into the config_base field.
 	 */
-	hwc->config_base	    = (unsigned long)mapping;
-	hwc->config		    = 0;
-	hwc->event_base		    = 0;
+	hwc->config_base	    |= (unsigned long)mapping;
 
 	if (!hwc->sample_period) {
 		hwc->sample_period  = armpmu->max_period;
@@ -542,32 +536,23 @@
 
 static int armpmu_event_init(struct perf_event *event)
 {
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	int err = 0;
+	atomic_t *active_events = &armpmu->active_events;
 
-	switch (event->attr.type) {
-	case PERF_TYPE_RAW:
-	case PERF_TYPE_HARDWARE:
-	case PERF_TYPE_HW_CACHE:
-		break;
-
-	default:
+	if (armpmu->map_event(event) == -ENOENT)
 		return -ENOENT;
-	}
-
-	if (!armpmu)
-		return -ENODEV;
 
 	event->destroy = hw_perf_event_destroy;
 
-	if (!atomic_inc_not_zero(&active_events)) {
-		mutex_lock(&pmu_reserve_mutex);
-		if (atomic_read(&active_events) == 0) {
-			err = armpmu_reserve_hardware();
-		}
+	if (!atomic_inc_not_zero(active_events)) {
+		mutex_lock(&armpmu->reserve_mutex);
+		if (atomic_read(active_events) == 0)
+			err = armpmu_reserve_hardware(armpmu);
 
 		if (!err)
-			atomic_inc(&active_events);
-		mutex_unlock(&pmu_reserve_mutex);
+			atomic_inc(active_events);
+		mutex_unlock(&armpmu->reserve_mutex);
 	}
 
 	if (err)
@@ -582,22 +567,9 @@
 
 static void armpmu_enable(struct pmu *pmu)
 {
-	/* Enable all of the perf events on hardware. */
-	int idx, enabled = 0;
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-
-	if (!armpmu)
-		return;
-
-	for (idx = 0; idx <= armpmu->num_events; ++idx) {
-		struct perf_event *event = cpuc->events[idx];
-
-		if (!event)
-			continue;
-
-		armpmu->enable(&event->hw, idx);
-		enabled = 1;
-	}
+	struct arm_pmu *armpmu = to_arm_pmu(pmu);
+	struct pmu_hw_events *hw_events = armpmu->get_hw_events();
+	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
 
 	if (enabled)
 		armpmu->start();
@@ -605,20 +577,32 @@
 
 static void armpmu_disable(struct pmu *pmu)
 {
-	if (armpmu)
-		armpmu->stop();
+	struct arm_pmu *armpmu = to_arm_pmu(pmu);
+	armpmu->stop();
 }
 
-static struct pmu pmu = {
-	.pmu_enable	= armpmu_enable,
-	.pmu_disable	= armpmu_disable,
-	.event_init	= armpmu_event_init,
-	.add		= armpmu_add,
-	.del		= armpmu_del,
-	.start		= armpmu_start,
-	.stop		= armpmu_stop,
-	.read		= armpmu_read,
-};
+static void __init armpmu_init(struct arm_pmu *armpmu)
+{
+	atomic_set(&armpmu->active_events, 0);
+	mutex_init(&armpmu->reserve_mutex);
+
+	armpmu->pmu = (struct pmu) {
+		.pmu_enable	= armpmu_enable,
+		.pmu_disable	= armpmu_disable,
+		.event_init	= armpmu_event_init,
+		.add		= armpmu_add,
+		.del		= armpmu_del,
+		.start		= armpmu_start,
+		.stop		= armpmu_stop,
+		.read		= armpmu_read,
+	};
+}
+
+int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type)
+{
+	armpmu_init(armpmu);
+	return perf_pmu_register(&armpmu->pmu, name, type);
+}
 
 /* Include the PMU-specific implementations. */
 #include "perf_event_xscale.c"
@@ -630,14 +614,75 @@
  * This requires SMP to be available, so exists as a separate initcall.
  */
 static int __init
-armpmu_reset(void)
+cpu_pmu_reset(void)
 {
-	if (armpmu && armpmu->reset)
-		return on_each_cpu(armpmu->reset, NULL, 1);
+	if (cpu_pmu && cpu_pmu->reset)
+		return on_each_cpu(cpu_pmu->reset, NULL, 1);
 	return 0;
 }
-arch_initcall(armpmu_reset);
+arch_initcall(cpu_pmu_reset);
+
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static struct of_device_id armpmu_of_device_ids[] = {
+	{.compatible = "arm,cortex-a9-pmu"},
+	{.compatible = "arm,cortex-a8-pmu"},
+	{.compatible = "arm,arm1136-pmu"},
+	{.compatible = "arm,arm1176-pmu"},
+	{},
+};
+
+static struct platform_device_id armpmu_plat_device_ids[] = {
+	{.name = "arm-pmu"},
+	{},
+};
+
+static int __devinit armpmu_device_probe(struct platform_device *pdev)
+{
+	if (!cpu_pmu)
+		return -ENODEV;
+
+	cpu_pmu->plat_device = pdev;
+	return 0;
+}
+
+static struct platform_driver armpmu_driver = {
+	.driver		= {
+		.name	= "arm-pmu",
+		.of_match_table = armpmu_of_device_ids,
+	},
+	.probe		= armpmu_device_probe,
+	.id_table	= armpmu_plat_device_ids,
+};
+
+static int __init register_pmu_driver(void)
+{
+	return platform_driver_register(&armpmu_driver);
+}
+device_initcall(register_pmu_driver);
+
+static struct pmu_hw_events *armpmu_get_cpu_events(void)
+{
+	return &__get_cpu_var(cpu_hw_events);
+}
+
+static void __init cpu_pmu_init(struct arm_pmu *armpmu)
+{
+	int cpu;
+	for_each_possible_cpu(cpu) {
+		struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu);
+		events->events = per_cpu(hw_events, cpu);
+		events->used_mask = per_cpu(used_mask, cpu);
+		raw_spin_lock_init(&events->pmu_lock);
+	}
+	armpmu->get_hw_events = armpmu_get_cpu_events;
+	armpmu->type = ARM_PMU_DEVICE_CPU;
+}
 
+/*
+ * CPU PMU identification and registration.
+ */
 static int __init
 init_hw_perf_events(void)
 {
@@ -651,22 +696,22 @@
 		case 0xB360:	/* ARM1136 */
 		case 0xB560:	/* ARM1156 */
 		case 0xB760:	/* ARM1176 */
-			armpmu = armv6pmu_init();
+			cpu_pmu = armv6pmu_init();
 			break;
 		case 0xB020:	/* ARM11mpcore */
-			armpmu = armv6mpcore_pmu_init();
+			cpu_pmu = armv6mpcore_pmu_init();
 			break;
 		case 0xC080:	/* Cortex-A8 */
-			armpmu = armv7_a8_pmu_init();
+			cpu_pmu = armv7_a8_pmu_init();
 			break;
 		case 0xC090:	/* Cortex-A9 */
-			armpmu = armv7_a9_pmu_init();
+			cpu_pmu = armv7_a9_pmu_init();
 			break;
 		case 0xC050:	/* Cortex-A5 */
-			armpmu = armv7_a5_pmu_init();
+			cpu_pmu = armv7_a5_pmu_init();
 			break;
 		case 0xC0F0:	/* Cortex-A15 */
-			armpmu = armv7_a15_pmu_init();
+			cpu_pmu = armv7_a15_pmu_init();
 			break;
 		}
 	/* Intel CPUs [xscale]. */
@@ -674,23 +719,23 @@
 		part_number = (cpuid >> 13) & 0x7;
 		switch (part_number) {
 		case 1:
-			armpmu = xscale1pmu_init();
+			cpu_pmu = xscale1pmu_init();
 			break;
 		case 2:
-			armpmu = xscale2pmu_init();
+			cpu_pmu = xscale2pmu_init();
 			break;
 		}
 	}
 
-	if (armpmu) {
+	if (cpu_pmu) {
 		pr_info("enabled with %s PMU driver, %d counters available\n",
-			armpmu->name, armpmu->num_events);
+			cpu_pmu->name, cpu_pmu->num_events);
+		cpu_pmu_init(cpu_pmu);
+		armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW);
 	} else {
 		pr_info("no hardware support available\n");
 	}
 
-	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
-
 	return 0;
 }
 early_initcall(init_hw_perf_events);
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/perf_event_v6.c linux-libre-3.2-gnu/arch/arm/kernel/perf_event_v6.c
--- linux-libre-3.1-gnu/arch/arm/kernel/perf_event_v6.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/perf_event_v6.c	2012-01-04 18:55:44.000000000 -0500
@@ -54,7 +54,7 @@
 };
 
 enum armv6_counters {
-	ARMV6_CYCLE_COUNTER = 1,
+	ARMV6_CYCLE_COUNTER = 0,
 	ARMV6_COUNTER0,
 	ARMV6_COUNTER1,
 };
@@ -433,6 +433,7 @@
 		      int idx)
 {
 	unsigned long val, mask, evt, flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	if (ARMV6_CYCLE_COUNTER == idx) {
 		mask	= 0;
@@ -454,12 +455,29 @@
 	 * Mask out the current event and set the counter to count the event
 	 * that we're interested in.
 	 */
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = armv6_pmcr_read();
 	val &= ~mask;
 	val |= evt;
 	armv6_pmcr_write(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static int counter_is_active(unsigned long pmcr, int idx)
+{
+	unsigned long mask = 0;
+	if (idx == ARMV6_CYCLE_COUNTER)
+		mask = ARMV6_PMCR_CCOUNT_IEN;
+	else if (idx == ARMV6_COUNTER0)
+		mask = ARMV6_PMCR_COUNT0_IEN;
+	else if (idx == ARMV6_COUNTER1)
+		mask = ARMV6_PMCR_COUNT1_IEN;
+
+	if (mask)
+		return pmcr & mask;
+
+	WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+	return 0;
 }
 
 static irqreturn_t
@@ -468,7 +486,7 @@
 {
 	unsigned long pmcr = armv6_pmcr_read();
 	struct perf_sample_data data;
-	struct cpu_hw_events *cpuc;
+	struct pmu_hw_events *cpuc;
 	struct pt_regs *regs;
 	int idx;
 
@@ -487,11 +505,11 @@
 	perf_sample_data_init(&data, 0);
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
-	for (idx = 0; idx <= armpmu->num_events; ++idx) {
+	for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
 		struct perf_event *event = cpuc->events[idx];
 		struct hw_perf_event *hwc;
 
-		if (!test_bit(idx, cpuc->active_mask))
+		if (!counter_is_active(pmcr, idx))
 			continue;
 
 		/*
@@ -508,7 +526,7 @@
 			continue;
 
 		if (perf_event_overflow(event, &data, regs))
-			armpmu->disable(hwc, idx);
+			cpu_pmu->disable(hwc, idx);
 	}
 
 	/*
@@ -527,28 +545,30 @@
 armv6pmu_start(void)
 {
 	unsigned long flags, val;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = armv6_pmcr_read();
 	val |= ARMV6_PMCR_ENABLE;
 	armv6_pmcr_write(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
 armv6pmu_stop(void)
 {
 	unsigned long flags, val;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = armv6_pmcr_read();
 	val &= ~ARMV6_PMCR_ENABLE;
 	armv6_pmcr_write(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static int
-armv6pmu_get_event_idx(struct cpu_hw_events *cpuc,
+armv6pmu_get_event_idx(struct pmu_hw_events *cpuc,
 		       struct hw_perf_event *event)
 {
 	/* Always place a cycle counter into the cycle counter. */
@@ -578,6 +598,7 @@
 		       int idx)
 {
 	unsigned long val, mask, evt, flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	if (ARMV6_CYCLE_COUNTER == idx) {
 		mask	= ARMV6_PMCR_CCOUNT_IEN;
@@ -598,12 +619,12 @@
 	 * of ETM bus signal assertion cycles. The external reporting should
 	 * be disabled and so this should never increment.
 	 */
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = armv6_pmcr_read();
 	val &= ~mask;
 	val |= evt;
 	armv6_pmcr_write(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
@@ -611,6 +632,7 @@
 			      int idx)
 {
 	unsigned long val, mask, flags, evt = 0;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	if (ARMV6_CYCLE_COUNTER == idx) {
 		mask	= ARMV6_PMCR_CCOUNT_IEN;
@@ -627,15 +649,21 @@
 	 * Unlike UP ARMv6, we don't have a way of stopping the counters. We
 	 * simply disable the interrupt reporting.
 	 */
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = armv6_pmcr_read();
 	val &= ~mask;
 	val |= evt;
 	armv6_pmcr_write(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static const struct arm_pmu armv6pmu = {
+static int armv6_map_event(struct perf_event *event)
+{
+	return map_cpu_event(event, &armv6_perf_map,
+				&armv6_perf_cache_map, 0xFF);
+}
+
+static struct arm_pmu armv6pmu = {
 	.id			= ARM_PERF_PMU_ID_V6,
 	.name			= "v6",
 	.handle_irq		= armv6pmu_handle_irq,
@@ -646,14 +674,12 @@
 	.get_event_idx		= armv6pmu_get_event_idx,
 	.start			= armv6pmu_start,
 	.stop			= armv6pmu_stop,
-	.cache_map		= &armv6_perf_cache_map,
-	.event_map		= &armv6_perf_map,
-	.raw_event_mask		= 0xFF,
+	.map_event		= armv6_map_event,
 	.num_events		= 3,
 	.max_period		= (1LLU << 32) - 1,
 };
 
-static const struct arm_pmu *__init armv6pmu_init(void)
+static struct arm_pmu *__init armv6pmu_init(void)
 {
 	return &armv6pmu;
 }
@@ -665,7 +691,14 @@
  * disable the interrupt reporting and update the event. When unthrottling we
  * reset the period and enable the interrupt reporting.
  */
-static const struct arm_pmu armv6mpcore_pmu = {
+
+static int armv6mpcore_map_event(struct perf_event *event)
+{
+	return map_cpu_event(event, &armv6mpcore_perf_map,
+				&armv6mpcore_perf_cache_map, 0xFF);
+}
+
+static struct arm_pmu armv6mpcore_pmu = {
 	.id			= ARM_PERF_PMU_ID_V6MP,
 	.name			= "v6mpcore",
 	.handle_irq		= armv6pmu_handle_irq,
@@ -676,24 +709,22 @@
 	.get_event_idx		= armv6pmu_get_event_idx,
 	.start			= armv6pmu_start,
 	.stop			= armv6pmu_stop,
-	.cache_map		= &armv6mpcore_perf_cache_map,
-	.event_map		= &armv6mpcore_perf_map,
-	.raw_event_mask		= 0xFF,
+	.map_event		= armv6mpcore_map_event,
 	.num_events		= 3,
 	.max_period		= (1LLU << 32) - 1,
 };
 
-static const struct arm_pmu *__init armv6mpcore_pmu_init(void)
+static struct arm_pmu *__init armv6mpcore_pmu_init(void)
 {
 	return &armv6mpcore_pmu;
 }
 #else
-static const struct arm_pmu *__init armv6pmu_init(void)
+static struct arm_pmu *__init armv6pmu_init(void)
 {
 	return NULL;
 }
 
-static const struct arm_pmu *__init armv6mpcore_pmu_init(void)
+static struct arm_pmu *__init armv6mpcore_pmu_init(void)
 {
 	return NULL;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/perf_event_v7.c linux-libre-3.2-gnu/arch/arm/kernel/perf_event_v7.c
--- linux-libre-3.1-gnu/arch/arm/kernel/perf_event_v7.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/perf_event_v7.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,9 @@
  */
 
 #ifdef CONFIG_CPU_V7
+
+static struct arm_pmu armv7pmu;
+
 /*
  * Common ARMv7 event types
  *
@@ -676,23 +679,24 @@
 };
 
 /*
- * Perf Events counters
+ * Perf Events' indices
  */
-enum armv7_counters {
-	ARMV7_CYCLE_COUNTER		= 1,	/* Cycle counter */
-	ARMV7_COUNTER0			= 2,	/* First event counter */
-};
+#define	ARMV7_IDX_CYCLE_COUNTER	0
+#define	ARMV7_IDX_COUNTER0	1
+#define	ARMV7_IDX_COUNTER_LAST	(ARMV7_IDX_CYCLE_COUNTER + cpu_pmu->num_events - 1)
+
+#define	ARMV7_MAX_COUNTERS	32
+#define	ARMV7_COUNTER_MASK	(ARMV7_MAX_COUNTERS - 1)
 
 /*
- * The cycle counter is ARMV7_CYCLE_COUNTER.
- * The first event counter is ARMV7_COUNTER0.
- * The last event counter is (ARMV7_COUNTER0 + armpmu->num_events - 1).
+ * ARMv7 low level PMNC access
  */
-#define	ARMV7_COUNTER_LAST	(ARMV7_COUNTER0 + armpmu->num_events - 1)
 
 /*
- * ARMv7 low level PMNC access
+ * Perf Event to low level counters mapping
  */
+#define	ARMV7_IDX_TO_COUNTER(x)	\
+	(((x) - ARMV7_IDX_COUNTER0) & ARMV7_COUNTER_MASK)
 
 /*
  * Per-CPU PMNC: config reg
@@ -708,103 +712,76 @@
 #define	ARMV7_PMNC_MASK		0x3f	 /* Mask for writable bits */
 
 /*
- * Available counters
- */
-#define ARMV7_CNT0		0	/* First event counter */
-#define ARMV7_CCNT		31	/* Cycle counter */
-
-/* Perf Event to low level counters mapping */
-#define ARMV7_EVENT_CNT_TO_CNTx	(ARMV7_COUNTER0 - ARMV7_CNT0)
-
-/*
- * CNTENS: counters enable reg
- */
-#define ARMV7_CNTENS_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_CNTENS_C		(1 << ARMV7_CCNT)
-
-/*
- * CNTENC: counters disable reg
- */
-#define ARMV7_CNTENC_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_CNTENC_C		(1 << ARMV7_CCNT)
-
-/*
- * INTENS: counters overflow interrupt enable reg
- */
-#define ARMV7_INTENS_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_INTENS_C		(1 << ARMV7_CCNT)
-
-/*
- * INTENC: counters overflow interrupt disable reg
- */
-#define ARMV7_INTENC_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_INTENC_C		(1 << ARMV7_CCNT)
-
-/*
- * EVTSEL: Event selection reg
+ * FLAG: counters overflow flag status reg
  */
-#define	ARMV7_EVTSEL_MASK	0xff		/* Mask for writable bits */
+#define	ARMV7_FLAG_MASK		0xffffffff	/* Mask for writable bits */
+#define	ARMV7_OVERFLOWED_MASK	ARMV7_FLAG_MASK
 
 /*
- * SELECT: Counter selection reg
+ * PMXEVTYPER: Event selection reg
  */
-#define	ARMV7_SELECT_MASK	0x1f		/* Mask for writable bits */
+#define	ARMV7_EVTYPE_MASK	0xc00000ff	/* Mask for writable bits */
+#define	ARMV7_EVTYPE_EVENT	0xff		/* Mask for EVENT bits */
 
 /*
- * FLAG: counters overflow flag status reg
+ * Event filters for PMUv2
  */
-#define ARMV7_FLAG_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_FLAG_C		(1 << ARMV7_CCNT)
-#define	ARMV7_FLAG_MASK		0xffffffff	/* Mask for writable bits */
-#define	ARMV7_OVERFLOWED_MASK	ARMV7_FLAG_MASK
+#define	ARMV7_EXCLUDE_PL1	(1 << 31)
+#define	ARMV7_EXCLUDE_USER	(1 << 30)
+#define	ARMV7_INCLUDE_HYP	(1 << 27)
 
-static inline unsigned long armv7_pmnc_read(void)
+static inline u32 armv7_pmnc_read(void)
 {
 	u32 val;
 	asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(val));
 	return val;
 }
 
-static inline void armv7_pmnc_write(unsigned long val)
+static inline void armv7_pmnc_write(u32 val)
 {
 	val &= ARMV7_PMNC_MASK;
 	isb();
 	asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val));
 }
 
-static inline int armv7_pmnc_has_overflowed(unsigned long pmnc)
+static inline int armv7_pmnc_has_overflowed(u32 pmnc)
 {
 	return pmnc & ARMV7_OVERFLOWED_MASK;
 }
 
-static inline int armv7_pmnc_counter_has_overflowed(unsigned long pmnc,
-					enum armv7_counters counter)
+static inline int armv7_pmnc_counter_valid(int idx)
+{
+	return idx >= ARMV7_IDX_CYCLE_COUNTER && idx <= ARMV7_IDX_COUNTER_LAST;
+}
+
+static inline int armv7_pmnc_counter_has_overflowed(u32 pmnc, int idx)
 {
 	int ret = 0;
+	u32 counter;
 
-	if (counter == ARMV7_CYCLE_COUNTER)
-		ret = pmnc & ARMV7_FLAG_C;
-	else if ((counter >= ARMV7_COUNTER0) && (counter <= ARMV7_COUNTER_LAST))
-		ret = pmnc & ARMV7_FLAG_P(counter);
-	else
+	if (!armv7_pmnc_counter_valid(idx)) {
 		pr_err("CPU%u checking wrong counter %d overflow status\n",
-			smp_processor_id(), counter);
+			smp_processor_id(), idx);
+	} else {
+		counter = ARMV7_IDX_TO_COUNTER(idx);
+		ret = pmnc & BIT(counter);
+	}
 
 	return ret;
 }
 
-static inline int armv7_pmnc_select_counter(unsigned int idx)
+static inline int armv7_pmnc_select_counter(int idx)
 {
-	u32 val;
+	u32 counter;
 
-	if ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST)) {
-		pr_err("CPU%u selecting wrong PMNC counter"
-			" %d\n", smp_processor_id(), idx);
-		return -1;
+	if (!armv7_pmnc_counter_valid(idx)) {
+		pr_err("CPU%u selecting wrong PMNC counter %d\n",
+			smp_processor_id(), idx);
+		return -EINVAL;
 	}
 
-	val = (idx - ARMV7_EVENT_CNT_TO_CNTx) & ARMV7_SELECT_MASK;
-	asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
+	counter = ARMV7_IDX_TO_COUNTER(idx);
+	asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (counter));
 	isb();
 
 	return idx;
@@ -812,124 +789,95 @@
 
 static inline u32 armv7pmu_read_counter(int idx)
 {
-	unsigned long value = 0;
+	u32 value = 0;
 
-	if (idx == ARMV7_CYCLE_COUNTER)
-		asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value));
-	else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
-		if (armv7_pmnc_select_counter(idx) == idx)
-			asm volatile("mrc p15, 0, %0, c9, c13, 2"
-				     : "=r" (value));
-	} else
+	if (!armv7_pmnc_counter_valid(idx))
 		pr_err("CPU%u reading wrong counter %d\n",
 			smp_processor_id(), idx);
+	else if (idx == ARMV7_IDX_CYCLE_COUNTER)
+		asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value));
+	else if (armv7_pmnc_select_counter(idx) == idx)
+		asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (value));
 
 	return value;
 }
 
 static inline void armv7pmu_write_counter(int idx, u32 value)
 {
-	if (idx == ARMV7_CYCLE_COUNTER)
-		asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
-	else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
-		if (armv7_pmnc_select_counter(idx) == idx)
-			asm volatile("mcr p15, 0, %0, c9, c13, 2"
-				     : : "r" (value));
-	} else
+	if (!armv7_pmnc_counter_valid(idx))
 		pr_err("CPU%u writing wrong counter %d\n",
 			smp_processor_id(), idx);
+	else if (idx == ARMV7_IDX_CYCLE_COUNTER)
+		asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
+	else if (armv7_pmnc_select_counter(idx) == idx)
+		asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (value));
 }
 
-static inline void armv7_pmnc_write_evtsel(unsigned int idx, u32 val)
+static inline void armv7_pmnc_write_evtsel(int idx, u32 val)
 {
 	if (armv7_pmnc_select_counter(idx) == idx) {
-		val &= ARMV7_EVTSEL_MASK;
+		val &= ARMV7_EVTYPE_MASK;
 		asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
 	}
 }
 
-static inline u32 armv7_pmnc_enable_counter(unsigned int idx)
+static inline int armv7_pmnc_enable_counter(int idx)
 {
-	u32 val;
+	u32 counter;
 
-	if ((idx != ARMV7_CYCLE_COUNTER) &&
-	    ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
-		pr_err("CPU%u enabling wrong PMNC counter"
-			" %d\n", smp_processor_id(), idx);
-		return -1;
+	if (!armv7_pmnc_counter_valid(idx)) {
+		pr_err("CPU%u enabling wrong PMNC counter %d\n",
+			smp_processor_id(), idx);
+		return -EINVAL;
 	}
 
-	if (idx == ARMV7_CYCLE_COUNTER)
-		val = ARMV7_CNTENS_C;
-	else
-		val = ARMV7_CNTENS_P(idx);
-
-	asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val));
-
+	counter = ARMV7_IDX_TO_COUNTER(idx);
+	asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (BIT(counter)));
 	return idx;
 }
 
-static inline u32 armv7_pmnc_disable_counter(unsigned int idx)
+static inline int armv7_pmnc_disable_counter(int idx)
 {
-	u32 val;
-
+	u32 counter;
 
-	if ((idx != ARMV7_CYCLE_COUNTER) &&
-	    ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
-		pr_err("CPU%u disabling wrong PMNC counter"
-			" %d\n", smp_processor_id(), idx);
-		return -1;
+	if (!armv7_pmnc_counter_valid(idx)) {
+		pr_err("CPU%u disabling wrong PMNC counter %d\n",
+			smp_processor_id(), idx);
+		return -EINVAL;
 	}
 
-	if (idx == ARMV7_CYCLE_COUNTER)
-		val = ARMV7_CNTENC_C;
-	else
-		val = ARMV7_CNTENC_P(idx);
-
-	asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val));
-
+	counter = ARMV7_IDX_TO_COUNTER(idx);
+	asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (BIT(counter)));
 	return idx;
 }
 
-static inline u32 armv7_pmnc_enable_intens(unsigned int idx)
+static inline int armv7_pmnc_enable_intens(int idx)
 {
-	u32 val;
+	u32 counter;
 
-	if ((idx != ARMV7_CYCLE_COUNTER) &&
-	    ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
-		pr_err("CPU%u enabling wrong PMNC counter"
-			" interrupt enable %d\n", smp_processor_id(), idx);
-		return -1;
+	if (!armv7_pmnc_counter_valid(idx)) {
+		pr_err("CPU%u enabling wrong PMNC counter IRQ enable %d\n",
+			smp_processor_id(), idx);
+		return -EINVAL;
 	}
 
-	if (idx == ARMV7_CYCLE_COUNTER)
-		val = ARMV7_INTENS_C;
-	else
-		val = ARMV7_INTENS_P(idx);
-
-	asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val));
-
+	counter = ARMV7_IDX_TO_COUNTER(idx);
+	asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (BIT(counter)));
 	return idx;
 }
 
-static inline u32 armv7_pmnc_disable_intens(unsigned int idx)
+static inline int armv7_pmnc_disable_intens(int idx)
 {
-	u32 val;
+	u32 counter;
 
-	if ((idx != ARMV7_CYCLE_COUNTER) &&
-	    ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
-		pr_err("CPU%u disabling wrong PMNC counter"
-			" interrupt enable %d\n", smp_processor_id(), idx);
-		return -1;
+	if (!armv7_pmnc_counter_valid(idx)) {
+		pr_err("CPU%u disabling wrong PMNC counter IRQ enable %d\n",
+			smp_processor_id(), idx);
+		return -EINVAL;
 	}
 
-	if (idx == ARMV7_CYCLE_COUNTER)
-		val = ARMV7_INTENC_C;
-	else
-		val = ARMV7_INTENC_P(idx);
-
-	asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (val));
-
+	counter = ARMV7_IDX_TO_COUNTER(idx);
+	asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (BIT(counter)));
 	return idx;
 }
 
@@ -973,14 +921,14 @@
 	asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
 	printk(KERN_INFO "CCNT  =0x%08x\n", val);
 
-	for (cnt = ARMV7_COUNTER0; cnt < ARMV7_COUNTER_LAST; cnt++) {
+	for (cnt = ARMV7_IDX_COUNTER0; cnt <= ARMV7_IDX_COUNTER_LAST; cnt++) {
 		armv7_pmnc_select_counter(cnt);
 		asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
 		printk(KERN_INFO "CNT[%d] count =0x%08x\n",
-			cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
+			ARMV7_IDX_TO_COUNTER(cnt), val);
 		asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val));
 		printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n",
-			cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
+			ARMV7_IDX_TO_COUNTER(cnt), val);
 	}
 }
 #endif
@@ -988,12 +936,13 @@
 static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
 {
 	unsigned long flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	/*
 	 * Enable counter and interrupt, and set the counter to count
 	 * the event that we're interested in.
 	 */
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 
 	/*
 	 * Disable counter
@@ -1002,9 +951,10 @@
 
 	/*
 	 * Set event (if destined for PMNx counters)
-	 * We don't need to set the event if it's a cycle count
+	 * We only need to set the event for the cycle counter if we
+	 * have the ability to perform event filtering.
 	 */
-	if (idx != ARMV7_CYCLE_COUNTER)
+	if (armv7pmu.set_event_filter || idx != ARMV7_IDX_CYCLE_COUNTER)
 		armv7_pmnc_write_evtsel(idx, hwc->config_base);
 
 	/*
@@ -1017,17 +967,18 @@
 	 */
 	armv7_pmnc_enable_counter(idx);
 
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx)
 {
 	unsigned long flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	/*
 	 * Disable counter and interrupt
 	 */
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 
 	/*
 	 * Disable counter
@@ -1039,14 +990,14 @@
 	 */
 	armv7_pmnc_disable_intens(idx);
 
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
 {
-	unsigned long pmnc;
+	u32 pmnc;
 	struct perf_sample_data data;
-	struct cpu_hw_events *cpuc;
+	struct pmu_hw_events *cpuc;
 	struct pt_regs *regs;
 	int idx;
 
@@ -1069,13 +1020,10 @@
 	perf_sample_data_init(&data, 0);
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
-	for (idx = 0; idx <= armpmu->num_events; ++idx) {
+	for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
 		struct perf_event *event = cpuc->events[idx];
 		struct hw_perf_event *hwc;
 
-		if (!test_bit(idx, cpuc->active_mask))
-			continue;
-
 		/*
 		 * We have a single interrupt for all counters. Check that
 		 * each counter has overflowed before we process it.
@@ -1090,7 +1038,7 @@
 			continue;
 
 		if (perf_event_overflow(event, &data, regs))
-			armpmu->disable(hwc, idx);
+			cpu_pmu->disable(hwc, idx);
 	}
 
 	/*
@@ -1108,61 +1056,114 @@
 static void armv7pmu_start(void)
 {
 	unsigned long flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	/* Enable all counters */
 	armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void armv7pmu_stop(void)
 {
 	unsigned long flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	/* Disable all counters */
 	armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc,
+static int armv7pmu_get_event_idx(struct pmu_hw_events *cpuc,
 				  struct hw_perf_event *event)
 {
 	int idx;
+	unsigned long evtype = event->config_base & ARMV7_EVTYPE_EVENT;
 
 	/* Always place a cycle counter into the cycle counter. */
-	if (event->config_base == ARMV7_PERFCTR_CPU_CYCLES) {
-		if (test_and_set_bit(ARMV7_CYCLE_COUNTER, cpuc->used_mask))
+	if (evtype == ARMV7_PERFCTR_CPU_CYCLES) {
+		if (test_and_set_bit(ARMV7_IDX_CYCLE_COUNTER, cpuc->used_mask))
 			return -EAGAIN;
 
-		return ARMV7_CYCLE_COUNTER;
-	} else {
-		/*
-		 * For anything other than a cycle counter, try and use
-		 * the events counters
-		 */
-		for (idx = ARMV7_COUNTER0; idx <= armpmu->num_events; ++idx) {
-			if (!test_and_set_bit(idx, cpuc->used_mask))
-				return idx;
-		}
+		return ARMV7_IDX_CYCLE_COUNTER;
+	}
 
-		/* The counters are all in use. */
-		return -EAGAIN;
+	/*
+	 * For anything other than a cycle counter, try and use
+	 * the events counters
+	 */
+	for (idx = ARMV7_IDX_COUNTER0; idx < cpu_pmu->num_events; ++idx) {
+		if (!test_and_set_bit(idx, cpuc->used_mask))
+			return idx;
 	}
+
+	/* The counters are all in use. */
+	return -EAGAIN;
+}
+
+/*
+ * Add an event filter to a given event. This will only work for PMUv2 PMUs.
+ */
+static int armv7pmu_set_event_filter(struct hw_perf_event *event,
+				     struct perf_event_attr *attr)
+{
+	unsigned long config_base = 0;
+
+	if (attr->exclude_idle)
+		return -EPERM;
+	if (attr->exclude_user)
+		config_base |= ARMV7_EXCLUDE_USER;
+	if (attr->exclude_kernel)
+		config_base |= ARMV7_EXCLUDE_PL1;
+	if (!attr->exclude_hv)
+		config_base |= ARMV7_INCLUDE_HYP;
+
+	/*
+	 * Install the filter into config_base as this is used to
+	 * construct the event type.
+	 */
+	event->config_base = config_base;
+
+	return 0;
 }
 
 static void armv7pmu_reset(void *info)
 {
-	u32 idx, nb_cnt = armpmu->num_events;
+	u32 idx, nb_cnt = cpu_pmu->num_events;
 
 	/* The counter and interrupt enable registers are unknown at reset. */
-	for (idx = 1; idx < nb_cnt; ++idx)
+	for (idx = ARMV7_IDX_CYCLE_COUNTER; 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 int armv7_a8_map_event(struct perf_event *event)
+{
+	return map_cpu_event(event, &armv7_a8_perf_map,
+				&armv7_a8_perf_cache_map, 0xFF);
+}
+
+static int armv7_a9_map_event(struct perf_event *event)
+{
+	return map_cpu_event(event, &armv7_a9_perf_map,
+				&armv7_a9_perf_cache_map, 0xFF);
+}
+
+static int armv7_a5_map_event(struct perf_event *event)
+{
+	return map_cpu_event(event, &armv7_a5_perf_map,
+				&armv7_a5_perf_cache_map, 0xFF);
+}
+
+static int armv7_a15_map_event(struct perf_event *event)
+{
+	return map_cpu_event(event, &armv7_a15_perf_map,
+				&armv7_a15_perf_cache_map, 0xFF);
+}
+
 static struct arm_pmu armv7pmu = {
 	.handle_irq		= armv7pmu_handle_irq,
 	.enable			= armv7pmu_enable_event,
@@ -1173,7 +1174,6 @@
 	.start			= armv7pmu_start,
 	.stop			= armv7pmu_stop,
 	.reset			= armv7pmu_reset,
-	.raw_event_mask		= 0xFF,
 	.max_period		= (1LLU << 32) - 1,
 };
 
@@ -1188,62 +1188,59 @@
 	return nb_cnt + 1;
 }
 
-static const struct arm_pmu *__init armv7_a8_pmu_init(void)
+static struct arm_pmu *__init armv7_a8_pmu_init(void)
 {
 	armv7pmu.id		= ARM_PERF_PMU_ID_CA8;
 	armv7pmu.name		= "ARMv7 Cortex-A8";
-	armv7pmu.cache_map	= &armv7_a8_perf_cache_map;
-	armv7pmu.event_map	= &armv7_a8_perf_map;
+	armv7pmu.map_event	= armv7_a8_map_event;
 	armv7pmu.num_events	= armv7_read_num_pmnc_events();
 	return &armv7pmu;
 }
 
-static const struct arm_pmu *__init armv7_a9_pmu_init(void)
+static struct arm_pmu *__init armv7_a9_pmu_init(void)
 {
 	armv7pmu.id		= ARM_PERF_PMU_ID_CA9;
 	armv7pmu.name		= "ARMv7 Cortex-A9";
-	armv7pmu.cache_map	= &armv7_a9_perf_cache_map;
-	armv7pmu.event_map	= &armv7_a9_perf_map;
+	armv7pmu.map_event	= armv7_a9_map_event;
 	armv7pmu.num_events	= armv7_read_num_pmnc_events();
 	return &armv7pmu;
 }
 
-static const struct arm_pmu *__init armv7_a5_pmu_init(void)
+static struct arm_pmu *__init armv7_a5_pmu_init(void)
 {
 	armv7pmu.id		= ARM_PERF_PMU_ID_CA5;
 	armv7pmu.name		= "ARMv7 Cortex-A5";
-	armv7pmu.cache_map	= &armv7_a5_perf_cache_map;
-	armv7pmu.event_map	= &armv7_a5_perf_map;
+	armv7pmu.map_event	= armv7_a5_map_event;
 	armv7pmu.num_events	= armv7_read_num_pmnc_events();
 	return &armv7pmu;
 }
 
-static const struct arm_pmu *__init armv7_a15_pmu_init(void)
+static struct arm_pmu *__init armv7_a15_pmu_init(void)
 {
 	armv7pmu.id		= ARM_PERF_PMU_ID_CA15;
 	armv7pmu.name		= "ARMv7 Cortex-A15";
-	armv7pmu.cache_map	= &armv7_a15_perf_cache_map;
-	armv7pmu.event_map	= &armv7_a15_perf_map;
+	armv7pmu.map_event	= armv7_a15_map_event;
 	armv7pmu.num_events	= armv7_read_num_pmnc_events();
+	armv7pmu.set_event_filter = armv7pmu_set_event_filter;
 	return &armv7pmu;
 }
 #else
-static const struct arm_pmu *__init armv7_a8_pmu_init(void)
+static struct arm_pmu *__init armv7_a8_pmu_init(void)
 {
 	return NULL;
 }
 
-static const struct arm_pmu *__init armv7_a9_pmu_init(void)
+static struct arm_pmu *__init armv7_a9_pmu_init(void)
 {
 	return NULL;
 }
 
-static const struct arm_pmu *__init armv7_a5_pmu_init(void)
+static struct arm_pmu *__init armv7_a5_pmu_init(void)
 {
 	return NULL;
 }
 
-static const struct arm_pmu *__init armv7_a15_pmu_init(void)
+static struct arm_pmu *__init armv7_a15_pmu_init(void)
 {
 	return NULL;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/perf_event_xscale.c linux-libre-3.2-gnu/arch/arm/kernel/perf_event_xscale.c
--- linux-libre-3.1-gnu/arch/arm/kernel/perf_event_xscale.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/perf_event_xscale.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,7 +40,7 @@
 };
 
 enum xscale_counters {
-	XSCALE_CYCLE_COUNTER	= 1,
+	XSCALE_CYCLE_COUNTER	= 0,
 	XSCALE_COUNTER0,
 	XSCALE_COUNTER1,
 	XSCALE_COUNTER2,
@@ -222,7 +222,7 @@
 {
 	unsigned long pmnc;
 	struct perf_sample_data data;
-	struct cpu_hw_events *cpuc;
+	struct pmu_hw_events *cpuc;
 	struct pt_regs *regs;
 	int idx;
 
@@ -249,13 +249,10 @@
 	perf_sample_data_init(&data, 0);
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
-	for (idx = 0; idx <= armpmu->num_events; ++idx) {
+	for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
 		struct perf_event *event = cpuc->events[idx];
 		struct hw_perf_event *hwc;
 
-		if (!test_bit(idx, cpuc->active_mask))
-			continue;
-
 		if (!xscale1_pmnc_counter_has_overflowed(pmnc, idx))
 			continue;
 
@@ -266,7 +263,7 @@
 			continue;
 
 		if (perf_event_overflow(event, &data, regs))
-			armpmu->disable(hwc, idx);
+			cpu_pmu->disable(hwc, idx);
 	}
 
 	irq_work_run();
@@ -284,6 +281,7 @@
 xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx)
 {
 	unsigned long val, mask, evt, flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	switch (idx) {
 	case XSCALE_CYCLE_COUNTER:
@@ -305,18 +303,19 @@
 		return;
 	}
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = xscale1pmu_read_pmnc();
 	val &= ~mask;
 	val |= evt;
 	xscale1pmu_write_pmnc(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
 xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx)
 {
 	unsigned long val, mask, evt, flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	switch (idx) {
 	case XSCALE_CYCLE_COUNTER:
@@ -336,16 +335,16 @@
 		return;
 	}
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = xscale1pmu_read_pmnc();
 	val &= ~mask;
 	val |= evt;
 	xscale1pmu_write_pmnc(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static int
-xscale1pmu_get_event_idx(struct cpu_hw_events *cpuc,
+xscale1pmu_get_event_idx(struct pmu_hw_events *cpuc,
 			struct hw_perf_event *event)
 {
 	if (XSCALE_PERFCTR_CCNT == event->config_base) {
@@ -368,24 +367,26 @@
 xscale1pmu_start(void)
 {
 	unsigned long flags, val;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = xscale1pmu_read_pmnc();
 	val |= XSCALE_PMU_ENABLE;
 	xscale1pmu_write_pmnc(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
 xscale1pmu_stop(void)
 {
 	unsigned long flags, val;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = xscale1pmu_read_pmnc();
 	val &= ~XSCALE_PMU_ENABLE;
 	xscale1pmu_write_pmnc(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static inline u32
@@ -424,7 +425,13 @@
 	}
 }
 
-static const struct arm_pmu xscale1pmu = {
+static int xscale_map_event(struct perf_event *event)
+{
+	return map_cpu_event(event, &xscale_perf_map,
+				&xscale_perf_cache_map, 0xFF);
+}
+
+static struct arm_pmu xscale1pmu = {
 	.id		= ARM_PERF_PMU_ID_XSCALE1,
 	.name		= "xscale1",
 	.handle_irq	= xscale1pmu_handle_irq,
@@ -435,14 +442,12 @@
 	.get_event_idx	= xscale1pmu_get_event_idx,
 	.start		= xscale1pmu_start,
 	.stop		= xscale1pmu_stop,
-	.cache_map	= &xscale_perf_cache_map,
-	.event_map	= &xscale_perf_map,
-	.raw_event_mask	= 0xFF,
+	.map_event	= xscale_map_event,
 	.num_events	= 3,
 	.max_period	= (1LLU << 32) - 1,
 };
 
-static const struct arm_pmu *__init xscale1pmu_init(void)
+static struct arm_pmu *__init xscale1pmu_init(void)
 {
 	return &xscale1pmu;
 }
@@ -560,7 +565,7 @@
 {
 	unsigned long pmnc, of_flags;
 	struct perf_sample_data data;
-	struct cpu_hw_events *cpuc;
+	struct pmu_hw_events *cpuc;
 	struct pt_regs *regs;
 	int idx;
 
@@ -581,13 +586,10 @@
 	perf_sample_data_init(&data, 0);
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
-	for (idx = 0; idx <= armpmu->num_events; ++idx) {
+	for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
 		struct perf_event *event = cpuc->events[idx];
 		struct hw_perf_event *hwc;
 
-		if (!test_bit(idx, cpuc->active_mask))
-			continue;
-
 		if (!xscale2_pmnc_counter_has_overflowed(pmnc, idx))
 			continue;
 
@@ -598,7 +600,7 @@
 			continue;
 
 		if (perf_event_overflow(event, &data, regs))
-			armpmu->disable(hwc, idx);
+			cpu_pmu->disable(hwc, idx);
 	}
 
 	irq_work_run();
@@ -616,6 +618,7 @@
 xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)
 {
 	unsigned long flags, ien, evtsel;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	ien = xscale2pmu_read_int_enable();
 	evtsel = xscale2pmu_read_event_select();
@@ -649,16 +652,17 @@
 		return;
 	}
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	xscale2pmu_write_event_select(evtsel);
 	xscale2pmu_write_int_enable(ien);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
 xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)
 {
 	unsigned long flags, ien, evtsel;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
 	ien = xscale2pmu_read_int_enable();
 	evtsel = xscale2pmu_read_event_select();
@@ -692,14 +696,14 @@
 		return;
 	}
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	xscale2pmu_write_event_select(evtsel);
 	xscale2pmu_write_int_enable(ien);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static int
-xscale2pmu_get_event_idx(struct cpu_hw_events *cpuc,
+xscale2pmu_get_event_idx(struct pmu_hw_events *cpuc,
 			struct hw_perf_event *event)
 {
 	int idx = xscale1pmu_get_event_idx(cpuc, event);
@@ -718,24 +722,26 @@
 xscale2pmu_start(void)
 {
 	unsigned long flags, val;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64;
 	val |= XSCALE_PMU_ENABLE;
 	xscale2pmu_write_pmnc(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static void
 xscale2pmu_stop(void)
 {
 	unsigned long flags, val;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
 
-	raw_spin_lock_irqsave(&pmu_lock, flags);
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
 	val = xscale2pmu_read_pmnc();
 	val &= ~XSCALE_PMU_ENABLE;
 	xscale2pmu_write_pmnc(val);
-	raw_spin_unlock_irqrestore(&pmu_lock, flags);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
 static inline u32
@@ -786,7 +792,7 @@
 	}
 }
 
-static const struct arm_pmu xscale2pmu = {
+static struct arm_pmu xscale2pmu = {
 	.id		= ARM_PERF_PMU_ID_XSCALE2,
 	.name		= "xscale2",
 	.handle_irq	= xscale2pmu_handle_irq,
@@ -797,24 +803,22 @@
 	.get_event_idx	= xscale2pmu_get_event_idx,
 	.start		= xscale2pmu_start,
 	.stop		= xscale2pmu_stop,
-	.cache_map	= &xscale_perf_cache_map,
-	.event_map	= &xscale_perf_map,
-	.raw_event_mask	= 0xFF,
+	.map_event	= xscale_map_event,
 	.num_events	= 5,
 	.max_period	= (1LLU << 32) - 1,
 };
 
-static const struct arm_pmu *__init xscale2pmu_init(void)
+static struct arm_pmu *__init xscale2pmu_init(void)
 {
 	return &xscale2pmu;
 }
 #else
-static const struct arm_pmu *__init xscale1pmu_init(void)
+static struct arm_pmu *__init xscale1pmu_init(void)
 {
 	return NULL;
 }
 
-static const struct arm_pmu *__init xscale2pmu_init(void)
+static struct arm_pmu *__init xscale2pmu_init(void)
 {
 	return NULL;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/pj4-cp0.c linux-libre-3.2-gnu/arch/arm/kernel/pj4-cp0.c
--- linux-libre-3.1-gnu/arch/arm/kernel/pj4-cp0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/pj4-cp0.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/pmu.c linux-libre-3.2-gnu/arch/arm/kernel/pmu.c
--- linux-libre-3.1-gnu/arch/arm/kernel/pmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/pmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,192 +10,27 @@
  *
  */
 
-#define pr_fmt(fmt) "PMU: " fmt
-
-#include <linux/cpumask.h>
 #include <linux/err.h>
-#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
 
 #include <asm/pmu.h>
 
-static volatile long pmu_lock;
-
-static struct platform_device *pmu_devices[ARM_NUM_PMU_DEVICES];
-
-static int __devinit pmu_register(struct platform_device *pdev,
-					enum arm_pmu_type type)
-{
-	if (type < 0 || type >= ARM_NUM_PMU_DEVICES) {
-		pr_warning("received registration request for unknown "
-				"PMU device type %d\n", type);
-		return -EINVAL;
-	}
-
-	if (pmu_devices[type]) {
-		pr_warning("rejecting duplicate registration of PMU device "
-			"type %d.", type);
-		return -ENOSPC;
-	}
-
-	pr_info("registered new PMU device of type %d\n", type);
-	pmu_devices[type] = pdev;
-	return 0;
-}
-
-#define OF_MATCH_PMU(_name, _type) {	\
-	.compatible = _name,		\
-	.data = (void *)_type,		\
-}
-
-#define OF_MATCH_CPU(name)	OF_MATCH_PMU(name, ARM_PMU_DEVICE_CPU)
-
-static struct of_device_id armpmu_of_device_ids[] = {
-	OF_MATCH_CPU("arm,cortex-a9-pmu"),
-	OF_MATCH_CPU("arm,cortex-a8-pmu"),
-	OF_MATCH_CPU("arm,arm1136-pmu"),
-	OF_MATCH_CPU("arm,arm1176-pmu"),
-	{},
-};
-
-#define PLAT_MATCH_PMU(_name, _type) {	\
-	.name		= _name,	\
-	.driver_data	= _type,	\
-}
-
-#define PLAT_MATCH_CPU(_name)	PLAT_MATCH_PMU(_name, ARM_PMU_DEVICE_CPU)
-
-static struct platform_device_id armpmu_plat_device_ids[] = {
-	PLAT_MATCH_CPU("arm-pmu"),
-	{},
-};
-
-enum arm_pmu_type armpmu_device_type(struct platform_device *pdev)
-{
-	const struct of_device_id	*of_id;
-	const struct platform_device_id *pdev_id;
-
-	/* provided by of_device_id table */
-	if (pdev->dev.of_node) {
-		of_id = of_match_device(armpmu_of_device_ids, &pdev->dev);
-		BUG_ON(!of_id);
-		return (enum arm_pmu_type)of_id->data;
-	}
-
-	/* Provided by platform_device_id table */
-	pdev_id = platform_get_device_id(pdev);
-	BUG_ON(!pdev_id);
-	return pdev_id->driver_data;
-}
-
-static int __devinit armpmu_device_probe(struct platform_device *pdev)
-{
-	return pmu_register(pdev, armpmu_device_type(pdev));
-}
-
-static struct platform_driver armpmu_driver = {
-	.driver		= {
-		.name	= "arm-pmu",
-		.of_match_table = armpmu_of_device_ids,
-	},
-	.probe		= armpmu_device_probe,
-	.id_table	= armpmu_plat_device_ids,
-};
-
-static int __init register_pmu_driver(void)
-{
-	return platform_driver_register(&armpmu_driver);
-}
-device_initcall(register_pmu_driver);
+/*
+ * PMU locking to ensure mutual exclusion between different subsystems.
+ */
+static unsigned long pmu_lock[BITS_TO_LONGS(ARM_NUM_PMU_DEVICES)];
 
-struct platform_device *
+int
 reserve_pmu(enum arm_pmu_type type)
 {
-	struct platform_device *pdev;
-
-	if (test_and_set_bit_lock(type, &pmu_lock)) {
-		pdev = ERR_PTR(-EBUSY);
-	} else if (pmu_devices[type] == NULL) {
-		clear_bit_unlock(type, &pmu_lock);
-		pdev = ERR_PTR(-ENODEV);
-	} else {
-		pdev = pmu_devices[type];
-	}
-
-	return pdev;
+	return test_and_set_bit_lock(type, pmu_lock) ? -EBUSY : 0;
 }
 EXPORT_SYMBOL_GPL(reserve_pmu);
 
-int
+void
 release_pmu(enum arm_pmu_type type)
 {
-	if (WARN_ON(!pmu_devices[type]))
-		return -EINVAL;
-	clear_bit_unlock(type, &pmu_lock);
-	return 0;
+	clear_bit_unlock(type, pmu_lock);
 }
 EXPORT_SYMBOL_GPL(release_pmu);
-
-static int
-set_irq_affinity(int irq,
-		 unsigned int cpu)
-{
-#ifdef CONFIG_SMP
-	int err = irq_set_affinity(irq, cpumask_of(cpu));
-	if (err)
-		pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
-			   irq, cpu);
-	return err;
-#else
-	return -EINVAL;
-#endif
-}
-
-static int
-init_cpu_pmu(void)
-{
-	int i, irqs, err = 0;
-	struct platform_device *pdev = pmu_devices[ARM_PMU_DEVICE_CPU];
-
-	if (!pdev)
-		return -ENODEV;
-
-	irqs = pdev->num_resources;
-
-	/*
-	 * If we have a single PMU interrupt that we can't shift, assume that
-	 * we're running on a uniprocessor machine and continue.
-	 */
-	if (irqs == 1 && !irq_can_set_affinity(platform_get_irq(pdev, 0)))
-		return 0;
-
-	for (i = 0; i < irqs; ++i) {
-		err = set_irq_affinity(platform_get_irq(pdev, i), i);
-		if (err)
-			break;
-	}
-
-	return err;
-}
-
-int
-init_pmu(enum arm_pmu_type type)
-{
-	int err = 0;
-
-	switch (type) {
-	case ARM_PMU_DEVICE_CPU:
-		err = init_cpu_pmu();
-		break;
-	default:
-		pr_warning("attempt to initialise PMU of unknown "
-			   "type %d\n", type);
-		err = -EINVAL;
-	}
-
-	return err;
-}
-EXPORT_SYMBOL_GPL(init_pmu);
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/process.c linux-libre-3.2-gnu/arch/arm/kernel/process.c
--- linux-libre-3.1-gnu/arch/arm/kernel/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  */
 #include <stdarg.h>
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -192,6 +192,9 @@
 #endif
 
 			local_irq_disable();
+#ifdef CONFIG_PL310_ERRATA_769419
+			wmb();
+#endif
 			if (hlt_counter) {
 				local_irq_enable();
 				cpu_relax();
@@ -319,7 +322,7 @@
 	printk("\n");
 	printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm);
 	__show_regs(regs);
-	__backtrace();
+	dump_stack();
 }
 
 ATOMIC_NOTIFIER_HEAD(thread_notify_head);
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/ptrace.c linux-libre-3.2-gnu/arch/arm/kernel/ptrace.c
--- linux-libre-3.1-gnu/arch/arm/kernel/ptrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/ptrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/elf.h>
 #include <linux/smp.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/return_address.c linux-libre-3.2-gnu/arch/arm/kernel/return_address.c
--- linux-libre-3.1-gnu/arch/arm/kernel/return_address.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/return_address.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  * under the terms of the GNU General Public License version 2 as published by
  * the Free Software Foundation.
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/ftrace.h>
 
 #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/setup.c linux-libre-3.2-gnu/arch/arm/kernel/setup.c
--- linux-libre-3.1-gnu/arch/arm/kernel/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * 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/export.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
 #include <linux/ioport.h>
@@ -29,6 +29,8 @@
 #include <linux/fs.h>
 #include <linux/proc_fs.h>
 #include <linux/memblock.h>
+#include <linux/bug.h>
+#include <linux/compiler.h>
 
 #include <asm/unified.h>
 #include <asm/cpu.h>
@@ -42,6 +44,7 @@
 #include <asm/cacheflush.h>
 #include <asm/cachetype.h>
 #include <asm/tlbflush.h>
+#include <asm/system.h>
 
 #include <asm/prom.h>
 #include <asm/mach/arch.h>
@@ -115,6 +118,13 @@
 EXPORT_SYMBOL(outer_cache);
 #endif
 
+/*
+ * Cached cpu_architecture() result for use by assembler code.
+ * C code should use the cpu_architecture() function instead of accessing this
+ * variable directly.
+ */
+int __cpu_architecture __read_mostly = CPU_ARCH_UNKNOWN;
+
 struct stack {
 	u32 irq[3];
 	u32 abt[3];
@@ -210,7 +220,7 @@
 	"?(17)",
 };
 
-int cpu_architecture(void)
+static int __get_cpu_architecture(void)
 {
 	int cpu_arch;
 
@@ -243,11 +253,22 @@
 	return cpu_arch;
 }
 
+int __pure cpu_architecture(void)
+{
+	BUG_ON(__cpu_architecture == CPU_ARCH_UNKNOWN);
+
+	return __cpu_architecture;
+}
+
 static int cpu_has_aliasing_icache(unsigned int arch)
 {
 	int aliasing_icache;
 	unsigned int id_reg, num_sets, line_size;
 
+	/* PIPT caches never alias. */
+	if (icache_is_pipt())
+		return 0;
+
 	/* arch specifies the register format */
 	switch (arch) {
 	case CPU_ARCH_ARMv7:
@@ -282,8 +303,14 @@
 			/* ARMv7 register format */
 			arch = CPU_ARCH_ARMv7;
 			cacheid = CACHEID_VIPT_NONALIASING;
-			if ((cachetype & (3 << 14)) == 1 << 14)
+			switch (cachetype & (3 << 14)) {
+			case (1 << 14):
 				cacheid |= CACHEID_ASID_TAGGED;
+				break;
+			case (3 << 14):
+				cacheid |= CACHEID_PIPT;
+				break;
+			}
 		} else {
 			arch = CPU_ARCH_ARMv6;
 			if (cachetype & (1 << 23))
@@ -300,10 +327,11 @@
 	printk("CPU: %s data cache, %s instruction cache\n",
 		cache_is_vivt() ? "VIVT" :
 		cache_is_vipt_aliasing() ? "VIPT aliasing" :
-		cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
+		cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown",
 		cache_is_vivt() ? "VIVT" :
 		icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
 		icache_is_vipt_aliasing() ? "VIPT aliasing" :
+		icache_is_pipt() ? "PIPT" :
 		cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
 }
 
@@ -414,6 +442,7 @@
 	}
 
 	cpu_name = list->cpu_name;
+	__cpu_architecture = __get_cpu_architecture();
 
 #ifdef MULTI_CPU
 	processor = *list->proc;
@@ -432,8 +461,10 @@
 	       cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
 	       proc_arch[cpu_architecture()], cr_alignment);
 
-	sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
-	sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
+	snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
+		 list->arch_name, ENDIANNESS);
+	snprintf(elf_platform, ELF_PLATFORM_SIZE, "%s%c",
+		 list->elf_name, ENDIANNESS);
 	elf_hwcap = list->elf_hwcap;
 #ifndef CONFIG_ARM_THUMB
 	elf_hwcap &= ~HWCAP_THUMB;
@@ -820,25 +851,8 @@
 
 	if (__atags_pointer)
 		tags = phys_to_virt(__atags_pointer);
-	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);
-		}
-	}
+	else if (mdesc->atag_offset)
+		tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
 
 #if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
 	/*
@@ -861,7 +875,7 @@
 	}
 
 	if (mdesc->fixup)
-		mdesc->fixup(mdesc, tags, &from, &meminfo);
+		mdesc->fixup(tags, &from, &meminfo);
 
 	if (tags->hdr.tag == ATAG_CORE) {
 		if (meminfo.nr_banks != 0)
@@ -881,8 +895,6 @@
 {
 	struct machine_desc *mdesc;
 
-	unwind_init();
-
 	setup_processor();
 	mdesc = setup_machine_fdt(__atags_pointer);
 	if (!mdesc)
@@ -890,6 +902,12 @@
 	machine_desc = mdesc;
 	machine_name = mdesc->name;
 
+#ifdef CONFIG_ZONE_DMA
+	if (mdesc->dma_zone_size) {
+		extern unsigned long arm_dma_zone_size;
+		arm_dma_zone_size = mdesc->dma_zone_size;
+	}
+#endif
 	if (mdesc->soft_reboot)
 		reboot_setup("s");
 
@@ -920,12 +938,6 @@
 
 	tcm_init();
 
-#ifdef CONFIG_ZONE_DMA
-	if (mdesc->dma_zone_size) {
-		extern unsigned long arm_dma_zone_size;
-		arm_dma_zone_size = mdesc->dma_zone_size;
-	}
-#endif
 #ifdef CONFIG_MULTI_IRQ_HANDLER
 	handle_arch_irq = mdesc->handle_irq;
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/sleep.S linux-libre-3.2-gnu/arch/arm/kernel/sleep.S
--- linux-libre-3.1-gnu/arch/arm/kernel/sleep.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/sleep.S	2012-01-04 18:55:44.000000000 -0500
@@ -8,92 +8,61 @@
 	.text
 
 /*
- * Save CPU state for a suspend
- *  r1 = v:p offset
- *  r2 = suspend function arg0
- *  r3 = suspend function
+ * Save CPU state for a suspend.  This saves the CPU general purpose
+ * registers, and allocates space on the kernel stack to save the CPU
+ * specific registers and some other data for resume.
+ *  r0 = suspend function arg0
+ *  r1 = suspend function
  */
 ENTRY(__cpu_suspend)
 	stmfd	sp!, {r4 - r11, lr}
 #ifdef MULTI_CPU
 	ldr	r10, =processor
-	ldr	r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
-	ldr	ip, [r10, #CPU_DO_RESUME] @ virtual resume function
+	ldr	r4, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
 #else
-	ldr	r5, =cpu_suspend_size
-	ldr	ip, =cpu_do_resume
+	ldr	r4, =cpu_suspend_size
 #endif
-	mov	r6, sp			@ current virtual SP
-	sub	sp, sp, r5		@ allocate CPU state on stack
-	mov	r0, sp			@ save pointer to CPU save block
-	add	ip, ip, r1		@ convert resume fn to phys
-	stmfd	sp!, {r1, r6, ip}	@ save v:p, virt SP, phys resume fn
-	ldr	r5, =sleep_save_sp
-	add	r6, sp, r1		@ convert SP to phys
-	stmfd	sp!, {r2, r3}		@ save suspend func arg and pointer
+	mov	r5, sp			@ current virtual SP
+	add	r4, r4, #12		@ Space for pgd, virt sp, phys resume fn
+	sub	sp, sp, r4		@ allocate CPU state on stack
+	stmfd	sp!, {r0, r1}		@ save suspend func arg and pointer
+	add	r0, sp, #8		@ save pointer to save block
+	mov	r1, r4			@ size of save block
+	mov	r2, r5			@ virtual SP
+	ldr	r3, =sleep_save_sp
 #ifdef CONFIG_SMP
 	ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
 	ALT_UP(mov lr, #0)
 	and	lr, lr, #15
-	str	r6, [r5, lr, lsl #2]	@ save phys SP
-#else
-	str	r6, [r5]		@ save phys SP
-#endif
-#ifdef MULTI_CPU
-	mov	lr, pc
-	ldr	pc, [r10, #CPU_DO_SUSPEND] @ save CPU state
-#else
-	bl	cpu_do_suspend
-#endif
-
-	@ flush data cache
-#ifdef MULTI_CACHE
-	ldr	r10, =cpu_cache
-	mov	lr, pc
-	ldr	pc, [r10, #CACHE_FLUSH_KERN_ALL]
-#else
-	bl	__cpuc_flush_kern_all
+	add	r3, r3, lr, lsl #2
 #endif
+	bl	__cpu_suspend_save
 	adr	lr, BSYM(cpu_suspend_abort)
 	ldmfd	sp!, {r0, pc}		@ call suspend fn
 ENDPROC(__cpu_suspend)
 	.ltorg
 
 cpu_suspend_abort:
-	ldmia	sp!, {r1 - r3}		@ pop v:p, virt SP, phys resume fn
+	ldmia	sp!, {r1 - r3}		@ pop phys pgd, virt SP, phys resume fn
+	teq	r0, #0
+	moveq	r0, #1			@ force non-zero value
 	mov	sp, r2
 	ldmfd	sp!, {r4 - r11, pc}
 ENDPROC(cpu_suspend_abort)
 
 /*
  * r0 = control register value
- * r1 = v:p offset (preserved by cpu_do_resume)
- * r2 = phys page table base
- * r3 = L1 section flags
  */
+	.align	5
 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
+	mcr	p15, 0, r0, c1, c0, 0	@ turn on MMU, I-cache, etc
+	mrc	p15, 0, r0, c0, c0, 0	@ read id reg
+	mov	r0, r0
+	mov	r0, r0
 	mov	pc, r3			@ jump to virtual address
-ENDPROC(cpu_resume_turn_mmu_on)
+ENDPROC(cpu_resume_mmu)
 cpu_resume_after_mmu:
-	str	r5, [r2, r4, lsl #2]	@ restore old mapping
-	mcr	p15, 0, r0, c1, c0, 0	@ turn on D-cache
 	bl	cpu_init		@ restore the und/abt/irq banked regs
 	mov	r0, #0			@ return zero on success
 	ldmfd	sp!, {r4 - r11, pc}
@@ -119,7 +88,7 @@
 	ldr	r0, sleep_save_sp	@ stack phys addr
 #endif
 	setmode	PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1  @ set SVC, irqs off
-	@ load v:p, stack, resume fn
+	@ load phys pgd, stack, resume fn
   ARM(	ldmia	r0!, {r1, sp, pc}	)
 THUMB(	ldmia	r0!, {r1, r2, r3}	)
 THUMB(	mov	sp, r2			)
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/smp.c linux-libre-3.2-gnu/arch/arm/kernel/smp.c
--- linux-libre-3.1-gnu/arch/arm/kernel/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,6 @@
 #include <linux/cache.h>
 #include <linux/profile.h>
 #include <linux/errno.h>
-#include <linux/ftrace.h>
 #include <linux/mm.h>
 #include <linux/err.h>
 #include <linux/cpu.h>
@@ -31,6 +30,8 @@
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
 #include <asm/cputype.h>
+#include <asm/exception.h>
+#include <asm/topology.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -39,6 +40,7 @@
 #include <asm/tlbflush.h>
 #include <asm/ptrace.h>
 #include <asm/localtimer.h>
+#include <asm/smp_plat.h>
 
 /*
  * as from 2.5, kernels no longer have an init_tasks structure
@@ -259,6 +261,20 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
+int __cpu_logical_map[NR_CPUS];
+
+void __init smp_setup_processor_id(void)
+{
+	int i;
+	u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0;
+
+	cpu_logical_map(0) = cpu;
+	for (i = 1; i < NR_CPUS; ++i)
+		cpu_logical_map(i) = i == cpu ? 0 : i;
+
+	printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu);
+}
+
 /*
  * Called by both boot and secondaries to move global data into
  * per-processor storage.
@@ -268,6 +284,8 @@
 	struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);
 
 	cpu_info->loops_per_jiffy = loops_per_jiffy;
+
+	store_cpu_topology(cpuid);
 }
 
 /*
@@ -301,17 +319,7 @@
 	 */
 	platform_secondary_init(cpu);
 
-	/*
-	 * Enable local interrupts.
-	 */
 	notify_cpu_starting(cpu);
-	local_irq_enable();
-	local_fiq_enable();
-
-	/*
-	 * Setup the percpu timer for this CPU.
-	 */
-	percpu_timer_setup();
 
 	calibrate_delay();
 
@@ -323,10 +331,23 @@
 	 * before we continue.
 	 */
 	set_cpu_online(cpu, true);
+
+	/*
+	 * Setup the percpu timer for this CPU.
+	 */
+	percpu_timer_setup();
+
 	while (!cpu_active(cpu))
 		cpu_relax();
 
 	/*
+	 * cpu_active bit is set, so it's safe to enalbe interrupts
+	 * now.
+	 */
+	local_irq_enable();
+	local_fiq_enable();
+
+	/*
 	 * OK, it's off to the idle thread for us
 	 */
 	cpu_idle();
@@ -358,6 +379,8 @@
 {
 	unsigned int ncores = num_possible_cpus();
 
+	init_cpu_topology();
+
 	smp_store_cpu_info(smp_processor_id());
 
 	/*
@@ -437,10 +460,6 @@
 	for (i = 0; i < NR_IPI; i++)
 		sum += __get_irq_stat(cpu, ipi_irqs[i]);
 
-#ifdef CONFIG_LOCAL_TIMERS
-	sum += __get_irq_stat(cpu, local_timer_irqs);
-#endif
-
 	return sum;
 }
 
@@ -457,33 +476,6 @@
 	irq_exit();
 }
 
-#ifdef CONFIG_LOCAL_TIMERS
-asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs)
-{
-	struct pt_regs *old_regs = set_irq_regs(regs);
-	int cpu = smp_processor_id();
-
-	if (local_timer_ack()) {
-		__inc_irq_stat(cpu, local_timer_irqs);
-		ipi_timer();
-	}
-
-	set_irq_regs(old_regs);
-}
-
-void show_local_irqs(struct seq_file *p, int prec)
-{
-	unsigned int cpu;
-
-	seq_printf(p, "%*s: ", prec, "LOC");
-
-	for_each_present_cpu(cpu)
-		seq_printf(p, "%10u ", __get_irq_stat(cpu, local_timer_irqs));
-
-	seq_printf(p, " Local timer interrupts\n");
-}
-#endif
-
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 static void smp_timer_broadcast(const struct cpumask *mask)
 {
@@ -534,11 +526,11 @@
 	unsigned int cpu = smp_processor_id();
 	struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
 
-	evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+	local_timer_stop(evt);
 }
 #endif
 
-static DEFINE_SPINLOCK(stop_lock);
+static DEFINE_RAW_SPINLOCK(stop_lock);
 
 /*
  * ipi_cpu_stop - handle IPI from smp_send_stop()
@@ -547,10 +539,10 @@
 {
 	if (system_state == SYSTEM_BOOTING ||
 	    system_state == SYSTEM_RUNNING) {
-		spin_lock(&stop_lock);
+		raw_spin_lock(&stop_lock);
 		printk(KERN_CRIT "CPU%u: stopping\n", cpu);
 		dump_stack();
-		spin_unlock(&stop_lock);
+		raw_spin_unlock(&stop_lock);
 	}
 
 	set_cpu_online(cpu, false);
@@ -567,6 +559,11 @@
  */
 asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
 {
+	handle_IPI(ipinr, regs);
+}
+
+void handle_IPI(int ipinr, struct pt_regs *regs)
+{
 	unsigned int cpu = smp_processor_id();
 	struct pt_regs *old_regs = set_irq_regs(regs);
 
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/smp_scu.c linux-libre-3.2-gnu/arch/arm/kernel/smp_scu.c
--- linux-libre-3.1-gnu/arch/arm/kernel/smp_scu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/smp_scu.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,7 +34,7 @@
 /*
  * Enable the SCU
  */
-void __init scu_enable(void __iomem *scu_base)
+void scu_enable(void __iomem *scu_base)
 {
 	u32 scu_ctrl;
 
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/smp_twd.c linux-libre-3.2-gnu/arch/arm/kernel/smp_twd.c
--- linux-libre-3.1-gnu/arch/arm/kernel/smp_twd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/smp_twd.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/io.h>
 
 #include <asm/smp_twd.h>
+#include <asm/localtimer.h>
 #include <asm/hardware/gic.h>
 
 /* set up by the platform code */
@@ -26,6 +27,8 @@
 
 static unsigned long twd_timer_rate;
 
+static struct clock_event_device __percpu **twd_evt;
+
 static void twd_set_mode(enum clock_event_mode mode,
 			struct clock_event_device *clk)
 {
@@ -80,6 +83,12 @@
 	return 0;
 }
 
+void twd_timer_stop(struct clock_event_device *clk)
+{
+	twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
+	disable_percpu_irq(clk->irq);
+}
+
 static void __cpuinit twd_calibrate_rate(void)
 {
 	unsigned long count;
@@ -119,11 +128,43 @@
 	}
 }
 
+static irqreturn_t twd_handler(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+
+	if (twd_timer_ack()) {
+		evt->event_handler(evt);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
 /*
  * Setup the local clock events for a CPU.
  */
 void __cpuinit twd_timer_setup(struct clock_event_device *clk)
 {
+	struct clock_event_device **this_cpu_clk;
+
+	if (!twd_evt) {
+		int err;
+
+		twd_evt = alloc_percpu(struct clock_event_device *);
+		if (!twd_evt) {
+			pr_err("twd: can't allocate memory\n");
+			return;
+		}
+
+		err = request_percpu_irq(clk->irq, twd_handler,
+					 "twd", twd_evt);
+		if (err) {
+			pr_err("twd: can't register interrupt %d (%d)\n",
+			       clk->irq, err);
+			return;
+		}
+	}
+
 	twd_calibrate_rate();
 
 	clk->name = "local_timer";
@@ -137,8 +178,10 @@
 	clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
 	clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
 
+	this_cpu_clk = __this_cpu_ptr(twd_evt);
+	*this_cpu_clk = clk;
+
 	clockevents_register_device(clk);
 
-	/* Make sure our local interrupt controller has this enabled */
-	gic_enable_ppi(clk->irq);
+	enable_percpu_irq(clk->irq, 0);
 }
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/stacktrace.c linux-libre-3.2-gnu/arch/arm/kernel/stacktrace.c
--- linux-libre-3.1-gnu/arch/arm/kernel/stacktrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/stacktrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/stacktrace.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/suspend.c linux-libre-3.2-gnu/arch/arm/kernel/suspend.c
--- linux-libre-3.1-gnu/arch/arm/kernel/suspend.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/kernel/suspend.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,72 @@
+#include <linux/init.h>
+
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/memory.h>
+#include <asm/suspend.h>
+#include <asm/tlbflush.h>
+
+static pgd_t *suspend_pgd;
+
+extern int __cpu_suspend(unsigned long, int (*)(unsigned long));
+extern void cpu_resume_mmu(void);
+
+/*
+ * This is called by __cpu_suspend() to save the state, and do whatever
+ * flushing is required to ensure that when the CPU goes to sleep we have
+ * the necessary data available when the caches are not searched.
+ */
+void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)
+{
+	*save_ptr = virt_to_phys(ptr);
+
+	/* This must correspond to the LDM in cpu_resume() assembly */
+	*ptr++ = virt_to_phys(suspend_pgd);
+	*ptr++ = sp;
+	*ptr++ = virt_to_phys(cpu_do_resume);
+
+	cpu_do_suspend(ptr);
+
+	flush_cache_all();
+	outer_clean_range(*save_ptr, *save_ptr + ptrsz);
+	outer_clean_range(virt_to_phys(save_ptr),
+			  virt_to_phys(save_ptr) + sizeof(*save_ptr));
+}
+
+/*
+ * Hide the first two arguments to __cpu_suspend - these are an implementation
+ * detail which platform code shouldn't have to know about.
+ */
+int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
+{
+	struct mm_struct *mm = current->active_mm;
+	int ret;
+
+	if (!suspend_pgd)
+		return -EINVAL;
+
+	/*
+	 * Provide a temporary page table with an identity mapping for
+	 * the MMU-enable code, required for resuming.  On successful
+	 * resume (indicated by a zero return code), we need to switch
+	 * back to the correct page tables.
+	 */
+	ret = __cpu_suspend(arg, fn);
+	if (ret == 0) {
+		cpu_switch_mm(mm->pgd, mm);
+		local_flush_tlb_all();
+	}
+
+	return ret;
+}
+
+static int __init cpu_suspend_init(void)
+{
+	suspend_pgd = pgd_alloc(&init_mm);
+	if (suspend_pgd) {
+		unsigned long addr = virt_to_phys(cpu_resume_mmu);
+		identity_mapping_add(suspend_pgd, addr, addr + SECTION_SIZE);
+	}
+	return suspend_pgd ? 0 : -ENOMEM;
+}
+core_initcall(cpu_suspend_init);
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/sys_arm.c linux-libre-3.2-gnu/arch/arm/kernel/sys_arm.c
--- linux-libre-3.1-gnu/arch/arm/kernel/sys_arm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/sys_arm.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
  *  have a non-standard calling sequence on the Linux/arm
  *  platform.
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/time.c linux-libre-3.2-gnu/arch/arm/kernel/time.c
--- linux-libre-3.1-gnu/arch/arm/kernel/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *  This file contains the ARM-specific time handling details:
  *  reading the RTC at bootup, etc...
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/time.h>
@@ -39,13 +39,11 @@
  */
 static struct sys_timer *system_timer;
 
-#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
+#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \
+    defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE)
 /* this needs a better home */
 DEFINE_SPINLOCK(rtc_lock);
-
-#ifdef CONFIG_RTC_DRV_CMOS_MODULE
 EXPORT_SYMBOL(rtc_lock);
-#endif
 #endif	/* pc-style 'CMOS' RTC support */
 
 /* change this if you have some constant time drift */
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/topology.c linux-libre-3.2-gnu/arch/arm/kernel/topology.c
--- linux-libre-3.1-gnu/arch/arm/kernel/topology.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/kernel/topology.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,148 @@
+/*
+ * arch/arm/kernel/topology.c
+ *
+ * Copyright (C) 2011 Linaro Limited.
+ * Written by: Vincent Guittot
+ *
+ * based on arch/sh/kernel/topology.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/node.h>
+#include <linux/nodemask.h>
+#include <linux/sched.h>
+
+#include <asm/cputype.h>
+#include <asm/topology.h>
+
+#define MPIDR_SMP_BITMASK (0x3 << 30)
+#define MPIDR_SMP_VALUE (0x2 << 30)
+
+#define MPIDR_MT_BITMASK (0x1 << 24)
+
+/*
+ * These masks reflect the current use of the affinity levels.
+ * The affinity level can be up to 16 bits according to ARM ARM
+ */
+
+#define MPIDR_LEVEL0_MASK 0x3
+#define MPIDR_LEVEL0_SHIFT 0
+
+#define MPIDR_LEVEL1_MASK 0xF
+#define MPIDR_LEVEL1_SHIFT 8
+
+#define MPIDR_LEVEL2_MASK 0xFF
+#define MPIDR_LEVEL2_SHIFT 16
+
+struct cputopo_arm cpu_topology[NR_CPUS];
+
+const struct cpumask *cpu_coregroup_mask(int cpu)
+{
+	return &cpu_topology[cpu].core_sibling;
+}
+
+/*
+ * store_cpu_topology is called at boot when only one cpu is running
+ * and with the mutex cpu_hotplug.lock locked, when several cpus have booted,
+ * which prevents simultaneous write access to cpu_topology array
+ */
+void store_cpu_topology(unsigned int cpuid)
+{
+	struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid];
+	unsigned int mpidr;
+	unsigned int cpu;
+
+	/* If the cpu topology has been already set, just return */
+	if (cpuid_topo->core_id != -1)
+		return;
+
+	mpidr = read_cpuid_mpidr();
+
+	/* create cpu topology mapping */
+	if ((mpidr & MPIDR_SMP_BITMASK) == MPIDR_SMP_VALUE) {
+		/*
+		 * This is a multiprocessor system
+		 * multiprocessor format & multiprocessor mode field are set
+		 */
+
+		if (mpidr & MPIDR_MT_BITMASK) {
+			/* core performance interdependency */
+			cpuid_topo->thread_id = (mpidr >> MPIDR_LEVEL0_SHIFT)
+				& MPIDR_LEVEL0_MASK;
+			cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL1_SHIFT)
+				& MPIDR_LEVEL1_MASK;
+			cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL2_SHIFT)
+				& MPIDR_LEVEL2_MASK;
+		} else {
+			/* largely independent cores */
+			cpuid_topo->thread_id = -1;
+			cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL0_SHIFT)
+				& MPIDR_LEVEL0_MASK;
+			cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL1_SHIFT)
+				& MPIDR_LEVEL1_MASK;
+		}
+	} else {
+		/*
+		 * This is an uniprocessor system
+		 * we are in multiprocessor format but uniprocessor system
+		 * or in the old uniprocessor format
+		 */
+		cpuid_topo->thread_id = -1;
+		cpuid_topo->core_id = 0;
+		cpuid_topo->socket_id = -1;
+	}
+
+	/* update core and thread sibling masks */
+	for_each_possible_cpu(cpu) {
+		struct cputopo_arm *cpu_topo = &cpu_topology[cpu];
+
+		if (cpuid_topo->socket_id == cpu_topo->socket_id) {
+			cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
+			if (cpu != cpuid)
+				cpumask_set_cpu(cpu,
+					&cpuid_topo->core_sibling);
+
+			if (cpuid_topo->core_id == cpu_topo->core_id) {
+				cpumask_set_cpu(cpuid,
+					&cpu_topo->thread_sibling);
+				if (cpu != cpuid)
+					cpumask_set_cpu(cpu,
+						&cpuid_topo->thread_sibling);
+			}
+		}
+	}
+	smp_wmb();
+
+	printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n",
+		cpuid, cpu_topology[cpuid].thread_id,
+		cpu_topology[cpuid].core_id,
+		cpu_topology[cpuid].socket_id, mpidr);
+}
+
+/*
+ * init_cpu_topology is called at boot when only one cpu is running
+ * which prevent simultaneous write access to cpu_topology array
+ */
+void init_cpu_topology(void)
+{
+	unsigned int cpu;
+
+	/* init core mask */
+	for_each_possible_cpu(cpu) {
+		struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]);
+
+		cpu_topo->thread_id = -1;
+		cpu_topo->core_id =  -1;
+		cpu_topo->socket_id = -1;
+		cpumask_clear(&cpu_topo->core_sibling);
+		cpumask_clear(&cpu_topo->thread_sibling);
+	}
+	smp_wmb();
+}
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/traps.c linux-libre-3.2-gnu/arch/arm/kernel/traps.c
--- linux-libre-3.1-gnu/arch/arm/kernel/traps.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/traps.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,12 +21,14 @@
 #include <linux/kdebug.h>
 #include <linux/module.h>
 #include <linux/kexec.h>
+#include <linux/bug.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 
 #include <linux/atomic.h>
 #include <asm/cacheflush.h>
+#include <asm/exception.h>
 #include <asm/system.h>
 #include <asm/unistd.h>
 #include <asm/traps.h>
@@ -255,7 +257,7 @@
 	return ret;
 }
 
-static DEFINE_SPINLOCK(die_lock);
+static DEFINE_RAW_SPINLOCK(die_lock);
 
 /*
  * This function is protected against re-entrancy.
@@ -267,9 +269,11 @@
 
 	oops_enter();
 
-	spin_lock_irq(&die_lock);
+	raw_spin_lock_irq(&die_lock);
 	console_verbose();
 	bust_spinlocks(1);
+	if (!user_mode(regs))
+		report_bug(regs->ARM_pc, regs);
 	ret = __die(str, err, thread, regs);
 
 	if (regs && kexec_should_crash(thread->task))
@@ -277,7 +281,7 @@
 
 	bust_spinlocks(0);
 	add_taint(TAINT_DIE);
-	spin_unlock_irq(&die_lock);
+	raw_spin_unlock_irq(&die_lock);
 	oops_exit();
 
 	if (in_interrupt())
@@ -301,25 +305,43 @@
 	}
 }
 
+#ifdef CONFIG_GENERIC_BUG
+
+int is_valid_bugaddr(unsigned long pc)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+	unsigned short bkpt;
+#else
+	unsigned long bkpt;
+#endif
+
+	if (probe_kernel_address((unsigned *)pc, bkpt))
+		return 0;
+
+	return bkpt == BUG_INSTR_VALUE;
+}
+
+#endif
+
 static LIST_HEAD(undef_hook);
-static DEFINE_SPINLOCK(undef_lock);
+static DEFINE_RAW_SPINLOCK(undef_lock);
 
 void register_undef_hook(struct undef_hook *hook)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&undef_lock, flags);
+	raw_spin_lock_irqsave(&undef_lock, flags);
 	list_add(&hook->node, &undef_hook);
-	spin_unlock_irqrestore(&undef_lock, flags);
+	raw_spin_unlock_irqrestore(&undef_lock, flags);
 }
 
 void unregister_undef_hook(struct undef_hook *hook)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&undef_lock, flags);
+	raw_spin_lock_irqsave(&undef_lock, flags);
 	list_del(&hook->node);
-	spin_unlock_irqrestore(&undef_lock, flags);
+	raw_spin_unlock_irqrestore(&undef_lock, flags);
 }
 
 static int call_undef_hook(struct pt_regs *regs, unsigned int instr)
@@ -328,12 +350,12 @@
 	unsigned long flags;
 	int (*fn)(struct pt_regs *regs, unsigned int instr) = NULL;
 
-	spin_lock_irqsave(&undef_lock, flags);
+	raw_spin_lock_irqsave(&undef_lock, flags);
 	list_for_each_entry(hook, &undef_hook, node)
 		if ((instr & hook->instr_mask) == hook->instr_val &&
 		    (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val)
 			fn = hook->fn;
-	spin_unlock_irqrestore(&undef_lock, flags);
+	raw_spin_unlock_irqrestore(&undef_lock, flags);
 
 	return fn ? fn(regs, instr) : 1;
 }
@@ -706,16 +728,6 @@
 	arm_notify_die("unknown data abort code", regs, &info, instr, 0);
 }
 
-void __attribute__((noreturn)) __bug(const char *file, int line)
-{
-	printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line);
-	*(int *)0 = 0;
-
-	/* Avoid "noreturn function does return" */
-	for (;;);
-}
-EXPORT_SYMBOL(__bug);
-
 void __readwrite_bug(const char *fn)
 {
 	printk("%s called, but not implemented\n", fn);
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/unwind.c linux-libre-3.2-gnu/arch/arm/kernel/unwind.c
--- linux-libre-3.1-gnu/arch/arm/kernel/unwind.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/unwind.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,7 +39,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
@@ -67,7 +67,7 @@
 
 struct unwind_ctrl_block {
 	unsigned long vrs[16];		/* virtual register set */
-	unsigned long *insn;		/* pointer to the current instructions word */
+	const unsigned long *insn;	/* pointer to the current instructions word */
 	int entries;			/* number of entries left to interpret */
 	int byte;			/* current byte number in the instructions word */
 };
@@ -83,8 +83,9 @@
 	PC = 15
 };
 
-extern struct unwind_idx __start_unwind_idx[];
-extern struct unwind_idx __stop_unwind_idx[];
+extern const struct unwind_idx __start_unwind_idx[];
+static const struct unwind_idx *__origin_unwind_idx;
+extern const struct unwind_idx __stop_unwind_idx[];
 
 static DEFINE_SPINLOCK(unwind_lock);
 static LIST_HEAD(unwind_tables);
@@ -98,45 +99,99 @@
 })
 
 /*
- * Binary search in the unwind index. The entries entries are
+ * Binary search in the unwind index. The entries are
  * guaranteed to be sorted in ascending order by the linker.
+ *
+ * start = first entry
+ * origin = first entry with positive offset (or stop if there is no such entry)
+ * stop - 1 = last entry
  */
-static struct unwind_idx *search_index(unsigned long addr,
-				       struct unwind_idx *first,
-				       struct unwind_idx *last)
+static const struct unwind_idx *search_index(unsigned long addr,
+				       const struct unwind_idx *start,
+				       const struct unwind_idx *origin,
+				       const struct unwind_idx *stop)
 {
-	pr_debug("%s(%08lx, %p, %p)\n", __func__, addr, first, last);
+	unsigned long addr_prel31;
 
-	if (addr < first->addr) {
+	pr_debug("%s(%08lx, %p, %p, %p)\n",
+			__func__, addr, start, origin, stop);
+
+	/*
+	 * only search in the section with the matching sign. This way the
+	 * prel31 numbers can be compared as unsigned longs.
+	 */
+	if (addr < (unsigned long)start)
+		/* negative offsets: [start; origin) */
+		stop = origin;
+	else
+		/* positive offsets: [origin; stop) */
+		start = origin;
+
+	/* prel31 for address relavive to start */
+	addr_prel31 = (addr - (unsigned long)start) & 0x7fffffff;
+
+	while (start < stop - 1) {
+		const struct unwind_idx *mid = start + ((stop - start) >> 1);
+
+		/*
+		 * As addr_prel31 is relative to start an offset is needed to
+		 * make it relative to mid.
+		 */
+		if (addr_prel31 - ((unsigned long)mid - (unsigned long)start) <
+				mid->addr_offset)
+			stop = mid;
+		else {
+			/* keep addr_prel31 relative to start */
+			addr_prel31 -= ((unsigned long)mid -
+					(unsigned long)start);
+			start = mid;
+		}
+	}
+
+	if (likely(start->addr_offset <= addr_prel31))
+		return start;
+	else {
 		pr_warning("unwind: Unknown symbol address %08lx\n", addr);
 		return NULL;
-	} else if (addr >= last->addr)
-		return last;
+	}
+}
 
-	while (first < last - 1) {
-		struct unwind_idx *mid = first + ((last - first + 1) >> 1);
+static const struct unwind_idx *unwind_find_origin(
+		const struct unwind_idx *start, const struct unwind_idx *stop)
+{
+	pr_debug("%s(%p, %p)\n", __func__, start, stop);
+	while (start < stop) {
+		const struct unwind_idx *mid = start + ((stop - start) >> 1);
 
-		if (addr < mid->addr)
-			last = mid;
+		if (mid->addr_offset >= 0x40000000)
+			/* negative offset */
+			start = mid + 1;
 		else
-			first = mid;
+			/* positive offset */
+			stop = mid;
 	}
-
-	return first;
+	pr_debug("%s -> %p\n", __func__, stop);
+	return stop;
 }
 
-static struct unwind_idx *unwind_find_idx(unsigned long addr)
+static const struct unwind_idx *unwind_find_idx(unsigned long addr)
 {
-	struct unwind_idx *idx = NULL;
+	const struct unwind_idx *idx = NULL;
 	unsigned long flags;
 
 	pr_debug("%s(%08lx)\n", __func__, addr);
 
-	if (core_kernel_text(addr))
+	if (core_kernel_text(addr)) {
+		if (unlikely(!__origin_unwind_idx))
+			__origin_unwind_idx =
+				unwind_find_origin(__start_unwind_idx,
+						__stop_unwind_idx);
+
 		/* main unwind table */
 		idx = search_index(addr, __start_unwind_idx,
-				   __stop_unwind_idx - 1);
-	else {
+				   __origin_unwind_idx,
+				   __stop_unwind_idx);
+	} else {
 		/* module unwind tables */
 		struct unwind_table *table;
 
@@ -145,7 +200,8 @@
 			if (addr >= table->begin_addr &&
 			    addr < table->end_addr) {
 				idx = search_index(addr, table->start,
-						   table->stop - 1);
+						   table->origin,
+						   table->stop);
 				/* Move-to-front to exploit common traces */
 				list_move(&table->list, &unwind_tables);
 				break;
@@ -274,7 +330,7 @@
 int unwind_frame(struct stackframe *frame)
 {
 	unsigned long high, low;
-	struct unwind_idx *idx;
+	const struct unwind_idx *idx;
 	struct unwind_ctrl_block ctrl;
 
 	/* only go to a higher address on the stack */
@@ -399,7 +455,6 @@
 				      unsigned long text_size)
 {
 	unsigned long flags;
-	struct unwind_idx *idx;
 	struct unwind_table *tab = kmalloc(sizeof(*tab), GFP_KERNEL);
 
 	pr_debug("%s(%08lx, %08lx, %08lx, %08lx)\n", __func__, start, size,
@@ -408,15 +463,12 @@
 	if (!tab)
 		return tab;
 
-	tab->start = (struct unwind_idx *)start;
-	tab->stop = (struct unwind_idx *)(start + size);
+	tab->start = (const struct unwind_idx *)start;
+	tab->stop = (const struct unwind_idx *)(start + size);
+	tab->origin = unwind_find_origin(tab->start, tab->stop);
 	tab->begin_addr = text_addr;
 	tab->end_addr = text_addr + text_size;
 
-	/* Convert the symbol addresses to absolute values */
-	for (idx = tab->start; idx < tab->stop; idx++)
-		idx->addr = prel31_to_addr(&idx->addr);
-
 	spin_lock_irqsave(&unwind_lock, flags);
 	list_add_tail(&tab->list, &unwind_tables);
 	spin_unlock_irqrestore(&unwind_lock, flags);
@@ -437,16 +489,3 @@
 
 	kfree(tab);
 }
-
-int __init unwind_init(void)
-{
-	struct unwind_idx *idx;
-
-	/* Convert the symbol addresses to absolute values */
-	for (idx = __start_unwind_idx; idx < __stop_unwind_idx; idx++)
-		idx->addr = prel31_to_addr(&idx->addr);
-
-	pr_debug("unwind: ARM stack unwinding initialised\n");
-
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/vmlinux.lds.S linux-libre-3.2-gnu/arch/arm/kernel/vmlinux.lds.S
--- linux-libre-3.1-gnu/arch/arm/kernel/vmlinux.lds.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/vmlinux.lds.S	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,8 @@
 #define ARM_CPU_KEEP(x)
 #endif
 
-#if defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)
+#if (defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)) || \
+	defined(CONFIG_GENERIC_BUG)
 #define ARM_EXIT_KEEP(x)	x
 #define ARM_EXIT_DISCARD(x)
 #else
diff -druN linux-libre-3.1-gnu/arch/arm/kernel/xscale-cp0.c linux-libre-3.2-gnu/arch/arm/kernel/xscale-cp0.c
--- linux-libre-3.1-gnu/arch/arm/kernel/xscale-cp0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/kernel/xscale-cp0.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
diff -druN linux-libre-3.1-gnu/arch/arm/lib/backtrace.S linux-libre-3.2-gnu/arch/arm/lib/backtrace.S
--- linux-libre-3.1-gnu/arch/arm/lib/backtrace.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/lib/backtrace.S	2012-01-04 18:55:44.000000000 -0500
@@ -22,15 +22,10 @@
 #define mask	r7
 #define offset	r8
 
-ENTRY(__backtrace)
-		mov	r1, #0x10
-		mov	r0, fp
-
 ENTRY(c_backtrace)
 
 #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
 		mov	pc, lr
-ENDPROC(__backtrace)
 ENDPROC(c_backtrace)
 #else
 		stmfd	sp!, {r4 - r8, lr}	@ Save an extra register so we have a location...
@@ -107,7 +102,6 @@
 		mov	r1, frame
 		bl	printk
 no_frame:	ldmfd	sp!, {r4 - r8, pc}
-ENDPROC(__backtrace)
 ENDPROC(c_backtrace)
 		
 		.pushsection __ex_table,"a"
diff -druN linux-libre-3.1-gnu/arch/arm/lib/bitops.h linux-libre-3.2-gnu/arch/arm/lib/bitops.h
--- linux-libre-3.1-gnu/arch/arm/lib/bitops.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/lib/bitops.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,9 @@
+#include <asm/unwind.h>
+
 #if __LINUX_ARM_ARCH__ >= 6
-	.macro	bitop, instr
+	.macro	bitop, name, instr
+ENTRY(	\name		)
+UNWIND(	.fnstart	)
 	ands	ip, r1, #3
 	strneb	r1, [ip]		@ assert word-aligned
 	mov	r2, #1
@@ -13,9 +17,13 @@
 	cmp	r0, #0
 	bne	1b
 	bx	lr
+UNWIND(	.fnend		)
+ENDPROC(\name		)
 	.endm
 
-	.macro	testop, instr, store
+	.macro	testop, name, instr, store
+ENTRY(	\name		)
+UNWIND(	.fnstart	)
 	ands	ip, r1, #3
 	strneb	r1, [ip]		@ assert word-aligned
 	mov	r2, #1
@@ -34,9 +42,13 @@
 	cmp	r0, #0
 	movne	r0, #1
 2:	bx	lr
+UNWIND(	.fnend		)
+ENDPROC(\name		)
 	.endm
 #else
-	.macro	bitop, instr
+	.macro	bitop, name, instr
+ENTRY(	\name		)
+UNWIND(	.fnstart	)
 	ands	ip, r1, #3
 	strneb	r1, [ip]		@ assert word-aligned
 	and	r2, r0, #31
@@ -49,6 +61,8 @@
 	str	r2, [r1, r0, lsl #2]
 	restore_irqs ip
 	mov	pc, lr
+UNWIND(	.fnend		)
+ENDPROC(\name		)
 	.endm
 
 /**
@@ -59,7 +73,9 @@
  * Note: we can trivially conditionalise the store instruction
  * to avoid dirtying the data cache.
  */
-	.macro	testop, instr, store
+	.macro	testop, name, instr, store
+ENTRY(	\name		)
+UNWIND(	.fnstart	)
 	ands	ip, r1, #3
 	strneb	r1, [ip]		@ assert word-aligned
 	and	r3, r0, #31
@@ -73,5 +89,7 @@
 	moveq	r0, #0
 	restore_irqs ip
 	mov	pc, lr
+UNWIND(	.fnend		)
+ENDPROC(\name		)
 	.endm
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/lib/changebit.S linux-libre-3.2-gnu/arch/arm/lib/changebit.S
--- linux-libre-3.1-gnu/arch/arm/lib/changebit.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/lib/changebit.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_change_bit)
-	bitop	eor
-ENDPROC(_change_bit)
+bitop	_change_bit, eor
diff -druN linux-libre-3.1-gnu/arch/arm/lib/clearbit.S linux-libre-3.2-gnu/arch/arm/lib/clearbit.S
--- linux-libre-3.1-gnu/arch/arm/lib/clearbit.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/lib/clearbit.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_clear_bit)
-	bitop	bic
-ENDPROC(_clear_bit)
+bitop	_clear_bit, bic
diff -druN linux-libre-3.1-gnu/arch/arm/lib/div64.S linux-libre-3.2-gnu/arch/arm/lib/div64.S
--- linux-libre-3.1-gnu/arch/arm/lib/div64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/lib/div64.S	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/unwind.h>
 
 #ifdef __ARMEB__
 #define xh r0
@@ -44,6 +45,7 @@
  */
 
 ENTRY(__do_div64)
+UNWIND(.fnstart)
 
 	@ Test for easy paths first.
 	subs	ip, r4, #1
@@ -189,7 +191,12 @@
 	moveq	yh, xh
 	moveq	xh, #0
 	moveq	pc, lr
+UNWIND(.fnend)
 
+UNWIND(.fnstart)
+UNWIND(.pad #4)
+UNWIND(.save {lr})
+Ldiv0_64:
 	@ Division by 0:
 	str	lr, [sp, #-8]!
 	bl	__div0
@@ -200,4 +207,5 @@
 	mov	xh, #0
 	ldr	pc, [sp], #8
 
+UNWIND(.fnend)
 ENDPROC(__do_div64)
diff -druN linux-libre-3.1-gnu/arch/arm/lib/setbit.S linux-libre-3.2-gnu/arch/arm/lib/setbit.S
--- linux-libre-3.1-gnu/arch/arm/lib/setbit.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/lib/setbit.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,4 @@
 #include "bitops.h"
 		.text
 
-ENTRY(_set_bit)
-	bitop	orr
-ENDPROC(_set_bit)
+bitop	_set_bit, orr
diff -druN linux-libre-3.1-gnu/arch/arm/lib/testchangebit.S linux-libre-3.2-gnu/arch/arm/lib/testchangebit.S
--- linux-libre-3.1-gnu/arch/arm/lib/testchangebit.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/lib/testchangebit.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_change_bit)
-	testop	eor, str
-ENDPROC(_test_and_change_bit)
+testop	_test_and_change_bit, eor, str
diff -druN linux-libre-3.1-gnu/arch/arm/lib/testclearbit.S linux-libre-3.2-gnu/arch/arm/lib/testclearbit.S
--- linux-libre-3.1-gnu/arch/arm/lib/testclearbit.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/lib/testclearbit.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_clear_bit)
-	testop	bicne, strne
-ENDPROC(_test_and_clear_bit)
+testop	_test_and_clear_bit, bicne, strne
diff -druN linux-libre-3.1-gnu/arch/arm/lib/testsetbit.S linux-libre-3.2-gnu/arch/arm/lib/testsetbit.S
--- linux-libre-3.1-gnu/arch/arm/lib/testsetbit.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/lib/testsetbit.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_set_bit)
-	testop	orreq, streq
-ENDPROC(_test_and_set_bit)
+testop	_test_and_set_bit, orreq, streq
diff -druN linux-libre-3.1-gnu/arch/arm/lib/uaccess_with_memcpy.c linux-libre-3.2-gnu/arch/arm/lib/uaccess_with_memcpy.c
--- linux-libre-3.1-gnu/arch/arm/lib/uaccess_with_memcpy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/lib/uaccess_with_memcpy.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/sched.h>
 #include <linux/hardirq.h> /* for in_atomic() */
 #include <linux/gfp.h>
+#include <linux/highmem.h>
 #include <asm/current.h>
 #include <asm/page.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/at91cap9.c linux-libre-3.2-gnu/arch/arm/mach-at91/at91cap9.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/at91cap9.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/at91cap9.c	2012-01-04 18:55:44.000000000 -0500
@@ -219,6 +219,8 @@
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+	/* fake hclk clock */
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/at91cap9_devices.c linux-libre-3.2-gnu/arch/arm/mach-at91/at91cap9_devices.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/at91cap9_devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/at91cap9_devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <asm/mach/irq.h>
 
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 
@@ -23,7 +24,6 @@
 
 #include <mach/board.h>
 #include <mach/cpu.h>
-#include <mach/gpio.h>
 #include <mach/at91cap9.h>
 #include <mach/at91cap9_matrix.h>
 #include <mach/at91sam9_smc.h>
@@ -80,6 +80,12 @@
 			at91_set_gpio_output(data->vbus_pin[i], 0);
 	}
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_data = *data;
 	platform_device_register(&at91_usbh_device);
 }
@@ -92,7 +98,7 @@
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
+#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
 
 static struct resource usba_udc_resources[] = {
 	[0] = {
@@ -1015,8 +1021,8 @@
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
 	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.start	= AT91_BASE_SYS + AT91_DBGU,
+		.end	= AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -1029,7 +1035,6 @@
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/at91rm9200.c linux-libre-3.2-gnu/arch/arm/mach-at91/at91rm9200.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/at91rm9200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/at91rm9200.c	2012-01-04 18:55:44.000000000 -0500
@@ -193,6 +193,8 @@
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
+	/* fake hclk clock */
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/at91rm9200_devices.c linux-libre-3.2-gnu/arch/arm/mach-at91/at91rm9200_devices.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/at91rm9200_devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/at91rm9200_devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,11 +14,11 @@
 #include <asm/mach/map.h>
 
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91rm9200.h>
 #include <mach/at91rm9200_mc.h>
 
@@ -60,9 +60,17 @@
 
 void __init at91_add_device_usbh(struct at91_usbh_data *data)
 {
+	int i;
+
 	if (!data)
 		return;
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_data = *data;
 	platform_device_register(&at91rm9200_usbh_device);
 }
@@ -75,7 +83,7 @@
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_GADGET_AT91
+#ifdef CONFIG_USB_AT91
 static struct at91_udc_data udc_data;
 
 static struct resource udc_resources[] = {
@@ -869,8 +877,8 @@
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
 	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.start	= AT91_BASE_SYS + AT91_DBGU,
+		.end	= AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -883,7 +891,6 @@
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9260.c linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9260.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9260.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9260.c	2012-01-04 18:55:44.000000000 -0500
@@ -195,10 +195,20 @@
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
 	CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
 	CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
-	CLKDEV_CON_DEV_ID("t3_clk", "atmel_tcb.1", &tc3_clk),
-	CLKDEV_CON_DEV_ID("t4_clk", "atmel_tcb.1", &tc4_clk),
-	CLKDEV_CON_DEV_ID("t5_clk", "atmel_tcb.1", &tc5_clk),
+	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
+	CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
+	CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
+	/* more usart lookup table for DT entries */
+	CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
+	CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffb4000.serial", &usart1_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffb8000.serial", &usart2_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffd0000.serial", &usart3_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffd4000.serial", &usart4_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffd8000.serial", &usart5_clk),
+	/* fake hclk clock */
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9260_devices.c linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9260_devices.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9260_devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9260_devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,11 +13,11 @@
 #include <asm/mach/map.h>
 
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/cpu.h>
 #include <mach/at91sam9260.h>
 #include <mach/at91sam9260_matrix.h>
@@ -61,9 +61,17 @@
 
 void __init at91_add_device_usbh(struct at91_usbh_data *data)
 {
+	int i;
+
 	if (!data)
 		return;
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_data = *data;
 	platform_device_register(&at91_usbh_device);
 }
@@ -76,7 +84,7 @@
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_GADGET_AT91
+#ifdef CONFIG_USB_AT91
 static struct at91_udc_data udc_data;
 
 static struct resource udc_resources[] = {
@@ -319,7 +327,7 @@
 	if (!data)
 		return;
 
-	for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+	for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
 		if (data->slot[i].bus_width) {
 			/* input/irq */
 			if (data->slot[i].detect_pin) {
@@ -829,8 +837,8 @@
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
 	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.start	= AT91_BASE_SYS + AT91_DBGU,
+		.end	= AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -843,7 +851,6 @@
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9261.c linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9261.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9261.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9261.c	2012-01-04 18:55:44.000000000 -0500
@@ -129,6 +129,20 @@
 	.type		= CLK_TYPE_PERIPHERAL,
 };
 
+/* HClocks */
+static struct clk hck0 = {
+	.name		= "hck0",
+	.pmc_mask	= AT91_PMC_HCK0,
+	.type		= CLK_TYPE_SYSTEM,
+	.id		= 0,
+};
+static struct clk hck1 = {
+	.name		= "hck1",
+	.pmc_mask	= AT91_PMC_HCK1,
+	.type		= CLK_TYPE_SYSTEM,
+	.id		= 1,
+};
+
 static struct clk *periph_clocks[] __initdata = {
 	&pioA_clk,
 	&pioB_clk,
@@ -161,6 +175,7 @@
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
@@ -199,20 +214,6 @@
 	.id		= 3,
 };
 
-/* HClocks */
-static struct clk hck0 = {
-	.name		= "hck0",
-	.pmc_mask	= AT91_PMC_HCK0,
-	.type		= CLK_TYPE_SYSTEM,
-	.id		= 0,
-};
-static struct clk hck1 = {
-	.name		= "hck1",
-	.pmc_mask	= AT91_PMC_HCK1,
-	.type		= CLK_TYPE_SYSTEM,
-	.id		= 1,
-};
-
 static void __init at91sam9261_register_clocks(void)
 {
 	int i;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9261_devices.c linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9261_devices.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9261_devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9261_devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <asm/mach/map.h>
 
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 
@@ -21,7 +22,6 @@
 #include <video/atmel_lcdc.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9261.h>
 #include <mach/at91sam9261_matrix.h>
 #include <mach/at91sam9_smc.h>
@@ -64,9 +64,17 @@
 
 void __init at91_add_device_usbh(struct at91_usbh_data *data)
 {
+	int i;
+
 	if (!data)
 		return;
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_data = *data;
 	platform_device_register(&at91sam9261_usbh_device);
 }
@@ -79,7 +87,7 @@
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_GADGET_AT91
+#ifdef CONFIG_USB_AT91
 static struct at91_udc_data udc_data;
 
 static struct resource udc_resources[] = {
@@ -808,8 +816,8 @@
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
 	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.start	= AT91_BASE_SYS + AT91_DBGU,
+		.end	= AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -822,7 +830,6 @@
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9263.c linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9263.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9263.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9263.c	2012-01-04 18:55:44.000000000 -0500
@@ -189,6 +189,8 @@
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
+	/* fake hclk clock */
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9263_devices.c linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9263_devices.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9263_devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9263_devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <asm/mach/map.h>
 
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 
@@ -20,7 +21,6 @@
 #include <video/atmel_lcdc.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9263.h>
 #include <mach/at91sam9263_matrix.h>
 #include <mach/at91sam9_smc.h>
@@ -74,6 +74,12 @@
 			at91_set_gpio_output(data->vbus_pin[i], 0);
 	}
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_data = *data;
 	platform_device_register(&at91_usbh_device);
 }
@@ -86,7 +92,7 @@
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_GADGET_AT91
+#ifdef CONFIG_USB_AT91
 static struct at91_udc_data udc_data;
 
 static struct resource udc_resources[] = {
@@ -1190,8 +1196,8 @@
 
 static struct resource dbgu_resources[] = {
 	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.start	= AT91_BASE_SYS + AT91_DBGU,
+		.end	= AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -1204,7 +1210,6 @@
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9g45.c linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9g45.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9g45.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9g45.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 
 #include <linux/module.h>
 #include <linux/pm.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
@@ -53,6 +54,11 @@
 	.pmc_mask	= 1 << AT91SAM9G45_ID_PIODE,
 	.type		= CLK_TYPE_PERIPHERAL,
 };
+static struct clk trng_clk = {
+	.name		= "trng_clk",
+	.pmc_mask	= 1 << AT91SAM9G45_ID_TRNG,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
 static struct clk usart0_clk = {
 	.name		= "usart0_clk",
 	.pmc_mask	= 1 << AT91SAM9G45_ID_US0,
@@ -176,6 +182,7 @@
 	&pioB_clk,
 	&pioC_clk,
 	&pioDE_clk,
+	&trng_clk,
 	&usart0_clk,
 	&usart1_clk,
 	&usart2_clk,
@@ -215,6 +222,15 @@
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+	CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
+	/* more usart lookup table for DT entries */
+	CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck),
+	CLKDEV_CON_DEV_ID("usart", "fff8c000.serial", &usart0_clk),
+	CLKDEV_CON_DEV_ID("usart", "fff90000.serial", &usart1_clk),
+	CLKDEV_CON_DEV_ID("usart", "fff94000.serial", &usart2_clk),
+	CLKDEV_CON_DEV_ID("usart", "fff98000.serial", &usart3_clk),
+	/* fake hclk clock */
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
@@ -319,6 +335,7 @@
 static void __init at91sam9g45_map_io(void)
 {
 	at91_init_sram(0, AT91SAM9G45_SRAM_BASE, AT91SAM9G45_SRAM_SIZE);
+	init_consistent_dma_size(SZ_4M);
 }
 
 static void __init at91sam9g45_initialize(void)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9g45_devices.c linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9g45_devices.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9g45_devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9g45_devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <asm/mach/map.h>
 
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 #include <linux/atmel-mci.h>
@@ -21,7 +22,6 @@
 #include <video/atmel_lcdc.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9g45.h>
 #include <mach/at91sam9g45_matrix.h>
 #include <mach/at91sam9_smc.h>
@@ -124,6 +124,12 @@
 			at91_set_gpio_output(data->vbus_pin[i], 0);
 	}
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_ohci_data = *data;
 	platform_device_register(&at91_usbh_ohci_device);
 }
@@ -191,7 +197,7 @@
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
+#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
 static struct resource usba_udc_resources[] = {
 	[0] = {
 		.start	= AT91SAM9G45_UDPHS_FIFO,
@@ -1095,6 +1101,34 @@
 
 
 /* --------------------------------------------------------------------
+ *  TRNG
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_HW_RANDOM_ATMEL) || defined(CONFIG_HW_RANDOM_ATMEL_MODULE)
+static struct resource trng_resources[] = {
+	{
+		.start	= AT91SAM9G45_BASE_TRNG,
+		.end	= AT91SAM9G45_BASE_TRNG + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device at91sam9g45_trng_device = {
+	.name		= "atmel-trng",
+	.id		= -1,
+	.resource	= trng_resources,
+	.num_resources	= ARRAY_SIZE(trng_resources),
+};
+
+static void __init at91_add_device_trng(void)
+{
+	platform_device_register(&at91sam9g45_trng_device);
+}
+#else
+static void __init at91_add_device_trng(void) {}
+#endif
+
+/* --------------------------------------------------------------------
  *  Watchdog
  * -------------------------------------------------------------------- */
 
@@ -1298,8 +1332,8 @@
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
 	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.start	= AT91_BASE_SYS + AT91_DBGU,
+		.end	= AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -1312,7 +1346,6 @@
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
@@ -1583,6 +1616,7 @@
 	at91_add_device_hdmac();
 	at91_add_device_rtc();
 	at91_add_device_rtt();
+	at91_add_device_trng();
 	at91_add_device_watchdog();
 	at91_add_device_tc();
 	return 0;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9rl_devices.c linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9rl_devices.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/at91sam9rl_devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/at91sam9rl_devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <asm/mach/map.h>
 
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 
@@ -17,7 +18,6 @@
 #include <video/atmel_lcdc.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9rl.h>
 #include <mach/at91sam9rl_matrix.h>
 #include <mach/at91sam9_smc.h>
@@ -75,7 +75,7 @@
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
+#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
 
 static struct resource usba_udc_resources[] = {
 	[0] = {
@@ -908,8 +908,8 @@
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
 	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.start	= AT91_BASE_SYS + AT91_DBGU,
+		.end	= AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -922,7 +922,6 @@
 static struct atmel_uart_data dbgu_data = {
 	.use_dma_tx	= 0,
 	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-1arm.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-1arm.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-1arm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-1arm.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -34,7 +35,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/cpu.h>
 
 #include "generic.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-afeb-9260v1.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-afeb-9260v1.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-afeb-9260v1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-afeb-9260v1.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -43,7 +44,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 
 #include "generic.h"
 
@@ -130,19 +130,14 @@
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(afeb9260_nand_partition);
-	return afeb9260_nand_partition;
-}
-
 static struct atmel_nand_data __initdata afeb9260_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 	.rdy_pin	= AT91_PIN_PC13,
 	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
 	.bus_width_16	= 0,
+	.parts		= afeb9260_nand_partition,
+	.num_parts	= ARRAY_SIZE(afeb9260_nand_partition),
 };
 
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-cam60.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-cam60.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-cam60.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-cam60.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -38,7 +39,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -132,19 +132,14 @@
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(cam60_nand_partition);
-	return cam60_nand_partition;
-}
-
 static struct atmel_nand_data __initdata cam60_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 	// .det_pin	= ... not there
 	.rdy_pin	= AT91_PIN_PA9,
 	.enable_pin	= AT91_PIN_PA7,
-	.partition_info	= nand_partitions,
+	.parts		= cam60_nand_partition,
+	.num_parts	= ARRAY_SIZE(cam60_nand_partition),
 };
 
 static struct sam9_smc_config __initdata cam60_nand_smc_config = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-cap9adk.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-cap9adk.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-cap9adk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-cap9adk.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -41,7 +42,6 @@
 #include <asm/mach/map.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91cap9_matrix.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/system_rev.h>
@@ -169,19 +169,14 @@
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(cap9adk_nand_partitions);
-	return cap9adk_nand_partitions;
-}
-
 static struct atmel_nand_data __initdata cap9adk_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 //	.rdy_pin	= ... not connected
 	.enable_pin	= AT91_PIN_PD15,
-	.partition_info	= nand_partitions,
+	.parts		= cap9adk_nand_partitions,
+	.num_parts	= ARRAY_SIZE(cap9adk_nand_partitions),
 };
 
 static struct sam9_smc_config __initdata cap9adk_nand_smc_config = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-carmeva.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-carmeva.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-carmeva.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-carmeva.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -35,7 +36,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 
 #include "generic.h"
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-cpu9krea.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-cpu9krea.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-cpu9krea.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-cpu9krea.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -40,7 +41,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91sam9260_matrix.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-cpuat91.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-cpuat91.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-cpuat91.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-cpuat91.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -36,7 +37,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/cpu.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-csb337.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-csb337.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-csb337.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-csb337.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -38,7 +39,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 
 #include "generic.h"
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-csb637.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-csb637.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-csb637.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-csb637.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -35,7 +36,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 
 #include "generic.h"
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-dt.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-dt.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-dt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-dt.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,123 @@
+/*
+ *  Setup code for AT91SAM Evaluation Kits with Device Tree support
+ *
+ *  Covers: * AT91SAM9G45-EKES  board
+ *          * AT91SAM9M10-EKES  board
+ *          * AT91SAM9M10G45-EK board
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+#include <mach/system_rev.h>
+#include <mach/at91sam9_smc.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include "sam9_smc.h"
+#include "generic.h"
+
+
+static void __init ek_init_early(void)
+{
+	/* Initialize processor: 12.000 MHz crystal */
+	at91_initialize(12000000);
+
+	/* DGBU on ttyS0. (Rx & Tx only) */
+	at91_register_uart(0, 0, 0);
+
+	/* set serial console to ttyS0 (ie, DBGU) */
+	at91_set_serial_console(0);
+}
+
+/* det_pin is not connected */
+static struct atmel_nand_data __initdata ek_nand_data = {
+	.ale		= 21,
+	.cle		= 22,
+	.rdy_pin	= AT91_PIN_PC8,
+	.enable_pin	= AT91_PIN_PC14,
+};
+
+static struct sam9_smc_config __initdata ek_nand_smc_config = {
+	.ncs_read_setup		= 0,
+	.nrd_setup		= 2,
+	.ncs_write_setup	= 0,
+	.nwe_setup		= 2,
+
+	.ncs_read_pulse		= 4,
+	.nrd_pulse		= 4,
+	.ncs_write_pulse	= 4,
+	.nwe_pulse		= 4,
+
+	.read_cycle		= 7,
+	.write_cycle		= 7,
+
+	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
+	.tdf_cycles		= 3,
+};
+
+static void __init ek_add_device_nand(void)
+{
+	ek_nand_data.bus_width_16 = board_have_nand_16bit();
+	/* setup bus-width (8 or 16) */
+	if (ek_nand_data.bus_width_16)
+		ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
+	else
+		ek_nand_smc_config.mode |= AT91_SMC_DBW_8;
+
+	/* configure chip-select 3 (NAND) */
+	sam9_smc_configure(3, &ek_nand_smc_config);
+
+	at91_add_device_nand(&ek_nand_data);
+}
+
+static const struct of_device_id aic_of_match[] __initconst = {
+	{ .compatible = "atmel,at91rm9200-aic", },
+	{},
+};
+
+static void __init at91_dt_init_irq(void)
+{
+	irq_domain_generate_simple(aic_of_match, 0xfffff000, 0);
+	at91_init_irq_default();
+}
+
+static void __init at91_dt_device_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+	/* NAND */
+	ek_add_device_nand();
+}
+
+static const char *at91_dt_board_compat[] __initdata = {
+	"atmel,at91sam9m10g45ek",
+	"calao,usb-a9g20",
+	NULL
+};
+
+DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
+	/* Maintainer: Atmel */
+	.timer		= &at91sam926x_timer,
+	.map_io		= at91_map_io,
+	.init_early	= ek_init_early,
+	.init_irq	= at91_dt_init_irq,
+	.init_machine	= at91_dt_device_init,
+	.dt_compat	= at91_dt_board_compat,
+MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-eb9200.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-eb9200.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-eb9200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-eb9200.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -35,7 +36,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 
 #include "generic.h"
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-ecbat91.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-ecbat91.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-ecbat91.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-ecbat91.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -37,7 +38,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/cpu.h>
 
 #include "generic.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-kafa.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-kafa.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-kafa.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-kafa.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -34,7 +35,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/cpu.h>
 
 #include "generic.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-kb9202.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-kb9202.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-kb9202.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-kb9202.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -35,7 +36,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/cpu.h>
 #include <mach/at91rm9200_mc.h>
 
@@ -97,19 +97,14 @@
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(kb9202_nand_partition);
-	return kb9202_nand_partition;
-}
-
 static struct atmel_nand_data __initdata kb9202_nand_data = {
 	.ale		= 22,
 	.cle		= 21,
 	// .det_pin	= ... not there
 	.rdy_pin	= AT91_PIN_PC29,
 	.enable_pin	= AT91_PIN_PC28,
-	.partition_info	= nand_partitions,
+	.parts		= kb9202_nand_partition,
+	.num_parts	= ARRAY_SIZE(kb9202_nand_partition),
 };
 
 static void __init kb9202_board_init(void)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-neocore926.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-neocore926.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-neocore926.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-neocore926.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -44,7 +45,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -182,19 +182,14 @@
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(neocore926_nand_partition);
-	return neocore926_nand_partition;
-}
-
 static struct atmel_nand_data __initdata neocore926_nand_data = {
 	.ale			= 21,
 	.cle			= 22,
 	.rdy_pin		= AT91_PIN_PB19,
 	.rdy_pin_active_low	= 1,
 	.enable_pin		= AT91_PIN_PD15,
-	.partition_info		= nand_partitions,
+	.parts			= neocore926_nand_partition,
+	.num_parts		= ARRAY_SIZE(neocore926_nand_partition),
 };
 
 static struct sam9_smc_config __initdata neocore926_nand_smc_config = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-picotux200.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-picotux200.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-picotux200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-picotux200.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -37,7 +38,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91rm9200_mc.h>
 
 #include "generic.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-qil-a9260.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-qil-a9260.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-qil-a9260.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-qil-a9260.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -40,7 +41,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 
@@ -130,19 +130,14 @@
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PC13,
 	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-rm9200dk.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-rm9200dk.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-rm9200dk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-rm9200dk.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -39,7 +40,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91rm9200_mc.h>
 
 #include "generic.h"
@@ -138,19 +138,14 @@
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(dk_nand_partition);
-	return dk_nand_partition;
-}
-
 static struct atmel_nand_data __initdata dk_nand_data = {
 	.ale		= 22,
 	.cle		= 21,
 	.det_pin	= AT91_PIN_PB1,
 	.rdy_pin	= AT91_PIN_PC2,
 	// .enable_pin	= ... not there
-	.partition_info	= nand_partitions,
+	.parts		= dk_nand_partition,
+	.num_parts	= ARRAY_SIZE(dk_nand_partition),
 };
 
 #define DK_FLASH_BASE	AT91_CHIPSELECT_0
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-rm9200ek.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-rm9200ek.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-rm9200ek.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-rm9200ek.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -39,7 +40,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91rm9200_mc.h>
 
 #include "generic.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-rsi-ews.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-rsi-ews.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-rsi-ews.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-rsi-ews.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,233 @@
+/*
+ * board-rsi-ews.c
+ *
+ *  Copyright (C)
+ *  2005 SAN People,
+ *  2008-2011 R-S-I Elektrotechnik GmbH & Co. KG
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+
+#include <linux/gpio.h>
+
+#include "generic.h"
+
+static void __init rsi_ews_init_early(void)
+{
+	/* Initialize processor: 18.432 MHz crystal */
+	at91_initialize(18432000);
+
+	/* Setup the LEDs */
+	at91_init_leds(AT91_PIN_PB6, AT91_PIN_PB9);
+
+	/* DBGU on ttyS0. (Rx & Tx only) */
+	/* This one is for debugging */
+	at91_register_uart(0, 0, 0);
+
+	/* USART1 on ttyS2. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+	/* Dialin/-out modem interface */
+	at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
+			   | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+			   | ATMEL_UART_RI);
+
+	/* USART3 on ttyS4. (Rx, Tx, RTS) */
+	/* RS485 communication */
+	at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_RTS);
+
+	/* set serial console to ttyS0 (ie, DBGU) */
+	at91_set_serial_console(0);
+}
+
+/*
+ * Ethernet
+ */
+static struct at91_eth_data rsi_ews_eth_data __initdata = {
+	.phy_irq_pin	= AT91_PIN_PC4,
+	.is_rmii	= 1,
+};
+
+/*
+ * USB Host
+ */
+static struct at91_usbh_data rsi_ews_usbh_data __initdata = {
+	.ports		= 1,
+};
+
+/*
+ * SD/MC
+ */
+static struct at91_mmc_data rsi_ews_mmc_data __initdata = {
+	.slot_b		= 0,
+	.wire4		= 1,
+	.det_pin	= AT91_PIN_PB27,
+	.wp_pin		= AT91_PIN_PB29,
+};
+
+/*
+ * I2C
+ */
+static struct i2c_board_info rsi_ews_i2c_devices[] __initdata = {
+	{
+		I2C_BOARD_INFO("ds1337", 0x68),
+	},
+	{
+		I2C_BOARD_INFO("24c01", 0x50),
+	}
+};
+
+/*
+ * LEDs
+ */
+static struct gpio_led rsi_ews_leds[] = {
+	{
+		.name			= "led0",
+		.gpio			= AT91_PIN_PB6,
+		.active_low		= 0,
+	},
+	{
+		.name			= "led1",
+		.gpio			= AT91_PIN_PB7,
+		.active_low		= 0,
+	},
+	{
+		.name			= "led2",
+		.gpio			= AT91_PIN_PB8,
+		.active_low		= 0,
+	},
+	{
+		.name			= "led3",
+		.gpio			= AT91_PIN_PB9,
+		.active_low		= 0,
+	},
+};
+
+/*
+ * DataFlash
+ */
+static struct spi_board_info rsi_ews_spi_devices[] = {
+	{	/* DataFlash chip 1*/
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 0,
+		.max_speed_hz	= 5 * 1000 * 1000,
+	},
+	{	/* DataFlash chip 2*/
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 1,
+		.max_speed_hz	= 5 * 1000 * 1000,
+	},
+};
+
+/*
+ * NOR flash
+ */
+static struct mtd_partition rsiews_nor_partitions[] = {
+	{
+		.name		= "boot",
+		.offset		= 0,
+		.size		= 3 * SZ_128K,
+		.mask_flags	= MTD_WRITEABLE
+	},
+	{
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= SZ_2M - (3 * SZ_128K)
+	},
+	{
+		.name		= "root",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= SZ_8M
+	},
+	{
+		.name		= "kernelupd",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= 3 * SZ_512K,
+		.mask_flags	= MTD_WRITEABLE
+	},
+	{
+		.name		= "rootupd",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= 9 * SZ_512K,
+		.mask_flags	= MTD_WRITEABLE
+	},
+};
+
+static struct physmap_flash_data rsiews_nor_data = {
+	.width		= 2,
+	.parts		= rsiews_nor_partitions,
+	.nr_parts	= ARRAY_SIZE(rsiews_nor_partitions),
+};
+
+#define NOR_BASE	AT91_CHIPSELECT_0
+#define NOR_SIZE	SZ_16M
+
+static struct resource nor_flash_resources[] = {
+	{
+		.start	= NOR_BASE,
+		.end	= NOR_BASE + NOR_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device rsiews_nor_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+				.platform_data	= &rsiews_nor_data,
+	},
+	.resource	= nor_flash_resources,
+	.num_resources	= ARRAY_SIZE(nor_flash_resources),
+};
+
+/*
+ * Init Func
+ */
+static void __init rsi_ews_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	at91_set_gpio_output(AT91_PIN_PA21, 0);
+	/* Ethernet */
+	at91_add_device_eth(&rsi_ews_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&rsi_ews_usbh_data);
+	/* I2C */
+	at91_add_device_i2c(rsi_ews_i2c_devices,
+			ARRAY_SIZE(rsi_ews_i2c_devices));
+	/* SPI */
+	at91_add_device_spi(rsi_ews_spi_devices,
+			ARRAY_SIZE(rsi_ews_spi_devices));
+	/* MMC */
+	at91_add_device_mmc(0, &rsi_ews_mmc_data);
+	/* NOR Flash */
+	platform_device_register(&rsiews_nor_flash);
+	/* LEDs */
+	at91_gpio_leds(rsi_ews_leds, ARRAY_SIZE(rsi_ews_leds));
+}
+
+MACHINE_START(RSI_EWS, "RSI EWS")
+	/* Maintainer: Josef Holzmayr <holzmayr@rsi-elektrotechnik.de> */
+	.timer		= &at91rm9200_timer,
+	.map_io		= at91_map_io,
+	.init_early	= rsi_ews_init_early,
+	.init_irq	= at91_init_irq_default,
+	.init_machine	= rsi_ews_board_init,
+MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-sam9260ek.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-sam9260ek.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-sam9260ek.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-sam9260ek.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -41,7 +42,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
@@ -173,19 +173,14 @@
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PC13,
 	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-sam9261ek.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-sam9261ek.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-sam9261ek.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-sam9261ek.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -45,7 +46,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
@@ -179,19 +179,14 @@
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 22,
 	.cle		= 21,
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PC15,
 	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-sam9263ek.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-sam9263ek.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-sam9263ek.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-sam9263ek.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -44,7 +45,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
@@ -180,19 +180,14 @@
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PA22,
 	.enable_pin	= AT91_PIN_PD15,
-	.partition_info	= nand_partitions,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-sam9g20ek.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-sam9g20ek.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-sam9g20ek.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-sam9g20ek.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -41,7 +42,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/system_rev.h>
 
@@ -157,19 +157,14 @@
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
 /* det_pin is not connected */
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 	.rdy_pin	= AT91_PIN_PC13,
 	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-sam9-l9260.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-sam9-l9260.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-sam9-l9260.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-sam9-l9260.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -37,7 +38,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -131,19 +131,14 @@
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PC13,
 	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-sam9m10g45ek.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-sam9m10g45ek.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-sam9m10g45ek.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-sam9m10g45ek.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -38,7 +39,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
@@ -137,19 +137,14 @@
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
 /* det_pin is not connected */
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 	.rdy_pin	= AT91_PIN_PC8,
 	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-sam9rlek.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-sam9rlek.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-sam9rlek.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-sam9rlek.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -30,7 +31,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 
@@ -88,19 +88,14 @@
 	},
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PD17,
 	.enable_pin	= AT91_PIN_PB6,
-	.partition_info	= nand_partitions,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
 };
 
 static struct sam9_smc_config __initdata ek_nand_smc_config = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-snapper9260.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-snapper9260.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-snapper9260.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-snapper9260.c	2012-01-04 18:55:44.000000000 -0500
@@ -97,18 +97,12 @@
 	},
 };
 
-static struct mtd_partition * __init
-snapper9260_nand_partition_info(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(snapper9260_nand_partitions);
-	return snapper9260_nand_partitions;
-}
-
 static struct atmel_nand_data __initdata snapper9260_nand_data = {
 	.ale		= 21,
 	.cle		= 22,
 	.rdy_pin	= AT91_PIN_PC13,
-	.partition_info	= snapper9260_nand_partition_info,
+	.parts		= snapper9260_nand_partitions,
+	.num_parts	= ARRAY_SIZE(snapper9260_nand_partitions),
 	.bus_width_16	= 0,
 };
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-usb-a9260.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-usb-a9260.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-usb-a9260.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-usb-a9260.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,230 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-usb-a9260.c
- *
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2006 Atmel
- *  Copyright (C) 2007 Calao-systems
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/clk.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/gpio.h>
-#include <mach/at91sam9_smc.h>
-#include <mach/at91_shdwc.h>
-
-#include "sam9_smc.h"
-#include "generic.h"
-
-
-static void __init ek_init_early(void)
-{
-	/* Initialize processor: 12.000 MHz crystal */
-	at91_initialize(12000000);
-
-	/* DBGU on ttyS0. (Rx & Tx only) */
-	at91_register_uart(0, 0, 0);
-
-	/* set serial console to ttyS0 (ie, DBGU) */
-	at91_set_serial_console(0);
-}
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
-	.ports		= 2,
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
-	.vbus_pin	= AT91_PIN_PC5,
-	.pullup_pin	= 0,		/* pull-up driven by UDC */
-};
-
-/*
- * MACB Ethernet device
- */
-static struct at91_eth_data __initdata ek_macb_data = {
-	.phy_irq_pin	= AT91_PIN_PA31,
-	.is_rmii	= 1,
-};
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-	{
-		.name	= "Uboot & Kernel",
-		.offset	= 0,
-		.size	= SZ_16M,
-	},
-	{
-		.name	= "Root FS",
-		.offset	= MTDPART_OFS_NXTBLK,
-		.size	= 120 * SZ_1M,
-	},
-	{
-		.name	= "FS",
-		.offset	= MTDPART_OFS_NXTBLK,
-		.size	= 120 * SZ_1M,
-	}
-};
-
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
-static struct atmel_nand_data __initdata ek_nand_data = {
-	.ale		= 21,
-	.cle		= 22,
-//	.det_pin	= ... not connected
-	.rdy_pin	= AT91_PIN_PC13,
-	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
-	.ncs_read_setup		= 0,
-	.nrd_setup		= 1,
-	.ncs_write_setup	= 0,
-	.nwe_setup		= 1,
-
-	.ncs_read_pulse		= 3,
-	.nrd_pulse		= 3,
-	.ncs_write_pulse	= 3,
-	.nwe_pulse		= 3,
-
-	.read_cycle		= 5,
-	.write_cycle		= 5,
-
-	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
-	.tdf_cycles		= 2,
-};
-
-static void __init ek_add_device_nand(void)
-{
-	/* configure chip-select 3 (NAND) */
-	sam9_smc_configure(3, &ek_nand_smc_config);
-
-	at91_add_device_nand(&ek_nand_data);
-}
-
-/*
- * GPIO Buttons
- */
-
-#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-static struct gpio_keys_button ek_buttons[] = {
-	{	/* USER PUSH BUTTON */
-		.code		= KEY_ENTER,
-		.gpio		= AT91_PIN_PB10,
-		.active_low	= 1,
-		.desc		= "user_pb",
-		.wakeup		= 1,
-	}
-};
-
-static struct gpio_keys_platform_data ek_button_data = {
-	.buttons	= ek_buttons,
-	.nbuttons	= ARRAY_SIZE(ek_buttons),
-};
-
-static struct platform_device ek_button_device = {
-	.name		= "gpio-keys",
-	.id		= -1,
-	.num_resources	= 0,
-	.dev		= {
-		.platform_data	= &ek_button_data,
-	}
-};
-
-static void __init ek_add_device_buttons(void)
-{
-	at91_set_GPIO_periph(AT91_PIN_PB10, 1);	/* user push button, pull up enabled */
-	at91_set_deglitch(AT91_PIN_PB10, 1);
-
-	platform_device_register(&ek_button_device);
-}
-#else
-static void __init ek_add_device_buttons(void) {}
-#endif
-
-/*
- * LEDs
- */
-static struct gpio_led ek_leds[] = {
-	{	/* user_led (green) */
-		.name			= "user_led",
-		.gpio			= AT91_PIN_PB21,
-		.active_low		= 0,
-		.default_trigger	= "heartbeat",
-	}
-};
-
-static void __init ek_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&ek_udc_data);
-	/* NAND */
-	ek_add_device_nand();
-	/* I2C */
-	at91_add_device_i2c(NULL, 0);
-	/* Ethernet */
-	at91_add_device_eth(&ek_macb_data);
-	/* Push Buttons */
-	ek_add_device_buttons();
-	/* LEDs */
-	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-	/* shutdown controller, wakeup button (5 msec low) */
-	at91_sys_write(AT91_SHDW_MR, AT91_SHDW_CPTWK0_(10) | AT91_SHDW_WKMODE0_LOW
-				| AT91_SHDW_RTTWKEN);
-}
-
-MACHINE_START(USB_A9260, "CALAO USB_A9260")
-	/* Maintainer: calao-systems */
-	.timer		= &at91sam926x_timer,
-	.map_io		= at91_map_io,
-	.init_early	= ek_init_early,
-	.init_irq	= at91_init_irq_default,
-	.init_machine	= ek_board_init,
-MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-usb-a9263.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-usb-a9263.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-usb-a9263.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-usb-a9263.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,246 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-usb-a9263.c
- *
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2007 Atmel Corporation.
- *  Copyright (C) 2007 Calao-systems
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/gpio.h>
-#include <mach/at91sam9_smc.h>
-#include <mach/at91_shdwc.h>
-
-#include "sam9_smc.h"
-#include "generic.h"
-
-
-static void __init ek_init_early(void)
-{
-	/* Initialize processor: 12.00 MHz crystal */
-	at91_initialize(12000000);
-
-	/* DBGU on ttyS0. (Rx & Tx only) */
-	at91_register_uart(0, 0, 0);
-
-	/* set serial console to ttyS0 (ie, DBGU) */
-	at91_set_serial_console(0);
-}
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
-	.ports		= 2,
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
-	.vbus_pin	= AT91_PIN_PB11,
-	.pullup_pin	= 0,		/* pull-up driven by UDC */
-};
-
-/*
- * SPI devices.
- */
-static struct spi_board_info ek_spi_devices[] = {
-#if !defined(CONFIG_MMC_AT91)
-	{	/* DataFlash chip */
-		.modalias	= "mtd_dataflash",
-		.chip_select	= 0,
-		.max_speed_hz	= 15 * 1000 * 1000,
-		.bus_num	= 0,
-	}
-#endif
-};
-
-/*
- * MACB Ethernet device
- */
-static struct at91_eth_data __initdata ek_macb_data = {
-	.phy_irq_pin	= AT91_PIN_PE31,
-	.is_rmii	= 1,
-};
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-	{
-		.name	= "Linux Kernel",
-		.offset	= 0,
-		.size	= SZ_16M,
-	},
-	{
-		.name	= "Root FS",
-		.offset	= MTDPART_OFS_NXTBLK,
-		.size	= 120 * SZ_1M,
-	},
-	{
-		.name	= "FS",
-		.offset	= MTDPART_OFS_NXTBLK,
-		.size	= 120 * SZ_1M,
-	}
-};
-
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
-static struct atmel_nand_data __initdata ek_nand_data = {
-	.ale		= 21,
-	.cle		= 22,
-//	.det_pin	= ... not connected
-	.rdy_pin	= AT91_PIN_PA22,
-	.enable_pin	= AT91_PIN_PD15,
-	.partition_info	= nand_partitions,
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
-	.ncs_read_setup		= 0,
-	.nrd_setup		= 1,
-	.ncs_write_setup	= 0,
-	.nwe_setup		= 1,
-
-	.ncs_read_pulse		= 3,
-	.nrd_pulse		= 3,
-	.ncs_write_pulse	= 3,
-	.nwe_pulse		= 3,
-
-	.read_cycle		= 5,
-	.write_cycle		= 5,
-
-	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
-	.tdf_cycles		= 2,
-};
-
-static void __init ek_add_device_nand(void)
-{
-	/* configure chip-select 3 (NAND) */
-	sam9_smc_configure(3, &ek_nand_smc_config);
-
-	at91_add_device_nand(&ek_nand_data);
-}
-
-
-/*
- * GPIO Buttons
- */
-#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-static struct gpio_keys_button ek_buttons[] = {
-	{	/* USER PUSH BUTTON */
-		.code		= KEY_ENTER,
-		.gpio		= AT91_PIN_PB10,
-		.active_low	= 1,
-		.desc		= "user_pb",
-		.wakeup		= 1,
-	}
-};
-
-static struct gpio_keys_platform_data ek_button_data = {
-	.buttons	= ek_buttons,
-	.nbuttons	= ARRAY_SIZE(ek_buttons),
-};
-
-static struct platform_device ek_button_device = {
-	.name		= "gpio-keys",
-	.id		= -1,
-	.num_resources	= 0,
-	.dev		= {
-		.platform_data	= &ek_button_data,
-	}
-};
-
-static void __init ek_add_device_buttons(void)
-{
-	at91_set_GPIO_periph(AT91_PIN_PB10, 1);	/* user push button, pull up enabled */
-	at91_set_deglitch(AT91_PIN_PB10, 1);
-
-	platform_device_register(&ek_button_device);
-}
-#else
-static void __init ek_add_device_buttons(void) {}
-#endif
-
-/*
- * LEDs
- */
-static struct gpio_led ek_leds[] = {
-	{	/* user_led (green) */
-		.name			= "user_led",
-		.gpio			= AT91_PIN_PB21,
-		.active_low		= 1,
-		.default_trigger	= "heartbeat",
-	}
-};
-
-
-static void __init ek_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&ek_udc_data);
-	/* SPI */
-	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
-	/* Ethernet */
-	at91_add_device_eth(&ek_macb_data);
-	/* NAND */
-	ek_add_device_nand();
-	/* I2C */
-	at91_add_device_i2c(NULL, 0);
-	/* Push Buttons */
-	ek_add_device_buttons();
-	/* LEDs */
-	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-	/* shutdown controller, wakeup button (5 msec low) */
-	at91_sys_write(AT91_SHDW_MR, AT91_SHDW_CPTWK0_(10) | AT91_SHDW_WKMODE0_LOW
-				| AT91_SHDW_RTTWKEN);
-}
-
-MACHINE_START(USB_A9263, "CALAO USB_A9263")
-	/* Maintainer: calao-systems */
-	.timer		= &at91sam926x_timer,
-	.map_io		= at91_map_io,
-	.init_early	= ek_init_early,
-	.init_irq	= at91_init_irq_default,
-	.init_machine	= ek_board_init,
-MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-usb-a926x.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-usb-a926x.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-usb-a926x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-usb-a926x.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,378 @@
+/*
+ * linux/arch/arm/mach-at91/board-usb-a926x.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *  Copyright (C) 2007 Atmel Corporation.
+ *  Copyright (C) 2007 Calao-systems
+ *  Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/spi/mmc_spi.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+#include <mach/at91sam9_smc.h>
+#include <mach/at91_shdwc.h>
+
+#include "sam9_smc.h"
+#include "generic.h"
+
+
+static void __init ek_init_early(void)
+{
+	/* Initialize processor: 12.00 MHz crystal */
+	at91_initialize(12000000);
+
+	/* DBGU on ttyS0. (Rx & Tx only) */
+	at91_register_uart(0, 0, 0);
+
+	/* set serial console to ttyS0 (ie, DBGU) */
+	at91_set_serial_console(0);
+}
+
+/*
+ * USB Host port
+ */
+static struct at91_usbh_data __initdata ek_usbh_data = {
+	.ports		= 2,
+};
+
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata ek_udc_data = {
+	.vbus_pin	= AT91_PIN_PB11,
+	.pullup_pin	= 0,		/* pull-up driven by UDC */
+};
+
+static void __init ek_add_device_udc(void)
+{
+	if (machine_is_usb_a9260() || machine_is_usb_a9g20())
+		ek_udc_data.vbus_pin = AT91_PIN_PC5;
+
+	at91_add_device_udc(&ek_udc_data);
+}
+
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+#define MMC_SPI_CARD_DETECT_INT AT91_PIN_PC4
+static int at91_mmc_spi_init(struct device *dev,
+	irqreturn_t (*detect_int)(int, void *), void *data)
+{
+	/* Configure Interrupt pin as input, no pull-up */
+	at91_set_gpio_input(MMC_SPI_CARD_DETECT_INT, 0);
+	return request_irq(gpio_to_irq(MMC_SPI_CARD_DETECT_INT), detect_int,
+		IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+		"mmc-spi-detect", data);
+}
+
+static void at91_mmc_spi_exit(struct device *dev, void *data)
+{
+	free_irq(gpio_to_irq(MMC_SPI_CARD_DETECT_INT), data);
+}
+
+static struct mmc_spi_platform_data at91_mmc_spi_pdata = {
+	.init = at91_mmc_spi_init,
+	.exit = at91_mmc_spi_exit,
+	.detect_delay = 100, /* msecs */
+};
+#endif
+
+/*
+ * SPI devices.
+ */
+static struct spi_board_info usb_a9263_spi_devices[] = {
+#if !defined(CONFIG_MMC_AT91)
+	{	/* DataFlash chip */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 0,
+		.max_speed_hz	= 15 * 1000 * 1000,
+		.bus_num	= 0,
+	}
+#endif
+};
+
+static struct spi_board_info usb_a9g20_spi_devices[] = {
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+	{
+		.modalias = "mmc_spi",
+		.max_speed_hz = 20000000,	/* max spi clock (SCK) speed in HZ */
+		.bus_num = 1,
+		.chip_select = 0,
+		.platform_data = &at91_mmc_spi_pdata,
+		.mode = SPI_MODE_3,
+	},
+#endif
+};
+
+static void __init ek_add_device_spi(void)
+{
+	if (machine_is_usb_a9263())
+		at91_add_device_spi(usb_a9263_spi_devices, ARRAY_SIZE(usb_a9263_spi_devices));
+	else if (machine_is_usb_a9g20())
+		at91_add_device_spi(usb_a9g20_spi_devices, ARRAY_SIZE(usb_a9g20_spi_devices));
+}
+
+/*
+ * MACB Ethernet device
+ */
+static struct at91_eth_data __initdata ek_macb_data = {
+	.phy_irq_pin	= AT91_PIN_PE31,
+	.is_rmii	= 1,
+};
+
+static void __init ek_add_device_eth(void)
+{
+	if (machine_is_usb_a9260() || machine_is_usb_a9g20())
+		ek_macb_data.phy_irq_pin = AT91_PIN_PA31;
+
+	at91_add_device_eth(&ek_macb_data);
+}
+
+/*
+ * NAND flash
+ */
+static struct mtd_partition __initdata ek_nand_partition[] = {
+	{
+		.name	= "barebox",
+		.offset	= 0,
+		.size	= 3 * SZ_128K,
+	}, {
+		.name	= "bareboxenv",
+		.offset	= MTDPART_OFS_NXTBLK,
+		.size	= SZ_128K,
+	}, {
+		.name	= "bareboxenv2",
+		.offset	= MTDPART_OFS_NXTBLK,
+		.size	= SZ_128K,
+	}, {
+		.name	= "kernel",
+		.offset	= MTDPART_OFS_NXTBLK,
+		.size	= 4 * SZ_1M,
+	}, {
+		.name	= "rootfs",
+		.offset	= MTDPART_OFS_NXTBLK,
+		.size	= 120 * SZ_1M,
+	}, {
+		.name	= "data",
+		.offset	= MTDPART_OFS_NXTBLK,
+		.size	= MTDPART_SIZ_FULL,
+	}
+};
+
+static struct atmel_nand_data __initdata ek_nand_data = {
+	.ale		= 21,
+	.cle		= 22,
+//	.det_pin	= ... not connected
+	.rdy_pin	= AT91_PIN_PA22,
+	.enable_pin	= AT91_PIN_PD15,
+	.parts		= ek_nand_partition,
+	.num_parts	= ARRAY_SIZE(ek_nand_partition),
+};
+
+static struct sam9_smc_config __initdata usb_a9260_nand_smc_config = {
+	.ncs_read_setup		= 0,
+	.nrd_setup		= 1,
+	.ncs_write_setup	= 0,
+	.nwe_setup		= 1,
+
+	.ncs_read_pulse		= 3,
+	.nrd_pulse		= 3,
+	.ncs_write_pulse	= 3,
+	.nwe_pulse		= 3,
+
+	.read_cycle		= 5,
+	.write_cycle		= 5,
+
+	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
+	.tdf_cycles		= 2,
+};
+
+static struct sam9_smc_config __initdata usb_a9g20_nand_smc_config = {
+	.ncs_read_setup		= 0,
+	.nrd_setup		= 2,
+	.ncs_write_setup	= 0,
+	.nwe_setup		= 2,
+
+	.ncs_read_pulse		= 4,
+	.nrd_pulse		= 4,
+	.ncs_write_pulse	= 4,
+	.nwe_pulse		= 4,
+
+	.read_cycle		= 7,
+	.write_cycle		= 7,
+
+	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
+	.tdf_cycles		= 3,
+};
+
+static void __init ek_add_device_nand(void)
+{
+	if (machine_is_usb_a9260() || machine_is_usb_a9g20()) {
+		ek_nand_data.rdy_pin	= AT91_PIN_PC13;
+		ek_nand_data.enable_pin	= AT91_PIN_PC14;
+	}
+
+	/* configure chip-select 3 (NAND) */
+	if (machine_is_usb_a9g20())
+		sam9_smc_configure(3, &usb_a9g20_nand_smc_config);
+	else
+		sam9_smc_configure(3, &usb_a9260_nand_smc_config);
+
+	at91_add_device_nand(&ek_nand_data);
+}
+
+
+/*
+ * GPIO Buttons
+ */
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+static struct gpio_keys_button ek_buttons[] = {
+	{	/* USER PUSH BUTTON */
+		.code		= KEY_ENTER,
+		.gpio		= AT91_PIN_PB10,
+		.active_low	= 1,
+		.desc		= "user_pb",
+		.wakeup		= 1,
+	}
+};
+
+static struct gpio_keys_platform_data ek_button_data = {
+	.buttons	= ek_buttons,
+	.nbuttons	= ARRAY_SIZE(ek_buttons),
+};
+
+static struct platform_device ek_button_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.num_resources	= 0,
+	.dev		= {
+		.platform_data	= &ek_button_data,
+	}
+};
+
+static void __init ek_add_device_buttons(void)
+{
+	at91_set_GPIO_periph(AT91_PIN_PB10, 1);	/* user push button, pull up enabled */
+	at91_set_deglitch(AT91_PIN_PB10, 1);
+
+	platform_device_register(&ek_button_device);
+}
+#else
+static void __init ek_add_device_buttons(void) {}
+#endif
+
+/*
+ * LEDs
+ */
+static struct gpio_led ek_leds[] = {
+	{	/* user_led (green) */
+		.name			= "user_led",
+		.gpio			= AT91_PIN_PB21,
+		.active_low		= 1,
+		.default_trigger	= "heartbeat",
+	}
+};
+
+static struct i2c_board_info __initdata ek_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("rv3029c2", 0x56),
+	},
+};
+
+static void __init ek_add_device_leds(void)
+{
+	if (machine_is_usb_a9260() || machine_is_usb_a9g20())
+		ek_leds[0].active_low = 0;
+
+	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+}
+
+static void __init ek_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* USB Host */
+	at91_add_device_usbh(&ek_usbh_data);
+	/* USB Device */
+	ek_add_device_udc();
+	/* SPI */
+	ek_add_device_spi();
+	/* Ethernet */
+	ek_add_device_eth();
+	/* NAND */
+	ek_add_device_nand();
+	/* Push Buttons */
+	ek_add_device_buttons();
+	/* LEDs */
+	ek_add_device_leds();
+
+	if (machine_is_usb_a9g20()) {
+		/* I2C */
+		at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
+	} else {
+		/* I2C */
+		at91_add_device_i2c(NULL, 0);
+		/* shutdown controller, wakeup button (5 msec low) */
+		at91_sys_write(AT91_SHDW_MR, AT91_SHDW_CPTWK0_(10)
+				| AT91_SHDW_WKMODE0_LOW
+				| AT91_SHDW_RTTWKEN);
+	}
+}
+
+MACHINE_START(USB_A9263, "CALAO USB_A9263")
+	/* Maintainer: calao-systems */
+	.timer		= &at91sam926x_timer,
+	.map_io		= at91_map_io,
+	.init_early	= ek_init_early,
+	.init_irq	= at91_init_irq_default,
+	.init_machine	= ek_board_init,
+MACHINE_END
+
+MACHINE_START(USB_A9260, "CALAO USB_A9260")
+	/* Maintainer: calao-systems */
+	.timer		= &at91sam926x_timer,
+	.map_io		= at91_map_io,
+	.init_early	= ek_init_early,
+	.init_irq	= at91_init_irq_default,
+	.init_machine	= ek_board_init,
+MACHINE_END
+
+MACHINE_START(USB_A9G20, "CALAO USB_A92G0")
+	/* Maintainer: Jean-Christophe PLAGNIOL-VILLARD */
+	.timer		= &at91sam926x_timer,
+	.map_io		= at91_map_io,
+	.init_early	= ek_init_early,
+	.init_irq	= at91_init_irq_default,
+	.init_machine	= ek_board_init,
+MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/board-yl-9200.c linux-libre-3.2-gnu/arch/arm/mach-at91/board-yl-9200.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/board-yl-9200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/board-yl-9200.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/module.h>
@@ -43,7 +44,6 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/cpu.h>
 
@@ -172,19 +172,14 @@
 	}
 };
 
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(yl9200_nand_partition);
-	return yl9200_nand_partition;
-}
-
 static struct atmel_nand_data __initdata yl9200_nand_data = {
 	.ale		= 6,
 	.cle		= 7,
 	// .det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PC14,	/* R/!B (Sheet10) */
 	.enable_pin	= AT91_PIN_PC15,	/* !CE  (Sheet10) */
-	.partition_info	= nand_partitions,
+	.parts		= yl9200_nand_partition,
+	.num_parts	= ARRAY_SIZE(yl9200_nand_partition),
 };
 
 /*
@@ -389,7 +384,7 @@
 #include <video/s1d13xxxfb.h>
 
 
-static void __init yl9200_init_video(void)
+static void yl9200_init_video(void)
 {
 	/* NWAIT Signal */
 	at91_set_A_periph(AT91_PIN_PC6, 0);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/cpuidle.c linux-libre-3.2-gnu/arch/arm/mach-at91/cpuidle.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/cpuidle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/cpuidle.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/cpuidle.h>
 #include <asm/proc-fns.h>
 #include <linux/io.h>
+#include <linux/export.h>
 
 #include "pm.h"
 
@@ -33,7 +34,8 @@
 
 /* Actual code that puts the SoC in different idle states */
 static int at91_enter_idle(struct cpuidle_device *dev,
-			       struct cpuidle_state *state)
+			struct cpuidle_driver *drv,
+			       int index)
 {
 	struct timeval before, after;
 	int idle_time;
@@ -41,10 +43,10 @@
 
 	local_irq_disable();
 	do_gettimeofday(&before);
-	if (state == &dev->states[0])
+	if (index == 0)
 		/* Wait for interrupt state */
 		cpu_do_idle();
-	else if (state == &dev->states[1]) {
+	else if (index == 1) {
 		asm("b 1f; .align 5; 1:");
 		asm("mcr p15, 0, r0, c7, c10, 4");	/* drain write buffer */
 		saved_lpr = sdram_selfrefresh_enable();
@@ -55,34 +57,38 @@
 	local_irq_enable();
 	idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
 			(after.tv_usec - before.tv_usec);
-	return idle_time;
+
+	dev->last_residency = idle_time;
+	return index;
 }
 
 /* Initialize CPU idle by registering the idle states */
 static int at91_init_cpuidle(void)
 {
 	struct cpuidle_device *device;
-
-	cpuidle_register_driver(&at91_idle_driver);
+	struct cpuidle_driver *driver = &at91_idle_driver;
 
 	device = &per_cpu(at91_cpuidle_device, smp_processor_id());
 	device->state_count = AT91_MAX_STATES;
+	driver->state_count = AT91_MAX_STATES;
 
 	/* Wait for interrupt state */
-	device->states[0].enter = at91_enter_idle;
-	device->states[0].exit_latency = 1;
-	device->states[0].target_residency = 10000;
-	device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
-	strcpy(device->states[0].name, "WFI");
-	strcpy(device->states[0].desc, "Wait for interrupt");
+	driver->states[0].enter = at91_enter_idle;
+	driver->states[0].exit_latency = 1;
+	driver->states[0].target_residency = 10000;
+	driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(driver->states[0].name, "WFI");
+	strcpy(driver->states[0].desc, "Wait for interrupt");
 
 	/* Wait for interrupt and RAM self refresh state */
-	device->states[1].enter = at91_enter_idle;
-	device->states[1].exit_latency = 10;
-	device->states[1].target_residency = 10000;
-	device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
-	strcpy(device->states[1].name, "RAM_SR");
-	strcpy(device->states[1].desc, "WFI and RAM Self Refresh");
+	driver->states[1].enter = at91_enter_idle;
+	driver->states[1].exit_latency = 10;
+	driver->states[1].target_residency = 10000;
+	driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(driver->states[1].name, "RAM_SR");
+	strcpy(driver->states[1].desc, "WFI and RAM Self Refresh");
+
+	cpuidle_register_driver(&at91_idle_driver);
 
 	if (cpuidle_register_device(device)) {
 		printk(KERN_ERR "at91_init_cpuidle: Failed registering\n");
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/gpio.c linux-libre-3.2-gnu/arch/arm/mach-at91/gpio.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 
 #include <linux/clk.h>
 #include <linux/errno.h>
+#include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/debugfs.h>
@@ -22,9 +23,6 @@
 
 #include <mach/hardware.h>
 #include <mach/at91_pio.h>
-#include <mach/gpio.h>
-
-#include <asm/gpio.h>
 
 #include "generic.h"
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/include/mach/at91sam9g45.h linux-libre-3.2-gnu/arch/arm/mach-at91/include/mach/at91sam9g45.h
--- linux-libre-3.1-gnu/arch/arm/mach-at91/include/mach/at91sam9g45.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/include/mach/at91sam9g45.h	2012-01-04 18:55:44.000000000 -0500
@@ -128,8 +128,6 @@
 #define AT91SAM9G45_EHCI_BASE	0x00800000	/* USB Host controller (EHCI) */
 #define AT91SAM9G45_VDEC_BASE	0x00900000	/* Video Decoder Controller */
 
-#define CONSISTENT_DMA_SIZE	SZ_4M
-
 /*
  * DMA peripheral identifiers
  * for hardware handshaking interface
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/include/mach/board.h linux-libre-3.2-gnu/arch/arm/mach-at91/include/mach/board.h
--- linux-libre-3.1-gnu/arch/arm/mach-at91/include/mach/board.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/include/mach/board.h	2012-01-04 18:55:44.000000000 -0500
@@ -98,6 +98,11 @@
 struct at91_usbh_data {
 	u8		ports;		/* number of ports on root hub */
 	u8		vbus_pin[2];	/* port power-control pin */
+	u8              vbus_pin_inverted;
+	u8              overcurrent_supported;
+	u8              overcurrent_pin[2];
+	u8              overcurrent_status[2];
+	u8              overcurrent_changed[2];
 };
 extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
 extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data);
@@ -112,7 +117,8 @@
 	u8		ale;		/* address line number connected to ALE */
 	u8		cle;		/* address line number connected to CLE */
 	u8		bus_width_16;	/* buswidth is 16 bit */
-	struct mtd_partition* (*partition_info)(int, int*);
+	struct mtd_partition *parts;
+	unsigned int	num_parts;
 };
 extern void __init at91_add_device_nand(struct atmel_nand_data *data);
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-at91/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-at91/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 #include <mach/hardware.h>
 #include <mach/at91_dbgu.h>
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldr	\rp, =(AT91_BASE_SYS + AT91_DBGU)	@ System peripherals (phys address)
 	ldr	\rv, =(AT91_VA_BASE_SYS	+ AT91_DBGU)	@ System peripherals (virt address)
 	.endm
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-at91/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-at91/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -214,11 +214,6 @@
  */
 
 #include <asm/errno.h>
-#include <asm-generic/gpio.h>		/* cansleep wrappers */
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
 
 #define gpio_to_irq(gpio) (gpio)
 #define irq_to_gpio(irq)  (irq)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/include/mach/system_rev.h linux-libre-3.2-gnu/arch/arm/mach-at91/include/mach/system_rev.h
--- linux-libre-3.1-gnu/arch/arm/mach-at91/include/mach/system_rev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/include/mach/system_rev.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 #define BOARD_HAVE_NAND_16BIT	(1 << 31)
 static inline int board_have_nand_16bit(void)
 {
-	return system_rev & BOARD_HAVE_NAND_16BIT;
+	return (system_rev & BOARD_HAVE_NAND_16BIT) ? 1 : 0;
 }
 
 #endif /* __ARCH_SYSTEM_REV_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/include/mach/timex.h linux-libre-3.2-gnu/arch/arm/mach-at91/include/mach/timex.h
--- linux-libre-3.1-gnu/arch/arm/mach-at91/include/mach/timex.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/include/mach/timex.h	2012-01-04 18:55:44.000000000 -0500
@@ -64,7 +64,12 @@
 
 #elif defined(CONFIG_ARCH_AT91SAM9G20)
 
+#if defined(CONFIG_MACH_USB_A9G20)
+#define AT91SAM9_MASTER_CLOCK	133000000
+#else
 #define AT91SAM9_MASTER_CLOCK	132096000
+#endif
+
 #define CLOCK_TICK_RATE		(AT91SAM9_MASTER_CLOCK/16)
 
 #elif defined(CONFIG_ARCH_AT91SAM9G45)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/include/mach/vmalloc.h linux-libre-3.2-gnu/arch/arm/mach-at91/include/mach/vmalloc.h
--- linux-libre-3.1-gnu/arch/arm/mach-at91/include/mach/vmalloc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/include/mach/vmalloc.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,8 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
 
+#include <mach/hardware.h>
+
 #define VMALLOC_END		(AT91_VIRT_BASE & PGDIR_MASK)
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/Kconfig linux-libre-3.2-gnu/arch/arm/mach-at91/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-at91/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -182,6 +182,11 @@
 	help
 	  Select this if you are using the eco920 board
 
+config MACH_RSI_EWS
+	bool "RSI Embedded Webserver"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using RSIs EWS board.
 endif
 
 # ----------------------------------------------------------
@@ -190,12 +195,6 @@
 
 comment "AT91SAM9260 Variants"
 
-config ARCH_AT91SAM9260_SAM9XE
-	bool "AT91SAM9XE"
-	help
-	  Select this if you are using Atmel's AT91SAM9XE System-on-Chip.
-	  They are basically AT91SAM9260s with various sizes of embedded Flash.
-
 comment "AT91SAM9260 / AT91SAM9XE Board Type"
 
 config MACH_AT91SAM9260EK
@@ -381,6 +380,14 @@
 	  This enables support for the GS_IA18_S board
 	  produced by GeoSIG Ltd company. This is an internet accelerograph.
 	  <http://www.geosig.com>
+
+config MACH_USB_A9G20
+	bool "CALAO USB-A9G20"
+	depends on ARCH_AT91SAM9G20
+	help
+	  Select this if you are using a Calao Systems USB-A9G20.
+	  <http://www.calao-systems.com>
+
 endif
 
 if (ARCH_AT91SAM9260 || ARCH_AT91SAM9G20)
@@ -442,6 +449,17 @@
 
 # ----------------------------------------------------------
 
+comment "Generic Board Type"
+
+config MACH_AT91SAM_DT
+	bool "Atmel AT91SAM Evaluation Kits with device-tree support"
+	select USE_OF
+	help
+	  Select this if you want to experiment device-tree with
+	  an Atmel Evaluation Kit.
+
+# ----------------------------------------------------------
+
 comment "AT91 Board Options"
 
 config MTD_AT91_DATAFLASH_CARD
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/leds.c linux-libre-3.2-gnu/arch/arm/mach-at91/leds.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/leds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/leds.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,13 +9,13 @@
  * 2 of the License, or (at your option) any later version.
 */
 
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
 
 
 /* ------------------------------------------------------------------------- */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/Makefile linux-libre-3.2-gnu/arch/arm/mach-at91/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-at91/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -36,12 +36,13 @@
 obj-$(CONFIG_MACH_YL9200)	+= board-yl-9200.o
 obj-$(CONFIG_MACH_CPUAT91)	+= board-cpuat91.o
 obj-$(CONFIG_MACH_ECO920)	+= board-eco920.o
+obj-$(CONFIG_MACH_RSI_EWS)	+= board-rsi-ews.o
 
 # AT91SAM9260 board-specific support
 obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
 obj-$(CONFIG_MACH_CAM60)	+= board-cam60.o
 obj-$(CONFIG_MACH_SAM9_L9260)	+= board-sam9-l9260.o
-obj-$(CONFIG_MACH_USB_A9260)	+= board-usb-a9260.o
+obj-$(CONFIG_MACH_USB_A9260)	+= board-usb-a926x.o
 obj-$(CONFIG_MACH_QIL_A9260)	+= board-qil-a9260.o
 obj-$(CONFIG_MACH_AFEB9260)	+= board-afeb-9260v1.o
 obj-$(CONFIG_MACH_CPU9260)	+= board-cpu9krea.o
@@ -53,7 +54,7 @@
 
 # AT91SAM9263 board-specific support
 obj-$(CONFIG_MACH_AT91SAM9263EK) += board-sam9263ek.o
-obj-$(CONFIG_MACH_USB_A9263)	+= board-usb-a9263.o
+obj-$(CONFIG_MACH_USB_A9263)	+= board-usb-a926x.o
 obj-$(CONFIG_MACH_NEOCORE926)	+= board-neocore926.o
 
 # AT91SAM9RL board-specific support
@@ -67,6 +68,7 @@
 obj-$(CONFIG_MACH_PORTUXG20)	+= board-stamp9g20.o
 obj-$(CONFIG_MACH_PCONTROL_G20)	+= board-pcontrol-g20.o board-stamp9g20.o
 obj-$(CONFIG_MACH_GSIA18S)	+= board-gsia18s.o board-stamp9g20.o
+obj-$(CONFIG_MACH_USB_A9G20)	+= board-usb-a926x.o
 
 # AT91SAM9260/AT91SAM9G20 board-specific support
 obj-$(CONFIG_MACH_SNAPPER_9260)	+= board-snapper9260.o
@@ -74,6 +76,9 @@
 # AT91SAM9G45 board-specific support
 obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o
 
+# AT91SAM board with device-tree
+obj-$(CONFIG_MACH_AT91SAM_DT) += board-dt.o
+
 # AT91CAP9 board-specific support
 obj-$(CONFIG_MACH_AT91CAP9ADK)	+= board-cap9adk.o
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-at91/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-at91/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -4,15 +4,17 @@
 #   INITRD_PHYS must be in RAM
 
 ifeq ($(CONFIG_ARCH_AT91CAP9),y)
-   zreladdr-y	:= 0x70008000
+   zreladdr-y	+= 0x70008000
 params_phys-y	:= 0x70000100
 initrd_phys-y	:= 0x70410000
 else ifeq ($(CONFIG_ARCH_AT91SAM9G45),y)
-   zreladdr-y	:= 0x70008000
+   zreladdr-y	+= 0x70008000
 params_phys-y	:= 0x70000100
 initrd_phys-y	:= 0x70410000
 else
-   zreladdr-y	:= 0x20008000
+   zreladdr-y	+= 0x20008000
 params_phys-y	:= 0x20000100
 initrd_phys-y	:= 0x20410000
 endif
+
+dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9m10g45ek.dtb usb_a9g20.dtb
diff -druN linux-libre-3.1-gnu/arch/arm/mach-at91/pm.c linux-libre-3.2-gnu/arch/arm/mach-at91/pm.c
--- linux-libre-3.1-gnu/arch/arm/mach-at91/pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-at91/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/gpio.h>
 #include <linux/suspend.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
@@ -25,7 +26,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/at91_pmc.h>
-#include <mach/gpio.h>
 #include <mach/cpu.h>
 
 #include "generic.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-bcmring/arch.c linux-libre-3.2-gnu/arch/arm/mach-bcmring/arch.c
--- linux-libre-3.1-gnu/arch/arm/mach-bcmring/arch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-bcmring/arch.c	2012-01-04 18:55:44.000000000 -0500
@@ -136,8 +136,8 @@
 *
 *****************************************************************************/
 
-static void __init bcmring_fixup(struct machine_desc *desc,
-     struct tag *t, char **cmdline, struct meminfo *mi) {
+static void __init bcmring_fixup(struct tag *t, char **cmdline,
+	struct meminfo *mi) {
 #ifdef CONFIG_BLK_DEV_INITRD
 	printk(KERN_NOTICE "bcmring_fixup\n");
 	t->hdr.tag = ATAG_CORE;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-bcmring/core.c linux-libre-3.2-gnu/arch/arm/mach-bcmring/core.c
--- linux-libre-3.1-gnu/arch/arm/mach-bcmring/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-bcmring/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -235,7 +235,7 @@
 	 */
 	bcmring_clocksource_init();
 
-	sp804_clockevents_register(TIMER0_VA_BASE, IRQ_TIMER0, "timer0");
+	sp804_clockevents_init(TIMER0_VA_BASE, IRQ_TIMER0, "timer0");
 }
 
 struct sys_timer bcmring_timer = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-bcmring/dma.c linux-libre-3.2-gnu/arch/arm/mach-bcmring/dma.c
--- linux-libre-3.1-gnu/arch/arm/mach-bcmring/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-bcmring/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
+#include <linux/sched.h>
 #include <linux/irqreturn.h>
 #include <linux/proc_fs.h>
 #include <linux/slab.h>
@@ -35,6 +36,7 @@
 #include <linux/mm.h>
 #include <linux/pfn.h>
 #include <linux/atomic.h>
+#include <linux/sched.h>
 #include <mach/dma.h>
 
 /* I don't quite understand why dc4 fails when this is set to 1 and DMA is enabled */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-bcmring/include/mach/hardware.h linux-libre-3.2-gnu/arch/arm/mach-bcmring/include/mach/hardware.h
--- linux-libre-3.1-gnu/arch/arm/mach-bcmring/include/mach/hardware.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-bcmring/include/mach/hardware.h	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,6 @@
 #define __ASM_ARCH_HARDWARE_H
 
 #include <asm/sizes.h>
-#include <mach/memory.h>
 #include <cfg_global.h>
 #include <mach/csp/mm_io.h>
 
@@ -31,7 +30,7 @@
  *  *_SIZE  is the size of the region
  *  *_BASE  is the virtual address
  */
-#define RAM_START               PLAT_PHYS_OFFSET
+#define RAM_START               PHYS_OFFSET
 
 #define RAM_SIZE                (CFG_GLOBAL_RAM_SIZE-CFG_GLOBAL_RAM_SIZE_RESERVED)
 #define RAM_BASE                PAGE_OFFSET
diff -druN linux-libre-3.1-gnu/arch/arm/mach-bcmring/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-bcmring/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-bcmring/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-bcmring/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/*****************************************************************************
-* Copyright 2005 - 2008 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#include <cfg_global.h>
-
-/*
- * 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.
- */
-
-#define PLAT_PHYS_OFFSET CFG_GLOBAL_RAM_BASE
-
-/*
- * Maximum DMA memory allowed is 14M
- */
-#define CONSISTENT_DMA_SIZE (SZ_16M - SZ_2M)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-bcmring/irq.c linux-libre-3.2-gnu/arch/arm/mach-bcmring/irq.c
--- linux-libre-3.1-gnu/arch/arm/mach-bcmring/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-bcmring/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,6 @@
 #include <linux/stddef.h>
 #include <linux/list.h>
 #include <linux/timer.h>
-#include <linux/version.h>
 #include <linux/io.h>
 
 #include <mach/hardware.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-bcmring/Kconfig linux-libre-3.2-gnu/arch/arm/mach-bcmring/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-bcmring/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-bcmring/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -17,5 +17,3 @@
 	hex "Compressed ZREL ADDR"
 
 endmenu
-
-# source "drivers/char/bcmring/Kconfig"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-bcmring/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-bcmring/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-bcmring/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-bcmring/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 # Address where decompressor will be written and eventually executed.
 #
 # default to SDRAM
-zreladdr-y      := $(CONFIG_BCM_ZRELADDR)
+zreladdr-y      += $(CONFIG_BCM_ZRELADDR)
 params_phys-y   := 0x00000800
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-bcmring/mm.c linux-libre-3.2-gnu/arch/arm/mach-bcmring/mm.c
--- linux-libre-3.1-gnu/arch/arm/mach-bcmring/mm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-bcmring/mm.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,8 @@
 *****************************************************************************/
 
 #include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <asm/page.h>
 #include <asm/mach/map.h>
 
 #include <mach/hardware.h>
@@ -53,4 +55,6 @@
 {
 
 	iotable_init(bcmring_io_desc, ARRAY_SIZE(bcmring_io_desc));
+	/* Maximum DMA memory allowed is 14M */
+	init_consistent_dma_size(14 << 20);
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-bcmring/timer.c linux-libre-3.2-gnu/arch/arm/mach-bcmring/timer.c
--- linux-libre-3.1-gnu/arch/arm/mach-bcmring/timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-bcmring/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,6 @@
 * consent.
 *****************************************************************************/
 
-#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/module.h>
 #include <csp/tmrHw.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-clps711x/autcpu12.c linux-libre-3.2-gnu/arch/arm/mach-clps711x/autcpu12.c
--- linux-libre-3.1-gnu/arch/arm/mach-clps711x/autcpu12.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-clps711x/autcpu12.c	2012-01-04 18:55:44.000000000 -0500
@@ -64,7 +64,7 @@
 
 MACHINE_START(AUTCPU12, "autronix autcpu12")
 	/* Maintainer: Thomas Gleixner */
-	.boot_params	= 0xc0020000,
+	.atag_offset	= 0x20000,
 	.map_io		= autcpu12_map_io,
 	.init_irq	= clps711x_init_irq,
 	.timer		= &clps711x_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-clps711x/cdb89712.c linux-libre-3.2-gnu/arch/arm/mach-clps711x/cdb89712.c
--- linux-libre-3.1-gnu/arch/arm/mach-clps711x/cdb89712.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-clps711x/cdb89712.c	2012-01-04 18:55:44.000000000 -0500
@@ -55,7 +55,7 @@
 
 MACHINE_START(CDB89712, "Cirrus-CDB89712")
 	/* Maintainer: Ray Lehtiniemi */
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= cdb89712_map_io,
 	.init_irq	= clps711x_init_irq,
 	.timer		= &clps711x_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-clps711x/ceiva.c linux-libre-3.2-gnu/arch/arm/mach-clps711x/ceiva.c
--- linux-libre-3.1-gnu/arch/arm/mach-clps711x/ceiva.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-clps711x/ceiva.c	2012-01-04 18:55:44.000000000 -0500
@@ -56,7 +56,7 @@
 
 MACHINE_START(CEIVA, "CEIVA/Polaroid Photo MAX Digital Picture Frame")
 	/* Maintainer: Rob Scott */
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= ceiva_map_io,
 	.init_irq	= clps711x_init_irq,
 	.timer		= &clps711x_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-clps711x/clep7312.c linux-libre-3.2-gnu/arch/arm/mach-clps711x/clep7312.c
--- linux-libre-3.1-gnu/arch/arm/mach-clps711x/clep7312.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-clps711x/clep7312.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,8 +26,7 @@
 #include "common.h"
 
 static void __init
-fixup_clep7312(struct machine_desc *desc, struct tag *tags,
-	    char **cmdline, struct meminfo *mi)
+fixup_clep7312(struct tag *tags, char **cmdline, struct meminfo *mi)
 {
 	mi->nr_banks=1;
 	mi->bank[0].start = 0xc0000000;
@@ -37,7 +36,7 @@
 
 MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312")
 	/* Maintainer: Nobody */
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x0100,
 	.fixup		= fixup_clep7312,
 	.map_io		= clps711x_map_io,
 	.init_irq	= clps711x_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-clps711x/edb7211-arch.c linux-libre-3.2-gnu/arch/arm/mach-clps711x/edb7211-arch.c
--- linux-libre-3.1-gnu/arch/arm/mach-clps711x/edb7211-arch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-clps711x/edb7211-arch.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,8 +37,7 @@
 }
 
 static void __init
-fixup_edb7211(struct machine_desc *desc, struct tag *tags,
-	      char **cmdline, struct meminfo *mi)
+fixup_edb7211(struct tag *tags, char **cmdline, struct meminfo *mi)
 {
 	/*
 	 * Bank start addresses are not present in the information
@@ -57,7 +56,7 @@
 
 MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)")
 	/* Maintainer: Jon McClintock */
-	.boot_params	= 0xc0020100,	/* 0xc0000000 - 0xc001ffff can be video RAM */
+	.atag_offset	= 0x20100,	/* 0xc0000000 - 0xc001ffff can be video RAM */
 	.fixup		= fixup_edb7211,
 	.map_io		= edb7211_map_io,
 	.reserve	= edb7211_reserve,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-clps711x/fortunet.c linux-libre-3.2-gnu/arch/arm/mach-clps711x/fortunet.c
--- linux-libre-3.1-gnu/arch/arm/mach-clps711x/fortunet.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-clps711x/fortunet.c	2012-01-04 18:55:44.000000000 -0500
@@ -57,8 +57,7 @@
 #define IMAGE_PARAMS_PHYS	0xC01F0000
 
 static void __init
-fortunet_fixup(struct machine_desc *desc, struct tag *tags,
-		 char **cmdline, struct meminfo *mi)
+fortunet_fixup(struct tag *tags, char **cmdline, struct meminfo *mi)
 {
 	IMAGE_PARAMS *ip = phys_to_virt(IMAGE_PARAMS_PHYS);
 	*cmdline = phys_to_virt(ip->command_line);
@@ -75,7 +74,6 @@
 
 MACHINE_START(FORTUNET, "ARM-FortuNet")
 	/* Maintainer: FortuNet Inc. */
-	.boot_params	= 0x00000000,
 	.fixup		= fortunet_fixup,
 	.map_io		= clps711x_map_io,
 	.init_irq	= clps711x_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-clps711x/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-clps711x/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-clps711x/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-clps711x/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 #include <mach/hardware.h>
 #include <asm/hardware/clps7111.h>
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 #ifndef CONFIG_DEBUG_CLPS711X_UART2
 		mov	\rp, #0x0000	@ UART1
 #else
diff -druN linux-libre-3.1-gnu/arch/arm/mach-clps711x/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-clps711x/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-clps711x/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-clps711x/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 # The standard locations for stuff on CLPS711x type processors
-   zreladdr-y				:= 0xc0028000
+   zreladdr-y				+= 0xc0028000
 params_phys-y				:= 0xc0000100
 # Should probably have some agreement on these...
 initrd_phys-$(CONFIG_ARCH_P720T)	:= 0xc0400000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-clps711x/p720t.c linux-libre-3.2-gnu/arch/arm/mach-clps711x/p720t.c
--- linux-libre-3.1-gnu/arch/arm/mach-clps711x/p720t.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-clps711x/p720t.c	2012-01-04 18:55:44.000000000 -0500
@@ -56,8 +56,7 @@
 };
 
 static void __init
-fixup_p720t(struct machine_desc *desc, struct tag *tag,
-	    char **cmdline, struct meminfo *mi)
+fixup_p720t(struct tag *tag, char **cmdline, struct meminfo *mi)
 {
 	/*
 	 * Our bootloader doesn't setup any tags (yet).
@@ -89,7 +88,7 @@
 
 MACHINE_START(P720T, "ARM-Prospector720T")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.fixup		= fixup_p720t,
 	.map_io		= p720t_map_io,
 	.init_irq	= clps711x_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-cns3xxx/cns3420vb.c linux-libre-3.2-gnu/arch/arm/mach-cns3xxx/cns3420vb.c
--- linux-libre-3.1-gnu/arch/arm/mach-cns3xxx/cns3420vb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-cns3xxx/cns3420vb.c	2012-01-04 18:55:44.000000000 -0500
@@ -197,7 +197,7 @@
 }
 
 MACHINE_START(CNS3420VB, "Cavium Networks CNS3420 Validation Board")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= cns3420_map_io,
 	.init_irq	= cns3xxx_init_irq,
 	.timer		= &cns3xxx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-cns3xxx/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-cns3xxx/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-cns3xxx/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-cns3xxx/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  * published by the Free Software Foundation.
  */
 
-		.macro	addruart,rp,rv
+		.macro	addruart,rp,rv,tmp
 		mov	\rp, #0x00009000
 		orr	\rv, \rp, #0xf0000000	@ virtual base
 		orr	\rp, \rp, #0x10000000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-cns3xxx/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-cns3xxx/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-cns3xxx/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-cns3xxx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- * Copyright 2003 ARM Limited
- * Copyright 2008 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
- */
-
-#ifndef __MACH_MEMORY_H
-#define __MACH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET		UL(0x00000000)
-
-#define __phys_to_bus(x)	((x) + PHYS_OFFSET)
-#define __bus_to_phys(x)	((x) - PHYS_OFFSET)
-
-#define __virt_to_bus(v)	__phys_to_bus(__virt_to_phys(v))
-#define __bus_to_virt(b)	__phys_to_virt(__bus_to_phys(b))
-#define __pfn_to_bus(p)		__phys_to_bus(__pfn_to_phys(p))
-#define __bus_to_pfn(b)		__phys_to_pfn(__bus_to_phys(b))
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-cns3xxx/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-cns3xxx/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-cns3xxx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-cns3xxx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00C00000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/board-da830-evm.c linux-libre-3.2-gnu/arch/arm/mach-davinci/board-da830-evm.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/board-da830-evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/board-da830-evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -377,7 +377,7 @@
 	.nr_parts	= ARRAY_SIZE(da830_evm_nand_partitions),
 	.ecc_mode	= NAND_ECC_HW,
 	.ecc_bits	= 4,
-	.options	= NAND_USE_FLASH_BBT,
+	.bbt_options	= NAND_BBT_USE_FLASH,
 	.bbt_td		= &da830_evm_nand_bbt_main_descr,
 	.bbt_md		= &da830_evm_nand_bbt_mirror_descr,
 	.timing         = &da830_evm_nandflash_timing,
@@ -676,7 +676,7 @@
 }
 
 MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137/AM17x EVM")
-	.boot_params	= (DA8XX_DDR_BASE + 0x100),
+	.atag_offset	= 0x100,
 	.map_io		= da830_evm_map_io,
 	.init_irq	= cp_intc_init,
 	.timer		= &davinci_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/board-da850-evm.c linux-libre-3.2-gnu/arch/arm/mach-davinci/board-da850-evm.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/board-da850-evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/board-da850-evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,8 @@
 #include <linux/input/tps6507x-ts.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
+#include <linux/delay.h>
+#include <linux/wl12xx.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -49,6 +51,9 @@
 #define DA850_MMCSD_CD_PIN		GPIO_TO_PIN(4, 0)
 #define DA850_MMCSD_WP_PIN		GPIO_TO_PIN(4, 1)
 
+#define DA850_WLAN_EN			GPIO_TO_PIN(6, 9)
+#define DA850_WLAN_IRQ			GPIO_TO_PIN(6, 10)
+
 #define DA850_MII_MDIO_CLKEN_PIN	GPIO_TO_PIN(2, 6)
 
 static struct mtd_partition da850evm_spiflash_part[] = {
@@ -251,7 +256,7 @@
 	.nr_parts	= ARRAY_SIZE(da850_evm_nandflash_partition),
 	.ecc_mode	= NAND_ECC_HW,
 	.ecc_bits	= 4,
-	.options	= NAND_USE_FLASH_BBT,
+	.bbt_options	= NAND_BBT_USE_FLASH,
 	.timing		= &da850_evm_nandflash_timing,
 };
 
@@ -748,7 +753,7 @@
 	.num_serializer	= ARRAY_SIZE(da850_iis_serializer_direction),
 	.tdm_slots	= 2,
 	.serial_dir	= da850_iis_serializer_direction,
-	.asp_chan_q	= EVENTQ_1,
+	.asp_chan_q	= EVENTQ_0,
 	.version	= MCASP_VERSION_2,
 	.txnumevt	= 1,
 	.rxnumevt	= 1,
@@ -1143,6 +1148,110 @@
 static __init int da850_evm_init_cpufreq(void) { return 0; }
 #endif
 
+#ifdef CONFIG_DA850_WL12XX
+
+static void wl12xx_set_power(int index, bool power_on)
+{
+	static bool power_state;
+
+	pr_debug("Powering %s wl12xx", power_on ? "on" : "off");
+
+	if (power_on == power_state)
+		return;
+	power_state = power_on;
+
+	if (power_on) {
+		/* Power up sequence required for wl127x devices */
+		gpio_set_value(DA850_WLAN_EN, 1);
+		usleep_range(15000, 15000);
+		gpio_set_value(DA850_WLAN_EN, 0);
+		usleep_range(1000, 1000);
+		gpio_set_value(DA850_WLAN_EN, 1);
+		msleep(70);
+	} else {
+		gpio_set_value(DA850_WLAN_EN, 0);
+	}
+}
+
+static struct davinci_mmc_config da850_wl12xx_mmc_config = {
+	.set_power	= wl12xx_set_power,
+	.wires		= 4,
+	.max_freq	= 25000000,
+	.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_NONREMOVABLE |
+			  MMC_CAP_POWER_OFF_CARD,
+	.version	= MMC_CTLR_VERSION_2,
+};
+
+static const short da850_wl12xx_pins[] __initconst = {
+	DA850_MMCSD1_DAT_0, DA850_MMCSD1_DAT_1, DA850_MMCSD1_DAT_2,
+	DA850_MMCSD1_DAT_3, DA850_MMCSD1_CLK, DA850_MMCSD1_CMD,
+	DA850_GPIO6_9, DA850_GPIO6_10,
+	-1
+};
+
+static struct wl12xx_platform_data da850_wl12xx_wlan_data __initdata = {
+	.irq			= -1,
+	.board_ref_clock	= WL12XX_REFCLOCK_38,
+	.platform_quirks	= WL12XX_PLATFORM_QUIRK_EDGE_IRQ,
+};
+
+static __init int da850_wl12xx_init(void)
+{
+	int ret;
+
+	ret = davinci_cfg_reg_list(da850_wl12xx_pins);
+	if (ret) {
+		pr_err("wl12xx/mmc mux setup failed: %d\n", ret);
+		goto exit;
+	}
+
+	ret = da850_register_mmcsd1(&da850_wl12xx_mmc_config);
+	if (ret) {
+		pr_err("wl12xx/mmc registration failed: %d\n", ret);
+		goto exit;
+	}
+
+	ret = gpio_request_one(DA850_WLAN_EN, GPIOF_OUT_INIT_LOW, "wl12xx_en");
+	if (ret) {
+		pr_err("Could not request wl12xx enable gpio: %d\n", ret);
+		goto exit;
+	}
+
+	ret = gpio_request_one(DA850_WLAN_IRQ, GPIOF_IN, "wl12xx_irq");
+	if (ret) {
+		pr_err("Could not request wl12xx irq gpio: %d\n", ret);
+		goto free_wlan_en;
+	}
+
+	da850_wl12xx_wlan_data.irq = gpio_to_irq(DA850_WLAN_IRQ);
+
+	ret = wl12xx_set_platform_data(&da850_wl12xx_wlan_data);
+	if (ret) {
+		pr_err("Could not set wl12xx data: %d\n", ret);
+		goto free_wlan_irq;
+	}
+
+	return 0;
+
+free_wlan_irq:
+	gpio_free(DA850_WLAN_IRQ);
+
+free_wlan_en:
+	gpio_free(DA850_WLAN_EN);
+
+exit:
+	return ret;
+}
+
+#else /* CONFIG_DA850_WL12XX */
+
+static __init int da850_wl12xx_init(void)
+{
+	return 0;
+}
+
+#endif /* CONFIG_DA850_WL12XX */
+
 #define DA850EVM_SATA_REFCLKPN_RATE	(100 * 1000 * 1000)
 
 static __init void da850_evm_init(void)
@@ -1197,6 +1306,11 @@
 		if (ret)
 			pr_warning("da850_evm_init: mmcsd0 registration failed:"
 					" %d\n", ret);
+
+		ret = da850_wl12xx_init();
+		if (ret)
+			pr_warning("da850_evm_init: wl12xx initialization"
+				   " failed: %d\n", ret);
 	}
 
 	davinci_serial_init(&da850_evm_uart_config);
@@ -1291,7 +1405,7 @@
 }
 
 MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM")
-	.boot_params	= (DA8XX_DDR_BASE + 0x100),
+	.atag_offset	= 0x100,
 	.map_io		= da850_evm_map_io,
 	.init_irq	= cp_intc_init,
 	.timer		= &davinci_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/board-dm355-evm.c linux-libre-3.2-gnu/arch/arm/mach-davinci/board-dm355-evm.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/board-dm355-evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/board-dm355-evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -77,7 +77,7 @@
 	.parts			= davinci_nand_partitions,
 	.nr_parts		= ARRAY_SIZE(davinci_nand_partitions),
 	.ecc_mode		= NAND_ECC_HW,
-	.options		= NAND_USE_FLASH_BBT,
+	.bbt_options		= NAND_BBT_USE_FLASH,
 	.ecc_bits		= 4,
 };
 
@@ -351,7 +351,7 @@
 }
 
 MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM")
-	.boot_params  = (0x80000100),
+	.atag_offset  = 0x100,
 	.map_io	      = dm355_evm_map_io,
 	.init_irq     = davinci_irq_init,
 	.timer	      = &davinci_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/board-dm355-leopard.c linux-libre-3.2-gnu/arch/arm/mach-davinci/board-dm355-leopard.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/board-dm355-leopard.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/board-dm355-leopard.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,7 +74,7 @@
 	.parts			= davinci_nand_partitions,
 	.nr_parts		= ARRAY_SIZE(davinci_nand_partitions),
 	.ecc_mode		= NAND_ECC_HW_SYNDROME,
-	.options		= NAND_USE_FLASH_BBT,
+	.bbt_options		= NAND_BBT_USE_FLASH,
 };
 
 static struct resource davinci_nand_resources[] = {
@@ -270,7 +270,7 @@
 }
 
 MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard")
-	.boot_params  = (0x80000100),
+	.atag_offset  = 0x100,
 	.map_io	      = dm355_leopard_map_io,
 	.init_irq     = davinci_irq_init,
 	.timer	      = &davinci_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/board-dm365-evm.c linux-libre-3.2-gnu/arch/arm/mach-davinci/board-dm365-evm.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/board-dm365-evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/board-dm365-evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -107,7 +107,7 @@
 		/* UBL (a few copies) plus U-Boot */
 		.name		= "bootloader",
 		.offset		= 0,
-		.size		= 28 * NAND_BLOCK_SIZE,
+		.size		= 30 * NAND_BLOCK_SIZE,
 		.mask_flags	= MTD_WRITEABLE, /* force read-only */
 	}, {
 		/* U-Boot environment */
@@ -139,7 +139,7 @@
 	.parts			= davinci_nand_partitions,
 	.nr_parts		= ARRAY_SIZE(davinci_nand_partitions),
 	.ecc_mode		= NAND_ECC_HW,
-	.options		= NAND_USE_FLASH_BBT,
+	.bbt_options		= NAND_BBT_USE_FLASH,
 	.ecc_bits		= 4,
 };
 
@@ -612,7 +612,7 @@
 }
 
 MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM")
-	.boot_params	= (0x80000100),
+	.atag_offset	= 0x100,
 	.map_io		= dm365_evm_map_io,
 	.init_irq	= davinci_irq_init,
 	.timer		= &davinci_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/board-dm644x-evm.c linux-libre-3.2-gnu/arch/arm/mach-davinci/board-dm644x-evm.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/board-dm644x-evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/board-dm644x-evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/phy.h>
 #include <linux/clk.h>
 #include <linux/videodev2.h>
+#include <linux/export.h>
 
 #include <media/tvp514x.h>
 
@@ -150,7 +151,7 @@
 	.parts		= davinci_evm_nandflash_partition,
 	.nr_parts	= ARRAY_SIZE(davinci_evm_nandflash_partition),
 	.ecc_mode	= NAND_ECC_HW,
-	.options	= NAND_USE_FLASH_BBT,
+	.bbt_options	= NAND_BBT_USE_FLASH,
 	.timing		= &davinci_evm_nandflash_timing,
 };
 
@@ -712,7 +713,7 @@
 
 MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM")
 	/* Maintainer: MontaVista Software <source@mvista.com> */
-	.boot_params  = (DAVINCI_DDR_BASE + 0x100),
+	.atag_offset  = 0x100,
 	.map_io	      = davinci_evm_map_io,
 	.init_irq     = davinci_irq_init,
 	.timer	      = &davinci_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/board-dm646x-evm.c linux-libre-3.2-gnu/arch/arm/mach-davinci/board-dm646x-evm.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/board-dm646x-evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/board-dm646x-evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/clk.h>
+#include <linux/export.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -563,7 +564,7 @@
 	int val;
 	u32 value;
 
-	if (!vpif_vsclkdis_reg || !cpld_client)
+	if (!vpif_vidclkctl_reg || !cpld_client)
 		return -ENXIO;
 
 	val = i2c_smbus_read_byte(cpld_client);
@@ -571,7 +572,7 @@
 		return val;
 
 	spin_lock_irqsave(&vpif_reg_lock, flags);
-	value = __raw_readl(vpif_vsclkdis_reg);
+	value = __raw_readl(vpif_vidclkctl_reg);
 	if (mux_mode) {
 		val &= VPIF_INPUT_TWO_CHANNEL;
 		value |= VIDCH1CLK;
@@ -579,7 +580,7 @@
 		val |= VPIF_INPUT_ONE_CHANNEL;
 		value &= ~VIDCH1CLK;
 	}
-	__raw_writel(value, vpif_vsclkdis_reg);
+	__raw_writel(value, vpif_vidclkctl_reg);
 	spin_unlock_irqrestore(&vpif_reg_lock, flags);
 
 	err = i2c_smbus_write_byte(cpld_client, val);
@@ -792,7 +793,7 @@
 }
 
 MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
-	.boot_params  = (0x80000100),
+	.atag_offset  = 0x100,
 	.map_io       = davinci_map_io,
 	.init_irq     = davinci_irq_init,
 	.timer        = &davinci_timer,
@@ -801,7 +802,7 @@
 MACHINE_END
 
 MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
-	.boot_params  = (0x80000100),
+	.atag_offset  = 0x100,
 	.map_io       = davinci_map_io,
 	.init_irq     = davinci_irq_init,
 	.timer        = &davinci_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/board-mityomapl138.c linux-libre-3.2-gnu/arch/arm/mach-davinci/board-mityomapl138.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/board-mityomapl138.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/board-mityomapl138.c	2012-01-04 18:55:44.000000000 -0500
@@ -396,7 +396,8 @@
 	.parts		= mityomapl138_nandflash_partition,
 	.nr_parts	= ARRAY_SIZE(mityomapl138_nandflash_partition),
 	.ecc_mode	= NAND_ECC_HW,
-	.options	= NAND_USE_FLASH_BBT | NAND_BUSWIDTH_16,
+	.bbt_options	= NAND_BBT_USE_FLASH,
+	.options	= NAND_BUSWIDTH_16,
 	.ecc_bits	= 1, /* 4 bit mode is not supported with 16 bit NAND */
 };
 
@@ -566,7 +567,7 @@
 }
 
 MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808")
-	.boot_params	= (DA8XX_DDR_BASE + 0x100),
+	.atag_offset	= 0x100,
 	.map_io		= mityomapl138_map_io,
 	.init_irq	= cp_intc_init,
 	.timer		= &davinci_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/board-neuros-osd2.c linux-libre-3.2-gnu/arch/arm/mach-davinci/board-neuros-osd2.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/board-neuros-osd2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/board-neuros-osd2.c	2012-01-04 18:55:44.000000000 -0500
@@ -87,7 +87,7 @@
 	.parts		= davinci_ntosd2_nandflash_partition,
 	.nr_parts	= ARRAY_SIZE(davinci_ntosd2_nandflash_partition),
 	.ecc_mode	= NAND_ECC_HW,
-	.options	= NAND_USE_FLASH_BBT,
+	.bbt_options	= NAND_BBT_USE_FLASH,
 };
 
 static struct resource davinci_ntosd2_nandflash_resource[] = {
@@ -272,7 +272,7 @@
 
 MACHINE_START(NEUROS_OSD2, "Neuros OSD2")
 	/* Maintainer: Neuros Technologies <neuros@groups.google.com> */
-	.boot_params	= (DAVINCI_DDR_BASE + 0x100),
+	.atag_offset	= 0x100,
 	.map_io		 = davinci_ntosd2_map_io,
 	.init_irq	= davinci_irq_init,
 	.timer		= &davinci_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/board-omapl138-hawk.c linux-libre-3.2-gnu/arch/arm/mach-davinci/board-omapl138-hawk.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/board-omapl138-hawk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/board-omapl138-hawk.c	2012-01-04 18:55:44.000000000 -0500
@@ -338,7 +338,7 @@
 }
 
 MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard")
-	.boot_params	= (DA8XX_DDR_BASE + 0x100),
+	.atag_offset	= 0x100,
 	.map_io		= omapl138_hawk_map_io,
 	.init_irq	= cp_intc_init,
 	.timer		= &davinci_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/board-sffsdr.c linux-libre-3.2-gnu/arch/arm/mach-davinci/board-sffsdr.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/board-sffsdr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/board-sffsdr.c	2012-01-04 18:55:44.000000000 -0500
@@ -151,7 +151,7 @@
 
 MACHINE_START(SFFSDR, "Lyrtech SFFSDR")
 	/* Maintainer: Hugo Villeneuve hugo.villeneuve@lyrtech.com */
-	.boot_params  = (DAVINCI_DDR_BASE + 0x100),
+	.atag_offset  = 0x100,
 	.map_io	      = davinci_sffsdr_map_io,
 	.init_irq     = davinci_irq_init,
 	.timer	      = &davinci_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/board-tnetv107x-evm.c linux-libre-3.2-gnu/arch/arm/mach-davinci/board-tnetv107x-evm.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/board-tnetv107x-evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/board-tnetv107x-evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -144,7 +144,7 @@
 	.parts		= nand_partitions,
 	.nr_parts	= ARRAY_SIZE(nand_partitions),
 	.ecc_mode	= NAND_ECC_HW,
-	.options	= NAND_USE_FLASH_BBT,
+	.bbt_options	= NAND_BBT_USE_FLASH,
 	.ecc_bits	= 1,
 };
 
@@ -277,7 +277,7 @@
 #endif
 
 MACHINE_START(TNETV107X, "TNETV107X EVM")
-	.boot_params	= (TNETV107X_DDR_BASE + 0x100),
+	.atag_offset	= 0x100,
 	.map_io		= tnetv107x_init,
 	.init_irq	= cp_intc_init,
 	.timer		= &davinci_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/cdce949.c linux-libre-3.2-gnu/arch/arm/mach-davinci/cdce949.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/cdce949.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/cdce949.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/module.h>
 
 #include <mach/clock.h>
 #include <mach/cdce949.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/common.c linux-libre-3.2-gnu/arch/arm/mach-davinci/common.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/io.h>
 #include <linux/etherdevice.h>
 #include <linux/davinci_emac.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/tlb.h>
 #include <asm/mach/map.h>
@@ -86,6 +87,8 @@
 		iotable_init(davinci_soc_info.io_desc,
 				davinci_soc_info.io_desc_num);
 
+	init_consistent_dma_size(14 << 20);
+
 	/*
 	 * Normally devicemaps_init() would flush caches and tlb after
 	 * mdesc->map_io(), but we must also do it here because of the CPU
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/cpufreq.c linux-libre-3.2-gnu/arch/arm/mach-davinci/cpufreq.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/export.h>
 
 #include <mach/hardware.h>
 #include <mach/cpufreq.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/cpuidle.c linux-libre-3.2-gnu/arch/arm/mach-davinci/cpuidle.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/cpuidle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/cpuidle.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,10 +16,11 @@
 #include <linux/platform_device.h>
 #include <linux/cpuidle.h>
 #include <linux/io.h>
+#include <linux/export.h>
 #include <asm/proc-fns.h>
 
 #include <mach/cpuidle.h>
-#include <mach/memory.h>
+#include <mach/ddr2.h>
 
 #define DAVINCI_CPUIDLE_MAX_STATES	2
 
@@ -78,9 +79,11 @@
 
 /* Actual code that puts the SoC in different idle states */
 static int davinci_enter_idle(struct cpuidle_device *dev,
-						struct cpuidle_state *state)
+				struct cpuidle_driver *drv,
+						int index)
 {
-	struct davinci_ops *ops = cpuidle_get_statedata(state);
+	struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+	struct davinci_ops *ops = cpuidle_get_statedata(state_usage);
 	struct timeval before, after;
 	int idle_time;
 
@@ -98,13 +101,17 @@
 	local_irq_enable();
 	idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
 			(after.tv_usec - before.tv_usec);
-	return idle_time;
+
+	dev->last_residency = idle_time;
+
+	return index;
 }
 
 static int __init davinci_cpuidle_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct cpuidle_device *device;
+	struct cpuidle_driver *driver = &davinci_idle_driver;
 	struct davinci_cpuidle_config *pdata = pdev->dev.platform_data;
 
 	device = &per_cpu(davinci_cpuidle_device, smp_processor_id());
@@ -116,32 +123,33 @@
 
 	ddr2_reg_base = pdata->ddr2_ctlr_base;
 
-	ret = cpuidle_register_driver(&davinci_idle_driver);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to register driver\n");
-		return ret;
-	}
-
 	/* Wait for interrupt state */
-	device->states[0].enter = davinci_enter_idle;
-	device->states[0].exit_latency = 1;
-	device->states[0].target_residency = 10000;
-	device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
-	strcpy(device->states[0].name, "WFI");
-	strcpy(device->states[0].desc, "Wait for interrupt");
+	driver->states[0].enter = davinci_enter_idle;
+	driver->states[0].exit_latency = 1;
+	driver->states[0].target_residency = 10000;
+	driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(driver->states[0].name, "WFI");
+	strcpy(driver->states[0].desc, "Wait for interrupt");
 
 	/* Wait for interrupt and DDR self refresh state */
-	device->states[1].enter = davinci_enter_idle;
-	device->states[1].exit_latency = 10;
-	device->states[1].target_residency = 10000;
-	device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
-	strcpy(device->states[1].name, "DDR SR");
-	strcpy(device->states[1].desc, "WFI and DDR Self Refresh");
+	driver->states[1].enter = davinci_enter_idle;
+	driver->states[1].exit_latency = 10;
+	driver->states[1].target_residency = 10000;
+	driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(driver->states[1].name, "DDR SR");
+	strcpy(driver->states[1].desc, "WFI and DDR Self Refresh");
 	if (pdata->ddr2_pdown)
 		davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN;
-	cpuidle_set_statedata(&device->states[1], &davinci_states[1]);
+	cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]);
 
 	device->state_count = DAVINCI_CPUIDLE_MAX_STATES;
+	driver->state_count = DAVINCI_CPUIDLE_MAX_STATES;
+
+	ret = cpuidle_register_driver(&davinci_idle_driver);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register driver\n");
+		return ret;
+	}
 
 	ret = cpuidle_register_device(device);
 	if (ret) {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/da830.c linux-libre-3.2-gnu/arch/arm/mach-davinci/da830.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/da830.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/da830.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/clk.h>
 
@@ -19,7 +20,7 @@
 #include <mach/common.h>
 #include <mach/time.h>
 #include <mach/da8xx.h>
-#include <mach/gpio.h>
+#include <mach/gpio-davinci.h>
 
 #include "clock.h"
 #include "mux.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/da850.c linux-libre-3.2-gnu/arch/arm/mach-davinci/da850.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/da850.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/da850.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/platform_device.h>
@@ -27,7 +28,7 @@
 #include <mach/da8xx.h>
 #include <mach/cpufreq.h>
 #include <mach/pm.h>
-#include <mach/gpio.h>
+#include <mach/gpio-davinci.h>
 
 #include "clock.h"
 #include "mux.h"
@@ -535,6 +536,13 @@
 	MUX_CFG(DA850, MMCSD0_DAT_3,	10,	20,	15,	2,	false)
 	MUX_CFG(DA850, MMCSD0_CLK,	10,	0,	15,	2,	false)
 	MUX_CFG(DA850, MMCSD0_CMD,	10,	4,	15,	2,	false)
+	/* MMC/SD1 function */
+	MUX_CFG(DA850, MMCSD1_DAT_0,	18,	8,	15,	2,	false)
+	MUX_CFG(DA850, MMCSD1_DAT_1,	19,	16,	15,	2,	false)
+	MUX_CFG(DA850, MMCSD1_DAT_2,	19,	12,	15,	2,	false)
+	MUX_CFG(DA850, MMCSD1_DAT_3,	19,	8,	15,	2,	false)
+	MUX_CFG(DA850, MMCSD1_CLK,	18,	12,	15,	2,	false)
+	MUX_CFG(DA850, MMCSD1_CMD,	18,	16,	15,	2,	false)
 	/* EMIF2.5/EMIFA function */
 	MUX_CFG(DA850, EMA_D_7,		9,	0,	15,	1,	false)
 	MUX_CFG(DA850, EMA_D_6,		9,	4,	15,	1,	false)
@@ -593,6 +601,8 @@
 	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_9,		13,	24,	15,	8,	false)
+	MUX_CFG(DA850, GPIO6_10,	13,	20,	15,	8,	false)
 	MUX_CFG(DA850, GPIO6_13,	13,	8,	15,	8,	false)
 	MUX_CFG(DA850, RTC_ALARM,	0,	28,	15,	2,	false)
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/devices-da8xx.c linux-libre-3.2-gnu/arch/arm/mach-davinci/devices-da8xx.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/devices-da8xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/devices-da8xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -136,6 +136,7 @@
 	.n_cc			= 1,
 	.queue_tc_mapping	= da8xx_queue_tc_mapping,
 	.queue_priority_mapping	= da8xx_queue_priority_mapping,
+	.default_queue		= EVENTQ_1,
 };
 
 static struct edma_soc_info *da830_edma_info[EDMA_MAX_CC] = {
@@ -151,6 +152,7 @@
 		.n_cc			= 1,
 		.queue_tc_mapping	= da8xx_queue_tc_mapping,
 		.queue_priority_mapping	= da8xx_queue_priority_mapping,
+		.default_queue		= EVENTQ_1,
 	},
 	{
 		.n_channel		= 32,
@@ -160,6 +162,7 @@
 		.n_cc			= 1,
 		.queue_tc_mapping	= da850_queue_tc_mapping,
 		.queue_priority_mapping	= da850_queue_priority_mapping,
+		.default_queue		= EVENTQ_0,
 	},
 };
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/devices-tnetv107x.c linux-libre-3.2-gnu/arch/arm/mach-davinci/devices-tnetv107x.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/devices-tnetv107x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/devices-tnetv107x.c	2012-01-04 18:55:44.000000000 -0500
@@ -80,6 +80,7 @@
 	.n_cc			= 1,
 	.queue_tc_mapping	= edma_tc_mapping,
 	.queue_priority_mapping	= edma_priority_mapping,
+	.default_queue		= EVENTQ_1,
 };
 
 static struct edma_soc_info *tnetv107x_edma_info[EDMA_MAX_CC] = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/dm355.c linux-libre-3.2-gnu/arch/arm/mach-davinci/dm355.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/dm355.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/dm355.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@
 #include <linux/serial_8250.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
-#include <linux/gpio.h>
 
 #include <linux/spi/spi.h>
 
@@ -30,6 +29,7 @@
 #include <mach/common.h>
 #include <mach/asp.h>
 #include <mach/spi.h>
+#include <mach/gpio-davinci.h>
 
 #include "clock.h"
 #include "mux.h"
@@ -591,6 +591,7 @@
 	.n_cc			= 1,
 	.queue_tc_mapping	= queue_tc_mapping,
 	.queue_priority_mapping	= queue_priority_mapping,
+	.default_queue		= EVENTQ_1,
 };
 
 static struct edma_soc_info *dm355_edma_info[EDMA_MAX_CC] = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/dm365.c linux-libre-3.2-gnu/arch/arm/mach-davinci/dm365.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/dm365.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/dm365.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,6 @@
 #include <linux/serial_8250.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
-#include <linux/gpio.h>
 #include <linux/spi/spi.h>
 
 #include <asm/mach/map.h>
@@ -34,7 +33,7 @@
 #include <mach/asp.h>
 #include <mach/keyscan.h>
 #include <mach/spi.h>
-
+#include <mach/gpio-davinci.h>
 
 #include "clock.h"
 #include "mux.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/dm644x.c linux-libre-3.2-gnu/arch/arm/mach-davinci/dm644x.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/dm644x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/dm644x.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,6 @@
 #include <linux/clk.h>
 #include <linux/serial_8250.h>
 #include <linux/platform_device.h>
-#include <linux/gpio.h>
 
 #include <asm/mach/map.h>
 
@@ -26,6 +25,7 @@
 #include <mach/serial.h>
 #include <mach/common.h>
 #include <mach/asp.h>
+#include <mach/gpio-davinci.h>
 
 #include "clock.h"
 #include "mux.h"
@@ -514,6 +514,7 @@
 	.n_cc			= 1,
 	.queue_tc_mapping	= queue_tc_mapping,
 	.queue_priority_mapping	= queue_priority_mapping,
+	.default_queue		= EVENTQ_1,
 };
 
 static struct edma_soc_info *dm644x_edma_info[EDMA_MAX_CC] = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/dm646x.c linux-libre-3.2-gnu/arch/arm/mach-davinci/dm646x.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/dm646x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/dm646x.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@
 #include <linux/clk.h>
 #include <linux/serial_8250.h>
 #include <linux/platform_device.h>
-#include <linux/gpio.h>
 
 #include <asm/mach/map.h>
 
@@ -27,6 +26,7 @@
 #include <mach/serial.h>
 #include <mach/common.h>
 #include <mach/asp.h>
+#include <mach/gpio-davinci.h>
 
 #include "clock.h"
 #include "mux.h"
@@ -161,7 +161,6 @@
 	.name = "dsp",
 	.parent = &pll1_sysclk1,
 	.lpsc = DM646X_LPSC_C64X_CPU,
-	.flags = PSC_DSP,
 	.usecount = 1,			/* REVISIT how to disable? */
 };
 
@@ -555,6 +554,7 @@
 	.n_cc			= 1,
 	.queue_tc_mapping	= dm646x_queue_tc_mapping,
 	.queue_priority_mapping	= dm646x_queue_priority_mapping,
+	.default_queue		= EVENTQ_1,
 };
 
 static struct edma_soc_info *dm646x_edma_info[EDMA_MAX_CC] = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/dma.c linux-libre-3.2-gnu/arch/arm/mach-davinci/dma.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -1435,12 +1435,11 @@
 			goto fail1;
 		}
 
-		edma_cc[j] = kmalloc(sizeof(struct edma), GFP_KERNEL);
+		edma_cc[j] = kzalloc(sizeof(struct edma), GFP_KERNEL);
 		if (!edma_cc[j]) {
 			status = -ENOMEM;
 			goto fail1;
 		}
-		memset(edma_cc[j], 0, sizeof(struct edma));
 
 		edma_cc[j]->num_channels = min_t(unsigned, info[j]->n_channel,
 							EDMA_MAX_DMACH);
@@ -1450,8 +1449,6 @@
 							EDMA_MAX_CC);
 
 		edma_cc[j]->default_queue = info[j]->default_queue;
-		if (!edma_cc[j]->default_queue)
-			edma_cc[j]->default_queue = EVENTQ_1;
 
 		dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n",
 			edmacc_regs_base[j]);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/gpio.c linux-libre-3.2-gnu/arch/arm/mach-davinci/gpio.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,460 +0,0 @@
-/*
- * TI DaVinci GPIO Support
- *
- * Copyright (c) 2006-2007 David Brownell
- * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.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/errno.h>
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include <mach/gpio.h>
-
-#include <asm/mach/irq.h>
-
-struct davinci_gpio_regs {
-	u32	dir;
-	u32	out_data;
-	u32	set_data;
-	u32	clr_data;
-	u32	in_data;
-	u32	set_rising;
-	u32	clr_rising;
-	u32	set_falling;
-	u32	clr_falling;
-	u32	intstat;
-};
-
-#define chip2controller(chip)	\
-	container_of(chip, struct davinci_gpio_controller, chip)
-
-static struct davinci_gpio_controller chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)];
-static void __iomem *gpio_base;
-
-static struct davinci_gpio_regs __iomem __init *gpio2regs(unsigned gpio)
-{
-	void __iomem *ptr;
-
-	if (gpio < 32 * 1)
-		ptr = gpio_base + 0x10;
-	else if (gpio < 32 * 2)
-		ptr = gpio_base + 0x38;
-	else if (gpio < 32 * 3)
-		ptr = gpio_base + 0x60;
-	else if (gpio < 32 * 4)
-		ptr = gpio_base + 0x88;
-	else if (gpio < 32 * 5)
-		ptr = gpio_base + 0xb0;
-	else
-		ptr = NULL;
-	return ptr;
-}
-
-static inline struct davinci_gpio_regs __iomem *irq2regs(int irq)
-{
-	struct davinci_gpio_regs __iomem *g;
-
-	g = (__force struct davinci_gpio_regs __iomem *)irq_get_chip_data(irq);
-
-	return g;
-}
-
-static int __init davinci_gpio_irq_setup(void);
-
-/*--------------------------------------------------------------------------*/
-
-/* board setup code *MUST* setup pinmux and enable the GPIO clock. */
-static inline int __davinci_direction(struct gpio_chip *chip,
-			unsigned offset, bool out, int value)
-{
-	struct davinci_gpio_controller *d = chip2controller(chip);
-	struct davinci_gpio_regs __iomem *g = d->regs;
-	unsigned long flags;
-	u32 temp;
-	u32 mask = 1 << offset;
-
-	spin_lock_irqsave(&d->lock, flags);
-	temp = __raw_readl(&g->dir);
-	if (out) {
-		temp &= ~mask;
-		__raw_writel(mask, value ? &g->set_data : &g->clr_data);
-	} else {
-		temp |= mask;
-	}
-	__raw_writel(temp, &g->dir);
-	spin_unlock_irqrestore(&d->lock, flags);
-
-	return 0;
-}
-
-static int davinci_direction_in(struct gpio_chip *chip, unsigned offset)
-{
-	return __davinci_direction(chip, offset, false, 0);
-}
-
-static int
-davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value)
-{
-	return __davinci_direction(chip, offset, true, value);
-}
-
-/*
- * Read the pin's value (works even if it's set up as output);
- * returns zero/nonzero.
- *
- * Note that changes are synched to the GPIO clock, so reading values back
- * right after you've set them may give old values.
- */
-static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct davinci_gpio_controller *d = chip2controller(chip);
-	struct davinci_gpio_regs __iomem *g = d->regs;
-
-	return (1 << offset) & __raw_readl(&g->in_data);
-}
-
-/*
- * Assuming the pin is muxed as a gpio output, set its output value.
- */
-static void
-davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	struct davinci_gpio_controller *d = chip2controller(chip);
-	struct davinci_gpio_regs __iomem *g = d->regs;
-
-	__raw_writel((1 << offset), value ? &g->set_data : &g->clr_data);
-}
-
-static int __init davinci_gpio_setup(void)
-{
-	int i, base;
-	unsigned ngpio;
-	struct davinci_soc_info *soc_info = &davinci_soc_info;
-	struct davinci_gpio_regs *regs;
-
-	if (soc_info->gpio_type != GPIO_TYPE_DAVINCI)
-		return 0;
-
-	/*
-	 * The gpio banks conceptually expose a segmented bitmap,
-	 * and "ngpio" is one more than the largest zero-based
-	 * bit index that's valid.
-	 */
-	ngpio = soc_info->gpio_num;
-	if (ngpio == 0) {
-		pr_err("GPIO setup:  how many GPIOs?\n");
-		return -EINVAL;
-	}
-
-	if (WARN_ON(DAVINCI_N_GPIO < ngpio))
-		ngpio = DAVINCI_N_GPIO;
-
-	gpio_base = ioremap(soc_info->gpio_base, SZ_4K);
-	if (WARN_ON(!gpio_base))
-		return -ENOMEM;
-
-	for (i = 0, base = 0; base < ngpio; i++, base += 32) {
-		chips[i].chip.label = "DaVinci";
-
-		chips[i].chip.direction_input = davinci_direction_in;
-		chips[i].chip.get = davinci_gpio_get;
-		chips[i].chip.direction_output = davinci_direction_out;
-		chips[i].chip.set = davinci_gpio_set;
-
-		chips[i].chip.base = base;
-		chips[i].chip.ngpio = ngpio - base;
-		if (chips[i].chip.ngpio > 32)
-			chips[i].chip.ngpio = 32;
-
-		spin_lock_init(&chips[i].lock);
-
-		regs = gpio2regs(base);
-		chips[i].regs = regs;
-		chips[i].set_data = &regs->set_data;
-		chips[i].clr_data = &regs->clr_data;
-		chips[i].in_data = &regs->in_data;
-
-		gpiochip_add(&chips[i].chip);
-	}
-
-	soc_info->gpio_ctlrs = chips;
-	soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32);
-
-	davinci_gpio_irq_setup();
-	return 0;
-}
-pure_initcall(davinci_gpio_setup);
-
-/*--------------------------------------------------------------------------*/
-/*
- * We expect irqs will normally be set up as input pins, but they can also be
- * used as output pins ... which is convenient for testing.
- *
- * NOTE:  The first few GPIOs also have direct INTC hookups in addition
- * to their GPIOBNK0 irq, with a bit less overhead.
- *
- * All those INTC hookups (direct, plus several IRQ banks) can also
- * serve as EDMA event triggers.
- */
-
-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_handler_data(d);
-
-	__raw_writel(mask, &g->clr_falling);
-	__raw_writel(mask, &g->clr_rising);
-}
-
-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_handler_data(d);
-	unsigned status = irqd_get_trigger_type(d);
-
-	status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
-	if (!status)
-		status = IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
-
-	if (status & IRQ_TYPE_EDGE_FALLING)
-		__raw_writel(mask, &g->set_falling);
-	if (status & IRQ_TYPE_EDGE_RISING)
-		__raw_writel(mask, &g->set_rising);
-}
-
-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_handler_data(d);
-
-	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-		return -EINVAL;
-
-	return 0;
-}
-
-static struct irq_chip gpio_irqchip = {
-	.name		= "GPIO",
-	.irq_enable	= gpio_irq_enable,
-	.irq_disable	= gpio_irq_disable,
-	.irq_set_type	= gpio_irq_type,
-	.flags		= IRQCHIP_SET_TYPE_MASKED,
-};
-
-static void
-gpio_irq_handler(unsigned irq, struct irq_desc *desc)
-{
-	struct davinci_gpio_regs __iomem *g;
-	u32 mask = 0xffff;
-	struct davinci_gpio_controller *d;
-
-	d = (struct davinci_gpio_controller *)irq_desc_get_handler_data(desc);
-	g = (struct davinci_gpio_regs __iomem *)d->regs;
-
-	/* we only care about one bank */
-	if (irq & 1)
-		mask <<= 16;
-
-	/* temporarily mask (level sensitive) parent IRQ */
-	desc->irq_data.chip->irq_mask(&desc->irq_data);
-	desc->irq_data.chip->irq_ack(&desc->irq_data);
-	while (1) {
-		u32		status;
-		int		n;
-		int		res;
-
-		/* ack any irqs */
-		status = __raw_readl(&g->intstat) & mask;
-		if (!status)
-			break;
-		__raw_writel(status, &g->intstat);
-
-		/* now demux them to the right lowlevel handler */
-		n = d->irq_base;
-		if (irq & 1) {
-			n += 16;
-			status >>= 16;
-		}
-
-		while (status) {
-			res = ffs(status);
-			n += res;
-			generic_handle_irq(n - 1);
-			status >>= res;
-		}
-	}
-	desc->irq_data.chip->irq_unmask(&desc->irq_data);
-	/* now it may re-trigger */
-}
-
-static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset)
-{
-	struct davinci_gpio_controller *d = chip2controller(chip);
-
-	if (d->irq_base >= 0)
-		return d->irq_base + offset;
-	else
-		return -ENODEV;
-}
-
-static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)
-{
-	struct davinci_soc_info *soc_info = &davinci_soc_info;
-
-	/* NOTE:  we assume for now that only irqs in the first gpio_chip
-	 * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs).
-	 */
-	if (offset < soc_info->gpio_unbanked)
-		return soc_info->gpio_irq + offset;
-	else
-		return -ENODEV;
-}
-
-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_handler_data(d);
-
-	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-		return -EINVAL;
-
-	__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;
-}
-
-/*
- * NOTE:  for suspend/resume, probably best to make a platform_device with
- * suspend_late/resume_resume calls hooking into results of the set_wake()
- * calls ... so if no gpios are wakeup events the clock can be disabled,
- * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0
- * (dm6446) can be set appropriately for GPIOV33 pins.
- */
-
-static int __init davinci_gpio_irq_setup(void)
-{
-	unsigned	gpio, irq, bank;
-	struct clk	*clk;
-	u32		binten = 0;
-	unsigned	ngpio, bank_irq;
-	struct davinci_soc_info *soc_info = &davinci_soc_info;
-	struct davinci_gpio_regs	__iomem *g;
-
-	ngpio = soc_info->gpio_num;
-
-	bank_irq = soc_info->gpio_irq;
-	if (bank_irq == 0) {
-		printk(KERN_ERR "Don't know first GPIO bank IRQ.\n");
-		return -EINVAL;
-	}
-
-	clk = clk_get(NULL, "gpio");
-	if (IS_ERR(clk)) {
-		printk(KERN_ERR "Error %ld getting gpio clock?\n",
-		       PTR_ERR(clk));
-		return PTR_ERR(clk);
-	}
-	clk_enable(clk);
-
-	/* Arrange gpio_to_irq() support, handling either direct IRQs or
-	 * banked IRQs.  Having GPIOs in the first GPIO bank use direct
-	 * IRQs, while the others use banked IRQs, would need some setup
-	 * tweaks to recognize hardware which can do that.
-	 */
-	for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) {
-		chips[bank].chip.to_irq = gpio_to_irq_banked;
-		chips[bank].irq_base = soc_info->gpio_unbanked
-			? -EINVAL
-			: (soc_info->intc_irq_num + gpio);
-	}
-
-	/*
-	 * AINTC can handle direct/unbanked IRQs for GPIOs, with the GPIO
-	 * controller only handling trigger modes.  We currently assume no
-	 * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs.
-	 */
-	if (soc_info->gpio_unbanked) {
-		static struct irq_chip gpio_irqchip_unbanked;
-
-		/* pass "bank 0" GPIO IRQs to AINTC */
-		chips[0].chip.to_irq = gpio_to_irq_unbanked;
-		binten = BIT(0);
-
-		/* AINTC handles mask/unmask; GPIO handles triggering */
-		irq = bank_irq;
-		gpio_irqchip_unbanked = *irq_get_chip(irq);
-		gpio_irqchip_unbanked.name = "GPIO-AINTC";
-		gpio_irqchip_unbanked.irq_set_type = gpio_irq_type_unbanked;
-
-		/* default trigger: both edges */
-		g = gpio2regs(0);
-		__raw_writel(~0, &g->set_falling);
-		__raw_writel(~0, &g->set_rising);
-
-		/* set the direct IRQs up to use that irqchip */
-		for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) {
-			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;
-	}
-
-	/*
-	 * Or, AINTC can handle IRQs for banks of 16 GPIO IRQs, which we
-	 * then chain through our own handler.
-	 */
-	for (gpio = 0, irq = gpio_to_irq(0), bank = 0;
-			gpio < ngpio;
-			bank++, bank_irq++) {
-		unsigned		i;
-
-		/* disabled by default, enabled only as needed */
-		g = gpio2regs(gpio);
-		__raw_writel(~0, &g->clr_falling);
-		__raw_writel(~0, &g->clr_rising);
-
-		/* set up all irqs in this bank */
-		irq_set_chained_handler(bank_irq, gpio_irq_handler);
-
-		/*
-		 * Each chip handles 32 gpios, and each irq bank consists of 16
-		 * gpio irqs. Pass the irq bank's corresponding controller to
-		 * the chained irq handler.
-		 */
-		irq_set_handler_data(bank_irq, &chips[gpio / 32]);
-
-		for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) {
-			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);
-		}
-
-		binten |= BIT(bank);
-	}
-
-done:
-	/* BINTEN -- per-bank interrupt enable. genirq would also let these
-	 * bits be set/cleared dynamically.
-	 */
-	__raw_writel(binten, gpio_base + 0x08);
-
-	printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
-
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/gpio-tnetv107x.c linux-libre-3.2-gnu/arch/arm/mach-davinci/gpio-tnetv107x.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/gpio-tnetv107x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/gpio-tnetv107x.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,205 +0,0 @@
-/*
- * Texas Instruments TNETV107X GPIO Controller
- *
- * Copyright (C) 2010 Texas Instruments
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/gpio.h>
-
-#include <mach/common.h>
-#include <mach/tnetv107x.h>
-
-struct tnetv107x_gpio_regs {
-	u32	idver;
-	u32	data_in[3];
-	u32	data_out[3];
-	u32	direction[3];
-	u32	enable[3];
-};
-
-#define gpio_reg_index(gpio)	((gpio) >> 5)
-#define gpio_reg_bit(gpio)	BIT((gpio) & 0x1f)
-
-#define gpio_reg_rmw(reg, mask, val)	\
-	__raw_writel((__raw_readl(reg) & ~(mask)) | (val), (reg))
-
-#define gpio_reg_set_bit(reg, gpio)	\
-	gpio_reg_rmw((reg) + gpio_reg_index(gpio), 0, gpio_reg_bit(gpio))
-
-#define gpio_reg_clear_bit(reg, gpio)	\
-	gpio_reg_rmw((reg) + gpio_reg_index(gpio), gpio_reg_bit(gpio), 0)
-
-#define gpio_reg_get_bit(reg, gpio)	\
-	(__raw_readl((reg) + gpio_reg_index(gpio)) & gpio_reg_bit(gpio))
-
-#define chip2controller(chip)		\
-	container_of(chip, struct davinci_gpio_controller, chip)
-
-#define TNETV107X_GPIO_CTLRS	DIV_ROUND_UP(TNETV107X_N_GPIO, 32)
-
-static struct davinci_gpio_controller chips[TNETV107X_GPIO_CTLRS];
-
-static int tnetv107x_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-	struct davinci_gpio_controller *ctlr = chip2controller(chip);
-	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
-	unsigned gpio = chip->base + offset;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-
-	gpio_reg_set_bit(regs->enable, gpio);
-
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-
-	return 0;
-}
-
-static void tnetv107x_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-	struct davinci_gpio_controller *ctlr = chip2controller(chip);
-	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
-	unsigned gpio = chip->base + offset;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-
-	gpio_reg_clear_bit(regs->enable, gpio);
-
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-}
-
-static int tnetv107x_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
-{
-	struct davinci_gpio_controller *ctlr = chip2controller(chip);
-	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
-	unsigned gpio = chip->base + offset;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-
-	gpio_reg_set_bit(regs->direction, gpio);
-
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-
-	return 0;
-}
-
-static int tnetv107x_gpio_dir_out(struct gpio_chip *chip,
-		unsigned offset, int value)
-{
-	struct davinci_gpio_controller *ctlr = chip2controller(chip);
-	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
-	unsigned gpio = chip->base + offset;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-
-	if (value)
-		gpio_reg_set_bit(regs->data_out, gpio);
-	else
-		gpio_reg_clear_bit(regs->data_out, gpio);
-
-	gpio_reg_clear_bit(regs->direction, gpio);
-
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-
-	return 0;
-}
-
-static int tnetv107x_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct davinci_gpio_controller *ctlr = chip2controller(chip);
-	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
-	unsigned gpio = chip->base + offset;
-	int ret;
-
-	ret = gpio_reg_get_bit(regs->data_in, gpio);
-
-	return ret ? 1 : 0;
-}
-
-static void tnetv107x_gpio_set(struct gpio_chip *chip,
-		unsigned offset, int value)
-{
-	struct davinci_gpio_controller *ctlr = chip2controller(chip);
-	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
-	unsigned gpio = chip->base + offset;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-
-	if (value)
-		gpio_reg_set_bit(regs->data_out, gpio);
-	else
-		gpio_reg_clear_bit(regs->data_out, gpio);
-
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-}
-
-static int __init tnetv107x_gpio_setup(void)
-{
-	int i, base;
-	unsigned ngpio;
-	struct davinci_soc_info *soc_info = &davinci_soc_info;
-	struct tnetv107x_gpio_regs *regs;
-	struct davinci_gpio_controller *ctlr;
-
-	if (soc_info->gpio_type != GPIO_TYPE_TNETV107X)
-		return 0;
-
-	ngpio = soc_info->gpio_num;
-	if (ngpio == 0) {
-		pr_err("GPIO setup:  how many GPIOs?\n");
-		return -EINVAL;
-	}
-
-	if (WARN_ON(TNETV107X_N_GPIO < ngpio))
-		ngpio = TNETV107X_N_GPIO;
-
-	regs = ioremap(soc_info->gpio_base, SZ_4K);
-	if (WARN_ON(!regs))
-		return -EINVAL;
-
-	for (i = 0, base = 0; base < ngpio; i++, base += 32) {
-		ctlr = &chips[i];
-
-		ctlr->chip.label	= "tnetv107x";
-		ctlr->chip.can_sleep	= 0;
-		ctlr->chip.base		= base;
-		ctlr->chip.ngpio	= ngpio - base;
-		if (ctlr->chip.ngpio > 32)
-			ctlr->chip.ngpio = 32;
-
-		ctlr->chip.request		= tnetv107x_gpio_request;
-		ctlr->chip.free			= tnetv107x_gpio_free;
-		ctlr->chip.direction_input	= tnetv107x_gpio_dir_in;
-		ctlr->chip.get			= tnetv107x_gpio_get;
-		ctlr->chip.direction_output	= tnetv107x_gpio_dir_out;
-		ctlr->chip.set			= tnetv107x_gpio_set;
-
-		spin_lock_init(&ctlr->lock);
-
-		ctlr->regs	= regs;
-		ctlr->set_data	= &regs->data_out[i];
-		ctlr->clr_data	= &regs->data_out[i];
-		ctlr->in_data	= &regs->data_in[i];
-
-		gpiochip_add(&ctlr->chip);
-	}
-
-	soc_info->gpio_ctlrs = chips;
-	soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32);
-	return 0;
-}
-pure_initcall(tnetv107x_gpio_setup);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/ddr2.h linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/ddr2.h
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/ddr2.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/ddr2.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,4 @@
+#define DDR2_SDRCR_OFFSET	0xc
+#define DDR2_SRPD_BIT		(1 << 23)
+#define DDR2_MCLKSTOPEN_BIT	(1 << 30)
+#define DDR2_LPMODEN_BIT	(1 << 31)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -18,56 +18,50 @@
 
 #include <linux/serial_reg.h>
 
-#include <asm/memory.h>
-
 #include <mach/serial.h>
 
 #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
 		.popsection
 
-		.macro addruart, rp, rv
+		.macro addruart, rp, rv, tmp
 
 		/* Use davinci_uart_phys/virt if already configured */
-10:		mrc	p15, 0, \rp, c1, c0
-		tst	\rp, #1			@ MMU enabled?
-		ldreq	\rp, =davinci_uart_v2p(davinci_uart_phys)
-		ldrne	\rp, =davinci_uart_phys
-		add	\rv, \rp, #4		@ davinci_uart_virt
-		ldr	\rp, [\rp, #0]
-		ldr	\rv, [\rv, #0]
+10:		adr	\rp, 99f		@ get effective addr of 99f
+		ldr	\rv, [\rp]		@ get absolute addr of 99f
+		sub	\rv, \rv, \rp		@ offset between the two
+		ldr	\rp, [\rp, #4]		@ abs addr of omap_uart_phys
+		sub	\tmp, \rp, \rv		@ make it effective
+		ldr	\rp, [\tmp, #0]		@ davinci_uart_phys
+		ldr	\rv, [\tmp, #4]		@ davinci_uart_virt
 		cmp	\rp, #0			@ is port configured?
 		cmpne	\rv, #0
-		bne	99f			@ already configured
+		bne	100f			@ already configured
 
 		/* Check the debug UART address set in uncompress.h */
-		mrc	p15, 0, \rp, c1, c0
-		tst	\rp, #1			@ MMU enabled?
+		and	\rp, pc, #0xff000000
+		ldr	\rv, =DAVINCI_UART_INFO_OFS
+		add	\rp, \rp, \rv
 
 		/* Copy uart phys address from decompressor uart info */
-		ldreq	\rv, =davinci_uart_v2p(davinci_uart_phys)
-		ldrne	\rv, =davinci_uart_phys
-		ldreq	\rp, =DAVINCI_UART_INFO
-		ldrne	\rp, =davinci_uart_p2v(DAVINCI_UART_INFO)
-		ldr	\rp, [\rp, #0]
-		str	\rp, [\rv]
+		ldr	\rv, [\rp, #0]
+		str	\rv, [\tmp, #0]
 
 		/* Copy uart virt address from decompressor uart info */
-		ldreq	\rv, =davinci_uart_v2p(davinci_uart_virt)
-		ldrne	\rv, =davinci_uart_virt
-		ldreq	\rp, =DAVINCI_UART_INFO
-		ldrne	\rp, =davinci_uart_p2v(DAVINCI_UART_INFO)
-		ldr	\rp, [\rp, #4]
-		str	\rp, [\rv]
+		ldr	\rv, [\rp, #4]
+		str	\rv, [\tmp, #4]
 
 		b	10b
-99:
+
+		.align
+99:		.word	.
+		.word	davinci_uart_phys
+		.ltorg
+
+100:
 		.endm
 
 		.macro	senduart,rd,rx
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/gpio-davinci.h linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/gpio-davinci.h
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/gpio-davinci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/gpio-davinci.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,91 @@
+/*
+ * TI DaVinci GPIO Support
+ *
+ * Copyright (c) 2006 David Brownell
+ * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.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.
+ */
+
+#ifndef	__DAVINCI_DAVINCI_GPIO_H
+#define	__DAVINCI_DAVINCI_GPIO_H
+
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+#include <asm-generic/gpio.h>
+
+#include <mach/irqs.h>
+#include <mach/common.h>
+
+#define DAVINCI_GPIO_BASE 0x01C67000
+
+enum davinci_gpio_type {
+	GPIO_TYPE_DAVINCI = 0,
+	GPIO_TYPE_TNETV107X,
+};
+
+/*
+ * basic gpio routines
+ *
+ * board-specific init should be done by arch/.../.../board-XXX.c (maybe
+ * initializing banks together) rather than boot loaders; kexec() won't
+ * go through boot loaders.
+ *
+ * the gpio clock will be turned on when gpios are used, and you may also
+ * need to pay attention to PINMUX registers to be sure those pins are
+ * used as gpios, not with other peripherals.
+ *
+ * On-chip GPIOs are numbered 0..(DAVINCI_N_GPIO-1).  For documentation,
+ * and maybe for later updates, code may write GPIO(N).  These may be
+ * all 1.8V signals, all 3.3V ones, or a mix of the two.  A given chip
+ * may not support all the GPIOs in that range.
+ *
+ * GPIOs can also be on external chips, numbered after the ones built-in
+ * to the DaVinci chip.  For now, they won't be usable as IRQ sources.
+ */
+#define	GPIO(X)		(X)		/* 0 <= X <= (DAVINCI_N_GPIO - 1) */
+
+/* Convert GPIO signal to GPIO pin number */
+#define GPIO_TO_PIN(bank, gpio)	(16 * (bank) + (gpio))
+
+struct davinci_gpio_controller {
+	struct gpio_chip	chip;
+	int			irq_base;
+	spinlock_t		lock;
+	void __iomem		*regs;
+	void __iomem		*set_data;
+	void __iomem		*clr_data;
+	void __iomem		*in_data;
+};
+
+/* The __gpio_to_controller() and __gpio_mask() functions inline to constants
+ * with constant parameters; or in outlined code they execute at runtime.
+ *
+ * You'd access the controller directly when reading or writing more than
+ * one gpio value at a time, and to support wired logic where the value
+ * being driven by the cpu need not match the value read back.
+ *
+ * These are NOT part of the cross-platform GPIO interface
+ */
+static inline struct davinci_gpio_controller *
+__gpio_to_controller(unsigned gpio)
+{
+	struct davinci_gpio_controller *ctlrs = davinci_soc_info.gpio_ctlrs;
+	int index = gpio / 32;
+
+	if (!ctlrs || index >= davinci_soc_info.gpio_ctlrs_num)
+		return NULL;
+
+	return ctlrs + index;
+}
+
+static inline u32 __gpio_mask(unsigned gpio)
+{
+	return 1 << (gpio % 32);
+}
+
+#endif	/* __DAVINCI_DAVINCI_GPIO_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,80 +13,12 @@
 #ifndef	__DAVINCI_GPIO_H
 #define	__DAVINCI_GPIO_H
 
-#include <linux/io.h>
-#include <linux/spinlock.h>
-
 #include <asm-generic/gpio.h>
 
-#include <mach/irqs.h>
-#include <mach/common.h>
-
-#define DAVINCI_GPIO_BASE 0x01C67000
-
-enum davinci_gpio_type {
-	GPIO_TYPE_DAVINCI = 0,
-	GPIO_TYPE_TNETV107X,
-};
-
-/*
- * basic gpio routines
- *
- * board-specific init should be done by arch/.../.../board-XXX.c (maybe
- * initializing banks together) rather than boot loaders; kexec() won't
- * go through boot loaders.
- *
- * the gpio clock will be turned on when gpios are used, and you may also
- * need to pay attention to PINMUX registers to be sure those pins are
- * used as gpios, not with other peripherals.
- *
- * On-chip GPIOs are numbered 0..(DAVINCI_N_GPIO-1).  For documentation,
- * and maybe for later updates, code may write GPIO(N).  These may be
- * all 1.8V signals, all 3.3V ones, or a mix of the two.  A given chip
- * may not support all the GPIOs in that range.
- *
- * GPIOs can also be on external chips, numbered after the ones built-in
- * to the DaVinci chip.  For now, they won't be usable as IRQ sources.
- */
-#define	GPIO(X)		(X)		/* 0 <= X <= (DAVINCI_N_GPIO - 1) */
-
-/* Convert GPIO signal to GPIO pin number */
-#define GPIO_TO_PIN(bank, gpio)	(16 * (bank) + (gpio))
-
-struct davinci_gpio_controller {
-	struct gpio_chip	chip;
-	int			irq_base;
-	spinlock_t		lock;
-	void __iomem		*regs;
-	void __iomem		*set_data;
-	void __iomem		*clr_data;
-	void __iomem		*in_data;
-};
-
-/* The __gpio_to_controller() and __gpio_mask() functions inline to constants
- * with constant parameters; or in outlined code they execute at runtime.
- *
- * You'd access the controller directly when reading or writing more than
- * one gpio value at a time, and to support wired logic where the value
- * being driven by the cpu need not match the value read back.
- *
- * These are NOT part of the cross-platform GPIO interface
- */
-static inline struct davinci_gpio_controller *
-__gpio_to_controller(unsigned gpio)
-{
-	struct davinci_gpio_controller *ctlrs = davinci_soc_info.gpio_ctlrs;
-	int index = gpio / 32;
-
-	if (!ctlrs || index >= davinci_soc_info.gpio_ctlrs_num)
-		return NULL;
-
-	return ctlrs + index;
-}
+#define __ARM_GPIOLIB_COMPLEX
 
-static inline u32 __gpio_mask(unsigned gpio)
-{
-	return 1 << (gpio % 32);
-}
+/* The inline versions use the static inlines in the driver header */
+#include "gpio-davinci.h"
 
 /*
  * The get/set/clear functions will inline when called with constant
@@ -147,11 +79,6 @@
 		return __gpio_cansleep(gpio);
 }
 
-static inline int gpio_to_irq(unsigned gpio)
-{
-	return __gpio_to_irq(gpio);
-}
-
 static inline int irq_to_gpio(unsigned irq)
 {
 	/* don't support the reverse mapping */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/*
- * DaVinci memory space definitions
- *
- * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
- *
- * 2007 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/**************************************************************************
- * Included Files
- **************************************************************************/
-#include <asm/page.h>
-#include <asm/sizes.h>
-
-/**************************************************************************
- * Definitions
- **************************************************************************/
-#define DAVINCI_DDR_BASE	0x80000000
-#define DA8XX_DDR_BASE		0xc0000000
-
-#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 PLAT_PHYS_OFFSET DA8XX_DDR_BASE
-#else
-#define PLAT_PHYS_OFFSET DAVINCI_DDR_BASE
-#endif
-
-#define DDR2_SDRCR_OFFSET	0xc
-#define DDR2_SRPD_BIT		BIT(23)
-#define DDR2_MCLKSTOPEN_BIT	BIT(30)
-#define DDR2_LPMODEN_BIT	BIT(31)
-
-/*
- * Increase size of DMA-consistent memory region
- */
-#define CONSISTENT_DMA_SIZE (14<<20)
-
-#endif /* __ASM_ARCH_MEMORY_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/mmc.h linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/mmc.h
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/mmc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/mmc.h	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,9 @@
 	/* get_cd()/get_wp() may sleep */
 	int	(*get_cd)(int module);
 	int	(*get_ro)(int module);
+
+	void	(*set_power)(int module, bool on);
+
 	/* wires == 0 is equivalent to wires == 4 (4-bit parallel) */
 	u8	wires;
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/mux.h linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/mux.h
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/mux.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/mux.h	2012-01-04 18:55:44.000000000 -0500
@@ -857,6 +857,14 @@
 	DA850_MMCSD0_CLK,
 	DA850_MMCSD0_CMD,
 
+	/* MMC/SD1 function */
+	DA850_MMCSD1_DAT_0,
+	DA850_MMCSD1_DAT_1,
+	DA850_MMCSD1_DAT_2,
+	DA850_MMCSD1_DAT_3,
+	DA850_MMCSD1_CLK,
+	DA850_MMCSD1_CMD,
+
 	/* EMIF2.5/EMIFA function */
 	DA850_EMA_D_7,
 	DA850_EMA_D_6,
@@ -916,6 +924,8 @@
 	DA850_GPIO3_13,
 	DA850_GPIO4_0,
 	DA850_GPIO4_1,
+	DA850_GPIO6_9,
+	DA850_GPIO6_10,
 	DA850_GPIO6_13,
 	DA850_RTC_ALARM,
 };
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/nand.h linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/nand.h
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/nand.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/nand.h	2012-01-04 18:55:44.000000000 -0500
@@ -74,8 +74,10 @@
 	nand_ecc_modes_t	ecc_mode;
 	u8			ecc_bits;
 
-	/* e.g. NAND_BUSWIDTH_16 or NAND_USE_FLASH_BBT */
+	/* e.g. NAND_BUSWIDTH_16 */
 	unsigned		options;
+	/* e.g. NAND_BBT_USE_FLASH */
+	unsigned		bbt_options;
 
 	/* Main and mirror bbt descriptor overrides */
 	struct nand_bbt_descr	*bbt_td;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/psc.h linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/psc.h
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/psc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/psc.h	2012-01-04 18:55:44.000000000 -0500
@@ -233,7 +233,7 @@
 #define PTCMD		0x120
 #define PTSTAT		0x128
 #define PDSTAT		0x200
-#define PDCTL1		0x304
+#define PDCTL		0x300
 #define MDSTAT		0x800
 #define MDCTL		0xA00
 
@@ -244,7 +244,10 @@
 #define PSC_STATE_ENABLE	3
 
 #define MDSTAT_STATE_MASK	0x3f
+#define PDSTAT_STATE_MASK	0x1f
 #define MDCTL_FORCE		BIT(31)
+#define PDCTL_NEXT		BIT(1)
+#define PDCTL_EPCGOOD		BIT(8)
 
 #ifndef __ASSEMBLER__
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/serial.h linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/serial.h
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/serial.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/serial.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,8 +21,9 @@
  * macros in debug-macro.S.
  *
  * This area sits just below the page tables (see arch/arm/kernel/head.S).
+ * We define it as a relative offset from start of usable RAM.
  */
-#define DAVINCI_UART_INFO	(PLAT_PHYS_OFFSET + 0x3ff8)
+#define DAVINCI_UART_INFO_OFS	0x3ff8
 
 #define DAVINCI_UART0_BASE	(IO_PHYS + 0x20000)
 #define DAVINCI_UART1_BASE	(IO_PHYS + 0x20400)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/uncompress.h linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/uncompress.h
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/include/mach/uncompress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/include/mach/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,12 @@
 
 static inline void set_uart_info(u32 phys, void * __iomem virt)
 {
-	u32 *uart_info = (u32 *)(DAVINCI_UART_INFO);
+	/*
+	 * Get address of some.bss variable and round it down
+	 * a la CONFIG_AUTO_ZRELADDR.
+	 */
+	u32 ram_start = (u32)&uart & 0xf8000000;
+	u32 *uart_info = (u32 *)(ram_start + DAVINCI_UART_INFO_OFS);
 
 	uart = (u32 *)phys;
 	uart_info[0] = phys;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/Kconfig linux-libre-3.2-gnu/arch/arm/mach-davinci/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -192,6 +192,16 @@
 
 endchoice
 
+config DA850_WL12XX
+	bool "AM18x wl1271 daughter board"
+	depends on MACH_DAVINCI_DA850_EVM
+	help
+	  The wl1271 daughter card for AM18x EVMs is a combo wireless
+	  connectivity add-on card, based on the LS Research TiWi module with
+	  Texas Instruments' wl1271 solution.
+	  Say Y if you want to use a wl1271 expansion card connected to the
+	  AM18x EVM.
+
 config GPIO_PCA953X
 	default MACH_DAVINCI_DA850_EVM
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/Makefile linux-libre-3.2-gnu/arch/arm/mach-davinci/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
 
 # Common objects
 obj-y 			:= time.o clock.o serial.o io.o psc.o \
-			   gpio.o dma.o usb.o common.o sram.o aemif.o
+			   dma.o usb.o common.o sram.o aemif.o
 
 obj-$(CONFIG_DAVINCI_MUX)		+= mux.o
 
@@ -17,7 +17,6 @@
 obj-$(CONFIG_ARCH_DAVINCI_DA830)        += da830.o devices-da8xx.o
 obj-$(CONFIG_ARCH_DAVINCI_DA850)        += da850.o devices-da8xx.o
 obj-$(CONFIG_ARCH_DAVINCI_TNETV107X)    += tnetv107x.o devices-tnetv107x.o
-obj-$(CONFIG_ARCH_DAVINCI_TNETV107X)    += gpio-tnetv107x.o
 
 obj-$(CONFIG_AINTC)			+= irq.o
 obj-$(CONFIG_CP_INTC)			+= cp_intc.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-davinci/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -2,12 +2,12 @@
 ifeq ($(CONFIG_ARCH_DAVINCI_DMx),y)
 $(error Cannot enable DaVinci and DA8XX platforms concurrently)
 else
-   zreladdr-y	:= 0xc0008000
+   zreladdr-y	+= 0xc0008000
 params_phys-y	:= 0xc0000100
 initrd_phys-y	:= 0xc0800000
 endif
 else
-   zreladdr-y	:= 0x80008000
+   zreladdr-y	+= 0x80008000
 params_phys-y	:= 0x80000100
 initrd_phys-y	:= 0x80800000
 endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/psc.c linux-libre-3.2-gnu/arch/arm/mach-davinci/psc.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/psc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/psc.c	2012-01-04 18:55:44.000000000 -0500
@@ -52,7 +52,7 @@
 void davinci_psc_config(unsigned int domain, unsigned int ctlr,
 		unsigned int id, bool enable, u32 flags)
 {
-	u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl;
+	u32 epcpr, ptcmd, ptstat, pdstat, pdctl, mdstat, mdctl;
 	void __iomem *psc_base;
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 	u32 next_state = PSC_STATE_ENABLE;
@@ -79,11 +79,11 @@
 		mdctl |= MDCTL_FORCE;
 	__raw_writel(mdctl, psc_base + MDCTL + 4 * id);
 
-	pdstat = __raw_readl(psc_base + PDSTAT);
-	if ((pdstat & 0x00000001) == 0) {
-		pdctl1 = __raw_readl(psc_base + PDCTL1);
-		pdctl1 |= 0x1;
-		__raw_writel(pdctl1, psc_base + PDCTL1);
+	pdstat = __raw_readl(psc_base + PDSTAT + 4 * domain);
+	if ((pdstat & PDSTAT_STATE_MASK) == 0) {
+		pdctl = __raw_readl(psc_base + PDCTL + 4 * domain);
+		pdctl |= PDCTL_NEXT;
+		__raw_writel(pdctl, psc_base + PDCTL + 4 * domain);
 
 		ptcmd = 1 << domain;
 		__raw_writel(ptcmd, psc_base + PTCMD);
@@ -92,9 +92,9 @@
 			epcpr = __raw_readl(psc_base + EPCPR);
 		} while ((((epcpr >> domain) & 1) == 0));
 
-		pdctl1 = __raw_readl(psc_base + PDCTL1);
-		pdctl1 |= 0x100;
-		__raw_writel(pdctl1, psc_base + PDCTL1);
+		pdctl = __raw_readl(psc_base + PDCTL + 4 * domain);
+		pdctl |= PDCTL_EPCGOOD;
+		__raw_writel(pdctl, psc_base + PDCTL + 4 * domain);
 	} else {
 		ptcmd = 1 << domain;
 		__raw_writel(ptcmd, psc_base + PTCMD);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/sleep.S linux-libre-3.2-gnu/arch/arm/mach-davinci/sleep.S
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/sleep.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/sleep.S	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,7 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <mach/psc.h>
-#include <mach/memory.h>
+#include <mach/ddr2.h>
 
 #include "clock.h"
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-davinci/tnetv107x.c linux-libre-3.2-gnu/arch/arm/mach-davinci/tnetv107x.c
--- linux-libre-3.1-gnu/arch/arm/mach-davinci/tnetv107x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-davinci/tnetv107x.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/clk.h>
@@ -27,9 +28,9 @@
 #include <mach/psc.h>
 #include <mach/cp_intc.h>
 #include <mach/irqs.h>
-#include <mach/gpio.h>
 #include <mach/hardware.h>
 #include <mach/tnetv107x.h>
+#include <mach/gpio-davinci.h>
 
 #include "clock.h"
 #include "mux.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-dove/cm-a510.c linux-libre-3.2-gnu/arch/arm/mach-dove/cm-a510.c
--- linux-libre-3.1-gnu/arch/arm/mach-dove/cm-a510.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-dove/cm-a510.c	2012-01-04 18:55:44.000000000 -0500
@@ -87,7 +87,7 @@
 }
 
 MACHINE_START(CM_A510, "Compulab CM-A510 Board")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= cm_a510_init,
 	.map_io		= dove_map_io,
 	.init_early	= dove_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-dove/dove-db-setup.c linux-libre-3.2-gnu/arch/arm/mach-dove/dove-db-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-dove/dove-db-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-dove/dove-db-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -94,7 +94,7 @@
 }
 
 MACHINE_START(DOVE_DB, "Marvell DB-MV88AP510-BP Development Board")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= dove_db_init,
 	.map_io		= dove_map_io,
 	.init_early	= dove_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-dove/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-dove/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-dove/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-dove/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
 
 #include <mach/bridge-regs.h>
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldr	\rp, =DOVE_SB_REGS_PHYS_BASE
 	ldr	\rv, =DOVE_SB_REGS_VIRT_BASE
 	orr	\rp, \rp, #0x00012000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-dove/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-dove/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-dove/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-dove/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-/*
- * arch/arm/mach-dove/include/mach/memory.h
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET		UL(0x00000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-dove/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-dove/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-dove/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-dove/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ebsa110/core.c linux-libre-3.2-gnu/arch/arm/mach-ebsa110/core.c
--- linux-libre-3.1-gnu/arch/arm/mach-ebsa110/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ebsa110/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -280,7 +280,7 @@
 
 MACHINE_START(EBSA110, "EBSA110")
 	/* Maintainer: Russell King */
-	.boot_params	= 0x00000400,
+	.atag_offset	= 0x400,
 	.reserve_lp0	= 1,
 	.reserve_lp2	= 1,
 	.soft_reboot	= 1,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ebsa110/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-ebsa110/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-ebsa110/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ebsa110/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *
 **/
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0xf0000000
 		orr	\rp, \rp, #0x00000be0
 		mov	\rp, \rv
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ebsa110/include/mach/io.h linux-libre-3.2-gnu/arch/arm/mach-ebsa110/include/mach/io.h
--- linux-libre-3.1-gnu/arch/arm/mach-ebsa110/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ebsa110/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,8 +13,6 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#define IO_SPACE_LIMIT 0xffff
-
 u8 __inb8(unsigned int port);
 void __outb8(u8  val, unsigned int port);
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ebsa110/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-ebsa110/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-ebsa110/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ebsa110/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000400
 initrd_phys-y	:= 0x00800000
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ep93xx/adssphere.c linux-libre-3.2-gnu/arch/arm/mach-ep93xx/adssphere.c
--- linux-libre-3.1-gnu/arch/arm/mach-ep93xx/adssphere.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ep93xx/adssphere.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,7 @@
 
 MACHINE_START(ADSSPHERE, "ADS Sphere board")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ep93xx/core.c linux-libre-3.2-gnu/arch/arm/mach-ep93xx/core.c
--- linux-libre-3.1-gnu/arch/arm/mach-ep93xx/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ep93xx/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,11 +33,13 @@
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
 #include <linux/spi/spi.h>
+#include <linux/export.h>
 
 #include <mach/hardware.h>
 #include <mach/fb.h>
 #include <mach/ep93xx_keypad.h>
 #include <mach/ep93xx_spi.h>
+#include <mach/gpio-ep93xx.h>
 
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ep93xx/edb93xx.c linux-libre-3.2-gnu/arch/arm/mach-ep93xx/edb93xx.c
--- linux-libre-3.1-gnu/arch/arm/mach-ep93xx/edb93xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ep93xx/edb93xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <mach/hardware.h>
 #include <mach/fb.h>
 #include <mach/ep93xx_spi.h>
+#include <mach/gpio-ep93xx.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -159,6 +160,11 @@
 /*************************************************************************
  * EDB93xx I2S
  *************************************************************************/
+static struct platform_device edb93xx_audio_device = {
+	.name		= "edb93xx-audio",
+	.id		= -1,
+};
+
 static int __init edb93xx_has_audio(void)
 {
 	return (machine_is_edb9301() || machine_is_edb9302() ||
@@ -170,6 +176,7 @@
 {
 	if (edb93xx_has_audio()) {
 		ep93xx_register_i2s();
+		platform_device_register(&edb93xx_audio_device);
 	}
 }
 
@@ -240,7 +247,7 @@
 #ifdef CONFIG_MACH_EDB9301
 MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board")
 	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -251,7 +258,7 @@
 #ifdef CONFIG_MACH_EDB9302
 MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
 	/* Maintainer: George Kashperko <george@chas.com.ua> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -262,7 +269,7 @@
 #ifdef CONFIG_MACH_EDB9302A
 MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -273,7 +280,7 @@
 #ifdef CONFIG_MACH_EDB9307
 MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
 	/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -284,7 +291,7 @@
 #ifdef CONFIG_MACH_EDB9307A
 MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
 	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
-	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -295,7 +302,7 @@
 #ifdef CONFIG_MACH_EDB9312
 MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
 	/* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -306,7 +313,7 @@
 #ifdef CONFIG_MACH_EDB9315
 MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -317,7 +324,7 @@
 #ifdef CONFIG_MACH_EDB9315A
 MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ep93xx/gesbc9312.c linux-libre-3.2-gnu/arch/arm/mach-ep93xx/gesbc9312.c
--- linux-libre-3.1-gnu/arch/arm/mach-ep93xx/gesbc9312.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ep93xx/gesbc9312.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,7 @@
 
 MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ep93xx/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-ep93xx/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-ep93xx/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ep93xx/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  */
 #include <mach/ep93xx-regs.h>
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		ldr	\rp, =EP93XX_APB_PHYS_BASE	@ Physical base
 		ldr	\rv, =EP93XX_APB_VIRT_BASE	@ virtual base
 		orr	\rp, \rp, #0x000c0000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h linux-libre-3.2-gnu/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h
--- linux-libre-3.1-gnu/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,100 @@
+/* Include file for the EP93XX GPIO controller machine specifics */
+
+#ifndef __GPIO_EP93XX_H
+#define __GPIO_EP93XX_H
+
+/* GPIO port A.  */
+#define EP93XX_GPIO_LINE_A(x)		((x) + 0)
+#define EP93XX_GPIO_LINE_EGPIO0		EP93XX_GPIO_LINE_A(0)
+#define EP93XX_GPIO_LINE_EGPIO1		EP93XX_GPIO_LINE_A(1)
+#define EP93XX_GPIO_LINE_EGPIO2		EP93XX_GPIO_LINE_A(2)
+#define EP93XX_GPIO_LINE_EGPIO3		EP93XX_GPIO_LINE_A(3)
+#define EP93XX_GPIO_LINE_EGPIO4		EP93XX_GPIO_LINE_A(4)
+#define EP93XX_GPIO_LINE_EGPIO5		EP93XX_GPIO_LINE_A(5)
+#define EP93XX_GPIO_LINE_EGPIO6		EP93XX_GPIO_LINE_A(6)
+#define EP93XX_GPIO_LINE_EGPIO7		EP93XX_GPIO_LINE_A(7)
+
+/* GPIO port B.  */
+#define EP93XX_GPIO_LINE_B(x)		((x) + 8)
+#define EP93XX_GPIO_LINE_EGPIO8		EP93XX_GPIO_LINE_B(0)
+#define EP93XX_GPIO_LINE_EGPIO9		EP93XX_GPIO_LINE_B(1)
+#define EP93XX_GPIO_LINE_EGPIO10	EP93XX_GPIO_LINE_B(2)
+#define EP93XX_GPIO_LINE_EGPIO11	EP93XX_GPIO_LINE_B(3)
+#define EP93XX_GPIO_LINE_EGPIO12	EP93XX_GPIO_LINE_B(4)
+#define EP93XX_GPIO_LINE_EGPIO13	EP93XX_GPIO_LINE_B(5)
+#define EP93XX_GPIO_LINE_EGPIO14	EP93XX_GPIO_LINE_B(6)
+#define EP93XX_GPIO_LINE_EGPIO15	EP93XX_GPIO_LINE_B(7)
+
+/* GPIO port C.  */
+#define EP93XX_GPIO_LINE_C(x)		((x) + 40)
+#define EP93XX_GPIO_LINE_ROW0		EP93XX_GPIO_LINE_C(0)
+#define EP93XX_GPIO_LINE_ROW1		EP93XX_GPIO_LINE_C(1)
+#define EP93XX_GPIO_LINE_ROW2		EP93XX_GPIO_LINE_C(2)
+#define EP93XX_GPIO_LINE_ROW3		EP93XX_GPIO_LINE_C(3)
+#define EP93XX_GPIO_LINE_ROW4		EP93XX_GPIO_LINE_C(4)
+#define EP93XX_GPIO_LINE_ROW5		EP93XX_GPIO_LINE_C(5)
+#define EP93XX_GPIO_LINE_ROW6		EP93XX_GPIO_LINE_C(6)
+#define EP93XX_GPIO_LINE_ROW7		EP93XX_GPIO_LINE_C(7)
+
+/* GPIO port D.  */
+#define EP93XX_GPIO_LINE_D(x)		((x) + 24)
+#define EP93XX_GPIO_LINE_COL0		EP93XX_GPIO_LINE_D(0)
+#define EP93XX_GPIO_LINE_COL1		EP93XX_GPIO_LINE_D(1)
+#define EP93XX_GPIO_LINE_COL2		EP93XX_GPIO_LINE_D(2)
+#define EP93XX_GPIO_LINE_COL3		EP93XX_GPIO_LINE_D(3)
+#define EP93XX_GPIO_LINE_COL4		EP93XX_GPIO_LINE_D(4)
+#define EP93XX_GPIO_LINE_COL5		EP93XX_GPIO_LINE_D(5)
+#define EP93XX_GPIO_LINE_COL6		EP93XX_GPIO_LINE_D(6)
+#define EP93XX_GPIO_LINE_COL7		EP93XX_GPIO_LINE_D(7)
+
+/* GPIO port E.  */
+#define EP93XX_GPIO_LINE_E(x)		((x) + 32)
+#define EP93XX_GPIO_LINE_GRLED		EP93XX_GPIO_LINE_E(0)
+#define EP93XX_GPIO_LINE_RDLED		EP93XX_GPIO_LINE_E(1)
+#define EP93XX_GPIO_LINE_DIORn		EP93XX_GPIO_LINE_E(2)
+#define EP93XX_GPIO_LINE_IDECS1n	EP93XX_GPIO_LINE_E(3)
+#define EP93XX_GPIO_LINE_IDECS2n	EP93XX_GPIO_LINE_E(4)
+#define EP93XX_GPIO_LINE_IDEDA0		EP93XX_GPIO_LINE_E(5)
+#define EP93XX_GPIO_LINE_IDEDA1		EP93XX_GPIO_LINE_E(6)
+#define EP93XX_GPIO_LINE_IDEDA2		EP93XX_GPIO_LINE_E(7)
+
+/* GPIO port F.  */
+#define EP93XX_GPIO_LINE_F(x)		((x) + 16)
+#define EP93XX_GPIO_LINE_WP		EP93XX_GPIO_LINE_F(0)
+#define EP93XX_GPIO_LINE_MCCD1		EP93XX_GPIO_LINE_F(1)
+#define EP93XX_GPIO_LINE_MCCD2		EP93XX_GPIO_LINE_F(2)
+#define EP93XX_GPIO_LINE_MCBVD1		EP93XX_GPIO_LINE_F(3)
+#define EP93XX_GPIO_LINE_MCBVD2		EP93XX_GPIO_LINE_F(4)
+#define EP93XX_GPIO_LINE_VS1		EP93XX_GPIO_LINE_F(5)
+#define EP93XX_GPIO_LINE_READY		EP93XX_GPIO_LINE_F(6)
+#define EP93XX_GPIO_LINE_VS2		EP93XX_GPIO_LINE_F(7)
+
+/* GPIO port G.  */
+#define EP93XX_GPIO_LINE_G(x)		((x) + 48)
+#define EP93XX_GPIO_LINE_EECLK		EP93XX_GPIO_LINE_G(0)
+#define EP93XX_GPIO_LINE_EEDAT		EP93XX_GPIO_LINE_G(1)
+#define EP93XX_GPIO_LINE_SLA0		EP93XX_GPIO_LINE_G(2)
+#define EP93XX_GPIO_LINE_SLA1		EP93XX_GPIO_LINE_G(3)
+#define EP93XX_GPIO_LINE_DD12		EP93XX_GPIO_LINE_G(4)
+#define EP93XX_GPIO_LINE_DD13		EP93XX_GPIO_LINE_G(5)
+#define EP93XX_GPIO_LINE_DD14		EP93XX_GPIO_LINE_G(6)
+#define EP93XX_GPIO_LINE_DD15		EP93XX_GPIO_LINE_G(7)
+
+/* GPIO port H.  */
+#define EP93XX_GPIO_LINE_H(x)		((x) + 56)
+#define EP93XX_GPIO_LINE_DD0		EP93XX_GPIO_LINE_H(0)
+#define EP93XX_GPIO_LINE_DD1		EP93XX_GPIO_LINE_H(1)
+#define EP93XX_GPIO_LINE_DD2		EP93XX_GPIO_LINE_H(2)
+#define EP93XX_GPIO_LINE_DD3		EP93XX_GPIO_LINE_H(3)
+#define EP93XX_GPIO_LINE_DD4		EP93XX_GPIO_LINE_H(4)
+#define EP93XX_GPIO_LINE_DD5		EP93XX_GPIO_LINE_H(5)
+#define EP93XX_GPIO_LINE_DD6		EP93XX_GPIO_LINE_H(6)
+#define EP93XX_GPIO_LINE_DD7		EP93XX_GPIO_LINE_H(7)
+
+/* maximum value for gpio line identifiers */
+#define EP93XX_GPIO_LINE_MAX		EP93XX_GPIO_LINE_H(7)
+
+/* maximum value for irq capable line identifiers */
+#define EP93XX_GPIO_LINE_MAX_IRQ	EP93XX_GPIO_LINE_F(7)
+
+#endif /* __GPIO_EP93XX_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ep93xx/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-ep93xx/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-ep93xx/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ep93xx/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,120 +1 @@
-/*
- * arch/arm/mach-ep93xx/include/mach/gpio.h
- */
-
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-/* GPIO port A.  */
-#define EP93XX_GPIO_LINE_A(x)		((x) + 0)
-#define EP93XX_GPIO_LINE_EGPIO0		EP93XX_GPIO_LINE_A(0)
-#define EP93XX_GPIO_LINE_EGPIO1		EP93XX_GPIO_LINE_A(1)
-#define EP93XX_GPIO_LINE_EGPIO2		EP93XX_GPIO_LINE_A(2)
-#define EP93XX_GPIO_LINE_EGPIO3		EP93XX_GPIO_LINE_A(3)
-#define EP93XX_GPIO_LINE_EGPIO4		EP93XX_GPIO_LINE_A(4)
-#define EP93XX_GPIO_LINE_EGPIO5		EP93XX_GPIO_LINE_A(5)
-#define EP93XX_GPIO_LINE_EGPIO6		EP93XX_GPIO_LINE_A(6)
-#define EP93XX_GPIO_LINE_EGPIO7		EP93XX_GPIO_LINE_A(7)
-
-/* GPIO port B.  */
-#define EP93XX_GPIO_LINE_B(x)		((x) + 8)
-#define EP93XX_GPIO_LINE_EGPIO8		EP93XX_GPIO_LINE_B(0)
-#define EP93XX_GPIO_LINE_EGPIO9		EP93XX_GPIO_LINE_B(1)
-#define EP93XX_GPIO_LINE_EGPIO10	EP93XX_GPIO_LINE_B(2)
-#define EP93XX_GPIO_LINE_EGPIO11	EP93XX_GPIO_LINE_B(3)
-#define EP93XX_GPIO_LINE_EGPIO12	EP93XX_GPIO_LINE_B(4)
-#define EP93XX_GPIO_LINE_EGPIO13	EP93XX_GPIO_LINE_B(5)
-#define EP93XX_GPIO_LINE_EGPIO14	EP93XX_GPIO_LINE_B(6)
-#define EP93XX_GPIO_LINE_EGPIO15	EP93XX_GPIO_LINE_B(7)
-
-/* GPIO port C.  */
-#define EP93XX_GPIO_LINE_C(x)		((x) + 40)
-#define EP93XX_GPIO_LINE_ROW0		EP93XX_GPIO_LINE_C(0)
-#define EP93XX_GPIO_LINE_ROW1		EP93XX_GPIO_LINE_C(1)
-#define EP93XX_GPIO_LINE_ROW2		EP93XX_GPIO_LINE_C(2)
-#define EP93XX_GPIO_LINE_ROW3		EP93XX_GPIO_LINE_C(3)
-#define EP93XX_GPIO_LINE_ROW4		EP93XX_GPIO_LINE_C(4)
-#define EP93XX_GPIO_LINE_ROW5		EP93XX_GPIO_LINE_C(5)
-#define EP93XX_GPIO_LINE_ROW6		EP93XX_GPIO_LINE_C(6)
-#define EP93XX_GPIO_LINE_ROW7		EP93XX_GPIO_LINE_C(7)
-
-/* GPIO port D.  */
-#define EP93XX_GPIO_LINE_D(x)		((x) + 24)
-#define EP93XX_GPIO_LINE_COL0		EP93XX_GPIO_LINE_D(0)
-#define EP93XX_GPIO_LINE_COL1		EP93XX_GPIO_LINE_D(1)
-#define EP93XX_GPIO_LINE_COL2		EP93XX_GPIO_LINE_D(2)
-#define EP93XX_GPIO_LINE_COL3		EP93XX_GPIO_LINE_D(3)
-#define EP93XX_GPIO_LINE_COL4		EP93XX_GPIO_LINE_D(4)
-#define EP93XX_GPIO_LINE_COL5		EP93XX_GPIO_LINE_D(5)
-#define EP93XX_GPIO_LINE_COL6		EP93XX_GPIO_LINE_D(6)
-#define EP93XX_GPIO_LINE_COL7		EP93XX_GPIO_LINE_D(7)
-
-/* GPIO port E.  */
-#define EP93XX_GPIO_LINE_E(x)		((x) + 32)
-#define EP93XX_GPIO_LINE_GRLED		EP93XX_GPIO_LINE_E(0)
-#define EP93XX_GPIO_LINE_RDLED		EP93XX_GPIO_LINE_E(1)
-#define EP93XX_GPIO_LINE_DIORn		EP93XX_GPIO_LINE_E(2)
-#define EP93XX_GPIO_LINE_IDECS1n	EP93XX_GPIO_LINE_E(3)
-#define EP93XX_GPIO_LINE_IDECS2n	EP93XX_GPIO_LINE_E(4)
-#define EP93XX_GPIO_LINE_IDEDA0		EP93XX_GPIO_LINE_E(5)
-#define EP93XX_GPIO_LINE_IDEDA1		EP93XX_GPIO_LINE_E(6)
-#define EP93XX_GPIO_LINE_IDEDA2		EP93XX_GPIO_LINE_E(7)
-
-/* GPIO port F.  */
-#define EP93XX_GPIO_LINE_F(x)		((x) + 16)
-#define EP93XX_GPIO_LINE_WP		EP93XX_GPIO_LINE_F(0)
-#define EP93XX_GPIO_LINE_MCCD1		EP93XX_GPIO_LINE_F(1)
-#define EP93XX_GPIO_LINE_MCCD2		EP93XX_GPIO_LINE_F(2)
-#define EP93XX_GPIO_LINE_MCBVD1		EP93XX_GPIO_LINE_F(3)
-#define EP93XX_GPIO_LINE_MCBVD2		EP93XX_GPIO_LINE_F(4)
-#define EP93XX_GPIO_LINE_VS1		EP93XX_GPIO_LINE_F(5)
-#define EP93XX_GPIO_LINE_READY		EP93XX_GPIO_LINE_F(6)
-#define EP93XX_GPIO_LINE_VS2		EP93XX_GPIO_LINE_F(7)
-
-/* GPIO port G.  */
-#define EP93XX_GPIO_LINE_G(x)		((x) + 48)
-#define EP93XX_GPIO_LINE_EECLK		EP93XX_GPIO_LINE_G(0)
-#define EP93XX_GPIO_LINE_EEDAT		EP93XX_GPIO_LINE_G(1)
-#define EP93XX_GPIO_LINE_SLA0		EP93XX_GPIO_LINE_G(2)
-#define EP93XX_GPIO_LINE_SLA1		EP93XX_GPIO_LINE_G(3)
-#define EP93XX_GPIO_LINE_DD12		EP93XX_GPIO_LINE_G(4)
-#define EP93XX_GPIO_LINE_DD13		EP93XX_GPIO_LINE_G(5)
-#define EP93XX_GPIO_LINE_DD14		EP93XX_GPIO_LINE_G(6)
-#define EP93XX_GPIO_LINE_DD15		EP93XX_GPIO_LINE_G(7)
-
-/* GPIO port H.  */
-#define EP93XX_GPIO_LINE_H(x)		((x) + 56)
-#define EP93XX_GPIO_LINE_DD0		EP93XX_GPIO_LINE_H(0)
-#define EP93XX_GPIO_LINE_DD1		EP93XX_GPIO_LINE_H(1)
-#define EP93XX_GPIO_LINE_DD2		EP93XX_GPIO_LINE_H(2)
-#define EP93XX_GPIO_LINE_DD3		EP93XX_GPIO_LINE_H(3)
-#define EP93XX_GPIO_LINE_DD4		EP93XX_GPIO_LINE_H(4)
-#define EP93XX_GPIO_LINE_DD5		EP93XX_GPIO_LINE_H(5)
-#define EP93XX_GPIO_LINE_DD6		EP93XX_GPIO_LINE_H(6)
-#define EP93XX_GPIO_LINE_DD7		EP93XX_GPIO_LINE_H(7)
-
-/* maximum value for gpio line identifiers */
-#define EP93XX_GPIO_LINE_MAX		EP93XX_GPIO_LINE_H(7)
-
-/* maximum value for irq capable line identifiers */
-#define EP93XX_GPIO_LINE_MAX_IRQ	EP93XX_GPIO_LINE_F(7)
-
-/* new generic GPIO API - see Documentation/gpio.txt */
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-
-/*
- * Map GPIO A0..A7  (0..7)  to irq 64..71,
- *          B0..B7  (7..15) to irq 72..79, and
- *          F0..F7 (16..24) to irq 80..87.
- */
-#define gpio_to_irq(gpio)	\
-	(((gpio) <= EP93XX_GPIO_LINE_MAX_IRQ) ? (64 + (gpio)) : -EINVAL)
-
-#define irq_to_gpio(irq)	((irq) - gpio_to_irq(0))
-
-#endif
+/* empty */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ep93xx/Kconfig linux-libre-3.2-gnu/arch/arm/mach-ep93xx/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-ep93xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ep93xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -182,6 +182,13 @@
 	  Say 'Y' here if you want your kernel to support the
 	  Technologic Systems TS-72xx board.
 
+config MACH_VISION_EP9307
+	bool "Support Vision Engraving Systems EP9307 SoM"
+	depends on EP93XX_SDCE0_PHYS_OFFSET
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Vision Engraving Systems EP9307 SoM.
+
 choice
 	prompt "Select a UART for early kernel messages"
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ep93xx/Makefile linux-libre-3.2-gnu/arch/arm/mach-ep93xx/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-ep93xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ep93xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -15,3 +15,4 @@
 obj-$(CONFIG_MACH_SIM_ONE)	+= simone.o
 obj-$(CONFIG_MACH_SNAPPER_CL15)	+= snappercl15.o
 obj-$(CONFIG_MACH_TS72XX)	+= ts72xx.o
+obj-$(CONFIG_MACH_VISION_EP9307)+= vision_ep9307.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ep93xx/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-ep93xx/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-ep93xx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ep93xx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,14 +1,14 @@
-   zreladdr-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)	:= 0x00008000
+   zreladdr-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)	+= 0x00008000
 params_phys-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)	:= 0x00000100
 
-   zreladdr-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)		:= 0xc0008000
+   zreladdr-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)		+= 0xc0008000
 params_phys-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)		:= 0xc0000100
 
-   zreladdr-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET)		:= 0xd0008000
+   zreladdr-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET)		+= 0xd0008000
 params_phys-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET)		:= 0xd0000100
 
-   zreladdr-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET)		:= 0xe0008000
+   zreladdr-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET)		+= 0xe0008000
 params_phys-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET)		:= 0xe0000100
 
-   zreladdr-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET)	:= 0xf0008000
+   zreladdr-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET)	+= 0xf0008000
 params_phys-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET)	:= 0xf0000100
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ep93xx/micro9.c linux-libre-3.2-gnu/arch/arm/mach-ep93xx/micro9.c
--- linux-libre-3.1-gnu/arch/arm/mach-ep93xx/micro9.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ep93xx/micro9.c	2012-01-04 18:55:44.000000000 -0500
@@ -77,7 +77,7 @@
 #ifdef CONFIG_MACH_MICRO9H
 MACHINE_START(MICRO9, "Contec Micro9-High")
 	/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -88,7 +88,7 @@
 #ifdef CONFIG_MACH_MICRO9M
 MACHINE_START(MICRO9M, "Contec Micro9-Mid")
 	/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -99,7 +99,7 @@
 #ifdef CONFIG_MACH_MICRO9L
 MACHINE_START(MICRO9L, "Contec Micro9-Lite")
 	/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
@@ -110,7 +110,7 @@
 #ifdef CONFIG_MACH_MICRO9S
 MACHINE_START(MICRO9S, "Contec Micro9-Slim")
 	/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ep93xx/simone.c linux-libre-3.2-gnu/arch/arm/mach-ep93xx/simone.c
--- linux-libre-3.1-gnu/arch/arm/mach-ep93xx/simone.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ep93xx/simone.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,12 +18,12 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
 
 #include <mach/hardware.h>
 #include <mach/fb.h>
+#include <mach/gpio-ep93xx.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -53,6 +53,17 @@
 	},
 };
 
+static struct platform_device simone_audio_device = {
+	.name		= "simone-audio",
+	.id		= -1,
+};
+
+static void __init simone_register_audio(void)
+{
+	ep93xx_register_ac97();
+	platform_device_register(&simone_audio_device);
+}
+
 static void __init simone_init_machine(void)
 {
 	ep93xx_init_devices();
@@ -61,12 +72,12 @@
 	ep93xx_register_fb(&simone_fb_info);
 	ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info,
 			    ARRAY_SIZE(simone_i2c_board_info));
-	ep93xx_register_ac97();
+	simone_register_audio();
 }
 
 MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
-/* Maintainer: Ryan Mallon */
-	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
+	/* Maintainer: Ryan Mallon */
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ep93xx/snappercl15.c linux-libre-3.2-gnu/arch/arm/mach-ep93xx/snappercl15.c
--- linux-libre-3.1-gnu/arch/arm/mach-ep93xx/snappercl15.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ep93xx/snappercl15.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
 #include <linux/fb.h>
@@ -30,6 +29,7 @@
 
 #include <mach/hardware.h>
 #include <mach/fb.h>
+#include <mach/gpio-ep93xx.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -150,6 +150,17 @@
 	.bpp			= 16,
 };
 
+static struct platform_device snappercl15_audio_device = {
+	.name		= "snappercl15-audio",
+	.id		= -1,
+};
+
+static void __init snappercl15_register_audio(void)
+{
+	ep93xx_register_i2s();
+	platform_device_register(&snappercl15_audio_device);
+}
+
 static void __init snappercl15_init_machine(void)
 {
 	ep93xx_init_devices();
@@ -157,13 +168,13 @@
 	ep93xx_register_i2c(&snappercl15_i2c_gpio_data, snappercl15_i2c_data,
 			    ARRAY_SIZE(snappercl15_i2c_data));
 	ep93xx_register_fb(&snappercl15_fb_info);
-	ep93xx_register_i2s();
+	snappercl15_register_audio();
 	platform_device_register(&snappercl15_nand_device);
 }
 
 MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15")
 	/* Maintainer: Ryan Mallon */
-	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer 		= &ep93xx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ep93xx/ts72xx.c linux-libre-3.2-gnu/arch/arm/mach-ep93xx/ts72xx.c
--- linux-libre-3.1-gnu/arch/arm/mach-ep93xx/ts72xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ep93xx/ts72xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -116,8 +116,9 @@
 		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
 	}, {
 		.name		= "Linux",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= 0,			/* filled in later */
+		.offset		= MTDPART_OFS_RETAIN,
+		.size		= TS72XX_REDBOOT_PART_SIZE,
+				/* leave so much for last partition */
 	}, {
 		.name		= "RedBoot",
 		.offset		= MTDPART_OFS_APPEND,
@@ -126,28 +127,14 @@
 	},
 };
 
-static void ts72xx_nand_set_parts(uint64_t size,
-				  struct platform_nand_chip *chip)
-{
-	/* Factory TS-72xx boards only come with 32MiB or 128MiB NAND options */
-	if (size == SZ_32M || size == SZ_128M) {
-		/* Set the "Linux" partition size */
-		ts72xx_nand_parts[1].size = size - TS72XX_REDBOOT_PART_SIZE;
-
-		chip->partitions = ts72xx_nand_parts;
-		chip->nr_partitions = ARRAY_SIZE(ts72xx_nand_parts);
-	} else {
-		pr_warning("Unknown nand disk size:%lluMiB\n", size >> 20);
-	}
-}
-
 static struct platform_nand_data ts72xx_nand_data = {
 	.chip = {
 		.nr_chips	= 1,
 		.chip_offset	= 0,
 		.chip_delay	= 15,
 		.part_probe_types = ts72xx_nand_part_probes,
-		.set_parts	= ts72xx_nand_set_parts,
+		.partitions	= ts72xx_nand_parts,
+		.nr_partitions	= ARRAY_SIZE(ts72xx_nand_parts),
 	},
 	.ctrl = {
 		.cmd_ctrl	= ts72xx_nand_hwcontrol,
@@ -257,7 +244,7 @@
 
 MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ts72xx_map_io,
 	.init_irq	= ep93xx_init_irq,
 	.timer		= &ep93xx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ep93xx/vision_ep9307.c linux-libre-3.2-gnu/arch/arm/mach-ep93xx/vision_ep9307.c
--- linux-libre-3.1-gnu/arch/arm/mach-ep93xx/vision_ep9307.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-ep93xx/vision_ep9307.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,364 @@
+/*
+ * arch/arm/mach-ep93xx/vision_ep9307.c
+ * Vision Engraving Systems EP9307 SoM support.
+ *
+ * Copyright (C) 2008-2011 Vision Engraving Systems
+ * H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/mtd/partitions.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/mmc_spi.h>
+#include <linux/mmc/host.h>
+
+#include <mach/hardware.h>
+#include <mach/fb.h>
+#include <mach/ep93xx_spi.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+
+/*************************************************************************
+ * Static I/O mappings for the FPGA
+ *************************************************************************/
+#define VISION_PHYS_BASE	EP93XX_CS7_PHYS_BASE
+#define VISION_VIRT_BASE	0xfebff000
+
+static struct map_desc vision_io_desc[] __initdata = {
+	{
+		.virtual	= VISION_VIRT_BASE,
+		.pfn		= __phys_to_pfn(VISION_PHYS_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static void __init vision_map_io(void)
+{
+	ep93xx_map_io();
+
+	iotable_init(vision_io_desc, ARRAY_SIZE(vision_io_desc));
+}
+
+/*************************************************************************
+ * Ethernet
+ *************************************************************************/
+static struct ep93xx_eth_data vision_eth_data __initdata = {
+	.phy_id		= 1,
+};
+
+/*************************************************************************
+ * Framebuffer
+ *************************************************************************/
+#define VISION_LCD_ENABLE	EP93XX_GPIO_LINE_EGPIO1
+
+static int vision_lcd_setup(struct platform_device *pdev)
+{
+	int err;
+
+	err = gpio_request_one(VISION_LCD_ENABLE, GPIOF_INIT_HIGH,
+				dev_name(&pdev->dev));
+	if (err)
+		return err;
+
+	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_RAS |
+				 EP93XX_SYSCON_DEVCFG_RASONP3 |
+				 EP93XX_SYSCON_DEVCFG_EXVC);
+
+	return 0;
+}
+
+static void vision_lcd_teardown(struct platform_device *pdev)
+{
+	gpio_free(VISION_LCD_ENABLE);
+}
+
+static void vision_lcd_blank(int blank_mode, struct fb_info *info)
+{
+	if (blank_mode)
+		gpio_set_value(VISION_LCD_ENABLE, 0);
+	else
+		gpio_set_value(VISION_LCD_ENABLE, 1);
+}
+
+static struct ep93xxfb_mach_info ep93xxfb_info __initdata = {
+	.num_modes	= EP93XXFB_USE_MODEDB,
+	.bpp		= 16,
+	.flags		= EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING,
+	.setup		= vision_lcd_setup,
+	.teardown	= vision_lcd_teardown,
+	.blank		= vision_lcd_blank,
+};
+
+
+/*************************************************************************
+ * GPIO Expanders
+ *************************************************************************/
+#define PCA9539_74_GPIO_BASE	(EP93XX_GPIO_LINE_MAX + 1)
+#define PCA9539_75_GPIO_BASE	(PCA9539_74_GPIO_BASE + 16)
+#define PCA9539_76_GPIO_BASE	(PCA9539_75_GPIO_BASE + 16)
+#define PCA9539_77_GPIO_BASE	(PCA9539_76_GPIO_BASE + 16)
+
+static struct pca953x_platform_data pca953x_74_gpio_data = {
+	.gpio_base	= PCA9539_74_GPIO_BASE,
+	.irq_base	= EP93XX_BOARD_IRQ(0),
+};
+
+static struct pca953x_platform_data pca953x_75_gpio_data = {
+	.gpio_base	= PCA9539_75_GPIO_BASE,
+	.irq_base	= -1,
+};
+
+static struct pca953x_platform_data pca953x_76_gpio_data = {
+	.gpio_base	= PCA9539_76_GPIO_BASE,
+	.irq_base	= -1,
+};
+
+static struct pca953x_platform_data pca953x_77_gpio_data = {
+	.gpio_base	= PCA9539_77_GPIO_BASE,
+	.irq_base	= -1,
+};
+
+/*************************************************************************
+ * I2C Bus
+ *************************************************************************/
+static struct i2c_gpio_platform_data vision_i2c_gpio_data __initdata = {
+	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
+	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
+};
+
+static struct i2c_board_info vision_i2c_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("isl1208", 0x6f),
+		.irq		= IRQ_EP93XX_EXT1,
+	}, {
+		I2C_BOARD_INFO("pca9539", 0x74),
+		.platform_data	= &pca953x_74_gpio_data,
+		.irq		= gpio_to_irq(EP93XX_GPIO_LINE_F(7)),
+	}, {
+		I2C_BOARD_INFO("pca9539", 0x75),
+		.platform_data	= &pca953x_75_gpio_data,
+	}, {
+		I2C_BOARD_INFO("pca9539", 0x76),
+		.platform_data	= &pca953x_76_gpio_data,
+	}, {
+		I2C_BOARD_INFO("pca9539", 0x77),
+		.platform_data	= &pca953x_77_gpio_data,
+	},
+};
+
+/*************************************************************************
+ * SPI Flash
+ *************************************************************************/
+#define VISION_SPI_FLASH_CS	EP93XX_GPIO_LINE_EGPIO7
+
+static struct mtd_partition vision_spi_flash_partitions[] = {
+	{
+		.name	= "SPI bootstrap",
+		.offset	= 0,
+		.size	= SZ_4K,
+	}, {
+		.name	= "Bootstrap config",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= SZ_4K,
+	}, {
+		.name	= "System config",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct flash_platform_data vision_spi_flash_data = {
+	.name		= "SPI Flash",
+	.parts		= vision_spi_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(vision_spi_flash_partitions),
+};
+
+static int vision_spi_flash_hw_setup(struct spi_device *spi)
+{
+	return gpio_request_one(VISION_SPI_FLASH_CS, GPIOF_INIT_HIGH,
+				spi->modalias);
+}
+
+static void vision_spi_flash_hw_cleanup(struct spi_device *spi)
+{
+	gpio_free(VISION_SPI_FLASH_CS);
+}
+
+static void vision_spi_flash_hw_cs_control(struct spi_device *spi, int value)
+{
+	gpio_set_value(VISION_SPI_FLASH_CS, value);
+}
+
+static struct ep93xx_spi_chip_ops vision_spi_flash_hw = {
+	.setup		= vision_spi_flash_hw_setup,
+	.cleanup	= vision_spi_flash_hw_cleanup,
+	.cs_control	= vision_spi_flash_hw_cs_control,
+};
+
+/*************************************************************************
+ * SPI SD/MMC host
+ *************************************************************************/
+#define VISION_SPI_MMC_CS	EP93XX_GPIO_LINE_G(2)
+#define VISION_SPI_MMC_WP	EP93XX_GPIO_LINE_F(0)
+#define VISION_SPI_MMC_CD	EP93XX_GPIO_LINE_EGPIO15
+
+static struct gpio vision_spi_mmc_gpios[] = {
+	{ VISION_SPI_MMC_WP, GPIOF_DIR_IN, "mmc_spi:wp" },
+	{ VISION_SPI_MMC_CD, GPIOF_DIR_IN, "mmc_spi:cd" },
+};
+
+static int vision_spi_mmc_init(struct device *pdev,
+			irqreturn_t (*func)(int, void *), void *pdata)
+{
+	int err;
+
+	err = gpio_request_array(vision_spi_mmc_gpios,
+				 ARRAY_SIZE(vision_spi_mmc_gpios));
+	if (err)
+		return err;
+
+	err = gpio_set_debounce(VISION_SPI_MMC_CD, 1);
+	if (err)
+		goto exit_err;
+
+	err = request_irq(gpio_to_irq(VISION_SPI_MMC_CD), func,
+			IRQ_TYPE_EDGE_BOTH, "mmc_spi:cd", pdata);
+	if (err)
+		goto exit_err;
+
+	return 0;
+
+exit_err:
+	gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
+	return err;
+
+}
+
+static void vision_spi_mmc_exit(struct device *pdev, void *pdata)
+{
+	free_irq(gpio_to_irq(VISION_SPI_MMC_CD), pdata);
+	gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
+}
+
+static int vision_spi_mmc_get_ro(struct device *pdev)
+{
+	return !!gpio_get_value(VISION_SPI_MMC_WP);
+}
+
+static int vision_spi_mmc_get_cd(struct device *pdev)
+{
+	return !gpio_get_value(VISION_SPI_MMC_CD);
+}
+
+static struct mmc_spi_platform_data vision_spi_mmc_data = {
+	.init		= vision_spi_mmc_init,
+	.exit		= vision_spi_mmc_exit,
+	.get_ro		= vision_spi_mmc_get_ro,
+	.get_cd		= vision_spi_mmc_get_cd,
+	.detect_delay	= 100,
+	.powerup_msecs	= 100,
+	.ocr_mask	= MMC_VDD_32_33 | MMC_VDD_33_34,
+};
+
+static int vision_spi_mmc_hw_setup(struct spi_device *spi)
+{
+	return gpio_request_one(VISION_SPI_MMC_CS, GPIOF_INIT_HIGH,
+				spi->modalias);
+}
+
+static void vision_spi_mmc_hw_cleanup(struct spi_device *spi)
+{
+	gpio_free(VISION_SPI_MMC_CS);
+}
+
+static void vision_spi_mmc_hw_cs_control(struct spi_device *spi, int value)
+{
+	gpio_set_value(VISION_SPI_MMC_CS, value);
+}
+
+static struct ep93xx_spi_chip_ops vision_spi_mmc_hw = {
+	.setup		= vision_spi_mmc_hw_setup,
+	.cleanup	= vision_spi_mmc_hw_cleanup,
+	.cs_control	= vision_spi_mmc_hw_cs_control,
+};
+
+/*************************************************************************
+ * SPI Bus
+ *************************************************************************/
+static struct spi_board_info vision_spi_board_info[] __initdata = {
+	{
+		.modalias		= "sst25l",
+		.platform_data		= &vision_spi_flash_data,
+		.controller_data	= &vision_spi_flash_hw,
+		.max_speed_hz		= 20000000,
+		.bus_num		= 0,
+		.chip_select		= 0,
+		.mode			= SPI_MODE_3,
+	}, {
+		.modalias		= "mmc_spi",
+		.platform_data		= &vision_spi_mmc_data,
+		.controller_data	= &vision_spi_mmc_hw,
+		.max_speed_hz		= 20000000,
+		.bus_num		= 0,
+		.chip_select		= 1,
+		.mode			= SPI_MODE_3,
+	},
+};
+
+static struct ep93xx_spi_info vision_spi_master __initdata = {
+	.num_chipselect		= ARRAY_SIZE(vision_spi_board_info),
+};
+
+/*************************************************************************
+ * Machine Initialization
+ *************************************************************************/
+static void __init vision_init_machine(void)
+{
+	ep93xx_init_devices();
+	ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_64M);
+	ep93xx_register_eth(&vision_eth_data, 1);
+	ep93xx_register_fb(&ep93xxfb_info);
+	ep93xx_register_pwm(1, 0);
+
+	/*
+	 * Request the gpio expander's interrupt gpio line now to prevent
+	 * the kernel from doing a WARN in gpiolib:gpio_ensure_requested().
+	 */
+	if (gpio_request_one(EP93XX_GPIO_LINE_F(7), GPIOF_DIR_IN,
+				"pca9539:74"))
+		pr_warn("cannot request interrupt gpio for pca9539:74\n");
+
+	ep93xx_register_i2c(&vision_i2c_gpio_data, vision_i2c_info,
+				ARRAY_SIZE(vision_i2c_info));
+	ep93xx_register_spi(&vision_spi_master, vision_spi_board_info,
+				ARRAY_SIZE(vision_spi_board_info));
+}
+
+MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307")
+	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
+	.atag_offset	= 0x100,
+	.map_io		= vision_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.timer		= &ep93xx_timer,
+	.init_machine	= vision_init_machine,
+MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/clock.c linux-libre-3.2-gnu/arch/arm/mach-exynos/clock.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/clock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1491 @@
+/* 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 <linux/syscore_ops.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 <plat/exynos4.h>
+#include <plat/pm.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/sysmmu.h>
+#include <mach/exynos4-clock.h>
+
+static struct sleep_save exynos4_clock_save[] = {
+	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_CLKSRC_TOP0),
+	SAVE_ITEM(S5P_CLKSRC_TOP1),
+	SAVE_ITEM(S5P_CLKSRC_CAM),
+	SAVE_ITEM(S5P_CLKSRC_TV),
+	SAVE_ITEM(S5P_CLKSRC_MFC),
+	SAVE_ITEM(S5P_CLKSRC_G3D),
+	SAVE_ITEM(S5P_CLKSRC_LCD0),
+	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_LCD0),
+	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_TOP),
+	SAVE_ITEM(S5P_CLKSRC_MASK_CAM),
+	SAVE_ITEM(S5P_CLKSRC_MASK_TV),
+	SAVE_ITEM(S5P_CLKSRC_MASK_LCD0),
+	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_CLKDIV2_RATIO),
+	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_LCD0),
+	SAVE_ITEM(S5P_CLKGATE_IP_FSYS),
+	SAVE_ITEM(S5P_CLKGATE_IP_GPS),
+	SAVE_ITEM(S5P_CLKGATE_IP_PERIL),
+	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_CLKDIV_CPU + 0x4),
+	SAVE_ITEM(S5P_CLKGATE_SCLKCPU),
+	SAVE_ITEM(S5P_CLKGATE_IP_CPU),
+};
+
+struct clk clk_sclk_hdmi27m = {
+	.name		= "sclk_hdmi27m",
+	.rate		= 27000000,
+};
+
+struct clk clk_sclk_hdmiphy = {
+	.name		= "sclk_hdmiphy",
+};
+
+struct clk clk_sclk_usbphy0 = {
+	.name		= "sclk_usbphy0",
+	.rate		= 27000000,
+};
+
+struct clk clk_sclk_usbphy1 = {
+	.name		= "sclk_usbphy1",
+};
+
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.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);
+}
+
+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_clksrc_mask_tv_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_TV, 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);
+}
+
+int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_LCD1, clk, enable);
+}
+
+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);
+}
+
+static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
+}
+
+static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
+}
+
+/* Core list of CMU_CPU side */
+
+static struct clksrc_clk clk_mout_apll = {
+	.clk	= {
+		.name		= "mout_apll",
+	},
+	.sources	= &clk_src_apll,
+	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 },
+};
+
+struct clksrc_clk clk_sclk_apll = {
+	.clk	= {
+		.name		= "sclk_apll",
+		.parent		= &clk_mout_apll.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 },
+};
+
+struct clksrc_clk clk_mout_epll = {
+	.clk	= {
+		.name		= "mout_epll",
+	},
+	.sources	= &clk_src_epll,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 },
+};
+
+struct clksrc_clk clk_mout_mpll = {
+	.clk = {
+		.name		= "mout_mpll",
+	},
+	.sources	= &clk_src_mpll,
+
+	/* reg_src will be added in each SoCs' clock */
+};
+
+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",
+	},
+	.sources	= &clkset_moutcore,
+	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 16, .size = 1 },
+};
+
+static struct clksrc_clk clk_coreclk = {
+	.clk	= {
+		.name		= "core_clk",
+		.parent		= &clk_moutcore.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk clk_armclk = {
+	.clk	= {
+		.name		= "armclk",
+		.parent		= &clk_coreclk.clk,
+	},
+};
+
+static struct clksrc_clk clk_aclk_corem0 = {
+	.clk	= {
+		.name		= "aclk_corem0",
+		.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",
+		.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",
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 8, .size = 3 },
+};
+
+static struct clksrc_clk clk_periphclk = {
+	.clk	= {
+		.name		= "periphclk",
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
+};
+
+/* Core list of CMU_CORE side */
+
+struct clk *clkset_corebus_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_sclk_apll.clk,
+};
+
+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",
+	},
+	.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",
+		.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",
+		.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",
+		.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",
+		.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",
+		.parent		= &clk_aclk_acp.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 4, .size = 3 },
+};
+
+/* Core list of CMU_TOP side */
+
+struct clk *clkset_aclk_top_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_sclk_apll.clk,
+};
+
+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",
+	},
+	.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",
+	},
+	.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",
+	},
+	.sources	= &clkset_aclk,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 },
+};
+
+struct clksrc_clk clk_aclk_133 = {
+	.clk	= {
+		.name		= "aclk_133",
+	},
+	.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",
+		.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),
+};
+
+struct clksrc_clk clk_sclk_vpll = {
+	.clk	= {
+		.name		= "sclk_vpll",
+	},
+	.sources	= &clkset_sclk_vpll,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
+};
+
+static struct clk init_clocks_off[] = {
+	{
+		.name		= "timers",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1<<24),
+	}, {
+		.name		= "csis",
+		.devname	= "s5p-mipi-csis.0",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "csis",
+		.devname	= "s5p-mipi-csis.1",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 5),
+	}, {
+		.name		= "fimc",
+		.devname	= "exynos4-fimc.0",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "fimc",
+		.devname	= "exynos4-fimc.1",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "fimc",
+		.devname	= "exynos4-fimc.2",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 2),
+	}, {
+		.name		= "fimc",
+		.devname	= "exynos4-fimc.3",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "fimd",
+		.devname	= "exynos4-fb.0",
+		.enable		= exynos4_clk_ip_lcd0_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "hsmmc",
+		.devname	= "s3c-sdhci.0",
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 5),
+	}, {
+		.name		= "hsmmc",
+		.devname	= "s3c-sdhci.1",
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 6),
+	}, {
+		.name		= "hsmmc",
+		.devname	= "s3c-sdhci.2",
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 7),
+	}, {
+		.name		= "hsmmc",
+		.devname	= "s3c-sdhci.3",
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "dwmmc",
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 9),
+	}, {
+		.name		= "dac",
+		.devname	= "s5p-sdo",
+		.enable		= exynos4_clk_ip_tv_ctrl,
+		.ctrlbit	= (1 << 2),
+	}, {
+		.name		= "mixer",
+		.devname	= "s5p-mixer",
+		.enable		= exynos4_clk_ip_tv_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "vp",
+		.devname	= "s5p-mixer",
+		.enable		= exynos4_clk_ip_tv_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "hdmi",
+		.devname	= "exynos4-hdmi",
+		.enable		= exynos4_clk_ip_tv_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "hdmiphy",
+		.devname	= "exynos4-hdmi",
+		.enable		= exynos4_clk_hdmiphy_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "dacphy",
+		.devname	= "s5p-sdo",
+		.enable		= exynos4_clk_dac_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "dma",
+		.devname	= "dma-pl330.0",
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "dma",
+		.devname	= "dma-pl330.1",
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "adc",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 15),
+	}, {
+		.name		= "keypad",
+		.enable		= exynos4_clk_ip_perir_ctrl,
+		.ctrlbit	= (1 << 16),
+	}, {
+		.name		= "rtc",
+		.enable		= exynos4_clk_ip_perir_ctrl,
+		.ctrlbit	= (1 << 15),
+	}, {
+		.name		= "watchdog",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_perir_ctrl,
+		.ctrlbit	= (1 << 14),
+	}, {
+		.name		= "usbhost",
+		.enable		= exynos4_clk_ip_fsys_ctrl ,
+		.ctrlbit	= (1 << 12),
+	}, {
+		.name		= "otg",
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 13),
+	}, {
+		.name		= "spi",
+		.devname	= "s3c64xx-spi.0",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 16),
+	}, {
+		.name		= "spi",
+		.devname	= "s3c64xx-spi.1",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 17),
+	}, {
+		.name		= "spi",
+		.devname	= "s3c64xx-spi.2",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 18),
+	}, {
+		.name		= "iis",
+		.devname	= "samsung-i2s.0",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 19),
+	}, {
+		.name		= "iis",
+		.devname	= "samsung-i2s.1",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 20),
+	}, {
+		.name		= "iis",
+		.devname	= "samsung-i2s.2",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 21),
+	}, {
+		.name		= "ac97",
+		.devname	= "samsung-ac97",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 27),
+	}, {
+		.name		= "fimg2d",
+		.enable		= exynos4_clk_ip_image_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "mfc",
+		.devname	= "s5p-mfc",
+		.enable		= exynos4_clk_ip_mfc_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-i2c.0",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 6),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-i2c.1",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 7),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-i2c.2",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-i2c.3",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 9),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-i2c.4",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 10),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-i2c.5",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 11),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-i2c.6",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 12),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-i2c.7",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 13),
+	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-hdmiphy-i2c",
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 14),
+	}, {
+		.name		= "SYSMMU_MDMA",
+		.enable		= exynos4_clk_ip_image_ctrl,
+		.ctrlbit	= (1 << 5),
+	}, {
+		.name		= "SYSMMU_FIMC0",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 7),
+	}, {
+		.name		= "SYSMMU_FIMC1",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "SYSMMU_FIMC2",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 9),
+	}, {
+		.name		= "SYSMMU_FIMC3",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 10),
+	}, {
+		.name		= "SYSMMU_JPEG",
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 11),
+	}, {
+		.name		= "SYSMMU_FIMD0",
+		.enable		= exynos4_clk_ip_lcd0_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "SYSMMU_FIMD1",
+		.enable		= exynos4_clk_ip_lcd1_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "SYSMMU_PCIe",
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 18),
+	}, {
+		.name		= "SYSMMU_G2D",
+		.enable		= exynos4_clk_ip_image_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "SYSMMU_ROTATOR",
+		.enable		= exynos4_clk_ip_image_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "SYSMMU_TV",
+		.enable		= exynos4_clk_ip_tv_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "SYSMMU_MFC_L",
+		.enable		= exynos4_clk_ip_mfc_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "SYSMMU_MFC_R",
+		.enable		= exynos4_clk_ip_mfc_ctrl,
+		.ctrlbit	= (1 << 2),
+	}
+};
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "uart",
+		.devname	= "s5pv210-uart.0",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "uart",
+		.devname	= "s5pv210-uart.1",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "uart",
+		.devname	= "s5pv210-uart.2",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 2),
+	}, {
+		.name		= "uart",
+		.devname	= "s5pv210-uart.3",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "uart",
+		.devname	= "s5pv210-uart.4",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "uart",
+		.devname	= "s5pv210-uart.5",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 5),
+	}
+};
+
+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,
+};
+
+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",
+	},
+	.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",
+	},
+	.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 clk *clkset_mout_mfc0_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_sclk_apll.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc0 = {
+	.sources	= clkset_mout_mfc0_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_mfc0_list),
+};
+
+static struct clksrc_clk clk_mout_mfc0 = {
+	.clk	= {
+		.name		= "mout_mfc0",
+	},
+	.sources	= &clkset_mout_mfc0,
+	.reg_src	= { .reg = S5P_CLKSRC_MFC, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_mout_mfc1_list[] = {
+	[0] = &clk_mout_epll.clk,
+	[1] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc1 = {
+	.sources	= clkset_mout_mfc1_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_mfc1_list),
+};
+
+static struct clksrc_clk clk_mout_mfc1 = {
+	.clk	= {
+		.name		= "mout_mfc1",
+	},
+	.sources	= &clkset_mout_mfc1,
+	.reg_src	= { .reg = S5P_CLKSRC_MFC, .shift = 4, .size = 1 },
+};
+
+static struct clk *clkset_mout_mfc_list[] = {
+	[0] = &clk_mout_mfc0.clk,
+	[1] = &clk_mout_mfc1.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc = {
+	.sources	= clkset_mout_mfc_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_mfc_list),
+};
+
+static struct clk *clkset_sclk_dac_list[] = {
+	[0] = &clk_sclk_vpll.clk,
+	[1] = &clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources clkset_sclk_dac = {
+	.sources	= clkset_sclk_dac_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_dac_list),
+};
+
+static struct clksrc_clk clk_sclk_dac = {
+	.clk		= {
+		.name		= "sclk_dac",
+		.enable		= exynos4_clksrc_mask_tv_ctrl,
+		.ctrlbit	= (1 << 8),
+	},
+	.sources = &clkset_sclk_dac,
+	.reg_src = { .reg = S5P_CLKSRC_TV, .shift = 8, .size = 1 },
+};
+
+static struct clksrc_clk clk_sclk_pixel = {
+	.clk		= {
+		.name		= "sclk_pixel",
+		.parent = &clk_sclk_vpll.clk,
+	},
+	.reg_div = { .reg = S5P_CLKDIV_TV, .shift = 0, .size = 4 },
+};
+
+static struct clk *clkset_sclk_hdmi_list[] = {
+	[0] = &clk_sclk_pixel.clk,
+	[1] = &clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources clkset_sclk_hdmi = {
+	.sources	= clkset_sclk_hdmi_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_hdmi_list),
+};
+
+static struct clksrc_clk clk_sclk_hdmi = {
+	.clk		= {
+		.name		= "sclk_hdmi",
+		.enable		= exynos4_clksrc_mask_tv_ctrl,
+		.ctrlbit	= (1 << 0),
+	},
+	.sources = &clkset_sclk_hdmi,
+	.reg_src = { .reg = S5P_CLKSRC_TV, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_sclk_mixer_list[] = {
+	[0] = &clk_sclk_dac.clk,
+	[1] = &clk_sclk_hdmi.clk,
+};
+
+static struct clksrc_sources clkset_sclk_mixer = {
+	.sources	= clkset_sclk_mixer_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_mixer_list),
+};
+
+static struct clksrc_clk clk_sclk_mixer = {
+	.clk		= {
+		.name		= "sclk_mixer",
+		.enable		= exynos4_clksrc_mask_tv_ctrl,
+		.ctrlbit	= (1 << 4),
+	},
+	.sources = &clkset_sclk_mixer,
+	.reg_src = { .reg = S5P_CLKSRC_TV, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk *sclk_tv[] = {
+	&clk_sclk_dac,
+	&clk_sclk_pixel,
+	&clk_sclk_hdmi,
+	&clk_sclk_mixer,
+};
+
+static struct clksrc_clk clk_dout_mmc0 = {
+	.clk		= {
+		.name		= "dout_mmc0",
+	},
+	.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",
+	},
+	.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",
+	},
+	.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",
+	},
+	.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",
+	},
+	.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",
+			.devname	= "s5pv210-uart.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",
+			.devname	= "s5pv210-uart.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",
+			.devname	= "s5pv210-uart.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",
+			.devname	= "s5pv210-uart.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",
+			.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",
+			.devname	= "s5p-mipi-csis.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",
+			.devname	= "s5p-mipi-csis.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_cam0",
+			.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_cam1",
+			.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",
+			.devname	= "exynos4-fimc.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",
+			.devname	= "exynos4-fimc.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",
+			.devname	= "exynos4-fimc.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",
+			.devname	= "exynos4-fimc.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",
+			.devname	= "exynos4-fb.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_spi",
+			.devname	= "s3c64xx-spi.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",
+			.devname	= "s3c64xx-spi.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",
+			.devname	= "s3c64xx-spi.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",
+		},
+		.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_mfc",
+			.devname	= "s5p-mfc",
+		},
+		.sources = &clkset_mout_mfc,
+		.reg_src = { .reg = S5P_CLKSRC_MFC, .shift = 8, .size = 1 },
+		.reg_div = { .reg = S5P_CLKDIV_MFC, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.devname	= "s3c-sdhci.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",
+			.devname	= "s3c-sdhci.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",
+			.devname	= "s3c-sdhci.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",
+			.devname	= "s3c-sdhci.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_dwmmc",
+			.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,
+	&clk_mout_mfc0,
+	&clk_mout_mfc1,
+};
+
+static int xtal_rate;
+
+static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
+{
+	if (soc_is_exynos4210())
+		return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0),
+					pll_4508);
+	else if (soc_is_exynos4212() || soc_is_exynos4412())
+		return s5p_get_pll35xx(xtal_rate, __raw_readl(S5P_APLL_CON0));
+	else
+		return 0;
+}
+
+static struct clk_ops exynos4_fout_apll_ops = {
+	.get_rate = exynos4_fout_apll_get_rate,
+};
+
+static u32 vpll_div[][8] = {
+	{  54000000, 3, 53, 3, 1024, 0, 17, 0 },
+	{ 108000000, 3, 53, 2, 1024, 0, 17, 0 },
+};
+
+static unsigned long exynos4_vpll_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+
+static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned int vpll_con0, vpll_con1 = 0;
+	unsigned int i;
+
+	/* Return if nothing changed */
+	if (clk->rate == rate)
+		return 0;
+
+	vpll_con0 = __raw_readl(S5P_VPLL_CON0);
+	vpll_con0 &= ~(0x1 << 27 |					\
+			PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |	\
+			PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |	\
+			PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
+
+	vpll_con1 = __raw_readl(S5P_VPLL_CON1);
+	vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT |	\
+			PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT |	\
+			PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
+
+	for (i = 0; i < ARRAY_SIZE(vpll_div); i++) {
+		if (vpll_div[i][0] == rate) {
+			vpll_con0 |= vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
+			vpll_con0 |= vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
+			vpll_con0 |= vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
+			vpll_con1 |= vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
+			vpll_con1 |= vpll_div[i][5] << PLL46XX_MFR_SHIFT;
+			vpll_con1 |= vpll_div[i][6] << PLL46XX_MRR_SHIFT;
+			vpll_con0 |= vpll_div[i][7] << 27;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(vpll_div)) {
+		printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	__raw_writel(vpll_con0, S5P_VPLL_CON0);
+	__raw_writel(vpll_con1, S5P_VPLL_CON1);
+
+	/* Wait for VPLL lock */
+	while (!(__raw_readl(S5P_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
+		continue;
+
+	clk->rate = rate;
+	return 0;
+}
+
+static struct clk_ops exynos4_vpll_ops = {
+	.get_rate = exynos4_vpll_get_rate,
+	.set_rate = exynos4_vpll_set_rate,
+};
+
+void __init_or_cpufreq exynos4_setup_clocks(void)
+{
+	struct clk *xtal_clk;
+	unsigned long apll = 0;
+	unsigned long mpll = 0;
+	unsigned long epll = 0;
+	unsigned long vpll = 0;
+	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);
+
+	if (soc_is_exynos4210()) {
+		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_4650c);
+	} else if (soc_is_exynos4212() || soc_is_exynos4412()) {
+		apll = s5p_get_pll35xx(xtal, __raw_readl(S5P_APLL_CON0));
+		mpll = s5p_get_pll35xx(xtal, __raw_readl(S5P_MPLL_CON0));
+		epll = s5p_get_pll36xx(xtal, __raw_readl(S5P_EPLL_CON0),
+					__raw_readl(S5P_EPLL_CON1));
+
+		vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
+		vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
+					__raw_readl(S5P_VPLL_CON1));
+	} else {
+		/* nothing */
+	}
+
+	clk_fout_apll.ops = &exynos4_fout_apll_ops;
+	clk_fout_mpll.rate = mpll;
+	clk_fout_epll.rate = epll;
+	clk_fout_vpll.ops = &exynos4_vpll_ops;
+	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 = {
+	&clk_sclk_hdmi27m,
+	&clk_sclk_hdmiphy,
+	&clk_sclk_usbphy0,
+	&clk_sclk_usbphy1,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos4_clock_suspend(void)
+{
+	s3c_pm_do_save(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
+	return 0;
+}
+
+static void exynos4_clock_resume(void)
+{
+	s3c_pm_do_restore_core(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
+}
+
+#else
+#define exynos4_clock_suspend NULL
+#define exynos4_clock_resume NULL
+#endif
+
+struct syscore_ops exynos4_clock_syscore_ops = {
+	.suspend	= exynos4_clock_suspend,
+	.resume		= exynos4_clock_resume,
+};
+
+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);
+
+	for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
+		s3c_register_clksrc(sclk_tv[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));
+
+	register_syscore_ops(&exynos4_clock_syscore_ops);
+	s3c24xx_register_clock(&dummy_apb_pclk);
+
+	s3c_pwmclk_init();
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/clock-exynos4210.c linux-libre-3.2-gnu/arch/arm/mach-exynos/clock-exynos4210.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/clock-exynos4210.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/clock-exynos4210.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,139 @@
+/*
+ * linux/arch/arm/mach-exynos4/clock-exynos4210.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4210 - 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/clk.h>
+#include <linux/io.h>
+#include <linux/syscore_ops.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 <plat/exynos4.h>
+#include <plat/pm.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/exynos4-clock.h>
+
+static struct sleep_save exynos4210_clock_save[] = {
+	SAVE_ITEM(S5P_CLKSRC_IMAGE),
+	SAVE_ITEM(S5P_CLKSRC_LCD1),
+	SAVE_ITEM(S5P_CLKDIV_IMAGE),
+	SAVE_ITEM(S5P_CLKDIV_LCD1),
+	SAVE_ITEM(S5P_CLKSRC_MASK_LCD1),
+	SAVE_ITEM(S5P_CLKGATE_IP_IMAGE_4210),
+	SAVE_ITEM(S5P_CLKGATE_IP_LCD1),
+	SAVE_ITEM(S5P_CLKGATE_IP_PERIR_4210),
+};
+
+static struct clksrc_clk *sysclks[] = {
+	/* nothing here yet */
+};
+
+static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_LCD1, clk, enable);
+}
+
+static struct clksrc_clk clksrcs[] = {
+	{
+		.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_fimd",
+			.devname	= "exynos4-fb.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 },
+	},
+};
+
+static struct clk init_clocks_off[] = {
+	{
+		.name		= "sataphy",
+		.id		= -1,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "sata",
+		.id		= -1,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 10),
+	}, {
+		.name		= "fimd",
+		.devname	= "exynos4-fb.1",
+		.enable		= exynos4_clk_ip_lcd1_ctrl,
+		.ctrlbit	= (1 << 0),
+	},
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos4210_clock_suspend(void)
+{
+	s3c_pm_do_save(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
+
+	return 0;
+}
+
+static void exynos4210_clock_resume(void)
+{
+	s3c_pm_do_restore_core(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
+}
+
+#else
+#define exynos4210_clock_suspend NULL
+#define exynos4210_clock_resume NULL
+#endif
+
+struct syscore_ops exynos4210_clock_syscore_ops = {
+	.suspend	= exynos4210_clock_suspend,
+	.resume		= exynos4210_clock_resume,
+};
+
+void __init exynos4210_register_clocks(void)
+{
+	int ptr;
+
+	clk_mout_mpll.reg_src.reg = S5P_CLKSRC_CPU;
+	clk_mout_mpll.reg_src.shift = 8;
+	clk_mout_mpll.reg_src.size = 1;
+
+	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_off, ARRAY_SIZE(init_clocks_off));
+	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+
+	register_syscore_ops(&exynos4210_clock_syscore_ops);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/clock-exynos4212.c linux-libre-3.2-gnu/arch/arm/mach-exynos/clock-exynos4212.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/clock-exynos4212.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/clock-exynos4212.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,118 @@
+/*
+ * linux/arch/arm/mach-exynos4/clock-exynos4212.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4212 - 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/clk.h>
+#include <linux/io.h>
+#include <linux/syscore_ops.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 <plat/exynos4.h>
+#include <plat/pm.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/exynos4-clock.h>
+
+static struct sleep_save exynos4212_clock_save[] = {
+	SAVE_ITEM(S5P_CLKSRC_IMAGE),
+	SAVE_ITEM(S5P_CLKDIV_IMAGE),
+	SAVE_ITEM(S5P_CLKGATE_IP_IMAGE_4212),
+	SAVE_ITEM(S5P_CLKGATE_IP_PERIR_4212),
+};
+
+static struct clk *clk_src_mpll_user_list[] = {
+	[0] = &clk_fin_mpll,
+	[1] = &clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources clk_src_mpll_user = {
+	.sources	= clk_src_mpll_user_list,
+	.nr_sources	= ARRAY_SIZE(clk_src_mpll_user_list),
+};
+
+static struct clksrc_clk clk_mout_mpll_user = {
+	.clk = {
+		.name		= "mout_mpll_user",
+	},
+	.sources	= &clk_src_mpll_user,
+	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 24, .size = 1 },
+};
+
+static struct clksrc_clk *sysclks[] = {
+	&clk_mout_mpll_user,
+};
+
+static struct clksrc_clk clksrcs[] = {
+	/* nothing here yet */
+};
+
+static struct clk init_clocks_off[] = {
+	/* nothing here yet */
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos4212_clock_suspend(void)
+{
+	s3c_pm_do_save(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
+
+	return 0;
+}
+
+static void exynos4212_clock_resume(void)
+{
+	s3c_pm_do_restore_core(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
+}
+
+#else
+#define exynos4212_clock_suspend NULL
+#define exynos4212_clock_resume NULL
+#endif
+
+struct syscore_ops exynos4212_clock_syscore_ops = {
+	.suspend	= exynos4212_clock_suspend,
+	.resume		= exynos4212_clock_resume,
+};
+
+void __init exynos4212_register_clocks(void)
+{
+	int ptr;
+
+	/* usbphy1 is removed */
+	clkset_group_list[4] = NULL;
+
+	/* mout_mpll_user is used */
+	clkset_group_list[6] = &clk_mout_mpll_user.clk;
+	clkset_aclk_top_list[0] = &clk_mout_mpll_user.clk;
+
+	clk_mout_mpll.reg_src.reg = S5P_CLKSRC_DMC;
+	clk_mout_mpll.reg_src.shift = 12;
+	clk_mout_mpll.reg_src.size = 1;
+
+	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_off, ARRAY_SIZE(init_clocks_off));
+	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+
+	register_syscore_ops(&exynos4212_clock_syscore_ops);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/cpu.c linux-libre-3.2-gnu/arch/arm/mach-exynos/cpu.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/cpu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,293 @@
+/* linux/arch/arm/mach-exynos/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 <asm/hardware/gic.h>
+
+#include <plat/cpu.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/exynos4.h>
+#include <plat/adc-core.h>
+#include <plat/sdhci.h>
+#include <plat/fb-core.h>
+#include <plat/fimc-core.h>
+#include <plat/iic-core.h>
+#include <plat/reset.h>
+#include <plat/tv-core.h>
+
+#include <mach/regs-irq.h>
+#include <mach/regs-pmu.h>
+
+unsigned int gic_bank_offset __read_mostly;
+
+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 exynos_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_SYSTIMER,
+		.pfn		= __phys_to_pfn(EXYNOS_PA_SYSTIMER),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_PMU,
+		.pfn		= __phys_to_pfn(EXYNOS_PA_PMU),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_COMBINER_BASE,
+		.pfn		= __phys_to_pfn(EXYNOS_PA_COMBINER),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GIC_CPU,
+		.pfn		= __phys_to_pfn(EXYNOS_PA_GIC_CPU),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GIC_DIST,
+		.pfn		= __phys_to_pfn(EXYNOS_PA_GIC_DIST),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C_VA_UART,
+		.pfn		= __phys_to_pfn(S3C_PA_UART),
+		.length		= SZ_512K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static struct map_desc exynos4_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_CMU,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_CMU),
+		.length		= SZ_128K,
+		.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_USB_HSPHY,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_HSPHY),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static struct map_desc exynos4_iodesc0[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_SYSRAM,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_SYSRAM0),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static struct map_desc exynos4_iodesc1[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_SYSRAM,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_SYSRAM1),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static void exynos_idle(void)
+{
+	if (!need_resched())
+		cpu_do_idle();
+
+	local_irq_enable();
+}
+
+static void exynos4_sw_reset(void)
+{
+	__raw_writel(0x1, S5P_SWRESET);
+}
+
+/*
+ * exynos_map_io
+ *
+ * register the standard cpu IO areas
+ */
+void __init exynos4_map_io(void)
+{
+	iotable_init(exynos_iodesc, ARRAY_SIZE(exynos_iodesc));
+	iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
+
+	if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_0)
+		iotable_init(exynos4_iodesc0, ARRAY_SIZE(exynos4_iodesc0));
+	else
+		iotable_init(exynos4_iodesc1, ARRAY_SIZE(exynos4_iodesc1));
+
+	/* initialize device information early */
+	exynos4_default_sdhci0();
+	exynos4_default_sdhci1();
+	exynos4_default_sdhci2();
+	exynos4_default_sdhci3();
+
+	s3c_adc_setname("samsung-adc-v3");
+
+	s3c_fimc_setname(0, "exynos4-fimc");
+	s3c_fimc_setname(1, "exynos4-fimc");
+	s3c_fimc_setname(2, "exynos4-fimc");
+	s3c_fimc_setname(3, "exynos4-fimc");
+
+	/* The I2C bus controllers are directly compatible with s3c2440 */
+	s3c_i2c0_setname("s3c2440-i2c");
+	s3c_i2c1_setname("s3c2440-i2c");
+	s3c_i2c2_setname("s3c2440-i2c");
+
+	s5p_fb_setname(0, "exynos4-fb");
+	s5p_hdmi_setname("exynos4-hdmi");
+}
+
+void __init exynos4_init_clocks(int xtal)
+{
+	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
+
+	s3c24xx_register_baseclocks(xtal);
+	s5p_register_clocks(xtal);
+
+	if (soc_is_exynos4210())
+		exynos4210_register_clocks();
+	else if (soc_is_exynos4212() || soc_is_exynos4412())
+		exynos4212_register_clocks();
+
+	exynos4_register_clocks();
+	exynos4_setup_clocks();
+}
+
+static void exynos4_gic_irq_fix_base(struct irq_data *d)
+{
+	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+
+	gic_data->cpu_base = S5P_VA_GIC_CPU +
+			    (gic_bank_offset * smp_processor_id());
+
+	gic_data->dist_base = S5P_VA_GIC_DIST +
+			    (gic_bank_offset * smp_processor_id());
+}
+
+void __init exynos4_init_irq(void)
+{
+	int irq;
+
+	gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
+
+	gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+	gic_arch_extn.irq_eoi = exynos4_gic_irq_fix_base;
+	gic_arch_extn.irq_unmask = exynos4_gic_irq_fix_base;
+	gic_arch_extn.irq_mask = exynos4_gic_irq_fix_base;
+
+	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
+
+		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);
+
+	if (soc_is_exynos4210())
+		__raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
+	else if (soc_is_exynos4212() || soc_is_exynos4412())
+		__raw_writel(0x120, 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 exynos_init(void)
+{
+	printk(KERN_INFO "EXYNOS: Initializing architecture\n");
+
+	/* set idle function */
+	pm_idle = exynos_idle;
+
+	/* set sw_reset function */
+	if (soc_is_exynos4210() || soc_is_exynos4212() || soc_is_exynos4412())
+		s5p_reset_hook = exynos4_sw_reset;
+
+	return sysdev_register(&exynos4_sysdev);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/cpuidle.c linux-libre-3.2-gnu/arch/arm/mach-exynos/cpuidle.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/cpuidle.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/cpuidle.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,92 @@
+/* linux/arch/arm/mach-exynos4/cpuidle.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/kernel.h>
+#include <linux/init.h>
+#include <linux/cpuidle.h>
+#include <linux/io.h>
+#include <linux/export.h>
+#include <linux/time.h>
+
+#include <asm/proc-fns.h>
+
+static int exynos4_enter_idle(struct cpuidle_device *dev,
+			struct cpuidle_driver *drv,
+			      int index);
+
+static struct cpuidle_state exynos4_cpuidle_set[] = {
+	[0] = {
+		.enter			= exynos4_enter_idle,
+		.exit_latency		= 1,
+		.target_residency	= 100000,
+		.flags			= CPUIDLE_FLAG_TIME_VALID,
+		.name			= "IDLE",
+		.desc			= "ARM clock gating(WFI)",
+	},
+};
+
+static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
+
+static struct cpuidle_driver exynos4_idle_driver = {
+	.name		= "exynos4_idle",
+	.owner		= THIS_MODULE,
+};
+
+static int exynos4_enter_idle(struct cpuidle_device *dev,
+				struct cpuidle_driver *drv,
+			      int index)
+{
+	struct timeval before, after;
+	int idle_time;
+
+	local_irq_disable();
+	do_gettimeofday(&before);
+
+	cpu_do_idle();
+
+	do_gettimeofday(&after);
+	local_irq_enable();
+	idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
+		    (after.tv_usec - before.tv_usec);
+
+	dev->last_residency = idle_time;
+	return index;
+}
+
+static int __init exynos4_init_cpuidle(void)
+{
+	int i, max_cpuidle_state, cpu_id;
+	struct cpuidle_device *device;
+	struct cpuidle_driver *drv = &exynos4_idle_driver;
+
+	/* Setup cpuidle driver */
+	drv->state_count = (sizeof(exynos4_cpuidle_set) /
+				       sizeof(struct cpuidle_state));
+	max_cpuidle_state = drv->state_count;
+	for (i = 0; i < max_cpuidle_state; i++) {
+		memcpy(&drv->states[i], &exynos4_cpuidle_set[i],
+				sizeof(struct cpuidle_state));
+	}
+	cpuidle_register_driver(&exynos4_idle_driver);
+
+	for_each_cpu(cpu_id, cpu_online_mask) {
+		device = &per_cpu(exynos4_cpuidle_device, cpu_id);
+		device->cpu = cpu_id;
+
+		device->state_count = drv->state_count;
+
+		if (cpuidle_register_device(device)) {
+			printk(KERN_ERR "CPUidle register device failed\n,");
+			return -EIO;
+		}
+	}
+	return 0;
+}
+device_initcall(exynos4_init_cpuidle);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/dev-ahci.c linux-libre-3.2-gnu/arch/arm/mach-exynos/dev-ahci.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/dev-ahci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/dev-ahci.c	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/dev-audio.c linux-libre-3.2-gnu/arch/arm/mach-exynos/dev-audio.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/dev-audio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/dev-audio.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,369 @@
+/* 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>
+#include <mach/regs-audss.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,
+			.idma_addr = EXYNOS4_AUDSS_INT_MEM,
+		},
+	},
+};
+
+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(4));
+
+	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-3.1-gnu/arch/arm/mach-exynos/dev-dwmci.c linux-libre-3.2-gnu/arch/arm/mach-exynos/dev-dwmci.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/dev-dwmci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/dev-dwmci.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,82 @@
+/*
+ * linux/arch/arm/mach-exynos4/dev-dwmci.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Platform device for Synopsys DesignWare Mobile Storage IP
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/mmc/dw_mmc.h>
+
+#include <plat/devs.h>
+
+#include <mach/map.h>
+
+static int exynos4_dwmci_get_bus_wd(u32 slot_id)
+{
+	return 4;
+}
+
+static int exynos4_dwmci_init(u32 slot_id, irq_handler_t handler, void *data)
+{
+	return 0;
+}
+
+static struct resource exynos4_dwmci_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_DWMCI,
+		.end	= EXYNOS4_PA_DWMCI + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_DWMCI,
+		.end	= IRQ_DWMCI,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static struct dw_mci_board exynos4_dwci_pdata = {
+	.num_slots			= 1,
+	.quirks				= DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
+	.bus_hz				= 80 * 1000 * 1000,
+	.detect_delay_ms	= 200,
+	.init				= exynos4_dwmci_init,
+	.get_bus_wd			= exynos4_dwmci_get_bus_wd,
+};
+
+static u64 exynos4_dwmci_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device exynos4_device_dwmci = {
+	.name		= "dw_mmc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(exynos4_dwmci_resource),
+	.resource	= exynos4_dwmci_resource,
+	.dev		= {
+		.dma_mask		= &exynos4_dwmci_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data	= &exynos4_dwci_pdata,
+	},
+};
+
+void __init exynos4_dwmci_set_platdata(struct dw_mci_board *pd)
+{
+	struct dw_mci_board *npd;
+
+	npd = s3c_set_platdata(pd, sizeof(struct dw_mci_board),
+			&exynos4_device_dwmci);
+
+	if (!npd->init)
+		npd->init = exynos4_dwmci_init;
+	if (!npd->get_bus_wd)
+		npd->get_bus_wd = exynos4_dwmci_get_bus_wd;
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/dev-pd.c linux-libre-3.2-gnu/arch/arm/mach-exynos/dev-pd.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/dev-pd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/dev-pd.c	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/dev-sysmmu.c linux-libre-3.2-gnu/arch/arm/mach-exynos/dev-sysmmu.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/dev-sysmmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/dev-sysmmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,233 @@
+/* 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 <linux/export.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-3.1-gnu/arch/arm/mach-exynos/dma.c linux-libre-3.2-gnu/arch/arm/mach-exynos/dma.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,250 @@
+/* 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/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
+
+#include <asm/irq.h>
+#include <plat/devs.h>
+#include <plat/irqs.h>
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+#include <mach/dma.h>
+
+static u64 dma_dmamask = DMA_BIT_MASK(32);
+
+struct dma_pl330_peri pdma0_peri[28] = {
+	{
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ0,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ2,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART4_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART4_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS4_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS4_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_AC97_MICIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMOUT,
+		.rqtype = MEMTODEV,
+	},
+};
+
+struct dma_pl330_platdata exynos4_pdma0_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(pdma0_peri),
+	.peri = pdma0_peri,
+};
+
+struct amba_device exynos4_device_pdma0 = {
+	.dev = {
+		.init_name = "dma-pl330.0",
+		.dma_mask = &dma_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &exynos4_pdma0_pdata,
+	},
+	.res = {
+		.start = EXYNOS4_PA_PDMA0,
+		.end = EXYNOS4_PA_PDMA0 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_PDMA0, NO_IRQ},
+	.periphid = 0x00041330,
+};
+
+struct dma_pl330_peri pdma1_peri[25] = {
+	{
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ1,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ3,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS5_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS5_TX,
+		.rqtype = MEMTODEV,
+	},
+};
+
+struct dma_pl330_platdata exynos4_pdma1_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
+	.peri = pdma1_peri,
+};
+
+struct amba_device exynos4_device_pdma1 = {
+	.dev = {
+		.init_name = "dma-pl330.1",
+		.dma_mask = &dma_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &exynos4_pdma1_pdata,
+	},
+	.res = {
+		.start = EXYNOS4_PA_PDMA1,
+		.end = EXYNOS4_PA_PDMA1 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_PDMA1, NO_IRQ},
+	.periphid = 0x00041330,
+};
+
+static int __init exynos4_dma_init(void)
+{
+	amba_device_register(&exynos4_device_pdma0, &iomem_resource);
+	amba_device_register(&exynos4_device_pdma1, &iomem_resource);
+
+	return 0;
+}
+arch_initcall(exynos4_dma_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/headsmp.S linux-libre-3.2-gnu/arch/arm/mach-exynos/headsmp.S
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/headsmp.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/headsmp.S	2012-01-04 18:55:44.000000000 -0500
@@ -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>
+
+	__CPUINIT
+
+/*
+ * 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-3.1-gnu/arch/arm/mach-exynos/hotplug.c linux-libre-3.2-gnu/arch/arm/mach-exynos/hotplug.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/hotplug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/hotplug.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,133 @@
+/* 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 <linux/io.h>
+
+#include <asm/cacheflush.h>
+
+#include <mach/regs-pmu.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)
+{
+	for (;;) {
+
+		/* make cpu1 to be turned off at next WFI command */
+		if (cpu == 1)
+			__raw_writel(0, S5P_ARM_CORE1_CONFIGURATION);
+
+		/*
+		 * here's the WFI
+		 */
+		asm(".word	0xe320f003\n"
+		    :
+		    :
+		    : "memory", "cc");
+
+		if (pen_release == cpu_logical_map(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-3.1-gnu/arch/arm/mach-exynos/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -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, tmp
+		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-3.1-gnu/arch/arm/mach-exynos/include/mach/dma.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/dma.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -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 DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
+
+#endif /* __MACH_DMA_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/dwmci.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/dwmci.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/dwmci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/dwmci.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,20 @@
+/* linux/arch/arm/mach-exynos4/include/mach/dwmci.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Synopsys DesignWare Mobile Storage for EXYNOS4210
+ *
+ * This program is free software; you can 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_DWMCI_H
+#define __ASM_ARM_ARCH_DWMCI_H __FILE__
+
+#include <linux/mmc/dw_mmc.h>
+
+extern void exynos4_dwmci_set_platdata(struct dw_mci_board *pd);
+
+#endif /* __ASM_ARM_ARCH_DWMCI_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/entry-macro.S linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/entry-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/entry-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,91 @@
+/* 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 <mach/map.h>
+#include <asm/hardware/gic.h>
+
+		.macro	disable_fiq
+		.endm
+
+		.macro  get_irqnr_preamble, base, tmp
+		mov	\tmp, #0
+
+		mrc	p15, 0, \base, c0, c0, 5
+		and	\base, \base, #3
+		cmp	\base, #0
+		beq	1f
+
+		ldr	\tmp, =gic_bank_offset
+		ldr	\tmp, [\tmp]
+		cmp	\base, #1
+		beq	1f
+
+		cmp	\base, #2
+		addeq	\tmp, \tmp, \tmp
+		addne	\tmp, \tmp, \tmp, LSL #1
+
+1:		ldr	\base, =gic_cpu_base_addr
+		ldr	\base, [\base]
+		add	\base, \base, \tmp
+		.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, #15
+		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
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/exynos4-clock.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/exynos4-clock.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/exynos4-clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/exynos4-clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,43 @@
+/*
+ * linux/arch/arm/mach-exynos4/include/mach/exynos4-clock.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Header file for 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.
+*/
+
+#ifndef __ASM_ARCH_CLOCK_H
+#define __ASM_ARCH_CLOCK_H __FILE__
+
+#include <linux/clk.h>
+
+extern struct clk clk_sclk_hdmi27m;
+extern struct clk clk_sclk_usbphy0;
+extern struct clk clk_sclk_usbphy1;
+extern struct clk clk_sclk_hdmiphy;
+
+extern struct clksrc_clk clk_sclk_apll;
+extern struct clksrc_clk clk_mout_mpll;
+extern struct clksrc_clk clk_aclk_133;
+extern struct clksrc_clk clk_mout_epll;
+extern struct clksrc_clk clk_sclk_vpll;
+
+extern struct clk *clkset_corebus_list[];
+extern struct clksrc_sources clkset_mout_corebus;
+
+extern struct clk *clkset_aclk_top_list[];
+extern struct clksrc_sources clkset_aclk;
+
+extern struct clk *clkset_group_list[];
+extern struct clksrc_sources clkset_group;
+
+extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable);
+extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable);
+extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable);
+
+#endif /* __ASM_ARCH_CLOCK_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,149 @@
+/* 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__
+
+/* 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)
+
+#endif /* __ASM_ARCH_GPIO_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/hardware.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/hardware.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/hardware.h	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/include/mach/io.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/io.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/include/mach/irqs.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/irqs.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,169 @@
+/* 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_MCT_LOCALTIMER	IRQ_PPI(12)
+
+/* SPI: Shared Peripheral Interrupt */
+
+#define IRQ_SPI(x)		S5P_IRQ(x+32)
+
+#define IRQ_EINT0		IRQ_SPI(16)
+#define IRQ_EINT1		IRQ_SPI(17)
+#define IRQ_EINT2		IRQ_SPI(18)
+#define IRQ_EINT3		IRQ_SPI(19)
+#define IRQ_EINT4		IRQ_SPI(20)
+#define IRQ_EINT5		IRQ_SPI(21)
+#define IRQ_EINT6		IRQ_SPI(22)
+#define IRQ_EINT7		IRQ_SPI(23)
+#define IRQ_EINT8		IRQ_SPI(24)
+#define IRQ_EINT9		IRQ_SPI(25)
+#define IRQ_EINT10		IRQ_SPI(26)
+#define IRQ_EINT11		IRQ_SPI(27)
+#define IRQ_EINT12		IRQ_SPI(28)
+#define IRQ_EINT13		IRQ_SPI(29)
+#define IRQ_EINT14		IRQ_SPI(30)
+#define IRQ_EINT15		IRQ_SPI(31)
+#define IRQ_EINT16_31		IRQ_SPI(32)
+
+#define IRQ_PDMA0		IRQ_SPI(35)
+#define IRQ_PDMA1		IRQ_SPI(36)
+#define IRQ_TIMER0_VIC		IRQ_SPI(37)
+#define IRQ_TIMER1_VIC		IRQ_SPI(38)
+#define IRQ_TIMER2_VIC		IRQ_SPI(39)
+#define IRQ_TIMER3_VIC		IRQ_SPI(40)
+#define IRQ_TIMER4_VIC		IRQ_SPI(41)
+#define IRQ_MCT_L0		IRQ_SPI(42)
+#define IRQ_WDT			IRQ_SPI(43)
+#define IRQ_RTC_ALARM		IRQ_SPI(44)
+#define IRQ_RTC_TIC		IRQ_SPI(45)
+#define IRQ_GPIO_XB		IRQ_SPI(46)
+#define IRQ_GPIO_XA		IRQ_SPI(47)
+#define IRQ_MCT_L1		IRQ_SPI(48)
+
+#define IRQ_UART0		IRQ_SPI(52)
+#define IRQ_UART1		IRQ_SPI(53)
+#define IRQ_UART2		IRQ_SPI(54)
+#define IRQ_UART3		IRQ_SPI(55)
+#define IRQ_UART4		IRQ_SPI(56)
+#define IRQ_MCT_G0		IRQ_SPI(57)
+#define IRQ_IIC			IRQ_SPI(58)
+#define IRQ_IIC1		IRQ_SPI(59)
+#define IRQ_IIC2		IRQ_SPI(60)
+#define IRQ_IIC3		IRQ_SPI(61)
+#define IRQ_IIC4		IRQ_SPI(62)
+#define IRQ_IIC5		IRQ_SPI(63)
+#define IRQ_IIC6		IRQ_SPI(64)
+#define IRQ_IIC7		IRQ_SPI(65)
+
+#define IRQ_USB_HOST		IRQ_SPI(70)
+#define IRQ_USB_HSOTG		IRQ_SPI(71)
+#define IRQ_MODEM_IF		IRQ_SPI(72)
+#define IRQ_HSMMC0		IRQ_SPI(73)
+#define IRQ_HSMMC1		IRQ_SPI(74)
+#define IRQ_HSMMC2		IRQ_SPI(75)
+#define IRQ_HSMMC3		IRQ_SPI(76)
+#define IRQ_DWMCI		IRQ_SPI(77)
+
+#define IRQ_MIPI_CSIS0		IRQ_SPI(78)
+#define IRQ_MIPI_CSIS1		IRQ_SPI(80)
+
+#define IRQ_ONENAND_AUDI	IRQ_SPI(82)
+#define IRQ_ROTATOR		IRQ_SPI(83)
+#define IRQ_FIMC0		IRQ_SPI(84)
+#define IRQ_FIMC1		IRQ_SPI(85)
+#define IRQ_FIMC2		IRQ_SPI(86)
+#define IRQ_FIMC3		IRQ_SPI(87)
+#define IRQ_JPEG		IRQ_SPI(88)
+#define IRQ_2D			IRQ_SPI(89)
+#define IRQ_PCIE		IRQ_SPI(90)
+
+#define IRQ_MIXER		IRQ_SPI(91)
+#define IRQ_HDMI		IRQ_SPI(92)
+#define IRQ_IIC_HDMIPHY		IRQ_SPI(93)
+#define IRQ_MFC			IRQ_SPI(94)
+#define IRQ_SDO			IRQ_SPI(95)
+
+#define IRQ_AUDIO_SS		IRQ_SPI(96)
+#define IRQ_I2S0		IRQ_SPI(97)
+#define IRQ_I2S1		IRQ_SPI(98)
+#define IRQ_I2S2		IRQ_SPI(99)
+#define IRQ_AC97		IRQ_SPI(100)
+
+#define IRQ_SPDIF		IRQ_SPI(104)
+#define IRQ_ADC0		IRQ_SPI(105)
+#define IRQ_PEN0		IRQ_SPI(106)
+#define IRQ_ADC1		IRQ_SPI(107)
+#define IRQ_PEN1		IRQ_SPI(108)
+#define IRQ_KEYPAD		IRQ_SPI(109)
+#define IRQ_PMU			IRQ_SPI(110)
+#define IRQ_GPS			IRQ_SPI(111)
+#define IRQ_INTFEEDCTRL_SSS	IRQ_SPI(112)
+#define IRQ_SLIMBUS		IRQ_SPI(113)
+
+#define IRQ_TSI			IRQ_SPI(115)
+#define IRQ_SATA		IRQ_SPI(116)
+
+#define MAX_IRQ_IN_COMBINER	8
+#define COMBINER_GROUP(x)	((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(128))
+#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_FIMD0_FIFO		COMBINER_IRQ(11, 0)
+#define IRQ_FIMD0_VSYNC		COMBINER_IRQ(11, 1)
+#define IRQ_FIMD0_SYSTEM	COMBINER_IRQ(11, 2)
+
+#define MAX_COMBINER_NR		16
+
+#define IRQ_ADC			IRQ_ADC0
+#define IRQ_TC			IRQ_PEN0
+
+#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 + 64)
+
+#endif /* __ASM_ARCH_IRQS_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/map.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/map.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/map.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/map.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,197 @@
+/* linux/arch/arm/mach-exynos/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_SYSRAM0		0x02025000
+#define EXYNOS4_PA_SYSRAM1		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		0x10440000
+
+#define EXYNOS4_PA_GIC_CPU		0x10480000
+#define EXYNOS4_PA_GIC_DIST		0x10490000
+
+#define EXYNOS4_PA_COREPERI		0x10500000
+#define EXYNOS4_PA_TWD			0x10500600
+#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_FIMD0		0x11C00000
+
+#define EXYNOS4_PA_HSMMC(x)		(0x12510000 + ((x) * 0x10000))
+#define EXYNOS4_PA_DWMCI		0x12550000
+
+#define EXYNOS4_PA_SATA			0x12560000
+#define EXYNOS4_PA_SATAPHY		0x125D0000
+#define EXYNOS4_PA_SATAPHY_CTRL		0x126B0000
+
+#define EXYNOS4_PA_SROMC		0x12570000
+
+#define EXYNOS4_PA_EHCI			0x12580000
+#define EXYNOS4_PA_HSPHY		0x125B0000
+#define EXYNOS4_PA_MFC			0x13400000
+
+#define EXYNOS4_PA_UART			0x13800000
+
+#define EXYNOS4_PA_VP			0x12C00000
+#define EXYNOS4_PA_MIXER		0x12C10000
+#define EXYNOS4_PA_SDO			0x12C20000
+#define EXYNOS4_PA_HDMI			0x12D00000
+#define EXYNOS4_PA_IIC_HDMIPHY		0x138E0000
+
+#define EXYNOS4_PA_IIC(x)		(0x13860000 + ((x) * 0x10000))
+
+#define EXYNOS4_PA_ADC			0x13910000
+#define EXYNOS4_PA_ADC1			0x13911000
+
+#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 S3C_PA_UART			EXYNOS4_PA_UART
+
+#define S5P_PA_CHIPID			EXYNOS4_PA_CHIPID
+#define S5P_PA_EHCI			EXYNOS4_PA_EHCI
+#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_FIMD0			EXYNOS4_PA_FIMD0
+#define S5P_PA_HDMI			EXYNOS4_PA_HDMI
+#define S5P_PA_IIC_HDMIPHY		EXYNOS4_PA_IIC_HDMIPHY
+#define S5P_PA_MFC			EXYNOS4_PA_MFC
+#define S5P_PA_MIPI_CSIS0		EXYNOS4_PA_MIPI_CSIS0
+#define S5P_PA_MIPI_CSIS1		EXYNOS4_PA_MIPI_CSIS1
+#define S5P_PA_MIXER			EXYNOS4_PA_MIXER
+#define S5P_PA_ONENAND			EXYNOS4_PA_ONENAND
+#define S5P_PA_ONENAND_DMA		EXYNOS4_PA_ONENAND_DMA
+#define S5P_PA_SDO			EXYNOS4_PA_SDO
+#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 S5P_PA_VP			EXYNOS4_PA_VP
+
+#define SAMSUNG_PA_ADC			EXYNOS4_PA_ADC
+#define SAMSUNG_PA_ADC1			EXYNOS4_PA_ADC1
+#define SAMSUNG_PA_KEYPAD		EXYNOS4_PA_KEYPAD
+
+#define EXYNOS_PA_COMBINER		EXYNOS4_PA_COMBINER
+#define EXYNOS_PA_GIC_CPU		EXYNOS4_PA_GIC_CPU
+#define EXYNOS_PA_GIC_DIST		EXYNOS4_PA_GIC_DIST
+#define EXYNOS_PA_PMU			EXYNOS4_PA_PMU
+#define EXYNOS_PA_SYSTIMER		EXYNOS4_PA_SYSTIMER
+
+/* Compatibility UART */
+
+#define S3C_VA_UARTx(x)			(S3C_VA_UART + ((x) * S3C_UART_OFFSET))
+
+#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-3.1-gnu/arch/arm/mach-exynos/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/memory.h	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/include/mach/pm-core.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/pm-core.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/pm-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/pm-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,65 @@
+/* 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.
+*/
+
+#ifndef __ASM_ARCH_PM_CORE_H
+#define __ASM_ARCH_PM_CORE_H __FILE__
+
+#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 */
+}
+
+static inline void s3c_pm_restored_gpios(void)
+{
+	/* nothing here yet */
+}
+
+static inline void samsung_pm_saved_gpios(void)
+{
+	/* nothing here yet */
+}
+
+#endif /* __ASM_ARCH_PM_CORE_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/pmu.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/pmu.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/pmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/pmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,32 @@
+/* linux/arch/arm/mach-exynos4/include/mach/pmu.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * EXYNOS4210 - PMU(Power Management Unit) 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_PMU_H
+#define __ASM_ARCH_PMU_H __FILE__
+
+#define PMU_TABLE_END	NULL
+
+enum sys_powerdown {
+	SYS_AFTR,
+	SYS_LPA,
+	SYS_SLEEP,
+	NUM_SYS_POWERDOWN,
+};
+
+struct exynos4_pmu_conf {
+	void __iomem *reg;
+	unsigned int val[NUM_SYS_POWERDOWN];
+};
+
+extern void exynos4_sys_powerdown_conf(enum sys_powerdown mode);
+
+#endif /* __ASM_ARCH_PMU_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-audss.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-audss.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-audss.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-audss.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+/* arch/arm/mach-exynos4/include/mach/regs-audss.h
+ *
+ * Copyright (c) 2011 Samsung Electronics
+ *		http://www.samsung.com
+ *
+ * Exynos4 Audio SubSystem 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 __PLAT_REGS_AUDSS_H
+#define __PLAT_REGS_AUDSS_H __FILE__
+
+#define EXYNOS4_AUDSS_INT_MEM	(0x03000000)
+
+#endif /* _PLAT_REGS_AUDSS_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-clock.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-clock.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,210 @@
+/* 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 <plat/cpu.h>
+#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_LOCK			S5P_CLKREG(0x0C010)
+#define S5P_VPLL_LOCK			S5P_CLKREG(0x0C020)
+
+#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_TV			S5P_CLKREG(0x0C224)
+#define S5P_CLKSRC_MFC			S5P_CLKREG(0x0C228)
+#define S5P_CLKSRC_G3D			S5P_CLKREG(0x0C22C)
+#define S5P_CLKSRC_IMAGE		S5P_CLKREG(0x0C230)
+#define S5P_CLKSRC_LCD0			S5P_CLKREG(0x0C234)
+#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_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_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_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_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_CLKDIV2_RATIO		S5P_CLKREG(0x0C580)
+
+#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		(soc_is_exynos4210() ? \
+					S5P_CLKREG(0x0C930) : \
+					S5P_CLKREG(0x04930))
+#define S5P_CLKGATE_IP_IMAGE_4210	S5P_CLKREG(0x0C930)
+#define S5P_CLKGATE_IP_IMAGE_4212	S5P_CLKREG(0x04930)
+#define S5P_CLKGATE_IP_LCD0		S5P_CLKREG(0x0C934)
+#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		(soc_is_exynos4210() ? \
+					S5P_CLKREG(0x0C960) : \
+					S5P_CLKREG(0x08960))
+#define S5P_CLKGATE_IP_PERIR_4210	S5P_CLKREG(0x0C960)
+#define S5P_CLKGATE_IP_PERIR_4212	S5P_CLKREG(0x08960)
+#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			(soc_is_exynos4210() ? \
+					S5P_CLKREG(0x14004) :  \
+					S5P_CLKREG(0x10008))
+#define S5P_APLL_CON0			S5P_CLKREG(0x14100)
+#define S5P_APLL_CON1			S5P_CLKREG(0x14104)
+#define S5P_MPLL_CON0			(soc_is_exynos4210() ? \
+					S5P_CLKREG(0x14108) : \
+					S5P_CLKREG(0x10108))
+#define S5P_MPLL_CON1			(soc_is_exynos4210() ? \
+					S5P_CLKREG(0x1410C) : \
+					S5P_CLKREG(0x1010C))
+
+#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_EPLLCON0_ENABLE_SHIFT	(31)
+#define S5P_EPLLCON0_LOCKED_SHIFT	(29)
+
+#define S5P_VPLLCON0_ENABLE_SHIFT	(31)
+#define S5P_VPLLCON0_LOCKED_SHIFT	(29)
+
+#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)
+
+/* Only for EXYNOS4210 */
+
+#define S5P_CLKSRC_LCD1			S5P_CLKREG(0x0C238)
+#define S5P_CLKSRC_MASK_LCD1		S5P_CLKREG(0x0C338)
+#define S5P_CLKDIV_LCD1			S5P_CLKREG(0x0C538)
+#define S5P_CLKGATE_IP_LCD1		S5P_CLKREG(0x0C938)
+
+/* 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-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-gpio.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-irq.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-irq.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-irq.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-mct.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-mct.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-mct.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-mct.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,53 @@
+/* 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_L_BASE		EXYNOS4_MCTREG(0x300)
+#define EXYNOS4_MCT_L_BASE(x)		(_EXYNOS4_MCT_L_BASE + (0x100 * x))
+#define EXYNOS4_MCT_L_MASK		(0xffffff00)
+
+#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-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-mem.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-mem.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-mem.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-mem.h	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-pmu.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-pmu.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-pmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-pmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,220 @@
+/* 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_STANDBYWFI_ISP_ARM		(1 << 18)
+#define S5P_USE_STANDBY_WFE0			(1 << 24)
+#define S5P_USE_STANDBY_WFE1			(1 << 25)
+#define S5P_USE_STANDBYWFE_ISP_ARM		(1 << 26)
+
+#define S5P_SWRESET				S5P_PMUREG(0x0400)
+
+#define S5P_WAKEUP_STAT				S5P_PMUREG(0x0600)
+#define S5P_EINT_WAKEUP_MASK			S5P_PMUREG(0x0604)
+#define S5P_WAKEUP_MASK				S5P_PMUREG(0x0608)
+
+#define S5P_HDMI_PHY_CONTROL			S5P_PMUREG(0x0700)
+#define S5P_HDMI_PHY_ENABLE			(1 << 0)
+
+#define S5P_DAC_PHY_CONTROL			S5P_PMUREG(0x070C)
+#define S5P_DAC_PHY_ENABLE			(1 << 0)
+
+#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_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_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_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_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_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_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_GPS_CONF			S5P_PMUREG(0x3CE0)
+
+#define S5P_PMU_SATA_PHY_CONTROL_EN		0x1
+#define S5P_CORE_LOCAL_PWR_EN			0x3
+#define S5P_INT_LOCAL_PWR_EN			0x7
+
+#define S5P_CHECK_SLEEP				0x00000BAD
+
+/* Only for EXYNOS4210 */
+#define S5P_USBHOST_PHY_CONTROL		S5P_PMUREG(0x0708)
+#define S5P_USBHOST_PHY_ENABLE		(1 << 0)
+
+#define S5P_PMU_SATA_PHY_CONTROL	S5P_PMUREG(0x0720)
+
+#define S5P_CMU_CLKSTOP_LCD1_LOWPWR	S5P_PMUREG(0x1154)
+#define S5P_CMU_RESET_LCD1_LOWPWR	S5P_PMUREG(0x1174)
+#define S5P_MODIMIF_MEM_LOWPWR		S5P_PMUREG(0x11C4)
+#define S5P_PCIE_MEM_LOWPWR		S5P_PMUREG(0x11E0)
+#define S5P_SATA_MEM_LOWPWR		S5P_PMUREG(0x11E4)
+#define S5P_LCD1_LOWPWR			S5P_PMUREG(0x1394)
+
+#define S5P_PMU_LCD1_CONF		S5P_PMUREG(0x3CA0)
+
+/* Only for EXYNOS4212 */
+#define S5P_ISP_ARM_LOWPWR			S5P_PMUREG(0x1050)
+#define S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR	S5P_PMUREG(0x1054)
+#define S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR	S5P_PMUREG(0x1058)
+#define S5P_CMU_ACLKSTOP_COREBLK_LOWPWR		S5P_PMUREG(0x1110)
+#define S5P_CMU_SCLKSTOP_COREBLK_LOWPWR		S5P_PMUREG(0x1114)
+#define S5P_CMU_RESET_COREBLK_LOWPWR		S5P_PMUREG(0x111C)
+#define S5P_MPLLUSER_SYSCLK_LOWPWR		S5P_PMUREG(0x1130)
+#define S5P_CMU_CLKSTOP_ISP_LOWPWR		S5P_PMUREG(0x1154)
+#define S5P_CMU_RESET_ISP_LOWPWR		S5P_PMUREG(0x1174)
+#define S5P_TOP_BUS_COREBLK_LOWPWR		S5P_PMUREG(0x1190)
+#define S5P_TOP_RETENTION_COREBLK_LOWPWR	S5P_PMUREG(0x1194)
+#define S5P_TOP_PWR_COREBLK_LOWPWR		S5P_PMUREG(0x1198)
+#define S5P_OSCCLK_GATE_LOWPWR			S5P_PMUREG(0x11A4)
+#define S5P_LOGIC_RESET_COREBLK_LOWPWR		S5P_PMUREG(0x11B0)
+#define S5P_OSCCLK_GATE_COREBLK_LOWPWR		S5P_PMUREG(0x11B4)
+#define S5P_HSI_MEM_LOWPWR			S5P_PMUREG(0x11C4)
+#define S5P_ROTATOR_MEM_LOWPWR			S5P_PMUREG(0x11DC)
+#define S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR	S5P_PMUREG(0x123C)
+#define S5P_PAD_ISOLATION_COREBLK_LOWPWR	S5P_PMUREG(0x1250)
+#define S5P_GPIO_MODE_COREBLK_LOWPWR		S5P_PMUREG(0x1320)
+#define S5P_TOP_ASB_RESET_LOWPWR		S5P_PMUREG(0x1344)
+#define S5P_TOP_ASB_ISOLATION_LOWPWR		S5P_PMUREG(0x1348)
+#define S5P_ISP_LOWPWR				S5P_PMUREG(0x1394)
+#define S5P_DRAM_FREQ_DOWN_LOWPWR		S5P_PMUREG(0x13B0)
+#define S5P_DDRPHY_DLLOFF_LOWPWR		S5P_PMUREG(0x13B4)
+#define S5P_CMU_SYSCLK_ISP_LOWPWR		S5P_PMUREG(0x13B8)
+#define S5P_CMU_SYSCLK_GPS_LOWPWR		S5P_PMUREG(0x13BC)
+#define S5P_LPDDR_PHY_DLL_LOCK_LOWPWR		S5P_PMUREG(0x13C0)
+
+#define S5P_ARM_L2_0_OPTION			S5P_PMUREG(0x2608)
+#define S5P_ARM_L2_1_OPTION			S5P_PMUREG(0x2628)
+#define S5P_ONENAND_MEM_OPTION			S5P_PMUREG(0x2E08)
+#define S5P_HSI_MEM_OPTION			S5P_PMUREG(0x2E28)
+#define S5P_G2D_ACP_MEM_OPTION			S5P_PMUREG(0x2E48)
+#define S5P_USBOTG_MEM_OPTION			S5P_PMUREG(0x2E68)
+#define S5P_HSMMC_MEM_OPTION			S5P_PMUREG(0x2E88)
+#define S5P_CSSYS_MEM_OPTION			S5P_PMUREG(0x2EA8)
+#define S5P_SECSS_MEM_OPTION			S5P_PMUREG(0x2EC8)
+#define S5P_ROTATOR_MEM_OPTION			S5P_PMUREG(0x2F48)
+
+#endif /* __ASM_ARCH_REGS_PMU_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-sysmmu.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-sysmmu.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-sysmmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-sysmmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-usb-phy.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-usb-phy.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/regs-usb-phy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/regs-usb-phy.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef __PLAT_S5P_REGS_USB_PHY_H
+#define __PLAT_S5P_REGS_USB_PHY_H
+
+#define EXYNOS4_HSOTG_PHYREG(x)		((x) + S3C_VA_USB_HSPHY)
+
+#define EXYNOS4_PHYPWR			EXYNOS4_HSOTG_PHYREG(0x00)
+#define PHY1_HSIC_NORMAL_MASK		(0xf << 9)
+#define PHY1_HSIC1_SLEEP		(1 << 12)
+#define PHY1_HSIC1_FORCE_SUSPEND	(1 << 11)
+#define PHY1_HSIC0_SLEEP		(1 << 10)
+#define PHY1_HSIC0_FORCE_SUSPEND	(1 << 9)
+
+#define PHY1_STD_NORMAL_MASK		(0x7 << 6)
+#define PHY1_STD_SLEEP			(1 << 8)
+#define PHY1_STD_ANALOG_POWERDOWN	(1 << 7)
+#define PHY1_STD_FORCE_SUSPEND		(1 << 6)
+
+#define PHY0_NORMAL_MASK		(0x39 << 0)
+#define PHY0_SLEEP			(1 << 5)
+#define PHY0_OTG_DISABLE		(1 << 4)
+#define PHY0_ANALOG_POWERDOWN		(1 << 3)
+#define PHY0_FORCE_SUSPEND		(1 << 0)
+
+#define EXYNOS4_PHYCLK			EXYNOS4_HSOTG_PHYREG(0x04)
+#define PHY1_COMMON_ON_N		(1 << 7)
+#define PHY0_COMMON_ON_N		(1 << 4)
+#define PHY0_ID_PULLUP			(1 << 2)
+#define CLKSEL_MASK			(0x3 << 0)
+#define CLKSEL_SHIFT			(0)
+#define CLKSEL_48M			(0x0 << 0)
+#define CLKSEL_12M			(0x2 << 0)
+#define CLKSEL_24M			(0x3 << 0)
+
+#define EXYNOS4_RSTCON			EXYNOS4_HSOTG_PHYREG(0x08)
+#define HOST_LINK_PORT_SWRST_MASK	(0xf << 6)
+#define HOST_LINK_PORT2_SWRST		(1 << 9)
+#define HOST_LINK_PORT1_SWRST		(1 << 8)
+#define HOST_LINK_PORT0_SWRST		(1 << 7)
+#define HOST_LINK_ALL_SWRST		(1 << 6)
+
+#define PHY1_SWRST_MASK			(0x7 << 3)
+#define PHY1_HSIC_SWRST			(1 << 5)
+#define PHY1_STD_SWRST			(1 << 4)
+#define PHY1_ALL_SWRST			(1 << 3)
+
+#define PHY0_SWRST_MASK			(0x7 << 0)
+#define PHY0_PHYLINK_SWRST		(1 << 2)
+#define PHY0_HLINK_SWRST		(1 << 1)
+#define PHY0_SWRST			(1 << 0)
+
+#define EXYNOS4_PHY1CON			EXYNOS4_HSOTG_PHYREG(0x34)
+#define FPENABLEN			(1 << 0)
+
+#endif /* __PLAT_S5P_REGS_USB_PHY_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/sysmmu.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/sysmmu.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/sysmmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/sysmmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/include/mach/system.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/system.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/include/mach/timex.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/timex.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/timex.h	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/include/mach/uncompress.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/uncompress.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/include/mach/vmalloc.h linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/vmalloc.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/include/mach/vmalloc.h	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/init.c linux-libre-3.2-gnu/arch/arm/mach-exynos/init.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/init.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,42 @@
+/* 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);
+		}
+		tcfg->flags |= NO_NEED_CHECK_CLKSRC;
+	}
+
+	s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/irq-combiner.c linux-libre-3.2-gnu/arch/arm/mach-exynos/irq-combiner.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/irq-combiner.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/irq-combiner.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,124 @@
+/* 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;
+
+	chained_irq_enter(chip, desc);
+
+	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:
+	chained_irq_exit(chip, desc);
+}
+
+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-3.1-gnu/arch/arm/mach-exynos/irq-eint.c linux-libre-3.2-gnu/arch/arm/mach-exynos/irq-eint.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/irq-eint.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/irq-eint.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,237 @@
+/* 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>
+
+#include <asm/mach/irq.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)
+{
+	struct irq_chip *chip = irq_get_chip(irq);
+	chained_irq_enter(chip, desc);
+	exynos4_irq_demux_eint(IRQ_EINT(16));
+	exynos4_irq_demux_eint(IRQ_EINT(24));
+	chained_irq_exit(chip, desc);
+}
+
+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);
+
+	chained_irq_enter(chip, desc);
+	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);
+	chained_irq_exit(chip, desc);
+}
+
+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-3.1-gnu/arch/arm/mach-exynos/Kconfig linux-libre-3.2-gnu/arch/arm/mach-exynos/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,349 @@
+# arch/arm/mach-exynos/Kconfig
+#
+# Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+#		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+# Configuration options for the EXYNOS4
+
+if ARCH_EXYNOS
+
+menu "SAMSUNG EXYNOS SoCs Support"
+
+choice
+	prompt "EXYNOS System Type"
+	default ARCH_EXYNOS4
+
+config ARCH_EXYNOS4
+	bool "SAMSUNG EXYNOS4"
+	help
+	  Samsung EXYNOS4 SoCs based systems
+
+endchoice
+
+comment "EXYNOS SoCs"
+
+config CPU_EXYNOS4210
+	bool "SAMSUNG EXYNOS4210"
+	default y
+	depends on ARCH_EXYNOS4
+	select SAMSUNG_DMADEV
+	select ARM_CPU_SUSPEND if PM
+	select S5P_PM if PM
+	select S5P_SLEEP if PM
+	help
+	  Enable EXYNOS4210 CPU support
+
+config SOC_EXYNOS4212
+	bool "SAMSUNG EXYNOS4212"
+	default y
+	depends on ARCH_EXYNOS4
+	select S5P_PM if PM
+	select S5P_SLEEP if PM
+	help
+	  Enable EXYNOS4212 SoC support
+
+config SOC_EXYNOS4412
+	bool "SAMSUNG EXYNOS4412"
+	default y
+	depends on ARCH_EXYNOS4
+	help
+	  Enable EXYNOS4412 SoC support
+
+config EXYNOS4_MCT
+	bool
+	default y
+	help
+	  Use MCT (Multi Core Timer) as kernel timers
+
+config EXYNOS4_DEV_AHCI
+	bool
+	help
+	  Compile in platform device definitions for AHCI
+
+config EXYNOS4_SETUP_FIMD0
+	bool
+	help
+	  Common setup code for FIMD0.
+
+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_DEV_DWMCI
+	bool
+	help
+	  Compile in platform device definitions for DWMCI
+
+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.
+
+config EXYNOS4_SETUP_USB_PHY
+	bool
+	help
+	  Common setup code for USB PHY controller
+
+# machine support
+
+if ARCH_EXYNOS4
+
+comment "EXYNOS4210 Boards"
+
+config MACH_SMDKC210
+	bool "SMDKC210"
+	select MACH_SMDKV310
+	help
+	  Machine support for Samsung SMDKC210
+
+config MACH_SMDKV310
+	bool "SMDKV310"
+	select CPU_EXYNOS4210
+	select S5P_DEV_FIMD0
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select S3C_DEV_I2C1
+	select S5P_DEV_FIMC0
+	select S5P_DEV_FIMC1
+	select S5P_DEV_FIMC2
+	select S5P_DEV_FIMC3
+	select S5P_DEV_I2C_HDMIPHY
+	select S5P_DEV_MFC
+	select S5P_DEV_TV
+	select S5P_DEV_USB_EHCI
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC1
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select SAMSUNG_DEV_BACKLIGHT
+	select EXYNOS4_DEV_AHCI
+	select SAMSUNG_DEV_KEYPAD
+	select EXYNOS4_DEV_PD
+	select SAMSUNG_DEV_PWM
+	select EXYNOS4_DEV_SYSMMU
+	select EXYNOS4_SETUP_FIMD0
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_KEYPAD
+	select EXYNOS4_SETUP_SDHCI
+	select EXYNOS4_SETUP_USB_PHY
+	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 S5P_GPIO_INT
+	select S5P_DEV_FIMC0
+	select S5P_DEV_FIMC1
+	select S5P_DEV_FIMC2
+	select S5P_DEV_FIMC3
+	select S5P_DEV_CSIS0
+	select S5P_DEV_FIMD0
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select S3C_DEV_I2C1
+	select S3C_DEV_I2C3
+	select S3C_DEV_I2C5
+	select S5P_DEV_I2C_HDMIPHY
+	select S5P_DEV_MFC
+	select S5P_DEV_ONENAND
+	select S5P_DEV_TV
+	select EXYNOS4_DEV_PD
+	select EXYNOS4_SETUP_FIMD0
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_I2C3
+	select EXYNOS4_SETUP_I2C5
+	select EXYNOS4_SETUP_SDHCI
+	select EXYNOS4_SETUP_FIMC
+	select S5P_SETUP_MIPIPHY
+	help
+	  Machine support for Samsung Mobile Universal S5PC210 Reference
+	  Board.
+
+config MACH_NURI
+	bool "Mobile NURI Board"
+	select CPU_EXYNOS4210
+	select S5P_GPIO_INT
+	select S3C_DEV_WDT
+	select S3C_DEV_RTC
+	select S5P_DEV_FIMD0
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select S3C_DEV_I2C1
+	select S3C_DEV_I2C3
+	select S3C_DEV_I2C5
+	select S5P_DEV_CSIS0
+	select S5P_DEV_FIMC0
+	select S5P_DEV_FIMC1
+	select S5P_DEV_FIMC2
+	select S5P_DEV_FIMC3
+	select S5P_DEV_MFC
+	select S5P_DEV_USB_EHCI
+	select S5P_SETUP_MIPIPHY
+	select EXYNOS4_DEV_PD
+	select EXYNOS4_SETUP_FIMC
+	select EXYNOS4_SETUP_FIMD0
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_I2C3
+	select EXYNOS4_SETUP_I2C5
+	select EXYNOS4_SETUP_SDHCI
+	select EXYNOS4_SETUP_USB_PHY
+	select S5P_SETUP_MIPIPHY
+	select SAMSUNG_DEV_PWM
+	select SAMSUNG_DEV_ADC
+	help
+	  Machine support for Samsung Mobile NURI Board.
+
+config MACH_ORIGEN
+	bool "ORIGEN"
+	select CPU_EXYNOS4210
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC2
+	select S5P_DEV_FIMC0
+	select S5P_DEV_FIMC1
+	select S5P_DEV_FIMC2
+	select S5P_DEV_FIMC3
+	select S5P_DEV_FIMD0
+	select S5P_DEV_I2C_HDMIPHY
+	select S5P_DEV_MFC
+	select S5P_DEV_TV
+	select S5P_DEV_USB_EHCI
+	select SAMSUNG_DEV_BACKLIGHT
+	select SAMSUNG_DEV_PWM
+	select EXYNOS4_DEV_PD
+	select EXYNOS4_SETUP_FIMD0
+	select EXYNOS4_SETUP_SDHCI
+	select EXYNOS4_SETUP_USB_PHY
+	help
+	  Machine support for ORIGEN based on Samsung EXYNOS4210
+
+comment "EXYNOS4212 Boards"
+
+config MACH_SMDK4212
+	bool "SMDK4212"
+	select SOC_EXYNOS4212
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select S3C_DEV_I2C1
+	select S3C_DEV_I2C3
+	select S3C_DEV_I2C7
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select SAMSUNG_DEV_BACKLIGHT
+	select SAMSUNG_DEV_KEYPAD
+	select SAMSUNG_DEV_PWM
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_I2C3
+	select EXYNOS4_SETUP_I2C7
+	select EXYNOS4_SETUP_KEYPAD
+	select EXYNOS4_SETUP_SDHCI
+	help
+	  Machine support for Samsung SMDK4212
+
+comment "EXYNOS4412 Boards"
+
+config MACH_SMDK4412
+	bool "SMDK4412"
+	select SOC_EXYNOS4412
+	select MACH_SMDK4212
+	help
+	  Machine support for Samsung SMDK4412
+endif
+
+if ARCH_EXYNOS4
+
+comment "Configuration for HSMMC 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.
+endif
+
+endmenu
+
+endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/mach-armlex4210.c linux-libre-3.2-gnu/arch/arm/mach-exynos/mach-armlex4210.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/mach-armlex4210.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/mach-armlex4210.c	2012-01-04 18:55:44.000000000 -0500
@@ -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> */
+	.atag_offset	= 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-3.1-gnu/arch/arm/mach-exynos/mach-nuri.c linux-libre-3.2-gnu/arch/arm/mach-exynos/mach-nuri.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/mach-nuri.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/mach-nuri.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1339 @@
+/*
+ * 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/i2c/atmel_mxt_ts.h>
+#include <linux/i2c-gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio.h>
+#include <linux/power/max8903_charger.h>
+#include <linux/power/max17042_battery.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mfd/max8997.h>
+#include <linux/mfd/max8997-private.h>
+#include <linux/mmc/host.h>
+#include <linux/fb.h>
+#include <linux/pwm_backlight.h>
+
+#include <video/platform_lcd.h>
+#include <media/m5mols.h>
+#include <media/s5p_fimc.h>
+#include <media/v4l2-mediabus.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/adc.h>
+#include <plat/regs-fb-v4.h>
+#include <plat/regs-serial.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/fb.h>
+#include <plat/sdhci.h>
+#include <plat/ehci.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <plat/iic.h>
+#include <plat/mfc.h>
+#include <plat/pd.h>
+#include <plat/fimc-core.h>
+#include <plat/camport.h>
+#include <plat/mipi_csis.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,
+	FIXED_REG_ID_MAX8903,
+	FIXED_REG_ID_CAM_A28V,
+	FIXED_REG_ID_CAM_12V,
+};
+
+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,
+	},
+};
+
+/* Frame Buffer */
+static struct s3c_fb_pd_win nuri_fb_win0 = {
+	.win_mode = {
+		.left_margin	= 64,
+		.right_margin	= 16,
+		.upper_margin	= 64,
+		.lower_margin	= 1,
+		.hsync_len	= 48,
+		.vsync_len	= 3,
+		.xres		= 1280,
+		.yres		= 800,
+		.refresh	= 60,
+	},
+	.max_bpp	= 24,
+	.default_bpp	= 16,
+	.virtual_x	= 1280,
+	.virtual_y	= 800,
+};
+
+static struct s3c_fb_platdata nuri_fb_pdata __initdata = {
+	.win[0]		= &nuri_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
+			  VIDCON0_CLKSEL_LCD,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+	.setup_gpio	= exynos4_fimd0_gpio_setup_24bpp,
+};
+
+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 */
+};
+
+/* TSP */
+static u8 mxt_init_vals[] = {
+	/* MXT_GEN_COMMAND(6) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* MXT_GEN_POWER(7) */
+	0x20, 0xff, 0x32,
+	/* MXT_GEN_ACQUIRE(8) */
+	0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23,
+	/* MXT_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,
+	/* MXT_TOUCH_KEYARRAY(15) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	0x00,
+	/* MXT_SPT_GPIOPWM(19) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* MXT_PROCI_GRIPFACE(20) */
+	0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04,
+	0x0f, 0x0a,
+	/* MXT_PROCG_NOISE(22) */
+	0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00,
+	0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03,
+	/* MXT_TOUCH_PROXIMITY(23) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00,
+	/* MXT_PROCI_ONETOUCH(24) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* MXT_SPT_SELFTEST(25) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	/* MXT_PROCI_TWOTOUCH(27) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* MXT_SPT_CTECONFIG(28) */
+	0x00, 0x00, 0x02, 0x08, 0x10, 0x00,
+};
+
+static struct mxt_platform_data mxt_platform_data = {
+	.config			= mxt_init_vals,
+	.config_length		= ARRAY_SIZE(mxt_init_vals),
+
+	.x_line			= 18,
+	.y_line			= 11,
+	.x_size			= 1024,
+	.y_size			= 600,
+	.blen			= 0x1,
+	.threshold		= 0x28,
+	.voltage		= 2800000,		/* 2.8V */
+	.orient			= MXT_DIAGONAL_COUNTER,
+	.irqflags		= IRQF_TRIGGER_FALLING,
+};
+
+static struct s3c2410_platform_i2c i2c3_data __initdata = {
+	.flags		= 0,
+	.bus_num	= 3,
+	.slave_addr	= 0x10,
+	.frequency	= 400 * 1000,
+	.sda_delay	= 100,
+};
+
+static struct i2c_board_info i2c3_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("atmel_mxt_ts", 0x4a),
+		.platform_data	= &mxt_platform_data,
+		.irq		= IRQ_EINT(4),
+	},
+};
+
+static void __init nuri_tsp_init(void)
+{
+	int gpio;
+
+	/* TOUCH_INT: XEINT_4 */
+	gpio = EXYNOS4_GPX0(4);
+	gpio_request(gpio, "TOUCH_INT");
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+}
+
+static struct regulator_consumer_supply __initdata max8997_ldo1_[] = {
+	REGULATOR_SUPPLY("vdd", "s5p-adc"), /* Used by CPU's ADC drv */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo3_[] = {
+	REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo4_[] = {
+	REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo5_[] = {
+	REGULATOR_SUPPLY("vhsic", "modemctl"), /* MODEM */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo7_[] = {
+	REGULATOR_SUPPLY("dig_18", "0-001f"), /* HCD803 */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo8_[] = {
+	REGULATOR_SUPPLY("vusb_d", NULL), /* Used by CPU */
+	REGULATOR_SUPPLY("vdac", NULL), /* Used by CPU */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo11_[] = {
+	REGULATOR_SUPPLY("vcc", "platform-lcd"), /* U804 LVDS */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo12_[] = {
+	REGULATOR_SUPPLY("vddio", "6-003c"), /* HDC802 */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo13_[] = {
+	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"), /* TFLASH */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo14_[] = {
+	REGULATOR_SUPPLY("inmotor", "max8997-haptic"),
+};
+static struct regulator_consumer_supply __initdata max8997_ldo15_[] = {
+	REGULATOR_SUPPLY("avdd", "3-004a"), /* Touch Screen */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo16_[] = {
+	REGULATOR_SUPPLY("d_sensor", "0-001f"), /* HDC803 */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo18_[] = {
+	REGULATOR_SUPPLY("vdd", "3-004a"), /* Touch Screen */
+};
+static struct regulator_consumer_supply __initdata max8997_buck1_[] = {
+	REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata max8997_buck2_[] = {
+	REGULATOR_SUPPLY("vdd_int", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata max8997_buck3_[] = {
+	REGULATOR_SUPPLY("vdd", "mali_dev.0"), /* G3D of Exynos 4 */
+};
+static struct regulator_consumer_supply __initdata max8997_buck4_[] = {
+	REGULATOR_SUPPLY("core", "0-001f"), /* HDC803 */
+};
+static struct regulator_consumer_supply __initdata max8997_buck6_[] = {
+	REGULATOR_SUPPLY("dig_28", "0-001f"), /* pin "7" of HDC803 */
+};
+static struct regulator_consumer_supply __initdata max8997_esafeout1_[] = {
+	REGULATOR_SUPPLY("usb_vbus", NULL), /* CPU's USB OTG */
+};
+static struct regulator_consumer_supply __initdata max8997_esafeout2_[] = {
+	REGULATOR_SUPPLY("usb_vbus", "modemctl"), /* VBUS of Modem */
+};
+
+static struct regulator_consumer_supply __initdata max8997_charger_[] = {
+	REGULATOR_SUPPLY("vinchg1", "charger-manager.0"),
+};
+static struct regulator_consumer_supply __initdata max8997_chg_toff_[] = {
+	REGULATOR_SUPPLY("vinchg_stop", NULL), /* for jack interrupt handlers */
+};
+
+static struct regulator_consumer_supply __initdata max8997_32khz_ap_[] = {
+	REGULATOR_SUPPLY("gps_clk", "bcm4751"),
+	REGULATOR_SUPPLY("bt_clk", "bcm4330-b1"),
+	REGULATOR_SUPPLY("wifi_clk", "bcm433-b1"),
+};
+
+static struct regulator_init_data __initdata max8997_ldo1_data = {
+	.constraints	= {
+		.name		= "VADC_3.3V_C210",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo1_),
+	.consumer_supplies	= max8997_ldo1_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo2_data = {
+	.constraints	= {
+		.name		= "VALIVE_1.1V_C210",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo3_data = {
+	.constraints	= {
+		.name		= "VUSB_1.1V_C210",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo3_),
+	.consumer_supplies	= max8997_ldo3_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo4_data = {
+	.constraints	= {
+		.name		= "VMIPI_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo4_),
+	.consumer_supplies	= max8997_ldo4_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo5_data = {
+	.constraints	= {
+		.name		= "VHSIC_1.2V_C210",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo5_),
+	.consumer_supplies	= max8997_ldo5_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo6_data = {
+	.constraints	= {
+		.name		= "VCC_1.8V_PDA",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo7_data = {
+	.constraints	= {
+		.name		= "CAM_ISP_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo7_),
+	.consumer_supplies	= max8997_ldo7_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo8_data = {
+	.constraints	= {
+		.name		= "VUSB/VDAC_3.3V_C210",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo8_),
+	.consumer_supplies	= max8997_ldo8_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo9_data = {
+	.constraints	= {
+		.name		= "VCC_2.8V_PDA",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo10_data = {
+	.constraints	= {
+		.name		= "VPLL_1.1V_C210",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo11_data = {
+	.constraints	= {
+		.name		= "LVDS_VDD3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.boot_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo11_),
+	.consumer_supplies	= max8997_ldo11_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo12_data = {
+	.constraints	= {
+		.name		= "VT_CAM_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo12_),
+	.consumer_supplies	= max8997_ldo12_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo13_data = {
+	.constraints	= {
+		.name		= "VTF_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo13_),
+	.consumer_supplies	= max8997_ldo13_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo14_data = {
+	.constraints	= {
+		.name		= "VCC_3.0V_MOTOR",
+		.min_uV		= 3000000,
+		.max_uV		= 3000000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo14_),
+	.consumer_supplies	= max8997_ldo14_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo15_data = {
+	.constraints	= {
+		.name		= "VTOUCH_ADVV2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo15_),
+	.consumer_supplies	= max8997_ldo15_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo16_data = {
+	.constraints	= {
+		.name		= "CAM_SENSOR_IO_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo16_),
+	.consumer_supplies	= max8997_ldo16_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo18_data = {
+	.constraints	= {
+		.name		= "VTOUCH_VDD2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo18_),
+	.consumer_supplies	= max8997_ldo18_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo21_data = {
+	.constraints	= {
+		.name		= "VDDQ_M1M2_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_buck1_data = {
+	.constraints	= {
+		.name		= "VARM_1.2V_C210",
+		.min_uV		= 900000,
+		.max_uV		= 1350000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_buck1_),
+	.consumer_supplies = max8997_buck1_,
+};
+
+static struct regulator_init_data __initdata max8997_buck2_data = {
+	.constraints	= {
+		.name		= "VINT_1.1V_C210",
+		.min_uV		= 900000,
+		.max_uV		= 1100000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_buck2_),
+	.consumer_supplies = max8997_buck2_,
+};
+
+static struct regulator_init_data __initdata max8997_buck3_data = {
+	.constraints	= {
+		.name		= "VG3D_1.1V_C210",
+		.min_uV		= 900000,
+		.max_uV		= 1100000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_buck3_),
+	.consumer_supplies = max8997_buck3_,
+};
+
+static struct regulator_init_data __initdata max8997_buck4_data = {
+	.constraints	= {
+		.name		= "CAM_ISP_CORE_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_buck4_),
+	.consumer_supplies = max8997_buck4_,
+};
+
+static struct regulator_init_data __initdata max8997_buck5_data = {
+	.constraints	= {
+		.name		= "VMEM_1.2V_C210",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_buck6_data = {
+	.constraints	= {
+		.name		= "CAM_AF_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_buck6_),
+	.consumer_supplies = max8997_buck6_,
+};
+
+static struct regulator_init_data __initdata max8997_buck7_data = {
+	.constraints	= {
+		.name		= "VCC_SUB_2.0V",
+		.min_uV		= 2000000,
+		.max_uV		= 2000000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_32khz_ap_data = {
+	.constraints	= {
+		.name		= "32KHz AP",
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_32khz_ap_),
+	.consumer_supplies = max8997_32khz_ap_,
+};
+
+static struct regulator_init_data __initdata max8997_32khz_cp_data = {
+	.constraints	= {
+		.name		= "32KHz CP",
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_vichg_data = {
+	.constraints	= {
+		.name		= "VICHG",
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_esafeout1_data = {
+	.constraints	= {
+		.name		= "SAFEOUT1",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_esafeout1_),
+	.consumer_supplies	= max8997_esafeout1_,
+};
+
+static struct regulator_init_data __initdata max8997_esafeout2_data = {
+	.constraints	= {
+		.name		= "SAFEOUT2",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_esafeout2_),
+	.consumer_supplies	= max8997_esafeout2_,
+};
+
+static struct regulator_init_data __initdata max8997_charger_cv_data = {
+	.constraints	= {
+		.name		= "CHARGER_CV",
+		.min_uV		= 4200000,
+		.max_uV		= 4200000,
+		.apply_uV	= 1,
+	},
+};
+
+static struct regulator_init_data __initdata max8997_charger_data = {
+	.constraints	= {
+		.name		= "CHARGER",
+		.min_uA		= 200000,
+		.max_uA		= 950000,
+		.boot_on	= 1,
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS |
+				REGULATOR_CHANGE_CURRENT,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_charger_),
+	.consumer_supplies	= max8997_charger_,
+};
+
+static struct regulator_init_data __initdata max8997_charger_topoff_data = {
+	.constraints	= {
+		.name		= "CHARGER TOPOFF",
+		.min_uA		= 50000,
+		.max_uA		= 200000,
+		.valid_ops_mask = REGULATOR_CHANGE_CURRENT,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_chg_toff_),
+	.consumer_supplies	= max8997_chg_toff_,
+};
+
+static struct max8997_regulator_data __initdata nuri_max8997_regulators[] = {
+	{ MAX8997_LDO1, &max8997_ldo1_data },
+	{ MAX8997_LDO2, &max8997_ldo2_data },
+	{ MAX8997_LDO3, &max8997_ldo3_data },
+	{ MAX8997_LDO4, &max8997_ldo4_data },
+	{ MAX8997_LDO5, &max8997_ldo5_data },
+	{ MAX8997_LDO6, &max8997_ldo6_data },
+	{ MAX8997_LDO7, &max8997_ldo7_data },
+	{ MAX8997_LDO8, &max8997_ldo8_data },
+	{ MAX8997_LDO9, &max8997_ldo9_data },
+	{ MAX8997_LDO10, &max8997_ldo10_data },
+	{ MAX8997_LDO11, &max8997_ldo11_data },
+	{ MAX8997_LDO12, &max8997_ldo12_data },
+	{ MAX8997_LDO13, &max8997_ldo13_data },
+	{ MAX8997_LDO14, &max8997_ldo14_data },
+	{ MAX8997_LDO15, &max8997_ldo15_data },
+	{ MAX8997_LDO16, &max8997_ldo16_data },
+
+	{ MAX8997_LDO18, &max8997_ldo18_data },
+	{ MAX8997_LDO21, &max8997_ldo21_data },
+
+	{ MAX8997_BUCK1, &max8997_buck1_data },
+	{ MAX8997_BUCK2, &max8997_buck2_data },
+	{ MAX8997_BUCK3, &max8997_buck3_data },
+	{ MAX8997_BUCK4, &max8997_buck4_data },
+	{ MAX8997_BUCK5, &max8997_buck5_data },
+	{ MAX8997_BUCK6, &max8997_buck6_data },
+	{ MAX8997_BUCK7, &max8997_buck7_data },
+
+	{ MAX8997_EN32KHZ_AP, &max8997_32khz_ap_data },
+	{ MAX8997_EN32KHZ_CP, &max8997_32khz_cp_data },
+
+	{ MAX8997_ENVICHG, &max8997_vichg_data },
+	{ MAX8997_ESAFEOUT1, &max8997_esafeout1_data },
+	{ MAX8997_ESAFEOUT2, &max8997_esafeout2_data },
+	{ MAX8997_CHARGER_CV, &max8997_charger_cv_data },
+	{ MAX8997_CHARGER, &max8997_charger_data },
+	{ MAX8997_CHARGER_TOPOFF, &max8997_charger_topoff_data },
+};
+
+static struct max8997_platform_data __initdata nuri_max8997_pdata = {
+	.wakeup			= 1,
+
+	.num_regulators		= ARRAY_SIZE(nuri_max8997_regulators),
+	.regulators		= nuri_max8997_regulators,
+
+	.buck125_gpios = { EXYNOS4_GPX0(5), EXYNOS4_GPX0(6), EXYNOS4_GPL0(0) },
+	.buck2_gpiodvs = true,
+
+	.buck1_voltage[0] = 1350000, /* 1.35V */
+	.buck1_voltage[1] = 1300000, /* 1.3V */
+	.buck1_voltage[2] = 1250000, /* 1.25V */
+	.buck1_voltage[3] = 1200000, /* 1.2V */
+	.buck1_voltage[4] = 1150000, /* 1.15V */
+	.buck1_voltage[5] = 1100000, /* 1.1V */
+	.buck1_voltage[6] = 1000000, /* 1.0V */
+	.buck1_voltage[7] = 950000, /* 0.95V */
+
+	.buck2_voltage[0] = 1100000, /* 1.1V */
+	.buck2_voltage[1] = 1000000, /* 1.0V */
+	.buck2_voltage[2] = 950000, /* 0.95V */
+	.buck2_voltage[3] = 900000, /* 0.9V */
+	.buck2_voltage[4] = 1100000, /* 1.1V */
+	.buck2_voltage[5] = 1000000, /* 1.0V */
+	.buck2_voltage[6] = 950000, /* 0.95V */
+	.buck2_voltage[7] = 900000, /* 0.9V */
+
+	.buck5_voltage[0] = 1200000, /* 1.2V */
+	.buck5_voltage[1] = 1200000, /* 1.2V */
+	.buck5_voltage[2] = 1200000, /* 1.2V */
+	.buck5_voltage[3] = 1200000, /* 1.2V */
+	.buck5_voltage[4] = 1200000, /* 1.2V */
+	.buck5_voltage[5] = 1200000, /* 1.2V */
+	.buck5_voltage[6] = 1200000, /* 1.2V */
+	.buck5_voltage[7] = 1200000, /* 1.2V */
+};
+
+/* GPIO I2C 5 (PMIC) */
+enum { I2C5_MAX8997 };
+static struct i2c_board_info i2c5_devs[] __initdata = {
+	[I2C5_MAX8997] = {
+		I2C_BOARD_INFO("max8997", 0xCC >> 1),
+		.platform_data	= &nuri_max8997_pdata,
+	},
+};
+
+static struct max17042_platform_data nuri_battery_platform_data = {
+};
+
+/* GPIO I2C 9 (Fuel Gauge) */
+static struct i2c_gpio_platform_data i2c9_gpio_data = {
+	.sda_pin		= EXYNOS4_GPY4(0),      /* XM0ADDR_8 */
+	.scl_pin		= EXYNOS4_GPY4(1),      /* XM0ADDR_9 */
+};
+static struct platform_device i2c9_gpio = {
+	.name			= "i2c-gpio",
+	.id			= 9,
+	.dev			= {
+		.platform_data	= &i2c9_gpio_data,
+	},
+};
+enum { I2C9_MAX17042};
+static struct i2c_board_info i2c9_devs[] __initdata = {
+	[I2C9_MAX17042] = {
+		I2C_BOARD_INFO("max17042", 0x36),
+		.platform_data = &nuri_battery_platform_data,
+	},
+};
+
+/* MAX8903 Secondary Charger */
+static struct regulator_consumer_supply supplies_max8903[] = {
+	REGULATOR_SUPPLY("vinchg2", "charger-manager.0"),
+};
+
+static struct regulator_init_data max8903_charger_en_data = {
+	.constraints = {
+		.name		= "VOUT_CHARGER",
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		.boot_on	= 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(supplies_max8903),
+	.consumer_supplies = supplies_max8903,
+};
+
+static struct fixed_voltage_config max8903_charger_en = {
+	.supply_name = "VOUT_CHARGER",
+	.microvolts = 5000000, /* Assume 5VDC */
+	.gpio = EXYNOS4_GPY4(5), /* TA_EN negaged */
+	.enable_high = 0, /* Enable = Low */
+	.enabled_at_boot = 1,
+	.init_data = &max8903_charger_en_data,
+};
+
+static struct platform_device max8903_fixed_reg_dev = {
+	.name = "reg-fixed-voltage",
+	.id = FIXED_REG_ID_MAX8903,
+	.dev = { .platform_data	= &max8903_charger_en },
+};
+
+static struct max8903_pdata nuri_max8903 = {
+	/*
+	 * cen: don't control with the driver, let it be
+	 * controlled by regulator above
+	 */
+	.dok = EXYNOS4_GPX1(4), /* TA_nCONNECTED */
+	/* uok, usus: not connected */
+	.chg = EXYNOS4_GPE2(0), /* TA_nCHG */
+	/* flt: vcc_1.8V_pda */
+	.dcm = EXYNOS4_GPL0(1), /* CURR_ADJ */
+
+	.dc_valid = true,
+	.usb_valid = false, /* USB is not wired to MAX8903 */
+};
+
+static struct platform_device nuri_max8903_device = {
+	.name			= "max8903-charger",
+	.dev			= {
+		.platform_data	= &nuri_max8903,
+	},
+};
+
+static void __init nuri_power_init(void)
+{
+	int gpio;
+	int irq_base = IRQ_GPIO_END + 1;
+	int ta_en = 0;
+
+	nuri_max8997_pdata.irq_base = irq_base;
+	irq_base += MAX8997_IRQ_NR;
+
+	gpio = EXYNOS4_GPX0(7);
+	gpio_request(gpio, "AP_PMIC_IRQ");
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+
+	gpio = EXYNOS4_GPX2(3);
+	gpio_request(gpio, "FUEL_ALERT");
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+
+	gpio = nuri_max8903.dok;
+	gpio_request(gpio, "TA_nCONNECTED");
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+	ta_en = gpio_get_value(gpio) ? 0 : 1;
+
+	gpio = nuri_max8903.chg;
+	gpio_request(gpio, "TA_nCHG");
+	gpio_direction_input(gpio);
+
+	gpio = nuri_max8903.dcm;
+	gpio_request(gpio, "CURR_ADJ");
+	gpio_direction_output(gpio, ta_en);
+}
+
+/* USB EHCI */
+static struct s5p_ehci_platdata nuri_ehci_pdata;
+
+static void __init nuri_ehci_init(void)
+{
+	struct s5p_ehci_platdata *pdata = &nuri_ehci_pdata;
+
+	s5p_ehci_set_platdata(pdata);
+}
+
+/* CAMERA */
+static struct regulator_consumer_supply cam_vdda_supply[] = {
+	REGULATOR_SUPPLY("a_sensor", "0-001f"),
+};
+
+static struct regulator_init_data cam_vdda_reg_init_data = {
+	.constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
+	.num_consumer_supplies = ARRAY_SIZE(cam_vdda_supply),
+	.consumer_supplies = cam_vdda_supply,
+};
+
+static struct fixed_voltage_config cam_vdda_fixed_voltage_cfg = {
+	.supply_name	= "CAM_IO_EN",
+	.microvolts	= 2800000,
+	.gpio		= EXYNOS4_GPE2(1), /* CAM_IO_EN */
+	.enable_high	= 1,
+	.init_data	= &cam_vdda_reg_init_data,
+};
+
+static struct platform_device cam_vdda_fixed_rdev = {
+	.name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_A28V,
+	.dev = { .platform_data	= &cam_vdda_fixed_voltage_cfg },
+};
+
+static struct regulator_consumer_supply camera_8m_12v_supply =
+	REGULATOR_SUPPLY("dig_12", "0-001f");
+
+static struct regulator_init_data cam_8m_12v_reg_init_data = {
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &camera_8m_12v_supply,
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS
+	},
+};
+
+static struct fixed_voltage_config cam_8m_12v_fixed_voltage_cfg = {
+	.supply_name	= "8M_1.2V",
+	.microvolts	= 1200000,
+	.gpio		= EXYNOS4_GPE2(5), /* 8M_1.2V_EN */
+	.enable_high	= 1,
+	.init_data	= &cam_8m_12v_reg_init_data,
+};
+
+static struct platform_device cam_8m_12v_fixed_rdev = {
+	.name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_12V,
+	.dev = { .platform_data = &cam_8m_12v_fixed_voltage_cfg },
+};
+
+static struct s5p_platform_mipi_csis mipi_csis_platdata = {
+	.clk_rate	= 166000000UL,
+	.lanes		= 2,
+	.alignment	= 32,
+	.hs_settle	= 12,
+	.phy_enable	= s5p_csis_phy_enable,
+};
+
+#define GPIO_CAM_MEGA_RST	EXYNOS4_GPY3(7) /* ISP_RESET */
+#define GPIO_CAM_8M_ISP_INT	EXYNOS4_GPL2(5)
+
+static struct m5mols_platform_data m5mols_platdata = {
+	.gpio_reset = GPIO_CAM_MEGA_RST,
+};
+
+static struct i2c_board_info m5mols_board_info = {
+	I2C_BOARD_INFO("M5MOLS", 0x1F),
+	.platform_data	= &m5mols_platdata,
+};
+
+static struct s5p_fimc_isp_info nuri_camera_sensors[] = {
+	{
+		.flags		= V4L2_MBUS_PCLK_SAMPLE_FALLING |
+				  V4L2_MBUS_VSYNC_ACTIVE_LOW,
+		.bus_type	= FIMC_MIPI_CSI2,
+		.board_info	= &m5mols_board_info,
+		.clk_frequency	= 24000000UL,
+		.csi_data_align	= 32,
+	},
+};
+
+static struct s5p_platform_fimc fimc_md_platdata = {
+	.isp_info	= nuri_camera_sensors,
+	.num_clients	= ARRAY_SIZE(nuri_camera_sensors),
+};
+
+static struct gpio nuri_camera_gpios[] = {
+	{ GPIO_CAM_8M_ISP_INT,	GPIOF_IN,           "8M_ISP_INT"  },
+	{ GPIO_CAM_MEGA_RST,	GPIOF_OUT_INIT_LOW, "CAM_8M_NRST" },
+};
+
+static void nuri_camera_init(void)
+{
+	s3c_set_platdata(&mipi_csis_platdata, sizeof(mipi_csis_platdata),
+			 &s5p_device_mipi_csis0);
+	s3c_set_platdata(&fimc_md_platdata,  sizeof(fimc_md_platdata),
+			 &s5p_device_fimc_md);
+
+	if (gpio_request_array(nuri_camera_gpios,
+			       ARRAY_SIZE(nuri_camera_gpios))) {
+		pr_err("%s: GPIO request failed\n", __func__);
+		return;
+	}
+
+	m5mols_board_info.irq = s5p_register_gpio_interrupt(GPIO_CAM_8M_ISP_INT);
+	if (!IS_ERR_VALUE(m5mols_board_info.irq))
+		s3c_gpio_cfgpin(GPIO_CAM_8M_ISP_INT, S3C_GPIO_SFN(0xF));
+	else
+		pr_err("%s: Failed to configure 8M_ISP_INT GPIO\n", __func__);
+
+	/* Free GPIOs controlled directly by the sensor drivers. */
+	gpio_free(GPIO_CAM_MEGA_RST);
+
+	if (exynos4_fimc_setup_gpio(S5P_CAMPORT_A)) {
+		pr_err("%s: Camera port A setup failed\n", __func__);
+		return;
+	}
+	/* Increase drive strength of the sensor clock output */
+	s5p_gpio_set_drvstr(EXYNOS4_GPJ1(3), S5P_GPIO_DRVSTR_LV4);
+}
+
+static struct s3c2410_platform_i2c nuri_i2c0_platdata __initdata = {
+	.frequency	= 400000U,
+	.sda_delay	= 200,
+};
+
+static struct platform_device *nuri_devices[] __initdata = {
+	/* Samsung Platform Devices */
+	&s3c_device_i2c5, /* PMIC should initialize first */
+	&s3c_device_i2c0,
+	&emmc_fixed_voltage,
+	&s5p_device_mipi_csis0,
+	&s5p_device_fimc0,
+	&s5p_device_fimc1,
+	&s5p_device_fimc2,
+	&s5p_device_fimc3,
+	&s5p_device_fimd0,
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_wdt,
+	&s3c_device_timer[0],
+	&s5p_device_ehci,
+	&s3c_device_i2c3,
+	&i2c9_gpio,
+	&s3c_device_adc,
+	&s3c_device_rtc,
+	&s5p_device_mfc,
+	&s5p_device_mfc_l,
+	&s5p_device_mfc_r,
+	&exynos4_device_pd[PD_MFC],
+	&exynos4_device_pd[PD_LCD0],
+	&exynos4_device_pd[PD_CAM],
+	&s5p_device_fimc_md,
+
+	/* NURI Devices */
+	&nuri_gpio_keys,
+	&nuri_lcd_device,
+	&nuri_backlight_device,
+	&max8903_fixed_reg_dev,
+	&nuri_max8903_device,
+	&cam_vdda_fixed_rdev,
+	&cam_8m_12v_fixed_rdev,
+};
+
+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_reserve(void)
+{
+	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
+static void __init nuri_machine_init(void)
+{
+	nuri_sdhci_init();
+	nuri_tsp_init();
+	nuri_power_init();
+
+	s3c_i2c0_set_platdata(&nuri_i2c0_platdata);
+	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
+	s3c_i2c3_set_platdata(&i2c3_data);
+	i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
+	s3c_i2c5_set_platdata(NULL);
+	i2c5_devs[I2C5_MAX8997].irq = gpio_to_irq(EXYNOS4_GPX0(7));
+	i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
+	i2c9_devs[I2C9_MAX17042].irq = gpio_to_irq(EXYNOS4_GPX2(3));
+	i2c_register_board_info(9, i2c9_devs, ARRAY_SIZE(i2c9_devs));
+
+	s5p_fimd0_set_platdata(&nuri_fb_pdata);
+
+	nuri_camera_init();
+
+	nuri_ehci_init();
+	clk_xusbxti.rate = 24000000;
+
+	/* Last */
+	platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
+	s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
+	s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
+
+	s5p_device_fimc0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_fimc1.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_fimc2.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_fimc3.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_mipi_csis0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+}
+
+MACHINE_START(NURI, "NURI")
+	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= nuri_map_io,
+	.init_machine	= nuri_machine_init,
+	.timer		= &exynos4_timer,
+	.reserve        = &nuri_reserve,
+MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/mach-origen.c linux-libre-3.2-gnu/arch/arm/mach-exynos/mach-origen.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/mach-origen.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/mach-origen.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,700 @@
+/* linux/arch/arm/mach-exynos4/mach-origen.c
+ *
+ * Copyright (c) 2011 Insignal Co., Ltd.
+ *		http://www.insignal.co.kr/
+ *
+ * This program is free software; you can 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/io.h>
+#include <linux/input.h>
+#include <linux/pwm_backlight.h>
+#include <linux/gpio_keys.h>
+#include <linux/i2c.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/max8997.h>
+#include <linux/lcd.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <video/platform_lcd.h>
+
+#include <plat/regs-serial.h>
+#include <plat/regs-fb-v4.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/sdhci.h>
+#include <plat/iic.h>
+#include <plat/ehci.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <plat/backlight.h>
+#include <plat/pd.h>
+#include <plat/fb.h>
+#include <plat/mfc.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define ORIGEN_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define ORIGEN_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define ORIGEN_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg origen_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= ORIGEN_UCON_DEFAULT,
+		.ulcon		= ORIGEN_ULCON_DEFAULT,
+		.ufcon		= ORIGEN_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= ORIGEN_UCON_DEFAULT,
+		.ulcon		= ORIGEN_ULCON_DEFAULT,
+		.ufcon		= ORIGEN_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= ORIGEN_UCON_DEFAULT,
+		.ulcon		= ORIGEN_ULCON_DEFAULT,
+		.ufcon		= ORIGEN_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= ORIGEN_UCON_DEFAULT,
+		.ulcon		= ORIGEN_ULCON_DEFAULT,
+		.ufcon		= ORIGEN_UFCON_DEFAULT,
+	},
+};
+
+static struct regulator_consumer_supply __initdata ldo3_consumer[] = {
+	REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
+	REGULATOR_SUPPLY("vdd", "exynos4-hdmi"), /* HDMI */
+	REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"), /* HDMI */
+};
+static struct regulator_consumer_supply __initdata ldo6_consumer[] = {
+	REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
+};
+static struct regulator_consumer_supply __initdata ldo7_consumer[] = {
+	REGULATOR_SUPPLY("avdd", "alc5625"), /* Realtek ALC5625 */
+};
+static struct regulator_consumer_supply __initdata ldo8_consumer[] = {
+	REGULATOR_SUPPLY("vdd", "s5p-adc"), /* ADC */
+	REGULATOR_SUPPLY("vdd_osc", "exynos4-hdmi"), /* HDMI */
+};
+static struct regulator_consumer_supply __initdata ldo9_consumer[] = {
+	REGULATOR_SUPPLY("dvdd", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
+};
+static struct regulator_consumer_supply __initdata ldo11_consumer[] = {
+	REGULATOR_SUPPLY("dvdd", "alc5625"), /* Realtek ALC5625 */
+};
+static struct regulator_consumer_supply __initdata ldo14_consumer[] = {
+	REGULATOR_SUPPLY("avdd18", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
+};
+static struct regulator_consumer_supply __initdata ldo17_consumer[] = {
+	REGULATOR_SUPPLY("vdd33", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
+};
+static struct regulator_consumer_supply __initdata buck1_consumer[] = {
+	REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata buck2_consumer[] = {
+	REGULATOR_SUPPLY("vdd_int", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata buck3_consumer[] = {
+	REGULATOR_SUPPLY("vdd_g3d", "mali_drm"), /* G3D */
+};
+static struct regulator_consumer_supply __initdata buck7_consumer[] = {
+	REGULATOR_SUPPLY("vcc", "platform-lcd"), /* LCD */
+};
+
+static struct regulator_init_data __initdata max8997_ldo1_data = {
+	.constraints	= {
+		.name		= "VDD_ABB_3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo2_data	= {
+	.constraints	= {
+		.name		= "VDD_ALIVE_1.1V",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo3_data = {
+	.constraints	= {
+		.name		= "VMIPI_1.1V",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldo3_consumer),
+	.consumer_supplies	= ldo3_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo4_data = {
+	.constraints	= {
+		.name		= "VDD_RTC_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo6_data = {
+	.constraints	= {
+		.name		= "VMIPI_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldo6_consumer),
+	.consumer_supplies	= ldo6_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo7_data = {
+	.constraints	= {
+		.name		= "VDD_AUD_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldo7_consumer),
+	.consumer_supplies	= ldo7_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo8_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,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldo8_consumer),
+	.consumer_supplies	= ldo8_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo9_data = {
+	.constraints	= {
+		.name		= "DVDD_SWB_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldo9_consumer),
+	.consumer_supplies	= ldo9_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo10_data = {
+	.constraints	= {
+		.name		= "VDD_PLL_1.1V",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo11_data = {
+	.constraints	= {
+		.name		= "VDD_AUD_3V",
+		.min_uV		= 3000000,
+		.max_uV		= 3000000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldo11_consumer),
+	.consumer_supplies	= ldo11_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo14_data = {
+	.constraints	= {
+		.name		= "AVDD18_SWB_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldo14_consumer),
+	.consumer_supplies	= ldo14_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo17_data = {
+	.constraints	= {
+		.name		= "VDD_SWB_3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(ldo17_consumer),
+	.consumer_supplies	= ldo17_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo21_data = {
+	.constraints	= {
+		.name		= "VDD_MIF_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_buck1_data = {
+	.constraints	= {
+		.name		= "VDD_ARM_1.2V",
+		.min_uV		= 950000,
+		.max_uV		= 1350000,
+		.always_on	= 1,
+		.boot_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(buck1_consumer),
+	.consumer_supplies	= buck1_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_buck2_data = {
+	.constraints	= {
+		.name		= "VDD_INT_1.1V",
+		.min_uV		= 900000,
+		.max_uV		= 1100000,
+		.always_on	= 1,
+		.boot_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(buck2_consumer),
+	.consumer_supplies	= buck2_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_buck3_data = {
+	.constraints	= {
+		.name		= "VDD_G3D_1.1V",
+		.min_uV		= 900000,
+		.max_uV		= 1100000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
+					REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(buck3_consumer),
+	.consumer_supplies	= buck3_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_buck5_data = {
+	.constraints	= {
+		.name		= "VDDQ_M1M2_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_buck7_data = {
+	.constraints	= {
+		.name		= "VDD_LCD_3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.boot_on	= 1,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(buck7_consumer),
+	.consumer_supplies	= buck7_consumer,
+};
+
+static struct max8997_regulator_data __initdata origen_max8997_regulators[] = {
+	{ MAX8997_LDO1,		&max8997_ldo1_data },
+	{ MAX8997_LDO2,		&max8997_ldo2_data },
+	{ MAX8997_LDO3,		&max8997_ldo3_data },
+	{ MAX8997_LDO4,		&max8997_ldo4_data },
+	{ MAX8997_LDO6,		&max8997_ldo6_data },
+	{ MAX8997_LDO7,		&max8997_ldo7_data },
+	{ MAX8997_LDO8,		&max8997_ldo8_data },
+	{ MAX8997_LDO9,		&max8997_ldo9_data },
+	{ MAX8997_LDO10,	&max8997_ldo10_data },
+	{ MAX8997_LDO11,	&max8997_ldo11_data },
+	{ MAX8997_LDO14,	&max8997_ldo14_data },
+	{ MAX8997_LDO17,	&max8997_ldo17_data },
+	{ MAX8997_LDO21,	&max8997_ldo21_data },
+	{ MAX8997_BUCK1,	&max8997_buck1_data },
+	{ MAX8997_BUCK2,	&max8997_buck2_data },
+	{ MAX8997_BUCK3,	&max8997_buck3_data },
+	{ MAX8997_BUCK5,	&max8997_buck5_data },
+	{ MAX8997_BUCK7,	&max8997_buck7_data },
+};
+
+struct max8997_platform_data __initdata origen_max8997_pdata = {
+	.num_regulators = ARRAY_SIZE(origen_max8997_regulators),
+	.regulators	= origen_max8997_regulators,
+
+	.wakeup	= true,
+	.buck1_gpiodvs	= false,
+	.buck2_gpiodvs	= false,
+	.buck5_gpiodvs	= false,
+	.irq_base	= IRQ_GPIO_END + 1,
+
+	.ignore_gpiodvs_side_effect = true,
+	.buck125_default_idx = 0x0,
+
+	.buck125_gpios[0]	= EXYNOS4_GPX0(0),
+	.buck125_gpios[1]	= EXYNOS4_GPX0(1),
+	.buck125_gpios[2]	= EXYNOS4_GPX0(2),
+
+	.buck1_voltage[0]	= 1350000,
+	.buck1_voltage[1]	= 1300000,
+	.buck1_voltage[2]	= 1250000,
+	.buck1_voltage[3]	= 1200000,
+	.buck1_voltage[4]	= 1150000,
+	.buck1_voltage[5]	= 1100000,
+	.buck1_voltage[6]	= 1000000,
+	.buck1_voltage[7]	= 950000,
+
+	.buck2_voltage[0]	= 1100000,
+	.buck2_voltage[1]	= 1100000,
+	.buck2_voltage[2]	= 1100000,
+	.buck2_voltage[3]	= 1100000,
+	.buck2_voltage[4]	= 1000000,
+	.buck2_voltage[5]	= 1000000,
+	.buck2_voltage[6]	= 1000000,
+	.buck2_voltage[7]	= 1000000,
+
+	.buck5_voltage[0]	= 1200000,
+	.buck5_voltage[1]	= 1200000,
+	.buck5_voltage[2]	= 1200000,
+	.buck5_voltage[3]	= 1200000,
+	.buck5_voltage[4]	= 1200000,
+	.buck5_voltage[5]	= 1200000,
+	.buck5_voltage[6]	= 1200000,
+	.buck5_voltage[7]	= 1200000,
+};
+
+/* I2C0 */
+static struct i2c_board_info i2c0_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("max8997", (0xCC >> 1)),
+		.platform_data	= &origen_max8997_pdata,
+		.irq		= IRQ_EINT(4),
+	},
+};
+
+static struct s3c_sdhci_platdata origen_hsmmc0_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_INTERNAL,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct s3c_sdhci_platdata origen_hsmmc2_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_INTERNAL,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+/* USB EHCI */
+static struct s5p_ehci_platdata origen_ehci_pdata;
+
+static void __init origen_ehci_init(void)
+{
+	struct s5p_ehci_platdata *pdata = &origen_ehci_pdata;
+
+	s5p_ehci_set_platdata(pdata);
+}
+
+static struct gpio_keys_button origen_gpio_keys_table[] = {
+	{
+		.code			= KEY_MENU,
+		.gpio			= EXYNOS4_GPX1(5),
+		.desc			= "gpio-keys: KEY_MENU",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.wakeup			= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_HOME,
+		.gpio			= EXYNOS4_GPX1(6),
+		.desc			= "gpio-keys: KEY_HOME",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.wakeup			= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_BACK,
+		.gpio			= EXYNOS4_GPX1(7),
+		.desc			= "gpio-keys: KEY_BACK",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.wakeup			= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_UP,
+		.gpio			= EXYNOS4_GPX2(0),
+		.desc			= "gpio-keys: KEY_UP",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.wakeup			= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_DOWN,
+		.gpio			= EXYNOS4_GPX2(1),
+		.desc			= "gpio-keys: KEY_DOWN",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.wakeup			= 1,
+		.debounce_interval	= 1,
+	},
+};
+
+static struct gpio_keys_platform_data origen_gpio_keys_data = {
+	.buttons	= origen_gpio_keys_table,
+	.nbuttons	= ARRAY_SIZE(origen_gpio_keys_table),
+};
+
+static struct platform_device origen_device_gpiokeys = {
+	.name		= "gpio-keys",
+	.dev		= {
+		.platform_data	= &origen_gpio_keys_data,
+	},
+};
+
+static void lcd_hv070wsa_set_power(struct plat_lcd_data *pd, unsigned int power)
+{
+	int ret;
+
+	if (power)
+		ret = gpio_request_one(EXYNOS4_GPE3(4),
+					GPIOF_OUT_INIT_HIGH, "GPE3_4");
+	else
+		ret = gpio_request_one(EXYNOS4_GPE3(4),
+					GPIOF_OUT_INIT_LOW, "GPE3_4");
+
+	gpio_free(EXYNOS4_GPE3(4));
+
+	if (ret)
+		pr_err("failed to request gpio for LCD power: %d\n", ret);
+}
+
+static struct plat_lcd_data origen_lcd_hv070wsa_data = {
+	.set_power = lcd_hv070wsa_set_power,
+};
+
+static struct platform_device origen_lcd_hv070wsa = {
+	.name			= "platform-lcd",
+	.dev.parent		= &s5p_device_fimd0.dev,
+	.dev.platform_data	= &origen_lcd_hv070wsa_data,
+};
+
+static struct s3c_fb_pd_win origen_fb_win0 = {
+	.win_mode = {
+		.left_margin	= 64,
+		.right_margin	= 16,
+		.upper_margin	= 64,
+		.lower_margin	= 16,
+		.hsync_len	= 48,
+		.vsync_len	= 3,
+		.xres		= 1024,
+		.yres		= 600,
+	},
+	.max_bpp		= 32,
+	.default_bpp		= 24,
+};
+
+static struct s3c_fb_platdata origen_lcd_pdata __initdata = {
+	.win[0]		= &origen_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+	.setup_gpio	= exynos4_fimd0_gpio_setup_24bpp,
+};
+
+static struct platform_device *origen_devices[] __initdata = {
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc0,
+	&s3c_device_i2c0,
+	&s3c_device_rtc,
+	&s3c_device_wdt,
+	&s5p_device_ehci,
+	&s5p_device_fimc0,
+	&s5p_device_fimc1,
+	&s5p_device_fimc2,
+	&s5p_device_fimc3,
+	&s5p_device_fimd0,
+	&s5p_device_hdmi,
+	&s5p_device_i2c_hdmiphy,
+	&s5p_device_mfc,
+	&s5p_device_mfc_l,
+	&s5p_device_mfc_r,
+	&s5p_device_mixer,
+	&exynos4_device_pd[PD_LCD0],
+	&exynos4_device_pd[PD_TV],
+	&exynos4_device_pd[PD_G3D],
+	&exynos4_device_pd[PD_LCD1],
+	&exynos4_device_pd[PD_CAM],
+	&exynos4_device_pd[PD_GPS],
+	&exynos4_device_pd[PD_MFC],
+	&origen_device_gpiokeys,
+	&origen_lcd_hv070wsa,
+};
+
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info origen_bl_gpio_info = {
+	.no		= EXYNOS4_GPD0(0),
+	.func		= S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data origen_bl_data = {
+	.pwm_id		= 0,
+	.pwm_period_ns	= 1000,
+};
+
+static void s5p_tv_setup(void)
+{
+	/* Direct HPD to HDMI chip */
+	gpio_request_one(EXYNOS4_GPX3(7), GPIOF_IN, "hpd-plug");
+	s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
+	s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
+}
+
+static void __init origen_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
+}
+
+static void __init origen_power_init(void)
+{
+	gpio_request(EXYNOS4_GPX0(4), "PMIC_IRQ");
+	s3c_gpio_cfgpin(EXYNOS4_GPX0(4), S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(EXYNOS4_GPX0(4), S3C_GPIO_PULL_NONE);
+}
+
+static void __init origen_reserve(void)
+{
+	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
+static void __init origen_machine_init(void)
+{
+	origen_power_init();
+
+	s3c_i2c0_set_platdata(NULL);
+	i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
+
+	/*
+	 * Since sdhci instance 2 can contain a bootable media,
+	 * sdhci instance 0 is registered after instance 2.
+	 */
+	s3c_sdhci2_set_platdata(&origen_hsmmc2_pdata);
+	s3c_sdhci0_set_platdata(&origen_hsmmc0_pdata);
+
+	origen_ehci_init();
+	clk_xusbxti.rate = 24000000;
+
+	s5p_tv_setup();
+	s5p_i2c_hdmiphy_set_platdata(NULL);
+
+	s5p_fimd0_set_platdata(&origen_lcd_pdata);
+
+	platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices));
+
+	s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
+
+	s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
+	s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
+
+	s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
+
+	samsung_bl_set(&origen_bl_gpio_info, &origen_bl_data);
+}
+
+MACHINE_START(ORIGEN, "ORIGEN")
+	/* Maintainer: JeongHyeon Kim <jhkim@insignal.co.kr> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= origen_map_io,
+	.init_machine	= origen_machine_init,
+	.timer		= &exynos4_timer,
+	.reserve	= &origen_reserve,
+MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/mach-smdk4x12.c linux-libre-3.2-gnu/arch/arm/mach-exynos/mach-smdk4x12.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/mach-smdk4x12.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/mach-smdk4x12.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,302 @@
+/*
+ * linux/arch/arm/mach-exynos4/mach-smdk4x12.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/i2c.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/mfd/max8997.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/pwm_backlight.h>
+#include <linux/regulator/machine.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/backlight.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/exynos4.h>
+#include <plat/gpio-cfg.h>
+#include <plat/iic.h>
+#include <plat/keypad.h>
+#include <plat/regs-serial.h>
+#include <plat/sdhci.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define SMDK4X12_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define SMDK4X12_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define SMDK4X12_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg smdk4x12_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= SMDK4X12_UCON_DEFAULT,
+		.ulcon		= SMDK4X12_ULCON_DEFAULT,
+		.ufcon		= SMDK4X12_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= SMDK4X12_UCON_DEFAULT,
+		.ulcon		= SMDK4X12_ULCON_DEFAULT,
+		.ufcon		= SMDK4X12_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= SMDK4X12_UCON_DEFAULT,
+		.ulcon		= SMDK4X12_ULCON_DEFAULT,
+		.ufcon		= SMDK4X12_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= SMDK4X12_UCON_DEFAULT,
+		.ulcon		= SMDK4X12_ULCON_DEFAULT,
+		.ufcon		= SMDK4X12_UFCON_DEFAULT,
+	},
+};
+
+static struct s3c_sdhci_platdata smdk4x12_hsmmc2_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_INTERNAL,
+	.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 smdk4x12_hsmmc3_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_INTERNAL,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct regulator_consumer_supply max8997_buck1 =
+	REGULATOR_SUPPLY("vdd_arm", NULL);
+
+static struct regulator_consumer_supply max8997_buck2 =
+	REGULATOR_SUPPLY("vdd_int", NULL);
+
+static struct regulator_consumer_supply max8997_buck3 =
+	REGULATOR_SUPPLY("vdd_g3d", NULL);
+
+static struct regulator_init_data max8997_buck1_data = {
+	.constraints	= {
+		.name		= "VDD_ARM_SMDK4X12",
+		.min_uV		= 925000,
+		.max_uV		= 1350000,
+		.always_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &max8997_buck1,
+};
+
+static struct regulator_init_data max8997_buck2_data = {
+	.constraints	= {
+		.name		= "VDD_INT_SMDK4X12",
+		.min_uV		= 950000,
+		.max_uV		= 1150000,
+		.always_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &max8997_buck2,
+};
+
+static struct regulator_init_data max8997_buck3_data = {
+	.constraints	= {
+		.name		= "VDD_G3D_SMDK4X12",
+		.min_uV		= 950000,
+		.max_uV		= 1150000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &max8997_buck3,
+};
+
+static struct max8997_regulator_data smdk4x12_max8997_regulators[] = {
+	{ MAX8997_BUCK1, &max8997_buck1_data },
+	{ MAX8997_BUCK2, &max8997_buck2_data },
+	{ MAX8997_BUCK3, &max8997_buck3_data },
+};
+
+static struct max8997_platform_data smdk4x12_max8997_pdata = {
+	.num_regulators	= ARRAY_SIZE(smdk4x12_max8997_regulators),
+	.regulators	= smdk4x12_max8997_regulators,
+
+	.buck1_voltage[0] = 1100000,	/* 1.1V */
+	.buck1_voltage[1] = 1100000,	/* 1.1V */
+	.buck1_voltage[2] = 1100000,	/* 1.1V */
+	.buck1_voltage[3] = 1100000,	/* 1.1V */
+	.buck1_voltage[4] = 1100000,	/* 1.1V */
+	.buck1_voltage[5] = 1100000,	/* 1.1V */
+	.buck1_voltage[6] = 1000000,	/* 1.0V */
+	.buck1_voltage[7] = 950000,	/* 0.95V */
+
+	.buck2_voltage[0] = 1100000,	/* 1.1V */
+	.buck2_voltage[1] = 1000000,	/* 1.0V */
+	.buck2_voltage[2] = 950000,	/* 0.95V */
+	.buck2_voltage[3] = 900000,	/* 0.9V */
+	.buck2_voltage[4] = 1100000,	/* 1.1V */
+	.buck2_voltage[5] = 1000000,	/* 1.0V */
+	.buck2_voltage[6] = 950000,	/* 0.95V */
+	.buck2_voltage[7] = 900000,	/* 0.9V */
+
+	.buck5_voltage[0] = 1100000,	/* 1.1V */
+	.buck5_voltage[1] = 1100000,	/* 1.1V */
+	.buck5_voltage[2] = 1100000,	/* 1.1V */
+	.buck5_voltage[3] = 1100000,	/* 1.1V */
+	.buck5_voltage[4] = 1100000,	/* 1.1V */
+	.buck5_voltage[5] = 1100000,	/* 1.1V */
+	.buck5_voltage[6] = 1100000,	/* 1.1V */
+	.buck5_voltage[7] = 1100000,	/* 1.1V */
+};
+
+static struct i2c_board_info smdk4x12_i2c_devs0[] __initdata = {
+	{
+		I2C_BOARD_INFO("max8997", 0x66),
+		.platform_data	= &smdk4x12_max8997_pdata,
+	}
+};
+
+static struct i2c_board_info smdk4x12_i2c_devs1[] __initdata = {
+	{ I2C_BOARD_INFO("wm8994", 0x1a), }
+};
+
+static struct i2c_board_info smdk4x12_i2c_devs3[] __initdata = {
+	/* nothing here yet */
+};
+
+static struct i2c_board_info smdk4x12_i2c_devs7[] __initdata = {
+	/* nothing here yet */
+};
+
+static struct samsung_bl_gpio_info smdk4x12_bl_gpio_info = {
+	.no = EXYNOS4_GPD0(1),
+	.func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdk4x12_bl_data = {
+	.pwm_id = 1,
+	.pwm_period_ns  = 1000,
+};
+
+static uint32_t smdk4x12_keymap[] __initdata = {
+	/* KEY(row, col, keycode) */
+	KEY(1, 0, KEY_D), KEY(1, 1, KEY_A), KEY(1, 2, KEY_B),
+	KEY(1, 3, KEY_E), KEY(1, 4, KEY_C)
+};
+
+static struct matrix_keymap_data smdk4x12_keymap_data __initdata = {
+	.keymap		= smdk4x12_keymap,
+	.keymap_size	= ARRAY_SIZE(smdk4x12_keymap),
+};
+
+static struct samsung_keypad_platdata smdk4x12_keypad_data __initdata = {
+	.keymap_data	= &smdk4x12_keymap_data,
+	.rows		= 2,
+	.cols		= 5,
+};
+
+static struct platform_device *smdk4x12_devices[] __initdata = {
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_i2c0,
+	&s3c_device_i2c1,
+	&s3c_device_i2c3,
+	&s3c_device_i2c7,
+	&s3c_device_rtc,
+	&s3c_device_wdt,
+	&samsung_device_keypad,
+};
+
+static void __init smdk4x12_map_io(void)
+{
+	clk_xusbxti.rate = 24000000;
+
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(clk_xusbxti.rate);
+	s3c24xx_init_uarts(smdk4x12_uartcfgs, ARRAY_SIZE(smdk4x12_uartcfgs));
+}
+
+static void __init smdk4x12_machine_init(void)
+{
+	s3c_i2c0_set_platdata(NULL);
+	i2c_register_board_info(0, smdk4x12_i2c_devs0,
+				ARRAY_SIZE(smdk4x12_i2c_devs0));
+
+	s3c_i2c1_set_platdata(NULL);
+	i2c_register_board_info(1, smdk4x12_i2c_devs1,
+				ARRAY_SIZE(smdk4x12_i2c_devs1));
+
+	s3c_i2c3_set_platdata(NULL);
+	i2c_register_board_info(3, smdk4x12_i2c_devs3,
+				ARRAY_SIZE(smdk4x12_i2c_devs3));
+
+	s3c_i2c7_set_platdata(NULL);
+	i2c_register_board_info(7, smdk4x12_i2c_devs7,
+				ARRAY_SIZE(smdk4x12_i2c_devs7));
+
+	samsung_bl_set(&smdk4x12_bl_gpio_info, &smdk4x12_bl_data);
+
+	samsung_keypad_set_platdata(&smdk4x12_keypad_data);
+
+	s3c_sdhci2_set_platdata(&smdk4x12_hsmmc2_pdata);
+	s3c_sdhci3_set_platdata(&smdk4x12_hsmmc3_pdata);
+
+	platform_add_devices(smdk4x12_devices, ARRAY_SIZE(smdk4x12_devices));
+}
+
+MACHINE_START(SMDK4212, "SMDK4212")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= smdk4x12_map_io,
+	.init_machine	= smdk4x12_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
+
+MACHINE_START(SMDK4412, "SMDK4412")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= smdk4x12_map_io,
+	.init_machine	= smdk4x12_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/mach-smdkv310.c linux-libre-3.2-gnu/arch/arm/mach-exynos/mach-smdkv310.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/mach-smdkv310.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/mach-smdkv310.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,390 @@
+/* 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/delay.h>
+#include <linux/gpio.h>
+#include <linux/lcd.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 <linux/pwm_backlight.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <video/platform_lcd.h>
+#include <plat/regs-serial.h>
+#include <plat/regs-srom.h>
+#include <plat/regs-fb-v4.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/fb.h>
+#include <plat/keypad.h>
+#include <plat/sdhci.h>
+#include <plat/iic.h>
+#include <plat/pd.h>
+#include <plat/gpio-cfg.h>
+#include <plat/backlight.h>
+#include <plat/mfc.h>
+#include <plat/ehci.h>
+#include <plat/clock.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_INTERNAL,
+	.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_INTERNAL,
+	.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 void lcd_lte480wv_set_power(struct plat_lcd_data *pd,
+				   unsigned int power)
+{
+	if (power) {
+#if !defined(CONFIG_BACKLIGHT_PWM)
+		gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_HIGH, "GPD0");
+		gpio_free(EXYNOS4_GPD0(1));
+#endif
+		/* fire nRESET on power up */
+		gpio_request(EXYNOS4_GPX0(6), "GPX0");
+
+		gpio_direction_output(EXYNOS4_GPX0(6), 1);
+		mdelay(100);
+
+		gpio_set_value(EXYNOS4_GPX0(6), 0);
+		mdelay(10);
+
+		gpio_set_value(EXYNOS4_GPX0(6), 1);
+		mdelay(10);
+
+		gpio_free(EXYNOS4_GPX0(6));
+	} else {
+#if !defined(CONFIG_BACKLIGHT_PWM)
+		gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_LOW, "GPD0");
+		gpio_free(EXYNOS4_GPD0(1));
+#endif
+	}
+}
+
+static struct plat_lcd_data smdkv310_lcd_lte480wv_data = {
+	.set_power		= lcd_lte480wv_set_power,
+};
+
+static struct platform_device smdkv310_lcd_lte480wv = {
+	.name			= "platform-lcd",
+	.dev.parent		= &s5p_device_fimd0.dev,
+	.dev.platform_data	= &smdkv310_lcd_lte480wv_data,
+};
+
+static struct s3c_fb_pd_win smdkv310_fb_win0 = {
+	.win_mode = {
+		.left_margin	= 13,
+		.right_margin	= 8,
+		.upper_margin	= 7,
+		.lower_margin	= 5,
+		.hsync_len	= 3,
+		.vsync_len	= 1,
+		.xres		= 800,
+		.yres		= 480,
+	},
+	.max_bpp		= 32,
+	.default_bpp		= 24,
+};
+
+static struct s3c_fb_platdata smdkv310_lcd0_pdata __initdata = {
+	.win[0]		= &smdkv310_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+	.setup_gpio	= exynos4_fimd0_gpio_setup_24bpp,
+};
+
+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),},
+};
+
+/* USB EHCI */
+static struct s5p_ehci_platdata smdkv310_ehci_pdata;
+
+static void __init smdkv310_ehci_init(void)
+{
+	struct s5p_ehci_platdata *pdata = &smdkv310_ehci_pdata;
+
+	s5p_ehci_set_platdata(pdata);
+}
+
+static struct platform_device *smdkv310_devices[] __initdata = {
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc1,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_i2c1,
+	&s5p_device_i2c_hdmiphy,
+	&s3c_device_rtc,
+	&s3c_device_wdt,
+	&s5p_device_ehci,
+	&s5p_device_fimc0,
+	&s5p_device_fimc1,
+	&s5p_device_fimc2,
+	&s5p_device_fimc3,
+	&exynos4_device_ac97,
+	&exynos4_device_i2s0,
+	&samsung_device_keypad,
+	&s5p_device_mfc,
+	&s5p_device_mfc_l,
+	&s5p_device_mfc_r,
+	&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_spdif,
+	&exynos4_device_sysmmu,
+	&samsung_asoc_dma,
+	&samsung_asoc_idma,
+	&s5p_device_fimd0,
+	&smdkv310_lcd_lte480wv,
+	&smdkv310_smsc911x,
+	&exynos4_device_ahci,
+	&s5p_device_hdmi,
+	&s5p_device_mixer,
+};
+
+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);
+}
+
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info smdkv310_bl_gpio_info = {
+	.no = EXYNOS4_GPD0(1),
+	.func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdkv310_bl_data = {
+	.pwm_id = 1,
+	.pwm_period_ns  = 1000,
+};
+
+static void s5p_tv_setup(void)
+{
+	/* direct HPD to HDMI chip */
+	WARN_ON(gpio_request_one(EXYNOS4_GPX3(7), GPIOF_IN, "hpd-plug"));
+	s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
+	s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
+
+	/* setup dependencies between TV devices */
+	s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
+	s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
+}
+
+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_reserve(void)
+{
+	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
+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);
+
+	s5p_tv_setup();
+	s5p_i2c_hdmiphy_set_platdata(NULL);
+
+	samsung_keypad_set_platdata(&smdkv310_keypad_data);
+
+	samsung_bl_set(&smdkv310_bl_gpio_info, &smdkv310_bl_data);
+	s5p_fimd0_set_platdata(&smdkv310_lcd0_pdata);
+
+	smdkv310_ehci_init();
+	clk_xusbxti.rate = 24000000;
+
+	platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
+	s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
+}
+
+MACHINE_START(SMDKV310, "SMDKV310")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= smdkv310_map_io,
+	.init_machine	= smdkv310_machine_init,
+	.timer		= &exynos4_timer,
+	.reserve	= &smdkv310_reserve,
+MACHINE_END
+
+MACHINE_START(SMDKC210, "SMDKC210")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	.atag_offset	= 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-3.1-gnu/arch/arm/mach-exynos/mach-universal_c210.c linux-libre-3.2-gnu/arch/arm/mach-exynos/mach-universal_c210.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/mach-universal_c210.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/mach-universal_c210.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1064 @@
+/* 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/fb.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 <linux/i2c-gpio.h>
+#include <linux/i2c/mcs.h>
+#include <linux/i2c/atmel_mxt_ts.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/gpio-cfg.h>
+#include <plat/fb.h>
+#include <plat/mfc.h>
+#include <plat/sdhci.h>
+#include <plat/pd.h>
+#include <plat/regs-fb-v4.h>
+#include <plat/fimc-core.h>
+#include <plat/camport.h>
+#include <plat/mipi_csis.h>
+
+#include <mach/map.h>
+
+#include <media/v4l2-mediabus.h>
+#include <media/s5p_fimc.h>
+#include <media/m5mols.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("vdd_arm", 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("vdd_int", NULL);
+
+static struct regulator_consumer_supply lp3974_buck2_consumer =
+	REGULATOR_SUPPLY("vddg3d", NULL);
+
+static struct regulator_consumer_supply lp3974_buck3_consumer =
+	REGULATOR_SUPPLY("vdet", "s5p-sdo");
+
+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,
+		},
+	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &lp3974_buck3_consumer,
+};
+
+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_consumer_supply lp3974_ldo3_consumer[] = {
+	REGULATOR_SUPPLY("vdd", "exynos4-hdmi"),
+	REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"),
+	REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"),
+};
+
+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,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(lp3974_ldo3_consumer),
+	.consumer_supplies = lp3974_ldo3_consumer,
+};
+
+static struct regulator_consumer_supply lp3974_ldo4_consumer[] = {
+	REGULATOR_SUPPLY("vdd_osc", "exynos4-hdmi"),
+};
+
+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,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(lp3974_ldo4_consumer),
+	.consumer_supplies = lp3974_ldo4_consumer,
+};
+
+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_consumer_supply lp3974_ldo7_consumer[] = {
+	REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"),
+};
+
+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,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(lp3974_ldo7_consumer),
+	.consumer_supplies	= lp3974_ldo7_consumer,
+};
+
+static struct regulator_consumer_supply lp3974_ldo8_consumer[] = {
+	REGULATOR_SUPPLY("vdd33a_dac", "s5p-sdo"),
+};
+
+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,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(lp3974_ldo8_consumer),
+	.consumer_supplies = lp3974_ldo8_consumer,
+};
+
+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_consumer_supply lp3974_ldo11_consumer =
+	REGULATOR_SUPPLY("dig_28", "0-001f");
+
+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,
+		},
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &lp3974_ldo11_consumer,
+};
+
+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_consumer_supply lp3974_ldo14_consumer =
+	REGULATOR_SUPPLY("dig_18", "0-001f");
+
+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,
+		},
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &lp3974_ldo14_consumer,
+};
+
+
+static struct regulator_consumer_supply lp3974_ldo15_consumer =
+	REGULATOR_SUPPLY("dig_12", "0-001f");
+
+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,
+		},
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &lp3974_ldo15_consumer,
+};
+
+static struct regulator_consumer_supply lp3974_ldo16_consumer[] = {
+	REGULATOR_SUPPLY("a_sensor", "0-001f"),
+};
+
+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,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(lp3974_ldo16_consumer),
+	.consumer_supplies	= lp3974_ldo16_consumer,
+};
+
+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,
+};
+
+
+enum fixed_regulator_id {
+	FIXED_REG_ID_MMC0,
+	FIXED_REG_ID_HDMI_5V,
+	FIXED_REG_ID_CAM_S_IF,
+	FIXED_REG_ID_CAM_I_CORE,
+	FIXED_REG_ID_CAM_VT_DIO,
+};
+
+static struct regulator_consumer_supply hdmi_fixed_consumer =
+	REGULATOR_SUPPLY("hdmi-en", "exynos4-hdmi");
+
+static struct regulator_init_data hdmi_fixed_voltage_init_data = {
+	.constraints		= {
+		.name		= "HDMI_5V",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &hdmi_fixed_consumer,
+};
+
+static struct fixed_voltage_config hdmi_fixed_voltage_config = {
+	.supply_name		= "HDMI_EN1",
+	.microvolts		= 5000000,
+	.gpio			= EXYNOS4_GPE0(1),
+	.enable_high		= true,
+	.init_data		= &hdmi_fixed_voltage_init_data,
+};
+
+static struct platform_device hdmi_fixed_voltage = {
+	.name			= "reg-fixed-voltage",
+	.id			= FIXED_REG_ID_HDMI_5V,
+	.dev			= {
+		.platform_data	= &hdmi_fixed_voltage_config,
+	},
+};
+
+/* 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,
+	},
+};
+
+/* I2C3 (TSP) */
+static struct mxt_platform_data qt602240_platform_data = {
+	.x_line		= 19,
+	.y_line		= 11,
+	.x_size		= 800,
+	.y_size		= 480,
+	.blen		= 0x11,
+	.threshold	= 0x28,
+	.voltage	= 2800000,		/* 2.8V */
+	.orient		= MXT_DIAGONAL,
+};
+
+static struct i2c_board_info i2c3_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("qt602240_ts", 0x4a),
+		.platform_data = &qt602240_platform_data,
+	},
+};
+
+static void __init universal_tsp_init(void)
+{
+	int gpio;
+
+	/* TSP_LDO_ON: XMDMADDR_11 */
+	gpio = EXYNOS4_GPE2(3);
+	gpio_request(gpio, "TSP_LDO_ON");
+	gpio_direction_output(gpio, 1);
+	gpio_export(gpio, 0);
+
+	/* TSP_INT: XMDMADDR_7 */
+	gpio = EXYNOS4_GPE1(7);
+	gpio_request(gpio, "TSP_INT");
+
+	s5p_register_gpio_interrupt(gpio);
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+	i2c3_devs[0].irq = gpio_to_irq(gpio);
+}
+
+
+/* GPIO I2C 12 (3 Touchkey) */
+static uint32_t touchkey_keymap[] = {
+	/* MCS_KEY_MAP(value, keycode) */
+	MCS_KEY_MAP(0, KEY_MENU),		/* KEY_SEND */
+	MCS_KEY_MAP(1, KEY_BACK),		/* KEY_END */
+};
+
+static struct mcs_platform_data touchkey_data = {
+	.keymap		= touchkey_keymap,
+	.keymap_size	= ARRAY_SIZE(touchkey_keymap),
+	.key_maxval	= 2,
+};
+
+/* GPIO I2C 3_TOUCH 2.8V */
+#define I2C_GPIO_BUS_12		12
+static struct i2c_gpio_platform_data i2c_gpio12_data = {
+	.sda_pin	= EXYNOS4_GPE4(0),	/* XMDMDATA_8 */
+	.scl_pin	= EXYNOS4_GPE4(1),	/* XMDMDATA_9 */
+};
+
+static struct platform_device i2c_gpio12 = {
+	.name		= "i2c-gpio",
+	.id		= I2C_GPIO_BUS_12,
+	.dev		= {
+		.platform_data	= &i2c_gpio12_data,
+	},
+};
+
+static struct i2c_board_info i2c_gpio12_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("mcs5080_touchkey", 0x20),
+		.platform_data = &touchkey_data,
+	},
+};
+
+static void __init universal_touchkey_init(void)
+{
+	int gpio;
+
+	gpio = EXYNOS4_GPE3(7);			/* XMDMDATA_7 */
+	gpio_request(gpio, "3_TOUCH_INT");
+	s5p_register_gpio_interrupt(gpio);
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	i2c_gpio12_devs[0].irq = gpio_to_irq(gpio);
+
+	gpio = EXYNOS4_GPE3(3);			/* XMDMDATA_3 */
+	gpio_request(gpio, "3_TOUCH_EN");
+	gpio_direction_output(gpio, 1);
+}
+
+static struct s3c2410_platform_i2c universal_i2c0_platdata __initdata = {
+	.frequency	= 300 * 1000,
+	.sda_delay	= 200,
+};
+
+/* 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			= FIXED_REG_ID_MMC0,
+	.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);
+}
+
+/* I2C1 */
+static struct i2c_board_info i2c1_devs[] __initdata = {
+	/* Gyro, To be updated */
+};
+
+/* Frame Buffer */
+static struct s3c_fb_pd_win universal_fb_win0 = {
+	.win_mode = {
+		.left_margin	= 16,
+		.right_margin	= 16,
+		.upper_margin	= 2,
+		.lower_margin	= 28,
+		.hsync_len	= 2,
+		.vsync_len	= 1,
+		.xres		= 480,
+		.yres		= 800,
+		.refresh	= 55,
+	},
+	.max_bpp	= 32,
+	.default_bpp	= 16,
+};
+
+static struct s3c_fb_platdata universal_lcd_pdata __initdata = {
+	.win[0]		= &universal_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
+			  VIDCON0_CLKSEL_LCD,
+	.vidcon1	= VIDCON1_INV_VCLK | VIDCON1_INV_VDEN
+			  | VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+	.setup_gpio	= exynos4_fimd0_gpio_setup_24bpp,
+};
+
+static struct regulator_consumer_supply cam_i_core_supply =
+	REGULATOR_SUPPLY("core", "0-001f");
+
+static struct regulator_init_data cam_i_core_reg_init_data = {
+	.constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &cam_i_core_supply,
+};
+
+static struct fixed_voltage_config cam_i_core_fixed_voltage_cfg = {
+	.supply_name	= "CAM_I_CORE_1.2V",
+	.microvolts	= 1200000,
+	.gpio		= EXYNOS4_GPE2(2),	/* CAM_8M_CORE_EN */
+	.enable_high	= 1,
+	.init_data	= &cam_i_core_reg_init_data,
+};
+
+static struct platform_device cam_i_core_fixed_reg_dev = {
+	.name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_I_CORE,
+	.dev = { .platform_data	= &cam_i_core_fixed_voltage_cfg },
+};
+
+static struct regulator_consumer_supply cam_s_if_supply =
+	REGULATOR_SUPPLY("d_sensor", "0-001f");
+
+static struct regulator_init_data cam_s_if_reg_init_data = {
+	.constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &cam_s_if_supply,
+};
+
+static struct fixed_voltage_config cam_s_if_fixed_voltage_cfg = {
+	.supply_name	= "CAM_S_IF_1.8V",
+	.microvolts	= 1800000,
+	.gpio		= EXYNOS4_GPE3(0),	/* CAM_PWR_EN1 */
+	.enable_high	= 1,
+	.init_data	= &cam_s_if_reg_init_data,
+};
+
+static struct platform_device cam_s_if_fixed_reg_dev = {
+	.name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_S_IF,
+	.dev = { .platform_data	= &cam_s_if_fixed_voltage_cfg },
+};
+
+static struct s5p_platform_mipi_csis mipi_csis_platdata = {
+	.clk_rate	= 166000000UL,
+	.lanes		= 2,
+	.alignment	= 32,
+	.hs_settle	= 12,
+	.phy_enable	= s5p_csis_phy_enable,
+};
+
+#define GPIO_CAM_LEVEL_EN(n)	EXYNOS4_GPE4(n + 3)
+#define GPIO_CAM_8M_ISP_INT	EXYNOS4_GPX1(5)	/* XEINT_13 */
+#define GPIO_CAM_MEGA_nRST	EXYNOS4_GPE2(5)
+
+static int m5mols_set_power(struct device *dev, int on)
+{
+	gpio_set_value(GPIO_CAM_LEVEL_EN(1), !on);
+	gpio_set_value(GPIO_CAM_LEVEL_EN(2), !!on);
+	return 0;
+}
+
+static struct m5mols_platform_data m5mols_platdata = {
+	.gpio_reset	= GPIO_CAM_MEGA_nRST,
+	.reset_polarity	= 0,
+	.set_power	= m5mols_set_power,
+};
+
+static struct i2c_board_info m5mols_board_info = {
+	I2C_BOARD_INFO("M5MOLS", 0x1F),
+	.platform_data = &m5mols_platdata,
+};
+
+static struct s5p_fimc_isp_info universal_camera_sensors[] = {
+	{
+		.mux_id		= 0,
+		.flags		= V4L2_MBUS_PCLK_SAMPLE_FALLING |
+				  V4L2_MBUS_VSYNC_ACTIVE_LOW,
+		.bus_type	= FIMC_MIPI_CSI2,
+		.board_info	= &m5mols_board_info,
+		.i2c_bus_num	= 0,
+		.clk_frequency	= 21600000UL,
+		.csi_data_align	= 32,
+	},
+};
+
+static struct s5p_platform_fimc fimc_md_platdata = {
+	.isp_info	= universal_camera_sensors,
+	.num_clients	= ARRAY_SIZE(universal_camera_sensors),
+};
+
+static struct gpio universal_camera_gpios[] = {
+	{ GPIO_CAM_LEVEL_EN(1),	GPIOF_OUT_INIT_HIGH, "CAM_LVL_EN1" },
+	{ GPIO_CAM_LEVEL_EN(2),	GPIOF_OUT_INIT_LOW,  "CAM_LVL_EN2" },
+	{ GPIO_CAM_8M_ISP_INT,	GPIOF_IN,            "8M_ISP_INT"  },
+	{ GPIO_CAM_MEGA_nRST,	GPIOF_OUT_INIT_LOW,  "CAM_8M_NRST" },
+};
+
+static void universal_camera_init(void)
+{
+	s3c_set_platdata(&mipi_csis_platdata, sizeof(mipi_csis_platdata),
+			 &s5p_device_mipi_csis0);
+	s3c_set_platdata(&fimc_md_platdata,  sizeof(fimc_md_platdata),
+			 &s5p_device_fimc_md);
+
+	if (gpio_request_array(universal_camera_gpios,
+			       ARRAY_SIZE(universal_camera_gpios))) {
+		pr_err("%s: GPIO request failed\n", __func__);
+		return;
+	}
+
+	if (!s3c_gpio_cfgpin(GPIO_CAM_8M_ISP_INT, S3C_GPIO_SFN(0xf)))
+		m5mols_board_info.irq = gpio_to_irq(GPIO_CAM_8M_ISP_INT);
+	else
+		pr_err("Failed to configure 8M_ISP_INT GPIO\n");
+
+	/* Free GPIOs controlled directly by the sensor drivers. */
+	gpio_free(GPIO_CAM_MEGA_nRST);
+	gpio_free(GPIO_CAM_8M_ISP_INT);
+
+	if (exynos4_fimc_setup_gpio(S5P_CAMPORT_A))
+		pr_err("Camera port A setup failed\n");
+}
+
+static struct platform_device *universal_devices[] __initdata = {
+	/* Samsung Platform Devices */
+	&s5p_device_mipi_csis0,
+	&s5p_device_fimc0,
+	&s5p_device_fimc1,
+	&s5p_device_fimc2,
+	&s5p_device_fimc3,
+	&mmc0_fixed_voltage,
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_i2c0,
+	&s3c_device_i2c3,
+	&s3c_device_i2c5,
+	&s5p_device_i2c_hdmiphy,
+	&hdmi_fixed_voltage,
+	&exynos4_device_pd[PD_TV],
+	&s5p_device_hdmi,
+	&s5p_device_sdo,
+	&s5p_device_mixer,
+
+	/* Universal Devices */
+	&i2c_gpio12,
+	&universal_gpio_keys,
+	&s5p_device_onenand,
+	&s5p_device_fimd0,
+	&s5p_device_mfc,
+	&s5p_device_mfc_l,
+	&s5p_device_mfc_r,
+	&exynos4_device_pd[PD_MFC],
+	&exynos4_device_pd[PD_LCD0],
+	&exynos4_device_pd[PD_CAM],
+	&cam_i_core_fixed_reg_dev,
+	&cam_s_if_fixed_reg_dev,
+	&s5p_device_fimc_md,
+};
+
+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));
+}
+
+void s5p_tv_setup(void)
+{
+	/* direct HPD to HDMI chip */
+	gpio_request(EXYNOS4_GPX3(7), "hpd-plug");
+
+	gpio_direction_input(EXYNOS4_GPX3(7));
+	s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
+	s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
+
+	/* setup dependencies between TV devices */
+	s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
+	s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
+}
+
+static void __init universal_reserve(void)
+{
+	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
+static void __init universal_machine_init(void)
+{
+	universal_sdhci_init();
+	s5p_tv_setup();
+
+	s3c_i2c0_set_platdata(&universal_i2c0_platdata);
+	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
+
+	universal_tsp_init();
+	s3c_i2c3_set_platdata(NULL);
+	i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
+
+	s3c_i2c5_set_platdata(NULL);
+	s5p_i2c_hdmiphy_set_platdata(NULL);
+	i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
+
+	s5p_fimd0_set_platdata(&universal_lcd_pdata);
+
+	universal_touchkey_init();
+	i2c_register_board_info(I2C_GPIO_BUS_12, i2c_gpio12_devs,
+			ARRAY_SIZE(i2c_gpio12_devs));
+
+	universal_camera_init();
+
+	/* Last */
+	platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
+
+	s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
+	s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
+
+	s5p_device_fimc0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_fimc1.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_fimc2.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_fimc3.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_mipi_csis0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+}
+
+MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
+	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= universal_map_io,
+	.init_machine	= universal_machine_init,
+	.timer		= &exynos4_timer,
+	.reserve        = &universal_reserve,
+MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/Makefile linux-libre-3.2-gnu/arch/arm/mach-exynos/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,60 @@
+# arch/arm/mach-exynos/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_ARCH_EXYNOS4)	+= cpu.o init.o clock.o irq-combiner.o setup-i2c0.o
+obj-$(CONFIG_ARCH_EXYNOS4)	+= irq-eint.o dma.o pmu.o
+obj-$(CONFIG_CPU_EXYNOS4210)	+= clock-exynos4210.o
+obj-$(CONFIG_SOC_EXYNOS4212)	+= clock-exynos4212.o
+obj-$(CONFIG_PM)		+= pm.o
+obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
+
+obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
+
+obj-$(CONFIG_EXYNOS4_MCT)	+= mct.o
+
+obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
+
+# machine support
+
+obj-$(CONFIG_MACH_SMDKC210)		+= mach-smdkv310.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
+obj-$(CONFIG_MACH_ORIGEN)		+= mach-origen.o
+
+obj-$(CONFIG_MACH_SMDK4212)		+= mach-smdk4x12.o
+obj-$(CONFIG_MACH_SMDK4412)		+= mach-smdk4x12.o
+
+# device support
+
+obj-$(CONFIG_ARCH_EXYNOS4)		+= 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_DEV_DWMCI)		+= dev-dwmci.o
+
+obj-$(CONFIG_EXYNOS4_SETUP_FIMC)	+= setup-fimc.o
+obj-$(CONFIG_EXYNOS4_SETUP_FIMD0)	+= setup-fimd0.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
+obj-$(CONFIG_EXYNOS4_SETUP_USB_PHY)	+= setup-usb-phy.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-exynos/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2 @@
+   zreladdr-y	+= 0x40008000
+params_phys-y	:= 0x40000100
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/mct.c linux-libre-3.2-gnu/arch/arm/mach-exynos/mct.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/mct.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/mct.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,478 @@
+/* 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 <asm/hardware/gic.h>
+
+#include <plat/cpu.h>
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+#include <mach/regs-mct.h>
+#include <asm/mach/time.h>
+
+enum {
+	MCT_INT_SPI,
+	MCT_INT_PPI
+};
+
+static unsigned long clk_cnt_per_tick;
+static unsigned long clk_rate;
+static unsigned int mct_int_type;
+
+struct mct_clock_event_device {
+	struct clock_event_device *evt;
+	void __iomem *base;
+	char name[10];
+};
+
+static void exynos4_mct_write(unsigned int value, void *addr)
+{
+	void __iomem *stat_addr;
+	u32 mask;
+	u32 i;
+
+	__raw_writel(value, addr);
+
+	if (likely(addr >= EXYNOS4_MCT_L_BASE(0))) {
+		u32 base = (u32) addr & EXYNOS4_MCT_L_MASK;
+		switch ((u32) addr & ~EXYNOS4_MCT_L_MASK) {
+		case (u32) MCT_L_TCON_OFFSET:
+			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+			mask = 1 << 3;		/* L_TCON write status */
+			break;
+		case (u32) MCT_L_ICNTB_OFFSET:
+			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+			mask = 1 << 1;		/* L_ICNTB write status */
+			break;
+		case (u32) MCT_L_TCNTB_OFFSET:
+			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+			mask = 1 << 0;		/* L_TCNTB write status */
+			break;
+		default:
+			return;
+		}
+	} else {
+		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 w 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;
+		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;
+}
+
+static void exynos4_frc_resume(struct clocksource *cs)
+{
+	exynos4_mct_frc_start(0, 0);
+}
+
+struct clocksource mct_frc = {
+	.name		= "mct-frc",
+	.rating		= 400,
+	.read		= exynos4_frc_read,
+	.mask		= CLOCKSOURCE_MASK(64),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+	.resume		= exynos4_frc_resume,
+};
+
+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
+
+static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick);
+
+/* 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 = this_cpu_ptr(&percpu_mct_tick);
+
+	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 = this_cpu_ptr(&percpu_mct_tick);
+
+	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 int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
+{
+	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 */
+	if (__raw_readl(mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
+		exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+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;
+
+	exynos4_mct_tick_clear(mevt);
+
+	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)
+{
+	struct mct_clock_event_device *mevt;
+	unsigned int cpu = smp_processor_id();
+
+	mevt = this_cpu_ptr(&percpu_mct_tick);
+	mevt->evt = evt;
+
+	mevt->base = EXYNOS4_MCT_L_BASE(cpu);
+	sprintf(mevt->name, "mct_tick%d", cpu);
+
+	evt->name = mevt->name;
+	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, mevt->base + MCT_L_TCNTB_OFFSET);
+
+	if (mct_int_type == MCT_INT_SPI) {
+		if (cpu == 0) {
+			mct_tick0_event_irq.dev_id = mevt;
+			evt->irq = IRQ_MCT_L0;
+			setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
+		} else {
+			mct_tick1_event_irq.dev_id = mevt;
+			evt->irq = IRQ_MCT_L1;
+			setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
+			irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
+		}
+	} else {
+		enable_percpu_irq(IRQ_MCT_LOCALTIMER, 0);
+	}
+}
+
+/* Setup the local clock events for a CPU */
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	exynos4_mct_tick_init(evt);
+
+	return 0;
+}
+
+void local_timer_stop(struct clock_event_device *evt)
+{
+	unsigned int cpu = smp_processor_id();
+	evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+	if (mct_int_type == MCT_INT_SPI)
+		if (cpu == 0)
+			remove_irq(evt->irq, &mct_tick0_event_irq);
+		else
+			remove_irq(evt->irq, &mct_tick1_event_irq);
+	else
+		disable_percpu_irq(IRQ_MCT_LOCALTIMER);
+}
+#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);
+
+#ifdef CONFIG_LOCAL_TIMERS
+	if (mct_int_type == MCT_INT_PPI) {
+		int err;
+
+		err = request_percpu_irq(IRQ_MCT_LOCALTIMER,
+					 exynos4_mct_tick_isr, "MCT",
+					 &percpu_mct_tick);
+		WARN(err, "MCT: can't request IRQ %d (%d)\n",
+		     IRQ_MCT_LOCALTIMER, err);
+	}
+#endif /* CONFIG_LOCAL_TIMERS */
+}
+
+static void __init exynos4_timer_init(void)
+{
+	if (soc_is_exynos4210())
+		mct_int_type = MCT_INT_SPI;
+	else
+		mct_int_type = MCT_INT_PPI;
+
+	exynos4_timer_resources();
+	exynos4_clocksource_init();
+	exynos4_clockevent_init();
+}
+
+struct sys_timer exynos4_timer = {
+	.init		= exynos4_timer_init,
+};
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/platsmp.c linux-libre-3.2-gnu/arch/arm/mach-exynos/platsmp.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/platsmp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,223 @@
+/* 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/hardware/gic.h>
+#include <asm/smp_scu.h>
+#include <asm/unified.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-pmu.h>
+
+#include <plat/cpu.h>
+
+extern unsigned int gic_bank_offset;
+extern void exynos4_secondary_startup(void);
+
+#define CPU1_BOOT_REG		(samsung_rev() == EXYNOS4210_REV_1_1 ? \
+				S5P_INFORM5 : S5P_VA_SYSRAM)
+
+/*
+ * 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);
+
+static void __cpuinit exynos4_gic_secondary_init(void)
+{
+	void __iomem *dist_base = S5P_VA_GIC_DIST +
+				(gic_bank_offset * smp_processor_id());
+	void __iomem *cpu_base = S5P_VA_GIC_CPU +
+				(gic_bank_offset * smp_processor_id());
+	int i;
+
+	/*
+	 * Deal with the banked PPI and SGI interrupts - disable all
+	 * PPI interrupts, ensure all SGI interrupts are enabled.
+	 */
+	__raw_writel(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
+	__raw_writel(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
+
+	/*
+	 * Set priority on PPI and SGI interrupts
+	 */
+	for (i = 0; i < 32; i += 4)
+		__raw_writel(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
+
+	__raw_writel(0xf0, cpu_base + GIC_CPU_PRIMASK);
+	__raw_writel(1, cpu_base + GIC_CPU_CTRL);
+}
+
+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
+	 */
+	exynos4_gic_secondary_init();
+
+	/*
+	 * 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_logical_map(cpu));
+
+	if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) {
+		__raw_writel(S5P_CORE_LOCAL_PWR_EN,
+			     S5P_ARM_CORE1_CONFIGURATION);
+
+		timeout = 10;
+
+		/* wait max 10 ms until cpu1 is on */
+		while ((__raw_readl(S5P_ARM_CORE1_STATUS)
+			& S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) {
+			if (timeout-- == 0)
+				break;
+
+			mdelay(1);
+		}
+
+		if (timeout == 0) {
+			printk(KERN_ERR "cpu1 power enable failed");
+			spin_unlock(&boot_lock);
+			return -ETIMEDOUT;
+		}
+	}
+	/*
+	 * 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.
+	 */
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout)) {
+		smp_rmb();
+
+		__raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)),
+			CPU1_BOOT_REG);
+		gic_raise_softirq(cpumask_of(cpu), 1);
+
+		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_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
+	}
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+
+	set_smp_cross_call(gic_raise_softirq);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+
+	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)),
+			CPU1_BOOT_REG);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/pm.c linux-libre-3.2-gnu/arch/arm/mach-exynos/pm.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,428 @@
+/* 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/syscore_ops.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/pll.h>
+#include <plat/regs-srom.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>
+#include <mach/pmu.h>
+
+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_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 exynos4210_set_clksrc[] = {
+	{ .reg = S5P_CLKSRC_MASK_LCD1			, .val = 0x00001111, },
+};
+
+static struct sleep_save exynos4_epll_save[] = {
+	SAVE_ITEM(S5P_EPLL_CON0),
+	SAVE_ITEM(S5P_EPLL_CON1),
+};
+
+static struct sleep_save exynos4_vpll_save[] = {
+	SAVE_ITEM(S5P_VPLL_CON0),
+	SAVE_ITEM(S5P_VPLL_CON1),
+};
+
+static struct sleep_save exynos4_core_save[] = {
+	/* 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),
+
+	/* SROM side */
+	SAVE_ITEM(S5P_SROM_BW),
+	SAVE_ITEM(S5P_SROM_BC0),
+	SAVE_ITEM(S5P_SROM_BC1),
+	SAVE_ITEM(S5P_SROM_BC2),
+	SAVE_ITEM(S5P_SROM_BC3),
+};
+
+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),
+};
+
+/* For Cortex-A9 Diagnostic and Power control register */
+static unsigned int save_arm_register[2];
+
+static int exynos4_cpu_suspend(unsigned long arg)
+{
+	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));
+	s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
+	s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
+
+	tmp = __raw_readl(S5P_INFORM1);
+
+	/* Set value of power down register for sleep mode */
+
+	exynos4_sys_powerdown_conf(SYS_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));
+
+	if (soc_is_exynos4210())
+		s3c_pm_do_restore_core(exynos4210_set_clksrc, ARRAY_SIZE(exynos4210_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 unsigned long pll_base_rate;
+
+static void exynos4_restore_pll(void)
+{
+	unsigned long pll_con, locktime, lockcnt;
+	unsigned long pll_in_rate;
+	unsigned int p_div, epll_wait = 0, vpll_wait = 0;
+
+	if (pll_base_rate == 0)
+		return;
+
+	pll_in_rate = pll_base_rate;
+
+	/* EPLL */
+	pll_con = exynos4_epll_save[0].val;
+
+	if (pll_con & (1 << 31)) {
+		pll_con &= (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT);
+		p_div = (pll_con >> PLL46XX_PDIV_SHIFT);
+
+		pll_in_rate /= 1000000;
+
+		locktime = (3000 / pll_in_rate) * p_div;
+		lockcnt = locktime * 10000 / (10000 / pll_in_rate);
+
+		__raw_writel(lockcnt, S5P_EPLL_LOCK);
+
+		s3c_pm_do_restore_core(exynos4_epll_save,
+					ARRAY_SIZE(exynos4_epll_save));
+		epll_wait = 1;
+	}
+
+	pll_in_rate = pll_base_rate;
+
+	/* VPLL */
+	pll_con = exynos4_vpll_save[0].val;
+
+	if (pll_con & (1 << 31)) {
+		pll_in_rate /= 1000000;
+		/* 750us */
+		locktime = 750;
+		lockcnt = locktime * 10000 / (10000 / pll_in_rate);
+
+		__raw_writel(lockcnt, S5P_VPLL_LOCK);
+
+		s3c_pm_do_restore_core(exynos4_vpll_save,
+					ARRAY_SIZE(exynos4_vpll_save));
+		vpll_wait = 1;
+	}
+
+	/* Wait PLL locking */
+
+	do {
+		if (epll_wait) {
+			pll_con = __raw_readl(S5P_EPLL_CON0);
+			if (pll_con & (1 << S5P_EPLLCON0_LOCKED_SHIFT))
+				epll_wait = 0;
+		}
+
+		if (vpll_wait) {
+			pll_con = __raw_readl(S5P_VPLL_CON0);
+			if (pll_con & (1 << S5P_VPLLCON0_LOCKED_SHIFT))
+				vpll_wait = 0;
+		}
+	} while (epll_wait || vpll_wait);
+}
+
+static struct sysdev_driver exynos4_pm_driver = {
+	.add		= exynos4_pm_add,
+};
+
+static __init int exynos4_pm_drvinit(void)
+{
+	struct clk *pll_base;
+	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);
+
+	pll_base = clk_get(NULL, "xtal");
+
+	if (!IS_ERR(pll_base)) {
+		pll_base_rate = clk_get_rate(pll_base);
+		clk_put(pll_base);
+	}
+
+	return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver);
+}
+arch_initcall(exynos4_pm_drvinit);
+
+static int exynos4_pm_suspend(void)
+{
+	unsigned long tmp;
+
+	/* 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);
+
+	if (soc_is_exynos4212()) {
+		tmp = __raw_readl(S5P_CENTRAL_SEQ_OPTION);
+		tmp &= ~(S5P_USE_STANDBYWFI_ISP_ARM |
+			 S5P_USE_STANDBYWFE_ISP_ARM);
+		__raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
+	}
+
+	/* Save Power control register */
+	asm ("mrc p15, 0, %0, c15, c0, 0"
+	     : "=r" (tmp) : : "cc");
+	save_arm_register[0] = tmp;
+
+	/* Save Diagnostic register */
+	asm ("mrc p15, 0, %0, c15, c0, 1"
+	     : "=r" (tmp) : : "cc");
+	save_arm_register[1] = tmp;
+
+	return 0;
+}
+
+static void exynos4_pm_resume(void)
+{
+	unsigned long tmp;
+
+	/*
+	 * If PMU failed while entering sleep mode, WFI will be
+	 * ignored by PMU and then exiting cpu_do_idle().
+	 * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
+	 * in this situation.
+	 */
+	tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+	if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
+		tmp |= S5P_CENTRAL_LOWPWR_CFG;
+		__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+		/* No need to perform below restore code */
+		goto early_wakeup;
+	}
+	/* Restore Power control register */
+	tmp = save_arm_register[0];
+	asm volatile ("mcr p15, 0, %0, c15, c0, 0"
+		      : : "r" (tmp)
+		      : "cc");
+
+	/* Restore Diagnostic register */
+	tmp = save_arm_register[1];
+	asm volatile ("mcr p15, 0, %0, c15, c0, 1"
+		      : : "r" (tmp)
+		      : "cc");
+
+	/* 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_restore_pll();
+
+	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
+
+early_wakeup:
+	return;
+}
+
+static struct syscore_ops exynos4_pm_syscore_ops = {
+	.suspend	= exynos4_pm_suspend,
+	.resume		= exynos4_pm_resume,
+};
+
+static __init int exynos4_pm_syscore_init(void)
+{
+	register_syscore_ops(&exynos4_pm_syscore_ops);
+	return 0;
+}
+arch_initcall(exynos4_pm_syscore_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/pmu.c linux-libre-3.2-gnu/arch/arm/mach-exynos/pmu.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/pmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/pmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,230 @@
+/* linux/arch/arm/mach-exynos4/pmu.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * EXYNOS4210 - CPU PMU(Power Management Unit) 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 <mach/regs-clock.h>
+#include <mach/pmu.h>
+
+static struct exynos4_pmu_conf *exynos4_pmu_config;
+
+static struct exynos4_pmu_conf exynos4210_pmu_config[] = {
+	/* { .reg = address, .val = { AFTR, LPA, SLEEP } */
+	{ S5P_ARM_CORE0_LOWPWR,			{ 0x0, 0x0, 0x2 } },
+	{ S5P_DIS_IRQ_CORE0,			{ 0x0, 0x0, 0x0 } },
+	{ S5P_DIS_IRQ_CENTRAL0,			{ 0x0, 0x0, 0x0 } },
+	{ S5P_ARM_CORE1_LOWPWR,			{ 0x0, 0x0, 0x2 } },
+	{ S5P_DIS_IRQ_CORE1,			{ 0x0, 0x0, 0x0 } },
+	{ S5P_DIS_IRQ_CENTRAL1,			{ 0x0, 0x0, 0x0 } },
+	{ S5P_ARM_COMMON_LOWPWR,		{ 0x0, 0x0, 0x2 } },
+	{ S5P_L2_0_LOWPWR,			{ 0x2, 0x2, 0x3 } },
+	{ S5P_L2_1_LOWPWR,			{ 0x2, 0x2, 0x3 } },
+	{ S5P_CMU_ACLKSTOP_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_SCLKSTOP_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_LOWPWR,			{ 0x1, 0x1, 0x0 } },
+	{ S5P_APLL_SYSCLK_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_MPLL_SYSCLK_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_VPLL_SYSCLK_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_EPLL_SYSCLK_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR,	{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_GPSALIVE_LOWPWR,	{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_CAM_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_TV_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_MFC_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_G3D_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_LCD0_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_LCD1_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_MAUDIO_LOWPWR,	{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_CLKSTOP_GPS_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_CAM_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_TV_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_MFC_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_G3D_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_LCD0_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_LCD1_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_MAUDIO_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_GPS_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_TOP_BUS_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_TOP_RETENTION_LOWPWR,		{ 0x1, 0x0, 0x1 } },
+	{ S5P_TOP_PWR_LOWPWR,			{ 0x3, 0x0, 0x3 } },
+	{ S5P_LOGIC_RESET_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_ONENAND_MEM_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_MODIMIF_MEM_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_G2D_ACP_MEM_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_USBOTG_MEM_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_HSMMC_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_CSSYS_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_SECSS_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_PCIE_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_SATA_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_DRAM_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_MAUDIO_LOWPWR,	{ 0x1, 0x1, 0x0 } },
+	{ S5P_PAD_RETENTION_GPIO_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_UART_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_MMCA_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_MMCB_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_EBIA_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_EBIB_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_ISOLATION_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_ALV_SEL_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_XUSBXTI_LOWPWR,			{ 0x1, 0x1, 0x0 } },
+	{ S5P_XXTI_LOWPWR,			{ 0x1, 0x1, 0x0 } },
+	{ S5P_EXT_REGULATOR_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_GPIO_MODE_LOWPWR,			{ 0x1, 0x0, 0x0 } },
+	{ S5P_GPIO_MODE_MAUDIO_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CAM_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_TV_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_MFC_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_G3D_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_LCD0_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_LCD1_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_MAUDIO_LOWPWR,			{ 0x7, 0x7, 0x0 } },
+	{ S5P_GPS_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_GPS_ALIVE_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ PMU_TABLE_END,},
+};
+
+static struct exynos4_pmu_conf exynos4212_pmu_config[] = {
+	{ S5P_ARM_CORE0_LOWPWR,			{ 0x0, 0x0, 0x2 } },
+	{ S5P_DIS_IRQ_CORE0,			{ 0x0, 0x0, 0x0 } },
+	{ S5P_DIS_IRQ_CENTRAL0,			{ 0x0, 0x0, 0x0 } },
+	{ S5P_ARM_CORE1_LOWPWR,			{ 0x0, 0x0, 0x2 } },
+	{ S5P_DIS_IRQ_CORE1,			{ 0x0, 0x0, 0x0 } },
+	{ S5P_DIS_IRQ_CENTRAL1,			{ 0x0, 0x0, 0x0 } },
+	{ S5P_ISP_ARM_LOWPWR,			{ 0x1, 0x0, 0x0 } },
+	{ S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR,	{ 0x0, 0x0, 0x0 } },
+	{ S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR,	{ 0x0, 0x0, 0x0 } },
+	{ S5P_ARM_COMMON_LOWPWR,		{ 0x0, 0x0, 0x2 } },
+	{ S5P_L2_0_LOWPWR,			{ 0x0, 0x0, 0x3 } },
+	/* XXX_OPTION register should be set other field */
+	{ S5P_ARM_L2_0_OPTION,			{ 0x10, 0x10, 0x0 } },
+	{ S5P_L2_1_LOWPWR,			{ 0x0, 0x0, 0x3 } },
+	{ S5P_ARM_L2_1_OPTION,			{ 0x10, 0x10, 0x0 } },
+	{ S5P_CMU_ACLKSTOP_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_SCLKSTOP_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_LOWPWR,			{ 0x1, 0x1, 0x0 } },
+	{ S5P_DRAM_FREQ_DOWN_LOWPWR,		{ 0x1, 0x1, 0x1 } },
+	{ S5P_DDRPHY_DLLOFF_LOWPWR,		{ 0x1, 0x1, 0x1 } },
+	{ S5P_LPDDR_PHY_DLL_LOCK_LOWPWR,	{ 0x1, 0x1, 0x1 } },
+	{ S5P_CMU_ACLKSTOP_COREBLK_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_SCLKSTOP_COREBLK_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_COREBLK_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_APLL_SYSCLK_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_MPLL_SYSCLK_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_VPLL_SYSCLK_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_EPLL_SYSCLK_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_MPLLUSER_SYSCLK_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_GPSALIVE_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_CAM_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_TV_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_MFC_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_G3D_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_LCD0_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_ISP_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_MAUDIO_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_CLKSTOP_GPS_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_CAM_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_TV_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_MFC_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_G3D_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_LCD0_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_ISP_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_RESET_MAUDIO_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_CMU_RESET_GPS_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_TOP_BUS_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_TOP_RETENTION_LOWPWR,		{ 0x1, 0x0, 0x1 } },
+	{ S5P_TOP_PWR_LOWPWR,			{ 0x3, 0x0, 0x3 } },
+	{ S5P_TOP_BUS_COREBLK_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_TOP_RETENTION_COREBLK_LOWPWR,	{ 0x1, 0x0, 0x1 } },
+	{ S5P_TOP_PWR_COREBLK_LOWPWR,		{ 0x3, 0x0, 0x3 } },
+	{ S5P_LOGIC_RESET_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_OSCCLK_GATE_LOWPWR,		{ 0x1, 0x0, 0x1 } },
+	{ S5P_LOGIC_RESET_COREBLK_LOWPWR,	{ 0x1, 0x1, 0x0 } },
+	{ S5P_OSCCLK_GATE_COREBLK_LOWPWR,	{ 0x1, 0x0, 0x1 } },
+	{ S5P_ONENAND_MEM_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_ONENAND_MEM_OPTION,		{ 0x10, 0x10, 0x0 } },
+	{ S5P_HSI_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_HSI_MEM_OPTION,			{ 0x10, 0x10, 0x0 } },
+	{ S5P_G2D_ACP_MEM_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_G2D_ACP_MEM_OPTION,		{ 0x10, 0x10, 0x0 } },
+	{ S5P_USBOTG_MEM_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_USBOTG_MEM_OPTION,		{ 0x10, 0x10, 0x0 } },
+	{ S5P_HSMMC_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_HSMMC_MEM_OPTION,			{ 0x10, 0x10, 0x0 } },
+	{ S5P_CSSYS_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_CSSYS_MEM_OPTION,			{ 0x10, 0x10, 0x0 } },
+	{ S5P_SECSS_MEM_LOWPWR,			{ 0x3, 0x0, 0x0 } },
+	{ S5P_SECSS_MEM_OPTION,			{ 0x10, 0x10, 0x0 } },
+	{ S5P_ROTATOR_MEM_LOWPWR,		{ 0x3, 0x0, 0x0 } },
+	{ S5P_ROTATOR_MEM_OPTION,		{ 0x10, 0x10, 0x0 } },
+	{ S5P_PAD_RETENTION_DRAM_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_MAUDIO_LOWPWR,	{ 0x1, 0x1, 0x0 } },
+	{ S5P_PAD_RETENTION_GPIO_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_UART_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_MMCA_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_MMCB_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_EBIA_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_EBIB_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR,{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_ISOLATION_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_ISOLATION_COREBLK_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_PAD_RETENTION_ALV_SEL_LOWPWR,	{ 0x1, 0x0, 0x0 } },
+	{ S5P_XUSBXTI_LOWPWR,			{ 0x1, 0x1, 0x0 } },
+	{ S5P_XXTI_LOWPWR,			{ 0x1, 0x1, 0x0 } },
+	{ S5P_EXT_REGULATOR_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_GPIO_MODE_LOWPWR,			{ 0x1, 0x0, 0x0 } },
+	{ S5P_GPIO_MODE_COREBLK_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_GPIO_MODE_MAUDIO_LOWPWR,		{ 0x1, 0x1, 0x0 } },
+	{ S5P_TOP_ASB_RESET_LOWPWR,		{ 0x1, 0x1, 0x1 } },
+	{ S5P_TOP_ASB_ISOLATION_LOWPWR,		{ 0x1, 0x0, 0x1 } },
+	{ S5P_CAM_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_TV_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_MFC_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_G3D_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_LCD0_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_ISP_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_MAUDIO_LOWPWR,			{ 0x7, 0x7, 0x0 } },
+	{ S5P_GPS_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_GPS_ALIVE_LOWPWR,			{ 0x7, 0x0, 0x0 } },
+	{ S5P_CMU_SYSCLK_ISP_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ S5P_CMU_SYSCLK_GPS_LOWPWR,		{ 0x1, 0x0, 0x0 } },
+	{ PMU_TABLE_END,},
+};
+
+void exynos4_sys_powerdown_conf(enum sys_powerdown mode)
+{
+	unsigned int i;
+
+	for (i = 0; (exynos4_pmu_config[i].reg != PMU_TABLE_END) ; i++)
+		__raw_writel(exynos4_pmu_config[i].val[mode],
+				exynos4_pmu_config[i].reg);
+}
+
+static int __init exynos4_pmu_init(void)
+{
+	exynos4_pmu_config = exynos4210_pmu_config;
+
+	if (soc_is_exynos4210()) {
+		exynos4_pmu_config = exynos4210_pmu_config;
+		pr_info("EXYNOS4210 PMU Initialize\n");
+	} else if (soc_is_exynos4212()) {
+		exynos4_pmu_config = exynos4212_pmu_config;
+		pr_info("EXYNOS4212 PMU Initialize\n");
+	} else {
+		pr_info("EXYNOS4: PMU not supported\n");
+	}
+
+	return 0;
+}
+arch_initcall(exynos4_pmu_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-fimc.c linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-fimc.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-fimc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-fimc.c	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/setup-fimd0.c linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-fimd0.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-fimd0.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-fimd0.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,43 @@
+/* linux/arch/arm/mach-exynos4/setup-fimd0.c
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Base Exynos4 FIMD 0 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/fb.h>
+#include <linux/gpio.h>
+
+#include <plat/gpio-cfg.h>
+#include <plat/regs-fb-v4.h>
+
+#include <mach/map.h>
+
+void exynos4_fimd0_gpio_setup_24bpp(void)
+{
+	unsigned int reg;
+
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF0(0), 8, S3C_GPIO_SFN(2));
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF1(0), 8, S3C_GPIO_SFN(2));
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF2(0), 8, S3C_GPIO_SFN(2));
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF3(0), 4, S3C_GPIO_SFN(2));
+
+	/*
+	 * Set DISPLAY_CONTROL register for Display path selection.
+	 *
+	 * DISPLAY_CONTROL[1:0]
+	 * ---------------------
+	 *  00 | MIE
+	 *  01 | MDINE
+	 *  10 | FIMD : selected
+	 *  11 | FIMD
+	 */
+	reg = __raw_readl(S3C_VA_SYS + 0x0210);
+	reg |= (1 << 1);
+	__raw_writel(reg, S3C_VA_SYS + 0x0210);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-i2c0.c linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-i2c0.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-i2c0.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-i2c0.c	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/setup-i2c1.c linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-i2c1.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-i2c1.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-i2c1.c	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/setup-i2c2.c linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-i2c2.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-i2c2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-i2c2.c	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/setup-i2c3.c linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-i2c3.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-i2c3.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-i2c3.c	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/setup-i2c4.c linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-i2c4.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-i2c4.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-i2c4.c	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/setup-i2c5.c linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-i2c5.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-i2c5.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-i2c5.c	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/setup-i2c6.c linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-i2c6.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-i2c6.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-i2c6.c	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/setup-i2c7.c linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-i2c7.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-i2c7.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-i2c7.c	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/setup-keypad.c linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-keypad.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-keypad.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,36 @@
+/* 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_cfgall_range(EXYNOS4_GPX2(0), 8, S3C_GPIO_SFN(3),
+					S3C_GPIO_PULL_UP);
+
+		/* Set all the necessary GPX3 pins: KP_ROW[8~] */
+		s3c_gpio_cfgall_range(EXYNOS4_GPX3(0), (rows - 8),
+					 S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+	} else {
+		/* Set all the necessary GPX2 pins: KP_ROW[x] */
+		s3c_gpio_cfgall_range(EXYNOS4_GPX2(0), rows, S3C_GPIO_SFN(3),
+					S3C_GPIO_PULL_UP);
+	}
+
+	/* 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-3.1-gnu/arch/arm/mach-exynos/setup-sdhci.c linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-sdhci.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-sdhci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-sdhci.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+/* 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/types.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,
+};
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-sdhci-gpio.c linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-sdhci-gpio.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-sdhci-gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-sdhci-gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/arch/arm/mach-exynos/setup-usb-phy.c linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-usb-phy.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos/setup-usb-phy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos/setup-usb-phy.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2011 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/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <mach/regs-pmu.h>
+#include <mach/regs-usb-phy.h>
+#include <plat/cpu.h>
+#include <plat/usb-phy.h>
+
+static int exynos4_usb_phy1_init(struct platform_device *pdev)
+{
+	struct clk *otg_clk;
+	struct clk *xusbxti_clk;
+	u32 phyclk;
+	u32 rstcon;
+	int err;
+
+	otg_clk = clk_get(&pdev->dev, "otg");
+	if (IS_ERR(otg_clk)) {
+		dev_err(&pdev->dev, "Failed to get otg clock\n");
+		return PTR_ERR(otg_clk);
+	}
+
+	err = clk_enable(otg_clk);
+	if (err) {
+		clk_put(otg_clk);
+		return err;
+	}
+
+	writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE,
+			S5P_USBHOST_PHY_CONTROL);
+
+	/* set clock frequency for PLL */
+	phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK;
+
+	xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
+	if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
+		switch (clk_get_rate(xusbxti_clk)) {
+		case 12 * MHZ:
+			phyclk |= CLKSEL_12M;
+			break;
+		case 24 * MHZ:
+			phyclk |= CLKSEL_24M;
+			break;
+		default:
+		case 48 * MHZ:
+			/* default reference clock */
+			break;
+		}
+		clk_put(xusbxti_clk);
+	}
+
+	writel(phyclk, EXYNOS4_PHYCLK);
+
+	/* floating prevention logic: disable */
+	writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON);
+
+	/* set to normal HSIC 0 and 1 of PHY1 */
+	writel((readl(EXYNOS4_PHYPWR) & ~PHY1_HSIC_NORMAL_MASK),
+			EXYNOS4_PHYPWR);
+
+	/* set to normal standard USB of PHY1 */
+	writel((readl(EXYNOS4_PHYPWR) & ~PHY1_STD_NORMAL_MASK), EXYNOS4_PHYPWR);
+
+	/* reset all ports of both PHY and Link */
+	rstcon = readl(EXYNOS4_RSTCON) | HOST_LINK_PORT_SWRST_MASK |
+		PHY1_SWRST_MASK;
+	writel(rstcon, EXYNOS4_RSTCON);
+	udelay(10);
+
+	rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK);
+	writel(rstcon, EXYNOS4_RSTCON);
+	udelay(80);
+
+	clk_disable(otg_clk);
+	clk_put(otg_clk);
+
+	return 0;
+}
+
+static int exynos4_usb_phy1_exit(struct platform_device *pdev)
+{
+	struct clk *otg_clk;
+	int err;
+
+	otg_clk = clk_get(&pdev->dev, "otg");
+	if (IS_ERR(otg_clk)) {
+		dev_err(&pdev->dev, "Failed to get otg clock\n");
+		return PTR_ERR(otg_clk);
+	}
+
+	err = clk_enable(otg_clk);
+	if (err) {
+		clk_put(otg_clk);
+		return err;
+	}
+
+	writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN),
+			EXYNOS4_PHYPWR);
+
+	writel(readl(S5P_USBHOST_PHY_CONTROL) & ~S5P_USBHOST_PHY_ENABLE,
+			S5P_USBHOST_PHY_CONTROL);
+
+	clk_disable(otg_clk);
+	clk_put(otg_clk);
+
+	return 0;
+}
+
+int s5p_usb_phy_init(struct platform_device *pdev, int type)
+{
+	if (type == S5P_USB_PHY_HOST)
+		return exynos4_usb_phy1_init(pdev);
+
+	return -EINVAL;
+}
+
+int s5p_usb_phy_exit(struct platform_device *pdev, int type)
+{
+	if (type == S5P_USB_PHY_HOST)
+		return exynos4_usb_phy1_exit(pdev);
+
+	return -EINVAL;
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/clock.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/clock.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/clock.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1212 +0,0 @@
-/* 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",
-	.rate		= 27000000,
-};
-
-static struct clk clk_sclk_hdmiphy = {
-	.name		= "sclk_hdmiphy",
-};
-
-static struct clk clk_sclk_usbphy0 = {
-	.name		= "sclk_usbphy0",
-	.rate		= 27000000,
-};
-
-static struct clk clk_sclk_usbphy1 = {
-	.name		= "sclk_usbphy1",
-};
-
-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",
-	},
-	.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",
-		.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",
-	},
-	.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",
-	},
-	.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",
-	},
-	.sources	= &clkset_moutcore,
-	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 16, .size = 1 },
-};
-
-static struct clksrc_clk clk_coreclk = {
-	.clk	= {
-		.name		= "core_clk",
-		.parent		= &clk_moutcore.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk clk_armclk = {
-	.clk	= {
-		.name		= "armclk",
-		.parent		= &clk_coreclk.clk,
-	},
-};
-
-static struct clksrc_clk clk_aclk_corem0 = {
-	.clk	= {
-		.name		= "aclk_corem0",
-		.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",
-		.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",
-		.parent		= &clk_coreclk.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk clk_periphclk = {
-	.clk	= {
-		.name		= "periphclk",
-		.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",
-	},
-	.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",
-		.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",
-		.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",
-		.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",
-		.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",
-		.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",
-	},
-	.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",
-	},
-	.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",
-	},
-	.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",
-	},
-	.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",
-		.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",
-	},
-	.sources	= &clkset_sclk_vpll,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
-};
-
-static struct clk init_clocks_off[] = {
-	{
-		.name		= "timers",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1<<24),
-	}, {
-		.name		= "csis",
-		.devname	= "s5p-mipi-csis.0",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "csis",
-		.devname	= "s5p-mipi-csis.1",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.0",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.1",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.2",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.3",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "fimd",
-		.devname	= "exynos4-fb.0",
-		.enable		= exynos4_clk_ip_lcd0_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "fimd",
-		.devname	= "exynos4-fb.1",
-		.enable		= exynos4_clk_ip_lcd1_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "sataphy",
-		.parent		= &clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.0",
-		.parent		= &clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.1",
-		.parent		= &clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.2",
-		.parent		= &clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.3",
-		.parent		= &clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "dwmmc",
-		.parent		= &clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "sata",
-		.parent		= &clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "pdma",
-		.devname	= "s3c-pl330.0",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "pdma",
-		.devname	= "s3c-pl330.1",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "adc",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "keypad",
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "rtc",
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "watchdog",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 14),
-	}, {
-		.name		= "usbhost",
-		.enable		= exynos4_clk_ip_fsys_ctrl ,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "otg",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "spi",
-		.devname	= "s3c64xx-spi.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "spi",
-		.devname	= "s3c64xx-spi.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 17),
-	}, {
-		.name		= "spi",
-		.devname	= "s3c64xx-spi.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 18),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 19),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 20),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 21),
-	}, {
-		.name		= "ac97",
-		.devname	= "samsung-ac97",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 27),
-	}, {
-		.name		= "fimg2d",
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "mfc",
-		.devname	= "s5p-mfc",
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.0",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.1",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.2",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.3",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.4",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.5",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.6",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.7",
-		.parent		= &clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "SYSMMU_MDMA",
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "SYSMMU_FIMC0",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "SYSMMU_FIMC1",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "SYSMMU_FIMC2",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "SYSMMU_FIMC3",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "SYSMMU_JPEG",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "SYSMMU_FIMD0",
-		.enable		= exynos4_clk_ip_lcd0_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "SYSMMU_FIMD1",
-		.enable		= exynos4_clk_ip_lcd1_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "SYSMMU_PCIe",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 18),
-	}, {
-		.name		= "SYSMMU_G2D",
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "SYSMMU_ROTATOR",
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "SYSMMU_TV",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "SYSMMU_MFC_L",
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "SYSMMU_MFC_R",
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 2),
-	}
-};
-
-static struct clk init_clocks[] = {
-	{
-		.name		= "uart",
-		.devname	= "s5pv210-uart.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.3",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.4",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.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",
-	},
-	.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",
-	},
-	.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 clk *clkset_mout_mfc0_list[] = {
-	[0] = &clk_mout_mpll.clk,
-	[1] = &clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources clkset_mout_mfc0 = {
-	.sources	= clkset_mout_mfc0_list,
-	.nr_sources	= ARRAY_SIZE(clkset_mout_mfc0_list),
-};
-
-static struct clksrc_clk clk_mout_mfc0 = {
-	.clk	= {
-		.name		= "mout_mfc0",
-	},
-	.sources	= &clkset_mout_mfc0,
-	.reg_src	= { .reg = S5P_CLKSRC_MFC, .shift = 0, .size = 1 },
-};
-
-static struct clk *clkset_mout_mfc1_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_mout_mfc1 = {
-	.sources	= clkset_mout_mfc1_list,
-	.nr_sources	= ARRAY_SIZE(clkset_mout_mfc1_list),
-};
-
-static struct clksrc_clk clk_mout_mfc1 = {
-	.clk	= {
-		.name		= "mout_mfc1",
-	},
-	.sources	= &clkset_mout_mfc1,
-	.reg_src	= { .reg = S5P_CLKSRC_MFC, .shift = 4, .size = 1 },
-};
-
-static struct clk *clkset_mout_mfc_list[] = {
-	[0] = &clk_mout_mfc0.clk,
-	[1] = &clk_mout_mfc1.clk,
-};
-
-static struct clksrc_sources clkset_mout_mfc = {
-	.sources	= clkset_mout_mfc_list,
-	.nr_sources	= ARRAY_SIZE(clkset_mout_mfc_list),
-};
-
-static struct clksrc_clk clk_dout_mmc0 = {
-	.clk		= {
-		.name		= "dout_mmc0",
-	},
-	.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",
-	},
-	.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",
-	},
-	.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",
-	},
-	.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",
-	},
-	.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",
-			.devname	= "s5pv210-uart.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",
-			.devname	= "s5pv210-uart.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",
-			.devname	= "s5pv210-uart.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",
-			.devname	= "s5pv210-uart.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",
-			.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",
-			.devname	= "s5p-mipi-csis.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",
-			.devname	= "s5p-mipi-csis.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_cam0",
-			.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_cam1",
-			.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",
-			.devname	= "exynos4-fimc.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",
-			.devname	= "exynos4-fimc.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",
-			.devname	= "exynos4-fimc.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",
-			.devname	= "exynos4-fimc.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",
-			.devname	= "exynos4-fb.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",
-			.devname	= "exynos4-fb.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",
-			.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",
-			.devname	= "s3c64xx-spi.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",
-			.devname	= "s3c64xx-spi.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",
-			.devname	= "s3c64xx-spi.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",
-		},
-		.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_mfc",
-			.devname	= "s5p-mfc",
-		},
-		.sources = &clkset_mout_mfc,
-		.reg_src = { .reg = S5P_CLKSRC_MFC, .shift = 8, .size = 1 },
-		.reg_div = { .reg = S5P_CLKDIV_MFC, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mmc",
-			.devname	= "s3c-sdhci.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",
-			.devname	= "s3c-sdhci.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",
-			.devname	= "s3c-sdhci.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",
-			.devname	= "s3c-sdhci.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_dwmmc",
-			.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,
-	&clk_mout_mfc0,
-	&clk_mout_mfc1,
-};
-
-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_4650c);
-
-	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-3.1-gnu/arch/arm/mach-exynos4/cpu.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/cpu.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/cpu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,254 +0,0 @@
-/* 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 <asm/hardware/gic.h>
-
-#include <plat/cpu.h>
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/exynos4.h>
-#include <plat/adc-core.h>
-#include <plat/sdhci.h>
-#include <plat/fb-core.h>
-#include <plat/fimc-core.h>
-#include <plat/iic-core.h>
-#include <plat/reset.h>
-
-#include <mach/regs-irq.h>
-#include <mach/regs-pmu.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,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_USB_HSPHY,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_HSPHY),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GIC_CPU,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
-		.length		= SZ_64K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GIC_DIST,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
-		.length		= SZ_64K,
-		.type		= MT_DEVICE,
-	},
-};
-
-static void exynos4_idle(void)
-{
-	if (!need_resched())
-		cpu_do_idle();
-
-	local_irq_enable();
-}
-
-static void exynos4_sw_reset(void)
-{
-	__raw_writel(0x1, S5P_SWRESET);
-}
-
-/*
- * 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_adc_setname("samsung-adc-v3");
-
-	s3c_fimc_setname(0, "exynos4-fimc");
-	s3c_fimc_setname(1, "exynos4-fimc");
-	s3c_fimc_setname(2, "exynos4-fimc");
-	s3c_fimc_setname(3, "exynos4-fimc");
-
-	/* The I2C bus controllers are directly compatible with s3c2440 */
-	s3c_i2c0_setname("s3c2440-i2c");
-	s3c_i2c1_setname("s3c2440-i2c");
-	s3c_i2c2_setname("s3c2440-i2c");
-
-	s5p_fb_setname(0, "exynos4-fb");
-}
-
-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();
-}
-
-static void exynos4_gic_irq_eoi(struct irq_data *d)
-{
-	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
-
-	gic_data->cpu_base = S5P_VA_GIC_CPU +
-			    (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
-}
-
-void __init exynos4_init_irq(void)
-{
-	int irq;
-
-	gic_init(0, IRQ_SPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
-	gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;
-
-	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
-
-		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;
-
-	/* set sw_reset function */
-	s5p_reset_hook = exynos4_sw_reset;
-
-	return sysdev_register(&exynos4_sysdev);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/cpuidle.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/cpuidle.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/cpuidle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/cpuidle.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,86 +0,0 @@
-/* linux/arch/arm/mach-exynos4/cpuidle.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/kernel.h>
-#include <linux/init.h>
-#include <linux/cpuidle.h>
-#include <linux/io.h>
-
-#include <asm/proc-fns.h>
-
-static int exynos4_enter_idle(struct cpuidle_device *dev,
-			      struct cpuidle_state *state);
-
-static struct cpuidle_state exynos4_cpuidle_set[] = {
-	[0] = {
-		.enter			= exynos4_enter_idle,
-		.exit_latency		= 1,
-		.target_residency	= 100000,
-		.flags			= CPUIDLE_FLAG_TIME_VALID,
-		.name			= "IDLE",
-		.desc			= "ARM clock gating(WFI)",
-	},
-};
-
-static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
-
-static struct cpuidle_driver exynos4_idle_driver = {
-	.name		= "exynos4_idle",
-	.owner		= THIS_MODULE,
-};
-
-static int exynos4_enter_idle(struct cpuidle_device *dev,
-			      struct cpuidle_state *state)
-{
-	struct timeval before, after;
-	int idle_time;
-
-	local_irq_disable();
-	do_gettimeofday(&before);
-
-	cpu_do_idle();
-
-	do_gettimeofday(&after);
-	local_irq_enable();
-	idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
-		    (after.tv_usec - before.tv_usec);
-
-	return idle_time;
-}
-
-static int __init exynos4_init_cpuidle(void)
-{
-	int i, max_cpuidle_state, cpu_id;
-	struct cpuidle_device *device;
-
-	cpuidle_register_driver(&exynos4_idle_driver);
-
-	for_each_cpu(cpu_id, cpu_online_mask) {
-		device = &per_cpu(exynos4_cpuidle_device, cpu_id);
-		device->cpu = cpu_id;
-
-		device->state_count = (sizeof(exynos4_cpuidle_set) /
-					       sizeof(struct cpuidle_state));
-
-		max_cpuidle_state = device->state_count;
-
-		for (i = 0; i < max_cpuidle_state; i++) {
-			memcpy(&device->states[i], &exynos4_cpuidle_set[i],
-					sizeof(struct cpuidle_state));
-		}
-
-		if (cpuidle_register_device(device)) {
-			printk(KERN_ERR "CPUidle register device failed\n,");
-			return -EIO;
-		}
-	}
-	return 0;
-}
-device_initcall(exynos4_init_cpuidle);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/dev-ahci.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/dev-ahci.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/dev-ahci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/dev-ahci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,263 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/dev-audio.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/dev-audio.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/dev-audio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/dev-audio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,369 +0,0 @@
-/* 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>
-#include <mach/regs-audss.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,
-			.idma_addr = EXYNOS4_AUDSS_INT_MEM,
-		},
-	},
-};
-
-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(4));
-
-	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-3.1-gnu/arch/arm/mach-exynos4/dev-dwmci.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/dev-dwmci.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/dev-dwmci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/dev-dwmci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,82 +0,0 @@
-/*
- * linux/arch/arm/mach-exynos4/dev-dwmci.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Platform device for Synopsys DesignWare Mobile Storage IP
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/mmc/dw_mmc.h>
-
-#include <plat/devs.h>
-
-#include <mach/map.h>
-
-static int exynos4_dwmci_get_bus_wd(u32 slot_id)
-{
-	return 4;
-}
-
-static int exynos4_dwmci_init(u32 slot_id, irq_handler_t handler, void *data)
-{
-	return 0;
-}
-
-static struct resource exynos4_dwmci_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_DWMCI,
-		.end	= EXYNOS4_PA_DWMCI + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_DWMCI,
-		.end	= IRQ_DWMCI,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static struct dw_mci_board exynos4_dwci_pdata = {
-	.num_slots			= 1,
-	.quirks				= DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
-	.bus_hz				= 80 * 1000 * 1000,
-	.detect_delay_ms	= 200,
-	.init				= exynos4_dwmci_init,
-	.get_bus_wd			= exynos4_dwmci_get_bus_wd,
-};
-
-static u64 exynos4_dwmci_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device exynos4_device_dwmci = {
-	.name		= "dw_mmc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(exynos4_dwmci_resource),
-	.resource	= exynos4_dwmci_resource,
-	.dev		= {
-		.dma_mask		= &exynos4_dwmci_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-		.platform_data	= &exynos4_dwci_pdata,
-	},
-};
-
-void __init exynos4_dwmci_set_platdata(struct dw_mci_board *pd)
-{
-	struct dw_mci_board *npd;
-
-	npd = s3c_set_platdata(pd, sizeof(struct dw_mci_board),
-			&exynos4_device_dwmci);
-
-	if (!npd->init)
-		npd->init = exynos4_dwmci_init;
-	if (!npd->get_bus_wd)
-		npd->get_bus_wd = exynos4_dwmci_get_bus_wd;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/dev-pd.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/dev-pd.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/dev-pd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/dev-pd.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,139 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/dev-sysmmu.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/dev-sysmmu.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/dev-sysmmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/dev-sysmmu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,232 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/dma.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/dma.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/dma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,172 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/headsmp.S linux-libre-3.2-gnu/arch/arm/mach-exynos4/headsmp.S
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/headsmp.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/headsmp.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-/*
- *  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>
-
-	__CPUINIT
-
-/*
- * 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-3.1-gnu/arch/arm/mach-exynos4/hotplug.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/hotplug.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/hotplug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/hotplug.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,133 +0,0 @@
-/* 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 <linux/io.h>
-
-#include <asm/cacheflush.h>
-
-#include <mach/regs-pmu.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)
-{
-	for (;;) {
-
-		/* make cpu1 to be turned off at next WFI command */
-		if (cpu == 1)
-			__raw_writel(0, S5P_ARM_CORE1_CONFIGURATION);
-
-		/*
-		 * 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-3.1-gnu/arch/arm/mach-exynos4/include/mach/clkdev.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/clkdev.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/clkdev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef __MACH_CLKDEV_H__
-#define __MACH_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do {} while (0)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/include/mach/dma.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/dma.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/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-3.1-gnu/arch/arm/mach-exynos4/include/mach/dwmci.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/dwmci.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/dwmci.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/dwmci.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/dwmci.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Synopsys DesignWare Mobile Storage for EXYNOS4210
- *
- * This program is free software; you can 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_DWMCI_H
-#define __ASM_ARM_ARCH_DWMCI_H __FILE__
-
-#include <linux/mmc/dw_mmc.h>
-
-extern void exynos4_dwmci_set_platdata(struct dw_mci_board *pd);
-
-#endif /* __ASM_ARM_ARCH_DWMCI_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/entry-macro.S linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/entry-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/entry-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-/* 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 <mach/map.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]
-		mrc     p15, 0, \tmp, c0, c0, 5
-		and     \tmp, \tmp, #3
-		cmp     \tmp, #1
-		addeq   \base, \base, #EXYNOS4_GIC_BANK_OFFSET
-		.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
-		.endm
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,156 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/include/mach/hardware.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/hardware.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/hardware.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/include/mach/io.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/io.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/include/mach/irqs.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/irqs.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,163 +0,0 @@
-/* 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)
-
-/* SPI: Shared Peripheral Interrupt */
-
-#define IRQ_SPI(x)		S5P_IRQ(x+32)
-
-#define IRQ_EINT0		IRQ_SPI(16)
-#define IRQ_EINT1		IRQ_SPI(17)
-#define IRQ_EINT2		IRQ_SPI(18)
-#define IRQ_EINT3		IRQ_SPI(19)
-#define IRQ_EINT4		IRQ_SPI(20)
-#define IRQ_EINT5		IRQ_SPI(21)
-#define IRQ_EINT6		IRQ_SPI(22)
-#define IRQ_EINT7		IRQ_SPI(23)
-#define IRQ_EINT8		IRQ_SPI(24)
-#define IRQ_EINT9		IRQ_SPI(25)
-#define IRQ_EINT10		IRQ_SPI(26)
-#define IRQ_EINT11		IRQ_SPI(27)
-#define IRQ_EINT12		IRQ_SPI(28)
-#define IRQ_EINT13		IRQ_SPI(29)
-#define IRQ_EINT14		IRQ_SPI(30)
-#define IRQ_EINT15		IRQ_SPI(31)
-#define IRQ_EINT16_31		IRQ_SPI(32)
-
-#define IRQ_PDMA0		IRQ_SPI(35)
-#define IRQ_PDMA1		IRQ_SPI(36)
-#define IRQ_TIMER0_VIC		IRQ_SPI(37)
-#define IRQ_TIMER1_VIC		IRQ_SPI(38)
-#define IRQ_TIMER2_VIC		IRQ_SPI(39)
-#define IRQ_TIMER3_VIC		IRQ_SPI(40)
-#define IRQ_TIMER4_VIC		IRQ_SPI(41)
-#define IRQ_MCT_L0		IRQ_SPI(42)
-#define IRQ_WDT			IRQ_SPI(43)
-#define IRQ_RTC_ALARM		IRQ_SPI(44)
-#define IRQ_RTC_TIC		IRQ_SPI(45)
-#define IRQ_GPIO_XB		IRQ_SPI(46)
-#define IRQ_GPIO_XA		IRQ_SPI(47)
-#define IRQ_MCT_L1		IRQ_SPI(48)
-
-#define IRQ_UART0		IRQ_SPI(52)
-#define IRQ_UART1		IRQ_SPI(53)
-#define IRQ_UART2		IRQ_SPI(54)
-#define IRQ_UART3		IRQ_SPI(55)
-#define IRQ_UART4		IRQ_SPI(56)
-#define IRQ_MCT_G0		IRQ_SPI(57)
-#define IRQ_IIC			IRQ_SPI(58)
-#define IRQ_IIC1		IRQ_SPI(59)
-#define IRQ_IIC2		IRQ_SPI(60)
-#define IRQ_IIC3		IRQ_SPI(61)
-#define IRQ_IIC4		IRQ_SPI(62)
-#define IRQ_IIC5		IRQ_SPI(63)
-#define IRQ_IIC6		IRQ_SPI(64)
-#define IRQ_IIC7		IRQ_SPI(65)
-
-#define IRQ_USB_HOST		IRQ_SPI(70)
-#define IRQ_USB_HSOTG		IRQ_SPI(71)
-#define IRQ_MODEM_IF		IRQ_SPI(72)
-#define IRQ_HSMMC0		IRQ_SPI(73)
-#define IRQ_HSMMC1		IRQ_SPI(74)
-#define IRQ_HSMMC2		IRQ_SPI(75)
-#define IRQ_HSMMC3		IRQ_SPI(76)
-#define IRQ_DWMCI		IRQ_SPI(77)
-
-#define IRQ_MIPI_CSIS0		IRQ_SPI(78)
-#define IRQ_MIPI_CSIS1		IRQ_SPI(80)
-
-#define IRQ_ONENAND_AUDI	IRQ_SPI(82)
-#define IRQ_ROTATOR		IRQ_SPI(83)
-#define IRQ_FIMC0		IRQ_SPI(84)
-#define IRQ_FIMC1		IRQ_SPI(85)
-#define IRQ_FIMC2		IRQ_SPI(86)
-#define IRQ_FIMC3		IRQ_SPI(87)
-#define IRQ_JPEG		IRQ_SPI(88)
-#define IRQ_2D			IRQ_SPI(89)
-#define IRQ_PCIE		IRQ_SPI(90)
-
-#define IRQ_MFC			IRQ_SPI(94)
-
-#define IRQ_AUDIO_SS		IRQ_SPI(96)
-#define IRQ_I2S0		IRQ_SPI(97)
-#define IRQ_I2S1		IRQ_SPI(98)
-#define IRQ_I2S2		IRQ_SPI(99)
-#define IRQ_AC97		IRQ_SPI(100)
-
-#define IRQ_SPDIF		IRQ_SPI(104)
-#define IRQ_ADC0		IRQ_SPI(105)
-#define IRQ_PEN0		IRQ_SPI(106)
-#define IRQ_ADC1		IRQ_SPI(107)
-#define IRQ_PEN1		IRQ_SPI(108)
-#define IRQ_KEYPAD		IRQ_SPI(109)
-#define IRQ_PMU			IRQ_SPI(110)
-#define IRQ_GPS			IRQ_SPI(111)
-#define IRQ_INTFEEDCTRL_SSS	IRQ_SPI(112)
-#define IRQ_SLIMBUS		IRQ_SPI(113)
-
-#define IRQ_TSI			IRQ_SPI(115)
-#define IRQ_SATA		IRQ_SPI(116)
-
-#define MAX_IRQ_IN_COMBINER	8
-#define COMBINER_GROUP(x)	((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(128))
-#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_FIMD0_FIFO		COMBINER_IRQ(11, 0)
-#define IRQ_FIMD0_VSYNC		COMBINER_IRQ(11, 1)
-#define IRQ_FIMD0_SYSTEM	COMBINER_IRQ(11, 2)
-
-#define MAX_COMBINER_NR		16
-
-#define IRQ_ADC			IRQ_ADC0
-#define IRQ_TC			IRQ_PEN0
-
-#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 + 64)
-
-#endif /* __ASM_ARCH_IRQS_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/map.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/map.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/map.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,179 +0,0 @@
-/* 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		0x10440000
-
-#define EXYNOS4_PA_GIC_CPU		0x10480000
-#define EXYNOS4_PA_GIC_DIST		0x10490000
-#define EXYNOS4_GIC_BANK_OFFSET		0x8000
-
-#define EXYNOS4_PA_COREPERI		0x10500000
-#define EXYNOS4_PA_TWD			0x10500600
-#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_FIMD0		0x11C00000
-
-#define EXYNOS4_PA_HSMMC(x)		(0x12510000 + ((x) * 0x10000))
-#define EXYNOS4_PA_DWMCI		0x12550000
-
-#define EXYNOS4_PA_SATA			0x12560000
-#define EXYNOS4_PA_SATAPHY		0x125D0000
-#define EXYNOS4_PA_SATAPHY_CTRL		0x126B0000
-
-#define EXYNOS4_PA_SROMC		0x12570000
-
-#define EXYNOS4_PA_EHCI			0x12580000
-#define EXYNOS4_PA_HSPHY		0x125B0000
-#define EXYNOS4_PA_MFC			0x13400000
-
-#define EXYNOS4_PA_UART			0x13800000
-
-#define EXYNOS4_PA_IIC(x)		(0x13860000 + ((x) * 0x10000))
-
-#define EXYNOS4_PA_ADC			0x13910000
-#define EXYNOS4_PA_ADC1			0x13911000
-
-#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 SAMSUNG_PA_ADC			EXYNOS4_PA_ADC
-#define SAMSUNG_PA_ADC1			EXYNOS4_PA_ADC1
-#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_FIMD0			EXYNOS4_PA_FIMD0
-#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_MFC			EXYNOS4_PA_MFC
-#define S5P_PA_SYSCON			EXYNOS4_PA_SYSCON
-#define S5P_PA_TIMER			EXYNOS4_PA_TIMER
-#define S5P_PA_EHCI			EXYNOS4_PA_EHCI
-
-#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-3.1-gnu/arch/arm/mach-exynos4/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/include/mach/pm-core.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/pm-core.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/pm-core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/pm-core.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,59 +0,0 @@
-/* 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 */
-}
-
-static inline void s3c_pm_restored_gpios(void)
-{
-	/* nothing here yet */
-}
-
-static inline void s3c_pm_saved_gpios(void)
-{
-	/* nothing here yet */
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/pmu.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/pmu.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/pmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/pmu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,25 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/pmu.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * EXYNOS4210 - PMU(Power Management Unit) 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_PMU_H
-#define __ASM_ARCH_PMU_H __FILE__
-
-enum sys_powerdown {
-	SYS_AFTR,
-	SYS_LPA,
-	SYS_SLEEP,
-	NUM_SYS_POWERDOWN,
-};
-
-extern void exynos4_sys_powerdown_conf(enum sys_powerdown mode);
-
-#endif /* __ASM_ARCH_PMU_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/pwm-clock.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/pwm-clock.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/pwm-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/pwm-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-audss.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-audss.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-audss.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-audss.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/* arch/arm/mach-exynos4/include/mach/regs-audss.h
- *
- * Copyright (c) 2011 Samsung Electronics
- *		http://www.samsung.com
- *
- * Exynos4 Audio SubSystem 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 __PLAT_REGS_AUDSS_H
-#define __PLAT_REGS_AUDSS_H __FILE__
-
-#define EXYNOS4_AUDSS_INT_MEM	(0x03000000)
-
-#endif /* _PLAT_REGS_AUDSS_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-clock.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-clock.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,192 +0,0 @@
-/* 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_LOCK			S5P_CLKREG(0x0C010)
-#define S5P_VPLL_LOCK			S5P_CLKREG(0x0C020)
-
-#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_TV			S5P_CLKREG(0x0C224)
-#define S5P_CLKSRC_MFC			S5P_CLKREG(0x0C228)
-#define S5P_CLKSRC_G3D			S5P_CLKREG(0x0C22C)
-#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_CLKDIV2_RATIO		S5P_CLKREG(0x0C580)
-
-#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_EPLLCON0_ENABLE_SHIFT	(31)
-#define S5P_EPLLCON0_LOCKED_SHIFT	(29)
-
-#define S5P_VPLLCON0_ENABLE_SHIFT	(31)
-#define S5P_VPLLCON0_LOCKED_SHIFT	(29)
-
-#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-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-gpio.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-irq.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-irq.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-irq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-mct.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-mct.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-mct.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-mct.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-mem.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-mem.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-mem.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-mem.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-pmu.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-pmu.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-pmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-pmu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,168 +0,0 @@
-/* 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_SWRESET				S5P_PMUREG(0x0400)
-
-#define S5P_WAKEUP_STAT				S5P_PMUREG(0x0600)
-#define S5P_EINT_WAKEUP_MASK			S5P_PMUREG(0x0604)
-#define S5P_WAKEUP_MASK				S5P_PMUREG(0x0608)
-
-#define S5P_USBHOST_PHY_CONTROL			S5P_PMUREG(0x0708)
-#define S5P_USBHOST_PHY_ENABLE			(1 << 0)
-
-#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_CORE_LOCAL_PWR_EN			0x3
-#define S5P_INT_LOCAL_PWR_EN			0x7
-
-#define S5P_CHECK_SLEEP				0x00000BAD
-
-#endif /* __ASM_ARCH_REGS_PMU_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#ifndef __PLAT_S5P_REGS_USB_PHY_H
-#define __PLAT_S5P_REGS_USB_PHY_H
-
-#define EXYNOS4_HSOTG_PHYREG(x)		((x) + S3C_VA_USB_HSPHY)
-
-#define EXYNOS4_PHYPWR			EXYNOS4_HSOTG_PHYREG(0x00)
-#define PHY1_HSIC_NORMAL_MASK		(0xf << 9)
-#define PHY1_HSIC1_SLEEP		(1 << 12)
-#define PHY1_HSIC1_FORCE_SUSPEND	(1 << 11)
-#define PHY1_HSIC0_SLEEP		(1 << 10)
-#define PHY1_HSIC0_FORCE_SUSPEND	(1 << 9)
-
-#define PHY1_STD_NORMAL_MASK		(0x7 << 6)
-#define PHY1_STD_SLEEP			(1 << 8)
-#define PHY1_STD_ANALOG_POWERDOWN	(1 << 7)
-#define PHY1_STD_FORCE_SUSPEND		(1 << 6)
-
-#define PHY0_NORMAL_MASK		(0x39 << 0)
-#define PHY0_SLEEP			(1 << 5)
-#define PHY0_OTG_DISABLE		(1 << 4)
-#define PHY0_ANALOG_POWERDOWN		(1 << 3)
-#define PHY0_FORCE_SUSPEND		(1 << 0)
-
-#define EXYNOS4_PHYCLK			EXYNOS4_HSOTG_PHYREG(0x04)
-#define PHY1_COMMON_ON_N		(1 << 7)
-#define PHY0_COMMON_ON_N		(1 << 4)
-#define PHY0_ID_PULLUP			(1 << 2)
-#define CLKSEL_MASK			(0x3 << 0)
-#define CLKSEL_SHIFT			(0)
-#define CLKSEL_48M			(0x0 << 0)
-#define CLKSEL_12M			(0x2 << 0)
-#define CLKSEL_24M			(0x3 << 0)
-
-#define EXYNOS4_RSTCON			EXYNOS4_HSOTG_PHYREG(0x08)
-#define HOST_LINK_PORT_SWRST_MASK	(0xf << 6)
-#define HOST_LINK_PORT2_SWRST		(1 << 9)
-#define HOST_LINK_PORT1_SWRST		(1 << 8)
-#define HOST_LINK_PORT0_SWRST		(1 << 7)
-#define HOST_LINK_ALL_SWRST		(1 << 6)
-
-#define PHY1_SWRST_MASK			(0x7 << 3)
-#define PHY1_HSIC_SWRST			(1 << 5)
-#define PHY1_STD_SWRST			(1 << 4)
-#define PHY1_ALL_SWRST			(1 << 3)
-
-#define PHY0_SWRST_MASK			(0x7 << 0)
-#define PHY0_PHYLINK_SWRST		(1 << 2)
-#define PHY0_HLINK_SWRST		(1 << 1)
-#define PHY0_SWRST			(1 << 0)
-
-#define EXYNOS4_PHY1CON			EXYNOS4_HSOTG_PHYREG(0x34)
-#define FPENABLEN			(1 << 0)
-
-#endif /* __PLAT_S5P_REGS_USB_PHY_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/sysmmu.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/sysmmu.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/sysmmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/sysmmu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/include/mach/system.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/system.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/include/mach/timex.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/timex.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/timex.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/include/mach/uncompress.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/uncompress.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/uncompress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,30 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/include/mach/vmalloc.h linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/vmalloc.h
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/include/mach/vmalloc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/init.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/init.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/init.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-/* 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);
-		}
-		tcfg->flags |= NO_NEED_CHECK_CLKSRC;
-	}
-
-	s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/irq-combiner.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/irq-combiner.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/irq-combiner.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/irq-combiner.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,124 +0,0 @@
-/* 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;
-
-	chained_irq_enter(chip, desc);
-
-	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:
-	chained_irq_exit(chip, desc);
-}
-
-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-3.1-gnu/arch/arm/mach-exynos4/irq-eint.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/irq-eint.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/irq-eint.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/irq-eint.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,237 +0,0 @@
-/* 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>
-
-#include <asm/mach/irq.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)
-{
-	struct irq_chip *chip = irq_get_chip(irq);
-	chained_irq_enter(chip, desc);
-	exynos4_irq_demux_eint(IRQ_EINT(16));
-	exynos4_irq_demux_eint(IRQ_EINT(24));
-	chained_irq_exit(chip, desc);
-}
-
-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);
-
-	chained_irq_enter(chip, desc);
-	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);
-	chained_irq_exit(chip, desc);
-}
-
-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-3.1-gnu/arch/arm/mach-exynos4/Kconfig linux-libre-3.2-gnu/arch/arm/mach-exynos4/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,241 +0,0 @@
-# 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
-	default y
-	help
-	  Use MCT (Multi Core Timer) as kernel timers
-
-config EXYNOS4_DEV_AHCI
-	bool
-	help
-	  Compile in platform device definitions for AHCI
-
-config EXYNOS4_SETUP_FIMD0
-	bool
-	help
-	  Common setup code for FIMD0.
-
-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_DEV_DWMCI
-	bool
-	help
-	  Compile in platform device definitions for DWMCI
-
-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.
-
-config EXYNOS4_SETUP_USB_PHY
-	bool
-	help
-	  Common setup code for USB PHY controller
-
-# machine support
-
-menu "EXYNOS4 Machines"
-
-config MACH_SMDKC210
-	bool "SMDKC210"
-	select CPU_EXYNOS4210
-	select S5P_DEV_FIMD0
-	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_PWM
-	select SAMSUNG_DEV_BACKLIGHT
-	select EXYNOS4_DEV_PD
-	select EXYNOS4_DEV_SYSMMU
-	select EXYNOS4_SETUP_FIMD0
-	select EXYNOS4_SETUP_I2C1
-	select EXYNOS4_SETUP_SDHCI
-	help
-	  Machine support for Samsung SMDKC210
-
-config MACH_SMDKV310
-	bool "SMDKV310"
-	select CPU_EXYNOS4210
-	select S5P_DEV_FIMD0
-	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_BACKLIGHT
-	select EXYNOS4_DEV_AHCI
-	select SAMSUNG_DEV_KEYPAD
-	select EXYNOS4_DEV_PD
-	select SAMSUNG_DEV_PWM
-	select EXYNOS4_DEV_SYSMMU
-	select EXYNOS4_SETUP_FIMD0
-	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 S5P_GPIO_INT
-	select S5P_DEV_FIMC0
-	select S5P_DEV_FIMC1
-	select S5P_DEV_FIMC2
-	select S5P_DEV_FIMC3
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_HSMMC3
-	select S3C_DEV_I2C1
-	select S3C_DEV_I2C3
-	select S3C_DEV_I2C5
-	select S5P_DEV_MFC
-	select S5P_DEV_ONENAND
-	select EXYNOS4_DEV_PD
-	select EXYNOS4_SETUP_I2C1
-	select EXYNOS4_SETUP_I2C3
-	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_I2C3
-	select S3C_DEV_I2C5
-	select S5P_DEV_MFC
-	select S5P_DEV_USB_EHCI
-	select EXYNOS4_DEV_PD
-	select EXYNOS4_SETUP_I2C1
-	select EXYNOS4_SETUP_I2C3
-	select EXYNOS4_SETUP_I2C5
-	select EXYNOS4_SETUP_SDHCI
-	select EXYNOS4_SETUP_USB_PHY
-	select SAMSUNG_DEV_PWM
-	select SAMSUNG_DEV_ADC
-	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-3.1-gnu/arch/arm/mach-exynos4/mach-armlex4210.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/mach-armlex4210.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/mach-armlex4210.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/mach-armlex4210.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,215 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/mach-nuri.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/mach-nuri.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/mach-nuri.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/mach-nuri.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1161 +0,0 @@
-/*
- * 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/i2c/atmel_mxt_ts.h>
-#include <linux/i2c-gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/gpio.h>
-#include <linux/power/max8903_charger.h>
-#include <linux/power/max17042_battery.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-#include <linux/mfd/max8997.h>
-#include <linux/mfd/max8997-private.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/adc.h>
-#include <plat/regs-serial.h>
-#include <plat/exynos4.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/sdhci.h>
-#include <plat/ehci.h>
-#include <plat/clock.h>
-#include <plat/gpio-cfg.h>
-#include <plat/iic.h>
-#include <plat/mfc.h>
-#include <plat/pd.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,
-	FIXED_REG_ID_MAX8903,
-};
-
-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 */
-};
-
-/* TSP */
-static u8 mxt_init_vals[] = {
-	/* MXT_GEN_COMMAND(6) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* MXT_GEN_POWER(7) */
-	0x20, 0xff, 0x32,
-	/* MXT_GEN_ACQUIRE(8) */
-	0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23,
-	/* MXT_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,
-	/* MXT_TOUCH_KEYARRAY(15) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
-	0x00,
-	/* MXT_SPT_GPIOPWM(19) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* MXT_PROCI_GRIPFACE(20) */
-	0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04,
-	0x0f, 0x0a,
-	/* MXT_PROCG_NOISE(22) */
-	0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00,
-	0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03,
-	/* MXT_TOUCH_PROXIMITY(23) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00,
-	/* MXT_PROCI_ONETOUCH(24) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* MXT_SPT_SELFTEST(25) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00,
-	/* MXT_PROCI_TWOTOUCH(27) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* MXT_SPT_CTECONFIG(28) */
-	0x00, 0x00, 0x02, 0x08, 0x10, 0x00,
-};
-
-static struct mxt_platform_data mxt_platform_data = {
-	.config			= mxt_init_vals,
-	.config_length		= ARRAY_SIZE(mxt_init_vals),
-
-	.x_line			= 18,
-	.y_line			= 11,
-	.x_size			= 1024,
-	.y_size			= 600,
-	.blen			= 0x1,
-	.threshold		= 0x28,
-	.voltage		= 2800000,		/* 2.8V */
-	.orient			= MXT_DIAGONAL_COUNTER,
-	.irqflags		= IRQF_TRIGGER_FALLING,
-};
-
-static struct s3c2410_platform_i2c i2c3_data __initdata = {
-	.flags		= 0,
-	.bus_num	= 3,
-	.slave_addr	= 0x10,
-	.frequency	= 400 * 1000,
-	.sda_delay	= 100,
-};
-
-static struct i2c_board_info i2c3_devs[] __initdata = {
-	{
-		I2C_BOARD_INFO("atmel_mxt_ts", 0x4a),
-		.platform_data	= &mxt_platform_data,
-		.irq		= IRQ_EINT(4),
-	},
-};
-
-static void __init nuri_tsp_init(void)
-{
-	int gpio;
-
-	/* TOUCH_INT: XEINT_4 */
-	gpio = EXYNOS4_GPX0(4);
-	gpio_request(gpio, "TOUCH_INT");
-	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-}
-
-static struct regulator_consumer_supply __initdata max8997_ldo1_[] = {
-	REGULATOR_SUPPLY("vdd", "s5p-adc"), /* Used by CPU's ADC drv */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo3_[] = {
-	REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo4_[] = {
-	REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo5_[] = {
-	REGULATOR_SUPPLY("vhsic", "modemctl"), /* MODEM */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo7_[] = {
-	REGULATOR_SUPPLY("dig_18", "0-001f"), /* HCD803 */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo8_[] = {
-	REGULATOR_SUPPLY("vusb_d", NULL), /* Used by CPU */
-	REGULATOR_SUPPLY("vdac", NULL), /* Used by CPU */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo11_[] = {
-	REGULATOR_SUPPLY("vcc", "platform-lcd"), /* U804 LVDS */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo12_[] = {
-	REGULATOR_SUPPLY("vddio", "6-003c"), /* HDC802 */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo13_[] = {
-	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"), /* TFLASH */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo14_[] = {
-	REGULATOR_SUPPLY("inmotor", "max8997-haptic"),
-};
-static struct regulator_consumer_supply __initdata max8997_ldo15_[] = {
-	REGULATOR_SUPPLY("avdd", "3-004a"), /* Touch Screen */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo16_[] = {
-	REGULATOR_SUPPLY("d_sensor", "0-001f"), /* HDC803 */
-};
-static struct regulator_consumer_supply __initdata max8997_ldo18_[] = {
-	REGULATOR_SUPPLY("vdd", "3-004a"), /* Touch Screen */
-};
-static struct regulator_consumer_supply __initdata max8997_buck1_[] = {
-	REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */
-};
-static struct regulator_consumer_supply __initdata max8997_buck2_[] = {
-	REGULATOR_SUPPLY("vdd_int", NULL), /* CPUFREQ */
-};
-static struct regulator_consumer_supply __initdata max8997_buck3_[] = {
-	REGULATOR_SUPPLY("vdd", "mali_dev.0"), /* G3D of Exynos 4 */
-};
-static struct regulator_consumer_supply __initdata max8997_buck4_[] = {
-	REGULATOR_SUPPLY("core", "0-001f"), /* HDC803 */
-};
-static struct regulator_consumer_supply __initdata max8997_buck6_[] = {
-	REGULATOR_SUPPLY("dig_28", "0-001f"), /* pin "7" of HDC803 */
-};
-static struct regulator_consumer_supply __initdata max8997_esafeout1_[] = {
-	REGULATOR_SUPPLY("usb_vbus", NULL), /* CPU's USB OTG */
-};
-static struct regulator_consumer_supply __initdata max8997_esafeout2_[] = {
-	REGULATOR_SUPPLY("usb_vbus", "modemctl"), /* VBUS of Modem */
-};
-
-static struct regulator_consumer_supply __initdata max8997_charger_[] = {
-	REGULATOR_SUPPLY("vinchg1", "charger-manager.0"),
-};
-static struct regulator_consumer_supply __initdata max8997_chg_toff_[] = {
-	REGULATOR_SUPPLY("vinchg_stop", NULL), /* for jack interrupt handlers */
-};
-
-static struct regulator_consumer_supply __initdata max8997_32khz_ap_[] = {
-	REGULATOR_SUPPLY("gps_clk", "bcm4751"),
-	REGULATOR_SUPPLY("bt_clk", "bcm4330-b1"),
-	REGULATOR_SUPPLY("wifi_clk", "bcm433-b1"),
-};
-
-static struct regulator_init_data __initdata max8997_ldo1_data = {
-	.constraints	= {
-		.name		= "VADC_3.3V_C210",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo1_),
-	.consumer_supplies	= max8997_ldo1_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo2_data = {
-	.constraints	= {
-		.name		= "VALIVE_1.1V_C210",
-		.min_uV		= 1100000,
-		.max_uV		= 1100000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_ldo3_data = {
-	.constraints	= {
-		.name		= "VUSB_1.1V_C210",
-		.min_uV		= 1100000,
-		.max_uV		= 1100000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo3_),
-	.consumer_supplies	= max8997_ldo3_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo4_data = {
-	.constraints	= {
-		.name		= "VMIPI_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo4_),
-	.consumer_supplies	= max8997_ldo4_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo5_data = {
-	.constraints	= {
-		.name		= "VHSIC_1.2V_C210",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo5_),
-	.consumer_supplies	= max8997_ldo5_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo6_data = {
-	.constraints	= {
-		.name		= "VCC_1.8V_PDA",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_ldo7_data = {
-	.constraints	= {
-		.name		= "CAM_ISP_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo7_),
-	.consumer_supplies	= max8997_ldo7_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo8_data = {
-	.constraints	= {
-		.name		= "VUSB/VDAC_3.3V_C210",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo8_),
-	.consumer_supplies	= max8997_ldo8_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo9_data = {
-	.constraints	= {
-		.name		= "VCC_2.8V_PDA",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_ldo10_data = {
-	.constraints	= {
-		.name		= "VPLL_1.1V_C210",
-		.min_uV		= 1100000,
-		.max_uV		= 1100000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_ldo11_data = {
-	.constraints	= {
-		.name		= "LVDS_VDD3.3V",
-		.min_uV		= 3300000,
-		.max_uV		= 3300000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.boot_on	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo11_),
-	.consumer_supplies	= max8997_ldo11_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo12_data = {
-	.constraints	= {
-		.name		= "VT_CAM_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo12_),
-	.consumer_supplies	= max8997_ldo12_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo13_data = {
-	.constraints	= {
-		.name		= "VTF_2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo13_),
-	.consumer_supplies	= max8997_ldo13_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo14_data = {
-	.constraints	= {
-		.name		= "VCC_3.0V_MOTOR",
-		.min_uV		= 3000000,
-		.max_uV		= 3000000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo14_),
-	.consumer_supplies	= max8997_ldo14_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo15_data = {
-	.constraints	= {
-		.name		= "VTOUCH_ADVV2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo15_),
-	.consumer_supplies	= max8997_ldo15_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo16_data = {
-	.constraints	= {
-		.name		= "CAM_SENSOR_IO_1.8V",
-		.min_uV		= 1800000,
-		.max_uV		= 1800000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo16_),
-	.consumer_supplies	= max8997_ldo16_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo18_data = {
-	.constraints	= {
-		.name		= "VTOUCH_VDD2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.apply_uV	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo18_),
-	.consumer_supplies	= max8997_ldo18_,
-};
-
-static struct regulator_init_data __initdata max8997_ldo21_data = {
-	.constraints	= {
-		.name		= "VDDQ_M1M2_1.2V",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_buck1_data = {
-	.constraints	= {
-		.name		= "VARM_1.2V_C210",
-		.min_uV		= 900000,
-		.max_uV		= 1350000,
-		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
-		.always_on	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies = ARRAY_SIZE(max8997_buck1_),
-	.consumer_supplies = max8997_buck1_,
-};
-
-static struct regulator_init_data __initdata max8997_buck2_data = {
-	.constraints	= {
-		.name		= "VINT_1.1V_C210",
-		.min_uV		= 900000,
-		.max_uV		= 1100000,
-		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
-		.always_on	= 1,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies = ARRAY_SIZE(max8997_buck2_),
-	.consumer_supplies = max8997_buck2_,
-};
-
-static struct regulator_init_data __initdata max8997_buck3_data = {
-	.constraints	= {
-		.name		= "VG3D_1.1V_C210",
-		.min_uV		= 900000,
-		.max_uV		= 1100000,
-		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
-				  REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies = ARRAY_SIZE(max8997_buck3_),
-	.consumer_supplies = max8997_buck3_,
-};
-
-static struct regulator_init_data __initdata max8997_buck4_data = {
-	.constraints	= {
-		.name		= "CAM_ISP_CORE_1.2V",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies = ARRAY_SIZE(max8997_buck4_),
-	.consumer_supplies = max8997_buck4_,
-};
-
-static struct regulator_init_data __initdata max8997_buck5_data = {
-	.constraints	= {
-		.name		= "VMEM_1.2V_C210",
-		.min_uV		= 1200000,
-		.max_uV		= 1200000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_buck6_data = {
-	.constraints	= {
-		.name		= "CAM_AF_2.8V",
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies = ARRAY_SIZE(max8997_buck6_),
-	.consumer_supplies = max8997_buck6_,
-};
-
-static struct regulator_init_data __initdata max8997_buck7_data = {
-	.constraints	= {
-		.name		= "VCC_SUB_2.0V",
-		.min_uV		= 2000000,
-		.max_uV		= 2000000,
-		.apply_uV	= 1,
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_32khz_ap_data = {
-	.constraints	= {
-		.name		= "32KHz AP",
-		.always_on	= 1,
-		.state_mem	= {
-			.enabled	= 1,
-		},
-	},
-	.num_consumer_supplies = ARRAY_SIZE(max8997_32khz_ap_),
-	.consumer_supplies = max8997_32khz_ap_,
-};
-
-static struct regulator_init_data __initdata max8997_32khz_cp_data = {
-	.constraints	= {
-		.name		= "32KHz CP",
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_vichg_data = {
-	.constraints	= {
-		.name		= "VICHG",
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-};
-
-static struct regulator_init_data __initdata max8997_esafeout1_data = {
-	.constraints	= {
-		.name		= "SAFEOUT1",
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_esafeout1_),
-	.consumer_supplies	= max8997_esafeout1_,
-};
-
-static struct regulator_init_data __initdata max8997_esafeout2_data = {
-	.constraints	= {
-		.name		= "SAFEOUT2",
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-		.state_mem	= {
-			.disabled	= 1,
-		},
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_esafeout2_),
-	.consumer_supplies	= max8997_esafeout2_,
-};
-
-static struct regulator_init_data __initdata max8997_charger_cv_data = {
-	.constraints	= {
-		.name		= "CHARGER_CV",
-		.min_uV		= 4200000,
-		.max_uV		= 4200000,
-		.apply_uV	= 1,
-	},
-};
-
-static struct regulator_init_data __initdata max8997_charger_data = {
-	.constraints	= {
-		.name		= "CHARGER",
-		.min_uA		= 200000,
-		.max_uA		= 950000,
-		.boot_on	= 1,
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS |
-				REGULATOR_CHANGE_CURRENT,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_charger_),
-	.consumer_supplies	= max8997_charger_,
-};
-
-static struct regulator_init_data __initdata max8997_charger_topoff_data = {
-	.constraints	= {
-		.name		= "CHARGER TOPOFF",
-		.min_uA		= 50000,
-		.max_uA		= 200000,
-		.valid_ops_mask = REGULATOR_CHANGE_CURRENT,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(max8997_chg_toff_),
-	.consumer_supplies	= max8997_chg_toff_,
-};
-
-static struct max8997_regulator_data __initdata nuri_max8997_regulators[] = {
-	{ MAX8997_LDO1, &max8997_ldo1_data },
-	{ MAX8997_LDO2, &max8997_ldo2_data },
-	{ MAX8997_LDO3, &max8997_ldo3_data },
-	{ MAX8997_LDO4, &max8997_ldo4_data },
-	{ MAX8997_LDO5, &max8997_ldo5_data },
-	{ MAX8997_LDO6, &max8997_ldo6_data },
-	{ MAX8997_LDO7, &max8997_ldo7_data },
-	{ MAX8997_LDO8, &max8997_ldo8_data },
-	{ MAX8997_LDO9, &max8997_ldo9_data },
-	{ MAX8997_LDO10, &max8997_ldo10_data },
-	{ MAX8997_LDO11, &max8997_ldo11_data },
-	{ MAX8997_LDO12, &max8997_ldo12_data },
-	{ MAX8997_LDO13, &max8997_ldo13_data },
-	{ MAX8997_LDO14, &max8997_ldo14_data },
-	{ MAX8997_LDO15, &max8997_ldo15_data },
-	{ MAX8997_LDO16, &max8997_ldo16_data },
-
-	{ MAX8997_LDO18, &max8997_ldo18_data },
-	{ MAX8997_LDO21, &max8997_ldo21_data },
-
-	{ MAX8997_BUCK1, &max8997_buck1_data },
-	{ MAX8997_BUCK2, &max8997_buck2_data },
-	{ MAX8997_BUCK3, &max8997_buck3_data },
-	{ MAX8997_BUCK4, &max8997_buck4_data },
-	{ MAX8997_BUCK5, &max8997_buck5_data },
-	{ MAX8997_BUCK6, &max8997_buck6_data },
-	{ MAX8997_BUCK7, &max8997_buck7_data },
-
-	{ MAX8997_EN32KHZ_AP, &max8997_32khz_ap_data },
-	{ MAX8997_EN32KHZ_CP, &max8997_32khz_cp_data },
-
-	{ MAX8997_ENVICHG, &max8997_vichg_data },
-	{ MAX8997_ESAFEOUT1, &max8997_esafeout1_data },
-	{ MAX8997_ESAFEOUT2, &max8997_esafeout2_data },
-	{ MAX8997_CHARGER_CV, &max8997_charger_cv_data },
-	{ MAX8997_CHARGER, &max8997_charger_data },
-	{ MAX8997_CHARGER_TOPOFF, &max8997_charger_topoff_data },
-};
-
-static struct max8997_platform_data __initdata nuri_max8997_pdata = {
-	.wakeup			= 1,
-
-	.num_regulators		= ARRAY_SIZE(nuri_max8997_regulators),
-	.regulators		= nuri_max8997_regulators,
-
-	.buck125_gpios = { EXYNOS4_GPX0(5), EXYNOS4_GPX0(6), EXYNOS4_GPL0(0) },
-	.buck2_gpiodvs = true,
-
-	.buck1_voltage[0] = 1350000, /* 1.35V */
-	.buck1_voltage[1] = 1300000, /* 1.3V */
-	.buck1_voltage[2] = 1250000, /* 1.25V */
-	.buck1_voltage[3] = 1200000, /* 1.2V */
-	.buck1_voltage[4] = 1150000, /* 1.15V */
-	.buck1_voltage[5] = 1100000, /* 1.1V */
-	.buck1_voltage[6] = 1000000, /* 1.0V */
-	.buck1_voltage[7] = 950000, /* 0.95V */
-
-	.buck2_voltage[0] = 1100000, /* 1.1V */
-	.buck2_voltage[1] = 1000000, /* 1.0V */
-	.buck2_voltage[2] = 950000, /* 0.95V */
-	.buck2_voltage[3] = 900000, /* 0.9V */
-	.buck2_voltage[4] = 1100000, /* 1.1V */
-	.buck2_voltage[5] = 1000000, /* 1.0V */
-	.buck2_voltage[6] = 950000, /* 0.95V */
-	.buck2_voltage[7] = 900000, /* 0.9V */
-
-	.buck5_voltage[0] = 1200000, /* 1.2V */
-	.buck5_voltage[1] = 1200000, /* 1.2V */
-	.buck5_voltage[2] = 1200000, /* 1.2V */
-	.buck5_voltage[3] = 1200000, /* 1.2V */
-	.buck5_voltage[4] = 1200000, /* 1.2V */
-	.buck5_voltage[5] = 1200000, /* 1.2V */
-	.buck5_voltage[6] = 1200000, /* 1.2V */
-	.buck5_voltage[7] = 1200000, /* 1.2V */
-};
-
-/* GPIO I2C 5 (PMIC) */
-enum { I2C5_MAX8997 };
-static struct i2c_board_info i2c5_devs[] __initdata = {
-	[I2C5_MAX8997] = {
-		I2C_BOARD_INFO("max8997", 0xCC >> 1),
-		.platform_data	= &nuri_max8997_pdata,
-	},
-};
-
-static struct max17042_platform_data nuri_battery_platform_data = {
-};
-
-/* GPIO I2C 9 (Fuel Gauge) */
-static struct i2c_gpio_platform_data i2c9_gpio_data = {
-	.sda_pin		= EXYNOS4_GPY4(0),      /* XM0ADDR_8 */
-	.scl_pin		= EXYNOS4_GPY4(1),      /* XM0ADDR_9 */
-};
-static struct platform_device i2c9_gpio = {
-	.name			= "i2c-gpio",
-	.id			= 9,
-	.dev			= {
-		.platform_data	= &i2c9_gpio_data,
-	},
-};
-enum { I2C9_MAX17042};
-static struct i2c_board_info i2c9_devs[] __initdata = {
-	[I2C9_MAX17042] = {
-		I2C_BOARD_INFO("max17042", 0x36),
-		.platform_data = &nuri_battery_platform_data,
-	},
-};
-
-/* MAX8903 Secondary Charger */
-static struct regulator_consumer_supply supplies_max8903[] = {
-	REGULATOR_SUPPLY("vinchg2", "charger-manager.0"),
-};
-
-static struct regulator_init_data max8903_charger_en_data = {
-	.constraints = {
-		.name		= "VOUT_CHARGER",
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		.boot_on	= 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(supplies_max8903),
-	.consumer_supplies = supplies_max8903,
-};
-
-static struct fixed_voltage_config max8903_charger_en = {
-	.supply_name = "VOUT_CHARGER",
-	.microvolts = 5000000, /* Assume 5VDC */
-	.gpio = EXYNOS4_GPY4(5), /* TA_EN negaged */
-	.enable_high = 0, /* Enable = Low */
-	.enabled_at_boot = 1,
-	.init_data = &max8903_charger_en_data,
-};
-
-static struct platform_device max8903_fixed_reg_dev = {
-	.name = "reg-fixed-voltage",
-	.id = FIXED_REG_ID_MAX8903,
-	.dev = { .platform_data	= &max8903_charger_en },
-};
-
-static struct max8903_pdata nuri_max8903 = {
-	/*
-	 * cen: don't control with the driver, let it be
-	 * controlled by regulator above
-	 */
-	.dok = EXYNOS4_GPX1(4), /* TA_nCONNECTED */
-	/* uok, usus: not connected */
-	.chg = EXYNOS4_GPE2(0), /* TA_nCHG */
-	/* flt: vcc_1.8V_pda */
-	.dcm = EXYNOS4_GPL0(1), /* CURR_ADJ */
-
-	.dc_valid = true,
-	.usb_valid = false, /* USB is not wired to MAX8903 */
-};
-
-static struct platform_device nuri_max8903_device = {
-	.name			= "max8903-charger",
-	.dev			= {
-		.platform_data	= &nuri_max8903,
-	},
-};
-
-static struct device *nuri_cm_devices[] = {
-	&s3c_device_i2c5.dev,
-	&s3c_device_adc.dev,
-	NULL, /* Reserved for UART */
-	NULL,
-};
-
-static void __init nuri_power_init(void)
-{
-	int gpio;
-	int irq_base = IRQ_GPIO_END + 1;
-	int ta_en = 0;
-
-	nuri_max8997_pdata.irq_base = irq_base;
-	irq_base += MAX8997_IRQ_NR;
-
-	gpio = EXYNOS4_GPX0(7);
-	gpio_request(gpio, "AP_PMIC_IRQ");
-	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-
-	gpio = EXYNOS4_GPX2(3);
-	gpio_request(gpio, "FUEL_ALERT");
-	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-
-	gpio = nuri_max8903.dok;
-	gpio_request(gpio, "TA_nCONNECTED");
-	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-	ta_en = gpio_get_value(gpio) ? 0 : 1;
-
-	gpio = nuri_max8903.chg;
-	gpio_request(gpio, "TA_nCHG");
-	gpio_direction_input(gpio);
-
-	gpio = nuri_max8903.dcm;
-	gpio_request(gpio, "CURR_ADJ");
-	gpio_direction_output(gpio, ta_en);
-}
-
-/* USB EHCI */
-static struct s5p_ehci_platdata nuri_ehci_pdata;
-
-static void __init nuri_ehci_init(void)
-{
-	struct s5p_ehci_platdata *pdata = &nuri_ehci_pdata;
-
-	s5p_ehci_set_platdata(pdata);
-}
-
-static struct platform_device *nuri_devices[] __initdata = {
-	/* Samsung Platform Devices */
-	&s3c_device_i2c5, /* PMIC should initialize first */
-	&emmc_fixed_voltage,
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc2,
-	&s3c_device_hsmmc3,
-	&s3c_device_wdt,
-	&s3c_device_timer[0],
-	&s5p_device_ehci,
-	&s3c_device_i2c3,
-	&i2c9_gpio,
-	&s3c_device_adc,
-	&s3c_device_rtc,
-	&s5p_device_mfc,
-	&s5p_device_mfc_l,
-	&s5p_device_mfc_r,
-	&exynos4_device_pd[PD_MFC],
-
-	/* NURI Devices */
-	&nuri_gpio_keys,
-	&nuri_lcd_device,
-	&nuri_backlight_device,
-	&max8903_fixed_reg_dev,
-	&nuri_max8903_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_reserve(void)
-{
-	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
-}
-
-static void __init nuri_machine_init(void)
-{
-	nuri_sdhci_init();
-	nuri_tsp_init();
-	nuri_power_init();
-
-	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
-	s3c_i2c3_set_platdata(&i2c3_data);
-	i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
-	s3c_i2c5_set_platdata(NULL);
-	i2c5_devs[I2C5_MAX8997].irq = gpio_to_irq(EXYNOS4_GPX0(7));
-	i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
-	i2c9_devs[I2C9_MAX17042].irq = gpio_to_irq(EXYNOS4_GPX2(3));
-	i2c_register_board_info(9, i2c9_devs, ARRAY_SIZE(i2c9_devs));
-
-	nuri_ehci_init();
-	clk_xusbxti.rate = 24000000;
-
-	/* Last */
-	platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
-	s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
-}
-
-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,
-	.reserve        = &nuri_reserve,
-MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/mach-smdkc210.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/mach-smdkc210.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/mach-smdkc210.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/mach-smdkc210.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,309 +0,0 @@
-/* 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/delay.h>
-#include <linux/gpio.h>
-#include <linux/lcd.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/pwm_backlight.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include <video/platform_lcd.h>
-
-#include <plat/regs-serial.h>
-#include <plat/regs-srom.h>
-#include <plat/regs-fb-v4.h>
-#include <plat/exynos4.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/fb.h>
-#include <plat/sdhci.h>
-#include <plat/iic.h>
-#include <plat/pd.h>
-#include <plat/gpio-cfg.h>
-#include <plat/backlight.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 void lcd_lte480wv_set_power(struct plat_lcd_data *pd,
-				   unsigned int power)
-{
-	if (power) {
-#if !defined(CONFIG_BACKLIGHT_PWM)
-		gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_HIGH, "GPD0");
-		gpio_free(EXYNOS4_GPD0(1));
-#endif
-		/* fire nRESET on power up */
-		gpio_request(EXYNOS4_GPX0(6), "GPX0");
-
-		gpio_direction_output(EXYNOS4_GPX0(6), 1);
-		mdelay(100);
-
-		gpio_set_value(EXYNOS4_GPX0(6), 0);
-		mdelay(10);
-
-		gpio_set_value(EXYNOS4_GPX0(6), 1);
-		mdelay(10);
-
-		gpio_free(EXYNOS4_GPX0(6));
-	} else {
-#if !defined(CONFIG_BACKLIGHT_PWM)
-		gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_LOW, "GPD0");
-		gpio_free(EXYNOS4_GPD0(1));
-#endif
-	}
-}
-
-static struct plat_lcd_data smdkc210_lcd_lte480wv_data = {
-	.set_power		= lcd_lte480wv_set_power,
-};
-
-static struct platform_device smdkc210_lcd_lte480wv = {
-	.name			= "platform-lcd",
-	.dev.parent		= &s5p_device_fimd0.dev,
-	.dev.platform_data	= &smdkc210_lcd_lte480wv_data,
-};
-
-static struct s3c_fb_pd_win smdkc210_fb_win0 = {
-	.win_mode = {
-		.left_margin	= 13,
-		.right_margin	= 8,
-		.upper_margin	= 7,
-		.lower_margin	= 5,
-		.hsync_len	= 3,
-		.vsync_len	= 1,
-		.xres		= 800,
-		.yres		= 480,
-	},
-	.max_bpp		= 32,
-	.default_bpp		= 24,
-};
-
-static struct s3c_fb_platdata smdkc210_lcd0_pdata __initdata = {
-	.win[0]		= &smdkc210_fb_win0,
-	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
-	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
-	.setup_gpio	= exynos4_fimd0_gpio_setup_24bpp,
-};
-
-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,
-	&s5p_device_fimd0,
-	&smdkc210_lcd_lte480wv,
-	&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);
-}
-
-/* LCD Backlight data */
-static struct samsung_bl_gpio_info smdkc210_bl_gpio_info = {
-	.no = EXYNOS4_GPD0(1),
-	.func = S3C_GPIO_SFN(2),
-};
-
-static struct platform_pwm_backlight_data smdkc210_bl_data = {
-	.pwm_id = 1,
-	.pwm_period_ns  = 1000,
-};
-
-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);
-
-	samsung_bl_set(&smdkc210_bl_gpio_info, &smdkc210_bl_data);
-	s5p_fimd0_set_platdata(&smdkc210_lcd0_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-3.1-gnu/arch/arm/mach-exynos4/mach-smdkv310.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/mach-smdkv310.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/mach-smdkv310.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/mach-smdkv310.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,263 +0,0 @@
-/* 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 <linux/pwm_backlight.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 <plat/gpio-cfg.h>
-#include <plat/backlight.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_INTERNAL,
-	.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_INTERNAL,
-	.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_spdif,
-	&exynos4_device_sysmmu,
-	&samsung_asoc_dma,
-	&samsung_asoc_idma,
-	&smdkv310_smsc911x,
-	&exynos4_device_ahci,
-};
-
-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);
-}
-
-/* LCD Backlight data */
-static struct samsung_bl_gpio_info smdkv310_bl_gpio_info = {
-	.no = EXYNOS4_GPD0(1),
-	.func = S3C_GPIO_SFN(2),
-};
-
-static struct platform_pwm_backlight_data smdkv310_bl_data = {
-	.pwm_id = 1,
-	.pwm_period_ns  = 1000,
-};
-
-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);
-
-	samsung_bl_set(&smdkv310_bl_gpio_info, &smdkv310_bl_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-3.1-gnu/arch/arm/mach-exynos4/mach-universal_c210.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/mach-universal_c210.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/mach-universal_c210.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/mach-universal_c210.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,771 +0,0 @@
-/* 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 <linux/i2c-gpio.h>
-#include <linux/i2c/mcs.h>
-#include <linux/i2c/atmel_mxt_ts.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/gpio-cfg.h>
-#include <plat/mfc.h>
-#include <plat/sdhci.h>
-#include <plat/pd.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("vdd_arm", 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("vdd_int", 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,
-	},
-};
-
-/* I2C3 (TSP) */
-static struct mxt_platform_data qt602240_platform_data = {
-	.x_line		= 19,
-	.y_line		= 11,
-	.x_size		= 800,
-	.y_size		= 480,
-	.blen		= 0x11,
-	.threshold	= 0x28,
-	.voltage	= 2800000,		/* 2.8V */
-	.orient		= MXT_DIAGONAL,
-};
-
-static struct i2c_board_info i2c3_devs[] __initdata = {
-	{
-		I2C_BOARD_INFO("qt602240_ts", 0x4a),
-		.platform_data = &qt602240_platform_data,
-	},
-};
-
-static void __init universal_tsp_init(void)
-{
-	int gpio;
-
-	/* TSP_LDO_ON: XMDMADDR_11 */
-	gpio = EXYNOS4_GPE2(3);
-	gpio_request(gpio, "TSP_LDO_ON");
-	gpio_direction_output(gpio, 1);
-	gpio_export(gpio, 0);
-
-	/* TSP_INT: XMDMADDR_7 */
-	gpio = EXYNOS4_GPE1(7);
-	gpio_request(gpio, "TSP_INT");
-
-	s5p_register_gpio_interrupt(gpio);
-	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
-	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-	i2c3_devs[0].irq = gpio_to_irq(gpio);
-}
-
-
-/* GPIO I2C 12 (3 Touchkey) */
-static uint32_t touchkey_keymap[] = {
-	/* MCS_KEY_MAP(value, keycode) */
-	MCS_KEY_MAP(0, KEY_MENU),		/* KEY_SEND */
-	MCS_KEY_MAP(1, KEY_BACK),		/* KEY_END */
-};
-
-static struct mcs_platform_data touchkey_data = {
-	.keymap		= touchkey_keymap,
-	.keymap_size	= ARRAY_SIZE(touchkey_keymap),
-	.key_maxval	= 2,
-};
-
-/* GPIO I2C 3_TOUCH 2.8V */
-#define I2C_GPIO_BUS_12		12
-static struct i2c_gpio_platform_data i2c_gpio12_data = {
-	.sda_pin	= EXYNOS4_GPE4(0),	/* XMDMDATA_8 */
-	.scl_pin	= EXYNOS4_GPE4(1),	/* XMDMDATA_9 */
-};
-
-static struct platform_device i2c_gpio12 = {
-	.name		= "i2c-gpio",
-	.id		= I2C_GPIO_BUS_12,
-	.dev		= {
-		.platform_data	= &i2c_gpio12_data,
-	},
-};
-
-static struct i2c_board_info i2c_gpio12_devs[] __initdata = {
-	{
-		I2C_BOARD_INFO("mcs5080_touchkey", 0x20),
-		.platform_data = &touchkey_data,
-	},
-};
-
-static void __init universal_touchkey_init(void)
-{
-	int gpio;
-
-	gpio = EXYNOS4_GPE3(7);			/* XMDMDATA_7 */
-	gpio_request(gpio, "3_TOUCH_INT");
-	s5p_register_gpio_interrupt(gpio);
-	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
-	i2c_gpio12_devs[0].irq = gpio_to_irq(gpio);
-
-	gpio = EXYNOS4_GPE3(3);			/* XMDMDATA_3 */
-	gpio_request(gpio, "3_TOUCH_EN");
-	gpio_direction_output(gpio, 1);
-}
-
-/* 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 */
-	&s5p_device_fimc0,
-	&s5p_device_fimc1,
-	&s5p_device_fimc2,
-	&s5p_device_fimc3,
-	&mmc0_fixed_voltage,
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc2,
-	&s3c_device_hsmmc3,
-	&s3c_device_i2c3,
-	&s3c_device_i2c5,
-
-	/* Universal Devices */
-	&i2c_gpio12,
-	&universal_gpio_keys,
-	&s5p_device_onenand,
-	&s5p_device_mfc,
-	&s5p_device_mfc_l,
-	&s5p_device_mfc_r,
-	&exynos4_device_pd[PD_MFC],
-};
-
-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_reserve(void)
-{
-	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
-}
-
-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));
-
-	universal_tsp_init();
-	s3c_i2c3_set_platdata(NULL);
-	i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
-
-	s3c_i2c5_set_platdata(NULL);
-	i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
-
-	universal_touchkey_init();
-	i2c_register_board_info(I2C_GPIO_BUS_12, i2c_gpio12_devs,
-			ARRAY_SIZE(i2c_gpio12_devs));
-
-	/* Last */
-	platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
-	s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
-}
-
-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,
-	.reserve        = &universal_reserve,
-MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/Makefile linux-libre-3.2-gnu/arch/arm/mach-exynos4/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,55 +0,0 @@
-# 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 irq-eint.o dma.o pmu.o
-obj-$(CONFIG_PM)		+= pm.o sleep.o
-obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
-
-obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
-
-obj-$(CONFIG_EXYNOS4_MCT)	+= mct.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_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_DEV_DWMCI)	+= dev-dwmci.o
-
-obj-$(CONFIG_EXYNOS4_SETUP_FIMC)	+= setup-fimc.o
-obj-$(CONFIG_EXYNOS4_SETUP_FIMD0)	+= setup-fimd0.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
-
-obj-$(CONFIG_EXYNOS4_SETUP_USB_PHY)	+= setup-usb-phy.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-exynos4/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/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-3.1-gnu/arch/arm/mach-exynos4/mct.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/mct.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/mct.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/mct.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,429 +0,0 @@
-/* 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;
-}
-
-static void exynos4_frc_resume(struct clocksource *cs)
-{
-	exynos4_mct_frc_start(0, 0);
-}
-
-struct clocksource mct_frc = {
-	.name		= "mct-frc",
-	.rating		= 400,
-	.read		= exynos4_frc_read,
-	.mask		= CLOCKSOURCE_MASK(64),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-	.resume		= exynos4_frc_resume,
-};
-
-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];
-		setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
-		irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
-	}
-}
-
-/* Setup the local clock events for a CPU */
-int __cpuinit local_timer_setup(struct clock_event_device *evt)
-{
-	exynos4_mct_tick_init(evt);
-
-	return 0;
-}
-
-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-3.1-gnu/arch/arm/mach-exynos4/platsmp.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/platsmp.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/platsmp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/platsmp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,222 +0,0 @@
-/* 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/hardware/gic.h>
-#include <asm/smp_scu.h>
-#include <asm/unified.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-pmu.h>
-
-extern void exynos4_secondary_startup(void);
-
-#define CPU1_BOOT_REG S5P_VA_SYSRAM
-
-/*
- * 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);
-
-static void __cpuinit exynos4_gic_secondary_init(void)
-{
-	void __iomem *dist_base = S5P_VA_GIC_DIST +
-				 (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
-	void __iomem *cpu_base = S5P_VA_GIC_CPU +
-				(EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
-	int i;
-
-	/*
-	 * Deal with the banked PPI and SGI interrupts - disable all
-	 * PPI interrupts, ensure all SGI interrupts are enabled.
-	 */
-	__raw_writel(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
-	__raw_writel(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
-
-	/*
-	 * Set priority on PPI and SGI interrupts
-	 */
-	for (i = 0; i < 32; i += 4)
-		__raw_writel(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
-
-	__raw_writel(0xf0, cpu_base + GIC_CPU_PRIMASK);
-	__raw_writel(1, cpu_base + GIC_CPU_CTRL);
-}
-
-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
-	 */
-	exynos4_gic_secondary_init();
-
-	/*
-	 * 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);
-
-	set_cpu_online(cpu, true);
-}
-
-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);
-
-	if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) {
-		__raw_writel(S5P_CORE_LOCAL_PWR_EN,
-			     S5P_ARM_CORE1_CONFIGURATION);
-
-		timeout = 10;
-
-		/* wait max 10 ms until cpu1 is on */
-		while ((__raw_readl(S5P_ARM_CORE1_STATUS)
-			& S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) {
-			if (timeout-- == 0)
-				break;
-
-			mdelay(1);
-		}
-
-		if (timeout == 0) {
-			printk(KERN_ERR "cpu1 power enable failed");
-			spin_unlock(&boot_lock);
-			return -ETIMEDOUT;
-		}
-	}
-	/*
-	 * 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.
-	 */
-
-	timeout = jiffies + (1 * HZ);
-	while (time_before(jiffies, timeout)) {
-		smp_rmb();
-
-		__raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)),
-			CPU1_BOOT_REG);
-		gic_raise_softirq(cpumask_of(cpu), 1);
-
-		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);
-
-	set_smp_cross_call(gic_raise_softirq);
-}
-
-void __init platform_smp_prepare_cpus(unsigned int max_cpus)
-{
-
-	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-3.1-gnu/arch/arm/mach-exynos4/pm.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/pm.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/pm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,486 +0,0 @@
-/* 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/syscore_ops.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-
-#include <asm/cacheflush.h>
-#include <asm/hardware/cache-l2x0.h>
-
-#include <plat/cpu.h>
-#include <plat/pm.h>
-#include <plat/pll.h>
-#include <plat/regs-srom.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>
-#include <mach/pmu.h>
-
-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_epll_save[] = {
-	SAVE_ITEM(S5P_EPLL_CON0),
-	SAVE_ITEM(S5P_EPLL_CON1),
-};
-
-static struct sleep_save exynos4_vpll_save[] = {
-	SAVE_ITEM(S5P_VPLL_CON0),
-	SAVE_ITEM(S5P_VPLL_CON1),
-};
-
-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_CLKSRC_TOP0),
-	SAVE_ITEM(S5P_CLKSRC_TOP1),
-	SAVE_ITEM(S5P_CLKSRC_CAM),
-	SAVE_ITEM(S5P_CLKSRC_TV),
-	SAVE_ITEM(S5P_CLKSRC_MFC),
-	SAVE_ITEM(S5P_CLKSRC_G3D),
-	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_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_CLKDIV2_RATIO),
-	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_CLKDIV_CPU + 0x4),
-	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),
-
-	/* SROM side */
-	SAVE_ITEM(S5P_SROM_BW),
-	SAVE_ITEM(S5P_SROM_BC0),
-	SAVE_ITEM(S5P_SROM_BC1),
-	SAVE_ITEM(S5P_SROM_BC2),
-	SAVE_ITEM(S5P_SROM_BC3),
-};
-
-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),
-};
-
-/* For Cortex-A9 Diagnostic and Power control register */
-static unsigned int save_arm_register[2];
-
-static int exynos4_cpu_suspend(unsigned long arg)
-{
-	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));
-	s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
-	s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
-
-	tmp = __raw_readl(S5P_INFORM1);
-
-	/* Set value of power down register for sleep mode */
-
-	exynos4_sys_powerdown_conf(SYS_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 unsigned long pll_base_rate;
-
-static void exynos4_restore_pll(void)
-{
-	unsigned long pll_con, locktime, lockcnt;
-	unsigned long pll_in_rate;
-	unsigned int p_div, epll_wait = 0, vpll_wait = 0;
-
-	if (pll_base_rate == 0)
-		return;
-
-	pll_in_rate = pll_base_rate;
-
-	/* EPLL */
-	pll_con = exynos4_epll_save[0].val;
-
-	if (pll_con & (1 << 31)) {
-		pll_con &= (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT);
-		p_div = (pll_con >> PLL46XX_PDIV_SHIFT);
-
-		pll_in_rate /= 1000000;
-
-		locktime = (3000 / pll_in_rate) * p_div;
-		lockcnt = locktime * 10000 / (10000 / pll_in_rate);
-
-		__raw_writel(lockcnt, S5P_EPLL_LOCK);
-
-		s3c_pm_do_restore_core(exynos4_epll_save,
-					ARRAY_SIZE(exynos4_epll_save));
-		epll_wait = 1;
-	}
-
-	pll_in_rate = pll_base_rate;
-
-	/* VPLL */
-	pll_con = exynos4_vpll_save[0].val;
-
-	if (pll_con & (1 << 31)) {
-		pll_in_rate /= 1000000;
-		/* 750us */
-		locktime = 750;
-		lockcnt = locktime * 10000 / (10000 / pll_in_rate);
-
-		__raw_writel(lockcnt, S5P_VPLL_LOCK);
-
-		s3c_pm_do_restore_core(exynos4_vpll_save,
-					ARRAY_SIZE(exynos4_vpll_save));
-		vpll_wait = 1;
-	}
-
-	/* Wait PLL locking */
-
-	do {
-		if (epll_wait) {
-			pll_con = __raw_readl(S5P_EPLL_CON0);
-			if (pll_con & (1 << S5P_EPLLCON0_LOCKED_SHIFT))
-				epll_wait = 0;
-		}
-
-		if (vpll_wait) {
-			pll_con = __raw_readl(S5P_VPLL_CON0);
-			if (pll_con & (1 << S5P_VPLLCON0_LOCKED_SHIFT))
-				vpll_wait = 0;
-		}
-	} while (epll_wait || vpll_wait);
-}
-
-static struct sysdev_driver exynos4_pm_driver = {
-	.add		= exynos4_pm_add,
-};
-
-static __init int exynos4_pm_drvinit(void)
-{
-	struct clk *pll_base;
-	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);
-
-	pll_base = clk_get(NULL, "xtal");
-
-	if (!IS_ERR(pll_base)) {
-		pll_base_rate = clk_get_rate(pll_base);
-		clk_put(pll_base);
-	}
-
-	return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver);
-}
-arch_initcall(exynos4_pm_drvinit);
-
-static int exynos4_pm_suspend(void)
-{
-	unsigned long tmp;
-
-	/* 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);
-
-	/* Save Power control register */
-	asm ("mrc p15, 0, %0, c15, c0, 0"
-	     : "=r" (tmp) : : "cc");
-	save_arm_register[0] = tmp;
-
-	/* Save Diagnostic register */
-	asm ("mrc p15, 0, %0, c15, c0, 1"
-	     : "=r" (tmp) : : "cc");
-	save_arm_register[1] = tmp;
-
-	return 0;
-}
-
-static void exynos4_pm_resume(void)
-{
-	unsigned long tmp;
-
-	/*
-	 * If PMU failed while entering sleep mode, WFI will be
-	 * ignored by PMU and then exiting cpu_do_idle().
-	 * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
-	 * in this situation.
-	 */
-	tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
-	if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
-		tmp |= S5P_CENTRAL_LOWPWR_CFG;
-		__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
-		/* No need to perform below restore code */
-		goto early_wakeup;
-	}
-	/* Restore Power control register */
-	tmp = save_arm_register[0];
-	asm volatile ("mcr p15, 0, %0, c15, c0, 0"
-		      : : "r" (tmp)
-		      : "cc");
-
-	/* Restore Diagnostic register */
-	tmp = save_arm_register[1];
-	asm volatile ("mcr p15, 0, %0, c15, c0, 1"
-		      : : "r" (tmp)
-		      : "cc");
-
-	/* 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_restore_pll();
-
-	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
-
-early_wakeup:
-	return;
-}
-
-static struct syscore_ops exynos4_pm_syscore_ops = {
-	.suspend	= exynos4_pm_suspend,
-	.resume		= exynos4_pm_resume,
-};
-
-static __init int exynos4_pm_syscore_init(void)
-{
-	register_syscore_ops(&exynos4_pm_syscore_ops);
-	return 0;
-}
-arch_initcall(exynos4_pm_syscore_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/pmu.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/pmu.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/pmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/pmu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,175 +0,0 @@
-/* linux/arch/arm/mach-exynos4/pmu.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * EXYNOS4210 - CPU PMU(Power Management Unit) 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 <mach/regs-clock.h>
-#include <mach/pmu.h>
-
-static void __iomem *sys_powerdown_reg[] = {
-	S5P_ARM_CORE0_LOWPWR,
-	S5P_DIS_IRQ_CORE0,
-	S5P_DIS_IRQ_CENTRAL0,
-	S5P_ARM_CORE1_LOWPWR,
-	S5P_DIS_IRQ_CORE1,
-	S5P_DIS_IRQ_CENTRAL1,
-	S5P_ARM_COMMON_LOWPWR,
-	S5P_L2_0_LOWPWR,
-	S5P_L2_1_LOWPWR,
-	S5P_CMU_ACLKSTOP_LOWPWR,
-	S5P_CMU_SCLKSTOP_LOWPWR,
-	S5P_CMU_RESET_LOWPWR,
-	S5P_APLL_SYSCLK_LOWPWR,
-	S5P_MPLL_SYSCLK_LOWPWR,
-	S5P_VPLL_SYSCLK_LOWPWR,
-	S5P_EPLL_SYSCLK_LOWPWR,
-	S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR,
-	S5P_CMU_RESET_GPSALIVE_LOWPWR,
-	S5P_CMU_CLKSTOP_CAM_LOWPWR,
-	S5P_CMU_CLKSTOP_TV_LOWPWR,
-	S5P_CMU_CLKSTOP_MFC_LOWPWR,
-	S5P_CMU_CLKSTOP_G3D_LOWPWR,
-	S5P_CMU_CLKSTOP_LCD0_LOWPWR,
-	S5P_CMU_CLKSTOP_LCD1_LOWPWR,
-	S5P_CMU_CLKSTOP_MAUDIO_LOWPWR,
-	S5P_CMU_CLKSTOP_GPS_LOWPWR,
-	S5P_CMU_RESET_CAM_LOWPWR,
-	S5P_CMU_RESET_TV_LOWPWR,
-	S5P_CMU_RESET_MFC_LOWPWR,
-	S5P_CMU_RESET_G3D_LOWPWR,
-	S5P_CMU_RESET_LCD0_LOWPWR,
-	S5P_CMU_RESET_LCD1_LOWPWR,
-	S5P_CMU_RESET_MAUDIO_LOWPWR,
-	S5P_CMU_RESET_GPS_LOWPWR,
-	S5P_TOP_BUS_LOWPWR,
-	S5P_TOP_RETENTION_LOWPWR,
-	S5P_TOP_PWR_LOWPWR,
-	S5P_LOGIC_RESET_LOWPWR,
-	S5P_ONENAND_MEM_LOWPWR,
-	S5P_MODIMIF_MEM_LOWPWR,
-	S5P_G2D_ACP_MEM_LOWPWR,
-	S5P_USBOTG_MEM_LOWPWR,
-	S5P_HSMMC_MEM_LOWPWR,
-	S5P_CSSYS_MEM_LOWPWR,
-	S5P_SECSS_MEM_LOWPWR,
-	S5P_PCIE_MEM_LOWPWR,
-	S5P_SATA_MEM_LOWPWR,
-	S5P_PAD_RETENTION_DRAM_LOWPWR,
-	S5P_PAD_RETENTION_MAUDIO_LOWPWR,
-	S5P_PAD_RETENTION_GPIO_LOWPWR,
-	S5P_PAD_RETENTION_UART_LOWPWR,
-	S5P_PAD_RETENTION_MMCA_LOWPWR,
-	S5P_PAD_RETENTION_MMCB_LOWPWR,
-	S5P_PAD_RETENTION_EBIA_LOWPWR,
-	S5P_PAD_RETENTION_EBIB_LOWPWR,
-	S5P_PAD_RETENTION_ISOLATION_LOWPWR,
-	S5P_PAD_RETENTION_ALV_SEL_LOWPWR,
-	S5P_XUSBXTI_LOWPWR,
-	S5P_XXTI_LOWPWR,
-	S5P_EXT_REGULATOR_LOWPWR,
-	S5P_GPIO_MODE_LOWPWR,
-	S5P_GPIO_MODE_MAUDIO_LOWPWR,
-	S5P_CAM_LOWPWR,
-	S5P_TV_LOWPWR,
-	S5P_MFC_LOWPWR,
-	S5P_G3D_LOWPWR,
-	S5P_LCD0_LOWPWR,
-	S5P_LCD1_LOWPWR,
-	S5P_MAUDIO_LOWPWR,
-	S5P_GPS_LOWPWR,
-	S5P_GPS_ALIVE_LOWPWR,
-};
-
-static const unsigned int sys_powerdown_val[][NUM_SYS_POWERDOWN] = {
-	/* { AFTR, LPA, SLEEP }*/
-	{ 0, 0, 2 },	/* ARM_CORE0 */
-	{ 0, 0, 0 },	/* ARM_DIS_IRQ_CORE0 */
-	{ 0, 0, 0 },	/* ARM_DIS_IRQ_CENTRAL0 */
-	{ 0, 0, 2 },	/* ARM_CORE1 */
-	{ 0, 0, 0 },	/* ARM_DIS_IRQ_CORE1 */
-	{ 0, 0, 0 },	/* ARM_DIS_IRQ_CENTRAL1 */
-	{ 0, 0, 2 },	/* ARM_COMMON */
-	{ 2, 2, 3 },	/* ARM_CPU_L2_0 */
-	{ 2, 2, 3 },	/* ARM_CPU_L2_1 */
-	{ 1, 0, 0 },	/* CMU_ACLKSTOP */
-	{ 1, 0, 0 },	/* CMU_SCLKSTOP */
-	{ 1, 1, 0 },	/* CMU_RESET */
-	{ 1, 0, 0 },	/* APLL_SYSCLK */
-	{ 1, 0, 0 },	/* MPLL_SYSCLK */
-	{ 1, 0, 0 },	/* VPLL_SYSCLK */
-	{ 1, 1, 0 },	/* EPLL_SYSCLK */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_GPS_ALIVE */
-	{ 1, 1, 0 },	/* CMU_RESET_GPS_ALIVE */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_CAM */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_TV */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_MFC */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_G3D */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_LCD0 */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_LCD1 */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_MAUDIO */
-	{ 1, 1, 0 },	/* CMU_CLKSTOP_GPS */
-	{ 1, 1, 0 },	/* CMU_RESET_CAM */
-	{ 1, 1, 0 },	/* CMU_RESET_TV */
-	{ 1, 1, 0 },	/* CMU_RESET_MFC */
-	{ 1, 1, 0 },	/* CMU_RESET_G3D */
-	{ 1, 1, 0 },	/* CMU_RESET_LCD0 */
-	{ 1, 1, 0 },	/* CMU_RESET_LCD1 */
-	{ 1, 1, 0 },	/* CMU_RESET_MAUDIO */
-	{ 1, 1, 0 },	/* CMU_RESET_GPS */
-	{ 3, 0, 0 },	/* TOP_BUS */
-	{ 1, 0, 1 },	/* TOP_RETENTION */
-	{ 3, 0, 3 },	/* TOP_PWR */
-	{ 1, 1, 0 },	/* LOGIC_RESET */
-	{ 3, 0, 0 },	/* ONENAND_MEM */
-	{ 3, 0, 0 },	/* MODIMIF_MEM */
-	{ 3, 0, 0 },	/* G2D_ACP_MEM */
-	{ 3, 0, 0 },	/* USBOTG_MEM */
-	{ 3, 0, 0 },	/* HSMMC_MEM */
-	{ 3, 0, 0 },	/* CSSYS_MEM */
-	{ 3, 0, 0 },	/* SECSS_MEM */
-	{ 3, 0, 0 },	/* PCIE_MEM */
-	{ 3, 0, 0 },	/* SATA_MEM */
-	{ 1, 0, 0 },	/* PAD_RETENTION_DRAM */
-	{ 1, 1, 0 },	/* PAD_RETENTION_MAUDIO */
-	{ 1, 0, 0 },	/* PAD_RETENTION_GPIO */
-	{ 1, 0, 0 },	/* PAD_RETENTION_UART */
-	{ 1, 0, 0 },	/* PAD_RETENTION_MMCA */
-	{ 1, 0, 0 },	/* PAD_RETENTION_MMCB */
-	{ 1, 0, 0 },	/* PAD_RETENTION_EBIA */
-	{ 1, 0, 0 },	/* PAD_RETENTION_EBIB */
-	{ 1, 0, 0 },	/* PAD_RETENTION_ISOLATION */
-	{ 1, 0, 0 },	/* PAD_RETENTION_ALV_SEL */
-	{ 1, 1, 0 },	/* XUSBXTI */
-	{ 1, 1, 0 },	/* XXTI */
-	{ 1, 1, 0 },	/* EXT_REGULATOR */
-	{ 1, 0, 0 },	/* GPIO_MODE */
-	{ 1, 1, 0 },	/* GPIO_MODE_MAUDIO */
-	{ 7, 0, 0 },	/* CAM */
-	{ 7, 0, 0 },	/* TV */
-	{ 7, 0, 0 },	/* MFC */
-	{ 7, 0, 0 },	/* G3D */
-	{ 7, 0, 0 },	/* LCD0 */
-	{ 7, 0, 0 },	/* LCD1 */
-	{ 7, 7, 0 },	/* MAUDIO */
-	{ 7, 0, 0 },	/* GPS */
-	{ 7, 0, 0 },	/* GPS_ALIVE */
-};
-
-void exynos4_sys_powerdown_conf(enum sys_powerdown mode)
-{
-	unsigned int count = ARRAY_SIZE(sys_powerdown_reg);
-
-	for (; count > 0; count--)
-		__raw_writel(sys_powerdown_val[count - 1][mode],
-				sys_powerdown_reg[count - 1]);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/setup-fimc.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-fimc.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/setup-fimc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-fimc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/*
- * 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-3.1-gnu/arch/arm/mach-exynos4/setup-fimd0.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-fimd0.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/setup-fimd0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-fimd0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/* linux/arch/arm/mach-exynos4/setup-fimd0.c
- *
- * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Base Exynos4 FIMD 0 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/fb.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/regs-fb-v4.h>
-
-#include <mach/map.h>
-
-void exynos4_fimd0_gpio_setup_24bpp(void)
-{
-	unsigned int reg;
-
-	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF0(0), 8, S3C_GPIO_SFN(2));
-	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF1(0), 8, S3C_GPIO_SFN(2));
-	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF2(0), 8, S3C_GPIO_SFN(2));
-	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF3(0), 4, S3C_GPIO_SFN(2));
-
-	/*
-	 * Set DISPLAY_CONTROL register for Display path selection.
-	 *
-	 * DISPLAY_CONTROL[1:0]
-	 * ---------------------
-	 *  00 | MIE
-	 *  01 | MDINE
-	 *  10 | FIMD : selected
-	 *  11 | FIMD
-	 */
-	reg = __raw_readl(S3C_VA_SYS + 0x0210);
-	reg |= (1 << 1);
-	__raw_writel(reg, S3C_VA_SYS + 0x0210);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/setup-i2c0.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-i2c0.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/setup-i2c0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-i2c0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- * 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-3.1-gnu/arch/arm/mach-exynos4/setup-i2c1.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-i2c1.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/setup-i2c1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-i2c1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * 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-3.1-gnu/arch/arm/mach-exynos4/setup-i2c2.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-i2c2.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/setup-i2c2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-i2c2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * 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-3.1-gnu/arch/arm/mach-exynos4/setup-i2c3.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-i2c3.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/setup-i2c3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-i2c3.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * 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-3.1-gnu/arch/arm/mach-exynos4/setup-i2c4.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-i2c4.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/setup-i2c4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-i2c4.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * 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-3.1-gnu/arch/arm/mach-exynos4/setup-i2c5.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-i2c5.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/setup-i2c5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-i2c5.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * 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-3.1-gnu/arch/arm/mach-exynos4/setup-i2c6.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-i2c6.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/setup-i2c6.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-i2c6.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * 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-3.1-gnu/arch/arm/mach-exynos4/setup-i2c7.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-i2c7.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/setup-i2c7.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-i2c7.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * 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-3.1-gnu/arch/arm/mach-exynos4/setup-keypad.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-keypad.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/setup-keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-keypad.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-/* 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_cfgall_range(EXYNOS4_GPX2(0), 8, S3C_GPIO_SFN(3),
-					S3C_GPIO_PULL_UP);
-
-		/* Set all the necessary GPX3 pins: KP_ROW[8~] */
-		s3c_gpio_cfgall_range(EXYNOS4_GPX3(0), (rows - 8),
-					 S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-	} else {
-		/* Set all the necessary GPX2 pins: KP_ROW[x] */
-		s3c_gpio_cfgall_range(EXYNOS4_GPX2(0), rows, S3C_GPIO_SFN(3),
-					S3C_GPIO_PULL_UP);
-	}
-
-	/* 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-3.1-gnu/arch/arm/mach-exynos4/setup-sdhci.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-sdhci.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/setup-sdhci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-sdhci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,69 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/setup-sdhci-gpio.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-sdhci-gpio.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/setup-sdhci-gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-sdhci-gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,152 +0,0 @@
-/* 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-3.1-gnu/arch/arm/mach-exynos4/setup-usb-phy.c linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-usb-phy.c
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/setup-usb-phy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/setup-usb-phy.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2011 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/clk.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <mach/regs-pmu.h>
-#include <mach/regs-usb-phy.h>
-#include <plat/cpu.h>
-#include <plat/usb-phy.h>
-
-static int exynos4_usb_phy1_init(struct platform_device *pdev)
-{
-	struct clk *otg_clk;
-	struct clk *xusbxti_clk;
-	u32 phyclk;
-	u32 rstcon;
-	int err;
-
-	otg_clk = clk_get(&pdev->dev, "otg");
-	if (IS_ERR(otg_clk)) {
-		dev_err(&pdev->dev, "Failed to get otg clock\n");
-		return PTR_ERR(otg_clk);
-	}
-
-	err = clk_enable(otg_clk);
-	if (err) {
-		clk_put(otg_clk);
-		return err;
-	}
-
-	writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE,
-			S5P_USBHOST_PHY_CONTROL);
-
-	/* set clock frequency for PLL */
-	phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK;
-
-	xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
-	if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
-		switch (clk_get_rate(xusbxti_clk)) {
-		case 12 * MHZ:
-			phyclk |= CLKSEL_12M;
-			break;
-		case 24 * MHZ:
-			phyclk |= CLKSEL_24M;
-			break;
-		default:
-		case 48 * MHZ:
-			/* default reference clock */
-			break;
-		}
-		clk_put(xusbxti_clk);
-	}
-
-	writel(phyclk, EXYNOS4_PHYCLK);
-
-	/* floating prevention logic: disable */
-	writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON);
-
-	/* set to normal HSIC 0 and 1 of PHY1 */
-	writel((readl(EXYNOS4_PHYPWR) & ~PHY1_HSIC_NORMAL_MASK),
-			EXYNOS4_PHYPWR);
-
-	/* set to normal standard USB of PHY1 */
-	writel((readl(EXYNOS4_PHYPWR) & ~PHY1_STD_NORMAL_MASK), EXYNOS4_PHYPWR);
-
-	/* reset all ports of both PHY and Link */
-	rstcon = readl(EXYNOS4_RSTCON) | HOST_LINK_PORT_SWRST_MASK |
-		PHY1_SWRST_MASK;
-	writel(rstcon, EXYNOS4_RSTCON);
-	udelay(10);
-
-	rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK);
-	writel(rstcon, EXYNOS4_RSTCON);
-	udelay(80);
-
-	clk_disable(otg_clk);
-	clk_put(otg_clk);
-
-	return 0;
-}
-
-static int exynos4_usb_phy1_exit(struct platform_device *pdev)
-{
-	struct clk *otg_clk;
-	int err;
-
-	otg_clk = clk_get(&pdev->dev, "otg");
-	if (IS_ERR(otg_clk)) {
-		dev_err(&pdev->dev, "Failed to get otg clock\n");
-		return PTR_ERR(otg_clk);
-	}
-
-	err = clk_enable(otg_clk);
-	if (err) {
-		clk_put(otg_clk);
-		return err;
-	}
-
-	writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN),
-			EXYNOS4_PHYPWR);
-
-	writel(readl(S5P_USBHOST_PHY_CONTROL) & ~S5P_USBHOST_PHY_ENABLE,
-			S5P_USBHOST_PHY_CONTROL);
-
-	clk_disable(otg_clk);
-	clk_put(otg_clk);
-
-	return 0;
-}
-
-int s5p_usb_phy_init(struct platform_device *pdev, int type)
-{
-	if (type == S5P_USB_PHY_HOST)
-		return exynos4_usb_phy1_init(pdev);
-
-	return -EINVAL;
-}
-
-int s5p_usb_phy_exit(struct platform_device *pdev, int type)
-{
-	if (type == S5P_USB_PHY_HOST)
-		return exynos4_usb_phy1_exit(pdev);
-
-	return -EINVAL;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-exynos4/sleep.S linux-libre-3.2-gnu/arch/arm/mach-exynos4/sleep.S
--- linux-libre-3.1-gnu/arch/arm/mach-exynos4/sleep.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-exynos4/sleep.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,54 +0,0 @@
-/* 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
-
-	/*
-	 * 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-3.1-gnu/arch/arm/mach-footbridge/cats-hw.c linux-libre-3.2-gnu/arch/arm/mach-footbridge/cats-hw.c
--- linux-libre-3.1-gnu/arch/arm/mach-footbridge/cats-hw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-footbridge/cats-hw.c	2012-01-04 18:55:44.000000000 -0500
@@ -76,8 +76,7 @@
  * hard reboots fail on early boards.
  */
 static void __init
-fixup_cats(struct machine_desc *desc, struct tag *tags,
-	   char **cmdline, struct meminfo *mi)
+fixup_cats(struct tag *tags, char **cmdline, struct meminfo *mi)
 {
 	screen_info.orig_video_lines  = 25;
 	screen_info.orig_video_points = 16;
@@ -86,7 +85,7 @@
 
 MACHINE_START(CATS, "Chalice-CATS")
 	/* Maintainer: Philip Blundell */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.soft_reboot	= 1,
 	.fixup		= fixup_cats,
 	.map_io		= footbridge_map_io,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-footbridge/ebsa285.c linux-libre-3.2-gnu/arch/arm/mach-footbridge/ebsa285.c
--- linux-libre-3.1-gnu/arch/arm/mach-footbridge/ebsa285.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-footbridge/ebsa285.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
 
 MACHINE_START(EBSA285, "EBSA285")
 	/* Maintainer: Russell King */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.video_start	= 0x000a0000,
 	.video_end	= 0x000bffff,
 	.map_io		= footbridge_map_io,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-footbridge/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-footbridge/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-footbridge/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-footbridge/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
 
 #ifndef CONFIG_DEBUG_DC21285_PORT
 	/* For NetWinder debugging */
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x000003f8
 		orr	\rv, \rp, #0xff000000	@ virtual
 		orr	\rp, \rp, #0x7c000000	@ physical
@@ -31,7 +31,7 @@
 		.equ	dc21285_high, ARMCSR_BASE & 0xff000000
 		.equ	dc21285_low,  ARMCSR_BASE & 0x00ffffff
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		.if	dc21285_low
 		mov	\rp, #dc21285_low
 		.else
diff -druN linux-libre-3.1-gnu/arch/arm/mach-footbridge/include/mach/hardware.h linux-libre-3.2-gnu/arch/arm/mach-footbridge/include/mach/hardware.h
--- linux-libre-3.1-gnu/arch/arm/mach-footbridge/include/mach/hardware.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-footbridge/include/mach/hardware.h	2012-01-04 18:55:44.000000000 -0500
@@ -93,7 +93,7 @@
 #define CPLD_FLASH_WR_ENABLE	1
 
 #ifndef __ASSEMBLY__
-extern spinlock_t nw_gpio_lock;
+extern raw_spinlock_t nw_gpio_lock;
 extern void nw_gpio_modify_op(unsigned int mask, unsigned int set);
 extern void nw_gpio_modify_io(unsigned int mask, unsigned int in);
 extern unsigned int nw_gpio_read(void);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-footbridge/include/mach/io.h linux-libre-3.2-gnu/arch/arm/mach-footbridge/include/mach/io.h
--- linux-libre-3.1-gnu/arch/arm/mach-footbridge/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-footbridge/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -23,8 +23,6 @@
 #define PCIO_SIZE       0x00100000
 #define PCIO_BASE       MMU_IO(0xff000000, 0x7c000000)
 
-#define IO_SPACE_LIMIT 0xffff
-
 /*
  * Translation of various region addresses to virtual addresses
  */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-footbridge/Kconfig linux-libre-3.2-gnu/arch/arm/mach-footbridge/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-footbridge/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-footbridge/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -4,8 +4,8 @@
 
 config ARCH_CATS
 	bool "CATS"
-	select CLKSRC_I8253
 	select CLKEVT_I8253
+	select CLKSRC_I8253
 	select FOOTBRIDGE_HOST
 	select ISA
 	select ISA_DMA
@@ -61,8 +61,8 @@
 
 config ARCH_NETWINDER
 	bool "NetWinder"
-	select CLKSRC_I8253
 	select CLKEVT_I8253
+	select CLKSRC_I8253
 	select FOOTBRIDGE_HOST
 	select ISA
 	select ISA_DMA
diff -druN linux-libre-3.1-gnu/arch/arm/mach-footbridge/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-footbridge/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-footbridge/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-footbridge/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-footbridge/netwinder-hw.c linux-libre-3.2-gnu/arch/arm/mach-footbridge/netwinder-hw.c
--- linux-libre-3.1-gnu/arch/arm/mach-footbridge/netwinder-hw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-footbridge/netwinder-hw.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,7 +68,7 @@
 /*
  * This is a lock for accessing ports GP1_IO_BASE and GP2_IO_BASE
  */
-DEFINE_SPINLOCK(nw_gpio_lock);
+DEFINE_RAW_SPINLOCK(nw_gpio_lock);
 EXPORT_SYMBOL(nw_gpio_lock);
 
 static unsigned int current_gpio_op;
@@ -327,9 +327,9 @@
 	/*
 	 * Set Group1/Group2 outputs
 	 */
-	spin_lock_irqsave(&nw_gpio_lock, flags);
+	raw_spin_lock_irqsave(&nw_gpio_lock, flags);
 	nw_gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN);
-	spin_unlock_irqrestore(&nw_gpio_lock, flags);
+	raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
 }
 
 /*
@@ -390,9 +390,9 @@
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&nw_gpio_lock, flags);
+	raw_spin_lock_irqsave(&nw_gpio_lock, flags);
 	nw_cpld_modify(-1, CPLD_UNMUTE | CPLD_7111_DISABLE);
-	spin_unlock_irqrestore(&nw_gpio_lock, flags);
+	raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
 }
 
 static unsigned char rwa_unlock[] __initdata =
@@ -616,9 +616,9 @@
 		cpld_init();
 		rwa010_init();
 
-		spin_lock_irqsave(&nw_gpio_lock, flags);
+		raw_spin_lock_irqsave(&nw_gpio_lock, flags);
 		nw_gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS);
-		spin_unlock_irqrestore(&nw_gpio_lock, flags);
+		raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
 	}
 	return 0;
 }
@@ -631,8 +631,7 @@
  * the parameter page.
  */
 static void __init
-fixup_netwinder(struct machine_desc *desc, struct tag *tags,
-		char **cmdline, struct meminfo *mi)
+fixup_netwinder(struct tag *tags, char **cmdline, struct meminfo *mi)
 {
 #ifdef CONFIG_ISAPNP
 	extern int isapnp_disable;
@@ -648,7 +647,7 @@
 
 MACHINE_START(NETWINDER, "Rebel-NetWinder")
 	/* Maintainer: Russell King/Rebel.com */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.video_start	= 0x000a0000,
 	.video_end	= 0x000bffff,
 	.reserve_lp0	= 1,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-footbridge/netwinder-leds.c linux-libre-3.2-gnu/arch/arm/mach-footbridge/netwinder-leds.c
--- linux-libre-3.1-gnu/arch/arm/mach-footbridge/netwinder-leds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-footbridge/netwinder-leds.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,13 +31,13 @@
 static char led_state;
 static char hw_led_state;
 
-static DEFINE_SPINLOCK(leds_lock);
+static DEFINE_RAW_SPINLOCK(leds_lock);
 
 static void netwinder_leds_event(led_event_t evt)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&leds_lock, flags);
+	raw_spin_lock_irqsave(&leds_lock, flags);
 
 	switch (evt) {
 	case led_start:
@@ -117,12 +117,12 @@
 		break;
 	}
 
-	spin_unlock_irqrestore(&leds_lock, flags);
+	raw_spin_unlock_irqrestore(&leds_lock, flags);
 
 	if  (led_state & LED_STATE_ENABLED) {
-		spin_lock_irqsave(&nw_gpio_lock, flags);
+		raw_spin_lock_irqsave(&nw_gpio_lock, flags);
 		nw_gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED, hw_led_state);
-		spin_unlock_irqrestore(&nw_gpio_lock, flags);
+		raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
 	}
 }
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-footbridge/personal.c linux-libre-3.2-gnu/arch/arm/mach-footbridge/personal.c
--- linux-libre-3.1-gnu/arch/arm/mach-footbridge/personal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-footbridge/personal.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
 
 MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer")
 	/* Maintainer: Jamey Hicks / George France */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= footbridge_map_io,
 	.init_irq	= footbridge_init_irq,
 	.timer		= &footbridge_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-gemini/board-nas4220b.c linux-libre-3.2-gnu/arch/arm/mach-gemini/board-nas4220b.c
--- linux-libre-3.1-gnu/arch/arm/mach-gemini/board-nas4220b.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-gemini/board-nas4220b.c	2012-01-04 18:55:44.000000000 -0500
@@ -102,7 +102,7 @@
 }
 
 MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")
-	.boot_params	= 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= gemini_map_io,
 	.init_irq	= gemini_init_irq,
 	.timer		= &ib4220b_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-gemini/board-rut1xx.c linux-libre-3.2-gnu/arch/arm/mach-gemini/board-rut1xx.c
--- linux-libre-3.1-gnu/arch/arm/mach-gemini/board-rut1xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-gemini/board-rut1xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -86,7 +86,7 @@
 }
 
 MACHINE_START(RUT100, "Teltonika RUT100")
-	.boot_params	= 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= gemini_map_io,
 	.init_irq	= gemini_init_irq,
 	.timer		= &rut1xx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-gemini/board-wbd111.c linux-libre-3.2-gnu/arch/arm/mach-gemini/board-wbd111.c
--- linux-libre-3.1-gnu/arch/arm/mach-gemini/board-wbd111.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-gemini/board-wbd111.c	2012-01-04 18:55:44.000000000 -0500
@@ -129,7 +129,7 @@
 }
 
 MACHINE_START(WBD111, "Wiliboard WBD-111")
-	.boot_params	= 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= gemini_map_io,
 	.init_irq	= gemini_init_irq,
 	.timer		= &wbd111_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-gemini/board-wbd222.c linux-libre-3.2-gnu/arch/arm/mach-gemini/board-wbd222.c
--- linux-libre-3.1-gnu/arch/arm/mach-gemini/board-wbd222.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-gemini/board-wbd222.c	2012-01-04 18:55:44.000000000 -0500
@@ -129,7 +129,7 @@
 }
 
 MACHINE_START(WBD222, "Wiliboard WBD-222")
-	.boot_params	= 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= gemini_map_io,
 	.init_irq	= gemini_init_irq,
 	.timer		= &wbd222_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-gemini/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-gemini/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-gemini/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-gemini/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  */
 #include <mach/hardware.h>
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldr	\rp, =GEMINI_UART_BASE			@ physical
 	ldr	\rv, =IO_ADDRESS(GEMINI_UART_BASE)	@ virtual
 	.endm
diff -druN linux-libre-3.1-gnu/arch/arm/mach-gemini/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-gemini/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-gemini/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-gemini/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,11 +13,6 @@
 #define __MACH_GPIO_H__
 
 #include <mach/irqs.h>
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
 
 #define gpio_to_irq(x)	((x) + GPIO_IRQ_BASE)
 #define irq_to_gpio(x)	((x) - GPIO_IRQ_BASE)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-gemini/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-gemini/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-gemini/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-gemini/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-/*
- *  Copyright (C) 2001-2006 Storlink, Corp.
- *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 __MACH_MEMORY_H
-#define __MACH_MEMORY_H
-
-#ifdef CONFIG_GEMINI_MEM_SWAP
-# define PLAT_PHYS_OFFSET	UL(0x00000000)
-#else
-# define PLAT_PHYS_OFFSET	UL(0x10000000)
-#endif
-
-#endif /* __MACH_MEMORY_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-gemini/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-gemini/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-gemini/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-gemini/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,9 +1,9 @@
 ifeq ($(CONFIG_GEMINI_MEM_SWAP),y)
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
 else
-   zreladdr-y	:= 0x10008000
+   zreladdr-y	+= 0x10008000
 params_phys-y	:= 0x10000100
 initrd_phys-y	:= 0x10800000
 endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-h720x/h7201-eval.c linux-libre-3.2-gnu/arch/arm/mach-h720x/h7201-eval.c
--- linux-libre-3.1-gnu/arch/arm/mach-h720x/h7201-eval.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-h720x/h7201-eval.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,7 @@
 
 MACHINE_START(H7201, "Hynix GMS30C7201")
 	/* Maintainer: Robert Schwebel, Pengutronix */
-	.boot_params	= 0xc0001000,
+	.atag_offset	= 0x1000,
 	.map_io		= h720x_map_io,
 	.init_irq	= h720x_init_irq,
 	.timer		= &h7201_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-h720x/h7202-eval.c linux-libre-3.2-gnu/arch/arm/mach-h720x/h7202-eval.c
--- linux-libre-3.1-gnu/arch/arm/mach-h720x/h7202-eval.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-h720x/h7202-eval.c	2012-01-04 18:55:44.000000000 -0500
@@ -71,7 +71,7 @@
 
 MACHINE_START(H7202, "Hynix HMS30C7202")
 	/* Maintainer: Robert Schwebel, Pengutronix */
-	.boot_params	= 0x40000100,
+	.atag_offset	= 0x100,
 	.map_io		= h720x_map_io,
 	.init_irq	= h7202_init_irq,
 	.timer		= &h7202_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-h720x/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-h720x/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-h720x/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-h720x/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
 		.equ    io_virt, IO_VIRT
 		.equ    io_phys, IO_PHYS
 
-		.macro  addruart, rp, rv
+		.macro  addruart, rp, rv, tmp
 		mov     \rp, #0x00020000	@ UART1
 		add     \rv, \rp, #io_virt	@ virtual address
 		add     \rp, \rp, #io_phys	@ physical base address
diff -druN linux-libre-3.1-gnu/arch/arm/mach-h720x/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-h720x/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-h720x/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-h720x/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,11 +0,0 @@
-/*
- * arch/arm/mach-h720x/include/mach/memory.h
- *
- * Copyright (c) 2000 Jungjun Kim
- *
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET	UL(0x40000000)
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-h720x/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-h720x/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-h720x/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-h720x/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-   zreladdr-$(CONFIG_ARCH_H720X)	:= 0x40008000
+   zreladdr-$(CONFIG_ARCH_H720X)	+= 0x40008000
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/clock.c linux-libre-3.2-gnu/arch/arm/mach-highbank/clock.c
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/clock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+
+struct clk {
+	unsigned long rate;
+};
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+
+void clk_disable(struct clk *clk)
+{}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	return clk->rate;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	return 0;
+}
+
+static struct clk eclk = { .rate = 200000000 };
+static struct clk pclk = { .rate = 150000000 };
+
+static struct clk_lookup lookups[] = {
+	{ .clk = &pclk, .con_id = "apb_pclk", },
+	{ .clk = &pclk, .dev_id = "sp804", },
+	{ .clk = &eclk, .dev_id = "ffe0e000.sdhci", },
+	{ .clk = &pclk, .dev_id = "fff36000.serial", },
+};
+
+void __init highbank_clocks_init(void)
+{
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/core.h linux-libre-3.2-gnu/arch/arm/mach-highbank/core.h
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/core.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,9 @@
+extern void highbank_set_cpu_jump(int cpu, void *jump_addr);
+extern void highbank_clocks_init(void);
+extern void __iomem *scu_base_addr;
+#ifdef CONFIG_DEBUG_HIGHBANK_UART
+extern void highbank_lluart_map_io(void);
+#else
+static inline void highbank_lluart_map_io(void) {}
+#endif
+
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/highbank.c linux-libre-3.2-gnu/arch/arm/mach-highbank/highbank.c
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/highbank.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/highbank.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/smp.h>
+
+#include <asm/cacheflush.h>
+#include <asm/unified.h>
+#include <asm/smp_scu.h>
+#include <asm/hardware/arm_timer.h>
+#include <asm/hardware/timer-sp.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+
+#include "core.h"
+#include "sysregs.h"
+
+void __iomem *sregs_base;
+
+#define HB_SCU_VIRT_BASE	0xfee00000
+void __iomem *scu_base_addr = ((void __iomem *)(HB_SCU_VIRT_BASE));
+
+static struct map_desc scu_io_desc __initdata = {
+	.virtual	= HB_SCU_VIRT_BASE,
+	.pfn		= 0, /* run-time */
+	.length		= SZ_4K,
+	.type		= MT_DEVICE,
+};
+
+static void __init highbank_scu_map_io(void)
+{
+	unsigned long base;
+
+	/* Get SCU base */
+	asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+	scu_io_desc.pfn = __phys_to_pfn(base);
+	iotable_init(&scu_io_desc, 1);
+}
+
+static void __init highbank_map_io(void)
+{
+	highbank_scu_map_io();
+	highbank_lluart_map_io();
+}
+
+#define HB_JUMP_TABLE_PHYS(cpu)		(0x40 + (0x10 * (cpu)))
+#define HB_JUMP_TABLE_VIRT(cpu)		phys_to_virt(HB_JUMP_TABLE_PHYS(cpu))
+
+void highbank_set_cpu_jump(int cpu, void *jump_addr)
+{
+#ifdef CONFIG_SMP
+	cpu = cpu_logical_map(cpu);
+#endif
+	writel(BSYM(virt_to_phys(jump_addr)), HB_JUMP_TABLE_VIRT(cpu));
+	__cpuc_flush_dcache_area(HB_JUMP_TABLE_VIRT(cpu), 16);
+	outer_clean_range(HB_JUMP_TABLE_PHYS(cpu),
+			  HB_JUMP_TABLE_PHYS(cpu) + 15);
+}
+
+const static struct of_device_id irq_match[] = {
+	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+	{}
+};
+
+static void __init highbank_init_irq(void)
+{
+	of_irq_init(irq_match);
+	l2x0_of_init(0, ~0UL);
+}
+
+static void __init highbank_timer_init(void)
+{
+	int irq;
+	struct device_node *np;
+	void __iomem *timer_base;
+
+	/* Map system registers */
+	np = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs");
+	sregs_base = of_iomap(np, 0);
+	WARN_ON(!sregs_base);
+
+	np = of_find_compatible_node(NULL, NULL, "arm,sp804");
+	timer_base = of_iomap(np, 0);
+	WARN_ON(!timer_base);
+	irq = irq_of_parse_and_map(np, 0);
+
+	highbank_clocks_init();
+
+	sp804_clocksource_init(timer_base + 0x20, "timer1");
+	sp804_clockevents_init(timer_base, irq, "timer0");
+}
+
+static struct sys_timer highbank_timer = {
+	.init = highbank_timer_init,
+};
+
+static void highbank_power_off(void)
+{
+	hignbank_set_pwr_shutdown();
+	scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+
+	while (1)
+		cpu_do_idle();
+}
+
+static void __init highbank_init(void)
+{
+	pm_power_off = highbank_power_off;
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *highbank_match[] __initconst = {
+	"calxeda,highbank",
+	NULL,
+};
+
+DT_MACHINE_START(HIGHBANK, "Highbank")
+	.map_io		= highbank_map_io,
+	.init_irq	= highbank_init_irq,
+	.timer		= &highbank_timer,
+	.init_machine	= highbank_init,
+	.dt_compat	= highbank_match,
+MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/hotplug.c linux-libre-3.2-gnu/arch/arm/mach-highbank/hotplug.c
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/hotplug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/hotplug.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+
+#include <asm/smp_scu.h>
+#include <asm/cacheflush.h>
+
+#include "core.h"
+
+extern void secondary_startup(void);
+
+int platform_cpu_kill(unsigned int cpu)
+{
+	return 1;
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+	flush_cache_all();
+
+	highbank_set_cpu_jump(cpu, secondary_startup);
+	scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+
+	cpu_do_idle();
+
+	/* We should never return from idle */
+	panic("highbank: cpu %d unexpectedly exit from shutdown\n", cpu);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+	/*
+	 * CPU0 should not be shut down via hotplug.  cpu_idle can WFI
+	 * or a proper shutdown or hibernate should be used.
+	 */
+	return cpu == 0 ? -EPERM : 0;
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+/*
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+		.macro	addruart,rp,rv,tmp
+		movw	\rv, #0x6000
+		movt	\rv, #0xfee3
+		movw	\rp, #0x6000
+		movt	\rp, #0xfff3
+		.endm
+
+#include <asm/hardware/debug-pl01x.S>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/entry-macro.S linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/entry-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/entry-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,7 @@
+#include <asm/hardware/entry-macro-gic.S>
+
+	.macro	disable_fiq
+	.endm
+
+	.macro	arch_ret_to_user, tmp1, tmp2
+	.endm
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+/* empty */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/io.h linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/io.h
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,7 @@
+#ifndef __MACH_IO_H
+#define __MACH_IO_H
+
+#define __io(a)		({ (void)(a); __typesafe_io(0); })
+#define __mem_pci(a)	(a)
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/irqs.h linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/irqs.h
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,6 @@
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define NR_IRQS			192
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/memory.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+/* empty */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/system.h linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/system.h
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __MACH_SYSTEM_H
+#define __MACH_SYSTEM_H
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+extern void arch_reset(char mode, const char *cmd);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/timex.h linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/timex.h
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/timex.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,6 @@
+#ifndef __MACH_TIMEX_H
+#define __MACH_TIMEX_H
+
+#define CLOCK_TICK_RATE		1000000
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/uncompress.h linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/uncompress.h
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,9 @@
+#ifndef __MACH_UNCOMPRESS_H
+#define __MACH_UNCOMPRESS_H
+
+#define putc(c)
+#define flush()
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/vmalloc.h linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/vmalloc.h
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/include/mach/vmalloc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+#define VMALLOC_END		0xFEE00000UL
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/lluart.c linux-libre-3.2-gnu/arch/arm/mach-highbank/lluart.c
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/lluart.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/lluart.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/init.h>
+#include <asm/page.h>
+#include <asm/sizes.h>
+#include <asm/mach/map.h>
+
+#define HB_DEBUG_LL_PHYS_BASE	0xfff36000
+#define HB_DEBUG_LL_VIRT_BASE	0xfee36000
+
+static struct map_desc lluart_io_desc __initdata = {
+	.virtual	= HB_DEBUG_LL_VIRT_BASE,
+	.pfn		= __phys_to_pfn(HB_DEBUG_LL_PHYS_BASE),
+	.length		= SZ_4K,
+	.type		= MT_DEVICE,
+};
+
+void __init highbank_lluart_map_io(void)
+{
+	iotable_init(&lluart_io_desc, 1);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/localtimer.c linux-libre-3.2-gnu/arch/arm/mach-highbank/localtimer.c
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/localtimer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/localtimer.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ * Based on localtimer.c, Copyright (C) 2002 ARM Ltd.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/smp_twd.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
+	if (!twd_base) {
+		twd_base = of_iomap(np, 0);
+		WARN_ON(!twd_base);
+	}
+	evt->irq = irq_of_parse_and_map(np, 0);
+	twd_timer_setup(evt);
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/Makefile linux-libre-3.2-gnu/arch/arm/mach-highbank/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,6 @@
+obj-y					:= clock.o highbank.o system.o
+obj-$(CONFIG_DEBUG_HIGHBANK_UART)	+= lluart.o
+obj-$(CONFIG_SMP)			+= platsmp.o
+obj-$(CONFIG_LOCAL_TIMERS)		+= localtimer.o
+obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
+obj-$(CONFIG_PM_SLEEP)			+= pm.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-highbank/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+zreladdr-y	:= 0x00008000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/platsmp.c linux-libre-3.2-gnu/arch/arm/mach-highbank/platsmp.c
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/platsmp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/smp_scu.h>
+#include <asm/hardware/gic.h>
+
+#include "core.h"
+
+extern void secondary_startup(void);
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+	gic_secondary_init(0);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	gic_raise_softirq(cpumask_of(cpu), 0);
+	return 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)
+{
+	unsigned int i, ncores;
+
+	ncores = scu_get_core_count(scu_base_addr);
+
+	/* sanity check */
+	if (ncores > NR_CPUS) {
+		printk(KERN_WARNING
+		       "highbank: 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);
+
+	set_smp_cross_call(gic_raise_softirq);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+	int i;
+
+	scu_enable(scu_base_addr);
+
+	/*
+	 * Write the address of secondary startup into the jump table
+	 * The cores are in wfi and wait until they receive a soft interrupt
+	 * and a non-zero value to jump to. Then the secondary CPU branches
+	 * to this address.
+	 */
+	for (i = 1; i < max_cpus; i++)
+		highbank_set_cpu_jump(i, secondary_startup);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/pm.c linux-libre-3.2-gnu/arch/arm/mach-highbank/pm.c
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/suspend.h>
+
+#include <asm/proc-fns.h>
+#include <asm/smp_scu.h>
+#include <asm/suspend.h>
+
+#include "core.h"
+#include "sysregs.h"
+
+static int highbank_suspend_finish(unsigned long val)
+{
+	cpu_do_idle();
+	return 0;
+}
+
+static int highbank_pm_enter(suspend_state_t state)
+{
+	hignbank_set_pwr_suspend();
+	highbank_set_cpu_jump(0, cpu_resume);
+
+	scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+	cpu_suspend(0, highbank_suspend_finish);
+
+	return 0;
+}
+
+static const struct platform_suspend_ops highbank_pm_ops = {
+	.enter = highbank_pm_enter,
+	.valid = suspend_valid_only_mem,
+};
+
+static int __init highbank_pm_init(void)
+{
+	suspend_set_ops(&highbank_pm_ops);
+	return 0;
+}
+module_init(highbank_pm_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/sysregs.h linux-libre-3.2-gnu/arch/arm/mach-highbank/sysregs.h
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/sysregs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/sysregs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _MACH_HIGHBANK__SYSREGS_H_
+#define _MACH_HIGHBANK__SYSREGS_H_
+
+#include <linux/io.h>
+
+extern void __iomem *sregs_base;
+
+#define HB_SREG_A9_PWR_REQ		0xf00
+#define HB_SREG_A9_BOOT_STAT		0xf04
+#define HB_SREG_A9_BOOT_DATA		0xf08
+
+#define HB_PWR_SUSPEND			0
+#define HB_PWR_SOFT_RESET		1
+#define HB_PWR_HARD_RESET		2
+#define HB_PWR_SHUTDOWN			3
+
+static inline void hignbank_set_pwr_suspend(void)
+{
+	writel(HB_PWR_SUSPEND, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+static inline void hignbank_set_pwr_shutdown(void)
+{
+	writel(HB_PWR_SHUTDOWN, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+static inline void hignbank_set_pwr_soft_reset(void)
+{
+	writel(HB_PWR_SOFT_RESET, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+static inline void hignbank_set_pwr_hard_reset(void)
+{
+	writel(HB_PWR_HARD_RESET, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-highbank/system.c linux-libre-3.2-gnu/arch/arm/mach-highbank/system.c
--- linux-libre-3.1-gnu/arch/arm/mach-highbank/system.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-highbank/system.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/io.h>
+#include <asm/smp_scu.h>
+#include <asm/proc-fns.h>
+
+#include "core.h"
+#include "sysregs.h"
+
+void arch_reset(char mode, const char *cmd)
+{
+	if (mode == 'h')
+		hignbank_set_pwr_hard_reset();
+	else
+		hignbank_set_pwr_soft_reset();
+
+	scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+	cpu_do_idle();
+}
+
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/cache-l2x0.c linux-libre-3.2-gnu/arch/arm/mach-imx/cache-l2x0.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/cache-l2x0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/cache-l2x0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Pengutronix
- * Sascha Hauer <s.hauer@pengutronix.de>
- * Juergen Beisert <j.beisert@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 <linux/init.h>
-#include <linux/err.h>
-#include <linux/kernel.h>
-
-#include <asm/hardware/cache-l2x0.h>
-
-#include <mach/hardware.h>
-
-static int mxc_init_l2x0(void)
-{
-	void __iomem *l2x0_base;
-	void __iomem *clkctl_base;
-
-	if (!cpu_is_mx31() && !cpu_is_mx35())
-		return 0;
-
-/*
- * First of all, we must repair broken chip settings. There are some
- * i.MX35 CPUs in the wild, comming with bogus L2 cache settings. These
- * misconfigured CPUs will run amok immediately when the L2 cache gets enabled.
- * Workaraound is to setup the correct register setting prior enabling the
- * L2 cache. This should not hurt already working CPUs, as they are using the
- * same value.
- */
-#define L2_MEM_VAL 0x10
-
-	clkctl_base = ioremap(MX35_CLKCTL_BASE_ADDR, 4096);
-	if (clkctl_base != NULL) {
-		writel(0x00000515, clkctl_base + L2_MEM_VAL);
-		iounmap(clkctl_base);
-	} else {
-		pr_err("L2 cache: Cannot fix timing. Trying to continue without\n");
-	}
-
-	l2x0_base = ioremap(MX3x_L2CC_BASE_ADDR, 4096);
-	if (IS_ERR(l2x0_base)) {
-		printk(KERN_ERR "remapping L2 cache area failed with %ld\n",
-				PTR_ERR(l2x0_base));
-		return 0;
-	}
-
-	l2x0_init(l2x0_base, 0x00030024, 0x00000000);
-
-	return 0;
-}
-arch_initcall(mxc_init_l2x0);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/clock-imx25.c linux-libre-3.2-gnu/arch/arm/mach-imx/clock-imx25.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/clock-imx25.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/clock-imx25.c	2012-01-04 18:55:44.000000000 -0500
@@ -263,6 +263,7 @@
 DEFINE_CLOCK(csi_clk,    0, CCM_CGCR1,  4, get_rate_csi, NULL,  &csi_per_clk);
 DEFINE_CLOCK(can1_clk,	 0, CCM_CGCR1,  2, get_rate_ipg, NULL, NULL);
 DEFINE_CLOCK(can2_clk,	 1, CCM_CGCR1,  3, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(iim_clk,    0, CCM_CGCR1, 26, NULL, NULL, NULL);
 
 #define _REGISTER_CLOCK(d, n, c)	\
 	{				\
@@ -310,6 +311,7 @@
 	_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
 	/* i.mx25 has the i.mx35 type sdma */
 	_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
+	_REGISTER_CLOCK(NULL, "iim", iim_clk)
 };
 
 int __init mx25_clocks_init(void)
@@ -334,6 +336,10 @@
 	/* Clock source for gpt is ahb_div */
 	__raw_writel(__raw_readl(CRM_BASE+0x64) & ~(1 << 5), CRM_BASE + 0x64);
 
+	clk_enable(&iim_clk);
+	imx_print_silicon_rev("i.MX25", mx25_revision());
+	clk_disable(&iim_clk);
+
 	mxc_timer_init(&gpt_clk, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
 
 	return 0;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/clock-imx27.c linux-libre-3.2-gnu/arch/arm/mach-imx/clock-imx27.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/clock-imx27.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/clock-imx27.c	2012-01-04 18:55:44.000000000 -0500
@@ -583,7 +583,7 @@
 DEFINE_CLOCK(dma_clk1,     0, PCCR1, 20, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(csi_clk1,     0, PCCR1, 21, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(brom_clk,     0, PCCR1, 22, NULL, NULL, &ahb_clk);
-DEFINE_CLOCK(ata_clk,      0, PCCR1, 23, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(pata_clk,      0, PCCR1, 23, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(wdog_clk,     0, PCCR1, 24, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(usb_clk,      0, PCCR1, 25, get_rate_usb, &usb_clk1, &spll_clk);
 DEFINE_CLOCK(uart6_clk1,   0, PCCR1, 26, NULL, NULL, &ipg_clk);
@@ -666,7 +666,7 @@
 	_REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
 	_REGISTER_CLOCK(NULL, "emi", emi_clk)
 	_REGISTER_CLOCK(NULL, "sahara2", sahara2_clk)
-	_REGISTER_CLOCK(NULL, "ata", ata_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
 	_REGISTER_CLOCK(NULL, "mstick", mstick_clk)
 	_REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk)
 	_REGISTER_CLOCK(NULL, "gpio", gpio_clk)
@@ -751,6 +751,8 @@
 	clk_enable(&gpio_clk);
 	clk_enable(&emi_clk);
 	clk_enable(&iim_clk);
+	imx_print_silicon_rev("i.MX27", mx27_revision());
+	clk_disable(&iim_clk);
 
 #if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
 	clk_enable(&uart1_clk);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/clock-imx31.c linux-libre-3.2-gnu/arch/arm/mach-imx/clock-imx31.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/clock-imx31.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/clock-imx31.c	2012-01-04 18:55:44.000000000 -0500
@@ -476,7 +476,7 @@
 DEFINE_CLOCK(epit1_clk,   0, MXC_CCM_CGR0,  6, NULL, NULL, &perclk_clk);
 DEFINE_CLOCK(epit2_clk,   1, MXC_CCM_CGR0,  8, NULL, NULL, &perclk_clk);
 DEFINE_CLOCK(iim_clk,     0, MXC_CCM_CGR0, 10, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(ata_clk,     0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(pata_clk,     0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(sdma_clk1,   0, MXC_CCM_CGR0, 14, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(cspi3_clk,   2, MXC_CCM_CGR0, 16, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(rng_clk,     0, MXC_CCM_CGR0, 18, NULL, NULL, &ipg_clk);
@@ -562,7 +562,7 @@
 	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
 	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
 	_REGISTER_CLOCK(NULL, "firi", firi_clk)
-	_REGISTER_CLOCK(NULL, "ata", ata_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
 	_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
 	_REGISTER_CLOCK(NULL, "rng", rng_clk)
 	_REGISTER_CLOCK("imx31-sdma", NULL, sdma_clk1)
@@ -611,11 +611,11 @@
 	clk_enable(&gpt_clk);
 	clk_enable(&emi_clk);
 	clk_enable(&iim_clk);
+	mx31_revision();
+	clk_disable(&iim_clk);
 
 	clk_enable(&serial_pll_clk);
 
-	mx31_read_cpu_rev();
-
 	if (mx31_revision() >= IMX_CHIP_REVISION_2_0) {
 		reg = __raw_readl(MXC_CCM_PMCR1);
 		/* No PLL restart on DVFS switch; enable auto EMI handshake */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/clock-imx35.c linux-libre-3.2-gnu/arch/arm/mach-imx/clock-imx35.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/clock-imx35.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/clock-imx35.c	2012-01-04 18:55:44.000000000 -0500
@@ -354,7 +354,7 @@
 	}
 
 DEFINE_CLOCK(asrc_clk,   0, CCM_CGR0,  0, NULL, NULL);
-DEFINE_CLOCK(ata_clk,    0, CCM_CGR0,  2, get_rate_ipg, NULL);
+DEFINE_CLOCK(pata_clk,    0, CCM_CGR0,  2, get_rate_ipg, NULL);
 /* DEFINE_CLOCK(audmux_clk, 0, CCM_CGR0,  4, NULL, NULL); */
 DEFINE_CLOCK(can1_clk,   0, CCM_CGR0,  6, get_rate_ipg, NULL);
 DEFINE_CLOCK(can2_clk,   1, CCM_CGR0,  8, get_rate_ipg, NULL);
@@ -447,7 +447,7 @@
 
 static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "asrc", asrc_clk)
-	_REGISTER_CLOCK(NULL, "ata", ata_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
 	_REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
 	_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
 	_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi1_clk)
@@ -507,7 +507,7 @@
 
 int __init mx35_clocks_init()
 {
-	unsigned int cgr2 = 3 << 26, cgr3 = 0;
+	unsigned int cgr2 = 3 << 26;
 
 #if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
 	cgr2 |= 3 << 16;
@@ -521,6 +521,12 @@
 	__raw_writel((3 << 18), CCM_BASE + CCM_CGR0);
 	__raw_writel((3 << 2) | (3 << 4) | (3 << 6) | (3 << 8) | (3 << 16),
 			CCM_BASE + CCM_CGR1);
+	__raw_writel(cgr2, CCM_BASE + CCM_CGR2);
+	__raw_writel(0, CCM_BASE + CCM_CGR3);
+
+	clk_enable(&iim_clk);
+	imx_print_silicon_rev("i.MX35", mx35_revision());
+	clk_disable(&iim_clk);
 
 	/*
 	 * Check if we came up in internal boot mode. If yes, we need some
@@ -529,16 +535,11 @@
 	 */
 	if (!(__raw_readl(CCM_BASE + CCM_RCSR) & (3 << 10))) {
 		/* Additionally turn on UART1, SCC, and IIM clocks */
-		cgr2 |= 3 << 16 | 3 << 4;
-		cgr3 |= 3 << 2;
+		clk_enable(&iim_clk);
+		clk_enable(&uart1_clk);
+		clk_enable(&scc_clk);
 	}
 
-	__raw_writel(cgr2, CCM_BASE + CCM_CGR2);
-	__raw_writel(cgr3, CCM_BASE + CCM_CGR3);
-
-	clk_enable(&iim_clk);
-	mx35_read_cpu_rev();
-
 #ifdef CONFIG_MXC_USE_EPIT
 	epit_timer_init(&epit1_clk,
 			MX35_IO_ADDRESS(MX35_EPIT1_BASE_ADDR), MX35_INT_EPIT1);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/clock-imx6q.c linux-libre-3.2-gnu/arch/arm/mach-imx/clock-imx6q.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/clock-imx6q.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/clock-imx6q.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2030 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/types.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/div64.h>
+#include <asm/mach/map.h>
+#include <mach/clock.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+#define PLL_BASE		IMX_IO_ADDRESS(MX6Q_ANATOP_BASE_ADDR)
+#define PLL1_SYS		(PLL_BASE + 0x000)
+#define PLL2_BUS		(PLL_BASE + 0x030)
+#define PLL3_USB_OTG		(PLL_BASE + 0x010)
+#define PLL4_AUDIO		(PLL_BASE + 0x070)
+#define PLL5_VIDEO		(PLL_BASE + 0x0a0)
+#define PLL6_MLB		(PLL_BASE + 0x0d0)
+#define PLL7_USB_HOST		(PLL_BASE + 0x020)
+#define PLL8_ENET		(PLL_BASE + 0x0e0)
+#define PFD_480			(PLL_BASE + 0x0f0)
+#define PFD_528			(PLL_BASE + 0x100)
+#define PLL_NUM_OFFSET		0x010
+#define PLL_DENOM_OFFSET	0x020
+
+#define PFD0			7
+#define PFD1			15
+#define PFD2			23
+#define PFD3			31
+#define PFD_FRAC_MASK		0x3f
+
+#define BM_PLL_BYPASS			(0x1 << 16)
+#define BM_PLL_ENABLE			(0x1 << 13)
+#define BM_PLL_POWER_DOWN		(0x1 << 12)
+#define BM_PLL_LOCK			(0x1 << 31)
+#define BP_PLL_SYS_DIV_SELECT		0
+#define BM_PLL_SYS_DIV_SELECT		(0x7f << 0)
+#define BP_PLL_BUS_DIV_SELECT		0
+#define BM_PLL_BUS_DIV_SELECT		(0x1 << 0)
+#define BP_PLL_USB_DIV_SELECT		0
+#define BM_PLL_USB_DIV_SELECT		(0x3 << 0)
+#define BP_PLL_AV_DIV_SELECT		0
+#define BM_PLL_AV_DIV_SELECT		(0x7f << 0)
+#define BP_PLL_ENET_DIV_SELECT		0
+#define BM_PLL_ENET_DIV_SELECT		(0x3 << 0)
+#define BM_PLL_ENET_EN_PCIE		(0x1 << 19)
+#define BM_PLL_ENET_EN_SATA		(0x1 << 20)
+
+#define CCM_BASE	IMX_IO_ADDRESS(MX6Q_CCM_BASE_ADDR)
+#define CCR		(CCM_BASE + 0x00)
+#define CCDR		(CCM_BASE + 0x04)
+#define CSR		(CCM_BASE + 0x08)
+#define CCSR		(CCM_BASE + 0x0c)
+#define CACRR		(CCM_BASE + 0x10)
+#define CBCDR		(CCM_BASE + 0x14)
+#define CBCMR		(CCM_BASE + 0x18)
+#define CSCMR1		(CCM_BASE + 0x1c)
+#define CSCMR2		(CCM_BASE + 0x20)
+#define CSCDR1		(CCM_BASE + 0x24)
+#define CS1CDR		(CCM_BASE + 0x28)
+#define CS2CDR		(CCM_BASE + 0x2c)
+#define CDCDR		(CCM_BASE + 0x30)
+#define CHSCCDR		(CCM_BASE + 0x34)
+#define CSCDR2		(CCM_BASE + 0x38)
+#define CSCDR3		(CCM_BASE + 0x3c)
+#define CSCDR4		(CCM_BASE + 0x40)
+#define CWDR		(CCM_BASE + 0x44)
+#define CDHIPR		(CCM_BASE + 0x48)
+#define CDCR		(CCM_BASE + 0x4c)
+#define CTOR		(CCM_BASE + 0x50)
+#define CLPCR		(CCM_BASE + 0x54)
+#define CISR		(CCM_BASE + 0x58)
+#define CIMR		(CCM_BASE + 0x5c)
+#define CCOSR		(CCM_BASE + 0x60)
+#define CGPR		(CCM_BASE + 0x64)
+#define CCGR0		(CCM_BASE + 0x68)
+#define CCGR1		(CCM_BASE + 0x6c)
+#define CCGR2		(CCM_BASE + 0x70)
+#define CCGR3		(CCM_BASE + 0x74)
+#define CCGR4		(CCM_BASE + 0x78)
+#define CCGR5		(CCM_BASE + 0x7c)
+#define CCGR6		(CCM_BASE + 0x80)
+#define CCGR7		(CCM_BASE + 0x84)
+#define CMEOR		(CCM_BASE + 0x88)
+
+#define CG0		0
+#define CG1		2
+#define CG2		4
+#define CG3		6
+#define CG4		8
+#define CG5		10
+#define CG6		12
+#define CG7		14
+#define CG8		16
+#define CG9		18
+#define CG10		20
+#define CG11		22
+#define CG12		24
+#define CG13		26
+#define CG14		28
+#define CG15		30
+
+#define BM_CCSR_PLL1_SW_SEL		(0x1 << 2)
+#define BM_CCSR_STEP_SEL		(0x1 << 8)
+
+#define BP_CACRR_ARM_PODF		0
+#define BM_CACRR_ARM_PODF		(0x7 << 0)
+
+#define BP_CBCDR_PERIPH2_CLK2_PODF	0
+#define BM_CBCDR_PERIPH2_CLK2_PODF	(0x7 << 0)
+#define BP_CBCDR_MMDC_CH1_AXI_PODF	3
+#define BM_CBCDR_MMDC_CH1_AXI_PODF	(0x7 << 3)
+#define BP_CBCDR_AXI_SEL		6
+#define BM_CBCDR_AXI_SEL		(0x3 << 6)
+#define BP_CBCDR_IPG_PODF		8
+#define BM_CBCDR_IPG_PODF		(0x3 << 8)
+#define BP_CBCDR_AHB_PODF		10
+#define BM_CBCDR_AHB_PODF		(0x7 << 10)
+#define BP_CBCDR_AXI_PODF		16
+#define BM_CBCDR_AXI_PODF		(0x7 << 16)
+#define BP_CBCDR_MMDC_CH0_AXI_PODF	19
+#define BM_CBCDR_MMDC_CH0_AXI_PODF	(0x7 << 19)
+#define BP_CBCDR_PERIPH_CLK_SEL		25
+#define BM_CBCDR_PERIPH_CLK_SEL		(0x1 << 25)
+#define BP_CBCDR_PERIPH2_CLK_SEL	26
+#define BM_CBCDR_PERIPH2_CLK_SEL	(0x1 << 26)
+#define BP_CBCDR_PERIPH_CLK2_PODF	27
+#define BM_CBCDR_PERIPH_CLK2_PODF	(0x7 << 27)
+
+#define BP_CBCMR_GPU2D_AXI_SEL		0
+#define BM_CBCMR_GPU2D_AXI_SEL		(0x1 << 0)
+#define BP_CBCMR_GPU3D_AXI_SEL		1
+#define BM_CBCMR_GPU3D_AXI_SEL		(0x1 << 1)
+#define BP_CBCMR_GPU3D_CORE_SEL		4
+#define BM_CBCMR_GPU3D_CORE_SEL		(0x3 << 4)
+#define BP_CBCMR_GPU3D_SHADER_SEL	8
+#define BM_CBCMR_GPU3D_SHADER_SEL	(0x3 << 8)
+#define BP_CBCMR_PCIE_AXI_SEL		10
+#define BM_CBCMR_PCIE_AXI_SEL		(0x1 << 10)
+#define BP_CBCMR_VDO_AXI_SEL		11
+#define BM_CBCMR_VDO_AXI_SEL		(0x1 << 11)
+#define BP_CBCMR_PERIPH_CLK2_SEL	12
+#define BM_CBCMR_PERIPH_CLK2_SEL	(0x3 << 12)
+#define BP_CBCMR_VPU_AXI_SEL		14
+#define BM_CBCMR_VPU_AXI_SEL		(0x3 << 14)
+#define BP_CBCMR_GPU2D_CORE_SEL		16
+#define BM_CBCMR_GPU2D_CORE_SEL		(0x3 << 16)
+#define BP_CBCMR_PRE_PERIPH_CLK_SEL	18
+#define BM_CBCMR_PRE_PERIPH_CLK_SEL	(0x3 << 18)
+#define BP_CBCMR_PERIPH2_CLK2_SEL	20
+#define BM_CBCMR_PERIPH2_CLK2_SEL	(0x1 << 20)
+#define BP_CBCMR_PRE_PERIPH2_CLK_SEL	21
+#define BM_CBCMR_PRE_PERIPH2_CLK_SEL	(0x3 << 21)
+#define BP_CBCMR_GPU2D_CORE_PODF	23
+#define BM_CBCMR_GPU2D_CORE_PODF	(0x7 << 23)
+#define BP_CBCMR_GPU3D_CORE_PODF	26
+#define BM_CBCMR_GPU3D_CORE_PODF	(0x7 << 26)
+#define BP_CBCMR_GPU3D_SHADER_PODF	29
+#define BM_CBCMR_GPU3D_SHADER_PODF	(0x7 << 29)
+
+#define BP_CSCMR1_PERCLK_PODF		0
+#define BM_CSCMR1_PERCLK_PODF		(0x3f << 0)
+#define BP_CSCMR1_SSI1_SEL		10
+#define BM_CSCMR1_SSI1_SEL		(0x3 << 10)
+#define BP_CSCMR1_SSI2_SEL		12
+#define BM_CSCMR1_SSI2_SEL		(0x3 << 12)
+#define BP_CSCMR1_SSI3_SEL		14
+#define BM_CSCMR1_SSI3_SEL		(0x3 << 14)
+#define BP_CSCMR1_USDHC1_SEL		16
+#define BM_CSCMR1_USDHC1_SEL		(0x1 << 16)
+#define BP_CSCMR1_USDHC2_SEL		17
+#define BM_CSCMR1_USDHC2_SEL		(0x1 << 17)
+#define BP_CSCMR1_USDHC3_SEL		18
+#define BM_CSCMR1_USDHC3_SEL		(0x1 << 18)
+#define BP_CSCMR1_USDHC4_SEL		19
+#define BM_CSCMR1_USDHC4_SEL		(0x1 << 19)
+#define BP_CSCMR1_EMI_PODF		20
+#define BM_CSCMR1_EMI_PODF		(0x7 << 20)
+#define BP_CSCMR1_EMI_SLOW_PODF		23
+#define BM_CSCMR1_EMI_SLOW_PODF		(0x7 << 23)
+#define BP_CSCMR1_EMI_SEL		27
+#define BM_CSCMR1_EMI_SEL		(0x3 << 27)
+#define BP_CSCMR1_EMI_SLOW_SEL		29
+#define BM_CSCMR1_EMI_SLOW_SEL		(0x3 << 29)
+
+#define BP_CSCMR2_CAN_PODF		2
+#define BM_CSCMR2_CAN_PODF		(0x3f << 2)
+#define BM_CSCMR2_LDB_DI0_IPU_DIV	(0x1 << 10)
+#define BM_CSCMR2_LDB_DI1_IPU_DIV	(0x1 << 11)
+#define BP_CSCMR2_ESAI_SEL		19
+#define BM_CSCMR2_ESAI_SEL		(0x3 << 19)
+
+#define BP_CSCDR1_UART_PODF		0
+#define BM_CSCDR1_UART_PODF		(0x3f << 0)
+#define BP_CSCDR1_USDHC1_PODF		11
+#define BM_CSCDR1_USDHC1_PODF		(0x7 << 11)
+#define BP_CSCDR1_USDHC2_PODF		16
+#define BM_CSCDR1_USDHC2_PODF		(0x7 << 16)
+#define BP_CSCDR1_USDHC3_PODF		19
+#define BM_CSCDR1_USDHC3_PODF		(0x7 << 19)
+#define BP_CSCDR1_USDHC4_PODF		22
+#define BM_CSCDR1_USDHC4_PODF		(0x7 << 22)
+#define BP_CSCDR1_VPU_AXI_PODF		25
+#define BM_CSCDR1_VPU_AXI_PODF		(0x7 << 25)
+
+#define BP_CS1CDR_SSI1_PODF		0
+#define BM_CS1CDR_SSI1_PODF		(0x3f << 0)
+#define BP_CS1CDR_SSI1_PRED		6
+#define BM_CS1CDR_SSI1_PRED		(0x7 << 6)
+#define BP_CS1CDR_ESAI_PRED		9
+#define BM_CS1CDR_ESAI_PRED		(0x7 << 9)
+#define BP_CS1CDR_SSI3_PODF		16
+#define BM_CS1CDR_SSI3_PODF		(0x3f << 16)
+#define BP_CS1CDR_SSI3_PRED		22
+#define BM_CS1CDR_SSI3_PRED		(0x7 << 22)
+#define BP_CS1CDR_ESAI_PODF		25
+#define BM_CS1CDR_ESAI_PODF		(0x7 << 25)
+
+#define BP_CS2CDR_SSI2_PODF		0
+#define BM_CS2CDR_SSI2_PODF		(0x3f << 0)
+#define BP_CS2CDR_SSI2_PRED		6
+#define BM_CS2CDR_SSI2_PRED		(0x7 << 6)
+#define BP_CS2CDR_LDB_DI0_SEL		9
+#define BM_CS2CDR_LDB_DI0_SEL		(0x7 << 9)
+#define BP_CS2CDR_LDB_DI1_SEL		12
+#define BM_CS2CDR_LDB_DI1_SEL		(0x7 << 12)
+#define BP_CS2CDR_ENFC_SEL		16
+#define BM_CS2CDR_ENFC_SEL		(0x3 << 16)
+#define BP_CS2CDR_ENFC_PRED		18
+#define BM_CS2CDR_ENFC_PRED		(0x7 << 18)
+#define BP_CS2CDR_ENFC_PODF		21
+#define BM_CS2CDR_ENFC_PODF		(0x3f << 21)
+
+#define BP_CDCDR_ASRC_SERIAL_SEL	7
+#define BM_CDCDR_ASRC_SERIAL_SEL	(0x3 << 7)
+#define BP_CDCDR_ASRC_SERIAL_PODF	9
+#define BM_CDCDR_ASRC_SERIAL_PODF	(0x7 << 9)
+#define BP_CDCDR_ASRC_SERIAL_PRED	12
+#define BM_CDCDR_ASRC_SERIAL_PRED	(0x7 << 12)
+#define BP_CDCDR_SPDIF_SEL		20
+#define BM_CDCDR_SPDIF_SEL		(0x3 << 20)
+#define BP_CDCDR_SPDIF_PODF		22
+#define BM_CDCDR_SPDIF_PODF		(0x7 << 22)
+#define BP_CDCDR_SPDIF_PRED		25
+#define BM_CDCDR_SPDIF_PRED		(0x7 << 25)
+#define BP_CDCDR_HSI_TX_PODF		29
+#define BM_CDCDR_HSI_TX_PODF		(0x7 << 29)
+#define BP_CDCDR_HSI_TX_SEL		28
+#define BM_CDCDR_HSI_TX_SEL		(0x1 << 28)
+
+#define BP_CHSCCDR_IPU1_DI0_SEL		0
+#define BM_CHSCCDR_IPU1_DI0_SEL		(0x7 << 0)
+#define BP_CHSCCDR_IPU1_DI0_PRE_PODF	3
+#define BM_CHSCCDR_IPU1_DI0_PRE_PODF	(0x7 << 3)
+#define BP_CHSCCDR_IPU1_DI0_PRE_SEL	6
+#define BM_CHSCCDR_IPU1_DI0_PRE_SEL	(0x7 << 6)
+#define BP_CHSCCDR_IPU1_DI1_SEL		9
+#define BM_CHSCCDR_IPU1_DI1_SEL		(0x7 << 9)
+#define BP_CHSCCDR_IPU1_DI1_PRE_PODF	12
+#define BM_CHSCCDR_IPU1_DI1_PRE_PODF	(0x7 << 12)
+#define BP_CHSCCDR_IPU1_DI1_PRE_SEL	15
+#define BM_CHSCCDR_IPU1_DI1_PRE_SEL	(0x7 << 15)
+
+#define BP_CSCDR2_IPU2_DI0_SEL		0
+#define BM_CSCDR2_IPU2_DI0_SEL		(0x7)
+#define BP_CSCDR2_IPU2_DI0_PRE_PODF	3
+#define BM_CSCDR2_IPU2_DI0_PRE_PODF	(0x7 << 3)
+#define BP_CSCDR2_IPU2_DI0_PRE_SEL	6
+#define BM_CSCDR2_IPU2_DI0_PRE_SEL	(0x7 << 6)
+#define BP_CSCDR2_IPU2_DI1_SEL		9
+#define BM_CSCDR2_IPU2_DI1_SEL		(0x7 << 9)
+#define BP_CSCDR2_IPU2_DI1_PRE_PODF	12
+#define BM_CSCDR2_IPU2_DI1_PRE_PODF	(0x7 << 12)
+#define BP_CSCDR2_IPU2_DI1_PRE_SEL	15
+#define BM_CSCDR2_IPU2_DI1_PRE_SEL	(0x7 << 15)
+#define BP_CSCDR2_ECSPI_CLK_PODF	19
+#define BM_CSCDR2_ECSPI_CLK_PODF	(0x3f << 19)
+
+#define BP_CSCDR3_IPU1_HSP_SEL		9
+#define BM_CSCDR3_IPU1_HSP_SEL		(0x3 << 9)
+#define BP_CSCDR3_IPU1_HSP_PODF		11
+#define BM_CSCDR3_IPU1_HSP_PODF		(0x7 << 11)
+#define BP_CSCDR3_IPU2_HSP_SEL		14
+#define BM_CSCDR3_IPU2_HSP_SEL		(0x3 << 14)
+#define BP_CSCDR3_IPU2_HSP_PODF		16
+#define BM_CSCDR3_IPU2_HSP_PODF		(0x7 << 16)
+
+#define BM_CDHIPR_AXI_PODF_BUSY		(0x1 << 0)
+#define BM_CDHIPR_AHB_PODF_BUSY		(0x1 << 1)
+#define BM_CDHIPR_MMDC_CH1_PODF_BUSY	(0x1 << 2)
+#define BM_CDHIPR_PERIPH2_SEL_BUSY	(0x1 << 3)
+#define BM_CDHIPR_MMDC_CH0_PODF_BUSY	(0x1 << 4)
+#define BM_CDHIPR_PERIPH_SEL_BUSY	(0x1 << 5)
+#define BM_CDHIPR_ARM_PODF_BUSY		(0x1 << 16)
+
+#define BP_CLPCR_LPM			0
+#define BM_CLPCR_LPM			(0x3 << 0)
+#define BM_CLPCR_BYPASS_PMIC_READY	(0x1 << 2)
+#define BM_CLPCR_ARM_CLK_DIS_ON_LPM	(0x1 << 5)
+#define BM_CLPCR_SBYOS			(0x1 << 6)
+#define BM_CLPCR_DIS_REF_OSC		(0x1 << 7)
+#define BM_CLPCR_VSTBY			(0x1 << 8)
+#define BP_CLPCR_STBY_COUNT		9
+#define BM_CLPCR_STBY_COUNT		(0x3 << 9)
+#define BM_CLPCR_COSC_PWRDOWN		(0x1 << 11)
+#define BM_CLPCR_WB_PER_AT_LPM		(0x1 << 16)
+#define BM_CLPCR_WB_CORE_AT_LPM		(0x1 << 17)
+#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS	(0x1 << 19)
+#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS	(0x1 << 21)
+#define BM_CLPCR_MASK_CORE0_WFI		(0x1 << 22)
+#define BM_CLPCR_MASK_CORE1_WFI		(0x1 << 23)
+#define BM_CLPCR_MASK_CORE2_WFI		(0x1 << 24)
+#define BM_CLPCR_MASK_CORE3_WFI		(0x1 << 25)
+#define BM_CLPCR_MASK_SCU_IDLE		(0x1 << 26)
+#define BM_CLPCR_MASK_L2CC_IDLE		(0x1 << 27)
+
+#define FREQ_480M	480000000
+#define FREQ_528M	528000000
+#define FREQ_594M	594000000
+#define FREQ_650M	650000000
+#define FREQ_1300M	1300000000
+
+static struct clk pll1_sys;
+static struct clk pll2_bus;
+static struct clk pll3_usb_otg;
+static struct clk pll4_audio;
+static struct clk pll5_video;
+static struct clk pll6_mlb;
+static struct clk pll7_usb_host;
+static struct clk pll8_enet;
+static struct clk apbh_dma_clk;
+static struct clk arm_clk;
+static struct clk ipg_clk;
+static struct clk ahb_clk;
+static struct clk axi_clk;
+static struct clk mmdc_ch0_axi_clk;
+static struct clk mmdc_ch1_axi_clk;
+static struct clk periph_clk;
+static struct clk periph_pre_clk;
+static struct clk periph_clk2_clk;
+static struct clk periph2_clk;
+static struct clk periph2_pre_clk;
+static struct clk periph2_clk2_clk;
+static struct clk gpu2d_core_clk;
+static struct clk gpu3d_core_clk;
+static struct clk gpu3d_shader_clk;
+static struct clk ipg_perclk;
+static struct clk emi_clk;
+static struct clk emi_slow_clk;
+static struct clk can1_clk;
+static struct clk uart_clk;
+static struct clk usdhc1_clk;
+static struct clk usdhc2_clk;
+static struct clk usdhc3_clk;
+static struct clk usdhc4_clk;
+static struct clk vpu_clk;
+static struct clk hsi_tx_clk;
+static struct clk ipu1_di0_pre_clk;
+static struct clk ipu1_di1_pre_clk;
+static struct clk ipu2_di0_pre_clk;
+static struct clk ipu2_di1_pre_clk;
+static struct clk ipu1_clk;
+static struct clk ipu2_clk;
+static struct clk ssi1_clk;
+static struct clk ssi3_clk;
+static struct clk esai_clk;
+static struct clk ssi2_clk;
+static struct clk spdif_clk;
+static struct clk asrc_serial_clk;
+static struct clk gpu2d_axi_clk;
+static struct clk gpu3d_axi_clk;
+static struct clk pcie_clk;
+static struct clk vdo_axi_clk;
+static struct clk ldb_di0_clk;
+static struct clk ldb_di1_clk;
+static struct clk ipu1_di0_clk;
+static struct clk ipu1_di1_clk;
+static struct clk ipu2_di0_clk;
+static struct clk ipu2_di1_clk;
+static struct clk enfc_clk;
+static struct clk dummy_clk = {};
+
+static unsigned long external_high_reference;
+static unsigned long external_low_reference;
+static unsigned long oscillator_reference;
+
+static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
+{
+	return oscillator_reference;
+}
+
+static unsigned long get_high_reference_clock_rate(struct clk *clk)
+{
+	return external_high_reference;
+}
+
+static unsigned long get_low_reference_clock_rate(struct clk *clk)
+{
+	return external_low_reference;
+}
+
+static struct clk ckil_clk = {
+	.get_rate = get_low_reference_clock_rate,
+};
+
+static struct clk ckih_clk = {
+	.get_rate = get_high_reference_clock_rate,
+};
+
+static struct clk osc_clk = {
+	.get_rate = get_oscillator_reference_clock_rate,
+};
+
+static inline void __iomem *pll_get_reg_addr(struct clk *pll)
+{
+	if (pll == &pll1_sys)
+		return PLL1_SYS;
+	else if (pll == &pll2_bus)
+		return PLL2_BUS;
+	else if (pll == &pll3_usb_otg)
+		return PLL3_USB_OTG;
+	else if (pll == &pll4_audio)
+		return PLL4_AUDIO;
+	else if (pll == &pll5_video)
+		return PLL5_VIDEO;
+	else if (pll == &pll6_mlb)
+		return PLL6_MLB;
+	else if (pll == &pll7_usb_host)
+		return PLL7_USB_HOST;
+	else if (pll == &pll8_enet)
+		return PLL8_ENET;
+	else
+		BUG();
+
+	return NULL;
+}
+
+static int pll_enable(struct clk *clk)
+{
+	int timeout = 0x100000;
+	void __iomem *reg;
+	u32 val;
+
+	reg = pll_get_reg_addr(clk);
+	val = readl_relaxed(reg);
+	val &= ~BM_PLL_BYPASS;
+	val &= ~BM_PLL_POWER_DOWN;
+	/* 480MHz PLLs have the opposite definition for power bit */
+	if (clk == &pll3_usb_otg || clk == &pll7_usb_host)
+		val |= BM_PLL_POWER_DOWN;
+	writel_relaxed(val, reg);
+
+	/* Wait for PLL to lock */
+	while (!(readl_relaxed(reg) & BM_PLL_LOCK) && --timeout)
+		cpu_relax();
+
+	if (unlikely(!timeout))
+		return -EBUSY;
+
+	/* Enable the PLL output now */
+	val = readl_relaxed(reg);
+	val |= BM_PLL_ENABLE;
+	writel_relaxed(val, reg);
+
+	return 0;
+}
+
+static void pll_disable(struct clk *clk)
+{
+	void __iomem *reg;
+	u32 val;
+
+	reg = pll_get_reg_addr(clk);
+	val = readl_relaxed(reg);
+	val &= ~BM_PLL_ENABLE;
+	val |= BM_PLL_BYPASS;
+	val |= BM_PLL_POWER_DOWN;
+	if (clk == &pll3_usb_otg || clk == &pll7_usb_host)
+		val &= ~BM_PLL_POWER_DOWN;
+	writel_relaxed(val, reg);
+}
+
+static unsigned long pll1_sys_get_rate(struct clk *clk)
+{
+	u32 div = (readl_relaxed(PLL1_SYS) & BM_PLL_SYS_DIV_SELECT) >>
+		  BP_PLL_SYS_DIV_SELECT;
+
+	return clk_get_rate(clk->parent) * div / 2;
+}
+
+static int pll1_sys_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 val, div;
+
+	if (rate < FREQ_650M || rate > FREQ_1300M)
+		return -EINVAL;
+
+	div = rate * 2 / clk_get_rate(clk->parent);
+	val = readl_relaxed(PLL1_SYS);
+	val &= ~BM_PLL_SYS_DIV_SELECT;
+	val |= div << BP_PLL_SYS_DIV_SELECT;
+	writel_relaxed(val, PLL1_SYS);
+
+	return 0;
+}
+
+static unsigned long pll8_enet_get_rate(struct clk *clk)
+{
+	u32 div = (readl_relaxed(PLL8_ENET) & BM_PLL_ENET_DIV_SELECT) >>
+		  BP_PLL_ENET_DIV_SELECT;
+
+	switch (div) {
+	case 0:
+		return 25000000;
+	case 1:
+		return 50000000;
+	case 2:
+		return 100000000;
+	case 3:
+		return 125000000;
+	}
+
+	return 0;
+}
+
+static int pll8_enet_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 val, div;
+
+	switch (rate) {
+	case 25000000:
+		div = 0;
+		break;
+	case 50000000:
+		div = 1;
+		break;
+	case 100000000:
+		div = 2;
+		break;
+	case 125000000:
+		div = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	val = readl_relaxed(PLL8_ENET);
+	val &= ~BM_PLL_ENET_DIV_SELECT;
+	val |= div << BP_PLL_ENET_DIV_SELECT;
+	writel_relaxed(val, PLL8_ENET);
+
+	return 0;
+}
+
+static unsigned long pll_av_get_rate(struct clk *clk)
+{
+	void __iomem *reg = (clk == &pll4_audio) ? PLL4_AUDIO : PLL5_VIDEO;
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	u32 mfn = readl_relaxed(reg + PLL_NUM_OFFSET);
+	u32 mfd = readl_relaxed(reg + PLL_DENOM_OFFSET);
+	u32 div = (readl_relaxed(reg) & BM_PLL_AV_DIV_SELECT) >>
+		  BP_PLL_AV_DIV_SELECT;
+
+	return (parent_rate * div) + ((parent_rate / mfd) * mfn);
+}
+
+static int pll_av_set_rate(struct clk *clk, unsigned long rate)
+{
+	void __iomem *reg = (clk == &pll4_audio) ? PLL4_AUDIO : PLL5_VIDEO;
+	unsigned int parent_rate = clk_get_rate(clk->parent);
+	u32 val, div;
+	u32 mfn, mfd = 1000000;
+	s64 temp64;
+
+	if (rate < FREQ_650M || rate > FREQ_1300M)
+		return -EINVAL;
+
+	div = rate / parent_rate;
+	temp64 = (u64) (rate - div * parent_rate);
+	temp64 *= mfd;
+	do_div(temp64, parent_rate);
+	mfn = temp64;
+
+	val = readl_relaxed(reg);
+	val &= ~BM_PLL_AV_DIV_SELECT;
+	val |= div << BP_PLL_AV_DIV_SELECT;
+	writel_relaxed(val, reg);
+	writel_relaxed(mfn, reg + PLL_NUM_OFFSET);
+	writel_relaxed(mfd, reg + PLL_DENOM_OFFSET);
+
+	return 0;
+}
+
+static void __iomem *pll_get_div_reg_bit(struct clk *clk, u32 *bp, u32 *bm)
+{
+	void __iomem *reg;
+
+	if (clk == &pll2_bus) {
+		reg = PLL2_BUS;
+		*bp = BP_PLL_BUS_DIV_SELECT;
+		*bm = BM_PLL_BUS_DIV_SELECT;
+	} else if (clk == &pll3_usb_otg) {
+		reg = PLL3_USB_OTG;
+		*bp = BP_PLL_USB_DIV_SELECT;
+		*bm = BM_PLL_USB_DIV_SELECT;
+	} else if (clk == &pll7_usb_host) {
+		reg = PLL7_USB_HOST;
+		*bp = BP_PLL_USB_DIV_SELECT;
+		*bm = BM_PLL_USB_DIV_SELECT;
+	} else {
+		BUG();
+	}
+
+	return reg;
+}
+
+static unsigned long pll_get_rate(struct clk *clk)
+{
+	void __iomem *reg;
+	u32 div, bp, bm;
+
+	reg = pll_get_div_reg_bit(clk, &bp, &bm);
+	div = (readl_relaxed(reg) & bm) >> bp;
+
+	return (div == 1) ? clk_get_rate(clk->parent) * 22 :
+			    clk_get_rate(clk->parent) * 20;
+}
+
+static int pll_set_rate(struct clk *clk, unsigned long rate)
+{
+	void __iomem *reg;
+	u32 val, div, bp, bm;
+
+	if (rate == FREQ_528M)
+		div = 1;
+	else if (rate == FREQ_480M)
+		div = 0;
+	else
+		return -EINVAL;
+
+	reg = pll_get_div_reg_bit(clk, &bp, &bm);
+	val = readl_relaxed(reg);
+	val &= ~bm;
+	val |= div << bp;
+	writel_relaxed(val, reg);
+
+	return 0;
+}
+
+#define pll2_bus_get_rate	pll_get_rate
+#define pll2_bus_set_rate	pll_set_rate
+#define pll3_usb_otg_get_rate	pll_get_rate
+#define pll3_usb_otg_set_rate	pll_set_rate
+#define pll7_usb_host_get_rate	pll_get_rate
+#define pll7_usb_host_set_rate	pll_set_rate
+#define pll4_audio_get_rate	pll_av_get_rate
+#define pll4_audio_set_rate	pll_av_set_rate
+#define pll5_video_get_rate	pll_av_get_rate
+#define pll5_video_set_rate	pll_av_set_rate
+#define pll6_mlb_get_rate	NULL
+#define pll6_mlb_set_rate	NULL
+
+#define DEF_PLL(name)					\
+	static struct clk name = {			\
+		.enable		= pll_enable,		\
+		.disable	= pll_disable,		\
+		.get_rate	= name##_get_rate,	\
+		.set_rate	= name##_set_rate,	\
+		.parent		= &osc_clk,		\
+	}
+
+DEF_PLL(pll1_sys);
+DEF_PLL(pll2_bus);
+DEF_PLL(pll3_usb_otg);
+DEF_PLL(pll4_audio);
+DEF_PLL(pll5_video);
+DEF_PLL(pll6_mlb);
+DEF_PLL(pll7_usb_host);
+DEF_PLL(pll8_enet);
+
+static unsigned long pfd_get_rate(struct clk *clk)
+{
+	u64 tmp = (u64) clk_get_rate(clk->parent) * 18;
+	u32 frac, bp_frac;
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.enable(&apbh_dma_clk);
+
+	bp_frac = clk->enable_shift - 7;
+	frac = readl_relaxed(clk->enable_reg) >> bp_frac & PFD_FRAC_MASK;
+	do_div(tmp, frac);
+
+	return tmp;
+}
+
+static int pfd_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 val, frac, bp_frac;
+	u64 tmp = (u64) clk_get_rate(clk->parent) * 18;
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.enable(&apbh_dma_clk);
+
+	/*
+	 * Round up the divider so that we don't set a rate
+	 * higher than what is requested
+	 */
+	tmp += rate / 2;
+	do_div(tmp, rate);
+	frac = tmp;
+	frac = (frac < 12) ? 12 : frac;
+	frac = (frac > 35) ? 35 : frac;
+
+	/*
+	 * The frac field always starts from 7 bits lower
+	 * position of enable bit
+	 */
+	bp_frac = clk->enable_shift - 7;
+	val = readl_relaxed(clk->enable_reg);
+	val &= ~(PFD_FRAC_MASK << bp_frac);
+	val |= frac << bp_frac;
+	writel_relaxed(val, clk->enable_reg);
+
+	tmp = (u64) clk_get_rate(clk->parent) * 18;
+	do_div(tmp, frac);
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.disable(&apbh_dma_clk);
+
+	return 0;
+}
+
+static unsigned long pfd_round_rate(struct clk *clk, unsigned long rate)
+{
+	u32 frac;
+	u64 tmp;
+
+	tmp = (u64) clk_get_rate(clk->parent) * 18;
+	tmp += rate / 2;
+	do_div(tmp, rate);
+	frac = tmp;
+	frac = (frac < 12) ? 12 : frac;
+	frac = (frac > 35) ? 35 : frac;
+	tmp = (u64) clk_get_rate(clk->parent) * 18;
+	do_div(tmp, frac);
+
+	return tmp;
+}
+
+static int pfd_enable(struct clk *clk)
+{
+	u32 val;
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.enable(&apbh_dma_clk);
+
+	val = readl_relaxed(clk->enable_reg);
+	val &= ~(1 << clk->enable_shift);
+	writel_relaxed(val, clk->enable_reg);
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.disable(&apbh_dma_clk);
+
+	return 0;
+}
+
+static void pfd_disable(struct clk *clk)
+{
+	u32 val;
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.enable(&apbh_dma_clk);
+
+	val = readl_relaxed(clk->enable_reg);
+	val |= 1 << clk->enable_shift;
+	writel_relaxed(val, clk->enable_reg);
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.disable(&apbh_dma_clk);
+}
+
+#define DEF_PFD(name, er, es, p)			\
+	static struct clk name = {			\
+		.enable_reg	= er,			\
+		.enable_shift	= es,			\
+		.enable		= pfd_enable,		\
+		.disable	= pfd_disable,		\
+		.get_rate	= pfd_get_rate,		\
+		.set_rate	= pfd_set_rate,		\
+		.round_rate	= pfd_round_rate,	\
+		.parent		= p,			\
+	}
+
+DEF_PFD(pll2_pfd_352m, PFD_528, PFD0, &pll2_bus);
+DEF_PFD(pll2_pfd_594m, PFD_528, PFD1, &pll2_bus);
+DEF_PFD(pll2_pfd_400m, PFD_528, PFD2, &pll2_bus);
+DEF_PFD(pll3_pfd_720m, PFD_480, PFD0, &pll3_usb_otg);
+DEF_PFD(pll3_pfd_540m, PFD_480, PFD1, &pll3_usb_otg);
+DEF_PFD(pll3_pfd_508m, PFD_480, PFD2, &pll3_usb_otg);
+DEF_PFD(pll3_pfd_454m, PFD_480, PFD3, &pll3_usb_otg);
+
+static unsigned long pll2_200m_get_rate(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 2;
+}
+
+static struct clk pll2_200m = {
+	.parent = &pll2_pfd_400m,
+	.get_rate = pll2_200m_get_rate,
+};
+
+static unsigned long pll3_120m_get_rate(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 4;
+}
+
+static struct clk pll3_120m = {
+	.parent = &pll3_usb_otg,
+	.get_rate = pll3_120m_get_rate,
+};
+
+static unsigned long pll3_80m_get_rate(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 6;
+}
+
+static struct clk pll3_80m = {
+	.parent = &pll3_usb_otg,
+	.get_rate = pll3_80m_get_rate,
+};
+
+static unsigned long pll3_60m_get_rate(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 8;
+}
+
+static struct clk pll3_60m = {
+	.parent = &pll3_usb_otg,
+	.get_rate = pll3_60m_get_rate,
+};
+
+static int pll1_sw_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 val = readl_relaxed(CCSR);
+
+	if (parent == &pll1_sys) {
+		val &= ~BM_CCSR_PLL1_SW_SEL;
+		val &= ~BM_CCSR_STEP_SEL;
+	} else if (parent == &osc_clk) {
+		val |= BM_CCSR_PLL1_SW_SEL;
+		val &= ~BM_CCSR_STEP_SEL;
+	} else if (parent == &pll2_pfd_400m) {
+		val |= BM_CCSR_PLL1_SW_SEL;
+		val |= BM_CCSR_STEP_SEL;
+	} else {
+		return -EINVAL;
+	}
+
+	writel_relaxed(val, CCSR);
+
+	return 0;
+}
+
+static struct clk pll1_sw_clk = {
+	.parent = &pll1_sys,
+	.set_parent = pll1_sw_clk_set_parent,
+};
+
+static void calc_pred_podf_dividers(u32 div, u32 *pred, u32 *podf)
+{
+	u32 min_pred, temp_pred, old_err, err;
+
+	if (div >= 512) {
+		*pred = 8;
+		*podf = 64;
+	} else if (div >= 8) {
+		min_pred = (div - 1) / 64 + 1;
+		old_err = 8;
+		for (temp_pred = 8; temp_pred >= min_pred; temp_pred--) {
+			err = div % temp_pred;
+			if (err == 0) {
+				*pred = temp_pred;
+				break;
+			}
+			err = temp_pred - err;
+			if (err < old_err) {
+				old_err = err;
+				*pred = temp_pred;
+			}
+		}
+		*podf = (div + *pred - 1) / *pred;
+	} else if (div < 8) {
+		*pred = div;
+		*podf = 1;
+	}
+}
+
+static int _clk_enable(struct clk *clk)
+{
+	u32 reg;
+	reg = readl_relaxed(clk->enable_reg);
+	reg |= 0x3 << clk->enable_shift;
+	writel_relaxed(reg, clk->enable_reg);
+
+	return 0;
+}
+
+static void _clk_disable(struct clk *clk)
+{
+	u32 reg;
+	reg = readl_relaxed(clk->enable_reg);
+	reg &= ~(0x3 << clk->enable_shift);
+	writel_relaxed(reg, clk->enable_reg);
+}
+
+struct divider {
+	struct clk *clk;
+	void __iomem *reg;
+	u32 bp_pred;
+	u32 bm_pred;
+	u32 bp_podf;
+	u32 bm_podf;
+};
+
+#define DEF_CLK_DIV1(d, c, r, b)				\
+	static struct divider d = {				\
+		.clk = c,					\
+		.reg = r,					\
+		.bp_podf = BP_##r##_##b##_PODF,			\
+		.bm_podf = BM_##r##_##b##_PODF,			\
+	}
+
+DEF_CLK_DIV1(arm_div,		&arm_clk,		CACRR,	ARM);
+DEF_CLK_DIV1(ipg_div,		&ipg_clk,		CBCDR,	IPG);
+DEF_CLK_DIV1(ahb_div,		&ahb_clk,		CBCDR,	AHB);
+DEF_CLK_DIV1(axi_div,		&axi_clk,		CBCDR,	AXI);
+DEF_CLK_DIV1(mmdc_ch0_axi_div,	&mmdc_ch0_axi_clk,	CBCDR,	MMDC_CH0_AXI);
+DEF_CLK_DIV1(mmdc_ch1_axi_div,	&mmdc_ch1_axi_clk,	CBCDR,	MMDC_CH1_AXI);
+DEF_CLK_DIV1(periph_clk2_div,	&periph_clk2_clk,	CBCDR,	PERIPH_CLK2);
+DEF_CLK_DIV1(periph2_clk2_div,	&periph2_clk2_clk,	CBCDR,	PERIPH2_CLK2);
+DEF_CLK_DIV1(gpu2d_core_div,	&gpu2d_core_clk,	CBCMR,	GPU2D_CORE);
+DEF_CLK_DIV1(gpu3d_core_div,	&gpu3d_core_clk,	CBCMR,	GPU3D_CORE);
+DEF_CLK_DIV1(gpu3d_shader_div,	&gpu3d_shader_clk,	CBCMR,	GPU3D_SHADER);
+DEF_CLK_DIV1(ipg_perclk_div,	&ipg_perclk,		CSCMR1,	PERCLK);
+DEF_CLK_DIV1(emi_div,		&emi_clk,		CSCMR1,	EMI);
+DEF_CLK_DIV1(emi_slow_div,	&emi_slow_clk,		CSCMR1,	EMI_SLOW);
+DEF_CLK_DIV1(can_div,		&can1_clk,		CSCMR2,	CAN);
+DEF_CLK_DIV1(uart_div,		&uart_clk,		CSCDR1,	UART);
+DEF_CLK_DIV1(usdhc1_div,	&usdhc1_clk,		CSCDR1,	USDHC1);
+DEF_CLK_DIV1(usdhc2_div,	&usdhc2_clk,		CSCDR1,	USDHC2);
+DEF_CLK_DIV1(usdhc3_div,	&usdhc3_clk,		CSCDR1,	USDHC3);
+DEF_CLK_DIV1(usdhc4_div,	&usdhc4_clk,		CSCDR1,	USDHC4);
+DEF_CLK_DIV1(vpu_div,		&vpu_clk,		CSCDR1,	VPU_AXI);
+DEF_CLK_DIV1(hsi_tx_div,	&hsi_tx_clk,		CDCDR,	HSI_TX);
+DEF_CLK_DIV1(ipu1_di0_pre_div,	&ipu1_di0_pre_clk,	CHSCCDR, IPU1_DI0_PRE);
+DEF_CLK_DIV1(ipu1_di1_pre_div,	&ipu1_di1_pre_clk,	CHSCCDR, IPU1_DI1_PRE);
+DEF_CLK_DIV1(ipu2_di0_pre_div,	&ipu2_di0_pre_clk,	CSCDR2,	IPU2_DI0_PRE);
+DEF_CLK_DIV1(ipu2_di1_pre_div,	&ipu2_di1_pre_clk,	CSCDR2,	IPU2_DI1_PRE);
+DEF_CLK_DIV1(ipu1_div,		&ipu1_clk,		CSCDR3,	IPU1_HSP);
+DEF_CLK_DIV1(ipu2_div,		&ipu2_clk,		CSCDR3,	IPU2_HSP);
+
+#define DEF_CLK_DIV2(d, c, r, b)				\
+	static struct divider d = {				\
+		.clk = c,					\
+		.reg = r,					\
+		.bp_pred = BP_##r##_##b##_PRED,			\
+		.bm_pred = BM_##r##_##b##_PRED,			\
+		.bp_podf = BP_##r##_##b##_PODF,			\
+		.bm_podf = BM_##r##_##b##_PODF,			\
+	}
+
+DEF_CLK_DIV2(ssi1_div,		&ssi1_clk,		CS1CDR,	SSI1);
+DEF_CLK_DIV2(ssi3_div,		&ssi3_clk,		CS1CDR,	SSI3);
+DEF_CLK_DIV2(esai_div,		&esai_clk,		CS1CDR,	ESAI);
+DEF_CLK_DIV2(ssi2_div,		&ssi2_clk,		CS2CDR,	SSI2);
+DEF_CLK_DIV2(enfc_div,		&enfc_clk,		CS2CDR,	ENFC);
+DEF_CLK_DIV2(spdif_div,		&spdif_clk,		CDCDR,	SPDIF);
+DEF_CLK_DIV2(asrc_serial_div,	&asrc_serial_clk,	CDCDR,	ASRC_SERIAL);
+
+static struct divider *dividers[] = {
+	&arm_div,
+	&ipg_div,
+	&ahb_div,
+	&axi_div,
+	&mmdc_ch0_axi_div,
+	&mmdc_ch1_axi_div,
+	&periph_clk2_div,
+	&periph2_clk2_div,
+	&gpu2d_core_div,
+	&gpu3d_core_div,
+	&gpu3d_shader_div,
+	&ipg_perclk_div,
+	&emi_div,
+	&emi_slow_div,
+	&can_div,
+	&uart_div,
+	&usdhc1_div,
+	&usdhc2_div,
+	&usdhc3_div,
+	&usdhc4_div,
+	&vpu_div,
+	&hsi_tx_div,
+	&ipu1_di0_pre_div,
+	&ipu1_di1_pre_div,
+	&ipu2_di0_pre_div,
+	&ipu2_di1_pre_div,
+	&ipu1_div,
+	&ipu2_div,
+	&ssi1_div,
+	&ssi3_div,
+	&esai_div,
+	&ssi2_div,
+	&enfc_div,
+	&spdif_div,
+	&asrc_serial_div,
+};
+
+static unsigned long ldb_di_clk_get_rate(struct clk *clk)
+{
+	u32 val = readl_relaxed(CSCMR2);
+
+	val &= (clk == &ldb_di0_clk) ? BM_CSCMR2_LDB_DI0_IPU_DIV :
+				       BM_CSCMR2_LDB_DI1_IPU_DIV;
+	if (val)
+		return clk_get_rate(clk->parent) / 7;
+	else
+		return clk_get_rate(clk->parent) * 2 / 7;
+}
+
+static int ldb_di_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	u32 val = readl_relaxed(CSCMR2);
+
+	if (rate * 7 <= parent_rate + parent_rate / 20)
+		val |= BM_CSCMR2_LDB_DI0_IPU_DIV;
+	else
+		val &= ~BM_CSCMR2_LDB_DI0_IPU_DIV;
+
+	writel_relaxed(val, CSCMR2);
+
+	return 0;
+}
+
+static unsigned long ldb_di_clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+
+	if (rate * 7 <= parent_rate + parent_rate / 20)
+		return parent_rate / 7;
+	else
+		return 2 * parent_rate / 7;
+}
+
+static unsigned long _clk_get_rate(struct clk *clk)
+{
+	struct divider *d;
+	u32 val, pred, podf;
+	int i, num;
+
+	if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
+		return ldb_di_clk_get_rate(clk);
+
+	num = ARRAY_SIZE(dividers);
+	for (i = 0; i < num; i++)
+		if (dividers[i]->clk == clk) {
+			d = dividers[i];
+			break;
+		}
+	if (i == num)
+		return clk_get_rate(clk->parent);
+
+	val = readl_relaxed(d->reg);
+	pred = ((val & d->bm_pred) >> d->bp_pred) + 1;
+	podf = ((val & d->bm_podf) >> d->bp_podf) + 1;
+
+	return clk_get_rate(clk->parent) / (pred * podf);
+}
+
+static int clk_busy_wait(struct clk *clk)
+{
+	int timeout = 0x100000;
+	u32 bm;
+
+	if (clk == &axi_clk)
+		bm = BM_CDHIPR_AXI_PODF_BUSY;
+	else if (clk == &ahb_clk)
+		bm = BM_CDHIPR_AHB_PODF_BUSY;
+	else if (clk == &mmdc_ch0_axi_clk)
+		bm = BM_CDHIPR_MMDC_CH0_PODF_BUSY;
+	else if (clk == &periph_clk)
+		bm = BM_CDHIPR_PERIPH_SEL_BUSY;
+	else if (clk == &arm_clk)
+		bm = BM_CDHIPR_ARM_PODF_BUSY;
+	else
+		return -EINVAL;
+
+	while ((readl_relaxed(CDHIPR) & bm) && --timeout)
+		cpu_relax();
+
+	if (unlikely(!timeout))
+		return -EBUSY;
+
+	return 0;
+}
+
+static int _clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	struct divider *d;
+	u32 val, div, max_div, pred = 0, podf;
+	int i, num;
+
+	if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
+		return ldb_di_clk_set_rate(clk, rate);
+
+	num = ARRAY_SIZE(dividers);
+	for (i = 0; i < num; i++)
+		if (dividers[i]->clk == clk) {
+			d = dividers[i];
+			break;
+		}
+	if (i == num)
+		return -EINVAL;
+
+	max_div = ((d->bm_pred >> d->bp_pred) + 1) *
+		  ((d->bm_podf >> d->bp_podf) + 1);
+
+	div = parent_rate / rate;
+	if (div == 0)
+		div++;
+
+	if ((parent_rate / div != rate) || div > max_div)
+		return -EINVAL;
+
+	if (d->bm_pred) {
+		calc_pred_podf_dividers(div, &pred, &podf);
+	} else {
+		pred = 1;
+		podf = div;
+	}
+
+	val = readl_relaxed(d->reg);
+	val &= ~(d->bm_pred | d->bm_podf);
+	val |= (pred - 1) << d->bp_pred | (podf - 1) << d->bp_podf;
+	writel_relaxed(val, d->reg);
+
+	if (clk == &axi_clk || clk == &ahb_clk ||
+	    clk == &mmdc_ch0_axi_clk || clk == &arm_clk)
+		return clk_busy_wait(clk);
+
+	return 0;
+}
+
+static unsigned long _clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	u32 div = parent_rate / rate;
+	u32 div_max, pred = 0, podf;
+	struct divider *d;
+	int i, num;
+
+	if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
+		return ldb_di_clk_round_rate(clk, rate);
+
+	num = ARRAY_SIZE(dividers);
+	for (i = 0; i < num; i++)
+		if (dividers[i]->clk == clk) {
+			d = dividers[i];
+			break;
+		}
+	if (i == num)
+		return -EINVAL;
+
+	if (div == 0 || parent_rate % rate)
+		div++;
+
+	if (d->bm_pred) {
+		calc_pred_podf_dividers(div, &pred, &podf);
+		div = pred * podf;
+	} else {
+		div_max = (d->bm_podf >> d->bp_podf) + 1;
+		if (div > div_max)
+			div = div_max;
+	}
+
+	return parent_rate / div;
+}
+
+struct multiplexer {
+	struct clk *clk;
+	void __iomem *reg;
+	u32 bp;
+	u32 bm;
+	int pnum;
+	struct clk *parents[];
+};
+
+static struct multiplexer axi_mux = {
+	.clk = &axi_clk,
+	.reg = CBCDR,
+	.bp = BP_CBCDR_AXI_SEL,
+	.bm = BM_CBCDR_AXI_SEL,
+	.parents = {
+		&periph_clk,
+		&pll2_pfd_400m,
+		&pll3_pfd_540m,
+		NULL
+	},
+};
+
+static struct multiplexer periph_mux = {
+	.clk = &periph_clk,
+	.reg = CBCDR,
+	.bp = BP_CBCDR_PERIPH_CLK_SEL,
+	.bm = BM_CBCDR_PERIPH_CLK_SEL,
+	.parents = {
+		&periph_pre_clk,
+		&periph_clk2_clk,
+		NULL
+	},
+};
+
+static struct multiplexer periph_pre_mux = {
+	.clk = &periph_pre_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_PRE_PERIPH_CLK_SEL,
+	.bm = BM_CBCMR_PRE_PERIPH_CLK_SEL,
+	.parents = {
+		&pll2_bus,
+		&pll2_pfd_400m,
+		&pll2_pfd_352m,
+		&pll2_200m,
+		NULL
+	},
+};
+
+static struct multiplexer periph_clk2_mux = {
+	.clk = &periph_clk2_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_PERIPH_CLK2_SEL,
+	.bm = BM_CBCMR_PERIPH_CLK2_SEL,
+	.parents = {
+		&pll3_usb_otg,
+		&osc_clk,
+		NULL
+	},
+};
+
+static struct multiplexer periph2_mux = {
+	.clk = &periph2_clk,
+	.reg = CBCDR,
+	.bp = BP_CBCDR_PERIPH2_CLK_SEL,
+	.bm = BM_CBCDR_PERIPH2_CLK_SEL,
+	.parents = {
+		&periph2_pre_clk,
+		&periph2_clk2_clk,
+		NULL
+	},
+};
+
+static struct multiplexer periph2_pre_mux = {
+	.clk = &periph2_pre_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_PRE_PERIPH2_CLK_SEL,
+	.bm = BM_CBCMR_PRE_PERIPH2_CLK_SEL,
+	.parents = {
+		&pll2_bus,
+		&pll2_pfd_400m,
+		&pll2_pfd_352m,
+		&pll2_200m,
+		NULL
+	},
+};
+
+static struct multiplexer periph2_clk2_mux = {
+	.clk = &periph2_clk2_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_PERIPH2_CLK2_SEL,
+	.bm = BM_CBCMR_PERIPH2_CLK2_SEL,
+	.parents = {
+		&pll3_usb_otg,
+		&osc_clk,
+		NULL
+	},
+};
+
+static struct multiplexer gpu2d_axi_mux = {
+	.clk = &gpu2d_axi_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_GPU2D_AXI_SEL,
+	.bm = BM_CBCMR_GPU2D_AXI_SEL,
+	.parents = {
+		&axi_clk,
+		&ahb_clk,
+		NULL
+	},
+};
+
+static struct multiplexer gpu3d_axi_mux = {
+	.clk = &gpu3d_axi_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_GPU3D_AXI_SEL,
+	.bm = BM_CBCMR_GPU3D_AXI_SEL,
+	.parents = {
+		&axi_clk,
+		&ahb_clk,
+		NULL
+	},
+};
+
+static struct multiplexer gpu3d_core_mux = {
+	.clk = &gpu3d_core_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_GPU3D_CORE_SEL,
+	.bm = BM_CBCMR_GPU3D_CORE_SEL,
+	.parents = {
+		&mmdc_ch0_axi_clk,
+		&pll3_usb_otg,
+		&pll2_pfd_594m,
+		&pll2_pfd_400m,
+		NULL
+	},
+};
+
+static struct multiplexer gpu3d_shader_mux = {
+	.clk = &gpu3d_shader_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_GPU3D_SHADER_SEL,
+	.bm = BM_CBCMR_GPU3D_SHADER_SEL,
+	.parents = {
+		&mmdc_ch0_axi_clk,
+		&pll3_usb_otg,
+		&pll2_pfd_594m,
+		&pll3_pfd_720m,
+		NULL
+	},
+};
+
+static struct multiplexer pcie_axi_mux = {
+	.clk = &pcie_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_PCIE_AXI_SEL,
+	.bm = BM_CBCMR_PCIE_AXI_SEL,
+	.parents = {
+		&axi_clk,
+		&ahb_clk,
+		NULL
+	},
+};
+
+static struct multiplexer vdo_axi_mux = {
+	.clk = &vdo_axi_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_VDO_AXI_SEL,
+	.bm = BM_CBCMR_VDO_AXI_SEL,
+	.parents = {
+		&axi_clk,
+		&ahb_clk,
+		NULL
+	},
+};
+
+static struct multiplexer vpu_axi_mux = {
+	.clk = &vpu_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_VPU_AXI_SEL,
+	.bm = BM_CBCMR_VPU_AXI_SEL,
+	.parents = {
+		&axi_clk,
+		&pll2_pfd_400m,
+		&pll2_pfd_352m,
+		NULL
+	},
+};
+
+static struct multiplexer gpu2d_core_mux = {
+	.clk = &gpu2d_core_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_GPU2D_CORE_SEL,
+	.bm = BM_CBCMR_GPU2D_CORE_SEL,
+	.parents = {
+		&axi_clk,
+		&pll3_usb_otg,
+		&pll2_pfd_352m,
+		&pll2_pfd_400m,
+		NULL
+	},
+};
+
+#define DEF_SSI_MUX(id)							\
+	static struct multiplexer ssi##id##_mux = {			\
+		.clk = &ssi##id##_clk,					\
+		.reg = CSCMR1,						\
+		.bp = BP_CSCMR1_SSI##id##_SEL,				\
+		.bm = BM_CSCMR1_SSI##id##_SEL,				\
+		.parents = {						\
+			&pll3_pfd_508m,					\
+			&pll3_pfd_454m,					\
+			&pll4_audio,					\
+			NULL						\
+		},							\
+	}
+
+DEF_SSI_MUX(1);
+DEF_SSI_MUX(2);
+DEF_SSI_MUX(3);
+
+#define DEF_USDHC_MUX(id)						\
+	static struct multiplexer usdhc##id##_mux = {			\
+		.clk = &usdhc##id##_clk,				\
+		.reg = CSCMR1,						\
+		.bp = BP_CSCMR1_USDHC##id##_SEL,			\
+		.bm = BM_CSCMR1_USDHC##id##_SEL,			\
+		.parents = {						\
+			&pll2_pfd_400m,					\
+			&pll2_pfd_352m,					\
+			NULL						\
+		},							\
+	}
+
+DEF_USDHC_MUX(1);
+DEF_USDHC_MUX(2);
+DEF_USDHC_MUX(3);
+DEF_USDHC_MUX(4);
+
+static struct multiplexer emi_mux = {
+	.clk = &emi_clk,
+	.reg = CSCMR1,
+	.bp = BP_CSCMR1_EMI_SEL,
+	.bm = BM_CSCMR1_EMI_SEL,
+	.parents = {
+		&axi_clk,
+		&pll3_usb_otg,
+		&pll2_pfd_400m,
+		&pll2_pfd_352m,
+		NULL
+	},
+};
+
+static struct multiplexer emi_slow_mux = {
+	.clk = &emi_slow_clk,
+	.reg = CSCMR1,
+	.bp = BP_CSCMR1_EMI_SLOW_SEL,
+	.bm = BM_CSCMR1_EMI_SLOW_SEL,
+	.parents = {
+		&axi_clk,
+		&pll3_usb_otg,
+		&pll2_pfd_400m,
+		&pll2_pfd_352m,
+		NULL
+	},
+};
+
+static struct multiplexer esai_mux = {
+	.clk = &esai_clk,
+	.reg = CSCMR2,
+	.bp = BP_CSCMR2_ESAI_SEL,
+	.bm = BM_CSCMR2_ESAI_SEL,
+	.parents = {
+		&pll4_audio,
+		&pll3_pfd_508m,
+		&pll3_pfd_454m,
+		&pll3_usb_otg,
+		NULL
+	},
+};
+
+#define DEF_LDB_DI_MUX(id)						\
+	static struct multiplexer ldb_di##id##_mux = {			\
+		.clk = &ldb_di##id##_clk,				\
+		.reg = CS2CDR,						\
+		.bp = BP_CS2CDR_LDB_DI##id##_SEL,			\
+		.bm = BM_CS2CDR_LDB_DI##id##_SEL,			\
+		.parents = {						\
+			&pll5_video,					\
+			&pll2_pfd_352m,					\
+			&pll2_pfd_400m,					\
+			&pll3_pfd_540m,					\
+			&pll3_usb_otg,					\
+			NULL						\
+		},							\
+	}
+
+DEF_LDB_DI_MUX(0);
+DEF_LDB_DI_MUX(1);
+
+static struct multiplexer enfc_mux = {
+	.clk = &enfc_clk,
+	.reg = CS2CDR,
+	.bp = BP_CS2CDR_ENFC_SEL,
+	.bm = BM_CS2CDR_ENFC_SEL,
+	.parents = {
+		&pll2_pfd_352m,
+		&pll2_bus,
+		&pll3_usb_otg,
+		&pll2_pfd_400m,
+		NULL
+	},
+};
+
+static struct multiplexer spdif_mux = {
+	.clk = &spdif_clk,
+	.reg = CDCDR,
+	.bp = BP_CDCDR_SPDIF_SEL,
+	.bm = BM_CDCDR_SPDIF_SEL,
+	.parents = {
+		&pll4_audio,
+		&pll3_pfd_508m,
+		&pll3_pfd_454m,
+		&pll3_usb_otg,
+		NULL
+	},
+};
+
+static struct multiplexer asrc_serial_mux = {
+	.clk = &asrc_serial_clk,
+	.reg = CDCDR,
+	.bp = BP_CDCDR_ASRC_SERIAL_SEL,
+	.bm = BM_CDCDR_ASRC_SERIAL_SEL,
+	.parents = {
+		&pll4_audio,
+		&pll3_pfd_508m,
+		&pll3_pfd_454m,
+		&pll3_usb_otg,
+		NULL
+	},
+};
+
+static struct multiplexer hsi_tx_mux = {
+	.clk = &hsi_tx_clk,
+	.reg = CDCDR,
+	.bp = BP_CDCDR_HSI_TX_SEL,
+	.bm = BM_CDCDR_HSI_TX_SEL,
+	.parents = {
+		&pll3_120m,
+		&pll2_pfd_400m,
+		NULL
+	},
+};
+
+#define DEF_IPU_DI_PRE_MUX(r, i, d)					\
+	static struct multiplexer ipu##i##_di##d##_pre_mux = {		\
+		.clk = &ipu##i##_di##d##_pre_clk,			\
+		.reg = r,						\
+		.bp = BP_##r##_IPU##i##_DI##d##_PRE_SEL,		\
+		.bm = BM_##r##_IPU##i##_DI##d##_PRE_SEL,		\
+		.parents = {						\
+			&mmdc_ch0_axi_clk,				\
+			&pll3_usb_otg,					\
+			&pll5_video,					\
+			&pll2_pfd_352m,					\
+			&pll2_pfd_400m,					\
+			&pll3_pfd_540m,					\
+			NULL						\
+		},							\
+	}
+
+DEF_IPU_DI_PRE_MUX(CHSCCDR, 1, 0);
+DEF_IPU_DI_PRE_MUX(CHSCCDR, 1, 1);
+DEF_IPU_DI_PRE_MUX(CSCDR2, 2, 0);
+DEF_IPU_DI_PRE_MUX(CSCDR2, 2, 1);
+
+#define DEF_IPU_DI_MUX(r, i, d)						\
+	static struct multiplexer ipu##i##_di##d##_mux = {		\
+		.clk = &ipu##i##_di##d##_clk,				\
+		.reg = r,						\
+		.bp = BP_##r##_IPU##i##_DI##d##_SEL,			\
+		.bm = BM_##r##_IPU##i##_DI##d##_SEL,			\
+		.parents = {						\
+			&ipu##i##_di##d##_pre_clk,			\
+			&dummy_clk,					\
+			&dummy_clk,					\
+			&ldb_di0_clk,					\
+			&ldb_di1_clk,					\
+			NULL						\
+		},							\
+	}
+
+DEF_IPU_DI_MUX(CHSCCDR, 1, 0);
+DEF_IPU_DI_MUX(CHSCCDR, 1, 1);
+DEF_IPU_DI_MUX(CSCDR2, 2, 0);
+DEF_IPU_DI_MUX(CSCDR2, 2, 1);
+
+#define DEF_IPU_MUX(id)							\
+	static struct multiplexer ipu##id##_mux = {			\
+		.clk = &ipu##id##_clk,					\
+		.reg = CSCDR3,						\
+		.bp = BP_CSCDR3_IPU##id##_HSP_SEL,			\
+		.bm = BM_CSCDR3_IPU##id##_HSP_SEL,			\
+		.parents = {						\
+			&mmdc_ch0_axi_clk,				\
+			&pll2_pfd_400m,					\
+			&pll3_120m,					\
+			&pll3_pfd_540m,					\
+			NULL						\
+		},							\
+	}
+
+DEF_IPU_MUX(1);
+DEF_IPU_MUX(2);
+
+static struct multiplexer *multiplexers[] = {
+	&axi_mux,
+	&periph_mux,
+	&periph_pre_mux,
+	&periph_clk2_mux,
+	&periph2_mux,
+	&periph2_pre_mux,
+	&periph2_clk2_mux,
+	&gpu2d_axi_mux,
+	&gpu3d_axi_mux,
+	&gpu3d_core_mux,
+	&gpu3d_shader_mux,
+	&pcie_axi_mux,
+	&vdo_axi_mux,
+	&vpu_axi_mux,
+	&gpu2d_core_mux,
+	&ssi1_mux,
+	&ssi2_mux,
+	&ssi3_mux,
+	&usdhc1_mux,
+	&usdhc2_mux,
+	&usdhc3_mux,
+	&usdhc4_mux,
+	&emi_mux,
+	&emi_slow_mux,
+	&esai_mux,
+	&ldb_di0_mux,
+	&ldb_di1_mux,
+	&enfc_mux,
+	&spdif_mux,
+	&asrc_serial_mux,
+	&hsi_tx_mux,
+	&ipu1_di0_pre_mux,
+	&ipu1_di0_mux,
+	&ipu1_di1_pre_mux,
+	&ipu1_di1_mux,
+	&ipu2_di0_pre_mux,
+	&ipu2_di0_mux,
+	&ipu2_di1_pre_mux,
+	&ipu2_di1_mux,
+	&ipu1_mux,
+	&ipu2_mux,
+};
+
+static int _clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct multiplexer *m;
+	int i, num;
+	u32 val;
+
+	num = ARRAY_SIZE(multiplexers);
+	for (i = 0; i < num; i++)
+		if (multiplexers[i]->clk == clk) {
+			m = multiplexers[i];
+			break;
+		}
+	if (i == num)
+		return -EINVAL;
+
+	i = 0;
+	while (m->parents[i]) {
+		if (parent == m->parents[i])
+			break;
+		i++;
+	}
+	if (!m->parents[i])
+		return -EINVAL;
+
+	val = readl_relaxed(m->reg);
+	val &= ~m->bm;
+	val |= i << m->bp;
+	writel_relaxed(val, m->reg);
+
+	if (clk == &periph_clk)
+		return clk_busy_wait(clk);
+
+	return 0;
+}
+
+#define DEF_NG_CLK(name, p)				\
+	static struct clk name = {			\
+		.get_rate	= _clk_get_rate,	\
+		.set_rate	= _clk_set_rate,	\
+		.round_rate	= _clk_round_rate,	\
+		.set_parent	= _clk_set_parent,	\
+		.parent		= p,			\
+	}
+
+DEF_NG_CLK(periph_clk2_clk,	&osc_clk);
+DEF_NG_CLK(periph_pre_clk,	&pll2_bus);
+DEF_NG_CLK(periph_clk,		&periph_pre_clk);
+DEF_NG_CLK(periph2_clk2_clk,	&osc_clk);
+DEF_NG_CLK(periph2_pre_clk,	&pll2_bus);
+DEF_NG_CLK(periph2_clk,		&periph2_pre_clk);
+DEF_NG_CLK(axi_clk,		&periph_clk);
+DEF_NG_CLK(emi_clk,		&axi_clk);
+DEF_NG_CLK(arm_clk,		&pll1_sw_clk);
+DEF_NG_CLK(ahb_clk,		&periph_clk);
+DEF_NG_CLK(ipg_clk,		&ahb_clk);
+DEF_NG_CLK(ipg_perclk,		&ipg_clk);
+DEF_NG_CLK(ipu1_di0_pre_clk,	&pll3_pfd_540m);
+DEF_NG_CLK(ipu1_di1_pre_clk,	&pll3_pfd_540m);
+DEF_NG_CLK(ipu2_di0_pre_clk,	&pll3_pfd_540m);
+DEF_NG_CLK(ipu2_di1_pre_clk,	&pll3_pfd_540m);
+DEF_NG_CLK(asrc_serial_clk,	&pll3_usb_otg);
+
+#define DEF_CLK(name, er, es, p, s)			\
+	static struct clk name = {			\
+		.enable_reg	= er,			\
+		.enable_shift	= es,			\
+		.enable		= _clk_enable,		\
+		.disable	= _clk_disable,		\
+		.get_rate	= _clk_get_rate,	\
+		.set_rate	= _clk_set_rate,	\
+		.round_rate	= _clk_round_rate,	\
+		.set_parent	= _clk_set_parent,	\
+		.parent		= p,			\
+		.secondary	= s,			\
+	}
+
+DEF_CLK(aips_tz1_clk,	  CCGR0, CG0,  &ahb_clk,	  NULL);
+DEF_CLK(aips_tz2_clk,	  CCGR0, CG1,  &ahb_clk,	  NULL);
+DEF_CLK(apbh_dma_clk,	  CCGR0, CG2,  &ahb_clk,	  NULL);
+DEF_CLK(asrc_clk,	  CCGR0, CG3,  &pll4_audio,	  NULL);
+DEF_CLK(can1_serial_clk,  CCGR0, CG8,  &pll3_usb_otg,	  NULL);
+DEF_CLK(can1_clk,	  CCGR0, CG7,  &pll3_usb_otg,	  &can1_serial_clk);
+DEF_CLK(can2_serial_clk,  CCGR0, CG10, &pll3_usb_otg,	  NULL);
+DEF_CLK(can2_clk,	  CCGR0, CG9,  &pll3_usb_otg,	  &can2_serial_clk);
+DEF_CLK(ecspi1_clk,	  CCGR1, CG0,  &pll3_60m,	  NULL);
+DEF_CLK(ecspi2_clk,	  CCGR1, CG1,  &pll3_60m,	  NULL);
+DEF_CLK(ecspi3_clk,	  CCGR1, CG2,  &pll3_60m,	  NULL);
+DEF_CLK(ecspi4_clk,	  CCGR1, CG3,  &pll3_60m,	  NULL);
+DEF_CLK(ecspi5_clk,	  CCGR1, CG4,  &pll3_60m,	  NULL);
+DEF_CLK(enet_clk,	  CCGR1, CG5,  &ipg_clk,	  NULL);
+DEF_CLK(esai_clk,	  CCGR1, CG8,  &pll3_usb_otg,	  NULL);
+DEF_CLK(gpt_serial_clk,	  CCGR1, CG11, &ipg_perclk,	  NULL);
+DEF_CLK(gpt_clk,	  CCGR1, CG10, &ipg_perclk,	  &gpt_serial_clk);
+DEF_CLK(gpu2d_core_clk,	  CCGR1, CG12, &pll2_pfd_352m,	  &gpu2d_axi_clk);
+DEF_CLK(gpu3d_core_clk,	  CCGR1, CG13, &pll2_pfd_594m,	  &gpu3d_axi_clk);
+DEF_CLK(gpu3d_shader_clk, CCGR1, CG13, &pll3_pfd_720m,	  &gpu3d_axi_clk);
+DEF_CLK(hdmi_iahb_clk,	  CCGR2, CG0,  &ahb_clk,	  NULL);
+DEF_CLK(hdmi_isfr_clk,	  CCGR2, CG2,  &pll3_pfd_540m,	  &hdmi_iahb_clk);
+DEF_CLK(i2c1_clk,	  CCGR2, CG3,  &ipg_perclk,	  NULL);
+DEF_CLK(i2c2_clk,	  CCGR2, CG4,  &ipg_perclk,	  NULL);
+DEF_CLK(i2c3_clk,	  CCGR2, CG5,  &ipg_perclk,	  NULL);
+DEF_CLK(iim_clk,	  CCGR2, CG6,  &ipg_clk,	  NULL);
+DEF_CLK(enfc_clk,	  CCGR2, CG7,  &pll2_pfd_352m,	  NULL);
+DEF_CLK(ipu1_clk,	  CCGR3, CG0,  &mmdc_ch0_axi_clk, NULL);
+DEF_CLK(ipu1_di0_clk,	  CCGR3, CG1,  &ipu1_di0_pre_clk, NULL);
+DEF_CLK(ipu1_di1_clk,	  CCGR3, CG2,  &ipu1_di1_pre_clk, NULL);
+DEF_CLK(ipu2_clk,	  CCGR3, CG3,  &mmdc_ch0_axi_clk, NULL);
+DEF_CLK(ipu2_di0_clk,	  CCGR3, CG4,  &ipu2_di0_pre_clk, NULL);
+DEF_CLK(ipu2_di1_clk,	  CCGR3, CG5,  &ipu2_di1_pre_clk, NULL);
+DEF_CLK(ldb_di0_clk,	  CCGR3, CG6,  &pll3_pfd_540m,	  NULL);
+DEF_CLK(ldb_di1_clk,	  CCGR3, CG7,  &pll3_pfd_540m,	  NULL);
+DEF_CLK(hsi_tx_clk,	  CCGR3, CG8,  &pll2_pfd_400m,	  NULL);
+DEF_CLK(mlb_clk,	  CCGR3, CG9,  &pll6_mlb,	  NULL);
+DEF_CLK(mmdc_ch0_ipg_clk, CCGR3, CG12, &ipg_clk,	  NULL);
+DEF_CLK(mmdc_ch0_axi_clk, CCGR3, CG10, &periph_clk,	  &mmdc_ch0_ipg_clk);
+DEF_CLK(mmdc_ch1_ipg_clk, CCGR3, CG13, &ipg_clk,	  NULL);
+DEF_CLK(mmdc_ch1_axi_clk, CCGR3, CG11, &periph2_clk,	  &mmdc_ch1_ipg_clk);
+DEF_CLK(openvg_axi_clk,   CCGR3, CG13, &axi_clk,	  NULL);
+DEF_CLK(pwm1_clk,	  CCGR4, CG8,  &ipg_perclk,	  NULL);
+DEF_CLK(pwm2_clk,	  CCGR4, CG9,  &ipg_perclk,	  NULL);
+DEF_CLK(pwm3_clk,	  CCGR4, CG10, &ipg_perclk,	  NULL);
+DEF_CLK(pwm4_clk,	  CCGR4, CG11, &ipg_perclk,	  NULL);
+DEF_CLK(gpmi_bch_apb_clk, CCGR4, CG12, &usdhc3_clk,	  NULL);
+DEF_CLK(gpmi_bch_clk,	  CCGR4, CG13, &usdhc4_clk,	  &gpmi_bch_apb_clk);
+DEF_CLK(gpmi_apb_clk,	  CCGR4, CG15, &usdhc3_clk,	  &gpmi_bch_clk);
+DEF_CLK(gpmi_io_clk,	  CCGR4, CG14, &enfc_clk,	  &gpmi_apb_clk);
+DEF_CLK(sdma_clk,	  CCGR5, CG3,  &ahb_clk,	  NULL);
+DEF_CLK(spba_clk,	  CCGR5, CG6,  &ipg_clk,	  NULL);
+DEF_CLK(spdif_clk,	  CCGR5, CG7,  &pll3_usb_otg,	  &spba_clk);
+DEF_CLK(ssi1_clk,	  CCGR5, CG9,  &pll3_pfd_508m,	  NULL);
+DEF_CLK(ssi2_clk,	  CCGR5, CG10, &pll3_pfd_508m,	  NULL);
+DEF_CLK(ssi3_clk,	  CCGR5, CG11, &pll3_pfd_508m,	  NULL);
+DEF_CLK(uart_serial_clk,  CCGR5, CG13, &pll3_usb_otg,	  NULL);
+DEF_CLK(uart_clk,	  CCGR5, CG12, &pll3_80m,	  &uart_serial_clk);
+DEF_CLK(usboh3_clk,	  CCGR6, CG0,  &ipg_clk,	  NULL);
+DEF_CLK(usdhc1_clk,	  CCGR6, CG1,  &pll2_pfd_400m,	  NULL);
+DEF_CLK(usdhc2_clk,	  CCGR6, CG2,  &pll2_pfd_400m,	  NULL);
+DEF_CLK(usdhc3_clk,	  CCGR6, CG3,  &pll2_pfd_400m,	  NULL);
+DEF_CLK(usdhc4_clk,	  CCGR6, CG4,  &pll2_pfd_400m,	  NULL);
+DEF_CLK(emi_slow_clk,	  CCGR6, CG5,  &axi_clk,	  NULL);
+DEF_CLK(vdo_axi_clk,	  CCGR6, CG6,  &axi_clk,	  NULL);
+DEF_CLK(vpu_clk,	  CCGR6, CG7,  &axi_clk,	  NULL);
+
+static int pcie_clk_enable(struct clk *clk)
+{
+	u32 val;
+
+	val = readl_relaxed(PLL8_ENET);
+	val |= BM_PLL_ENET_EN_PCIE;
+	writel_relaxed(val, PLL8_ENET);
+
+	return _clk_enable(clk);
+}
+
+static void pcie_clk_disable(struct clk *clk)
+{
+	u32 val;
+
+	_clk_disable(clk);
+
+	val = readl_relaxed(PLL8_ENET);
+	val &= BM_PLL_ENET_EN_PCIE;
+	writel_relaxed(val, PLL8_ENET);
+}
+
+static struct clk pcie_clk = {
+	.enable_reg = CCGR4,
+	.enable_shift = CG0,
+	.enable = pcie_clk_enable,
+	.disable = pcie_clk_disable,
+	.set_parent = _clk_set_parent,
+	.parent = &axi_clk,
+	.secondary = &pll8_enet,
+};
+
+static int sata_clk_enable(struct clk *clk)
+{
+	u32 val;
+
+	val = readl_relaxed(PLL8_ENET);
+	val |= BM_PLL_ENET_EN_SATA;
+	writel_relaxed(val, PLL8_ENET);
+
+	return _clk_enable(clk);
+}
+
+static void sata_clk_disable(struct clk *clk)
+{
+	u32 val;
+
+	_clk_disable(clk);
+
+	val = readl_relaxed(PLL8_ENET);
+	val &= BM_PLL_ENET_EN_SATA;
+	writel_relaxed(val, PLL8_ENET);
+}
+
+static struct clk sata_clk = {
+	.enable_reg = CCGR5,
+	.enable_shift = CG2,
+	.enable = sata_clk_enable,
+	.disable = sata_clk_disable,
+	.parent = &ipg_clk,
+	.secondary = &pll8_enet,
+};
+
+#define _REGISTER_CLOCK(d, n, c) \
+	{ \
+		.dev_id = d, \
+		.con_id = n, \
+		.clk = &c, \
+	}
+
+static struct clk_lookup lookups[] = {
+	_REGISTER_CLOCK("2020000.uart", NULL, uart_clk),
+	_REGISTER_CLOCK("21e8000.uart", NULL, uart_clk),
+	_REGISTER_CLOCK("21ec000.uart", NULL, uart_clk),
+	_REGISTER_CLOCK("21f0000.uart", NULL, uart_clk),
+	_REGISTER_CLOCK("21f4000.uart", NULL, uart_clk),
+	_REGISTER_CLOCK("2188000.enet", NULL, enet_clk),
+	_REGISTER_CLOCK("2190000.usdhc", NULL, usdhc1_clk),
+	_REGISTER_CLOCK("2194000.usdhc", NULL, usdhc2_clk),
+	_REGISTER_CLOCK("2198000.usdhc", NULL, usdhc3_clk),
+	_REGISTER_CLOCK("219c000.usdhc", NULL, usdhc4_clk),
+	_REGISTER_CLOCK("21a0000.i2c", NULL, i2c1_clk),
+	_REGISTER_CLOCK("21a4000.i2c", NULL, i2c2_clk),
+	_REGISTER_CLOCK("21a8000.i2c", NULL, i2c3_clk),
+	_REGISTER_CLOCK("2008000.ecspi", NULL, ecspi1_clk),
+	_REGISTER_CLOCK("200c000.ecspi", NULL, ecspi2_clk),
+	_REGISTER_CLOCK("2010000.ecspi", NULL, ecspi3_clk),
+	_REGISTER_CLOCK("2014000.ecspi", NULL, ecspi4_clk),
+	_REGISTER_CLOCK("2018000.ecspi", NULL, ecspi5_clk),
+	_REGISTER_CLOCK("20ec000.sdma", NULL, sdma_clk),
+	_REGISTER_CLOCK("20bc000.wdog", NULL, dummy_clk),
+	_REGISTER_CLOCK("20c0000.wdog", NULL, dummy_clk),
+	_REGISTER_CLOCK(NULL, "ckih", ckih_clk),
+	_REGISTER_CLOCK(NULL, "ckil_clk", ckil_clk),
+	_REGISTER_CLOCK(NULL, "aips_tz1_clk", aips_tz1_clk),
+	_REGISTER_CLOCK(NULL, "aips_tz2_clk", aips_tz2_clk),
+	_REGISTER_CLOCK(NULL, "asrc_clk", asrc_clk),
+	_REGISTER_CLOCK(NULL, "can2_clk", can2_clk),
+	_REGISTER_CLOCK(NULL, "hdmi_isfr_clk", hdmi_isfr_clk),
+	_REGISTER_CLOCK(NULL, "iim_clk", iim_clk),
+	_REGISTER_CLOCK(NULL, "mlb_clk", mlb_clk),
+	_REGISTER_CLOCK(NULL, "openvg_axi_clk", openvg_axi_clk),
+	_REGISTER_CLOCK(NULL, "pwm1_clk", pwm1_clk),
+	_REGISTER_CLOCK(NULL, "pwm2_clk", pwm2_clk),
+	_REGISTER_CLOCK(NULL, "pwm3_clk", pwm3_clk),
+	_REGISTER_CLOCK(NULL, "pwm4_clk", pwm4_clk),
+	_REGISTER_CLOCK(NULL, "gpmi_io_clk", gpmi_io_clk),
+	_REGISTER_CLOCK(NULL, "usboh3_clk", usboh3_clk),
+	_REGISTER_CLOCK(NULL, "sata_clk", sata_clk),
+};
+
+int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
+{
+	u32 val = readl_relaxed(CLPCR);
+
+	val &= ~BM_CLPCR_LPM;
+	switch (mode) {
+	case WAIT_CLOCKED:
+		break;
+	case WAIT_UNCLOCKED:
+		val |= 0x1 << BP_CLPCR_LPM;
+		break;
+	case STOP_POWER_ON:
+		val |= 0x2 << BP_CLPCR_LPM;
+		break;
+	case WAIT_UNCLOCKED_POWER_OFF:
+		val |= 0x1 << BP_CLPCR_LPM;
+		val &= ~BM_CLPCR_VSTBY;
+		val &= ~BM_CLPCR_SBYOS;
+		val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+		break;
+	case STOP_POWER_OFF:
+		val |= 0x2 << BP_CLPCR_LPM;
+		val |= 0x3 << BP_CLPCR_STBY_COUNT;
+		val |= BM_CLPCR_VSTBY;
+		val |= BM_CLPCR_SBYOS;
+		val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+		break;
+	default:
+		return -EINVAL;
+	}
+	writel_relaxed(val, CLPCR);
+
+	return 0;
+}
+
+static struct map_desc imx6q_clock_desc[] = {
+	imx_map_entry(MX6Q, CCM, MT_DEVICE),
+	imx_map_entry(MX6Q, ANATOP, MT_DEVICE),
+};
+
+void __init imx6q_clock_map_io(void)
+{
+	iotable_init(imx6q_clock_desc, ARRAY_SIZE(imx6q_clock_desc));
+}
+
+int __init mx6q_clocks_init(void)
+{
+	struct device_node *np;
+	void __iomem *base;
+	int i, irq;
+
+	/* retrieve the freqency of fixed clocks from device tree */
+	for_each_compatible_node(np, NULL, "fixed-clock") {
+		u32 rate;
+		if (of_property_read_u32(np, "clock-frequency", &rate))
+			continue;
+
+		if (of_device_is_compatible(np, "fsl,imx-ckil"))
+			external_low_reference = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
+			external_high_reference = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-osc"))
+			oscillator_reference = rate;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(lookups); i++)
+		clkdev_add(&lookups[i]);
+
+	/* only keep necessary clocks on */
+	writel_relaxed(0x3 << CG0  | 0x3 << CG1  | 0x3 << CG2,	CCGR0);
+	writel_relaxed(0x3 << CG8  | 0x3 << CG9  | 0x3 << CG10,	CCGR2);
+	writel_relaxed(0x3 << CG10 | 0x3 << CG12,		CCGR3);
+	writel_relaxed(0x3 << CG4  | 0x3 << CG6  | 0x3 << CG7,	CCGR4);
+	writel_relaxed(0x3 << CG0,				CCGR5);
+	writel_relaxed(0,					CCGR6);
+	writel_relaxed(0,					CCGR7);
+
+	clk_enable(&uart_clk);
+	clk_enable(&mmdc_ch0_axi_clk);
+
+	clk_set_rate(&pll4_audio, FREQ_650M);
+	clk_set_rate(&pll5_video, FREQ_650M);
+	clk_set_parent(&ipu1_di0_clk, &ipu1_di0_pre_clk);
+	clk_set_parent(&ipu1_di0_pre_clk, &pll5_video);
+	clk_set_parent(&gpu3d_shader_clk, &pll2_pfd_594m);
+	clk_set_rate(&gpu3d_shader_clk, FREQ_594M);
+	clk_set_parent(&gpu3d_core_clk, &mmdc_ch0_axi_clk);
+	clk_set_rate(&gpu3d_core_clk, FREQ_528M);
+	clk_set_parent(&asrc_serial_clk, &pll3_usb_otg);
+	clk_set_rate(&asrc_serial_clk, 1500000);
+	clk_set_rate(&enfc_clk, 11000000);
+
+	/*
+	 * Before pinctrl API is available, we have to rely on the pad
+	 * configuration set up by bootloader.  For usdhc example here,
+	 * u-boot sets up the pads for 49.5 MHz case, and we have to lower
+	 * the usdhc clock from 198 to 49.5 MHz to match the pad configuration.
+	 *
+	 * FIXME: This is should be removed after pinctrl API is available.
+	 * At that time, usdhc driver can call pinctrl API to change pad
+	 * configuration dynamically per different usdhc clock settings.
+	 */
+	clk_set_rate(&usdhc1_clk, 49500000);
+	clk_set_rate(&usdhc2_clk, 49500000);
+	clk_set_rate(&usdhc3_clk, 49500000);
+	clk_set_rate(&usdhc4_clk, 49500000);
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
+	base = of_iomap(np, 0);
+	WARN_ON(!base);
+	irq = irq_of_parse_and_map(np, 0);
+	mxc_timer_init(&gpt_clk, base, irq);
+
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/cpu-imx25.c linux-libre-3.2-gnu/arch/arm/mach-imx/cpu-imx25.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/cpu-imx25.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/cpu-imx25.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,41 @@
+/*
+ * MX25 CPU type detection
+ *
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/iim.h>
+
+static int mx25_cpu_rev = -1;
+
+static int mx25_read_cpu_rev(void)
+{
+	u32 rev;
+
+	rev = __raw_readl(MX25_IO_ADDRESS(MX25_IIM_BASE_ADDR + MXC_IIMSREV));
+	switch (rev) {
+	case 0x00:
+		return IMX_CHIP_REVISION_1_0;
+	case 0x01:
+		return IMX_CHIP_REVISION_1_1;
+	default:
+		return IMX_CHIP_REVISION_UNKNOWN;
+	}
+}
+
+int mx25_revision(void)
+{
+	if (mx25_cpu_rev == -1)
+		mx25_cpu_rev = mx25_read_cpu_rev();
+
+	return mx25_cpu_rev;
+}
+EXPORT_SYMBOL(mx25_revision);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/cpu-imx27.c linux-libre-3.2-gnu/arch/arm/mach-imx/cpu-imx27.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/cpu-imx27.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/cpu-imx27.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,12 +26,12 @@
 
 #include <mach/hardware.h>
 
-static int cpu_silicon_rev = -1;
-static int cpu_partnumber;
+static int mx27_cpu_rev = -1;
+static int mx27_cpu_partnumber;
 
 #define SYS_CHIP_ID             0x00    /* The offset of CHIP ID register */
 
-static void query_silicon_parameter(void)
+static int mx27_read_cpu_rev(void)
 {
 	u32 val;
 	/*
@@ -42,20 +42,18 @@
 	val = __raw_readl(MX27_IO_ADDRESS(MX27_SYSCTRL_BASE_ADDR
 				+ SYS_CHIP_ID));
 
+	mx27_cpu_partnumber = (int)((val >> 12) & 0xFFFF);
+
 	switch (val >> 28) {
 	case 0:
-		cpu_silicon_rev = IMX_CHIP_REVISION_1_0;
-		break;
+		return IMX_CHIP_REVISION_1_0;
 	case 1:
-		cpu_silicon_rev = IMX_CHIP_REVISION_2_0;
-		break;
+		return IMX_CHIP_REVISION_2_0;
 	case 2:
-		cpu_silicon_rev = IMX_CHIP_REVISION_2_1;
-		break;
+		return IMX_CHIP_REVISION_2_1;
 	default:
-		cpu_silicon_rev = IMX_CHIP_REVISION_UNKNOWN;
+		return IMX_CHIP_REVISION_UNKNOWN;
 	}
-	cpu_partnumber = (int)((val >> 12) & 0xFFFF);
 }
 
 /*
@@ -65,12 +63,12 @@
  */
 int mx27_revision(void)
 {
-	if (cpu_silicon_rev == -1)
-		query_silicon_parameter();
+	if (mx27_cpu_rev == -1)
+		mx27_cpu_rev = mx27_read_cpu_rev();
 
-	if (cpu_partnumber != 0x8821)
+	if (mx27_cpu_partnumber != 0x8821)
 		return -EINVAL;
 
-	return cpu_silicon_rev;
+	return mx27_cpu_rev;
 }
 EXPORT_SYMBOL(mx27_revision);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/cpu-imx31.c linux-libre-3.2-gnu/arch/arm/mach-imx/cpu-imx31.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/cpu-imx31.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/cpu-imx31.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,45 +13,50 @@
 #include <linux/io.h>
 #include <mach/hardware.h>
 #include <mach/iim.h>
+#include <mach/common.h>
 
-unsigned int mx31_cpu_rev;
-EXPORT_SYMBOL(mx31_cpu_rev);
+static int mx31_cpu_rev = -1;
 
 static struct {
 	u8 srev;
 	const char *name;
-	const char *v;
 	unsigned int rev;
-} mx31_cpu_type[] __initdata = {
-	{ .srev = 0x00, .name = "i.MX31(L)", .v = "1.0",  .rev = IMX_CHIP_REVISION_1_0	},
-	{ .srev = 0x10, .name = "i.MX31",    .v = "1.1",  .rev = IMX_CHIP_REVISION_1_1	},
-	{ .srev = 0x11, .name = "i.MX31L",   .v = "1.1",  .rev = IMX_CHIP_REVISION_1_1	},
-	{ .srev = 0x12, .name = "i.MX31",    .v = "1.15", .rev = IMX_CHIP_REVISION_1_1	},
-	{ .srev = 0x13, .name = "i.MX31L",   .v = "1.15", .rev = IMX_CHIP_REVISION_1_1	},
-	{ .srev = 0x14, .name = "i.MX31",    .v = "1.2",  .rev = IMX_CHIP_REVISION_1_2	},
-	{ .srev = 0x15, .name = "i.MX31L",   .v = "1.2",  .rev = IMX_CHIP_REVISION_1_2	},
-	{ .srev = 0x28, .name = "i.MX31",    .v = "2.0",  .rev = IMX_CHIP_REVISION_2_0	},
-	{ .srev = 0x29, .name = "i.MX31L",   .v = "2.0",  .rev = IMX_CHIP_REVISION_2_0	},
+} mx31_cpu_type[] = {
+	{ .srev = 0x00, .name = "i.MX31(L)", .rev = IMX_CHIP_REVISION_1_0 },
+	{ .srev = 0x10, .name = "i.MX31",    .rev = IMX_CHIP_REVISION_1_1 },
+	{ .srev = 0x11, .name = "i.MX31L",   .rev = IMX_CHIP_REVISION_1_1 },
+	{ .srev = 0x12, .name = "i.MX31",    .rev = IMX_CHIP_REVISION_1_1 },
+	{ .srev = 0x13, .name = "i.MX31L",   .rev = IMX_CHIP_REVISION_1_1 },
+	{ .srev = 0x14, .name = "i.MX31",    .rev = IMX_CHIP_REVISION_1_2 },
+	{ .srev = 0x15, .name = "i.MX31L",   .rev = IMX_CHIP_REVISION_1_2 },
+	{ .srev = 0x28, .name = "i.MX31",    .rev = IMX_CHIP_REVISION_2_0 },
+	{ .srev = 0x29, .name = "i.MX31L",   .rev = IMX_CHIP_REVISION_2_0 },
 };
 
-void __init mx31_read_cpu_rev(void)
+static int mx31_read_cpu_rev(void)
 {
 	u32 i, srev;
 
 	/* read SREV register from IIM module */
 	srev = __raw_readl(MX31_IO_ADDRESS(MX31_IIM_BASE_ADDR + MXC_IIMSREV));
+	srev &= 0xff;
 
 	for (i = 0; i < ARRAY_SIZE(mx31_cpu_type); i++)
 		if (srev == mx31_cpu_type[i].srev) {
-			printk(KERN_INFO
-				"CPU identified as %s, silicon rev %s\n",
-				mx31_cpu_type[i].name, mx31_cpu_type[i].v);
-
-			mx31_cpu_rev = mx31_cpu_type[i].rev;
-			return;
+			imx_print_silicon_rev(mx31_cpu_type[i].name,
+						mx31_cpu_type[i].rev);
+			return mx31_cpu_type[i].rev;
 		}
 
-	mx31_cpu_rev = IMX_CHIP_REVISION_UNKNOWN;
+	imx_print_silicon_rev("i.MX31", IMX_CHIP_REVISION_UNKNOWN);
+	return IMX_CHIP_REVISION_UNKNOWN;
+}
 
-	printk(KERN_WARNING "Unknown CPU identifier. srev = %02x\n", srev);
+int mx31_revision(void)
+{
+	if (mx31_cpu_rev == -1)
+		mx31_cpu_rev = mx31_read_cpu_rev();
+
+	return mx31_cpu_rev;
 }
+EXPORT_SYMBOL(mx31_revision);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/cpu-imx35.c linux-libre-3.2-gnu/arch/arm/mach-imx/cpu-imx35.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/cpu-imx35.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/cpu-imx35.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,32 +13,30 @@
 #include <mach/hardware.h>
 #include <mach/iim.h>
 
-unsigned int mx35_cpu_rev;
-EXPORT_SYMBOL(mx35_cpu_rev);
+static int mx35_cpu_rev = -1;
 
-void __init mx35_read_cpu_rev(void)
+static int mx35_read_cpu_rev(void)
 {
 	u32 rev;
-	char *srev;
 
 	rev = __raw_readl(MX35_IO_ADDRESS(MX35_IIM_BASE_ADDR + MXC_IIMSREV));
 	switch (rev) {
 	case 0x00:
-		mx35_cpu_rev = IMX_CHIP_REVISION_1_0;
-		srev = "1.0";
-		break;
+		return IMX_CHIP_REVISION_1_0;
 	case 0x10:
-		mx35_cpu_rev = IMX_CHIP_REVISION_2_0;
-		srev = "2.0";
-		break;
+		return IMX_CHIP_REVISION_2_0;
 	case 0x11:
-		mx35_cpu_rev = IMX_CHIP_REVISION_2_1;
-		srev = "2.1";
-		break;
+		return IMX_CHIP_REVISION_2_1;
 	default:
-		mx35_cpu_rev = IMX_CHIP_REVISION_UNKNOWN;
-		srev = "unknown";
+		return IMX_CHIP_REVISION_UNKNOWN;
 	}
+}
 
-	printk(KERN_INFO "CPU identified as i.MX35, silicon rev %s\n", srev);
+int mx35_revision(void)
+{
+	if (mx35_cpu_rev == -1)
+		mx35_cpu_rev = mx35_read_cpu_rev();
+
+	return mx35_cpu_rev;
 }
+EXPORT_SYMBOL(mx35_revision);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/devices-imx27.h linux-libre-3.2-gnu/arch/arm/mach-imx/devices-imx27.h
--- linux-libre-3.1-gnu/arch/arm/mach-imx/devices-imx27.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/devices-imx27.h	2012-01-04 18:55:44.000000000 -0500
@@ -76,3 +76,7 @@
 #define imx27_add_spi_imx0(pdata)	imx27_add_cspi(0, pdata)
 #define imx27_add_spi_imx1(pdata)	imx27_add_cspi(1, pdata)
 #define imx27_add_spi_imx2(pdata)	imx27_add_cspi(2, pdata)
+
+extern const struct imx_pata_imx_data imx27_pata_imx_data;
+#define imx27_add_pata_imx() \
+	imx_add_pata_imx(&imx27_pata_imx_data)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/devices-imx31.h linux-libre-3.2-gnu/arch/arm/mach-imx/devices-imx31.h
--- linux-libre-3.1-gnu/arch/arm/mach-imx/devices-imx31.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/devices-imx31.h	2012-01-04 18:55:44.000000000 -0500
@@ -78,3 +78,7 @@
 #define imx31_add_spi_imx0(pdata)	imx31_add_cspi(0, pdata)
 #define imx31_add_spi_imx1(pdata)	imx31_add_cspi(1, pdata)
 #define imx31_add_spi_imx2(pdata)	imx31_add_cspi(2, pdata)
+
+extern const struct imx_pata_imx_data imx31_pata_imx_data;
+#define imx31_add_pata_imx() \
+	imx_add_pata_imx(&imx31_pata_imx_data)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/devices-imx35.h linux-libre-3.2-gnu/arch/arm/mach-imx/devices-imx35.h
--- linux-libre-3.1-gnu/arch/arm/mach-imx/devices-imx35.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/devices-imx35.h	2012-01-04 18:55:44.000000000 -0500
@@ -81,3 +81,7 @@
 	imx_add_spi_imx(&imx35_cspi_data[id], pdata)
 #define imx35_add_spi_imx0(pdata)	imx35_add_cspi(0, pdata)
 #define imx35_add_spi_imx1(pdata)	imx35_add_cspi(1, pdata)
+
+extern const struct imx_pata_imx_data imx35_pata_imx_data;
+#define imx35_add_pata_imx() \
+	imx_add_pata_imx(&imx35_pata_imx_data)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/gpc.c linux-libre-3.2-gnu/arch/arm/mach-imx/gpc.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/gpc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/gpc.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/hardware/gic.h>
+
+#define GPC_IMR1		0x008
+#define GPC_PGC_CPU_PDN		0x2a0
+
+#define IMR_NUM			4
+
+static void __iomem *gpc_base;
+static u32 gpc_wake_irqs[IMR_NUM];
+static u32 gpc_saved_imrs[IMR_NUM];
+
+void imx_gpc_pre_suspend(void)
+{
+	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
+	int i;
+
+	/* Tell GPC to power off ARM core when suspend */
+	writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
+
+	for (i = 0; i < IMR_NUM; i++) {
+		gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
+		writel_relaxed(~gpc_wake_irqs[i], reg_imr1 + i * 4);
+	}
+}
+
+void imx_gpc_post_resume(void)
+{
+	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
+	int i;
+
+	/* Keep ARM core powered on for other low-power modes */
+	writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN);
+
+	for (i = 0; i < IMR_NUM; i++)
+		writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
+}
+
+static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+	unsigned int idx = d->irq / 32 - 1;
+	u32 mask;
+
+	/* Sanity check for SPI irq */
+	if (d->irq < 32)
+		return -EINVAL;
+
+	mask = 1 << d->irq % 32;
+	gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask :
+				  gpc_wake_irqs[idx] & ~mask;
+
+	return 0;
+}
+
+static void imx_gpc_irq_unmask(struct irq_data *d)
+{
+	void __iomem *reg;
+	u32 val;
+
+	/* Sanity check for SPI irq */
+	if (d->irq < 32)
+		return;
+
+	reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
+	val = readl_relaxed(reg);
+	val &= ~(1 << d->irq % 32);
+	writel_relaxed(val, reg);
+}
+
+static void imx_gpc_irq_mask(struct irq_data *d)
+{
+	void __iomem *reg;
+	u32 val;
+
+	/* Sanity check for SPI irq */
+	if (d->irq < 32)
+		return;
+
+	reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
+	val = readl_relaxed(reg);
+	val |= 1 << (d->irq % 32);
+	writel_relaxed(val, reg);
+}
+
+void __init imx_gpc_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
+	gpc_base = of_iomap(np, 0);
+	WARN_ON(!gpc_base);
+
+	/* Register GPC as the secondary interrupt controller behind GIC */
+	gic_arch_extn.irq_mask = imx_gpc_irq_mask;
+	gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;
+	gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake;
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/head-v7.S linux-libre-3.2-gnu/arch/arm/mach-imx/head-v7.S
--- linux-libre-3.1-gnu/arch/arm/mach-imx/head-v7.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/head-v7.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+#include <asm/hardware/cache-l2x0.h>
+
+	.section ".text.head", "ax"
+	__CPUINIT
+
+/*
+ * The secondary kernel init calls v7_flush_dcache_all before it enables
+ * the L1; however, the L1 comes out of reset in an undefined state, so
+ * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
+ * of cache lines with uninitialized data and uninitialized tags to get
+ * written out to memory, which does really unpleasant things to the main
+ * processor.  We fix this by performing an invalidate, rather than a
+ * clean + invalidate, before jumping into the kernel.
+ *
+ * This funciton is cloned from arch/arm/mach-tegra/headsmp.S, and needs
+ * to be called for both secondary cores startup and primary core resume
+ * procedures.  Ideally, it should be moved into arch/arm/mm/cache-v7.S.
+ */
+ENTRY(v7_invalidate_l1)
+	mov	r0, #0
+	mcr	p15, 2, r0, c0, c0, 0
+	mrc	p15, 1, r0, c0, c0, 0
+
+	ldr	r1, =0x7fff
+	and	r2, r1, r0, lsr #13
+
+	ldr	r1, =0x3ff
+
+	and	r3, r1, r0, lsr #3	@ NumWays - 1
+	add	r2, r2, #1		@ NumSets
+
+	and	r0, r0, #0x7
+	add	r0, r0, #4	@ SetShift
+
+	clz	r1, r3		@ WayShift
+	add	r4, r3, #1	@ NumWays
+1:	sub	r2, r2, #1	@ NumSets--
+	mov	r3, r4		@ Temp = NumWays
+2:	subs	r3, r3, #1	@ Temp--
+	mov	r5, r3, lsl r1
+	mov	r6, r2, lsl r0
+	orr	r5, r5, r6	@ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
+	mcr	p15, 0, r5, c7, c6, 2
+	bgt	2b
+	cmp	r2, #0
+	bgt	1b
+	dsb
+	isb
+	mov	pc, lr
+ENDPROC(v7_invalidate_l1)
+
+#ifdef CONFIG_SMP
+ENTRY(v7_secondary_startup)
+	bl	v7_invalidate_l1
+	b	secondary_startup
+ENDPROC(v7_secondary_startup)
+#endif
+
+/*
+ * The following code is located into the .data section.  This is to
+ * allow phys_l2x0_saved_regs to be accessed with a relative load
+ * as we are running on physical address here.
+ */
+	.data
+	.align
+
+	.macro	pl310_resume
+	ldr	r2, phys_l2x0_saved_regs
+	ldr	r0, [r2, #L2X0_R_PHY_BASE]	@ get physical base of l2x0
+	ldr	r1, [r2, #L2X0_R_AUX_CTRL]	@ get aux_ctrl value
+	str	r1, [r0, #L2X0_AUX_CTRL]	@ restore aux_ctrl
+	mov	r1, #0x1
+	str	r1, [r0, #L2X0_CTRL]		@ re-enable L2
+	.endm
+
+ENTRY(v7_cpu_resume)
+	bl	v7_invalidate_l1
+	pl310_resume
+	b	cpu_resume
+ENDPROC(v7_cpu_resume)
+
+	.globl	phys_l2x0_saved_regs
+phys_l2x0_saved_regs:
+        .long   0
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/hotplug.c linux-libre-3.2-gnu/arch/arm/mach-imx/hotplug.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/hotplug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/hotplug.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/errno.h>
+#include <asm/cacheflush.h>
+#include <mach/common.h>
+
+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)
+{
+	flush_cache_all();
+	imx_enable_cpu(cpu, false);
+	cpu_do_idle();
+
+	/* We should never return from idle */
+	panic("cpu %d unexpectedly exit from shutdown\n", cpu);
+}
+
+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-3.1-gnu/arch/arm/mach-imx/iomux-imx31.c linux-libre-3.2-gnu/arch/arm/mach-imx/iomux-imx31.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/iomux-imx31.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/iomux-imx31.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,13 +17,12 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  * MA 02110-1301, USA.
  */
-
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <mach/hardware.h>
-#include <mach/gpio.h>
 #include <mach/iomux-mx3.h>
 
 /*
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/Kconfig linux-libre-3.2-gnu/arch/arm/mach-imx/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-imx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,18 +1,30 @@
 config IMX_HAVE_DMA_V1
 	bool
-#
-# ARCH_MX31 and ARCH_MX35 are left for compatibility
-# Some usages assume that having one of them implies not having (e.g.) ARCH_MX2.
-# To easily distinguish good and reviewed from unreviewed usages new (and IMHO
-# more sensible) names are used: SOC_IMX31 and SOC_IMX35
-config ARCH_MX31
+
+config HAVE_IMX_GPC
 	bool
 
-config ARCH_MX35
+config HAVE_IMX_MMDC
+	bool
+
+config HAVE_IMX_SRC
+	bool
+
+config ARCH_MX1
+	bool
+
+config MACH_MX21
+	bool
+
+config ARCH_MX25
+	bool
+
+config MACH_MX27
 	bool
 
 config SOC_IMX1
 	bool
+	select ARCH_MX1
 	select CPU_ARM920T
 	select IMX_HAVE_DMA_V1
 	select IMX_HAVE_IOMUX_V1
@@ -20,6 +32,7 @@
 
 config SOC_IMX21
 	bool
+	select MACH_MX21
 	select CPU_ARM926T
 	select ARCH_MXC_AUDMUX_V1
 	select IMX_HAVE_DMA_V1
@@ -28,6 +41,7 @@
 
 config SOC_IMX25
 	bool
+	select ARCH_MX25
 	select CPU_ARM926T
 	select ARCH_MXC_AUDMUX_V2
 	select ARCH_MXC_IOMUX_V3
@@ -35,6 +49,7 @@
 
 config SOC_IMX27
 	bool
+	select MACH_MX27
 	select CPU_ARM926T
 	select ARCH_MXC_AUDMUX_V1
 	select IMX_HAVE_DMA_V1
@@ -46,8 +61,8 @@
 	select CPU_V6
 	select IMX_HAVE_PLATFORM_MXC_RNGA
 	select ARCH_MXC_AUDMUX_V2
-	select ARCH_MX31
 	select MXC_AVIC
+	select SMP_ON_UP if SMP
 
 config SOC_IMX35
 	bool
@@ -55,11 +70,11 @@
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_MXC_AUDMUX_V2
 	select HAVE_EPIT
-	select ARCH_MX35
 	select MXC_AVIC
+	select SMP_ON_UP if SMP
 
 
-if ARCH_MX1
+if ARCH_IMX_V4_V5
 
 comment "MX1 platforms:"
 config MACH_MXLADS
@@ -87,30 +102,6 @@
 	help
 	  Say Yes here if you are using the Armadeus APF9328 development board
 
-endif
-
-if ARCH_MX2
-
-choice
-	prompt "CPUs:"
-	default MACH_MX21
-
-config MACH_MX21
-	bool "i.MX21 support"
-	help
-	  This enables support for Freescale's MX2 based i.MX21 processor.
-
-config MACH_MX27
-	bool "i.MX27 support"
-	help
-	  This enables support for Freescale's MX2 based i.MX27 processor.
-
-endchoice
-
-endif
-
-if MACH_MX21
-
 comment "MX21 platforms:"
 
 config MACH_MX21ADS
@@ -124,15 +115,12 @@
 	  Include support for MX21ADS platform. This includes specific
 	  configurations for the board and its peripherals.
 
-endif
-
-if ARCH_MX25
-
 comment "MX25 platforms:"
 
 config MACH_MX25_3DS
 	bool "Support MX25PDK (3DS) Platform"
 	select SOC_IMX25
+	select IMX_HAVE_PLATFORM_FLEXCAN
 	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select IMX_HAVE_PLATFORM_IMXDI_RTC
@@ -144,7 +132,7 @@
 	select IMX_HAVE_PLATFORM_MXC_NAND
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 
-config MACH_EUKREA_CPUIMX25
+config MACH_EUKREA_CPUIMX25SD
 	bool "Support Eukrea CPUIMX25 Platform"
 	select SOC_IMX25
 	select IMX_HAVE_PLATFORM_FLEXCAN
@@ -160,7 +148,7 @@
 
 choice
 	prompt "Baseboard"
-	depends on MACH_EUKREA_CPUIMX25
+	depends on MACH_EUKREA_CPUIMX25SD
 	default MACH_EUKREA_MBIMXSD25_BASEBOARD
 
 config MACH_EUKREA_MBIMXSD25_BASEBOARD
@@ -174,10 +162,6 @@
 
 endchoice
 
-endif
-
-if MACH_MX27
-
 comment "MX27 platforms:"
 
 config MACH_MX27ADS
@@ -356,7 +340,7 @@
 
 endif
 
-if ARCH_MX3
+if ARCH_IMX_V6_V7
 
 comment "MX31 platforms:"
 
@@ -449,6 +433,7 @@
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_IPU_CORE
 	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_MXC_MMC
 	select IMX_HAVE_PLATFORM_MXC_NAND
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	select MXC_ULPI if USB_ULPI
@@ -485,6 +470,7 @@
 	bool "Support Dave/DENX QongEVB-LITE platform"
 	select SOC_IMX31
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_IMX2_WDT
 	help
 	  Include support for Dave/DENX QongEVB-LITE platform. This includes
 	  specific configurations for the board and its peripherals.
@@ -556,7 +542,7 @@
 	  Include support for MX35PDK platform. This includes specific
 	  configurations for the board and its peripherals.
 
-config MACH_EUKREA_CPUIMX35
+config MACH_EUKREA_CPUIMX35SD
 	bool "Support Eukrea CPUIMX35 Platform"
 	select SOC_IMX35
 	select IMX_HAVE_PLATFORM_FLEXCAN
@@ -574,7 +560,7 @@
 
 choice
 	prompt "Baseboard"
-	depends on MACH_EUKREA_CPUIMX35
+	depends on MACH_EUKREA_CPUIMX35SD
 	default MACH_EUKREA_MBIMXSD35_BASEBOARD
 
 config MACH_EUKREA_MBIMXSD35_BASEBOARD
@@ -605,4 +591,20 @@
 	  Include support for VPR200 platform. This includes specific
 	  configurations for the board and its peripherals.
 
+comment "i.MX6 family:"
+
+config SOC_IMX6Q
+	bool "i.MX6 Quad support"
+	select ARM_GIC
+	select CACHE_L2X0
+	select CPU_V7
+	select HAVE_ARM_SCU
+	select HAVE_IMX_GPC
+	select HAVE_IMX_MMDC
+	select HAVE_IMX_SRC
+	select USE_OF
+
+	help
+	  This enables support for Freescale i.MX6 Quad processor.
+
 endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/lluart.c linux-libre-3.2-gnu/arch/arm/mach-imx/lluart.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/lluart.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/lluart.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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 <asm/page.h>
+#include <asm/sizes.h>
+#include <asm/mach/map.h>
+#include <mach/hardware.h>
+
+static struct map_desc imx_lluart_desc = {
+#ifdef CONFIG_DEBUG_IMX6Q_UART
+	.virtual	= MX6Q_IO_P2V(MX6Q_UART4_BASE_ADDR),
+	.pfn		= __phys_to_pfn(MX6Q_UART4_BASE_ADDR),
+	.length		= MX6Q_UART4_SIZE,
+	.type		= MT_DEVICE,
+#endif
+};
+
+void __init imx_lluart_map_io(void)
+{
+	if (imx_lluart_desc.virtual)
+		iotable_init(&imx_lluart_desc, 1);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/localtimer.c linux-libre-3.2-gnu/arch/arm/mach-imx/localtimer.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/localtimer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/localtimer.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/clockchips.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/smp_twd.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
+	if (!twd_base) {
+		twd_base = of_iomap(np, 0);
+		WARN_ON(!twd_base);
+	}
+	evt->irq = irq_of_parse_and_map(np, 0);
+	twd_timer_setup(evt);
+
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-apf9328.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-apf9328.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-apf9328.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-apf9328.c	2012-01-04 18:55:44.000000000 -0500
@@ -136,6 +136,7 @@
 	.map_io       = mx1_map_io,
 	.init_early   = imx1_init_early,
 	.init_irq     = mx1_init_irq,
+	.handle_irq   = imx1_handle_irq,
 	.timer        = &apf9328_timer,
 	.init_machine = apf9328_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-armadillo5x0.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-armadillo5x0.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-armadillo5x0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-armadillo5x0.c	2012-01-04 18:55:44.000000000 -0500
@@ -314,25 +314,19 @@
 	},
 };
 
-static struct physmap_flash_data armadillo5x0_nor_flash_pdata = {
+static const struct physmap_flash_data
+		armadillo5x0_nor_flash_pdata __initconst = {
 	.width		= 2,
 	.parts		= armadillo5x0_nor_flash_partitions,
 	.nr_parts	= ARRAY_SIZE(armadillo5x0_nor_flash_partitions),
 };
 
-static struct resource armadillo5x0_nor_flash_resource = {
+static const struct resource armadillo5x0_nor_flash_resource __initconst = {
 	.flags		= IORESOURCE_MEM,
 	.start		= MX31_CS0_BASE_ADDR,
 	.end		= MX31_CS0_BASE_ADDR + SZ_64M - 1,
 };
 
-static struct platform_device armadillo5x0_nor_flash = {
-	.name			= "physmap-flash",
-	.id			= -1,
-	.num_resources		= 1,
-	.resource		= &armadillo5x0_nor_flash_resource,
-};
-
 /*
  * FB support
  */
@@ -514,8 +508,10 @@
 	imx31_add_mx3_sdc_fb(&mx3fb_pdata);
 
 	/* Register NOR Flash */
-	mxc_register_device(&armadillo5x0_nor_flash,
-			    &armadillo5x0_nor_flash_pdata);
+	platform_device_register_resndata(NULL, "physmap-flash", -1,
+			&armadillo5x0_nor_flash_resource, 1,
+			&armadillo5x0_nor_flash_pdata,
+			sizeof(armadillo5x0_nor_flash_pdata));
 
 	/* Register NAND Flash */
 	imx31_add_mxc_nand(&armadillo5x0_nand_board_info);
@@ -558,10 +554,11 @@
 
 MACHINE_START(ARMADILLO5X0, "Armadillo-500")
 	/* Maintainer: Alberto Panizzo  */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &armadillo5x0_timer,
 	.init_machine = armadillo5x0_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-bug.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-bug.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-bug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-bug.c	2012-01-04 18:55:44.000000000 -0500
@@ -62,6 +62,7 @@
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &bug_timer,
 	.init_machine = bug_board_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-cpuimx27.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-cpuimx27.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-cpuimx27.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-cpuimx27.c	2012-01-04 18:55:44.000000000 -0500
@@ -311,10 +311,11 @@
 };
 
 MACHINE_START(EUKREA_CPUIMX27, "EUKREA CPUIMX27")
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &eukrea_cpuimx27_timer,
 	.init_machine = eukrea_cpuimx27_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-cpuimx35.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-cpuimx35.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-cpuimx35.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-cpuimx35.c	2012-01-04 18:55:44.000000000 -0500
@@ -53,12 +53,18 @@
 	.bitrate =		100000,
 };
 
+#define TSC2007_IRQGPIO		IMX_GPIO_NR(3, 2)
+static int tsc2007_get_pendown_state(void)
+{
+	return !gpio_get_value(TSC2007_IRQGPIO);
+}
+
 static struct tsc2007_platform_data tsc2007_info = {
 	.model			= 2007,
 	.x_plate_ohms		= 180,
+	.get_pendown_state = tsc2007_get_pendown_state,
 };
 
-#define TSC2007_IRQGPIO		IMX_GPIO_NR(3, 2)
 static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = {
 	{
 		I2C_BOARD_INFO("pcf8563", 0x51),
@@ -66,7 +72,7 @@
 		I2C_BOARD_INFO("tsc2007", 0x48),
 		.type		= "tsc2007",
 		.platform_data	= &tsc2007_info,
-		.irq		= gpio_to_irq(TSC2007_IRQGPIO),
+		.irq		= IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
 	},
 };
 
@@ -194,10 +200,11 @@
 
 MACHINE_START(EUKREA_CPUIMX35SD, "Eukrea CPUIMX35")
 	/* Maintainer: Eukrea Electromatique */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx35_map_io,
 	.init_early = imx35_init_early,
 	.init_irq = mx35_init_irq,
+	.handle_irq = imx35_handle_irq,
 	.timer = &eukrea_cpuimx35_timer,
 	.init_machine = eukrea_cpuimx35_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-eukrea_cpuimx25.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-eukrea_cpuimx25.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-eukrea_cpuimx25.c	2012-01-04 18:55:44.000000000 -0500
@@ -163,10 +163,11 @@
 
 MACHINE_START(EUKREA_CPUIMX25SD, "Eukrea CPUIMX25")
 	/* Maintainer: Eukrea Electromatique */
-	.boot_params = MX25_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx25_map_io,
 	.init_early = imx25_init_early,
 	.init_irq = mx25_init_irq,
+	.handle_irq = imx25_handle_irq,
 	.timer = &eukrea_cpuimx25_timer,
 	.init_machine = eukrea_cpuimx25_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-imx27ipcam.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-imx27ipcam.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-imx27ipcam.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-imx27ipcam.c	2012-01-04 18:55:44.000000000 -0500
@@ -71,10 +71,11 @@
 
 MACHINE_START(IMX27IPCAM, "Freescale IMX27IPCAM")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &mx27ipcam_timer,
 	.init_machine = mx27ipcam_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-imx27lite.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-imx27lite.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-imx27lite.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-imx27lite.c	2012-01-04 18:55:44.000000000 -0500
@@ -77,10 +77,11 @@
 };
 
 MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &mx27lite_timer,
 	.init_machine = mx27lite_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-imx27_visstrim_m10.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-imx27_visstrim_m10.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-imx27_visstrim_m10.c	2012-01-04 18:55:44.000000000 -0500
@@ -275,10 +275,11 @@
 };
 
 MACHINE_START(IMX27_VISSTRIM_M10, "Vista Silicon Visstrim_M10")
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &visstrim_m10_timer,
 	.init_machine = visstrim_m10_board_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-imx6q.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-imx6q.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-imx6q.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-imx6q.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+static void __init imx6q_init_machine(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+	imx6q_pm_init();
+}
+
+static void __init imx6q_map_io(void)
+{
+	imx_lluart_map_io();
+	imx_scu_map_io();
+	imx6q_clock_map_io();
+}
+
+static int __init imx6q_gpio_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
+
+	gpio_irq_base -= 32;
+	irq_domain_add_simple(np, gpio_irq_base);
+
+	return 0;
+}
+
+static const struct of_device_id imx6q_irq_match[] __initconst = {
+	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+	{ .compatible = "fsl,imx6q-gpio", .data = imx6q_gpio_add_irq_domain, },
+	{ /* sentinel */ }
+};
+
+static void __init imx6q_init_irq(void)
+{
+	l2x0_of_init(0, ~0UL);
+	imx_src_init();
+	imx_gpc_init();
+	of_irq_init(imx6q_irq_match);
+}
+
+static void __init imx6q_timer_init(void)
+{
+	mx6q_clocks_init();
+}
+
+static struct sys_timer imx6q_timer = {
+	.init = imx6q_timer_init,
+};
+
+static const char *imx6q_dt_compat[] __initdata = {
+	"fsl,imx6q-sabreauto",
+	NULL,
+};
+
+DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)")
+	.map_io		= imx6q_map_io,
+	.init_irq	= imx6q_init_irq,
+	.handle_irq	= imx6q_handle_irq,
+	.timer		= &imx6q_timer,
+	.init_machine	= imx6q_init_machine,
+	.dt_compat	= imx6q_dt_compat,
+MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-kzm_arm11_01.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-kzm_arm11_01.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-kzm_arm11_01.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-kzm_arm11_01.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 
 #include <mach/clock.h>
 #include <mach/common.h>
+#include <mach/hardware.h>
 #include <mach/iomux-mx3.h>
 
 #include "devices-imx31.h"
@@ -271,10 +272,11 @@
 };
 
 MACHINE_START(KZM_ARM11_01, "Kyoto Microcomputer Co., Ltd. KZM-ARM11-01")
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = kzm_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &kzm_timer,
 	.init_machine = kzm_board_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx1ads.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx1ads.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx1ads.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx1ads.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,23 +68,16 @@
  * Physmap flash
  */
 
-static struct physmap_flash_data mx1ads_flash_data = {
+static const struct physmap_flash_data mx1ads_flash_data __initconst = {
 	.width		= 4,		/* bankwidth in bytes */
 };
 
-static struct resource flash_resource = {
+static const struct resource flash_resource __initconst = {
 	.start	= MX1_CS0_PHYS,
 	.end	= MX1_CS0_PHYS + SZ_32M - 1,
 	.flags	= IORESOURCE_MEM,
 };
 
-static struct platform_device flash_device = {
-	.name	= "physmap-flash",
-	.id	= 0,
-	.resource = &flash_resource,
-	.num_resources = 1,
-};
-
 /*
  * I2C
  */
@@ -125,7 +118,9 @@
 	imx1_add_imx_uart1(&uart1_pdata);
 
 	/* Physmap flash */
-	mxc_register_device(&flash_device, &mx1ads_flash_data);
+	platform_device_register_resndata(NULL, "physmap-flash", 0,
+			&flash_resource, 1,
+			&mx1ads_flash_data, sizeof(mx1ads_flash_data));
 
 	/* I2C */
 	i2c_register_board_info(0, mx1ads_i2c_devices,
@@ -145,19 +140,21 @@
 
 MACHINE_START(MX1ADS, "Freescale MX1ADS")
 	/* Maintainer: Sascha Hauer, Pengutronix */
-	.boot_params = MX1_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx1_map_io,
 	.init_early = imx1_init_early,
 	.init_irq = mx1_init_irq,
+	.handle_irq = imx1_handle_irq,
 	.timer = &mx1ads_timer,
 	.init_machine = mx1ads_init,
 MACHINE_END
 
 MACHINE_START(MXLADS, "Freescale MXLADS")
-	.boot_params = MX1_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx1_map_io,
 	.init_early = imx1_init_early,
 	.init_irq = mx1_init_irq,
+	.handle_irq = imx1_handle_irq,
 	.timer = &mx1ads_timer,
 	.init_machine = mx1ads_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx21ads.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx21ads.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx21ads.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx21ads.c	2012-01-04 18:55:44.000000000 -0500
@@ -305,10 +305,11 @@
 
 MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX21_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx21ads_map_io,
 	.init_early = imx21_init_early,
 	.init_irq = mx21_init_irq,
+	.handle_irq = imx21_handle_irq,
 	.timer = &mx21ads_timer,
 	.init_machine = mx21ads_board_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx25_3ds.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx25_3ds.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx25_3ds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx25_3ds.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,8 @@
 
 #include "devices-imx25.h"
 
+#define MX25PDK_CAN_PWDN	IMX_GPIO_NR(4, 6)
+
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
@@ -108,6 +110,11 @@
 	/* I2C1 */
 	MX25_PAD_I2C1_CLK__I2C1_CLK,
 	MX25_PAD_I2C1_DAT__I2C1_DAT,
+
+	/* CAN1 */
+	MX25_PAD_GPIO_A__CAN1_TX,
+	MX25_PAD_GPIO_B__CAN1_RX,
+	MX25_PAD_D14__GPIO_4_6,	/* CAN_PWDN */
 };
 
 static const struct fec_platform_data mx25_fec_pdata __initconst = {
@@ -240,6 +247,9 @@
 
 	imx25_add_sdhci_esdhc_imx(0, &mx25pdk_esdhc_pdata);
 	imx25_add_imx_i2c0(&mx25_3ds_i2c0_data);
+
+	gpio_request_one(MX25PDK_CAN_PWDN, GPIOF_OUT_INIT_LOW, "can-pwdn");
+	imx25_add_flexcan0(NULL);
 }
 
 static void __init mx25pdk_timer_init(void)
@@ -253,10 +263,11 @@
 
 MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX25_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx25_map_io,
 	.init_early = imx25_init_early,
 	.init_irq = mx25_init_irq,
+	.handle_irq = imx25_handle_irq,
 	.timer = &mx25pdk_timer,
 	.init_machine = mx25pdk_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx27_3ds.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx27_3ds.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx27_3ds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx27_3ds.c	2012-01-04 18:55:44.000000000 -0500
@@ -241,7 +241,7 @@
 };
 
 static struct regulator_consumer_supply vmmc1_consumers[] = {
-	REGULATOR_SUPPLY("lcd_2v8", NULL),
+	REGULATOR_SUPPLY("vcore", "spi0.0"),
 };
 
 static struct regulator_init_data vmmc1_init = {
@@ -257,7 +257,7 @@
 };
 
 static struct regulator_consumer_supply vgen_consumers[] = {
-	REGULATOR_SUPPLY("vdd_lcdio", NULL),
+	REGULATOR_SUPPLY("vdd", "spi0.0"),
 };
 
 static struct regulator_init_data vgen_init = {
@@ -293,8 +293,7 @@
 		.num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
 
 	},
-	.flags  = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN |
-	MC13783_USE_RTC,
+	.flags  = MC13XXX_USE_TOUCHSCREEN | MC13XXX_USE_RTC,
 };
 
 /* SPI */
@@ -348,8 +347,6 @@
 static struct l4f00242t03_pdata mx27_3ds_lcd_pdata = {
 	.reset_gpio		= LCD_RESET,
 	.data_enable_gpio	= LCD_ENABLE,
-	.core_supply		= "lcd_2v8",
-	.io_supply		= "vdd_lcdio",
 };
 
 static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
@@ -359,7 +356,7 @@
 		.bus_num	= 1,
 		.chip_select	= 0, /* SS0 */
 		.platform_data	= &mc13783_pdata,
-		.irq = gpio_to_irq(PMIC_INT),
+		.irq = IMX_GPIO_TO_IRQ(PMIC_INT),
 		.mode = SPI_CS_HIGH,
 	}, {
 		.modalias	= "l4f00242t03",
@@ -421,10 +418,11 @@
 
 MACHINE_START(MX27_3DS, "Freescale MX27PDK")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &mx27pdk_timer,
 	.init_machine = mx27pdk_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx27ads.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx27ads.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx27ads.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx27ads.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
@@ -27,7 +27,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
-#include <mach/gpio.h>
 #include <mach/iomux-mx27.h>
 
 #include "devices-imx27.h"
@@ -345,10 +344,11 @@
 
 MACHINE_START(MX27ADS, "Freescale i.MX27ADS")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27ads_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &mx27ads_timer,
 	.init_machine = mx27ads_board_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx31_3ds.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx31_3ds.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx31_3ds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx31_3ds.c	2012-01-04 18:55:44.000000000 -0500
@@ -285,8 +285,6 @@
 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",
 };
 
 /*
@@ -411,7 +409,7 @@
 };
 
 static struct regulator_consumer_supply vmmc1_consumers[] = {
-	REGULATOR_SUPPLY("lcd_2v8", NULL),
+	REGULATOR_SUPPLY("vcore", "spi0.0"),
 	REGULATOR_SUPPLY("cmos_2v8", "soc-camera-pdrv.0"),
 };
 
@@ -428,7 +426,7 @@
 };
 
 static struct regulator_consumer_supply vgen_consumers[] = {
-	REGULATOR_SUPPLY("vdd_lcdio", NULL),
+	REGULATOR_SUPPLY("vdd", "spi0.0"),
 };
 
 static struct regulator_init_data vgen_init = {
@@ -494,7 +492,7 @@
 		.regulators = mx31_3ds_regulators,
 		.num_regulators = ARRAY_SIZE(mx31_3ds_regulators),
 	},
-	.flags  = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN,
+	.flags  = MC13XXX_USE_TOUCHSCREEN,
 };
 
 /* SPI */
@@ -542,7 +540,7 @@
 mx31_3ds_nand_board_info __initconst = {
 	.width		= 1,
 	.hw_ecc		= 1,
-#ifdef MACH_MX31_3DS_MXC_NAND_USE_BBT
+#ifdef CONFIG_MACH_MX31_3DS_MXC_NAND_USE_BBT
 	.flash_bbt	= 1,
 #endif
 };
@@ -764,10 +762,11 @@
 
 MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &mx31_3ds_timer,
 	.init_machine = mx31_3ds_init,
 	.reserve = mx31_3ds_reserve,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx31ads.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx31ads.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx31ads.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx31ads.c	2012-01-04 18:55:44.000000000 -0500
@@ -535,10 +535,11 @@
 
 MACHINE_START(MX31ADS, "Freescale MX31ADS")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx31ads_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31ads_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &mx31ads_timer,
 	.init_machine = mx31ads_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx31lilly.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx31lilly.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx31lilly.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx31lilly.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
+#include <linux/moduleparam.h>
 #include <linux/smsc911x.h>
 #include <linux/mtd/physmap.h>
 #include <linux/spi/spi.h>
@@ -295,10 +296,11 @@
 };
 
 MACHINE_START(LILLY1131, "INCO startec LILLY-1131")
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &mx31lilly_timer,
 	.init_machine = mx31lilly_board_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx31lite.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx31lite.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx31lite.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx31lite.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/memory.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/moduleparam.h>
 #include <linux/smsc911x.h>
 #include <linux/mfd/mc13783.h>
 #include <linux/spi/spi.h>
@@ -112,8 +113,7 @@
 };
 
 static struct mc13xxx_platform_data mc13783_pdata __initdata = {
-	.flags  = MC13XXX_USE_RTC |
-		  MC13XXX_USE_REGULATOR,
+	.flags = MC13XXX_USE_RTC,
 };
 
 static struct spi_board_info mc13783_spi_dev __initdata = {
@@ -280,10 +280,11 @@
 
 MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx31lite_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &mx31lite_timer,
 	.init_machine = mx31lite_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx31moboard.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx31moboard.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx31moboard.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx31moboard.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/moduleparam.h>
 #include <linux/leds.h>
 #include <linux/memory.h>
 #include <linux/mtd/physmap.h>
@@ -28,6 +29,10 @@
 #include <linux/spi/spi.h>
 #include <linux/types.h>
 #include <linux/memblock.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/input.h>
 
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
@@ -222,7 +227,7 @@
 	},
 };
 
-static struct mc13783_led_platform_data moboard_led[] = {
+static struct mc13xxx_led_platform_data moboard_led[] = {
 	{
 		.id = MC13783_LED_R1,
 		.name = "coreboard-led-4:red",
@@ -255,7 +260,7 @@
 	},
 };
 
-static struct mc13783_leds_platform_data moboard_leds = {
+static struct mc13xxx_leds_platform_data moboard_leds = {
 	.num_leds = ARRAY_SIZE(moboard_led),
 	.led = moboard_led,
 	.flags = MC13783_LED_SLEWLIMTC,
@@ -264,14 +269,20 @@
 	.tc2_period = MC13783_LED_PERIOD_10MS,
 };
 
+static struct mc13xxx_buttons_platform_data moboard_buttons = {
+	.b1on_flags = MC13783_BUTTON_DBNC_750MS | MC13783_BUTTON_ENABLE |
+			MC13783_BUTTON_POL_INVERT,
+	.b1on_key = KEY_POWER,
+};
+
 static struct mc13xxx_platform_data moboard_pmic = {
 	.regulators = {
 		.regulators = moboard_regulators,
 		.num_regulators = ARRAY_SIZE(moboard_regulators),
 	},
 	.leds = &moboard_leds,
-	.flags = MC13XXX_USE_REGULATOR | MC13XXX_USE_RTC |
-		MC13XXX_USE_ADC | MC13XXX_USE_LED,
+	.buttons = &moboard_buttons,
+	.flags = MC13XXX_USE_RTC | MC13XXX_USE_ADC,
 };
 
 static struct spi_board_info moboard_spi_board_info[] __initdata = {
@@ -490,6 +501,18 @@
 
 }
 
+static void mx31moboard_poweroff(void)
+{
+	struct clk *clk = clk_get_sys("imx2-wdt.0", NULL);
+
+	if (!IS_ERR(clk))
+		clk_enable(clk);
+
+	mxc_iomux_mode(MX31_PIN_WATCHDOG_RST__WATCHDOG_RST);
+
+	__raw_writew(1 << 6 | 1 << 2, MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
+}
+
 static int mx31moboard_baseboard;
 core_param(mx31moboard_baseboard, mx31moboard_baseboard, int, 0444);
 
@@ -528,6 +551,8 @@
 
 	moboard_usbh2_init();
 
+	pm_power_off = mx31moboard_poweroff;
+
 	switch (mx31moboard_baseboard) {
 	case MX31NOBOARD:
 		break;
@@ -567,11 +592,12 @@
 
 MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
 	/* Maintainer: Valentin Longchamp, EPFL Mobots group */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.reserve = mx31moboard_reserve,
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &mx31moboard_timer,
 	.init_machine = mx31moboard_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx35_3ds.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx35_3ds.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mx35_3ds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mx35_3ds.c	2012-01-04 18:55:44.000000000 -0500
@@ -217,10 +217,11 @@
 
 MACHINE_START(MX35_3DS, "Freescale MX35PDK")
 	/* Maintainer: Freescale Semiconductor, Inc */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx35_map_io,
 	.init_early = imx35_init_early,
 	.init_irq = mx35_init_irq,
+	.handle_irq = imx35_handle_irq,
 	.timer = &mx35pdk_timer,
 	.init_machine = mx35_3ds_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mxt_td60.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mxt_td60.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-mxt_td60.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-mxt_td60.c	2012-01-04 18:55:44.000000000 -0500
@@ -267,10 +267,11 @@
 
 MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60")
 	/* maintainer: Maxtrack Industrial */
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &mxt_td60_timer,
 	.init_machine = mxt_td60_board_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-pca100.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-pca100.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-pca100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-pca100.c	2012-01-04 18:55:44.000000000 -0500
@@ -435,10 +435,11 @@
 };
 
 MACHINE_START(PCA100, "phyCARD-i.MX27")
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.init_machine = pca100_init,
 	.timer = &pca100_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-pcm037.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-pcm037.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-pcm037.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-pcm037.c	2012-01-04 18:55:44.000000000 -0500
@@ -688,11 +688,12 @@
 
 MACHINE_START(PCM037, "Phytec Phycore pcm037")
 	/* Maintainer: Pengutronix */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.reserve = pcm037_reserve,
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &pcm037_timer,
 	.init_machine = pcm037_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-pcm038.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-pcm038.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-pcm038.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-pcm038.c	2012-01-04 18:55:44.000000000 -0500
@@ -176,7 +176,9 @@
  * setup other stuffs to access the sram. */
 static void __init pcm038_init_sram(void)
 {
-	mx27_setup_weimcs(1, 0x0000d843, 0x22252521, 0x22220a00);
+	__raw_writel(0x0000d843, MX27_IO_ADDRESS(MX27_WEIM_CSCRxU(1)));
+	__raw_writel(0x22252521, MX27_IO_ADDRESS(MX27_WEIM_CSCRxL(1)));
+	__raw_writel(0x22220a00, MX27_IO_ADDRESS(MX27_WEIM_CSCRxA(1)));
 }
 
 static const struct imxi2c_platform_data pcm038_i2c1_data __initconst = {
@@ -266,8 +268,7 @@
 		.regulators = pcm038_regulators,
 		.num_regulators = ARRAY_SIZE(pcm038_regulators),
 	},
-	.flags = MC13783_USE_ADC | MC13783_USE_REGULATOR |
-		 MC13783_USE_TOUCHSCREEN,
+	.flags = MC13XXX_USE_ADC | MC13XXX_USE_TOUCHSCREEN,
 };
 
 static struct spi_board_info pcm038_spi_board_info[] __initdata = {
@@ -349,10 +350,11 @@
 };
 
 MACHINE_START(PCM038, "phyCORE-i.MX27")
-	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &pcm038_timer,
 	.init_machine = pcm038_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-pcm043.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-pcm043.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-pcm043.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-pcm043.c	2012-01-04 18:55:44.000000000 -0500
@@ -418,10 +418,11 @@
 
 MACHINE_START(PCM043, "Phytec Phycore pcm043")
 	/* Maintainer: Pengutronix */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx35_map_io,
 	.init_early = imx35_init_early,
 	.init_irq = mx35_init_irq,
+	.handle_irq = imx35_handle_irq,
 	.timer = &pcm043_timer,
 	.init_machine = pcm043_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-qong.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-qong.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-qong.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-qong.c	2012-01-04 18:55:44.000000000 -0500
@@ -190,7 +190,10 @@
 static void __init qong_init_nand_mtd(void)
 {
 	/* init CS */
-	mx31_setup_weimcs(3, 0x00004f00, 0x20013b31, 0x00020800);
+	__raw_writel(0x00004f00, MX31_IO_ADDRESS(MX31_WEIM_CSCRxU(3)));
+	__raw_writel(0x20013b31, MX31_IO_ADDRESS(MX31_WEIM_CSCRxL(3)));
+	__raw_writel(0x00020800, MX31_IO_ADDRESS(MX31_WEIM_CSCRxA(3)));
+
 	mxc_iomux_set_gpr(MUX_SDCTL_CSD1_SEL, true);
 
 	/* enable pin */
@@ -249,6 +252,7 @@
 	mxc_init_imx_uart();
 	qong_init_nor_mtd();
 	qong_init_fpga();
+	imx31_add_imx2_wdt(NULL);
 }
 
 static void __init qong_timer_init(void)
@@ -262,10 +266,11 @@
 
 MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
 	/* Maintainer: DENX Software Engineering GmbH */
-	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &qong_timer,
 	.init_machine = qong_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-scb9328.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-scb9328.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-scb9328.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-scb9328.c	2012-01-04 18:55:44.000000000 -0500
@@ -137,10 +137,11 @@
 
 MACHINE_START(SCB9328, "Synertronixx scb9328")
 	/* Sascha Hauer */
-	.boot_params = 0x08000100,
+	.atag_offset = 100,
 	.map_io = mx1_map_io,
 	.init_early = imx1_init_early,
 	.init_irq = mx1_init_irq,
+	.handle_irq = imx1_handle_irq,
 	.timer = &scb9328_timer,
 	.init_machine = scb9328_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mach-vpr200.c linux-libre-3.2-gnu/arch/arm/mach-imx/mach-vpr200.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mach-vpr200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mach-vpr200.c	2012-01-04 18:55:44.000000000 -0500
@@ -162,7 +162,7 @@
 	}, {
 		I2C_BOARD_INFO("mc13892", 0x08),
 		.platform_data = &vpr200_pmic,
-		.irq = gpio_to_irq(GPIO_PMIC_INT),
+		.irq = IMX_GPIO_TO_IRQ(GPIO_PMIC_INT),
 	}
 };
 
@@ -319,6 +319,7 @@
 	.map_io = mx35_map_io,
 	.init_early = imx35_init_early,
 	.init_irq = mx35_init_irq,
+	.handle_irq = imx35_handle_irq,
 	.timer = &vpr200_timer,
 	.init_machine = vpr200_board_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/Makefile linux-libre-3.2-gnu/arch/arm/mach-imx/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-imx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,16 +1,15 @@
 obj-$(CONFIG_IMX_HAVE_DMA_V1) += dma-v1.o
 
-obj-$(CONFIG_ARCH_MX1) += clock-imx1.o mm-imx1.o
-obj-$(CONFIG_MACH_MX21) += clock-imx21.o mm-imx21.o
+obj-$(CONFIG_SOC_IMX1) += clock-imx1.o mm-imx1.o
+obj-$(CONFIG_SOC_IMX21) += clock-imx21.o mm-imx21.o
 
-obj-$(CONFIG_ARCH_MX25) += clock-imx25.o mm-imx25.o ehci-imx25.o
+obj-$(CONFIG_SOC_IMX25) += clock-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
 
-obj-$(CONFIG_MACH_MX27) += cpu-imx27.o pm-imx27.o
-obj-$(CONFIG_MACH_MX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
+obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o
+obj-$(CONFIG_SOC_IMX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
 
-obj-$(CONFIG_SOC_IMX31) += mm-imx31.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o
-obj-$(CONFIG_SOC_IMX35) += mm-imx35.o cpu-imx35.o clock-imx35.o ehci-imx35.o
-obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
+obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o
+obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o
 
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
@@ -25,7 +24,7 @@
 
 # i.MX25 based machines
 obj-$(CONFIG_MACH_MX25_3DS) += mach-mx25_3ds.o
-obj-$(CONFIG_MACH_EUKREA_CPUIMX25) += mach-eukrea_cpuimx25.o
+obj-$(CONFIG_MACH_EUKREA_CPUIMX25SD) += mach-eukrea_cpuimx25.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD25_BASEBOARD) += eukrea_mbimxsd25-baseboard.o
 
 # i.MX27 based machines
@@ -58,6 +57,17 @@
 # i.MX35 based machines
 obj-$(CONFIG_MACH_PCM043) += mach-pcm043.o
 obj-$(CONFIG_MACH_MX35_3DS) += mach-mx35_3ds.o
-obj-$(CONFIG_MACH_EUKREA_CPUIMX35) += mach-cpuimx35.o
+obj-$(CONFIG_MACH_EUKREA_CPUIMX35SD) += mach-cpuimx35.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o
 obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o
+
+obj-$(CONFIG_DEBUG_LL) += lluart.o
+obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
+obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
+obj-$(CONFIG_HAVE_IMX_SRC) += src.o
+obj-$(CONFIG_CPU_V7) += head-v7.o
+AFLAGS_head-v7.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SMP) += platsmp.o
+obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
+obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o pm-imx6q.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-imx/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-imx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,19 +1,27 @@
-zreladdr-$(CONFIG_ARCH_MX1)	:= 0x08008000
-params_phys-$(CONFIG_ARCH_MX1)	:= 0x08000100
-initrd_phys-$(CONFIG_ARCH_MX1)	:= 0x08800000
+zreladdr-$(CONFIG_SOC_IMX1)	+= 0x08008000
+params_phys-$(CONFIG_SOC_IMX1)	:= 0x08000100
+initrd_phys-$(CONFIG_SOC_IMX1)	:= 0x08800000
 
-zreladdr-$(CONFIG_MACH_MX21)	:= 0xC0008000
-params_phys-$(CONFIG_MACH_MX21)	:= 0xC0000100
-initrd_phys-$(CONFIG_MACH_MX21)	:= 0xC0800000
+zreladdr-$(CONFIG_SOC_IMX21)	+= 0xC0008000
+params_phys-$(CONFIG_SOC_IMX21)	:= 0xC0000100
+initrd_phys-$(CONFIG_SOC_IMX21)	:= 0xC0800000
 
-zreladdr-$(CONFIG_ARCH_MX25)	:= 0x80008000
-params_phys-$(CONFIG_ARCH_MX25)	:= 0x80000100
-initrd_phys-$(CONFIG_ARCH_MX25)	:= 0x80800000
+zreladdr-$(CONFIG_SOC_IMX25)	+= 0x80008000
+params_phys-$(CONFIG_SOC_IMX25)	:= 0x80000100
+initrd_phys-$(CONFIG_SOC_IMX25)	:= 0x80800000
 
-zreladdr-$(CONFIG_MACH_MX27)	:= 0xA0008000
-params_phys-$(CONFIG_MACH_MX27)	:= 0xA0000100
-initrd_phys-$(CONFIG_MACH_MX27)	:= 0xA0800000
+zreladdr-$(CONFIG_SOC_IMX27)	+= 0xA0008000
+params_phys-$(CONFIG_SOC_IMX27)	:= 0xA0000100
+initrd_phys-$(CONFIG_SOC_IMX27)	:= 0xA0800000
 
-zreladdr-$(CONFIG_ARCH_MX3)	:= 0x80008000
-params_phys-$(CONFIG_ARCH_MX3)	:= 0x80000100
-initrd_phys-$(CONFIG_ARCH_MX3)	:= 0x80800000
+zreladdr-$(CONFIG_SOC_IMX31)	+= 0x80008000
+params_phys-$(CONFIG_SOC_IMX31)	:= 0x80000100
+initrd_phys-$(CONFIG_SOC_IMX31)	:= 0x80800000
+
+zreladdr-$(CONFIG_SOC_IMX35)	+= 0x80008000
+params_phys-$(CONFIG_SOC_IMX35)	:= 0x80000100
+initrd_phys-$(CONFIG_SOC_IMX35)	:= 0x80800000
+
+zreladdr-$(CONFIG_SOC_IMX6Q)	+= 0x10008000
+params_phys-$(CONFIG_SOC_IMX6Q)	:= 0x10000100
+initrd_phys-$(CONFIG_SOC_IMX6Q)	:= 0x10800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mmdc.c linux-libre-3.2-gnu/arch/arm/mach-imx/mmdc.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mmdc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mmdc.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+
+#define MMDC_MAPSR		0x404
+#define BP_MMDC_MAPSR_PSD	0
+#define BP_MMDC_MAPSR_PSS	4
+
+static int __devinit imx_mmdc_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	void __iomem *mmdc_base, *reg;
+	u32 val;
+	int timeout = 0x400;
+
+	mmdc_base = of_iomap(np, 0);
+	WARN_ON(!mmdc_base);
+
+	reg = mmdc_base + MMDC_MAPSR;
+
+	/* Enable automatic power saving */
+	val = readl_relaxed(reg);
+	val &= ~(1 << BP_MMDC_MAPSR_PSD);
+	writel_relaxed(val, reg);
+
+	/* Ensure it's successfully enabled */
+	while (!(readl_relaxed(reg) & 1 << BP_MMDC_MAPSR_PSS) && --timeout)
+		cpu_relax();
+
+	if (unlikely(!timeout)) {
+		pr_warn("%s: failed to enable automatic power saving\n",
+			__func__);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static struct of_device_id imx_mmdc_dt_ids[] = {
+	{ .compatible = "fsl,imx6q-mmdc", },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver imx_mmdc_driver = {
+	.driver		= {
+		.name	= "imx-mmdc",
+		.owner	= THIS_MODULE,
+		.of_match_table = imx_mmdc_dt_ids,
+	},
+	.probe		= imx_mmdc_probe,
+};
+
+static int __init imx_mmdc_init(void)
+{
+	return platform_driver_register(&imx_mmdc_driver);
+}
+postcore_initcall(imx_mmdc_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mm-imx31.c linux-libre-3.2-gnu/arch/arm/mach-imx/mm-imx31.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mm-imx31.c	2012-03-19 21:30:58.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mm-imx31.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-/*
- *  Copyright (C) 1999,2000 Arm Limited
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *  Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- *    - add MX31 specific definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT 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/mm.h>
-#include <linux/init.h>
-#include <linux/err.h>
-
-#include <asm/pgtable.h>
-#include <asm/mach/map.h>
-
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-v3.h>
-#include <mach/irqs.h>
-
-static struct map_desc mx31_io_desc[] __initdata = {
-	imx_map_entry(MX31, X_MEMC, MT_DEVICE),
-	imx_map_entry(MX31, AVIC, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX31, AIPS1, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX31, AIPS2, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX31, SPBA0, MT_DEVICE_NONSHARED),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-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));
-}
-
-void __init mx31_init_irq(void)
-{
-	mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
-}
-
-static struct sdma_script_start_addrs imx31_to1_sdma_script __initdata = {
-	.per_2_per_addr = 1677,
-};
-
-static struct sdma_script_start_addrs imx31_to2_sdma_script __initdata = {
-	.ap_2_ap_addr = 423,
-	.ap_2_bp_addr = 829,
-	.bp_2_ap_addr = 1029,
-};
-
-static struct sdma_platform_data imx31_sdma_pdata __initdata = {
-	.fw_name = "/*(DEBLOBBED)*/",
-	.script_addrs = &imx31_to2_sdma_script,
-};
-
-void __init imx31_soc_init(void)
-{
-	int to_version = mx31_revision() >> 4;
-
-	mxc_register_gpio("imx31-gpio", 0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0);
-	mxc_register_gpio("imx31-gpio", 1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0);
-	mxc_register_gpio("imx31-gpio", 2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0);
-
-	if (to_version == 1) {
-		strncpy(imx31_sdma_pdata.fw_name, "/*(DEBLOBBED)*/",
-			strlen(imx31_sdma_pdata.fw_name));
-		imx31_sdma_pdata.script_addrs = &imx31_to1_sdma_script;
-	}
-
-	imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mm-imx35.c linux-libre-3.2-gnu/arch/arm/mach-imx/mm-imx35.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mm-imx35.c	2012-03-19 21:31:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mm-imx35.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,109 +0,0 @@
-/*
- *  Copyright (C) 1999,2000 Arm Limited
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *  Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- *    - add MX31 specific definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT 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/mm.h>
-#include <linux/init.h>
-#include <linux/err.h>
-
-#include <asm/pgtable.h>
-#include <asm/mach/map.h>
-#include <asm/hardware/cache-l2x0.h>
-
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-v3.h>
-#include <mach/irqs.h>
-
-static struct map_desc mx35_io_desc[] __initdata = {
-	imx_map_entry(MX35, X_MEMC, MT_DEVICE),
-	imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED),
-};
-
-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));
-}
-
-void __init mx35_init_irq(void)
-{
-	mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
-}
-
-static struct sdma_script_start_addrs imx35_to1_sdma_script __initdata = {
-	.ap_2_ap_addr = 642,
-	.uart_2_mcu_addr = 817,
-	.mcu_2_app_addr = 747,
-	.uartsh_2_mcu_addr = 1183,
-	.per_2_shp_addr = 1033,
-	.mcu_2_shp_addr = 961,
-	.ata_2_mcu_addr = 1333,
-	.mcu_2_ata_addr = 1252,
-	.app_2_mcu_addr = 683,
-	.shp_2_per_addr = 1111,
-	.shp_2_mcu_addr = 892,
-};
-
-static struct sdma_script_start_addrs imx35_to2_sdma_script __initdata = {
-	.ap_2_ap_addr = 729,
-	.uart_2_mcu_addr = 904,
-	.per_2_app_addr = 1597,
-	.mcu_2_app_addr = 834,
-	.uartsh_2_mcu_addr = 1270,
-	.per_2_shp_addr = 1120,
-	.mcu_2_shp_addr = 1048,
-	.ata_2_mcu_addr = 1429,
-	.mcu_2_ata_addr = 1339,
-	.app_2_per_addr = 1531,
-	.app_2_mcu_addr = 770,
-	.shp_2_per_addr = 1198,
-	.shp_2_mcu_addr = 979,
-};
-
-static struct sdma_platform_data imx35_sdma_pdata __initdata = {
-	.fw_name = "/*(DEBLOBBED)*/",
-	.script_addrs = &imx35_to2_sdma_script,
-};
-
-void __init imx35_soc_init(void)
-{
-	int to_version = mx35_revision() >> 4;
-
-	/* i.mx35 has the i.mx31 type gpio */
-	mxc_register_gpio("imx31-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
-	mxc_register_gpio("imx31-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
-	mxc_register_gpio("imx31-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
-
-	if (to_version == 1) {
-		strncpy(imx35_sdma_pdata.fw_name, "/*(DEBLOBBED)*/",
-			strlen(imx35_sdma_pdata.fw_name));
-		imx35_sdma_pdata.script_addrs = &imx35_to1_sdma_script;
-	}
-
-	imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/mm-imx3.c linux-libre-3.2-gnu/arch/arm/mach-imx/mm-imx3.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/mm-imx3.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/mm-imx3.c	2012-03-19 21:32:39.000000000 -0400
@@ -0,0 +1,263 @@
+/*
+ *  Copyright (C) 1999,2000 Arm Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *    - add MX31 specific definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/mm.h>
+#include <linux/init.h>
+#include <linux/err.h>
+
+#include <asm/pgtable.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach/map.h>
+
+#include <mach/common.h>
+#include <mach/devices-common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-v3.h>
+#include <mach/irqs.h>
+
+static void imx3_idle(void)
+{
+	unsigned long reg = 0;
+
+	if (!need_resched())
+		__asm__ __volatile__(
+			/* disable I and D cache */
+			"mrc p15, 0, %0, c1, c0, 0\n"
+			"bic %0, %0, #0x00001000\n"
+			"bic %0, %0, #0x00000004\n"
+			"mcr p15, 0, %0, c1, c0, 0\n"
+			/* invalidate I cache */
+			"mov %0, #0\n"
+			"mcr p15, 0, %0, c7, c5, 0\n"
+			/* clear and invalidate D cache */
+			"mov %0, #0\n"
+			"mcr p15, 0, %0, c7, c14, 0\n"
+			/* WFI */
+			"mov %0, #0\n"
+			"mcr p15, 0, %0, c7, c0, 4\n"
+			"nop\n" "nop\n" "nop\n" "nop\n"
+			"nop\n" "nop\n" "nop\n"
+			/* enable I and D cache */
+			"mrc p15, 0, %0, c1, c0, 0\n"
+			"orr %0, %0, #0x00001000\n"
+			"orr %0, %0, #0x00000004\n"
+			"mcr p15, 0, %0, c1, c0, 0\n"
+			: "=r" (reg));
+	local_irq_enable();
+}
+
+static void __iomem *imx3_ioremap(unsigned long phys_addr, size_t size,
+				  unsigned int mtype)
+{
+	if (mtype == MT_DEVICE) {
+		/*
+		 * Access all peripherals below 0x80000000 as nonshared device
+		 * on mx3, but leave l2cc alone.  Otherwise cache corruptions
+		 * can occur.
+		 */
+		if (phys_addr < 0x80000000 &&
+				!addr_in_module(phys_addr, MX3x_L2CC))
+			mtype = MT_DEVICE_NONSHARED;
+	}
+
+	return __arm_ioremap(phys_addr, size, mtype);
+}
+
+void imx3_init_l2x0(void)
+{
+	void __iomem *l2x0_base;
+	void __iomem *clkctl_base;
+
+/*
+ * First of all, we must repair broken chip settings. There are some
+ * i.MX35 CPUs in the wild, comming with bogus L2 cache settings. These
+ * misconfigured CPUs will run amok immediately when the L2 cache gets enabled.
+ * Workaraound is to setup the correct register setting prior enabling the
+ * L2 cache. This should not hurt already working CPUs, as they are using the
+ * same value.
+ */
+#define L2_MEM_VAL 0x10
+
+	clkctl_base = ioremap(MX35_CLKCTL_BASE_ADDR, 4096);
+	if (clkctl_base != NULL) {
+		writel(0x00000515, clkctl_base + L2_MEM_VAL);
+		iounmap(clkctl_base);
+	} else {
+		pr_err("L2 cache: Cannot fix timing. Trying to continue without\n");
+	}
+
+	l2x0_base = ioremap(MX3x_L2CC_BASE_ADDR, 4096);
+	if (IS_ERR(l2x0_base)) {
+		printk(KERN_ERR "remapping L2 cache area failed with %ld\n",
+				PTR_ERR(l2x0_base));
+		return;
+	}
+
+	l2x0_init(l2x0_base, 0x00030024, 0x00000000);
+}
+
+#ifdef CONFIG_SOC_IMX31
+static struct map_desc mx31_io_desc[] __initdata = {
+	imx_map_entry(MX31, X_MEMC, MT_DEVICE),
+	imx_map_entry(MX31, AVIC, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX31, AIPS1, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX31, AIPS2, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX31, SPBA0, MT_DEVICE_NONSHARED),
+};
+
+/*
+ * This function initializes the memory map. It is called during the
+ * system startup to create static physical to virtual memory mappings
+ * for the IO modules.
+ */
+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));
+	pm_idle = imx3_idle;
+	imx_ioremap = imx3_ioremap;
+}
+
+void __init mx31_init_irq(void)
+{
+	mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
+}
+
+static struct sdma_script_start_addrs imx31_to1_sdma_script __initdata = {
+	.per_2_per_addr = 1677,
+};
+
+static struct sdma_script_start_addrs imx31_to2_sdma_script __initdata = {
+	.ap_2_ap_addr = 423,
+	.ap_2_bp_addr = 829,
+	.bp_2_ap_addr = 1029,
+};
+
+static struct sdma_platform_data imx31_sdma_pdata __initdata = {
+	.fw_name = "/*(DEBLOBBED)*/",
+	.script_addrs = &imx31_to2_sdma_script,
+};
+
+void __init imx31_soc_init(void)
+{
+	int to_version = mx31_revision() >> 4;
+
+	imx3_init_l2x0();
+
+	mxc_register_gpio("imx31-gpio", 0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0);
+	mxc_register_gpio("imx31-gpio", 1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0);
+	mxc_register_gpio("imx31-gpio", 2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0);
+
+	if (to_version == 1) {
+		strncpy(imx31_sdma_pdata.fw_name, "/*(DEBLOBBED)*/",
+			strlen(imx31_sdma_pdata.fw_name));
+		imx31_sdma_pdata.script_addrs = &imx31_to1_sdma_script;
+	}
+
+	imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
+}
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+static struct map_desc mx35_io_desc[] __initdata = {
+	imx_map_entry(MX35, X_MEMC, MT_DEVICE),
+	imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED),
+};
+
+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));
+	pm_idle = imx3_idle;
+	imx_ioremap = imx3_ioremap;
+}
+
+void __init mx35_init_irq(void)
+{
+	mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
+}
+
+static struct sdma_script_start_addrs imx35_to1_sdma_script __initdata = {
+	.ap_2_ap_addr = 642,
+	.uart_2_mcu_addr = 817,
+	.mcu_2_app_addr = 747,
+	.uartsh_2_mcu_addr = 1183,
+	.per_2_shp_addr = 1033,
+	.mcu_2_shp_addr = 961,
+	.ata_2_mcu_addr = 1333,
+	.mcu_2_ata_addr = 1252,
+	.app_2_mcu_addr = 683,
+	.shp_2_per_addr = 1111,
+	.shp_2_mcu_addr = 892,
+};
+
+static struct sdma_script_start_addrs imx35_to2_sdma_script __initdata = {
+	.ap_2_ap_addr = 729,
+	.uart_2_mcu_addr = 904,
+	.per_2_app_addr = 1597,
+	.mcu_2_app_addr = 834,
+	.uartsh_2_mcu_addr = 1270,
+	.per_2_shp_addr = 1120,
+	.mcu_2_shp_addr = 1048,
+	.ata_2_mcu_addr = 1429,
+	.mcu_2_ata_addr = 1339,
+	.app_2_per_addr = 1531,
+	.app_2_mcu_addr = 770,
+	.shp_2_per_addr = 1198,
+	.shp_2_mcu_addr = 979,
+};
+
+static struct sdma_platform_data imx35_sdma_pdata __initdata = {
+	.fw_name = "/*(DEBLOBBED)*/",
+	.script_addrs = &imx35_to2_sdma_script,
+};
+
+void __init imx35_soc_init(void)
+{
+	int to_version = mx35_revision() >> 4;
+
+	imx3_init_l2x0();
+
+	/* i.mx35 has the i.mx31 type gpio */
+	mxc_register_gpio("imx31-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
+	mxc_register_gpio("imx31-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
+	mxc_register_gpio("imx31-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
+
+	if (to_version == 1) {
+		strncpy(imx35_sdma_pdata.fw_name, "/*(DEBLOBBED)*/",
+			strlen(imx35_sdma_pdata.fw_name));
+		imx35_sdma_pdata.script_addrs = &imx35_to1_sdma_script;
+	}
+
+	imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
+}
+#endif /* ifdef CONFIG_SOC_IMX35 */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/platsmp.c linux-libre-3.2-gnu/arch/arm/mach-imx/platsmp.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/platsmp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/smp.h>
+#include <asm/page.h>
+#include <asm/smp_scu.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/map.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+static void __iomem *scu_base;
+
+static struct map_desc scu_io_desc __initdata = {
+	/* .virtual and .pfn are run-time assigned */
+	.length		= SZ_4K,
+	.type		= MT_DEVICE,
+};
+
+void __init imx_scu_map_io(void)
+{
+	unsigned long base;
+
+	/* Get SCU base */
+	asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+	scu_io_desc.virtual = IMX_IO_P2V(base);
+	scu_io_desc.pfn = __phys_to_pfn(base);
+	iotable_init(&scu_io_desc, 1);
+
+	scu_base = IMX_IO_ADDRESS(base);
+}
+
+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);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	imx_set_cpu_jump(cpu, v7_secondary_startup);
+	imx_enable_cpu(cpu, true);
+	return 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)
+{
+	int i, ncores;
+
+	ncores = scu_get_core_count(scu_base);
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+
+	set_smp_cross_call(gic_raise_softirq);
+}
+
+void imx_smp_prepare(void)
+{
+	scu_enable(scu_base);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+	imx_smp_prepare();
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/pm-imx27.c linux-libre-3.2-gnu/arch/arm/mach-imx/pm-imx27.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/pm-imx27.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/pm-imx27.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
 #include <linux/suspend.h>
 #include <linux/io.h>
 #include <mach/system.h>
-#include <mach/mx27.h>
+#include <mach/hardware.h>
 
 static int mx27_suspend_enter(suspend_state_t state)
 {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/pm-imx6q.c linux-libre-3.2-gnu/arch/arm/mach-imx/pm-imx6q.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/pm-imx6q.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/pm-imx6q.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/io.h>
+#include <linux/of.h>
+#include <linux/suspend.h>
+#include <asm/cacheflush.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+extern unsigned long phys_l2x0_saved_regs;
+
+static int imx6q_suspend_finish(unsigned long val)
+{
+	cpu_do_idle();
+	return 0;
+}
+
+static int imx6q_pm_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_MEM:
+		imx6q_set_lpm(STOP_POWER_OFF);
+		imx_gpc_pre_suspend();
+		imx_set_cpu_jump(0, v7_cpu_resume);
+		/* Zzz ... */
+		cpu_suspend(0, imx6q_suspend_finish);
+		imx_smp_prepare();
+		imx_gpc_post_resume();
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct platform_suspend_ops imx6q_pm_ops = {
+	.enter = imx6q_pm_enter,
+	.valid = suspend_valid_only_mem,
+};
+
+void __init imx6q_pm_init(void)
+{
+	/*
+	 * The l2x0 core code provides an infrastucture to save and restore
+	 * l2x0 registers across suspend/resume cycle.  But because imx6q
+	 * retains L2 content during suspend and needs to resume L2 before
+	 * MMU is enabled, it can only utilize register saving support and
+	 * have to take care of restoring on its own.  So we save physical
+	 * address of the data structure used by l2x0 core to save registers,
+	 * and later restore the necessary ones in imx6q resume entry.
+	 */
+	phys_l2x0_saved_regs = __pa(&l2x0_saved_regs);
+
+	suspend_set_ops(&imx6q_pm_ops);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-imx/src.c linux-libre-3.2-gnu/arch/arm/mach-imx/src.c
--- linux-libre-3.1-gnu/arch/arm/mach-imx/src.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-imx/src.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/smp.h>
+#include <asm/unified.h>
+
+#define SRC_SCR				0x000
+#define SRC_GPR1			0x020
+#define BP_SRC_SCR_CORE1_RST		14
+#define BP_SRC_SCR_CORE1_ENABLE		22
+
+static void __iomem *src_base;
+
+#ifndef CONFIG_SMP
+#define cpu_logical_map(cpu)		0
+#endif
+
+void imx_enable_cpu(int cpu, bool enable)
+{
+	u32 mask, val;
+
+	cpu = cpu_logical_map(cpu);
+	mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
+	val = readl_relaxed(src_base + SRC_SCR);
+	val = enable ? val | mask : val & ~mask;
+	writel_relaxed(val, src_base + SRC_SCR);
+}
+
+void imx_set_cpu_jump(int cpu, void *jump_addr)
+{
+	cpu = cpu_logical_map(cpu);
+	writel_relaxed(BSYM(virt_to_phys(jump_addr)),
+		       src_base + SRC_GPR1 + cpu * 8);
+}
+
+void __init imx_src_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-src");
+	src_base = of_iomap(np, 0);
+	WARN_ON(!src_base);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-integrator/core.c linux-libre-3.2-gnu/arch/arm/mach-integrator/core.c
--- linux-libre-3.1-gnu/arch/arm/mach-integrator/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-integrator/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -126,6 +126,10 @@
 	{	/* Bus clock */
 		.con_id		= "apb_pclk",
 		.clk		= &dummy_apb_pclk,
+	}, {
+		/* Integrator/AP timer frequency */
+		.dev_id		= "ap_timer",
+		.clk		= &clk24mhz,
 	}, {	/* UART0 */
 		.dev_id		= "mb:16",
 		.clk		= &uartclk,
@@ -205,7 +209,7 @@
 
 #define CM_CTRL	IO_ADDRESS(INTEGRATOR_HDR_CTRL)
 
-static DEFINE_SPINLOCK(cm_lock);
+static DEFINE_RAW_SPINLOCK(cm_lock);
 
 /**
  * cm_control - update the CM_CTRL register.
@@ -217,10 +221,10 @@
 	unsigned long flags;
 	u32 val;
 
-	spin_lock_irqsave(&cm_lock, flags);
+	raw_spin_lock_irqsave(&cm_lock, flags);
 	val = readl(CM_CTRL) & ~mask;
 	writel(val | set, CM_CTRL);
-	spin_unlock_irqrestore(&cm_lock, flags);
+	raw_spin_unlock_irqrestore(&cm_lock, flags);
 }
 
 EXPORT_SYMBOL(cm_control);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-integrator/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-integrator/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-integrator/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-integrator/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *
 */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x16000000	@ physical base address
 		mov	\rv, #0xf0000000	@ virtual base
 		add	\rv, \rv, #0x16000000 >> 4
diff -druN linux-libre-3.1-gnu/arch/arm/mach-integrator/include/mach/io.h linux-libre-3.2-gnu/arch/arm/mach-integrator/include/mach/io.h
--- linux-libre-3.1-gnu/arch/arm/mach-integrator/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-integrator/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,8 +20,6 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#define IO_SPACE_LIMIT 0xffff
-
 /*
  * WARNING: this has to mirror definitions in platform.h
  */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-integrator/include/mach/platform.h linux-libre-3.2-gnu/arch/arm/mach-integrator/include/mach/platform.h
--- linux-libre-3.1-gnu/arch/arm/mach-integrator/include/mach/platform.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-integrator/include/mach/platform.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,9 +13,6 @@
  * 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
- */
 /**************************************************************************
  * * Copyright Â© ARM Limited 1998.  All rights reserved.
  * ***********************************************************************/
@@ -399,15 +396,6 @@
 #define INTEGRATOR_TIMER1_BASE          (INTEGRATOR_CT_BASE + 0x100)
 #define INTEGRATOR_TIMER2_BASE          (INTEGRATOR_CT_BASE + 0x200)
 
-#define TICKS_PER_uSEC                  24
-
-/*
- *  These are useconds NOT ticks.
- *
- */
-#define mSEC_1                          1000
-#define mSEC_10                         (mSEC_1 * 10)
-
 #define INTEGRATOR_CSR_BASE             0x10000000
 #define INTEGRATOR_CSR_SIZE             0x10000000
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-integrator/integrator_ap.c linux-libre-3.2-gnu/arch/arm/mach-integrator/integrator_ap.c
--- linux-libre-3.1-gnu/arch/arm/mach-integrator/integrator_ap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-integrator/integrator_ap.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/mtd/physmap.h>
+#include <linux/clk.h>
 #include <video/vga.h>
 
 #include <mach/hardware.h>
@@ -322,27 +323,16 @@
 #define TIMER1_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER1_BASE)
 #define TIMER2_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER2_BASE)
 
-/*
- * How long is the timer interval?
- */
-#define TIMER_INTERVAL	(TICKS_PER_uSEC * mSEC_10)
-#if TIMER_INTERVAL >= 0x100000
-#define TICKS2USECS(x)	(256 * (x) / TICKS_PER_uSEC)
-#elif TIMER_INTERVAL >= 0x10000
-#define TICKS2USECS(x)	(16 * (x) / TICKS_PER_uSEC)
-#else
-#define TICKS2USECS(x)	((x) / TICKS_PER_uSEC)
-#endif
-
 static unsigned long timer_reload;
 
-static void integrator_clocksource_init(u32 khz)
+static void integrator_clocksource_init(unsigned long inrate)
 {
 	void __iomem *base = (void __iomem *)TIMER2_VA_BASE;
 	u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
+	unsigned long rate = inrate;
 
-	if (khz >= 1500) {
-		khz /= 16;
+	if (rate >= 1500000) {
+		rate /= 16;
 		ctrl |= TIMER_CTRL_DIV16;
 	}
 
@@ -350,7 +340,7 @@
 	writel(ctrl, base + TIMER_CTRL);
 
 	clocksource_mmio_init(base + TIMER_VALUE, "timer2",
-		khz * 1000, 200, 16, clocksource_mmio_readl_down);
+			rate, 200, 16, clocksource_mmio_readl_down);
 }
 
 static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE;
@@ -374,15 +364,29 @@
 {
 	u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
 
-	BUG_ON(mode == CLOCK_EVT_MODE_ONESHOT);
+	/* Disable timer */
+	writel(ctrl, clkevt_base + TIMER_CTRL);
 
-	if (mode == CLOCK_EVT_MODE_PERIODIC) {
-		writel(ctrl, clkevt_base + TIMER_CTRL);
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		/* Enable the timer and start the periodic tick */
 		writel(timer_reload, clkevt_base + TIMER_LOAD);
 		ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
+		writel(ctrl, clkevt_base + TIMER_CTRL);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		/* Leave the timer disabled, .set_next_event will enable it */
+		ctrl &= ~TIMER_CTRL_PERIODIC;
+		writel(ctrl, clkevt_base + TIMER_CTRL);
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+	default:
+		/* Just leave in disabled state */
+		break;
 	}
 
-	writel(ctrl, clkevt_base + TIMER_CTRL);
 }
 
 static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt)
@@ -398,12 +402,10 @@
 
 static struct clock_event_device integrator_clockevent = {
 	.name		= "timer1",
-	.shift		= 34,
-	.features	= CLOCK_EVT_FEAT_PERIODIC,
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
 	.set_mode	= clkevt_set_mode,
 	.set_next_event	= clkevt_set_next_event,
 	.rating		= 300,
-	.cpumask	= cpu_all_mask,
 };
 
 static struct irqaction integrator_timer_irq = {
@@ -413,29 +415,27 @@
 	.dev_id		= &integrator_clockevent,
 };
 
-static void integrator_clockevent_init(u32 khz)
+static void integrator_clockevent_init(unsigned long inrate)
 {
-	struct clock_event_device *evt = &integrator_clockevent;
+	unsigned long rate = inrate;
 	unsigned int ctrl = 0;
 
-	if (khz * 1000 > 0x100000 * HZ) {
-		khz /= 256;
+	/* Calculate and program a divisor */
+	if (rate > 0x100000 * HZ) {
+		rate /= 256;
 		ctrl |= TIMER_CTRL_DIV256;
-	} else if (khz * 1000 > 0x10000 * HZ) {
-		khz /= 16;
+	} else if (rate > 0x10000 * HZ) {
+		rate /= 16;
 		ctrl |= TIMER_CTRL_DIV16;
 	}
-
-	timer_reload = khz * 1000 / HZ;
+	timer_reload = rate / HZ;
 	writel(ctrl, clkevt_base + TIMER_CTRL);
 
-	evt->irq = IRQ_TIMERINT1;
-	evt->mult = div_sc(khz, NSEC_PER_MSEC, evt->shift);
-	evt->max_delta_ns = clockevent_delta2ns(0xffff, evt);
-	evt->min_delta_ns = clockevent_delta2ns(0xf, evt);
-
 	setup_irq(IRQ_TIMERINT1, &integrator_timer_irq);
-	clockevents_register_device(evt);
+	clockevents_config_and_register(&integrator_clockevent,
+					rate,
+					1,
+					0xffffU);
 }
 
 /*
@@ -443,14 +443,20 @@
  */
 static void __init ap_init_timer(void)
 {
-	u32 khz = TICKS_PER_uSEC * 1000;
+	struct clk *clk;
+	unsigned long rate;
+
+	clk = clk_get_sys("ap_timer", NULL);
+	BUG_ON(IS_ERR(clk));
+	clk_enable(clk);
+	rate = clk_get_rate(clk);
 
 	writel(0, TIMER0_VA_BASE + TIMER_CTRL);
 	writel(0, TIMER1_VA_BASE + TIMER_CTRL);
 	writel(0, TIMER2_VA_BASE + TIMER_CTRL);
 
-	integrator_clocksource_init(khz);
-	integrator_clockevent_init(khz);
+	integrator_clocksource_init(rate);
+	integrator_clockevent_init(rate);
 }
 
 static struct sys_timer ap_timer = {
@@ -459,7 +465,7 @@
 
 MACHINE_START(INTEGRATOR, "ARM-Integrator")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.reserve	= integrator_reserve,
 	.map_io		= ap_map_io,
 	.init_early	= integrator_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-integrator/integrator_cp.c linux-libre-3.2-gnu/arch/arm/mach-integrator/integrator_cp.c
--- linux-libre-3.1-gnu/arch/arm/mach-integrator/integrator_cp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-integrator/integrator_cp.c	2012-01-04 18:55:44.000000000 -0500
@@ -492,7 +492,7 @@
 
 MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.reserve	= integrator_reserve,
 	.map_io		= intcp_map_io,
 	.init_early	= intcp_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-integrator/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-integrator/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-integrator/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-integrator/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-integrator/pci_v3.c linux-libre-3.2-gnu/arch/arm/mach-integrator/pci_v3.c
--- linux-libre-3.1-gnu/arch/arm/mach-integrator/pci_v3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-integrator/pci_v3.c	2012-01-04 18:55:44.000000000 -0500
@@ -163,7 +163,7 @@
  *	 7:2	register number
  *  
  */
-static DEFINE_SPINLOCK(v3_lock);
+static DEFINE_RAW_SPINLOCK(v3_lock);
 
 #define PCI_BUS_NONMEM_START	0x00000000
 #define PCI_BUS_NONMEM_SIZE	SZ_256M
@@ -284,7 +284,7 @@
 	unsigned long flags;
 	u32 v;
 
-	spin_lock_irqsave(&v3_lock, flags);
+	raw_spin_lock_irqsave(&v3_lock, flags);
 	addr = v3_open_config_window(bus, devfn, where);
 
 	switch (size) {
@@ -302,7 +302,7 @@
 	}
 
 	v3_close_config_window();
-	spin_unlock_irqrestore(&v3_lock, flags);
+	raw_spin_unlock_irqrestore(&v3_lock, flags);
 
 	*val = v;
 	return PCIBIOS_SUCCESSFUL;
@@ -314,7 +314,7 @@
 	unsigned long addr;
 	unsigned long flags;
 
-	spin_lock_irqsave(&v3_lock, flags);
+	raw_spin_lock_irqsave(&v3_lock, flags);
 	addr = v3_open_config_window(bus, devfn, where);
 
 	switch (size) {
@@ -335,7 +335,7 @@
 	}
 
 	v3_close_config_window();
-	spin_unlock_irqrestore(&v3_lock, flags);
+	raw_spin_unlock_irqrestore(&v3_lock, flags);
 
 	return PCIBIOS_SUCCESSFUL;
 }
@@ -513,7 +513,7 @@
 	hook_fault_code(8, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
 	hook_fault_code(10, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
 
-	spin_lock_irqsave(&v3_lock, flags);
+	raw_spin_lock_irqsave(&v3_lock, flags);
 
 	/*
 	 * Unlock V3 registers, but only if they were previously locked.
@@ -586,7 +586,7 @@
 		printk(KERN_ERR "PCI: unable to grab PCI error "
 		       "interrupt: %d\n", ret);
 
-	spin_unlock_irqrestore(&v3_lock, flags);
+	raw_spin_unlock_irqrestore(&v3_lock, flags);
 }
 
 void __init pci_v3_postinit(void)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop13xx/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-iop13xx/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-iop13xx/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop13xx/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  * published by the Free Software Foundation.
  */
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	mov	\rp, #0x00002300
 	orr	\rp, \rp, #0x00000040
 	orr	\rv, \rp, #0xfe000000	@ virtual
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop13xx/iq81340mc.c linux-libre-3.2-gnu/arch/arm/mach-iop13xx/iq81340mc.c
--- linux-libre-3.1-gnu/arch/arm/mach-iop13xx/iq81340mc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop13xx/iq81340mc.c	2012-01-04 18:55:44.000000000 -0500
@@ -91,7 +91,7 @@
 
 MACHINE_START(IQ81340MC, "Intel IQ81340MC")
 	/* Maintainer: Dan Williams <dan.j.williams@intel.com> */
-	.boot_params    = 0x00000100,
+	.atag_offset    = 0x100,
 	.map_io         = iop13xx_map_io,
 	.init_irq       = iop13xx_init_irq,
 	.timer          = &iq81340mc_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop13xx/iq81340sc.c linux-libre-3.2-gnu/arch/arm/mach-iop13xx/iq81340sc.c
--- linux-libre-3.1-gnu/arch/arm/mach-iop13xx/iq81340sc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop13xx/iq81340sc.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,7 +93,7 @@
 
 MACHINE_START(IQ81340SC, "Intel IQ81340SC")
 	/* Maintainer: Dan Williams <dan.j.williams@intel.com> */
-	.boot_params    = 0x00000100,
+	.atag_offset    = 0x100,
 	.map_io         = iop13xx_map_io,
 	.init_irq       = iop13xx_init_irq,
 	.timer          = &iq81340sc_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop13xx/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-iop13xx/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-iop13xx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop13xx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y   := 0x00008000
+   zreladdr-y   += 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y 	:= 0x00800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop13xx/pci.c linux-libre-3.2-gnu/arch/arm/mach-iop13xx/pci.c
--- linux-libre-3.1-gnu/arch/arm/mach-iop13xx/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop13xx/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/jiffies.h>
+#include <linux/export.h>
 #include <asm/irq.h>
 #include <mach/hardware.h>
 #include <asm/sizes.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop32x/em7210.c linux-libre-3.2-gnu/arch/arm/mach-iop32x/em7210.c
--- linux-libre-3.1-gnu/arch/arm/mach-iop32x/em7210.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop32x/em7210.c	2012-01-04 18:55:44.000000000 -0500
@@ -203,7 +203,7 @@
 }
 
 MACHINE_START(EM7210, "Lanner EM7210")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= em7210_map_io,
 	.init_irq	= iop32x_init_irq,
 	.timer		= &em7210_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop32x/glantank.c linux-libre-3.2-gnu/arch/arm/mach-iop32x/glantank.c
--- linux-libre-3.1-gnu/arch/arm/mach-iop32x/glantank.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop32x/glantank.c	2012-01-04 18:55:44.000000000 -0500
@@ -207,7 +207,7 @@
 
 MACHINE_START(GLANTANK, "GLAN Tank")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= glantank_map_io,
 	.init_irq	= iop32x_init_irq,
 	.timer		= &glantank_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop32x/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-iop32x/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-iop32x/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop32x/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  * published by the Free Software Foundation.
  */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0xfe000000	@ physical as well as virtual
 		orr	\rp, \rp, #0x00800000	@ location of the UART
 		mov	\rv, \rp
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop32x/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-iop32x/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-iop32x/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop32x/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-/*
- * arch/arm/mach-iop32x/include/mach/memory.h
- */
-
-#ifndef __MEMORY_H
-#define __MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0xa0000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop32x/iq31244.c linux-libre-3.2-gnu/arch/arm/mach-iop32x/iq31244.c
--- linux-libre-3.1-gnu/arch/arm/mach-iop32x/iq31244.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop32x/iq31244.c	2012-01-04 18:55:44.000000000 -0500
@@ -313,7 +313,7 @@
 
 MACHINE_START(IQ31244, "Intel IQ31244")
 	/* Maintainer: Intel Corp. */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= iq31244_map_io,
 	.init_irq	= iop32x_init_irq,
 	.timer		= &iq31244_timer,
@@ -327,7 +327,7 @@
  */
 MACHINE_START(EP80219, "Intel EP80219")
 	/* Maintainer: Intel Corp. */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= iq31244_map_io,
 	.init_irq	= iop32x_init_irq,
 	.timer		= &iq31244_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop32x/iq80321.c linux-libre-3.2-gnu/arch/arm/mach-iop32x/iq80321.c
--- linux-libre-3.1-gnu/arch/arm/mach-iop32x/iq80321.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop32x/iq80321.c	2012-01-04 18:55:44.000000000 -0500
@@ -186,7 +186,7 @@
 
 MACHINE_START(IQ80321, "Intel IQ80321")
 	/* Maintainer: Intel Corp. */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= iq80321_map_io,
 	.init_irq	= iop32x_init_irq,
 	.timer		= &iq80321_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop32x/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-iop32x/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-iop32x/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop32x/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0xa0008000
+   zreladdr-y	+= 0xa0008000
 params_phys-y	:= 0xa0000100
 initrd_phys-y	:= 0xa0800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop32x/n2100.c linux-libre-3.2-gnu/arch/arm/mach-iop32x/n2100.c
--- linux-libre-3.1-gnu/arch/arm/mach-iop32x/n2100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop32x/n2100.c	2012-01-04 18:55:44.000000000 -0500
@@ -327,7 +327,7 @@
 
 MACHINE_START(N2100, "Thecus N2100")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= n2100_map_io,
 	.init_irq	= iop32x_init_irq,
 	.timer		= &n2100_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop33x/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-iop33x/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-iop33x/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop33x/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  * published by the Free Software Foundation.
  */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x00ff0000
 		orr	\rp, \rp, #0x0000f700
 		orr	\rv, #0xfe000000	@ virtual
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop33x/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-iop33x/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-iop33x/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop33x/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-/*
- * arch/arm/mach-iop33x/include/mach/memory.h
- */
-
-#ifndef __MEMORY_H
-#define __MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop33x/iq80331.c linux-libre-3.2-gnu/arch/arm/mach-iop33x/iq80331.c
--- linux-libre-3.1-gnu/arch/arm/mach-iop33x/iq80331.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop33x/iq80331.c	2012-01-04 18:55:44.000000000 -0500
@@ -141,7 +141,7 @@
 
 MACHINE_START(IQ80331, "Intel IQ80331")
 	/* Maintainer: Intel Corp. */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= iop3xx_map_io,
 	.init_irq	= iop33x_init_irq,
 	.timer		= &iq80331_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop33x/iq80332.c linux-libre-3.2-gnu/arch/arm/mach-iop33x/iq80332.c
--- linux-libre-3.1-gnu/arch/arm/mach-iop33x/iq80332.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop33x/iq80332.c	2012-01-04 18:55:44.000000000 -0500
@@ -141,7 +141,7 @@
 
 MACHINE_START(IQ80332, "Intel IQ80332")
 	/* Maintainer: Intel Corp. */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= iop3xx_map_io,
 	.init_irq	= iop33x_init_irq,
 	.timer		= &iq80332_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-iop33x/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-iop33x/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-iop33x/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-iop33x/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp2000/core.c linux-libre-3.2-gnu/arch/arm/mach-ixp2000/core.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp2000/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp2000/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
  * License version 2. This program is licensed "as is" without any 
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
@@ -25,6 +25,7 @@
 #include <linux/bitops.h>
 #include <linux/serial_8250.h>
 #include <linux/mm.h>
+#include <linux/export.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -39,7 +40,7 @@
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 
-#include <mach/gpio.h>
+#include <mach/gpio-ixp2000.h>
 
 static DEFINE_SPINLOCK(ixp2000_slowport_lock);
 static unsigned long ixp2000_slowport_irq_flags;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp2000/enp2611.c linux-libre-3.2-gnu/arch/arm/mach-ixp2000/enp2611.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp2000/enp2611.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp2000/enp2611.c	2012-01-04 18:55:44.000000000 -0500
@@ -254,7 +254,7 @@
 
 MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= enp2611_map_io,
 	.init_irq	= ixp2000_init_irq,
 	.timer		= &enp2611_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp2000/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-ixp2000/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-ixp2000/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp2000/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *
 */
 
-		.macro  addruart, rp, rv
+		.macro  addruart, rp, rv, tmp
 		mov	\rp, #0x00030000
 #ifdef	__ARMEB__
 		orr	\rp, \rp, #0x00000003
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp2000/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-ixp2000/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-ixp2000/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp2000/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,48 +0,0 @@
-/*
- * arch/arm/mach-ixp2000/include/mach/gpio.h
- *
- * Copyright (C) 2002 Intel Corporation.
- *
- * This program is free software, you can redistribute it and/or modify 
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/*
- * IXP2000 GPIO in/out, edge/level detection for IRQs:
- * IRQs are generated on Falling-edge, Rising-Edge, Level-low, Level-High
- * or both Falling-edge and Rising-edge.  
- * This must be called *before* the corresponding IRQ is registerd.
- * Use this instead of directly setting the GPIO registers.
- * GPIOs may also be used as GPIOs (e.g. for emulating i2c/smb)
- */
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-#ifndef __ASSEMBLY__
-
-#define GPIO_IN				0
-#define GPIO_OUT			1
-
-#define IXP2000_GPIO_LOW		0
-#define IXP2000_GPIO_HIGH		1
-
-extern void gpio_line_config(int line, int direction);
-
-static inline int gpio_line_get(int line)
-{
-	return (((*IXP2000_GPIO_PLR) >> line) & 1);
-}
-
-static inline void gpio_line_set(int line, int value)
-{
-	if (value == IXP2000_GPIO_HIGH) {
-		ixp2000_reg_write(IXP2000_GPIO_POSR, 1 << line);
-	} else if (value == IXP2000_GPIO_LOW) {
-		ixp2000_reg_write(IXP2000_GPIO_POCR, 1 << line);
-	}
-}
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* ASM_ARCH_IXP2000_GPIO_H_ */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h linux-libre-3.2-gnu/arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h
--- linux-libre-3.1-gnu/arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp2000/include/mach/gpio-ixp2000.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,48 @@
+/*
+ * arch/arm/mach-ixp2000/include/mach/gpio.h
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ *
+ * This program is free software, you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * IXP2000 GPIO in/out, edge/level detection for IRQs:
+ * IRQs are generated on Falling-edge, Rising-Edge, Level-low, Level-High
+ * or both Falling-edge and Rising-edge.
+ * This must be called *before* the corresponding IRQ is registerd.
+ * Use this instead of directly setting the GPIO registers.
+ * GPIOs may also be used as GPIOs (e.g. for emulating i2c/smb)
+ */
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
+
+#ifndef __ASSEMBLY__
+
+#define GPIO_IN				0
+#define GPIO_OUT			1
+
+#define IXP2000_GPIO_LOW		0
+#define IXP2000_GPIO_HIGH		1
+
+extern void gpio_line_config(int line, int direction);
+
+static inline int gpio_line_get(int line)
+{
+	return (((*IXP2000_GPIO_PLR) >> line) & 1);
+}
+
+static inline void gpio_line_set(int line, int value)
+{
+	if (value == IXP2000_GPIO_HIGH) {
+		ixp2000_reg_write(IXP2000_GPIO_POSR, 1 << line);
+	} else if (value == IXP2000_GPIO_LOW) {
+		ixp2000_reg_write(IXP2000_GPIO_POCR, 1 << line);
+	}
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* ASM_ARCH_IXP2000_GPIO_H_ */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp2000/ixdp2400.c linux-libre-3.2-gnu/arch/arm/mach-ixp2000/ixdp2400.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp2000/ixdp2400.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp2000/ixdp2400.c	2012-01-04 18:55:44.000000000 -0500
@@ -171,7 +171,7 @@
 
 MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= ixdp2x00_map_io,
 	.init_irq	= ixdp2400_init_irq,
 	.timer		= &ixdp2400_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp2000/ixdp2800.c linux-libre-3.2-gnu/arch/arm/mach-ixp2000/ixdp2800.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp2000/ixdp2800.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp2000/ixdp2800.c	2012-01-04 18:55:44.000000000 -0500
@@ -286,7 +286,7 @@
 
 MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= ixdp2x00_map_io,
 	.init_irq	= ixdp2800_init_irq,
 	.timer		= &ixdp2800_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp2000/ixdp2x00.c linux-libre-3.2-gnu/arch/arm/mach-ixp2000/ixdp2x00.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp2000/ixdp2x00.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp2000/ixdp2x00.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
  */
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/mm.h>
@@ -40,8 +41,7 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/arch.h>
 
-#include <mach/gpio.h>
-
+#include <mach/gpio-ixp2000.h>
 
 /*************************************************************************
  * IXDP2x00 IRQ Initialization
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp2000/ixdp2x01.c linux-libre-3.2-gnu/arch/arm/mach-ixp2000/ixdp2x01.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp2000/ixdp2x01.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp2000/ixdp2x01.c	2012-01-04 18:55:44.000000000 -0500
@@ -417,7 +417,7 @@
 #ifdef CONFIG_ARCH_IXDP2401
 MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= ixdp2x01_map_io,
 	.init_irq	= ixdp2x01_init_irq,
 	.timer		= &ixdp2x01_timer,
@@ -428,7 +428,7 @@
 #ifdef CONFIG_ARCH_IXDP2801
 MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= ixdp2x01_map_io,
 	.init_irq	= ixdp2x01_init_irq,
 	.timer		= &ixdp2x01_timer,
@@ -441,7 +441,7 @@
  */
 MACHINE_START(IXDP28X5, "Intel IXDP2805/2855 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= ixdp2x01_map_io,
 	.init_irq	= ixdp2x01_init_irq,
 	.timer		= &ixdp2x01_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp2000/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-ixp2000/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-ixp2000/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp2000/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp23xx/espresso.c linux-libre-3.2-gnu/arch/arm/mach-ixp23xx/espresso.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp23xx/espresso.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp23xx/espresso.c	2012-01-04 18:55:44.000000000 -0500
@@ -88,6 +88,6 @@
 	.map_io		= ixp23xx_map_io,
 	.init_irq	= ixp23xx_init_irq,
 	.timer		= &ixp23xx_timer,
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= espresso_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp23xx/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-ixp23xx/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-ixp23xx/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp23xx/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
  */
 #include <mach/ixp23xx.h>
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		ldr	\rp, =IXP23XX_PERIPHERAL_PHYS 	@ physical
 		ldr	\rv, =IXP23XX_PERIPHERAL_VIRT	@ virtual
 #ifdef __ARMEB__
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp23xx/ixdp2351.c linux-libre-3.2-gnu/arch/arm/mach-ixp23xx/ixdp2351.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp23xx/ixdp2351.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp23xx/ixdp2351.c	2012-01-04 18:55:44.000000000 -0500
@@ -331,6 +331,6 @@
 	.map_io		= ixdp2351_map_io,
 	.init_irq	= ixdp2351_init_irq,
 	.timer		= &ixp23xx_timer,
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= ixdp2351_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp23xx/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-ixp23xx/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-ixp23xx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp23xx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp23xx/roadrunner.c linux-libre-3.2-gnu/arch/arm/mach-ixp23xx/roadrunner.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp23xx/roadrunner.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp23xx/roadrunner.c	2012-01-04 18:55:44.000000000 -0500
@@ -175,6 +175,6 @@
 	.map_io		= ixp23xx_map_io,
 	.init_irq	= ixp23xx_init_irq,
 	.timer		= &ixp23xx_timer,
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= roadrunner_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/avila-setup.c linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/avila-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/avila-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/avila-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -167,7 +167,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= avila_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
@@ -185,7 +185,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= avila_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/common.c linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/common.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/io.h>
+#include <linux/export.h>
 
 #include <mach/udc.h>
 #include <mach/hardware.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/common-pci.c linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/common-pci.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/common-pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/common-pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/io.h>
+#include <linux/export.h>
 #include <asm/dma-mapping.h>
 
 #include <asm/cputype.h>
@@ -54,7 +55,7 @@
  * these transactions are atomic or we will end up
  * with corrupt data on the bus or in a driver.
  */
-static DEFINE_SPINLOCK(ixp4xx_pci_lock);
+static DEFINE_RAW_SPINLOCK(ixp4xx_pci_lock);
 
 /*
  * Read from PCI config space
@@ -62,10 +63,10 @@
 static void crp_read(u32 ad_cbe, u32 *data)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+	raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
 	*PCI_CRP_AD_CBE = ad_cbe;
 	*data = *PCI_CRP_RDATA;
-	spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+	raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
 }
 
 /*
@@ -74,10 +75,10 @@
 static void crp_write(u32 ad_cbe, u32 data)
 { 
 	unsigned long flags;
-	spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+	raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
 	*PCI_CRP_AD_CBE = CRP_AD_CBE_WRITE | ad_cbe;
 	*PCI_CRP_WDATA = data;
-	spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+	raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
 }
 
 static inline int check_master_abort(void)
@@ -101,7 +102,7 @@
 	int retval = 0;
 	int i;
 
-	spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+	raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
 
 	*PCI_NP_AD = addr;
 
@@ -118,7 +119,7 @@
 	if(check_master_abort())
 		retval = 1;
 
-	spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+	raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
 	return retval;
 }
 
@@ -127,7 +128,7 @@
 	unsigned long flags;
 	int retval = 0;
 
-	spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+	raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
 
 	*PCI_NP_AD = addr;
 
@@ -140,7 +141,7 @@
 	if(check_master_abort())
 		retval = 1;
 
-	spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+	raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
 	return retval;
 }
 
@@ -149,7 +150,7 @@
 	unsigned long flags;
 	int retval = 0;
 
-	spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+	raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
 
 	*PCI_NP_AD = addr;
 
@@ -162,7 +163,7 @@
 	if(check_master_abort())
 		retval = 1;
 
-	spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+	raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
 	return retval;
 }
 
@@ -397,7 +398,8 @@
 		local_write_config(PCI_BASE_ADDRESS_0, 4, PHYS_OFFSET);
 		local_write_config(PCI_BASE_ADDRESS_1, 4, PHYS_OFFSET + SZ_16M);
 		local_write_config(PCI_BASE_ADDRESS_2, 4, PHYS_OFFSET + SZ_32M);
-		local_write_config(PCI_BASE_ADDRESS_3, 4, PHYS_OFFSET + SZ_48M);
+		local_write_config(PCI_BASE_ADDRESS_3, 4,
+					PHYS_OFFSET + SZ_32M + SZ_16M);
 
 		/*
 		 * Enable CSR window at 64 MiB to allow PCI masters
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/coyote-setup.c linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/coyote-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/coyote-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/coyote-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -112,7 +112,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= coyote_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
@@ -130,7 +130,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= coyote_init,
 MACHINE_END
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/dsmg600-setup.c linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/dsmg600-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/dsmg600-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/dsmg600-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
  * Author: Rod Whitby <rod@whitby.id.au>
  * Maintainers: http://www.nslu2-linux.org/
  */
-
+#include <linux/gpio.h>
 #include <linux/irq.h>
 #include <linux/jiffies.h>
 #include <linux/timer.h>
@@ -31,7 +31,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/time.h>
-#include <asm/gpio.h>
 
 #define DSMG600_SDA_PIN		5
 #define DSMG600_SCL_PIN		4
@@ -279,7 +278,7 @@
 
 MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
 	/* Maintainer: www.nslu2-linux.org */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer          = &dsmg600_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/fsg-setup.c linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/fsg-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/fsg-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/fsg-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
  * Maintainers: http://www.nslu2-linux.org/
  *
  */
-
+#include <linux/gpio.h>
 #include <linux/if_ether.h>
 #include <linux/irq.h>
 #include <linux/serial.h>
@@ -27,7 +27,6 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
-#include <asm/gpio.h>
 
 #define FSG_SDA_PIN		12
 #define FSG_SCL_PIN		13
@@ -273,7 +272,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= fsg_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/gateway7001-setup.c linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/gateway7001-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/gateway7001-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/gateway7001-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -99,7 +99,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= gateway7001_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/goramo_mlr.c linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/goramo_mlr.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/goramo_mlr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/goramo_mlr.c	2012-01-04 18:55:44.000000000 -0500
@@ -499,7 +499,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= gmlr_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/gtwx5715-setup.c linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/gtwx5715-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/gtwx5715-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/gtwx5715-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -167,7 +167,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= gtwx5715_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  * published by the Free Software Foundation.
 */
 
-                .macro  addruart, rp, rv
+                .macro  addruart, rp, rv, tmp
 #ifdef __ARMEB__
                 mov     \rp, #3         @ Uart regs are at off set of 3 if
 					@ byte writes used - Big Endian.
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,8 @@
 #include <linux/kernel.h>
 #include <mach/hardware.h>
 
+#define __ARM_GPIOLIB_COMPLEX
+
 static inline int gpio_request(unsigned gpio, const char *label)
 {
 	return 0;
@@ -70,6 +72,7 @@
 #include <asm-generic/gpio.h>			/* cansleep wrappers */
 
 extern int gpio_to_irq(int gpio);
+#define gpio_to_irq gpio_to_irq
 extern int irq_to_gpio(unsigned int irq);
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/include/mach/io.h linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/include/mach/io.h
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,8 +17,6 @@
 
 #include <mach/hardware.h>
 
-#define IO_SPACE_LIMIT 0x0000ffff
-
 extern int (*ixp4xx_pci_read)(u32 addr, u32 cmd, u32* data);
 extern int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data);
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-/*
- * arch/arm/mach-ixp4xx/include/mach/memory.h
- *
- * Copyright (c) 2001-2004 MontaVista Software, Inc.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#include <asm/sizes.h>
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/include/mach/uncompress.h linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/include/mach/uncompress.h
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/include/mach/uncompress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/include/mach/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -41,7 +41,8 @@
 	 * Some boards are using UART2 as console
 	 */
 	if (machine_is_adi_coyote() || machine_is_gtwx5715() ||
-			 machine_is_gateway7001() || machine_is_wg302v2())
+	    machine_is_gateway7001() || machine_is_wg302v2() ||
+	    machine_is_devixp() || machine_is_miccpt() || machine_is_mic256())
 		uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS;
 	else
 		uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/ixdp425-setup.c linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/ixdp425-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/ixdp425-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/ixdp425-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -256,7 +256,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= ixdp425_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
@@ -270,7 +270,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= ixdp425_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
@@ -284,7 +284,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= ixdp425_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
@@ -298,7 +298,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= ixdp425_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/Kconfig linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -179,6 +179,25 @@
 		"High Speed" UART is n/c (as far as I can tell)
 		20 Pin ARM/Xscale JTAG interface on J2
 
+config MACH_DEVIXP
+	bool "Omicron DEVIXP"
+	help
+	  Say 'Y' here if you want your kernel to support the DEVIXP
+	  board from OMICRON electronics GmbH.
+
+config MACH_MICCPT
+	bool "Omicron MICCPT"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support the MICCPT
+	  board from OMICRON electronics GmbH.
+
+config MACH_MIC256
+	bool "Omicron MIC256"
+	help
+	  Say 'Y' here if you want your kernel to support the MIC256
+	  board from OMICRON electronics GmbH.
+
 comment "IXP4xx Options"
 
 config IXP4XX_INDIRECT_PCI
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/Makefile linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 obj-pci-$(CONFIG_MACH_IXDPG425)		+= ixdpg425-pci.o
 obj-pci-$(CONFIG_ARCH_ADI_COYOTE)	+= coyote-pci.o
 obj-pci-$(CONFIG_MACH_GTWX5715)		+= gtwx5715-pci.o
+obj-pci-$(CONFIG_MACH_MICCPT)		+= miccpt-pci.o
 obj-pci-$(CONFIG_MACH_NSLU2)		+= nslu2-pci.o
 obj-pci-$(CONFIG_MACH_NAS100D)		+= nas100d-pci.o
 obj-pci-$(CONFIG_MACH_DSMG600)		+= dsmg600-pci.o
@@ -25,6 +26,9 @@
 obj-$(CONFIG_MACH_IXDPG425)	+= coyote-setup.o
 obj-$(CONFIG_ARCH_ADI_COYOTE)	+= coyote-setup.o
 obj-$(CONFIG_MACH_GTWX5715)	+= gtwx5715-setup.o
+obj-$(CONFIG_MACH_DEVIXP)	+= omixp-setup.o
+obj-$(CONFIG_MACH_MICCPT)	+= omixp-setup.o
+obj-$(CONFIG_MACH_MIC256)	+= omixp-setup.o
 obj-$(CONFIG_MACH_NSLU2)	+= nslu2-setup.o
 obj-$(CONFIG_MACH_NAS100D)	+= nas100d-setup.o
 obj-$(CONFIG_MACH_DSMG600)      += dsmg600-setup.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/miccpt-pci.c linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/miccpt-pci.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/miccpt-pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/miccpt-pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,78 @@
+/*
+ * arch/arm/mach-ixp4xx/miccpt-pci.c
+ *
+ * MICCPT board-level PCI initialization
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * Copyright (C) 2006 OMICRON electronics GmbH
+ *
+ * Author: Michael Jochum <michael.jochum@omicron.at>
+ *
+ * This program is free software; you can 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/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+
+#define MAX_DEV		4
+#define IRQ_LINES	4
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define INTA		1
+#define INTB		2
+#define INTC		3
+#define INTD		4
+
+
+void __init miccpt_pci_preinit(void)
+{
+	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();
+}
+
+static int __init miccpt_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	static int pci_irq_table[IRQ_LINES] = {
+		IXP4XX_GPIO_IRQ(INTA),
+		IXP4XX_GPIO_IRQ(INTB),
+		IXP4XX_GPIO_IRQ(INTC),
+		IXP4XX_GPIO_IRQ(INTD)
+	};
+
+	if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
+		return pci_irq_table[(slot + pin - 2) % 4];
+
+	return -1;
+}
+
+struct hw_pci miccpt_pci __initdata = {
+	.nr_controllers = 1,
+	.preinit	= miccpt_pci_preinit,
+	.swizzle	= pci_std_swizzle,
+	.setup		= ixp4xx_setup,
+	.scan		= ixp4xx_scan_bus,
+	.map_irq	= miccpt_map_irq,
+};
+
+int __init miccpt_pci_init(void)
+{
+	if (machine_is_miccpt())
+		pci_common_init(&miccpt_pci);
+	return 0;
+}
+
+subsys_initcall(miccpt_pci_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/nas100d-setup.c linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/nas100d-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/nas100d-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/nas100d-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
  * Maintainers: http://www.nslu2-linux.org/
  *
  */
-
+#include <linux/gpio.h>
 #include <linux/if_ether.h>
 #include <linux/irq.h>
 #include <linux/jiffies.h>
@@ -32,7 +32,6 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
-#include <asm/gpio.h>
 
 #define NAS100D_SDA_PIN		5
 #define NAS100D_SCL_PIN		6
@@ -314,7 +313,7 @@
 
 MACHINE_START(NAS100D, "Iomega NAS 100d")
 	/* Maintainer: www.nslu2-linux.org */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer          = &ixp4xx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/nslu2-setup.c linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/nslu2-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/nslu2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/nslu2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
  * Maintainers: http://www.nslu2-linux.org/
  *
  */
-
+#include <linux/gpio.h>
 #include <linux/if_ether.h>
 #include <linux/irq.h>
 #include <linux/serial.h>
@@ -30,7 +30,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/time.h>
-#include <asm/gpio.h>
 
 #define NSLU2_SDA_PIN		7
 #define NSLU2_SCL_PIN		6
@@ -300,7 +299,7 @@
 
 MACHINE_START(NSLU2, "Linksys NSLU2")
 	/* Maintainer: www.nslu2-linux.org */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer          = &nslu2_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/omixp-setup.c linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/omixp-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/omixp-setup.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/omixp-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,273 @@
+/*
+ * arch/arm/mach-ixp4xx/omixp-setup.c
+ *
+ * omicron ixp4xx board setup
+ *      Copyright (C) 2009 OMICRON electronics GmbH
+ *
+ * based nslu2-setup.c, ixdp425-setup.c:
+ *      Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#ifdef CONFIG_LEDS_CLASS
+#include <linux/leds.h>
+#endif
+
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct resource omixp_flash_resources[] = {
+	{
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct mtd_partition omixp_partitions[] = {
+	{
+		.name =		"Recovery Bootloader",
+		.size =		0x00020000,
+		.offset =	0,
+	}, {
+		.name =		"Calibration Data",
+		.size =		0x00020000,
+		.offset =	0x00020000,
+	}, {
+		.name =		"Recovery FPGA",
+		.size =		0x00020000,
+		.offset =	0x00040000,
+	}, {
+		.name =		"Release Bootloader",
+		.size =		0x00020000,
+		.offset =	0x00060000,
+	}, {
+		.name =		"Release FPGA",
+		.size =		0x00020000,
+		.offset =	0x00080000,
+	}, {
+		.name =		"Kernel",
+		.size =		0x00160000,
+		.offset =	0x000a0000,
+	}, {
+		.name =		"Filesystem",
+		.size =		0x00C00000,
+		.offset =	0x00200000,
+	}, {
+		.name =		"Persistent Storage",
+		.size =		0x00200000,
+		.offset =	0x00E00000,
+	},
+};
+
+static struct flash_platform_data omixp_flash_data[] = {
+	{
+		.map_name	= "cfi_probe",
+		.parts		= omixp_partitions,
+		.nr_parts	= ARRAY_SIZE(omixp_partitions),
+	}, {
+		.map_name	= "cfi_probe",
+		.parts		= NULL,
+		.nr_parts	= 0,
+	},
+};
+
+static struct platform_device omixp_flash_device[] = {
+	{
+		.name		= "IXP4XX-Flash",
+		.id		= 0,
+		.dev = {
+			.platform_data = &omixp_flash_data[0],
+		},
+		.resource = &omixp_flash_resources[0],
+		.num_resources = 1,
+	}, {
+		.name		= "IXP4XX-Flash",
+		.id		= 1,
+		.dev = {
+			.platform_data = &omixp_flash_data[1],
+		},
+		.resource = &omixp_flash_resources[1],
+		.num_resources = 1,
+	},
+};
+
+/* Swap UART's - These boards have the console on UART2. The following
+ * configuration is used:
+ *      ttyS0 .. UART2
+ *      ttyS1 .. UART1
+ * This way standard images can be used with the kernel that expect
+ * the console on ttyS0.
+ */
+static struct resource omixp_uart_resources[] = {
+	{
+		.start		= IXP4XX_UART2_BASE_PHYS,
+		.end		= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	}, {
+		.start		= IXP4XX_UART1_BASE_PHYS,
+		.end		= IXP4XX_UART1_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct plat_serial8250_port omixp_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	}, {
+		.mapbase	= IXP4XX_UART1_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART1,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	}, {
+		/* list termination */
+	}
+};
+
+static struct platform_device omixp_uart = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev.platform_data	= omixp_uart_data,
+	.num_resources		= 2,
+	.resource		= omixp_uart_resources,
+};
+
+static struct gpio_led mic256_led_pins[] = {
+	{
+		.name		= "LED-A",
+		.gpio		= 7,
+	},
+};
+
+static struct gpio_led_platform_data mic256_led_data = {
+	.num_leds		= ARRAY_SIZE(mic256_led_pins),
+	.leds			= mic256_led_pins,
+};
+
+static struct platform_device mic256_leds = {
+	.name			= "leds-gpio",
+	.id			= -1,
+	.dev.platform_data	= &mic256_led_data,
+};
+
+/* Built-in 10/100 Ethernet MAC interfaces */
+static struct eth_plat_info ixdp425_plat_eth[] = {
+	{
+		.phy		= 0,
+		.rxq		= 3,
+		.txreadyq	= 20,
+	}, {
+		.phy		= 1,
+		.rxq		= 4,
+		.txreadyq	= 21,
+	},
+};
+
+static struct platform_device ixdp425_eth[] = {
+	{
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEB,
+		.dev.platform_data	= ixdp425_plat_eth,
+	}, {
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEC,
+		.dev.platform_data	= ixdp425_plat_eth + 1,
+	},
+};
+
+
+static struct platform_device *devixp_pldev[] __initdata = {
+	&omixp_uart,
+	&omixp_flash_device[0],
+	&ixdp425_eth[0],
+	&ixdp425_eth[1],
+};
+
+static struct platform_device *mic256_pldev[] __initdata = {
+	&omixp_uart,
+	&omixp_flash_device[0],
+	&mic256_leds,
+	&ixdp425_eth[0],
+	&ixdp425_eth[1],
+};
+
+static struct platform_device *miccpt_pldev[] __initdata = {
+	&omixp_uart,
+	&omixp_flash_device[0],
+	&omixp_flash_device[1],
+	&ixdp425_eth[0],
+	&ixdp425_eth[1],
+};
+
+static void __init omixp_init(void)
+{
+	ixp4xx_sys_init();
+
+	/* 16MiB Boot Flash */
+	omixp_flash_resources[0].start = IXP4XX_EXP_BUS_BASE(0);
+	omixp_flash_resources[0].end   = IXP4XX_EXP_BUS_END(0);
+
+	/* 32 MiB Data Flash */
+	omixp_flash_resources[1].start = IXP4XX_EXP_BUS_BASE(2);
+	omixp_flash_resources[1].end   = IXP4XX_EXP_BUS_END(2);
+
+	if (machine_is_devixp())
+		platform_add_devices(devixp_pldev, ARRAY_SIZE(devixp_pldev));
+	else if (machine_is_miccpt())
+		platform_add_devices(miccpt_pldev, ARRAY_SIZE(miccpt_pldev));
+	else if (machine_is_mic256())
+		platform_add_devices(mic256_pldev, ARRAY_SIZE(mic256_pldev));
+}
+
+#ifdef CONFIG_MACH_DEVIXP
+MACHINE_START(DEVIXP, "Omicron DEVIXP")
+	.atag_offset    = 0x100,
+	.map_io		= ixp4xx_map_io,
+	.init_irq	= ixp4xx_init_irq,
+	.timer          = &ixp4xx_timer,
+	.init_machine	= omixp_init,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MICCPT
+MACHINE_START(MICCPT, "Omicron MICCPT")
+	.atag_offset    = 0x100,
+	.map_io		= ixp4xx_map_io,
+	.init_irq	= ixp4xx_init_irq,
+	.timer          = &ixp4xx_timer,
+	.init_machine	= omixp_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MIC256
+MACHINE_START(MIC256, "Omicron MIC256")
+	.atag_offset    = 0x100,
+	.map_io		= ixp4xx_map_io,
+	.init_irq	= ixp4xx_init_irq,
+	.timer          = &ixp4xx_timer,
+	.init_machine	= omixp_init,
+MACHINE_END
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/vulcan-setup.c linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/vulcan-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/vulcan-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/vulcan-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -239,7 +239,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= vulcan_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/wg302v2-setup.c linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/wg302v2-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-ixp4xx/wg302v2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ixp4xx/wg302v2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -100,7 +100,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
-	.boot_params	= 0x0100,
+	.atag_offset	= 0x100,
 	.init_machine	= wg302v2_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/cpuidle.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/cpuidle.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/cpuidle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/cpuidle.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/cpuidle.h>
 #include <linux/io.h>
+#include <linux/export.h>
 #include <asm/proc-fns.h>
 #include <mach/kirkwood.h>
 
@@ -32,17 +33,18 @@
 
 /* Actual code that puts the SoC in different idle states */
 static int kirkwood_enter_idle(struct cpuidle_device *dev,
-			       struct cpuidle_state *state)
+				struct cpuidle_driver *drv,
+			       int index)
 {
 	struct timeval before, after;
 	int idle_time;
 
 	local_irq_disable();
 	do_gettimeofday(&before);
-	if (state == &dev->states[0])
+	if (index == 0)
 		/* Wait for interrupt state */
 		cpu_do_idle();
-	else if (state == &dev->states[1]) {
+	else if (index == 1) {
 		/*
 		 * Following write will put DDR in self refresh.
 		 * Note that we have 256 cycles before DDR puts it
@@ -57,35 +59,40 @@
 	local_irq_enable();
 	idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
 			(after.tv_usec - before.tv_usec);
-	return idle_time;
+
+	/* Update last residency */
+	dev->last_residency = idle_time;
+
+	return index;
 }
 
 /* Initialize CPU idle by registering the idle states */
 static int kirkwood_init_cpuidle(void)
 {
 	struct cpuidle_device *device;
-
-	cpuidle_register_driver(&kirkwood_idle_driver);
+	struct cpuidle_driver *driver = &kirkwood_idle_driver;
 
 	device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id());
 	device->state_count = KIRKWOOD_MAX_STATES;
+	driver->state_count = KIRKWOOD_MAX_STATES;
 
 	/* Wait for interrupt state */
-	device->states[0].enter = kirkwood_enter_idle;
-	device->states[0].exit_latency = 1;
-	device->states[0].target_residency = 10000;
-	device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
-	strcpy(device->states[0].name, "WFI");
-	strcpy(device->states[0].desc, "Wait for interrupt");
+	driver->states[0].enter = kirkwood_enter_idle;
+	driver->states[0].exit_latency = 1;
+	driver->states[0].target_residency = 10000;
+	driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(driver->states[0].name, "WFI");
+	strcpy(driver->states[0].desc, "Wait for interrupt");
 
 	/* Wait for interrupt and DDR self refresh state */
-	device->states[1].enter = kirkwood_enter_idle;
-	device->states[1].exit_latency = 10;
-	device->states[1].target_residency = 10000;
-	device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
-	strcpy(device->states[1].name, "DDR SR");
-	strcpy(device->states[1].desc, "WFI and DDR Self Refresh");
+	driver->states[1].enter = kirkwood_enter_idle;
+	driver->states[1].exit_latency = 10;
+	driver->states[1].target_residency = 10000;
+	driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(driver->states[1].name, "DDR SR");
+	strcpy(driver->states[1].desc, "WFI and DDR Self Refresh");
 
+	cpuidle_register_driver(&kirkwood_idle_driver);
 	if (cpuidle_register_device(device)) {
 		printk(KERN_ERR "kirkwood_init_cpuidle: Failed registering\n");
 		return -EIO;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/d2net_v2-setup.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/d2net_v2-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/d2net_v2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/d2net_v2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -221,7 +221,7 @@
 }
 
 MACHINE_START(D2NET_V2, "LaCie d2 Network v2")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= d2net_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/db88f6281-bp-setup.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/db88f6281-bp-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/db88f6281-bp-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -97,7 +97,7 @@
 
 MACHINE_START(DB88F6281_BP, "Marvell DB-88F6281-BP Development Board")
 	/* Maintainer: Saeed Bishara <saeed@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= db88f6281_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/dockstar-setup.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/dockstar-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/dockstar-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/dockstar-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -102,7 +102,7 @@
 }
 
 MACHINE_START(DOCKSTAR, "Seagate FreeAgent DockStar")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= dockstar_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/guruplug-setup.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/guruplug-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/guruplug-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/guruplug-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -121,7 +121,7 @@
 
 MACHINE_START(GURUPLUG, "Marvell GuruPlug Reference Board")
 	/* Maintainer: Siddarth Gore <gores@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= guruplug_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-kirkwood/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
 
 #include <mach/bridge-regs.h>
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldr	\rp, =KIRKWOOD_REGS_PHYS_BASE
 	ldr	\rv, =KIRKWOOD_REGS_VIRT_BASE
 	orr	\rp, \rp, #0x00012000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-kirkwood/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/memory.h
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET		UL(0x00000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/irq.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/irq.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,14 +7,13 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <mach/bridge-regs.h>
 #include <plat/irq.h>
-#include <asm/gpio.h>
 #include "common.h"
 
 static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-kirkwood/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/mpp.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/mpp.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/mpp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/mpp.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,12 +7,11 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/mbus.h>
 #include <linux/io.h>
-#include <asm/gpio.h>
 #include <mach/hardware.h>
 #include <plat/mpp.h>
 #include "common.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -163,7 +163,7 @@
 
 MACHINE_START(MV88F6281GTW_GE, "Marvell 88F6281 GTW GE Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= mv88f6281gtw_ge_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/netspace_v2-setup.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/netspace_v2-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/netspace_v2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/netspace_v2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -258,7 +258,7 @@
 
 #ifdef CONFIG_MACH_NETSPACE_V2
 MACHINE_START(NETSPACE_V2, "LaCie Network Space v2")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= netspace_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
@@ -269,7 +269,7 @@
 
 #ifdef CONFIG_MACH_INETSPACE_V2
 MACHINE_START(INETSPACE_V2, "LaCie Internet Space v2")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= netspace_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
@@ -280,7 +280,7 @@
 
 #ifdef CONFIG_MACH_NETSPACE_MAX_V2
 MACHINE_START(NETSPACE_MAX_V2, "LaCie Network Space Max v2")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= netspace_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/netxbig_v2-setup.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/netxbig_v2-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/netxbig_v2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/netxbig_v2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -399,7 +399,7 @@
 
 #ifdef CONFIG_MACH_NET2BIG_V2
 MACHINE_START(NET2BIG_V2, "LaCie 2Big Network v2")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= netxbig_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
@@ -410,7 +410,7 @@
 
 #ifdef CONFIG_MACH_NET5BIG_V2
 MACHINE_START(NET5BIG_V2, "LaCie 5Big Network v2")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= netxbig_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/openrd-setup.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/openrd-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/openrd-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/openrd-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -214,7 +214,7 @@
 #ifdef CONFIG_MACH_OPENRD_BASE
 MACHINE_START(OPENRD_BASE, "Marvell OpenRD Base Board")
 	/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= openrd_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
@@ -226,7 +226,7 @@
 #ifdef CONFIG_MACH_OPENRD_CLIENT
 MACHINE_START(OPENRD_CLIENT, "Marvell OpenRD Client Board")
 	/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= openrd_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
@@ -238,7 +238,7 @@
 #ifdef CONFIG_MACH_OPENRD_ULTIMATE
 MACHINE_START(OPENRD_ULTIMATE, "Marvell OpenRD Ultimate Board")
 	/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= openrd_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -79,7 +79,7 @@
 
 MACHINE_START(RD88F6192_NAS, "Marvell RD-88F6192-NAS Development Board")
 	/* Maintainer: Saeed Bishara <saeed@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= rd88f6192_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/rd88f6281-setup.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/rd88f6281-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/rd88f6281-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/rd88f6281-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -115,7 +115,7 @@
 
 MACHINE_START(RD88F6281, "Marvell RD-88F6281 Reference Board")
 	/* Maintainer: Saeed Bishara <saeed@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= rd88f6281_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/sheevaplug-setup.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/sheevaplug-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/sheevaplug-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/sheevaplug-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -138,7 +138,7 @@
 #ifdef CONFIG_MACH_SHEEVAPLUG
 MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board")
 	/* Maintainer: shadi Ammouri <shadi@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= sheevaplug_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
@@ -149,7 +149,7 @@
 
 #ifdef CONFIG_MACH_ESATA_SHEEVAPLUG
 MACHINE_START(ESATA_SHEEVAPLUG, "Marvell eSATA SheevaPlug Reference Board")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= sheevaplug_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/t5325-setup.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/t5325-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/t5325-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/t5325-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -201,7 +201,7 @@
 
 MACHINE_START(T5325, "HP t5325 Thin Client")
 	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= hp_t5325_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/ts219-setup.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/ts219-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/ts219-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/ts219-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -132,7 +132,7 @@
 
 MACHINE_START(TS219, "QNAP TS-119/TS-219")
 	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= qnap_ts219_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-kirkwood/ts41x-setup.c linux-libre-3.2-gnu/arch/arm/mach-kirkwood/ts41x-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-kirkwood/ts41x-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-kirkwood/ts41x-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -176,7 +176,7 @@
 
 MACHINE_START(TS41X, "QNAP TS-41x")
 	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= qnap_ts41x_init,
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ks8695/board-acs5k.c linux-libre-3.2-gnu/arch/arm/mach-ks8695/board-acs5k.c
--- linux-libre-3.1-gnu/arch/arm/mach-ks8695/board-acs5k.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ks8695/board-acs5k.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  * 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/kernel.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
@@ -34,7 +34,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/devices.h>
-#include <mach/gpio.h>
+#include <mach/gpio-ks8695.h>
 
 #include "generic.h"
 
@@ -223,7 +223,7 @@
 
 MACHINE_START(ACS5K, "Brivo Systems LLC ACS-5000 Master board")
 	/* Maintainer: Simtec Electronics. */
-	.boot_params	= KS8695_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= acs5k_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ks8695/board-dsm320.c linux-libre-3.2-gnu/arch/arm/mach-ks8695/board-dsm320.c
--- linux-libre-3.1-gnu/arch/arm/mach-ks8695/board-dsm320.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ks8695/board-dsm320.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  * 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/kernel.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
@@ -29,7 +29,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/devices.h>
-#include <mach/gpio.h>
+#include <mach/gpio-ks8695.h>
 
 #include "generic.h"
 
@@ -121,7 +121,7 @@
 
 MACHINE_START(DSM320, "D-Link DSM-320 Wireless Media Player")
 	/* Maintainer: Simtec Electronics. */
-	.boot_params	= KS8695_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= dsm320_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ks8695/board-micrel.c linux-libre-3.2-gnu/arch/arm/mach-ks8695/board-micrel.c
--- linux-libre-3.1-gnu/arch/arm/mach-ks8695/board-micrel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ks8695/board-micrel.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
  * 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/kernel.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
@@ -18,7 +18,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/gpio.h>
+#include <mach/gpio-ks8695.h>
 #include <mach/devices.h>
 
 #include "generic.h"
@@ -53,7 +53,7 @@
 
 MACHINE_START(KS8695, "KS8695 Centaur Development Board")
 	/* Maintainer: Micrel Semiconductor Inc. */
-	.boot_params	= KS8695_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= micrel_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ks8695/devices.c linux-libre-3.2-gnu/arch/arm/mach-ks8695/devices.c
--- linux-libre-3.1-gnu/arch/arm/mach-ks8695/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ks8695/devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 
 #include <mach/irqs.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ks8695/gpio.c linux-libre-3.2-gnu/arch/arm/mach-ks8695/gpio.c
--- linux-libre-3.1-gnu/arch/arm/mach-ks8695/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ks8695/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,319 +0,0 @@
-/*
- * arch/arm/mach-ks8695/gpio.c
- *
- * Copyright (C) 2006 Andrew Victor
- * Updated to GPIOLIB, Copyright 2008 Simtec Electronics
- *                     Daniel Silverstone <dsilvers@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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/mach/irq.h>
-
-#include <mach/regs-gpio.h>
-#include <mach/gpio.h>
-
-/*
- * Configure a GPIO line for either GPIO function, or its internal
- * function (Interrupt, Timer, etc).
- */
-static void ks8695_gpio_mode(unsigned int pin, short gpio)
-{
-	unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
-	unsigned long x, flags;
-
-	if (pin > KS8695_GPIO_5)	/* only GPIO 0..5 have internal functions */
-		return;
-
-	local_irq_save(flags);
-
-	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
-	if (gpio)			/* GPIO: set bit to 0 */
-		x &= ~enable[pin];
-	else				/* Internal function: set bit to 1 */
-		x |= enable[pin];
-	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC);
-
-	local_irq_restore(flags);
-}
-
-
-static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 };
-
-/*
- * Configure GPIO pin as external interrupt source.
- */
-int ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
-{
-	unsigned long x, flags;
-
-	if (pin > KS8695_GPIO_3)	/* only GPIO 0..3 can generate IRQ */
-		return -EINVAL;
-
-	local_irq_save(flags);
-
-	/* set pin as input */
-	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
-	x &= ~IOPM(pin);
-	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
-
-	local_irq_restore(flags);
-
-	/* Set IRQ triggering type */
-	irq_set_irq_type(gpio_irq[pin], type);
-
-	/* enable interrupt mode */
-	ks8695_gpio_mode(pin, 0);
-
-	return 0;
-}
-EXPORT_SYMBOL(ks8695_gpio_interrupt);
-
-
-
-/* .... Generic GPIO interface .............................................. */
-
-/*
- * Configure the GPIO line as an input.
- */
-static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin)
-{
-	unsigned long x, flags;
-
-	if (pin > KS8695_GPIO_15)
-		return -EINVAL;
-
-	/* set pin to GPIO mode */
-	ks8695_gpio_mode(pin, 1);
-
-	local_irq_save(flags);
-
-	/* set pin as input */
-	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
-	x &= ~IOPM(pin);
-	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-
-/*
- * Configure the GPIO line as an output, with default state.
- */
-static int ks8695_gpio_direction_output(struct gpio_chip *gc,
-					unsigned int pin, int state)
-{
-	unsigned long x, flags;
-
-	if (pin > KS8695_GPIO_15)
-		return -EINVAL;
-
-	/* set pin to GPIO mode */
-	ks8695_gpio_mode(pin, 1);
-
-	local_irq_save(flags);
-
-	/* set line state */
-	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
-	if (state)
-		x |= IOPD(pin);
-	else
-		x &= ~IOPD(pin);
-	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
-
-	/* set pin as output */
-	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
-	x |= IOPM(pin);
-	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-
-/*
- * Set the state of an output GPIO line.
- */
-static void ks8695_gpio_set_value(struct gpio_chip *gc,
-				  unsigned int pin, int state)
-{
-	unsigned long x, flags;
-
-	if (pin > KS8695_GPIO_15)
-		return;
-
-	local_irq_save(flags);
-
-	/* set output line state */
-	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
-	if (state)
-		x |= IOPD(pin);
-	else
-		x &= ~IOPD(pin);
-	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
-
-	local_irq_restore(flags);
-}
-
-
-/*
- * Read the state of a GPIO line.
- */
-static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin)
-{
-	unsigned long x;
-
-	if (pin > KS8695_GPIO_15)
-		return -EINVAL;
-
-	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
-	return (x & IOPD(pin)) != 0;
-}
-
-
-/*
- * Map GPIO line to IRQ number.
- */
-static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin)
-{
-	if (pin > KS8695_GPIO_3)	/* only GPIO 0..3 can generate IRQ */
-		return -EINVAL;
-
-	return gpio_irq[pin];
-}
-
-/*
- * Map IRQ number to GPIO line.
- */
-int irq_to_gpio(unsigned int irq)
-{
-	if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3))
-		return -EINVAL;
-
-	return (irq - KS8695_IRQ_EXTERN0);
-}
-EXPORT_SYMBOL(irq_to_gpio);
-
-/* GPIOLIB interface */
-
-static struct gpio_chip ks8695_gpio_chip = {
-	.label			= "KS8695",
-	.direction_input	= ks8695_gpio_direction_input,
-	.direction_output	= ks8695_gpio_direction_output,
-	.get			= ks8695_gpio_get_value,
-	.set			= ks8695_gpio_set_value,
-	.to_irq			= ks8695_gpio_to_irq,
-	.base			= 0,
-	.ngpio			= 16,
-	.can_sleep		= 0,
-};
-
-/* Register the GPIOs */
-void ks8695_register_gpios(void)
-{
-	if (gpiochip_add(&ks8695_gpio_chip))
-		printk(KERN_ERR "Unable to register core GPIOs\n");
-}
-
-/* .... Debug interface ..................................................... */
-
-#ifdef CONFIG_DEBUG_FS
-
-static int ks8695_gpio_show(struct seq_file *s, void *unused)
-{
-	unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
-	unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM };
-	unsigned long mode, ctrl, data;
-	int i;
-
-	mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
-	ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
-	data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
-
-	seq_printf(s, "Pin\tI/O\tFunction\tState\n\n");
-
-	for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) {
-		seq_printf(s, "%i:\t", i);
-
-		seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input");
-
-		if (i <= KS8695_GPIO_3) {
-			if (ctrl & enable[i]) {
-				seq_printf(s, "EXT%i ", i);
-
-				switch ((ctrl & intmask[i]) >> (4 * i)) {
-					case IOPC_TM_LOW:
-						seq_printf(s, "(Low)");		break;
-					case IOPC_TM_HIGH:
-						seq_printf(s, "(High)");	break;
-					case IOPC_TM_RISING:
-						seq_printf(s, "(Rising)");	break;
-					case IOPC_TM_FALLING:
-						seq_printf(s, "(Falling)");	break;
-					case IOPC_TM_EDGE:
-						seq_printf(s, "(Edges)");	break;
-				}
-			}
-			else
-				seq_printf(s, "GPIO\t");
-		}
-		else if (i <= KS8695_GPIO_5) {
-			if (ctrl & enable[i])
-				seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4);
-			else
-				seq_printf(s, "GPIO\t");
-		}
-		else
-			seq_printf(s, "GPIO\t");
-
-		seq_printf(s, "\t");
-
-		seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0);
-	}
-	return 0;
-}
-
-static int ks8695_gpio_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ks8695_gpio_show, NULL);
-}
-
-static const struct file_operations ks8695_gpio_operations = {
-	.open		= ks8695_gpio_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int __init ks8695_gpio_debugfs_init(void)
-{
-	/* /sys/kernel/debug/ks8695_gpio */
-	(void) debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, &ks8695_gpio_operations);
-	return 0;
-}
-postcore_initcall(ks8695_gpio_debugfs_init);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ks8695/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-ks8695/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-ks8695/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ks8695/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 #include <mach/hardware.h>
 #include <mach/regs-uart.h>
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 		ldr	\rp, =KS8695_UART_PA		@ physical base address
 		ldr	\rv, =KS8695_UART_VA		@ virtual base address
 	.endm
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ks8695/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-ks8695/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-ks8695/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ks8695/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,47 +11,9 @@
 #ifndef __ASM_ARCH_GPIO_H_
 #define __ASM_ARCH_GPIO_H_
 
-#include <linux/kernel.h>
-
-#define KS8695_GPIO_0		0
-#define KS8695_GPIO_1		1
-#define KS8695_GPIO_2		2
-#define KS8695_GPIO_3		3
-#define KS8695_GPIO_4		4
-#define KS8695_GPIO_5		5
-#define KS8695_GPIO_6		6
-#define KS8695_GPIO_7		7
-#define KS8695_GPIO_8		8
-#define KS8695_GPIO_9		9
-#define KS8695_GPIO_10		10
-#define KS8695_GPIO_11		11
-#define KS8695_GPIO_12		12
-#define KS8695_GPIO_13		13
-#define KS8695_GPIO_14		14
-#define KS8695_GPIO_15		15
-
-/*
- * Configure GPIO pin as external interrupt source.
- */
-extern int ks8695_gpio_interrupt(unsigned int pin, unsigned int type);
-
 /*
  * Map IRQ number to GPIO line.
  */
 extern int irq_to_gpio(unsigned int irq);
 
-#include <asm-generic/gpio.h>
-
-/* If it turns out that we need to optimise GPIO access for the
- * Micrel's GPIOs, then these can be changed to check their argument
- * directly as static inlines. However for now it's probably not
- * worthwhile.
- */
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_to_irq __gpio_to_irq
-
-/* Register the GPIOs */
-extern void ks8695_register_gpios(void);
-
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h linux-libre-3.2-gnu/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h
--- linux-libre-3.1-gnu/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-ks8695/include/mach/gpio-ks8695.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2006 Andrew Victor
+ *
+ * This program is free software; you can 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_KS8659_GPIO_H
+#define __MACH_KS8659_GPIO_H
+
+#include <linux/kernel.h>
+
+#define KS8695_GPIO_0		0
+#define KS8695_GPIO_1		1
+#define KS8695_GPIO_2		2
+#define KS8695_GPIO_3		3
+#define KS8695_GPIO_4		4
+#define KS8695_GPIO_5		5
+#define KS8695_GPIO_6		6
+#define KS8695_GPIO_7		7
+#define KS8695_GPIO_8		8
+#define KS8695_GPIO_9		9
+#define KS8695_GPIO_10		10
+#define KS8695_GPIO_11		11
+#define KS8695_GPIO_12		12
+#define KS8695_GPIO_13		13
+#define KS8695_GPIO_14		14
+#define KS8695_GPIO_15		15
+
+/*
+ * Configure GPIO pin as external interrupt source.
+ */
+extern int ks8695_gpio_interrupt(unsigned int pin, unsigned int type);
+
+/* Register the GPIOs */
+extern void ks8695_register_gpios(void);
+
+#endif /* __MACH_KS8659_GPIO_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ks8695/leds.c linux-libre-3.2-gnu/arch/arm/mach-ks8695/leds.c
--- linux-libre-3.1-gnu/arch/arm/mach-ks8695/leds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ks8695/leds.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,14 +7,14 @@
  * 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/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 
 #include <asm/leds.h>
 #include <mach/devices.h>
-#include <mach/gpio.h>
 
 
 static inline void ks8695_led_on(unsigned int led)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ks8695/Makefile linux-libre-3.2-gnu/arch/arm/mach-ks8695/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-ks8695/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ks8695/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
 # Makefile for KS8695 architecture support
 #
 
-obj-y				:= cpu.o irq.o time.o gpio.o devices.o
+obj-y				:= cpu.o irq.o time.o devices.o
 obj-m				:=
 obj-n				:=
 obj-				:=
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ks8695/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-ks8695/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-ks8695/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ks8695/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -3,6 +3,6 @@
 #   PARAMS_PHYS must be within 4MB of ZRELADDR
 #   INITRD_PHYS must be in RAM
 
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-l7200/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-l7200/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-l7200/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-l7200/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 		.equ	io_virt, IO_BASE
 		.equ	io_phys, IO_START
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x00044000	@ UART1
 @		mov	\rp, #0x00045000	@ UART2
 		add	\rv, \rp, #io_virt	@ virtual address
diff -druN linux-libre-3.1-gnu/arch/arm/mach-lpc32xx/gpiolib.c linux-libre-3.2-gnu/arch/arm/mach-lpc32xx/gpiolib.c
--- linux-libre-3.1-gnu/arch/arm/mach-lpc32xx/gpiolib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-lpc32xx/gpiolib.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,446 +0,0 @@
-/*
- * arch/arm/mach-lpc32xx/gpiolib.c
- *
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT 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/io.h>
-#include <linux/errno.h>
-#include <linux/gpio.h>
-
-#include <mach/hardware.h>
-#include <mach/platform.h>
-#include "common.h"
-
-#define LPC32XX_GPIO_P3_INP_STATE		_GPREG(0x000)
-#define LPC32XX_GPIO_P3_OUTP_SET		_GPREG(0x004)
-#define LPC32XX_GPIO_P3_OUTP_CLR		_GPREG(0x008)
-#define LPC32XX_GPIO_P3_OUTP_STATE		_GPREG(0x00C)
-#define LPC32XX_GPIO_P2_DIR_SET			_GPREG(0x010)
-#define LPC32XX_GPIO_P2_DIR_CLR			_GPREG(0x014)
-#define LPC32XX_GPIO_P2_DIR_STATE		_GPREG(0x018)
-#define LPC32XX_GPIO_P2_INP_STATE		_GPREG(0x01C)
-#define LPC32XX_GPIO_P2_OUTP_SET		_GPREG(0x020)
-#define LPC32XX_GPIO_P2_OUTP_CLR		_GPREG(0x024)
-#define LPC32XX_GPIO_P2_MUX_SET			_GPREG(0x028)
-#define LPC32XX_GPIO_P2_MUX_CLR			_GPREG(0x02C)
-#define LPC32XX_GPIO_P2_MUX_STATE		_GPREG(0x030)
-#define LPC32XX_GPIO_P0_INP_STATE		_GPREG(0x040)
-#define LPC32XX_GPIO_P0_OUTP_SET		_GPREG(0x044)
-#define LPC32XX_GPIO_P0_OUTP_CLR		_GPREG(0x048)
-#define LPC32XX_GPIO_P0_OUTP_STATE		_GPREG(0x04C)
-#define LPC32XX_GPIO_P0_DIR_SET			_GPREG(0x050)
-#define LPC32XX_GPIO_P0_DIR_CLR			_GPREG(0x054)
-#define LPC32XX_GPIO_P0_DIR_STATE		_GPREG(0x058)
-#define LPC32XX_GPIO_P1_INP_STATE		_GPREG(0x060)
-#define LPC32XX_GPIO_P1_OUTP_SET		_GPREG(0x064)
-#define LPC32XX_GPIO_P1_OUTP_CLR		_GPREG(0x068)
-#define LPC32XX_GPIO_P1_OUTP_STATE		_GPREG(0x06C)
-#define LPC32XX_GPIO_P1_DIR_SET			_GPREG(0x070)
-#define LPC32XX_GPIO_P1_DIR_CLR			_GPREG(0x074)
-#define LPC32XX_GPIO_P1_DIR_STATE		_GPREG(0x078)
-
-#define GPIO012_PIN_TO_BIT(x)			(1 << (x))
-#define GPIO3_PIN_TO_BIT(x)			(1 << ((x) + 25))
-#define GPO3_PIN_TO_BIT(x)			(1 << (x))
-#define GPIO012_PIN_IN_SEL(x, y)		(((x) >> (y)) & 1)
-#define GPIO3_PIN_IN_SHIFT(x)			((x) == 5 ? 24 : 10 + (x))
-#define GPIO3_PIN_IN_SEL(x, y)			((x) >> GPIO3_PIN_IN_SHIFT(y))
-#define GPIO3_PIN5_IN_SEL(x)			(((x) >> 24) & 1)
-#define GPI3_PIN_IN_SEL(x, y)			(((x) >> (y)) & 1)
-
-struct gpio_regs {
-	void __iomem *inp_state;
-	void __iomem *outp_set;
-	void __iomem *outp_clr;
-	void __iomem *dir_set;
-	void __iomem *dir_clr;
-};
-
-/*
- * GPIO names
- */
-static const char *gpio_p0_names[LPC32XX_GPIO_P0_MAX] = {
-	"p0.0", "p0.1", "p0.2", "p0.3",
-	"p0.4", "p0.5", "p0.6", "p0.7"
-};
-
-static const char *gpio_p1_names[LPC32XX_GPIO_P1_MAX] = {
-	"p1.0", "p1.1", "p1.2", "p1.3",
-	"p1.4", "p1.5", "p1.6", "p1.7",
-	"p1.8", "p1.9", "p1.10", "p1.11",
-	"p1.12", "p1.13", "p1.14", "p1.15",
-	"p1.16", "p1.17", "p1.18", "p1.19",
-	"p1.20", "p1.21", "p1.22", "p1.23",
-};
-
-static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {
-	"p2.0", "p2.1", "p2.2", "p2.3",
-	"p2.4", "p2.5", "p2.6", "p2.7",
-	"p2.8", "p2.9", "p2.10", "p2.11",
-	"p2.12"
-};
-
-static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {
-	"gpi000", "gpio01", "gpio02", "gpio03",
-	"gpio04", "gpio05"
-};
-
-static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = {
-	"gpi00", "gpi01", "gpi02", "gpi03",
-	"gpi04", "gpi05", "gpi06", "gpi07",
-	"gpi08", "gpi09",  NULL,    NULL,
-	 NULL,    NULL,    NULL,   "gpi15",
-	"gpi16", "gpi17", "gpi18", "gpi19",
-	"gpi20", "gpi21", "gpi22", "gpi23",
-	"gpi24", "gpi25", "gpi26", "gpi27"
-};
-
-static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = {
-	"gpo00", "gpo01", "gpo02", "gpo03",
-	"gpo04", "gpo05", "gpo06", "gpo07",
-	"gpo08", "gpo09", "gpo10", "gpo11",
-	"gpo12", "gpo13", "gpo14", "gpo15",
-	"gpo16", "gpo17", "gpo18", "gpo19",
-	"gpo20", "gpo21", "gpo22", "gpo23"
-};
-
-static struct gpio_regs gpio_grp_regs_p0 = {
-	.inp_state	= LPC32XX_GPIO_P0_INP_STATE,
-	.outp_set	= LPC32XX_GPIO_P0_OUTP_SET,
-	.outp_clr	= LPC32XX_GPIO_P0_OUTP_CLR,
-	.dir_set	= LPC32XX_GPIO_P0_DIR_SET,
-	.dir_clr	= LPC32XX_GPIO_P0_DIR_CLR,
-};
-
-static struct gpio_regs gpio_grp_regs_p1 = {
-	.inp_state	= LPC32XX_GPIO_P1_INP_STATE,
-	.outp_set	= LPC32XX_GPIO_P1_OUTP_SET,
-	.outp_clr	= LPC32XX_GPIO_P1_OUTP_CLR,
-	.dir_set	= LPC32XX_GPIO_P1_DIR_SET,
-	.dir_clr	= LPC32XX_GPIO_P1_DIR_CLR,
-};
-
-static struct gpio_regs gpio_grp_regs_p2 = {
-	.inp_state	= LPC32XX_GPIO_P2_INP_STATE,
-	.outp_set	= LPC32XX_GPIO_P2_OUTP_SET,
-	.outp_clr	= LPC32XX_GPIO_P2_OUTP_CLR,
-	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
-	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
-};
-
-static struct gpio_regs gpio_grp_regs_p3 = {
-	.inp_state	= LPC32XX_GPIO_P3_INP_STATE,
-	.outp_set	= LPC32XX_GPIO_P3_OUTP_SET,
-	.outp_clr	= LPC32XX_GPIO_P3_OUTP_CLR,
-	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
-	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
-};
-
-struct lpc32xx_gpio_chip {
-	struct gpio_chip	chip;
-	struct gpio_regs	*gpio_grp;
-};
-
-static inline struct lpc32xx_gpio_chip *to_lpc32xx_gpio(
-	struct gpio_chip *gpc)
-{
-	return container_of(gpc, struct lpc32xx_gpio_chip, chip);
-}
-
-static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group,
-	unsigned pin, int input)
-{
-	if (input)
-		__raw_writel(GPIO012_PIN_TO_BIT(pin),
-			group->gpio_grp->dir_clr);
-	else
-		__raw_writel(GPIO012_PIN_TO_BIT(pin),
-			group->gpio_grp->dir_set);
-}
-
-static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group,
-	unsigned pin, int input)
-{
-	u32 u = GPIO3_PIN_TO_BIT(pin);
-
-	if (input)
-		__raw_writel(u, group->gpio_grp->dir_clr);
-	else
-		__raw_writel(u, group->gpio_grp->dir_set);
-}
-
-static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group,
-	unsigned pin, int high)
-{
-	if (high)
-		__raw_writel(GPIO012_PIN_TO_BIT(pin),
-			group->gpio_grp->outp_set);
-	else
-		__raw_writel(GPIO012_PIN_TO_BIT(pin),
-			group->gpio_grp->outp_clr);
-}
-
-static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group,
-	unsigned pin, int high)
-{
-	u32 u = GPIO3_PIN_TO_BIT(pin);
-
-	if (high)
-		__raw_writel(u, group->gpio_grp->outp_set);
-	else
-		__raw_writel(u, group->gpio_grp->outp_clr);
-}
-
-static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group,
-	unsigned pin, int high)
-{
-	if (high)
-		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);
-	else
-		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);
-}
-
-static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group,
-	unsigned pin)
-{
-	return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state),
-		pin);
-}
-
-static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
-	unsigned pin)
-{
-	int state = __raw_readl(group->gpio_grp->inp_state);
-
-	/*
-	 * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped
-	 * to bits 10..14, while GPIOP3-5 is mapped to bit 24.
-	 */
-	return GPIO3_PIN_IN_SEL(state, pin);
-}
-
-static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
-	unsigned pin)
-{
-	return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin);
-}
-
-/*
- * GENERIC_GPIO primitives.
- */
-static int lpc32xx_gpio_dir_input_p012(struct gpio_chip *chip,
-	unsigned pin)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	__set_gpio_dir_p012(group, pin, 1);
-
-	return 0;
-}
-
-static int lpc32xx_gpio_dir_input_p3(struct gpio_chip *chip,
-	unsigned pin)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	__set_gpio_dir_p3(group, pin, 1);
-
-	return 0;
-}
-
-static int lpc32xx_gpio_dir_in_always(struct gpio_chip *chip,
-	unsigned pin)
-{
-	return 0;
-}
-
-static int lpc32xx_gpio_get_value_p012(struct gpio_chip *chip, unsigned pin)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	return __get_gpio_state_p012(group, pin);
-}
-
-static int lpc32xx_gpio_get_value_p3(struct gpio_chip *chip, unsigned pin)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	return __get_gpio_state_p3(group, pin);
-}
-
-static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	return __get_gpi_state_p3(group, pin);
-}
-
-static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,
-	int value)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	__set_gpio_dir_p012(group, pin, 0);
-
-	return 0;
-}
-
-static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
-	int value)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	__set_gpio_dir_p3(group, pin, 0);
-
-	return 0;
-}
-
-static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,
-	int value)
-{
-	return 0;
-}
-
-static void lpc32xx_gpio_set_value_p012(struct gpio_chip *chip, unsigned pin,
-	int value)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	__set_gpio_level_p012(group, pin, value);
-}
-
-static void lpc32xx_gpio_set_value_p3(struct gpio_chip *chip, unsigned pin,
-	int value)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	__set_gpio_level_p3(group, pin, value);
-}
-
-static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,
-	int value)
-{
-	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
-
-	__set_gpo_level_p3(group, pin, value);
-}
-
-static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
-{
-	if (pin < chip->ngpio)
-		return 0;
-
-	return -EINVAL;
-}
-
-static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
-	{
-		.chip = {
-			.label			= "gpio_p0",
-			.direction_input	= lpc32xx_gpio_dir_input_p012,
-			.get			= lpc32xx_gpio_get_value_p012,
-			.direction_output	= lpc32xx_gpio_dir_output_p012,
-			.set			= lpc32xx_gpio_set_value_p012,
-			.request		= lpc32xx_gpio_request,
-			.base			= LPC32XX_GPIO_P0_GRP,
-			.ngpio			= LPC32XX_GPIO_P0_MAX,
-			.names			= gpio_p0_names,
-			.can_sleep		= 0,
-		},
-		.gpio_grp = &gpio_grp_regs_p0,
-	},
-	{
-		.chip = {
-			.label			= "gpio_p1",
-			.direction_input	= lpc32xx_gpio_dir_input_p012,
-			.get			= lpc32xx_gpio_get_value_p012,
-			.direction_output	= lpc32xx_gpio_dir_output_p012,
-			.set			= lpc32xx_gpio_set_value_p012,
-			.request		= lpc32xx_gpio_request,
-			.base			= LPC32XX_GPIO_P1_GRP,
-			.ngpio			= LPC32XX_GPIO_P1_MAX,
-			.names			= gpio_p1_names,
-			.can_sleep		= 0,
-		},
-		.gpio_grp = &gpio_grp_regs_p1,
-	},
-	{
-		.chip = {
-			.label			= "gpio_p2",
-			.direction_input	= lpc32xx_gpio_dir_input_p012,
-			.get			= lpc32xx_gpio_get_value_p012,
-			.direction_output	= lpc32xx_gpio_dir_output_p012,
-			.set			= lpc32xx_gpio_set_value_p012,
-			.request		= lpc32xx_gpio_request,
-			.base			= LPC32XX_GPIO_P2_GRP,
-			.ngpio			= LPC32XX_GPIO_P2_MAX,
-			.names			= gpio_p2_names,
-			.can_sleep		= 0,
-		},
-		.gpio_grp = &gpio_grp_regs_p2,
-	},
-	{
-		.chip = {
-			.label			= "gpio_p3",
-			.direction_input	= lpc32xx_gpio_dir_input_p3,
-			.get			= lpc32xx_gpio_get_value_p3,
-			.direction_output	= lpc32xx_gpio_dir_output_p3,
-			.set			= lpc32xx_gpio_set_value_p3,
-			.request		= lpc32xx_gpio_request,
-			.base			= LPC32XX_GPIO_P3_GRP,
-			.ngpio			= LPC32XX_GPIO_P3_MAX,
-			.names			= gpio_p3_names,
-			.can_sleep		= 0,
-		},
-		.gpio_grp = &gpio_grp_regs_p3,
-	},
-	{
-		.chip = {
-			.label			= "gpi_p3",
-			.direction_input	= lpc32xx_gpio_dir_in_always,
-			.get			= lpc32xx_gpi_get_value,
-			.request		= lpc32xx_gpio_request,
-			.base			= LPC32XX_GPI_P3_GRP,
-			.ngpio			= LPC32XX_GPI_P3_MAX,
-			.names			= gpi_p3_names,
-			.can_sleep		= 0,
-		},
-		.gpio_grp = &gpio_grp_regs_p3,
-	},
-	{
-		.chip = {
-			.label			= "gpo_p3",
-			.direction_output	= lpc32xx_gpio_dir_out_always,
-			.set			= lpc32xx_gpo_set_value,
-			.request		= lpc32xx_gpio_request,
-			.base			= LPC32XX_GPO_P3_GRP,
-			.ngpio			= LPC32XX_GPO_P3_MAX,
-			.names			= gpo_p3_names,
-			.can_sleep		= 0,
-		},
-		.gpio_grp = &gpio_grp_regs_p3,
-	},
-};
-
-void __init lpc32xx_gpio_init(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++)
-		gpiochip_add(&lpc32xx_gpiochip[i].chip);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-lpc32xx/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-lpc32xx/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-lpc32xx/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
  * Debug output is hardcoded to standard UART 5
 */
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldreq	\rp, =0x40090000
 	ldrne	\rv, =0xF4090000
 	.endm
diff -druN linux-libre-3.1-gnu/arch/arm/mach-lpc32xx/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-lpc32xx/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-lpc32xx/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-lpc32xx/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,74 +1 @@
-/*
- * arch/arm/mach-lpc32xx/include/mach/gpio.h
- *
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT 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_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-/*
- * Note!
- * Muxed GP pins need to be setup to the GP state in the board level
- * code prior to using this driver.
- * GPI pins : 28xP3 group
- * GPO pins : 24xP3 group
- * GPIO pins: 8xP0 group, 24xP1 group, 13xP2 group, 6xP3 group
- */
-
-#define LPC32XX_GPIO_P0_MAX 8
-#define LPC32XX_GPIO_P1_MAX 24
-#define LPC32XX_GPIO_P2_MAX 13
-#define LPC32XX_GPIO_P3_MAX 6
-#define LPC32XX_GPI_P3_MAX 28
-#define LPC32XX_GPO_P3_MAX 24
-
-#define LPC32XX_GPIO_P0_GRP 0
-#define LPC32XX_GPIO_P1_GRP (LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX)
-#define LPC32XX_GPIO_P2_GRP (LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX)
-#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX)
-#define LPC32XX_GPI_P3_GRP (LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX)
-#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)
-
-/*
- * A specific GPIO can be selected with this macro
- * ie, GPIO_05 can be selected with LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
- * See the LPC32x0 User's guide for GPIO group numbers
- */
-#define LPC32XX_GPIO(x, y) ((x) + (y))
-
-static inline int gpio_get_value(unsigned gpio)
-{
-	return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	__gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned gpio)
-{
-	return __gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(unsigned gpio)
-{
-	return __gpio_to_irq(gpio);
-}
-
-#endif
+/* empty */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h linux-libre-3.2-gnu/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h
--- linux-libre-3.1-gnu/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-lpc32xx/include/mach/gpio-lpc32xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,50 @@
+/*
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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_GPIO_LPC32XX_H
+#define __MACH_GPIO_LPC32XX_H
+
+/*
+ * Note!
+ * Muxed GP pins need to be setup to the GP state in the board level
+ * code prior to using this driver.
+ * GPI pins : 28xP3 group
+ * GPO pins : 24xP3 group
+ * GPIO pins: 8xP0 group, 24xP1 group, 13xP2 group, 6xP3 group
+ */
+
+#define LPC32XX_GPIO_P0_MAX 8
+#define LPC32XX_GPIO_P1_MAX 24
+#define LPC32XX_GPIO_P2_MAX 13
+#define LPC32XX_GPIO_P3_MAX 6
+#define LPC32XX_GPI_P3_MAX 28
+#define LPC32XX_GPO_P3_MAX 24
+
+#define LPC32XX_GPIO_P0_GRP 0
+#define LPC32XX_GPIO_P1_GRP (LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX)
+#define LPC32XX_GPIO_P2_GRP (LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX)
+#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX)
+#define LPC32XX_GPI_P3_GRP (LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX)
+#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)
+
+/*
+ * A specific GPIO can be selected with this macro
+ * ie, GPIO_05 can be selected with LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
+ * See the LPC32x0 User's guide for GPIO group numbers
+ */
+#define LPC32XX_GPIO(x, y) ((x) + (y))
+
+#endif /* __MACH_GPIO_LPC32XX_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-lpc32xx/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-lpc32xx/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-lpc32xx/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-lpc32xx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-/*
- * arch/arm/mach-lpc32xx/include/mach/memory.h
- *
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT 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_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset of bank 0
- */
-#define PLAT_PHYS_OFFSET	UL(0x80000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-lpc32xx/Makefile linux-libre-3.2-gnu/arch/arm/mach-lpc32xx/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-lpc32xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-lpc32xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,6 +3,6 @@
 #
 
 obj-y	:= timer.o irq.o common.o serial.o clock.o
-obj-y	+= gpiolib.o pm.o suspend.o
+obj-y	+= pm.o suspend.o
 obj-y	+= phy3250.o
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-lpc32xx/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-lpc32xx/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-lpc32xx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-lpc32xx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x80008000
+   zreladdr-y	+= 0x80008000
 params_phys-y	:= 0x80000100
 initrd_phys-y	:= 0x82000000
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-lpc32xx/phy3250.c linux-libre-3.2-gnu/arch/arm/mach-lpc32xx/phy3250.c
--- linux-libre-3.1-gnu/arch/arm/mach-lpc32xx/phy3250.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-lpc32xx/phy3250.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
+#include <mach/gpio-lpc32xx.h>
 #include "common.h"
 
 /*
@@ -382,7 +383,7 @@
 
 MACHINE_START(PHY3250, "Phytec 3250 board with the LPC3250 Microcontroller")
 	/* Maintainer: Kevin Wells, NXP Semiconductors */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.map_io		= lpc32xx_map_io,
 	.init_irq	= lpc32xx_init_irq,
 	.timer		= &lpc32xx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/aspenite.c linux-libre-3.2-gnu/arch/arm/mach-mmp/aspenite.c
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/aspenite.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/aspenite.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  publishhed by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
@@ -17,13 +17,13 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
 #include <linux/interrupt.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/addr-map.h>
 #include <mach/mfp-pxa168.h>
 #include <mach/pxa168.h>
-#include <mach/gpio.h>
 #include <video/pxa168fb.h>
 #include <linux/input.h>
 #include <plat/pxa27x_keypad.h>
@@ -160,15 +160,16 @@
 	}, {
 		.name		= "filesystem",
 		.offset		= MTDPART_OFS_APPEND,
-		.size		= SZ_48M,
+		.size		= SZ_32M + SZ_16M,
 		.mask_flags	= 0,
 	}
 };
 
 static struct pxa3xx_nand_platform_data aspenite_nand_info = {
 	.enable_arbiter	= 1,
-	.parts		= aspenite_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(aspenite_nand_partitions),
+	.num_cs = 1,
+	.parts[0]	= aspenite_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(aspenite_nand_partitions),
 };
 
 static struct i2c_board_info aspenite_i2c_info[] __initdata = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/brownstone.c linux-libre-3.2-gnu/arch/arm/mach-mmp/brownstone.c
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/brownstone.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/brownstone.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/gpio.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/max8649.h>
 #include <linux/regulator/fixed.h>
@@ -186,6 +185,15 @@
 		| PXA_FLAG_SD_8_BIT_CAPABLE_SLOT,
 };
 
+static struct sram_platdata mmp2_asram_platdata = {
+	.pool_name	= "asram",
+	.granularity	= SRAM_GRANULARITY,
+};
+
+static struct sram_platdata mmp2_isram_platdata = {
+	.pool_name	= "isram",
+	.granularity	= SRAM_GRANULARITY,
+};
 
 static void __init brownstone_init(void)
 {
@@ -197,6 +205,8 @@
 	mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(brownstone_twsi1_info));
 	mmp2_add_sdhost(0, &mmp2_sdh_platdata_mmc0); /* SD/MMC */
 	mmp2_add_sdhost(2, &mmp2_sdh_platdata_mmc2); /* eMMC */
+	mmp2_add_asram(&mmp2_asram_platdata);
+	mmp2_add_isram(&mmp2_isram_platdata);
 
 	/* enable 5v regulator */
 	platform_device_register(&brownstone_v_5vp_device);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/clock.h linux-libre-3.2-gnu/arch/arm/mach-mmp/clock.h
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@
 
 #define APBC_CLK(_name, _reg, _fnclksel, _rate)			\
 struct clk clk_##_name = {					\
-		.clk_rst	= (void __iomem *)APBC_##_reg,	\
+		.clk_rst	= APBC_##_reg,			\
 		.fnclksel	= _fnclksel,			\
 		.rate		= _rate,			\
 		.ops		= &apbc_clk_ops,		\
@@ -38,7 +38,7 @@
 
 #define APBC_CLK_OPS(_name, _reg, _fnclksel, _rate, _ops)	\
 struct clk clk_##_name = {					\
-		.clk_rst	= (void __iomem *)APBC_##_reg,	\
+		.clk_rst	= APBC_##_reg,			\
 		.fnclksel	= _fnclksel,			\
 		.rate		= _rate,			\
 		.ops		= _ops,				\
@@ -46,7 +46,7 @@
 
 #define APMU_CLK(_name, _reg, _eval, _rate)			\
 struct clk clk_##_name = {					\
-		.clk_rst	= (void __iomem *)APMU_##_reg,	\
+		.clk_rst	= APMU_##_reg,			\
 		.enable_val	= _eval,			\
 		.rate		= _rate,			\
 		.ops		= &apmu_clk_ops,		\
@@ -54,7 +54,7 @@
 
 #define APMU_CLK_OPS(_name, _reg, _eval, _rate, _ops)		\
 struct clk clk_##_name = {					\
-		.clk_rst	= (void __iomem *)APMU_##_reg,	\
+		.clk_rst	= APMU_##_reg,			\
 		.enable_val	= _eval,			\
 		.rate		= _rate,			\
 		.ops		= _ops,				\
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/common.c linux-libre-3.2-gnu/arch/arm/mach-mmp/common.c
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,12 +27,12 @@
 static struct map_desc standard_io_desc[] __initdata = {
 	{
 		.pfn		= __phys_to_pfn(APB_PHYS_BASE),
-		.virtual	= APB_VIRT_BASE,
+		.virtual	= (unsigned long)APB_VIRT_BASE,
 		.length		= APB_PHYS_SIZE,
 		.type		= MT_DEVICE,
 	}, {
 		.pfn		= __phys_to_pfn(AXI_PHYS_BASE),
-		.virtual	= AXI_VIRT_BASE,
+		.virtual	= (unsigned long)AXI_VIRT_BASE,
 		.length		= AXI_PHYS_SIZE,
 		.type		= MT_DEVICE,
 	},
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/gplugd.c linux-libre-3.2-gnu/arch/arm/mach-mmp/gplugd.c
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/gplugd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/gplugd.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,11 +9,11 @@
  */
 
 #include <linux/init.h>
+#include <linux/gpio.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
-#include <mach/gpio.h>
 #include <mach/pxa168.h>
 #include <mach/mfp-pxa168.h>
 
@@ -182,13 +182,13 @@
 
 	/* on-chip devices */
 	pxa168_add_uart(3);
-	pxa168_add_ssp(0);
+	pxa168_add_ssp(1);
 	pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info));
 
 	pxa168_add_eth(&gplugd_eth_platform_data);
 }
 
-MACHINE_START(SHEEVAD, "PXA168-based GuruPlug Display (gplugD) Platform")
+MACHINE_START(GPLUGD, "PXA168-based GuruPlug Display (gplugD) Platform")
 	.map_io		= mmp_map_io,
 	.nr_irqs	= IRQ_BOARD_START,
 	.init_irq       = pxa168_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/include/mach/addr-map.h linux-libre-3.2-gnu/arch/arm/mach-mmp/include/mach/addr-map.h
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/include/mach/addr-map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/include/mach/addr-map.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,12 @@
 #ifndef __ASM_MACH_ADDR_MAP_H
 #define __ASM_MACH_ADDR_MAP_H
 
+#ifndef __ASSEMBLER__
+#define IOMEM(x)	((void __iomem *)(x))
+#else
+#define IOMEM(x)	(x)
+#endif
+
 /* APB - Application Subsystem Peripheral Bus
  *
  * NOTE: the DMA controller registers are actually on the AXI fabric #1
@@ -18,11 +24,11 @@
  * peripherals on APB, let's count it into the ABP mapping area.
  */
 #define APB_PHYS_BASE		0xd4000000
-#define APB_VIRT_BASE		0xfe000000
+#define APB_VIRT_BASE		IOMEM(0xfe000000)
 #define APB_PHYS_SIZE		0x00200000
 
 #define AXI_PHYS_BASE		0xd4200000
-#define AXI_VIRT_BASE		0xfe200000
+#define AXI_VIRT_BASE		IOMEM(0xfe200000)
 #define AXI_PHYS_SIZE		0x00200000
 
 /* Static Memory Controller - Chip Select 0 and 1 */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-mmp/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
 
 #include <mach/addr-map.h>
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		ldr	\rp, =APB_PHYS_BASE		@ physical
 		ldr	\rv, =APB_VIRT_BASE		@ virtual
 		orr	\rp, \rp, #0x00017000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-mmp/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,36 +1,13 @@
 #ifndef __ASM_MACH_GPIO_H
 #define __ASM_MACH_GPIO_H
 
-#include <mach/addr-map.h>
-#include <mach/irqs.h>
 #include <asm-generic/gpio.h>
 
-#define GPIO_REGS_VIRT	(APB_VIRT_BASE + 0x19000)
-
-#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		IRQ_GPIO_NUM
-
-#define gpio_to_bank(gpio)	((gpio) >> 5)
 #define gpio_to_irq(gpio)	(IRQ_GPIO_START + (gpio))
 #define irq_to_gpio(irq)	((irq) - IRQ_GPIO_START)
 
-
 #define __gpio_is_inverted(gpio)	(0)
 #define __gpio_is_occupied(gpio)	(0)
 
-/* NOTE: these macros are defined here to make optimization of
- * gpio_{get,set}_value() to work when 'gpio' is a constant.
- * Usage of these macros otherwise is no longer recommended,
- * use generic GPIO API whenever possible.
- */
-#define GPIO_bit(gpio)	(1 << ((gpio) & 0x1f))
-
-#define GPLR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x00)
-#define GPDR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x0c)
-#define GPSR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x18)
-#define GPCR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x24)
-
 #include <plat/gpio.h>
 #endif /* __ASM_MACH_GPIO_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/include/mach/gpio-pxa.h linux-libre-3.2-gnu/arch/arm/mach-mmp/include/mach/gpio-pxa.h
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/include/mach/gpio-pxa.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/include/mach/gpio-pxa.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,30 @@
+#ifndef __ASM_MACH_GPIO_PXA_H
+#define __ASM_MACH_GPIO_PXA_H
+
+#include <mach/addr-map.h>
+#include <mach/irqs.h>
+
+#define GPIO_REGS_VIRT	(APB_VIRT_BASE + 0x19000)
+
+#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		IRQ_GPIO_NUM
+
+#define gpio_to_bank(gpio)	((gpio) >> 5)
+
+/* NOTE: these macros are defined here to make optimization of
+ * gpio_{get,set}_value() to work when 'gpio' is a constant.
+ * Usage of these macros otherwise is no longer recommended,
+ * use generic GPIO API whenever possible.
+ */
+#define GPIO_bit(gpio)	(1 << ((gpio) & 0x1f))
+
+#define GPLR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x00)
+#define GPDR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x0c)
+#define GPSR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x18)
+#define GPCR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x24)
+
+#include <plat/gpio-pxa.h>
+
+#endif /* __ASM_MACH_GPIO_PXA_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-mmp/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-/*
- * linux/arch/arm/mach-mmp/include/mach/memory.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_MACH_MEMORY_H
-#define __ASM_MACH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#endif /* __ASM_MACH_MEMORY_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/include/mach/mmp2.h linux-libre-3.2-gnu/arch/arm/mach-mmp/include/mach/mmp2.h
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/include/mach/mmp2.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/include/mach/mmp2.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c/pxa-i2c.h>
 #include <mach/devices.h>
+#include <mach/sram.h>
 
 extern struct pxa_device_desc mmp2_device_uart1;
 extern struct pxa_device_desc mmp2_device_uart2;
@@ -28,6 +29,8 @@
 extern struct pxa_device_desc mmp2_device_sdh1;
 extern struct pxa_device_desc mmp2_device_sdh2;
 extern struct pxa_device_desc mmp2_device_sdh3;
+extern struct pxa_device_desc mmp2_device_asram;
+extern struct pxa_device_desc mmp2_device_isram;
 
 static inline int mmp2_add_uart(int id)
 {
@@ -85,5 +88,15 @@
 	return pxa_register_device(d, data, sizeof(*data));
 }
 
+static inline int mmp2_add_asram(struct sram_platdata *data)
+{
+	return pxa_register_device(&mmp2_device_asram, data, sizeof(*data));
+}
+
+static inline int mmp2_add_isram(struct sram_platdata *data)
+{
+	return pxa_register_device(&mmp2_device_isram, data, sizeof(*data));
+}
+
 #endif /* __ASM_MACH_MMP2_H */
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/include/mach/pxa168.h linux-libre-3.2-gnu/arch/arm/mach-mmp/include/mach/pxa168.h
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/include/mach/pxa168.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/include/mach/pxa168.h	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,13 @@
 extern struct pxa_device_desc pxa168_device_keypad;
 extern struct pxa_device_desc pxa168_device_eth;
 
+struct pxa168_usb_pdata {
+	/* If NULL, default phy init routine for PXA168 would be called */
+	int (*phy_init)(void __iomem *usb_phy_reg_base);
+};
+/* pdata can be NULL */
+int __init pxa168_add_usb_host(struct pxa168_usb_pdata *pdata);
+
 static inline int pxa168_add_uart(int id)
 {
 	struct pxa_device_desc *d = NULL;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/include/mach/sram.h linux-libre-3.2-gnu/arch/arm/mach-mmp/include/mach/sram.h
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/include/mach/sram.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/include/mach/sram.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ *  linux/arch/arm/mach-mmp/include/mach/sram.h
+ *
+ *  SRAM Memory Management
+ *
+ *  Copyright (c) 2011 Marvell Semiconductors 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 __ASM_ARCH_SRAM_H
+#define __ASM_ARCH_SRAM_H
+
+#include <linux/genalloc.h>
+
+/* ARBITRARY:  SRAM allocations are multiples of this 2^N size */
+#define SRAM_GRANULARITY	512
+
+enum sram_type {
+	MMP_SRAM_UNDEFINED = 0,
+	MMP_ASRAM,
+	MMP_ISRAM,
+};
+
+struct sram_platdata {
+	char *pool_name;
+	int granularity;
+};
+
+extern struct gen_pool *sram_get_gpool(char *pool_name);
+
+#endif /* __ASM_ARCH_SRAM_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/jasper.c linux-libre-3.2-gnu/arch/arm/mach-mmp/jasper.c
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/jasper.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/jasper.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/gpio.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/max8649.h>
 #include <linux/mfd/max8925.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/Kconfig linux-libre-3.2-gnu/arch/arm/mach-mmp/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -77,7 +77,7 @@
 	  Say 'Y' here if you want to support the Marvell PXA168-based
 	  Teton BGA Development Board.
 
-config MACH_SHEEVAD
+config MACH_GPLUGD
 	bool "Marvell's PXA168 GuruPlug Display (gplugD) Board"
 	select CPU_PXA168
 	help
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/Makefile linux-libre-3.2-gnu/arch/arm/mach-mmp/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
 # SoC support
 obj-$(CONFIG_CPU_PXA168)	+= pxa168.o irq-pxa168.o
 obj-$(CONFIG_CPU_PXA910)	+= pxa910.o irq-pxa168.o
-obj-$(CONFIG_CPU_MMP2)		+= mmp2.o irq-mmp2.o
+obj-$(CONFIG_CPU_MMP2)		+= mmp2.o irq-mmp2.o sram.o
 
 # board support
 obj-$(CONFIG_MACH_ASPENITE)	+= aspenite.o
@@ -19,4 +19,4 @@
 obj-$(CONFIG_MACH_FLINT)	+= flint.o
 obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
 obj-$(CONFIG_MACH_TETON_BGA)	+= teton_bga.o
-obj-$(CONFIG_MACH_SHEEVAD)	+= gplugd.o
+obj-$(CONFIG_MACH_GPLUGD)	+= gplugd.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-mmp/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1 +1 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/mmp2.c linux-libre-3.2-gnu/arch/arm/mach-mmp/mmp2.c
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/mmp2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/mmp2.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@
  * 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>
@@ -25,7 +24,7 @@
 #include <mach/irqs.h>
 #include <mach/dma.h>
 #include <mach/mfp.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
 #include <mach/devices.h>
 #include <mach/mmp2.h>
 
@@ -87,7 +86,8 @@
 
 void mmp2_clear_pmic_int(void)
 {
-	unsigned long mfpr_pmic, data;
+	void __iomem *mfpr_pmic;
+	unsigned long data;
 
 	mfpr_pmic = APB_VIRT_BASE + 0x1e000 + 0x2c4;
 	data = __raw_readl(mfpr_pmic);
@@ -226,4 +226,7 @@
 MMP2_DEVICE(sdh1, "sdhci-pxav3", 1, MMC2, 0xd4280800, 0x120);
 MMP2_DEVICE(sdh2, "sdhci-pxav3", 2, MMC3, 0xd4281000, 0x120);
 MMP2_DEVICE(sdh3, "sdhci-pxav3", 3, MMC4, 0xd4281800, 0x120);
+MMP2_DEVICE(asram, "asram", -1, NONE, 0xe0000000, 0x4000);
+/* 0xd1000000 ~ 0xd101ffff is reserved for secure processor */
+MMP2_DEVICE(isram, "isram", -1, NONE, 0xd1020000, 0x18000);
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/pxa168.c linux-libre-3.2-gnu/arch/arm/mach-mmp/pxa168.c
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/pxa168.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/pxa168.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,6 @@
  * 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>
@@ -21,10 +20,13 @@
 #include <mach/regs-apbc.h>
 #include <mach/regs-apmu.h>
 #include <mach/irqs.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
 #include <mach/dma.h>
 #include <mach/devices.h>
 #include <mach/mfp.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <mach/pxa168.h>
 
 #include "common.h"
 #include "clock.h"
@@ -83,6 +85,7 @@
 static APMU_CLK(nand, NAND, 0x19b, 156000000);
 static APMU_CLK(lcd, LCD, 0x7f, 312000000);
 static APMU_CLK(eth, ETH, 0x09, 0);
+static APMU_CLK(usb, USB, 0x12, 0);
 
 /* device and clock bindings */
 static struct clk_lookup pxa168_clkregs[] = {
@@ -104,6 +107,7 @@
 	INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL),
 	INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL),
 	INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"),
+	INIT_CLKREG(&clk_usb, "pxa168-ehci", "PXA168-USBCLK"),
 };
 
 static int __init pxa168_init(void)
@@ -169,3 +173,44 @@
 PXA168_DEVICE(fb, "pxa168-fb", -1, LCD, 0xd420b000, 0x1c8);
 PXA168_DEVICE(keypad, "pxa27x-keypad", -1, KEYPAD, 0xd4012000, 0x4c);
 PXA168_DEVICE(eth, "pxa168-eth", -1, MFU, 0xc0800000, 0x0fff);
+
+struct resource pxa168_usb_host_resources[] = {
+	/* USB Host conroller register base */
+	[0] = {
+		.start	= 0xd4209000,
+		.end	= 0xd4209000 + 0x200,
+		.flags	= IORESOURCE_MEM,
+		.name	= "pxa168-usb-host",
+	},
+	/* USB PHY register base */
+	[1] = {
+		.start	= 0xd4206000,
+		.end	= 0xd4206000 + 0xff,
+		.flags	= IORESOURCE_MEM,
+		.name	= "pxa168-usb-phy",
+	},
+	[2] = {
+		.start	= IRQ_PXA168_USB2,
+		.end	= IRQ_PXA168_USB2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 pxa168_usb_host_dmamask = DMA_BIT_MASK(32);
+struct platform_device pxa168_device_usb_host = {
+	.name = "pxa168-ehci",
+	.id   = -1,
+	.dev  = {
+		.dma_mask = &pxa168_usb_host_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+
+	.num_resources = ARRAY_SIZE(pxa168_usb_host_resources),
+	.resource      = pxa168_usb_host_resources,
+};
+
+int __init pxa168_add_usb_host(struct pxa168_usb_pdata *pdata)
+{
+	pxa168_device_usb_host.dev.platform_data = pdata;
+	return platform_device_register(&pxa168_device_usb_host);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/pxa910.c linux-libre-3.2-gnu/arch/arm/mach-mmp/pxa910.c
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/pxa910.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/pxa910.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,6 @@
  * 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>
@@ -20,7 +19,7 @@
 #include <mach/regs-apmu.h>
 #include <mach/cputype.h>
 #include <mach/irqs.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
 #include <mach/dma.h>
 #include <mach/mfp.h>
 #include <mach/devices.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/sram.c linux-libre-3.2-gnu/arch/arm/mach-mmp/sram.c
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/sram.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/sram.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,168 @@
+/*
+ *  linux/arch/arm/mach-mmp/sram.c
+ *
+ *  based on mach-davinci/sram.c - DaVinci simple SRAM allocator
+ *
+ *  Copyright (c) 2011 Marvell Semiconductors Inc.
+ *  All Rights Reserved
+ *
+ *  Add for mmp sram support - Leo Yan <leoy@marvell.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/genalloc.h>
+
+#include <mach/sram.h>
+
+struct sram_bank_info {
+	char *pool_name;
+	struct gen_pool *gpool;
+	int granularity;
+
+	phys_addr_t sram_phys;
+	void __iomem *sram_virt;
+	u32 sram_size;
+
+	struct list_head node;
+};
+
+static DEFINE_MUTEX(sram_lock);
+static LIST_HEAD(sram_bank_list);
+
+struct gen_pool *sram_get_gpool(char *pool_name)
+{
+	struct sram_bank_info *info = NULL;
+
+	if (!pool_name)
+		return NULL;
+
+	mutex_lock(&sram_lock);
+
+	list_for_each_entry(info, &sram_bank_list, node)
+		if (!strcmp(pool_name, info->pool_name))
+			break;
+
+	mutex_unlock(&sram_lock);
+
+	if (&info->node == &sram_bank_list)
+		return NULL;
+
+	return info->gpool;
+}
+EXPORT_SYMBOL(sram_get_gpool);
+
+static int __devinit sram_probe(struct platform_device *pdev)
+{
+	struct sram_platdata *pdata = pdev->dev.platform_data;
+	struct sram_bank_info *info;
+	struct resource *res;
+	int ret = 0;
+
+	if (!pdata && !pdata->pool_name)
+		return -ENODEV;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no memory resource defined\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (!resource_size(res))
+		return 0;
+
+	info->sram_phys   = (phys_addr_t)res->start;
+	info->sram_size   = resource_size(res);
+	info->sram_virt   = ioremap(info->sram_phys, info->sram_size);
+	info->pool_name	  = kstrdup(pdata->pool_name, GFP_KERNEL);
+	info->granularity = pdata->granularity;
+
+	info->gpool = gen_pool_create(ilog2(info->granularity), -1);
+	if (!info->gpool) {
+		dev_err(&pdev->dev, "create pool failed\n");
+		ret = -ENOMEM;
+		goto create_pool_err;
+	}
+
+	ret = gen_pool_add_virt(info->gpool, (unsigned long)info->sram_virt,
+				info->sram_phys, info->sram_size, -1);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "add new chunk failed\n");
+		ret = -ENOMEM;
+		goto add_chunk_err;
+	}
+
+	mutex_lock(&sram_lock);
+	list_add(&info->node, &sram_bank_list);
+	mutex_unlock(&sram_lock);
+
+	platform_set_drvdata(pdev, info);
+
+	dev_info(&pdev->dev, "initialized\n");
+	return 0;
+
+add_chunk_err:
+	gen_pool_destroy(info->gpool);
+create_pool_err:
+	iounmap(info->sram_virt);
+	kfree(info->pool_name);
+out:
+	kfree(info);
+	return ret;
+}
+
+static int __devexit sram_remove(struct platform_device *pdev)
+{
+	struct sram_bank_info *info;
+
+	info = platform_get_drvdata(pdev);
+	if (info == NULL)
+		return -ENODEV;
+
+	mutex_lock(&sram_lock);
+	list_del(&info->node);
+	mutex_unlock(&sram_lock);
+
+	gen_pool_destroy(info->gpool);
+	iounmap(info->sram_virt);
+	kfree(info->pool_name);
+	kfree(info);
+	return 0;
+}
+
+static const struct platform_device_id sram_id_table[] = {
+	{ "asram", MMP_ASRAM },
+	{ "isram", MMP_ISRAM },
+	{ }
+};
+
+static struct platform_driver sram_driver = {
+	.probe		= sram_probe,
+	.remove		= sram_remove,
+	.driver		= {
+		.name	= "mmp-sram",
+	},
+	.id_table	= sram_id_table,
+};
+
+static int __init sram_init(void)
+{
+	return platform_driver_register(&sram_driver);
+}
+core_initcall(sram_init);
+
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/tavorevb.c linux-libre-3.2-gnu/arch/arm/mach-mmp/tavorevb.c
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/tavorevb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/tavorevb.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,18 +7,18 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  publishhed by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/smc91x.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/addr-map.h>
 #include <mach/mfp-pxa910.h>
 #include <mach/pxa910.h>
-#include <mach/gpio.h>
 
 #include "common.h"
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mmp/ttc_dkb.c linux-libre-3.2-gnu/arch/arm/mach-mmp/ttc_dkb.c
--- linux-libre-3.1-gnu/arch/arm/mach-mmp/ttc_dkb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mmp/ttc_dkb.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,7 +93,7 @@
 	}, {
 		.name		= "filesystem",
 		.offset		= MTDPART_OFS_APPEND,
-		.size		= SZ_48M,
+		.size		= SZ_32M + SZ_16M,
 		.mask_flags	= 0,
 	}
 };
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/board-halibut.c linux-libre-3.2-gnu/arch/arm/mach-msm/board-halibut.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/board-halibut.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/board-halibut.c	2012-01-04 18:55:44.000000000 -0500
@@ -78,8 +78,8 @@
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
-static void __init halibut_fixup(struct machine_desc *desc, struct tag *tags,
-				 char **cmdline, struct meminfo *mi)
+static void __init halibut_fixup(struct tag *tags, char **cmdline,
+				 struct meminfo *mi)
 {
 	mi->nr_banks=1;
 	mi->bank[0].start = PHYS_OFFSET;
@@ -93,7 +93,7 @@
 }
 
 MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)")
-	.boot_params	= 0x10000100,
+	.atag_offset	= 0x100,
 	.fixup		= halibut_fixup,
 	.map_io		= halibut_map_io,
 	.init_irq	= halibut_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/board-mahimahi.c linux-libre-3.2-gnu/arch/arm/mach-msm/board-mahimahi.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/board-mahimahi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/board-mahimahi.c	2012-01-04 18:55:44.000000000 -0500
@@ -53,8 +53,8 @@
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
-static void __init mahimahi_fixup(struct machine_desc *desc, struct tag *tags,
-				 char **cmdline, struct meminfo *mi)
+static void __init mahimahi_fixup(struct tag *tags, char **cmdline,
+				  struct meminfo *mi)
 {
 	mi->nr_banks = 2;
 	mi->bank[0].start = PHYS_OFFSET;
@@ -74,7 +74,7 @@
 extern struct sys_timer msm_timer;
 
 MACHINE_START(MAHIMAHI, "mahimahi")
-	.boot_params	= 0x20000100,
+	.atag_offset	= 0x100,
 	.fixup		= mahimahi_fixup,
 	.map_io		= mahimahi_map_io,
 	.init_irq	= msm_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/board-msm7x27.c linux-libre-3.2-gnu/arch/arm/mach-msm/board-msm7x27.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/board-msm7x27.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/board-msm7x27.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
  * GNU General Public License for more details.
  *
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -34,7 +34,6 @@
 
 #include <mach/vreg.h>
 #include <mach/mpp.h>
-#include <mach/gpio.h>
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 
@@ -130,7 +129,7 @@
 }
 
 MACHINE_START(MSM7X27_SURF, "QCT MSM7x27 SURF")
-	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= msm7x2x_map_io,
 	.init_irq	= msm7x2x_init_irq,
 	.init_machine	= msm7x2x_init,
@@ -138,7 +137,7 @@
 MACHINE_END
 
 MACHINE_START(MSM7X27_FFA, "QCT MSM7x27 FFA")
-	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= msm7x2x_map_io,
 	.init_irq	= msm7x2x_init_irq,
 	.init_machine	= msm7x2x_init,
@@ -146,7 +145,7 @@
 MACHINE_END
 
 MACHINE_START(MSM7X25_SURF, "QCT MSM7x25 SURF")
-	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= msm7x2x_map_io,
 	.init_irq	= msm7x2x_init_irq,
 	.init_machine	= msm7x2x_init,
@@ -154,7 +153,7 @@
 MACHINE_END
 
 MACHINE_START(MSM7X25_FFA, "QCT MSM7x25 FFA")
-	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= msm7x2x_map_io,
 	.init_irq	= msm7x2x_init_irq,
 	.init_machine	= msm7x2x_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/board-msm7x30.c linux-libre-3.2-gnu/arch/arm/mach-msm/board-msm7x30.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/board-msm7x30.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/board-msm7x30.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
@@ -24,13 +24,13 @@
 #include <linux/smsc911x.h>
 #include <linux/usb/msm_hsusb.h>
 #include <linux/clkdev.h>
+#include <linux/memblock.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/msm_iomap.h>
 #include <mach/dma.h>
@@ -42,6 +42,21 @@
 
 extern struct sys_timer msm_timer;
 
+static void __init msm7x30_fixup(struct tag *tag, char **cmdline,
+		struct meminfo *mi)
+{
+	for (; tag->hdr.size; tag = tag_next(tag))
+		if (tag->hdr.tag == ATAG_MEM && tag->u.mem.start == 0x200000) {
+			tag->u.mem.start = 0;
+			tag->u.mem.size += SZ_2M;
+		}
+}
+
+static void __init msm7x30_reserve(void)
+{
+	memblock_remove(0x0, SZ_2M);
+}
+
 static int hsusb_phy_init_seq[] = {
 	0x30, 0x32,	/* Enable and set Pre-Emphasis Depth to 20% */
 	0x02, 0x36,	/* Disable CDR Auto Reset feature */
@@ -106,7 +121,9 @@
 }
 
 MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
-	.boot_params = PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
+	.fixup = msm7x30_fixup,
+	.reserve = msm7x30_reserve,
 	.map_io = msm7x30_map_io,
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
@@ -114,7 +131,9 @@
 MACHINE_END
 
 MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
-	.boot_params = PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
+	.fixup = msm7x30_fixup,
+	.reserve = msm7x30_reserve,
 	.map_io = msm7x30_map_io,
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
@@ -122,7 +141,9 @@
 MACHINE_END
 
 MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID")
-	.boot_params = PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
+	.fixup = msm7x30_fixup,
+	.reserve = msm7x30_reserve,
 	.map_io = msm7x30_map_io,
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/board-msm8960.c linux-libre-3.2-gnu/arch/arm/mach-msm/board-msm8960.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/board-msm8960.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/board-msm8960.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,16 +20,34 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/clkdev.h>
+#include <linux/memblock.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
+#include <asm/setup.h>
 
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 
 #include "devices.h"
 
+static void __init msm8960_fixup(struct tag *tag, char **cmdline,
+		struct meminfo *mi)
+{
+	for (; tag->hdr.size; tag = tag_next(tag))
+		if (tag->hdr.tag == ATAG_MEM &&
+				tag->u.mem.start == 0x40200000) {
+			tag->u.mem.start = 0x40000000;
+			tag->u.mem.size += SZ_2M;
+		}
+}
+
+static void __init msm8960_reserve(void)
+{
+	memblock_remove(0x40000000, SZ_2M);
+}
+
 static void __init msm8960_map_io(void)
 {
 	msm_map_msm8960_io();
@@ -76,6 +94,8 @@
 }
 
 MACHINE_START(MSM8960_SIM, "QCT MSM8960 SIMULATOR")
+	.fixup = msm8960_fixup,
+	.reserve = msm8960_reserve,
 	.map_io = msm8960_map_io,
 	.init_irq = msm8960_init_irq,
 	.timer = &msm_timer,
@@ -83,6 +103,8 @@
 MACHINE_END
 
 MACHINE_START(MSM8960_RUMI3, "QCT MSM8960 RUMI3")
+	.fixup = msm8960_fixup,
+	.reserve = msm8960_reserve,
 	.map_io = msm8960_map_io,
 	.init_irq = msm8960_init_irq,
 	.timer = &msm_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/board-msm8x60.c linux-libre-3.2-gnu/arch/arm/mach-msm/board-msm8x60.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/board-msm8x60.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/board-msm8x60.c	2012-01-04 18:55:44.000000000 -0500
@@ -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
@@ -8,26 +8,41 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You 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/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/memblock.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
+#include <asm/setup.h>
 
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 
+static void __init msm8x60_fixup(struct tag *tag, char **cmdline,
+		struct meminfo *mi)
+{
+	for (; tag->hdr.size; tag = tag_next(tag))
+		if (tag->hdr.tag == ATAG_MEM &&
+				tag->u.mem.start == 0x40200000) {
+			tag->u.mem.start = 0x40000000;
+			tag->u.mem.size += SZ_2M;
+		}
+}
+
+static void __init msm8x60_reserve(void)
+{
+	memblock_remove(0x40000000, SZ_2M);
+}
 
 static void __init msm8x60_map_io(void)
 {
@@ -36,8 +51,6 @@
 
 static void __init msm8x60_init_irq(void)
 {
-	unsigned int i;
-
 	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
 		 (void *)MSM_QGIC_CPU_BASE);
 
@@ -49,22 +62,50 @@
 	 */
 	if (!machine_is_msm8x60_sim())
 		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 void __init msm8x60_init(void)
 {
 }
 
+#ifdef CONFIG_OF
+static struct of_dev_auxdata msm_auxdata_lookup[] __initdata = {
+	{}
+};
+
+static struct of_device_id msm_dt_gic_match[] __initdata = {
+	{ .compatible = "qcom,msm-8660-qgic", },
+	{}
+};
+
+static void __init msm8x60_dt_init(void)
+{
+	struct device_node *node;
+
+	node = of_find_matching_node_by_address(NULL, msm_dt_gic_match,
+			MSM8X60_QGIC_DIST_PHYS);
+	if (node)
+		irq_domain_add_simple(node, GIC_SPI_START);
+
+	if (of_machine_is_compatible("qcom,msm8660-surf")) {
+		printk(KERN_INFO "Init surf UART registers\n");
+		msm8x60_init_uart12dm();
+	}
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			msm_auxdata_lookup, NULL);
+}
+
+static const char *msm8x60_fluid_match[] __initdata = {
+	"qcom,msm8660-fluid",
+	"qcom,msm8660-surf",
+	NULL
+};
+#endif /* CONFIG_OF */
+
 MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3")
+	.fixup = msm8x60_fixup,
+	.reserve = msm8x60_reserve,
 	.map_io = msm8x60_map_io,
 	.init_irq = msm8x60_init_irq,
 	.init_machine = msm8x60_init,
@@ -72,6 +113,8 @@
 MACHINE_END
 
 MACHINE_START(MSM8X60_SURF, "QCT MSM8X60 SURF")
+	.fixup = msm8x60_fixup,
+	.reserve = msm8x60_reserve,
 	.map_io = msm8x60_map_io,
 	.init_irq = msm8x60_init_irq,
 	.init_machine = msm8x60_init,
@@ -79,6 +122,8 @@
 MACHINE_END
 
 MACHINE_START(MSM8X60_SIM, "QCT MSM8X60 SIMULATOR")
+	.fixup = msm8x60_fixup,
+	.reserve = msm8x60_reserve,
 	.map_io = msm8x60_map_io,
 	.init_irq = msm8x60_init_irq,
 	.init_machine = msm8x60_init,
@@ -86,8 +131,21 @@
 MACHINE_END
 
 MACHINE_START(MSM8X60_FFA, "QCT MSM8X60 FFA")
+	.fixup = msm8x60_fixup,
+	.reserve = msm8x60_reserve,
 	.map_io = msm8x60_map_io,
 	.init_irq = msm8x60_init_irq,
 	.init_machine = msm8x60_init,
 	.timer = &msm_timer,
 MACHINE_END
+
+#ifdef CONFIG_OF
+/* TODO: General device tree support for all MSM. */
+DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
+	.map_io = msm8x60_map_io,
+	.init_irq = msm8x60_init_irq,
+	.init_machine = msm8x60_dt_init,
+	.timer = &msm_timer,
+	.dt_compat = msm8x60_fluid_match,
+MACHINE_END
+#endif /* CONFIG_OF */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/board-qsd8x50.c linux-libre-3.2-gnu/arch/arm/mach-msm/board-qsd8x50.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/board-qsd8x50.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/board-qsd8x50.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
@@ -32,7 +32,6 @@
 #include <mach/board.h>
 #include <mach/irqs.h>
 #include <mach/sirc.h>
-#include <mach/gpio.h>
 #include <mach/vreg.h>
 #include <mach/mmc.h>
 
@@ -193,7 +192,7 @@
 }
 
 MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
-	.boot_params = PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = qsd8x50_map_io,
 	.init_irq = qsd8x50_init_irq,
 	.init_machine = qsd8x50_init,
@@ -201,7 +200,7 @@
 MACHINE_END
 
 MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5")
-	.boot_params = PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = qsd8x50_map_io,
 	.init_irq = qsd8x50_init_irq,
 	.init_machine = qsd8x50_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/board-sapphire.c linux-libre-3.2-gnu/arch/arm/mach-msm/board-sapphire.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/board-sapphire.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/board-sapphire.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
 */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -22,7 +22,6 @@
 
 #include <linux/delay.h>
 
-#include <asm/gpio.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -77,8 +76,8 @@
 	}
 };
 
-static void __init sapphire_fixup(struct machine_desc *desc, struct tag *tags,
-				  char **cmdline, struct meminfo *mi)
+static void __init sapphire_fixup(struct tag *tags, char **cmdline,
+				  struct meminfo *mi)
 {
 	int smi_sz = parse_tag_smi((const struct tag *)tags);
 
@@ -105,7 +104,7 @@
 
 MACHINE_START(SAPPHIRE, "sapphire")
 /* Maintainer: Brian Swetland <swetland@google.com> */
-	.boot_params    = PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset    = 0x100,
 	.fixup          = sapphire_fixup,
 	.map_io         = sapphire_map_io,
 	.init_irq       = sapphire_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/board-trout.c linux-libre-3.2-gnu/arch/arm/mach-msm/board-trout.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/board-trout.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/board-trout.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,8 +48,8 @@
 	msm_init_irq();
 }
 
-static void __init trout_fixup(struct machine_desc *desc, struct tag *tags,
-				char **cmdline, struct meminfo *mi)
+static void __init trout_fixup(struct tag *tags, char **cmdline,
+			       struct meminfo *mi)
 {
 	mi->nr_banks = 1;
 	mi->bank[0].start = PHYS_OFFSET;
@@ -93,7 +93,7 @@
 }
 
 MACHINE_START(TROUT, "HTC Dream")
-	.boot_params	= 0x10000100,
+	.atag_offset	= 0x100,
 	.fixup		= trout_fixup,
 	.map_io		= trout_map_io,
 	.init_irq	= trout_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/board-trout-mmc.c linux-libre-3.2-gnu/arch/arm/mach-msm/board-trout-mmc.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/board-trout-mmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/board-trout-mmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-msm/board-trout-mmc.c
 ** Author: Brian Swetland <swetland@google.com>
 */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -11,7 +11,6 @@
 #include <linux/err.h>
 #include <linux/debugfs.h>
 
-#include <asm/gpio.h>
 #include <asm/io.h>
 
 #include <mach/vreg.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/board-trout-panel.c linux-libre-3.2-gnu/arch/arm/mach-msm/board-trout-panel.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/board-trout-panel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/board-trout-panel.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-msm/board-trout-mddi.c
 ** Author: Brian Swetland <swetland@google.com>
 */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -11,7 +11,6 @@
 #include <linux/err.h>
 
 #include <asm/io.h>
-#include <asm/gpio.h>
 #include <asm/mach-types.h>
 
 #include <mach/msm_fb.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/clock.c linux-libre-3.2-gnu/arch/arm/mach-msm/clock.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/list.h>
 #include <linux/err.h>
 #include <linux/spinlock.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
 #include <linux/mutex.h>
 #include <linux/clk.h>
 #include <linux/string.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/devices-iommu.c linux-libre-3.2-gnu/arch/arm/mach-msm/devices-iommu.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/devices-iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/devices-iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/bootmem.h>
+#include <linux/module.h>
 #include <mach/irqs.h>
 #include <mach/iommu.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/devices-msm7x00.c linux-libre-3.2-gnu/arch/arm/mach-msm/devices-msm7x00.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/devices-msm7x00.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/devices-msm7x00.c	2012-01-04 18:55:44.000000000 -0500
@@ -176,12 +176,6 @@
 		.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"
 	},
@@ -204,12 +198,6 @@
 		.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"
@@ -233,12 +221,6 @@
 		.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"
@@ -262,12 +244,6 @@
 		.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"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/devices-qsd8x50.c linux-libre-3.2-gnu/arch/arm/mach-msm/devices-qsd8x50.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/devices-qsd8x50.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/devices-qsd8x50.c	2012-01-04 18:55:44.000000000 -0500
@@ -140,12 +140,6 @@
 		.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"
 	},
@@ -168,12 +162,6 @@
 		.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"
@@ -197,12 +185,6 @@
 		.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"
@@ -226,12 +208,6 @@
 		.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"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/hotplug.c linux-libre-3.2-gnu/arch/arm/mach-msm/hotplug.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/hotplug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/hotplug.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,7 +37,7 @@
 		    :
 		    : "memory", "cc");
 
-		if (pen_release == cpu) {
+		if (pen_release == cpu_logical_map(cpu)) {
 			/*
 			 * OK, proper wakeup, we're done
 			 */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-msm/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-msm/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
 #include <mach/msm_iomap.h>
 
 #if defined(CONFIG_HAS_MSM_DEBUG_UART_PHYS) && !defined(CONFIG_MSM_DEBUG_UART_NONE)
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldr	\rp, =MSM_DEBUG_UART_PHYS
 	ldr	\rv, =MSM_DEBUG_UART_BASE
 	.endm
@@ -37,7 +37,7 @@
 	beq	1001b
 	.endm
 #else
-	.macro  addruart, rp, rv
+	.macro  addruart, rp, rv, tmp
 	mov	\rv, #0xff000000
 	orr	\rv, \rv, #0x00f00000
 	.endm
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/include/mach/entry-macro-qgic.S linux-libre-3.2-gnu/arch/arm/mach-msm/include/mach/entry-macro-qgic.S
--- linux-libre-3.1-gnu/arch/arm/mach-msm/include/mach/entry-macro-qgic.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/include/mach/entry-macro-qgic.S	2012-01-04 18:55:44.000000000 -0500
@@ -8,81 +8,10 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
 
 	.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:
-	 *
-	 * Migrated the code from ARM MP port to be more consistent
-	 * with interrupt processing , the following still holds true
-	 * however, all interrupts are treated the same regardless of
-	 * if they are local IPI or PPI
-	 *
-	 * Interrupts 0-15 are IPI
-	 * 16-31 are PPI
-	 *   (16-18 are the timers)
-	 * 32-1020 are global
-	 * 1021-1022 are reserved
-	 * 1023 is "spurious" (no interrupt)
-	 *
-	 * 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 (0-1020 inclusive).
-	 *
-	 * Base ARM code assumes that the local (private) peripheral interrupts
-	 * are not valid, we treat them differently, in that the privates are
-	 * handled like normal shared interrupts with the exception that only
-	 * one processor can register the interrupt and the handler must be
-	 * the same for all processors.
-	 */
-
-	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-	ldr  \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 =srcCPU,
-						   9-0 =int # */
-
-	bic     \irqnr, \irqstat, #0x1c00	@mask src
-	cmp     \irqnr, #15
-	ldr		\tmp, =1021
-	cmpcc	\irqnr, \irqnr
-	cmpne	\irqnr, \tmp
-	cmpcs	\irqnr, \irqnr
-
-	.endm
-
-	/* We assume that irqstat (the raw value of the IRQ acknowledge
-	 * register) is preserved from the macro above.
-	 * If there is an IPI, we immediately signal end of interrupt on the
-	 * controller, since this requires the original irqstat value which
-	 * we won't easily be able to recreate later.
-	 */
-	.macro test_for_ipi, irqnr, irqstat, base, tmp
-    bic \irqnr, \irqstat, #0x1c00
-    cmp \irqnr, #16
-    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, #16
-    moveq   \tmp, #1
-    streq   \irqstat, [\base, #GIC_CPU_EOI]
-    cmp \tmp, #0
-	.endm
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-msm/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-msm/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,26 +1 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
- * Author: Mike Lockwood <lockwood@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 __ASM_ARCH_MSM_GPIO_H
-#define __ASM_ARCH_MSM_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value  __gpio_get_value
-#define gpio_set_value  __gpio_set_value
-#define gpio_cansleep   __gpio_cansleep
-#define gpio_to_irq     __gpio_to_irq
-
-#endif /* __ASM_ARCH_MSM_GPIO_H */
+/* empty */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-msm/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-msm/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-/* arch/arm/mach-msm/include/mach/memory.h
- *
- * Copyright (C) 2007 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 __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/* physical offset of RAM */
-#if defined(CONFIG_ARCH_QSD8X50) && defined(CONFIG_MSM_SOC_REV_A)
-#define PLAT_PHYS_OFFSET		UL(0x00000000)
-#elif defined(CONFIG_ARCH_QSD8X50)
-#define PLAT_PHYS_OFFSET		UL(0x20000000)
-#elif defined(CONFIG_ARCH_MSM7X30)
-#define PLAT_PHYS_OFFSET		UL(0x00200000)
-#elif defined(CONFIG_ARCH_MSM8X60)
-#define PLAT_PHYS_OFFSET		UL(0x40200000)
-#elif defined(CONFIG_ARCH_MSM8960)
-#define PLAT_PHYS_OFFSET		UL(0x40200000)
-#else
-#define PLAT_PHYS_OFFSET		UL(0x10000000)
-#endif
-
-#endif
-
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/include/mach/mmc.h linux-libre-3.2-gnu/arch/arm/mach-msm/include/mach/mmc.h
--- linux-libre-3.1-gnu/arch/arm/mach-msm/include/mach/mmc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/include/mach/mmc.h	2012-01-04 18:55:44.000000000 -0500
@@ -8,13 +8,6 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/sdio_func.h>
 
-struct embedded_sdio_data {
-	struct sdio_cis cis;
-	struct sdio_cccr cccr;
-	struct sdio_embedded_func *funcs;
-	int num_funcs;
-};
-
 struct msm_mmc_gpio {
 	unsigned no;
 	const char *name;
@@ -29,9 +22,9 @@
 	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;
+	void (*init_card)(struct mmc_card *card);
 };
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/io.c linux-libre-3.2-gnu/arch/arm/mach-msm/io.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/io.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/export.h>
 
 #include <mach/hardware.h>
 #include <asm/page.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/Makefile linux-libre-3.2-gnu/arch/arm/mach-msm/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-msm/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,8 @@
 obj-$(CONFIG_MSM_SMD) += last_radio_log.o
 obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
 
+CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
+
 obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
 obj-$(CONFIG_SMP) += headsmp.o platsmp.o
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-msm/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-msm/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-  zreladdr-y		:= 0x10008000
+  zreladdr-y		+= 0x10008000
 params_phys-y		:= 0x10000100
 initrd_phys-y		:= 0x10800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/platsmp.c linux-libre-3.2-gnu/arch/arm/mach-msm/platsmp.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/platsmp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -117,7 +117,7 @@
 	 * Note that "pen_release" is the hardware CPU ID, whereas
 	 * "cpu" is Linux's internal ID.
 	 */
-	pen_release = cpu;
+	pen_release = cpu_logical_map(cpu);
 	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
 	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
 
@@ -156,6 +156,12 @@
 {
 	unsigned int i, ncores = get_core_count();
 
+	if (ncores > nr_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
+	}
+
 	for (i = 0; i < ncores; i++)
 		set_cpu_possible(i, true);
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/scm.c linux-libre-3.2-gnu/arch/arm/mach-msm/scm.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/scm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/scm.c	2012-01-04 18:55:44.000000000 -0500
@@ -180,6 +180,9 @@
 			__asmeq("%1", "r0")
 			__asmeq("%2", "r1")
 			__asmeq("%3", "r2")
+#ifdef REQUIRES_SEC
+			".arch_extension sec\n"
+#endif
 			"smc	#0	@ switch to secure world\n"
 			: "=r" (r0)
 			: "r" (r0), "r" (r1), "r" (r2)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-msm/timer.c linux-libre-3.2-gnu/arch/arm/mach-msm/timer.c
--- linux-libre-3.1-gnu/arch/arm/mach-msm/timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-msm/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -71,12 +71,16 @@
 struct msm_clock {
 	struct clock_event_device   clockevent;
 	struct clocksource          clocksource;
-	struct irqaction            irq;
+	unsigned int		    irq;
 	void __iomem                *regbase;
 	uint32_t                    freq;
 	uint32_t                    shift;
 	void __iomem                *global_counter;
 	void __iomem                *local_counter;
+	union {
+		struct clock_event_device		*evt;
+		struct clock_event_device __percpu	**percpu_evt;
+	};		
 };
 
 enum {
@@ -87,13 +91,10 @@
 
 
 static struct msm_clock msm_clocks[];
-static struct clock_event_device *local_clock_event;
 
 static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
 {
-	struct clock_event_device *evt = dev_id;
-	if (smp_processor_id() != 0)
-		evt = local_clock_event;
+	struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
 	if (evt->event_handler == NULL)
 		return IRQ_HANDLED;
 	evt->event_handler(evt);
@@ -171,13 +172,7 @@
 			.mask           = CLOCKSOURCE_MASK(32),
 			.flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 		},
-		.irq = {
-			.name    = "gp_timer",
-			.flags   = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_RISING,
-			.handler = msm_timer_interrupt,
-			.dev_id  = &msm_clocks[0].clockevent,
-			.irq     = INT_GP_TIMER_EXP
-		},
+		.irq = INT_GP_TIMER_EXP,
 		.freq = GPT_HZ,
 	},
 	[MSM_CLOCK_DGT] = {
@@ -196,13 +191,7 @@
 			.mask           = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)),
 			.flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 		},
-		.irq = {
-			.name    = "dg_timer",
-			.flags   = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_RISING,
-			.handler = msm_timer_interrupt,
-			.dev_id  = &msm_clocks[1].clockevent,
-			.irq     = INT_DEBUG_TIMER_EXP
-		},
+		.irq = INT_DEBUG_TIMER_EXP,
 		.freq = DGT_HZ >> MSM_DGT_SHIFT,
 		.shift = MSM_DGT_SHIFT,
 	}
@@ -261,10 +250,30 @@
 			printk(KERN_ERR "msm_timer_init: clocksource_register "
 			       "failed for %s\n", cs->name);
 
-		res = setup_irq(clock->irq.irq, &clock->irq);
+		ce->irq = clock->irq;
+		if (cpu_is_msm8x60() || cpu_is_msm8960()) {
+			clock->percpu_evt = alloc_percpu(struct clock_event_device *);
+			if (!clock->percpu_evt) {
+				pr_err("msm_timer_init: memory allocation "
+				       "failed for %s\n", ce->name);
+				continue;
+			}
+
+			*__this_cpu_ptr(clock->percpu_evt) = ce;
+			res = request_percpu_irq(ce->irq, msm_timer_interrupt,
+						 ce->name, clock->percpu_evt);
+			if (!res)
+				enable_percpu_irq(ce->irq, 0);
+		} else {
+			clock->evt = ce;
+			res = request_irq(ce->irq, msm_timer_interrupt,
+					  IRQF_TIMER | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
+					  ce->name, &clock->evt);
+		}
+
 		if (res)
-			printk(KERN_ERR "msm_timer_init: setup_irq "
-			       "failed for %s\n", cs->name);
+			pr_err("msm_timer_init: request_irq failed for %s\n",
+			       ce->name);
 
 		clockevents_register_device(ce);
 	}
@@ -273,6 +282,7 @@
 #ifdef CONFIG_SMP
 int __cpuinit local_timer_setup(struct clock_event_device *evt)
 {
+	static bool local_timer_inited;
 	struct msm_clock *clock = &msm_clocks[MSM_GLOBAL_TIMER];
 
 	/* Use existing clock_event for cpu 0 */
@@ -281,12 +291,13 @@
 
 	writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
 
-	if (!local_clock_event) {
+	if (!local_timer_inited) {
 		writel(0, clock->regbase  + TIMER_ENABLE);
 		writel(0, clock->regbase + TIMER_CLEAR);
 		writel(~0, clock->regbase + TIMER_MATCH_VAL);
+		local_timer_inited = true;
 	}
-	evt->irq = clock->irq.irq;
+	evt->irq = clock->irq;
 	evt->name = "local_timer";
 	evt->features = CLOCK_EVT_FEAT_ONESHOT;
 	evt->rating = clock->clockevent.rating;
@@ -298,17 +309,17 @@
 		clockevent_delta2ns(0xf0000000 >> clock->shift, evt);
 	evt->min_delta_ns = clockevent_delta2ns(4, evt);
 
-	local_clock_event = evt;
-
-	gic_enable_ppi(clock->irq.irq);
+	*__this_cpu_ptr(clock->percpu_evt) = evt;
+	enable_percpu_irq(evt->irq, 0);
 
 	clockevents_register_device(evt);
 	return 0;
 }
 
-inline int local_timer_ack(void)
+void local_timer_stop(struct clock_event_device *evt)
 {
-	return 1;
+	evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+	disable_percpu_irq(evt->irq);
 }
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c linux-libre-3.2-gnu/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -145,7 +145,7 @@
 
 MACHINE_START(TERASTATION_WXL, "Buffalo Nas WXL")
 	/* Maintainer: Sebastien Requiem <sebastien@requiem.fr> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= wxl_init,
 	.map_io		= mv78xx0_map_io,
 	.init_early	= mv78xx0_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mv78xx0/db78x00-bp-setup.c linux-libre-3.2-gnu/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-mv78xx0/db78x00-bp-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mv78xx0/db78x00-bp-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,7 +93,7 @@
 
 MACHINE_START(DB78X00_BP, "Marvell DB-78x00-BP Development Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= db78x00_init,
 	.map_io		= mv78xx0_map_io,
 	.init_early	= mv78xx0_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mv78xx0/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-mv78xx0/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-mv78xx0/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mv78xx0/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
 
 #include <mach/mv78xx0.h>
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldr	\rp, =MV78XX0_REGS_PHYS_BASE
 	ldr	\rv, =MV78XX0_REGS_VIRT_BASE
 	orr	\rp, \rp, #0x00012000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mv78xx0/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-mv78xx0/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-mv78xx0/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mv78xx0/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-/*
- * arch/arm/mach-mv78xx0/include/mach/memory.h
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET		UL(0x00000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mv78xx0/irq.c linux-libre-3.2-gnu/arch/arm/mach-mv78xx0/irq.c
--- linux-libre-3.1-gnu/arch/arm/mach-mv78xx0/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mv78xx0/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,12 +7,11 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/irq.h>
-#include <asm/gpio.h>
 #include <mach/bridge-regs.h>
 #include <plat/irq.h>
 #include "common.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mv78xx0/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-mv78xx0/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-mv78xx0/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mv78xx0/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mv78xx0/mpp.c linux-libre-3.2-gnu/arch/arm/mach-mv78xx0/mpp.c
--- linux-libre-3.1-gnu/arch/arm/mach-mv78xx0/mpp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mv78xx0/mpp.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,13 +7,12 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/mbus.h>
 #include <linux/io.h>
 #include <plat/mpp.h>
-#include <asm/gpio.h>
 #include <mach/hardware.h>
 #include "common.h"
 #include "mpp.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c linux-libre-3.2-gnu/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -78,7 +78,7 @@
 
 MACHINE_START(RD78X00_MASA, "Marvell RD-78x00-MASA Development Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= rd78x00_masa_init,
 	.map_io		= mv78xx0_map_io,
 	.init_early	= mv78xx0_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/board-cpuimx51.c linux-libre-3.2-gnu/arch/arm/mach-mx5/board-cpuimx51.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/board-cpuimx51.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/board-cpuimx51.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,21 +22,18 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 
 #include <mach/eukrea-baseboards.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-mx51.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"
 
 #define CPUIMX51_USBH1_STP	IMX_GPIO_NR(1, 27)
 #define CPUIMX51_QUARTA_GPIO	IMX_GPIO_NR(3, 28)
@@ -57,7 +54,7 @@
 static struct plat_serial8250_port serial_platform_data[] = {
 	{
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000),
-		.irq = gpio_to_irq(CPUIMX51_QUARTA_GPIO),
+		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTA_GPIO),
 		.irqflags = IRQF_TRIGGER_HIGH,
 		.uartclk = CPUIMX51_QUART_XTAL,
 		.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -65,7 +62,7 @@
 		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
 	}, {
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x800000),
-		.irq = gpio_to_irq(CPUIMX51_QUARTB_GPIO),
+		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTB_GPIO),
 		.irqflags = IRQF_TRIGGER_HIGH,
 		.uartclk = CPUIMX51_QUART_XTAL,
 		.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -73,7 +70,7 @@
 		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
 	}, {
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x1000000),
-		.irq = gpio_to_irq(CPUIMX51_QUARTC_GPIO),
+		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTC_GPIO),
 		.irqflags = IRQF_TRIGGER_HIGH,
 		.uartclk = CPUIMX51_QUART_XTAL,
 		.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -81,7 +78,7 @@
 		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
 	}, {
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x2000000),
-		.irq = gpio_to_irq(CPUIMX51_QUARTD_GPIO),
+		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTD_GPIO),
 		.irqflags = IRQF_TRIGGER_HIGH,
 		.uartclk = CPUIMX51_QUART_XTAL,
 		.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -167,7 +164,7 @@
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -190,7 +187,7 @@
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -206,17 +203,17 @@
 			MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
-static struct mxc_usbh_platform_data dr_utmi_config = {
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
 	.init		= initialize_otg_port,
 	.portsc	= MXC_EHCI_UTMI_16BIT,
 };
 
-static struct fsl_usb2_platform_data usb_pdata = {
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
 };
 
-static struct mxc_usbh_platform_data usbh1_config = {
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
 	.init		= initialize_usbh1_port,
 	.portsc	= MXC_EHCI_MODE_ULPI,
 };
@@ -270,12 +267,12 @@
 				ARRAY_SIZE(eukrea_cpuimx51_i2c_devices));
 
 	if (otg_mode_host)
-		mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+		imx51_add_mxc_ehci_otg(&dr_utmi_config);
 	else {
 		initialize_otg_port(NULL);
-		mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
+		imx51_add_fsl_usb2_udc(&usb_pdata);
 	}
-	mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+	imx51_add_mxc_ehci_hs(1, &usbh1_config);
 
 #ifdef CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD
 	eukrea_mbimx51_baseboard_init();
@@ -293,10 +290,11 @@
 
 MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
 	/* Maintainer: Eric BÃ©nard <eric@eukrea.com> */
-	.boot_params = MX51_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.timer = &mxc_timer,
 	.init_machine = eukrea_cpuimx51_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/board-cpuimx51sd.c linux-libre-3.2-gnu/arch/arm/mach-mx5/board-cpuimx51sd.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/board-cpuimx51sd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/board-cpuimx51sd.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,6 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/i2c-gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/can/platform/mcp251x.h>
@@ -32,14 +31,12 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx51.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 "cpu_op-mx51.h"
 
 #define USBH1_RST		IMX_GPIO_NR(2, 28)
@@ -108,7 +105,7 @@
 
 	/* Touchscreen */
 	/* IRQ */
-	_MX51_PAD_GPIO_NAND__GPIO_NAND | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
+	NEW_PAD_CTRL(MX51_PAD_GPIO_NAND__GPIO_NAND, PAD_CTL_PUS_22K_UP |
 			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
 			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
 };
@@ -129,7 +126,7 @@
 		I2C_BOARD_INFO("tsc2007", 0x49),
 		.type		= "tsc2007",
 		.platform_data	= &tsc2007_info,
-		.irq		= gpio_to_irq(TSC2007_IRQGPIO),
+		.irq		= IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
 	},
 };
 
@@ -149,7 +146,7 @@
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -172,7 +169,7 @@
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -189,17 +186,17 @@
 			MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
-static struct mxc_usbh_platform_data dr_utmi_config = {
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
 	.init		= initialize_otg_port,
 	.portsc	= MXC_EHCI_UTMI_16BIT,
 };
 
-static struct fsl_usb2_platform_data usb_pdata = {
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
 };
 
-static struct mxc_usbh_platform_data usbh1_config = {
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
 	.init		= initialize_usbh1_port,
 	.portsc	= MXC_EHCI_MODE_ULPI,
 };
@@ -245,7 +242,7 @@
 		.mode		= SPI_MODE_0,
 		.chip_select     = 0,
 		.platform_data   = &mcp251x_info,
-		.irq             = gpio_to_irq(CAN_IRQGPIO)
+		.irq             = IMX_GPIO_TO_IRQ(CAN_IRQGPIO)
 	},
 };
 
@@ -303,17 +300,17 @@
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 
 	if (otg_mode_host)
-		mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+		imx51_add_mxc_ehci_otg(&dr_utmi_config);
 	else {
 		initialize_otg_port(NULL);
-		mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
+		imx51_add_fsl_usb2_udc(&usb_pdata);
 	}
 
 	gpio_request(USBH1_RST, "usb_rst");
 	gpio_direction_output(USBH1_RST, 0);
 	msleep(20);
 	gpio_set_value(USBH1_RST, 1);
-	mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+	imx51_add_mxc_ehci_hs(1, &usbh1_config);
 
 #ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD
 	eukrea_mbimxsd51_baseboard_init();
@@ -331,10 +328,11 @@
 
 MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
 	/* Maintainer: Eric BÃ©nard <eric@eukrea.com> */
-	.boot_params = MX51_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.timer = &mxc_timer,
 	.init_machine = eukrea_cpuimx51sd_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx50_rdp.c linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx50_rdp.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx50_rdp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx50_rdp.c	2012-01-04 18:55:44.000000000 -0500
@@ -219,6 +219,7 @@
 	.map_io = mx50_map_io,
 	.init_early = imx50_init_early,
 	.init_irq = mx50_init_irq,
+	.handle_irq = imx50_handle_irq,
 	.timer = &mx50_rdp_timer,
 	.init_machine = mx50_rdp_board_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx51_3ds.c linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx51_3ds.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx51_3ds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx51_3ds.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,7 +25,6 @@
 #include <mach/3ds_debugboard.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 
 #define EXPIO_PARENT_INT	gpio_to_irq(IMX_GPIO_NR(1, 6))
 #define MX51_3DS_ECSPI2_CS	(GPIO_PORTC + 28)
@@ -169,10 +168,11 @@
 
 MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params = MX51_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.timer = &mx51_3ds_timer,
 	.init_machine = mx51_3ds_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx51_babbage.c linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx51_babbage.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx51_babbage.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx51_babbage.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,14 +24,12 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx51.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 "cpu_op-mx51.h"
 
 #define BABBAGE_USB_HUB_RESET	IMX_GPIO_NR(1, 7)
@@ -176,7 +174,7 @@
 	.bitrate = 100000,
 };
 
-static struct imxi2c_platform_data babbage_hsi2c_data = {
+static const struct imxi2c_platform_data babbage_hsi2c_data __initconst = {
 	.bitrate = 400000,
 };
 
@@ -249,7 +247,7 @@
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -272,7 +270,7 @@
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -288,17 +286,17 @@
 			MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
-static struct mxc_usbh_platform_data dr_utmi_config = {
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
 	.init		= initialize_otg_port,
 	.portsc	= MXC_EHCI_UTMI_16BIT,
 };
 
-static struct fsl_usb2_platform_data usb_pdata = {
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
 };
 
-static struct mxc_usbh_platform_data usbh1_config = {
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
 	.init		= initialize_usbh1_port,
 	.portsc	= MXC_EHCI_MODE_ULPI,
 };
@@ -351,22 +349,27 @@
 	.wp_type = ESDHC_WP_GPIO,
 };
 
+void __init imx51_babbage_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
+					 ARRAY_SIZE(mx51babbage_pads));
+}
+
 /*
  * Board specific initialization.
  */
 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 |
-		MUX_PAD_CTRL(PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP);
+	iomux_v3_cfg_t power_key = NEW_PAD_CTRL(MX51_PAD_EIM_A27__GPIO2_21,
+		PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH);
 
 	imx51_soc_init();
 
 #if defined(CONFIG_CPU_FREQ_IMX)
 	get_cpu_op = mx51_get_cpu_op;
 #endif
-	mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
-					ARRAY_SIZE(mx51babbage_pads));
+	imx51_babbage_common_init();
 
 	imx51_add_imx_uart(0, &uart_pdata);
 	imx51_add_imx_uart(1, NULL);
@@ -381,17 +384,17 @@
 
 	imx51_add_imx_i2c(0, &babbage_i2c_data);
 	imx51_add_imx_i2c(1, &babbage_i2c_data);
-	mxc_register_device(&mxc_hsi2c_device, &babbage_hsi2c_data);
+	imx51_add_hsi2c(&babbage_hsi2c_data);
 
 	if (otg_mode_host)
-		mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+		imx51_add_mxc_ehci_otg(&dr_utmi_config);
 	else {
 		initialize_otg_port(NULL);
-		mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
+		imx51_add_fsl_usb2_udc(&usb_pdata);
 	}
 
 	gpio_usbh1_active();
-	mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+	imx51_add_mxc_ehci_hs(1, &usbh1_config);
 	/* setback USBH1_STP to be function */
 	mxc_iomux_v3_setup_pad(usbh1stp);
 	babbage_usbhub_reset();
@@ -416,10 +419,11 @@
 
 MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
 	/* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
-	.boot_params = MX51_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.timer = &mx51_babbage_timer,
 	.init_machine = mx51_babbage_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx51_efikamx.c linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx51_efikamx.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx51_efikamx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx51_efikamx.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,14 +32,12 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx51.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 EFIKAMX_PCBID0		IMX_GPIO_NR(3, 16)
@@ -163,6 +161,11 @@
 	.num_leds = ARRAY_SIZE(mx51_efikamx_leds),
 };
 
+static struct esdhc_platform_data sd_pdata = {
+	.cd_type = ESDHC_CD_CONTROLLER,
+	.wp_type = ESDHC_WP_CONTROLLER,
+};
+
 static struct gpio_keys_button mx51_efikamx_powerkey[] = {
 	{
 		.code = KEY_POWER,
@@ -239,9 +242,11 @@
 
 	/* on < 1.2 boards both SD controllers are used */
 	if (system_rev < 0x12) {
-		imx51_add_sdhci_esdhc_imx(1, NULL);
+		imx51_add_sdhci_esdhc_imx(0, NULL);
+		imx51_add_sdhci_esdhc_imx(1, &sd_pdata);
 		mx51_efikamx_leds[2].default_trigger = "mmc1";
-	}
+	} else
+		imx51_add_sdhci_esdhc_imx(0, &sd_pdata);
 
 	gpio_led_register_device(-1, &mx51_efikamx_leds_data);
 	imx_add_gpio_keys(&mx51_efikamx_powerkey_data);
@@ -280,10 +285,11 @@
 
 MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop")
 	/* Maintainer: Amit Kucheria <amit.kucheria@linaro.org> */
-	.boot_params = MX51_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.timer = &mx51_efikamx_timer,
 	.init_machine = mx51_efikamx_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx51_efikasb.c linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx51_efikasb.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx51_efikasb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx51_efikasb.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,14 +35,12 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx51.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)
@@ -56,6 +54,7 @@
 #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)
+#define MX51_PAD_SD1_CD	IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_ESDHC_PAD_CTRL)
 
 static iomux_v3_cfg_t mx51efikasb_pads[] = {
 	/* USB HOST2 */
@@ -97,6 +96,8 @@
 
 	/* BT */
 	MX51_PAD_EIM_A17__GPIO2_11,
+
+	MX51_PAD_SD1_CD,
 };
 
 static int initialize_usbh2_port(struct platform_device *pdev)
@@ -119,7 +120,7 @@
 	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
-static struct mxc_usbh_platform_data usbh2_config = {
+static struct mxc_usbh_platform_data usbh2_config __initdata = {
 	.init   = initialize_usbh2_port,
 	.portsc = MXC_EHCI_MODE_ULPI,
 };
@@ -129,7 +130,7 @@
 	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);
+		imx51_add_mxc_ehci_hs(2, &usbh2_config);
 }
 
 static const struct gpio_led mx51_efikasb_leds[] __initconst = {
@@ -182,6 +183,18 @@
 	.nbuttons = ARRAY_SIZE(mx51_efikasb_keys),
 };
 
+static struct esdhc_platform_data sd0_pdata = {
+#define EFIKASB_SD1_CD	IMX_GPIO_NR(2, 27)
+	.cd_gpio = EFIKASB_SD1_CD,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_CONTROLLER,
+};
+
+static struct esdhc_platform_data sd1_pdata = {
+	.cd_type = ESDHC_CD_CONTROLLER,
+	.wp_type = ESDHC_WP_CONTROLLER,
+};
+
 static struct regulator *pwgt1, *pwgt2;
 
 static void mx51_efikasb_power_off(void)
@@ -250,7 +263,8 @@
 
 	mx51_efikasb_board_id();
 	mx51_efikasb_usb();
-	imx51_add_sdhci_esdhc_imx(1, NULL);
+	imx51_add_sdhci_esdhc_imx(0, &sd0_pdata);
+	imx51_add_sdhci_esdhc_imx(1, &sd1_pdata);
 
 	gpio_led_register_device(-1, &mx51_efikasb_leds_data);
 	imx_add_gpio_keys(&mx51_efikasb_keys_data);
@@ -266,10 +280,11 @@
 };
 
 MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook")
-	.boot_params = MX51_PHYS_OFFSET + 0x100,
+	.atag_offset = 0x100,
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.init_machine =  efikasb_board_init,
 	.timer = &mx51_efikasb_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx53_ard.c linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx53_ard.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx53_ard.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx53_ard.c	2012-01-04 18:55:44.000000000 -0500
@@ -134,8 +134,8 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
-		.start =  gpio_to_irq(ARD_ETHERNET_INT_B),
-		.end =  gpio_to_irq(ARD_ETHERNET_INT_B),
+		.start =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
+		.end =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -171,9 +171,6 @@
 
 static void __init mx53_ard_io_init(void)
 {
-	mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
-				ARRAY_SIZE(mx53_ard_pads));
-
 	gpio_request(ARD_ETHERNET_INT_B, "eth-int-b");
 	gpio_direction_input(ARD_ETHERNET_INT_B);
 
@@ -216,6 +213,13 @@
 	return 0;
 }
 
+void __init imx53_ard_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
+					 ARRAY_SIZE(mx53_ard_pads));
+	weim_cs_config();
+}
+
 static struct platform_device *devices[] __initdata = {
 	&ard_smsc_lan9220_device,
 };
@@ -225,8 +229,8 @@
 	imx53_soc_init();
 	imx53_add_imx_uart(0, NULL);
 
+	imx53_ard_common_init();
 	mx53_ard_io_init();
-	weim_cs_config();
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 
 	imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
@@ -234,6 +238,7 @@
 	imx53_add_imx_i2c(1, &mx53_ard_i2c2_data);
 	imx53_add_imx_i2c(2, &mx53_ard_i2c3_data);
 	imx_add_gpio_keys(&ard_button_data);
+	imx53_add_ahci_imx();
 }
 
 static void __init mx53_ard_timer_init(void)
@@ -249,6 +254,7 @@
 	.map_io = mx53_map_io,
 	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
+	.handle_irq = imx53_handle_irq,
 	.timer = &mx53_ard_timer,
 	.init_machine = mx53_ard_board_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx53_evk.c linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx53_evk.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx53_evk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx53_evk.c	2012-01-04 18:55:44.000000000 -0500
@@ -106,7 +106,7 @@
 	gpio_set_value(MX53_EVK_FEC_PHY_RST, 1);
 }
 
-static struct fec_platform_data mx53_evk_fec_pdata = {
+static const struct fec_platform_data mx53_evk_fec_pdata __initconst = {
 	.phy = PHY_INTERFACE_MODE_RMII,
 };
 
@@ -131,12 +131,17 @@
 	.num_chipselect = ARRAY_SIZE(mx53_evk_spi_cs),
 };
 
+void __init imx53_evk_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
+					 ARRAY_SIZE(mx53_evk_pads));
+}
+
 static void __init mx53_evk_board_init(void)
 {
 	imx53_soc_init();
+	imx53_evk_common_init();
 
-	mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
-					ARRAY_SIZE(mx53_evk_pads));
 	mx53_evk_init_uart();
 	mx53_evk_fec_reset();
 	imx53_add_fec(&mx53_evk_fec_pdata);
@@ -167,6 +172,7 @@
 	.map_io = mx53_map_io,
 	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
+	.handle_irq = imx53_handle_irq,
 	.timer = &mx53_evk_timer,
 	.init_machine = mx53_evk_board_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx53_loco.c linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx53_loco.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx53_loco.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx53_loco.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
+#include <linux/i2c.h>
 
 #include <mach/common.h>
 #include <mach/hardware.h>
@@ -42,6 +43,7 @@
 #define LOCO_SD3_CD			IMX_GPIO_NR(3, 11)
 #define LOCO_SD3_WP			IMX_GPIO_NR(3, 12)
 #define LOCO_SD1_CD			IMX_GPIO_NR(3, 13)
+#define LOCO_ACCEL_EN			IMX_GPIO_NR(6, 14)
 
 static iomux_v3_cfg_t mx53_loco_pads[] = {
 	/* FEC */
@@ -64,6 +66,10 @@
 	MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD,
 	MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS,
 	MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD,
+	/* I2C1 */
+	MX53_PAD_CSI0_DAT8__I2C1_SDA,
+	MX53_PAD_CSI0_DAT9__I2C1_SCL,
+	MX53_PAD_NANDF_CS1__GPIO6_14,	/* Accelerometer Enable */
 	/* I2C2 */
 	MX53_PAD_KEY_COL3__I2C2_SCL,
 	MX53_PAD_KEY_ROW3__I2C2_SDA,
@@ -236,7 +242,7 @@
 	gpio_set_value(LOCO_FEC_PHY_RST, 1);
 }
 
-static struct fec_platform_data mx53_loco_fec_data = {
+static const struct fec_platform_data mx53_loco_fec_data __initconst = {
 	.phy = PHY_INTERFACE_MODE_RMII,
 };
 
@@ -257,22 +263,42 @@
 	.num_leds	= ARRAY_SIZE(mx53loco_leds),
 };
 
+void __init imx53_qsb_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
+					 ARRAY_SIZE(mx53_loco_pads));
+}
+
+static struct i2c_board_info mx53loco_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("mma8450", 0x1C),
+	},
+};
+
 static void __init mx53_loco_board_init(void)
 {
+	int ret;
 	imx53_soc_init();
+	imx53_qsb_common_init();
 
-	mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
-					ARRAY_SIZE(mx53_loco_pads));
 	imx53_add_imx_uart(0, NULL);
 	mx53_loco_fec_reset();
 	imx53_add_fec(&mx53_loco_fec_data);
 	imx53_add_imx2_wdt(0, NULL);
+
+	ret = gpio_request_one(LOCO_ACCEL_EN, GPIOF_OUT_INIT_HIGH, "accel_en");
+	if (ret)
+		pr_err("Cannot request ACCEL_EN pin: %d\n", ret);
+
+	i2c_register_board_info(0, mx53loco_i2c_devices,
+				ARRAY_SIZE(mx53loco_i2c_devices));
 	imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
 	imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
 	imx53_add_sdhci_esdhc_imx(0, &mx53_loco_sd1_data);
 	imx53_add_sdhci_esdhc_imx(2, &mx53_loco_sd3_data);
 	imx_add_gpio_keys(&loco_button_data);
 	gpio_led_register_device(-1, &mx53loco_leds_data);
+	imx53_add_ahci_imx();
 }
 
 static void __init mx53_loco_timer_init(void)
@@ -288,6 +314,7 @@
 	.map_io = mx53_map_io,
 	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
+	.handle_irq = imx53_handle_irq,
 	.timer = &mx53_loco_timer,
 	.init_machine = mx53_loco_board_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx53_smd.c linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx53_smd.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/board-mx53_smd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/board-mx53_smd.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include "devices-imx53.h"
 
 #define SMD_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
+#define MX53_SMD_SATA_PWR_EN    IMX_GPIO_NR(3, 3)
 
 static iomux_v3_cfg_t mx53_smd_pads[] = {
 	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
@@ -103,7 +104,7 @@
 	gpio_set_value(SMD_FEC_PHY_RST, 1);
 }
 
-static struct fec_platform_data mx53_smd_fec_data = {
+static const struct fec_platform_data mx53_smd_fec_data __initconst = {
 	.phy = PHY_INTERFACE_MODE_RMII,
 };
 
@@ -111,12 +112,30 @@
 	.bitrate = 100000,
 };
 
+static inline void mx53_smd_ahci_pwr_on(void)
+{
+	int ret;
+
+	/* Enable SATA PWR */
+	ret = gpio_request_one(MX53_SMD_SATA_PWR_EN,
+			GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "ahci-sata-pwr");
+	if (ret) {
+		pr_err("failed to enable SATA_PWR_EN: %d\n", ret);
+		return;
+	}
+}
+
+void __init imx53_smd_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
+					 ARRAY_SIZE(mx53_smd_pads));
+}
+
 static void __init mx53_smd_board_init(void)
 {
 	imx53_soc_init();
+	imx53_smd_common_init();
 
-	mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
-					ARRAY_SIZE(mx53_smd_pads));
 	mx53_smd_init_uart();
 	mx53_smd_fec_reset();
 	imx53_add_fec(&mx53_smd_fec_data);
@@ -125,6 +144,8 @@
 	imx53_add_sdhci_esdhc_imx(0, NULL);
 	imx53_add_sdhci_esdhc_imx(1, NULL);
 	imx53_add_sdhci_esdhc_imx(2, NULL);
+	mx53_smd_ahci_pwr_on();
+	imx53_add_ahci_imx();
 }
 
 static void __init mx53_smd_timer_init(void)
@@ -140,6 +161,7 @@
 	.map_io = mx53_map_io,
 	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
+	.handle_irq = imx53_handle_irq,
 	.timer = &mx53_smd_timer,
 	.init_machine = mx53_smd_board_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/clock-mx51-mx53.c linux-libre-3.2-gnu/arch/arm/mach-mx5/clock-mx51-mx53.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/clock-mx51-mx53.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/clock-mx51-mx53.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/clkdev.h>
+#include <linux/of.h>
 
 #include <asm/div64.h>
 
@@ -1280,9 +1281,9 @@
 	NULL,  NULL, &ipg_clk, &gpt_ipg_clk);
 
 DEFINE_CLOCK(pwm1_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG6_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
+	NULL, NULL, &ipg_perclk, NULL);
 DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
+	NULL, NULL, &ipg_perclk, NULL);
 
 /* I2C */
 DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
@@ -1401,6 +1402,22 @@
 	.secondary = &esdhc4_ipg_clk,
 };
 
+static struct clk sata_clk = {
+	.parent = &ipg_clk,
+	.enable = _clk_max_enable,
+	.enable_reg = MXC_CCM_CCGR4,
+	.enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+	.disable = _clk_max_disable,
+};
+
+static struct clk ahci_phy_clk = {
+	.parent = &usb_phy1_clk,
+};
+
+static struct clk ahci_dma_clk = {
+	.parent = &ahb_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);
@@ -1418,6 +1435,10 @@
 DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
 		NULL, NULL, &pll3_sw_clk, NULL);
 
+/* PATA */
+DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG0_OFFSET,
+		NULL, NULL, &ipg_clk, &spba_clk);
+
 #define _REGISTER_CLOCK(d, n, c) \
        { \
 		.dev_id = d, \
@@ -1474,6 +1495,7 @@
 	_REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
 	_REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
 	_REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
 };
 
 static struct clk_lookup mx53_lookups[] = {
@@ -1507,6 +1529,10 @@
 	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
 	_REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
 	_REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
+	_REGISTER_CLOCK("imx53-ahci.0", "ahci", sata_clk)
+	_REGISTER_CLOCK("imx53-ahci.0", "ahci_phy", ahci_phy_clk)
+	_REGISTER_CLOCK("imx53-ahci.0", "ahci_dma", ahci_dma_clk)
 };
 
 static void clk_tree_init(void)
@@ -1548,9 +1574,8 @@
 	clk_enable(&main_bus_clk);
 
 	clk_enable(&iim_clk);
-	mx51_revision();
+	imx_print_silicon_rev("i.MX51", mx51_revision());
 	clk_disable(&iim_clk);
-	mx51_display_revision();
 
 	/* move usb_phy_clk to 24MHz */
 	clk_set_parent(&usb_phy1_clk, &osc_clk);
@@ -1568,7 +1593,7 @@
 
 	/* System timer */
 	mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
-		MX51_MXC_INT_GPT);
+		MX51_INT_GPT);
 	return 0;
 }
 
@@ -1592,9 +1617,8 @@
 	clk_enable(&main_bus_clk);
 
 	clk_enable(&iim_clk);
-	mx53_revision();
+	imx_print_silicon_rev("i.MX53", mx53_revision());
 	clk_disable(&iim_clk);
-	mx53_display_revision();
 
 	/* Set SDHC parents to be PLL2 */
 	clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
@@ -1609,3 +1633,43 @@
 		MX53_INT_GPT);
 	return 0;
 }
+
+#ifdef CONFIG_OF
+static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc,
+				   unsigned long *ckih1, unsigned long *ckih2)
+{
+	struct device_node *np;
+
+	/* retrieve the freqency of fixed clocks from device tree */
+	for_each_compatible_node(np, NULL, "fixed-clock") {
+		u32 rate;
+		if (of_property_read_u32(np, "clock-frequency", &rate))
+			continue;
+
+		if (of_device_is_compatible(np, "fsl,imx-ckil"))
+			*ckil = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-osc"))
+			*osc = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
+			*ckih1 = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-ckih2"))
+			*ckih2 = rate;
+	}
+}
+
+int __init mx51_clocks_init_dt(void)
+{
+	unsigned long ckil, osc, ckih1, ckih2;
+
+	clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
+	return mx51_clocks_init(ckil, osc, ckih1, ckih2);
+}
+
+int __init mx53_clocks_init_dt(void)
+{
+	unsigned long ckil, osc, ckih1, ckih2;
+
+	clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
+	return mx53_clocks_init(ckil, osc, ckih1, ckih2);
+}
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/cpu.c linux-libre-3.2-gnu/arch/arm/mach-mx5/cpu.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,9 +16,9 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <mach/hardware.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
-static int cpu_silicon_rev = -1;
+static int mx5_cpu_rev = -1;
 
 #define IIM_SREV 0x24
 #define MX50_HW_ADADIG_DIGPROG	0xB0
@@ -28,11 +28,14 @@
 	void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
 	u32 rev = readl(iim_base + IIM_SREV) & 0xff;
 
-	if (rev == 0x0)
+	switch (rev) {
+	case 0x0:
 		return IMX_CHIP_REVISION_2_0;
-	else if (rev == 0x10)
+	case 0x10:
 		return IMX_CHIP_REVISION_3_0;
-	return 0;
+	default:
+		return IMX_CHIP_REVISION_UNKNOWN;
+	}
 }
 
 /*
@@ -45,33 +48,13 @@
 	if (!cpu_is_mx51())
 		return -EINVAL;
 
-	if (cpu_silicon_rev == -1)
-		cpu_silicon_rev = get_mx51_srev();
+	if (mx5_cpu_rev == -1)
+		mx5_cpu_rev = get_mx51_srev();
 
-	return cpu_silicon_rev;
+	return mx5_cpu_rev;
 }
 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
 
 /*
@@ -84,7 +67,8 @@
 	if (!cpu_is_mx51())
 		return 0;
 
-	if (mx51_revision() < IMX_CHIP_REVISION_3_0 && (elf_hwcap & HWCAP_NEON)) {
+	if (mx51_revision() < IMX_CHIP_REVISION_3_0 &&
+			(elf_hwcap & HWCAP_NEON)) {
 		elf_hwcap &= ~HWCAP_NEON;
 		pr_info("Turning off NEON support, detected broken NEON implementation\n");
 	}
@@ -121,10 +105,10 @@
 	if (!cpu_is_mx53())
 		return -EINVAL;
 
-	if (cpu_silicon_rev == -1)
-		cpu_silicon_rev = get_mx53_srev();
+	if (mx5_cpu_rev == -1)
+		mx5_cpu_rev = get_mx53_srev();
 
-	return cpu_silicon_rev;
+	return mx5_cpu_rev;
 }
 EXPORT_SYMBOL(mx53_revision);
 
@@ -134,7 +118,7 @@
 	u32 rev;
 
 	if (!anatop) {
-		cpu_silicon_rev = -EINVAL;
+		mx5_cpu_rev = -EINVAL;
 		return 0;
 	}
 
@@ -159,36 +143,13 @@
 	if (!cpu_is_mx50())
 		return -EINVAL;
 
-	if (cpu_silicon_rev == -1)
-		cpu_silicon_rev = get_mx50_srev();
+	if (mx5_cpu_rev == -1)
+		mx5_cpu_rev = get_mx50_srev();
 
-	return cpu_silicon_rev;
+	return mx5_cpu_rev;
 }
 EXPORT_SYMBOL(mx50_revision);
 
-void mx53_display_revision(void)
-{
-	int rev;
-	char *srev;
-	rev = mx53_revision();
-
-	switch (rev) {
-	case IMX_CHIP_REVISION_1_0:
-		srev = IMX_CHIP_REVISION_1_0_STRING;
-		break;
-	case IMX_CHIP_REVISION_2_0:
-		srev = IMX_CHIP_REVISION_2_0_STRING;
-		break;
-	case IMX_CHIP_REVISION_2_1:
-		srev = IMX_CHIP_REVISION_2_1_STRING;
-		break;
-	default:
-		srev = IMX_CHIP_REVISION_UNKNOWN_STRING;
-	}
-	printk(KERN_INFO "CPU identified as i.MX53, silicon rev %s\n", srev);
-}
-EXPORT_SYMBOL(mx53_display_revision);
-
 static int __init post_cpu_init(void)
 {
 	unsigned int reg;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/devices.c linux-libre-3.2-gnu/arch/arm/mach-mx5/devices.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/devices.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,120 +0,0 @@
-/*
- * Copyright 2009 Amit Kucheria <amit.kucheria@canonical.com>
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
- * 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/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/imx-uart.h>
-#include <mach/irqs.h>
-
-static struct resource mxc_hsi2c_resources[] = {
-	{
-		.start = MX51_HSI2C_DMA_BASE_ADDR,
-		.end = MX51_HSI2C_DMA_BASE_ADDR + SZ_16K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = MX51_MXC_INT_HS_I2C,
-		.end = MX51_MXC_INT_HS_I2C,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_hsi2c_device = {
-	.name = "imx-i2c",
-	.id = 2,
-	.num_resources = ARRAY_SIZE(mxc_hsi2c_resources),
-	.resource = mxc_hsi2c_resources
-};
-
-static u64 usb_dma_mask = DMA_BIT_MASK(32);
-
-static struct resource usbotg_resources[] = {
-	{
-		.start = MX51_OTG_BASE_ADDR,
-		.end = MX51_OTG_BASE_ADDR + 0x1ff,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = MX51_MXC_INT_USB_OTG,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-/* OTG gadget device */
-struct platform_device mxc_usbdr_udc_device = {
-	.name		= "fsl-usb2-udc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(usbotg_resources),
-	.resource	= usbotg_resources,
-	.dev		= {
-		.dma_mask		= &usb_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-struct platform_device mxc_usbdr_host_device = {
-	.name = "mxc-ehci",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(usbotg_resources),
-	.resource = usbotg_resources,
-	.dev = {
-		.dma_mask = &usb_dma_mask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
-
-static struct resource usbh1_resources[] = {
-	{
-		.start = MX51_OTG_BASE_ADDR + 0x200,
-		.end = MX51_OTG_BASE_ADDR + 0x200 + 0x1ff,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = MX51_MXC_INT_USB_H1,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_usbh1_device = {
-	.name = "mxc-ehci",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(usbh1_resources),
-	.resource = usbh1_resources,
-	.dev = {
-		.dma_mask = &usb_dma_mask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
-
-static struct resource usbh2_resources[] = {
-	{
-		.start = MX51_OTG_BASE_ADDR + 0x400,
-		.end = MX51_OTG_BASE_ADDR + 0x400 + 0x1ff,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = MX51_MXC_INT_USB_H2,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_usbh2_device = {
-	.name = "mxc-ehci",
-	.id = 2,
-	.num_resources = ARRAY_SIZE(usbh2_resources),
-	.resource = usbh2_resources,
-	.dev = {
-		.dma_mask = &usb_dma_mask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/devices.h linux-libre-3.2-gnu/arch/arm/mach-mx5/devices.h
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/devices.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/devices.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-extern struct platform_device mxc_usbdr_host_device;
-extern struct platform_device mxc_usbh1_device;
-extern struct platform_device mxc_usbh2_device;
-extern struct platform_device mxc_usbdr_udc_device;
-extern struct platform_device mxc_hsi2c_device;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/devices-imx51.h linux-libre-3.2-gnu/arch/arm/mach-mx5/devices-imx51.h
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/devices-imx51.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/devices-imx51.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,9 +13,15 @@
 #define imx51_add_fec(pdata)	\
 	imx_add_fec(&imx51_fec_data, pdata)
 
+extern const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data;
+#define imx51_add_fsl_usb2_udc(pdata)	\
+	imx_add_fsl_usb2_udc(&imx51_fsl_usb2_udc_data, pdata)
+
 extern const struct imx_imx_i2c_data imx51_imx_i2c_data[];
 #define imx51_add_imx_i2c(id, pdata)	\
 	imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
+#define imx51_add_hsi2c(pdata)	\
+	imx51_add_imx_i2c(2, pdata)
 
 extern const struct imx_imx_ssi_data imx51_imx_ssi_data[];
 #define imx51_add_imx_ssi(id, pdata)	\
@@ -25,6 +31,13 @@
 #define imx51_add_imx_uart(id, pdata)	\
 	imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata)
 
+extern const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data;
+#define imx51_add_mxc_ehci_otg(pdata)	\
+	imx_add_mxc_ehci(&imx51_mxc_ehci_otg_data, pdata)
+extern const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[];
+#define imx51_add_mxc_ehci_hs(id, pdata)	\
+	imx_add_mxc_ehci(&imx51_mxc_ehci_hs_data[id - 1], pdata)
+
 extern const struct imx_mxc_nand_data imx51_mxc_nand_data;
 #define imx51_add_mxc_nand(pdata)	\
 	imx_add_mxc_nand(&imx51_mxc_nand_data, pdata)
@@ -52,3 +65,7 @@
 extern const struct imx_imx_keypad_data imx51_imx_keypad_data;
 #define imx51_add_imx_keypad(pdata)	\
 	imx_add_imx_keypad(&imx51_imx_keypad_data, pdata)
+
+extern const struct imx_pata_imx_data imx51_pata_imx_data;
+#define imx51_add_pata_imx() \
+	imx_add_pata_imx(&imx51_pata_imx_data)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/devices-imx53.h linux-libre-3.2-gnu/arch/arm/mach-mx5/devices-imx53.h
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/devices-imx53.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/devices-imx53.h	2012-01-04 18:55:44.000000000 -0500
@@ -40,3 +40,9 @@
 extern const struct imx_imx_keypad_data imx53_imx_keypad_data;
 #define imx53_add_imx_keypad(pdata)	\
 	imx_add_imx_keypad(&imx53_imx_keypad_data, pdata)
+
+extern const struct imx_pata_imx_data imx53_pata_imx_data;
+#define imx53_add_pata_imx() \
+	imx_add_pata_imx(&imx53_pata_imx_data)
+
+extern struct platform_device *__init imx53_add_ahci_imx(void);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/ehci.c linux-libre-3.2-gnu/arch/arm/mach-mx5/ehci.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/ehci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/ehci.c	2012-01-04 18:55:44.000000000 -0500
@@ -52,7 +52,7 @@
 	void __iomem *usbother_base;
 	int ret = 0;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base) {
 		printk(KERN_ERR "%s(): ioremap failed\n", __func__);
 		return -ENOMEM;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c linux-libre-3.2-gnu/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,6 @@
 #include <asm/mach/arch.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 
 #define MBIMX51_TSC2007_GPIO	IMX_GPIO_NR(3, 30)
 #define MBIMX51_LED0		IMX_GPIO_NR(3, 5)
@@ -160,7 +159,7 @@
 static struct i2c_board_info mbimx51_i2c_devices[] = {
 	{
 		I2C_BOARD_INFO("tsc2007", 0x49),
-		.irq  = gpio_to_irq(MBIMX51_TSC2007_GPIO),
+		.irq  = IMX_GPIO_TO_IRQ(MBIMX51_TSC2007_GPIO),
 		.platform_data = &tsc2007_data,
 	}, {
 		I2C_BOARD_INFO("tlv320aic23", 0x1a),
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c linux-libre-3.2-gnu/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,6 @@
 
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/leds.h>
 #include <linux/platform_device.h>
 #include <linux/input.h>
@@ -41,13 +40,12 @@
 #include <mach/audmux.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 
 static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
 	/* LED */
 	MX51_PAD_NANDF_D10__GPIO3_30,
 	/* SWITCH */
-	_MX51_PAD_NANDF_D9__GPIO3_31 | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
+	NEW_PAD_CTRL(MX51_PAD_NANDF_D9__GPIO3_31, PAD_CTL_PUS_22K_UP |
 			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
 			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
 	/* UART2 */
@@ -66,7 +64,7 @@
 	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 |
+	NEW_PAD_CTRL(MX51_PAD_GPIO1_0__SD1_CD, PAD_CTL_PUS_22K_UP |
 			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
 			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
 };
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/imx51-dt.c linux-libre-3.2-gnu/arch/arm/mach-mx5/imx51-dt.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/imx51-dt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/imx51-dt.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx51.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate().  Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "imx27-fec.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx51.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx51.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx51.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx51.3", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-cspi", MX51_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-sdma", MX51_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-wdt", MX51_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+	{ /* sentinel */ }
+};
+
+static int __init imx51_tzic_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	irq_domain_add_simple(np, 0);
+	return 0;
+}
+
+static int __init imx51_gpio_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
+
+	gpio_irq_base -= 32;
+	irq_domain_add_simple(np, gpio_irq_base);
+
+	return 0;
+}
+
+static const struct of_device_id imx51_irq_match[] __initconst = {
+	{ .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, },
+	{ .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, },
+	{ /* sentinel */ }
+};
+
+static const struct of_device_id imx51_iomuxc_of_match[] __initconst = {
+	{ .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, },
+	{ /* sentinel */ }
+};
+
+static void __init imx51_dt_init(void)
+{
+	struct device_node *node;
+	const struct of_device_id *of_id;
+	void (*func)(void);
+
+	of_irq_init(imx51_irq_match);
+
+	node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
+	if (node) {
+		of_id = of_match_node(imx51_iomuxc_of_match, node);
+		func = of_id->data;
+		func();
+		of_node_put(node);
+	}
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     imx51_auxdata_lookup, NULL);
+}
+
+static void __init imx51_timer_init(void)
+{
+	mx51_clocks_init_dt();
+}
+
+static struct sys_timer imx51_timer = {
+	.init = imx51_timer_init,
+};
+
+static const char *imx51_dt_board_compat[] __initdata = {
+	"fsl,imx51-babbage",
+	NULL
+};
+
+DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
+	.map_io		= mx51_map_io,
+	.init_early	= imx51_init_early,
+	.init_irq	= mx51_init_irq,
+	.handle_irq	= imx51_handle_irq,
+	.timer		= &imx51_timer,
+	.init_machine	= imx51_dt_init,
+	.dt_compat	= imx51_dt_board_compat,
+MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/imx53-dt.c linux-libre-3.2-gnu/arch/arm/mach-mx5/imx53-dt.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/imx53-dt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/imx53-dt.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx53.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate().  Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART4_BASE_ADDR, "imx21-uart.3", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART5_BASE_ADDR, "imx21-uart.4", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-fec", MX53_FEC_BASE_ADDR, "imx25-fec.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx53.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx53.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx53.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx53.3", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+	{ /* sentinel */ }
+};
+
+static int __init imx53_tzic_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	irq_domain_add_simple(np, 0);
+	return 0;
+}
+
+static int __init imx53_gpio_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
+
+	gpio_irq_base -= 32;
+	irq_domain_add_simple(np, gpio_irq_base);
+
+	return 0;
+}
+
+static const struct of_device_id imx53_irq_match[] __initconst = {
+	{ .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, },
+	{ .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, },
+	{ /* sentinel */ }
+};
+
+static const struct of_device_id imx53_iomuxc_of_match[] __initconst = {
+	{ .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, },
+	{ .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, },
+	{ .compatible = "fsl,imx53-iomuxc-qsb", .data = imx53_qsb_common_init, },
+	{ .compatible = "fsl,imx53-iomuxc-smd", .data = imx53_smd_common_init, },
+	{ /* sentinel */ }
+};
+
+static void __init imx53_dt_init(void)
+{
+	struct device_node *node;
+	const struct of_device_id *of_id;
+	void (*func)(void);
+
+	of_irq_init(imx53_irq_match);
+
+	node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
+	if (node) {
+		of_id = of_match_node(imx53_iomuxc_of_match, node);
+		func = of_id->data;
+		func();
+		of_node_put(node);
+	}
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     imx53_auxdata_lookup, NULL);
+}
+
+static void __init imx53_timer_init(void)
+{
+	mx53_clocks_init_dt();
+}
+
+static struct sys_timer imx53_timer = {
+	.init = imx53_timer_init,
+};
+
+static const char *imx53_dt_board_compat[] __initdata = {
+	"fsl,imx53-ard",
+	"fsl,imx53-evk",
+	"fsl,imx53-qsb",
+	"fsl,imx53-smd",
+	NULL
+};
+
+DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
+	.map_io		= mx53_map_io,
+	.init_early	= imx53_init_early,
+	.init_irq	= mx53_init_irq,
+	.handle_irq	= imx53_handle_irq,
+	.timer		= &imx53_timer,
+	.init_machine	= imx53_dt_init,
+	.dt_compat	= imx53_dt_board_compat,
+MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/Kconfig linux-libre-3.2-gnu/arch/arm/mach-mx5/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,8 +1,9 @@
-if ARCH_MX503 || ARCH_MX51
+if ARCH_MX5
+
 # ARCH_MX5/50/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_MX5
+config ARCH_MX51
 	bool
 
 config ARCH_MX50
@@ -19,7 +20,6 @@
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_MXC_AUDMUX_V2
 	select ARCH_HAS_CPUFREQ
-	select ARCH_MX5
 	select ARCH_MX50
 
 config	SOC_IMX51
@@ -30,7 +30,7 @@
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_MXC_AUDMUX_V2
 	select ARCH_HAS_CPUFREQ
-	select ARCH_MX5
+	select ARCH_MX51
 
 config	SOC_IMX53
 	bool
@@ -38,10 +38,8 @@
 	select ARM_L1_CACHE_SHIFT_6
 	select MXC_TZIC
 	select ARCH_MXC_IOMUX_V3
-	select ARCH_MX5
 	select ARCH_MX53
 
-if ARCH_MX50_SUPPORTED
 #comment "i.MX50 machines:"
 
 config MACH_MX50_RDP
@@ -52,22 +50,29 @@
 	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.
 
-endif # ARCH_MX50_SUPPORTED
-
-if ARCH_MX51
 comment "i.MX51 machines:"
 
+config MACH_IMX51_DT
+	bool "Support i.MX51 platforms from device tree"
+	select SOC_IMX51
+	select USE_OF
+	select MACH_MX51_BABBAGE
+	help
+	  Include support for Freescale i.MX51 based platforms
+	  using the device tree for discovery
+
 config MACH_MX51_BABBAGE
 	bool "Support MX51 BABBAGE platforms"
 	select SOC_IMX51
+	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_SDHCI_ESDHC_IMX
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	help
@@ -91,8 +96,10 @@
 config MACH_EUKREA_CPUIMX51
 	bool "Support Eukrea CPUIMX51 module"
 	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
 	select IMX_HAVE_PLATFORM_MXC_NAND
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	help
@@ -119,10 +126,12 @@
 config MACH_EUKREA_CPUIMX51SD
 	bool "Support Eukrea CPUIMX51SD module"
 	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_SPI_IMX
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
 	select IMX_HAVE_PLATFORM_MXC_NAND
+	select IMX_HAVE_PLATFORM_SPI_IMX
 	help
 	  Include support for Eukrea CPUIMX51SD platform. This includes
 	  specific configurations for the module and its peripherals.
@@ -147,6 +156,8 @@
 	bool
 	select SOC_IMX51
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_PATA_IMX
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	select MXC_ULPI if USB_ULPI
@@ -167,11 +178,20 @@
 	  Include support for Genesi Efika Smartbook. This includes specific
 	  configurations for the board and its peripherals.
 
-endif # ARCH_MX51
-
-if ARCH_MX53_SUPPORTED
 comment "i.MX53 machines:"
 
+config MACH_IMX53_DT
+	bool "Support i.MX53 platforms from device tree"
+	select SOC_IMX53
+	select USE_OF
+	select MACH_MX53_ARD
+	select MACH_MX53_EVK
+	select MACH_MX53_LOCO
+	select MACH_MX53_SMD
+	help
+	  Include support for Freescale i.MX53 based platforms
+	  using the device tree for discovery
+
 config MACH_MX53_EVK
 	bool "Support MX53 EVK platforms"
 	select SOC_IMX53
@@ -221,6 +241,4 @@
 	  Include support for MX53 ARD platform. This includes specific
 	  configurations for the board and its peripherals.
 
-endif # ARCH_MX53_SUPPORTED
-
 endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/Makefile linux-libre-3.2-gnu/arch/arm/mach-mx5/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,8 +3,7 @@
 #
 
 # Object file lists.
-obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o system.o
-obj-$(CONFIG_SOC_IMX50) += mm-mx50.o
+obj-y   := cpu.o mm.o clock-mx51-mx53.o ehci.o system.o
 
 obj-$(CONFIG_PM) += pm-imx5.o
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
@@ -22,3 +21,6 @@
 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
+
+obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
+obj-$(CONFIG_MACH_IMX53_DT) += imx53-dt.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-mx5/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,9 +1,9 @@
-   zreladdr-$(CONFIG_ARCH_MX50)	:= 0x70008000
+   zreladdr-$(CONFIG_ARCH_MX50)	+= 0x70008000
 params_phys-$(CONFIG_ARCH_MX50)	:= 0x70000100
 initrd_phys-$(CONFIG_ARCH_MX50)	:= 0x70800000
-   zreladdr-$(CONFIG_ARCH_MX51)	:= 0x90008000
+   zreladdr-$(CONFIG_ARCH_MX51)	+= 0x90008000
 params_phys-$(CONFIG_ARCH_MX51)	:= 0x90000100
 initrd_phys-$(CONFIG_ARCH_MX51)	:= 0x90800000
-   zreladdr-$(CONFIG_ARCH_MX53)	:= 0x70008000
+   zreladdr-$(CONFIG_ARCH_MX53)	+= 0x70008000
 params_phys-$(CONFIG_ARCH_MX53)	:= 0x70000100
 initrd_phys-$(CONFIG_ARCH_MX53)	:= 0x70800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/mm.c linux-libre-3.2-gnu/arch/arm/mach-mx5/mm.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/mm.c	2012-03-19 21:31:13.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/mm.c	2012-03-19 21:32:47.000000000 -0400
@@ -21,12 +21,29 @@
 #include <mach/devices-common.h>
 #include <mach/iomux-v3.h>
 
+static void imx5_idle(void)
+{
+	if (!need_resched())
+		mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+	local_irq_enable();
+}
+
+/*
+ * Define the MX50 memory map.
+ */
+static struct map_desc mx50_io_desc[] __initdata = {
+	imx_map_entry(MX50, TZIC, MT_DEVICE),
+	imx_map_entry(MX50, SPBA0, MT_DEVICE),
+	imx_map_entry(MX50, AIPS1, MT_DEVICE),
+	imx_map_entry(MX50, AIPS2, MT_DEVICE),
+};
+
 /*
  * Define the MX51 memory map.
  */
 static struct map_desc mx51_io_desc[] __initdata = {
+	imx_map_entry(MX51, TZIC, MT_DEVICE),
 	imx_map_entry(MX51, IRAM, MT_DEVICE),
-	imx_map_entry(MX51, DEBUG, MT_DEVICE),
 	imx_map_entry(MX51, AIPS1, MT_DEVICE),
 	imx_map_entry(MX51, SPBA0, MT_DEVICE),
 	imx_map_entry(MX51, AIPS2, MT_DEVICE),
@@ -36,6 +53,7 @@
  * Define the MX53 memory map.
  */
 static struct map_desc mx53_io_desc[] __initdata = {
+	imx_map_entry(MX53, TZIC, MT_DEVICE),
 	imx_map_entry(MX53, AIPS1, MT_DEVICE),
 	imx_map_entry(MX53, SPBA0, MT_DEVICE),
 	imx_map_entry(MX53, AIPS2, MT_DEVICE),
@@ -46,21 +64,34 @@
  * system startup to create static physical to virtual memory mappings
  * for the IO modules.
  */
+void __init mx50_map_io(void)
+{
+	iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
+}
+
 void __init mx51_map_io(void)
 {
 	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 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));
+}
+
 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));
-}
-
-void __init mx53_map_io(void)
-{
-	iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
+	pm_idle = imx5_idle;
 }
 
 void __init imx53_init_early(void)
@@ -70,35 +101,19 @@
 	mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
 }
 
-void __init mx51_init_irq(void)
+void __init mx50_init_irq(void)
 {
-	unsigned long tzic_addr;
-	void __iomem *tzic_virt;
-
-	if (mx51_revision() < IMX_CHIP_REVISION_2_0)
-		tzic_addr = MX51_TZIC_BASE_ADDR_TO1;
-	else
-		tzic_addr = MX51_TZIC_BASE_ADDR;
-
-	tzic_virt = ioremap(tzic_addr, SZ_16K);
-	if (!tzic_virt)
-		panic("unable to map TZIC interrupt controller\n");
+	tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
+}
 
-	tzic_init_irq(tzic_virt);
+void __init mx51_init_irq(void)
+{
+	tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR));
 }
 
 void __init mx53_init_irq(void)
 {
-	unsigned long tzic_addr;
-	void __iomem *tzic_virt;
-
-	tzic_addr = MX53_TZIC_BASE_ADDR;
-
-	tzic_virt = ioremap(tzic_addr, SZ_16K);
-	if (!tzic_virt)
-		panic("unable to map TZIC interrupt controller\n");
-
-	tzic_init_irq(tzic_virt);
+	tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR));
 }
 
 static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
@@ -138,13 +153,24 @@
 	.script_addrs = &imx53_sdma_script,
 };
 
+void __init imx50_soc_init(void)
+{
+	/* i.mx50 has the i.mx31 type gpio */
+	mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
+	mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
+	mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
+	mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
+	mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
+	mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
+}
+
 void __init imx51_soc_init(void)
 {
 	/* i.mx51 has the i.mx31 type gpio */
-	mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO1_LOW, MX51_MXC_INT_GPIO1_HIGH);
-	mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH);
-	mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH);
-	mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH);
+	mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH);
+	mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH);
+	mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH);
+	mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH);
 
 	/* i.mx51 has the i.mx35 type sdma */
 	imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/mm-mx50.c linux-libre-3.2-gnu/arch/arm/mach-mx5/mm-mx50.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/mm-mx50.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/mm-mx50.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,72 +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.
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-v3.h>
-#include <mach/irqs.h>
-
-/*
- * Define the MX50 memory map.
- */
-static struct map_desc mx50_io_desc[] __initdata = {
-	imx_map_entry(MX50, TZIC, MT_DEVICE),
-	imx_map_entry(MX50, SPBA0, MT_DEVICE),
-	imx_map_entry(MX50, AIPS1, MT_DEVICE),
-	imx_map_entry(MX50, AIPS2, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-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));
-}
-
-void __init mx50_init_irq(void)
-{
-	tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
-}
-
-void __init imx50_soc_init(void)
-{
-	/* i.mx50 has the i.mx31 type gpio */
-	mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
-	mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
-	mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
-	mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
-	mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
-	mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/mx51_efika.c linux-libre-3.2-gnu/arch/arm/mach-mx5/mx51_efika.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/mx51_efika.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/mx51_efika.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,14 +34,12 @@
 #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"
 
@@ -133,7 +131,7 @@
 	u32 v;
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
@@ -150,7 +148,7 @@
 	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
 }
 
-static struct mxc_usbh_platform_data dr_utmi_config = {
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
 	.init   = initialize_otg_port,
 	.portsc = MXC_EHCI_UTMI_16BIT,
 };
@@ -170,7 +168,7 @@
 	gpio_set_value(EFIKAMX_USBH1_STP, 1);
 	msleep(1);
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_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 */
@@ -189,7 +187,7 @@
 	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
-static struct mxc_usbh_platform_data usbh1_config = {
+static struct mxc_usbh_platform_data usbh1_config __initdata = {
 	.init   = initialize_usbh1_port,
 	.portsc = MXC_EHCI_MODE_ULPI,
 };
@@ -217,9 +215,9 @@
 	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);
+	imx51_add_mxc_ehci_otg(&dr_utmi_config);
 	if (usbh1_config.otg)
-		mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+		imx51_add_mxc_ehci_hs(1, &usbh1_config);
 }
 
 static struct mtd_partition mx51_efika_spi_nor_partitions[] = {
@@ -567,7 +565,7 @@
 };
 
 static struct mc13xxx_platform_data mx51_efika_mc13892_data = {
-	.flags = MC13XXX_USE_RTC | MC13XXX_USE_REGULATOR,
+	.flags = MC13XXX_USE_RTC,
 	.regulators = {
 		.num_regulators = ARRAY_SIZE(mx51_efika_regulators),
 		.regulators = mx51_efika_regulators,
@@ -589,7 +587,7 @@
 		.bus_num = 0,
 		.chip_select = 0,
 		.platform_data = &mx51_efika_mc13892_data,
-		.irq = gpio_to_irq(EFIKAMX_PMIC),
+		.irq = IMX_GPIO_TO_IRQ(EFIKAMX_PMIC),
 	},
 };
 
@@ -609,7 +607,6 @@
 					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)
@@ -627,8 +624,9 @@
 		ARRAY_SIZE(mx51_efika_spi_board_info));
 	imx51_add_ecspi(0, &mx51_efika_spi_pdata);
 
+	imx51_add_pata_imx();
+
 #if defined(CONFIG_CPU_FREQ_IMX)
 	get_cpu_op = mx51_get_cpu_op;
 #endif
 }
-
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/pm-imx5.c linux-libre-3.2-gnu/arch/arm/mach-mx5/pm-imx5.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/pm-imx5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/pm-imx5.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,14 +14,19 @@
 #include <linux/err.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
-#include <mach/system.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
 #include "crm_regs.h"
 
 static struct clk *gpc_dvfs_clk;
 
+static int mx5_suspend_prepare(void)
+{
+	return clk_enable(gpc_dvfs_clk);
+}
+
 static int mx5_suspend_enter(suspend_state_t state)
 {
-	clk_enable(gpc_dvfs_clk);
 	switch (state) {
 	case PM_SUSPEND_MEM:
 		mx5_cpu_lp_set(STOP_POWER_OFF);
@@ -42,11 +47,14 @@
 		__raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
 	}
 	cpu_do_idle();
-	clk_disable(gpc_dvfs_clk);
-
 	return 0;
 }
 
+static void mx5_suspend_finish(void)
+{
+	clk_disable(gpc_dvfs_clk);
+}
+
 static int mx5_pm_valid(suspend_state_t state)
 {
 	return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
@@ -54,7 +62,9 @@
 
 static const struct platform_suspend_ops mx5_suspend_ops = {
 	.valid = mx5_pm_valid,
+	.prepare = mx5_suspend_prepare,
 	.enter = mx5_suspend_enter,
+	.finish = mx5_suspend_finish,
 };
 
 static int __init mx5_pm_init(void)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mx5/system.c linux-libre-3.2-gnu/arch/arm/mach-mx5/system.c
--- linux-libre-3.1-gnu/arch/arm/mach-mx5/system.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mx5/system.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <mach/hardware.h>
+#include <mach/common.h>
 #include "crm_regs.h"
 
 /* set cpu low power mode before WFI instruction. This function is called
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/clock-mx28.c linux-libre-3.2-gnu/arch/arm/mach-mxs/clock-mx28.c
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/clock-mx28.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/clock-mx28.c	2012-01-04 18:55:44.000000000 -0500
@@ -349,7 +349,7 @@
 									\
 		reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##fr);	\
 		reg &= ~BM_CLKCTRL_##fr##_##fs##FRAC;			\
-		reg |= frac;						\
+		reg |= frac << BP_CLKCTRL_##fr##_##fs##FRAC;		\
 		__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##fr);	\
 	}								\
 									\
@@ -404,7 +404,7 @@
 	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr);		\
 	reg &= ~BM_CLKCTRL_##dr##_DIV;					\
 	reg |= div << BP_CLKCTRL_##dr##_DIV;				\
-	if (reg | (1 << clk->enable_shift)) {				\
+	if (reg & (1 << clk->enable_shift)) {				\
 		pr_err("%s: clock is gated\n", __func__);		\
 		return -EINVAL;						\
 	}								\
@@ -640,6 +640,8 @@
 	_REGISTER_CLOCK(NULL, "lradc", lradc_clk)
 	_REGISTER_CLOCK(NULL, "spdif", spdif_clk)
 	_REGISTER_CLOCK("imx28-fb", NULL, lcdif_clk)
+	_REGISTER_CLOCK("mxs-saif.0", NULL, saif0_clk)
+	_REGISTER_CLOCK("mxs-saif.1", NULL, saif1_clk)
 };
 
 static int clk_misc_init(void)
@@ -708,11 +710,11 @@
 
 	/* SAIF has to use frac div for functional operation */
 	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF0);
-	reg &= ~BM_CLKCTRL_SAIF0_DIV_FRAC_EN;
+	reg |= BM_CLKCTRL_SAIF0_DIV_FRAC_EN;
 	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF0);
 
 	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF1);
-	reg &= ~BM_CLKCTRL_SAIF1_DIV_FRAC_EN;
+	reg |= BM_CLKCTRL_SAIF1_DIV_FRAC_EN;
 	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF1);
 
 	/*
@@ -738,11 +740,17 @@
 	__raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT,
 			CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_SET);
 
-	/* Extra fec clock setting */
-	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
-	reg &= ~BM_CLKCTRL_ENET_SLEEP;
-	reg |= BM_CLKCTRL_ENET_CLK_OUT_EN;
-	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
+	/*
+	 * Extra fec clock setting
+	 * The DENX M28 uses an external clock source
+	 * and the clock output must not be enabled
+	 */
+	if (!machine_is_m28evk()) {
+		reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
+		reg &= ~BM_CLKCTRL_ENET_SLEEP;
+		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,
@@ -774,6 +782,8 @@
 	clk_enable(&uart_clk);
 
 	clk_set_parent(&lcdif_clk, &ref_pix_clk);
+	clk_set_parent(&saif0_clk, &pll0_clk);
+	clk_set_parent(&saif1_clk, &pll0_clk);
 
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/devices/Kconfig linux-libre-3.2-gnu/arch/arm/mach-mxs/devices/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/devices/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/devices/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -23,3 +23,9 @@
 
 config MXS_HAVE_PLATFORM_MXSFB
 	bool
+
+config MXS_HAVE_PLATFORM_MXS_SAIF
+	bool
+
+config MXS_HAVE_PLATFORM_RTC_STMP3XXX
+	bool
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/devices/Makefile linux-libre-3.2-gnu/arch/arm/mach-mxs/devices/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/devices/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/devices/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -8,3 +8,5 @@
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o
 obj-y += platform-gpio-mxs.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXSFB) += platform-mxsfb.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_SAIF) += platform-mxs-saif.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_RTC_STMP3XXX) += platform-rtc-stmp3xxx.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/devices/platform-mxs-saif.c linux-libre-3.2-gnu/arch/arm/mach-mxs/devices/platform-mxs-saif.c
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/devices/platform-mxs-saif.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/devices/platform-mxs-saif.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,60 @@
+/*
+ * 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_saif_data_entry_single(soc, _id)				\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _SAIF ## _id ## _BASE_ADDR,		\
+		.irq = soc ## _INT_SAIF ## _id,				\
+		.dma = soc ## _DMA_SAIF ## _id,				\
+		.dmairq = soc ## _INT_SAIF ## _id ##_DMA,		\
+	}
+
+#define mxs_saif_data_entry(soc, _id)					\
+	[_id] = mxs_saif_data_entry_single(soc, _id)
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_saif_data mx28_saif_data[] __initconst = {
+	mxs_saif_data_entry(MX28, 0),
+	mxs_saif_data_entry(MX28, 1),
+};
+#endif
+
+struct platform_device *__init mxs_add_saif(const struct mxs_saif_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->dma,
+			.end = data->dma,
+			.flags = IORESOURCE_DMA,
+		}, {
+			.start = data->dmairq,
+			.end = data->dmairq,
+			.flags = IORESOURCE_IRQ,
+		},
+
+	};
+
+	return mxs_add_platform_device("mxs-saif", data->id, res,
+					ARRAY_SIZE(res), NULL, 0);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c linux-libre-3.2-gnu/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -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/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#ifdef CONFIG_SOC_IMX23
+struct platform_device *__init mx23_add_rtc_stmp3xxx(void)
+{
+	struct resource res[] = {
+		{
+			.start = MX23_RTC_BASE_ADDR,
+			.end = MX23_RTC_BASE_ADDR + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = MX23_INT_RTC_ALARM,
+			.end = MX23_INT_RTC_ALARM,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return mxs_add_platform_device("stmp3xxx-rtc", 0, res, ARRAY_SIZE(res),
+					NULL, 0);
+}
+#endif /* CONFIG_SOC_IMX23 */
+
+#ifdef CONFIG_SOC_IMX28
+struct platform_device *__init mx28_add_rtc_stmp3xxx(void)
+{
+	struct resource res[] = {
+		{
+			.start = MX28_RTC_BASE_ADDR,
+			.end = MX28_RTC_BASE_ADDR + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = MX28_INT_RTC_ALARM,
+			.end = MX28_INT_RTC_ALARM,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return mxs_add_platform_device("stmp3xxx-rtc", 0, res, ARRAY_SIZE(res),
+					NULL, 0);
+}
+#endif /* CONFIG_SOC_IMX28 */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/devices-mx23.h linux-libre-3.2-gnu/arch/arm/mach-mxs/devices-mx23.h
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/devices-mx23.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/devices-mx23.h	2012-01-04 18:55:44.000000000 -0500
@@ -29,3 +29,5 @@
 
 struct platform_device *__init mx23_add_mxsfb(
 		const struct mxsfb_platform_data *pdata);
+
+struct platform_device *__init mx23_add_rtc_stmp3xxx(void);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/devices-mx28.h linux-libre-3.2-gnu/arch/arm/mach-mxs/devices-mx28.h
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/devices-mx28.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/devices-mx28.h	2012-01-04 18:55:44.000000000 -0500
@@ -45,3 +45,8 @@
 
 struct platform_device *__init mx28_add_mxsfb(
 		const struct mxsfb_platform_data *pdata);
+
+extern const struct mxs_saif_data mx28_saif_data[] __initconst;
+#define mx28_add_saif(id)              mxs_add_saif(&mx28_saif_data[id])
+
+struct platform_device *__init mx28_add_rtc_stmp3xxx(void);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-mxs/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -14,23 +14,15 @@
 #include <mach/mx23.h>
 #include <mach/mx28.h>
 
-#ifdef CONFIG_SOC_IMX23
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#ifdef CONFIG_DEBUG_IMX23_UART
 #define UART_PADDR	MX23_DUART_BASE_ADDR
-#endif
-
-#ifdef CONFIG_SOC_IMX28
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX28_UART)
 #define UART_PADDR	MX28_DUART_BASE_ADDR
 #endif
 
 #define UART_VADDR	MXS_IO_ADDRESS(UART_PADDR)
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		ldr	\rp, =UART_PADDR	@ physical
 		ldr	\rv, =UART_VADDR	@ virtual
 		.endm
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/include/mach/devices-common.h linux-libre-3.2-gnu/arch/arm/mach-mxs/include/mach/devices-common.h
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/include/mach/devices-common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/include/mach/devices-common.h	2012-01-04 18:55:44.000000000 -0500
@@ -92,3 +92,15 @@
 /* pwm */
 struct platform_device *__init mxs_add_mxs_pwm(
 		resource_size_t iobase, int id);
+
+/* saif */
+struct mxs_saif_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t irq;
+	resource_size_t dma;
+	resource_size_t dmairq;
+};
+
+struct platform_device *__init mxs_add_saif(
+		const struct mxs_saif_data *data);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-mxs/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,35 +1 @@
-/*
- * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, 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
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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_MXS_GPIO_H__
-#define __MACH_MXS_GPIO_H__
-
-#include <asm-generic/gpio.h>
-
-#define MXS_GPIO_NR(bank, nr)	((bank) * 32 + (nr))
-
-/* use gpiolib dispatchers */
-#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
-
-#define irq_to_gpio(irq)	((irq) - MXS_GPIO_IRQ_START)
-
-#endif /* __MACH_MXS_GPIO_H__ */
+/* empty */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-mxs/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2009-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.
- */
-
-#ifndef __MACH_MXS_MEMORY_H__
-#define __MACH_MXS_MEMORY_H__
-
-#define PHYS_OFFSET		UL(0x40000000)
-
-#endif /* __MACH_MXS_MEMORY_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/include/mach/mx28.h linux-libre-3.2-gnu/arch/arm/mach-mxs/include/mach/mx28.h
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/include/mach/mx28.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/include/mach/mx28.h	2012-01-04 18:55:44.000000000 -0500
@@ -104,8 +104,8 @@
 #define MX28_INT_CAN1			9
 #define MX28_INT_LRADC_TOUCH		10
 #define MX28_INT_HSADC			13
-#define MX28_INT_IRADC_THRESH0		14
-#define MX28_INT_IRADC_THRESH1		15
+#define MX28_INT_LRADC_THRESH0		14
+#define MX28_INT_LRADC_THRESH1		15
 #define MX28_INT_LRADC_CH0		16
 #define MX28_INT_LRADC_CH1		17
 #define MX28_INT_LRADC_CH2		18
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/include/mach/mxs.h linux-libre-3.2-gnu/arch/arm/mach-mxs/include/mach/mxs.h
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/include/mach/mxs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/include/mach/mxs.h	2012-01-04 18:55:44.000000000 -0500
@@ -30,9 +30,11 @@
  */
 #define cpu_is_mx23()		(					\
 		machine_is_mx23evk() ||					\
+		machine_is_stmp378x() ||				\
 		0)
 #define cpu_is_mx28()		(					\
 		machine_is_mx28evk() ||					\
+		machine_is_m28evk() ||					\
 		machine_is_tx28() ||					\
 		0)
 
@@ -86,6 +88,8 @@
 	.type = _type,							\
 }
 
+#define MXS_GPIO_NR(bank, nr)	((bank) * 32 + (nr))
+
 #define MXS_SET_ADDR		0x4
 #define MXS_CLR_ADDR		0x8
 #define MXS_TOG_ADDR		0xc
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/include/mach/uncompress.h linux-libre-3.2-gnu/arch/arm/mach-mxs/include/mach/uncompress.h
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/include/mach/uncompress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/include/mach/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -63,6 +63,7 @@
 		mxs_duart_base = MX23_DUART_BASE_ADDR;
 		break;
 	case MACH_TYPE_MX28EVK:
+	case MACH_TYPE_M28EVK:
 	case MACH_TYPE_TX28:
 		mxs_duart_base = MX28_DUART_BASE_ADDR;
 		break;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/Kconfig linux-libre-3.2-gnu/arch/arm/mach-mxs/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 	select MXS_HAVE_AMBA_DUART
 	select MXS_HAVE_PLATFORM_AUART
 	select MXS_HAVE_PLATFORM_MXS_MMC
+	select MXS_HAVE_PLATFORM_RTC_STMP3XXX
 	help
 	  Include support for STMP378x-devb platform. This includes specific
 	  configurations for the board and its peripherals.
@@ -34,6 +35,7 @@
 	select MXS_HAVE_PLATFORM_AUART
 	select MXS_HAVE_PLATFORM_MXS_MMC
 	select MXS_HAVE_PLATFORM_MXSFB
+	select MXS_HAVE_PLATFORM_RTC_STMP3XXX
 	help
 	  Include support for MX23EVK platform. This includes specific
 	  configurations for the board and its peripherals.
@@ -48,6 +50,9 @@
 	select MXS_HAVE_PLATFORM_FLEXCAN
 	select MXS_HAVE_PLATFORM_MXS_MMC
 	select MXS_HAVE_PLATFORM_MXSFB
+	select MXS_HAVE_PLATFORM_MXS_SAIF
+	select MXS_HAVE_PLATFORM_MXS_I2C
+	select MXS_HAVE_PLATFORM_RTC_STMP3XXX
 	select MXS_OCOTP
 	help
 	  Include support for MX28EVK platform. This includes specific
@@ -63,9 +68,27 @@
 	select MXS_HAVE_PLATFORM_MXS_I2C
 	select MXS_HAVE_PLATFORM_MXS_MMC
 	select MXS_HAVE_PLATFORM_MXS_PWM
+	select MXS_HAVE_PLATFORM_RTC_STMP3XXX
+
+config MODULE_M28
+	bool
+	select SOC_IMX28
+	select LEDS_GPIO_REGISTER
+	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_I2C
+	select MXS_HAVE_PLATFORM_MXS_MMC
+	select MXS_HAVE_PLATFORM_MXSFB
+	select MXS_OCOTP
 
 config MACH_TX28
 	bool "Ka-Ro TX28 module"
 	select MODULE_TX28
 
+config MACH_M28EVK
+	bool "Support DENX M28EVK Platform"
+	select MODULE_M28
+
 endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/mach-m28evk.c linux-libre-3.2-gnu/arch/arm/mach-mxs/mach-m28evk.c
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/mach-m28evk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/mach-m28evk.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2011
+ * Stefano Babic, DENX Software Engineering, <sbabic@denx.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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/common.h>
+#include <mach/iomux-mx28.h>
+
+#include "devices-mx28.h"
+
+#define M28EVK_GPIO_USERLED1	MXS_GPIO_NR(3, 16)
+#define M28EVK_GPIO_USERLED2	MXS_GPIO_NR(3, 17)
+
+#define MX28EVK_BL_ENABLE	MXS_GPIO_NR(3, 18)
+#define M28EVK_LCD_ENABLE	MXS_GPIO_NR(3, 28)
+
+#define MX28EVK_MMC0_WRITE_PROTECT	MXS_GPIO_NR(2, 12)
+#define MX28EVK_MMC1_WRITE_PROTECT	MXS_GPIO_NR(0, 28)
+
+static const iomux_cfg_t m28evk_pads[] __initconst = {
+	/* duart */
+	MX28_PAD_AUART0_CTS__DUART_RX | MXS_PAD_CTRL,
+	MX28_PAD_AUART0_RTS__DUART_TX | MXS_PAD_CTRL,
+
+	/* auart0 */
+	MX28_PAD_AUART0_RX__AUART0_RX | MXS_PAD_CTRL,
+	MX28_PAD_AUART0_TX__AUART0_TX | 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 | 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,
+
+	/* 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,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL,
+	MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+	/* 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_ENABLE__LCD_ENABLE	| MXS_PAD_CTRL,
+	MX28_PAD_LCD_DOTCLK__LCD_DOTCLK | MXS_PAD_CTRL,
+
+	/* 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),
+
+	/* mmc1 */
+	MX28_PAD_GPMI_D00__SSP1_D0 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D01__SSP1_D1 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D02__SSP1_D2 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D03__SSP1_D3 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D04__SSP1_D4 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D05__SSP1_D5 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	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),
+	/* slot power enable */
+	MX28_PAD_PWM4__GPIO_3_29 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+	/* led */
+	MX28_PAD_PWM0__GPIO_3_16 | MXS_PAD_CTRL,
+	MX28_PAD_PWM1__GPIO_3_17 | MXS_PAD_CTRL,
+
+	/* nand */
+	MX28_PAD_GPMI_D00__GPMI_D0 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D01__GPMI_D1 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D02__GPMI_D2 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D03__GPMI_D3 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D04__GPMI_D4 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D05__GPMI_D5 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D06__GPMI_D6 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D07__GPMI_D7 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_CE0N__GPMI_CE0N |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_RDY0__GPMI_READY0 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_RDN__GPMI_RDN |
+		(MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_WRN__GPMI_WRN |
+		(MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_ALE__GPMI_ALE |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_CLE__GPMI_CLE |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_RESETN__GPMI_RESETN |
+		(MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+
+	/* Backlight */
+	MX28_PAD_PWM3__GPIO_3_28 | MXS_PAD_CTRL,
+};
+
+/* led */
+static const struct gpio_led m28evk_leds[] __initconst = {
+	{
+		.name = "user-led1",
+		.default_trigger = "heartbeat",
+		.gpio = M28EVK_GPIO_USERLED1,
+	},
+	{
+		.name = "user-led2",
+		.default_trigger = "heartbeat",
+		.gpio = M28EVK_GPIO_USERLED2,
+	},
+};
+
+static const struct gpio_led_platform_data m28evk_led_data __initconst = {
+	.leds = m28evk_leds,
+	.num_leds = ARRAY_SIZE(m28evk_leds),
+};
+
+static struct fec_platform_data mx28_fec_pdata[] __initdata = {
+	{
+		/* fec0 */
+		.phy = PHY_INTERFACE_MODE_RMII,
+	}, {
+		/* fec1 */
+		.phy = PHY_INTERFACE_MODE_RMII,
+	},
+};
+
+static int __init m28evk_fec_get_mac(void)
+{
+	int i;
+	u32 val;
+	const u32 *ocotp = mxs_get_ocotp();
+
+	if (!ocotp) {
+		pr_err("%s: timeout when reading fec mac from OCOTP\n",
+			__func__);
+		return -ETIMEDOUT;
+	}
+
+	/*
+	 * OCOTP only stores the last 4 octets for each mac address,
+	 * so hard-code DENX OUI (C0:E5:4E) here.
+	 */
+	for (i = 0; i < 2; i++) {
+		val = ocotp[i * 4];
+		mx28_fec_pdata[i].mac[0] = 0xC0;
+		mx28_fec_pdata[i].mac[1] = 0xE5;
+		mx28_fec_pdata[i].mac[2] = 0x4E;
+		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;
+}
+
+/* mxsfb (lcdif) */
+static struct fb_videomode m28evk_video_modes[] = {
+	{
+		.name		= "Ampire AM-800480R2TMQW-T01H",
+		.refresh	= 60,
+		.xres		= 800,
+		.yres		= 480,
+		.pixclock	= 30066, /* picosecond (33.26 MHz) */
+		.left_margin	= 0,
+		.right_margin	= 256,
+		.upper_margin	= 0,
+		.lower_margin	= 45,
+		.hsync_len	= 1,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_DATA_ENABLE_HIGH_ACT,
+	},
+};
+
+static const struct mxsfb_platform_data m28evk_mxsfb_pdata __initconst = {
+	.mode_list	= m28evk_video_modes,
+	.mode_count	= ARRAY_SIZE(m28evk_video_modes),
+	.default_bpp	= 16,
+	.ld_intf_width	= STMLCDIF_18BIT,
+};
+
+static struct at24_platform_data m28evk_eeprom = {
+	.byte_len = 16384,
+	.page_size = 32,
+	.flags = AT24_FLAG_ADDR16,
+};
+
+static struct i2c_board_info m28_stk5v3_i2c_boardinfo[] __initdata = {
+	{
+		I2C_BOARD_INFO("at24", 0x51),	/* E0=1, E1=0, E2=0 */
+		.platform_data = &m28evk_eeprom,
+	},
+};
+
+static struct mxs_mmc_platform_data m28evk_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 m28evk_init(void)
+{
+	mxs_iomux_setup_multiple_pads(m28evk_pads, ARRAY_SIZE(m28evk_pads));
+
+	mx28_add_duart();
+	mx28_add_auart0();
+	mx28_add_auart3();
+
+	if (!m28evk_fec_get_mac()) {
+		mx28_add_fec(0, &mx28_fec_pdata[0]);
+		mx28_add_fec(1, &mx28_fec_pdata[1]);
+	}
+
+	mx28_add_flexcan(0, NULL);
+	mx28_add_flexcan(1, NULL);
+
+	mx28_add_mxsfb(&m28evk_mxsfb_pdata);
+
+	mx28_add_mxs_mmc(0, &m28evk_mmc_pdata[0]);
+	mx28_add_mxs_mmc(1, &m28evk_mmc_pdata[1]);
+
+	gpio_led_register_device(0, &m28evk_led_data);
+
+	/* I2C */
+	mx28_add_mxs_i2c(0);
+	i2c_register_board_info(0, m28_stk5v3_i2c_boardinfo,
+			ARRAY_SIZE(m28_stk5v3_i2c_boardinfo));
+}
+
+static void __init m28evk_timer_init(void)
+{
+	mx28_clocks_init();
+}
+
+static struct sys_timer m28evk_timer = {
+	.init	= m28evk_timer_init,
+};
+
+MACHINE_START(M28EVK, "DENX M28 EVK")
+	.map_io		= mx28_map_io,
+	.init_irq	= mx28_init_irq,
+	.timer		= &m28evk_timer,
+	.init_machine	= m28evk_init,
+MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/mach-mx23evk.c linux-libre-3.2-gnu/arch/arm/mach-mxs/mach-mx23evk.c
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/mach-mx23evk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/mach-mx23evk.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,6 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-#include <linux/irq.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -167,6 +166,7 @@
 		gpio_set_value(MX23EVK_BL_ENABLE, 1);
 
 	mx23_add_mxsfb(&mx23evk_mxsfb_pdata);
+	mx23_add_rtc_stmp3xxx();
 }
 
 static void __init mx23evk_timer_init(void)
@@ -182,6 +182,6 @@
 	/* Maintainer: Freescale Semiconductor, Inc. */
 	.map_io		= mx23_map_io,
 	.init_irq	= mx23_init_irq,
-	.init_machine	= mx23evk_init,
 	.timer		= &mx23evk_timer,
+	.init_machine	= mx23evk_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/mach-mx28evk.c linux-libre-3.2-gnu/arch/arm/mach-mxs/mach-mx28evk.c
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/mach-mx28evk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/mach-mx28evk.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,8 +16,10 @@
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
-#include <linux/irq.h>
 #include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -183,6 +185,24 @@
 
 	/* led */
 	MX28_PAD_AUART1_TX__GPIO_3_5 | MXS_PAD_CTRL,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_I2C0_SDA__I2C0_SDA |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+
+	/* saif0 & saif1 */
+	MX28_PAD_SAIF0_MCLK__SAIF0_MCLK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0 |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0 |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
 };
 
 /* led */
@@ -352,6 +372,55 @@
 	},
 };
 
+static struct i2c_board_info mxs_i2c0_board_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("sgtl5000", 0x0a),
+	},
+};
+
+#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
+static struct regulator_consumer_supply mx28evk_audio_consumer_supplies[] = {
+	REGULATOR_SUPPLY("VDDA", "0-000a"),
+	REGULATOR_SUPPLY("VDDIO", "0-000a"),
+};
+
+static struct regulator_init_data mx28evk_vdd_reg_init_data = {
+	.constraints	= {
+		.name	= "3V3",
+		.always_on = 1,
+	},
+	.consumer_supplies = mx28evk_audio_consumer_supplies,
+	.num_consumer_supplies = ARRAY_SIZE(mx28evk_audio_consumer_supplies),
+};
+
+static struct fixed_voltage_config mx28evk_vdd_pdata = {
+	.supply_name	= "board-3V3",
+	.microvolts	= 3300000,
+	.gpio		= -EINVAL,
+	.enabled_at_boot = 1,
+	.init_data	= &mx28evk_vdd_reg_init_data,
+};
+static struct platform_device mx28evk_voltage_regulator = {
+	.name		= "reg-fixed-voltage",
+	.id		= -1,
+	.num_resources	= 0,
+	.dev		= {
+		.platform_data	= &mx28evk_vdd_pdata,
+	},
+};
+static void __init mx28evk_add_regulators(void)
+{
+	platform_device_register(&mx28evk_voltage_regulator);
+}
+#else
+static void __init mx28evk_add_regulators(void) {}
+#endif
+
+static struct gpio mx28evk_lcd_gpios[] = {
+	{ MX28EVK_LCD_ENABLE, GPIOF_OUT_INIT_HIGH, "lcd-enable" },
+	{ MX28EVK_BL_ENABLE, GPIOF_OUT_INIT_HIGH, "bl-enable" },
+};
+
 static void __init mx28evk_init(void)
 {
 	int ret;
@@ -378,32 +447,41 @@
 		mx28_add_flexcan(1, &mx28evk_flexcan_pdata[1]);
 	}
 
-	ret = gpio_request_one(MX28EVK_LCD_ENABLE, GPIOF_DIR_OUT, "lcd-enable");
+	ret = gpio_request_array(mx28evk_lcd_gpios,
+				 ARRAY_SIZE(mx28evk_lcd_gpios));
 	if (ret)
-		pr_warn("failed to request gpio lcd-enable: %d\n", ret);
+		pr_warn("failed to request gpio pins for lcd: %d\n", ret);
 	else
-		gpio_set_value(MX28EVK_LCD_ENABLE, 1);
+		mx28_add_mxsfb(&mx28evk_mxsfb_pdata);
 
-	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_saif(0);
+	mx28_add_saif(1);
 
-	mx28_add_mxsfb(&mx28evk_mxsfb_pdata);
+	mx28_add_mxs_i2c(0);
+	i2c_register_board_info(0, mxs_i2c0_board_info,
+				ARRAY_SIZE(mxs_i2c0_board_info));
+
+	mx28evk_add_regulators();
+
+	mxs_add_platform_device("mxs-sgtl5000", 0, NULL, 0,
+			NULL, 0);
 
 	/* power on mmc slot by writing 0 to the gpio */
 	ret = gpio_request_one(MX28EVK_MMC0_SLOT_POWER, GPIOF_OUT_INIT_LOW,
 			       "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]);
+	else
+		mx28_add_mxs_mmc(0, &mx28evk_mmc_pdata[0]);
 
 	ret = gpio_request_one(MX28EVK_MMC1_SLOT_POWER, GPIOF_OUT_INIT_LOW,
 			       "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]);
+	else
+		mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]);
+
+	mx28_add_rtc_stmp3xxx();
 
 	gpio_led_register_device(0, &mx28evk_led_data);
 }
@@ -421,6 +499,6 @@
 	/* Maintainer: Freescale Semiconductor, Inc. */
 	.map_io		= mx28_map_io,
 	.init_irq	= mx28_init_irq,
-	.init_machine	= mx28evk_init,
 	.timer		= &mx28evk_timer,
+	.init_machine	= mx28evk_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/mach-stmp378x_devb.c linux-libre-3.2-gnu/arch/arm/mach-mxs/mach-stmp378x_devb.c
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/mach-stmp378x_devb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/mach-stmp378x_devb.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,6 @@
 
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-#include <linux/irq.h>
 #include <linux/spi/spi.h>
 
 #include <asm/mach-types.h>
@@ -91,6 +90,7 @@
 
 	mx23_add_duart();
 	mx23_add_auart0();
+	mx23_add_rtc_stmp3xxx();
 
 	/* power on mmc slot */
 	ret = gpio_request_one(STMP378X_DEVB_MMC0_SLOT_POWER,
@@ -115,6 +115,6 @@
 MACHINE_START(STMP378X, "STMP378X")
 	.map_io		= mx23_map_io,
 	.init_irq	= mx23_init_irq,
-	.init_machine	= stmp378x_dvb_init,
 	.timer		= &stmp378x_dvb_timer,
+	.init_machine	= stmp378x_dvb_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/mach-tx28.c linux-libre-3.2-gnu/arch/arm/mach-mxs/mach-tx28.c
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/mach-tx28.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/mach-tx28.c	2012-01-04 18:55:44.000000000 -0500
@@ -161,6 +161,7 @@
 	i2c_register_board_info(0, tx28_stk5v3_i2c_boardinfo,
 			ARRAY_SIZE(tx28_stk5v3_i2c_boardinfo));
 	mx28_add_mxs_mmc(0, &tx28_mmc0_pdata);
+	mx28_add_rtc_stmp3xxx();
 }
 
 static void __init tx28_timer_init(void)
@@ -175,6 +176,6 @@
 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,
+	.init_machine = tx28_stk5v3_init,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/Makefile linux-libre-3.2-gnu/arch/arm/mach-mxs/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,15 +1,16 @@
 # Common support
-obj-y := clock.o devices.o icoll.o iomux.o system.o timer.o
+obj-y := clock.o devices.o icoll.o iomux.o system.o timer.o mm.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_SOC_IMX23) += clock-mx23.o
+obj-$(CONFIG_SOC_IMX28) += clock-mx28.o
 
 obj-$(CONFIG_MACH_STMP378X_DEVB) += mach-stmp378x_devb.o
 obj-$(CONFIG_MACH_MX23EVK) += mach-mx23evk.o
 obj-$(CONFIG_MACH_MX28EVK) += mach-mx28evk.o
+obj-$(CONFIG_MACH_M28EVK)    += mach-m28evk.o
 obj-$(CONFIG_MODULE_TX28) += module-tx28.o
 obj-$(CONFIG_MACH_TX28)    += mach-tx28.o
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-mxs/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1 +1 @@
-zreladdr-y := 0x40008000
+zreladdr-y += 0x40008000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/mm.c linux-libre-3.2-gnu/arch/arm/mach-mxs/mm.c
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/mm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008-2010 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
+ *
+ * Create static mapping between physical to virtual memory.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/common.h>
+#include <mach/iomux.h>
+
+/*
+ * Define the MX23 memory map.
+ */
+static struct map_desc mx23_io_desc[] __initdata = {
+	mxs_map_entry(MX23, OCRAM, MT_DEVICE),
+	mxs_map_entry(MX23, IO, MT_DEVICE),
+};
+
+/*
+ * Define the MX28 memory map.
+ */
+static struct map_desc mx28_io_desc[] __initdata = {
+	mxs_map_entry(MX28, OCRAM, MT_DEVICE),
+	mxs_map_entry(MX28, IO, MT_DEVICE),
+};
+
+/*
+ * This function initializes the memory map. It is called during the
+ * system startup to create static physical to virtual memory mappings
+ * for the IO modules.
+ */
+void __init mx23_map_io(void)
+{
+	iotable_init(mx23_io_desc, ARRAY_SIZE(mx23_io_desc));
+}
+
+void __init mx23_init_irq(void)
+{
+	icoll_init_irq();
+}
+
+void __init mx28_map_io(void)
+{
+	iotable_init(mx28_io_desc, ARRAY_SIZE(mx28_io_desc));
+}
+
+void __init mx28_init_irq(void)
+{
+	icoll_init_irq();
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/mm-mx23.c linux-libre-3.2-gnu/arch/arm/mach-mxs/mm-mx23.c
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/mm-mx23.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/mm-mx23.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/*
- * Copyright 2008-2010 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
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/mx23.h>
-#include <mach/common.h>
-#include <mach/iomux.h>
-
-/*
- * Define the MX23 memory map.
- */
-static struct map_desc mx23_io_desc[] __initdata = {
-	mxs_map_entry(MX23, OCRAM, MT_DEVICE),
-	mxs_map_entry(MX23, IO, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx23_map_io(void)
-{
-	iotable_init(mx23_io_desc, ARRAY_SIZE(mx23_io_desc));
-}
-
-void __init mx23_init_irq(void)
-{
-	icoll_init_irq();
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/mm-mx28.c linux-libre-3.2-gnu/arch/arm/mach-mxs/mm-mx28.c
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/mm-mx28.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/mm-mx28.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/*
- * Copyright 2008-2010 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
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/mx28.h>
-#include <mach/common.h>
-#include <mach/iomux.h>
-
-/*
- * Define the MX28 memory map.
- */
-static struct map_desc mx28_io_desc[] __initdata = {
-	mxs_map_entry(MX28, OCRAM, MT_DEVICE),
-	mxs_map_entry(MX28, IO, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx28_map_io(void)
-{
-	iotable_init(mx28_io_desc, ARRAY_SIZE(mx28_io_desc));
-}
-
-void __init mx28_init_irq(void)
-{
-	icoll_init_irq();
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-mxs/module-tx28.c linux-libre-3.2-gnu/arch/arm/mach-mxs/module-tx28.c
--- linux-libre-3.1-gnu/arch/arm/mach-mxs/module-tx28.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-mxs/module-tx28.c	2012-01-04 18:55:44.000000000 -0500
@@ -66,11 +66,11 @@
 	MX28_PAD_ENET0_CRS__ENET1_RX_EN,
 };
 
-static struct fec_platform_data tx28_fec0_data = {
+static const struct fec_platform_data tx28_fec0_data __initconst = {
 	.phy = PHY_INTERFACE_MODE_RMII,
 };
 
-static struct fec_platform_data tx28_fec1_data = {
+static const struct fec_platform_data tx28_fec1_data __initconst = {
 	.phy = PHY_INTERFACE_MODE_RMII,
 };
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-netx/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-netx/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-netx/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-netx/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
 
 #include "hardware.h"
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x00000a00
 		orr	\rv, \rp, #io_p2v(0x00100000)	@ virtual
 		orr	\rp, \rp, #0x00100000		@ physical
diff -druN linux-libre-3.1-gnu/arch/arm/mach-netx/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-netx/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-netx/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-netx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- *  arch/arm/mach-netx/include/mach/memory.h
- *
- * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x80000000)
-
-#endif
-
diff -druN linux-libre-3.1-gnu/arch/arm/mach-netx/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-netx/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-netx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-netx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-    zreladdr-y			:= 0x80008000
+    zreladdr-y			+= 0x80008000
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-netx/nxdb500.c linux-libre-3.2-gnu/arch/arm/mach-netx/nxdb500.c
--- linux-libre-3.1-gnu/arch/arm/mach-netx/nxdb500.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-netx/nxdb500.c	2012-01-04 18:55:44.000000000 -0500
@@ -200,7 +200,7 @@
 }
 
 MACHINE_START(NXDB500, "Hilscher nxdb500")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.map_io		= netx_map_io,
 	.init_irq	= netx_init_irq,
 	.timer		= &netx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-netx/nxdkn.c linux-libre-3.2-gnu/arch/arm/mach-netx/nxdkn.c
--- linux-libre-3.1-gnu/arch/arm/mach-netx/nxdkn.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-netx/nxdkn.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,7 +93,7 @@
 }
 
 MACHINE_START(NXDKN, "Hilscher nxdkn")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.map_io		= netx_map_io,
 	.init_irq	= netx_init_irq,
 	.timer		= &netx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-netx/nxeb500hmi.c linux-libre-3.2-gnu/arch/arm/mach-netx/nxeb500hmi.c
--- linux-libre-3.1-gnu/arch/arm/mach-netx/nxeb500hmi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-netx/nxeb500hmi.c	2012-01-04 18:55:44.000000000 -0500
@@ -177,7 +177,7 @@
 }
 
 MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.map_io		= netx_map_io,
 	.init_irq	= netx_init_irq,
 	.timer		= &netx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-netx/xc.c linux-libre-3.2-gnu/arch/arm/mach-netx/xc.c
--- linux-libre-3.1-gnu/arch/arm/mach-netx/xc.c	2012-03-19 21:28:40.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-netx/xc.c	2012-03-19 21:29:39.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/export.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nomadik/board-nhk8815.c linux-libre-3.2-gnu/arch/arm/mach-nomadik/board-nhk8815.c
--- linux-libre-3.1-gnu/arch/arm/mach-nomadik/board-nhk8815.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nomadik/board-nhk8815.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/flash.h>
 
+#include <plat/gpio-nomadik.h>
 #include <plat/mtu.h>
 
 #include <mach/setup.h>
@@ -276,7 +277,7 @@
 
 MACHINE_START(NOMADIK, "NHK8815")
 	/* Maintainer: ST MicroElectronics */
-	.boot_params	= 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= cpu8815_map_io,
 	.init_irq	= cpu8815_init_irq,
 	.timer		= &nomadik_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nomadik/cpu-8815.c linux-libre-3.2-gnu/arch/arm/mach-nomadik/cpu-8815.c
--- linux-libre-3.1-gnu/arch/arm/mach-nomadik/cpu-8815.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nomadik/cpu-8815.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,8 +21,8 @@
 #include <linux/device.h>
 #include <linux/amba/bus.h>
 #include <linux/platform_device.h>
-#include <linux/gpio.h>
 
+#include <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <asm/mach/map.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nomadik/i2c-8815nhk.c linux-libre-3.2-gnu/arch/arm/mach-nomadik/i2c-8815nhk.c
--- linux-libre-3.1-gnu/arch/arm/mach-nomadik/i2c-8815nhk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nomadik/i2c-8815nhk.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,8 +3,8 @@
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 #include <linux/i2c-gpio.h>
-#include <linux/gpio.h>
 #include <linux/platform_device.h>
+#include <plat/gpio-nomadik.h>
 
 /*
  * There are two busses in the 8815NHK.
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nomadik/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-nomadik/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-nomadik/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nomadik/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  *
 */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x00100000
 		add	\rp, \rp, #0x000fb000
 		add	\rv, \rp, #0xf0000000	@ virtual base
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nomadik/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-nomadik/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-nomadik/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nomadik/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,4 @@
 #ifndef __ASM_ARCH_GPIO_H
 #define __ASM_ARCH_GPIO_H
 
-#include <plat/gpio.h>
-
 #endif /* __ASM_ARCH_GPIO_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nomadik/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-nomadik/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-nomadik/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nomadik/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- *  mach-nomadik/include/mach/memory.h
- *
- *  Copyright (C) 1999 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nomadik/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-nomadik/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-nomadik/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nomadik/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/clock.c linux-libre-3.2-gnu/arch/arm/mach-nuc93x/clock.c
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/clock.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/clock.c
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/spinlock.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-
-#include "clock.h"
-
-static DEFINE_SPINLOCK(clocks_lock);
-
-int clk_enable(struct clk *clk)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&clocks_lock, flags);
-	if (clk->enabled++ == 0)
-		(clk->enable)(clk, 1);
-	spin_unlock_irqrestore(&clocks_lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-	unsigned long flags;
-
-	WARN_ON(clk->enabled == 0);
-
-	spin_lock_irqsave(&clocks_lock, flags);
-	if (--clk->enabled == 0)
-		(clk->enable)(clk, 0);
-	spin_unlock_irqrestore(&clocks_lock, flags);
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	return 27000000;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-void nuc93x_clk_enable(struct clk *clk, int enable)
-{
-	unsigned int clocks = clk->cken;
-	unsigned long clken;
-
-	clken = __raw_readl(NUC93X_VA_CLKPWR);
-
-	if (enable)
-		clken |= clocks;
-	else
-		clken &= ~clocks;
-
-	__raw_writel(clken, NUC93X_VA_CLKPWR);
-}
-
-void clks_register(struct clk_lookup *clks, size_t num)
-{
-	int i;
-
-	for (i = 0; i < num; i++)
-		clkdev_add(&clks[i]);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/clock.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/clock.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/clock.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
- */
-
-#include <linux/clkdev.h>
-
-void nuc93x_clk_enable(struct clk *clk, int enable);
-void clks_register(struct clk_lookup *clks, size_t num);
-
-struct clk {
-	unsigned long		cken;
-	unsigned int		enabled;
-	void			(*enable)(struct clk *, int enable);
-};
-
-#define DEFINE_CLK(_name, _ctrlbit)			\
-struct clk clk_##_name = {				\
-		.enable	= nuc93x_clk_enable,		\
-		.cken	= (1 << _ctrlbit),		\
-	}
-
-#define DEF_CLKLOOK(_clk, _devname, _conname)		\
-	{						\
-		.clk		= _clk,			\
-		.dev_id		= _devname,		\
-		.con_id		= _conname,		\
-	}
-
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/cpu.c linux-libre-3.2-gnu/arch/arm/mach-nuc93x/cpu.c
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/cpu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,135 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/cpu.c
- *
- * Copyright (c) 2009 Nuvoton corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * NUC93x series cpu common support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/serial_8250.h>
-#include <linux/delay.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-serial.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-ebi.h>
-
-#include "cpu.h"
-#include "clock.h"
-
-/* Initial IO mappings */
-
-static struct map_desc nuc93x_iodesc[] __initdata = {
-	IODESC_ENT(IRQ),
-	IODESC_ENT(GCR),
-	IODESC_ENT(UART),
-	IODESC_ENT(TIMER),
-	IODESC_ENT(EBI),
-};
-
-/* Initial nuc932 clock declarations. */
-static DEFINE_CLK(audio, 2);
-static DEFINE_CLK(sd, 3);
-static DEFINE_CLK(jpg, 4);
-static DEFINE_CLK(video, 5);
-static DEFINE_CLK(vpost, 6);
-static DEFINE_CLK(2d, 7);
-static DEFINE_CLK(gpu, 8);
-static DEFINE_CLK(gdma, 9);
-static DEFINE_CLK(adc, 10);
-static DEFINE_CLK(uart, 11);
-static DEFINE_CLK(spi, 12);
-static DEFINE_CLK(pwm, 13);
-static DEFINE_CLK(timer, 14);
-static DEFINE_CLK(wdt, 15);
-static DEFINE_CLK(ac97, 16);
-static DEFINE_CLK(i2s, 16);
-static DEFINE_CLK(usbck, 17);
-static DEFINE_CLK(usb48, 18);
-static DEFINE_CLK(usbh, 19);
-static DEFINE_CLK(i2c, 20);
-static DEFINE_CLK(ext, 0);
-
-static struct clk_lookup nuc932_clkregs[] = {
-       DEF_CLKLOOK(&clk_audio, "nuc932-audio", NULL),
-       DEF_CLKLOOK(&clk_sd, "nuc932-sd", NULL),
-       DEF_CLKLOOK(&clk_jpg, "nuc932-jpg", "NULL"),
-       DEF_CLKLOOK(&clk_video, "nuc932-video", "NULL"),
-       DEF_CLKLOOK(&clk_vpost, "nuc932-vpost", NULL),
-       DEF_CLKLOOK(&clk_2d, "nuc932-2d", NULL),
-       DEF_CLKLOOK(&clk_gpu, "nuc932-gpu", NULL),
-       DEF_CLKLOOK(&clk_gdma, "nuc932-gdma", "NULL"),
-       DEF_CLKLOOK(&clk_adc, "nuc932-adc", NULL),
-       DEF_CLKLOOK(&clk_uart, NULL, "uart"),
-       DEF_CLKLOOK(&clk_spi, "nuc932-spi", NULL),
-       DEF_CLKLOOK(&clk_pwm, "nuc932-pwm", NULL),
-       DEF_CLKLOOK(&clk_timer, NULL, "timer"),
-       DEF_CLKLOOK(&clk_wdt, "nuc932-wdt", NULL),
-       DEF_CLKLOOK(&clk_ac97, "nuc932-ac97", NULL),
-       DEF_CLKLOOK(&clk_i2s, "nuc932-i2s", NULL),
-       DEF_CLKLOOK(&clk_usbck, "nuc932-usbck", NULL),
-       DEF_CLKLOOK(&clk_usb48, "nuc932-usb48", NULL),
-       DEF_CLKLOOK(&clk_usbh, "nuc932-usbh", NULL),
-       DEF_CLKLOOK(&clk_i2c, "nuc932-i2c", NULL),
-       DEF_CLKLOOK(&clk_ext, NULL, "ext"),
-};
-
-/* Initial serial platform data */
-
-struct plat_serial8250_port nuc93x_uart_data[] = {
-	NUC93X_8250PORT(UART0),
-	{},
-};
-
-struct platform_device nuc93x_serial_device = {
-	.name			= "serial8250",
-	.id			= PLAT8250_DEV_PLATFORM,
-	.dev			= {
-		.platform_data	= nuc93x_uart_data,
-	},
-};
-
-/*Init NUC93x evb io*/
-
-void __init nuc93x_map_io(struct map_desc *mach_desc, int mach_size)
-{
-	unsigned long idcode = 0x0;
-
-	iotable_init(mach_desc, mach_size);
-	iotable_init(nuc93x_iodesc, ARRAY_SIZE(nuc93x_iodesc));
-
-	idcode = __raw_readl(NUC93XPDID);
-	if (idcode == NUC932_CPUID)
-		printk(KERN_INFO "CPU type 0x%08lx is NUC910\n", idcode);
-	else
-		printk(KERN_ERR "CPU type detect error!\n");
-
-}
-
-/*Init NUC93x clock*/
-
-void __init nuc93x_init_clocks(void)
-{
-	clks_register(nuc932_clkregs, ARRAY_SIZE(nuc932_clkregs));
-}
-
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/cpu.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/cpu.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/cpu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/cpu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,48 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/cpu.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Header file for NUC93X CPU support
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#define IODESC_ENT(y)					\
-{							\
-	.virtual = (unsigned long)NUC93X_VA_##y,	\
-	.pfn     = __phys_to_pfn(NUC93X_PA_##y),	\
-	.length  = NUC93X_SZ_##y,			\
-	.type    = MT_DEVICE,				\
-}
-
-#define NUC93X_8250PORT(name)					\
-{								\
-	.membase	= name##_BA,				\
-	.mapbase	= name##_PA,				\
-	.irq		= IRQ_##name,				\
-	.uartclk	= 57139200,				\
-	.regshift	= 2,					\
-	.iotype		= UPIO_MEM,				\
-	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,	\
-}
-
-/*Cpu identifier register*/
-
-#define NUC93XPDID	NUC93X_VA_GCR
-#define NUC932_CPUID	0x29550091
-
-/* extern file from cpu.c */
-
-extern void nuc93x_clock_source(struct device *dev, unsigned char *src);
-extern void nuc93x_init_clocks(void);
-extern void nuc93x_map_io(struct map_desc *mach_desc, int mach_size);
-extern void nuc93x_board_init(struct platform_device **device, int size);
-extern struct platform_device nuc93x_serial_device;
-
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/dev.c linux-libre-3.2-gnu/arch/arm/mach-nuc93x/dev.c
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/dev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/dev.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/dev.c
- *
- * Copyright (C) 2009 Nuvoton corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation;version 2 of the License.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/mach-types.h>
-
-#include "cpu.h"
-
-/*Here should be your evb resourse,such as LCD*/
-
-static struct platform_device *nuc93x_public_dev[] __initdata = {
-	&nuc93x_serial_device,
-};
-
-/* Provide adding specific CPU platform devices API */
-
-void __init nuc93x_board_init(struct platform_device **device, int size)
-{
-	platform_add_devices(device, size);
-	platform_add_devices(nuc93x_public_dev, ARRAY_SIZE(nuc93x_public_dev));
-}
-
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/entry-macro.S linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/entry-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/entry-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/entry-macro.S
- *
- * 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/regs-irq.h>
-
-	.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	\base, #AIC_BA
-
-		ldr	\irqnr, [ \base, #AIC_IPER]
-		ldr	\irqnr, [ \base, #AIC_ISNR]
-		cmp	\irqnr, #0
-
-	.endm
-
-	/* currently don't need an disable_fiq macro */
-
-	.macro	disable_fiq
-	.endm
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/hardware.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/hardware.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/hardware.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/hardware.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <asm/sizes.h>
-#include <mach/map.h>
-
-#endif /* __ASM_ARCH_HARDWARE_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/io.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/io.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/io.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT	0xffffffff
-
-/*
- * 1:1 mapping for ioremapped regions.
- */
-
-#define __mem_pci(a)	(a)
-#define __io(a)		__typesafe_io(a)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/irqs.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/irqs.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,59 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/irqs.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-#define NUC93X_IRQ(x)	(x)
-
-/* Main cpu interrupts */
-
-#define IRQ_WDT		NUC93X_IRQ(1)
-#define IRQ_IRQ0	NUC93X_IRQ(2)
-#define IRQ_IRQ1	NUC93X_IRQ(3)
-#define IRQ_IRQ2	NUC93X_IRQ(4)
-#define IRQ_IRQ3	NUC93X_IRQ(5)
-#define IRQ_USBH	NUC93X_IRQ(6)
-#define IRQ_APU		NUC93X_IRQ(7)
-#define IRQ_VPOST	NUC93X_IRQ(8)
-#define IRQ_ADC		NUC93X_IRQ(9)
-#define IRQ_UART0	NUC93X_IRQ(10)
-#define IRQ_TIMER0	NUC93X_IRQ(11)
-#define IRQ_GPU0	NUC93X_IRQ(12)
-#define IRQ_GPU1	NUC93X_IRQ(13)
-#define IRQ_GPU2	NUC93X_IRQ(14)
-#define IRQ_GPU3	NUC93X_IRQ(15)
-#define IRQ_GPU4	NUC93X_IRQ(16)
-#define IRQ_VIN		NUC93X_IRQ(17)
-#define IRQ_USBD	NUC93X_IRQ(18)
-#define IRQ_VRAMLD	NUC93X_IRQ(19)
-#define IRQ_GDMA0	NUC93X_IRQ(20)
-#define IRQ_GDMA1	NUC93X_IRQ(21)
-#define IRQ_SDIO	NUC93X_IRQ(22)
-#define IRQ_FMI		NUC93X_IRQ(22)
-#define IRQ_JPEG	NUC93X_IRQ(23)
-#define IRQ_SPI0	NUC93X_IRQ(24)
-#define IRQ_SPI1	NUC93X_IRQ(25)
-#define IRQ_RTC		NUC93X_IRQ(26)
-#define IRQ_PWM0	NUC93X_IRQ(27)
-#define IRQ_PWM1	NUC93X_IRQ(28)
-#define IRQ_PWM2	NUC93X_IRQ(29)
-#define IRQ_PWM3	NUC93X_IRQ(30)
-#define IRQ_I2SAC97	NUC93X_IRQ(31)
-#define IRQ_CAP0	IRQ_PWM0
-#define IRQ_CAP1	IRQ_PWM1
-#define IRQ_CAP2	IRQ_PWM2
-#define IRQ_CAP3	IRQ_PWM3
-#define NR_IRQS		(IRQ_I2SAC97 + 1)
-
-#endif /* __ASM_ARCH_IRQ_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/map.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/map.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/map.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,139 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/map.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H
-
-#define MAP_OFFSET	(0xfff00000)
-#define CLK_OFFSET	(0x10)
-
-#ifndef __ASSEMBLY__
-#define NUC93X_ADDR(x)	((void __iomem *)(0xF0000000 + ((x)&(~MAP_OFFSET))))
-#else
-#define NUC93X_ADDR(x)	(0xF0000000 + ((x)&(~MAP_OFFSET)))
-#endif
-
- /*
-  * nuc932 hardware register definition
-  */
-
-#define NUC93X_PA_IRQ		(0xFFF83000)
-#define NUC93X_PA_GCR		(0xFFF00000)
-#define NUC93X_PA_EBI		(0xFFF01000)
-#define NUC93X_PA_UART		(0xFFF80000)
-#define NUC93X_PA_TIMER		(0xFFF81000)
-#define NUC93X_PA_GPIO		(0xFFF84000)
-#define NUC93X_PA_GDMA		(0xFFF03000)
-#define NUC93X_PA_USBHOST	(0xFFF0d000)
-#define NUC93X_PA_I2C		(0xFFF89000)
-#define NUC93X_PA_LCD		(0xFFF06000)
-#define NUC93X_PA_GE		(0xFFF05000)
-#define NUC93X_PA_ADC		(0xFFF85000)
-#define NUC93X_PA_RTC		(0xFFF87000)
-#define NUC93X_PA_PWM		(0xFFF82000)
-#define NUC93X_PA_ACTL		(0xFFF0a000)
-#define NUC93X_PA_USBDEV	(0xFFF0C000)
-#define NUC93X_PA_JEPEG		(0xFFF0e000)
-#define NUC93X_PA_CACHE_T	(0xFFF60000)
-#define NUC93X_PA_VRAM		(0xFFF0b000)
-#define NUC93X_PA_DMAC		(0xFFF09000)
-#define NUC93X_PA_I2SM		(0xFFF08000)
-#define NUC93X_PA_CACHE		(0xFFF02000)
-#define NUC93X_PA_GPU		(0xFFF04000)
-#define NUC93X_PA_VIDEOIN	(0xFFF07000)
-#define NUC93X_PA_SPI0		(0xFFF86000)
-#define NUC93X_PA_SPI1		(0xFFF88000)
-
- /*
-  * nuc932 virtual address mapping.
-  * interrupt controller is the first thing we put in, to make
-  * the assembly code for the irq detection easier
-  */
-
-#define NUC93X_VA_IRQ		NUC93X_ADDR(0x00000000)
-#define NUC93X_SZ_IRQ		SZ_4K
-
-#define NUC93X_VA_GCR		NUC93X_ADDR(NUC93X_PA_IRQ)
-#define NUC93X_VA_CLKPWR	(NUC93X_VA_GCR+CLK_OFFSET)
-#define NUC93X_SZ_GCR		SZ_4K
-
-/* EBI management */
-
-#define NUC93X_VA_EBI		NUC93X_ADDR(NUC93X_PA_EBI)
-#define NUC93X_SZ_EBI		SZ_4K
-
-/* UARTs */
-
-#define NUC93X_VA_UART		NUC93X_ADDR(NUC93X_PA_UART)
-#define NUC93X_SZ_UART		SZ_4K
-
-/* Timers */
-
-#define NUC93X_VA_TIMER	NUC93X_ADDR(NUC93X_PA_TIMER)
-#define NUC93X_SZ_TIMER	SZ_4K
-
-/* GPIO ports */
-
-#define NUC93X_VA_GPIO		NUC93X_ADDR(NUC93X_PA_GPIO)
-#define NUC93X_SZ_GPIO		SZ_4K
-
-/* GDMA control */
-
-#define NUC93X_VA_GDMA		NUC93X_ADDR(NUC93X_PA_GDMA)
-#define NUC93X_SZ_GDMA		SZ_4K
-
-/* I2C hardware controller */
-
-#define NUC93X_VA_I2C		NUC93X_ADDR(NUC93X_PA_I2C)
-#define NUC93X_SZ_I2C		SZ_4K
-
-/* LCD controller*/
-
-#define NUC93X_VA_LCD		NUC93X_ADDR(NUC93X_PA_LCD)
-#define NUC93X_SZ_LCD		SZ_4K
-
-/* 2D controller*/
-
-#define NUC93X_VA_GE		NUC93X_ADDR(NUC93X_PA_GE)
-#define NUC93X_SZ_GE		SZ_4K
-
-/* ADC */
-
-#define NUC93X_VA_ADC		NUC93X_ADDR(NUC93X_PA_ADC)
-#define NUC93X_SZ_ADC		SZ_4K
-
-/* RTC */
-
-#define NUC93X_VA_RTC		NUC93X_ADDR(NUC93X_PA_RTC)
-#define NUC93X_SZ_RTC		SZ_4K
-
-/* Pulse Width Modulation(PWM) Registers */
-
-#define NUC93X_VA_PWM		NUC93X_ADDR(NUC93X_PA_PWM)
-#define NUC93X_SZ_PWM		SZ_4K
-
-/* Audio Controller controller */
-
-#define NUC93X_VA_ACTL		NUC93X_ADDR(NUC93X_PA_ACTL)
-#define NUC93X_SZ_ACTL		SZ_4K
-
-/* USB Device port */
-
-#define NUC93X_VA_USBDEV	NUC93X_ADDR(NUC93X_PA_USBDEV)
-#define NUC93X_SZ_USBDEV	SZ_4K
-
-/* USB host controller*/
-#define NUC93X_VA_USBHOST	NUC93X_ADDR(NUC93X_PA_USBHOST)
-#define NUC93X_SZ_USBHOST	SZ_4K
-
-#endif /* __ASM_ARCH_MAP_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/memory.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/regs-clock.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/regs-clock.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/regs-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/regs-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-clock.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_REGS_CLOCK_H
-#define __ASM_ARCH_REGS_CLOCK_H
-
-/* Clock Control Registers  */
-#define CLK_BA		NUC93X_VA_CLKPWR
-#define REG_CLKEN	(CLK_BA + 0x00)
-#define REG_CLKSEL	(CLK_BA + 0x04)
-#define REG_CLKDIV	(CLK_BA + 0x08)
-#define REG_PLLCON0	(CLK_BA + 0x0C)
-#define REG_PLLCON1	(CLK_BA + 0x10)
-#define REG_PMCON	(CLK_BA + 0x14)
-#define REG_IRQWAKECON	(CLK_BA + 0x18)
-#define REG_IRQWAKEFLAG	(CLK_BA + 0x1C)
-#define REG_IPSRST	(CLK_BA + 0x20)
-#define REG_CLKEN1	(CLK_BA + 0x24)
-#define REG_CLKDIV1	(CLK_BA + 0x28)
-
-/* Define PLL freq setting */
-#define PLL_DISABLE		0x12B63
-#define	PLL_66MHZ		0x2B63
-#define	PLL_100MHZ		0x4F64
-#define PLL_120MHZ		0x4F63
-#define	PLL_166MHZ		0x4124
-#define	PLL_200MHZ		0x4F24
-
-/* Define AHB:CPUFREQ ratio */
-#define	AHB_CPUCLK_1_1		0x00
-#define	AHB_CPUCLK_1_2		0x01
-#define	AHB_CPUCLK_1_4		0x02
-#define	AHB_CPUCLK_1_8		0x03
-
-/* Define APB:AHB ratio */
-#define APB_AHB_1_2		0x01
-#define APB_AHB_1_4		0x02
-#define APB_AHB_1_8		0x03
-
-/* Define clock skew */
-#define DEFAULTSKEW		0x48
-
-#endif /*  __ASM_ARCH_REGS_CLOCK_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/regs-ebi.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/regs-ebi.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/regs-ebi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/regs-ebi.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-ebi.h
- *
- * Copyright (c) 2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_REGS_EBI_H
-#define __ASM_ARCH_REGS_EBI_H
-
-/* EBI Control Registers */
-
-#define EBI_BA		NUC93X_VA_EBI
-#define REG_EBICON	(EBI_BA + 0x00)
-#define REG_ROMCON	(EBI_BA + 0x04)
-#define REG_SDCONF0	(EBI_BA + 0x08)
-#define REG_SDCONF1	(EBI_BA + 0x0C)
-#define REG_SDTIME0	(EBI_BA + 0x10)
-#define REG_SDTIME1	(EBI_BA + 0x14)
-#define REG_EXT0CON	(EBI_BA + 0x18)
-#define REG_EXT1CON	(EBI_BA + 0x1C)
-#define REG_EXT2CON	(EBI_BA + 0x20)
-#define REG_EXT3CON	(EBI_BA + 0x24)
-#define REG_EXT4CON	(EBI_BA + 0x28)
-#define REG_CKSKEW	(EBI_BA + 0x2C)
-
-#endif /*  __ASM_ARCH_REGS_EBI_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/regs-irq.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/regs-irq.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/regs-irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/regs-irq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-irq.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef ___ASM_ARCH_REGS_IRQ_H
-#define ___ASM_ARCH_REGS_IRQ_H
-
-/* Advance Interrupt Controller (AIC) Registers */
-
-#define AIC_BA    		NUC93X_VA_IRQ
-
-#define REG_AIC_IRQSC		(AIC_BA+0x80)
-#define REG_AIC_GEN		(AIC_BA+0x84)
-#define REG_AIC_GASR		(AIC_BA+0x88)
-#define REG_AIC_GSCR		(AIC_BA+0x8C)
-#define REG_AIC_IRSR		(AIC_BA+0x100)
-#define REG_AIC_IASR		(AIC_BA+0x104)
-#define REG_AIC_ISR		(AIC_BA+0x108)
-#define REG_AIC_IPER		(AIC_BA+0x10C)
-#define REG_AIC_ISNR		(AIC_BA+0x110)
-#define REG_AIC_IMR		(AIC_BA+0x114)
-#define REG_AIC_OISR		(AIC_BA+0x118)
-#define REG_AIC_MECR		(AIC_BA+0x120)
-#define REG_AIC_MDCR		(AIC_BA+0x124)
-#define REG_AIC_SSCR		(AIC_BA+0x128)
-#define REG_AIC_SCCR		(AIC_BA+0x12C)
-#define REG_AIC_EOSCR		(AIC_BA+0x130)
-#define AIC_IPER		(0x10C)
-#define AIC_ISNR		(0x110)
-
-#endif /* ___ASM_ARCH_REGS_IRQ_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/regs-serial.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/regs-serial.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/regs-serial.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/regs-serial.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-serial.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARM_REGS_SERIAL_H
-#define __ASM_ARM_REGS_SERIAL_H
-
-#define UART0_BA	NUC93X_VA_UART
-#define UART1_BA	(NUC93X_VA_UART+0x100)
-
-#define UART0_PA	NUC93X_PA_UART
-#define UART1_PA	(NUC93X_PA_UART+0x100)
-
-
-#ifndef __ASSEMBLY__
-
-struct nuc93x_uart_clksrc {
-	const char	*name;
-	unsigned int	divisor;
-	unsigned int	min_baud;
-	unsigned int	max_baud;
-};
-
-struct nuc93x_uartcfg {
-	unsigned char	hwport;
-	unsigned char	unused;
-	unsigned short	flags;
-	unsigned long	uart_flags;
-
-	unsigned long	ucon;
-	unsigned long	ulcon;
-	unsigned long	ufcon;
-
-	struct nuc93x_uart_clksrc *clocks;
-	unsigned int	clocks_size;
-};
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __ASM_ARM_REGS_SERIAL_H */
-
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/regs-timer.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/regs-timer.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/regs-timer.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/regs-timer.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-timer.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_REGS_TIMER_H
-#define __ASM_ARCH_REGS_TIMER_H
-
-/* Timer Registers */
-
-#define TMR_BA			NUC93X_VA_TIMER
-#define REG_TCSR0		(TMR_BA+0x00)
-#define REG_TICR0		(TMR_BA+0x08)
-#define REG_TDR0		(TMR_BA+0x10)
-#define REG_TISR		(TMR_BA+0x18)
-#define REG_WTCR		(TMR_BA+0x1C)
-
-#endif /*  __ASM_ARCH_REGS_TIMER_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/system.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/system.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- * arch/arm/machnuc93x/include/mach/system.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/system.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#include <asm/proc-fns.h>
-
-static void arch_idle(void)
-{
-}
-
-static void arch_reset(char mode, const char *cmd)
-{
-	cpu_reset(0);
-}
-
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/timex.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/timex.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/timex.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,25 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/timex.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/timex.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-/* CLOCK_TICK_RATE Now, I don't use it. */
-
-#define CLOCK_TICK_RATE 27000000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/uncompress.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/uncompress.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/uncompress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/uncompress.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/uncompress.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H
-
-/* Defines for UART registers */
-
-#include <mach/regs-serial.h>
-#include <mach/map.h>
-#include <linux/serial_reg.h>
-
-#define arch_decomp_wdog()
-
-#define TX_DONE	(UART_LSR_TEMT | UART_LSR_THRE)
-static u32 * const uart_base = (u32 *)UART0_PA;
-
-static void putc(int ch)
-{
-	/* Check THRE and TEMT bits before we transmit the character.
-	 */
-	while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
-		barrier();
-
-	*uart_base = ch;
-}
-
-static inline void flush(void)
-{
-}
-
-static void arch_decomp_setup(void)
-{
-}
-
-#endif/* __ASM_NUC93X_UNCOMPRESS_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/vmalloc.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/vmalloc.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/include/mach/vmalloc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/vmalloc.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_VMALLOC_H
-#define __ASM_ARCH_VMALLOC_H
-
-#define VMALLOC_END	  0xE0000000UL
-
-#endif /* __ASM_ARCH_VMALLOC_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/irq.c linux-libre-3.2-gnu/arch/arm/mach-nuc93x/irq.c
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/irq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,66 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/irq.c
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/ptrace.h>
-#include <linux/sysdev.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-irq.h>
-
-static void nuc93x_irq_mask(struct irq_data *d)
-{
-	__raw_writel(1 << d->irq, REG_AIC_MDCR);
-}
-
-/*
- * By the w90p910 spec,any irq,only write 1
- * to REG_AIC_EOSCR for ACK
- */
-
-static void nuc93x_irq_ack(struct irq_data *d)
-{
-	__raw_writel(0x01, REG_AIC_EOSCR);
-}
-
-static void nuc93x_irq_unmask(struct irq_data *d)
-{
-	__raw_writel(1 << d->irq, REG_AIC_MECR);
-
-}
-
-static struct irq_chip nuc93x_irq_chip = {
-	.irq_ack	= nuc93x_irq_ack,
-	.irq_mask	= nuc93x_irq_mask,
-	.irq_unmask	= nuc93x_irq_unmask,
-};
-
-void __init nuc93x_init_irq(void)
-{
-	int irqno;
-
-	__raw_writel(0xFFFFFFFE, REG_AIC_MDCR);
-
-	for (irqno = IRQ_WDT; irqno <= NR_IRQS; irqno++) {
-		irq_set_chip_and_handler(irqno, &nuc93x_irq_chip,
-					 handle_level_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/Kconfig linux-libre-3.2-gnu/arch/arm/mach-nuc93x/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-if ARCH_NUC93X
-
-config CPU_NUC932
-	bool
-	help
-	  Support for NUC932 of Nuvoton NUC93X CPUs.
-
-menu "NUC932 Machines"
-
-config MACH_NUC932EVB
-	bool "Nuvoton NUC932 Evaluation Board"
-	default y
-	select CPU_NUC932
-	help
-	   Say Y here if you are using the Nuvoton NUC932EVB
-
-endmenu
-
-endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/mach-nuc932evb.c linux-libre-3.2-gnu/arch/arm/mach-nuc93x/mach-nuc932evb.c
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/mach-nuc932evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/mach-nuc932evb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/*
- * linux/arch/arm/mach-w90x900/mach-nuc910evb.c
- *
- * Based on mach-s3c2410/mach-smdk2410.c by Jonas Dietsche
- *
- * Copyright (C) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation;version 2 of the License.
- *
- */
-
-#include <linux/platform_device.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach-types.h>
-#include <mach/map.h>
-
-#include "nuc932.h"
-
-static void __init nuc932evb_map_io(void)
-{
-	nuc932_map_io();
-	nuc932_init_clocks();
-	nuc932_init_uartclk();
-}
-
-static void __init nuc932evb_init(void)
-{
-	nuc932_board_init();
-}
-
-MACHINE_START(NUC932EVB, "NUC932EVB")
-	/* Maintainer: Wan ZongShun */
-	.boot_params	= 0,
-	.map_io		= nuc932evb_map_io,
-	.init_irq	= nuc93x_init_irq,
-	.init_machine	= nuc932evb_init,
-	.timer		= &nuc93x_timer,
-MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/Makefile linux-libre-3.2-gnu/arch/arm/mach-nuc93x/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y				:= irq.o time.o dev.o cpu.o clock.o
-# NUC932 CPU support files
-
-obj-$(CONFIG_CPU_NUC932)	+= nuc932.o
-
-# machine support
-
-obj-$(CONFIG_MACH_NUC932EVB)	+= mach-nuc932evb.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-nuc93x/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
@@ -1,3 +0,0 @@
-zreladdr-y	:= 0x00008000
-params_phys-y	:= 0x00000100
-
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/nuc932.c linux-libre-3.2-gnu/arch/arm/mach-nuc93x/nuc932.c
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/nuc932.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/nuc932.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/nuc932.c
- *
- * Copyright (c) 2009 Nuvoton corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * NUC932 cpu support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <asm/mach/map.h>
-#include <mach/hardware.h>
-
-#include "cpu.h"
-#include "clock.h"
-
-/* define specific CPU platform device */
-
-static struct platform_device *nuc932_dev[] __initdata = {
-};
-
-/* define specific CPU platform io map */
-
-static struct map_desc nuc932evb_iodesc[] __initdata = {
-};
-
-/*Init NUC932 evb io*/
-
-void __init nuc932_map_io(void)
-{
-	nuc93x_map_io(nuc932evb_iodesc, ARRAY_SIZE(nuc932evb_iodesc));
-}
-
-/*Init NUC932 clock*/
-
-void __init nuc932_init_clocks(void)
-{
-	nuc93x_init_clocks();
-}
-
-/*enable NUC932 uart clock*/
-
-void __init nuc932_init_uartclk(void)
-{
-	struct clk *ck_uart = clk_get(NULL, "uart");
-	BUG_ON(IS_ERR(ck_uart));
-
-	clk_enable(ck_uart);
-}
-
-/*Init NUC932 board info*/
-
-void __init nuc932_board_init(void)
-{
-	nuc93x_board_init(nuc932_dev, ARRAY_SIZE(nuc932_dev));
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/nuc932.h linux-libre-3.2-gnu/arch/arm/mach-nuc93x/nuc932.h
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/nuc932.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/nuc932.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/nuc932.h
- *
- * Copyright (c) 2008 Nuvoton corporation
- *
- * Header file for NUC93x CPU support
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-struct map_desc;
-struct sys_timer;
-
-/* core initialisation functions */
-
-extern void nuc93x_init_irq(void);
-extern struct sys_timer nuc93x_timer;
-
-/* extern file from nuc932.c */
-
-extern void nuc932_board_init(void);
-extern void nuc932_init_clocks(void);
-extern void nuc932_map_io(void);
-extern void nuc932_init_uartclk(void);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-nuc93x/time.c linux-libre-3.2-gnu/arch/arm/mach-nuc93x/time.c
--- linux-libre-3.1-gnu/arch/arm/mach-nuc93x/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-nuc93x/time.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,100 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/time.c
- *
- * Copyright (c) 2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/leds.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-
-#include <mach/system.h>
-#include <mach/map.h>
-#include <mach/regs-timer.h>
-
-#define RESETINT	0x01
-#define PERIOD		(0x01 << 27)
-#define ONESHOT		(0x00 << 27)
-#define COUNTEN		(0x01 << 30)
-#define INTEN		(0x01 << 29)
-
-#define TICKS_PER_SEC	100
-#define PRESCALE	0x63 /* Divider = prescale + 1 */
-
-unsigned int timer0_load;
-
-static unsigned long nuc93x_gettimeoffset(void)
-{
-	return 0;
-}
-
-/*IRQ handler for the timer*/
-
-static irqreturn_t nuc93x_timer_interrupt(int irq, void *dev_id)
-{
-	timer_tick();
-	__raw_writel(0x01, REG_TISR); /* clear TIF0 */
-	return IRQ_HANDLED;
-}
-
-static struct irqaction nuc93x_timer_irq = {
-	.name		= "nuc93x Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= nuc93x_timer_interrupt,
-};
-
-/*Set up timer reg.*/
-
-static void nuc93x_timer_setup(void)
-{
-	struct clk *ck_ext = clk_get(NULL, "ext");
-	struct clk *ck_timer = clk_get(NULL, "timer");
-	unsigned int rate, val = 0;
-
-	BUG_ON(IS_ERR(ck_ext) || IS_ERR(ck_timer));
-
-	clk_enable(ck_timer);
-	rate = clk_get_rate(ck_ext);
-	clk_put(ck_ext);
-	rate = rate / (PRESCALE + 0x01);
-
-	 /* set a known state */
-	__raw_writel(0x00, REG_TCSR0);
-	__raw_writel(RESETINT, REG_TISR);
-
-	timer0_load = (rate / TICKS_PER_SEC);
-	__raw_writel(timer0_load, REG_TICR0);
-
-	val |= (PERIOD | COUNTEN | INTEN | PRESCALE);;
-	__raw_writel(val, REG_TCSR0);
-
-}
-
-static void __init nuc93x_timer_init(void)
-{
-	nuc93x_timer_setup();
-	setup_irq(IRQ_TIMER0, &nuc93x_timer_irq);
-}
-
-struct sys_timer nuc93x_timer = {
-	.init		= nuc93x_timer_init,
-	.offset		= nuc93x_gettimeoffset,
-	.resume		= nuc93x_timer_setup
-};
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-ams-delta.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-ams-delta.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-ams-delta.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-ams-delta.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  * 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/kernel.h>
 #include <linux/init.h>
 #include <linux/input.h>
@@ -19,6 +19,7 @@
 #include <linux/leds.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
+#include <linux/export.h>
 
 #include <media/soc_camera.h>
 
@@ -30,7 +31,6 @@
 
 #include <plat/io.h>
 #include <plat/board-ams-delta.h>
-#include <mach/gpio.h>
 #include <plat/keypad.h>
 #include <plat/mux.h>
 #include <plat/usb.h>
@@ -135,12 +135,6 @@
 	*(volatile __u16 *) AMS_DELTA_LATCH2_VIRT = ams_delta_latch2_reg;
 }
 
-static void __init ams_delta_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static struct map_desc ams_delta_io_desc[] __initdata = {
 	/* AMS_DELTA_LATCH1 */
 	{
@@ -308,8 +302,6 @@
 	omap_cfg_reg(J19_1610_CAM_D6);
 	omap_cfg_reg(J18_1610_CAM_D7);
 
-	iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
-
 	omap_board_config = ams_delta_config;
 	omap_board_config_size = ARRAY_SIZE(ams_delta_config);
 	omap_serial_init();
@@ -381,15 +373,17 @@
 
 static void __init ams_delta_map_io(void)
 {
-	omap1_map_common_io();
+	omap15xx_map_io();
+	iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
 }
 
 MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
 	/* Maintainer: Jonathan McDowell <noodles@earth.li> */
-	.boot_params	= 0x10000100,
+	.atag_offset	= 0x100,
 	.map_io		= ams_delta_map_io,
+	.init_early	= omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= ams_delta_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= ams_delta_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-fsample.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-fsample.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-fsample.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-fsample.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  * 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/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -28,7 +28,6 @@
 #include <asm/mach/map.h>
 
 #include <plat/tc.h>
-#include <mach/gpio.h>
 #include <plat/mux.h>
 #include <plat/flash.h>
 #include <plat/fpga.h>
@@ -297,6 +296,39 @@
 
 static void __init omap_fsample_init(void)
 {
+	/* Early, board-dependent init */
+
+	/*
+	 * Hold GSM Reset until needed
+	 */
+	omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
+
+	/*
+	 * UARTs -> done automagically by 8250 driver
+	 */
+
+	/*
+	 * CSx timings, GPIO Mux ... setup
+	 */
+
+	/* Flash: CS0 timings setup */
+	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
+	omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
+
+	/*
+	 * Ethernet support through the debug board
+	 * CS1 timings setup
+	 */
+	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
+	omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
+
+	/*
+	 * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
+	 * It is used as the Ethernet controller interrupt
+	 */
+	omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF,
+			OMAP7XX_IO_CONF_9);
+
 	fsample_init_smc91x();
 
 	if (gpio_request(FSAMPLE_NAND_RB_GPIO_PIN, "NAND ready") < 0)
@@ -326,12 +358,6 @@
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init omap_fsample_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
 static struct map_desc omap_fsample_io_desc[] __initdata = {
 	{
@@ -350,49 +376,18 @@
 
 static void __init omap_fsample_map_io(void)
 {
-	omap1_map_common_io();
+	omap15xx_map_io();
 	iotable_init(omap_fsample_io_desc,
 		     ARRAY_SIZE(omap_fsample_io_desc));
-
-	/* Early, board-dependent init */
-
-	/*
-	 * Hold GSM Reset until needed
-	 */
-	omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
-
-	/*
-	 * UARTs -> done automagically by 8250 driver
-	 */
-
-	/*
-	 * CSx timings, GPIO Mux ... setup
-	 */
-
-	/* Flash: CS0 timings setup */
-	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
-	omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
-
-	/*
-	 * Ethernet support through the debug board
-	 * CS1 timings setup
-	 */
-	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
-	omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
-
-	/*
-	 * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
-	 * It is used as the Ethernet controller interrupt
-	 */
-	omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF, OMAP7XX_IO_CONF_9);
 }
 
 MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
 /* Maintainer: Brian Swetland <swetland@google.com> */
-	.boot_params	= 0x10000100,
+	.atag_offset	= 0x100,
 	.map_io		= omap_fsample_map_io,
+	.init_early	= omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_fsample_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_fsample_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-generic.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-generic.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-generic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-generic.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
  * 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/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -22,18 +22,11 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/gpio.h>
 #include <plat/mux.h>
 #include <plat/usb.h>
 #include <plat/board.h>
 #include <plat/common.h>
 
-static void __init omap_generic_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 /* assume no Mini-AB port */
 
 #ifdef CONFIG_ARCH_OMAP15XX
@@ -87,17 +80,13 @@
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init omap_generic_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
 	/* Maintainer: Tony Lindgren <tony@atomide.com> */
-	.boot_params	= 0x10000100,
-	.map_io		= omap_generic_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap16xx_map_io,
+	.init_early	= omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_generic_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_generic_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-h2.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-h2.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-h2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-h2.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
  * 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/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
@@ -32,7 +32,6 @@
 #include <linux/smc91x.h>
 
 #include <mach/hardware.h>
-#include <asm/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -373,12 +372,6 @@
 	},
 };
 
-static void __init h2_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static struct omap_usb_config h2_usb_config __initdata = {
 	/* usb1 has a Mini-AB port and external isp1301 transceiver */
 	.otg		= 2,
@@ -454,17 +447,13 @@
 	h2_mmc_init();
 }
 
-static void __init h2_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_H2, "TI-H2")
 	/* Maintainer: Imre Deak <imre.deak@nokia.com> */
-	.boot_params	= 0x10000100,
-	.map_io		= h2_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap16xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= h2_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= h2_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-h2-mmc.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-h2-mmc.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-h2-mmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-h2-mmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,13 +11,12 @@
  * 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/platform_device.h>
 
 #include <linux/i2c/tps65010.h>
 
 #include <plat/mmc.h>
-#include <mach/gpio.h>
 
 #include "board-h2.h"
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-h3.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-h3.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-h3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-h3.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
  * 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/types.h>
 #include <linux/init.h>
 #include <linux/major.h>
@@ -34,7 +34,6 @@
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <mach/hardware.h>
-#include <asm/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -436,23 +435,13 @@
 	h3_mmc_init();
 }
 
-static void __init h3_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
-static void __init h3_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
 	/* Maintainer: Texas Instruments, Inc. */
-	.boot_params	= 0x10000100,
-	.map_io		= h3_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap16xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= h3_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= h3_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-h3-mmc.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-h3-mmc.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-h3-mmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-h3-mmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,13 +11,12 @@
  * 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/platform_device.h>
 
 #include <linux/i2c/tps65010.h>
 
 #include <plat/mmc.h>
-#include <mach/gpio.h>
 
 #include "board-h3.h"
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-htcherald.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-htcherald.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-htcherald.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-htcherald.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,6 @@
  * 02110-1301, USA.
  *
  */
-
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -500,7 +499,7 @@
 
 static void __init htcherald_map_io(void)
 {
-	omap1_map_common_io();
+	omap7xx_map_io();
 
 	/*
 	 * The LCD panel must be disabled and DMA turned off here, as doing
@@ -601,20 +600,14 @@
 #endif
 }
 
-static void __init htcherald_init_irq(void)
-{
-	printk(KERN_INFO "htcherald_init_irq.\n");
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 MACHINE_START(HERALD, "HTC Herald")
 	/* Maintainer: Cory Maccarrone <darkstar6262@gmail.com> */
 	/* Maintainer: wing-linux.sourceforge.net */
-	.boot_params    = 0x10000100,
+	.atag_offset    = 0x100,
 	.map_io         = htcherald_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq       = htcherald_init_irq,
+	.init_irq       = omap1_init_irq,
 	.init_machine   = htcherald_init,
 	.timer          = &omap1_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-innovator.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-innovator.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-innovator.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-innovator.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
  * 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/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -34,7 +34,6 @@
 #include <plat/mux.h>
 #include <plat/flash.h>
 #include <plat/fpga.h>
-#include <mach/gpio.h>
 #include <plat/tc.h>
 #include <plat/usb.h>
 #include <plat/keypad.h>
@@ -289,12 +288,6 @@
 	}
 }
 
-static void __init innovator_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 #ifdef CONFIG_ARCH_OMAP15XX
 static struct omap_usb_config innovator1510_usb_config __initdata = {
 	/* for bundled non-standard host and peripheral cables */
@@ -439,30 +432,32 @@
 	innovator_mmc_init();
 }
 
+/*
+ * REVISIT: Assume 15xx for now, we don't want to do revision check
+ * until later on. The right way to fix this is to set up a different
+ * machine_id for 16xx Innovator, or use device tree.
+ */
 static void __init innovator_map_io(void)
 {
-	omap1_map_common_io();
+	omap15xx_map_io();
 
-#ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap1510()) {
-		iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc));
-		udelay(10);	/* Delay needed for FPGA */
+	iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc));
+	udelay(10);	/* Delay needed for FPGA */
 
-		/* Dump the Innovator FPGA rev early - useful info for support. */
-		printk("Innovator FPGA Rev %d.%d Board Rev %d\n",
-		       fpga_read(OMAP1510_FPGA_REV_HIGH),
-		       fpga_read(OMAP1510_FPGA_REV_LOW),
-		       fpga_read(OMAP1510_FPGA_BOARD_REV));
-	}
-#endif
+	/* Dump the Innovator FPGA rev early - useful info for support. */
+	pr_debug("Innovator FPGA Rev %d.%d Board Rev %d\n",
+			fpga_read(OMAP1510_FPGA_REV_HIGH),
+			fpga_read(OMAP1510_FPGA_REV_LOW),
+			fpga_read(OMAP1510_FPGA_BOARD_REV));
 }
 
 MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
 	/* Maintainer: MontaVista Software, Inc. */
-	.boot_params	= 0x10000100,
+	.atag_offset	= 0x100,
 	.map_io		= innovator_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= innovator_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= innovator_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-nokia770.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-nokia770.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-nokia770.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-nokia770.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * 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/kernel.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
@@ -26,7 +26,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/gpio.h>
 #include <plat/mux.h>
 #include <plat/usb.h>
 #include <plat/board.h>
@@ -39,21 +38,6 @@
 
 #define ADS7846_PENDOWN_GPIO	15
 
-static void __init omap_nokia770_init_irq(void)
-{
-	/* On Nokia 770, the SleepX signal is masked with an
-	 * MPUIO line by default.  It has to be unmasked for it
-	 * to become functional */
-
-	/* SleepX mask direction */
-	omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
-	/* Unmask SleepX signal */
-	omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
-
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static const unsigned int nokia770_keymap[] = {
 	KEY(1, 0, GROUP_0 | KEY_UP),
 	KEY(2, 0, GROUP_1 | KEY_F5),
@@ -246,6 +230,15 @@
 
 static void __init omap_nokia770_init(void)
 {
+	/* On Nokia 770, the SleepX signal is masked with an
+	 * MPUIO line by default.  It has to be unmasked for it
+	 * to become functional */
+
+	/* SleepX mask direction */
+	omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
+	/* Unmask SleepX signal */
+	omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
+
 	platform_add_devices(nokia770_devices, ARRAY_SIZE(nokia770_devices));
 	spi_register_board_info(nokia770_spi_board_info,
 				ARRAY_SIZE(nokia770_spi_board_info));
@@ -258,16 +251,12 @@
 	nokia770_mmc_init();
 }
 
-static void __init omap_nokia770_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(NOKIA770, "Nokia 770")
-	.boot_params	= 0x10000100,
-	.map_io		= omap_nokia770_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap16xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_nokia770_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_nokia770_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-osk.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-osk.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-osk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-osk.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,7 +25,7 @@
  * with this program; if not, write  to the Free Software Foundation, Inc.,
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -42,7 +42,6 @@
 #include <linux/i2c/tps65010.h>
 
 #include <mach/hardware.h>
-#include <asm/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -279,12 +278,6 @@
 	irq_set_irq_type(gpio_to_irq(62), IRQ_TYPE_EDGE_FALLING);
 }
 
-static void __init osk_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static struct omap_usb_config osk_usb_config __initdata = {
 	/* has usb host connector (A) ... for development it can also
 	 * be used, with a NONSTANDARD gender-bending cable/dongle, as
@@ -576,17 +569,13 @@
 	osk_mistral_init();
 }
 
-static void __init osk_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_OSK, "TI-OSK")
 	/* Maintainer: Dirk Behme <dirk.behme@de.bosch.com> */
-	.boot_params	= 0x10000100,
-	.map_io		= osk_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap16xx_map_io,
+	.init_early	= omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= osk_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= osk_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-palmte.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-palmte.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-palmte.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-palmte.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
  * 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/kernel.h>
 #include <linux/init.h>
 #include <linux/input.h>
@@ -33,7 +33,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/gpio.h>
 #include <plat/flash.h>
 #include <plat/mux.h>
 #include <plat/usb.h>
@@ -59,12 +58,6 @@
 #define PALMTE_MMC2_GPIO	OMAP_MPUIO(7)
 #define PALMTE_MMC3_GPIO	OMAP_MPUIO(11)
 
-static void __init omap_palmte_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static const unsigned int palmte_keymap[] = {
 	KEY(0, 0, KEY_F1),		/* Calendar */
 	KEY(1, 0, KEY_F2),		/* Contacts */
@@ -269,16 +262,12 @@
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init omap_palmte_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
-	.boot_params	= 0x10000100,
-	.map_io		= omap_palmte_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap15xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_palmte_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_palmte_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-palmtt.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-palmtt.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-palmtt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-palmtt.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -30,7 +31,6 @@
 #include <asm/mach/map.h>
 
 #include <plat/led.h>
-#include <mach/gpio.h>
 #include <plat/flash.h>
 #include <plat/mux.h>
 #include <plat/usb.h>
@@ -263,12 +263,6 @@
 	}
 };
 
-static void __init omap_palmtt_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static struct omap_usb_config palmtt_usb_config __initdata = {
 	.register_dev	= 1,
 	.hmc_mode	= 0,
@@ -315,16 +309,12 @@
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init omap_palmtt_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T")
-	.boot_params	= 0x10000100,
-	.map_io		= omap_palmtt_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap15xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_palmtt_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_palmtt_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-palmz71.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-palmz71.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-palmz71.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-palmz71.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -32,7 +33,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/gpio.h>
 #include <plat/flash.h>
 #include <plat/mux.h>
 #include <plat/usb.h>
@@ -42,7 +42,6 @@
 #include <plat/irda.h>
 #include <plat/keypad.h>
 #include <plat/common.h>
-#include <plat/omap-alsa.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
@@ -57,13 +56,6 @@
 #define PALMZ71_SLIDER_GPIO	OMAP_MPUIO(3)
 #define PALMZ71_MMC_IN_GPIO	OMAP_MPUIO(4)
 
-static void __init
-omap_palmz71_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static const unsigned int palmz71_keymap[] = {
 	KEY(0, 0, KEY_F1),
 	KEY(1, 0, KEY_F2),
@@ -334,17 +326,12 @@
 	palmz71_gpio_setup(0);
 }
 
-static void __init
-omap_palmz71_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71")
-	.boot_params	= 0x10000100,
-	.map_io		= omap_palmz71_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap15xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_palmz71_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_palmz71_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-perseus2.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-perseus2.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-perseus2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-perseus2.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  * 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/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -28,7 +28,6 @@
 #include <asm/mach/map.h>
 
 #include <plat/tc.h>
-#include <mach/gpio.h>
 #include <plat/mux.h>
 #include <plat/fpga.h>
 #include <plat/flash.h>
@@ -265,6 +264,39 @@
 
 static void __init omap_perseus2_init(void)
 {
+	/* Early, board-dependent init */
+
+	/*
+	 * Hold GSM Reset until needed
+	 */
+	omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
+
+	/*
+	 * UARTs -> done automagically by 8250 driver
+	 */
+
+	/*
+	 * CSx timings, GPIO Mux ... setup
+	 */
+
+	/* Flash: CS0 timings setup */
+	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
+	omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
+
+	/*
+	 * Ethernet support through the debug board
+	 * CS1 timings setup
+	 */
+	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
+	omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
+
+	/*
+	 * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
+	 * It is used as the Ethernet controller interrupt
+	 */
+	omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF,
+				OMAP7XX_IO_CONF_9);
+
 	perseus2_init_smc91x();
 
 	if (gpio_request(P2_NAND_RB_GPIO_PIN, "NAND ready") < 0)
@@ -294,11 +326,6 @@
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init omap_perseus2_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
 static struct map_desc omap_perseus2_io_desc[] __initdata = {
 	{
@@ -311,49 +338,18 @@
 
 static void __init omap_perseus2_map_io(void)
 {
-	omap1_map_common_io();
+	omap7xx_map_io();
 	iotable_init(omap_perseus2_io_desc,
 		     ARRAY_SIZE(omap_perseus2_io_desc));
-
-	/* Early, board-dependent init */
-
-	/*
-	 * Hold GSM Reset until needed
-	 */
-	omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
-
-	/*
-	 * UARTs -> done automagically by 8250 driver
-	 */
-
-	/*
-	 * CSx timings, GPIO Mux ... setup
-	 */
-
-	/* Flash: CS0 timings setup */
-	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
-	omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
-
-	/*
-	 * Ethernet support through the debug board
-	 * CS1 timings setup
-	 */
-	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
-	omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
-
-	/*
-	 * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
-	 * It is used as the Ethernet controller interrupt
-	 */
-	omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF, OMAP7XX_IO_CONF_9);
 }
 
 MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
 	/* Maintainer: Kevin Hilman <kjh@hilman.org> */
-	.boot_params	= 0x10000100,
+	.atag_offset	= 0x100,
 	.map_io		= omap_perseus2_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_perseus2_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_perseus2_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-sx1.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-sx1.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-sx1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-sx1.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 * 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/kernel.h>
 #include <linux/init.h>
 #include <linux/input.h>
@@ -26,13 +26,13 @@
 #include <linux/types.h>
 #include <linux/i2c.h>
 #include <linux/errno.h>
+#include <linux/export.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/gpio.h>
 #include <plat/flash.h>
 #include <plat/mux.h>
 #include <plat/dma.h>
@@ -407,24 +407,13 @@
 	gpio_direction_output(11, 0);	/*A_SWITCH = 0 */
 	gpio_direction_output(15, 0);	/*A_USB_ON = 0 */
 }
-/*----------------------------------------*/
-static void __init omap_sx1_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-/*----------------------------------------*/
-
-static void __init omap_sx1_map_io(void)
-{
-	omap1_map_common_io();
-}
 
 MACHINE_START(SX1, "OMAP310 based Siemens SX1")
-	.boot_params	= 0x10000100,
-	.map_io		= omap_sx1_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap15xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_sx1_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_sx1_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-sx1-mmc.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-sx1-mmc.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-sx1-mmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-sx1-mmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,11 +12,11 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 
 #include <mach/hardware.h>
 #include <plat/mmc.h>
-#include <mach/gpio.h>
 #include <plat/board-sx1.h>
 
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/board-voiceblue.c linux-libre-3.2-gnu/arch/arm/mach-omap1/board-voiceblue.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/board-voiceblue.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/board-voiceblue.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -24,6 +25,7 @@
 #include <linux/serial_8250.h>
 #include <linux/serial_reg.h>
 #include <linux/smc91x.h>
+#include <linux/export.h>
 
 #include <mach/hardware.h>
 #include <mach/system.h>
@@ -33,7 +35,6 @@
 
 #include <plat/board-voiceblue.h>
 #include <plat/common.h>
-#include <mach/gpio.h>
 #include <plat/flash.h>
 #include <plat/mux.h>
 #include <plat/tc.h>
@@ -159,17 +160,6 @@
 static struct omap_board_config_kernel voiceblue_config[] = {
 };
 
-static void __init voiceblue_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
-static void __init voiceblue_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 #define MACHINE_PANICED		1
 #define MACHINE_REBOOTING	2
 #define MACHINE_REBOOT		4
@@ -301,10 +291,11 @@
 
 MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
 	/* Maintainer: Ladislav Michl <michl@2n.cz> */
-	.boot_params	= 0x10000100,
-	.map_io		= voiceblue_map_io,
+	.atag_offset	= 0x100,
+	.map_io		= omap15xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= voiceblue_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= voiceblue_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/clock_data.c linux-libre-3.2-gnu/arch/arm/mach-omap1/clock_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/clock_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/clock_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
 
 #include <linux/kernel.h>
 #include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
 #include <linux/io.h>
 
 #include <asm/mach-types.h>  /* for machine_is_* */
@@ -767,6 +769,15 @@
 	.clk_disable_unused	= omap1_clk_disable_unused,
 };
 
+static void __init omap1_show_rates(void)
+{
+	pr_notice("Clocking rate (xtal/DPLL1/MPU): "
+			"%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
+		ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
+		ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
+		arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
+}
+
 int __init omap1_clk_init(void)
 {
 	struct omap_clk *c;
@@ -835,9 +846,12 @@
 	/* We want to be in syncronous scalable mode */
 	omap_writew(0x1000, ARM_SYSST);
 
-#ifdef CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER
-	/* Use values set by bootloader. Determine PLL rate and recalculate
-	 * dependent clocks as if kernel had changed PLL or divisors.
+
+	/*
+	 * Initially use the values set by bootloader. Determine PLL rate and
+	 * recalculate dependent clocks as if kernel had changed PLL or
+	 * divisors. See also omap1_clk_late_init() that can reprogram dpll1
+	 * after the SRAM is initialized.
 	 */
 	{
 		unsigned pll_ctl_val = omap_readw(DPLL_CTL);
@@ -862,25 +876,10 @@
 			}
 		}
 	}
-#else
-	/* Find the highest supported frequency and enable it */
-	if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) {
-		printk(KERN_ERR "System frequencies not set. Check your config.\n");
-		/* Guess sane values (60MHz) */
-		omap_writew(0x2290, DPLL_CTL);
-		omap_writew(cpu_is_omap7xx() ? 0x3005 : 0x1005, ARM_CKCTL);
-		ck_dpll1.rate = 60000000;
-	}
-#endif
 	propagate_rate(&ck_dpll1);
 	/* Cache rates for clocks connected to ck_ref (not dpll1) */
 	propagate_rate(&ck_ref);
-	printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): "
-		"%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
-	       ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
-	       ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
-	       arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
-
+	omap1_show_rates();
 	if (machine_is_omap_perseus2() || machine_is_omap_fsample()) {
 		/* Select slicer output as OMAP input clock */
 		omap_writew(omap_readw(OMAP7XX_PCC_UPLD_CTRL) & ~0x1,
@@ -925,3 +924,27 @@
 
 	return 0;
 }
+
+#define OMAP1_DPLL1_SANE_VALUE	60000000
+
+void __init omap1_clk_late_init(void)
+{
+	unsigned long rate = ck_dpll1.rate;
+
+	if (rate >= OMAP1_DPLL1_SANE_VALUE)
+		return;
+
+	/* System booting at unusable rate, force reprogramming of DPLL1 */
+	ck_dpll1_p->rate = 0;
+
+	/* Find the highest supported frequency and enable it */
+	if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) {
+		pr_err("System frequencies not set, using default. Check your config.\n");
+		omap_writew(0x2290, DPLL_CTL);
+		omap_writew(cpu_is_omap7xx() ? 0x2005 : 0x0005, ARM_CKCTL);
+		ck_dpll1.rate = OMAP1_DPLL1_SANE_VALUE;
+	}
+	propagate_rate(&ck_dpll1);
+	omap1_show_rates();
+	loops_per_jiffy = cpufreq_scale(loops_per_jiffy, rate, ck_dpll1.rate);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/clock.h linux-libre-3.2-gnu/arch/arm/mach-omap1/clock.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,8 @@
 
 #include <plat/clock.h>
 
-extern int __init omap1_clk_init(void);
+int omap1_clk_init(void);
+void omap1_clk_late_init(void);
 extern int omap1_clk_enable(struct clk *clk);
 extern void omap1_clk_disable(struct clk *clk);
 extern long omap1_clk_round_rate(struct clk *clk, unsigned long rate);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/devices.c linux-libre-3.2-gnu/arch/arm/mach-omap1/devices.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <linux/dma-mapping.h>
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -21,14 +22,16 @@
 #include <mach/hardware.h>
 #include <asm/mach/map.h>
 
+#include <plat/common.h>
 #include <plat/tc.h>
 #include <plat/board.h>
 #include <plat/mux.h>
-#include <mach/gpio.h>
 #include <plat/mmc.h>
 #include <plat/omap7xx.h>
 #include <plat/mcbsp.h>
 
+#include "clock.h"
+
 /*-------------------------------------------------------------------------*/
 
 #if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE)
@@ -291,6 +294,9 @@
 	if (!cpu_class_is_omap1())
 		return -ENODEV;
 
+	omap_sram_init();
+	omap1_clk_late_init();
+
 	/* please keep these calls, and their implementations above,
 	 * in alphabetical order so they're easier to sort through.
 	 */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/fpga.c linux-libre-3.2-gnu/arch/arm/mach-omap1/fpga.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/fpga.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/fpga.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
@@ -28,7 +29,6 @@
 #include <asm/mach/irq.h>
 
 #include <plat/fpga.h>
-#include <mach/gpio.h>
 
 static void fpga_mask_irq(struct irq_data *d)
 {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-omap1/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -13,13 +13,8 @@
 
 #include <linux/serial_reg.h>
 
-#include <asm/memory.h>
-
 #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
@@ -31,26 +26,24 @@
 		 * the desired UART phys and virt addresses temporarily into
 		 * the omap_uart_phys and omap_uart_virt above.
 		 */
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 
 		/* Use omap_uart_phys/virt if already configured */
-9:		mrc	p15, 0, \rp, c1, c0
-		tst	\rp, #1			@ MMU 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]
-		ldr	\rv, [\rv, #0]
+9:		adr	\rp, 99f		@ get effective addr of 99f
+		ldr	\rv, [\rp]		@ get absolute addr of 99f
+		sub	\rv, \rv, \rp		@ offset between the two
+		ldr	\rp, [\rp, #4]		@ abs addr of omap_uart_phys
+		sub	\tmp, \rp, \rv		@ make it effective
+		ldr	\rp, [\tmp, #0]		@ omap_uart_phys
+		ldr	\rv, [\tmp, #4]		@ omap_uart_virt
 		cmp	\rp, #0			@ is port configured?
 		cmpne	\rv, #0
-		bne	99f			@ already configured
+		bne	100f			@ already configured
 
 		/* Check the debug UART configuration set in uncompress.h */
-		mrc	p15, 0, \rp, c1, c0
-		tst	\rp, #1			@ MMU enabled?
-		ldreq	\rp, =OMAP_UART_INFO	@ MMU not enabled
-		ldrne	\rp, =omap_uart_p2v(OMAP_UART_INFO)	@ MMU enabled
-		ldr	\rp, [\rp, #0]
+		and	\rp, pc, #0xff000000
+		ldr	\rv, =OMAP_UART_INFO_OFS
+		ldr	\rp, [\rp, \rv]
 
 		/* Select the UART to use based on the UART1 scratchpad value */
 10:		cmp	\rp, #0			@ no port configured?
@@ -74,17 +67,18 @@
 
 		/* Store both phys and virt address for the uart */
 98:		add	\rp, \rp, #0xff000000	@ phys base
-		mrc	p15, 0, \rv, c1, c0
-		tst	\rv, #1			@ MMU enabled?
-		ldreq	\rv, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
-		ldrne	\rv, =omap_uart_phys	@ MMU enabled
-		str	\rp, [\rv, #0]
+		str	\rp, [\tmp, #0]		@ omap_uart_phys
 		sub	\rp, \rp, #0xff000000	@ phys base
 		add	\rp, \rp, #0xfe000000	@ virt base
-		add	\rv, \rv, #4		@ omap_uart_lsr
-		str	\rp, [\rv, #0]
+		str	\rp, [\tmp, #4]		@ omap_uart_virt
 		b	9b
-99:
+
+		.align
+99:		.word	.
+		.word	omap_uart_phys
+		.ltorg
+
+100:
 		.endm
 
 		.macro	senduart,rd,rx
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-omap1/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/include/mach/memory.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,4 +2,55 @@
  * arch/arm/mach-omap1/include/mach/memory.h
  */
 
-#include <plat/memory.h>
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PLAT_PHYS_OFFSET		UL(0x10000000)
+
+/*
+ * Bus address is physical address, except for OMAP-1510 Local Bus.
+ * OMAP-1510 bus address is translated into a Local Bus address if the
+ * OMAP bus type is lbus. We do the address translation based on the
+ * device overriding the defaults used in the dma-mapping API.
+ * Note that the is_lbus_device() test is not very efficient on 1510
+ * because of the strncmp().
+ */
+#ifdef CONFIG_ARCH_OMAP15XX
+
+/*
+ * OMAP-1510 Local Bus address offset
+ */
+#define OMAP1510_LB_OFFSET	UL(0x30000000)
+
+#define virt_to_lbus(x)		((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)
+#define lbus_to_virt(x)		((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
+#define is_lbus_device(dev)	(cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0))
+
+#define __arch_pfn_to_dma(dev, pfn)	\
+	({ dma_addr_t __dma = __pfn_to_phys(pfn); \
+	   if (is_lbus_device(dev)) \
+		__dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \
+	   __dma; })
+
+#define __arch_dma_to_pfn(dev, addr)	\
+	({ dma_addr_t __dma = addr;				\
+	   if (is_lbus_device(dev))				\
+		__dma += PHYS_OFFSET - OMAP1510_LB_OFFSET;	\
+	   __phys_to_pfn(__dma);				\
+	})
+
+#define __arch_dma_to_virt(dev, addr)	({ (void *) (is_lbus_device(dev) ? \
+						lbus_to_virt(addr) : \
+						__phys_to_virt(addr)); })
+
+#define __arch_virt_to_dma(dev, addr)	({ unsigned long __addr = (unsigned long)(addr); \
+					   (dma_addr_t) (is_lbus_device(dev) ? \
+						virt_to_lbus(__addr) : \
+						__virt_to_phys(__addr)); })
+
+#endif	/* CONFIG_ARCH_OMAP15XX */
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/io.c linux-libre-3.2-gnu/arch/arm/mach-omap1/io.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/io.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,6 @@
 #include "clock.h"
 
 extern void omap_check_revision(void);
-extern void omap_sram_init(void);
 
 /*
  * The machine specific code may provide the extra mapping besides the
@@ -85,50 +84,45 @@
 #endif
 
 /*
- * Maps common IO regions for omap1. This should only get called from
- * board specific init.
+ * Maps common IO regions for omap1
  */
-void __init omap1_map_common_io(void)
+static void __init omap1_map_common_io(void)
 {
 	iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc));
-
-	/* Normally devicemaps_init() would flush caches and tlb after
-	 * mdesc->map_io(), but we must also do it here because of the CPU
-	 * revision check below.
-	 */
-	local_flush_tlb_all();
-	flush_cache_all();
-
-	/* We want to check CPU revision early for cpu_is_omapxxxx() macros.
-	 * IO space mapping must be initialized before we can do that.
-	 */
-	omap_check_revision();
+}
 
 #if defined (CONFIG_ARCH_OMAP730) || defined (CONFIG_ARCH_OMAP850)
-	if (cpu_is_omap7xx()) {
-		iotable_init(omap7xx_io_desc, ARRAY_SIZE(omap7xx_io_desc));
-	}
+void __init omap7xx_map_io(void)
+{
+	omap1_map_common_io();
+	iotable_init(omap7xx_io_desc, ARRAY_SIZE(omap7xx_io_desc));
+}
 #endif
+
 #ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap15xx()) {
-		iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
-	}
-#endif
-#if defined(CONFIG_ARCH_OMAP16XX)
-	if (cpu_is_omap16xx()) {
-		iotable_init(omap16xx_io_desc, ARRAY_SIZE(omap16xx_io_desc));
-	}
+void __init omap15xx_map_io(void)
+{
+	omap1_map_common_io();
+	iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
+}
 #endif
 
-	omap_sram_init();
+#if defined(CONFIG_ARCH_OMAP16XX)
+void __init omap16xx_map_io(void)
+{
+	omap1_map_common_io();
+	iotable_init(omap16xx_io_desc, ARRAY_SIZE(omap16xx_io_desc));
 }
+#endif
 
 /*
- * Common low-level hardware init for omap1. This should only get called from
- * board specific init.
+ * Common low-level hardware init for omap1.
  */
-void __init omap1_init_common_hw(void)
+void omap1_init_early(void)
 {
+	omap_check_revision();
+	omap_ioremap_init();
+
 	/* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort
 	 * on a Posted Write in the TIPB Bridge".
 	 */
@@ -138,8 +132,8 @@
 	/* Must init clocks early to assure that timer interrupt works
 	 */
 	omap1_clk_init();
-
 	omap1_mux_init();
+	omap_init_consistent_dma_size();
 }
 
 /*
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/irq.c linux-libre-3.2-gnu/arch/arm/mach-omap1/irq.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,7 +35,7 @@
  * with this program; if not, write  to the Free Software Foundation, Inc.,
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/sched.h>
@@ -45,7 +45,6 @@
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
-#include <mach/gpio.h>
 #include <plat/cpu.h>
 
 #define IRQ_BANK(irq) ((irq) >> 5)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/Kconfig linux-libre-3.2-gnu/arch/arm/mach-omap1/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -171,14 +171,6 @@
 comment "OMAP CPU Speed"
 	depends on ARCH_OMAP1
 
-config OMAP_CLOCKS_SET_BY_BOOTLOADER
-	bool "OMAP clocks set by bootloader"
-	depends on ARCH_OMAP1
-	help
-	  Enable this option to prevent the kernel from overriding the clock
-	  frequencies programmed by bootloader for MPU, DSP, MMUs, TC,
-	  internal LCD controller and MPU peripherals.
-
 config OMAP_ARM_216MHZ
 	bool "OMAP ARM 216 MHz CPU (1710 only)"
         depends on ARCH_OMAP1 && ARCH_OMAP16XX
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/leds.c linux-libre-3.2-gnu/arch/arm/mach-omap1/leds.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/leds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/leds.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,13 +3,13 @@
  *
  * OMAP LEDs dispatcher
  */
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 
 #include <asm/leds.h>
 #include <asm/mach-types.h>
 
-#include <mach/gpio.h>
 #include <plat/mux.h>
 
 #include "leds.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/leds-h2p2-debug.c linux-libre-3.2-gnu/arch/arm/mach-omap1/leds-h2p2-debug.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/leds-h2p2-debug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/leds-h2p2-debug.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  * The "surfer" expansion board and H2 sample board also have two-color
  * green+red LEDs (in parallel), used here for timer and idle indicators.
  */
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
 #include <linux/sched.h>
@@ -20,7 +21,6 @@
 #include <asm/mach-types.h>
 
 #include <plat/fpga.h>
-#include <mach/gpio.h>
 
 #include "leds.h"
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/leds-osk.c linux-libre-3.2-gnu/arch/arm/mach-omap1/leds-osk.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/leds-osk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/leds-osk.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,14 +3,13 @@
  *
  * LED driver for OSK with optional Mistral QVGA board
  */
+#include <linux/gpio.h>
 #include <linux/init.h>
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
 #include <asm/system.h>
 
-#include <mach/gpio.h>
-
 #include "leds.h"
 
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/mailbox.c linux-libre-3.2-gnu/arch/arm/mach-omap1/mailbox.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/mailbox.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/mailbox.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  * for more details.
  */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/Makefile linux-libre-3.2-gnu/arch/arm/mach-omap1/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -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 reset.o pm_bus.o
+obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o timer.o
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-omap1/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y		:= 0x10008000
+   zreladdr-y		+= 0x10008000
 params_phys-y		:= 0x10000100
 initrd_phys-y		:= 0x10800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/mcbsp.c linux-libre-3.2-gnu/arch/arm/mach-omap1/mcbsp.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/mcbsp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/mcbsp.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 static int dsp_use;
 static struct clk *api_clk;
 static struct clk *dsp_clk;
+static struct platform_device **omap_mcbsp_devices;
 
 static void omap1_mcbsp_request(unsigned int id)
 {
@@ -78,6 +79,17 @@
 	.free		= omap1_mcbsp_free,
 };
 
+#define OMAP7XX_MCBSP1_BASE	0xfffb1000
+#define OMAP7XX_MCBSP2_BASE	0xfffb1800
+
+#define OMAP1510_MCBSP1_BASE	0xe1011800
+#define OMAP1510_MCBSP2_BASE	0xfffb1000
+#define OMAP1510_MCBSP3_BASE	0xe1017000
+
+#define OMAP1610_MCBSP1_BASE	0xe1011800
+#define OMAP1610_MCBSP2_BASE	0xfffb1000
+#define OMAP1610_MCBSP3_BASE	0xe1017000
+
 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
 struct resource omap7xx_mcbsp_res[][6] = {
 	{
@@ -369,6 +381,39 @@
 #define OMAP16XX_MCBSP_COUNT		0
 #endif
 
+static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
+			struct omap_mcbsp_platform_data *config, int size)
+{
+	int i;
+
+	omap_mcbsp_devices = kzalloc(size * sizeof(struct platform_device *),
+				     GFP_KERNEL);
+	if (!omap_mcbsp_devices) {
+		printk(KERN_ERR "Could not register McBSP devices\n");
+		return;
+	}
+
+	for (i = 0; i < size; i++) {
+		struct platform_device *new_mcbsp;
+		int ret;
+
+		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);
+		config[i].reg_size = 2;
+		config[i].reg_step = 2;
+		new_mcbsp->dev.platform_data = &config[i];
+		ret = platform_device_add(new_mcbsp);
+		if (ret) {
+			platform_device_put(new_mcbsp);
+			continue;
+		}
+		omap_mcbsp_devices[i] = new_mcbsp;
+	}
+}
+
 static int __init omap1_mcbsp_init(void)
 {
 	if (!cpu_class_is_omap1())
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/pm_bus.c linux-libre-3.2-gnu/arch/arm/mach-omap1/pm_bus.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/pm_bus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/pm_bus.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
+#include <linux/pm_clock.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
 #include <linux/clk.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/pm.c linux-libre-3.2-gnu/arch/arm/mach-omap1/pm.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -116,7 +116,7 @@
 		return;
 	}
 
-#ifdef CONFIG_OMAP_MPU_TIMER
+#if defined(CONFIG_OMAP_MPU_TIMER) && !defined(CONFIG_OMAP_DM_TIMER)
 #warning Enable 32kHz OS timer in order to allow sleep states in idle
 	use_idlect1 = use_idlect1 & ~(1 << 9);
 #else
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/serial.c linux-libre-3.2-gnu/arch/arm/mach-omap1/serial.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/serial.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/serial.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * 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/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -24,7 +24,6 @@
 
 #include <plat/board.h>
 #include <plat/mux.h>
-#include <mach/gpio.h>
 #include <plat/fpga.h>
 
 #include "pm.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap1/timer.c linux-libre-3.2-gnu/arch/arm/mach-omap1/timer.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap1/timer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-omap1/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,173 @@
+/**
+ * OMAP1 Dual-Mode Timers - platform device registration
+ *
+ * Contains first level initialization routines which internally
+ * generates timer device information and registers with linux
+ * device model. It also has low level function to chnage the timer
+ * input clock source.
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * 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.
+ *
+ * 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/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+
+#include <plat/dmtimer.h>
+
+#define OMAP1610_GPTIMER1_BASE		0xfffb1400
+#define OMAP1610_GPTIMER2_BASE		0xfffb1c00
+#define OMAP1610_GPTIMER3_BASE		0xfffb2400
+#define OMAP1610_GPTIMER4_BASE		0xfffb2c00
+#define OMAP1610_GPTIMER5_BASE		0xfffb3400
+#define OMAP1610_GPTIMER6_BASE		0xfffb3c00
+#define OMAP1610_GPTIMER7_BASE		0xfffb7400
+#define OMAP1610_GPTIMER8_BASE		0xfffbd400
+
+#define OMAP1_DM_TIMER_COUNT		8
+
+static int omap1_dm_timer_set_src(struct platform_device *pdev,
+				int source)
+{
+	int n = (pdev->id - 1) << 1;
+	u32 l;
+
+	l = __raw_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
+	l |= source << n;
+	__raw_writel(l, MOD_CONF_CTRL_1);
+
+	return 0;
+}
+
+
+int __init omap1_dm_timer_init(void)
+{
+	int i;
+	int ret;
+	struct dmtimer_platform_data *pdata;
+	struct platform_device *pdev;
+
+	if (!cpu_is_omap16xx())
+		return 0;
+
+	for (i = 1; i <= OMAP1_DM_TIMER_COUNT; i++) {
+		struct resource res[2];
+		u32 base, irq;
+
+		switch (i) {
+		case 1:
+			base = OMAP1610_GPTIMER1_BASE;
+			irq = INT_1610_GPTIMER1;
+			break;
+		case 2:
+			base = OMAP1610_GPTIMER2_BASE;
+			irq = INT_1610_GPTIMER2;
+			break;
+		case 3:
+			base = OMAP1610_GPTIMER3_BASE;
+			irq = INT_1610_GPTIMER3;
+			break;
+		case 4:
+			base = OMAP1610_GPTIMER4_BASE;
+			irq = INT_1610_GPTIMER4;
+			break;
+		case 5:
+			base = OMAP1610_GPTIMER5_BASE;
+			irq = INT_1610_GPTIMER5;
+			break;
+		case 6:
+			base = OMAP1610_GPTIMER6_BASE;
+			irq = INT_1610_GPTIMER6;
+			break;
+		case 7:
+			base = OMAP1610_GPTIMER7_BASE;
+			irq = INT_1610_GPTIMER7;
+			break;
+		case 8:
+			base = OMAP1610_GPTIMER8_BASE;
+			irq = INT_1610_GPTIMER8;
+			break;
+		default:
+			/*
+			 * not supposed to reach here.
+			 * this is to remove warning.
+			 */
+			return -EINVAL;
+		}
+
+		pdev = platform_device_alloc("omap_timer", i);
+		if (!pdev) {
+			pr_err("%s: Failed to device alloc for dmtimer%d\n",
+				__func__, i);
+			return -ENOMEM;
+		}
+
+		memset(res, 0, 2 * sizeof(struct resource));
+		res[0].start = base;
+		res[0].end = base + 0x46;
+		res[0].flags = IORESOURCE_MEM;
+		res[1].start = irq;
+		res[1].end = irq;
+		res[1].flags = IORESOURCE_IRQ;
+		ret = platform_device_add_resources(pdev, res,
+				ARRAY_SIZE(res));
+		if (ret) {
+			dev_err(&pdev->dev, "%s: Failed to add resources.\n",
+				__func__);
+			goto err_free_pdev;
+		}
+
+		pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+		if (!pdata) {
+			dev_err(&pdev->dev, "%s: Failed to allocate pdata.\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err_free_pdata;
+		}
+
+		pdata->set_timer_src = omap1_dm_timer_set_src;
+		pdata->needs_manual_reset = 1;
+
+		ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+		if (ret) {
+			dev_err(&pdev->dev, "%s: Failed to add platform data.\n",
+				__func__);
+			goto err_free_pdata;
+		}
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: Failed to add platform device.\n",
+				__func__);
+			goto err_free_pdata;
+		}
+
+		dev_dbg(&pdev->dev, " Registered.\n");
+	}
+
+	return 0;
+
+err_free_pdata:
+	kfree(pdata);
+
+err_free_pdev:
+	platform_device_unregister(pdev);
+
+	return ret;
+}
+arch_initcall(omap1_dm_timer_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-2430sdp.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-2430sdp.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-2430sdp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-2430sdp.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,9 @@
 #include <plat/usb.h>
 #include <plat/gpmc-smc91x.h>
 
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
 #include "mux.h"
 #include "hsmmc.h"
 #include "common-board-devices.h"
@@ -99,20 +102,72 @@
 	.resource	= &sdp2430_flash_resource,
 };
 
-static struct platform_device sdp2430_lcd_device = {
-	.name		= "sdp2430_lcd",
-	.id		= -1,
-};
-
 static struct platform_device *sdp2430_devices[] __initdata = {
 	&sdp2430_flash_device,
+};
+
+/* LCD */
+#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO	91
+#define SDP2430_LCD_PANEL_ENABLE_GPIO		154
+
+static int sdp2430_panel_enable_lcd(struct omap_dss_device *dssdev)
+{
+	gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 1);
+	gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 1);
+
+	return 0;
+}
+
+static void sdp2430_panel_disable_lcd(struct omap_dss_device *dssdev)
+{
+	gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 0);
+	gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 0);
+}
+
+static struct panel_generic_dpi_data sdp2430_panel_data = {
+	.name			= "nec_nl2432dr22-11b",
+	.platform_enable	= sdp2430_panel_enable_lcd,
+	.platform_disable	= sdp2430_panel_disable_lcd,
+};
+
+static struct omap_dss_device sdp2430_lcd_device = {
+	.name			= "lcd",
+	.driver_name		= "generic_dpi_panel",
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.phy.dpi.data_lines	= 16,
+	.data			= &sdp2430_panel_data,
+};
+
+static struct omap_dss_device *sdp2430_dss_devices[] = {
 	&sdp2430_lcd_device,
 };
 
-static struct omap_lcd_config sdp2430_lcd_config __initdata = {
-	.ctrl_name	= "internal",
+static struct omap_dss_board_info sdp2430_dss_data = {
+	.num_devices	= ARRAY_SIZE(sdp2430_dss_devices),
+	.devices	= sdp2430_dss_devices,
+	.default_device	= &sdp2430_lcd_device,
 };
 
+static void __init sdp2430_display_init(void)
+{
+	int r;
+
+	static struct gpio gpios[] __initdata = {
+		{ SDP2430_LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW,
+			"LCD reset" },
+		{ SDP2430_LCD_PANEL_BACKLIGHT_GPIO, GPIOF_OUT_INIT_LOW,
+			"LCD Backlight" },
+	};
+
+	r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
+	if (r) {
+		pr_err("Cannot request LCD GPIOs, error %d\n", r);
+		return;
+	}
+
+	omap_display_init(&sdp2430_dss_data);
+}
+
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91x_MODULE)
 
 static struct omap_smc91x_platform_data board_smc91x_data = {
@@ -137,16 +192,6 @@
 
 #endif
 
-static struct omap_board_config_kernel sdp2430_config[] __initdata = {
-	{OMAP_TAG_LCD, &sdp2430_lcd_config},
-};
-
-static void __init omap_2430sdp_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 static struct regulator_consumer_supply sdp2430_vmmc1_supplies[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
@@ -229,13 +274,11 @@
 {
 	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));
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	omap2_hsmmc_init(mmc);
 	omap2_usbfs_init(&sdp2430_usb_config);
 
@@ -247,20 +290,16 @@
 	/* Turn off secondary LCD backlight */
 	gpio_request_one(SECONDARY_LCD_GPIO, GPIOF_OUT_INIT_LOW,
 			 "Secondary LCD backlight");
-}
 
-static void __init omap_2430sdp_map_io(void)
-{
-	omap2_set_globals_243x();
-	omap243x_map_common_io();
+	sdp2430_display_init();
 }
 
 MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board")
 	/* Maintainer: Syed Khasim - Texas Instruments Inc */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap_2430sdp_map_io,
-	.init_early	= omap_2430sdp_init_early,
+	.map_io		= omap243x_map_io,
+	.init_early	= omap2430_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= omap_2430sdp_init,
 	.timer		= &omap2_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-3430sdp.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-3430sdp.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-3430sdp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-3430sdp.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,7 +37,7 @@
 #include <plat/dma.h>
 #include <plat/gpmc.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include <plat/gpmc-smc91x.h>
 
@@ -186,8 +186,7 @@
 	.platform_disable	= sdp3430_panel_disable_lcd,
 };
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable	= sdp3430_panel_enable_dvi,
 	.platform_disable	= sdp3430_panel_disable_dvi,
 };
@@ -195,7 +194,7 @@
 static struct omap_dss_device sdp3430_dvi_device = {
 	.name			= "dvi",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
-	.driver_name		= "generic_dpi_panel",
+	.driver_name		= "dvi",
 	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
 };
@@ -225,12 +224,6 @@
 static struct omap_board_config_kernel sdp3430_config[] __initdata = {
 };
 
-static void __init omap_3430sdp_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(hyb18m512160af6_sdrc_params, NULL);
-}
-
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
@@ -719,6 +712,7 @@
 		gpio_pendown = SDP3430_TS_GPIO_IRQ_SDPV1;
 	omap_ads7846_init(1, gpio_pendown, 310, NULL);
 	board_serial_init();
+	omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
 	usb_musb_init(NULL);
 	board_smc91x_init();
 	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
@@ -729,10 +723,10 @@
 
 MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
 	/* Maintainer: Syed Khasim - Texas Instruments Inc */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap_3430sdp_init_early,
+	.init_early	= omap3430_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_3430sdp_init,
 	.timer		= &omap3_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-3630sdp.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-3630sdp.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-3630sdp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-3630sdp.c	2012-01-04 18:55:44.000000000 -0500
@@ -70,13 +70,6 @@
 static struct omap_board_config_kernel sdp_config[] __initdata = {
 };
 
-static void __init omap_sdp_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(h8mbx00u0mer0em_sdrc_params,
-				  h8mbx00u0mer0em_sdrc_params);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
@@ -207,6 +200,8 @@
 	omap_board_config = sdp_config;
 	omap_board_config_size = ARRAY_SIZE(sdp_config);
 	zoom_peripherals_init();
+	omap_sdrc_init(h8mbx00u0mer0em_sdrc_params,
+				  h8mbx00u0mer0em_sdrc_params);
 	zoom_display_init();
 	board_smc91x_init();
 	board_flash_init(sdp_flash_partitions, chip_sel_sdp, NAND_BUSWIDTH_16);
@@ -215,10 +210,10 @@
 }
 
 MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap_sdp_init_early,
+	.init_early	= omap3630_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_sdp_init,
 	.timer		= &omap3_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-4430sdp.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-4430sdp.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-4430sdp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-4430sdp.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,8 @@
 #include <plat/mmc.h>
 #include <plat/omap4-keypad.h>
 #include <video/omapdss.h>
+#include <video/omap-panel-nokia-dsi.h>
+#include <video/omap-panel-picodlp.h>
 #include <linux/wl12xx.h>
 
 #include "mux.h"
@@ -52,6 +54,8 @@
 #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 */
+#define DISPLAY_SEL_GPIO	59	/* LCD2/PicoDLP switch */
+#define DLP_POWER_ON_GPIO	40
 
 #define GPIO_WIFI_PMENA		54
 #define GPIO_WIFI_IRQ		53
@@ -129,7 +133,7 @@
 	KEY(7, 6, KEY_OK),
 	KEY(7, 7, KEY_DOWN),
 };
-static struct omap_device_pad keypad_pads[] __initdata = {
+static struct omap_device_pad keypad_pads[] = {
 	{	.name   = "kpd_col1.kpd_col1",
 		.enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
 	},
@@ -340,11 +344,6 @@
 	return status;
 }
 
-static struct platform_device sdp4430_lcd_device = {
-	.name		= "sdp4430_lcd",
-	.id		= -1,
-};
-
 static struct regulator_consumer_supply sdp4430_vbat_supply[] = {
 	REGULATOR_SUPPLY("vddvibl", "twl6040-vibra"),
 	REGULATOR_SUPPLY("vddvibr", "twl6040-vibra"),
@@ -374,27 +373,12 @@
 };
 
 static struct platform_device *sdp4430_devices[] __initdata = {
-	&sdp4430_lcd_device,
 	&sdp4430_gpio_keys_device,
 	&sdp4430_leds_gpio,
 	&sdp4430_leds_pwm,
 	&sdp4430_vbat,
 };
 
-static struct omap_lcd_config sdp4430_lcd_config __initdata = {
-	.ctrl_name	= "internal",
-};
-
-static struct omap_board_config_kernel sdp4430_config[] __initdata = {
-	{ OMAP_TAG_LCD,		&sdp4430_lcd_config },
-};
-
-static void __init omap_4430sdp_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type		= MUSB_INTERFACE_UTMI,
 	.mode			= MUSB_OTG,
@@ -648,37 +632,202 @@
 	gpio_free(HDMI_GPIO_HPD);
 }
 
-static struct omap_dss_device sdp4430_hdmi_device = {
-	.name = "hdmi",
-	.driver_name = "hdmi_panel",
-	.type = OMAP_DISPLAY_TYPE_HDMI,
-	.clocks	= {
-		.dispc	= {
+static struct nokia_dsi_panel_data dsi1_panel = {
+		.name		= "taal",
+		.reset_gpio	= 102,
+		.use_ext_te	= false,
+		.ext_te_gpio	= 101,
+		.esd_interval	= 0,
+};
+
+static struct omap_dss_device sdp4430_lcd_device = {
+	.name			= "lcd",
+	.driver_name		= "taal",
+	.type			= OMAP_DISPLAY_TYPE_DSI,
+	.data			= &dsi1_panel,
+	.phy.dsi		= {
+		.clk_lane	= 1,
+		.clk_pol	= 0,
+		.data1_lane	= 2,
+		.data1_pol	= 0,
+		.data2_lane	= 3,
+		.data2_pol	= 0,
+
+		.module		= 0,
+	},
+
+	.clocks = {
+		.dispc = {
+			.channel = {
+				/* Logic Clock = 172.8 MHz */
+				.lck_div	= 1,
+				/* Pixel Clock = 34.56 MHz */
+				.pck_div	= 5,
+				.lcd_clk_src	= OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC,
+			},
 			.dispc_fclk_src	= OMAP_DSS_CLK_SRC_FCK,
 		},
-		.hdmi	= {
-			.regn	= 15,
-			.regm2	= 1,
+
+		.dsi = {
+			.regn		= 16,	/* Fint = 2.4 MHz */
+			.regm		= 180,	/* DDR Clock = 216 MHz */
+			.regm_dispc	= 5,	/* PLL1_CLK1 = 172.8 MHz */
+			.regm_dsi	= 5,	/* PLL1_CLK2 = 172.8 MHz */
+
+			.lp_clk_div	= 10,	/* LP Clock = 8.64 MHz */
+			.dsi_fclk_src	= OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI,
 		},
 	},
+	.channel		= OMAP_DSS_CHANNEL_LCD,
+};
+
+static struct nokia_dsi_panel_data dsi2_panel = {
+		.name		= "taal",
+		.reset_gpio	= 104,
+		.use_ext_te	= false,
+		.ext_te_gpio	= 103,
+		.esd_interval	= 0,
+};
+
+static struct omap_dss_device sdp4430_lcd2_device = {
+	.name			= "lcd2",
+	.driver_name		= "taal",
+	.type			= OMAP_DISPLAY_TYPE_DSI,
+	.data			= &dsi2_panel,
+	.phy.dsi		= {
+		.clk_lane	= 1,
+		.clk_pol	= 0,
+		.data1_lane	= 2,
+		.data1_pol	= 0,
+		.data2_lane	= 3,
+		.data2_pol	= 0,
+
+		.module		= 1,
+	},
+
+	.clocks = {
+		.dispc = {
+			.channel = {
+				/* Logic Clock = 172.8 MHz */
+				.lck_div	= 1,
+				/* Pixel Clock = 34.56 MHz */
+				.pck_div	= 5,
+				.lcd_clk_src	= OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC,
+			},
+			.dispc_fclk_src	= OMAP_DSS_CLK_SRC_FCK,
+		},
+
+		.dsi = {
+			.regn		= 16,	/* Fint = 2.4 MHz */
+			.regm		= 180,	/* DDR Clock = 216 MHz */
+			.regm_dispc	= 5,	/* PLL1_CLK1 = 172.8 MHz */
+			.regm_dsi	= 5,	/* PLL1_CLK2 = 172.8 MHz */
+
+			.lp_clk_div	= 10,	/* LP Clock = 8.64 MHz */
+			.dsi_fclk_src	= OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI,
+		},
+	},
+	.channel		= OMAP_DSS_CHANNEL_LCD2,
+};
+
+static void sdp4430_lcd_init(void)
+{
+	int r;
+
+	r = gpio_request_one(dsi1_panel.reset_gpio, GPIOF_DIR_OUT,
+		"lcd1_reset_gpio");
+	if (r)
+		pr_err("%s: Could not get lcd1_reset_gpio\n", __func__);
+
+	r = gpio_request_one(dsi2_panel.reset_gpio, GPIOF_DIR_OUT,
+		"lcd2_reset_gpio");
+	if (r)
+		pr_err("%s: Could not get lcd2_reset_gpio\n", __func__);
+}
+
+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 picodlp_panel_data sdp4430_picodlp_pdata = {
+	.picodlp_adapter_id	= 2,
+	.emu_done_gpio		= 44,
+	.pwrgood_gpio		= 45,
+};
+
+static void sdp4430_picodlp_init(void)
+{
+	int r;
+	const struct gpio picodlp_gpios[] = {
+		{DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW,
+			"DLP POWER ON"},
+		{sdp4430_picodlp_pdata.emu_done_gpio, GPIOF_IN,
+			"DLP EMU DONE"},
+		{sdp4430_picodlp_pdata.pwrgood_gpio, GPIOF_OUT_INIT_LOW,
+			"DLP PWRGOOD"},
+	};
+
+	r = gpio_request_array(picodlp_gpios, ARRAY_SIZE(picodlp_gpios));
+	if (r)
+		pr_err("Cannot request PicoDLP GPIOs, error %d\n", r);
+}
+
+static int sdp4430_panel_enable_picodlp(struct omap_dss_device *dssdev)
+{
+	gpio_set_value(DISPLAY_SEL_GPIO, 0);
+	gpio_set_value(DLP_POWER_ON_GPIO, 1);
+
+	return 0;
+}
+
+static void sdp4430_panel_disable_picodlp(struct omap_dss_device *dssdev)
+{
+	gpio_set_value(DLP_POWER_ON_GPIO, 0);
+	gpio_set_value(DISPLAY_SEL_GPIO, 1);
+}
+
+static struct omap_dss_device sdp4430_picodlp_device = {
+	.name			= "picodlp",
+	.driver_name		= "picodlp_panel",
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.phy.dpi.data_lines	= 24,
+	.channel		= OMAP_DSS_CHANNEL_LCD2,
+	.platform_enable	= sdp4430_panel_enable_picodlp,
+	.platform_disable	= sdp4430_panel_disable_picodlp,
+	.data			= &sdp4430_picodlp_pdata,
+};
+
 static struct omap_dss_device *sdp4430_dss_devices[] = {
+	&sdp4430_lcd_device,
+	&sdp4430_lcd2_device,
 	&sdp4430_hdmi_device,
+	&sdp4430_picodlp_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,
+	.default_device	= &sdp4430_lcd_device,
 };
 
-void omap_4430sdp_display_init(void)
+static void omap_4430sdp_display_init(void)
 {
+	int r;
+
+	/* Enable LCD2 by default (instead of Pico DLP) */
+	r = gpio_request_one(DISPLAY_SEL_GPIO, GPIOF_OUT_INIT_HIGH,
+			"display_sel");
+	if (r)
+		pr_err("%s: Could not get display_sel GPIO\n", __func__);
+
+	sdp4430_lcd_init();
 	sdp4430_hdmi_mux_init();
+	sdp4430_picodlp_init();
 	omap_display_init(&sdp4430_dss_data);
 }
 
@@ -802,13 +951,11 @@
 		package = OMAP_PACKAGE_CBL;
 	omap4_mux_init(board_mux, NULL, 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));
 	board_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	omap4_sdp4430_wifi_init();
 	omap4_twl6030_hsmmc_init(mmc);
 
@@ -830,18 +977,12 @@
 	omap_4430sdp_display_init();
 }
 
-static void __init omap_4430sdp_map_io(void)
-{
-	omap2_set_globals_443x();
-	omap44xx_map_common_io();
-}
-
 MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
 	/* Maintainer: Santosh Shilimkar - Texas Instruments Inc */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap_4430sdp_map_io,
-	.init_early	= omap_4430sdp_init_early,
+	.map_io		= omap4_map_io,
+	.init_early	= omap4430_init_early,
 	.init_irq	= gic_init_irq,
 	.init_machine	= omap_4430sdp_init,
 	.timer		= &omap4_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-am3517crane.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-am3517crane.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-am3517crane.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-am3517crane.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,12 +47,6 @@
 };
 #endif
 
-static void __init am3517_crane_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 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,
@@ -70,6 +64,7 @@
 
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 
 	omap_board_config = am3517_crane_config;
 	omap_board_config_size = ARRAY_SIZE(am3517_crane_config);
@@ -98,10 +93,10 @@
 }
 
 MACHINE_START(CRANEBOARD, "AM3517/05 CRANEBOARD")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= am3517_crane_init_early,
+	.init_early	= am35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= am3517_crane_init,
 	.timer		= &omap3_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-am3517evm.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-am3517evm.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-am3517evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-am3517evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 #include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include "mux.h"
 #include "control.h"
@@ -333,8 +334,7 @@
 	dvi_enabled = 0;
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable	= am3517_evm_panel_enable_dvi,
 	.platform_disable	= am3517_evm_panel_disable_dvi,
 };
@@ -342,7 +342,7 @@
 static struct omap_dss_device am3517_evm_dvi_device = {
 	.type			= OMAP_DISPLAY_TYPE_DPI,
 	.name			= "dvi",
-	.driver_name		= "generic_dpi_panel",
+	.driver_name		= "dvi",
 	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
 };
@@ -362,11 +362,6 @@
 /*
  * Board initialization
  */
-static void __init am3517_evm_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
 
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type         = MUSB_INTERFACE_ULPI,
@@ -469,6 +464,7 @@
 	am3517_evm_i2c_init();
 	omap_display_init(&am3517_evm_dss_data);
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 
 	/* Configure GPIO for EHCI port */
 	omap_mux_init_gpio(57, OMAP_PIN_OUTPUT);
@@ -490,10 +486,10 @@
 }
 
 MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= am3517_evm_init_early,
+	.init_early	= am35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= am3517_evm_init,
 	.timer		= &omap3_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-apollon.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-apollon.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-apollon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-apollon.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,9 @@
 #include <plat/common.h>
 #include <plat/gpmc.h>
 
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
 #include "mux.h"
 #include "control.h"
 
@@ -149,11 +152,6 @@
 	.resource	= apollon_smc91x_resources,
 };
 
-static struct platform_device apollon_lcd_device = {
-	.name		= "apollon_lcd",
-	.id		= -1,
-};
-
 static struct omap_led_config apollon_led_config[] = {
 	{
 		.cdev	= {
@@ -191,7 +189,6 @@
 static struct platform_device *apollon_devices[] __initdata = {
 	&apollon_onenand_device,
 	&apollon_smc91x_device,
-	&apollon_lcd_device,
 	&apollon_led_device,
 };
 
@@ -265,19 +262,27 @@
 	.pins[0]	= 6,
 };
 
-static struct omap_lcd_config apollon_lcd_config __initdata = {
-	.ctrl_name	= "internal",
+static struct panel_generic_dpi_data apollon_panel_data = {
+	.name			= "apollon",
 };
 
-static struct omap_board_config_kernel apollon_config[] __initdata = {
-	{ OMAP_TAG_LCD,		&apollon_lcd_config },
+static struct omap_dss_device apollon_lcd_device = {
+	.name			= "lcd",
+	.driver_name		= "generic_dpi_panel",
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.phy.dpi.data_lines	= 18,
+	.data			= &apollon_panel_data,
 };
 
-static void __init omap_apollon_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
+static struct omap_dss_device *apollon_dss_devices[] = {
+	&apollon_lcd_device,
+};
+
+static struct omap_dss_board_info apollon_dss_data = {
+	.num_devices	= ARRAY_SIZE(apollon_dss_devices),
+	.devices	= apollon_dss_devices,
+	.default_device	= &apollon_lcd_device,
+};
 
 static struct gpio apollon_gpio_leds[] __initdata = {
 	{ LED0_GPIO13, GPIOF_OUT_INIT_LOW, "LED0" }, /* LED0 - AA10 */
@@ -314,8 +319,6 @@
 	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();
@@ -340,20 +343,16 @@
 	 */
 	platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
 	omap_serial_init();
-}
-
-static void __init omap_apollon_map_io(void)
-{
-	omap2_set_globals_242x();
-	omap242x_map_common_io();
+	omap_sdrc_init(NULL, NULL);
+	omap_display_init(&apollon_dss_data);
 }
 
 MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
 	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap_apollon_map_io,
-	.init_early	= omap_apollon_init_early,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= omap_apollon_init,
 	.timer		= &omap2_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-cm-t3517.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-cm-t3517.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-cm-t3517.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-cm-t3517.c	2012-01-04 18:55:44.000000000 -0500
@@ -251,12 +251,6 @@
 static struct omap_board_config_kernel cm_t3517_config[] __initdata = {
 };
 
-static void __init cm_t3517_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* GPIO186 - Green LED */
@@ -289,6 +283,7 @@
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	omap_board_config = cm_t3517_config;
 	omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
 	cm_t3517_init_leds();
@@ -299,10 +294,10 @@
 }
 
 MACHINE_START(CM_T3517, "Compulab CM-T3517")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve        = omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= cm_t3517_init_early,
+	.init_early	= am35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= cm_t3517_init,
 	.timer		= &omap3_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-cm-t35.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-cm-t35.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-cm-t35.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-cm-t35.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@
 #include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 #include <plat/mcspi.h>
 
 #include <mach/hardware.h>
@@ -242,8 +243,7 @@
 	.phy.dpi.data_lines	= 18,
 };
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable	= cm_t35_panel_enable_dvi,
 	.platform_disable	= cm_t35_panel_disable_dvi,
 };
@@ -251,7 +251,7 @@
 static struct omap_dss_device cm_t35_dvi_device = {
 	.name			= "dvi",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
-	.driver_name		= "generic_dpi_panel",
+	.driver_name		= "dvi",
 	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
 };
@@ -471,13 +471,6 @@
 	omap3_pmic_init("tps65930", &cm_t35_twldata);
 }
 
-static void __init cm_t35_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-			     mt46h32m32lf6_sdrc_params);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* nCS and IRQ for CM-T35 ethernet */
@@ -610,6 +603,8 @@
 	omap_board_config_size = ARRAY_SIZE(cm_t35_config);
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+			     mt46h32m32lf6_sdrc_params);
 	cm_t35_init_i2c();
 	omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL);
 	cm_t35_init_ethernet();
@@ -634,20 +629,20 @@
 }
 
 MACHINE_START(CM_T35, "Compulab CM-T35")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= cm_t35_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= cm_t35_init,
 	.timer		= &omap3_timer,
 MACHINE_END
 
 MACHINE_START(CM_T3730, "Compulab CM-T3730")
-	.boot_params    = 0x80000100,
+	.atag_offset    = 0x100,
 	.reserve        = omap_reserve,
 	.map_io         = omap3_map_io,
-	.init_early     = cm_t35_init_early,
+	.init_early     = omap3630_init_early,
 	.init_irq       = omap3_init_irq,
 	.init_machine   = cm_t3730_init,
 	.timer          = &omap3_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-devkit8000.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-devkit8000.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-devkit8000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-devkit8000.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,7 @@
 #include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include <plat/mcspi.h>
 #include <linux/input/matrix_keypad.h>
@@ -139,7 +140,7 @@
 };
 
 static struct panel_generic_dpi_data lcd_panel = {
-	.name			= "generic",
+	.name			= "innolux_at070tn83",
 	.platform_enable        = devkit8000_panel_enable_lcd,
 	.platform_disable       = devkit8000_panel_disable_lcd,
 };
@@ -152,8 +153,7 @@
 	.phy.dpi.data_lines     = 24,
 };
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable        = devkit8000_panel_enable_dvi,
 	.platform_disable       = devkit8000_panel_disable_dvi,
 };
@@ -161,7 +161,7 @@
 static struct omap_dss_device devkit8000_dvi_device = {
 	.name                   = "dvi",
 	.type                   = OMAP_DISPLAY_TYPE_DPI,
-	.driver_name            = "generic_dpi_panel",
+	.driver_name            = "dvi",
 	.data			= &dvi_panel,
 	.phy.dpi.data_lines     = 24,
 };
@@ -226,7 +226,6 @@
 {
 	int ret;
 
-	omap_mux_init_gpio(29, OMAP_PIN_INPUT);
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
 	omap2_hsmmc_init(mmc);
@@ -267,7 +266,7 @@
 
 static struct regulator_consumer_supply devkit8000_vpll1_supplies[] = {
 	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
 };
 
 /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
@@ -397,19 +396,6 @@
 	},
 };
 
-
-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)
-{
-	omap3_init_irq();
-}
-
 #define OMAP_DM9000_BASE	0x2c000000
 
 static struct resource omap_dm9000_resources[] = {
@@ -645,6 +631,8 @@
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 
 	omap_dm9000_init();
 
@@ -667,11 +655,11 @@
 }
 
 MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= devkit8000_init_early,
-	.init_irq	= devkit8000_init_irq,
+	.init_early	= omap35xx_init_early,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= devkit8000_init,
 	.timer		= &omap3_secure_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-flash.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-flash.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-flash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-flash.c	2012-01-04 18:55:44.000000000 -0500
@@ -148,11 +148,6 @@
 	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, int nand_type)
-{
-}
 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
 
 /**
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-flash.h linux-libre-3.2-gnu/arch/arm/mach-omap2/board-flash.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-flash.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-flash.h	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,26 @@
 	int nr_parts;
 };
 
+#if defined(CONFIG_MTD_NAND_OMAP2) || \
+		defined(CONFIG_MTD_NAND_OMAP2_MODULE) || \
+		defined(CONFIG_MTD_ONENAND_OMAP2) || \
+		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
 extern void board_flash_init(struct flash_partitions [],
 				char chip_sel[][GPMC_CS_NUM], int nand_type);
+#else
+static inline void board_flash_init(struct flash_partitions part[],
+				char chip_sel[][GPMC_CS_NUM], int nand_type)
+{
+}
+#endif
+
+#if defined(CONFIG_MTD_NAND_OMAP2) || \
+		defined(CONFIG_MTD_NAND_OMAP2_MODULE)
 extern void board_nand_init(struct mtd_partition *nand_parts,
 					u8 nr_parts, u8 cs, int nand_type);
+#else
+static inline void board_nand_init(struct mtd_partition *nand_parts,
+					u8 nr_parts, u8 cs, int nand_type)
+{
+}
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-generic.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-generic.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-generic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-generic.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,76 +1,165 @@
 /*
- * linux/arch/arm/mach-omap2/board-generic.c
- *
  * Copyright (C) 2005 Nokia Corporation
  * Author: Paul Mundt <paul.mundt@nokia.com>
  *
- * Modified from mach-omap/omap1/board-generic.c
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
  *
- * Code for generic OMAP2 board. Should work on many OMAP2 systems where
- * the bootloader passes the board-specific data to the kernel.
- * Do not put any board specific code to this file; create a new machine
- * type if you need custom low-level initializations.
+ * Modified from the original mach-omap/omap2/board-generic.c did by Paul
+ * to support the OMAP2+ device tree boards with an unique board file.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/irqdomain.h>
+#include <linux/i2c/twl.h>
 
 #include <mach/hardware.h>
-#include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/map.h>
 
-#include <mach/gpio.h>
-#include <plat/usb.h>
 #include <plat/board.h>
 #include <plat/common.h>
+#include <mach/omap4-common.h>
+#include "common-board-devices.h"
 
-static struct omap_board_config_kernel generic_config[] = {
+/*
+ * XXX: Still needed to boot until the i2c & twl driver is adapted to
+ * device-tree
+ */
+#ifdef CONFIG_ARCH_OMAP4
+static struct twl4030_platform_data sdp4430_twldata = {
+	.irq_base	= TWL6030_IRQ_BASE,
+	.irq_end	= TWL6030_IRQ_END,
 };
 
-static void __init omap_generic_init_early(void)
+static void __init omap4_i2c_init(void)
 {
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
+	omap4_pmic_init("twl6030", &sdp4430_twldata);
+}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+static struct twl4030_platform_data beagle_twldata = {
+	.irq_base	= TWL4030_IRQ_BASE,
+	.irq_end	= TWL4030_IRQ_END,
+};
+
+static void __init omap3_i2c_init(void)
+{
+	omap3_pmic_init("twl4030", &beagle_twldata);
 }
+#endif
+
+static struct of_device_id omap_dt_match_table[] __initdata = {
+	{ .compatible = "simple-bus", },
+	{ .compatible = "ti,omap-infra", },
+	{ }
+};
+
+static struct of_device_id intc_match[] __initdata = {
+	{ .compatible = "ti,omap3-intc", },
+	{ .compatible = "arm,cortex-a9-gic", },
+	{ }
+};
 
 static void __init omap_generic_init(void)
 {
+	struct device_node *node = of_find_matching_node(NULL, intc_match);
+	if (node)
+		irq_domain_add_simple(node, 0);
+
 	omap_serial_init();
-	omap_board_config = generic_config;
-	omap_board_config_size = ARRAY_SIZE(generic_config);
+	omap_sdrc_init(NULL, NULL);
+
+	of_platform_populate(NULL, omap_dt_match_table, NULL, NULL);
 }
 
-static void __init omap_generic_map_io(void)
+#ifdef CONFIG_ARCH_OMAP4
+static void __init omap4_init(void)
 {
-	if (cpu_is_omap242x()) {
-		omap2_set_globals_242x();
-		omap242x_map_common_io();
-	} else if (cpu_is_omap243x()) {
-		omap2_set_globals_243x();
-		omap243x_map_common_io();
-	} else if (cpu_is_omap34xx()) {
-		omap2_set_globals_3xxx();
-		omap34xx_map_common_io();
-	} else if (cpu_is_omap44xx()) {
-		omap2_set_globals_443x();
-		omap44xx_map_common_io();
-	}
+	omap4_i2c_init();
+	omap_generic_init();
 }
+#endif
 
-/* XXX This machine entry name should be updated */
-MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
-	/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
-	.boot_params	= 0x80000100,
+#ifdef CONFIG_ARCH_OMAP3
+static void __init omap3_init(void)
+{
+	omap3_i2c_init();
+	omap_generic_init();
+}
+#endif
+
+#if defined(CONFIG_SOC_OMAP2420)
+static const char *omap242x_boards_compat[] __initdata = {
+	"ti,omap2420",
+	NULL,
+};
+
+DT_MACHINE_START(OMAP242X_DT, "Generic OMAP2420 (Flattened Device Tree)")
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap_generic_map_io,
-	.init_early	= omap_generic_init_early,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= omap_generic_init,
 	.timer		= &omap2_timer,
+	.dt_compat	= omap242x_boards_compat,
 MACHINE_END
+#endif
+
+#if defined(CONFIG_SOC_OMAP2430)
+static const char *omap243x_boards_compat[] __initdata = {
+	"ti,omap2430",
+	NULL,
+};
+
+DT_MACHINE_START(OMAP243X_DT, "Generic OMAP2430 (Flattened Device Tree)")
+	.atag_offset	= 0x100,
+	.reserve	= omap_reserve,
+	.map_io		= omap243x_map_io,
+	.init_early	= omap2430_init_early,
+	.init_irq	= omap2_init_irq,
+	.init_machine	= omap_generic_init,
+	.timer		= &omap2_timer,
+	.dt_compat	= omap243x_boards_compat,
+MACHINE_END
+#endif
+
+#if defined(CONFIG_ARCH_OMAP3)
+static const char *omap3_boards_compat[] __initdata = {
+	"ti,omap3",
+	NULL,
+};
+
+DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
+	.atag_offset	= 0x100,
+	.reserve	= omap_reserve,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3430_init_early,
+	.init_irq	= omap3_init_irq,
+	.init_machine	= omap3_init,
+	.timer		= &omap3_timer,
+	.dt_compat	= omap3_boards_compat,
+MACHINE_END
+#endif
+
+#if defined(CONFIG_ARCH_OMAP4)
+static const char *omap4_boards_compat[] __initdata = {
+	"ti,omap4",
+	NULL,
+};
+
+DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)")
+	.atag_offset	= 0x100,
+	.reserve	= omap_reserve,
+	.map_io		= omap4_map_io,
+	.init_early	= omap4430_init_early,
+	.init_irq	= gic_init_irq,
+	.init_machine	= omap4_init,
+	.timer		= &omap4_timer,
+	.dt_compat	= omap4_boards_compat,
+MACHINE_END
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-h4.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-h4.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-h4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-h4.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  * 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/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -25,21 +25,23 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/input/matrix_keypad.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/gpio.h>
 #include <plat/usb.h>
 #include <plat/board.h>
 #include <plat/common.h>
-#include <plat/keypad.h>
 #include <plat/menelaus.h>
 #include <plat/dma.h>
 #include <plat/gpmc.h>
 
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
 #include "mux.h"
 #include "control.h"
 
@@ -48,10 +50,8 @@
 
 #define H4_ETHR_GPIO_IRQ		92
 
-static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 };
-static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 };
-
-static const unsigned int h4_keymap[] = {
+#if defined(CONFIG_KEYBOARD_MATRIX) || defined(CONFIG_KEYBOARD_MATRIX_MODULE)
+static const uint32_t board_matrix_keys[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(1, 0, KEY_RIGHT),
 	KEY(2, 0, KEY_A),
@@ -84,6 +84,71 @@
 	KEY(4, 5, KEY_ENTER),
 };
 
+static const struct matrix_keymap_data board_keymap_data = {
+	.keymap			= board_matrix_keys,
+	.keymap_size		= ARRAY_SIZE(board_matrix_keys),
+};
+
+static unsigned int board_keypad_row_gpios[] = {
+	88, 89, 124, 11, 6, 96
+};
+
+static unsigned int board_keypad_col_gpios[] = {
+	90, 91, 100, 36, 12, 97, 98
+};
+
+static struct matrix_keypad_platform_data board_keypad_platform_data = {
+	.keymap_data	= &board_keymap_data,
+	.row_gpios	= board_keypad_row_gpios,
+	.num_row_gpios	= ARRAY_SIZE(board_keypad_row_gpios),
+	.col_gpios	= board_keypad_col_gpios,
+	.num_col_gpios	= ARRAY_SIZE(board_keypad_col_gpios),
+	.active_low	= 1,
+
+	.debounce_ms		= 20,
+	.col_scan_delay_us	= 5,
+};
+
+static struct platform_device board_keyboard = {
+	.name	= "matrix-keypad",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &board_keypad_platform_data,
+	},
+};
+static void __init board_mkp_init(void)
+{
+	omap_mux_init_gpio(88, OMAP_PULL_ENA | OMAP_PULL_UP);
+	omap_mux_init_gpio(89, OMAP_PULL_ENA | OMAP_PULL_UP);
+	omap_mux_init_gpio(124, OMAP_PULL_ENA | OMAP_PULL_UP);
+	omap_mux_init_signal("mcbsp2_dr.gpio_11", OMAP_PULL_ENA | OMAP_PULL_UP);
+	if (omap_has_menelaus()) {
+		omap_mux_init_signal("sdrc_a14.gpio0",
+			OMAP_PULL_ENA | OMAP_PULL_UP);
+		omap_mux_init_signal("vlynq_rx0.gpio_15", 0);
+		omap_mux_init_signal("gpio_98", 0);
+		board_keypad_row_gpios[5] = 0;
+		board_keypad_col_gpios[2] = 15;
+		board_keypad_col_gpios[6] = 18;
+	} else {
+		omap_mux_init_signal("gpio_96", OMAP_PULL_ENA | OMAP_PULL_UP);
+		omap_mux_init_signal("gpio_100", 0);
+		omap_mux_init_signal("gpio_98", 0);
+	}
+	omap_mux_init_signal("gpio_90", 0);
+	omap_mux_init_signal("gpio_91", 0);
+	omap_mux_init_signal("gpio_36", 0);
+	omap_mux_init_signal("mcbsp2_clkx.gpio_12", 0);
+	omap_mux_init_signal("gpio_97", 0);
+
+	platform_device_register(&board_keyboard);
+}
+#else
+static inline void board_mkp_init(void)
+{
+}
+#endif
+
 static struct mtd_partition h4_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
@@ -135,37 +200,30 @@
 	.resource	= &h4_flash_resource,
 };
 
-static const struct matrix_keymap_data h4_keymap_data = {
-	.keymap		= h4_keymap,
-	.keymap_size	= ARRAY_SIZE(h4_keymap),
+static struct platform_device *h4_devices[] __initdata = {
+	&h4_flash_device,
 };
 
-static struct omap_kp_platform_data h4_kp_data = {
-	.rows		= 6,
-	.cols		= 7,
-	.keymap_data	= &h4_keymap_data,
-	.rep		= true,
-	.row_gpios 	= row_gpios,
-	.col_gpios 	= col_gpios,
+static struct panel_generic_dpi_data h4_panel_data = {
+	.name			= "h4",
 };
 
-static struct platform_device h4_kp_device = {
-	.name		= "omap-keypad",
-	.id		= -1,
-	.dev		= {
-		.platform_data = &h4_kp_data,
-	},
+static struct omap_dss_device h4_lcd_device = {
+	.name			= "lcd",
+	.driver_name		= "generic_dpi_panel",
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.phy.dpi.data_lines	= 16,
+	.data			= &h4_panel_data,
 };
 
-static struct platform_device h4_lcd_device = {
-	.name		= "lcd_h4",
-	.id		= -1,
+static struct omap_dss_device *h4_dss_devices[] = {
+	&h4_lcd_device,
 };
 
-static struct platform_device *h4_devices[] __initdata = {
-	&h4_flash_device,
-	&h4_kp_device,
-	&h4_lcd_device,
+static struct omap_dss_board_info h4_dss_data = {
+	.num_devices	= ARRAY_SIZE(h4_dss_devices),
+	.devices	= h4_dss_devices,
+	.default_device	= &h4_lcd_device,
 };
 
 /* 2420 Sysboot setup (2430 is different) */
@@ -271,10 +329,6 @@
 	h4_flash_resource.end	= base + SZ_64M - 1;
 }
 
-static struct omap_lcd_config h4_lcd_config __initdata = {
-	.ctrl_name	= "internal",
-};
-
 static struct omap_usb_config h4_usb_config __initdata = {
 	/* S1.10 OFF -- usb "download port"
 	 * usb0 switched to Mini-B port and isp1105 transceiver;
@@ -286,21 +340,6 @@
 	.hmc_mode	= 0x00,		/* 0:dev|otg 1:disable 2:disable */
 };
 
-static struct omap_board_config_kernel h4_config[] __initdata = {
-	{ OMAP_TAG_LCD,		&h4_lcd_config },
-};
-
-static void __init omap_h4_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
-static void __init omap_h4_init_irq(void)
-{
-	omap2_init_irq();
-}
-
 static struct at24_platform_data m24c01 = {
 	.byte_len	= SZ_1K / 8,
 	.page_size	= 16,
@@ -331,62 +370,32 @@
 {
 	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
 	 * if not needed.
 	 */
 
-#if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
-	omap_mux_init_gpio(88, OMAP_PULL_ENA | OMAP_PULL_UP);
-	omap_mux_init_gpio(89, OMAP_PULL_ENA | OMAP_PULL_UP);
-	omap_mux_init_gpio(124, OMAP_PULL_ENA | OMAP_PULL_UP);
-	omap_mux_init_signal("mcbsp2_dr.gpio_11", OMAP_PULL_ENA | OMAP_PULL_UP);
-	if (omap_has_menelaus()) {
-		omap_mux_init_signal("sdrc_a14.gpio0",
-			OMAP_PULL_ENA | OMAP_PULL_UP);
-		omap_mux_init_signal("vlynq_rx0.gpio_15", 0);
-		omap_mux_init_signal("gpio_98", 0);
-		row_gpios[5] = 0;
-		col_gpios[2] = 15;
-		col_gpios[6] = 18;
-	} else {
-		omap_mux_init_signal("gpio_96", OMAP_PULL_ENA | OMAP_PULL_UP);
-		omap_mux_init_signal("gpio_100", 0);
-		omap_mux_init_signal("gpio_98", 0);
-	}
-	omap_mux_init_signal("gpio_90", 0);
-	omap_mux_init_signal("gpio_91", 0);
-	omap_mux_init_signal("gpio_36", 0);
-	omap_mux_init_signal("mcbsp2_clkx.gpio_12", 0);
-	omap_mux_init_signal("gpio_97", 0);
-#endif
-
+	board_mkp_init();
 	i2c_register_board_info(1, h4_i2c_board_info,
 			ARRAY_SIZE(h4_i2c_board_info));
 
 	platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
 	omap2_usbfs_init(&h4_usb_config);
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	h4_init_flash();
-}
 
-static void __init omap_h4_map_io(void)
-{
-	omap2_set_globals_242x();
-	omap242x_map_common_io();
+	omap_display_init(&h4_dss_data);
 }
 
 MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
 	/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap_h4_map_io,
-	.init_early	= omap_h4_init_early,
-	.init_irq	= omap_h4_init_irq,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
+	.init_irq	= omap2_init_irq,
 	.init_machine	= omap_h4_init,
 	.timer		= &omap2_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-igep0020.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-igep0020.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-igep0020.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-igep0020.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,7 @@
 #include <plat/gpmc.h>
 #include <plat/usb.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 #include <plat/onenand.h>
 
 #include "mux.h"
@@ -455,16 +455,16 @@
 	gpio_direction_output(IGEP2_GPIO_DVI_PUP, 0);
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable	= igep2_enable_dvi,
 	.platform_disable	= igep2_disable_dvi,
+	.i2c_bus_num = 3,
 };
 
 static struct omap_dss_device igep2_dvi_device = {
 	.type			= OMAP_DISPLAY_TYPE_DPI,
 	.name			= "dvi",
-	.driver_name		= "generic_dpi_panel",
+	.driver_name		= "dvi",
 	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
 };
@@ -491,13 +491,6 @@
 	&igep_vwlan_device,
 };
 
-static void __init igep_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(m65kxxxxam_sdrc_params,
-				  m65kxxxxam_sdrc_params);
-}
-
 static int igep2_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(0, 1, KEY_RIGHT),
@@ -650,6 +643,8 @@
 	igep_i2c_init();
 	platform_add_devices(igep_devices, ARRAY_SIZE(igep_devices));
 	omap_serial_init();
+	omap_sdrc_init(m65kxxxxam_sdrc_params,
+				  m65kxxxxam_sdrc_params);
 	usb_musb_init(NULL);
 
 	igep_flash_init();
@@ -672,20 +667,20 @@
 }
 
 MACHINE_START(IGEP0020, "IGEP v2 board")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= igep_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= igep_init,
 	.timer		= &omap3_timer,
 MACHINE_END
 
 MACHINE_START(IGEP0030, "IGEP OMAP3 module")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= igep_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= igep_init,
 	.timer		= &omap3_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-ldp.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-ldp.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-ldp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-ldp.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  * 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/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -27,6 +27,7 @@
 #include <linux/io.h>
 #include <linux/smsc911x.h>
 #include <linux/mmc/host.h>
+#include <linux/gpio.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -34,7 +35,6 @@
 #include <asm/mach/map.h>
 
 #include <plat/mcspi.h>
-#include <mach/gpio.h>
 #include <plat/board.h>
 #include <plat/common.h>
 #include <plat/gpmc.h>
@@ -44,6 +44,9 @@
 #include <plat/usb.h>
 #include <plat/gpmc-smsc911x.h>
 
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
 #include "board-flash.h"
 #include "mux.h"
 #include "hsmmc.h"
@@ -180,29 +183,102 @@
 	gpmc_smsc911x_init(&smsc911x_cfg);
 }
 
-static struct platform_device ldp_lcd_device = {
-	.name		= "ldp_lcd",
-	.id		= -1,
+/* LCD */
+
+static int ldp_backlight_gpio;
+static int ldp_lcd_enable_gpio;
+
+#define LCD_PANEL_RESET_GPIO		55
+#define LCD_PANEL_QVGA_GPIO		56
+
+static int ldp_panel_enable_lcd(struct omap_dss_device *dssdev)
+{
+	if (gpio_is_valid(ldp_lcd_enable_gpio))
+		gpio_direction_output(ldp_lcd_enable_gpio, 1);
+	if (gpio_is_valid(ldp_backlight_gpio))
+		gpio_direction_output(ldp_backlight_gpio, 1);
+
+	return 0;
+}
+
+static void ldp_panel_disable_lcd(struct omap_dss_device *dssdev)
+{
+	if (gpio_is_valid(ldp_lcd_enable_gpio))
+		gpio_direction_output(ldp_lcd_enable_gpio, 0);
+	if (gpio_is_valid(ldp_backlight_gpio))
+		gpio_direction_output(ldp_backlight_gpio, 0);
+}
+
+static struct panel_generic_dpi_data ldp_panel_data = {
+	.name			= "nec_nl2432dr22-11b",
+	.platform_enable	= ldp_panel_enable_lcd,
+	.platform_disable	= ldp_panel_disable_lcd,
 };
 
-static struct omap_lcd_config ldp_lcd_config __initdata = {
-	.ctrl_name	= "internal",
+static struct omap_dss_device ldp_lcd_device = {
+	.name			= "lcd",
+	.driver_name		= "generic_dpi_panel",
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.phy.dpi.data_lines	= 18,
+	.data			= &ldp_panel_data,
 };
 
-static struct omap_board_config_kernel ldp_config[] __initdata = {
-	{ OMAP_TAG_LCD,		&ldp_lcd_config },
+static struct omap_dss_device *ldp_dss_devices[] = {
+	&ldp_lcd_device,
 };
 
-static void __init omap_ldp_init_early(void)
+static struct omap_dss_board_info ldp_dss_data = {
+	.num_devices	= ARRAY_SIZE(ldp_dss_devices),
+	.devices	= ldp_dss_devices,
+	.default_device	= &ldp_lcd_device,
+};
+
+static void __init ldp_display_init(void)
 {
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
+	int r;
+
+	static struct gpio gpios[] __initdata = {
+		{LCD_PANEL_RESET_GPIO, GPIOF_OUT_INIT_HIGH, "LCD RESET"},
+		{LCD_PANEL_QVGA_GPIO, GPIOF_OUT_INIT_HIGH, "LCD QVGA"},
+	};
+
+	r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
+	if (r) {
+		pr_err("Cannot request LCD GPIOs, error %d\n", r);
+		return;
+	}
+
+	omap_display_init(&ldp_dss_data);
+}
+
+static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio)
+{
+	int r;
+
+	struct gpio gpios[] = {
+		{gpio + 7 , GPIOF_OUT_INIT_LOW, "LCD ENABLE"},
+		{gpio + 15, GPIOF_OUT_INIT_LOW, "LCD BACKLIGHT"},
+	};
+
+	r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
+	if (r) {
+		pr_err("Cannot request LCD GPIOs, error %d\n", r);
+		ldp_backlight_gpio = -EINVAL;
+		ldp_lcd_enable_gpio = -EINVAL;
+		return r;
+	}
+
+	ldp_backlight_gpio = gpio + 15;
+	ldp_lcd_enable_gpio = gpio + 7;
+
+	return 0;
 }
 
 static struct twl4030_gpio_platform_data ldp_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
 	.irq_end	= TWL4030_GPIO_IRQ_END,
+	.setup		= ldp_twl_gpio_setup,
 };
 
 static struct regulator_consumer_supply ldp_vmmc1_supply[] = {
@@ -244,10 +320,31 @@
 	.consumer_supplies		= ldp_vaux1_supplies,
 };
 
+static struct regulator_consumer_supply ldp_vpll2_supplies[] = {
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
+
+static struct regulator_init_data ldp_vpll2 = {
+	.constraints = {
+		.name			= "VDVI",
+		.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	= ARRAY_SIZE(ldp_vpll2_supplies),
+	.consumer_supplies	= ldp_vpll2_supplies,
+};
+
 static struct twl4030_platform_data ldp_twldata = {
 	/* platform_data for children goes here */
 	.vmmc1		= &ldp_vmmc1,
 	.vaux1		= &ldp_vaux1,
+	.vpll2		= &ldp_vpll2,
 	.gpio		= &ldp_gpio_data,
 	.keypad		= &ldp_kp_twl4030_data,
 };
@@ -273,7 +370,6 @@
 };
 
 static struct platform_device *ldp_devices[] __initdata = {
-	&ldp_lcd_device,
 	&ldp_gpio_keys_device,
 };
 
@@ -318,25 +414,25 @@
 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));
 	omap_ads7846_init(1, 54, 310, NULL);
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	usb_musb_init(NULL);
 	board_nand_init(ldp_nand_partitions,
 		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
 
 	omap2_hsmmc_init(mmc);
+	ldp_display_init();
 }
 
 MACHINE_START(OMAP_LDP, "OMAP LDP board")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap_ldp_init_early,
+	.init_early	= omap3430_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_ldp_init,
 	.timer		= &omap3_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-n8x0.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-n8x0.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-n8x0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-n8x0.c	2012-01-04 18:55:44.000000000 -0500
@@ -616,18 +616,6 @@
 	},
 };
 
-static void __init n8x0_map_io(void)
-{
-	omap2_set_globals_242x();
-	omap242x_map_common_io();
-}
-
-static void __init n8x0_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* I2S codec port pins for McBSP block */
@@ -689,36 +677,37 @@
 		i2c_register_board_info(2, n810_i2c_board_info_2,
 					ARRAY_SIZE(n810_i2c_board_info_2));
 	board_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	gpmc_onenand_init(board_onenand_data);
 	n8x0_mmc_init();
 	n8x0_usb_init();
 }
 
 MACHINE_START(NOKIA_N800, "Nokia N800")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= n8x0_map_io,
-	.init_early	= n8x0_init_early,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= n8x0_init_machine,
 	.timer		= &omap2_timer,
 MACHINE_END
 
 MACHINE_START(NOKIA_N810, "Nokia N810")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= n8x0_map_io,
-	.init_early	= n8x0_init_early,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= n8x0_init_machine,
 	.timer		= &omap2_timer,
 MACHINE_END
 
 MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= n8x0_map_io,
-	.init_early	= n8x0_init_early,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= n8x0_init_machine,
 	.timer		= &omap2_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-omap3beagle.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-omap3beagle.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-omap3beagle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-omap3beagle.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,7 +42,7 @@
 #include <plat/board.h>
 #include <plat/common.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
@@ -203,16 +203,16 @@
 		gpio_set_value(dssdev->reset_gpio, 0);
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable = beagle_enable_dvi,
 	.platform_disable = beagle_disable_dvi,
+	.i2c_bus_num = 3,
 };
 
 static struct omap_dss_device beagle_dvi_device = {
 	.type = OMAP_DISPLAY_TYPE_DPI,
 	.name = "dvi",
-	.driver_name = "generic_dpi_panel",
+	.driver_name = "dvi",
 	.data = &dvi_panel,
 	.phy.dpi.data_lines = 24,
 	.reset_gpio = -EINVAL,
@@ -378,7 +378,8 @@
 static int __init omap3_beagle_i2c_init(void)
 {
 	omap3_pmic_get_config(&beagle_twldata,
-			TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_AUDIO,
+			TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_MADC |
+			TWL_COMMON_PDATA_AUDIO,
 			TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
 
 	beagle_twldata.vpll2->constraints.name = "VDVI";
@@ -444,21 +445,15 @@
 	},
 };
 
-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)
-{
-	omap3_init_irq();
-}
+static struct platform_device madc_hwmon = {
+	.name	= "twl4030_madc_hwmon",
+	.id	= -1,
+};
 
 static struct platform_device *omap3_beagle_devices[] __initdata = {
 	&leds_gpio,
 	&keys_gpio,
+	&madc_hwmon,
 };
 
 static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
@@ -493,8 +488,8 @@
 	if (cpu_is_omap3630()) {
 		struct device *mpu_dev, *iva_dev;
 
-		mpu_dev = omap2_get_mpuss_device();
-		iva_dev = omap2_get_iva_device();
+		mpu_dev = omap_device_get_by_hwmod_name("mpu");
+		iva_dev = omap_device_get_by_hwmod_name("iva");
 
 		if (!mpu_dev || !iva_dev) {
 			pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
@@ -534,6 +529,8 @@
 			ARRAY_SIZE(omap3_beagle_devices));
 	omap_display_init(&beagle_dss_data);
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 
 	omap_mux_init_gpio(170, OMAP_PIN_INPUT);
 	/* REVISIT leave DVI powered down until it's needed ... */
@@ -557,11 +554,11 @@
 
 MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
 	/* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3_beagle_init_early,
-	.init_irq	= omap3_beagle_init_irq,
+	.init_early	= omap3_init_early,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3_beagle_init,
 	.timer		= &omap3_secure_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-omap3evm.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-omap3evm.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-omap3evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-omap3evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/mmc/host.h>
+#include <linux/export.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -45,7 +46,7 @@
 #include <plat/common.h>
 #include <plat/mcspi.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
@@ -247,8 +248,7 @@
 	dvi_enabled = 0;
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable	= omap3_evm_enable_dvi,
 	.platform_disable	= omap3_evm_disable_dvi,
 };
@@ -256,7 +256,7 @@
 static struct omap_dss_device omap3_evm_dvi_device = {
 	.name			= "dvi",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
-	.driver_name		= "generic_dpi_panel",
+	.driver_name		= "dvi",
 	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
 };
@@ -520,12 +520,6 @@
 static struct omap_board_config_kernel omap3_evm_config[] __initdata = {
 };
 
-static void __init omap3_evm_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params, NULL);
-}
-
 static struct usbhs_omap_board_data usbhs_bdata __initdata = {
 
 	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
@@ -640,6 +634,7 @@
 	omap_display_init(&omap3_evm_dss_data);
 
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params, NULL);
 
 	/* OMAP3EVM uses ISP1504 phy and so register nop transceiver */
 	usb_nop_xceiv_register();
@@ -681,10 +676,10 @@
 
 MACHINE_START(OMAP3EVM, "OMAP3 EVM")
 	/* Maintainer: Syed Mohammed Khasim - Texas Instruments */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3_evm_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3_evm_init,
 	.timer		= &omap3_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-omap3logic.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-omap3logic.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-omap3logic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-omap3logic.c	2012-01-04 18:55:44.000000000 -0500
@@ -182,12 +182,6 @@
 	gpmc_smsc911x_init(&board_smsc911x_data);
 }
 
-static void __init omap3logic_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
@@ -200,6 +194,7 @@
 	omap3torpedo_fix_pbias_voltage();
 	omap3logic_i2c_init();
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	board_mmc_init();
 	board_smsc911x_init();
 
@@ -209,18 +204,18 @@
 }
 
 MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3logic_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3logic_init,
 	.timer		= &omap3_timer,
 MACHINE_END
 
 MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3logic_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3logic_init,
 	.timer		= &omap3_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-omap3pandora.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-omap3pandora.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-omap3pandora.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-omap3pandora.c	2012-01-04 18:55:44.000000000 -0500
@@ -335,7 +335,7 @@
 static struct regulator_consumer_supply pandora_vdds_supplies[] = {
 	REGULATOR_SUPPLY("vdds_sdi", "omapdss"),
 	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
 };
 
 static struct regulator_consumer_supply pandora_vcc_lcd_supply[] = {
@@ -525,13 +525,6 @@
 	}
 };
 
-static void __init omap3pandora_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-				  mt46h32m32lf6_sdrc_params);
-}
-
 static void __init pandora_wl1251_init(void)
 {
 	struct wl12xx_platform_data pandora_wl1251_pdata;
@@ -593,6 +586,8 @@
 			ARRAY_SIZE(omap3pandora_devices));
 	omap_display_init(&pandora_dss_data);
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 	spi_register_board_info(omap3pandora_spi_board_info,
 			ARRAY_SIZE(omap3pandora_spi_board_info));
 	omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL);
@@ -606,10 +601,10 @@
 }
 
 MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3pandora_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3pandora_init,
 	.timer		= &omap3_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-omap3stalker.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-omap3stalker.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-omap3stalker.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-omap3stalker.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
 #include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include <plat/mcspi.h>
 #include <linux/input/matrix_keypad.h>
@@ -107,39 +108,6 @@
 	return;
 }
 
-static int omap3_stalker_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(DSS_ENABLE_GPIO, 1);
-	gpio_set_value(LCD_PANEL_BKLIGHT_GPIO, 1);
-	lcd_enabled = 1;
-	return 0;
-}
-
-static void omap3_stalker_disable_lcd(struct omap_dss_device *dssdev)
-{
-	gpio_set_value(DSS_ENABLE_GPIO, 0);
-	gpio_set_value(LCD_PANEL_BKLIGHT_GPIO, 0);
-	lcd_enabled = 0;
-}
-
-static struct panel_generic_dpi_data lcd_panel = {
-	.name			= "generic",
-	.platform_enable	= omap3_stalker_enable_lcd,
-	.platform_disable	= omap3_stalker_disable_lcd,
-};
-
-static struct omap_dss_device omap3_stalker_lcd_device = {
-	.name			= "lcd",
-	.driver_name		= "generic_dpi_panel",
-	.data			= &lcd_panel,
-	.phy.dpi.data_lines	= 24,
-	.type			= OMAP_DISPLAY_TYPE_DPI,
-};
-
 static int omap3_stalker_enable_tv(struct omap_dss_device *dssdev)
 {
 	return 0;
@@ -179,8 +147,7 @@
 	dvi_enabled = 0;
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable	= omap3_stalker_enable_dvi,
 	.platform_disable	= omap3_stalker_disable_dvi,
 };
@@ -188,13 +155,12 @@
 static struct omap_dss_device omap3_stalker_dvi_device = {
 	.name			= "dvi",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
-	.driver_name		= "generic_dpi_panel",
+	.driver_name		= "dvi",
 	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
 };
 
 static struct omap_dss_device *omap3_stalker_dss_devices[] = {
-	&omap3_stalker_lcd_device,
 	&omap3_stalker_tv_device,
 	&omap3_stalker_dvi_device,
 };
@@ -428,17 +394,6 @@
 static struct omap_board_config_kernel omap3_stalker_config[] __initdata = {
 };
 
-static void __init omap3_stalker_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params, NULL);
-}
-
-static void __init omap3_stalker_init_irq(void)
-{
-	omap3_init_irq();
-}
-
 static struct platform_device *omap3_stalker_devices[] __initdata = {
 	&keys_gpio,
 };
@@ -478,6 +433,7 @@
 	omap_display_init(&omap3_stalker_dss_data);
 
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params, NULL);
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	omap_ads7846_init(1, OMAP3_STALKER_TS_GPIO, 310, NULL);
@@ -494,10 +450,10 @@
 
 MACHINE_START(SBC3530, "OMAP3 STALKER")
 	/* Maintainer: Jason Lam -lzg@ema-tech.com */
-	.boot_params		= 0x80000100,
+	.atag_offset		= 0x100,
 	.map_io			= omap3_map_io,
-	.init_early		= omap3_stalker_init_early,
-	.init_irq		= omap3_stalker_init_irq,
+	.init_early		= omap35xx_init_early,
+	.init_irq		= omap3_init_irq,
 	.init_machine		= omap3_stalker_init,
 	.timer			= &omap3_secure_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-omap3touchbook.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-omap3touchbook.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-omap3touchbook.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-omap3touchbook.c	2012-01-04 18:55:44.000000000 -0500
@@ -104,15 +104,6 @@
 	{}	/* Terminator */
 };
 
-static struct platform_device omap3_touchbook_lcd_device = {
-	.name		= "omap3touchbook_lcd",
-	.id		= -1,
-};
-
-static struct omap_lcd_config omap3_touchbook_lcd_config __initdata = {
-	.ctrl_name	= "internal",
-};
-
 static struct regulator_consumer_supply touchbook_vmmc1_supply[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
@@ -165,14 +156,12 @@
 static struct regulator_consumer_supply touchbook_vdac_supply[] = {
 {
 	.supply		= "vdac",
-	.dev		= &omap3_touchbook_lcd_device.dev,
 },
 };
 
 static struct regulator_consumer_supply touchbook_vdvi_supply[] = {
 {
 	.supply		= "vdvi",
-	.dev		= &omap3_touchbook_lcd_device.dev,
 },
 };
 
@@ -316,30 +305,13 @@
 	},
 };
 
-static struct omap_board_config_kernel omap3_touchbook_config[] __initdata = {
-	{ OMAP_TAG_LCD,		&omap3_touchbook_lcd_config },
-};
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
 #endif
 
-static void __init omap3_touchbook_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-				  mt46h32m32lf6_sdrc_params);
-}
-
-static void __init omap3_touchbook_init_irq(void)
-{
-	omap3_init_irq();
-}
-
 static struct platform_device *omap3_touchbook_devices[] __initdata = {
-	&omap3_touchbook_lcd_device,
 	&leds_gpio,
 	&keys_gpio,
 };
@@ -376,8 +348,6 @@
 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;
 
@@ -385,6 +355,8 @@
 	platform_add_devices(omap3_touchbook_devices,
 			ARRAY_SIZE(omap3_touchbook_devices));
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 
 	omap_mux_init_gpio(170, OMAP_PIN_INPUT);
 	/* REVISIT leave DVI powered down until it's needed ... */
@@ -404,11 +376,11 @@
 
 MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board")
 	/* Maintainer: Gregoire Gentil - http://www.alwaysinnovating.com */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3_touchbook_init_early,
-	.init_irq	= omap3_touchbook_init_irq,
+	.init_early	= omap3430_init_early,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3_touchbook_init,
 	.timer		= &omap3_secure_timer,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-omap4panda.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-omap4panda.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-omap4panda.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-omap4panda.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,7 +40,7 @@
 #include <plat/common.h>
 #include <plat/usb.h>
 #include <plat/mmc.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include "hsmmc.h"
 #include "control.h"
@@ -95,12 +95,6 @@
 	&wl1271_device,
 };
 
-static void __init omap4_panda_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 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,
@@ -455,16 +449,16 @@
 }
 
 /* Using generic display panel */
-static struct panel_generic_dpi_data omap4_dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data omap4_dvi_panel = {
 	.platform_enable	= omap4_panda_enable_dvi,
 	.platform_disable	= omap4_panda_disable_dvi,
+	.i2c_bus_num = 3,
 };
 
 struct omap_dss_device omap4_panda_dvi_device = {
 	.type			= OMAP_DISPLAY_TYPE_DPI,
 	.name			= "dvi",
-	.driver_name		= "generic_dpi_panel",
+	.driver_name		= "dvi",
 	.data			= &omap4_dvi_panel,
 	.phy.dpi.data_lines	= 24,
 	.reset_gpio		= PANDA_DVI_TFP410_POWER_DOWN_GPIO,
@@ -569,24 +563,19 @@
 	platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
 	platform_device_register(&omap_vwlan_device);
 	board_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	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)
-{
-	omap2_set_globals_443x();
-	omap44xx_map_common_io();
-}
-
 MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
 	/* Maintainer: David Anders - Texas Instruments Inc */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap4_panda_map_io,
-	.init_early	= omap4_panda_init_early,
+	.map_io		= omap4_map_io,
+	.init_early	= omap4430_init_early,
 	.init_irq	= gic_init_irq,
 	.init_machine	= omap4_panda_init,
 	.timer		= &omap4_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-overo.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-overo.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-overo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-overo.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,6 +46,7 @@
 #include <plat/common.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 #include <plat/gpmc.h>
 #include <mach/hardware.h>
 #include <plat/nand.h>
@@ -182,16 +183,16 @@
 	dvi_enabled = 0;
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-	.name			= "generic",
+static struct panel_dvi_platform_data dvi_panel = {
 	.platform_enable	= overo_panel_enable_dvi,
 	.platform_disable	= overo_panel_disable_dvi,
+	.i2c_bus_num		= 3,
 };
 
 static struct omap_dss_device overo_dvi_device = {
 	.name			= "dvi",
 	.type			= OMAP_DISPLAY_TYPE_DPI,
-	.driver_name		= "generic_dpi_panel",
+	.driver_name		= "dvi",
 	.data			= &dvi_panel,
 	.phy.dpi.data_lines	= 24,
 };
@@ -478,13 +479,6 @@
 	return 0;
 }
 
-static void __init overo_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-				  mt46h32m32lf6_sdrc_params);
-}
-
 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,
@@ -514,6 +508,8 @@
 	overo_i2c_init();
 	omap_display_init(&overo_dss_data);
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 	omap_nand_flash_init(0, overo_nand_partitions,
 			     ARRAY_SIZE(overo_nand_partitions));
 	usb_musb_init(NULL);
@@ -561,10 +557,10 @@
 }
 
 MACHINE_START(OVERO, "Gumstix Overo")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= overo_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= overo_init,
 	.timer		= &omap3_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-rm680.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-rm680.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-rm680.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-rm680.c	2012-01-04 18:55:44.000000000 -0500
@@ -123,15 +123,6 @@
 	omap2_hsmmc_init(mmc);
 }
 
-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);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
@@ -140,23 +131,23 @@
 
 static void __init rm680_init(void)
 {
+	struct omap_sdrc_params *sdrc_params;
+
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_serial_init();
+
+	sdrc_params = nokia_get_sdram_timings();
+	omap_sdrc_init(sdrc_params, sdrc_params);
+
 	usb_musb_init(NULL);
 	rm680_peripherals_init();
 }
 
-static void __init rm680_map_io(void)
-{
-	omap2_set_globals_3xxx();
-	omap34xx_map_common_io();
-}
-
 MACHINE_START(NOKIA_RM680, "Nokia RM-680 board")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= rm680_map_io,
-	.init_early	= rm680_init_early,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3630_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= rm680_init,
 	.timer		= &omap3_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-rx51.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-rx51.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-rx51.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-rx51.c	2012-01-04 18:55:44.000000000 -0500
@@ -79,38 +79,6 @@
 	{7505 + 15274, 484329, 1},
 };
 
-static struct omap_lcd_config rx51_lcd_config = {
-	.ctrl_name	= "internal",
-};
-
-static struct omap_fbmem_config rx51_fbmem0_config = {
-	.size = 752 * 1024,
-};
-
-static struct omap_fbmem_config rx51_fbmem1_config = {
-	.size = 752 * 1024,
-};
-
-static struct omap_fbmem_config rx51_fbmem2_config = {
-	.size = 752 * 1024,
-};
-
-static struct omap_board_config_kernel rx51_config[] = {
-	{ OMAP_TAG_FBMEM,	&rx51_fbmem0_config },
-	{ OMAP_TAG_FBMEM,	&rx51_fbmem1_config },
-	{ OMAP_TAG_FBMEM,	&rx51_fbmem2_config },
-	{ OMAP_TAG_LCD,		&rx51_lcd_config },
-};
-
-static void __init rx51_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);
-}
-
 extern void __init rx51_peripherals_init(void);
 
 #ifdef CONFIG_OMAP_MUX
@@ -127,11 +95,15 @@
 
 static void __init rx51_init(void)
 {
+	struct omap_sdrc_params *sdrc_params;
+
 	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();
+
+	sdrc_params = nokia_get_sdram_timings();
+	omap_sdrc_init(sdrc_params, sdrc_params);
+
 	usb_musb_init(&musb_board_data);
 	rx51_peripherals_init();
 
@@ -142,12 +114,6 @@
 	platform_device_register(&leds_gpio);
 }
 
-static void __init rx51_map_io(void)
-{
-	omap2_set_globals_3xxx();
-	omap34xx_map_common_io();
-}
-
 static void __init rx51_reserve(void)
 {
 	rx51_video_mem_init();
@@ -156,10 +122,10 @@
 
 MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
 	/* Maintainer: Lauri Leukkunen <lauri.leukkunen@nokia.com> */
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= rx51_reserve,
-	.map_io		= rx51_map_io,
-	.init_early	= rx51_init_early,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3430_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= rx51_init,
 	.timer		= &omap3_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-rx51-peripherals.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-rx51-peripherals.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-rx51-peripherals.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-rx51-peripherals.c	2012-01-04 18:55:44.000000000 -0500
@@ -193,7 +193,7 @@
 static void __init rx51_charger_init(void)
 {
 	WARN_ON(gpio_request_one(RX51_USB_TRANSCEIVER_RST_GPIO,
-		GPIOF_OUT_INIT_LOW, "isp1704_reset"));
+		GPIOF_OUT_INIT_HIGH, "isp1704_reset"));
 
 	platform_device_register(&rx51_charger_device);
 }
@@ -900,7 +900,6 @@
 };
 
 static struct tpa6130a2_platform_data rx51_tpa6130a2_data __initdata_or_module = {
-	.id			= TPA6130A2,
 	.power_gpio		= 98,
 };
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-ti8168evm.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-ti8168evm.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-ti8168evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-ti8168evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,30 +27,24 @@
 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(void)
 {
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	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,
+	.atag_offset	= 0x100,
 	.map_io		= ti8168_evm_map_io,
-	.init_early	= ti8168_init_early,
+	.init_early	= ti816x_init_early,
 	.init_irq	= ti816x_init_irq,
 	.timer		= &omap3_timer,
 	.init_machine	= ti8168_evm_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/board-zoom.c linux-libre-3.2-gnu/arch/arm/mach-omap2/board-zoom.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/board-zoom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/board-zoom.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,17 +34,6 @@
 
 #define ZOOM3_EHCI_RESET_GPIO		64
 
-static void __init omap_zoom_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	if (machine_is_omap_zoom2())
-		omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-					  mt46h32m32lf6_sdrc_params);
-	else if (machine_is_omap_zoom3())
-		omap2_init_common_devices(h8mbx00u0mer0em_sdrc_params,
-					  h8mbx00u0mer0em_sdrc_params);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* WLAN IRQ - GPIO 162 */
@@ -129,24 +118,32 @@
 						ZOOM_NAND_CS, NAND_BUSWIDTH_16);
 	zoom_debugboard_init();
 	zoom_peripherals_init();
+
+	if (machine_is_omap_zoom2())
+		omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+					  mt46h32m32lf6_sdrc_params);
+	else if (machine_is_omap_zoom3())
+		omap_sdrc_init(h8mbx00u0mer0em_sdrc_params,
+					  h8mbx00u0mer0em_sdrc_params);
+
 	zoom_display_init();
 }
 
 MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap_zoom_init_early,
+	.init_early	= omap3430_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_zoom_init,
 	.timer		= &omap3_timer,
 MACHINE_END
 
 MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
-	.boot_params	= 0x80000100,
+	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap_zoom_init_early,
+	.init_early	= omap3630_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_zoom_init,
 	.timer		= &omap3_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/clkt_dpll.c linux-libre-3.2-gnu/arch/arm/mach-omap2/clkt_dpll.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/clkt_dpll.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/clkt_dpll.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,10 +46,19 @@
 					 (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE))
 
 /* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
-#define DPLL_FINT_BAND1_MIN		750000
-#define DPLL_FINT_BAND1_MAX		2100000
-#define DPLL_FINT_BAND2_MIN		7500000
-#define DPLL_FINT_BAND2_MAX		21000000
+#define OMAP3430_DPLL_FINT_BAND1_MIN	750000
+#define OMAP3430_DPLL_FINT_BAND1_MAX	2100000
+#define OMAP3430_DPLL_FINT_BAND2_MIN	7500000
+#define OMAP3430_DPLL_FINT_BAND2_MAX	21000000
+
+/*
+ * DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx.
+ * From device data manual section 4.3 "DPLL and DLL Specifications".
+ */
+#define OMAP3PLUS_DPLL_FINT_JTYPE_MIN	500000
+#define OMAP3PLUS_DPLL_FINT_JTYPE_MAX	2500000
+#define OMAP3PLUS_DPLL_FINT_MIN		32000
+#define OMAP3PLUS_DPLL_FINT_MAX		52000000
 
 /* _dpll_test_fint() return codes */
 #define DPLL_FINT_UNDERFLOW		-1
@@ -71,33 +80,43 @@
 static int _dpll_test_fint(struct clk *clk, u8 n)
 {
 	struct dpll_data *dd;
-	long fint;
+	long fint, fint_min, fint_max;
 	int ret = 0;
 
 	dd = clk->dpll_data;
 
 	/* DPLL divider must result in a valid jitter correction val */
 	fint = clk->parent->rate / n;
-	if (fint < DPLL_FINT_BAND1_MIN) {
 
+	if (cpu_is_omap24xx()) {
+		/* Should not be called for OMAP2, so warn if it is called */
+		WARN(1, "No fint limits available for OMAP2!\n");
+		return DPLL_FINT_INVALID;
+	} else if (cpu_is_omap3430()) {
+		fint_min = OMAP3430_DPLL_FINT_BAND1_MIN;
+		fint_max = OMAP3430_DPLL_FINT_BAND2_MAX;
+	} else if (dd->flags & DPLL_J_TYPE) {
+		fint_min = OMAP3PLUS_DPLL_FINT_JTYPE_MIN;
+		fint_max = OMAP3PLUS_DPLL_FINT_JTYPE_MAX;
+	} else {
+		fint_min = OMAP3PLUS_DPLL_FINT_MIN;
+		fint_max = OMAP3PLUS_DPLL_FINT_MAX;
+	}
+
+	if (fint < fint_min) {
 		pr_debug("rejecting n=%d due to Fint failure, "
 			 "lowering max_divider\n", n);
 		dd->max_divider = n;
 		ret = DPLL_FINT_UNDERFLOW;
-
-	} else if (fint > DPLL_FINT_BAND1_MAX &&
-		   fint < DPLL_FINT_BAND2_MIN) {
-
-		pr_debug("rejecting n=%d due to Fint failure\n", n);
-		ret = DPLL_FINT_INVALID;
-
-	} else if (fint > DPLL_FINT_BAND2_MAX) {
-
+	} else if (fint > fint_max) {
 		pr_debug("rejecting n=%d due to Fint failure, "
 			 "boosting min_divider\n", n);
 		dd->min_divider = n;
 		ret = DPLL_FINT_INVALID;
-
+	} else if (cpu_is_omap3430() && fint > OMAP3430_DPLL_FINT_BAND1_MAX &&
+		   fint < OMAP3430_DPLL_FINT_BAND2_MIN) {
+		pr_debug("rejecting n=%d due to Fint failure\n", n);
+		ret = DPLL_FINT_INVALID;
 	}
 
 	return ret;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/clock2420_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/clock2420_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/clock2420_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/clock2420_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -1898,6 +1898,42 @@
 	CLK(NULL,	"pka_ick",	&pka_ick,	CK_242X),
 	CLK(NULL,	"usb_fck",	&usb_fck,	CK_242X),
 	CLK("musb-hdrc",	"fck",	&osc_ck,	CK_242X),
+	CLK("omap_timer.1",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.2",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.3",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.4",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.5",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.6",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.7",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.8",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.9",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.10",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.11",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.12",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.1",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.2",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.3",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.4",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.5",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.6",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.7",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.8",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.9",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.10",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.11",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.12",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.1",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.2",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.3",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.4",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.5",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.6",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.7",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.8",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.9",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.10",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.11",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.12",	"alt_ck",	&alt_ck,	CK_243X),
 };
 
 /*
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/clock2430_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/clock2430_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/clock2430_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/clock2430_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -1998,6 +1998,42 @@
 	CLK(NULL,	"mdm_intc_ick",	&mdm_intc_ick,	CK_243X),
 	CLK("omap_hsmmc.0", "mmchsdb_fck",	&mmchsdb1_fck,	CK_243X),
 	CLK("omap_hsmmc.1", "mmchsdb_fck",	&mmchsdb2_fck,	CK_243X),
+	CLK("omap_timer.1",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.2",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.3",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.4",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.5",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.6",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.7",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.8",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.9",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.10",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.11",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.12",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.1",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.2",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.3",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.4",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.5",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.6",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.7",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.8",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.9",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.10",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.11",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.12",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.1",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.2",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.3",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.4",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.5",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.6",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.7",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.8",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.9",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.10",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.11",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.12",	"alt_ck",	&alt_ck,	CK_243X),
 };
 
 /*
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/clock3xxx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/clock3xxx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/clock3xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/clock3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -3464,6 +3464,30 @@
 	CLK("musb-am35x",	"fck",		&hsotgusb_fck_am35xx,	CK_AM35XX),
 	CLK(NULL,	"hecc_ck",	&hecc_ck,	CK_AM35XX),
 	CLK(NULL,	"uart4_ick",	&uart4_ick_am35xx,	CK_AM35XX),
+	CLK("omap_timer.1",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.2",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.3",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.4",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.5",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.6",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.7",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.8",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.9",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.10",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.11",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.12",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.1",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.2",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.3",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.4",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.5",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.6",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.7",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.8",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.9",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.10",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.11",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.12",	"sys_ck",	&sys_ck,	CK_3XXX),
 };
 
 
@@ -3472,7 +3496,16 @@
 	struct omap_clk *c;
 	u32 cpu_clkflg = 0;
 
-	if (cpu_is_omap3517()) {
+	/*
+	 * 3505 must be tested before 3517, since 3517 returns true
+	 * for both AM3517 chips and AM3517 family chips, which
+	 * includes 3505.  Unfortunately there's no obvious family
+	 * test for 3517/3505 :-(
+	 */
+	if (cpu_is_omap3505()) {
+		cpu_mask = RATE_IN_34XX;
+		cpu_clkflg = CK_3505;
+	} else if (cpu_is_omap3517()) {
 		cpu_mask = RATE_IN_34XX;
 		cpu_clkflg = CK_3517;
 	} else if (cpu_is_omap3505()) {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/clock44xx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/clock44xx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/clock44xx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/clock44xx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -270,8 +270,8 @@
 	.dpll_data	= &dpll_abe_dd,
 	.init		= &omap2_init_dpll_parent,
 	.ops		= &clkops_omap3_noncore_dpll_ops,
-	.recalc		= &omap3_dpll_recalc,
-	.round_rate	= &omap2_dpll_round_rate,
+	.recalc		= &omap4_dpll_regm4xen_recalc,
+	.round_rate	= &omap4_dpll_regm4xen_round_rate,
 	.set_rate	= &omap3_noncore_dpll_set_rate,
 };
 
@@ -1195,11 +1195,25 @@
 	.recalc		= &omap2_clksel_recalc,
 };
 
+static const struct clksel_rate div2_2to1_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_4430 },
+	{ .div = 2, .val = 0, .flags = RATE_IN_4430 },
+	{ .div = 0 },
+};
+
+static const struct clksel ocp_abe_iclk_div[] = {
+	{ .parent = &aess_fclk, .rates = div2_2to1_rates },
+	{ .parent = NULL },
+};
+
 static struct clk ocp_abe_iclk = {
 	.name		= "ocp_abe_iclk",
 	.parent		= &aess_fclk,
+	.clksel		= ocp_abe_iclk_div,
+	.clksel_reg	= OMAP4430_CM1_ABE_AESS_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_AESS_FCLK_MASK,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk per_abe_24m_fclk = {
@@ -1398,9 +1412,9 @@
 };
 
 static const struct clksel_rate div3_8to32_rates[] = {
-	{ .div = 8, .val = 0, .flags = RATE_IN_44XX },
-	{ .div = 16, .val = 1, .flags = RATE_IN_44XX },
-	{ .div = 32, .val = 2, .flags = RATE_IN_44XX },
+	{ .div = 8, .val = 0, .flags = RATE_IN_4460 },
+	{ .div = 16, .val = 1, .flags = RATE_IN_4460 },
+	{ .div = 32, .val = 2, .flags = RATE_IN_4460 },
 	{ .div = 0 },
 };
 
@@ -3363,6 +3377,28 @@
 	CLK("usbhs-omap.0",	"usbhost_ick",		&dummy_ck,		CK_443X),
 	CLK("usbhs-omap.0",	"usbtll_fck",		&dummy_ck,	CK_443X),
 	CLK("omap_wdt",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_timer.1",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.2",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.3",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.4",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.5",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.6",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.7",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.8",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.9",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.10",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.11",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.1",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.2",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.3",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.4",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.9",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.10",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.11",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.5",	"sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("omap_timer.6",	"sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("omap_timer.7",	"sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("omap_timer.8",	"sys_ck",	&syc_clk_div_ck,	CK_443X),
 };
 
 int __init omap4xxx_clk_init(void)
@@ -3370,12 +3406,12 @@
 	struct omap_clk *c;
 	u32 cpu_clkflg;
 
-	if (cpu_is_omap44xx()) {
+	if (cpu_is_omap443x()) {
 		cpu_mask = RATE_IN_4430;
 		cpu_clkflg = CK_443X;
 	} else if (cpu_is_omap446x()) {
-		cpu_mask = RATE_IN_4460;
-		cpu_clkflg = CK_446X;
+		cpu_mask = RATE_IN_4460 | RATE_IN_4430;
+		cpu_clkflg = CK_446X | CK_443X;
 	} else {
 		return 0;
 	}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/clock44xx.h linux-libre-3.2-gnu/arch/arm/mach-omap2/clock44xx.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/clock44xx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/clock44xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,13 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
 #define __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
 
+/*
+ * OMAP4430_REGM4XEN_MULT: If the CM_CLKMODE_DPLL_ABE.DPLL_REGM4XEN bit is
+ *    set, then the DPLL's lock frequency is multiplied by 4 (OMAP4430 TRM
+ *    vV Section 3.6.3.3.1 "DPLLs Output Clocks Parameters")
+ */
+#define OMAP4430_REGM4XEN_MULT	4
+
 int omap4xxx_clk_init(void);
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -52,8 +52,6 @@
 	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 */
 
@@ -98,8 +96,6 @@
 	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 */
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomain44xx.c linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomain44xx.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomain44xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomain44xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -52,8 +52,6 @@
 	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 */
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomain.c linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomain.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomain.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomain.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/device.h>
 #include <linux/list.h>
 #include <linux/errno.h>
+#include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/limits.h>
@@ -73,9 +74,6 @@
 	if (!clkdm || !clkdm->name)
 		return -EINVAL;
 
-	if (!omap_chip_is(clkdm->omap_chip))
-		return -EINVAL;
-
 	pwrdm = pwrdm_lookup(clkdm->pwrdm.name);
 	if (!pwrdm) {
 		pr_err("clockdomain: %s: powerdomain %s does not exist\n",
@@ -105,13 +103,10 @@
 {
 	struct clkdm_dep *cd;
 
-	if (!clkdm || !deps || !omap_chip_is(clkdm->omap_chip))
+	if (!clkdm || !deps)
 		return ERR_PTR(-EINVAL);
 
 	for (cd = deps; 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);
 
@@ -148,9 +143,6 @@
 	if (!autodep)
 		return;
 
-	if (!omap_chip_is(autodep->omap_chip))
-		return;
-
 	clkdm = clkdm_lookup(autodep->clkdm.name);
 	if (!clkdm) {
 		pr_err("clockdomain: autodeps: clockdomain %s does not exist\n",
@@ -182,9 +174,6 @@
 		if (IS_ERR(autodep->clkdm.ptr))
 			continue;
 
-		if (!omap_chip_is(autodep->omap_chip))
-			continue;
-
 		pr_debug("clockdomain: adding %s sleepdep/wkdep for "
 			 "clkdm %s\n", autodep->clkdm.ptr->name,
 			 clkdm->name);
@@ -216,9 +205,6 @@
 		if (IS_ERR(autodep->clkdm.ptr))
 			continue;
 
-		if (!omap_chip_is(autodep->omap_chip))
-			continue;
-
 		pr_debug("clockdomain: removing %s sleepdep/wkdep for "
 			 "clkdm %s\n", autodep->clkdm.ptr->name,
 			 clkdm->name);
@@ -243,8 +229,6 @@
 	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);
@@ -257,43 +241,113 @@
 /* Public functions */
 
 /**
- * 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
+ * clkdm_register_platform_funcs - register clockdomain implementation fns
+ * @co: 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,
- * register all that are available on the current platform. Similarly,
- * if a pointer to an array of clockdomain autodependencies
- * @init_autodeps was provided, register those.  No return value.
+ * Register the list of function pointers used to implement the
+ * clockdomain functions on different OMAP SoCs.  Should be called
+ * before any other clkdm_register*() function.  Returns -EINVAL if
+ * @co is null, -EEXIST if platform functions have already been
+ * registered, or 0 upon success.
  */
-void clkdm_init(struct clockdomain **clkdms,
-		struct clkdm_autodep *init_autodeps,
-		struct clkdm_ops *custom_funcs)
+int clkdm_register_platform_funcs(struct clkdm_ops *co)
+{
+	if (!co)
+		return -EINVAL;
+
+	if (arch_clkdm)
+		return -EEXIST;
+
+	arch_clkdm = co;
+
+	return 0;
+};
+
+/**
+ * clkdm_register_clkdms - register SoC clockdomains
+ * @cs: pointer to an array of struct clockdomain to register
+ *
+ * Register the clockdomains available on a particular OMAP SoC.  Must
+ * be called after clkdm_register_platform_funcs().  May be called
+ * multiple times.  Returns -EACCES if called before
+ * clkdm_register_platform_funcs(); -EINVAL if the argument @cs is
+ * null; or 0 upon success.
+ */
+int clkdm_register_clkdms(struct clockdomain **cs)
 {
 	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 (!arch_clkdm)
+		return -EACCES;
 
-	if (clkdms)
-		for (c = clkdms; *c; c++)
-			_clkdm_register(*c);
+	if (!cs)
+		return -EINVAL;
+
+	for (c = cs; *c; c++)
+		_clkdm_register(*c);
+
+	return 0;
+}
+
+/**
+ * clkdm_register_autodeps - register autodeps (if required)
+ * @ia: pointer to a static array of struct clkdm_autodep to register
+ *
+ * Register clockdomain "automatic dependencies."  These are
+ * clockdomain wakeup and sleep dependencies that are automatically
+ * added whenever the first clock inside a clockdomain is enabled, and
+ * removed whenever the last clock inside a clockdomain is disabled.
+ * These are currently only used on OMAP3 devices, and are deprecated,
+ * since they waste energy.  However, until the OMAP2/3 IP block
+ * enable/disable sequence can be converted to match the OMAP4
+ * sequence, they are needed.
+ *
+ * Must be called only after all of the SoC clockdomains are
+ * registered, since the function will resolve autodep clockdomain
+ * names into clockdomain pointers.
+ *
+ * The struct clkdm_autodep @ia array must be static, as this function
+ * does not copy the array elements.
+ *
+ * Returns -EACCES if called before any clockdomains have been
+ * registered, -EINVAL if called with a null @ia argument, -EEXIST if
+ * autodeps have already been registered, or 0 upon success.
+ */
+int clkdm_register_autodeps(struct clkdm_autodep *ia)
+{
+	struct clkdm_autodep *a = NULL;
+
+	if (list_empty(&clkdm_list))
+		return -EACCES;
+
+	if (!ia)
+		return -EINVAL;
 
-	autodeps = init_autodeps;
 	if (autodeps)
-		for (autodep = autodeps; autodep->clkdm.ptr; autodep++)
-			_autodep_lookup(autodep);
+		return -EEXIST;
+
+	autodeps = ia;
+	for (a = autodeps; a->clkdm.ptr; a++)
+		_autodep_lookup(a);
+
+	return 0;
+}
+
+/**
+ * clkdm_complete_init - set up the clockdomain layer
+ *
+ * Put all clockdomains into software-supervised mode; PM code should
+ * later enable hardware-supervised mode as appropriate.  Must be
+ * called after clkdm_register_clkdms().  Returns -EACCES if called
+ * before clkdm_register_clkdms(), or 0 upon success.
+ */
+int clkdm_complete_init(void)
+{
+	struct clockdomain *clkdm;
+
+	if (list_empty(&clkdm_list))
+		return -EACCES;
 
-	/*
-	 * Put all clockdomains into software-supervised mode; PM code
-	 * should later enable hardware-supervised mode as appropriate
-	 */
 	list_for_each_entry(clkdm, &clkdm_list, node) {
 		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
 			clkdm_wakeup(clkdm);
@@ -306,6 +360,8 @@
 		_resolve_clkdm_deps(clkdm, clkdm->sleepdep_srcs);
 		clkdm_clear_all_sleepdeps(clkdm);
 	}
+
+	return 0;
 }
 
 /**
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomain.h linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomain.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomain.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomain.h	2012-01-04 18:55:44.000000000 -0500
@@ -45,7 +45,6 @@
 /**
  * struct clkdm_autodep - clkdm deps to add when entering/exiting hwsup mode
  * @clkdm: clockdomain to add wkdep+sleepdep on - set name member only
- * @omap_chip: OMAP chip types that this autodep is valid on
  *
  * A clockdomain that should have wkdeps and sleepdeps added when a
  * clockdomain should stay active in hwsup mode; and conversely,
@@ -60,14 +59,12 @@
 		const char *name;
 		struct clockdomain *ptr;
 	} clkdm;
-	const struct omap_chip_id omap_chip;
 };
 
 /**
  * struct clkdm_dep - encode dependencies between clockdomains
  * @clkdm_name: clockdomain name
  * @clkdm: pointer to the struct clockdomain of @clkdm_name
- * @omap_chip: OMAP chip types that this dependency is valid on
  * @wkdep_usecount: Number of wakeup dependencies causing this clkdm to wake
  * @sleepdep_usecount: Number of sleep deps that could prevent clkdm from idle
  *
@@ -81,7 +78,6 @@
 	struct clockdomain *clkdm;
 	atomic_t wkdep_usecount;
 	atomic_t sleepdep_usecount;
-	const struct omap_chip_id omap_chip;
 };
 
 /* Possible flags for struct clockdomain._flags */
@@ -101,7 +97,6 @@
  * @clkdm_offs: (OMAP4 only) CM clockdomain register offset
  * @wkdep_srcs: Clockdomains that can be told to wake this powerdomain up
  * @sleepdep_srcs: Clockdomains that can be told to keep this clkdm from inact
- * @omap_chip: OMAP chip types that this clockdomain is valid on
  * @usecount: Usecount tracking
  * @node: list_head to link all clockdomains together
  *
@@ -126,7 +121,6 @@
 	const u16 clkdm_offs;
 	struct clkdm_dep *wkdep_srcs;
 	struct clkdm_dep *sleepdep_srcs;
-	const struct omap_chip_id omap_chip;
 	atomic_t usecount;
 	struct list_head node;
 	spinlock_t lock;
@@ -166,8 +160,11 @@
 	int	(*clkdm_clk_disable)(struct clockdomain *clkdm);
 };
 
-void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps,
-			struct clkdm_ops *custom_funcs);
+int clkdm_register_platform_funcs(struct clkdm_ops *co);
+int clkdm_register_autodeps(struct clkdm_autodep *ia);
+int clkdm_register_clkdms(struct clockdomain **c);
+int clkdm_complete_init(void);
+
 struct clockdomain *clkdm_lookup(const char *name);
 
 int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
@@ -195,7 +192,8 @@
 int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh);
 int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh);
 
-extern void __init omap2xxx_clockdomains_init(void);
+extern void __init omap242x_clockdomains_init(void);
+extern void __init omap243x_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);
@@ -205,4 +203,10 @@
 extern struct clkdm_ops omap3_clkdm_operations;
 extern struct clkdm_ops omap4_clkdm_operations;
 
+extern struct clkdm_dep gfx_24xx_wkdeps[];
+extern struct clkdm_dep dsp_24xx_wkdeps[];
+extern struct clockdomain wkup_common_clkdm;
+extern struct clockdomain prm_common_clkdm;
+extern struct clockdomain cm_common_clkdm;
+
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomains2420_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomains2420_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomains2420_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomains2420_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,154 @@
+/*
+ * OMAP2420 clockdomains
+ *
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni HÃ¶gander
+ *
+ * This file contains clockdomains and clockdomain wakeup dependencies
+ * for OMAP2420 chips.  Some notes:
+ *
+ * A useful validation rule for struct clockdomain: Any clockdomain
+ * referenced by a wkdep_srcs must have a dep_bit assigned.  So
+ * wkdep_srcs are really just software-controllable dependencies.
+ * Non-software-controllable dependencies do exist, but they are not
+ * encoded below (yet).
+ *
+ * 24xx does not support programmable sleep dependencies (SLEEPDEP)
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}.  The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ *
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
+ */
+
+/*
+ * To-Do List
+ * -> Port the Sleep/Wakeup dependencies for the domains
+ *    from the Power domain framework
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "prm-regbits-24xx.h"
+
+/*
+ * Clockdomain dependencies for wkdeps
+ *
+ * XXX Hardware dependencies (e.g., dependencies that cannot be
+ * changed in software) are not included here yet, but should be.
+ */
+
+/* Wakeup dependency source arrays */
+
+/* 2420-specific possible wakeup dependencies */
+
+/* 2420 PM_WKDEP_MPU: CORE, DSP, WKUP */
+static struct clkdm_dep mpu_2420_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "dsp_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/* 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP */
+static struct clkdm_dep core_2420_wkdeps[] = {
+	{ .clkdm_name = "dsp_clkdm" },
+	{ .clkdm_name = "gfx_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/*
+ * 2420-only clockdomains
+ */
+
+static struct clockdomain mpu_2420_clkdm = {
+	.name		= "mpu_clkdm",
+	.pwrdm		= { .name = "mpu_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.wkdep_srcs	= mpu_2420_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
+};
+
+static struct clockdomain iva1_2420_clkdm = {
+	.name		= "iva1_clkdm",
+	.pwrdm		= { .name = "dsp_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
+	.wkdep_srcs	= dsp_24xx_wkdeps,
+	.clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK,
+};
+
+static struct clockdomain dsp_2420_clkdm = {
+	.name		= "dsp_clkdm",
+	.pwrdm		= { .name = "dsp_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
+};
+
+static struct clockdomain gfx_2420_clkdm = {
+	.name		= "gfx_clkdm",
+	.pwrdm		= { .name = "gfx_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= gfx_24xx_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
+};
+
+static struct clockdomain core_l3_2420_clkdm = {
+	.name		= "core_l3_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.wkdep_srcs	= core_2420_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
+};
+
+static struct clockdomain core_l4_2420_clkdm = {
+	.name		= "core_l4_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.wkdep_srcs	= core_2420_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
+};
+
+static struct clockdomain dss_2420_clkdm = {
+	.name		= "dss_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
+};
+
+static struct clockdomain *clockdomains_omap242x[] __initdata = {
+	&wkup_common_clkdm,
+	&cm_common_clkdm,
+	&prm_common_clkdm,
+	&mpu_2420_clkdm,
+	&iva1_2420_clkdm,
+	&dsp_2420_clkdm,
+	&gfx_2420_clkdm,
+	&core_l3_2420_clkdm,
+	&core_l4_2420_clkdm,
+	&dss_2420_clkdm,
+	NULL,
+};
+
+void __init omap242x_clockdomains_init(void)
+{
+	if (!cpu_is_omap242x())
+		return;
+
+	clkdm_register_platform_funcs(&omap2_clkdm_operations);
+	clkdm_register_clkdms(clockdomains_omap242x);
+	clkdm_complete_init();
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomains2430_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomains2430_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomains2430_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomains2430_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,181 @@
+/*
+ * OMAP2xxx clockdomains
+ *
+ * Copyright (C) 2008-2009 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni HÃ¶gander
+ *
+ * This file contains clockdomains and clockdomain wakeup dependencies
+ * for OMAP2xxx chips.  Some notes:
+ *
+ * A useful validation rule for struct clockdomain: Any clockdomain
+ * referenced by a wkdep_srcs must have a dep_bit assigned.  So
+ * wkdep_srcs are really just software-controllable dependencies.
+ * Non-software-controllable dependencies do exist, but they are not
+ * encoded below (yet).
+ *
+ * 24xx does not support programmable sleep dependencies (SLEEPDEP)
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}.  The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ *
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
+ */
+
+/*
+ * To-Do List
+ * -> Port the Sleep/Wakeup dependencies for the domains
+ *    from the Power domain framework
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "prm-regbits-24xx.h"
+
+/*
+ * Clockdomain dependencies for wkdeps
+ *
+ * XXX Hardware dependencies (e.g., dependencies that cannot be
+ * changed in software) are not included here yet, but should be.
+ */
+
+/* Wakeup dependency source arrays */
+
+/* 2430-specific possible wakeup dependencies */
+
+/* 2430 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP, MDM */
+static struct clkdm_dep core_2430_wkdeps[] = {
+	{ .clkdm_name = "dsp_clkdm" },
+	{ .clkdm_name = "gfx_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ .clkdm_name = "mdm_clkdm" },
+	{ NULL },
+};
+
+/* 2430 PM_WKDEP_MPU: CORE, DSP, WKUP, MDM */
+static struct clkdm_dep mpu_2430_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "dsp_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ .clkdm_name = "mdm_clkdm" },
+	{ NULL },
+};
+
+/* 2430 PM_WKDEP_MDM: CORE, MPU, WKUP */
+static struct clkdm_dep mdm_2430_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/*
+ * 2430-only clockdomains
+ */
+
+static struct clockdomain mpu_2430_clkdm = {
+	.name		= "mpu_clkdm",
+	.pwrdm		= { .name = "mpu_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= mpu_2430_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
+};
+
+/* Another case of bit name collisions between several registers: EN_MDM */
+static struct clockdomain mdm_clkdm = {
+	.name		= "mdm_clkdm",
+	.pwrdm		= { .name = "mdm_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
+	.wkdep_srcs	= mdm_2430_wkdeps,
+	.clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK,
+};
+
+static struct clockdomain dsp_2430_clkdm = {
+	.name		= "dsp_clkdm",
+	.pwrdm		= { .name = "dsp_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
+	.wkdep_srcs	= dsp_24xx_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
+};
+
+static struct clockdomain gfx_2430_clkdm = {
+	.name		= "gfx_clkdm",
+	.pwrdm		= { .name = "gfx_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= gfx_24xx_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l3_2430_clkdm = {
+	.name		= "core_l3_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.dep_bit	= OMAP24XX_EN_CORE_SHIFT,
+	.wkdep_srcs	= core_2430_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l4_2430_clkdm = {
+	.name		= "core_l4_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.dep_bit	= OMAP24XX_EN_CORE_SHIFT,
+	.wkdep_srcs	= core_2430_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
+};
+
+static struct clockdomain dss_2430_clkdm = {
+	.name		= "dss_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
+};
+
+static struct clockdomain *clockdomains_omap243x[] __initdata = {
+	&wkup_common_clkdm,
+	&cm_common_clkdm,
+	&prm_common_clkdm,
+	&mpu_2430_clkdm,
+	&mdm_clkdm,
+	&dsp_2430_clkdm,
+	&gfx_2430_clkdm,
+	&core_l3_2430_clkdm,
+	&core_l4_2430_clkdm,
+	&dss_2430_clkdm,
+	NULL,
+};
+
+void __init omap243x_clockdomains_init(void)
+{
+	if (!cpu_is_omap243x())
+		return;
+
+	clkdm_register_platform_funcs(&omap2_clkdm_operations);
+	clkdm_register_clkdms(clockdomains_omap243x);
+	clkdm_complete_init();
+}
+
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
- * OMAP2/3 clockdomains
+ * OMAP2/3 clockdomain common data
  *
- * Copyright (C) 2008-2009 Texas Instruments, Inc.
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
  * Copyright (C) 2008-2010 Nokia Corporation
  *
  * Paul Walmsley, Jouni HÃ¶gander
@@ -51,374 +51,28 @@
  * changed in software) are not included here yet, but should be.
  */
 
-/* OMAP2/3-common wakeup dependencies */
-
-/*
- * 2420/2430 PM_WKDEP_GFX: CORE, MPU, WKUP
- * 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
- * 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
- * These can share data since they will never be present simultaneously
- * on the same device.
- */
-static struct clkdm_dep gfx_sgx_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
-					    CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
-					    CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-
-/* 24XX-specific possible dependencies */
-
-#ifdef CONFIG_ARCH_OMAP2
-
 /* Wakeup dependency source arrays */
 
-/* 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP */
-static struct clkdm_dep dsp_24xx_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{ NULL },
-};
-
-/*
- * 2420 PM_WKDEP_MPU: CORE, DSP, WKUP
- * 2430 adds MDM
- */
-static struct clkdm_dep mpu_24xx_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "dsp_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "mdm_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
-	},
-	{ NULL },
-};
-
-/*
- * 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP
- * 2430 adds MDM
- */
-static struct clkdm_dep core_24xx_wkdeps[] = {
-	{
-		.clkdm_name = "dsp_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "gfx_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "mdm_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
-	},
-	{ NULL },
-};
-
-#endif /* CONFIG_ARCH_OMAP2 */
-
-/* 2430-specific possible wakeup dependencies */
-
-#ifdef CONFIG_SOC_OMAP2430
-
-/* 2430 PM_WKDEP_MDM: CORE, MPU, WKUP */
-static struct clkdm_dep mdm_2430_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{ NULL },
-};
-
-#endif /* CONFIG_SOC_OMAP2430 */
-
-
-/* OMAP3-specific possible dependencies */
-
-#ifdef CONFIG_ARCH_OMAP3
-
-/* 3430: PM_WKDEP_PER: CORE, IVA2, MPU, WKUP */
-static struct clkdm_dep per_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430ES2: PM_WKDEP_USBHOST: CORE, IVA2, MPU, WKUP */
-static struct clkdm_dep usbhost_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER */
-static struct clkdm_dep mpu_3xxx_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "dss_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "per_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER */
-static struct clkdm_dep iva2_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "dss_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "per_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-
-/* 3430 PM_WKDEP_CAM: IVA2, MPU, WKUP */
-static struct clkdm_dep cam_wkdeps[] = {
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430 PM_WKDEP_DSS: IVA2, MPU, WKUP */
-static struct clkdm_dep dss_wkdeps[] = {
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430: PM_WKDEP_NEON: MPU */
-static struct clkdm_dep neon_wkdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-
-/* Sleep dependency source arrays for OMAP3-specific clkdms */
-
-/* 3430: CM_SLEEPDEP_DSS: MPU, IVA */
-static struct clkdm_dep dss_sleepdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430: CM_SLEEPDEP_PER: MPU, IVA */
-static struct clkdm_dep per_sleepdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA */
-static struct clkdm_dep usbhost_sleepdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
+/* 2xxx-specific possible dependencies */
 
-/* 3430: CM_SLEEPDEP_CAM: MPU */
-static struct clkdm_dep cam_sleepdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
+/* 2xxx PM_WKDEP_GFX: CORE, MPU, WKUP */
+struct clkdm_dep gfx_24xx_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
 	{ NULL },
 };
 
-/*
- * 3430ES1: CM_SLEEPDEP_GFX: MPU
- * 3430ES2: CM_SLEEPDEP_SGX: MPU
- * These can share data since they will never be present simultaneously
- * on the same device.
- */
-static struct clkdm_dep gfx_sgx_sleepdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
+/* 2xxx PM_WKDEP_DSP: CORE, MPU, WKUP */
+struct clkdm_dep dsp_24xx_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
 	{ NULL },
 };
 
-#endif /* CONFIG_ARCH_OMAP3 */
-
 
 /*
  * OMAP2/3-common clockdomains
@@ -430,439 +84,18 @@
  */
 
 /* This is an implicit clockdomain - it is never defined as such in TRM */
-static struct clockdomain wkup_clkdm = {
+struct clockdomain wkup_common_clkdm = {
 	.name		= "wkup_clkdm",
 	.pwrdm		= { .name = "wkup_pwrdm" },
 	.dep_bit	= OMAP_EN_WKUP_SHIFT,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
 };
 
-static struct clockdomain prm_clkdm = {
+struct clockdomain prm_common_clkdm = {
 	.name		= "prm_clkdm",
 	.pwrdm		= { .name = "wkup_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
 };
 
-static struct clockdomain cm_clkdm = {
+struct clockdomain cm_common_clkdm = {
 	.name		= "cm_clkdm",
 	.pwrdm		= { .name = "core_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
 };
-
-/*
- * 2420-only clockdomains
- */
-
-#if defined(CONFIG_SOC_OMAP2420)
-
-static struct clockdomain mpu_2420_clkdm = {
-	.name		= "mpu_clkdm",
-	.pwrdm		= { .name = "mpu_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.wkdep_srcs	= mpu_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain iva1_2420_clkdm = {
-	.name		= "iva1_clkdm",
-	.pwrdm		= { .name = "dsp_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
-	.wkdep_srcs	= dsp_24xx_wkdeps,
-	.clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain dsp_2420_clkdm = {
-	.name		= "dsp_clkdm",
-	.pwrdm		= { .name = "dsp_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain gfx_2420_clkdm = {
-	.name		= "gfx_clkdm",
-	.pwrdm		= { .name = "gfx_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= gfx_sgx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain core_l3_2420_clkdm = {
-	.name		= "core_l3_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.wkdep_srcs	= core_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain core_l4_2420_clkdm = {
-	.name		= "core_l4_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.wkdep_srcs	= core_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain dss_2420_clkdm = {
-	.name		= "dss_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-#endif   /* CONFIG_SOC_OMAP2420 */
-
-
-/*
- * 2430-only clockdomains
- */
-
-#if defined(CONFIG_SOC_OMAP2430)
-
-static struct clockdomain mpu_2430_clkdm = {
-	.name		= "mpu_clkdm",
-	.pwrdm		= { .name = "mpu_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= mpu_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-/* Another case of bit name collisions between several registers: EN_MDM */
-static struct clockdomain mdm_clkdm = {
-	.name		= "mdm_clkdm",
-	.pwrdm		= { .name = "mdm_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
-	.wkdep_srcs	= mdm_2430_wkdeps,
-	.clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-static struct clockdomain dsp_2430_clkdm = {
-	.name		= "dsp_clkdm",
-	.pwrdm		= { .name = "dsp_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
-	.wkdep_srcs	= dsp_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-static struct clockdomain gfx_2430_clkdm = {
-	.name		= "gfx_clkdm",
-	.pwrdm		= { .name = "gfx_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= gfx_sgx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-/*
- * XXX add usecounting for clkdm dependencies, otherwise the presence
- * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
- * could cause trouble
- */
-static struct clockdomain core_l3_2430_clkdm = {
-	.name		= "core_l3_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.dep_bit	= OMAP24XX_EN_CORE_SHIFT,
-	.wkdep_srcs	= core_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-/*
- * XXX add usecounting for clkdm dependencies, otherwise the presence
- * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
- * could cause trouble
- */
-static struct clockdomain core_l4_2430_clkdm = {
-	.name		= "core_l4_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.dep_bit	= OMAP24XX_EN_CORE_SHIFT,
-	.wkdep_srcs	= core_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-static struct clockdomain dss_2430_clkdm = {
-	.name		= "dss_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-#endif    /* CONFIG_SOC_OMAP2430 */
-
-
-/*
- * OMAP3 clockdomains
- */
-
-#if defined(CONFIG_ARCH_OMAP3)
-
-static struct clockdomain mpu_3xxx_clkdm = {
-	.name		= "mpu_clkdm",
-	.pwrdm		= { .name = "mpu_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
-	.dep_bit	= OMAP3430_EN_MPU_SHIFT,
-	.wkdep_srcs	= mpu_3xxx_wkdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain neon_clkdm = {
-	.name		= "neon_clkdm",
-	.pwrdm		= { .name = "neon_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= neon_wkdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain iva2_clkdm = {
-	.name		= "iva2_clkdm",
-	.pwrdm		= { .name = "iva2_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
-	.wkdep_srcs	= iva2_wkdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain gfx_3430es1_clkdm = {
-	.name		= "gfx_clkdm",
-	.pwrdm		= { .name = "gfx_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= gfx_sgx_wkdeps,
-	.sleepdep_srcs	= gfx_sgx_sleepdeps,
-	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
-};
-
-static struct clockdomain sgx_clkdm = {
-	.name		= "sgx_clkdm",
-	.pwrdm		= { .name = "sgx_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= gfx_sgx_wkdeps,
-	.sleepdep_srcs	= gfx_sgx_sleepdeps,
-	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
-};
-
-/*
- * The die-to-die clockdomain was documented in the 34xx ES1 TRM, but
- * then that information was removed from the 34xx ES2+ TRM.  It is
- * unclear whether the core is still there, but the clockdomain logic
- * is there, and must be programmed to an appropriate state if the
- * CORE clockdomain is to become inactive.
- */
-static struct clockdomain d2d_clkdm = {
-	.name		= "d2d_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/*
- * XXX add usecounting for clkdm dependencies, otherwise the presence
- * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
- * could cause trouble
- */
-static struct clockdomain core_l3_3xxx_clkdm = {
-	.name		= "core_l3_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.dep_bit	= OMAP3430_EN_CORE_SHIFT,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/*
- * XXX add usecounting for clkdm dependencies, otherwise the presence
- * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
- * could cause trouble
- */
-static struct clockdomain core_l4_3xxx_clkdm = {
-	.name		= "core_l4_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.dep_bit	= OMAP3430_EN_CORE_SHIFT,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/* Another case of bit name collisions between several registers: EN_DSS */
-static struct clockdomain dss_3xxx_clkdm = {
-	.name		= "dss_clkdm",
-	.pwrdm		= { .name = "dss_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
-	.wkdep_srcs	= dss_wkdeps,
-	.sleepdep_srcs	= dss_sleepdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain cam_clkdm = {
-	.name		= "cam_clkdm",
-	.pwrdm		= { .name = "cam_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= cam_wkdeps,
-	.sleepdep_srcs	= cam_sleepdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain usbhost_clkdm = {
-	.name		= "usbhost_clkdm",
-	.pwrdm		= { .name = "usbhost_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= usbhost_wkdeps,
-	.sleepdep_srcs	= usbhost_sleepdeps,
-	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
-};
-
-static struct clockdomain per_clkdm = {
-	.name		= "per_clkdm",
-	.pwrdm		= { .name = "per_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP3430_EN_PER_SHIFT,
-	.wkdep_srcs	= per_wkdeps,
-	.sleepdep_srcs	= per_sleepdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/*
- * Disable hw supervised mode for emu_clkdm, because emu_pwrdm is
- * switched of even if sdti is in use
- */
-static struct clockdomain emu_clkdm = {
-	.name		= "emu_clkdm",
-	.pwrdm		= { .name = "emu_pwrdm" },
-	.flags		= /* CLKDM_CAN_ENABLE_AUTO |  */CLKDM_CAN_SWSUP,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll1_clkdm = {
-	.name		= "dpll1_clkdm",
-	.pwrdm		= { .name = "dpll1_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll2_clkdm = {
-	.name		= "dpll2_clkdm",
-	.pwrdm		= { .name = "dpll2_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll3_clkdm = {
-	.name		= "dpll3_clkdm",
-	.pwrdm		= { .name = "dpll3_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll4_clkdm = {
-	.name		= "dpll4_clkdm",
-	.pwrdm		= { .name = "dpll4_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll5_clkdm = {
-	.name		= "dpll5_clkdm",
-	.pwrdm		= { .name = "dpll5_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
-};
-
-#endif   /* CONFIG_ARCH_OMAP3 */
-
-/*
- * Clockdomain hwsup dependencies (OMAP3 only)
- */
-
-static struct clkdm_autodep clkdm_autodeps[] = {
-	{
-		.clkdm	   = { .name = "mpu_clkdm" },
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm	   = { .name = "iva2_clkdm" },
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm	   = { .name = NULL },
-	}
-};
-
-static struct clockdomain *clockdomains_omap2[] __initdata = {
-	&wkup_clkdm,
-	&cm_clkdm,
-	&prm_clkdm,
-
-#ifdef CONFIG_SOC_OMAP2420
-	&mpu_2420_clkdm,
-	&iva1_2420_clkdm,
-	&dsp_2420_clkdm,
-	&gfx_2420_clkdm,
-	&core_l3_2420_clkdm,
-	&core_l4_2420_clkdm,
-	&dss_2420_clkdm,
-#endif
-
-#ifdef CONFIG_SOC_OMAP2430
-	&mpu_2430_clkdm,
-	&mdm_clkdm,
-	&dsp_2430_clkdm,
-	&gfx_2430_clkdm,
-	&core_l3_2430_clkdm,
-	&core_l4_2430_clkdm,
-	&dss_2430_clkdm,
-#endif
-
-#ifdef CONFIG_ARCH_OMAP3
-	&mpu_3xxx_clkdm,
-	&neon_clkdm,
-	&iva2_clkdm,
-	&gfx_3430es1_clkdm,
-	&sgx_clkdm,
-	&d2d_clkdm,
-	&core_l3_3xxx_clkdm,
-	&core_l4_3xxx_clkdm,
-	&dss_3xxx_clkdm,
-	&cam_clkdm,
-	&usbhost_clkdm,
-	&per_clkdm,
-	&emu_clkdm,
-	&dpll1_clkdm,
-	&dpll2_clkdm,
-	&dpll3_clkdm,
-	&dpll4_clkdm,
-	&dpll5_clkdm,
-#endif
-	NULL,
-};
-
-void __init omap2xxx_clockdomains_init(void)
-{
-	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-3.1-gnu/arch/arm/mach-omap2/clockdomains3xxx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomains3xxx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomains3xxx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomains3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,398 @@
+/*
+ * OMAP3xxx clockdomains
+ *
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni HÃ¶gander
+ *
+ * This file contains clockdomains and clockdomain wakeup/sleep
+ * dependencies for the OMAP3xxx chips.  Some notes:
+ *
+ * A useful validation rule for struct clockdomain: Any clockdomain
+ * referenced by a wkdep_srcs or sleepdep_srcs array must have a
+ * dep_bit assigned.  So wkdep_srcs/sleepdep_srcs are really just
+ * software-controllable dependencies.  Non-software-controllable
+ * dependencies do exist, but they are not encoded below (yet).
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}.  The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ *
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
+ */
+
+/*
+ * To-Do List
+ * -> Port the Sleep/Wakeup dependencies for the domains
+ *    from the Power domain framework
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-34xx.h"
+#include "prm-regbits-34xx.h"
+
+/*
+ * Clockdomain dependencies for wkdeps/sleepdeps
+ *
+ * XXX Hardware dependencies (e.g., dependencies that cannot be
+ * changed in software) are not included here yet, but should be.
+ */
+
+/* OMAP3-specific possible dependencies */
+
+/*
+ * 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
+ * 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
+ */
+static struct clkdm_dep gfx_sgx_3xxx_wkdeps[] = {
+	{ .clkdm_name = "iva2_clkdm", },
+	{ .clkdm_name = "mpu_clkdm", },
+	{ .clkdm_name = "wkup_clkdm", },
+	{ NULL },
+};
+
+/* 3430: PM_WKDEP_PER: CORE, IVA2, MPU, WKUP */
+static struct clkdm_dep per_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/* 3430ES2: PM_WKDEP_USBHOST: CORE, IVA2, MPU, WKUP */
+static struct clkdm_dep usbhost_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER */
+static struct clkdm_dep mpu_3xxx_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ .clkdm_name = "dss_clkdm" },
+	{ .clkdm_name = "per_clkdm" },
+	{ NULL },
+};
+
+/* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER */
+static struct clkdm_dep iva2_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ .clkdm_name = "dss_clkdm" },
+	{ .clkdm_name = "per_clkdm" },
+	{ NULL },
+};
+
+/* 3430 PM_WKDEP_CAM: IVA2, MPU, WKUP */
+static struct clkdm_dep cam_wkdeps[] = {
+	{ .clkdm_name = "iva2_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/* 3430 PM_WKDEP_DSS: IVA2, MPU, WKUP */
+static struct clkdm_dep dss_wkdeps[] = {
+	{ .clkdm_name = "iva2_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/* 3430: PM_WKDEP_NEON: MPU */
+static struct clkdm_dep neon_wkdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ NULL },
+};
+
+/* Sleep dependency source arrays for OMAP3-specific clkdms */
+
+/* 3430: CM_SLEEPDEP_DSS: MPU, IVA */
+static struct clkdm_dep dss_sleepdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ NULL },
+};
+
+/* 3430: CM_SLEEPDEP_PER: MPU, IVA */
+static struct clkdm_dep per_sleepdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ NULL },
+};
+
+/* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA */
+static struct clkdm_dep usbhost_sleepdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ NULL },
+};
+
+/* 3430: CM_SLEEPDEP_CAM: MPU */
+static struct clkdm_dep cam_sleepdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ NULL },
+};
+
+/*
+ * 3430ES1: CM_SLEEPDEP_GFX: MPU
+ * 3430ES2: CM_SLEEPDEP_SGX: MPU
+ * These can share data since they will never be present simultaneously
+ * on the same device.
+ */
+static struct clkdm_dep gfx_sgx_sleepdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ NULL },
+};
+
+/*
+ * OMAP3 clockdomains
+ */
+
+static struct clockdomain mpu_3xxx_clkdm = {
+	.name		= "mpu_clkdm",
+	.pwrdm		= { .name = "mpu_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
+	.dep_bit	= OMAP3430_EN_MPU_SHIFT,
+	.wkdep_srcs	= mpu_3xxx_wkdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
+};
+
+static struct clockdomain neon_clkdm = {
+	.name		= "neon_clkdm",
+	.pwrdm		= { .name = "neon_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= neon_wkdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK,
+};
+
+static struct clockdomain iva2_clkdm = {
+	.name		= "iva2_clkdm",
+	.pwrdm		= { .name = "iva2_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
+	.wkdep_srcs	= iva2_wkdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
+};
+
+static struct clockdomain gfx_3430es1_clkdm = {
+	.name		= "gfx_clkdm",
+	.pwrdm		= { .name = "gfx_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= gfx_sgx_3xxx_wkdeps,
+	.sleepdep_srcs	= gfx_sgx_sleepdeps,
+	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK,
+};
+
+static struct clockdomain sgx_clkdm = {
+	.name		= "sgx_clkdm",
+	.pwrdm		= { .name = "sgx_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= gfx_sgx_3xxx_wkdeps,
+	.sleepdep_srcs	= gfx_sgx_sleepdeps,
+	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
+};
+
+/*
+ * The die-to-die clockdomain was documented in the 34xx ES1 TRM, but
+ * then that information was removed from the 34xx ES2+ TRM.  It is
+ * unclear whether the core is still there, but the clockdomain logic
+ * is there, and must be programmed to an appropriate state if the
+ * CORE clockdomain is to become inactive.
+ */
+static struct clockdomain d2d_clkdm = {
+	.name		= "d2d_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l3_3xxx_clkdm = {
+	.name		= "core_l3_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.dep_bit	= OMAP3430_EN_CORE_SHIFT,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l4_3xxx_clkdm = {
+	.name		= "core_l4_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.dep_bit	= OMAP3430_EN_CORE_SHIFT,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK,
+};
+
+/* Another case of bit name collisions between several registers: EN_DSS */
+static struct clockdomain dss_3xxx_clkdm = {
+	.name		= "dss_clkdm",
+	.pwrdm		= { .name = "dss_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
+	.wkdep_srcs	= dss_wkdeps,
+	.sleepdep_srcs	= dss_sleepdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
+};
+
+static struct clockdomain cam_clkdm = {
+	.name		= "cam_clkdm",
+	.pwrdm		= { .name = "cam_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= cam_wkdeps,
+	.sleepdep_srcs	= cam_sleepdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,
+};
+
+static struct clockdomain usbhost_clkdm = {
+	.name		= "usbhost_clkdm",
+	.pwrdm		= { .name = "usbhost_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= usbhost_wkdeps,
+	.sleepdep_srcs	= usbhost_sleepdeps,
+	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
+};
+
+static struct clockdomain per_clkdm = {
+	.name		= "per_clkdm",
+	.pwrdm		= { .name = "per_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP3430_EN_PER_SHIFT,
+	.wkdep_srcs	= per_wkdeps,
+	.sleepdep_srcs	= per_sleepdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
+};
+
+/*
+ * Disable hw supervised mode for emu_clkdm, because emu_pwrdm is
+ * switched of even if sdti is in use
+ */
+static struct clockdomain emu_clkdm = {
+	.name		= "emu_clkdm",
+	.pwrdm		= { .name = "emu_pwrdm" },
+	.flags		= /* CLKDM_CAN_ENABLE_AUTO |  */CLKDM_CAN_SWSUP,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,
+};
+
+static struct clockdomain dpll1_clkdm = {
+	.name		= "dpll1_clkdm",
+	.pwrdm		= { .name = "dpll1_pwrdm" },
+};
+
+static struct clockdomain dpll2_clkdm = {
+	.name		= "dpll2_clkdm",
+	.pwrdm		= { .name = "dpll2_pwrdm" },
+};
+
+static struct clockdomain dpll3_clkdm = {
+	.name		= "dpll3_clkdm",
+	.pwrdm		= { .name = "dpll3_pwrdm" },
+};
+
+static struct clockdomain dpll4_clkdm = {
+	.name		= "dpll4_clkdm",
+	.pwrdm		= { .name = "dpll4_pwrdm" },
+};
+
+static struct clockdomain dpll5_clkdm = {
+	.name		= "dpll5_clkdm",
+	.pwrdm		= { .name = "dpll5_pwrdm" },
+};
+
+/*
+ * Clockdomain hwsup dependencies
+ */
+
+static struct clkdm_autodep clkdm_autodeps[] = {
+	{
+		.clkdm = { .name = "mpu_clkdm" },
+	},
+	{
+		.clkdm = { .name = "iva2_clkdm" },
+	},
+	{
+		.clkdm = { .name = NULL },
+	}
+};
+
+/*
+ *
+ */
+
+static struct clockdomain *clockdomains_omap3430_common[] __initdata = {
+	&wkup_common_clkdm,
+	&cm_common_clkdm,
+	&prm_common_clkdm,
+	&mpu_3xxx_clkdm,
+	&neon_clkdm,
+	&iva2_clkdm,
+	&d2d_clkdm,
+	&core_l3_3xxx_clkdm,
+	&core_l4_3xxx_clkdm,
+	&dss_3xxx_clkdm,
+	&cam_clkdm,
+	&per_clkdm,
+	&emu_clkdm,
+	&dpll1_clkdm,
+	&dpll2_clkdm,
+	&dpll3_clkdm,
+	&dpll4_clkdm,
+	NULL
+};
+
+static struct clockdomain *clockdomains_omap3430es1[] __initdata = {
+	&gfx_3430es1_clkdm,
+	NULL,
+};
+
+static struct clockdomain *clockdomains_omap3430es2plus[] __initdata = {
+	&sgx_clkdm,
+	&dpll5_clkdm,
+	&usbhost_clkdm,
+	NULL,
+};
+
+void __init omap3xxx_clockdomains_init(void)
+{
+	struct clockdomain **sc;
+
+	if (!cpu_is_omap34xx())
+		return;
+
+	clkdm_register_platform_funcs(&omap3_clkdm_operations);
+	clkdm_register_clkdms(clockdomains_omap3430_common);
+
+	sc = (omap_rev() == OMAP3430_REV_ES1_0) ? clockdomains_omap3430es1 :
+		clockdomains_omap3430es2plus;
+
+	clkdm_register_clkdms(sc);
+
+	clkdm_register_autodeps(clkdm_autodeps);
+	clkdm_complete_init();
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomains44xx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomains44xx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/clockdomains44xx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/clockdomains44xx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,350 +34,122 @@
 /* Static Dependencies for OMAP4 Clock Domains */
 
 static struct clkdm_dep 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)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_2_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l3_init_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
 	{ NULL },
 };
 
 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)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_2_clkdm" },
+	{ .clkdm_name = "l3_dss_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l3_gfx_clkdm" },
+	{ .clkdm_name = "l3_init_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
+	{ .clkdm_name = "l4_secure_clkdm" },
+	{ .clkdm_name = "l4_wkup_clkdm" },
+	{ .clkdm_name = "tesla_clkdm" },
 	{ 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)
-	},
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
 	{ 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)
-	},
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
 	{ 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)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ducati_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_dss_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l3_init_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
+	{ .clkdm_name = "l4_secure_clkdm" },
+	{ .clkdm_name = "l4_wkup_clkdm" },
 	{ 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)
-	},
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_2_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
 	{ 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)
-	},
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
 	{ 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)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
+	{ .clkdm_name = "l4_secure_clkdm" },
+	{ .clkdm_name = "l4_wkup_clkdm" },
 	{ 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)
-	},
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep mpu_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)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ducati_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_2_clkdm" },
+	{ .clkdm_name = "l3_dss_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l3_gfx_clkdm" },
+	{ .clkdm_name = "l3_init_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
+	{ .clkdm_name = "l4_secure_clkdm" },
+	{ .clkdm_name = "l4_wkup_clkdm" },
+	{ .clkdm_name = "tesla_clkdm" },
 	{ 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)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_2_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l3_init_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
+	{ .clkdm_name = "l4_wkup_clkdm" },
 	{ NULL },
 };
 
@@ -388,7 +160,6 @@
 	.cm_inst	  = OMAP4430_CM2_CEFUSE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CEFUSE_CEFUSE_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l4_cfg_44xx_clkdm = {
@@ -399,7 +170,6 @@
 	.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),
 };
 
 static struct clockdomain tesla_44xx_clkdm = {
@@ -412,7 +182,6 @@
 	.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),
 };
 
 static struct clockdomain l3_gfx_44xx_clkdm = {
@@ -425,7 +194,6 @@
 	.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),
 };
 
 static struct clockdomain ivahd_44xx_clkdm = {
@@ -438,7 +206,6 @@
 	.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),
 };
 
 static struct clockdomain l4_secure_44xx_clkdm = {
@@ -451,7 +218,6 @@
 	.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),
 };
 
 static struct clockdomain l4_per_44xx_clkdm = {
@@ -462,7 +228,6 @@
 	.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),
 };
 
 static struct clockdomain abe_44xx_clkdm = {
@@ -473,7 +238,6 @@
 	.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),
 };
 
 static struct clockdomain l3_instr_44xx_clkdm = {
@@ -482,7 +246,6 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L3INSTR_CDOFFS,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_init_44xx_clkdm = {
@@ -495,7 +258,6 @@
 	.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),
 };
 
 static struct clockdomain d2d_44xx_clkdm = {
@@ -507,7 +269,6 @@
 	.wkdep_srcs	  = d2d_wkup_sleep_deps,
 	.sleepdep_srcs	  = d2d_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain mpu0_44xx_clkdm = {
@@ -517,7 +278,6 @@
 	.cm_inst	  = OMAP4430_PRCM_MPU_CPU0_INST,
 	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU0_CPU0_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain mpu1_44xx_clkdm = {
@@ -527,7 +287,6 @@
 	.cm_inst	  = OMAP4430_PRCM_MPU_CPU1_INST,
 	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU1_CPU1_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_emif_44xx_clkdm = {
@@ -538,7 +297,6 @@
 	.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),
 };
 
 static struct clockdomain l4_ao_44xx_clkdm = {
@@ -548,7 +306,6 @@
 	.cm_inst	  = OMAP4430_CM2_ALWAYS_ON_INST,
 	.clkdm_offs	  = OMAP4430_CM2_ALWAYS_ON_ALWON_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain ducati_44xx_clkdm = {
@@ -561,7 +318,6 @@
 	.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),
 };
 
 static struct clockdomain mpu_44xx_clkdm = {
@@ -573,7 +329,6 @@
 	.wkdep_srcs	  = mpu_wkup_sleep_deps,
 	.sleepdep_srcs	  = mpu_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_2_44xx_clkdm = {
@@ -584,7 +339,6 @@
 	.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),
 };
 
 static struct clockdomain l3_1_44xx_clkdm = {
@@ -595,7 +349,6 @@
 	.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),
 };
 
 static struct clockdomain iss_44xx_clkdm = {
@@ -607,7 +360,6 @@
 	.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),
 };
 
 static struct clockdomain l3_dss_44xx_clkdm = {
@@ -620,7 +372,6 @@
 	.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),
 };
 
 static struct clockdomain l4_wkup_44xx_clkdm = {
@@ -631,7 +382,6 @@
 	.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),
 };
 
 static struct clockdomain emu_sys_44xx_clkdm = {
@@ -641,7 +391,6 @@
 	.cm_inst	  = OMAP4430_PRM_EMU_CM_INST,
 	.clkdm_offs	  = OMAP4430_PRM_EMU_CM_EMU_CDOFFS,
 	.flags		  = CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_dma_44xx_clkdm = {
@@ -653,7 +402,6 @@
 	.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),
 };
 
 /* As clockdomains are added or removed above, this list must also be changed */
@@ -685,7 +433,10 @@
 	NULL
 };
 
+
 void __init omap44xx_clockdomains_init(void)
 {
-	clkdm_init(clockdomains_omap44xx, NULL, &omap4_clkdm_operations);
+	clkdm_register_platform_funcs(&omap4_clkdm_operations);
+	clkdm_register_clkdms(clockdomains_omap44xx);
+	clkdm_complete_init();
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/clock.h linux-libre-3.2-gnu/arch/arm/mach-omap2/clock.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -66,6 +66,8 @@
 int omap4_dpllmx_gatectrl_read(struct clk *clk);
 void omap4_dpllmx_allow_gatectrl(struct clk *clk);
 void omap4_dpllmx_deny_gatectrl(struct clk *clk);
+long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate);
+unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk);
 
 #ifdef CONFIG_OMAP_RESET_CLOCKS
 void omap2_clk_disable_unused(struct clk *clk);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/common.c linux-libre-3.2-gnu/arch/arm/mach-omap2/common.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,17 +45,22 @@
 static struct omap_globals omap242x_globals = {
 	.class	= OMAP242X_CLASS,
 	.tap	= OMAP2_L4_IO_ADDRESS(0x48014000),
-	.sdrc	= OMAP2420_SDRC_BASE,
-	.sms	= OMAP2420_SMS_BASE,
-	.ctrl	= OMAP242X_CTRL_BASE,
-	.prm	= OMAP2420_PRM_BASE,
-	.cm	= OMAP2420_CM_BASE,
+	.sdrc	= OMAP2_L3_IO_ADDRESS(OMAP2420_SDRC_BASE),
+	.sms	= OMAP2_L3_IO_ADDRESS(OMAP2420_SMS_BASE),
+	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE),
+	.prm	= OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE),
+	.cm	= OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE),
 };
 
 void __init omap2_set_globals_242x(void)
 {
 	__omap2_set_globals(&omap242x_globals);
 }
+
+void __init omap242x_map_io(void)
+{
+	omap242x_map_common_io();
+}
 #endif
 
 #if defined(CONFIG_SOC_OMAP2430)
@@ -63,17 +68,22 @@
 static struct omap_globals omap243x_globals = {
 	.class	= OMAP243X_CLASS,
 	.tap	= OMAP2_L4_IO_ADDRESS(0x4900a000),
-	.sdrc	= OMAP243X_SDRC_BASE,
-	.sms	= OMAP243X_SMS_BASE,
-	.ctrl	= OMAP243X_CTRL_BASE,
-	.prm	= OMAP2430_PRM_BASE,
-	.cm	= OMAP2430_CM_BASE,
+	.sdrc	= OMAP2_L3_IO_ADDRESS(OMAP243X_SDRC_BASE),
+	.sms	= OMAP2_L3_IO_ADDRESS(OMAP243X_SMS_BASE),
+	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE),
+	.prm	= OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE),
+	.cm	= OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE),
 };
 
 void __init omap2_set_globals_243x(void)
 {
 	__omap2_set_globals(&omap243x_globals);
 }
+
+void __init omap243x_map_io(void)
+{
+	omap243x_map_common_io();
+}
 #endif
 
 #if defined(CONFIG_ARCH_OMAP3)
@@ -81,11 +91,11 @@
 static struct omap_globals omap3_globals = {
 	.class	= OMAP343X_CLASS,
 	.tap	= OMAP2_L4_IO_ADDRESS(0x4830A000),
-	.sdrc	= OMAP343X_SDRC_BASE,
-	.sms	= OMAP343X_SMS_BASE,
-	.ctrl	= OMAP343X_CTRL_BASE,
-	.prm	= OMAP3430_PRM_BASE,
-	.cm	= OMAP3430_CM_BASE,
+	.sdrc	= OMAP2_L3_IO_ADDRESS(OMAP343X_SDRC_BASE),
+	.sms	= OMAP2_L3_IO_ADDRESS(OMAP343X_SMS_BASE),
+	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE),
+	.prm	= OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE),
+	.cm	= OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE),
 };
 
 void __init omap2_set_globals_3xxx(void)
@@ -95,7 +105,6 @@
 
 void __init omap3_map_io(void)
 {
-	omap2_set_globals_3xxx();
 	omap34xx_map_common_io();
 }
 
@@ -110,9 +119,9 @@
 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,
+	.ctrl   = OMAP2_L4_IO_ADDRESS(TI816X_CTRL_BASE),
+	.prm    = OMAP2_L4_IO_ADDRESS(TI816X_PRCM_BASE),
+	.cm     = OMAP2_L4_IO_ADDRESS(TI816X_PRCM_BASE),
 };
 
 void __init omap2_set_globals_ti816x(void)
@@ -125,11 +134,11 @@
 static struct omap_globals omap4_globals = {
 	.class	= OMAP443X_CLASS,
 	.tap	= OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
-	.ctrl	= OMAP443X_SCM_BASE,
-	.ctrl_pad	= OMAP443X_CTRL_BASE,
-	.prm	= OMAP4430_PRM_BASE,
-	.cm	= OMAP4430_CM_BASE,
-	.cm2	= OMAP4430_CM2_BASE,
+	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
+	.ctrl_pad	= OMAP2_L4_IO_ADDRESS(OMAP443X_CTRL_BASE),
+	.prm	= OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE),
+	.cm	= OMAP2_L4_IO_ADDRESS(OMAP4430_CM_BASE),
+	.cm2	= OMAP2_L4_IO_ADDRESS(OMAP4430_CM2_BASE),
 };
 
 void __init omap2_set_globals_443x(void)
@@ -138,5 +147,10 @@
 	omap2_set_globals_control(&omap4_globals);
 	omap2_set_globals_prcm(&omap4_globals);
 }
+
+void __init omap4_map_io(void)
+{
+	omap44xx_map_common_io();
+}
 #endif
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/control.c linux-libre-3.2-gnu/arch/arm/mach-omap2/control.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/control.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/control.c	2012-01-04 18:55:44.000000000 -0500
@@ -149,17 +149,11 @@
 
 void __init omap2_set_globals_control(struct omap_globals *omap2_globals)
 {
-	/* Static mapping, never released */
-	if (omap2_globals->ctrl) {
-		omap2_ctrl_base = ioremap(omap2_globals->ctrl, SZ_4K);
-		WARN_ON(!omap2_ctrl_base);
-	}
+	if (omap2_globals->ctrl)
+		omap2_ctrl_base = omap2_globals->ctrl;
 
-	/* Static mapping, never released */
-	if (omap2_globals->ctrl_pad) {
-		omap4_ctrl_pad_base = ioremap(omap2_globals->ctrl_pad, SZ_4K);
-		WARN_ON(!omap4_ctrl_pad_base);
-	}
+	if (omap2_globals->ctrl_pad)
+		omap4_ctrl_pad_base = omap2_globals->ctrl_pad;
 }
 
 void __iomem *omap_ctrl_base_get(void)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/cpuidle34xx.c linux-libre-3.2-gnu/arch/arm/mach-omap2/cpuidle34xx.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/cpuidle34xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/cpuidle34xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 
 #include <linux/sched.h>
 #include <linux/cpuidle.h>
+#include <linux/export.h>
 
 #include <plat/prcm.h>
 #include <plat/irqs.h>
@@ -88,17 +89,21 @@
 /**
  * omap3_enter_idle - Programs OMAP3 to enter the specified state
  * @dev: cpuidle device
- * @state: The target state to be programmed
+ * @drv: cpuidle driver
+ * @index: the index of state to be entered
  *
  * Called from the CPUidle framework to program the device to the
  * specified target state selected by the governor.
  */
 static int omap3_enter_idle(struct cpuidle_device *dev,
-			struct cpuidle_state *state)
+				struct cpuidle_driver *drv,
+				int index)
 {
-	struct omap3_idle_statedata *cx = cpuidle_get_statedata(state);
+	struct omap3_idle_statedata *cx =
+			cpuidle_get_statedata(&dev->states_usage[index]);
 	struct timespec ts_preidle, ts_postidle, ts_idle;
 	u32 mpu_state = cx->mpu_state, core_state = cx->core_state;
+	int idle_time;
 
 	/* Used to keep track of the total time in idle */
 	getnstimeofday(&ts_preidle);
@@ -113,7 +118,7 @@
 		goto return_sleep_time;
 
 	/* Deny idle for C1 */
-	if (state == &dev->states[0]) {
+	if (index == 0) {
 		pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
 		pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
 	}
@@ -122,7 +127,7 @@
 	omap_sram_idle();
 
 	/* Re-allow idle for C1 */
-	if (state == &dev->states[0]) {
+	if (index == 0) {
 		pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
 		pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
 	}
@@ -134,28 +139,38 @@
 	local_irq_enable();
 	local_fiq_enable();
 
-	return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC;
+	idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \
+								USEC_PER_SEC;
+
+	/* Update cpuidle counters */
+	dev->last_residency = idle_time;
+
+	return index;
 }
 
 /**
  * next_valid_state - Find next valid C-state
  * @dev: cpuidle device
- * @state: Currently selected C-state
+ * @drv: cpuidle driver
+ * @index: Index of currently selected c-state
  *
- * If the current state is valid, it is returned back to the caller.
- * Else, this function searches for a lower c-state which is still
- * valid.
+ * If the state corresponding to index is valid, index is returned back
+ * to the caller. Else, this function searches for a lower c-state which is
+ * still valid (as defined in omap3_power_states[]) and returns its index.
  *
  * A state is valid if the 'valid' field is enabled and
  * if it satisfies the enable_off_mode condition.
  */
-static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
-					      struct cpuidle_state *curr)
+static int next_valid_state(struct cpuidle_device *dev,
+			struct cpuidle_driver *drv,
+				int index)
 {
-	struct cpuidle_state *next = NULL;
-	struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr);
+	struct cpuidle_state_usage *curr_usage = &dev->states_usage[index];
+	struct cpuidle_state *curr = &drv->states[index];
+	struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
 	u32 mpu_deepest_state = PWRDM_POWER_RET;
 	u32 core_deepest_state = PWRDM_POWER_RET;
+	int next_index = -1;
 
 	if (enable_off_mode) {
 		mpu_deepest_state = PWRDM_POWER_OFF;
@@ -172,20 +187,20 @@
 	if ((cx->valid) &&
 	    (cx->mpu_state >= mpu_deepest_state) &&
 	    (cx->core_state >= core_deepest_state)) {
-		return curr;
+		return index;
 	} else {
 		int idx = OMAP3_NUM_STATES - 1;
 
 		/* Reach the current state starting at highest C-state */
 		for (; idx >= 0; idx--) {
-			if (&dev->states[idx] == curr) {
-				next = &dev->states[idx];
+			if (&drv->states[idx] == curr) {
+				next_index = idx;
 				break;
 			}
 		}
 
 		/* Should never hit this condition */
-		WARN_ON(next == NULL);
+		WARN_ON(next_index == -1);
 
 		/*
 		 * Drop to next valid state.
@@ -193,41 +208,44 @@
 		 */
 		idx--;
 		for (; idx >= 0; idx--) {
-			cx = cpuidle_get_statedata(&dev->states[idx]);
+			cx = cpuidle_get_statedata(&dev->states_usage[idx]);
 			if ((cx->valid) &&
 			    (cx->mpu_state >= mpu_deepest_state) &&
 			    (cx->core_state >= core_deepest_state)) {
-				next = &dev->states[idx];
+				next_index = idx;
 				break;
 			}
 		}
 		/*
 		 * C1 is always valid.
-		 * So, no need to check for 'next==NULL' outside this loop.
+		 * So, no need to check for 'next_index == -1' outside
+		 * this loop.
 		 */
 	}
 
-	return next;
+	return next_index;
 }
 
 /**
  * omap3_enter_idle_bm - Checks for any bus activity
  * @dev: cpuidle device
- * @state: The target state to be programmed
+ * @drv: cpuidle driver
+ * @index: array index of target state to be programmed
  *
  * This function checks for any pending activity and then programs
  * the device to the specified or a safer state.
  */
 static int omap3_enter_idle_bm(struct cpuidle_device *dev,
-			       struct cpuidle_state *state)
+				struct cpuidle_driver *drv,
+			       int index)
 {
-	struct cpuidle_state *new_state;
+	int new_state_idx;
 	u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
 	struct omap3_idle_statedata *cx;
 	int ret;
 
 	if (!omap3_can_sleep()) {
-		new_state = dev->safe_state;
+		new_state_idx = drv->safe_state_index;
 		goto select_state;
 	}
 
@@ -237,7 +255,7 @@
 	 */
 	cam_state = pwrdm_read_pwrst(cam_pd);
 	if (cam_state == PWRDM_POWER_ON) {
-		new_state = dev->safe_state;
+		new_state_idx = drv->safe_state_index;
 		goto select_state;
 	}
 
@@ -253,7 +271,7 @@
 	 * Prevent PER off if CORE is not in retention or off as this
 	 * would disable PER wakeups completely.
 	 */
-	cx = cpuidle_get_statedata(state);
+	cx = cpuidle_get_statedata(&dev->states_usage[index]);
 	core_next_state = cx->core_state;
 	per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
 	if ((per_next_state == PWRDM_POWER_OFF) &&
@@ -264,11 +282,10 @@
 	if (per_next_state != per_saved_state)
 		pwrdm_set_next_pwrst(per_pd, per_next_state);
 
-	new_state = next_valid_state(dev, state);
+	new_state_idx = next_valid_state(dev, drv, index);
 
 select_state:
-	dev->last_state = new_state;
-	ret = omap3_enter_idle(dev, new_state);
+	ret = omap3_enter_idle(dev, drv, new_state_idx);
 
 	/* Restore original PER state if it was modified */
 	if (per_next_state != per_saved_state)
@@ -301,22 +318,31 @@
 	.owner = 	THIS_MODULE,
 };
 
-/* Helper to fill the C-state common data and register the driver_data */
-static inline struct omap3_idle_statedata *_fill_cstate(
-					struct cpuidle_device *dev,
+/* Helper to fill the C-state common data*/
+static inline void _fill_cstate(struct cpuidle_driver *drv,
 					int idx, const char *descr)
 {
-	struct omap3_idle_statedata *cx = &omap3_idle_data[idx];
-	struct cpuidle_state *state = &dev->states[idx];
+	struct cpuidle_state *state = &drv->states[idx];
 
 	state->exit_latency	= cpuidle_params_table[idx].exit_latency;
 	state->target_residency	= cpuidle_params_table[idx].target_residency;
 	state->flags		= CPUIDLE_FLAG_TIME_VALID;
 	state->enter		= omap3_enter_idle_bm;
-	cx->valid		= cpuidle_params_table[idx].valid;
 	sprintf(state->name, "C%d", idx + 1);
 	strncpy(state->desc, descr, CPUIDLE_DESC_LEN);
-	cpuidle_set_statedata(state, cx);
+
+}
+
+/* Helper to register the driver_data */
+static inline struct omap3_idle_statedata *_fill_cstate_usage(
+					struct cpuidle_device *dev,
+					int idx)
+{
+	struct omap3_idle_statedata *cx = &omap3_idle_data[idx];
+	struct cpuidle_state_usage *state_usage = &dev->states_usage[idx];
+
+	cx->valid		= cpuidle_params_table[idx].valid;
+	cpuidle_set_statedata(state_usage, cx);
 
 	return cx;
 }
@@ -330,6 +356,7 @@
 int __init omap3_idle_init(void)
 {
 	struct cpuidle_device *dev;
+	struct cpuidle_driver *drv = &omap3_idle_driver;
 	struct omap3_idle_statedata *cx;
 
 	mpu_pd = pwrdm_lookup("mpu_pwrdm");
@@ -337,44 +364,52 @@
 	per_pd = pwrdm_lookup("per_pwrdm");
 	cam_pd = pwrdm_lookup("cam_pwrdm");
 
-	cpuidle_register_driver(&omap3_idle_driver);
+
+	drv->safe_state_index = -1;
 	dev = &per_cpu(omap3_idle_dev, smp_processor_id());
 
 	/* C1 . MPU WFI + Core active */
-	cx = _fill_cstate(dev, 0, "MPU ON + CORE ON");
-	(&dev->states[0])->enter = omap3_enter_idle;
-	dev->safe_state = &dev->states[0];
+	_fill_cstate(drv, 0, "MPU ON + CORE ON");
+	(&drv->states[0])->enter = omap3_enter_idle;
+	drv->safe_state_index = 0;
+	cx = _fill_cstate_usage(dev, 0);
 	cx->valid = 1;	/* C1 is always valid */
 	cx->mpu_state = PWRDM_POWER_ON;
 	cx->core_state = PWRDM_POWER_ON;
 
 	/* C2 . MPU WFI + Core inactive */
-	cx = _fill_cstate(dev, 1, "MPU ON + CORE ON");
+	_fill_cstate(drv, 1, "MPU ON + CORE ON");
+	cx = _fill_cstate_usage(dev, 1);
 	cx->mpu_state = PWRDM_POWER_ON;
 	cx->core_state = PWRDM_POWER_ON;
 
 	/* C3 . MPU CSWR + Core inactive */
-	cx = _fill_cstate(dev, 2, "MPU RET + CORE ON");
+	_fill_cstate(drv, 2, "MPU RET + CORE ON");
+	cx = _fill_cstate_usage(dev, 2);
 	cx->mpu_state = PWRDM_POWER_RET;
 	cx->core_state = PWRDM_POWER_ON;
 
 	/* C4 . MPU OFF + Core inactive */
-	cx = _fill_cstate(dev, 3, "MPU OFF + CORE ON");
+	_fill_cstate(drv, 3, "MPU OFF + CORE ON");
+	cx = _fill_cstate_usage(dev, 3);
 	cx->mpu_state = PWRDM_POWER_OFF;
 	cx->core_state = PWRDM_POWER_ON;
 
 	/* C5 . MPU RET + Core RET */
-	cx = _fill_cstate(dev, 4, "MPU RET + CORE RET");
+	_fill_cstate(drv, 4, "MPU RET + CORE RET");
+	cx = _fill_cstate_usage(dev, 4);
 	cx->mpu_state = PWRDM_POWER_RET;
 	cx->core_state = PWRDM_POWER_RET;
 
 	/* C6 . MPU OFF + Core RET */
-	cx = _fill_cstate(dev, 5, "MPU OFF + CORE RET");
+	_fill_cstate(drv, 5, "MPU OFF + CORE RET");
+	cx = _fill_cstate_usage(dev, 5);
 	cx->mpu_state = PWRDM_POWER_OFF;
 	cx->core_state = PWRDM_POWER_RET;
 
 	/* C7 . MPU OFF + Core OFF */
-	cx = _fill_cstate(dev, 6, "MPU OFF + CORE OFF");
+	_fill_cstate(drv, 6, "MPU OFF + CORE OFF");
+	cx = _fill_cstate_usage(dev, 6);
 	/*
 	 * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
 	 * enable OFF mode in a stable form for previous revisions.
@@ -388,6 +423,9 @@
 	cx->mpu_state = PWRDM_POWER_OFF;
 	cx->core_state = PWRDM_POWER_OFF;
 
+	drv->state_count = OMAP3_NUM_STATES;
+	cpuidle_register_driver(&omap3_idle_driver);
+
 	dev->state_count = OMAP3_NUM_STATES;
 	if (cpuidle_register_device(dev)) {
 		printk(KERN_ERR "%s: CPUidle register device failed\n",
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/devices.c linux-libre-3.2-gnu/arch/arm/mach-omap2/devices.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -16,6 +16,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
@@ -26,7 +27,6 @@
 #include <plat/tc.h>
 #include <plat/board.h>
 #include <plat/mcbsp.h>
-#include <mach/gpio.h>
 #include <plat/mmc.h>
 #include <plat/dma.h>
 #include <plat/omap_hwmod.h>
@@ -44,7 +44,7 @@
 {
 	int l;
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	char oh_name[L3_MODULES_MAX_LEN];
 
 	/*
@@ -61,12 +61,12 @@
 	if (!oh)
 		pr_err("could not look up %s\n", oh_name);
 
-	od = omap_device_build("omap_l3_smx", 0, oh, NULL, 0,
+	pdev = 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);
+	WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
 
-	return IS_ERR(od) ? PTR_ERR(od) : 0;
+	return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
 }
 postcore_initcall(omap3_l3_init);
 
@@ -74,9 +74,13 @@
 {
 	int l, i;
 	struct omap_hwmod *oh[3];
-	struct omap_device *od;
+	struct platform_device *pdev;
 	char oh_name[L3_MODULES_MAX_LEN];
 
+	/* If dtb is there, the devices will be created dynamically */
+	if (of_have_populated_dt())
+		return -ENODEV;
+
 	/*
 	 * To avoid code running on other OMAPs in
 	 * multi-omap builds
@@ -92,12 +96,12 @@
 			pr_err("could not look up %s\n", oh_name);
 	}
 
-	od = omap_device_build_ss("omap_l3_noc", 0, oh, 3, NULL,
+	pdev = 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);
+	WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
 
-	return IS_ERR(od) ? PTR_ERR(od) : 0;
+	return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
 }
 postcore_initcall(omap4_l3_init);
 
@@ -221,18 +225,10 @@
 #endif
 }
 
-struct omap_device_pm_latency omap_keyboard_latency[] = {
-	{
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 int __init omap4_keyboard_init(struct omap4_keypad_platform_data
 			*sdp4430_keypad_data, struct omap_board_data *bdata)
 {
-	struct omap_device *od;
+	struct platform_device *pdev;
 	struct omap_hwmod *oh;
 	struct omap4_keypad_platform_data *keypad_data;
 	unsigned int id = -1;
@@ -247,15 +243,13 @@
 
 	keypad_data = sdp4430_keypad_data;
 
-	od = omap_device_build(name, id, oh, keypad_data,
-			sizeof(struct omap4_keypad_platform_data),
-			omap_keyboard_latency,
-			ARRAY_SIZE(omap_keyboard_latency), 0);
+	pdev = omap_device_build(name, id, oh, keypad_data,
+			sizeof(struct omap4_keypad_platform_data), NULL, 0, 0);
 
-	if (IS_ERR(od)) {
+	if (IS_ERR(pdev)) {
 		WARN(1, "Can't build omap_device for %s:%s.\n",
 						name, oh->name);
-		return PTR_ERR(od);
+		return PTR_ERR(pdev);
 	}
 	oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
 
@@ -263,18 +257,10 @@
 }
 
 #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)
 {
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 
 	oh = omap_hwmod_lookup("mailbox");
 	if (!oh) {
@@ -282,10 +268,9 @@
 		return;
 	}
 
-	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));
+	pdev = omap_device_build("omap-mailbox", -1, oh, NULL, 0, NULL, 0, 0);
+	WARN(IS_ERR(pdev), "%s: could not build device, err %ld\n",
+						__func__, PTR_ERR(pdev));
 }
 #else
 static inline void omap_init_mbox(void) { }
@@ -330,21 +315,34 @@
 static inline void omap_init_audio(void) {}
 #endif
 
+#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \
+		defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE)
+
+static void omap_init_mcpdm(void)
+{
+	struct omap_hwmod *oh;
+	struct platform_device *pdev;
+
+	oh = omap_hwmod_lookup("mcpdm");
+	if (!oh) {
+		printk(KERN_ERR "Could not look up mcpdm hw_mod\n");
+		return;
+	}
+
+	pdev = omap_device_build("omap-mcpdm", -1, oh, NULL, 0, NULL, 0, 0);
+	WARN(IS_ERR(pdev), "Can't build omap_device for omap-mcpdm.\n");
+}
+#else
+static inline void omap_init_mcpdm(void) {}
+#endif
+
 #if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
 
 #include <plat/mcspi.h>
 
-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,
-	},
-};
-
 static int omap_mcspi_init(struct omap_hwmod *oh, void *unused)
 {
-	struct omap_device *od;
+	struct platform_device *pdev;
 	char *name = "omap2_mcspi";
 	struct omap2_mcspi_platform_config *pdata;
 	static int spi_num;
@@ -371,10 +369,9 @@
 	}
 
 	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",
+	pdev = omap_device_build(name, spi_num, oh, pdata,
+				sizeof(*pdata),	NULL, 0, 0);
+	WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s\n",
 				name, oh->name);
 	kfree(pdata);
 	return 0;
@@ -683,6 +680,7 @@
 	 * in alphabetical order so they're easier to sort through.
 	 */
 	omap_init_audio();
+	omap_init_mcpdm();
 	omap_init_camera();
 	omap_init_mbox();
 	omap_init_mcspi();
@@ -698,18 +696,10 @@
 arch_initcall(omap2_init_devices);
 
 #if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
-static struct omap_device_pm_latency omap_wdt_latency[] = {
-	[0] = {
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static int __init omap_init_wdt(void)
 {
 	int id = -1;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	struct omap_hwmod *oh;
 	char *oh_name = "wd_timer2";
 	char *dev_name = "omap_wdt";
@@ -723,10 +713,8 @@
 		return -EINVAL;
 	}
 
-	od = omap_device_build(dev_name, id, oh, NULL, 0,
-				omap_wdt_latency,
-				ARRAY_SIZE(omap_wdt_latency), 0);
-	WARN(IS_ERR(od), "Can't build omap_device for %s:%s.\n",
+	pdev = omap_device_build(dev_name, id, oh, NULL, 0, NULL, 0, 0);
+	WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n",
 				dev_name, oh->name);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/display.c linux-libre-3.2-gnu/arch/arm/mach-omap2/display.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/display.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/display.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -26,6 +27,35 @@
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
 #include <plat/omap-pm.h>
+#include <plat/common.h>
+
+#include "control.h"
+#include "display.h"
+
+#define DISPC_CONTROL		0x0040
+#define DISPC_CONTROL2		0x0238
+#define DISPC_IRQSTATUS		0x0018
+
+#define DSS_SYSCONFIG		0x10
+#define DSS_SYSSTATUS		0x14
+#define DSS_CONTROL		0x40
+#define DSS_SDI_CONTROL		0x44
+#define DSS_PLL_CONTROL		0x48
+
+#define LCD_EN_MASK		(0x1 << 0)
+#define DIGIT_EN_MASK		(0x1 << 1)
+
+#define FRAMEDONE_IRQ_SHIFT	0
+#define EVSYNC_EVEN_IRQ_SHIFT	2
+#define EVSYNC_ODD_IRQ_SHIFT	3
+#define FRAMEDONE2_IRQ_SHIFT	22
+#define FRAMEDONETV_IRQ_SHIFT	24
+
+/*
+ * FRAMEDONE_IRQ_TIMEOUT: how long (in milliseconds) to wait during DISPC
+ *     reset before deciding that something has gone wrong
+ */
+#define FRAMEDONE_IRQ_TIMEOUT		100
 
 static struct platform_device omap_display_device = {
 	.name          = "omapdss",
@@ -35,14 +65,6 @@
 	},
 };
 
-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,
-	},
-};
-
 struct omap_dss_hwmod_data {
 	const char *oh_name;
 	const char *dev_name;
@@ -61,7 +83,7 @@
 	{ "dss_dispc", "omapdss_dispc", -1 },
 	{ "dss_rfbi", "omapdss_rfbi", -1 },
 	{ "dss_venc", "omapdss_venc", -1 },
-	{ "dss_dsi1", "omapdss_dsi1", -1 },
+	{ "dss_dsi1", "omapdss_dsi", 0 },
 };
 
 static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = {
@@ -69,16 +91,63 @@
 	{ "dss_dispc", "omapdss_dispc", -1 },
 	{ "dss_rfbi", "omapdss_rfbi", -1 },
 	{ "dss_venc", "omapdss_venc", -1 },
-	{ "dss_dsi1", "omapdss_dsi1", -1 },
-	{ "dss_dsi2", "omapdss_dsi2", -1 },
+	{ "dss_dsi1", "omapdss_dsi", 0 },
+	{ "dss_dsi2", "omapdss_dsi", 1 },
 	{ "dss_hdmi", "omapdss_hdmi", -1 },
 };
 
+static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
+{
+	u32 enable_mask, enable_shift;
+	u32 pipd_mask, pipd_shift;
+	u32 reg;
+
+	if (dsi_id == 0) {
+		enable_mask = OMAP4_DSI1_LANEENABLE_MASK;
+		enable_shift = OMAP4_DSI1_LANEENABLE_SHIFT;
+		pipd_mask = OMAP4_DSI1_PIPD_MASK;
+		pipd_shift = OMAP4_DSI1_PIPD_SHIFT;
+	} else if (dsi_id == 1) {
+		enable_mask = OMAP4_DSI2_LANEENABLE_MASK;
+		enable_shift = OMAP4_DSI2_LANEENABLE_SHIFT;
+		pipd_mask = OMAP4_DSI2_PIPD_MASK;
+		pipd_shift = OMAP4_DSI2_PIPD_SHIFT;
+	} else {
+		return -ENODEV;
+	}
+
+	reg = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+
+	reg &= ~enable_mask;
+	reg &= ~pipd_mask;
+
+	reg |= (lanes << enable_shift) & enable_mask;
+	reg |= (lanes << pipd_shift) & pipd_mask;
+
+	omap4_ctrl_pad_writel(reg, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+
+	return 0;
+}
+
+static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
+{
+	if (cpu_is_omap44xx())
+		return omap4_dsi_mux_pads(dsi_id, lane_mask);
+
+	return 0;
+}
+
+static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
+{
+	if (cpu_is_omap44xx())
+		omap4_dsi_mux_pads(dsi_id, 0);
+}
+
 int __init omap_display_init(struct omap_dss_board_info *board_data)
 {
 	int r = 0;
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	int i, oh_count;
 	struct omap_display_platform_data pdata;
 	const struct omap_dss_hwmod_data *curr_dss_hwmod;
@@ -96,6 +165,11 @@
 		oh_count = ARRAY_SIZE(omap4_dss_hwmod_data);
 	}
 
+	if (board_data->dsi_enable_pads == NULL)
+		board_data->dsi_enable_pads = omap_dsi_enable_pads;
+	if (board_data->dsi_disable_pads == NULL)
+		board_data->dsi_disable_pads = omap_dsi_disable_pads;
+
 	pdata.board_data = board_data;
 	pdata.board_data->get_context_loss_count =
 		omap_pm_get_dev_context_loss_count;
@@ -108,13 +182,12 @@
 			return -ENODEV;
 		}
 
-		od = omap_device_build(curr_dss_hwmod[i].dev_name,
+		pdev = omap_device_build(curr_dss_hwmod[i].dev_name,
 				curr_dss_hwmod[i].id, oh, &pdata,
 				sizeof(struct omap_display_platform_data),
-				omap_dss_latency,
-				ARRAY_SIZE(omap_dss_latency), 0);
+				NULL, 0, 0);
 
-		if (WARN((IS_ERR(od)), "Could not build omap_device for %s\n",
+		if (WARN((IS_ERR(pdev)), "Could not build omap_device for %s\n",
 				curr_dss_hwmod[i].oh_name))
 			return -ENODEV;
 	}
@@ -126,3 +199,135 @@
 
 	return r;
 }
+
+static void dispc_disable_outputs(void)
+{
+	u32 v, irq_mask = 0;
+	bool lcd_en, digit_en, lcd2_en = false;
+	int i;
+	struct omap_dss_dispc_dev_attr *da;
+	struct omap_hwmod *oh;
+
+	oh = omap_hwmod_lookup("dss_dispc");
+	if (!oh) {
+		WARN(1, "display: could not disable outputs during reset - could not find dss_dispc hwmod\n");
+		return;
+	}
+
+	if (!oh->dev_attr) {
+		pr_err("display: could not disable outputs during reset due to missing dev_attr\n");
+		return;
+	}
+
+	da = (struct omap_dss_dispc_dev_attr *)oh->dev_attr;
+
+	/* store value of LCDENABLE and DIGITENABLE bits */
+	v = omap_hwmod_read(oh, DISPC_CONTROL);
+	lcd_en = v & LCD_EN_MASK;
+	digit_en = v & DIGIT_EN_MASK;
+
+	/* store value of LCDENABLE for LCD2 */
+	if (da->manager_count > 2) {
+		v = omap_hwmod_read(oh, DISPC_CONTROL2);
+		lcd2_en = v & LCD_EN_MASK;
+	}
+
+	if (!(lcd_en | digit_en | lcd2_en))
+		return; /* no managers currently enabled */
+
+	/*
+	 * If any manager was enabled, we need to disable it before
+	 * DSS clocks are disabled or DISPC module is reset
+	 */
+	if (lcd_en)
+		irq_mask |= 1 << FRAMEDONE_IRQ_SHIFT;
+
+	if (digit_en) {
+		if (da->has_framedonetv_irq) {
+			irq_mask |= 1 << FRAMEDONETV_IRQ_SHIFT;
+		} else {
+			irq_mask |= 1 << EVSYNC_EVEN_IRQ_SHIFT |
+				1 << EVSYNC_ODD_IRQ_SHIFT;
+		}
+	}
+
+	if (lcd2_en)
+		irq_mask |= 1 << FRAMEDONE2_IRQ_SHIFT;
+
+	/*
+	 * clear any previous FRAMEDONE, FRAMEDONETV,
+	 * EVSYNC_EVEN/ODD or FRAMEDONE2 interrupts
+	 */
+	omap_hwmod_write(irq_mask, oh, DISPC_IRQSTATUS);
+
+	/* disable LCD and TV managers */
+	v = omap_hwmod_read(oh, DISPC_CONTROL);
+	v &= ~(LCD_EN_MASK | DIGIT_EN_MASK);
+	omap_hwmod_write(v, oh, DISPC_CONTROL);
+
+	/* disable LCD2 manager */
+	if (da->manager_count > 2) {
+		v = omap_hwmod_read(oh, DISPC_CONTROL2);
+		v &= ~LCD_EN_MASK;
+		omap_hwmod_write(v, oh, DISPC_CONTROL2);
+	}
+
+	i = 0;
+	while ((omap_hwmod_read(oh, DISPC_IRQSTATUS) & irq_mask) !=
+	       irq_mask) {
+		i++;
+		if (i > FRAMEDONE_IRQ_TIMEOUT) {
+			pr_err("didn't get FRAMEDONE1/2 or TV interrupt\n");
+			break;
+		}
+		mdelay(1);
+	}
+}
+
+#define MAX_MODULE_SOFTRESET_WAIT	10000
+int omap_dss_reset(struct omap_hwmod *oh)
+{
+	struct omap_hwmod_opt_clk *oc;
+	int c = 0;
+	int i, r;
+
+	if (!(oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)) {
+		pr_err("dss_core: hwmod data doesn't contain reset data\n");
+		return -EINVAL;
+	}
+
+	for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+		if (oc->_clk)
+			clk_enable(oc->_clk);
+
+	dispc_disable_outputs();
+
+	/* clear SDI registers */
+	if (cpu_is_omap3430()) {
+		omap_hwmod_write(0x0, oh, DSS_SDI_CONTROL);
+		omap_hwmod_write(0x0, oh, DSS_PLL_CONTROL);
+	}
+
+	/*
+	 * clear DSS_CONTROL register to switch DSS clock sources to
+	 * PRCM clock, if any
+	 */
+	omap_hwmod_write(0x0, oh, DSS_CONTROL);
+
+	omap_test_timeout((omap_hwmod_read(oh, oh->class->sysc->syss_offs)
+				& SYSS_RESETDONE_MASK),
+			MAX_MODULE_SOFTRESET_WAIT, c);
+
+	if (c == MAX_MODULE_SOFTRESET_WAIT)
+		pr_warning("dss_core: waiting for reset to finish failed\n");
+	else
+		pr_debug("dss_core: softreset done\n");
+
+	for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+		if (oc->_clk)
+			clk_disable(oc->_clk);
+
+	r = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
+
+	return r;
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/display.h linux-libre-3.2-gnu/arch/arm/mach-omap2/display.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/display.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/display.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * display.h - OMAP2+ integration-specific DSS header
+ *
+ * Copyright (C) 2011 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 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_DISPLAY_H
+#define __ARCH_ARM_MACH_OMAP2_DISPLAY_H
+
+#include <linux/kernel.h>
+
+struct omap_dss_dispc_dev_attr {
+	u8	manager_count;
+	bool	has_framedonetv_irq;
+};
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/dma.c linux-libre-3.2-gnu/arch/arm/mach-omap2/dma.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -87,14 +87,6 @@
 	[CCDN]			= 0xd8,
 };
 
-static struct omap_device_pm_latency omap2_dma_latency[] = {
-	{
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func	 = omap_device_enable_hwmods,
-		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static void __iomem *dma_base;
 static inline void dma_write(u32 val, int reg, int lch)
 {
@@ -228,7 +220,7 @@
 /* One time initializations */
 static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 {
-	struct omap_device			*od;
+	struct platform_device			*pdev;
 	struct omap_system_dma_plat_info	*p;
 	struct resource				*mem;
 	char					*name = "omap_dma_system";
@@ -258,23 +250,22 @@
 
 	p->errata		= configure_dma_errata();
 
-	od = omap_device_build(name, 0, oh, p, sizeof(*p),
-			omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0);
+	pdev = omap_device_build(name, 0, oh, p, sizeof(*p), NULL, 0, 0);
 	kfree(p);
-	if (IS_ERR(od)) {
+	if (IS_ERR(pdev)) {
 		pr_err("%s: Can't build omap_device for %s:%s.\n",
 			__func__, name, oh->name);
-		return PTR_ERR(od);
+		return PTR_ERR(pdev);
 	}
 
-	mem = platform_get_resource(&od->pdev, IORESOURCE_MEM, 0);
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem) {
-		dev_err(&od->pdev.dev, "%s: no mem resource\n", __func__);
+		dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
 		return -EINVAL;
 	}
 	dma_base = ioremap(mem->start, resource_size(mem));
 	if (!dma_base) {
-		dev_err(&od->pdev.dev, "%s: ioremap fail\n", __func__);
+		dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
 		return -ENOMEM;
 	}
 
@@ -283,7 +274,7 @@
 					(d->lch_count), GFP_KERNEL);
 
 	if (!d->chan) {
-		dev_err(&od->pdev.dev, "%s: kzalloc fail\n", __func__);
+		dev_err(&pdev->dev, "%s: kzalloc fail\n", __func__);
 		return -ENOMEM;
 	}
 	return 0;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/dpll3xxx.c linux-libre-3.2-gnu/arch/arm/mach-omap2/dpll3xxx.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/dpll3xxx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/dpll3xxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -390,7 +390,8 @@
 	 * propagating?
 	 */
 	if (!r)
-		clk->rate = omap2_get_dpll_rate(clk);
+		clk->rate = (clk->recalc) ? clk->recalc(clk) :
+			omap2_get_dpll_rate(clk);
 
 	return r;
 }
@@ -424,6 +425,7 @@
 int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
 {
 	struct clk *new_parent = NULL;
+	unsigned long hw_rate;
 	u16 freqsel = 0;
 	struct dpll_data *dd;
 	int ret;
@@ -435,7 +437,8 @@
 	if (!dd)
 		return -EINVAL;
 
-	if (rate == omap2_get_dpll_rate(clk))
+	hw_rate = (clk->recalc) ? clk->recalc(clk) : omap2_get_dpll_rate(clk);
+	if (rate == hw_rate)
 		return 0;
 
 	/*
@@ -455,7 +458,7 @@
 			new_parent = dd->clk_bypass;
 	} else {
 		if (dd->last_rounded_rate != rate)
-			omap2_dpll_round_rate(clk, rate);
+			rate = clk->round_rate(clk, rate);
 
 		if (dd->last_rounded_rate == 0)
 			return -EINVAL;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/dpll44xx.c linux-libre-3.2-gnu/arch/arm/mach-omap2/dpll44xx.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/dpll44xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/dpll44xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <plat/clock.h>
 
 #include "clock.h"
+#include "clock44xx.h"
 #include "cm-regbits-44xx.h"
 
 /* Supported only on OMAP4 */
@@ -82,3 +83,71 @@
 	.deny_idle	= omap4_dpllmx_deny_gatectrl,
 };
 
+/**
+ * omap4_dpll_regm4xen_recalc - compute DPLL rate, considering REGM4XEN bit
+ * @clk: struct clk * of the DPLL to compute the rate for
+ *
+ * Compute the output rate for the OMAP4 DPLL represented by @clk.
+ * Takes the REGM4XEN bit into consideration, which is needed for the
+ * OMAP4 ABE DPLL.  Returns the DPLL's output rate (before M-dividers)
+ * upon success, or 0 upon error.
+ */
+unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk)
+{
+	u32 v;
+	unsigned long rate;
+	struct dpll_data *dd;
+
+	if (!clk || !clk->dpll_data)
+		return 0;
+
+	dd = clk->dpll_data;
+
+	rate = omap2_get_dpll_rate(clk);
+
+	/* regm4xen adds a multiplier of 4 to DPLL calculations */
+	v = __raw_readl(dd->control_reg);
+	if (v & OMAP4430_DPLL_REGM4XEN_MASK)
+		rate *= OMAP4430_REGM4XEN_MULT;
+
+	return rate;
+}
+
+/**
+ * omap4_dpll_regm4xen_round_rate - round DPLL rate, considering REGM4XEN bit
+ * @clk: struct clk * of the DPLL to round a rate for
+ * @target_rate: the desired rate of the DPLL
+ *
+ * Compute the rate that would be programmed into the DPLL hardware
+ * for @clk if set_rate() were to be provided with the rate
+ * @target_rate.  Takes the REGM4XEN bit into consideration, which is
+ * needed for the OMAP4 ABE DPLL.  Returns the rounded rate (before
+ * M-dividers) upon success, -EINVAL if @clk is null or not a DPLL, or
+ * ~0 if an error occurred in omap2_dpll_round_rate().
+ */
+long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate)
+{
+	u32 v;
+	struct dpll_data *dd;
+	long r;
+
+	if (!clk || !clk->dpll_data)
+		return -EINVAL;
+
+	dd = clk->dpll_data;
+
+	/* regm4xen adds a multiplier of 4 to DPLL calculations */
+	v = __raw_readl(dd->control_reg) & OMAP4430_DPLL_REGM4XEN_MASK;
+
+	if (v)
+		target_rate = target_rate / OMAP4430_REGM4XEN_MULT;
+
+	r = omap2_dpll_round_rate(clk, target_rate);
+	if (r == ~0)
+		return r;
+
+	if (v)
+		clk->dpll_data->last_rounded_rate *= OMAP4430_REGM4XEN_MULT;
+
+	return clk->dpll_data->last_rounded_rate;
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/dsp.c linux-libre-3.2-gnu/arch/arm/mach-omap2/dsp.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/dsp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/dsp.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
  * of the OMAP PM core code.
  */
 
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include "cm2xxx_3xxx.h"
 #include "prm2xxx_3xxx.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/gpio.c linux-libre-3.2-gnu/arch/arm/mach-omap2/gpio.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,17 +24,9 @@
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
 
-static struct omap_device_pm_latency omap_gpio_latency[] = {
-	[0] = {
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
 {
-	struct omap_device *od;
+	struct platform_device *pdev;
 	struct omap_gpio_platform_data *pdata;
 	struct omap_gpio_dev_attr *dev_attr;
 	char *name = "omap_gpio";
@@ -107,19 +99,17 @@
 		return -EINVAL;
 	}
 
-	od = omap_device_build(name, id - 1, oh, pdata,
-				sizeof(*pdata),	omap_gpio_latency,
-				ARRAY_SIZE(omap_gpio_latency),
-				false);
+	pdev = omap_device_build(name, id - 1, oh, pdata,
+				sizeof(*pdata),	NULL, 0, false);
 	kfree(pdata);
 
-	if (IS_ERR(od)) {
+	if (IS_ERR(pdev)) {
 		WARN(1, "Can't build omap_device for %s:%s.\n",
 					name, oh->name);
-		return PTR_ERR(od);
+		return PTR_ERR(pdev);
 	}
 
-	omap_device_disable_idle_on_suspend(od);
+	omap_device_disable_idle_on_suspend(pdev);
 
 	gpio_bank_count++;
 	return 0;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/gpmc-onenand.c linux-libre-3.2-gnu/arch/arm/mach-omap2/gpmc-onenand.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/gpmc-onenand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/gpmc-onenand.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/onenand_regs.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/hsmmc.c linux-libre-3.2-gnu/arch/arm/mach-omap2/hsmmc.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/hsmmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/hsmmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -129,15 +129,11 @@
 	 * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the
 	 * card with Vcc regulator (from twl4030 or whatever).  OMAP has both
 	 * 1.8V and 3.0V modes, controlled by the PBIAS register.
-	 *
-	 * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which
-	 * is most naturally TWL VSIM; those pins also use PBIAS.
-	 *
-	 * FIXME handle VMMC1A as needed ...
 	 */
 	reg = omap4_ctrl_pad_readl(control_pbias_offset);
 	reg &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
-		OMAP4_MMC1_PWRDNZ_MASK);
+		OMAP4_MMC1_PWRDNZ_MASK |
+		OMAP4_MMC1_PBIASLITE_VMODE_MASK);
 	omap4_ctrl_pad_writel(reg, control_pbias_offset);
 }
 
@@ -172,12 +168,6 @@
 			reg &= ~(OMAP4_MMC1_PWRDNZ_MASK);
 			omap4_ctrl_pad_writel(reg, control_pbias_offset);
 		}
-	} else {
-		reg = omap4_ctrl_pad_readl(control_pbias_offset);
-		reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
-			OMAP4_MMC1_PWRDNZ_MASK |
-			OMAP4_MMC1_PBIASLITE_VMODE_MASK);
-		omap4_ctrl_pad_writel(reg, control_pbias_offset);
 	}
 }
 
@@ -409,31 +399,17 @@
 	return 0;
 }
 
-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.
-	 */
-};
-
 #define MAX_OMAP_MMC_HWMOD_NAME_LEN		16
 
 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;
+	struct platform_device *pdev;
 	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) {
@@ -448,8 +424,6 @@
 	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);
@@ -467,9 +441,9 @@
 		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)) {
+	pdev = omap_device_build(name, ctrl_nr - 1, oh, mmc_data,
+		sizeof(struct omap_mmc_platform_data), NULL, 0, false);
+	if (IS_ERR(pdev)) {
 		WARN(1, "Can't build omap_device for %s:%s.\n", name, oh->name);
 		kfree(mmc_data->slots[0].name);
 		goto done;
@@ -478,7 +452,7 @@
 	 * return device handle to board setup code
 	 * required to populate for regulator framework structure
 	 */
-	hsmmcinfo->dev = &od->pdev.dev;
+	hsmmcinfo->dev = &pdev->dev;
 
 done:
 	kfree(mmc_data);
@@ -505,7 +479,7 @@
 			OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK);
 		reg &= ~(OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK |
 			OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK);
-		reg |= (OMAP4_USBC1_DR0_SPEEDCTRL_MASK|
+		reg |= (OMAP4_SDMMC1_DR0_SPEEDCTRL_MASK |
 			OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK |
 			OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK);
 		omap4_ctrl_pad_writel(reg, control_mmc1);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/hwspinlock.c linux-libre-3.2-gnu/arch/arm/mach-omap2/hwspinlock.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/hwspinlock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/hwspinlock.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,23 +19,20 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/hwspinlock.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,
-	}
+static struct hwspinlock_pdata omap_hwspinlock_pdata __initdata = {
+	.base_id = 0,
 };
 
 int __init hwspinlocks_init(void)
 {
 	int retval = 0;
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	const char *oh_name = "spinlock";
 	const char *dev_name = "omap_hwspinlock";
 
@@ -48,13 +45,13 @@
 	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)) {
+	pdev = omap_device_build(dev_name, 0, oh, &omap_hwspinlock_pdata,
+				sizeof(struct hwspinlock_pdata),
+				NULL, 0, false);
+	if (IS_ERR(pdev)) {
 		pr_err("Can't build omap_device for %s:%s\n", dev_name,
 								oh_name);
-		retval = PTR_ERR(od);
+		retval = PTR_ERR(pdev);
 	}
 
 	return retval;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/id.c linux-libre-3.2-gnu/arch/arm/mach-omap2/id.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/id.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/id.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,6 @@
 
 #include "control.h"
 
-static struct omap_chip_id omap_chip;
 static unsigned int omap_revision;
 
 u32 omap_features;
@@ -39,19 +38,6 @@
 }
 EXPORT_SYMBOL(omap_rev);
 
-/**
- * omap_chip_is - test whether currently running OMAP matches a chip type
- * @oc: omap_chip_t to test against
- *
- * Test whether the currently-running OMAP chip matches the supplied
- * chip type 'oc'.  Returns 1 upon a match; 0 upon failure.
- */
-int omap_chip_is(struct omap_chip_id oci)
-{
-	return (oci.oc & omap_chip.oc) ? 1 : 0;
-}
-EXPORT_SYMBOL(omap_chip_is);
-
 int omap_type(void)
 {
 	u32 val = 0;
@@ -201,8 +187,11 @@
 	OMAP3_CHECK_FEATURE(status, ISP);
 	if (cpu_is_omap3630())
 		omap_features |= OMAP3_HAS_192MHZ_CLK;
-	if (!cpu_is_omap3505() && !cpu_is_omap3517())
+	if (cpu_is_omap3430() || cpu_is_omap3630())
 		omap_features |= OMAP3_HAS_IO_WAKEUP;
+	if (cpu_is_omap3630() || omap_rev() == OMAP3430_REV_ES3_1 ||
+	    omap_rev() == OMAP3430_REV_ES3_1_2)
+		omap_features |= OMAP3_HAS_IO_CHAIN_CTRL;
 
 	omap_features |= OMAP3_HAS_SDRC;
 
@@ -242,14 +231,12 @@
 	omap_features = OMAP3_HAS_NEON;
 }
 
-static void __init omap3_check_revision(void)
+static void __init omap3_check_revision(const char **cpu_rev)
 {
 	u32 cpuid, idcode;
 	u16 hawkeye;
 	u8 rev;
 
-	omap_chip.oc = CHIP_IS_OMAP3430;
-
 	/*
 	 * We cannot access revision registers on ES1.0.
 	 * If the processor type is Cortex-A8 and the revision is 0x0
@@ -258,7 +245,7 @@
 	cpuid = read_cpuid(CPUID_ID);
 	if ((((cpuid >> 4) & 0xfff) == 0xc08) && ((cpuid & 0xf) == 0x0)) {
 		omap_revision = OMAP3430_REV_ES1_0;
-		omap_chip.oc |= CHIP_IS_OMAP3430ES1;
+		*cpu_rev = "1.0";
 		return;
 	}
 
@@ -279,77 +266,85 @@
 		case 0: /* Take care of early samples */
 		case 1:
 			omap_revision = OMAP3430_REV_ES2_0;
-			omap_chip.oc |= CHIP_IS_OMAP3430ES2;
+			*cpu_rev = "2.0";
 			break;
 		case 2:
 			omap_revision = OMAP3430_REV_ES2_1;
-			omap_chip.oc |= CHIP_IS_OMAP3430ES2;
+			*cpu_rev = "2.1";
 			break;
 		case 3:
 			omap_revision = OMAP3430_REV_ES3_0;
-			omap_chip.oc |= CHIP_IS_OMAP3430ES3_0;
+			*cpu_rev = "3.0";
 			break;
 		case 4:
 			omap_revision = OMAP3430_REV_ES3_1;
-			omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
+			*cpu_rev = "3.1";
 			break;
 		case 7:
 		/* FALLTHROUGH */
 		default:
 			/* Use the latest known revision as default */
 			omap_revision = OMAP3430_REV_ES3_1_2;
-
-			/* REVISIT: Add CHIP_IS_OMAP3430ES3_1_2? */
-			omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
+			*cpu_rev = "3.1.2";
 		}
 		break;
 	case 0xb868:
-		/* Handle OMAP35xx/AM35xx devices
+		/*
+		 * Handle OMAP/AM 3505/3517 devices
 		 *
-		 * Set the device to be OMAP3505 here. Actual device
+		 * Set the device to be OMAP3517 here. Actual device
 		 * is identified later based on the features.
-		 *
-		 * REVISIT: AM3505/AM3517 should have their own CHIP_IS
 		 */
-		omap_revision = OMAP3505_REV(rev);
-		omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
+		switch (rev) {
+		case 0:
+			omap_revision = OMAP3517_REV_ES1_0;
+			*cpu_rev = "1.0";
+			break;
+		case 1:
+		/* FALLTHROUGH */
+		default:
+			omap_revision = OMAP3517_REV_ES1_1;
+			*cpu_rev = "1.1";
+		}
 		break;
 	case 0xb891:
 		/* Handle 36xx devices */
-		omap_chip.oc |= CHIP_IS_OMAP3630ES1;
 
 		switch(rev) {
 		case 0: /* Take care of early samples */
 			omap_revision = OMAP3630_REV_ES1_0;
+			*cpu_rev = "1.0";
 			break;
 		case 1:
 			omap_revision = OMAP3630_REV_ES1_1;
-			omap_chip.oc |= CHIP_IS_OMAP3630ES1_1;
+			*cpu_rev = "1.1";
 			break;
 		case 2:
+		/* FALLTHROUGH */
 		default:
-			omap_revision =  OMAP3630_REV_ES1_2;
-			omap_chip.oc |= CHIP_IS_OMAP3630ES1_2;
+			omap_revision = OMAP3630_REV_ES1_2;
+			*cpu_rev = "1.2";
 		}
 		break;
 	case 0xb81e:
-		omap_chip.oc = CHIP_IS_TI816X;
-
 		switch (rev) {
 		case 0:
 			omap_revision = TI8168_REV_ES1_0;
+			*cpu_rev = "1.0";
 			break;
 		case 1:
+		/* FALLTHROUGH */
+		default:
 			omap_revision = TI8168_REV_ES1_1;
+			*cpu_rev = "1.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;
-		omap_chip.oc |= CHIP_IS_OMAP3630ES1_2;
+		/* Unknown default to latest silicon rev as default */
+		omap_revision = OMAP3630_REV_ES1_2;
+		*cpu_rev = "1.2";
+		pr_warn("Warning: unknown chip type; assuming OMAP3630ES1.2\n");
 	}
 }
 
@@ -382,24 +377,20 @@
 		switch (rev) {
 		case 0:
 			omap_revision = OMAP4430_REV_ES1_0;
-			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_2;
-			omap_chip.oc |= CHIP_IS_OMAP4430ES2_2;
 		}
 		break;
 	case 0xb94e:
@@ -407,14 +398,12 @@
 		case 0:
 		default:
 			omap_revision = OMAP4460_REV_ES1_0;
-			omap_chip.oc |= CHIP_IS_OMAP4460ES1_0;
 			break;
 		}
 		break;
 	default:
 		/* 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.%d\n", omap_rev() >> 16,
@@ -425,94 +414,33 @@
 	if (omap3_has_ ##feat())		\
 		printk(#feat" ");
 
-static void __init omap3_cpuinfo(void)
+static void __init omap3_cpuinfo(const char *cpu_rev)
 {
-	u8 rev = GET_OMAP_REVISION();
-	char cpu_name[16], cpu_rev[16];
+	const char *cpu_name;
 
-	/* OMAP3430 and OMAP3530 are assumed to be same.
+	/*
+	 * OMAP3430 and OMAP3530 are assumed to be same.
 	 *
 	 * OMAP3525, OMAP3515 and OMAP3503 can be detected only based
 	 * on available features. Upon detection, update the CPU id
 	 * and CPU class bits.
 	 */
 	if (cpu_is_omap3630()) {
-		strcpy(cpu_name, "OMAP3630");
-	} else if (cpu_is_omap3505()) {
-		/*
-		 * AM35xx devices
-		 */
-		if (omap3_has_sgx()) {
-			omap_revision = OMAP3517_REV(rev);
-			strcpy(cpu_name, "AM3517");
-		} else {
-			/* Already set in omap3_check_revision() */
-			strcpy(cpu_name, "AM3505");
-		}
+		cpu_name = "OMAP3630";
+	} else if (cpu_is_omap3517()) {
+		/* AM35xx devices */
+		cpu_name = (omap3_has_sgx()) ? "AM3517" : "AM3505";
 	} else if (cpu_is_ti816x()) {
-		strcpy(cpu_name, "TI816X");
+		cpu_name = "TI816X";
 	} else if (omap3_has_iva() && omap3_has_sgx()) {
 		/* OMAP3430, OMAP3525, OMAP3515, OMAP3503 devices */
-		strcpy(cpu_name, "OMAP3430/3530");
+		cpu_name = "OMAP3430/3530";
 	} else if (omap3_has_iva()) {
-		omap_revision = OMAP3525_REV(rev);
-		strcpy(cpu_name, "OMAP3525");
+		cpu_name = "OMAP3525";
 	} else if (omap3_has_sgx()) {
-		omap_revision = OMAP3515_REV(rev);
-		strcpy(cpu_name, "OMAP3515");
-	} else {
-		omap_revision = OMAP3503_REV(rev);
-		strcpy(cpu_name, "OMAP3503");
-	}
-
-	if (cpu_is_omap3630() || cpu_is_ti816x()) {
-		switch (rev) {
-		case OMAP_REVBITS_00:
-			strcpy(cpu_rev, "1.0");
-			break;
-		case OMAP_REVBITS_01:
-			strcpy(cpu_rev, "1.1");
-			break;
-		case OMAP_REVBITS_02:
-			/* FALLTHROUGH */
-		default:
-			/* Use the latest known revision as default */
-			strcpy(cpu_rev, "1.2");
-		}
-	} else if (cpu_is_omap3505() || cpu_is_omap3517()) {
-		switch (rev) {
-		case OMAP_REVBITS_00:
-			strcpy(cpu_rev, "1.0");
-			break;
-		case OMAP_REVBITS_01:
-			/* FALLTHROUGH */
-		default:
-			/* Use the latest known revision as default */
-			strcpy(cpu_rev, "1.1");
-		}
+		cpu_name = "OMAP3515";
 	} else {
-		switch (rev) {
-		case OMAP_REVBITS_00:
-			strcpy(cpu_rev, "1.0");
-			break;
-		case OMAP_REVBITS_01:
-			strcpy(cpu_rev, "2.0");
-			break;
-		case OMAP_REVBITS_02:
-			strcpy(cpu_rev, "2.1");
-			break;
-		case OMAP_REVBITS_03:
-			strcpy(cpu_rev, "3.0");
-			break;
-		case OMAP_REVBITS_04:
-			strcpy(cpu_rev, "3.1");
-			break;
-		case OMAP_REVBITS_05:
-			/* FALLTHROUGH */
-		default:
-			/* Use the latest known revision as default */
-			strcpy(cpu_rev, "3.1.2");
-		}
+		cpu_name = "OMAP3503";
 	}
 
 	/* Print verbose information */
@@ -533,6 +461,8 @@
  */
 void __init omap2_check_revision(void)
 {
+	const char *cpu_rev;
+
 	/*
 	 * At this point we have an idea about the processor revision set
 	 * earlier with omap2_set_globals_tap().
@@ -540,7 +470,7 @@
 	if (cpu_is_omap24xx()) {
 		omap24xx_check_revision();
 	} else if (cpu_is_omap34xx()) {
-		omap3_check_revision();
+		omap3_check_revision(&cpu_rev);
 
 		/* TI816X doesn't have feature register */
 		if (!cpu_is_ti816x())
@@ -548,7 +478,7 @@
 		else
 			ti816x_check_features();
 
-		omap3_cpuinfo();
+		omap3_cpuinfo(cpu_rev);
 		return;
 	} else if (cpu_is_omap44xx()) {
 		omap4_check_revision();
@@ -557,22 +487,6 @@
 	} else {
 		pr_err("OMAP revision unknown, please fix!\n");
 	}
-
-	/*
-	 * OK, now we know the exact revision. Initialize omap_chip bits
-	 * for powerdowmain and clockdomain code.
-	 */
-	if (cpu_is_omap243x()) {
-		/* Currently only supports 2430ES2.1 and 2430-all */
-		omap_chip.oc |= CHIP_IS_OMAP2430;
-		return;
-	} else if (cpu_is_omap242x()) {
-		/* Currently only supports 2420ES2.1.1 and 2420-all */
-		omap_chip.oc |= CHIP_IS_OMAP2420;
-		return;
-	}
-
-	pr_err("Uninitialized omap_chip, please fix!\n");
 }
 
 /*
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h linux-libre-3.2-gnu/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -941,10 +941,10 @@
 #define OMAP4_DSI2_LANEENABLE_MASK				(0x7 << 29)
 #define OMAP4_DSI1_LANEENABLE_SHIFT				24
 #define OMAP4_DSI1_LANEENABLE_MASK				(0x1f << 24)
-#define OMAP4_DSI1_PIPD_SHIFT					19
-#define OMAP4_DSI1_PIPD_MASK					(0x1f << 19)
-#define OMAP4_DSI2_PIPD_SHIFT					14
-#define OMAP4_DSI2_PIPD_MASK					(0x1f << 14)
+#define OMAP4_DSI2_PIPD_SHIFT					19
+#define OMAP4_DSI2_PIPD_MASK					(0x1f << 19)
+#define OMAP4_DSI1_PIPD_SHIFT					14
+#define OMAP4_DSI1_PIPD_MASK					(0x1f << 14)
 
 /* CONTROL_MCBSPLP */
 #define OMAP4_ALBCTRLRX_FSX_SHIFT				31
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-omap2/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -13,15 +13,10 @@
 
 #include <linux/serial_reg.h>
 
-#include <asm/memory.h>
-
 #include <plat/serial.h>
 
 #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
@@ -34,26 +29,25 @@
 		 * the desired UART phys and virt addresses temporarily into
 		 * the omap_uart_phys and omap_uart_virt above.
 		 */
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 
 		/* Use omap_uart_phys/virt if already configured */
-10:		mrc	p15, 0, \rp, c1, c0
-		tst	\rp, #1			@ MMU 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]
-		ldr	\rv, [\rv, #0]
+10:		adr	\rp, 99f		@ get effective addr of 99f
+		ldr	\rv, [\rp]		@ get absolute addr of 99f
+		sub	\rv, \rv, \rp		@ offset between the two
+		ldr	\rp, [\rp, #4]		@ abs addr of omap_uart_phys
+		sub	\tmp, \rp, \rv		@ make it effective
+		ldr	\rp, [\tmp, #0]		@ omap_uart_phys
+		ldr	\rv, [\tmp, #4]		@ omap_uart_virt
 		cmp	\rp, #0			@ is port configured?
 		cmpne	\rv, #0
-		bne	99f			@ already configured
+		bne	100f			@ already configured
 
 		/* Check the debug UART configuration set in uncompress.h */
-		mrc	p15, 0, \rp, c1, c0
-		tst	\rp, #1			@ MMU enabled?
-		ldreq	\rp, =OMAP_UART_INFO	@ MMU not enabled
-		ldrne	\rp, =omap_uart_p2v(OMAP_UART_INFO)	@ MMU enabled
-		ldr	\rp, [\rp, #0]
+		mov	\rp, pc
+		ldr	\rv, =OMAP_UART_INFO_OFS
+		and	\rp, \rp, #0xff000000
+		ldr	\rp, [\rp, \rv]
 
 		/* Select the UART to use based on the UART1 scratchpad value */
 		cmp	\rp, #0			@ no port configured?
@@ -106,50 +100,47 @@
 		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, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
-		ldrne	\rv, =omap_uart_phys	@ MMU enabled
-		str	\rp, [\rv, #0]
+		str	\rp, [\tmp, #0]		@ omap_uart_phys
 		ldr	\rp, =ZOOM_UART_VIRT
-		add	\rv, \rv, #4		@ omap_uart_virt
-		str	\rp, [\rv, #0]
+		str	\rp, [\tmp, #4]		@ omap_uart_virt
 		mov	\rp, #(UART_LSR << ZOOM_PORT_SHIFT)
-		add	\rv, \rv, #4		@ omap_uart_lsr
-		str	\rp, [\rv, #0]
+		str	\rp, [\tmp, #8]		@ omap_uart_lsr
 		b	10b
 
 		/* Store both phys and virt address for the uart */
 98:		add	\rp, \rp, #0x48000000	@ phys base
-		mrc	p15, 0, \rv, c1, c0
-		tst	\rv, #1			@ MMU enabled?
-		ldreq	\rv, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
-		ldrne	\rv, =omap_uart_phys	@ MMU enabled
-		str	\rp, [\rv, #0]
+		str	\rp, [\tmp, #0]		@ omap_uart_phys
 		sub	\rp, \rp, #0x48000000	@ phys base
 		add	\rp, \rp, #0xfa000000	@ virt base
-		add	\rv, \rv, #4		@ omap_uart_virt
-		str	\rp, [\rv, #0]
+		str	\rp, [\tmp, #4]		@ omap_uart_virt
 		mov	\rp, #(UART_LSR << OMAP_PORT_SHIFT)
-		add	\rv, \rv, #4		@ omap_uart_lsr
-		str	\rp, [\rv, #0]
+		str	\rp, [\tmp, #8]		@ omap_uart_lsr
 
 		b	10b
-99:
+
+		.align
+99:		.word	.
+		.word	omap_uart_phys
+		.ltorg
+
+100:		/* Pass the UART_LSR reg address */
+		ldr	\tmp, [\tmp, #8]	@ omap_uart_lsr
+		add	\rp, \rp, \tmp
+		add	\rv, \rv, \tmp
 		.endm
 
 		.macro	senduart,rd,rx
-		strb	\rd, [\rx]
+		orr	\rd, \rd, \rx, lsl #24	@ preserve LSR reg offset
+		bic	\rx, \rx, #0xff		@ get base (THR) reg address
+		strb	\rd, [\rx]		@ send lower byte of rd
+		orr	\rx, \rx, \rd, lsr #24	@ restore original rx (LSR)
+		bic	\rd, \rd, #(0xff << 24)	@ restore original rd
 		.endm
 
 		.macro	busyuart,rd,rx
-1001:		mrc	p15, 0, \rd, c1, c0
-		tst	\rd, #1			@ MMU 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]
+1001:		ldrb	\rd, [\rx]		@ rx contains UART_LSR address
 		and	\rd, \rd, #(UART_LSR_TEMT | UART_LSR_THRE)
 		teq	\rd, #(UART_LSR_TEMT | UART_LSR_THRE)
 		bne	1001b
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/include/mach/entry-macro.S linux-libre-3.2-gnu/arch/arm/mach-omap2/include/mach/entry-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/include/mach/entry-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/include/mach/entry-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -78,7 +78,7 @@
 4401:		ldr     \irqstat, [\base, #GIC_CPU_INTACK]
 		ldr     \tmp, =1021
 		bic     \irqnr, \irqstat, #0x1c00
-		cmp     \irqnr, #29
+		cmp     \irqnr, #15
 		cmpcc   \irqnr, \irqnr
 		cmpne   \irqnr, \tmp
 		cmpcs   \irqnr, \irqnr
@@ -101,18 +101,6 @@
 		it	cs
 		cmpcs	\irqnr, \irqnr
 		.endm
-
-		/* As above, this assumes that irqstat and base are preserved */
-
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov 	\tmp, #0
-		cmp	\irqnr, #29
-		itt	eq
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
 #endif	/* CONFIG_SMP */
 
 #else	/* MULTI_OMAP2 */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-omap2/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-/*
- * arch/arm/mach-omap2/include/mach/memory.h
- */
-
-#include <plat/memory.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/io.c linux-libre-3.2-gnu/arch/arm/mach-omap2/io.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/io.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,6 @@
  * 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>
@@ -35,14 +34,16 @@
 #include "clock2xxx.h"
 #include "clock3xxx.h"
 #include "clock44xx.h"
-#include "io.h"
 
+#include <plat/common.h>
 #include <plat/omap-pm.h>
+#include "voltage.h"
 #include "powerdomain.h"
 
 #include "clockdomain.h"
 #include <plat/omap_hwmod.h>
 #include <plat/multi.h>
+#include <plat/common.h>
 
 /*
  * The machine specific code may provide the extra mapping besides the
@@ -239,25 +240,11 @@
 };
 #endif
 
-static void __init _omap2_map_common_io(void)
-{
-	/* Normally devicemaps_init() would flush caches and tlb after
-	 * mdesc->map_io(), but we must also do it here because of the CPU
-	 * revision check below.
-	 */
-	local_flush_tlb_all();
-	flush_cache_all();
-
-	omap2_check_revision();
-	omap_sram_init();
-}
-
 #ifdef CONFIG_SOC_OMAP2420
 void __init omap242x_map_common_io(void)
 {
 	iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
 	iotable_init(omap242x_io_desc, ARRAY_SIZE(omap242x_io_desc));
-	_omap2_map_common_io();
 }
 #endif
 
@@ -266,7 +253,6 @@
 {
 	iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
 	iotable_init(omap243x_io_desc, ARRAY_SIZE(omap243x_io_desc));
-	_omap2_map_common_io();
 }
 #endif
 
@@ -274,7 +260,6 @@
 void __init omap34xx_map_common_io(void)
 {
 	iotable_init(omap34xx_io_desc, ARRAY_SIZE(omap34xx_io_desc));
-	_omap2_map_common_io();
 }
 #endif
 
@@ -282,7 +267,6 @@
 void __init omapti816x_map_common_io(void)
 {
 	iotable_init(omapti816x_io_desc, ARRAY_SIZE(omapti816x_io_desc));
-	_omap2_map_common_io();
 }
 #endif
 
@@ -290,7 +274,6 @@
 void __init omap44xx_map_common_io(void)
 {
 	iotable_init(omap44xx_io_desc, ARRAY_SIZE(omap44xx_io_desc));
-	_omap2_map_common_io();
 }
 #endif
 
@@ -336,29 +319,16 @@
 /* See irq.c, omap4-common.c and entry-macro.S */
 void __iomem *omap_irq_base;
 
-void __init omap2_init_common_infrastructure(void)
+static void __init omap_common_init_early(void)
 {
-	u8 postsetup_state;
+	omap2_check_revision();
+	omap_ioremap_init();
+	omap_init_consistent_dma_size();
+}
 
-	if (cpu_is_omap242x()) {
-		omap2xxx_powerdomains_init();
-		omap2xxx_clockdomains_init();
-		omap2420_hwmod_init();
-	} else if (cpu_is_omap243x()) {
-		omap2xxx_powerdomains_init();
-		omap2xxx_clockdomains_init();
-		omap2430_hwmod_init();
-	} else if (cpu_is_omap34xx()) {
-		omap3xxx_powerdomains_init();
-		omap3xxx_clockdomains_init();
-		omap3xxx_hwmod_init();
-	} else if (cpu_is_omap44xx()) {
-		omap44xx_powerdomains_init();
-		omap44xx_clockdomains_init();
-		omap44xx_hwmod_init();
-	} else {
-		pr_err("Could not init hwmod data - unknown SoC\n");
-        }
+static void __init omap_hwmod_init_postsetup(void)
+{
+	u8 postsetup_state;
 
 	/* Set the default postsetup state for all hwmods */
 #ifdef CONFIG_PM_RUNTIME
@@ -376,7 +346,7 @@
 	 * omap_hwmod_late_init(), so boards that desire full watchdog
 	 * coverage of kernel initialization can reprogram the
 	 * postsetup_state between the calls to
-	 * omap2_init_common_infra() and omap2_init_common_devices().
+	 * omap2_init_common_infra() and omap_sdrc_init().
 	 *
 	 * XXX ideally we could detect whether the MPU WDT was currently
 	 * enabled here and make this conditional
@@ -387,27 +357,107 @@
 				     &postsetup_state);
 
 	omap_pm_if_early_init();
+}
 
-	if (cpu_is_omap2420())
-		omap2420_clk_init();
-	else if (cpu_is_omap2430())
-		omap2430_clk_init();
-	else if (cpu_is_omap34xx())
-		omap3xxx_clk_init();
-	else if (cpu_is_omap44xx())
-		omap4xxx_clk_init();
-	else
-		pr_err("Could not init clock framework - unknown SoC\n");
+#ifdef CONFIG_ARCH_OMAP2
+void __init omap2420_init_early(void)
+{
+	omap2_set_globals_242x();
+	omap_common_init_early();
+	omap2xxx_voltagedomains_init();
+	omap242x_powerdomains_init();
+	omap242x_clockdomains_init();
+	omap2420_hwmod_init();
+	omap_hwmod_init_postsetup();
+	omap2420_clk_init();
 }
 
-void __init omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
+void __init omap2430_init_early(void)
+{
+	omap2_set_globals_243x();
+	omap_common_init_early();
+	omap2xxx_voltagedomains_init();
+	omap243x_powerdomains_init();
+	omap243x_clockdomains_init();
+	omap2430_hwmod_init();
+	omap_hwmod_init_postsetup();
+	omap2430_clk_init();
+}
+#endif
+
+/*
+ * Currently only board-omap3beagle.c should call this because of the
+ * same machine_id for 34xx and 36xx beagle.. Will get fixed with DT.
+ */
+#ifdef CONFIG_ARCH_OMAP3
+void __init omap3_init_early(void)
+{
+	omap2_set_globals_3xxx();
+	omap_common_init_early();
+	omap3xxx_voltagedomains_init();
+	omap3xxx_powerdomains_init();
+	omap3xxx_clockdomains_init();
+	omap3xxx_hwmod_init();
+	omap_hwmod_init_postsetup();
+	omap3xxx_clk_init();
+}
+
+void __init omap3430_init_early(void)
+{
+	omap3_init_early();
+}
+
+void __init omap35xx_init_early(void)
+{
+	omap3_init_early();
+}
+
+void __init omap3630_init_early(void)
+{
+	omap3_init_early();
+}
+
+void __init am35xx_init_early(void)
+{
+	omap3_init_early();
+}
+
+void __init ti816x_init_early(void)
+{
+	omap2_set_globals_ti816x();
+	omap_common_init_early();
+	omap3xxx_voltagedomains_init();
+	omap3xxx_powerdomains_init();
+	omap3xxx_clockdomains_init();
+	omap3xxx_hwmod_init();
+	omap_hwmod_init_postsetup();
+	omap3xxx_clk_init();
+}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+void __init omap4430_init_early(void)
+{
+	omap2_set_globals_443x();
+	omap_common_init_early();
+	omap44xx_voltagedomains_init();
+	omap44xx_powerdomains_init();
+	omap44xx_clockdomains_init();
+	omap44xx_hwmod_init();
+	omap_hwmod_init_postsetup();
+	omap4xxx_clk_init();
+}
+#endif
+
+void __init omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
 				      struct omap_sdrc_params *sdrc_cs1)
 {
+	omap_sram_init();
+
 	if (cpu_is_omap24xx() || omap3_has_sdrc()) {
 		omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
 		_omap2_init_reprogram_sdrc();
 	}
-
 }
 
 /*
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/io.h linux-libre-3.2-gnu/arch/arm/mach-omap2/io.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/io.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-
-#ifndef __MACH_OMAP2_IO_H__
-#define __MACH_OMAP2_IO_H__
-
-extern int __init omap_sram_init(void);
-
-#endif /*  __MACH_OMAP2_IO_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/iommu2.c linux-libre-3.2-gnu/arch/arm/mach-omap2/iommu2.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/iommu2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/iommu2.c	2012-01-04 18:55:44.000000000 -0500
@@ -66,7 +66,7 @@
 	 ((pgsz) == MMU_CAM_PGSZ_4K)  ? 0xfffff000 : 0)
 
 
-static void __iommu_set_twl(struct iommu *obj, bool on)
+static void __iommu_set_twl(struct omap_iommu *obj, bool on)
 {
 	u32 l = iommu_read_reg(obj, MMU_CNTL);
 
@@ -85,7 +85,7 @@
 }
 
 
-static int omap2_iommu_enable(struct iommu *obj)
+static int omap2_iommu_enable(struct omap_iommu *obj)
 {
 	u32 l, pa;
 	unsigned long timeout;
@@ -127,7 +127,7 @@
 	return 0;
 }
 
-static void omap2_iommu_disable(struct iommu *obj)
+static void omap2_iommu_disable(struct omap_iommu *obj)
 {
 	u32 l = iommu_read_reg(obj, MMU_CNTL);
 
@@ -138,12 +138,12 @@
 	dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
 }
 
-static void omap2_iommu_set_twl(struct iommu *obj, bool on)
+static void omap2_iommu_set_twl(struct omap_iommu *obj, bool on)
 {
 	__iommu_set_twl(obj, false);
 }
 
-static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
+static u32 omap2_iommu_fault_isr(struct omap_iommu *obj, u32 *ra)
 {
 	u32 stat, da;
 	u32 errs = 0;
@@ -173,13 +173,13 @@
 	return errs;
 }
 
-static void omap2_tlb_read_cr(struct iommu *obj, struct cr_regs *cr)
+static void omap2_tlb_read_cr(struct omap_iommu *obj, struct cr_regs *cr)
 {
 	cr->cam = iommu_read_reg(obj, MMU_READ_CAM);
 	cr->ram = iommu_read_reg(obj, MMU_READ_RAM);
 }
 
-static void omap2_tlb_load_cr(struct iommu *obj, struct cr_regs *cr)
+static void omap2_tlb_load_cr(struct omap_iommu *obj, struct cr_regs *cr)
 {
 	iommu_write_reg(obj, cr->cam | MMU_CAM_V, MMU_CAM);
 	iommu_write_reg(obj, cr->ram, MMU_RAM);
@@ -193,7 +193,8 @@
 	return cr->cam & mask;
 }
 
-static struct cr_regs *omap2_alloc_cr(struct iommu *obj, struct iotlb_entry *e)
+static struct cr_regs *omap2_alloc_cr(struct omap_iommu *obj,
+						struct iotlb_entry *e)
 {
 	struct cr_regs *cr;
 
@@ -230,7 +231,8 @@
 	return attr;
 }
 
-static ssize_t omap2_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf)
+static ssize_t
+omap2_dump_cr(struct omap_iommu *obj, struct cr_regs *cr, char *buf)
 {
 	char *p = buf;
 
@@ -254,7 +256,8 @@
 			goto out;					\
 	} while (0)
 
-static ssize_t omap2_iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t len)
+static ssize_t
+omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len)
 {
 	char *p = buf;
 
@@ -280,7 +283,7 @@
 	return p - buf;
 }
 
-static void omap2_iommu_save_ctx(struct iommu *obj)
+static void omap2_iommu_save_ctx(struct omap_iommu *obj)
 {
 	int i;
 	u32 *p = obj->ctx;
@@ -293,7 +296,7 @@
 	BUG_ON(p[0] != IOMMU_ARCH_VERSION);
 }
 
-static void omap2_iommu_restore_ctx(struct iommu *obj)
+static void omap2_iommu_restore_ctx(struct omap_iommu *obj)
 {
 	int i;
 	u32 *p = obj->ctx;
@@ -343,13 +346,13 @@
 
 static int __init omap2_iommu_init(void)
 {
-	return install_iommu_arch(&omap2_iommu_ops);
+	return omap_install_iommu_arch(&omap2_iommu_ops);
 }
 module_init(omap2_iommu_init);
 
 static void __exit omap2_iommu_exit(void)
 {
-	uninstall_iommu_arch(&omap2_iommu_ops);
+	omap_uninstall_iommu_arch(&omap2_iommu_ops);
 }
 module_exit(omap2_iommu_exit);
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/irq.c linux-libre-3.2-gnu/arch/arm/mach-omap2/irq.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -165,8 +165,8 @@
 
 		omap_irq_bank_init_one(bank);
 
-		for (i = 0, j = 0; i < bank->nr_irqs; i += 32, j += 0x20)
-			omap_alloc_gc(bank->base_reg + j, i, 32);
+		for (j = 0; j < bank->nr_irqs; j += 32)
+			omap_alloc_gc(bank->base_reg + j, j, 32);
 
 		nr_of_irqs += bank->nr_irqs;
 		nr_banks++;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/Kconfig linux-libre-3.2-gnu/arch/arm/mach-omap2/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,6 @@
 	select SERIAL_OMAP_CONSOLE
 	select I2C
 	select I2C_OMAP
-	select MFD_SUPPORT
 	select MENELAUS if ARCH_OMAP2
 	select TWL4030_CORE if ARCH_OMAP3 || ARCH_OMAP4
 	select TWL4030_POWER if ARCH_OMAP3 || ARCH_OMAP4
@@ -36,6 +35,7 @@
 	select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4
 	select ARCH_HAS_OPP
 	select PM_OPP if PM
+	select ARM_CPU_SUSPEND if PM
 
 config ARCH_OMAP4
 	bool "TI OMAP4"
@@ -50,6 +50,7 @@
 	select ARCH_HAS_OPP
 	select PM_OPP if PM
 	select USB_ARCH_HAS_EHCI
+	select ARM_CPU_SUSPEND if PM
 
 comment "OMAP Core Type"
 	depends on ARCH_OMAP2
@@ -106,9 +107,13 @@
 	depends on ARCH_OMAP2PLUS
 
 config MACH_OMAP_GENERIC
-	bool "Generic OMAP board"
-	depends on ARCH_OMAP2
+	bool "Generic OMAP2+ board"
+	depends on ARCH_OMAP2PLUS
+	select USE_OF
 	default y
+	help
+	  Support for generic TI OMAP2+ boards using Flattened Device Tree.
+	  More information at Documentation/devicetree
 
 config MACH_OMAP2_TUSB6010
 	bool
@@ -329,6 +334,7 @@
 config OMAP3_EMU
 	bool "OMAP3 debugging peripherals"
 	depends on ARCH_OMAP3
+	select ARM_AMBA
 	select OC_ETM
 	help
 	  Say Y here to enable debugging hardware of omap3
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/mailbox.c linux-libre-3.2-gnu/arch/arm/mach-omap2/mailbox.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/mailbox.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/mailbox.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  * for more details.
  */
 
+#include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/Makefile linux-libre-3.2-gnu/arch/arm/mach-omap2/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer.o pm.o \
-	 common.o gpio.o dma.o wd_timer.o
+	 common.o gpio.o dma.o wd_timer.o display.o
 
 omap-2-3-common				= irq.o sdrc.o
 hwmod-common				= omap_hwmod.o \
@@ -89,14 +89,13 @@
 					   vp44xx_data.o
 
 # OMAP voltage domains
-ifeq ($(CONFIG_PM),y)
-voltagedomain-common			:= voltage.o
-obj-$(CONFIG_ARCH_OMAP2)		+= $(voltagedomain-common)
+voltagedomain-common			:= voltage.o vc.o vp.o
+obj-$(CONFIG_ARCH_OMAP2)		+= $(voltagedomain-common) \
+					   voltagedomains2xxx_data.o
 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
@@ -116,9 +115,12 @@
 obj-$(CONFIG_ARCH_OMAP2)		+= clockdomain.o \
 					   clockdomain2xxx_3xxx.o \
 					   clockdomains2xxx_3xxx_data.o
+obj-$(CONFIG_SOC_OMAP2420)		+= clockdomains2420_data.o
+obj-$(CONFIG_SOC_OMAP2430)		+= clockdomains2430_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clockdomain.o \
 					   clockdomain2xxx_3xxx.o \
-					   clockdomains2xxx_3xxx_data.o
+					   clockdomains2xxx_3xxx_data.o \
+					   clockdomains3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP4)		+= clockdomain.o \
 					   clockdomain44xx.o \
 					   clockdomains44xx_data.o
@@ -185,81 +187,67 @@
 # Specific board support
 obj-$(CONFIG_MACH_OMAP_GENERIC)		+= board-generic.o
 obj-$(CONFIG_MACH_OMAP_H4)		+= board-h4.o
-obj-$(CONFIG_MACH_OMAP_2430SDP)		+= board-2430sdp.o \
-					   hsmmc.o
+obj-$(CONFIG_MACH_OMAP_2430SDP)		+= board-2430sdp.o
 obj-$(CONFIG_MACH_OMAP_APOLLON)		+= board-apollon.o
-obj-$(CONFIG_MACH_OMAP3_BEAGLE)		+= board-omap3beagle.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_DEVKIT8000)     	+= board-devkit8000.o \
-                                           hsmmc.o
-obj-$(CONFIG_MACH_OMAP_LDP)		+= board-ldp.o \
-					   board-flash.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP3530_LV_SOM)      += board-omap3logic.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP3_TORPEDO)        += board-omap3logic.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OVERO)		+= board-overo.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP3EVM)		+= board-omap3evm.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP3_PANDORA)	+= board-omap3pandora.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP_3430SDP)		+= board-3430sdp.o \
-					   hsmmc.o \
-					   board-flash.o
+obj-$(CONFIG_MACH_OMAP3_BEAGLE)		+= board-omap3beagle.o
+obj-$(CONFIG_MACH_DEVKIT8000)     	+= board-devkit8000.o
+obj-$(CONFIG_MACH_OMAP_LDP)		+= board-ldp.o
+obj-$(CONFIG_MACH_OMAP3530_LV_SOM)      += board-omap3logic.o
+obj-$(CONFIG_MACH_OMAP3_TORPEDO)        += board-omap3logic.o
+obj-$(CONFIG_MACH_ENCORE)		+= board-omap3encore.o
+obj-$(CONFIG_MACH_OVERO)		+= board-overo.o
+obj-$(CONFIG_MACH_OMAP3EVM)		+= board-omap3evm.o
+obj-$(CONFIG_MACH_OMAP3_PANDORA)	+= board-omap3pandora.o
+obj-$(CONFIG_MACH_OMAP_3430SDP)		+= board-3430sdp.o
 obj-$(CONFIG_MACH_NOKIA_N8X0)		+= board-n8x0.o
 obj-$(CONFIG_MACH_NOKIA_RM680)		+= board-rm680.o \
-					   sdram-nokia.o \
-					   hsmmc.o
+					   sdram-nokia.o
 obj-$(CONFIG_MACH_NOKIA_RX51)		+= board-rx51.o \
 					   sdram-nokia.o \
 					   board-rx51-peripherals.o \
-					   board-rx51-video.o \
-					   hsmmc.o
+					   board-rx51-video.o
 obj-$(CONFIG_MACH_OMAP_ZOOM2)		+= board-zoom.o \
 					   board-zoom-peripherals.o \
 					   board-zoom-display.o \
-					   board-flash.o \
-					   hsmmc.o \
 					   board-zoom-debugboard.o
 obj-$(CONFIG_MACH_OMAP_ZOOM3)		+= board-zoom.o \
 					   board-zoom-peripherals.o \
 					   board-zoom-display.o \
-					   board-flash.o \
-					   hsmmc.o \
 					   board-zoom-debugboard.o
 obj-$(CONFIG_MACH_OMAP_3630SDP)		+= board-3630sdp.o \
 					   board-zoom-peripherals.o \
-					   board-zoom-display.o \
-					   board-flash.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_CM_T35)		+= board-cm-t35.o \
-					   hsmmc.o
+					   board-zoom-display.o
+obj-$(CONFIG_MACH_CM_T35)		+= board-cm-t35.o
 obj-$(CONFIG_MACH_CM_T3517)		+= board-cm-t3517.o
-obj-$(CONFIG_MACH_IGEP0020)		+= board-igep0020.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK)	+= board-omap3touchbook.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP_4430SDP)		+= board-4430sdp.o \
-					   hsmmc.o \
-					   omap_phy_internal.o
-obj-$(CONFIG_MACH_OMAP4_PANDA)		+= board-omap4panda.o \
-					   hsmmc.o \
-					   omap_phy_internal.o
+obj-$(CONFIG_MACH_IGEP0020)		+= board-igep0020.o
+obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK)	+= board-omap3touchbook.o
+obj-$(CONFIG_MACH_OMAP_4430SDP)		+= board-4430sdp.o
+obj-$(CONFIG_MACH_OMAP4_PANDA)		+= board-omap4panda.o
 
-obj-$(CONFIG_MACH_OMAP3517EVM)		+= board-am3517evm.o \
-					   omap_phy_internal.o \
+obj-$(CONFIG_MACH_PCM049)		+= board-omap4pcm049.o
+
+obj-$(CONFIG_MACH_OMAP3517EVM)		+= board-am3517evm.o
 
 obj-$(CONFIG_MACH_CRANEBOARD)		+= board-am3517crane.o
 
-obj-$(CONFIG_MACH_SBC3530)		+= board-omap3stalker.o \
-					   hsmmc.o
+obj-$(CONFIG_MACH_SBC3530)		+= board-omap3stalker.o
 obj-$(CONFIG_MACH_TI8168EVM)		+= board-ti8168evm.o
+
 # Platform specific device init code
+
+omap-flash-$(CONFIG_MTD_NAND_OMAP2)	:= board-flash.o
+omap-flash-$(CONFIG_MTD_ONENAND_OMAP2)	:= board-flash.o
+obj-y					+= $(omap-flash-y) $(omap-flash-m)
+
+omap-hsmmc-$(CONFIG_MMC_OMAP_HS)	:= hsmmc.o
+obj-y					+= $(omap-hsmmc-m) $(omap-hsmmc-y)
+
+
 usbfs-$(CONFIG_ARCH_OMAP_OTG)		:= usb-fs.o
 obj-y					+= $(usbfs-m) $(usbfs-y)
 obj-y					+= usb-musb.o
+obj-y					+= omap_phy_internal.o
+
 obj-$(CONFIG_MACH_OMAP2_TUSB6010)	+= usb-tusb6010.o
 obj-y					+= usb-host.o
 
@@ -276,7 +264,4 @@
 obj-y					+= $(smsc911x-m) $(smsc911x-y)
 obj-$(CONFIG_ARCH_OMAP4)		+= hwspinlock.o
 
-disp-$(CONFIG_OMAP2_DSS)		:= display.o
-obj-y					+= $(disp-m) $(disp-y)
-
 obj-y					+= common-board-devices.o twl-common.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-omap2/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-  zreladdr-y		:= 0x80008000
+  zreladdr-y		+= 0x80008000
 params_phys-y		:= 0x80000100
 initrd_phys-y		:= 0x80800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/mcbsp.c linux-libre-3.2-gnu/arch/arm/mach-omap2/mcbsp.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/mcbsp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/mcbsp.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,66 +27,69 @@
 
 #include "control.h"
 
-/* McBSP internal signal muxing functions */
+/*
+ * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle.
+ * Sidetone needs non-gated ICLK and sidetone autoidle is broken.
+ */
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-34xx.h"
 
-void omap2_mcbsp1_mux_clkr_src(u8 mux)
+/* McBSP internal signal muxing function */
+static int omap2_mcbsp1_mux_rx_clk(struct device *dev, const char *signal,
+				   const char *src)
 {
 	u32 v;
 
 	v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-	if (mux == CLKR_SRC_CLKR)
-		v &= ~OMAP2_MCBSP1_CLKR_MASK;
-	else if (mux == CLKR_SRC_CLKX)
-		v |= OMAP2_MCBSP1_CLKR_MASK;
-	omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
-}
-EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src);
 
-void omap2_mcbsp1_mux_fsr_src(u8 mux)
-{
-	u32 v;
+	if (!strcmp(signal, "clkr")) {
+		if (!strcmp(src, "clkr"))
+			v &= ~OMAP2_MCBSP1_CLKR_MASK;
+		else if (!strcmp(src, "clkx"))
+			v |= OMAP2_MCBSP1_CLKR_MASK;
+		else
+			return -EINVAL;
+	} else if (!strcmp(signal, "fsr")) {
+		if (!strcmp(src, "fsr"))
+			v &= ~OMAP2_MCBSP1_FSR_MASK;
+		else if (!strcmp(src, "fsx"))
+			v |= OMAP2_MCBSP1_FSR_MASK;
+		else
+			return -EINVAL;
+	} else {
+		return -EINVAL;
+	}
 
-	v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-	if (mux == FSR_SRC_FSR)
-		v &= ~OMAP2_MCBSP1_FSR_MASK;
-	else if (mux == FSR_SRC_FSX)
-		v |= OMAP2_MCBSP1_FSR_MASK;
 	omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
+
+	return 0;
 }
-EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src);
 
 /* McBSP CLKS source switching function */
-
-int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
+static int omap2_mcbsp_set_clk_src(struct device *dev, struct clk *clk,
+				   const char *src)
 {
-	struct omap_mcbsp *mcbsp;
 	struct clk *fck_src;
 	char *fck_src_name;
 	int r;
 
-	if (!omap_mcbsp_check_valid_id(id)) {
-		pr_err("%s: Invalid id (%d)\n", __func__, id + 1);
-		return -EINVAL;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
-	if (fck_src_id == MCBSP_CLKS_PAD_SRC)
+	if (!strcmp(src, "clks_ext"))
 		fck_src_name = "pad_fck";
-	else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
+	else if (!strcmp(src, "clks_fclk"))
 		fck_src_name = "prcm_fck";
 	else
 		return -EINVAL;
 
-	fck_src = clk_get(mcbsp->dev, fck_src_name);
+	fck_src = clk_get(dev, fck_src_name);
 	if (IS_ERR_OR_NULL(fck_src)) {
 		pr_err("omap-mcbsp: %s: could not clk_get() %s\n", "clks",
 		       fck_src_name);
 		return -EINVAL;
 	}
 
-	pm_runtime_put_sync(mcbsp->dev);
+	pm_runtime_put_sync(dev);
 
-	r = clk_set_parent(mcbsp->fclk, fck_src);
+	r = clk_set_parent(clk, fck_src);
 	if (IS_ERR_VALUE(r)) {
 		pr_err("omap-mcbsp: %s: could not clk_set_parent() to %s\n",
 		       "clks", fck_src_name);
@@ -94,21 +97,30 @@
 		return -EINVAL;
 	}
 
-	pm_runtime_get_sync(mcbsp->dev);
+	pm_runtime_get_sync(dev);
 
 	clk_put(fck_src);
 
 	return 0;
 }
-EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
 
-struct omap_device_pm_latency omap2_mcbsp_latency[] = {
-	{
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
+static int omap3_enable_st_clock(unsigned int id, bool enable)
+{
+	unsigned int w;
+
+	/*
+	 * Sidetone uses McBSP ICLK - which must not idle when sidetones
+	 * are enabled or sidetones start sounding ugly.
+	 */
+	w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
+	if (enable)
+		w &= ~(1 << (id - 2));
+	else
+		w |= 1 << (id - 2);
+	omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
+
+	return 0;
+}
 
 static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 {
@@ -116,7 +128,7 @@
 	char *name = "omap-mcbsp";
 	struct omap_hwmod *oh_device[2];
 	struct omap_mcbsp_platform_data *pdata = NULL;
-	struct omap_device *od;
+	struct platform_device *pdev;
 
 	sscanf(oh->name, "mcbsp%d", &id);
 
@@ -126,7 +138,16 @@
 		return -ENOMEM;
 	}
 
-	pdata->mcbsp_config_type = oh->class->rev;
+	pdata->reg_step = 4;
+	if (oh->class->rev < MCBSP_CONFIG_TYPE2) {
+		pdata->reg_size = 2;
+	} else {
+		pdata->reg_size = 4;
+		pdata->has_ccr = true;
+	}
+	pdata->set_clk_src = omap2_mcbsp_set_clk_src;
+	if (id == 1)
+		pdata->mux_signal = omap2_mcbsp1_mux_rx_clk;
 
 	if (oh->class->rev == MCBSP_CONFIG_TYPE3) {
 		if (id == 2)
@@ -137,21 +158,24 @@
 			pdata->buffer_size = 0x80;
 	}
 
+	if (oh->class->rev >= MCBSP_CONFIG_TYPE3)
+		pdata->has_wakeup = true;
+
 	oh_device[0] = oh;
 
 	if (oh->dev_attr) {
 		oh_device[1] = omap_hwmod_lookup((
 		(struct omap_mcbsp_dev_attr *)(oh->dev_attr))->sidetone);
+		pdata->enable_st_clock = omap3_enable_st_clock;
 		count++;
 	}
-	od = omap_device_build_ss(name, id, oh_device, count, pdata,
-				sizeof(*pdata), omap2_mcbsp_latency,
-				ARRAY_SIZE(omap2_mcbsp_latency), false);
+	pdev = omap_device_build_ss(name, id, oh_device, count, pdata,
+				sizeof(*pdata), NULL, 0, false);
 	kfree(pdata);
-	if (IS_ERR(od))  {
+	if (IS_ERR(pdev))  {
 		pr_err("%s: Can't build omap_device for %s:%s.\n", __func__,
 					name, oh->name);
-		return PTR_ERR(od);
+		return PTR_ERR(pdev);
 	}
 	omap_mcbsp_count++;
 	return 0;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_hwmod_2420_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_hwmod_2420_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_hwmod_2420_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_hwmod_2420_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -100,7 +100,6 @@
 	.masters_cnt	= ARRAY_SIZE(omap2420_l3_main_masters),
 	.slaves		= omap2420_l3_main_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_l3_main_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -206,7 +205,6 @@
 	.masters_cnt	= ARRAY_SIZE(omap2420_l4_core_masters),
 	.slaves		= omap2420_l4_core_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_l4_core_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -227,7 +225,6 @@
 	.masters_cnt	= ARRAY_SIZE(omap2420_l4_wkup_masters),
 	.slaves		= omap2420_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_l4_wkup_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -243,7 +240,6 @@
 	.main_clk	= "mpu_ck",
 	.masters	= omap2420_mpu_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2420_mpu_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /*
@@ -271,7 +267,16 @@
 	.class		= &iva_hwmod_class,
 	.masters	= omap2420_iva_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2420_iva_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability       = OMAP_TIMER_HAS_PWM,
 };
 
 /* timer1 */
@@ -314,10 +319,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer1_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer2 */
@@ -351,10 +356,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer2_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer3 */
@@ -388,10 +393,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer3_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer4 */
@@ -425,10 +430,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer4_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer5 */
@@ -462,10 +467,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer5_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 
@@ -500,10 +505,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer6_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer7 */
@@ -537,10 +542,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer7_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer8 */
@@ -574,10 +579,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer8_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer9 */
@@ -611,10 +616,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer9_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer10 */
@@ -648,10 +653,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer10_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer11 */
@@ -685,10 +690,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer11_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer12 */
@@ -722,10 +727,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer12_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer12_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* l4_wkup -> wd_timer2 */
@@ -766,7 +771,6 @@
 	},
 	.slaves		= omap2420_wd_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_wd_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* UART1 */
@@ -792,7 +796,6 @@
 	.slaves		= omap2420_uart1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_uart1_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* UART2 */
@@ -818,7 +821,6 @@
 	.slaves		= omap2420_uart2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_uart2_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* UART3 */
@@ -844,7 +846,6 @@
 	.slaves		= omap2420_uart3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_uart3_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* dss */
@@ -874,6 +875,10 @@
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+	/*
+	 * The DSS HW needs all DSS clocks enabled during reset. The dss_core
+	 * driver does not use these clocks.
+	 */
 	{ .role = "tv_clk", .clk = "dss_54m_fck" },
 	{ .role = "sys_clk", .clk = "dss2_fck" },
 };
@@ -898,8 +903,7 @@
 	.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,
+	.flags		= HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 };
 
 /* l4_core -> dss_dispc */
@@ -938,8 +942,8 @@
 	},
 	.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,
+	.dev_attr	= &omap2_3_dss_dispc_dev_attr
 };
 
 /* l4_core -> dss_rfbi */
@@ -962,6 +966,10 @@
 	&omap2420_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
+	{ .role = "ick", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap2_rfbi_hwmod_class,
@@ -973,9 +981,10 @@
 			.module_offs = CORE_MOD,
 		},
 	},
+	.opt_clks	= dss_rfbi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_rfbi_opt_clks),
 	.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,
 };
 
@@ -983,7 +992,7 @@
 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",
+	.clk		= "dss_ick",
 	.addr		= omap2_dss_venc_addrs,
 	.fw = {
 		.omap2 = {
@@ -1003,7 +1012,7 @@
 static struct omap_hwmod omap2420_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap2_venc_hwmod_class,
-	.main_clk	= "dss1_fck",
+	.main_clk	= "dss_54m_fck",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
@@ -1013,7 +1022,6 @@
 	},
 	.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,
 };
 
@@ -1064,7 +1072,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2420_i2c1_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_16BIT_REG,
 };
 
@@ -1092,7 +1099,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2420_i2c2_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_16BIT_REG,
 };
 
@@ -1197,7 +1203,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio1_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* gpio2 */
@@ -1223,7 +1228,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio2_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* gpio3 */
@@ -1249,7 +1253,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio3_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* gpio4 */
@@ -1275,7 +1278,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio4_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* dma attributes */
@@ -1322,7 +1324,6 @@
 	.masters	= omap2420_dma_system_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2420_dma_system_masters),
 	.dev_attr	= &dma_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1363,7 +1364,6 @@
 	},
 	.slaves		= omap2420_mailbox_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mailbox_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* mcspi1 */
@@ -1393,7 +1393,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mcspi1_slaves),
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi1_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* mcspi2 */
@@ -1423,7 +1422,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mcspi2_slaves),
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi2_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /*
@@ -1473,7 +1471,6 @@
 	},
 	.slaves		= omap2420_mcbsp1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mcbsp1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* mcbsp2 */
@@ -1514,7 +1511,6 @@
 	},
 	.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[] = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_hwmod_2430_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_hwmod_2430_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_hwmod_2430_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_hwmod_2430_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -110,7 +110,6 @@
 	.masters_cnt	= ARRAY_SIZE(omap2430_l3_main_masters),
 	.slaves		= omap2430_l3_main_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_l3_main_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -250,7 +249,6 @@
 	.masters_cnt	= ARRAY_SIZE(omap2430_l4_core_masters),
 	.slaves		= omap2430_l4_core_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_l4_core_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -301,7 +299,6 @@
 	.masters_cnt	= ARRAY_SIZE(omap2430_l4_wkup_masters),
 	.slaves		= omap2430_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_l4_wkup_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -317,7 +314,6 @@
 	.main_clk	= "mpu_ck",
 	.masters	= omap2430_mpu_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2430_mpu_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /*
@@ -345,7 +341,16 @@
 	.class		= &iva_hwmod_class,
 	.masters	= omap2430_iva_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2430_iva_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability       = OMAP_TIMER_HAS_PWM,
 };
 
 /* timer1 */
@@ -388,10 +393,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer1_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer2 */
@@ -425,10 +430,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer2_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer3 */
@@ -462,10 +467,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer3_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer4 */
@@ -499,10 +504,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer4_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer5 */
@@ -536,10 +541,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer5_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer6 */
@@ -573,10 +578,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer6_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer7 */
@@ -610,10 +615,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer7_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer8 */
@@ -647,10 +652,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer8_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer9 */
@@ -684,10 +689,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer9_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer10 */
@@ -721,10 +726,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer10_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer11 */
@@ -758,10 +763,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer11_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer12 */
@@ -795,10 +800,10 @@
 			.idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer12_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer12_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* l4_wkup -> wd_timer2 */
@@ -839,7 +844,6 @@
 	},
 	.slaves		= omap2430_wd_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_wd_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* UART1 */
@@ -865,7 +869,6 @@
 	.slaves		= omap2430_uart1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_uart1_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* UART2 */
@@ -891,7 +894,6 @@
 	.slaves		= omap2430_uart2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_uart2_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* UART3 */
@@ -917,7 +919,6 @@
 	.slaves		= omap2430_uart3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_uart3_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* dss */
@@ -941,6 +942,10 @@
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+	/*
+	 * The DSS HW needs all DSS clocks enabled during reset. The dss_core
+	 * driver does not use these clocks.
+	 */
 	{ .role = "tv_clk", .clk = "dss_54m_fck" },
 	{ .role = "sys_clk", .clk = "dss2_fck" },
 };
@@ -965,8 +970,7 @@
 	.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,
+	.flags		= HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 };
 
 /* l4_core -> dss_dispc */
@@ -999,8 +1003,8 @@
 	},
 	.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,
+	.dev_attr	= &omap2_3_dss_dispc_dev_attr
 };
 
 /* l4_core -> dss_rfbi */
@@ -1017,6 +1021,10 @@
 	&omap2430_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
+	{ .role = "ick", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap2_rfbi_hwmod_class,
@@ -1028,9 +1036,10 @@
 			.module_offs = CORE_MOD,
 		},
 	},
+	.opt_clks	= dss_rfbi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_rfbi_opt_clks),
 	.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,
 };
 
@@ -1038,7 +1047,7 @@
 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",
+	.clk		= "dss_ick",
 	.addr		= omap2_dss_venc_addrs,
 	.flags		= OCPIF_SWSUP_IDLE,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
@@ -1052,7 +1061,7 @@
 static struct omap_hwmod omap2430_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap2_venc_hwmod_class,
-	.main_clk	= "dss1_fck",
+	.main_clk	= "dss_54m_fck",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
@@ -1062,7 +1071,6 @@
 	},
 	.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,
 };
 
@@ -1123,7 +1131,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2430_i2c1_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* I2C2 */
@@ -1151,7 +1158,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2430_i2c2_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* l4_wkup -> gpio1 */
@@ -1273,7 +1279,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio1_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* gpio2 */
@@ -1299,7 +1304,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio2_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* gpio3 */
@@ -1325,7 +1329,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio3_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* gpio4 */
@@ -1351,7 +1354,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio4_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* gpio5 */
@@ -1382,7 +1384,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio5_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* dma attributes */
@@ -1429,7 +1430,6 @@
 	.masters	= omap2430_dma_system_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2430_dma_system_masters),
 	.dev_attr	= &dma_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1469,7 +1469,6 @@
 	},
 	.slaves		= omap2430_mailbox_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mailbox_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcspi1 */
@@ -1499,7 +1498,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi1_slaves),
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi1_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcspi2 */
@@ -1529,7 +1527,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi2_slaves),
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi2_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcspi3 */
@@ -1572,7 +1569,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi3_slaves),
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi3_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /*
@@ -1628,7 +1624,6 @@
 	 */
 	.flags		= HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE
 				| HWMOD_SWSUP_MSTANDBY,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /*
@@ -1689,7 +1684,6 @@
 	},
 	.slaves		= omap2430_mcbsp1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcbsp2 */
@@ -1731,7 +1725,6 @@
 	},
 	.slaves		= omap2430_mcbsp2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcbsp3 */
@@ -1783,7 +1776,6 @@
 	},
 	.slaves		= omap2430_mcbsp3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcbsp4 */
@@ -1841,7 +1833,6 @@
 	},
 	.slaves		= omap2430_mcbsp4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcbsp5 */
@@ -1899,7 +1890,6 @@
 	},
 	.slaves		= omap2430_mcbsp5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp5_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* MMC/SD/SDIO common */
@@ -1966,7 +1956,6 @@
 	.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 */
@@ -2010,7 +1999,6 @@
 	.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[] = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <plat/omap_hwmod.h>
 #include <plat/serial.h>
 #include <plat/dma.h>
+#include <plat/common.h>
 
 #include <mach/irqs.h>
 
@@ -43,13 +44,15 @@
 	.rev_offs	= 0x0000,
 	.sysc_offs	= 0x0010,
 	.syss_offs	= 0x0014,
-	.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,
 };
 
 struct omap_hwmod_class omap2_dss_hwmod_class = {
 	.name	= "dss",
 	.sysc	= &omap2_dss_sysc,
+	.reset	= omap_dss_reset,
 };
 
 /*
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -156,7 +156,6 @@
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_l3_main_masters),
 	.slaves		= omap3xxx_l3_main_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l3_main_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -459,7 +458,6 @@
 	.class		= &l4_hwmod_class,
 	.slaves		= omap3xxx_l4_core_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_core_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -474,7 +472,6 @@
 	.class		= &l4_hwmod_class,
 	.slaves		= omap3xxx_l4_per_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_per_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -489,7 +486,6 @@
 	.class		= &l4_hwmod_class,
 	.slaves		= omap3xxx_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_wkup_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -505,7 +501,6 @@
 	.main_clk	= "arm_fck",
 	.masters	= omap3xxx_mpu_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_mpu_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /*
@@ -533,7 +528,6 @@
 	.class		= &iva_hwmod_class,
 	.masters	= omap3xxx_iva_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_iva_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer class */
@@ -570,6 +564,21 @@
 	.rev =  OMAP_TIMER_IP_VERSION_1,
 };
 
+/* secure timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_secure_dev_attr = {
+	.timer_capability       = OMAP_TIMER_SECURE,
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability       = OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap3xxx_timer1_hwmod;
 
@@ -610,10 +619,10 @@
 			.idlest_idle_bit = OMAP3430_ST_GPT1_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.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 */
@@ -656,10 +665,10 @@
 			.idlest_idle_bit = OMAP3430_ST_GPT2_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.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 */
@@ -702,10 +711,10 @@
 			.idlest_idle_bit = OMAP3430_ST_GPT3_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.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 */
@@ -748,10 +757,10 @@
 			.idlest_idle_bit = OMAP3430_ST_GPT4_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.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 */
@@ -794,10 +803,10 @@
 			.idlest_idle_bit = OMAP3430_ST_GPT5_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.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 */
@@ -840,10 +849,10 @@
 			.idlest_idle_bit = OMAP3430_ST_GPT6_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.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 */
@@ -886,10 +895,10 @@
 			.idlest_idle_bit = OMAP3430_ST_GPT7_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.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 */
@@ -932,10 +941,10 @@
 			.idlest_idle_bit = OMAP3430_ST_GPT8_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.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 */
@@ -978,10 +987,10 @@
 			.idlest_idle_bit = OMAP3430_ST_GPT9_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.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 */
@@ -1015,10 +1024,10 @@
 			.idlest_idle_bit = OMAP3430_ST_GPT10_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.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 */
@@ -1052,10 +1061,10 @@
 			.idlest_idle_bit = OMAP3430_ST_GPT11_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.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*/
@@ -1102,10 +1111,10 @@
 			.idlest_idle_bit = OMAP3430_ST_GPT12_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_secure_dev_attr,
 	.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 */
@@ -1182,7 +1191,6 @@
 	},
 	.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?
@@ -1213,7 +1221,6 @@
 	.slaves		= omap3xxx_uart1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart1_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* UART2 */
@@ -1239,7 +1246,6 @@
 	.slaves		= omap3xxx_uart2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart2_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* UART3 */
@@ -1265,7 +1271,6 @@
 	.slaves		= omap3xxx_uart3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart3_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* UART4 */
@@ -1302,7 +1307,6 @@
 	.slaves		= omap3xxx_uart4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart4_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
 };
 
 static struct omap_hwmod_class i2c_class = {
@@ -1365,9 +1369,14 @@
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
-	{ .role = "tv_clk", .clk = "dss_tv_fck" },
-	{ .role = "video_clk", .clk = "dss_96m_fck" },
+	/*
+	 * The DSS HW needs all DSS clocks enabled during reset. The dss_core
+	 * driver does not use these clocks.
+	 */
 	{ .role = "sys_clk", .clk = "dss2_alwon_fck" },
+	{ .role = "tv_clk", .clk = "dss_tv_fck" },
+	/* required only on OMAP3430 */
+	{ .role = "tv_dac_clk", .clk = "dss_96m_fck" },
 };
 
 static struct omap_hwmod omap3430es1_dss_core_hwmod = {
@@ -1390,12 +1399,12 @@
 	.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,
+	.flags		= HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 };
 
 static struct omap_hwmod omap3xxx_dss_core_hwmod = {
 	.name		= "dss_core",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.class		= &omap2_dss_hwmod_class,
 	.main_clk	= "dss1_alwon_fck", /* instead of dss_fck */
 	.sdma_reqs	= omap3xxx_dss_sdma_chs,
@@ -1415,8 +1424,6 @@
 	.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),
 };
 
 /* l4_core -> dss_dispc */
@@ -1454,10 +1461,8 @@
 	},
 	.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,
+	.dev_attr	= &omap2_3_dss_dispc_dev_attr
 };
 
 /*
@@ -1488,6 +1493,7 @@
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dsi1 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_dss_dsi1_hwmod,
+	.clk		= "dss_ick",
 	.addr		= omap3xxx_dss_dsi1_addrs,
 	.fw = {
 		.omap2 = {
@@ -1504,6 +1510,10 @@
 	&omap3xxx_l4_core__dss_dsi1,
 };
 
+static struct omap_hwmod_opt_clk dss_dsi1_opt_clks[] = {
+	{ .role = "sys_clk", .clk = "dss2_alwon_fck" },
+};
+
 static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
 	.name		= "dss_dsi1",
 	.class		= &omap3xxx_dsi_hwmod_class,
@@ -1516,11 +1526,10 @@
 			.module_offs = OMAP3430_DSS_MOD,
 		},
 	},
+	.opt_clks	= dss_dsi1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_dsi1_opt_clks),
 	.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,
 };
 
@@ -1545,6 +1554,10 @@
 	&omap3xxx_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
+	{ .role = "ick", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap2_rfbi_hwmod_class,
@@ -1556,11 +1569,10 @@
 			.module_offs = OMAP3430_DSS_MOD,
 		},
 	},
+	.opt_clks	= dss_rfbi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_rfbi_opt_clks),
 	.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,
 };
 
@@ -1568,7 +1580,7 @@
 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",
+	.clk		= "dss_ick",
 	.addr		= omap2_dss_venc_addrs,
 	.fw = {
 		.omap2 = {
@@ -1586,10 +1598,15 @@
 	&omap3xxx_l4_core__dss_venc,
 };
 
+static struct omap_hwmod_opt_clk dss_venc_opt_clks[] = {
+	/* required only on OMAP3430 */
+	{ .role = "tv_dac_clk", .clk = "dss_96m_fck" },
+};
+
 static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap2_venc_hwmod_class,
-	.main_clk	= "dss1_alwon_fck",
+	.main_clk	= "dss_tv_fck",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
@@ -1597,11 +1614,10 @@
 			.module_offs = OMAP3430_DSS_MOD,
 		},
 	},
+	.opt_clks	= dss_venc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_venc_opt_clks),
 	.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,
 };
 
@@ -1637,7 +1653,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c1_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c1_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* I2C2 */
@@ -1672,7 +1687,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c2_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c2_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* I2C3 */
@@ -1718,7 +1732,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c3_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c3_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* l4_wkup -> gpio1 */
@@ -1880,7 +1893,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio1_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* gpio2 */
@@ -1912,7 +1924,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio2_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* gpio3 */
@@ -1944,7 +1955,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio3_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* gpio4 */
@@ -1976,7 +1986,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio4_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* gpio5 */
@@ -2013,7 +2022,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio5_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* gpio6 */
@@ -2050,7 +2058,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio6_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* dma_system -> L3 */
@@ -2134,7 +2141,6 @@
 	.masters	= omap3xxx_dma_system_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_dma_system_masters),
 	.dev_attr	= &dma_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -2207,7 +2213,6 @@
 	},
 	.slaves		= omap3xxx_mcbsp1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcbsp2 */
@@ -2264,7 +2269,6 @@
 	.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 */
@@ -2321,7 +2325,6 @@
 	.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 */
@@ -2379,7 +2382,6 @@
 	},
 	.slaves		= omap3xxx_mcbsp4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcbsp5 */
@@ -2437,7 +2439,6 @@
 	},
 	.slaves		= omap3xxx_mcbsp5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp5_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 /* 'mcbsp sidetone' class */
 
@@ -2498,7 +2499,6 @@
 	},
 	.slaves		= omap3xxx_mcbsp2_sidetone_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcbsp3_sidetone */
@@ -2547,7 +2547,6 @@
 	},
 	.slaves		= omap3xxx_mcbsp3_sidetone_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 
@@ -2597,7 +2596,7 @@
 	.name		= "sr1_hwmod",
 	.class		= &omap34xx_smartreflex_hwmod_class,
 	.main_clk	= "sr1_fck",
-	.vdd_name	= "mpu",
+	.vdd_name	= "mpu_iva",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
@@ -2609,9 +2608,6 @@
 	},
 	.slaves		= omap3_sr1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3_sr1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 |
-					CHIP_IS_OMAP3430ES3_0 |
-					CHIP_IS_OMAP3430ES3_1),
 	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
@@ -2619,7 +2615,7 @@
 	.name		= "sr1_hwmod",
 	.class		= &omap36xx_smartreflex_hwmod_class,
 	.main_clk	= "sr1_fck",
-	.vdd_name	= "mpu",
+	.vdd_name	= "mpu_iva",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
@@ -2631,7 +2627,6 @@
 	},
 	.slaves		= omap3_sr1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3_sr1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
 };
 
 /* SR2 */
@@ -2655,9 +2650,6 @@
 	},
 	.slaves		= omap3_sr2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3_sr2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 |
-					CHIP_IS_OMAP3430ES3_0 |
-					CHIP_IS_OMAP3430ES3_1),
 	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
@@ -2677,7 +2669,6 @@
 	},
 	.slaves		= omap3_sr2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3_sr2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
 };
 
 /*
@@ -2745,7 +2736,6 @@
 	},
 	.slaves		= omap3xxx_mailbox_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mailbox_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* l4 core -> mcspi1 interface */
@@ -2843,7 +2833,6 @@
 	.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 */
@@ -2873,7 +2862,6 @@
 	.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 */
@@ -2916,7 +2904,6 @@
 	.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 */
@@ -2957,7 +2944,6 @@
 	.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),
 };
 
 /*
@@ -3014,7 +3000,6 @@
 	 */
 	.flags		= HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE
 				| HWMOD_SWSUP_MSTANDBY,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* usb_otg_hs */
@@ -3042,7 +3027,6 @@
 	.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 */
@@ -3108,7 +3092,6 @@
 	.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 */
@@ -3151,7 +3134,6 @@
 	.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 */
@@ -3193,7 +3175,6 @@
 	.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[] = {
@@ -3205,7 +3186,6 @@
 	&omap3xxx_mmc2_hwmod,
 	&omap3xxx_mmc3_hwmod,
 	&omap3xxx_mpu_hwmod,
-	&omap3xxx_iva_hwmod,
 
 	&omap3xxx_timer1_hwmod,
 	&omap3xxx_timer2_hwmod,
@@ -3224,10 +3204,7 @@
 	&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,
@@ -3237,11 +3214,6 @@
 	&omap3xxx_i2c1_hwmod,
 	&omap3xxx_i2c2_hwmod,
 	&omap3xxx_i2c3_hwmod,
-	&omap34xx_sr1_hwmod,
-	&omap34xx_sr2_hwmod,
-	&omap36xx_sr1_hwmod,
-	&omap36xx_sr2_hwmod,
-
 
 	/* gpio class */
 	&omap3xxx_gpio1_hwmod,
@@ -3263,8 +3235,6 @@
 	&omap3xxx_mcbsp2_sidetone_hwmod,
 	&omap3xxx_mcbsp3_sidetone_hwmod,
 
-	/* mailbox class */
-	&omap3xxx_mailbox_hwmod,
 
 	/* mcspi class */
 	&omap34xx_mcspi1,
@@ -3272,16 +3242,100 @@
 	&omap34xx_mcspi3,
 	&omap34xx_mcspi4,
 
-	/* usbotg class */
+	NULL,
+};
+
+/* 3430ES1-only hwmods */
+static __initdata struct omap_hwmod *omap3430es1_hwmods[] = {
+	&omap3430es1_dss_core_hwmod,
+	NULL
+};
+
+/* 3430ES2+-only hwmods */
+static __initdata struct omap_hwmod *omap3430es2plus_hwmods[] = {
+	&omap3xxx_dss_core_hwmod,
 	&omap3xxx_usbhsotg_hwmod,
+	NULL
+};
 
-	/* usbotg for am35x */
-	&am35xx_usbhsotg_hwmod,
+/* 34xx-only hwmods (all ES revisions) */
+static __initdata struct omap_hwmod *omap34xx_hwmods[] = {
+	&omap3xxx_iva_hwmod,
+	&omap34xx_sr1_hwmod,
+	&omap34xx_sr2_hwmod,
+	&omap3xxx_mailbox_hwmod,
+	NULL
+};
 
-	NULL,
+/* 36xx-only hwmods (all ES revisions) */
+static __initdata struct omap_hwmod *omap36xx_hwmods[] = {
+	&omap3xxx_iva_hwmod,
+	&omap3xxx_uart4_hwmod,
+	&omap3xxx_dss_core_hwmod,
+	&omap36xx_sr1_hwmod,
+	&omap36xx_sr2_hwmod,
+	&omap3xxx_usbhsotg_hwmod,
+	&omap3xxx_mailbox_hwmod,
+	NULL
+};
+
+static __initdata struct omap_hwmod *am35xx_hwmods[] = {
+	&omap3xxx_dss_core_hwmod, /* XXX ??? */
+	&am35xx_usbhsotg_hwmod,
+	NULL
 };
 
 int __init omap3xxx_hwmod_init(void)
 {
-	return omap_hwmod_register(omap3xxx_hwmods);
+	int r;
+	struct omap_hwmod **h = NULL;
+	unsigned int rev;
+
+	/* Register hwmods common to all OMAP3 */
+	r = omap_hwmod_register(omap3xxx_hwmods);
+	if (r < 0)
+		return r;
+
+	rev = omap_rev();
+
+	/*
+	 * Register hwmods common to individual OMAP3 families, all
+	 * silicon revisions (e.g., 34xx, or AM3505/3517, or 36xx)
+	 * All possible revisions should be included in this conditional.
+	 */
+	if (rev == OMAP3430_REV_ES1_0 || rev == OMAP3430_REV_ES2_0 ||
+	    rev == OMAP3430_REV_ES2_1 || rev == OMAP3430_REV_ES3_0 ||
+	    rev == OMAP3430_REV_ES3_1 || rev == OMAP3430_REV_ES3_1_2) {
+		h = omap34xx_hwmods;
+	} else if (rev == OMAP3517_REV_ES1_0 || rev == OMAP3517_REV_ES1_1) {
+		h = am35xx_hwmods;
+	} else if (rev == OMAP3630_REV_ES1_0 || rev == OMAP3630_REV_ES1_1 ||
+		   rev == OMAP3630_REV_ES1_2) {
+		h = omap36xx_hwmods;
+	} else {
+		WARN(1, "OMAP3 hwmod family init: unknown chip type\n");
+		return -EINVAL;
+	};
+
+	r = omap_hwmod_register(h);
+	if (r < 0)
+		return r;
+
+	/*
+	 * Register hwmods specific to certain ES levels of a
+	 * particular family of silicon (e.g., 34xx ES1.0)
+	 */
+	h = NULL;
+	if (rev == OMAP3430_REV_ES1_0) {
+		h = omap3430es1_hwmods;
+	} else if (rev == OMAP3430_REV_ES2_0 || rev == OMAP3430_REV_ES2_1 ||
+		   rev == OMAP3430_REV_ES3_0 || rev == OMAP3430_REV_ES3_1 ||
+		   rev == OMAP3430_REV_ES3_1_2) {
+		h = omap3430es2plus_hwmods;
+	};
+
+	if (h)
+		r = omap_hwmod_register(h);
+
+	return r;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_hwmod_44xx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_hwmod_44xx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_hwmod_44xx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,8 @@
 #include <plat/mcbsp.h>
 #include <plat/mmc.h>
 #include <plat/i2c.h>
+#include <plat/dmtimer.h>
+#include <plat/common.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -133,7 +135,6 @@
 	.slaves		= omap44xx_dmm_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dmm_slaves),
 	.mpu_irqs	= omap44xx_dmm_irqs,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -189,7 +190,6 @@
 	},
 	.slaves		= omap44xx_emif_fw_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_emif_fw_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -236,7 +236,6 @@
 	},
 	.slaves		= omap44xx_l3_instr_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_instr_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l3_main_1 */
@@ -336,7 +335,6 @@
 	},
 	.slaves		= omap44xx_l3_main_1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_main_1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l3_main_2 */
@@ -438,7 +436,6 @@
 	},
 	.slaves		= omap44xx_l3_main_2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_main_2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l3_main_3 */
@@ -496,7 +493,6 @@
 	},
 	.slaves		= omap44xx_l3_main_3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_main_3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -559,7 +555,6 @@
 	},
 	.slaves		= omap44xx_l4_abe_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_abe_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l4_cfg */
@@ -588,7 +583,6 @@
 	},
 	.slaves		= omap44xx_l4_cfg_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_cfg_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l4_per */
@@ -617,7 +611,6 @@
 	},
 	.slaves		= omap44xx_l4_per_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_per_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l4_wkup */
@@ -646,7 +639,6 @@
 	},
 	.slaves		= omap44xx_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_wkup_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -677,7 +669,6 @@
 	.clkdm_name	= "mpuss_clkdm",
 	.slaves		= omap44xx_mpu_private_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mpu_private_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -828,7 +819,6 @@
 	.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),
 };
 
 /*
@@ -856,7 +846,6 @@
 	},
 	.opt_clks	= bandgap_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(bandgap_opt_clks),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -917,7 +906,6 @@
 	},
 	.slaves		= omap44xx_counter_32k_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_counter_32k_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1005,7 +993,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dma_system_slaves),
 	.masters	= omap44xx_dma_system_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_dma_system_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1098,7 +1085,6 @@
 	},
 	.slaves		= omap44xx_dmic_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dmic_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1164,7 +1150,6 @@
 			.rstctrl_offs = OMAP4_RM_TESLA_RSTCTRL_OFFSET,
 		},
 	},
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct omap_hwmod omap44xx_dsp_hwmod = {
@@ -1187,7 +1172,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dsp_slaves),
 	.masters	= omap44xx_dsp_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_dsp_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1204,6 +1188,7 @@
 static struct omap_hwmod_class omap44xx_dss_hwmod_class = {
 	.name	= "dss",
 	.sysc	= &omap44xx_dss_sysc,
+	.reset	= omap_dss_reset,
 };
 
 /* dss */
@@ -1257,12 +1242,12 @@
 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" },
+	{ .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
 };
 
 static struct omap_hwmod omap44xx_dss_hwmod = {
 	.name		= "dss_core",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.class		= &omap44xx_dss_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
 	.main_clk	= "dss_dss_clk",
@@ -1278,7 +1263,6 @@
 	.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),
 };
 
 /*
@@ -1343,6 +1327,11 @@
 	{ }
 };
 
+static struct omap_dss_dispc_dev_attr omap44xx_dss_dispc_dev_attr = {
+	.manager_count		= 3,
+	.has_framedonetv_irq	= 1
+};
+
 /* l4_per -> dss_dispc */
 static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dispc = {
 	.master		= &omap44xx_l4_per_hwmod,
@@ -1358,12 +1347,6 @@
 	&omap44xx_l4_per__dss_dispc,
 };
 
-static struct omap_hwmod_opt_clk dss_dispc_opt_clks[] = {
-	{ .role = "sys_clk", .clk = "dss_sys_clk" },
-	{ .role = "tv_clk", .clk = "dss_tv_clk" },
-	{ .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
-};
-
 static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap44xx_dispc_hwmod_class,
@@ -1377,11 +1360,9 @@
 			.context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
 		},
 	},
-	.opt_clks	= dss_dispc_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(dss_dispc_opt_clks),
 	.slaves		= omap44xx_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+	.dev_attr	= &omap44xx_dss_dispc_dev_attr
 };
 
 /*
@@ -1480,7 +1461,6 @@
 	.opt_clks_cnt	= ARRAY_SIZE(dss_dsi1_opt_clks),
 	.slaves		= omap44xx_dss_dsi1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* dss_dsi2 */
@@ -1558,7 +1538,6 @@
 	.opt_clks_cnt	= ARRAY_SIZE(dss_dsi2_opt_clks),
 	.slaves		= omap44xx_dss_dsi2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1645,7 +1624,7 @@
 	.clkdm_name	= "l3_dss_clkdm",
 	.mpu_irqs	= omap44xx_dss_hdmi_irqs,
 	.sdma_reqs	= omap44xx_dss_hdmi_sdma_reqs,
-	.main_clk	= "dss_dss_clk",
+	.main_clk	= "dss_48mhz_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
@@ -1656,7 +1635,6 @@
 	.opt_clks_cnt	= ARRAY_SIZE(dss_hdmi_opt_clks),
 	.slaves		= omap44xx_dss_hdmi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1748,7 +1726,6 @@
 	.opt_clks_cnt	= ARRAY_SIZE(dss_rfbi_opt_clks),
 	.slaves		= omap44xx_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1808,7 +1785,7 @@
 	.name		= "dss_venc",
 	.class		= &omap44xx_venc_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
-	.main_clk	= "dss_dss_clk",
+	.main_clk	= "dss_tv_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
@@ -1817,7 +1794,6 @@
 	},
 	.slaves		= omap44xx_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_venc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1901,7 +1877,6 @@
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* gpio2 */
@@ -1957,7 +1932,6 @@
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* gpio3 */
@@ -2013,7 +1987,6 @@
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* gpio4 */
@@ -2069,7 +2042,6 @@
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* gpio5 */
@@ -2125,7 +2097,6 @@
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio5_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* gpio6 */
@@ -2181,7 +2152,6 @@
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio6_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2261,7 +2231,6 @@
 	.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),
 };
 
 /*
@@ -2345,7 +2314,6 @@
 	.slaves		= omap44xx_i2c1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c1_slaves),
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* i2c2 */
@@ -2402,7 +2370,6 @@
 	.slaves		= omap44xx_i2c2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c2_slaves),
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* i2c3 */
@@ -2459,7 +2426,6 @@
 	.slaves		= omap44xx_i2c3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c3_slaves),
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* i2c4 */
@@ -2516,7 +2482,6 @@
 	.slaves		= omap44xx_i2c4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c4_slaves),
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2577,7 +2542,6 @@
 			.rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
 		},
 	},
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* Pseudo hwmod for reset control purpose only */
@@ -2593,7 +2557,6 @@
 			.rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
 		},
 	},
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct omap_hwmod omap44xx_ipu_hwmod = {
@@ -2616,7 +2579,6 @@
 	.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),
 };
 
 /*
@@ -2706,7 +2668,6 @@
 	.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),
 };
 
 /*
@@ -2781,7 +2742,6 @@
 			.rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
 		},
 	},
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* Pseudo hwmod for reset control purpose only */
@@ -2797,7 +2757,6 @@
 			.rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
 		},
 	},
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct omap_hwmod omap44xx_iva_hwmod = {
@@ -2820,7 +2779,6 @@
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_iva_slaves),
 	.masters	= omap44xx_iva_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_iva_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2890,7 +2848,6 @@
 	},
 	.slaves		= omap44xx_kbd_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_kbd_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2956,7 +2913,6 @@
 	},
 	.slaves		= omap44xx_mailbox_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mailbox_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -3051,7 +3007,6 @@
 	},
 	.slaves		= omap44xx_mcbsp1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mcbsp2 */
@@ -3127,7 +3082,6 @@
 	},
 	.slaves		= omap44xx_mcbsp2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mcbsp3 */
@@ -3203,7 +3157,6 @@
 	},
 	.slaves		= omap44xx_mcbsp3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mcbsp4 */
@@ -3258,7 +3211,6 @@
 	},
 	.slaves		= omap44xx_mcbsp4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -3353,7 +3305,6 @@
 	},
 	.slaves		= omap44xx_mcpdm_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcpdm_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -3442,7 +3393,6 @@
 	.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 */
@@ -3505,7 +3455,6 @@
 	.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 */
@@ -3568,7 +3517,6 @@
 	.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 */
@@ -3629,7 +3577,6 @@
 	.dev_attr	= &mcspi4_dev_attr,
 	.slaves		= omap44xx_mcspi4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -3718,7 +3665,6 @@
 	.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 */
@@ -3779,7 +3725,6 @@
 	.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 */
@@ -3834,7 +3779,6 @@
 	},
 	.slaves		= omap44xx_mmc3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mmc4 */
@@ -3890,7 +3834,6 @@
 	},
 	.slaves		= omap44xx_mmc4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mmc5 */
@@ -3945,7 +3888,6 @@
 	},
 	.slaves		= omap44xx_mmc5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc5_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -3987,7 +3929,6 @@
 	},
 	.masters	= omap44xx_mpu_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_mpu_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -4063,7 +4004,6 @@
 	},
 	.slaves		= omap44xx_smartreflex_core_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_core_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* smartreflex_iva */
@@ -4112,7 +4052,6 @@
 	},
 	.slaves		= omap44xx_smartreflex_iva_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_iva_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* smartreflex_mpu */
@@ -4161,7 +4100,6 @@
 	},
 	.slaves		= omap44xx_smartreflex_mpu_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_mpu_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -4224,7 +4162,6 @@
 	},
 	.slaves		= omap44xx_spinlock_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_spinlock_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -4265,6 +4202,16 @@
 	.sysc	= &omap44xx_timer_sysc,
 };
 
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability	= OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability	= OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap44xx_timer1_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer1_irqs[] = {
@@ -4308,9 +4255,9 @@
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer2 */
@@ -4356,9 +4303,9 @@
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer3 */
@@ -4404,9 +4351,9 @@
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer4 */
@@ -4452,9 +4399,9 @@
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer5 */
@@ -4519,9 +4466,9 @@
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer5_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer6 */
@@ -4587,9 +4534,9 @@
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer6_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer7 */
@@ -4654,9 +4601,9 @@
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer7_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer8 */
@@ -4721,9 +4668,9 @@
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer8_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer9 */
@@ -4769,9 +4716,9 @@
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer9_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer10 */
@@ -4817,9 +4764,9 @@
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer10_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer11 */
@@ -4865,9 +4812,9 @@
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer11_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -4944,7 +4891,6 @@
 	},
 	.slaves		= omap44xx_uart1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_uart1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* uart2 */
@@ -4999,7 +4945,6 @@
 	},
 	.slaves		= omap44xx_uart2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_uart2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* uart3 */
@@ -5055,7 +5000,6 @@
 	},
 	.slaves		= omap44xx_uart3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_uart3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* uart4 */
@@ -5110,7 +5054,6 @@
 	},
 	.slaves		= omap44xx_uart4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_uart4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -5195,7 +5138,6 @@
 	.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),
 };
 
 /*
@@ -5266,7 +5208,6 @@
 	},
 	.slaves		= omap44xx_wd_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_wd_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* wd_timer3 */
@@ -5333,7 +5274,6 @@
 	},
 	.slaves		= omap44xx_wd_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
@@ -5430,7 +5370,7 @@
 	&omap44xx_mcbsp4_hwmod,
 
 	/* mcpdm class */
-/*	&omap44xx_mcpdm_hwmod, */
+	&omap44xx_mcpdm_hwmod,
 
 	/* mcspi class */
 	&omap44xx_mcspi1_hwmod,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_hwmod.c linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_hwmod.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_hwmod.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_hwmod.c	2012-01-04 18:55:44.000000000 -0500
@@ -749,7 +749,7 @@
 		ohii = &oh->mpu_irqs[i++];
 	} while (ohii->irq != -1);
 
-	return i;
+	return i-1;
 }
 
 /**
@@ -772,7 +772,7 @@
 		ohdi = &oh->sdma_reqs[i++];
 	} while (ohdi->dma_req != -1);
 
-	return i;
+	return i-1;
 }
 
 /**
@@ -795,7 +795,7 @@
 		mem = &os->addr[i++];
 	} while (mem->pa_start != mem->pa_end);
 
-	return i;
+	return i-1;
 }
 
 /**
@@ -1954,9 +1954,6 @@
 
 	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);
@@ -2628,7 +2625,7 @@
  * Returns the context loss count of the powerdomain assocated with @oh
  * upon success, or zero if no powerdomain exists for @oh.
  */
-u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
+int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
 {
 	struct powerdomain *pwrdm;
 	int ret = 0;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_hwmod_common_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_hwmod_common_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_hwmod_common_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_hwmod_common_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,3 +49,7 @@
 	.srst_shift	= SYSC_TYPE2_SOFTRESET_SHIFT,
 };
 
+struct omap_dss_dispc_dev_attr omap2_3_dss_dispc_dev_attr = {
+	.manager_count		= 2,
+	.has_framedonetv_irq	= 0
+};
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_hwmod_common_data.h linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_hwmod_common_data.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_hwmod_common_data.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_hwmod_common_data.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
 
 #include <plat/omap_hwmod.h>
 
+#include "display.h"
+
 /* Common address space across OMAP2xxx */
 extern struct omap_hwmod_addr_space omap2xxx_uart1_addr_space[];
 extern struct omap_hwmod_addr_space omap2xxx_uart2_addr_space[];
@@ -111,4 +113,6 @@
 extern struct omap_hwmod_class omap2xxx_mailbox_hwmod_class;
 extern struct omap_hwmod_class omap2xxx_mcspi_class;
 
+extern struct omap_dss_dispc_dev_attr omap2_3_dss_dispc_dev_attr;
+
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/omap-iommu.c linux-libre-3.2-gnu/arch/arm/mach-omap2/omap-iommu.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/omap-iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/omap-iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/module.h>
 #include <linux/platform_device.h>
 
 #include <plat/iommu.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_l3_noc.c linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_l3_noc.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_l3_noc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_l3_noc.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,25 +1,26 @@
 /*
-  * 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
-  */
+ * 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/module.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
@@ -55,12 +56,12 @@
 static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
 {
 
-	struct omap4_l3		*l3 = _l3;
-	int inttype, i, j;
+	struct omap4_l3 *l3 = _l3;
+	int inttype, i, k;
 	int err_src = 0;
-	u32 std_err_main_addr, std_err_main, err_reg;
-	u32 base, slave_addr, clear;
-	char *source_name;
+	u32 std_err_main, err_reg, clear, masterid;
+	void __iomem *base, *l3_targ_base;
+	char *target_name, *master_name = "UN IDENTIFIED";
 
 	/* Get the Type of interrupt */
 	inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
@@ -70,43 +71,50 @@
 		 * 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));
+		base = l3->l3_base[i];
+		err_reg = __raw_readl(base + l3_flagmux[i] +
+					+ L3_FLAGMUX_REGERR0 + (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 = __ffs(err_reg);
 
-			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);
+			l3_targ_base = base + *(l3_targ[i] + err_src);
+			std_err_main =  __raw_readl(l3_targ_base +
+					L3_TARG_STDERRLOG_MAIN);
+			masterid = __raw_readl(l3_targ_base +
+					L3_TARG_STDERRLOG_MSTADDR);
 
 			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));
+				target_name =
+					l3_targ_inst_name[i][err_src];
+				WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
+					target_name,
+					__raw_readl(l3_targ_base +
+						L3_TARG_STDERRLOG_SLVOFSLSB));
 				/* clear the std error log*/
 				clear = std_err_main | CLEAR_STDERR_LOG;
-				writel(clear, std_err_main_addr);
+				writel(clear, l3_targ_base +
+					L3_TARG_STDERRLOG_MAIN);
 				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);
+				target_name =
+					l3_targ_inst_name[i][err_src];
+				for (k = 0; k < NUM_OF_L3_MASTERS; k++) {
+					if (masterid == l3_masters[k].id)
+						master_name =
+							l3_masters[k].name;
+				}
+				WARN(true, "L3 custom error: MASTER:%s TARGET:%s\n",
+					master_name, target_name);
 				/* clear the std error log*/
 				clear = std_err_main | CLEAR_STDERR_LOG;
-				writel(clear, std_err_main_addr);
+				writel(clear, l3_targ_base +
+					L3_TARG_STDERRLOG_MAIN);
 				break;
 
 			default:
@@ -120,12 +128,11 @@
 	return IRQ_HANDLED;
 }
 
-static int __init omap4_l3_probe(struct platform_device *pdev)
+static int __devinit omap4_l3_probe(struct platform_device *pdev)
 {
-	static struct omap4_l3		*l3;
-	struct resource		*res;
-	int			ret;
-	int			irq;
+	static struct omap4_l3 *l3;
+	struct resource	*res;
+	int ret;
 
 	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
 	if (!l3)
@@ -177,27 +184,25 @@
 	/*
 	 * Setup interrupt Handlers
 	 */
-	irq = platform_get_irq(pdev, 0);
-	ret = request_irq(irq,
+	l3->debug_irq = platform_get_irq(pdev, 0);
+	ret = request_irq(l3->debug_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);
+						OMAP44XX_IRQ_L3_DBG);
 		goto err3;
 	}
-	l3->debug_irq = irq;
 
-	irq = platform_get_irq(pdev, 1);
-	ret = request_irq(irq,
+	l3->app_irq = platform_get_irq(pdev, 1);
+	ret = request_irq(l3->app_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);
+						OMAP44XX_IRQ_L3_APP);
 		goto err4;
 	}
-	l3->app_irq = irq;
 
 	return 0;
 
@@ -214,9 +219,9 @@
 	return ret;
 }
 
-static int __exit omap4_l3_remove(struct platform_device *pdev)
+static int __devexit omap4_l3_remove(struct platform_device *pdev)
 {
-	struct omap4_l3         *l3 = platform_get_drvdata(pdev);
+	struct omap4_l3 *l3 = platform_get_drvdata(pdev);
 
 	free_irq(l3->app_irq, l3);
 	free_irq(l3->debug_irq, l3);
@@ -228,16 +233,29 @@
 	return 0;
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id l3_noc_match[] = {
+	{.compatible = "ti,omap4-l3-noc", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, l3_noc_match);
+#else
+#define l3_noc_match NULL
+#endif
+
 static struct platform_driver omap4_l3_driver = {
-	.remove		= __exit_p(omap4_l3_remove),
+	.probe		= omap4_l3_probe,
+	.remove		= __devexit_p(omap4_l3_remove),
 	.driver		= {
-	.name		= "omap_l3_noc",
+		.name		= "omap_l3_noc",
+		.owner		= THIS_MODULE,
+		.of_match_table = l3_noc_match,
 	},
 };
 
 static int __init omap4_l3_init(void)
 {
-	return platform_driver_probe(&omap4_l3_driver, omap4_l3_probe);
+	return platform_driver_register(&omap4_l3_driver);
 }
 postcore_initcall_sync(omap4_l3_init);
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_l3_noc.h linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_l3_noc.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_l3_noc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_l3_noc.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,132 +1,162 @@
- /*
-  * 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
-  */
+/*
+ * 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 TARG register offsets */
+#define L3_TARG_STDERRLOG_MAIN		0x48
+#define L3_TARG_STDERRLOG_SLVOFSLSB	0x5c
+#define L3_TARG_STDERRLOG_MSTADDR	0x68
+#define L3_FLAGMUX_REGERR0		0xc
+
+#define NUM_OF_L3_MASTERS	(sizeof(l3_masters)/sizeof(l3_masters[0]))
+
+static u32 l3_flagmux[L3_MODULES] = {
+	0x500,
+	0x1000,
+	0X0200
 };
 
-/*
- * L3 Target standard Error register offsets
- */
-u32 l3_targ_stderrlog_main_clk1[] = {
-	0x148, /* DMM1 */
-	0x248, /* DMM2 */
-	0x348, /* ABE */
-	0x448, /* L4CFG */
-	0x648  /* CLK2 PWR DISC */
+/* L3 Target standard Error register offsets */
+static u32 l3_targ_inst_clk1[] = {
+	0x100, /* DMM1 */
+	0x200, /* DMM2 */
+	0x300, /* ABE */
+	0x400, /* L4CFG */
+	0x600  /* 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*/
+static u32 l3_targ_inst_clk2[] = {
+	0x500, /* CORTEX M3 */
+	0x300, /* DSS */
+	0x100, /* GPMC */
+	0x400, /* ISS */
+	0x700, /* IVAHD */
+	0xD00, /* missing in TRM  corresponds to AES1*/
+	0x900, /* L4 PER0*/
+	0x200, /* OCMRAM */
+	0x100, /* missing in TRM corresponds to GPMC sERROR*/
+	0x600, /* SGX */
+	0x800, /* SL2 */
+	0x1600, /* C2C */
+	0x1100,	/* missing in TRM corresponds PWR DISC CLK1*/
+	0xF00, /* missing in TRM corrsponds to SHA1*/
+	0xE00, /* missing in TRM corresponds to AES2*/
+	0xC00, /* L4 PER3 */
+	0xA00, /* L4 PER1*/
+	0xB00 /* L4 PER2*/
 };
 
-u32 l3_targ_stderrlog_main_clk3[] = {
-	0x0148	/* EMUSS */
+static u32 l3_targ_inst_clk3[] = {
+	0x0100	/* EMUSS */
 };
 
-char *l3_targ_stderrlog_main_name[L3_MODULES][18] = {
+static struct l3_masters_data {
+	u32 id;
+	char name[10];
+} l3_masters[] = {
+	{ 0x0 , "MPU"},
+	{ 0x10, "CS_ADP"},
+	{ 0x14, "xxx"},
+	{ 0x20, "DSP"},
+	{ 0x30, "IVAHD"},
+	{ 0x40, "ISS"},
+	{ 0x44, "DucatiM3"},
+	{ 0x48, "FaceDetect"},
+	{ 0x50, "SDMA_Rd"},
+	{ 0x54, "SDMA_Wr"},
+	{ 0x58, "xxx"},
+	{ 0x5C, "xxx"},
+	{ 0x60, "SGX"},
+	{ 0x70, "DSS"},
+	{ 0x80, "C2C"},
+	{ 0x88, "xxx"},
+	{ 0x8C, "xxx"},
+	{ 0x90, "HSI"},
+	{ 0xA0, "MMC1"},
+	{ 0xA4, "MMC2"},
+	{ 0xA8, "MMC6"},
+	{ 0xB0, "UNIPRO1"},
+	{ 0xC0, "USBHOSTHS"},
+	{ 0xC4, "USBOTGHS"},
+	{ 0xC8, "USBHOSTFS"}
+};
+
+static char *l3_targ_inst_name[L3_MODULES][18] = {
 	{
-	"DMM1",
-	"DMM2",
-	"ABE",
-	"L4CFG",
-	"CLK2 PWR DISC",
+		"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",
+		"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",
+		"EMUSS",
 	},
 };
 
-u32 *l3_targ[L3_MODULES] = {
-	l3_targ_stderrlog_main_clk1,
-	l3_targ_stderrlog_main_clk2,
-	l3_targ_stderrlog_main_clk3,
+static u32 *l3_targ[L3_MODULES] = {
+	l3_targ_inst_clk1,
+	l3_targ_inst_clk2,
+	l3_targ_inst_clk3,
 };
 
 struct omap4_l3 {
-	struct device	*dev;
-	struct clk	*ick;
+	struct device *dev;
+	struct clk *ick;
 
 	/* memory base */
-	void __iomem *l3_base[4];
+	void __iomem *l3_base[L3_MODULES];
 
-	int		debug_irq;
-	int		app_irq;
+	int debug_irq;
+	int app_irq;
 };
-
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_l3_smx.c linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_l3_smx.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_l3_smx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_l3_smx.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,26 +1,26 @@
- /*
-  * 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
-  */
+/*
+ * 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>
@@ -135,7 +135,7 @@
 	}
 }
 
-/**
+/*
  * omap3_l3_block_irq - handles a register block's irq
  * @l3: struct omap3_l3 *
  * @base: register block base address
@@ -150,30 +150,29 @@
 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);
+	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 seen by %s %s at address %x\n",
-				 omap3_l3_code_string(code),
-			  omap3_l3_initiator_string(initid),
-			     multi ? "Multiple Errors" : "",
-						   address);
+			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;
+	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;
 
 	int_type = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
 	if (!int_type) {
@@ -191,14 +190,12 @@
 	}
 
 	/* identify the error source */
-	for (err_source = 0; !(status & (1 << err_source)); err_source++)
-									;
+	err_source = __ffs(status);
 
-	base = l3->rt + *(omap3_l3_bases[int_type] + 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);
 	}
 
@@ -215,9 +212,9 @@
 
 static int __init omap3_l3_probe(struct platform_device *pdev)
 {
-	struct omap3_l3         *l3;
-	struct resource         *res;
-	int                     ret;
+	struct omap3_l3 *l3;
+	struct resource *res;
+	int ret;
 
 	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
 	if (!l3)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_l3_smx.h linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_l3_smx.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_l3_smx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_l3_smx.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,26 +1,26 @@
- /*
-  * 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
-  */
+/*
+ * 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
 
@@ -40,7 +40,7 @@
 #define L3_SI_CONTROL			0x020
 #define L3_SI_FLAG_STATUS_0		0x510
 
-const u64 shift = 1;
+static const u64 shift = 1;
 
 #define L3_STATUS_0_MPUIA_BRST		(shift << 0)
 #define L3_STATUS_0_MPUIA_RSP		(shift << 1)
@@ -78,32 +78,32 @@
 #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       \
+#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
@@ -137,19 +137,19 @@
 
 enum omap3_l3_initiator_id {
 	/* LCD has 1 ID */
-	OMAP_L3_LCD	        = 29,
+	OMAP_L3_LCD = 29,
 	/* SAD2D has 1 ID */
-	OMAP_L3_SAD2D		= 28,
+	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,
+	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,
+	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,
@@ -158,25 +158,25 @@
 	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,
+	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,
+	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,
+	OMAP_L3_IA_DAP = 9,
 	/* SDMA WR has 2 IDs */
-	OMAP_L3_SDMA_WR_1	= 8,
-	OMAP_L3_SDMA_WR_2	= 7,
+	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,
+	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,
+	OMAP_L3_USBOTG = 2,
 	/* HSUSB HOST has 1 ID */
-	OMAP_L3_USBHOST		= 1,
+	OMAP_L3_USBHOST = 1,
 };
 
 enum omap3_l3_code {
@@ -192,21 +192,21 @@
 };
 
 struct omap3_l3 {
-	struct device   *dev;
-	struct clk      *ick;
+	struct device *dev;
+	struct clk *ick;
 
 	/* memory base*/
-	void __iomem    *rt;
+	void __iomem *rt;
 
-	int             debug_irq;
-	int             app_irq;
+	int debug_irq;
+	int app_irq;
 
 	/* true when and inband functional error occurs */
-	unsigned        inband:1;
+	unsigned inband:1;
 };
 
 /* offsets for l3 agents in order with the Flag status register */
-unsigned int __iomem omap3_l3_app_bases[] = {
+static unsigned int omap3_l3_app_bases[] = {
 	/* MPU IA */
 	0x1400,
 	0x1400,
@@ -305,7 +305,7 @@
 	0,
 };
 
-unsigned int __iomem omap3_l3_debug_bases[] = {
+static unsigned int omap3_l3_debug_bases[] = {
 	/* MPU DATA IA */
 	0x1400,
 	/* RESERVED */
@@ -321,7 +321,7 @@
 	/* REST RESERVED */
 };
 
-u32 *omap3_l3_bases[] = {
+static u32 *omap3_l3_bases[] = {
 	omap3_l3_app_bases,
 	omap3_l3_debug_bases,
 };
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/omap-smp.c linux-libre-3.2-gnu/arch/arm/mach-omap2/omap-smp.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/omap-smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/omap-smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -102,19 +102,20 @@
 {
 	unsigned int i, ncores;
 
-	/* Never released */
-	scu_base = ioremap(OMAP44XX_SCU_BASE, SZ_256);
+	/*
+	 * Currently we can't call ioremap here because
+	 * SoC detection won't work until after init_early.
+	 */
+	scu_base =  OMAP2_L4_IO_ADDRESS(OMAP44XX_SCU_BASE);
 	BUG_ON(!scu_base);
 
 	ncores = scu_get_core_count(scu_base);
 
 	/* sanity check */
-	if (ncores > NR_CPUS) {
-		printk(KERN_WARNING
-		       "OMAP4: no. of cores (%d) greater than configured "
-		       "maximum of %d - clipping\n",
-		       ncores, NR_CPUS);
-		ncores = NR_CPUS;
+	if (ncores > nr_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
 	}
 
 	for (i = 0; i < ncores; i++)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_twl.c linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_twl.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/omap_twl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/omap_twl.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,8 +42,11 @@
 
 #define OMAP4_SRI2C_SLAVE_ADDR		0x12
 #define OMAP4_VDD_MPU_SR_VOLT_REG	0x55
+#define OMAP4_VDD_MPU_SR_CMD_REG	0x56
 #define OMAP4_VDD_IVA_SR_VOLT_REG	0x5B
+#define OMAP4_VDD_IVA_SR_CMD_REG	0x5C
 #define OMAP4_VDD_CORE_SR_VOLT_REG	0x61
+#define OMAP4_VDD_CORE_SR_CMD_REG	0x62
 
 #define OMAP4_VP_CONFIG_ERROROFFSET	0x00
 #define OMAP4_VP_VSTEPMIN_VSTEPMIN	0x01
@@ -95,6 +98,8 @@
 		is_offset_valid = true;
 	}
 
+	if (!vsel)
+		return 0;
 	/*
 	 * There is no specific formula for voltage to vsel
 	 * conversion above 1.3V. There are special hardcoded
@@ -106,9 +111,9 @@
 		return 1350000;
 
 	if (smps_offset & 0x8)
-		return ((((vsel - 1) * 125) + 7000)) * 100;
+		return ((((vsel - 1) * 1266) + 70900)) * 10;
 	else
-		return ((((vsel - 1) * 125) + 6000)) * 100;
+		return ((((vsel - 1) * 1266) + 60770)) * 10;
 }
 
 static u8 twl6030_uv_to_vsel(unsigned long uv)
@@ -127,6 +132,8 @@
 		is_offset_valid = true;
 	}
 
+	if (!uv)
+		return 0x00;
 	/*
 	 * There is no specific formula for voltage to vsel
 	 * conversion above 1.3V. There are special hardcoded
@@ -134,16 +141,21 @@
 	 * hardcoding only for 1.35 V which is used for 1GH OPP for
 	 * OMAP4430.
 	 */
-	if (uv == 1350000)
+	if (uv > twl6030_vsel_to_uv(0x39)) {
+		if (uv == 1350000)
+			return 0x3A;
+		pr_err("%s:OUT OF RANGE! non mapped vsel for %ld Vs max %ld\n",
+			__func__, uv, twl6030_vsel_to_uv(0x39));
 		return 0x3A;
+	}
 
 	if (smps_offset & 0x8)
-		return DIV_ROUND_UP(uv - 700000, 12500) + 1;
+		return DIV_ROUND_UP(uv - 709000, 12660) + 1;
 	else
-		return DIV_ROUND_UP(uv - 600000, 12500) + 1;
+		return DIV_ROUND_UP(uv - 607700, 12660) + 1;
 }
 
-static struct omap_volt_pmic_info omap3_mpu_volt_info = {
+static struct omap_voltdm_pmic omap3_mpu_pmic = {
 	.slew_rate		= 4000,
 	.step_size		= 12500,
 	.on_volt		= 1200000,
@@ -158,12 +170,13 @@
 	.vp_vddmax		= OMAP3430_VP1_VLIMITTO_VDDMAX,
 	.vp_timeout_us		= OMAP3_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP3_SRI2C_SLAVE_ADDR,
-	.pmic_reg		= OMAP3_VDD_MPU_SR_CONTROL_REG,
+	.volt_reg_addr		= OMAP3_VDD_MPU_SR_CONTROL_REG,
+	.i2c_high_speed		= true,
 	.vsel_to_uv		= twl4030_vsel_to_uv,
 	.uv_to_vsel		= twl4030_uv_to_vsel,
 };
 
-static struct omap_volt_pmic_info omap3_core_volt_info = {
+static struct omap_voltdm_pmic omap3_core_pmic = {
 	.slew_rate		= 4000,
 	.step_size		= 12500,
 	.on_volt                = 1200000,
@@ -178,18 +191,19 @@
 	.vp_vddmax		= OMAP3430_VP2_VLIMITTO_VDDMAX,
 	.vp_timeout_us		= OMAP3_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP3_SRI2C_SLAVE_ADDR,
-	.pmic_reg		= OMAP3_VDD_CORE_SR_CONTROL_REG,
+	.volt_reg_addr		= OMAP3_VDD_CORE_SR_CONTROL_REG,
+	.i2c_high_speed		= true,
 	.vsel_to_uv		= twl4030_vsel_to_uv,
 	.uv_to_vsel		= twl4030_uv_to_vsel,
 };
 
-static struct omap_volt_pmic_info omap4_mpu_volt_info = {
+static struct omap_voltdm_pmic omap4_mpu_pmic = {
 	.slew_rate		= 4000,
-	.step_size		= 12500,
-	.on_volt		= 1350000,
-	.onlp_volt		= 1350000,
-	.ret_volt		= 837500,
-	.off_volt		= 600000,
+	.step_size		= 12660,
+	.on_volt		= 1375000,
+	.onlp_volt		= 1375000,
+	.ret_volt		= 830000,
+	.off_volt		= 0,
 	.volt_setup_time	= 0,
 	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
 	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
@@ -198,18 +212,20 @@
 	.vp_vddmax		= OMAP4_VP_MPU_VLIMITTO_VDDMAX,
 	.vp_timeout_us		= OMAP4_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP4_SRI2C_SLAVE_ADDR,
-	.pmic_reg		= OMAP4_VDD_MPU_SR_VOLT_REG,
+	.volt_reg_addr		= OMAP4_VDD_MPU_SR_VOLT_REG,
+	.cmd_reg_addr		= OMAP4_VDD_MPU_SR_CMD_REG,
+	.i2c_high_speed		= true,
 	.vsel_to_uv		= twl6030_vsel_to_uv,
 	.uv_to_vsel		= twl6030_uv_to_vsel,
 };
 
-static struct omap_volt_pmic_info omap4_iva_volt_info = {
+static struct omap_voltdm_pmic omap4_iva_pmic = {
 	.slew_rate		= 4000,
-	.step_size		= 12500,
-	.on_volt		= 1100000,
-	.onlp_volt		= 1100000,
-	.ret_volt		= 837500,
-	.off_volt		= 600000,
+	.step_size		= 12660,
+	.on_volt		= 1188000,
+	.onlp_volt		= 1188000,
+	.ret_volt		= 830000,
+	.off_volt		= 0,
 	.volt_setup_time	= 0,
 	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
 	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
@@ -218,18 +234,20 @@
 	.vp_vddmax		= OMAP4_VP_IVA_VLIMITTO_VDDMAX,
 	.vp_timeout_us		= OMAP4_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP4_SRI2C_SLAVE_ADDR,
-	.pmic_reg		= OMAP4_VDD_IVA_SR_VOLT_REG,
+	.volt_reg_addr		= OMAP4_VDD_IVA_SR_VOLT_REG,
+	.cmd_reg_addr		= OMAP4_VDD_IVA_SR_CMD_REG,
+	.i2c_high_speed		= true,
 	.vsel_to_uv		= twl6030_vsel_to_uv,
 	.uv_to_vsel		= twl6030_uv_to_vsel,
 };
 
-static struct omap_volt_pmic_info omap4_core_volt_info = {
+static struct omap_voltdm_pmic omap4_core_pmic = {
 	.slew_rate		= 4000,
-	.step_size		= 12500,
-	.on_volt		= 1100000,
-	.onlp_volt		= 1100000,
-	.ret_volt		= 837500,
-	.off_volt		= 600000,
+	.step_size		= 12660,
+	.on_volt		= 1200000,
+	.onlp_volt		= 1200000,
+	.ret_volt		= 830000,
+	.off_volt		= 0,
 	.volt_setup_time	= 0,
 	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
 	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
@@ -238,7 +256,8 @@
 	.vp_vddmax		= OMAP4_VP_CORE_VLIMITTO_VDDMAX,
 	.vp_timeout_us		= OMAP4_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP4_SRI2C_SLAVE_ADDR,
-	.pmic_reg		= OMAP4_VDD_CORE_SR_VOLT_REG,
+	.volt_reg_addr		= OMAP4_VDD_CORE_SR_VOLT_REG,
+	.cmd_reg_addr		= OMAP4_VDD_CORE_SR_CMD_REG,
 	.vsel_to_uv		= twl6030_vsel_to_uv,
 	.uv_to_vsel		= twl6030_uv_to_vsel,
 };
@@ -250,14 +269,14 @@
 	if (!cpu_is_omap44xx())
 		return -ENODEV;
 
-	voltdm = omap_voltage_domain_lookup("mpu");
-	omap_voltage_register_pmic(voltdm, &omap4_mpu_volt_info);
+	voltdm = voltdm_lookup("mpu");
+	omap_voltage_register_pmic(voltdm, &omap4_mpu_pmic);
 
-	voltdm = omap_voltage_domain_lookup("iva");
-	omap_voltage_register_pmic(voltdm, &omap4_iva_volt_info);
+	voltdm = voltdm_lookup("iva");
+	omap_voltage_register_pmic(voltdm, &omap4_iva_pmic);
 
-	voltdm = omap_voltage_domain_lookup("core");
-	omap_voltage_register_pmic(voltdm, &omap4_core_volt_info);
+	voltdm = voltdm_lookup("core");
+	omap_voltage_register_pmic(voltdm, &omap4_core_pmic);
 
 	return 0;
 }
@@ -270,10 +289,10 @@
 		return -ENODEV;
 
 	if (cpu_is_omap3630()) {
-		omap3_mpu_volt_info.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN;
-		omap3_mpu_volt_info.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX;
-		omap3_core_volt_info.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN;
-		omap3_core_volt_info.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
+		omap3_mpu_pmic.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN;
+		omap3_mpu_pmic.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX;
+		omap3_core_pmic.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN;
+		omap3_core_pmic.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
 	}
 
 	/*
@@ -288,11 +307,11 @@
 	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);
+	voltdm = voltdm_lookup("mpu_iva");
+	omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic);
 
-	voltdm = omap_voltage_domain_lookup("core");
-	omap_voltage_register_pmic(voltdm, &omap3_core_volt_info);
+	voltdm = voltdm_lookup("core");
+	omap_voltage_register_pmic(voltdm, &omap3_core_pmic);
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/opp.c linux-libre-3.2-gnu/arch/arm/mach-omap2/opp.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/opp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/opp.c	2012-01-04 18:55:44.000000000 -0500
@@ -69,7 +69,7 @@
 				opp_def->hwmod_name, i);
 			return -EINVAL;
 		}
-		dev = &oh->od->pdev.dev;
+		dev = &oh->od->pdev->dev;
 
 		r = opp_add(dev, opp_def->freq, opp_def->u_volt);
 		if (r) {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/pm24xx.c linux-libre-3.2-gnu/arch/arm/mach-omap2/pm24xx.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/pm24xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/pm24xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -53,8 +53,6 @@
 #include "powerdomain.h"
 #include "clockdomain.h"
 
-static int omap2_pm_debug;
-
 #ifdef CONFIG_SUSPEND
 static suspend_state_t suspend_state = PM_SUSPEND_ON;
 static inline bool is_suspending(void)
@@ -96,7 +94,6 @@
 static void omap2_enter_full_retention(void)
 {
 	u32 l;
-	struct timespec ts_preidle, ts_postidle, ts_idle;
 
 	/* There is 1 reference hold for all children of the oscillator
 	 * clock, the following will remove it. If no one else uses the
@@ -124,10 +121,6 @@
 
 	omap2_gpio_prepare_for_idle(0);
 
-	if (omap2_pm_debug) {
-		getnstimeofday(&ts_preidle);
-	}
-
 	/* One last check for pending IRQs to avoid extra latency due
 	 * to sleeping unnecessarily. */
 	if (omap_irq_pending())
@@ -155,13 +148,6 @@
 		console_unlock();
 
 no_sleep:
-	if (omap2_pm_debug) {
-		unsigned long long tmp;
-
-		getnstimeofday(&ts_postidle);
-		ts_idle = timespec_sub(ts_postidle, ts_preidle);
-		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
-	}
 	omap2_gpio_resume_after_idle();
 
 	clk_enable(osc_ck);
@@ -219,7 +205,6 @@
 static void omap2_enter_mpu_retention(void)
 {
 	int only_idle = 0;
-	struct timespec ts_preidle, ts_postidle, ts_idle;
 
 	/* Putting MPU into the WFI state while a transfer is active
 	 * seems to cause the I2C block to timeout. Why? Good question. */
@@ -246,19 +231,7 @@
 		only_idle = 1;
 	}
 
-	if (omap2_pm_debug) {
-		getnstimeofday(&ts_preidle);
-	}
-
 	omap2_sram_idle();
-
-	if (omap2_pm_debug) {
-		unsigned long long tmp;
-
-		getnstimeofday(&ts_postidle);
-		ts_idle = timespec_sub(ts_postidle, ts_preidle);
-		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
-	}
 }
 
 static int omap2_can_sleep(void)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/pm34xx.c linux-libre-3.2-gnu/arch/arm/mach-omap2/pm34xx.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/pm34xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/pm34xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -55,7 +55,7 @@
 static suspend_state_t suspend_state = PM_SUSPEND_ON;
 static inline bool is_suspending(void)
 {
-	return (suspend_state != PM_SUSPEND_ON);
+	return (suspend_state != PM_SUSPEND_ON) && console_suspend_enabled;
 }
 #else
 static inline bool is_suspending(void)
@@ -99,31 +99,27 @@
 {
 	int timeout = 0;
 
-	if (omap_rev() >= OMAP3430_REV_ES3_1) {
-		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
-				     PM_WKEN);
-		/* Do a readback to assure write has been done */
-		omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
+	omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+				   PM_WKEN);
+	/* Do a readback to assure write has been done */
+	omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
 
-		while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
-			 OMAP3430_ST_IO_CHAIN_MASK)) {
-			timeout++;
-			if (timeout > 1000) {
-				printk(KERN_ERR "Wake up daisy chain "
-				       "activation failed.\n");
-				return;
-			}
-			omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
-					     WKUP_MOD, PM_WKEN);
+	while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
+		 OMAP3430_ST_IO_CHAIN_MASK)) {
+		timeout++;
+		if (timeout > 1000) {
+			pr_err("Wake up daisy chain activation failed.\n");
+			return;
 		}
+		omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
+					   WKUP_MOD, PM_WKEN);
 	}
 }
 
 static void omap3_disable_io_chain(void)
 {
-	if (omap_rev() >= OMAP3430_REV_ES3_1)
-		omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
-				       PM_WKEN);
+	omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+				     PM_WKEN);
 }
 
 static void omap3_core_save_context(void)
@@ -363,7 +359,6 @@
 		printk(KERN_ERR "Invalid mpu state in sram_idle\n");
 		return;
 	}
-	pwrdm_pre_transition();
 
 	/* NEON control */
 	if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON)
@@ -376,7 +371,8 @@
 	    (per_next_state < PWRDM_POWER_ON ||
 	     core_next_state < PWRDM_POWER_ON)) {
 		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
-		omap3_enable_io_chain();
+		if (omap3_has_io_chain_ctrl())
+			omap3_enable_io_chain();
 	}
 
 	/* Block console output in case it is on one of the OMAP UARTs */
@@ -386,6 +382,8 @@
 			if (!console_trylock())
 				goto console_still_active;
 
+	pwrdm_pre_transition();
+
 	/* PER */
 	if (per_next_state < PWRDM_POWER_ON) {
 		per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
@@ -409,13 +407,14 @@
 	omap3_intc_prepare_idle();
 
 	/*
-	* On EMU/HS devices ROM code restores a SRDC value
-	* from scratchpad which has automatic self refresh on timeout
-	* of AUTO_CNT = 1 enabled. This takes care of erratum ID i443.
-	* Hence store/restore the SDRC_POWER register here.
-	*/
-	if (omap_rev() >= OMAP3430_REV_ES3_0 &&
-	    omap_type() != OMAP2_DEVICE_TYPE_GP &&
+	 * On EMU/HS devices ROM code restores a SRDC value
+	 * from scratchpad which has automatic self refresh on timeout
+	 * of AUTO_CNT = 1 enabled. This takes care of erratum ID i443.
+	 * Hence store/restore the SDRC_POWER register here.
+	 */
+	if (cpu_is_omap3430() && omap_rev() >= OMAP3430_REV_ES3_0 &&
+	    (omap_type() == OMAP2_DEVICE_TYPE_EMU ||
+	     omap_type() == OMAP2_DEVICE_TYPE_SEC) &&
 	    core_next_state == PWRDM_POWER_OFF)
 		sdrc_pwr = sdrc_read_reg(SDRC_POWER);
 
@@ -432,8 +431,9 @@
 		omap34xx_do_sram_idle(save_state);
 
 	/* Restore normal SDRC POWER settings */
-	if (omap_rev() >= OMAP3430_REV_ES3_0 &&
-	    omap_type() != OMAP2_DEVICE_TYPE_GP &&
+	if (cpu_is_omap3430() && omap_rev() >= OMAP3430_REV_ES3_0 &&
+	    (omap_type() == OMAP2_DEVICE_TYPE_EMU ||
+	     omap_type() == OMAP2_DEVICE_TYPE_SEC) &&
 	    core_next_state == PWRDM_POWER_OFF)
 		sdrc_write_reg(sdrc_pwr, SDRC_POWER);
 
@@ -455,6 +455,8 @@
 	}
 	omap3_intc_resume_idle();
 
+	pwrdm_post_transition();
+
 	/* PER */
 	if (per_next_state < PWRDM_POWER_ON) {
 		per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm);
@@ -475,11 +477,10 @@
 	     core_next_state < PWRDM_POWER_ON)) {
 		omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
 					     PM_WKEN);
-		omap3_disable_io_chain();
+		if (omap3_has_io_chain_ctrl())
+			omap3_disable_io_chain();
 	}
 
-	pwrdm_post_transition();
-
 	clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
 }
 
@@ -870,6 +871,9 @@
 	if (!cpu_is_omap34xx())
 		return -ENODEV;
 
+	if (!omap3_has_io_chain_ctrl())
+		pr_warning("PM: no software I/O chain control; some wakeups may be lost\n");
+
 	pm_errata_configure();
 
 	/* XXX prcm_setup_regs needs to be before enabling hw
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/pm.c linux-libre-3.2-gnu/arch/arm/mach-omap2/pm.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/opp.h>
+#include <linux/export.h>
 
 #include <plat/omap-pm.h>
 #include <plat/omap_device.h>
@@ -23,57 +24,25 @@
 #include "powerdomain.h"
 #include "clockdomain.h"
 #include "pm.h"
+#include "twl-common.h"
 
 static struct omap_device_pm_latency *pm_lats;
 
-static struct device *mpu_dev;
-static struct device *iva_dev;
-static struct device *l3_dev;
-static struct device *dsp_dev;
-
-struct device *omap2_get_mpuss_device(void)
-{
-	WARN_ON_ONCE(!mpu_dev);
-	return mpu_dev;
-}
-
-struct device *omap2_get_iva_device(void)
-{
-	WARN_ON_ONCE(!iva_dev);
-	return iva_dev;
-}
-
-struct device *omap2_get_l3_device(void)
-{
-	WARN_ON_ONCE(!l3_dev);
-	return l3_dev;
-}
-
-struct device *omap4_get_dsp_device(void)
-{
-	WARN_ON_ONCE(!dsp_dev);
-	return dsp_dev;
-}
-EXPORT_SYMBOL(omap4_get_dsp_device);
-
-/* static int _init_omap_device(struct omap_hwmod *oh, void *user) */
-static int _init_omap_device(char *name, struct device **new_dev)
+static int _init_omap_device(char *name)
 {
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 
 	oh = omap_hwmod_lookup(name);
 	if (WARN(!oh, "%s: could not find omap_hwmod for %s\n",
 		 __func__, name))
 		return -ENODEV;
 
-	od = omap_device_build(oh->name, 0, oh, NULL, 0, pm_lats, 0, false);
-	if (WARN(IS_ERR(od), "%s: could not build omap_device for %s\n",
+	pdev = omap_device_build(oh->name, 0, oh, NULL, 0, pm_lats, 0, false);
+	if (WARN(IS_ERR(pdev), "%s: could not build omap_device for %s\n",
 		 __func__, name))
 		return -ENODEV;
 
-	*new_dev = &od->pdev.dev;
-
 	return 0;
 }
 
@@ -82,16 +51,16 @@
  */
 static void omap2_init_processor_devices(void)
 {
-	_init_omap_device("mpu", &mpu_dev);
+	_init_omap_device("mpu");
 	if (omap3_has_iva())
-		_init_omap_device("iva", &iva_dev);
+		_init_omap_device("iva");
 
 	if (cpu_is_omap44xx()) {
-		_init_omap_device("l3_main_1", &l3_dev);
-		_init_omap_device("dsp", &dsp_dev);
-		_init_omap_device("iva", &iva_dev);
+		_init_omap_device("l3_main_1");
+		_init_omap_device("dsp");
+		_init_omap_device("iva");
 	} else {
-		_init_omap_device("l3_main", &l3_dev);
+		_init_omap_device("l3_main");
 	}
 }
 
@@ -136,8 +105,8 @@
 
 	ret = pwrdm_set_next_pwrst(pwrdm, state);
 	if (ret) {
-		printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
-		       pwrdm->name);
+		pr_err("%s: unable to set state of powerdomain: %s\n",
+		       __func__, pwrdm->name);
 		goto err;
 	}
 
@@ -161,37 +130,44 @@
 }
 
 /*
- * This API is to be called during init to put the various voltage
+ * This API is to be called during init to set the various voltage
  * domains to the voltage as per the opp table. Typically we boot up
  * at the nominal voltage. So this function finds out the rate of
  * the clock associated with the voltage domain, finds out the correct
- * opp entry and puts the voltage domain to the voltage specifies
+ * opp entry and sets the voltage domain to the voltage specified
  * in the opp entry
  */
 static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
-						struct device *dev)
+					 const char *oh_name)
 {
 	struct voltagedomain *voltdm;
 	struct clk *clk;
 	struct opp *opp;
 	unsigned long freq, bootup_volt;
+	struct device *dev;
 
-	if (!vdd_name || !clk_name || !dev) {
-		printk(KERN_ERR "%s: Invalid parameters!\n", __func__);
+	if (!vdd_name || !clk_name || !oh_name) {
+		pr_err("%s: invalid parameters\n", __func__);
 		goto exit;
 	}
 
-	voltdm = omap_voltage_domain_lookup(vdd_name);
+	dev = omap_device_get_by_hwmod_name(oh_name);
+	if (IS_ERR(dev)) {
+		pr_err("%s: Unable to get dev pointer for hwmod %s\n",
+			__func__, oh_name);
+		goto exit;
+	}
+
+	voltdm = voltdm_lookup(vdd_name);
 	if (IS_ERR(voltdm)) {
-		printk(KERN_ERR "%s: Unable to get vdd pointer for vdd_%s\n",
+		pr_err("%s: unable to get vdd pointer for vdd_%s\n",
 			__func__, vdd_name);
 		goto exit;
 	}
 
 	clk =  clk_get(NULL, clk_name);
 	if (IS_ERR(clk)) {
-		printk(KERN_ERR "%s: unable to get clk %s\n",
-			__func__, clk_name);
+		pr_err("%s: unable to get clk %s\n", __func__, clk_name);
 		goto exit;
 	}
 
@@ -200,24 +176,23 @@
 
 	opp = opp_find_freq_ceil(dev, &freq);
 	if (IS_ERR(opp)) {
-		printk(KERN_ERR "%s: unable to find boot up OPP for vdd_%s\n",
+		pr_err("%s: unable to find boot up OPP for vdd_%s\n",
 			__func__, vdd_name);
 		goto exit;
 	}
 
 	bootup_volt = opp_get_voltage(opp);
 	if (!bootup_volt) {
-		printk(KERN_ERR "%s: unable to find voltage corresponding"
+		pr_err("%s: unable to find voltage corresponding "
 			"to the bootup OPP for vdd_%s\n", __func__, vdd_name);
 		goto exit;
 	}
 
-	omap_voltage_scale_vdd(voltdm, bootup_volt);
+	voltdm_scale(voltdm, bootup_volt);
 	return 0;
 
 exit:
-	printk(KERN_ERR "%s: Unable to put vdd_%s to its init voltage\n\n",
-		__func__, vdd_name);
+	pr_err("%s: unable to set vdd_%s\n", __func__, vdd_name);
 	return -EINVAL;
 }
 
@@ -226,8 +201,8 @@
 	if (!cpu_is_omap34xx())
 		return;
 
-	omap2_set_init_voltage("mpu", "dpll1_ck", mpu_dev);
-	omap2_set_init_voltage("core", "l3_ick", l3_dev);
+	omap2_set_init_voltage("mpu_iva", "dpll1_ck", "mpu");
+	omap2_set_init_voltage("core", "l3_ick", "l3_main");
 }
 
 static void __init omap4_init_voltages(void)
@@ -235,14 +210,15 @@
 	if (!cpu_is_omap44xx())
 		return;
 
-	omap2_set_init_voltage("mpu", "dpll_mpu_ck", mpu_dev);
-	omap2_set_init_voltage("core", "l3_div_ck", l3_dev);
-	omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", iva_dev);
+	omap2_set_init_voltage("mpu", "dpll_mpu_ck", "mpu");
+	omap2_set_init_voltage("core", "l3_div_ck", "l3_main_1");
+	omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", "iva");
 }
 
 static int __init omap2_common_pm_init(void)
 {
-	omap2_init_processor_devices();
+	if (!of_have_populated_dt())
+		omap2_init_processor_devices();
 	omap_pm_if_init();
 
 	return 0;
@@ -251,11 +227,8 @@
 
 static int __init omap2_common_pm_late_init(void)
 {
-	/* Init the OMAP TWL parameters */
-	omap3_twl_init();
-	omap4_twl_init();
-
 	/* Init the voltage layer */
+	omap_pmic_late_init();
 	omap_voltage_late_init();
 
 	/* Initialize the voltages */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c linux-libre-3.2-gnu/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * OMAP2 and OMAP3 powerdomain control
  *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2009 Nokia Corporation
  *
  * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/powerdomain.c linux-libre-3.2-gnu/arch/arm/mach-omap2/powerdomain.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/powerdomain.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/powerdomain.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * OMAP powerdomain control
  *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Written by Paul Walmsley
@@ -77,13 +77,11 @@
 static int _pwrdm_register(struct powerdomain *pwrdm)
 {
 	int i;
+	struct voltagedomain *voltdm;
 
 	if (!pwrdm || !pwrdm->name)
 		return -EINVAL;
 
-	if (!omap_chip_is(pwrdm->omap_chip))
-		return -EINVAL;
-
 	if (cpu_is_omap44xx() &&
 	    pwrdm->prcm_partition == OMAP4430_INVALID_PRCM_PARTITION) {
 		pr_err("powerdomain: %s: missing OMAP4 PRCM partition ID\n",
@@ -94,6 +92,16 @@
 	if (_pwrdm_lookup(pwrdm->name))
 		return -EEXIST;
 
+	voltdm = voltdm_lookup(pwrdm->voltdm.name);
+	if (!voltdm) {
+		pr_err("powerdomain: %s: voltagedomain %s does not exist\n",
+		       pwrdm->name, pwrdm->voltdm.name);
+		return -EINVAL;
+	}
+	pwrdm->voltdm.ptr = voltdm;
+	INIT_LIST_HEAD(&pwrdm->voltdm_node);
+	voltdm_add_pwrdm(voltdm, pwrdm);
+
 	list_add(&pwrdm->node, &pwrdm_list);
 
 	/* Initialize the powerdomain's state counter */
@@ -194,36 +202,76 @@
 /* Public functions */
 
 /**
- * pwrdm_init - set up the powerdomain layer
- * @pwrdms: array of struct powerdomain pointers to register
- * @custom_funcs: func pointers for arch specific implementations
+ * pwrdm_register_platform_funcs - register powerdomain implementation fns
+ * @po: func pointers for arch specific implementations
  *
- * Loop through the array of powerdomains @pwrdms, registering all
- * that are available on the current CPU.  Also, program all
- * powerdomain target state as ON; this is to prevent domains from
- * hitting low power states (if bootloader has target states set to
- * something other than ON) and potentially even losing context while
- * PM is not fully initialized.  The PM late init code can then program
- * the desired target state for all the power domains.  No return
- * value.
+ * Register the list of function pointers used to implement the
+ * powerdomain functions on different OMAP SoCs.  Should be called
+ * before any other pwrdm_register*() function.  Returns -EINVAL if
+ * @po is null, -EEXIST if platform functions have already been
+ * registered, or 0 upon success.
  */
-void pwrdm_init(struct powerdomain **pwrdms, struct pwrdm_ops *custom_funcs)
+int pwrdm_register_platform_funcs(struct pwrdm_ops *po)
+{
+	if (!po)
+		return -EINVAL;
+
+	if (arch_pwrdm)
+		return -EEXIST;
+
+	arch_pwrdm = po;
+
+	return 0;
+}
+
+/**
+ * pwrdm_register_pwrdms - register SoC powerdomains
+ * @ps: pointer to an array of struct powerdomain to register
+ *
+ * Register the powerdomains available on a particular OMAP SoC.  Must
+ * be called after pwrdm_register_platform_funcs().  May be called
+ * multiple times.  Returns -EACCES if called before
+ * pwrdm_register_platform_funcs(); -EINVAL if the argument @ps is
+ * null; or 0 upon success.
+ */
+int pwrdm_register_pwrdms(struct powerdomain **ps)
 {
 	struct powerdomain **p = NULL;
-	struct powerdomain *temp_p;
 
-	if (!custom_funcs)
-		WARN(1, "powerdomain: No custom pwrdm functions registered\n");
-	else
-		arch_pwrdm = custom_funcs;
+	if (!arch_pwrdm)
+		return -EEXIST;
 
-	if (pwrdms) {
-		for (p = pwrdms; *p; p++)
-			_pwrdm_register(*p);
-	}
+	if (!ps)
+		return -EINVAL;
+
+	for (p = ps; *p; p++)
+		_pwrdm_register(*p);
+
+	return 0;
+}
+
+/**
+ * pwrdm_complete_init - set up the powerdomain layer
+ *
+ * Do whatever is necessary to initialize registered powerdomains and
+ * powerdomain code.  Currently, this programs the next power state
+ * for each powerdomain to ON.  This prevents powerdomains from
+ * unexpectedly losing context or entering high wakeup latency modes
+ * with non-power-management-enabled kernels.  Must be called after
+ * pwrdm_register_pwrdms().  Returns -EACCES if called before
+ * pwrdm_register_pwrdms(), or 0 upon success.
+ */
+int pwrdm_complete_init(void)
+{
+	struct powerdomain *temp_p;
+
+	if (list_empty(&pwrdm_list))
+		return -EACCES;
 
 	list_for_each_entry(temp_p, &pwrdm_list, node)
 		pwrdm_set_next_pwrst(temp_p, PWRDM_POWER_ON);
+
+	return 0;
 }
 
 /**
@@ -390,6 +438,18 @@
 }
 
 /**
+ * pwrdm_get_voltdm - return a ptr to the voltdm that this pwrdm resides in
+ * @pwrdm: struct powerdomain *
+ *
+ * Return a pointer to the struct voltageomain that the specified powerdomain
+ * @pwrdm exists in.
+ */
+struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm)
+{
+	return pwrdm->voltdm.ptr;
+}
+
+/**
  * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
  * @pwrdm: struct powerdomain *
  *
@@ -942,16 +1002,16 @@
  * @pwrdm: struct powerdomain * to wait for
  *
  * Context loss count is the sum of powerdomain off-mode counter, the
- * logic off counter and the per-bank memory off counter.  Returns 0
+ * logic off counter and the per-bank memory off counter.  Returns negative
  * (and WARNs) upon error, otherwise, returns the context loss count.
  */
-u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
+int pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
 {
 	int i, count;
 
 	if (!pwrdm) {
 		WARN(1, "powerdomain: %s: pwrdm is null\n", __func__);
-		return 0;
+		return -ENODEV;
 	}
 
 	count = pwrdm->state_counter[PWRDM_POWER_OFF];
@@ -960,7 +1020,13 @@
 	for (i = 0; i < pwrdm->banks; i++)
 		count += pwrdm->ret_mem_off_counter[i];
 
-	pr_debug("powerdomain: %s: context loss count = %u\n",
+	/*
+	 * Context loss count has to be a non-negative value. Clear the sign
+	 * bit to get a value range from 0 to INT_MAX.
+	 */
+	count &= INT_MAX;
+
+	pr_debug("powerdomain: %s: context loss count = %d\n",
 		 pwrdm->name, count);
 
 	return count;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/powerdomain-common.c linux-libre-3.2-gnu/arch/arm/mach-omap2/powerdomain-common.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/powerdomain-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/powerdomain-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,9 +1,8 @@
 /*
- *  linux/arch/arm/mach-omap2/powerdomain-common.c
- *  Contains common powerdomain framework functions
+ * Common powerdomain framework functions
  *
- *  Copyright (C) 2010 Texas Instruments, Inc.
- *  Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2010-2011 Texas Instruments, Inc.
+ * Copyright (C) 2010 Nokia Corporation
  *
  * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
  *
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/powerdomain.h linux-libre-3.2-gnu/arch/arm/mach-omap2/powerdomain.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/powerdomain.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/powerdomain.h	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
 
 #include <plat/cpu.h>
 
+#include "voltage.h"
+
 /* Powerdomain basic power states */
 #define PWRDM_POWER_OFF		0x0
 #define PWRDM_POWER_RET		0x1
@@ -78,7 +80,7 @@
 /**
  * struct powerdomain - OMAP powerdomain
  * @name: Powerdomain name
- * @omap_chip: represents the OMAP chip types containing this pwrdm
+ * @voltdm: voltagedomain containing this powerdomain
  * @prcm_offs: the address offset from CM_BASE/PRM_BASE
  * @prcm_partition: (OMAP4 only) the PRCM partition ID containing @prcm_offs
  * @pwrsts: Possible powerdomain power states
@@ -89,6 +91,7 @@
  * @pwrsts_mem_on: Possible memory bank pwrstates when pwrdm in ON
  * @pwrdm_clkdms: Clockdomains in this powerdomain
  * @node: list_head linking all powerdomains
+ * @voltdm_node: list_head linking all powerdomains in a voltagedomain
  * @state:
  * @state_counter:
  * @timer:
@@ -98,7 +101,10 @@
  */
 struct powerdomain {
 	const char *name;
-	const struct omap_chip_id omap_chip;
+	union {
+		const char *name;
+		struct voltagedomain *ptr;
+	} voltdm;
 	const s16 prcm_offs;
 	const u8 pwrsts;
 	const u8 pwrsts_logic_ret;
@@ -109,6 +115,7 @@
 	const u8 prcm_partition;
 	struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
 	struct list_head node;
+	struct list_head voltdm_node;
 	int state;
 	unsigned state_counter[PWRDM_MAX_PWRSTS];
 	unsigned ret_logic_off_counter;
@@ -162,7 +169,9 @@
 	int	(*pwrdm_wait_transition)(struct powerdomain *pwrdm);
 };
 
-void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs);
+int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
+int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list);
+int pwrdm_complete_init(void);
 
 struct powerdomain *pwrdm_lookup(const char *name);
 
@@ -176,6 +185,7 @@
 int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
 			 int (*fn)(struct powerdomain *pwrdm,
 				   struct clockdomain *clkdm));
+struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
 
 int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
 
@@ -207,10 +217,11 @@
 int pwrdm_pre_transition(void);
 int pwrdm_post_transition(void);
 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
-u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
+int 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 omap242x_powerdomains_init(void);
+extern void omap243x_powerdomains_init(void);
 extern void omap3xxx_powerdomains_init(void);
 extern void omap44xx_powerdomains_init(void);
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * OMAP2/3 common powerdomain definitions
  *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni HÃ¶gander
@@ -12,20 +12,6 @@
  */
 
 /*
- * To Do List
- * -> Move the Sleep/Wakeup dependencies from Power Domain framework to
- *    Clock Domain Framework
- */
-
-/*
- * This file contains all of the powerdomains that have some element
- * of software control for the OMAP24xx and OMAP34xx chips.
- *
- * This is not an exhaustive listing of powerdomains on the chips; only
- * powerdomains that can be controlled in software.
- */
-
-/*
  * The names for the DSP/IVA2 powerdomains are confusing.
  *
  * Most OMAP chips have an on-board DSP.
@@ -59,8 +45,6 @@
 struct powerdomain gfx_omap2_pwrdm = {
 	.name		  = "gfx_pwrdm",
 	.prcm_offs	  = GFX_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
-					   CHIP_IS_OMAP3430ES1),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
@@ -70,11 +54,12 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 struct powerdomain wkup_omap2_pwrdm = {
 	.name		= "wkup_pwrdm",
 	.prcm_offs	= WKUP_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
 	.pwrsts		= PWRSTS_ON,
+	.voltdm         = { .name = "wakeup" },
 };
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/powerdomains2xxx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/powerdomains2xxx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/powerdomains2xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/powerdomains2xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * OMAP2XXX powerdomain definitions
  *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni HÃ¶gander
@@ -28,7 +28,6 @@
 static struct powerdomain dsp_pwrdm = {
 	.name		  = "dsp_pwrdm",
 	.prcm_offs	  = OMAP24XX_DSP_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
@@ -38,12 +37,12 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain mpu_24xx_pwrdm = {
 	.name		  = "mpu_pwrdm",
 	.prcm_offs	  = MPU_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -53,12 +52,12 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain core_24xx_pwrdm = {
 	.name		  = "core_pwrdm",
 	.prcm_offs	  = CORE_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.banks		  = 3,
 	.pwrsts_mem_ret	  = {
@@ -71,6 +70,7 @@
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 		[2] = PWRSTS_OFF_RET_ON, /* MEM3ONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 
@@ -78,14 +78,11 @@
  * 2430-specific powerdomains
  */
 
-#ifdef CONFIG_SOC_OMAP2430
-
 /* XXX 2430 KILLDOMAINWKUP bit?  No current users apparently */
 
 static struct powerdomain mdm_pwrdm = {
 	.name		  = "mdm_pwrdm",
 	.prcm_offs	  = OMAP2430_MDM_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
@@ -95,29 +92,44 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
-#endif     /* CONFIG_SOC_OMAP2430 */
-
-/* As powerdomains are added or removed above, this list must also be changed */
-static struct powerdomain *powerdomains_omap2xxx[] __initdata = {
+/*
+ *
+ */
 
+static struct powerdomain *powerdomains_omap24xx[] __initdata = {
 	&wkup_omap2_pwrdm,
 	&gfx_omap2_pwrdm,
-
-#ifdef CONFIG_ARCH_OMAP2
 	&dsp_pwrdm,
 	&mpu_24xx_pwrdm,
 	&core_24xx_pwrdm,
-#endif
+	NULL
+};
 
-#ifdef CONFIG_SOC_OMAP2430
+static struct powerdomain *powerdomains_omap2430[] __initdata = {
 	&mdm_pwrdm,
-#endif
 	NULL
 };
 
-void __init omap2xxx_powerdomains_init(void)
+void __init omap242x_powerdomains_init(void)
 {
-	pwrdm_init(powerdomains_omap2xxx, &omap2_pwrdm_operations);
+	if (!cpu_is_omap2420())
+		return;
+
+	pwrdm_register_platform_funcs(&omap2_pwrdm_operations);
+	pwrdm_register_pwrdms(powerdomains_omap24xx);
+	pwrdm_complete_init();
+}
+
+void __init omap243x_powerdomains_init(void)
+{
+	if (!cpu_is_omap2430())
+		return;
+
+	pwrdm_register_platform_funcs(&omap2_pwrdm_operations);
+	pwrdm_register_pwrdms(powerdomains_omap24xx);
+	pwrdm_register_pwrdms(powerdomains_omap2430);
+	pwrdm_complete_init();
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/powerdomains3xxx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/powerdomains3xxx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/powerdomains3xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/powerdomains3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * OMAP3 powerdomain definitions
  *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni HÃ¶gander
@@ -14,6 +14,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
+#include <plat/cpu.h>
+
 #include "powerdomain.h"
 #include "powerdomains2xxx_3xxx_data.h"
 
@@ -27,8 +29,6 @@
  * 34XX-specific powerdomains, dependencies
  */
 
-#ifdef CONFIG_ARCH_OMAP3
-
 /*
  * Powerdomains
  */
@@ -36,7 +36,6 @@
 static struct powerdomain iva2_pwrdm = {
 	.name		  = "iva2_pwrdm",
 	.prcm_offs	  = OMAP3430_IVA2_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 4,
@@ -52,12 +51,12 @@
 		[2] = PWRSTS_OFF_ON,
 		[3] = PWRSTS_ON,
 	},
+	.voltdm           = { .name = "mpu_iva" },
 };
 
 static struct powerdomain mpu_3xxx_pwrdm = {
 	.name		  = "mpu_pwrdm",
 	.prcm_offs	  = MPU_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.flags		  = PWRDM_HAS_MPU_QUIRK,
@@ -68,6 +67,7 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_OFF_ON,
 	},
+	.voltdm           = { .name = "mpu_iva" },
 };
 
 /*
@@ -83,10 +83,6 @@
 static struct powerdomain core_3xxx_pre_es3_1_pwrdm = {
 	.name		  = "core_pwrdm",
 	.prcm_offs	  = CORE_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
-					   CHIP_IS_OMAP3430ES2 |
-					   CHIP_IS_OMAP3430ES3_0 |
-					   CHIP_IS_OMAP3630ES1),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 2,
@@ -98,13 +94,12 @@
 		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain core_3xxx_es3_1_pwrdm = {
 	.name		  = "core_pwrdm",
 	.prcm_offs	  = CORE_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES3_1 |
-					  CHIP_GE_OMAP3630ES1_1),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	/*
@@ -121,11 +116,11 @@
 		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain dss_pwrdm = {
 	.name		  = "dss_pwrdm",
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.prcm_offs	  = OMAP3430_DSS_MOD,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
@@ -136,6 +131,7 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 /*
@@ -146,7 +142,6 @@
 static struct powerdomain sgx_pwrdm = {
 	.name		  = "sgx_pwrdm",
 	.prcm_offs	  = OMAP3430ES2_SGX_MOD,
-	.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 = PWRSTS_RET,
@@ -157,11 +152,11 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain cam_pwrdm = {
 	.name		  = "cam_pwrdm",
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.prcm_offs	  = OMAP3430_CAM_MOD,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
@@ -172,12 +167,12 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain per_pwrdm = {
 	.name		  = "per_pwrdm",
 	.prcm_offs	  = OMAP3430_PER_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -187,26 +182,26 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain emu_pwrdm = {
 	.name		= "emu_pwrdm",
 	.prcm_offs	= OMAP3430_EMU_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain neon_pwrdm = {
 	.name		  = "neon_pwrdm",
 	.prcm_offs	  = OMAP3430_NEON_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
+	.voltdm           = { .name = "mpu_iva" },
 };
 
 static struct powerdomain usbhost_pwrdm = {
 	.name		  = "usbhost_pwrdm",
 	.prcm_offs	  = OMAP3430ES2_USBHOST_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
 	/*
@@ -223,65 +218,103 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain dpll1_pwrdm = {
 	.name		= "dpll1_pwrdm",
 	.prcm_offs	= MPU_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.voltdm           = { .name = "mpu_iva" },
 };
 
 static struct powerdomain dpll2_pwrdm = {
 	.name		= "dpll2_pwrdm",
 	.prcm_offs	= OMAP3430_IVA2_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.voltdm           = { .name = "mpu_iva" },
 };
 
 static struct powerdomain dpll3_pwrdm = {
 	.name		= "dpll3_pwrdm",
 	.prcm_offs	= PLL_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain dpll4_pwrdm = {
 	.name		= "dpll4_pwrdm",
 	.prcm_offs	= PLL_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain dpll5_pwrdm = {
 	.name		= "dpll5_pwrdm",
 	.prcm_offs	= PLL_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
+	.voltdm           = { .name = "core" },
 };
 
 /* As powerdomains are added or removed above, this list must also be changed */
-static struct powerdomain *powerdomains_omap3xxx[] __initdata = {
-
+static struct powerdomain *powerdomains_omap3430_common[] __initdata = {
 	&wkup_omap2_pwrdm,
-	&gfx_omap2_pwrdm,
 	&iva2_pwrdm,
 	&mpu_3xxx_pwrdm,
 	&neon_pwrdm,
-	&core_3xxx_pre_es3_1_pwrdm,
-	&core_3xxx_es3_1_pwrdm,
 	&cam_pwrdm,
 	&dss_pwrdm,
 	&per_pwrdm,
 	&emu_pwrdm,
-	&sgx_pwrdm,
-	&usbhost_pwrdm,
 	&dpll1_pwrdm,
 	&dpll2_pwrdm,
 	&dpll3_pwrdm,
 	&dpll4_pwrdm,
+	NULL
+};
+
+static struct powerdomain *powerdomains_omap3430es1[] __initdata = {
+	&gfx_omap2_pwrdm,
+	&core_3xxx_pre_es3_1_pwrdm,
+	NULL
+};
+
+/* also includes 3630ES1.0 */
+static struct powerdomain *powerdomains_omap3430es2_es3_0[] __initdata = {
+	&core_3xxx_pre_es3_1_pwrdm,
+	&sgx_pwrdm,
+	&usbhost_pwrdm,
 	&dpll5_pwrdm,
-#endif
 	NULL
 };
 
+/* also includes 3630ES1.1+ */
+static struct powerdomain *powerdomains_omap3430es3_1plus[] __initdata = {
+	&core_3xxx_es3_1_pwrdm,
+	&sgx_pwrdm,
+	&usbhost_pwrdm,
+	&dpll5_pwrdm,
+	NULL
+};
 
 void __init omap3xxx_powerdomains_init(void)
 {
-	pwrdm_init(powerdomains_omap3xxx, &omap3_pwrdm_operations);
+	unsigned int rev;
+
+	if (!cpu_is_omap34xx())
+		return;
+
+	pwrdm_register_platform_funcs(&omap3_pwrdm_operations);
+	pwrdm_register_pwrdms(powerdomains_omap3430_common);
+
+	rev = omap_rev();
+
+	if (rev == OMAP3430_REV_ES1_0)
+		pwrdm_register_pwrdms(powerdomains_omap3430es1);
+	else if (rev == OMAP3430_REV_ES2_0 || rev == OMAP3430_REV_ES2_1 ||
+		 rev == OMAP3430_REV_ES3_0 || rev == OMAP3630_REV_ES1_0)
+		pwrdm_register_pwrdms(powerdomains_omap3430es2_es3_0);
+	else if (rev == OMAP3430_REV_ES3_1 || rev == OMAP3430_REV_ES3_1_2 ||
+		 rev == OMAP3517_REV_ES1_0 || rev == OMAP3517_REV_ES1_1 ||
+		 rev == OMAP3630_REV_ES1_1 || rev == OMAP3630_REV_ES1_2)
+		pwrdm_register_pwrdms(powerdomains_omap3430es3_1plus);
+	else
+		WARN(1, "OMAP3 powerdomain init: unknown chip type\n");
+
+	pwrdm_complete_init();
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/powerdomains44xx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/powerdomains44xx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/powerdomains44xx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/powerdomains44xx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,9 +33,9 @@
 /* core_44xx_pwrdm: CORE power domain */
 static struct powerdomain core_44xx_pwrdm = {
 	.name		  = "core_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_CORE_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 5,
@@ -59,9 +59,9 @@
 /* gfx_44xx_pwrdm: 3D accelerator power domain */
 static struct powerdomain gfx_44xx_pwrdm = {
 	.name		  = "gfx_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_GFX_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
@@ -76,9 +76,9 @@
 /* abe_44xx_pwrdm: Audio back end power domain */
 static struct powerdomain abe_44xx_pwrdm = {
 	.name		  = "abe_pwrdm",
+	.voltdm		  = { .name = "iva" },
 	.prcm_offs	  = OMAP4430_PRM_ABE_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 2,
@@ -96,9 +96,9 @@
 /* dss_44xx_pwrdm: Display subsystem power domain */
 static struct powerdomain dss_44xx_pwrdm = {
 	.name		  = "dss_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_DSS_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 1,
@@ -114,9 +114,9 @@
 /* tesla_44xx_pwrdm: Tesla processor power domain */
 static struct powerdomain tesla_44xx_pwrdm = {
 	.name		  = "tesla_pwrdm",
+	.voltdm		  = { .name = "iva" },
 	.prcm_offs	  = OMAP4430_PRM_TESLA_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 3,
@@ -136,9 +136,9 @@
 /* wkup_44xx_pwrdm: Wake-up power domain */
 static struct powerdomain wkup_44xx_pwrdm = {
 	.name		  = "wkup_pwrdm",
+	.voltdm		  = { .name = "wakeup" },
 	.prcm_offs	  = OMAP4430_PRM_WKUP_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
@@ -152,9 +152,9 @@
 /* cpu0_44xx_pwrdm: MPU0 processor and Neon coprocessor power domain */
 static struct powerdomain cpu0_44xx_pwrdm = {
 	.name		  = "cpu0_pwrdm",
+	.voltdm		  = { .name = "mpu" },
 	.prcm_offs	  = OMAP4430_PRCM_MPU_CPU0_INST,
 	.prcm_partition	  = OMAP4430_PRCM_MPU_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -169,9 +169,9 @@
 /* cpu1_44xx_pwrdm: MPU1 processor and Neon coprocessor power domain */
 static struct powerdomain cpu1_44xx_pwrdm = {
 	.name		  = "cpu1_pwrdm",
+	.voltdm		  = { .name = "mpu" },
 	.prcm_offs	  = OMAP4430_PRCM_MPU_CPU1_INST,
 	.prcm_partition	  = OMAP4430_PRCM_MPU_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -186,9 +186,9 @@
 /* emu_44xx_pwrdm: Emulation power domain */
 static struct powerdomain emu_44xx_pwrdm = {
 	.name		  = "emu_pwrdm",
+	.voltdm		  = { .name = "wakeup" },
 	.prcm_offs	  = OMAP4430_PRM_EMU_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
@@ -202,9 +202,9 @@
 /* mpu_44xx_pwrdm: Modena processor and the Neon coprocessor power domain */
 static struct powerdomain mpu_44xx_pwrdm = {
 	.name		  = "mpu_pwrdm",
+	.voltdm		  = { .name = "mpu" },
 	.prcm_offs	  = OMAP4430_PRM_MPU_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 3,
@@ -223,9 +223,9 @@
 /* ivahd_44xx_pwrdm: IVA-HD power domain */
 static struct powerdomain ivahd_44xx_pwrdm = {
 	.name		  = "ivahd_pwrdm",
+	.voltdm		  = { .name = "iva" },
 	.prcm_offs	  = OMAP4430_PRM_IVAHD_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 4,
@@ -247,9 +247,9 @@
 /* cam_44xx_pwrdm: Camera subsystem power domain */
 static struct powerdomain cam_44xx_pwrdm = {
 	.name		  = "cam_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_CAM_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
@@ -264,9 +264,9 @@
 /* l3init_44xx_pwrdm: L3 initators pheripherals power domain  */
 static struct powerdomain l3init_44xx_pwrdm = {
 	.name		  = "l3init_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_L3INIT_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -282,9 +282,9 @@
 /* l4per_44xx_pwrdm: Target peripherals power domain */
 static struct powerdomain l4per_44xx_pwrdm = {
 	.name		  = "l4per_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_L4PER_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 2,
@@ -305,18 +305,18 @@
  */
 static struct powerdomain always_on_core_44xx_pwrdm = {
 	.name		  = "always_on_core_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_ALWAYS_ON_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_ON,
 };
 
 /* cefuse_44xx_pwrdm: Customer efuse controller power domain */
 static struct powerdomain cefuse_44xx_pwrdm = {
 	.name		  = "cefuse_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_CEFUSE_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -352,5 +352,7 @@
 
 void __init omap44xx_powerdomains_init(void)
 {
-	pwrdm_init(powerdomains_omap44xx, &omap4_pwrdm_operations);
+	pwrdm_register_platform_funcs(&omap4_pwrdm_operations);
+	pwrdm_register_pwrdms(powerdomains_omap44xx);
+	pwrdm_complete_init();
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/prcm.c linux-libre-3.2-gnu/arch/arm/mach-omap2/prcm.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/prcm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/prcm.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 
 #include <mach/system.h>
 #include <plat/common.h>
@@ -151,17 +152,10 @@
 
 void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals)
 {
-	/* Static mapping, never released */
-	if (omap2_globals->prm) {
-		prm_base = ioremap(omap2_globals->prm, SZ_8K);
-		WARN_ON(!prm_base);
-	}
-	if (omap2_globals->cm) {
-		cm_base = ioremap(omap2_globals->cm, SZ_8K);
-		WARN_ON(!cm_base);
-	}
-	if (omap2_globals->cm2) {
-		cm2_base = ioremap(omap2_globals->cm2, SZ_8K);
-		WARN_ON(!cm2_base);
-	}
+	if (omap2_globals->prm)
+		prm_base = omap2_globals->prm;
+	if (omap2_globals->cm)
+		cm_base = omap2_globals->cm;
+	if (omap2_globals->cm2)
+		cm2_base = omap2_globals->cm2;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/prm2xxx_3xxx.c linux-libre-3.2-gnu/arch/arm/mach-omap2/prm2xxx_3xxx.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/prm2xxx_3xxx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/prm2xxx_3xxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,8 @@
 #include <plat/cpu.h>
 #include <plat/prcm.h>
 
+#include "vp.h"
+
 #include "prm2xxx_3xxx.h"
 #include "cm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
@@ -156,3 +158,57 @@
 
 	return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
 }
+
+/* PRM VP */
+
+/*
+ * struct omap3_vp - OMAP3 VP register access description.
+ * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
+ */
+struct omap3_vp {
+	u32 tranxdone_status;
+};
+
+static struct omap3_vp omap3_vp[] = {
+	[OMAP3_VP_VDD_MPU_ID] = {
+		.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
+	},
+	[OMAP3_VP_VDD_CORE_ID] = {
+		.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
+	},
+};
+
+#define MAX_VP_ID ARRAY_SIZE(omap3_vp);
+
+u32 omap3_prm_vp_check_txdone(u8 vp_id)
+{
+	struct omap3_vp *vp = &omap3_vp[vp_id];
+	u32 irqstatus;
+
+	irqstatus = omap2_prm_read_mod_reg(OCP_MOD,
+					   OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+	return irqstatus & vp->tranxdone_status;
+}
+
+void omap3_prm_vp_clear_txdone(u8 vp_id)
+{
+	struct omap3_vp *vp = &omap3_vp[vp_id];
+
+	omap2_prm_write_mod_reg(vp->tranxdone_status,
+				OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+}
+
+u32 omap3_prm_vcvp_read(u8 offset)
+{
+	return omap2_prm_read_mod_reg(OMAP3430_GR_MOD, offset);
+}
+
+void omap3_prm_vcvp_write(u32 val, u8 offset)
+{
+	omap2_prm_write_mod_reg(val, OMAP3430_GR_MOD, offset);
+}
+
+u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
+{
+	return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/prm2xxx_3xxx.h linux-libre-3.2-gnu/arch/arm/mach-omap2/prm2xxx_3xxx.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/prm2xxx_3xxx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/prm2xxx_3xxx.h	2012-01-04 18:55:44.000000000 -0500
@@ -303,7 +303,19 @@
 extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
 extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift);
 
+/* OMAP3-specific VP functions */
+u32 omap3_prm_vp_check_txdone(u8 vp_id);
+void omap3_prm_vp_clear_txdone(u8 vp_id);
+
+/*
+ * OMAP3 access functions for voltage controller (VC) and
+ * voltage proccessor (VP) in the PRM.
+ */
+extern u32 omap3_prm_vcvp_read(u8 offset);
+extern void omap3_prm_vcvp_write(u32 val, u8 offset);
+extern u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
 #endif	/* CONFIG_ARCH_OMAP4 */
+
 #endif
 
 /*
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/prm44xx.c linux-libre-3.2-gnu/arch/arm/mach-omap2/prm44xx.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/prm44xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/prm44xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,8 +21,11 @@
 #include <plat/cpu.h>
 #include <plat/prcm.h>
 
+#include "vp.h"
 #include "prm44xx.h"
 #include "prm-regbits-44xx.h"
+#include "prcm44xx.h"
+#include "prminst44xx.h"
 
 /* PRM low-level functions */
 
@@ -50,3 +53,71 @@
 
 	return v;
 }
+
+/* PRM VP */
+
+/*
+ * struct omap4_vp - OMAP4 VP register access description.
+ * @irqstatus_mpu: offset to IRQSTATUS_MPU register for VP
+ * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
+ */
+struct omap4_vp {
+	u32 irqstatus_mpu;
+	u32 tranxdone_status;
+};
+
+static struct omap4_vp omap4_vp[] = {
+	[OMAP4_VP_VDD_MPU_ID] = {
+		.irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
+		.tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
+	},
+	[OMAP4_VP_VDD_IVA_ID] = {
+		.irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+		.tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
+	},
+	[OMAP4_VP_VDD_CORE_ID] = {
+		.irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+		.tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
+	},
+};
+
+u32 omap4_prm_vp_check_txdone(u8 vp_id)
+{
+	struct omap4_vp *vp = &omap4_vp[vp_id];
+	u32 irqstatus;
+
+	irqstatus = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+						OMAP4430_PRM_OCP_SOCKET_INST,
+						vp->irqstatus_mpu);
+	return irqstatus & vp->tranxdone_status;
+}
+
+void omap4_prm_vp_clear_txdone(u8 vp_id)
+{
+	struct omap4_vp *vp = &omap4_vp[vp_id];
+
+	omap4_prminst_write_inst_reg(vp->tranxdone_status,
+				     OMAP4430_PRM_PARTITION,
+				     OMAP4430_PRM_OCP_SOCKET_INST,
+				     vp->irqstatus_mpu);
+};
+
+u32 omap4_prm_vcvp_read(u8 offset)
+{
+	return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+					   OMAP4430_PRM_DEVICE_INST, offset);
+}
+
+void omap4_prm_vcvp_write(u32 val, u8 offset)
+{
+	omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION,
+				     OMAP4430_PRM_DEVICE_INST, offset);
+}
+
+u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
+{
+	return omap4_prminst_rmw_inst_reg_bits(mask, bits,
+					       OMAP4430_PRM_PARTITION,
+					       OMAP4430_PRM_DEVICE_INST,
+					       offset);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/prm44xx.h linux-libre-3.2-gnu/arch/arm/mach-omap2/prm44xx.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/prm44xx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/prm44xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -751,6 +751,18 @@
 extern void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 idx);
 extern u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
 
+/* OMAP4-specific VP functions */
+u32 omap4_prm_vp_check_txdone(u8 vp_id);
+void omap4_prm_vp_clear_txdone(u8 vp_id);
+
+/*
+ * OMAP4 access functions for voltage controller (VC) and
+ * voltage proccessor (VP) in the PRM.
+ */
+extern u32 omap4_prm_vcvp_read(u8 offset);
+extern void omap4_prm_vcvp_write(u32 val, u8 offset);
+extern u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
+
 # endif
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/sdrc.c linux-libre-3.2-gnu/arch/arm/mach-omap2/sdrc.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/sdrc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/sdrc.c	2012-01-04 18:55:44.000000000 -0500
@@ -117,15 +117,10 @@
 
 void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals)
 {
-	/* Static mapping, never released */
-	if (omap2_globals->sdrc) {
-		omap2_sdrc_base = ioremap(omap2_globals->sdrc, SZ_64K);
-		WARN_ON(!omap2_sdrc_base);
-	}
-	if (omap2_globals->sms) {
-		omap2_sms_base = ioremap(omap2_globals->sms, SZ_64K);
-		WARN_ON(!omap2_sms_base);
-	}
+	if (omap2_globals->sdrc)
+		omap2_sdrc_base = omap2_globals->sdrc;
+	if (omap2_globals->sms)
+		omap2_sms_base = omap2_globals->sms;
 }
 
 /**
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/serial.c linux-libre-3.2-gnu/arch/arm/mach-omap2/serial.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/serial.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/serial.c	2012-01-04 18:55:44.000000000 -0500
@@ -107,28 +107,6 @@
 static LIST_HEAD(uart_list);
 static u8 num_uarts;
 
-static int uart_idle_hwmod(struct omap_device *od)
-{
-	omap_hwmod_idle(od->hwmods[0]);
-
-	return 0;
-}
-
-static int uart_enable_hwmod(struct omap_device *od)
-{
-	omap_hwmod_enable(od->hwmods[0]);
-
-	return 0;
-}
-
-static struct omap_device_pm_latency omap_uart_latency[] = {
-	{
-		.deactivate_func = uart_idle_hwmod,
-		.activate_func	 = uart_enable_hwmod,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static inline unsigned int __serial_read_reg(struct uart_port *up,
 					     int offset)
 {
@@ -711,7 +689,7 @@
 {
 	struct omap_uart_state *uart;
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	void *pdata = NULL;
 	u32 pdata_size = 0;
 	char *name;
@@ -799,20 +777,19 @@
 	if (WARN_ON(!oh))
 		return;
 
-	od = omap_device_build(name, uart->num, oh, pdata, pdata_size,
-			       omap_uart_latency,
-			       ARRAY_SIZE(omap_uart_latency), false);
-	WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
+	pdev = omap_device_build(name, uart->num, oh, pdata, pdata_size,
+				 NULL, 0, false);
+	WARN(IS_ERR(pdev), "Could not build omap_device for %s: %s.\n",
 	     name, oh->name);
 
-	omap_device_disable_idle_on_suspend(od);
+	omap_device_disable_idle_on_suspend(pdev);
 	oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
 
 	uart->irq = oh->mpu_irqs[0].irq;
 	uart->regshift = 2;
 	uart->mapbase = oh->slaves[0]->addr->pa_start;
 	uart->membase = omap_hwmod_get_mpu_rt_va(oh);
-	uart->pdev = &od->pdev;
+	uart->pdev = pdev;
 
 	oh->dev_attr = uart;
 
@@ -846,8 +823,8 @@
 
 	if ((cpu_is_omap34xx() && uart->padconf) ||
 	    (uart->wk_en && uart->wk_mask)) {
-		device_init_wakeup(&od->pdev.dev, true);
-		DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout);
+		device_init_wakeup(&pdev->dev, true);
+		DEV_CREATE_FILE(&pdev->dev, &dev_attr_sleep_timeout);
 	}
 
 	/* Enable the MDR1 errata for OMAP3 */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/smartreflex.c linux-libre-3.2-gnu/arch/arm/mach-omap2/smartreflex.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/smartreflex.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/smartreflex.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/clk.h>
 #include <linux/io.h>
@@ -62,6 +63,7 @@
 
 static struct omap_sr_class_data *sr_class;
 static struct omap_sr_pmic_data *sr_pmic_data;
+static struct dentry		*sr_dbg_dir;
 
 static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
 {
@@ -137,7 +139,7 @@
 		sr_write_reg(sr_info, ERRCONFIG_V1, status);
 	} else if (sr_info->ip_type == SR_TYPE_V2) {
 		/* Read the status bits */
-		sr_read_reg(sr_info, IRQSTATUS);
+		status = sr_read_reg(sr_info, IRQSTATUS);
 
 		/* Clear them by writing back */
 		sr_write_reg(sr_info, IRQSTATUS, status);
@@ -247,7 +249,7 @@
  * driver register and sr device intializtion API's. Only one call
  * will ultimately succeed.
  *
- * Currently this function registers interrrupt handler for a particular SR
+ * Currently this function registers interrupt handler for a particular SR
  * if smartreflex class driver is already registered and has
  * requested for interrupts and the SR interrupt line in present.
  */
@@ -826,9 +828,10 @@
 	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, *nvalue_dir;
+	struct dentry *nvalue_dir;
 	struct omap_volt_data *volt_data;
 	int i, ret = 0;
+	char *name;
 
 	if (!sr_info) {
 		dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
@@ -899,18 +902,25 @@
 	}
 
 	dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__);
+	if (!sr_dbg_dir) {
+		sr_dbg_dir = debugfs_create_dir("smartreflex", NULL);
+		if (!sr_dbg_dir) {
+			ret = PTR_ERR(sr_dbg_dir);
+			pr_err("%s:sr debugfs dir creation failed(%d)\n",
+				__func__, ret);
+			goto err_iounmap;
+		}
+	}
 
-	/*
-	 * If the voltage domain debugfs directory is not created, do
-	 * not try to create rest of the debugfs entries.
-	 */
-	vdd_dbg_dir = omap_voltage_get_dbgdir(sr_info->voltdm);
-	if (!vdd_dbg_dir) {
-		ret = -EINVAL;
+	name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
+	if (!name) {
+		dev_err(&pdev->dev, "%s: Unable to alloc debugfs name\n",
+			__func__);
+		ret = -ENOMEM;
 		goto err_iounmap;
 	}
-
-	sr_info->dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir);
+	sr_info->dbg_dir = debugfs_create_dir(name, sr_dbg_dir);
+	kfree(name);
 	if (IS_ERR(sr_info->dbg_dir)) {
 		dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
 			__func__);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/smartreflex-class3.c linux-libre-3.2-gnu/arch/arm/mach-omap2/smartreflex-class3.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/smartreflex-class3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/smartreflex-class3.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
 
 static int sr_class3_enable(struct voltagedomain *voltdm)
 {
-	unsigned long volt = omap_voltage_get_nom_volt(voltdm);
+	unsigned long volt = voltdm_get_voltage(voltdm);
 
 	if (!volt) {
 		pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
@@ -32,7 +32,7 @@
 	omap_vp_disable(voltdm);
 	sr_disable(voltdm);
 	if (is_volt_reset)
-		omap_voltage_reset(voltdm);
+		voltdm_reset(voltdm);
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/sr_device.c linux-libre-3.2-gnu/arch/arm/mach-omap2/sr_device.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/sr_device.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/sr_device.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,14 +31,6 @@
 
 static bool sr_enable_on_init;
 
-static struct omap_device_pm_latency omap_sr_latency[] = {
-	{
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func	 = omap_device_enable_hwmods,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST
-	},
-};
-
 /* Read EFUSE values from control registers for OMAP3430 */
 static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
 				struct omap_sr_data *sr_data)
@@ -80,7 +72,7 @@
 static int sr_dev_init(struct omap_hwmod *oh, void *user)
 {
 	struct omap_sr_data *sr_data;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	struct omap_volt_data *volt_data;
 	char *name = "smartreflex";
 	static int i;
@@ -102,7 +94,7 @@
 	sr_data->senn_mod = 0x1;
 	sr_data->senp_mod = 0x1;
 
-	sr_data->voltdm = omap_voltage_domain_lookup(oh->vdd_name);
+	sr_data->voltdm = voltdm_lookup(oh->vdd_name);
 	if (IS_ERR(sr_data->voltdm)) {
 		pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
 			__func__, oh->vdd_name);
@@ -120,10 +112,9 @@
 
 	sr_data->enable_on_init = sr_enable_on_init;
 
-	od = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
-			       omap_sr_latency,
-			       ARRAY_SIZE(omap_sr_latency), 0);
-	if (IS_ERR(od))
+	pdev = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
+				 NULL, 0, 0);
+	if (IS_ERR(pdev))
 		pr_warning("%s: Could not build omap_device for %s: %s.\n\n",
 			__func__, name, oh->name);
 exit:
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/timer.c linux-libre-3.2-gnu/arch/arm/mach-omap2/timer.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <linux/irq.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/slab.h>
 
 #include <asm/mach/time.h>
 #include <plat/dmtimer.h>
@@ -42,6 +43,10 @@
 #include <asm/sched_clock.h>
 #include <plat/common.h>
 #include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
+
+#include "powerdomain.h"
 
 /* Parent clocks, eventually these will come from the clock framework */
 
@@ -67,7 +72,7 @@
 /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
 #define MAX_GPTIMER_ID		12
 
-u32 sys_timer_reserved;
+static u32 sys_timer_reserved;
 
 /* Clockevent code */
 
@@ -78,7 +83,7 @@
 {
 	struct clock_event_device *evt = &clockevent_gpt;
 
-	__omap_dm_timer_write_status(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
+	__omap_dm_timer_write_status(&clkev, OMAP_TIMER_INT_OVERFLOW);
 
 	evt->event_handler(evt);
 	return IRQ_HANDLED;
@@ -93,7 +98,7 @@
 static int omap2_gp_timer_set_next_event(unsigned long cycles,
 					 struct clock_event_device *evt)
 {
-	__omap_dm_timer_load_start(clkev.io_base, OMAP_TIMER_CTRL_ST,
+	__omap_dm_timer_load_start(&clkev, OMAP_TIMER_CTRL_ST,
 						0xffffffff - cycles, 1);
 
 	return 0;
@@ -104,16 +109,16 @@
 {
 	u32 period;
 
-	__omap_dm_timer_stop(clkev.io_base, 1, clkev.rate);
+	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 		period = clkev.rate / HZ;
 		period -= 1;
 		/* Looks like we need to first set the load value separately */
-		__omap_dm_timer_write(clkev.io_base, OMAP_TIMER_LOAD_REG,
+		__omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG,
 					0xffffffff - period, 1);
-		__omap_dm_timer_load_start(clkev.io_base,
+		__omap_dm_timer_load_start(&clkev,
 					OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
 						0xffffffff - period, 1);
 		break;
@@ -189,7 +194,8 @@
 			clk_put(src);
 		}
 	}
-	__omap_dm_timer_reset(timer->io_base, 1, 1);
+	__omap_dm_timer_init_regs(timer);
+	__omap_dm_timer_reset(timer, 1, 1);
 	timer->posted = 1;
 
 	timer->rate = clk_get_rate(timer->fclk);
@@ -210,7 +216,7 @@
 	omap2_gp_timer_irq.dev_id = (void *)&clkev;
 	setup_irq(clkev.irq, &omap2_gp_timer_irq);
 
-	__omap_dm_timer_int_enable(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
+	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
 
 	clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC,
 				     clockevent_gpt.shift);
@@ -251,7 +257,7 @@
 static DEFINE_CLOCK_DATA(cd);
 static cycle_t clocksource_read_cycles(struct clocksource *cs)
 {
-	return (cycle_t)__omap_dm_timer_read_counter(clksrc.io_base, 1);
+	return (cycle_t)__omap_dm_timer_read_counter(&clksrc, 1);
 }
 
 static struct clocksource clocksource_gpt = {
@@ -266,7 +272,7 @@
 {
 	u32 cyc;
 
-	cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
+	cyc = __omap_dm_timer_read_counter(&clksrc, 1);
 
 	update_sched_clock(&cd, cyc, (u32)~0);
 }
@@ -276,7 +282,7 @@
 	u32 cyc = 0;
 
 	if (clksrc.reserved)
-		cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
+		cyc = __omap_dm_timer_read_counter(&clksrc, 1);
 
 	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
 }
@@ -293,7 +299,7 @@
 	pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
 		gptimer_id, clksrc.rate);
 
-	__omap_dm_timer_load_start(clksrc.io_base,
+	__omap_dm_timer_load_start(&clksrc,
 			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
 	init_sched_clock(&cd, dmtimer_update_sched_clock, 32, clksrc.rate);
 
@@ -341,3 +347,157 @@
 }
 OMAP_SYS_TIMER(4)
 #endif
+
+/**
+ * omap2_dm_timer_set_src - change the timer input clock source
+ * @pdev:	timer platform device pointer
+ * @source:	array index of parent clock source
+ */
+static int omap2_dm_timer_set_src(struct platform_device *pdev, int source)
+{
+	int ret;
+	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
+	struct clk *fclk, *parent;
+	char *parent_name = NULL;
+
+	fclk = clk_get(&pdev->dev, "fck");
+	if (IS_ERR_OR_NULL(fclk)) {
+		dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
+				__func__, __LINE__);
+		return -EINVAL;
+	}
+
+	switch (source) {
+	case OMAP_TIMER_SRC_SYS_CLK:
+		parent_name = "sys_ck";
+		break;
+
+	case OMAP_TIMER_SRC_32_KHZ:
+		parent_name = "32k_ck";
+		break;
+
+	case OMAP_TIMER_SRC_EXT_CLK:
+		if (pdata->timer_ip_version == OMAP_TIMER_IP_VERSION_1) {
+			parent_name = "alt_ck";
+			break;
+		}
+		dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
+			__func__, __LINE__);
+		clk_put(fclk);
+		return -EINVAL;
+	}
+
+	parent = clk_get(&pdev->dev, parent_name);
+	if (IS_ERR_OR_NULL(parent)) {
+		dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
+			__func__, __LINE__, parent_name);
+		clk_put(fclk);
+		return -EINVAL;
+	}
+
+	ret = clk_set_parent(fclk, parent);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(&pdev->dev, "%s: clk_set_parent() to %s FAILED\n",
+			__func__, parent_name);
+		ret = -EINVAL;
+	}
+
+	clk_put(parent);
+	clk_put(fclk);
+
+	return ret;
+}
+
+/**
+ * omap_timer_init - build and register timer device with an
+ * associated timer hwmod
+ * @oh:	timer hwmod pointer to be used to build timer device
+ * @user:	parameter that can be passed from calling hwmod API
+ *
+ * Called by omap_hwmod_for_each_by_class to register each of the timer
+ * devices present in the system. The number of timer devices is known
+ * by parsing through the hwmod database for a given class name. At the
+ * end of function call memory is allocated for timer device and it is
+ * registered to the framework ready to be proved by the driver.
+ */
+static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
+{
+	int id;
+	int ret = 0;
+	char *name = "omap_timer";
+	struct dmtimer_platform_data *pdata;
+	struct platform_device *pdev;
+	struct omap_timer_capability_dev_attr *timer_dev_attr;
+	struct powerdomain *pwrdm;
+
+	pr_debug("%s: %s\n", __func__, oh->name);
+
+	/* on secure device, do not register secure timer */
+	timer_dev_attr = oh->dev_attr;
+	if (omap_type() != OMAP2_DEVICE_TYPE_GP && timer_dev_attr)
+		if (timer_dev_attr->timer_capability == OMAP_TIMER_SECURE)
+			return ret;
+
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("%s: No memory for [%s]\n", __func__, oh->name);
+		return -ENOMEM;
+	}
+
+	/*
+	 * Extract the IDs from name field in hwmod database
+	 * and use the same for constructing ids' for the
+	 * timer devices. In a way, we are avoiding usage of
+	 * static variable witin the function to do the same.
+	 * CAUTION: We have to be careful and make sure the
+	 * name in hwmod database does not change in which case
+	 * we might either make corresponding change here or
+	 * switch back static variable mechanism.
+	 */
+	sscanf(oh->name, "timer%2d", &id);
+
+	pdata->set_timer_src = omap2_dm_timer_set_src;
+	pdata->timer_ip_version = oh->class->rev;
+
+	/* Mark clocksource and clockevent timers as reserved */
+	if ((sys_timer_reserved >> (id - 1)) & 0x1)
+		pdata->reserved = 1;
+
+	pwrdm = omap_hwmod_get_pwrdm(oh);
+	pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm);
+#ifdef CONFIG_PM
+	pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
+#endif
+	pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
+				 NULL, 0, 0);
+
+	if (IS_ERR(pdev)) {
+		pr_err("%s: Can't build omap_device for %s: %s.\n",
+			__func__, name, oh->name);
+		ret = -EINVAL;
+	}
+
+	kfree(pdata);
+
+	return ret;
+}
+
+/**
+ * omap2_dm_timer_init - top level regular device initialization
+ *
+ * Uses dedicated hwmod api to parse through hwmod database for
+ * given class name and then build and register the timer device.
+ */
+static int __init omap2_dm_timer_init(void)
+{
+	int ret;
+
+	ret = omap_hwmod_for_each_by_class("timer", omap_timer_init, NULL);
+	if (unlikely(ret)) {
+		pr_err("%s: device registration failed.\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+arch_initcall(omap2_dm_timer_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/twl-common.c linux-libre-3.2-gnu/arch/arm/mach-omap2/twl-common.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/twl-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/twl-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <plat/usb.h>
 
 #include "twl-common.h"
+#include "pm.h"
 
 static struct i2c_board_info __initdata pmic_i2c_board_info = {
 	.addr		= 0x48,
@@ -48,6 +49,16 @@
 	omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1);
 }
 
+void __init omap_pmic_late_init(void)
+{
+	/* Init the OMAP TWL parameters (if PMIC has been registerd) */
+	if (!pmic_i2c_board_info.irq)
+		return;
+
+	omap3_twl_init();
+	omap4_twl_init();
+}
+
 #if defined(CONFIG_ARCH_OMAP3)
 static struct twl4030_usb_data omap3_usb_pdata = {
 	.usb_mode	= T2_USB_MODE_ULPI,
@@ -99,7 +110,7 @@
 
 static struct regulator_consumer_supply omap3_vpll2_supplies[] = {
 	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
 };
 
 static struct regulator_init_data omap3_vpll2_idata = {
@@ -235,6 +246,12 @@
 	},
 };
 
+static struct regulator_consumer_supply omap4_vcxio_supply[] = {
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dss"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.1"),
+};
+
 static struct regulator_init_data omap4_vcxio_idata = {
 	.constraints = {
 		.min_uV			= 1800000,
@@ -243,7 +260,10 @@
 					| REGULATOR_MODE_STANDBY,
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
+		.always_on		= true,
 	},
+	.num_consumer_supplies	= ARRAY_SIZE(omap4_vcxio_supply),
+	.consumer_supplies	= omap4_vcxio_supply,
 };
 
 static struct regulator_init_data omap4_vusb_idata = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/twl-common.h linux-libre-3.2-gnu/arch/arm/mach-omap2/twl-common.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/twl-common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/twl-common.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,8 @@
 #ifndef __OMAP_PMIC_COMMON__
 #define __OMAP_PMIC_COMMON__
 
+#include <plat/irqs.h>
+
 #define TWL_COMMON_PDATA_USB		(1 << 0)
 #define TWL_COMMON_PDATA_BCI		(1 << 1)
 #define TWL_COMMON_PDATA_MADC		(1 << 2)
@@ -30,6 +32,7 @@
 
 void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq,
 		    struct twl4030_platform_data *pmic_data);
+void omap_pmic_late_init(void);
 
 static inline void omap2_pmic_init(const char *pmic_type,
 				   struct twl4030_platform_data *pmic_data)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/usb-musb.c linux-libre-3.2-gnu/arch/arm/mach-omap2/usb-musb.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/usb-musb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/usb-musb.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,52 +60,6 @@
 
 static u64 musb_dmamask = DMA_BIT_MASK(32);
 
-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,
-	},
-};
-
-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;
-	}
-}
-
 static struct omap_musb_board_data musb_default_board_data = {
 	.interface_type		= MUSB_INTERFACE_ULPI,
 	.mode			= MUSB_OTG,
@@ -115,7 +69,6 @@
 void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
 {
 	struct omap_hwmod		*oh;
-	struct omap_device		*od;
 	struct platform_device		*pdev;
 	struct device			*dev;
 	int				bus_id = -1;
@@ -145,22 +98,19 @@
 		name = "musb-omap2430";
 	}
 
-	oh = omap_hwmod_lookup(oh_name);
-	if (!oh) {
-		pr_err("Could not look up %s\n", oh_name);
-		return;
-	}
+        oh = omap_hwmod_lookup(oh_name);
+        if (WARN(!oh, "%s: could not find omap_hwmod for %s\n",
+                 __func__, 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)) {
+	pdev = omap_device_build(name, bus_id, oh, &musb_plat,
+			       sizeof(musb_plat), NULL, 0, false);
+	if (IS_ERR(pdev)) {
 		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;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/usb-tusb6010.c linux-libre-3.2-gnu/arch/arm/mach-omap2/usb-tusb6010.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/usb-tusb6010.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/usb-tusb6010.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,11 +8,13 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/string.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/export.h>
 
 #include <linux/usb/musb.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/vc3xxx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/vc3xxx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/vc3xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/vc3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,9 +29,7 @@
  * 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,
+static struct omap_vc_common omap3_vc_common = {
 	.bypass_val_reg	 = OMAP3_PRM_VC_BYPASS_VAL_OFFSET,
 	.data_shift	 = OMAP3430_DATA_SHIFT,
 	.slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT,
@@ -42,22 +40,33 @@
 	.cmd_onlp_shift	 = OMAP3430_VC_CMD_ONLP_SHIFT,
 	.cmd_ret_shift	 = OMAP3430_VC_CMD_RET_SHIFT,
 	.cmd_off_shift	 = OMAP3430_VC_CMD_OFF_SHIFT,
+	.i2c_cfg_hsen_mask = OMAP3430_HSEN_MASK,
+	.i2c_cfg_reg	 = OMAP3_PRM_VC_I2C_CFG_OFFSET,
+	.i2c_mcode_mask	 = OMAP3430_MCODE_MASK,
 };
 
-struct omap_vc_instance_data omap3_vc1_data = {
-	.vc_common = &omap3_vc_common,
+struct omap_vc_channel omap3_vc_mpu = {
+	.common = &omap3_vc_common,
+	.smps_sa_reg	 = OMAP3_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg	 = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
+	.smps_cmdra_reg	 = OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET,
+	.cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET,
 	.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,
+	.smps_cmdra_mask = OMAP3430_CMDRA0_MASK,
+	.cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT,
 };
 
-struct omap_vc_instance_data omap3_vc2_data = {
-	.vc_common = &omap3_vc_common,
+struct omap_vc_channel omap3_vc_core = {
+	.common = &omap3_vc_common,
+	.smps_sa_reg	 = OMAP3_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg	 = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
+	.smps_cmdra_reg	 = OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET,
+	.cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET,
 	.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,
+	.smps_cmdra_mask = OMAP3430_CMDRA1_MASK,
+	.cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
 };
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/vc44xx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/vc44xx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/vc44xx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/vc44xx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,9 +30,7 @@
  * 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,
+static const struct omap_vc_common omap4_vc_common = {
 	.bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET,
 	.data_shift = OMAP4430_DATA_SHIFT,
 	.slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT,
@@ -43,33 +41,49 @@
 	.cmd_onlp_shift = OMAP4430_ONLP_SHIFT,
 	.cmd_ret_shift = OMAP4430_RET_SHIFT,
 	.cmd_off_shift = OMAP4430_OFF_SHIFT,
+	.i2c_cfg_reg = OMAP4_PRM_VC_CFG_I2C_MODE_OFFSET,
+	.i2c_cfg_hsen_mask = OMAP4430_HSMODEEN_MASK,
+	.i2c_mcode_mask	 = OMAP4430_HSMCODE_MASK,
 };
 
 /* VC instance data for each controllable voltage line */
-struct omap_vc_instance_data omap4_vc_mpu_data = {
-	.vc_common = &omap4_vc_common,
+struct omap_vc_channel omap4_vc_mpu = {
+	.flags = OMAP_VC_CHANNEL_DEFAULT | OMAP_VC_CHANNEL_CFG_MUTANT,
+	.common = &omap4_vc_common,
+	.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+	.smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
+	.cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
 	.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,
+	.smps_cmdra_mask = OMAP4430_CMDRA_VDD_MPU_L_MASK,
+	.cfg_channel_sa_shift = OMAP4430_SA_VDD_MPU_L_SHIFT,
 };
 
-struct omap_vc_instance_data omap4_vc_iva_data = {
-	.vc_common = &omap4_vc_common,
+struct omap_vc_channel omap4_vc_iva = {
+	.common = &omap4_vc_common,
+	.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+	.smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
+	.cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
 	.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,
+	.smps_cmdra_mask = OMAP4430_CMDRA_VDD_IVA_L_MASK,
+	.cfg_channel_sa_shift = OMAP4430_SA_VDD_IVA_L_SHIFT,
 };
 
-struct omap_vc_instance_data omap4_vc_core_data = {
-	.vc_common = &omap4_vc_common,
+struct omap_vc_channel omap4_vc_core = {
+	.common = &omap4_vc_common,
+	.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+	.smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
+	.cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
 	.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,
+	.smps_cmdra_mask = OMAP4430_CMDRA_VDD_CORE_L_MASK,
+	.cfg_channel_sa_shift = OMAP4430_SA_VDD_CORE_L_SHIFT,
 };
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/vc.c linux-libre-3.2-gnu/arch/arm/mach-omap2/vc.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/vc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/vc.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,367 @@
+/*
+ * OMAP Voltage Controller (VC) interface
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <plat/cpu.h>
+
+#include "voltage.h"
+#include "vc.h"
+#include "prm-regbits-34xx.h"
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+
+/**
+ * struct omap_vc_channel_cfg - describe the cfg_channel bitfield
+ * @sa: bit for slave address
+ * @rav: bit for voltage configuration register
+ * @rac: bit for command configuration register
+ * @racen: enable bit for RAC
+ * @cmd: bit for command value set selection
+ *
+ * Channel configuration bits, common for OMAP3+
+ * OMAP3 register: PRM_VC_CH_CONF
+ * OMAP4 register: PRM_VC_CFG_CHANNEL
+ * OMAP5 register: PRM_VC_SMPS_<voltdm>_CONFIG
+ */
+struct omap_vc_channel_cfg {
+	u8 sa;
+	u8 rav;
+	u8 rac;
+	u8 racen;
+	u8 cmd;
+};
+
+static struct omap_vc_channel_cfg vc_default_channel_cfg = {
+	.sa    = BIT(0),
+	.rav   = BIT(1),
+	.rac   = BIT(2),
+	.racen = BIT(3),
+	.cmd   = BIT(4),
+};
+
+/*
+ * On OMAP3+, all VC channels have the above default bitfield
+ * configuration, except the OMAP4 MPU channel.  This appears
+ * to be a freak accident as every other VC channel has the
+ * default configuration, thus creating a mutant channel config.
+ */
+static struct omap_vc_channel_cfg vc_mutant_channel_cfg = {
+	.sa    = BIT(0),
+	.rav   = BIT(2),
+	.rac   = BIT(3),
+	.racen = BIT(4),
+	.cmd   = BIT(1),
+};
+
+static struct omap_vc_channel_cfg *vc_cfg_bits;
+#define CFG_CHANNEL_MASK 0x1f
+
+/**
+ * omap_vc_config_channel - configure VC channel to PMIC mappings
+ * @voltdm: pointer to voltagdomain defining the desired VC channel
+ *
+ * Configures the VC channel to PMIC mappings for the following
+ * PMIC settings
+ * - i2c slave address (SA)
+ * - voltage configuration address (RAV)
+ * - command configuration address (RAC) and enable bit (RACEN)
+ * - command values for ON, ONLP, RET and OFF (CMD)
+ *
+ * This function currently only allows flexible configuration of the
+ * non-default channel.  Starting with OMAP4, there are more than 2
+ * channels, with one defined as the default (on OMAP4, it's MPU.)
+ * Only the non-default channel can be configured.
+ */
+static int omap_vc_config_channel(struct voltagedomain *voltdm)
+{
+	struct omap_vc_channel *vc = voltdm->vc;
+
+	/*
+	 * For default channel, the only configurable bit is RACEN.
+	 * All others must stay at zero (see function comment above.)
+	 */
+	if (vc->flags & OMAP_VC_CHANNEL_DEFAULT)
+		vc->cfg_channel &= vc_cfg_bits->racen;
+
+	voltdm->rmw(CFG_CHANNEL_MASK << vc->cfg_channel_sa_shift,
+		    vc->cfg_channel << vc->cfg_channel_sa_shift,
+		    vc->cfg_channel_reg);
+
+	return 0;
+}
+
+/* Voltage scale and accessory APIs */
+int omap_vc_pre_scale(struct voltagedomain *voltdm,
+		      unsigned long target_volt,
+		      u8 *target_vsel, u8 *current_vsel)
+{
+	struct omap_vc_channel *vc = voltdm->vc;
+	u32 vc_cmdval;
+
+	/* Check if sufficient pmic info is available for this vdd */
+	if (!voltdm->pmic) {
+		pr_err("%s: Insufficient pmic info to scale the vdd_%s\n",
+			__func__, voltdm->name);
+		return -EINVAL;
+	}
+
+	if (!voltdm->pmic->uv_to_vsel) {
+		pr_err("%s: PMIC function to convert voltage in uV to"
+			"vsel not registered. Hence unable to scale voltage"
+			"for vdd_%s\n", __func__, voltdm->name);
+		return -ENODATA;
+	}
+
+	if (!voltdm->read || !voltdm->write) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return -EINVAL;
+	}
+
+	*target_vsel = voltdm->pmic->uv_to_vsel(target_volt);
+	*current_vsel = voltdm->pmic->uv_to_vsel(voltdm->nominal_volt);
+
+	/* Setting the ON voltage to the new target voltage */
+	vc_cmdval = voltdm->read(vc->cmdval_reg);
+	vc_cmdval &= ~vc->common->cmd_on_mask;
+	vc_cmdval |= (*target_vsel << vc->common->cmd_on_shift);
+	voltdm->write(vc_cmdval, vc->cmdval_reg);
+
+	omap_vp_update_errorgain(voltdm, target_volt);
+
+	return 0;
+}
+
+void omap_vc_post_scale(struct voltagedomain *voltdm,
+			unsigned long target_volt,
+			u8 target_vsel, u8 current_vsel)
+{
+	u32 smps_steps = 0, smps_delay = 0;
+
+	smps_steps = abs(target_vsel - current_vsel);
+	/* SMPS slew rate / step size. 2us added as buffer. */
+	smps_delay = ((smps_steps * voltdm->pmic->step_size) /
+			voltdm->pmic->slew_rate) + 2;
+	udelay(smps_delay);
+}
+
+/* vc_bypass_scale - VC bypass method of voltage scaling */
+int omap_vc_bypass_scale(struct voltagedomain *voltdm,
+			 unsigned long target_volt)
+{
+	struct omap_vc_channel *vc = voltdm->vc;
+	u32 loop_cnt = 0, retries_cnt = 0;
+	u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
+	u8 target_vsel, current_vsel;
+	int ret;
+
+	ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
+	if (ret)
+		return ret;
+
+	vc_valid = vc->common->valid;
+	vc_bypass_val_reg = vc->common->bypass_val_reg;
+	vc_bypass_value = (target_vsel << vc->common->data_shift) |
+		(vc->volt_reg_addr << vc->common->regaddr_shift) |
+		(vc->i2c_slave_addr << vc->common->slaveaddr_shift);
+
+	voltdm->write(vc_bypass_value, vc_bypass_val_reg);
+	voltdm->write(vc_bypass_value | vc_valid, vc_bypass_val_reg);
+
+	vc_bypass_value = voltdm->read(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
+	 * to be revisited.
+	 */
+	while (!(vc_bypass_value & vc_valid)) {
+		loop_cnt++;
+
+		if (retries_cnt > 10) {
+			pr_warning("%s: Retry count exceeded\n", __func__);
+			return -ETIMEDOUT;
+		}
+
+		if (loop_cnt > 50) {
+			retries_cnt++;
+			loop_cnt = 0;
+			udelay(10);
+		}
+		vc_bypass_value = voltdm->read(vc_bypass_val_reg);
+	}
+
+	omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
+	return 0;
+}
+
+static void __init omap3_vfsm_init(struct voltagedomain *voltdm)
+{
+	/*
+	 * Voltage Manager FSM parameters init
+	 * XXX This data should be passed in from the board file
+	 */
+	voltdm->write(OMAP3_CLKSETUP, OMAP3_PRM_CLKSETUP_OFFSET);
+	voltdm->write(OMAP3_VOLTOFFSET, OMAP3_PRM_VOLTOFFSET_OFFSET);
+	voltdm->write(OMAP3_VOLTSETUP2, OMAP3_PRM_VOLTSETUP2_OFFSET);
+}
+
+static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
+{
+	static bool is_initialized;
+
+	if (is_initialized)
+		return;
+
+	omap3_vfsm_init(voltdm);
+
+	is_initialized = true;
+}
+
+
+/* OMAP4 specific voltage init functions */
+static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
+{
+	static bool is_initialized;
+	u32 vc_val;
+
+	if (is_initialized)
+		return;
+
+	/* XXX These are magic numbers and do not belong! */
+	vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
+	voltdm->write(vc_val, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
+
+	is_initialized = true;
+}
+
+/**
+ * omap_vc_i2c_init - initialize I2C interface to PMIC
+ * @voltdm: voltage domain containing VC data
+ *
+ * Use PMIC supplied seetings for I2C high-speed mode and
+ * master code (if set) and program the VC I2C configuration
+ * register.
+ *
+ * The VC I2C configuration is common to all VC channels,
+ * so this function only configures I2C for the first VC
+ * channel registers.  All other VC channels will use the
+ * same configuration.
+ */
+static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
+{
+	struct omap_vc_channel *vc = voltdm->vc;
+	static bool initialized;
+	static bool i2c_high_speed;
+	u8 mcode;
+
+	if (initialized) {
+		if (voltdm->pmic->i2c_high_speed != i2c_high_speed)
+			pr_warn("%s: I2C config for all channels must match.",
+				__func__);
+		return;
+	}
+
+	i2c_high_speed = voltdm->pmic->i2c_high_speed;
+	if (i2c_high_speed)
+		voltdm->rmw(vc->common->i2c_cfg_hsen_mask,
+			    vc->common->i2c_cfg_hsen_mask,
+			    vc->common->i2c_cfg_reg);
+
+	mcode = voltdm->pmic->i2c_mcode;
+	if (mcode)
+		voltdm->rmw(vc->common->i2c_mcode_mask,
+			    mcode << __ffs(vc->common->i2c_mcode_mask),
+			    vc->common->i2c_cfg_reg);
+
+	initialized = true;
+}
+
+void __init omap_vc_init_channel(struct voltagedomain *voltdm)
+{
+	struct omap_vc_channel *vc = voltdm->vc;
+	u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
+	u32 val;
+
+	if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) {
+		pr_err("%s: PMIC info requried to configure vc for"
+			"vdd_%s not populated.Hence cannot initialize vc\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	if (!voltdm->read || !voltdm->write) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	vc->cfg_channel = 0;
+	if (vc->flags & OMAP_VC_CHANNEL_CFG_MUTANT)
+		vc_cfg_bits = &vc_mutant_channel_cfg;
+	else
+		vc_cfg_bits = &vc_default_channel_cfg;
+
+	/* get PMIC/board specific settings */
+	vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr;
+	vc->volt_reg_addr = voltdm->pmic->volt_reg_addr;
+	vc->cmd_reg_addr = voltdm->pmic->cmd_reg_addr;
+	vc->setup_time = voltdm->pmic->volt_setup_time;
+
+	/* Configure the i2c slave address for this VC */
+	voltdm->rmw(vc->smps_sa_mask,
+		    vc->i2c_slave_addr << __ffs(vc->smps_sa_mask),
+		    vc->smps_sa_reg);
+	vc->cfg_channel |= vc_cfg_bits->sa;
+
+	/*
+	 * Configure the PMIC register addresses.
+	 */
+	voltdm->rmw(vc->smps_volra_mask,
+		    vc->volt_reg_addr << __ffs(vc->smps_volra_mask),
+		    vc->smps_volra_reg);
+	vc->cfg_channel |= vc_cfg_bits->rav;
+
+	if (vc->cmd_reg_addr) {
+		voltdm->rmw(vc->smps_cmdra_mask,
+			    vc->cmd_reg_addr << __ffs(vc->smps_cmdra_mask),
+			    vc->smps_cmdra_reg);
+		vc->cfg_channel |= vc_cfg_bits->rac | vc_cfg_bits->racen;
+	}
+
+	/* Set up the on, inactive, retention and off voltage */
+	on_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->on_volt);
+	onlp_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->onlp_volt);
+	ret_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->ret_volt);
+	off_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->off_volt);
+	val = ((on_vsel << vc->common->cmd_on_shift) |
+	       (onlp_vsel << vc->common->cmd_onlp_shift) |
+	       (ret_vsel << vc->common->cmd_ret_shift) |
+	       (off_vsel << vc->common->cmd_off_shift));
+	voltdm->write(val, vc->cmdval_reg);
+	vc->cfg_channel |= vc_cfg_bits->cmd;
+
+	/* Channel configuration */
+	omap_vc_config_channel(voltdm);
+
+	/* Configure the setup times */
+	voltdm->rmw(voltdm->vfsm->voltsetup_mask,
+		    vc->setup_time << __ffs(voltdm->vfsm->voltsetup_mask),
+		    voltdm->vfsm->voltsetup_reg);
+
+	omap_vc_i2c_init(voltdm);
+
+	if (cpu_is_omap34xx())
+		omap3_vc_init_channel(voltdm);
+	else if (cpu_is_omap44xx())
+		omap4_vc_init_channel(voltdm);
+}
+
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/vc.h linux-libre-3.2-gnu/arch/arm/mach-omap2/vc.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/vc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/vc.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,12 +19,12 @@
 
 #include <linux/kernel.h>
 
+struct voltagedomain;
+
 /**
- * struct omap_vc_common_data - per-VC register/bitfield data
+ * struct omap_vc_common - 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
@@ -33,15 +33,16 @@
  * @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
+ * @i2c_cfg_reg: I2C configuration register offset
+ * @i2c_cfg_hsen_mask: high-speed mode bit field mask in I2C config register
+ * @i2c_mcode_mask: MCODE field mask for I2C config 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 {
+struct omap_vc_common {
 	u32 cmd_on_mask;
 	u32 valid;
-	u8 smps_sa_reg;
-	u8 smps_volra_reg;
 	u8 bypass_val_reg;
 	u8 data_shift;
 	u8 slaveaddr_shift;
@@ -50,34 +51,75 @@
 	u8 cmd_onlp_shift;
 	u8 cmd_ret_shift;
 	u8 cmd_off_shift;
+	u8 i2c_cfg_reg;
+	u8 i2c_cfg_hsen_mask;
+	u8 i2c_mcode_mask;
 };
 
+/* omap_vc_channel.flags values */
+#define OMAP_VC_CHANNEL_DEFAULT BIT(0)
+#define OMAP_VC_CHANNEL_CFG_MUTANT BIT(1)
+
 /**
- * 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
+ * struct omap_vc_channel - VC per-instance data
+ * @i2c_slave_addr: I2C slave address of PMIC for this VC channel
+ * @volt_reg_addr: voltage configuration register address
+ * @cmd_reg_addr: command configuration register address
+ * @setup_time: setup time (in sys_clk cycles) of regulator for this channel
+ * @cfg_channel: current value of VC channel configuration register
+ * @i2c_high_speed: whether or not to use I2C high-speed mode
  *
- * XXX It is not necessary to have both a *_mask and a *_shift -
- *     remove one
+ * @common: pointer to VC common data for this platform
+ * @smps_sa_mask: i2c slave address bitmask in the PRM_VC_SMPS_SA register
+ * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register
+ * @smps_cmdra_mask: CMDRA* bitmask in the PRM_VC_CMD_RA register
+ * @cmdval_reg: register for on/ret/off voltage level values for this channel
+ * @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
+ * @smps_cmdra_reg: Offset of PRM_VC_SMPS_CMD_RA reg from PRM start
+ * @cfg_channel_reg: VC channel configuration register
+ * @cfg_channel_sa_shift: bit shift for slave address cfg_channel register
+ * @flags: VC channel-specific flags (optional)
  */
-struct omap_vc_instance_data {
-	const struct omap_vc_common_data *vc_common;
+struct omap_vc_channel {
+	/* channel state */
+	u16 i2c_slave_addr;
+	u16 volt_reg_addr;
+	u16 cmd_reg_addr;
+	u16 setup_time;
+	u8 cfg_channel;
+	bool i2c_high_speed;
+
+	/* register access data */
+	const struct omap_vc_common *common;
 	u32 smps_sa_mask;
 	u32 smps_volra_mask;
+	u32 smps_cmdra_mask;
 	u8 cmdval_reg;
-	u8 smps_sa_shift;
-	u8 smps_volra_shift;
+	u8 smps_sa_reg;
+	u8 smps_volra_reg;
+	u8 smps_cmdra_reg;
+	u8 cfg_channel_reg;
+	u8 cfg_channel_sa_shift;
+	u8 flags;
 };
 
-extern struct omap_vc_instance_data omap3_vc1_data;
-extern struct omap_vc_instance_data omap3_vc2_data;
+extern struct omap_vc_channel omap3_vc_mpu;
+extern struct omap_vc_channel omap3_vc_core;
 
-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;
+extern struct omap_vc_channel omap4_vc_mpu;
+extern struct omap_vc_channel omap4_vc_iva;
+extern struct omap_vc_channel omap4_vc_core;
+
+void omap_vc_init_channel(struct voltagedomain *voltdm);
+int omap_vc_pre_scale(struct voltagedomain *voltdm,
+		      unsigned long target_volt,
+		      u8 *target_vsel, u8 *current_vsel);
+void omap_vc_post_scale(struct voltagedomain *voltdm,
+			unsigned long target_volt,
+			u8 target_vsel, u8 current_vsel);
+int omap_vc_bypass_scale(struct voltagedomain *voltdm,
+			 unsigned long target_volt);
 
 #endif
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/voltage.c linux-libre-3.2-gnu/arch/arm/mach-omap2/voltage.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/voltage.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/voltage.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,10 +21,11 @@
 
 #include <linux/delay.h>
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
 
 #include <plat/common.h>
 
@@ -36,839 +37,88 @@
 #include "control.h"
 
 #include "voltage.h"
+#include "powerdomain.h"
 
 #include "vc.h"
 #include "vp.h"
 
-#define VOLTAGE_DIR_SIZE	16
-
-
-static struct omap_vdd_info **vdd_info;
-
-/*
- * Number of scalable voltage domains.
- */
-static int nr_scalable_vdd;
-
-/* XXX document */
-static s16 prm_mod_offs;
-static s16 prm_irqst_ocp_mod_offs;
-
-static struct dentry *voltage_dir;
-
-/* Init function pointers */
-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)
-{
-	return omap2_prm_read_mod_reg(mod, offset);
-}
-
-static void omap3_voltage_write_reg(u32 val, u16 mod, u8 offset)
-{
-	omap2_prm_write_mod_reg(val, mod, offset);
-}
-
-static u32 omap4_voltage_read_reg(u16 mod, u8 offset)
-{
-	return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
-					mod, offset);
-}
-
-static void omap4_voltage_write_reg(u32 val, u16 mod, u8 offset)
-{
-	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)
-{
-	struct omap_vdd_info *vdd = (struct omap_vdd_info *) data;
-	u8 vsel;
-
-	if (!vdd) {
-		pr_warning("Wrong paramater passed\n");
-		return -EINVAL;
-	}
-
-	vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
-
-	if (!vdd->pmic_info->vsel_to_uv) {
-		pr_warning("PMIC function to convert vsel to voltage"
-			"in uV not registerd\n");
-		return -EINVAL;
-	}
-
-	*val = vdd->pmic_info->vsel_to_uv(vsel);
-	return 0;
-}
-
-static int nom_volt_debug_get(void *data, u64 *val)
-{
-	struct omap_vdd_info *vdd = (struct omap_vdd_info *) data;
-
-	if (!vdd) {
-		pr_warning("Wrong paramater passed\n");
-		return -EINVAL;
-	}
-
-	*val = omap_voltage_get_nom_volt(&vdd->voltdm);
-
-	return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(vp_volt_debug_fops, vp_volt_debug_get, NULL, "%llu\n");
-DEFINE_SIMPLE_ATTRIBUTE(nom_volt_debug_fops, nom_volt_debug_get, NULL,
-								"%llu\n");
-static void vp_latch_vsel(struct omap_vdd_info *vdd)
-{
-	u32 vpconfig;
-	unsigned long uvdc;
-	char vsel;
-
-	uvdc = omap_voltage_get_nom_volt(&vdd->voltdm);
-	if (!uvdc) {
-		pr_warning("%s: unable to find current voltage for vdd_%s\n",
-			__func__, vdd->voltdm.name);
-		return;
-	}
-
-	if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
-		pr_warning("%s: PMIC function to convert voltage in uV to"
-			" vsel not registered\n", __func__);
-		return;
-	}
-
-	vsel = vdd->pmic_info->uv_to_vsel(uvdc);
-
-	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, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	/* Trigger initVDD value copy to voltage processor */
-	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, prm_mod_offs, vdd->vp_data->vpconfig);
-}
-
-/* Generic voltage init functions */
-static void __init vp_init(struct omap_vdd_info *vdd)
-{
-	u32 vp_val;
-
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, vdd->voltdm.name);
-		return;
-	}
-
-	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_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_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_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)
-{
-	char *name;
-
-	name = kzalloc(VOLTAGE_DIR_SIZE, GFP_KERNEL);
-	if (!name) {
-		pr_warning("%s: Unable to allocate memory for debugfs"
-			" directory name for vdd_%s",
-			__func__, vdd->voltdm.name);
-		return;
-	}
-	strcpy(name, "vdd_");
-	strcat(name, vdd->voltdm.name);
-
-	vdd->debug_dir = debugfs_create_dir(name, voltage_dir);
-	kfree(name);
-	if (IS_ERR(vdd->debug_dir)) {
-		pr_warning("%s: Unable to create debugfs directory for"
-			" vdd_%s\n", __func__, vdd->voltdm.name);
-		vdd->debug_dir = NULL;
-		return;
-	}
-
-	(void) debugfs_create_x16("vp_errorgain", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vpconfig_errorgain));
-	(void) debugfs_create_x16("vp_smpswaittimemin", S_IRUGO,
-				vdd->debug_dir,
-				&(vdd->vp_rt_data.vstepmin_smpswaittimemin));
-	(void) debugfs_create_x8("vp_stepmin", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vstepmin_stepmin));
-	(void) debugfs_create_x16("vp_smpswaittimemax", S_IRUGO,
-				vdd->debug_dir,
-				&(vdd->vp_rt_data.vstepmax_smpswaittimemax));
-	(void) debugfs_create_x8("vp_stepmax", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vstepmax_stepmax));
-	(void) debugfs_create_x8("vp_vddmax", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vlimitto_vddmax));
-	(void) debugfs_create_x8("vp_vddmin", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vlimitto_vddmin));
-	(void) debugfs_create_x16("vp_timeout", S_IRUGO, vdd->debug_dir,
-				&(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,
-				vdd->debug_dir, (void *) vdd,
-				&nom_volt_debug_fops);
-}
-
-/* Voltage scale and accessory APIs */
-static int _pre_volt_scale(struct omap_vdd_info *vdd,
-		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;
-
-	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) {
-		pr_err("%s: Insufficient pmic info to scale the vdd_%s\n",
-			__func__, vdd->voltdm.name);
-		return -EINVAL;
-	}
-
-	if (!vdd->pmic_info->uv_to_vsel) {
-		pr_err("%s: PMIC function to convert voltage in uV to"
-			"vsel not registered. Hence unable to scale voltage"
-			"for vdd_%s\n", __func__, vdd->voltdm.name);
-		return -ENODATA;
-	}
-
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, vdd->voltdm.name);
-		return -EINVAL;
-	}
-
-	/* 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(prm_mod_offs, vdd->vp_data->voltage);
-
-	/* Setting the ON voltage to the new target voltage */
-	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(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;
-}
-
-static void _post_volt_scale(struct omap_vdd_info *vdd,
-		unsigned long target_volt, u8 target_vsel, u8 current_vsel)
-{
-	u32 smps_steps = 0, smps_delay = 0;
-
-	smps_steps = abs(target_vsel - current_vsel);
-	/* SMPS slew rate / step size. 2us added as buffer. */
-	smps_delay = ((smps_steps * vdd->pmic_info->step_size) /
-			vdd->pmic_info->slew_rate) + 2;
-	udelay(smps_delay);
-
-	vdd->curr_volt = target_volt;
-}
-
-/* vc_bypass_scale_voltage - VC bypass method of voltage scaling */
-static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,
-		unsigned long target_volt)
-{
-	u32 loop_cnt = 0, retries_cnt = 0;
-	u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
-	u8 target_vsel, current_vsel;
-	int ret;
-
-	ret = _pre_volt_scale(vdd, target_volt, &target_vsel, &current_vsel);
-	if (ret)
-		return ret;
-
-	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_data->vc_common->regaddr_shift) |
-			(vdd->pmic_info->i2c_slave_addr <<
-			vdd->vc_data->vc_common->slaveaddr_shift);
-
-	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(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
-	 * to be revisited.
-	 */
-	while (!(vc_bypass_value & vc_valid)) {
-		loop_cnt++;
-
-		if (retries_cnt > 10) {
-			pr_warning("%s: Retry count exceeded\n", __func__);
-			return -ETIMEDOUT;
-		}
-
-		if (loop_cnt > 50) {
-			retries_cnt++;
-			loop_cnt = 0;
-			udelay(10);
-		}
-		vc_bypass_value = vdd->read_reg(prm_mod_offs,
-						vc_bypass_val_reg);
-	}
-
-	_post_volt_scale(vdd, target_volt, target_vsel, current_vsel);
-	return 0;
-}
-
-/* VP force update method of voltage scaling */
-static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
-		unsigned long target_volt)
-{
-	u32 vpconfig;
-	u8 target_vsel, current_vsel, prm_irqst_reg;
-	int ret, timeout = 0;
-
-	ret = _pre_volt_scale(vdd, target_volt, &target_vsel, &current_vsel);
-	if (ret)
-		return ret;
-
-	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_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) {
-		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
-			"Voltage change aborted", __func__, vdd->voltdm.name);
-		return -ETIMEDOUT;
-	}
-
-	/* Configure for VP-Force Update */
-	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_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_data->vp_common->vpconfig_initvdd;
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	/* Force update of voltage */
-	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(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",
-			__func__, vdd->voltdm.name);
-
-	_post_volt_scale(vdd, target_volt, target_vsel, current_vsel);
-
-	/*
-	 * Disable TransactionDone interrupt , clear all status, clear
-	 * control registers
-	 */
-	timeout = 0;
-	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
-		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)
-		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
-			"to clear the TRANXDONE status\n",
-			__func__, vdd->voltdm.name);
-
-	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
-	/* Clear initVDD copy trigger bit */
-	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_data->vp_common->vpconfig_forceupdate;
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	return 0;
-}
-
-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);
-}
-
-static void __init omap3_vc_init(struct omap_vdd_info *vdd)
-{
-	static bool is_initialized;
-	u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
-	u32 vc_val;
-
-	if (is_initialized)
-		return;
-
-	/* 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_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
-	 * 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, prm_mod_offs,
-			OMAP3_PRM_VC_I2C_CFG_OFFSET);
-
-	omap3_vfsm_init(vdd);
-
-	is_initialized = true;
-}
-
-
-/* OMAP4 specific voltage init functions */
-static void __init omap4_vc_init(struct omap_vdd_info *vdd)
-{
-	static bool is_initialized;
-	u32 vc_val;
-
-	if (is_initialized)
-		return;
-
-	/* TODO: Configure setup times and CMD_VAL values*/
-
-	/*
-	 * Generic VC parameters init
-	 * XXX This data should be abstracted out
-	 */
-	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);
-
-	/* 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);
-
-	is_initialized = true;
-}
-
-static void __init omap_vc_init(struct omap_vdd_info *vdd)
-{
-	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);
-		return;
-	}
-
-	/* Set up the SMPS_SA(i2c slave address in VC */
-	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(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);
-
-	/* 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);
-
-	if (cpu_is_omap34xx())
-		omap3_vc_init(vdd);
-	else if (cpu_is_omap44xx())
-		omap4_vc_init(vdd);
-}
-
-static int __init omap_vdd_data_configure(struct omap_vdd_info *vdd)
-{
-	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);
-		goto ovdc_out;
-	}
-
-	if (IS_ERR_VALUE(_config_common_vdd_data(vdd)))
-		goto ovdc_out;
-
-	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;
-	}
-
-ovdc_out:
-	return ret;
-}
+static LIST_HEAD(voltdm_list);
 
 /* Public functions */
 /**
- * omap_voltage_get_nom_volt() - Gets the current non-auto-compensated voltage
- * @voltdm:	pointer to the VDD for which current voltage info is needed
- *
- * API to get the current non-auto-compensated voltage for a VDD.
- * Returns 0 in case of error else returns the current voltage for the VDD.
- */
-unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm)
-{
-	struct omap_vdd_info *vdd;
-
-	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
-		return 0;
-	}
-
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	return vdd->curr_volt;
-}
-
-/**
- * omap_vp_get_curr_volt() - API to get the current vp voltage.
- * @voltdm:	pointer to the VDD.
+ * voltdm_get_voltage() - Gets the current non-auto-compensated voltage
+ * @voltdm:	pointer to the voltdm for which current voltage info is needed
  *
- * This API returns the current voltage for the specified voltage processor
+ * API to get the current non-auto-compensated voltage for a voltage domain.
+ * Returns 0 in case of error else returns the current voltage.
  */
-unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)
+unsigned long voltdm_get_voltage(struct voltagedomain *voltdm)
 {
-	struct omap_vdd_info *vdd;
-	u8 curr_vsel;
-
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return 0;
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-	if (!vdd->read_reg) {
-		pr_err("%s: No read API for reading vdd_%s regs\n",
-			__func__, voltdm->name);
-		return 0;
-	}
-
-	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"
-			"in uV not registerd\n", __func__);
-		return 0;
-	}
-
-	return vdd->pmic_info->vsel_to_uv(curr_vsel);
-}
-
-/**
- * omap_vp_enable() - API to enable a particular VP
- * @voltdm:	pointer to the VDD whose VP is to be enabled.
- *
- * This API enables a particular voltage processor. Needed by the smartreflex
- * class drivers.
- */
-void omap_vp_enable(struct voltagedomain *voltdm)
-{
-	struct omap_vdd_info *vdd;
-	u32 vpconfig;
-
-	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
-		return;
-	}
-
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, voltdm->name);
-		return;
-	}
-
-	/* If VP is already enabled, do nothing. Return */
-	if (vdd->vp_enabled)
-		return;
-
-	vp_latch_vsel(vdd);
-
-	/* Enable VP */
-	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;
-}
-
-/**
- * omap_vp_disable() - API to disable a particular VP
- * @voltdm:	pointer to the VDD whose VP is to be disabled.
- *
- * This API disables a particular voltage processor. Needed by the smartreflex
- * class drivers.
- */
-void omap_vp_disable(struct voltagedomain *voltdm)
-{
-	struct omap_vdd_info *vdd;
-	u32 vpconfig;
-	int timeout;
-
-	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
-		return;
-	}
-
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, voltdm->name);
-		return;
-	}
-
-	/* If VP is already disabled, do nothing. Return */
-	if (!vdd->vp_enabled) {
-		pr_warning("%s: Trying to disable VP for vdd_%s when"
-			"it is already disabled\n", __func__, voltdm->name);
-		return;
-	}
-
-	/* Disable VP */
-	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(prm_mod_offs, vdd->vp_data->vstatus)),
-				VP_IDLE_TIMEOUT, timeout);
-
-	if (timeout >= VP_IDLE_TIMEOUT)
-		pr_warning("%s: vdd_%s idle timedout\n",
-			__func__, voltdm->name);
-
-	vdd->vp_enabled = false;
-
-	return;
+	return voltdm->nominal_volt;
 }
 
 /**
- * omap_voltage_scale_vdd() - API to scale voltage of a particular
- *				voltage domain.
- * @voltdm:	pointer to the VDD which is to be scaled.
- * @target_volt:	The target voltage of the voltage domain
+ * voltdm_scale() - API to scale voltage of a particular voltage domain.
+ * @voltdm: pointer to the voltage domain which is to be scaled.
+ * @target_volt: The target voltage of the voltage domain
  *
  * This API should be called by the kernel to do the voltage scaling
- * for a particular voltage domain during dvfs or any other situation.
+ * for a particular voltage domain during DVFS.
  */
-int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
-		unsigned long target_volt)
+int voltdm_scale(struct voltagedomain *voltdm,
+		 unsigned long target_volt)
 {
-	struct omap_vdd_info *vdd;
+	int ret;
 
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return -EINVAL;
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	if (!vdd->volt_scale) {
+	if (!voltdm->scale) {
 		pr_err("%s: No voltage scale API registered for vdd_%s\n",
 			__func__, voltdm->name);
 		return -ENODATA;
 	}
 
-	return vdd->volt_scale(vdd, target_volt);
+	ret = voltdm->scale(voltdm, target_volt);
+	if (!ret)
+		voltdm->nominal_volt = target_volt;
+
+	return ret;
 }
 
 /**
- * omap_voltage_reset() - Resets the voltage of a particular voltage domain
- *			to that of the current OPP.
- * @voltdm:	pointer to the VDD whose voltage is to be reset.
+ * voltdm_reset() - Resets the voltage of a particular voltage domain
+ *		    to that of the current OPP.
+ * @voltdm: pointer to the voltage domain 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 especially
  * while disabling any voltage compensation modules.
  */
-void omap_voltage_reset(struct voltagedomain *voltdm)
+void voltdm_reset(struct voltagedomain *voltdm)
 {
-	unsigned long target_uvdc;
+	unsigned long target_volt;
 
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return;
 	}
 
-	target_uvdc = omap_voltage_get_nom_volt(voltdm);
-	if (!target_uvdc) {
+	target_volt = voltdm_get_voltage(voltdm);
+	if (!target_volt) {
 		pr_err("%s: unable to find current voltage for vdd_%s\n",
 			__func__, voltdm->name);
 		return;
 	}
 
-	omap_voltage_scale_vdd(voltdm, target_uvdc);
+	voltdm_scale(voltdm, target_volt);
 }
 
 /**
@@ -884,18 +134,14 @@
  *
  */
 void omap_voltage_get_volttable(struct voltagedomain *voltdm,
-		struct omap_volt_data **volt_data)
+				struct omap_volt_data **volt_data)
 {
-	struct omap_vdd_info *vdd;
-
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return;
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	*volt_data = vdd->volt_data;
+	*volt_data = voltdm->volt_data;
 }
 
 /**
@@ -914,9 +160,8 @@
  * domain or if there is no matching entry.
  */
 struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
-		unsigned long volt)
+						 unsigned long volt)
 {
-	struct omap_vdd_info *vdd;
 	int i;
 
 	if (!voltdm || IS_ERR(voltdm)) {
@@ -924,17 +169,15 @@
 		return ERR_PTR(-EINVAL);
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	if (!vdd->volt_data) {
+	if (!voltdm->volt_data) {
 		pr_warning("%s: voltage table does not exist for vdd_%s\n",
 			__func__, voltdm->name);
 		return ERR_PTR(-ENODATA);
 	}
 
-	for (i = 0; vdd->volt_data[i].volt_nominal != 0; i++) {
-		if (vdd->volt_data[i].volt_nominal == volt)
-			return &vdd->volt_data[i];
+	for (i = 0; voltdm->volt_data[i].volt_nominal != 0; i++) {
+		if (voltdm->volt_data[i].volt_nominal == volt)
+			return &voltdm->volt_data[i];
 	}
 
 	pr_notice("%s: Unable to match the current voltage with the voltage"
@@ -947,54 +190,25 @@
  * omap_voltage_register_pmic() - API to register PMIC specific data
  * @voltdm:	pointer to the VDD for which the PMIC specific data is
  *		to be registered
- * @pmic_info:	the structure containing pmic info
+ * @pmic:	the structure containing pmic info
  *
  * This API is to be called by the SOC/PMIC file to specify the
- * pmic specific info as present in omap_volt_pmic_info structure.
+ * pmic specific info as present in omap_voltdm_pmic structure.
  */
 int omap_voltage_register_pmic(struct voltagedomain *voltdm,
-		struct omap_volt_pmic_info *pmic_info)
+			       struct omap_voltdm_pmic *pmic)
 {
-	struct omap_vdd_info *vdd;
-
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return -EINVAL;
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	vdd->pmic_info = pmic_info;
+	voltdm->pmic = pmic;
 
 	return 0;
 }
 
 /**
- * omap_voltage_get_dbgdir() - API to get pointer to the debugfs directory
- *				corresponding to a voltage domain.
- *
- * @voltdm:	pointer to the VDD whose debug directory is required.
- *
- * This API returns pointer to the debugfs directory corresponding
- * to the voltage domain. Should be used by drivers requiring to
- * add any debug entry for a particular voltage domain. Returns NULL
- * in case of error.
- */
-struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm)
-{
-	struct omap_vdd_info *vdd;
-
-	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
-		return NULL;
-	}
-
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	return vdd->debug_dir;
-}
-
-/**
  * omap_change_voltscale_method() - API to change the voltage scaling method.
  * @voltdm:	pointer to the VDD whose voltage scaling method
  *		has to be changed.
@@ -1005,23 +219,19 @@
  * defined in voltage.h
  */
 void omap_change_voltscale_method(struct voltagedomain *voltdm,
-		int voltscale_method)
+				  int voltscale_method)
 {
-	struct omap_vdd_info *vdd;
-
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return;
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
 	switch (voltscale_method) {
 	case VOLTSCALE_VPFORCEUPDATE:
-		vdd->volt_scale = vp_forceupdate_scale_voltage;
+		voltdm->scale = omap_vp_forceupdate_scale;
 		return;
 	case VOLTSCALE_VCBYPASS:
-		vdd->volt_scale = vc_bypass_scale_voltage;
+		voltdm->scale = omap_vc_bypass_scale;
 		return;
 	default:
 		pr_warning("%s: Trying to change the method of voltage scaling"
@@ -1030,77 +240,192 @@
 }
 
 /**
- * omap_voltage_domain_lookup() - API to get the voltage domain pointer
- * @name:	Name of the voltage domain
+ * omap_voltage_late_init() - Init the various voltage parameters
  *
- * This API looks up in the global vdd_info struct for the
- * existence of voltage domain <name>. If it exists, the API returns
- * a pointer to the voltage domain structure corresponding to the
- * VDD<name>. Else retuns error pointer.
+ * This API is to be called in the later stages of the
+ * system boot to init the voltage controller and
+ * voltage processors.
  */
-struct voltagedomain *omap_voltage_domain_lookup(char *name)
+int __init omap_voltage_late_init(void)
 {
-	int i;
+	struct voltagedomain *voltdm;
 
-	if (!vdd_info) {
-		pr_err("%s: Voltage driver init not yet happened.Faulting!\n",
+	if (list_empty(&voltdm_list)) {
+		pr_err("%s: Voltage driver support not added\n",
 			__func__);
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 	}
 
-	if (!name) {
-		pr_err("%s: No name to get the votage domain!\n", __func__);
-		return ERR_PTR(-EINVAL);
+	list_for_each_entry(voltdm, &voltdm_list, node) {
+		struct clk *sys_ck;
+
+		if (!voltdm->scalable)
+			continue;
+
+		sys_ck = clk_get(NULL, voltdm->sys_clk.name);
+		if (IS_ERR(sys_ck)) {
+			pr_warning("%s: Could not get sys clk.\n", __func__);
+			return -EINVAL;
+		}
+		voltdm->sys_clk.rate = clk_get_rate(sys_ck);
+		WARN_ON(!voltdm->sys_clk.rate);
+		clk_put(sys_ck);
+
+		if (voltdm->vc) {
+			voltdm->scale = omap_vc_bypass_scale;
+			omap_vc_init_channel(voltdm);
+		}
+
+		if (voltdm->vp) {
+			voltdm->scale = omap_vp_forceupdate_scale;
+			omap_vp_init(voltdm);
+		}
 	}
 
-	for (i = 0; i < nr_scalable_vdd; i++) {
-		if (!(strcmp(name, vdd_info[i]->voltdm.name)))
-			return &vdd_info[i]->voltdm;
+	return 0;
+}
+
+static struct voltagedomain *_voltdm_lookup(const char *name)
+{
+	struct voltagedomain *voltdm, *temp_voltdm;
+
+	voltdm = NULL;
+
+	list_for_each_entry(temp_voltdm, &voltdm_list, node) {
+		if (!strcmp(name, temp_voltdm->name)) {
+			voltdm = temp_voltdm;
+			break;
+		}
 	}
 
-	return ERR_PTR(-EINVAL);
+	return voltdm;
 }
 
 /**
- * omap_voltage_late_init() - Init the various voltage parameters
+ * voltdm_add_pwrdm - add a powerdomain to a voltagedomain
+ * @voltdm: struct voltagedomain * to add the powerdomain to
+ * @pwrdm: struct powerdomain * to associate with a voltagedomain
  *
- * This API is to be called in the later stages of the
- * system boot to init the voltage controller and
- * voltage processors.
+ * Associate the powerdomain @pwrdm with a voltagedomain @voltdm.  This
+ * enables the use of voltdm_for_each_pwrdm().  Returns -EINVAL if
+ * presented with invalid pointers; -ENOMEM if memory could not be allocated;
+ * or 0 upon success.
  */
-int __init omap_voltage_late_init(void)
+int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm)
 {
-	int i;
+	if (!voltdm || !pwrdm)
+		return -EINVAL;
 
-	if (!vdd_info) {
-		pr_err("%s: Voltage driver support not added\n",
-			__func__);
+	pr_debug("voltagedomain: associating powerdomain %s with voltagedomain "
+		 "%s\n", pwrdm->name, voltdm->name);
+
+	list_add(&pwrdm->voltdm_node, &voltdm->pwrdm_list);
+
+	return 0;
+}
+
+/**
+ * voltdm_for_each_pwrdm - call function for each pwrdm in a voltdm
+ * @voltdm: struct voltagedomain * to iterate over
+ * @fn: callback function *
+ *
+ * Call the supplied function @fn for each powerdomain in the
+ * voltagedomain @voltdm.  Returns -EINVAL if presented with invalid
+ * pointers; or passes along the last return value of the callback
+ * function, which should be 0 for success or anything else to
+ * indicate failure.
+ */
+int voltdm_for_each_pwrdm(struct voltagedomain *voltdm,
+			  int (*fn)(struct voltagedomain *voltdm,
+				    struct powerdomain *pwrdm))
+{
+	struct powerdomain *pwrdm;
+	int ret = 0;
+
+	if (!fn)
 		return -EINVAL;
-	}
 
-	voltage_dir = debugfs_create_dir("voltage", NULL);
-	if (IS_ERR(voltage_dir))
-		pr_err("%s: Unable to create voltage debugfs main dir\n",
-			__func__);
-	for (i = 0; i < nr_scalable_vdd; i++) {
-		if (omap_vdd_data_configure(vdd_info[i]))
-			continue;
-		omap_vc_init(vdd_info[i]);
-		vp_init(vdd_info[i]);
-		vdd_debugfs_init(vdd_info[i]);
+	list_for_each_entry(pwrdm, &voltdm->pwrdm_list, voltdm_node)
+		ret = (*fn)(voltdm, pwrdm);
+
+	return ret;
+}
+
+/**
+ * voltdm_for_each - call function on each registered voltagedomain
+ * @fn: callback function *
+ *
+ * Call the supplied function @fn for each registered voltagedomain.
+ * The callback function @fn can return anything but 0 to bail out
+ * early from the iterator.  Returns the last return value of the
+ * callback function, which should be 0 for success or anything else
+ * to indicate failure; or -EINVAL if the function pointer is null.
+ */
+int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user),
+		    void *user)
+{
+	struct voltagedomain *temp_voltdm;
+	int ret = 0;
+
+	if (!fn)
+		return -EINVAL;
+
+	list_for_each_entry(temp_voltdm, &voltdm_list, node) {
+		ret = (*fn)(temp_voltdm, user);
+		if (ret)
+			break;
 	}
 
-	return 0;
+	return ret;
 }
 
-/* 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)
+static int _voltdm_register(struct voltagedomain *voltdm)
 {
-	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;
+	if (!voltdm || !voltdm->name)
+		return -EINVAL;
+
+	INIT_LIST_HEAD(&voltdm->pwrdm_list);
+	list_add(&voltdm->node, &voltdm_list);
+
+	pr_debug("voltagedomain: registered %s\n", voltdm->name);
+
 	return 0;
 }
+
+/**
+ * voltdm_lookup - look up a voltagedomain by name, return a pointer
+ * @name: name of voltagedomain
+ *
+ * Find a registered voltagedomain by its name @name.  Returns a pointer
+ * to the struct voltagedomain if found, or NULL otherwise.
+ */
+struct voltagedomain *voltdm_lookup(const char *name)
+{
+	struct voltagedomain *voltdm ;
+
+	if (!name)
+		return NULL;
+
+	voltdm = _voltdm_lookup(name);
+
+	return voltdm;
+}
+
+/**
+ * voltdm_init - set up the voltagedomain layer
+ * @voltdm_list: array of struct voltagedomain pointers to register
+ *
+ * Loop through the array of voltagedomains @voltdm_list, registering all
+ * that are available on the current CPU. If voltdm_list is supplied
+ * and not null, all of the referenced voltagedomains will be
+ * registered.  No return value.
+ */
+void voltdm_init(struct voltagedomain **voltdms)
+{
+	struct voltagedomain **v;
+
+	if (voltdms) {
+		for (v = voltdms; *v; v++)
+			_voltdm_register(*v);
+	}
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/voltagedomains2xxx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/voltagedomains2xxx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/voltagedomains2xxx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/voltagedomains2xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,32 @@
+/*
+ * OMAP3 voltage domain data
+ *
+ * Copyright (C) 2011 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include "voltage.h"
+
+static struct voltagedomain omap2_voltdm_core = {
+	.name = "core",
+};
+
+static struct voltagedomain omap2_voltdm_wkup = {
+	.name = "wakeup",
+};
+
+static struct voltagedomain *voltagedomains_omap2[] __initdata = {
+	&omap2_voltdm_core,
+	&omap2_voltdm_wkup,
+	NULL,
+};
+
+void __init omap2xxx_voltagedomains_init(void)
+{
+	voltdm_init(voltagedomains_omap2);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/voltagedomains3xxx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/voltagedomains3xxx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/voltagedomains3xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/voltagedomains3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,65 +31,70 @@
  * VDD data
  */
 
-static const struct omap_vfsm_instance_data omap3_vdd1_vfsm_data = {
+static const struct omap_vfsm_instance omap3_vdd1_vfsm = {
 	.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 = {
+static const struct omap_vfsm_instance omap3_vdd2_vfsm = {
 	.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",
-	},
+static struct voltagedomain omap3_voltdm_mpu = {
+	.name = "mpu_iva",
+	.scalable = true,
+	.read = omap3_prm_vcvp_read,
+	.write = omap3_prm_vcvp_write,
+	.rmw = omap3_prm_vcvp_rmw,
+	.vc = &omap3_vc_mpu,
+	.vfsm = &omap3_vdd1_vfsm,
+	.vp = &omap3_vp_mpu,
 };
 
-/* OMAP3 VDD structures */
-static struct omap_vdd_info *omap3_vdd_info[] = {
-	&omap3_vdd1_info,
-	&omap3_vdd2_info,
+static struct voltagedomain omap3_voltdm_core = {
+	.name = "core",
+	.scalable = true,
+	.read = omap3_prm_vcvp_read,
+	.write = omap3_prm_vcvp_write,
+	.rmw = omap3_prm_vcvp_rmw,
+	.vc = &omap3_vc_core,
+	.vfsm = &omap3_vdd2_vfsm,
+	.vp = &omap3_vp_core,
 };
 
-/* 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;
+static struct voltagedomain omap3_voltdm_wkup = {
+	.name = "wakeup",
+};
 
-	if (!cpu_is_omap34xx())
-		return 0;
+static struct voltagedomain *voltagedomains_omap3[] __initdata = {
+	&omap3_voltdm_mpu,
+	&omap3_voltdm_core,
+	&omap3_voltdm_wkup,
+	NULL,
+};
+
+static const char *sys_clk_name __initdata = "sys_ck";
+
+void __init omap3xxx_voltagedomains_init(void)
+{
+	struct voltagedomain *voltdm;
+	int i;
 
 	/*
 	 * 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;
+		omap3_voltdm_mpu.volt_data = omap36xx_vddmpu_volt_data;
+		omap3_voltdm_core.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;
+		omap3_voltdm_mpu.volt_data = omap34xx_vddmpu_volt_data;
+		omap3_voltdm_core.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));
+	for (i = 0; voltdm = voltagedomains_omap3[i], voltdm; i++)
+		voltdm->sys_clk.name = sys_clk_name;
+
+	voltdm_init(voltagedomains_omap3);
 };
-core_initcall(omap3xxx_voltage_early_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/voltagedomains44xx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/voltagedomains44xx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/voltagedomains44xx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/voltagedomains44xx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,71 +32,80 @@
 #include "vc.h"
 #include "vp.h"
 
-static const struct omap_vfsm_instance_data omap4_vdd_mpu_vfsm_data = {
+static const struct omap_vfsm_instance omap4_vdd_mpu_vfsm = {
 	.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 omap4_vdd_iva_vfsm = {
+	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET,
 };
 
-static const struct omap_vfsm_instance_data omap4_vdd_iva_vfsm_data = {
-	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET,
+static const struct omap_vfsm_instance omap4_vdd_core_vfsm = {
+	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_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 struct voltagedomain omap4_voltdm_mpu = {
+	.name = "mpu",
+	.scalable = true,
+	.read = omap4_prm_vcvp_read,
+	.write = omap4_prm_vcvp_write,
+	.rmw = omap4_prm_vcvp_rmw,
+	.vc = &omap4_vc_mpu,
+	.vfsm = &omap4_vdd_mpu_vfsm,
+	.vp = &omap4_vp_mpu,
 };
 
-static const struct omap_vfsm_instance_data omap4_vdd_core_vfsm_data = {
-	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET,
+static struct voltagedomain omap4_voltdm_iva = {
+	.name = "iva",
+	.scalable = true,
+	.read = omap4_prm_vcvp_read,
+	.write = omap4_prm_vcvp_write,
+	.rmw = omap4_prm_vcvp_rmw,
+	.vc = &omap4_vc_iva,
+	.vfsm = &omap4_vdd_iva_vfsm,
+	.vp = &omap4_vp_iva,
 };
 
-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",
-	},
+static struct voltagedomain omap4_voltdm_core = {
+	.name = "core",
+	.scalable = true,
+	.read = omap4_prm_vcvp_read,
+	.write = omap4_prm_vcvp_write,
+	.rmw = omap4_prm_vcvp_rmw,
+	.vc = &omap4_vc_core,
+	.vfsm = &omap4_vdd_core_vfsm,
+	.vp = &omap4_vp_core,
 };
 
-/* OMAP4 VDD structures */
-static struct omap_vdd_info *omap4_vdd_info[] = {
-	&omap4_vdd_mpu_info,
-	&omap4_vdd_iva_info,
-	&omap4_vdd_core_info,
+static struct voltagedomain omap4_voltdm_wkup = {
+	.name = "wakeup",
 };
 
-/* 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;
+static struct voltagedomain *voltagedomains_omap4[] __initdata = {
+	&omap4_voltdm_mpu,
+	&omap4_voltdm_iva,
+	&omap4_voltdm_core,
+	&omap4_voltdm_wkup,
+	NULL,
+};
 
-	if (!cpu_is_omap44xx())
-		return 0;
+static const char *sys_clk_name __initdata = "sys_clkin_ck";
+
+void __init omap44xx_voltagedomains_init(void)
+{
+	struct voltagedomain *voltdm;
+	int i;
 
 	/*
 	 * 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;
+	omap4_voltdm_mpu.volt_data = omap44xx_vdd_mpu_volt_data;
+	omap4_voltdm_iva.volt_data = omap44xx_vdd_iva_volt_data;
+	omap4_voltdm_core.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));
+	for (i = 0; voltdm = voltagedomains_omap4[i], voltdm; i++)
+		voltdm->sys_clk.name = sys_clk_name;
+
+	voltdm_init(voltagedomains_omap4);
 };
-core_initcall(omap44xx_voltage_early_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/voltage.h linux-libre-3.2-gnu/arch/arm/mach-omap2/voltage.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/voltage.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/voltage.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
 #include "vc.h"
 #include "vp.h"
 
+struct powerdomain;
+
 /* XXX document */
 #define VOLTSCALE_VPFORCEUPDATE		1
 #define VOLTSCALE_VCBYPASS		2
@@ -32,29 +34,60 @@
 #define OMAP3_VOLTSETUP2	0xff
 
 /**
- * struct omap_vfsm_instance_data - per-voltage manager FSM register/bitfield
+ * struct omap_vfsm_instance - 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 {
+struct omap_vfsm_instance {
 	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.
+ * @name: Name of the voltage domain which can be used as a unique identifier.
+ * @scalable: Whether or not this voltage domain is scalable
+ * @node: list_head linking all voltage domains
+ * @pwrdm_list: list_head linking all powerdomains in this voltagedomain
+ * @vc: pointer to VC channel associated with this voltagedomain
+ * @vp: pointer to VP associated with this voltagedomain
+ * @read: read a VC/VP register
+ * @write: write a VC/VP register
+ * @read: read-modify-write a VC/VP register
+ * @sys_clk: system clock name/frequency, used for various timing calculations
+ * @scale: function used to scale the voltage of the voltagedomain
+ * @nominal_volt: current nominal voltage for this voltage domain
+ * @volt_data: voltage table having the distinct voltages supported
+ *             by the domain and other associated per voltage data.
  */
 struct voltagedomain {
 	char *name;
+	bool scalable;
+	struct list_head node;
+	struct list_head pwrdm_list;
+	struct omap_vc_channel *vc;
+	const struct omap_vfsm_instance *vfsm;
+	struct omap_vp_instance *vp;
+	struct omap_voltdm_pmic *pmic;
+
+	/* VC/VP register access functions: SoC specific */
+	u32 (*read) (u8 offset);
+	void (*write) (u32 val, u8 offset);
+	u32 (*rmw)(u32 mask, u32 bits, u8 offset);
+
+	union {
+		const char *name;
+		u32 rate;
+	} sys_clk;
+
+	int (*scale) (struct voltagedomain *voltdm,
+		      unsigned long target_volt);
+
+	u32 nominal_volt;
+	struct omap_volt_data *volt_data;
 };
 
 /**
@@ -77,13 +110,18 @@
 };
 
 /**
- * struct omap_volt_pmic_info - PMIC specific data required by voltage driver.
+ * struct omap_voltdm_pmic - PMIC specific data required by voltage driver.
  * @slew_rate:	PMIC slew rate (in uv/us)
  * @step_size:	PMIC voltage step size (in uv)
+ * @i2c_slave_addr: I2C slave address of PMIC
+ * @volt_reg_addr: voltage configuration register address
+ * @cmd_reg_addr: command (on, on-LP, ret, off) configuration register address
+ * @i2c_high_speed: whether VC uses I2C high-speed mode to PMIC
+ * @i2c_mcode: master code value for I2C high-speed preamble transmission
  * @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 {
+struct omap_voltdm_pmic {
 	int slew_rate;
 	int step_size;
 	u32 on_volt;
@@ -91,94 +129,44 @@
 	u32 ret_volt;
 	u32 off_volt;
 	u16 volt_setup_time;
+	u16 i2c_slave_addr;
+	u16 volt_reg_addr;
+	u16 cmd_reg_addr;
 	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;
+	bool i2c_high_speed;
+	u8 i2c_mcode;
 	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);
+			       struct omap_voltdm_pmic *pmic);
 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
 
+extern void omap2xxx_voltagedomains_init(void);
+extern void omap3xxx_voltagedomains_init(void);
+extern void omap44xx_voltagedomains_init(void);
+
+struct voltagedomain *voltdm_lookup(const char *name);
+void voltdm_init(struct voltagedomain **voltdm_list);
+int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm);
+int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user),
+		    void *user);
+int voltdm_for_each_pwrdm(struct voltagedomain *voltdm,
+			  int (*fn)(struct voltagedomain *voltdm,
+				    struct powerdomain *pwrdm));
+int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
+void voltdm_reset(struct voltagedomain *voltdm);
+unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/vp3xxx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/vp3xxx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/vp3xxx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/vp3xxx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,16 +25,20 @@
 #include "voltage.h"
 
 #include "vp.h"
+#include "prm2xxx_3xxx.h"
+
+static const struct omap_vp_ops omap3_vp_ops = {
+	.check_txdone = omap3_prm_vp_check_txdone,
+	.clear_txdone = omap3_prm_vp_clear_txdone,
+};
 
 /*
  * 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,
+static const struct omap_vp_common omap3_vp_common = {
+	.vpconfig_erroroffset_mask = OMAP3430_ERROROFFSET_MASK,
 	.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,
@@ -47,36 +51,29 @@
 	.vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT,
 	.vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT,
 	.vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT,
-};
+	.vpvoltage_mask = OMAP3430_VPVOLTAGE_MASK,
 
-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,
+	.ops = &omap3_vp_ops,
 };
 
-struct omap_vp_instance_data omap3_vp1_data = {
-	.vp_common = &omap3_vp_common,
+struct omap_vp_instance omap3_vp_mpu = {
+	.id = OMAP3_VP_VDD_MPU_ID,
+	.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,
+struct omap_vp_instance omap3_vp_core = {
+	.id = OMAP3_VP_VDD_CORE_ID,
+	.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-3.1-gnu/arch/arm/mach-omap2/vp44xx_data.c linux-libre-3.2-gnu/arch/arm/mach-omap2/vp44xx_data.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/vp44xx_data.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/vp44xx_data.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,15 +27,18 @@
 
 #include "vp.h"
 
+static const struct omap_vp_ops omap4_vp_ops = {
+	.check_txdone = omap4_prm_vp_check_txdone,
+	.clear_txdone = omap4_prm_vp_clear_txdone,
+};
+
 /*
  * 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,
+static const struct omap_vp_common omap4_vp_common = {
+	.vpconfig_erroroffset_mask = OMAP4430_ERROROFFSET_MASK,
 	.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,
@@ -48,53 +51,39 @@
 	.vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT,
 	.vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT,
 	.vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT,
+	.vpvoltage_mask = OMAP4430_VPVOLTAGE_MASK,
+	.ops = &omap4_vp_ops,
 };
 
-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,
+struct omap_vp_instance omap4_vp_mpu = {
+	.id = OMAP4_VP_VDD_MPU_ID,
+	.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,
+struct omap_vp_instance omap4_vp_iva = {
+	.id = OMAP4_VP_VDD_IVA_ID,
+	.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,
+struct omap_vp_instance omap4_vp_core = {
+	.id = OMAP4_VP_VDD_CORE_ID,
+	.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-3.1-gnu/arch/arm/mach-omap2/vp.c linux-libre-3.2-gnu/arch/arm/mach-omap2/vp.c
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/vp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/vp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,278 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "voltage.h"
+#include "vp.h"
+#include "prm-regbits-34xx.h"
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+
+static u32 _vp_set_init_voltage(struct voltagedomain *voltdm, u32 volt)
+{
+	struct omap_vp_instance *vp = voltdm->vp;
+	u32 vpconfig;
+	char vsel;
+
+	vsel = voltdm->pmic->uv_to_vsel(volt);
+
+	vpconfig = voltdm->read(vp->vpconfig);
+	vpconfig &= ~(vp->common->vpconfig_initvoltage_mask |
+		      vp->common->vpconfig_forceupdate |
+		      vp->common->vpconfig_initvdd);
+	vpconfig |= vsel << __ffs(vp->common->vpconfig_initvoltage_mask);
+	voltdm->write(vpconfig, vp->vpconfig);
+
+	/* Trigger initVDD value copy to voltage processor */
+	voltdm->write((vpconfig | vp->common->vpconfig_initvdd),
+		       vp->vpconfig);
+
+	/* Clear initVDD copy trigger bit */
+	voltdm->write(vpconfig, vp->vpconfig);
+
+	return vpconfig;
+}
+
+/* Generic voltage init functions */
+void __init omap_vp_init(struct voltagedomain *voltdm)
+{
+	struct omap_vp_instance *vp = voltdm->vp;
+	u32 val, sys_clk_rate, timeout, waittime;
+	u32 vddmin, vddmax, vstepmin, vstepmax;
+
+	if (!voltdm->read || !voltdm->write) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	vp->enabled = false;
+
+	/* Divide to avoid overflow */
+	sys_clk_rate = voltdm->sys_clk.rate / 1000;
+
+	timeout = (sys_clk_rate * voltdm->pmic->vp_timeout_us) / 1000;
+	vddmin = voltdm->pmic->vp_vddmin;
+	vddmax = voltdm->pmic->vp_vddmax;
+
+	waittime = ((voltdm->pmic->step_size / voltdm->pmic->slew_rate) *
+		    sys_clk_rate) / 1000;
+	vstepmin = voltdm->pmic->vp_vstepmin;
+	vstepmax = voltdm->pmic->vp_vstepmax;
+
+	/*
+	 * VP_CONFIG: error gain is not set here, it will be updated
+	 * on each scale, based on OPP.
+	 */
+	val = (voltdm->pmic->vp_erroroffset <<
+	       __ffs(voltdm->vp->common->vpconfig_erroroffset_mask)) |
+		vp->common->vpconfig_timeouten;
+	voltdm->write(val, vp->vpconfig);
+
+	/* VSTEPMIN */
+	val = (waittime << vp->common->vstepmin_smpswaittimemin_shift) |
+		(vstepmin <<  vp->common->vstepmin_stepmin_shift);
+	voltdm->write(val, vp->vstepmin);
+
+	/* VSTEPMAX */
+	val = (vstepmax << vp->common->vstepmax_stepmax_shift) |
+		(waittime << vp->common->vstepmax_smpswaittimemax_shift);
+	voltdm->write(val, vp->vstepmax);
+
+	/* VLIMITTO */
+	val = (vddmax << vp->common->vlimitto_vddmax_shift) |
+		(vddmin << vp->common->vlimitto_vddmin_shift) |
+		(timeout <<  vp->common->vlimitto_timeout_shift);
+	voltdm->write(val, vp->vlimitto);
+}
+
+int omap_vp_update_errorgain(struct voltagedomain *voltdm,
+			     unsigned long target_volt)
+{
+	struct omap_volt_data *volt_data;
+
+	if (!voltdm->vp)
+		return -EINVAL;
+
+	/* Get volt_data corresponding to target_volt */
+	volt_data = omap_voltage_get_voltdata(voltdm, target_volt);
+	if (IS_ERR(volt_data))
+		return -EINVAL;
+
+	/* Setting vp errorgain based on the voltage */
+	voltdm->rmw(voltdm->vp->common->vpconfig_errorgain_mask,
+		    volt_data->vp_errgain <<
+		    __ffs(voltdm->vp->common->vpconfig_errorgain_mask),
+		    voltdm->vp->vpconfig);
+
+	return 0;
+}
+
+/* VP force update method of voltage scaling */
+int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
+			      unsigned long target_volt)
+{
+	struct omap_vp_instance *vp = voltdm->vp;
+	u32 vpconfig;
+	u8 target_vsel, current_vsel;
+	int ret, timeout = 0;
+
+	ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
+	if (ret)
+		return ret;
+
+	/*
+	 * Clear all pending TransactionDone interrupt/status. Typical latency
+	 * is <3us
+	 */
+	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+		vp->common->ops->clear_txdone(vp->id);
+		if (!vp->common->ops->check_txdone(vp->id))
+			break;
+		udelay(1);
+	}
+	if (timeout >= VP_TRANXDONE_TIMEOUT) {
+		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
+			"Voltage change aborted", __func__, voltdm->name);
+		return -ETIMEDOUT;
+	}
+
+	vpconfig = _vp_set_init_voltage(voltdm, target_volt);
+
+	/* Force update of voltage */
+	voltdm->write(vpconfig | vp->common->vpconfig_forceupdate,
+		      voltdm->vp->vpconfig);
+
+	/*
+	 * Wait for TransactionDone. Typical latency is <200us.
+	 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
+	 */
+	timeout = 0;
+	omap_test_timeout(vp->common->ops->check_txdone(vp->id),
+			  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",
+			__func__, voltdm->name);
+
+	omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
+
+	/*
+	 * Disable TransactionDone interrupt , clear all status, clear
+	 * control registers
+	 */
+	timeout = 0;
+	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+		vp->common->ops->clear_txdone(vp->id);
+		if (!vp->common->ops->check_txdone(vp->id))
+			break;
+		udelay(1);
+	}
+
+	if (timeout >= VP_TRANXDONE_TIMEOUT)
+		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
+			"to clear the TRANXDONE status\n",
+			__func__, voltdm->name);
+
+	/* Clear force bit */
+	voltdm->write(vpconfig, vp->vpconfig);
+
+	return 0;
+}
+
+/**
+ * omap_vp_enable() - API to enable a particular VP
+ * @voltdm:	pointer to the VDD whose VP is to be enabled.
+ *
+ * This API enables a particular voltage processor. Needed by the smartreflex
+ * class drivers.
+ */
+void omap_vp_enable(struct voltagedomain *voltdm)
+{
+	struct omap_vp_instance *vp;
+	u32 vpconfig, volt;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not exist!\n", __func__);
+		return;
+	}
+
+	vp = voltdm->vp;
+	if (!voltdm->read || !voltdm->write) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	/* If VP is already enabled, do nothing. Return */
+	if (vp->enabled)
+		return;
+
+	volt = voltdm_get_voltage(voltdm);
+	if (!volt) {
+		pr_warning("%s: unable to find current voltage for %s\n",
+			   __func__, voltdm->name);
+		return;
+	}
+
+	vpconfig = _vp_set_init_voltage(voltdm, volt);
+
+	/* Enable VP */
+	vpconfig |= vp->common->vpconfig_vpenable;
+	voltdm->write(vpconfig, vp->vpconfig);
+
+	vp->enabled = true;
+}
+
+/**
+ * omap_vp_disable() - API to disable a particular VP
+ * @voltdm:	pointer to the VDD whose VP is to be disabled.
+ *
+ * This API disables a particular voltage processor. Needed by the smartreflex
+ * class drivers.
+ */
+void omap_vp_disable(struct voltagedomain *voltdm)
+{
+	struct omap_vp_instance *vp;
+	u32 vpconfig;
+	int timeout;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not exist!\n", __func__);
+		return;
+	}
+
+	vp = voltdm->vp;
+	if (!voltdm->read || !voltdm->write) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	/* If VP is already disabled, do nothing. Return */
+	if (!vp->enabled) {
+		pr_warning("%s: Trying to disable VP for vdd_%s when"
+			"it is already disabled\n", __func__, voltdm->name);
+		return;
+	}
+
+	/* Disable VP */
+	vpconfig = voltdm->read(vp->vpconfig);
+	vpconfig &= ~vp->common->vpconfig_vpenable;
+	voltdm->write(vpconfig, vp->vpconfig);
+
+	/*
+	 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
+	 */
+	omap_test_timeout((voltdm->read(vp->vstatus)),
+			  VP_IDLE_TIMEOUT, timeout);
+
+	if (timeout >= VP_IDLE_TIMEOUT)
+		pr_warning("%s: vdd_%s idle timedout\n",
+			__func__, voltdm->name);
+
+	vp->enabled = false;
+
+	return;
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-omap2/vp.h linux-libre-3.2-gnu/arch/arm/mach-omap2/vp.h
--- linux-libre-3.1-gnu/arch/arm/mach-omap2/vp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-omap2/vp.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,44 +19,60 @@
 
 #include <linux/kernel.h>
 
+struct voltagedomain;
+
+/*
+ * Voltage Processor (VP) identifiers
+ */
+#define OMAP3_VP_VDD_MPU_ID 0
+#define OMAP3_VP_VDD_CORE_ID 1
+#define OMAP4_VP_VDD_CORE_ID 0
+#define OMAP4_VP_VDD_IVA_ID 1
+#define OMAP4_VP_VDD_MPU_ID 2
+
 /* XXX document */
 #define VP_IDLE_TIMEOUT		200
 #define VP_TRANXDONE_TIMEOUT	300
 
+/**
+ * struct omap_vp_ops - per-VP operations
+ * @check_txdone: check for VP transaction done
+ * @clear_txdone: clear VP transaction done status
+ */
+struct omap_vp_ops {
+	u32 (*check_txdone)(u8 vp_id);
+	void (*clear_txdone)(u8 vp_id);
+};
 
 /**
- * struct omap_vp_common_data - register data common to all VDDs
+ * struct omap_vp_common - register data common to all VDDs
+ * @vpconfig_erroroffset_mask: ERROROFFSET bitmask in the PRM_VP*_CONFIG reg
  * @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_timeouten: 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!
+ * @vstepmin_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg
+ * @vstepmin_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg
+ * @vstepmax_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg
+ * @vstepmax_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg
+ * @vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg
+ * @vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg
+ * @vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg
+ * @vpvoltage_mask: VPVOLTAGE field mask in PRM_VP*_VOLTAGE reg
  */
-struct omap_vp_common_data {
+struct omap_vp_common {
+	u32 vpconfig_erroroffset_mask;
 	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 vpconfig_timeouten;
+	u8 vpconfig_initvdd;
+	u8 vpconfig_forceupdate;
+	u8 vpconfig_vpenable;
 	u8 vstepmin_stepmin_shift;
 	u8 vstepmin_smpswaittimemin_shift;
 	u8 vstepmax_stepmax_shift;
@@ -64,80 +80,49 @@
 	u8 vlimitto_vddmin_shift;
 	u8 vlimitto_vddmax_shift;
 	u8 vlimitto_timeout_shift;
-};
+	u8 vpvoltage_mask;
 
-/**
- * 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;
+	const struct omap_vp_ops *ops;
 };
 
 /**
- * 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
+ * struct omap_vp_instance - VP register offsets (per-VDD)
+ * @common: pointer to struct omap_vp_common * for this SoC
  * @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
+ * @id: Unique identifier for VP instance.
+ * @enabled: flag to keep track of whether vp is enabled or not
  *
  * 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;
+struct omap_vp_instance {
+	const struct omap_vp_common *common;
 	u8 vpconfig;
 	u8 vstepmin;
 	u8 vstepmax;
 	u8 vlimitto;
 	u8 vstatus;
 	u8 voltage;
+	u8 id;
+	bool enabled;
 };
 
-/**
- * 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 omap3_vp_mpu;
+extern struct omap_vp_instance omap3_vp_core;
 
-extern struct omap_vp_instance_data omap3_vp1_data;
-extern struct omap_vp_instance_data omap3_vp2_data;
+extern struct omap_vp_instance omap4_vp_mpu;
+extern struct omap_vp_instance omap4_vp_iva;
+extern struct omap_vp_instance omap4_vp_core;
 
-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;
+void omap_vp_init(struct voltagedomain *voltdm);
+void omap_vp_enable(struct voltagedomain *voltdm);
+void omap_vp_disable(struct voltagedomain *voltdm);
+int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
+			      unsigned long target_volt);
+int omap_vp_update_errorgain(struct voltagedomain *voltdm,
+			     unsigned long target_volt);
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/common.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/common.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -308,8 +308,8 @@
  * Many orion-based systems have buggy bootloader implementations.
  * This is a common fixup for bogus memory tags.
  */
-void __init tag_fixup_mem32(struct machine_desc *mdesc, struct tag *t,
-			    char **from, struct meminfo *meminfo)
+void __init tag_fixup_mem32(struct tag *t, char **from,
+			    struct meminfo *meminfo)
 {
 	for (; t->hdr.size; t = tag_next(t))
 		if (t->hdr.tag == ATAG_MEM &&
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/common.h linux-libre-3.2-gnu/arch/arm/mach-orion5x/common.h
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/common.h	2012-01-04 18:55:44.000000000 -0500
@@ -53,11 +53,9 @@
 struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
 int orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
 
-struct machine_desc;
 struct meminfo;
 struct tag;
-extern void __init tag_fixup_mem32(struct machine_desc *, struct tag *,
-				   char **, struct meminfo *);
+extern void __init tag_fixup_mem32(struct tag *, char **, struct meminfo *);
 
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/d2net-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/d2net-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/d2net-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/d2net-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -336,7 +336,7 @@
 
 #ifdef CONFIG_MACH_D2NET
 MACHINE_START(D2NET, "LaCie d2 Network")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= d2net_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
@@ -348,7 +348,7 @@
 
 #ifdef CONFIG_MACH_BIGDISK
 MACHINE_START(BIGDISK, "LaCie Big Disk Network")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= d2net_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/db88f5281-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/db88f5281-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/db88f5281-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/db88f5281-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -21,7 +21,6 @@
 #include <linux/mv643xx_eth.h>
 #include <linux/i2c.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -359,7 +358,7 @@
 
 MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
 	/* Maintainer: Tzachi Perelstein <tzachi@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= db88f5281_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/dns323-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/dns323-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/dns323-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/dns323-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
  * License, or (at your option) any later version.
  *
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -30,7 +30,6 @@
 #include <linux/phy.h>
 #include <linux/marvell_phy.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -730,7 +729,7 @@
 /* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */
 MACHINE_START(DNS323, "D-Link DNS-323")
 	/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= dns323_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/edmini_v2-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/edmini_v2-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/edmini_v2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/edmini_v2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -251,7 +251,7 @@
 /* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */
 MACHINE_START(EDMINI_V2, "LaCie Ethernet Disk mini V2")
 	/* Maintainer: Christopher Moore <moore@free.fr> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= edmini_v2_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-orion5x/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
 
 #include <mach/orion5x.h>
 
-	.macro  addruart, rp, rv
+	.macro  addruart, rp, rv, tmp
 	ldr	\rp, =ORION5X_REGS_PHYS_BASE
 	ldr	\rv, =ORION5X_REGS_VIRT_BASE
 	orr	\rp, \rp, #0x00012000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-orion5x/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-/*
- * arch/arm/mach-orion5x/include/mach/memory.h
- *
- * Marvell Orion memory definitions
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/irq.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/irq.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,12 +9,11 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/io.h>
-#include <asm/gpio.h>
 #include <mach/bridge-regs.h>
 #include <plat/irq.h>
 #include "common.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/kurobox_pro-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/kurobox_pro-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/kurobox_pro-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/kurobox_pro-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -21,7 +21,6 @@
 #include <linux/serial_reg.h>
 #include <linux/ata_platform.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -380,7 +379,7 @@
 #ifdef CONFIG_MACH_KUROBOX_PRO
 MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro")
 	/* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= kurobox_pro_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
@@ -393,7 +392,7 @@
 #ifdef CONFIG_MACH_LINKSTATION_PRO
 MACHINE_START(LINKSTATION_PRO, "Buffalo Linkstation Pro/Live")
 	/* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= kurobox_pro_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/ls-chl-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/ls-chl-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/ls-chl-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/ls-chl-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -318,7 +318,7 @@
 
 MACHINE_START(LINKSTATION_LSCHL, "Buffalo Linkstation LiveV3 (LS-CHL)")
 	/* Maintainer: Ash Hughes <ashley.hughes@blueyonder.co.uk> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= lschl_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/ls_hgl-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/ls_hgl-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/ls_hgl-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/ls_hgl-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -265,7 +265,7 @@
 
 MACHINE_START(LINKSTATION_LS_HGL, "Buffalo Linkstation LS-HGL")
 	/* Maintainer: Zhu Qingsen <zhuqs@cn.fujistu.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= ls_hgl_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/lsmini-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/lsmini-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/lsmini-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/lsmini-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -267,7 +267,7 @@
 #ifdef CONFIG_MACH_LINKSTATION_MINI
 MACHINE_START(LINKSTATION_MINI, "Buffalo Linkstation Mini")
 	/* Maintainer: Alexey Kopytko <alexey@kopytko.ru> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= lsmini_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-orion5x/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/mss2-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/mss2-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/mss2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/mss2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -261,7 +261,7 @@
 
 MACHINE_START(MSS2, "Maxtor Shared Storage II")
 	/* Maintainer: Sylver Bruneau <sylver.bruneau@googlemail.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= mss2_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/mv2120-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/mv2120-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/mv2120-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/mv2120-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -20,7 +20,6 @@
 #include <linux/i2c.h>
 #include <linux/ata_platform.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <mach/orion5x.h>
 #include "common.h"
@@ -229,7 +228,7 @@
 /* Warning: HP uses a wrong mach-type (=526) in their bootloader */
 MACHINE_START(MV2120, "HP Media Vault mv2120")
 	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= mv2120_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/net2big-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/net2big-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/net2big-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/net2big-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -419,7 +419,7 @@
 
 /* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */
 MACHINE_START(NET2BIG, "LaCie 2Big Network")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= net2big_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -18,7 +18,6 @@
 #include <linux/ethtool.h>
 #include <net/dsa.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/leds.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
@@ -169,7 +168,7 @@
 
 MACHINE_START(RD88F5181L_FXO, "Marvell Orion-VoIP FXO Reference Design")
 	/* Maintainer: Nicolas Pitre <nico@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= rd88f5181l_fxo_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -19,7 +19,6 @@
 #include <linux/i2c.h>
 #include <net/dsa.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/leds.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
@@ -181,7 +180,7 @@
 
 MACHINE_START(RD88F5181L_GE, "Marvell Orion-VoIP GE Reference Design")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= rd88f5181l_ge_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/rd88f5182-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/rd88f5182-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/rd88f5182-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/rd88f5182-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -20,7 +20,6 @@
 #include <linux/ata_platform.h>
 #include <linux/i2c.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/leds.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
@@ -306,7 +305,7 @@
 
 MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
 	/* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= rd88f5182_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -21,7 +21,6 @@
 #include <linux/ethtool.h>
 #include <net/dsa.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/leds.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
@@ -122,7 +121,7 @@
 
 MACHINE_START(RD88F6183AP_GE, "Marvell Orion-1-90 AP GE Reference Design")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= rd88f6183ap_ge_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/terastation_pro2-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/terastation_pro2-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/terastation_pro2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/terastation_pro2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -20,7 +20,6 @@
 #include <linux/i2c.h>
 #include <linux/serial_reg.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -358,7 +357,7 @@
 
 MACHINE_START(TERASTATION_PRO2, "Buffalo Terastation Pro II/Live")
 	/* Maintainer:  Sylver Bruneau <sylver.bruneau@googlemail.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= tsp2_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/ts209-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/ts209-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/ts209-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/ts209-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -23,7 +23,6 @@
 #include <linux/serial_reg.h>
 #include <linux/ata_platform.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -323,7 +322,7 @@
 
 MACHINE_START(TS209, "QNAP TS-109/TS-209")
 	/* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= qnap_ts209_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/ts409-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/ts409-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/ts409-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/ts409-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -25,7 +25,6 @@
 #include <linux/i2c.h>
 #include <linux/serial_reg.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -312,7 +311,7 @@
 
 MACHINE_START(TS409, "QNAP TS-409")
 	/* Maintainer:  Sylver Bruneau <sylver.bruneau@gmail.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= qnap_ts409_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/ts78xx-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/ts78xx-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/ts78xx-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/ts78xx-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -275,7 +275,7 @@
 		.partitions		= ts78xx_ts_nand_parts,
 		.nr_partitions		= ARRAY_SIZE(ts78xx_ts_nand_parts),
 		.chip_delay		= 15,
-		.options		= NAND_USE_FLASH_BBT,
+		.bbt_options		= NAND_BBT_USE_FLASH,
 	},
 	.ctrl	= {
 		/*
@@ -621,7 +621,7 @@
 
 MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC")
 	/* Maintainer: Alexander Clouter <alex@digriz.org.uk> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= ts78xx_init,
 	.map_io		= ts78xx_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/wnr854t-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/wnr854t-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/wnr854t-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/wnr854t-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -17,7 +17,6 @@
 #include <linux/ethtool.h>
 #include <net/dsa.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -173,7 +172,7 @@
 
 MACHINE_START(WNR854T, "Netgear WNR854T")
 	/* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= wnr854t_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-orion5x/wrt350n-v2-setup.c linux-libre-3.2-gnu/arch/arm/mach-orion5x/wrt350n-v2-setup.c
--- linux-libre-3.1-gnu/arch/arm/mach-orion5x/wrt350n-v2-setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-orion5x/wrt350n-v2-setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -20,7 +20,6 @@
 #include <linux/input.h>
 #include <net/dsa.h>
 #include <asm/mach-types.h>
-#include <asm/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -261,7 +260,7 @@
 
 MACHINE_START(WRT350N_V2, "Linksys WRT350N v2")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_machine	= wrt350n_v2_init,
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/common.c linux-libre-3.2-gnu/arch/arm/mach-picoxcell/common.c
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 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/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/hardware/vic.h>
+
+#include <mach/map.h>
+#include <mach/picoxcell_soc.h>
+
+#include "common.h"
+
+static void __init picoxcell_init_machine(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *picoxcell_dt_match[] = {
+	"picochip,pc3x2",
+	"picochip,pc3x3",
+	NULL
+};
+
+static const struct of_device_id vic_of_match[] __initconst = {
+	{ .compatible = "arm,pl192-vic" },
+	{ /* Sentinel */ }
+};
+
+static void __init picoxcell_init_irq(void)
+{
+	vic_init(IO_ADDRESS(PICOXCELL_VIC0_BASE), 0, ~0, 0);
+	vic_init(IO_ADDRESS(PICOXCELL_VIC1_BASE), 32, ~0, 0);
+	irq_domain_generate_simple(vic_of_match, PICOXCELL_VIC0_BASE, 0);
+	irq_domain_generate_simple(vic_of_match, PICOXCELL_VIC1_BASE, 32);
+}
+
+DT_MACHINE_START(PICOXCELL, "Picochip picoXcell")
+	.map_io		= picoxcell_map_io,
+	.nr_irqs	= ARCH_NR_IRQS,
+	.init_irq	= picoxcell_init_irq,
+	.timer		= &picoxcell_timer,
+	.init_machine	= picoxcell_init_machine,
+	.dt_compat	= picoxcell_dt_match,
+MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/common.h linux-libre-3.2-gnu/arch/arm/mach-picoxcell/common.h
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/common.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 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
+ */
+#ifndef __PICOXCELL_COMMON_H__
+#define __PICOXCELL_COMMON_H__
+
+#include <asm/mach/time.h>
+
+extern struct sys_timer picoxcell_timer;
+extern void picoxcell_map_io(void);
+
+#endif /* __PICOXCELL_COMMON_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 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.
+ *
+ * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
+ * accesses to the 8250.
+ */
+#include <linux/serial_reg.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#define UART_SHIFT 2
+
+		.macro	addruart, rp, rv, tmp
+		ldr	\rv, =PHYS_TO_IO(PICOXCELL_UART1_BASE)
+		ldr	\rp, =PICOXCELL_UART1_BASE
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #UART_TX << UART_SHIFT]
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldr	\rd, [\rx, #UART_LSR << UART_SHIFT]
+		and	\rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
+		teq	\rd, #UART_LSR_TEMT | UART_LSR_THRE
+		bne	1002b
+		.endm
+
+		/* The UART's don't have any flow control IO's wired up. */
+		.macro	waituart,rd,rx
+		.endm
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/entry-macro.S linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/entry-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/entry-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+/*
+ * entry-macro.S
+ *
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * Low-level IRQ helper macros for picoXcell 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>
+#include <mach/map.h>
+
+#define VA_VIC0		IO_ADDRESS(PICOXCELL_VIC0_BASE)
+#define VA_VIC1		IO_ADDRESS(PICOXCELL_VIC1_BASE)
+
+#include <asm/entry-macro-vic2.S>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+/* empty */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/hardware.h linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/hardware.h
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/hardware.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This file contains the hardware definitions of the picoXcell SoC 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <mach/picoxcell_soc.h>
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/io.h linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/io.h
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 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.
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+/* No ioports, but needed for driver compatibility. */
+#define __io(a)			__typesafe_io(a)
+/* No PCI possible on picoxcell. */
+#define __mem_pci(a)		(a)
+
+#endif /* __ASM_ARM_ARCH_IO_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/irqs.h linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/irqs.h
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This file contains the hardware definitions of the picoXcell SoC 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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_IRQS_H
+#define __MACH_IRQS_H
+
+#define ARCH_NR_IRQS			64
+#define NR_IRQS				(128 + ARCH_NR_IRQS)
+
+#define IRQ_VIC0_BASE			0
+#define IRQ_VIC1_BASE			32
+
+#endif /* __MACH_IRQS_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/map.h linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/map.h
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/map.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/map.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 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.
+ */
+#ifndef __PICOXCELL_MAP_H__
+#define __PICOXCELL_MAP_H__
+
+#define PHYS_TO_IO(x)		(((x) & 0x00ffffff) | 0xfe000000)
+
+#ifdef __ASSEMBLY__
+#define IO_ADDRESS(x)		PHYS_TO_IO((x))
+#else
+#define IO_ADDRESS(x)		(void __iomem __force *)(PHYS_TO_IO((x)))
+#endif
+
+#endif /* __PICOXCELL_MAP_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/memory.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+/* empty */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This file contains the hardware definitions of the picoXcell SoC 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 __PICOXCELL_SOC_H__
+#define __PICOXCELL_SOC_H__
+
+#define PICOXCELL_UART1_BASE		0x80230000
+#define PICOXCELL_PERIPH_BASE		0x80000000
+#define PICOXCELL_PERIPH_LENGTH		SZ_4M
+#define PICOXCELL_VIC0_BASE		0x80060000
+#define PICOXCELL_VIC1_BASE		0x80064000
+
+#endif /* __PICOXCELL_SOC_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/system.h linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/system.h
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 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.
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+static inline void arch_idle(void)
+{
+	/*
+	 * This should do all the clock switching and wait for interrupt
+	 * tricks.
+	 */
+	cpu_do_idle();
+}
+
+static inline void arch_reset(int mode, const char *cmd)
+{
+	/* Watchdog reset to go here. */
+}
+
+#endif /* __ASM_ARCH_SYSTEM_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/timex.h linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/timex.h
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/timex.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 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
+ */
+#ifndef __TIMEX_H__
+#define __TIMEX_H__
+
+/* Bogus value to allow the kernel to compile. */
+#define CLOCK_TICK_RATE		1000000
+
+#endif /* __TIMEX_H__ */
+
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/uncompress.h linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/uncompress.h
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 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
+ */
+#define putc(c)
+#define flush()
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/vmalloc.h linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/vmalloc.h
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/include/mach/vmalloc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 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.
+ */
+#define VMALLOC_END	0xfe000000UL
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/io.c linux-libre-3.2-gnu/arch/arm/mach-picoxcell/io.c
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/io.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 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/io.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/map.h>
+#include <mach/picoxcell_soc.h>
+
+#include "common.h"
+
+void __init picoxcell_map_io(void)
+{
+	struct map_desc io_map = {
+		.virtual	= PHYS_TO_IO(PICOXCELL_PERIPH_BASE),
+		.pfn		= __phys_to_pfn(PICOXCELL_PERIPH_BASE),
+		.length		= PICOXCELL_PERIPH_LENGTH,
+		.type		= MT_DEVICE,
+	};
+
+	iotable_init(&io_map, 1);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/Makefile linux-libre-3.2-gnu/arch/arm/mach-picoxcell/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,3 @@
+obj-y	:= common.o
+obj-y	+= time.o
+obj-y	+= io.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-picoxcell/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+zreladdr-y := 0x00008000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-picoxcell/time.c linux-libre-3.2-gnu/arch/arm/mach-picoxcell/time.c
--- linux-libre-3.1-gnu/arch/arm/mach-picoxcell/time.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-picoxcell/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 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/dw_apb_timer.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched.h>
+
+#include <asm/mach/time.h>
+#include <asm/sched_clock.h>
+
+#include "common.h"
+
+static void timer_get_base_and_rate(struct device_node *np,
+				    void __iomem **base, u32 *rate)
+{
+	*base = of_iomap(np, 0);
+
+	if (!*base)
+		panic("Unable to map regs for %s", np->name);
+
+	if (of_property_read_u32(np, "clock-freq", rate))
+		panic("No clock-freq property for %s", np->name);
+}
+
+static void picoxcell_add_clockevent(struct device_node *event_timer)
+{
+	void __iomem *iobase;
+	struct dw_apb_clock_event_device *ced;
+	u32 irq, rate;
+
+	irq = irq_of_parse_and_map(event_timer, 0);
+	if (irq == NO_IRQ)
+		panic("No IRQ for clock event timer");
+
+	timer_get_base_and_rate(event_timer, &iobase, &rate);
+
+	ced = dw_apb_clockevent_init(0, event_timer->name, 300, iobase, irq,
+				     rate);
+	if (!ced)
+		panic("Unable to initialise clockevent device");
+
+	dw_apb_clockevent_register(ced);
+}
+
+static void picoxcell_add_clocksource(struct device_node *source_timer)
+{
+	void __iomem *iobase;
+	struct dw_apb_clocksource *cs;
+	u32 rate;
+
+	timer_get_base_and_rate(source_timer, &iobase, &rate);
+
+	cs = dw_apb_clocksource_init(300, source_timer->name, iobase, rate);
+	if (!cs)
+		panic("Unable to initialise clocksource device");
+
+	dw_apb_clocksource_start(cs);
+	dw_apb_clocksource_register(cs);
+}
+
+static DEFINE_CLOCK_DATA(cd);
+static void __iomem *sched_io_base;
+
+unsigned long long notrace sched_clock(void)
+{
+	cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0;
+
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace picoxcell_update_sched_clock(void)
+{
+	cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0;
+
+	update_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static const struct of_device_id picoxcell_rtc_ids[] __initconst = {
+	{ .compatible = "picochip,pc3x2-rtc" },
+	{ /* Sentinel */ },
+};
+
+static void picoxcell_init_sched_clock(void)
+{
+	struct device_node *sched_timer;
+	u32 rate;
+
+	sched_timer = of_find_matching_node(NULL, picoxcell_rtc_ids);
+	if (!sched_timer)
+		panic("No RTC for sched clock to use");
+
+	timer_get_base_and_rate(sched_timer, &sched_io_base, &rate);
+	of_node_put(sched_timer);
+
+	init_sched_clock(&cd, picoxcell_update_sched_clock, 32, rate);
+}
+
+static const struct of_device_id picoxcell_timer_ids[] __initconst = {
+	{ .compatible = "picochip,pc3x2-timer" },
+	{},
+};
+
+static void __init picoxcell_timer_init(void)
+{
+	struct device_node *event_timer, *source_timer;
+
+	event_timer = of_find_matching_node(NULL, picoxcell_timer_ids);
+	if (!event_timer)
+		panic("No timer for clockevent");
+	picoxcell_add_clockevent(event_timer);
+
+	source_timer = of_find_matching_node(event_timer, picoxcell_timer_ids);
+	if (!source_timer)
+		panic("No timer for clocksource");
+	picoxcell_add_clocksource(source_timer);
+
+	of_node_put(source_timer);
+
+	picoxcell_init_sched_clock();
+}
+
+struct sys_timer picoxcell_timer = {
+	.init = picoxcell_timer_init,
+};
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pnx4008/core.c linux-libre-3.2-gnu/arch/arm/mach-pnx4008/core.c
--- linux-libre-3.1-gnu/arch/arm/mach-pnx4008/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pnx4008/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -264,7 +264,7 @@
 
 MACHINE_START(PNX4008, "Philips PNX4008")
 	/* Maintainer: MontaVista Software Inc. */
-	.boot_params		= 0x80000100,
+	.atag_offset		= 0x100,
 	.map_io 		= pnx4008_map_io,
 	.init_irq 		= pnx4008_init_irq,
 	.init_machine 		= pnx4008_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pnx4008/gpio.c linux-libre-3.2-gnu/arch/arm/mach-pnx4008/gpio.c
--- linux-libre-3.1-gnu/arch/arm/mach-pnx4008/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pnx4008/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,14 +13,13 @@
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
-
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/io.h>
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pnx4008.h>
 
 /* register definitions */
 #define PIO_VA_BASE	IO_ADDRESS(PNX4008_PIO_BASE)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pnx4008/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-pnx4008/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-pnx4008/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pnx4008/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *
 */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x00090000
 		add	\rv, \rp, #0xf4000000	@ virtual
 		add	\rp, \rp, #0x40000000	@ physical
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pnx4008/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-pnx4008/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-pnx4008/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pnx4008/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,241 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/include/mach/gpio.h
- *
- * PNX4008 GPIO driver - header file
- *
- * Author: Dmitry Chigirev <source@mvista.com>
- *
- * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
- * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef _PNX4008_GPIO_H_
-#define _PNX4008_GPIO_H_
-
-
-/* Block numbers */
-#define GPIO_IN		(0)
-#define GPIO_OUT		(0x100)
-#define GPIO_BID		(0x200)
-#define GPIO_RAM		(0x300)
-#define GPIO_MUX		(0x400)
-
-#define GPIO_TYPE_MASK(K) ((K) & 0x700)
-
-/* INPUT GPIOs */
-/* GPI */
-#define GPI_00		(GPIO_IN | 0)
-#define GPI_01		(GPIO_IN | 1)
-#define GPI_02   	(GPIO_IN | 2)
-#define GPI_03 	 	(GPIO_IN | 3)
-#define GPI_04   	(GPIO_IN | 4)
-#define GPI_05   	(GPIO_IN | 5)
-#define GPI_06   	(GPIO_IN | 6)
-#define GPI_07   	(GPIO_IN | 7)
-#define GPI_08   	(GPIO_IN | 8)
-#define GPI_09   	(GPIO_IN | 9)
-#define U1_RX 		(GPIO_IN | 15)
-#define U2_HTCS 	(GPIO_IN | 16)
-#define U2_RX	 	(GPIO_IN | 17)
-#define U3_RX		(GPIO_IN | 18)
-#define U4_RX		(GPIO_IN | 19)
-#define U5_RX		(GPIO_IN | 20)
-#define U6_IRRX 	(GPIO_IN | 21)
-#define U7_HCTS 	(GPIO_IN | 22)
-#define U7_RX		(GPIO_IN | 23)
-/* MISC IN */
-#define SPI1_DATIN	(GPIO_IN | 25)
-#define DISP_SYNC	(GPIO_IN | 26)
-#define SPI2_DATIN	(GPIO_IN | 27)
-#define GPI_11  	(GPIO_IN | 28)
-
-#define GPIO_IN_MASK   0x1eff83ff
-
-/* OUTPUT GPIOs */
-/* GPO */
-#define GPO_00		(GPIO_OUT | 0)
-#define GPO_01   	(GPIO_OUT | 1)
-#define GPO_02   	(GPIO_OUT | 2)
-#define GPO_03 	 	(GPIO_OUT | 3)
-#define GPO_04   	(GPIO_OUT | 4)
-#define GPO_05   	(GPIO_OUT | 5)
-#define GPO_06   	(GPIO_OUT | 6)
-#define GPO_07   	(GPIO_OUT | 7)
-#define GPO_08		(GPIO_OUT | 8)
-#define GPO_09   	(GPIO_OUT | 9)
-#define GPO_10   	(GPIO_OUT | 10)
-#define GPO_11 	 	(GPIO_OUT | 11)
-#define GPO_12   	(GPIO_OUT | 12)
-#define GPO_13   	(GPIO_OUT | 13)
-#define GPO_14   	(GPIO_OUT | 14)
-#define GPO_15   	(GPIO_OUT | 15)
-#define GPO_16  	(GPIO_OUT | 16)
-#define GPO_17 	 	(GPIO_OUT | 17)
-#define GPO_18   	(GPIO_OUT | 18)
-#define GPO_19   	(GPIO_OUT | 19)
-#define GPO_20   	(GPIO_OUT | 20)
-#define GPO_21   	(GPIO_OUT | 21)
-#define GPO_22   	(GPIO_OUT | 22)
-#define GPO_23   	(GPIO_OUT | 23)
-
-#define GPIO_OUT_MASK   0xffffff
-
-/* BIDIRECTIONAL GPIOs */
-/* RAM pins */
-#define RAM_D19		(GPIO_RAM | 0)
-#define RAM_D20  	(GPIO_RAM | 1)
-#define RAM_D21  	(GPIO_RAM | 2)
-#define RAM_D22 	(GPIO_RAM | 3)
-#define RAM_D23  	(GPIO_RAM | 4)
-#define RAM_D24  	(GPIO_RAM | 5)
-#define RAM_D25  	(GPIO_RAM | 6)
-#define RAM_D26  	(GPIO_RAM | 7)
-#define RAM_D27		(GPIO_RAM | 8)
-#define RAM_D28  	(GPIO_RAM | 9)
-#define RAM_D29  	(GPIO_RAM | 10)
-#define RAM_D30 	(GPIO_RAM | 11)
-#define RAM_D31  	(GPIO_RAM | 12)
-
-#define GPIO_RAM_MASK   0x1fff
-
-/* I/O pins */
-#define GPIO_00  	(GPIO_BID | 25)
-#define GPIO_01 	(GPIO_BID | 26)
-#define GPIO_02  	(GPIO_BID | 27)
-#define GPIO_03  	(GPIO_BID | 28)
-#define GPIO_04 	(GPIO_BID | 29)
-#define GPIO_05  	(GPIO_BID | 30)
-
-#define GPIO_BID_MASK   0x7e000000
-
-/* Non-GPIO multiplexed PIOs. For multiplexing with GPIO, please use GPIO macros */
-#define GPIO_SDRAM_SEL 	(GPIO_MUX | 3)
-
-#define GPIO_MUX_MASK   0x8
-
-/* Extraction/assembly macros */
-#define GPIO_BIT_MASK(K) ((K) & 0x1F)
-#define GPIO_BIT(K) (1 << GPIO_BIT_MASK(K))
-#define GPIO_ISMUX(K) ((GPIO_TYPE_MASK(K) == GPIO_MUX) && (GPIO_BIT(K) & GPIO_MUX_MASK))
-#define GPIO_ISRAM(K) ((GPIO_TYPE_MASK(K) == GPIO_RAM) && (GPIO_BIT(K) & GPIO_RAM_MASK))
-#define GPIO_ISBID(K) ((GPIO_TYPE_MASK(K) == GPIO_BID) && (GPIO_BIT(K) & GPIO_BID_MASK))
-#define GPIO_ISOUT(K) ((GPIO_TYPE_MASK(K) == GPIO_OUT) && (GPIO_BIT(K) & GPIO_OUT_MASK))
-#define GPIO_ISIN(K)  ((GPIO_TYPE_MASK(K) == GPIO_IN) && (GPIO_BIT(K) & GPIO_IN_MASK))
-
-/* Start Enable Pin Interrupts - table 58 page 66 */
-
-#define SE_PIN_BASE_INT   32
-
-#define SE_U7_RX_INT            63
-#define SE_U7_HCTS_INT          62
-#define SE_BT_CLKREQ_INT        61
-#define SE_U6_IRRX_INT          60
-/*59 unused*/
-#define SE_U5_RX_INT            58
-#define SE_GPI_11_INT           57
-#define SE_U3_RX_INT            56
-#define SE_U2_HCTS_INT          55
-#define SE_U2_RX_INT            54
-#define SE_U1_RX_INT            53
-#define SE_DISP_SYNC_INT        52
-/*51 unused*/
-#define SE_SDIO_INT_N           50
-#define SE_MSDIO_START_INT      49
-#define SE_GPI_06_INT           48
-#define SE_GPI_05_INT           47
-#define SE_GPI_04_INT           46
-#define SE_GPI_03_INT           45
-#define SE_GPI_02_INT           44
-#define SE_GPI_01_INT           43
-#define SE_GPI_00_INT           42
-#define SE_SYSCLKEN_PIN_INT     41
-#define SE_SPI1_DATAIN_INT      40
-#define SE_GPI_07_INT           39
-#define SE_SPI2_DATAIN_INT      38
-#define SE_GPI_10_INT           37
-#define SE_GPI_09_INT           36
-#define SE_GPI_08_INT           35
-/*34-32 unused*/
-
-/* Start Enable Internal Interrupts - table 57 page 65 */
-
-#define SE_INT_BASE_INT   0
-
-#define SE_TS_IRQ               31
-#define SE_TS_P_INT             30
-#define SE_TS_AUX_INT           29
-/*27-28 unused*/
-#define SE_USB_AHB_NEED_CLK_INT 26
-#define SE_MSTIMER_INT          25
-#define SE_RTC_INT              24
-#define SE_USB_NEED_CLK_INT     23
-#define SE_USB_INT              22
-#define SE_USB_I2C_INT          21
-#define SE_USB_OTG_TIMER_INT    20
-#define SE_USB_OTG_ATX_INT_N    19
-/*18 unused*/
-#define SE_DSP_GPIO4_INT        17
-#define SE_KEY_IRQ              16
-#define SE_DSP_SLAVEPORT_INT    15
-#define SE_DSP_GPIO1_INT        14
-#define SE_DSP_GPIO0_INT        13
-#define SE_DSP_AHB_INT          12
-/*11-6 unused*/
-#define SE_GPIO_05_INT          5
-#define SE_GPIO_04_INT          4
-#define SE_GPIO_03_INT          3
-#define SE_GPIO_02_INT          2
-#define SE_GPIO_01_INT          1
-#define SE_GPIO_00_INT          0
-
-#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F))
-
-#define START_INT_ER_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1)))
-#define START_INT_RSR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1)))
-#define START_INT_SR_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1)))
-#define START_INT_APR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1)))
-
-extern int pnx4008_gpio_register_pin(unsigned short pin);
-extern int pnx4008_gpio_unregister_pin(unsigned short pin);
-extern unsigned long pnx4008_gpio_read_pin(unsigned short pin);
-extern int pnx4008_gpio_write_pin(unsigned short pin, int output);
-extern int pnx4008_gpio_set_pin_direction(unsigned short pin, int output);
-extern int pnx4008_gpio_read_pin_direction(unsigned short pin);
-extern int pnx4008_gpio_set_pin_mux(unsigned short pin, int output);
-extern int pnx4008_gpio_read_pin_mux(unsigned short pin);
-
-static inline void start_int_umask(u8 irq)
-{
-	__raw_writel(__raw_readl(START_INT_ER_REG(irq)) |
-		     START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
-}
-
-static inline void start_int_mask(u8 irq)
-{
-	__raw_writel(__raw_readl(START_INT_ER_REG(irq)) &
-		     ~START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
-}
-
-static inline void start_int_ack(u8 irq)
-{
-	__raw_writel(START_INT_REG_BIT(irq), START_INT_RSR_REG(irq));
-}
-
-static inline void start_int_set_falling_edge(u8 irq)
-{
-	__raw_writel(__raw_readl(START_INT_APR_REG(irq)) &
-		     ~START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
-}
-
-static inline void start_int_set_rising_edge(u8 irq)
-{
-	__raw_writel(__raw_readl(START_INT_APR_REG(irq)) |
-		     START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
-}
-
-#endif				/* _PNX4008_GPIO_H_ */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h linux-libre-3.2-gnu/arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h
--- linux-libre-3.1-gnu/arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,241 @@
+/*
+ * arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h
+ *
+ * PNX4008 GPIO driver - header file
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
+ * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef _PNX4008_GPIO_H_
+#define _PNX4008_GPIO_H_
+
+
+/* Block numbers */
+#define GPIO_IN		(0)
+#define GPIO_OUT		(0x100)
+#define GPIO_BID		(0x200)
+#define GPIO_RAM		(0x300)
+#define GPIO_MUX		(0x400)
+
+#define GPIO_TYPE_MASK(K) ((K) & 0x700)
+
+/* INPUT GPIOs */
+/* GPI */
+#define GPI_00		(GPIO_IN | 0)
+#define GPI_01		(GPIO_IN | 1)
+#define GPI_02   	(GPIO_IN | 2)
+#define GPI_03 	 	(GPIO_IN | 3)
+#define GPI_04   	(GPIO_IN | 4)
+#define GPI_05   	(GPIO_IN | 5)
+#define GPI_06   	(GPIO_IN | 6)
+#define GPI_07   	(GPIO_IN | 7)
+#define GPI_08   	(GPIO_IN | 8)
+#define GPI_09   	(GPIO_IN | 9)
+#define U1_RX 		(GPIO_IN | 15)
+#define U2_HTCS 	(GPIO_IN | 16)
+#define U2_RX	 	(GPIO_IN | 17)
+#define U3_RX		(GPIO_IN | 18)
+#define U4_RX		(GPIO_IN | 19)
+#define U5_RX		(GPIO_IN | 20)
+#define U6_IRRX 	(GPIO_IN | 21)
+#define U7_HCTS 	(GPIO_IN | 22)
+#define U7_RX		(GPIO_IN | 23)
+/* MISC IN */
+#define SPI1_DATIN	(GPIO_IN | 25)
+#define DISP_SYNC	(GPIO_IN | 26)
+#define SPI2_DATIN	(GPIO_IN | 27)
+#define GPI_11  	(GPIO_IN | 28)
+
+#define GPIO_IN_MASK   0x1eff83ff
+
+/* OUTPUT GPIOs */
+/* GPO */
+#define GPO_00		(GPIO_OUT | 0)
+#define GPO_01   	(GPIO_OUT | 1)
+#define GPO_02   	(GPIO_OUT | 2)
+#define GPO_03 	 	(GPIO_OUT | 3)
+#define GPO_04   	(GPIO_OUT | 4)
+#define GPO_05   	(GPIO_OUT | 5)
+#define GPO_06   	(GPIO_OUT | 6)
+#define GPO_07   	(GPIO_OUT | 7)
+#define GPO_08		(GPIO_OUT | 8)
+#define GPO_09   	(GPIO_OUT | 9)
+#define GPO_10   	(GPIO_OUT | 10)
+#define GPO_11 	 	(GPIO_OUT | 11)
+#define GPO_12   	(GPIO_OUT | 12)
+#define GPO_13   	(GPIO_OUT | 13)
+#define GPO_14   	(GPIO_OUT | 14)
+#define GPO_15   	(GPIO_OUT | 15)
+#define GPO_16  	(GPIO_OUT | 16)
+#define GPO_17 	 	(GPIO_OUT | 17)
+#define GPO_18   	(GPIO_OUT | 18)
+#define GPO_19   	(GPIO_OUT | 19)
+#define GPO_20   	(GPIO_OUT | 20)
+#define GPO_21   	(GPIO_OUT | 21)
+#define GPO_22   	(GPIO_OUT | 22)
+#define GPO_23   	(GPIO_OUT | 23)
+
+#define GPIO_OUT_MASK   0xffffff
+
+/* BIDIRECTIONAL GPIOs */
+/* RAM pins */
+#define RAM_D19		(GPIO_RAM | 0)
+#define RAM_D20  	(GPIO_RAM | 1)
+#define RAM_D21  	(GPIO_RAM | 2)
+#define RAM_D22 	(GPIO_RAM | 3)
+#define RAM_D23  	(GPIO_RAM | 4)
+#define RAM_D24  	(GPIO_RAM | 5)
+#define RAM_D25  	(GPIO_RAM | 6)
+#define RAM_D26  	(GPIO_RAM | 7)
+#define RAM_D27		(GPIO_RAM | 8)
+#define RAM_D28  	(GPIO_RAM | 9)
+#define RAM_D29  	(GPIO_RAM | 10)
+#define RAM_D30 	(GPIO_RAM | 11)
+#define RAM_D31  	(GPIO_RAM | 12)
+
+#define GPIO_RAM_MASK   0x1fff
+
+/* I/O pins */
+#define GPIO_00  	(GPIO_BID | 25)
+#define GPIO_01 	(GPIO_BID | 26)
+#define GPIO_02  	(GPIO_BID | 27)
+#define GPIO_03  	(GPIO_BID | 28)
+#define GPIO_04 	(GPIO_BID | 29)
+#define GPIO_05  	(GPIO_BID | 30)
+
+#define GPIO_BID_MASK   0x7e000000
+
+/* Non-GPIO multiplexed PIOs. For multiplexing with GPIO, please use GPIO macros */
+#define GPIO_SDRAM_SEL 	(GPIO_MUX | 3)
+
+#define GPIO_MUX_MASK   0x8
+
+/* Extraction/assembly macros */
+#define GPIO_BIT_MASK(K) ((K) & 0x1F)
+#define GPIO_BIT(K) (1 << GPIO_BIT_MASK(K))
+#define GPIO_ISMUX(K) ((GPIO_TYPE_MASK(K) == GPIO_MUX) && (GPIO_BIT(K) & GPIO_MUX_MASK))
+#define GPIO_ISRAM(K) ((GPIO_TYPE_MASK(K) == GPIO_RAM) && (GPIO_BIT(K) & GPIO_RAM_MASK))
+#define GPIO_ISBID(K) ((GPIO_TYPE_MASK(K) == GPIO_BID) && (GPIO_BIT(K) & GPIO_BID_MASK))
+#define GPIO_ISOUT(K) ((GPIO_TYPE_MASK(K) == GPIO_OUT) && (GPIO_BIT(K) & GPIO_OUT_MASK))
+#define GPIO_ISIN(K)  ((GPIO_TYPE_MASK(K) == GPIO_IN) && (GPIO_BIT(K) & GPIO_IN_MASK))
+
+/* Start Enable Pin Interrupts - table 58 page 66 */
+
+#define SE_PIN_BASE_INT   32
+
+#define SE_U7_RX_INT            63
+#define SE_U7_HCTS_INT          62
+#define SE_BT_CLKREQ_INT        61
+#define SE_U6_IRRX_INT          60
+/*59 unused*/
+#define SE_U5_RX_INT            58
+#define SE_GPI_11_INT           57
+#define SE_U3_RX_INT            56
+#define SE_U2_HCTS_INT          55
+#define SE_U2_RX_INT            54
+#define SE_U1_RX_INT            53
+#define SE_DISP_SYNC_INT        52
+/*51 unused*/
+#define SE_SDIO_INT_N           50
+#define SE_MSDIO_START_INT      49
+#define SE_GPI_06_INT           48
+#define SE_GPI_05_INT           47
+#define SE_GPI_04_INT           46
+#define SE_GPI_03_INT           45
+#define SE_GPI_02_INT           44
+#define SE_GPI_01_INT           43
+#define SE_GPI_00_INT           42
+#define SE_SYSCLKEN_PIN_INT     41
+#define SE_SPI1_DATAIN_INT      40
+#define SE_GPI_07_INT           39
+#define SE_SPI2_DATAIN_INT      38
+#define SE_GPI_10_INT           37
+#define SE_GPI_09_INT           36
+#define SE_GPI_08_INT           35
+/*34-32 unused*/
+
+/* Start Enable Internal Interrupts - table 57 page 65 */
+
+#define SE_INT_BASE_INT   0
+
+#define SE_TS_IRQ               31
+#define SE_TS_P_INT             30
+#define SE_TS_AUX_INT           29
+/*27-28 unused*/
+#define SE_USB_AHB_NEED_CLK_INT 26
+#define SE_MSTIMER_INT          25
+#define SE_RTC_INT              24
+#define SE_USB_NEED_CLK_INT     23
+#define SE_USB_INT              22
+#define SE_USB_I2C_INT          21
+#define SE_USB_OTG_TIMER_INT    20
+#define SE_USB_OTG_ATX_INT_N    19
+/*18 unused*/
+#define SE_DSP_GPIO4_INT        17
+#define SE_KEY_IRQ              16
+#define SE_DSP_SLAVEPORT_INT    15
+#define SE_DSP_GPIO1_INT        14
+#define SE_DSP_GPIO0_INT        13
+#define SE_DSP_AHB_INT          12
+/*11-6 unused*/
+#define SE_GPIO_05_INT          5
+#define SE_GPIO_04_INT          4
+#define SE_GPIO_03_INT          3
+#define SE_GPIO_02_INT          2
+#define SE_GPIO_01_INT          1
+#define SE_GPIO_00_INT          0
+
+#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F))
+
+#define START_INT_ER_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_RSR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_SR_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_APR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1)))
+
+extern int pnx4008_gpio_register_pin(unsigned short pin);
+extern int pnx4008_gpio_unregister_pin(unsigned short pin);
+extern unsigned long pnx4008_gpio_read_pin(unsigned short pin);
+extern int pnx4008_gpio_write_pin(unsigned short pin, int output);
+extern int pnx4008_gpio_set_pin_direction(unsigned short pin, int output);
+extern int pnx4008_gpio_read_pin_direction(unsigned short pin);
+extern int pnx4008_gpio_set_pin_mux(unsigned short pin, int output);
+extern int pnx4008_gpio_read_pin_mux(unsigned short pin);
+
+static inline void start_int_umask(u8 irq)
+{
+	__raw_writel(__raw_readl(START_INT_ER_REG(irq)) |
+		     START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
+}
+
+static inline void start_int_mask(u8 irq)
+{
+	__raw_writel(__raw_readl(START_INT_ER_REG(irq)) &
+		     ~START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
+}
+
+static inline void start_int_ack(u8 irq)
+{
+	__raw_writel(START_INT_REG_BIT(irq), START_INT_RSR_REG(irq));
+}
+
+static inline void start_int_set_falling_edge(u8 irq)
+{
+	__raw_writel(__raw_readl(START_INT_APR_REG(irq)) &
+		     ~START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
+}
+
+static inline void start_int_set_rising_edge(u8 irq)
+{
+	__raw_writel(__raw_readl(START_INT_APR_REG(irq)) |
+		     START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
+}
+
+#endif				/* _PNX4008_GPIO_H_ */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pnx4008/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-pnx4008/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-pnx4008/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pnx4008/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/include/mach/memory.h
- *
- * Copyright (c) 2005 Philips Semiconductors
- * Copyright (c) 2005 MontaVista Software, Inc.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0x80000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pnx4008/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-pnx4008/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-pnx4008/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pnx4008/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y		:= 0x80008000
+   zreladdr-y		+= 0x80008000
 params_phys-y		:= 0x80000100
 initrd_phys-y		:= 0x80800000
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pnx4008/serial.c linux-libre-3.2-gnu/arch/arm/mach-pnx4008/serial.c
--- linux-libre-3.1-gnu/arch/arm/mach-pnx4008/serial.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pnx4008/serial.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@
  *  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/io.h>
@@ -19,8 +18,8 @@
 
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
-#include <mach/gpio.h>
 
+#include <mach/gpio-pnx4008.h>
 #include <mach/clock.h>
 
 #define UART_3		0
diff -druN linux-libre-3.1-gnu/arch/arm/mach-prima2/clock.c linux-libre-3.2-gnu/arch/arm/mach-prima2/clock.c
--- linux-libre-3.1-gnu/arch/arm/mach-prima2/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-prima2/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -350,10 +350,10 @@
 		.clk = &clk_mem,
 	}, {
 		.dev_id = "sys",
-			.clk = &clk_sys,
+		.clk = &clk_sys,
 	}, {
 		.dev_id = "io",
-			.clk = &clk_io,
+		.clk = &clk_io,
 	},
 };
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-prima2/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-prima2/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-prima2/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-prima2/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
 #include <mach/hardware.h>
 #include <mach/uart.h>
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldr	\rp, =SIRFSOC_UART1_PA_BASE		@ physical
 	ldr	\rv, =SIRFSOC_UART1_VA_BASE		@ virtual
 	.endm
diff -druN linux-libre-3.1-gnu/arch/arm/mach-prima2/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-prima2/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-prima2/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-prima2/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * arch/arm/mach-prima2/include/mach/memory.h
- *
- * Copyright (c) 2010 â€“ 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- *
- * Licensed under GPLv2 or later.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET        UL(0x00000000)
-
-/*
- * Restrict DMA-able region to workaround silicon limitation.
- * The limitation restricts buffers available for DMA to SD/MMC
- * hardware to be below 256MB
- */
-#define ARM_DMA_ZONE_SIZE	(SZ_256M)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-prima2/irq.c linux-libre-3.2-gnu/arch/arm/mach-prima2/irq.c
--- linux-libre-3.1-gnu/arch/arm/mach-prima2/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-prima2/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,8 @@
 #include <asm/mach/irq.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/irqdomain.h>
+#include <linux/syscore_ops.h>
 
 #define SIRFSOC_INT_RISC_MASK0          0x0018
 #define SIRFSOC_INT_RISC_MASK1          0x001C
@@ -66,7 +68,48 @@
 	if (!sirfsoc_intc_base)
 		panic("unable to map intc cpu registers\n");
 
+	irq_domain_add_simple(np, 0);
+
 	of_node_put(np);
 
 	sirfsoc_irq_init();
 }
+
+struct sirfsoc_irq_status {
+	u32 mask0;
+	u32 mask1;
+	u32 level0;
+	u32 level1;
+};
+
+static struct sirfsoc_irq_status sirfsoc_irq_st;
+
+static int sirfsoc_irq_suspend(void)
+{
+	sirfsoc_irq_st.mask0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
+	sirfsoc_irq_st.mask1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
+	sirfsoc_irq_st.level0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
+	sirfsoc_irq_st.level1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
+
+	return 0;
+}
+
+static void sirfsoc_irq_resume(void)
+{
+	writel_relaxed(sirfsoc_irq_st.mask0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
+	writel_relaxed(sirfsoc_irq_st.mask1, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
+	writel_relaxed(sirfsoc_irq_st.level0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
+	writel_relaxed(sirfsoc_irq_st.level1, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
+}
+
+static struct syscore_ops sirfsoc_irq_syscore_ops = {
+	.suspend	= sirfsoc_irq_suspend,
+	.resume		= sirfsoc_irq_resume,
+};
+
+static int __init sirfsoc_irq_pm_init(void)
+{
+	register_syscore_ops(&sirfsoc_irq_syscore_ops);
+	return 0;
+}
+device_initcall(sirfsoc_irq_pm_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-prima2/l2x0.c linux-libre-3.2-gnu/arch/arm/mach-prima2/l2x0.c
--- linux-libre-3.1-gnu/arch/arm/mach-prima2/l2x0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-prima2/l2x0.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,52 +8,24 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/errno.h>
 #include <linux/of.h>
-#include <linux/of_address.h>
 #include <asm/hardware/cache-l2x0.h>
-#include <mach/memory.h>
-
-#define L2X0_ADDR_FILTERING_START       0xC00
-#define L2X0_ADDR_FILTERING_END         0xC04
 
-static struct of_device_id l2x_ids[]  = {
-	{ .compatible = "arm,pl310-cache" },
+static struct of_device_id prima2_l2x0_ids[]  = {
+	{ .compatible = "sirf,prima2-pl310-cache" },
+	{},
 };
 
-static int __init sirfsoc_of_l2x_init(void)
+static int __init sirfsoc_l2x0_init(void)
 {
 	struct device_node *np;
-	void __iomem *sirfsoc_l2x_base;
-
-	np = of_find_matching_node(NULL, l2x_ids);
-	if (!np)
-		panic("unable to find compatible l2x node in dtb\n");
-
-	sirfsoc_l2x_base = of_iomap(np, 0);
-	if (!sirfsoc_l2x_base)
-		panic("unable to map l2x cpu registers\n");
 
-	of_node_put(np);
-
-	if (!(readl_relaxed(sirfsoc_l2x_base + L2X0_CTRL) & 1)) {
-		/*
-		 * set the physical memory windows L2 cache will cover
-		 */
-		writel_relaxed(PLAT_PHYS_OFFSET + 1024 * 1024 * 1024,
-			sirfsoc_l2x_base + L2X0_ADDR_FILTERING_END);
-		writel_relaxed(PLAT_PHYS_OFFSET | 0x1,
-			sirfsoc_l2x_base + L2X0_ADDR_FILTERING_START);
-
-		writel_relaxed(0,
-			sirfsoc_l2x_base + L2X0_TAG_LATENCY_CTRL);
-		writel_relaxed(0,
-			sirfsoc_l2x_base + L2X0_DATA_LATENCY_CTRL);
+	np = of_find_matching_node(NULL, prima2_l2x0_ids);
+	if (np) {
+		pr_info("Initializing prima2 L2 cache\n");
+		return l2x0_of_init(0x40000, 0);
 	}
-	l2x0_init((void __iomem *)sirfsoc_l2x_base, 0x00040000,
-		0x00000000);
 
 	return 0;
 }
-early_initcall(sirfsoc_of_l2x_init);
+early_initcall(sirfsoc_l2x0_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-prima2/Makefile linux-libre-3.2-gnu/arch/arm/mach-prima2/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-prima2/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-prima2/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,5 +3,7 @@
 obj-y += clock.o
 obj-y += rstc.o
 obj-y += prima2.o
+obj-y += rtciobrg.o
 obj-$(CONFIG_DEBUG_LL) += lluart.o
 obj-$(CONFIG_CACHE_L2X0) += l2x0.o
+obj-$(CONFIG_SUSPEND) += pm.o sleep.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-prima2/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-prima2/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-prima2/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-prima2/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-zreladdr-y		:= 0x00008000
+zreladdr-y		+= 0x00008000
 params_phys-y		:= 0x00000100
 initrd_phys-y		:= 0x00800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-prima2/pm.c linux-libre-3.2-gnu/arch/arm/mach-prima2/pm.c
--- linux-libre-3.1-gnu/arch/arm/mach-prima2/pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-prima2/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,151 @@
+/*
+ * power management entry for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/suspend.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/rtc/sirfsoc_rtciobrg.h>
+#include <asm/suspend.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include "pm.h"
+
+/*
+ * suspend asm codes will access these to make DRAM become self-refresh and
+ * system sleep
+ */
+u32 sirfsoc_pwrc_base;
+void __iomem *sirfsoc_memc_base;
+
+static void sirfsoc_set_wakeup_source(void)
+{
+	u32 pwr_trigger_en_reg;
+	pwr_trigger_en_reg = sirfsoc_rtc_iobrg_readl(sirfsoc_pwrc_base +
+		SIRFSOC_PWRC_TRIGGER_EN);
+#define X_ON_KEY_B (1 << 0)
+	sirfsoc_rtc_iobrg_writel(pwr_trigger_en_reg | X_ON_KEY_B,
+		sirfsoc_pwrc_base + SIRFSOC_PWRC_TRIGGER_EN);
+}
+
+static void sirfsoc_set_sleep_mode(u32 mode)
+{
+	u32 sleep_mode = sirfsoc_rtc_iobrg_readl(sirfsoc_pwrc_base +
+		SIRFSOC_PWRC_PDN_CTRL);
+	sleep_mode &= ~(SIRFSOC_SLEEP_MODE_MASK << 1);
+	sleep_mode |= mode << 1;
+	sirfsoc_rtc_iobrg_writel(sleep_mode, sirfsoc_pwrc_base +
+		SIRFSOC_PWRC_PDN_CTRL);
+}
+
+static int sirfsoc_pre_suspend_power_off(void)
+{
+	u32 wakeup_entry = virt_to_phys(cpu_resume);
+
+	sirfsoc_rtc_iobrg_writel(wakeup_entry, sirfsoc_pwrc_base +
+		SIRFSOC_PWRC_SCRATCH_PAD1);
+
+	sirfsoc_set_wakeup_source();
+
+	sirfsoc_set_sleep_mode(SIRFSOC_DEEP_SLEEP_MODE);
+
+	return 0;
+}
+
+static int sirfsoc_pm_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_MEM:
+		sirfsoc_pre_suspend_power_off();
+
+		outer_flush_all();
+		outer_disable();
+		/* go zzz */
+		cpu_suspend(0, sirfsoc_finish_suspend);
+		outer_resume();
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static const struct platform_suspend_ops sirfsoc_pm_ops = {
+	.enter = sirfsoc_pm_enter,
+	.valid = suspend_valid_only_mem,
+};
+
+static int __init sirfsoc_pm_init(void)
+{
+	suspend_set_ops(&sirfsoc_pm_ops);
+	return 0;
+}
+late_initcall(sirfsoc_pm_init);
+
+static const struct of_device_id pwrc_ids[] = {
+	{ .compatible = "sirf,prima2-pwrc" },
+	{}
+};
+
+static int __init sirfsoc_of_pwrc_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_matching_node(NULL, pwrc_ids);
+	if (!np)
+		panic("unable to find compatible pwrc node in dtb\n");
+
+	/*
+	 * pwrc behind rtciobrg is not located in memory space
+	 * though the property is named reg. reg only means base
+	 * offset for pwrc. then of_iomap is not suitable here.
+	 */
+	if (of_property_read_u32(np, "reg", &sirfsoc_pwrc_base))
+		panic("unable to find base address of pwrc node in dtb\n");
+
+	of_node_put(np);
+
+	return 0;
+}
+postcore_initcall(sirfsoc_of_pwrc_init);
+
+static const struct of_device_id memc_ids[] = {
+	{ .compatible = "sirf,prima2-memc" },
+	{}
+};
+
+static int __devinit sirfsoc_memc_probe(struct platform_device *op)
+{
+	struct device_node *np = op->dev.of_node;
+
+	sirfsoc_memc_base = of_iomap(np, 0);
+	if (!sirfsoc_memc_base)
+		panic("unable to map memc registers\n");
+
+	return 0;
+}
+
+static struct platform_driver sirfsoc_memc_driver = {
+	.probe		= sirfsoc_memc_probe,
+	.driver = {
+		.name = "sirfsoc-memc",
+		.owner = THIS_MODULE,
+		.of_match_table	= memc_ids,
+	},
+};
+
+static int __init sirfsoc_memc_init(void)
+{
+	return platform_driver_register(&sirfsoc_memc_driver);
+}
+postcore_initcall(sirfsoc_memc_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-prima2/pm.h linux-libre-3.2-gnu/arch/arm/mach-prima2/pm.h
--- linux-libre-3.1-gnu/arch/arm/mach-prima2/pm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-prima2/pm.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/pm.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef _MACH_PRIMA2_PM_H_
+#define _MACH_PRIMA2_PM_H_
+
+#define SIRFSOC_PWR_SLEEPFORCE		0x01
+
+#define SIRFSOC_SLEEP_MODE_MASK         0x3
+#define SIRFSOC_DEEP_SLEEP_MODE         0x1
+
+#define SIRFSOC_PWRC_PDN_CTRL           0x0
+#define SIRFSOC_PWRC_PON_OFF            0x4
+#define SIRFSOC_PWRC_TRIGGER_EN         0x8
+#define SIRFSOC_PWRC_PIN_STATUS         0x14
+#define SIRFSOC_PWRC_SCRATCH_PAD1       0x18
+#define SIRFSOC_PWRC_SCRATCH_PAD2       0x1C
+
+#ifndef __ASSEMBLY__
+extern int sirfsoc_finish_suspend(unsigned long);
+#endif
+
+#endif
+
diff -druN linux-libre-3.1-gnu/arch/arm/mach-prima2/prima2.c linux-libre-3.2-gnu/arch/arm/mach-prima2/prima2.c
--- linux-libre-3.1-gnu/arch/arm/mach-prima2/prima2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-prima2/prima2.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Defines machines for CSR SiRFprimaII 
+ * Defines machines for CSR SiRFprimaII
  *
  * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
  *
@@ -8,6 +8,7 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <asm/sizes.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <linux/of.h>
@@ -31,11 +32,12 @@
 
 MACHINE_START(PRIMA2_EVB, "prima2cb")
 	/* Maintainer: Barry Song <baohua.song@csr.com> */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.init_early     = sirfsoc_of_clk_init,
 	.map_io         = sirfsoc_map_lluart,
 	.init_irq	= sirfsoc_of_irq_init,
 	.timer		= &sirfsoc_timer,
+	.dma_zone_size	= SZ_256M,
 	.init_machine	= sirfsoc_mach_init,
 	.dt_compat      = prima2cb_dt_match,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-prima2/rtciobrg.c linux-libre-3.2-gnu/arch/arm/mach-prima2/rtciobrg.c
--- linux-libre-3.1-gnu/arch/arm/mach-prima2/rtciobrg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-prima2/rtciobrg.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,139 @@
+/*
+ * RTC I/O Bridge interfaces for CSR SiRFprimaII
+ * ARM access the registers of SYSRTC, GPSRTC and PWRC through this module
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#define SIRFSOC_CPUIOBRG_CTRL           0x00
+#define SIRFSOC_CPUIOBRG_WRBE           0x04
+#define SIRFSOC_CPUIOBRG_ADDR           0x08
+#define SIRFSOC_CPUIOBRG_DATA           0x0c
+
+/*
+ * suspend asm codes will access this address to make system deepsleep
+ * after DRAM becomes self-refresh
+ */
+void __iomem *sirfsoc_rtciobrg_base;
+static DEFINE_SPINLOCK(rtciobrg_lock);
+
+/*
+ * symbols without lock are only used by suspend asm codes
+ * and these symbols are not exported too
+ */
+void sirfsoc_rtc_iobrg_wait_sync(void)
+{
+	while (readl_relaxed(sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL))
+		cpu_relax();
+}
+
+void sirfsoc_rtc_iobrg_besyncing(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtciobrg_lock, flags);
+
+	sirfsoc_rtc_iobrg_wait_sync();
+
+	spin_unlock_irqrestore(&rtciobrg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_besyncing);
+
+u32 __sirfsoc_rtc_iobrg_readl(u32 addr)
+{
+	sirfsoc_rtc_iobrg_wait_sync();
+
+	writel_relaxed(0x00, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_WRBE);
+	writel_relaxed(addr, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_ADDR);
+	writel_relaxed(0x01, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL);
+
+	sirfsoc_rtc_iobrg_wait_sync();
+
+	return readl_relaxed(sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_DATA);
+}
+
+u32 sirfsoc_rtc_iobrg_readl(u32 addr)
+{
+	unsigned long flags, val;
+
+	spin_lock_irqsave(&rtciobrg_lock, flags);
+
+	val = __sirfsoc_rtc_iobrg_readl(addr);
+
+	spin_unlock_irqrestore(&rtciobrg_lock, flags);
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_readl);
+
+void sirfsoc_rtc_iobrg_pre_writel(u32 val, u32 addr)
+{
+	sirfsoc_rtc_iobrg_wait_sync();
+
+	writel_relaxed(0xf1, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_WRBE);
+	writel_relaxed(addr, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_ADDR);
+
+	writel_relaxed(val, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_DATA);
+}
+
+void sirfsoc_rtc_iobrg_writel(u32 val, u32 addr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtciobrg_lock, flags);
+
+	sirfsoc_rtc_iobrg_pre_writel(val, addr);
+
+	writel_relaxed(0x01, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL);
+
+	sirfsoc_rtc_iobrg_wait_sync();
+
+	spin_unlock_irqrestore(&rtciobrg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_writel);
+
+static const struct of_device_id rtciobrg_ids[] = {
+	{ .compatible = "sirf,prima2-rtciobg" },
+	{}
+};
+
+static int __devinit sirfsoc_rtciobrg_probe(struct platform_device *op)
+{
+	struct device_node *np = op->dev.of_node;
+
+	sirfsoc_rtciobrg_base = of_iomap(np, 0);
+	if (!sirfsoc_rtciobrg_base)
+		panic("unable to map rtc iobrg registers\n");
+
+	return 0;
+}
+
+static struct platform_driver sirfsoc_rtciobrg_driver = {
+	.probe		= sirfsoc_rtciobrg_probe,
+	.driver = {
+		.name = "sirfsoc-rtciobrg",
+		.owner = THIS_MODULE,
+		.of_match_table	= rtciobrg_ids,
+	},
+};
+
+static int __init sirfsoc_rtciobrg_init(void)
+{
+	return platform_driver_register(&sirfsoc_rtciobrg_driver);
+}
+postcore_initcall(sirfsoc_rtciobrg_init);
+
+MODULE_AUTHOR("Zhiwu Song <zhiwu.song@csr.com>, "
+		"Barry Song <baohua.song@csr.com>");
+MODULE_DESCRIPTION("CSR SiRFprimaII rtc io bridge");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/arch/arm/mach-prima2/sleep.S linux-libre-3.2-gnu/arch/arm/mach-prima2/sleep.S
--- linux-libre-3.1-gnu/arch/arm/mach-prima2/sleep.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-prima2/sleep.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,64 @@
+/*
+ * sleep mode for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/assembler.h>
+
+#include "pm.h"
+
+#define DENALI_CTL_22_OFF	0x58
+#define DENALI_CTL_112_OFF	0x1c0
+
+	.text
+
+ENTRY(sirfsoc_finish_suspend)
+	@ r5: 	mem controller
+	ldr     r0, =sirfsoc_memc_base
+	ldr	r5, [r0]
+	@ r6: 	pwrc base offset
+	ldr     r0, =sirfsoc_pwrc_base
+	ldr	r6, [r0]
+	@ r7: 	rtc iobrg controller
+	ldr     r0, =sirfsoc_rtciobrg_base
+	ldr	r7, [r0]
+
+	@ Read the power control register and set the
+	@ sleep force bit.
+	add	r0, r6, #SIRFSOC_PWRC_PDN_CTRL
+	bl	__sirfsoc_rtc_iobrg_readl
+	orr	r0,r0,#SIRFSOC_PWR_SLEEPFORCE
+	add	r1, r6, #SIRFSOC_PWRC_PDN_CTRL
+	bl	sirfsoc_rtc_iobrg_pre_writel
+	mov	r1, #0x1
+
+	@ read the MEM ctl register and set the self
+	@ refresh bit
+
+	ldr	r2, [r5, #DENALI_CTL_22_OFF]
+	orr	r2, r2, #0x1
+
+	@ Following code has to run from cache since
+	@ the RAM is going to self refresh mode
+	.align 5
+	str	r2, [r5, #DENALI_CTL_22_OFF]
+
+1:
+	ldr	r4, [r5, #DENALI_CTL_112_OFF]
+	tst	r4, #0x1
+	bne	1b
+
+	@ write SLEEPFORCE through rtc iobridge
+
+	str	r1, [r7]
+	@ wait rtc io bridge sync
+1:
+	ldr	r3, [r7]
+	tst	r3, #0x01
+	bne	1b
+	b .
diff -druN linux-libre-3.1-gnu/arch/arm/mach-prima2/timer.c linux-libre-3.2-gnu/arch/arm/mach-prima2/timer.c
--- linux-libre-3.1-gnu/arch/arm/mach-prima2/timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-prima2/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,17 @@
 
 #define SIRFSOC_TIMER_LATCH_BIT	 BIT(0)
 
+#define SIRFSOC_TIMER_REG_CNT 11
+
+static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
+	SIRFSOC_TIMER_MATCH_0, SIRFSOC_TIMER_MATCH_1, SIRFSOC_TIMER_MATCH_2,
+	SIRFSOC_TIMER_MATCH_3, SIRFSOC_TIMER_MATCH_4, SIRFSOC_TIMER_MATCH_5,
+	SIRFSOC_TIMER_INT_EN, SIRFSOC_TIMER_WATCHDOG_EN, SIRFSOC_TIMER_DIV,
+	SIRFSOC_TIMER_LATCHED_LO, SIRFSOC_TIMER_LATCHED_HI,
+};
+
+static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
+
 static void __iomem *sirfsoc_timer_base;
 static void __init sirfsoc_of_timer_map(void);
 
@@ -106,6 +117,27 @@
 	}
 }
 
+static void sirfsoc_clocksource_suspend(struct clocksource *cs)
+{
+	int i;
+
+	writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+
+	for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
+		sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
+}
+
+static void sirfsoc_clocksource_resume(struct clocksource *cs)
+{
+	int i;
+
+	for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
+		writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
+
+	writel_relaxed(sirfsoc_timer_reg_val[i - 2], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
+	writel_relaxed(sirfsoc_timer_reg_val[i - 1], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
+}
+
 static struct clock_event_device sirfsoc_clockevent = {
 	.name = "sirfsoc_clockevent",
 	.rating = 200,
@@ -120,6 +152,8 @@
 	.mask = CLOCKSOURCE_MASK(64),
 	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
 	.read = sirfsoc_timer_read,
+	.suspend = sirfsoc_clocksource_suspend,
+	.resume = sirfsoc_clocksource_resume,
 };
 
 static struct irqaction sirfsoc_timer_irq = {
@@ -133,14 +167,14 @@
 /* Overwrite weak default sched_clock with more precise one */
 unsigned long long notrace sched_clock(void)
 {
-	static int is_mapped = 0;
+	static int is_mapped;
 
 	/*
 	 * sched_clock is called earlier than .init of sys_timer
 	 * if we map timer memory in .init of sys_timer, system
 	 * will panic due to illegal memory access
 	 */
-	if(!is_mapped) {
+	if (!is_mapped) {
 		sirfsoc_of_timer_map();
 		is_mapped = 1;
 	}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/balloon3.c linux-libre-3.2-gnu/arch/arm/mach-pxa/balloon3.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/balloon3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/balloon3.c	2012-01-04 18:55:44.000000000 -0500
@@ -307,7 +307,7 @@
 /******************************************************************************
  * USB Gadget
  ******************************************************************************/
-#if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE)
 static void balloon3_udc_command(int cmd)
 {
 	if (cmd == PXA2XX_UDC_CMD_CONNECT)
@@ -591,7 +591,7 @@
 				BALLOON3_NAND_CONTROL_REG);
 		if (balloon3_ctl_set)
 			__raw_writel(balloon3_ctl_set,
-				BALLOON3_NAND_CONTROL_REG |
+				BALLOON3_NAND_CONTROL_REG +
 				BALLOON3_FPGA_SETnCLR);
 	}
 
@@ -608,7 +608,7 @@
 	__raw_writew(
 		BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 |
 		BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3,
-		BALLOON3_NAND_CONTROL_REG | BALLOON3_FPGA_SETnCLR);
+		BALLOON3_NAND_CONTROL_REG + BALLOON3_FPGA_SETnCLR);
 
 	/* Deassert correct nCE line */
 	__raw_writew(BALLOON3_NAND_CONTROL_FLCE0 << chip,
@@ -626,7 +626,7 @@
 	int ret;
 
 	__raw_writew(BALLOON3_NAND_CONTROL2_16BIT,
-		BALLOON3_NAND_CONTROL2_REG | BALLOON3_FPGA_SETnCLR);
+		BALLOON3_NAND_CONTROL2_REG + BALLOON3_FPGA_SETnCLR);
 
 	ver = __raw_readw(BALLOON3_FPGA_VER);
 	if (ver < 0x4f08)
@@ -649,7 +649,7 @@
 		BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 |
 		BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3 |
 		BALLOON3_NAND_CONTROL_FLWP,
-		BALLOON3_NAND_CONTROL_REG | BALLOON3_FPGA_SETnCLR);
+		BALLOON3_NAND_CONTROL_REG + BALLOON3_FPGA_SETnCLR);
 	return 0;
 
 err2:
@@ -807,7 +807,7 @@
 
 static struct map_desc balloon3_io_desc[] __initdata = {
 	{	/* CPLD/FPGA */
-		.virtual	=  BALLOON3_FPGA_VIRT,
+		.virtual	= (unsigned long)BALLOON3_FPGA_VIRT,
 		.pfn		= __phys_to_pfn(BALLOON3_FPGA_PHYS),
 		.length		= BALLOON3_FPGA_LENGTH,
 		.type		= MT_DEVICE,
@@ -828,5 +828,5 @@
 	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= balloon3_init,
-	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
+	.atag_offset	= 0x100,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/capc7117.c linux-libre-3.2-gnu/arch/arm/mach-pxa/capc7117.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/capc7117.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/capc7117.c	2012-01-04 18:55:44.000000000 -0500
@@ -148,7 +148,7 @@
 
 MACHINE_START(CAPC7117,
 	      "Embedian CAPC-7117 evaluation kit based on the MXM-8x10 CoM")
-	.boot_params = 0xa0000100,
+	.atag_offset = 0x100,
 	.map_io = pxa3xx_map_io,
 	.init_irq = pxa3xx_init_irq,
 	.handle_irq = pxa3xx_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/cm-x255.c linux-libre-3.2-gnu/arch/arm/mach-pxa/cm-x255.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/cm-x255.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/cm-x255.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,6 @@
 
 #include <linux/platform_device.h>
 #include <linux/irq.h>
-#include <linux/gpio.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/nand-gpio.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/cm-x2xx.c linux-libre-3.2-gnu/arch/arm/mach-pxa/cm-x2xx.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/cm-x2xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/cm-x2xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,7 +39,7 @@
 #define CMX2XX_NR_IRQS		(IRQ_BOARD_START + 40)
 
 /* virtual addresses for statically mapped regions */
-#define CMX2XX_VIRT_BASE	(0xe8000000)
+#define CMX2XX_VIRT_BASE	(void __iomem *)(0xe8000000)
 #define CMX2XX_IT8152_VIRT	(CMX2XX_VIRT_BASE)
 
 /* physical address if local-bus attached devices */
@@ -482,7 +482,7 @@
 /* Map PCI companion statically */
 static struct map_desc cmx2xx_io_desc[] __initdata = {
 	[0] = { /* PCI bridge */
-		.virtual	= CMX2XX_IT8152_VIRT,
+		.virtual	= (unsigned long)CMX2XX_IT8152_VIRT,
 		.pfn		= __phys_to_pfn(PXA_CS4_PHYS),
 		.length		= SZ_64M,
 		.type		= MT_DEVICE
@@ -513,7 +513,7 @@
 #endif
 
 MACHINE_START(ARMCORE, "Compulab CM-X2XX")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= cmx2xx_map_io,
 	.nr_irqs	= CMX2XX_NR_IRQS,
 	.init_irq	= cmx2xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/cm-x2xx-pci.c linux-libre-3.2-gnu/arch/arm/mach-pxa/cm-x2xx-pci.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/cm-x2xx-pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/cm-x2xx-pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,7 +26,7 @@
 
 #include <asm/hardware/it8152.h>
 
-unsigned long it8152_base_address;
+void __iomem *it8152_base_address;
 static int cmx2xx_it8152_irq_gpio;
 
 static void cmx2xx_it8152_irq_demux(unsigned int irq, struct irq_desc *desc)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/cm-x300.c linux-libre-3.2-gnu/arch/arm/mach-pxa/cm-x300.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/cm-x300.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/cm-x300.c	2012-01-04 18:55:44.000000000 -0500
@@ -424,8 +424,9 @@
 static struct pxa3xx_nand_platform_data cm_x300_nand_info = {
 	.enable_arbiter	= 1,
 	.keep_config	= 1,
-	.parts		= cm_x300_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(cm_x300_nand_partitions),
+	.num_cs		= 1,
+	.parts[0]	= cm_x300_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(cm_x300_nand_partitions),
 };
 
 static void __init cm_x300_init_nand(void)
@@ -775,7 +776,6 @@
 
 static void __init cm_x300_init_wi2wi(void)
 {
-	int bt_reset, wlan_en;
 	int err;
 
 	if (system_rev < 130) {
@@ -791,12 +791,11 @@
 	}
 
 	udelay(10);
-	gpio_set_value(bt_reset, 0);
+	gpio_set_value(cm_x300_wi2wi_gpios[1].gpio, 0);
 	udelay(10);
-	gpio_set_value(bt_reset, 1);
+	gpio_set_value(cm_x300_wi2wi_gpios[1].gpio, 1);
 
-	gpio_free(wlan_en);
-	gpio_free(bt_reset);
+	gpio_free_array(ARRAY_AND_SIZE(cm_x300_wi2wi_gpios));
 }
 
 /* MFP */
@@ -839,8 +838,8 @@
 	cm_x300_init_bl();
 }
 
-static void __init cm_x300_fixup(struct machine_desc *mdesc, struct tag *tags,
-				 char **cmdline, struct meminfo *mi)
+static void __init cm_x300_fixup(struct tag *tags, char **cmdline,
+				 struct meminfo *mi)
 {
 	/* Make sure that mi->bank[0].start = PHYS_ADDR */
 	for (; tags->hdr.size; tags = tag_next(tags))
@@ -852,7 +851,7 @@
 }
 
 MACHINE_START(CM_X300, "CM-X300 module")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
 	.handle_irq	= pxa3xx_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/colibri-pxa270.c linux-libre-3.2-gnu/arch/arm/mach-pxa/colibri-pxa270.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/colibri-pxa270.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/colibri-pxa270.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -306,7 +307,7 @@
 }
 
 MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
-	.boot_params	= COLIBRI_SDRAM_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.init_machine	= colibri_pxa270_init,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
@@ -315,7 +316,7 @@
 MACHINE_END
 
 MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.init_machine	= colibri_pxa270_income_init,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/colibri-pxa300.c linux-libre-3.2-gnu/arch/arm/mach-pxa/colibri-pxa300.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/colibri-pxa300.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/colibri-pxa300.c	2012-01-04 18:55:44.000000000 -0500
@@ -183,7 +183,7 @@
 }
 
 MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
-	.boot_params	= COLIBRI_SDRAM_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.init_machine	= colibri_pxa300_init,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/colibri-pxa320.c linux-libre-3.2-gnu/arch/arm/mach-pxa/colibri-pxa320.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/colibri-pxa320.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/colibri-pxa320.c	2012-01-04 18:55:44.000000000 -0500
@@ -146,7 +146,7 @@
 static inline void __init colibri_pxa320_init_eth(void) {}
 #endif /* CONFIG_AX88796 */
 
-#if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE)
 static struct gpio_vbus_mach_info colibri_pxa320_gpio_vbus_info = {
 	.gpio_vbus		= mfp_to_gpio(MFP_PIN_GPIO96),
 	.gpio_pullup		= -1,
@@ -253,7 +253,7 @@
 }
 
 MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
-	.boot_params	= COLIBRI_SDRAM_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.init_machine	= colibri_pxa320_init,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/colibri-pxa3xx.c linux-libre-3.2-gnu/arch/arm/mach-pxa/colibri-pxa3xx.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/colibri-pxa3xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/colibri-pxa3xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -139,8 +139,9 @@
 static struct pxa3xx_nand_platform_data colibri_nand_info = {
 	.enable_arbiter	= 1,
 	.keep_config	= 1,
-	.parts		= colibri_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(colibri_nand_partitions),
+	.num_cs		= 1,
+	.parts[0]	= colibri_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(colibri_nand_partitions),
 };
 
 void __init colibri_pxa3xx_init_nand(void)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/corgi.c linux-libre-3.2-gnu/arch/arm/mach-pxa/corgi.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/corgi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/corgi.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/mtd/sharpsl.h>
 #include <linux/input/matrix_keypad.h>
+#include <linux/module.h>
 #include <video/w100fb.h>
 
 #include <asm/setup.h>
@@ -705,8 +706,8 @@
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
-static void __init fixup_corgi(struct machine_desc *desc,
-		struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init fixup_corgi(struct tag *tags, char **cmdline,
+			       struct meminfo *mi)
 {
 	sharpsl_save_param();
 	mi->nr_banks=1;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/csb726.c linux-libre-3.2-gnu/arch/arm/mach-pxa/csb726.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/csb726.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/csb726.c	2012-01-04 18:55:44.000000000 -0500
@@ -272,7 +272,7 @@
 }
 
 MACHINE_START(CSB726, "Cogent CSB726")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io         = pxa27x_map_io,
 	.init_irq       = pxa27x_init_irq,
 	.handle_irq       = pxa27x_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/em-x270.c linux-libre-3.2-gnu/arch/arm/mach-pxa/em-x270.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/em-x270.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/em-x270.c	2012-01-04 18:55:44.000000000 -0500
@@ -1299,7 +1299,7 @@
 }
 
 MACHINE_START(EM_X270, "Compulab EM-X270")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
@@ -1308,7 +1308,7 @@
 MACHINE_END
 
 MACHINE_START(EXEDA, "Compulab eXeda")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/eseries.c linux-libre-3.2-gnu/arch/arm/mach-pxa/eseries.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/eseries.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/eseries.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,8 +41,7 @@
 #include "clock.h"
 
 /* Only e800 has 128MB RAM */
-void __init eseries_fixup(struct machine_desc *desc,
-	struct tag *tags, char **cmdline, struct meminfo *mi)
+void __init eseries_fixup(struct tag *tags, char **cmdline, struct meminfo *mi)
 {
 	mi->nr_banks=1;
 	mi->bank[0].start = 0xa0000000;
@@ -145,7 +144,7 @@
 	INIT_CLKREG(&tmio_dummy_clk, NULL, "CLK_CK32K"),
 };
 
-void eseries_register_clks(void)
+static void __init eseries_register_clks(void)
 {
 	clkdev_add_table(eseries_clkregs, ARRAY_SIZE(eseries_clkregs));
 }
@@ -189,7 +188,7 @@
 
 MACHINE_START(E330, "Toshiba e330")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
@@ -239,7 +238,7 @@
 
 MACHINE_START(E350, "Toshiba e350")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
@@ -362,7 +361,7 @@
 
 MACHINE_START(E400, "Toshiba e400")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
@@ -551,7 +550,7 @@
 
 MACHINE_START(E740, "Toshiba e740")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
@@ -743,7 +742,7 @@
 
 MACHINE_START(E750, "Toshiba e750")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
@@ -948,7 +947,7 @@
 
 MACHINE_START(E800, "Toshiba e800")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/eseries.h linux-libre-3.2-gnu/arch/arm/mach-pxa/eseries.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/eseries.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/eseries.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,4 @@
-void __init eseries_fixup(struct machine_desc *desc,
-	struct tag *tags, char **cmdline, struct meminfo *mi);
+void __init eseries_fixup(struct tag *tags, char **cmdline, struct meminfo *mi);
 
 extern struct pxa2xx_udc_mach_info e7xx_udc_mach_info;
 extern struct pxaficp_platform_data e7xx_ficp_platform_data;
@@ -12,5 +11,4 @@
 extern void eseries_get_tmio_gpios(void);
 extern struct resource eseries_tmio_resources[];
 extern struct platform_device e300_tc6387xb_device;
-extern void eseries_register_clks(void);
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/ezx.c linux-libre-3.2-gnu/arch/arm/mach-pxa/ezx.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/ezx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/ezx.c	2012-01-04 18:55:44.000000000 -0500
@@ -797,7 +797,7 @@
 }
 
 MACHINE_START(EZX_A780, "Motorola EZX A780")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
@@ -863,7 +863,7 @@
 }
 
 MACHINE_START(EZX_E680, "Motorola EZX E680")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
@@ -929,7 +929,7 @@
 }
 
 MACHINE_START(EZX_A1200, "Motorola EZX A1200")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
@@ -1120,7 +1120,7 @@
 }
 
 MACHINE_START(EZX_A910, "Motorola EZX A910")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
@@ -1186,7 +1186,7 @@
 }
 
 MACHINE_START(EZX_E6, "Motorola EZX E6")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
@@ -1226,7 +1226,7 @@
 }
 
 MACHINE_START(EZX_E2, "Motorola EZX E2")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/generic.c linux-libre-3.2-gnu/arch/arm/mach-pxa/generic.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/generic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/generic.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
  * initialization stuff for PXA machines which can be overridden later if
  * need be.
  */
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -26,7 +27,6 @@
 #include <asm/mach-types.h>
 
 #include <mach/reset.h>
-#include <mach/gpio.h>
 #include <mach/smemc.h>
 #include <mach/pxa3xx-regs.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/gumstix.c linux-libre-3.2-gnu/arch/arm/mach-pxa/gumstix.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/gumstix.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/gumstix.c	2012-01-04 18:55:44.000000000 -0500
@@ -106,7 +106,7 @@
 }
 #endif
 
-#ifdef CONFIG_USB_GADGET_PXA25X
+#ifdef CONFIG_USB_PXA25X
 static struct gpio_vbus_mach_info gumstix_udc_info = {
 	.gpio_vbus		= GPIO_GUMSTIX_USB_GPIOn,
 	.gpio_pullup		= GPIO_GUMSTIX_USB_GPIOx,
@@ -233,7 +233,7 @@
 }
 
 MACHINE_START(GUMSTIX, "Gumstix")
-	.boot_params	= 0xa0000100, /* match u-boot bi_boot_params */
+	.atag_offset	= 0x100, /* match u-boot bi_boot_params */
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/h5000.c linux-libre-3.2-gnu/arch/arm/mach-pxa/h5000.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/h5000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/h5000.c	2012-01-04 18:55:44.000000000 -0500
@@ -203,7 +203,7 @@
 }
 
 MACHINE_START(H5400, "HP iPAQ H5000")
-	.boot_params = 0xa0000100,
+	.atag_offset = 0x100,
 	.map_io = pxa25x_map_io,
 	.init_irq = pxa25x_init_irq,
 	.handle_irq = pxa25x_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/himalaya.c linux-libre-3.2-gnu/arch/arm/mach-pxa/himalaya.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/himalaya.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/himalaya.c	2012-01-04 18:55:44.000000000 -0500
@@ -158,7 +158,7 @@
 
 
 MACHINE_START(HIMALAYA, "HTC Himalaya")
-	.boot_params = 0xa0000100,
+	.atag_offset = 0x100,
 	.map_io = pxa25x_map_io,
 	.init_irq = pxa25x_init_irq,
 	.handle_irq = pxa25x_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/hx4700.c linux-libre-3.2-gnu/arch/arm/mach-pxa/hx4700.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/hx4700.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/hx4700.c	2012-01-04 18:55:44.000000000 -0500
@@ -838,7 +838,7 @@
 }
 
 MACHINE_START(H4700, "HP iPAQ HX4700")
-	.boot_params  = 0xa0000100,
+	.atag_offset  = 0x100,
 	.map_io       = pxa27x_map_io,
 	.nr_irqs      = HX4700_NR_IRQS,
 	.init_irq     = pxa27x_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/icontrol.c linux-libre-3.2-gnu/arch/arm/mach-pxa/icontrol.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/icontrol.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/icontrol.c	2012-01-04 18:55:44.000000000 -0500
@@ -191,7 +191,7 @@
 }
 
 MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
 	.handle_irq	= pxa3xx_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/addr-map.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/addr-map.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/addr-map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/addr-map.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
  * Peripheral Bus
  */
 #define PERIPH_PHYS		0x40000000
-#define PERIPH_VIRT		0xf2000000
+#define PERIPH_VIRT		IOMEM(0xf2000000)
 #define PERIPH_SIZE		0x02000000
 
 /*
@@ -28,21 +28,21 @@
  */
 #define PXA2XX_SMEMC_PHYS	0x48000000
 #define PXA3XX_SMEMC_PHYS	0x4a000000
-#define SMEMC_VIRT		0xf6000000
+#define SMEMC_VIRT		IOMEM(0xf6000000)
 #define SMEMC_SIZE		0x00100000
 
 /*
  * Dynamic Memory Controller (only on PXA3xx)
  */
 #define DMEMC_PHYS		0x48100000
-#define DMEMC_VIRT		0xf6100000
+#define DMEMC_VIRT		IOMEM(0xf6100000)
 #define DMEMC_SIZE		0x00100000
 
 /*
  * Internal Memory Controller (PXA27x and later)
  */
 #define IMEMC_PHYS		0x58000000
-#define IMEMC_VIRT		0xfe000000
+#define IMEMC_VIRT		IOMEM(0xfe000000)
 #define IMEMC_SIZE		0x00100000
 
 #endif /* __ASM_MACH_ADDR_MAP_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/balloon3.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/balloon3.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/balloon3.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/balloon3.h	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,7 @@
 };
 
 #define BALLOON3_FPGA_PHYS	PXA_CS4_PHYS
-#define BALLOON3_FPGA_VIRT	(0xf1000000)	/* as per balloon2 */
+#define BALLOON3_FPGA_VIRT	IOMEM(0xf1000000)	/* as per balloon2 */
 #define BALLOON3_FPGA_LENGTH	0x01000000
 
 #define	BALLOON3_FPGA_SETnCLR		(0x1000)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
 
 #include "hardware.h"
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x00100000
 		orr	\rv, \rp, #io_p2v(0x40000000)	@ virtual
 		orr	\rp, \rp, #0x40000000		@ physical
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -24,84 +24,10 @@
 #ifndef __ASM_ARCH_PXA_GPIO_H
 #define __ASM_ARCH_PXA_GPIO_H
 
-#include <mach/irqs.h>
-#include <mach/hardware.h>
 #include <asm-generic/gpio.h>
+/* The defines for the driver are needed for the accelerated accessors */
+#include "gpio-pxa.h"
 
-#define GPIO_REGS_VIRT	io_p2v(0x40E00000)
-
-#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
-#define GPIO_REG(x)	(*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
-
-/* GPIO Pin Level Registers */
-#define GPLR0		GPIO_REG(BANK_OFF(0) + 0x00)
-#define GPLR1		GPIO_REG(BANK_OFF(1) + 0x00)
-#define GPLR2		GPIO_REG(BANK_OFF(2) + 0x00)
-#define GPLR3		GPIO_REG(BANK_OFF(3) + 0x00)
-
-/* GPIO Pin Direction Registers */
-#define GPDR0		GPIO_REG(BANK_OFF(0) + 0x0c)
-#define GPDR1		GPIO_REG(BANK_OFF(1) + 0x0c)
-#define GPDR2		GPIO_REG(BANK_OFF(2) + 0x0c)
-#define GPDR3		GPIO_REG(BANK_OFF(3) + 0x0c)
-
-/* GPIO Pin Output Set Registers */
-#define GPSR0		GPIO_REG(BANK_OFF(0) + 0x18)
-#define GPSR1		GPIO_REG(BANK_OFF(1) + 0x18)
-#define GPSR2		GPIO_REG(BANK_OFF(2) + 0x18)
-#define GPSR3		GPIO_REG(BANK_OFF(3) + 0x18)
-
-/* GPIO Pin Output Clear Registers */
-#define GPCR0		GPIO_REG(BANK_OFF(0) + 0x24)
-#define GPCR1		GPIO_REG(BANK_OFF(1) + 0x24)
-#define GPCR2		GPIO_REG(BANK_OFF(2) + 0x24)
-#define GPCR3		GPIO_REG(BANK_OFF(3) + 0x24)
-
-/* GPIO Rising Edge Detect Registers */
-#define GRER0		GPIO_REG(BANK_OFF(0) + 0x30)
-#define GRER1		GPIO_REG(BANK_OFF(1) + 0x30)
-#define GRER2		GPIO_REG(BANK_OFF(2) + 0x30)
-#define GRER3		GPIO_REG(BANK_OFF(3) + 0x30)
-
-/* GPIO Falling Edge Detect Registers */
-#define GFER0		GPIO_REG(BANK_OFF(0) + 0x3c)
-#define GFER1		GPIO_REG(BANK_OFF(1) + 0x3c)
-#define GFER2		GPIO_REG(BANK_OFF(2) + 0x3c)
-#define GFER3		GPIO_REG(BANK_OFF(3) + 0x3c)
-
-/* GPIO Edge Detect Status Registers */
-#define GEDR0		GPIO_REG(BANK_OFF(0) + 0x48)
-#define GEDR1		GPIO_REG(BANK_OFF(1) + 0x48)
-#define GEDR2		GPIO_REG(BANK_OFF(2) + 0x48)
-#define GEDR3		GPIO_REG(BANK_OFF(3) + 0x48)
-
-/* GPIO Alternate Function Select Registers */
-#define GAFR0_L		GPIO_REG(0x0054)
-#define GAFR0_U		GPIO_REG(0x0058)
-#define GAFR1_L		GPIO_REG(0x005C)
-#define GAFR1_U		GPIO_REG(0x0060)
-#define GAFR2_L		GPIO_REG(0x0064)
-#define GAFR2_U		GPIO_REG(0x0068)
-#define GAFR3_L		GPIO_REG(0x006C)
-#define GAFR3_U		GPIO_REG(0x0070)
-
-/* More handy macros.  The argument is a literal GPIO number. */
-
-#define GPIO_bit(x)	(1 << ((x) & 0x1f))
-
-#define GPLR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x00)
-#define GPDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x0c)
-#define GPSR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x18)
-#define GPCR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x24)
-#define GRER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x30)
-#define GFER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x3c)
-#define GEDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x48)
-#define GAFR(x)		GPIO_REG(0x54 + (((x) & 0x70) >> 2))
-
-
-#define NR_BUILTIN_GPIO		PXA_GPIO_IRQ_NUM
-
-#define gpio_to_bank(gpio)	((gpio) >> 5)
 #define gpio_to_irq(gpio)	IRQ_GPIO(gpio)
 
 static inline int irq_to_gpio(unsigned int irq)
@@ -118,37 +44,5 @@
 	return -1;
 }
 
-#ifdef CONFIG_CPU_PXA26x
-/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
- * as well as their Alternate Function value being '1' for GPIO in GAFRx.
- */
-static inline int __gpio_is_inverted(unsigned gpio)
-{
-	return cpu_is_pxa25x() && gpio > 85;
-}
-#else
-static inline int __gpio_is_inverted(unsigned gpio) { return 0; }
-#endif
-
-/*
- * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
- * function of a GPIO, and GPDRx cannot be altered once configured. It
- * is attributed as "occupied" here (I know this terminology isn't
- * accurate, you are welcome to propose a better one :-)
- */
-static inline int __gpio_is_occupied(unsigned gpio)
-{
-	if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
-		int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
-		int dir = GPDR(gpio) & GPIO_bit(gpio);
-
-		if (__gpio_is_inverted(gpio))
-			return af != 1 || dir == 0;
-		else
-			return af != 0 || dir != 0;
-	} else
-		return GPDR(gpio) & GPIO_bit(gpio);
-}
-
 #include <plat/gpio.h>
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/gpio-pxa.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/gpio-pxa.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/gpio-pxa.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/gpio-pxa.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,133 @@
+/*
+ * Written by Philipp Zabel <philipp.zabel@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_PXA_GPIO_PXA_H
+#define __MACH_PXA_GPIO_PXA_H
+
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+
+#define GPIO_REGS_VIRT	io_p2v(0x40E00000)
+
+#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
+#define GPIO_REG(x)	(*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
+
+/* GPIO Pin Level Registers */
+#define GPLR0		GPIO_REG(BANK_OFF(0) + 0x00)
+#define GPLR1		GPIO_REG(BANK_OFF(1) + 0x00)
+#define GPLR2		GPIO_REG(BANK_OFF(2) + 0x00)
+#define GPLR3		GPIO_REG(BANK_OFF(3) + 0x00)
+
+/* GPIO Pin Direction Registers */
+#define GPDR0		GPIO_REG(BANK_OFF(0) + 0x0c)
+#define GPDR1		GPIO_REG(BANK_OFF(1) + 0x0c)
+#define GPDR2		GPIO_REG(BANK_OFF(2) + 0x0c)
+#define GPDR3		GPIO_REG(BANK_OFF(3) + 0x0c)
+
+/* GPIO Pin Output Set Registers */
+#define GPSR0		GPIO_REG(BANK_OFF(0) + 0x18)
+#define GPSR1		GPIO_REG(BANK_OFF(1) + 0x18)
+#define GPSR2		GPIO_REG(BANK_OFF(2) + 0x18)
+#define GPSR3		GPIO_REG(BANK_OFF(3) + 0x18)
+
+/* GPIO Pin Output Clear Registers */
+#define GPCR0		GPIO_REG(BANK_OFF(0) + 0x24)
+#define GPCR1		GPIO_REG(BANK_OFF(1) + 0x24)
+#define GPCR2		GPIO_REG(BANK_OFF(2) + 0x24)
+#define GPCR3		GPIO_REG(BANK_OFF(3) + 0x24)
+
+/* GPIO Rising Edge Detect Registers */
+#define GRER0		GPIO_REG(BANK_OFF(0) + 0x30)
+#define GRER1		GPIO_REG(BANK_OFF(1) + 0x30)
+#define GRER2		GPIO_REG(BANK_OFF(2) + 0x30)
+#define GRER3		GPIO_REG(BANK_OFF(3) + 0x30)
+
+/* GPIO Falling Edge Detect Registers */
+#define GFER0		GPIO_REG(BANK_OFF(0) + 0x3c)
+#define GFER1		GPIO_REG(BANK_OFF(1) + 0x3c)
+#define GFER2		GPIO_REG(BANK_OFF(2) + 0x3c)
+#define GFER3		GPIO_REG(BANK_OFF(3) + 0x3c)
+
+/* GPIO Edge Detect Status Registers */
+#define GEDR0		GPIO_REG(BANK_OFF(0) + 0x48)
+#define GEDR1		GPIO_REG(BANK_OFF(1) + 0x48)
+#define GEDR2		GPIO_REG(BANK_OFF(2) + 0x48)
+#define GEDR3		GPIO_REG(BANK_OFF(3) + 0x48)
+
+/* GPIO Alternate Function Select Registers */
+#define GAFR0_L		GPIO_REG(0x0054)
+#define GAFR0_U		GPIO_REG(0x0058)
+#define GAFR1_L		GPIO_REG(0x005C)
+#define GAFR1_U		GPIO_REG(0x0060)
+#define GAFR2_L		GPIO_REG(0x0064)
+#define GAFR2_U		GPIO_REG(0x0068)
+#define GAFR3_L		GPIO_REG(0x006C)
+#define GAFR3_U		GPIO_REG(0x0070)
+
+/* More handy macros.  The argument is a literal GPIO number. */
+
+#define GPIO_bit(x)	(1 << ((x) & 0x1f))
+
+#define GPLR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x00)
+#define GPDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x0c)
+#define GPSR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x18)
+#define GPCR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x24)
+#define GRER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x30)
+#define GFER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x3c)
+#define GEDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x48)
+#define GAFR(x)		GPIO_REG(0x54 + (((x) & 0x70) >> 2))
+
+
+#define NR_BUILTIN_GPIO		PXA_GPIO_IRQ_NUM
+
+#define gpio_to_bank(gpio)	((gpio) >> 5)
+
+#ifdef CONFIG_CPU_PXA26x
+/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
+ * as well as their Alternate Function value being '1' for GPIO in GAFRx.
+ */
+static inline int __gpio_is_inverted(unsigned gpio)
+{
+	return cpu_is_pxa25x() && gpio > 85;
+}
+#else
+static inline int __gpio_is_inverted(unsigned gpio) { return 0; }
+#endif
+
+/*
+ * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
+ * function of a GPIO, and GPDRx cannot be altered once configured. It
+ * is attributed as "occupied" here (I know this terminology isn't
+ * accurate, you are welcome to propose a better one :-)
+ */
+static inline int __gpio_is_occupied(unsigned gpio)
+{
+	if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
+		int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
+		int dir = GPDR(gpio) & GPIO_bit(gpio);
+
+		if (__gpio_is_inverted(gpio))
+			return af != 1 || dir == 0;
+		else
+			return af != 0 || dir != 0;
+	} else
+		return GPDR(gpio) & GPIO_bit(gpio);
+}
+
+#include <plat/gpio-pxa.h>
+#endif /* __MACH_PXA_GPIO_PXA_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/hardware.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/hardware.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/hardware.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/hardware.h	2012-01-04 18:55:44.000000000 -0500
@@ -36,22 +36,23 @@
  * Note that not all PXA2xx chips implement all those addresses, and the
  * kernel only maps the minimum needed range of this mapping.
  */
-#define io_p2v(x) (0xf2000000 + ((x) & 0x01ffffff) + (((x) & 0x1c000000) >> 1))
 #define io_v2p(x) (0x3c000000 + ((x) & 0x01ffffff) + (((x) & 0x0e000000) << 1))
+#define io_p2v(x) IOMEM(0xf2000000 + ((x) & 0x01ffffff) + (((x) & 0x1c000000) >> 1))
 
 #ifndef __ASSEMBLY__
-
-# define __REG(x)	(*((volatile u32 *)io_p2v(x)))
+# define IOMEM(x) ((void __iomem *)(x))
+# define __REG(x)	(*((volatile u32 __iomem *)io_p2v(x)))
 
 /* With indexed regs we don't want to feed the index through io_p2v()
    especially if it is a variable, otherwise horrible code will result. */
 # define __REG2(x,y)	\
-	(*(volatile u32 *)((u32)&__REG(x) + (y)))
+	(*(volatile u32 __iomem*)((u32)&__REG(x) + (y)))
 
 # define __PREG(x)	(io_v2p((u32)&(x)))
 
 #else
 
+# define IOMEM(x)	x 
 # define __REG(x)	io_p2v(x)
 # define __PREG(x)	io_v2p(x)
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/littleton.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/littleton.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/littleton.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/littleton.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 #ifndef __ASM_ARCH_LITTLETON_H
 #define __ASM_ARCH_LITTLETON_H
 
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
 
 #define LITTLETON_ETH_PHYS	0x30000000
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/lpd270.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/lpd270.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/lpd270.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/lpd270.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,13 +13,13 @@
 #define __ASM_ARCH_LPD270_H
 
 #define LPD270_CPLD_PHYS	PXA_CS2_PHYS
-#define LPD270_CPLD_VIRT	0xf0000000
+#define LPD270_CPLD_VIRT	IOMEM(0xf0000000)
 #define LPD270_CPLD_SIZE	0x00100000
 
 #define LPD270_ETH_PHYS		(PXA_CS2_PHYS + 0x01000000)
 
 /* CPLD registers  */
-#define LPD270_CPLD_REG(x)	((unsigned long)(LPD270_CPLD_VIRT + (x)))
+#define LPD270_CPLD_REG(x)	(LPD270_CPLD_VIRT + (x))
 #define LPD270_CONTROL		LPD270_CPLD_REG(0x00)
 #define LPD270_PERIPHERAL0	LPD270_CPLD_REG(0x04)
 #define LPD270_PERIPHERAL1	LPD270_CPLD_REG(0x08)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/*
- *  arch/arm/mach-pxa/include/mach/memory.h
- *
- * Author:	Nicolas Pitre
- * Copyright:	(C) 2001 MontaVista Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0xa0000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/mtd-xip.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/mtd-xip.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/mtd-xip.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/mtd-xip.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,6 @@
 #define __ARCH_PXA_MTD_XIP_H__
 
 #include <mach/regs-ost.h>
-#include <mach/regs-intc.h>
 
 #define xip_irqpending()	(ICIP & ICMR)
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/palm27x.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/palm27x.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/palm27x.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/palm27x.h	2012-01-04 18:55:44.000000000 -0500
@@ -34,11 +34,11 @@
 extern void __init palm27x_lcd_init(int power,
 					struct pxafb_mode_info *mode);
 #else
-static inline void palm27x_lcd_init(int power, struct pxafb_mode_info *mode) {}
+#define palm27x_lcd_init(power, mode)	do {} while (0)
 #endif
 
-#if	defined(CONFIG_USB_GADGET_PXA27X) || \
-	defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if	defined(CONFIG_USB_PXA27X) || \
+	defined(CONFIG_USB_PXA27X_MODULE)
 extern void __init palm27x_udc_init(int vbus, int pullup,
 					int vbus_inverted);
 #else
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/palmtx.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/palmtx.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/palmtx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/palmtx.h	2012-01-04 18:55:44.000000000 -0500
@@ -71,7 +71,7 @@
 
 /* Various addresses  */
 #define PALMTX_PCMCIA_PHYS	0x28000000
-#define PALMTX_PCMCIA_VIRT	0xf0000000
+#define PALMTX_PCMCIA_VIRT	IOMEM(0xf0000000)
 #define PALMTX_PCMCIA_SIZE	0x100000
 
 #define PALMTX_PHYS_RAM_START	0xa0000000
@@ -84,8 +84,8 @@
 
 #define PALMTX_NAND_ALE_PHYS	(PALMTX_PHYS_NAND_START | (1 << 24))
 #define PALMTX_NAND_CLE_PHYS	(PALMTX_PHYS_NAND_START | (1 << 25))
-#define PALMTX_NAND_ALE_VIRT	0xff100000
-#define PALMTX_NAND_CLE_VIRT	0xff200000
+#define PALMTX_NAND_ALE_VIRT	IOMEM(0xff100000)
+#define PALMTX_NAND_CLE_VIRT	IOMEM(0xff200000)
 
 /* TOUCHSCREEN */
 #define AC97_LINK_FRAME			21
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/pxa27x.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/pxa27x.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/pxa27x.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/pxa27x.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 #ifndef __MACH_PXA27x_H
 #define __MACH_PXA27x_H
 
+#include <linux/suspend.h>
 #include <mach/hardware.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa27x.h>
@@ -21,6 +22,7 @@
 extern void __init pxa27x_map_io(void);
 extern void __init pxa27x_init_irq(void);
 extern int __init pxa27x_set_pwrmode(unsigned int mode);
+extern void pxa27x_cpu_pm_enter(suspend_state_t state);
 
 #define pxa27x_handle_irq	ichp_handle_irq
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/pxa95x.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/pxa95x.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/pxa95x.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/pxa95x.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,7 @@
+#ifndef __MACH_PXA95X_H
+#define __MACH_PXA95X_H
+
+#include <mach/pxa3xx.h>
+#include <mach/mfp-pxa930.h>
+
+#endif /* __MACH_PXA95X_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/pxafb.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/pxafb.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/pxafb.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/pxafb.h	2012-01-04 18:55:44.000000000 -0500
@@ -158,5 +158,18 @@
 void pxa_set_fb_info(struct device *, struct pxafb_mach_info *);
 unsigned long pxafb_get_hsync_time(struct device *dev);
 
+#ifdef CONFIG_FB_PXA_SMARTPANEL
 extern int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int);
 extern int pxafb_smart_flush(struct fb_info *info);
+#else
+static inline int pxafb_smart_queue(struct fb_info *info,
+				    uint16_t *cmds, int n)
+{
+	return 0;
+}
+
+static inline int pxafb_smart_flush(struct fb_info *info)
+{
+	return 0;
+}
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/smemc.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/smemc.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/smemc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/smemc.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
 
 #define PXA2XX_SMEMC_BASE	0x48000000
 #define PXA3XX_SMEMC_BASE	0x4a000000
-#define SMEMC_VIRT		0xf6000000
+#define SMEMC_VIRT		IOMEM(0xf6000000)
 
 #define MDCNFG		(SMEMC_VIRT + 0x00)  /* SDRAM Configuration Register 0 */
 #define MDREFR		(SMEMC_VIRT + 0x04)  /* SDRAM Refresh Control Register */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/zeus.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/zeus.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/zeus.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/zeus.h	2012-01-04 18:55:44.000000000 -0500
@@ -68,7 +68,7 @@
  * Be gentle, and remap that over 32kB...
  */
 
-#define ZEUS_CPLD		(0xf0000000)
+#define ZEUS_CPLD		IOMEM(0xf0000000)
 #define ZEUS_CPLD_VERSION	(ZEUS_CPLD + 0x0000)
 #define ZEUS_CPLD_ISA_IRQ	(ZEUS_CPLD + 0x1000)
 #define ZEUS_CPLD_CONTROL	(ZEUS_CPLD + 0x2000)
@@ -76,7 +76,7 @@
 /* CPLD register bits */
 #define ZEUS_CPLD_CONTROL_CF_RST        0x01
 
-#define ZEUS_PC104IO		(0xf1000000)
+#define ZEUS_PC104IO		IOMEM(0xf1000000)
 
 #define ZEUS_SRAM_SIZE		(256 * 1024)
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/zylonite.h linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/zylonite.h
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/include/mach/zylonite.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/include/mach/zylonite.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 extern int lcd_id;
 extern int lcd_orientation;
 
-#ifdef CONFIG_CPU_PXA300
+#ifdef CONFIG_MACH_ZYLONITE300
 extern void zylonite_pxa300_init(void);
 #else
 static inline void zylonite_pxa300_init(void)
@@ -29,7 +29,7 @@
 }
 #endif
 
-#ifdef CONFIG_CPU_PXA320
+#ifdef CONFIG_MACH_ZYLONITE320
 extern void zylonite_pxa320_init(void);
 #else
 static inline void zylonite_pxa320_init(void)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/irq.c linux-libre-3.2-gnu/arch/arm/mach-pxa/irq.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,6 @@
  *  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>
@@ -19,13 +18,15 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 
+#include <asm/exception.h>
+
 #include <mach/hardware.h>
 #include <mach/irqs.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
 
 #include "generic.h"
 
-#define IRQ_BASE		(void __iomem *)io_p2v(0x40d00000)
+#define IRQ_BASE		io_p2v(0x40d00000)
 
 #define ICIP			(0x000)
 #define ICMR			(0x004)
@@ -63,7 +64,7 @@
 		0x40d00130,
 	};
 
-	return (void __iomem *)io_p2v(phys_base[i]);
+	return io_p2v(phys_base[i]);
 }
 
 void pxa_mask_irq(struct irq_data *d)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/Kconfig linux-libre-3.2-gnu/arch/arm/mach-pxa/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,27 @@
 
 menu "Intel PXA2xx/PXA3xx Implementations"
 
+config ARCH_PXA_V7
+	bool "ARMv7 (PXA95x) based systems"
+
+if ARCH_PXA_V7
+comment "Marvell Dev Platforms (sorted by hardware release time)"
+config MACH_TAVOREVB3
+	bool "PXA95x Development Platform (aka TavorEVB III)"
+	select CPU_PXA955
+
+config MACH_SAARB
+	bool "PXA955 Handheld Platform (aka SAARB)"
+	select CPU_PXA955
+endif
+
+config PXA_V7_MACH_AUTO
+	def_bool y
+	depends on ARCH_PXA_V7
+	depends on !MACH_SAARB
+	select MACH_TAVOREVB3
+
+if !ARCH_PXA_V7
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
 config ARCH_LUBBOCK
@@ -41,19 +62,11 @@
 	select PXA3xx
 	select CPU_PXA930
 
-config MACH_TAVOREVB3
-	bool "PXA95x Development Platform (aka TavorEVB III)"
-	select CPU_PXA950
-
 config MACH_SAAR
 	bool "PXA930 Handheld Platform (aka SAAR)"
 	select PXA3xx
 	select CPU_PXA930
 
-config MACH_SAARB
-	bool "PXA955 Handheld Platform (aka SAARB)"
-	select CPU_PXA955
-
 comment "Third Party Dev Platforms (sorted by vendor name)"
 
 config ARCH_PXA_IDP
@@ -414,6 +427,7 @@
 	bool "Palm Centro 685 (GSM)"
 	default y
 	depends on ARCH_PXA_PALM
+	select MACH_PALM27X
 	select PXA27x
 	select IWMMXT
 	select PALM_TREO
@@ -425,6 +439,7 @@
 	bool "Palm Treo 680"
 	default y
 	depends on ARCH_PXA_PALM
+	select MACH_PALM27X
 	select PXA27x
 	select IWMMXT
 	select PALM_TREO
@@ -436,15 +451,18 @@
 	bool "Raumfeld Controller"
 	select PXA3xx
 	select CPU_PXA300
+	select POWER_SUPPLY
 	select HAVE_PWM
 
 config MACH_RAUMFELD_CONNECTOR
 	bool "Raumfeld Connector"
+	select POWER_SUPPLY
 	select PXA3xx
 	select CPU_PXA300
 
 config MACH_RAUMFELD_SPEAKER
 	bool "Raumfeld Speaker"
+	select POWER_SUPPLY
 	select PXA3xx
 	select CPU_PXA300
 
@@ -598,7 +616,7 @@
 	bool "Zipit Z2 Handheld"
 	select PXA27x
 	select HAVE_PWM
-
+endif
 endmenu
 
 config PXA25x
@@ -688,6 +706,8 @@
 config SHARPSL_PM_MAX1111
 	bool
 	select HWMON
+	select SPI
+	select SPI_MASTER
 	select SENSORS_MAX1111
 
 config PXA_HAVE_ISA_IRQS
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/littleton.c linux-libre-3.2-gnu/arch/arm/mach-pxa/littleton.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/littleton.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/littleton.c	2012-01-04 18:55:44.000000000 -0500
@@ -325,8 +325,9 @@
 
 static struct pxa3xx_nand_platform_data littleton_nand_info = {
 	.enable_arbiter	= 1,
-	.parts		= littleton_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(littleton_nand_partitions),
+	.num_cs		= 1,
+	.parts[0]	= littleton_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(littleton_nand_partitions),
 };
 
 static void __init littleton_init_nand(void)
@@ -437,7 +438,7 @@
 }
 
 MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleton)")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa3xx_map_io,
 	.nr_irqs	= LITTLETON_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/lpd270.c linux-libre-3.2-gnu/arch/arm/mach-pxa/lpd270.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/lpd270.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/lpd270.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/syscore_ops.h>
@@ -39,7 +39,6 @@
 #include <asm/mach/flash.h>
 
 #include <mach/pxa27x.h>
-#include <mach/gpio.h>
 #include <mach/lpd270.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
@@ -480,7 +479,7 @@
 
 static struct map_desc lpd270_io_desc[] __initdata = {
 	{
-		.virtual	= LPD270_CPLD_VIRT,
+		.virtual	= (unsigned long)LPD270_CPLD_VIRT,
 		.pfn		= __phys_to_pfn(LPD270_CPLD_PHYS),
 		.length		= LPD270_CPLD_SIZE,
 		.type		= MT_DEVICE,
@@ -499,7 +498,7 @@
 
 MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine")
 	/* Maintainer: Peter Barada */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= lpd270_map_io,
 	.nr_irqs	= LPD270_NR_IRQS,
 	.init_irq	= lpd270_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/lubbock.c linux-libre-3.2-gnu/arch/arm/mach-pxa/lubbock.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/lubbock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/lubbock.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  *  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/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -42,7 +43,6 @@
 #include <asm/hardware/sa1111.h>
 
 #include <mach/pxa25x.h>
-#include <mach/gpio.h>
 #include <mach/audio.h>
 #include <mach/lubbock.h>
 #include <mach/udc.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/magician.c linux-libre-3.2-gnu/arch/arm/mach-pxa/magician.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/magician.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/magician.c	2012-01-04 18:55:44.000000000 -0500
@@ -753,7 +753,7 @@
 
 
 MACHINE_START(MAGICIAN, "HTC Magician")
-	.boot_params = 0xa0000100,
+	.atag_offset = 0x100,
 	.map_io = pxa27x_map_io,
 	.nr_irqs = MAGICIAN_NR_IRQS,
 	.init_irq = pxa27x_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/mainstone.c linux-libre-3.2-gnu/arch/arm/mach-pxa/mainstone.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/mainstone.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/mainstone.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/syscore_ops.h>
@@ -43,7 +43,6 @@
 #include <asm/mach/flash.h>
 
 #include <mach/pxa27x.h>
-#include <mach/gpio.h>
 #include <mach/mainstone.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
@@ -616,7 +615,7 @@
 
 MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
 	/* Maintainer: MontaVista Software Inc. */
-	.boot_params	= 0xa0000100,	/* BLOB boot parameter setting */
+	.atag_offset	= 0x100,	/* BLOB boot parameter setting */
 	.map_io		= mainstone_map_io,
 	.nr_irqs	= MAINSTONE_NR_IRQS,
 	.init_irq	= mainstone_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/Makefile linux-libre-3.2-gnu/arch/arm/mach-pxa/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 obj-$(CONFIG_PXA25x)		+= mfp-pxa2xx.o clock-pxa2xx.o pxa2xx.o pxa25x.o
 obj-$(CONFIG_PXA27x)		+= mfp-pxa2xx.o clock-pxa2xx.o pxa2xx.o pxa27x.o
 obj-$(CONFIG_PXA3xx)		+= mfp-pxa3xx.o clock-pxa3xx.o pxa3xx.o smemc.o pxa3xx-ulpi.o
-obj-$(CONFIG_PXA95x)		+= mfp-pxa3xx.o clock-pxa3xx.o pxa95x.o smemc.o
+obj-$(CONFIG_PXA95x)		+= mfp-pxa3xx.o clock-pxa3xx.o pxa3xx.o pxa95x.o smemc.o
 obj-$(CONFIG_CPU_PXA300)	+= pxa300.o
 obj-$(CONFIG_CPU_PXA320)	+= pxa320.o
 obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-pxa/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-   zreladdr-y	:= 0xa0008000
+   zreladdr-y	+= 0xa0008000
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/mfp-pxa2xx.c linux-libre-3.2-gnu/arch/arm/mach-pxa/mfp-pxa2xx.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/mfp-pxa2xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/mfp-pxa2xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,15 +12,15 @@
  *  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/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/syscore_ops.h>
 
-#include <mach/gpio.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa2xx.h>
+#include <mach/gpio-pxa.h>
 
 #include "generic.h"
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/mioa701.c linux-libre-3.2-gnu/arch/arm/mach-pxa/mioa701.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/mioa701.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/mioa701.c	2012-01-04 18:55:44.000000000 -0500
@@ -751,7 +751,7 @@
 }
 
 MACHINE_START(MIOA701, "MIO A701")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= &pxa27x_map_io,
 	.init_irq	= &pxa27x_init_irq,
 	.handle_irq	= &pxa27x_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/mp900.c linux-libre-3.2-gnu/arch/arm/mach-pxa/mp900.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/mp900.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/mp900.c	2012-01-04 18:55:44.000000000 -0500
@@ -92,7 +92,7 @@
 
 /* Maintainer - Michael Petchkovsky <mkpetch@internode.on.net> */
 MACHINE_START(NEC_MP900, "MobilePro900/C")
-	.boot_params	= 0xa0220100,
+	.atag_offset	= 0x220100,
 	.timer		= &pxa_timer,
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/mxm8x10.c linux-libre-3.2-gnu/arch/arm/mach-pxa/mxm8x10.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/mxm8x10.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/mxm8x10.c	2012-01-04 18:55:44.000000000 -0500
@@ -389,10 +389,11 @@
 };
 
 static struct pxa3xx_nand_platform_data mxm_8x10_nand_info = {
-	.enable_arbiter = 1,
-	.keep_config = 1,
-	.parts = mxm_8x10_nand_partitions,
-	.nr_parts = ARRAY_SIZE(mxm_8x10_nand_partitions)
+	.enable_arbiter	= 1,
+	.keep_config	= 1,
+	.num_cs		= 1,
+	.parts[0]	= mxm_8x10_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(mxm_8x10_nand_partitions)
 };
 
 static void __init mxm_8x10_nand_init(void)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/palm27x.c linux-libre-3.2-gnu/arch/arm/mach-pxa/palm27x.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/palm27x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/palm27x.c	2012-01-04 18:55:44.000000000 -0500
@@ -164,8 +164,8 @@
 /******************************************************************************
  * USB Gadget
  ******************************************************************************/
-#if	defined(CONFIG_USB_GADGET_PXA27X) || \
-	defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if	defined(CONFIG_USB_PXA27X) || \
+	defined(CONFIG_USB_PXA27X_MODULE)
 static struct gpio_vbus_mach_info palm27x_udc_info = {
 	.gpio_vbus_inverted	= 1,
 };
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/palmld.c linux-libre-3.2-gnu/arch/arm/mach-pxa/palmld.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/palmld.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/palmld.c	2012-01-04 18:55:44.000000000 -0500
@@ -342,7 +342,7 @@
 }
 
 MACHINE_START(PALMLD, "Palm LifeDrive")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= palmld_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/palmt5.c linux-libre-3.2-gnu/arch/arm/mach-pxa/palmt5.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/palmt5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/palmt5.c	2012-01-04 18:55:44.000000000 -0500
@@ -202,7 +202,7 @@
 }
 
 MACHINE_START(PALMT5, "Palm Tungsten|T5")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa27x_map_io,
 	.reserve	= palmt5_reserve,
 	.init_irq	= pxa27x_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/palmtc.c linux-libre-3.2-gnu/arch/arm/mach-pxa/palmtc.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/palmtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/palmtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -338,7 +338,7 @@
 /******************************************************************************
  * UDC
  ******************************************************************************/
-#if defined(CONFIG_USB_GADGET_PXA25X)||defined(CONFIG_USB_GADGET_PXA25X_MODULE)
+#if defined(CONFIG_USB_PXA25X)||defined(CONFIG_USB_PXA25X_MODULE)
 static struct gpio_vbus_mach_info palmtc_udc_info = {
 	.gpio_vbus		= GPIO_NR_PALMTC_USB_DETECT_N,
 	.gpio_vbus_inverted	= 1,
@@ -537,7 +537,7 @@
 };
 
 MACHINE_START(PALMTC, "Palm Tungsten|C")
-	.boot_params 	= 0xa0000100,
+	.atag_offset 	= 0x100,
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/palmte2.c linux-libre-3.2-gnu/arch/arm/mach-pxa/palmte2.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/palmte2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/palmte2.c	2012-01-04 18:55:44.000000000 -0500
@@ -356,7 +356,7 @@
 }
 
 MACHINE_START(PALMTE2, "Palm Tungsten|E2")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/palmtreo.c linux-libre-3.2-gnu/arch/arm/mach-pxa/palmtreo.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/palmtreo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/palmtreo.c	2012-01-04 18:55:44.000000000 -0500
@@ -423,6 +423,7 @@
 	palmtreo_leds_init();
 }
 
+#ifdef CONFIG_MACH_TREO680
 static void __init treo680_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(treo680_pin_config));
@@ -430,7 +431,9 @@
 	palm27x_mmc_init(GPIO_NR_TREO_SD_DETECT_N, GPIO_NR_TREO680_SD_READONLY,
 			GPIO_NR_TREO680_SD_POWER, 0);
 }
+#endif
 
+#ifdef CONFIG_MACH_CENTRO
 static void __init centro_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(centro685_pin_config));
@@ -438,9 +441,11 @@
 	palm27x_mmc_init(GPIO_NR_TREO_SD_DETECT_N, -1,
 			GPIO_NR_CENTRO_SD_POWER, 1);
 }
+#endif
 
+#ifdef CONFIG_MACH_TREO680
 MACHINE_START(TREO680, "Palm Treo 680")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
 	.reserve	= treo_reserve,
 	.init_irq       = pxa27x_init_irq,
@@ -448,9 +453,11 @@
 	.timer          = &pxa_timer,
 	.init_machine   = treo680_init,
 MACHINE_END
+#endif
 
+#ifdef CONFIG_MACH_CENTRO
 MACHINE_START(CENTRO, "Palm Centro 685")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
 	.reserve	= treo_reserve,
 	.init_irq       = pxa27x_init_irq,
@@ -458,3 +465,4 @@
 	.timer          = &pxa_timer,
 	.init_machine	= centro_init,
 MACHINE_END
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/palmtx.c linux-libre-3.2-gnu/arch/arm/mach-pxa/palmtx.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/palmtx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/palmtx.c	2012-01-04 18:55:44.000000000 -0500
@@ -247,7 +247,7 @@
 				 unsigned int ctrl)
 {
 	struct nand_chip *this = mtd->priv;
-	unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
+	char __iomem *nandaddr = this->IO_ADDR_W;
 
 	if (cmd == NAND_CMD_NONE)
 		return;
@@ -315,17 +315,17 @@
  ******************************************************************************/
 static struct map_desc palmtx_io_desc[] __initdata = {
 {
-	.virtual	= PALMTX_PCMCIA_VIRT,
+	.virtual	= (unsigned long)PALMTX_PCMCIA_VIRT,
 	.pfn		= __phys_to_pfn(PALMTX_PCMCIA_PHYS),
 	.length		= PALMTX_PCMCIA_SIZE,
 	.type		= MT_DEVICE,
 }, {
-	.virtual	= PALMTX_NAND_ALE_VIRT,
+	.virtual	= (unsigned long)PALMTX_NAND_ALE_VIRT,
 	.pfn		= __phys_to_pfn(PALMTX_NAND_ALE_PHYS),
 	.length		= SZ_1M,
 	.type		= MT_DEVICE,
 }, {
-	.virtual	= PALMTX_NAND_CLE_VIRT,
+	.virtual	= (unsigned long)PALMTX_NAND_CLE_VIRT,
 	.pfn		= __phys_to_pfn(PALMTX_NAND_CLE_PHYS),
 	.length		= SZ_1M,
 	.type		= MT_DEVICE,
@@ -364,7 +364,7 @@
 }
 
 MACHINE_START(PALMTX, "Palm T|X")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= palmtx_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/palmz72.c linux-libre-3.2-gnu/arch/arm/mach-pxa/palmz72.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/palmz72.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/palmz72.c	2012-01-04 18:55:44.000000000 -0500
@@ -399,7 +399,7 @@
 }
 
 MACHINE_START(PALMZ72, "Palm Zire72")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/pcm027.c linux-libre-3.2-gnu/arch/arm/mach-pxa/pcm027.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/pcm027.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/pcm027.c	2012-01-04 18:55:44.000000000 -0500
@@ -258,7 +258,7 @@
 
 MACHINE_START(PCM027, "Phytec Messtechnik GmbH phyCORE-PXA270")
 	/* Maintainer: Pengutronix */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pcm027_map_io,
 	.nr_irqs	= PCM027_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/pcm990-baseboard.c linux-libre-3.2-gnu/arch/arm/mach-pxa/pcm990-baseboard.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/pcm990-baseboard.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/pcm990-baseboard.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
  *  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/irq.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
@@ -28,7 +28,6 @@
 
 #include <media/soc_camera.h>
 
-#include <asm/gpio.h>
 #include <mach/camera.h>
 #include <asm/mach/map.h>
 #include <mach/pxa27x.h>
@@ -395,9 +394,9 @@
 	}
 
 	if (flags & SOCAM_DATAWIDTH_8)
-		gpio_set_value(gpio_bus_switch, 1);
+		gpio_set_value_cansleep(gpio_bus_switch, 1);
 	else
-		gpio_set_value(gpio_bus_switch, 0);
+		gpio_set_value_cansleep(gpio_bus_switch, 0);
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/poodle.c linux-libre-3.2-gnu/arch/arm/mach-pxa/poodle.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/poodle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/poodle.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/fb.h>
 #include <linux/pm.h>
@@ -454,8 +455,8 @@
 	poodle_init_spi();
 }
 
-static void __init fixup_poodle(struct machine_desc *desc,
-		struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init fixup_poodle(struct tag *tags, char **cmdline,
+				struct meminfo *mi)
 {
 	sharpsl_save_param();
 	mi->nr_banks=1;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/pxa25x.c linux-libre-3.2-gnu/arch/arm/mach-pxa/pxa25x.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/pxa25x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/pxa25x.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
  * initialization stuff for PXA machines which can be overridden later if
  * need be.
  */
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -23,12 +24,12 @@
 #include <linux/suspend.h>
 #include <linux/syscore_ops.h>
 #include <linux/irq.h>
+#include <linux/gpio.h>
 
 #include <asm/mach/map.h>
 #include <asm/suspend.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
-#include <mach/gpio.h>
 #include <mach/pxa25x.h>
 #include <mach/reset.h>
 #include <mach/pm.h>
@@ -324,7 +325,7 @@
 
 static struct map_desc pxa25x_io_desc[] __initdata = {
 	{	/* Mem Ctl */
-		.virtual	= SMEMC_VIRT,
+		.virtual	= (unsigned long)SMEMC_VIRT,
 		.pfn		= __phys_to_pfn(PXA2XX_SMEMC_BASE),
 		.length		= 0x00200000,
 		.type		= MT_DEVICE
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/pxa27x.c linux-libre-3.2-gnu/arch/arm/mach-pxa/pxa27x.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/pxa27x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/pxa27x.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  * 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/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -20,13 +21,13 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/i2c/pxa-i2c.h>
+#include <linux/gpio.h>
 
 #include <asm/mach/map.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/suspend.h>
 #include <mach/irqs.h>
-#include <mach/gpio.h>
 #include <mach/pxa27x.h>
 #include <mach/reset.h>
 #include <mach/ohci.h>
@@ -390,7 +391,7 @@
 
 static struct map_desc pxa27x_io_desc[] __initdata = {
 	{	/* Mem Ctl */
-		.virtual	= SMEMC_VIRT,
+		.virtual	= (unsigned long)SMEMC_VIRT,
 		.pfn		= __phys_to_pfn(PXA2XX_SMEMC_BASE),
 		.length		= 0x00200000,
 		.type		= MT_DEVICE
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/pxa3xx.c linux-libre-3.2-gnu/arch/arm/mach-pxa/pxa3xx.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/pxa3xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/pxa3xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,6 @@
  * 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>
@@ -26,7 +25,7 @@
 #include <asm/mach/map.h>
 #include <asm/suspend.h>
 #include <mach/hardware.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
 #include <mach/pxa3xx-regs.h>
 #include <mach/reset.h>
 #include <mach/ohci.h>
@@ -394,7 +393,7 @@
 
 static struct map_desc pxa3xx_io_desc[] __initdata = {
 	{	/* Mem Ctl */
-		.virtual	= SMEMC_VIRT,
+		.virtual	= (unsigned long)SMEMC_VIRT,
 		.pfn		= __phys_to_pfn(PXA3XX_SMEMC_BASE),
 		.length		= 0x00200000,
 		.type		= MT_DEVICE
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/pxa3xx-ulpi.c linux-libre-3.2-gnu/arch/arm/mach-pxa/pxa3xx-ulpi.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/pxa3xx-ulpi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/pxa3xx-ulpi.c	2012-01-04 18:55:44.000000000 -0500
@@ -265,6 +265,7 @@
 
 	return err;
 }
+EXPORT_SYMBOL_GPL(pxa3xx_u2d_start_hc);
 
 void pxa3xx_u2d_stop_hc(struct usb_bus *host)
 {
@@ -277,6 +278,7 @@
 
 	clk_disable(u2d->clk);
 }
+EXPORT_SYMBOL_GPL(pxa3xx_u2d_stop_hc);
 
 static int pxa3xx_u2d_probe(struct platform_device *pdev)
 {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/pxa95x.c linux-libre-3.2-gnu/arch/arm/mach-pxa/pxa95x.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/pxa95x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/pxa95x.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@
  * 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>
@@ -21,7 +20,7 @@
 #include <linux/syscore_ops.h>
 
 #include <mach/hardware.h>
-#include <mach/gpio.h>
+#include <mach/gpio-pxa.h>
 #include <mach/pxa3xx-regs.h>
 #include <mach/pxa930.h>
 #include <mach/reset.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/raumfeld.c linux-libre-3.2-gnu/arch/arm/mach-pxa/raumfeld.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/raumfeld.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/raumfeld.c	2012-01-04 18:55:44.000000000 -0500
@@ -346,8 +346,9 @@
 static struct pxa3xx_nand_platform_data raumfeld_nand_info = {
 	.enable_arbiter	= 1,
 	.keep_config	= 1,
-	.parts		= raumfeld_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(raumfeld_nand_partitions),
+	.num_cs		= 1,
+	.parts[0]	= raumfeld_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(raumfeld_nand_partitions),
 };
 
 /**
@@ -1086,7 +1087,7 @@
 
 #ifdef CONFIG_MACH_RAUMFELD_RC
 MACHINE_START(RAUMFELD_RC, "Raumfeld Controller")
-	.boot_params	= RAUMFELD_SDRAM_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.init_machine	= raumfeld_controller_init,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
@@ -1097,7 +1098,7 @@
 
 #ifdef CONFIG_MACH_RAUMFELD_CONNECTOR
 MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector")
-	.boot_params	= RAUMFELD_SDRAM_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.init_machine	= raumfeld_connector_init,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
@@ -1108,7 +1109,7 @@
 
 #ifdef CONFIG_MACH_RAUMFELD_SPEAKER
 MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker")
-	.boot_params	= RAUMFELD_SDRAM_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.init_machine	= raumfeld_speaker_init,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/saarb.c linux-libre-3.2-gnu/arch/arm/mach-pxa/saarb.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/saarb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/saarb.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,12 +9,13 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  publishhed by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pxa-i2c.h>
 #include <linux/mfd/88pm860x.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -23,7 +24,7 @@
 #include <mach/hardware.h>
 #include <mach/mfp.h>
 #include <mach/mfp-pxa930.h>
-#include <mach/gpio.h>
+#include <mach/pxa95x.h>
 
 #include "generic.h"
 
@@ -103,7 +104,7 @@
 }
 
 MACHINE_START(SAARB, "PXA955 Handheld Platform (aka SAARB)")
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa3xx_map_io,
 	.nr_irqs	= SAARB_NR_IRQS,
 	.init_irq       = pxa95x_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/saar.c linux-libre-3.2-gnu/arch/arm/mach-pxa/saar.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/saar.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/saar.c	2012-01-04 18:55:44.000000000 -0500
@@ -540,7 +540,7 @@
 	}, {
 		.name		= "filesystem",
 		.offset		= MTDPART_OFS_APPEND,
-		.size		= SZ_48M,
+		.size		= SZ_32M + SZ_16M,
 		.mask_flags	= 0,
 	}
 };
@@ -596,7 +596,7 @@
 
 MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
 	/* Maintainer: Eric Miao <eric.miao@marvell.com> */
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa3xx_map_io,
 	.init_irq       = pxa3xx_init_irq,
 	.handle_irq       = pxa3xx_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/spitz.c linux-libre-3.2-gnu/arch/arm/mach-pxa/spitz.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/spitz.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/spitz.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/input/matrix_keypad.h>
 #include <linux/regulator/machine.h>
 #include <linux/io.h>
+#include <linux/module.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -970,8 +971,8 @@
 	spitz_i2c_init();
 }
 
-static void __init spitz_fixup(struct machine_desc *desc,
-		struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init spitz_fixup(struct tag *tags, char **cmdline,
+			       struct meminfo *mi)
 {
 	sharpsl_save_param();
 	mi->nr_banks = 1;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/stargate2.c linux-libre-3.2-gnu/arch/arm/mach-pxa/stargate2.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/stargate2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/stargate2.c	2012-01-04 18:55:44.000000000 -0500
@@ -1004,7 +1004,7 @@
 	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= imote2_init,
-	.boot_params	= 0xA0000100,
+	.atag_offset	= 0x100,
 MACHINE_END
 #endif
 
@@ -1016,6 +1016,6 @@
 	.handle_irq = pxa27x_handle_irq,
 	.timer = &pxa_timer,
 	.init_machine = stargate2_init,
-	.boot_params = 0xA0000100,
+	.atag_offset = 0x100,
 MACHINE_END
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/tavorevb3.c linux-libre-3.2-gnu/arch/arm/mach-pxa/tavorevb3.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/tavorevb3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/tavorevb3.c	2012-01-04 18:55:44.000000000 -0500
@@ -125,7 +125,7 @@
 }
 
 MACHINE_START(TAVOREVB3, "PXA950 Evaluation Board (aka TavorEVB3)")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io         = pxa3xx_map_io,
 	.nr_irqs	= TAVOREVB3_NR_IRQS,
 	.init_irq       = pxa3xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/tavorevb.c linux-libre-3.2-gnu/arch/arm/mach-pxa/tavorevb.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/tavorevb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/tavorevb.c	2012-01-04 18:55:44.000000000 -0500
@@ -489,7 +489,7 @@
 
 MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
 	/* Maintainer: Eric Miao <eric.miao@marvell.com> */
-	.boot_params    = 0xa0000100,
+	.atag_offset    = 0x100,
 	.map_io         = pxa3xx_map_io,
 	.init_irq       = pxa3xx_init_irq,
 	.handle_irq       = pxa3xx_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/tosa.c linux-libre-3.2-gnu/arch/arm/mach-pxa/tosa.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/tosa.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/tosa.c	2012-01-04 18:55:44.000000000 -0500
@@ -960,8 +960,8 @@
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
-static void __init fixup_tosa(struct machine_desc *desc,
-		struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init fixup_tosa(struct tag *tags, char **cmdline,
+			      struct meminfo *mi)
 {
 	sharpsl_save_param();
 	mi->nr_banks=1;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/trizeps4.c linux-libre-3.2-gnu/arch/arm/mach-pxa/trizeps4.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/trizeps4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/trizeps4.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/bitops.h>
 #include <linux/fb.h>
@@ -554,7 +555,7 @@
 
 MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
 	/* MAINTAINER("JÃ¼rgen Schindele") */
-	.boot_params	= TRIZEPS4_SDRAM_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.init_machine	= trizeps4_init,
 	.map_io		= trizeps4_map_io,
 	.init_irq	= pxa27x_init_irq,
@@ -564,7 +565,7 @@
 
 MACHINE_START(TRIZEPS4WL, "Keith und Koep Trizeps IV-WL module")
 	/* MAINTAINER("JÃ¼rgen Schindele") */
-	.boot_params	= TRIZEPS4_SDRAM_BASE + 0x100,
+	.atag_offset	= 0x100,
 	.init_machine	= trizeps4_init,
 	.map_io		= trizeps4_map_io,
 	.init_irq	= pxa27x_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/viper.c linux-libre-3.2-gnu/arch/arm/mach-pxa/viper.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/viper.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/viper.c	2012-01-04 18:55:44.000000000 -0500
@@ -992,7 +992,7 @@
 
 MACHINE_START(VIPER, "Arcom/Eurotech VIPER SBC")
 	/* Maintainer: Marc Zyngier <maz@misterjones.org> */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= viper_map_io,
 	.init_irq	= viper_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/vpac270.c linux-libre-3.2-gnu/arch/arm/mach-pxa/vpac270.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/vpac270.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/vpac270.c	2012-01-04 18:55:44.000000000 -0500
@@ -343,7 +343,7 @@
 /******************************************************************************
  * USB Gadget
  ******************************************************************************/
-#if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE)
 static struct gpio_vbus_mach_info vpac270_gpio_vbus_info = {
 	.gpio_vbus		= GPIO41_VPAC270_UDC_DETECT,
 	.gpio_pullup		= -1,
@@ -716,7 +716,7 @@
 }
 
 MACHINE_START(VPAC270, "Voipac PXA270")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/xcep.c linux-libre-3.2-gnu/arch/arm/mach-pxa/xcep.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/xcep.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/xcep.c	2012-01-04 18:55:44.000000000 -0500
@@ -142,8 +142,7 @@
 
 /* We have to state that there are HWMON devices on the I2C bus on XCEP.
  * Drivers for HWMON verify capabilities of the adapter when loading and
- * refuse to attach if the adapter doesn't support HWMON class of devices.
- * See also Documentation/i2c/porting-clients. */
+ * refuse to attach if the adapter doesn't support HWMON class of devices. */
 static struct i2c_pxa_platform_data xcep_i2c_platform_data  = {
 	.class = I2C_CLASS_HWMON
 };
@@ -180,7 +179,7 @@
 }
 
 MACHINE_START(XCEP, "Iskratel XCEP")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.init_machine	= xcep_init,
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/z2.c linux-libre-3.2-gnu/arch/arm/mach-pxa/z2.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/z2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/z2.c	2012-01-04 18:55:44.000000000 -0500
@@ -686,7 +686,8 @@
 	 */
 	PSPR = 0x0;
 	local_irq_disable();
-	pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+	pxa27x_set_pwrmode(PWRMODE_DEEPSLEEP);
+	pxa27x_cpu_pm_enter(PM_SUSPEND_MEM);
 }
 #else
 #define z2_power_off   NULL
@@ -718,7 +719,7 @@
 }
 
 MACHINE_START(ZIPIT2, "Zipit Z2")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/zeus.c linux-libre-3.2-gnu/arch/arm/mach-pxa/zeus.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/zeus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/zeus.c	2012-01-04 18:55:44.000000000 -0500
@@ -860,25 +860,25 @@
 
 static struct map_desc zeus_io_desc[] __initdata = {
 	{
-		.virtual = ZEUS_CPLD_VERSION,
+		.virtual = (unsigned long)ZEUS_CPLD_VERSION,
 		.pfn     = __phys_to_pfn(ZEUS_CPLD_VERSION_PHYS),
 		.length  = 0x1000,
 		.type    = MT_DEVICE,
 	},
 	{
-		.virtual = ZEUS_CPLD_ISA_IRQ,
+		.virtual = (unsigned long)ZEUS_CPLD_ISA_IRQ,
 		.pfn     = __phys_to_pfn(ZEUS_CPLD_ISA_IRQ_PHYS),
 		.length  = 0x1000,
 		.type    = MT_DEVICE,
 	},
 	{
-		.virtual = ZEUS_CPLD_CONTROL,
+		.virtual = (unsigned long)ZEUS_CPLD_CONTROL,
 		.pfn     = __phys_to_pfn(ZEUS_CPLD_CONTROL_PHYS),
 		.length  = 0x1000,
 		.type    = MT_DEVICE,
 	},
 	{
-		.virtual = ZEUS_PC104IO,
+		.virtual = (unsigned long)ZEUS_PC104IO,
 		.pfn     = __phys_to_pfn(ZEUS_PC104IO_PHYS),
 		.length  = 0x00800000,
 		.type    = MT_DEVICE,
@@ -904,7 +904,7 @@
 
 MACHINE_START(ARCOM_ZEUS, "Arcom/Eurotech ZEUS")
 	/* Maintainer: Marc Zyngier <maz@misterjones.org> */
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= zeus_map_io,
 	.nr_irqs	= ZEUS_NR_IRQS,
 	.init_irq	= zeus_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-pxa/zylonite.c linux-libre-3.2-gnu/arch/arm/mach-pxa/zylonite.c
--- linux-libre-3.1-gnu/arch/arm/mach-pxa/zylonite.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-pxa/zylonite.c	2012-01-04 18:55:44.000000000 -0500
@@ -366,8 +366,9 @@
 
 static struct pxa3xx_nand_platform_data zylonite_nand_info = {
 	.enable_arbiter	= 1,
-	.parts		= zylonite_nand_partitions,
-	.nr_parts	= ARRAY_SIZE(zylonite_nand_partitions),
+	.num_cs		= 1,
+	.parts[0]	= zylonite_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(zylonite_nand_partitions),
 };
 
 static void __init zylonite_init_nand(void)
@@ -422,7 +423,7 @@
 }
 
 MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
-	.boot_params	= 0xa0000100,
+	.atag_offset	= 0x100,
 	.map_io		= pxa3xx_map_io,
 	.nr_irqs	= ZYLONITE_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-realview/core.c linux-libre-3.2-gnu/arch/arm/mach-realview/core.c
--- linux-libre-3.1-gnu/arch/arm/mach-realview/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-realview/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -517,8 +517,7 @@
 /*
  * Setup the memory banks.
  */
-void realview_fixup(struct machine_desc *mdesc, struct tag *tags, char **from,
-		    struct meminfo *meminfo)
+void realview_fixup(struct tag *tags, char **from, struct meminfo *meminfo)
 {
 	/*
 	 * Most RealView platforms have 512MB contiguous RAM at 0x70000000.
diff -druN linux-libre-3.1-gnu/arch/arm/mach-realview/core.h linux-libre-3.2-gnu/arch/arm/mach-realview/core.h
--- linux-libre-3.1-gnu/arch/arm/mach-realview/core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-realview/core.h	2012-01-04 18:55:44.000000000 -0500
@@ -63,8 +63,8 @@
 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_fixup(struct tag *tags, char **from,
+			   struct meminfo *meminfo);
 extern void (*realview_reset)(char);
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-realview/hotplug.c linux-libre-3.2-gnu/arch/arm/mach-realview/hotplug.c
--- linux-libre-3.1-gnu/arch/arm/mach-realview/hotplug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-realview/hotplug.c	2012-01-04 18:55:44.000000000 -0500
@@ -69,7 +69,7 @@
 		    :
 		    : "memory", "cc");
 
-		if (pen_release == cpu) {
+		if (pen_release == cpu_logical_map(cpu)) {
 			/*
 			 * OK, proper wakeup, we're done
 			 */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-realview/include/mach/board-pb1176.h linux-libre-3.2-gnu/arch/arm/mach-realview/include/mach/board-pb1176.h
--- linux-libre-3.1-gnu/arch/arm/mach-realview/include/mach/board-pb1176.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-realview/include/mach/board-pb1176.h	2012-01-04 18:55:44.000000000 -0500
@@ -70,6 +70,7 @@
 
 #define REALVIEW_DC1176_GIC_CPU_BASE		0x10120000 /* GIC CPU interface, on devchip */
 #define REALVIEW_DC1176_GIC_DIST_BASE		0x10121000 /* GIC distributor, on devchip */
+#define REALVIEW_DC1176_ROM_BASE		0x10200000 /* 16KiB NRAM preudo-ROM, on devchip */
 #define REALVIEW_PB1176_GIC_CPU_BASE		0x10040000 /* GIC CPU interface, on FPGA */
 #define REALVIEW_PB1176_GIC_DIST_BASE		0x10041000 /* GIC distributor, on FPGA */
 #define REALVIEW_PB1176_L220_BASE		0x10110000 /* L220 registers */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-realview/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-realview/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-realview/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-realview/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -10,30 +10,17 @@
  * published by the Free Software Foundation.
  */
 
-#if defined(CONFIG_MACH_REALVIEW_EB) || \
-    defined(CONFIG_MACH_REALVIEW_PB11MP) || \
-    defined(CONFIG_MACH_REALVIEW_PBA8) || \
-    defined(CONFIG_MACH_REALVIEW_PBX)
-#ifndef DEBUG_LL_UART_OFFSET
+#ifdef CONFIG_DEBUG_REALVIEW_STD_PORT
 #define DEBUG_LL_UART_OFFSET	0x00009000
-#elif DEBUG_LL_UART_OFFSET != 0x00009000
-#warning "DEBUG_LL_UART_OFFSET already defined to a different value"
-#endif
-#endif
-
-#ifdef CONFIG_MACH_REALVIEW_PB1176
-#ifndef DEBUG_LL_UART_OFFSET
+#elif defined(CONFIG_DEBUG_REALVIEW_PB1176_PORT)
 #define DEBUG_LL_UART_OFFSET	0x0010c000
-#elif DEBUG_LL_UART_OFFSET != 0x0010c000
-#warning "DEBUG_LL_UART_OFFSET already defined to a different value"
-#endif
 #endif
 
 #ifndef DEBUG_LL_UART_OFFSET
 #error "Unknown RealView platform"
 #endif
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #DEBUG_LL_UART_OFFSET
 		orr	\rv, \rp, #0xfb000000	@ virtual base
 		orr	\rp, \rp, #0x10000000	@ physical base
diff -druN linux-libre-3.1-gnu/arch/arm/mach-realview/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-realview/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-realview/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-realview/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1 @@
-#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
+/* empty */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-realview/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-realview/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-realview/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-realview/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,9 +1,9 @@
 ifeq ($(CONFIG_REALVIEW_HIGH_PHYS_OFFSET),y)
-   zreladdr-y	:= 0x70008000
+   zreladdr-y	+= 0x70008000
 params_phys-y	:= 0x70000100
 initrd_phys-y	:= 0x70800000
 else
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
 endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-realview/platsmp.c linux-libre-3.2-gnu/arch/arm/mach-realview/platsmp.c
--- linux-libre-3.1-gnu/arch/arm/mach-realview/platsmp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-realview/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -52,12 +52,10 @@
 	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
 
 	/* sanity check */
-	if (ncores > NR_CPUS) {
-		printk(KERN_WARNING
-		       "Realview: no. of cores (%d) greater than configured "
-		       "maximum of %d - clipping\n",
-		       ncores, NR_CPUS);
-		ncores = NR_CPUS;
+	if (ncores > nr_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
 	}
 
 	for (i = 0; i < ncores; i++)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-realview/realview_eb.c linux-libre-3.2-gnu/arch/arm/mach-realview/realview_eb.c
--- linux-libre-3.1-gnu/arch/arm/mach-realview/realview_eb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-realview/realview_eb.c	2012-01-04 18:55:44.000000000 -0500
@@ -463,7 +463,7 @@
 
 MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
+	.atag_offset	= 0x100,
 	.fixup		= realview_fixup,
 	.map_io		= realview_eb_map_io,
 	.init_early	= realview_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-realview/realview_pb1176.c linux-libre-3.2-gnu/arch/arm/mach-realview/realview_pb1176.c
--- linux-libre-3.1-gnu/arch/arm/mach-realview/realview_pb1176.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-realview/realview_pb1176.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,8 @@
 #include <linux/amba/pl061.h>
 #include <linux/amba/mmci.h>
 #include <linux/amba/pl022.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/partitions.h>
 #include <linux/io.h>
 
 #include <mach/hardware.h>
@@ -204,22 +206,48 @@
  * RealView PB1176 platform devices
  */
 static struct resource realview_pb1176_flash_resources[] = {
-	[0] = {
+	{
 		.start		= REALVIEW_PB1176_FLASH_BASE,
 		.end		= REALVIEW_PB1176_FLASH_BASE + REALVIEW_PB1176_FLASH_SIZE - 1,
 		.flags		= IORESOURCE_MEM,
 	},
-	[1] = {
+#ifdef CONFIG_REALVIEW_PB1176_SECURE_FLASH
+	{
 		.start		= REALVIEW_PB1176_SEC_FLASH_BASE,
 		.end		= REALVIEW_PB1176_SEC_FLASH_BASE + REALVIEW_PB1176_SEC_FLASH_SIZE - 1,
 		.flags		= IORESOURCE_MEM,
 	},
-};
-#ifdef CONFIG_REALVIEW_PB1176_SECURE_FLASH
-#define PB1176_FLASH_BLOCKS	2
-#else
-#define PB1176_FLASH_BLOCKS	1
 #endif
+};
+
+static struct physmap_flash_data pb1176_rom_pdata = {
+	.probe_type	= "map_rom",
+	.width		= 4,
+	.nr_parts	= 0,
+};
+
+static struct resource pb1176_rom_resources[] = {
+	/*
+	 * This exposes the PB1176 DevChip ROM as an MTD ROM mapping.
+	 * The reference manual states that this is actually a pseudo-ROM
+	 * programmed in NVRAM.
+	 */
+	{
+		.start		= REALVIEW_DC1176_ROM_BASE,
+		.end		= REALVIEW_DC1176_ROM_BASE + SZ_16K - 1,
+		.flags		= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device pb1176_rom_device = {
+	.name		= "physmap-flash",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(pb1176_rom_resources),
+	.resource	= pb1176_rom_resources,
+	.dev = {
+		.platform_data = &pb1176_rom_pdata,
+	},
+};
 
 static struct resource realview_pb1176_smsc911x_resources[] = {
 	[0] = {
@@ -316,8 +344,7 @@
 	__raw_writel(REALVIEW_PB1176_SYS_SOFT_RESET, reset_ctrl);
 }
 
-static void realview_pb1176_fixup(struct machine_desc *mdesc,
-				  struct tag *tags, char **from,
+static void realview_pb1176_fixup(struct tag *tags, char **from,
 				  struct meminfo *meminfo)
 {
 	/*
@@ -338,7 +365,8 @@
 #endif
 
 	realview_flash_register(realview_pb1176_flash_resources,
-				PB1176_FLASH_BLOCKS);
+				ARRAY_SIZE(realview_pb1176_flash_resources));
+	platform_device_register(&pb1176_rom_device);
 	realview_eth_register(NULL, realview_pb1176_smsc911x_resources);
 	platform_device_register(&realview_i2c_device);
 	realview_usb_register(realview_pb1176_isp1761_resources);
@@ -358,7 +386,7 @@
 
 MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
+	.atag_offset	= 0x100,
 	.fixup		= realview_pb1176_fixup,
 	.map_io		= realview_pb1176_map_io,
 	.init_early	= realview_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-realview/realview_pb11mp.c linux-libre-3.2-gnu/arch/arm/mach-realview/realview_pb11mp.c
--- linux-libre-3.1-gnu/arch/arm/mach-realview/realview_pb11mp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-realview/realview_pb11mp.c	2012-01-04 18:55:44.000000000 -0500
@@ -360,7 +360,7 @@
 
 MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
+	.atag_offset	= 0x100,
 	.fixup		= realview_fixup,
 	.map_io		= realview_pb11mp_map_io,
 	.init_early	= realview_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-realview/realview_pba8.c linux-libre-3.2-gnu/arch/arm/mach-realview/realview_pba8.c
--- linux-libre-3.1-gnu/arch/arm/mach-realview/realview_pba8.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-realview/realview_pba8.c	2012-01-04 18:55:44.000000000 -0500
@@ -310,7 +310,7 @@
 
 MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
+	.atag_offset	= 0x100,
 	.fixup		= realview_fixup,
 	.map_io		= realview_pba8_map_io,
 	.init_early	= realview_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-realview/realview_pbx.c linux-libre-3.2-gnu/arch/arm/mach-realview/realview_pbx.c
--- linux-libre-3.1-gnu/arch/arm/mach-realview/realview_pbx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-realview/realview_pbx.c	2012-01-04 18:55:44.000000000 -0500
@@ -319,8 +319,8 @@
 	.init		= realview_pbx_timer_init,
 };
 
-static void realview_pbx_fixup(struct machine_desc *mdesc, struct tag *tags,
-			       char **from, struct meminfo *meminfo)
+static void realview_pbx_fixup(struct tag *tags, char **from,
+			       struct meminfo *meminfo)
 {
 #ifdef CONFIG_SPARSEMEM
 	/*
@@ -335,7 +335,7 @@
 	meminfo->bank[2].size = SZ_256M;
 	meminfo->nr_banks = 3;
 #else
-	realview_fixup(mdesc, tags, from, meminfo);
+	realview_fixup(tags, from, meminfo);
 #endif
 }
 
@@ -393,7 +393,7 @@
 
 MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
+	.atag_offset	= 0x100,
 	.fixup		= realview_pbx_fixup,
 	.map_io		= realview_pbx_map_io,
 	.init_early	= realview_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-rpc/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-rpc/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-rpc/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-rpc/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *
 */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x00010000
 		orr	\rp, \rp, #0x00000fe0
 		orr	\rv, \rp, #0xe0000000	@ virtual
diff -druN linux-libre-3.1-gnu/arch/arm/mach-rpc/include/mach/hardware.h linux-libre-3.2-gnu/arch/arm/mach-rpc/include/mach/hardware.h
--- linux-libre-3.1-gnu/arch/arm/mach-rpc/include/mach/hardware.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-rpc/include/mach/hardware.h	2012-01-04 18:55:44.000000000 -0500
@@ -36,7 +36,7 @@
 
 #define EASI_SIZE		0x08000000	/* EASI I/O */
 #define EASI_START		0x08000000
-#define EASI_BASE		0xe5000000
+#define EASI_BASE		IOMEM(0xe5000000)
 
 #define IO_START		0x03000000	/* I/O */
 #define IO_SIZE			0x01000000
@@ -51,21 +51,20 @@
 /*
  * IO Addresses
  */
-#define VIDC_BASE		IOMEM(0xe0400000)
-#define EXPMASK_BASE		0xe0360000
-#define IOMD_BASE		IOMEM(0xe0200000)
-#define IOC_BASE		IOMEM(0xe0200000)
-#define PCIO_BASE		IOMEM(0xe0010000)
-#define FLOPPYDMA_BASE		IOMEM(0xe002a000)
+#define ECARD_EASI_BASE		(EASI_BASE)
+#define VIDC_BASE		(IO_BASE + 0x00400000)
+#define EXPMASK_BASE		(IO_BASE + 0x00360000)
+#define ECARD_IOC4_BASE		(IO_BASE + 0x00270000)
+#define ECARD_IOC_BASE		(IO_BASE + 0x00240000)
+#define IOMD_BASE		(IO_BASE + 0x00200000)
+#define IOC_BASE		(IO_BASE + 0x00200000)
+#define ECARD_MEMC8_BASE	(IO_BASE + 0x0002b000)
+#define FLOPPYDMA_BASE		(IO_BASE + 0x0002a000)
+#define PCIO_BASE		(IO_BASE + 0x00010000)
+#define ECARD_MEMC_BASE		(IO_BASE + 0x00000000)
 
 #define vidc_writel(val)	__raw_writel(val, VIDC_BASE)
 
-#define IO_EC_EASI_BASE		0x81400000
-#define IO_EC_IOC4_BASE		0x8009c000
-#define IO_EC_IOC_BASE		0x80090000
-#define IO_EC_MEMC8_BASE	0x8000ac00
-#define IO_EC_MEMC_BASE		0x80000000
-
 #define NETSLOT_BASE		0x0302b000
 #define NETSLOT_SIZE		0x00001000
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-rpc/include/mach/io.h linux-libre-3.2-gnu/arch/arm/mach-rpc/include/mach/io.h
--- linux-libre-3.1-gnu/arch/arm/mach-rpc/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-rpc/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,195 +15,18 @@
 
 #include <mach/hardware.h>
 
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * We use two different types of addressing - PC style addresses, and ARM
- * addresses.  PC style accesses the PC hardware with the normal PC IO
- * addresses, eg 0x3f8 for serial#1.  ARM addresses are 0x80000000+
- * and are translated to the start of IO.  Note that all addresses are
- * shifted left!
- */
-#define __PORT_PCIO(x)	(!((x) & 0x80000000))
-
-/*
- * Dynamic IO functions.
- */
-static inline void __outb (unsigned int value, unsigned int port)
-{
-	unsigned long temp;
-	__asm__ __volatile__(
-	"tst	%2, #0x80000000\n\t"
-	"mov	%0, %4\n\t"
-	"addeq	%0, %0, %3\n\t"
-	"strb	%1, [%0, %2, lsl #2]	@ outb"
-	: "=&r" (temp)
-	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
-	: "cc");
-}
-
-static inline void __outw (unsigned int value, unsigned int port)
-{
-	unsigned long temp;
-	__asm__ __volatile__(
-	"tst	%2, #0x80000000\n\t"
-	"mov	%0, %4\n\t"
-	"addeq	%0, %0, %3\n\t"
-	"str	%1, [%0, %2, lsl #2]	@ outw"
-	: "=&r" (temp)
-	: "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
-	: "cc");
-}
-
-static inline void __outl (unsigned int value, unsigned int port)
-{
-	unsigned long temp;
-	__asm__ __volatile__(
-	"tst	%2, #0x80000000\n\t"
-	"mov	%0, %4\n\t"
-	"addeq	%0, %0, %3\n\t"
-	"str	%1, [%0, %2, lsl #2]	@ outl"
-	: "=&r" (temp)
-	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
-	: "cc");
-}
-
-#define DECLARE_DYN_IN(sz,fnsuffix,instr)					\
-static inline unsigned sz __in##fnsuffix (unsigned int port)		\
-{										\
-	unsigned long temp, value;						\
-	__asm__ __volatile__(							\
-	"tst	%2, #0x80000000\n\t"						\
-	"mov	%0, %4\n\t"							\
-	"addeq	%0, %0, %3\n\t"							\
-	"ldr" instr "	%1, [%0, %2, lsl #2]	@ in" #fnsuffix			\
-	: "=&r" (temp), "=r" (value)						\
-	: "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)		\
-	: "cc");								\
-	return (unsigned sz)value;						\
-}
-
-static inline void __iomem *__deprecated __ioaddr(unsigned int port)
-{
-	void __iomem *ret;
-	if (__PORT_PCIO(port))
-		ret = PCIO_BASE;
-	else
-		ret = IO_BASE;
-	return ret + (port << 2);
-}
-
-#define DECLARE_IO(sz,fnsuffix,instr)	\
-	DECLARE_DYN_IN(sz,fnsuffix,instr)
-
-DECLARE_IO(char,b,"b")
-DECLARE_IO(short,w,"")
-DECLARE_IO(int,l,"")
-
-#undef DECLARE_IO
-#undef DECLARE_DYN_IN
+#define IO_SPACE_LIMIT 0xffff
 
 /*
- * Constant address IO functions
+ * We need PC style IO addressing for:
+ *  - floppy (at 0x3f2,0x3f4,0x3f5,0x3f7)
+ *  - parport (at 0x278-0x27a, 0x27b-0x27f, 0x778-0x77a)
+ *  - 8250 serial (only for compile)
  *
- * These have to be macros for the 'J' constraint to work -
- * +/-4096 immediate operand.
+ * These peripherals are found in an area of MMIO which looks very much
+ * like an ISA bus, but with registers at the low byte of each word.
  */
-#define __outbc(value,port)							\
-({										\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"strb	%0, [%1, %2]	@ outbc"				\
-		: : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
-	else									\
-		__asm__ __volatile__(						\
-		"strb	%0, [%1, %2]	@ outbc"				\
-		: : "r" (value), "r" (IO_BASE), "r" ((port) << 2));		\
-})
-
-#define __inbc(port)								\
-({										\
-	unsigned char result;							\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"ldrb	%0, [%1, %2]	@ inbc"					\
-		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
-	else									\
-		__asm__ __volatile__(						\
-		"ldrb	%0, [%1, %2]	@ inbc"					\
-		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
-	result;									\
-})
-
-#define __outwc(value,port)							\
-({										\
-	unsigned long __v = value;						\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]	@ outwc"				\
-		: : "r" (__v|__v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2));	\
-	else									\
-		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]	@ outwc"				\
-		: : "r" (__v|__v<<16), "r" (IO_BASE), "r" ((port) << 2));		\
-})
-
-#define __inwc(port)								\
-({										\
-	unsigned short result;							\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]	@ inwc"					\
-		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
-	else									\
-		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]	@ inwc"					\
-		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
-	result & 0xffff;							\
-})
-
-#define __outlc(value,port)							\
-({										\
-	unsigned long __v = value;						\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]	@ outlc"				\
-		: : "r" (__v), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
-	else									\
-		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]	@ outlc"				\
-		: : "r" (__v), "r" (IO_BASE), "r" ((port) << 2));		\
-})
-
-#define __inlc(port)								\
-({										\
-	unsigned long result;							\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]	@ inlc"					\
-		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
-	else									\
-		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]	@ inlc"					\
-		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
-	result;									\
-})
-
-#define inb(p)	 	(__builtin_constant_p((p)) ? __inbc(p)    : __inb(p))
-#define inw(p)	 	(__builtin_constant_p((p)) ? __inwc(p)    : __inw(p))
-#define inl(p)	 	(__builtin_constant_p((p)) ? __inlc(p)    : __inl(p))
-#define outb(v,p)	(__builtin_constant_p((p)) ? __outbc(v,p) : __outb(v,p))
-#define outw(v,p)	(__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
-#define outl(v,p)	(__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
-
-/* the following macro is deprecated */
-#define ioaddr(port)	((unsigned long)__ioaddr((port)))
-
-#define insb(p,d,l)	__raw_readsb(__ioaddr(p),d,l)
-#define insw(p,d,l)	__raw_readsw(__ioaddr(p),d,l)
-
-#define outsb(p,d,l)	__raw_writesb(__ioaddr(p),d,l)
-#define outsw(p,d,l)	__raw_writesw(__ioaddr(p),d,l)
+#define __io(a)		(PCIO_BASE + ((a) << 2))
 
 /*
  * 1:1 mapping for ioremapped regions.
diff -druN linux-libre-3.1-gnu/arch/arm/mach-rpc/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-rpc/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-rpc/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-rpc/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x10008000
+   zreladdr-y	+= 0x10008000
 params_phys-y	:= 0x10000100
 initrd_phys-y	:= 0x18000000
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-rpc/riscpc.c linux-libre-3.2-gnu/arch/arm/mach-rpc/riscpc.c
--- linux-libre-3.1-gnu/arch/arm/mach-rpc/riscpc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-rpc/riscpc.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,7 +74,7 @@
 		.length		= 	IO_SIZE	 ,
 		.type		= MT_DEVICE
 	}, {	/* EASI space	*/
-		.virtual	= EASI_BASE,
+		.virtual	= (unsigned long)EASI_BASE,
 		.pfn		= __phys_to_pfn(EASI_START),
 		.length		= EASI_SIZE,
 		.type		= MT_DEVICE
@@ -218,7 +218,7 @@
 
 MACHINE_START(RISCPC, "Acorn-RiscPC")
 	/* Maintainer: Russell King */
-	.boot_params	= 0x10000100,
+	.atag_offset	= 0x100,
 	.reserve_lp0	= 1,
 	.reserve_lp1	= 1,
 	.map_io		= rpc_map_io,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2400/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-s3c2400/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2400/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2400/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/* arch/arm/mach-s3c2400/include/mach/memory.h
- *  from arch/arm/mach-rpc/include/mach/memory.h
- *
- *  Copyright 2007 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- *  Copyright (C) 1996,1997,1998 Russell King.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET	UL(0x0C000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/dma.c linux-libre-3.2-gnu/arch/arm/mach-s3c2410/dma.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,38 +47,26 @@
 		.channels[0]	= S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
 		.channels[2]	= S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
 		.channels[3]	= S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_SPI0] = {
 		.name		= "spi0",
 		.channels[1]	= S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
 	},
 	[DMACH_SPI1] = {
 		.name		= "spi1",
 		.channels[3]	= S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
 	},
 	[DMACH_UART0] = {
 		.name		= "uart0",
 		.channels[0]	= S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1] = {
 		.name		= "uart1",
 		.channels[1]	= S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2] = {
 		.name		= "uart2",
 		.channels[3]	= S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
 	[DMACH_TIMER] = {
 		.name		= "timer",
@@ -90,12 +78,10 @@
 		.name		= "i2s-sdi",
 		.channels[1]	= S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
 		.channels[2]	= S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_I2S_OUT] = {
 		.name		= "i2s-sdo",
 		.channels[2]	= S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_USB_EP1] = {
 		.name		= "usb-ep1",
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/gpio.c linux-libre-3.2-gnu/arch/arm/mach-s3c2410/gpio.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,72 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/gpio.c
- *
- * Copyright (c) 2004-2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 GPIO support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/gpio-fns.h>
-#include <asm/irq.h>
-
-#include <mach/regs-gpio.h>
-
-int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
-			   unsigned int config)
-{
-	void __iomem *reg = S3C24XX_EINFLT0;
-	unsigned long flags;
-	unsigned long val;
-
-	if (pin < S3C2410_GPG(8) || pin > S3C2410_GPG(15))
-		return -EINVAL;
-
-	config &= 0xff;
-
-	pin -= S3C2410_GPG(8);
-	reg += pin & ~3;
-
-	local_irq_save(flags);
-
-	/* update filter width and clock source */
-
-	val = __raw_readl(reg);
-	val &= ~(0xff << ((pin & 3) * 8));
-	val |= config << ((pin & 3) * 8);
-	__raw_writel(val, reg);
-
-	/* update filter enable */
-
-	val = __raw_readl(S3C24XX_EXTINT2);
-	val &= ~(1 << ((pin * 4) + 3));
-	val |= on << ((pin * 4) + 3);
-	__raw_writel(val, S3C24XX_EXTINT2);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 #define S3C2410_UART1_OFF (0x4000)
 #define SHIFT_2440TXF (14-9)
 
-	.macro addruart, rp, rv
+	.macro addruart, rp, rv, tmp
 		ldr	\rp, = S3C24XX_PA_UART
 		ldr	\rv, = S3C24XX_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/dma.h linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/dma.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H __FILE__
 
-#include <plat/dma.h>
 #include <linux/sysdev.h>
 
 #define MAX_DMA_TRANSFER_SIZE   0x100000 /* Data Unit is half word  */
@@ -51,6 +50,18 @@
 	DMACH_MAX,		/* the end entry */
 };
 
+static inline bool samsung_dma_has_circular(void)
+{
+	return false;
+}
+
+static inline bool samsung_dma_is_dmadev(void)
+{
+	return false;
+}
+
+#include <plat/dma.h>
+
 #define DMACH_LOW_LEVEL	(1<<28)	/* use this to specifiy hardware ch no */
 
 /* we have 4 dma channels */
@@ -163,7 +174,7 @@
 	struct s3c2410_dma_client *client;
 
 	/* channel configuration */
-	enum s3c2410_dmasrc	 source;
+	enum dma_data_direction	 source;
 	enum dma_ch		 req_ch;
 	unsigned long		 dev_addr;
 	unsigned long		 load_timeout;
@@ -196,9 +207,4 @@
 
 typedef unsigned long dma_device_t;
 
-static inline bool s3c_dma_has_circular(void)
-{
-	return false;
-}
-
 #endif /* __ASM_ARCH_DMA_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/fb.h linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/fb.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/fb.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/fb.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,74 +1 @@
-/* arch/arm/mach-s3c2410/include/mach/fb.h
- *
- * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
- *
- * Inspired by pxafb.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_ARM_FB_H
-#define __ASM_ARM_FB_H
-
-#include <mach/regs-lcd.h>
-
-struct s3c2410fb_hw {
-	unsigned long	lcdcon1;
-	unsigned long	lcdcon2;
-	unsigned long	lcdcon3;
-	unsigned long	lcdcon4;
-	unsigned long	lcdcon5;
-};
-
-/* LCD description */
-struct s3c2410fb_display {
-	/* LCD type */
-	unsigned type;
-
-	/* Screen size */
-	unsigned short width;
-	unsigned short height;
-
-	/* Screen info */
-	unsigned short xres;
-	unsigned short yres;
-	unsigned short bpp;
-
-	unsigned pixclock;		/* pixclock in picoseconds */
-	unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */
-	unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
-	unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */
-	unsigned short upper_margin;	/* value in lines (TFT) or 0 (STN) */
-	unsigned short lower_margin;	/* value in lines (TFT) or 0 (STN) */
-	unsigned short vsync_len;	/* value in lines (TFT) or 0 (STN) */
-
-	/* lcd configuration registers */
-	unsigned long	lcdcon5;
-};
-
-struct s3c2410fb_mach_info {
-
-	struct s3c2410fb_display *displays;	/* attached diplays info */
-	unsigned num_displays;			/* number of defined displays */
-	unsigned default_display;
-
-	/* GPIOs */
-
-	unsigned long	gpcup;
-	unsigned long	gpcup_mask;
-	unsigned long	gpccon;
-	unsigned long	gpccon_mask;
-	unsigned long	gpdup;
-	unsigned long	gpdup_mask;
-	unsigned long	gpdcon;
-	unsigned long	gpdcon_mask;
-
-	/* lpc3600 control register */
-	unsigned long	lpcsel;
-};
-
-extern void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *);
-
-#endif /* __ASM_ARM_FB_H */
+#include <plat/fb-s3c2410.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/gpio-fns.h linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/gpio-fns.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/gpio-fns.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/gpio-fns.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,98 +1 @@
-/* arch/arm/mach-s3c2410/include/mach/gpio-fns.h
- *
- * Copyright (c) 2003-2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 - hardware
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __MACH_GPIO_FNS_H
-#define __MACH_GPIO_FNS_H __FILE__
-
-/* These functions are in the to-be-removed category and it is strongly
- * encouraged not to use these in new code. They will be marked deprecated
- * very soon.
- *
- * Most of the functionality can be either replaced by the gpiocfg calls
- * for the s3c platform or by the generic GPIOlib API.
- *
- * As of 2.6.35-rc, these will be removed, with the few drivers using them
- * either replaced or given a wrapper until the calls can be removed.
-*/
-
-#include <plat/gpio-cfg.h>
-
-static inline void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int cfg)
-{
-	/* 1:1 mapping between cfgpin and setcfg calls at the moment */
-	s3c_gpio_cfgpin(pin, cfg);
-}
-
-/* external functions for GPIO support
- *
- * These allow various different clients to access the same GPIO
- * registers without conflicting. If your driver only owns the entire
- * GPIO register, then it is safe to ioremap/__raw_{read|write} to it.
-*/
-
-extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
-
-/* s3c2410_gpio_getirq
- *
- * turn the given pin number into the corresponding IRQ number
- *
- * returns:
- *	< 0 = no interrupt for this pin
- *	>=0 = interrupt number for the pin
-*/
-
-extern int s3c2410_gpio_getirq(unsigned int pin);
-
-/* s3c2410_gpio_irqfilter
- *
- * set the irq filtering on the given pin
- *
- * on = 0 => disable filtering
- *      1 => enable filtering
- *
- * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
- *          width of filter (0 through 63)
- *
- *
-*/
-
-extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
-				  unsigned int config);
-
-/* s3c2410_gpio_pullup
- *
- * This call should be replaced with s3c_gpio_setpull().
- *
- * As a note, there is currently no distinction between pull-up and pull-down
- * in the s3c24xx series devices with only an on/off configuration.
- */
-
-/* s3c2410_gpio_pullup
- *
- * configure the pull-up control on the given pin
- *
- * to = 1 => disable the pull-up
- *      0 => enable the pull-up
- *
- * eg;
- *
- *   s3c2410_gpio_pullup(S3C2410_GPB(0), 0);
- *   s3c2410_gpio_pullup(S3C2410_GPE(8), 0);
-*/
-
-extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
-
-extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
-
-extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
-
-#endif /* __MACH_GPIO_FNS_H */
+#include <plat/gpio-fns.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,11 +11,6 @@
  * published by the Free Software Foundation.
 */
 
-#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
-
 /* some boards require extra gpio capacity to support external
  * devices that need GPIO.
  */
@@ -28,7 +23,6 @@
 #define ARCH_NR_GPIOS	(256 + CONFIG_S3C24XX_GPIO_EXTRA)
 #endif
 
-#include <asm-generic/gpio.h>
 #include <mach/gpio-nrs.h>
 #include <mach/gpio-fns.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h	2012-01-04 18:55:44.000000000 -0500
@@ -53,7 +53,7 @@
 #define S3C2410_GPIO_M_NR	(32)	/* technically 2. */
 
 #if CONFIG_S3C_GPIO_SPACE != 0
-#error CONFIG_S3C_GPIO_SPACE cannot be zero at the moment
+#error CONFIG_S3C_GPIO_SPACE cannot be nonzero at the moment
 #endif
 
 #define S3C2410_GPIO_NEXT(__gpio) \
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/gpio-track.h linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/gpio-track.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/gpio-track.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/gpio-track.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,11 +17,11 @@
 
 #include <mach/regs-gpio.h>
 
-extern struct s3c_gpio_chip s3c24xx_gpios[];
+extern struct samsung_gpio_chip s3c24xx_gpios[];
 
-static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin)
+static inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int pin)
 {
-	struct s3c_gpio_chip *chip;
+	struct samsung_gpio_chip *chip;
 
 	if (pin > S3C_GPIO_END)
 		return NULL;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/h1940-latch.h linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/h1940-latch.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/h1940-latch.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/h1940-latch.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 #ifndef __ASM_ARCH_H1940_LATCH_H
 #define __ASM_ARCH_H1940_LATCH_H
 
-#include <mach/gpio.h>
+#include <asm/gpio.h>
 
 #define H1940_LATCH_GPIO(x)		(S3C_GPIO_END + (x))
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/io.h linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/io.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -199,8 +199,6 @@
 #define outw(v,p)	(__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
 #define outl(v,p)	(__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
 #define __ioaddr(p)	(__builtin_constant_p((p)) ? __ioaddr(p)  : __ioaddrc(p))
-/* the following macro is deprecated */
-#define ioaddr(port)	__ioaddr((port))
 
 #define insb(p,d,l)	__raw_readsb(__ioaddr(p),d,l)
 #define insw(p,d,l)	__raw_readsw(__ioaddr(p),d,l)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/irqs.h linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/irqs.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -191,9 +191,9 @@
 #define IRQ_LCD_SYSTEM		IRQ_S3C2443_LCD2
 
 #ifdef CONFIG_CPU_S3C2440
-#define IRQ_S3C244x_AC97 IRQ_S3C2440_AC97
+#define IRQ_S3C244X_AC97 IRQ_S3C2440_AC97
 #else
-#define IRQ_S3C244x_AC97 IRQ_S3C2443_AC97
+#define IRQ_S3C244X_AC97 IRQ_S3C2443_AC97
 #endif
 
 /* Our FIQs are routable from IRQ_EINT0 to IRQ_ADCPARENT */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/map.h linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/map.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/map.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,9 +14,53 @@
 #define __ASM_ARCH_MAP_H
 
 #include <plat/map-base.h>
-#include <plat/map.h>
 
-#define S3C2410_ADDR(x)		S3C_ADDR(x)
+/*
+ * S3C2410 UART offset is 0x4000 but the other SoCs are 0x400.
+ * So need to define it, and here is to avoid redefinition warning.
+ */
+#define S3C_UART_OFFSET		(0x4000)
+
+#include <plat/map-s3c.h>
+
+/*
+ * interrupt controller is the first thing we put in, to make
+ * the assembly code for the irq detection easier
+ */
+#define S3C2410_PA_IRQ		(0x4A000000)
+#define S3C24XX_SZ_IRQ		SZ_1M
+
+/* memory controller registers */
+#define S3C2410_PA_MEMCTRL	(0x48000000)
+#define S3C24XX_SZ_MEMCTRL	SZ_1M
+
+/* UARTs */
+#define S3C_VA_UARTx(uart)	(S3C_VA_UART + ((uart * S3C_UART_OFFSET)))
+
+/* Timers */
+#define S3C2410_PA_TIMER	(0x51000000)
+#define S3C24XX_SZ_TIMER	SZ_1M
+
+/* Clock and Power management */
+#define S3C24XX_SZ_CLKPWR	SZ_1M
+
+/* USB Device port */
+#define S3C2410_PA_USBDEV	(0x52000000)
+#define S3C24XX_SZ_USBDEV	SZ_1M
+
+/* Watchdog */
+#define S3C2410_PA_WATCHDOG	(0x53000000)
+#define S3C24XX_SZ_WATCHDOG	SZ_1M
+
+/* Standard size definitions for peripheral blocks. */
+
+#define S3C24XX_SZ_UART		SZ_1M
+#define S3C24XX_SZ_IIS		SZ_1M
+#define S3C24XX_SZ_ADC		SZ_1M
+#define S3C24XX_SZ_SPI		SZ_1M
+#define S3C24XX_SZ_SDI		SZ_1M
+#define S3C24XX_SZ_NAND		SZ_1M
+#define S3C24XX_SZ_GPIO		SZ_1M
 
 /* USB host controller */
 #define S3C2410_PA_USBHOST (0x49000000)
@@ -75,10 +119,8 @@
 
 /* S3C2412 memory and IO controls */
 #define S3C2412_PA_SSMC	(0x4F000000)
-#define S3C2412_VA_SSMC	S3C_ADDR_CPU(0x00000000)
 
 #define S3C2412_PA_EBI	(0x48800000)
-#define S3C2412_VA_EBI	S3C_ADDR_CPU(0x00010000)
 
 /* physical addresses of all the chip-select areas */
 
@@ -100,15 +142,14 @@
 #define S3C24XX_PA_DMA      S3C2410_PA_DMA
 #define S3C24XX_PA_CLKPWR   S3C2410_PA_CLKPWR
 #define S3C24XX_PA_LCD      S3C2410_PA_LCD
-#define S3C24XX_PA_UART     S3C2410_PA_UART
 #define S3C24XX_PA_TIMER    S3C2410_PA_TIMER
 #define S3C24XX_PA_USBDEV   S3C2410_PA_USBDEV
 #define S3C24XX_PA_WATCHDOG S3C2410_PA_WATCHDOG
 #define S3C24XX_PA_IIS      S3C2410_PA_IIS
-#define S3C24XX_PA_GPIO     S3C2410_PA_GPIO
 #define S3C24XX_PA_RTC      S3C2410_PA_RTC
 #define S3C24XX_PA_ADC      S3C2410_PA_ADC
 #define S3C24XX_PA_SPI      S3C2410_PA_SPI
+#define S3C24XX_PA_SPI1		(S3C2410_PA_SPI + S3C2410_SPI1)
 #define S3C24XX_PA_SDI      S3C2410_PA_SDI
 #define S3C24XX_PA_NAND	    S3C2410_PA_NAND
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/memory.h
- *  from arch/arm/mach-rpc/include/mach/memory.h
- *
- *  Copyright (C) 1996,1997,1998 Russell King.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET	UL(0x30000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/pm-core.h linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/pm-core.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/pm-core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/pm-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -64,4 +64,4 @@
 }
 
 static inline void s3c_pm_restored_gpios(void) { }
-static inline void s3c_pm_saved_gpios(void) { }
+static inline void samsung_pm_saved_gpios(void) { }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -65,6 +65,7 @@
 #define S3C2443_CLKDIV0_PREDIV_MASK	(3<<4)
 #define S3C2443_CLKDIV0_PREDIV_SHIFT	(4)
 
+#define S3C2416_CLKDIV0_ARMDIV_MASK	(7 << 9)
 #define S3C2443_CLKDIV0_ARMDIV_MASK	(15<<9)
 #define S3C2443_CLKDIV0_ARMDIV_SHIFT	(9)
 #define S3C2443_CLKDIV0_ARMDIV_1	(0<<9)
@@ -102,6 +103,7 @@
 #define S3C2443_PCLKCON_UART3		(1<<3)
 #define S3C2443_PCLKCON_IIC		(1<<4)
 #define S3C2443_PCLKCON_SDI		(1<<5)
+#define S3C2443_PCLKCON_HSSPI		(1<<6)
 #define S3C2443_PCLKCON_ADC		(1<<7)
 #define S3C2443_PCLKCON_AC97		(1<<8)
 #define S3C2443_PCLKCON_IIS		(1<<9)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/Kconfig linux-libre-3.2-gnu/arch/arm/mach-s3c2410/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -6,9 +6,7 @@
 	bool
 	depends on ARCH_S3C2410
 	select CPU_ARM920T
-	select S3C_GPIO_PULL_UP
 	select S3C2410_CLOCK
-	select S3C2410_GPIO
 	select CPU_LLSERIAL_S3C2410
 	select S3C2410_PM if PM
 	select S3C2410_CPUFREQ if CPU_FREQ_S3C24XX
@@ -28,11 +26,6 @@
 	help
 	  Power Management code common to S3C2410 and better
 
-config S3C2410_GPIO
-	bool
-	help
-	  GPIO code for S3C2410 and similar processors
-
 config SIMTEC_NOR
 	bool
 	help
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-amlm5900.c linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-amlm5900.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-amlm5900.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-amlm5900.c	2012-01-04 18:55:44.000000000 -0500
@@ -236,7 +236,7 @@
 }
 
 MACHINE_START(AML_M5900, "AML_M5900")
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= amlm5900_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= amlm5900_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-bast.c linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-bast.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-bast.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-bast.c	2012-01-04 18:55:44.000000000 -0500
@@ -657,7 +657,7 @@
 
 MACHINE_START(BAST, "Simtec-BAST")
 	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= bast_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= bast_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-h1940.c linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-h1940.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-h1940.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-h1940.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <video/platform_lcd.h>
 
 #include <linux/mmc/host.h>
+#include <linux/export.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -696,9 +697,9 @@
 			      S3C2410_MISCCR_USBSUSPND0 |
 			      S3C2410_MISCCR_USBSUSPND1, 0x0);
 
-	tmp =   (0x78 << S3C24XX_PLLCON_MDIVSHIFT)
-	      | (0x02 << S3C24XX_PLLCON_PDIVSHIFT)
-	      | (0x03 << S3C24XX_PLLCON_SDIVSHIFT);
+	tmp =   (0x78 << S3C24XX_PLL_MDIV_SHIFT)
+	      | (0x02 << S3C24XX_PLL_PDIV_SHIFT)
+	      | (0x03 << S3C24XX_PLL_SDIV_SHIFT);
 	writel(tmp, S3C2410_UPLLCON);
 
 	gpio_request(S3C2410_GPC(0), "LCD power");
@@ -744,7 +745,7 @@
 
 MACHINE_START(H1940, "IPAQ-H1940")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= h1940_map_io,
 	.reserve	= h1940_reserve,
 	.init_irq	= h1940_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-n30.c linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-n30.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-n30.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-n30.c	2012-01-04 18:55:44.000000000 -0500
@@ -586,7 +586,7 @@
 	/* Maintainer: Christer Weinigel <christer@weinigel.se>,
 				Ben Dooks <ben-linux@fluff.org>
 	*/
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.timer		= &s3c24xx_timer,
 	.init_machine	= n30_init,
 	.init_irq	= s3c24xx_init_irq,
@@ -596,7 +596,7 @@
 MACHINE_START(N35, "Acer-N35")
 	/* Maintainer: Christer Weinigel <christer@weinigel.se>
 	*/
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.timer		= &s3c24xx_timer,
 	.init_machine	= n30_init,
 	.init_irq	= s3c24xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-otom.c linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-otom.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-otom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-otom.c	2012-01-04 18:55:44.000000000 -0500
@@ -116,7 +116,7 @@
 
 MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
 	/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= otom11_map_io,
 	.init_machine	= otom11_init,
 	.init_irq	= s3c24xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-qt2410.c linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-qt2410.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-qt2410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-qt2410.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,6 +49,7 @@
 
 #include <mach/regs-gpio.h>
 #include <mach/leds-gpio.h>
+#include <mach/regs-lcd.h>
 #include <plat/regs-serial.h>
 #include <mach/fb.h>
 #include <plat/nand.h>
@@ -344,7 +345,7 @@
 }
 
 MACHINE_START(QT2410, "QT2410")
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= qt2410_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= qt2410_machine_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-smdk2410.c linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-smdk2410.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-smdk2410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-smdk2410.c	2012-01-04 18:55:44.000000000 -0500
@@ -111,7 +111,7 @@
 MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
 				    * to SMDK2410 */
 	/* Maintainer: Jonas Dietsche */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= smdk2410_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= smdk2410_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-tct_hammer.c linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-tct_hammer.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-tct_hammer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-tct_hammer.c	2012-01-04 18:55:44.000000000 -0500
@@ -146,7 +146,7 @@
 }
 
 MACHINE_START(TCT_HAMMER, "TCT_HAMMER")
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= tct_hammer_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= tct_hammer_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-vr1000.c linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-vr1000.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/mach-vr1000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/mach-vr1000.c	2012-01-04 18:55:44.000000000 -0500
@@ -400,7 +400,7 @@
 
 MACHINE_START(VR1000, "Thorcom-VR1000")
 	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= vr1000_map_io,
 	.init_machine	= vr1000_init,
 	.init_irq	= s3c24xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/Makefile linux-libre-3.2-gnu/arch/arm/mach-s3c2410/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@
 obj-$(CONFIG_CPU_S3C2410_DMA)	+= dma.o
 obj-$(CONFIG_CPU_S3C2410_DMA)	+= dma.o
 obj-$(CONFIG_S3C2410_PM)	+= pm.o sleep.o
-obj-$(CONFIG_S3C2410_GPIO)	+= gpio.o
 obj-$(CONFIG_S3C2410_CPUFREQ)	+= cpu-freq.o
 obj-$(CONFIG_S3C2410_PLLTABLE)	+= pll.o
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-s3c2410/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 ifeq ($(CONFIG_PM_H1940),y)
-	zreladdr-y		:= 0x30108000
+	zreladdr-y	+= 0x30108000
 	params_phys-y	:= 0x30100100
 else
-	zreladdr-y		:= 0x30008000
+	zreladdr-y	+= 0x30008000
 	params_phys-y	:= 0x30000100
 endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2410/s3c2410.c linux-libre-3.2-gnu/arch/arm/mach-s3c2410/s3c2410.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2410/s3c2410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2410/s3c2410.c	2012-01-04 18:55:44.000000000 -0500
@@ -72,8 +72,8 @@
 
 void __init s3c2410_map_io(void)
 {
-	s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up;
-	s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up;
+	s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1up;
+	s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1up;
 
 	iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2412/dma.c linux-libre-3.2-gnu/arch/arm/mach-s3c2412/dma.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2412/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2412/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -50,64 +50,46 @@
 		.name		= "sdi",
 		.channels	= MAP(S3C2412_DMAREQSEL_SDI),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_SDI),
-		.hw_addr.to	= S3C2410_PA_SDI + S3C2410_SDIDATA,
-		.hw_addr.from	= S3C2410_PA_SDI + S3C2410_SDIDATA,
 	},
 	[DMACH_SPI0] = {
 		.name		= "spi0",
 		.channels	= MAP(S3C2412_DMAREQSEL_SPI0TX),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_SPI0RX),
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
 	},
 	[DMACH_SPI1] = {
 		.name		= "spi1",
 		.channels	= MAP(S3C2412_DMAREQSEL_SPI1TX),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_SPI1RX),
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2412_SPI1 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2412_SPI1  + S3C2410_SPRDAT,
 	},
 	[DMACH_UART0] = {
 		.name		= "uart0",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART0_0),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART0_0),
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1] = {
 		.name		= "uart1",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART1_0),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART1_0),
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2] = {
 		.name		= "uart2",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART2_0),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART2_0),
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
 	[DMACH_UART0_SRC2] = {
 		.name		= "uart0",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART0_1),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART0_1),
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1_SRC2] = {
 		.name		= "uart1",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART1_1),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART1_1),
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2_SRC2] = {
 		.name		= "uart2",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART2_1),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART2_1),
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
 	[DMACH_TIMER] = {
 		.name		= "timer",
@@ -148,11 +130,11 @@
 
 static void s3c2412_dma_direction(struct s3c2410_dma_chan *chan,
 				  struct s3c24xx_dma_map *map,
-				  enum s3c2410_dmasrc dir)
+				  enum dma_data_direction dir)
 {
 	unsigned long chsel;
 
-	if (dir == S3C2410_DMASRC_HW)
+	if (dir == DMA_FROM_DEVICE)
 		chsel = map->channels_rx[0];
 	else
 		chsel = map->channels[0];
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2412/gpio.c linux-libre-3.2-gnu/arch/arm/mach-s3c2412/gpio.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2412/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2412/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,7 @@
 
 int s3c2412_gpio_set_sleepcfg(unsigned int pin, unsigned int state)
 {
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
 	unsigned long offs = pin - chip->chip.base;
 	unsigned long flags;
 	unsigned long slpcon;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2412/Kconfig linux-libre-3.2-gnu/arch/arm/mach-s3c2412/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2412/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2412/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@
 	select CPU_LLSERIAL_S3C2440
 	select S3C2412_PM if PM
 	select S3C2412_DMA if S3C2410_DMA
-	select S3C2410_GPIO
 	help
 	  Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2412/mach-jive.c linux-libre-3.2-gnu/arch/arm/mach-s3c2412/mach-jive.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2412/mach-jive.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2412/mach-jive.c	2012-01-04 18:55:44.000000000 -0500
@@ -655,7 +655,7 @@
 
 MACHINE_START(JIVE, "JIVE")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= jive_map_io,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2412/mach-smdk2413.c linux-libre-3.2-gnu/arch/arm/mach-s3c2412/mach-smdk2413.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2412/mach-smdk2413.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2412/mach-smdk2413.c	2012-01-04 18:55:44.000000000 -0500
@@ -92,8 +92,7 @@
 	&s3c_device_usbgadget,
 };
 
-static void __init smdk2413_fixup(struct machine_desc *desc,
-				  struct tag *tags, char **cmdline,
+static void __init smdk2413_fixup(struct tag *tags, char **cmdline,
 				  struct meminfo *mi)
 {
 	if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
@@ -128,7 +127,7 @@
 
 MACHINE_START(S3C2413, "S3C2413")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 
 	.fixup		= smdk2413_fixup,
 	.init_irq	= s3c24xx_init_irq,
@@ -139,7 +138,7 @@
 
 MACHINE_START(SMDK2412, "SMDK2412")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 
 	.fixup		= smdk2413_fixup,
 	.init_irq	= s3c24xx_init_irq,
@@ -150,7 +149,7 @@
 
 MACHINE_START(SMDK2413, "SMDK2413")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 
 	.fixup		= smdk2413_fixup,
 	.init_irq	= s3c24xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2412/mach-vstms.c linux-libre-3.2-gnu/arch/arm/mach-s3c2412/mach-vstms.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2412/mach-vstms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2412/mach-vstms.c	2012-01-04 18:55:44.000000000 -0500
@@ -129,9 +129,8 @@
 	&s3c_device_nand,
 };
 
-static void __init vstms_fixup(struct machine_desc *desc,
-				  struct tag *tags, char **cmdline,
-				  struct meminfo *mi)
+static void __init vstms_fixup(struct tag *tags, char **cmdline,
+			       struct meminfo *mi)
 {
 	if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
 		mi->nr_banks=1;
@@ -156,7 +155,7 @@
 }
 
 MACHINE_START(VSTMS, "VSTMS")
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 
 	.fixup		= vstms_fixup,
 	.init_irq	= s3c24xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2412/Makefile linux-libre-3.2-gnu/arch/arm/mach-s3c2412/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2412/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2412/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,6 @@
 obj-$(CONFIG_CPU_S3C2412)	+= s3c2412.o
 obj-$(CONFIG_CPU_S3C2412)	+= irq.o
 obj-$(CONFIG_CPU_S3C2412)	+= clock.o
-obj-$(CONFIG_CPU_S3C2412)	+= gpio.o
 obj-$(CONFIG_S3C2412_DMA)	+= dma.o
 obj-$(CONFIG_S3C2412_PM)	+= pm.o
 obj-$(CONFIG_S3C2412_PM_SLEEP)	+= sleep.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2416/clock.c linux-libre-3.2-gnu/arch/arm/mach-s3c2416/clock.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2416/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2416/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,6 @@
 #include <plat/cpu.h>
 
 #include <plat/cpu-freq.h>
-#include <plat/pll6553x.h>
 #include <plat/pll.h>
 
 #include <asm/mach/map.h>
@@ -29,6 +28,14 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-s3c2443-clock.h>
 
+/* armdiv
+ *
+ * this clock is sourced from msysclk and can have a number of
+ * divider values applied to it to then be fed into armclk.
+ * The real clock definition is done in s3c2443-clock.c,
+ * only the armdiv divisor table must be defined here.
+*/
+
 static unsigned int armdiv[8] = {
 	[0] = 1,
 	[1] = 2,
@@ -38,6 +45,32 @@
 	[7] = 8,
 };
 
+static struct clksrc_clk hsspi_eplldiv = {
+	.clk = {
+		.name	= "hsspi-eplldiv",
+		.parent	= &clk_esysclk.clk,
+		.ctrlbit = (1 << 14),
+		.enable = s3c2443_clkcon_enable_s,
+	},
+	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 24 },
+};
+
+static struct clk *hsspi_sources[] = {
+	[0] = &hsspi_eplldiv.clk,
+	[1] = NULL, /* to fix */
+};
+
+static struct clksrc_clk hsspi_mux = {
+	.clk	= {
+		.name	= "hsspi-if",
+	},
+	.sources = &(struct clksrc_sources) {
+		.sources = hsspi_sources,
+		.nr_sources = ARRAY_SIZE(hsspi_sources),
+	},
+	.reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 18 },
+};
+
 static struct clksrc_clk hsmmc_div[] = {
 	[0] = {
 		.clk = {
@@ -100,20 +133,15 @@
 	.ctrlbit	= S3C2416_HCLKCON_HSMMC0,
 };
 
-static inline unsigned int s3c2416_fclk_div(unsigned long clkcon0)
-{
-	clkcon0 &= 7 << S3C2443_CLKDIV0_ARMDIV_SHIFT;
-
-	return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
-}
-
 void __init_or_cpufreq s3c2416_setup_clocks(void)
 {
-	s3c2443_common_setup_clocks(s3c2416_get_pll, s3c2416_fclk_div);
+	s3c2443_common_setup_clocks(s3c2416_get_pll);
 }
 
 
 static struct clksrc_clk *clksrcs[] __initdata = {
+	&hsspi_eplldiv,
+	&hsspi_mux,
 	&hsmmc_div[0],
 	&hsmmc_div[1],
 	&hsmmc_mux[0],
@@ -131,7 +159,9 @@
 
 	clk_epll.parent = &clk_epllref.clk;
 
-	s3c2443_common_init_clocks(xtal, s3c2416_get_pll, s3c2416_fclk_div);
+	s3c2443_common_init_clocks(xtal, s3c2416_get_pll,
+				   armdiv, ARRAY_SIZE(armdiv),
+				   S3C2416_CLKDIV0_ARMDIV_MASK);
 
 	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
 		s3c_register_clksrc(clksrcs[ptr], 1);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2416/Kconfig linux-libre-3.2-gnu/arch/arm/mach-s3c2416/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2416/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2416/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@
 	select CPU_ARM926T
 	select S3C2416_DMA if S3C2410_DMA
 	select CPU_LLSERIAL_S3C2440
-	select S3C_GPIO_PULL_UPDOWN
 	select SAMSUNG_CLKSRC
 	select S3C2443_CLOCK
 	help
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2416/mach-smdk2416.c linux-libre-3.2-gnu/arch/arm/mach-s3c2416/mach-smdk2416.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2416/mach-smdk2416.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2416/mach-smdk2416.c	2012-01-04 18:55:44.000000000 -0500
@@ -245,7 +245,7 @@
 
 MACHINE_START(SMDK2416, "SMDK2416")
 	/* Maintainer: Yauhen Kharuzhy <jekhor@gmail.com> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= smdk2416_map_io,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2416/s3c2416.c linux-libre-3.2-gnu/arch/arm/mach-s3c2416/s3c2416.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2416/s3c2416.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2416/s3c2416.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,6 +60,7 @@
 #include <plat/iic-core.h>
 #include <plat/fb-core.h>
 #include <plat/nand-core.h>
+#include <plat/adc-core.h>
 
 static struct map_desc s3c2416_iodesc[] __initdata = {
 	IODESC_ENT(WATCHDOG),
@@ -97,6 +98,8 @@
 
 	s3c_fb_setname("s3c2443-fb");
 
+	s3c_adc_setname("s3c2416-adc");
+
 #ifdef CONFIG_PM
 	register_syscore_ops(&s3c2416_pm_syscore_ops);
 #endif
@@ -120,8 +123,8 @@
 
 void __init s3c2416_map_io(void)
 {
-	s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_updown;
-	s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_updown;
+	s3c24xx_gpiocfg_default.set_pull = samsung_gpio_setpull_updown;
+	s3c24xx_gpiocfg_default.get_pull = samsung_gpio_getpull_updown;
 
 	/* initialize device information early */
 	s3c2416_default_sdhci0();
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2416/setup-sdhci.c linux-libre-3.2-gnu/arch/arm/mach-s3c2416/setup-sdhci.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2416/setup-sdhci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2416/setup-sdhci.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,17 +12,7 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
 
 /* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
 
@@ -32,30 +22,3 @@
 	[2] = "hsmmc-if",
 	/* [3] = "48m", - note not successfully used yet */
 };
-
-void s3c2416_setup_sdhci_cfg_card(struct platform_device *dev,
-				  void __iomem *r,
-				  struct mmc_ios *ios,
-				  struct mmc_card *card)
-{
-	u32 ctrl2, ctrl3;
-
-	ctrl2 = __raw_readl(r + S3C_SDHCI_CONTROL2);
-	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-		  S3C_SDHCI_CTRL2_ENFBCLKRX |
-		  S3C_SDHCI_CTRL2_DFCNT_NONE |
-		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-	if (ios->clock < 25 * 1000000)
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-			 S3C_SDHCI_CTRL3_FCSEL2 |
-			 S3C_SDHCI_CTRL3_FCSEL1 |
-			 S3C_SDHCI_CTRL3_FCSEL0);
-	else
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-	__raw_writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-	__raw_writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2440/dma.c linux-libre-3.2-gnu/arch/arm/mach-s3c2440/dma.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2440/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2440/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,38 +48,26 @@
 		.channels[1]	= S3C2440_DCON_CH1_SDI | DMA_CH_VALID,
 		.channels[2]	= S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
 		.channels[3]	= S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_SPI0] = {
 		.name		= "spi0",
 		.channels[1]	= S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
 	},
 	[DMACH_SPI1] = {
 		.name		= "spi1",
 		.channels[3]	= S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
 	},
 	[DMACH_UART0] = {
 		.name		= "uart0",
 		.channels[0]	= S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1] = {
 		.name		= "uart1",
 		.channels[1]	= S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2] = {
 		.name		= "uart2",
 		.channels[3]	= S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
 	[DMACH_TIMER] = {
 		.name		= "timer",
@@ -91,31 +79,26 @@
 		.name		= "i2s-sdi",
 		.channels[1]	= S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
 		.channels[2]	= S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_I2S_OUT] = {
 		.name		= "i2s-sdo",
 		.channels[0]	= S3C2440_DCON_CH0_I2SSDO | DMA_CH_VALID,
 		.channels[2]	= S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_PCM_IN] = {
 		.name		= "pcm-in",
 		.channels[0]	= S3C2440_DCON_CH0_PCMIN | DMA_CH_VALID,
 		.channels[2]	= S3C2440_DCON_CH2_PCMIN | DMA_CH_VALID,
-		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
 	},
 	[DMACH_PCM_OUT] = {
 		.name		= "pcm-out",
 		.channels[1]	= S3C2440_DCON_CH1_PCMOUT | DMA_CH_VALID,
 		.channels[3]	= S3C2440_DCON_CH3_PCMOUT | DMA_CH_VALID,
-		.hw_addr.to	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
 	},
 	[DMACH_MIC_IN] = {
 		.name		= "mic-in",
 		.channels[2]	= S3C2440_DCON_CH2_MICIN | DMA_CH_VALID,
 		.channels[3]	= S3C2440_DCON_CH3_MICIN | DMA_CH_VALID,
-		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
 	},
 	[DMACH_USB_EP1] = {
 		.name		= "usb-ep1",
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2440/Kconfig linux-libre-3.2-gnu/arch/arm/mach-s3c2440/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2440/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2440/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -5,10 +5,8 @@
 config CPU_S3C2440
 	bool
 	select CPU_ARM920T
-	select S3C_GPIO_PULL_UP
 	select S3C2410_CLOCK
 	select S3C2410_PM if PM
-	select S3C2410_GPIO
 	select S3C2440_DMA if S3C2410_DMA
 	select CPU_S3C244X
 	select CPU_LLSERIAL_S3C2440
@@ -18,9 +16,7 @@
 config CPU_S3C2442
 	bool
 	select CPU_ARM920T
-	select S3C_GPIO_PULL_DOWN
 	select S3C2410_CLOCK
-	select S3C2410_GPIO
 	select S3C2410_PM if PM
 	select CPU_S3C244X
 	select CPU_LLSERIAL_S3C2440
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-anubis.c linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-anubis.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-anubis.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-anubis.c	2012-01-04 18:55:44.000000000 -0500
@@ -498,7 +498,7 @@
 
 MACHINE_START(ANUBIS, "Simtec-Anubis")
 	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= anubis_map_io,
 	.init_machine	= anubis_init,
 	.init_irq	= s3c24xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-at2440evb.c linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-at2440evb.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-at2440evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-at2440evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -233,7 +233,7 @@
 
 
 MACHINE_START(AT2440EVB, "AT2440EVB")
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= at2440evb_map_io,
 	.init_machine	= at2440evb_init,
 	.init_irq	= s3c24xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-gta02.c linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-gta02.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-gta02.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-gta02.c	2012-01-04 18:55:44.000000000 -0500
@@ -595,7 +595,7 @@
 
 MACHINE_START(NEO1973_GTA02, "GTA02")
 	/* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= gta02_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= gta02_machine_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-mini2440.c linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-mini2440.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-mini2440.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-mini2440.c	2012-01-04 18:55:44.000000000 -0500
@@ -676,7 +676,7 @@
 
 MACHINE_START(MINI2440, "MINI2440")
 	/* Maintainer: Michel Pollet <buserror@gmail.com> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= mini2440_map_io,
 	.init_machine	= mini2440_init,
 	.init_irq	= s3c24xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-nexcoder.c linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-nexcoder.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-nexcoder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-nexcoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -151,7 +151,7 @@
 
 MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
 	/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= nexcoder_map_io,
 	.init_machine	= nexcoder_init,
 	.init_irq	= s3c24xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-osiris.c linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-osiris.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-osiris.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-osiris.c	2012-01-04 18:55:44.000000000 -0500
@@ -447,7 +447,7 @@
 
 MACHINE_START(OSIRIS, "Simtec-OSIRIS")
 	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= osiris_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= osiris_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-rx1950.c linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-rx1950.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-rx1950.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-rx1950.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@
 
 #include <mach/regs-gpio.h>
 #include <mach/regs-gpioj.h>
+#include <mach/regs-lcd.h>
 #include <mach/h1940.h>
 #include <mach/fb.h>
 
@@ -825,7 +826,7 @@
 
 MACHINE_START(RX1950, "HP iPAQ RX1950")
     /* Maintainers: Vasily Khoruzhick */
-	.boot_params = S3C2410_SDRAM_PA + 0x100,
+	.atag_offset = 0x100,
 	.map_io = rx1950_map_io,
 	.reserve	= rx1950_reserve,
 	.init_irq = s3c24xx_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-rx3715.c linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-rx3715.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-rx3715.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-rx3715.c	2012-01-04 18:55:44.000000000 -0500
@@ -218,7 +218,7 @@
 
 MACHINE_START(RX3715, "IPAQ-RX3715")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= rx3715_map_io,
 	.reserve	= rx3715_reserve,
 	.init_irq	= rx3715_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-smdk2440.c linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-smdk2440.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2440/mach-smdk2440.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2440/mach-smdk2440.c	2012-01-04 18:55:44.000000000 -0500
@@ -175,7 +175,7 @@
 
 MACHINE_START(S3C2440, "SMDK2440")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= smdk2440_map_io,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2440/s3c2440.c linux-libre-3.2-gnu/arch/arm/mach-s3c2440/s3c2440.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2440/s3c2440.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2440/s3c2440.c	2012-01-04 18:55:44.000000000 -0500
@@ -70,6 +70,6 @@
 {
 	s3c244x_map_io();
 
-	s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up;
-	s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up;
+	s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1up;
+	s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1up;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2440/s3c2442.c linux-libre-3.2-gnu/arch/arm/mach-s3c2440/s3c2442.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2440/s3c2442.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2440/s3c2442.c	2012-01-04 18:55:44.000000000 -0500
@@ -182,6 +182,6 @@
 {
 	s3c244x_map_io();
 
-	s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1down;
-	s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1down;
+	s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1down;
+	s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1down;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2443/clock.c linux-libre-3.2-gnu/arch/arm/mach-s3c2443/clock.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2443/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2443/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -57,18 +57,14 @@
 
 /* clock selections */
 
-static struct clk clk_i2s_ext = {
-	.name		= "i2s-ext",
-};
-
 /* armdiv
  *
  * this clock is sourced from msysclk and can have a number of
  * divider values applied to it to then be fed into armclk.
+ * The real clock definition is done in s3c2443-clock.c,
+ * only the armdiv divisor table must be defined here.
 */
 
-/* armdiv divisor table */
-
 static unsigned int armdiv[16] = {
 	[S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 1,
 	[S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 2,
@@ -80,92 +76,6 @@
 	[S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 16,
 };
 
-static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0)
-{
-	clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
-
-	return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
-}
-
-static unsigned long s3c2443_armclk_roundrate(struct clk *clk,
-					      unsigned long rate)
-{
-	unsigned long parent = clk_get_rate(clk->parent);
-	unsigned long calc;
-	unsigned best = 256; /* bigger than any value */
-	unsigned div;
-	int ptr;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) {
-		div = armdiv[ptr];
-		calc = parent / div;
-		if (calc <= rate && div < best)
-			best = div;
-	}
-
-	return parent / best;
-}
-
-static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent = clk_get_rate(clk->parent);
-	unsigned long calc;
-	unsigned div;
-	unsigned best = 256; /* bigger than any value */
-	int ptr;
-	int val = -1;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) {
-		div = armdiv[ptr];
-		calc = parent / div;
-		if (calc <= rate && div < best) {
-			best = div;
-			val = ptr;
-		}
-	}
-
-	if (val >= 0) {
-		unsigned long clkcon0;
-
-		clkcon0 = __raw_readl(S3C2443_CLKDIV0);
-		clkcon0 &= ~S3C2443_CLKDIV0_ARMDIV_MASK;
-		clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT;
-		__raw_writel(clkcon0, S3C2443_CLKDIV0);
-	}
-
-	return (val == -1) ? -EINVAL : 0;
-}
-
-static struct clk clk_armdiv = {
-	.name		= "armdiv",
-	.parent		= &clk_msysclk.clk,
-	.ops		= &(struct clk_ops) {
-		.round_rate = s3c2443_armclk_roundrate,
-		.set_rate = s3c2443_armclk_setrate,
-	},
-};
-
-/* armclk
- *
- * this is the clock fed into the ARM core itself, from armdiv or from hclk.
- */
-
-static struct clk *clk_arm_sources[] = {
-	[0] = &clk_armdiv,
-	[1] = &clk_h,
-};
-
-static struct clksrc_clk clk_arm = {
-	.clk	= {
-		.name		= "armclk",
-	},
-	.sources = &(struct clksrc_sources) {
-		.sources = clk_arm_sources,
-		.nr_sources = ARRAY_SIZE(clk_arm_sources),
-	},
-	.reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 },
-};
-
 /* hsspi
  *
  * high-speed spi clock, sourced from esysclk
@@ -173,7 +83,7 @@
 
 static struct clksrc_clk clk_hsspi = {
 	.clk	= {
-		.name		= "hsspi",
+		.name		= "hsspi-if",
 		.parent		= &clk_esysclk.clk,
 		.ctrlbit	= S3C2443_SCLKCON_HSSPICLK,
 		.enable		= s3c2443_clkcon_enable_s,
@@ -235,48 +145,6 @@
 	},
 };
 
-/* i2s_eplldiv
- *
- * This clock is the output from the I2S divisor of ESYSCLK, and is separate
- * from the mux that comes after it (cannot merge into one single clock)
-*/
-
-static struct clksrc_clk clk_i2s_eplldiv = {
-	.clk	= {
-		.name		= "i2s-eplldiv",
-		.parent		= &clk_esysclk.clk,
-	},
-	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
-};
-
-/* i2s-ref
- *
- * i2s bus reference clock, selectable from external, esysclk or epllref
- *
- * Note, this used to be two clocks, but was compressed into one.
-*/
-
-struct clk *clk_i2s_srclist[] = {
-	[0] = &clk_i2s_eplldiv.clk,
-	[1] = &clk_i2s_ext,
-	[2] = &clk_epllref.clk,
-	[3] = &clk_epllref.clk,
-};
-
-static struct clksrc_clk clk_i2s = {
-	.clk	= {
-		.name		= "i2s-if",
-		.ctrlbit	= S3C2443_SCLKCON_I2SCLK,
-		.enable		= s3c2443_clkcon_enable_s,
-
-	},
-	.sources = &(struct clksrc_sources) {
-		.sources = clk_i2s_srclist,
-		.nr_sources = ARRAY_SIZE(clk_i2s_srclist),
-	},
-	.reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
-};
-
 /* standard clock definitions */
 
 static struct clk init_clocks_off[] = {
@@ -286,11 +154,6 @@
 		.enable		= s3c2443_clkcon_enable_p,
 		.ctrlbit	= S3C2443_PCLKCON_SDI,
 	}, {
-		.name		= "iis",
-		.parent		= &clk_p,
-		.enable		= s3c2443_clkcon_enable_p,
-		.ctrlbit	= S3C2443_PCLKCON_IIS,
-	}, {
 		.name		= "spi",
 		.devname	= "s3c2410-spi.0",
 		.parent		= &clk_p,
@@ -305,27 +168,20 @@
 	}
 };
 
-static struct clk init_clocks[] = {
-};
-
 /* clocks to add straight away */
 
 static struct clksrc_clk *clksrcs[] __initdata = {
-	&clk_arm,
-	&clk_i2s_eplldiv,
-	&clk_i2s,
 	&clk_hsspi,
 	&clk_hsmmc_div,
 };
 
 static struct clk *clks[] __initdata = {
 	&clk_hsmmc,
-	&clk_armdiv,
 };
 
 void __init_or_cpufreq s3c2443_setup_clocks(void)
 {
-	s3c2443_common_setup_clocks(s3c2443_get_mpll, s3c2443_fclk_div);
+	s3c2443_common_setup_clocks(s3c2443_get_mpll);
 }
 
 void __init s3c2443_init_clocks(int xtal)
@@ -336,7 +192,9 @@
 	clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
 	clk_epll.parent = &clk_epllref.clk;
 
-	s3c2443_common_init_clocks(xtal, s3c2443_get_mpll, s3c2443_fclk_div);
+	s3c2443_common_init_clocks(xtal, s3c2443_get_mpll,
+				   armdiv, ARRAY_SIZE(armdiv),
+				   S3C2443_CLKDIV0_ARMDIV_MASK);
 
 	s3c2443_setup_clocks();
 
@@ -345,10 +203,6 @@
 	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
 		s3c_register_clksrc(clksrcs[ptr], 1);
 
-	/* register clocks from clock array */
-
-	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
-
 	/* We must be careful disabling the clocks we are not intending to
 	 * be using at boot time, as subsystems such as the LCD which do
 	 * their own DMA requests to the bus can cause the system to lockup
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2443/dma.c linux-libre-3.2-gnu/arch/arm/mach-s3c2443/dma.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2443/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2443/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -54,68 +54,46 @@
 	[DMACH_SDI] = {
 		.name		= "sdi",
 		.channels	= MAP(S3C2443_DMAREQSEL_SDI),
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_SPI0] = {
 		.name		= "spi0",
 		.channels	= MAP(S3C2443_DMAREQSEL_SPI0TX),
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
 	},
 	[DMACH_SPI1] = {
 		.name		= "spi1",
 		.channels	= MAP(S3C2443_DMAREQSEL_SPI1TX),
-		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
 	},
 	[DMACH_UART0] = {
 		.name		= "uart0",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART0_0),
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1] = {
 		.name		= "uart1",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART1_0),
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2] = {
 		.name		= "uart2",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART2_0),
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
       	[DMACH_UART3] = {
 		.name		= "uart3",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART3_0),
-		.hw_addr.to	= S3C2443_PA_UART3 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2443_PA_UART3 + S3C2410_URXH,
 	},
 	[DMACH_UART0_SRC2] = {
 		.name		= "uart0",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART0_1),
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1_SRC2] = {
 		.name		= "uart1",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART1_1),
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2_SRC2] = {
 		.name		= "uart2",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART2_1),
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
       	[DMACH_UART3_SRC2] = {
 		.name		= "uart3",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART3_1),
-		.hw_addr.to	= S3C2443_PA_UART3 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2443_PA_UART3 + S3C2410_URXH,
 	},
 	[DMACH_TIMER] = {
 		.name		= "timer",
@@ -124,27 +102,22 @@
 	[DMACH_I2S_IN] = {
 		.name		= "i2s-sdi",
 		.channels	= MAP(S3C2443_DMAREQSEL_I2SRX),
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_I2S_OUT] = {
 		.name		= "i2s-sdo",
 		.channels	= MAP(S3C2443_DMAREQSEL_I2STX),
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_PCM_IN] = {
 		.name		= "pcm-in",
 		.channels	= MAP(S3C2443_DMAREQSEL_PCMIN),
-		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
 	},
 	[DMACH_PCM_OUT] = {
 		.name		= "pcm-out",
 		.channels	= MAP(S3C2443_DMAREQSEL_PCMOUT),
-		.hw_addr.to	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
 	},
 	[DMACH_MIC_IN] = {
 		.name		= "mic-in",
 		.channels	= MAP(S3C2443_DMAREQSEL_MICIN),
-		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
 	},
 };
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2443/Kconfig linux-libre-3.2-gnu/arch/arm/mach-s3c2443/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2443/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2443/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,6 @@
 	select CPU_LLSERIAL_S3C2440
 	select SAMSUNG_CLKSRC
 	select S3C2443_CLOCK
-	select S3C_GPIO_PULL_S3C2443
 	help
 	  Support for the S3C2443 SoC from the S3C24XX line
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2443/mach-smdk2443.c linux-libre-3.2-gnu/arch/arm/mach-s3c2443/mach-smdk2443.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2443/mach-smdk2443.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2443/mach-smdk2443.c	2012-01-04 18:55:44.000000000 -0500
@@ -139,7 +139,7 @@
 
 MACHINE_START(SMDK2443, "SMDK2443")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= smdk2443_map_io,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c2443/s3c2443.c linux-libre-3.2-gnu/arch/arm/mach-s3c2443/s3c2443.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c2443/s3c2443.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c2443/s3c2443.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
 #include <plat/cpu.h>
 #include <plat/fb-core.h>
 #include <plat/nand-core.h>
+#include <plat/adc-core.h>
 
 static struct map_desc s3c2443_iodesc[] __initdata = {
 	IODESC_ENT(WATCHDOG),
@@ -70,6 +71,8 @@
 	s3c_nand_setname("s3c2412-nand");
 	s3c_fb_setname("s3c2443-fb");
 
+	s3c_adc_setname("s3c2443-adc");
+
 	/* change WDT IRQ number */
 	s3c_device_wdt.resource[1].start = IRQ_S3C2443_WDT;
 	s3c_device_wdt.resource[1].end   = IRQ_S3C2443_WDT;
@@ -90,8 +93,8 @@
 
 void __init s3c2443_map_io(void)
 {
-	s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_s3c2443;
-	s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_s3c2443;
+	s3c24xx_gpiocfg_default.set_pull = s3c2443_gpio_setpull;
+	s3c24xx_gpiocfg_default.get_pull = s3c2443_gpio_getpull;
 
 	iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc));
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/clock.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/clock.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,13 +25,13 @@
 
 #include <mach/regs-sys.h>
 #include <mach/regs-clock.h>
-#include <mach/pll.h>
 
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/cpu-freq.h>
 #include <plat/clock.h>
 #include <plat/clock-clksrc.h>
+#include <plat/pll.h>
 
 /* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
  * ext_xtal_mux for want of an actual name from the manual.
@@ -735,7 +735,8 @@
 	/* For now assume the mux always selects the crystal */
 	clk_ext_xtal_mux.parent = xtal_clk;
 
-	epll = s3c6400_get_epll(xtal);
+	epll = s3c_get_pll6553x(xtal, __raw_readl(S3C_EPLL_CON0),
+				__raw_readl(S3C_EPLL_CON1));
 	mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON));
 	apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON));
 
@@ -744,7 +745,13 @@
 	printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n",
 	       apll, mpll, epll);
 
-	hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
+	if(__raw_readl(S3C64XX_OTHERS) & S3C64XX_OTHERS_SYNCMUXSEL)
+		/* Synchronous mode */
+		hclk2 = apll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
+	else
+		/* Asynchronous mode */
+		hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
+
 	hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK);
 	pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK);
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/cpu.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/cpu.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/dma-mapping.h>
 
 #include <mach/hardware.h>
 #include <mach/map.h>
@@ -33,8 +34,8 @@
 #include <plat/devs.h>
 #include <plat/clock.h>
 
-#include <mach/s3c6400.h>
-#include <mach/s3c6410.h>
+#include <plat/s3c6400.h>
+#include <plat/s3c6410.h>
 
 /* table of supported CPUs */
 
@@ -43,16 +44,16 @@
 
 static struct cpu_table cpu_ids[] __initdata = {
 	{
-		.idcode		= 0x36400000,
-		.idmask		= 0xfffff000,
+		.idcode		= S3C6400_CPU_ID,
+		.idmask		= S3C64XX_CPU_MASK,
 		.map_io		= s3c6400_map_io,
 		.init_clocks	= s3c6400_init_clocks,
 		.init_uarts	= s3c6400_init_uarts,
 		.init		= s3c6400_init,
 		.name		= name_s3c6400,
 	}, {
-		.idcode		= 0x36410100,
-		.idmask		= 0xffffff00,
+		.idcode		= S3C6410_CPU_ID,
+		.idmask		= S3C64XX_CPU_MASK,
 		.map_io		= s3c6410_map_io,
 		.init_clocks	= s3c6410_init_clocks,
 		.init_uarts	= s3c6410_init_uarts,
@@ -140,22 +141,15 @@
 
 void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
 {
-	unsigned long idcode;
-
 	/* initialise the io descriptors we need for initialisation */
 	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
 	iotable_init(mach_desc, size);
+	init_consistent_dma_size(SZ_8M);
 
-	idcode = __raw_readl(S3C_VA_SYS + 0x118);
-	if (!idcode) {
-		/* S3C6400 has the ID register in a different place,
-		 * and needs a write before it can be read. */
-
-		__raw_writel(0x0, S3C_VA_SYS + 0xA1C);
-		idcode = __raw_readl(S3C_VA_SYS + 0xA1C);
-	}
+	/* detect cpu id */
+	s3c64xx_init_cpu();
 
-	s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
+	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
 }
 
 static __init int s3c64xx_sysdev_init(void)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/dev-audio.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/dev-audio.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/dev-audio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/dev-audio.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
+#include <linux/export.h>
 
 #include <mach/irqs.h>
 #include <mach/map.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/dev-onenand1.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/dev-onenand1.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/dev-onenand1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/dev-onenand1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-/*
- * linux/arch/arm/mach-s3c64xx/dev-onenand1.c
- *
- *  Copyright (c) 2008-2010 Samsung Electronics
- *  Kyungmin Park <kyungmin.park@samsung.com>
- *
- * S3C64XX series device definition for OneNAND devices
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/onenand.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-
-static struct resource s3c64xx_onenand1_resources[] = {
-	[0] = {
-		.start	= S3C64XX_PA_ONENAND1,
-		.end	= S3C64XX_PA_ONENAND1 + 0x400 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= S3C64XX_PA_ONENAND1_BUF,
-		.end	= S3C64XX_PA_ONENAND1_BUF + S3C64XX_SZ_ONENAND1_BUF - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= IRQ_ONENAND1,
-		.end	= IRQ_ONENAND1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c64xx_device_onenand1 = {
-	.name		= "samsung-onenand",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s3c64xx_onenand1_resources),
-	.resource	= s3c64xx_onenand1_resources,
-};
-
-void s3c64xx_onenand1_set_platdata(struct onenand_platform_data *pdata)
-{
-	s3c_set_platdata(pdata, sizeof(struct onenand_platform_data),
-			 &s3c64xx_device_onenand1);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/dev-spi.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/dev-spi.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/dev-spi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/dev-spi.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/string.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/dev-uart.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/dev-uart.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/dev-uart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/dev-uart.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,21 +37,10 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S3CUART_RX0,
-		.end	= IRQ_S3CUART_RX0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S3CUART_TX0,
-		.end	= IRQ_S3CUART_TX0,
+		.start	= IRQ_UART0,
+		.end	= IRQ_UART0,
 		.flags	= IORESOURCE_IRQ,
-
 	},
-	[3] = {
-		.start	= IRQ_S3CUART_ERR0,
-		.end	= IRQ_S3CUART_ERR0,
-		.flags	= IORESOURCE_IRQ,
-	}
 };
 
 static struct resource s3c64xx_uart1_resource[] = {
@@ -61,19 +50,8 @@
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S3CUART_RX1,
-		.end	= IRQ_S3CUART_RX1,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S3CUART_TX1,
-		.end	= IRQ_S3CUART_TX1,
-		.flags	= IORESOURCE_IRQ,
-
-	},
-	[3] = {
-		.start	= IRQ_S3CUART_ERR1,
-		.end	= IRQ_S3CUART_ERR1,
+		.start	= IRQ_UART1,
+		.end	= IRQ_UART1,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -85,19 +63,8 @@
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S3CUART_RX2,
-		.end	= IRQ_S3CUART_RX2,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S3CUART_TX2,
-		.end	= IRQ_S3CUART_TX2,
-		.flags	= IORESOURCE_IRQ,
-
-	},
-	[3] = {
-		.start	= IRQ_S3CUART_ERR2,
-		.end	= IRQ_S3CUART_ERR2,
+		.start	= IRQ_UART2,
+		.end	= IRQ_UART2,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -109,19 +76,8 @@
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S3CUART_RX3,
-		.end	= IRQ_S3CUART_RX3,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S3CUART_TX3,
-		.end	= IRQ_S3CUART_TX3,
-		.flags	= IORESOURCE_IRQ,
-
-	},
-	[3] = {
-		.start	= IRQ_S3CUART_ERR3,
-		.end	= IRQ_S3CUART_ERR3,
+		.start	= IRQ_UART3,
+		.end	= IRQ_UART3,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/dma.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/dma.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -147,14 +147,14 @@
 	u32 control0, control1;
 
 	switch (chan->source) {
-	case S3C2410_DMASRC_HW:
+	case DMA_FROM_DEVICE:
 		src = chan->dev_addr;
 		dst = data;
 		control0 = PL080_CONTROL_SRC_AHB2;
 		control0 |= PL080_CONTROL_DST_INCR;
 		break;
 
-	case S3C2410_DMASRC_MEM:
+	case DMA_TO_DEVICE:
 		src = data;
 		dst = chan->dev_addr;
 		control0 = PL080_CONTROL_DST_AHB2;
@@ -416,7 +416,7 @@
 
 
 int s3c2410_dma_devconfig(enum dma_ch channel,
-			  enum s3c2410_dmasrc source,
+			  enum dma_data_direction source,
 			  unsigned long devaddr)
 {
 	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
@@ -437,11 +437,11 @@
 	pr_debug("%s: peripheral %d\n", __func__, peripheral);
 
 	switch (source) {
-	case S3C2410_DMASRC_HW:
+	case DMA_FROM_DEVICE:
 		config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
 		config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
 		break;
-	case S3C2410_DMASRC_MEM:
+	case DMA_TO_DEVICE:
 		config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
 		config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
 		break;
@@ -740,7 +740,7 @@
 	}
 
 	/* Set all DMA configuration to be DMA, not SDMA */
-	writel(0xffffff, S3C_SYSREG(0x110));
+	writel(0xffffff, S3C64XX_SDMA_SEL);
 
 	/* Register standard DMA controllers */
 	s3c64xx_dma_init1(0, DMACH_UART0, IRQ_DMA0, 0x75000000);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/gpiolib.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/gpiolib.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/gpiolib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/gpiolib.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,290 +0,0 @@
-/* arch/arm/plat-s3c64xx/gpiolib.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C64XX - 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>
-#include <mach/regs-gpio.h>
-
-/* GPIO bank summary:
- *
- * Bank	GPIOs	Style	SlpCon	ExtInt Group
- * A	8	4Bit	Yes	1
- * B	7	4Bit	Yes	1
- * C	8	4Bit	Yes	2
- * D	5	4Bit	Yes	3
- * E	5	4Bit	Yes	None
- * F	16	2Bit	Yes	4 [1]
- * G	7	4Bit	Yes	5
- * H	10	4Bit[2]	Yes	6
- * I	16	2Bit	Yes	None
- * J	12	2Bit	Yes	None
- * K	16	4Bit[2]	No	None
- * L	15	4Bit[2] No	None
- * M	6	4Bit	No	IRQ_EINT
- * N	16	2Bit	No	IRQ_EINT
- * O	16	2Bit	Yes	7
- * P	15	2Bit	Yes	8
- * Q	9	2Bit	Yes	9
- *
- * [1] BANKF pins 14,15 do not form part of the external interrupt sources
- * [2] BANK has two control registers, GPxCON0 and GPxCON1
- */
-
-static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.get_config	= s3c_gpio_getcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
-	.cfg_eint	= 7,
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.get_config	= s3c_gpio_getcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
-	.cfg_eint	= 3,
-	.get_config	= s3c_gpio_getcfg_s3c64xx_4bit,
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin)
-{
-	return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
-}
-
-static struct s3c_gpio_chip gpio_4bit[] = {
-	{
-		.base	= S3C64XX_GPA_BASE,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPA(0),
-			.ngpio	= S3C64XX_GPIO_A_NR,
-			.label	= "GPA",
-		},
-	}, {
-		.base	= S3C64XX_GPB_BASE,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPB(0),
-			.ngpio	= S3C64XX_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.base	= S3C64XX_GPC_BASE,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPC(0),
-			.ngpio	= S3C64XX_GPIO_C_NR,
-			.label	= "GPC",
-		},
-	}, {
-		.base	= S3C64XX_GPD_BASE,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPD(0),
-			.ngpio	= S3C64XX_GPIO_D_NR,
-			.label	= "GPD",
-		},
-	}, {
-		.base	= S3C64XX_GPE_BASE,
-		.config	= &gpio_4bit_cfg_noint,
-		.chip	= {
-			.base	= S3C64XX_GPE(0),
-			.ngpio	= S3C64XX_GPIO_E_NR,
-			.label	= "GPE",
-		},
-	}, {
-		.base	= S3C64XX_GPG_BASE,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPG(0),
-			.ngpio	= S3C64XX_GPIO_G_NR,
-			.label	= "GPG",
-		},
-	}, {
-		.base	= S3C64XX_GPM_BASE,
-		.config	= &gpio_4bit_cfg_eint0011,
-		.chip	= {
-			.base	= S3C64XX_GPM(0),
-			.ngpio	= S3C64XX_GPIO_M_NR,
-			.label	= "GPM",
-			.to_irq = s3c64xx_gpio2int_gpm,
-		},
-	},
-};
-
-static int s3c64xx_gpio2int_gpl(struct gpio_chip *chip, unsigned pin)
-{
-	return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
-}
-
-static struct s3c_gpio_chip gpio_4bit2[] = {
-	{
-		.base	= S3C64XX_GPH_BASE + 0x4,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPH(0),
-			.ngpio	= S3C64XX_GPIO_H_NR,
-			.label	= "GPH",
-		},
-	}, {
-		.base	= S3C64XX_GPK_BASE + 0x4,
-		.config	= &gpio_4bit_cfg_noint,
-		.chip	= {
-			.base	= S3C64XX_GPK(0),
-			.ngpio	= S3C64XX_GPIO_K_NR,
-			.label	= "GPK",
-		},
-	}, {
-		.base	= S3C64XX_GPL_BASE + 0x4,
-		.config	= &gpio_4bit_cfg_eint0011,
-		.chip	= {
-			.base	= S3C64XX_GPL(0),
-			.ngpio	= S3C64XX_GPIO_L_NR,
-			.label	= "GPL",
-			.to_irq = s3c64xx_gpio2int_gpl,
-		},
-	},
-};
-
-static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
-	.set_config	= s3c_gpio_setcfg_s3c24xx,
-	.get_config	= s3c_gpio_getcfg_s3c24xx,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
-	.cfg_eint	= 2,
-	.set_config	= s3c_gpio_setcfg_s3c24xx,
-	.get_config	= s3c_gpio_getcfg_s3c24xx,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
-	.cfg_eint	= 3,
-	.set_config	= s3c_gpio_setcfg_s3c24xx,
-	.get_config	= s3c_gpio_getcfg_s3c24xx,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_chip gpio_2bit[] = {
-	{
-		.base	= S3C64XX_GPF_BASE,
-		.config	= &gpio_2bit_cfg_eint11,
-		.chip	= {
-			.base	= S3C64XX_GPF(0),
-			.ngpio	= S3C64XX_GPIO_F_NR,
-			.label	= "GPF",
-		},
-	}, {
-		.base	= S3C64XX_GPI_BASE,
-		.config	= &gpio_2bit_cfg_noint,
-		.chip	= {
-			.base	= S3C64XX_GPI(0),
-			.ngpio	= S3C64XX_GPIO_I_NR,
-			.label	= "GPI",
-		},
-	}, {
-		.base	= S3C64XX_GPJ_BASE,
-		.config	= &gpio_2bit_cfg_noint,
-		.chip	= {
-			.base	= S3C64XX_GPJ(0),
-			.ngpio	= S3C64XX_GPIO_J_NR,
-			.label	= "GPJ",
-		},
-	}, {
-		.base	= S3C64XX_GPN_BASE,
-		.irq_base = IRQ_EINT(0),
-		.config	= &gpio_2bit_cfg_eint10,
-		.chip	= {
-			.base	= S3C64XX_GPN(0),
-			.ngpio	= S3C64XX_GPIO_N_NR,
-			.label	= "GPN",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= S3C64XX_GPO_BASE,
-		.config	= &gpio_2bit_cfg_eint11,
-		.chip	= {
-			.base	= S3C64XX_GPO(0),
-			.ngpio	= S3C64XX_GPIO_O_NR,
-			.label	= "GPO",
-		},
-	}, {
-		.base	= S3C64XX_GPP_BASE,
-		.config	= &gpio_2bit_cfg_eint11,
-		.chip	= {
-			.base	= S3C64XX_GPP(0),
-			.ngpio	= S3C64XX_GPIO_P_NR,
-			.label	= "GPP",
-		},
-	}, {
-		.base	= S3C64XX_GPQ_BASE,
-		.config	= &gpio_2bit_cfg_eint11,
-		.chip	= {
-			.base	= S3C64XX_GPQ(0),
-			.ngpio	= S3C64XX_GPIO_Q_NR,
-			.label	= "GPQ",
-		},
-	},
-};
-
-static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
-{
-	chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
-}
-
-static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
-				       int nr_chips,
-				       void (*fn)(struct s3c_gpio_chip *))
-{
-	for (; nr_chips > 0; nr_chips--, chips++) {
-		if (fn)
-			(fn)(chips);
-		s3c_gpiolib_add(chips);
-	}
-}
-
-static __init int s3c64xx_gpiolib_init(void)
-{
-	s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
-			    samsung_gpiolib_add_4bit);
-
-	s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
-			    samsung_gpiolib_add_4bit2);
-
-	s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
-			    s3c64xx_gpiolib_add_2bit);
-
-	return 0;
-}
-
-core_initcall(s3c64xx_gpiolib_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/clkdev.h linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/clkdev.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/clkdev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef __MACH_CLKDEV_H__
-#define __MACH_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do {} while (0)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/crag6410.h linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/crag6410.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/crag6410.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/crag6410.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+/* Cragganmore 6410 shared definitions
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *	Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MACH_CRAG6410_H
+#define MACH_CRAG6410_H
+
+#include <linux/gpio.h>
+
+#define BANFF_PMIC_IRQ_BASE		IRQ_BOARD_START
+#define GLENFARCLAS_PMIC_IRQ_BASE	(IRQ_BOARD_START + 64)
+
+#define PCA935X_GPIO_BASE		GPIO_BOARD_START
+#define CODEC_GPIO_BASE		(GPIO_BOARD_START + 8)
+#define GLENFARCLAS_PMIC_GPIO_BASE	(GPIO_BOARD_START + 16)
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
 	 * aligned and add in the offset when we load the value here.
 	 */
 
-	.macro addruart, rp, rv
+	.macro addruart, rp, rv, tmp
 		ldr	\rp, = S3C_PA_UART
 		ldr	\rv, = (S3C_VA_UART + S3C_PA_UART & 0xfffff)
 #if CONFIG_DEBUG_S3C_UART != 0
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/dma.h linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/dma.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -58,11 +58,15 @@
 	DMACH_MAX		/* the end */
 };
 
-static __inline__ bool s3c_dma_has_circular(void)
+static inline bool samsung_dma_has_circular(void)
 {
 	return true;
 }
 
+static inline bool samsung_dma_is_dmadev(void)
+{
+	return false;
+}
 #define S3C2410_DMAF_CIRCULAR		(1 << 0)
 
 #include <plat/dma.h>
@@ -95,7 +99,7 @@
 	unsigned char		 peripheral;
 
 	unsigned int		 flags;
-	enum s3c2410_dmasrc	 source;
+	enum dma_data_direction	 source;
 
 
 	dma_addr_t		dev_addr;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -12,11 +12,6 @@
  * published by the Free Software Foundation.
 */
 
-#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
-
 /* GPIO bank sizes */
 #define S3C64XX_GPIO_A_NR	(8)
 #define S3C64XX_GPIO_B_NR	(7)
@@ -96,5 +91,3 @@
 #define BOARD_NR_GPIOS 16
 
 #define ARCH_NR_GPIOS	(GPIO_BOARD_START + BOARD_NR_GPIOS)
-
-#include <asm-generic/gpio.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/irqs.h linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/irqs.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -27,36 +27,6 @@
 #define IRQ_VIC0_BASE	S3C_IRQ(0)
 #define IRQ_VIC1_BASE	S3C_IRQ(32)
 
-/* UART interrupts, each UART has 4 intterupts per channel so
- * use the space between the ISA and S3C main interrupts. Note, these
- * are not in the same order as the S3C24XX series! */
-
-#define IRQ_S3CUART_BASE0	(16)
-#define IRQ_S3CUART_BASE1	(20)
-#define IRQ_S3CUART_BASE2	(24)
-#define IRQ_S3CUART_BASE3	(28)
-
-#define UART_IRQ_RXD		(0)
-#define UART_IRQ_ERR		(1)
-#define UART_IRQ_TXD		(2)
-#define UART_IRQ_MODEM		(3)
-
-#define IRQ_S3CUART_RX0		(IRQ_S3CUART_BASE0 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX0		(IRQ_S3CUART_BASE0 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR0	(IRQ_S3CUART_BASE0 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX1		(IRQ_S3CUART_BASE1 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX1		(IRQ_S3CUART_BASE1 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR1	(IRQ_S3CUART_BASE1 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX2		(IRQ_S3CUART_BASE2 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX2		(IRQ_S3CUART_BASE2 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR2	(IRQ_S3CUART_BASE2 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX3		(IRQ_S3CUART_BASE3 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX3		(IRQ_S3CUART_BASE3 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR3	(IRQ_S3CUART_BASE3 + UART_IRQ_ERR)
-
 /* VIC based IRQs */
 
 #define S3C64XX_IRQ_VIC0(x)	(IRQ_VIC0_BASE + (x))
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/map.h linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/map.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/map.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #define __ASM_ARCH_MAP_H __FILE__
 
 #include <plat/map-base.h>
+#include <plat/map-s3c.h>
 
 /*
  * Post-mux Chip Select Regions Xm0CSn_
@@ -83,7 +84,6 @@
 #define S3C64XX_PA_IIC1		(0x7F00F000)
 
 #define S3C64XX_PA_GPIO		(0x7F008000)
-#define S3C64XX_VA_GPIO		S3C_ADDR_CPU(0x00000000)
 #define S3C64XX_SZ_GPIO		SZ_4K
 
 #define S3C64XX_PA_SDRAM	(0x50000000)
@@ -94,16 +94,10 @@
 #define S3C64XX_PA_VIC1		(0x71300000)
 
 #define S3C64XX_PA_MODEM	(0x74108000)
-#define S3C64XX_VA_MODEM	S3C_ADDR_CPU(0x00100000)
 
 #define S3C64XX_PA_USBHOST	(0x74300000)
 
 #define S3C64XX_PA_USB_HSPHY	(0x7C100000)
-#define S3C64XX_VA_USB_HSPHY	S3C_ADDR_CPU(0x00200000)
-
-/* place VICs close together */
-#define VA_VIC0			(S3C_VA_IRQ + 0x00)
-#define VA_VIC1			(S3C_VA_IRQ + 0x10000)
 
 /* compatibiltiy defines. */
 #define S3C_PA_TIMER		S3C64XX_PA_TIMER
@@ -119,7 +113,6 @@
 #define S3C_PA_FB		S3C64XX_PA_FB
 #define S3C_PA_USBHOST		S3C64XX_PA_USBHOST
 #define S3C_PA_USB_HSOTG	S3C64XX_PA_USB_HSOTG
-#define S3C_VA_USB_HSPHY	S3C64XX_VA_USB_HSPHY
 #define S3C_PA_RTC		S3C64XX_PA_RTC
 #define S3C_PA_WDT		S3C64XX_PA_WATCHDOG
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/* arch/arm/mach-s3c6400/include/mach/memory.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET     UL(0x50000000)
-
-#define CONSISTENT_DMA_SIZE	SZ_8M
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/pll.h linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/pll.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/pll.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/pll.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-/* arch/arm/plat-s3c64xx/include/plat/pll.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C64XX PLL 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.
-*/
-
-#define S3C6400_PLL_MDIV_MASK	((1 << (25-16+1)) - 1)
-#define S3C6400_PLL_PDIV_MASK	((1 << (13-8+1)) - 1)
-#define S3C6400_PLL_SDIV_MASK	((1 << (2-0+1)) - 1)
-#define S3C6400_PLL_MDIV_SHIFT	(16)
-#define S3C6400_PLL_PDIV_SHIFT	(8)
-#define S3C6400_PLL_SDIV_SHIFT	(0)
-
-#include <asm/div64.h>
-#include <plat/pll6553x.h>
-
-static inline unsigned long s3c6400_get_pll(unsigned long baseclk,
-					    u32 pllcon)
-{
-	u32 mdiv, pdiv, sdiv;
-	u64 fvco = baseclk;
-
-	mdiv = (pllcon >> S3C6400_PLL_MDIV_SHIFT) & S3C6400_PLL_MDIV_MASK;
-	pdiv = (pllcon >> S3C6400_PLL_PDIV_SHIFT) & S3C6400_PLL_PDIV_MASK;
-	sdiv = (pllcon >> S3C6400_PLL_SDIV_SHIFT) & S3C6400_PLL_SDIV_MASK;
-
-	fvco *= mdiv;
-	do_div(fvco, (pdiv << sdiv));
-
-	return (unsigned long)fvco;
-}
-
-static inline unsigned long s3c6400_get_epll(unsigned long baseclk)
-{
-	return s3c_get_pll6553x(baseclk, __raw_readl(S3C_EPLL_CON0),
-				__raw_readl(S3C_EPLL_CON1));
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/pm-core.h linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/pm-core.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/pm-core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/pm-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -104,7 +104,7 @@
 	__raw_writel(0, S3C64XX_SLPEN);
 }
 
-static inline void s3c_pm_saved_gpios(void)
+static inline void samsung_pm_saved_gpios(void)
 {
 	/* turn on the sleep mode and keep it there, as it seems that during
 	 * suspend the xCON registers get re-set and thus you can end up with
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/pwm-clock.h linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/pwm-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/pwm-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-/* linux/arch/arm/mach-s3c6400/include/mach/pwm-clock.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C64xx - pwm clock and timer support
- */
-
-/**
- * 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
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/regs-sys.h linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/regs-sys.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/regs-sys.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/regs-sys.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,8 +21,11 @@
 #define S3C64XX_AHB_CON1	S3C_SYSREG(0x104)
 #define S3C64XX_AHB_CON2	S3C_SYSREG(0x108)
 
+#define S3C64XX_SDMA_SEL	S3C_SYSREG(0x110)
+
 #define S3C64XX_OTHERS		S3C_SYSREG(0x900)
 
 #define S3C64XX_OTHERS_USBMASK	(1 << 16)
+#define S3C64XX_OTHERS_SYNCMUXSEL	(1 << 6)
 
 #endif /* _PLAT_REGS_SYS_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/s3c6400.h linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/s3c6400.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/s3c6400.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/s3c6400.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-/* arch/arm/mach-s3c64xx/include/macht/s3c6400.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * Header file for s3c6400 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 S3C6400 related SoCs */
-
-extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-extern void s3c6400_setup_clocks(void);
-
-extern void s3c64xx_register_clocks(unsigned long xtal, unsigned armclk_limit);
-
-#ifdef CONFIG_CPU_S3C6400
-
-extern  int s3c6400_init(void);
-extern void s3c6400_init_irq(void);
-extern void s3c6400_map_io(void);
-extern void s3c6400_init_clocks(int xtal);
-
-#define s3c6400_init_uarts s3c6400_common_init_uarts
-
-#else
-#define s3c6400_init_clocks NULL
-#define s3c6400_init_uarts NULL
-#define s3c6400_map_io NULL
-#define s3c6400_init NULL
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/s3c6410.h linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/s3c6410.h
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/include/mach/s3c6410.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/include/mach/s3c6410.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/* arch/arm/mach-s3c64xx/include/mach/s3c6410.h
- *
- * Copyright 2008 Openmoko,  Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * Header file for s3c6410 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.
-*/
-
-#ifdef CONFIG_CPU_S3C6410
-
-extern  int s3c6410_init(void);
-extern void s3c6410_init_irq(void);
-extern void s3c6410_map_io(void);
-extern void s3c6410_init_clocks(int xtal);
-
-#define s3c6410_init_uarts s3c6400_common_init_uarts
-
-#else
-#define s3c6410_init_clocks NULL
-#define s3c6410_init_uarts NULL
-#define s3c6410_map_io NULL
-#define s3c6410_init NULL
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/irq.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/irq.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,29 +25,6 @@
 #include <plat/irq-uart.h>
 #include <plat/cpu.h>
 
-static struct s3c_uart_irq uart_irqs[] = {
-	[0] = {
-		.regs		= S3C_VA_UART0,
-		.base_irq	= IRQ_S3CUART_BASE0,
-		.parent_irq	= IRQ_UART0,
-	},
-	[1] = {
-		.regs		= S3C_VA_UART1,
-		.base_irq	= IRQ_S3CUART_BASE1,
-		.parent_irq	= IRQ_UART1,
-	},
-	[2] = {
-		.regs		= S3C_VA_UART2,
-		.base_irq	= IRQ_S3CUART_BASE2,
-		.parent_irq	= IRQ_UART2,
-	},
-	[3] = {
-		.regs		= S3C_VA_UART3,
-		.base_irq	= IRQ_S3CUART_BASE3,
-		.parent_irq	= IRQ_UART3,
-	},
-};
-
 /* setup the sources the vic should advertise resume for, even though it
  * is not doing the wake (set_irq_wake needs to be valid) */
 #define IRQ_VIC0_RESUME (1 << (IRQ_RTC_TIC - IRQ_VIC0_BASE))
@@ -67,6 +44,4 @@
 
 	/* add the timer sub-irqs */
 	s3c_init_vic_timer_irq(5, IRQ_TIMER0);
-
-	s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/Kconfig linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -288,5 +288,6 @@
 	select S3C_DEV_RTC
 	select S3C64XX_DEV_SPI
 	select S3C24XX_GPIO_EXTRA128
+	select I2C
 	help
 	  Machine support for the Wolfson Cragganmore S3C6410 variant.
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-anw6410.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-anw6410.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-anw6410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-anw6410.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,7 +45,7 @@
 #include <plat/fb.h>
 #include <plat/regs-fb-v4.h>
 
-#include <mach/s3c6410.h>
+#include <plat/s3c6410.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -233,7 +233,7 @@
 
 MACHINE_START(ANW6410, "A&W6410")
 	/* Maintainer: Kwangwoo Lee <kwangwoo.lee@gmail.com> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= anw6410_map_io,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-crag6410.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-crag6410.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-crag6410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-crag6410.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,13 +43,14 @@
 #include <mach/hardware.h>
 #include <mach/map.h>
 
-#include <mach/s3c6410.h>
 #include <mach/regs-sys.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-modem.h>
+#include <mach/crag6410.h>
 
 #include <mach/regs-gpio-memport.h>
 
+#include <plat/s3c6410.h>
 #include <plat/regs-serial.h>
 #include <plat/regs-fb-v4.h>
 #include <plat/fb.h>
@@ -65,17 +66,6 @@
 #include <plat/iic.h>
 #include <plat/pm.h>
 
-#include <sound/wm8996.h>
-#include <sound/wm8962.h>
-#include <sound/wm9081.h>
-
-#define BANFF_PMIC_IRQ_BASE		IRQ_BOARD_START
-#define GLENFARCLAS_PMIC_IRQ_BASE	(IRQ_BOARD_START + 64)
-
-#define PCA935X_GPIO_BASE		GPIO_BOARD_START
-#define CODEC_GPIO_BASE		(GPIO_BOARD_START + 8)
-#define GLENFARCLAS_PMIC_GPIO_BASE	(GPIO_BOARD_START + 16)
-
 /* serial port setup */
 
 #define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
@@ -287,6 +277,11 @@
 	.id		= -1,
 };
 
+static struct platform_device lowland_device = {
+	.name		= "lowland",
+	.id		= -1,
+};
+
 static struct platform_device speyside_wm8962_device = {
 	.name		= "speyside-wm8962",
 	.id		= -1,
@@ -295,6 +290,8 @@
 static struct regulator_consumer_supply wallvdd_consumers[] = {
 	REGULATOR_SUPPLY("SPKVDD1", "1-001a"),
 	REGULATOR_SUPPLY("SPKVDD2", "1-001a"),
+	REGULATOR_SUPPLY("SPKVDDL", "1-001a"),
+	REGULATOR_SUPPLY("SPKVDDR", "1-001a"),
 };
 
 static struct regulator_init_data wallvdd_data = {
@@ -329,9 +326,6 @@
 	&s3c_device_fb,
 	&s3c_device_ohci,
 	&s3c_device_usb_hsotg,
-	&s3c_device_adc,
-	&s3c_device_rtc,
-	&s3c_device_ts,
 	&s3c_device_timer[0],
 	&s3c64xx_device_iis0,
 	&s3c64xx_device_iis1,
@@ -345,6 +339,7 @@
 	&crag6410_backlight_device,
 	&speyside_device,
 	&speyside_wm8962_device,
+	&lowland_device,
 	&wallvdd_device,
 };
 
@@ -353,6 +348,12 @@
 	.irq_base	= 0,
 };
 
+/* VDDARM is controlled by DVS1 connected to GPK(0) */
+static struct wm831x_buckv_pdata vddarm_pdata = {
+	.dvs_control_src = 1,
+	.dvs_gpio = S3C64XX_GPK(0),
+};
+
 static struct regulator_consumer_supply vddarm_consumers[] __initdata = {
 	REGULATOR_SUPPLY("vddarm", NULL),
 };
@@ -368,6 +369,7 @@
 	.num_consumer_supplies = ARRAY_SIZE(vddarm_consumers),
 	.consumer_supplies = vddarm_consumers,
 	.supply_regulator = "WALLVDD",
+	.driver_data = &vddarm_pdata,
 };
 
 static struct regulator_init_data vddint __initdata = {
@@ -503,6 +505,8 @@
 	.backup = &banff_backup_pdata,
 
 	.gpio_defaults = {
+		/* GPIO5: DVS1_REQ - CMOS, DBVDD, active high */
+		[4] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA | 0x8,
 		/* GPIO11: Touchscreen data - CMOS, DBVDD, active high*/
 		[10] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x6,
 		/* GPIO12: Touchscreen pen down - CMOS, DBVDD, active high*/
@@ -560,8 +564,12 @@
 };
 
 static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = {
+	REGULATOR_SUPPLY("LDOVDD", "1-001a"),
 	REGULATOR_SUPPLY("PLLVDD", "1-001a"),
 	REGULATOR_SUPPLY("DBVDD", "1-001a"),
+	REGULATOR_SUPPLY("DBVDD1", "1-001a"),
+	REGULATOR_SUPPLY("DBVDD2", "1-001a"),
+	REGULATOR_SUPPLY("DBVDD3", "1-001a"),
 	REGULATOR_SUPPLY("CPVDD", "1-001a"),
 	REGULATOR_SUPPLY("AVDD2", "1-001a"),
 	REGULATOR_SUPPLY("DCVDD", "1-001a"),
@@ -614,81 +622,16 @@
 	.disable_touch = true,
 };
 
-static struct wm8996_retune_mobile_config wm8996_retune[] = {
-	{
-		.name = "Sub LPF",
-		.rate = 48000,
-		.regs = {
-			0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
-			0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
-			0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
-		},
-	},
-	{
-		.name = "Sub HPF",
-		.rate = 48000,
-		.regs = {
-			0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
-			0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
-			0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
-		},
-	},
-};
-
-static struct wm8996_pdata wm8996_pdata __initdata = {
-	.ldo_ena = S3C64XX_GPN(7),
-	.gpio_base = CODEC_GPIO_BASE,
-	.micdet_def = 1,
-	.inl_mode = WM8996_DIFFERRENTIAL_1,
-	.inr_mode = WM8996_DIFFERRENTIAL_1,
-
-	.irq_flags = IRQF_TRIGGER_RISING,
-
-	.gpio_default = {
-		0x8001, /* GPIO1 == ADCLRCLK1 */
-		0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
-		0x0141, /* GPIO3 == HP_SEL */
-		0x0002, /* GPIO4 == IRQ */
-		0x020e, /* GPIO5 == CLKOUT */
-	},
-
-	.retune_mobile_cfgs = wm8996_retune,
-	.num_retune_mobile_cfgs = ARRAY_SIZE(wm8996_retune),
-};
-
-static struct wm8962_pdata wm8962_pdata __initdata = {
-	.gpio_init = {
-		0,
-		WM8962_GPIO_FN_OPCLK,
-		WM8962_GPIO_FN_DMICCLK,
-		0,
-		0x8000 | WM8962_GPIO_FN_DMICDAT,
-		WM8962_GPIO_FN_IRQ,    /* Open drain mode */
-	},
-	.irq_active_low = true,
-};
-
-static struct wm9081_pdata wm9081_pdata __initdata = {
-	.irq_high = false,
-	.irq_cmos = false,
-};
-
 static struct i2c_board_info i2c_devs1[] __initdata = {
 	{ I2C_BOARD_INFO("wm8311", 0x34),
 	  .irq = S3C_EINT(0),
 	  .platform_data = &glenfarclas_pmic_pdata },
 
+	{ I2C_BOARD_INFO("wlf-gf-module", 0x24) },
+	{ I2C_BOARD_INFO("wlf-gf-module", 0x25) },
+	{ I2C_BOARD_INFO("wlf-gf-module", 0x26) },
+
 	{ I2C_BOARD_INFO("wm1250-ev1", 0x27) },
-	{ I2C_BOARD_INFO("wm8996", 0x1a),
-	  .platform_data = &wm8996_pdata,
-	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
-	},
-	{ I2C_BOARD_INFO("wm9081", 0x6c),
-	  .platform_data = &wm9081_pdata, },
-	{ I2C_BOARD_INFO("wm8962", 0x1a),
-	  .platform_data = &wm8962_pdata,
-	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
-	},
 };
 
 static void __init crag6410_map_io(void)
@@ -766,7 +709,7 @@
 
 MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410")
 	/* Maintainer: Mark Brown <broonie@opensource.wolfsonmicro.com> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= crag6410_map_io,
 	.init_machine	= crag6410_machine_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-crag6410-module.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-crag6410-module.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-crag6410-module.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-crag6410-module.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,182 @@
+/* Speyside modules for Cragganmore - board data probing
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *	Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/export.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+
+#include <linux/mfd/wm831x/irq.h>
+#include <linux/mfd/wm831x/gpio.h>
+
+#include <sound/wm8996.h>
+#include <sound/wm8962.h>
+#include <sound/wm9081.h>
+
+#include <mach/crag6410.h>
+
+static struct wm8996_retune_mobile_config wm8996_retune[] = {
+	{
+		.name = "Sub LPF",
+		.rate = 48000,
+		.regs = {
+			0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
+			0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
+			0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
+		},
+	},
+	{
+		.name = "Sub HPF",
+		.rate = 48000,
+		.regs = {
+			0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
+			0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
+			0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
+		},
+	},
+};
+
+static struct wm8996_pdata wm8996_pdata __initdata = {
+	.ldo_ena = S3C64XX_GPN(7),
+	.gpio_base = CODEC_GPIO_BASE,
+	.micdet_def = 1,
+	.inl_mode = WM8996_DIFFERRENTIAL_1,
+	.inr_mode = WM8996_DIFFERRENTIAL_1,
+
+	.irq_flags = IRQF_TRIGGER_RISING,
+
+	.gpio_default = {
+		0x8001, /* GPIO1 == ADCLRCLK1 */
+		0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
+		0x0141, /* GPIO3 == HP_SEL */
+		0x0002, /* GPIO4 == IRQ */
+		0x020e, /* GPIO5 == CLKOUT */
+	},
+
+	.retune_mobile_cfgs = wm8996_retune,
+	.num_retune_mobile_cfgs = ARRAY_SIZE(wm8996_retune),
+};
+
+static struct wm8962_pdata wm8962_pdata __initdata = {
+	.gpio_init = {
+		0,
+		WM8962_GPIO_FN_OPCLK,
+		WM8962_GPIO_FN_DMICCLK,
+		0,
+		0x8000 | WM8962_GPIO_FN_DMICDAT,
+		WM8962_GPIO_FN_IRQ,    /* Open drain mode */
+	},
+	.irq_active_low = true,
+};
+
+static struct wm9081_pdata wm9081_pdata __initdata = {
+	.irq_high = false,
+	.irq_cmos = false,
+};
+
+static const struct i2c_board_info wm1254_devs[] = {
+	{ I2C_BOARD_INFO("wm8996", 0x1a),
+	  .platform_data = &wm8996_pdata,
+	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+	},
+	{ I2C_BOARD_INFO("wm9081", 0x6c),
+	  .platform_data = &wm9081_pdata, },
+};
+
+static const struct i2c_board_info wm1255_devs[] = {
+	{ I2C_BOARD_INFO("wm5100", 0x1a),
+	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+	},
+	{ I2C_BOARD_INFO("wm9081", 0x6c),
+	  .platform_data = &wm9081_pdata, },
+};
+
+static const struct i2c_board_info wm1259_devs[] = {
+	{ I2C_BOARD_INFO("wm8962", 0x1a),
+	  .platform_data = &wm8962_pdata,
+	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+	},
+};
+
+
+static __devinitdata const struct {
+	u8 id;
+	const char *name;
+	const struct i2c_board_info *i2c_devs;
+	int num_i2c_devs;
+} gf_mods[] = {
+	{ .id = 0x01, .name = "1250-EV1 Springbank" },
+	{ .id = 0x02, .name = "1251-EV1 Jura" },
+	{ .id = 0x03, .name = "1252-EV1 Glenlivet" },
+	{ .id = 0x11, .name = "6249-EV2 Glenfarclas", },
+	{ .id = 0x21, .name = "1275-EV1 Mortlach" },
+	{ .id = 0x25, .name = "1274-EV1 Glencadam" },
+	{ .id = 0x31, .name = "1253-EV1 Tomatin", },
+	{ .id = 0x39, .name = "1254-EV1 Dallas Dhu",
+	  .i2c_devs = wm1254_devs, .num_i2c_devs = ARRAY_SIZE(wm1254_devs) },
+	{ .id = 0x3a, .name = "1259-EV1 Tobermory",
+	  .i2c_devs = wm1259_devs, .num_i2c_devs = ARRAY_SIZE(wm1259_devs) },
+	{ .id = 0x3b, .name = "1255-EV1 Kilchoman",
+	  .i2c_devs = wm1255_devs, .num_i2c_devs = ARRAY_SIZE(wm1255_devs) },
+	{ .id = 0x3c, .name = "1273-EV1 Longmorn" },
+};
+
+static __devinit int wlf_gf_module_probe(struct i2c_client *i2c,
+					 const struct i2c_device_id *i2c_id)
+{
+	int ret, i, j, id, rev;
+
+	ret = i2c_smbus_read_byte_data(i2c, 0);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to read ID: %d\n", ret);
+		return ret;
+	}
+
+	id = (ret & 0xfe) >> 2;
+	rev = ret & 0x3;
+	for (i = 0; i < ARRAY_SIZE(gf_mods); i++)
+		if (id == gf_mods[i].id)
+			break;
+
+	if (i < ARRAY_SIZE(gf_mods)) {
+		dev_info(&i2c->dev, "%s revision %d\n",
+			 gf_mods[i].name, rev + 1);
+		for (j = 0; j < gf_mods[i].num_i2c_devs; j++) {
+			if (!i2c_new_device(i2c->adapter,
+					    &(gf_mods[i].i2c_devs[j])))
+				dev_err(&i2c->dev,
+					"Failed to register dev: %d\n", ret);
+		}
+	} else {
+		dev_warn(&i2c->dev, "Unknown module ID %d revision %d\n",
+			 id, rev);
+	}
+
+	return 0;
+}
+
+static const struct i2c_device_id wlf_gf_module_id[] = {
+	{ "wlf-gf-module", 0 },
+	{ }
+};
+
+static struct i2c_driver wlf_gf_module_driver = {
+	.driver = {
+		.name = "wlf-gf-module",
+		.owner = THIS_MODULE,
+	},
+	.probe = wlf_gf_module_probe,
+	.id_table = wlf_gf_module_id,
+};
+
+static int __init wlf_gf_module_register(void)
+{
+	return i2c_add_driver(&wlf_gf_module_driver);
+}
+module_init(wlf_gf_module_register);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-hmt.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-hmt.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-hmt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-hmt.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,7 +37,7 @@
 #include <plat/fb.h>
 #include <plat/nand.h>
 
-#include <mach/s3c6410.h>
+#include <plat/s3c6410.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -265,7 +265,7 @@
 
 MACHINE_START(HMT, "Airgoo-HMT")
 	/* Maintainer: Peter Korsgaard <jacmet@sunsite.dk> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= hmt_map_io,
 	.init_machine	= hmt_machine_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-mini6410.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-mini6410.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-mini6410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-mini6410.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,8 +32,8 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-modem.h>
 #include <mach/regs-srom.h>
-#include <mach/s3c6410.h>
 
+#include <plat/s3c6410.h>
 #include <plat/adc.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
@@ -205,12 +205,6 @@
 	.dev.platform_data	= &mini6410_lcd_power_data,
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 static struct platform_device *mini6410_devices[] __initdata = {
 	&mini6410_device_eth,
 	&s3c_device_hsmmc0,
@@ -319,7 +313,7 @@
 
 	s3c_nand_set_platdata(&mini6410_nand_info);
 	s3c_fb_set_platdata(&mini6410_lcd_pdata);
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	/* configure nCS1 width to 16 bits */
 
@@ -349,7 +343,7 @@
 
 MACHINE_START(MINI6410, "MINI6410")
 	/* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= mini6410_map_io,
 	.init_machine	= mini6410_machine_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-ncp.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-ncp.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-ncp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-ncp.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,7 +39,7 @@
 #include <plat/iic.h>
 #include <plat/fb.h>
 
-#include <mach/s3c6410.h>
+#include <plat/s3c6410.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -97,7 +97,7 @@
 
 MACHINE_START(NCP, "NCP")
 	/* Maintainer: Samsung Electronics */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= ncp_map_io,
 	.init_machine	= ncp_machine_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-real6410.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-real6410.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-real6410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-real6410.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,8 +33,8 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-modem.h>
 #include <mach/regs-srom.h>
-#include <mach/s3c6410.h>
 
+#include <plat/s3c6410.h>
 #include <plat/adc.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
@@ -198,12 +198,6 @@
 	&s3c_device_ohci,
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 static void __init real6410_map_io(void)
 {
 	u32 tmp;
@@ -300,7 +294,7 @@
 
 	s3c_fb_set_platdata(&real6410_lcd_pdata);
 	s3c_nand_set_platdata(&real6410_nand_info);
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	/* configure nCS1 width to 16 bits */
 
@@ -329,7 +323,7 @@
 
 MACHINE_START(REAL6410, "REAL6410")
 	/* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= real6410_map_io,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-smartq5.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-smartq5.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-smartq5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-smartq5.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,8 +22,8 @@
 
 #include <mach/map.h>
 #include <mach/regs-gpio.h>
-#include <mach/s3c6410.h>
 
+#include <plat/s3c6410.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/fb.h>
@@ -146,7 +146,7 @@
 
 MACHINE_START(SMARTQ5, "SmartQ 5")
 	/* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= smartq_map_io,
 	.init_machine	= smartq5_machine_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-smartq7.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-smartq7.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-smartq7.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-smartq7.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,8 +22,8 @@
 
 #include <mach/map.h>
 #include <mach/regs-gpio.h>
-#include <mach/s3c6410.h>
 
+#include <plat/s3c6410.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/fb.h>
@@ -162,7 +162,7 @@
 
 MACHINE_START(SMARTQ7, "SmartQ 7")
 	/* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= smartq_map_io,
 	.init_machine	= smartq7_machine_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-smdk6400.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-smdk6400.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-smdk6400.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-smdk6400.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,7 @@
 
 #include <plat/regs-serial.h>
 
-#include <mach/s3c6400.h>
+#include <plat/s3c6400.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -85,7 +85,7 @@
 
 MACHINE_START(SMDK6400, "SMDK6400")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s3c6400_init_irq,
 	.map_io		= smdk6400_map_io,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-smdk6410.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-smdk6410.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/mach-smdk6410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/mach-smdk6410.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,7 +63,7 @@
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
 
-#include <mach/s3c6410.h>
+#include <plat/s3c6410.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -619,12 +619,6 @@
 	{ I2C_BOARD_INFO("24c128", 0x57), },	/* Samsung S524AD0XD1 */
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 /* LCD Backlight data */
 static struct samsung_bl_gpio_info smdk6410_bl_gpio_info = {
 	.no = S3C64XX_GPF(15),
@@ -666,7 +660,7 @@
 
 	samsung_keypad_set_platdata(&smdk6410_keypad_data);
 
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	/* configure nCS1 width to 16 bits */
 
@@ -703,7 +697,7 @@
 
 MACHINE_START(SMDK6410, "SMDK6410")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= smdk6410_map_io,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/Makefile linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@
 # Core files
 obj-y				+= cpu.o
 obj-y				+= clock.o
-obj-y				+= gpiolib.o
 
 # Core support for S3C6400 system
 
@@ -55,12 +54,10 @@
 obj-$(CONFIG_MACH_SMARTQ)	+= mach-smartq.o
 obj-$(CONFIG_MACH_SMARTQ5)	+= mach-smartq5.o
 obj-$(CONFIG_MACH_SMARTQ7)	+= mach-smartq7.o
-obj-$(CONFIG_MACH_WLF_CRAGG_6410) += mach-crag6410.o
+obj-$(CONFIG_MACH_WLF_CRAGG_6410) += mach-crag6410.o mach-crag6410-module.o
 
 # device support
 
 obj-y				+= dev-uart.o
 obj-y				+= dev-audio.o
 obj-$(CONFIG_S3C64XX_DEV_SPI)	+= dev-spi.o
-obj-$(CONFIG_S3C64XX_DEV_TS)	+= dev-ts.o
-obj-$(CONFIG_S3C64XX_DEV_ONENAND1)	+= dev-onenand1.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-   zreladdr-y	:= 0x50008000
+   zreladdr-y	+= 0x50008000
 params_phys-y	:= 0x50000100
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/pm.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/pm.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-syscon-power.h>
 #include <mach/regs-gpio-memport.h>
+#include <mach/regs-modem.h>
 
 #ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
 void s3c_pm_debug_smdkled(u32 set, u32 clear)
@@ -85,6 +86,9 @@
 	SAVE_ITEM(S3C64XX_MEM0CONSLP0),
 	SAVE_ITEM(S3C64XX_MEM0CONSLP1),
 	SAVE_ITEM(S3C64XX_MEM1CONSLP),
+
+	SAVE_ITEM(S3C64XX_SDMA_SEL),
+	SAVE_ITEM(S3C64XX_MODEM_MIFPCON),
 };
 
 void s3c_pm_configure_extint(void)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/s3c6400.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/s3c6400.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/s3c6400.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/s3c6400.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,7 +38,7 @@
 #include <plat/sdhci.h>
 #include <plat/iic-core.h>
 #include <plat/onenand-core.h>
-#include <mach/s3c6400.h>
+#include <plat/s3c6400.h>
 
 void __init s3c6400_map_io(void)
 {
@@ -70,7 +70,7 @@
 	s3c64xx_init_irq(~0 & ~(0xf << 5), ~0);
 }
 
-struct sysdev_class s3c6400_sysclass = {
+static struct sysdev_class s3c6400_sysclass = {
 	.name	= "s3c6400-core",
 };
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/s3c6410.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/s3c6410.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/s3c6410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/s3c6410.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,8 +41,8 @@
 #include <plat/adc-core.h>
 #include <plat/iic-core.h>
 #include <plat/onenand-core.h>
-#include <mach/s3c6400.h>
-#include <mach/s3c6410.h>
+#include <plat/s3c6400.h>
+#include <plat/s3c6410.h>
 
 void __init s3c6410_map_io(void)
 {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/setup-fb-24bpp.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/setup-fb-24bpp.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/setup-fb-24bpp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/setup-fb-24bpp.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
 
-extern void s3c64xx_fb_gpio_setup_24bpp(void)
+void s3c64xx_fb_gpio_setup_24bpp(void)
 {
 	s3c_gpio_cfgrange_nopull(S3C64XX_GPI(0), 16, S3C_GPIO_SFN(2));
 	s3c_gpio_cfgrange_nopull(S3C64XX_GPJ(0), 12, S3C_GPIO_SFN(2));
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/setup-sdhci.c linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/setup-sdhci.c
--- linux-libre-3.1-gnu/arch/arm/mach-s3c64xx/setup-sdhci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s3c64xx/setup-sdhci.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,17 +12,7 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
 
 /* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
 
@@ -32,41 +22,3 @@
 	[2] = "mmc_bus",
 	/* [3] = "48m", - note not successfully used yet */
 };
-
-void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev,
-				  void __iomem *r,
-				  struct mmc_ios *ios,
-				  struct mmc_card *card)
-{
-	u32 ctrl2, ctrl3;
-
-	ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
-	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-		  S3C_SDHCI_CTRL2_ENFBCLKRX |
-		  S3C_SDHCI_CTRL2_DFCNT_NONE |
-		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-	if (ios->clock < 25 * 1000000)
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-			 S3C_SDHCI_CTRL3_FCSEL2 |
-			 S3C_SDHCI_CTRL3_FCSEL1 |
-			 S3C_SDHCI_CTRL3_FCSEL0);
-	else
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-	pr_debug("%s: CTRL 2=%08x, 3=%08x\n", __func__, ctrl2, ctrl3);
-	writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
-
-void s3c6410_setup_sdhci_cfg_card(struct platform_device *dev,
-				  void __iomem *r,
-				  struct mmc_ios *ios,
-				  struct mmc_card *card)
-{
-	writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4);
-
-	s3c6400_setup_sdhci_cfg_card(dev, r, ios, card);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/clock-s5p6440.c linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/clock-s5p6440.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/clock-s5p6440.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/clock-s5p6440.c	2012-01-04 18:55:44.000000000 -0500
@@ -146,7 +146,8 @@
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 8),
 	}, {
-		.name		= "pdma",
+		.name		= "dma",
+		.devname	= "dma-pl330",
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 12),
@@ -499,6 +500,11 @@
 	&clk_pclk_low,
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 void __init_or_cpufreq s5p6440_setup_clocks(void)
 {
 	struct clk *xtal_clk;
@@ -581,5 +587,7 @@
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
+
 	s3c_pwmclk_init();
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/clock-s5p6450.c linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/clock-s5p6450.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/clock-s5p6450.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/clock-s5p6450.c	2012-01-04 18:55:44.000000000 -0500
@@ -179,7 +179,8 @@
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
-		.name		= "pdma",
+		.name		= "dma",
+		.devname	= "dma-pl330",
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 12),
@@ -553,6 +554,11 @@
 	&clk_sclk_audio0,
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 void __init_or_cpufreq s5p6450_setup_clocks(void)
 {
 	struct clk *xtal_clk;
@@ -632,5 +638,7 @@
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
+
 	s3c_pwmclk_init();
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/cpu.c linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/cpu.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -38,6 +39,7 @@
 #include <plat/s5p6440.h>
 #include <plat/s5p6450.h>
 #include <plat/adc-core.h>
+#include <plat/fb-core.h>
 
 /* Initial IO mappings */
 
@@ -108,18 +110,22 @@
 {
 	/* initialize any device information early */
 	s3c_adc_setname("s3c64xx-adc");
+	s3c_fb_setname("s5p64x0-fb");
 
 	iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
 	iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc));
+	init_consistent_dma_size(SZ_8M);
 }
 
 void __init s5p6450_map_io(void)
 {
 	/* initialize any device information early */
 	s3c_adc_setname("s3c64xx-adc");
+	s3c_fb_setname("s5p64x0-fb");
 
 	iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
 	iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc));
+	init_consistent_dma_size(SZ_8M);
 }
 
 /*
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/dev-spi.c linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/dev-spi.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/dev-spi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/dev-spi.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <mach/regs-clock.h>
 #include <mach/spi-clocks.h>
 
+#include <plat/cpu.h>
 #include <plat/s3c64xx-spi.h>
 #include <plat/gpio-cfg.h>
 
@@ -185,11 +186,8 @@
 
 void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
 {
-	unsigned int id;
 	struct s3c64xx_spi_info *pd;
 
-	id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
-
 	/* Reject invalid configuration */
 	if (!num_cs || src_clk_nr < 0
 			|| src_clk_nr > S5P64X0_SPI_SRCCLK_SCLK) {
@@ -199,7 +197,7 @@
 
 	switch (cntrlr) {
 	case 0:
-		if (id == 0x50000)
+		if (soc_is_s5p6450())
 			pd = &s5p6450_spi0_pdata;
 		else
 			pd = &s5p6440_spi0_pdata;
@@ -207,7 +205,7 @@
 		s5p64x0_device_spi0.dev.platform_data = pd;
 		break;
 	case 1:
-		if (id == 0x50000)
+		if (soc_is_s5p6450())
 			pd = &s5p6450_spi1_pdata;
 		else
 			pd = &s5p6440_spi1_pdata;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/dma.c linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/dma.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,128 +21,218 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
+
+#include <asm/irq.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
 #include <mach/regs-clock.h>
+#include <mach/dma.h>
 
+#include <plat/cpu.h>
 #include <plat/devs.h>
-#include <plat/s3c-pl330-pdata.h>
+#include <plat/irqs.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5p64x0_pdma_resource[] = {
-	[0] = {
-		.start	= S5P64X0_PA_PDMA,
-		.end	= S5P64X0_PA_PDMA + SZ_4K,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_DMA0,
-		.end	= IRQ_DMA0,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri s5p6440_pdma_peri[22] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_MAX,
+	}, {
+		.peri_id = DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
 	},
 };
 
-static struct s3c_pl330_platdata s5p6440_pdma_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_MAX,
-		[9] = DMACH_MAX,
-		[10] = DMACH_PCM0_TX,
-		[11] = DMACH_PCM0_RX,
-		[12] = DMACH_I2S0_TX,
-		[13] = DMACH_I2S0_RX,
-		[14] = DMACH_SPI0_TX,
-		[15] = DMACH_SPI0_RX,
-		[16] = DMACH_MAX,
-		[17] = DMACH_MAX,
-		[18] = DMACH_MAX,
-		[19] = DMACH_MAX,
-		[20] = DMACH_SPI1_TX,
-		[21] = DMACH_SPI1_RX,
-		[22] = DMACH_MAX,
-		[23] = DMACH_MAX,
-		[24] = DMACH_MAX,
-		[25] = DMACH_MAX,
-		[26] = DMACH_MAX,
-		[27] = DMACH_MAX,
-		[28] = DMACH_MAX,
-		[29] = DMACH_PWM,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata s5p6440_pdma_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(s5p6440_pdma_peri),
+	.peri = s5p6440_pdma_peri,
 };
 
-static struct s3c_pl330_platdata s5p6450_pdma_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_UART4_RX,
-		[9] = DMACH_UART4_TX,
-		[10] = DMACH_PCM0_TX,
-		[11] = DMACH_PCM0_RX,
-		[12] = DMACH_I2S0_TX,
-		[13] = DMACH_I2S0_RX,
-		[14] = DMACH_SPI0_TX,
-		[15] = DMACH_SPI0_RX,
-		[16] = DMACH_PCM1_TX,
-		[17] = DMACH_PCM1_RX,
-		[18] = DMACH_PCM2_TX,
-		[19] = DMACH_PCM2_RX,
-		[20] = DMACH_SPI1_TX,
-		[21] = DMACH_SPI1_RX,
-		[22] = DMACH_USI_TX,
-		[23] = DMACH_USI_RX,
-		[24] = DMACH_MAX,
-		[25] = DMACH_I2S1_TX,
-		[26] = DMACH_I2S1_RX,
-		[27] = DMACH_I2S2_TX,
-		[28] = DMACH_I2S2_RX,
-		[29] = DMACH_PWM,
-		[30] = DMACH_UART5_RX,
-		[31] = DMACH_UART5_TX,
+struct dma_pl330_peri s5p6450_pdma_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART4_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART4_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_USI_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_USI_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PWM,
+	}, {
+		.peri_id = (u8)DMACH_UART5_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART5_TX,
+		.rqtype = MEMTODEV,
 	},
 };
 
-static struct platform_device s5p64x0_device_pdma = {
-	.name		= "s3c-pl330",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p64x0_pdma_resource),
-	.resource	= s5p64x0_pdma_resource,
-	.dev		= {
+struct dma_pl330_platdata s5p6450_pdma_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(s5p6450_pdma_peri),
+	.peri = s5p6450_pdma_peri,
+};
+
+struct amba_device s5p64x0_device_pdma = {
+	.dev = {
+		.init_name = "dma-pl330",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 	},
+	.res = {
+		.start = S5P64X0_PA_PDMA,
+		.end = S5P64X0_PA_PDMA + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_DMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
 static int __init s5p64x0_dma_init(void)
 {
-	unsigned int id;
-
-	id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
-
-	if (id == 0x50000)
+	if (soc_is_s5p6450())
 		s5p64x0_device_pdma.dev.platform_data = &s5p6450_pdma_pdata;
 	else
 		s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata;
 
-	platform_device_register(&s5p64x0_device_pdma);
+	amba_device_register(&s5p64x0_device_pdma, &iomem_resource);
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/gpiolib.c linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/gpiolib.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/gpiolib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/gpiolib.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-clock.h>
 
+#include <plat/cpu.h>
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
 #include <plat/gpio-cfg-helpers.h>
@@ -473,14 +474,10 @@
 
 static int __init s5p64x0_gpiolib_init(void)
 {
-	unsigned int chipid;
-
-	chipid = __raw_readl(S5P64X0_SYS_ID);
-
 	s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs,
 				ARRAY_SIZE(s5p64x0_gpio_cfgs));
 
-	if ((chipid & 0xff000) == 0x50000) {
+	if (soc_is_s5p6450()) {
 		samsung_gpiolib_add_2bit_chips(s5p6450_gpio_2bit,
 					ARRAY_SIZE(s5p6450_gpio_2bit));
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/clkdev.h linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/clkdev.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/clkdev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef __MACH_CLKDEV_H__
-#define __MACH_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do {} while (0)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
 
 #include <plat/regs-serial.h>
 
-	.macro addruart, rp, rv
+	.macro addruart, rp, rv, tmp
 		mov	\rp, #0xE0000000
 		orr	\rp, \rp, #0x00100000
 		ldr	\rp, [\rp, #0x118 ]
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/dma.h linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/dma.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
 #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>
+/* This platform uses the common common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,11 +13,6 @@
 #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
-
 /* GPIO bank sizes */
 
 #define S5P6440_GPIO_A_NR	(6)
@@ -134,6 +129,4 @@
 
 #define ARCH_NR_GPIOS		(S5P64X0_GPIO_END + CONFIG_SAMSUNG_GPIO_EXTRA)
 
-#include <asm-generic/gpio.h>
-
 #endif /* __ASM_ARCH_GPIO_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/irqs.h linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/irqs.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -87,6 +87,10 @@
 
 #define IRQ_I2S0		IRQ_I2SV40
 
+#define IRQ_LCD_FIFO		IRQ_DISPCON0
+#define IRQ_LCD_VSYNC		IRQ_DISPCON1
+#define IRQ_LCD_SYSTEM		IRQ_DISPCON2
+
 /* S5P6450 EINT feature will be added */
 
 /*
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/map.h linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/map.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/map.h	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,8 @@
 
 #define S5P64X0_PA_HSMMC(x)	(0xED800000 + ((x) * 0x100000))
 
+#define S5P64X0_PA_FB		0xEE000000
+
 #define S5P64X0_PA_I2S		0xF2000000
 #define S5P6450_PA_I2S1		0xF2800000
 #define S5P6450_PA_I2S2		0xF2900000
@@ -64,6 +66,7 @@
 #define S3C_PA_IIC1		S5P6440_PA_IIC1
 #define S3C_PA_RTC		S5P64X0_PA_RTC
 #define S3C_PA_WDT		S5P64X0_PA_WDT
+#define S3C_PA_FB		S5P64X0_PA_FB
 
 #define S5P_PA_CHIPID		S5P64X0_PA_CHIPID
 #define S5P_PA_SROMC		S5P64X0_PA_SROMC
@@ -85,5 +88,6 @@
 #define S5P_PA_UART5		S5P6450_PA_UART(5)
 
 #define S5P_SZ_UART		SZ_256
+#define S3C_VA_UARTx(x)		(S3C_VA_UART + ((x) * S3C_UART_OFFSET))
 
 #endif /* __ASM_ARCH_MAP_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/memory.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P64X0 - 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(0x20000000)
-#define CONSISTENT_DMA_SIZE	SZ_8M
-
-#endif /* __ASM_ARCH_MEMORY_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/pm-core.h linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/pm-core.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/pm-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/pm-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,117 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/pm-core.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - PM core support for arch/arm/plat-samsung/pm.c
+ *
+ * Based on PM core support for S3C64XX 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.
+ */
+
+#include <mach/regs-gpio.h>
+
+static inline void s3c_pm_debug_init_uart(void)
+{
+	u32 tmp = __raw_readl(S5P64X0_CLK_GATE_PCLK);
+
+	/*
+	 * As a note, since the S5P64X0 UARTs generally have multiple
+	 * clock sources, we simply enable PCLK at the moment and hope
+	 * that the resume settings for the UART are suitable for the
+	 * use with PCLK.
+	 */
+	tmp |= S5P64X0_CLK_GATE_PCLK_UART0;
+	tmp |= S5P64X0_CLK_GATE_PCLK_UART1;
+	tmp |= S5P64X0_CLK_GATE_PCLK_UART2;
+	tmp |= S5P64X0_CLK_GATE_PCLK_UART3;
+
+	__raw_writel(tmp, S5P64X0_CLK_GATE_PCLK);
+	udelay(10);
+}
+
+static inline void s3c_pm_arch_prepare_irqs(void)
+{
+	/* VIC should have already been taken care of */
+
+	/* clear any pending EINT0 interrupts */
+	__raw_writel(__raw_readl(S5P64X0_EINT0PEND), S5P64X0_EINT0PEND);
+}
+
+static inline void s3c_pm_arch_stop_clocks(void) { }
+static inline void s3c_pm_arch_show_resume_irqs(void) { }
+
+/*
+ * make these defines, we currently do not have any need to change
+ * the IRQ wake controls depending on the CPU we are running on
+ */
+#define s3c_irqwake_eintallow	((1 << 16) - 1)
+#define s3c_irqwake_intallow	(~0)
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+					struct pm_uart_save *save)
+{
+	u32 ucon = __raw_readl(regs + S3C2410_UCON);
+	u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK;
+	u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK;
+	u32 new_ucon;
+	u32 delta;
+
+	/*
+	 * S5P64X0 UART blocks only support level interrupts, so ensure that
+	 * when we restore unused UART blocks we force the level interrupt
+	 * settings.
+	 */
+	save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL;
+
+	/*
+	 * We have a constraint on changing the clock type of the UART
+	 * between UCLKx and PCLK, so ensure that when we restore UCON
+	 * that the CLK field is correctly modified if the bootloader
+	 * has changed anything.
+	 */
+	if (ucon_clk != save_clk) {
+		new_ucon = save->ucon;
+		delta = ucon_clk ^ save_clk;
+
+		/*
+		 * change from UCLKx => wrong PCLK,
+		 * either UCLK can be tested for by a bit-test
+		 * with UCLK0
+		 */
+		if (ucon_clk & S3C6400_UCON_UCLK0 &&
+		!(save_clk & S3C6400_UCON_UCLK0) &&
+		delta & S3C6400_UCON_PCLK2) {
+			new_ucon &= ~S3C6400_UCON_UCLK0;
+		} else if (delta == S3C6400_UCON_PCLK2) {
+			/*
+			 * as a precaution, don't change from
+			 * PCLK2 => PCLK or vice-versa
+			 */
+			new_ucon ^= S3C6400_UCON_PCLK2;
+		}
+
+		S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n",
+			ucon, new_ucon, save->ucon);
+		save->ucon = new_ucon;
+	}
+}
+
+static inline void s3c_pm_restored_gpios(void)
+{
+	/* ensure sleep mode has been cleared from the system */
+	__raw_writel(0, S5P64X0_SLPEN);
+}
+
+static inline void samsung_pm_saved_gpios(void)
+{
+	/*
+	 * turn on the sleep mode and keep it there, as it seems that during
+	 * suspend the xCON registers get re-set and thus you can end up with
+	 * problems between going to sleep and resuming.
+	 */
+	__raw_writel(S5P64X0_SLPEN_USE_xSLP, S5P64X0_SLPEN);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h
- *
- * Copyright (c) 2009-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/
- *
- * S5P64X0 - 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 0;
-}
-
-/**
- * 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 0
-
-#endif /* __ASM_ARCH_PWMCLK_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/regs-clock.h linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/regs-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/regs-clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -41,17 +41,50 @@
 #define S5P6450_DPLL_CON		S5P_CLKREG(0x50)
 #define S5P6450_DPLL_CON_K		S5P_CLKREG(0x54)
 
+#define S5P64X0_AHB_CON0		S5P_CLKREG(0x100)
 #define S5P64X0_CLK_SRC1		S5P_CLKREG(0x10C)
 
 #define S5P64X0_SYS_ID			S5P_CLKREG(0x118)
 #define S5P64X0_SYS_OTHERS		S5P_CLKREG(0x11C)
 
 #define S5P64X0_PWR_CFG			S5P_CLKREG(0x804)
+#define S5P64X0_EINT_WAKEUP_MASK	S5P_CLKREG(0x808)
+#define S5P64X0_SLEEP_CFG		S5P_CLKREG(0x818)
+#define S5P64X0_PWR_STABLE		S5P_CLKREG(0x828)
+
 #define S5P64X0_OTHERS			S5P_CLKREG(0x900)
+#define S5P64X0_WAKEUP_STAT		S5P_CLKREG(0x908)
+
+#define S5P64X0_INFORM0			S5P_CLKREG(0xA00)
 
 #define S5P64X0_CLKDIV0_HCLK_SHIFT	(8)
 #define S5P64X0_CLKDIV0_HCLK_MASK	(0xF << S5P64X0_CLKDIV0_HCLK_SHIFT)
 
+/* HCLK GATE Registers */
+#define S5P64X0_CLK_GATE_HCLK1_FIMGVG	(1 << 2)
+#define S5P64X0_CLK_GATE_SCLK1_FIMGVG	(1 << 2)
+
+/* PCLK GATE Registers */
+#define S5P64X0_CLK_GATE_PCLK_UART3	(1 << 4)
+#define S5P64X0_CLK_GATE_PCLK_UART2	(1 << 3)
+#define S5P64X0_CLK_GATE_PCLK_UART1	(1 << 2)
+#define S5P64X0_CLK_GATE_PCLK_UART0	(1 << 1)
+
+#define S5P64X0_PWR_CFG_MMC1_DISABLE		(1 << 15)
+#define S5P64X0_PWR_CFG_MMC0_DISABLE		(1 << 14)
+#define S5P64X0_PWR_CFG_RTC_TICK_DISABLE	(1 << 11)
+#define S5P64X0_PWR_CFG_RTC_ALRM_DISABLE	(1 << 10)
+#define S5P64X0_PWR_CFG_WFI_MASK		(3 << 5)
+#define S5P64X0_PWR_CFG_WFI_SLEEP		(3 << 5)
+
+#define S5P64X0_SLEEP_CFG_OSC_EN	(1 << 0)
+
+#define S5P64X0_PWR_STABLE_PWR_CNT_VAL4	(4 << 0)
+
+#define S5P6450_OTHERS_DISABLE_INT	(1 << 31)
+#define S5P64X0_OTHERS_RET_UART		(1 << 26)
+#define S5P64X0_OTHERS_RET_MMC1		(1 << 25)
+#define S5P64X0_OTHERS_RET_MMC0		(1 << 24)
 #define S5P64X0_OTHERS_USB_SIG_MASK	(1 << 16)
 
 /* Compatibility defines */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -34,14 +34,35 @@
 #define S5P6450_GPQ_BASE		(S5P_VA_GPIO + 0x0180)
 #define S5P6450_GPS_BASE		(S5P_VA_GPIO + 0x0300)
 
+#define S5P64X0_SPCON0			(S5P_VA_GPIO + 0x1A0)
+#define S5P64X0_SPCON0_LCD_SEL_MASK	(0x3 << 0)
+#define S5P64X0_SPCON0_LCD_SEL_RGB	(0x1 << 0)
+#define S5P64X0_SPCON1			(S5P_VA_GPIO + 0x2B0)
+
+#define S5P64X0_MEM0CONSLP0		(S5P_VA_GPIO + 0x1C0)
+#define S5P64X0_MEM0CONSLP1		(S5P_VA_GPIO + 0x1C4)
+#define S5P64X0_MEM0DRVCON		(S5P_VA_GPIO + 0x1D0)
+#define S5P64X0_MEM1DRVCON		(S5P_VA_GPIO + 0x1D4)
+
+#define S5P64X0_EINT12CON		(S5P_VA_GPIO + 0x200)
+#define S5P64X0_EINT12FLTCON		(S5P_VA_GPIO + 0x220)
+#define S5P64X0_EINT12MASK		(S5P_VA_GPIO + 0x240)
+
 /* External interrupt control registers for group0 */
 
 #define EINT0CON0_OFFSET		(0x900)
+#define EINT0FLTCON0_OFFSET		(0x910)
+#define EINT0FLTCON1_OFFSET		(0x914)
 #define EINT0MASK_OFFSET		(0x920)
 #define EINT0PEND_OFFSET		(0x924)
 
 #define S5P64X0_EINT0CON0		(S5P_VA_GPIO + EINT0CON0_OFFSET)
+#define S5P64X0_EINT0FLTCON0		(S5P_VA_GPIO + EINT0FLTCON0_OFFSET)
+#define S5P64X0_EINT0FLTCON1		(S5P_VA_GPIO + EINT0FLTCON1_OFFSET)
 #define S5P64X0_EINT0MASK		(S5P_VA_GPIO + EINT0MASK_OFFSET)
 #define S5P64X0_EINT0PEND		(S5P_VA_GPIO + EINT0PEND_OFFSET)
 
+#define S5P64X0_SLPEN			(S5P_VA_GPIO + 0x930)
+#define S5P64X0_SLPEN_USE_xSLP		(1 << 0)
+
 #endif /* __ASM_ARCH_REGS_GPIO_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/irq-eint.c linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/irq-eint.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/irq-eint.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/irq-eint.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,8 +17,10 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 
+#include <plat/cpu.h>
 #include <plat/regs-irqtype.h>
 #include <plat/gpio-cfg.h>
+#include <plat/pm.h>
 
 #include <mach/regs-gpio.h>
 #include <mach/regs-clock.h>
@@ -67,7 +69,7 @@
 	__raw_writel(ctrl, S5P64X0_EINT0CON0);
 
 	/* Configure the GPIO pin for 6450 or 6440 based on CPU ID */
-	if (0x50000 == (__raw_readl(S5P64X0_SYS_ID) & 0xFF000))
+	if (soc_is_s5p6450())
 		s3c_gpio_cfgpin(S5P6450_GPN(offs), S3C_GPIO_SFN(2));
 	else
 		s3c_gpio_cfgpin(S5P6440_GPN(offs), S3C_GPIO_SFN(2));
@@ -133,6 +135,7 @@
 	ct->chip.irq_mask = irq_gc_mask_set_bit;
 	ct->chip.irq_unmask = irq_gc_mask_clr_bit;
 	ct->chip.irq_set_type = s5p64x0_irq_eint_set_type;
+	ct->chip.irq_set_wake = s3c_irqext_wake;
 	ct->regs.ack = EINT0PEND_OFFSET;
 	ct->regs.mask = EINT0MASK_OFFSET;
 	irq_setup_generic_chip(gc, IRQ_MSK(16), IRQ_GC_INIT_MASK_CACHE,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/irq-pm.c linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/irq-pm.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/irq-pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/irq-pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,92 @@
+/* linux/arch/arm/mach-s5p64x0/irq-pm.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - Interrupt handling Power Management
+ *
+ * Based on arch/arm/mach-s3c64xx/irq-pm.c 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.
+ */
+
+#include <linux/syscore_ops.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+
+#include <plat/regs-serial.h>
+#include <plat/pm.h>
+
+#include <mach/regs-gpio.h>
+
+static struct sleep_save irq_save[] = {
+	SAVE_ITEM(S5P64X0_EINT0CON0),
+	SAVE_ITEM(S5P64X0_EINT0FLTCON0),
+	SAVE_ITEM(S5P64X0_EINT0FLTCON1),
+	SAVE_ITEM(S5P64X0_EINT0MASK),
+};
+
+static struct irq_grp_save {
+	u32	con;
+	u32	fltcon;
+	u32	mask;
+} eint_grp_save[4];
+
+static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS];
+
+static int s5p64x0_irq_pm_suspend(void)
+{
+	struct irq_grp_save *grp = eint_grp_save;
+	int i;
+
+	S3C_PMDBG("%s: suspending IRQs\n", __func__);
+
+	s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+
+	for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
+		irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM);
+
+	for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
+		grp->con = __raw_readl(S5P64X0_EINT12CON + (i * 4));
+		grp->mask = __raw_readl(S5P64X0_EINT12MASK + (i * 4));
+		grp->fltcon = __raw_readl(S5P64X0_EINT12FLTCON + (i * 4));
+	}
+
+	return 0;
+}
+
+static void s5p64x0_irq_pm_resume(void)
+{
+	struct irq_grp_save *grp = eint_grp_save;
+	int i;
+
+	S3C_PMDBG("%s: resuming IRQs\n", __func__);
+
+	s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+
+	for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
+		__raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM);
+
+	for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
+		__raw_writel(grp->con, S5P64X0_EINT12CON + (i * 4));
+		__raw_writel(grp->mask, S5P64X0_EINT12MASK + (i * 4));
+		__raw_writel(grp->fltcon, S5P64X0_EINT12FLTCON + (i * 4));
+	}
+
+	S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
+}
+
+static struct syscore_ops s5p64x0_irq_syscore_ops = {
+	.suspend = s5p64x0_irq_pm_suspend,
+	.resume  = s5p64x0_irq_pm_resume,
+};
+
+static int __init s5p64x0_syscore_init(void)
+{
+	register_syscore_ops(&s5p64x0_irq_syscore_ops);
+
+	return 0;
+}
+core_initcall(s5p64x0_syscore_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/Kconfig linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -9,18 +9,28 @@
 
 config CPU_S5P6440
 	bool
-	select S3C_PL330_DMA
+	select SAMSUNG_DMADEV
 	select S5P_HRT
+	select S5P_SLEEP if PM
+	select SAMSUNG_WAKEMASK if PM
 	help
 	  Enable S5P6440 CPU support
 
 config CPU_S5P6450
 	bool
-	select S3C_PL330_DMA
+	select SAMSUNG_DMADEV
 	select S5P_HRT
+	select S5P_SLEEP if PM
+	select SAMSUNG_WAKEMASK if PM
 	help
 	  Enable S5P6450 CPU support
 
+config S5P64X0_SETUP_FB_24BPP
+	bool
+	help
+	  Common setup code for S5P64X0 based boards with a LCD display
+	  through RGB interface.
+
 config S5P64X0_SETUP_I2C1
 	bool
 	help
@@ -31,6 +41,7 @@
 config MACH_SMDK6440
 	bool "SMDK6440"
 	select CPU_S5P6440
+	select S3C_DEV_FB
 	select S3C_DEV_I2C1
 	select S3C_DEV_RTC
 	select S3C_DEV_WDT
@@ -39,6 +50,7 @@
 	select SAMSUNG_DEV_BACKLIGHT
 	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_TS
+	select S5P64X0_SETUP_FB_24BPP
 	select S5P64X0_SETUP_I2C1
 	help
 	  Machine support for the Samsung SMDK6440
@@ -46,6 +58,7 @@
 config MACH_SMDK6450
 	bool "SMDK6450"
 	select CPU_S5P6450
+	select S3C_DEV_FB
 	select S3C_DEV_I2C1
 	select S3C_DEV_RTC
 	select S3C_DEV_WDT
@@ -54,6 +67,7 @@
 	select SAMSUNG_DEV_BACKLIGHT
 	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_TS
+	select S5P64X0_SETUP_FB_24BPP
 	select S5P64X0_SETUP_I2C1
 	help
 	  Machine support for the Samsung SMDK6450
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/mach-smdk6440.c linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/mach-smdk6440.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/mach-smdk6440.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/mach-smdk6440.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,9 @@
 #include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/pwm_backlight.h>
+#include <linux/fb.h>
+
+#include <video/platform_lcd.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -47,6 +50,8 @@
 #include <plat/ts.h>
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
+#include <plat/fb.h>
+#include <plat/regs-fb.h>
 
 #define SMDK6440_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
 				S3C2410_UCON_RXILEVEL |		\
@@ -92,6 +97,59 @@
 	},
 };
 
+/* Frame Buffer */
+static struct s3c_fb_pd_win smdk6440_fb_win0 = {
+	.win_mode = {
+		.left_margin	= 8,
+		.right_margin	= 13,
+		.upper_margin	= 7,
+		.lower_margin	= 5,
+		.hsync_len	= 3,
+		.vsync_len	= 1,
+		.xres		= 800,
+		.yres		= 480,
+	},
+	.max_bpp	= 32,
+	.default_bpp	= 24,
+};
+
+static struct s3c_fb_platdata smdk6440_lcd_pdata __initdata = {
+	.win[0]		= &smdk6440_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+	.setup_gpio	= s5p64x0_fb_gpio_setup_24bpp,
+};
+
+/* LCD power controller */
+static void smdk6440_lte480_reset_power(struct plat_lcd_data *pd,
+					 unsigned int power)
+{
+	int err;
+
+	if (power) {
+		err = gpio_request(S5P6440_GPN(5), "GPN");
+		if (err) {
+			printk(KERN_ERR "failed to request GPN for lcd reset\n");
+			return;
+		}
+
+		gpio_direction_output(S5P6440_GPN(5), 1);
+		gpio_set_value(S5P6440_GPN(5), 0);
+		gpio_set_value(S5P6440_GPN(5), 1);
+		gpio_free(S5P6440_GPN(5));
+	}
+}
+
+static struct plat_lcd_data smdk6440_lcd_power_data = {
+	.set_power	= smdk6440_lte480_reset_power,
+};
+
+static struct platform_device smdk6440_lcd_lte480wv = {
+	.name			= "platform-lcd",
+	.dev.parent		= &s3c_device_fb.dev,
+	.dev.platform_data	= &smdk6440_lcd_power_data,
+};
+
 static struct platform_device *smdk6440_devices[] __initdata = {
 	&s3c_device_adc,
 	&s3c_device_rtc,
@@ -101,6 +159,8 @@
 	&s3c_device_wdt,
 	&samsung_asoc_dma,
 	&s5p6440_device_iis,
+	&s3c_device_fb,
+	&smdk6440_lcd_lte480wv,
 };
 
 static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = {
@@ -129,12 +189,6 @@
 	/* To be populated */
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 /* LCD Backlight data */
 static struct samsung_bl_gpio_info smdk6440_bl_gpio_info = {
 	.no = S5P6440_GPF(15),
@@ -153,9 +207,20 @@
 	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
+static void s5p6440_set_lcd_interface(void)
+{
+	unsigned int cfg;
+
+	/* select TFT LCD type (RGB I/F) */
+	cfg = __raw_readl(S5P64X0_SPCON0);
+	cfg &= ~S5P64X0_SPCON0_LCD_SEL_MASK;
+	cfg |= S5P64X0_SPCON0_LCD_SEL_RGB;
+	__raw_writel(cfg, S5P64X0_SPCON0);
+}
+
 static void __init smdk6440_machine_init(void)
 {
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	s3c_i2c0_set_platdata(&s5p6440_i2c0_data);
 	s3c_i2c1_set_platdata(&s5p6440_i2c1_data);
@@ -166,12 +231,15 @@
 
 	samsung_bl_set(&smdk6440_bl_gpio_info, &smdk6440_bl_data);
 
+	s5p6440_set_lcd_interface();
+	s3c_fb_set_platdata(&smdk6440_lcd_pdata);
+
 	platform_add_devices(smdk6440_devices, ARRAY_SIZE(smdk6440_devices));
 }
 
 MACHINE_START(SMDK6440, "SMDK6440")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.boot_params	= S5P64X0_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s5p6440_init_irq,
 	.map_io		= smdk6440_map_io,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/mach-smdk6450.c linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/mach-smdk6450.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/mach-smdk6450.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/mach-smdk6450.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,9 @@
 #include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/pwm_backlight.h>
+#include <linux/fb.h>
+
+#include <video/platform_lcd.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -47,6 +50,8 @@
 #include <plat/ts.h>
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
+#include <plat/fb.h>
+#include <plat/regs-fb.h>
 
 #define SMDK6450_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
 				S3C2410_UCON_RXILEVEL |		\
@@ -110,6 +115,59 @@
 #endif
 };
 
+/* Frame Buffer */
+static struct s3c_fb_pd_win smdk6450_fb_win0 = {
+	.win_mode	= {
+		.left_margin	= 8,
+		.right_margin	= 13,
+		.upper_margin	= 7,
+		.lower_margin	= 5,
+		.hsync_len	= 3,
+		.vsync_len	= 1,
+		.xres		= 800,
+		.yres		= 480,
+	},
+	.max_bpp	= 32,
+	.default_bpp	= 24,
+};
+
+static struct s3c_fb_platdata smdk6450_lcd_pdata __initdata = {
+	.win[0]		= &smdk6450_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+	.setup_gpio	= s5p64x0_fb_gpio_setup_24bpp,
+};
+
+/* LCD power controller */
+static void smdk6450_lte480_reset_power(struct plat_lcd_data *pd,
+					 unsigned int power)
+{
+	int err;
+
+	if (power) {
+		err = gpio_request(S5P6450_GPN(5), "GPN");
+		if (err) {
+			printk(KERN_ERR "failed to request GPN for lcd reset\n");
+			return;
+		}
+
+		gpio_direction_output(S5P6450_GPN(5), 1);
+		gpio_set_value(S5P6450_GPN(5), 0);
+		gpio_set_value(S5P6450_GPN(5), 1);
+		gpio_free(S5P6450_GPN(5));
+	}
+}
+
+static struct plat_lcd_data smdk6450_lcd_power_data = {
+	.set_power	= smdk6450_lte480_reset_power,
+};
+
+static struct platform_device smdk6450_lcd_lte480wv = {
+	.name			= "platform-lcd",
+	.dev.parent		= &s3c_device_fb.dev,
+	.dev.platform_data	= &smdk6450_lcd_power_data,
+};
+
 static struct platform_device *smdk6450_devices[] __initdata = {
 	&s3c_device_adc,
 	&s3c_device_rtc,
@@ -119,6 +177,9 @@
 	&s3c_device_wdt,
 	&samsung_asoc_dma,
 	&s5p6450_device_iis0,
+	&s3c_device_fb,
+	&smdk6450_lcd_lte480wv,
+
 	/* s5p6450_device_spi0 will be added */
 };
 
@@ -148,12 +209,6 @@
 	{ I2C_BOARD_INFO("24c128", 0x57), },/* Samsung S524AD0XD1 EEPROM */
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 /* LCD Backlight data */
 static struct samsung_bl_gpio_info smdk6450_bl_gpio_info = {
 	.no = S5P6450_GPF(15),
@@ -172,9 +227,20 @@
 	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
+static void s5p6450_set_lcd_interface(void)
+{
+	unsigned int cfg;
+
+	/* select TFT LCD type (RGB I/F) */
+	cfg = __raw_readl(S5P64X0_SPCON0);
+	cfg &= ~S5P64X0_SPCON0_LCD_SEL_MASK;
+	cfg |= S5P64X0_SPCON0_LCD_SEL_RGB;
+	__raw_writel(cfg, S5P64X0_SPCON0);
+}
+
 static void __init smdk6450_machine_init(void)
 {
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	s3c_i2c0_set_platdata(&s5p6450_i2c0_data);
 	s3c_i2c1_set_platdata(&s5p6450_i2c1_data);
@@ -185,12 +251,15 @@
 
 	samsung_bl_set(&smdk6450_bl_gpio_info, &smdk6450_bl_data);
 
+	s5p6450_set_lcd_interface();
+	s3c_fb_set_platdata(&smdk6450_lcd_pdata);
+
 	platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices));
 }
 
 MACHINE_START(SMDK6450, "SMDK6450")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.boot_params	= S5P64X0_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 
 	.init_irq	= s5p6450_init_irq,
 	.map_io		= smdk6450_map_io,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/Makefile linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -12,10 +12,11 @@
 
 # Core support for S5P64X0 system
 
-obj-$(CONFIG_ARCH_S5P64X0)	+= cpu.o init.o clock.o dma.o gpiolib.o
+obj-$(CONFIG_ARCH_S5P64X0)	+= cpu.o init.o clock.o dma.o
 obj-$(CONFIG_ARCH_S5P64X0)	+= setup-i2c0.o irq-eint.o
 obj-$(CONFIG_CPU_S5P6440)	+= clock-s5p6440.o
 obj-$(CONFIG_CPU_S5P6450)	+= clock-s5p6450.o
+obj-$(CONFIG_PM)		+= pm.o irq-pm.o
 
 # machine support
 
@@ -28,3 +29,4 @@
 obj-$(CONFIG_S3C64XX_DEV_SPI)	+= dev-spi.o
 
 obj-$(CONFIG_S5P64X0_SETUP_I2C1)	+= setup-i2c1.o
+obj-$(CONFIG_S5P64X0_SETUP_FB_24BPP)	+= setup-fb-24bpp.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-   zreladdr-y	:= 0x20008000
+   zreladdr-y	+= 0x20008000
 params_phys-y	:= 0x20000100
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/pm.c linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/pm.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,204 @@
+/* linux/arch/arm/mach-s5p64x0/pm.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 Power Management Support
+ *
+ * Based on arch/arm/mach-s3c64xx/pm.c 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.
+*/
+
+#include <linux/suspend.h>
+#include <linux/syscore_ops.h>
+#include <linux/io.h>
+
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/regs-timer.h>
+#include <plat/wakeup-mask.h>
+
+#include <mach/regs-clock.h>
+#include <mach/regs-gpio.h>
+
+static struct sleep_save s5p64x0_core_save[] = {
+	SAVE_ITEM(S5P64X0_APLL_CON),
+	SAVE_ITEM(S5P64X0_MPLL_CON),
+	SAVE_ITEM(S5P64X0_EPLL_CON),
+	SAVE_ITEM(S5P64X0_EPLL_CON_K),
+	SAVE_ITEM(S5P64X0_CLK_SRC0),
+	SAVE_ITEM(S5P64X0_CLK_SRC1),
+	SAVE_ITEM(S5P64X0_CLK_DIV0),
+	SAVE_ITEM(S5P64X0_CLK_DIV1),
+	SAVE_ITEM(S5P64X0_CLK_DIV2),
+	SAVE_ITEM(S5P64X0_CLK_DIV3),
+	SAVE_ITEM(S5P64X0_CLK_GATE_MEM0),
+	SAVE_ITEM(S5P64X0_CLK_GATE_HCLK1),
+	SAVE_ITEM(S5P64X0_CLK_GATE_SCLK1),
+};
+
+static struct sleep_save s5p64x0_misc_save[] = {
+	SAVE_ITEM(S5P64X0_AHB_CON0),
+	SAVE_ITEM(S5P64X0_SPCON0),
+	SAVE_ITEM(S5P64X0_SPCON1),
+	SAVE_ITEM(S5P64X0_MEM0CONSLP0),
+	SAVE_ITEM(S5P64X0_MEM0CONSLP1),
+	SAVE_ITEM(S5P64X0_MEM0DRVCON),
+	SAVE_ITEM(S5P64X0_MEM1DRVCON),
+
+	SAVE_ITEM(S3C64XX_TINT_CSTAT),
+};
+
+/* DPLL is present only in S5P6450 */
+static struct sleep_save s5p6450_core_save[] = {
+	SAVE_ITEM(S5P6450_DPLL_CON),
+	SAVE_ITEM(S5P6450_DPLL_CON_K),
+};
+
+void s3c_pm_configure_extint(void)
+{
+	__raw_writel(s3c_irqwake_eintmask, S5P64X0_EINT_WAKEUP_MASK);
+}
+
+void s3c_pm_restore_core(void)
+{
+	__raw_writel(0, S5P64X0_EINT_WAKEUP_MASK);
+
+	s3c_pm_do_restore_core(s5p64x0_core_save,
+				ARRAY_SIZE(s5p64x0_core_save));
+
+	if (soc_is_s5p6450())
+		s3c_pm_do_restore_core(s5p6450_core_save,
+				ARRAY_SIZE(s5p6450_core_save));
+
+	s3c_pm_do_restore(s5p64x0_misc_save, ARRAY_SIZE(s5p64x0_misc_save));
+}
+
+void s3c_pm_save_core(void)
+{
+	s3c_pm_do_save(s5p64x0_misc_save, ARRAY_SIZE(s5p64x0_misc_save));
+
+	if (soc_is_s5p6450())
+		s3c_pm_do_save(s5p6450_core_save,
+				ARRAY_SIZE(s5p6450_core_save));
+
+	s3c_pm_do_save(s5p64x0_core_save, ARRAY_SIZE(s5p64x0_core_save));
+}
+
+static int s5p64x0_cpu_suspend(unsigned long arg)
+{
+	unsigned long tmp = 0;
+
+	/*
+	 * Issue the standby signal into the pm unit. Note, we
+	 * issue a write-buffer drain just in case.
+	 */
+	asm("b 1f\n\t"
+	    ".align 5\n\t"
+	    "1:\n\t"
+	    "mcr p15, 0, %0, c7, c10, 5\n\t"
+	    "mcr p15, 0, %0, c7, c10, 4\n\t"
+	    "mcr p15, 0, %0, c7, c0, 4" : : "r" (tmp));
+
+	/* we should never get past here */
+	panic("sleep resumed to originator?");
+}
+
+/* mapping of interrupts to parts of the wakeup mask */
+static struct samsung_wakeup_mask s5p64x0_wake_irqs[] = {
+	{ .irq = IRQ_RTC_ALARM,	.bit = S5P64X0_PWR_CFG_RTC_ALRM_DISABLE, },
+	{ .irq = IRQ_RTC_TIC,	.bit = S5P64X0_PWR_CFG_RTC_TICK_DISABLE, },
+	{ .irq = IRQ_HSMMC0,	.bit = S5P64X0_PWR_CFG_MMC0_DISABLE, },
+	{ .irq = IRQ_HSMMC1,	.bit = S5P64X0_PWR_CFG_MMC1_DISABLE, },
+};
+
+static void s5p64x0_pm_prepare(void)
+{
+	u32 tmp;
+
+	samsung_sync_wakemask(S5P64X0_PWR_CFG,
+			s5p64x0_wake_irqs, ARRAY_SIZE(s5p64x0_wake_irqs));
+
+	/* store the resume address in INFORM0 register */
+	__raw_writel(virt_to_phys(s3c_cpu_resume), S5P64X0_INFORM0);
+
+	/* setup clock gating for FIMGVG block */
+	__raw_writel((__raw_readl(S5P64X0_CLK_GATE_HCLK1) | \
+		(S5P64X0_CLK_GATE_HCLK1_FIMGVG)), S5P64X0_CLK_GATE_HCLK1);
+	__raw_writel((__raw_readl(S5P64X0_CLK_GATE_SCLK1) | \
+		(S5P64X0_CLK_GATE_SCLK1_FIMGVG)), S5P64X0_CLK_GATE_SCLK1);
+
+	/* Configure the stabilization counter with wait time required */
+	__raw_writel(S5P64X0_PWR_STABLE_PWR_CNT_VAL4, S5P64X0_PWR_STABLE);
+
+	/* set WFI to SLEEP mode configuration */
+	tmp = __raw_readl(S5P64X0_SLEEP_CFG);
+	tmp &= ~(S5P64X0_SLEEP_CFG_OSC_EN);
+	__raw_writel(tmp, S5P64X0_SLEEP_CFG);
+
+	tmp = __raw_readl(S5P64X0_PWR_CFG);
+	tmp &= ~(S5P64X0_PWR_CFG_WFI_MASK);
+	tmp |= S5P64X0_PWR_CFG_WFI_SLEEP;
+	__raw_writel(tmp, S5P64X0_PWR_CFG);
+
+	/*
+	 * set OTHERS register to disable interrupt before going to
+	 * sleep. This bit is present only in S5P6450, it is reserved
+	 * in S5P6440.
+	 */
+	if (soc_is_s5p6450()) {
+		tmp = __raw_readl(S5P64X0_OTHERS);
+		tmp |= S5P6450_OTHERS_DISABLE_INT;
+		__raw_writel(tmp, S5P64X0_OTHERS);
+	}
+
+	/* ensure previous wakeup state is cleared before sleeping */
+	__raw_writel(__raw_readl(S5P64X0_WAKEUP_STAT), S5P64X0_WAKEUP_STAT);
+
+}
+
+static int s5p64x0_pm_add(struct sys_device *sysdev)
+{
+	pm_cpu_prep = s5p64x0_pm_prepare;
+	pm_cpu_sleep = s5p64x0_cpu_suspend;
+	pm_uart_udivslot = 1;
+
+	return 0;
+}
+
+static struct sysdev_driver s5p64x0_pm_driver = {
+	.add		= s5p64x0_pm_add,
+};
+
+static __init int s5p64x0_pm_drvinit(void)
+{
+	s3c_pm_init();
+
+	return sysdev_driver_register(&s5p64x0_sysclass, &s5p64x0_pm_driver);
+}
+arch_initcall(s5p64x0_pm_drvinit);
+
+static void s5p64x0_pm_resume(void)
+{
+	u32 tmp;
+
+	tmp = __raw_readl(S5P64X0_OTHERS);
+	tmp |= (S5P64X0_OTHERS_RET_MMC0 | S5P64X0_OTHERS_RET_MMC1 | \
+			S5P64X0_OTHERS_RET_UART);
+	__raw_writel(tmp , S5P64X0_OTHERS);
+}
+
+static struct syscore_ops s5p64x0_pm_syscore_ops = {
+	.resume		= s5p64x0_pm_resume,
+};
+
+static __init int s5p64x0_pm_syscore_init(void)
+{
+	register_syscore_ops(&s5p64x0_pm_syscore_ops);
+
+	return 0;
+}
+arch_initcall(s5p64x0_pm_syscore_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/setup-fb-24bpp.c linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5p64x0/setup-fb-24bpp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-s5p64x0/setup-fb-24bpp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/* linux/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Base S5P64X0 GPIO setup information for LCD framebuffer
+ *
+ * This program is free software; you can 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/fb.h>
+#include <linux/gpio.h>
+
+#include <plat/cpu.h>
+#include <plat/fb.h>
+#include <plat/gpio-cfg.h>
+
+void s5p64x0_fb_gpio_setup_24bpp(void)
+{
+	if (soc_is_s5p6440()) {
+		s3c_gpio_cfgrange_nopull(S5P6440_GPI(0), 16, S3C_GPIO_SFN(2));
+		s3c_gpio_cfgrange_nopull(S5P6440_GPJ(0), 12, S3C_GPIO_SFN(2));
+	} else if (soc_is_s5p6450()) {
+		s3c_gpio_cfgrange_nopull(S5P6450_GPI(0), 16, S3C_GPIO_SFN(2));
+		s3c_gpio_cfgrange_nopull(S5P6450_GPJ(0), 12, S3C_GPIO_SFN(2));
+	}
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pc100/clock.c linux-libre-3.2-gnu/arch/arm/mach-s5pc100/clock.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5pc100/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pc100/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,11 @@
 	.name		= "otg_phy",
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 static struct clk *clk_src_mout_href_list[] = {
 	[0] = &s5p_clk_27m,
 	[1] = &clk_fin_hpll,
@@ -454,14 +459,14 @@
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
-		.name		= "pdma",
-		.devname	= "s3c-pl330.1",
+		.name		= "dma",
+		.devname	= "dma-pl330.1",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
-		.name		= "pdma",
-		.devname	= "s3c-pl330.0",
+		.name		= "dma",
+		.devname	= "dma-pl330.0",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 0),
@@ -1276,5 +1281,7 @@
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
+
 	s3c_pwmclk_init();
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pc100/dma.c linux-libre-3.2-gnu/arch/arm/mach-s5pc100/dma.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5pc100/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pc100/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,8 @@
-/*
+/* linux/arch/arm/mach-s5pc100/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>
  *
@@ -17,150 +21,246 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
 
+#include <asm/irq.h>
 #include <plat/devs.h>
+#include <plat/irqs.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
+#include <mach/dma.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5pc100_pdma0_resource[] = {
-	[0] = {
-		.start  = S5PC100_PA_PDMA0,
-		.end    = S5PC100_PA_PDMA0 + SZ_4K,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA0,
-		.end	= IRQ_PDMA0,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri pdma0_peri[30] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_IRDA,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_AC97_MICIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMOUT,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_EXTERNAL,
+	}, {
+		.peri_id = (u8)DMACH_PWM,
+	}, {
+		.peri_id = (u8)DMACH_SPDIF,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_HSI_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_HSI_TX,
+		.rqtype = MEMTODEV,
 	},
 };
 
-static struct s3c_pl330_platdata s5pc100_pdma0_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_IRDA,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S0S_TX,
-		[12] = DMACH_I2S1_RX,
-		[13] = DMACH_I2S1_TX,
-		[14] = DMACH_I2S2_RX,
-		[15] = DMACH_I2S2_TX,
-		[16] = DMACH_SPI0_RX,
-		[17] = DMACH_SPI0_TX,
-		[18] = DMACH_SPI1_RX,
-		[19] = DMACH_SPI1_TX,
-		[20] = DMACH_SPI2_RX,
-		[21] = DMACH_SPI2_TX,
-		[22] = DMACH_AC97_MICIN,
-		[23] = DMACH_AC97_PCMIN,
-		[24] = DMACH_AC97_PCMOUT,
-		[25] = DMACH_EXTERNAL,
-		[26] = DMACH_PWM,
-		[27] = DMACH_SPDIF,
-		[28] = DMACH_HSI_RX,
-		[29] = DMACH_HSI_TX,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata s5pc100_pdma0_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(pdma0_peri),
+	.peri = pdma0_peri,
 };
 
-static struct platform_device s5pc100_device_pdma0 = {
-	.name		= "s3c-pl330",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5pc100_pdma0_resource),
-	.resource	= s5pc100_pdma0_resource,
-	.dev		= {
+struct amba_device s5pc100_device_pdma0 = {
+	.dev = {
+		.init_name = "dma-pl330.0",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &s5pc100_pdma0_pdata,
 	},
-};
-
-static struct resource s5pc100_pdma1_resource[] = {
-	[0] = {
-		.start  = S5PC100_PA_PDMA1,
-		.end    = S5PC100_PA_PDMA1 + SZ_4K,
+	.res = {
+		.start = S5PC100_PA_PDMA0,
+		.end = S5PC100_PA_PDMA0 + SZ_4K,
 		.flags = IORESOURCE_MEM,
 	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
-	},
+	.irq = {IRQ_PDMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
-static struct s3c_pl330_platdata s5pc100_pdma1_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_IRDA,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S0S_TX,
-		[12] = DMACH_I2S1_RX,
-		[13] = DMACH_I2S1_TX,
-		[14] = DMACH_I2S2_RX,
-		[15] = DMACH_I2S2_TX,
-		[16] = DMACH_SPI0_RX,
-		[17] = DMACH_SPI0_TX,
-		[18] = DMACH_SPI1_RX,
-		[19] = DMACH_SPI1_TX,
-		[20] = DMACH_SPI2_RX,
-		[21] = DMACH_SPI2_TX,
-		[22] = DMACH_PCM0_RX,
-		[23] = DMACH_PCM0_TX,
-		[24] = DMACH_PCM1_RX,
-		[25] = DMACH_PCM1_TX,
-		[26] = DMACH_MSM_REQ0,
-		[27] = DMACH_MSM_REQ1,
-		[28] = DMACH_MSM_REQ2,
-		[29] = DMACH_MSM_REQ3,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
+struct dma_pl330_peri pdma1_peri[30] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_IRDA,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ0,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ1,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ2,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ3,
 	},
 };
 
-static struct platform_device s5pc100_device_pdma1 = {
-	.name		= "s3c-pl330",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5pc100_pdma1_resource),
-	.resource	= s5pc100_pdma1_resource,
-	.dev		= {
+struct dma_pl330_platdata s5pc100_pdma1_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
+	.peri = pdma1_peri,
+};
+
+struct amba_device s5pc100_device_pdma1 = {
+	.dev = {
+		.init_name = "dma-pl330.1",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &s5pc100_pdma1_pdata,
 	},
-};
-
-static struct platform_device *s5pc100_dmacs[] __initdata = {
-	&s5pc100_device_pdma0,
-	&s5pc100_device_pdma1,
+	.res = {
+		.start = S5PC100_PA_PDMA1,
+		.end = S5PC100_PA_PDMA1 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_PDMA1, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
 static int __init s5pc100_dma_init(void)
 {
-	platform_add_devices(s5pc100_dmacs, ARRAY_SIZE(s5pc100_dmacs));
+	amba_device_register(&s5pc100_device_pdma0, &iomem_resource);
+	amba_device_register(&s5pc100_device_pdma1, &iomem_resource);
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pc100/include/mach/clkdev.h linux-libre-3.2-gnu/arch/arm/mach-s5pc100/include/mach/clkdev.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5pc100/include/mach/clkdev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pc100/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef __MACH_CLKDEV_H__
-#define __MACH_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do {} while (0)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pc100/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-s5pc100/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-s5pc100/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pc100/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,7 @@
 	 * aligned and add in the offset when we load the value here.
 	 */
 
-	.macro addruart, rp, rv
+	.macro addruart, rp, rv, tmp
 		ldr	\rp, = S3C_PA_UART
 		ldr	\rv, = S3C_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pc100/include/mach/dma.h linux-libre-3.2-gnu/arch/arm/mach-s5pc100/include/mach/dma.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5pc100/include/mach/dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pc100/include/mach/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
 #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>
+/* This platform uses the common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pc100/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-s5pc100/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5pc100/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pc100/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,11 +15,6 @@
 #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
-
 /* GPIO bank sizes */
 #define S5PC100_GPIO_A0_NR	(8)
 #define S5PC100_GPIO_A1_NR	(5)
@@ -146,6 +141,4 @@
 /* define the number of gpios we need to the one after the MP04() range */
 #define ARCH_NR_GPIOS		(S5PC100_GPIO_END + 1)
 
-#include <asm-generic/gpio.h>
-
 #endif /* __ASM_ARCH_GPIO_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pc100/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-s5pc100/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5pc100/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pc100/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/* arch/arm/mach-s5pc100/include/mach/memory.h
- *
- * Copyright 2008 Samsung Electronics Co.
- *      Byungho Min <bhmin@samsung.com>
- *
- * Based on mach-s3c6400/include/mach/memory.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_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET     	UL(0x20000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pc100/include/mach/pwm-clock.h linux-libre-3.2-gnu/arch/arm/mach-s5pc100/include/mach/pwm-clock.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5pc100/include/mach/pwm-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pc100/include/mach/pwm-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/include/mach/pwm-clock.h
- *
- * Copyright 2009 Samsung Electronics Co.
- *      Byungho Min <bhmin@samsung.com>
- *
- * S5PC100 - pwm clock and timer support
- *
- * Based on mach-s3c6400/include/mach/pwm-clock.h
- */
-
-/**
- * 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
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pc100/Kconfig linux-libre-3.2-gnu/arch/arm/mach-s5pc100/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-s5pc100/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pc100/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
 config CPU_S5PC100
 	bool
 	select S5P_EXT_INT
-	select S3C_PL330_DMA
+	select SAMSUNG_DMADEV
 	help
 	  Enable S5PC100 CPU support
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pc100/mach-smdkc100.c linux-libre-3.2-gnu/arch/arm/mach-s5pc100/mach-smdkc100.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5pc100/mach-smdkc100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pc100/mach-smdkc100.c	2012-01-04 18:55:44.000000000 -0500
@@ -203,12 +203,6 @@
 	&s5pc100_device_spdif,
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 /* LCD Backlight data */
 static struct samsung_bl_gpio_info smdkc100_bl_gpio_info = {
 	.no = S5PC100_GPD(0),
@@ -228,7 +222,7 @@
 
 static void __init smdkc100_machine_init(void)
 {
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	/* I2C */
 	s3c_i2c0_set_platdata(NULL);
@@ -254,7 +248,7 @@
 
 MACHINE_START(SMDKC100, "SMDKC100")
 	/* Maintainer: Byungho Min <bhmin@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s5pc100_init_irq,
 	.map_io		= smdkc100_map_io,
 	.init_machine	= smdkc100_machine_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pc100/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-s5pc100/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-s5pc100/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pc100/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-   zreladdr-y	:= 0x20008000
+   zreladdr-y	+= 0x20008000
 params_phys-y	:= 0x20000100
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pc100/setup-sdhci.c linux-libre-3.2-gnu/arch/arm/mach-s5pc100/setup-sdhci.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5pc100/setup-sdhci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pc100/setup-sdhci.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,17 +11,7 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
 
 /* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
 
@@ -31,35 +21,3 @@
 	[2] = "sclk_mmc",	/* mmc_bus */
 	/* [3] = "48m",		- note not successfully used yet */
 };
-
-
-void s5pc100_setup_sdhci0_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 */
-
-	writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4);
-
-	ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
-	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-		  S3C_SDHCI_CTRL2_ENFBCLKRX |
-		  S3C_SDHCI_CTRL2_DFCNT_NONE |
-		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-	if (ios->clock < 25 * 1000000)
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-			 S3C_SDHCI_CTRL3_FCSEL2 |
-			 S3C_SDHCI_CTRL3_FCSEL1 |
-			 S3C_SDHCI_CTRL3_FCSEL0);
-	else
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-	writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/clock.c linux-libre-3.2-gnu/arch/arm/mach-s5pv210/clock.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -174,6 +174,16 @@
 	return s5p_gatectrl(S5P_CLK_SRC_MASK1, clk, enable);
 }
 
+static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
+}
+
+static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
+}
+
 static struct clk clk_sclk_hdmi27m = {
 	.name		= "sclk_hdmi27m",
 	.rate		= 27000000,
@@ -203,6 +213,11 @@
 	.name		= "pcmcdclk",
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 static struct clk *clkset_vpllsrc_list[] = {
 	[0] = &clk_fin_vpll,
 	[1] = &clk_sclk_hdmi27m,
@@ -289,14 +304,14 @@
 
 static struct clk init_clocks_off[] = {
 	{
-		.name		= "pdma",
-		.devname	= "s3c-pl330.0",
+		.name		= "dma",
+		.devname	= "dma-pl330.0",
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip0_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
-		.name		= "pdma",
-		.devname	= "s3c-pl330.1",
+		.name		= "dma",
+		.devname	= "dma-pl330.1",
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip0_ctrl,
 		.ctrlbit	= (1 << 4),
@@ -330,6 +345,40 @@
 		.enable		= s5pv210_clk_ip0_ctrl,
 		.ctrlbit	= (1 << 16),
 	}, {
+		.name		= "dac",
+		.devname	= "s5p-sdo",
+		.parent		= &clk_hclk_dsys.clk,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1 << 10),
+	}, {
+		.name		= "mixer",
+		.devname	= "s5p-mixer",
+		.parent		= &clk_hclk_dsys.clk,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1 << 9),
+	}, {
+		.name		= "vp",
+		.devname	= "s5p-mixer",
+		.parent		= &clk_hclk_dsys.clk,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "hdmi",
+		.devname	= "s5pv210-hdmi",
+		.parent		= &clk_hclk_dsys.clk,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1 << 11),
+	}, {
+		.name		= "hdmiphy",
+		.devname	= "s5pv210-hdmi",
+		.enable		= exynos4_clk_hdmiphy_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "dacphy",
+		.devname	= "s5p-sdo",
+		.enable		= exynos4_clk_dac_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
 		.name		= "otg",
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip1_ctrl,
@@ -407,6 +456,12 @@
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1<<9),
 	}, {
+		.name		= "i2c",
+		.devname	= "s3c2440-hdmiphy-i2c",
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1 << 11),
+	}, {
 		.name		= "spi",
 		.devname	= "s3c64xx-spi.0",
 		.parent		= &clk_pclk_psys.clk,
@@ -594,6 +649,23 @@
 	.nr_sources	= ARRAY_SIZE(clkset_sclk_mixer_list),
 };
 
+static struct clksrc_clk clk_sclk_mixer = {
+	.clk		= {
+		.name		= "sclk_mixer",
+		.enable		= s5pv210_clk_mask0_ctrl,
+		.ctrlbit	= (1 << 1),
+	},
+	.sources = &clkset_sclk_mixer,
+	.reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk *sclk_tv[] = {
+	&clk_sclk_dac,
+	&clk_sclk_pixel,
+	&clk_sclk_hdmi,
+	&clk_sclk_mixer,
+};
+
 static struct clk *clkset_sclk_audio0_list[] = {
 	[0] = &clk_ext_xtal_mux,
 	[1] = &clk_pcmcdclk0,
@@ -777,14 +849,6 @@
 		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 },
 	}, {
 		.clk	= {
-			.name		= "sclk_mixer",
-			.enable		= s5pv210_clk_mask0_ctrl,
-			.ctrlbit	= (1 << 1),
-		},
-		.sources = &clkset_sclk_mixer,
-		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
-	}, {
-		.clk	= {
 			.name		= "sclk_fimc",
 			.devname	= "s5pv210-fimc.0",
 			.enable		= s5pv210_clk_mask1_ctrl,
@@ -973,9 +1037,6 @@
 	&clk_pclk_psys,
 	&clk_vpllsrc,
 	&clk_sclk_vpll,
-	&clk_sclk_dac,
-	&clk_sclk_pixel,
-	&clk_sclk_hdmi,
 	&clk_mout_dmc0,
 	&clk_sclk_dmc0,
 	&clk_sclk_audio0,
@@ -1060,6 +1121,61 @@
 	.get_rate = s5p_epll_get_rate,
 };
 
+static u32 vpll_div[][5] = {
+	{  54000000, 3, 53, 3, 0 },
+	{ 108000000, 3, 53, 2, 0 },
+};
+
+static unsigned long s5pv210_vpll_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+
+static int s5pv210_vpll_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned int vpll_con;
+	unsigned int i;
+
+	/* Return if nothing changed */
+	if (clk->rate == rate)
+		return 0;
+
+	vpll_con = __raw_readl(S5P_VPLL_CON);
+	vpll_con &= ~(0x1 << 27 |					\
+			PLL90XX_MDIV_MASK << PLL90XX_MDIV_SHIFT |	\
+			PLL90XX_PDIV_MASK << PLL90XX_PDIV_SHIFT |	\
+			PLL90XX_SDIV_MASK << PLL90XX_SDIV_SHIFT);
+
+	for (i = 0; i < ARRAY_SIZE(vpll_div); i++) {
+		if (vpll_div[i][0] == rate) {
+			vpll_con |= vpll_div[i][1] << PLL90XX_PDIV_SHIFT;
+			vpll_con |= vpll_div[i][2] << PLL90XX_MDIV_SHIFT;
+			vpll_con |= vpll_div[i][3] << PLL90XX_SDIV_SHIFT;
+			vpll_con |= vpll_div[i][4] << 27;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(vpll_div)) {
+		printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	__raw_writel(vpll_con, S5P_VPLL_CON);
+
+	/* Wait for VPLL lock */
+	while (!(__raw_readl(S5P_VPLL_CON) & (1 << PLL90XX_LOCKED_SHIFT)))
+		continue;
+
+	clk->rate = rate;
+	return 0;
+}
+static struct clk_ops s5pv210_vpll_ops = {
+	.get_rate = s5pv210_vpll_get_rate,
+	.set_rate = s5pv210_vpll_set_rate,
+};
+
 void __init_or_cpufreq s5pv210_setup_clocks(void)
 {
 	struct clk *xtal_clk;
@@ -1108,6 +1224,7 @@
 	clk_fout_apll.ops = &clk_fout_apll_ops;
 	clk_fout_mpll.rate = mpll;
 	clk_fout_epll.rate = epll;
+	clk_fout_vpll.ops = &s5pv210_vpll_ops;
 	clk_fout_vpll.rate = vpll;
 
 	printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
@@ -1153,11 +1270,15 @@
 	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
 		s3c_register_clksrc(sysclks[ptr], 1);
 
+	for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
+		s3c_register_clksrc(sclk_tv[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));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
 	s3c_pwmclk_init();
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/cpu.c linux-libre-3.2-gnu/arch/arm/mach-s5pv210/cpu.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/sysdev.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -41,6 +42,7 @@
 #include <plat/keypad-core.h>
 #include <plat/sdhci.h>
 #include <plat/reset.h>
+#include <plat/tv-core.h>
 
 /* Initial IO mappings */
 
@@ -119,6 +121,7 @@
 void __init s5pv210_map_io(void)
 {
 	iotable_init(s5pv210_iodesc, ARRAY_SIZE(s5pv210_iodesc));
+	init_consistent_dma_size(14 << 20);
 
 	/* initialise device information early */
 	s5pv210_default_sdhci0();
@@ -143,6 +146,9 @@
 
 	/* Use s5pv210-keypad instead of samsung-keypad */
 	samsung_keypad_setname("s5pv210-keypad");
+
+	/* setup TV devices */
+	s5p_hdmi_setname("s5pv210-hdmi");
 }
 
 void __init s5pv210_init_clocks(int xtal)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/dma.c linux-libre-3.2-gnu/arch/arm/mach-s5pv210/dma.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,8 @@
-/*
+/* linux/arch/arm/mach-s5pv210/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>
  *
@@ -17,151 +21,240 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
 
+#include <asm/irq.h>
 #include <plat/devs.h>
 #include <plat/irqs.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
+#include <mach/dma.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5pv210_pdma0_resource[] = {
-	[0] = {
-		.start  = S5PV210_PA_PDMA0,
-		.end    = S5PV210_PA_PDMA0 + SZ_4K,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA0,
-		.end	= IRQ_PDMA0,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri pdma0_peri[28] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_AC97_MICIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMOUT,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_PWM,
+	}, {
+		.peri_id = (u8)DMACH_SPDIF,
+		.rqtype = MEMTODEV,
 	},
 };
 
-static struct s3c_pl330_platdata s5pv210_pdma0_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_MAX,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S0S_TX,
-		[12] = DMACH_I2S1_RX,
-		[13] = DMACH_I2S1_TX,
-		[14] = DMACH_MAX,
-		[15] = DMACH_MAX,
-		[16] = DMACH_SPI0_RX,
-		[17] = DMACH_SPI0_TX,
-		[18] = DMACH_SPI1_RX,
-		[19] = DMACH_SPI1_TX,
-		[20] = DMACH_MAX,
-		[21] = DMACH_MAX,
-		[22] = DMACH_AC97_MICIN,
-		[23] = DMACH_AC97_PCMIN,
-		[24] = DMACH_AC97_PCMOUT,
-		[25] = DMACH_MAX,
-		[26] = DMACH_PWM,
-		[27] = DMACH_SPDIF,
-		[28] = DMACH_MAX,
-		[29] = DMACH_MAX,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata s5pv210_pdma0_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(pdma0_peri),
+	.peri = pdma0_peri,
 };
 
-static struct platform_device s5pv210_device_pdma0 = {
-	.name		= "s3c-pl330",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5pv210_pdma0_resource),
-	.resource	= s5pv210_pdma0_resource,
-	.dev		= {
+struct amba_device s5pv210_device_pdma0 = {
+	.dev = {
+		.init_name = "dma-pl330.0",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &s5pv210_pdma0_pdata,
 	},
-};
-
-static struct resource s5pv210_pdma1_resource[] = {
-	[0] = {
-		.start  = S5PV210_PA_PDMA1,
-		.end    = S5PV210_PA_PDMA1 + SZ_4K,
+	.res = {
+		.start = S5PV210_PA_PDMA0,
+		.end = S5PV210_PA_PDMA0 + SZ_4K,
 		.flags = IORESOURCE_MEM,
 	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
-	},
+	.irq = {IRQ_PDMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
-static struct s3c_pl330_platdata s5pv210_pdma1_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_MAX,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S0S_TX,
-		[12] = DMACH_I2S1_RX,
-		[13] = DMACH_I2S1_TX,
-		[14] = DMACH_I2S2_RX,
-		[15] = DMACH_I2S2_TX,
-		[16] = DMACH_SPI0_RX,
-		[17] = DMACH_SPI0_TX,
-		[18] = DMACH_SPI1_RX,
-		[19] = DMACH_SPI1_TX,
-		[20] = DMACH_MAX,
-		[21] = DMACH_MAX,
-		[22] = DMACH_PCM0_RX,
-		[23] = DMACH_PCM0_TX,
-		[24] = DMACH_PCM1_RX,
-		[25] = DMACH_PCM1_TX,
-		[26] = DMACH_MSM_REQ0,
-		[27] = DMACH_MSM_REQ1,
-		[28] = DMACH_MSM_REQ2,
-		[29] = DMACH_MSM_REQ3,
-		[30] = DMACH_PCM2_RX,
-		[31] = DMACH_PCM2_TX,
+struct dma_pl330_peri pdma1_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ0,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ1,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ2,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ3,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_TX,
+		.rqtype = MEMTODEV,
 	},
 };
 
-static struct platform_device s5pv210_device_pdma1 = {
-	.name		= "s3c-pl330",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5pv210_pdma1_resource),
-	.resource	= s5pv210_pdma1_resource,
-	.dev		= {
+struct dma_pl330_platdata s5pv210_pdma1_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
+	.peri = pdma1_peri,
+};
+
+struct amba_device s5pv210_device_pdma1 = {
+	.dev = {
+		.init_name = "dma-pl330.1",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &s5pv210_pdma1_pdata,
 	},
-};
-
-static struct platform_device *s5pv210_dmacs[] __initdata = {
-	&s5pv210_device_pdma0,
-	&s5pv210_device_pdma1,
+	.res = {
+		.start = S5PV210_PA_PDMA1,
+		.end = S5PV210_PA_PDMA1 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_PDMA1, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
 static int __init s5pv210_dma_init(void)
 {
-	platform_add_devices(s5pv210_dmacs, ARRAY_SIZE(s5pv210_dmacs));
+	amba_device_register(&s5pv210_device_pdma0, &iomem_resource);
+	amba_device_register(&s5pv210_device_pdma1, &iomem_resource);
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/clkdev.h linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/clkdev.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/clkdev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef __MACH_CLKDEV_H__
-#define __MACH_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do {} while (0)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
 	 * aligned and add in the offset when we load the value here.
 	 */
 
-	.macro addruart, rp, rv
+	.macro addruart, rp, rv, tmp
 		ldr	\rp, = S3C_PA_UART
 		ldr	\rv, = S3C_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/dma.h linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/dma.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
 #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>
+/* This platform uses the common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,11 +13,6 @@
 #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 MP03 are the configurable gpio banks */
 
 /* GPIO bank sizes */
@@ -142,6 +137,4 @@
 #define ARCH_NR_GPIOS		(S5PV210_MP05(S5PV210_GPIO_MP05_NR) +	\
 				 CONFIG_SAMSUNG_GPIO_EXTRA + 1)
 
-#include <asm-generic/gpio.h>
-
 #endif /* __ASM_ARCH_GPIO_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/irqs.h linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/irqs.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -56,7 +56,7 @@
 #define IRQ_SPI2		S5P_IRQ_VIC1(17)
 #define IRQ_IRDA		S5P_IRQ_VIC1(18)
 #define IRQ_IIC2		S5P_IRQ_VIC1(19)
-#define IRQ_IIC3		S5P_IRQ_VIC1(20)
+#define IRQ_IIC_HDMIPHY		S5P_IRQ_VIC1(20)
 #define IRQ_HSIRX		S5P_IRQ_VIC1(21)
 #define IRQ_HSITX		S5P_IRQ_VIC1(22)
 #define IRQ_UHOST		S5P_IRQ_VIC1(23)
@@ -86,7 +86,7 @@
 #define IRQ_HDMI		S5P_IRQ_VIC2(12)
 #define IRQ_IIC1		S5P_IRQ_VIC2(13)
 #define IRQ_MFC			S5P_IRQ_VIC2(14)
-#define IRQ_TVENC		S5P_IRQ_VIC2(15)
+#define IRQ_SDO			S5P_IRQ_VIC2(15)
 #define IRQ_I2S0		S5P_IRQ_VIC2(16)
 #define IRQ_I2S1		S5P_IRQ_VIC2(17)
 #define IRQ_I2S2		S5P_IRQ_VIC2(18)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/map.h linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/map.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/map.h	2012-01-04 18:55:44.000000000 -0500
@@ -90,6 +90,12 @@
 #define S5PV210_PA_FIMC1		0xFB300000
 #define S5PV210_PA_FIMC2		0xFB400000
 
+#define S5PV210_PA_SDO			0xF9000000
+#define S5PV210_PA_VP			0xF9100000
+#define S5PV210_PA_MIXER		0xF9200000
+#define S5PV210_PA_HDMI			0xFA100000
+#define S5PV210_PA_IIC_HDMIPHY		0xFA900000
+
 /* Compatibiltiy Defines */
 
 #define S3C_PA_FB			S5PV210_PA_FB
@@ -110,6 +116,13 @@
 #define S5P_PA_FIMC2			S5PV210_PA_FIMC2
 #define S5P_PA_MIPI_CSIS0		S5PV210_PA_MIPI_CSIS
 #define S5P_PA_MFC			S5PV210_PA_MFC
+#define S5P_PA_IIC_HDMIPHY		S5PV210_PA_IIC_HDMIPHY
+
+#define S5P_PA_SDO			S5PV210_PA_SDO
+#define S5P_PA_VP			S5PV210_PA_VP
+#define S5P_PA_MIXER			S5PV210_PA_MIXER
+#define S5P_PA_HDMI			S5PV210_PA_HDMI
+
 #define S5P_PA_ONENAND			S5PC110_PA_ONENAND
 #define S5P_PA_ONENAND_DMA		S5PC110_PA_ONENAND_DMA
 #define S5P_PA_SDRAM			S5PV210_PA_SDRAM
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/memory.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,6 @@
 #define __ASM_ARCH_MEMORY_H
 
 #define PLAT_PHYS_OFFSET		UL(0x20000000)
-#define CONSISTENT_DMA_SIZE	(SZ_8M + SZ_4M + SZ_2M)
 
 /*
  * Sparsemem support
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/pm-core.h linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/pm-core.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/pm-core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/pm-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -43,4 +43,4 @@
 }
 
 static inline void s3c_pm_restored_gpios(void) { }
-static inline void s3c_pm_saved_gpios(void) { }
+static inline void samsung_pm_saved_gpios(void) { }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/pwm-clock.h linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/pwm-clock.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/pwm-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/pwm-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/pwm-clock.h
- *
- * Copyright (c) 2009 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
- *
- * S5PV210 - 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-3.1-gnu/arch/arm/mach-s5pv210/include/mach/regs-clock.h linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/regs-clock.h
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/include/mach/regs-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/include/mach/regs-clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -144,8 +144,9 @@
 
 #define S5P_OTHERS		S5P_CLKREG(0xE000)
 #define S5P_OM_STAT		S5P_CLKREG(0xE100)
+#define S5P_HDMI_PHY_CONTROL	S5P_CLKREG(0xE804)
 #define S5P_USB_PHY_CONTROL	S5P_CLKREG(0xE80C)
-#define S5P_DAC_CONTROL		S5P_CLKREG(0xE810)
+#define S5P_DAC_PHY_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)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/Kconfig linux-libre-3.2-gnu/arch/arm/mach-s5pv210/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -11,10 +11,11 @@
 
 config CPU_S5PV210
 	bool
-	select S3C_PL330_DMA
+	select SAMSUNG_DMADEV
 	select S5P_EXT_INT
 	select S5P_HRT
-	select S5PV210_PM if PM
+	select S5P_PM if PM
+	select S5P_SLEEP if PM
 	help
 	  Enable S5PV210 CPU support
 
@@ -94,11 +95,13 @@
 	select S3C_DEV_USB_HSOTG
 	select S5P_DEV_ONENAND
 	select SAMSUNG_DEV_KEYPAD
+	select S5P_DEV_TV
 	select S5PV210_SETUP_FB_24BPP
 	select S5PV210_SETUP_I2C1
 	select S5PV210_SETUP_I2C2
 	select S5PV210_SETUP_KEYPAD
 	select S5PV210_SETUP_SDHCI
+	select S5PV210_SETUP_FIMC
 	help
 	  Machine support for Samsung GONI board
 	  S5PC110(MCP) is one of package option of S5PV210
@@ -169,9 +172,4 @@
 
 endmenu
 
-config S5PV210_PM
-	bool
-	help
-	  Power Management code common to S5PV210
-
 endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/mach-aquila.c linux-libre-3.2-gnu/arch/arm/mach-s5pv210/mach-aquila.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/mach-aquila.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/mach-aquila.c	2012-01-04 18:55:44.000000000 -0500
@@ -678,7 +678,7 @@
 	/* Maintainers:
 	   Marek Szyprowski <m.szyprowski@samsung.com>
 	   Kyungmin Park <kyungmin.park@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= aquila_map_io,
 	.init_machine	= aquila_machine_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/mach-goni.c linux-libre-3.2-gnu/arch/arm/mach-s5pv210/mach-goni.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/mach-goni.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/mach-goni.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,6 +48,11 @@
 #include <plat/s5p-time.h>
 #include <plat/mfc.h>
 #include <plat/regs-fb-v4.h>
+#include <plat/camport.h>
+
+#include <media/v4l2-mediabus.h>
+#include <media/s5p_fimc.h>
+#include <media/noon010pc30.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define GONI_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -272,6 +277,14 @@
 	i2c2_devs[0].irq = gpio_to_irq(gpio);
 }
 
+static void goni_camera_init(void)
+{
+	s5pv210_fimc_setup_gpio(S5P_CAMPORT_A);
+
+	/* Set max driver strength on CAM_A_CLKOUT pin. */
+	s5p_gpio_set_drvstr(S5PV210_GPE1(3), S5P_GPIO_DRVSTR_LV4);
+}
+
 /* MAX8998 regulators */
 #if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
 
@@ -285,6 +298,7 @@
 
 static struct regulator_consumer_supply goni_ldo8_consumers[] = {
 	REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"),
+	REGULATOR_SUPPLY("vdd33a_dac", "s5p-sdo"),
 };
 
 static struct regulator_consumer_supply goni_ldo11_consumers[] = {
@@ -475,6 +489,10 @@
 static struct regulator_consumer_supply buck2_consumer =
 	REGULATOR_SUPPLY("vddint", NULL);
 
+static struct regulator_consumer_supply buck3_consumer =
+	REGULATOR_SUPPLY("vdet", "s5p-sdo");
+
+
 static struct regulator_init_data goni_buck1_data = {
 	.constraints	= {
 		.name		= "VARM_1.2V",
@@ -511,6 +529,8 @@
 			.enabled = 1,
 		},
 	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &buck3_consumer,
 };
 
 static struct regulator_init_data goni_buck4_data = {
@@ -801,6 +821,34 @@
 	s3c_sdhci2_set_platdata(&goni_hsmmc2_data);
 };
 
+static struct noon010pc30_platform_data noon010pc30_pldata = {
+	.clk_rate	= 16000000UL,
+	.gpio_nreset	= S5PV210_GPB(2), /* CAM_CIF_NRST */
+	.gpio_nstby	= S5PV210_GPB(0), /* CAM_CIF_NSTBY */
+};
+
+static struct i2c_board_info noon010pc30_board_info = {
+	I2C_BOARD_INFO("NOON010PC30", 0x60 >> 1),
+	.platform_data = &noon010pc30_pldata,
+};
+
+static struct s5p_fimc_isp_info goni_camera_sensors[] = {
+	{
+		.mux_id		= 0,
+		.flags		= V4L2_MBUS_PCLK_SAMPLE_FALLING |
+				  V4L2_MBUS_VSYNC_ACTIVE_LOW,
+		.bus_type	= FIMC_ITU_601,
+		.board_info	= &noon010pc30_board_info,
+		.i2c_bus_num	= 0,
+		.clk_frequency	= 16000000UL,
+	},
+};
+
+struct s5p_platform_fimc goni_fimc_md_platdata __initdata = {
+	.isp_info	= goni_camera_sensors,
+	.num_clients	= ARRAY_SIZE(goni_camera_sensors),
+};
+
 static struct platform_device *goni_devices[] __initdata = {
 	&s3c_device_fb,
 	&s5p_device_onenand,
@@ -812,10 +860,13 @@
 	&s5p_device_mfc,
 	&s5p_device_mfc_l,
 	&s5p_device_mfc_r,
+	&s5p_device_mixer,
+	&s5p_device_sdo,
 	&s3c_device_i2c0,
 	&s5p_device_fimc0,
 	&s5p_device_fimc1,
 	&s5p_device_fimc2,
+	&s5p_device_fimc_md,
 	&s3c_device_hsmmc0,
 	&s3c_device_hsmmc1,
 	&s3c_device_hsmmc2,
@@ -884,6 +935,12 @@
 	/* FB */
 	s3c_fb_set_platdata(&goni_lcd_pdata);
 
+	/* FIMC */
+	s3c_set_platdata(&goni_fimc_md_platdata, sizeof(goni_fimc_md_platdata),
+			 &s5p_device_fimc_md);
+
+	goni_camera_init();
+
 	/* SPI */
 	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 
@@ -897,7 +954,7 @@
 
 MACHINE_START(GONI, "GONI")
 	/* Maintainers: Kyungmin Park <kyungmin.park@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= goni_map_io,
 	.init_machine	= goni_machine_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/mach-smdkc110.c linux-libre-3.2-gnu/arch/arm/mach-s5pv210/mach-smdkc110.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/mach-smdkc110.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/mach-smdkc110.c	2012-01-04 18:55:44.000000000 -0500
@@ -136,7 +136,7 @@
 
 MACHINE_START(SMDKC110, "SMDKC110")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= smdkc110_map_io,
 	.init_machine	= smdkc110_machine_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/mach-smdkv210.c linux-libre-3.2-gnu/arch/arm/mach-s5pv210/mach-smdkv210.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/mach-smdkv210.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/mach-smdkv210.c	2012-01-04 18:55:44.000000000 -0500
@@ -265,12 +265,6 @@
 	/* To Be Updated */
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 /* LCD Backlight data */
 static struct samsung_bl_gpio_info smdkv210_bl_gpio_info = {
 	.no = S5PV210_GPD0(3),
@@ -279,6 +273,7 @@
 
 static struct platform_pwm_backlight_data smdkv210_bl_data = {
 	.pwm_id = 3,
+	.pwm_period_ns = 1000,
 };
 
 static void __init smdkv210_map_io(void)
@@ -296,7 +291,7 @@
 	smdkv210_dm9000_init();
 
 	samsung_keypad_set_platdata(&smdkv210_keypad_data);
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	s3c_i2c0_set_platdata(NULL);
 	s3c_i2c1_set_platdata(NULL);
@@ -319,7 +314,7 @@
 
 MACHINE_START(SMDKV210, "SMDKV210")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= smdkv210_map_io,
 	.init_machine	= smdkv210_machine_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/mach-torbreck.c linux-libre-3.2-gnu/arch/arm/mach-s5pv210/mach-torbreck.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/mach-torbreck.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/mach-torbreck.c	2012-01-04 18:55:44.000000000 -0500
@@ -125,7 +125,7 @@
 
 MACHINE_START(TORBRECK, "TORBRECK")
 	/* Maintainer: Hyunchul Ko <ghcstop@gmail.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.atag_offset	= 0x100,
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= torbreck_map_io,
 	.init_machine	= torbreck_machine_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/Makefile linux-libre-3.2-gnu/arch/arm/mach-s5pv210/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 
 obj-$(CONFIG_CPU_S5PV210)	+= cpu.o init.o clock.o dma.o
 obj-$(CONFIG_CPU_S5PV210)	+= setup-i2c0.o
-obj-$(CONFIG_S5PV210_PM)	+= pm.o sleep.o
+obj-$(CONFIG_PM)		+= pm.o
 
 # machine support
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-s5pv210/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-   zreladdr-y	:= 0x20008000
+   zreladdr-y	+= 0x20008000
 params_phys-y	:= 0x20000100
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/setup-sdhci.c linux-libre-3.2-gnu/arch/arm/mach-s5pv210/setup-sdhci.c
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/setup-sdhci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/setup-sdhci.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,17 +10,7 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
 
 /* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
 
@@ -30,34 +20,3 @@
 	[2] = "sclk_mmc",	/* mmc_bus */
 	/* [3] = NULL,		- reserved */
 };
-
-void s5pv210_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 */
-
-	writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4);
-
-	ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
-	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-		  S3C_SDHCI_CTRL2_ENFBCLKRX |
-		  S3C_SDHCI_CTRL2_DFCNT_NONE |
-		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-	if (ios->clock < 25 * 1000000)
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-			 S3C_SDHCI_CTRL3_FCSEL2 |
-			 S3C_SDHCI_CTRL3_FCSEL1 |
-			 S3C_SDHCI_CTRL3_FCSEL0);
-	else
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-	writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-s5pv210/sleep.S linux-libre-3.2-gnu/arch/arm/mach-s5pv210/sleep.S
--- linux-libre-3.1-gnu/arch/arm/mach-s5pv210/sleep.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-s5pv210/sleep.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-/* linux/arch/arm/plat-s5p/sleep.S
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV210 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
-
-	/* 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-3.1-gnu/arch/arm/mach-sa1100/assabet.c linux-libre-3.2-gnu/arch/arm/mach-sa1100/assabet.c
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/assabet.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/assabet.c	2012-01-04 18:55:44.000000000 -0500
@@ -301,8 +301,7 @@
 }
 
 static void __init
-fixup_assabet(struct machine_desc *desc, struct tag *tags,
-	      char **cmdline, struct meminfo *mi)
+fixup_assabet(struct tag *tags, char **cmdline, struct meminfo *mi)
 {
 	/* This must be done before any call to machine_has_neponset() */
 	map_sa1100_gpio_regs();
@@ -447,7 +446,7 @@
 
 
 MACHINE_START(ASSABET, "Intel-Assabet")
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.fixup		= fixup_assabet,
 	.map_io		= assabet_map_io,
 	.init_irq	= sa1100_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/badge4.c linux-libre-3.2-gnu/arch/arm/mach-sa1100/badge4.c
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/badge4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/badge4.c	2012-01-04 18:55:44.000000000 -0500
@@ -302,7 +302,7 @@
 }
 
 MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4")
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= badge4_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/collie.c linux-libre-3.2-gnu/arch/arm/mach-sa1100/collie.c
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/collie.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/collie.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/irq.h>
+#include <asm/page.h>
 #include <asm/setup.h>
 #include <mach/collie.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/generic.c linux-libre-3.2-gnu/arch/arm/mach-sa1100/generic.c
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/generic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/generic.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  * 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/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -24,7 +25,6 @@
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 #include <asm/irq.h>
-#include <asm/gpio.h>
 
 #include "generic.h"
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/gpio.c linux-libre-3.2-gnu/arch/arm/mach-sa1100/gpio.c
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-/*
- * linux/arch/arm/mach-sa1100/gpio.c
- *
- * Generic SA-1100 GPIO handling
- *
- * This program is free software; you can 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 <asm/gpio.h>
-#include <mach/hardware.h>
-#include "generic.h"
-
-static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	return GPLR & GPIO_GPIO(offset);
-}
-
-static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	if (value)
-		GPSR = GPIO_GPIO(offset);
-	else
-		GPCR = GPIO_GPIO(offset);
-}
-
-static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	GPDR &= ~GPIO_GPIO(offset);
-	local_irq_restore(flags);
-	return 0;
-}
-
-static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int value)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	sa1100_gpio_set(chip, offset, value);
-	GPDR |= GPIO_GPIO(offset);
-	local_irq_restore(flags);
-	return 0;
-}
-
-static struct gpio_chip sa1100_gpio_chip = {
-	.label			= "gpio",
-	.direction_input	= sa1100_direction_input,
-	.direction_output	= sa1100_direction_output,
-	.set			= sa1100_gpio_set,
-	.get			= sa1100_gpio_get,
-	.base			= 0,
-	.ngpio			= GPIO_MAX + 1,
-};
-
-void __init sa1100_init_gpio(void)
-{
-	gpiochip_add(&sa1100_gpio_chip);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/h3100.c linux-libre-3.2-gnu/arch/arm/mach-sa1100/h3100.c
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/h3100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/h3100.c	2012-01-04 18:55:44.000000000 -0500
@@ -84,7 +84,7 @@
 }
 
 MACHINE_START(H3100, "Compaq iPAQ H3100")
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= h3100_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/h3600.c linux-libre-3.2-gnu/arch/arm/mach-sa1100/h3600.c
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/h3600.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/h3600.c	2012-01-04 18:55:44.000000000 -0500
@@ -125,7 +125,7 @@
 }
 
 MACHINE_START(H3600, "Compaq iPAQ H3600")
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= h3600_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/hackkit.c linux-libre-3.2-gnu/arch/arm/mach-sa1100/hackkit.c
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/hackkit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/hackkit.c	2012-01-04 18:55:44.000000000 -0500
@@ -195,7 +195,7 @@
  */
 
 MACHINE_START(HACKKIT, "HackKit Cpu Board")
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= hackkit_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-sa1100/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
 */
 #include <mach/hardware.h>
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mrc	p15, 0, \rp, c1, c0
 		tst	\rp, #1			@ MMU enabled?
 		moveq	\rp, #0x80000000	@ physical base address
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-sa1100/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,8 @@
 #include <asm/irq.h>
 #include <asm-generic/gpio.h>
 
+#define __ARM_GPIOLIB_COMPLEX
+
 static inline int gpio_get_value(unsigned gpio)
 {
 	if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
@@ -51,7 +53,5 @@
 
 #define gpio_to_irq(gpio)	((gpio < 11) ? (IRQ_GPIO0 + gpio) : \
 					(IRQ_GPIO11 - 11 + gpio))
-#define irq_to_gpio(irq)	((irq < IRQ_GPIO11_27) ? (irq - IRQ_GPIO0) : \
-					(irq - IRQ_GPIO11 + 11))
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/include/mach/io.h linux-libre-3.2-gnu/arch/arm/mach-sa1100/include/mach/io.h
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -10,11 +10,9 @@
 #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...
+ * __io() is required to be an equivalent mapping to __mem_pci() for
+ * SOC_COMMON to work.
  */
 #define __io(a)		__typesafe_io(a)
 #define __mem_pci(a)	(a)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/include/mach/simpad.h linux-libre-3.2-gnu/arch/arm/mach-sa1100/include/mach/simpad.h
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/include/mach/simpad.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/include/mach/simpad.h	2012-01-04 18:55:44.000000000 -0500
@@ -48,32 +48,80 @@
 #define GPIO_SMART_CARD		GPIO_GPIO10
 #define IRQ_GPIO_SMARD_CARD	IRQ_GPIO10
 
-// CS3 Latch is write only, a shadow is necessary
+/*--- ucb1x00 GPIO ---*/
+#define SIMPAD_UCB1X00_GPIO_BASE	(GPIO_MAX + 1)
+#define SIMPAD_UCB1X00_GPIO_PROG1	(SIMPAD_UCB1X00_GPIO_BASE)
+#define SIMPAD_UCB1X00_GPIO_PROG2	(SIMPAD_UCB1X00_GPIO_BASE + 1)
+#define SIMPAD_UCB1X00_GPIO_UP		(SIMPAD_UCB1X00_GPIO_BASE + 2)
+#define SIMPAD_UCB1X00_GPIO_DOWN	(SIMPAD_UCB1X00_GPIO_BASE + 3)
+#define SIMPAD_UCB1X00_GPIO_LEFT	(SIMPAD_UCB1X00_GPIO_BASE + 4)
+#define SIMPAD_UCB1X00_GPIO_RIGHT	(SIMPAD_UCB1X00_GPIO_BASE + 5)
+#define SIMPAD_UCB1X00_GPIO_6		(SIMPAD_UCB1X00_GPIO_BASE + 6)
+#define SIMPAD_UCB1X00_GPIO_7		(SIMPAD_UCB1X00_GPIO_BASE + 7)
+#define SIMPAD_UCB1X00_GPIO_HEADSET	(SIMPAD_UCB1X00_GPIO_BASE + 8)
+#define SIMPAD_UCB1X00_GPIO_SPEAKER	(SIMPAD_UCB1X00_GPIO_BASE + 9)
+
+/*--- CS3 Latch ---*/
+#define SIMPAD_CS3_GPIO_BASE		(GPIO_MAX + 11)
+#define SIMPAD_CS3_VCC_5V_EN		(SIMPAD_CS3_GPIO_BASE)
+#define SIMPAD_CS3_VCC_3V_EN		(SIMPAD_CS3_GPIO_BASE + 1)
+#define SIMPAD_CS3_EN1			(SIMPAD_CS3_GPIO_BASE + 2)
+#define SIMPAD_CS3_EN0			(SIMPAD_CS3_GPIO_BASE + 3)
+#define SIMPAD_CS3_DISPLAY_ON		(SIMPAD_CS3_GPIO_BASE + 4)
+#define SIMPAD_CS3_PCMCIA_BUFF_DIS	(SIMPAD_CS3_GPIO_BASE + 5)
+#define SIMPAD_CS3_MQ_RESET		(SIMPAD_CS3_GPIO_BASE + 6)
+#define SIMPAD_CS3_PCMCIA_RESET		(SIMPAD_CS3_GPIO_BASE + 7)
+#define SIMPAD_CS3_DECT_POWER_ON	(SIMPAD_CS3_GPIO_BASE + 8)
+#define SIMPAD_CS3_IRDA_SD		(SIMPAD_CS3_GPIO_BASE + 9)
+#define SIMPAD_CS3_RS232_ON		(SIMPAD_CS3_GPIO_BASE + 10)
+#define SIMPAD_CS3_SD_MEDIAQ		(SIMPAD_CS3_GPIO_BASE + 11)
+#define SIMPAD_CS3_LED2_ON		(SIMPAD_CS3_GPIO_BASE + 12)
+#define SIMPAD_CS3_IRDA_MODE		(SIMPAD_CS3_GPIO_BASE + 13)
+#define SIMPAD_CS3_ENABLE_5V		(SIMPAD_CS3_GPIO_BASE + 14)
+#define SIMPAD_CS3_RESET_SIMCARD	(SIMPAD_CS3_GPIO_BASE + 15)
+
+#define SIMPAD_CS3_PCMCIA_BVD1		(SIMPAD_CS3_GPIO_BASE + 16)
+#define SIMPAD_CS3_PCMCIA_BVD2		(SIMPAD_CS3_GPIO_BASE + 17)
+#define SIMPAD_CS3_PCMCIA_VS1		(SIMPAD_CS3_GPIO_BASE + 18)
+#define SIMPAD_CS3_PCMCIA_VS2		(SIMPAD_CS3_GPIO_BASE + 19)
+#define SIMPAD_CS3_LOCK_IND		(SIMPAD_CS3_GPIO_BASE + 20)
+#define SIMPAD_CS3_CHARGING_STATE	(SIMPAD_CS3_GPIO_BASE + 21)
+#define SIMPAD_CS3_PCMCIA_SHORT		(SIMPAD_CS3_GPIO_BASE + 22)
+#define SIMPAD_CS3_GPIO_23		(SIMPAD_CS3_GPIO_BASE + 23)
 
-#define CS3BUSTYPE unsigned volatile long
 #define CS3_BASE        0xf1000000
 
-#define VCC_5V_EN       0x0001 // For 5V PCMCIA
-#define VCC_3V_EN       0x0002 // FOR 3.3V PCMCIA
-#define EN1             0x0004 // This is only for EPROM's
-#define EN0             0x0008 // Both should be enable for 3.3V or 5V
-#define DISPLAY_ON      0x0010
-#define PCMCIA_BUFF_DIS 0x0020
-#define MQ_RESET        0x0040
-#define PCMCIA_RESET    0x0080
-#define DECT_POWER_ON   0x0100
-#define IRDA_SD         0x0200 // Shutdown for powersave
-#define RS232_ON        0x0400
-#define SD_MEDIAQ       0x0800 // Shutdown for powersave
-#define LED2_ON         0x1000
-#define IRDA_MODE       0x2000 // Fast/Slow IrDA mode
-#define ENABLE_5V       0x4000 // Enable 5V circuit
-#define RESET_SIMCARD   0x8000
+long simpad_get_cs3_ro(void);
+long simpad_get_cs3_shadow(void);
+void simpad_set_cs3_bit(int value);
+void simpad_clear_cs3_bit(int value);
 
-#define RS232_ENABLE    0x0440
-#define PCMCIAMASK      0x402f
+#define VCC_5V_EN	0x0001 /* For 5V PCMCIA */
+#define VCC_3V_EN	0x0002 /* FOR 3.3V PCMCIA */
+#define EN1		0x0004 /* This is only for EPROM's */
+#define EN0		0x0008 /* Both should be enable for 3.3V or 5V */
+#define DISPLAY_ON	0x0010
+#define PCMCIA_BUFF_DIS	0x0020
+#define MQ_RESET	0x0040
+#define PCMCIA_RESET	0x0080
+#define DECT_POWER_ON	0x0100
+#define IRDA_SD		0x0200 /* Shutdown for powersave */
+#define RS232_ON	0x0400
+#define SD_MEDIAQ	0x0800 /* Shutdown for powersave */
+#define LED2_ON		0x1000
+#define IRDA_MODE	0x2000 /* Fast/Slow IrDA mode */
+#define ENABLE_5V	0x4000 /* Enable 5V circuit */
+#define RESET_SIMCARD	0x8000
 
+#define PCMCIA_BVD1	0x01
+#define PCMCIA_BVD2	0x02
+#define PCMCIA_VS1	0x04
+#define PCMCIA_VS2	0x08
+#define LOCK_IND	0x10
+#define CHARGING_STATE	0x20
+#define PCMCIA_SHORT	0x40
 
+/*--- Battery ---*/
 struct simpad_battery {
 	unsigned char ac_status;	/* line connected yes/no */
 	unsigned char status;		/* battery loading yes/no */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/jornada720.c linux-libre-3.2-gnu/arch/arm/mach-sa1100/jornada720.c
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/jornada720.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/jornada720.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <mach/hardware.h>
 #include <asm/hardware/sa1111.h>
 #include <asm/irq.h>
+#include <asm/page.h>
 #include <asm/mach-types.h>
 #include <asm/setup.h>
 #include <asm/mach/arch.h>
@@ -364,7 +365,7 @@
 
 MACHINE_START(JORNADA720, "HP Jornada 720")
 	/* Maintainer: Kristoffer Ericson <Kristoffer.Ericson@gmail.com> */
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= jornada720_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/lart.c linux-libre-3.2-gnu/arch/arm/mach-sa1100/lart.c
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/lart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/lart.c	2012-01-04 18:55:44.000000000 -0500
@@ -61,7 +61,7 @@
 }
 
 MACHINE_START(LART, "LART")
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= lart_map_io,
 	.init_irq	= sa1100_init_irq,
 	.init_machine	= lart_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/leds.c linux-libre-3.2-gnu/arch/arm/mach-sa1100/leds.c
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/leds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/leds.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,8 +42,6 @@
 		leds_event = adsbitsy_leds_event;
 	if (machine_is_pt_system3())
 		leds_event = system3_leds_event;
-	if (machine_is_simpad())
-		leds_event = simpad_leds_event; /* what about machine registry? including led, apm... -zecke */
 
 	leds_event(led_start);
 	return 0;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/leds.h linux-libre-3.2-gnu/arch/arm/mach-sa1100/leds.h
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/leds.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/leds.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,4 +11,3 @@
 extern void graphicsmaster_leds_event(led_event_t evt);
 extern void adsbitsy_leds_event(led_event_t evt);
 extern void system3_leds_event(led_event_t evt);
-extern void simpad_leds_event(led_event_t evt);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/leds-simpad.c linux-libre-3.2-gnu/arch/arm/mach-sa1100/leds-simpad.c
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/leds-simpad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/leds-simpad.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,100 +0,0 @@
-/*
- * linux/arch/arm/mach-sa1100/leds-simpad.c
- *
- * Author: Juergen Messerer <juergen.messerer@siemens.ch>
- */
-#include <linux/init.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-#include <asm/system.h>
-#include <mach/simpad.h>
-
-#include "leds.h"
-
-
-#define LED_STATE_ENABLED	1
-#define LED_STATE_CLAIMED	2
-
-static unsigned int led_state;
-static unsigned int hw_led_state;
-
-#define	LED_GREEN	(1)
-#define	LED_MASK	(1)
-
-extern void set_cs3_bit(int value);
-extern void clear_cs3_bit(int value);     
-
-void simpad_leds_event(led_event_t evt)
-{
-	switch (evt)
-	{
-	case led_start:
-	        hw_led_state = LED_GREEN;
-		led_state = LED_STATE_ENABLED;
-		break;
-
-	case led_stop:
-		led_state &= ~LED_STATE_ENABLED;
-		break;
-
-	case led_claim:
-		led_state |= LED_STATE_CLAIMED;
-		hw_led_state = LED_GREEN;
-		break;
-
-	case led_release:
-		led_state &= ~LED_STATE_CLAIMED;
-		hw_led_state = LED_GREEN;
-		break;
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state ^= LED_GREEN;
-		break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-	case led_idle_start:
-		break;
-
-	case led_idle_end:
-		break;
-#endif
-
-	case led_halted:
-		break;
-
-	case led_green_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= LED_GREEN;
-		break;
-
-	case led_green_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~LED_GREEN;
-		break;
-
-	case led_amber_on:
-		break;
-
-	case led_amber_off:
-		break;
-
-	case led_red_on:
-		break;
-
-	case led_red_off:
-		break;
-
-	default:
-		break;
-	}
-
-	if  (led_state & LED_STATE_ENABLED)
-		set_cs3_bit(LED2_ON);
-	else 
-	        clear_cs3_bit(LED2_ON);
-}
-
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/Makefile linux-libre-3.2-gnu/arch/arm/mach-sa1100/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := clock.o generic.o gpio.o irq.o dma.o time.o #nmi-oopser.o
+obj-y := clock.o generic.o irq.o dma.o time.o #nmi-oopser.o
 obj-m :=
 obj-n :=
 obj-  :=
@@ -45,7 +45,6 @@
 obj-$(CONFIG_SA1100_SHANNON)		+= shannon.o
 
 obj-$(CONFIG_SA1100_SIMPAD)		+= simpad.o
-led-$(CONFIG_SA1100_SIMPAD)		+= leds-simpad.o
 
 # LEDs support
 obj-$(CONFIG_LEDS) += $(led-y)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-sa1100/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
-   zreladdr-y	:= 0xc0008000
-ifeq ($(CONFIG_ARCH_SA1100),y)
-   zreladdr-$(CONFIG_SA1111)		:= 0xc0208000
+ifeq ($(CONFIG_SA1111),y)
+   zreladdr-y	+= 0xc0208000
+else
+   zreladdr-y	+= 0xc0008000
 endif
 params_phys-y	:= 0xc0000100
 initrd_phys-y	:= 0xc0800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/nanoengine.c linux-libre-3.2-gnu/arch/arm/mach-sa1100/nanoengine.c
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/nanoengine.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/nanoengine.c	2012-01-04 18:55:44.000000000 -0500
@@ -111,7 +111,7 @@
 }
 
 MACHINE_START(NANOENGINE, "BSE nanoEngine")
-	.boot_params	= 0xc0000000,
+	.atag_offset	= 0x100,
 	.map_io		= nanoengine_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/shannon.c linux-libre-3.2-gnu/arch/arm/mach-sa1100/shannon.c
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/shannon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/shannon.c	2012-01-04 18:55:44.000000000 -0500
@@ -82,7 +82,7 @@
 }
 
 MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)")
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= shannon_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-sa1100/simpad.c linux-libre-3.2-gnu/arch/arm/mach-sa1100/simpad.c
--- linux-libre-3.1-gnu/arch/arm/mach-sa1100/simpad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-sa1100/simpad.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
+#include <linux/gpio.h>
 
 #include <asm/irq.h>
 #include <mach/hardware.h>
@@ -28,35 +29,92 @@
 
 #include <linux/serial_core.h>
 #include <linux/ioport.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/leds.h>
+#include <linux/i2c-gpio.h>
 
 #include "generic.h"
 
-long cs3_shadow;
+/*
+ * CS3 support
+ */
 
-long get_cs3_shadow(void)
+static long cs3_shadow;
+static spinlock_t cs3_lock;
+static struct gpio_chip cs3_gpio;
+
+long simpad_get_cs3_ro(void)
+{
+	return readl(CS3_BASE);
+}
+EXPORT_SYMBOL(simpad_get_cs3_ro);
+
+long simpad_get_cs3_shadow(void)
 {
 	return cs3_shadow;
 }
+EXPORT_SYMBOL(simpad_get_cs3_shadow);
 
-void set_cs3(long value)
+static void __simpad_write_cs3(void)
 {
-	*(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow = value;
+	writel(cs3_shadow, CS3_BASE);
 }
 
-void set_cs3_bit(int value)
+void simpad_set_cs3_bit(int value)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&cs3_lock, flags);
 	cs3_shadow |= value;
-	*(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow;
+	__simpad_write_cs3();
+	spin_unlock_irqrestore(&cs3_lock, flags);
 }
+EXPORT_SYMBOL(simpad_set_cs3_bit);
 
-void clear_cs3_bit(int value)
+void simpad_clear_cs3_bit(int value)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&cs3_lock, flags);
 	cs3_shadow &= ~value;
-	*(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow;
+	__simpad_write_cs3();
+	spin_unlock_irqrestore(&cs3_lock, flags);
 }
+EXPORT_SYMBOL(simpad_clear_cs3_bit);
 
-EXPORT_SYMBOL(set_cs3_bit);
-EXPORT_SYMBOL(clear_cs3_bit);
+static void cs3_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	if (offset > 15)
+		return;
+	if (value)
+		simpad_set_cs3_bit(1 << offset);
+	else
+		simpad_clear_cs3_bit(1 << offset);
+};
+
+static int cs3_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset > 15)
+		return simpad_get_cs3_ro() & (1 << (offset - 16));
+	return simpad_get_cs3_shadow() & (1 << offset);
+};
+
+static int cs3_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset > 15)
+		return 0;
+	return -EINVAL;
+};
+
+static int cs3_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+	int value)
+{
+	if (offset > 15)
+		return -EINVAL;
+	cs3_gpio_set(chip, offset, value);
+	return 0;
+};
 
 static struct map_desc simpad_io_desc[] __initdata = {
 	{	/* MQ200 */
@@ -64,9 +122,9 @@
 		.pfn		= __phys_to_pfn(0x4b800000),
 		.length		= 0x00800000,
 		.type		= MT_DEVICE
-	}, {	/* Paules CS3, write only */
-		.virtual	=  0xf1000000,
-		.pfn		= __phys_to_pfn(0x18000000),
+	}, {	/* Simpad CS3 */
+		.virtual	= CS3_BASE,
+		.pfn		= __phys_to_pfn(SA1100_CS3_PHYS),
 		.length		= 0x00100000,
 		.type		= MT_DEVICE
 	},
@@ -78,12 +136,12 @@
 	if (port->mapbase == (u_int)&Ser1UTCR0) {
 		if (state)
 		{
-			clear_cs3_bit(RS232_ON);
-			clear_cs3_bit(DECT_POWER_ON);
+			simpad_clear_cs3_bit(RS232_ON);
+			simpad_clear_cs3_bit(DECT_POWER_ON);
 		}else
 		{
-			set_cs3_bit(RS232_ON);
-			set_cs3_bit(DECT_POWER_ON);
+			simpad_set_cs3_bit(RS232_ON);
+			simpad_set_cs3_bit(DECT_POWER_ON);
 		}
 	}
 }
@@ -132,6 +190,7 @@
 static struct mcp_plat_data simpad_mcp_data = {
 	.mccr0		= MCCR0_ADM,
 	.sclk_rate	= 11981000,
+	.gpio_base	= SIMPAD_UCB1X00_GPIO_BASE,
 };
 
 
@@ -142,9 +201,10 @@
 
 	iotable_init(simpad_io_desc, ARRAY_SIZE(simpad_io_desc));
 
-	set_cs3_bit (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON |
-		      ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON);
-
+	/* Initialize CS3 */
+	cs3_shadow = (EN1 | EN0 | LED2_ON | DISPLAY_ON |
+		RS232_ON | ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON);
+	__simpad_write_cs3(); /* Spinlocks not yet initialized */
 
         sa1100_register_uart_fns(&simpad_port_fns);
 	sa1100_register_uart(0, 3);  /* serial interface */
@@ -170,13 +230,14 @@
 
 static void simpad_power_off(void)
 {
-	local_irq_disable(); // was cli
-	set_cs3(0x800);        /* only SD_MEDIAQ */
+	local_irq_disable();
+	cs3_shadow = SD_MEDIAQ;
+	__simpad_write_cs3(); /* Bypass spinlock here */
 
 	/* disable internal oscillator, float CS lines */
 	PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS);
-	/* enable wake-up on GPIO0 (Assabet...) */
-	PWER = GFER = GRER = 1;
+	/* enable wake-up on GPIO0 */
+	PWER = GFER = GRER = PWER_GPIO0;
 	/*
 	 * set scratchpad to zero, just in case it is used as a
 	 * restart address by the bootloader.
@@ -192,6 +253,91 @@
 
 }
 
+/*
+ * gpio_keys
+*/
+
+static struct gpio_keys_button simpad_button_table[] = {
+	{ KEY_POWER, IRQ_GPIO_POWER_BUTTON, 1, "power button" },
+};
+
+static struct gpio_keys_platform_data simpad_keys_data = {
+	.buttons = simpad_button_table,
+	.nbuttons = ARRAY_SIZE(simpad_button_table),
+};
+
+static struct platform_device simpad_keys = {
+	.name = "gpio-keys",
+	.dev = {
+		.platform_data = &simpad_keys_data,
+	},
+};
+
+static struct gpio_keys_button simpad_polled_button_table[] = {
+	{ KEY_PROG1, SIMPAD_UCB1X00_GPIO_PROG1, 1, "prog1 button" },
+	{ KEY_PROG2, SIMPAD_UCB1X00_GPIO_PROG2, 1, "prog2 button" },
+	{ KEY_UP,    SIMPAD_UCB1X00_GPIO_UP,    1, "up button" },
+	{ KEY_DOWN,  SIMPAD_UCB1X00_GPIO_DOWN,  1, "down button" },
+	{ KEY_LEFT,  SIMPAD_UCB1X00_GPIO_LEFT,  1, "left button" },
+	{ KEY_RIGHT, SIMPAD_UCB1X00_GPIO_RIGHT, 1, "right button" },
+};
+
+static struct gpio_keys_platform_data simpad_polled_keys_data = {
+	.buttons = simpad_polled_button_table,
+	.nbuttons = ARRAY_SIZE(simpad_polled_button_table),
+	.poll_interval = 50,
+};
+
+static struct platform_device simpad_polled_keys = {
+	.name = "gpio-keys-polled",
+	.dev = {
+		.platform_data = &simpad_polled_keys_data,
+	},
+};
+
+/*
+ * GPIO LEDs
+ */
+
+static struct gpio_led simpad_leds[] = {
+	{
+		.name = "simpad:power",
+		.gpio = SIMPAD_CS3_LED2_ON,
+		.active_low = 0,
+		.default_trigger = "default-on",
+	},
+};
+
+static struct gpio_led_platform_data simpad_led_data = {
+	.num_leds = ARRAY_SIZE(simpad_leds),
+	.leds = simpad_leds,
+};
+
+static struct platform_device simpad_gpio_leds = {
+	.name = "leds-gpio",
+	.id = 0,
+	.dev = {
+		.platform_data = &simpad_led_data,
+	},
+};
+
+/*
+ * i2c
+ */
+static struct i2c_gpio_platform_data simpad_i2c_data = {
+	.sda_pin = GPIO_GPIO21,
+	.scl_pin = GPIO_GPIO25,
+	.udelay = 10,
+	.timeout = HZ,
+};
+
+static struct platform_device simpad_i2c = {
+	.name = "i2c-gpio",
+	.id = 0,
+	.dev = {
+		.platform_data = &simpad_i2c_data,
+	},
+};
 
 /*
  * MediaQ Video Device
@@ -202,7 +348,11 @@
 };
 
 static struct platform_device *devices[] __initdata = {
-	&simpad_mq200fb
+	&simpad_keys,
+	&simpad_polled_keys,
+	&simpad_mq200fb,
+	&simpad_gpio_leds,
+	&simpad_i2c,
 };
 
 
@@ -211,6 +361,19 @@
 {
 	int ret;
 
+	spin_lock_init(&cs3_lock);
+
+	cs3_gpio.label = "simpad_cs3";
+	cs3_gpio.base = SIMPAD_CS3_GPIO_BASE;
+	cs3_gpio.ngpio = 24;
+	cs3_gpio.set = cs3_gpio_set;
+	cs3_gpio.get = cs3_gpio_get;
+	cs3_gpio.direction_input = cs3_gpio_direction_input;
+	cs3_gpio.direction_output = cs3_gpio_direction_output;
+	ret = gpiochip_add(&cs3_gpio);
+	if (ret)
+		printk(KERN_WARNING "simpad: Unable to register cs3 GPIO device");
+
 	pm_power_off = simpad_power_off;
 
 	sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
@@ -229,7 +392,7 @@
 
 MACHINE_START(SIMPAD, "Simpad")
 	/* Maintainer: Holger Freyther */
-	.boot_params	= 0xc0000100,
+	.atag_offset	= 0x100,
 	.map_io		= simpad_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shark/core.c linux-libre-3.2-gnu/arch/arm/mach-shark/core.c
--- linux-libre-3.1-gnu/arch/arm/mach-shark/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shark/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -152,7 +152,7 @@
 
 MACHINE_START(SHARK, "Shark")
 	/* Maintainer: Alexander Schulz */
-	.boot_params	= 0x08003000,
+	.atag_offset	= 0x3000,
 	.map_io		= shark_map_io,
 	.init_irq	= shark_init_irq,
 	.timer		= &shark_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shark/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-shark/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-shark/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shark/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *
 */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0xe0000000
 		orr	\rp, \rp, #0x000003f8
 		mov	\rv, \rp
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shark/leds.c linux-libre-3.2-gnu/arch/arm/mach-shark/leds.c
--- linux-libre-3.1-gnu/arch/arm/mach-shark/leds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shark/leds.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,7 +36,7 @@
 static short hw_led_state;
 static short saved_state;
 
-static DEFINE_SPINLOCK(leds_lock);
+static DEFINE_RAW_SPINLOCK(leds_lock);
 
 short sequoia_read(int addr) {
   outw(addr,0x24);
@@ -52,7 +52,7 @@
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&leds_lock, flags);
+	raw_spin_lock_irqsave(&leds_lock, flags);
 
 	hw_led_state = sequoia_read(0x09);
 
@@ -144,7 +144,7 @@
 	if  (led_state & LED_STATE_ENABLED)
 		sequoia_write(hw_led_state,0x09);
 
-	spin_unlock_irqrestore(&leds_lock, flags);
+	raw_spin_unlock_irqrestore(&leds_lock, flags);
 }
 
 static int __init leds_init(void)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shark/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-shark/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-shark/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shark/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,2 +1,2 @@
-   zreladdr-y	:= 0x08008000
+   zreladdr-y	+= 0x08008000
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/board-ag5evm.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/board-ag5evm.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/board-ag5evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/board-ag5evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
 #include <linux/sh_clk.h>
+#include <linux/dma-mapping.h>
 #include <video/sh_mobile_lcdc.h>
 #include <video/sh_mipi_dsi.h>
 #include <sound/sh_fsi.h>
@@ -58,7 +59,7 @@
 		.flags		= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start		= gic_spi(33), /* PINT1 */
+		.start		= SH73A0_PINT0_IRQ(2), /* PINTA2 */
 		.flags		= IORESOURCE_IRQ,
 	},
 };
@@ -338,6 +339,18 @@
 	},
 };
 
+/* SDHI0 */
+static irqreturn_t ag5evm_sdhi0_gpio_cd(int irq, void *arg)
+{
+	struct device *dev = arg;
+	struct sh_mobile_sdhi_info *info = dev->platform_data;
+	struct tmio_mmc_data *pdata = info->pdata;
+
+	tmio_mmc_cd_wakeup(pdata);
+
+	return IRQ_HANDLED;
+}
+
 static struct sh_mobile_sdhi_info sdhi0_info = {
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
@@ -354,14 +367,17 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
+		.name	= SH_MOBILE_SDHI_IRQ_CARD_DETECT,
 		.start	= gic_spi(83),
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
+		.name	= SH_MOBILE_SDHI_IRQ_SDCARD,
 		.start	= gic_spi(84),
 		.flags	= IORESOURCE_IRQ,
 	},
 	[3] = {
+		.name	= SH_MOBILE_SDHI_IRQ_SDIO,
 		.start	= gic_spi(85),
 		.flags	= IORESOURCE_IRQ,
 	},
@@ -397,14 +413,17 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
+		.name	= SH_MOBILE_SDHI_IRQ_CARD_DETECT,
 		.start	= gic_spi(87),
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
+		.name	= SH_MOBILE_SDHI_IRQ_SDCARD,
 		.start	= gic_spi(88),
 		.flags	= IORESOURCE_IRQ,
 	},
 	[3] = {
+		.name	= SH_MOBILE_SDHI_IRQ_SDIO,
 		.start	= gic_spi(89),
 		.flags	= IORESOURCE_IRQ,
 	},
@@ -447,25 +466,14 @@
 static void __init ag5evm_map_io(void)
 {
 	iotable_init(ag5evm_io_desc, ARRAY_SIZE(ag5evm_io_desc));
+	/* DMA memory at 0xf6000000 - 0xffdfffff */
+	init_consistent_dma_size(158 << 20);
 
 	/* setup early devices and console here as well */
 	sh73a0_add_early_devices();
 	shmobile_setup_console();
 }
 
-#define PINTC_ADDR	0xe6900000
-#define PINTER0A	(PINTC_ADDR + 0xa0)
-#define PINTCR0A	(PINTC_ADDR + 0xb0)
-
-void __init ag5evm_init_irq(void)
-{
-	sh73a0_init_irq();
-
-	/* setup PINT: enable PINTA2 as active low */
-	__raw_writel(__raw_readl(PINTER0A) | (1<<29), PINTER0A);
-	__raw_writew(__raw_readw(PINTCR0A) | (2<<10), PINTCR0A);
-}
-
 #define DSI0PHYCR	0xe615006c
 
 static void __init ag5evm_init(void)
@@ -507,14 +515,14 @@
 	/* enable MMCIF */
 	gpio_request(GPIO_FN_MMCCLK0, NULL);
 	gpio_request(GPIO_FN_MMCCMD0_PU, NULL);
-	gpio_request(GPIO_FN_MMCD0_0, NULL);
-	gpio_request(GPIO_FN_MMCD0_1, NULL);
-	gpio_request(GPIO_FN_MMCD0_2, NULL);
-	gpio_request(GPIO_FN_MMCD0_3, NULL);
-	gpio_request(GPIO_FN_MMCD0_4, NULL);
-	gpio_request(GPIO_FN_MMCD0_5, NULL);
-	gpio_request(GPIO_FN_MMCD0_6, NULL);
-	gpio_request(GPIO_FN_MMCD0_7, NULL);
+	gpio_request(GPIO_FN_MMCD0_0_PU, NULL);
+	gpio_request(GPIO_FN_MMCD0_1_PU, NULL);
+	gpio_request(GPIO_FN_MMCD0_2_PU, NULL);
+	gpio_request(GPIO_FN_MMCD0_3_PU, NULL);
+	gpio_request(GPIO_FN_MMCD0_4_PU, NULL);
+	gpio_request(GPIO_FN_MMCD0_5_PU, NULL);
+	gpio_request(GPIO_FN_MMCD0_6_PU, NULL);
+	gpio_request(GPIO_FN_MMCD0_7_PU, NULL);
 	gpio_request(GPIO_PORT208, NULL); /* Reset */
 	gpio_direction_output(GPIO_PORT208, 1);
 
@@ -561,6 +569,13 @@
 	gpio_request(GPIO_FN_SDHID0_1, NULL);
 	gpio_request(GPIO_FN_SDHID0_0, NULL);
 
+	if (!request_irq(intcs_evt2irq(0x3c0), ag5evm_sdhi0_gpio_cd,
+			 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			 "sdhi0 cd", &sdhi0_device.dev))
+		sdhi0_info.tmio_flags |= TMIO_MMC_HAS_COLD_CD;
+	else
+		pr_warn("Unable to setup SDHI0 GPIO IRQ\n");
+
 	/* enable SDHI1 on CN4 [WLAN I/F] */
 	gpio_request(GPIO_FN_SDHICLK1, NULL);
 	gpio_request(GPIO_FN_SDHICMD1_PU, NULL);
@@ -592,7 +607,8 @@
 
 MACHINE_START(AG5EVM, "ag5evm")
 	.map_io		= ag5evm_map_io,
-	.init_irq	= ag5evm_init_irq,
+	.nr_irqs	= NR_IRQS_LEGACY,
+	.init_irq	= sh73a0_init_irq,
 	.handle_irq	= shmobile_handle_irq_gic,
 	.init_machine	= ag5evm_init,
 	.timer		= &ag5evm_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/board-ap4evb.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/board-ap4evb.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/board-ap4evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/board-ap4evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,8 @@
 #include <linux/leds.h>
 #include <linux/input/sh_keysc.h>
 #include <linux/usb/r8a66597.h>
+#include <linux/pm_clock.h>
+#include <linux/dma-mapping.h>
 
 #include <media/sh_mobile_ceu.h>
 #include <media/sh_mobile_csi2.h>
@@ -198,8 +200,8 @@
 
 static struct resource nor_flash_resources[] = {
 	[0]	= {
-		.start	= 0x00000000,
-		.end	= 0x08000000 - 1,
+		.start	= 0x20000000, /* CS0 shadow instead of regular CS0 */
+		.end	= 0x28000000 - 1, /* needed by USB MASK ROM boot */
 		.flags	= IORESOURCE_MEM,
 	}
 };
@@ -931,7 +933,7 @@
 static struct sh_csi2_client_config csi2_clients[] = {
 	{
 		.phy		= SH_CSI2_PHY_MAIN,
-		.lanes		= 3,
+		.lanes		= 0,		/* default: 2 lanes */
 		.channel	= 0,
 		.pdev		= &ap4evb_camera,
 	},
@@ -1170,6 +1172,8 @@
 static void __init ap4evb_map_io(void)
 {
 	iotable_init(ap4evb_io_desc, ARRAY_SIZE(ap4evb_io_desc));
+	/* DMA memory at 0xf6000000 - 0xffdfffff */
+	init_consistent_dma_size(158 << 20);
 
 	/* setup early devices and console here as well */
 	sh7372_add_early_devices();
@@ -1408,6 +1412,11 @@
 	sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
 	sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
 
+	sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device);
+
 	hdmi_init_pm_clock();
 	fsi_init_pm_clock();
 	sh7372_pm_init();
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/board-g3evm.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/board-g3evm.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/board-g3evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/board-g3evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 #include <linux/gpio.h>
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
+#include <linux/dma-mapping.h>
 #include <mach/sh7367.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
@@ -260,6 +261,8 @@
 static void __init g3evm_map_io(void)
 {
 	iotable_init(g3evm_io_desc, ARRAY_SIZE(g3evm_io_desc));
+	/* DMA memory at 0xf6000000 - 0xffdfffff */
+	init_consistent_dma_size(158 << 20);
 
 	/* setup early devices and console here as well */
 	sh7367_add_early_devices();
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/board-g4evm.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/board-g4evm.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/board-g4evm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/board-g4evm.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/gpio.h>
+#include <linux/dma-mapping.h>
 #include <mach/sh7377.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
@@ -274,6 +275,8 @@
 static void __init g4evm_map_io(void)
 {
 	iotable_init(g4evm_io_desc, ARRAY_SIZE(g4evm_io_desc));
+	/* DMA memory at 0xf6000000 - 0xffdfffff */
+	init_consistent_dma_size(158 << 20);
 
 	/* setup early devices and console here as well */
 	sh7377_add_early_devices();
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/board-kota2.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/board-kota2.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/board-kota2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/board-kota2.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,557 @@
+/*
+ * kota2 board support
+ *
+ * Copyright (C) 2011  Renesas Solutions Corp.
+ * Copyright (C) 2011  Magnus Damm
+ * Copyright (C) 2010  Takashi Yoshii <yoshii.takashi.zj@renesas.com>
+ * Copyright (C) 2009  Yoshihiro Shimoda <shimoda.yoshihiro@renesas.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/smsc911x.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/input/sh_keysc.h>
+#include <linux/gpio_keys.h>
+#include <linux/leds.h>
+#include <linux/platform_data/leds-renesas-tpu.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mmcif.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
+#include <mach/hardware.h>
+#include <mach/sh73a0.h>
+#include <mach/common.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/traps.h>
+
+/* SMSC 9220 */
+static struct resource smsc9220_resources[] = {
+	[0] = {
+		.start		= 0x14000000, /* CS5A */
+		.end		= 0x140000ff, /* A1->A7 */
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= SH73A0_PINT0_IRQ(2), /* PINTA2 */
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct smsc911x_platform_config smsc9220_platdata = {
+	.flags		= SMSC911X_USE_32BIT, /* 32-bit SW on 16-bit HW bus */
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+};
+
+static struct platform_device eth_device = {
+	.name		= "smsc911x",
+	.id		= 0,
+	.dev  = {
+		.platform_data = &smsc9220_platdata,
+	},
+	.resource	= smsc9220_resources,
+	.num_resources	= ARRAY_SIZE(smsc9220_resources),
+};
+
+/* KEYSC */
+static struct sh_keysc_info keysc_platdata = {
+	.mode		= SH_KEYSC_MODE_6,
+	.scan_timing	= 3,
+	.delay		= 100,
+	.keycodes	= {
+		KEY_NUMERIC_STAR, KEY_NUMERIC_0, KEY_NUMERIC_POUND,
+		0, 0, 0, 0, 0,
+		KEY_NUMERIC_7, KEY_NUMERIC_8, KEY_NUMERIC_9,
+		0, KEY_DOWN, 0, 0, 0,
+		KEY_NUMERIC_4, KEY_NUMERIC_5, KEY_NUMERIC_6,
+		KEY_LEFT, KEY_ENTER, KEY_RIGHT, 0, 0,
+		KEY_NUMERIC_1, KEY_NUMERIC_2, KEY_NUMERIC_3,
+		0, KEY_UP, 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,
+	},
+};
+
+static struct resource keysc_resources[] = {
+	[0] = {
+		.name	= "KEYSC",
+		.start	= 0xe61b0000,
+		.end	= 0xe61b0098 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gic_spi(71),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device keysc_device = {
+	.name		= "sh_keysc",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(keysc_resources),
+	.resource	= keysc_resources,
+	.dev		= {
+		.platform_data	= &keysc_platdata,
+	},
+};
+
+/* GPIO KEY */
+#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
+
+static struct gpio_keys_button gpio_buttons[] = {
+	GPIO_KEY(KEY_VOLUMEUP, GPIO_PORT56, "+"), /* S2: VOL+ [IRQ9] */
+	GPIO_KEY(KEY_VOLUMEDOWN, GPIO_PORT54, "-"), /* S3: VOL- [IRQ10] */
+	GPIO_KEY(KEY_MENU, GPIO_PORT27, "Menu"), /* S4: MENU [IRQ30] */
+	GPIO_KEY(KEY_HOMEPAGE, GPIO_PORT26, "Home"), /* S5: HOME [IRQ31] */
+	GPIO_KEY(KEY_BACK, GPIO_PORT11, "Back"), /* S6: BACK [IRQ0] */
+	GPIO_KEY(KEY_PHONE, GPIO_PORT238, "Tel"), /* S7: TEL [IRQ11] */
+	GPIO_KEY(KEY_POWER, GPIO_PORT239, "C1"), /* S8: CAM [IRQ13] */
+	GPIO_KEY(KEY_MAIL, GPIO_PORT224, "Mail"), /* S9: MAIL [IRQ3] */
+	/* Omitted button "C3?": GPIO_PORT223 - S10: CUST [IRQ8] */
+	GPIO_KEY(KEY_CAMERA, GPIO_PORT164, "C2"), /* S11: CAM_HALF [IRQ25] */
+	/* Omitted button "?": GPIO_PORT152 - S12: CAM_FULL [No IRQ] */
+};
+
+static struct gpio_keys_platform_data gpio_key_info = {
+	.buttons        = gpio_buttons,
+	.nbuttons       = ARRAY_SIZE(gpio_buttons),
+	.poll_interval  = 250, /* polled for now */
+};
+
+static struct platform_device gpio_keys_device = {
+	.name   = "gpio-keys-polled", /* polled for now */
+	.id     = -1,
+	.dev    = {
+		.platform_data  = &gpio_key_info,
+	},
+};
+
+/* GPIO LED */
+#define GPIO_LED(n, g) { .name = n, .gpio = g }
+
+static struct gpio_led gpio_leds[] = {
+	GPIO_LED("G", GPIO_PORT20), /* PORT20 [GPO0] -> LED7 -> "G" */
+	GPIO_LED("H", GPIO_PORT21), /* PORT21 [GPO1] -> LED8 -> "H" */
+	GPIO_LED("J", GPIO_PORT22), /* PORT22 [GPO2] -> LED9 -> "J" */
+};
+
+static struct gpio_led_platform_data gpio_leds_info = {
+	.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_info,
+	},
+};
+
+/* TPU LED */
+static struct led_renesas_tpu_config led_renesas_tpu12_pdata = {
+	.name		= "V2513",
+	.pin_gpio_fn	= GPIO_FN_TPU1TO2,
+	.pin_gpio	= GPIO_PORT153,
+	.channel_offset = 0x90,
+	.timer_bit = 2,
+	.max_brightness = 1000,
+};
+
+static struct resource tpu12_resources[] = {
+	[0] = {
+		.name	= "TPU12",
+		.start	= 0xe6610090,
+		.end	= 0xe66100b5,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device leds_tpu12_device = {
+	.name = "leds-renesas-tpu",
+	.id = 12,
+	.dev = {
+		.platform_data  = &led_renesas_tpu12_pdata,
+	},
+	.num_resources	= ARRAY_SIZE(tpu12_resources),
+	.resource	= tpu12_resources,
+};
+
+static struct led_renesas_tpu_config led_renesas_tpu41_pdata = {
+	.name		= "V2514",
+	.pin_gpio_fn	= GPIO_FN_TPU4TO1,
+	.pin_gpio	= GPIO_PORT199,
+	.channel_offset = 0x50,
+	.timer_bit = 1,
+	.max_brightness = 1000,
+};
+
+static struct resource tpu41_resources[] = {
+	[0] = {
+		.name	= "TPU41",
+		.start	= 0xe6640050,
+		.end	= 0xe6640075,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device leds_tpu41_device = {
+	.name = "leds-renesas-tpu",
+	.id = 41,
+	.dev = {
+		.platform_data  = &led_renesas_tpu41_pdata,
+	},
+	.num_resources	= ARRAY_SIZE(tpu41_resources),
+	.resource	= tpu41_resources,
+};
+
+static struct led_renesas_tpu_config led_renesas_tpu21_pdata = {
+	.name		= "V2515",
+	.pin_gpio_fn	= GPIO_FN_TPU2TO1,
+	.pin_gpio	= GPIO_PORT197,
+	.channel_offset = 0x50,
+	.timer_bit = 1,
+	.max_brightness = 1000,
+};
+
+static struct resource tpu21_resources[] = {
+	[0] = {
+		.name	= "TPU21",
+		.start	= 0xe6620050,
+		.end	= 0xe6620075,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device leds_tpu21_device = {
+	.name = "leds-renesas-tpu",
+	.id = 21,
+	.dev = {
+		.platform_data  = &led_renesas_tpu21_pdata,
+	},
+	.num_resources	= ARRAY_SIZE(tpu21_resources),
+	.resource	= tpu21_resources,
+};
+
+static struct led_renesas_tpu_config led_renesas_tpu30_pdata = {
+	.name		= "KEYLED",
+	.pin_gpio_fn	= GPIO_FN_TPU3TO0,
+	.pin_gpio	= GPIO_PORT163,
+	.channel_offset = 0x10,
+	.timer_bit = 0,
+	.max_brightness = 1000,
+};
+
+static struct resource tpu30_resources[] = {
+	[0] = {
+		.name	= "TPU30",
+		.start	= 0xe6630010,
+		.end	= 0xe6630035,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device leds_tpu30_device = {
+	.name = "leds-renesas-tpu",
+	.id = 30,
+	.dev = {
+		.platform_data  = &led_renesas_tpu30_pdata,
+	},
+	.num_resources	= ARRAY_SIZE(tpu30_resources),
+	.resource	= tpu30_resources,
+};
+
+/* MMCIF */
+static struct resource mmcif_resources[] = {
+	[0] = {
+		.name   = "MMCIF",
+		.start  = 0xe6bd0000,
+		.end    = 0xe6bd00ff,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = gic_spi(140),
+		.flags  = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start  = gic_spi(141),
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct sh_mmcif_plat_data mmcif_info = {
+	.ocr            = MMC_VDD_165_195,
+	.caps           = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
+};
+
+static struct platform_device mmcif_device = {
+	.name           = "sh_mmcif",
+	.id             = 0,
+	.dev            = {
+		.platform_data          = &mmcif_info,
+	},
+	.num_resources  = ARRAY_SIZE(mmcif_resources),
+	.resource       = mmcif_resources,
+};
+
+/* SDHI0 */
+static struct sh_mobile_sdhi_info sdhi0_info = {
+	.tmio_caps      = MMC_CAP_SD_HIGHSPEED,
+	.tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
+};
+
+static struct resource sdhi0_resources[] = {
+	[0] = {
+		.name   = "SDHI0",
+		.start  = 0xee100000,
+		.end    = 0xee1000ff,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = gic_spi(83),
+		.flags  = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start  = gic_spi(84),
+		.flags  = IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start	= gic_spi(85),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device sdhi0_device = {
+	.name           = "sh_mobile_sdhi",
+	.id             = 0,
+	.num_resources  = ARRAY_SIZE(sdhi0_resources),
+	.resource       = sdhi0_resources,
+	.dev    = {
+		.platform_data  = &sdhi0_info,
+	},
+};
+
+/* SDHI1 */
+static struct sh_mobile_sdhi_info sdhi1_info = {
+	.tmio_caps      = MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ,
+	.tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
+};
+
+static struct resource sdhi1_resources[] = {
+	[0] = {
+		.name   = "SDHI1",
+		.start  = 0xee120000,
+		.end    = 0xee1200ff,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = gic_spi(87),
+		.flags  = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start  = gic_spi(88),
+		.flags  = IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start	= gic_spi(89),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device sdhi1_device = {
+	.name           = "sh_mobile_sdhi",
+	.id             = 1,
+	.num_resources  = ARRAY_SIZE(sdhi1_resources),
+	.resource       = sdhi1_resources,
+	.dev    = {
+		.platform_data  = &sdhi1_info,
+	},
+};
+
+static struct platform_device *kota2_devices[] __initdata = {
+	&eth_device,
+	&keysc_device,
+	&gpio_keys_device,
+	&gpio_leds_device,
+	&leds_tpu12_device,
+	&leds_tpu41_device,
+	&leds_tpu21_device,
+	&leds_tpu30_device,
+	&mmcif_device,
+	&sdhi0_device,
+	&sdhi1_device,
+};
+
+static struct map_desc kota2_io_desc[] __initdata = {
+	/* create a 1:1 entity map for 0xe6xxxxxx
+	 * used by CPGA, INTC and PFC.
+	 */
+	{
+		.virtual	= 0xe6000000,
+		.pfn		= __phys_to_pfn(0xe6000000),
+		.length		= 256 << 20,
+		.type		= MT_DEVICE_NONSHARED
+	},
+};
+
+static void __init kota2_map_io(void)
+{
+	iotable_init(kota2_io_desc, ARRAY_SIZE(kota2_io_desc));
+
+	/* setup early devices and console here as well */
+	sh73a0_add_early_devices();
+	shmobile_setup_console();
+}
+
+static void __init kota2_init(void)
+{
+	sh73a0_pinmux_init();
+
+	/* SCIFA2 (UART2) */
+	gpio_request(GPIO_FN_SCIFA2_TXD1, NULL);
+	gpio_request(GPIO_FN_SCIFA2_RXD1, NULL);
+	gpio_request(GPIO_FN_SCIFA2_RTS1_, NULL);
+	gpio_request(GPIO_FN_SCIFA2_CTS1_, NULL);
+
+	/* SCIFA4 (UART1) */
+	gpio_request(GPIO_FN_SCIFA4_TXD, NULL);
+	gpio_request(GPIO_FN_SCIFA4_RXD, NULL);
+	gpio_request(GPIO_FN_SCIFA4_RTS_, NULL);
+	gpio_request(GPIO_FN_SCIFA4_CTS_, NULL);
+
+	/* SMSC911X */
+	gpio_request(GPIO_FN_D0_NAF0, NULL);
+	gpio_request(GPIO_FN_D1_NAF1, NULL);
+	gpio_request(GPIO_FN_D2_NAF2, NULL);
+	gpio_request(GPIO_FN_D3_NAF3, NULL);
+	gpio_request(GPIO_FN_D4_NAF4, NULL);
+	gpio_request(GPIO_FN_D5_NAF5, NULL);
+	gpio_request(GPIO_FN_D6_NAF6, NULL);
+	gpio_request(GPIO_FN_D7_NAF7, NULL);
+	gpio_request(GPIO_FN_D8_NAF8, NULL);
+	gpio_request(GPIO_FN_D9_NAF9, NULL);
+	gpio_request(GPIO_FN_D10_NAF10, NULL);
+	gpio_request(GPIO_FN_D11_NAF11, NULL);
+	gpio_request(GPIO_FN_D12_NAF12, NULL);
+	gpio_request(GPIO_FN_D13_NAF13, NULL);
+	gpio_request(GPIO_FN_D14_NAF14, NULL);
+	gpio_request(GPIO_FN_D15_NAF15, NULL);
+	gpio_request(GPIO_FN_CS5A_, NULL);
+	gpio_request(GPIO_FN_WE0__FWE, NULL);
+	gpio_request(GPIO_PORT144, NULL); /* PINTA2 */
+	gpio_direction_input(GPIO_PORT144);
+	gpio_request(GPIO_PORT145, NULL); /* RESET */
+	gpio_direction_output(GPIO_PORT145, 1);
+
+	/* KEYSC */
+	gpio_request(GPIO_FN_KEYIN0_PU, NULL);
+	gpio_request(GPIO_FN_KEYIN1_PU, NULL);
+	gpio_request(GPIO_FN_KEYIN2_PU, NULL);
+	gpio_request(GPIO_FN_KEYIN3_PU, NULL);
+	gpio_request(GPIO_FN_KEYIN4_PU, NULL);
+	gpio_request(GPIO_FN_KEYIN5_PU, NULL);
+	gpio_request(GPIO_FN_KEYIN6_PU, NULL);
+	gpio_request(GPIO_FN_KEYIN7_PU, NULL);
+	gpio_request(GPIO_FN_KEYOUT0, NULL);
+	gpio_request(GPIO_FN_KEYOUT1, NULL);
+	gpio_request(GPIO_FN_KEYOUT2, NULL);
+	gpio_request(GPIO_FN_KEYOUT3, NULL);
+	gpio_request(GPIO_FN_KEYOUT4, NULL);
+	gpio_request(GPIO_FN_KEYOUT5, NULL);
+	gpio_request(GPIO_FN_PORT59_KEYOUT6, NULL);
+	gpio_request(GPIO_FN_PORT58_KEYOUT7, NULL);
+	gpio_request(GPIO_FN_KEYOUT8, NULL);
+
+	/* MMCIF */
+	gpio_request(GPIO_FN_MMCCLK0, NULL);
+	gpio_request(GPIO_FN_MMCD0_0, NULL);
+	gpio_request(GPIO_FN_MMCD0_1, NULL);
+	gpio_request(GPIO_FN_MMCD0_2, NULL);
+	gpio_request(GPIO_FN_MMCD0_3, NULL);
+	gpio_request(GPIO_FN_MMCD0_4, NULL);
+	gpio_request(GPIO_FN_MMCD0_5, NULL);
+	gpio_request(GPIO_FN_MMCD0_6, NULL);
+	gpio_request(GPIO_FN_MMCD0_7, NULL);
+	gpio_request(GPIO_FN_MMCCMD0, NULL);
+	gpio_request(GPIO_PORT208, NULL); /* Reset */
+	gpio_direction_output(GPIO_PORT208, 1);
+
+	/* SDHI0 (microSD) */
+	gpio_request(GPIO_FN_SDHICD0_PU, NULL);
+	gpio_request(GPIO_FN_SDHICMD0_PU, NULL);
+	gpio_request(GPIO_FN_SDHICLK0, NULL);
+	gpio_request(GPIO_FN_SDHID0_3_PU, NULL);
+	gpio_request(GPIO_FN_SDHID0_2_PU, NULL);
+	gpio_request(GPIO_FN_SDHID0_1_PU, NULL);
+	gpio_request(GPIO_FN_SDHID0_0_PU, NULL);
+
+	/* SCIFB (BT) */
+	gpio_request(GPIO_FN_PORT159_SCIFB_SCK, NULL);
+	gpio_request(GPIO_FN_PORT160_SCIFB_TXD, NULL);
+	gpio_request(GPIO_FN_PORT161_SCIFB_CTS_, NULL);
+	gpio_request(GPIO_FN_PORT162_SCIFB_RXD, NULL);
+	gpio_request(GPIO_FN_PORT163_SCIFB_RTS_, NULL);
+
+	/* SDHI1 (BCM4330) */
+	gpio_request(GPIO_FN_SDHICLK1, NULL);
+	gpio_request(GPIO_FN_SDHICMD1_PU, NULL);
+	gpio_request(GPIO_FN_SDHID1_3_PU, NULL);
+	gpio_request(GPIO_FN_SDHID1_2_PU, NULL);
+	gpio_request(GPIO_FN_SDHID1_1_PU, NULL);
+	gpio_request(GPIO_FN_SDHID1_0_PU, NULL);
+
+#ifdef CONFIG_CACHE_L2X0
+	/* Early BRESP enable, Shared attribute override enable, 64K*8way */
+	l2x0_init(__io(0xf0100000), 0x40460000, 0x82000fff);
+#endif
+	sh73a0_add_standard_devices();
+	platform_add_devices(kota2_devices, ARRAY_SIZE(kota2_devices));
+}
+
+static void __init kota2_timer_init(void)
+{
+	sh73a0_clock_init();
+	shmobile_timer.init();
+	return;
+}
+
+struct sys_timer kota2_timer = {
+	.init	= kota2_timer_init,
+};
+
+MACHINE_START(KOTA2, "kota2")
+	.map_io		= kota2_map_io,
+	.nr_irqs	= NR_IRQS_LEGACY,
+	.init_irq	= sh73a0_init_irq,
+	.handle_irq	= shmobile_handle_irq_gic,
+	.init_machine	= kota2_init,
+	.timer		= &kota2_timer,
+MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/board-mackerel.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/board-mackerel.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/board-mackerel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/board-mackerel.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,12 +39,13 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
-#include <linux/pm_runtime.h>
+#include <linux/pm_clock.h>
 #include <linux/smsc911x.h>
 #include <linux/sh_intc.h>
 #include <linux/tca6416_keypad.h>
 #include <linux/usb/r8a66597.h>
 #include <linux/usb/renesas_usbhs.h>
+#include <linux/dma-mapping.h>
 
 #include <video/sh_mobile_hdmi.h>
 #include <video/sh_mobile_lcdc.h>
@@ -272,8 +273,8 @@
 
 static struct resource nor_flash_resources[] = {
 	[0]	= {
-		.start	= 0x00000000,
-		.end	= 0x08000000 - 1,
+		.start	= 0x20000000, /* CS0 shadow instead of regular CS0 */
+		.end	= 0x28000000 - 1, /* needed by USB MASK ROM boot */
 		.flags	= IORESOURCE_MEM,
 	}
 };
@@ -810,6 +811,7 @@
 		},
 		.driver_param = {
 			.buswait_bwait	= 4,
+			.has_otg	= 1,
 			.pipe_type	= usbhs1_pipe_cfg,
 			.pipe_size	= ARRAY_SIZE(usbhs1_pipe_cfg),
 			.d0_tx_id	= SHDMA_SLAVE_USB1_TX,
@@ -1070,14 +1072,17 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
+		.name	= SH_MOBILE_SDHI_IRQ_CARD_DETECT,
 		.start	= evt2irq(0x0e80), /* SDHI1_SDHI1I0 */
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
+		.name	= SH_MOBILE_SDHI_IRQ_SDCARD,
 		.start	= evt2irq(0x0ea0), /* SDHI1_SDHI1I1 */
 		.flags	= IORESOURCE_IRQ,
 	},
 	[3] = {
+		.name	= SH_MOBILE_SDHI_IRQ_SDIO,
 		.start	= evt2irq(0x0ec0), /* SDHI1_SDHI1I2 */
 		.flags	= IORESOURCE_IRQ,
 	},
@@ -1121,14 +1126,17 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
+		.name	= SH_MOBILE_SDHI_IRQ_CARD_DETECT,
 		.start	= evt2irq(0x1200), /* SDHI2_SDHI2I0 */
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
+		.name	= SH_MOBILE_SDHI_IRQ_SDCARD,
 		.start	= evt2irq(0x1220), /* SDHI2_SDHI2I1 */
 		.flags	= IORESOURCE_IRQ,
 	},
 	[3] = {
+		.name	= SH_MOBILE_SDHI_IRQ_SDIO,
 		.start	= evt2irq(0x1240), /* SDHI2_SDHI2I2 */
 		.flags	= IORESOURCE_IRQ,
 	},
@@ -1215,9 +1223,10 @@
 		.width = 640,
 		.height = 480,
 	},
-	.bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
-	SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8 |
-	SOCAM_DATA_ACTIVE_HIGH,
+	.mbus_param = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+	V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+	V4L2_MBUS_DATA_ACTIVE_HIGH,
+	.mbus_type = V4L2_MBUS_PARALLEL,
 	.set_capture = camera_set_capture,
 };
 
@@ -1381,6 +1390,8 @@
 static void __init mackerel_map_io(void)
 {
 	iotable_init(mackerel_io_desc, ARRAY_SIZE(mackerel_io_desc));
+	/* DMA memory at 0xf6000000 - 0xffdfffff */
+	init_consistent_dma_size(158 << 20);
 
 	/* setup early devices and console here as well */
 	sh7372_add_early_devices();
@@ -1587,7 +1598,17 @@
 
 	sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
 	sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device);
+	sh7372_add_device_to_domain(&sh7372_a4lc, &meram_device);
 	sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs0_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs1_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device);
+#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
+	sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device);
+#endif
+	sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi2_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device);
 
 	hdmi_init_pm_clock();
 	sh7372_pm_init();
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/clock.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/clock.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/sh_clk.h>
+#include <linux/export.h>
 
 int __init clk_init(void)
 {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/clock-sh7372.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/clock-sh7372.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/clock-sh7372.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/clock-sh7372.c	2012-01-04 18:55:44.000000000 -0500
@@ -476,7 +476,7 @@
 	.disable	= fsidiv_disable,
 };
 
-static struct clk_mapping sh7372_fsidiva_clk_mapping = {
+static struct clk_mapping fsidiva_clk_mapping = {
 	.phys	= FSIDIVA,
 	.len	= 8,
 };
@@ -484,10 +484,10 @@
 struct clk sh7372_fsidiva_clk = {
 	.ops		= &fsidiv_clk_ops,
 	.parent		= &div6_reparent_clks[DIV6_FSIA], /* late install */
-	.mapping	= &sh7372_fsidiva_clk_mapping,
+	.mapping	= &fsidiva_clk_mapping,
 };
 
-static struct clk_mapping sh7372_fsidivb_clk_mapping = {
+static struct clk_mapping fsidivb_clk_mapping = {
 	.phys	= FSIDIVB,
 	.len	= 8,
 };
@@ -495,7 +495,7 @@
 struct clk sh7372_fsidivb_clk = {
 	.ops		= &fsidiv_clk_ops,
 	.parent		= &div6_reparent_clks[DIV6_FSIB],  /* late install */
-	.mapping	= &sh7372_fsidivb_clk_mapping,
+	.mapping	= &fsidivb_clk_mapping,
 };
 
 static struct clk *late_main_clks[] = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/clock-sh73a0.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/clock-sh73a0.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/clock-sh73a0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/clock-sh73a0.c	2012-01-04 18:55:44.000000000 -0500
@@ -113,6 +113,12 @@
 	.ops		= &main_clk_ops,
 };
 
+/* Divide Main clock by two */
+static struct clk main_div2_clk = {
+	.ops		= &div2_clk_ops,
+	.parent		= &main_clk,
+};
+
 /* PLL0, PLL1, PLL2, PLL3 */
 static unsigned long pll_recalc(struct clk *clk)
 {
@@ -181,6 +187,7 @@
 	&extal1_div2_clk,
 	&extal2_div2_clk,
 	&main_clk,
+	&main_div2_clk,
 	&pll0_clk,
 	&pll1_clk,
 	&pll2_clk,
@@ -243,7 +250,7 @@
 	[DIV6_VCK1] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR1, 0),
 	[DIV6_VCK2] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR2, 0),
 	[DIV6_VCK3] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR3, 0),
-	[DIV6_ZB1] = SH_CLK_DIV6(&pll1_div2_clk, ZBCKCR, 0),
+	[DIV6_ZB1] = SH_CLK_DIV6(&pll1_div2_clk, ZBCKCR, CLK_ENABLE_ON_INIT),
 	[DIV6_FLCTL] = SH_CLK_DIV6(&pll1_div2_clk, FLCKCR, 0),
 	[DIV6_SDHI0] = SH_CLK_DIV6(&pll1_div2_clk, SD0CKCR, 0),
 	[DIV6_SDHI1] = SH_CLK_DIV6(&pll1_div2_clk, SD1CKCR, 0),
@@ -268,6 +275,7 @@
 	MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
 	MSTP331, MSTP329, MSTP325, MSTP323, MSTP318,
 	MSTP314, MSTP313, MSTP312, MSTP311,
+	MSTP303, MSTP302, MSTP301, MSTP300,
 	MSTP411, MSTP410, MSTP403,
 	MSTP_NR };
 
@@ -301,6 +309,10 @@
 	[MSTP313] = MSTP(&div6_clks[DIV6_SDHI1], SMSTPCR3, 13, 0), /* SDHI1 */
 	[MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMCIF0 */
 	[MSTP311] = MSTP(&div6_clks[DIV6_SDHI2], SMSTPCR3, 11, 0), /* SDHI2 */
+	[MSTP303] = MSTP(&main_div2_clk, SMSTPCR3, 3, 0), /* TPU1 */
+	[MSTP302] = MSTP(&main_div2_clk, SMSTPCR3, 2, 0), /* TPU2 */
+	[MSTP301] = MSTP(&main_div2_clk, SMSTPCR3, 1, 0), /* TPU3 */
+	[MSTP300] = MSTP(&main_div2_clk, SMSTPCR3, 0, 0), /* TPU4 */
 	[MSTP411] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */
 	[MSTP410] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 10, 0), /* IIC4 */
 	[MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
@@ -350,6 +362,10 @@
 	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
 	CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */
+	CLKDEV_DEV_ID("leds-renesas-tpu.12", &mstp_clks[MSTP303]), /* TPU1 */
+	CLKDEV_DEV_ID("leds-renesas-tpu.21", &mstp_clks[MSTP302]), /* TPU2 */
+	CLKDEV_DEV_ID("leds-renesas-tpu.30", &mstp_clks[MSTP301]), /* TPU3 */
+	CLKDEV_DEV_ID("leds-renesas-tpu.41", &mstp_clks[MSTP300]), /* TPU4 */
 	CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* I2C3 */
 	CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */
 	CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/cpuidle.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/cpuidle.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/cpuidle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/cpuidle.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,65 +26,59 @@
 };
 
 static int shmobile_cpuidle_enter(struct cpuidle_device *dev,
-				  struct cpuidle_state *state)
+				  struct cpuidle_driver *drv,
+				  int index)
 {
 	ktime_t before, after;
-	int requested_state = state - &dev->states[0];
 
-	dev->last_state = &dev->states[requested_state];
 	before = ktime_get();
 
 	local_irq_disable();
 	local_fiq_disable();
 
-	shmobile_cpuidle_modes[requested_state]();
+	shmobile_cpuidle_modes[index]();
 
 	local_irq_enable();
 	local_fiq_enable();
 
 	after = ktime_get();
-	return ktime_to_ns(ktime_sub(after, before)) >> 10;
+	dev->last_residency = ktime_to_ns(ktime_sub(after, before)) >> 10;
+
+	return index;
 }
 
 static struct cpuidle_device shmobile_cpuidle_dev;
 static struct cpuidle_driver shmobile_cpuidle_driver = {
 	.name =		"shmobile_cpuidle",
 	.owner =	THIS_MODULE,
+	.states[0] = {
+		.name = "C1",
+		.desc = "WFI",
+		.exit_latency = 1,
+		.target_residency = 1 * 2,
+		.flags = CPUIDLE_FLAG_TIME_VALID,
+	},
+	.safe_state_index = 0, /* C1 */
+	.state_count = 1,
 };
 
-void (*shmobile_cpuidle_setup)(struct cpuidle_device *dev);
+void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv);
 
 static int shmobile_cpuidle_init(void)
 {
 	struct cpuidle_device *dev = &shmobile_cpuidle_dev;
-	struct cpuidle_state *state;
+	struct cpuidle_driver *drv = &shmobile_cpuidle_driver;
 	int i;
 
-	cpuidle_register_driver(&shmobile_cpuidle_driver);
-
-	for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
-		dev->states[i].name[0] = '\0';
-		dev->states[i].desc[0] = '\0';
-		dev->states[i].enter = shmobile_cpuidle_enter;
-	}
-
-	i = CPUIDLE_DRIVER_STATE_START;
-
-	state = &dev->states[i++];
-	snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
-	strncpy(state->desc, "WFI", CPUIDLE_DESC_LEN);
-	state->exit_latency = 1;
-	state->target_residency = 1 * 2;
-	state->power_usage = 3;
-	state->flags = 0;
-	state->flags |= CPUIDLE_FLAG_TIME_VALID;
-
-	dev->safe_state = state;
-	dev->state_count = i;
+	for (i = 0; i < CPUIDLE_STATE_MAX; i++)
+		drv->states[i].enter = shmobile_cpuidle_enter;
 
 	if (shmobile_cpuidle_setup)
-		shmobile_cpuidle_setup(dev);
+		shmobile_cpuidle_setup(drv);
 
+	cpuidle_register_driver(drv);
+
+	dev->state_count = drv->state_count;
 	cpuidle_register_device(dev);
 
 	return 0;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/entry-intc.S linux-libre-3.2-gnu/arch/arm/mach-shmobile/entry-intc.S
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/entry-intc.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/entry-intc.S	2012-01-04 18:55:44.000000000 -0500
@@ -51,7 +51,4 @@
 	.macro  test_for_ipi, irqnr, irqstat, base, tmp
 	.endm
 
-	.macro  test_for_ltirq, irqnr, irqstat, base, tmp
-	.endm
-
 	arch_irq_handler shmobile_handle_irq_intc
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/include/mach/common.h linux-libre-3.2-gnu/arch/arm/mach-shmobile/include/mach/common.h
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/include/mach/common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/include/mach/common.h	2012-01-04 18:55:44.000000000 -0500
@@ -9,9 +9,9 @@
 extern void shmobile_handle_irq_intc(struct pt_regs *);
 extern void shmobile_handle_irq_gic(struct pt_regs *);
 extern struct platform_suspend_ops shmobile_suspend_ops;
-struct cpuidle_device;
+struct cpuidle_driver;
 extern void (*shmobile_cpuidle_modes[])(void);
-extern void (*shmobile_cpuidle_setup)(struct cpuidle_device *dev);
+extern void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv);
 
 extern void sh7367_init_irq(void);
 extern void sh7367_add_early_devices(void);
@@ -35,8 +35,8 @@
 extern void sh7372_clock_init(void);
 extern void sh7372_pinmux_init(void);
 extern void sh7372_pm_init(void);
-extern void sh7372_cpu_suspend(void);
-extern void sh7372_cpu_resume(void);
+extern void sh7372_resume_core_standby_a3sm(void);
+extern int sh7372_do_idle_a3sm(unsigned long unused);
 extern struct clk sh7372_extal1_clk;
 extern struct clk sh7372_extal2_clk;
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/include/mach/entry-macro.S linux-libre-3.2-gnu/arch/arm/mach-shmobile/include/mach/entry-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/include/mach/entry-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/include/mach/entry-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -27,8 +27,5 @@
 	.macro  test_for_ipi, irqnr, irqstat, base, tmp
 	.endm
 
-	.macro  test_for_ltirq, irqnr, irqstat, base, tmp
-	.endm
-
 	.macro  arch_ret_to_user, tmp1, tmp2
 	.endm
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-shmobile/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -18,31 +18,15 @@
 
 #ifdef CONFIG_GPIOLIB
 
-static inline int gpio_get_value(unsigned gpio)
-{
-	return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	__gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned gpio)
-{
-	return __gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(unsigned gpio)
-{
-	return __gpio_to_irq(gpio);
-}
-
 static inline int irq_to_gpio(unsigned int irq)
 {
 	return -ENOSYS;
 }
 
+#else
+
+#define __ARM_GPIOLIB_COMPLEX
+
 #endif /* CONFIG_GPIOLIB */
 
 #endif /* __ASM_ARCH_GPIO_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/include/mach/intc.h linux-libre-3.2-gnu/arch/arm/mach-shmobile/include/mach/intc.h
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/include/mach/intc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/include/mach/intc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,246 @@
+#ifndef __ASM_MACH_INTC_H
+#define __ASM_MACH_INTC_H
+#include <linux/sh_intc.h>
+
+#define INTC_IRQ_PINS_ENUM_16L(p)				\
+	p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
+	p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7,		\
+	p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,	\
+	p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15
+
+#define INTC_IRQ_PINS_ENUM_16H(p)				\
+	p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,	\
+	p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23,	\
+	p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,	\
+	p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31
+
+#define INTC_IRQ_PINS_VECT_16L(p, vect)				\
+	vect(p ## _IRQ0, 0x0200), vect(p ## _IRQ1, 0x0220),	\
+	vect(p ## _IRQ2, 0x0240), vect(p ## _IRQ3, 0x0260),	\
+	vect(p ## _IRQ4, 0x0280), vect(p ## _IRQ5, 0x02a0),	\
+	vect(p ## _IRQ6, 0x02c0), vect(p ## _IRQ7, 0x02e0),	\
+	vect(p ## _IRQ8, 0x0300), vect(p ## _IRQ9, 0x0320),	\
+	vect(p ## _IRQ10, 0x0340), vect(p ## _IRQ11, 0x0360),	\
+	vect(p ## _IRQ12, 0x0380), vect(p ## _IRQ13, 0x03a0),	\
+	vect(p ## _IRQ14, 0x03c0), vect(p ## _IRQ15, 0x03e0)
+
+#define INTC_IRQ_PINS_VECT_16H(p, vect)				\
+	vect(p ## _IRQ16, 0x3200), vect(p ## _IRQ17, 0x3220),	\
+	vect(p ## _IRQ18, 0x3240), vect(p ## _IRQ19, 0x3260),	\
+	vect(p ## _IRQ20, 0x3280), vect(p ## _IRQ21, 0x32a0),	\
+	vect(p ## _IRQ22, 0x32c0), vect(p ## _IRQ23, 0x32e0),	\
+	vect(p ## _IRQ24, 0x3300), vect(p ## _IRQ25, 0x3320),	\
+	vect(p ## _IRQ26, 0x3340), vect(p ## _IRQ27, 0x3360),	\
+	vect(p ## _IRQ28, 0x3380), vect(p ## _IRQ29, 0x33a0),	\
+	vect(p ## _IRQ30, 0x33c0), vect(p ## _IRQ31, 0x33e0)
+
+#define INTC_IRQ_PINS_MASK_16L(p, base)					\
+	{ base + 0x40, base + 0x60, 8, /* INTMSK00A / INTMSKCLR00A */	\
+	  { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
+	    p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } },		\
+	{ base + 0x44, base + 0x64, 8, /* INTMSK10A / INTMSKCLR10A */	\
+	  { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,		\
+	    p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_MASK_16H(p, base)					\
+	{ base + 0x48, base + 0x68, 8, /* INTMSK20A / INTMSKCLR20A */	\
+	  { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,		\
+	    p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } },	\
+	{ base + 0x4c, base + 0x6c, 8, /* INTMSK30A / INTMSKCLR30A */	\
+	  { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,		\
+	    p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_PRIO_16L(p, base)					\
+	{ base + 0x10, 0, 32, 4, /* INTPRI00A */			\
+	  { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
+	    p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } },		\
+	{ base + 0x14, 0, 32, 4, /* INTPRI10A */			\
+	  { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,		\
+	    p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_PRIO_16H(p, base)					\
+	{ base + 0x18, 0, 32, 4, /* INTPRI20A */			\
+	  { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,		\
+	    p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } },	\
+	{ base + 0x1c, 0, 32, 4, /* INTPRI30A */			\
+	  { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,		\
+	    p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_SENSE_16L(p, base)				\
+	{ base + 0x00, 32, 4, /* ICR1A */				\
+	  { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
+	    p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } },		\
+	{ base + 0x04, 32, 4, /* ICR2A */				\
+	  { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,		\
+	    p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_SENSE_16H(p, base)				\
+	{ base + 0x08, 32, 4, /* ICR3A */				\
+	  { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,		\
+	    p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } },	\
+	{ base + 0x0c, 32, 4, /* ICR4A */				\
+	  { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,		\
+	    p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_ACK_16L(p, base)					\
+	{ base + 0x20, 0, 8, /* INTREQ00A */				\
+	  { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3,		\
+	    p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } },		\
+	{ base + 0x24, 0, 8, /* INTREQ10A */				\
+	  { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11,		\
+	    p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_ACK_16H(p, base)					\
+	{ base + 0x28, 0, 8, /* INTREQ20A */				\
+	  { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19,		\
+	    p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } },	\
+	{ base + 0x2c, 0, 8, /* INTREQ30A */				\
+	  { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27,		\
+	    p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_16(p, base, vect, str)				\
+									\
+static struct resource p ## _resources[] __initdata = {			\
+	[0] = {								\
+		.start	= base,						\
+		.end	= base + 0x64,					\
+		.flags	= IORESOURCE_MEM,				\
+	},								\
+};									\
+									\
+enum {									\
+	p ## _UNUSED = 0,						\
+	INTC_IRQ_PINS_ENUM_16L(p),					\
+};									\
+									\
+static struct intc_vect p ## _vectors[] __initdata = {			\
+	INTC_IRQ_PINS_VECT_16L(p, vect),				\
+};									\
+									\
+static struct intc_mask_reg p ## _mask_registers[] __initdata = {	\
+	INTC_IRQ_PINS_MASK_16L(p, base),				\
+};									\
+									\
+static struct intc_prio_reg p ## _prio_registers[] __initdata = {	\
+	INTC_IRQ_PINS_PRIO_16L(p, base),				\
+};									\
+									\
+static struct intc_sense_reg p ## _sense_registers[] __initdata = {	\
+	INTC_IRQ_PINS_SENSE_16L(p, base),				\
+};									\
+									\
+static struct intc_mask_reg p ## _ack_registers[] __initdata = {	\
+	INTC_IRQ_PINS_ACK_16L(p, base),					\
+};									\
+									\
+static struct intc_desc p ## _desc __initdata = {			\
+	.name = str,							\
+	.resource = p ## _resources,					\
+	.num_resources = ARRAY_SIZE(p ## _resources),			\
+	.hw = INTC_HW_DESC(p ## _vectors, NULL,				\
+			     p ## _mask_registers, p ## _prio_registers, \
+			     p ## _sense_registers, p ## _ack_registers) \
+}
+
+#define INTC_IRQ_PINS_32(p, base, vect, str)				\
+									\
+static struct resource p ## _resources[] __initdata = {			\
+	[0] = {								\
+		.start	= base,						\
+		.end	= base + 0x6c,					\
+		.flags	= IORESOURCE_MEM,				\
+	},								\
+};									\
+									\
+enum {									\
+	p ## _UNUSED = 0,						\
+	INTC_IRQ_PINS_ENUM_16L(p),					\
+	INTC_IRQ_PINS_ENUM_16H(p),					\
+};									\
+									\
+static struct intc_vect p ## _vectors[] __initdata = {			\
+	INTC_IRQ_PINS_VECT_16L(p, vect),				\
+	INTC_IRQ_PINS_VECT_16H(p, vect),				\
+};									\
+									\
+static struct intc_mask_reg p ## _mask_registers[] __initdata = {	\
+	INTC_IRQ_PINS_MASK_16L(p, base),				\
+	INTC_IRQ_PINS_MASK_16H(p, base),				\
+};									\
+									\
+static struct intc_prio_reg p ## _prio_registers[] __initdata = {	\
+	INTC_IRQ_PINS_PRIO_16L(p, base),				\
+	INTC_IRQ_PINS_PRIO_16H(p, base),				\
+};									\
+									\
+static struct intc_sense_reg p ## _sense_registers[] __initdata = {	\
+	INTC_IRQ_PINS_SENSE_16L(p, base),				\
+	INTC_IRQ_PINS_SENSE_16H(p, base),				\
+};									\
+									\
+static struct intc_mask_reg p ## _ack_registers[] __initdata = {	\
+	INTC_IRQ_PINS_ACK_16L(p, base),					\
+	INTC_IRQ_PINS_ACK_16H(p, base),					\
+};									\
+									\
+static struct intc_desc p ## _desc __initdata = {			\
+	.name = str,							\
+	.resource = p ## _resources,					\
+	.num_resources = ARRAY_SIZE(p ## _resources),			\
+	.hw = INTC_HW_DESC(p ## _vectors, NULL,				\
+			     p ## _mask_registers, p ## _prio_registers, \
+			     p ## _sense_registers, p ## _ack_registers) \
+}
+
+#define INTC_PINT_E_EMPTY
+#define INTC_PINT_E_NONE 0, 0, 0, 0, 0, 0, 0, 0,
+#define INTC_PINT_E(p)							\
+	PINT ## p ## 0, PINT ## p ## 1, PINT ## p ## 2, PINT ## p ## 3,	\
+	PINT ## p ## 4, PINT ## p ## 5, PINT ## p ## 6, PINT ## p ## 7,
+
+#define INTC_PINT_V_NONE
+#define INTC_PINT_V(p, vect)					\
+	vect(PINT ## p ## 0, 0), vect(PINT ## p ## 1, 1),	\
+	vect(PINT ## p ## 2, 2), vect(PINT ## p ## 3, 3),	\
+	vect(PINT ## p ## 4, 4), vect(PINT ## p ## 5, 5),	\
+	vect(PINT ## p ## 6, 6), vect(PINT ## p ## 7, 7),
+
+#define INTC_PINT(p, mask_reg, sense_base, str,				\
+	enums_1, enums_2, enums_3, enums_4,				\
+	vect_1, vect_2, vect_3, vect_4,					\
+	mask_a, mask_b, mask_c, mask_d,					\
+	sense_a, sense_b, sense_c, sense_d)				\
+									\
+enum {									\
+	PINT ## p ## _UNUSED = 0,					\
+	enums_1 enums_2 enums_3 enums_4 				\
+};									\
+									\
+static struct intc_vect p ## _vectors[] __initdata = {			\
+	vect_1 vect_2 vect_3 vect_4					\
+};									\
+									\
+static struct intc_mask_reg p ## _mask_registers[] __initdata = {	\
+	{ mask_reg, 0, 32, /* PINTER */					\
+	  { mask_a mask_b mask_c mask_d } }				\
+};									\
+									\
+static struct intc_sense_reg p ## _sense_registers[] __initdata = {	\
+	{ sense_base + 0x00, 16, 2, /* PINTCR */			\
+	  { sense_a } },						\
+	{ sense_base + 0x04, 16, 2, /* PINTCR */			\
+	  { sense_b } },						\
+	{ sense_base + 0x08, 16, 2, /* PINTCR */			\
+	  { sense_c } },						\
+	{ sense_base + 0x0c, 16, 2, /* PINTCR */			\
+	  { sense_d } },						\
+};									\
+									\
+static struct intc_desc p ## _desc __initdata = {			\
+	.name = str,							\
+	.hw = INTC_HW_DESC(p ## _vectors, NULL,				\
+			     p ## _mask_registers, NULL,		\
+			     p ## _sense_registers, NULL),		\
+}
+
+#endif  /* __ASM_MACH_INTC_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-shmobile/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/include/mach/memory.h	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,4 @@
 #define PLAT_PHYS_OFFSET	UL(CONFIG_MEMORY_START)
 #define MEM_SIZE	UL(CONFIG_MEMORY_SIZE)
 
-/* DMA memory at 0xf6000000 - 0xffdfffff */
-#define CONSISTENT_DMA_SIZE (158 << 20)
-
 #endif /* __ASM_MACH_MEMORY_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/include/mach/sh7372.h linux-libre-3.2-gnu/arch/arm/mach-shmobile/include/mach/sh7372.h
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/include/mach/sh7372.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/include/mach/sh7372.h	2012-01-04 18:55:44.000000000 -0500
@@ -479,7 +479,12 @@
 
 struct sh7372_pm_domain {
 	struct generic_pm_domain genpd;
+	struct dev_power_governor *gov;
+	void (*suspend)(void);
+	void (*resume)(void);
 	unsigned int bit_shift;
+	bool no_debug;
+	bool stay_on;
 };
 
 static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d)
@@ -491,16 +496,24 @@
 extern struct sh7372_pm_domain sh7372_a4lc;
 extern struct sh7372_pm_domain sh7372_a4mp;
 extern struct sh7372_pm_domain sh7372_d4;
+extern struct sh7372_pm_domain sh7372_a4r;
 extern struct sh7372_pm_domain sh7372_a3rv;
 extern struct sh7372_pm_domain sh7372_a3ri;
+extern struct sh7372_pm_domain sh7372_a3sp;
 extern struct sh7372_pm_domain sh7372_a3sg;
 
 extern void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd);
 extern void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd,
 					struct platform_device *pdev);
+extern void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd,
+				    struct sh7372_pm_domain *sh7372_sd);
 #else
 #define sh7372_init_pm_domain(pd) do { } while(0)
 #define sh7372_add_device_to_domain(pd, pdev) do { } while(0)
+#define sh7372_pm_add_subdomain(pd, sd) do { } while(0)
 #endif /* CONFIG_PM */
 
+extern void sh7372_intcs_suspend(void);
+extern void sh7372_intcs_resume(void);
+
 #endif /* __ASM_SH7372_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/include/mach/sh73a0.h linux-libre-3.2-gnu/arch/arm/mach-shmobile/include/mach/sh73a0.h
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/include/mach/sh73a0.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/include/mach/sh73a0.h	2012-01-04 18:55:44.000000000 -0500
@@ -451,18 +451,39 @@
 	GPIO_FN_KEYIN5_PU,
 	GPIO_FN_KEYIN6_PU,
 	GPIO_FN_KEYIN7_PU,
+	GPIO_FN_SDHICD0_PU,
+	GPIO_FN_SDHID0_0_PU,
+	GPIO_FN_SDHID0_1_PU,
+	GPIO_FN_SDHID0_2_PU,
+	GPIO_FN_SDHID0_3_PU,
+	GPIO_FN_SDHICMD0_PU,
+	GPIO_FN_SDHIWP0_PU,
 	GPIO_FN_SDHID1_0_PU,
 	GPIO_FN_SDHID1_1_PU,
 	GPIO_FN_SDHID1_2_PU,
 	GPIO_FN_SDHID1_3_PU,
 	GPIO_FN_SDHICMD1_PU,
+	GPIO_FN_SDHID2_0_PU,
+	GPIO_FN_SDHID2_1_PU,
+	GPIO_FN_SDHID2_2_PU,
+	GPIO_FN_SDHID2_3_PU,
+	GPIO_FN_SDHICMD2_PU,
 	GPIO_FN_MMCCMD0_PU,
 	GPIO_FN_MMCCMD1_PU,
+	GPIO_FN_MMCD0_0_PU,
+	GPIO_FN_MMCD0_1_PU,
+	GPIO_FN_MMCD0_2_PU,
+	GPIO_FN_MMCD0_3_PU,
+	GPIO_FN_MMCD0_4_PU,
+	GPIO_FN_MMCD0_5_PU,
+	GPIO_FN_MMCD0_6_PU,
+	GPIO_FN_MMCD0_7_PU,
 	GPIO_FN_FSIACK_PU,
 	GPIO_FN_FSIAILR_PU,
 	GPIO_FN_FSIAIBT_PU,
 	GPIO_FN_FSIAISLD_PU,
 };
+
 /* DMA slave IDs */
 enum {
 	SHDMA_SLAVE_INVALID,
@@ -494,4 +515,8 @@
 	SHDMA_SLAVE_MMCIF_RX,
 };
 
+/* PINT interrupts are located at Linux IRQ 768 and up */
+#define SH73A0_PINT0_IRQ(irq) ((irq) + 768)
+#define SH73A0_PINT1_IRQ(irq) ((irq) + 800)
+
 #endif /* __ASM_SH73A0_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/intc-sh7367.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/intc-sh7367.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/intc-sh7367.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/intc-sh7367.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sh_intc.h>
+#include <mach/intc.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -31,8 +32,6 @@
 	DISABLED,
 
 	/* interrupt sources INTCA */
-	IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A,
-	IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A,
 	DIRC,
 	CRYPT1_ERR, CRYPT2_STD,
 	IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1,
@@ -76,14 +75,6 @@
 };
 
 static struct intc_vect intca_vectors[] __initdata = {
-	INTC_VECT(IRQ0A, 0x0200), INTC_VECT(IRQ1A, 0x0220),
-	INTC_VECT(IRQ2A, 0x0240), INTC_VECT(IRQ3A, 0x0260),
-	INTC_VECT(IRQ4A, 0x0280), INTC_VECT(IRQ5A, 0x02a0),
-	INTC_VECT(IRQ6A, 0x02c0), INTC_VECT(IRQ7A, 0x02e0),
-	INTC_VECT(IRQ8A, 0x0300), INTC_VECT(IRQ9A, 0x0320),
-	INTC_VECT(IRQ10A, 0x0340), INTC_VECT(IRQ11A, 0x0360),
-	INTC_VECT(IRQ12A, 0x0380), INTC_VECT(IRQ13A, 0x03a0),
-	INTC_VECT(IRQ14A, 0x03c0), INTC_VECT(IRQ15A, 0x03e0),
 	INTC_VECT(DIRC, 0x0560),
 	INTC_VECT(CRYPT1_ERR, 0x05e0),
 	INTC_VECT(CRYPT2_STD, 0x0700),
@@ -163,10 +154,6 @@
 };
 
 static struct intc_mask_reg intca_mask_registers[] __initdata = {
-	{ 0xe6900040, 0xe6900060, 8, /* INTMSK00A / INTMSKCLR00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900044, 0xe6900064, 8, /* INTMSK10A / INTMSKCLR10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
 	{ 0xe6940080, 0xe69400c0, 8, /* IMR0A / IMCR0A */
 	  { DMAC2_1_DEI3, DMAC2_1_DEI2, DMAC2_1_DEI1, DMAC2_1_DEI0,
 	    ARM11_IRQPMU, 0, ARM11_COMMTX, ARM11_COMMRX } },
@@ -212,11 +199,6 @@
 };
 
 static struct intc_prio_reg intca_prio_registers[] __initdata = {
-	{ 0xe6900010, 0, 32, 4, /* INTPRI00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900014, 0, 32, 4, /* INTPRI10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-
 	{ 0xe6940000, 0, 16, 4, /* IPRAA */ { DMAC3_1, DMAC3_2, CMT2, LCRC } },
 	{ 0xe6940004, 0, 16, 4, /* IPRBA */ { IRDA, ETM11, BBIF1, BBIF2 } },
 	{ 0xe6940008, 0, 16, 4, /* IPRCA */ { CRYPT1_ERR, CRYPT2_STD,
@@ -240,29 +222,18 @@
 	{ 0xe6940038, 0, 16, 4, /* IPROA */ { 0, 0, DIRC, SDHI2 } },
 };
 
-static struct intc_sense_reg intca_sense_registers[] __initdata = {
-	{ 0xe6900000, 16, 2, /* ICR1A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900004, 16, 2, /* ICR2A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-};
-
-static struct intc_mask_reg intca_ack_registers[] __initdata = {
-	{ 0xe6900020, 0, 8, /* INTREQ00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900024, 0, 8, /* INTREQ10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-};
-
 static struct intc_desc intca_desc __initdata = {
 	.name = "sh7367-intca",
 	.force_enable = ENABLED,
 	.force_disable = DISABLED,
 	.hw = INTC_HW_DESC(intca_vectors, intca_groups,
 			   intca_mask_registers, intca_prio_registers,
-			   intca_sense_registers, intca_ack_registers),
+			   NULL, NULL),
 };
 
+INTC_IRQ_PINS_16(intca_irq_pins, 0xe6900000,
+		 INTC_VECT, "sh7367-intca-irq-pins");
+
 enum {
 	UNUSED_INTCS = 0,
 
@@ -432,6 +403,7 @@
 	void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
 
 	register_intc_controller(&intca_desc);
+	register_intc_controller(&intca_irq_pins_desc);
 	register_intc_controller(&intcs_desc);
 
 	/* demux using INTEVTSA */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/intc-sh7372.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/intc-sh7372.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/intc-sh7372.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/intc-sh7372.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sh_intc.h>
+#include <mach/intc.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -29,10 +30,6 @@
 	UNUSED_INTCA = 0,
 
 	/* interrupt sources INTCA */
-	IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A,
-	IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A,
-	IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A,
-	IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A,
 	DIRC,
 	CRYPT_STD,
 	IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1,
@@ -86,22 +83,6 @@
 };
 
 static struct intc_vect intca_vectors[] __initdata = {
-	INTC_VECT(IRQ0A, 0x0200), INTC_VECT(IRQ1A, 0x0220),
-	INTC_VECT(IRQ2A, 0x0240), INTC_VECT(IRQ3A, 0x0260),
-	INTC_VECT(IRQ4A, 0x0280), INTC_VECT(IRQ5A, 0x02a0),
-	INTC_VECT(IRQ6A, 0x02c0), INTC_VECT(IRQ7A, 0x02e0),
-	INTC_VECT(IRQ8A, 0x0300), INTC_VECT(IRQ9A, 0x0320),
-	INTC_VECT(IRQ10A, 0x0340), INTC_VECT(IRQ11A, 0x0360),
-	INTC_VECT(IRQ12A, 0x0380), INTC_VECT(IRQ13A, 0x03a0),
-	INTC_VECT(IRQ14A, 0x03c0), INTC_VECT(IRQ15A, 0x03e0),
-	INTC_VECT(IRQ16A, 0x3200), INTC_VECT(IRQ17A, 0x3220),
-	INTC_VECT(IRQ18A, 0x3240), INTC_VECT(IRQ19A, 0x3260),
-	INTC_VECT(IRQ20A, 0x3280), INTC_VECT(IRQ21A, 0x32a0),
-	INTC_VECT(IRQ22A, 0x32c0), INTC_VECT(IRQ23A, 0x32e0),
-	INTC_VECT(IRQ24A, 0x3300), INTC_VECT(IRQ25A, 0x3320),
-	INTC_VECT(IRQ26A, 0x3340), INTC_VECT(IRQ27A, 0x3360),
-	INTC_VECT(IRQ28A, 0x3380), INTC_VECT(IRQ29A, 0x33a0),
-	INTC_VECT(IRQ30A, 0x33c0), INTC_VECT(IRQ31A, 0x33e0),
 	INTC_VECT(DIRC, 0x0560),
 	INTC_VECT(CRYPT_STD, 0x0700),
 	INTC_VECT(IIC1_ALI1, 0x0780), INTC_VECT(IIC1_TACKI1, 0x07a0),
@@ -203,15 +184,6 @@
 };
 
 static struct intc_mask_reg intca_mask_registers[] __initdata = {
-	{ 0xe6900040, 0xe6900060, 8, /* INTMSK00A / INTMSKCLR00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900044, 0xe6900064, 8, /* INTMSK10A / INTMSKCLR10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-	{ 0xe6900048, 0xe6900068, 8, /* INTMSK20A / INTMSKCLR20A */
-	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
-	{ 0xe690004c, 0xe690006c, 8, /* INTMSK30A / INTMSKCLR30A */
-	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
-
 	{ 0xe6940080, 0xe69400c0, 8, /* IMR0A / IMCR0A */
 	  { DMAC2_1_DEI3, DMAC2_1_DEI2, DMAC2_1_DEI1, DMAC2_1_DEI0,
 	    AP_ARM_IRQPMU, 0, AP_ARM_COMMTX, AP_ARM_COMMRX } },
@@ -282,15 +254,6 @@
 };
 
 static struct intc_prio_reg intca_prio_registers[] __initdata = {
-	{ 0xe6900010, 0, 32, 4, /* INTPRI00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900014, 0, 32, 4, /* INTPRI10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-	{ 0xe6900018, 0, 32, 4, /* INTPRI20A */
-	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
-	{ 0xe690001c, 0, 32, 4, /* INTPRI30A */
-	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
-
 	{ 0xe6940000, 0, 16, 4, /* IPRAA */ { DMAC3_1, DMAC3_2, CMT2, 0 } },
 	{ 0xe6940004, 0, 16, 4, /* IPRBA */ { IRDA, 0, BBIF1, BBIF2 } },
 	{ 0xe6940008, 0, 16, 4, /* IPRCA */ { 0, CRYPT_STD,
@@ -336,33 +299,13 @@
 	{ 0xe6950050, 0, 16, 4, /* IPRUA3 */ { USBHSDMAC1_USHDMI, 0, 0, 0 } },
 };
 
-static struct intc_sense_reg intca_sense_registers[] __initdata = {
-	{ 0xe6900000, 32, 4, /* ICR1A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900004, 32, 4, /* ICR2A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-	{ 0xe6900008, 32, 4, /* ICR3A */
-	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
-	{ 0xe690000c, 32, 4, /* ICR4A */
-	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
-};
-
-static struct intc_mask_reg intca_ack_registers[] __initdata = {
-	{ 0xe6900020, 0, 8, /* INTREQ00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900024, 0, 8, /* INTREQ10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-	{ 0xe6900028, 0, 8, /* INTREQ20A */
-	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
-	{ 0xe690002c, 0, 8, /* INTREQ30A */
-	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
-};
-
-static DECLARE_INTC_DESC_ACK(intca_desc, "sh7372-intca",
-			     intca_vectors, intca_groups,
-			     intca_mask_registers, intca_prio_registers,
-			     intca_sense_registers, intca_ack_registers);
+static DECLARE_INTC_DESC(intca_desc, "sh7372-intca",
+			 intca_vectors, intca_groups,
+			 intca_mask_registers, intca_prio_registers,
+			 NULL);
 
+INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
+		 INTC_VECT, "sh7372-intca-irq-pins");
 enum {
 	UNUSED_INTCS = 0,
 	ENABLED_INTCS,
@@ -606,14 +549,65 @@
 	generic_handle_irq(intcs_evt2irq(evtcodeas));
 }
 
+static void __iomem *intcs_ffd2;
+static void __iomem *intcs_ffd5;
+
 void __init sh7372_init_irq(void)
 {
-	void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
+	void __iomem *intevtsa;
+
+	intcs_ffd2 = ioremap_nocache(0xffd20000, PAGE_SIZE);
+	intevtsa = intcs_ffd2 + 0x100;
+	intcs_ffd5 = ioremap_nocache(0xffd50000, PAGE_SIZE);
 
 	register_intc_controller(&intca_desc);
+	register_intc_controller(&intca_irq_pins_desc);
 	register_intc_controller(&intcs_desc);
 
 	/* demux using INTEVTSA */
 	irq_set_handler_data(evt2irq(0xf80), (void *)intevtsa);
 	irq_set_chained_handler(evt2irq(0xf80), intcs_demux);
 }
+
+static unsigned short ffd2[0x200];
+static unsigned short ffd5[0x100];
+
+void sh7372_intcs_suspend(void)
+{
+	int k;
+
+	for (k = 0x00; k <= 0x30; k += 4)
+		ffd2[k] = __raw_readw(intcs_ffd2 + k);
+
+	for (k = 0x80; k <= 0xb0; k += 4)
+		ffd2[k] = __raw_readb(intcs_ffd2 + k);
+
+	for (k = 0x180; k <= 0x188; k += 4)
+		ffd2[k] = __raw_readb(intcs_ffd2 + k);
+
+	for (k = 0x00; k <= 0x3c; k += 4)
+		ffd5[k] = __raw_readw(intcs_ffd5 + k);
+
+	for (k = 0x80; k <= 0x9c; k += 4)
+		ffd5[k] = __raw_readb(intcs_ffd5 + k);
+}
+
+void sh7372_intcs_resume(void)
+{
+	int k;
+
+	for (k = 0x00; k <= 0x30; k += 4)
+		__raw_writew(ffd2[k], intcs_ffd2 + k);
+
+	for (k = 0x80; k <= 0xb0; k += 4)
+		__raw_writeb(ffd2[k], intcs_ffd2 + k);
+
+	for (k = 0x180; k <= 0x188; k += 4)
+		__raw_writeb(ffd2[k], intcs_ffd2 + k);
+
+	for (k = 0x00; k <= 0x3c; k += 4)
+		__raw_writew(ffd5[k], intcs_ffd5 + k);
+
+	for (k = 0x80; k <= 0x9c; k += 4)
+		__raw_writeb(ffd5[k], intcs_ffd5 + k);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/intc-sh7377.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/intc-sh7377.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/intc-sh7377.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/intc-sh7377.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sh_intc.h>
+#include <mach/intc.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -31,10 +32,6 @@
 	DISABLED,
 
 	/* interrupt sources INTCA */
-	IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A,
-	IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A,
-	IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A,
-	IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A,
 	DIRC,
 	_2DG,
 	CRYPT_STD,
@@ -91,22 +88,6 @@
 };
 
 static struct intc_vect intca_vectors[] __initdata = {
-	INTC_VECT(IRQ0A, 0x0200), INTC_VECT(IRQ1A, 0x0220),
-	INTC_VECT(IRQ2A, 0x0240), INTC_VECT(IRQ3A, 0x0260),
-	INTC_VECT(IRQ4A, 0x0280), INTC_VECT(IRQ5A, 0x02a0),
-	INTC_VECT(IRQ6A, 0x02c0), INTC_VECT(IRQ7A, 0x02e0),
-	INTC_VECT(IRQ8A, 0x0300), INTC_VECT(IRQ9A, 0x0320),
-	INTC_VECT(IRQ10A, 0x0340), INTC_VECT(IRQ11A, 0x0360),
-	INTC_VECT(IRQ12A, 0x0380), INTC_VECT(IRQ13A, 0x03a0),
-	INTC_VECT(IRQ14A, 0x03c0), INTC_VECT(IRQ15A, 0x03e0),
-	INTC_VECT(IRQ16A, 0x3200), INTC_VECT(IRQ17A, 0x3220),
-	INTC_VECT(IRQ18A, 0x3240), INTC_VECT(IRQ19A, 0x3260),
-	INTC_VECT(IRQ20A, 0x3280), INTC_VECT(IRQ31A, 0x32a0),
-	INTC_VECT(IRQ22A, 0x32c0), INTC_VECT(IRQ23A, 0x32e0),
-	INTC_VECT(IRQ24A, 0x3300), INTC_VECT(IRQ25A, 0x3320),
-	INTC_VECT(IRQ26A, 0x3340), INTC_VECT(IRQ27A, 0x3360),
-	INTC_VECT(IRQ28A, 0x3380), INTC_VECT(IRQ29A, 0x33a0),
-	INTC_VECT(IRQ30A, 0x33c0), INTC_VECT(IRQ31A, 0x33e0),
 	INTC_VECT(DIRC, 0x0560),
 	INTC_VECT(_2DG, 0x05e0),
 	INTC_VECT(CRYPT_STD, 0x0700),
@@ -203,15 +184,6 @@
 };
 
 static struct intc_mask_reg intca_mask_registers[] __initdata = {
-	{ 0xe6900040, 0xe6900060, 8, /* INTMSK00A / INTMSKCLR00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900044, 0xe6900064, 8, /* INTMSK10A / INTMSKCLR10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-	{ 0xe6900048, 0xe6900068, 8, /* INTMSK20A / INTMSKCLR20A */
-	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
-	{ 0xe690004c, 0xe690006c, 8, /* INTMSK30A / INTMSKCLR30A */
-	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
-
 	{ 0xe6940080, 0xe69400c0, 8, /* IMR0A / IMCR0A */
 	  { DMAC2_1_DEI3, DMAC2_1_DEI2, DMAC2_1_DEI1, DMAC2_1_DEI0,
 	    AP_ARM_IRQPMU, 0, AP_ARM_COMMTX, AP_ARM_COMMRX } },
@@ -273,15 +245,6 @@
 };
 
 static struct intc_prio_reg intca_prio_registers[] __initdata = {
-	{ 0xe6900010, 0, 32, 4, /* INTPRI00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900014, 0, 32, 4, /* INTPRI10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-	{ 0xe6900018, 0, 32, 4, /* INTPRI10A */
-	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
-	{ 0xe690001c, 0, 32, 4, /* INTPRI30A */
-	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
-
 	{ 0xe6940000, 0, 16, 4, /* IPRAA */ { DMAC3_1, DMAC3_2, CMT2, LCRC } },
 	{ 0xe6940004, 0, 16, 4, /* IPRBA */ { IRDA, 0, BBIF1, BBIF2 } },
 	{ 0xe6940008, 0, 16, 4, /* IPRCA */ { _2DG, CRYPT_STD,
@@ -315,37 +278,18 @@
 	{ 0xe694003c, 0, 16, 4, /* IPRPA3 */ { SCIFA6, 0, 0, 0 } },
 };
 
-static struct intc_sense_reg intca_sense_registers[] __initdata = {
-	{ 0xe6900000, 16, 2, /* ICR1A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900004, 16, 2, /* ICR2A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-	{ 0xe6900008, 16, 2, /* ICR3A */
-	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
-	{ 0xe690000c, 16, 2, /* ICR4A */
-	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
-};
-
-static struct intc_mask_reg intca_ack_registers[] __initdata = {
-	{ 0xe6900020, 0, 8, /* INTREQ00A */
-	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
-	{ 0xe6900024, 0, 8, /* INTREQ10A */
-	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
-	{ 0xe6900028, 0, 8, /* INTREQ20A */
-	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
-	{ 0xe690002c, 0, 8, /* INTREQ30A */
-	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
-};
-
 static struct intc_desc intca_desc __initdata = {
 	.name = "sh7377-intca",
 	.force_enable = ENABLED,
 	.force_disable = DISABLED,
 	.hw = INTC_HW_DESC(intca_vectors, intca_groups,
 			   intca_mask_registers, intca_prio_registers,
-			   intca_sense_registers, intca_ack_registers),
+			   NULL, NULL),
 };
 
+INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
+		 INTC_VECT, "sh7377-intca-irq-pins");
+
 /* this macro ignore entry which is also in INTCA */
 #define __IGNORE(a...)
 #define __IGNORE0(a...) 0
@@ -638,6 +582,7 @@
 	void __iomem *intevtsa = ioremap_nocache(INTEVTSA, PAGE_SIZE);
 
 	register_intc_controller(&intca_desc);
+	register_intc_controller(&intca_irq_pins_desc);
 	register_intc_controller(&intcs_desc);
 
 	/* demux using INTEVTSA */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/intc-sh73a0.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/intc-sh73a0.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/intc-sh73a0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/intc-sh73a0.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,8 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sh_intc.h>
+#include <mach/intc.h>
+#include <mach/sh73a0.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -255,20 +257,205 @@
 	return 0; /* always allow wakeup */
 }
 
+#define RELOC_BASE 0x1000
+
+/* INTCA IRQ pins at INTCS + 0x1000 to make space for GIC+INTC handling */
+#define INTCS_VECT_RELOC(n, vect) INTCS_VECT((n), (vect) + RELOC_BASE)
+
+INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
+		 INTCS_VECT_RELOC, "sh73a0-intca-irq-pins");
+
+static int to_gic_irq(struct irq_data *data)
+{
+	unsigned int vect = irq2evt(data->irq) - INTCS_VECT_BASE;
+
+	if (vect >= 0x3200)
+		vect -= 0x3000;
+	else
+		vect -= 0x0200;
+
+	return gic_spi((vect >> 5) + 1);
+}
+
+static int to_intca_reloc_irq(struct irq_data *data)
+{
+	return data->irq + (RELOC_BASE >> 5);
+}
+
+#define irq_cb(cb, irq) irq_get_chip(irq)->cb(irq_get_irq_data(irq))
+#define irq_cbp(cb, irq, p...) irq_get_chip(irq)->cb(irq_get_irq_data(irq), p)
+
+static void intca_gic_enable(struct irq_data *data)
+{
+	irq_cb(irq_unmask, to_intca_reloc_irq(data));
+	irq_cb(irq_unmask, to_gic_irq(data));
+}
+
+static void intca_gic_disable(struct irq_data *data)
+{
+	irq_cb(irq_mask, to_gic_irq(data));
+	irq_cb(irq_mask, to_intca_reloc_irq(data));
+}
+
+static void intca_gic_mask_ack(struct irq_data *data)
+{
+	irq_cb(irq_mask, to_gic_irq(data));
+	irq_cb(irq_mask_ack, to_intca_reloc_irq(data));
+}
+
+static void intca_gic_eoi(struct irq_data *data)
+{
+	irq_cb(irq_eoi, to_gic_irq(data));
+}
+
+static int intca_gic_set_type(struct irq_data *data, unsigned int type)
+{
+	return irq_cbp(irq_set_type, to_intca_reloc_irq(data), type);
+}
+
+static int intca_gic_set_wake(struct irq_data *data, unsigned int on)
+{
+	return irq_cbp(irq_set_wake, to_intca_reloc_irq(data), on);
+}
+
+#ifdef CONFIG_SMP
+static int intca_gic_set_affinity(struct irq_data *data,
+				  const struct cpumask *cpumask,
+				  bool force)
+{
+	return irq_cbp(irq_set_affinity, to_gic_irq(data), cpumask, force);
+}
+#endif
+
+struct irq_chip intca_gic_irq_chip = {
+	.name			= "INTCA-GIC",
+	.irq_mask		= intca_gic_disable,
+	.irq_unmask		= intca_gic_enable,
+	.irq_mask_ack		= intca_gic_mask_ack,
+	.irq_eoi		= intca_gic_eoi,
+	.irq_enable		= intca_gic_enable,
+	.irq_disable		= intca_gic_disable,
+	.irq_shutdown		= intca_gic_disable,
+	.irq_set_type		= intca_gic_set_type,
+	.irq_set_wake		= intca_gic_set_wake,
+#ifdef CONFIG_SMP
+	.irq_set_affinity	= intca_gic_set_affinity,
+#endif
+};
+
+static int to_intc_vect(int irq)
+{
+	unsigned int irq_pin = irq - gic_spi(1);
+	unsigned int offs;
+
+	if (irq_pin < 16)
+		offs = 0x0200;
+	else
+		offs = 0x3000;
+
+	return offs + (irq_pin << 5);
+}
+
+static irqreturn_t sh73a0_irq_pin_demux(int irq, void *dev_id)
+{
+	generic_handle_irq(intcs_evt2irq(to_intc_vect(irq)));
+	return IRQ_HANDLED;
+}
+
+static struct irqaction sh73a0_irq_pin_cascade[32];
+
+#define PINTER0 0xe69000a0
+#define PINTER1 0xe69000a4
+#define PINTRR0 0xe69000d0
+#define PINTRR1 0xe69000d4
+
+#define PINT0A_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq))
+#define PINT0B_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 8))
+#define PINT0C_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 16))
+#define PINT0D_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 24))
+#define PINT1E_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT1_IRQ(irq))
+
+INTC_PINT(intc_pint0, PINTER0, 0xe69000b0, "sh73a0-pint0",		\
+  INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D),	\
+  INTC_PINT_V(A, PINT0A_IRQ), INTC_PINT_V(B, PINT0B_IRQ),		\
+  INTC_PINT_V(C, PINT0C_IRQ), INTC_PINT_V(D, PINT0D_IRQ),		\
+  INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D),	\
+  INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D));
+
+INTC_PINT(intc_pint1, PINTER1, 0xe69000c0, "sh73a0-pint1",		\
+  INTC_PINT_E(E), INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, \
+  INTC_PINT_V(E, PINT1E_IRQ), INTC_PINT_V_NONE,				\
+  INTC_PINT_V_NONE, INTC_PINT_V_NONE,					\
+  INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E(E), \
+  INTC_PINT_E(E), INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E_NONE);
+
+static struct irqaction sh73a0_pint0_cascade;
+static struct irqaction sh73a0_pint1_cascade;
+
+static void pint_demux(unsigned long rr, unsigned long er, int base_irq)
+{
+	unsigned long value =  ioread32(rr) & ioread32(er);
+	int k;
+
+	for (k = 0; k < 32; k++) {
+		if (value & (1 << (31 - k))) {
+			generic_handle_irq(base_irq + k);
+			iowrite32(~(1 << (31 - k)), rr);
+		}
+	}
+}
+
+static irqreturn_t sh73a0_pint0_demux(int irq, void *dev_id)
+{
+	pint_demux(PINTRR0, PINTER0, SH73A0_PINT0_IRQ(0));
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t sh73a0_pint1_demux(int irq, void *dev_id)
+{
+	pint_demux(PINTRR1, PINTER1, SH73A0_PINT1_IRQ(0));
+	return IRQ_HANDLED;
+}
+
 void __init sh73a0_init_irq(void)
 {
 	void __iomem *gic_dist_base = __io(0xf0001000);
 	void __iomem *gic_cpu_base = __io(0xf0000100);
 	void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
+	int k, n;
 
 	gic_init(0, 29, gic_dist_base, gic_cpu_base);
 	gic_arch_extn.irq_set_wake = sh73a0_set_wake;
 
 	register_intc_controller(&intcs_desc);
+	register_intc_controller(&intca_irq_pins_desc);
+	register_intc_controller(&intc_pint0_desc);
+	register_intc_controller(&intc_pint1_desc);
 
 	/* demux using INTEVTSA */
 	sh73a0_intcs_cascade.name = "INTCS cascade";
 	sh73a0_intcs_cascade.handler = sh73a0_intcs_demux;
 	sh73a0_intcs_cascade.dev_id = intevtsa;
 	setup_irq(gic_spi(50), &sh73a0_intcs_cascade);
+
+	/* IRQ pins require special handling through INTCA and GIC */
+	for (k = 0; k < 32; k++) {
+		sh73a0_irq_pin_cascade[k].name = "INTCA-GIC cascade";
+		sh73a0_irq_pin_cascade[k].handler = sh73a0_irq_pin_demux;
+		setup_irq(gic_spi(1 + k), &sh73a0_irq_pin_cascade[k]);
+
+		n = intcs_evt2irq(to_intc_vect(gic_spi(1 + k)));
+		irq_set_chip_and_handler_name(n, &intca_gic_irq_chip,
+					      handle_level_irq, "level");
+		set_irq_flags(n, IRQF_VALID); /* yuck */
+	}
+
+	/* PINT pins are sanely tied to the GIC as SPI */
+	sh73a0_pint0_cascade.name = "PINT0 cascade";
+	sh73a0_pint0_cascade.handler = sh73a0_pint0_demux;
+	setup_irq(gic_spi(33), &sh73a0_pint0_cascade);
+
+	sh73a0_pint1_cascade.name = "PINT1 cascade";
+	sh73a0_pint1_cascade.handler = sh73a0_pint1_demux;
+	setup_irq(gic_spi(34), &sh73a0_pint1_cascade);
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/Kconfig linux-libre-3.2-gnu/arch/arm/mach-shmobile/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 	select SH_CLK_CPG
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARM_GIC
+	select I2C
 
 comment "SH-Mobile Board Type"
 
@@ -69,6 +70,11 @@
 	depends on ARCH_SH7372
 	select ARCH_REQUIRE_GPIOLIB
 
+config MACH_KOTA2
+	bool "KOTA2 board"
+	select ARCH_REQUIRE_GPIOLIB
+	depends on ARCH_SH73A0
+
 comment "SH-Mobile System Configuration"
 
 menu "Memory configuration"
@@ -78,6 +84,7 @@
 	default "0x50000000" if MACH_G3EVM
 	default "0x40000000" if MACH_G4EVM || MACH_AP4EVB || MACH_AG5EVM || \
 				MACH_MACKEREL
+	default "0x41000000" if MACH_KOTA2
 	default "0x00000000"
 	---help---
 	  Tweak this only when porting to a new machine which does not
@@ -89,6 +96,7 @@
 	default "0x08000000" if MACH_G3EVM
 	default "0x08000000" if MACH_G4EVM
 	default "0x20000000" if MACH_AG5EVM
+	default "0x1e000000" if MACH_KOTA2
 	default "0x10000000" if MACH_AP4EVB || MACH_MACKEREL
 	default "0x04000000"
 	help
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/Makefile linux-libre-3.2-gnu/arch/arm/mach-shmobile/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
 #
 
 # Common objects
-obj-y				:= timer.o console.o clock.o pm_runtime.o
+obj-y				:= timer.o console.o clock.o
 
 # CPU objects
 obj-$(CONFIG_ARCH_SH7367)	+= setup-sh7367.o clock-sh7367.o intc-sh7367.o
@@ -41,6 +41,7 @@
 obj-$(CONFIG_MACH_AP4EVB)	+= board-ap4evb.o
 obj-$(CONFIG_MACH_AG5EVM)	+= board-ag5evm.o
 obj-$(CONFIG_MACH_MACKEREL)	+= board-mackerel.o
+obj-$(CONFIG_MACH_KOTA2)	+= board-kota2.o
 
 # Framework support
 obj-$(CONFIG_SMP)		+= $(smp-y)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-shmobile/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 __ZRELADDR	:= $(shell /bin/bash -c 'printf "0x%08x" \
 		     $$[$(CONFIG_MEMORY_START) + 0x8000]')
 
-   zreladdr-y   := $(__ZRELADDR)
+   zreladdr-y   += $(__ZRELADDR)
 
 # Unsupported legacy stuff
 #
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/pfc-sh7367.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/pfc-sh7367.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/pfc-sh7367.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/pfc-sh7367.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,68 +21,49 @@
 #include <linux/gpio.h>
 #include <mach/sh7367.h>
 
-#define _1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define _10(fn, pfx, sfx)				\
-	_1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),	\
-	_1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),	\
-	_1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),	\
-	_1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),	\
-	_1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
-
-#define _90(fn, pfx, sfx)				\
-	_10(fn, pfx##1, sfx), _10(fn, pfx##2, sfx),	\
-	_10(fn, pfx##3, sfx), _10(fn, pfx##4, sfx),	\
-	_10(fn, pfx##5, sfx), _10(fn, pfx##6, sfx),	\
-	_10(fn, pfx##7, sfx), _10(fn, pfx##8, sfx),	\
-	_10(fn, pfx##9, sfx)
-
-#define _273(fn, pfx, sfx)		\
-	_10(fn, pfx, sfx), _90(fn, pfx, sfx),		\
-	_10(fn, pfx##10, sfx), _90(fn, pfx##1, sfx),	\
-	_10(fn, pfx##20, sfx), _10(fn, pfx##21, sfx),	\
-	_10(fn, pfx##22, sfx), _10(fn, pfx##23, sfx),	\
-	_10(fn, pfx##24, sfx), _10(fn, pfx##25, sfx),	\
-	_10(fn, pfx##26, sfx), _1(fn, pfx##270, sfx),	\
-	_1(fn, pfx##271, sfx), _1(fn, pfx##272, sfx)
-
-#define _PORT(pfx, sfx) pfx##_##sfx
-#define PORT_273(str) _273(_PORT, PORT, str)
+#define CPU_ALL_PORT(fn, pfx, sfx)				\
+	PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx),		\
+	PORT_10(fn, pfx##10, sfx), PORT_90(fn, pfx##1, sfx),	\
+	PORT_10(fn, pfx##20, sfx), PORT_10(fn, pfx##21, sfx),	\
+	PORT_10(fn, pfx##22, sfx), PORT_10(fn, pfx##23, sfx),	\
+	PORT_10(fn, pfx##24, sfx), PORT_10(fn, pfx##25, sfx),	\
+	PORT_10(fn, pfx##26, sfx), PORT_1(fn, pfx##270, sfx),	\
+	PORT_1(fn, pfx##271, sfx), PORT_1(fn, pfx##272, sfx)
 
 enum {
 	PINMUX_RESERVED = 0,
 
 	PINMUX_DATA_BEGIN,
-	PORT_273(DATA), /* PORT0_DATA -> PORT272_DATA */
+	PORT_ALL(DATA), /* PORT0_DATA -> PORT272_DATA */
 	PINMUX_DATA_END,
 
 	PINMUX_INPUT_BEGIN,
-	PORT_273(IN), /* PORT0_IN -> PORT272_IN */
+	PORT_ALL(IN), /* PORT0_IN -> PORT272_IN */
 	PINMUX_INPUT_END,
 
 	PINMUX_INPUT_PULLUP_BEGIN,
-	PORT_273(IN_PU), /* PORT0_IN_PU -> PORT272_IN_PU */
+	PORT_ALL(IN_PU), /* PORT0_IN_PU -> PORT272_IN_PU */
 	PINMUX_INPUT_PULLUP_END,
 
 	PINMUX_INPUT_PULLDOWN_BEGIN,
-	PORT_273(IN_PD), /* PORT0_IN_PD -> PORT272_IN_PD */
+	PORT_ALL(IN_PD), /* PORT0_IN_PD -> PORT272_IN_PD */
 	PINMUX_INPUT_PULLDOWN_END,
 
 	PINMUX_OUTPUT_BEGIN,
-	PORT_273(OUT), /* PORT0_OUT -> PORT272_OUT */
+	PORT_ALL(OUT), /* PORT0_OUT -> PORT272_OUT */
 	PINMUX_OUTPUT_END,
 
 	PINMUX_FUNCTION_BEGIN,
-	PORT_273(FN_IN), /* PORT0_FN_IN -> PORT272_FN_IN */
-	PORT_273(FN_OUT), /* PORT0_FN_OUT -> PORT272_FN_OUT */
-	PORT_273(FN0), /* PORT0_FN0 -> PORT272_FN0 */
-	PORT_273(FN1), /* PORT0_FN1 -> PORT272_FN1 */
-	PORT_273(FN2), /* PORT0_FN2 -> PORT272_FN2 */
-	PORT_273(FN3), /* PORT0_FN3 -> PORT272_FN3 */
-	PORT_273(FN4), /* PORT0_FN4 -> PORT272_FN4 */
-	PORT_273(FN5), /* PORT0_FN5 -> PORT272_FN5 */
-	PORT_273(FN6), /* PORT0_FN6 -> PORT272_FN6 */
-	PORT_273(FN7), /* PORT0_FN7 -> PORT272_FN7 */
+	PORT_ALL(FN_IN), /* PORT0_FN_IN -> PORT272_FN_IN */
+	PORT_ALL(FN_OUT), /* PORT0_FN_OUT -> PORT272_FN_OUT */
+	PORT_ALL(FN0), /* PORT0_FN0 -> PORT272_FN0 */
+	PORT_ALL(FN1), /* PORT0_FN1 -> PORT272_FN1 */
+	PORT_ALL(FN2), /* PORT0_FN2 -> PORT272_FN2 */
+	PORT_ALL(FN3), /* PORT0_FN3 -> PORT272_FN3 */
+	PORT_ALL(FN4), /* PORT0_FN4 -> PORT272_FN4 */
+	PORT_ALL(FN5), /* PORT0_FN5 -> PORT272_FN5 */
+	PORT_ALL(FN6), /* PORT0_FN6 -> PORT272_FN6 */
+	PORT_ALL(FN7), /* PORT0_FN7 -> PORT272_FN7 */
 
 	MSELBCR_MSEL2_1, MSELBCR_MSEL2_0,
 	PINMUX_FUNCTION_END,
@@ -327,41 +308,6 @@
 	PINMUX_MARK_END,
 };
 
-#define PORT_DATA_I(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_IN)
-
-#define PORT_DATA_I_PD(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-		    PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_I_PU(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-		    PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_I_PU_PD(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-		    PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-#define PORT_DATA_O(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT)
-
-#define PORT_DATA_IO(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-		    PORT##nr##_IN)
-
-#define PORT_DATA_IO_PD(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-		    PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_IO_PU(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-		    PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_IO_PU_PD(nr) \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-		    PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-
 static pinmux_enum_t pinmux_data[] = {
 
 	/* specify valid pin states for each pin in GPIO mode */
@@ -1098,13 +1044,9 @@
 	PINMUX_DATA(DIVLOCK_MARK, PORT272_FN1),
 };
 
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define GPIO_PORT_273() _273(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
-
 static struct pinmux_gpio pinmux_gpios[] = {
 	/* 49-1 -> 49-6 (GPIO) */
-	GPIO_PORT_273(),
+	GPIO_PORT_ALL(),
 
 	/* Special Pull-up / Pull-down Functions */
 	GPIO_FN(PORT48_KEYIN0_PU), GPIO_FN(PORT49_KEYIN1_PU),
@@ -1345,22 +1287,6 @@
 	GPIO_FN(DIVLOCK),
 };
 
-/* helper for top 4 bits in PORTnCR */
-#define PCRH(in, in_pd, in_pu, out)		\
-	0, (out), (in), 0,			\
-	0, 0, 0, 0,				\
-	0, 0, (in_pd), 0,			\
-	0, 0, (in_pu), 0
-
-#define PORTCR(nr, reg)						\
-	{ PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {		\
-		PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,		\
-		     PORT##nr##_IN_PU, PORT##nr##_OUT),		\
-		PORT##nr##_FN0, PORT##nr##_FN1, PORT##nr##_FN2,	\
-		PORT##nr##_FN3,	PORT##nr##_FN4, PORT##nr##_FN5,	\
-		PORT##nr##_FN6, PORT##nr##_FN7 }		\
-	}
-
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	PORTCR(0, 0xe6050000), /* PORT0CR */
 	PORTCR(1, 0xe6050001), /* PORT1CR */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/pfc-sh7372.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/pfc-sh7372.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/pfc-sh7372.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/pfc-sh7372.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,27 +25,13 @@
 #include <linux/gpio.h>
 #include <mach/sh7372.h>
 
-#define _1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define _10(fn, pfx, sfx)				\
-	_1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),	\
-	_1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),	\
-	_1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),	\
-	_1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),	\
-	_1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
-
-#define _80(fn, pfx, sfx)				\
-	_10(fn, pfx##1, sfx),	_10(fn, pfx##2, sfx),	\
-	_10(fn, pfx##3, sfx),	_10(fn, pfx##4, sfx),	\
-	_10(fn, pfx##5, sfx),	_10(fn, pfx##6, sfx),	\
-	_10(fn, pfx##7, sfx),	_10(fn, pfx##8, sfx)
-
-#define _190(fn, pfx, sfx) \
-	_10(fn, pfx, sfx), _80(fn, pfx, sfx), _10(fn, pfx##9, sfx), \
-	_10(fn, pfx##10, sfx), _80(fn, pfx##1, sfx), _1(fn, pfx##190, sfx)
-
-#define _PORT(pfx, sfx) pfx##_##sfx
-#define PORT_ALL(str) _190(_PORT, PORT, str)
+#define CPU_ALL_PORT(fn, pfx, sfx) \
+	PORT_10(fn, pfx, sfx),		PORT_90(fn, pfx, sfx), \
+	PORT_10(fn, pfx##10, sfx),	PORT_10(fn, pfx##11, sfx), \
+	PORT_10(fn, pfx##12, sfx),	PORT_10(fn, pfx##13, sfx), \
+	PORT_10(fn, pfx##14, sfx),	PORT_10(fn, pfx##15, sfx), \
+	PORT_10(fn, pfx##16, sfx),	PORT_10(fn, pfx##17, sfx), \
+	PORT_10(fn, pfx##18, sfx),	PORT_1(fn, pfx##190, sfx)
 
 enum {
 	PINMUX_RESERVED = 0,
@@ -381,108 +367,124 @@
 	PINMUX_MARK_END,
 };
 
-/* PORT_DATA_I_PD(nr) */
-#define _I___D(nr)			     \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-		    PORT##nr##_IN, PORT##nr##_IN_PD)
-
-/* PORT_DATA_I_PU(nr) */
-#define _I__U_(nr)			     \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-		    PORT##nr##_IN, PORT##nr##_IN_PU)
-
-/* PORT_DATA_I_PU_PD(nr) */
-#define _I__UD(nr)			     \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-		    PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-/* PORT_DATA_O(nr) */
-#define __O___(nr)							\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT)
-
-/* PORT_DATA_IO(nr) */
-#define _IO___(nr)				     \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-		    PORT##nr##_IN)
-
-/* PORT_DATA_IO_PD(nr) */
-#define _IO__D(nr)					     \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-		    PORT##nr##_IN, PORT##nr##_IN_PD)
-
-/* PORT_DATA_IO_PU(nr) */
-#define _IO_U_(nr)					     \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-		    PORT##nr##_IN, PORT##nr##_IN_PU)
-
-/* PORT_DATA_IO_PU_PD(nr) */
-#define _IO_UD(nr)					     \
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-		    PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-
 static pinmux_enum_t pinmux_data[] = {
 
 	/* specify valid pin states for each pin in GPIO mode */
+	PORT_DATA_IO_PD(0),		PORT_DATA_IO_PD(1),
+	PORT_DATA_O(2),			PORT_DATA_I_PD(3),
+	PORT_DATA_I_PD(4),		PORT_DATA_I_PD(5),
+	PORT_DATA_IO_PU_PD(6),		PORT_DATA_I_PD(7),
+	PORT_DATA_IO_PD(8),		PORT_DATA_O(9),
 
-	_IO__D(0), _IO__D(1), __O___(2), _I___D(3), _I___D(4),
-	_I___D(5), _IO_UD(6), _I___D(7), _IO__D(8), __O___(9),
-
-	__O___(10), __O___(11), _IO_UD(12), _IO__D(13), _IO__D(14),
-	__O___(15), _IO__D(16), _IO__D(17), _I___D(18), _IO___(19),
+	PORT_DATA_O(10),		PORT_DATA_O(11),
+	PORT_DATA_IO_PU_PD(12),		PORT_DATA_IO_PD(13),
+	PORT_DATA_IO_PD(14),		PORT_DATA_O(15),
+	PORT_DATA_IO_PD(16),		PORT_DATA_IO_PD(17),
+	PORT_DATA_I_PD(18),		PORT_DATA_IO(19),
 
-	_IO___(20), _IO___(21), _IO___(22), _IO___(23), _IO___(24),
-	_IO___(25), _IO___(26), _IO___(27), _IO___(28), _IO___(29),
+	PORT_DATA_IO(20),		PORT_DATA_IO(21),
+	PORT_DATA_IO(22),		PORT_DATA_IO(23),
+	PORT_DATA_IO(24),		PORT_DATA_IO(25),
+	PORT_DATA_IO(26),		PORT_DATA_IO(27),
+	PORT_DATA_IO(28),		PORT_DATA_IO(29),
 
-	_IO___(30), _IO___(31), _IO___(32), _IO___(33), _IO___(34),
-	_IO___(35), _IO___(36), _IO___(37), _IO___(38), _IO___(39),
+	PORT_DATA_IO(30),		PORT_DATA_IO(31),
+	PORT_DATA_IO(32),		PORT_DATA_IO(33),
+	PORT_DATA_IO(34),		PORT_DATA_IO(35),
+	PORT_DATA_IO(36),		PORT_DATA_IO(37),
+	PORT_DATA_IO(38),		PORT_DATA_IO(39),
 
-	_IO___(40), _IO___(41), _IO___(42), _IO___(43), _IO___(44),
-	_IO___(45), _IO_U_(46), _IO_U_(47), _IO_U_(48), _IO_U_(49),
+	PORT_DATA_IO(40),		PORT_DATA_IO(41),
+	PORT_DATA_IO(42),		PORT_DATA_IO(43),
+	PORT_DATA_IO(44),		PORT_DATA_IO(45),
+	PORT_DATA_IO_PU(46),		PORT_DATA_IO_PU(47),
+	PORT_DATA_IO_PU(48),		PORT_DATA_IO_PU(49),
 
-	_IO_U_(50), _IO_U_(51), _IO_U_(52), _IO_U_(53), _IO_U_(54),
-	_IO_U_(55), _IO_U_(56), _IO_U_(57), _IO_U_(58), _IO_U_(59),
+	PORT_DATA_IO_PU(50),		PORT_DATA_IO_PU(51),
+	PORT_DATA_IO_PU(52),		PORT_DATA_IO_PU(53),
+	PORT_DATA_IO_PU(54),		PORT_DATA_IO_PU(55),
+	PORT_DATA_IO_PU(56),		PORT_DATA_IO_PU(57),
+	PORT_DATA_IO_PU(58),		PORT_DATA_IO_PU(59),
 
-	_IO_U_(60), _IO_U_(61), _IO___(62), __O___(63), __O___(64),
-	_IO_U_(65), __O___(66), _IO_U_(67), __O___(68), _IO___(69), /*66?*/
+	PORT_DATA_IO_PU(60),		PORT_DATA_IO_PU(61),
+	PORT_DATA_IO(62),		PORT_DATA_O(63),
+	PORT_DATA_O(64),		PORT_DATA_IO_PU(65),
+	PORT_DATA_O(66),		PORT_DATA_IO_PU(67),  /*66?*/
+	PORT_DATA_O(68),		PORT_DATA_IO(69),
 
-	_IO___(70), _IO___(71), __O___(72), _I__U_(73), _I__UD(74),
-	_IO_UD(75), _IO_UD(76), _IO_UD(77), _IO_UD(78), _IO_UD(79),
+	PORT_DATA_IO(70),		PORT_DATA_IO(71),
+	PORT_DATA_O(72),		PORT_DATA_I_PU(73),
+	PORT_DATA_I_PU_PD(74),		PORT_DATA_IO_PU_PD(75),
+	PORT_DATA_IO_PU_PD(76),		PORT_DATA_IO_PU_PD(77),
+	PORT_DATA_IO_PU_PD(78),		PORT_DATA_IO_PU_PD(79),
 
-	_IO_UD(80), _IO_UD(81), _IO_UD(82), _IO_UD(83), _IO_UD(84),
-	_IO_UD(85), _IO_UD(86), _IO_UD(87), _IO_UD(88), _IO_UD(89),
+	PORT_DATA_IO_PU_PD(80),		PORT_DATA_IO_PU_PD(81),
+	PORT_DATA_IO_PU_PD(82),		PORT_DATA_IO_PU_PD(83),
+	PORT_DATA_IO_PU_PD(84),		PORT_DATA_IO_PU_PD(85),
+	PORT_DATA_IO_PU_PD(86),		PORT_DATA_IO_PU_PD(87),
+	PORT_DATA_IO_PU_PD(88),		PORT_DATA_IO_PU_PD(89),
 
-	_IO_UD(90), _IO_UD(91), _IO_UD(92), _IO_UD(93), _IO_UD(94),
-	_IO_UD(95), _IO_U_(96), _IO_UD(97), _IO_UD(98), __O___(99), /*99?*/
+	PORT_DATA_IO_PU_PD(90),		PORT_DATA_IO_PU_PD(91),
+	PORT_DATA_IO_PU_PD(92),		PORT_DATA_IO_PU_PD(93),
+	PORT_DATA_IO_PU_PD(94),		PORT_DATA_IO_PU_PD(95),
+	PORT_DATA_IO_PU(96),		PORT_DATA_IO_PU_PD(97),
+	PORT_DATA_IO_PU_PD(98),		PORT_DATA_O(99), /*99?*/
 
-	_IO__D(100), _IO__D(101), _IO__D(102), _IO__D(103), _IO__D(104),
-	_IO__D(105), _IO_U_(106), _IO_U_(107), _IO_U_(108), _IO_U_(109),
+	PORT_DATA_IO_PD(100),		PORT_DATA_IO_PD(101),
+	PORT_DATA_IO_PD(102),		PORT_DATA_IO_PD(103),
+	PORT_DATA_IO_PD(104),		PORT_DATA_IO_PD(105),
+	PORT_DATA_IO_PU(106),		PORT_DATA_IO_PU(107),
+	PORT_DATA_IO_PU(108),		PORT_DATA_IO_PU(109),
 
-	_IO_U_(110), _IO_U_(111), _IO__D(112), _IO__D(113), _IO_U_(114),
-	_IO_U_(115), _IO_U_(116), _IO_U_(117), _IO_U_(118), _IO_U_(119),
+	PORT_DATA_IO_PU(110),		PORT_DATA_IO_PU(111),
+	PORT_DATA_IO_PD(112),		PORT_DATA_IO_PD(113),
+	PORT_DATA_IO_PU(114),		PORT_DATA_IO_PU(115),
+	PORT_DATA_IO_PU(116),		PORT_DATA_IO_PU(117),
+	PORT_DATA_IO_PU(118),		PORT_DATA_IO_PU(119),
 
-	_IO_U_(120), _IO__D(121), _IO__D(122), _IO__D(123), _IO__D(124),
-	_IO__D(125), _IO__D(126), _IO__D(127), _IO__D(128), _IO_UD(129),
+	PORT_DATA_IO_PU(120),		PORT_DATA_IO_PD(121),
+	PORT_DATA_IO_PD(122),		PORT_DATA_IO_PD(123),
+	PORT_DATA_IO_PD(124),		PORT_DATA_IO_PD(125),
+	PORT_DATA_IO_PD(126),		PORT_DATA_IO_PD(127),
+	PORT_DATA_IO_PD(128),		PORT_DATA_IO_PU_PD(129),
 
-	_IO_UD(130), _IO_UD(131), _IO_UD(132), _IO_UD(133), _IO_UD(134),
-	_IO_UD(135), _IO__D(136), _IO__D(137), _IO__D(138), _IO__D(139),
+	PORT_DATA_IO_PU_PD(130),	PORT_DATA_IO_PU_PD(131),
+	PORT_DATA_IO_PU_PD(132),	PORT_DATA_IO_PU_PD(133),
+	PORT_DATA_IO_PU_PD(134),	PORT_DATA_IO_PU_PD(135),
+	PORT_DATA_IO_PD(136),		PORT_DATA_IO_PD(137),
+	PORT_DATA_IO_PD(138),		PORT_DATA_IO_PD(139),
 
-	_IO__D(140), _IO__D(141), _IO__D(142), _IO_UD(143), _IO__D(144),
-	_IO__D(145), _IO__D(146), _IO__D(147), _IO__D(148), _IO__D(149),
+	PORT_DATA_IO_PD(140),		PORT_DATA_IO_PD(141),
+	PORT_DATA_IO_PD(142),		PORT_DATA_IO_PU_PD(143),
+	PORT_DATA_IO_PD(144),		PORT_DATA_IO_PD(145),
+	PORT_DATA_IO_PD(146),		PORT_DATA_IO_PD(147),
+	PORT_DATA_IO_PD(148),		PORT_DATA_IO_PD(149),
 
-	_IO__D(150), _IO__D(151), _IO_UD(152), _I___D(153), _IO_UD(154),
-	_I___D(155), _IO__D(156), _IO__D(157), _I___D(158), _IO__D(159),
+	PORT_DATA_IO_PD(150),		PORT_DATA_IO_PD(151),
+	PORT_DATA_IO_PU_PD(152),	PORT_DATA_I_PD(153),
+	PORT_DATA_IO_PU_PD(154),	PORT_DATA_I_PD(155),
+	PORT_DATA_IO_PD(156),		PORT_DATA_IO_PD(157),
+	PORT_DATA_I_PD(158),		PORT_DATA_IO_PD(159),
 
-	__O___(160), _IO__D(161), _IO__D(162), _IO__D(163), _I___D(164),
-	_IO__D(165), _I___D(166), _I___D(167), _I___D(168), _I___D(169),
+	PORT_DATA_O(160),		PORT_DATA_IO_PD(161),
+	PORT_DATA_IO_PD(162),		PORT_DATA_IO_PD(163),
+	PORT_DATA_I_PD(164),		PORT_DATA_IO_PD(165),
+	PORT_DATA_I_PD(166),		PORT_DATA_I_PD(167),
+	PORT_DATA_I_PD(168),		PORT_DATA_I_PD(169),
 
-	_I___D(170), __O___(171), _IO_UD(172), _IO_UD(173), _IO_UD(174),
-	_IO_UD(175), _IO_UD(176), _IO_UD(177), _IO_UD(178), __O___(179),
+	PORT_DATA_I_PD(170),		PORT_DATA_O(171),
+	PORT_DATA_IO_PU_PD(172),	PORT_DATA_IO_PU_PD(173),
+	PORT_DATA_IO_PU_PD(174),	PORT_DATA_IO_PU_PD(175),
+	PORT_DATA_IO_PU_PD(176),	PORT_DATA_IO_PU_PD(177),
+	PORT_DATA_IO_PU_PD(178),	PORT_DATA_O(179),
 
-	_IO_UD(180), _IO_UD(181), _IO_UD(182), _IO_UD(183), _IO_UD(184),
-	__O___(185), _IO_UD(186), _IO_UD(187), _IO_UD(188), _IO_UD(189),
+	PORT_DATA_IO_PU_PD(180),	PORT_DATA_IO_PU_PD(181),
+	PORT_DATA_IO_PU_PD(182),	PORT_DATA_IO_PU_PD(183),
+	PORT_DATA_IO_PU_PD(184),	PORT_DATA_O(185),
+	PORT_DATA_IO_PU_PD(186),	PORT_DATA_IO_PU_PD(187),
+	PORT_DATA_IO_PU_PD(188),	PORT_DATA_IO_PU_PD(189),
 
-	_IO_UD(190),
+	PORT_DATA_IO_PU_PD(190),
 
 	/* IRQ */
 	PINMUX_DATA(IRQ0_6_MARK,	PORT6_FN0, 	MSEL1CR_0_0),
@@ -926,10 +928,6 @@
 	PINMUX_DATA(MFIv4_MARK,		MSEL4CR_6_1),
 };
 
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define GPIO_PORT_ALL() _190(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
-
 static struct pinmux_gpio pinmux_gpios[] = {
 
 	/* PORT */
@@ -1201,22 +1199,6 @@
 	GPIO_FN(SDENC_DV_CLKI),
 };
 
-/* helper for top 4 bits in PORTnCR */
-#define PCRH(in, in_pd, in_pu, out)		\
-	0, (out), (in), 0,			\
-	0, 0, 0, 0,				\
-	0, 0, (in_pd), 0,			\
-	0, 0, (in_pu), 0
-
-#define PORTCR(nr, reg)						\
-	{ PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {		\
-		PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,		\
-		     PORT##nr##_IN_PU, PORT##nr##_OUT),		\
-		PORT##nr##_FN0, PORT##nr##_FN1, PORT##nr##_FN2,	\
-		PORT##nr##_FN3,	PORT##nr##_FN4, PORT##nr##_FN5,	\
-		PORT##nr##_FN6, PORT##nr##_FN7 }		\
-	}
-
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	PORTCR(0,	0xE6051000), /* PORT0CR */
 	PORTCR(1,	0xE6051001), /* PORT1CR */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/pfc-sh7377.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/pfc-sh7377.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/pfc-sh7377.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/pfc-sh7377.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,84 +22,65 @@
 #include <linux/gpio.h>
 #include <mach/sh7377.h>
 
-#define _1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define _10(fn, pfx, sfx)				\
-	_1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),	\
-	_1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),	\
-	_1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),	\
-	_1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),	\
-	_1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
-
-#define _90(fn, pfx, sfx)				\
-	_10(fn, pfx##1, sfx), _10(fn, pfx##2, sfx),	\
-	_10(fn, pfx##3, sfx), _10(fn, pfx##4, sfx),	\
-	_10(fn, pfx##5, sfx), _10(fn, pfx##6, sfx),	\
-	_10(fn, pfx##7, sfx), _10(fn, pfx##8, sfx),	\
-	_10(fn, pfx##9, sfx)
-
-#define _265(fn, pfx, sfx)				\
-	_10(fn, pfx, sfx), _90(fn, pfx, sfx),		\
-	_10(fn, pfx##10, sfx),				\
-	_1(fn, pfx##110, sfx), _1(fn, pfx##111, sfx),	\
-	_1(fn, pfx##112, sfx), _1(fn, pfx##113, sfx),	\
-	_1(fn, pfx##114, sfx), _1(fn, pfx##115, sfx),	\
-	_1(fn, pfx##116, sfx), _1(fn, pfx##117, sfx),	\
-	_1(fn, pfx##118, sfx),				\
-	_1(fn, pfx##128, sfx), _1(fn, pfx##129, sfx),	\
-	_10(fn, pfx##13, sfx), _10(fn, pfx##14, sfx),	\
-	_10(fn, pfx##15, sfx),				\
-	_1(fn, pfx##160, sfx), _1(fn, pfx##161, sfx),	\
-	_1(fn, pfx##162, sfx), _1(fn, pfx##163, sfx),	\
-	_1(fn, pfx##164, sfx),				\
-	_1(fn, pfx##192, sfx), _1(fn, pfx##193, sfx),	\
-	_1(fn, pfx##194, sfx), _1(fn, pfx##195, sfx),	\
-	_1(fn, pfx##196, sfx), _1(fn, pfx##197, sfx),	\
-	_1(fn, pfx##198, sfx), _1(fn, pfx##199, sfx),	\
-	_10(fn, pfx##20, sfx), _10(fn, pfx##21, sfx),	\
-	_10(fn, pfx##22, sfx), _10(fn, pfx##23, sfx),	\
-	_10(fn, pfx##24, sfx), _10(fn, pfx##25, sfx),	\
-	_1(fn, pfx##260, sfx), _1(fn, pfx##261, sfx),	\
-	_1(fn, pfx##262, sfx), _1(fn, pfx##263, sfx),	\
-	_1(fn, pfx##264, sfx)
-
-#define _PORT(pfx, sfx) pfx##_##sfx
-#define PORT_265(str) _265(_PORT, PORT, str)
+#define CPU_ALL_PORT(fn, pfx, sfx)				\
+	PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx),		\
+	PORT_10(fn, pfx##10, sfx),				\
+	PORT_1(fn, pfx##110, sfx), PORT_1(fn, pfx##111, sfx),	\
+	PORT_1(fn, pfx##112, sfx), PORT_1(fn, pfx##113, sfx),	\
+	PORT_1(fn, pfx##114, sfx), PORT_1(fn, pfx##115, sfx),	\
+	PORT_1(fn, pfx##116, sfx), PORT_1(fn, pfx##117, sfx),	\
+	PORT_1(fn, pfx##118, sfx),				\
+	PORT_1(fn, pfx##128, sfx), PORT_1(fn, pfx##129, sfx),	\
+	PORT_10(fn, pfx##13, sfx), PORT_10(fn, pfx##14, sfx),	\
+	PORT_10(fn, pfx##15, sfx),				\
+	PORT_1(fn, pfx##160, sfx), PORT_1(fn, pfx##161, sfx),	\
+	PORT_1(fn, pfx##162, sfx), PORT_1(fn, pfx##163, sfx),	\
+	PORT_1(fn, pfx##164, sfx),				\
+	PORT_1(fn, pfx##192, sfx), PORT_1(fn, pfx##193, sfx),	\
+	PORT_1(fn, pfx##194, sfx), PORT_1(fn, pfx##195, sfx),	\
+	PORT_1(fn, pfx##196, sfx), PORT_1(fn, pfx##197, sfx),	\
+	PORT_1(fn, pfx##198, sfx), PORT_1(fn, pfx##199, sfx),	\
+	PORT_10(fn, pfx##20, sfx), PORT_10(fn, pfx##21, sfx),	\
+	PORT_10(fn, pfx##22, sfx), PORT_10(fn, pfx##23, sfx),	\
+	PORT_10(fn, pfx##24, sfx), PORT_10(fn, pfx##25, sfx),	\
+	PORT_1(fn, pfx##260, sfx), PORT_1(fn, pfx##261, sfx),	\
+	PORT_1(fn, pfx##262, sfx), PORT_1(fn, pfx##263, sfx),	\
+	PORT_1(fn, pfx##264, sfx)
 
 enum {
 	PINMUX_RESERVED = 0,
 
 	PINMUX_DATA_BEGIN,
-	PORT_265(DATA), /* PORT0_DATA -> PORT264_DATA */
+	PORT_ALL(DATA), /* PORT0_DATA -> PORT264_DATA */
 	PINMUX_DATA_END,
 
 	PINMUX_INPUT_BEGIN,
-	PORT_265(IN), /* PORT0_IN -> PORT264_IN */
+	PORT_ALL(IN), /* PORT0_IN -> PORT264_IN */
 	PINMUX_INPUT_END,
 
 	PINMUX_INPUT_PULLUP_BEGIN,
-	PORT_265(IN_PU), /* PORT0_IN_PU -> PORT264_IN_PU */
+	PORT_ALL(IN_PU), /* PORT0_IN_PU -> PORT264_IN_PU */
 	PINMUX_INPUT_PULLUP_END,
 
 	PINMUX_INPUT_PULLDOWN_BEGIN,
-	PORT_265(IN_PD), /* PORT0_IN_PD -> PORT264_IN_PD */
+	PORT_ALL(IN_PD), /* PORT0_IN_PD -> PORT264_IN_PD */
 	PINMUX_INPUT_PULLDOWN_END,
 
 	PINMUX_OUTPUT_BEGIN,
-	PORT_265(OUT), /* PORT0_OUT -> PORT264_OUT */
+	PORT_ALL(OUT), /* PORT0_OUT -> PORT264_OUT */
 	PINMUX_OUTPUT_END,
 
 	PINMUX_FUNCTION_BEGIN,
-	PORT_265(FN_IN), /* PORT0_FN_IN -> PORT264_FN_IN */
-	PORT_265(FN_OUT), /* PORT0_FN_OUT -> PORT264_FN_OUT */
-	PORT_265(FN0), /* PORT0_FN0 -> PORT264_FN0 */
-	PORT_265(FN1), /* PORT0_FN1 -> PORT264_FN1 */
-	PORT_265(FN2), /* PORT0_FN2 -> PORT264_FN2 */
-	PORT_265(FN3), /* PORT0_FN3 -> PORT264_FN3 */
-	PORT_265(FN4), /* PORT0_FN4 -> PORT264_FN4 */
-	PORT_265(FN5), /* PORT0_FN5 -> PORT264_FN5 */
-	PORT_265(FN6), /* PORT0_FN6 -> PORT264_FN6 */
-	PORT_265(FN7), /* PORT0_FN7 -> PORT264_FN7 */
+	PORT_ALL(FN_IN), /* PORT0_FN_IN -> PORT264_FN_IN */
+	PORT_ALL(FN_OUT), /* PORT0_FN_OUT -> PORT264_FN_OUT */
+	PORT_ALL(FN0), /* PORT0_FN0 -> PORT264_FN0 */
+	PORT_ALL(FN1), /* PORT0_FN1 -> PORT264_FN1 */
+	PORT_ALL(FN2), /* PORT0_FN2 -> PORT264_FN2 */
+	PORT_ALL(FN3), /* PORT0_FN3 -> PORT264_FN3 */
+	PORT_ALL(FN4), /* PORT0_FN4 -> PORT264_FN4 */
+	PORT_ALL(FN5), /* PORT0_FN5 -> PORT264_FN5 */
+	PORT_ALL(FN6), /* PORT0_FN6 -> PORT264_FN6 */
+	PORT_ALL(FN7), /* PORT0_FN7 -> PORT264_FN7 */
 
 	MSELBCR_MSEL17_1, MSELBCR_MSEL17_0,
 	MSELBCR_MSEL16_1, MSELBCR_MSEL16_0,
@@ -360,45 +341,6 @@
 	PINMUX_MARK_END,
 };
 
-#define PORT_DATA_I(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_IN)
-
-#define PORT_DATA_I_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_I_PU(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_I_PU_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_IN, PORT##nr##_IN_PD,	\
-				PORT##nr##_IN_PU)
-
-#define PORT_DATA_O(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT)
-
-#define PORT_DATA_IO(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT, PORT##nr##_IN)
-
-#define PORT_DATA_IO_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT, PORT##nr##_IN,		\
-				PORT##nr##_IN_PD)
-
-#define PORT_DATA_IO_PU(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT, PORT##nr##_IN,		\
-				PORT##nr##_IN_PU)
-
-#define PORT_DATA_IO_PU_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT, PORT##nr##_IN,		\
-				PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
 static pinmux_enum_t pinmux_data[] = {
 	/* specify valid pin states for each pin in GPIO mode */
 	/* 55-1 (GPIO) */
@@ -1078,13 +1020,9 @@
 	PINMUX_DATA(RESETOUTS_MARK, PORT264_FN1),
 };
 
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define GPIO_PORT_265() _265(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
-
 static struct pinmux_gpio pinmux_gpios[] = {
 	/* 55-1 -> 55-5 (GPIO) */
-	GPIO_PORT_265(),
+	GPIO_PORT_ALL(),
 
 	/* Special Pull-up / Pull-down Functions */
 	GPIO_FN(PORT66_KEYIN0_PU), GPIO_FN(PORT67_KEYIN1_PU),
@@ -1362,23 +1300,6 @@
 	GPIO_FN(RESETOUTS),
 };
 
-/* helper for top 4 bits in PORTnCR */
-#define PCRH(in, in_pd, in_pu, out)	\
-	0, (out), (in), 0,	\
-		0, 0, 0, 0,	\
-		0, 0, (in_pd), 0,	\
-		0, 0, (in_pu), 0
-
-#define PORTCR(nr, reg)	\
-	{ PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {	\
-			PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,	\
-				 PORT##nr##_IN_PU, PORT##nr##_OUT),	\
-				PORT##nr##_FN0, PORT##nr##_FN1,	\
-				PORT##nr##_FN2, PORT##nr##_FN3,	\
-				PORT##nr##_FN4, PORT##nr##_FN5,	\
-				PORT##nr##_FN6, PORT##nr##_FN7 }	\
-	}
-
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	PORTCR(0, 0xe6050000), /* PORT0CR */
 	PORTCR(1, 0xe6050001), /* PORT1CR */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/pfc-sh73a0.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/pfc-sh73a0.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/pfc-sh73a0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/pfc-sh73a0.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,84 +22,73 @@
 #include <linux/kernel.h>
 #include <linux/gpio.h>
 #include <mach/sh73a0.h>
+#include <mach/irqs.h>
 
-#define _1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define _10(fn, pfx, sfx)				\
-	_1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),	\
-	_1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),	\
-	_1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),	\
-	_1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),	\
-	_1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
-
-#define _310(fn, pfx, sfx)				\
-	_10(fn, pfx,    sfx), _10(fn, pfx##1, sfx),	\
-	_10(fn, pfx##2, sfx), _10(fn, pfx##3, sfx),	\
-	_10(fn, pfx##4, sfx), _10(fn, pfx##5, sfx),	\
-	_10(fn, pfx##6, sfx), _10(fn, pfx##7, sfx),	\
-	_10(fn, pfx##8, sfx), _10(fn, pfx##9, sfx),	\
-	_10(fn, pfx##10, sfx),				\
-	_1(fn, pfx##110, sfx), _1(fn, pfx##111, sfx),	\
-	_1(fn, pfx##112, sfx), _1(fn, pfx##113, sfx),	\
-	_1(fn, pfx##114, sfx), _1(fn, pfx##115, sfx),	\
-	_1(fn, pfx##116, sfx), _1(fn, pfx##117, sfx),	\
-	_1(fn, pfx##118, sfx),				\
-	_1(fn, pfx##128, sfx), _1(fn, pfx##129, sfx),	\
-	_10(fn, pfx##13, sfx), _10(fn, pfx##14, sfx),	\
-	_10(fn, pfx##15, sfx),				\
-	_1(fn, pfx##160, sfx), _1(fn, pfx##161, sfx),	\
-	_1(fn, pfx##162, sfx), _1(fn, pfx##163, sfx),	\
-	_1(fn, pfx##164, sfx),				\
-	_1(fn, pfx##192, sfx), _1(fn, pfx##193, sfx),	\
-	_1(fn, pfx##194, sfx), _1(fn, pfx##195, sfx),	\
-	_1(fn, pfx##196, sfx), _1(fn, pfx##197, sfx),	\
-	_1(fn, pfx##198, sfx), _1(fn, pfx##199, sfx),	\
-	_10(fn, pfx##20, sfx), _10(fn, pfx##21, sfx),	\
-	_10(fn, pfx##22, sfx), _10(fn, pfx##23, sfx),	\
-	_10(fn, pfx##24, sfx), _10(fn, pfx##25, sfx),	\
-	_10(fn, pfx##26, sfx), _10(fn, pfx##27, sfx),	\
-	_1(fn, pfx##280, sfx), _1(fn, pfx##281, sfx),	\
-	_1(fn, pfx##282, sfx),				\
-	_1(fn, pfx##288, sfx), _1(fn, pfx##289, sfx),	\
-	_10(fn, pfx##29, sfx), _10(fn, pfx##30, sfx)
-
-#define _PORT(pfx, sfx) pfx##_##sfx
-#define PORT_310(str) _310(_PORT, PORT, str)
+#define CPU_ALL_PORT(fn, pfx, sfx)				\
+	PORT_10(fn, pfx,    sfx), PORT_10(fn, pfx##1, sfx),	\
+	PORT_10(fn, pfx##2, sfx), PORT_10(fn, pfx##3, sfx),	\
+	PORT_10(fn, pfx##4, sfx), PORT_10(fn, pfx##5, sfx),	\
+	PORT_10(fn, pfx##6, sfx), PORT_10(fn, pfx##7, sfx),	\
+	PORT_10(fn, pfx##8, sfx), PORT_10(fn, pfx##9, sfx),	\
+	PORT_10(fn, pfx##10, sfx),				\
+	PORT_1(fn, pfx##110, sfx), PORT_1(fn, pfx##111, sfx),	\
+	PORT_1(fn, pfx##112, sfx), PORT_1(fn, pfx##113, sfx),	\
+	PORT_1(fn, pfx##114, sfx), PORT_1(fn, pfx##115, sfx),	\
+	PORT_1(fn, pfx##116, sfx), PORT_1(fn, pfx##117, sfx),	\
+	PORT_1(fn, pfx##118, sfx),				\
+	PORT_1(fn, pfx##128, sfx), PORT_1(fn, pfx##129, sfx),	\
+	PORT_10(fn, pfx##13, sfx), PORT_10(fn, pfx##14, sfx),	\
+	PORT_10(fn, pfx##15, sfx),				\
+	PORT_1(fn, pfx##160, sfx), PORT_1(fn, pfx##161, sfx),	\
+	PORT_1(fn, pfx##162, sfx), PORT_1(fn, pfx##163, sfx),	\
+	PORT_1(fn, pfx##164, sfx),				\
+	PORT_1(fn, pfx##192, sfx), PORT_1(fn, pfx##193, sfx),	\
+	PORT_1(fn, pfx##194, sfx), PORT_1(fn, pfx##195, sfx),	\
+	PORT_1(fn, pfx##196, sfx), PORT_1(fn, pfx##197, sfx),	\
+	PORT_1(fn, pfx##198, sfx), PORT_1(fn, pfx##199, sfx),	\
+	PORT_10(fn, pfx##20, sfx), PORT_10(fn, pfx##21, sfx),	\
+	PORT_10(fn, pfx##22, sfx), PORT_10(fn, pfx##23, sfx),	\
+	PORT_10(fn, pfx##24, sfx), PORT_10(fn, pfx##25, sfx),	\
+	PORT_10(fn, pfx##26, sfx), PORT_10(fn, pfx##27, sfx),	\
+	PORT_1(fn, pfx##280, sfx), PORT_1(fn, pfx##281, sfx),	\
+	PORT_1(fn, pfx##282, sfx),				\
+	PORT_1(fn, pfx##288, sfx), PORT_1(fn, pfx##289, sfx),	\
+	PORT_10(fn, pfx##29, sfx), PORT_10(fn, pfx##30, sfx)
 
 enum {
 	PINMUX_RESERVED = 0,
 
 	PINMUX_DATA_BEGIN,
-	PORT_310(DATA),			/* PORT0_DATA -> PORT309_DATA */
+	PORT_ALL(DATA),			/* PORT0_DATA -> PORT309_DATA */
 	PINMUX_DATA_END,
 
 	PINMUX_INPUT_BEGIN,
-	PORT_310(IN),			/* PORT0_IN -> PORT309_IN */
+	PORT_ALL(IN),			/* PORT0_IN -> PORT309_IN */
 	PINMUX_INPUT_END,
 
 	PINMUX_INPUT_PULLUP_BEGIN,
-	PORT_310(IN_PU),		/* PORT0_IN_PU -> PORT309_IN_PU */
+	PORT_ALL(IN_PU),		/* PORT0_IN_PU -> PORT309_IN_PU */
 	PINMUX_INPUT_PULLUP_END,
 
 	PINMUX_INPUT_PULLDOWN_BEGIN,
-	PORT_310(IN_PD),		/* PORT0_IN_PD -> PORT309_IN_PD */
+	PORT_ALL(IN_PD),		/* PORT0_IN_PD -> PORT309_IN_PD */
 	PINMUX_INPUT_PULLDOWN_END,
 
 	PINMUX_OUTPUT_BEGIN,
-	PORT_310(OUT),			/* PORT0_OUT -> PORT309_OUT */
+	PORT_ALL(OUT),			/* PORT0_OUT -> PORT309_OUT */
 	PINMUX_OUTPUT_END,
 
 	PINMUX_FUNCTION_BEGIN,
-	PORT_310(FN_IN),		/* PORT0_FN_IN -> PORT309_FN_IN */
-	PORT_310(FN_OUT),		/* PORT0_FN_OUT -> PORT309_FN_OUT */
-	PORT_310(FN0),			/* PORT0_FN0 -> PORT309_FN0 */
-	PORT_310(FN1),			/* PORT0_FN1 -> PORT309_FN1 */
-	PORT_310(FN2),			/* PORT0_FN2 -> PORT309_FN2 */
-	PORT_310(FN3),			/* PORT0_FN3 -> PORT309_FN3 */
-	PORT_310(FN4),			/* PORT0_FN4 -> PORT309_FN4 */
-	PORT_310(FN5),			/* PORT0_FN5 -> PORT309_FN5 */
-	PORT_310(FN6),			/* PORT0_FN6 -> PORT309_FN6 */
-	PORT_310(FN7),			/* PORT0_FN7 -> PORT309_FN7 */
+	PORT_ALL(FN_IN),		/* PORT0_FN_IN -> PORT309_FN_IN */
+	PORT_ALL(FN_OUT),		/* PORT0_FN_OUT -> PORT309_FN_OUT */
+	PORT_ALL(FN0),			/* PORT0_FN0 -> PORT309_FN0 */
+	PORT_ALL(FN1),			/* PORT0_FN1 -> PORT309_FN1 */
+	PORT_ALL(FN2),			/* PORT0_FN2 -> PORT309_FN2 */
+	PORT_ALL(FN3),			/* PORT0_FN3 -> PORT309_FN3 */
+	PORT_ALL(FN4),			/* PORT0_FN4 -> PORT309_FN4 */
+	PORT_ALL(FN5),			/* PORT0_FN5 -> PORT309_FN5 */
+	PORT_ALL(FN6),			/* PORT0_FN6 -> PORT309_FN6 */
+	PORT_ALL(FN7),			/* PORT0_FN7 -> PORT309_FN7 */
 
 	MSEL2CR_MSEL19_0, MSEL2CR_MSEL19_1,
 	MSEL2CR_MSEL18_0, MSEL2CR_MSEL18_1,
@@ -488,13 +477,34 @@
 	KEYIN5_PU_MARK,
 	KEYIN6_PU_MARK,
 	KEYIN7_PU_MARK,
+	SDHICD0_PU_MARK,
+	SDHID0_0_PU_MARK,
+	SDHID0_1_PU_MARK,
+	SDHID0_2_PU_MARK,
+	SDHID0_3_PU_MARK,
+	SDHICMD0_PU_MARK,
+	SDHIWP0_PU_MARK,
 	SDHID1_0_PU_MARK,
 	SDHID1_1_PU_MARK,
 	SDHID1_2_PU_MARK,
 	SDHID1_3_PU_MARK,
 	SDHICMD1_PU_MARK,
+	SDHID2_0_PU_MARK,
+	SDHID2_1_PU_MARK,
+	SDHID2_2_PU_MARK,
+	SDHID2_3_PU_MARK,
+	SDHICMD2_PU_MARK,
 	MMCCMD0_PU_MARK,
 	MMCCMD1_PU_MARK,
+	MMCD0_0_PU_MARK,
+	MMCD0_1_PU_MARK,
+	MMCD0_2_PU_MARK,
+	MMCD0_3_PU_MARK,
+	MMCD0_4_PU_MARK,
+	MMCD0_5_PU_MARK,
+	MMCD0_6_PU_MARK,
+	MMCD0_7_PU_MARK,
+	FSIBISLD_PU_MARK,
 	FSIACK_PU_MARK,
 	FSIAILR_PU_MARK,
 	FSIAIBT_PU_MARK,
@@ -503,45 +513,6 @@
 	PINMUX_MARK_END,
 };
 
-#define PORT_DATA_I(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_IN)
-
-#define PORT_DATA_I_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_I_PU(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_I_PU_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_IN, PORT##nr##_IN_PD,	\
-				PORT##nr##_IN_PU)
-
-#define PORT_DATA_O(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT)
-
-#define PORT_DATA_IO(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT, PORT##nr##_IN)
-
-#define PORT_DATA_IO_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT, PORT##nr##_IN,		\
-				PORT##nr##_IN_PD)
-
-#define PORT_DATA_IO_PU(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT, PORT##nr##_IN,		\
-				PORT##nr##_IN_PU)
-
-#define PORT_DATA_IO_PU_PD(nr)	\
-	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,	\
-				PORT##nr##_OUT, PORT##nr##_IN,		\
-				PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
 static pinmux_enum_t pinmux_data[] = {
 	/* specify valid pin states for each pin in GPIO mode */
 
@@ -1387,19 +1358,28 @@
 	PINMUX_DATA(TS_SCK4_MARK, PORT268_FN3),
 	PINMUX_DATA(SDHICMD2_MARK, PORT269_FN1),
 	PINMUX_DATA(MMCCLK0_MARK, PORT270_FN1, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_0_MARK, PORT271_FN1, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_1_MARK, PORT272_FN1, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_2_MARK, PORT273_FN1, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_3_MARK, PORT274_FN1, MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCD0_4_MARK, PORT275_FN1, MSEL4CR_MSEL15_0), \
+	PINMUX_DATA(MMCD0_0_MARK, PORT271_FN1, PORT271_IN_PU,
+		MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_1_MARK, PORT272_FN1, PORT272_IN_PU,
+		MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_2_MARK, PORT273_FN1, PORT273_IN_PU,
+		MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_3_MARK, PORT274_FN1, PORT274_IN_PU,
+		MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_4_MARK, PORT275_FN1, PORT275_IN_PU,
+		MSEL4CR_MSEL15_0), \
 	PINMUX_DATA(TS_SPSYNC5_MARK, PORT275_FN3),
-	PINMUX_DATA(MMCD0_5_MARK, PORT276_FN1, MSEL4CR_MSEL15_0), \
+	PINMUX_DATA(MMCD0_5_MARK, PORT276_FN1, PORT276_IN_PU,
+		MSEL4CR_MSEL15_0), \
 	PINMUX_DATA(TS_SDAT5_MARK, PORT276_FN3),
-	PINMUX_DATA(MMCD0_6_MARK, PORT277_FN1, MSEL4CR_MSEL15_0), \
+	PINMUX_DATA(MMCD0_6_MARK, PORT277_FN1, PORT277_IN_PU,
+		MSEL4CR_MSEL15_0), \
 	PINMUX_DATA(TS_SDEN5_MARK, PORT277_FN3),
-	PINMUX_DATA(MMCD0_7_MARK, PORT278_FN1, MSEL4CR_MSEL15_0), \
+	PINMUX_DATA(MMCD0_7_MARK, PORT278_FN1, PORT278_IN_PU,
+		MSEL4CR_MSEL15_0), \
 	PINMUX_DATA(TS_SCK5_MARK, PORT278_FN3),
-	PINMUX_DATA(MMCCMD0_MARK, PORT279_FN1, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCCMD0_MARK, PORT279_FN1, PORT279_IN_PU,
+		MSEL4CR_MSEL15_0),
 	PINMUX_DATA(RESETOUTS__MARK, PORT281_FN1), \
 	PINMUX_DATA(EXTAL2OUT_MARK, PORT281_FN2),
 	PINMUX_DATA(MCP_WAIT__MCP_FRB_MARK, PORT288_FN1),
@@ -1516,28 +1496,55 @@
 	PINMUX_DATA(KEYIN6_PU_MARK, PORT72_FN2, PORT72_IN_PU),
 	PINMUX_DATA(KEYIN7_PU_MARK, PORT73_FN2, PORT73_IN_PU),
 
-	PINMUX_DATA(SDHID1_0_PU_MARK, PORT259_IN_PU, PORT259_FN1),
-	PINMUX_DATA(SDHID1_1_PU_MARK, PORT260_IN_PU, PORT260_FN1),
-	PINMUX_DATA(SDHID1_2_PU_MARK, PORT261_IN_PU, PORT261_FN1),
-	PINMUX_DATA(SDHID1_3_PU_MARK, PORT262_IN_PU, PORT262_FN1),
-	PINMUX_DATA(SDHICMD1_PU_MARK, PORT263_IN_PU, PORT263_FN1),
+	PINMUX_DATA(SDHICD0_PU_MARK,  PORT251_FN1, PORT251_IN_PU),
+	PINMUX_DATA(SDHID0_0_PU_MARK, PORT252_FN1, PORT252_IN_PU),
+	PINMUX_DATA(SDHID0_1_PU_MARK, PORT253_FN1, PORT253_IN_PU),
+	PINMUX_DATA(SDHID0_2_PU_MARK, PORT254_FN1, PORT254_IN_PU),
+	PINMUX_DATA(SDHID0_3_PU_MARK, PORT255_FN1, PORT255_IN_PU),
+	PINMUX_DATA(SDHICMD0_PU_MARK, PORT256_FN1, PORT256_IN_PU),
+	PINMUX_DATA(SDHIWP0_PU_MARK,  PORT257_FN1, PORT256_IN_PU),
+	PINMUX_DATA(SDHID1_0_PU_MARK, PORT259_FN1, PORT259_IN_PU),
+	PINMUX_DATA(SDHID1_1_PU_MARK, PORT260_FN1, PORT260_IN_PU),
+	PINMUX_DATA(SDHID1_2_PU_MARK, PORT261_FN1, PORT261_IN_PU),
+	PINMUX_DATA(SDHID1_3_PU_MARK, PORT262_FN1, PORT262_IN_PU),
+	PINMUX_DATA(SDHICMD1_PU_MARK, PORT263_FN1, PORT263_IN_PU),
+	PINMUX_DATA(SDHID2_0_PU_MARK, PORT265_FN1, PORT265_IN_PU),
+	PINMUX_DATA(SDHID2_1_PU_MARK, PORT266_FN1, PORT266_IN_PU),
+	PINMUX_DATA(SDHID2_2_PU_MARK, PORT267_FN1, PORT267_IN_PU),
+	PINMUX_DATA(SDHID2_3_PU_MARK, PORT268_FN1, PORT268_IN_PU),
+	PINMUX_DATA(SDHICMD2_PU_MARK, PORT269_FN1, PORT269_IN_PU),
 
 	PINMUX_DATA(MMCCMD0_PU_MARK, PORT279_FN1, PORT279_IN_PU,
 		MSEL4CR_MSEL15_0),
-	PINMUX_DATA(MMCCMD1_PU_MARK, PORT297_FN2, PORT279_IN_PU,
+	PINMUX_DATA(MMCCMD1_PU_MARK, PORT297_FN2, PORT297_IN_PU,
 		MSEL4CR_MSEL15_1),
+
+	PINMUX_DATA(MMCD0_0_PU_MARK,
+		    PORT271_FN1, PORT271_IN_PU, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_1_PU_MARK,
+		    PORT272_FN1, PORT272_IN_PU, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_2_PU_MARK,
+		    PORT273_FN1, PORT273_IN_PU, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_3_PU_MARK,
+		    PORT274_FN1, PORT274_IN_PU, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_4_PU_MARK,
+		    PORT275_FN1, PORT275_IN_PU, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_5_PU_MARK,
+		    PORT276_FN1, PORT276_IN_PU, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_6_PU_MARK,
+		    PORT277_FN1, PORT277_IN_PU, MSEL4CR_MSEL15_0),
+	PINMUX_DATA(MMCD0_7_PU_MARK,
+		    PORT278_FN1, PORT278_IN_PU, MSEL4CR_MSEL15_0),
+
+	PINMUX_DATA(FSIBISLD_PU_MARK, PORT39_FN1, PORT39_IN_PU),
 	PINMUX_DATA(FSIACK_PU_MARK, PORT49_FN1, PORT49_IN_PU),
 	PINMUX_DATA(FSIAILR_PU_MARK, PORT50_FN5, PORT50_IN_PU),
 	PINMUX_DATA(FSIAIBT_PU_MARK, PORT51_FN5, PORT51_IN_PU),
 	PINMUX_DATA(FSIAISLD_PU_MARK, PORT55_FN1, PORT55_IN_PU),
 };
 
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define GPIO_PORT_310() _310(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
-
 static struct pinmux_gpio pinmux_gpios[] = {
-	GPIO_PORT_310(),
+	GPIO_PORT_ALL(),
 
 	/* Table 25-1 (Functions 0-7) */
 	GPIO_FN(VBUS_0),
@@ -2181,31 +2188,39 @@
 	GPIO_FN(KEYIN5_PU),
 	GPIO_FN(KEYIN6_PU),
 	GPIO_FN(KEYIN7_PU),
+	GPIO_FN(SDHICD0_PU),
+	GPIO_FN(SDHID0_0_PU),
+	GPIO_FN(SDHID0_1_PU),
+	GPIO_FN(SDHID0_2_PU),
+	GPIO_FN(SDHID0_3_PU),
+	GPIO_FN(SDHICMD0_PU),
+	GPIO_FN(SDHIWP0_PU),
 	GPIO_FN(SDHID1_0_PU),
 	GPIO_FN(SDHID1_1_PU),
 	GPIO_FN(SDHID1_2_PU),
 	GPIO_FN(SDHID1_3_PU),
 	GPIO_FN(SDHICMD1_PU),
+	GPIO_FN(SDHID2_0_PU),
+	GPIO_FN(SDHID2_1_PU),
+	GPIO_FN(SDHID2_2_PU),
+	GPIO_FN(SDHID2_3_PU),
+	GPIO_FN(SDHICMD2_PU),
 	GPIO_FN(MMCCMD0_PU),
 	GPIO_FN(MMCCMD1_PU),
+	GPIO_FN(MMCD0_0_PU),
+	GPIO_FN(MMCD0_1_PU),
+	GPIO_FN(MMCD0_2_PU),
+	GPIO_FN(MMCD0_3_PU),
+	GPIO_FN(MMCD0_4_PU),
+	GPIO_FN(MMCD0_5_PU),
+	GPIO_FN(MMCD0_6_PU),
+	GPIO_FN(MMCD0_7_PU),
 	GPIO_FN(FSIACK_PU),
 	GPIO_FN(FSIAILR_PU),
 	GPIO_FN(FSIAIBT_PU),
 	GPIO_FN(FSIAISLD_PU),
 };
 
-#define PORTCR(nr, reg)	\
-	{ PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) { \
-		0, \
-		/*0001*/ PORT##nr##_OUT , \
-		/*0010*/ PORT##nr##_IN , 0, 0, 0, 0, 0, 0, 0, \
-		/*1010*/ PORT##nr##_IN_PD, 0, 0, 0, \
-		/*1110*/ PORT##nr##_IN_PU, 0, \
-		PORT##nr##_FN0, PORT##nr##_FN1,	PORT##nr##_FN2, \
-		PORT##nr##_FN3,	PORT##nr##_FN4, PORT##nr##_FN5, \
-		PORT##nr##_FN6, PORT##nr##_FN7, 0, 0, 0, 0, 0, 0, 0, 0 } \
-	}
-
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
 	PORTCR(0, 0xe6050000), /* PORT0CR */
 	PORTCR(1, 0xe6050001), /* PORT1CR */
@@ -2718,6 +2733,45 @@
 	{ },
 };
 
+/* IRQ pins through INTCS with IRQ0->15 from 0x200 and IRQ16-31 from 0x3200 */
+#define EXT_IRQ16L(n) intcs_evt2irq(0x200 + ((n) << 5))
+#define EXT_IRQ16H(n) intcs_evt2irq(0x3200 + ((n - 16) << 5))
+
+static struct pinmux_irq pinmux_irqs[] = {
+	PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(1), PORT10_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(0), PORT11_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(18), PORT13_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(20), PORT14_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(21), PORT15_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(31), PORT26_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(30), PORT27_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(29), PORT28_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(22), PORT40_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(23), PORT53_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(10), PORT54_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(9), PORT56_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(26), PORT115_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(27), PORT116_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(28), PORT117_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(24), PORT118_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(6), PORT147_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(2), PORT149_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(7), PORT150_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(12), PORT156_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(4), PORT159_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(25), PORT164_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(8), PORT223_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(3), PORT224_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(5), PORT227_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(17), PORT234_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(11), PORT238_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(13), PORT239_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(16), PORT249_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(14), PORT251_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(9), PORT308_FN0),
+};
+
 static struct pinmux_info sh73a0_pinmux_info = {
 	.name = "sh73a0_pfc",
 	.reserved_id = PINMUX_RESERVED,
@@ -2738,6 +2792,9 @@
 
 	.gpio_data = pinmux_data,
 	.gpio_data_size = ARRAY_SIZE(pinmux_data),
+
+	.gpio_irq = pinmux_irqs,
+	.gpio_irq_size = ARRAY_SIZE(pinmux_irqs),
 };
 
 void sh73a0_pinmux_init(void)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/platsmp.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/platsmp.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/platsmp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,9 +21,11 @@
 #include <asm/mach-types.h>
 #include <mach/common.h>
 
+#define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2())
+
 static unsigned int __init shmobile_smp_get_core_count(void)
 {
-	if (machine_is_ag5evm())
+	if (is_sh73a0())
 		return sh73a0_get_core_count();
 
 	return 1;
@@ -31,7 +33,7 @@
 
 static void __init shmobile_smp_prepare_cpus(void)
 {
-	if (machine_is_ag5evm())
+	if (is_sh73a0())
 		sh73a0_smp_prepare_cpus();
 }
 
@@ -39,13 +41,13 @@
 {
 	trace_hardirqs_off();
 
-	if (machine_is_ag5evm())
+	if (is_sh73a0())
 		sh73a0_secondary_init(cpu);
 }
 
 int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-	if (machine_is_ag5evm())
+	if (is_sh73a0())
 		return sh73a0_boot_secondary(cpu);
 
 	return -ENOSYS;
@@ -56,6 +58,12 @@
 	unsigned int ncores = shmobile_smp_get_core_count();
 	unsigned int i;
 
+	if (ncores > nr_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
+	}
+
 	for (i = 0; i < ncores; i++)
 		set_cpu_possible(i, true);
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/pm_runtime.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/pm_runtime.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/pm_runtime.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/pm_runtime.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,66 +0,0 @@
-/*
- * arch/arm/mach-shmobile/pm_runtime.c
- *
- * Runtime PM support code for SuperH Mobile ARM
- *
- *  Copyright (C) 2009-2010 Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/pm_runtime.h>
-#include <linux/pm_domain.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/sh_clk.h>
-#include <linux/bitmap.h>
-#include <linux/slab.h>
-
-#ifdef CONFIG_PM_RUNTIME
-
-static int default_platform_runtime_idle(struct device *dev)
-{
-	/* suspend synchronously to disable clocks immediately */
-	return pm_runtime_suspend(dev);
-}
-
-static struct dev_pm_domain default_pm_domain = {
-	.ops = {
-		.runtime_suspend = pm_clk_suspend,
-		.runtime_resume = pm_clk_resume,
-		.runtime_idle = default_platform_runtime_idle,
-		USE_PLATFORM_PM_SLEEP_OPS
-	},
-};
-
-#define DEFAULT_PM_DOMAIN_PTR	(&default_pm_domain)
-
-#else
-
-#define DEFAULT_PM_DOMAIN_PTR	NULL
-
-#endif /* CONFIG_PM_RUNTIME */
-
-static struct pm_clk_notifier_block platform_bus_notifier = {
-	.pm_domain = DEFAULT_PM_DOMAIN_PTR,
-	.con_ids = { NULL, },
-};
-
-static int __init sh_pm_runtime_init(void)
-{
-	pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
-	return 0;
-}
-core_initcall(sh_pm_runtime_init);
-
-static int __init sh_pm_runtime_late_init(void)
-{
-	pm_genpd_poweroff_unused();
-	return 0;
-}
-late_initcall(sh_pm_runtime_late_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/pm-sh7372.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/pm-sh7372.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/pm-sh7372.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/pm-sh7372.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,23 +15,62 @@
 #include <linux/list.h>
 #include <linux/err.h>
 #include <linux/slab.h>
-#include <linux/pm_runtime.h>
+#include <linux/pm_clock.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/bitrev.h>
+#include <linux/console.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/tlbflush.h>
+#include <asm/suspend.h>
 #include <mach/common.h>
 #include <mach/sh7372.h>
 
-#define SMFRAM 0xe6a70000
+/* DBG */
+#define DBGREG1 0xe6100020
+#define DBGREG9 0xe6100040
+
+/* CPGA */
 #define SYSTBCR 0xe6150024
-#define SBAR 0xe6180020
-#define APARMBAREA 0xe6f10020
+#define MSTPSR0 0xe6150030
+#define MSTPSR1 0xe6150038
+#define MSTPSR2 0xe6150040
+#define MSTPSR3 0xe6150048
+#define MSTPSR4 0xe615004c
+#define PLLC01STPCR 0xe61500c8
 
+/* SYSC */
 #define SPDCR 0xe6180008
 #define SWUCR 0xe6180014
+#define SBAR 0xe6180020
+#define WUPRMSK 0xe6180028
+#define WUPSMSK 0xe618002c
+#define WUPSMSK2 0xe6180048
 #define PSTR 0xe6180080
+#define WUPSFAC 0xe6180098
+#define IRQCR 0xe618022c
+#define IRQCR2 0xe6180238
+#define IRQCR3 0xe6180244
+#define IRQCR4 0xe6180248
+#define PDNSEL 0xe6180254
+
+/* INTC */
+#define ICR1A 0xe6900000
+#define ICR2A 0xe6900004
+#define ICR3A 0xe6900008
+#define ICR4A 0xe690000c
+#define INTMSK00A 0xe6900040
+#define INTMSK10A 0xe6900044
+#define INTMSK20A 0xe6900048
+#define INTMSK30A 0xe690004c
+
+/* MFIS */
+#define SMFRAM 0xe6a70000
+
+/* AP-System Core */
+#define APARMBAREA 0xe6f10020
 
 #define PSTR_RETRIES 100
 #define PSTR_DELAY_US 10
@@ -43,6 +82,12 @@
 	struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
 	unsigned int mask = 1 << sh7372_pd->bit_shift;
 
+	if (sh7372_pd->suspend)
+		sh7372_pd->suspend();
+
+	if (sh7372_pd->stay_on)
+		return 0;
+
 	if (__raw_readl(PSTR) & mask) {
 		unsigned int retry_count;
 
@@ -55,19 +100,22 @@
 		}
 	}
 
-	pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
-		 mask, __raw_readl(PSTR));
+	if (!sh7372_pd->no_debug)
+		pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
+			 mask, __raw_readl(PSTR));
 
 	return 0;
 }
 
-static int pd_power_up(struct generic_pm_domain *genpd)
+static int __pd_power_up(struct sh7372_pm_domain *sh7372_pd, bool do_resume)
 {
-	struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
 	unsigned int mask = 1 << sh7372_pd->bit_shift;
 	unsigned int retry_count;
 	int ret = 0;
 
+	if (sh7372_pd->stay_on)
+		goto out;
+
 	if (__raw_readl(PSTR) & mask)
 		goto out;
 
@@ -75,76 +123,63 @@
 
 	for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
 		if (!(__raw_readl(SWUCR) & mask))
-			goto out;
+			break;
 		if (retry_count > PSTR_RETRIES)
 			udelay(PSTR_DELAY_US);
 		else
 			cpu_relax();
 	}
-	if (__raw_readl(SWUCR) & mask)
+	if (!retry_count)
 		ret = -EIO;
 
+	if (!sh7372_pd->no_debug)
+		pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
+			 mask, __raw_readl(PSTR));
+
  out:
-	pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
-		 mask, __raw_readl(PSTR));
+	if (ret == 0 && sh7372_pd->resume && do_resume)
+		sh7372_pd->resume();
 
 	return ret;
 }
 
-static int pd_power_up_a3rv(struct generic_pm_domain *genpd)
+static int pd_power_up(struct generic_pm_domain *genpd)
 {
-	int ret = pd_power_up(genpd);
-
-	/* force A4LC on after A3RV has been requested on */
-	pm_genpd_poweron(&sh7372_a4lc.genpd);
-
-	return ret;
+	 return __pd_power_up(to_sh7372_pd(genpd), true);
 }
 
-static int pd_power_down_a3rv(struct generic_pm_domain *genpd)
+static void sh7372_a4r_suspend(void)
 {
-	int ret = pd_power_down(genpd);
-
-	/* try to power down A4LC after A3RV is requested off */
-	genpd_queue_power_off_work(&sh7372_a4lc.genpd);
-
-	return ret;
+	sh7372_intcs_suspend();
+	__raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */
 }
 
-static int pd_power_down_a4lc(struct generic_pm_domain *genpd)
+static bool pd_active_wakeup(struct device *dev)
 {
-	/* only power down A4LC if A3RV is off */
-	if (!(__raw_readl(PSTR) & (1 << sh7372_a3rv.bit_shift)))
-		return pd_power_down(genpd);
-
-	return -EBUSY;
+	return true;
 }
 
-static bool pd_active_wakeup(struct device *dev)
+static bool sh7372_power_down_forbidden(struct dev_pm_domain *domain)
 {
-	return true;
+	return false;
 }
 
+struct dev_power_governor sh7372_always_on_gov = {
+	.power_down_ok = sh7372_power_down_forbidden,
+};
+
 void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd)
 {
 	struct generic_pm_domain *genpd = &sh7372_pd->genpd;
 
-	pm_genpd_init(genpd, NULL, false);
+	pm_genpd_init(genpd, sh7372_pd->gov, false);
 	genpd->stop_device = pm_clk_suspend;
 	genpd->start_device = pm_clk_resume;
+	genpd->dev_irq_safe = true;
 	genpd->active_wakeup = pd_active_wakeup;
-
-	if (sh7372_pd == &sh7372_a4lc) {
-		genpd->power_off = pd_power_down_a4lc;
-		genpd->power_on = pd_power_up;
-	} else if (sh7372_pd == &sh7372_a3rv) {
-		genpd->power_off = pd_power_down_a3rv;
-		genpd->power_on = pd_power_up_a3rv;
-	} else {
-		genpd->power_off = pd_power_down;
-		genpd->power_on = pd_power_up;
-	}
-	genpd->power_on(&sh7372_pd->genpd);
+	genpd->power_off = pd_power_down;
+	genpd->power_on = pd_power_up;
+	__pd_power_up(sh7372_pd, false);
 }
 
 void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd,
@@ -152,11 +187,15 @@
 {
 	struct device *dev = &pdev->dev;
 
-	if (!dev->power.subsys_data) {
-		pm_clk_init(dev);
-		pm_clk_add(dev, NULL);
-	}
 	pm_genpd_add_device(&sh7372_pd->genpd, dev);
+	if (pm_clk_no_clocks(dev))
+		pm_clk_add(dev, NULL);
+}
+
+void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd,
+			     struct sh7372_pm_domain *sh7372_sd)
+{
+	pm_genpd_add_subdomain(&sh7372_pd->genpd, &sh7372_sd->genpd);
 }
 
 struct sh7372_pm_domain sh7372_a4lc = {
@@ -171,6 +210,14 @@
 	.bit_shift = 3,
 };
 
+struct sh7372_pm_domain sh7372_a4r = {
+	.bit_shift = 5,
+	.gov = &sh7372_always_on_gov,
+	.suspend = sh7372_a4r_suspend,
+	.resume = sh7372_intcs_resume,
+	.stay_on = true,
+};
+
 struct sh7372_pm_domain sh7372_a3rv = {
 	.bit_shift = 6,
 };
@@ -179,55 +226,211 @@
 	.bit_shift = 8,
 };
 
+struct sh7372_pm_domain sh7372_a3sp = {
+	.bit_shift = 11,
+	.gov = &sh7372_always_on_gov,
+	.no_debug = true,
+};
+
+static void sh7372_a3sp_init(void)
+{
+	/* serial consoles make use of SCIF hardware located in A3SP,
+	 * keep such power domain on if "no_console_suspend" is set.
+	 */
+	sh7372_a3sp.stay_on = !console_suspend_enabled;
+}
+
 struct sh7372_pm_domain sh7372_a3sg = {
 	.bit_shift = 13,
 };
 
-#endif /* CONFIG_PM */
+#else /* !CONFIG_PM */
+
+static inline void sh7372_a3sp_init(void) {}
+
+#endif /* !CONFIG_PM */
+
+#if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE)
+static int sh7372_do_idle_core_standby(unsigned long unused)
+{
+	cpu_do_idle(); /* WFI when SYSTBCR == 0x10 -> Core Standby */
+	return 0;
+}
 
 static void sh7372_enter_core_standby(void)
 {
-	void __iomem *smfram = (void __iomem *)SMFRAM;
+	/* set reset vector, translate 4k */
+	__raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR);
+	__raw_writel(0, APARMBAREA);
 
-	__raw_writel(0, APARMBAREA); /* translate 4k */
-	__raw_writel(__pa(sh7372_cpu_resume), SBAR); /* set reset vector */
-	__raw_writel(0x10, SYSTBCR); /* enable core standby */
+	/* enter sleep mode with SYSTBCR to 0x10 */
+	__raw_writel(0x10, SYSTBCR);
+	cpu_suspend(0, sh7372_do_idle_core_standby);
+	__raw_writel(0, SYSTBCR);
 
-	__raw_writel(0, smfram + 0x3c); /* clear page table address */
+	 /* disable reset vector translation */
+	__raw_writel(0, SBAR);
+}
+#endif
 
-	sh7372_cpu_suspend();
-	cpu_init();
+#ifdef CONFIG_SUSPEND
+static void sh7372_enter_a3sm_common(int pllc0_on)
+{
+	/* set reset vector, translate 4k */
+	__raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR);
+	__raw_writel(0, APARMBAREA);
 
-	/* if page table address is non-NULL then we have been powered down */
-	if (__raw_readl(smfram + 0x3c)) {
-		__raw_writel(__raw_readl(smfram + 0x40),
-			     __va(__raw_readl(smfram + 0x3c)));
+	if (pllc0_on)
+		__raw_writel(0, PLLC01STPCR);
+	else
+		__raw_writel(1 << 28, PLLC01STPCR);
 
-		flush_tlb_all();
-		set_cr(__raw_readl(smfram + 0x38));
+	__raw_writel(0, PDNSEL); /* power-down A3SM only, not A4S */
+	__raw_readl(WUPSFAC); /* read wakeup int. factor before sleep */
+	cpu_suspend(0, sh7372_do_idle_a3sm);
+	__raw_readl(WUPSFAC); /* read wakeup int. factor after wakeup */
+
+	 /* disable reset vector translation */
+	__raw_writel(0, SBAR);
+}
+
+static int sh7372_a3sm_valid(unsigned long *mskp, unsigned long *msk2p)
+{
+	unsigned long mstpsr0, mstpsr1, mstpsr2, mstpsr3, mstpsr4;
+	unsigned long msk, msk2;
+
+	/* check active clocks to determine potential wakeup sources */
+
+	mstpsr0 = __raw_readl(MSTPSR0);
+	if ((mstpsr0 & 0x00000003) != 0x00000003) {
+		pr_debug("sh7372 mstpsr0 0x%08lx\n", mstpsr0);
+		return 0;
 	}
 
-	__raw_writel(0, SYSTBCR); /* disable core standby */
-	__raw_writel(0, SBAR); /* disable reset vector translation */
+	mstpsr1 = __raw_readl(MSTPSR1);
+	if ((mstpsr1 & 0xff079b7f) != 0xff079b7f) {
+		pr_debug("sh7372 mstpsr1 0x%08lx\n", mstpsr1);
+		return 0;
+	}
+
+	mstpsr2 = __raw_readl(MSTPSR2);
+	if ((mstpsr2 & 0x000741ff) != 0x000741ff) {
+		pr_debug("sh7372 mstpsr2 0x%08lx\n", mstpsr2);
+		return 0;
+	}
+
+	mstpsr3 = __raw_readl(MSTPSR3);
+	if ((mstpsr3 & 0x1a60f010) != 0x1a60f010) {
+		pr_debug("sh7372 mstpsr3 0x%08lx\n", mstpsr3);
+		return 0;
+	}
+
+	mstpsr4 = __raw_readl(MSTPSR4);
+	if ((mstpsr4 & 0x00008cf0) != 0x00008cf0) {
+		pr_debug("sh7372 mstpsr4 0x%08lx\n", mstpsr4);
+		return 0;
+	}
+
+	msk = 0;
+	msk2 = 0;
+
+	/* make bitmaps of limited number of wakeup sources */
+
+	if ((mstpsr2 & (1 << 23)) == 0) /* SPU2 */
+		msk |= 1 << 31;
+
+	if ((mstpsr2 & (1 << 12)) == 0) /* MFI_MFIM */
+		msk |= 1 << 21;
+
+	if ((mstpsr4 & (1 << 3)) == 0) /* KEYSC */
+		msk |= 1 << 2;
+
+	if ((mstpsr1 & (1 << 24)) == 0) /* CMT0 */
+		msk |= 1 << 1;
+
+	if ((mstpsr3 & (1 << 29)) == 0) /* CMT1 */
+		msk |= 1 << 1;
+
+	if ((mstpsr4 & (1 << 0)) == 0) /* CMT2 */
+		msk |= 1 << 1;
+
+	if ((mstpsr2 & (1 << 13)) == 0) /* MFI_MFIS */
+		msk2 |= 1 << 17;
+
+	*mskp = msk;
+	*msk2p = msk2;
+
+	return 1;
 }
 
+static void sh7372_icr_to_irqcr(unsigned long icr, u16 *irqcr1p, u16 *irqcr2p)
+{
+	u16 tmp, irqcr1, irqcr2;
+	int k;
+
+	irqcr1 = 0;
+	irqcr2 = 0;
+
+	/* convert INTCA ICR register layout to SYSC IRQCR+IRQCR2 */
+	for (k = 0; k <= 7; k++) {
+		tmp = (icr >> ((7 - k) * 4)) & 0xf;
+		irqcr1 |= (tmp & 0x03) << (k * 2);
+		irqcr2 |= (tmp >> 2) << (k * 2);
+	}
+
+	*irqcr1p = irqcr1;
+	*irqcr2p = irqcr2;
+}
+
+static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2)
+{
+	u16 irqcrx_low, irqcrx_high, irqcry_low, irqcry_high;
+	unsigned long tmp;
+
+	/* read IRQ0A -> IRQ15A mask */
+	tmp = bitrev8(__raw_readb(INTMSK00A));
+	tmp |= bitrev8(__raw_readb(INTMSK10A)) << 8;
+
+	/* setup WUPSMSK from clocks and external IRQ mask */
+	msk = (~msk & 0xc030000f) | (tmp << 4);
+	__raw_writel(msk, WUPSMSK);
+
+	/* propage level/edge trigger for external IRQ 0->15 */
+	sh7372_icr_to_irqcr(__raw_readl(ICR1A), &irqcrx_low, &irqcry_low);
+	sh7372_icr_to_irqcr(__raw_readl(ICR2A), &irqcrx_high, &irqcry_high);
+	__raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR);
+	__raw_writel((irqcry_high << 16) | irqcry_low, IRQCR2);
+
+	/* read IRQ16A -> IRQ31A mask */
+	tmp = bitrev8(__raw_readb(INTMSK20A));
+	tmp |= bitrev8(__raw_readb(INTMSK30A)) << 8;
+
+	/* setup WUPSMSK2 from clocks and external IRQ mask */
+	msk2 = (~msk2 & 0x00030000) | tmp;
+	__raw_writel(msk2, WUPSMSK2);
+
+	/* propage level/edge trigger for external IRQ 16->31 */
+	sh7372_icr_to_irqcr(__raw_readl(ICR3A), &irqcrx_low, &irqcry_low);
+	sh7372_icr_to_irqcr(__raw_readl(ICR4A), &irqcrx_high, &irqcry_high);
+	__raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR3);
+	__raw_writel((irqcry_high << 16) | irqcry_low, IRQCR4);
+}
+#endif
+
 #ifdef CONFIG_CPU_IDLE
-static void sh7372_cpuidle_setup(struct cpuidle_device *dev)
+
+static void sh7372_cpuidle_setup(struct cpuidle_driver *drv)
 {
-	struct cpuidle_state *state;
-	int i = dev->state_count;
+	struct cpuidle_state *state = &drv->states[drv->state_count];
 
-	state = &dev->states[i];
 	snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
 	strncpy(state->desc, "Core Standby Mode", CPUIDLE_DESC_LEN);
 	state->exit_latency = 10;
 	state->target_residency = 20 + 10;
-	state->power_usage = 1; /* perhaps not */
-	state->flags = 0;
-	state->flags |= CPUIDLE_FLAG_TIME_VALID;
-	shmobile_cpuidle_modes[i] = sh7372_enter_core_standby;
+	state->flags = CPUIDLE_FLAG_TIME_VALID;
+	shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_core_standby;
 
-	dev->state_count = i + 1;
+	drv->state_count++;
 }
 
 static void sh7372_cpuidle_init(void)
@@ -239,9 +442,25 @@
 #endif
 
 #ifdef CONFIG_SUSPEND
+
 static int sh7372_enter_suspend(suspend_state_t suspend_state)
 {
-	sh7372_enter_core_standby();
+	unsigned long msk, msk2;
+
+	/* check active clocks to determine potential wakeup sources */
+	if (sh7372_a3sm_valid(&msk, &msk2)) {
+
+		/* convert INTC mask and sense to SYSC mask and sense */
+		sh7372_setup_a3sm(msk, msk2);
+
+		/* enter A3SM sleep with PLLC0 off */
+		pr_debug("entering A3SM\n");
+		sh7372_enter_a3sm_common(0);
+	} else {
+		/* default to Core Standby that supports all wakeup sources */
+		pr_debug("entering Core Standby\n");
+		sh7372_enter_core_standby();
+	}
 	return 0;
 }
 
@@ -253,9 +472,6 @@
 static void sh7372_suspend_init(void) {}
 #endif
 
-#define DBGREG1 0xe6100020
-#define DBGREG9 0xe6100040
-
 void __init sh7372_pm_init(void)
 {
 	/* enable DBG hardware block to kick SYSC */
@@ -263,6 +479,11 @@
 	__raw_writel(0x0000a501, DBGREG9);
 	__raw_writel(0x00000000, DBGREG1);
 
+	/* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */
+	__raw_writel(0, PDNSEL);
+
+	sh7372_a3sp_init();
+
 	sh7372_suspend_init();
 	sh7372_cpuidle_init();
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/setup-sh7372.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/setup-sh7372.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/setup-sh7372.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/setup-sh7372.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/sh_dma.h>
 #include <linux/sh_intc.h>
 #include <linux/sh_timer.h>
+#include <linux/pm_domain.h>
 #include <mach/hardware.h>
 #include <mach/sh7372.h>
 #include <asm/mach-types.h>
@@ -990,9 +991,14 @@
 	sh7372_init_pm_domain(&sh7372_a4lc);
 	sh7372_init_pm_domain(&sh7372_a4mp);
 	sh7372_init_pm_domain(&sh7372_d4);
+	sh7372_init_pm_domain(&sh7372_a4r);
 	sh7372_init_pm_domain(&sh7372_a3rv);
 	sh7372_init_pm_domain(&sh7372_a3ri);
 	sh7372_init_pm_domain(&sh7372_a3sg);
+	sh7372_init_pm_domain(&sh7372_a3sp);
+
+	sh7372_pm_add_subdomain(&sh7372_a4lc, &sh7372_a3rv);
+	sh7372_pm_add_subdomain(&sh7372_a4r, &sh7372_a4lc);
 
 	platform_add_devices(sh7372_early_devices,
 			    ARRAY_SIZE(sh7372_early_devices));
@@ -1003,6 +1009,25 @@
 	sh7372_add_device_to_domain(&sh7372_a3rv, &vpu_device);
 	sh7372_add_device_to_domain(&sh7372_a4mp, &spu0_device);
 	sh7372_add_device_to_domain(&sh7372_a4mp, &spu1_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &scif0_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &scif1_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &scif2_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &scif3_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &scif4_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &scif5_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &scif6_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &iic1_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &dma0_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &dma1_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &dma2_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &usb_dma0_device);
+	sh7372_add_device_to_domain(&sh7372_a3sp, &usb_dma1_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &iic0_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &veu0_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &veu1_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &veu2_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &veu3_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &jpu_device);
 }
 
 void __init sh7372_add_early_devices(void)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/sleep-sh7372.S linux-libre-3.2-gnu/arch/arm/mach-shmobile/sleep-sh7372.S
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/sleep-sh7372.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/sleep-sh7372.S	2012-01-04 18:55:44.000000000 -0500
@@ -30,58 +30,20 @@
  */
 
 #include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/memory.h>
 #include <asm/assembler.h>
 
-#define SMFRAM 0xe6a70000
-
-	.align
-kernel_flush:
-	.word	v7_flush_dcache_all
-
-	.align	3
-ENTRY(sh7372_cpu_suspend)
-	stmfd	sp!, {r0-r12, lr}	@ save registers on stack
-
-	ldr	r8, =SMFRAM
-
-	mov	r4, sp			@ Store sp
-	mrs	r5, spsr		@ Store spsr
-	mov	r6, lr			@ Store lr
-	stmia	r8!, {r4-r6}
-
-	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}
-
-	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, 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}
-
-	/*
-	 * 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
+#if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE)
+	.align	12
+	.text
+	.global sh7372_resume_core_standby_a3sm
+sh7372_resume_core_standby_a3sm:
+	ldr     pc, 1f
+1:	.long   cpu_resume - PAGE_OFFSET + PLAT_PHYS_OFFSET
 
+	.global	sh7372_do_idle_a3sm
+sh7372_do_idle_a3sm:
 	/*
 	 * Clear the SCTLR.C bit to prevent further data cache
 	 * allocation. Clearing SCTLR.C would make all the data accesses
@@ -92,10 +54,13 @@
 	mcr	p15, 0, r0, c1, c0, 0
 	isb
 
+	/* disable L2 cache in the aux control register */
+	mrc     p15, 0, r10, c1, c0, 1
+	bic     r10, r10, #2
+	mcr     p15, 0, r10, c1, c0, 1
+
 	/*
-	 * 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.
+	 * Invalidate data cache again.
 	 */
 	ldr	r1, kernel_flush
 	blx	r1
@@ -115,146 +80,16 @@
 	dsb
 	dmb
 
-/*
- * ===================================
- * == WFI instruction => Enter idle ==
- * ===================================
- */
-	wfi				@ wait for interrupt
-
-/*
- * ===================================
- * == Resume path for non-OFF modes ==
- * ===================================
- */
-	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 ==
- * ===================================
- */
-	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
-
-	.pool
-
-	.align	12
-	.text
-	.global	sh7372_cpu_resume
-sh7372_cpu_resume:
-
-	mov	r1, #0
-	/*
-	 * Invalidate all instruction caches to PoU
-	 * and flush branch target cache
-	 */
-	mcr	p15, 0, r1, c7, c5, 0
-
-	ldr	r3, =SMFRAM
-
-	ldmia	r3!, {r4-r6}
-	mov	sp, r4			@ Restore sp
-	msr	spsr_cxsf, r5		@ Restore spsr
-	mov	lr, r6			@ Restore lr
-
-	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
-
-	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-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
-
-	/* Starting to enable MMU here */
-	mrc	p15, 0, r7, c2, c0, 2 	@ Read TTBRControl
-	/* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1 */
-	and	r7, #0x7
-	cmp	r7, #0x0
-	beq	usettbr0
-ttbr_error:
-	/*
-	 * More work needs to be done to support N[0:2] value other than 0
-	 * So looping here so that the error can be detected
-	 */
-	b	ttbr_error
-
-	.align
-cache_pred_disable_mask:
-	.word	0xFFFFE7FB
-ttbrbit_mask:
-	.word	0xFFFFC000
-table_index_mask:
-	.word	0xFFF00000
-table_entry:
-	.word	0x00000C02
-usettbr0:
-
-	mrc	p15, 0, r2, c2, c0, 0
-	ldr	r5, ttbrbit_mask
-	and	r2, r5
-	mov	r4, pc
-	ldr	r5, table_index_mask
-	and	r4, r5			@ r4 = 31 to 20 bits of pc
-	/* Extract the value to be written to table entry */
-	ldr	r6, table_entry
-	/* r6 has the value to be written to table entry */
-	add	r6, r6, r4
-	/* Getting the address of table entry to modify */
-	lsr	r4, #18
-	/* r2 has the location which needs to be modified */
-	add	r2, r4
-	ldr	r4, [r2]
-	str	r6, [r2] /* modify the table entry */
-
-	mov	r7, r6
-	mov	r5, r2
-	mov	r6, r4
-	/* r5 = original page table address */
-	/* r6 = original page table data */
-
-	mov	r0, #0
-	mcr	p15, 0, r0, c7, c5, 4	@ Flush prefetch buffer
-	mcr	p15, 0, r0, c7, c5, 6	@ Invalidate branch predictor array
-	mcr	p15, 0, r0, c8, c5, 0	@ Invalidate instruction TLB
-	mcr	p15, 0, r0, c8, c6, 0	@ Invalidate data TLB
-
-	/*
-	 * Restore control register. This enables the MMU.
-	 * The caches and prediction are not enabled here, they
-	 * will be enabled after restoring the MMU table entry.
-	 */
-	ldmia	r3!, {r4}
-	stmia	r3!, {r5} /* save original page table address */
-	stmia	r3!, {r6} /* save original page table data */
-	stmia	r3!, {r7} /* save modified page table data */
-
-	ldr	r2, cache_pred_disable_mask
-	and	r4, r2
-	mcr	p15, 0, r4, c1, c0, 0
-	dsb
-	isb
-
-	ldr     r0, =restoremmu_on
-	bx      r0
+#define SPDCR 0xe6180008
+#define A3SM (1 << 12)
 
-/*
- * ==============================
- * == Exit point from OFF mode ==
- * ==============================
- */
-restoremmu_on:
+	/* A3SM power down */
+	ldr     r0, =SPDCR
+	ldr     r1, =A3SM
+	str     r1, [r0]
+1:
+	b      1b
 
-	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
+kernel_flush:
+	.word v7_flush_dcache_all
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-shmobile/smp-sh73a0.c linux-libre-3.2-gnu/arch/arm/mach-shmobile/smp-sh73a0.c
--- linux-libre-3.1-gnu/arch/arm/mach-shmobile/smp-sh73a0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-shmobile/smp-sh73a0.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,6 +74,8 @@
 
 int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
 {
+	cpu = cpu_logical_map(cpu);
+
 	/* enable cache coherency */
 	modify_scu_cpu_psr(0, 3 << (cpu * 8));
 
@@ -87,6 +89,8 @@
 
 void __init sh73a0_smp_prepare_cpus(void)
 {
+	int cpu = cpu_logical_map(0);
+
 	scu_enable(scu_base_addr());
 
 	/* Map the reset vector (in headsmp.S) */
@@ -94,5 +98,5 @@
 	__raw_writel(__pa(shmobile_secondary_vector), __io(SBAR));
 
 	/* enable cache coherency on CPU0 */
-	modify_scu_cpu_psr(0, 3 << (0 * 8));
+	modify_scu_cpu_psr(0, 3 << (cpu * 8));
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-spear3xx/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-spear3xx/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-spear3xx/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-spear3xx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/memory.h
- *
- * Memory map for SPEAr3xx machine family
- *
- * Copyright (C) 2009 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 __MACH_MEMORY_H
-#define __MACH_MEMORY_H
-
-#include <plat/memory.h>
-
-#endif /* __MACH_MEMORY_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-spear3xx/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-spear3xx/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-spear3xx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-spear3xx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-zreladdr-y	:= 0x00008000
+zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-spear3xx/spear300_evb.c linux-libre-3.2-gnu/arch/arm/mach-spear3xx/spear300_evb.c
--- linux-libre-3.1-gnu/arch/arm/mach-spear3xx/spear300_evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-spear3xx/spear300_evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -64,7 +64,7 @@
 }
 
 MACHINE_START(SPEAR300, "ST-SPEAR300-EVB")
-	.boot_params	=	0x00000100,
+	.atag_offset	=	0x100,
 	.map_io		=	spear3xx_map_io,
 	.init_irq	=	spear3xx_init_irq,
 	.timer		=	&spear3xx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-spear3xx/spear310_evb.c linux-libre-3.2-gnu/arch/arm/mach-spear3xx/spear310_evb.c
--- linux-libre-3.1-gnu/arch/arm/mach-spear3xx/spear310_evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-spear3xx/spear310_evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -70,7 +70,7 @@
 }
 
 MACHINE_START(SPEAR310, "ST-SPEAR310-EVB")
-	.boot_params	=	0x00000100,
+	.atag_offset	=	0x100,
 	.map_io		=	spear3xx_map_io,
 	.init_irq	=	spear3xx_init_irq,
 	.timer		=	&spear3xx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-spear3xx/spear320_evb.c linux-libre-3.2-gnu/arch/arm/mach-spear3xx/spear320_evb.c
--- linux-libre-3.1-gnu/arch/arm/mach-spear3xx/spear320_evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-spear3xx/spear320_evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,7 +68,7 @@
 }
 
 MACHINE_START(SPEAR320, "ST-SPEAR320-EVB")
-	.boot_params	=	0x00000100,
+	.atag_offset	=	0x100,
 	.map_io		=	spear3xx_map_io,
 	.init_irq	=	spear3xx_init_irq,
 	.timer		=	&spear3xx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-spear6xx/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-spear6xx/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-spear6xx/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-spear6xx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/include/mach/memory.h
- *
- * Memory map for SPEAr6xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Rajeev Kumar<rajeev-dlh.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 __MACH_MEMORY_H
-#define __MACH_MEMORY_H
-
-#include <plat/memory.h>
-
-#endif	/* __MACH_MEMORY_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-spear6xx/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-spear6xx/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-spear6xx/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-spear6xx/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-zreladdr-y	:= 0x00008000
+zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-spear6xx/spear600_evb.c linux-libre-3.2-gnu/arch/arm/mach-spear6xx/spear600_evb.c
--- linux-libre-3.1-gnu/arch/arm/mach-spear6xx/spear600_evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-spear6xx/spear600_evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,7 @@
 }
 
 MACHINE_START(SPEAR600, "ST-SPEAR600-EVB")
-	.boot_params	=	0x00000100,
+	.atag_offset	=	0x100,
 	.map_io		=	spear6xx_map_io,
 	.init_irq	=	spear6xx_init_irq,
 	.timer		=	&spear6xx_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tcc8k/board-tcc8000-sdk.c linux-libre-3.2-gnu/arch/arm/mach-tcc8k/board-tcc8000-sdk.c
--- linux-libre-3.1-gnu/arch/arm/mach-tcc8k/board-tcc8000-sdk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tcc8k/board-tcc8000-sdk.c	2012-01-04 18:55:44.000000000 -0500
@@ -73,7 +73,7 @@
 }
 
 MACHINE_START(TCC8000_SDK, "Telechips TCC8000-SDK Demo Board")
-	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= tcc8k_map_io,
 	.init_irq	= tcc8k_init_irq,
 	.init_machine	= tcc8k_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tcc8k/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-tcc8k/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-tcc8k/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tcc8k/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y		:= 0x20008000
+   zreladdr-y		+= 0x20008000
 params_phys-y		:= 0x20000100
 initrd_phys-y		:= 0x20800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/board-dt.c linux-libre-3.2-gnu/arch/arm/mach-tegra/board-dt.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/board-dt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/board-dt.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,7 +47,7 @@
 
 void harmony_pinmux_init(void);
 void seaboard_pinmux_init(void);
-
+void ventana_pinmux_init(void);
 
 struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
@@ -80,9 +80,19 @@
 	{}
 };
 
+static struct {
+	char *machine;
+	void (*init)(void);
+} pinmux_configs[] = {
+	{ "nvidia,harmony", harmony_pinmux_init },
+	{ "nvidia,seaboard", seaboard_pinmux_init },
+	{ "nvidia,ventana", ventana_pinmux_init },
+};
+
 static void __init tegra_dt_init(void)
 {
 	struct device_node *node;
+	int i;
 
 	node = of_find_matching_node_by_address(NULL, tegra_dt_gic_match,
 						TEGRA_ARM_INT_DIST_BASE);
@@ -91,21 +101,28 @@
 
 	tegra_clk_init_from_table(tegra_dt_clk_init_table);
 
-	if (of_machine_is_compatible("nvidia,harmony"))
-		harmony_pinmux_init();
-	else if (of_machine_is_compatible("nvidia,seaboard"))
-		seaboard_pinmux_init();
-
 	/*
 	 * Finished with the static registrations now; fill in the missing
 	 * devices
 	 */
-	of_platform_populate(NULL, tegra_dt_match_table, tegra20_auxdata_lookup, NULL);
+	of_platform_populate(NULL, tegra_dt_match_table,
+				tegra20_auxdata_lookup, NULL);
+
+	for (i = 0; i < ARRAY_SIZE(pinmux_configs); i++) {
+		if (of_machine_is_compatible(pinmux_configs[i].machine)) {
+			pinmux_configs[i].init();
+			break;
+		}
+	}
+
+	WARN(i == ARRAY_SIZE(pinmux_configs),
+		"Unknown platform! Pinmuxing not initialized\n");
 }
 
 static const char * tegra_dt_board_compat[] = {
 	"nvidia,harmony",
 	"nvidia,seaboard",
+	"nvidia,ventana",
 	NULL
 };
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/board-harmony.c linux-libre-3.2-gnu/arch/arm/mach-tegra/board-harmony.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/board-harmony.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/board-harmony.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,7 +49,8 @@
 		.membase	= IO_ADDRESS(TEGRA_UARTD_BASE),
 		.mapbase	= TEGRA_UARTD_BASE,
 		.irq		= INT_UARTD,
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+		.type		= PORT_TEGRA,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
@@ -117,14 +118,15 @@
 	&tegra_sdhci_device1,
 	&tegra_sdhci_device2,
 	&tegra_sdhci_device4,
+	&tegra_ehci3_device,
 	&tegra_i2s_device1,
 	&tegra_das_device,
 	&tegra_pcm_device,
 	&harmony_audio_device,
 };
 
-static void __init tegra_harmony_fixup(struct machine_desc *desc,
-	struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init tegra_harmony_fixup(struct tag *tags, char **cmdline,
+	struct meminfo *mi)
 {
 	mi->nr_banks = 2;
 	mi->bank[0].start = PHYS_OFFSET;
@@ -140,6 +142,7 @@
 	{ "pll_a_out0",	"pll_a",	11289600,	true },
 	{ "cdev1",	NULL,		0,		true },
 	{ "i2s1",	"pll_a_out0",	11289600,	false},
+	{ "usb3",	"clk_m",	12000000,	true },
 	{ NULL,		NULL,		0,		0},
 };
 
@@ -179,7 +182,7 @@
 }
 
 MACHINE_START(HARMONY, "harmony")
-	.boot_params  = 0x00000100,
+	.atag_offset	= 0x100,
 	.fixup		= tegra_harmony_fixup,
 	.map_io         = tegra_map_common_io,
 	.init_early	= tegra_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/board-harmony.h linux-libre-3.2-gnu/arch/arm/mach-tegra/board-harmony.h
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/board-harmony.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/board-harmony.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,8 @@
 #ifndef _MACH_TEGRA_BOARD_HARMONY_H
 #define _MACH_TEGRA_BOARD_HARMONY_H
 
+#include <mach/gpio-tegra.h>
+
 #define HARMONY_GPIO_TPS6586X(_x_)	(TEGRA_NR_GPIOS + (_x_))
 #define HARMONY_GPIO_WM8903(_x_)	(HARMONY_GPIO_TPS6586X(4) + (_x_))
 
@@ -31,6 +33,7 @@
 #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
+#define TEGRA_GPIO_EN_VDD_1V05_GPIO	HARMONY_GPIO_TPS6586X(2)
 
 void harmony_pinmux_init(void);
 int harmony_regulator_init(void);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/board-harmony-pcie.c linux-libre-3.2-gnu/arch/arm/mach-tegra/board-harmony-pcie.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/board-harmony-pcie.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/board-harmony-pcie.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,12 +24,10 @@
 
 #include <mach/pinmux.h>
 #include "board.h"
+#include "board-harmony.h"
 
 #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;
@@ -38,11 +36,11 @@
 	if (!machine_is_harmony())
 		return 0;
 
-	err = gpio_request(EN_VDD_1V05_GPIO, "EN_VDD_1V05");
+	err = gpio_request(TEGRA_GPIO_EN_VDD_1V05_GPIO, "EN_VDD_1V05");
 	if (err)
 		return err;
 
-	gpio_direction_output(EN_VDD_1V05_GPIO, 1);
+	gpio_direction_output(TEGRA_GPIO_EN_VDD_1V05_GPIO, 1);
 
 	regulator = regulator_get(NULL, "pex_clk");
 	if (IS_ERR_OR_NULL(regulator))
@@ -68,7 +66,7 @@
 	regulator_disable(regulator);
 	regulator_put(regulator);
 err_reg:
-	gpio_free(EN_VDD_1V05_GPIO);
+	gpio_free(TEGRA_GPIO_EN_VDD_1V05_GPIO);
 
 	return err;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/board-harmony-pinmux.c linux-libre-3.2-gnu/arch/arm/mach-tegra/board-harmony-pinmux.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/board-harmony-pinmux.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/board-harmony-pinmux.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,10 +16,13 @@
 
 #include <linux/kernel.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
+
 #include <mach/pinmux.h>
 
 #include "gpio-names.h"
 #include "board-harmony.h"
+#include "devices.h"
 
 static struct tegra_pingroup_config harmony_pinmux[] = {
 	{TEGRA_PINGROUP_ATA,   TEGRA_MUX_IDE,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
@@ -140,6 +143,11 @@
 	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 };
 
+static struct platform_device *pinmux_devices[] = {
+	&tegra_gpio_device,
+	&tegra_pinmux_device,
+};
+
 static struct tegra_gpio_table gpio_table[] = {
 	{ .gpio = TEGRA_GPIO_SD2_CD,		.enable = true	},
 	{ .gpio = TEGRA_GPIO_SD2_WP,		.enable = true	},
@@ -155,6 +163,10 @@
 
 void harmony_pinmux_init(void)
 {
+	if (!of_machine_is_compatible("nvidia,tegra20"))
+		platform_add_devices(pinmux_devices,
+					ARRAY_SIZE(pinmux_devices));
+
 	tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux));
 
 	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/board-harmony-power.c linux-libre-3.2-gnu/arch/arm/mach-tegra/board-harmony-power.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/board-harmony-power.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/board-harmony-power.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,10 +18,11 @@
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-
+#include <linux/io.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/tps6586x.h>
 
+#include <mach/iomap.h>
 #include <mach/irqs.h>
 
 #include "board-harmony.h"
@@ -113,6 +114,16 @@
 
 int __init harmony_regulator_init(void)
 {
+	void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
+	u32 pmc_ctrl;
+
+	/*
+	 * Configure the power management controller to trigger PMU
+	 * interrupts when low
+	 */
+	pmc_ctrl = readl(pmc + PMC_CTRL);
+	writel(pmc_ctrl | PMC_CTRL_INTR_LOW, pmc + PMC_CTRL);
+
 	i2c_register_board_info(3, harmony_regulators, 1);
 
 	return 0;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/board-paz00.c linux-libre-3.2-gnu/arch/arm/mach-tegra/board-paz00.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/board-paz00.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/board-paz00.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,8 @@
 #include <linux/pda_power.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/rfkill-gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -35,7 +37,6 @@
 #include <mach/iomap.h>
 #include <mach/irqs.h>
 #include <mach/sdhci.h>
-#include <mach/gpio.h>
 
 #include "board.h"
 #include "board-paz00.h"
@@ -45,10 +46,22 @@
 
 static struct plat_serial8250_port debug_uart_platform_data[] = {
 	{
+		/* serial port on JP1 */
+		.membase	= IO_ADDRESS(TEGRA_UARTA_BASE),
+		.mapbase	= TEGRA_UARTA_BASE,
+		.irq		= INT_UARTA,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+		.type		= PORT_TEGRA,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= 216000000,
+	}, {
+		/* serial port on mini-pcie */
 		.membase	= IO_ADDRESS(TEGRA_UARTD_BASE),
 		.mapbase	= TEGRA_UARTD_BASE,
 		.irq		= INT_UARTD,
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+		.type		= PORT_TEGRA,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
@@ -65,10 +78,48 @@
 	},
 };
 
+static struct rfkill_gpio_platform_data wifi_rfkill_platform_data = {
+	.name		= "wifi_rfkill",
+	.reset_gpio	= TEGRA_WIFI_RST,
+	.shutdown_gpio	= TEGRA_WIFI_PWRN,
+	.type	= RFKILL_TYPE_WLAN,
+};
+
+static struct platform_device wifi_rfkill_device = {
+	.name	= "rfkill_gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &wifi_rfkill_platform_data,
+	},
+};
+
+static struct gpio_led gpio_leds[] = {
+	{
+		.name			= "wifi-led",
+		.default_trigger	= "rfkill0",
+		.gpio			= TEGRA_WIFI_LED,
+	},
+};
+
+static struct gpio_led_platform_data gpio_led_info = {
+	.leds		= gpio_leds,
+	.num_leds	= ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds_gpio = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &gpio_led_info,
+        },
+};
+
 static struct platform_device *paz00_devices[] __initdata = {
 	&debug_uart,
-	&tegra_sdhci_device1,
 	&tegra_sdhci_device4,
+	&tegra_sdhci_device1,
+	&wifi_rfkill_device,
+	&leds_gpio,
 };
 
 static void paz00_i2c_init(void)
@@ -84,8 +135,8 @@
 	platform_device_register(&tegra_ehci3_device);
 }
 
-static void __init tegra_paz00_fixup(struct machine_desc *desc,
-	struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init tegra_paz00_fixup(struct tag *tags, char **cmdline,
+	struct meminfo *mi)
 {
 	mi->nr_banks = 1;
 	mi->bank[0].start = PHYS_OFFSET;
@@ -94,7 +145,14 @@
 
 static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = {
 	/* name		parent		rate		enabled */
+	{ "uarta",	"pll_p",	216000000,	true },
 	{ "uartd",	"pll_p",	216000000,	true },
+
+	{ "pll_p_out4",	"pll_p",	24000000,	true },
+	{ "usbd",	"clk_m",	12000000,	false },
+	{ "usb2",	"clk_m",	12000000,	false },
+	{ "usb3",	"clk_m",	12000000,	false },
+
 	{ NULL,		NULL,		0,		0},
 };
 
@@ -127,7 +185,7 @@
 }
 
 MACHINE_START(PAZ00, "Toshiba AC100 / Dynabook AZ")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.fixup		= tegra_paz00_fixup,
 	.map_io         = tegra_map_common_io,
 	.init_early	= tegra_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/board-paz00.h linux-libre-3.2-gnu/arch/arm/mach-tegra/board-paz00.h
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/board-paz00.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/board-paz00.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,11 +17,21 @@
 #ifndef _MACH_TEGRA_BOARD_PAZ00_H
 #define _MACH_TEGRA_BOARD_PAZ00_H
 
+#include <mach/gpio-tegra.h>
+
+/* SDCARD */
 #define TEGRA_GPIO_SD1_CD		TEGRA_GPIO_PV5
 #define TEGRA_GPIO_SD1_WP		TEGRA_GPIO_PH1
 #define TEGRA_GPIO_SD1_POWER		TEGRA_GPIO_PT3
+
+/* ULPI */
 #define TEGRA_ULPI_RST			TEGRA_GPIO_PV0
 
+/* WIFI */
+#define TEGRA_WIFI_PWRN			TEGRA_GPIO_PK5
+#define TEGRA_WIFI_RST			TEGRA_GPIO_PD1
+#define TEGRA_WIFI_LED			TEGRA_GPIO_PD0
+
 void paz00_pinmux_init(void);
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/board-paz00-pinmux.c linux-libre-3.2-gnu/arch/arm/mach-tegra/board-paz00-pinmux.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/board-paz00-pinmux.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/board-paz00-pinmux.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,10 +16,13 @@
 
 #include <linux/kernel.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
+
 #include <mach/pinmux.h>
 
 #include "gpio-names.h"
 #include "board-paz00.h"
+#include "devices.h"
 
 static struct tegra_pingroup_config paz00_pinmux[] = {
 	{TEGRA_PINGROUP_ATA,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
@@ -140,15 +143,27 @@
 	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 };
 
+static struct platform_device *pinmux_devices[] = {
+	&tegra_gpio_device,
+	&tegra_pinmux_device,
+};
+
 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_ULPI_RST,	.enable = true },
+	{ .gpio = TEGRA_WIFI_PWRN,	.enable = true },
+	{ .gpio = TEGRA_WIFI_RST,	.enable = true },
+	{ .gpio = TEGRA_WIFI_LED,	.enable = true },
 };
 
 void paz00_pinmux_init(void)
 {
+	if (!of_machine_is_compatible("nvidia,tegra20"))
+		platform_add_devices(pinmux_devices,
+					ARRAY_SIZE(pinmux_devices));
+
 	tegra_pinmux_config_table(paz00_pinmux, ARRAY_SIZE(paz00_pinmux));
 
 	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/board-seaboard.c linux-libre-3.2-gnu/arch/arm/mach-tegra/board-seaboard.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/board-seaboard.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/board-seaboard.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,9 +25,12 @@
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 
+#include <sound/wm8903.h>
+
 #include <mach/iomap.h>
 #include <mach/irqs.h>
 #include <mach/sdhci.h>
+#include <mach/tegra_wm8903_pdata.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -41,7 +44,8 @@
 static struct plat_serial8250_port debug_uart_platform_data[] = {
 	{
 		/* Memory and IRQ filled in before registration */
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+		.type		= PORT_TEGRA,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
@@ -62,6 +66,12 @@
 	/* name		parent		rate		enabled */
 	{ "uartb",	"pll_p",	216000000,	true},
 	{ "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},
+	{ "usbd",	"clk_m",	12000000,	true},
+	{ "usb3",	"clk_m",	12000000,	true},
 	{ NULL,		NULL,		0,		0},
 };
 
@@ -117,6 +127,22 @@
 	.is_8bit	= 1,
 };
 
+static struct tegra_wm8903_platform_data seaboard_audio_pdata = {
+	.gpio_spkr_en		= TEGRA_GPIO_SPKR_EN,
+	.gpio_hp_det		= TEGRA_GPIO_HP_DET,
+	.gpio_hp_mute		= -1,
+	.gpio_int_mic_en	= -1,
+	.gpio_ext_mic_en	= -1,
+};
+
+static struct platform_device seaboard_audio_device = {
+	.name	= "tegra-snd-wm8903",
+	.id	= 0,
+	.dev	= {
+		.platform_data  = &seaboard_audio_pdata,
+	},
+};
+
 static struct platform_device *seaboard_devices[] __initdata = {
 	&debug_uart,
 	&tegra_pmu_device,
@@ -124,6 +150,10 @@
 	&tegra_sdhci_device3,
 	&tegra_sdhci_device1,
 	&seaboard_gpio_keys_device,
+	&tegra_i2s_device1,
+	&tegra_das_device,
+	&tegra_pcm_device,
+	&seaboard_audio_device,
 };
 
 static struct i2c_board_info __initdata isl29018_device = {
@@ -135,12 +165,56 @@
 	I2C_BOARD_INFO("adt7461", 0x4c),
 };
 
+static struct wm8903_platform_data wm8903_pdata = {
+	.irq_active_low = 0,
+	.micdet_cfg = 0,
+	.micdet_delay = 100,
+	.gpio_base = SEABOARD_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_device = {
+	I2C_BOARD_INFO("wm8903", 0x1a),
+	.platform_data = &wm8903_pdata,
+	.irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_CDC_IRQ),
+};
+
+static int seaboard_ehci_init(void)
+{
+	int gpio_status;
+
+	gpio_status = gpio_request(TEGRA_GPIO_USB1, "VBUS_USB1");
+	if (gpio_status < 0) {
+		pr_err("VBUS_USB1 request GPIO FAILED\n");
+		WARN_ON(1);
+	}
+
+	gpio_status = gpio_direction_output(TEGRA_GPIO_USB1, 1);
+	if (gpio_status < 0) {
+		pr_err("VBUS_USB1 request GPIO DIRECTION FAILED\n");
+		WARN_ON(1);
+	}
+	gpio_set_value(TEGRA_GPIO_USB1, 1);
+
+	platform_device_register(&tegra_ehci1_device);
+	platform_device_register(&tegra_ehci3_device);
+
+	return 0;
+}
+
 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(0, &wm8903_device, 1);
 
 	i2c_register_board_info(3, &adt7461_device, 1);
 
@@ -161,6 +235,8 @@
 	tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
 
 	platform_add_devices(seaboard_devices, ARRAY_SIZE(seaboard_devices));
+
+	seaboard_ehci_init();
 }
 
 static void __init tegra_seaboard_init(void)
@@ -182,6 +258,9 @@
 	debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE;
 	debug_uart_platform_data[0].irq = INT_UARTB;
 
+	seaboard_audio_pdata.gpio_hp_mute = TEGRA_GPIO_KAEN_HP_MUTE;
+	tegra_gpio_enable(TEGRA_GPIO_KAEN_HP_MUTE);
+
 	seaboard_common_init();
 
 	seaboard_i2c_init();
@@ -201,7 +280,7 @@
 
 
 MACHINE_START(SEABOARD, "seaboard")
-	.boot_params    = 0x00000100,
+	.atag_offset    = 0x100,
 	.map_io         = tegra_map_common_io,
 	.init_early     = tegra_init_early,
 	.init_irq       = tegra_init_irq,
@@ -210,7 +289,7 @@
 MACHINE_END
 
 MACHINE_START(KAEN, "kaen")
-	.boot_params    = 0x00000100,
+	.atag_offset    = 0x100,
 	.map_io         = tegra_map_common_io,
 	.init_early     = tegra_init_early,
 	.init_irq       = tegra_init_irq,
@@ -219,7 +298,7 @@
 MACHINE_END
 
 MACHINE_START(WARIO, "wario")
-	.boot_params    = 0x00000100,
+	.atag_offset    = 0x100,
 	.map_io         = tegra_map_common_io,
 	.init_early     = tegra_init_early,
 	.init_irq       = tegra_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/board-seaboard.h linux-libre-3.2-gnu/arch/arm/mach-tegra/board-seaboard.h
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/board-seaboard.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/board-seaboard.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,11 @@
 #ifndef _MACH_TEGRA_BOARD_SEABOARD_H
 #define _MACH_TEGRA_BOARD_SEABOARD_H
 
+#include <mach/gpio-tegra.h>
+
+#define SEABOARD_GPIO_TPS6586X(_x_)	(TEGRA_NR_GPIOS + (_x_))
+#define SEABOARD_GPIO_WM8903(_x_)	(SEABOARD_GPIO_TPS6586X(4) + (_x_))
+
 #define TEGRA_GPIO_SD2_CD		TEGRA_GPIO_PI5
 #define TEGRA_GPIO_SD2_WP		TEGRA_GPIO_PH1
 #define TEGRA_GPIO_SD2_POWER		TEGRA_GPIO_PI6
@@ -31,10 +36,11 @@
 #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)
+#define TEGRA_GPIO_WWAN_PWR		SEABOARD_GPIO_TPS6586X(2)
+#define TEGRA_GPIO_CDC_IRQ		TEGRA_GPIO_PX3
+#define TEGRA_GPIO_SPKR_EN		SEABOARD_GPIO_WM8903(2)
+#define TEGRA_GPIO_HP_DET		TEGRA_GPIO_PX1
+#define TEGRA_GPIO_KAEN_HP_MUTE		TEGRA_GPIO_PA5
 
 void seaboard_pinmux_init(void);
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/board-seaboard-pinmux.c linux-libre-3.2-gnu/arch/arm/mach-tegra/board-seaboard-pinmux.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/board-seaboard-pinmux.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/board-seaboard-pinmux.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2010 NVIDIA Corporation
+ * Copyright (C) 2010,2011 NVIDIA Corporation
+ * Copyright (C) 2011 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
@@ -15,12 +16,14 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
 
 #include <mach/pinmux.h>
 #include <mach/pinmux-t2.h>
 
 #include "gpio-names.h"
 #include "board-seaboard.h"
+#include "devices.h"
 
 #define DEFAULT_DRIVE(_name)					\
 	{							\
@@ -49,7 +52,7 @@
 	{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_DAP2,  TEGRA_MUX_DAP2,          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_NORMAL},
 	{TEGRA_PINGROUP_DDC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
@@ -133,7 +136,7 @@
 	{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_SPIC,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
 	{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},
@@ -157,24 +160,86 @@
 	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 };
 
+static __initdata struct tegra_pingroup_config ventana_pinmux[] = {
+	{TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3,     TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DDC,  TEGRA_MUX_RSVD2,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{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_GMD,  TEGRA_MUX_SFLASH,   TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPW0, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LPW2, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSC1, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSCK, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSDA, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_PTA,  TEGRA_MUX_RSVD2,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXC, TEGRA_MUX_SDIO3,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXK, TEGRA_MUX_SDIO3,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+};
 
+static struct platform_device *pinmux_devices[] = {
+	&tegra_gpio_device,
+	&tegra_pinmux_device,
+};
 
-
-static struct tegra_gpio_table gpio_table[] = {
+static struct tegra_gpio_table common_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_HP_DET,		.enable = true },
 	{ .gpio = TEGRA_GPIO_ISL29018_IRQ,	.enable = true },
+	{ .gpio = TEGRA_GPIO_CDC_IRQ,		.enable = true },
+	{ .gpio = TEGRA_GPIO_USB1,		.enable = true },
 };
 
-void __init seaboard_pinmux_init(void)
+static void __init update_pinmux(struct tegra_pingroup_config *newtbl, int size)
 {
+	int i, j;
+	struct tegra_pingroup_config *new_pingroup, *base_pingroup;
+
+	/* Update base seaboard pinmux table with secondary board
+	 * specific pinmux table table.
+	 */
+	for (i = 0; i < size; i++) {
+		new_pingroup = &newtbl[i];
+		for (j = 0; j < ARRAY_SIZE(seaboard_pinmux); j++) {
+			base_pingroup = &seaboard_pinmux[j];
+			if (new_pingroup->pingroup == base_pingroup->pingroup) {
+				*base_pingroup = *new_pingroup;
+				break;
+			}
+		}
+	}
+}
+
+void __init seaboard_common_pinmux_init(void)
+{
+	if (!of_machine_is_compatible("nvidia,tegra20"))
+		platform_add_devices(pinmux_devices,
+					ARRAY_SIZE(pinmux_devices));
+
 	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));
+	tegra_gpio_config(common_gpio_table, ARRAY_SIZE(common_gpio_table));
 }
+
+void __init seaboard_pinmux_init(void)
+{
+	seaboard_common_pinmux_init();
+}
+
+void __init ventana_pinmux_init(void)
+{
+	update_pinmux(ventana_pinmux, ARRAY_SIZE(ventana_pinmux));
+	seaboard_common_pinmux_init();
+}
+
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/board-trimslice.c linux-libre-3.2-gnu/arch/arm/mach-tegra/board-trimslice.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/board-trimslice.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/board-trimslice.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,6 @@
 
 #include <mach/iomap.h>
 #include <mach/sdhci.h>
-#include <mach/gpio.h>
 
 #include "board.h"
 #include "clock.h"
@@ -46,7 +45,8 @@
 		.membase	= IO_ADDRESS(TEGRA_UARTA_BASE),
 		.mapbase	= TEGRA_UARTA_BASE,
 		.irq		= INT_UARTA,
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+		.type		= PORT_TEGRA,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
@@ -126,8 +126,8 @@
 	platform_device_register(&tegra_ehci1_device);
 }
 
-static void __init tegra_trimslice_fixup(struct machine_desc *desc,
-	struct tag *tags, char **cmdline, struct meminfo *mi)
+static void __init tegra_trimslice_fixup(struct tag *tags, char **cmdline,
+	struct meminfo *mi)
 {
 	mi->nr_banks = 2;
 	mi->bank[0].start = PHYS_OFFSET;
@@ -171,7 +171,7 @@
 }
 
 MACHINE_START(TRIMSLICE, "trimslice")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.fixup		= tegra_trimslice_fixup,
 	.map_io         = tegra_map_common_io,
 	.init_early	= tegra_init_early,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/board-trimslice.h linux-libre-3.2-gnu/arch/arm/mach-tegra/board-trimslice.h
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/board-trimslice.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/board-trimslice.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,8 @@
 #ifndef _MACH_TEGRA_BOARD_TRIMSLICE_H
 #define _MACH_TEGRA_BOARD_TRIMSLICE_H
 
+#include <mach/gpio-tegra.h>
+
 #define TRIMSLICE_GPIO_SD4_CD	TEGRA_GPIO_PP1	/* mmc4 cd */
 #define TRIMSLICE_GPIO_SD4_WP	TEGRA_GPIO_PP2	/* mmc4 wp */
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/board-trimslice-pinmux.c linux-libre-3.2-gnu/arch/arm/mach-tegra/board-trimslice-pinmux.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/board-trimslice-pinmux.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/board-trimslice-pinmux.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,15 +13,16 @@
  * GNU General Public License for more details.
  *
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/of.h>
 
 #include <mach/pinmux.h>
-#include <mach/gpio.h>
 
 #include "gpio-names.h"
 #include "board-trimslice.h"
+#include "devices.h"
 
 static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
 	{TEGRA_PINGROUP_ATA,   TEGRA_MUX_IDE,           TEGRA_PUPD_NORMAL,	TEGRA_TRI_TRISTATE},
@@ -142,6 +143,11 @@
 	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
 };
 
+static struct platform_device *pinmux_devices[] = {
+	&tegra_gpio_device,
+	&tegra_pinmux_device,
+};
+
 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 */
@@ -152,6 +158,9 @@
 
 void __init trimslice_pinmux_init(void)
 {
+	if (!of_machine_is_compatible("nvidia,tegra20"))
+		platform_add_devices(pinmux_devices,
+					ARRAY_SIZE(pinmux_devices));
 	tegra_pinmux_config_table(trimslice_pinmux, ARRAY_SIZE(trimslice_pinmux));
 	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/common.c linux-libre-3.2-gnu/arch/arm/mach-tegra/common.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -61,7 +61,7 @@
 	{ NULL,		NULL,		0,		0},
 };
 
-void __init tegra_init_cache(void)
+static void __init tegra_init_cache(void)
 {
 #ifdef CONFIG_CACHE_L2X0
 	void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/cpu-tegra.c linux-libre-3.2-gnu/arch/arm/mach-tegra/cpu-tegra.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/cpu-tegra.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/cpu-tegra.c	2012-01-04 18:55:44.000000000 -0500
@@ -56,12 +56,12 @@
 static DEFINE_MUTEX(tegra_cpu_lock);
 static bool is_suspended;
 
-int tegra_verify_speed(struct cpufreq_policy *policy)
+static int tegra_verify_speed(struct cpufreq_policy *policy)
 {
 	return cpufreq_frequency_table_verify(policy, freq_table);
 }
 
-unsigned int tegra_getspeed(unsigned int cpu)
+static unsigned int tegra_getspeed(unsigned int cpu)
 {
 	unsigned long rate;
 
@@ -129,7 +129,7 @@
 		       unsigned int target_freq,
 		       unsigned int relation)
 {
-	int idx;
+	unsigned int idx;
 	unsigned int freq;
 	int ret = 0;
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/devices.c linux-libre-3.2-gnu/arch/arm/mach-tegra/devices.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,93 @@
 #include <mach/iomap.h>
 #include <mach/dma.h>
 #include <mach/usb_phy.h>
+
 #include "gpio-names.h"
+#include "devices.h"
+
+static struct resource gpio_resource[] = {
+	[0] = {
+		.start	= TEGRA_GPIO_BASE,
+		.end	= TEGRA_GPIO_BASE + TEGRA_GPIO_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_GPIO1,
+		.end	= INT_GPIO1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= INT_GPIO2,
+		.end	= INT_GPIO2,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start	= INT_GPIO3,
+		.end	= INT_GPIO3,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[4] = {
+		.start	= INT_GPIO4,
+		.end	= INT_GPIO4,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[5] = {
+		.start	= INT_GPIO5,
+		.end	= INT_GPIO5,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[6] = {
+		.start	= INT_GPIO6,
+		.end	= INT_GPIO6,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[7] = {
+		.start	= INT_GPIO7,
+		.end	= INT_GPIO7,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device tegra_gpio_device = {
+	.name		= "tegra-gpio",
+	.id		= -1,
+	.resource	= gpio_resource,
+	.num_resources	= ARRAY_SIZE(gpio_resource),
+};
+
+static struct resource pinmux_resource[] = {
+	[0] = {
+		/* Tri-state registers */
+		.start	= TEGRA_APB_MISC_BASE + 0x14,
+		.end	= TEGRA_APB_MISC_BASE + 0x20 + 3,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* Mux registers */
+		.start	= TEGRA_APB_MISC_BASE + 0x80,
+		.end	= TEGRA_APB_MISC_BASE + 0x9c + 3,
+		.flags	= IORESOURCE_MEM,
+	},
+	[2] = {
+		/* Pull-up/down registers */
+		.start	= TEGRA_APB_MISC_BASE + 0xa0,
+		.end	= TEGRA_APB_MISC_BASE + 0xb0 + 3,
+		.flags	= IORESOURCE_MEM,
+	},
+	[3] = {
+		/* Pad control registers */
+		.start	= TEGRA_APB_MISC_BASE + 0x868,
+		.end	= TEGRA_APB_MISC_BASE + 0x90c + 3,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device tegra_pinmux_device = {
+	.name		= "tegra-pinmux",
+	.id		= -1,
+	.resource	= pinmux_resource,
+	.num_resources	= ARRAY_SIZE(pinmux_resource),
+};
 
 static struct resource i2c_resource1[] = {
 	[0] = {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/devices.h linux-libre-3.2-gnu/arch/arm/mach-tegra/devices.h
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/devices.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/devices.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,8 @@
 
 #include <linux/platform_device.h>
 
+extern struct platform_device tegra_gpio_device;
+extern struct platform_device tegra_pinmux_device;
 extern struct platform_device tegra_sdhci_device1;
 extern struct platform_device tegra_sdhci_device2;
 extern struct platform_device tegra_sdhci_device3;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/dma.c linux-libre-3.2-gnu/arch/arm/mach-tegra/dma.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -105,13 +105,17 @@
 
 #define NV_DMA_MAX_TRASFER_SIZE 0x10000
 
-const unsigned int ahb_addr_wrap_table[8] = {
+static const unsigned int ahb_addr_wrap_table[8] = {
 	0, 32, 64, 128, 256, 512, 1024, 2048
 };
 
-const unsigned int apb_addr_wrap_table[8] = {0, 1, 2, 4, 8, 16, 32, 64};
+static const unsigned int apb_addr_wrap_table[8] = {
+	0, 1, 2, 4, 8, 16, 32, 64
+};
 
-const unsigned int bus_width_table[5] = {8, 16, 32, 64, 128};
+static const unsigned int bus_width_table[5] = {
+	8, 16, 32, 64, 128
+};
 
 #define TEGRA_DMA_NAME_SIZE 16
 struct tegra_dma_channel {
@@ -157,7 +161,7 @@
 	return;
 }
 
-void tegra_dma_stop(struct tegra_dma_channel *ch)
+static void tegra_dma_stop(struct tegra_dma_channel *ch)
 {
 	u32 csr;
 	u32 status;
@@ -174,7 +178,7 @@
 		writel(status, ch->addr + APB_DMA_CHAN_STA);
 }
 
-int tegra_dma_cancel(struct tegra_dma_channel *ch)
+static int tegra_dma_cancel(struct tegra_dma_channel *ch)
 {
 	u32 csr;
 	unsigned long irq_flags;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-tegra/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
 #include <mach/io.h>
 #include <mach/iomap.h>
 
-	.macro  addruart, rp, rv
+	.macro  addruart, rp, rv, tmp
         ldr     \rp, =IO_APB_PHYS       @ physical
         ldr     \rv, =IO_APB_VIRT        @ virtual
 	orr	\rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-tegra/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,60 +1 @@
-/*
- * arch/arm/mach-tegra/include/mach/gpio.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Erik Gilling <konkers@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_GPIO_H
-#define __MACH_TEGRA_GPIO_H
-
-#include <linux/init.h>
-#include <mach/irqs.h>
-
-#define TEGRA_NR_GPIOS		INT_GPIO_NR
-
-#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 TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio))
-#define TEGRA_IRQ_TO_GPIO(irq) ((irq) - INT_GPIO_BASE)
-
-static inline int gpio_to_irq(unsigned int gpio)
-{
-	if (gpio < TEGRA_NR_GPIOS)
-		return INT_GPIO_BASE + gpio;
-	return -EINVAL;
-}
-
-static inline int irq_to_gpio(unsigned int irq)
-{
-	if ((irq >= INT_GPIO_BASE) && (irq < INT_GPIO_BASE + INT_GPIO_NR))
-		return irq - INT_GPIO_BASE;
-	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);
-
-#endif
+/* empty */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/include/mach/gpio-tegra.h linux-libre-3.2-gnu/arch/arm/mach-tegra/include/mach/gpio-tegra.h
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/include/mach/gpio-tegra.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/include/mach/gpio-tegra.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,39 @@
+/*
+ * arch/arm/mach-tegra/include/mach/gpio.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Erik Gilling <konkers@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_GPIO_TEGRA_H
+#define __MACH_TEGRA_GPIO_TEGRA_H
+
+#include <linux/types.h>
+#include <mach/irqs.h>
+
+#define TEGRA_NR_GPIOS		INT_GPIO_NR
+
+#define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio))
+
+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);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/include/mach/io.h linux-libre-3.2-gnu/arch/arm/mach-tegra/include/mach/io.h
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -33,20 +33,26 @@
  *
  */
 
+#ifdef __ASSEMBLY__
+#define IOMEM(x)	(x)
+#else
+#define IOMEM(x)	((void __force __iomem *)(x))
+#endif
+
 #define IO_IRAM_PHYS	0x40000000
-#define IO_IRAM_VIRT	0xFE400000
+#define IO_IRAM_VIRT	IOMEM(0xFE400000)
 #define IO_IRAM_SIZE	SZ_256K
 
 #define IO_CPU_PHYS     0x50040000
-#define IO_CPU_VIRT     0xFE000000
+#define IO_CPU_VIRT     IOMEM(0xFE000000)
 #define IO_CPU_SIZE	SZ_16K
 
 #define IO_PPSB_PHYS	0x60000000
-#define IO_PPSB_VIRT	0xFE200000
+#define IO_PPSB_VIRT	IOMEM(0xFE200000)
 #define IO_PPSB_SIZE	SZ_1M
 
 #define IO_APB_PHYS	0x70000000
-#define IO_APB_VIRT	0xFE300000
+#define IO_APB_VIRT	IOMEM(0xFE300000)
 #define IO_APB_SIZE	SZ_1M
 
 #define IO_TO_VIRT_BETWEEN(p, st, sz)	((p) >= (st) && (p) < ((st) + (sz)))
@@ -61,7 +67,7 @@
 		IO_TO_VIRT_XLATE((n), IO_CPU_PHYS, IO_CPU_VIRT) :	\
 	IO_TO_VIRT_BETWEEN((n), IO_IRAM_PHYS, IO_IRAM_SIZE) ?		\
 		IO_TO_VIRT_XLATE((n), IO_IRAM_PHYS, IO_IRAM_VIRT) :	\
-	0)
+	NULL)
 
 #ifndef __ASSEMBLER__
 
@@ -71,7 +77,7 @@
 void __iomem *tegra_ioremap(unsigned long phys, size_t size, unsigned int type);
 void tegra_iounmap(volatile void __iomem *addr);
 
-#define IO_ADDRESS(n) ((void __iomem *) IO_TO_VIRT(n))
+#define IO_ADDRESS(n) (IO_TO_VIRT(n))
 
 #ifdef CONFIG_TEGRA_PCI
 extern void __iomem *tegra_pcie_io_base;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-tegra/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/memory.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *	Erik Gilling <konkers@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_MEMORY_H
-#define __MACH_TEGRA_MEMORY_H
-
-/* physical offset of RAM */
-#define PLAT_PHYS_OFFSET		UL(0)
-
-#endif
-
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/include/mach/pinmux.h linux-libre-3.2-gnu/arch/arm/mach-tegra/include/mach/pinmux.h
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/include/mach/pinmux.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/include/mach/pinmux.h	2012-01-04 18:55:44.000000000 -0500
@@ -199,6 +199,7 @@
 
 struct tegra_drive_pingroup_desc {
 	const char *name;
+	s16 reg_bank;
 	s16 reg;
 };
 
@@ -207,6 +208,9 @@
 	int funcs[4];
 	int func_safe;
 	int vddio;
+	s16 tri_bank;	/* Register bank the tri_reg exists within */
+	s16 mux_bank;	/* Register bank the mux_reg exists within */
+	s16 pupd_bank;	/* Register bank the pupd_reg exists within */
 	s16 tri_reg; 	/* offset into the TRISTATE_REG_* register bank */
 	s16 mux_reg;	/* offset into the PIN_MUX_CTL_* register bank */
 	s16 pupd_reg;	/* offset into the PULL_UPDOWN_REG_* register bank */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/include/mach/powergate.h linux-libre-3.2-gnu/arch/arm/mach-tegra/include/mach/powergate.h
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/include/mach/powergate.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/include/mach/powergate.h	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,6 @@
 
 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 */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/io.c linux-libre-3.2-gnu/arch/arm/mach-tegra/io.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/io.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,25 +31,25 @@
 
 static struct map_desc tegra_io_desc[] __initdata = {
 	{
-		.virtual = IO_PPSB_VIRT,
+		.virtual = (unsigned long)IO_PPSB_VIRT,
 		.pfn = __phys_to_pfn(IO_PPSB_PHYS),
 		.length = IO_PPSB_SIZE,
 		.type = MT_DEVICE,
 	},
 	{
-		.virtual = IO_APB_VIRT,
+		.virtual = (unsigned long)IO_APB_VIRT,
 		.pfn = __phys_to_pfn(IO_APB_PHYS),
 		.length = IO_APB_SIZE,
 		.type = MT_DEVICE,
 	},
 	{
-		.virtual = IO_CPU_VIRT,
+		.virtual = (unsigned long)IO_CPU_VIRT,
 		.pfn = __phys_to_pfn(IO_CPU_PHYS),
 		.length = IO_CPU_SIZE,
 		.type = MT_DEVICE,
 	},
 	{
-		.virtual = IO_IRAM_VIRT,
+		.virtual = (unsigned long)IO_IRAM_VIRT,
 		.pfn = __phys_to_pfn(IO_IRAM_PHYS),
 		.length = IO_IRAM_SIZE,
 		.type = MT_DEVICE,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/Kconfig linux-libre-3.2-gnu/arch/arm/mach-tegra/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -69,6 +69,12 @@
        help
          Support for the Wario version of Seaboard
 
+config MACH_VENTANA
+       bool "Ventana board"
+       select MACH_TEGRA_DT
+       help
+         Support for the nVidia Ventana development platform
+
 choice
         prompt "Low-level debug console UART"
         default TEGRA_DEBUG_UART_NONE
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/Makefile linux-libre-3.2-gnu/arch/arm/mach-tegra/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 
 obj-${CONFIG_MACH_TEGRA_DT}             += board-dt.o
 obj-${CONFIG_MACH_TEGRA_DT}             += board-harmony-pinmux.o
+obj-${CONFIG_MACH_TEGRA_DT}             += board-seaboard-pinmux.o
 
 obj-${CONFIG_MACH_TRIMSLICE}            += board-trimslice.o
 obj-${CONFIG_MACH_TRIMSLICE}            += board-trimslice-pinmux.o
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-tegra/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
-zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00008000
+zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC)	+= 0x00008000
 params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00000100
 initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00800000
 
 dtb-$(CONFIG_MACH_HARMONY) += tegra-harmony.dtb
 dtb-$(CONFIG_MACH_SEABOARD) += tegra-seaboard.dtb
+dtb-$(CONFIG_MACH_VENTANA) += tegra-ventana.dtb
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/pcie.c linux-libre-3.2-gnu/arch/arm/mach-tegra/pcie.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/pcie.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/pcie.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 #include <linux/irq.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 
 #include <asm/sizes.h>
 #include <asm/mach/pci.h>
@@ -41,6 +42,8 @@
 #include <mach/clk.h>
 #include <mach/powergate.h>
 
+#include "board.h"
+
 /* register definitions */
 #define AFI_OFFSET	0x3800
 #define PADS_OFFSET	0x3000
@@ -150,9 +153,9 @@
 static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
 
 #define pmc_writel(value, reg) \
-	__raw_writel(value, (u32)reg_pmc_base + (reg))
+	__raw_writel(value, reg_pmc_base + (reg))
 #define pmc_readl(reg) \
-	__raw_readl((u32)reg_pmc_base + (reg))
+	__raw_readl(reg_pmc_base + (reg))
 
 /*
  * Tegra2 defines 1GB in the AXI address map for PCIe.
@@ -460,7 +463,7 @@
 	struct tegra_pcie_port *pp;
 
 	if (nr >= tegra_pcie.num_ports)
-		return 0;
+		return NULL;
 
 	pp = tegra_pcie.port + nr;
 	pp->root_bus_nr = sys->busnr;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/pinmux.c linux-libre-3.2-gnu/arch/arm/mach-tegra/pinmux.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/pinmux.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/pinmux.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/errno.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
 
 #include <mach/iomap.h>
 #include <mach/pinmux.h>
@@ -169,15 +170,17 @@
 	}
 }
 
+static int nbanks;
+static void __iomem **regs;
 
-static inline unsigned long pg_readl(unsigned long offset)
+static inline u32 pg_readl(u32 bank, u32 reg)
 {
-	return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+	return readl(regs[bank] + reg);
 }
 
-static inline void pg_writel(unsigned long value, unsigned long offset)
+static inline void pg_writel(u32 val, u32 bank, u32 reg)
 {
-	writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+	writel(val, regs[bank] + reg);
 }
 
 static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config)
@@ -217,10 +220,10 @@
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(pingroups[pg].mux_reg);
+	reg = pg_readl(pingroups[pg].mux_bank, pingroups[pg].mux_reg);
 	reg &= ~(0x3 << pingroups[pg].mux_bit);
 	reg |= mux << pingroups[pg].mux_bit;
-	pg_writel(reg, pingroups[pg].mux_reg);
+	pg_writel(reg, pingroups[pg].mux_bank, pingroups[pg].mux_reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -241,11 +244,11 @@
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(pingroups[pg].tri_reg);
+	reg = pg_readl(pingroups[pg].tri_bank, pingroups[pg].tri_reg);
 	reg &= ~(0x1 << pingroups[pg].tri_bit);
 	if (tristate)
 		reg |= 1 << pingroups[pg].tri_bit;
-	pg_writel(reg, pingroups[pg].tri_reg);
+	pg_writel(reg, pingroups[pg].tri_bank, pingroups[pg].tri_reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -272,10 +275,10 @@
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(pingroups[pg].pupd_reg);
+	reg = pg_readl(pingroups[pg].pupd_bank, pingroups[pg].pupd_reg);
 	reg &= ~(0x3 << pingroups[pg].pupd_bit);
 	reg |= pupd << pingroups[pg].pupd_bit;
-	pg_writel(reg, pingroups[pg].pupd_reg);
+	pg_writel(reg, pingroups[pg].pupd_bank, pingroups[pg].pupd_reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -362,12 +365,12 @@
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	if (hsm == TEGRA_HSM_ENABLE)
 		reg |= (1 << 2);
 	else
 		reg &= ~(1 << 2);
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -387,12 +390,12 @@
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	if (schmitt == TEGRA_SCHMITT_ENABLE)
 		reg |= (1 << 3);
 	else
 		reg &= ~(1 << 3);
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -412,10 +415,10 @@
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x3 << 4);
 	reg |= drive << 4;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -435,10 +438,10 @@
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x1f << 12);
 	reg |= pull_down << 12;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -458,10 +461,10 @@
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x1f << 12);
 	reg |= pull_up << 12;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -481,10 +484,10 @@
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x3 << 28);
 	reg |= slew_rising << 28;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -504,10 +507,10 @@
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x3 << 30);
 	reg |= slew_falling << 30;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -665,6 +668,99 @@
 	}
 }
 
+static int __devinit tegra_pinmux_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int i;
+	int config_bad = 0;
+
+	for (i = 0; ; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res)
+			break;
+	}
+	nbanks = i;
+
+	for (i = 0; i < TEGRA_MAX_PINGROUP; i++) {
+		if (pingroups[i].tri_bank >= nbanks) {
+			dev_err(&pdev->dev, "pingroup %d: bad tri_bank\n", i);
+			config_bad = 1;
+		}
+
+		if (pingroups[i].mux_bank >= nbanks) {
+			dev_err(&pdev->dev, "pingroup %d: bad mux_bank\n", i);
+			config_bad = 1;
+		}
+
+		if (pingroups[i].pupd_bank >= nbanks) {
+			dev_err(&pdev->dev, "pingroup %d: bad pupd_bank\n", i);
+			config_bad = 1;
+		}
+	}
+
+	for (i = 0; i < TEGRA_MAX_DRIVE_PINGROUP; i++) {
+		if (drive_pingroups[i].reg_bank >= nbanks) {
+			dev_err(&pdev->dev,
+				"drive pingroup %d: bad reg_bank\n", i);
+			config_bad = 1;
+		}
+	}
+
+	if (config_bad)
+		return -ENODEV;
+
+	regs = devm_kzalloc(&pdev->dev, nbanks * sizeof(*regs), GFP_KERNEL);
+	if (!regs) {
+		dev_err(&pdev->dev, "Can't alloc regs pointer\n");
+		return -ENODEV;
+	}
+
+	for (i = 0; i < nbanks; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res) {
+			dev_err(&pdev->dev, "Missing MEM resource\n");
+			return -ENODEV;
+		}
+
+		if (!devm_request_mem_region(&pdev->dev, res->start,
+					    resource_size(res),
+					    dev_name(&pdev->dev))) {
+			dev_err(&pdev->dev,
+				"Couldn't request MEM resource %d\n", i);
+			return -ENODEV;
+		}
+
+		regs[i] = devm_ioremap(&pdev->dev, res->start,
+					resource_size(res));
+		if (!regs) {
+			dev_err(&pdev->dev, "Couldn't ioremap regs %d\n", i);
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
+static struct of_device_id tegra_pinmux_of_match[] __devinitdata = {
+	{ .compatible = "nvidia,tegra20-pinmux", },
+	{ },
+};
+
+static struct platform_driver tegra_pinmux_driver = {
+	.driver		= {
+		.name	= "tegra-pinmux",
+		.owner	= THIS_MODULE,
+		.of_match_table = tegra_pinmux_of_match,
+	},
+	.probe		= tegra_pinmux_probe,
+};
+
+static int __init tegra_pinmux_init(void)
+{
+	return platform_driver_register(&tegra_pinmux_driver);
+}
+postcore_initcall(tegra_pinmux_init);
+
 #ifdef	CONFIG_DEBUG_FS
 
 #include <linux/debugfs.h>
@@ -684,6 +780,7 @@
 	int len;
 
 	for (i = 0; i < TEGRA_MAX_PINGROUP; i++) {
+		unsigned long reg;
 		unsigned long tri;
 		unsigned long mux;
 		unsigned long pupd;
@@ -696,8 +793,9 @@
 			seq_printf(s, "TEGRA_MUX_NONE");
 			len = strlen("NONE");
 		} else {
-			mux = (pg_readl(pingroups[i].mux_reg) >>
-			       pingroups[i].mux_bit) & 0x3;
+			reg = pg_readl(pingroups[i].mux_bank,
+					pingroups[i].mux_reg);
+			mux = (reg >> pingroups[i].mux_bit) & 0x3;
 			if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) {
 				seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1);
 				len = 5;
@@ -713,8 +811,9 @@
 			seq_printf(s, "TEGRA_PUPD_NORMAL");
 			len = strlen("NORMAL");
 		} else {
-			pupd = (pg_readl(pingroups[i].pupd_reg) >>
-				pingroups[i].pupd_bit) & 0x3;
+			reg = pg_readl(pingroups[i].pupd_bank,
+					pingroups[i].pupd_reg);
+			pupd = (reg >> pingroups[i].pupd_bit) & 0x3;
 			seq_printf(s, "TEGRA_PUPD_%s", pupd_name(pupd));
 			len = strlen(pupd_name(pupd));
 		}
@@ -723,8 +822,9 @@
 		if (pingroups[i].tri_reg < 0) {
 			seq_printf(s, "TEGRA_TRI_NORMAL");
 		} else {
-			tri = (pg_readl(pingroups[i].tri_reg) >>
-			       pingroups[i].tri_bit) & 0x1;
+			reg = pg_readl(pingroups[i].tri_bank,
+					pingroups[i].tri_reg);
+			tri = (reg >> pingroups[i].tri_bit) & 0x1;
 
 			seq_printf(s, "TEGRA_TRI_%s", tri_name(tri));
 		}
@@ -759,7 +859,8 @@
 		dbg_pad_field(s, 7 - len);
 
 
-		reg = pg_readl(drive_pingroups[i].reg);
+		reg = pg_readl(drive_pingroups[i].reg_bank,
+				drive_pingroups[i].reg);
 		if (HSM_EN(reg)) {
 			seq_printf(s, "TEGRA_HSM_ENABLE");
 			len = 16;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/pinmux-t2-tables.c linux-libre-3.2-gnu/arch/arm/mach-tegra/pinmux-t2-tables.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/pinmux-t2-tables.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/pinmux-t2-tables.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,10 +31,16 @@
 #include <mach/pinmux.h>
 #include <mach/suspend.h>
 
+#define TRISTATE_REG_A		0x14
+#define PIN_MUX_CTL_REG_A	0x80
+#define PULLUPDOWN_REG_A	0xa0
+#define PINGROUP_REG_A		0x868
+
 #define DRIVE_PINGROUP(pg_name, r)				\
 	[TEGRA_DRIVE_PINGROUP_ ## pg_name] = {			\
 		.name = #pg_name,				\
-		.reg = r					\
+		.reg_bank = 3,					\
+		.reg = ((r) - PINGROUP_REG_A)			\
 	}
 
 const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE_PINGROUP] = {
@@ -90,11 +96,14 @@
 			TEGRA_MUX_ ## f3,			\
 		},						\
 		.func_safe = TEGRA_MUX_ ## f_safe,		\
-		.tri_reg = tri_r,				\
+		.tri_bank = 0,					\
+		.tri_reg = ((tri_r) - TRISTATE_REG_A),		\
 		.tri_bit = tri_b,				\
-		.mux_reg = mux_r,				\
+		.mux_bank = 1,					\
+		.mux_reg = ((mux_r) - PIN_MUX_CTL_REG_A),	\
 		.mux_bit = mux_b,				\
-		.pupd_reg = pupd_r,				\
+		.pupd_bank = 2,				\
+		.pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A),	\
 		.pupd_bit = pupd_b,				\
 	}
 
@@ -217,62 +226,3 @@
 	PINGROUP(XM2C,  DDR,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xA8, 30),
 	PINGROUP(XM2D,  DDR,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xA8, 28),
 };
-
-#ifdef CONFIG_PM
-#define TRISTATE_REG_A         0x14
-#define TRISTATE_REG_NUM       4
-#define PIN_MUX_CTL_REG_A      0x80
-#define PIN_MUX_CTL_REG_NUM    8
-#define PULLUPDOWN_REG_A       0xa0
-#define PULLUPDOWN_REG_NUM     5
-
-static u32 pinmux_reg[TRISTATE_REG_NUM + PIN_MUX_CTL_REG_NUM +
-		      PULLUPDOWN_REG_NUM +
-		      ARRAY_SIZE(tegra_soc_drive_pingroups)];
-
-static inline unsigned long pg_readl(unsigned long offset)
-{
-	return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
-}
-
-static inline void pg_writel(unsigned long value, unsigned long offset)
-{
-	writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
-}
-
-void tegra_pinmux_suspend(void)
-{
-	unsigned int i;
-	u32 *ctx = pinmux_reg;
-
-	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)
-{
-	unsigned int i;
-	u32 *ctx = pinmux_reg;
-
-	for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
-		pg_writel(*ctx++, PIN_MUX_CTL_REG_A + i*4);
-
-	for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
-		pg_writel(*ctx++, PULLUPDOWN_REG_A + i*4);
-
-	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-3.1-gnu/arch/arm/mach-tegra/platsmp.c linux-libre-3.2-gnu/arch/arm/mach-tegra/platsmp.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/platsmp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -114,10 +114,10 @@
 {
 	unsigned int i, ncores = scu_get_core_count(scu_base);
 
-	if (ncores > NR_CPUS) {
-		printk(KERN_ERR "Tegra: no. of cores (%u) greater than configured (%u), clipping\n",
-			ncores, NR_CPUS);
-		ncores = NR_CPUS;
+	if (ncores > nr_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
 	}
 
 	for (i = 0; i < ncores; i++)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/powergate.c linux-libre-3.2-gnu/arch/arm/mach-tegra/powergate.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/powergate.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/powergate.c	2012-01-04 18:55:44.000000000 -0500
@@ -89,12 +89,11 @@
 	return tegra_powergate_set(id, false);
 }
 
-bool tegra_powergate_is_powered(int id)
+static bool tegra_powergate_is_powered(int id)
 {
 	u32 status;
 
-	if (id < 0 || id >= TEGRA_NUM_POWERGATE)
-		return -EINVAL;
+	WARN_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
 
 	status = pmc_read(PWRGATE_STATUS) & (1 << id);
 	return !!status;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/tegra2_clocks.c linux-libre-3.2-gnu/arch/arm/mach-tegra/tegra2_clocks.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/tegra2_clocks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/tegra2_clocks.c	2012-01-04 18:55:44.000000000 -0500
@@ -166,13 +166,13 @@
 static int tegra_periph_clk_enable_refcount[3 * 32];
 
 #define clk_writel(value, reg) \
-	__raw_writel(value, (u32)reg_clk_base + (reg))
+	__raw_writel(value, reg_clk_base + (reg))
 #define clk_readl(reg) \
-	__raw_readl((u32)reg_clk_base + (reg))
+	__raw_readl(reg_clk_base + (reg))
 #define pmc_writel(value, reg) \
-	__raw_writel(value, (u32)reg_pmc_base + (reg))
+	__raw_writel(value, reg_pmc_base + (reg))
 #define pmc_readl(reg) \
-	__raw_readl((u32)reg_pmc_base + (reg))
+	__raw_readl(reg_pmc_base + (reg))
 
 unsigned long clk_measure_input_freq(void)
 {
@@ -918,7 +918,7 @@
 static void tegra2_periph_clk_init(struct clk *c)
 {
 	u32 val = clk_readl(c->reg);
-	const struct clk_mux_sel *mux = 0;
+	const struct clk_mux_sel *mux = NULL;
 	const struct clk_mux_sel *sel;
 	if (c->flags & MUX) {
 		for (sel = c->inputs; sel->input != NULL; sel++) {
@@ -1459,7 +1459,7 @@
 static struct clk_mux_sel tegra_clk_m_sel[] = {
 	{ .input = &tegra_clk_32k, .value = 0},
 	{ .input = &tegra_pll_s,  .value = 1},
-	{ 0, 0},
+	{ NULL , 0},
 };
 
 static struct clk tegra_clk_m = {
@@ -1861,7 +1861,7 @@
 	{ .name = "ext_audio_clk1", .value = 6 },
 	{ .name = "ext_vimclk", .value = 7 },
 #endif
-	{ 0, 0 }
+	{ NULL, 0 }
 };
 
 static struct clk tegra_clk_audio = {
@@ -1885,7 +1885,7 @@
 	},
 };
 
-struct clk_lookup tegra_audio_clk_lookups[] = {
+static struct clk_lookup tegra_audio_clk_lookups[] = {
 	{ .con_id = "audio", .clk = &tegra_clk_audio },
 	{ .con_id = "audio_2x", .clk = &tegra_clk_audio_2x }
 };
@@ -1926,7 +1926,7 @@
 	{ .input = &tegra_pll_p_out3,	.value = 6},
 	{ .input = &tegra_clk_d,	.value = 7},
 	{ .input = &tegra_pll_x,	.value = 8},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_sclk[] = {
@@ -1938,7 +1938,7 @@
 	{ .input = &tegra_clk_d,	.value = 5},
 	{ .input = &tegra_clk_32k,	.value = 6},
 	{ .input = &tegra_pll_m_out1,	.value = 7},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk tegra_clk_cclk = {
@@ -2009,7 +2009,7 @@
 	{ .input = &tegra_pll_c, .value = 1},
 	{ .input = &tegra_pll_p, .value = 2},
 	{ .input = &tegra_pll_a_out0, .value = 3},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllm_pllc_pllp_clkm[] = {
@@ -2017,7 +2017,7 @@
 	{ .input = &tegra_pll_c, .value = 1},
 	{ .input = &tegra_pll_p, .value = 2},
 	{ .input = &tegra_clk_m, .value = 3},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = {
@@ -2025,7 +2025,7 @@
 	{ .input = &tegra_pll_c, .value = 1},
 	{ .input = &tegra_pll_m, .value = 2},
 	{ .input = &tegra_clk_m, .value = 3},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllaout0_audio2x_pllp_clkm[] = {
@@ -2033,7 +2033,7 @@
 	{.input = &tegra_clk_audio_2x, .value = 1},
 	{.input = &tegra_pll_p, .value = 2},
 	{.input = &tegra_clk_m, .value = 3},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = {
@@ -2041,7 +2041,7 @@
 	{.input = &tegra_pll_d_out0, .value = 1},
 	{.input = &tegra_pll_c, .value = 2},
 	{.input = &tegra_clk_m, .value = 3},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = {
@@ -2050,39 +2050,39 @@
 	{.input = &tegra_clk_audio,     .value = 2},
 	{.input = &tegra_clk_m,     .value = 3},
 	{.input = &tegra_clk_32k,   .value = 4},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllp_pllc_pllm[] = {
 	{.input = &tegra_pll_p,     .value = 0},
 	{.input = &tegra_pll_c,     .value = 1},
 	{.input = &tegra_pll_m,     .value = 2},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_clk_m[] = {
 	{ .input = &tegra_clk_m, .value = 0},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllp_out3[] = {
 	{ .input = &tegra_pll_p_out3, .value = 0},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_plld[] = {
 	{ .input = &tegra_pll_d, .value = 0},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_clk_32k[] = {
 	{ .input = &tegra_clk_32k, .value = 0},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pclk[] = {
 	{ .input = &tegra_clk_pclk, .value = 0},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk tegra_clk_emc = {
@@ -2125,7 +2125,7 @@
 		.parent = _parent,			\
 	}
 
-struct clk tegra_list_clks[] = {
+static 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),
@@ -2221,7 +2221,7 @@
  * configuration.  List those here to register them twice in the clock lookup
  * table under two names.
  */
-struct clk_duplicate tegra_clk_duplicates[] = {
+static struct clk_duplicate tegra_clk_duplicates[] = {
 	CLK_DUPLICATE("uarta",	"tegra_uart.0",	NULL),
 	CLK_DUPLICATE("uartb",	"tegra_uart.1",	NULL),
 	CLK_DUPLICATE("uartc",	"tegra_uart.2",	NULL),
@@ -2252,7 +2252,7 @@
 		.clk = ck,	\
 	}
 
-struct clk *tegra_ptr_clks[] = {
+static struct clk *tegra_ptr_clks[] = {
 	&tegra_clk_32k,
 	&tegra_pll_s,
 	&tegra_clk_m,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/timer.c linux-libre-3.2-gnu/arch/arm/mach-tegra/timer.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -62,9 +62,9 @@
 static u64 persistent_ms, last_persistent_ms;
 
 #define timer_writel(value, reg) \
-	__raw_writel(value, (u32)timer_reg_base + (reg))
+	__raw_writel(value, timer_reg_base + (reg))
 #define timer_readl(reg) \
-	__raw_readl((u32)timer_reg_base + (reg))
+	__raw_readl(timer_reg_base + (reg))
 
 static int tegra_timer_set_next_event(unsigned long cycles,
 					 struct clock_event_device *evt)
@@ -133,7 +133,7 @@
  * tegra_rtc driver could be executing to avoid race conditions
  * on the RTC shadow register
  */
-u64 tegra_rtc_read_ms(void)
+static u64 tegra_rtc_read_ms(void)
 {
 	u32 ms = readl(rtc_base + RTC_MILLISECONDS);
 	u32 s = readl(rtc_base + RTC_SHADOW_SECONDS);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-tegra/usb_phy.c linux-libre-3.2-gnu/arch/arm/mach-tegra/usb_phy.c
--- linux-libre-3.1-gnu/arch/arm/mach-tegra/usb_phy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-tegra/usb_phy.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 #include <asm/mach-types.h>
+#include <mach/gpio-tegra.h>
 #include <mach/usb_phy.h>
 #include <mach/iomap.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-u300/core.c linux-libre-3.2-gnu/arch/arm/mach-u300/core.c
--- linux-libre-3.1-gnu/arch/arm/mach-u300/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-u300/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,9 @@
 #include <linux/err.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/fsmc.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -37,6 +40,7 @@
 #include <mach/hardware.h>
 #include <mach/syscon.h>
 #include <mach/dma_channels.h>
+#include <mach/gpio-u300.h>
 
 #include "clock.h"
 #include "mmc.h"
@@ -68,30 +72,13 @@
 		.length		= SZ_32K,
 		.type		= MT_DEVICE,
 	},
-	{
-		.virtual	= 0xffff2000, /* TCM memory */
-		.pfn		= __phys_to_pfn(0xffff2000),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	},
-
-	/*
-	 * This overlaps with the IRQ vectors etc at 0xffff0000, so these
-	 * may have to be moved to 0x00000000 in order to use the ROM.
-	 */
-	/*
-	{
-		.virtual	= U300_BOOTROM_VIRT_BASE,
-		.pfn		= __phys_to_pfn(U300_BOOTROM_PHYS_BASE),
-		.length		= SZ_64K,
-		.type		= MT_ROM,
-	},
-	*/
 };
 
 void __init u300_map_io(void)
 {
 	iotable_init(u300_io_desc, ARRAY_SIZE(u300_io_desc));
+	/* We enable a real big DMA buffer if need be. */
+	init_consistent_dma_size(SZ_4M);
 }
 
 /*
@@ -239,7 +226,7 @@
 		.end   = IRQ_U300_GPIO_PORT2,
 		.flags = IORESOURCE_IRQ,
 	},
-#ifdef U300_COH901571_3
+#if defined(CONFIG_MACH_U300_BS365) || defined(CONFIG_MACH_U300_BS335)
 	{
 		.name  = "gpio3",
 		.start = IRQ_U300_GPIO_PORT3,
@@ -252,6 +239,7 @@
 		.end   = IRQ_U300_GPIO_PORT4,
 		.flags = IORESOURCE_IRQ,
 	},
+#endif
 #ifdef CONFIG_MACH_U300_BS335
 	{
 		.name  = "gpio5",
@@ -266,7 +254,6 @@
 		.flags = IORESOURCE_IRQ,
 	},
 #endif /* CONFIG_MACH_U300_BS335 */
-#endif /* U300_COH901571_3 */
 };
 
 static struct resource keypad_resources[] = {
@@ -361,51 +348,6 @@
 	}
 };
 
-/* TODO: These should be protected by suitable #ifdef's */
-static struct resource ave_resources[] = {
-	{
-		.name  = "AVE3e I/O Area",
-		.start = U300_VIDEOENC_BASE,
-		.end   = U300_VIDEOENC_BASE + SZ_512K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name  = "AVE3e IRQ0",
-		.start = IRQ_U300_VIDEO_ENC_0,
-		.end   = IRQ_U300_VIDEO_ENC_0,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name  = "AVE3e IRQ1",
-		.start = IRQ_U300_VIDEO_ENC_1,
-		.end   = IRQ_U300_VIDEO_ENC_1,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name  = "AVE3e Physmem Area",
-		.start = 0, /* 0 will be remapped to reserved memory */
-		.end   = SZ_1M - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	/*
-	 * The AVE3e requires two regions of 256MB that it considers
-	 * "invisible". The hardware will not be able to access these
-	 * addresses, so they should never point to system RAM.
-	 */
-	{
-		.name  = "AVE3e Reserved 0",
-		.start = 0xd0000000,
-		.end   = 0xd0000000 + SZ_256M - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name  = "AVE3e Reserved 1",
-		.start = 0xe0000000,
-		.end   = 0xe0000000 + SZ_256M - 1,
-		.flags = IORESOURCE_MEM,
-	},
-};
-
 static struct resource dma_resource[] = {
 	{
 		.start = U300_DMAC_BASE,
@@ -1535,6 +1477,14 @@
 	.max_channels = U300_DMA_CHANNELS,
 };
 
+static struct resource pinmux_resources[] = {
+	{
+		.start = U300_SYSCON_BASE,
+		.end   = U300_SYSCON_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
 static struct platform_device wdog_device = {
 	.name = "coh901327_wdog",
 	.id = -1,
@@ -1556,11 +1506,35 @@
 	.resource = i2c1_resources,
 };
 
+/*
+ * The different variants have a few different versions of the
+ * GPIO block, with different number of ports.
+ */
+static struct u300_gpio_platform u300_gpio_plat = {
+#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
+	.variant = U300_GPIO_COH901335,
+	.ports = 3,
+#endif
+#ifdef CONFIG_MACH_U300_BS335
+	.variant = U300_GPIO_COH901571_3_BS335,
+	.ports = 7,
+#endif
+#ifdef CONFIG_MACH_U300_BS365
+	.variant = U300_GPIO_COH901571_3_BS365,
+	.ports = 5,
+#endif
+	.gpio_base = 0,
+	.gpio_irq_base = IRQ_U300_GPIO_BASE,
+};
+
 static struct platform_device gpio_device = {
 	.name = "u300-gpio",
 	.id = -1,
 	.num_resources = ARRAY_SIZE(gpio_resources),
 	.resource = gpio_resources,
+	.dev = {
+		.platform_data = &u300_gpio_plat,
+	},
 };
 
 static struct platform_device keypad_device = {
@@ -1612,13 +1586,6 @@
 	},
 };
 
-static struct platform_device ave_device = {
-	.name = "video_enc",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(ave_resources),
-	.resource = ave_resources,
-};
-
 static struct platform_device dma_device = {
 	.name		= "coh901318",
 	.id		= -1,
@@ -1630,6 +1597,72 @@
 	},
 };
 
+static struct platform_device pinmux_device = {
+	.name = "pinmux-u300",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(pinmux_resources),
+	.resource = pinmux_resources,
+};
+
+/* Pinmux settings */
+static struct pinmux_map u300_pinmux_map[] = {
+	/* anonymous maps for chip power and EMIFs */
+	PINMUX_MAP_PRIMARY_SYS_HOG("POWER", "power"),
+	PINMUX_MAP_PRIMARY_SYS_HOG("EMIF0", "emif0"),
+	PINMUX_MAP_PRIMARY_SYS_HOG("EMIF1", "emif1"),
+	/* per-device maps for MMC/SD, SPI and UART */
+	PINMUX_MAP_PRIMARY("MMCSD", "mmc0", "mmci"),
+	PINMUX_MAP_PRIMARY("SPI", "spi0", "pl022"),
+	PINMUX_MAP_PRIMARY("UART0", "uart0", "uart0"),
+};
+
+struct u300_mux_hog {
+	const char *name;
+	struct device *dev;
+	struct pinmux *pmx;
+};
+
+static struct u300_mux_hog u300_mux_hogs[] = {
+	{
+		.name = "uart0",
+		.dev = &uart0_device.dev,
+	},
+	{
+		.name = "spi0",
+		.dev = &pl022_device.dev,
+	},
+	{
+		.name = "mmc0",
+		.dev = &mmcsd_device.dev,
+	},
+};
+
+static int __init u300_pinmux_fetch(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(u300_mux_hogs); i++) {
+		struct pinmux *pmx;
+		int ret;
+
+		pmx = pinmux_get(u300_mux_hogs[i].dev, NULL);
+		if (IS_ERR(pmx)) {
+			pr_err("u300: could not get pinmux hog %s\n",
+			       u300_mux_hogs[i].name);
+			continue;
+		}
+		ret = pinmux_enable(pmx);
+		if (ret) {
+			pr_err("u300: could enable pinmux hog %s\n",
+			       u300_mux_hogs[i].name);
+			continue;
+		}
+		u300_mux_hogs[i].pmx = pmx;
+	}
+	return 0;
+}
+subsys_initcall(u300_pinmux_fetch);
+
 /*
  * Notice that AMBA devices are initialized before platform devices.
  *
@@ -1643,10 +1676,9 @@
 	&gpio_device,
 	&nand_device,
 	&wdog_device,
-	&ave_device
+	&pinmux_device,
 };
 
-
 /*
  * Interrupts: the U300 platforms have two pl190 ARM PrimeCells connected
  * together so some interrupts are connected to the first one and some
@@ -1666,7 +1698,7 @@
 	BUG_ON(IS_ERR(clk));
 	clk_enable(clk);
 
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < U300_VIC_IRQS_END; i++)
 		set_bit(i, (unsigned long *) &mask[0]);
 	vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0], mask[0]);
 	vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1], mask[1]);
@@ -1828,6 +1860,10 @@
 
 	u300_assign_physmem();
 
+	/* Initialize pinmuxing */
+	pinmux_register_mappings(u300_pinmux_map,
+				 ARRAY_SIZE(u300_pinmux_map));
+
 	/* Register subdevices on the I2C buses */
 	u300_i2c_register_board_devices();
 
@@ -1837,17 +1873,10 @@
 	/* 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
-	 * both subsystems are requesting this mode.
-	 * If we not share the Acc SDRAM, this is never the case. Therefore
-	 * enable it here from the App side.
-	 */
+	/* Enable SEMI self refresh */
 	val = readw(U300_SYSCON_VBASE + U300_SYSCON_SMCR) |
 		U300_SYSCON_SMCR_SEMI_SREFREQ_ENABLE;
 	writew(val, U300_SYSCON_VBASE + U300_SYSCON_SMCR);
-#endif /* CONFIG_MACH_U300_SEMI_IS_SHARED */
 }
 
 static int core_module_init(void)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-u300/i2c.c linux-libre-3.2-gnu/arch/arm/mach-u300/i2c.c
--- linux-libre-3.1-gnu/arch/arm/mach-u300/i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-u300/i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -256,57 +256,8 @@
 };
 #endif
 
-#ifdef CONFIG_AB3550_CORE
-static struct abx500_init_settings ab3550_init_settings[] = {
-	{
-		.bank = 0,
-		.reg = AB3550_IMR1,
-		.setting = 0xff
-	},
-	{
-		.bank = 0,
-		.reg = AB3550_IMR2,
-		.setting = 0xff
-	},
-	{
-		.bank = 0,
-		.reg = AB3550_IMR3,
-		.setting = 0xff
-	},
-	{
-		.bank = 0,
-		.reg = AB3550_IMR4,
-		.setting = 0xff
-	},
-	{
-		.bank = 0,
-		.reg = AB3550_IMR5,
-		/* The two most significant bits are not used */
-		.setting = 0x3f
-	},
-};
-
-static struct ab3550_platform_data ab3550_plf_data = {
-	.irq = {
-		.base = IRQ_AB3550_BASE,
-		.count = (IRQ_AB3550_END - IRQ_AB3550_BASE + 1),
-	},
-	.dev_data = {
-	},
-	.init_settings = ab3550_init_settings,
-	.init_settings_sz = ARRAY_SIZE(ab3550_init_settings),
-};
-#endif
-
 static struct i2c_board_info __initdata bus0_i2c_board_info[] = {
-#if defined(CONFIG_AB3550_CORE)
-	{
-		.type = "ab3550",
-		.addr = 0x4A,
-		.irq = IRQ_U300_IRQ0_EXT,
-		.platform_data = &ab3550_plf_data,
-	},
-#elif defined(CONFIG_AB3100_CORE)
+#ifdef CONFIG_AB3100_CORE
 	{
 		.type = "ab3100",
 		.addr = 0x48,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-u300/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-u300/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-u300/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-u300/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  */
 #include <mach/hardware.h>
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	/* If we move the address using MMU, use this. */
 	ldr	\rp,	  = U300_SLOW_PER_PHYS_BASE @ MMU off, physical address
 	ldr	\rv,	  = U300_SLOW_PER_VIRT_BASE @ MMU on, virtual address
diff -druN linux-libre-3.1-gnu/arch/arm/mach-u300/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-u300/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-u300/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-u300/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,294 +1 @@
-/*
- *
- * arch/arm/mach-u300/include/mach/gpio.h
- *
- *
- * Copyright (C) 2007-2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * GPIO block resgister definitions and inline macros for
- * U300 GPIO COH 901 335 or COH 901 571/3
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- */
-
-#ifndef __MACH_U300_GPIO_H
-#define __MACH_U300_GPIO_H
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-/* Switch type depending on platform/chip variant */
-#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
-#define U300_COH901335
-#endif
-#if defined(CONFIG_MACH_U300_BS365) || defined(CONFIG_MACH_U300_BS335)
-#define U300_COH901571_3
-#endif
-
-/* Get base address for regs here */
-#include "u300-regs.h"
-/* IRQ numbers */
-#include "irqs.h"
-
-/*
- * This is the GPIO block definitions. GPIO (General Purpose I/O) can be
- * used for anything, and often is. The event/enable etc figures are for
- * the lowermost pin (pin 0 on each port), shift this left to match your
- * pin if you're gonna use these values.
- */
-#ifdef U300_COH901335
-#define U300_GPIO_PORTX_SPACING				(0x1C)
-/* Port X Pin Data Register 32bit, this is both input and output (R/W) */
-#define U300_GPIO_PXPDIR				(0x00)
-#define U300_GPIO_PXPDOR				(0x00)
-/* Port X Pin Config Register 32bit (R/W) */
-#define U300_GPIO_PXPCR					(0x04)
-#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK		(0x0000FFFFUL)
-#define U300_GPIO_PXPCR_PIN_MODE_MASK			(0x00000003UL)
-#define U300_GPIO_PXPCR_PIN_MODE_SHIFT			(0x00000002UL)
-#define U300_GPIO_PXPCR_PIN_MODE_INPUT			(0x00000000UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL	(0x00000001UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN	(0x00000002UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE	(0x00000003UL)
-/* Port X Interrupt Event Register 32bit (R/W) */
-#define U300_GPIO_PXIEV					(0x08)
-#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK		(0x000000FFUL)
-#define U300_GPIO_PXIEV_IRQ_EVENT			(0x00000001UL)
-/* Port X Interrupt Enable Register 32bit (R/W) */
-#define U300_GPIO_PXIEN					(0x0C)
-#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK		(0x000000FFUL)
-#define U300_GPIO_PXIEN_IRQ_ENABLE			(0x00000001UL)
-/* Port X Interrupt Force Register 32bit (R/W) */
-#define U300_GPIO_PXIFR					(0x10)
-#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK		(0x000000FFUL)
-#define U300_GPIO_PXIFR_IRQ_FORCE			(0x00000001UL)
-/* Port X Interrupt Config Register 32bit (R/W) */
-#define U300_GPIO_PXICR					(0x14)
-#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK		(0x000000FFUL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_MASK			(0x00000001UL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE		(0x00000000UL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE		(0x00000001UL)
-/* Port X Pull-up Enable Register 32bit (R/W) */
-#define U300_GPIO_PXPER					(0x18)
-#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK	(0x000000FFUL)
-#define U300_GPIO_PXPER_PULL_UP_DISABLE			(0x00000001UL)
-/* Control Register 32bit (R/W) */
-#define U300_GPIO_CR					(0x54)
-#define U300_GPIO_CR_BLOCK_CLOCK_ENABLE			(0x00000001UL)
-/* three ports of 8 bits each = GPIO pins 0..23 */
-#define U300_GPIO_NUM_PORTS 3
-#define U300_GPIO_PINS_PER_PORT 8
-#define U300_GPIO_MAX	(U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1)
-#endif
-
-#ifdef U300_COH901571_3
-/*
- * Control Register 32bit (R/W)
- * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores
- * gives the number of GPIO pins.
- * bit 8-2  (mask 0x000001FC) contains the core version ID.
- */
-#define U300_GPIO_CR					(0x00)
-#define U300_GPIO_CR_SYNC_SEL_ENABLE			(0x00000002UL)
-#define U300_GPIO_CR_BLOCK_CLKRQ_ENABLE			(0x00000001UL)
-#define U300_GPIO_PORTX_SPACING				(0x30)
-/* Port X Pin Data INPUT Register 32bit (R/W) */
-#define U300_GPIO_PXPDIR				(0x04)
-/* Port X Pin Data OUTPUT Register 32bit (R/W) */
-#define U300_GPIO_PXPDOR				(0x08)
-/* Port X Pin Config Register 32bit (R/W) */
-#define U300_GPIO_PXPCR					(0x0C)
-#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK		(0x0000FFFFUL)
-#define U300_GPIO_PXPCR_PIN_MODE_MASK			(0x00000003UL)
-#define U300_GPIO_PXPCR_PIN_MODE_SHIFT			(0x00000002UL)
-#define U300_GPIO_PXPCR_PIN_MODE_INPUT			(0x00000000UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL	(0x00000001UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN	(0x00000002UL)
-#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE	(0x00000003UL)
-/* Port X Pull-up Enable Register 32bit (R/W) */
-#define U300_GPIO_PXPER					(0x10)
-#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK	(0x000000FFUL)
-#define U300_GPIO_PXPER_PULL_UP_DISABLE			(0x00000001UL)
-/* Port X Interrupt Event Register 32bit (R/W) */
-#define U300_GPIO_PXIEV					(0x14)
-#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK		(0x000000FFUL)
-#define U300_GPIO_PXIEV_IRQ_EVENT			(0x00000001UL)
-/* Port X Interrupt Enable Register 32bit (R/W) */
-#define U300_GPIO_PXIEN					(0x18)
-#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK		(0x000000FFUL)
-#define U300_GPIO_PXIEN_IRQ_ENABLE			(0x00000001UL)
-/* Port X Interrupt Force Register 32bit (R/W) */
-#define U300_GPIO_PXIFR					(0x1C)
-#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK		(0x000000FFUL)
-#define U300_GPIO_PXIFR_IRQ_FORCE			(0x00000001UL)
-/* Port X Interrupt Config Register 32bit (R/W) */
-#define U300_GPIO_PXICR					(0x20)
-#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK		(0x000000FFUL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_MASK			(0x00000001UL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE		(0x00000000UL)
-#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE		(0x00000001UL)
-#ifdef CONFIG_MACH_U300_BS335
-/* seven ports of 8 bits each = GPIO pins 0..55 */
-#define U300_GPIO_NUM_PORTS 7
-#else
-/* five ports of 8 bits each = GPIO pins 0..39 */
-#define U300_GPIO_NUM_PORTS 5
-#endif
-#define U300_GPIO_PINS_PER_PORT 8
-#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1)
-#endif
-
-/*
- * Individual pin assignments for the B26/S26. Notice that the
- * actual usage of these pins depends on the PAD MUX settings, that
- * is why the same number can potentially appear several times.
- * In the reference design each pin is only used for one purpose.
- * These were determined by inspecting the B26/S26 schematic:
- * 2/1911-ROA 128 1603
- */
-#ifdef CONFIG_MACH_U300_BS2X
-#define U300_GPIO_PIN_UART_RX		0
-#define U300_GPIO_PIN_UART_TX		1
-#define U300_GPIO_PIN_GPIO02		2  /* Unrouted */
-#define U300_GPIO_PIN_GPIO03		3  /* Unrouted */
-#define U300_GPIO_PIN_CAM_SLEEP		4
-#define U300_GPIO_PIN_CAM_REG_EN	5
-#define U300_GPIO_PIN_GPIO06		6  /* Unrouted */
-#define U300_GPIO_PIN_GPIO07		7  /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO08		8  /* Service point SP2321 */
-#define U300_GPIO_PIN_GPIO09		9  /* Service point SP2322 */
-#define U300_GPIO_PIN_PHFSENSE		10 /* Headphone jack sensing */
-#define U300_GPIO_PIN_MMC_CLKRET	11 /* Clock return from MMC/SD card */
-#define U300_GPIO_PIN_MMC_CD		12 /* MMC Card insertion detection */
-#define U300_GPIO_PIN_FLIPSENSE		13 /* Mechanical flip sensing */
-#define U300_GPIO_PIN_GPIO14		14 /* DSP JTAG Port RTCK */
-#define U300_GPIO_PIN_GPIO15		15 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO16		16 /* Unrouted */
-#define U300_GPIO_PIN_GPIO17		17 /* Unrouted */
-#define U300_GPIO_PIN_GPIO18		18 /* Unrouted */
-#define U300_GPIO_PIN_GPIO19		19 /* Unrouted */
-#define U300_GPIO_PIN_GPIO20		20 /* Unrouted */
-#define U300_GPIO_PIN_GPIO21		21 /* Unrouted */
-#define U300_GPIO_PIN_GPIO22		22 /* Unrouted */
-#define U300_GPIO_PIN_GPIO23		23 /* Unrouted */
-#endif
-
-/*
- * Individual pin assignments for the B330/S330 and B365/S365.
- * Notice that the actual usage of these pins depends on the
- * PAD MUX settings, that is why the same number can potentially
- * appear several times. In the reference design each pin is only
- * used for one purpose. These were determined by inspecting the
- * S365 schematic.
- */
-#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \
-    defined(CONFIG_MACH_U300_BS335)
-#define U300_GPIO_PIN_UART_RX		0
-#define U300_GPIO_PIN_UART_TX		1
-#define U300_GPIO_PIN_UART_CTS		2
-#define U300_GPIO_PIN_UART_RTS		3
-#define U300_GPIO_PIN_CAM_MAIN_STANDBY	4 /* Camera MAIN standby */
-#define U300_GPIO_PIN_GPIO05		5 /* Unrouted */
-#define U300_GPIO_PIN_MS_CD		6 /* Memory Stick Card insertion */
-#define U300_GPIO_PIN_GPIO07		7 /* Test point TP2430 */
-
-#define U300_GPIO_PIN_GPIO08		8 /* Test point TP2437 */
-#define U300_GPIO_PIN_GPIO09		9 /* Test point TP2431 */
-#define U300_GPIO_PIN_GPIO10		10 /* Test point TP2432 */
-#define U300_GPIO_PIN_MMC_CLKRET	11 /* Clock return from MMC/SD card */
-#define U300_GPIO_PIN_MMC_CD		12 /* MMC Card insertion detection */
-#define U300_GPIO_PIN_CAM_SUB_STANDBY	13 /* Camera SUB standby */
-#define U300_GPIO_PIN_GPIO14		14 /* Test point TP2436 */
-#define U300_GPIO_PIN_GPIO15		15 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO16		16 /* Test point TP2438 */
-#define U300_GPIO_PIN_PHFSENSE		17 /* Headphone jack sensing */
-#define U300_GPIO_PIN_GPIO18		18 /* Test point TP2439 */
-#define U300_GPIO_PIN_GPIO19		19 /* Routed somewhere */
-#define U300_GPIO_PIN_GPIO20		20 /* Unrouted */
-#define U300_GPIO_PIN_GPIO21		21 /* Unrouted */
-#define U300_GPIO_PIN_GPIO22		22 /* Unrouted */
-#define U300_GPIO_PIN_GPIO23		23 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO24		24 /* Unrouted */
-#define U300_GPIO_PIN_GPIO25		25 /* Unrouted */
-#define U300_GPIO_PIN_GPIO26		26 /* Unrouted */
-#define U300_GPIO_PIN_GPIO27		27 /* Unrouted */
-#define U300_GPIO_PIN_GPIO28		28 /* Unrouted */
-#define U300_GPIO_PIN_GPIO29		29 /* Unrouted */
-#define U300_GPIO_PIN_GPIO30		30 /* Unrouted */
-#define U300_GPIO_PIN_GPIO31		31 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO32		32 /* Unrouted */
-#define U300_GPIO_PIN_GPIO33		33 /* Unrouted */
-#define U300_GPIO_PIN_GPIO34		34 /* Unrouted */
-#define U300_GPIO_PIN_GPIO35		35 /* Unrouted */
-#define U300_GPIO_PIN_GPIO36		36 /* Unrouted */
-#define U300_GPIO_PIN_GPIO37		37 /* Unrouted */
-#define U300_GPIO_PIN_GPIO38		38 /* Unrouted */
-#define U300_GPIO_PIN_GPIO39		39 /* Unrouted */
-
-#ifdef CONFIG_MACH_U300_BS335
-
-#define U300_GPIO_PIN_GPIO40		40 /* Unrouted */
-#define U300_GPIO_PIN_GPIO41		41 /* Unrouted */
-#define U300_GPIO_PIN_GPIO42		42 /* Unrouted */
-#define U300_GPIO_PIN_GPIO43		43 /* Unrouted */
-#define U300_GPIO_PIN_GPIO44		44 /* Unrouted */
-#define U300_GPIO_PIN_GPIO45		45 /* Unrouted */
-#define U300_GPIO_PIN_GPIO46		46 /* Unrouted */
-#define U300_GPIO_PIN_GPIO47		47 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO48		48 /* Unrouted */
-#define U300_GPIO_PIN_GPIO49		49 /* Unrouted */
-#define U300_GPIO_PIN_GPIO50		50 /* Unrouted */
-#define U300_GPIO_PIN_GPIO51		51 /* Unrouted */
-#define U300_GPIO_PIN_GPIO52		52 /* Unrouted */
-#define U300_GPIO_PIN_GPIO53		53 /* Unrouted */
-#define U300_GPIO_PIN_GPIO54		54 /* Unrouted */
-#define U300_GPIO_PIN_GPIO55		55 /* Unrouted */
-#endif
-
-#endif
-
-/* translates a pin number to a port number */
-#define PIN_TO_PORT(val) (val >> 3)
-
-/* These can be found in arch/arm/mach-u300/gpio.c */
-extern int gpio_is_valid(int number);
-extern int gpio_request(unsigned gpio, const char *label);
-extern void gpio_free(unsigned gpio);
-extern int gpio_direction_input(unsigned gpio);
-extern int gpio_direction_output(unsigned gpio, int value);
-extern int gpio_register_callback(unsigned gpio,
-				  int (*func)(void *arg),
-				  void *);
-extern int gpio_unregister_callback(unsigned gpio);
-extern void enable_irq_on_gpio_pin(unsigned gpio, int edge);
-extern void disable_irq_on_gpio_pin(unsigned gpio);
-extern void gpio_pullup(unsigned gpio, int value);
-extern int gpio_get_value(unsigned gpio);
-extern void gpio_set_value(unsigned gpio, int value);
-
-#define gpio_get_value_cansleep gpio_get_value
-#define gpio_set_value_cansleep gpio_set_value
-
-/* wrappers to sleep-enable the previous two functions */
-static inline unsigned gpio_to_irq(unsigned gpio)
-{
-	return PIN_TO_PORT(gpio) + IRQ_U300_GPIO_PORT0;
-}
-
-static inline unsigned irq_to_gpio(unsigned irq)
-{
-	/*
-	 * FIXME: This is no 1-1 mapping at all, it points to the
-	 * whole block of 8 pins.
-	 */
-	return (irq - IRQ_U300_GPIO_PORT0) << 3;
-}
-
-#endif
+/* empty */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-u300/include/mach/gpio-u300.h linux-libre-3.2-gnu/arch/arm/mach-u300/include/mach/gpio-u300.h
--- linux-libre-3.1-gnu/arch/arm/mach-u300/include/mach/gpio-u300.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-u300/include/mach/gpio-u300.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2007-2011 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * GPIO block resgister definitions and inline macros for
+ * U300 GPIO COH 901 335 or COH 901 571/3
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+
+#ifndef __MACH_U300_GPIO_U300_H
+#define __MACH_U300_GPIO_U300_H
+
+/*
+ * Individual pin assignments for the B26/S26. Notice that the
+ * actual usage of these pins depends on the PAD MUX settings, that
+ * is why the same number can potentially appear several times.
+ * In the reference design each pin is only used for one purpose.
+ * These were determined by inspecting the B26/S26 schematic:
+ * 2/1911-ROA 128 1603
+ */
+#ifdef CONFIG_MACH_U300_BS2X
+#define U300_GPIO_PIN_UART_RX		0
+#define U300_GPIO_PIN_UART_TX		1
+#define U300_GPIO_PIN_GPIO02		2  /* Unrouted */
+#define U300_GPIO_PIN_GPIO03		3  /* Unrouted */
+#define U300_GPIO_PIN_CAM_SLEEP		4
+#define U300_GPIO_PIN_CAM_REG_EN	5
+#define U300_GPIO_PIN_GPIO06		6  /* Unrouted */
+#define U300_GPIO_PIN_GPIO07		7  /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO08		8  /* Service point SP2321 */
+#define U300_GPIO_PIN_GPIO09		9  /* Service point SP2322 */
+#define U300_GPIO_PIN_PHFSENSE		10 /* Headphone jack sensing */
+#define U300_GPIO_PIN_MMC_CLKRET	11 /* Clock return from MMC/SD card */
+#define U300_GPIO_PIN_MMC_CD		12 /* MMC Card insertion detection */
+#define U300_GPIO_PIN_FLIPSENSE		13 /* Mechanical flip sensing */
+#define U300_GPIO_PIN_GPIO14		14 /* DSP JTAG Port RTCK */
+#define U300_GPIO_PIN_GPIO15		15 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO16		16 /* Unrouted */
+#define U300_GPIO_PIN_GPIO17		17 /* Unrouted */
+#define U300_GPIO_PIN_GPIO18		18 /* Unrouted */
+#define U300_GPIO_PIN_GPIO19		19 /* Unrouted */
+#define U300_GPIO_PIN_GPIO20		20 /* Unrouted */
+#define U300_GPIO_PIN_GPIO21		21 /* Unrouted */
+#define U300_GPIO_PIN_GPIO22		22 /* Unrouted */
+#define U300_GPIO_PIN_GPIO23		23 /* Unrouted */
+#endif
+
+/*
+ * Individual pin assignments for the B330/S330 and B365/S365.
+ * Notice that the actual usage of these pins depends on the
+ * PAD MUX settings, that is why the same number can potentially
+ * appear several times. In the reference design each pin is only
+ * used for one purpose. These were determined by inspecting the
+ * S365 schematic.
+ */
+#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \
+    defined(CONFIG_MACH_U300_BS335)
+#define U300_GPIO_PIN_UART_RX		0
+#define U300_GPIO_PIN_UART_TX		1
+#define U300_GPIO_PIN_UART_CTS		2
+#define U300_GPIO_PIN_UART_RTS		3
+#define U300_GPIO_PIN_CAM_MAIN_STANDBY	4 /* Camera MAIN standby */
+#define U300_GPIO_PIN_GPIO05		5 /* Unrouted */
+#define U300_GPIO_PIN_MS_CD		6 /* Memory Stick Card insertion */
+#define U300_GPIO_PIN_GPIO07		7 /* Test point TP2430 */
+
+#define U300_GPIO_PIN_GPIO08		8 /* Test point TP2437 */
+#define U300_GPIO_PIN_GPIO09		9 /* Test point TP2431 */
+#define U300_GPIO_PIN_GPIO10		10 /* Test point TP2432 */
+#define U300_GPIO_PIN_MMC_CLKRET	11 /* Clock return from MMC/SD card */
+#define U300_GPIO_PIN_MMC_CD		12 /* MMC Card insertion detection */
+#define U300_GPIO_PIN_CAM_SUB_STANDBY	13 /* Camera SUB standby */
+#define U300_GPIO_PIN_GPIO14		14 /* Test point TP2436 */
+#define U300_GPIO_PIN_GPIO15		15 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO16		16 /* Test point TP2438 */
+#define U300_GPIO_PIN_PHFSENSE		17 /* Headphone jack sensing */
+#define U300_GPIO_PIN_GPIO18		18 /* Test point TP2439 */
+#define U300_GPIO_PIN_GPIO19		19 /* Routed somewhere */
+#define U300_GPIO_PIN_GPIO20		20 /* Unrouted */
+#define U300_GPIO_PIN_GPIO21		21 /* Unrouted */
+#define U300_GPIO_PIN_GPIO22		22 /* Unrouted */
+#define U300_GPIO_PIN_GPIO23		23 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO24		24 /* Unrouted */
+#define U300_GPIO_PIN_GPIO25		25 /* Unrouted */
+#define U300_GPIO_PIN_GPIO26		26 /* Unrouted */
+#define U300_GPIO_PIN_GPIO27		27 /* Unrouted */
+#define U300_GPIO_PIN_GPIO28		28 /* Unrouted */
+#define U300_GPIO_PIN_GPIO29		29 /* Unrouted */
+#define U300_GPIO_PIN_GPIO30		30 /* Unrouted */
+#define U300_GPIO_PIN_GPIO31		31 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO32		32 /* Unrouted */
+#define U300_GPIO_PIN_GPIO33		33 /* Unrouted */
+#define U300_GPIO_PIN_GPIO34		34 /* Unrouted */
+#define U300_GPIO_PIN_GPIO35		35 /* Unrouted */
+#define U300_GPIO_PIN_GPIO36		36 /* Unrouted */
+#define U300_GPIO_PIN_GPIO37		37 /* Unrouted */
+#define U300_GPIO_PIN_GPIO38		38 /* Unrouted */
+#define U300_GPIO_PIN_GPIO39		39 /* Unrouted */
+
+#ifdef CONFIG_MACH_U300_BS335
+
+#define U300_GPIO_PIN_GPIO40		40 /* Unrouted */
+#define U300_GPIO_PIN_GPIO41		41 /* Unrouted */
+#define U300_GPIO_PIN_GPIO42		42 /* Unrouted */
+#define U300_GPIO_PIN_GPIO43		43 /* Unrouted */
+#define U300_GPIO_PIN_GPIO44		44 /* Unrouted */
+#define U300_GPIO_PIN_GPIO45		45 /* Unrouted */
+#define U300_GPIO_PIN_GPIO46		46 /* Unrouted */
+#define U300_GPIO_PIN_GPIO47		47 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO48		48 /* Unrouted */
+#define U300_GPIO_PIN_GPIO49		49 /* Unrouted */
+#define U300_GPIO_PIN_GPIO50		50 /* Unrouted */
+#define U300_GPIO_PIN_GPIO51		51 /* Unrouted */
+#define U300_GPIO_PIN_GPIO52		52 /* Unrouted */
+#define U300_GPIO_PIN_GPIO53		53 /* Unrouted */
+#define U300_GPIO_PIN_GPIO54		54 /* Unrouted */
+#define U300_GPIO_PIN_GPIO55		55 /* Unrouted */
+#endif
+
+#endif
+
+/**
+ * enum u300_gpio_variant - the type of U300 GPIO employed
+ */
+enum u300_gpio_variant {
+	U300_GPIO_COH901335,
+	U300_GPIO_COH901571_3_BS335,
+	U300_GPIO_COH901571_3_BS365,
+};
+
+/**
+ * struct u300_gpio_platform - U300 GPIO platform data
+ * @variant: IP block variant
+ * @ports: number of GPIO block ports
+ * @gpio_base: first GPIO number for this block (use a free range)
+ * @gpio_irq_base: first GPIO IRQ number for this block (use a free range)
+ */
+struct u300_gpio_platform {
+	enum u300_gpio_variant variant;
+	u8 ports;
+	int gpio_base;
+	int gpio_irq_base;
+};
+
+#endif /* __MACH_U300_GPIO_U300_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-u300/include/mach/irqs.h linux-libre-3.2-gnu/arch/arm/mach-u300/include/mach/irqs.h
--- linux-libre-3.1-gnu/arch/arm/mach-u300/include/mach/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-u300/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -72,7 +72,7 @@
 
 /* DB3150 and DB3200 have only 45 IRQs */
 #if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
-#define U300_NR_IRQS			45
+#define U300_VIC_IRQS_END		45
 #endif
 
 /* The DB3350-specific interrupt lines */
@@ -88,7 +88,7 @@
 #define IRQ_U300_GPIO_PORT4		53
 #define IRQ_U300_GPIO_PORT5		54
 #define IRQ_U300_GPIO_PORT6		55
-#define U300_NR_IRQS			56
+#define U300_VIC_IRQS_END		56
 #endif
 
 /* The DB3210-specific interrupt lines */
@@ -106,16 +106,17 @@
 #define IRQ_U300_NFIF			45
 #define IRQ_U300_NFIF2			46
 #define IRQ_U300_SYSCON_PLL_LOCK	47
-#define U300_NR_IRQS			48
+#define U300_VIC_IRQS_END		48
 #endif
 
-#ifdef CONFIG_AB3550_CORE
-#define IRQ_AB3550_BASE			(U300_NR_IRQS)
-#define IRQ_AB3550_END			(IRQ_AB3550_BASE + 37)
-
-#define NR_IRQS				(IRQ_AB3550_END + 1)
+/* Maximum 8*7 GPIO lines */
+#ifdef CONFIG_GPIO_U300
+#define IRQ_U300_GPIO_BASE		(U300_VIC_IRQS_END)
+#define IRQ_U300_GPIO_END		(IRQ_U300_GPIO_BASE + 56)
 #else
-#define NR_IRQS U300_NR_IRQS
+#define IRQ_U300_GPIO_END		(U300_VIC_IRQS_END)
 #endif
 
+#define NR_IRQS				(IRQ_U300_GPIO_END)
+
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-u300/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-u300/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-u300/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-u300/include/mach/memory.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,30 +13,7 @@
 #ifndef __MACH_MEMORY_H
 #define __MACH_MEMORY_H
 
-#ifdef CONFIG_MACH_U300_DUAL_RAM
-
-#define PLAT_PHYS_OFFSET		UL(0x48000000)
-#define BOOT_PARAMS_OFFSET	(PHYS_OFFSET + 0x100)
-
-#else
-
-#ifdef CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
-#define PLAT_PHYS_OFFSET (0x28000000 + \
-	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE - \
-	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
-#else
-#define PLAT_PHYS_OFFSET (0x28000000 + \
-	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE +	\
-	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
-#endif
-#define BOOT_PARAMS_OFFSET (0x28000000 + \
-	    (CONFIG_MACH_U300_ACCESS_MEM_SIZE +		\
-	    (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024 + 0x100)
-#endif
-
-/*
- * We enable a real big DMA buffer if need be.
- */
-#define CONSISTENT_DMA_SIZE SZ_4M
+#define PLAT_PHYS_OFFSET	UL(0x48000000)
+#define BOOT_PARAMS_OFFSET	0x100
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-u300/include/mach/syscon.h linux-libre-3.2-gnu/arch/arm/mach-u300/include/mach/syscon.h
--- linux-libre-3.1-gnu/arch/arm/mach-u300/include/mach/syscon.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-u300/include/mach/syscon.h	2012-01-04 18:55:44.000000000 -0500
@@ -234,91 +234,6 @@
 #define U300_SYSCON_ECCR_EMIF_1_RET_OUT_CLK_EN_N_DISABLE	(0x0004)
 #define U300_SYSCON_ECCR_EMIF_MEMCLK_RET_EN_N_DISABLE		(0x0002)
 #define U300_SYSCON_ECCR_EMIF_SDRCLK_RET_EN_N_DISABLE		(0x0001)
-/* PAD MUX Control register 1 (LOW) 16bit (R/W) */
-#define U300_SYSCON_PMC1LR					(0x007C)
-#define U300_SYSCON_PMC1LR_MASK					(0xFFFF)
-#define U300_SYSCON_PMC1LR_CDI_MASK				(0xC000)
-#define U300_SYSCON_PMC1LR_CDI_CDI				(0x0000)
-#define U300_SYSCON_PMC1LR_CDI_EMIF				(0x4000)
-#ifdef CONFIG_MACH_U300_BS335
-#define U300_SYSCON_PMC1LR_CDI_CDI2				(0x8000)
-#define U300_SYSCON_PMC1LR_CDI_WCDMA_APP_GPIO			(0xC000)
-#elif CONFIG_MACH_U300_BS365
-#define U300_SYSCON_PMC1LR_CDI_GPIO				(0x8000)
-#define U300_SYSCON_PMC1LR_CDI_WCDMA				(0xC000)
-#endif
-#define U300_SYSCON_PMC1LR_PDI_MASK				(0x3000)
-#define U300_SYSCON_PMC1LR_PDI_PDI				(0x0000)
-#define U300_SYSCON_PMC1LR_PDI_EGG				(0x1000)
-#define U300_SYSCON_PMC1LR_PDI_WCDMA				(0x3000)
-#define U300_SYSCON_PMC1LR_MMCSD_MASK				(0x0C00)
-#define U300_SYSCON_PMC1LR_MMCSD_MMCSD				(0x0000)
-#define U300_SYSCON_PMC1LR_MMCSD_MSPRO				(0x0400)
-#define U300_SYSCON_PMC1LR_MMCSD_DSP				(0x0800)
-#define U300_SYSCON_PMC1LR_MMCSD_WCDMA				(0x0C00)
-#define U300_SYSCON_PMC1LR_ETM_MASK				(0x0300)
-#define U300_SYSCON_PMC1LR_ETM_ACC				(0x0000)
-#define U300_SYSCON_PMC1LR_ETM_APP				(0x0100)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_MASK			(0x00C0)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC			(0x0000)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_NFIF			(0x0040)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_SDRAM			(0x0080)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC_2GB		(0x00C0)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_MASK			(0x0030)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_STATIC			(0x0000)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_NFIF			(0x0010)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SDRAM			(0x0020)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SEMI			(0x0030)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_MASK			(0x000C)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_STATIC			(0x0000)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_NFIF			(0x0004)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SDRAM			(0x0008)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SEMI			(0x000C)
-#define U300_SYSCON_PMC1LR_EMIF_1_MASK				(0x0003)
-#define U300_SYSCON_PMC1LR_EMIF_1_STATIC			(0x0000)
-#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM0			(0x0001)
-#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM1			(0x0002)
-#define U300_SYSCON_PMC1LR_EMIF_1				(0x0003)
-/* PAD MUX Control register 2 (HIGH) 16bit (R/W) */
-#define U300_SYSCON_PMC1HR					(0x007E)
-#define U300_SYSCON_PMC1HR_MASK					(0xFFFF)
-#define U300_SYSCON_PMC1HR_MISC_2_MASK				(0xC000)
-#define U300_SYSCON_PMC1HR_MISC_2_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC1HR_MISC_2_MSPRO				(0x4000)
-#define U300_SYSCON_PMC1HR_MISC_2_DSP				(0x8000)
-#define U300_SYSCON_PMC1HR_MISC_2_AAIF				(0xC000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_MASK			(0x3000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_NFIF			(0x1000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_DSP			(0x2000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_AAIF			(0x3000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_MASK			(0x0C00)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_MMC			(0x0400)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_DSP			(0x0800)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_AAIF			(0x0C00)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK			(0x0300)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_APP_GPIO		(0x0000)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI			(0x0100)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_AAIF			(0x0300)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK			(0x00C0)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_APP_GPIO		(0x0000)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI			(0x0040)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_AAIF			(0x00C0)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_MASK			(0x0030)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_SPI			(0x0010)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_DSP			(0x0020)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_AAIF			(0x0030)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_MASK			(0x000C)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_UART0			(0x0004)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_NFIF_CS			(0x0008)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_AAIF			(0x000C)
-#define U300_SYSCON_PMC1HR_APP_UART0_1_MASK			(0x0003)
-#define U300_SYSCON_PMC1HR_APP_UART0_1_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC1HR_APP_UART0_1_UART0			(0x0001)
-#define U300_SYSCON_PMC1HR_APP_UART0_1_AAIF			(0x0003)
 /* Step one for killing the applications system 16bit (-/W) */
 #define U300_SYSCON_KA1R					(0x0080)
 #define U300_SYSCON_KA1R_MASK					(0xFFFF)
@@ -357,57 +272,6 @@
 #define U300_SYSCON_PUCR_EMIF_1_16BIT_PU_ENABLE			(0x0080)
 #define U300_SYSCON_PUCR_EMIF_1_8BIT_PU_ENABLE			(0x0040)
 #define U300_SYSCON_PUCR_KEY_IN_PU_EN_MASK			(0x003F)
-/* Padmux 2 control */
-#define U300_SYSCON_PMC2R					(0x100)
-#define U300_SYSCON_PMC2R_APP_MISC_0_MASK			(0x00C0)
-#define U300_SYSCON_PMC2R_APP_MISC_0_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_0_EMIF_SDRAM			(0x0040)
-#define U300_SYSCON_PMC2R_APP_MISC_0_MMC			(0x0080)
-#define U300_SYSCON_PMC2R_APP_MISC_0_CDI2			(0x00C0)
-#define U300_SYSCON_PMC2R_APP_MISC_1_MASK			(0x0300)
-#define U300_SYSCON_PMC2R_APP_MISC_1_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_1_EMIF_SDRAM			(0x0100)
-#define U300_SYSCON_PMC2R_APP_MISC_1_MMC			(0x0200)
-#define U300_SYSCON_PMC2R_APP_MISC_1_CDI2			(0x0300)
-#define U300_SYSCON_PMC2R_APP_MISC_2_MASK			(0x0C00)
-#define U300_SYSCON_PMC2R_APP_MISC_2_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_2_EMIF_SDRAM			(0x0400)
-#define U300_SYSCON_PMC2R_APP_MISC_2_MMC			(0x0800)
-#define U300_SYSCON_PMC2R_APP_MISC_2_CDI2			(0x0C00)
-#define U300_SYSCON_PMC2R_APP_MISC_3_MASK			(0x3000)
-#define U300_SYSCON_PMC2R_APP_MISC_3_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_3_EMIF_SDRAM			(0x1000)
-#define U300_SYSCON_PMC2R_APP_MISC_3_MMC			(0x2000)
-#define U300_SYSCON_PMC2R_APP_MISC_3_CDI2			(0x3000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_MASK			(0xC000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_EMIF_SDRAM			(0x4000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_MMC			(0x8000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_ACC_GPIO			(0xC000)
-/* TODO: More SYSCON registers missing */
-#define U300_SYSCON_PMC3R					(0x10c)
-#define U300_SYSCON_PMC3R_APP_MISC_11_MASK			(0xc000)
-#define U300_SYSCON_PMC3R_APP_MISC_11_SPI			(0x4000)
-#define U300_SYSCON_PMC3R_APP_MISC_10_MASK			(0x3000)
-#define U300_SYSCON_PMC3R_APP_MISC_10_SPI			(0x1000)
-/* TODO: Missing other configs */
-#define U300_SYSCON_PMC4R					(0x168)
-#define U300_SYSCON_PMC4R_APP_MISC_12_MASK			(0x0003)
-#define U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO			(0x0000)
-#define U300_SYSCON_PMC4R_APP_MISC_13_MASK			(0x000C)
-#define U300_SYSCON_PMC4R_APP_MISC_13_CDI			(0x0000)
-#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA			(0x0004)
-#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA2			(0x0008)
-#define U300_SYSCON_PMC4R_APP_MISC_13_APP_GPIO			(0x000C)
-#define U300_SYSCON_PMC4R_APP_MISC_14_MASK			(0x0030)
-#define U300_SYSCON_PMC4R_APP_MISC_14_CDI			(0x0000)
-#define U300_SYSCON_PMC4R_APP_MISC_14_SMIA			(0x0010)
-#define U300_SYSCON_PMC4R_APP_MISC_14_CDI2			(0x0020)
-#define U300_SYSCON_PMC4R_APP_MISC_14_APP_GPIO			(0x0030)
-#define U300_SYSCON_PMC4R_APP_MISC_16_MASK			(0x0300)
-#define U300_SYSCON_PMC4R_APP_MISC_16_APP_GPIO_13		(0x0000)
-#define U300_SYSCON_PMC4R_APP_MISC_16_APP_UART1_CTS		(0x0100)
-#define U300_SYSCON_PMC4R_APP_MISC_16_EMIF_1_STATIC_CS5_N	(0x0200)
 /* SYS_0_CLK_CONTROL first clock control 16bit (R/W) */
 #define U300_SYSCON_S0CCR					(0x120)
 #define U300_SYSCON_S0CCR_FIELD_MASK				(0x43FF)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-u300/Kconfig linux-libre-3.2-gnu/arch/arm/mach-u300/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mach-u300/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-u300/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,9 @@
 
 config MACH_U300
 	bool "U300"
+	select PINCTRL
+	select PINMUX_U300
+	select GPIO_U300
 
 comment "ST-Ericsson U300/U330/U335/U365 Feature Selections"
 
@@ -48,39 +51,12 @@
 
 endchoice
 
-choice
-	prompt "Memory configuration"
-	default MACH_U300_SINGLE_RAM
-	---help---
-	You have to config the kernel according to the physical memory
-	configuration.
-
-config MACH_U300_SINGLE_RAM
-	bool "Single RAM"
-	help
-		Select this if you want support for Single RAM phones.
-
-config MACH_U300_DUAL_RAM
-	bool "Dual RAM"
-	help
-		Select this if you want support for Dual RAM phones.
-		This is two RAM memories on different EMIFs.
-endchoice
-
 config U300_DEBUG
 	bool "Debug support for U300"
 	depends on PM
 	help
 		Debug support for U300 in sysfs, procfs etc.
 
-config MACH_U300_SEMI_IS_SHARED
-	bool "The SEMI is used by both the access and application side"
-	depends on MACH_U300
-	help
-		This makes it possible to use the SEMI (Shared External
-		Memory Interface) from both from access and application
-		side.
-
 config MACH_U300_SPIDUMMY
 	bool "SSP/SPI dummy chip"
 	select SPI
@@ -93,25 +69,6 @@
 		you don't need it. Selecting this will activate the
 		SPI framework and ARM PL022 support.
 
-comment "All the settings below must match the bootloader's settings"
-
-config MACH_U300_ACCESS_MEM_SIZE
-       int "Access CPU memory allocation"
-       range 7 25
-       depends on MACH_U300_SINGLE_RAM
-       default 13
-       help
-		How much memory in MiB that the Access side CPU has allocated
-
-config MACH_U300_2MB_ALIGNMENT_FIX
-       bool "2MiB alignment fix"
-       depends on MACH_U300_SINGLE_RAM
-       default y
-       help
-		If yes and the Access side CPU has allocated an odd size in
-		MiB, this fix gives you one MiB extra that would otherwise be
-		lost due to Linux 2 MiB alignment policy.
-
 endmenu
 
 endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-u300/Makefile linux-libre-3.2-gnu/arch/arm/mach-u300/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-u300/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-u300/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel, U300 machine.
 #
 
-obj-y		:= core.o clock.o timer.o padmux.o
+obj-y		:= core.o clock.o timer.o
 obj-m		:=
 obj-n		:=
 obj-		:=
diff -druN linux-libre-3.1-gnu/arch/arm/mach-u300/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-u300/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-u300/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-u300/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,15 +1,4 @@
-# Note: the following conditions must always be true:
-#   ZRELADDR == virt_to_phys(TEXTADDR)
-#   PARAMS_PHYS must be within 4MB of ZRELADDR
-#   INITRD_PHYS must be in RAM
-
-ifdef CONFIG_MACH_U300_SINGLE_RAM
-     zreladdr-y	:= 0x28E08000
-  params_phys-y	:= 0x28E00100
-else
-     zreladdr-y	:= 0x48008000
-  params_phys-y	:= 0x48000100
-endif
-
+   zreladdr-y	+= 0x48008000
+params_phys-y	:= 0x48000100
 # This isn't used.
-#initrd_phys-y	:= 0x29800000
+#initrd_phys-y	:= 0x48800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-u300/mmc.c linux-libre-3.2-gnu/arch/arm/mach-u300/mmc.c
--- linux-libre-3.1-gnu/arch/arm/mach-u300/mmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-u300/mmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,15 +13,14 @@
 #include <linux/device.h>
 #include <linux/amba/bus.h>
 #include <linux/mmc/host.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 <mach/gpio-u300.h>
 
 #include "mmc.h"
-#include "padmux.h"
 
 static struct mmci_platform_data mmc0_plat_data = {
 	/*
@@ -45,24 +44,9 @@
 int __devinit mmc_init(struct amba_device *adev)
 {
 	struct device *mmcsd_device = &adev->dev;
-	struct pmx *pmx;
 	int ret = 0;
 
 	mmcsd_device->platform_data = &mmc0_plat_data;
 
-	/*
-	 * Setup padmuxing for MMC. Since this must always be
-	 * compiled into the kernel, pmx is never released.
-	 */
-	pmx = pmx_get(mmcsd_device, U300_APP_PMX_MMC_SETTING);
-
-	if (IS_ERR(pmx))
-		pr_warning("Could not get padmux handle\n");
-	else {
-		ret = pmx_activate(mmcsd_device, pmx);
-		if (IS_ERR_VALUE(ret))
-			pr_warning("Could not activate padmuxing\n");
-	}
-
 	return ret;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-u300/padmux.c linux-libre-3.2-gnu/arch/arm/mach-u300/padmux.c
--- linux-libre-3.1-gnu/arch/arm/mach-u300/padmux.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-u300/padmux.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,367 +0,0 @@
-/*
- *
- * arch/arm/mach-u300/padmux.c
- *
- *
- * Copyright (C) 2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * U300 PADMUX functions
- * Author: Martin Persson <martin.persson@stericsson.com>
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/mutex.h>
-#include <linux/string.h>
-#include <linux/bug.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <mach/u300-regs.h>
-#include <mach/syscon.h>
-#include "padmux.h"
-
-static DEFINE_MUTEX(pmx_mutex);
-
-const u32 pmx_registers[] = {
-	(U300_SYSCON_VBASE + U300_SYSCON_PMC1LR),
-	(U300_SYSCON_VBASE + U300_SYSCON_PMC1HR),
-	(U300_SYSCON_VBASE + U300_SYSCON_PMC2R),
-	(U300_SYSCON_VBASE + U300_SYSCON_PMC3R),
-	(U300_SYSCON_VBASE + U300_SYSCON_PMC4R)
-};
-
-/* High level functionality */
-
-/* Lazy dog:
- * onmask = {
- *   {"PMC1LR" mask, "PMC1LR" value},
- *   {"PMC1HR" mask, "PMC1HR" value},
- *   {"PMC2R"  mask, "PMC2R"  value},
- *   {"PMC3R"  mask, "PMC3R"  value},
- *   {"PMC4R"  mask, "PMC4R"  value}
- * }
- */
-static struct pmx mmc_setting = {
-	.setting = U300_APP_PMX_MMC_SETTING,
-	.default_on = false,
-	.activated = false,
-	.name = "MMC",
-	.onmask = {
-		   {U300_SYSCON_PMC1LR_MMCSD_MASK,
-		    U300_SYSCON_PMC1LR_MMCSD_MMCSD},
-		   {0, 0},
-		   {0, 0},
-		   {0, 0},
-		   {U300_SYSCON_PMC4R_APP_MISC_12_MASK,
-		    U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO}
-		   },
-};
-
-static struct pmx spi_setting = {
-	.setting = U300_APP_PMX_SPI_SETTING,
-	.default_on = false,
-	.activated = false,
-	.name = "SPI",
-	.onmask = {{0, 0},
-		   {U300_SYSCON_PMC1HR_APP_SPI_2_MASK |
-		    U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK |
-		    U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK,
-		    U300_SYSCON_PMC1HR_APP_SPI_2_SPI |
-		    U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI |
-		    U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI},
-		   {0, 0},
-		   {0, 0},
-		   {0, 0}
-		   },
-};
-
-/* Available padmux settings */
-static struct pmx *pmx_settings[] = {
-	&mmc_setting,
-	&spi_setting,
-};
-
-static void update_registers(struct pmx *pmx, bool activate)
-{
-	u16 regval, val, mask;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(pmx_registers); i++) {
-		if (activate)
-			val = pmx->onmask[i].val;
-		else
-			val = 0;
-
-		mask = pmx->onmask[i].mask;
-		if (mask != 0) {
-			regval = readw(pmx_registers[i]);
-			regval &= ~mask;
-			regval |= val;
-			writew(regval, pmx_registers[i]);
-		}
-	}
-}
-
-struct pmx *pmx_get(struct device *dev, enum pmx_settings setting)
-{
-	int i;
-	struct pmx *pmx = ERR_PTR(-ENOENT);
-
-	if (dev == NULL)
-		return ERR_PTR(-EINVAL);
-
-	mutex_lock(&pmx_mutex);
-	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
-		if (setting == pmx_settings[i]->setting) {
-
-			if (pmx_settings[i]->dev != NULL) {
-				WARN(1, "padmux: required setting "
-				     "in use by another consumer\n");
-			} else {
-				pmx = pmx_settings[i];
-				pmx->dev = dev;
-				dev_dbg(dev, "padmux: setting nr %d is now "
-					"bound to %s and ready to use\n",
-					setting, dev_name(dev));
-				break;
-			}
-		}
-	}
-	mutex_unlock(&pmx_mutex);
-
-	return pmx;
-}
-EXPORT_SYMBOL(pmx_get);
-
-int pmx_put(struct device *dev, struct pmx *pmx)
-{
-	int i;
-	int ret = -ENOENT;
-
-	if (pmx == NULL || dev == NULL)
-		return -EINVAL;
-
-	mutex_lock(&pmx_mutex);
-	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
-		if (pmx->setting == pmx_settings[i]->setting) {
-
-			if (dev != pmx->dev) {
-				WARN(1, "padmux: cannot release handle as "
-					"it is bound to another consumer\n");
-				ret = -EINVAL;
-				break;
-			} else {
-				pmx_settings[i]->dev = NULL;
-				ret = 0;
-				break;
-			}
-		}
-	}
-	mutex_unlock(&pmx_mutex);
-
-	return ret;
-}
-EXPORT_SYMBOL(pmx_put);
-
-int pmx_activate(struct device *dev, struct pmx *pmx)
-{
-	int i, j, ret;
-	ret = 0;
-
-	if (pmx == NULL || dev == NULL)
-		return -EINVAL;
-
-	mutex_lock(&pmx_mutex);
-
-	/* Make sure the required bits are not used */
-	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
-		if (pmx_settings[i]->dev == NULL || pmx_settings[i] == pmx)
-			continue;
-
-		for (j = 0; j < ARRAY_SIZE(pmx_registers); j++) {
-
-			if (pmx_settings[i]->onmask[j].mask & pmx->
-				onmask[j].mask) {
-				/* More than one entry on the same bits */
-				WARN(1, "padmux: cannot activate "
-					"setting. Bit conflict with "
-					"an active setting\n");
-
-				ret = -EUSERS;
-				goto exit;
-			}
-		}
-	}
-	update_registers(pmx, true);
-	pmx->activated = true;
-	dev_dbg(dev, "padmux: setting nr %d is activated\n",
-		pmx->setting);
-
-exit:
-	mutex_unlock(&pmx_mutex);
-	return ret;
-}
-EXPORT_SYMBOL(pmx_activate);
-
-int pmx_deactivate(struct device *dev, struct pmx *pmx)
-{
-	int i;
-	int ret = -ENOENT;
-
-	if (pmx == NULL || dev == NULL)
-		return -EINVAL;
-
-	mutex_lock(&pmx_mutex);
-	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
-		if (pmx_settings[i]->dev == NULL)
-			continue;
-
-		if (pmx->setting == pmx_settings[i]->setting) {
-
-			if (dev != pmx->dev) {
-				WARN(1, "padmux: cannot deactivate "
-				     "pmx setting as it was activated "
-				     "by another consumer\n");
-
-				ret = -EBUSY;
-				continue;
-			} else {
-				update_registers(pmx, false);
-				pmx_settings[i]->dev = NULL;
-				pmx->activated = false;
-				ret = 0;
-				dev_dbg(dev, "padmux: setting nr %d is deactivated",
-					pmx->setting);
-				break;
-			}
-		}
-	}
-	mutex_unlock(&pmx_mutex);
-
-	return ret;
-}
-EXPORT_SYMBOL(pmx_deactivate);
-
-/*
- * For internal use only. If it is to be exported,
- * it should be reentrant. Notice that pmx_activate
- * (i.e. runtime settings) always override default settings.
- */
-static int pmx_set_default(void)
-{
-	/* Used to identify several entries on the same bits */
-	u16 modbits[ARRAY_SIZE(pmx_registers)];
-
-	int i, j;
-
-	memset(modbits, 0, ARRAY_SIZE(pmx_registers) * sizeof(u16));
-
-	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
-		if (!pmx_settings[i]->default_on)
-			continue;
-
-		for (j = 0; j < ARRAY_SIZE(pmx_registers); j++) {
-
-			/* Make sure there is only one entry on the same bits */
-			if (modbits[j] & pmx_settings[i]->onmask[j].mask) {
-				BUG();
-				return -EUSERS;
-			}
-			modbits[j] |= pmx_settings[i]->onmask[j].mask;
-		}
-		update_registers(pmx_settings[i], true);
-	}
-	return 0;
-}
-
-#if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG))
-static int pmx_show(struct seq_file *s, void *data)
-{
-	int i;
-	seq_printf(s, "-------------------------------------------------\n");
-	seq_printf(s, "SETTING     BOUND TO DEVICE               STATE\n");
-	seq_printf(s, "-------------------------------------------------\n");
-	mutex_lock(&pmx_mutex);
-	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-		/* Format pmx and device name nicely */
-		char cdp[33];
-		int chars;
-
-		chars = snprintf(&cdp[0], 17, "%s", pmx_settings[i]->name);
-		while (chars < 16) {
-			cdp[chars] = ' ';
-			chars++;
-		}
-		chars = snprintf(&cdp[16], 17, "%s", pmx_settings[i]->dev ?
-				dev_name(pmx_settings[i]->dev) : "N/A");
-		while (chars < 16) {
-			cdp[chars+16] = ' ';
-			chars++;
-		}
-		cdp[32] = '\0';
-
-		seq_printf(s,
-			"%s\t%s\n",
-			&cdp[0],
-			pmx_settings[i]->activated ?
-			"ACTIVATED" : "DEACTIVATED"
-			);
-
-	}
-	mutex_unlock(&pmx_mutex);
-	return 0;
-}
-
-static int pmx_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, pmx_show, NULL);
-}
-
-static const struct file_operations pmx_operations = {
-	.owner		= THIS_MODULE,
-	.open		= pmx_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int __init init_pmx_read_debugfs(void)
-{
-	/* Expose a simple debugfs interface to view pmx settings */
-	(void) debugfs_create_file("padmux", S_IFREG | S_IRUGO,
-				   NULL, NULL,
-				   &pmx_operations);
-	return 0;
-}
-
-/*
- * This needs to come in after the core_initcall(),
- * because debugfs is not available until
- * the subsystems come up.
- */
-module_init(init_pmx_read_debugfs);
-#endif
-
-static int __init pmx_init(void)
-{
-	int ret;
-
-	ret = pmx_set_default();
-
-	if (IS_ERR_VALUE(ret))
-		pr_crit("padmux: default settings could not be set\n");
-
-	return 0;
-}
-
-/* Should be initialized before consumers */
-core_initcall(pmx_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-u300/padmux.h linux-libre-3.2-gnu/arch/arm/mach-u300/padmux.h
--- linux-libre-3.1-gnu/arch/arm/mach-u300/padmux.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-u300/padmux.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,39 +0,0 @@
-/*
- *
- * arch/arm/mach-u300/padmux.h
- *
- *
- * Copyright (C) 2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * U300 PADMUX API
- * Author: Martin Persson <martin.persson@stericsson.com>
- */
-
-#ifndef __MACH_U300_PADMUX_H
-#define __MACH_U300_PADMUX_H
-
-enum pmx_settings {
-	U300_APP_PMX_MMC_SETTING,
-	U300_APP_PMX_SPI_SETTING
-};
-
-struct pmx_onmask {
-	u16 mask;		/* Mask bits */
-	u16 val;		/* Value when active */
-};
-
-struct pmx {
-	struct device *dev;
-	enum pmx_settings setting;
-	char *name;
-	bool activated;
-	bool default_on;
-	struct pmx_onmask onmask[];
-};
-
-struct pmx *pmx_get(struct device *dev, enum pmx_settings setting);
-int pmx_put(struct device *dev, struct pmx *pmx);
-int pmx_activate(struct device *dev, struct pmx *pmx);
-int pmx_deactivate(struct device *dev, struct pmx *pmx);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-u300/spi.c linux-libre-3.2-gnu/arch/arm/mach-u300/spi.c
--- linux-libre-3.1-gnu/arch/arm/mach-u300/spi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-u300/spi.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,8 +14,6 @@
 #include <mach/coh901318.h>
 #include <mach/dma_channels.h>
 
-#include "padmux.h"
-
 /*
  * The following is for the actual devices on the SSP/SPI bus
  */
@@ -95,25 +93,7 @@
 
 void __init u300_spi_init(struct amba_device *adev)
 {
-	struct pmx *pmx;
-
 	adev->dev.platform_data = &ssp_platform_data;
-	/*
-	 * Setup padmuxing for SPI. Since this must always be
-	 * compiled into the kernel, pmx is never released.
-	 */
-	pmx = pmx_get(&adev->dev, U300_APP_PMX_SPI_SETTING);
-
-	if (IS_ERR(pmx))
-		dev_warn(&adev->dev, "Could not get padmux handle\n");
-	else {
-		int ret;
-
-		ret = pmx_activate(&adev->dev, pmx);
-		if (IS_ERR_VALUE(ret))
-			dev_warn(&adev->dev, "Could not activate padmuxing\n");
-	}
-
 }
 
 void __init u300_spi_register_board_devices(void)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-u300/u300.c linux-libre-3.2-gnu/arch/arm/mach-u300/u300.c
--- linux-libre-3.1-gnu/arch/arm/mach-u300/u300.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-u300/u300.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,21 +23,6 @@
 #include <asm/mach/arch.h>
 #include <asm/memory.h>
 
-static void __init u300_reserve(void)
-{
-	/*
-	 * U300 - This platform family can share physical memory
-	 * between two ARM cpus, one running Linux and the other
-	 * running another OS.
-	 */
-#ifdef CONFIG_MACH_U300_SINGLE_RAM
-#if ((CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1) == 1) && \
-	CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
-        memblock_reserve(PHYS_OFFSET, 0x00100000);
-#endif
-#endif
-}
-
 static void __init u300_init_machine(void)
 {
 	u300_init_devices();
@@ -61,9 +46,8 @@
 
 MACHINE_START(U300, MACH_U300_STRING)
 	/* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
-	.boot_params	= BOOT_PARAMS_OFFSET,
+	.atag_offset	= BOOT_PARAMS_OFFSET,
 	.map_io		= u300_map_io,
-	.reserve	= u300_reserve,
 	.init_irq	= u300_init_irq,
 	.timer		= &u300_timer,
 	.init_machine	= u300_init_machine,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/board-mop500.c linux-libre-3.2-gnu/arch/arm/mach-ux500/board-mop500.c
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/board-mop500.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/board-mop500.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <plat/i2c.h>
 #include <plat/ste_dma40.h>
 #include <plat/pincfg.h>
+#include <plat/gpio-nomadik.h>
 
 #include <mach/hardware.h>
 #include <mach/setup.h>
@@ -603,28 +604,72 @@
 {
 	int i2c0_devs;
 
+	mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
+
+	u8500_init_devices();
+
+	mop500_pins_init();
+
+	platform_add_devices(mop500_platform_devs,
+			ARRAY_SIZE(mop500_platform_devs));
+
+	mop500_i2c_init();
+	mop500_sdi_init();
+	mop500_spi_init();
+	mop500_uart_init();
+
+	i2c0_devs = ARRAY_SIZE(mop500_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));
+
+	/* This board has full regulator constraints */
+	regulator_has_full_constraints();
+}
+
+static void __init snowball_init_machine(void)
+{
+	int i2c0_devs;
+
+	u8500_init_devices();
+
+	snowball_pins_init();
+
+	platform_add_devices(snowball_platform_devs,
+			ARRAY_SIZE(snowball_platform_devs));
+
+	mop500_i2c_init();
+	snowball_sdi_init();
+	mop500_spi_init();
+	mop500_uart_init();
+
+	i2c0_devs = ARRAY_SIZE(mop500_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));
+
+	/* This board has full regulator constraints */
+	regulator_has_full_constraints();
+}
+
+static void __init hrefv60_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_snowball()) {
-		if (machine_is_hrefv60())
-			mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
-		else
-			mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
-	}
+	mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
 
 	u8500_init_devices();
 
-	mop500_pins_init();
+	hrefv60_pins_init();
 
-	if (machine_is_snowball())
-		platform_add_devices(snowball_platform_devs,
-					ARRAY_SIZE(snowball_platform_devs));
-	else
-		platform_add_devices(mop500_platform_devs,
-					ARRAY_SIZE(mop500_platform_devs));
+	platform_add_devices(mop500_platform_devs,
+			ARRAY_SIZE(mop500_platform_devs));
 
 	mop500_i2c_init();
 	mop500_sdi_init();
@@ -632,8 +677,8 @@
 	mop500_uart_init();
 
 	i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
-	if (machine_is_hrefv60())
-		i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
+
+	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,
@@ -645,7 +690,7 @@
 
 MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
 	/* Maintainer: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> */
-	.boot_params	= 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
 	/* we re-use nomadik timer here */
@@ -654,18 +699,18 @@
 MACHINE_END
 
 MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
-	.boot_params	= 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
 	.timer		= &ux500_timer,
-	.init_machine	= mop500_init_machine,
+	.init_machine	= hrefv60_init_machine,
 MACHINE_END
 
 MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
-	.boot_params	= 0x100,
+	.atag_offset	= 0x100,
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
 	/* we re-use nomadik timer here */
 	.timer		= &ux500_timer,
-	.init_machine	= mop500_init_machine,
+	.init_machine	= snowball_init_machine,
 MACHINE_END
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/board-mop500.h linux-libre-3.2-gnu/arch/arm/mach-ux500/board-mop500.h
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/board-mop500.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/board-mop500.h	2012-01-04 18:55:44.000000000 -0500
@@ -40,10 +40,13 @@
 struct i2c_board_info;
 
 extern void mop500_sdi_init(void);
+extern void snowball_sdi_init(void);
 extern void mop500_sdi_tc35892_init(void);
 void __init mop500_u8500uib_init(void);
 void __init mop500_stuib_init(void);
 void __init mop500_pins_init(void);
+void __init hrefv60_pins_init(void);
+void __init snowball_pins_init(void);
 
 void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
 		unsigned n);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/board-mop500-pins.c linux-libre-3.2-gnu/arch/arm/mach-ux500/board-mop500-pins.c
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/board-mop500-pins.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/board-mop500-pins.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,10 +6,10 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <plat/pincfg.h>
+#include <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
 
 #include "pins-db8500.h"
@@ -153,7 +153,7 @@
 	GPIO7_U1_RTSn	| PIN_OUTPUT_HIGH,
 };
 
-static pin_cfg_t mop500_pins_hrefv60[] = {
+static pin_cfg_t hrefv60_pins[] = {
 	/* WLAN */
 	GPIO4_GPIO		| PIN_INPUT_PULLUP,/* WLAN_IRQ */
 	GPIO85_GPIO		| PIN_OUTPUT_LOW,/* WLAN_ENA */
@@ -279,14 +279,26 @@
 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 if (machine_is_snowball())
-		nmk_config_pins(snowball_pins,
-				ARRAY_SIZE(snowball_pins));
-	else
-		nmk_config_pins(mop500_pins_default,
-				ARRAY_SIZE(mop500_pins_default));
+			ARRAY_SIZE(mop500_pins_common));
+
+	nmk_config_pins(mop500_pins_default,
+			ARRAY_SIZE(mop500_pins_default));
+}
+
+void __init snowball_pins_init(void)
+{
+	nmk_config_pins(mop500_pins_common,
+			ARRAY_SIZE(mop500_pins_common));
+
+	nmk_config_pins(snowball_pins,
+			ARRAY_SIZE(snowball_pins));
+}
+
+void __init hrefv60_pins_init(void)
+{
+	nmk_config_pins(mop500_pins_common,
+			ARRAY_SIZE(mop500_pins_common));
+
+	nmk_config_pins(hrefv60_pins,
+			ARRAY_SIZE(hrefv60_pins));
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/board-mop500-sdi.c linux-libre-3.2-gnu/arch/arm/mach-ux500/board-mop500-sdi.c
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/board-mop500-sdi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/board-mop500-sdi.c	2012-01-04 18:55:44.000000000 -0500
@@ -216,30 +216,48 @@
 	/* 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;
-	/* sdi2 on snowball is in ATL_B mode for FSMC (LAN) */
-	if (!machine_is_snowball())
-		db8500_add_sdi2(&mop500_sdi2_data, periphid);
+
+	db8500_add_sdi2(&mop500_sdi2_data, periphid);
 
 	/* On-board eMMC */
 	db8500_add_sdi4(&mop500_sdi4_data, periphid);
 
-	if (machine_is_hrefv60() || machine_is_snowball()) {
-		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;
-		} else if (machine_is_snowball()) {
-			mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO;
-			mop500_sdi0_data.cd_invert = true;
-			sdi0_en = SNOWBALL_SDMMC_EN_GPIO;
-			sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO;
-		}
-		sdi0_configure();
-	}
-
 	/*
 	 * On boards with the TC35892 GPIO expander, sdi0 will finally
 	 * be added when the TC35892 initializes and calls
 	 * mop500_sdi_tc35892_init() above.
 	 */
 }
+
+void __init snowball_sdi_init(void)
+{
+	u32 periphid = 0x10480180;
+
+	mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
+
+	/* On-board eMMC */
+	db8500_add_sdi4(&mop500_sdi4_data, periphid);
+
+	mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO;
+	mop500_sdi0_data.cd_invert = true;
+	sdi0_en = SNOWBALL_SDMMC_EN_GPIO;
+	sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO;
+	sdi0_configure();
+}
+
+void __init hrefv60_sdi_init(void)
+{
+	u32 periphid = 0x10480180;
+
+	mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
+
+	db8500_add_sdi2(&mop500_sdi2_data, periphid);
+
+	/* On-board eMMC */
+	db8500_add_sdi4(&mop500_sdi4_data, periphid);
+
+	mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
+	sdi0_en = HREFV60_SDMMC_EN_GPIO;
+	sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
+	sdi0_configure();
+}
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/board-mop500-u8500uib.c linux-libre-3.2-gnu/arch/arm/mach-ux500/board-mop500-u8500uib.c
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/board-mop500-u8500uib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/board-mop500-u8500uib.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
  * Board data for the U8500 UIB, also known as the New UIB
  * License terms: GNU General Public License (GPL), version 2
  */
-
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
@@ -13,7 +13,6 @@
 #include <linux/mfd/tc3589x.h>
 #include <linux/input/matrix_keypad.h>
 
-#include <mach/gpio.h>
 #include <mach/irqs.h>
 
 #include "board-mop500.h"
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/board-u5500.c linux-libre-3.2-gnu/arch/arm/mach-ux500/board-u5500.c
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/board-u5500.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/board-u5500.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,15 +8,16 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/amba/bus.h>
-#include <linux/gpio.h>
 #include <linux/irq.h>
 #include <linux/i2c.h>
+#include <linux/mfd/ab5500/ab5500.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
 #include <plat/pincfg.h>
 #include <plat/i2c.h>
+#include <plat/gpio-nomadik.h>
 
 #include <mach/hardware.h>
 #include <mach/devices.h>
@@ -87,7 +88,6 @@
 	.brt_val = 0x7F,	/* Max brightness */
 };
 
-
 static struct i2c_board_info __initdata u5500_i2c2_devices[] = {
 	{
 		/* Backlight */
@@ -101,6 +101,30 @@
 	db5500_add_i2c2(&u5500_i2c2_data);
 	i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices));
 }
+
+static struct ab5500_platform_data ab5500_plf_data = {
+	.irq = {
+		.base = 0,
+		.count = 0,
+	},
+	.init_settings = NULL,
+	.init_settings_sz = 0,
+	.pm_power_off = false,
+};
+
+static struct platform_device ab5500_device = {
+	.name = "ab5500-core",
+	.id = 0,
+	.dev = {
+		.platform_data = &ab5500_plf_data,
+	},
+	.num_resources = 0,
+};
+
+static struct platform_device *u5500_platform_devices[] __initdata = {
+	&ab5500_device,
+};
+
 static void __init u5500_uart_init(void)
 {
 	db5500_add_uart0(NULL);
@@ -115,10 +139,13 @@
 	u5500_i2c_init();
 	u5500_sdi_init();
 	u5500_uart_init();
+
+	platform_add_devices(u5500_platform_devices,
+		ARRAY_SIZE(u5500_platform_devices));
 }
 
 MACHINE_START(U5500, "ST-Ericsson U5500 Platform")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= u5500_map_io,
 	.init_irq	= ux500_init_irq,
 	.timer		= &ux500_timer,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/board-u5500-sdi.c linux-libre-3.2-gnu/arch/arm/mach-ux500/board-u5500-sdi.c
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/board-u5500-sdi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/board-u5500-sdi.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,9 +7,9 @@
 
 #include <linux/amba/mmci.h>
 #include <linux/mmc/host.h>
-#include <linux/gpio.h>
 
 #include <plat/pincfg.h>
+#include <plat/gpio-nomadik.h>
 #include <mach/db5500-regs.h>
 #include <plat/ste_dma40.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/cache-l2x0.c linux-libre-3.2-gnu/arch/arm/mach-ux500/cache-l2x0.c
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/cache-l2x0.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/cache-l2x0.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/io.h>
+#include <asm/cacheflush.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <mach/hardware.h>
+#include <mach/id.h>
+
+static void __iomem *l2x0_base;
+
+static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
+{
+	/* wait for the operation to complete */
+	while (readl_relaxed(reg) & mask)
+		cpu_relax();
+}
+
+static inline void ux500_cache_sync(void)
+{
+	writel_relaxed(0, l2x0_base + L2X0_CACHE_SYNC);
+	ux500_cache_wait(l2x0_base + L2X0_CACHE_SYNC, 1);
+}
+
+/*
+ * The L2 cache cannot be turned off in the non-secure world.
+ * Dummy until a secure service is in place.
+ */
+static void ux500_l2x0_disable(void)
+{
+}
+
+/*
+ * This is only called when doing a kexec, just after turning off the L2
+ * and L1 cache, and it is surrounded by a spinlock in the generic version.
+ * However, we're not really turning off the L2 cache right now and the
+ * PL310 does not support exclusive accesses (used to implement the spinlock).
+ * So, the invalidation needs to be done without the spinlock.
+ */
+static void ux500_l2x0_inv_all(void)
+{
+	uint32_t l2x0_way_mask = (1<<16) - 1;	/* Bitmask of active ways */
+
+	/* invalidate all ways */
+	writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
+	ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
+	ux500_cache_sync();
+}
+
+static int __init ux500_l2x0_unlock(void)
+{
+	int i;
+
+	/*
+	 * Unlock Data and Instruction Lock if locked. Ux500 U-Boot versions
+	 * apparently locks both caches before jumping to the kernel. The
+	 * l2x0 core will not touch the unlock registers if the l2x0 is
+	 * already enabled, so we do it right here instead. The PL310 has
+	 * 8 sets of registers, one per possible CPU.
+	 */
+	for (i = 0; i < 8; i++) {
+		writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
+			       i * L2X0_LOCKDOWN_STRIDE);
+		writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE +
+			       i * L2X0_LOCKDOWN_STRIDE);
+	}
+	return 0;
+}
+
+static int __init ux500_l2x0_init(void)
+{
+	if (cpu_is_u5500())
+		l2x0_base = __io_address(U5500_L2CC_BASE);
+	else if (cpu_is_u8500())
+		l2x0_base = __io_address(U8500_L2CC_BASE);
+	else
+		ux500_unknown_soc();
+
+	/* Unlock before init */
+	ux500_l2x0_unlock();
+
+	/* 64KB way size, 8 way associativity, force WA */
+	l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
+
+	/* Override invalidate function */
+	outer_cache.disable = ux500_l2x0_disable;
+	outer_cache.inv_all = ux500_l2x0_inv_all;
+
+	return 0;
+}
+
+early_initcall(ux500_l2x0_init);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/cpu.c linux-libre-3.2-gnu/arch/arm/mach-ux500/cpu.c
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,14 +10,12 @@
 #include <linux/clk.h>
 #include <linux/mfd/db8500-prcmu.h>
 #include <linux/mfd/db5500-prcmu.h>
+#include <linux/clksrc-dbx500-prcmu.h>
 
-#include <asm/cacheflush.h>
-#include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/map.h>
 #include <asm/localtimer.h>
 
-#include <plat/mtu.h>
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
@@ -26,10 +24,6 @@
 
 void __iomem *_PRCMU_BASE;
 
-#ifdef CONFIG_CACHE_L2X0
-static void __iomem *l2x0_base;
-#endif
-
 void __init ux500_init_irq(void)
 {
 	void __iomem *dist_base;
@@ -53,96 +47,6 @@
 	if (cpu_is_u5500())
 		db5500_prcmu_early_init();
 	if (cpu_is_u8500())
-		prcmu_early_init();
+		db8500_prcmu_early_init();
 	clk_init();
 }
-
-#ifdef CONFIG_CACHE_L2X0
-static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
-{
-	/* wait for the operation to complete */
-	while (readl_relaxed(reg) & mask)
-		;
-}
-
-static inline void ux500_cache_sync(void)
-{
-	void __iomem *base = l2x0_base;
-
-	writel_relaxed(0, base + L2X0_CACHE_SYNC);
-	ux500_cache_wait(base + L2X0_CACHE_SYNC, 1);
-}
-
-/*
- * The L2 cache cannot be turned off in the non-secure world.
- * Dummy until a secure service is in place.
- */
-static void ux500_l2x0_disable(void)
-{
-}
-
-/*
- * This is only called when doing a kexec, just after turning off the L2
- * and L1 cache, and it is surrounded by a spinlock in the generic version.
- * However, we're not really turning off the L2 cache right now and the
- * PL310 does not support exclusive accesses (used to implement the spinlock).
- * So, the invalidation needs to be done without the spinlock.
- */
-static void ux500_l2x0_inv_all(void)
-{
-	void __iomem *base = l2x0_base;
-	uint32_t l2x0_way_mask = (1<<16) - 1;	/* Bitmask of active ways */
-
-	/* invalidate all ways */
-	writel_relaxed(l2x0_way_mask, base + L2X0_INV_WAY);
-	ux500_cache_wait(base + L2X0_INV_WAY, l2x0_way_mask);
-	ux500_cache_sync();
-}
-
-static int ux500_l2x0_init(void)
-{
-	if (cpu_is_u5500())
-		l2x0_base = __io_address(U5500_L2CC_BASE);
-	else if (cpu_is_u8500())
-		l2x0_base = __io_address(U8500_L2CC_BASE);
-	else
-		ux500_unknown_soc();
-
-	/* 64KB way size, 8 way associativity, force WA */
-	l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
-
-	/* Override invalidate function */
-	outer_cache.disable = ux500_l2x0_disable;
-	outer_cache.inv_all = ux500_l2x0_inv_all;
-
-	return 0;
-}
-early_initcall(ux500_l2x0_init);
-#endif
-
-static void __init ux500_timer_init(void)
-{
-#ifdef CONFIG_LOCAL_TIMERS
-	/* Setup the local timer base */
-	if (cpu_is_u5500())
-		twd_base = __io_address(U5500_TWD_BASE);
-	else if (cpu_is_u8500())
-		twd_base = __io_address(U8500_TWD_BASE);
-	else
-		ux500_unknown_soc();
-#endif
-	if (cpu_is_u5500())
-		mtu_base = __io_address(U5500_MTU0_BASE);
-	else if (cpu_is_u8500ed())
-		mtu_base = __io_address(U8500_MTU0_BASE_ED);
-	else if (cpu_is_u8500())
-		mtu_base = __io_address(U8500_MTU0_BASE);
-	else
-		ux500_unknown_soc();
-
-	nmdk_timer_init();
-}
-
-struct sys_timer ux500_timer = {
-	.init	= ux500_timer_init,
-};
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/cpu-db5500.c linux-libre-3.2-gnu/arch/arm/mach-ux500/cpu-db5500.c
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/cpu-db5500.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/cpu-db5500.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
 #include <asm/mach/map.h>
 #include <asm/pmu.h>
 
-#include <plat/gpio.h>
+#include <plat/gpio-nomadik.h>
 
 #include <mach/hardware.h>
 #include <mach/devices.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/cpu-db8500.c linux-libre-3.2-gnu/arch/arm/mach-ux500/cpu-db8500.c
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/cpu-db8500.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/cpu-db8500.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,12 +14,12 @@
 #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 <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/devices-common.c linux-libre-3.2-gnu/arch/arm/mach-ux500/devices-common.c
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/devices-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/devices-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/amba/bus.h>
 
-#include <plat/gpio.h>
+#include <plat/gpio-nomadik.h>
 
 #include <mach/hardware.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/hotplug.c linux-libre-3.2-gnu/arch/arm/mach-ux500/hotplug.c
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/hotplug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/hotplug.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,7 @@
 	for (;;) {
 		__asm__ __volatile__("dsb\n\t" "wfi\n\t"
 				: : : "memory");
-		if (pen_release == cpu) {
+		if (pen_release == cpu_logical_map(cpu)) {
 			/*
 			 * OK, proper wakeup, we're done
 			 */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/include/mach/db5500-regs.h linux-libre-3.2-gnu/arch/arm/mach-ux500/include/mach/db5500-regs.h
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/include/mach/db5500-regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/include/mach/db5500-regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -61,6 +61,8 @@
 #define U5500_SCR_BASE		(U5500_PER4_BASE + 0x5000)
 #define U5500_DMC_BASE		(U5500_PER4_BASE + 0x6000)
 #define U5500_PRCMU_BASE	(U5500_PER4_BASE + 0x7000)
+#define U5500_PRCMU_TIMER_3_BASE (U5500_PER4_BASE + 0x07338)
+#define U5500_PRCMU_TIMER_4_BASE (U5500_PER4_BASE + 0x07450)
 #define U5500_MSP1_BASE		(U5500_PER4_BASE + 0x9000)
 #define U5500_GPIO2_BASE	(U5500_PER4_BASE + 0xA000)
 #define U5500_CDETECT_BASE	(U5500_PER4_BASE + 0xF000)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/include/mach/db8500-regs.h linux-libre-3.2-gnu/arch/arm/mach-ux500/include/mach/db8500-regs.h
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/include/mach/db8500-regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/include/mach/db8500-regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -102,10 +102,13 @@
 #define U8500_SCR_BASE		(U8500_PER4_BASE + 0x05000)
 #define U8500_DMC_BASE		(U8500_PER4_BASE + 0x06000)
 #define U8500_PRCMU_BASE	(U8500_PER4_BASE + 0x07000)
+#define U8500_PRCMU_TIMER_3_BASE (U8500_PER4_BASE + 0x07338)
+#define U8500_PRCMU_TIMER_4_BASE (U8500_PER4_BASE + 0x07450)
 #define U8500_PRCMU_TCDM_BASE_V1 (U8500_PER4_BASE + 0x0f000)
 #define U8500_PRCMU_TCDM_BASE	(U8500_PER4_BASE + 0x68000)
 #define U8500_PRCMU_TCPM_BASE   (U8500_PER4_BASE + 0x60000)
 
+
 /* per3 base addresses */
 #define U8500_FSMC_BASE		(U8500_PER3_BASE + 0x0000)
 #define U8500_SSP0_BASE		(U8500_PER3_BASE + 0x2000)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-ux500/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -35,7 +35,7 @@
 #define UX500_UART(n)	__UX500_UART(n)
 #define UART_BASE	UX500_UART(CONFIG_UX500_DEBUG_UART)
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	ldr	\rp, =UART_BASE				@ no, physical address
 	ldr	\rv, =IO_ADDRESS(UART_BASE)		@ yes, virtual address
 	.endm
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-ux500/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,4 @@
  */
 #define ARCH_NR_GPIOS	350
 
-#include <plat/gpio.h>
-
 #endif /* __ASM_ARCH_GPIO_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-ux500/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2009 ST-Ericsson
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-#define BUS_OFFSET	UL(0x00000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/include/mach/uncompress.h linux-libre-3.2-gnu/arch/arm/mach-ux500/include/mach/uncompress.h
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/include/mach/uncompress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/include/mach/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -51,15 +51,9 @@
 static inline void arch_decomp_setup(void)
 {
 	/* 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()   ||
-	    machine_is_snowball())
-		ux500_uart_base = U8500_UART2_BASE;
-	else if (machine_is_u5500())
+	if (machine_is_u5500())
 		ux500_uart_base = U5500_UART0_BASE;
-	else /* not much can be done to help here */
+	else
 		ux500_uart_base = U8500_UART2_BASE;
 }
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/Makefile linux-libre-3.2-gnu/arch/arm/mach-ux500/Makefile
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,8 @@
 #
 
 obj-y				:= clock.o cpu.o devices.o devices-common.o \
-				   id.o usb.o
+				   id.o usb.o timer.o
+obj-$(CONFIG_CACHE_L2X0)	+= cache-l2x0.o
 obj-$(CONFIG_UX500_SOC_DB5500)	+= cpu-db5500.o dma-db5500.o
 obj-$(CONFIG_UX500_SOC_DB8500)	+= cpu-db8500.o devices-db8500.o
 obj-$(CONFIG_MACH_U8500)	+= board-mop500.o board-mop500-sdi.o \
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-ux500/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/pins-db8500.h linux-libre-3.2-gnu/arch/arm/mach-ux500/pins-db8500.h
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/pins-db8500.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/pins-db8500.h	2012-01-04 18:55:44.000000000 -0500
@@ -35,40 +35,40 @@
 
 #define GPIO4_GPIO		PIN_CFG(4, GPIO)
 #define GPIO4_U1_RXD		PIN_CFG(4, ALT_A)
-#define GPIO4_I2C4_SCL		PIN_CFG_PULL(4, ALT_B, UP)
+#define GPIO4_I2C4_SCL		PIN_CFG_INPUT(4, ALT_B, PULLUP)
 #define GPIO4_IP_TRSTn		PIN_CFG(4, ALT_C)
 
 #define GPIO5_GPIO		PIN_CFG(5, GPIO)
 #define GPIO5_U1_TXD		PIN_CFG(5, ALT_A)
-#define GPIO5_I2C4_SDA		PIN_CFG_PULL(5, ALT_B, UP)
+#define GPIO5_I2C4_SDA		PIN_CFG_INPUT(5, ALT_B, PULLUP)
 #define GPIO5_IP_GPIO6		PIN_CFG(5, ALT_C)
 
 #define GPIO6_GPIO		PIN_CFG(6, GPIO)
 #define GPIO6_U1_CTSn		PIN_CFG(6, ALT_A)
-#define GPIO6_I2C1_SCL		PIN_CFG_PULL(6, ALT_B, UP)
+#define GPIO6_I2C1_SCL		PIN_CFG_INPUT(6, ALT_B, PULLUP)
 #define GPIO6_IP_GPIO0		PIN_CFG(6, ALT_C)
 
 #define GPIO7_GPIO		PIN_CFG(7, GPIO)
 #define GPIO7_U1_RTSn		PIN_CFG(7, ALT_A)
-#define GPIO7_I2C1_SDA		PIN_CFG_PULL(7, ALT_B, UP)
+#define GPIO7_I2C1_SDA		PIN_CFG_INPUT(7, ALT_B, PULLUP)
 #define GPIO7_IP_GPIO1		PIN_CFG(7, ALT_C)
 
 #define GPIO8_GPIO		PIN_CFG(8, GPIO)
-#define GPIO8_IPI2C_SDA		PIN_CFG_PULL(8, ALT_A, UP)
-#define GPIO8_I2C2_SDA		PIN_CFG_PULL(8, ALT_B, UP)
+#define GPIO8_IPI2C_SDA		PIN_CFG_INPUT(8, ALT_A, PULLUP)
+#define GPIO8_I2C2_SDA		PIN_CFG_INPUT(8, ALT_B, PULLUP)
 
 #define GPIO9_GPIO		PIN_CFG(9, GPIO)
-#define GPIO9_IPI2C_SCL		PIN_CFG_PULL(9, ALT_A, UP)
-#define GPIO9_I2C2_SCL		PIN_CFG_PULL(9, ALT_B, UP)
+#define GPIO9_IPI2C_SCL		PIN_CFG_INPUT(9, ALT_A, PULLUP)
+#define GPIO9_I2C2_SCL		PIN_CFG_INPUT(9, ALT_B, PULLUP)
 
 #define GPIO10_GPIO		PIN_CFG(10, GPIO)
-#define GPIO10_IPI2C_SDA	PIN_CFG_PULL(10, ALT_A, UP)
-#define GPIO10_I2C2_SDA		PIN_CFG_PULL(10, ALT_B, UP)
+#define GPIO10_IPI2C_SDA	PIN_CFG_INPUT(10, ALT_A, PULLUP)
+#define GPIO10_I2C2_SDA		PIN_CFG_INPUT(10, ALT_B, PULLUP)
 #define GPIO10_IP_GPIO3		PIN_CFG(10, ALT_C)
 
 #define GPIO11_GPIO		PIN_CFG(11, GPIO)
-#define GPIO11_IPI2C_SCL	PIN_CFG_PULL(11, ALT_A, UP)
-#define GPIO11_I2C2_SCL		PIN_CFG_PULL(11, ALT_B, UP)
+#define GPIO11_IPI2C_SCL	PIN_CFG_INPUT(11, ALT_A, PULLUP)
+#define GPIO11_I2C2_SCL		PIN_CFG_INPUT(11, ALT_B, PULLUP)
 #define GPIO11_IP_GPIO2		PIN_CFG(11, ALT_C)
 
 #define GPIO12_GPIO		PIN_CFG(12, GPIO)
@@ -87,66 +87,66 @@
 
 #define GPIO16_GPIO		PIN_CFG(16, GPIO)
 #define GPIO16_MSP0_RFS		PIN_CFG(16, ALT_A)
-#define GPIO16_I2C1_SCL		PIN_CFG_PULL(16, ALT_B, UP)
+#define GPIO16_I2C1_SCL		PIN_CFG_INPUT(16, ALT_B, PULLUP)
 #define GPIO16_SLIM0_DAT	PIN_CFG(16, ALT_C)
 
 #define GPIO17_GPIO		PIN_CFG(17, GPIO)
 #define GPIO17_MSP0_RCK		PIN_CFG(17, ALT_A)
-#define GPIO17_I2C1_SDA		PIN_CFG_PULL(17, ALT_B, UP)
+#define GPIO17_I2C1_SDA		PIN_CFG_INPUT(17, ALT_B, PULLUP)
 #define GPIO17_SLIM0_CLK	PIN_CFG(17, ALT_C)
 
 #define GPIO18_GPIO		PIN_CFG(18, GPIO)
-#define GPIO18_MC0_CMDDIR	PIN_CFG_PULL(18, ALT_A, UP)
+#define GPIO18_MC0_CMDDIR	PIN_CFG_INPUT(18, ALT_A, PULLUP)
 #define GPIO18_U2_RXD		PIN_CFG(18, ALT_B)
 #define GPIO18_MS_IEP		PIN_CFG(18, ALT_C)
 
 #define GPIO19_GPIO		PIN_CFG(19, GPIO)
-#define GPIO19_MC0_DAT0DIR	PIN_CFG_PULL(19, ALT_A, UP)
+#define GPIO19_MC0_DAT0DIR	PIN_CFG_INPUT(19, ALT_A, PULLUP)
 #define GPIO19_U2_TXD		PIN_CFG(19, ALT_B)
 #define GPIO19_MS_DAT0DIR	PIN_CFG(19, ALT_C)
 
 #define GPIO20_GPIO		PIN_CFG(20, GPIO)
-#define GPIO20_MC0_DAT2DIR	PIN_CFG_PULL(20, ALT_A, UP)
+#define GPIO20_MC0_DAT2DIR	PIN_CFG_INPUT(20, ALT_A, PULLUP)
 #define GPIO20_UARTMOD_TXD	PIN_CFG(20, ALT_B)
 #define GPIO20_IP_TRIGOUT	PIN_CFG(20, ALT_C)
 
 #define GPIO21_GPIO		PIN_CFG(21, GPIO)
-#define GPIO21_MC0_DAT31DIR	PIN_CFG_PULL(21, ALT_A, UP)
+#define GPIO21_MC0_DAT31DIR	PIN_CFG_INPUT(21, ALT_A, PULLUP)
 #define GPIO21_MSP0_SCK		PIN_CFG(21, ALT_B)
 #define GPIO21_MS_DAT31DIR	PIN_CFG(21, ALT_C)
 
 #define GPIO22_GPIO		PIN_CFG(22, GPIO)
-#define GPIO22_MC0_FBCLK	PIN_CFG_PULL(22, ALT_A, UP)
+#define GPIO22_MC0_FBCLK	PIN_CFG_INPUT(22, ALT_A, PULLUP)
 #define GPIO22_UARTMOD_RXD	PIN_CFG(22, ALT_B)
 #define GPIO22_MS_FBCLK		PIN_CFG(22, ALT_C)
 
 #define GPIO23_GPIO		PIN_CFG(23, GPIO)
-#define GPIO23_MC0_CLK		PIN_CFG_PULL(23, ALT_A, UP)
+#define GPIO23_MC0_CLK		PIN_CFG_INPUT(23, ALT_A, PULLUP)
 #define GPIO23_STMMOD_CLK	PIN_CFG(23, ALT_B)
 #define GPIO23_MS_CLK		PIN_CFG(23, ALT_C)
 
 #define GPIO24_GPIO		PIN_CFG(24, GPIO)
-#define GPIO24_MC0_CMD		PIN_CFG_PULL(24, ALT_A, UP)
+#define GPIO24_MC0_CMD		PIN_CFG_INPUT(24, ALT_A, PULLUP)
 #define GPIO24_UARTMOD_RXD	PIN_CFG(24, ALT_B)
 #define GPIO24_MS_BS		PIN_CFG(24, ALT_C)
 
 #define GPIO25_GPIO		PIN_CFG(25, GPIO)
-#define GPIO25_MC0_DAT0		PIN_CFG_PULL(25, ALT_A, UP)
+#define GPIO25_MC0_DAT0		PIN_CFG_INPUT(25, ALT_A, PULLUP)
 #define GPIO25_STMMOD_DAT0	PIN_CFG(25, ALT_B)
 #define GPIO25_MS_DAT0		PIN_CFG(25, ALT_C)
 
 #define GPIO26_GPIO		PIN_CFG(26, GPIO)
-#define GPIO26_MC0_DAT1		PIN_CFG_PULL(26, ALT_A, UP)
+#define GPIO26_MC0_DAT1		PIN_CFG_INPUT(26, ALT_A, PULLUP)
 #define GPIO26_STMMOD_DAT1	PIN_CFG(26, ALT_B)
 #define GPIO26_MS_DAT1		PIN_CFG(26, ALT_C)
 
 #define GPIO27_GPIO		PIN_CFG(27, GPIO)
-#define GPIO27_MC0_DAT2		PIN_CFG_PULL(27, ALT_A, UP)
+#define GPIO27_MC0_DAT2		PIN_CFG_INPUT(27, ALT_A, PULLUP)
 #define GPIO27_STMMOD_DAT2	PIN_CFG(27, ALT_B)
 #define GPIO27_MS_DAT2		PIN_CFG(27, ALT_C)
 
 #define GPIO28_GPIO		PIN_CFG(28, GPIO)
-#define GPIO28_MC0_DAT3		PIN_CFG_PULL(28, ALT_A, UP)
+#define GPIO28_MC0_DAT3		PIN_CFG_INPUT(28, ALT_A, PULLUP)
 #define GPIO28_STMMOD_DAT3	PIN_CFG(28, ALT_B)
 #define GPIO28_MS_DAT3		PIN_CFG(28, ALT_C)
 
@@ -357,48 +357,48 @@
 #define GPIO97_MC5_DAT7		PIN_CFG(97, ALT_C)
 
 #define GPIO128_GPIO		PIN_CFG(128, GPIO)
-#define GPIO128_MC2_CLK		PIN_CFG_PULL(128, ALT_A, UP)
+#define GPIO128_MC2_CLK		PIN_CFG_INPUT(128, ALT_A, PULLUP)
 #define GPIO128_SM_CKO		PIN_CFG(128, ALT_B)
 
 #define GPIO129_GPIO		PIN_CFG(129, GPIO)
-#define GPIO129_MC2_CMD		PIN_CFG_PULL(129, ALT_A, UP)
+#define GPIO129_MC2_CMD		PIN_CFG_INPUT(129, ALT_A, PULLUP)
 #define GPIO129_SM_WAIT0n	PIN_CFG(129, ALT_B)
 
 #define GPIO130_GPIO		PIN_CFG(130, GPIO)
-#define GPIO130_MC2_FBCLK	PIN_CFG_PULL(130, ALT_A, UP)
+#define GPIO130_MC2_FBCLK	PIN_CFG_INPUT(130, ALT_A, PULLUP)
 #define GPIO130_SM_FBCLK	PIN_CFG(130, ALT_B)
 #define GPIO130_MC2_RSTN	PIN_CFG(130, ALT_C)
 
 #define GPIO131_GPIO		PIN_CFG(131, GPIO)
-#define GPIO131_MC2_DAT0	PIN_CFG_PULL(131, ALT_A, UP)
+#define GPIO131_MC2_DAT0	PIN_CFG_INPUT(131, ALT_A, PULLUP)
 #define GPIO131_SM_ADQ8		PIN_CFG(131, ALT_B)
 
 #define GPIO132_GPIO		PIN_CFG(132, GPIO)
-#define GPIO132_MC2_DAT1	PIN_CFG_PULL(132, ALT_A, UP)
+#define GPIO132_MC2_DAT1	PIN_CFG_INPUT(132, ALT_A, PULLUP)
 #define GPIO132_SM_ADQ9		PIN_CFG(132, ALT_B)
 
 #define GPIO133_GPIO		PIN_CFG(133, GPIO)
-#define GPIO133_MC2_DAT2	PIN_CFG_PULL(133, ALT_A, UP)
+#define GPIO133_MC2_DAT2	PIN_CFG_INPUT(133, ALT_A, PULLUP)
 #define GPIO133_SM_ADQ10	PIN_CFG(133, ALT_B)
 
 #define GPIO134_GPIO		PIN_CFG(134, GPIO)
-#define GPIO134_MC2_DAT3	PIN_CFG_PULL(134, ALT_A, UP)
+#define GPIO134_MC2_DAT3	PIN_CFG_INPUT(134, ALT_A, PULLUP)
 #define GPIO134_SM_ADQ11	PIN_CFG(134, ALT_B)
 
 #define GPIO135_GPIO		PIN_CFG(135, GPIO)
-#define GPIO135_MC2_DAT4	PIN_CFG_PULL(135, ALT_A, UP)
+#define GPIO135_MC2_DAT4	PIN_CFG_INPUT(135, ALT_A, PULLUP)
 #define GPIO135_SM_ADQ12	PIN_CFG(135, ALT_B)
 
 #define GPIO136_GPIO		PIN_CFG(136, GPIO)
-#define GPIO136_MC2_DAT5	PIN_CFG_PULL(136, ALT_A, UP)
+#define GPIO136_MC2_DAT5	PIN_CFG_INPUT(136, ALT_A, PULLUP)
 #define GPIO136_SM_ADQ13	PIN_CFG(136, ALT_B)
 
 #define GPIO137_GPIO		PIN_CFG(137, GPIO)
-#define GPIO137_MC2_DAT6	PIN_CFG_PULL(137, ALT_A, UP)
+#define GPIO137_MC2_DAT6	PIN_CFG_INPUT(137, ALT_A, PULLUP)
 #define GPIO137_SM_ADQ14	PIN_CFG(137, ALT_B)
 
 #define GPIO138_GPIO		PIN_CFG(138, GPIO)
-#define GPIO138_MC2_DAT7	PIN_CFG_PULL(138, ALT_A, UP)
+#define GPIO138_MC2_DAT7	PIN_CFG_INPUT(138, ALT_A, PULLUP)
 #define GPIO138_SM_ADQ15	PIN_CFG(138, ALT_B)
 
 #define GPIO139_GPIO		PIN_CFG(139, GPIO)
@@ -434,10 +434,10 @@
 #define GPIO146_SSP0_TXD	PIN_CFG(146, ALT_A)
 
 #define GPIO147_GPIO		PIN_CFG(147, GPIO)
-#define GPIO147_I2C0_SCL	PIN_CFG_PULL(147, ALT_A, UP)
+#define GPIO147_I2C0_SCL	PIN_CFG_INPUT(147, ALT_A, PULLUP)
 
 #define GPIO148_GPIO		PIN_CFG(148, GPIO)
-#define GPIO148_I2C0_SDA	PIN_CFG_PULL(148, ALT_A, UP)
+#define GPIO148_I2C0_SDA	PIN_CFG_INPUT(148, ALT_A, PULLUP)
 
 #define GPIO149_GPIO		PIN_CFG(149, GPIO)
 #define GPIO149_IP_GPIO0	PIN_CFG(149, ALT_A)
@@ -459,82 +459,82 @@
 #define GPIO152_KP_O9		PIN_CFG(152, ALT_C)
 
 #define GPIO153_GPIO		PIN_CFG(153, GPIO)
-#define GPIO153_KP_I7		PIN_CFG_PULL(153, ALT_A, DOWN)
+#define GPIO153_KP_I7		PIN_CFG_INPUT(153, ALT_A, PULLDOWN)
 #define GPIO153_LCD_D24		PIN_CFG(153, ALT_B)
 #define GPIO153_U2_RXD		PIN_CFG(153, ALT_C)
 
 #define GPIO154_GPIO		PIN_CFG(154, GPIO)
-#define GPIO154_KP_I6		PIN_CFG_PULL(154, ALT_A, DOWN)
+#define GPIO154_KP_I6		PIN_CFG_INPUT(154, ALT_A, PULLDOWN)
 #define GPIO154_LCD_D25		PIN_CFG(154, ALT_B)
 #define GPIO154_U2_TXD		PIN_CFG(154, ALT_C)
 
 #define GPIO155_GPIO		PIN_CFG(155, GPIO)
-#define GPIO155_KP_I5		PIN_CFG_PULL(155, ALT_A, DOWN)
+#define GPIO155_KP_I5		PIN_CFG_INPUT(155, ALT_A, PULLDOWN)
 #define GPIO155_LCD_D26		PIN_CFG(155, ALT_B)
 #define GPIO155_STMAPE_CLK	PIN_CFG(155, ALT_C)
 
 #define GPIO156_GPIO		PIN_CFG(156, GPIO)
-#define GPIO156_KP_I4		PIN_CFG_PULL(156, ALT_A, DOWN)
+#define GPIO156_KP_I4		PIN_CFG_INPUT(156, ALT_A, PULLDOWN)
 #define GPIO156_LCD_D27		PIN_CFG(156, ALT_B)
 #define GPIO156_STMAPE_DAT3	PIN_CFG(156, ALT_C)
 
 #define GPIO157_GPIO		PIN_CFG(157, GPIO)
-#define GPIO157_KP_O7		PIN_CFG_PULL(157, ALT_A, UP)
+#define GPIO157_KP_O7		PIN_CFG_INPUT(157, ALT_A, PULLUP)
 #define GPIO157_LCD_D28		PIN_CFG(157, ALT_B)
 #define GPIO157_STMAPE_DAT2	PIN_CFG(157, ALT_C)
 
 #define GPIO158_GPIO		PIN_CFG(158, GPIO)
-#define GPIO158_KP_O6		PIN_CFG_PULL(158, ALT_A, UP)
+#define GPIO158_KP_O6		PIN_CFG_INPUT(158, ALT_A, PULLUP)
 #define GPIO158_LCD_D29		PIN_CFG(158, ALT_B)
 #define GPIO158_STMAPE_DAT1	PIN_CFG(158, ALT_C)
 
 #define GPIO159_GPIO		PIN_CFG(159, GPIO)
-#define GPIO159_KP_O5		PIN_CFG_PULL(159, ALT_A, UP)
+#define GPIO159_KP_O5		PIN_CFG_INPUT(159, ALT_A, PULLUP)
 #define GPIO159_LCD_D30		PIN_CFG(159, ALT_B)
 #define GPIO159_STMAPE_DAT0	PIN_CFG(159, ALT_C)
 
 #define GPIO160_GPIO		PIN_CFG(160, GPIO)
-#define GPIO160_KP_O4		PIN_CFG_PULL(160, ALT_A, UP)
+#define GPIO160_KP_O4		PIN_CFG_INPUT(160, ALT_A, PULLUP)
 #define GPIO160_LCD_D31		PIN_CFG(160, ALT_B)
 #define GPIO160_NONE		PIN_CFG(160, ALT_C)
 
 #define GPIO161_GPIO		PIN_CFG(161, GPIO)
-#define GPIO161_KP_I3		PIN_CFG_PULL(161, ALT_A, DOWN)
+#define GPIO161_KP_I3		PIN_CFG_INPUT(161, ALT_A, PULLDOWN)
 #define GPIO161_LCD_D32		PIN_CFG(161, ALT_B)
 #define GPIO161_UARTMOD_RXD	PIN_CFG(161, ALT_C)
 
 #define GPIO162_GPIO		PIN_CFG(162, GPIO)
-#define GPIO162_KP_I2		PIN_CFG_PULL(162, ALT_A, DOWN)
+#define GPIO162_KP_I2		PIN_CFG_INPUT(162, ALT_A, PULLDOWN)
 #define GPIO162_LCD_D33		PIN_CFG(162, ALT_B)
 #define GPIO162_UARTMOD_TXD	PIN_CFG(162, ALT_C)
 
 #define GPIO163_GPIO		PIN_CFG(163, GPIO)
-#define GPIO163_KP_I1		PIN_CFG_PULL(163, ALT_A, DOWN)
+#define GPIO163_KP_I1		PIN_CFG_INPUT(163, ALT_A, PULLDOWN)
 #define GPIO163_LCD_D34		PIN_CFG(163, ALT_B)
 #define GPIO163_STMMOD_CLK	PIN_CFG(163, ALT_C)
 
 #define GPIO164_GPIO		PIN_CFG(164, GPIO)
-#define GPIO164_KP_I0		PIN_CFG_PULL(164, ALT_A, UP)
+#define GPIO164_KP_I0		PIN_CFG_INPUT(164, ALT_A, PULLUP)
 #define GPIO164_LCD_D35		PIN_CFG(164, ALT_B)
 #define GPIO164_STMMOD_DAT3	PIN_CFG(164, ALT_C)
 
 #define GPIO165_GPIO		PIN_CFG(165, GPIO)
-#define GPIO165_KP_O3		PIN_CFG_PULL(165, ALT_A, UP)
+#define GPIO165_KP_O3		PIN_CFG_INPUT(165, ALT_A, PULLUP)
 #define GPIO165_LCD_D36		PIN_CFG(165, ALT_B)
 #define GPIO165_STMMOD_DAT2	PIN_CFG(165, ALT_C)
 
 #define GPIO166_GPIO		PIN_CFG(166, GPIO)
-#define GPIO166_KP_O2		PIN_CFG_PULL(166, ALT_A, UP)
+#define GPIO166_KP_O2		PIN_CFG_INPUT(166, ALT_A, PULLUP)
 #define GPIO166_LCD_D37		PIN_CFG(166, ALT_B)
 #define GPIO166_STMMOD_DAT1	PIN_CFG(166, ALT_C)
 
 #define GPIO167_GPIO		PIN_CFG(167, GPIO)
-#define GPIO167_KP_O1		PIN_CFG_PULL(167, ALT_A, UP)
+#define GPIO167_KP_O1		PIN_CFG_INPUT(167, ALT_A, PULLUP)
 #define GPIO167_LCD_D38		PIN_CFG(167, ALT_B)
 #define GPIO167_STMMOD_DAT0	PIN_CFG(167, ALT_C)
 
 #define GPIO168_GPIO		PIN_CFG(168, GPIO)
-#define GPIO168_KP_O0		PIN_CFG_PULL(168, ALT_A, UP)
+#define GPIO168_KP_O0		PIN_CFG_INPUT(168, ALT_A, PULLUP)
 #define GPIO168_LCD_D39		PIN_CFG(168, ALT_B)
 #define GPIO168_NONE		PIN_CFG(168, ALT_C)
 
@@ -569,39 +569,39 @@
 #define GPIO196_MSP2_RXD	PIN_CFG(196, ALT_A)
 
 #define GPIO197_GPIO		PIN_CFG(197, GPIO)
-#define GPIO197_MC4_DAT3	PIN_CFG_PULL(197, ALT_A, UP)
+#define GPIO197_MC4_DAT3	PIN_CFG_INPUT(197, ALT_A, PULLUP)
 
 #define GPIO198_GPIO		PIN_CFG(198, GPIO)
-#define GPIO198_MC4_DAT2	PIN_CFG_PULL(198, ALT_A, UP)
+#define GPIO198_MC4_DAT2	PIN_CFG_INPUT(198, ALT_A, PULLUP)
 
 #define GPIO199_GPIO		PIN_CFG(199, GPIO)
-#define GPIO199_MC4_DAT1	PIN_CFG_PULL(199, ALT_A, UP)
+#define GPIO199_MC4_DAT1	PIN_CFG_INPUT(199, ALT_A, PULLUP)
 
 #define GPIO200_GPIO		PIN_CFG(200, GPIO)
-#define GPIO200_MC4_DAT0	PIN_CFG_PULL(200, ALT_A, UP)
+#define GPIO200_MC4_DAT0	PIN_CFG_INPUT(200, ALT_A, PULLUP)
 
 #define GPIO201_GPIO		PIN_CFG(201, GPIO)
-#define GPIO201_MC4_CMD		PIN_CFG_PULL(201, ALT_A, UP)
+#define GPIO201_MC4_CMD		PIN_CFG_INPUT(201, ALT_A, PULLUP)
 
 #define GPIO202_GPIO		PIN_CFG(202, GPIO)
-#define GPIO202_MC4_FBCLK	PIN_CFG_PULL(202, ALT_A, UP)
+#define GPIO202_MC4_FBCLK	PIN_CFG_INPUT(202, ALT_A, PULLUP)
 #define GPIO202_PWL		PIN_CFG(202, ALT_B)
 #define GPIO202_MC4_RSTN	PIN_CFG(202, ALT_C)
 
 #define GPIO203_GPIO		PIN_CFG(203, GPIO)
-#define GPIO203_MC4_CLK		PIN_CFG_PULL(203, ALT_A, UP)
+#define GPIO203_MC4_CLK		PIN_CFG_INPUT(203, ALT_A, PULLUP)
 
 #define GPIO204_GPIO		PIN_CFG(204, GPIO)
-#define GPIO204_MC4_DAT7	PIN_CFG_PULL(204, ALT_A, UP)
+#define GPIO204_MC4_DAT7	PIN_CFG_INPUT(204, ALT_A, PULLUP)
 
 #define GPIO205_GPIO		PIN_CFG(205, GPIO)
-#define GPIO205_MC4_DAT6	PIN_CFG_PULL(205, ALT_A, UP)
+#define GPIO205_MC4_DAT6	PIN_CFG_INPUT(205, ALT_A, PULLUP)
 
 #define GPIO206_GPIO		PIN_CFG(206, GPIO)
-#define GPIO206_MC4_DAT5	PIN_CFG_PULL(206, ALT_A, UP)
+#define GPIO206_MC4_DAT5	PIN_CFG_INPUT(206, ALT_A, PULLUP)
 
 #define GPIO207_GPIO		PIN_CFG(207, GPIO)
-#define GPIO207_MC4_DAT4	PIN_CFG_PULL(207, ALT_A, UP)
+#define GPIO207_MC4_DAT4	PIN_CFG_INPUT(207, ALT_A, PULLUP)
 
 #define GPIO208_GPIO		PIN_CFG(208, GPIO)
 #define GPIO208_MC1_CLK		PIN_CFG(208, ALT_A)
@@ -632,21 +632,25 @@
 #define GPIO215_MC1_CMDDIR	PIN_CFG(215, ALT_A)
 #define GPIO215_MC3_DAT2DIR	PIN_CFG(215, ALT_B)
 #define GPIO215_CLKOUT1		PIN_CFG(215, ALT_C)
+#define GPIO215_SPI2_TXD	PIN_CFG(215, ALT_C)
 
 #define GPIO216_GPIO		PIN_CFG(216, GPIO)
 #define GPIO216_MC1_DAT2DIR	PIN_CFG(216, ALT_A)
 #define GPIO216_MC3_CMDDIR	PIN_CFG(216, ALT_B)
-#define GPIO216_I2C3_SDA	PIN_CFG_PULL(216, ALT_C, UP)
+#define GPIO216_I2C3_SDA	PIN_CFG_INPUT(216, ALT_C, PULLUP)
+#define GPIO216_SPI2_FRM	PIN_CFG(216, ALT_C)
 
 #define GPIO217_GPIO		PIN_CFG(217, GPIO)
 #define GPIO217_MC1_DAT0DIR	PIN_CFG(217, ALT_A)
 #define GPIO217_MC3_DAT31DIR	PIN_CFG(217, ALT_B)
 #define GPIO217_CLKOUT2		PIN_CFG(217, ALT_C)
+#define GPIO217_SPI2_CLK	PIN_CFG(217, ALT_C)
 
 #define GPIO218_GPIO		PIN_CFG(218, GPIO)
 #define GPIO218_MC1_DAT31DIR	PIN_CFG(218, ALT_A)
 #define GPIO218_MC3_DAT0DIR	PIN_CFG(218, ALT_B)
-#define GPIO218_I2C3_SCL	PIN_CFG_PULL(218, ALT_C, UP)
+#define GPIO218_I2C3_SCL	PIN_CFG_INPUT(218, ALT_C, PULLUP)
+#define GPIO218_SPI2_RXD	PIN_CFG(218, ALT_C)
 
 #define GPIO219_GPIO		PIN_CFG(219, GPIO)
 #define GPIO219_HSIR_FLA0	PIN_CFG(219, ALT_A)
@@ -694,12 +698,12 @@
 #define GPIO229_GPIO		PIN_CFG(229, GPIO)
 #define GPIO229_CLKOUT1		PIN_CFG(229, ALT_A)
 #define GPIO229_PWL		PIN_CFG(229, ALT_B)
-#define GPIO229_I2C3_SDA	PIN_CFG_PULL(229, ALT_C, UP)
+#define GPIO229_I2C3_SDA	PIN_CFG_INPUT(229, ALT_C, PULLUP)
 
 #define GPIO230_GPIO		PIN_CFG(230, GPIO)
 #define GPIO230_CLKOUT2		PIN_CFG(230, ALT_A)
 #define GPIO230_PWL		PIN_CFG(230, ALT_B)
-#define GPIO230_I2C3_SCL	PIN_CFG_PULL(230, ALT_C, UP)
+#define GPIO230_I2C3_SCL	PIN_CFG_INPUT(230, ALT_C, PULLUP)
 
 #define GPIO256_GPIO		PIN_CFG(256, GPIO)
 #define GPIO256_USB_NXT		PIN_CFG(256, ALT_A)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/platsmp.c linux-libre-3.2-gnu/arch/arm/mach-ux500/platsmp.c
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/platsmp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -96,7 +96,7 @@
 	 * the holding pen - release it, then wait for it to flag
 	 * that it has been released by resetting pen_release.
 	 */
-	write_pen_release(cpu);
+	write_pen_release(cpu_logical_map(cpu));
 
 	gic_raise_softirq(cpumask_of(cpu), 1);
 
@@ -156,12 +156,10 @@
 	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
 
 	/* sanity check */
-	if (ncores > NR_CPUS) {
-		printk(KERN_WARNING
-		       "U8500: no. of cores (%d) greater than configured "
-		       "maximum of %d - clipping\n",
-		       ncores, NR_CPUS);
-		ncores = NR_CPUS;
+	if (ncores > nr_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
 	}
 
 	for (i = 0; i < ncores; i++)
diff -druN linux-libre-3.1-gnu/arch/arm/mach-ux500/timer.c linux-libre-3.2-gnu/arch/arm/mach-ux500/timer.c
--- linux-libre-3.1-gnu/arch/arm/mach-ux500/timer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-ux500/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson
+ */
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/clksrc-dbx500-prcmu.h>
+
+#include <asm/localtimer.h>
+
+#include <plat/mtu.h>
+
+#include <mach/setup.h>
+#include <mach/hardware.h>
+
+static void __init ux500_timer_init(void)
+{
+	void __iomem *prcmu_timer_base;
+
+	if (cpu_is_u5500()) {
+#ifdef CONFIG_LOCAL_TIMERS
+		twd_base = __io_address(U5500_TWD_BASE);
+#endif
+		mtu_base = __io_address(U5500_MTU0_BASE);
+		prcmu_timer_base = __io_address(U5500_PRCMU_TIMER_3_BASE);
+	} else if (cpu_is_u8500()) {
+#ifdef CONFIG_LOCAL_TIMERS
+		twd_base = __io_address(U8500_TWD_BASE);
+#endif
+		mtu_base = __io_address(U8500_MTU0_BASE);
+		prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE);
+	} else {
+		ux500_unknown_soc();
+	}
+
+	/*
+	 * Here we register the timerblocks active in the system.
+	 * Localtimers (twd) is started when both cpu is up and running.
+	 * MTU register a clocksource, clockevent and sched_clock.
+	 * Since the MTU is located in the VAPE power domain
+	 * it will be cleared in sleep which makes it unsuitable.
+	 * We however need it as a timer tick (clockevent)
+	 * during boot to calibrate delay until twd is started.
+	 * RTC-RTT have problems as timer tick during boot since it is
+	 * depending on delay which is not yet calibrated. RTC-RTT is in the
+	 * always-on powerdomain and is used as clockevent instead of twd when
+	 * sleeping.
+	 * The PRCMU timer 4(3 for DB5500) register a clocksource and
+	 * sched_clock with higher rating then MTU since is always-on.
+	 *
+	 */
+
+	nmdk_timer_init();
+	clksrc_dbx500_prcmu_init(prcmu_timer_base);
+}
+
+static void ux500_timer_reset(void)
+{
+	nmdk_clkevt_reset();
+	nmdk_clksrc_reset();
+}
+
+struct sys_timer ux500_timer = {
+	.init		= ux500_timer_init,
+	.resume		= ux500_timer_reset,
+};
diff -druN linux-libre-3.1-gnu/arch/arm/mach-versatile/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-versatile/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-versatile/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-versatile/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *
 */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp,      #0x001F0000
 		orr	\rp, \rp, #0x00001000
 		orr	\rv, \rp, #0xf1000000	@ virtual base
diff -druN linux-libre-3.1-gnu/arch/arm/mach-versatile/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-versatile/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-versatile/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-versatile/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1 @@
-#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
+/* empty */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-versatile/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-versatile/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-versatile/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-versatile/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- *  arch/arm/mach-versatile/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 PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-versatile/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-versatile/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-versatile/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-versatile/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-versatile/versatile_ab.c linux-libre-3.2-gnu/arch/arm/mach-versatile/versatile_ab.c
--- linux-libre-3.1-gnu/arch/arm/mach-versatile/versatile_ab.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-versatile/versatile_ab.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,7 +35,7 @@
 
 MACHINE_START(VERSATILE_AB, "ARM-Versatile AB")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= versatile_map_io,
 	.init_early	= versatile_init_early,
 	.init_irq	= versatile_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-versatile/versatile_pb.c linux-libre-3.2-gnu/arch/arm/mach-versatile/versatile_pb.c
--- linux-libre-3.1-gnu/arch/arm/mach-versatile/versatile_pb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-versatile/versatile_pb.c	2012-01-04 18:55:44.000000000 -0500
@@ -103,7 +103,7 @@
 
 MACHINE_START(VERSATILE_PB, "ARM-Versatile PB")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= versatile_map_io,
 	.init_early	= versatile_init_early,
 	.init_irq	= versatile_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-vexpress/ct-ca9x4.c linux-libre-3.2-gnu/arch/arm/mach-vexpress/ct-ca9x4.c
--- linux-libre-3.1-gnu/arch/arm/mach-vexpress/ct-ca9x4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-vexpress/ct-ca9x4.c	2012-01-04 18:55:44.000000000 -0500
@@ -221,6 +221,12 @@
 {
 	int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU));
 
+	if (ncores > nr_cpu_ids) {
+		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
+			ncores, nr_cpu_ids);
+		ncores = nr_cpu_ids;
+	}
+
 	for (i = 0; i < ncores; ++i)
 		set_cpu_possible(i, true);
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-vexpress/hotplug.c linux-libre-3.2-gnu/arch/arm/mach-vexpress/hotplug.c
--- linux-libre-3.1-gnu/arch/arm/mach-vexpress/hotplug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-vexpress/hotplug.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
+#include <asm/system.h>
 
 extern volatile int pen_release;
 
@@ -62,15 +63,9 @@
 	 * code will have already disabled interrupts
 	 */
 	for (;;) {
-		/*
-		 * here's the WFI
-		 */
-		asm(".word	0xe320f003\n"
-		    :
-		    :
-		    : "memory", "cc");
+		wfi();
 
-		if (pen_release == cpu) {
+		if (pen_release == cpu_logical_map(cpu)) {
 			/*
 			 * OK, proper wakeup, we're done
 			 */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-vexpress/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-vexpress/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-vexpress/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-vexpress/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
 
 #define DEBUG_LL_UART_OFFSET	0x00009000
 
-		.macro	addruart,rp,rv
+		.macro	addruart,rp,rv,tmp
 		mov	\rp, #DEBUG_LL_UART_OFFSET
 		orr	\rv, \rp, #0xf8000000	@ virtual base
 		orr	\rp, \rp, #0x10000000	@ physical base
diff -druN linux-libre-3.1-gnu/arch/arm/mach-vexpress/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-vexpress/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-vexpress/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/mach-vexpress/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+/* empty */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-vexpress/include/mach/io.h linux-libre-3.2-gnu/arch/arm/mach-vexpress/include/mach/io.h
--- linux-libre-3.1-gnu/arch/arm/mach-vexpress/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-vexpress/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,8 +20,6 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#define IO_SPACE_LIMIT 0xffffffff
-
 #define __io(a)		__typesafe_io(a)
 #define __mem_pci(a)	(a)
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-vexpress/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-vexpress/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-vexpress/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-vexpress/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,25 +0,0 @@
-/*
- *  arch/arm/mach-vexpress/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
-
-#define PLAT_PHYS_OFFSET		UL(0x60000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-vexpress/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-vexpress/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-vexpress/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-vexpress/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x60008000
+   zreladdr-y	+= 0x60008000
 params_phys-y	:= 0x60000100
 initrd_phys-y	:= 0x60800000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-vexpress/v2m.c linux-libre-3.2-gnu/arch/arm/mach-vexpress/v2m.c
--- linux-libre-3.1-gnu/arch/arm/mach-vexpress/v2m.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-vexpress/v2m.c	2012-01-04 18:55:44.000000000 -0500
@@ -443,7 +443,7 @@
 }
 
 MACHINE_START(VEXPRESS, "ARM-Versatile Express")
-	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
+	.atag_offset	= 0x100,
 	.map_io		= v2m_map_io,
 	.init_early	= v2m_init_early,
 	.init_irq	= v2m_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-vt8500/bv07.c linux-libre-3.2-gnu/arch/arm/mach-vt8500/bv07.c
--- linux-libre-3.1-gnu/arch/arm/mach-vt8500/bv07.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-vt8500/bv07.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,7 +68,7 @@
 }
 
 MACHINE_START(BV07, "Benign BV07 Mini Netbook")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.reserve	= vt8500_reserve_mem,
 	.map_io		= vt8500_map_io,
 	.init_irq	= vt8500_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-vt8500/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-vt8500/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-vt8500/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-vt8500/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *
 */
 
-	.macro	addruart, rp, rv
+	.macro	addruart, rp, rv, tmp
 	mov	\rp,      #0x00200000
 	orr	\rv, \rp, #0xf8000000
 	orr	\rp, \rp, #0xd8000000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-vt8500/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-vt8500/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-vt8500/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-vt8500/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1 @@
-#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
+/* empty */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-vt8500/include/mach/io.h linux-libre-3.2-gnu/arch/arm/mach-vt8500/include/mach/io.h
--- linux-libre-3.1-gnu/arch/arm/mach-vt8500/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-vt8500/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,8 +20,6 @@
 #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)
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-vt8500/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-vt8500/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-vt8500/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-vt8500/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- *  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-3.1-gnu/arch/arm/mach-vt8500/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-vt8500/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-vt8500/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-vt8500/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x01000000
diff -druN linux-libre-3.1-gnu/arch/arm/mach-vt8500/wm8505_7in.c linux-libre-3.2-gnu/arch/arm/mach-vt8500/wm8505_7in.c
--- linux-libre-3.1-gnu/arch/arm/mach-vt8500/wm8505_7in.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-vt8500/wm8505_7in.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,7 +68,7 @@
 }
 
 MACHINE_START(WM8505_7IN_NETBOOK, "WM8505 7-inch generic netbook")
-	.boot_params	= 0x00000100,
+	.atag_offset	= 0x100,
 	.reserve	= wm8505_reserve_mem,
 	.map_io		= wm8505_map_io,
 	.init_irq	= wm8505_init_irq,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-w90x900/cpu.c linux-libre-3.2-gnu/arch/arm/mach-w90x900/cpu.c
--- linux-libre-3.1-gnu/arch/arm/mach-w90x900/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-w90x900/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,7 +60,7 @@
 static DEFINE_SUBCLK(rmii, 2);
 static DEFINE_CLK(usbd, 8);
 static DEFINE_CLK(usbh, 9);
-static DEFINE_CLK(g2d, 10);;
+static DEFINE_CLK(g2d, 10);
 static DEFINE_CLK(pwm, 18);
 static DEFINE_CLK(ps2, 24);
 static DEFINE_CLK(kpi, 25);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-w90x900/dev.c linux-libre-3.2-gnu/arch/arm/mach-w90x900/dev.c
--- linux-libre-3.1-gnu/arch/arm/mach-w90x900/dev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-w90x900/dev.c	2012-01-04 18:55:44.000000000 -0500
@@ -422,7 +422,7 @@
 
 /* LCD controller*/
 
-static struct nuc900fb_display __initdata nuc900_lcd_info[] = {
+static struct nuc900fb_display nuc900_lcd_info[] = {
 	/* Giantplus Technology GPM1040A0 320x240 Color TFT LCD */
 	[0] = {
 		.type		= LCM_DCCS_VA_SRC_RGB565,
@@ -445,7 +445,7 @@
 	},
 };
 
-static struct nuc900fb_mach_info nuc900_fb_info __initdata = {
+static struct nuc900fb_mach_info nuc900_fb_info = {
 #if defined(CONFIG_GPM1040A0_320X240)
 	.displays		= &nuc900_lcd_info[0],
 #else
diff -druN linux-libre-3.1-gnu/arch/arm/mach-w90x900/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/mach-w90x900/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/mach-w90x900/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-w90x900/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,16 +15,12 @@
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
 
 static inline int gpio_to_irq(unsigned gpio)
 {
 	return gpio;
 }
+#define gpio_to_irq gpio_to_irq
 
 static inline int irq_to_gpio(unsigned irq)
 {
diff -druN linux-libre-3.1-gnu/arch/arm/mach-w90x900/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-w90x900/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-w90x900/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-w90x900/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * arch/arm/mach-w90x900/include/mach/memory.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/memory.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET	UL(0x00000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-w90x900/include/mach/mfp.h linux-libre-3.2-gnu/arch/arm/mach-w90x900/include/mach/mfp.h
--- linux-libre-3.1-gnu/arch/arm/mach-w90x900/include/mach/mfp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-w90x900/include/mach/mfp.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 extern void mfp_set_groupf(struct device *dev);
 extern void mfp_set_groupc(struct device *dev);
 extern void mfp_set_groupi(struct device *dev);
-extern void mfp_set_groupg(struct device *dev);
+extern void mfp_set_groupg(struct device *dev, const char *subname);
+extern void mfp_set_groupd(struct device *dev, const char *subname);
 
 #endif /* __ASM_ARCH_MFP_H */
diff -druN linux-libre-3.1-gnu/arch/arm/mach-w90x900/include/mach/nuc900_spi.h linux-libre-3.2-gnu/arch/arm/mach-w90x900/include/mach/nuc900_spi.h
--- linux-libre-3.1-gnu/arch/arm/mach-w90x900/include/mach/nuc900_spi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-w90x900/include/mach/nuc900_spi.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 #ifndef __ASM_ARCH_SPI_H
 #define __ASM_ARCH_SPI_H
 
-extern void mfp_set_groupg(struct device *dev);
+extern void mfp_set_groupg(struct device *dev, const char *subname);
 
 struct nuc900_spi_info {
 	unsigned int num_cs;
diff -druN linux-libre-3.1-gnu/arch/arm/mach-w90x900/mach-nuc910evb.c linux-libre-3.2-gnu/arch/arm/mach-w90x900/mach-nuc910evb.c
--- linux-libre-3.1-gnu/arch/arm/mach-w90x900/mach-nuc910evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-w90x900/mach-nuc910evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,7 +34,6 @@
 
 MACHINE_START(W90P910EVB, "W90P910EVB")
 	/* Maintainer: Wan ZongShun */
-	.boot_params	= 0,
 	.map_io		= nuc910evb_map_io,
 	.init_irq	= nuc900_init_irq,
 	.init_machine	= nuc910evb_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-w90x900/mach-nuc950evb.c linux-libre-3.2-gnu/arch/arm/mach-w90x900/mach-nuc950evb.c
--- linux-libre-3.1-gnu/arch/arm/mach-w90x900/mach-nuc950evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-w90x900/mach-nuc950evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,7 +37,6 @@
 
 MACHINE_START(W90P950EVB, "W90P950EVB")
 	/* Maintainer: Wan ZongShun */
-	.boot_params	= 0,
 	.map_io		= nuc950evb_map_io,
 	.init_irq	= nuc900_init_irq,
 	.init_machine	= nuc950evb_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-w90x900/mach-nuc960evb.c linux-libre-3.2-gnu/arch/arm/mach-w90x900/mach-nuc960evb.c
--- linux-libre-3.1-gnu/arch/arm/mach-w90x900/mach-nuc960evb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-w90x900/mach-nuc960evb.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,7 +34,6 @@
 
 MACHINE_START(W90N960EVB, "W90N960EVB")
 	/* Maintainer: Wan ZongShun */
-	.boot_params	= 0,
 	.map_io		= nuc960evb_map_io,
 	.init_irq	= nuc900_init_irq,
 	.init_machine	= nuc960evb_init,
diff -druN linux-libre-3.1-gnu/arch/arm/mach-w90x900/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-w90x900/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-w90x900/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-w90x900/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-zreladdr-y	:= 0x00008000
+zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 
diff -druN linux-libre-3.1-gnu/arch/arm/mach-w90x900/mfp.c linux-libre-3.2-gnu/arch/arm/mach-w90x900/mfp.c
--- linux-libre-3.1-gnu/arch/arm/mach-w90x900/mfp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-w90x900/mfp.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,10 +26,8 @@
 #define REG_MFSEL	(W90X900_VA_GCR + 0xC)
 
 #define GPSELF		(0x01 << 1)
-
 #define GPSELC		(0x03 << 2)
-#define ENKPI		(0x02 << 2)
-#define ENNAND		(0x01 << 2)
+#define GPSELD		(0x0f << 4)
 
 #define GPSELEI0	(0x01 << 26)
 #define GPSELEI1	(0x01 << 27)
@@ -37,11 +35,16 @@
 #define GPIOG0TO1	(0x03 << 14)
 #define GPIOG2TO3	(0x03 << 16)
 #define GPIOG22TO23	(0x03 << 22)
+#define GPIOG18TO20	(0x07 << 18)
 
 #define ENSPI		(0x0a << 14)
 #define ENI2C0		(0x01 << 14)
 #define ENI2C1		(0x01 << 16)
 #define ENAC97		(0x02 << 22)
+#define ENSD1		(0x02 << 18)
+#define ENSD0		(0x0a << 4)
+#define ENKPI		(0x02 << 2)
+#define ENNAND		(0x01 << 2)
 
 static DEFINE_MUTEX(mfp_mutex);
 
@@ -127,16 +130,19 @@
 }
 EXPORT_SYMBOL(mfp_set_groupi);
 
-void mfp_set_groupg(struct device *dev)
+void mfp_set_groupg(struct device *dev, const char *subname)
 {
 	unsigned long mfpen;
 	const char *dev_id;
 
-	BUG_ON(!dev);
+	BUG_ON((!dev) && (!subname));
 
 	mutex_lock(&mfp_mutex);
 
-	dev_id = dev_name(dev);
+	if (subname != NULL)
+		dev_id = subname;
+	else
+		dev_id = dev_name(dev);
 
 	mfpen = __raw_readl(REG_MFSEL);
 
@@ -152,6 +158,9 @@
 	} else if (strcmp(dev_id, "nuc900-audio") == 0) {
 		mfpen &= ~(GPIOG22TO23);
 		mfpen |= ENAC97;/*enable AC97*/
+	} else if (strcmp(dev_id, "nuc900-mmc-port1") == 0) {
+		mfpen &= ~(GPIOG18TO20);
+		mfpen |= (ENSD1 | 0x01);/*enable sd1*/
 	} else {
 		mfpen &= ~(GPIOG0TO1 | GPIOG2TO3);/*GPIOG[3:0]*/
 	}
@@ -162,3 +171,30 @@
 }
 EXPORT_SYMBOL(mfp_set_groupg);
 
+void mfp_set_groupd(struct device *dev, const char *subname)
+{
+	unsigned long mfpen;
+	const char *dev_id;
+
+	BUG_ON((!dev) && (!subname));
+
+	mutex_lock(&mfp_mutex);
+
+	if (subname != NULL)
+		dev_id = subname;
+	else
+		dev_id = dev_name(dev);
+
+	mfpen = __raw_readl(REG_MFSEL);
+
+	if (strcmp(dev_id, "nuc900-mmc-port0") == 0) {
+		mfpen &= ~GPSELD;/*enable sd0*/
+		mfpen |= ENSD0;
+	} else
+		mfpen &= (~GPSELD);
+
+	__raw_writel(mfpen, REG_MFSEL);
+
+	mutex_unlock(&mfp_mutex);
+}
+EXPORT_SYMBOL(mfp_set_groupd);
diff -druN linux-libre-3.1-gnu/arch/arm/mach-zynq/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/mach-zynq/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/mach-zynq/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-zynq/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
 #include <mach/zynq_soc.h>
 #include <mach/uart.h>
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		ldr	\rp, =LL_UART_PADDR	@ physical
 		ldr	\rv, =LL_UART_VADDR	@ virtual
 		.endm
diff -druN linux-libre-3.1-gnu/arch/arm/mach-zynq/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/mach-zynq/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/mach-zynq/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-zynq/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/memory.h
- *
- *  Copyright (C) 2011 Xilinx
- *
- * 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_MEMORY_H__
-#define __MACH_MEMORY_H__
-
-#include <asm/sizes.h>
-
-#define PLAT_PHYS_OFFSET	UL(0x0)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mach-zynq/Makefile.boot linux-libre-3.2-gnu/arch/arm/mach-zynq/Makefile.boot
--- linux-libre-3.1-gnu/arch/arm/mach-zynq/Makefile.boot	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mach-zynq/Makefile.boot	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
-   zreladdr-y	:= 0x00008000
+   zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
diff -druN linux-libre-3.1-gnu/arch/arm/Makefile linux-libre-3.2-gnu/arch/arm/Makefile
--- linux-libre-3.1-gnu/arch/arm/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -128,6 +128,9 @@
 ifeq ($(CONFIG_ARCH_SA1100),y)
 textofs-$(CONFIG_SA1111) := 0x00208000
 endif
+textofs-$(CONFIG_ARCH_MSM7X30) := 0x00208000
+textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000
+textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000
 
 # Machine directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
@@ -141,6 +144,7 @@
 machine-$(CONFIG_ARCH_EP93XX)		:= ep93xx
 machine-$(CONFIG_ARCH_GEMINI)		:= gemini
 machine-$(CONFIG_ARCH_H720X)		:= h720x
+machine-$(CONFIG_ARCH_HIGHBANK)		:= highbank
 machine-$(CONFIG_ARCH_INTEGRATOR)	:= integrator
 machine-$(CONFIG_ARCH_IOP13XX)		:= iop13xx
 machine-$(CONFIG_ARCH_IOP32X)		:= iop32x
@@ -154,10 +158,8 @@
 machine-$(CONFIG_ARCH_MMP)		:= mmp
 machine-$(CONFIG_ARCH_MSM)		:= msm
 machine-$(CONFIG_ARCH_MV78XX0)		:= mv78xx0
-machine-$(CONFIG_ARCH_MX1)		:= imx
-machine-$(CONFIG_ARCH_MX2)		:= imx
-machine-$(CONFIG_ARCH_MX25)		:= imx
-machine-$(CONFIG_ARCH_MX3)		:= imx
+machine-$(CONFIG_ARCH_IMX_V4_V5)	:= imx
+machine-$(CONFIG_ARCH_IMX_V6_V7)	:= imx
 machine-$(CONFIG_ARCH_MX5)		:= mx5
 machine-$(CONFIG_ARCH_MXS)		:= mxs
 machine-$(CONFIG_ARCH_NETX)		:= netx
@@ -167,6 +169,7 @@
 machine-$(CONFIG_ARCH_OMAP3)		:= omap2
 machine-$(CONFIG_ARCH_OMAP4)		:= omap2
 machine-$(CONFIG_ARCH_ORION5X)		:= orion5x
+machine-$(CONFIG_ARCH_PICOXCELL)	:= picoxcell
 machine-$(CONFIG_ARCH_PNX4008)		:= pnx4008
 machine-$(CONFIG_ARCH_PRIMA2)		:= prima2
 machine-$(CONFIG_ARCH_PXA)		:= pxa
@@ -177,7 +180,7 @@
 machine-$(CONFIG_ARCH_S5P64X0)		:= s5p64x0
 machine-$(CONFIG_ARCH_S5PC100)		:= s5pc100
 machine-$(CONFIG_ARCH_S5PV210)		:= s5pv210
-machine-$(CONFIG_ARCH_EXYNOS4)		:= exynos4
+machine-$(CONFIG_ARCH_EXYNOS4)		:= exynos
 machine-$(CONFIG_ARCH_SA1100)		:= sa1100
 machine-$(CONFIG_ARCH_SHARK)		:= shark
 machine-$(CONFIG_ARCH_SHMOBILE) 	:= shmobile
@@ -189,7 +192,6 @@
 machine-$(CONFIG_ARCH_VEXPRESS)		:= vexpress
 machine-$(CONFIG_ARCH_VT8500)		:= vt8500
 machine-$(CONFIG_ARCH_W90X900)		:= w90x900
-machine-$(CONFIG_ARCH_NUC93X)		:= nuc93x
 machine-$(CONFIG_FOOTBRIDGE)		:= footbridge
 machine-$(CONFIG_MACH_SPEAR300)		:= spear3xx
 machine-$(CONFIG_MACH_SPEAR310)		:= spear3xx
diff -druN linux-libre-3.1-gnu/arch/arm/mm/alignment.c linux-libre-3.2-gnu/arch/arm/mm/alignment.c
--- linux-libre-3.1-gnu/arch/arm/mm/alignment.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/alignment.c	2012-01-04 18:55:44.000000000 -0500
@@ -86,16 +86,6 @@
 #define UM_FIXUP	(1 << 1)
 #define UM_SIGNAL	(1 << 2)
 
-#ifdef CONFIG_PROC_FS
-static const char *usermode_action[] = {
-	"ignored",
-	"warn",
-	"fixup",
-	"fixup+warn",
-	"signal",
-	"signal+warn"
-};
-
 /* Return true if and only if the ARMv6 unaligned access model is in use. */
 static bool cpu_is_v6_unaligned(void)
 {
@@ -123,6 +113,16 @@
 	return new_usermode;
 }
 
+#ifdef CONFIG_PROC_FS
+static const char *usermode_action[] = {
+	"ignored",
+	"warn",
+	"fixup",
+	"fixup+warn",
+	"signal",
+	"signal+warn"
+};
+
 static int alignment_proc_show(struct seq_file *m, void *v)
 {
 	seq_printf(m, "User:\t\t%lu\n", ai_user);
diff -druN linux-libre-3.1-gnu/arch/arm/mm/cache-l2x0.c linux-libre-3.2-gnu/arch/arm/mm/cache-l2x0.c
--- linux-libre-3.1-gnu/arch/arm/mm/cache-l2x0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/cache-l2x0.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,9 +16,12 @@
  * 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/err.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 
 #include <asm/cacheflush.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -26,15 +29,23 @@
 #define CACHE_LINE_SIZE		32
 
 static void __iomem *l2x0_base;
-static DEFINE_SPINLOCK(l2x0_lock);
+static DEFINE_RAW_SPINLOCK(l2x0_lock);
 static uint32_t l2x0_way_mask;	/* Bitmask of active ways */
 static uint32_t l2x0_size;
 
+struct l2x0_regs l2x0_saved_regs;
+
+struct l2x0_of_data {
+	void (*setup)(const struct device_node *, __u32 *, __u32 *);
+	void (*save)(void);
+	void (*resume)(void);
+};
+
 static inline void cache_wait_way(void __iomem *reg, unsigned long mask)
 {
 	/* wait for cache operation by line or way to complete */
 	while (readl_relaxed(reg) & mask)
-		;
+		cpu_relax();
 }
 
 #ifdef CONFIG_CACHE_PL310
@@ -50,7 +61,7 @@
 {
 	void __iomem *base = l2x0_base;
 
-#ifdef CONFIG_ARM_ERRATA_753970
+#ifdef CONFIG_PL310_ERRATA_753970
 	/* write to an unmmapped register */
 	writel_relaxed(0, base + L2X0_DUMMY_REG);
 #else
@@ -115,9 +126,9 @@
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&l2x0_lock, flags);
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	cache_sync();
-	spin_unlock_irqrestore(&l2x0_lock, flags);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void __l2x0_flush_all(void)
@@ -134,9 +145,9 @@
 	unsigned long flags;
 
 	/* clean all ways */
-	spin_lock_irqsave(&l2x0_lock, flags);
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	__l2x0_flush_all();
-	spin_unlock_irqrestore(&l2x0_lock, flags);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_clean_all(void)
@@ -144,11 +155,11 @@
 	unsigned long flags;
 
 	/* clean all ways */
-	spin_lock_irqsave(&l2x0_lock, flags);
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_WAY);
 	cache_wait_way(l2x0_base + L2X0_CLEAN_WAY, l2x0_way_mask);
 	cache_sync();
-	spin_unlock_irqrestore(&l2x0_lock, flags);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_inv_all(void)
@@ -156,13 +167,13 @@
 	unsigned long flags;
 
 	/* invalidate all ways */
-	spin_lock_irqsave(&l2x0_lock, flags);
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	/* Invalidating when L2 is enabled is a nono */
 	BUG_ON(readl(l2x0_base + L2X0_CTRL) & 1);
 	writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
 	cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
 	cache_sync();
-	spin_unlock_irqrestore(&l2x0_lock, flags);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_inv_range(unsigned long start, unsigned long end)
@@ -170,7 +181,7 @@
 	void __iomem *base = l2x0_base;
 	unsigned long flags;
 
-	spin_lock_irqsave(&l2x0_lock, flags);
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	if (start & (CACHE_LINE_SIZE - 1)) {
 		start &= ~(CACHE_LINE_SIZE - 1);
 		debug_writel(0x03);
@@ -195,13 +206,13 @@
 		}
 
 		if (blk_end < end) {
-			spin_unlock_irqrestore(&l2x0_lock, flags);
-			spin_lock_irqsave(&l2x0_lock, flags);
+			raw_spin_unlock_irqrestore(&l2x0_lock, flags);
+			raw_spin_lock_irqsave(&l2x0_lock, flags);
 		}
 	}
 	cache_wait(base + L2X0_INV_LINE_PA, 1);
 	cache_sync();
-	spin_unlock_irqrestore(&l2x0_lock, flags);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_clean_range(unsigned long start, unsigned long end)
@@ -214,7 +225,7 @@
 		return;
 	}
 
-	spin_lock_irqsave(&l2x0_lock, flags);
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	start &= ~(CACHE_LINE_SIZE - 1);
 	while (start < end) {
 		unsigned long blk_end = start + min(end - start, 4096UL);
@@ -225,13 +236,13 @@
 		}
 
 		if (blk_end < end) {
-			spin_unlock_irqrestore(&l2x0_lock, flags);
-			spin_lock_irqsave(&l2x0_lock, flags);
+			raw_spin_unlock_irqrestore(&l2x0_lock, flags);
+			raw_spin_lock_irqsave(&l2x0_lock, flags);
 		}
 	}
 	cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
 	cache_sync();
-	spin_unlock_irqrestore(&l2x0_lock, flags);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_flush_range(unsigned long start, unsigned long end)
@@ -244,7 +255,7 @@
 		return;
 	}
 
-	spin_lock_irqsave(&l2x0_lock, flags);
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	start &= ~(CACHE_LINE_SIZE - 1);
 	while (start < end) {
 		unsigned long blk_end = start + min(end - start, 4096UL);
@@ -257,27 +268,27 @@
 		debug_writel(0x00);
 
 		if (blk_end < end) {
-			spin_unlock_irqrestore(&l2x0_lock, flags);
-			spin_lock_irqsave(&l2x0_lock, flags);
+			raw_spin_unlock_irqrestore(&l2x0_lock, flags);
+			raw_spin_lock_irqsave(&l2x0_lock, flags);
 		}
 	}
 	cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
 	cache_sync();
-	spin_unlock_irqrestore(&l2x0_lock, flags);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_disable(void)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&l2x0_lock, flags);
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	__l2x0_flush_all();
 	writel_relaxed(0, l2x0_base + L2X0_CTRL);
 	dsb();
-	spin_unlock_irqrestore(&l2x0_lock, flags);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
-static void __init l2x0_unlock(__u32 cache_id)
+static void l2x0_unlock(__u32 cache_id)
 {
 	int lockregs;
 	int i;
@@ -353,6 +364,8 @@
 		/* l2x0 controller is disabled */
 		writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL);
 
+		l2x0_saved_regs.aux_ctrl = aux;
+
 		l2x0_inv_all();
 
 		/* enable L2X0 */
@@ -372,3 +385,202 @@
 	printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n",
 			ways, cache_id, aux, l2x0_size);
 }
+
+#ifdef CONFIG_OF
+static void __init l2x0_of_setup(const struct device_node *np,
+				 __u32 *aux_val, __u32 *aux_mask)
+{
+	u32 data[2] = { 0, 0 };
+	u32 tag = 0;
+	u32 dirty = 0;
+	u32 val = 0, mask = 0;
+
+	of_property_read_u32(np, "arm,tag-latency", &tag);
+	if (tag) {
+		mask |= L2X0_AUX_CTRL_TAG_LATENCY_MASK;
+		val |= (tag - 1) << L2X0_AUX_CTRL_TAG_LATENCY_SHIFT;
+	}
+
+	of_property_read_u32_array(np, "arm,data-latency",
+				   data, ARRAY_SIZE(data));
+	if (data[0] && data[1]) {
+		mask |= L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK |
+			L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK;
+		val |= ((data[0] - 1) << L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT) |
+		       ((data[1] - 1) << L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT);
+	}
+
+	of_property_read_u32(np, "arm,dirty-latency", &dirty);
+	if (dirty) {
+		mask |= L2X0_AUX_CTRL_DIRTY_LATENCY_MASK;
+		val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT;
+	}
+
+	*aux_val &= ~mask;
+	*aux_val |= val;
+	*aux_mask &= ~mask;
+}
+
+static void __init pl310_of_setup(const struct device_node *np,
+				  __u32 *aux_val, __u32 *aux_mask)
+{
+	u32 data[3] = { 0, 0, 0 };
+	u32 tag[3] = { 0, 0, 0 };
+	u32 filter[2] = { 0, 0 };
+
+	of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag));
+	if (tag[0] && tag[1] && tag[2])
+		writel_relaxed(
+			((tag[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) |
+			((tag[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) |
+			((tag[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT),
+			l2x0_base + L2X0_TAG_LATENCY_CTRL);
+
+	of_property_read_u32_array(np, "arm,data-latency",
+				   data, ARRAY_SIZE(data));
+	if (data[0] && data[1] && data[2])
+		writel_relaxed(
+			((data[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) |
+			((data[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) |
+			((data[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT),
+			l2x0_base + L2X0_DATA_LATENCY_CTRL);
+
+	of_property_read_u32_array(np, "arm,filter-ranges",
+				   filter, ARRAY_SIZE(filter));
+	if (filter[1]) {
+		writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M),
+			       l2x0_base + L2X0_ADDR_FILTER_END);
+		writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L2X0_ADDR_FILTER_EN,
+			       l2x0_base + L2X0_ADDR_FILTER_START);
+	}
+}
+
+static void __init pl310_save(void)
+{
+	u32 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
+		L2X0_CACHE_ID_RTL_MASK;
+
+	l2x0_saved_regs.tag_latency = readl_relaxed(l2x0_base +
+		L2X0_TAG_LATENCY_CTRL);
+	l2x0_saved_regs.data_latency = readl_relaxed(l2x0_base +
+		L2X0_DATA_LATENCY_CTRL);
+	l2x0_saved_regs.filter_end = readl_relaxed(l2x0_base +
+		L2X0_ADDR_FILTER_END);
+	l2x0_saved_regs.filter_start = readl_relaxed(l2x0_base +
+		L2X0_ADDR_FILTER_START);
+
+	if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
+		/*
+		 * From r2p0, there is Prefetch offset/control register
+		 */
+		l2x0_saved_regs.prefetch_ctrl = readl_relaxed(l2x0_base +
+			L2X0_PREFETCH_CTRL);
+		/*
+		 * From r3p0, there is Power control register
+		 */
+		if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
+			l2x0_saved_regs.pwr_ctrl = readl_relaxed(l2x0_base +
+				L2X0_POWER_CTRL);
+	}
+}
+
+static void l2x0_resume(void)
+{
+	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+		/* restore aux ctrl and enable l2 */
+		l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID));
+
+		writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base +
+			L2X0_AUX_CTRL);
+
+		l2x0_inv_all();
+
+		writel_relaxed(1, l2x0_base + L2X0_CTRL);
+	}
+}
+
+static void pl310_resume(void)
+{
+	u32 l2x0_revision;
+
+	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+		/* restore pl310 setup */
+		writel_relaxed(l2x0_saved_regs.tag_latency,
+			l2x0_base + L2X0_TAG_LATENCY_CTRL);
+		writel_relaxed(l2x0_saved_regs.data_latency,
+			l2x0_base + L2X0_DATA_LATENCY_CTRL);
+		writel_relaxed(l2x0_saved_regs.filter_end,
+			l2x0_base + L2X0_ADDR_FILTER_END);
+		writel_relaxed(l2x0_saved_regs.filter_start,
+			l2x0_base + L2X0_ADDR_FILTER_START);
+
+		l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
+			L2X0_CACHE_ID_RTL_MASK;
+
+		if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
+			writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
+				l2x0_base + L2X0_PREFETCH_CTRL);
+			if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
+				writel_relaxed(l2x0_saved_regs.pwr_ctrl,
+					l2x0_base + L2X0_POWER_CTRL);
+		}
+	}
+
+	l2x0_resume();
+}
+
+static const struct l2x0_of_data pl310_data = {
+	pl310_of_setup,
+	pl310_save,
+	pl310_resume,
+};
+
+static const struct l2x0_of_data l2x0_data = {
+	l2x0_of_setup,
+	NULL,
+	l2x0_resume,
+};
+
+static const struct of_device_id l2x0_ids[] __initconst = {
+	{ .compatible = "arm,pl310-cache", .data = (void *)&pl310_data },
+	{ .compatible = "arm,l220-cache", .data = (void *)&l2x0_data },
+	{ .compatible = "arm,l210-cache", .data = (void *)&l2x0_data },
+	{}
+};
+
+int __init l2x0_of_init(__u32 aux_val, __u32 aux_mask)
+{
+	struct device_node *np;
+	struct l2x0_of_data *data;
+	struct resource res;
+
+	np = of_find_matching_node(NULL, l2x0_ids);
+	if (!np)
+		return -ENODEV;
+
+	if (of_address_to_resource(np, 0, &res))
+		return -ENODEV;
+
+	l2x0_base = ioremap(res.start, resource_size(&res));
+	if (!l2x0_base)
+		return -ENOMEM;
+
+	l2x0_saved_regs.phy_base = res.start;
+
+	data = of_match_node(l2x0_ids, np)->data;
+
+	/* L2 configuration can only be changed if the cache is disabled */
+	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+		if (data->setup)
+			data->setup(np, &aux_val, &aux_mask);
+	}
+
+	if (data->save)
+		data->save();
+
+	l2x0_init(l2x0_base, aux_val, aux_mask);
+
+	outer_cache.resume = data->resume;
+	return 0;
+}
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/mm/context.c linux-libre-3.2-gnu/arch/arm/mm/context.c
--- linux-libre-3.1-gnu/arch/arm/mm/context.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/context.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 
-static DEFINE_SPINLOCK(cpu_asid_lock);
+static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
 unsigned int cpu_last_asid = ASID_FIRST_VERSION;
 #ifdef CONFIG_SMP
 DEFINE_PER_CPU(struct mm_struct *, current_mm);
@@ -31,7 +31,7 @@
 void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
 	mm->context.id = 0;
-	spin_lock_init(&mm->context.id_lock);
+	raw_spin_lock_init(&mm->context.id_lock);
 }
 
 static void flush_context(void)
@@ -58,7 +58,7 @@
 	 * the broadcast. This function is also called via IPI so the
 	 * mm->context.id_lock has to be IRQ-safe.
 	 */
-	spin_lock_irqsave(&mm->context.id_lock, flags);
+	raw_spin_lock_irqsave(&mm->context.id_lock, flags);
 	if (likely((mm->context.id ^ cpu_last_asid) >> ASID_BITS)) {
 		/*
 		 * Old version of ASID found. Set the new one and
@@ -67,7 +67,7 @@
 		mm->context.id = asid;
 		cpumask_clear(mm_cpumask(mm));
 	}
-	spin_unlock_irqrestore(&mm->context.id_lock, flags);
+	raw_spin_unlock_irqrestore(&mm->context.id_lock, flags);
 
 	/*
 	 * Set the mm_cpumask(mm) bit for the current CPU.
@@ -117,7 +117,7 @@
 {
 	unsigned int asid;
 
-	spin_lock(&cpu_asid_lock);
+	raw_spin_lock(&cpu_asid_lock);
 #ifdef CONFIG_SMP
 	/*
 	 * Check the ASID again, in case the change was broadcast from
@@ -125,7 +125,7 @@
 	 */
 	if (unlikely(((mm->context.id ^ cpu_last_asid) >> ASID_BITS) == 0)) {
 		cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
-		spin_unlock(&cpu_asid_lock);
+		raw_spin_unlock(&cpu_asid_lock);
 		return;
 	}
 #endif
@@ -153,5 +153,5 @@
 	}
 
 	set_mm_context(mm, asid);
-	spin_unlock(&cpu_asid_lock);
+	raw_spin_unlock(&cpu_asid_lock);
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mm/copypage-v4mc.c linux-libre-3.2-gnu/arch/arm/mm/copypage-v4mc.c
--- linux-libre-3.1-gnu/arch/arm/mm/copypage-v4mc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/copypage-v4mc.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@
 #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
 				  L_PTE_MT_MINICACHE)
 
-static DEFINE_SPINLOCK(minicache_lock);
+static DEFINE_RAW_SPINLOCK(minicache_lock);
 
 /*
  * ARMv4 mini-dcache optimised copy_user_highpage
@@ -76,14 +76,14 @@
 	if (!test_and_set_bit(PG_dcache_clean, &from->flags))
 		__flush_dcache_page(page_mapping(from), from);
 
-	spin_lock(&minicache_lock);
+	raw_spin_lock(&minicache_lock);
 
 	set_pte_ext(TOP_PTE(0xffff8000), pfn_pte(page_to_pfn(from), minicache_pgprot), 0);
 	flush_tlb_kernel_page(0xffff8000);
 
 	mc_copy_user_page((void *)0xffff8000, kto);
 
-	spin_unlock(&minicache_lock);
+	raw_spin_unlock(&minicache_lock);
 
 	kunmap_atomic(kto, KM_USER1);
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mm/copypage-v6.c linux-libre-3.2-gnu/arch/arm/mm/copypage-v6.c
--- linux-libre-3.1-gnu/arch/arm/mm/copypage-v6.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/copypage-v6.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,7 @@
 #define from_address	(0xffff8000)
 #define to_address	(0xffffc000)
 
-static DEFINE_SPINLOCK(v6_lock);
+static DEFINE_RAW_SPINLOCK(v6_lock);
 
 /*
  * Copy the user page.  No aliasing to deal with so we can just
@@ -88,7 +88,7 @@
 	 * Now copy the page using the same cache colour as the
 	 * pages ultimate destination.
 	 */
-	spin_lock(&v6_lock);
+	raw_spin_lock(&v6_lock);
 
 	set_pte_ext(TOP_PTE(from_address) + offset, pfn_pte(page_to_pfn(from), PAGE_KERNEL), 0);
 	set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(to), PAGE_KERNEL), 0);
@@ -101,7 +101,7 @@
 
 	copy_page((void *)kto, (void *)kfrom);
 
-	spin_unlock(&v6_lock);
+	raw_spin_unlock(&v6_lock);
 }
 
 /*
@@ -121,13 +121,13 @@
 	 * Now clear the page using the same cache colour as
 	 * the pages ultimate destination.
 	 */
-	spin_lock(&v6_lock);
+	raw_spin_lock(&v6_lock);
 
 	set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(page), PAGE_KERNEL), 0);
 	flush_tlb_kernel_page(to);
 	clear_page((void *)to);
 
-	spin_unlock(&v6_lock);
+	raw_spin_unlock(&v6_lock);
 }
 
 struct cpu_user_fns v6_user_fns __initdata = {
diff -druN linux-libre-3.1-gnu/arch/arm/mm/copypage-xscale.c linux-libre-3.2-gnu/arch/arm/mm/copypage-xscale.c
--- linux-libre-3.1-gnu/arch/arm/mm/copypage-xscale.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/copypage-xscale.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,7 @@
 #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
 				  L_PTE_MT_MINICACHE)
 
-static DEFINE_SPINLOCK(minicache_lock);
+static DEFINE_RAW_SPINLOCK(minicache_lock);
 
 /*
  * XScale mini-dcache optimised copy_user_highpage
@@ -98,14 +98,14 @@
 	if (!test_and_set_bit(PG_dcache_clean, &from->flags))
 		__flush_dcache_page(page_mapping(from), from);
 
-	spin_lock(&minicache_lock);
+	raw_spin_lock(&minicache_lock);
 
 	set_pte_ext(TOP_PTE(COPYPAGE_MINICACHE), pfn_pte(page_to_pfn(from), minicache_pgprot), 0);
 	flush_tlb_kernel_page(COPYPAGE_MINICACHE);
 
 	mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto);
 
-	spin_unlock(&minicache_lock);
+	raw_spin_unlock(&minicache_lock);
 
 	kunmap_atomic(kto, KM_USER1);
 }
diff -druN linux-libre-3.1-gnu/arch/arm/mm/dma-mapping.c linux-libre-3.2-gnu/arch/arm/mm/dma-mapping.c
--- linux-libre-3.1-gnu/arch/arm/mm/dma-mapping.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/dma-mapping.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,12 +18,14 @@
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/highmem.h>
+#include <linux/slab.h>
 
 #include <asm/memory.h>
 #include <asm/highmem.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/sizes.h>
+#include <asm/mach/arch.h>
 
 #include "mm.h"
 
@@ -117,26 +119,36 @@
 }
 
 #ifdef CONFIG_MMU
-/* Sanity check size */
-#if (CONSISTENT_DMA_SIZE % SZ_2M)
-#error "CONSISTENT_DMA_SIZE must be multiple of 2MiB"
-#endif
 
-#define CONSISTENT_OFFSET(x)	(((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
-#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT)
-#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT)
+#define CONSISTENT_OFFSET(x)	(((unsigned long)(x) - consistent_base) >> PAGE_SHIFT)
+#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - consistent_base) >> PMD_SHIFT)
 
 /*
  * These are the page tables (2MB each) covering uncached, DMA consistent allocations
  */
-static pte_t *consistent_pte[NUM_CONSISTENT_PTES];
+static pte_t **consistent_pte;
+
+#define DEFAULT_CONSISTENT_DMA_SIZE SZ_2M
+
+unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE;
+
+void __init init_consistent_dma_size(unsigned long size)
+{
+	unsigned long base = CONSISTENT_END - ALIGN(size, SZ_2M);
+
+	BUG_ON(consistent_pte); /* Check we're called before DMA region init */
+	BUG_ON(base < VMALLOC_END);
+
+	/* Grow region to accommodate specified size  */
+	if (base < consistent_base)
+		consistent_base = base;
+}
 
 #include "vmregion.h"
 
 static struct arm_vmregion_head consistent_head = {
 	.vm_lock	= __SPIN_LOCK_UNLOCKED(&consistent_head.vm_lock),
 	.vm_list	= LIST_HEAD_INIT(consistent_head.vm_list),
-	.vm_start	= CONSISTENT_BASE,
 	.vm_end		= CONSISTENT_END,
 };
 
@@ -155,7 +167,17 @@
 	pmd_t *pmd;
 	pte_t *pte;
 	int i = 0;
-	u32 base = CONSISTENT_BASE;
+	unsigned long base = consistent_base;
+	unsigned long num_ptes = (CONSISTENT_END - base) >> PMD_SHIFT;
+
+	consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL);
+	if (!consistent_pte) {
+		pr_err("%s: no memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	pr_debug("DMA memory: 0x%08lx - 0x%08lx:\n", base, CONSISTENT_END);
+	consistent_head.vm_start = base;
 
 	do {
 		pgd = pgd_offset(&init_mm, base);
@@ -183,7 +205,7 @@
 		}
 
 		consistent_pte[i++] = pte;
-		base += (1 << PGDIR_SHIFT);
+		base += PMD_SIZE;
 	} while (base < CONSISTENT_END);
 
 	return ret;
@@ -198,7 +220,7 @@
 	size_t align;
 	int bit;
 
-	if (!consistent_pte[0]) {
+	if (!consistent_pte) {
 		printk(KERN_ERR "%s: not initialised\n", __func__);
 		dump_stack();
 		return NULL;
@@ -310,6 +332,15 @@
 	struct page *page;
 	void *addr;
 
+	/*
+	 * Following is a work-around (a.k.a. hack) to prevent pages
+	 * with __GFP_COMP being passed to split_page() which cannot
+	 * handle them.  The real problem is that this flag probably
+	 * should be 0 on ARM as it is not supported on this
+	 * platform; see CONFIG_HUGETLBFS.
+	 */
+	gfp &= ~(__GFP_COMP);
+
 	*handle = ~0;
 	size = PAGE_ALIGN(size);
 
diff -druN linux-libre-3.1-gnu/arch/arm/mm/fault-armv.c linux-libre-3.2-gnu/arch/arm/mm/fault-armv.c
--- linux-libre-3.1-gnu/arch/arm/mm/fault-armv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/fault-armv.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,6 @@
  * 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/kernel.h>
 #include <linux/mm.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mm/fault.c linux-libre-3.2-gnu/arch/arm/mm/fault.c
--- linux-libre-3.1-gnu/arch/arm/mm/fault.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/fault.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/highmem.h>
 #include <linux/perf_event.h>
 
+#include <asm/exception.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
diff -druN linux-libre-3.1-gnu/arch/arm/mm/init.c linux-libre-3.2-gnu/arch/arm/mm/init.c
--- linux-libre-3.1-gnu/arch/arm/mm/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/mman.h>
+#include <linux/export.h>
 #include <linux/nodemask.h>
 #include <linux/initrd.h>
 #include <linux/of_fdt.h>
@@ -660,9 +661,6 @@
 			"    ITCM    : 0x%08lx - 0x%08lx   (%4ld kB)\n"
 #endif
 			"    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
-#ifdef CONFIG_MMU
-			"    DMA     : 0x%08lx - 0x%08lx   (%4ld MB)\n"
-#endif
 			"    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"
 			"    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n"
 #ifdef CONFIG_HIGHMEM
@@ -681,9 +679,6 @@
 			MLK(ITCM_OFFSET, (unsigned long) itcm_end),
 #endif
 			MLK(FIXADDR_START, FIXADDR_TOP),
-#ifdef CONFIG_MMU
-			MLM(CONSISTENT_BASE, CONSISTENT_END),
-#endif
 			MLM(VMALLOC_START, VMALLOC_END),
 			MLM(PAGE_OFFSET, (unsigned long)high_memory),
 #ifdef CONFIG_HIGHMEM
@@ -706,9 +701,6 @@
 	 * be detected at build time already.
 	 */
 #ifdef CONFIG_MMU
-	BUILD_BUG_ON(VMALLOC_END			> CONSISTENT_BASE);
-	BUG_ON(VMALLOC_END				> CONSISTENT_BASE);
-
 	BUILD_BUG_ON(TASK_SIZE				> MODULES_VADDR);
 	BUG_ON(TASK_SIZE 				> MODULES_VADDR);
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mm/ioremap.c linux-libre-3.2-gnu/arch/arm/mm/ioremap.c
--- linux-libre-3.1-gnu/arch/arm/mm/ioremap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/ioremap.c	2012-01-04 18:55:44.000000000 -0500
@@ -289,6 +289,27 @@
 }
 EXPORT_SYMBOL(__arm_ioremap);
 
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space as memory. Needed when the kernel wants to execute
+ * code in external memory. This is needed for reprogramming source
+ * clocks that would affect normal memory for example. Please see
+ * CONFIG_GENERIC_ALLOCATOR for allocating external memory.
+ */
+void __iomem *
+__arm_ioremap_exec(unsigned long phys_addr, size_t size, bool cached)
+{
+	unsigned int mtype;
+
+	if (cached)
+		mtype = MT_MEMORY;
+	else
+		mtype = MT_MEMORY_NONCACHED;
+
+	return __arm_ioremap_caller(phys_addr, size, mtype,
+			__builtin_return_address(0));
+}
+
 void __iounmap(volatile void __iomem *io_addr)
 {
 	void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
diff -druN linux-libre-3.1-gnu/arch/arm/mm/Kconfig linux-libre-3.2-gnu/arch/arm/mm/Kconfig
--- linux-libre-3.1-gnu/arch/arm/mm/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -819,10 +819,10 @@
 config CACHE_L2X0
 	bool "Enable the L2x0 outer cache controller"
 	depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
-		   REALVIEW_EB_A9MP || SOC_IMX35 || SOC_IMX31 || MACH_REALVIEW_PBX || \
+		   REALVIEW_EB_A9MP || ARCH_IMX_V6_V7 || MACH_REALVIEW_PBX || \
 		   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_EXYNOS4 || ARCH_TEGRA || \
 		   ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE || \
-		   ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX
+		   ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX || ARCH_HIGHBANK
 	default y
 	select OUTER_CACHE
 	select OUTER_CACHE_SYNC
diff -druN linux-libre-3.1-gnu/arch/arm/mm/mmap.c linux-libre-3.2-gnu/arch/arm/mm/mmap.c
--- linux-libre-3.1-gnu/arch/arm/mm/mmap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/mmap.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,8 +9,7 @@
 #include <linux/io.h>
 #include <linux/personality.h>
 #include <linux/random.h>
-#include <asm/cputype.h>
-#include <asm/system.h>
+#include <asm/cachetype.h>
 
 #define COLOUR_ALIGN(addr,pgoff)		\
 	((((addr)+SHMLBA-1)&~(SHMLBA-1)) +	\
@@ -32,25 +31,15 @@
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
 	unsigned long start_addr;
-#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
-	unsigned int cache_type;
-	int do_align = 0, aliasing = 0;
+	int do_align = 0;
+	int aliasing = cache_is_vipt_aliasing();
 
 	/*
 	 * We only need to do colour alignment if either the I or D
-	 * caches alias.  This is indicated by bits 9 and 21 of the
-	 * cache type register.
+	 * caches alias.
 	 */
-	cache_type = read_cpuid_cachetype();
-	if (cache_type != read_cpuid_id()) {
-		aliasing = (cache_type | cache_type >> 12) & (1 << 11);
-		if (aliasing)
-			do_align = filp || flags & MAP_SHARED;
-	}
-#else
-#define do_align 0
-#define aliasing 0
-#endif
+	if (aliasing)
+		do_align = filp || (flags & MAP_SHARED);
 
 	/*
 	 * We enforce the MAP_FIXED case.
diff -druN linux-libre-3.1-gnu/arch/arm/mm/mm.h linux-libre-3.2-gnu/arch/arm/mm/mm.h
--- linux-libre-3.1-gnu/arch/arm/mm/mm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/mm.h	2012-01-04 18:55:44.000000000 -0500
@@ -12,8 +12,8 @@
 
 struct mem_type {
 	pteval_t prot_pte;
-	unsigned int prot_l1;
-	unsigned int prot_sect;
+	pmdval_t prot_l1;
+	pmdval_t prot_sect;
 	unsigned int domain;
 };
 
diff -druN linux-libre-3.1-gnu/arch/arm/mm/mmu.c linux-libre-3.2-gnu/arch/arm/mm/mmu.c
--- linux-libre-3.1-gnu/arch/arm/mm/mmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/mmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,7 +60,7 @@
 struct cachepolicy {
 	const char	policy[16];
 	unsigned int	cr_mask;
-	unsigned int	pmd;
+	pmdval_t	pmd;
 	pteval_t	pte;
 };
 
@@ -273,6 +273,14 @@
 		.prot_l1   = PMD_TYPE_TABLE,
 		.domain    = DOMAIN_KERNEL,
 	},
+	[MT_MEMORY_SO] = {
+		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+				L_PTE_MT_UNCACHED,
+		.prot_l1   = PMD_TYPE_TABLE,
+		.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_S |
+				PMD_SECT_UNCACHED | PMD_SECT_XN,
+		.domain    = DOMAIN_KERNEL,
+	},
 };
 
 const struct mem_type *get_mem_type(unsigned int type)
@@ -288,7 +296,7 @@
 {
 	struct cachepolicy *cp;
 	unsigned int cr = get_cr();
-	unsigned int user_pgprot, kern_pgprot, vecs_pgprot;
+	pteval_t user_pgprot, kern_pgprot, vecs_pgprot;
 	int cpu_arch = cpu_architecture();
 	int i;
 
@@ -863,14 +871,14 @@
 	/*
 	 * Clear out all the mappings below the kernel image.
 	 */
-	for (addr = 0; addr < MODULES_VADDR; addr += PGDIR_SIZE)
+	for (addr = 0; addr < MODULES_VADDR; addr += PMD_SIZE)
 		pmd_clear(pmd_off_k(addr));
 
 #ifdef CONFIG_XIP_KERNEL
 	/* The XIP kernel is mapped in the module area -- skip over it */
-	addr = ((unsigned long)_etext + PGDIR_SIZE - 1) & PGDIR_MASK;
+	addr = ((unsigned long)_etext + PMD_SIZE - 1) & PMD_MASK;
 #endif
-	for ( ; addr < PAGE_OFFSET; addr += PGDIR_SIZE)
+	for ( ; addr < PAGE_OFFSET; addr += PMD_SIZE)
 		pmd_clear(pmd_off_k(addr));
 
 	/*
@@ -885,10 +893,12 @@
 	 * memory bank, up to the end of the vmalloc region.
 	 */
 	for (addr = __phys_to_virt(end);
-	     addr < VMALLOC_END; addr += PGDIR_SIZE)
+	     addr < VMALLOC_END; addr += PMD_SIZE)
 		pmd_clear(pmd_off_k(addr));
 }
 
+#define SWAPPER_PG_DIR_SIZE	(PTRS_PER_PGD * sizeof(pgd_t))
+
 /*
  * Reserve the special regions of memory
  */
@@ -898,7 +908,7 @@
 	 * 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));
+	memblock_reserve(__pa(swapper_pg_dir), SWAPPER_PG_DIR_SIZE);
 
 #ifdef CONFIG_SA1111
 	/*
@@ -926,7 +936,7 @@
 	 */
 	vectors_page = early_alloc(PAGE_SIZE);
 
-	for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
+	for (addr = VMALLOC_END; addr; addr += PMD_SIZE)
 		pmd_clear(pmd_off_k(addr));
 
 	/*
diff -druN linux-libre-3.1-gnu/arch/arm/mm/proc-arm920.S linux-libre-3.2-gnu/arch/arm/mm/proc-arm920.S
--- linux-libre-3.1-gnu/arch/arm/mm/proc-arm920.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/proc-arm920.S	2012-01-04 18:55:44.000000000 -0500
@@ -379,31 +379,26 @@
 
 /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
 .globl	cpu_arm920_suspend_size
-.equ	cpu_arm920_suspend_size, 4 * 4
+.equ	cpu_arm920_suspend_size, 4 * 3
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_arm920_do_suspend)
-	stmfd	sp!, {r4 - r7, lr}
+	stmfd	sp!, {r4 - r6, 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}
+	mrc	p15, 0, r6, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r6}
+	ldmfd	sp!, {r4 - r6, 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}
+	ldmia	r0, {r4 - r6}
 	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
+	mcr	p15, 0, r1, c2, c0, 0	@ TTB address
+	mov	r0, r6			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_arm920_do_resume)
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mm/proc-arm926.S linux-libre-3.2-gnu/arch/arm/mm/proc-arm926.S
--- linux-libre-3.1-gnu/arch/arm/mm/proc-arm926.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/proc-arm926.S	2012-01-04 18:55:44.000000000 -0500
@@ -394,31 +394,26 @@
 
 /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
 .globl	cpu_arm926_suspend_size
-.equ	cpu_arm926_suspend_size, 4 * 4
+.equ	cpu_arm926_suspend_size, 4 * 3
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_arm926_do_suspend)
-	stmfd	sp!, {r4 - r7, lr}
+	stmfd	sp!, {r4 - r6, 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}
+	mrc	p15, 0, r6, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r6}
+	ldmfd	sp!, {r4 - r6, 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}
+	ldmia	r0, {r4 - r6}
 	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
+	mcr	p15, 0, r1, c2, c0, 0	@ TTB address
+	mov	r0, r6			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_arm926_do_resume)
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mm/proc-sa1100.S linux-libre-3.2-gnu/arch/arm/mm/proc-sa1100.S
--- linux-libre-3.1-gnu/arch/arm/mm/proc-sa1100.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/proc-sa1100.S	2012-01-04 18:55:44.000000000 -0500
@@ -168,20 +168,19 @@
 	mov	pc, lr
 
 .globl	cpu_sa1100_suspend_size
-.equ	cpu_sa1100_suspend_size, 4*4
+.equ	cpu_sa1100_suspend_size, 4 * 3
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_sa1100_do_suspend)
-	stmfd	sp!, {r4 - r7, lr}
+	stmfd	sp!, {r4 - r6, 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}
+	mrc	p15, 0, r5, c13, c0, 0		@ PID
+	mrc	p15, 0, r6, c1, c0, 0		@ control reg
+	stmia	r0, {r4 - r6}			@ store cp regs
+	ldmfd	sp!, {r4 - r6, pc}
 ENDPROC(cpu_sa1100_do_suspend)
 
 ENTRY(cpu_sa1100_do_resume)
-	ldmia	r0, {r4 - r7}			@ load cp regs
+	ldmia	r0, {r4 - r6}			@ load cp regs
 	mov	ip, #0
 	mcr	p15, 0, ip, c8, c7, 0		@ flush I+D TLBs
 	mcr	p15, 0, ip, c7, c7, 0		@ flush I&D cache
@@ -189,13 +188,9 @@
 	mcr	p15, 0, ip, 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
+	mcr	p15, 0, r1, c2, c0, 0		@ translation table base addr
+	mcr	p15, 0, r5, c13, c0, 0		@ PID
+	mov	r0, r6				@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_sa1100_do_resume)
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mm/proc-v6.S linux-libre-3.2-gnu/arch/arm/mm/proc-v6.S
--- linux-libre-3.1-gnu/arch/arm/mm/proc-v6.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/proc-v6.S	2012-01-04 18:55:44.000000000 -0500
@@ -128,20 +128,18 @@
 
 /* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
 .globl	cpu_v6_suspend_size
-.equ	cpu_v6_suspend_size, 4 * 8
+.equ	cpu_v6_suspend_size, 4 * 6
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_v6_do_suspend)
-	stmfd	sp!, {r4 - r11, lr}
+	stmfd	sp!, {r4 - r9, 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}
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 1	@ Translation table base 1
+	mrc	p15, 0, r7, c1, c0, 1	@ auxiliary control register
+	mrc	p15, 0, r8, c1, c0, 2	@ co-processor access control
+	mrc	p15, 0, r9, c1, c0, 0	@ control register
+	stmia	r0, {r4 - r9}
+	ldmfd	sp!, {r4- r9, pc}
 ENDPROC(cpu_v6_do_suspend)
 
 ENTRY(cpu_v6_do_resume)
@@ -150,25 +148,21 @@
 	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, ip, c13, c0, 1	@ set reserved context ID
+	ldmia	r0, {r4 - r9}
 	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, r5, c3, c0, 0	@ Domain ID
+	ALT_SMP(orr	r1, r1, #TTB_FLAGS_SMP)
+	ALT_UP(orr	r1, r1, #TTB_FLAGS_UP)
+	mcr	p15, 0, r1, c2, c0, 0	@ Translation table base 0
+	mcr	p15, 0, r6, c2, c0, 1	@ Translation table base 1
+	mcr	p15, 0, r7, c1, c0, 1	@ auxiliary control register
+	mcr	p15, 0, r8, 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
+	mov	r0, r9			@ control register
 	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)
 #endif
 
 	string	cpu_v6_name, "ARMv6-compatible processor"
diff -druN linux-libre-3.1-gnu/arch/arm/mm/proc-v7.S linux-libre-3.2-gnu/arch/arm/mm/proc-v7.S
--- linux-libre-3.1-gnu/arch/arm/mm/proc-v7.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/proc-v7.S	2012-01-04 18:55:44.000000000 -0500
@@ -217,56 +217,50 @@
 
 /* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
 .globl	cpu_v7_suspend_size
-.equ	cpu_v7_suspend_size, 4 * 9
-#ifdef CONFIG_PM_SLEEP
+.equ	cpu_v7_suspend_size, 4 * 7
+#ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_v7_do_suspend)
-	stmfd	sp!, {r4 - r11, lr}
+	stmfd	sp!, {r4 - r10, lr}
 	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
-	mrc	p15, 0, r5, c13, c0, 1	@ Context ID
-	mrc	p15, 0, r6, c13, c0, 3	@ User r/o thread ID
-	stmia	r0!, {r4 - r6}
+	mrc	p15, 0, r5, c13, c0, 3	@ User r/o thread ID
+	stmia	r0!, {r4 - r5}
 	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, {r6 - r11}
-	ldmfd	sp!, {r4 - r11, pc}
+	mrc	p15, 0, r7, c2, c0, 1	@ TTB 1
+	mrc	p15, 0, r8, c1, c0, 0	@ Control register
+	mrc	p15, 0, r9, c1, c0, 1	@ Auxiliary control register
+	mrc	p15, 0, r10, c1, c0, 2	@ Co-processor access control
+	stmia	r0, {r6 - r10}
+	ldmfd	sp!, {r4 - r10, 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 - r6}
+	mcr	p15, 0, ip, c13, c0, 1	@ set reserved context ID
+	ldmia	r0!, {r4 - r5}
 	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
-	mcr	p15, 0, r5, c13, c0, 1	@ Context ID
-	mcr	p15, 0, r6, c13, c0, 3	@ User r/o thread ID
-	ldmia	r0, {r6 - r11}
+	mcr	p15, 0, r5, c13, c0, 3	@ User r/o thread ID
+	ldmia	r0, {r6 - r10}
 	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
+	ALT_SMP(orr	r1, r1, #TTB_FLAGS_SMP)
+	ALT_UP(orr	r1, r1, #TTB_FLAGS_UP)
+	mcr	p15, 0, r1, c2, c0, 0	@ TTB 0
+	mcr	p15, 0, r7, c2, c0, 1	@ TTB 1
 	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
 	mrc	p15, 0, r4, c1, c0, 1	@ Read Auxiliary control register
-	teq	r4, r10			@ Is it already set?
-	mcrne	p15, 0, r10, c1, c0, 1	@ No, so write it
-	mcr	p15, 0, r11, c1, c0, 2	@ Co-processor access control
+	teq	r4, r9			@ Is it already set?
+	mcrne	p15, 0, r9, c1, c0, 1	@ No, so write it
+	mcr	p15, 0, r10, 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
 	dsb
-	mov	r0, r9			@ control register
-	mov	r2, r7, lsr #14		@ get TTB0 base
-	mov	r2, r2, lsl #14
-	ldr	r3, cpu_resume_l1_flags
+	mov	r0, r8			@ control register
 	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)
 #endif
 
 	__CPUINIT
@@ -369,11 +363,13 @@
 	orreq	r10, r10, #1 << 6		@ set bit #6
 	mcreq	p15, 0, r10, c15, c0, 1		@ write diagnostic register
 #endif
-#ifdef CONFIG_ARM_ERRATA_751472
-	cmp	r6, #0x30			@ present prior to r3p0
+#if defined(CONFIG_ARM_ERRATA_751472) && defined(CONFIG_SMP)
+	ALT_SMP(cmp r6, #0x30)			@ present prior to r3p0
+	ALT_UP_B(1f)
 	mrclt	p15, 0, r10, c15, c0, 1		@ read diagnostic register
 	orrlt	r10, r10, #1 << 11		@ set bit #11
 	mcrlt	p15, 0, r10, c15, c0, 1		@ write diagnostic register
+1:
 #endif
 
 3:	mov	r10, #0
diff -druN linux-libre-3.1-gnu/arch/arm/mm/proc-xsc3.S linux-libre-3.2-gnu/arch/arm/mm/proc-xsc3.S
--- linux-libre-3.1-gnu/arch/arm/mm/proc-xsc3.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/proc-xsc3.S	2012-01-04 18:55:44.000000000 -0500
@@ -406,24 +406,23 @@
 	.align
 
 .globl	cpu_xsc3_suspend_size
-.equ	cpu_xsc3_suspend_size, 4 * 7
+.equ	cpu_xsc3_suspend_size, 4 * 6
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_xsc3_do_suspend)
-	stmfd	sp!, {r4 - r10, lr}
+	stmfd	sp!, {r4 - r9, 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
+	mrc	p15, 0, r8, c1, c0, 1	@ auxiliary control reg
+	mrc 	p15, 0, r9, c1, c0, 0	@ control reg
 	bic	r4, r4, #2		@ clear frequency change bit
-	stmia	r0, {r4 - r10}		@ store cp regs
-	ldmia	sp!, {r4 - r10, pc}
+	stmia	r0, {r4 - r9}		@ store cp regs
+	ldmia	sp!, {r4 - r9, pc}
 ENDPROC(cpu_xsc3_do_suspend)
 
 ENTRY(cpu_xsc3_do_resume)
-	ldmia	r0, {r4 - r10}		@ load cp regs
+	ldmia	r0, {r4 - r9}		@ load 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
@@ -433,15 +432,10 @@
 	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
+	orr	r1, r1, #0x18		@ cache the page table in L2
+	mcr	p15, 0, r1, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r8, c1, c0, 1	@ auxiliary control reg
+	mov	r0, r9			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_xsc3_do_resume)
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/mm/proc-xscale.S linux-libre-3.2-gnu/arch/arm/mm/proc-xscale.S
--- linux-libre-3.1-gnu/arch/arm/mm/proc-xscale.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/mm/proc-xscale.S	2012-01-04 18:55:44.000000000 -0500
@@ -520,24 +520,23 @@
 	.align
 
 .globl	cpu_xscale_suspend_size
-.equ	cpu_xscale_suspend_size, 4 * 7
+.equ	cpu_xscale_suspend_size, 4 * 6
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_xscale_do_suspend)
-	stmfd	sp!, {r4 - r10, lr}
+	stmfd	sp!, {r4 - r9, 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
+	mrc	p15, 0, r8, c1, c1, 0	@ auxiliary control reg
+	mrc	p15, 0, r9, 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}
+	stmia	r0, {r4 - r9}		@ store cp regs
+	ldmfd	sp!, {r4 - r9, pc}
 ENDPROC(cpu_xscale_do_suspend)
 
 ENTRY(cpu_xscale_do_resume)
-	ldmia	r0, {r4 - r10}		@ load cp regs
+	ldmia	r0, {r4 - r9}		@ 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
@@ -545,13 +544,9 @@
 	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
+	mcr	p15, 0, r1, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r8, c1, c1, 0	@ auxiliary control reg
+	mov	r0, r9			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_xscale_do_resume)
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/oprofile/common.c linux-libre-3.2-gnu/arch/arm/oprofile/common.c
--- linux-libre-3.1-gnu/arch/arm/oprofile/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/oprofile/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -116,7 +116,7 @@
 	return oprofile_perf_init(ops);
 }
 
-void __exit oprofile_arch_exit(void)
+void oprofile_arch_exit(void)
 {
 	oprofile_perf_exit();
 }
diff -druN linux-libre-3.1-gnu/arch/arm/plat-iop/gpio.c linux-libre-3.2-gnu/arch/arm/plat-iop/gpio.c
--- linux-libre-3.1-gnu/arch/arm/plat-iop/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-iop/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/gpio.h>
+#include <linux/export.h>
 #include <asm/hardware/iop3xx.h>
 
 void gpio_line_config(int line, int direction)
diff -druN linux-libre-3.1-gnu/arch/arm/plat-iop/time.c linux-libre-3.2-gnu/arch/arm/plat-iop/time.c
--- linux-libre-3.1-gnu/arch/arm/plat-iop/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-iop/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/export.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/sched_clock.h>
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/audmux-v2.c linux-libre-3.2-gnu/arch/arm/plat-mxc/audmux-v2.c
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/audmux-v2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/audmux-v2.c	2012-01-04 18:55:44.000000000 -0500
@@ -187,18 +187,11 @@
 static int mxc_audmux_v2_init(void)
 {
 	int ret;
-#if defined(CONFIG_ARCH_MX5)
 	if (cpu_is_mx51()) {
 		audmux_base = MX51_IO_ADDRESS(MX51_AUDMUX_BASE_ADDR);
-		ret = 0;
-		return ret;
-	}
-#endif
-#if defined(CONFIG_ARCH_MX3)
-	if (cpu_is_mx31())
+	} else if (cpu_is_mx31()) {
 		audmux_base = MX31_IO_ADDRESS(MX31_AUDMUX_BASE_ADDR);
-
-	else if (cpu_is_mx35()) {
+	} else if (cpu_is_mx35()) {
 		audmux_clk = clk_get(NULL, "audmux");
 		if (IS_ERR(audmux_clk)) {
 			ret = PTR_ERR(audmux_clk);
@@ -207,10 +200,7 @@
 			return ret;
 		}
 		audmux_base = MX35_IO_ADDRESS(MX35_AUDMUX_BASE_ADDR);
-	}
-#endif
-#if defined(CONFIG_SOC_IMX25)
-	if (cpu_is_mx25()) {
+	} else if (cpu_is_mx25()) {
 		audmux_clk = clk_get(NULL, "audmux");
 		if (IS_ERR(audmux_clk)) {
 			ret = PTR_ERR(audmux_clk);
@@ -220,7 +210,7 @@
 		}
 		audmux_base = MX25_IO_ADDRESS(MX25_AUDMUX_BASE_ADDR);
 	}
-#endif /* if defined(CONFIG_SOC_IMX25) */
+
 	audmux_debugfs_init();
 
 	return 0;
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/avic.c linux-libre-3.2-gnu/arch/arm/plat-mxc/avic.c
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/avic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/avic.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <mach/common.h>
 #include <asm/mach/irq.h>
+#include <asm/exception.h>
 #include <mach/hardware.h>
 
 #include "irq-common.h"
@@ -50,6 +51,8 @@
 
 void __iomem *avic_base;
 
+static u32 avic_saved_mask_reg[2];
+
 #ifdef CONFIG_MXC_IRQ_PRIOR
 static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
 {
@@ -90,24 +93,8 @@
 }
 #endif /* CONFIG_FIQ */
 
-/* Disable interrupt number "irq" in the AVIC */
-static void mxc_mask_irq(struct irq_data *d)
-{
-	__raw_writel(d->irq, avic_base + AVIC_INTDISNUM);
-}
 
-/* Enable interrupt number "irq" in the AVIC */
-static void mxc_unmask_irq(struct irq_data *d)
-{
-	__raw_writel(d->irq, avic_base + AVIC_INTENNUM);
-}
-
-static struct mxc_irq_chip mxc_avic_chip = {
-	.base = {
-		.irq_ack = mxc_mask_irq,
-		.irq_mask = mxc_mask_irq,
-		.irq_unmask = mxc_unmask_irq,
-	},
+static struct mxc_extra_irq avic_extra_irq = {
 #ifdef CONFIG_MXC_IRQ_PRIOR
 	.set_priority = avic_irq_set_priority,
 #endif
@@ -116,6 +103,68 @@
 #endif
 };
 
+#ifdef CONFIG_PM
+static void avic_irq_suspend(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct = gc->chip_types;
+	int idx = gc->irq_base >> 5;
+
+	avic_saved_mask_reg[idx] = __raw_readl(avic_base + ct->regs.mask);
+	__raw_writel(gc->wake_active, avic_base + ct->regs.mask);
+}
+
+static void avic_irq_resume(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct = gc->chip_types;
+	int idx = gc->irq_base >> 5;
+
+	__raw_writel(avic_saved_mask_reg[idx], avic_base + ct->regs.mask);
+}
+
+#else
+#define avic_irq_suspend NULL
+#define avic_irq_resume NULL
+#endif
+
+static __init void avic_init_gc(unsigned int irq_start)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+	int idx = irq_start >> 5;
+
+	gc = irq_alloc_generic_chip("mxc-avic", 1, irq_start, avic_base,
+				    handle_level_irq);
+	gc->private = &avic_extra_irq;
+	gc->wake_enabled = IRQ_MSK(32);
+
+	ct = gc->chip_types;
+	ct->chip.irq_mask = irq_gc_mask_clr_bit;
+	ct->chip.irq_unmask = irq_gc_mask_set_bit;
+	ct->chip.irq_ack = irq_gc_mask_clr_bit;
+	ct->chip.irq_set_wake = irq_gc_set_wake;
+	ct->chip.irq_suspend = avic_irq_suspend;
+	ct->chip.irq_resume = avic_irq_resume;
+	ct->regs.mask = !idx ? AVIC_INTENABLEL : AVIC_INTENABLEH;
+	ct->regs.ack = ct->regs.mask;
+
+	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
+}
+
+asmlinkage void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
+{
+	u32 nivector;
+
+	do {
+		nivector = __raw_readl(avic_base + AVIC_NIVECSR) >> 16;
+		if (nivector == 0xffff)
+			break;
+
+		handle_IRQ(nivector, regs);
+	} while (1);
+}
+
 /*
  * This function initializes the AVIC hardware and disables all the
  * interrupts. It registers the interrupt enable and disable functions
@@ -140,11 +189,9 @@
 	/* all IRQ no FIQ */
 	__raw_writel(0, avic_base + AVIC_INTTYPEH);
 	__raw_writel(0, avic_base + AVIC_INTTYPEL);
-	for (i = 0; i < AVIC_NUM_IRQS; i++) {
-		irq_set_chip_and_handler(i, &mxc_avic_chip.base,
-					 handle_level_irq);
-		set_irq_flags(i, IRQF_VALID);
-	}
+
+	for (i = 0; i < AVIC_NUM_IRQS; i += 32)
+		avic_init_gc(i);
 
 	/* Set default priority value (0) for all IRQ's */
 	for (i = 0; i < 8; i++)
@@ -157,4 +204,3 @@
 
 	printk(KERN_INFO "MXC IRQ initialized\n");
 }
-
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/cpu.c linux-libre-3.2-gnu/arch/arm/plat-mxc/cpu.c
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 
 #include <linux/module.h>
+#include <mach/hardware.h>
 
 unsigned int __mxc_cpu_type;
 EXPORT_SYMBOL(__mxc_cpu_type);
@@ -9,3 +10,11 @@
 	__mxc_cpu_type = type;
 }
 
+void imx_print_silicon_rev(const char *cpu, int srev)
+{
+	if (srev == IMX_CHIP_REVISION_UNKNOWN)
+		pr_info("CPU identified as %s, unknown revision\n", cpu);
+	else
+		pr_info("CPU identified as %s, silicon rev %d.%d\n",
+				cpu, (srev >> 4) & 0xf, srev & 0xf);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/cpufreq.c linux-libre-3.2-gnu/arch/arm/plat-mxc/cpufreq.c
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
  * the CPU clock speed on the fly.
  */
 
+#include <linux/module.h>
 #include <linux/cpufreq.h>
 #include <linux/clk.h>
 #include <linux/err.h>
@@ -97,7 +98,7 @@
 	return ret;
 }
 
-static int __init mxc_cpufreq_init(struct cpufreq_policy *policy)
+static int mxc_cpufreq_init(struct cpufreq_policy *policy)
 {
 	int ret;
 	int i;
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/devices/Kconfig linux-libre-3.2-gnu/arch/arm/plat-mxc/devices/Kconfig
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/devices/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/devices/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 config IMX_HAVE_PLATFORM_FEC
 	bool
-	default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53
+	default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX50 || SOC_IMX51 || SOC_IMX53
 
 config IMX_HAVE_PLATFORM_FLEXCAN
 	select HAVE_CAN_FLEXCAN if CAN
@@ -31,6 +31,9 @@
 config IMX_HAVE_PLATFORM_IMX_KEYPAD
 	bool
 
+config IMX_HAVE_PLATFORM_PATA_IMX
+	bool
+
 config IMX_HAVE_PLATFORM_IMX_SSI
 	bool
 
@@ -76,3 +79,7 @@
 
 config IMX_HAVE_PLATFORM_SPI_IMX
 	bool
+
+config IMX_HAVE_PLATFORM_AHCI
+	bool
+	default y if ARCH_MX53
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/devices/Makefile linux-libre-3.2-gnu/arch/arm/plat-mxc/devices/Makefile
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/devices/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/devices/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_FB) += platform-imx-fb.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_I2C) += platform-imx-i2c.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_KEYPAD) += platform-imx-keypad.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_PATA_IMX) += platform-pata_imx.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_SSI) += platform-imx-ssi.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UART) += platform-imx-uart.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UDC) += platform-imx_udc.o
@@ -25,3 +26,4 @@
 obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_W1) += platform-mxc_w1.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX) += platform-sdhci-esdhc-imx.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_SPI_IMX) +=  platform-spi_imx.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_AHCI) +=  platform-ahci-imx.o
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/devices/platform-ahci-imx.c linux-libre-3.2-gnu/arch/arm/plat-mxc/devices/platform-ahci-imx.c
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/devices/platform-ahci-imx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/devices/platform-ahci-imx.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You 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/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <asm/sizes.h>
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_ahci_imx_data_entry_single(soc, _devid)		\
+	{								\
+		.devid = _devid,					\
+		.iobase = soc ## _SATA_BASE_ADDR,			\
+		.irq = soc ## _INT_SATA,				\
+	}
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_ahci_imx_data imx53_ahci_imx_data __initconst =
+	imx_ahci_imx_data_entry_single(MX53, "imx53-ahci");
+#endif
+
+enum {
+	HOST_CAP = 0x00,
+	HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
+	HOST_PORTS_IMPL	= 0x0c,
+	HOST_TIMER1MS = 0xe0, /* Timer 1-ms */
+};
+
+static struct clk *sata_clk, *sata_ref_clk;
+
+/* AHCI module Initialization, if return 0, initialization is successful. */
+static int imx_sata_init(struct device *dev, void __iomem *addr)
+{
+	u32 tmpdata;
+	int ret = 0;
+	struct clk *clk;
+
+	sata_clk = clk_get(dev, "ahci");
+	if (IS_ERR(sata_clk)) {
+		dev_err(dev, "no sata clock.\n");
+		return PTR_ERR(sata_clk);
+	}
+	ret = clk_enable(sata_clk);
+	if (ret) {
+		dev_err(dev, "can't enable sata clock.\n");
+		goto put_sata_clk;
+	}
+
+	/* Get the AHCI SATA PHY CLK */
+	sata_ref_clk = clk_get(dev, "ahci_phy");
+	if (IS_ERR(sata_ref_clk)) {
+		dev_err(dev, "no sata ref clock.\n");
+		ret = PTR_ERR(sata_ref_clk);
+		goto release_sata_clk;
+	}
+	ret = clk_enable(sata_ref_clk);
+	if (ret) {
+		dev_err(dev, "can't enable sata ref clock.\n");
+		goto put_sata_ref_clk;
+	}
+
+	/* Get the AHB clock rate, and configure the TIMER1MS reg later */
+	clk = clk_get(dev, "ahci_dma");
+	if (IS_ERR(clk)) {
+		dev_err(dev, "no dma clock.\n");
+		ret = PTR_ERR(clk);
+		goto release_sata_ref_clk;
+	}
+	tmpdata = clk_get_rate(clk) / 1000;
+	clk_put(clk);
+
+	writel(tmpdata, addr + HOST_TIMER1MS);
+
+	tmpdata = readl(addr + HOST_CAP);
+	if (!(tmpdata & HOST_CAP_SSS)) {
+		tmpdata |= HOST_CAP_SSS;
+		writel(tmpdata, addr + HOST_CAP);
+	}
+
+	if (!(readl(addr + HOST_PORTS_IMPL) & 0x1))
+		writel((readl(addr + HOST_PORTS_IMPL) | 0x1),
+			addr + HOST_PORTS_IMPL);
+
+	return 0;
+
+release_sata_ref_clk:
+	clk_disable(sata_ref_clk);
+put_sata_ref_clk:
+	clk_put(sata_ref_clk);
+release_sata_clk:
+	clk_disable(sata_clk);
+put_sata_clk:
+	clk_put(sata_clk);
+
+	return ret;
+}
+
+static void imx_sata_exit(struct device *dev)
+{
+	clk_disable(sata_ref_clk);
+	clk_put(sata_ref_clk);
+
+	clk_disable(sata_clk);
+	clk_put(sata_clk);
+
+}
+struct platform_device *__init imx_add_ahci_imx(
+		const struct imx_ahci_imx_data *data,
+		const struct ahci_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device_dmamask(data->devid, 0,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata),  DMA_BIT_MASK(32));
+}
+
+struct platform_device *__init imx53_add_ahci_imx(void)
+{
+	struct ahci_platform_data pdata = {
+		.init = imx_sata_init,
+		.exit = imx_sata_exit,
+	};
+
+	return imx_add_ahci_imx(&imx53_ahci_imx_data, &pdata);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c linux-libre-3.2-gnu/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,11 @@
 	imx_fsl_usb2_udc_data_entry_single(MX35);
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
+#ifdef CONFIG_SOC_IMX51
+const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data __initconst =
+	imx_fsl_usb2_udc_data_entry_single(MX51);
+#endif
+
 struct platform_device *__init imx_add_fsl_usb2_udc(
 		const struct imx_fsl_usb2_udc_data *data,
 		const struct fsl_usb2_platform_data *pdata)
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/devices/platform-imx-i2c.c linux-libre-3.2-gnu/arch/arm/plat-mxc/devices/platform-imx-i2c.c
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/devices/platform-imx-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/devices/platform-imx-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -85,6 +85,12 @@
 	imx_imx_i2c_data_entry(MX51, _id, _hwid, SZ_4K)
 	imx51_imx_i2c_data_entry(0, 1),
 	imx51_imx_i2c_data_entry(1, 2),
+	{
+		.id = 2,
+		.iobase = MX51_HSI2C_DMA_BASE_ADDR,
+		.iosize = SZ_16K,
+		.irq = MX51_INT_HS_I2C,
+	},
 };
 #endif /* ifdef CONFIG_SOC_IMX51 */
 
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/devices/platform-mxc-ehci.c linux-libre-3.2-gnu/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/devices/platform-mxc-ehci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/devices/platform-mxc-ehci.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,6 +49,15 @@
 	imx_mxc_ehci_data_entry_single(MX35, 1, HS);
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
+#ifdef CONFIG_SOC_IMX51
+const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data __initconst =
+	imx_mxc_ehci_data_entry_single(MX51, 0, OTG);
+const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[] __initconst = {
+	imx_mxc_ehci_data_entry_single(MX51, 1, HS1),
+	imx_mxc_ehci_data_entry_single(MX51, 2, HS2),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
 struct platform_device *__init imx_add_mxc_ehci(
 		const struct imx_mxc_ehci_data *data,
 		const struct mxc_usbh_platform_data *pdata)
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/devices/platform-pata_imx.c linux-libre-3.2-gnu/arch/arm/plat-mxc/devices/platform-pata_imx.c
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/devices/platform-pata_imx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/devices/platform-pata_imx.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,59 @@
+/*
+ * This program is free software; you can 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/devices-common.h>
+
+#define imx_pata_imx_data_entry_single(soc, _size)			\
+	{								\
+		.iobase = soc ## _ATA_BASE_ADDR,			\
+		.iosize = _size,					\
+		.irq = soc ## _INT_ATA,					\
+	}
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_pata_imx_data imx27_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX27, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_pata_imx_data imx31_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX31, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_pata_imx_data imx35_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX35, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_pata_imx_data imx51_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX51, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_pata_imx_data imx53_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX53, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
+struct platform_device *__init imx_add_pata_imx(
+		const struct imx_pata_imx_data *data)
+{
+	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 imx_add_platform_device("pata_imx", -1,
+			res, ARRAY_SIZE(res), NULL, 0);
+}
+
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/devices.c linux-libre-3.2-gnu/arch/arm/plat-mxc/devices.c
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,73 +23,6 @@
 #include <linux/platform_device.h>
 #include <mach/common.h>
 
-int __init mxc_register_device(struct platform_device *pdev, void *data)
-{
-	int ret;
-
-	pdev->dev.platform_data = data;
-
-	ret = platform_device_register(pdev);
-	if (ret)
-		pr_debug("Unable to register platform device '%s': %d\n",
-			 pdev->name, ret);
-
-	return ret;
-}
-
-struct platform_device *__init imx_add_platform_device_dmamask(
-		const char *name, int id,
-		const struct resource *res, unsigned int num_resources,
-		const void *data, size_t size_data, u64 dmamask)
-{
-	int ret = -ENOMEM;
-	struct platform_device *pdev;
-
-	pdev = platform_device_alloc(name, id);
-	if (!pdev)
-		goto err;
-
-	if (dmamask) {
-		/*
-		 * This memory isn't freed when the device is put,
-		 * I don't have a nice idea for that though.  Conceptually
-		 * dma_mask in struct device should not be a pointer.
-		 * See http://thread.gmane.org/gmane.linux.kernel.pci/9081
-		 */
-		pdev->dev.dma_mask =
-			kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
-		if (!pdev->dev.dma_mask)
-			/* ret is still -ENOMEM; */
-			goto err;
-
-		*pdev->dev.dma_mask = dmamask;
-		pdev->dev.coherent_dma_mask = dmamask;
-	}
-
-	if (res) {
-		ret = platform_device_add_resources(pdev, res, num_resources);
-		if (ret)
-			goto err;
-	}
-
-	if (data) {
-		ret = platform_device_add_data(pdev, data, size_data);
-		if (ret)
-			goto err;
-	}
-
-	ret = platform_device_add(pdev);
-	if (ret) {
-err:
-		if (dmamask)
-			kfree(pdev->dev.dma_mask);
-		platform_device_put(pdev);
-		return ERR_PTR(ret);
-	}
-
-	return pdev;
-}
-
 struct device mxc_aips_bus = {
 	.init_name	= "mxc_aips",
 	.parent		= &platform_bus,
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/gic.c linux-libre-3.2-gnu/arch/arm/plat-mxc/gic.c
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/gic.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/gic.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/io.h>
+#include <asm/exception.h>
+#include <asm/localtimer.h>
+#include <asm/hardware/gic.h>
+#ifdef CONFIG_SMP
+#include <asm/smp.h>
+#endif
+
+asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
+{
+	u32 irqstat, irqnr;
+
+	do {
+		irqstat = readl_relaxed(gic_cpu_base_addr + GIC_CPU_INTACK);
+		irqnr = irqstat & 0x3ff;
+		if (irqnr == 1023)
+			break;
+
+		if (irqnr > 15 && irqnr < 1021)
+			handle_IRQ(irqnr, regs);
+#ifdef CONFIG_SMP
+		else {
+			writel_relaxed(irqstat, gic_cpu_base_addr +
+						GIC_CPU_EOI);
+			handle_IPI(irqnr, regs);
+		}
+#endif
+	} while (1);
+}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/common.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/common.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/common.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 
 struct platform_device;
 struct clk;
+enum mxc_cpu_pwr_mode;
 
 extern void mx1_map_io(void);
 extern void mx21_map_io(void);
@@ -64,12 +65,72 @@
 			unsigned long ckih1, unsigned long ckih2);
 extern int mx53_clocks_init(unsigned long ckil, unsigned long osc,
 			unsigned long ckih1, unsigned long ckih2);
+extern int mx51_clocks_init_dt(void);
+extern int mx53_clocks_init_dt(void);
+extern int mx6q_clocks_init(void);
 extern struct platform_device *mxc_register_gpio(char *name, int id,
 	resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);
-extern int mxc_register_device(struct platform_device *pdev, void *data);
 extern void mxc_set_cpu_type(unsigned int type);
 extern void mxc_arch_reset_init(void __iomem *);
 extern void mx51_efikamx_reset(void);
 extern int mx53_revision(void);
 extern int mx53_display_revision(void);
+
+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 void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode);
+extern void imx_print_silicon_rev(const char *cpu, int srev);
+
+void avic_handle_irq(struct pt_regs *);
+void tzic_handle_irq(struct pt_regs *);
+void gic_handle_irq(struct pt_regs *);
+
+#define imx1_handle_irq avic_handle_irq
+#define imx21_handle_irq avic_handle_irq
+#define imx25_handle_irq avic_handle_irq
+#define imx27_handle_irq avic_handle_irq
+#define imx31_handle_irq avic_handle_irq
+#define imx35_handle_irq avic_handle_irq
+#define imx50_handle_irq tzic_handle_irq
+#define imx51_handle_irq tzic_handle_irq
+#define imx53_handle_irq tzic_handle_irq
+#define imx6q_handle_irq gic_handle_irq
+
+extern void imx_enable_cpu(int cpu, bool enable);
+extern void imx_set_cpu_jump(int cpu, void *jump_addr);
+#ifdef CONFIG_DEBUG_LL
+extern void imx_lluart_map_io(void);
+#else
+static inline void imx_lluart_map_io(void) {}
+#endif
+extern void v7_cpu_resume(void);
+extern u32 *pl310_get_save_ptr(void);
+#ifdef CONFIG_SMP
+extern void v7_secondary_startup(void);
+extern void imx_scu_map_io(void);
+extern void imx_smp_prepare(void);
+#else
+static inline void imx_scu_map_io(void) {}
+static inline void imx_smp_prepare(void) {}
+#endif
+extern void imx_enable_cpu(int cpu, bool enable);
+extern void imx_set_cpu_jump(int cpu, void *jump_addr);
+extern void imx_src_init(void);
+extern void imx_gpc_init(void);
+extern void imx_gpc_pre_suspend(void);
+extern void imx_gpc_post_resume(void);
+extern void imx51_babbage_common_init(void);
+extern void imx53_ard_common_init(void);
+extern void imx53_evk_common_init(void);
+extern void imx53_qsb_common_init(void);
+extern void imx53_smd_common_init(void);
+extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
+extern void imx6q_pm_init(void);
+extern void imx6q_clock_map_io(void);
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -12,49 +12,25 @@
  */
 #include <mach/hardware.h>
 
-#ifdef CONFIG_SOC_IMX1
+#ifdef CONFIG_DEBUG_IMX1_UART
 #define UART_PADDR	MX1_UART1_BASE_ADDR
-#endif
-
-#ifdef CONFIG_SOC_IMX25
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX25_UART)
 #define UART_PADDR	MX25_UART1_BASE_ADDR
-#endif
-
-#if defined(CONFIG_SOC_IMX21) || defined (CONFIG_SOC_IMX27)
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX21_IMX27_UART)
 #define UART_PADDR	MX2x_UART1_BASE_ADDR
-#endif
-
-#if defined(CONFIG_SOC_IMX31) || defined(CONFIG_SOC_IMX35)
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX31_IMX35_UART)
 #define UART_PADDR	MX3x_UART1_BASE_ADDR
-#endif
-
-#ifdef CONFIG_SOC_IMX51
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX51_UART)
 #define UART_PADDR	MX51_UART1_BASE_ADDR
-#endif
-
-/* iMX50/53 have same addresses, but not iMX51 */
-#if defined(CONFIG_SOC_IMX50) || defined(CONFIG_SOC_IMX53)
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX50_IMX53_UART)
 #define UART_PADDR	MX53_UART1_BASE_ADDR
+#elif defined (CONFIG_DEBUG_IMX6Q_UART)
+#define UART_PADDR	MX6Q_UART4_BASE_ADDR
 #endif
 
 #define UART_VADDR	IMX_IO_ADDRESS(UART_PADDR)
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		ldr	\rp, =UART_PADDR	@ physical
 		ldr	\rv, =UART_VADDR	@ virtual
 		.endm
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/devices-common.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/devices-common.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/devices-common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/devices-common.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,10 +14,22 @@
 extern struct device mxc_aips_bus;
 extern struct device mxc_ahb_bus;
 
-struct platform_device *imx_add_platform_device_dmamask(
+static inline struct platform_device *imx_add_platform_device_dmamask(
 		const char *name, int id,
 		const struct resource *res, unsigned int num_resources,
-		const void *data, size_t size_data, u64 dmamask);
+		const void *data, size_t size_data, u64 dmamask)
+{
+	struct platform_device_info pdevinfo = {
+		.name = name,
+		.id = id,
+		.res = res,
+		.num_res = num_resources,
+		.data = data,
+		.size_data = size_data,
+		.dma_mask = dmamask,
+	};
+	return platform_device_register_full(&pdevinfo);
+}
 
 static inline struct platform_device *imx_add_platform_device(
 		const char *name, int id,
@@ -251,6 +263,14 @@
 		const struct imx_mxc_nand_data *data,
 		const struct mxc_nand_platform_data *pdata);
 
+struct imx_pata_imx_data {
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_pata_imx(
+		const struct imx_pata_imx_data *data);
+
 struct imx_mxc_pwm_data {
 	int id;
 	resource_size_t iobase;
@@ -301,3 +321,13 @@
 struct platform_device *imx_add_imx_dma(void);
 struct platform_device *imx_add_imx_sdma(char *name,
 	resource_size_t iobase, int irq, struct sdma_platform_data *pdata);
+
+#include <linux/ahci_platform.h>
+struct imx_ahci_imx_data {
+	const char *devid;
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_ahci_imx(
+		const struct imx_ahci_imx_data *data,
+		const struct ahci_platform_data *pdata);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/entry-macro.S linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/entry-macro.S
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/entry-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/entry-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -9,72 +9,19 @@
  * published by the Free Software Foundation.
  */
 
-#include <mach/hardware.h>
-
-#define AVIC_NIMASK	0x04
+/* Unused, we use CONFIG_MULTI_IRQ_HANDLER */
 
-	@ this macro disables fast irq (not implemented)
 	.macro	disable_fiq
 	.endm
 
 	.macro  get_irqnr_preamble, base, tmp
-#ifndef CONFIG_MXC_TZIC
-	ldr	\base, =avic_base
-	ldr	\base, [\base]
-#ifdef CONFIG_MXC_IRQ_PRIOR
-	ldr	r4, [\base, #AVIC_NIMASK]
-#endif
-#elif defined CONFIG_MXC_TZIC
-	ldr	\base, =tzic_base
-	ldr	\base, [\base]
-#endif /* CONFIG_MXC_TZIC */
 	.endm
 
 	.macro  arch_ret_to_user, tmp1, tmp2
 	.endm
 
-	@ this macro checks which interrupt occurred
-	@ and returns its number in irqnr
-	@ 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
-	@ interrupt pending from AVIC_NIVECSR
-	ldr	\irqstat, [\base, #0x40]
-	@ Shift to get the decoded IRQ number, using ASR so
-	@ 'no interrupt pending' becomes 0xffffffff
-	mov	\irqnr, \irqstat, asr #16
-	@ set zero flag if IRQ + 1 == 0
-	adds	\tmp, \irqnr, #1
-#ifdef CONFIG_MXC_IRQ_PRIOR
-	bicne	\tmp, \irqstat, #0xFFFFFFE0
-	strne	\tmp, [\base, #AVIC_NIMASK]
-	streq	r4, [\base, #AVIC_NIMASK]
-#endif
-#elif defined CONFIG_MXC_TZIC
-	@ Load offset & priority of the highest priority
-	@ interrupt pending.
-	@ 0x080 is INTSEC0 register
-	@ 0xD80 is HIPND0 register
-	mov     \irqnr, #0
-1000:	add	\irqstat, \base, \irqnr, lsr #3
-	ldr	\tmp, [\irqstat, #0xd80]
-	ldr	\irqstat, [\irqstat, #0x080]
-	ands	\tmp, \tmp, \irqstat
-	bne	1001f
-	add	\irqnr, \irqnr, #32
-	cmp     \irqnr, #128
-	blo     1000b
-	b       2001f
-1001:	mov     \irqstat, #1
-1002:	tst     \tmp, \irqstat
-	bne     2002f
-	movs    \tmp, \tmp, lsr #1
-	addne   \irqnr, \irqnr, #1
-	bne     1002b
-2001:
-	mov  \irqnr, #0
-2002:
-	movs \irqnr, \irqnr
-#endif
+	.endm
+
+	.macro test_for_ipi, irqnr, irqstat, base, tmp
 	.endm
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/gpio.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/gpio.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,39 +1 @@
-/*
- * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, 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
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-#ifndef __ASM_ARCH_MXC_GPIO_H__
-#define __ASM_ARCH_MXC_GPIO_H__
-
-#include <linux/spinlock.h>
-#include <mach/hardware.h>
-#include <asm-generic/gpio.h>
-
-
-/* There's a off-by-one betweem the gpio bank number and the gpiochip */
-/* range e.g. GPIO_1_5 is gpio 5 under linux */
-#define IMX_GPIO_NR(bank, nr)		(((bank) - 1) * 32 + (nr))
-
-/* use gpiolib dispatchers */
-#define gpio_get_value		__gpio_get_value
-#define gpio_set_value		__gpio_set_value
-#define gpio_cansleep		__gpio_cansleep
-
-#define gpio_to_irq(gpio)	(MXC_GPIO_IRQ_START + (gpio))
-#define irq_to_gpio(irq)	((irq) - MXC_GPIO_IRQ_START)
-
-#endif
+/* empty */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/hardware.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/hardware.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/hardware.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/hardware.h	2012-01-04 18:55:44.000000000 -0500
@@ -81,11 +81,21 @@
  *	AIPS1	0x53f00000+0x100000	->	0xf5700000+0x100000
  *	AIPS2	0x63f00000+0x100000	->	0xf5300000+0x100000
  * mx51:
+ *	TZIC	0xe0000000+0x004000	->	0xf5000000+0x004000
  *	IRAM	0x1ffe0000+0x020000	->	0xf4fe0000+0x020000
- *	DEBUG	0x60000000+0x100000	->	0xf5000000+0x100000
  *	SPBA0	0x70000000+0x100000	->	0xf5400000+0x100000
  *	AIPS1	0x73f00000+0x100000	->	0xf5700000+0x100000
  *	AIPS2	0x83f00000+0x100000	->	0xf4300000+0x100000
+ * mx53:
+ *	TZIC	0x0fffc000+0x004000	->	0xf4bfc000+0x004000
+ *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
+ *	AIPS1	0x53f00000+0x100000	->	0xf5700000+0x100000
+ *	AIPS2	0x63f00000+0x100000	->	0xf5300000+0x100000
+ * mx6q:
+ *	SCU	0x00a00000+0x001000	->	0xf4000000+0x001000
+ *	CCM	0x020c4000+0x004000	->	0xf42c4000+0x004000
+ *	ANATOP	0x020c8000+0x001000	->	0xf42c8000+0x001000
+ *	UART4	0x021f0000+0x004000	->	0xf42f0000+0x004000
  */
 #define IMX_IO_P2V(x)	(						\
 			0xf4000000 +					\
@@ -97,6 +107,7 @@
 
 #include <mach/mxc.h>
 
+#include <mach/mx6q.h>
 #include <mach/mx50.h>
 #include <mach/mx51.h>
 #include <mach/mx53.h>
@@ -116,4 +127,10 @@
 	.type = _type,							\
 }
 
+/* There's a off-by-one betweem the gpio bank number and the gpiochip */
+/* range e.g. GPIO_1_5 is gpio 5 under linux */
+#define IMX_GPIO_NR(bank, nr)		(((bank) - 1) * 32 + (nr))
+
+#define IMX_GPIO_TO_IRQ(gpio)	(MXC_GPIO_IRQ_START + (gpio))
+
 #endif /* __ASM_ARCH_MXC_HARDWARE_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/i2c.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/i2c.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/i2c.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/i2c.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,14 +11,10 @@
 
 /**
  * struct imxi2c_platform_data - structure of platform data for MXC I2C driver
- * @init:	Initialise gpio's and other board specific things
- * @exit:	Free everything initialised by @init
  * @bitrate:	Bus speed measured in Hz
  *
  **/
 struct imxi2c_platform_data {
-	int (*init)(struct device *dev);
-	void (*exit)(struct device *dev);
 	int bitrate;
 };
 
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/io.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/io.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,32 +14,22 @@
 /* Allow IO space to be anywhere in the memory */
 #define IO_SPACE_LIMIT 0xffffffff
 
-#if defined(CONFIG_SOC_IMX31) || defined(CONFIG_SOC_IMX35)
-#include <mach/hardware.h>
-
 #define __arch_ioremap __imx_ioremap
 #define __arch_iounmap __iounmap
 
 #define addr_in_module(addr, mod) \
 	((unsigned long)(addr) - mod ## _BASE_ADDR < mod ## _SIZE)
 
+extern void __iomem *(*imx_ioremap)(unsigned long, size_t, unsigned int);
+
 static inline void __iomem *
 __imx_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
 {
-	if (mtype == MT_DEVICE && (cpu_is_mx31() || cpu_is_mx35())) {
-		/*
-		 * Access all peripherals below 0x80000000 as nonshared device
-		 * on mx3, but leave l2cc alone.  Otherwise cache corruptions
-		 * can occur.
-		 */
-		if (phys_addr < 0x80000000 &&
-				!addr_in_module(phys_addr, MX3x_L2CC))
-			mtype = MT_DEVICE_NONSHARED;
-	}
-
-	return __arm_ioremap(phys_addr, size, mtype);
+	if (imx_ioremap != NULL)
+		return imx_ioremap(phys_addr, size, mtype);
+	else
+		return __arm_ioremap(phys_addr, size, mtype);
 }
-#endif
 
 /* io address mapping macro */
 #define __io(a)		__typesafe_io(a)
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/iomux-mx3.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/iomux-mx3.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/iomux-mx3.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/iomux-mx3.h	2012-01-04 18:55:44.000000000 -0500
@@ -735,6 +735,7 @@
 #define MX31_PIN_KEY_COL5_KEY_COL5	IOMUX_MODE(MX31_PIN_KEY_COL5, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_KEY_COL6_KEY_COL6	IOMUX_MODE(MX31_PIN_KEY_COL6, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_KEY_COL7_KEY_COL7	IOMUX_MODE(MX31_PIN_KEY_COL7, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_WATCHDOG_RST__WATCHDOG_RST	IOMUX_MODE(MX31_PIN_WATCHDOG_RST, IOMUX_CONFIG_FUNC)
 
 
 /*
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/iomux-mx51.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/iomux-mx51.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/iomux-mx51.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/iomux-mx51.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,8 @@
 #define __MACH_IOMUX_MX51_H__
 
 #include <mach/iomux-v3.h>
+#define __NA_	0x000
+
 
 /* Pad control groupings */
 #define MX51_UART_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_DSE_HIGH | \
@@ -47,1521 +49,765 @@
 
 /* Raw pin modes without pad control */
 /*							  PAD    MUX ALT INPSE PATH PADCTRL */
-#define _MX51_PAD_EIM_D16__AUD4_RXFS		IOMUX_PAD(0x3f0, 0x5c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D16__AUD5_TXD		IOMUX_PAD(0x3f0, 0x5c, 7, 0x08d8, 0, 0)
-#define _MX51_PAD_EIM_D16__EIM_D16		IOMUX_PAD(0x3f0, 0x5c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D16__GPIO2_0		IOMUX_PAD(0x3f0, 0x5c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D16__I2C1_SDA		IOMUX_PAD(0x3f0, 0x5c, 0x14, 0x09b4, 0, 0)
-#define _MX51_PAD_EIM_D16__UART2_CTS		IOMUX_PAD(0x3f0, 0x5c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D16__USBH2_DATA0		IOMUX_PAD(0x3f0, 0x5c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D17__AUD5_RXD		IOMUX_PAD(0x3f4, 0x60, 7, 0x08d4, 0, 0)
-#define _MX51_PAD_EIM_D17__EIM_D17		IOMUX_PAD(0x3f4, 0x60, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D17__GPIO2_1		IOMUX_PAD(0x3f4, 0x60, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D17__UART2_RXD		IOMUX_PAD(0x3f4, 0x60, 3, 0x09ec, 0, 0)
-#define _MX51_PAD_EIM_D17__UART3_CTS		IOMUX_PAD(0x3f4, 0x60, 4, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D17__USBH2_DATA1		IOMUX_PAD(0x3f4, 0x60, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D18__AUD5_TXC		IOMUX_PAD(0x3f8, 0x64, 7, 0x08e4, 0, 0)
-#define _MX51_PAD_EIM_D18__EIM_D18		IOMUX_PAD(0x3f8, 0x64, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D18__GPIO2_2		IOMUX_PAD(0x3f8, 0x64, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D18__UART2_TXD		IOMUX_PAD(0x3f8, 0x64, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D18__UART3_RTS		IOMUX_PAD(0x3f8, 0x64, 4, 0x09f0, 1, 0)
-#define _MX51_PAD_EIM_D18__USBH2_DATA2		IOMUX_PAD(0x3f8, 0x64, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D19__AUD4_RXC		IOMUX_PAD(0x3fc, 0x68, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D19__AUD5_TXFS		IOMUX_PAD(0x3fc, 0x68, 7, 0x08e8, 0, 0)
-#define _MX51_PAD_EIM_D19__EIM_D19		IOMUX_PAD(0x3fc, 0x68, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D19__GPIO2_3		IOMUX_PAD(0x3fc, 0x68, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D19__I2C1_SCL		IOMUX_PAD(0x3fc, 0x68, 0x14, 0x09b0, 0, 0)
-#define _MX51_PAD_EIM_D19__UART2_RTS		IOMUX_PAD(0x3fc, 0x68, 3, 0x09e8, 1, 0)
-#define _MX51_PAD_EIM_D19__USBH2_DATA3		IOMUX_PAD(0x3fc, 0x68, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D20__AUD4_TXD		IOMUX_PAD(0x400, 0x6c, 5, 0x08c8, 0, 0)
-#define _MX51_PAD_EIM_D20__EIM_D20		IOMUX_PAD(0x400, 0x6c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D20__GPIO2_4		IOMUX_PAD(0x400, 0x6c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D20__SRTC_ALARM_DEB	IOMUX_PAD(0x400, 0x6c, 4, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D20__USBH2_DATA4		IOMUX_PAD(0x400, 0x6c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D21__AUD4_RXD		IOMUX_PAD(0x404, 0x70, 5, 0x08c4, 0, 0)
-#define _MX51_PAD_EIM_D21__EIM_D21		IOMUX_PAD(0x404, 0x70, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D21__GPIO2_5		IOMUX_PAD(0x404, 0x70, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D21__SRTC_ALARM_DEB	IOMUX_PAD(0x404, 0x70, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D21__USBH2_DATA5		IOMUX_PAD(0x404, 0x70, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D22__AUD4_TXC		IOMUX_PAD(0x408, 0x74, 5, 0x08cc, 0, 0)
-#define _MX51_PAD_EIM_D22__EIM_D22		IOMUX_PAD(0x408, 0x74, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D22__GPIO2_6		IOMUX_PAD(0x408, 0x74, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D22__USBH2_DATA6		IOMUX_PAD(0x408, 0x74, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D23__AUD4_TXFS		IOMUX_PAD(0x40c, 0x78, 5, 0x08d0, 0, 0)
-#define _MX51_PAD_EIM_D23__EIM_D23		IOMUX_PAD(0x40c, 0x78, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D23__GPIO2_7		IOMUX_PAD(0x40c, 0x78, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D23__SPDIF_OUT1		IOMUX_PAD(0x40c, 0x78, 4, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D23__USBH2_DATA7		IOMUX_PAD(0x40c, 0x78, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D24__AUD6_RXFS		IOMUX_PAD(0x410, 0x7c, 5, 0x08f8, 0, 0)
-#define _MX51_PAD_EIM_D24__EIM_D24		IOMUX_PAD(0x410, 0x7c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D24__GPIO2_8		IOMUX_PAD(0x410, 0x7c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D24__I2C2_SDA		IOMUX_PAD(0x410, 0x7c, 0x14, 0x09bc, 0, 0)
-#define _MX51_PAD_EIM_D24__UART3_CTS		IOMUX_PAD(0x410, 0x7c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D24__USBOTG_DATA0		IOMUX_PAD(0x410, 0x7c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D25__EIM_D25		IOMUX_PAD(0x414, 0x80, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D25__KEY_COL6		IOMUX_PAD(0x414, 0x80, 1, 0x09c8, 0, 0)
-#define _MX51_PAD_EIM_D25__UART2_CTS		IOMUX_PAD(0x414, 0x80, 4, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D25__UART3_RXD		IOMUX_PAD(0x414, 0x80, 3, 0x09f4, 0, 0)
-#define _MX51_PAD_EIM_D25__USBOTG_DATA1		IOMUX_PAD(0x414, 0x80, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D26__EIM_D26		IOMUX_PAD(0x418, 0x84, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D26__KEY_COL7		IOMUX_PAD(0x418, 0x84, 1, 0x09cc, 0, 0)
-#define _MX51_PAD_EIM_D26__UART2_RTS		IOMUX_PAD(0x418, 0x84, 4, 0x09e8, 3, 0)
-#define _MX51_PAD_EIM_D26__UART3_TXD		IOMUX_PAD(0x418, 0x84, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D26__USBOTG_DATA2		IOMUX_PAD(0x418, 0x84, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D27__AUD6_RXC		IOMUX_PAD(0x41c, 0x88, 5, 0x08f4, 0, 0)
-#define _MX51_PAD_EIM_D27__EIM_D27		IOMUX_PAD(0x41c, 0x88, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D27__GPIO2_9		IOMUX_PAD(0x41c, 0x88, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D27__I2C2_SCL		IOMUX_PAD(0x41c, 0x88, 0x14, 0x09b8, 0, 0)
-#define _MX51_PAD_EIM_D27__UART3_RTS		IOMUX_PAD(0x41c, 0x88, 3, 0x09f0, 3, 0)
-#define _MX51_PAD_EIM_D27__USBOTG_DATA3		IOMUX_PAD(0x41c, 0x88, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D28__AUD6_TXD		IOMUX_PAD(0x420, 0x8c, 5, 0x08f0, 0, 0)
-#define _MX51_PAD_EIM_D28__EIM_D28		IOMUX_PAD(0x420, 0x8c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D28__KEY_ROW4		IOMUX_PAD(0x420, 0x8c, 1, 0x09d0, 0, 0)
-#define _MX51_PAD_EIM_D28__USBOTG_DATA4		IOMUX_PAD(0x420, 0x8c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D29__AUD6_RXD		IOMUX_PAD(0x424, 0x90, 5, 0x08ec, 0, 0)
-#define _MX51_PAD_EIM_D29__EIM_D29		IOMUX_PAD(0x424, 0x90, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D29__KEY_ROW5		IOMUX_PAD(0x424, 0x90, 1, 0x09d4, 0, 0)
-#define _MX51_PAD_EIM_D29__USBOTG_DATA5		IOMUX_PAD(0x424, 0x90, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D30__AUD6_TXC		IOMUX_PAD(0x428, 0x94, 5, 0x08fc, 0, 0)
-#define _MX51_PAD_EIM_D30__EIM_D30		IOMUX_PAD(0x428, 0x94, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D30__KEY_ROW6		IOMUX_PAD(0x428, 0x94, 1, 0x09d8, 0, 0)
-#define _MX51_PAD_EIM_D30__USBOTG_DATA6		IOMUX_PAD(0x428, 0x94, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D31__AUD6_TXFS		IOMUX_PAD(0x42c, 0x98, 5, 0x0900, 0, 0)
-#define _MX51_PAD_EIM_D31__EIM_D31		IOMUX_PAD(0x42c, 0x98, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D31__KEY_ROW7		IOMUX_PAD(0x42c, 0x98, 1, 0x09dc, 0, 0)
-#define _MX51_PAD_EIM_D31__USBOTG_DATA7		IOMUX_PAD(0x42c, 0x98, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A16__EIM_A16		IOMUX_PAD(0x430, 0x9c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A16__GPIO2_10		IOMUX_PAD(0x430, 0x9c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A16__OSC_FREQ_SEL0	IOMUX_PAD(0x430, 0x9c, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A17__EIM_A17		IOMUX_PAD(0x434, 0xa0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A17__GPIO2_11		IOMUX_PAD(0x434, 0xa0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A17__OSC_FREQ_SEL1	IOMUX_PAD(0x434, 0xa0, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A18__BOOT_LPB0		IOMUX_PAD(0x438, 0xa4, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A18__EIM_A18		IOMUX_PAD(0x438, 0xa4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A18__GPIO2_12		IOMUX_PAD(0x438, 0xa4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A19__BOOT_LPB1		IOMUX_PAD(0x43c, 0xa8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A19__EIM_A19		IOMUX_PAD(0x43c, 0xa8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A19__GPIO2_13		IOMUX_PAD(0x43c, 0xa8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A20__BOOT_UART_SRC0	IOMUX_PAD(0x440, 0xac, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A20__EIM_A20		IOMUX_PAD(0x440, 0xac, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A20__GPIO2_14		IOMUX_PAD(0x440, 0xac, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A21__BOOT_UART_SRC1	IOMUX_PAD(0x444, 0xb0, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A21__EIM_A21		IOMUX_PAD(0x444, 0xb0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A21__GPIO2_15		IOMUX_PAD(0x444, 0xb0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A22__EIM_A22		IOMUX_PAD(0x448, 0xb4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A22__GPIO2_16		IOMUX_PAD(0x448, 0xb4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A23__BOOT_HPN_EN		IOMUX_PAD(0x44c, 0xb8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A23__EIM_A23		IOMUX_PAD(0x44c, 0xb8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A23__GPIO2_17		IOMUX_PAD(0x44c, 0xb8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A24__EIM_A24		IOMUX_PAD(0x450, 0xbc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A24__GPIO2_18		IOMUX_PAD(0x450, 0xbc, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A24__USBH2_CLK		IOMUX_PAD(0x450, 0xbc, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A25__DISP1_PIN4		IOMUX_PAD(0x454, 0xc0, 6, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A25__EIM_A25		IOMUX_PAD(0x454, 0xc0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A25__GPIO2_19		IOMUX_PAD(0x454, 0xc0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A25__USBH2_DIR		IOMUX_PAD(0x454, 0xc0, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A26__CSI1_DATA_EN		IOMUX_PAD(0x458, 0xc4, 5, 0x09a0, 0, 0)
-#define _MX51_PAD_EIM_A26__DISP2_EXT_CLK	IOMUX_PAD(0x458, 0xc4, 6, 0x0908, 0, 0)
-#define _MX51_PAD_EIM_A26__EIM_A26		IOMUX_PAD(0x458, 0xc4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A26__GPIO2_20		IOMUX_PAD(0x458, 0xc4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A26__USBH2_STP		IOMUX_PAD(0x458, 0xc4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A27__CSI2_DATA_EN		IOMUX_PAD(0x45c, 0xc8, 5, 0x099c, 0, 0)
-#define _MX51_PAD_EIM_A27__DISP1_PIN1		IOMUX_PAD(0x45c, 0xc8, 6, 0x09a4, 0, 0)
-#define _MX51_PAD_EIM_A27__EIM_A27		IOMUX_PAD(0x45c, 0xc8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A27__GPIO2_21		IOMUX_PAD(0x45c, 0xc8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A27__USBH2_NXT		IOMUX_PAD(0x45c, 0xc8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB0__EIM_EB0		IOMUX_PAD(0x460, 0xcc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB1__EIM_EB1		IOMUX_PAD(0x464, 0xd0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB2__AUD5_RXFS		IOMUX_PAD(0x468, 0xd4, 6, 0x08e0, 0, 0)
-#define _MX51_PAD_EIM_EB2__CSI1_D2		IOMUX_PAD(0x468, 0xd4, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB2__EIM_EB2		IOMUX_PAD(0x468, 0xd4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB2__FEC_MDIO		IOMUX_PAD(0x468, 0xd4, 3, 0x0954, 0, 0)
-#define _MX51_PAD_EIM_EB2__GPIO2_22		IOMUX_PAD(0x468, 0xd4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB2__GPT_CMPOUT1		IOMUX_PAD(0x468, 0xd4, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB3__AUD5_RXC		IOMUX_PAD(0x46c, 0xd8, 6, 0x08dc, 0, 0)
-#define _MX51_PAD_EIM_EB3__CSI1_D3		IOMUX_PAD(0x46c, 0xd8, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB3__EIM_EB3		IOMUX_PAD(0x46c, 0xd8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB3__FEC_RDATA1		IOMUX_PAD(0x46c, 0xd8, 3, 0x095c, 0, 0)
-#define _MX51_PAD_EIM_EB3__GPIO2_23		IOMUX_PAD(0x46c, 0xd8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB3__GPT_CMPOUT2		IOMUX_PAD(0x46c, 0xd8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_OE__EIM_OE		IOMUX_PAD(0x470, 0xdc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_OE__GPIO2_24		IOMUX_PAD(0x470, 0xdc, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS0__EIM_CS0		IOMUX_PAD(0x474, 0xe0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS0__GPIO2_25		IOMUX_PAD(0x474, 0xe0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS1__EIM_CS1		IOMUX_PAD(0x478, 0xe4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS1__GPIO2_26		IOMUX_PAD(0x478, 0xe4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS2__AUD5_TXD		IOMUX_PAD(0x47c, 0xe8, 6, 0x08d8, 1, 0)
-#define _MX51_PAD_EIM_CS2__CSI1_D4		IOMUX_PAD(0x47c, 0xe8, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS2__EIM_CS2		IOMUX_PAD(0x47c, 0xe8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS2__FEC_RDATA2		IOMUX_PAD(0x47c, 0xe8, 3, 0x0960, 0, 0)
-#define _MX51_PAD_EIM_CS2__GPIO2_27		IOMUX_PAD(0x47c, 0xe8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS2__USBOTG_STP		IOMUX_PAD(0x47c, 0xe8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS3__AUD5_RXD		IOMUX_PAD(0x480, 0xec, 6, 0x08d4, 1, 0)
-#define _MX51_PAD_EIM_CS3__CSI1_D5		IOMUX_PAD(0x480, 0xec, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS3__EIM_CS3		IOMUX_PAD(0x480, 0xec, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS3__FEC_RDATA3		IOMUX_PAD(0x480, 0xec, 3, 0x0964, 0, 0)
-#define _MX51_PAD_EIM_CS3__GPIO2_28		IOMUX_PAD(0x480, 0xec, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS3__USBOTG_NXT		IOMUX_PAD(0x480, 0xec, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS4__AUD5_TXC		IOMUX_PAD(0x484, 0xf0, 6, 0x08e4, 1, 0)
-#define _MX51_PAD_EIM_CS4__CSI1_D6		IOMUX_PAD(0x484, 0xf0, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS4__EIM_CS4		IOMUX_PAD(0x484, 0xf0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS4__FEC_RX_ER		IOMUX_PAD(0x484, 0xf0, 3, 0x0970, 0, 0)
-#define _MX51_PAD_EIM_CS4__GPIO2_29		IOMUX_PAD(0x484, 0xf0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS4__USBOTG_CLK		IOMUX_PAD(0x484, 0xf0, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS5__AUD5_TXFS		IOMUX_PAD(0x488, 0xf4, 6, 0x08e8, 1, 0)
-#define _MX51_PAD_EIM_CS5__CSI1_D7		IOMUX_PAD(0x488, 0xf4, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS5__DISP1_EXT_CLK	IOMUX_PAD(0x488, 0xf4, 4, 0x0904, 0, 0)
-#define _MX51_PAD_EIM_CS5__EIM_CS5		IOMUX_PAD(0x488, 0xf4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS5__FEC_CRS		IOMUX_PAD(0x488, 0xf4, 3, 0x0950, 0, 0)
-#define _MX51_PAD_EIM_CS5__GPIO2_30		IOMUX_PAD(0x488, 0xf4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS5__USBOTG_DIR		IOMUX_PAD(0x488, 0xf4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DTACK__EIM_DTACK		IOMUX_PAD(0x48c, 0xf8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DTACK__GPIO2_31		IOMUX_PAD(0x48c, 0xf8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_LBA__EIM_LBA		IOMUX_PAD(0x494, 0xfc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_LBA__GPIO3_1		IOMUX_PAD(0x494, 0xfc, 1, 0x0978, 0, 0)
-#define _MX51_PAD_EIM_CRE__EIM_CRE		IOMUX_PAD(0x4a0, 0x100, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CRE__GPIO3_2		IOMUX_PAD(0x4a0, 0x100, 1, 0x097c, 0, 0)
-#define _MX51_PAD_DRAM_CS1__DRAM_CS1		IOMUX_PAD(0x4d0, 0x104, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WE_B__GPIO3_3		IOMUX_PAD(0x4e4, 0x108, 3, 0x0980, 0, 0)
-#define _MX51_PAD_NANDF_WE_B__NANDF_WE_B	IOMUX_PAD(0x4e4, 0x108, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WE_B__PATA_DIOW		IOMUX_PAD(0x4e4, 0x108, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WE_B__SD3_DATA0		IOMUX_PAD(0x4e4, 0x108, 2, 0x093c, 0, 0)
-#define _MX51_PAD_NANDF_RE_B__GPIO3_4		IOMUX_PAD(0x4e8, 0x10c, 3, 0x0984, 0, 0)
-#define _MX51_PAD_NANDF_RE_B__NANDF_RE_B	IOMUX_PAD(0x4e8, 0x10c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RE_B__PATA_DIOR		IOMUX_PAD(0x4e8, 0x10c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RE_B__SD3_DATA1		IOMUX_PAD(0x4e8, 0x10c, 2, 0x0940, 0, 0)
-#define _MX51_PAD_NANDF_ALE__GPIO3_5		IOMUX_PAD(0x4ec, 0x110, 3, 0x0988, 0, 0)
-#define _MX51_PAD_NANDF_ALE__NANDF_ALE		IOMUX_PAD(0x4ec, 0x110, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_ALE__PATA_BUFFER_EN	IOMUX_PAD(0x4ec, 0x110, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CLE__GPIO3_6		IOMUX_PAD(0x4f0, 0x114, 3, 0x098c, 0, 0)
-#define _MX51_PAD_NANDF_CLE__NANDF_CLE		IOMUX_PAD(0x4f0, 0x114, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CLE__PATA_RESET_B	IOMUX_PAD(0x4f0, 0x114, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WP_B__GPIO3_7		IOMUX_PAD(0x4f4, 0x118, 3, 0x0990, 0, 0)
-#define _MX51_PAD_NANDF_WP_B__NANDF_WP_B	IOMUX_PAD(0x4f4, 0x118, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WP_B__PATA_DMACK	IOMUX_PAD(0x4f4, 0x118, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WP_B__SD3_DATA2		IOMUX_PAD(0x4f4, 0x118, 2, 0x0944, 0, 0)
-#define _MX51_PAD_NANDF_RB0__ECSPI2_SS1		IOMUX_PAD(0x4f8, 0x11c, 5, 0x0930, 0, 0)
-#define _MX51_PAD_NANDF_RB0__GPIO3_8		IOMUX_PAD(0x4f8, 0x11c, 3, 0x0994, 0, 0)
-#define _MX51_PAD_NANDF_RB0__NANDF_RB0		IOMUX_PAD(0x4f8, 0x11c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB0__PATA_DMARQ		IOMUX_PAD(0x4f8, 0x11c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB0__SD3_DATA3		IOMUX_PAD(0x4f8, 0x11c, 2, 0x0948, 0, 0)
-#define _MX51_PAD_NANDF_RB1__CSPI_MOSI		IOMUX_PAD(0x4fc, 0x120, 6, 0x091c, 0, 0)
-#define _MX51_PAD_NANDF_RB1__ECSPI2_RDY		IOMUX_PAD(0x4fc, 0x120, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB1__GPIO3_9		IOMUX_PAD(0x4fc, 0x120, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB1__NANDF_RB1		IOMUX_PAD(0x4fc, 0x120, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB1__PATA_IORDY		IOMUX_PAD(0x4fc, 0x120, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB1__SD4_CMD		IOMUX_PAD(0x4fc, 0x120, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__DISP2_WAIT		IOMUX_PAD(0x500, 0x124, 5, 0x09a8, 0, 0)
-#define _MX51_PAD_NANDF_RB2__ECSPI2_SCLK	IOMUX_PAD(0x500, 0x124, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__FEC_COL		IOMUX_PAD(0x500, 0x124, 1, 0x094c, 0, 0)
-#define _MX51_PAD_NANDF_RB2__GPIO3_10		IOMUX_PAD(0x500, 0x124, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__NANDF_RB2		IOMUX_PAD(0x500, 0x124, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__USBH3_H3_DP	IOMUX_PAD(0x500, 0x124, 7, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__USBH3_NXT		IOMUX_PAD(0x500, 0x124, 6, 0x0a20, 0, 0)
-#define _MX51_PAD_NANDF_RB3__DISP1_WAIT		IOMUX_PAD(0x504, 0x128, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB3__ECSPI2_MISO	IOMUX_PAD(0x504, 0x128, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB3__FEC_RX_CLK		IOMUX_PAD(0x504, 0x128, 1, 0x0968, 0, 0)
-#define _MX51_PAD_NANDF_RB3__GPIO3_11		IOMUX_PAD(0x504, 0x128, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB3__NANDF_RB3		IOMUX_PAD(0x504, 0x128, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB3__USBH3_CLK		IOMUX_PAD(0x504, 0x128, 6, 0x09f8, 0, 0)
-#define _MX51_PAD_NANDF_RB3__USBH3_H3_DM	IOMUX_PAD(0x504, 0x128, 7, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO_NAND__GPIO_NAND		IOMUX_PAD(0x514, 0x12c, 0, 0x0998, 0, 0)
-#define _MX51_PAD_GPIO_NAND__PATA_INTRQ		IOMUX_PAD(0x514, 0x12c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS0__GPIO3_16		IOMUX_PAD(0x518, 0x130, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS0__NANDF_CS0		IOMUX_PAD(0x518, 0x130, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS1__GPIO3_17		IOMUX_PAD(0x51c, 0x134, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS1__NANDF_CS1		IOMUX_PAD(0x51c, 0x134, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__CSPI_SCLK		IOMUX_PAD(0x520, 0x138, 6, 0x0914, 0, 0)
-#define _MX51_PAD_NANDF_CS2__FEC_TX_ER		IOMUX_PAD(0x520, 0x138, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__GPIO3_18		IOMUX_PAD(0x520, 0x138, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__NANDF_CS2		IOMUX_PAD(0x520, 0x138, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__PATA_CS_0		IOMUX_PAD(0x520, 0x138, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__SD4_CLK		IOMUX_PAD(0x520, 0x138, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__USBH3_H1_DP	IOMUX_PAD(0x520, 0x138, 7, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__FEC_MDC		IOMUX_PAD(0x524, 0x13c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__GPIO3_19		IOMUX_PAD(0x524, 0x13c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__NANDF_CS3		IOMUX_PAD(0x524, 0x13c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__PATA_CS_1		IOMUX_PAD(0x524, 0x13c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__SD4_DAT0		IOMUX_PAD(0x524, 0x13c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__USBH3_H1_DM	IOMUX_PAD(0x524, 0x13c, 7, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__FEC_TDATA1		IOMUX_PAD(0x528, 0x140, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__GPIO3_20		IOMUX_PAD(0x528, 0x140, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__NANDF_CS4		IOMUX_PAD(0x528, 0x140, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__PATA_DA_0		IOMUX_PAD(0x528, 0x140, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__SD4_DAT1		IOMUX_PAD(0x528, 0x140, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__USBH3_STP		IOMUX_PAD(0x528, 0x140, 7, 0x0a24, 0, 0)
-#define _MX51_PAD_NANDF_CS5__FEC_TDATA2		IOMUX_PAD(0x52c, 0x144, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__GPIO3_21		IOMUX_PAD(0x52c, 0x144, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__NANDF_CS5		IOMUX_PAD(0x52c, 0x144, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__PATA_DA_1		IOMUX_PAD(0x52c, 0x144, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__SD4_DAT2		IOMUX_PAD(0x52c, 0x144, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__USBH3_DIR		IOMUX_PAD(0x52c, 0x144, 7, 0x0a1c, 0, 0)
-#define _MX51_PAD_NANDF_CS6__CSPI_SS3		IOMUX_PAD(0x530, 0x148, 7, 0x0928, 0, 0)
-#define _MX51_PAD_NANDF_CS6__FEC_TDATA3		IOMUX_PAD(0x530, 0x148, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS6__GPIO3_22		IOMUX_PAD(0x530, 0x148, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS6__NANDF_CS6		IOMUX_PAD(0x530, 0x148, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS6__PATA_DA_2		IOMUX_PAD(0x530, 0x148, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS6__SD4_DAT3		IOMUX_PAD(0x530, 0x148, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS7__FEC_TX_EN		IOMUX_PAD(0x534, 0x14c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS7__GPIO3_23		IOMUX_PAD(0x534, 0x14c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS7__NANDF_CS7		IOMUX_PAD(0x534, 0x14c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS7__SD3_CLK		IOMUX_PAD(0x534, 0x14c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0	IOMUX_PAD(0x538, 0x150, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK	IOMUX_PAD(0x538, 0x150, 1, 0x0974, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__GPIO3_24	IOMUX_PAD(0x538, 0x150, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT	IOMUX_PAD(0x538, 0x150, 0, 0x0938, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__SD3_CMD	IOMUX_PAD(0x538, 0x150, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__ECSPI2_MOSI	IOMUX_PAD(0x53c, 0x154, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__GPIO3_25		IOMUX_PAD(0x53c, 0x154, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__NANDF_D15		IOMUX_PAD(0x53c, 0x154, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__PATA_DATA15	IOMUX_PAD(0x53c, 0x154, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__SD3_DAT7		IOMUX_PAD(0x53c, 0x154, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D14__ECSPI2_SS3		IOMUX_PAD(0x540, 0x158, 2, 0x0934, 0, 0)
-#define _MX51_PAD_NANDF_D14__GPIO3_26		IOMUX_PAD(0x540, 0x158, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D14__NANDF_D14		IOMUX_PAD(0x540, 0x158, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D14__PATA_DATA14	IOMUX_PAD(0x540, 0x158, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D14__SD3_DAT6		IOMUX_PAD(0x540, 0x158, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__ECSPI2_SS2		IOMUX_PAD(0x544, 0x15c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__GPIO3_27		IOMUX_PAD(0x544, 0x15c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__NANDF_D13		IOMUX_PAD(0x544, 0x15c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__PATA_DATA13	IOMUX_PAD(0x544, 0x15c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__SD3_DAT5		IOMUX_PAD(0x544, 0x15c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D12__ECSPI2_SS1		IOMUX_PAD(0x548, 0x160, 2, 0x0930, 1, 0)
-#define _MX51_PAD_NANDF_D12__GPIO3_28		IOMUX_PAD(0x548, 0x160, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D12__NANDF_D12		IOMUX_PAD(0x548, 0x160, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D12__PATA_DATA12	IOMUX_PAD(0x548, 0x160, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D12__SD3_DAT4		IOMUX_PAD(0x548, 0x160, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D11__FEC_RX_DV		IOMUX_PAD(0x54c, 0x164, 2, 0x096c, 0, 0)
-#define _MX51_PAD_NANDF_D11__GPIO3_29		IOMUX_PAD(0x54c, 0x164, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D11__NANDF_D11		IOMUX_PAD(0x54c, 0x164, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D11__PATA_DATA11	IOMUX_PAD(0x54c, 0x164, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D11__SD3_DATA3		IOMUX_PAD(0x54c, 0x164, 5, 0x0948, 1, 0)
-#define _MX51_PAD_NANDF_D10__GPIO3_30		IOMUX_PAD(0x550, 0x168, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D10__NANDF_D10		IOMUX_PAD(0x550, 0x168, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D10__PATA_DATA10	IOMUX_PAD(0x550, 0x168, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D10__SD3_DATA2		IOMUX_PAD(0x550, 0x168, 5, 0x0944, 1, 0)
-#define _MX51_PAD_NANDF_D9__FEC_RDATA0		IOMUX_PAD(0x554, 0x16c, 0x12, 0x0958, 0, 0)
-#define _MX51_PAD_NANDF_D9__GPIO3_31		IOMUX_PAD(0x554, 0x16c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D9__NANDF_D9		IOMUX_PAD(0x554, 0x16c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D9__PATA_DATA9		IOMUX_PAD(0x554, 0x16c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D9__SD3_DATA1		IOMUX_PAD(0x554, 0x16c, 5, 0x0940, 1, 0)
-#define _MX51_PAD_NANDF_D8__FEC_TDATA0		IOMUX_PAD(0x558, 0x170, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D8__GPIO4_0		IOMUX_PAD(0x558, 0x170, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D8__NANDF_D8		IOMUX_PAD(0x558, 0x170, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D8__PATA_DATA8		IOMUX_PAD(0x558, 0x170, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D8__SD3_DATA0		IOMUX_PAD(0x558, 0x170, 5, 0x093c, 1, 0)
-#define _MX51_PAD_NANDF_D7__GPIO4_1		IOMUX_PAD(0x55c, 0x174, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D7__NANDF_D7		IOMUX_PAD(0x55c, 0x174, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D7__PATA_DATA7		IOMUX_PAD(0x55c, 0x174, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D7__USBH3_DATA0		IOMUX_PAD(0x55c, 0x174, 5, 0x09fc, 0, 0)
-#define _MX51_PAD_NANDF_D6__GPIO4_2		IOMUX_PAD(0x560, 0x178, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D6__NANDF_D6		IOMUX_PAD(0x560, 0x178, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D6__PATA_DATA6		IOMUX_PAD(0x560, 0x178, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D6__SD4_LCTL		IOMUX_PAD(0x560, 0x178, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D6__USBH3_DATA1		IOMUX_PAD(0x560, 0x178, 5, 0x0a00, 0, 0)
-#define _MX51_PAD_NANDF_D5__GPIO4_3		IOMUX_PAD(0x564, 0x17c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D5__NANDF_D5		IOMUX_PAD(0x564, 0x17c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D5__PATA_DATA5		IOMUX_PAD(0x564, 0x17c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D5__SD4_WP		IOMUX_PAD(0x564, 0x17c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D5__USBH3_DATA2		IOMUX_PAD(0x564, 0x17c, 5, 0x0a04, 0, 0)
-#define _MX51_PAD_NANDF_D4__GPIO4_4		IOMUX_PAD(0x568, 0x180, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D4__NANDF_D4		IOMUX_PAD(0x568, 0x180, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D4__PATA_DATA4		IOMUX_PAD(0x568, 0x180, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D4__SD4_CD		IOMUX_PAD(0x568, 0x180, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D4__USBH3_DATA3		IOMUX_PAD(0x568, 0x180, 5, 0x0a08, 0, 0)
-#define _MX51_PAD_NANDF_D3__GPIO4_5		IOMUX_PAD(0x56c, 0x184, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D3__NANDF_D3		IOMUX_PAD(0x56c, 0x184, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D3__PATA_DATA3		IOMUX_PAD(0x56c, 0x184, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D3__SD4_DAT4		IOMUX_PAD(0x56c, 0x184, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D3__USBH3_DATA4		IOMUX_PAD(0x56c, 0x184, 5, 0x0a0c, 0, 0)
-#define _MX51_PAD_NANDF_D2__GPIO4_6		IOMUX_PAD(0x570, 0x188, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D2__NANDF_D2		IOMUX_PAD(0x570, 0x188, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D2__PATA_DATA2		IOMUX_PAD(0x570, 0x188, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D2__SD4_DAT5		IOMUX_PAD(0x570, 0x188, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D2__USBH3_DATA5		IOMUX_PAD(0x570, 0x188, 5, 0x0a10, 0, 0)
-#define _MX51_PAD_NANDF_D1__GPIO4_7		IOMUX_PAD(0x574, 0x18c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D1__NANDF_D1		IOMUX_PAD(0x574, 0x18c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D1__PATA_DATA1		IOMUX_PAD(0x574, 0x18c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D1__SD4_DAT6		IOMUX_PAD(0x574, 0x18c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D1__USBH3_DATA6		IOMUX_PAD(0x574, 0x18c, 5, 0x0a14, 0, 0)
-#define _MX51_PAD_NANDF_D0__GPIO4_8		IOMUX_PAD(0x578, 0x190, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D0__NANDF_D0		IOMUX_PAD(0x578, 0x190, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D0__PATA_DATA0		IOMUX_PAD(0x578, 0x190, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D0__SD4_DAT7		IOMUX_PAD(0x578, 0x190, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D0__USBH3_DATA7		IOMUX_PAD(0x578, 0x190, 5, 0x0a18, 0, 0)
-#define _MX51_PAD_CSI1_D8__CSI1_D8		IOMUX_PAD(0x57c, 0x194, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D8__GPIO3_12		IOMUX_PAD(0x57c, 0x194, 3, 0x0998, 1, 0)
-#define _MX51_PAD_CSI1_D9__CSI1_D9		IOMUX_PAD(0x580, 0x198, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D9__GPIO3_13		IOMUX_PAD(0x580, 0x198, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D10__CSI1_D10		IOMUX_PAD(0x584, 0x19c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D11__CSI1_D11		IOMUX_PAD(0x588, 0x1a0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D12__CSI1_D12		IOMUX_PAD(0x58c, 0x1a4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D13__CSI1_D13		IOMUX_PAD(0x590, 0x1a8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D14__CSI1_D14		IOMUX_PAD(0x594, 0x1ac, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D15__CSI1_D15		IOMUX_PAD(0x598, 0x1b0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D16__CSI1_D16		IOMUX_PAD(0x59c, 0x1b4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D17__CSI1_D17		IOMUX_PAD(0x5a0, 0x1b8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D18__CSI1_D18		IOMUX_PAD(0x5a4, 0x1bc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D19__CSI1_D19		IOMUX_PAD(0x5a8, 0x1c0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_VSYNC__CSI1_VSYNC	IOMUX_PAD(0x5ac, 0x1c4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_VSYNC__GPIO3_14		IOMUX_PAD(0x5ac, 0x1c4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_HSYNC__CSI1_HSYNC	IOMUX_PAD(0x5b0, 0x1c8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_HSYNC__GPIO3_15		IOMUX_PAD(0x5b0, 0x1c8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK	IOMUX_PAD(0x5b4, 0x000, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_MCLK__CSI1_MCLK		IOMUX_PAD(0x5b8, 0x000, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D12__CSI2_D12		IOMUX_PAD(0x5bc, 0x1cc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D12__GPIO4_9		IOMUX_PAD(0x5bc, 0x1cc, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D13__CSI2_D13		IOMUX_PAD(0x5c0, 0x1d0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D13__GPIO4_10		IOMUX_PAD(0x5c0, 0x1d0, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D14__CSI2_D14		IOMUX_PAD(0x5c4, 0x1d4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D15__CSI2_D15		IOMUX_PAD(0x5c8, 0x1d8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D16__CSI2_D16		IOMUX_PAD(0x5cc, 0x1dc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D17__CSI2_D17		IOMUX_PAD(0x5d0, 0x1e0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D18__CSI2_D18		IOMUX_PAD(0x5d4, 0x1e4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D18__GPIO4_11		IOMUX_PAD(0x5d4, 0x1e4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D19__CSI2_D19		IOMUX_PAD(0x5d8, 0x1e8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D19__GPIO4_12		IOMUX_PAD(0x5d8, 0x1e8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_VSYNC__CSI2_VSYNC	IOMUX_PAD(0x5dc, 0x1ec, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_VSYNC__GPIO4_13		IOMUX_PAD(0x5dc, 0x1ec, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_HSYNC__CSI2_HSYNC	IOMUX_PAD(0x5e0, 0x1f0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_HSYNC__GPIO4_14		IOMUX_PAD(0x5e0, 0x1f0, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK	IOMUX_PAD(0x5e4, 0x1f4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_PIXCLK__GPIO4_15		IOMUX_PAD(0x5e4, 0x1f4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_I2C1_CLK__GPIO4_16		IOMUX_PAD(0x5e8, 0x1f8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_I2C1_CLK__I2C1_CLK		IOMUX_PAD(0x5e8, 0x1f8, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_I2C1_DAT__GPIO4_17		IOMUX_PAD(0x5ec, 0x1fc, 3, 0x0000, 0, 0)
-#define _MX51_PAD_I2C1_DAT__I2C1_DAT		IOMUX_PAD(0x5ec, 0x1fc, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_TXD__AUD3_TXD		IOMUX_PAD(0x5f0, 0x200, 0, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_TXD__GPIO4_18		IOMUX_PAD(0x5f0, 0x200, 3, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_RXD__AUD3_RXD		IOMUX_PAD(0x5f4, 0x204, 0, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_RXD__GPIO4_19		IOMUX_PAD(0x5f4, 0x204, 3, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_RXD__UART3_RXD	IOMUX_PAD(0x5f4, 0x204, 1, 0x09f4, 2, 0)
-#define _MX51_PAD_AUD3_BB_CK__AUD3_TXC		IOMUX_PAD(0x5f8, 0x208, 0, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_CK__GPIO4_20		IOMUX_PAD(0x5f8, 0x208, 3, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_FS__AUD3_TXFS		IOMUX_PAD(0x5fc, 0x20c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_FS__GPIO4_21		IOMUX_PAD(0x5fc, 0x20c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_FS__UART3_TXD		IOMUX_PAD(0x5fc, 0x20c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI	IOMUX_PAD(0x600, 0x210, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_MOSI__GPIO4_22		IOMUX_PAD(0x600, 0x210, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_MOSI__I2C1_SDA		IOMUX_PAD(0x600, 0x210, 0x11, 0x09b4, 1, 0)
-#define _MX51_PAD_CSPI1_MISO__AUD4_RXD		IOMUX_PAD(0x604, 0x214, 1, 0x08c4, 1, 0)
-#define _MX51_PAD_CSPI1_MISO__ECSPI1_MISO	IOMUX_PAD(0x604, 0x214, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_MISO__GPIO4_23		IOMUX_PAD(0x604, 0x214, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SS0__AUD4_TXC		IOMUX_PAD(0x608, 0x218, 1, 0x08cc, 1, 0)
-#define _MX51_PAD_CSPI1_SS0__ECSPI1_SS0		IOMUX_PAD(0x608, 0x218, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SS0__GPIO4_24		IOMUX_PAD(0x608, 0x218, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SS1__AUD4_TXD		IOMUX_PAD(0x60c, 0x21c, 1, 0x08c8, 1, 0)
-#define _MX51_PAD_CSPI1_SS1__ECSPI1_SS1		IOMUX_PAD(0x60c, 0x21c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SS1__GPIO4_25		IOMUX_PAD(0x60c, 0x21c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_RDY__AUD4_TXFS		IOMUX_PAD(0x610, 0x220, 1, 0x08d0, 1, 0)
-#define _MX51_PAD_CSPI1_RDY__ECSPI1_RDY		IOMUX_PAD(0x610, 0x220, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_RDY__GPIO4_26		IOMUX_PAD(0x610, 0x220, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK	IOMUX_PAD(0x614, 0x224, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SCLK__GPIO4_27		IOMUX_PAD(0x614, 0x224, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SCLK__I2C1_SCL		IOMUX_PAD(0x614, 0x224, 0x11, 0x09b0, 1, 0)
-#define _MX51_PAD_UART1_RXD__GPIO4_28		IOMUX_PAD(0x618, 0x228, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_RXD__UART1_RXD		IOMUX_PAD(0x618, 0x228, 0, 0x09e4, 0, 0)
-#define _MX51_PAD_UART1_TXD__GPIO4_29		IOMUX_PAD(0x61c, 0x22c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_TXD__PWM2_PWMO		IOMUX_PAD(0x61c, 0x22c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_TXD__UART1_TXD		IOMUX_PAD(0x61c, 0x22c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_RTS__GPIO4_30		IOMUX_PAD(0x620, 0x230, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_RTS__UART1_RTS		IOMUX_PAD(0x620, 0x230, 0, 0x09e0, 0, 0)
-#define _MX51_PAD_UART1_CTS__GPIO4_31		IOMUX_PAD(0x624, 0x234, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_CTS__UART1_CTS		IOMUX_PAD(0x624, 0x234, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_RXD__FIRI_TXD		IOMUX_PAD(0x628, 0x238, 1, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_RXD__GPIO1_20		IOMUX_PAD(0x628, 0x238, 3, 0x0000, 0, 0)
-#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, 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)
-#define _MX51_PAD_UART3_RXD__UART3_RXD		IOMUX_PAD(0x630, 0x240, 1, 0x09f4, 4, 0)
-#define _MX51_PAD_UART3_TXD__CSI1_D1		IOMUX_PAD(0x634, 0x244, 2, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_TXD__GPIO1_23		IOMUX_PAD(0x634, 0x244, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_TXD__UART1_DSR		IOMUX_PAD(0x634, 0x244, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_TXD__UART3_TXD		IOMUX_PAD(0x634, 0x244, 1, 0x0000, 0, 0)
-#define _MX51_PAD_OWIRE_LINE__GPIO1_24		IOMUX_PAD(0x638, 0x248, 3, 0x0000, 0, 0)
-#define _MX51_PAD_OWIRE_LINE__OWIRE_LINE	IOMUX_PAD(0x638, 0x248, 0, 0x0000, 0, 0)
-#define _MX51_PAD_OWIRE_LINE__SPDIF_OUT		IOMUX_PAD(0x638, 0x248, 6, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_ROW0__KEY_ROW0		IOMUX_PAD(0x63c, 0x24c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_ROW1__KEY_ROW1		IOMUX_PAD(0x640, 0x250, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_ROW2__KEY_ROW2		IOMUX_PAD(0x644, 0x254, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_ROW3__KEY_ROW3		IOMUX_PAD(0x648, 0x258, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL0__KEY_COL0		IOMUX_PAD(0x64c, 0x25c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL0__PLL1_BYP		IOMUX_PAD(0x64c, 0x25c, 7, 0x090c, 0, 0)
-#define _MX51_PAD_KEY_COL1__KEY_COL1		IOMUX_PAD(0x650, 0x260, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL1__PLL2_BYP		IOMUX_PAD(0x650, 0x260, 7, 0x0910, 0, 0)
-#define _MX51_PAD_KEY_COL2__KEY_COL2		IOMUX_PAD(0x654, 0x264, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL2__PLL3_BYP		IOMUX_PAD(0x654, 0x264, 7, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL3__KEY_COL3		IOMUX_PAD(0x658, 0x268, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL4__I2C2_SCL		IOMUX_PAD(0x65c, 0x26c, 0x13, 0x09b8, 1, 0)
-#define _MX51_PAD_KEY_COL4__KEY_COL4		IOMUX_PAD(0x65c, 0x26c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL4__SPDIF_OUT1		IOMUX_PAD(0x65c, 0x26c, 6, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL4__UART1_RI		IOMUX_PAD(0x65c, 0x26c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL4__UART3_RTS		IOMUX_PAD(0x65c, 0x26c, 2, 0x09f0, 4, 0)
-#define _MX51_PAD_KEY_COL5__I2C2_SDA		IOMUX_PAD(0x660, 0x270, 0x13, 0x09bc, 1, 0)
-#define _MX51_PAD_KEY_COL5__KEY_COL5		IOMUX_PAD(0x660, 0x270, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL5__UART1_DCD		IOMUX_PAD(0x660, 0x270, 1, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL5__UART3_CTS		IOMUX_PAD(0x660, 0x270, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_CLK__CSPI_SCLK		IOMUX_PAD(0x678, 0x278, 1, 0x0914, 1, 0)
-#define _MX51_PAD_USBH1_CLK__GPIO1_25		IOMUX_PAD(0x678, 0x278, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_CLK__I2C2_SCL		IOMUX_PAD(0x678, 0x278, 0x15, 0x09b8, 2, 0)
-#define _MX51_PAD_USBH1_CLK__USBH1_CLK		IOMUX_PAD(0x678, 0x278, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DIR__CSPI_MOSI		IOMUX_PAD(0x67c, 0x27c, 1, 0x091c, 1, 0)
-#define _MX51_PAD_USBH1_DIR__GPIO1_26		IOMUX_PAD(0x67c, 0x27c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DIR__I2C2_SDA		IOMUX_PAD(0x67c, 0x27c, 0x15, 0x09bc, 2, 0)
-#define _MX51_PAD_USBH1_DIR__USBH1_DIR		IOMUX_PAD(0x67c, 0x27c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_STP__CSPI_RDY		IOMUX_PAD(0x680, 0x280, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_STP__GPIO1_27		IOMUX_PAD(0x680, 0x280, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_STP__UART3_RXD		IOMUX_PAD(0x680, 0x280, 5, 0x09f4, 6, 0)
-#define _MX51_PAD_USBH1_STP__USBH1_STP		IOMUX_PAD(0x680, 0x280, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_NXT__CSPI_MISO		IOMUX_PAD(0x684, 0x284, 1, 0x0918, 0, 0)
-#define _MX51_PAD_USBH1_NXT__GPIO1_28		IOMUX_PAD(0x684, 0x284, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_NXT__UART3_TXD		IOMUX_PAD(0x684, 0x284, 5, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_NXT__USBH1_NXT		IOMUX_PAD(0x684, 0x284, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA0__GPIO1_11		IOMUX_PAD(0x688, 0x288, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA0__UART2_CTS	IOMUX_PAD(0x688, 0x288, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA0__USBH1_DATA0	IOMUX_PAD(0x688, 0x288, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA1__GPIO1_12		IOMUX_PAD(0x68c, 0x28c, 2, 0x0000, 0, 0)
-#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, 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)
-#define _MX51_PAD_USBH1_DATA3__USBH1_DATA3	IOMUX_PAD(0x694, 0x294, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA4__CSPI_SS0		IOMUX_PAD(0x698, 0x298, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA4__GPIO1_15		IOMUX_PAD(0x698, 0x298, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA4__USBH1_DATA4	IOMUX_PAD(0x698, 0x298, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA5__CSPI_SS1		IOMUX_PAD(0x69c, 0x29c, 1, 0x0920, 0, 0)
-#define _MX51_PAD_USBH1_DATA5__GPIO1_16		IOMUX_PAD(0x69c, 0x29c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA5__USBH1_DATA5	IOMUX_PAD(0x69c, 0x29c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA6__CSPI_SS3		IOMUX_PAD(0x6a0, 0x2a0, 1, 0x0928, 1, 0)
-#define _MX51_PAD_USBH1_DATA6__GPIO1_17		IOMUX_PAD(0x6a0, 0x2a0, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA6__USBH1_DATA6	IOMUX_PAD(0x6a0, 0x2a0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA7__ECSPI1_SS3	IOMUX_PAD(0x6a4, 0x2a4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA7__ECSPI2_SS3	IOMUX_PAD(0x6a4, 0x2a4, 5, 0x0934, 1, 0)
-#define _MX51_PAD_USBH1_DATA7__GPIO1_18		IOMUX_PAD(0x6a4, 0x2a4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA7__USBH1_DATA7	IOMUX_PAD(0x6a4, 0x2a4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN11__DI1_PIN11		IOMUX_PAD(0x6a8, 0x2a8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN11__ECSPI1_SS2		IOMUX_PAD(0x6a8, 0x2a8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN11__GPIO3_0		IOMUX_PAD(0x6a8, 0x2a8, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN12__DI1_PIN12		IOMUX_PAD(0x6ac, 0x2ac, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN12__GPIO3_1		IOMUX_PAD(0x6ac, 0x2ac, 4, 0x0978, 1, 0)
-#define _MX51_PAD_DI1_PIN13__DI1_PIN13		IOMUX_PAD(0x6b0, 0x2b0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN13__GPIO3_2		IOMUX_PAD(0x6b0, 0x2b0, 4, 0x097c, 1, 0)
-#define _MX51_PAD_DI1_D0_CS__DI1_D0_CS		IOMUX_PAD(0x6b4, 0x2b4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_D0_CS__GPIO3_3		IOMUX_PAD(0x6b4, 0x2b4, 4, 0x0980, 1, 0)
-#define _MX51_PAD_DI1_D1_CS__DI1_D1_CS		IOMUX_PAD(0x6b8, 0x2b8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_D1_CS__DISP1_PIN14	IOMUX_PAD(0x6b8, 0x2b8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_D1_CS__DISP1_PIN5		IOMUX_PAD(0x6b8, 0x2b8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_D1_CS__GPIO3_4		IOMUX_PAD(0x6b8, 0x2b8, 4, 0x0984, 1, 0)
-#define _MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1	IOMUX_PAD(0x6bc, 0x2bc, 2, 0x09a4, 1, 0)
-#define _MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN	IOMUX_PAD(0x6bc, 0x2bc, 0, 0x09c4, 0, 0)
-#define _MX51_PAD_DISPB2_SER_DIN__GPIO3_5	IOMUX_PAD(0x6bc, 0x2bc, 4, 0x0988, 1, 0)
-#define _MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6	IOMUX_PAD(0x6c0, 0x2c0, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO	IOMUX_PAD(0x6c0, 0x2c0, 0, 0x09c4, 1, 0)
-#define _MX51_PAD_DISPB2_SER_DIO__GPIO3_6	IOMUX_PAD(0x6c0, 0x2c0, 4, 0x098c, 1, 0)
-#define _MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17	IOMUX_PAD(0x6c4, 0x2c4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7	IOMUX_PAD(0x6c4, 0x2c4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK	IOMUX_PAD(0x6c4, 0x2c4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_CLK__GPIO3_7	IOMUX_PAD(0x6c4, 0x2c4, 4, 0x0990, 1, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK	IOMUX_PAD(0x6c8, 0x2c8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISP1_PIN16	IOMUX_PAD(0x6c8, 0x2c8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISP1_PIN8	IOMUX_PAD(0x6c8, 0x2c8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__GPIO3_8	IOMUX_PAD(0x6c8, 0x2c8, 4, 0x0994, 1, 0)
-#define _MX51_PAD_DISP1_DAT0__DISP1_DAT0	IOMUX_PAD(0x6cc, 0x2cc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT1__DISP1_DAT1	IOMUX_PAD(0x6d0, 0x2d0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT2__DISP1_DAT2	IOMUX_PAD(0x6d4, 0x2d4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT3__DISP1_DAT3	IOMUX_PAD(0x6d8, 0x2d8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT4__DISP1_DAT4	IOMUX_PAD(0x6dc, 0x2dc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT5__DISP1_DAT5	IOMUX_PAD(0x6e0, 0x2e0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT6__BOOT_USB_SRC	IOMUX_PAD(0x6e4, 0x2e4, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT6__DISP1_DAT6	IOMUX_PAD(0x6e4, 0x2e4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG	IOMUX_PAD(0x6e8, 0x2e8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT7__DISP1_DAT7	IOMUX_PAD(0x6e8, 0x2e8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT8__BOOT_SRC0		IOMUX_PAD(0x6ec, 0x2ec, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT8__DISP1_DAT8	IOMUX_PAD(0x6ec, 0x2ec, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT9__BOOT_SRC1		IOMUX_PAD(0x6f0, 0x2f0, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT9__DISP1_DAT9	IOMUX_PAD(0x6f0, 0x2f0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE	IOMUX_PAD(0x6f4, 0x2f4, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT10__DISP1_DAT10	IOMUX_PAD(0x6f4, 0x2f4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2	IOMUX_PAD(0x6f8, 0x2f8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT11__DISP1_DAT11	IOMUX_PAD(0x6f8, 0x2f8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL	IOMUX_PAD(0x6fc, 0x2fc, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT12__DISP1_DAT12	IOMUX_PAD(0x6fc, 0x2fc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0	IOMUX_PAD(0x700, 0x300, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT13__DISP1_DAT13	IOMUX_PAD(0x700, 0x300, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1	IOMUX_PAD(0x704, 0x304, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT14__DISP1_DAT14	IOMUX_PAD(0x704, 0x304, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH	IOMUX_PAD(0x708, 0x308, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT15__DISP1_DAT15	IOMUX_PAD(0x708, 0x308, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0	IOMUX_PAD(0x70c, 0x30c, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT16__DISP1_DAT16	IOMUX_PAD(0x70c, 0x30c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1	IOMUX_PAD(0x710, 0x310, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT17__DISP1_DAT17	IOMUX_PAD(0x710, 0x310, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0	IOMUX_PAD(0x714, 0x314, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT18__DISP1_DAT18	IOMUX_PAD(0x714, 0x314, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT18__DISP2_PIN11	IOMUX_PAD(0x714, 0x314, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT18__DISP2_PIN5	IOMUX_PAD(0x714, 0x314, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1	IOMUX_PAD(0x718, 0x318, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT19__DISP1_DAT19	IOMUX_PAD(0x718, 0x318, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT19__DISP2_PIN12	IOMUX_PAD(0x718, 0x318, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT19__DISP2_PIN6	IOMUX_PAD(0x718, 0x318, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0	IOMUX_PAD(0x71c, 0x31c, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT20__DISP1_DAT20	IOMUX_PAD(0x71c, 0x31c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT20__DISP2_PIN13	IOMUX_PAD(0x71c, 0x31c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT20__DISP2_PIN7	IOMUX_PAD(0x71c, 0x31c, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1	IOMUX_PAD(0x720, 0x320, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT21__DISP1_DAT21	IOMUX_PAD(0x720, 0x320, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT21__DISP2_PIN14	IOMUX_PAD(0x720, 0x320, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT21__DISP2_PIN8	IOMUX_PAD(0x720, 0x320, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0	IOMUX_PAD(0x724, 0x324, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT22__DISP1_DAT22	IOMUX_PAD(0x724, 0x324, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT22__DISP2_D0_CS	IOMUX_PAD(0x724, 0x324, 6, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT22__DISP2_DAT16	IOMUX_PAD(0x724, 0x324, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1	IOMUX_PAD(0x728, 0x328, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__DISP1_DAT23	IOMUX_PAD(0x728, 0x328, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__DISP2_D1_CS	IOMUX_PAD(0x728, 0x328, 6, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__DISP2_DAT17	IOMUX_PAD(0x728, 0x328, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__DISP2_SER_CS	IOMUX_PAD(0x728, 0x328, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN3__DI1_PIN3		IOMUX_PAD(0x72c, 0x32c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN2__DI1_PIN2		IOMUX_PAD(0x734, 0x330, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI_GP2__DISP1_SER_CLK		IOMUX_PAD(0x740, 0x338, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI_GP2__DISP2_WAIT		IOMUX_PAD(0x740, 0x338, 2, 0x09a8, 1, 0)
-#define _MX51_PAD_DI_GP3__CSI1_DATA_EN		IOMUX_PAD(0x744, 0x33c, 3, 0x09a0, 1, 0)
-#define _MX51_PAD_DI_GP3__DISP1_SER_DIO		IOMUX_PAD(0x744, 0x33c, 0, 0x09c0, 0, 0)
-#define _MX51_PAD_DI_GP3__FEC_TX_ER		IOMUX_PAD(0x744, 0x33c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN4__CSI2_DATA_EN	IOMUX_PAD(0x748, 0x340, 3, 0x099c, 1, 0)
-#define _MX51_PAD_DI2_PIN4__DI2_PIN4		IOMUX_PAD(0x748, 0x340, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN4__FEC_CRS		IOMUX_PAD(0x748, 0x340, 2, 0x0950, 1, 0)
-#define _MX51_PAD_DI2_PIN2__DI2_PIN2		IOMUX_PAD(0x74c, 0x344, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN2__FEC_MDC		IOMUX_PAD(0x74c, 0x344, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN3__DI2_PIN3		IOMUX_PAD(0x750, 0x348, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN3__FEC_MDIO		IOMUX_PAD(0x750, 0x348, 2, 0x0954, 1, 0)
-#define _MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK	IOMUX_PAD(0x754, 0x34c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_DISP_CLK__FEC_RDATA1	IOMUX_PAD(0x754, 0x34c, 2, 0x095c, 1, 0)
-#define _MX51_PAD_DI_GP4__DI2_PIN15		IOMUX_PAD(0x758, 0x350, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DI_GP4__DISP1_SER_DIN		IOMUX_PAD(0x758, 0x350, 0, 0x09c0, 1, 0)
-#define _MX51_PAD_DI_GP4__DISP2_PIN1		IOMUX_PAD(0x758, 0x350, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DI_GP4__FEC_RDATA2		IOMUX_PAD(0x758, 0x350, 2, 0x0960, 1, 0)
-#define _MX51_PAD_DISP2_DAT0__DISP2_DAT0	IOMUX_PAD(0x75c, 0x354, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT0__FEC_RDATA3	IOMUX_PAD(0x75c, 0x354, 2, 0x0964, 1, 0)
-#define _MX51_PAD_DISP2_DAT0__KEY_COL6		IOMUX_PAD(0x75c, 0x354, 4, 0x09c8, 1, 0)
-#define _MX51_PAD_DISP2_DAT0__UART3_RXD		IOMUX_PAD(0x75c, 0x354, 5, 0x09f4, 8, 0)
-#define _MX51_PAD_DISP2_DAT0__USBH3_CLK		IOMUX_PAD(0x75c, 0x354, 3, 0x09f8, 1, 0)
-#define _MX51_PAD_DISP2_DAT1__DISP2_DAT1	IOMUX_PAD(0x760, 0x358, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT1__FEC_RX_ER		IOMUX_PAD(0x760, 0x358, 2, 0x0970, 1, 0)
-#define _MX51_PAD_DISP2_DAT1__KEY_COL7		IOMUX_PAD(0x760, 0x358, 4, 0x09cc, 1, 0)
-#define _MX51_PAD_DISP2_DAT1__UART3_TXD		IOMUX_PAD(0x760, 0x358, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT1__USBH3_DIR		IOMUX_PAD(0x760, 0x358, 3, 0x0a1c, 1, 0)
-#define _MX51_PAD_DISP2_DAT2__DISP2_DAT2	IOMUX_PAD(0x764, 0x35c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT3__DISP2_DAT3	IOMUX_PAD(0x768, 0x360, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT4__DISP2_DAT4	IOMUX_PAD(0x76c, 0x364, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT5__DISP2_DAT5	IOMUX_PAD(0x770, 0x368, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT6__DISP2_DAT6	IOMUX_PAD(0x774, 0x36c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT6__FEC_TDATA1	IOMUX_PAD(0x774, 0x36c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT6__GPIO1_19		IOMUX_PAD(0x774, 0x36c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT6__KEY_ROW4		IOMUX_PAD(0x774, 0x36c, 4, 0x09d0, 1, 0)
-#define _MX51_PAD_DISP2_DAT6__USBH3_STP		IOMUX_PAD(0x774, 0x36c, 3, 0x0a24, 1, 0)
-#define _MX51_PAD_DISP2_DAT7__DISP2_DAT7	IOMUX_PAD(0x778, 0x370, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT7__FEC_TDATA2	IOMUX_PAD(0x778, 0x370, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT7__GPIO1_29		IOMUX_PAD(0x778, 0x370, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT7__KEY_ROW5		IOMUX_PAD(0x778, 0x370, 4, 0x09d4, 1, 0)
-#define _MX51_PAD_DISP2_DAT7__USBH3_NXT		IOMUX_PAD(0x778, 0x370, 3, 0x0a20, 1, 0)
-#define _MX51_PAD_DISP2_DAT8__DISP2_DAT8	IOMUX_PAD(0x77c, 0x374, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT8__FEC_TDATA3	IOMUX_PAD(0x77c, 0x374, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT8__GPIO1_30		IOMUX_PAD(0x77c, 0x374, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT8__KEY_ROW6		IOMUX_PAD(0x77c, 0x374, 4, 0x09d8, 1, 0)
-#define _MX51_PAD_DISP2_DAT8__USBH3_DATA0	IOMUX_PAD(0x77c, 0x374, 3, 0x09fc, 1, 0)
-#define _MX51_PAD_DISP2_DAT9__AUD6_RXC		IOMUX_PAD(0x780, 0x378, 4, 0x08f4, 1, 0)
-#define _MX51_PAD_DISP2_DAT9__DISP2_DAT9	IOMUX_PAD(0x780, 0x378, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT9__FEC_TX_EN		IOMUX_PAD(0x780, 0x378, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT9__GPIO1_31		IOMUX_PAD(0x780, 0x378, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT9__USBH3_DATA1	IOMUX_PAD(0x780, 0x378, 3, 0x0a00, 1, 0)
-#define _MX51_PAD_DISP2_DAT10__DISP2_DAT10	IOMUX_PAD(0x784, 0x37c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT10__DISP2_SER_CS	IOMUX_PAD(0x784, 0x37c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT10__FEC_COL		IOMUX_PAD(0x784, 0x37c, 2, 0x094c, 1, 0)
-#define _MX51_PAD_DISP2_DAT10__KEY_ROW7		IOMUX_PAD(0x784, 0x37c, 4, 0x09dc, 1, 0)
-#define _MX51_PAD_DISP2_DAT10__USBH3_DATA2	IOMUX_PAD(0x784, 0x37c, 3, 0x0a04, 1, 0)
-#define _MX51_PAD_DISP2_DAT11__AUD6_TXD		IOMUX_PAD(0x788, 0x380, 4, 0x08f0, 1, 0)
-#define _MX51_PAD_DISP2_DAT11__DISP2_DAT11	IOMUX_PAD(0x788, 0x380, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT11__FEC_RX_CLK	IOMUX_PAD(0x788, 0x380, 2, 0x0968, 1, 0)
-#define _MX51_PAD_DISP2_DAT11__GPIO1_10		IOMUX_PAD(0x788, 0x380, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT11__USBH3_DATA3	IOMUX_PAD(0x788, 0x380, 3, 0x0a08, 1, 0)
-#define _MX51_PAD_DISP2_DAT12__AUD6_RXD		IOMUX_PAD(0x78c, 0x384, 4, 0x08ec, 1, 0)
-#define _MX51_PAD_DISP2_DAT12__DISP2_DAT12	IOMUX_PAD(0x78c, 0x384, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT12__FEC_RX_DV	IOMUX_PAD(0x78c, 0x384, 2, 0x096c, 1, 0)
-#define _MX51_PAD_DISP2_DAT12__USBH3_DATA4	IOMUX_PAD(0x78c, 0x384, 3, 0x0a0c, 1, 0)
-#define _MX51_PAD_DISP2_DAT13__AUD6_TXC		IOMUX_PAD(0x790, 0x388, 4, 0x08fc, 1, 0)
-#define _MX51_PAD_DISP2_DAT13__DISP2_DAT13	IOMUX_PAD(0x790, 0x388, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT13__FEC_TX_CLK	IOMUX_PAD(0x790, 0x388, 2, 0x0974, 1, 0)
-#define _MX51_PAD_DISP2_DAT13__USBH3_DATA5	IOMUX_PAD(0x790, 0x388, 3, 0x0a10, 1, 0)
-#define _MX51_PAD_DISP2_DAT14__AUD6_TXFS	IOMUX_PAD(0x794, 0x38c, 4, 0x0900, 1, 0)
-#define _MX51_PAD_DISP2_DAT14__DISP2_DAT14	IOMUX_PAD(0x794, 0x38c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT14__FEC_RDATA0	IOMUX_PAD(0x794, 0x38c, 2, 0x0958, 1, 0)
-#define _MX51_PAD_DISP2_DAT14__USBH3_DATA6	IOMUX_PAD(0x794, 0x38c, 3, 0x0a14, 1, 0)
-#define _MX51_PAD_DISP2_DAT15__AUD6_RXFS	IOMUX_PAD(0x798, 0x390, 4, 0x08f8, 1, 0)
-#define _MX51_PAD_DISP2_DAT15__DISP1_SER_CS	IOMUX_PAD(0x798, 0x390, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT15__DISP2_DAT15	IOMUX_PAD(0x798, 0x390, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT15__FEC_TDATA0	IOMUX_PAD(0x798, 0x390, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT15__USBH3_DATA7	IOMUX_PAD(0x798, 0x390, 3, 0x0a18, 1, 0)
-#define _MX51_PAD_SD1_CMD__AUD5_RXFS		IOMUX_PAD(0x79c, 0x394, 1, 0x08e0, 1, 0)
-#define _MX51_PAD_SD1_CMD__CSPI_MOSI		IOMUX_PAD(0x79c, 0x394, 2, 0x091c, 2, 0)
-#define _MX51_PAD_SD1_CMD__SD1_CMD		IOMUX_PAD(0x79c, 0x394, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_CLK__AUD5_RXC		IOMUX_PAD(0x7a0, 0x398, 1, 0x08dc, 1, 0)
-#define _MX51_PAD_SD1_CLK__CSPI_SCLK		IOMUX_PAD(0x7a0, 0x398, 2, 0x0914, 2, 0)
-#define _MX51_PAD_SD1_CLK__SD1_CLK		IOMUX_PAD(0x7a0, 0x398, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_DATA0__AUD5_TXD		IOMUX_PAD(0x7a4, 0x39c, 1, 0x08d8, 2, 0)
-#define _MX51_PAD_SD1_DATA0__CSPI_MISO		IOMUX_PAD(0x7a4, 0x39c, 2, 0x0918, 1, 0)
-#define _MX51_PAD_SD1_DATA0__SD1_DATA0		IOMUX_PAD(0x7a4, 0x39c, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA0__EIM_DA0		IOMUX_PAD(0x000, 0x01c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA1__EIM_DA1		IOMUX_PAD(0x000, 0x020, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA2__EIM_DA2		IOMUX_PAD(0x000, 0x024, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA3__EIM_DA3		IOMUX_PAD(0x000, 0x028, 0, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_DATA1__AUD5_RXD		IOMUX_PAD(0x7a8, 0x3a0, 1, 0x08d4, 2, 0)
-#define _MX51_PAD_SD1_DATA1__SD1_DATA1		IOMUX_PAD(0x7a8, 0x3a0, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA4__EIM_DA4		IOMUX_PAD(0x000, 0x02c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA5__EIM_DA5		IOMUX_PAD(0x000, 0x030, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA6__EIM_DA6		IOMUX_PAD(0x000, 0x034, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA7__EIM_DA7		IOMUX_PAD(0x000, 0x038, 0, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_DATA2__AUD5_TXC		IOMUX_PAD(0x7ac, 0x3a4, 1, 0x08e4, 2, 0)
-#define _MX51_PAD_SD1_DATA2__SD1_DATA2		IOMUX_PAD(0x7ac, 0x3a4, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA10__EIM_DA10		IOMUX_PAD(0x000, 0x044, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA11__EIM_DA11		IOMUX_PAD(0x000, 0x048, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA8__EIM_DA8		IOMUX_PAD(0x000, 0x03c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA9__EIM_DA9		IOMUX_PAD(0x000, 0x040, 0, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_DATA3__AUD5_TXFS		IOMUX_PAD(0x7b0, 0x3a8, 1, 0x08e8, 2, 0)
-#define _MX51_PAD_SD1_DATA3__CSPI_SS1		IOMUX_PAD(0x7b0, 0x3a8, 2, 0x0920, 1, 0)
-#define _MX51_PAD_SD1_DATA3__SD1_DATA3		IOMUX_PAD(0x7b0, 0x3a8, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_0__CSPI_SS2		IOMUX_PAD(0x7b4, 0x3ac, 2, 0x0924, 0, 0)
-#define _MX51_PAD_GPIO1_0__GPIO1_0		IOMUX_PAD(0x7b4, 0x3ac, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_0__SD1_CD		IOMUX_PAD(0x7b4, 0x3ac, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_1__CSPI_MISO		IOMUX_PAD(0x7b8, 0x3b0, 2, 0x0918, 2, 0)
-#define _MX51_PAD_GPIO1_1__GPIO1_1		IOMUX_PAD(0x7b8, 0x3b0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_1__SD1_WP		IOMUX_PAD(0x7b8, 0x3b0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA12__EIM_DA12		IOMUX_PAD(0x000, 0x04c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA13__EIM_DA13		IOMUX_PAD(0x000, 0x050, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA14__EIM_DA14		IOMUX_PAD(0x000, 0x054, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA15__EIM_DA15		IOMUX_PAD(0x000, 0x058, 0, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_CMD__CSPI_MOSI		IOMUX_PAD(0x000, 0x3b4, 2, 0x091c, 3, 0)
-#define _MX51_PAD_SD2_CMD__I2C1_SCL		IOMUX_PAD(0x7bc, 0x3b4, 0x11, 0x09b0, 2, 0)
-#define _MX51_PAD_SD2_CMD__SD2_CMD		IOMUX_PAD(0x7bc, 0x3b4, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_CLK__CSPI_SCLK		IOMUX_PAD(0x7c0, 0x3b8, 2, 0x0914, 3, 0)
-#define _MX51_PAD_SD2_CLK__I2C1_SDA		IOMUX_PAD(0x7c0, 0x3b8, 0x11, 0x09b4, 2, 0)
-#define _MX51_PAD_SD2_CLK__SD2_CLK		IOMUX_PAD(0x7c0, 0x3b8, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA0__CSPI_MISO		IOMUX_PAD(0x7c4, 0x3bc, 2, 0x0918, 3, 0)
-#define _MX51_PAD_SD2_DATA0__SD1_DAT4		IOMUX_PAD(0x7c4, 0x3bc, 1, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA0__SD2_DATA0		IOMUX_PAD(0x7c4, 0x3bc, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA1__SD1_DAT5		IOMUX_PAD(0x7c8, 0x3c0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA1__SD2_DATA1		IOMUX_PAD(0x7c8, 0x3c0, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA1__USBH3_H2_DP	IOMUX_PAD(0x7c8, 0x3c0, 2, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA2__SD1_DAT6		IOMUX_PAD(0x7cc, 0x3c4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA2__SD2_DATA2		IOMUX_PAD(0x7cc, 0x3c4, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA2__USBH3_H2_DM	IOMUX_PAD(0x7cc, 0x3c4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA3__CSPI_SS2		IOMUX_PAD(0x7d0, 0x3c8, 2, 0x0924, 1, 0)
-#define _MX51_PAD_SD2_DATA3__SD1_DAT7		IOMUX_PAD(0x7d0, 0x3c8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA3__SD2_DATA3		IOMUX_PAD(0x7d0, 0x3c8, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_2__CCM_OUT_2		IOMUX_PAD(0x7d4, 0x3cc, 5, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_2__GPIO1_2		IOMUX_PAD(0x7d4, 0x3cc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_2__I2C2_SCL		IOMUX_PAD(0x7d4, 0x3cc, 0x12, 0x09b8, 3, 0)
-#define _MX51_PAD_GPIO1_2__PLL1_BYP		IOMUX_PAD(0x7d4, 0x3cc, 7, 0x090c, 1, 0)
-#define _MX51_PAD_GPIO1_2__PWM1_PWMO		IOMUX_PAD(0x7d4, 0x3cc, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_3__GPIO1_3		IOMUX_PAD(0x7d8, 0x3d0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_3__I2C2_SDA		IOMUX_PAD(0x7d8, 0x3d0, 0x12, 0x09bc, 3, 0)
-#define _MX51_PAD_GPIO1_3__PLL2_BYP		IOMUX_PAD(0x7d8, 0x3d0, 7, 0x0910, 1, 0)
-#define _MX51_PAD_GPIO1_3__PWM2_PWMO		IOMUX_PAD(0x7d8, 0x3d0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	IOMUX_PAD(0x7fc, 0x3d4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B	IOMUX_PAD(0x7fc, 0x3d4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_4__DISP2_EXT_CLK	IOMUX_PAD(0x804, 0x3d8, 4, 0x0908, 1, 0)
-#define _MX51_PAD_GPIO1_4__EIM_RDY		IOMUX_PAD(0x804, 0x3d8, 3, 0x0938, 1, 0)
-#define _MX51_PAD_GPIO1_4__GPIO1_4		IOMUX_PAD(0x804, 0x3d8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_4__WDOG1_WDOG_B		IOMUX_PAD(0x804, 0x3d8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_5__CSI2_MCLK		IOMUX_PAD(0x808, 0x3dc, 6, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_5__DISP2_PIN16		IOMUX_PAD(0x808, 0x3dc, 3, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_5__GPIO1_5		IOMUX_PAD(0x808, 0x3dc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_5__WDOG2_WDOG_B		IOMUX_PAD(0x808, 0x3dc, 2, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_6__DISP2_PIN17		IOMUX_PAD(0x80c, 0x3e0, 4, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_6__GPIO1_6		IOMUX_PAD(0x80c, 0x3e0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_6__REF_EN_B		IOMUX_PAD(0x80c, 0x3e0, 3, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_7__CCM_OUT_0		IOMUX_PAD(0x810, 0x3e4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_7__GPIO1_7		IOMUX_PAD(0x810, 0x3e4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_7__SD2_WP		IOMUX_PAD(0x810, 0x3e4, 6, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_7__SPDIF_OUT1		IOMUX_PAD(0x810, 0x3e4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_8__CSI2_DATA_EN		IOMUX_PAD(0x814, 0x3e8, 2, 0x099c, 2, 0)
-#define _MX51_PAD_GPIO1_8__GPIO1_8		IOMUX_PAD(0x814, 0x3e8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_8__SD2_CD		IOMUX_PAD(0x814, 0x3e8, 6, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_8__USBH3_PWR		IOMUX_PAD(0x814, 0x3e8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__CCM_OUT_1		IOMUX_PAD(0x818, 0x3ec, 3, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__DISP2_D1_CS		IOMUX_PAD(0x818, 0x3ec, 2, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__DISP2_SER_CS		IOMUX_PAD(0x818, 0x3ec, 7, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__GPIO1_9		IOMUX_PAD(0x818, 0x3ec, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__SD2_LCTL		IOMUX_PAD(0x818, 0x3ec, 6, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__USBH3_OC		IOMUX_PAD(0x818, 0x3ec, 1, 0x0000, 0, 0)
 
 /* The same pins as above but with the default pad control values applied */
-#define MX51_PAD_EIM_D16__AUD4_RXFS		(_MX51_PAD_EIM_D16__AUD4_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D16__AUD5_TXD		(_MX51_PAD_EIM_D16__AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D16__EIM_D16		(_MX51_PAD_EIM_D16__EIM_D16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D16__GPIO2_0		(_MX51_PAD_EIM_D16__GPIO2_0 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D16__I2C1_SDA		(_MX51_PAD_EIM_D16__I2C1_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_EIM_D16__UART2_CTS		(_MX51_PAD_EIM_D16__UART2_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D16__USBH2_DATA0		(_MX51_PAD_EIM_D16__USBH2_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D17__AUD5_RXD		(_MX51_PAD_EIM_D17__AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D17__EIM_D17		(_MX51_PAD_EIM_D17__EIM_D17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D17__GPIO2_1		(_MX51_PAD_EIM_D17__GPIO2_1 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D17__UART2_RXD		(_MX51_PAD_EIM_D17__UART2_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D17__UART3_CTS		(_MX51_PAD_EIM_D17__UART3_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D17__USBH2_DATA1		(_MX51_PAD_EIM_D17__USBH2_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D18__AUD5_TXC		(_MX51_PAD_EIM_D18__AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D18__EIM_D18		(_MX51_PAD_EIM_D18__EIM_D18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D18__GPIO2_2		(_MX51_PAD_EIM_D18__GPIO2_2 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D18__UART2_TXD		(_MX51_PAD_EIM_D18__UART2_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D18__UART3_RTS		(_MX51_PAD_EIM_D18__UART3_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D18__USBH2_DATA2		(_MX51_PAD_EIM_D18__USBH2_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__AUD4_RXC		(_MX51_PAD_EIM_D19__AUD4_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__AUD5_TXFS		(_MX51_PAD_EIM_D19__AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__EIM_D19		(_MX51_PAD_EIM_D19__EIM_D19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__GPIO2_3		(_MX51_PAD_EIM_D19__GPIO2_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__I2C1_SCL		(_MX51_PAD_EIM_D19__I2C1_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_EIM_D19__UART2_RTS		(_MX51_PAD_EIM_D19__UART2_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D19__USBH2_DATA3		(_MX51_PAD_EIM_D19__USBH2_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__AUD4_TXD		(_MX51_PAD_EIM_D20__AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__EIM_D20		(_MX51_PAD_EIM_D20__EIM_D20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__GPIO2_4		(_MX51_PAD_EIM_D20__GPIO2_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__SRTC_ALARM_DEB	(_MX51_PAD_EIM_D20__SRTC_ALARM_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__USBH2_DATA4		(_MX51_PAD_EIM_D20__USBH2_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__AUD4_RXD		(_MX51_PAD_EIM_D21__AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__EIM_D21		(_MX51_PAD_EIM_D21__EIM_D21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__GPIO2_5		(_MX51_PAD_EIM_D21__GPIO2_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__SRTC_ALARM_DEB	(_MX51_PAD_EIM_D21__SRTC_ALARM_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__USBH2_DATA5		(_MX51_PAD_EIM_D21__USBH2_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D22__AUD4_TXC		(_MX51_PAD_EIM_D22__AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D22__EIM_D22		(_MX51_PAD_EIM_D22__EIM_D22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D22__GPIO2_6		(_MX51_PAD_EIM_D22__GPIO2_6 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D22__USBH2_DATA6		(_MX51_PAD_EIM_D22__USBH2_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__AUD4_TXFS		(_MX51_PAD_EIM_D23__AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__EIM_D23		(_MX51_PAD_EIM_D23__EIM_D23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__GPIO2_7		(_MX51_PAD_EIM_D23__GPIO2_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__SPDIF_OUT1		(_MX51_PAD_EIM_D23__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__USBH2_DATA7		(_MX51_PAD_EIM_D23__USBH2_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D24__AUD6_RXFS		(_MX51_PAD_EIM_D24__AUD6_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D24__EIM_D24		(_MX51_PAD_EIM_D24__EIM_D24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D24__GPIO2_8		(_MX51_PAD_EIM_D24__GPIO2_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D24__I2C2_SDA		(_MX51_PAD_EIM_D24__I2C2_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_EIM_D24__UART3_CTS		(_MX51_PAD_EIM_D24__UART3_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D24__USBOTG_DATA0		(_MX51_PAD_EIM_D24__USBOTG_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D25__EIM_D25		(_MX51_PAD_EIM_D25__EIM_D25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D25__KEY_COL6		(_MX51_PAD_EIM_D25__KEY_COL6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D25__UART2_CTS		(_MX51_PAD_EIM_D25__UART2_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D25__UART3_RXD		(_MX51_PAD_EIM_D25__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D25__USBOTG_DATA1		(_MX51_PAD_EIM_D25__USBOTG_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D26__EIM_D26		(_MX51_PAD_EIM_D26__EIM_D26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D26__KEY_COL7		(_MX51_PAD_EIM_D26__KEY_COL7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D26__UART2_RTS		(_MX51_PAD_EIM_D26__UART2_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D26__UART3_TXD		(_MX51_PAD_EIM_D26__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D26__USBOTG_DATA2		(_MX51_PAD_EIM_D26__USBOTG_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D27__AUD6_RXC		(_MX51_PAD_EIM_D27__AUD6_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D27__EIM_D27		(_MX51_PAD_EIM_D27__EIM_D27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D27__GPIO2_9		(_MX51_PAD_EIM_D27__GPIO2_9 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D27__I2C2_SCL		(_MX51_PAD_EIM_D27__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_EIM_D27__UART3_RTS		(_MX51_PAD_EIM_D27__UART3_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D27__USBOTG_DATA3		(_MX51_PAD_EIM_D27__USBOTG_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D28__AUD6_TXD		(_MX51_PAD_EIM_D28__AUD6_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D28__EIM_D28		(_MX51_PAD_EIM_D28__EIM_D28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D28__KEY_ROW4		(_MX51_PAD_EIM_D28__KEY_ROW4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D28__USBOTG_DATA4		(_MX51_PAD_EIM_D28__USBOTG_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D29__AUD6_RXD		(_MX51_PAD_EIM_D29__AUD6_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D29__EIM_D29		(_MX51_PAD_EIM_D29__EIM_D29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D29__KEY_ROW5		(_MX51_PAD_EIM_D29__KEY_ROW5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D29__USBOTG_DATA5		(_MX51_PAD_EIM_D29__USBOTG_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D30__AUD6_TXC		(_MX51_PAD_EIM_D30__AUD6_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D30__EIM_D30		(_MX51_PAD_EIM_D30__EIM_D30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D30__KEY_ROW6		(_MX51_PAD_EIM_D30__KEY_ROW6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D30__USBOTG_DATA6		(_MX51_PAD_EIM_D30__USBOTG_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D31__AUD6_TXFS		(_MX51_PAD_EIM_D31__AUD6_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D31__EIM_D31		(_MX51_PAD_EIM_D31__EIM_D31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D31__KEY_ROW7		(_MX51_PAD_EIM_D31__KEY_ROW7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D31__USBOTG_DATA7		(_MX51_PAD_EIM_D31__USBOTG_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A16__EIM_A16		(_MX51_PAD_EIM_A16__EIM_A16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A16__GPIO2_10		(_MX51_PAD_EIM_A16__GPIO2_10 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A16__OSC_FREQ_SEL0		(_MX51_PAD_EIM_A16__OSC_FREQ_SEL0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A17__EIM_A17		(_MX51_PAD_EIM_A17__EIM_A17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A17__GPIO2_11		(_MX51_PAD_EIM_A17__GPIO2_11 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A17__OSC_FREQ_SEL1		(_MX51_PAD_EIM_A17__OSC_FREQ_SEL1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A18__BOOT_LPB0		(_MX51_PAD_EIM_A18__BOOT_LPB0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A18__EIM_A18		(_MX51_PAD_EIM_A18__EIM_A18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A18__GPIO2_12		(_MX51_PAD_EIM_A18__GPIO2_12 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A19__BOOT_LPB1		(_MX51_PAD_EIM_A19__BOOT_LPB1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A19__EIM_A19		(_MX51_PAD_EIM_A19__EIM_A19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A19__GPIO2_13		(_MX51_PAD_EIM_A19__GPIO2_13 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A20__BOOT_UART_SRC0	(_MX51_PAD_EIM_A20__BOOT_UART_SRC0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A20__EIM_A20		(_MX51_PAD_EIM_A20__EIM_A20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A20__GPIO2_14		(_MX51_PAD_EIM_A20__GPIO2_14 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A21__BOOT_UART_SRC1	(_MX51_PAD_EIM_A21__BOOT_UART_SRC1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A21__EIM_A21		(_MX51_PAD_EIM_A21__EIM_A21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A21__GPIO2_15		(_MX51_PAD_EIM_A21__GPIO2_15 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A22__EIM_A22		(_MX51_PAD_EIM_A22__EIM_A22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A22__GPIO2_16		(_MX51_PAD_EIM_A22__GPIO2_16 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A23__BOOT_HPN_EN		(_MX51_PAD_EIM_A23__BOOT_HPN_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A23__EIM_A23		(_MX51_PAD_EIM_A23__EIM_A23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A23__GPIO2_17		(_MX51_PAD_EIM_A23__GPIO2_17 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A24__EIM_A24		(_MX51_PAD_EIM_A24__EIM_A24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A24__GPIO2_18		(_MX51_PAD_EIM_A24__GPIO2_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A24__USBH2_CLK		(_MX51_PAD_EIM_A24__USBH2_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A25__DISP1_PIN4		(_MX51_PAD_EIM_A25__DISP1_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A25__EIM_A25		(_MX51_PAD_EIM_A25__EIM_A25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A25__GPIO2_19		(_MX51_PAD_EIM_A25__GPIO2_19 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A25__USBH2_DIR		(_MX51_PAD_EIM_A25__USBH2_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__CSI1_DATA_EN		(_MX51_PAD_EIM_A26__CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__DISP2_EXT_CLK		(_MX51_PAD_EIM_A26__DISP2_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__EIM_A26		(_MX51_PAD_EIM_A26__EIM_A26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__GPIO2_20		(_MX51_PAD_EIM_A26__GPIO2_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__USBH2_STP		(_MX51_PAD_EIM_A26__USBH2_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__CSI2_DATA_EN		(_MX51_PAD_EIM_A27__CSI2_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__DISP1_PIN1		(_MX51_PAD_EIM_A27__DISP1_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__EIM_A27		(_MX51_PAD_EIM_A27__EIM_A27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__GPIO2_21		(_MX51_PAD_EIM_A27__GPIO2_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__USBH2_NXT		(_MX51_PAD_EIM_A27__USBH2_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB0__EIM_EB0		(_MX51_PAD_EIM_EB0__EIM_EB0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB1__EIM_EB1		(_MX51_PAD_EIM_EB1__EIM_EB1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__AUD5_RXFS		(_MX51_PAD_EIM_EB2__AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__CSI1_D2		(_MX51_PAD_EIM_EB2__CSI1_D2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__EIM_EB2		(_MX51_PAD_EIM_EB2__EIM_EB2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__FEC_MDIO		(_MX51_PAD_EIM_EB2__FEC_MDIO | \
+#define MX51_PAD_EIM_D16__AUD4_RXFS		IOMUX_PAD(0x3f0, 0x05c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__AUD5_TXD		IOMUX_PAD(0x3f0, 0x05c, 7, 0x8d8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__EIM_D16		IOMUX_PAD(0x3f0, 0x05c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__GPIO2_0		IOMUX_PAD(0x3f0, 0x05c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__I2C1_SDA		IOMUX_PAD(0x3f0, 0x05c, 0x14, 0x9b4, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D16__UART2_CTS		IOMUX_PAD(0x3f0, 0x05c, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D16__USBH2_DATA0		IOMUX_PAD(0x3f0, 0x05c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__AUD5_RXD		IOMUX_PAD(0x3f4, 0x060, 7, 0x8d4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__EIM_D17		IOMUX_PAD(0x3f4, 0x060, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__GPIO2_1		IOMUX_PAD(0x3f4, 0x060, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__UART2_RXD		IOMUX_PAD(0x3f4, 0x060, 3, 0x9ec, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D17__UART3_CTS		IOMUX_PAD(0x3f4, 0x060, 4, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D17__USBH2_DATA1		IOMUX_PAD(0x3f4, 0x060, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__AUD5_TXC		IOMUX_PAD(0x3f8, 0x064, 7, 0x8e4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__EIM_D18		IOMUX_PAD(0x3f8, 0x064, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__GPIO2_2		IOMUX_PAD(0x3f8, 0x064, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__UART2_TXD		IOMUX_PAD(0x3f8, 0x064, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D18__UART3_RTS		IOMUX_PAD(0x3f8, 0x064, 4, 0x9f0, 1, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D18__USBH2_DATA2		IOMUX_PAD(0x3f8, 0x064, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__AUD4_RXC		IOMUX_PAD(0x3fc, 0x068, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__AUD5_TXFS		IOMUX_PAD(0x3fc, 0x068, 7, 0x8e8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__EIM_D19		IOMUX_PAD(0x3fc, 0x068, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__GPIO2_3		IOMUX_PAD(0x3fc, 0x068, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__I2C1_SCL		IOMUX_PAD(0x3fc, 0x068, 0x14, 0x9b0, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D19__UART2_RTS		IOMUX_PAD(0x3fc, 0x068, 3, 0x9e8, 1, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D19__USBH2_DATA3		IOMUX_PAD(0x3fc, 0x068, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__AUD4_TXD		IOMUX_PAD(0x400, 0x06c, 5, 0x8c8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__EIM_D20		IOMUX_PAD(0x400, 0x06c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__GPIO2_4		IOMUX_PAD(0x400, 0x06c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__SRTC_ALARM_DEB	IOMUX_PAD(0x400, 0x06c, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__USBH2_DATA4		IOMUX_PAD(0x400, 0x06c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__AUD4_RXD		IOMUX_PAD(0x404, 0x070, 5, 0x8c4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__EIM_D21		IOMUX_PAD(0x404, 0x070, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__GPIO2_5		IOMUX_PAD(0x404, 0x070, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__SRTC_ALARM_DEB	IOMUX_PAD(0x404, 0x070, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__USBH2_DATA5		IOMUX_PAD(0x404, 0x070, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__AUD4_TXC		IOMUX_PAD(0x408, 0x074, 5, 0x8cc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__EIM_D22		IOMUX_PAD(0x408, 0x074, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__GPIO2_6		IOMUX_PAD(0x408, 0x074, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__USBH2_DATA6		IOMUX_PAD(0x408, 0x074, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__AUD4_TXFS		IOMUX_PAD(0x40c, 0x078, 5, 0x8d0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__EIM_D23		IOMUX_PAD(0x40c, 0x078, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__GPIO2_7		IOMUX_PAD(0x40c, 0x078, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__SPDIF_OUT1		IOMUX_PAD(0x40c, 0x078, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__USBH2_DATA7		IOMUX_PAD(0x40c, 0x078, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__AUD6_RXFS		IOMUX_PAD(0x410, 0x07c, 5, 0x8f8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__EIM_D24		IOMUX_PAD(0x410, 0x07c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__GPIO2_8		IOMUX_PAD(0x410, 0x07c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__I2C2_SDA		IOMUX_PAD(0x410, 0x07c, 0x14, 0x9bc, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D24__UART3_CTS		IOMUX_PAD(0x410, 0x07c, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D24__USBOTG_DATA0		IOMUX_PAD(0x410, 0x07c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__EIM_D25		IOMUX_PAD(0x414, 0x080, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__KEY_COL6		IOMUX_PAD(0x414, 0x080, 1, 0x9c8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__UART2_CTS		IOMUX_PAD(0x414, 0x080, 4, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D25__UART3_RXD		IOMUX_PAD(0x414, 0x080, 3, 0x9f4, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D25__USBOTG_DATA1		IOMUX_PAD(0x414, 0x080, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__EIM_D26		IOMUX_PAD(0x418, 0x084, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__KEY_COL7		IOMUX_PAD(0x418, 0x084, 1, 0x9cc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__UART2_RTS		IOMUX_PAD(0x418, 0x084, 4, 0x9e8, 3, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D26__UART3_TXD		IOMUX_PAD(0x418, 0x084, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D26__USBOTG_DATA2		IOMUX_PAD(0x418, 0x084, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__AUD6_RXC		IOMUX_PAD(0x41c, 0x088, 5, 0x8f4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__EIM_D27		IOMUX_PAD(0x41c, 0x088, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__GPIO2_9		IOMUX_PAD(0x41c, 0x088, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__I2C2_SCL		IOMUX_PAD(0x41c, 0x088, 0x14, 0x9b8, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D27__UART3_RTS		IOMUX_PAD(0x41c, 0x088, 3, 0x9f0, 3, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D27__USBOTG_DATA3		IOMUX_PAD(0x41c, 0x088, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__AUD6_TXD		IOMUX_PAD(0x420, 0x08c, 5, 0x8f0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__EIM_D28		IOMUX_PAD(0x420, 0x08c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__KEY_ROW4		IOMUX_PAD(0x420, 0x08c, 1, 0x9d0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__USBOTG_DATA4		IOMUX_PAD(0x420, 0x08c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__AUD6_RXD		IOMUX_PAD(0x424, 0x090, 5, 0x8ec, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__EIM_D29		IOMUX_PAD(0x424, 0x090, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__KEY_ROW5		IOMUX_PAD(0x424, 0x090, 1, 0x9d4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__USBOTG_DATA5		IOMUX_PAD(0x424, 0x090, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__AUD6_TXC		IOMUX_PAD(0x428, 0x094, 5, 0x8fc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__EIM_D30		IOMUX_PAD(0x428, 0x094, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__KEY_ROW6		IOMUX_PAD(0x428, 0x094, 1, 0x9d8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__USBOTG_DATA6		IOMUX_PAD(0x428, 0x094, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__AUD6_TXFS		IOMUX_PAD(0x42c, 0x098, 5, 0x900, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__EIM_D31		IOMUX_PAD(0x42c, 0x098, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__KEY_ROW7		IOMUX_PAD(0x42c, 0x098, 1, 0x9dc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__USBOTG_DATA7		IOMUX_PAD(0x42c, 0x098, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A16__EIM_A16		IOMUX_PAD(0x430, 0x09c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A16__GPIO2_10		IOMUX_PAD(0x430, 0x09c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A16__OSC_FREQ_SEL0		IOMUX_PAD(0x430, 0x09c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A17__EIM_A17		IOMUX_PAD(0x434, 0x0a0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A17__GPIO2_11		IOMUX_PAD(0x434, 0x0a0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A17__OSC_FREQ_SEL1		IOMUX_PAD(0x434, 0x0a0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A18__BOOT_LPB0		IOMUX_PAD(0x438, 0x0a4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A18__EIM_A18		IOMUX_PAD(0x438, 0x0a4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A18__GPIO2_12		IOMUX_PAD(0x438, 0x0a4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A19__BOOT_LPB1		IOMUX_PAD(0x43c, 0x0a8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A19__EIM_A19		IOMUX_PAD(0x43c, 0x0a8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A19__GPIO2_13		IOMUX_PAD(0x43c, 0x0a8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A20__BOOT_UART_SRC0	IOMUX_PAD(0x440, 0x0ac, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A20__EIM_A20		IOMUX_PAD(0x440, 0x0ac, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A20__GPIO2_14		IOMUX_PAD(0x440, 0x0ac, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A21__BOOT_UART_SRC1	IOMUX_PAD(0x444, 0x0b0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A21__EIM_A21		IOMUX_PAD(0x444, 0x0b0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A21__GPIO2_15		IOMUX_PAD(0x444, 0x0b0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A22__EIM_A22		IOMUX_PAD(0x448, 0x0b4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A22__GPIO2_16		IOMUX_PAD(0x448, 0x0b4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A23__BOOT_HPN_EN		IOMUX_PAD(0x44c, 0x0b8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A23__EIM_A23		IOMUX_PAD(0x44c, 0x0b8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A23__GPIO2_17		IOMUX_PAD(0x44c, 0x0b8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A24__EIM_A24		IOMUX_PAD(0x450, 0x0bc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A24__GPIO2_18		IOMUX_PAD(0x450, 0x0bc, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A24__USBH2_CLK		IOMUX_PAD(0x450, 0x0bc, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__DISP1_PIN4		IOMUX_PAD(0x454, 0x0c0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__EIM_A25		IOMUX_PAD(0x454, 0x0c0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__GPIO2_19		IOMUX_PAD(0x454, 0x0c0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__USBH2_DIR		IOMUX_PAD(0x454, 0x0c0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__CSI1_DATA_EN		IOMUX_PAD(0x458, 0x0c4, 5, 0x9a0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__DISP2_EXT_CLK		IOMUX_PAD(0x458, 0x0c4, 6, 0x908, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__EIM_A26		IOMUX_PAD(0x458, 0x0c4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__GPIO2_20		IOMUX_PAD(0x458, 0x0c4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__USBH2_STP		IOMUX_PAD(0x458, 0x0c4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__CSI2_DATA_EN		IOMUX_PAD(0x45c, 0x0c8, 5, 0x99c, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__DISP1_PIN1		IOMUX_PAD(0x45c, 0x0c8, 6, 0x9a4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__EIM_A27		IOMUX_PAD(0x45c, 0x0c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__GPIO2_21		IOMUX_PAD(0x45c, 0x0c8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__USBH2_NXT		IOMUX_PAD(0x45c, 0x0c8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB0__EIM_EB0		IOMUX_PAD(0x460, 0x0cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB1__EIM_EB1		IOMUX_PAD(0x464, 0x0d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__AUD5_RXFS		IOMUX_PAD(0x468, 0x0d4, 6, 0x8e0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__CSI1_D2		IOMUX_PAD(0x468, 0x0d4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__EIM_EB2		IOMUX_PAD(0x468, 0x0d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__FEC_MDIO		(IOMUX_PAD(0x468, 0x0d4, 3, 0x954, 0, 0) | \
 		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 MX51_PAD_EIM_EB2__GPIO2_22		(_MX51_PAD_EIM_EB2__GPIO2_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__GPT_CMPOUT1		(_MX51_PAD_EIM_EB2__GPT_CMPOUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__AUD5_RXC		(_MX51_PAD_EIM_EB3__AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__CSI1_D3		(_MX51_PAD_EIM_EB3__CSI1_D3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__EIM_EB3		(_MX51_PAD_EIM_EB3__EIM_EB3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__FEC_RDATA1		(_MX51_PAD_EIM_EB3__FEC_RDATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__GPIO2_23		(_MX51_PAD_EIM_EB3__GPIO2_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__GPT_CMPOUT2		(_MX51_PAD_EIM_EB3__GPT_CMPOUT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_OE__EIM_OE			(_MX51_PAD_EIM_OE__EIM_OE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_OE__GPIO2_24		(_MX51_PAD_EIM_OE__GPIO2_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS0__EIM_CS0		(_MX51_PAD_EIM_CS0__EIM_CS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS0__GPIO2_25		(_MX51_PAD_EIM_CS0__GPIO2_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS1__EIM_CS1		(_MX51_PAD_EIM_CS1__EIM_CS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS1__GPIO2_26		(_MX51_PAD_EIM_CS1__GPIO2_26 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__AUD5_TXD		(_MX51_PAD_EIM_CS2__AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__CSI1_D4		(_MX51_PAD_EIM_CS2__CSI1_D4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__EIM_CS2		(_MX51_PAD_EIM_CS2__EIM_CS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__FEC_RDATA2		(_MX51_PAD_EIM_CS2__FEC_RDATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__GPIO2_27		(_MX51_PAD_EIM_CS2__GPIO2_27 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__USBOTG_STP		(_MX51_PAD_EIM_CS2__USBOTG_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__AUD5_RXD		(_MX51_PAD_EIM_CS3__AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__CSI1_D5		(_MX51_PAD_EIM_CS3__CSI1_D5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__EIM_CS3		(_MX51_PAD_EIM_CS3__EIM_CS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__FEC_RDATA3		(_MX51_PAD_EIM_CS3__FEC_RDATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__GPIO2_28		(_MX51_PAD_EIM_CS3__GPIO2_28 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__USBOTG_NXT		(_MX51_PAD_EIM_CS3__USBOTG_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__AUD5_TXC		(_MX51_PAD_EIM_CS4__AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__CSI1_D6		(_MX51_PAD_EIM_CS4__CSI1_D6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__EIM_CS4		(_MX51_PAD_EIM_CS4__EIM_CS4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__FEC_RX_ER		(_MX51_PAD_EIM_CS4__FEC_RX_ER | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
-#define MX51_PAD_EIM_CS4__GPIO2_29		(_MX51_PAD_EIM_CS4__GPIO2_29 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__USBOTG_CLK		(_MX51_PAD_EIM_CS4__USBOTG_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__AUD5_TXFS		(_MX51_PAD_EIM_CS5__AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__CSI1_D7		(_MX51_PAD_EIM_CS5__CSI1_D7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__DISP1_EXT_CLK		(_MX51_PAD_EIM_CS5__DISP1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__EIM_CS5		(_MX51_PAD_EIM_CS5__EIM_CS5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__FEC_CRS		(_MX51_PAD_EIM_CS5__FEC_CRS | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
-#define MX51_PAD_EIM_CS5__GPIO2_30		(_MX51_PAD_EIM_CS5__GPIO2_30 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__USBOTG_DIR		(_MX51_PAD_EIM_CS5__USBOTG_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DTACK__EIM_DTACK		(_MX51_PAD_EIM_DTACK__EIM_DTACK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DTACK__GPIO2_31		(_MX51_PAD_EIM_DTACK__GPIO2_31 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_LBA__EIM_LBA		(_MX51_PAD_EIM_LBA__EIM_LBA | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_LBA__GPIO3_1		(_MX51_PAD_EIM_LBA__GPIO3_1 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CRE__EIM_CRE		(_MX51_PAD_EIM_CRE__EIM_CRE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CRE__GPIO3_2		(_MX51_PAD_EIM_CRE__GPIO3_2 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DRAM_CS1__DRAM_CS1		(_MX51_PAD_DRAM_CS1__DRAM_CS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#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(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(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))
-#define MX51_PAD_NANDF_CLE__GPIO3_6		(_MX51_PAD_NANDF_CLE__GPIO3_6 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CLE__NANDF_CLE		(_MX51_PAD_NANDF_CLE__NANDF_CLE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CLE__PATA_RESET_B	(_MX51_PAD_NANDF_CLE__PATA_RESET_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#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(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(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(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))
-#define MX51_PAD_NANDF_RB2__GPIO3_10		(_MX51_PAD_NANDF_RB2__GPIO3_10 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__NANDF_RB2		(_MX51_PAD_NANDF_RB2__NANDF_RB2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__USBH3_H3_DP		(_MX51_PAD_NANDF_RB2__USBH3_H3_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__USBH3_NXT		(_MX51_PAD_NANDF_RB2__USBH3_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__DISP1_WAIT		(_MX51_PAD_NANDF_RB3__DISP1_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__ECSPI2_MISO		(_MX51_PAD_NANDF_RB3__ECSPI2_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__FEC_RX_CLK		(_MX51_PAD_NANDF_RB3__FEC_RX_CLK | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
-#define MX51_PAD_NANDF_RB3__GPIO3_11		(_MX51_PAD_NANDF_RB3__GPIO3_11 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__NANDF_RB3		(_MX51_PAD_NANDF_RB3__NANDF_RB3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__USBH3_CLK		(_MX51_PAD_NANDF_RB3__USBH3_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__USBH3_H3_DM		(_MX51_PAD_NANDF_RB3__USBH3_H3_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO_NAND__GPIO_NAND		(_MX51_PAD_GPIO_NAND__GPIO_NAND | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_GPIO_NAND__PATA_INTRQ		(_MX51_PAD_GPIO_NAND__PATA_INTRQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS0__GPIO3_16		(_MX51_PAD_NANDF_CS0__GPIO3_16 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS0__NANDF_CS0		(_MX51_PAD_NANDF_CS0__NANDF_CS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS1__GPIO3_17		(_MX51_PAD_NANDF_CS1__GPIO3_17 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS1__NANDF_CS1		(_MX51_PAD_NANDF_CS1__NANDF_CS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__CSPI_SCLK		(_MX51_PAD_NANDF_CS2__CSPI_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__FEC_TX_ER		(_MX51_PAD_NANDF_CS2__FEC_TX_ER | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#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(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(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(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(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(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(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(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))
-#define MX51_PAD_NANDF_D15__PATA_DATA15		(_MX51_PAD_NANDF_D15__PATA_DATA15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D15__SD3_DAT7		(_MX51_PAD_NANDF_D15__SD3_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__ECSPI2_SS3		(_MX51_PAD_NANDF_D14__ECSPI2_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__GPIO3_26		(_MX51_PAD_NANDF_D14__GPIO3_26 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__NANDF_D14		(_MX51_PAD_NANDF_D14__NANDF_D14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__PATA_DATA14		(_MX51_PAD_NANDF_D14__PATA_DATA14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__SD3_DAT6		(_MX51_PAD_NANDF_D14__SD3_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__ECSPI2_SS2		(_MX51_PAD_NANDF_D13__ECSPI2_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__GPIO3_27		(_MX51_PAD_NANDF_D13__GPIO3_27 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__NANDF_D13		(_MX51_PAD_NANDF_D13__NANDF_D13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__PATA_DATA13		(_MX51_PAD_NANDF_D13__PATA_DATA13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__SD3_DAT5		(_MX51_PAD_NANDF_D13__SD3_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__ECSPI2_SS1		(_MX51_PAD_NANDF_D12__ECSPI2_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__GPIO3_28		(_MX51_PAD_NANDF_D12__GPIO3_28 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__NANDF_D12		(_MX51_PAD_NANDF_D12__NANDF_D12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__PATA_DATA12		(_MX51_PAD_NANDF_D12__PATA_DATA12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__SD3_DAT4		(_MX51_PAD_NANDF_D12__SD3_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__FEC_RX_DV		(_MX51_PAD_NANDF_D11__FEC_RX_DV | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__GPIO3_29		(_MX51_PAD_NANDF_D11__GPIO3_29 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__NANDF_D11		(_MX51_PAD_NANDF_D11__NANDF_D11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__PATA_DATA11		(_MX51_PAD_NANDF_D11__PATA_DATA11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__SD3_DATA3		(_MX51_PAD_NANDF_D11__SD3_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D10__GPIO3_30		(_MX51_PAD_NANDF_D10__GPIO3_30 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D10__NANDF_D10		(_MX51_PAD_NANDF_D10__NANDF_D10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D10__PATA_DATA10		(_MX51_PAD_NANDF_D10__PATA_DATA10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D10__SD3_DATA2		(_MX51_PAD_NANDF_D10__SD3_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D9__FEC_RDATA0		(_MX51_PAD_NANDF_D9__FEC_RDATA0 | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
-#define MX51_PAD_NANDF_D9__GPIO3_31		(_MX51_PAD_NANDF_D9__GPIO3_31 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D9__NANDF_D9		(_MX51_PAD_NANDF_D9__NANDF_D9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D9__PATA_DATA9		(_MX51_PAD_NANDF_D9__PATA_DATA9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D9__SD3_DATA1		(_MX51_PAD_NANDF_D9__SD3_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D8__FEC_TDATA0		(_MX51_PAD_NANDF_D8__FEC_TDATA0 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_D8__GPIO4_0		(_MX51_PAD_NANDF_D8__GPIO4_0 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D8__NANDF_D8		(_MX51_PAD_NANDF_D8__NANDF_D8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D8__PATA_DATA8		(_MX51_PAD_NANDF_D8__PATA_DATA8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D8__SD3_DATA0		(_MX51_PAD_NANDF_D8__SD3_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D7__GPIO4_1		(_MX51_PAD_NANDF_D7__GPIO4_1 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D7__NANDF_D7		(_MX51_PAD_NANDF_D7__NANDF_D7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D7__PATA_DATA7		(_MX51_PAD_NANDF_D7__PATA_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D7__USBH3_DATA0		(_MX51_PAD_NANDF_D7__USBH3_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__GPIO4_2		(_MX51_PAD_NANDF_D6__GPIO4_2 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__NANDF_D6		(_MX51_PAD_NANDF_D6__NANDF_D6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__PATA_DATA6		(_MX51_PAD_NANDF_D6__PATA_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__SD4_LCTL		(_MX51_PAD_NANDF_D6__SD4_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__USBH3_DATA1		(_MX51_PAD_NANDF_D6__USBH3_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__GPIO4_3		(_MX51_PAD_NANDF_D5__GPIO4_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__NANDF_D5		(_MX51_PAD_NANDF_D5__NANDF_D5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__PATA_DATA5		(_MX51_PAD_NANDF_D5__PATA_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__SD4_WP		(_MX51_PAD_NANDF_D5__SD4_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__USBH3_DATA2		(_MX51_PAD_NANDF_D5__USBH3_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__GPIO4_4		(_MX51_PAD_NANDF_D4__GPIO4_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__NANDF_D4		(_MX51_PAD_NANDF_D4__NANDF_D4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__PATA_DATA4		(_MX51_PAD_NANDF_D4__PATA_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__SD4_CD		(_MX51_PAD_NANDF_D4__SD4_CD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__USBH3_DATA3		(_MX51_PAD_NANDF_D4__USBH3_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__GPIO4_5		(_MX51_PAD_NANDF_D3__GPIO4_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__NANDF_D3		(_MX51_PAD_NANDF_D3__NANDF_D3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__PATA_DATA3		(_MX51_PAD_NANDF_D3__PATA_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__SD4_DAT4		(_MX51_PAD_NANDF_D3__SD4_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__USBH3_DATA4		(_MX51_PAD_NANDF_D3__USBH3_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__GPIO4_6		(_MX51_PAD_NANDF_D2__GPIO4_6 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__NANDF_D2		(_MX51_PAD_NANDF_D2__NANDF_D2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__PATA_DATA2		(_MX51_PAD_NANDF_D2__PATA_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__SD4_DAT5		(_MX51_PAD_NANDF_D2__SD4_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__USBH3_DATA5		(_MX51_PAD_NANDF_D2__USBH3_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__GPIO4_7		(_MX51_PAD_NANDF_D1__GPIO4_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__NANDF_D1		(_MX51_PAD_NANDF_D1__NANDF_D1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__PATA_DATA1		(_MX51_PAD_NANDF_D1__PATA_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__SD4_DAT6		(_MX51_PAD_NANDF_D1__SD4_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__USBH3_DATA6		(_MX51_PAD_NANDF_D1__USBH3_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__GPIO4_8		(_MX51_PAD_NANDF_D0__GPIO4_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__NANDF_D0		(_MX51_PAD_NANDF_D0__NANDF_D0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__PATA_DATA0		(_MX51_PAD_NANDF_D0__PATA_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__SD4_DAT7		(_MX51_PAD_NANDF_D0__SD4_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__USBH3_DATA7		(_MX51_PAD_NANDF_D0__USBH3_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D8__CSI1_D8		(_MX51_PAD_CSI1_D8__CSI1_D8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D8__GPIO3_12		(_MX51_PAD_CSI1_D8__GPIO3_12 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI1_D9__CSI1_D9		(_MX51_PAD_CSI1_D9__CSI1_D9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D9__GPIO3_13		(_MX51_PAD_CSI1_D9__GPIO3_13 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI1_D10__CSI1_D10		(_MX51_PAD_CSI1_D10__CSI1_D10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D11__CSI1_D11		(_MX51_PAD_CSI1_D11__CSI1_D11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D12__CSI1_D12		(_MX51_PAD_CSI1_D12__CSI1_D12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D13__CSI1_D13		(_MX51_PAD_CSI1_D13__CSI1_D13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D14__CSI1_D14		(_MX51_PAD_CSI1_D14__CSI1_D14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D15__CSI1_D15		(_MX51_PAD_CSI1_D15__CSI1_D15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D16__CSI1_D16		(_MX51_PAD_CSI1_D16__CSI1_D16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D17__CSI1_D17		(_MX51_PAD_CSI1_D17__CSI1_D17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D18__CSI1_D18		(_MX51_PAD_CSI1_D18__CSI1_D18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D19__CSI1_D19		(_MX51_PAD_CSI1_D19__CSI1_D19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_VSYNC__CSI1_VSYNC		(_MX51_PAD_CSI1_VSYNC__CSI1_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_VSYNC__GPIO3_14		(_MX51_PAD_CSI1_VSYNC__GPIO3_14 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI1_HSYNC__CSI1_HSYNC		(_MX51_PAD_CSI1_HSYNC__CSI1_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_HSYNC__GPIO3_15		(_MX51_PAD_CSI1_HSYNC__GPIO3_15 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK	(_MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_MCLK__CSI1_MCLK		(_MX51_PAD_CSI1_MCLK__CSI1_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D12__CSI2_D12		(_MX51_PAD_CSI2_D12__CSI2_D12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D12__GPIO4_9		(_MX51_PAD_CSI2_D12__GPIO4_9 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_D13__CSI2_D13		(_MX51_PAD_CSI2_D13__CSI2_D13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D13__GPIO4_10		(_MX51_PAD_CSI2_D13__GPIO4_10 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_D14__CSI2_D14		(_MX51_PAD_CSI2_D14__CSI2_D14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D15__CSI2_D15		(_MX51_PAD_CSI2_D15__CSI2_D15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D16__CSI2_D16		(_MX51_PAD_CSI2_D16__CSI2_D16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D17__CSI2_D17		(_MX51_PAD_CSI2_D17__CSI2_D17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D18__CSI2_D18		(_MX51_PAD_CSI2_D18__CSI2_D18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D18__GPIO4_11		(_MX51_PAD_CSI2_D18__GPIO4_11 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_D19__CSI2_D19		(_MX51_PAD_CSI2_D19__CSI2_D19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D19__GPIO4_12		(_MX51_PAD_CSI2_D19__GPIO4_12 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_VSYNC__CSI2_VSYNC		(_MX51_PAD_CSI2_VSYNC__CSI2_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_VSYNC__GPIO4_13		(_MX51_PAD_CSI2_VSYNC__GPIO4_13 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_HSYNC__CSI2_HSYNC		(_MX51_PAD_CSI2_HSYNC__CSI2_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_HSYNC__GPIO4_14		(_MX51_PAD_CSI2_HSYNC__GPIO4_14 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK	(_MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_PIXCLK__GPIO4_15		(_MX51_PAD_CSI2_PIXCLK__GPIO4_15 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_I2C1_CLK__GPIO4_16		(_MX51_PAD_I2C1_CLK__GPIO4_16 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_I2C1_CLK__I2C1_CLK		(_MX51_PAD_I2C1_CLK__I2C1_CLK | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_I2C1_DAT__GPIO4_17		(_MX51_PAD_I2C1_DAT__GPIO4_17 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_I2C1_DAT__I2C1_DAT		(_MX51_PAD_I2C1_DAT__I2C1_DAT | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_TXD__AUD3_TXD		(_MX51_PAD_AUD3_BB_TXD__AUD3_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_TXD__GPIO4_18		(_MX51_PAD_AUD3_BB_TXD__GPIO4_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_RXD__AUD3_RXD		(_MX51_PAD_AUD3_BB_RXD__AUD3_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_RXD__GPIO4_19		(_MX51_PAD_AUD3_BB_RXD__GPIO4_19 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_RXD__UART3_RXD		(_MX51_PAD_AUD3_BB_RXD__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_CK__AUD3_TXC		(_MX51_PAD_AUD3_BB_CK__AUD3_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_CK__GPIO4_20		(_MX51_PAD_AUD3_BB_CK__GPIO4_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_FS__AUD3_TXFS		(_MX51_PAD_AUD3_BB_FS__AUD3_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_FS__GPIO4_21		(_MX51_PAD_AUD3_BB_FS__GPIO4_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_FS__UART3_TXD		(_MX51_PAD_AUD3_BB_FS__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI	(_MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_MOSI__GPIO4_22		(_MX51_PAD_CSPI1_MOSI__GPIO4_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_MOSI__I2C1_SDA		(_MX51_PAD_CSPI1_MOSI__I2C1_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_CSPI1_MISO__AUD4_RXD		(_MX51_PAD_CSPI1_MISO__AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO	(_MX51_PAD_CSPI1_MISO__ECSPI1_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_MISO__GPIO4_23		(_MX51_PAD_CSPI1_MISO__GPIO4_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS0__AUD4_TXC		(_MX51_PAD_CSPI1_SS0__AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0		(_MX51_PAD_CSPI1_SS0__ECSPI1_SS0 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS0__GPIO4_24		(_MX51_PAD_CSPI1_SS0__GPIO4_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS1__AUD4_TXD		(_MX51_PAD_CSPI1_SS1__AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1		(_MX51_PAD_CSPI1_SS1__ECSPI1_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS1__GPIO4_25		(_MX51_PAD_CSPI1_SS1__GPIO4_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_RDY__AUD4_TXFS		(_MX51_PAD_CSPI1_RDY__AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY		(_MX51_PAD_CSPI1_RDY__ECSPI1_RDY | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_RDY__GPIO4_26		(_MX51_PAD_CSPI1_RDY__GPIO4_26 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK	(_MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_SCLK__GPIO4_27		(_MX51_PAD_CSPI1_SCLK__GPIO4_27 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SCLK__I2C1_SCL		(_MX51_PAD_CSPI1_SCLK__I2C1_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_UART1_RXD__GPIO4_28		(_MX51_PAD_UART1_RXD__GPIO4_28 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART1_RXD__UART1_RXD		(_MX51_PAD_UART1_RXD__UART1_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART1_TXD__GPIO4_29		(_MX51_PAD_UART1_TXD__GPIO4_29 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART1_TXD__PWM2_PWMO		(_MX51_PAD_UART1_TXD__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART1_TXD__UART1_TXD		(_MX51_PAD_UART1_TXD__UART1_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART1_RTS__GPIO4_30		(_MX51_PAD_UART1_RTS__GPIO4_30 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART1_RTS__UART1_RTS		(_MX51_PAD_UART1_RTS__UART1_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART1_CTS__GPIO4_31		(_MX51_PAD_UART1_CTS__GPIO4_31 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART1_CTS__UART1_CTS		(_MX51_PAD_UART1_CTS__UART1_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART2_RXD__FIRI_TXD		(_MX51_PAD_UART2_RXD__FIRI_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART2_RXD__GPIO1_20		(_MX51_PAD_UART2_RXD__GPIO1_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART2_RXD__UART2_RXD		(_MX51_PAD_UART2_RXD__UART2_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART2_TXD__FIRI_RXD		(_MX51_PAD_UART2_TXD__FIRI_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART2_TXD__GPIO1_21		(_MX51_PAD_UART2_TXD__GPIO1_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART2_TXD__UART2_TXD		(_MX51_PAD_UART2_TXD__UART2_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART3_RXD__CSI1_D0		(_MX51_PAD_UART3_RXD__CSI1_D0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART3_RXD__GPIO1_22		(_MX51_PAD_UART3_RXD__GPIO1_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART3_RXD__UART1_DTR		(_MX51_PAD_UART3_RXD__UART1_DTR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART3_RXD__UART3_RXD		(_MX51_PAD_UART3_RXD__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART3_TXD__CSI1_D1		(_MX51_PAD_UART3_TXD__CSI1_D1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART3_TXD__GPIO1_23		(_MX51_PAD_UART3_TXD__GPIO1_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART3_TXD__UART1_DSR		(_MX51_PAD_UART3_TXD__UART1_DSR | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART3_TXD__UART3_TXD		(_MX51_PAD_UART3_TXD__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_OWIRE_LINE__GPIO1_24		(_MX51_PAD_OWIRE_LINE__GPIO1_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_OWIRE_LINE__OWIRE_LINE		(_MX51_PAD_OWIRE_LINE__OWIRE_LINE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_OWIRE_LINE__SPDIF_OUT		(_MX51_PAD_OWIRE_LINE__SPDIF_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_ROW0__KEY_ROW0		(_MX51_PAD_KEY_ROW0__KEY_ROW0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_ROW1__KEY_ROW1		(_MX51_PAD_KEY_ROW1__KEY_ROW1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_ROW2__KEY_ROW2		(_MX51_PAD_KEY_ROW2__KEY_ROW2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_ROW3__KEY_ROW3		(_MX51_PAD_KEY_ROW3__KEY_ROW3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL0__KEY_COL0		(_MX51_PAD_KEY_COL0__KEY_COL0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL0__PLL1_BYP		(_MX51_PAD_KEY_COL0__PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL1__KEY_COL1		(_MX51_PAD_KEY_COL1__KEY_COL1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL1__PLL2_BYP		(_MX51_PAD_KEY_COL1__PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL2__KEY_COL2		(_MX51_PAD_KEY_COL2__KEY_COL2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL2__PLL3_BYP		(_MX51_PAD_KEY_COL2__PLL3_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL3__KEY_COL3		(_MX51_PAD_KEY_COL3__KEY_COL3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__I2C2_SCL		(_MX51_PAD_KEY_COL4__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__KEY_COL4		(_MX51_PAD_KEY_COL4__KEY_COL4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__SPDIF_OUT1		(_MX51_PAD_KEY_COL4__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__UART1_RI		(_MX51_PAD_KEY_COL4__UART1_RI | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__UART3_RTS		(_MX51_PAD_KEY_COL4__UART3_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_KEY_COL5__I2C2_SDA		(_MX51_PAD_KEY_COL5__I2C2_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_KEY_COL5__KEY_COL5		(_MX51_PAD_KEY_COL5__KEY_COL5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL5__UART1_DCD		(_MX51_PAD_KEY_COL5__UART1_DCD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_KEY_COL5__UART3_CTS		(_MX51_PAD_KEY_COL5__UART3_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_CLK__CSPI_SCLK		(_MX51_PAD_USBH1_CLK__CSPI_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_CLK__GPIO1_25		(_MX51_PAD_USBH1_CLK__GPIO1_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_CLK__I2C2_SCL		(_MX51_PAD_USBH1_CLK__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_USBH1_CLK__USBH1_CLK		(_MX51_PAD_USBH1_CLK__USBH1_CLK | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DIR__CSPI_MOSI		(_MX51_PAD_USBH1_DIR__CSPI_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DIR__GPIO1_26		(_MX51_PAD_USBH1_DIR__GPIO1_26 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DIR__I2C2_SDA		(_MX51_PAD_USBH1_DIR__I2C2_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_USBH1_DIR__USBH1_DIR		(_MX51_PAD_USBH1_DIR__USBH1_DIR | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_STP__CSPI_RDY		(_MX51_PAD_USBH1_STP__CSPI_RDY | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_STP__GPIO1_27		(_MX51_PAD_USBH1_STP__GPIO1_27 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_STP__UART3_RXD		(_MX51_PAD_USBH1_STP__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_STP__USBH1_STP		(_MX51_PAD_USBH1_STP__USBH1_STP | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_NXT__CSPI_MISO		(_MX51_PAD_USBH1_NXT__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_NXT__GPIO1_28		(_MX51_PAD_USBH1_NXT__GPIO1_28 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_NXT__UART3_TXD		(_MX51_PAD_USBH1_NXT__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_NXT__USBH1_NXT		(_MX51_PAD_USBH1_NXT__USBH1_NXT | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA0__GPIO1_11		(_MX51_PAD_USBH1_DATA0__GPIO1_11 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA0__UART2_CTS		(_MX51_PAD_USBH1_DATA0__UART2_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA0__USBH1_DATA0	(_MX51_PAD_USBH1_DATA0__USBH1_DATA0 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA1__GPIO1_12		(_MX51_PAD_USBH1_DATA1__GPIO1_12 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA1__UART2_RXD		(_MX51_PAD_USBH1_DATA1__UART2_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA1__USBH1_DATA1	(_MX51_PAD_USBH1_DATA1__USBH1_DATA1 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA2__GPIO1_13		(_MX51_PAD_USBH1_DATA2__GPIO1_13 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA2__UART2_TXD		(_MX51_PAD_USBH1_DATA2__UART2_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA2__USBH1_DATA2	(_MX51_PAD_USBH1_DATA2__USBH1_DATA2 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA3__GPIO1_14		(_MX51_PAD_USBH1_DATA3__GPIO1_14 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA3__UART2_RTS		(_MX51_PAD_USBH1_DATA3__UART2_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA3__USBH1_DATA3	(_MX51_PAD_USBH1_DATA3__USBH1_DATA3 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA4__CSPI_SS0		(_MX51_PAD_USBH1_DATA4__CSPI_SS0 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA4__GPIO1_15		(_MX51_PAD_USBH1_DATA4__GPIO1_15 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA4__USBH1_DATA4	(_MX51_PAD_USBH1_DATA4__USBH1_DATA4 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA5__CSPI_SS1		(_MX51_PAD_USBH1_DATA5__CSPI_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA5__GPIO1_16		(_MX51_PAD_USBH1_DATA5__GPIO1_16 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA5__USBH1_DATA5	(_MX51_PAD_USBH1_DATA5__USBH1_DATA5 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA6__CSPI_SS3		(_MX51_PAD_USBH1_DATA6__CSPI_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA6__GPIO1_17		(_MX51_PAD_USBH1_DATA6__GPIO1_17 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA6__USBH1_DATA6	(_MX51_PAD_USBH1_DATA6__USBH1_DATA6 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA7__ECSPI1_SS3	(_MX51_PAD_USBH1_DATA7__ECSPI1_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA7__ECSPI2_SS3	(_MX51_PAD_USBH1_DATA7__ECSPI2_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA7__GPIO1_18		(_MX51_PAD_USBH1_DATA7__GPIO1_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA7__USBH1_DATA7	(_MX51_PAD_USBH1_DATA7__USBH1_DATA7 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_DI1_PIN11__DI1_PIN11		(_MX51_PAD_DI1_PIN11__DI1_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN11__ECSPI1_SS2		(_MX51_PAD_DI1_PIN11__ECSPI1_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_DI1_PIN11__GPIO3_0		(_MX51_PAD_DI1_PIN11__GPIO3_0 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN12__DI1_PIN12		(_MX51_PAD_DI1_PIN12__DI1_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN12__GPIO3_1		(_MX51_PAD_DI1_PIN12__GPIO3_1 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN13__DI1_PIN13		(_MX51_PAD_DI1_PIN13__DI1_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN13__GPIO3_2		(_MX51_PAD_DI1_PIN13__GPIO3_2 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DI1_D0_CS__DI1_D0_CS		(_MX51_PAD_DI1_D0_CS__DI1_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_D0_CS__GPIO3_3		(_MX51_PAD_DI1_D0_CS__GPIO3_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DI1_D1_CS__DI1_D1_CS		(_MX51_PAD_DI1_D1_CS__DI1_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_D1_CS__DISP1_PIN14		(_MX51_PAD_DI1_D1_CS__DISP1_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_D1_CS__DISP1_PIN5		(_MX51_PAD_DI1_D1_CS__DISP1_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_D1_CS__GPIO3_4		(_MX51_PAD_DI1_D1_CS__GPIO3_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1	(_MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN	(_MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIN__GPIO3_5	(_MX51_PAD_DISPB2_SER_DIN__GPIO3_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6	(_MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO	(_MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIO__GPIO3_6	(_MX51_PAD_DISPB2_SER_DIO__GPIO3_6 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17	(_MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7	(_MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK	(_MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_CLK__GPIO3_7	(_MX51_PAD_DISPB2_SER_CLK__GPIO3_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK	(_MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN16	(_MX51_PAD_DISPB2_SER_RS__DISP1_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN8	(_MX51_PAD_DISPB2_SER_RS__DISP1_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	(_MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	(_MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__GPIO3_8		(_MX51_PAD_DISPB2_SER_RS__GPIO3_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT0__DISP1_DAT0		(_MX51_PAD_DISP1_DAT0__DISP1_DAT0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT1__DISP1_DAT1		(_MX51_PAD_DISP1_DAT1__DISP1_DAT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT2__DISP1_DAT2		(_MX51_PAD_DISP1_DAT2__DISP1_DAT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT3__DISP1_DAT3		(_MX51_PAD_DISP1_DAT3__DISP1_DAT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT4__DISP1_DAT4		(_MX51_PAD_DISP1_DAT4__DISP1_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT5__DISP1_DAT5		(_MX51_PAD_DISP1_DAT5__DISP1_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT6__BOOT_USB_SRC	(_MX51_PAD_DISP1_DAT6__BOOT_USB_SRC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT6__DISP1_DAT6		(_MX51_PAD_DISP1_DAT6__DISP1_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG	(_MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT7__DISP1_DAT7		(_MX51_PAD_DISP1_DAT7__DISP1_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT8__BOOT_SRC0		(_MX51_PAD_DISP1_DAT8__BOOT_SRC0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT8__DISP1_DAT8		(_MX51_PAD_DISP1_DAT8__DISP1_DAT8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT9__BOOT_SRC1		(_MX51_PAD_DISP1_DAT9__BOOT_SRC1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT9__DISP1_DAT9		(_MX51_PAD_DISP1_DAT9__DISP1_DAT9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE	(_MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT10__DISP1_DAT10	(_MX51_PAD_DISP1_DAT10__DISP1_DAT10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2	(_MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT11__DISP1_DAT11	(_MX51_PAD_DISP1_DAT11__DISP1_DAT11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL	(_MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT12__DISP1_DAT12	(_MX51_PAD_DISP1_DAT12__DISP1_DAT12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0	(_MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT13__DISP1_DAT13	(_MX51_PAD_DISP1_DAT13__DISP1_DAT13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1	(_MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT14__DISP1_DAT14	(_MX51_PAD_DISP1_DAT14__DISP1_DAT14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH	(_MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT15__DISP1_DAT15	(_MX51_PAD_DISP1_DAT15__DISP1_DAT15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0	(_MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT16__DISP1_DAT16	(_MX51_PAD_DISP1_DAT16__DISP1_DAT16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1	(_MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT17__DISP1_DAT17	(_MX51_PAD_DISP1_DAT17__DISP1_DAT17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0	(_MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT18__DISP1_DAT18	(_MX51_PAD_DISP1_DAT18__DISP1_DAT18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT18__DISP2_PIN11	(_MX51_PAD_DISP1_DAT18__DISP2_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT18__DISP2_PIN5	(_MX51_PAD_DISP1_DAT18__DISP2_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1	(_MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT19__DISP1_DAT19	(_MX51_PAD_DISP1_DAT19__DISP1_DAT19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT19__DISP2_PIN12	(_MX51_PAD_DISP1_DAT19__DISP2_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT19__DISP2_PIN6	(_MX51_PAD_DISP1_DAT19__DISP2_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0	(_MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT20__DISP1_DAT20	(_MX51_PAD_DISP1_DAT20__DISP1_DAT20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT20__DISP2_PIN13	(_MX51_PAD_DISP1_DAT20__DISP2_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT20__DISP2_PIN7	(_MX51_PAD_DISP1_DAT20__DISP2_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1	(_MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT21__DISP1_DAT21	(_MX51_PAD_DISP1_DAT21__DISP1_DAT21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT21__DISP2_PIN14	(_MX51_PAD_DISP1_DAT21__DISP2_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT21__DISP2_PIN8	(_MX51_PAD_DISP1_DAT21__DISP2_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0	(_MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT22__DISP1_DAT22	(_MX51_PAD_DISP1_DAT22__DISP1_DAT22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT22__DISP2_D0_CS	(_MX51_PAD_DISP1_DAT22__DISP2_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT22__DISP2_DAT16	(_MX51_PAD_DISP1_DAT22__DISP2_DAT16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1	(_MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__DISP1_DAT23	(_MX51_PAD_DISP1_DAT23__DISP1_DAT23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__DISP2_D1_CS	(_MX51_PAD_DISP1_DAT23__DISP2_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__DISP2_DAT17	(_MX51_PAD_DISP1_DAT23__DISP2_DAT17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__DISP2_SER_CS	(_MX51_PAD_DISP1_DAT23__DISP2_SER_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN3__DI1_PIN3		(_MX51_PAD_DI1_PIN3__DI1_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN2__DI1_PIN2		(_MX51_PAD_DI1_PIN2__DI1_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP2__DISP1_SER_CLK		(_MX51_PAD_DI_GP2__DISP1_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP2__DISP2_WAIT		(_MX51_PAD_DI_GP2__DISP2_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP3__CSI1_DATA_EN		(_MX51_PAD_DI_GP3__CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP3__DISP1_SER_DIO		(_MX51_PAD_DI_GP3__DISP1_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP3__FEC_TX_ER		(_MX51_PAD_DI_GP3__FEC_TX_ER | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DI2_PIN4__CSI2_DATA_EN		(_MX51_PAD_DI2_PIN4__CSI2_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN4__DI2_PIN4		(_MX51_PAD_DI2_PIN4__DI2_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN4__FEC_CRS		(_MX51_PAD_DI2_PIN4__FEC_CRS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN2__DI2_PIN2		(_MX51_PAD_DI2_PIN2__DI2_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN2__FEC_MDC		(_MX51_PAD_DI2_PIN2__FEC_MDC | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DI2_PIN3__DI2_PIN3		(_MX51_PAD_DI2_PIN3__DI2_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN3__FEC_MDIO		(_MX51_PAD_DI2_PIN3__FEC_MDIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK	(_MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_DISP_CLK__FEC_RDATA1	(_MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP4__DI2_PIN15		(_MX51_PAD_DI_GP4__DI2_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP4__DISP1_SER_DIN		(_MX51_PAD_DI_GP4__DISP1_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP4__DISP2_PIN1		(_MX51_PAD_DI_GP4__DISP2_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP4__FEC_RDATA2		(_MX51_PAD_DI_GP4__FEC_RDATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__DISP2_DAT0		(_MX51_PAD_DISP2_DAT0__DISP2_DAT0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__FEC_RDATA3		(_MX51_PAD_DISP2_DAT0__FEC_RDATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__KEY_COL6		(_MX51_PAD_DISP2_DAT0__KEY_COL6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__UART3_RXD		(_MX51_PAD_DISP2_DAT0__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__USBH3_CLK		(_MX51_PAD_DISP2_DAT0__USBH3_CLK | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__DISP2_DAT1		(_MX51_PAD_DISP2_DAT1__DISP2_DAT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__FEC_RX_ER		(_MX51_PAD_DISP2_DAT1__FEC_RX_ER | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__KEY_COL7		(_MX51_PAD_DISP2_DAT1__KEY_COL7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__UART3_TXD		(_MX51_PAD_DISP2_DAT1__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__USBH3_DIR		(_MX51_PAD_DISP2_DAT1__USBH3_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT2__DISP2_DAT2		(_MX51_PAD_DISP2_DAT2__DISP2_DAT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT3__DISP2_DAT3		(_MX51_PAD_DISP2_DAT3__DISP2_DAT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT4__DISP2_DAT4		(_MX51_PAD_DISP2_DAT4__DISP2_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT5__DISP2_DAT5		(_MX51_PAD_DISP2_DAT5__DISP2_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT6__DISP2_DAT6		(_MX51_PAD_DISP2_DAT6__DISP2_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT6__FEC_TDATA1		(_MX51_PAD_DISP2_DAT6__FEC_TDATA1 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT6__GPIO1_19		(_MX51_PAD_DISP2_DAT6__GPIO1_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT6__KEY_ROW4		(_MX51_PAD_DISP2_DAT6__KEY_ROW4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT6__USBH3_STP		(_MX51_PAD_DISP2_DAT6__USBH3_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT7__DISP2_DAT7		(_MX51_PAD_DISP2_DAT7__DISP2_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT7__FEC_TDATA2		(_MX51_PAD_DISP2_DAT7__FEC_TDATA2 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT7__GPIO1_29		(_MX51_PAD_DISP2_DAT7__GPIO1_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT7__KEY_ROW5		(_MX51_PAD_DISP2_DAT7__KEY_ROW5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT7__USBH3_NXT		(_MX51_PAD_DISP2_DAT7__USBH3_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT8__DISP2_DAT8		(_MX51_PAD_DISP2_DAT8__DISP2_DAT8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT8__FEC_TDATA3		(_MX51_PAD_DISP2_DAT8__FEC_TDATA3 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT8__GPIO1_30		(_MX51_PAD_DISP2_DAT8__GPIO1_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT8__KEY_ROW6		(_MX51_PAD_DISP2_DAT8__KEY_ROW6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT8__USBH3_DATA0	(_MX51_PAD_DISP2_DAT8__USBH3_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT9__AUD6_RXC		(_MX51_PAD_DISP2_DAT9__AUD6_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT9__DISP2_DAT9		(_MX51_PAD_DISP2_DAT9__DISP2_DAT9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT9__FEC_TX_EN		(_MX51_PAD_DISP2_DAT9__FEC_TX_EN | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT9__GPIO1_31		(_MX51_PAD_DISP2_DAT9__GPIO1_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT9__USBH3_DATA1	(_MX51_PAD_DISP2_DAT9__USBH3_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__DISP2_DAT10	(_MX51_PAD_DISP2_DAT10__DISP2_DAT10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__DISP2_SER_CS	(_MX51_PAD_DISP2_DAT10__DISP2_SER_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__FEC_COL		(_MX51_PAD_DISP2_DAT10__FEC_COL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__KEY_ROW7		(_MX51_PAD_DISP2_DAT10__KEY_ROW7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__USBH3_DATA2	(_MX51_PAD_DISP2_DAT10__USBH3_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__AUD6_TXD		(_MX51_PAD_DISP2_DAT11__AUD6_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__DISP2_DAT11	(_MX51_PAD_DISP2_DAT11__DISP2_DAT11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__FEC_RX_CLK	(_MX51_PAD_DISP2_DAT11__FEC_RX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__GPIO1_10		(_MX51_PAD_DISP2_DAT11__GPIO1_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__USBH3_DATA3	(_MX51_PAD_DISP2_DAT11__USBH3_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT12__AUD6_RXD		(_MX51_PAD_DISP2_DAT12__AUD6_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT12__DISP2_DAT12	(_MX51_PAD_DISP2_DAT12__DISP2_DAT12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT12__FEC_RX_DV		(_MX51_PAD_DISP2_DAT12__FEC_RX_DV | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT12__USBH3_DATA4	(_MX51_PAD_DISP2_DAT12__USBH3_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT13__AUD6_TXC		(_MX51_PAD_DISP2_DAT13__AUD6_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT13__DISP2_DAT13	(_MX51_PAD_DISP2_DAT13__DISP2_DAT13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT13__FEC_TX_CLK	(_MX51_PAD_DISP2_DAT13__FEC_TX_CLK | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
-#define MX51_PAD_DISP2_DAT13__USBH3_DATA5	(_MX51_PAD_DISP2_DAT13__USBH3_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT14__AUD6_TXFS		(_MX51_PAD_DISP2_DAT14__AUD6_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT14__DISP2_DAT14	(_MX51_PAD_DISP2_DAT14__DISP2_DAT14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT14__FEC_RDATA0	(_MX51_PAD_DISP2_DAT14__FEC_RDATA0 | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
-#define MX51_PAD_DISP2_DAT14__USBH3_DATA6	(_MX51_PAD_DISP2_DAT14__USBH3_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT15__AUD6_RXFS		(_MX51_PAD_DISP2_DAT15__AUD6_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT15__DISP1_SER_CS	(_MX51_PAD_DISP2_DAT15__DISP1_SER_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT15__DISP2_DAT15	(_MX51_PAD_DISP2_DAT15__DISP2_DAT15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT15__FEC_TDATA0	(_MX51_PAD_DISP2_DAT15__FEC_TDATA0 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT15__USBH3_DATA7	(_MX51_PAD_DISP2_DAT15__USBH3_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CMD__AUD5_RXFS		(_MX51_PAD_SD1_CMD__AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CMD__CSPI_MOSI		(_MX51_PAD_SD1_CMD__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CMD__SD1_CMD		(_MX51_PAD_SD1_CMD__SD1_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD1_CLK__AUD5_RXC		(_MX51_PAD_SD1_CLK__AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CLK__CSPI_SCLK		(_MX51_PAD_SD1_CLK__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#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(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(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(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(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))
-#define MX51_PAD_GPIO1_1__CSPI_MISO		(_MX51_PAD_GPIO1_1__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_GPIO1_1__GPIO1_1		(_MX51_PAD_GPIO1_1__GPIO1_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_1__SD1_WP		(_MX51_PAD_GPIO1_1__SD1_WP | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
-#define MX51_PAD_EIM_DA12__EIM_DA12		(_MX51_PAD_EIM_DA12__EIM_DA12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA13__EIM_DA13		(_MX51_PAD_EIM_DA13__EIM_DA13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA14__EIM_DA14		(_MX51_PAD_EIM_DA14__EIM_DA14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA15__EIM_DA15		(_MX51_PAD_EIM_DA15__EIM_DA15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_CMD__CSPI_MOSI		(_MX51_PAD_SD2_CMD__CSPI_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD2_CMD__I2C1_SCL		(_MX51_PAD_SD2_CMD__I2C1_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_SD2_CMD__SD2_CMD		(_MX51_PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD2_CLK__CSPI_SCLK		(_MX51_PAD_SD2_CLK__CSPI_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD2_CLK__I2C1_SDA		(_MX51_PAD_SD2_CLK__I2C1_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#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(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(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(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(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))
-#define MX51_PAD_GPIO1_2__PLL1_BYP		(_MX51_PAD_GPIO1_2__PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_2__PWM1_PWMO		(_MX51_PAD_GPIO1_2__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_3__GPIO1_3		(_MX51_PAD_GPIO1_3__GPIO1_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_3__I2C2_SDA		(_MX51_PAD_GPIO1_3__I2C2_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_GPIO1_3__PLL2_BYP		(_MX51_PAD_GPIO1_3__PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_3__PWM2_PWMO		(_MX51_PAD_GPIO1_3__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	(_MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B	(_MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_4__DISP2_EXT_CLK		(_MX51_PAD_GPIO1_4__DISP2_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_4__EIM_RDY		(_MX51_PAD_GPIO1_4__EIM_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_4__GPIO1_4		(_MX51_PAD_GPIO1_4__GPIO1_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_4__WDOG1_WDOG_B		(_MX51_PAD_GPIO1_4__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_5__CSI2_MCLK		(_MX51_PAD_GPIO1_5__CSI2_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_5__DISP2_PIN16		(_MX51_PAD_GPIO1_5__DISP2_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_5__GPIO1_5		(_MX51_PAD_GPIO1_5__GPIO1_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_5__WDOG2_WDOG_B		(_MX51_PAD_GPIO1_5__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_6__DISP2_PIN17		(_MX51_PAD_GPIO1_6__DISP2_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_6__GPIO1_6		(_MX51_PAD_GPIO1_6__GPIO1_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_6__REF_EN_B		(_MX51_PAD_GPIO1_6__REF_EN_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_7__CCM_OUT_0		(_MX51_PAD_GPIO1_7__CCM_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_7__GPIO1_7		(_MX51_PAD_GPIO1_7__GPIO1_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_7__SD2_WP		(_MX51_PAD_GPIO1_7__SD2_WP | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
-#define MX51_PAD_GPIO1_7__SPDIF_OUT1		(_MX51_PAD_GPIO1_7__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_8__CSI2_DATA_EN		(_MX51_PAD_GPIO1_8__CSI2_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_8__GPIO1_8		(_MX51_PAD_GPIO1_8__GPIO1_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_8__SD2_CD		(_MX51_PAD_GPIO1_8__SD2_CD | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
-#define MX51_PAD_GPIO1_8__USBH3_PWR		(_MX51_PAD_GPIO1_8__USBH3_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__CCM_OUT_1		(_MX51_PAD_GPIO1_9__CCM_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__DISP2_D1_CS		(_MX51_PAD_GPIO1_9__DISP2_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__DISP2_SER_CS		(_MX51_PAD_GPIO1_9__DISP2_SER_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__GPIO1_9		(_MX51_PAD_GPIO1_9__GPIO1_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__SD2_LCTL		(_MX51_PAD_GPIO1_9__SD2_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__USBH3_OC		(_MX51_PAD_GPIO1_9__USBH3_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_EIM_EB2__GPIO2_22		IOMUX_PAD(0x468, 0x0d4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__GPT_CMPOUT1		IOMUX_PAD(0x468, 0x0d4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__AUD5_RXC		IOMUX_PAD(0x46c, 0x0d8, 6, 0x8dc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__CSI1_D3		IOMUX_PAD(0x46c, 0x0d8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__EIM_EB3		IOMUX_PAD(0x46c, 0x0d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__FEC_RDATA1		IOMUX_PAD(0x46c, 0x0d8, 3, 0x95c, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__GPIO2_23		IOMUX_PAD(0x46c, 0x0d8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__GPT_CMPOUT2		IOMUX_PAD(0x46c, 0x0d8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_OE__EIM_OE			IOMUX_PAD(0x470, 0x0dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_OE__GPIO2_24		IOMUX_PAD(0x470, 0x0dc, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS0__EIM_CS0		IOMUX_PAD(0x474, 0x0e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS0__GPIO2_25		IOMUX_PAD(0x474, 0x0e0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS1__EIM_CS1		IOMUX_PAD(0x478, 0x0e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS1__GPIO2_26		IOMUX_PAD(0x478, 0x0e4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__AUD5_TXD		IOMUX_PAD(0x47c, 0x0e8, 6, 0x8d8, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__CSI1_D4		IOMUX_PAD(0x47c, 0x0e8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__EIM_CS2		IOMUX_PAD(0x47c, 0x0e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__FEC_RDATA2		IOMUX_PAD(0x47c, 0x0e8, 3, 0x960, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__GPIO2_27		IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__USBOTG_STP		IOMUX_PAD(0x47c, 0x0e8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__AUD5_RXD		IOMUX_PAD(0x480, 0x0ec, 6, 0x8d4, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__CSI1_D5		IOMUX_PAD(0x480, 0x0ec, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__EIM_CS3		IOMUX_PAD(0x480, 0x0ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__FEC_RDATA3		IOMUX_PAD(0x480, 0x0ec, 3, 0x964, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__GPIO2_28		IOMUX_PAD(0x480, 0x0ec, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__USBOTG_NXT		IOMUX_PAD(0x480, 0x0ec, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__AUD5_TXC		IOMUX_PAD(0x484, 0x0f0, 6, 0x8e4, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__CSI1_D6		IOMUX_PAD(0x484, 0x0f0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__EIM_CS4		IOMUX_PAD(0x484, 0x0f0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__FEC_RX_ER		IOMUX_PAD(0x484, 0x0f0, 3, 0x970, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_EIM_CS4__GPIO2_29		IOMUX_PAD(0x484, 0x0f0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__USBOTG_CLK		IOMUX_PAD(0x484, 0x0f0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__AUD5_TXFS		IOMUX_PAD(0x488, 0x0f4, 6, 0x8e8, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__CSI1_D7		IOMUX_PAD(0x488, 0x0f4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__DISP1_EXT_CLK		IOMUX_PAD(0x488, 0x0f4, 4, 0x904, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__EIM_CS5		IOMUX_PAD(0x488, 0x0f4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__FEC_CRS		IOMUX_PAD(0x488, 0x0f4, 3, 0x950, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_EIM_CS5__GPIO2_30		IOMUX_PAD(0x488, 0x0f4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__USBOTG_DIR		IOMUX_PAD(0x488, 0x0f4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DTACK__EIM_DTACK		IOMUX_PAD(0x48c, 0x0f8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DTACK__GPIO2_31		IOMUX_PAD(0x48c, 0x0f8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_LBA__EIM_LBA		IOMUX_PAD(0x494, 0x0fc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_LBA__GPIO3_1		IOMUX_PAD(0x494, 0x0fc, 1, 0x978, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CRE__EIM_CRE		IOMUX_PAD(0x4a0, 0x100, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CRE__GPIO3_2		IOMUX_PAD(0x4a0, 0x100, 1, 0x97c, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DRAM_CS1__DRAM_CS1		IOMUX_PAD(0x4d0, 0x104, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__GPIO3_3		IOMUX_PAD(0x4e4, 0x108, 3, 0x980, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__NANDF_WE_B		IOMUX_PAD(0x4e4, 0x108, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__PATA_DIOW		IOMUX_PAD(0x4e4, 0x108, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__SD3_DATA0		IOMUX_PAD(0x4e4, 0x108, 2, 0x93c, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__GPIO3_4		IOMUX_PAD(0x4e8, 0x10c, 3, 0x984, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__NANDF_RE_B		IOMUX_PAD(0x4e8, 0x10c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__PATA_DIOR		IOMUX_PAD(0x4e8, 0x10c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__SD3_DATA1		IOMUX_PAD(0x4e8, 0x10c, 2, 0x940, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_ALE__GPIO3_5		IOMUX_PAD(0x4ec, 0x110, 3, 0x988, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_ALE__NANDF_ALE		IOMUX_PAD(0x4ec, 0x110, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_ALE__PATA_BUFFER_EN	IOMUX_PAD(0x4ec, 0x110, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CLE__GPIO3_6		IOMUX_PAD(0x4f0, 0x114, 3, 0x98c, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CLE__NANDF_CLE		IOMUX_PAD(0x4f0, 0x114, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CLE__PATA_RESET_B	IOMUX_PAD(0x4f0, 0x114, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__GPIO3_7		IOMUX_PAD(0x4f4, 0x118, 3, 0x990, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__NANDF_WP_B		IOMUX_PAD(0x4f4, 0x118, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__PATA_DMACK		IOMUX_PAD(0x4f4, 0x118, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__SD3_DATA2		IOMUX_PAD(0x4f4, 0x118, 2, 0x944, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__ECSPI2_SS1		IOMUX_PAD(0x4f8, 0x11c, 5, 0x930, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__GPIO3_8		IOMUX_PAD(0x4f8, 0x11c, 3, 0x994, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__NANDF_RB0		IOMUX_PAD(0x4f8, 0x11c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__PATA_DMARQ		IOMUX_PAD(0x4f8, 0x11c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__SD3_DATA3		IOMUX_PAD(0x4f8, 0x11c, 2, 0x948, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__CSPI_MOSI		IOMUX_PAD(0x4fc, 0x120, 6, 0x91c, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__ECSPI2_RDY		IOMUX_PAD(0x4fc, 0x120, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__GPIO3_9		IOMUX_PAD(0x4fc, 0x120, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__NANDF_RB1		IOMUX_PAD(0x4fc, 0x120, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__PATA_IORDY		IOMUX_PAD(0x4fc, 0x120, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__SD4_CMD		IOMUX_PAD(0x4fc, 0x120, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__DISP2_WAIT		IOMUX_PAD(0x500, 0x124, 5, 0x9a8, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK		IOMUX_PAD(0x500, 0x124, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__FEC_COL		IOMUX_PAD(0x500, 0x124, 1, 0x94c, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_NANDF_RB2__GPIO3_10		IOMUX_PAD(0x500, 0x124, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__NANDF_RB2		IOMUX_PAD(0x500, 0x124, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__USBH3_H3_DP		IOMUX_PAD(0x500, 0x124, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__USBH3_NXT		IOMUX_PAD(0x500, 0x124, 6, 0xa20, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__DISP1_WAIT		IOMUX_PAD(0x504, 0x128, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__ECSPI2_MISO		IOMUX_PAD(0x504, 0x128, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__FEC_RX_CLK		IOMUX_PAD(0x504, 0x128, 1, 0x968, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_NANDF_RB3__GPIO3_11		IOMUX_PAD(0x504, 0x128, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__NANDF_RB3		IOMUX_PAD(0x504, 0x128, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__USBH3_CLK		IOMUX_PAD(0x504, 0x128, 6, 0x9f8, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__USBH3_H3_DM		IOMUX_PAD(0x504, 0x128, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_NAND__GPIO_NAND		IOMUX_PAD(0x514, 0x12c, 0, 0x998, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_NAND__PATA_INTRQ		IOMUX_PAD(0x514, 0x12c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS0__GPIO3_16		IOMUX_PAD(0x518, 0x130, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS0__NANDF_CS0		IOMUX_PAD(0x518, 0x130, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS1__GPIO3_17		IOMUX_PAD(0x51c, 0x134, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS1__NANDF_CS1		IOMUX_PAD(0x51c, 0x134, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__CSPI_SCLK		IOMUX_PAD(0x520, 0x138, 6, 0x914, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__FEC_TX_ER		IOMUX_PAD(0x520, 0x138, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS2__GPIO3_18		IOMUX_PAD(0x520, 0x138, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__NANDF_CS2		IOMUX_PAD(0x520, 0x138, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__PATA_CS_0		IOMUX_PAD(0x520, 0x138, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__SD4_CLK		IOMUX_PAD(0x520, 0x138, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_NANDF_CS2__USBH3_H1_DP		IOMUX_PAD(0x520, 0x138, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__FEC_MDC		IOMUX_PAD(0x524, 0x13c, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS3__GPIO3_19		IOMUX_PAD(0x524, 0x13c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__NANDF_CS3		IOMUX_PAD(0x524, 0x13c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__PATA_CS_1		IOMUX_PAD(0x524, 0x13c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__SD4_DAT0		IOMUX_PAD(0x524, 0x13c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__USBH3_H1_DM		IOMUX_PAD(0x524, 0x13c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__FEC_TDATA1		IOMUX_PAD(0x528, 0x140, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS4__GPIO3_20		IOMUX_PAD(0x528, 0x140, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__NANDF_CS4		IOMUX_PAD(0x528, 0x140, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__PATA_DA_0		IOMUX_PAD(0x528, 0x140, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__SD4_DAT1		IOMUX_PAD(0x528, 0x140, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__USBH3_STP		IOMUX_PAD(0x528, 0x140, 7, 0xa24, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__FEC_TDATA2		IOMUX_PAD(0x52c, 0x144, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS5__GPIO3_21		IOMUX_PAD(0x52c, 0x144, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__NANDF_CS5		IOMUX_PAD(0x52c, 0x144, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__PATA_DA_1		IOMUX_PAD(0x52c, 0x144, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__SD4_DAT2		IOMUX_PAD(0x52c, 0x144, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__USBH3_DIR		IOMUX_PAD(0x52c, 0x144, 7, 0xa1c, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__CSPI_SS3		IOMUX_PAD(0x530, 0x148, 7, 0x928, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__FEC_TDATA3		IOMUX_PAD(0x530, 0x148, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS6__GPIO3_22		IOMUX_PAD(0x530, 0x148, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__NANDF_CS6		IOMUX_PAD(0x530, 0x148, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__PATA_DA_2		IOMUX_PAD(0x530, 0x148, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__SD4_DAT3		IOMUX_PAD(0x530, 0x148, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__FEC_TX_EN		IOMUX_PAD(0x534, 0x14c, 1, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS7__GPIO3_23		IOMUX_PAD(0x534, 0x14c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__NANDF_CS7		IOMUX_PAD(0x534, 0x14c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__SD3_CLK		IOMUX_PAD(0x534, 0x14c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0	IOMUX_PAD(0x538, 0x150, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK	IOMUX_PAD(0x538, 0x150, 1, 0x974, 0, MX51_PAD_CTRL_4)
+#define MX51_PAD_NANDF_RDY_INT__GPIO3_24	IOMUX_PAD(0x538, 0x150, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT	IOMUX_PAD(0x538, 0x150, 0, 0x938, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__SD3_CMD		IOMUX_PAD(0x538, 0x150, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__ECSPI2_MOSI		IOMUX_PAD(0x53c, 0x154, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__GPIO3_25		IOMUX_PAD(0x53c, 0x154, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__NANDF_D15		IOMUX_PAD(0x53c, 0x154, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__PATA_DATA15		IOMUX_PAD(0x53c, 0x154, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__SD3_DAT7		IOMUX_PAD(0x53c, 0x154, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__ECSPI2_SS3		IOMUX_PAD(0x540, 0x158, 2, 0x934, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__GPIO3_26		IOMUX_PAD(0x540, 0x158, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__NANDF_D14		IOMUX_PAD(0x540, 0x158, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__PATA_DATA14		IOMUX_PAD(0x540, 0x158, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__SD3_DAT6		IOMUX_PAD(0x540, 0x158, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__ECSPI2_SS2		IOMUX_PAD(0x544, 0x15c, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__GPIO3_27		IOMUX_PAD(0x544, 0x15c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__NANDF_D13		IOMUX_PAD(0x544, 0x15c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__PATA_DATA13		IOMUX_PAD(0x544, 0x15c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__SD3_DAT5		IOMUX_PAD(0x544, 0x15c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__ECSPI2_SS1		IOMUX_PAD(0x548, 0x160, 2, 0x930, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__GPIO3_28		IOMUX_PAD(0x548, 0x160, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__NANDF_D12		IOMUX_PAD(0x548, 0x160, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__PATA_DATA12		IOMUX_PAD(0x548, 0x160, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__SD3_DAT4		IOMUX_PAD(0x548, 0x160, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__FEC_RX_DV		IOMUX_PAD(0x54c, 0x164, 2, 0x96c, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__GPIO3_29		IOMUX_PAD(0x54c, 0x164, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__NANDF_D11		IOMUX_PAD(0x54c, 0x164, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__PATA_DATA11		IOMUX_PAD(0x54c, 0x164, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__SD3_DATA3		IOMUX_PAD(0x54c, 0x164, 5, 0x948, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__GPIO3_30		IOMUX_PAD(0x550, 0x168, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__NANDF_D10		IOMUX_PAD(0x550, 0x168, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__PATA_DATA10		IOMUX_PAD(0x550, 0x168, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__SD3_DATA2		IOMUX_PAD(0x550, 0x168, 5, 0x944, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__FEC_RDATA0		IOMUX_PAD(0x554, 0x16c, 0x12, 0x958, 0, MX51_PAD_CTRL_4)
+#define MX51_PAD_NANDF_D9__GPIO3_31		IOMUX_PAD(0x554, 0x16c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__NANDF_D9		IOMUX_PAD(0x554, 0x16c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__PATA_DATA9		IOMUX_PAD(0x554, 0x16c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__SD3_DATA1		IOMUX_PAD(0x554, 0x16c, 5, 0x940, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__FEC_TDATA0		IOMUX_PAD(0x558, 0x170, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_D8__GPIO4_0		IOMUX_PAD(0x558, 0x170, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__NANDF_D8		IOMUX_PAD(0x558, 0x170, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__PATA_DATA8		IOMUX_PAD(0x558, 0x170, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__SD3_DATA0		IOMUX_PAD(0x558, 0x170, 5, 0x93c, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__GPIO4_1		IOMUX_PAD(0x55c, 0x174, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__NANDF_D7		IOMUX_PAD(0x55c, 0x174, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__PATA_DATA7		IOMUX_PAD(0x55c, 0x174, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__USBH3_DATA0		IOMUX_PAD(0x55c, 0x174, 5, 0x9fc, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__GPIO4_2		IOMUX_PAD(0x560, 0x178, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__NANDF_D6		IOMUX_PAD(0x560, 0x178, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__PATA_DATA6		IOMUX_PAD(0x560, 0x178, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__SD4_LCTL		IOMUX_PAD(0x560, 0x178, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__USBH3_DATA1		IOMUX_PAD(0x560, 0x178, 5, 0xa00, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__GPIO4_3		IOMUX_PAD(0x564, 0x17c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__NANDF_D5		IOMUX_PAD(0x564, 0x17c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__PATA_DATA5		IOMUX_PAD(0x564, 0x17c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__SD4_WP		IOMUX_PAD(0x564, 0x17c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__USBH3_DATA2		IOMUX_PAD(0x564, 0x17c, 5, 0xa04, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__GPIO4_4		IOMUX_PAD(0x568, 0x180, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__NANDF_D4		IOMUX_PAD(0x568, 0x180, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__PATA_DATA4		IOMUX_PAD(0x568, 0x180, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__SD4_CD		IOMUX_PAD(0x568, 0x180, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__USBH3_DATA3		IOMUX_PAD(0x568, 0x180, 5, 0xa08, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__GPIO4_5		IOMUX_PAD(0x56c, 0x184, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__NANDF_D3		IOMUX_PAD(0x56c, 0x184, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__PATA_DATA3		IOMUX_PAD(0x56c, 0x184, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__SD4_DAT4		IOMUX_PAD(0x56c, 0x184, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__USBH3_DATA4		IOMUX_PAD(0x56c, 0x184, 5, 0xa0c, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__GPIO4_6		IOMUX_PAD(0x570, 0x188, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__NANDF_D2		IOMUX_PAD(0x570, 0x188, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__PATA_DATA2		IOMUX_PAD(0x570, 0x188, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__SD4_DAT5		IOMUX_PAD(0x570, 0x188, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__USBH3_DATA5		IOMUX_PAD(0x570, 0x188, 5, 0xa10, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__GPIO4_7		IOMUX_PAD(0x574, 0x18c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__NANDF_D1		IOMUX_PAD(0x574, 0x18c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__PATA_DATA1		IOMUX_PAD(0x574, 0x18c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__SD4_DAT6		IOMUX_PAD(0x574, 0x18c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__USBH3_DATA6		IOMUX_PAD(0x574, 0x18c, 5, 0xa14, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__GPIO4_8		IOMUX_PAD(0x578, 0x190, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__NANDF_D0		IOMUX_PAD(0x578, 0x190, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__PATA_DATA0		IOMUX_PAD(0x578, 0x190, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__SD4_DAT7		IOMUX_PAD(0x578, 0x190, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__USBH3_DATA7		IOMUX_PAD(0x578, 0x190, 5, 0xa18, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D8__CSI1_D8		IOMUX_PAD(0x57c, 0x194, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D8__GPIO3_12		IOMUX_PAD(0x57c, 0x194, 3, 0x998, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_D9__CSI1_D9		IOMUX_PAD(0x580, 0x198, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D9__GPIO3_13		IOMUX_PAD(0x580, 0x198, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_D10__CSI1_D10		IOMUX_PAD(0x584, 0x19c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D11__CSI1_D11		IOMUX_PAD(0x588, 0x1a0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D12__CSI1_D12		IOMUX_PAD(0x58c, 0x1a4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D13__CSI1_D13		IOMUX_PAD(0x590, 0x1a8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D14__CSI1_D14		IOMUX_PAD(0x594, 0x1ac, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D15__CSI1_D15		IOMUX_PAD(0x598, 0x1b0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D16__CSI1_D16		IOMUX_PAD(0x59c, 0x1b4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D17__CSI1_D17		IOMUX_PAD(0x5a0, 0x1b8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D18__CSI1_D18		IOMUX_PAD(0x5a4, 0x1bc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D19__CSI1_D19		IOMUX_PAD(0x5a8, 0x1c0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_VSYNC__CSI1_VSYNC		IOMUX_PAD(0x5ac, 0x1c4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_VSYNC__GPIO3_14		IOMUX_PAD(0x5ac, 0x1c4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_HSYNC__CSI1_HSYNC		IOMUX_PAD(0x5b0, 0x1c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_HSYNC__GPIO3_15		IOMUX_PAD(0x5b0, 0x1c8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK	IOMUX_PAD(0x5b4, __NA_, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_MCLK__CSI1_MCLK		IOMUX_PAD(0x5b8, __NA_, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D12__CSI2_D12		IOMUX_PAD(0x5bc, 0x1cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D12__GPIO4_9		IOMUX_PAD(0x5bc, 0x1cc, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_D13__CSI2_D13		IOMUX_PAD(0x5c0, 0x1d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D13__GPIO4_10		IOMUX_PAD(0x5c0, 0x1d0, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_D14__CSI2_D14		IOMUX_PAD(0x5c4, 0x1d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D15__CSI2_D15		IOMUX_PAD(0x5c8, 0x1d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D16__CSI2_D16		IOMUX_PAD(0x5cc, 0x1dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D17__CSI2_D17		IOMUX_PAD(0x5d0, 0x1e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D18__CSI2_D18		IOMUX_PAD(0x5d4, 0x1e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D18__GPIO4_11		IOMUX_PAD(0x5d4, 0x1e4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_D19__CSI2_D19		IOMUX_PAD(0x5d8, 0x1e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D19__GPIO4_12		IOMUX_PAD(0x5d8, 0x1e8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_VSYNC__CSI2_VSYNC		IOMUX_PAD(0x5dc, 0x1ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_VSYNC__GPIO4_13		IOMUX_PAD(0x5dc, 0x1ec, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_HSYNC__CSI2_HSYNC		IOMUX_PAD(0x5e0, 0x1f0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_HSYNC__GPIO4_14		IOMUX_PAD(0x5e0, 0x1f0, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK	IOMUX_PAD(0x5e4, 0x1f4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_PIXCLK__GPIO4_15		IOMUX_PAD(0x5e4, 0x1f4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_I2C1_CLK__GPIO4_16		IOMUX_PAD(0x5e8, 0x1f8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_I2C1_CLK__I2C1_CLK		IOMUX_PAD(0x5e8, 0x1f8, 0x10, __NA_, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_I2C1_DAT__GPIO4_17		IOMUX_PAD(0x5ec, 0x1fc, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_I2C1_DAT__I2C1_DAT		IOMUX_PAD(0x5ec, 0x1fc, 0x10, __NA_, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_TXD__AUD3_TXD		IOMUX_PAD(0x5f0, 0x200, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_TXD__GPIO4_18		IOMUX_PAD(0x5f0, 0x200, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__AUD3_RXD		IOMUX_PAD(0x5f4, 0x204, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__GPIO4_19		IOMUX_PAD(0x5f4, 0x204, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__UART3_RXD		IOMUX_PAD(0x5f4, 0x204, 1, 0x9f4, 2, MX51_UART_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_CK__AUD3_TXC		IOMUX_PAD(0x5f8, 0x208, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_CK__GPIO4_20		IOMUX_PAD(0x5f8, 0x208, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__AUD3_TXFS		IOMUX_PAD(0x5fc, 0x20c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__GPIO4_21		IOMUX_PAD(0x5fc, 0x20c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__UART3_TXD		IOMUX_PAD(0x5fc, 0x20c, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI	IOMUX_PAD(0x600, 0x210, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__GPIO4_22		IOMUX_PAD(0x600, 0x210, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__I2C1_SDA		IOMUX_PAD(0x600, 0x210, 0x11, 0x9b4, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__AUD4_RXD		IOMUX_PAD(0x604, 0x214, 1, 0x8c4, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO	IOMUX_PAD(0x604, 0x214, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__GPIO4_23		IOMUX_PAD(0x604, 0x214, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__AUD4_TXC		IOMUX_PAD(0x608, 0x218, 1, 0x8cc, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0		IOMUX_PAD(0x608, 0x218, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__GPIO4_24		IOMUX_PAD(0x608, 0x218, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__AUD4_TXD		IOMUX_PAD(0x60c, 0x21c, 1, 0x8c8, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1		IOMUX_PAD(0x60c, 0x21c, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__GPIO4_25		IOMUX_PAD(0x60c, 0x21c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__AUD4_TXFS		IOMUX_PAD(0x610, 0x220, 1, 0x8d0, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY		IOMUX_PAD(0x610, 0x220, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__GPIO4_26		IOMUX_PAD(0x610, 0x220, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK	IOMUX_PAD(0x614, 0x224, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__GPIO4_27		IOMUX_PAD(0x614, 0x224, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__I2C1_SCL		IOMUX_PAD(0x614, 0x224, 0x11, 0x9b0, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_UART1_RXD__GPIO4_28		IOMUX_PAD(0x618, 0x228, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_RXD__UART1_RXD		IOMUX_PAD(0x618, 0x228, 0, 0x9e4, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART1_TXD__GPIO4_29		IOMUX_PAD(0x61c, 0x22c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_TXD__PWM2_PWMO		IOMUX_PAD(0x61c, 0x22c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART1_TXD__UART1_TXD		IOMUX_PAD(0x61c, 0x22c, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART1_RTS__GPIO4_30		IOMUX_PAD(0x620, 0x230, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_RTS__UART1_RTS		IOMUX_PAD(0x620, 0x230, 0, 0x9e0, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART1_CTS__GPIO4_31		IOMUX_PAD(0x624, 0x234, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_CTS__UART1_CTS		IOMUX_PAD(0x624, 0x234, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART2_RXD__FIRI_TXD		IOMUX_PAD(0x628, 0x238, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART2_RXD__GPIO1_20		IOMUX_PAD(0x628, 0x238, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART2_RXD__UART2_RXD		IOMUX_PAD(0x628, 0x238, 0, 0x9ec, 2, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART2_TXD__FIRI_RXD		IOMUX_PAD(0x62c, 0x23c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART2_TXD__GPIO1_21		IOMUX_PAD(0x62c, 0x23c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART2_TXD__UART2_TXD		IOMUX_PAD(0x62c, 0x23c, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__CSI1_D0		IOMUX_PAD(0x630, 0x240, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__GPIO1_22		IOMUX_PAD(0x630, 0x240, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__UART1_DTR		IOMUX_PAD(0x630, 0x240, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__UART3_RXD		IOMUX_PAD(0x630, 0x240, 1, 0x9f4, 4, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__CSI1_D1		IOMUX_PAD(0x634, 0x244, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__GPIO1_23		IOMUX_PAD(0x634, 0x244, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__UART1_DSR		IOMUX_PAD(0x634, 0x244, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__UART3_TXD		IOMUX_PAD(0x634, 0x244, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_OWIRE_LINE__GPIO1_24		IOMUX_PAD(0x638, 0x248, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_OWIRE_LINE__OWIRE_LINE		IOMUX_PAD(0x638, 0x248, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_OWIRE_LINE__SPDIF_OUT		IOMUX_PAD(0x638, 0x248, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW0__KEY_ROW0		IOMUX_PAD(0x63c, 0x24c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW1__KEY_ROW1		IOMUX_PAD(0x640, 0x250, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW2__KEY_ROW2		IOMUX_PAD(0x644, 0x254, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW3__KEY_ROW3		IOMUX_PAD(0x648, 0x258, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL0__KEY_COL0		IOMUX_PAD(0x64c, 0x25c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL0__PLL1_BYP		IOMUX_PAD(0x64c, 0x25c, 7, 0x90c, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL1__KEY_COL1		IOMUX_PAD(0x650, 0x260, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL1__PLL2_BYP		IOMUX_PAD(0x650, 0x260, 7, 0x910, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL2__KEY_COL2		IOMUX_PAD(0x654, 0x264, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL2__PLL3_BYP		IOMUX_PAD(0x654, 0x264, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL3__KEY_COL3		IOMUX_PAD(0x658, 0x268, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__I2C2_SCL		IOMUX_PAD(0x65c, 0x26c, 0x13, 0x9b8, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__KEY_COL4		IOMUX_PAD(0x65c, 0x26c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__SPDIF_OUT1		IOMUX_PAD(0x65c, 0x26c, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__UART1_RI		IOMUX_PAD(0x65c, 0x26c, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__UART3_RTS		IOMUX_PAD(0x65c, 0x26c, 2, 0x9f0, 4, MX51_UART_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__I2C2_SDA		IOMUX_PAD(0x660, 0x270, 0x13, 0x9bc, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__KEY_COL5		IOMUX_PAD(0x660, 0x270, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__UART1_DCD		IOMUX_PAD(0x660, 0x270, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__UART3_CTS		IOMUX_PAD(0x660, 0x270, 2, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__CSPI_SCLK		IOMUX_PAD(0x678, 0x278, 1, 0x914, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__GPIO1_25		IOMUX_PAD(0x678, 0x278, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__I2C2_SCL		IOMUX_PAD(0x678, 0x278, 0x15, 0x9b8, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__USBH1_CLK		IOMUX_PAD(0x678, 0x278, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__CSPI_MOSI		IOMUX_PAD(0x67c, 0x27c, 1, 0x91c, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__GPIO1_26		IOMUX_PAD(0x67c, 0x27c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__I2C2_SDA		IOMUX_PAD(0x67c, 0x27c, 0x15, 0x9bc, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__USBH1_DIR		IOMUX_PAD(0x67c, 0x27c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__CSPI_RDY		IOMUX_PAD(0x680, 0x280, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__GPIO1_27		IOMUX_PAD(0x680, 0x280, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__UART3_RXD		IOMUX_PAD(0x680, 0x280, 5, 0x9f4, 6, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__USBH1_STP		IOMUX_PAD(0x680, 0x280, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__CSPI_MISO		IOMUX_PAD(0x684, 0x284, 1, 0x918, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__GPIO1_28		IOMUX_PAD(0x684, 0x284, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__UART3_TXD		IOMUX_PAD(0x684, 0x284, 5, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__USBH1_NXT		IOMUX_PAD(0x684, 0x284, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA0__GPIO1_11		IOMUX_PAD(0x688, 0x288, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA0__UART2_CTS		IOMUX_PAD(0x688, 0x288, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA0__USBH1_DATA0	IOMUX_PAD(0x688, 0x288, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA1__GPIO1_12		IOMUX_PAD(0x68c, 0x28c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA1__UART2_RXD		IOMUX_PAD(0x68c, 0x28c, 1, 0x9ec, 4, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA1__USBH1_DATA1	IOMUX_PAD(0x68c, 0x28c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA2__GPIO1_13		IOMUX_PAD(0x690, 0x290, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA2__UART2_TXD		IOMUX_PAD(0x690, 0x290, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA2__USBH1_DATA2	IOMUX_PAD(0x690, 0x290, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA3__GPIO1_14		IOMUX_PAD(0x694, 0x294, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA3__UART2_RTS		IOMUX_PAD(0x694, 0x294, 1, 0x9e8, 5, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA3__USBH1_DATA3	IOMUX_PAD(0x694, 0x294, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA4__CSPI_SS0		IOMUX_PAD(0x698, 0x298, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA4__GPIO1_15		IOMUX_PAD(0x698, 0x298, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA4__USBH1_DATA4	IOMUX_PAD(0x698, 0x298, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA5__CSPI_SS1		IOMUX_PAD(0x69c, 0x29c, 1, 0x920, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA5__GPIO1_16		IOMUX_PAD(0x69c, 0x29c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA5__USBH1_DATA5	IOMUX_PAD(0x69c, 0x29c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA6__CSPI_SS3		IOMUX_PAD(0x6a0, 0x2a0, 1, 0x928, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA6__GPIO1_17		IOMUX_PAD(0x6a0, 0x2a0, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA6__USBH1_DATA6	IOMUX_PAD(0x6a0, 0x2a0, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__ECSPI1_SS3	IOMUX_PAD(0x6a4, 0x2a4, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__ECSPI2_SS3	IOMUX_PAD(0x6a4, 0x2a4, 5, 0x934, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__GPIO1_18		IOMUX_PAD(0x6a4, 0x2a4, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__USBH1_DATA7	IOMUX_PAD(0x6a4, 0x2a4, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_DI1_PIN11__DI1_PIN11		IOMUX_PAD(0x6a8, 0x2a8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN11__ECSPI1_SS2		IOMUX_PAD(0x6a8, 0x2a8, 7, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_DI1_PIN11__GPIO3_0		IOMUX_PAD(0x6a8, 0x2a8, 4, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN12__DI1_PIN12		IOMUX_PAD(0x6ac, 0x2ac, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN12__GPIO3_1		IOMUX_PAD(0x6ac, 0x2ac, 4, 0x978, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN13__DI1_PIN13		IOMUX_PAD(0x6b0, 0x2b0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN13__GPIO3_2		IOMUX_PAD(0x6b0, 0x2b0, 4, 0x97c, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_D0_CS__DI1_D0_CS		IOMUX_PAD(0x6b4, 0x2b4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D0_CS__GPIO3_3		IOMUX_PAD(0x6b4, 0x2b4, 4, 0x980, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__DI1_D1_CS		IOMUX_PAD(0x6b8, 0x2b8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__DISP1_PIN14		IOMUX_PAD(0x6b8, 0x2b8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__DISP1_PIN5		IOMUX_PAD(0x6b8, 0x2b8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__GPIO3_4		IOMUX_PAD(0x6b8, 0x2b8, 4, 0x984, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1	IOMUX_PAD(0x6bc, 0x2bc, 2, 0x9a4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN	IOMUX_PAD(0x6bc, 0x2bc, 0, 0x9c4, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__GPIO3_5	IOMUX_PAD(0x6bc, 0x2bc, 4, 0x988, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6	IOMUX_PAD(0x6c0, 0x2c0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO	IOMUX_PAD(0x6c0, 0x2c0, 0, 0x9c4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__GPIO3_6	IOMUX_PAD(0x6c0, 0x2c0, 4, 0x98c, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17	IOMUX_PAD(0x6c4, 0x2c4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7	IOMUX_PAD(0x6c4, 0x2c4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK	IOMUX_PAD(0x6c4, 0x2c4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__GPIO3_7	IOMUX_PAD(0x6c4, 0x2c4, 4, 0x990, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK	IOMUX_PAD(0x6c8, 0x2c8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN16	IOMUX_PAD(0x6c8, 0x2c8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN8	IOMUX_PAD(0x6c8, 0x2c8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__GPIO3_8		IOMUX_PAD(0x6c8, 0x2c8, 4, 0x994, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT0__DISP1_DAT0		IOMUX_PAD(0x6cc, 0x2cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT1__DISP1_DAT1		IOMUX_PAD(0x6d0, 0x2d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT2__DISP1_DAT2		IOMUX_PAD(0x6d4, 0x2d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT3__DISP1_DAT3		IOMUX_PAD(0x6d8, 0x2d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT4__DISP1_DAT4		IOMUX_PAD(0x6dc, 0x2dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT5__DISP1_DAT5		IOMUX_PAD(0x6e0, 0x2e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT6__BOOT_USB_SRC	IOMUX_PAD(0x6e4, 0x2e4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT6__DISP1_DAT6		IOMUX_PAD(0x6e4, 0x2e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG	IOMUX_PAD(0x6e8, 0x2e8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT7__DISP1_DAT7		IOMUX_PAD(0x6e8, 0x2e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT8__BOOT_SRC0		IOMUX_PAD(0x6ec, 0x2ec, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT8__DISP1_DAT8		IOMUX_PAD(0x6ec, 0x2ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT9__BOOT_SRC1		IOMUX_PAD(0x6f0, 0x2f0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT9__DISP1_DAT9		IOMUX_PAD(0x6f0, 0x2f0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE	IOMUX_PAD(0x6f4, 0x2f4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT10__DISP1_DAT10	IOMUX_PAD(0x6f4, 0x2f4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2	IOMUX_PAD(0x6f8, 0x2f8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT11__DISP1_DAT11	IOMUX_PAD(0x6f8, 0x2f8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL	IOMUX_PAD(0x6fc, 0x2fc, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT12__DISP1_DAT12	IOMUX_PAD(0x6fc, 0x2fc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0	IOMUX_PAD(0x700, 0x300, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT13__DISP1_DAT13	IOMUX_PAD(0x700, 0x300, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1	IOMUX_PAD(0x704, 0x304, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT14__DISP1_DAT14	IOMUX_PAD(0x704, 0x304, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH	IOMUX_PAD(0x708, 0x308, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT15__DISP1_DAT15	IOMUX_PAD(0x708, 0x308, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0	IOMUX_PAD(0x70c, 0x30c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT16__DISP1_DAT16	IOMUX_PAD(0x70c, 0x30c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1	IOMUX_PAD(0x710, 0x310, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT17__DISP1_DAT17	IOMUX_PAD(0x710, 0x310, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0	IOMUX_PAD(0x714, 0x314, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__DISP1_DAT18	IOMUX_PAD(0x714, 0x314, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__DISP2_PIN11	IOMUX_PAD(0x714, 0x314, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__DISP2_PIN5	IOMUX_PAD(0x714, 0x314, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1	IOMUX_PAD(0x718, 0x318, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__DISP1_DAT19	IOMUX_PAD(0x718, 0x318, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__DISP2_PIN12	IOMUX_PAD(0x718, 0x318, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__DISP2_PIN6	IOMUX_PAD(0x718, 0x318, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0	IOMUX_PAD(0x71c, 0x31c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__DISP1_DAT20	IOMUX_PAD(0x71c, 0x31c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__DISP2_PIN13	IOMUX_PAD(0x71c, 0x31c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__DISP2_PIN7	IOMUX_PAD(0x71c, 0x31c, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1	IOMUX_PAD(0x720, 0x320, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__DISP1_DAT21	IOMUX_PAD(0x720, 0x320, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__DISP2_PIN14	IOMUX_PAD(0x720, 0x320, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__DISP2_PIN8	IOMUX_PAD(0x720, 0x320, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0	IOMUX_PAD(0x724, 0x324, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__DISP1_DAT22	IOMUX_PAD(0x724, 0x324, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__DISP2_D0_CS	IOMUX_PAD(0x724, 0x324, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__DISP2_DAT16	IOMUX_PAD(0x724, 0x324, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1	IOMUX_PAD(0x728, 0x328, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP1_DAT23	IOMUX_PAD(0x728, 0x328, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP2_D1_CS	IOMUX_PAD(0x728, 0x328, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP2_DAT17	IOMUX_PAD(0x728, 0x328, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP2_SER_CS	IOMUX_PAD(0x728, 0x328, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN3__DI1_PIN3		IOMUX_PAD(0x72c, 0x32c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN2__DI1_PIN2		IOMUX_PAD(0x734, 0x330, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP2__DISP1_SER_CLK		IOMUX_PAD(0x740, 0x338, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP2__DISP2_WAIT		IOMUX_PAD(0x740, 0x338, 2, 0x9a8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP3__CSI1_DATA_EN		IOMUX_PAD(0x744, 0x33c, 3, 0x9a0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP3__DISP1_SER_DIO		IOMUX_PAD(0x744, 0x33c, 0, 0x9c0, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP3__FEC_TX_ER		IOMUX_PAD(0x744, 0x33c, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DI2_PIN4__CSI2_DATA_EN		IOMUX_PAD(0x748, 0x340, 3, 0x99c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN4__DI2_PIN4		IOMUX_PAD(0x748, 0x340, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN4__FEC_CRS		IOMUX_PAD(0x748, 0x340, 2, 0x950, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN2__DI2_PIN2		IOMUX_PAD(0x74c, 0x344, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN2__FEC_MDC		IOMUX_PAD(0x74c, 0x344, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DI2_PIN3__DI2_PIN3		IOMUX_PAD(0x750, 0x348, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN3__FEC_MDIO		IOMUX_PAD(0x750, 0x348, 2, 0x954, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK	IOMUX_PAD(0x754, 0x34c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_DISP_CLK__FEC_RDATA1	IOMUX_PAD(0x754, 0x34c, 2, 0x95c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__DI2_PIN15		IOMUX_PAD(0x758, 0x350, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__DISP1_SER_DIN		IOMUX_PAD(0x758, 0x350, 0, 0x9c0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__DISP2_PIN1		IOMUX_PAD(0x758, 0x350, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__FEC_RDATA2		IOMUX_PAD(0x758, 0x350, 2, 0x960, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__DISP2_DAT0		IOMUX_PAD(0x75c, 0x354, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__FEC_RDATA3		IOMUX_PAD(0x75c, 0x354, 2, 0x964, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__KEY_COL6		IOMUX_PAD(0x75c, 0x354, 4, 0x9c8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__UART3_RXD		IOMUX_PAD(0x75c, 0x354, 5, 0x9f4, 8, MX51_UART_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__USBH3_CLK		IOMUX_PAD(0x75c, 0x354, 3, 0x9f8, 1, MX51_UART_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__DISP2_DAT1		IOMUX_PAD(0x760, 0x358, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__FEC_RX_ER		IOMUX_PAD(0x760, 0x358, 2, 0x970, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__KEY_COL7		IOMUX_PAD(0x760, 0x358, 4, 0x9cc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__UART3_TXD		IOMUX_PAD(0x760, 0x358, 5, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__USBH3_DIR		IOMUX_PAD(0x760, 0x358, 3, 0xa1c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT2__DISP2_DAT2		IOMUX_PAD(0x764, 0x35c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT3__DISP2_DAT3		IOMUX_PAD(0x768, 0x360, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT4__DISP2_DAT4		IOMUX_PAD(0x76c, 0x364, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT5__DISP2_DAT5		IOMUX_PAD(0x770, 0x368, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__DISP2_DAT6		IOMUX_PAD(0x774, 0x36c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__FEC_TDATA1		IOMUX_PAD(0x774, 0x36c, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT6__GPIO1_19		IOMUX_PAD(0x774, 0x36c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__KEY_ROW4		IOMUX_PAD(0x774, 0x36c, 4, 0x9d0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__USBH3_STP		IOMUX_PAD(0x774, 0x36c, 3, 0xa24, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__DISP2_DAT7		IOMUX_PAD(0x778, 0x370, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__FEC_TDATA2		IOMUX_PAD(0x778, 0x370, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT7__GPIO1_29		IOMUX_PAD(0x778, 0x370, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__KEY_ROW5		IOMUX_PAD(0x778, 0x370, 4, 0x9d4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__USBH3_NXT		IOMUX_PAD(0x778, 0x370, 3, 0xa20, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__DISP2_DAT8		IOMUX_PAD(0x77c, 0x374, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__FEC_TDATA3		IOMUX_PAD(0x77c, 0x374, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT8__GPIO1_30		IOMUX_PAD(0x77c, 0x374, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__KEY_ROW6		IOMUX_PAD(0x77c, 0x374, 4, 0x9d8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__USBH3_DATA0	IOMUX_PAD(0x77c, 0x374, 3, 0x9fc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__AUD6_RXC		IOMUX_PAD(0x780, 0x378, 4, 0x8f4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__DISP2_DAT9		IOMUX_PAD(0x780, 0x378, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__FEC_TX_EN		IOMUX_PAD(0x780, 0x378, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT9__GPIO1_31		IOMUX_PAD(0x780, 0x378, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__USBH3_DATA1	IOMUX_PAD(0x780, 0x378, 3, 0xa00, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__DISP2_DAT10	IOMUX_PAD(0x784, 0x37c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__DISP2_SER_CS	IOMUX_PAD(0x784, 0x37c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__FEC_COL		IOMUX_PAD(0x784, 0x37c, 2, 0x94c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__KEY_ROW7		IOMUX_PAD(0x784, 0x37c, 4, 0x9dc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__USBH3_DATA2	IOMUX_PAD(0x784, 0x37c, 3, 0xa04, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__AUD6_TXD		IOMUX_PAD(0x788, 0x380, 4, 0x8f0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__DISP2_DAT11	IOMUX_PAD(0x788, 0x380, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__FEC_RX_CLK	IOMUX_PAD(0x788, 0x380, 2, 0x968, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__GPIO1_10		IOMUX_PAD(0x788, 0x380, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__USBH3_DATA3	IOMUX_PAD(0x788, 0x380, 3, 0xa08, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__AUD6_RXD		IOMUX_PAD(0x78c, 0x384, 4, 0x8ec, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__DISP2_DAT12	IOMUX_PAD(0x78c, 0x384, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__FEC_RX_DV		IOMUX_PAD(0x78c, 0x384, 2, 0x96c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__USBH3_DATA4	IOMUX_PAD(0x78c, 0x384, 3, 0xa0c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT13__AUD6_TXC		IOMUX_PAD(0x790, 0x388, 4, 0x8fc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT13__DISP2_DAT13	IOMUX_PAD(0x790, 0x388, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT13__FEC_TX_CLK	IOMUX_PAD(0x790, 0x388, 2, 0x974, 1, MX51_PAD_CTRL_4)
+#define MX51_PAD_DISP2_DAT13__USBH3_DATA5	IOMUX_PAD(0x790, 0x388, 3, 0xa10, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT14__AUD6_TXFS		IOMUX_PAD(0x794, 0x38c, 4, 0x900, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT14__DISP2_DAT14	IOMUX_PAD(0x794, 0x38c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT14__FEC_RDATA0	IOMUX_PAD(0x794, 0x38c, 2, 0x958, 1, MX51_PAD_CTRL_4)
+#define MX51_PAD_DISP2_DAT14__USBH3_DATA6	IOMUX_PAD(0x794, 0x38c, 3, 0xa14, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__AUD6_RXFS		IOMUX_PAD(0x798, 0x390, 4, 0x8f8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__DISP1_SER_CS	IOMUX_PAD(0x798, 0x390, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__DISP2_DAT15	IOMUX_PAD(0x798, 0x390, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__FEC_TDATA0	IOMUX_PAD(0x798, 0x390, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT15__USBH3_DATA7	IOMUX_PAD(0x798, 0x390, 3, 0xa18, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__AUD5_RXFS		IOMUX_PAD(0x79c, 0x394, 1, 0x8e0, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__CSPI_MOSI		IOMUX_PAD(0x79c, 0x394, 2, 0x91c, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__SD1_CMD		IOMUX_PAD(0x79c, 0x394, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__AUD5_RXC		IOMUX_PAD(0x7a0, 0x398, 1, 0x8dc, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__CSPI_SCLK		IOMUX_PAD(0x7a0, 0x398, 2, 0x914, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__SD1_CLK		IOMUX_PAD(0x7a0, 0x398, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD1_DATA0__AUD5_TXD		IOMUX_PAD(0x7a4, 0x39c, 1, 0x8d8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__CSPI_MISO		IOMUX_PAD(0x7a4, 0x39c, 2, 0x918, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__SD1_DATA0		IOMUX_PAD(0x7a4, 0x39c, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_EIM_DA0__EIM_DA0		IOMUX_PAD(__NA_, 0x01c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA1__EIM_DA1		IOMUX_PAD(__NA_, 0x020, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA2__EIM_DA2		IOMUX_PAD(__NA_, 0x024, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA3__EIM_DA3		IOMUX_PAD(__NA_, 0x028, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__AUD5_RXD		IOMUX_PAD(0x7a8, 0x3a0, 1, 0x8d4, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__SD1_DATA1		IOMUX_PAD(0x7a8, 0x3a0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_EIM_DA4__EIM_DA4		IOMUX_PAD(__NA_, 0x02c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA5__EIM_DA5		IOMUX_PAD(__NA_, 0x030, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA6__EIM_DA6		IOMUX_PAD(__NA_, 0x034, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA7__EIM_DA7		IOMUX_PAD(__NA_, 0x038, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__AUD5_TXC		IOMUX_PAD(0x7ac, 0x3a4, 1, 0x8e4, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__SD1_DATA2		IOMUX_PAD(0x7ac, 0x3a4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_EIM_DA10__EIM_DA10		IOMUX_PAD(__NA_, 0x044, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA11__EIM_DA11		IOMUX_PAD(__NA_, 0x048, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA8__EIM_DA8		IOMUX_PAD(__NA_, 0x03c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA9__EIM_DA9		IOMUX_PAD(__NA_, 0x040, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__AUD5_TXFS		IOMUX_PAD(0x7b0, 0x3a8, 1, 0x8e8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__CSPI_SS1		IOMUX_PAD(0x7b0, 0x3a8, 2, 0x920, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__SD1_DATA3		IOMUX_PAD(0x7b0, 0x3a8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_GPIO1_0__CSPI_SS2		IOMUX_PAD(0x7b4, 0x3ac, 2, 0x924, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_GPIO1_0__GPIO1_0		IOMUX_PAD(0x7b4, 0x3ac, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_0__SD1_CD		IOMUX_PAD(0x7b4, 0x3ac, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_GPIO1_1__CSPI_MISO		IOMUX_PAD(0x7b8, 0x3b0, 2, 0x918, 2, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_GPIO1_1__GPIO1_1		IOMUX_PAD(0x7b8, 0x3b0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_1__SD1_WP		IOMUX_PAD(0x7b8, 0x3b0, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_EIM_DA12__EIM_DA12		IOMUX_PAD(__NA_, 0x04c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA13__EIM_DA13		IOMUX_PAD(__NA_, 0x050, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA14__EIM_DA14		IOMUX_PAD(__NA_, 0x054, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA15__EIM_DA15		IOMUX_PAD(__NA_, 0x058, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__CSPI_MOSI		IOMUX_PAD(__NA_, 0x3b4, 2, 0x91c, 3, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__I2C1_SCL		IOMUX_PAD(0x7bc, 0x3b4, 0x11, 0x9b0, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__SD2_CMD		IOMUX_PAD(0x7bc, 0x3b4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__CSPI_SCLK		IOMUX_PAD(0x7c0, 0x3b8, 2, 0x914, 3, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__I2C1_SDA		IOMUX_PAD(0x7c0, 0x3b8, 0x11, 0x9b4, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__SD2_CLK		IOMUX_PAD(0x7c0, 0x3b8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD2_DATA0__CSPI_MISO		IOMUX_PAD(0x7c4, 0x3bc, 2, 0x918, 3, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA0__SD1_DAT4		IOMUX_PAD(0x7c4, 0x3bc, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA0__SD2_DATA0		IOMUX_PAD(0x7c4, 0x3bc, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__SD1_DAT5		IOMUX_PAD(0x7c8, 0x3c0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__SD2_DATA1		IOMUX_PAD(0x7c8, 0x3c0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__USBH3_H2_DP		IOMUX_PAD(0x7c8, 0x3c0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__SD1_DAT6		IOMUX_PAD(0x7cc, 0x3c4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__SD2_DATA2		IOMUX_PAD(0x7cc, 0x3c4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__USBH3_H2_DM		IOMUX_PAD(0x7cc, 0x3c4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__CSPI_SS2		IOMUX_PAD(0x7d0, 0x3c8, 2, 0x924, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__SD1_DAT7		IOMUX_PAD(0x7d0, 0x3c8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__SD2_DATA3		IOMUX_PAD(0x7d0, 0x3c8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__CCM_OUT_2		IOMUX_PAD(0x7d4, 0x3cc, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__GPIO1_2		IOMUX_PAD(0x7d4, 0x3cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__I2C2_SCL		IOMUX_PAD(0x7d4, 0x3cc, 0x12, 0x9b8, 3, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__PLL1_BYP		IOMUX_PAD(0x7d4, 0x3cc, 7, 0x90c, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__PWM1_PWMO		IOMUX_PAD(0x7d4, 0x3cc, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__GPIO1_3		IOMUX_PAD(0x7d8, 0x3d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__I2C2_SDA		IOMUX_PAD(0x7d8, 0x3d0, 0x12, 0x9bc, 3, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__PLL2_BYP		IOMUX_PAD(0x7d8, 0x3d0, 7, 0x910, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__PWM2_PWMO		IOMUX_PAD(0x7d8, 0x3d0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	IOMUX_PAD(0x7fc, 0x3d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B	IOMUX_PAD(0x7fc, 0x3d4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__DISP2_EXT_CLK		IOMUX_PAD(0x804, 0x3d8, 4, 0x908, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__EIM_RDY		IOMUX_PAD(0x804, 0x3d8, 3, 0x938, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__GPIO1_4		IOMUX_PAD(0x804, 0x3d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__WDOG1_WDOG_B		IOMUX_PAD(0x804, 0x3d8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__CSI2_MCLK		IOMUX_PAD(0x808, 0x3dc, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__DISP2_PIN16		IOMUX_PAD(0x808, 0x3dc, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__GPIO1_5		IOMUX_PAD(0x808, 0x3dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__WDOG2_WDOG_B		IOMUX_PAD(0x808, 0x3dc, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__DISP2_PIN17		IOMUX_PAD(0x80c, 0x3e0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__GPIO1_6		IOMUX_PAD(0x80c, 0x3e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__REF_EN_B		IOMUX_PAD(0x80c, 0x3e0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__CCM_OUT_0		IOMUX_PAD(0x810, 0x3e4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__GPIO1_7		IOMUX_PAD(0x810, 0x3e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__SD2_WP		IOMUX_PAD(0x810, 0x3e4, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__SPDIF_OUT1		IOMUX_PAD(0x810, 0x3e4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__CSI2_DATA_EN		IOMUX_PAD(0x814, 0x3e8, 2, 0x99c, 2, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__GPIO1_8		IOMUX_PAD(0x814, 0x3e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__SD2_CD		IOMUX_PAD(0x814, 0x3e8, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__USBH3_PWR		IOMUX_PAD(0x814, 0x3e8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__CCM_OUT_1		IOMUX_PAD(0x818, 0x3ec, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__DISP2_D1_CS		IOMUX_PAD(0x818, 0x3ec, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__DISP2_SER_CS		IOMUX_PAD(0x818, 0x3ec, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__GPIO1_9		IOMUX_PAD(0x818, 0x3ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__SD2_LCTL		IOMUX_PAD(0x818, 0x3ec, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__USBH3_OC		IOMUX_PAD(0x818, 0x3ec, 1, __NA_, 0, NO_PAD_CTRL)
 
 #endif /* __MACH_IOMUX_MX51_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/iomux-mx53.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/iomux-mx53.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/iomux-mx53.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/iomux-mx53.h	2012-01-04 18:55:44.000000000 -0500
@@ -23,2359 +23,1197 @@
 
 /* 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_PAD_I	0x00
+#define __NA_	0x00
 
 #define MX53_UART_PAD_CTRL		(PAD_CTL_PKE | PAD_CTL_PUE |	\
 		PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
 #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)
-#define PAD_CTRL_I2C	(PAD_CTL_SRE_FAST | PAD_CTL_ODE | PAD_CTL_PKE | \
-			PAD_CTL_PUE | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP \
-			| PAD_CTL_HYS)
 
-#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, 0, 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, 0x0, 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, 0x0, 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, 0x0, 0, 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, 0x0, 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, 0x0, 0, 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, 0x0, 0, 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, 0x0, 0, 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, 0x0, 0, 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 | IOMUX_CONFIG_SION, 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 | IOMUX_CONFIG_SION, 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 | IOMUX_CONFIG_SION, 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, 0x0, 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 | IOMUX_CONFIG_SION, 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, 0x0, 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, 0x0, 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, 0x0, 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, 0x0, 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 | IOMUX_CONFIG_SION, 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, 0x0, 0, 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, 7 | IOMUX_CONFIG_SION, 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, 0x0, 0, 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, 0x0, 0, 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, 0x0, 0, 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, 0x0, 0, 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, 0x0, 0, 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, 0x0, 0, 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, 0, 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, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__ESDHC4_DAT6		IOMUX_PAD(0x640, 0x2BC, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6	IOMUX_PAD(0x640, 0x2BC, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6	IOMUX_PAD(0x640, 0x2BC, 6, 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 | IOMUX_CONFIG_SION, 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, 0x0, 0, 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__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(MX53_UART_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(MX53_UART_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(MX53_UART_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(MX53_UART_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(PAD_CTRL_I2C))
-#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(PAD_CTRL_I2C))
-#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(MX53_UART_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(MX53_UART_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(PAD_CTRL_I2C))
-#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(PAD_CTRL_I2C))
-#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(MX53_UART_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(MX53_UART_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(MX53_UART_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(MX53_UART_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(MX53_UART_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(MX53_UART_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(MX53_UART_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(MX53_UART_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(PAD_CTRL_I2C))
-#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(PAD_CTRL_I2C))
-#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(PAD_CTRL_I2C))
-#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(PAD_CTRL_I2C))
-#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(MX53_UART_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(MX53_UART_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(PAD_CTRL_I2C))
-#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(MX53_UART_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(MX53_UART_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(MX53_UART_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(MX53_UART_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(MX53_UART_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(MX53_UART_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(MX53_UART_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(PAD_CTRL_I2C))
-#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(MX53_UART_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(MX53_UART_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(MX53_UART_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(MX53_UART_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(MX53_UART_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(PAD_CTRL_I2C))
-#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(PAD_CTRL_I2C))
-#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(PAD_CTRL_I2C))
-#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(MX53_UART_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(MX53_UART_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(PAD_CTRL_I2C))
-#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))
+#define MX53_PAD_GPIO_19__KPP_COL_5			IOMUX_PAD(0x348, 0x020, 0, 0x840, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__GPIO4_5			IOMUX_PAD(0x348, 0x020, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__CCM_CLKO			IOMUX_PAD(0x348, 0x020, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__SPDIF_OUT1			IOMUX_PAD(0x348, 0x020, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2		IOMUX_PAD(0x348, 0x020, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__ECSPI1_RDY			IOMUX_PAD(0x348, 0x020, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__FEC_TDATA_3			IOMUX_PAD(0x348, 0x020, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__SRC_INT_BOOT			IOMUX_PAD(0x348, 0x020, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__KPP_COL_0			IOMUX_PAD(0x34C, 0x024, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__GPIO4_6			IOMUX_PAD(0x34C, 0x024, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC		IOMUX_PAD(0x34C, 0x024, 2, 0x758, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__UART4_TXD_MUX		IOMUX_PAD(0x34C, 0x024, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__ECSPI1_SCLK			IOMUX_PAD(0x34C, 0x024, 5, 0x79C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__FEC_RDATA_3			IOMUX_PAD(0x34C, 0x024, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__SRC_ANY_PU_RST		IOMUX_PAD(0x34C, 0x024, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__KPP_ROW_0			IOMUX_PAD(0x350, 0x028, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__GPIO4_7			IOMUX_PAD(0x350, 0x028, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD		IOMUX_PAD(0x350, 0x028, 2, 0x74C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__UART4_RXD_MUX		IOMUX_PAD(0x350, 0x028, 4, 0x890, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__ECSPI1_MOSI			IOMUX_PAD(0x350, 0x028, 5, 0x7A4, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__FEC_TX_ER			IOMUX_PAD(0x350, 0x028, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__KPP_COL_1			IOMUX_PAD(0x354, 0x02C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__GPIO4_8			IOMUX_PAD(0x354, 0x02C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS		IOMUX_PAD(0x354, 0x02C, 2, 0x75C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__UART5_TXD_MUX		IOMUX_PAD(0x354, 0x02C, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__ECSPI1_MISO			IOMUX_PAD(0x354, 0x02C, 5, 0x7A0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__FEC_RX_CLK			IOMUX_PAD(0x354, 0x02C, 6, 0x808, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__USBPHY1_TXREADY		IOMUX_PAD(0x354, 0x02C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__KPP_ROW_1			IOMUX_PAD(0x358, 0x030, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__GPIO4_9			IOMUX_PAD(0x358, 0x030, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD		IOMUX_PAD(0x358, 0x030, 2, 0x748, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__UART5_RXD_MUX		IOMUX_PAD(0x358, 0x030, 4, 0x898, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__ECSPI1_SS0			IOMUX_PAD(0x358, 0x030, 5, 0x7A8, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__FEC_COL			IOMUX_PAD(0x358, 0x030, 6, 0x800, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__USBPHY1_RXVALID		IOMUX_PAD(0x358, 0x030, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__KPP_COL_2			IOMUX_PAD(0x35C, 0x034, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__GPIO4_10			IOMUX_PAD(0x35C, 0x034, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__CAN1_TXCAN			IOMUX_PAD(0x35C, 0x034, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__FEC_MDIO			IOMUX_PAD(0x35C, 0x034, 4, 0x804, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__ECSPI1_SS1			IOMUX_PAD(0x35C, 0x034, 5, 0x7AC, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__FEC_RDATA_2			IOMUX_PAD(0x35C, 0x034, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE		IOMUX_PAD(0x35C, 0x034, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__KPP_ROW_2			IOMUX_PAD(0x360, 0x038, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__GPIO4_11			IOMUX_PAD(0x360, 0x038, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__CAN1_RXCAN			IOMUX_PAD(0x360, 0x038, 2, 0x760, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__FEC_MDC			IOMUX_PAD(0x360, 0x038, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__ECSPI1_SS2			IOMUX_PAD(0x360, 0x038, 5, 0x7B0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__FEC_TDATA_2			IOMUX_PAD(0x360, 0x038, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__USBPHY1_RXERROR		IOMUX_PAD(0x360, 0x038, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__KPP_COL_3			IOMUX_PAD(0x364, 0x03C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__GPIO4_12			IOMUX_PAD(0x364, 0x03C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__USBOH3_H2_DP			IOMUX_PAD(0x364, 0x03C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__SPDIF_IN1			IOMUX_PAD(0x364, 0x03C, 3, 0x870, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__I2C2_SCL			IOMUX_PAD(0x364, 0x03C, 4 | IOMUX_CONFIG_SION, 0x81C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__ECSPI1_SS3			IOMUX_PAD(0x364, 0x03C, 5, 0x7B4, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__FEC_CRS			IOMUX_PAD(0x364, 0x03C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK		IOMUX_PAD(0x364, 0x03C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__KPP_ROW_3			IOMUX_PAD(0x368, 0x040, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__GPIO4_13			IOMUX_PAD(0x368, 0x040, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__USBOH3_H2_DM			IOMUX_PAD(0x368, 0x040, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK		IOMUX_PAD(0x368, 0x040, 3, 0x768, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__I2C2_SDA			IOMUX_PAD(0x368, 0x040, 4 | IOMUX_CONFIG_SION, 0x820, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__OSC32K_32K_OUT		IOMUX_PAD(0x368, 0x040, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__CCM_PLL4_BYP			IOMUX_PAD(0x368, 0x040, 6, 0x77C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0		IOMUX_PAD(0x368, 0x040, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__KPP_COL_4			IOMUX_PAD(0x36C, 0x044, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__GPIO4_14			IOMUX_PAD(0x36C, 0x044, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__CAN2_TXCAN			IOMUX_PAD(0x36C, 0x044, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__IPU_SISG_4			IOMUX_PAD(0x36C, 0x044, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__UART5_RTS			IOMUX_PAD(0x36C, 0x044, 4, 0x894, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC		IOMUX_PAD(0x36C, 0x044, 5, 0x89C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1		IOMUX_PAD(0x36C, 0x044, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__KPP_ROW_4			IOMUX_PAD(0x370, 0x048, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__GPIO4_15			IOMUX_PAD(0x370, 0x048, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__CAN2_RXCAN			IOMUX_PAD(0x370, 0x048, 2, 0x764, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__IPU_SISG_5			IOMUX_PAD(0x370, 0x048, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__UART5_CTS			IOMUX_PAD(0x370, 0x048, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR		IOMUX_PAD(0x370, 0x048, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID		IOMUX_PAD(0x370, 0x048, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK		IOMUX_PAD(0x378, 0x04C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__GPIO4_16			IOMUX_PAD(0x378, 0x04C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR		IOMUX_PAD(0x378, 0x04C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0	IOMUX_PAD(0x378, 0x04C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0		IOMUX_PAD(0x378, 0x04C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID		IOMUX_PAD(0x378, 0x04C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__IPU_DI0_PIN15		IOMUX_PAD(0x37C, 0x050, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__GPIO4_17			IOMUX_PAD(0x37C, 0x050, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC		IOMUX_PAD(0x37C, 0x050, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1	IOMUX_PAD(0x37C, 0x050, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1		IOMUX_PAD(0x37C, 0x050, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__USBPHY1_BVALID		IOMUX_PAD(0x37C, 0x050, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__IPU_DI0_PIN2			IOMUX_PAD(0x380, 0x054, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__GPIO4_18			IOMUX_PAD(0x380, 0x054, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD		IOMUX_PAD(0x380, 0x054, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2	IOMUX_PAD(0x380, 0x054, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2		IOMUX_PAD(0x380, 0x054, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION		IOMUX_PAD(0x380, 0x054, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__IPU_DI0_PIN3			IOMUX_PAD(0x384, 0x058, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__GPIO4_19			IOMUX_PAD(0x384, 0x058, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS		IOMUX_PAD(0x384, 0x058, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3	IOMUX_PAD(0x384, 0x058, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3		IOMUX_PAD(0x384, 0x058, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__USBPHY1_IDDIG		IOMUX_PAD(0x384, 0x058, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__IPU_DI0_PIN4			IOMUX_PAD(0x388, 0x05C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__GPIO4_20			IOMUX_PAD(0x388, 0x05C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD		IOMUX_PAD(0x388, 0x05C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__ESDHC1_WP			IOMUX_PAD(0x388, 0x05C, 3, 0x7FC, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD		IOMUX_PAD(0x388, 0x05C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4		IOMUX_PAD(0x388, 0x05C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT	IOMUX_PAD(0x388, 0x05C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0		IOMUX_PAD(0x38C, 0x060, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__GPIO4_21			IOMUX_PAD(0x38C, 0x060, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__CSPI_SCLK			IOMUX_PAD(0x38C, 0x060, 2, 0x780, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0	IOMUX_PAD(0x38C, 0x060, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN	IOMUX_PAD(0x38C, 0x060, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5		IOMUX_PAD(0x38C, 0x060, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY		IOMUX_PAD(0x38C, 0x060, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1		IOMUX_PAD(0x390, 0x064, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__GPIO4_22			IOMUX_PAD(0x390, 0x064, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__CSPI_MOSI			IOMUX_PAD(0x390, 0x064, 2, 0x788, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1	IOMUX_PAD(0x390, 0x064, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL	\
+							IOMUX_PAD(0x390, 0x064, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6		IOMUX_PAD(0x390, 0x064, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID		IOMUX_PAD(0x390, 0x064, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2		IOMUX_PAD(0x394, 0x068, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__GPIO4_23			IOMUX_PAD(0x394, 0x068, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__CSPI_MISO			IOMUX_PAD(0x394, 0x068, 2, 0x784, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2	IOMUX_PAD(0x394, 0x068, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE		IOMUX_PAD(0x394, 0x068, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7		IOMUX_PAD(0x394, 0x068, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE		IOMUX_PAD(0x394, 0x068, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3		IOMUX_PAD(0x398, 0x06C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__GPIO4_24			IOMUX_PAD(0x398, 0x06C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__CSPI_SS0			IOMUX_PAD(0x398, 0x06C, 2, 0x78C, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3	IOMUX_PAD(0x398, 0x06C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR	IOMUX_PAD(0x398, 0x06C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8		IOMUX_PAD(0x398, 0x06C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR		IOMUX_PAD(0x398, 0x06C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4		IOMUX_PAD(0x39C, 0x070, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__GPIO4_25			IOMUX_PAD(0x39C, 0x070, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__CSPI_SS1			IOMUX_PAD(0x39C, 0x070, 2, 0x790, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4	IOMUX_PAD(0x39C, 0x070, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB		IOMUX_PAD(0x39C, 0x070, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9		IOMUX_PAD(0x39C, 0x070, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK		IOMUX_PAD(0x39C, 0x070, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5		IOMUX_PAD(0x3A0, 0x074, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__GPIO4_26			IOMUX_PAD(0x3A0, 0x074, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__CSPI_SS2			IOMUX_PAD(0x3A0, 0x074, 2, 0x794, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5	IOMUX_PAD(0x3A0, 0x074, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS	IOMUX_PAD(0x3A0, 0x074, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10		IOMUX_PAD(0x3A0, 0x074, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0	IOMUX_PAD(0x3A0, 0x074, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6		IOMUX_PAD(0x3A4, 0x078, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__GPIO4_27			IOMUX_PAD(0x3A4, 0x078, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__CSPI_SS3			IOMUX_PAD(0x3A4, 0x078, 2, 0x798, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6	IOMUX_PAD(0x3A4, 0x078, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE	IOMUX_PAD(0x3A4, 0x078, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11		IOMUX_PAD(0x3A4, 0x078, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1	IOMUX_PAD(0x3A4, 0x078, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7		IOMUX_PAD(0x3A8, 0x07C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__GPIO4_28			IOMUX_PAD(0x3A8, 0x07C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__CSPI_RDY			IOMUX_PAD(0x3A8, 0x07C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7	IOMUX_PAD(0x3A8, 0x07C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0	IOMUX_PAD(0x3A8, 0x07C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12		IOMUX_PAD(0x3A8, 0x07C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID		IOMUX_PAD(0x3A8, 0x07C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8		IOMUX_PAD(0x3AC, 0x080, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__GPIO4_29			IOMUX_PAD(0x3AC, 0x080, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__PWM1_PWMO			IOMUX_PAD(0x3AC, 0x080, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B		IOMUX_PAD(0x3AC, 0x080, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1	IOMUX_PAD(0x3AC, 0x080, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13		IOMUX_PAD(0x3AC, 0x080, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__USBPHY2_AVALID		IOMUX_PAD(0x3AC, 0x080, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9		IOMUX_PAD(0x3B0, 0x084, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__GPIO4_30			IOMUX_PAD(0x3B0, 0x084, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__PWM2_PWMO			IOMUX_PAD(0x3B0, 0x084, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B		IOMUX_PAD(0x3B0, 0x084, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2	IOMUX_PAD(0x3B0, 0x084, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14		IOMUX_PAD(0x3B0, 0x084, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0		IOMUX_PAD(0x3B0, 0x084, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10		IOMUX_PAD(0x3B4, 0x088, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__GPIO4_31			IOMUX_PAD(0x3B4, 0x088, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP		IOMUX_PAD(0x3B4, 0x088, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3	\
+							IOMUX_PAD(0x3B4, 0x088, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15		IOMUX_PAD(0x3B4, 0x088, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1		IOMUX_PAD(0x3B4, 0x088, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11		IOMUX_PAD(0x3B8, 0x08C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__GPIO5_5			IOMUX_PAD(0x3B8, 0x08C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT		IOMUX_PAD(0x3B8, 0x08C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4	\
+							IOMUX_PAD(0x3B8, 0x08C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16		IOMUX_PAD(0x3B8, 0x08C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2		IOMUX_PAD(0x3B8, 0x08C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12		IOMUX_PAD(0x3BC, 0x090, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__GPIO5_6			IOMUX_PAD(0x3BC, 0x090, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK		IOMUX_PAD(0x3BC, 0x090, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5	\
+							IOMUX_PAD(0x3BC, 0x090, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17		IOMUX_PAD(0x3BC, 0x090, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3		IOMUX_PAD(0x3BC, 0x090, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13		IOMUX_PAD(0x3C0, 0x094, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__GPIO5_7			IOMUX_PAD(0x3C0, 0x094, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS		IOMUX_PAD(0x3C0, 0x094, 3, 0x754, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0	\
+							IOMUX_PAD(0x3C0, 0x094, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18		IOMUX_PAD(0x3C0, 0x094, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4		IOMUX_PAD(0x3C0, 0x094, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14		IOMUX_PAD(0x3C4, 0x098, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__GPIO5_8			IOMUX_PAD(0x3C4, 0x098, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC		IOMUX_PAD(0x3C4, 0x098, 3, 0x750, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1	\
+							IOMUX_PAD(0x3C4, 0x098, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19		IOMUX_PAD(0x3C4, 0x098, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5		IOMUX_PAD(0x3C4, 0x098, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15		IOMUX_PAD(0x3C8, 0x09C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__GPIO5_9			IOMUX_PAD(0x3C8, 0x09C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__ECSPI1_SS1		IOMUX_PAD(0x3C8, 0x09C, 2, 0x7AC, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__ECSPI2_SS1		IOMUX_PAD(0x3C8, 0x09C, 3, 0x7C8, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2	\
+							IOMUX_PAD(0x3C8, 0x09C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20		IOMUX_PAD(0x3C8, 0x09C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6		IOMUX_PAD(0x3C8, 0x09C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16		IOMUX_PAD(0x3CC, 0x0A0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__GPIO5_10			IOMUX_PAD(0x3CC, 0x0A0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__ECSPI2_MOSI		IOMUX_PAD(0x3CC, 0x0A0, 2, 0x7C0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC		IOMUX_PAD(0x3CC, 0x0A0, 3, 0x758, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0		IOMUX_PAD(0x3CC, 0x0A0, 4, 0x868, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3	\
+							IOMUX_PAD(0x3CC, 0x0A0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21		IOMUX_PAD(0x3CC, 0x0A0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7		IOMUX_PAD(0x3CC, 0x0A0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17		IOMUX_PAD(0x3D0, 0x0A4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__GPIO5_11			IOMUX_PAD(0x3D0, 0x0A4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__ECSPI2_MISO		IOMUX_PAD(0x3D0, 0x0A4, 2, 0x7BC, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD		IOMUX_PAD(0x3D0, 0x0A4, 3, 0x74C, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1		IOMUX_PAD(0x3D0, 0x0A4, 4, 0x86C, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4	\
+							IOMUX_PAD(0x3D0, 0x0A4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22		IOMUX_PAD(0x3D0, 0x0A4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18		IOMUX_PAD(0x3D4, 0x0A8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__GPIO5_12			IOMUX_PAD(0x3D4, 0x0A8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__ECSPI2_SS0		IOMUX_PAD(0x3D4, 0x0A8, 2, 0x7C4, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS		IOMUX_PAD(0x3D4, 0x0A8, 3, 0x75C, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS		IOMUX_PAD(0x3D4, 0x0A8, 4, 0x73C, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5	\
+							IOMUX_PAD(0x3D4, 0x0A8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23		IOMUX_PAD(0x3D4, 0x0A8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2		IOMUX_PAD(0x3D4, 0x0A8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19		IOMUX_PAD(0x3D8, 0x0AC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__GPIO5_13			IOMUX_PAD(0x3D8, 0x0AC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__ECSPI2_SCLK		IOMUX_PAD(0x3D8, 0x0AC, 2, 0x7B8, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD		IOMUX_PAD(0x3D8, 0x0AC, 3, 0x748, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC		IOMUX_PAD(0x3D8, 0x0AC, 4, 0x738, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6	\
+							IOMUX_PAD(0x3D8, 0x0AC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24		IOMUX_PAD(0x3D8, 0x0AC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3		IOMUX_PAD(0x3D8, 0x0AC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20		IOMUX_PAD(0x3DC, 0x0B0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__GPIO5_14			IOMUX_PAD(0x3DC, 0x0B0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__ECSPI1_SCLK		IOMUX_PAD(0x3DC, 0x0B0, 2, 0x79C, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC		IOMUX_PAD(0x3DC, 0x0B0, 3, 0x740, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7	\
+							IOMUX_PAD(0x3DC, 0x0B0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25		IOMUX_PAD(0x3DC, 0x0B0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__SATA_PHY_TDI		IOMUX_PAD(0x3DC, 0x0B0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21		IOMUX_PAD(0x3E0, 0x0B4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__GPIO5_15			IOMUX_PAD(0x3E0, 0x0B4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__ECSPI1_MOSI		IOMUX_PAD(0x3E0, 0x0B4, 2, 0x7A4, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD		IOMUX_PAD(0x3E0, 0x0B4, 3, 0x734, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0	IOMUX_PAD(0x3E0, 0x0B4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26		IOMUX_PAD(0x3E0, 0x0B4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__SATA_PHY_TDO		IOMUX_PAD(0x3E0, 0x0B4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22		IOMUX_PAD(0x3E4, 0x0B8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__GPIO5_16			IOMUX_PAD(0x3E4, 0x0B8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__ECSPI1_MISO		IOMUX_PAD(0x3E4, 0x0B8, 2, 0x7A0, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS		IOMUX_PAD(0x3E4, 0x0B8, 3, 0x744, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1	IOMUX_PAD(0x3E4, 0x0B8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27		IOMUX_PAD(0x3E4, 0x0B8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__SATA_PHY_TCK		IOMUX_PAD(0x3E4, 0x0B8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23		IOMUX_PAD(0x3E8, 0x0BC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__GPIO5_17			IOMUX_PAD(0x3E8, 0x0BC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__ECSPI1_SS0		IOMUX_PAD(0x3E8, 0x0BC, 2, 0x7A8, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD		IOMUX_PAD(0x3E8, 0x0BC, 3, 0x730, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2	IOMUX_PAD(0x3E8, 0x0BC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28		IOMUX_PAD(0x3E8, 0x0BC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__SATA_PHY_TMS		IOMUX_PAD(0x3E8, 0x0BC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK		IOMUX_PAD(0x3EC, 0x0C0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__GPIO5_18			IOMUX_PAD(0x3EC, 0x0C0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0		IOMUX_PAD(0x3EC, 0x0C0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29		IOMUX_PAD(0x3EC, 0x0C0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC		IOMUX_PAD(0x3F0, 0x0C4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__GPIO5_19			IOMUX_PAD(0x3F0, 0x0C4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK		IOMUX_PAD(0x3F0, 0x0C4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1		IOMUX_PAD(0x3F0, 0x0C4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30		IOMUX_PAD(0x3F0, 0x0C4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__TPIU_TRCTL			IOMUX_PAD(0x3F0, 0x0C4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN		IOMUX_PAD(0x3F4, 0x0C8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__GPIO5_20			IOMUX_PAD(0x3F4, 0x0C8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2		IOMUX_PAD(0x3F4, 0x0C8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31		IOMUX_PAD(0x3F4, 0x0C8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK		IOMUX_PAD(0x3F4, 0x0C8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC		IOMUX_PAD(0x3F8, 0x0CC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__GPIO5_21			IOMUX_PAD(0x3F8, 0x0CC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3		IOMUX_PAD(0x3F8, 0x0CC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32		IOMUX_PAD(0x3F8, 0x0CC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0		IOMUX_PAD(0x3F8, 0x0CC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4		IOMUX_PAD(0x3FC, 0x0D0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__GPIO5_22			IOMUX_PAD(0x3FC, 0x0D0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__KPP_COL_5			IOMUX_PAD(0x3FC, 0x0D0, 2, 0x840, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__ECSPI1_SCLK			IOMUX_PAD(0x3FC, 0x0D0, 3, 0x79C, 2, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP		IOMUX_PAD(0x3FC, 0x0D0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC		IOMUX_PAD(0x3FC, 0x0D0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33		IOMUX_PAD(0x3FC, 0x0D0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__TPIU_TRACE_1		IOMUX_PAD(0x3FC, 0x0D0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5		IOMUX_PAD(0x400, 0x0D4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__GPIO5_23			IOMUX_PAD(0x400, 0x0D4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__KPP_ROW_5			IOMUX_PAD(0x400, 0x0D4, 2, 0x84C, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__ECSPI1_MOSI			IOMUX_PAD(0x400, 0x0D4, 3, 0x7A4, 2, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT		IOMUX_PAD(0x400, 0x0D4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD		IOMUX_PAD(0x400, 0x0D4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34		IOMUX_PAD(0x400, 0x0D4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__TPIU_TRACE_2		IOMUX_PAD(0x400, 0x0D4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6		IOMUX_PAD(0x404, 0x0D8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__GPIO5_24			IOMUX_PAD(0x404, 0x0D8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__KPP_COL_6			IOMUX_PAD(0x404, 0x0D8, 2, 0x844, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__ECSPI1_MISO			IOMUX_PAD(0x404, 0x0D8, 3, 0x7A0, 2, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK		IOMUX_PAD(0x404, 0x0D8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS		IOMUX_PAD(0x404, 0x0D8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35		IOMUX_PAD(0x404, 0x0D8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__TPIU_TRACE_3		IOMUX_PAD(0x404, 0x0D8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7		IOMUX_PAD(0x408, 0x0DC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__GPIO5_25			IOMUX_PAD(0x408, 0x0DC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__KPP_ROW_6			IOMUX_PAD(0x408, 0x0DC, 2, 0x850, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__ECSPI1_SS0			IOMUX_PAD(0x408, 0x0DC, 3, 0x7A8, 2, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR		IOMUX_PAD(0x408, 0x0DC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD		IOMUX_PAD(0x408, 0x0DC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36		IOMUX_PAD(0x408, 0x0DC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__TPIU_TRACE_4		IOMUX_PAD(0x408, 0x0DC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8		IOMUX_PAD(0x40C, 0x0E0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__GPIO5_26			IOMUX_PAD(0x40C, 0x0E0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__KPP_COL_7			IOMUX_PAD(0x40C, 0x0E0, 2, 0x848, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__ECSPI2_SCLK			IOMUX_PAD(0x40C, 0x0E0, 3, 0x7B8, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC		IOMUX_PAD(0x40C, 0x0E0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__I2C1_SDA			IOMUX_PAD(0x40C, 0x0E0, 5 | IOMUX_CONFIG_SION, 0x818, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37		IOMUX_PAD(0x40C, 0x0E0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__TPIU_TRACE_5		IOMUX_PAD(0x40C, 0x0E0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9		IOMUX_PAD(0x410, 0x0E4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__GPIO5_27			IOMUX_PAD(0x410, 0x0E4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__KPP_ROW_7			IOMUX_PAD(0x410, 0x0E4, 2, 0x854, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__ECSPI2_MOSI			IOMUX_PAD(0x410, 0x0E4, 3, 0x7C0, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR		IOMUX_PAD(0x410, 0x0E4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__I2C1_SCL			IOMUX_PAD(0x410, 0x0E4, 5 | IOMUX_CONFIG_SION, 0x814, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38		IOMUX_PAD(0x410, 0x0E4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__TPIU_TRACE_6		IOMUX_PAD(0x410, 0x0E4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10		IOMUX_PAD(0x414, 0x0E8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__GPIO5_28			IOMUX_PAD(0x414, 0x0E8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__UART1_TXD_MUX		IOMUX_PAD(0x414, 0x0E8, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__ECSPI2_MISO		IOMUX_PAD(0x414, 0x0E8, 3, 0x7BC, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC		IOMUX_PAD(0x414, 0x0E8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4		IOMUX_PAD(0x414, 0x0E8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39		IOMUX_PAD(0x414, 0x0E8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__TPIU_TRACE_7		IOMUX_PAD(0x414, 0x0E8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11		IOMUX_PAD(0x418, 0x0EC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__GPIO5_29			IOMUX_PAD(0x418, 0x0EC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__UART1_RXD_MUX		IOMUX_PAD(0x418, 0x0EC, 2, 0x878, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__ECSPI2_SS0			IOMUX_PAD(0x418, 0x0EC, 3, 0x7C4, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS		IOMUX_PAD(0x418, 0x0EC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5		IOMUX_PAD(0x418, 0x0EC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40		IOMUX_PAD(0x418, 0x0EC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__TPIU_TRACE_8		IOMUX_PAD(0x418, 0x0EC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12		IOMUX_PAD(0x41C, 0x0F0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__GPIO5_30			IOMUX_PAD(0x41C, 0x0F0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__UART4_TXD_MUX		IOMUX_PAD(0x41C, 0x0F0, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0	IOMUX_PAD(0x41C, 0x0F0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6		IOMUX_PAD(0x41C, 0x0F0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41		IOMUX_PAD(0x41C, 0x0F0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__TPIU_TRACE_9		IOMUX_PAD(0x41C, 0x0F0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13		IOMUX_PAD(0x420, 0x0F4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__GPIO5_31			IOMUX_PAD(0x420, 0x0F4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__UART4_RXD_MUX		IOMUX_PAD(0x420, 0x0F4, 2, 0x890, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1	IOMUX_PAD(0x420, 0x0F4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7		IOMUX_PAD(0x420, 0x0F4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42		IOMUX_PAD(0x420, 0x0F4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__TPIU_TRACE_10		IOMUX_PAD(0x420, 0x0F4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14		IOMUX_PAD(0x424, 0x0F8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__GPIO6_0			IOMUX_PAD(0x424, 0x0F8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__UART5_TXD_MUX		IOMUX_PAD(0x424, 0x0F8, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2	IOMUX_PAD(0x424, 0x0F8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8		IOMUX_PAD(0x424, 0x0F8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43		IOMUX_PAD(0x424, 0x0F8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__TPIU_TRACE_11		IOMUX_PAD(0x424, 0x0F8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15		IOMUX_PAD(0x428, 0x0FC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__GPIO6_1			IOMUX_PAD(0x428, 0x0FC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__UART5_RXD_MUX		IOMUX_PAD(0x428, 0x0FC, 2, 0x898, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3	IOMUX_PAD(0x428, 0x0FC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9		IOMUX_PAD(0x428, 0x0FC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44		IOMUX_PAD(0x428, 0x0FC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__TPIU_TRACE_12		IOMUX_PAD(0x428, 0x0FC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16		IOMUX_PAD(0x42C, 0x100, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__GPIO6_2			IOMUX_PAD(0x42C, 0x100, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__UART4_RTS			IOMUX_PAD(0x42C, 0x100, 2, 0x88C, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4	IOMUX_PAD(0x42C, 0x100, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10		IOMUX_PAD(0x42C, 0x100, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45		IOMUX_PAD(0x42C, 0x100, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__TPIU_TRACE_13		IOMUX_PAD(0x42C, 0x100, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17		IOMUX_PAD(0x430, 0x104, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__GPIO6_3			IOMUX_PAD(0x430, 0x104, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__UART4_CTS			IOMUX_PAD(0x430, 0x104, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5	IOMUX_PAD(0x430, 0x104, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11		IOMUX_PAD(0x430, 0x104, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46		IOMUX_PAD(0x430, 0x104, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__TPIU_TRACE_14		IOMUX_PAD(0x430, 0x104, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18		IOMUX_PAD(0x434, 0x108, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__GPIO6_4			IOMUX_PAD(0x434, 0x108, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__UART5_RTS			IOMUX_PAD(0x434, 0x108, 2, 0x894, 2, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6	IOMUX_PAD(0x434, 0x108, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12		IOMUX_PAD(0x434, 0x108, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47		IOMUX_PAD(0x434, 0x108, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__TPIU_TRACE_15		IOMUX_PAD(0x434, 0x108, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19		IOMUX_PAD(0x438, 0x10C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__GPIO6_5			IOMUX_PAD(0x438, 0x10C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__UART5_CTS			IOMUX_PAD(0x438, 0x10C, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7	IOMUX_PAD(0x438, 0x10C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13		IOMUX_PAD(0x438, 0x10C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48		IOMUX_PAD(0x438, 0x10C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK		IOMUX_PAD(0x438, 0x10C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__EMI_WEIM_A_25			IOMUX_PAD(0x458, 0x110, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__GPIO5_2			IOMUX_PAD(0x458, 0x110, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__ECSPI2_RDY			IOMUX_PAD(0x458, 0x110, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__IPU_DI1_PIN12			IOMUX_PAD(0x458, 0x110, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__CSPI_SS1			IOMUX_PAD(0x458, 0x110, 4, 0x790, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__IPU_DI0_D1_CS			IOMUX_PAD(0x458, 0x110, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__USBPHY1_BISTOK		IOMUX_PAD(0x458, 0x110, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__EMI_WEIM_EB_2			IOMUX_PAD(0x45C, 0x114, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__GPIO2_30			IOMUX_PAD(0x45C, 0x114, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK		IOMUX_PAD(0x45C, 0x114, 2, 0x76C, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS		IOMUX_PAD(0x45C, 0x114, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__ECSPI1_SS0			IOMUX_PAD(0x45C, 0x114, 4, 0x7A8, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__I2C2_SCL			IOMUX_PAD(0x45C, 0x114, 5 | IOMUX_CONFIG_SION, 0x81C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__EMI_WEIM_D_16			IOMUX_PAD(0x460, 0x118, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__GPIO3_16			IOMUX_PAD(0x460, 0x118, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__IPU_DI0_PIN5			IOMUX_PAD(0x460, 0x118, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK		IOMUX_PAD(0x460, 0x118, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__ECSPI1_SCLK			IOMUX_PAD(0x460, 0x118, 4, 0x79C, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__I2C2_SDA			IOMUX_PAD(0x460, 0x118, 5 | IOMUX_CONFIG_SION, 0x820, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__EMI_WEIM_D_17			IOMUX_PAD(0x464, 0x11C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__GPIO3_17			IOMUX_PAD(0x464, 0x11C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__IPU_DI0_PIN6			IOMUX_PAD(0x464, 0x11C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN		IOMUX_PAD(0x464, 0x11C, 3, 0x830, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__ECSPI1_MISO			IOMUX_PAD(0x464, 0x11C, 4, 0x7A0, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__I2C3_SCL			IOMUX_PAD(0x464, 0x11C, 5 | IOMUX_CONFIG_SION, 0x824, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__EMI_WEIM_D_18			IOMUX_PAD(0x468, 0x120, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__GPIO3_18			IOMUX_PAD(0x468, 0x120, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__IPU_DI0_PIN7			IOMUX_PAD(0x468, 0x120, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO		IOMUX_PAD(0x468, 0x120, 3, 0x830, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__ECSPI1_MOSI			IOMUX_PAD(0x468, 0x120, 4, 0x7A4, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__I2C3_SDA			IOMUX_PAD(0x468, 0x120, 5 | IOMUX_CONFIG_SION, 0x828, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__IPU_DI1_D0_CS			IOMUX_PAD(0x468, 0x120, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__EMI_WEIM_D_19			IOMUX_PAD(0x46C, 0x124, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__GPIO3_19			IOMUX_PAD(0x46C, 0x124, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__IPU_DI0_PIN8			IOMUX_PAD(0x46C, 0x124, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS		IOMUX_PAD(0x46C, 0x124, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__ECSPI1_SS1			IOMUX_PAD(0x46C, 0x124, 4, 0x7AC, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__EPIT1_EPITO			IOMUX_PAD(0x46C, 0x124, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__UART1_CTS			IOMUX_PAD(0x46C, 0x124, 6, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D19__USBOH3_USBH2_OC		IOMUX_PAD(0x46C, 0x124, 7, 0x8A4, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__EMI_WEIM_D_20			IOMUX_PAD(0x470, 0x128, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__GPIO3_20			IOMUX_PAD(0x470, 0x128, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__IPU_DI0_PIN16			IOMUX_PAD(0x470, 0x128, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__IPU_SER_DISP0_CS		IOMUX_PAD(0x470, 0x128, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__CSPI_SS0			IOMUX_PAD(0x470, 0x128, 4, 0x78C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__EPIT2_EPITO			IOMUX_PAD(0x470, 0x128, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__UART1_RTS			IOMUX_PAD(0x470, 0x128, 6, 0x874, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D20__USBOH3_USBH2_PWR		IOMUX_PAD(0x470, 0x128, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__EMI_WEIM_D_21			IOMUX_PAD(0x474, 0x12C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__GPIO3_21			IOMUX_PAD(0x474, 0x12C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__IPU_DI0_PIN17			IOMUX_PAD(0x474, 0x12C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK		IOMUX_PAD(0x474, 0x12C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__CSPI_SCLK			IOMUX_PAD(0x474, 0x12C, 4, 0x780, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__I2C1_SCL			IOMUX_PAD(0x474, 0x12C, 5 | IOMUX_CONFIG_SION, 0x814, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__USBOH3_USBOTG_OC		IOMUX_PAD(0x474, 0x12C, 6, 0x89C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__EMI_WEIM_D_22			IOMUX_PAD(0x478, 0x130, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__GPIO3_22			IOMUX_PAD(0x478, 0x130, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__IPU_DI0_PIN1			IOMUX_PAD(0x478, 0x130, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN		IOMUX_PAD(0x478, 0x130, 3, 0x82C, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__CSPI_MISO			IOMUX_PAD(0x478, 0x130, 4, 0x784, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR		IOMUX_PAD(0x478, 0x130, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__EMI_WEIM_D_23			IOMUX_PAD(0x47C, 0x134, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__GPIO3_23			IOMUX_PAD(0x47C, 0x134, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__UART3_CTS			IOMUX_PAD(0x47C, 0x134, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D23__UART1_DCD			IOMUX_PAD(0x47C, 0x134, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__IPU_DI0_D0_CS			IOMUX_PAD(0x47C, 0x134, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__IPU_DI1_PIN2			IOMUX_PAD(0x47C, 0x134, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN		IOMUX_PAD(0x47C, 0x134, 6, 0x834, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__IPU_DI1_PIN14			IOMUX_PAD(0x47C, 0x134, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__EMI_WEIM_EB_3			IOMUX_PAD(0x480, 0x138, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__GPIO2_31			IOMUX_PAD(0x480, 0x138, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__UART3_RTS			IOMUX_PAD(0x480, 0x138, 2, 0x884, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__UART1_RI			IOMUX_PAD(0x480, 0x138, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__IPU_DI1_PIN3			IOMUX_PAD(0x480, 0x138, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC		IOMUX_PAD(0x480, 0x138, 6, 0x838, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__IPU_DI1_PIN16			IOMUX_PAD(0x480, 0x138, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__EMI_WEIM_D_24			IOMUX_PAD(0x484, 0x13C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__GPIO3_24			IOMUX_PAD(0x484, 0x13C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__UART3_TXD_MUX			IOMUX_PAD(0x484, 0x13C, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D24__ECSPI1_SS2			IOMUX_PAD(0x484, 0x13C, 3, 0x7B0, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__CSPI_SS2			IOMUX_PAD(0x484, 0x13C, 4, 0x794, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS		IOMUX_PAD(0x484, 0x13C, 5, 0x754, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__ECSPI2_SS2			IOMUX_PAD(0x484, 0x13C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__UART1_DTR			IOMUX_PAD(0x484, 0x13C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__EMI_WEIM_D_25			IOMUX_PAD(0x488, 0x140, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__GPIO3_25			IOMUX_PAD(0x488, 0x140, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__UART3_RXD_MUX			IOMUX_PAD(0x488, 0x140, 2, 0x888, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D25__ECSPI1_SS3			IOMUX_PAD(0x488, 0x140, 3, 0x7B4, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__CSPI_SS3			IOMUX_PAD(0x488, 0x140, 4, 0x798, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC		IOMUX_PAD(0x488, 0x140, 5, 0x750, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__ECSPI2_SS3			IOMUX_PAD(0x488, 0x140, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__UART1_DSR			IOMUX_PAD(0x488, 0x140, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__EMI_WEIM_D_26			IOMUX_PAD(0x48C, 0x144, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__GPIO3_26			IOMUX_PAD(0x48C, 0x144, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__UART2_TXD_MUX			IOMUX_PAD(0x48C, 0x144, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D26__FIRI_RXD			IOMUX_PAD(0x48C, 0x144, 3, 0x80C, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__IPU_CSI0_D_1			IOMUX_PAD(0x48C, 0x144, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__IPU_DI1_PIN11			IOMUX_PAD(0x48C, 0x144, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__IPU_SISG_2			IOMUX_PAD(0x48C, 0x144, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__IPU_DISP1_DAT_22		IOMUX_PAD(0x48C, 0x144, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__EMI_WEIM_D_27			IOMUX_PAD(0x490, 0x148, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__GPIO3_27			IOMUX_PAD(0x490, 0x148, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__UART2_RXD_MUX			IOMUX_PAD(0x490, 0x148, 2, 0x880, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D27__FIRI_TXD			IOMUX_PAD(0x490, 0x148, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__IPU_CSI0_D_0			IOMUX_PAD(0x490, 0x148, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__IPU_DI1_PIN13			IOMUX_PAD(0x490, 0x148, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__IPU_SISG_3			IOMUX_PAD(0x490, 0x148, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__IPU_DISP1_DAT_23		IOMUX_PAD(0x490, 0x148, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__EMI_WEIM_D_28			IOMUX_PAD(0x494, 0x14C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__GPIO3_28			IOMUX_PAD(0x494, 0x14C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__UART2_CTS			IOMUX_PAD(0x494, 0x14C, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO		IOMUX_PAD(0x494, 0x14C, 3, 0x82C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__CSPI_MOSI			IOMUX_PAD(0x494, 0x14C, 4, 0x788, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__I2C1_SDA			IOMUX_PAD(0x494, 0x14C, 5 | IOMUX_CONFIG_SION, 0x818, 1, PAD_CTRL_I2C)
+#define MX53_PAD_EIM_D28__IPU_EXT_TRIG			IOMUX_PAD(0x494, 0x14C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__IPU_DI0_PIN13			IOMUX_PAD(0x494, 0x14C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__EMI_WEIM_D_29			IOMUX_PAD(0x498, 0x150, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__GPIO3_29			IOMUX_PAD(0x498, 0x150, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__UART2_RTS			IOMUX_PAD(0x498, 0x150, 2, 0x87C, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS		IOMUX_PAD(0x498, 0x150, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__CSPI_SS0			IOMUX_PAD(0x498, 0x150, 4, 0x78C, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__IPU_DI1_PIN15			IOMUX_PAD(0x498, 0x150, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__IPU_CSI1_VSYNC		IOMUX_PAD(0x498, 0x150, 6, 0x83C, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__IPU_DI0_PIN14			IOMUX_PAD(0x498, 0x150, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__EMI_WEIM_D_30			IOMUX_PAD(0x49C, 0x154, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__GPIO3_30			IOMUX_PAD(0x49C, 0x154, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__UART3_CTS			IOMUX_PAD(0x49C, 0x154, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D30__IPU_CSI0_D_3			IOMUX_PAD(0x49C, 0x154, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__IPU_DI0_PIN11			IOMUX_PAD(0x49C, 0x154, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__IPU_DISP1_DAT_21		IOMUX_PAD(0x49C, 0x154, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__USBOH3_USBH1_OC		IOMUX_PAD(0x49C, 0x154, 6, 0x8A0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__USBOH3_USBH2_OC		IOMUX_PAD(0x49C, 0x154, 7, 0x8A4, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__EMI_WEIM_D_31			IOMUX_PAD(0x4A0, 0x158, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__GPIO3_31			IOMUX_PAD(0x4A0, 0x158, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__UART3_RTS			IOMUX_PAD(0x4A0, 0x158, 2, 0x884, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D31__IPU_CSI0_D_2			IOMUX_PAD(0x4A0, 0x158, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__IPU_DI0_PIN12			IOMUX_PAD(0x4A0, 0x158, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__IPU_DISP1_DAT_20		IOMUX_PAD(0x4A0, 0x158, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__USBOH3_USBH1_PWR		IOMUX_PAD(0x4A0, 0x158, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__USBOH3_USBH2_PWR		IOMUX_PAD(0x4A0, 0x158, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__EMI_WEIM_A_24			IOMUX_PAD(0x4A8, 0x15C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__GPIO5_4			IOMUX_PAD(0x4A8, 0x15C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__IPU_DISP1_DAT_19		IOMUX_PAD(0x4A8, 0x15C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__IPU_CSI1_D_19			IOMUX_PAD(0x4A8, 0x15C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__IPU_SISG_2			IOMUX_PAD(0x4A8, 0x15C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__USBPHY2_BVALID		IOMUX_PAD(0x4A8, 0x15C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__EMI_WEIM_A_23			IOMUX_PAD(0x4AC, 0x160, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__GPIO6_6			IOMUX_PAD(0x4AC, 0x160, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__IPU_DISP1_DAT_18		IOMUX_PAD(0x4AC, 0x160, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__IPU_CSI1_D_18			IOMUX_PAD(0x4AC, 0x160, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__IPU_SISG_3			IOMUX_PAD(0x4AC, 0x160, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__USBPHY2_ENDSESSION		IOMUX_PAD(0x4AC, 0x160, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__EMI_WEIM_A_22			IOMUX_PAD(0x4B0, 0x164, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__GPIO2_16			IOMUX_PAD(0x4B0, 0x164, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__IPU_DISP1_DAT_17		IOMUX_PAD(0x4B0, 0x164, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__IPU_CSI1_D_17			IOMUX_PAD(0x4B0, 0x164, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__SRC_BT_CFG1_7			IOMUX_PAD(0x4B0, 0x164, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__EMI_WEIM_A_21			IOMUX_PAD(0x4B4, 0x168, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__GPIO2_17			IOMUX_PAD(0x4B4, 0x168, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__IPU_DISP1_DAT_16		IOMUX_PAD(0x4B4, 0x168, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__IPU_CSI1_D_16			IOMUX_PAD(0x4B4, 0x168, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__SRC_BT_CFG1_6			IOMUX_PAD(0x4B4, 0x168, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__EMI_WEIM_A_20			IOMUX_PAD(0x4B8, 0x16C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__GPIO2_18			IOMUX_PAD(0x4B8, 0x16C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__IPU_DISP1_DAT_15		IOMUX_PAD(0x4B8, 0x16C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__IPU_CSI1_D_15			IOMUX_PAD(0x4B8, 0x16C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__SRC_BT_CFG1_5			IOMUX_PAD(0x4B8, 0x16C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__EMI_WEIM_A_19			IOMUX_PAD(0x4BC, 0x170, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__GPIO2_19			IOMUX_PAD(0x4BC, 0x170, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__IPU_DISP1_DAT_14		IOMUX_PAD(0x4BC, 0x170, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__IPU_CSI1_D_14			IOMUX_PAD(0x4BC, 0x170, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__SRC_BT_CFG1_4			IOMUX_PAD(0x4BC, 0x170, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__EMI_WEIM_A_18			IOMUX_PAD(0x4C0, 0x174, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__GPIO2_20			IOMUX_PAD(0x4C0, 0x174, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__IPU_DISP1_DAT_13		IOMUX_PAD(0x4C0, 0x174, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__IPU_CSI1_D_13			IOMUX_PAD(0x4C0, 0x174, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__SRC_BT_CFG1_3			IOMUX_PAD(0x4C0, 0x174, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__EMI_WEIM_A_17			IOMUX_PAD(0x4C4, 0x178, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__GPIO2_21			IOMUX_PAD(0x4C4, 0x178, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__IPU_DISP1_DAT_12		IOMUX_PAD(0x4C4, 0x178, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__IPU_CSI1_D_12			IOMUX_PAD(0x4C4, 0x178, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__SRC_BT_CFG1_2			IOMUX_PAD(0x4C4, 0x178, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__EMI_WEIM_A_16			IOMUX_PAD(0x4C8, 0x17C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__GPIO2_22			IOMUX_PAD(0x4C8, 0x17C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK		IOMUX_PAD(0x4C8, 0x17C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK		IOMUX_PAD(0x4C8, 0x17C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__SRC_BT_CFG1_1			IOMUX_PAD(0x4C8, 0x17C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__EMI_WEIM_CS_0			IOMUX_PAD(0x4CC, 0x180, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__GPIO2_23			IOMUX_PAD(0x4CC, 0x180, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__ECSPI2_SCLK			IOMUX_PAD(0x4CC, 0x180, 2, 0x7B8, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__IPU_DI1_PIN5			IOMUX_PAD(0x4CC, 0x180, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__EMI_WEIM_CS_1			IOMUX_PAD(0x4D0, 0x184, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__GPIO2_24			IOMUX_PAD(0x4D0, 0x184, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__ECSPI2_MOSI			IOMUX_PAD(0x4D0, 0x184, 2, 0x7C0, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__IPU_DI1_PIN6			IOMUX_PAD(0x4D0, 0x184, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__EMI_WEIM_OE			IOMUX_PAD(0x4D4, 0x188, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__GPIO2_25			IOMUX_PAD(0x4D4, 0x188, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__ECSPI2_MISO			IOMUX_PAD(0x4D4, 0x188, 2, 0x7BC, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__IPU_DI1_PIN7			IOMUX_PAD(0x4D4, 0x188, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__USBPHY2_IDDIG			IOMUX_PAD(0x4D4, 0x188, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__EMI_WEIM_RW			IOMUX_PAD(0x4D8, 0x18C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__GPIO2_26			IOMUX_PAD(0x4D8, 0x18C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__ECSPI2_SS0			IOMUX_PAD(0x4D8, 0x18C, 2, 0x7C4, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__IPU_DI1_PIN8			IOMUX_PAD(0x4D8, 0x18C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT		IOMUX_PAD(0x4D8, 0x18C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__EMI_WEIM_LBA			IOMUX_PAD(0x4DC, 0x190, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__GPIO2_27			IOMUX_PAD(0x4DC, 0x190, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__ECSPI2_SS1			IOMUX_PAD(0x4DC, 0x190, 2, 0x7C8, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__IPU_DI1_PIN17			IOMUX_PAD(0x4DC, 0x190, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__SRC_BT_CFG1_0			IOMUX_PAD(0x4DC, 0x190, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__EMI_WEIM_EB_0			IOMUX_PAD(0x4E4, 0x194, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__GPIO2_28			IOMUX_PAD(0x4E4, 0x194, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11		IOMUX_PAD(0x4E4, 0x194, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__IPU_CSI1_D_11			IOMUX_PAD(0x4E4, 0x194, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__GPC_PMIC_RDY			IOMUX_PAD(0x4E4, 0x194, 5, 0x810, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__SRC_BT_CFG2_7			IOMUX_PAD(0x4E4, 0x194, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__EMI_WEIM_EB_1			IOMUX_PAD(0x4E8, 0x198, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__GPIO2_29			IOMUX_PAD(0x4E8, 0x198, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10		IOMUX_PAD(0x4E8, 0x198, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__IPU_CSI1_D_10			IOMUX_PAD(0x4E8, 0x198, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__SRC_BT_CFG2_6			IOMUX_PAD(0x4E8, 0x198, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0		IOMUX_PAD(0x4EC, 0x19C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__GPIO3_0			IOMUX_PAD(0x4EC, 0x19C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9		IOMUX_PAD(0x4EC, 0x19C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__IPU_CSI1_D_9			IOMUX_PAD(0x4EC, 0x19C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__SRC_BT_CFG2_5			IOMUX_PAD(0x4EC, 0x19C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1		IOMUX_PAD(0x4F0, 0x1A0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__GPIO3_1			IOMUX_PAD(0x4F0, 0x1A0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8		IOMUX_PAD(0x4F0, 0x1A0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__IPU_CSI1_D_8			IOMUX_PAD(0x4F0, 0x1A0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__SRC_BT_CFG2_4			IOMUX_PAD(0x4F0, 0x1A0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2		IOMUX_PAD(0x4F4, 0x1A4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__GPIO3_2			IOMUX_PAD(0x4F4, 0x1A4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7		IOMUX_PAD(0x4F4, 0x1A4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__IPU_CSI1_D_7			IOMUX_PAD(0x4F4, 0x1A4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__SRC_BT_CFG2_3			IOMUX_PAD(0x4F4, 0x1A4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3		IOMUX_PAD(0x4F8, 0x1A8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__GPIO3_3			IOMUX_PAD(0x4F8, 0x1A8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6		IOMUX_PAD(0x4F8, 0x1A8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__IPU_CSI1_D_6			IOMUX_PAD(0x4F8, 0x1A8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__SRC_BT_CFG2_2			IOMUX_PAD(0x4F8, 0x1A8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4		IOMUX_PAD(0x4FC, 0x1AC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__GPIO3_4			IOMUX_PAD(0x4FC, 0x1AC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5		IOMUX_PAD(0x4FC, 0x1AC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__IPU_CSI1_D_5			IOMUX_PAD(0x4FC, 0x1AC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__SRC_BT_CFG3_7			IOMUX_PAD(0x4FC, 0x1AC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5		IOMUX_PAD(0x500, 0x1B0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__GPIO3_5			IOMUX_PAD(0x500, 0x1B0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4		IOMUX_PAD(0x500, 0x1B0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__IPU_CSI1_D_4			IOMUX_PAD(0x500, 0x1B0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__SRC_BT_CFG3_6			IOMUX_PAD(0x500, 0x1B0, 7 | IOMUX_CONFIG_SION, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6		IOMUX_PAD(0x504, 0x1B4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__GPIO3_6			IOMUX_PAD(0x504, 0x1B4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3		IOMUX_PAD(0x504, 0x1B4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__IPU_CSI1_D_3			IOMUX_PAD(0x504, 0x1B4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__SRC_BT_CFG3_5			IOMUX_PAD(0x504, 0x1B4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7		IOMUX_PAD(0x508, 0x1B8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__GPIO3_7			IOMUX_PAD(0x508, 0x1B8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2		IOMUX_PAD(0x508, 0x1B8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__IPU_CSI1_D_2			IOMUX_PAD(0x508, 0x1B8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__SRC_BT_CFG3_4			IOMUX_PAD(0x508, 0x1B8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8		IOMUX_PAD(0x50C, 0x1BC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__GPIO3_8			IOMUX_PAD(0x50C, 0x1BC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1		IOMUX_PAD(0x50C, 0x1BC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__IPU_CSI1_D_1			IOMUX_PAD(0x50C, 0x1BC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__SRC_BT_CFG3_3			IOMUX_PAD(0x50C, 0x1BC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9		IOMUX_PAD(0x510, 0x1C0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__GPIO3_9			IOMUX_PAD(0x510, 0x1C0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0		IOMUX_PAD(0x510, 0x1C0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__IPU_CSI1_D_0			IOMUX_PAD(0x510, 0x1C0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__SRC_BT_CFG3_2			IOMUX_PAD(0x510, 0x1C0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10		IOMUX_PAD(0x514, 0x1C4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__GPIO3_10			IOMUX_PAD(0x514, 0x1C4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__IPU_DI1_PIN15		IOMUX_PAD(0x514, 0x1C4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN		IOMUX_PAD(0x514, 0x1C4, 4, 0x834, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__SRC_BT_CFG3_1		IOMUX_PAD(0x514, 0x1C4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11		IOMUX_PAD(0x518, 0x1C8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__GPIO3_11			IOMUX_PAD(0x518, 0x1C8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__IPU_DI1_PIN2			IOMUX_PAD(0x518, 0x1C8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC		IOMUX_PAD(0x518, 0x1C8, 4, 0x838, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12		IOMUX_PAD(0x51C, 0x1CC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__GPIO3_12			IOMUX_PAD(0x51C, 0x1CC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__IPU_DI1_PIN3			IOMUX_PAD(0x51C, 0x1CC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC		IOMUX_PAD(0x51C, 0x1CC, 4, 0x83C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13		IOMUX_PAD(0x520, 0x1D0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__GPIO3_13			IOMUX_PAD(0x520, 0x1D0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__IPU_DI1_D0_CS		IOMUX_PAD(0x520, 0x1D0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK		IOMUX_PAD(0x520, 0x1D0, 4, 0x76C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14		IOMUX_PAD(0x524, 0x1D4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__GPIO3_14			IOMUX_PAD(0x524, 0x1D4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__IPU_DI1_D1_CS		IOMUX_PAD(0x524, 0x1D4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK		IOMUX_PAD(0x524, 0x1D4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15		IOMUX_PAD(0x528, 0x1D8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__GPIO3_15			IOMUX_PAD(0x528, 0x1D8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__IPU_DI1_PIN1			IOMUX_PAD(0x528, 0x1D8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__IPU_DI1_PIN4			IOMUX_PAD(0x528, 0x1D8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B		IOMUX_PAD(0x52C, 0x1DC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WE_B__GPIO6_12			IOMUX_PAD(0x52C, 0x1DC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B		IOMUX_PAD(0x530, 0x1E0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RE_B__GPIO6_13			IOMUX_PAD(0x530, 0x1E0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT		IOMUX_PAD(0x534, 0x1E4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_WAIT__GPIO5_0			IOMUX_PAD(0x534, 0x1E4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B		IOMUX_PAD(0x534, 0x1E4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX3_P__GPIO6_22			IOMUX_PAD(__NA_, 0x1EC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3		IOMUX_PAD(__NA_, 0x1EC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX2_P__GPIO6_24			IOMUX_PAD(__NA_, 0x1F0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2		IOMUX_PAD(__NA_, 0x1F0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_CLK_P__GPIO6_26			IOMUX_PAD(__NA_, 0x1F4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK		IOMUX_PAD(__NA_, 0x1F4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX1_P__GPIO6_28			IOMUX_PAD(__NA_, 0x1F8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1		IOMUX_PAD(__NA_, 0x1F8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX0_P__GPIO6_30			IOMUX_PAD(__NA_, 0x1FC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0		IOMUX_PAD(__NA_, 0x1FC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX3_P__GPIO7_22			IOMUX_PAD(__NA_, 0x200, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3		IOMUX_PAD(__NA_, 0x200, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_CLK_P__GPIO7_24			IOMUX_PAD(__NA_, 0x204, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK		IOMUX_PAD(__NA_, 0x204, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX2_P__GPIO7_26			IOMUX_PAD(__NA_, 0x208, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2		IOMUX_PAD(__NA_, 0x208, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX1_P__GPIO7_28			IOMUX_PAD(__NA_, 0x20C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1		IOMUX_PAD(__NA_, 0x20C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX0_P__GPIO7_30			IOMUX_PAD(__NA_, 0x210, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0		IOMUX_PAD(__NA_, 0x210, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_10__GPIO4_0			IOMUX_PAD(0x540, 0x214, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_10__OSC32k_32K_OUT		IOMUX_PAD(0x540, 0x214, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_11__GPIO4_1			IOMUX_PAD(0x544, 0x218, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_12__GPIO4_2			IOMUX_PAD(0x548, 0x21C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_13__GPIO4_3			IOMUX_PAD(0x54C, 0x220, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_14__GPIO4_4			IOMUX_PAD(0x550, 0x224, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CLE__EMI_NANDF_CLE		IOMUX_PAD(0x5A0, 0x228, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CLE__GPIO6_7			IOMUX_PAD(0x5A0, 0x228, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0		IOMUX_PAD(0x5A0, 0x228, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_ALE__EMI_NANDF_ALE		IOMUX_PAD(0x5A4, 0x22C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_ALE__GPIO6_8			IOMUX_PAD(0x5A4, 0x22C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1		IOMUX_PAD(0x5A4, 0x22C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B		IOMUX_PAD(0x5A8, 0x230, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WP_B__GPIO6_9			IOMUX_PAD(0x5A8, 0x230, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2		IOMUX_PAD(0x5A8, 0x230, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0		IOMUX_PAD(0x5AC, 0x234, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RB0__GPIO6_10			IOMUX_PAD(0x5AC, 0x234, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3		IOMUX_PAD(0x5AC, 0x234, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0		IOMUX_PAD(0x5B0, 0x238, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS0__GPIO6_11			IOMUX_PAD(0x5B0, 0x238, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4		IOMUX_PAD(0x5B0, 0x238, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1		IOMUX_PAD(0x5B4, 0x23C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__GPIO6_14			IOMUX_PAD(0x5B4, 0x23C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__MLB_MLBCLK			IOMUX_PAD(0x5B4, 0x23C, 6, 0x858, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5		IOMUX_PAD(0x5B4, 0x23C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2		IOMUX_PAD(0x5B8, 0x240, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__GPIO6_15			IOMUX_PAD(0x5B8, 0x240, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__IPU_SISG_0			IOMUX_PAD(0x5B8, 0x240, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__ESAI1_TX0			IOMUX_PAD(0x5B8, 0x240, 3, 0x7E4, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__EMI_WEIM_CRE		IOMUX_PAD(0x5B8, 0x240, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK		IOMUX_PAD(0x5B8, 0x240, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__MLB_MLBSIG			IOMUX_PAD(0x5B8, 0x240, 6, 0x860, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6		IOMUX_PAD(0x5B8, 0x240, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3		IOMUX_PAD(0x5BC, 0x244, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__GPIO6_16			IOMUX_PAD(0x5BC, 0x244, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__IPU_SISG_1			IOMUX_PAD(0x5BC, 0x244, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__ESAI1_TX1			IOMUX_PAD(0x5BC, 0x244, 3, 0x7E8, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__EMI_WEIM_A_26		IOMUX_PAD(0x5BC, 0x244, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__MLB_MLBDAT			IOMUX_PAD(0x5BC, 0x244, 6, 0x85C, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7		IOMUX_PAD(0x5BC, 0x244, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__FEC_MDIO			IOMUX_PAD(0x5C4, 0x248, 0, 0x804, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__GPIO1_22			IOMUX_PAD(0x5C4, 0x248, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__ESAI1_SCKR			IOMUX_PAD(0x5C4, 0x248, 2, 0x7DC, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__FEC_COL			IOMUX_PAD(0x5C4, 0x248, 3, 0x800, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2		IOMUX_PAD(0x5C4, 0x248, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3	IOMUX_PAD(0x5C4, 0x248, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49		IOMUX_PAD(0x5C4, 0x248, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__FEC_TX_CLK		IOMUX_PAD(0x5C8, 0x24C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__GPIO1_23			IOMUX_PAD(0x5C8, 0x24C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__ESAI1_FSR			IOMUX_PAD(0x5C8, 0x24C, 2, 0x7CC, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4	IOMUX_PAD(0x5C8, 0x24C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50		IOMUX_PAD(0x5C8, 0x24C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__FEC_RX_ER			IOMUX_PAD(0x5CC, 0x250, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__GPIO1_24			IOMUX_PAD(0x5CC, 0x250, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__ESAI1_HCKR			IOMUX_PAD(0x5CC, 0x250, 2, 0x7D4, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__FEC_RX_CLK			IOMUX_PAD(0x5CC, 0x250, 3, 0x808, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3		IOMUX_PAD(0x5CC, 0x250, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_CRS_DV__FEC_RX_DV			IOMUX_PAD(0x5D0, 0x254, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_CRS_DV__GPIO1_25			IOMUX_PAD(0x5D0, 0x254, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_CRS_DV__ESAI1_SCKT			IOMUX_PAD(0x5D0, 0x254, 2, 0x7E0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__FEC_RDATA_1			IOMUX_PAD(0x5D4, 0x258, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__GPIO1_26			IOMUX_PAD(0x5D4, 0x258, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__ESAI1_FST			IOMUX_PAD(0x5D4, 0x258, 2, 0x7D0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__MLB_MLBSIG			IOMUX_PAD(0x5D4, 0x258, 3, 0x860, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1		IOMUX_PAD(0x5D4, 0x258, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__FEC_RDATA_0			IOMUX_PAD(0x5D8, 0x25C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__GPIO1_27			IOMUX_PAD(0x5D8, 0x25C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__ESAI1_HCKT			IOMUX_PAD(0x5D8, 0x25C, 2, 0x7D8, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__OSC32k_32K_OUT		IOMUX_PAD(0x5D8, 0x25C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TX_EN__FEC_TX_EN			IOMUX_PAD(0x5DC, 0x260, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TX_EN__GPIO1_28			IOMUX_PAD(0x5DC, 0x260, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2		IOMUX_PAD(0x5DC, 0x260, 2, 0x7F0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__FEC_TDATA_1			IOMUX_PAD(0x5E0, 0x264, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__GPIO1_29			IOMUX_PAD(0x5E0, 0x264, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3		IOMUX_PAD(0x5E0, 0x264, 2, 0x7EC, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__MLB_MLBCLK			IOMUX_PAD(0x5E0, 0x264, 3, 0x858, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK		IOMUX_PAD(0x5E0, 0x264, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__FEC_TDATA_0			IOMUX_PAD(0x5E4, 0x268, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__GPIO1_30			IOMUX_PAD(0x5E4, 0x268, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1		IOMUX_PAD(0x5E4, 0x268, 2, 0x7F4, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0		IOMUX_PAD(0x5E4, 0x268, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__FEC_MDC			IOMUX_PAD(0x5E8, 0x26C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__GPIO1_31			IOMUX_PAD(0x5E8, 0x26C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__ESAI1_TX5_RX0			IOMUX_PAD(0x5E8, 0x26C, 2, 0x7F8, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__MLB_MLBDAT			IOMUX_PAD(0x5E8, 0x26C, 3, 0x85C, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG	IOMUX_PAD(0x5E8, 0x26C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1		IOMUX_PAD(0x5E8, 0x26C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOW__PATA_DIOW			IOMUX_PAD(0x5F0, 0x270, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOW__GPIO6_17			IOMUX_PAD(0x5F0, 0x270, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOW__UART1_TXD_MUX		IOMUX_PAD(0x5F0, 0x270, 3, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2		IOMUX_PAD(0x5F0, 0x270, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMACK__PATA_DMACK			IOMUX_PAD(0x5F4, 0x274, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMACK__GPIO6_18			IOMUX_PAD(0x5F4, 0x274, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMACK__UART1_RXD_MUX		IOMUX_PAD(0x5F4, 0x274, 3, 0x878, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3		IOMUX_PAD(0x5F4, 0x274, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__PATA_DMARQ			IOMUX_PAD(0x5F8, 0x278, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__GPIO7_0			IOMUX_PAD(0x5F8, 0x278, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__UART2_TXD_MUX		IOMUX_PAD(0x5F8, 0x278, 3, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0		IOMUX_PAD(0x5F8, 0x278, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4		IOMUX_PAD(0x5F8, 0x278, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN		IOMUX_PAD(0x5FC, 0x27C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__GPIO7_1		IOMUX_PAD(0x5FC, 0x27C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX		IOMUX_PAD(0x5FC, 0x27C, 3, 0x880, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1		IOMUX_PAD(0x5FC, 0x27C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5	IOMUX_PAD(0x5FC, 0x27C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__PATA_INTRQ			IOMUX_PAD(0x600, 0x280, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__GPIO7_2			IOMUX_PAD(0x600, 0x280, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__UART2_CTS			IOMUX_PAD(0x600, 0x280, 3, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__CAN1_TXCAN			IOMUX_PAD(0x600, 0x280, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2		IOMUX_PAD(0x600, 0x280, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6		IOMUX_PAD(0x600, 0x280, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__PATA_DIOR			IOMUX_PAD(0x604, 0x284, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__GPIO7_3			IOMUX_PAD(0x604, 0x284, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__UART2_RTS			IOMUX_PAD(0x604, 0x284, 3, 0x87C, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__CAN1_RXCAN			IOMUX_PAD(0x604, 0x284, 4, 0x760, 1, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7		IOMUX_PAD(0x604, 0x284, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B	IOMUX_PAD(0x608, 0x288, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__GPIO7_4			IOMUX_PAD(0x608, 0x288, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__ESDHC3_CMD		IOMUX_PAD(0x608, 0x288, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__UART1_CTS		IOMUX_PAD(0x608, 0x288, 3, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__CAN2_TXCAN		IOMUX_PAD(0x608, 0x288, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0	IOMUX_PAD(0x608, 0x288, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__PATA_IORDY			IOMUX_PAD(0x60C, 0x28C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__GPIO7_5			IOMUX_PAD(0x60C, 0x28C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__ESDHC3_CLK			IOMUX_PAD(0x60C, 0x28C, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__UART1_RTS			IOMUX_PAD(0x60C, 0x28C, 3, 0x874, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__CAN2_RXCAN			IOMUX_PAD(0x60C, 0x28C, 4, 0x764, 1, NO_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1		IOMUX_PAD(0x60C, 0x28C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__PATA_DA_0			IOMUX_PAD(0x610, 0x290, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__GPIO7_6			IOMUX_PAD(0x610, 0x290, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__ESDHC3_RST			IOMUX_PAD(0x610, 0x290, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__OWIRE_LINE			IOMUX_PAD(0x610, 0x290, 4, 0x864, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2		IOMUX_PAD(0x610, 0x290, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__PATA_DA_1			IOMUX_PAD(0x614, 0x294, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__GPIO7_7			IOMUX_PAD(0x614, 0x294, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__ESDHC4_CMD			IOMUX_PAD(0x614, 0x294, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__UART3_CTS			IOMUX_PAD(0x614, 0x294, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3		IOMUX_PAD(0x614, 0x294, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__PATA_DA_2			IOMUX_PAD(0x618, 0x298, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__GPIO7_8			IOMUX_PAD(0x618, 0x298, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__ESDHC4_CLK			IOMUX_PAD(0x618, 0x298, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__UART3_RTS			IOMUX_PAD(0x618, 0x298, 4, 0x884, 5, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4		IOMUX_PAD(0x618, 0x298, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_0__PATA_CS_0			IOMUX_PAD(0x61C, 0x29C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_0__GPIO7_9			IOMUX_PAD(0x61C, 0x29C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_0__UART3_TXD_MUX		IOMUX_PAD(0x61C, 0x29C, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5		IOMUX_PAD(0x61C, 0x29C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_1__PATA_CS_1			IOMUX_PAD(0x620, 0x2A0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_1__GPIO7_10			IOMUX_PAD(0x620, 0x2A0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_1__UART3_RXD_MUX		IOMUX_PAD(0x620, 0x2A0, 4, 0x888, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6		IOMUX_PAD(0x620, 0x2A0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__PATA_DATA_0		IOMUX_PAD(0x628, 0x2A4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__GPIO2_0			IOMUX_PAD(0x628, 0x2A4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__EMI_NANDF_D_0		IOMUX_PAD(0x628, 0x2A4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__ESDHC3_DAT4		IOMUX_PAD(0x628, 0x2A4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0	IOMUX_PAD(0x628, 0x2A4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0		IOMUX_PAD(0x628, 0x2A4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7		IOMUX_PAD(0x628, 0x2A4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__PATA_DATA_1		IOMUX_PAD(0x62C, 0x2A8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__GPIO2_1			IOMUX_PAD(0x62C, 0x2A8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__EMI_NANDF_D_1		IOMUX_PAD(0x62C, 0x2A8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__ESDHC3_DAT5		IOMUX_PAD(0x62C, 0x2A8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1	IOMUX_PAD(0x62C, 0x2A8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1		IOMUX_PAD(0x62C, 0x2A8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__PATA_DATA_2		IOMUX_PAD(0x630, 0x2AC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__GPIO2_2			IOMUX_PAD(0x630, 0x2AC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__EMI_NANDF_D_2		IOMUX_PAD(0x630, 0x2AC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__ESDHC3_DAT6		IOMUX_PAD(0x630, 0x2AC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2	IOMUX_PAD(0x630, 0x2AC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2		IOMUX_PAD(0x630, 0x2AC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__PATA_DATA_3		IOMUX_PAD(0x634, 0x2B0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__GPIO2_3			IOMUX_PAD(0x634, 0x2B0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__EMI_NANDF_D_3		IOMUX_PAD(0x634, 0x2B0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__ESDHC3_DAT7		IOMUX_PAD(0x634, 0x2B0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3	IOMUX_PAD(0x634, 0x2B0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3		IOMUX_PAD(0x634, 0x2B0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__PATA_DATA_4		IOMUX_PAD(0x638, 0x2B4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__GPIO2_4			IOMUX_PAD(0x638, 0x2B4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__EMI_NANDF_D_4		IOMUX_PAD(0x638, 0x2B4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__ESDHC4_DAT4		IOMUX_PAD(0x638, 0x2B4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4	IOMUX_PAD(0x638, 0x2B4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4		IOMUX_PAD(0x638, 0x2B4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__PATA_DATA_5		IOMUX_PAD(0x63C, 0x2B8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__GPIO2_5			IOMUX_PAD(0x63C, 0x2B8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__EMI_NANDF_D_5		IOMUX_PAD(0x63C, 0x2B8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__ESDHC4_DAT5		IOMUX_PAD(0x63C, 0x2B8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5	IOMUX_PAD(0x63C, 0x2B8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5		IOMUX_PAD(0x63C, 0x2B8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__PATA_DATA_6		IOMUX_PAD(0x640, 0x2BC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__GPIO2_6			IOMUX_PAD(0x640, 0x2BC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__EMI_NANDF_D_6		IOMUX_PAD(0x640, 0x2BC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__ESDHC4_DAT6		IOMUX_PAD(0x640, 0x2BC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6	IOMUX_PAD(0x640, 0x2BC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6		IOMUX_PAD(0x640, 0x2BC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__PATA_DATA_7		IOMUX_PAD(0x644, 0x2C0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__GPIO2_7			IOMUX_PAD(0x644, 0x2C0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__EMI_NANDF_D_7		IOMUX_PAD(0x644, 0x2C0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__ESDHC4_DAT7		IOMUX_PAD(0x644, 0x2C0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7	IOMUX_PAD(0x644, 0x2C0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7		IOMUX_PAD(0x644, 0x2C0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__PATA_DATA_8		IOMUX_PAD(0x648, 0x2C4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__GPIO2_8			IOMUX_PAD(0x648, 0x2C4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__ESDHC1_DAT4		IOMUX_PAD(0x648, 0x2C4, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__EMI_NANDF_D_8		IOMUX_PAD(0x648, 0x2C4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__ESDHC3_DAT0		IOMUX_PAD(0x648, 0x2C4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8	IOMUX_PAD(0x648, 0x2C4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8		IOMUX_PAD(0x648, 0x2C4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__PATA_DATA_9		IOMUX_PAD(0x64C, 0x2C8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__GPIO2_9			IOMUX_PAD(0x64C, 0x2C8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__ESDHC1_DAT5		IOMUX_PAD(0x64C, 0x2C8, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__EMI_NANDF_D_9		IOMUX_PAD(0x64C, 0x2C8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__ESDHC3_DAT1		IOMUX_PAD(0x64C, 0x2C8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9	IOMUX_PAD(0x64C, 0x2C8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9		IOMUX_PAD(0x64C, 0x2C8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__PATA_DATA_10		IOMUX_PAD(0x650, 0x2CC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__GPIO2_10			IOMUX_PAD(0x650, 0x2CC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__ESDHC1_DAT6		IOMUX_PAD(0x650, 0x2CC, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__EMI_NANDF_D_10		IOMUX_PAD(0x650, 0x2CC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__ESDHC3_DAT2		IOMUX_PAD(0x650, 0x2CC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10	IOMUX_PAD(0x650, 0x2CC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10		IOMUX_PAD(0x650, 0x2CC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__PATA_DATA_11		IOMUX_PAD(0x654, 0x2D0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__GPIO2_11			IOMUX_PAD(0x654, 0x2D0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__ESDHC1_DAT7		IOMUX_PAD(0x654, 0x2D0, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__EMI_NANDF_D_11		IOMUX_PAD(0x654, 0x2D0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__ESDHC3_DAT3		IOMUX_PAD(0x654, 0x2D0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11	IOMUX_PAD(0x654, 0x2D0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11		IOMUX_PAD(0x654, 0x2D0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__PATA_DATA_12		IOMUX_PAD(0x658, 0x2D4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__GPIO2_12			IOMUX_PAD(0x658, 0x2D4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__ESDHC2_DAT4		IOMUX_PAD(0x658, 0x2D4, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__EMI_NANDF_D_12		IOMUX_PAD(0x658, 0x2D4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__ESDHC4_DAT0		IOMUX_PAD(0x658, 0x2D4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12	IOMUX_PAD(0x658, 0x2D4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12		IOMUX_PAD(0x658, 0x2D4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__PATA_DATA_13		IOMUX_PAD(0x65C, 0x2D8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__GPIO2_13			IOMUX_PAD(0x65C, 0x2D8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__ESDHC2_DAT5		IOMUX_PAD(0x65C, 0x2D8, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__EMI_NANDF_D_13		IOMUX_PAD(0x65C, 0x2D8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__ESDHC4_DAT1		IOMUX_PAD(0x65C, 0x2D8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13	IOMUX_PAD(0x65C, 0x2D8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13		IOMUX_PAD(0x65C, 0x2D8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__PATA_DATA_14		IOMUX_PAD(0x660, 0x2DC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__GPIO2_14			IOMUX_PAD(0x660, 0x2DC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__ESDHC2_DAT6		IOMUX_PAD(0x660, 0x2DC, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__EMI_NANDF_D_14		IOMUX_PAD(0x660, 0x2DC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__ESDHC4_DAT2		IOMUX_PAD(0x660, 0x2DC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14	IOMUX_PAD(0x660, 0x2DC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14		IOMUX_PAD(0x660, 0x2DC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__PATA_DATA_15		IOMUX_PAD(0x664, 0x2E0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__GPIO2_15			IOMUX_PAD(0x664, 0x2E0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__ESDHC2_DAT7		IOMUX_PAD(0x664, 0x2E0, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__EMI_NANDF_D_15		IOMUX_PAD(0x664, 0x2E0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__ESDHC4_DAT3		IOMUX_PAD(0x664, 0x2E0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15	IOMUX_PAD(0x664, 0x2E0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15		IOMUX_PAD(0x664, 0x2E0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__ESDHC1_DAT0			IOMUX_PAD(0x66C, 0x2E4, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__GPIO1_16			IOMUX_PAD(0x66C, 0x2E4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__GPT_CAPIN1			IOMUX_PAD(0x66C, 0x2E4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__CSPI_MISO			IOMUX_PAD(0x66C, 0x2E4, 5, 0x784, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__CCM_PLL3_BYP		IOMUX_PAD(0x66C, 0x2E4, 7, 0x778, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__ESDHC1_DAT1			IOMUX_PAD(0x670, 0x2E8, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__GPIO1_17			IOMUX_PAD(0x670, 0x2E8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__GPT_CAPIN2			IOMUX_PAD(0x670, 0x2E8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__CSPI_SS0			IOMUX_PAD(0x670, 0x2E8, 5, 0x78C, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__CCM_PLL4_BYP		IOMUX_PAD(0x670, 0x2E8, 7, 0x77C, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__ESDHC1_CMD			IOMUX_PAD(0x674, 0x2EC, 0 | IOMUX_CONFIG_SION, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__GPIO1_18			IOMUX_PAD(0x674, 0x2EC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__GPT_CMPOUT1			IOMUX_PAD(0x674, 0x2EC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__CSPI_MOSI			IOMUX_PAD(0x674, 0x2EC, 5, 0x788, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__CCM_PLL1_BYP			IOMUX_PAD(0x674, 0x2EC, 7, 0x770, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__ESDHC1_DAT2			IOMUX_PAD(0x678, 0x2F0, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__GPIO1_19			IOMUX_PAD(0x678, 0x2F0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__GPT_CMPOUT2			IOMUX_PAD(0x678, 0x2F0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__PWM2_PWMO			IOMUX_PAD(0x678, 0x2F0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_B		IOMUX_PAD(0x678, 0x2F0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__CSPI_SS1			IOMUX_PAD(0x678, 0x2F0, 5, 0x790, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB	IOMUX_PAD(0x678, 0x2F0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__CCM_PLL2_BYP		IOMUX_PAD(0x678, 0x2F0, 7, 0x774, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__ESDHC1_CLK			IOMUX_PAD(0x67C, 0x2F4, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__GPIO1_20			IOMUX_PAD(0x67C, 0x2F4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__OSC32k_32K_OUT		IOMUX_PAD(0x67C, 0x2F4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__GPT_CLKIN			IOMUX_PAD(0x67C, 0x2F4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__CSPI_SCLK			IOMUX_PAD(0x67C, 0x2F4, 5, 0x780, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__SATA_PHY_DTB_0		IOMUX_PAD(0x67C, 0x2F4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__ESDHC1_DAT3			IOMUX_PAD(0x680, 0x2F8, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__GPIO1_21			IOMUX_PAD(0x680, 0x2F8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__GPT_CMPOUT3			IOMUX_PAD(0x680, 0x2F8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__PWM1_PWMO			IOMUX_PAD(0x680, 0x2F8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_B		IOMUX_PAD(0x680, 0x2F8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__CSPI_SS2			IOMUX_PAD(0x680, 0x2F8, 5, 0x794, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB	IOMUX_PAD(0x680, 0x2F8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1		IOMUX_PAD(0x680, 0x2F8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__ESDHC2_CLK			IOMUX_PAD(0x688, 0x2FC, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__GPIO1_10			IOMUX_PAD(0x688, 0x2FC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__KPP_COL_5			IOMUX_PAD(0x688, 0x2FC, 2, 0x840, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS		IOMUX_PAD(0x688, 0x2FC, 3, 0x73C, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__CSPI_SCLK			IOMUX_PAD(0x688, 0x2FC, 5, 0x780, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__SCC_RANDOM_V			IOMUX_PAD(0x688, 0x2FC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__ESDHC2_CMD			IOMUX_PAD(0x68C, 0x300, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__GPIO1_11			IOMUX_PAD(0x68C, 0x300, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__KPP_ROW_5			IOMUX_PAD(0x68C, 0x300, 2, 0x84C, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC		IOMUX_PAD(0x68C, 0x300, 3, 0x738, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__CSPI_MOSI			IOMUX_PAD(0x68C, 0x300, 5, 0x788, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__SCC_RANDOM			IOMUX_PAD(0x68C, 0x300, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__ESDHC2_DAT3			IOMUX_PAD(0x690, 0x304, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__GPIO1_12			IOMUX_PAD(0x690, 0x304, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__KPP_COL_6			IOMUX_PAD(0x690, 0x304, 2, 0x844, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC		IOMUX_PAD(0x690, 0x304, 3, 0x740, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__CSPI_SS2			IOMUX_PAD(0x690, 0x304, 5, 0x794, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__SJC_DONE			IOMUX_PAD(0x690, 0x304, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__ESDHC2_DAT2			IOMUX_PAD(0x694, 0x308, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__GPIO1_13			IOMUX_PAD(0x694, 0x308, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__KPP_ROW_6			IOMUX_PAD(0x694, 0x308, 2, 0x850, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD		IOMUX_PAD(0x694, 0x308, 3, 0x734, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__CSPI_SS1			IOMUX_PAD(0x694, 0x308, 5, 0x790, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__SJC_FAIL			IOMUX_PAD(0x694, 0x308, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__ESDHC2_DAT1			IOMUX_PAD(0x698, 0x30C, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__GPIO1_14			IOMUX_PAD(0x698, 0x30C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__KPP_COL_7			IOMUX_PAD(0x698, 0x30C, 2, 0x848, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS		IOMUX_PAD(0x698, 0x30C, 3, 0x744, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__CSPI_SS0			IOMUX_PAD(0x698, 0x30C, 5, 0x78C, 4, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__RTIC_SEC_VIO		IOMUX_PAD(0x698, 0x30C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__ESDHC2_DAT0			IOMUX_PAD(0x69C, 0x310, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__GPIO1_15			IOMUX_PAD(0x69C, 0x310, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__KPP_ROW_7			IOMUX_PAD(0x69C, 0x310, 2, 0x854, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD		IOMUX_PAD(0x69C, 0x310, 3, 0x730, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__CSPI_MISO			IOMUX_PAD(0x69C, 0x310, 5, 0x784, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__RTIC_DONE_INT		IOMUX_PAD(0x69C, 0x310, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__CCM_CLKO			IOMUX_PAD(0x6A4, 0x314, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__GPIO1_0			IOMUX_PAD(0x6A4, 0x314, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__KPP_COL_5			IOMUX_PAD(0x6A4, 0x314, 2, 0x840, 3, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK		IOMUX_PAD(0x6A4, 0x314, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__EPIT1_EPITO			IOMUX_PAD(0x6A4, 0x314, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__SRTC_ALARM_DEB			IOMUX_PAD(0x6A4, 0x314, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__USBOH3_USBH1_PWR		IOMUX_PAD(0x6A4, 0x314, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__CSU_TD				IOMUX_PAD(0x6A4, 0x314, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__ESAI1_SCKR			IOMUX_PAD(0x6A8, 0x318, 0, 0x7DC, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__GPIO1_1			IOMUX_PAD(0x6A8, 0x318, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__KPP_ROW_5			IOMUX_PAD(0x6A8, 0x318, 2, 0x84C, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK		IOMUX_PAD(0x6A8, 0x318, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__PWM2_PWMO			IOMUX_PAD(0x6A8, 0x318, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__WDOG2_WDOG_B			IOMUX_PAD(0x6A8, 0x318, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__ESDHC1_CD			IOMUX_PAD(0x6A8, 0x318, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__SRC_TESTER_ACK			IOMUX_PAD(0x6A8, 0x318, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__ESAI1_FSR			IOMUX_PAD(0x6AC, 0x31C, 0, 0x7CC, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__GPIO1_9			IOMUX_PAD(0x6AC, 0x31C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__KPP_COL_6			IOMUX_PAD(0x6AC, 0x31C, 2, 0x844, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__CCM_REF_EN_B			IOMUX_PAD(0x6AC, 0x31C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__PWM1_PWMO			IOMUX_PAD(0x6AC, 0x31C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__WDOG1_WDOG_B			IOMUX_PAD(0x6AC, 0x31C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__ESDHC1_WP			IOMUX_PAD(0x6AC, 0x31C, 6, 0x7FC, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__SCC_FAIL_STATE			IOMUX_PAD(0x6AC, 0x31C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__ESAI1_HCKR			IOMUX_PAD(0x6B0, 0x320, 0, 0x7D4, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__GPIO1_3			IOMUX_PAD(0x6B0, 0x320, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__I2C3_SCL			IOMUX_PAD(0x6B0, 0x320, 2 | IOMUX_CONFIG_SION, 0x824, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__DPLLIP1_TOG_EN			IOMUX_PAD(0x6B0, 0x320, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__CCM_CLKO2			IOMUX_PAD(0x6B0, 0x320, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0	IOMUX_PAD(0x6B0, 0x320, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__USBOH3_USBH1_OC		IOMUX_PAD(0x6B0, 0x320, 6, 0x8A0, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__MLB_MLBCLK			IOMUX_PAD(0x6B0, 0x320, 7, 0x858, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__ESAI1_SCKT			IOMUX_PAD(0x6B4, 0x324, 0, 0x7E0, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__GPIO1_6			IOMUX_PAD(0x6B4, 0x324, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__I2C3_SDA			IOMUX_PAD(0x6B4, 0x324, 2 | IOMUX_CONFIG_SION, 0x828, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__CCM_CCM_OUT_0			IOMUX_PAD(0x6B4, 0x324, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__CSU_CSU_INT_DEB		IOMUX_PAD(0x6B4, 0x324, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1	IOMUX_PAD(0x6B4, 0x324, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__ESDHC2_LCTL			IOMUX_PAD(0x6B4, 0x324, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__MLB_MLBSIG			IOMUX_PAD(0x6B4, 0x324, 7, 0x860, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__ESAI1_FST			IOMUX_PAD(0x6B8, 0x328, 0, 0x7D0, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__GPIO1_2			IOMUX_PAD(0x6B8, 0x328, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__KPP_ROW_6			IOMUX_PAD(0x6B8, 0x328, 2, 0x850, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__CCM_CCM_OUT_1			IOMUX_PAD(0x6B8, 0x328, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0		IOMUX_PAD(0x6B8, 0x328, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2	IOMUX_PAD(0x6B8, 0x328, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__ESDHC2_WP			IOMUX_PAD(0x6B8, 0x328, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__MLB_MLBDAT			IOMUX_PAD(0x6B8, 0x328, 7, 0x85C, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__ESAI1_HCKT			IOMUX_PAD(0x6BC, 0x32C, 0, 0x7D8, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__GPIO1_4			IOMUX_PAD(0x6BC, 0x32C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__KPP_COL_7			IOMUX_PAD(0x6BC, 0x32C, 2, 0x848, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__CCM_CCM_OUT_2			IOMUX_PAD(0x6BC, 0x32C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1		IOMUX_PAD(0x6BC, 0x32C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3	IOMUX_PAD(0x6BC, 0x32C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__ESDHC2_CD			IOMUX_PAD(0x6BC, 0x32C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__SCC_SEC_STATE			IOMUX_PAD(0x6BC, 0x32C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__ESAI1_TX2_RX3			IOMUX_PAD(0x6C0, 0x330, 0, 0x7EC, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__GPIO1_5			IOMUX_PAD(0x6C0, 0x330, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__KPP_ROW_7			IOMUX_PAD(0x6C0, 0x330, 2, 0x854, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__CCM_CLKO			IOMUX_PAD(0x6C0, 0x330, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2		IOMUX_PAD(0x6C0, 0x330, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4	IOMUX_PAD(0x6C0, 0x330, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__I2C3_SCL			IOMUX_PAD(0x6C0, 0x330, 6 | IOMUX_CONFIG_SION, 0x824, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__CCM_PLL1_BYP			IOMUX_PAD(0x6C0, 0x330, 7, 0x770, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__ESAI1_TX4_RX1			IOMUX_PAD(0x6C4, 0x334, 0, 0x7F4, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__GPIO1_7			IOMUX_PAD(0x6C4, 0x334, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__EPIT1_EPITO			IOMUX_PAD(0x6C4, 0x334, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__CAN1_TXCAN			IOMUX_PAD(0x6C4, 0x334, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__UART2_TXD_MUX			IOMUX_PAD(0x6C4, 0x334, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_GPIO_7__FIRI_RXD			IOMUX_PAD(0x6C4, 0x334, 5, 0x80C, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__SPDIF_PLOCK			IOMUX_PAD(0x6C4, 0x334, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__CCM_PLL2_BYP			IOMUX_PAD(0x6C4, 0x334, 7, 0x774, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__ESAI1_TX5_RX0			IOMUX_PAD(0x6C8, 0x338, 0, 0x7F8, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__GPIO1_8			IOMUX_PAD(0x6C8, 0x338, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__EPIT2_EPITO			IOMUX_PAD(0x6C8, 0x338, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__CAN1_RXCAN			IOMUX_PAD(0x6C8, 0x338, 3, 0x760, 3, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__UART2_RXD_MUX			IOMUX_PAD(0x6C8, 0x338, 4, 0x880, 5, MX53_UART_PAD_CTRL)
+#define MX53_PAD_GPIO_8__FIRI_TXD			IOMUX_PAD(0x6C8, 0x338, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__SPDIF_SRCLK			IOMUX_PAD(0x6C8, 0x338, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__CCM_PLL3_BYP			IOMUX_PAD(0x6C8, 0x338, 7, 0x778, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__ESAI1_TX3_RX2			IOMUX_PAD(0x6CC, 0x33C, 0, 0x7F0, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__GPIO7_11			IOMUX_PAD(0x6CC, 0x33C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT		IOMUX_PAD(0x6CC, 0x33C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1		IOMUX_PAD(0x6CC, 0x33C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__SPDIF_IN1			IOMUX_PAD(0x6CC, 0x33C, 5, 0x870, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__I2C3_SDA			IOMUX_PAD(0x6CC, 0x33C, 6 | IOMUX_CONFIG_SION, 0x828, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__SJC_DE_B			IOMUX_PAD(0x6CC, 0x33C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__ESAI1_TX0			IOMUX_PAD(0x6D0, 0x340, 0, 0x7E4, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__GPIO7_12			IOMUX_PAD(0x6D0, 0x340, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0		IOMUX_PAD(0x6D0, 0x340, 2, 0x868, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__GPC_PMIC_RDY			IOMUX_PAD(0x6D0, 0x340, 3, 0x810, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG		IOMUX_PAD(0x6D0, 0x340, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__SPDIF_OUT1			IOMUX_PAD(0x6D0, 0x340, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__IPU_SNOOP2			IOMUX_PAD(0x6D0, 0x340, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__SJC_JTAG_ACT			IOMUX_PAD(0x6D0, 0x340, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__ESAI1_TX1			IOMUX_PAD(0x6D4, 0x344, 0, 0x7E8, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__GPIO7_13			IOMUX_PAD(0x6D4, 0x344, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1		IOMUX_PAD(0x6D4, 0x344, 2, 0x86C, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__OWIRE_LINE			IOMUX_PAD(0x6D4, 0x344, 3, 0x864, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG	IOMUX_PAD(0x6D4, 0x344, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK		IOMUX_PAD(0x6D4, 0x344, 5, 0x768, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__ESDHC1_LCTL			IOMUX_PAD(0x6D4, 0x344, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__SRC_SYSTEM_RST		IOMUX_PAD(0x6D4, 0x344, 7, __NA_, 0, NO_PAD_CTRL)
 
 #endif	/* __MACH_IOMUX_MX53_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/iomux-v3.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/iomux-v3.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/iomux-v3.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/iomux-v3.h	2012-01-04 18:55:44.000000000 -0500
@@ -80,6 +80,7 @@
 		((iomux_v3_cfg_t)(_sel_input_ofs) << MUX_SEL_INPUT_OFS_SHIFT) | \
 		((iomux_v3_cfg_t)(_sel_input) << MUX_SEL_INPUT_SHIFT))
 
+#define NEW_PAD_CTRL(cfg, pad)	(((cfg) & ~MUX_PAD_CTRL_MASK) | MUX_PAD_CTRL(pad))
 /*
  * Use to set PAD control
  */
@@ -89,11 +90,11 @@
 #define PAD_CTL_HYS			(1 << 8)
 
 #define PAD_CTL_PKE			(1 << 7)
-#define PAD_CTL_PUE			(1 << 6)
-#define PAD_CTL_PUS_100K_DOWN		(0 << 4)
-#define PAD_CTL_PUS_47K_UP		(1 << 4)
-#define PAD_CTL_PUS_100K_UP		(2 << 4)
-#define PAD_CTL_PUS_22K_UP		(3 << 4)
+#define PAD_CTL_PUE			(1 << 6 | PAD_CTL_PKE)
+#define PAD_CTL_PUS_100K_DOWN		(0 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_47K_UP		(1 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_100K_UP		(2 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_22K_UP		(3 << 4 | PAD_CTL_PUE)
 
 #define PAD_CTL_ODE			(1 << 3)
 
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/irqs.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/irqs.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,9 +14,15 @@
 #include <asm-generic/gpio.h>
 
 /*
- * SoCs with TZIC interrupt controller have 128 IRQs, those with AVIC have 64
+ * SoCs with GIC interrupt controller have 160 IRQs, those with TZIC
+ * have 128 IRQs, and those with AVIC have 64.
+ *
+ * To support single image, the biggest number should be defined on
+ * top of the list.
  */
-#ifdef CONFIG_MXC_TZIC
+#if defined CONFIG_ARM_GIC
+#define MXC_INTERNAL_IRQS	160
+#elif defined CONFIG_MXC_TZIC
 #define MXC_INTERNAL_IRQS	128
 #else
 #define MXC_INTERNAL_IRQS	64
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,58 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_MXC_MEMORY_H__
-#define __ASM_ARCH_MXC_MEMORY_H__
-
-#define MX1_PHYS_OFFSET		UL(0x08000000)
-#define MX21_PHYS_OFFSET	UL(0xc0000000)
-#define MX25_PHYS_OFFSET	UL(0x80000000)
-#define MX27_PHYS_OFFSET	UL(0xa0000000)
-#define MX3x_PHYS_OFFSET	UL(0x80000000)
-#define MX50_PHYS_OFFSET	UL(0x70000000)
-#define MX51_PHYS_OFFSET	UL(0x90000000)
-#define MX53_PHYS_OFFSET	UL(0x70000000)
-
-#if !defined(CONFIG_RUNTIME_PHYS_OFFSET)
-# if defined CONFIG_ARCH_MX1
-#  define PLAT_PHYS_OFFSET		MX1_PHYS_OFFSET
-# elif defined CONFIG_MACH_MX21
-#  define PLAT_PHYS_OFFSET		MX21_PHYS_OFFSET
-# elif defined CONFIG_ARCH_MX25
-#  define PLAT_PHYS_OFFSET		MX25_PHYS_OFFSET
-# elif defined CONFIG_MACH_MX27
-#  define PLAT_PHYS_OFFSET		MX27_PHYS_OFFSET
-# elif defined CONFIG_ARCH_MX3
-#  define PLAT_PHYS_OFFSET		MX3x_PHYS_OFFSET
-# elif defined CONFIG_ARCH_MX50
-#  define PLAT_PHYS_OFFSET		MX50_PHYS_OFFSET
-# elif defined CONFIG_ARCH_MX51
-#  define PLAT_PHYS_OFFSET		MX51_PHYS_OFFSET
-# elif defined CONFIG_ARCH_MX53
-#  define PLAT_PHYS_OFFSET		MX53_PHYS_OFFSET
-# endif
-#endif
-
-#if defined(CONFIG_MX3_VIDEO)
-/*
- * Increase size of DMA-consistent memory region.
- * This is required for mx3 camera driver to capture at least two QXGA frames.
- */
-#define CONSISTENT_DMA_SIZE SZ_8M
-
-#elif defined(CONFIG_MX1_VIDEO) || defined(CONFIG_VIDEO_MX2_HOSTSUPPORT)
-/*
- * Increase size of DMA-consistent memory region.
- * This is required for i.MX camera driver to capture at least four VGA frames.
- */
-#define CONSISTENT_DMA_SIZE SZ_4M
-#endif /* CONFIG_MX1_VIDEO || CONFIG_VIDEO_MX2_HOSTSUPPORT */
-
-#endif /* __ASM_ARCH_MXC_MEMORY_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mx25.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mx25.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mx25.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mx25.h	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
 #define MX25_SSI2_BASE_ADDR		0x50014000
 #define MX25_SSI1_BASE_ADDR		0x50034000
 #define MX25_NFC_BASE_ADDR		0xbb000000
+#define MX25_IIM_BASE_ADDR		0x53ff0000
 #define MX25_DRYICE_BASE_ADDR		0x53ffc000
 #define MX25_ESDHC1_BASE_ADDR		0x53fb4000
 #define MX25_ESDHC2_BASE_ADDR		0x53fb8000
@@ -104,4 +105,8 @@
 #define MX25_DMA_REQ_SSI1_RX0	28
 #define MX25_DMA_REQ_SSI1_TX0	29
 
+#ifndef __ASSEMBLY__
+extern int mx25_revision(void);
+#endif
+
 #endif /* ifndef __MACH_MX25_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mx27.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mx27.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mx27.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mx27.h	2012-01-04 18:55:44.000000000 -0500
@@ -24,10 +24,6 @@
 #ifndef __MACH_MX27_H__
 #define __MACH_MX27_H__
 
-#ifndef __ASSEMBLER__
-#include <linux/io.h>
-#endif
-
 #define MX27_AIPI_BASE_ADDR		0x10000000
 #define MX27_AIPI_SIZE			SZ_1M
 #define MX27_DMA_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x01000)
@@ -131,16 +127,6 @@
 #define MX27_IO_P2V(x)			IMX_IO_P2V(x)
 #define MX27_IO_ADDRESS(x)		IOMEM(MX27_IO_P2V(x))
 
-#ifndef __ASSEMBLER__
-static inline void mx27_setup_weimcs(size_t cs,
-		unsigned upper, unsigned lower, unsigned addional)
-{
-	__raw_writel(upper, MX27_IO_ADDRESS(MX27_WEIM_CSCRxU(cs)));
-	__raw_writel(lower, MX27_IO_ADDRESS(MX27_WEIM_CSCRxL(cs)));
-	__raw_writel(addional, MX27_IO_ADDRESS(MX27_WEIM_CSCRxA(cs)));
-}
-#endif
-
 /* fixed interrupt numbers */
 #define MX27_INT_I2C2		1
 #define MX27_INT_GPT6		2
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mx31.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mx31.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mx31.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mx31.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,10 +1,6 @@
 #ifndef __MACH_MX31_H__
 #define __MACH_MX31_H__
 
-#ifndef __ASSEMBLER__
-#include <linux/io.h>
-#endif
-
 /*
  * IRAM
  */
@@ -122,16 +118,6 @@
 #define MX31_IO_P2V(x)			IMX_IO_P2V(x)
 #define MX31_IO_ADDRESS(x)		IOMEM(MX31_IO_P2V(x))
 
-#ifndef __ASSEMBLER__
-static inline void mx31_setup_weimcs(size_t cs,
-		unsigned upper, unsigned lower, unsigned addional)
-{
-	__raw_writel(upper, MX31_IO_ADDRESS(MX31_WEIM_CSCRxU(cs)));
-	__raw_writel(lower, MX31_IO_ADDRESS(MX31_WEIM_CSCRxL(cs)));
-	__raw_writel(addional, MX31_IO_ADDRESS(MX31_WEIM_CSCRxA(cs)));
-}
-#endif
-
 #define MX31_INT_I2C3		3
 #define MX31_INT_I2C2		4
 #define MX31_INT_MPEG4_ENCODER	5
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mx35.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mx35.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mx35.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mx35.h	2012-01-04 18:55:44.000000000 -0500
@@ -36,7 +36,7 @@
 #define MX35_UART3_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x0c000)
 #define MX35_CSPI2_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x10000)
 #define MX35_SSI2_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x14000)
-#define MX35_ATA_DMA_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x20000)
+#define MX35_ATA_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x20000)
 #define MX35_MSHC1_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x24000)
 #define MX35_FEC_BASE_ADDR		0x50038000
 #define MX35_SPBA_CTRL_BASE_ADDR		(MX35_SPBA0_BASE_ADDR + 0x3c000)
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mx3x.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mx3x.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mx3x.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mx3x.h	2012-01-04 18:55:44.000000000 -0500
@@ -187,22 +187,8 @@
 /* Mandatory defines used globally */
 
 #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
-
-extern unsigned int mx31_cpu_rev;
-extern void mx31_read_cpu_rev(void);
-
-static inline int mx31_revision(void)
-{
-	return mx31_cpu_rev;
-}
-
-extern unsigned int mx35_cpu_rev;
-extern void mx35_read_cpu_rev(void);
-
-static inline int mx35_revision(void)
-{
-	return mx35_cpu_rev;
-}
+extern int mx35_revision(void);
+extern int mx31_revision(void);
 #endif
 
 #endif /* ifndef __MACH_MX3x_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mx51.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mx51.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mx51.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mx51.h	2012-01-04 18:55:44.000000000 -0500
@@ -18,18 +18,6 @@
 #define MX51_GPU_CTRL_BASE_ADDR		0x30000000
 #define MX51_IPU_CTRL_BASE_ADDR		0x40000000
 
-#define MX51_DEBUG_BASE_ADDR		0x60000000
-#define MX51_DEBUG_SIZE			SZ_1M
-
-#define MX51_ETB_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x01000)
-#define MX51_ETM_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x02000)
-#define MX51_TPIU_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x03000)
-#define MX51_CTI0_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x04000)
-#define MX51_CTI1_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x05000)
-#define MX51_CTI2_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x06000)
-#define MX51_CTI3_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x07000)
-#define MX51_CORTEX_DBG_BASE_ADDR	(MX51_DEBUG_BASE_ADDR + 0x08000)
-
 /*
  * SPBA global module enabled #0
  */
@@ -55,7 +43,10 @@
 #define MX51_AIPS1_BASE_ADDR		0x73f00000
 #define MX51_AIPS1_SIZE			SZ_1M
 
-#define MX51_OTG_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x80000)
+#define MX51_USB_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x80000)
+#define MX51_USB_OTG_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0000)
+#define MX51_USB_HS1_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0200)
+#define MX51_USB_HS2_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0400)
 #define MX51_GPIO1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x84000)
 #define MX51_GPIO2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x88000)
 #define MX51_GPIO3_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x8c000)
@@ -132,6 +123,7 @@
 
 #define MX51_GPU2D_BASE_ADDR		0xd0000000
 #define MX51_TZIC_BASE_ADDR		0xe0000000
+#define MX51_TZIC_SIZE			SZ_16K
 
 #define MX51_IO_P2V(x)			IMX_IO_P2V(x)
 #define MX51_IO_ADDRESS(x)		IOMEM(MX51_IO_P2V(x))
@@ -240,117 +232,114 @@
 /*
  * Interrupt numbers
  */
-#define MX51_MXC_INT_BASE		0
-#define MX51_MXC_INT_RESV0		0
+#define MX51_INT_BASE			0
+#define MX51_INT_RESV0			0
 #define MX51_INT_ESDHC1			1
 #define MX51_INT_ESDHC2			2
 #define MX51_INT_ESDHC3			3
 #define MX51_INT_ESDHC4			4
-#define MX51_MXC_INT_RESV5		5
+#define MX51_INT_RESV5			5
 #define MX51_INT_SDMA			6
-#define MX51_MXC_INT_IOMUX		7
+#define MX51_INT_IOMUX			7
 #define MX51_INT_NFC			8
-#define MX51_MXC_INT_VPU		9
+#define MX51_INT_VPU			9
 #define MX51_INT_IPU_ERR		10
 #define MX51_INT_IPU_SYN		11
-#define MX51_MXC_INT_GPU		12
-#define MX51_MXC_INT_RESV13		13
-#define MX51_MXC_INT_USB_H1		14
-#define MX51_MXC_INT_EMI		15
-#define MX51_MXC_INT_USB_H2		16
-#define MX51_MXC_INT_USB_H3		17
-#define MX51_MXC_INT_USB_OTG		18
-#define MX51_MXC_INT_SAHARA_H0		19
-#define MX51_MXC_INT_SAHARA_H1		20
-#define MX51_MXC_INT_SCC_SMN		21
-#define MX51_MXC_INT_SCC_STZ		22
-#define MX51_MXC_INT_SCC_SCM		23
-#define MX51_MXC_INT_SRTC_NTZ		24
-#define MX51_MXC_INT_SRTC_TZ		25
-#define MX51_MXC_INT_RTIC		26
-#define MX51_MXC_INT_CSU		27
-#define MX51_MXC_INT_SLIM_B		28
+#define MX51_INT_GPU			12
+#define MX51_INT_RESV13			13
+#define MX51_INT_USB_HS1		14
+#define MX51_INT_EMI			15
+#define MX51_INT_USB_HS2		16
+#define MX51_INT_USB_HS3		17
+#define MX51_INT_USB_OTG		18
+#define MX51_INT_SAHARA_H0		19
+#define MX51_INT_SAHARA_H1		20
+#define MX51_INT_SCC_SMN		21
+#define MX51_INT_SCC_STZ		22
+#define MX51_INT_SCC_SCM		23
+#define MX51_INT_SRTC_NTZ		24
+#define MX51_INT_SRTC_TZ		25
+#define MX51_INT_RTIC			26
+#define MX51_INT_CSU			27
+#define MX51_INT_SLIM_B			28
 #define MX51_INT_SSI1			29
 #define MX51_INT_SSI2			30
 #define MX51_INT_UART1			31
 #define MX51_INT_UART2			32
 #define MX51_INT_UART3			33
-#define MX51_MXC_INT_RESV34		34
-#define MX51_MXC_INT_RESV35		35
+#define MX51_INT_RESV34			34
+#define MX51_INT_RESV35			35
 #define MX51_INT_ECSPI1			36
 #define MX51_INT_ECSPI2			37
 #define MX51_INT_CSPI			38
-#define MX51_MXC_INT_GPT		39
-#define MX51_MXC_INT_EPIT1		40
-#define MX51_MXC_INT_EPIT2		41
-#define MX51_MXC_INT_GPIO1_INT7		42
-#define MX51_MXC_INT_GPIO1_INT6		43
-#define MX51_MXC_INT_GPIO1_INT5		44
-#define MX51_MXC_INT_GPIO1_INT4		45
-#define MX51_MXC_INT_GPIO1_INT3		46
-#define MX51_MXC_INT_GPIO1_INT2		47
-#define MX51_MXC_INT_GPIO1_INT1		48
-#define MX51_MXC_INT_GPIO1_INT0		49
-#define MX51_MXC_INT_GPIO1_LOW		50
-#define MX51_MXC_INT_GPIO1_HIGH		51
-#define MX51_MXC_INT_GPIO2_LOW		52
-#define MX51_MXC_INT_GPIO2_HIGH		53
-#define MX51_MXC_INT_GPIO3_LOW		54
-#define MX51_MXC_INT_GPIO3_HIGH		55
-#define MX51_MXC_INT_GPIO4_LOW		56
-#define MX51_MXC_INT_GPIO4_HIGH		57
-#define MX51_MXC_INT_WDOG1		58
-#define MX51_MXC_INT_WDOG2		59
+#define MX51_INT_GPT			39
+#define MX51_INT_EPIT1			40
+#define MX51_INT_EPIT2			41
+#define MX51_INT_GPIO1_INT7		42
+#define MX51_INT_GPIO1_INT6		43
+#define MX51_INT_GPIO1_INT5		44
+#define MX51_INT_GPIO1_INT4		45
+#define MX51_INT_GPIO1_INT3		46
+#define MX51_INT_GPIO1_INT2		47
+#define MX51_INT_GPIO1_INT1		48
+#define MX51_INT_GPIO1_INT0		49
+#define MX51_INT_GPIO1_LOW		50
+#define MX51_INT_GPIO1_HIGH		51
+#define MX51_INT_GPIO2_LOW		52
+#define MX51_INT_GPIO2_HIGH		53
+#define MX51_INT_GPIO3_LOW		54
+#define MX51_INT_GPIO3_HIGH		55
+#define MX51_INT_GPIO4_LOW		56
+#define MX51_INT_GPIO4_HIGH		57
+#define MX51_INT_WDOG1			58
+#define MX51_INT_WDOG2			59
 #define MX51_INT_KPP			60
 #define MX51_INT_PWM1			61
 #define MX51_INT_I2C1			62
 #define MX51_INT_I2C2			63
-#define MX51_MXC_INT_HS_I2C		64
-#define MX51_MXC_INT_RESV65		65
-#define MX51_MXC_INT_RESV66		66
-#define MX51_MXC_INT_SIM_IPB		67
-#define MX51_MXC_INT_SIM_DAT		68
-#define MX51_MXC_INT_IIM		69
-#define MX51_MXC_INT_ATA		70
-#define MX51_MXC_INT_CCM1		71
-#define MX51_MXC_INT_CCM2		72
-#define MX51_MXC_INT_GPC1		73
-#define MX51_MXC_INT_GPC2		74
-#define MX51_MXC_INT_SRC		75
-#define MX51_MXC_INT_NM			76
-#define MX51_MXC_INT_PMU		77
-#define MX51_MXC_INT_CTI_IRQ		78
-#define MX51_MXC_INT_CTI1_TG0		79
-#define MX51_MXC_INT_CTI1_TG1		80
-#define MX51_MXC_INT_MCG_ERR		81
-#define MX51_MXC_INT_MCG_TMR		82
-#define MX51_MXC_INT_MCG_FUNC		83
-#define MX51_MXC_INT_GPU2_IRQ		84
-#define MX51_MXC_INT_GPU2_BUSY		85
-#define MX51_MXC_INT_RESV86		86
+#define MX51_INT_HS_I2C			64
+#define MX51_INT_RESV65			65
+#define MX51_INT_RESV66			66
+#define MX51_INT_SIM_IPB		67
+#define MX51_INT_SIM_DAT		68
+#define MX51_INT_IIM			69
+#define MX51_INT_ATA			70
+#define MX51_INT_CCM1			71
+#define MX51_INT_CCM2			72
+#define MX51_INT_GPC1				73
+#define MX51_INT_GPC2			74
+#define MX51_INT_SRC			75
+#define MX51_INT_NM			76
+#define MX51_INT_PMU			77
+#define MX51_INT_CTI_IRQ		78
+#define MX51_INT_CTI1_TG0		79
+#define MX51_INT_CTI1_TG1		80
+#define MX51_INT_MCG_ERR		81
+#define MX51_INT_MCG_TMR		82
+#define MX51_INT_MCG_FUNC		83
+#define MX51_INT_GPU2_IRQ		84
+#define MX51_INT_GPU2_BUSY		85
+#define MX51_INT_RESV86			86
 #define MX51_INT_FEC			87
-#define MX51_MXC_INT_OWIRE		88
-#define MX51_MXC_INT_CTI1_TG2		89
-#define MX51_MXC_INT_SJC		90
-#define MX51_MXC_INT_SPDIF		91
-#define MX51_MXC_INT_TVE		92
-#define MX51_MXC_INT_FIRI		93
+#define MX51_INT_OWIRE			88
+#define MX51_INT_CTI1_TG2		89
+#define MX51_INT_SJC			90
+#define MX51_INT_SPDIF			91
+#define MX51_INT_TVE			92
+#define MX51_INT_FIRI			93
 #define MX51_INT_PWM2			94
-#define MX51_MXC_INT_SLIM_EXP		95
+#define MX51_INT_SLIM_EXP		95
 #define MX51_INT_SSI3			96
-#define MX51_MXC_INT_EMI_BOOT		97
-#define MX51_MXC_INT_CTI1_TG3		98
-#define MX51_MXC_INT_SMC_RX		99
-#define MX51_MXC_INT_VPU_IDLE		100
-#define MX51_MXC_INT_EMI_NFC		101
-#define MX51_MXC_INT_GPU_IDLE		102
+#define MX51_INT_EMI_BOOT		97
+#define MX51_INT_CTI1_TG3		98
+#define MX51_INT_SMC_RX			99
+#define MX51_INT_VPU_IDLE		100
+#define MX51_INT_EMI_NFC		101
+#define MX51_INT_GPU_IDLE		102
 
 #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
 extern int mx51_revision(void);
 extern void mx51_display_revision(void);
 #endif
 
-/* tape-out 1 defines */
-#define MX51_TZIC_BASE_ADDR_TO1		0x8fffc000
-
 #endif	/* ifndef __MACH_MX51_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mx53.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mx53.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mx53.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mx53.h	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 
 /* TZIC */
 #define MX53_TZIC_BASE_ADDR		0x0FFFC000
+#define MX53_TZIC_SIZE			SZ_16K
 
 /*
  * AHCI SATA
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mx6q.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mx6q.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mx6q.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mx6q.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __MACH_MX6Q_H__
+#define __MACH_MX6Q_H__
+
+#define MX6Q_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX6Q_IO_ADDRESS(x)		IOMEM(MX6Q_IO_P2V(x))
+
+/*
+ * The following are the blocks that need to be statically mapped.
+ * For other blocks, the base address really should be retrieved from
+ * device tree.
+ */
+#define MX6Q_SCU_BASE_ADDR		0x00a00000
+#define MX6Q_SCU_SIZE			0x1000
+#define MX6Q_CCM_BASE_ADDR		0x020c4000
+#define MX6Q_CCM_SIZE			0x4000
+#define MX6Q_ANATOP_BASE_ADDR		0x020c8000
+#define MX6Q_ANATOP_SIZE		0x1000
+#define MX6Q_UART4_BASE_ADDR		0x021f0000
+#define MX6Q_UART4_SIZE			0x4000
+
+#endif	/* __MACH_MX6Q_H__ */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mxc.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mxc.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/mxc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/mxc.h	2012-01-04 18:55:44.000000000 -0500
@@ -50,20 +50,6 @@
 #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
@@ -183,13 +169,6 @@
 };
 
 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-3.1-gnu/arch/arm/plat-mxc/include/mach/system.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/system.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,43 +17,9 @@
 #ifndef __ASM_ARCH_MXC_SYSTEM_H__
 #define __ASM_ARCH_MXC_SYSTEM_H__
 
-#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)
 {
-	/* fix i.MX31 errata TLSbo65953 and i.MX35 errata ENGcm09472 */
-	if (cpu_is_mx31() || cpu_is_mx35()) {
-		unsigned long reg = 0;
-		__asm__ __volatile__(
-			/* disable I and D cache */
-			"mrc p15, 0, %0, c1, c0, 0\n"
-			"bic %0, %0, #0x00001000\n"
-			"bic %0, %0, #0x00000004\n"
-			"mcr p15, 0, %0, c1, c0, 0\n"
-			/* invalidate I cache */
-			"mov %0, #0\n"
-			"mcr p15, 0, %0, c7, c5, 0\n"
-			/* clear and invalidate D cache */
-			"mov %0, #0\n"
-			"mcr p15, 0, %0, c7, c14, 0\n"
-			/* WFI */
-			"mov %0, #0\n"
-			"mcr p15, 0, %0, c7, c0, 4\n"
-			"nop\n" "nop\n" "nop\n" "nop\n"
-			"nop\n" "nop\n" "nop\n"
-			/* enable I and D cache */
-			"mrc p15, 0, %0, c1, c0, 0\n"
-			"orr %0, %0, #0x00001000\n"
-			"orr %0, %0, #0x00000004\n"
-			"mcr p15, 0, %0, c1, c0, 0\n"
-			: "=r" (reg));
-	} else if (cpu_is_mx51())
-		mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
-	else
-		cpu_do_idle();
+	cpu_do_idle();
 }
 
 void arch_reset(char mode, const char *cmd);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/uncompress.h linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/uncompress.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/include/mach/uncompress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/include/mach/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -98,6 +98,7 @@
 	case MACH_TYPE_PCM043:
 	case MACH_TYPE_LILLY1131:
 	case MACH_TYPE_VPR200:
+	case MACH_TYPE_EUKREA_CPUIMX35SD:
 		uart_base = MX3X_UART1_BASE_ADDR;
 		break;
 	case MACH_TYPE_MAGX_ZN5:
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/irq-common.c linux-libre-3.2-gnu/arch/arm/plat-mxc/irq-common.c
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/irq-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/irq-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,17 +23,17 @@
 
 int imx_irq_set_priority(unsigned char irq, unsigned char prio)
 {
-	struct mxc_irq_chip *chip;
-	struct irq_chip *base;
+	struct irq_chip_generic *gc;
+	struct mxc_extra_irq *exirq;
 	int ret;
 
 	ret = -ENOSYS;
 
-	base = irq_get_chip(irq);
-	if (base) {
-		chip = container_of(base, struct mxc_irq_chip, base);
-		if (chip->set_priority)
-			ret = chip->set_priority(irq, prio);
+	gc = irq_get_chip_data(irq);
+	if (gc && gc->private) {
+		exirq = gc->private;
+		if (exirq->set_priority)
+			ret = exirq->set_priority(irq, prio);
 	}
 
 	return ret;
@@ -43,15 +43,16 @@
 int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
 {
 	struct irq_chip_generic *gc;
-	int (*set_irq_fiq)(unsigned int, unsigned int);
+	struct mxc_extra_irq *exirq;
 	int ret;
 
 	ret = -ENOSYS;
 
 	gc = irq_get_chip_data(irq);
 	if (gc && gc->private) {
-		set_irq_fiq = gc->private;
-		ret = set_irq_fiq(irq, type);
+		exirq = gc->private;
+		if (exirq->set_irq_fiq)
+			ret = exirq->set_irq_fiq(irq, type);
 	}
 
 	return ret;
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/irq-common.h linux-libre-3.2-gnu/arch/arm/plat-mxc/irq-common.h
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/irq-common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/irq-common.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,9 +19,8 @@
 #ifndef __PLAT_MXC_IRQ_COMMON_H__
 #define __PLAT_MXC_IRQ_COMMON_H__
 
-struct mxc_irq_chip
+struct mxc_extra_irq
 {
-	struct irq_chip	base;
 	int (*set_priority)(unsigned char irq, unsigned char prio);
 	int (*set_irq_fiq)(unsigned int irq, unsigned int type);
 };
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/Kconfig linux-libre-3.2-gnu/arch/arm/plat-mxc/Kconfig
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -4,50 +4,34 @@
 
 menu "Freescale MXC Implementations"
 
-config ARCH_MX50_SUPPORTED
-	bool
-
-config ARCH_MX53_SUPPORTED
-	bool
-
 choice
 	prompt "Freescale CPU family:"
-	default ARCH_MX3
-
-config ARCH_MX1
-	bool "MX1-based"
-	help
-	  This enables support for systems based on the Freescale i.MX1 family
-
-config ARCH_MX2
-	bool "MX2-based"
-	help
-	  This enables support for systems based on the Freescale i.MX2 family
+	default ARCH_IMX_V6_V7
 
-config ARCH_MX25
-	bool "MX25-based"
+config ARCH_IMX_V4_V5
+	bool "i.MX1, i.MX21, i.MX25, i.MX27"
+	select AUTO_ZRELADDR if !ZBOOT_ROM
+	select ARM_PATCH_PHYS_VIRT
 	help
-	  This enables support for systems based on the Freescale i.MX25 family
+	  This enables support for systems based on the Freescale i.MX ARMv4
+	  and ARMv5 SoCs
 
-config ARCH_MX3
-	bool "MX3-based"
+config ARCH_IMX_V6_V7
+	bool "i.MX3, i.MX6"
+	select AUTO_ZRELADDR if !ZBOOT_ROM
+	select ARM_PATCH_PHYS_VIRT
 	help
-	  This enables support for systems based on the Freescale i.MX3 family
+	  This enables support for systems based on the Freescale i.MX3 and i.MX6
+	  family.
 
-config ARCH_MX503
-	bool "i.MX50 + i.MX53"
-	select ARCH_MX50_SUPPORTED
-	select ARCH_MX53_SUPPORTED
+config ARCH_MX5
+	bool "i.MX50, i.MX51, i.MX53"
+	select AUTO_ZRELADDR if !ZBOOT_ROM
+	select ARM_PATCH_PHYS_VIRT
 	help
-	  This enables support for machines using Freescale's i.MX50 and i.MX51
+	  This enables support for machines using Freescale's i.MX50 and i.MX53
 	  processors.
 
-config ARCH_MX51
-	bool "i.MX51"
-	select ARCH_MX51_SUPPORTED
-	help
-	  This enables support for systems based on the Freescale i.MX51 family
-
 endchoice
 
 source "arch/arm/mach-imx/Kconfig"
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/Makefile linux-libre-3.2-gnu/arch/arm/plat-mxc/Makefile
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
 # Common support
 obj-y := clock.o time.o devices.o cpu.o system.o irq-common.o
 
-# MX51 uses the TZIC interrupt controller, older platforms use AVIC
+obj-$(CONFIG_ARM_GIC) += gic.o
 obj-$(CONFIG_MXC_TZIC) += tzic.o
 obj-$(CONFIG_MXC_AVIC) += avic.o
 
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/pwm.c linux-libre-3.2-gnu/arch/arm/plat-mxc/pwm.c
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/pwm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/pwm.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,9 @@
 #define MX3_PWMSAR                0x0C    /* PWM Sample Register */
 #define MX3_PWMPR                 0x10    /* PWM Period Register */
 #define MX3_PWMCR_PRESCALER(x)    (((x - 1) & 0xFFF) << 4)
+#define MX3_PWMCR_DOZEEN                (1 << 24)
+#define MX3_PWMCR_WAITEN                (1 << 23)
+#define MX3_PWMCR_DBGEN			(1 << 22)
 #define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16)
 #define MX3_PWMCR_CLKSRC_IPG      (1 << 16)
 #define MX3_PWMCR_EN              (1 << 0)
@@ -57,7 +60,7 @@
 	if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
 		return -EINVAL;
 
-	if (cpu_is_mx27() || cpu_is_mx3() || cpu_is_mx25() || cpu_is_mx51()) {
+	if (!(cpu_is_mx1() || cpu_is_mx21())) {
 		unsigned long long c;
 		unsigned long period_cycles, duty_cycles, prescale;
 		u32 cr;
@@ -74,10 +77,21 @@
 		do_div(c, period_ns);
 		duty_cycles = c;
 
+		/*
+		 * according to imx pwm RM, the real period value should be
+		 * PERIOD value in PWMPR plus 2.
+		 */
+		if (period_cycles > 2)
+			period_cycles -= 2;
+		else
+			period_cycles = 0;
+
 		writel(duty_cycles, pwm->mmio_base + MX3_PWMSAR);
 		writel(period_cycles, pwm->mmio_base + MX3_PWMPR);
 
-		cr = MX3_PWMCR_PRESCALER(prescale) | MX3_PWMCR_EN;
+		cr = MX3_PWMCR_PRESCALER(prescale) |
+			MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN |
+			MX3_PWMCR_DBGEN | MX3_PWMCR_EN;
 
 		if (cpu_is_mx25())
 			cr |= MX3_PWMCR_CLKSRC_IPG;
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/system.c linux-libre-3.2-gnu/arch/arm/plat-mxc/system.c
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/system.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/system.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 
 #include <mach/hardware.h>
 #include <mach/common.h>
@@ -28,6 +29,9 @@
 #include <asm/system.h>
 #include <asm/mach-types.h>
 
+void __iomem *(*imx_ioremap)(unsigned long, size_t, unsigned int) = NULL;
+EXPORT_SYMBOL_GPL(imx_ioremap);
+
 static void __iomem *wdog_base;
 
 /*
diff -druN linux-libre-3.1-gnu/arch/arm/plat-mxc/tzic.c linux-libre-3.2-gnu/arch/arm/plat-mxc/tzic.c
--- linux-libre-3.1-gnu/arch/arm/plat-mxc/tzic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-mxc/tzic.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 
 #include <asm/mach/irq.h>
+#include <asm/exception.h>
 
 #include <mach/hardware.h>
 #include <mach/common.h>
@@ -42,7 +43,7 @@
 #define TZIC_SRCCLAR0	0x0280	/* Source Clear Register 0 */
 #define TZIC_PRIORITY0	0x0400	/* Priority Register 0 */
 #define TZIC_PND0	0x0D00	/* Pending Register 0 */
-#define TZIC_HIPND0	0x0D80	/* High Priority Pending Register */
+#define TZIC_HIPND(i)	(0x0D80+ ((i) << 2))	/* High Priority Pending Register */
 #define TZIC_WAKEUP0(i)	(0x0E00 + ((i) << 2))	/* Wakeup Config Register */
 #define TZIC_SWINT	0x0F00	/* Software Interrupt Rigger Register */
 #define TZIC_ID0	0x0FD0	/* Indentification Register 0 */
@@ -74,6 +75,12 @@
 
 static unsigned int *wakeup_intr[4];
 
+static struct mxc_extra_irq tzic_extra_irq = {
+#ifdef CONFIG_FIQ
+	.set_irq_fiq = tzic_set_irq_fiq,
+#endif
+};
+
 static __init void tzic_init_gc(unsigned int irq_start)
 {
 	struct irq_chip_generic *gc;
@@ -82,7 +89,7 @@
 
 	gc = irq_alloc_generic_chip("tzic", 1, irq_start, tzic_base,
 				    handle_level_irq);
-	gc->private = tzic_set_irq_fiq;
+	gc->private = &tzic_extra_irq;
 	gc->wake_enabled = IRQ_MSK(32);
 	wakeup_intr[idx] = &gc->wake_active;
 
@@ -96,6 +103,28 @@
 	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
 }
 
+asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
+{
+	u32 stat;
+	int i, irqofs, handled;
+
+	do {
+		handled = 0;
+
+		for (i = 0; i < 4; i++) {
+			stat = __raw_readl(tzic_base + TZIC_HIPND(i)) &
+				__raw_readl(tzic_base + TZIC_INTSEC0(i));
+
+			while (stat) {
+				handled = 1;
+				irqofs = fls(stat) - 1;
+				handle_IRQ(irqofs + i * 32, regs);
+				stat &= ~(1 << irqofs);
+			}
+		}
+	} while (handled);
+}
+
 /*
  * This function initializes the TZIC hardware and disables all the
  * interrupts. It registers the interrupt enable and disable functions
diff -druN linux-libre-3.1-gnu/arch/arm/plat-nomadik/include/plat/gpio.h linux-libre-3.2-gnu/arch/arm/plat-nomadik/include/plat/gpio.h
--- linux-libre-3.1-gnu/arch/arm/plat-nomadik/include/plat/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-nomadik/include/plat/gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,96 +0,0 @@
-/*
- * Structures and registers for GPIO access in the Nomadik SoC
- *
- * Copyright (C) 2008 STMicroelectronics
- *     Author: Prafulla WADASKAR <prafulla.wadaskar@st.com>
- * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef __ASM_PLAT_GPIO_H
-#define __ASM_PLAT_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-/*
- * These currently cause a function call to happen, they may be optimized
- * if needed by adding cpu-specific defines to identify blocks
- * (see mach-pxa/include/mach/gpio.h as an example using GPLR etc)
- */
-#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
-
-/*
- * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
- * the "gpio" namespace for generic and cross-machine functions
- */
-
-/* Register in the logic block */
-#define NMK_GPIO_DAT	0x00
-#define NMK_GPIO_DATS	0x04
-#define NMK_GPIO_DATC	0x08
-#define NMK_GPIO_PDIS	0x0c
-#define NMK_GPIO_DIR	0x10
-#define NMK_GPIO_DIRS	0x14
-#define NMK_GPIO_DIRC	0x18
-#define NMK_GPIO_SLPC	0x1c
-#define NMK_GPIO_AFSLA	0x20
-#define NMK_GPIO_AFSLB	0x24
-
-#define NMK_GPIO_RIMSC	0x40
-#define NMK_GPIO_FIMSC	0x44
-#define NMK_GPIO_IS	0x48
-#define NMK_GPIO_IC	0x4c
-#define NMK_GPIO_RWIMSC	0x50
-#define NMK_GPIO_FWIMSC	0x54
-#define NMK_GPIO_WKS	0x58
-
-/* Alternate functions: function C is set in hw by setting both A and B */
-#define NMK_GPIO_ALT_GPIO	0
-#define NMK_GPIO_ALT_A	1
-#define NMK_GPIO_ALT_B	2
-#define NMK_GPIO_ALT_C	(NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
-
-/* Pull up/down values */
-enum nmk_gpio_pull {
-	NMK_GPIO_PULL_NONE,
-	NMK_GPIO_PULL_UP,
-	NMK_GPIO_PULL_DOWN,
-};
-
-/* Sleep mode */
-enum nmk_gpio_slpm {
-	NMK_GPIO_SLPM_INPUT,
-	NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
-	NMK_GPIO_SLPM_NOCHANGE,
-	NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
-};
-
-extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
-extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
-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);
-
-extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
-
-/*
- * Platform data to register a block: only the initial gpio/irq number.
- */
-struct nmk_gpio_platform_data {
-	char *name;
-	int first_gpio;
-	int first_irq;
-	int num_gpio;
-	u32 (*get_secondary_status)(unsigned int bank);
-	void (*set_ioforce)(bool enable);
-	bool supports_sleepmode;
-};
-
-#endif /* __ASM_PLAT_GPIO_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h linux-libre-3.2-gnu/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
--- linux-libre-3.1-gnu/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,88 @@
+/*
+ * Structures and registers for GPIO access in the Nomadik SoC
+ *
+ * Copyright (C) 2008 STMicroelectronics
+ *     Author: Prafulla WADASKAR <prafulla.wadaskar@st.com>
+ * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PLAT_NOMADIK_GPIO
+#define __PLAT_NOMADIK_GPIO
+
+/*
+ * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
+ * the "gpio" namespace for generic and cross-machine functions
+ */
+
+/* Register in the logic block */
+#define NMK_GPIO_DAT	0x00
+#define NMK_GPIO_DATS	0x04
+#define NMK_GPIO_DATC	0x08
+#define NMK_GPIO_PDIS	0x0c
+#define NMK_GPIO_DIR	0x10
+#define NMK_GPIO_DIRS	0x14
+#define NMK_GPIO_DIRC	0x18
+#define NMK_GPIO_SLPC	0x1c
+#define NMK_GPIO_AFSLA	0x20
+#define NMK_GPIO_AFSLB	0x24
+
+#define NMK_GPIO_RIMSC	0x40
+#define NMK_GPIO_FIMSC	0x44
+#define NMK_GPIO_IS	0x48
+#define NMK_GPIO_IC	0x4c
+#define NMK_GPIO_RWIMSC	0x50
+#define NMK_GPIO_FWIMSC	0x54
+#define NMK_GPIO_WKS	0x58
+
+/* Alternate functions: function C is set in hw by setting both A and B */
+#define NMK_GPIO_ALT_GPIO	0
+#define NMK_GPIO_ALT_A	1
+#define NMK_GPIO_ALT_B	2
+#define NMK_GPIO_ALT_C	(NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
+
+/* Pull up/down values */
+enum nmk_gpio_pull {
+	NMK_GPIO_PULL_NONE,
+	NMK_GPIO_PULL_UP,
+	NMK_GPIO_PULL_DOWN,
+};
+
+/* Sleep mode */
+enum nmk_gpio_slpm {
+	NMK_GPIO_SLPM_INPUT,
+	NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
+	NMK_GPIO_SLPM_NOCHANGE,
+	NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
+};
+
+extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
+extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
+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);
+
+extern void nmk_gpio_clocks_enable(void);
+extern void nmk_gpio_clocks_disable(void);
+
+extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
+
+/*
+ * Platform data to register a block: only the initial gpio/irq number.
+ */
+struct nmk_gpio_platform_data {
+	char *name;
+	int first_gpio;
+	int first_irq;
+	int num_gpio;
+	u32 (*get_secondary_status)(unsigned int bank);
+	void (*set_ioforce)(bool enable);
+	bool supports_sleepmode;
+};
+
+#endif /* __PLAT_NOMADIK_GPIO */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-nomadik/include/plat/mtu.h linux-libre-3.2-gnu/arch/arm/plat-nomadik/include/plat/mtu.h
--- linux-libre-3.1-gnu/arch/arm/plat-nomadik/include/plat/mtu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-nomadik/include/plat/mtu.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,54 +1,11 @@
 #ifndef __PLAT_MTU_H
 #define __PLAT_MTU_H
 
-/*
- * Guaranteed runtime conversion range in seconds for
- * the clocksource and clockevent.
- */
-#define MTU_MIN_RANGE 4
-
 /* should be set by the platform code */
 extern void __iomem *mtu_base;
 
-/*
- * The MTU device hosts four different counters, with 4 set of
- * registers. These are register names.
- */
-
-#define MTU_IMSC	0x00	/* Interrupt mask set/clear */
-#define MTU_RIS		0x04	/* Raw interrupt status */
-#define MTU_MIS		0x08	/* Masked interrupt status */
-#define MTU_ICR		0x0C	/* Interrupt clear register */
-
-/* per-timer registers take 0..3 as argument */
-#define MTU_LR(x)	(0x10 + 0x10 * (x) + 0x00)	/* Load value */
-#define MTU_VAL(x)	(0x10 + 0x10 * (x) + 0x04)	/* Current value */
-#define MTU_CR(x)	(0x10 + 0x10 * (x) + 0x08)	/* Control reg */
-#define MTU_BGLR(x)	(0x10 + 0x10 * (x) + 0x0c)	/* At next overflow */
-
-/* bits for the control register */
-#define MTU_CRn_ENA		0x80
-#define MTU_CRn_PERIODIC	0x40	/* if 0 = free-running */
-#define MTU_CRn_PRESCALE_MASK	0x0c
-#define MTU_CRn_PRESCALE_1		0x00
-#define MTU_CRn_PRESCALE_16		0x04
-#define MTU_CRn_PRESCALE_256		0x08
-#define MTU_CRn_32BITS		0x02
-#define MTU_CRn_ONESHOT		0x01	/* if 0 = wraps reloading from BGLR*/
-
-/* Other registers are usual amba/primecell registers, currently not used */
-#define MTU_ITCR	0xff0
-#define MTU_ITOP	0xff4
-
-#define MTU_PERIPH_ID0	0xfe0
-#define MTU_PERIPH_ID1	0xfe4
-#define MTU_PERIPH_ID2	0xfe8
-#define MTU_PERIPH_ID3	0xfeC
-
-#define MTU_PCELL0	0xff0
-#define MTU_PCELL1	0xff4
-#define MTU_PCELL2	0xff8
-#define MTU_PCELL3	0xffC
+void nmdk_clkevt_reset(void);
+void nmdk_clksrc_reset(void);
 
 #endif /* __PLAT_MTU_H */
 
diff -druN linux-libre-3.1-gnu/arch/arm/plat-nomadik/include/plat/pincfg.h linux-libre-3.2-gnu/arch/arm/plat-nomadik/include/plat/pincfg.h
--- linux-libre-3.1-gnu/arch/arm/plat-nomadik/include/plat/pincfg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-nomadik/include/plat/pincfg.h	2012-01-04 18:55:44.000000000 -0500
@@ -37,7 +37,6 @@
  *		     SLPM value = same as normal
  *
  * PIN_CFG	   - default config with alternate function
- * PIN_CFG_PULL	   - default config with alternate function and pull up/down
  */
 
 typedef unsigned long pin_cfg_t;
@@ -133,10 +132,6 @@
 	(PIN_CFG_DEFAULT |\
 	 (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
 
-#define PIN_CFG_PULL(num, alt, pull)	\
-	((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\
-	 (PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull))
-
 extern int nmk_config_pin(pin_cfg_t cfg, bool sleep);
 extern int nmk_config_pins(pin_cfg_t *cfgs, int num);
 extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-nomadik/Kconfig linux-libre-3.2-gnu/arch/arm/plat-nomadik/Kconfig
--- linux-libre-3.1-gnu/arch/arm/plat-nomadik/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-nomadik/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -15,10 +15,16 @@
 
 config HAS_MTU
 	bool
-	select HAVE_SCHED_CLOCK
 	help
 	  Support for Multi Timer Unit. MTU provides access
 	  to multiple interrupt generating programmable
 	  32-bit free running decrementing counters.
 
+config NOMADIK_MTU_SCHED_CLOCK
+	bool
+	depends on HAS_MTU
+	select HAVE_SCHED_CLOCK
+	help
+	  Use the Multi Timer Unit as the sched_clock.
+
 endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-nomadik/timer.c linux-libre-3.2-gnu/arch/arm/plat-nomadik/timer.c
--- linux-libre-3.1-gnu/arch/arm/plat-nomadik/timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-nomadik/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,10 +21,59 @@
 #include <asm/mach/time.h>
 #include <asm/sched_clock.h>
 
-#include <plat/mtu.h>
+/*
+ * Guaranteed runtime conversion range in seconds for
+ * the clocksource and clockevent.
+ */
+#define MTU_MIN_RANGE 4
+
+/*
+ * The MTU device hosts four different counters, with 4 set of
+ * registers. These are register names.
+ */
+
+#define MTU_IMSC	0x00	/* Interrupt mask set/clear */
+#define MTU_RIS		0x04	/* Raw interrupt status */
+#define MTU_MIS		0x08	/* Masked interrupt status */
+#define MTU_ICR		0x0C	/* Interrupt clear register */
+
+/* per-timer registers take 0..3 as argument */
+#define MTU_LR(x)	(0x10 + 0x10 * (x) + 0x00)	/* Load value */
+#define MTU_VAL(x)	(0x10 + 0x10 * (x) + 0x04)	/* Current value */
+#define MTU_CR(x)	(0x10 + 0x10 * (x) + 0x08)	/* Control reg */
+#define MTU_BGLR(x)	(0x10 + 0x10 * (x) + 0x0c)	/* At next overflow */
+
+/* bits for the control register */
+#define MTU_CRn_ENA		0x80
+#define MTU_CRn_PERIODIC	0x40	/* if 0 = free-running */
+#define MTU_CRn_PRESCALE_MASK	0x0c
+#define MTU_CRn_PRESCALE_1		0x00
+#define MTU_CRn_PRESCALE_16		0x04
+#define MTU_CRn_PRESCALE_256		0x08
+#define MTU_CRn_32BITS		0x02
+#define MTU_CRn_ONESHOT		0x01	/* if 0 = wraps reloading from BGLR*/
+
+/* Other registers are usual amba/primecell registers, currently not used */
+#define MTU_ITCR	0xff0
+#define MTU_ITOP	0xff4
+
+#define MTU_PERIPH_ID0	0xfe0
+#define MTU_PERIPH_ID1	0xfe4
+#define MTU_PERIPH_ID2	0xfe8
+#define MTU_PERIPH_ID3	0xfeC
+
+#define MTU_PCELL0	0xff0
+#define MTU_PCELL1	0xff4
+#define MTU_PCELL2	0xff8
+#define MTU_PCELL3	0xffC
+
+static bool clkevt_periodic;
+static u32 clk_prescale;
+static u32 nmdk_cycle;		/* write-once */
 
 void __iomem *mtu_base; /* Assigned by machine code */
 
+#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
 /*
  * Override the global weak sched_clock symbol with this
  * local implementation which uses the clocksource to get some
@@ -48,32 +97,56 @@
 	u32 cyc = -readl(mtu_base + MTU_VAL(0));
 	update_sched_clock(&cd, cyc, (u32)~0);
 }
+#endif
 
 /* Clockevent device: use one-shot mode */
+static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev)
+{
+	writel(1 << 1, mtu_base + MTU_IMSC);
+	writel(evt, mtu_base + MTU_LR(1));
+	/* Load highest value, enable device, enable interrupts */
+	writel(MTU_CRn_ONESHOT | clk_prescale |
+	       MTU_CRn_32BITS | MTU_CRn_ENA,
+	       mtu_base + MTU_CR(1));
+
+	return 0;
+}
+
+void nmdk_clkevt_reset(void)
+{
+	if (clkevt_periodic) {
+
+		/* Timer: configure load and background-load, and fire it up */
+		writel(nmdk_cycle, mtu_base + MTU_LR(1));
+		writel(nmdk_cycle, mtu_base + MTU_BGLR(1));
+
+		writel(MTU_CRn_PERIODIC | clk_prescale |
+		       MTU_CRn_32BITS | MTU_CRn_ENA,
+		       mtu_base + MTU_CR(1));
+		writel(1 << 1, mtu_base + MTU_IMSC);
+	} else {
+		/* Generate an interrupt to start the clockevent again */
+		(void) nmdk_clkevt_next(nmdk_cycle, NULL);
+	}
+}
+
 static void nmdk_clkevt_mode(enum clock_event_mode mode,
 			     struct clock_event_device *dev)
 {
-	u32 cr;
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
-		pr_err("%s: periodic mode not supported\n", __func__);
+		clkevt_periodic = true;
+		nmdk_clkevt_reset();
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
-		/* Load highest value, enable device, enable interrupts */
-		cr = readl(mtu_base + MTU_CR(1));
-		writel(0, mtu_base + MTU_LR(1));
-		writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(1));
-		writel(1 << 1, mtu_base + MTU_IMSC);
+		clkevt_periodic = false;
 		break;
 	case CLOCK_EVT_MODE_SHUTDOWN:
 	case CLOCK_EVT_MODE_UNUSED:
-		/* disable irq */
 		writel(0, mtu_base + MTU_IMSC);
 		/* disable timer */
-		cr = readl(mtu_base + MTU_CR(1));
-		cr &= ~MTU_CRn_ENA;
-		writel(cr, mtu_base + MTU_CR(1));
+		writel(0, mtu_base + MTU_CR(1));
 		/* load some high default value */
 		writel(0xffffffff, mtu_base + MTU_LR(1));
 		break;
@@ -82,16 +155,9 @@
 	}
 }
 
-static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev)
-{
-	/* writing the value has immediate effect */
-	writel(evt, mtu_base + MTU_LR(1));
-	return 0;
-}
-
 static struct clock_event_device nmdk_clkevt = {
 	.name		= "mtu_1",
-	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.features	= CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
 	.rating		= 200,
 	.set_mode	= nmdk_clkevt_mode,
 	.set_next_event	= nmdk_clkevt_next,
@@ -116,11 +182,23 @@
 	.dev_id		= &nmdk_clkevt,
 };
 
+void nmdk_clksrc_reset(void)
+{
+	/* Disable */
+	writel(0, mtu_base + MTU_CR(0));
+
+	/* ClockSource: configure load and background-load, and fire it up */
+	writel(nmdk_cycle, mtu_base + MTU_LR(0));
+	writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
+
+	writel(clk_prescale | MTU_CRn_32BITS | MTU_CRn_ENA,
+	       mtu_base + MTU_CR(0));
+}
+
 void __init nmdk_timer_init(void)
 {
 	unsigned long rate;
 	struct clk *clk0;
-	u32 cr = MTU_CRn_32BITS;
 
 	clk0 = clk_get_sys("mtu0", NULL);
 	BUG_ON(IS_ERR(clk0));
@@ -138,30 +216,28 @@
 	rate = clk_get_rate(clk0);
 	if (rate > 32000000) {
 		rate /= 16;
-		cr |= MTU_CRn_PRESCALE_16;
+		clk_prescale = MTU_CRn_PRESCALE_16;
 	} else {
-		cr |= MTU_CRn_PRESCALE_1;
+		clk_prescale = MTU_CRn_PRESCALE_1;
 	}
 
+	nmdk_cycle = (rate + HZ/2) / HZ;
+
+
 	/* Timer 0 is the free running clocksource */
-	writel(cr, mtu_base + MTU_CR(0));
-	writel(0, mtu_base + MTU_LR(0));
-	writel(0, mtu_base + MTU_BGLR(0));
-	writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
+	nmdk_clksrc_reset();
 
 	if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0",
 			rate, 200, 32, clocksource_mmio_readl_down))
 		pr_err("timer: failed to initialize clock source %s\n",
 		       "mtu_0");
-
+#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
 	init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate);
-
+#endif
 	/* Timer 1 is used for events */
 
 	clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE);
 
-	writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */
-
 	nmdk_clkevt.max_delta_ns =
 		clockevent_delta2ns(0xffffffff, &nmdk_clkevt);
 	nmdk_clkevt.min_delta_ns =
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/clock.c linux-libre-3.2-gnu/arch/arm/plat-omap/clock.c
--- linux-libre-3.1-gnu/arch/arm/plat-omap/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/errno.h>
+#include <linux/export.h>
 #include <linux/err.h>
 #include <linux/string.h>
 #include <linux/clk.h>
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/debug-devices.c linux-libre-3.2-gnu/arch/arm/plat-omap/debug-devices.c
--- linux-libre-3.1-gnu/arch/arm/plat-omap/debug-devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/debug-devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  * 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/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -18,7 +18,6 @@
 #include <mach/hardware.h>
 
 #include <plat/board.h>
-#include <mach/gpio.h>
 
 
 /* Many OMAP development platforms reuse the same "debug board"; these
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/debug-leds.c linux-libre-3.2-gnu/arch/arm/plat-omap/debug-leds.c
--- linux-libre-3.1-gnu/arch/arm/plat-omap/debug-leds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/debug-leds.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
@@ -19,7 +19,6 @@
 #include <asm/mach-types.h>
 
 #include <plat/fpga.h>
-#include <mach/gpio.h>
 
 
 /* Many OMAP development platforms reuse the same "debug board"; these
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/devices.c linux-libre-3.2-gnu/arch/arm/plat-omap/devices.c
--- linux-libre-3.1-gnu/arch/arm/plat-omap/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -24,91 +24,9 @@
 #include <plat/tc.h>
 #include <plat/board.h>
 #include <plat/mmc.h>
-#include <mach/gpio.h>
 #include <plat/menelaus.h>
-#include <plat/mcbsp.h>
 #include <plat/omap44xx.h>
 
-/*-------------------------------------------------------------------------*/
-
-#if defined(CONFIG_OMAP_MCBSP) || defined(CONFIG_OMAP_MCBSP_MODULE)
-
-static struct platform_device **omap_mcbsp_devices;
-
-void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
-			struct omap_mcbsp_platform_data *config, int size)
-{
-	int i;
-
-	omap_mcbsp_devices = kzalloc(size * sizeof(struct platform_device *),
-				     GFP_KERNEL);
-	if (!omap_mcbsp_devices) {
-		printk(KERN_ERR "Could not register McBSP devices\n");
-		return;
-	}
-
-	for (i = 0; i < size; i++) {
-		struct platform_device *new_mcbsp;
-		int ret;
-
-		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) {
-			platform_device_put(new_mcbsp);
-			continue;
-		}
-		omap_mcbsp_devices[i] = new_mcbsp;
-	}
-}
-
-#else
-void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
-			struct omap_mcbsp_platform_data *config, int size)
-{  }
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \
-		defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE)
-
-static struct resource mcpdm_resources[] = {
-	{
-		.name		= "mcpdm_mem",
-		.start		= OMAP44XX_MCPDM_BASE,
-		.end		= OMAP44XX_MCPDM_BASE + SZ_4K,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.name		= "mcpdm_irq",
-		.start		= OMAP44XX_IRQ_MCPDM,
-		.end		= OMAP44XX_IRQ_MCPDM,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device omap_mcpdm_device = {
-	.name		= "omap-mcpdm",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(mcpdm_resources),
-	.resource	= mcpdm_resources,
-};
-
-static void omap_init_mcpdm(void)
-{
-	(void) platform_device_register(&omap_mcpdm_device);
-}
-#else
-static inline void omap_init_mcpdm(void) {}
-#endif
-
-/*-------------------------------------------------------------------------*/
-
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
 	defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
@@ -291,7 +209,6 @@
 	 * in alphabetical order so they're easier to sort through.
 	 */
 	omap_init_rng();
-	omap_init_mcpdm();
 	omap_init_uwire();
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/dmtimer.c linux-libre-3.2-gnu/arch/arm/plat-omap/dmtimer.c
--- linux-libre-3.1-gnu/arch/arm/plat-omap/dmtimer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/dmtimer.c	2012-01-04 18:55:44.000000000 -0500
@@ -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>
+ *
+ * dmtimer adaptation to platform_driver.
+ *
  * Copyright (C) 2005 Nokia Corporation
  * OMAP2 support by Juha Yrjola
  * API improvements and OMAP2 clock framework support by Timo Teras
@@ -29,168 +35,81 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/list.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
 #include <linux/module.h>
-#include <mach/hardware.h>
-#include <plat/dmtimer.h>
-#include <mach/irqs.h>
-
-static int dm_timer_count;
-
-#ifdef CONFIG_ARCH_OMAP1
-static struct omap_dm_timer omap1_dm_timers[] = {
-	{ .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
-	{ .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
-	{ .phys_base = 0xfffb2400, .irq = INT_1610_GPTIMER3 },
-	{ .phys_base = 0xfffb2c00, .irq = INT_1610_GPTIMER4 },
-	{ .phys_base = 0xfffb3400, .irq = INT_1610_GPTIMER5 },
-	{ .phys_base = 0xfffb3c00, .irq = INT_1610_GPTIMER6 },
-	{ .phys_base = 0xfffb7400, .irq = INT_1610_GPTIMER7 },
-	{ .phys_base = 0xfffbd400, .irq = INT_1610_GPTIMER8 },
-};
-
-static const int omap1_dm_timer_count = ARRAY_SIZE(omap1_dm_timers);
-
-#else
-#define omap1_dm_timers			NULL
-#define omap1_dm_timer_count		0
-#endif	/* CONFIG_ARCH_OMAP1 */
-
-#ifdef CONFIG_ARCH_OMAP2
-static struct omap_dm_timer omap2_dm_timers[] = {
-	{ .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
-	{ .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
-	{ .phys_base = 0x48078000, .irq = INT_24XX_GPTIMER3 },
-	{ .phys_base = 0x4807a000, .irq = INT_24XX_GPTIMER4 },
-	{ .phys_base = 0x4807c000, .irq = INT_24XX_GPTIMER5 },
-	{ .phys_base = 0x4807e000, .irq = INT_24XX_GPTIMER6 },
-	{ .phys_base = 0x48080000, .irq = INT_24XX_GPTIMER7 },
-	{ .phys_base = 0x48082000, .irq = INT_24XX_GPTIMER8 },
-	{ .phys_base = 0x48084000, .irq = INT_24XX_GPTIMER9 },
-	{ .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
-	{ .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
-	{ .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 },
-};
-
-static const char *omap2_dm_source_names[] __initdata = {
-	"sys_ck",
-	"func_32k_ck",
-	"alt_ck",
-	NULL
-};
-
-static struct clk *omap2_dm_source_clocks[3];
-static const int omap2_dm_timer_count = ARRAY_SIZE(omap2_dm_timers);
-
-#else
-#define omap2_dm_timers			NULL
-#define omap2_dm_timer_count		0
-#define omap2_dm_source_names		NULL
-#define omap2_dm_source_clocks		NULL
-#endif	/* CONFIG_ARCH_OMAP2 */
-
-#ifdef CONFIG_ARCH_OMAP3
-static struct omap_dm_timer omap3_dm_timers[] = {
-	{ .phys_base = 0x48318000, .irq = INT_24XX_GPTIMER1 },
-	{ .phys_base = 0x49032000, .irq = INT_24XX_GPTIMER2 },
-	{ .phys_base = 0x49034000, .irq = INT_24XX_GPTIMER3 },
-	{ .phys_base = 0x49036000, .irq = INT_24XX_GPTIMER4 },
-	{ .phys_base = 0x49038000, .irq = INT_24XX_GPTIMER5 },
-	{ .phys_base = 0x4903A000, .irq = INT_24XX_GPTIMER6 },
-	{ .phys_base = 0x4903C000, .irq = INT_24XX_GPTIMER7 },
-	{ .phys_base = 0x4903E000, .irq = INT_24XX_GPTIMER8 },
-	{ .phys_base = 0x49040000, .irq = INT_24XX_GPTIMER9 },
-	{ .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
-	{ .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
-	{ .phys_base = 0x48304000, .irq = INT_34XX_GPT12_IRQ },
-};
-
-static const char *omap3_dm_source_names[] __initdata = {
-	"sys_ck",
-	"omap_32k_fck",
-	NULL
-};
-
-static struct clk *omap3_dm_source_clocks[2];
-static const int omap3_dm_timer_count = ARRAY_SIZE(omap3_dm_timers);
-
-#else
-#define omap3_dm_timers			NULL
-#define omap3_dm_timer_count		0
-#define omap3_dm_source_names		NULL
-#define omap3_dm_source_clocks		NULL
-#endif	/* CONFIG_ARCH_OMAP3 */
-
-#ifdef CONFIG_ARCH_OMAP4
-static struct omap_dm_timer omap4_dm_timers[] = {
-	{ .phys_base = 0x4a318000, .irq = OMAP44XX_IRQ_GPT1 },
-	{ .phys_base = 0x48032000, .irq = OMAP44XX_IRQ_GPT2 },
-	{ .phys_base = 0x48034000, .irq = OMAP44XX_IRQ_GPT3 },
-	{ .phys_base = 0x48036000, .irq = OMAP44XX_IRQ_GPT4 },
-	{ .phys_base = 0x40138000, .irq = OMAP44XX_IRQ_GPT5 },
-	{ .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT6 },
-	{ .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT7 },
-	{ .phys_base = 0x4013e000, .irq = OMAP44XX_IRQ_GPT8 },
-	{ .phys_base = 0x4803e000, .irq = OMAP44XX_IRQ_GPT9 },
-	{ .phys_base = 0x48086000, .irq = OMAP44XX_IRQ_GPT10 },
-	{ .phys_base = 0x48088000, .irq = OMAP44XX_IRQ_GPT11 },
-	{ .phys_base = 0x4a320000, .irq = OMAP44XX_IRQ_GPT12 },
-};
-static const char *omap4_dm_source_names[] __initdata = {
-	"sys_clkin_ck",
-	"sys_32k_ck",
-	NULL
-};
-static struct clk *omap4_dm_source_clocks[2];
-static const int omap4_dm_timer_count = ARRAY_SIZE(omap4_dm_timers);
-
-#else
-#define omap4_dm_timers			NULL
-#define omap4_dm_timer_count		0
-#define omap4_dm_source_names		NULL
-#define omap4_dm_source_clocks		NULL
-#endif	/* CONFIG_ARCH_OMAP4 */
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
 
-static struct omap_dm_timer *dm_timers;
-static const char **dm_source_names;
-static struct clk **dm_source_clocks;
+#include <plat/dmtimer.h>
 
-static spinlock_t dm_timer_lock;
+static LIST_HEAD(omap_timer_list);
+static DEFINE_SPINLOCK(dm_timer_lock);
 
-/*
- * Reads timer registers in posted and non-posted mode. The posted mode bit
- * is encoded in reg. Note that in posted mode write pending bit must be
- * checked. Otherwise a read of a non completed write will produce an error.
+/**
+ * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
+ * @timer:      timer pointer over which read operation to perform
+ * @reg:        lowest byte holds the register offset
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode write
+ * pending bit must be checked. Otherwise a read of a non completed write
+ * will produce an error.
  */
 static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
 {
-	return __omap_dm_timer_read(timer->io_base, reg, timer->posted);
+	WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
+	return __omap_dm_timer_read(timer, reg, timer->posted);
 }
 
-/*
- * Writes timer registers in posted and non-posted mode. The posted mode bit
- * is encoded in reg. Note that in posted mode the write pending bit must be
- * checked. Otherwise a write on a register which has a pending write will be
- * lost.
+/**
+ * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
+ * @timer:      timer pointer over which write operation is to perform
+ * @reg:        lowest byte holds the register offset
+ * @value:      data to write into the register
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode the write
+ * pending bit must be checked. Otherwise a write on a register which has a
+ * pending write will be lost.
  */
 static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
 						u32 value)
 {
-	__omap_dm_timer_write(timer->io_base, reg, value, timer->posted);
+	WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
+	__omap_dm_timer_write(timer, reg, value, timer->posted);
+}
+
+static void omap_timer_restore_context(struct omap_dm_timer *timer)
+{
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_OFFSET,
+				timer->context.tiocp_cfg);
+	if (timer->revision > 1)
+		__raw_writel(timer->context.tistat, timer->sys_stat);
+
+	__raw_writel(timer->context.tisr, timer->irq_stat);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
+				timer->context.twer);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
+				timer->context.tcrr);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
+				timer->context.tldr);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
+				timer->context.tmar);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
+				timer->context.tsicr);
+	__raw_writel(timer->context.tier, timer->irq_ena);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG,
+				timer->context.tclr);
 }
 
 static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
 {
 	int c;
 
+	if (!timer->sys_stat)
+		return;
+
 	c = 0;
-	while (!(omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) {
+	while (!(__raw_readl(timer->sys_stat) & 1)) {
 		c++;
 		if (c > 100000) {
 			printk(KERN_ERR "Timer failed to reset\n");
@@ -201,53 +120,65 @@
 
 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
 {
-	int autoidle = 0, wakeup = 0;
-
-	if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
+	omap_dm_timer_enable(timer);
+	if (timer->pdev->id != 1) {
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
 		omap_dm_timer_wait_for_reset(timer);
 	}
-	omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
-
-	/* Enable autoidle on OMAP2+ */
-	if (cpu_class_is_omap2())
-		autoidle = 1;
 
-	/*
-	 * Enable wake-up on OMAP2 CPUs.
-	 */
-	if (cpu_class_is_omap2())
-		wakeup = 1;
-
-	__omap_dm_timer_reset(timer->io_base, autoidle, wakeup);
+	__omap_dm_timer_reset(timer, 0, 0);
+	omap_dm_timer_disable(timer);
 	timer->posted = 1;
 }
 
-void omap_dm_timer_prepare(struct omap_dm_timer *timer)
+int omap_dm_timer_prepare(struct omap_dm_timer *timer)
 {
-	omap_dm_timer_enable(timer);
-	omap_dm_timer_reset(timer);
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+	int ret;
+
+	timer->fclk = clk_get(&timer->pdev->dev, "fck");
+	if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
+		timer->fclk = NULL;
+		dev_err(&timer->pdev->dev, ": No fclk handle.\n");
+		return -EINVAL;
+	}
+
+	if (pdata->needs_manual_reset)
+		omap_dm_timer_reset(timer);
+
+	ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
+
+	timer->posted = 1;
+	return ret;
 }
 
 struct omap_dm_timer *omap_dm_timer_request(void)
 {
-	struct omap_dm_timer *timer = NULL;
+	struct omap_dm_timer *timer = NULL, *t;
 	unsigned long flags;
-	int i;
+	int ret = 0;
 
 	spin_lock_irqsave(&dm_timer_lock, flags);
-	for (i = 0; i < dm_timer_count; i++) {
-		if (dm_timers[i].reserved)
+	list_for_each_entry(t, &omap_timer_list, node) {
+		if (t->reserved)
 			continue;
 
-		timer = &dm_timers[i];
+		timer = t;
 		timer->reserved = 1;
 		break;
 	}
+
+	if (timer) {
+		ret = omap_dm_timer_prepare(timer);
+		if (ret) {
+			timer->reserved = 0;
+			timer = NULL;
+		}
+	}
 	spin_unlock_irqrestore(&dm_timer_lock, flags);
 
-	if (timer != NULL)
-		omap_dm_timer_prepare(timer);
+	if (!timer)
+		pr_debug("%s: timer request failed!\n", __func__);
 
 	return timer;
 }
@@ -255,74 +186,65 @@
 
 struct omap_dm_timer *omap_dm_timer_request_specific(int id)
 {
-	struct omap_dm_timer *timer;
+	struct omap_dm_timer *timer = NULL, *t;
 	unsigned long flags;
+	int ret = 0;
 
 	spin_lock_irqsave(&dm_timer_lock, flags);
-	if (id <= 0 || id > dm_timer_count || dm_timers[id-1].reserved) {
-		spin_unlock_irqrestore(&dm_timer_lock, flags);
-		printk("BUG: warning at %s:%d/%s(): unable to get timer %d\n",
-		       __FILE__, __LINE__, __func__, id);
-		dump_stack();
-		return NULL;
+	list_for_each_entry(t, &omap_timer_list, node) {
+		if (t->pdev->id == id && !t->reserved) {
+			timer = t;
+			timer->reserved = 1;
+			break;
+		}
 	}
 
-	timer = &dm_timers[id-1];
-	timer->reserved = 1;
+	if (timer) {
+		ret = omap_dm_timer_prepare(timer);
+		if (ret) {
+			timer->reserved = 0;
+			timer = NULL;
+		}
+	}
 	spin_unlock_irqrestore(&dm_timer_lock, flags);
 
-	omap_dm_timer_prepare(timer);
+	if (!timer)
+		pr_debug("%s: timer%d request failed!\n", __func__, id);
 
 	return timer;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
 
-void omap_dm_timer_free(struct omap_dm_timer *timer)
+int omap_dm_timer_free(struct omap_dm_timer *timer)
 {
-	omap_dm_timer_enable(timer);
-	omap_dm_timer_reset(timer);
-	omap_dm_timer_disable(timer);
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	clk_put(timer->fclk);
 
 	WARN_ON(!timer->reserved);
 	timer->reserved = 0;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_free);
 
 void omap_dm_timer_enable(struct omap_dm_timer *timer)
 {
-	if (timer->enabled)
-		return;
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-	if (cpu_class_is_omap2()) {
-		clk_enable(timer->fclk);
-		clk_enable(timer->iclk);
-	}
-#endif
-
-	timer->enabled = 1;
+	pm_runtime_get_sync(&timer->pdev->dev);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
 
 void omap_dm_timer_disable(struct omap_dm_timer *timer)
 {
-	if (!timer->enabled)
-		return;
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-	if (cpu_class_is_omap2()) {
-		clk_disable(timer->iclk);
-		clk_disable(timer->fclk);
-	}
-#endif
-
-	timer->enabled = 0;
+	pm_runtime_put(&timer->pdev->dev);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
 
 int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
 {
-	return timer->irq;
+	if (timer)
+		return timer->irq;
+	return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
 
@@ -334,24 +256,29 @@
  */
 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 {
-	int i;
+	int i = 0;
+	struct omap_dm_timer *timer = NULL;
+	unsigned long flags;
 
 	/* If ARMXOR cannot be idled this function call is unnecessary */
 	if (!(inputmask & (1 << 1)))
 		return inputmask;
 
 	/* If any active timer is using ARMXOR return modified mask */
-	for (i = 0; i < dm_timer_count; i++) {
+	spin_lock_irqsave(&dm_timer_lock, flags);
+	list_for_each_entry(timer, &omap_timer_list, node) {
 		u32 l;
 
-		l = omap_dm_timer_read_reg(&dm_timers[i], OMAP_TIMER_CTRL_REG);
+		l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 		if (l & OMAP_TIMER_CTRL_ST) {
 			if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
 				inputmask &= ~(1 << 1);
 			else
 				inputmask &= ~(1 << 2);
 		}
+		i++;
 	}
+	spin_unlock_irqrestore(&dm_timer_lock, flags);
 
 	return inputmask;
 }
@@ -361,7 +288,9 @@
 
 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
 {
-	return timer->fclk;
+	if (timer)
+		return timer->fclk;
+	return NULL;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
 
@@ -375,70 +304,91 @@
 
 #endif
 
-void omap_dm_timer_trigger(struct omap_dm_timer *timer)
+int omap_dm_timer_trigger(struct omap_dm_timer *timer)
 {
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+		pr_err("%s: timer not available or enabled.\n", __func__);
+		return -EINVAL;
+	}
+
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
 
-void omap_dm_timer_start(struct omap_dm_timer *timer)
+int omap_dm_timer_start(struct omap_dm_timer *timer)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
+
+	if (timer->loses_context) {
+		u32 ctx_loss_cnt_after =
+			timer->get_context_loss_count(&timer->pdev->dev);
+		if (ctx_loss_cnt_after != timer->ctx_loss_count)
+			omap_timer_restore_context(timer);
+	}
+
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	if (!(l & OMAP_TIMER_CTRL_ST)) {
 		l |= OMAP_TIMER_CTRL_ST;
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 	}
+
+	/* Save the context */
+	timer->context.tclr = l;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_start);
 
-void omap_dm_timer_stop(struct omap_dm_timer *timer)
+int omap_dm_timer_stop(struct omap_dm_timer *timer)
 {
 	unsigned long rate = 0;
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
 
-#ifdef CONFIG_ARCH_OMAP2PLUS
-	rate = clk_get_rate(timer->fclk);
-#endif
+	if (unlikely(!timer))
+		return -EINVAL;
 
-	__omap_dm_timer_stop(timer->io_base, timer->posted, rate);
+	if (!pdata->needs_manual_reset)
+		rate = clk_get_rate(timer->fclk);
+
+	__omap_dm_timer_stop(timer, timer->posted, rate);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
 
-#ifdef CONFIG_ARCH_OMAP1
-
 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 {
-	int n = (timer - dm_timers) << 1;
-	u32 l;
-
-	l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
-	l |= source << n;
-	omap_writel(l, MOD_CONF_CTRL_1);
+	int ret;
+	struct dmtimer_platform_data *pdata;
 
-	return 0;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
+	if (unlikely(!timer))
+		return -EINVAL;
 
-#else
+	pdata = timer->pdev->dev.platform_data;
 
-int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
-{
 	if (source < 0 || source >= 3)
 		return -EINVAL;
 
-	return __omap_dm_timer_set_source(timer->fclk,
-						dm_source_clocks[source]);
+	ret = pdata->set_timer_src(timer->pdev, source);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
 
-#endif
-
-void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
+int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
 			    unsigned int load)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	if (autoreload)
 		l |= OMAP_TIMER_CTRL_AR;
@@ -448,15 +398,32 @@
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
 
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+	/* Save the context */
+	timer->context.tclr = l;
+	timer->context.tldr = load;
+	omap_dm_timer_disable(timer);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
 
 /* Optimized set_load which removes costly spin wait in timer_start */
-void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
+int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
                             unsigned int load)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
+
+	if (timer->loses_context) {
+		u32 ctx_loss_cnt_after =
+			timer->get_context_loss_count(&timer->pdev->dev);
+		if (ctx_loss_cnt_after != timer->ctx_loss_count)
+			omap_timer_restore_context(timer);
+	}
+
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	if (autoreload) {
 		l |= OMAP_TIMER_CTRL_AR;
@@ -466,15 +433,25 @@
 	}
 	l |= OMAP_TIMER_CTRL_ST;
 
-	__omap_dm_timer_load_start(timer->io_base, l, load, timer->posted);
+	__omap_dm_timer_load_start(timer, l, load, timer->posted);
+
+	/* Save the context */
+	timer->context.tclr = l;
+	timer->context.tldr = load;
+	timer->context.tcrr = load;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
 
-void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
+int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
 			     unsigned int match)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	if (enable)
 		l |= OMAP_TIMER_CTRL_CE;
@@ -482,14 +459,24 @@
 		l &= ~OMAP_TIMER_CTRL_CE;
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
+
+	/* Save the context */
+	timer->context.tclr = l;
+	timer->context.tmar = match;
+	omap_dm_timer_disable(timer);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
 
-void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
+int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
 			   int toggle, int trigger)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
 	       OMAP_TIMER_CTRL_PT | (0x03 << 10));
@@ -499,13 +486,22 @@
 		l |= OMAP_TIMER_CTRL_PT;
 	l |= trigger << 10;
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+
+	/* Save the context */
+	timer->context.tclr = l;
+	omap_dm_timer_disable(timer);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
 
-void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
+int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
 	if (prescaler >= 0x00 && prescaler <= 0x07) {
@@ -513,13 +509,28 @@
 		l |= prescaler << 2;
 	}
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+
+	/* Save the context */
+	timer->context.tclr = l;
+	omap_dm_timer_disable(timer);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
 
-void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
+int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
 				  unsigned int value)
 {
-	__omap_dm_timer_int_enable(timer->io_base, value);
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
+	__omap_dm_timer_int_enable(timer, value);
+
+	/* Save the context */
+	timer->context.tier = value;
+	timer->context.twer = value;
+	omap_dm_timer_disable(timer);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
 
@@ -527,40 +538,61 @@
 {
 	unsigned int l;
 
-	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+		pr_err("%s: timer not available or enabled.\n", __func__);
+		return 0;
+	}
+
+	l = __raw_readl(timer->irq_stat);
 
 	return l;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
 
-void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
+int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
 {
-	__omap_dm_timer_write_status(timer->io_base, value);
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
+		return -EINVAL;
+
+	__omap_dm_timer_write_status(timer, value);
+	/* Save the context */
+	timer->context.tisr = value;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
 
 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
 {
-	return __omap_dm_timer_read_counter(timer->io_base, timer->posted);
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+		pr_err("%s: timer not iavailable or enabled.\n", __func__);
+		return 0;
+	}
+
+	return __omap_dm_timer_read_counter(timer, timer->posted);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
 
-void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
+int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
 {
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+		pr_err("%s: timer not available or enabled.\n", __func__);
+		return -EINVAL;
+	}
+
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
+
+	/* Save the context */
+	timer->context.tcrr = value;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
 
 int omap_dm_timers_active(void)
 {
-	int i;
-
-	for (i = 0; i < dm_timer_count; i++) {
-		struct omap_dm_timer *timer;
-
-		timer = &dm_timers[i];
+	struct omap_dm_timer *timer;
 
-		if (!timer->enabled)
+	list_for_each_entry(timer, &omap_timer_list, node) {
+		if (!timer->reserved)
 			continue;
 
 		if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
@@ -572,69 +604,147 @@
 }
 EXPORT_SYMBOL_GPL(omap_dm_timers_active);
 
-static int __init omap_dm_timer_init(void)
+/**
+ * omap_dm_timer_probe - probe function called for every registered device
+ * @pdev:	pointer to current timer platform device
+ *
+ * Called by driver framework at the end of device registration for all
+ * timer devices.
+ */
+static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
 {
+	int ret;
+	unsigned long flags;
 	struct omap_dm_timer *timer;
-	int i, map_size = SZ_8K;	/* Module 4KB + L4 4KB except on omap1 */
+	struct resource *mem, *irq, *ioarea;
+	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
 
-	if (!(cpu_is_omap16xx() || cpu_class_is_omap2()))
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
 		return -ENODEV;
+	}
 
-	spin_lock_init(&dm_timer_lock);
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (unlikely(!irq)) {
+		dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
+		return -ENODEV;
+	}
 
-	if (cpu_class_is_omap1()) {
-		dm_timers = omap1_dm_timers;
-		dm_timer_count = omap1_dm_timer_count;
-		map_size = SZ_2K;
-	} else if (cpu_is_omap24xx()) {
-		dm_timers = omap2_dm_timers;
-		dm_timer_count = omap2_dm_timer_count;
-		dm_source_names = omap2_dm_source_names;
-		dm_source_clocks = omap2_dm_source_clocks;
-	} else if (cpu_is_omap34xx()) {
-		dm_timers = omap3_dm_timers;
-		dm_timer_count = omap3_dm_timer_count;
-		dm_source_names = omap3_dm_source_names;
-		dm_source_clocks = omap3_dm_source_clocks;
-	} else if (cpu_is_omap44xx()) {
-		dm_timers = omap4_dm_timers;
-		dm_timer_count = omap4_dm_timer_count;
-		dm_source_names = omap4_dm_source_names;
-		dm_source_clocks = omap4_dm_source_clocks;
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(!mem)) {
+		dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
+		return -ENODEV;
 	}
 
-	if (cpu_class_is_omap2())
-		for (i = 0; dm_source_names[i] != NULL; i++)
-			dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]);
+	ioarea = request_mem_region(mem->start, resource_size(mem),
+			pdev->name);
+	if (!ioarea) {
+		dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
+		return -EBUSY;
+	}
 
-	if (cpu_is_omap243x())
-		dm_timers[0].phys_base = 0x49018000;
+	timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
+	if (!timer) {
+		dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
+			__func__);
+		ret = -ENOMEM;
+		goto err_free_ioregion;
+	}
 
-	for (i = 0; i < dm_timer_count; i++) {
-		timer = &dm_timers[i];
+	timer->io_base = ioremap(mem->start, resource_size(mem));
+	if (!timer->io_base) {
+		dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__);
+		ret = -ENOMEM;
+		goto err_free_mem;
+	}
 
-		/* Static mapping, never released */
-		timer->io_base = ioremap(timer->phys_base, map_size);
-		BUG_ON(!timer->io_base);
+	timer->id = pdev->id;
+	timer->irq = irq->start;
+	timer->reserved = pdata->reserved;
+	timer->pdev = pdev;
+	timer->loses_context = pdata->loses_context;
+	timer->get_context_loss_count = pdata->get_context_loss_count;
 
-#ifdef CONFIG_ARCH_OMAP2PLUS
-		if (cpu_class_is_omap2()) {
-			char clk_name[16];
-			sprintf(clk_name, "gpt%d_ick", i + 1);
-			timer->iclk = clk_get(NULL, clk_name);
-			sprintf(clk_name, "gpt%d_fck", i + 1);
-			timer->fclk = clk_get(NULL, clk_name);
-		}
+	/* Skip pm_runtime_enable for OMAP1 */
+	if (!pdata->needs_manual_reset) {
+		pm_runtime_enable(&pdev->dev);
+		pm_runtime_irq_safe(&pdev->dev);
+	}
 
-		/* One or two timers may be set up early for sys_timer */
-		if (sys_timer_reserved & (1  << i)) {
-			timer->reserved = 1;
-			timer->posted = 1;
-		}
-#endif
+	if (!timer->reserved) {
+		pm_runtime_get_sync(&pdev->dev);
+		__omap_dm_timer_init_regs(timer);
+		pm_runtime_put(&pdev->dev);
 	}
 
+	/* add the timer element to the list */
+	spin_lock_irqsave(&dm_timer_lock, flags);
+	list_add_tail(&timer->node, &omap_timer_list);
+	spin_unlock_irqrestore(&dm_timer_lock, flags);
+
+	dev_dbg(&pdev->dev, "Device Probed.\n");
+
 	return 0;
+
+err_free_mem:
+	kfree(timer);
+
+err_free_ioregion:
+	release_mem_region(mem->start, resource_size(mem));
+
+	return ret;
 }
 
-arch_initcall(omap_dm_timer_init);
+/**
+ * omap_dm_timer_remove - cleanup a registered timer device
+ * @pdev:	pointer to current timer platform device
+ *
+ * Called by driver framework whenever a timer device is unregistered.
+ * In addition to freeing platform resources it also deletes the timer
+ * entry from the local list.
+ */
+static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
+{
+	struct omap_dm_timer *timer;
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	spin_lock_irqsave(&dm_timer_lock, flags);
+	list_for_each_entry(timer, &omap_timer_list, node)
+		if (timer->pdev->id == pdev->id) {
+			list_del(&timer->node);
+			kfree(timer);
+			ret = 0;
+			break;
+		}
+	spin_unlock_irqrestore(&dm_timer_lock, flags);
+
+	return ret;
+}
+
+static struct platform_driver omap_dm_timer_driver = {
+	.probe  = omap_dm_timer_probe,
+	.remove = __devexit_p(omap_dm_timer_remove),
+	.driver = {
+		.name   = "omap_timer",
+	},
+};
+
+static int __init omap_dm_timer_driver_init(void)
+{
+	return platform_driver_register(&omap_dm_timer_driver);
+}
+
+static void __exit omap_dm_timer_driver_exit(void)
+{
+	platform_driver_unregister(&omap_dm_timer_driver);
+}
+
+early_platform_init("earlytimer", &omap_dm_timer_driver);
+module_init(omap_dm_timer_driver_init);
+module_exit(omap_dm_timer_driver_exit);
+
+MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/i2c.c linux-libre-3.2-gnu/arch/arm/plat-omap/i2c.c
--- linux-libre-3.1-gnu/arch/arm/plat-omap/i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -108,6 +108,22 @@
 	res[1].start = INT_I2C;
 	pdata = &i2c_pdata[bus_id - 1];
 
+	/* all OMAP1 have IP version 1 register set */
+	pdata->rev = OMAP_I2C_IP_VERSION_1;
+
+	/* all OMAP1 I2C are implemented like this */
+	pdata->flags = OMAP_I2C_FLAG_NO_FIFO |
+		       OMAP_I2C_FLAG_SIMPLE_CLOCK |
+		       OMAP_I2C_FLAG_16BIT_DATA_REG |
+		       OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK;
+
+	/* how the cpu bus is wired up differs for 7xx only */
+
+	if (cpu_is_omap7xx())
+		pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_1;
+	else
+		pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_2;
+
 	return platform_device_register(pdev);
 }
 
@@ -123,21 +139,14 @@
 	omap_pm_set_max_mpu_wakeup_lat(dev, t);
 }
 
-static struct omap_device_pm_latency omap_i2c_latency[] = {
-	[0] = {
-		.deactivate_func	= omap_device_idle_hwmods,
-		.activate_func		= omap_device_enable_hwmods,
-		.flags			= OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static inline int omap2_i2c_add_bus(int bus_id)
 {
 	int l;
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	char oh_name[MAX_OMAP_I2C_HWMOD_NAME_LEN];
 	struct omap_i2c_bus_platform_data *pdata;
+	struct omap_i2c_dev_attr *dev_attr;
 
 	omap2_i2c_mux_pins(bus_id);
 
@@ -152,6 +161,16 @@
 
 	pdata = &i2c_pdata[bus_id - 1];
 	/*
+	 * pass the hwmod class's CPU-specific knowledge of I2C IP revision in
+	 * use, and functionality implementation flags, up to the OMAP I2C
+	 * driver via platform data
+	 */
+	pdata->rev = oh->class->rev;
+
+	dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr;
+	pdata->flags = dev_attr->flags;
+
+	/*
 	 * When waiting for completion of a i2c transfer, we need to
 	 * set a wake up latency constraint for the MPU. This is to
 	 * ensure quick enough wakeup from idle, when transfer
@@ -160,12 +179,12 @@
 	 */
 	if (cpu_is_omap34xx())
 		pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
-	od = omap_device_build(name, bus_id, oh, pdata,
+	pdev = omap_device_build(name, bus_id, oh, pdata,
 			sizeof(struct omap_i2c_bus_platform_data),
-			omap_i2c_latency, ARRAY_SIZE(omap_i2c_latency), 0);
-	WARN(IS_ERR(od), "Could not build omap_device for %s\n", name);
+			NULL, 0, 0);
+	WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", name);
 
-	return PTR_ERR(od);
+	return PTR_RET(pdev);
 }
 #else
 static inline int omap2_i2c_add_bus(int bus_id)
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/clock.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/clock.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -80,8 +80,6 @@
  *
  * @div is the divisor that should be applied to the parent clock's rate
  * to produce the current clock's rate.
- *
- * XXX @flags probably should be replaced with an struct omap_chip.
  */
 struct clksel_rate {
 	u32			val;
@@ -167,8 +165,8 @@
 	u8			auto_recal_bit;
 	u8			recal_en_bit;
 	u8			recal_st_bit;
-	u8			flags;
 #  endif
+	u8			flags;
 };
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/common.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/common.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/common.h	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/delay.h>
 
 #include <plat/i2c.h>
+#include <plat/omap_hwmod.h>
 
 struct sys_timer;
 
@@ -45,6 +46,20 @@
 
 extern void omap_reserve(void);
 
+void omap2420_init_early(void);
+void omap2430_init_early(void);
+void omap3430_init_early(void);
+void omap35xx_init_early(void);
+void omap3630_init_early(void);
+void omap3_init_early(void);	/* Do not use this one */
+void am35xx_init_early(void);
+void ti816x_init_early(void);
+void omap4430_init_early(void);
+
+extern int omap_dss_reset(struct omap_hwmod *);
+
+void omap_sram_init(void);
+
 /*
  * IO bases for various OMAP processors
  * Except the tap base, rest all the io bases
@@ -53,13 +68,13 @@
 struct omap_globals {
 	u32		class;		/* OMAP class to detect */
 	void __iomem	*tap;		/* Control module ID code */
-	unsigned long   sdrc;           /* SDRAM Controller */
-	unsigned long   sms;            /* SDRAM Memory Scheduler */
-	unsigned long   ctrl;           /* System Control Module */
-	unsigned long   ctrl_pad;	/* PAD Control Module */
-	unsigned long   prm;            /* Power and Reset Management */
-	unsigned long   cm;             /* Clock Management */
-	unsigned long   cm2;
+	void __iomem	*sdrc;           /* SDRAM Controller */
+	void __iomem	*sms;            /* SDRAM Memory Scheduler */
+	void __iomem	*ctrl;           /* System Control Module */
+	void __iomem	*ctrl_pad;	/* PAD Control Module */
+	void __iomem	*prm;            /* Power and Reset Management */
+	void __iomem	*cm;             /* Clock Management */
+	void __iomem	*cm2;
 };
 
 void omap2_set_globals_242x(void);
@@ -74,7 +89,11 @@
 void omap2_set_globals_control(struct omap_globals *);
 void omap2_set_globals_prcm(struct omap_globals *);
 
+void omap242x_map_io(void);
+void omap243x_map_io(void);
 void omap3_map_io(void);
+void omap4_map_io(void);
+
 
 /**
  * omap_test_timeout - busy-loop, testing a condition
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/cpu.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/cpu.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/cpu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/cpu.h	2012-01-04 18:55:44.000000000 -0500
@@ -44,13 +44,6 @@
 
 int omap_type(void);
 
-struct omap_chip_id {
-	u16 oc;
-	u8 type;
-};
-
-#define OMAP_CHIP_INIT(x)	{ .oc = x }
-
 /*
  * omap_rev bits:
  * CPU id bits	(0730, 1510, 1710, 2422...)	[31:16]
@@ -60,19 +53,6 @@
 unsigned int omap_rev(void);
 
 /*
- * Define CPU revision bits
- *
- * Verbose meaning of the revision bits may be different for a silicon
- * family. This difference can be handled separately.
- */
-#define OMAP_REVBITS_00		0x00
-#define OMAP_REVBITS_01		0x01
-#define OMAP_REVBITS_02		0x02
-#define OMAP_REVBITS_03		0x03
-#define OMAP_REVBITS_04		0x04
-#define OMAP_REVBITS_05		0x05
-
-/*
  * Get the CPU revision for OMAP devices
  */
 #define GET_OMAP_REVISION()	((omap_rev() >> 8) & 0xff)
@@ -262,7 +242,7 @@
 IS_OMAP_TYPE(2423, 0x2423)
 IS_OMAP_TYPE(2430, 0x2430)
 IS_OMAP_TYPE(3430, 0x3430)
-IS_OMAP_TYPE(3505, 0x3505)
+IS_OMAP_TYPE(3505, 0x3517)
 IS_OMAP_TYPE(3517, 0x3517)
 
 #define cpu_is_omap310()		0
@@ -354,8 +334,9 @@
 						(!omap3_has_sgx()) &&	\
 						(omap3_has_iva()))
 # define cpu_is_omap3530()		(cpu_is_omap3430())
-# define cpu_is_omap3505()		is_omap3505()
 # define cpu_is_omap3517()		is_omap3517()
+# define cpu_is_omap3505()		(cpu_is_omap3517() &&		\
+						!omap3_has_sgx())
 # undef cpu_is_omap3630
 # define cpu_is_omap3630()		is_omap363x()
 # define cpu_is_ti816x()		is_ti816x()
@@ -379,35 +360,31 @@
 /* Various silicon revisions for omap2 */
 #define OMAP242X_CLASS		0x24200024
 #define OMAP2420_REV_ES1_0	OMAP242X_CLASS
-#define OMAP2420_REV_ES2_0	(OMAP242X_CLASS | (OMAP_REVBITS_01 << 8))
+#define OMAP2420_REV_ES2_0	(OMAP242X_CLASS | (0x1 << 8))
 
 #define OMAP243X_CLASS		0x24300024
 #define OMAP2430_REV_ES1_0	OMAP243X_CLASS
 
 #define OMAP343X_CLASS		0x34300034
 #define OMAP3430_REV_ES1_0	OMAP343X_CLASS
-#define OMAP3430_REV_ES2_0	(OMAP343X_CLASS | (OMAP_REVBITS_01 << 8))
-#define OMAP3430_REV_ES2_1	(OMAP343X_CLASS | (OMAP_REVBITS_02 << 8))
-#define OMAP3430_REV_ES3_0	(OMAP343X_CLASS | (OMAP_REVBITS_03 << 8))
-#define OMAP3430_REV_ES3_1	(OMAP343X_CLASS | (OMAP_REVBITS_04 << 8))
-#define OMAP3430_REV_ES3_1_2	(OMAP343X_CLASS | (OMAP_REVBITS_05 << 8))
+#define OMAP3430_REV_ES2_0	(OMAP343X_CLASS | (0x1 << 8))
+#define OMAP3430_REV_ES2_1	(OMAP343X_CLASS | (0x2 << 8))
+#define OMAP3430_REV_ES3_0	(OMAP343X_CLASS | (0x3 << 8))
+#define OMAP3430_REV_ES3_1	(OMAP343X_CLASS | (0x4 << 8))
+#define OMAP3430_REV_ES3_1_2	(OMAP343X_CLASS | (0x5 << 8))
 
 #define OMAP363X_CLASS		0x36300034
 #define OMAP3630_REV_ES1_0	OMAP363X_CLASS
-#define OMAP3630_REV_ES1_1	(OMAP363X_CLASS | (OMAP_REVBITS_01 << 8))
-#define OMAP3630_REV_ES1_2	(OMAP363X_CLASS | (OMAP_REVBITS_02 << 8))
+#define OMAP3630_REV_ES1_1	(OMAP363X_CLASS | (0x1 << 8))
+#define OMAP3630_REV_ES1_2	(OMAP363X_CLASS | (0x2 << 8))
 
-#define OMAP35XX_CLASS		0x35000034
-#define OMAP3503_REV(v)		(OMAP35XX_CLASS | (0x3503 << 16) | (v << 8))
-#define OMAP3515_REV(v)		(OMAP35XX_CLASS | (0x3515 << 16) | (v << 8))
-#define OMAP3525_REV(v)		(OMAP35XX_CLASS | (0x3525 << 16) | (v << 8))
-#define OMAP3530_REV(v)		(OMAP35XX_CLASS | (0x3530 << 16) | (v << 8))
-#define OMAP3505_REV(v)		(OMAP35XX_CLASS | (0x3505 << 16) | (v << 8))
-#define OMAP3517_REV(v)		(OMAP35XX_CLASS | (0x3517 << 16) | (v << 8))
+#define OMAP3517_CLASS		0x35170034
+#define OMAP3517_REV_ES1_0	OMAP3517_CLASS
+#define OMAP3517_REV_ES1_1	(OMAP3517_CLASS | (0x1 << 8))
 
 #define TI816X_CLASS		0x81600034
 #define TI8168_REV_ES1_0	TI816X_CLASS
-#define TI8168_REV_ES1_1	(TI816X_CLASS | (OMAP_REVBITS_01 << 8))
+#define TI8168_REV_ES1_1	(TI816X_CLASS | (0x1 << 8))
 
 #define OMAP443X_CLASS		0x44300044
 #define OMAP4430_REV_ES1_0	(OMAP443X_CLASS | (0x10 << 8))
@@ -418,65 +395,17 @@
 #define OMAP446X_CLASS		0x44600044
 #define OMAP4460_REV_ES1_0	(OMAP446X_CLASS | (0x10 << 8))
 
-/*
- * omap_chip bits
- *
- * CHIP_IS_OMAP{2420,2430,3430} indicate that a particular structure is
- * valid on all chips of that type.  CHIP_IS_OMAP3430ES{1,2} indicates
- * something that is only valid on that particular ES revision.
- *
- * These bits may be ORed together to indicate structures that are
- * available on multiple chip types.
- *
- * To test whether a particular structure matches the current OMAP chip type,
- * use omap_chip_is().
- *
- */
-#define CHIP_IS_OMAP2420		(1 << 0)
-#define CHIP_IS_OMAP2430		(1 << 1)
-#define CHIP_IS_OMAP3430		(1 << 2)
-#define CHIP_IS_OMAP3430ES1		(1 << 3)
-#define CHIP_IS_OMAP3430ES2		(1 << 4)
-#define CHIP_IS_OMAP3430ES3_0		(1 << 5)
-#define CHIP_IS_OMAP3430ES3_1		(1 << 6)
-#define CHIP_IS_OMAP3630ES1		(1 << 7)
-#define CHIP_IS_OMAP4430ES1		(1 << 8)
-#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_OMAP4460ES1_0		(1 << 15)
-
-#define CHIP_IS_OMAP24XX		(CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
-
-#define CHIP_IS_OMAP4430		(CHIP_IS_OMAP4430ES1 |		\
-					 CHIP_IS_OMAP4430ES2 |		\
-					 CHIP_IS_OMAP4430ES2_1 |	\
-					 CHIP_IS_OMAP4430ES2_2 |	\
-					 CHIP_IS_OMAP4460ES1_0)
-
-/*
- * "GE" here represents "greater than or equal to" in terms of ES
- * levels.  So CHIP_GE_OMAP3430ES2 is intended to match all OMAP3430
- * chips at ES2 and beyond, but not, for example, any OMAP lines after
- * OMAP3.
- */
-#define CHIP_GE_OMAP3430ES2		(CHIP_IS_OMAP3430ES2 | \
-					 CHIP_IS_OMAP3430ES3_0 | \
-					 CHIP_GE_OMAP3430ES3_1)
-#define CHIP_GE_OMAP3430ES3_1		(CHIP_IS_OMAP3430ES3_1 | \
-					 CHIP_IS_OMAP3630ES1 | \
-					 CHIP_GE_OMAP3630ES1_1)
-#define CHIP_GE_OMAP3630ES1_1		(CHIP_IS_OMAP3630ES1_1 | \
-					 CHIP_IS_OMAP3630ES1_2)
-
-int omap_chip_is(struct omap_chip_id oci);
 void omap2_check_revision(void);
 
 /*
  * Runtime detection of OMAP3 features
+ *
+ * OMAP3_HAS_IO_CHAIN_CTRL: Some later members of the OMAP3 chip
+ *    family have OS-level control over the I/O chain clock.  This is
+ *    to avoid a window during which wakeups could potentially be lost
+ *    during powerdomain transitions.  If this bit is set, it
+ *    indicates that the chip does support OS-level control of this
+ *    feature.
  */
 extern u32 omap_features;
 
@@ -488,9 +417,10 @@
 #define OMAP3_HAS_192MHZ_CLK		BIT(5)
 #define OMAP3_HAS_IO_WAKEUP		BIT(6)
 #define OMAP3_HAS_SDRC			BIT(7)
-#define OMAP4_HAS_MPU_1GHZ		BIT(8)
-#define OMAP4_HAS_MPU_1_2GHZ		BIT(9)
-#define OMAP4_HAS_MPU_1_5GHZ		BIT(10)
+#define OMAP3_HAS_IO_CHAIN_CTRL		BIT(8)
+#define OMAP4_HAS_MPU_1GHZ		BIT(9)
+#define OMAP4_HAS_MPU_1_2GHZ		BIT(10)
+#define OMAP4_HAS_MPU_1_5GHZ		BIT(11)
 
 
 #define OMAP3_HAS_FEATURE(feat,flag)			\
@@ -507,12 +437,11 @@
 OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
 OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
 OMAP3_HAS_FEATURE(sdrc, SDRC)
+OMAP3_HAS_FEATURE(io_chain_ctrl, IO_CHAIN_CTRL)
 
 /*
  * Runtime detection of OMAP4 features
  */
-extern u32 omap_features;
-
 #define OMAP4_HAS_FEATURE(feat, flag)			\
 static inline unsigned int omap4_has_ ##feat(void)	\
 {							\
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/dmtimer.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/dmtimer.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/dmtimer.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/dmtimer.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * arch/arm/plat-omap/include/mach/dmtimer.h
+ * arch/arm/plat-omap/include/plat/dmtimer.h
  *
  * OMAP Dual-Mode Timers
  *
@@ -35,6 +35,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
 
 #ifndef __ASM_ARCH_DMTIMER_H
 #define __ASM_ARCH_DMTIMER_H
@@ -59,12 +60,56 @@
  * in OMAP4 can be distinguished.
  */
 #define OMAP_TIMER_IP_VERSION_1                        0x1
+
+/* timer capabilities used in hwmod database */
+#define OMAP_TIMER_SECURE				0x80000000
+#define OMAP_TIMER_ALWON				0x40000000
+#define OMAP_TIMER_HAS_PWM				0x20000000
+
+struct omap_timer_capability_dev_attr {
+	u32 timer_capability;
+};
+
 struct omap_dm_timer;
 struct clk;
 
+struct timer_regs {
+	u32 tidr;
+	u32 tiocp_cfg;
+	u32 tistat;
+	u32 tisr;
+	u32 tier;
+	u32 twer;
+	u32 tclr;
+	u32 tcrr;
+	u32 tldr;
+	u32 ttrg;
+	u32 twps;
+	u32 tmar;
+	u32 tcar1;
+	u32 tsicr;
+	u32 tcar2;
+	u32 tpir;
+	u32 tnir;
+	u32 tcvr;
+	u32 tocr;
+	u32 towr;
+};
+
+struct dmtimer_platform_data {
+	int (*set_timer_src)(struct platform_device *pdev, int source);
+	int timer_ip_version;
+	u32 needs_manual_reset:1;
+	bool reserved;
+
+	bool loses_context;
+
+	int (*get_context_loss_count)(struct device *dev);
+};
+
 struct omap_dm_timer *omap_dm_timer_request(void);
 struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
-void omap_dm_timer_free(struct omap_dm_timer *timer);
+int omap_dm_timer_free(struct omap_dm_timer *timer);
 void omap_dm_timer_enable(struct omap_dm_timer *timer);
 void omap_dm_timer_disable(struct omap_dm_timer *timer);
 
@@ -73,23 +118,23 @@
 u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer);
 
-void omap_dm_timer_trigger(struct omap_dm_timer *timer);
-void omap_dm_timer_start(struct omap_dm_timer *timer);
-void omap_dm_timer_stop(struct omap_dm_timer *timer);
+int omap_dm_timer_trigger(struct omap_dm_timer *timer);
+int omap_dm_timer_start(struct omap_dm_timer *timer);
+int omap_dm_timer_stop(struct omap_dm_timer *timer);
 
 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
-void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
-void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
-void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
-void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger);
-void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
+int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
+int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
+int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
+int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger);
+int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
 
-void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
 
 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
-void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
-void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value);
 
 int omap_dm_timers_active(void);
 
@@ -98,12 +143,30 @@
  * used by dmtimer.c and sys_timer related code.
  */
 
-/* register offsets */
-#define _OMAP_TIMER_ID_OFFSET		0x00
-#define _OMAP_TIMER_OCP_CFG_OFFSET	0x10
-#define _OMAP_TIMER_SYS_STAT_OFFSET	0x14
-#define _OMAP_TIMER_STAT_OFFSET		0x18
-#define _OMAP_TIMER_INT_EN_OFFSET	0x1c
+/*
+ * The interrupt registers are different between v1 and v2 ip.
+ * These registers are offsets from timer->iobase.
+ */
+#define OMAP_TIMER_ID_OFFSET		0x00
+#define OMAP_TIMER_OCP_CFG_OFFSET	0x10
+
+#define OMAP_TIMER_V1_SYS_STAT_OFFSET	0x14
+#define OMAP_TIMER_V1_STAT_OFFSET	0x18
+#define OMAP_TIMER_V1_INT_EN_OFFSET	0x1c
+
+#define OMAP_TIMER_V2_IRQSTATUS_RAW	0x24
+#define OMAP_TIMER_V2_IRQSTATUS		0x28
+#define OMAP_TIMER_V2_IRQENABLE_SET	0x2c
+#define OMAP_TIMER_V2_IRQENABLE_CLR	0x30
+
+/*
+ * The functional registers have a different base on v1 and v2 ip.
+ * These registers are offsets from timer->func_base. The func_base
+ * is samae as io_base for v1 and io_base + 0x14 for v2 ip.
+ *
+ */
+#define OMAP_TIMER_V2_FUNC_OFFSET		0x14
+
 #define _OMAP_TIMER_WAKEUP_EN_OFFSET	0x20
 #define _OMAP_TIMER_CTRL_OFFSET		0x24
 #define		OMAP_TIMER_CTRL_GPOCFG		(1 << 14)
@@ -147,21 +210,6 @@
 /* register offsets with the write pending bit encoded */
 #define	WPSHIFT					16
 
-#define OMAP_TIMER_ID_REG			(_OMAP_TIMER_ID_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_OCP_CFG_REG			(_OMAP_TIMER_OCP_CFG_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_SYS_STAT_REG			(_OMAP_TIMER_SYS_STAT_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_STAT_REG			(_OMAP_TIMER_STAT_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_INT_EN_REG			(_OMAP_TIMER_INT_EN_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
 #define OMAP_TIMER_WAKEUP_EN_REG		(_OMAP_TIMER_WAKEUP_EN_OFFSET \
 							| (WP_NONE << WPSHIFT))
 
@@ -209,49 +257,88 @@
 
 struct omap_dm_timer {
 	unsigned long phys_base;
+	int id;
 	int irq;
-#ifdef CONFIG_ARCH_OMAP2PLUS
 	struct clk *iclk, *fclk;
-#endif
-	void __iomem *io_base;
+
+	void __iomem	*io_base;
+	void __iomem	*sys_stat;	/* TISTAT timer status */
+	void __iomem	*irq_stat;	/* TISR/IRQSTATUS interrupt status */
+	void __iomem	*irq_ena;	/* irq enable */
+	void __iomem	*irq_dis;	/* irq disable, only on v2 ip */
+	void __iomem	*pend;		/* write pending */
+	void __iomem	*func_base;	/* function register base */
+
 	unsigned long rate;
 	unsigned reserved:1;
-	unsigned enabled:1;
 	unsigned posted:1;
+	struct timer_regs context;
+	bool loses_context;
+	int ctx_loss_count;
+	int revision;
+	struct platform_device *pdev;
+	struct list_head node;
+
+	int (*get_context_loss_count)(struct device *dev);
 };
 
-extern u32 sys_timer_reserved;
-void omap_dm_timer_prepare(struct omap_dm_timer *timer);
+int omap_dm_timer_prepare(struct omap_dm_timer *timer);
 
-static inline u32 __omap_dm_timer_read(void __iomem *base, u32 reg,
+static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg,
 						int posted)
 {
 	if (posted)
-		while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
-				& (reg >> WPSHIFT))
+		while (__raw_readl(timer->pend) & (reg >> WPSHIFT))
 			cpu_relax();
 
-	return __raw_readl(base + (reg & 0xff));
+	return __raw_readl(timer->func_base + (reg & 0xff));
 }
 
-static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, u32 val,
-						int posted)
+static inline void __omap_dm_timer_write(struct omap_dm_timer *timer,
+					u32 reg, u32 val, int posted)
 {
 	if (posted)
-		while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
-				& (reg >> WPSHIFT))
+		while (__raw_readl(timer->pend) & (reg >> WPSHIFT))
 			cpu_relax();
 
-	__raw_writel(val, base + (reg & 0xff));
+	__raw_writel(val, timer->func_base + (reg & 0xff));
+}
+
+static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
+{
+	u32 tidr;
+
+	/* Assume v1 ip if bits [31:16] are zero */
+	tidr = __raw_readl(timer->io_base);
+	if (!(tidr >> 16)) {
+		timer->revision = 1;
+		timer->sys_stat = timer->io_base +
+				OMAP_TIMER_V1_SYS_STAT_OFFSET;
+		timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET;
+		timer->irq_ena = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
+		timer->irq_dis = 0;
+		timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET;
+		timer->func_base = timer->io_base;
+	} else {
+		timer->revision = 2;
+		timer->sys_stat = 0;
+		timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS;
+		timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET;
+		timer->irq_dis = timer->io_base + OMAP_TIMER_V2_IRQENABLE_CLR;
+		timer->pend = timer->io_base +
+			_OMAP_TIMER_WRITE_PEND_OFFSET +
+				OMAP_TIMER_V2_FUNC_OFFSET;
+		timer->func_base = timer->io_base + OMAP_TIMER_V2_FUNC_OFFSET;
+	}
 }
 
 /* Assumes the source clock has been set by caller */
-static inline void __omap_dm_timer_reset(void __iomem *base, int autoidle,
-						int wakeup)
+static inline void __omap_dm_timer_reset(struct omap_dm_timer *timer,
+					int autoidle, int wakeup)
 {
 	u32 l;
 
-	l = __omap_dm_timer_read(base, OMAP_TIMER_OCP_CFG_REG, 0);
+	l = __raw_readl(timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
 	l |= 0x02 << 3;  /* Set to smart-idle mode */
 	l |= 0x2 << 8;   /* Set clock activity to perserve f-clock on idle */
 
@@ -261,10 +348,10 @@
 	if (wakeup)
 		l |= 1 << 2;
 
-	__omap_dm_timer_write(base, OMAP_TIMER_OCP_CFG_REG, l, 0);
+	__raw_writel(l, timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
 
 	/* Match hardware reset default of posted mode */
-	__omap_dm_timer_write(base, OMAP_TIMER_IF_CTRL_REG,
+	__omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
 					OMAP_TIMER_CTRL_POSTED, 0);
 }
 
@@ -286,18 +373,18 @@
 	return ret;
 }
 
-static inline void __omap_dm_timer_stop(void __iomem *base, int posted,
-						unsigned long rate)
+static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer,
+					int posted, unsigned long rate)
 {
 	u32 l;
 
-	l = __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
+	l = __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted);
 	if (l & OMAP_TIMER_CTRL_ST) {
 		l &= ~0x1;
-		__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, l, posted);
+		__omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, l, posted);
 #ifdef CONFIG_ARCH_OMAP2PLUS
 		/* Readback to make sure write has completed */
-		__omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
+		__omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted);
 		/*
 		 * Wait for functional clock period x 3.5 to make sure that
 		 * timer is stopped
@@ -307,34 +394,34 @@
 	}
 
 	/* Ack possibly pending interrupt */
-	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG,
-					OMAP_TIMER_INT_OVERFLOW, 0);
+	__raw_writel(OMAP_TIMER_INT_OVERFLOW, timer->irq_stat);
 }
 
-static inline void __omap_dm_timer_load_start(void __iomem *base, u32 ctrl,
-						unsigned int load, int posted)
+static inline void __omap_dm_timer_load_start(struct omap_dm_timer *timer,
+						u32 ctrl, unsigned int load,
+						int posted)
 {
-	__omap_dm_timer_write(base, OMAP_TIMER_COUNTER_REG, load, posted);
-	__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, ctrl, posted);
+	__omap_dm_timer_write(timer, OMAP_TIMER_COUNTER_REG, load, posted);
+	__omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, ctrl, posted);
 }
 
-static inline void __omap_dm_timer_int_enable(void __iomem *base,
+static inline void __omap_dm_timer_int_enable(struct omap_dm_timer *timer,
 						unsigned int value)
 {
-	__omap_dm_timer_write(base, OMAP_TIMER_INT_EN_REG, value, 0);
-	__omap_dm_timer_write(base, OMAP_TIMER_WAKEUP_EN_REG, value, 0);
+	__raw_writel(value, timer->irq_ena);
+	__omap_dm_timer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, value, 0);
 }
 
-static inline unsigned int __omap_dm_timer_read_counter(void __iomem *base,
-							int posted)
+static inline unsigned int
+__omap_dm_timer_read_counter(struct omap_dm_timer *timer, int posted)
 {
-	return __omap_dm_timer_read(base, OMAP_TIMER_COUNTER_REG, posted);
+	return __omap_dm_timer_read(timer, OMAP_TIMER_COUNTER_REG, posted);
 }
 
-static inline void __omap_dm_timer_write_status(void __iomem *base,
+static inline void __omap_dm_timer_write_status(struct omap_dm_timer *timer,
 						unsigned int value)
 {
-	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG, value, 0);
+	__raw_writel(value, timer->irq_stat);
 }
 
 #endif /* __ASM_ARCH_DMTIMER_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/gpio.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/gpio.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -222,26 +222,6 @@
 #include <linux/errno.h>
 #include <asm-generic/gpio.h>
 
-static inline int gpio_get_value(unsigned gpio)
-{
-	return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	__gpio_set_value(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned gpio)
-{
-	return __gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(unsigned gpio)
-{
-	return __gpio_to_irq(gpio);
-}
-
 static inline int irq_to_gpio(unsigned irq)
 {
 	int tmp;
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/io.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/io.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -228,13 +228,13 @@
 
 #define OMAP44XX_EMIF2_PHYS	OMAP44XX_EMIF2_BASE
 						/* 0x4d000000 --> 0xfd200000 */
-#define OMAP44XX_EMIF2_VIRT	(OMAP44XX_EMIF2_PHYS + OMAP4_L3_PER_IO_OFFSET)
 #define OMAP44XX_EMIF2_SIZE	SZ_1M
+#define OMAP44XX_EMIF2_VIRT	(OMAP44XX_EMIF1_VIRT + OMAP44XX_EMIF1_SIZE)
 
 #define OMAP44XX_DMM_PHYS	OMAP44XX_DMM_BASE
 						/* 0x4e000000 --> 0xfd300000 */
-#define OMAP44XX_DMM_VIRT	(OMAP44XX_DMM_PHYS + OMAP4_L3_PER_IO_OFFSET)
 #define OMAP44XX_DMM_SIZE	SZ_1M
+#define OMAP44XX_DMM_VIRT	(OMAP44XX_EMIF2_VIRT + OMAP44XX_EMIF2_SIZE)
 /*
  * ----------------------------------------------------------------------------
  * Omap specific register access
@@ -247,6 +247,8 @@
  * NOTE: Please use ioremap + __raw_read/write where possible instead of these
  */
 
+void omap_ioremap_init(void);
+
 extern u8 omap_readb(u32 pa);
 extern u16 omap_readw(u32 pa);
 extern u32 omap_readl(u32 pa);
@@ -256,8 +258,31 @@
 
 struct omap_sdrc_params;
 
-extern void omap1_map_common_io(void);
-extern void omap1_init_common_hw(void);
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+void omap7xx_map_io(void);
+#else
+static inline void omap_map_io(void)
+{
+}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP15XX
+void omap15xx_map_io(void);
+#else
+static inline void omap15xx_map_io(void)
+{
+}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP16XX
+void omap16xx_map_io(void);
+#else
+static inline void omap16xx_map_io(void)
+{
+}
+#endif
+
+void omap1_init_early(void);
 
 #ifdef CONFIG_SOC_OMAP2420
 extern void omap242x_map_common_io(void);
@@ -300,7 +325,7 @@
 #endif
 
 extern void omap2_init_common_infrastructure(void);
-extern void omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
+extern void omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
 				      struct omap_sdrc_params *sdrc_cs1);
 
 #define __arch_ioremap	omap_ioremap
@@ -309,6 +334,8 @@
 void __iomem *omap_ioremap(unsigned long phys, size_t size, unsigned int type);
 void omap_iounmap(volatile void __iomem *addr);
 
+extern void __init omap_init_consistent_dma_size(void);
+
 #endif
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/iommu2.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/iommu2.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/iommu2.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/iommu2.h	2012-01-04 18:55:44.000000000 -0500
@@ -83,12 +83,12 @@
 /*
  * register accessors
  */
-static inline u32 iommu_read_reg(struct iommu *obj, size_t offs)
+static inline u32 iommu_read_reg(struct omap_iommu *obj, size_t offs)
 {
 	return __raw_readl(obj->regbase + offs);
 }
 
-static inline void iommu_write_reg(struct iommu *obj, u32 val, size_t offs)
+static inline void iommu_write_reg(struct omap_iommu *obj, u32 val, size_t offs)
 {
 	__raw_writel(val, obj->regbase + offs);
 }
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/iommu.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/iommu.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/iommu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/iommu.h	2012-01-04 18:55:44.000000000 -0500
@@ -25,16 +25,17 @@
 	};
 };
 
-struct iommu {
+struct omap_iommu {
 	const char	*name;
 	struct module	*owner;
 	struct clk	*clk;
 	void __iomem	*regbase;
 	struct device	*dev;
 	void		*isr_priv;
+	struct iommu_domain *domain;
 
 	unsigned int	refcount;
-	struct mutex	iommu_lock;	/* global for this whole object */
+	spinlock_t	iommu_lock;	/* global for this whole object */
 
 	/*
 	 * We don't change iopgd for a situation like pgd for a task,
@@ -48,8 +49,6 @@
 	struct list_head	mmap;
 	struct mutex		mmap_lock; /* protect mmap */
 
-	int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs, void *priv);
-
 	void *ctx; /* iommu context: registres saved area */
 	u32 da_start;
 	u32 da_end;
@@ -81,25 +80,27 @@
 struct iommu_functions {
 	unsigned long	version;
 
-	int (*enable)(struct iommu *obj);
-	void (*disable)(struct iommu *obj);
-	void (*set_twl)(struct iommu *obj, bool on);
-	u32 (*fault_isr)(struct iommu *obj, u32 *ra);
+	int (*enable)(struct omap_iommu *obj);
+	void (*disable)(struct omap_iommu *obj);
+	void (*set_twl)(struct omap_iommu *obj, bool on);
+	u32 (*fault_isr)(struct omap_iommu *obj, u32 *ra);
 
-	void (*tlb_read_cr)(struct iommu *obj, struct cr_regs *cr);
-	void (*tlb_load_cr)(struct iommu *obj, struct cr_regs *cr);
+	void (*tlb_read_cr)(struct omap_iommu *obj, struct cr_regs *cr);
+	void (*tlb_load_cr)(struct omap_iommu *obj, struct cr_regs *cr);
 
-	struct cr_regs *(*alloc_cr)(struct iommu *obj, struct iotlb_entry *e);
+	struct cr_regs *(*alloc_cr)(struct omap_iommu *obj,
+							struct iotlb_entry *e);
 	int (*cr_valid)(struct cr_regs *cr);
 	u32 (*cr_to_virt)(struct cr_regs *cr);
 	void (*cr_to_e)(struct cr_regs *cr, struct iotlb_entry *e);
-	ssize_t (*dump_cr)(struct iommu *obj, struct cr_regs *cr, char *buf);
+	ssize_t (*dump_cr)(struct omap_iommu *obj, struct cr_regs *cr,
+							char *buf);
 
 	u32 (*get_pte_attr)(struct iotlb_entry *e);
 
-	void (*save_ctx)(struct iommu *obj);
-	void (*restore_ctx)(struct iommu *obj);
-	ssize_t (*dump_ctx)(struct iommu *obj, char *buf, ssize_t len);
+	void (*save_ctx)(struct omap_iommu *obj);
+	void (*restore_ctx)(struct omap_iommu *obj);
+	ssize_t (*dump_ctx)(struct omap_iommu *obj, char *buf, ssize_t len);
 };
 
 struct iommu_platform_data {
@@ -150,40 +151,31 @@
 /*
  * global functions
  */
-extern u32 iommu_arch_version(void);
-
-extern void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e);
-extern u32 iotlb_cr_to_virt(struct cr_regs *cr);
+extern u32 omap_iommu_arch_version(void);
 
-extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e);
-extern void iommu_set_twl(struct iommu *obj, bool on);
-extern void flush_iotlb_page(struct iommu *obj, u32 da);
-extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end);
-extern void flush_iotlb_all(struct iommu *obj);
+extern void omap_iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e);
 
-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
+omap_iopgtable_store_entry(struct omap_iommu *obj, struct iotlb_entry *e);
 
-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,
+extern int omap_iommu_set_isr(const char *name,
+		 int (*isr)(struct omap_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);
+extern void omap_iommu_save_ctx(struct omap_iommu *obj);
+extern void omap_iommu_restore_ctx(struct omap_iommu *obj);
 
-extern int install_iommu_arch(const struct iommu_functions *ops);
-extern void uninstall_iommu_arch(const struct iommu_functions *ops);
+extern int omap_install_iommu_arch(const struct iommu_functions *ops);
+extern void omap_uninstall_iommu_arch(const struct iommu_functions *ops);
 
-extern int foreach_iommu_device(void *data,
+extern int omap_foreach_iommu_device(void *data,
 				int (*fn)(struct device *, void *));
 
-extern ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t len);
-extern size_t dump_tlb_entries(struct iommu *obj, char *buf, ssize_t len);
+extern ssize_t
+omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len);
+extern size_t
+omap_dump_tlb_entries(struct omap_iommu *obj, char *buf, ssize_t len);
+struct device *omap_find_iommu_device(const char *name);
 
 #endif /* __MACH_IOMMU_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/iopgtable.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/iopgtable.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/iopgtable.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/iopgtable.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,120 @@
+/*
+ * omap iommu: pagetable definitions
+ *
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PLAT_OMAP_IOMMU_H
+#define __PLAT_OMAP_IOMMU_H
+
+/*
+ * "L2 table" address mask and size definitions.
+ */
+#define IOPGD_SHIFT		20
+#define IOPGD_SIZE		(1UL << IOPGD_SHIFT)
+#define IOPGD_MASK		(~(IOPGD_SIZE - 1))
+
+/*
+ * "section" address mask and size definitions.
+ */
+#define IOSECTION_SHIFT		20
+#define IOSECTION_SIZE		(1UL << IOSECTION_SHIFT)
+#define IOSECTION_MASK		(~(IOSECTION_SIZE - 1))
+
+/*
+ * "supersection" address mask and size definitions.
+ */
+#define IOSUPER_SHIFT		24
+#define IOSUPER_SIZE		(1UL << IOSUPER_SHIFT)
+#define IOSUPER_MASK		(~(IOSUPER_SIZE - 1))
+
+#define PTRS_PER_IOPGD		(1UL << (32 - IOPGD_SHIFT))
+#define IOPGD_TABLE_SIZE	(PTRS_PER_IOPGD * sizeof(u32))
+
+/*
+ * "small page" address mask and size definitions.
+ */
+#define IOPTE_SHIFT		12
+#define IOPTE_SIZE		(1UL << IOPTE_SHIFT)
+#define IOPTE_MASK		(~(IOPTE_SIZE - 1))
+
+/*
+ * "large page" address mask and size definitions.
+ */
+#define IOLARGE_SHIFT		16
+#define IOLARGE_SIZE		(1UL << IOLARGE_SHIFT)
+#define IOLARGE_MASK		(~(IOLARGE_SIZE - 1))
+
+#define PTRS_PER_IOPTE		(1UL << (IOPGD_SHIFT - IOPTE_SHIFT))
+#define IOPTE_TABLE_SIZE	(PTRS_PER_IOPTE * sizeof(u32))
+
+#define IOPAGE_MASK		IOPTE_MASK
+
+/**
+ * omap_iommu_translate() - va to pa translation
+ * @d:		omap iommu descriptor
+ * @va:		virtual address
+ * @mask:	omap iommu descriptor mask
+ *
+ * va to pa translation
+ */
+static inline phys_addr_t omap_iommu_translate(u32 d, u32 va, u32 mask)
+{
+	return (d & mask) | (va & (~mask));
+}
+
+/*
+ * some descriptor attributes.
+ */
+#define IOPGD_TABLE		(1 << 0)
+#define IOPGD_SECTION		(2 << 0)
+#define IOPGD_SUPER		(1 << 18 | 2 << 0)
+
+#define iopgd_is_table(x)	(((x) & 3) == IOPGD_TABLE)
+#define iopgd_is_section(x)	(((x) & (1 << 18 | 3)) == IOPGD_SECTION)
+#define iopgd_is_super(x)	(((x) & (1 << 18 | 3)) == IOPGD_SUPER)
+
+#define IOPTE_SMALL		(2 << 0)
+#define IOPTE_LARGE		(1 << 0)
+
+#define iopte_is_small(x)	(((x) & 2) == IOPTE_SMALL)
+#define iopte_is_large(x)	(((x) & 3) == IOPTE_LARGE)
+
+/* to find an entry in a page-table-directory */
+#define iopgd_index(da)		(((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1))
+#define iopgd_offset(obj, da)	((obj)->iopgd + iopgd_index(da))
+
+#define iopgd_page_paddr(iopgd)	(*iopgd & ~((1 << 10) - 1))
+#define iopgd_page_vaddr(iopgd)	((u32 *)phys_to_virt(iopgd_page_paddr(iopgd)))
+
+/* to find an entry in the second-level page table. */
+#define iopte_index(da)		(((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1))
+#define iopte_offset(iopgd, da)	(iopgd_page_vaddr(iopgd) + iopte_index(da))
+
+static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa,
+				   u32 flags)
+{
+	memset(e, 0, sizeof(*e));
+
+	e->da		= da;
+	e->pa		= pa;
+	e->valid	= 1;
+	/* FIXME: add OMAP1 support */
+	e->pgsz		= flags & MMU_CAM_PGSZ_MASK;
+	e->endian	= flags & MMU_RAM_ENDIAN_MASK;
+	e->elsz		= flags & MMU_RAM_ELSZ_MASK;
+	e->mixed	= flags & MMU_RAM_MIXED_MASK;
+
+	return iopgsz_to_bytes(e->pgsz);
+}
+
+#define to_iommu(dev)							\
+	(struct omap_iommu *)platform_get_drvdata(to_platform_device(dev))
+
+#endif /* __PLAT_OMAP_IOMMU_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/iovmm.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/iovmm.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/iovmm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/iovmm.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,8 +13,10 @@
 #ifndef __IOMMU_MMAP_H
 #define __IOMMU_MMAP_H
 
+#include <linux/iommu.h>
+
 struct iovm_struct {
-	struct iommu		*iommu;	/* iommu object which this belongs to */
+	struct omap_iommu	*iommu;	/* iommu object which this belongs to */
 	u32			da_start; /* area definition */
 	u32			da_end;
 	u32			flags; /* IOVMF_: see below */
@@ -70,20 +72,18 @@
 #define IOVMF_DA_FIXED		(1 << (4 + IOVMF_SW_SHIFT))
 
 
-extern struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da);
-extern u32 iommu_vmap(struct iommu *obj, u32 da,
+extern struct iovm_struct *omap_find_iovm_area(struct omap_iommu *obj, u32 da);
+extern u32
+omap_iommu_vmap(struct iommu_domain *domain, struct omap_iommu *obj, u32 da,
 			const struct sg_table *sgt, u32 flags);
-extern struct sg_table *iommu_vunmap(struct iommu *obj, u32 da);
-extern u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes,
-			   u32 flags);
-extern void iommu_vfree(struct iommu *obj, const u32 da);
-extern u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
-			u32 flags);
-extern void iommu_kunmap(struct iommu *obj, u32 da);
-extern u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes,
-			   u32 flags);
-extern void iommu_kfree(struct iommu *obj, u32 da);
-
-extern void *da_to_va(struct iommu *obj, u32 da);
+extern struct sg_table *omap_iommu_vunmap(struct iommu_domain *domain,
+				struct omap_iommu *obj, u32 da);
+extern u32
+omap_iommu_vmalloc(struct iommu_domain *domain, struct omap_iommu *obj,
+				u32 da, size_t bytes, u32 flags);
+extern void
+omap_iommu_vfree(struct iommu_domain *domain, struct omap_iommu *obj,
+				const u32 da);
+extern void *omap_da_to_va(struct omap_iommu *obj, u32 da);
 
 #endif /* __IOMMU_MMAP_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/mcbsp.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/mcbsp.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/mcbsp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/mcbsp.h	2012-01-04 18:55:44.000000000 -0500
@@ -25,9 +25,7 @@
 #define __ASM_ARCH_OMAP_MCBSP_H
 
 #include <linux/spinlock.h>
-
-#include <mach/hardware.h>
-#include <plat/clock.h>
+#include <linux/clk.h>
 
 /* macro for building platform_device for McBSP ports */
 #define OMAP_MCBSP_PLATFORM_DEVICE(port_nr)		\
@@ -40,104 +38,60 @@
 #define MCBSP_CONFIG_TYPE3	0x3
 #define MCBSP_CONFIG_TYPE4	0x4
 
-#define OMAP7XX_MCBSP1_BASE	0xfffb1000
-#define OMAP7XX_MCBSP2_BASE	0xfffb1800
-
-#define OMAP1510_MCBSP1_BASE	0xe1011800
-#define OMAP1510_MCBSP2_BASE	0xfffb1000
-#define OMAP1510_MCBSP3_BASE	0xe1017000
-
-#define OMAP1610_MCBSP1_BASE	0xe1011800
-#define OMAP1610_MCBSP2_BASE	0xfffb1000
-#define OMAP1610_MCBSP3_BASE	0xe1017000
-
-#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
-#define OMAP_MCBSP_REG_RCR1	0x0e
-#define OMAP_MCBSP_REG_XCR2	0x10
-#define OMAP_MCBSP_REG_XCR1	0x12
-#define OMAP_MCBSP_REG_SRGR2	0x14
-#define OMAP_MCBSP_REG_SRGR1	0x16
-#define OMAP_MCBSP_REG_MCR2	0x18
-#define OMAP_MCBSP_REG_MCR1	0x1a
-#define OMAP_MCBSP_REG_RCERA	0x1c
-#define OMAP_MCBSP_REG_RCERB	0x1e
-#define OMAP_MCBSP_REG_XCERA	0x20
-#define OMAP_MCBSP_REG_XCERB	0x22
-#define OMAP_MCBSP_REG_PCR0	0x24
-#define OMAP_MCBSP_REG_RCERC	0x26
-#define OMAP_MCBSP_REG_RCERD	0x28
-#define OMAP_MCBSP_REG_XCERC	0x2A
-#define OMAP_MCBSP_REG_XCERD	0x2C
-#define OMAP_MCBSP_REG_RCERE	0x2E
-#define OMAP_MCBSP_REG_RCERF	0x30
-#define OMAP_MCBSP_REG_XCERE	0x32
-#define OMAP_MCBSP_REG_XCERF	0x34
-#define OMAP_MCBSP_REG_RCERG	0x36
-#define OMAP_MCBSP_REG_RCERH	0x38
-#define OMAP_MCBSP_REG_XCERG	0x3A
-#define OMAP_MCBSP_REG_XCERH	0x3C
-
-/* Dummy defines, these are not available on omap1 */
-#define OMAP_MCBSP_REG_XCCR	0x00
-#define OMAP_MCBSP_REG_RCCR	0x00
+/* McBSP register numbers. Register address offset = num * reg_step */
+enum {
+	/* Common registers */
+	OMAP_MCBSP_REG_SPCR2 = 4,
+	OMAP_MCBSP_REG_SPCR1,
+	OMAP_MCBSP_REG_RCR2,
+	OMAP_MCBSP_REG_RCR1,
+	OMAP_MCBSP_REG_XCR2,
+	OMAP_MCBSP_REG_XCR1,
+	OMAP_MCBSP_REG_SRGR2,
+	OMAP_MCBSP_REG_SRGR1,
+	OMAP_MCBSP_REG_MCR2,
+	OMAP_MCBSP_REG_MCR1,
+	OMAP_MCBSP_REG_RCERA,
+	OMAP_MCBSP_REG_RCERB,
+	OMAP_MCBSP_REG_XCERA,
+	OMAP_MCBSP_REG_XCERB,
+	OMAP_MCBSP_REG_PCR0,
+	OMAP_MCBSP_REG_RCERC,
+	OMAP_MCBSP_REG_RCERD,
+	OMAP_MCBSP_REG_XCERC,
+	OMAP_MCBSP_REG_XCERD,
+	OMAP_MCBSP_REG_RCERE,
+	OMAP_MCBSP_REG_RCERF,
+	OMAP_MCBSP_REG_XCERE,
+	OMAP_MCBSP_REG_XCERF,
+	OMAP_MCBSP_REG_RCERG,
+	OMAP_MCBSP_REG_RCERH,
+	OMAP_MCBSP_REG_XCERG,
+	OMAP_MCBSP_REG_XCERH,
 
-#else
+	/* OMAP1-OMAP2420 registers */
+	OMAP_MCBSP_REG_DRR2 = 0,
+	OMAP_MCBSP_REG_DRR1,
+	OMAP_MCBSP_REG_DXR2,
+	OMAP_MCBSP_REG_DXR1,
 
-#define OMAP_MCBSP_REG_DRR2	0x00
-#define OMAP_MCBSP_REG_DRR1	0x04
-#define OMAP_MCBSP_REG_DXR2	0x08
-#define OMAP_MCBSP_REG_DXR1	0x0C
-#define OMAP_MCBSP_REG_DRR	0x00
-#define OMAP_MCBSP_REG_DXR	0x08
-#define OMAP_MCBSP_REG_SPCR2	0x10
-#define OMAP_MCBSP_REG_SPCR1	0x14
-#define OMAP_MCBSP_REG_RCR2	0x18
-#define OMAP_MCBSP_REG_RCR1	0x1C
-#define OMAP_MCBSP_REG_XCR2	0x20
-#define OMAP_MCBSP_REG_XCR1	0x24
-#define OMAP_MCBSP_REG_SRGR2	0x28
-#define OMAP_MCBSP_REG_SRGR1	0x2C
-#define OMAP_MCBSP_REG_MCR2	0x30
-#define OMAP_MCBSP_REG_MCR1	0x34
-#define OMAP_MCBSP_REG_RCERA	0x38
-#define OMAP_MCBSP_REG_RCERB	0x3C
-#define OMAP_MCBSP_REG_XCERA	0x40
-#define OMAP_MCBSP_REG_XCERB	0x44
-#define OMAP_MCBSP_REG_PCR0	0x48
-#define OMAP_MCBSP_REG_RCERC	0x4C
-#define OMAP_MCBSP_REG_RCERD	0x50
-#define OMAP_MCBSP_REG_XCERC	0x54
-#define OMAP_MCBSP_REG_XCERD	0x58
-#define OMAP_MCBSP_REG_RCERE	0x5C
-#define OMAP_MCBSP_REG_RCERF	0x60
-#define OMAP_MCBSP_REG_XCERE	0x64
-#define OMAP_MCBSP_REG_XCERF	0x68
-#define OMAP_MCBSP_REG_RCERG	0x6C
-#define OMAP_MCBSP_REG_RCERH	0x70
-#define OMAP_MCBSP_REG_XCERG	0x74
-#define OMAP_MCBSP_REG_XCERH	0x78
-#define OMAP_MCBSP_REG_SYSCON	0x8C
-#define OMAP_MCBSP_REG_THRSH2	0x90
-#define OMAP_MCBSP_REG_THRSH1	0x94
-#define OMAP_MCBSP_REG_IRQST	0xA0
-#define OMAP_MCBSP_REG_IRQEN	0xA4
-#define OMAP_MCBSP_REG_WAKEUPEN	0xA8
-#define OMAP_MCBSP_REG_XCCR	0xAC
-#define OMAP_MCBSP_REG_RCCR	0xB0
-#define OMAP_MCBSP_REG_XBUFFSTAT	0xB4
-#define OMAP_MCBSP_REG_RBUFFSTAT	0xB8
-#define OMAP_MCBSP_REG_SSELCR	0xBC
+	/* OMAP2430 and onwards */
+	OMAP_MCBSP_REG_DRR = 0,
+	OMAP_MCBSP_REG_DXR = 2,
+	OMAP_MCBSP_REG_SYSCON =	35,
+	OMAP_MCBSP_REG_THRSH2,
+	OMAP_MCBSP_REG_THRSH1,
+	OMAP_MCBSP_REG_IRQST = 40,
+	OMAP_MCBSP_REG_IRQEN,
+	OMAP_MCBSP_REG_WAKEUPEN,
+	OMAP_MCBSP_REG_XCCR,
+	OMAP_MCBSP_REG_RCCR,
+	OMAP_MCBSP_REG_XBUFFSTAT,
+	OMAP_MCBSP_REG_RBUFFSTAT,
+	OMAP_MCBSP_REG_SSELCR,
+};
 
+/* OMAP3 sidetone control registers */
 #define OMAP_ST_REG_REV		0x00
 #define OMAP_ST_REG_SYSCONFIG	0x10
 #define OMAP_ST_REG_IRQSTATUS	0x18
@@ -146,8 +100,6 @@
 #define OMAP_ST_REG_SFIRCR	0x28
 #define OMAP_ST_REG_SSELCR	0x2C
 
-#endif
-
 /************************** McBSP SPCR1 bit definitions ***********************/
 #define RRST			0x0001
 #define RRDY			0x0002
@@ -344,20 +296,20 @@
 struct omap_mcbsp_ops {
 	void (*request)(unsigned int);
 	void (*free)(unsigned int);
-	int (*set_clks_src)(u8, u8);
 };
 
 struct omap_mcbsp_platform_data {
-	unsigned long phys_base;
-	u8 dma_rx_sync, dma_tx_sync;
-	u16 rx_irq, tx_irq;
 	struct omap_mcbsp_ops *ops;
-#ifdef CONFIG_ARCH_OMAP3
-	/* Sidetone block for McBSP 2 and 3 */
-	unsigned long phys_base_st;
-#endif
 	u16 buffer_size;
-	unsigned int mcbsp_config_type;
+	u8 reg_size;
+	u8 reg_step;
+
+	/* McBSP platform and instance specific features */
+	bool has_wakeup; /* Wakeup capability */
+	bool has_ccr; /* Transceiver has configuration control registers */
+	int (*enable_st_clock)(unsigned int, bool);
+	int (*set_clk_src)(struct device *dev, struct clk *clk, const char *src);
+	int (*mux_signal)(struct device *dev, const char *signal, const char *src);
 };
 
 struct omap_mcbsp_st_data {
@@ -389,14 +341,12 @@
 	spinlock_t lock;
 	struct omap_mcbsp_platform_data *pdata;
 	struct clk *fclk;
-#ifdef CONFIG_ARCH_OMAP3
 	struct omap_mcbsp_st_data *st_data;
 	int dma_op_mode;
 	u16 max_tx_thres;
 	u16 max_rx_thres;
-#endif
 	void *reg_cache;
-	unsigned int mcbsp_config_type;
+	int reg_cache_size;
 };
 
 /**
@@ -408,16 +358,10 @@
 };
 
 extern struct omap_mcbsp **mcbsp_ptr;
-extern int omap_mcbsp_count, omap_mcbsp_cache_size;
-
-#define omap_mcbsp_check_valid_id(id)	(id < omap_mcbsp_count)
-#define id_to_mcbsp_ptr(id)		mcbsp_ptr[id];
+extern int omap_mcbsp_count;
 
 int omap_mcbsp_init(void);
-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);
 void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold);
 u16 omap_mcbsp_get_max_tx_threshold(unsigned int id);
@@ -426,18 +370,6 @@
 u16 omap_mcbsp_get_tx_delay(unsigned int id);
 u16 omap_mcbsp_get_rx_delay(unsigned int id);
 int omap_mcbsp_get_dma_op_mode(unsigned int id);
-#else
-static inline void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
-{ }
-static inline void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
-{ }
-static inline u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) { return 0; }
-static inline u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) { return 0; }
-static inline u16 omap_mcbsp_get_fifo_size(unsigned int id) { return 0; }
-static inline u16 omap_mcbsp_get_tx_delay(unsigned int id) { return 0; }
-static inline u16 omap_mcbsp_get_rx_delay(unsigned int id) { return 0; }
-static inline int omap_mcbsp_get_dma_op_mode(unsigned int id) { return 0; }
-#endif
 int omap_mcbsp_request(unsigned int id);
 void omap_mcbsp_free(unsigned int id);
 void omap_mcbsp_start(unsigned int id, int tx, int rx);
@@ -453,21 +385,11 @@
 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);
 int omap_st_get_chgain(unsigned int id, int channel, s16 *chgain);
 int omap_st_enable(unsigned int id);
 int omap_st_disable(unsigned int id);
 int omap_st_is_enabled(unsigned int id);
-#else
-static inline int omap_st_set_chgain(unsigned int id, int channel,
-				     s16 chgain) { return 0; }
-static inline int omap_st_get_chgain(unsigned int id, int channel,
-				     s16 *chgain) { return 0; }
-static inline int omap_st_enable(unsigned int id) { return 0; }
-static inline int omap_st_disable(unsigned int id) { return 0; }
-static inline int omap_st_is_enabled(unsigned int id) {  return 0; }
-#endif
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/memory.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/memory.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,102 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/memory.h
- *
- * Memory map for OMAP-1510 and 1610
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: Greg Lonnon <glonnon@ridgerun.com>
- *
- * This file was derived from arch/arm/mach-intergrator/include/mach/memory.h
- * Copyright (C) 1999 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#if defined(CONFIG_ARCH_OMAP1)
-#define PLAT_PHYS_OFFSET		UL(0x10000000)
-#else
-#define PLAT_PHYS_OFFSET		UL(0x80000000)
-#endif
-
-/*
- * Bus address is physical address, except for OMAP-1510 Local Bus.
- * OMAP-1510 bus address is translated into a Local Bus address if the
- * OMAP bus type is lbus. We do the address translation based on the
- * device overriding the defaults used in the dma-mapping API.
- * Note that the is_lbus_device() test is not very efficient on 1510
- * because of the strncmp().
- */
-#ifdef CONFIG_ARCH_OMAP15XX
-
-/*
- * OMAP-1510 Local Bus address offset
- */
-#define OMAP1510_LB_OFFSET	UL(0x30000000)
-
-#define virt_to_lbus(x)		((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)
-#define lbus_to_virt(x)		((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
-#define is_lbus_device(dev)	(cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0))
-
-#define __arch_pfn_to_dma(dev, pfn)	\
-	({ dma_addr_t __dma = __pfn_to_phys(pfn); \
-	   if (is_lbus_device(dev)) \
-		__dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \
-	   __dma; })
-
-#define __arch_dma_to_pfn(dev, addr)	\
-	({ dma_addr_t __dma = addr;				\
-	   if (is_lbus_device(dev))				\
-		__dma += PHYS_OFFSET - OMAP1510_LB_OFFSET;	\
-	   __phys_to_pfn(__dma);				\
-	})
-
-#define __arch_dma_to_virt(dev, addr)	({ (void *) (is_lbus_device(dev) ? \
-						lbus_to_virt(addr) : \
-						__phys_to_virt(addr)); })
-
-#define __arch_virt_to_dma(dev, addr)	({ unsigned long __addr = (unsigned long)(addr); \
-					   (dma_addr_t) (is_lbus_device(dev) ? \
-						virt_to_lbus(__addr) : \
-						__virt_to_phys(__addr)); })
-
-#endif	/* CONFIG_ARCH_OMAP15XX */
-
-/* Override the ARM default */
-#ifdef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE
-
-#if (CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE == 0)
-#undef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE
-#define CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE 2
-#endif
-
-#define CONSISTENT_DMA_SIZE \
-	(((CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE + 1) & ~1) * 1024 * 1024)
-
-#endif
-
-#endif
-
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/mmc.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/mmc.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/mmc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/mmc.h	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,24 @@
 
 #define OMAP_MMC_MAX_SLOTS	2
 
-#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT	BIT(1)
+/*
+ * struct omap_mmc_dev_attr.flags possibilities
+ *
+ * OMAP_HSMMC_SUPPORTS_DUAL_VOLT: Some HSMMC controller instances can
+ *    operate with either 1.8Vdc or 3.0Vdc card voltages; this flag
+ *    should be set if this is the case.  See for example Section 22.5.3
+ *    "MMC/SD/SDIO1 Bus Voltage Selection" of the OMAP34xx Multimedia
+ *    Device Silicon Revision 3.1.x Revision ZR (July 2011) (SWPU223R).
+ *
+ * OMAP_HSMMC_BROKEN_MULTIBLOCK_READ: Multiple-block read transfers
+ *    don't work correctly on some MMC controller instances on some
+ *    OMAP3 SoCs; this flag should be set if this is the case.  See
+ *    for example Advisory 2.1.1.128 "MMC: Multiple Block Read
+ *    Operation Issue" in _OMAP3530/3525/3515/3503 Silicon Errata_
+ *    Revision F (October 2010) (SPRZ278F).
+ */
+#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT		BIT(0)
+#define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ	BIT(1)
 
 struct omap_mmc_dev_attr {
 	u8 flags;
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/omap-alsa.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/omap-alsa.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/omap-alsa.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/omap-alsa.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,123 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/omap-alsa.h
- *
- * Alsa Driver for AIC23 and TSC2101 codecs on OMAP platform boards.
- *
- * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
- *
- * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
- * Written by Daniel Petrini, David Cohen, Anderson Briglia
- *            {daniel.petrini, david.cohen, anderson.briglia}@indt.org.br
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU 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.
- *
- *  History
- *  -------
- *
- *  2005/07/25 INdT-10LE Kernel Team - 	Alsa driver for omap osk,
- *  					original version based in sa1100 driver
- *  					and omap oss driver.
- */
-
-#ifndef __OMAP_ALSA_H
-#define __OMAP_ALSA_H
-
-#include <plat/dma.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <plat/mcbsp.h>
-#include <linux/platform_device.h>
-
-#define DMA_BUF_SIZE	(1024 * 8)
-
-/*
- * Buffer management for alsa and dma
- */
-struct audio_stream {
-	char *id;		/* identification string */
-	int stream_id;		/* numeric identification */
-	int dma_dev;		/* dma number of that device */
-	int *lch;		/* Chain of channels this stream is linked to */
-	char started;		/* to store if the chain was started or not */
-	int dma_q_head;		/* DMA Channel Q Head */
-	int dma_q_tail;		/* DMA Channel Q Tail */
-	char dma_q_count;	/* DMA Channel Q Count */
-	int active:1;		/* we are using this stream for transfer now */
-	int period;		/* current transfer period */
-	int periods;		/* current count of periods registerd in the DMA engine */
-	spinlock_t dma_lock;	/* for locking in DMA operations */
-	struct snd_pcm_substream *stream;	/* the pcm stream */
-	unsigned linked:1;	/* dma channels linked */
-	int offset;		/* store start position of the last period in the alsa buffer */
-	int (*hw_start)(void);  /* interface to start HW interface, e.g. McBSP */
-	int (*hw_stop)(void);   /* interface to stop HW interface, e.g. McBSP */
-};
-
-/*
- * Alsa card structure for aic23
- */
-struct snd_card_omap_codec {
-	struct snd_card *card;
-	struct snd_pcm *pcm;
-	long samplerate;
-	struct audio_stream s[2];	/* playback & capture */
-};
-
-/* Codec specific information and function pointers.
- * Codec (omap-alsa-aic23.c and omap-alsa-tsc2101.c)
- * are responsible for defining the function pointers.
- */
-struct omap_alsa_codec_config {
-	char 	*name;
-	struct	omap_mcbsp_reg_cfg *mcbsp_regs_alsa;
-	struct	snd_pcm_hw_constraint_list *hw_constraints_rates;
-	struct	snd_pcm_hardware *snd_omap_alsa_playback;
-	struct	snd_pcm_hardware *snd_omap_alsa_capture;
-	void	(*codec_configure_dev)(void);
-	void	(*codec_set_samplerate)(long);
-	void	(*codec_clock_setup)(void);
-	int	(*codec_clock_on)(void);
-	int 	(*codec_clock_off)(void);
-	int	(*get_default_samplerate)(void);
-};
-
-/*********** Mixer function prototypes *************************/
-int snd_omap_mixer(struct snd_card_omap_codec *);
-void snd_omap_init_mixer(void);
-
-#ifdef CONFIG_PM
-void snd_omap_suspend_mixer(void);
-void snd_omap_resume_mixer(void);
-#endif
-
-int snd_omap_alsa_post_probe(struct platform_device *pdev, struct omap_alsa_codec_config *config);
-int snd_omap_alsa_remove(struct platform_device *pdev);
-#ifdef CONFIG_PM
-int snd_omap_alsa_suspend(struct platform_device *pdev, pm_message_t state);
-int snd_omap_alsa_resume(struct platform_device *pdev);
-#else
-#define snd_omap_alsa_suspend	NULL
-#define snd_omap_alsa_resume	NULL
-#endif
-
-void callback_omap_alsa_sound_dma(void *);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/omap_device.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/omap_device.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/omap_device.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/omap_device.h	2012-01-04 18:55:44.000000000 -0500
@@ -68,7 +68,7 @@
  *
  */
 struct omap_device {
-	struct platform_device		pdev;
+	struct platform_device		*pdev;
 	struct omap_hwmod		**hwmods;
 	struct omap_device_pm_latency	*pm_lats;
 	u32				dev_wakeup_lat;
@@ -88,31 +88,26 @@
 
 /* Core code interface */
 
-int omap_device_count_resources(struct omap_device *od);
-int omap_device_fill_resources(struct omap_device *od, struct resource *res);
-
-struct omap_device *omap_device_build(const char *pdev_name, int pdev_id,
+struct platform_device *omap_device_build(const char *pdev_name, int pdev_id,
 				      struct omap_hwmod *oh, void *pdata,
 				      int pdata_len,
 				      struct omap_device_pm_latency *pm_lats,
 				      int pm_lats_cnt, int is_early_device);
 
-struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
+struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 					 struct omap_hwmod **oh, int oh_cnt,
 					 void *pdata, int pdata_len,
 					 struct omap_device_pm_latency *pm_lats,
 					 int pm_lats_cnt, int is_early_device);
 
-int omap_device_register(struct omap_device *od);
-int omap_early_device_register(struct omap_device *od);
-
 void __iomem *omap_device_get_rt_va(struct omap_device *od);
+struct device *omap_device_get_by_hwmod_name(const char *oh_name);
 
 /* OMAP PM interface */
 int omap_device_align_pm_lat(struct platform_device *pdev,
 			     u32 new_wakeup_lat_limit);
 struct powerdomain *omap_device_get_pwrdm(struct omap_device *od);
-u32 omap_device_get_context_loss_count(struct platform_device *pdev);
+int omap_device_get_context_loss_count(struct platform_device *pdev);
 
 /* Other */
 
@@ -122,11 +117,6 @@
 int omap_device_disable_clocks(struct omap_device *od);
 int omap_device_enable_clocks(struct omap_device *od);
 
-static inline void omap_device_disable_idle_on_suspend(struct omap_device *od)
-{
-	od->flags |= OMAP_DEVICE_NO_IDLE_ON_SUSPEND;
-}
-
 /*
  * Entries should be kept in latency order ascending
  *
@@ -157,6 +147,17 @@
 #define OMAP_DEVICE_LATENCY_AUTO_ADJUST BIT(1)
 
 /* Get omap_device pointer from platform_device pointer */
-#define to_omap_device(x) container_of((x), struct omap_device, pdev)
+static inline struct omap_device *to_omap_device(struct platform_device *pdev)
+{
+	return pdev ? pdev->archdata.od : NULL;
+}
+
+static inline
+void omap_device_disable_idle_on_suspend(struct platform_device *pdev)
+{
+	struct omap_device *od = to_omap_device(pdev);
+
+	od->flags |= OMAP_DEVICE_NO_IDLE_ON_SUSPEND;
+}
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/omap_hwmod.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/omap_hwmod.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/omap_hwmod.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/omap_hwmod.h	2012-01-04 18:55:44.000000000 -0500
@@ -496,7 +496,6 @@
  * @_state: internal-use hwmod state
  * @_postsetup_state: internal-use state to leave the hwmod in after _setup()
  * @flags: hwmod flags (documented below)
- * @omap_chip: OMAP chips this hwmod is present on
  * @_lock: spinlock serializing operations on this hwmod
  * @node: list node for hwmod list (internal use)
  *
@@ -526,7 +525,6 @@
 	char				*clkdm_name;
 	struct clockdomain		*clkdm;
 	char				*vdd_name;
-	struct voltagedomain		*voltdm;
 	struct omap_hwmod_ocp_if	**masters; /* connect to *_IA */
 	struct omap_hwmod_ocp_if	**slaves;  /* connect to *_TA */
 	void				*dev_attr;
@@ -545,7 +543,6 @@
 	u8				_int_flags;
 	u8				_state;
 	u8				_postsetup_state;
-	const struct omap_chip_id	omap_chip;
 };
 
 int omap_hwmod_register(struct omap_hwmod **ohs);
@@ -603,7 +600,7 @@
 				 void *user);
 
 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_get_context_loss_count(struct omap_hwmod *oh);
 
 int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/omap-pm.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/omap-pm.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/omap-pm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/omap-pm.h	2012-01-04 18:55:44.000000000 -0500
@@ -342,9 +342,9 @@
  * driver must restore device context.   If the number of context losses
  * exceeds the maximum positive integer, the function will wrap to 0 and
  * continue counting.  Returns the number of context losses for this device,
- * or zero upon error.
+ * or negative value upon error.
  */
-u32 omap_pm_get_dev_context_loss_count(struct device *dev);
+int omap_pm_get_dev_context_loss_count(struct device *dev);
 
 void omap_pm_enable_off_mode(void);
 void omap_pm_disable_off_mode(void);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/serial.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/serial.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/serial.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/serial.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,8 +16,8 @@
 #include <linux/init.h>
 
 /*
- * Memory entry used for the DEBUG_LL UART configuration. See also
- * uncompress.h and debug-macro.S.
+ * Memory entry used for the DEBUG_LL UART configuration, relative to
+ * start of RAM. See also uncompress.h and debug-macro.S.
  *
  * Note that using a memory location for storing the UART configuration
  * has at least two limitations:
@@ -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		(PLAT_PHYS_OFFSET + 0x3ffc)
+#define OMAP_UART_INFO_OFS	0x3ffc
 
 /* OMAP1 serial ports */
 #define OMAP1_UART1_BASE	0xfffb0000
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/uncompress.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/uncompress.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/uncompress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/uncompress.h	2012-01-04 18:55:44.000000000 -0500
@@ -36,7 +36,13 @@
  */
 static void set_omap_uart_info(unsigned char port)
 {
-	*(volatile u32 *)OMAP_UART_INFO = port;
+	/*
+	 * Get address of some.bss variable and round it down
+	 * a la CONFIG_AUTO_ZRELADDR.
+	 */
+	u32 ram_start = (u32)&uart_shift & 0xf8000000;
+	u32 *uart_info = (u32 *)(ram_start + OMAP_UART_INFO_OFS);
+	*uart_info = port;
 }
 
 static void putc(int c)
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/voltage.h linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/voltage.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/include/plat/voltage.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/include/plat/voltage.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,20 @@
+/*
+ * OMAP Voltage Management Routines
+ *
+ * Copyright (C) 2011, 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_OMAP_VOLTAGE_H
+#define __ARCH_ARM_OMAP_VOLTAGE_H
+
+struct voltagedomain;
+
+struct voltagedomain *voltdm_lookup(const char *name);
+int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
+unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/io.c linux-libre-3.2-gnu/arch/arm/plat-omap/io.c
--- linux-libre-3.1-gnu/arch/arm/plat-omap/io.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/mm.h>
+#include <linux/dma-mapping.h>
 
 #include <plat/omap7xx.h>
 #include <plat/omap1510.h>
@@ -23,11 +24,16 @@
 #define BETWEEN(p,st,sz)	((p) >= (st) && (p) < ((st) + (sz)))
 #define XLATE(p,pst,vst)	((void __iomem *)((p) - (pst) + (vst)))
 
+static int initialized;
+
 /*
  * Intercept ioremap() requests for addresses in our fixed mapping regions.
  */
 void __iomem *omap_ioremap(unsigned long p, size_t size, unsigned int type)
 {
+
+	WARN(!initialized, "Do not use ioremap before init_early\n");
+
 #ifdef CONFIG_ARCH_OMAP1
 	if (cpu_class_is_omap1()) {
 		if (BETWEEN(p, OMAP1_IO_PHYS, OMAP1_IO_SIZE))
@@ -139,3 +145,15 @@
 		__iounmap(addr);
 }
 EXPORT_SYMBOL(omap_iounmap);
+
+void __init omap_init_consistent_dma_size(void)
+{
+#ifdef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE
+	init_consistent_dma_size(CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE << 20);
+#endif
+}
+
+void __init omap_ioremap_init(void)
+{
+	initialized++;
+}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/iommu.c linux-libre-3.2-gnu/arch/arm/plat-omap/iommu.c
--- linux-libre-3.1-gnu/arch/arm/plat-omap/iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/iommu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1102 +0,0 @@
-/*
- * omap iommu: tlb and pagetable primitives
- *
- * Copyright (C) 2008-2010 Nokia Corporation
- *
- * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>,
- *		Paul Mundt and Toshihiro Kobayashi
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-
-#include <asm/cacheflush.h>
-
-#include <plat/iommu.h>
-
-#include "iopgtable.h"
-
-#define for_each_iotlb_cr(obj, n, __i, cr)				\
-	for (__i = 0;							\
-	     (__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true);	\
-	     __i++)
-
-/* accommodate the difference between omap1 and omap2/3 */
-static const struct iommu_functions *arch_iommu;
-
-static struct platform_driver omap_iommu_driver;
-static struct kmem_cache *iopte_cachep;
-
-/**
- * install_iommu_arch - Install archtecure specific iommu functions
- * @ops:	a pointer to architecture specific iommu functions
- *
- * There are several kind of iommu algorithm(tlb, pagetable) among
- * omap series. This interface installs such an iommu algorighm.
- **/
-int install_iommu_arch(const struct iommu_functions *ops)
-{
-	if (arch_iommu)
-		return -EBUSY;
-
-	arch_iommu = ops;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(install_iommu_arch);
-
-/**
- * uninstall_iommu_arch - Uninstall archtecure specific iommu functions
- * @ops:	a pointer to architecture specific iommu functions
- *
- * This interface uninstalls the iommu algorighm installed previously.
- **/
-void uninstall_iommu_arch(const struct iommu_functions *ops)
-{
-	if (arch_iommu != ops)
-		pr_err("%s: not your arch\n", __func__);
-
-	arch_iommu = NULL;
-}
-EXPORT_SYMBOL_GPL(uninstall_iommu_arch);
-
-/**
- * iommu_save_ctx - Save registers for pm off-mode support
- * @obj:	target iommu
- **/
-void iommu_save_ctx(struct iommu *obj)
-{
-	arch_iommu->save_ctx(obj);
-}
-EXPORT_SYMBOL_GPL(iommu_save_ctx);
-
-/**
- * iommu_restore_ctx - Restore registers for pm off-mode support
- * @obj:	target iommu
- **/
-void iommu_restore_ctx(struct iommu *obj)
-{
-	arch_iommu->restore_ctx(obj);
-}
-EXPORT_SYMBOL_GPL(iommu_restore_ctx);
-
-/**
- * iommu_arch_version - Return running iommu arch version
- **/
-u32 iommu_arch_version(void)
-{
-	return arch_iommu->version;
-}
-EXPORT_SYMBOL_GPL(iommu_arch_version);
-
-static int iommu_enable(struct iommu *obj)
-{
-	int err;
-
-	if (!obj)
-		return -EINVAL;
-
-	if (!arch_iommu)
-		return -ENODEV;
-
-	clk_enable(obj->clk);
-
-	err = arch_iommu->enable(obj);
-
-	clk_disable(obj->clk);
-	return err;
-}
-
-static void iommu_disable(struct iommu *obj)
-{
-	if (!obj)
-		return;
-
-	clk_enable(obj->clk);
-
-	arch_iommu->disable(obj);
-
-	clk_disable(obj->clk);
-}
-
-/*
- *	TLB operations
- */
-void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
-{
-	BUG_ON(!cr || !e);
-
-	arch_iommu->cr_to_e(cr, e);
-}
-EXPORT_SYMBOL_GPL(iotlb_cr_to_e);
-
-static inline int iotlb_cr_valid(struct cr_regs *cr)
-{
-	if (!cr)
-		return -EINVAL;
-
-	return arch_iommu->cr_valid(cr);
-}
-
-static inline struct cr_regs *iotlb_alloc_cr(struct iommu *obj,
-					     struct iotlb_entry *e)
-{
-	if (!e)
-		return NULL;
-
-	return arch_iommu->alloc_cr(obj, e);
-}
-
-u32 iotlb_cr_to_virt(struct cr_regs *cr)
-{
-	return arch_iommu->cr_to_virt(cr);
-}
-EXPORT_SYMBOL_GPL(iotlb_cr_to_virt);
-
-static u32 get_iopte_attr(struct iotlb_entry *e)
-{
-	return arch_iommu->get_pte_attr(e);
-}
-
-static u32 iommu_report_fault(struct iommu *obj, u32 *da)
-{
-	return arch_iommu->fault_isr(obj, da);
-}
-
-static void iotlb_lock_get(struct iommu *obj, struct iotlb_lock *l)
-{
-	u32 val;
-
-	val = iommu_read_reg(obj, MMU_LOCK);
-
-	l->base = MMU_LOCK_BASE(val);
-	l->vict = MMU_LOCK_VICT(val);
-
-}
-
-static void iotlb_lock_set(struct iommu *obj, struct iotlb_lock *l)
-{
-	u32 val;
-
-	val = (l->base << MMU_LOCK_BASE_SHIFT);
-	val |= (l->vict << MMU_LOCK_VICT_SHIFT);
-
-	iommu_write_reg(obj, val, MMU_LOCK);
-}
-
-static void iotlb_read_cr(struct iommu *obj, struct cr_regs *cr)
-{
-	arch_iommu->tlb_read_cr(obj, cr);
-}
-
-static void iotlb_load_cr(struct iommu *obj, struct cr_regs *cr)
-{
-	arch_iommu->tlb_load_cr(obj, cr);
-
-	iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
-	iommu_write_reg(obj, 1, MMU_LD_TLB);
-}
-
-/**
- * iotlb_dump_cr - Dump an iommu tlb entry into buf
- * @obj:	target iommu
- * @cr:		contents of cam and ram register
- * @buf:	output buffer
- **/
-static inline ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr,
-				    char *buf)
-{
-	BUG_ON(!cr || !buf);
-
-	return arch_iommu->dump_cr(obj, cr, buf);
-}
-
-/* only used in iotlb iteration for-loop */
-static struct cr_regs __iotlb_read_cr(struct iommu *obj, int n)
-{
-	struct cr_regs cr;
-	struct iotlb_lock l;
-
-	iotlb_lock_get(obj, &l);
-	l.vict = n;
-	iotlb_lock_set(obj, &l);
-	iotlb_read_cr(obj, &cr);
-
-	return cr;
-}
-
-/**
- * load_iotlb_entry - Set an iommu tlb entry
- * @obj:	target iommu
- * @e:		an iommu tlb entry info
- **/
-int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
-{
-	int err = 0;
-	struct iotlb_lock l;
-	struct cr_regs *cr;
-
-	if (!obj || !obj->nr_tlb_entries || !e)
-		return -EINVAL;
-
-	clk_enable(obj->clk);
-
-	iotlb_lock_get(obj, &l);
-	if (l.base == obj->nr_tlb_entries) {
-		dev_warn(obj->dev, "%s: preserve entries full\n", __func__);
-		err = -EBUSY;
-		goto out;
-	}
-	if (!e->prsvd) {
-		int i;
-		struct cr_regs tmp;
-
-		for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, tmp)
-			if (!iotlb_cr_valid(&tmp))
-				break;
-
-		if (i == obj->nr_tlb_entries) {
-			dev_dbg(obj->dev, "%s: full: no entry\n", __func__);
-			err = -EBUSY;
-			goto out;
-		}
-
-		iotlb_lock_get(obj, &l);
-	} else {
-		l.vict = l.base;
-		iotlb_lock_set(obj, &l);
-	}
-
-	cr = iotlb_alloc_cr(obj, e);
-	if (IS_ERR(cr)) {
-		clk_disable(obj->clk);
-		return PTR_ERR(cr);
-	}
-
-	iotlb_load_cr(obj, cr);
-	kfree(cr);
-
-	if (e->prsvd)
-		l.base++;
-	/* increment victim for next tlb load */
-	if (++l.vict == obj->nr_tlb_entries)
-		l.vict = l.base;
-	iotlb_lock_set(obj, &l);
-out:
-	clk_disable(obj->clk);
-	return err;
-}
-EXPORT_SYMBOL_GPL(load_iotlb_entry);
-
-/**
- * flush_iotlb_page - Clear an iommu tlb entry
- * @obj:	target iommu
- * @da:		iommu device virtual address
- *
- * Clear an iommu tlb entry which includes 'da' address.
- **/
-void flush_iotlb_page(struct iommu *obj, u32 da)
-{
-	int i;
-	struct cr_regs cr;
-
-	clk_enable(obj->clk);
-
-	for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) {
-		u32 start;
-		size_t bytes;
-
-		if (!iotlb_cr_valid(&cr))
-			continue;
-
-		start = iotlb_cr_to_virt(&cr);
-		bytes = iopgsz_to_bytes(cr.cam & 3);
-
-		if ((start <= da) && (da < start + bytes)) {
-			dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n",
-				__func__, start, da, bytes);
-			iotlb_load_cr(obj, &cr);
-			iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
-		}
-	}
-	clk_disable(obj->clk);
-
-	if (i == obj->nr_tlb_entries)
-		dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da);
-}
-EXPORT_SYMBOL_GPL(flush_iotlb_page);
-
-/**
- * flush_iotlb_range - Clear an iommu tlb entries
- * @obj:	target iommu
- * @start:	iommu device virtual address(start)
- * @end:	iommu device virtual address(end)
- *
- * Clear an iommu tlb entry which includes 'da' address.
- **/
-void flush_iotlb_range(struct iommu *obj, u32 start, u32 end)
-{
-	u32 da = start;
-
-	while (da < end) {
-		flush_iotlb_page(obj, da);
-		/* FIXME: Optimize for multiple page size */
-		da += IOPTE_SIZE;
-	}
-}
-EXPORT_SYMBOL_GPL(flush_iotlb_range);
-
-/**
- * flush_iotlb_all - Clear all iommu tlb entries
- * @obj:	target iommu
- **/
-void flush_iotlb_all(struct iommu *obj)
-{
-	struct iotlb_lock l;
-
-	clk_enable(obj->clk);
-
-	l.base = 0;
-	l.vict = 0;
-	iotlb_lock_set(obj, &l);
-
-	iommu_write_reg(obj, 1, MMU_GFLUSH);
-
-	clk_disable(obj->clk);
-}
-EXPORT_SYMBOL_GPL(flush_iotlb_all);
-
-/**
- * iommu_set_twl - enable/disable table walking logic
- * @obj:	target iommu
- * @on:		enable/disable
- *
- * Function used to enable/disable TWL. If one wants to work
- * exclusively with locked TLB entries and receive notifications
- * for TLB miss then call this function to disable TWL.
- */
-void iommu_set_twl(struct iommu *obj, bool on)
-{
-	clk_enable(obj->clk);
-	arch_iommu->set_twl(obj, on);
-	clk_disable(obj->clk);
-}
-EXPORT_SYMBOL_GPL(iommu_set_twl);
-
-#if defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
-
-ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t bytes)
-{
-	if (!obj || !buf)
-		return -EINVAL;
-
-	clk_enable(obj->clk);
-
-	bytes = arch_iommu->dump_ctx(obj, buf, bytes);
-
-	clk_disable(obj->clk);
-
-	return bytes;
-}
-EXPORT_SYMBOL_GPL(iommu_dump_ctx);
-
-static int __dump_tlb_entries(struct iommu *obj, struct cr_regs *crs, int num)
-{
-	int i;
-	struct iotlb_lock saved;
-	struct cr_regs tmp;
-	struct cr_regs *p = crs;
-
-	clk_enable(obj->clk);
-	iotlb_lock_get(obj, &saved);
-
-	for_each_iotlb_cr(obj, num, i, tmp) {
-		if (!iotlb_cr_valid(&tmp))
-			continue;
-		*p++ = tmp;
-	}
-
-	iotlb_lock_set(obj, &saved);
-	clk_disable(obj->clk);
-
-	return  p - crs;
-}
-
-/**
- * dump_tlb_entries - dump cr arrays to given buffer
- * @obj:	target iommu
- * @buf:	output buffer
- **/
-size_t dump_tlb_entries(struct iommu *obj, char *buf, ssize_t bytes)
-{
-	int i, num;
-	struct cr_regs *cr;
-	char *p = buf;
-
-	num = bytes / sizeof(*cr);
-	num = min(obj->nr_tlb_entries, num);
-
-	cr = kcalloc(num, sizeof(*cr), GFP_KERNEL);
-	if (!cr)
-		return 0;
-
-	num = __dump_tlb_entries(obj, cr, num);
-	for (i = 0; i < num; i++)
-		p += iotlb_dump_cr(obj, cr + i, p);
-	kfree(cr);
-
-	return p - buf;
-}
-EXPORT_SYMBOL_GPL(dump_tlb_entries);
-
-int foreach_iommu_device(void *data, int (*fn)(struct device *, void *))
-{
-	return driver_for_each_device(&omap_iommu_driver.driver,
-				      NULL, data, fn);
-}
-EXPORT_SYMBOL_GPL(foreach_iommu_device);
-
-#endif /* CONFIG_OMAP_IOMMU_DEBUG_MODULE */
-
-/*
- *	H/W pagetable operations
- */
-static void flush_iopgd_range(u32 *first, u32 *last)
-{
-	/* FIXME: L2 cache should be taken care of if it exists */
-	do {
-		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pgd"
-		    : : "r" (first));
-		first += L1_CACHE_BYTES / sizeof(*first);
-	} while (first <= last);
-}
-
-static void flush_iopte_range(u32 *first, u32 *last)
-{
-	/* FIXME: L2 cache should be taken care of if it exists */
-	do {
-		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pte"
-		    : : "r" (first));
-		first += L1_CACHE_BYTES / sizeof(*first);
-	} while (first <= last);
-}
-
-static void iopte_free(u32 *iopte)
-{
-	/* Note: freed iopte's must be clean ready for re-use */
-	kmem_cache_free(iopte_cachep, iopte);
-}
-
-static u32 *iopte_alloc(struct iommu *obj, u32 *iopgd, u32 da)
-{
-	u32 *iopte;
-
-	/* a table has already existed */
-	if (*iopgd)
-		goto pte_ready;
-
-	/*
-	 * do the allocation outside the page table lock
-	 */
-	spin_unlock(&obj->page_table_lock);
-	iopte = kmem_cache_zalloc(iopte_cachep, GFP_KERNEL);
-	spin_lock(&obj->page_table_lock);
-
-	if (!*iopgd) {
-		if (!iopte)
-			return ERR_PTR(-ENOMEM);
-
-		*iopgd = virt_to_phys(iopte) | IOPGD_TABLE;
-		flush_iopgd_range(iopgd, iopgd);
-
-		dev_vdbg(obj->dev, "%s: a new pte:%p\n", __func__, iopte);
-	} else {
-		/* We raced, free the reduniovant table */
-		iopte_free(iopte);
-	}
-
-pte_ready:
-	iopte = iopte_offset(iopgd, da);
-
-	dev_vdbg(obj->dev,
-		 "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n",
-		 __func__, da, iopgd, *iopgd, iopte, *iopte);
-
-	return iopte;
-}
-
-static int iopgd_alloc_section(struct iommu *obj, u32 da, u32 pa, u32 prot)
-{
-	u32 *iopgd = iopgd_offset(obj, da);
-
-	if ((da | pa) & ~IOSECTION_MASK) {
-		dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
-			__func__, da, pa, IOSECTION_SIZE);
-		return -EINVAL;
-	}
-
-	*iopgd = (pa & IOSECTION_MASK) | prot | IOPGD_SECTION;
-	flush_iopgd_range(iopgd, iopgd);
-	return 0;
-}
-
-static int iopgd_alloc_super(struct iommu *obj, u32 da, u32 pa, u32 prot)
-{
-	u32 *iopgd = iopgd_offset(obj, da);
-	int i;
-
-	if ((da | pa) & ~IOSUPER_MASK) {
-		dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
-			__func__, da, pa, IOSUPER_SIZE);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < 16; i++)
-		*(iopgd + i) = (pa & IOSUPER_MASK) | prot | IOPGD_SUPER;
-	flush_iopgd_range(iopgd, iopgd + 15);
-	return 0;
-}
-
-static int iopte_alloc_page(struct iommu *obj, u32 da, u32 pa, u32 prot)
-{
-	u32 *iopgd = iopgd_offset(obj, da);
-	u32 *iopte = iopte_alloc(obj, iopgd, da);
-
-	if (IS_ERR(iopte))
-		return PTR_ERR(iopte);
-
-	*iopte = (pa & IOPAGE_MASK) | prot | IOPTE_SMALL;
-	flush_iopte_range(iopte, iopte);
-
-	dev_vdbg(obj->dev, "%s: da:%08x pa:%08x pte:%p *pte:%08x\n",
-		 __func__, da, pa, iopte, *iopte);
-
-	return 0;
-}
-
-static int iopte_alloc_large(struct iommu *obj, u32 da, u32 pa, u32 prot)
-{
-	u32 *iopgd = iopgd_offset(obj, da);
-	u32 *iopte = iopte_alloc(obj, iopgd, da);
-	int i;
-
-	if ((da | pa) & ~IOLARGE_MASK) {
-		dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
-			__func__, da, pa, IOLARGE_SIZE);
-		return -EINVAL;
-	}
-
-	if (IS_ERR(iopte))
-		return PTR_ERR(iopte);
-
-	for (i = 0; i < 16; i++)
-		*(iopte + i) = (pa & IOLARGE_MASK) | prot | IOPTE_LARGE;
-	flush_iopte_range(iopte, iopte + 15);
-	return 0;
-}
-
-static int iopgtable_store_entry_core(struct iommu *obj, struct iotlb_entry *e)
-{
-	int (*fn)(struct iommu *, u32, u32, u32);
-	u32 prot;
-	int err;
-
-	if (!obj || !e)
-		return -EINVAL;
-
-	switch (e->pgsz) {
-	case MMU_CAM_PGSZ_16M:
-		fn = iopgd_alloc_super;
-		break;
-	case MMU_CAM_PGSZ_1M:
-		fn = iopgd_alloc_section;
-		break;
-	case MMU_CAM_PGSZ_64K:
-		fn = iopte_alloc_large;
-		break;
-	case MMU_CAM_PGSZ_4K:
-		fn = iopte_alloc_page;
-		break;
-	default:
-		fn = NULL;
-		BUG();
-		break;
-	}
-
-	prot = get_iopte_attr(e);
-
-	spin_lock(&obj->page_table_lock);
-	err = fn(obj, e->da, e->pa, prot);
-	spin_unlock(&obj->page_table_lock);
-
-	return err;
-}
-
-/**
- * iopgtable_store_entry - Make an iommu pte entry
- * @obj:	target iommu
- * @e:		an iommu tlb entry info
- **/
-int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e)
-{
-	int err;
-
-	flush_iotlb_page(obj, e->da);
-	err = iopgtable_store_entry_core(obj, e);
-#ifdef PREFETCH_IOTLB
-	if (!err)
-		load_iotlb_entry(obj, e);
-#endif
-	return err;
-}
-EXPORT_SYMBOL_GPL(iopgtable_store_entry);
-
-/**
- * iopgtable_lookup_entry - Lookup an iommu pte entry
- * @obj:	target iommu
- * @da:		iommu device virtual address
- * @ppgd:	iommu pgd entry pointer to be returned
- * @ppte:	iommu pte entry pointer to be returned
- **/
-void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd, u32 **ppte)
-{
-	u32 *iopgd, *iopte = NULL;
-
-	iopgd = iopgd_offset(obj, da);
-	if (!*iopgd)
-		goto out;
-
-	if (iopgd_is_table(*iopgd))
-		iopte = iopte_offset(iopgd, da);
-out:
-	*ppgd = iopgd;
-	*ppte = iopte;
-}
-EXPORT_SYMBOL_GPL(iopgtable_lookup_entry);
-
-static size_t iopgtable_clear_entry_core(struct iommu *obj, u32 da)
-{
-	size_t bytes;
-	u32 *iopgd = iopgd_offset(obj, da);
-	int nent = 1;
-
-	if (!*iopgd)
-		return 0;
-
-	if (iopgd_is_table(*iopgd)) {
-		int i;
-		u32 *iopte = iopte_offset(iopgd, da);
-
-		bytes = IOPTE_SIZE;
-		if (*iopte & IOPTE_LARGE) {
-			nent *= 16;
-			/* rewind to the 1st entry */
-			iopte = iopte_offset(iopgd, (da & IOLARGE_MASK));
-		}
-		bytes *= nent;
-		memset(iopte, 0, nent * sizeof(*iopte));
-		flush_iopte_range(iopte, iopte + (nent - 1) * sizeof(*iopte));
-
-		/*
-		 * do table walk to check if this table is necessary or not
-		 */
-		iopte = iopte_offset(iopgd, 0);
-		for (i = 0; i < PTRS_PER_IOPTE; i++)
-			if (iopte[i])
-				goto out;
-
-		iopte_free(iopte);
-		nent = 1; /* for the next L1 entry */
-	} else {
-		bytes = IOPGD_SIZE;
-		if ((*iopgd & IOPGD_SUPER) == IOPGD_SUPER) {
-			nent *= 16;
-			/* rewind to the 1st entry */
-			iopgd = iopgd_offset(obj, (da & IOSUPER_MASK));
-		}
-		bytes *= nent;
-	}
-	memset(iopgd, 0, nent * sizeof(*iopgd));
-	flush_iopgd_range(iopgd, iopgd + (nent - 1) * sizeof(*iopgd));
-out:
-	return bytes;
-}
-
-/**
- * iopgtable_clear_entry - Remove an iommu pte entry
- * @obj:	target iommu
- * @da:		iommu device virtual address
- **/
-size_t iopgtable_clear_entry(struct iommu *obj, u32 da)
-{
-	size_t bytes;
-
-	spin_lock(&obj->page_table_lock);
-
-	bytes = iopgtable_clear_entry_core(obj, da);
-	flush_iotlb_page(obj, da);
-
-	spin_unlock(&obj->page_table_lock);
-
-	return bytes;
-}
-EXPORT_SYMBOL_GPL(iopgtable_clear_entry);
-
-static void iopgtable_clear_entry_all(struct iommu *obj)
-{
-	int i;
-
-	spin_lock(&obj->page_table_lock);
-
-	for (i = 0; i < PTRS_PER_IOPGD; i++) {
-		u32 da;
-		u32 *iopgd;
-
-		da = i << IOPGD_SHIFT;
-		iopgd = iopgd_offset(obj, da);
-
-		if (!*iopgd)
-			continue;
-
-		if (iopgd_is_table(*iopgd))
-			iopte_free(iopte_offset(iopgd, 0));
-
-		*iopgd = 0;
-		flush_iopgd_range(iopgd, iopgd);
-	}
-
-	flush_iotlb_all(obj);
-
-	spin_unlock(&obj->page_table_lock);
-}
-
-/*
- *	Device IOMMU generic operations
- */
-static irqreturn_t iommu_fault_handler(int irq, void *data)
-{
-	u32 da, errs;
-	u32 *iopgd, *iopte;
-	struct iommu *obj = data;
-
-	if (!obj->refcount)
-		return IRQ_NONE;
-
-	clk_enable(obj->clk);
-	errs = iommu_report_fault(obj, &da);
-	clk_disable(obj->clk);
-	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);
-
-	iopgd = iopgd_offset(obj, da);
-
-	if (!iopgd_is_table(*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: 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;
-}
-
-static int device_match_by_alias(struct device *dev, void *data)
-{
-	struct iommu *obj = to_iommu(dev);
-	const char *name = data;
-
-	pr_debug("%s: %s %s\n", __func__, obj->name, name);
-
-	return strcmp(obj->name, name) == 0;
-}
-
-/**
- * iommu_set_da_range - Set a valid device address range
- * @obj:		target iommu
- * @start		Start of valid range
- * @end			End of valid range
- **/
-int iommu_set_da_range(struct iommu *obj, u32 start, u32 end)
-{
-
-	if (!obj)
-		return -EFAULT;
-
-	if (end < start || !PAGE_ALIGN(start | end))
-		return -EINVAL;
-
-	obj->da_start = start;
-	obj->da_end = end;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(iommu_set_da_range);
-
-/**
- * iommu_get - Get iommu handler
- * @name:	target iommu name
- **/
-struct iommu *iommu_get(const char *name)
-{
-	int err = -ENOMEM;
-	struct device *dev;
-	struct iommu *obj;
-
-	dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name,
-				 device_match_by_alias);
-	if (!dev)
-		return ERR_PTR(-ENODEV);
-
-	obj = to_iommu(dev);
-
-	mutex_lock(&obj->iommu_lock);
-
-	if (obj->refcount++ == 0) {
-		err = iommu_enable(obj);
-		if (err)
-			goto err_enable;
-		flush_iotlb_all(obj);
-	}
-
-	if (!try_module_get(obj->owner))
-		goto err_module;
-
-	mutex_unlock(&obj->iommu_lock);
-
-	dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
-	return obj;
-
-err_module:
-	if (obj->refcount == 1)
-		iommu_disable(obj);
-err_enable:
-	obj->refcount--;
-	mutex_unlock(&obj->iommu_lock);
-	return ERR_PTR(err);
-}
-EXPORT_SYMBOL_GPL(iommu_get);
-
-/**
- * iommu_put - Put back iommu handler
- * @obj:	target iommu
- **/
-void iommu_put(struct iommu *obj)
-{
-	if (!obj || IS_ERR(obj))
-		return;
-
-	mutex_lock(&obj->iommu_lock);
-
-	if (--obj->refcount == 0)
-		iommu_disable(obj);
-
-	module_put(obj->owner);
-
-	mutex_unlock(&obj->iommu_lock);
-
-	dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
-}
-EXPORT_SYMBOL_GPL(iommu_put);
-
-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
- */
-static int __devinit omap_iommu_probe(struct platform_device *pdev)
-{
-	int err = -ENODEV;
-	void *p;
-	int irq;
-	struct iommu *obj;
-	struct resource *res;
-	struct iommu_platform_data *pdata = pdev->dev.platform_data;
-
-	if (pdev->num_resources != 2)
-		return -EINVAL;
-
-	obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
-	if (!obj)
-		return -ENOMEM;
-
-	obj->clk = clk_get(&pdev->dev, pdata->clk_name);
-	if (IS_ERR(obj->clk))
-		goto err_clk;
-
-	obj->nr_tlb_entries = pdata->nr_tlb_entries;
-	obj->name = pdata->name;
-	obj->dev = &pdev->dev;
-	obj->ctx = (void *)obj + sizeof(*obj);
-	obj->da_start = pdata->da_start;
-	obj->da_end = pdata->da_end;
-
-	mutex_init(&obj->iommu_lock);
-	mutex_init(&obj->mmap_lock);
-	spin_lock_init(&obj->page_table_lock);
-	INIT_LIST_HEAD(&obj->mmap);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		err = -ENODEV;
-		goto err_mem;
-	}
-
-	res = request_mem_region(res->start, resource_size(res),
-				 dev_name(&pdev->dev));
-	if (!res) {
-		err = -EIO;
-		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;
-		goto err_irq;
-	}
-	err = request_irq(irq, iommu_fault_handler, IRQF_SHARED,
-			  dev_name(&pdev->dev), obj);
-	if (err < 0)
-		goto err_irq;
-	platform_set_drvdata(pdev, obj);
-
-	p = (void *)__get_free_pages(GFP_KERNEL, get_order(IOPGD_TABLE_SIZE));
-	if (!p) {
-		err = -ENOMEM;
-		goto err_pgd;
-	}
-	memset(p, 0, IOPGD_TABLE_SIZE);
-	clean_dcache_area(p, IOPGD_TABLE_SIZE);
-	obj->iopgd = p;
-
-	BUG_ON(!IS_ALIGNED((unsigned long)obj->iopgd, IOPGD_TABLE_SIZE));
-
-	dev_info(&pdev->dev, "%s registered\n", obj->name);
-	return 0;
-
-err_pgd:
-	free_irq(irq, obj);
-err_irq:
-	iounmap(obj->regbase);
-err_ioremap:
-	release_mem_region(res->start, resource_size(res));
-err_mem:
-	clk_put(obj->clk);
-err_clk:
-	kfree(obj);
-	return err;
-}
-
-static int __devexit omap_iommu_remove(struct platform_device *pdev)
-{
-	int irq;
-	struct resource *res;
-	struct iommu *obj = platform_get_drvdata(pdev);
-
-	platform_set_drvdata(pdev, NULL);
-
-	iopgtable_clear_entry_all(obj);
-	free_pages((unsigned long)obj->iopgd, get_order(IOPGD_TABLE_SIZE));
-
-	irq = platform_get_irq(pdev, 0);
-	free_irq(irq, obj);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-	iounmap(obj->regbase);
-
-	clk_put(obj->clk);
-	dev_info(&pdev->dev, "%s removed\n", obj->name);
-	kfree(obj);
-	return 0;
-}
-
-static struct platform_driver omap_iommu_driver = {
-	.probe	= omap_iommu_probe,
-	.remove	= __devexit_p(omap_iommu_remove),
-	.driver	= {
-		.name	= "omap-iommu",
-	},
-};
-
-static void iopte_cachep_ctor(void *iopte)
-{
-	clean_dcache_area(iopte, IOPTE_TABLE_SIZE);
-}
-
-static int __init omap_iommu_init(void)
-{
-	struct kmem_cache *p;
-	const unsigned long flags = SLAB_HWCACHE_ALIGN;
-	size_t align = 1 << 10; /* L2 pagetable alignement */
-
-	p = kmem_cache_create("iopte_cache", IOPTE_TABLE_SIZE, align, flags,
-			      iopte_cachep_ctor);
-	if (!p)
-		return -ENOMEM;
-	iopte_cachep = p;
-
-	return platform_driver_register(&omap_iommu_driver);
-}
-module_init(omap_iommu_init);
-
-static void __exit omap_iommu_exit(void)
-{
-	kmem_cache_destroy(iopte_cachep);
-
-	platform_driver_unregister(&omap_iommu_driver);
-}
-module_exit(omap_iommu_exit);
-
-MODULE_DESCRIPTION("omap iommu: tlb and pagetable primitives");
-MODULE_ALIAS("platform:omap-iommu");
-MODULE_AUTHOR("Hiroshi DOYU, Paul Mundt and Toshihiro Kobayashi");
-MODULE_LICENSE("GPL v2");
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/iommu-debug.c linux-libre-3.2-gnu/arch/arm/plat-omap/iommu-debug.c
--- linux-libre-3.1-gnu/arch/arm/plat-omap/iommu-debug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/iommu-debug.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,418 +0,0 @@
-/*
- * omap iommu: debugfs interface
- *
- * Copyright (C) 2008-2009 Nokia Corporation
- *
- * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/platform_device.h>
-#include <linux/debugfs.h>
-
-#include <plat/iommu.h>
-#include <plat/iovmm.h>
-
-#include "iopgtable.h"
-
-#define MAXCOLUMN 100 /* for short messages */
-
-static DEFINE_MUTEX(iommu_debug_lock);
-
-static struct dentry *iommu_debug_root;
-
-static ssize_t debug_read_ver(struct file *file, char __user *userbuf,
-			      size_t count, loff_t *ppos)
-{
-	u32 ver = iommu_arch_version();
-	char buf[MAXCOLUMN], *p = buf;
-
-	p += sprintf(p, "H/W version: %d.%d\n", (ver >> 4) & 0xf , ver & 0xf);
-
-	return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-}
-
-static ssize_t debug_read_regs(struct file *file, char __user *userbuf,
-			       size_t count, loff_t *ppos)
-{
-	struct iommu *obj = file->private_data;
-	char *p, *buf;
-	ssize_t bytes;
-
-	buf = kmalloc(count, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	p = buf;
-
-	mutex_lock(&iommu_debug_lock);
-
-	bytes = iommu_dump_ctx(obj, p, count);
-	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, bytes);
-
-	mutex_unlock(&iommu_debug_lock);
-	kfree(buf);
-
-	return bytes;
-}
-
-static ssize_t debug_read_tlb(struct file *file, char __user *userbuf,
-			      size_t count, loff_t *ppos)
-{
-	struct iommu *obj = file->private_data;
-	char *p, *buf;
-	ssize_t bytes, rest;
-
-	buf = kmalloc(count, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	p = buf;
-
-	mutex_lock(&iommu_debug_lock);
-
-	p += sprintf(p, "%8s %8s\n", "cam:", "ram:");
-	p += sprintf(p, "-----------------------------------------\n");
-	rest = count - (p - buf);
-	p += dump_tlb_entries(obj, p, rest);
-
-	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-
-	mutex_unlock(&iommu_debug_lock);
-	kfree(buf);
-
-	return bytes;
-}
-
-static ssize_t debug_write_pagetable(struct file *file,
-		     const char __user *userbuf, size_t count, loff_t *ppos)
-{
-	struct iotlb_entry e;
-	struct cr_regs cr;
-	int err;
-	struct iommu *obj = file->private_data;
-	char buf[MAXCOLUMN], *p = buf;
-
-	count = min(count, sizeof(buf));
-
-	mutex_lock(&iommu_debug_lock);
-	if (copy_from_user(p, userbuf, count)) {
-		mutex_unlock(&iommu_debug_lock);
-		return -EFAULT;
-	}
-
-	sscanf(p, "%x %x", &cr.cam, &cr.ram);
-	if (!cr.cam || !cr.ram) {
-		mutex_unlock(&iommu_debug_lock);
-		return -EINVAL;
-	}
-
-	iotlb_cr_to_e(&cr, &e);
-	err = iopgtable_store_entry(obj, &e);
-	if (err)
-		dev_err(obj->dev, "%s: fail to store cr\n", __func__);
-
-	mutex_unlock(&iommu_debug_lock);
-	return count;
-}
-
-#define dump_ioptable_entry_one(lv, da, val)			\
-	({							\
-		int __err = 0;					\
-		ssize_t bytes;					\
-		const int maxcol = 22;				\
-		const char *str = "%d: %08x %08x\n";		\
-		bytes = snprintf(p, maxcol, str, lv, da, val);	\
-		p += bytes;					\
-		len -= bytes;					\
-		if (len < maxcol)				\
-			__err = -ENOMEM;			\
-		__err;						\
-	})
-
-static ssize_t dump_ioptable(struct iommu *obj, char *buf, ssize_t len)
-{
-	int i;
-	u32 *iopgd;
-	char *p = buf;
-
-	spin_lock(&obj->page_table_lock);
-
-	iopgd = iopgd_offset(obj, 0);
-	for (i = 0; i < PTRS_PER_IOPGD; i++, iopgd++) {
-		int j, err;
-		u32 *iopte;
-		u32 da;
-
-		if (!*iopgd)
-			continue;
-
-		if (!(*iopgd & IOPGD_TABLE)) {
-			da = i << IOPGD_SHIFT;
-
-			err = dump_ioptable_entry_one(1, da, *iopgd);
-			if (err)
-				goto out;
-			continue;
-		}
-
-		iopte = iopte_offset(iopgd, 0);
-
-		for (j = 0; j < PTRS_PER_IOPTE; j++, iopte++) {
-			if (!*iopte)
-				continue;
-
-			da = (i << IOPGD_SHIFT) + (j << IOPTE_SHIFT);
-			err = dump_ioptable_entry_one(2, da, *iopgd);
-			if (err)
-				goto out;
-		}
-	}
-out:
-	spin_unlock(&obj->page_table_lock);
-
-	return p - buf;
-}
-
-static ssize_t debug_read_pagetable(struct file *file, char __user *userbuf,
-				    size_t count, loff_t *ppos)
-{
-	struct iommu *obj = file->private_data;
-	char *p, *buf;
-	size_t bytes;
-
-	buf = (char *)__get_free_page(GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	p = buf;
-
-	p += sprintf(p, "L: %8s %8s\n", "da:", "pa:");
-	p += sprintf(p, "-----------------------------------------\n");
-
-	mutex_lock(&iommu_debug_lock);
-
-	bytes = PAGE_SIZE - (p - buf);
-	p += dump_ioptable(obj, p, bytes);
-
-	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-
-	mutex_unlock(&iommu_debug_lock);
-	free_page((unsigned long)buf);
-
-	return bytes;
-}
-
-static ssize_t debug_read_mmap(struct file *file, char __user *userbuf,
-			       size_t count, loff_t *ppos)
-{
-	struct iommu *obj = file->private_data;
-	char *p, *buf;
-	struct iovm_struct *tmp;
-	int uninitialized_var(i);
-	ssize_t bytes;
-
-	buf = (char *)__get_free_page(GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	p = buf;
-
-	p += sprintf(p, "%-3s %-8s %-8s %6s %8s\n",
-		     "No", "start", "end", "size", "flags");
-	p += sprintf(p, "-------------------------------------------------\n");
-
-	mutex_lock(&iommu_debug_lock);
-
-	list_for_each_entry(tmp, &obj->mmap, list) {
-		size_t len;
-		const char *str = "%3d %08x-%08x %6x %8x\n";
-		const int maxcol = 39;
-
-		len = tmp->da_end - tmp->da_start;
-		p += snprintf(p, maxcol, str,
-			      i, tmp->da_start, tmp->da_end, len, tmp->flags);
-
-		if (PAGE_SIZE - (p - buf) < maxcol)
-			break;
-		i++;
-	}
-
-	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-
-	mutex_unlock(&iommu_debug_lock);
-	free_page((unsigned long)buf);
-
-	return bytes;
-}
-
-static ssize_t debug_read_mem(struct file *file, char __user *userbuf,
-			      size_t count, loff_t *ppos)
-{
-	struct iommu *obj = file->private_data;
-	char *p, *buf;
-	struct iovm_struct *area;
-	ssize_t bytes;
-
-	count = min_t(ssize_t, count, PAGE_SIZE);
-
-	buf = (char *)__get_free_page(GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	p = buf;
-
-	mutex_lock(&iommu_debug_lock);
-
-	area = find_iovm_area(obj, (u32)ppos);
-	if (IS_ERR(area)) {
-		bytes = -EINVAL;
-		goto err_out;
-	}
-	memcpy(p, area->va, count);
-	p += count;
-
-	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-err_out:
-	mutex_unlock(&iommu_debug_lock);
-	free_page((unsigned long)buf);
-
-	return bytes;
-}
-
-static ssize_t debug_write_mem(struct file *file, const char __user *userbuf,
-			       size_t count, loff_t *ppos)
-{
-	struct iommu *obj = file->private_data;
-	struct iovm_struct *area;
-	char *p, *buf;
-
-	count = min_t(size_t, count, PAGE_SIZE);
-
-	buf = (char *)__get_free_page(GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	p = buf;
-
-	mutex_lock(&iommu_debug_lock);
-
-	if (copy_from_user(p, userbuf, count)) {
-		count =  -EFAULT;
-		goto err_out;
-	}
-
-	area = find_iovm_area(obj, (u32)ppos);
-	if (IS_ERR(area)) {
-		count = -EINVAL;
-		goto err_out;
-	}
-	memcpy(area->va, p, count);
-err_out:
-	mutex_unlock(&iommu_debug_lock);
-	free_page((unsigned long)buf);
-
-	return count;
-}
-
-static int debug_open_generic(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-#define DEBUG_FOPS(name)						\
-	static const struct file_operations debug_##name##_fops = {	\
-		.open = debug_open_generic,				\
-		.read = debug_read_##name,				\
-		.write = debug_write_##name,				\
-		.llseek = generic_file_llseek,				\
-	};
-
-#define DEBUG_FOPS_RO(name)						\
-	static const struct file_operations debug_##name##_fops = {	\
-		.open = debug_open_generic,				\
-		.read = debug_read_##name,				\
-		.llseek = generic_file_llseek,				\
-	};
-
-DEBUG_FOPS_RO(ver);
-DEBUG_FOPS_RO(regs);
-DEBUG_FOPS_RO(tlb);
-DEBUG_FOPS(pagetable);
-DEBUG_FOPS_RO(mmap);
-DEBUG_FOPS(mem);
-
-#define __DEBUG_ADD_FILE(attr, mode)					\
-	{								\
-		struct dentry *dent;					\
-		dent = debugfs_create_file(#attr, mode, parent,		\
-					   obj, &debug_##attr##_fops);	\
-		if (!dent)						\
-			return -ENOMEM;					\
-	}
-
-#define DEBUG_ADD_FILE(name) __DEBUG_ADD_FILE(name, 600)
-#define DEBUG_ADD_FILE_RO(name) __DEBUG_ADD_FILE(name, 400)
-
-static int iommu_debug_register(struct device *dev, void *data)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct iommu *obj = platform_get_drvdata(pdev);
-	struct dentry *d, *parent;
-
-	if (!obj || !obj->dev)
-		return -EINVAL;
-
-	d = debugfs_create_dir(obj->name, iommu_debug_root);
-	if (!d)
-		return -ENOMEM;
-	parent = d;
-
-	d = debugfs_create_u8("nr_tlb_entries", 400, parent,
-			      (u8 *)&obj->nr_tlb_entries);
-	if (!d)
-		return -ENOMEM;
-
-	DEBUG_ADD_FILE_RO(ver);
-	DEBUG_ADD_FILE_RO(regs);
-	DEBUG_ADD_FILE_RO(tlb);
-	DEBUG_ADD_FILE(pagetable);
-	DEBUG_ADD_FILE_RO(mmap);
-	DEBUG_ADD_FILE(mem);
-
-	return 0;
-}
-
-static int __init iommu_debug_init(void)
-{
-	struct dentry *d;
-	int err;
-
-	d = debugfs_create_dir("iommu", NULL);
-	if (!d)
-		return -ENOMEM;
-	iommu_debug_root = d;
-
-	err = foreach_iommu_device(d, iommu_debug_register);
-	if (err)
-		goto err_out;
-	return 0;
-
-err_out:
-	debugfs_remove_recursive(iommu_debug_root);
-	return err;
-}
-module_init(iommu_debug_init)
-
-static void __exit iommu_debugfs_exit(void)
-{
-	debugfs_remove_recursive(iommu_debug_root);
-}
-module_exit(iommu_debugfs_exit)
-
-MODULE_DESCRIPTION("omap iommu: debugfs interface");
-MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
-MODULE_LICENSE("GPL v2");
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/iopgtable.h linux-libre-3.2-gnu/arch/arm/plat-omap/iopgtable.h
--- linux-libre-3.1-gnu/arch/arm/plat-omap/iopgtable.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/iopgtable.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,102 +0,0 @@
-/*
- * omap iommu: pagetable definitions
- *
- * Copyright (C) 2008-2010 Nokia Corporation
- *
- * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __PLAT_OMAP_IOMMU_H
-#define __PLAT_OMAP_IOMMU_H
-
-/*
- * "L2 table" address mask and size definitions.
- */
-#define IOPGD_SHIFT		20
-#define IOPGD_SIZE		(1UL << IOPGD_SHIFT)
-#define IOPGD_MASK		(~(IOPGD_SIZE - 1))
-
-/*
- * "section" address mask and size definitions.
- */
-#define IOSECTION_SHIFT		20
-#define IOSECTION_SIZE		(1UL << IOSECTION_SHIFT)
-#define IOSECTION_MASK		(~(IOSECTION_SIZE - 1))
-
-/*
- * "supersection" address mask and size definitions.
- */
-#define IOSUPER_SHIFT		24
-#define IOSUPER_SIZE		(1UL << IOSUPER_SHIFT)
-#define IOSUPER_MASK		(~(IOSUPER_SIZE - 1))
-
-#define PTRS_PER_IOPGD		(1UL << (32 - IOPGD_SHIFT))
-#define IOPGD_TABLE_SIZE	(PTRS_PER_IOPGD * sizeof(u32))
-
-/*
- * "small page" address mask and size definitions.
- */
-#define IOPTE_SHIFT		12
-#define IOPTE_SIZE		(1UL << IOPTE_SHIFT)
-#define IOPTE_MASK		(~(IOPTE_SIZE - 1))
-
-/*
- * "large page" address mask and size definitions.
- */
-#define IOLARGE_SHIFT		16
-#define IOLARGE_SIZE		(1UL << IOLARGE_SHIFT)
-#define IOLARGE_MASK		(~(IOLARGE_SIZE - 1))
-
-#define PTRS_PER_IOPTE		(1UL << (IOPGD_SHIFT - IOPTE_SHIFT))
-#define IOPTE_TABLE_SIZE	(PTRS_PER_IOPTE * sizeof(u32))
-
-#define IOPAGE_MASK		IOPTE_MASK
-
-/*
- * some descriptor attributes.
- */
-#define IOPGD_TABLE		(1 << 0)
-#define IOPGD_SECTION		(2 << 0)
-#define IOPGD_SUPER		(1 << 18 | 2 << 0)
-
-#define iopgd_is_table(x)	(((x) & 3) == IOPGD_TABLE)
-
-#define IOPTE_SMALL		(2 << 0)
-#define IOPTE_LARGE		(1 << 0)
-
-/* to find an entry in a page-table-directory */
-#define iopgd_index(da)		(((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1))
-#define iopgd_offset(obj, da)	((obj)->iopgd + iopgd_index(da))
-
-#define iopgd_page_paddr(iopgd)	(*iopgd & ~((1 << 10) - 1))
-#define iopgd_page_vaddr(iopgd)	((u32 *)phys_to_virt(iopgd_page_paddr(iopgd)))
-
-/* to find an entry in the second-level page table. */
-#define iopte_index(da)		(((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1))
-#define iopte_offset(iopgd, da)	(iopgd_page_vaddr(iopgd) + iopte_index(da))
-
-static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa,
-				   u32 flags)
-{
-	memset(e, 0, sizeof(*e));
-
-	e->da		= da;
-	e->pa		= pa;
-	e->valid	= 1;
-	/* FIXME: add OMAP1 support */
-	e->pgsz		= flags & MMU_CAM_PGSZ_MASK;
-	e->endian	= flags & MMU_RAM_ENDIAN_MASK;
-	e->elsz		= flags & MMU_RAM_ELSZ_MASK;
-	e->mixed	= flags & MMU_RAM_MIXED_MASK;
-
-	return iopgsz_to_bytes(e->pgsz);
-}
-
-#define to_iommu(dev)							\
-	(struct iommu *)platform_get_drvdata(to_platform_device(dev))
-
-#endif /* __PLAT_OMAP_IOMMU_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/iovmm.c linux-libre-3.2-gnu/arch/arm/plat-omap/iovmm.c
--- linux-libre-3.1-gnu/arch/arm/plat-omap/iovmm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/iovmm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,904 +0,0 @@
-/*
- * omap iommu: simple virtual address space management
- *
- * Copyright (C) 2008-2009 Nokia Corporation
- *
- * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/device.h>
-#include <linux/scatterlist.h>
-
-#include <asm/cacheflush.h>
-#include <asm/mach/map.h>
-
-#include <plat/iommu.h>
-#include <plat/iovmm.h>
-
-#include "iopgtable.h"
-
-/*
- * A device driver needs to create address mappings between:
- *
- * - iommu/device address
- * - physical address
- * - mpu virtual address
- *
- * There are 4 possible patterns for them:
- *
- *    |iova/			  mapping		iommu_		page
- *    | da	pa	va	(d)-(p)-(v)		function	type
- *  ---------------------------------------------------------------------------
- *  1 | c	c	c	 1 - 1 - 1	  _kmap() / _kunmap()	s
- *  2 | c	c,a	c	 1 - 1 - 1	_kmalloc()/ _kfree()	s
- *  3 | c	d	c	 1 - n - 1	  _vmap() / _vunmap()	s
- *  4 | c	d,a	c	 1 - n - 1	_vmalloc()/ _vfree()	n*
- *
- *
- *	'iova':	device iommu virtual address
- *	'da':	alias of 'iova'
- *	'pa':	physical address
- *	'va':	mpu virtual address
- *
- *	'c':	contiguous memory area
- *	'd':	discontiguous memory area
- *	'a':	anonymous memory allocation
- *	'()':	optional feature
- *
- *	'n':	a normal page(4KB) size is used.
- *	's':	multiple iommu superpage(16MB, 1MB, 64KB, 4KB) size is used.
- *
- *	'*':	not yet, but feasible.
- */
-
-static struct kmem_cache *iovm_area_cachep;
-
-/* return total bytes of sg buffers */
-static size_t sgtable_len(const struct sg_table *sgt)
-{
-	unsigned int i, total = 0;
-	struct scatterlist *sg;
-
-	if (!sgt)
-		return 0;
-
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		size_t bytes;
-
-		bytes = sg->length;
-
-		if (!iopgsz_ok(bytes)) {
-			pr_err("%s: sg[%d] not iommu pagesize(%x)\n",
-			       __func__, i, bytes);
-			return 0;
-		}
-
-		total += bytes;
-	}
-
-	return total;
-}
-#define sgtable_ok(x)	(!!sgtable_len(x))
-
-static unsigned max_alignment(u32 addr)
-{
-	int i;
-	unsigned pagesize[] = { SZ_16M, SZ_1M, SZ_64K, SZ_4K, };
-	for (i = 0; i < ARRAY_SIZE(pagesize) && addr & (pagesize[i] - 1); i++)
-		;
-	return (i < ARRAY_SIZE(pagesize)) ? pagesize[i] : 0;
-}
-
-/*
- * calculate the optimal number sg elements from total bytes based on
- * iommu superpages
- */
-static unsigned sgtable_nents(size_t bytes, u32 da, u32 pa)
-{
-	unsigned nr_entries = 0, ent_sz;
-
-	if (!IS_ALIGNED(bytes, PAGE_SIZE)) {
-		pr_err("%s: wrong size %08x\n", __func__, bytes);
-		return 0;
-	}
-
-	while (bytes) {
-		ent_sz = max_alignment(da | pa);
-		ent_sz = min_t(unsigned, ent_sz, iopgsz_max(bytes));
-		nr_entries++;
-		da += ent_sz;
-		pa += ent_sz;
-		bytes -= ent_sz;
-	}
-
-	return nr_entries;
-}
-
-/* allocate and initialize sg_table header(a kind of 'superblock') */
-static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags,
-							u32 da, u32 pa)
-{
-	unsigned int nr_entries;
-	int err;
-	struct sg_table *sgt;
-
-	if (!bytes)
-		return ERR_PTR(-EINVAL);
-
-	if (!IS_ALIGNED(bytes, PAGE_SIZE))
-		return ERR_PTR(-EINVAL);
-
-	if (flags & IOVMF_LINEAR) {
-		nr_entries = sgtable_nents(bytes, da, pa);
-		if (!nr_entries)
-			return ERR_PTR(-EINVAL);
-	} else
-		nr_entries =  bytes / PAGE_SIZE;
-
-	sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
-	if (!sgt)
-		return ERR_PTR(-ENOMEM);
-
-	err = sg_alloc_table(sgt, nr_entries, GFP_KERNEL);
-	if (err) {
-		kfree(sgt);
-		return ERR_PTR(err);
-	}
-
-	pr_debug("%s: sgt:%p(%d entries)\n", __func__, sgt, nr_entries);
-
-	return sgt;
-}
-
-/* free sg_table header(a kind of superblock) */
-static void sgtable_free(struct sg_table *sgt)
-{
-	if (!sgt)
-		return;
-
-	sg_free_table(sgt);
-	kfree(sgt);
-
-	pr_debug("%s: sgt:%p\n", __func__, sgt);
-}
-
-/* map 'sglist' to a contiguous mpu virtual area and return 'va' */
-static void *vmap_sg(const struct sg_table *sgt)
-{
-	u32 va;
-	size_t total;
-	unsigned int i;
-	struct scatterlist *sg;
-	struct vm_struct *new;
-	const struct mem_type *mtype;
-
-	mtype = get_mem_type(MT_DEVICE);
-	if (!mtype)
-		return ERR_PTR(-EINVAL);
-
-	total = sgtable_len(sgt);
-	if (!total)
-		return ERR_PTR(-EINVAL);
-
-	new = __get_vm_area(total, VM_IOREMAP, VMALLOC_START, VMALLOC_END);
-	if (!new)
-		return ERR_PTR(-ENOMEM);
-	va = (u32)new->addr;
-
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		size_t bytes;
-		u32 pa;
-		int err;
-
-		pa = sg_phys(sg);
-		bytes = sg->length;
-
-		BUG_ON(bytes != PAGE_SIZE);
-
-		err = ioremap_page(va,  pa, mtype);
-		if (err)
-			goto err_out;
-
-		va += bytes;
-	}
-
-	flush_cache_vmap((unsigned long)new->addr,
-				(unsigned long)(new->addr + total));
-	return new->addr;
-
-err_out:
-	WARN_ON(1); /* FIXME: cleanup some mpu mappings */
-	vunmap(new->addr);
-	return ERR_PTR(-EAGAIN);
-}
-
-static inline void vunmap_sg(const void *va)
-{
-	vunmap(va);
-}
-
-static struct iovm_struct *__find_iovm_area(struct iommu *obj, const u32 da)
-{
-	struct iovm_struct *tmp;
-
-	list_for_each_entry(tmp, &obj->mmap, list) {
-		if ((da >= tmp->da_start) && (da < tmp->da_end)) {
-			size_t len;
-
-			len = tmp->da_end - tmp->da_start;
-
-			dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n",
-				__func__, tmp->da_start, da, tmp->da_end, len,
-				tmp->flags);
-
-			return tmp;
-		}
-	}
-
-	return NULL;
-}
-
-/**
- * find_iovm_area  -  find iovma which includes @da
- * @da:		iommu device virtual address
- *
- * Find the existing iovma starting at @da
- */
-struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da)
-{
-	struct iovm_struct *area;
-
-	mutex_lock(&obj->mmap_lock);
-	area = __find_iovm_area(obj, da);
-	mutex_unlock(&obj->mmap_lock);
-
-	return area;
-}
-EXPORT_SYMBOL_GPL(find_iovm_area);
-
-/*
- * This finds the hole(area) which fits the requested address and len
- * in iovmas mmap, and returns the new allocated iovma.
- */
-static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da,
-					   size_t bytes, u32 flags)
-{
-	struct iovm_struct *new, *tmp;
-	u32 start, prev_end, alignment;
-
-	if (!obj || !bytes)
-		return ERR_PTR(-EINVAL);
-
-	start = da;
-	alignment = PAGE_SIZE;
-
-	if (~flags & IOVMF_DA_FIXED) {
-		/* Don't map address 0 */
-		start = obj->da_start ? obj->da_start : alignment;
-
-		if (flags & IOVMF_LINEAR)
-			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);
-	}
-
-	tmp = NULL;
-	if (list_empty(&obj->mmap))
-		goto found;
-
-	prev_end = 0;
-	list_for_each_entry(tmp, &obj->mmap, list) {
-
-		if (prev_end > start)
-			break;
-
-		if (tmp->da_start > start && (tmp->da_start - start) >= bytes)
-			goto found;
-
-		if (tmp->da_end >= start && ~flags & IOVMF_DA_FIXED)
-			start = roundup(tmp->da_end + 1, alignment);
-
-		prev_end = tmp->da_end;
-	}
-
-	if ((start >= prev_end) && (obj->da_end - start >= bytes))
-		goto found;
-
-	dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n",
-		__func__, da, bytes, flags);
-
-	return ERR_PTR(-EINVAL);
-
-found:
-	new = kmem_cache_zalloc(iovm_area_cachep, GFP_KERNEL);
-	if (!new)
-		return ERR_PTR(-ENOMEM);
-
-	new->iommu = obj;
-	new->da_start = start;
-	new->da_end = start + bytes;
-	new->flags = flags;
-
-	/*
-	 * keep ascending order of iovmas
-	 */
-	if (tmp)
-		list_add_tail(&new->list, &tmp->list);
-	else
-		list_add(&new->list, &obj->mmap);
-
-	dev_dbg(obj->dev, "%s: found %08x-%08x-%08x(%x) %08x\n",
-		__func__, new->da_start, start, new->da_end, bytes, flags);
-
-	return new;
-}
-
-static void free_iovm_area(struct iommu *obj, struct iovm_struct *area)
-{
-	size_t bytes;
-
-	BUG_ON(!obj || !area);
-
-	bytes = area->da_end - area->da_start;
-
-	dev_dbg(obj->dev, "%s: %08x-%08x(%x) %08x\n",
-		__func__, area->da_start, area->da_end, bytes, area->flags);
-
-	list_del(&area->list);
-	kmem_cache_free(iovm_area_cachep, area);
-}
-
-/**
- * da_to_va - convert (d) to (v)
- * @obj:	objective iommu
- * @da:		iommu device virtual address
- * @va:		mpu virtual address
- *
- * Returns mpu virtual addr which corresponds to a given device virtual addr
- */
-void *da_to_va(struct iommu *obj, u32 da)
-{
-	void *va = NULL;
-	struct iovm_struct *area;
-
-	mutex_lock(&obj->mmap_lock);
-
-	area = __find_iovm_area(obj, da);
-	if (!area) {
-		dev_dbg(obj->dev, "%s: no da area(%08x)\n", __func__, da);
-		goto out;
-	}
-	va = area->va;
-out:
-	mutex_unlock(&obj->mmap_lock);
-
-	return va;
-}
-EXPORT_SYMBOL_GPL(da_to_va);
-
-static void sgtable_fill_vmalloc(struct sg_table *sgt, void *_va)
-{
-	unsigned int i;
-	struct scatterlist *sg;
-	void *va = _va;
-	void *va_end;
-
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		struct page *pg;
-		const size_t bytes = PAGE_SIZE;
-
-		/*
-		 * iommu 'superpage' isn't supported with 'iommu_vmalloc()'
-		 */
-		pg = vmalloc_to_page(va);
-		BUG_ON(!pg);
-		sg_set_page(sg, pg, bytes, 0);
-
-		va += bytes;
-	}
-
-	va_end = _va + PAGE_SIZE * i;
-}
-
-static inline void sgtable_drain_vmalloc(struct sg_table *sgt)
-{
-	/*
-	 * Actually this is not necessary at all, just exists for
-	 * consistency of the code readability.
-	 */
-	BUG_ON(!sgt);
-}
-
-static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, u32 da,
-								size_t len)
-{
-	unsigned int i;
-	struct scatterlist *sg;
-
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		unsigned bytes;
-
-		bytes = max_alignment(da | pa);
-		bytes = min_t(unsigned, bytes, iopgsz_max(len));
-
-		BUG_ON(!iopgsz_ok(bytes));
-
-		sg_set_buf(sg, phys_to_virt(pa), bytes);
-		/*
-		 * 'pa' is cotinuous(linear).
-		 */
-		pa += bytes;
-		da += bytes;
-		len -= bytes;
-	}
-	BUG_ON(len);
-}
-
-static inline void sgtable_drain_kmalloc(struct sg_table *sgt)
-{
-	/*
-	 * Actually this is not necessary at all, just exists for
-	 * consistency of the code readability
-	 */
-	BUG_ON(!sgt);
-}
-
-/* create 'da' <-> 'pa' mapping from 'sgt' */
-static int map_iovm_area(struct iommu *obj, struct iovm_struct *new,
-			 const struct sg_table *sgt, u32 flags)
-{
-	int err;
-	unsigned int i, j;
-	struct scatterlist *sg;
-	u32 da = new->da_start;
-
-	if (!obj || !sgt)
-		return -EINVAL;
-
-	BUG_ON(!sgtable_ok(sgt));
-
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		u32 pa;
-		int pgsz;
-		size_t bytes;
-		struct iotlb_entry e;
-
-		pa = sg_phys(sg);
-		bytes = sg->length;
-
-		flags &= ~IOVMF_PGSZ_MASK;
-		pgsz = bytes_to_iopgsz(bytes);
-		if (pgsz < 0)
-			goto err_out;
-		flags |= pgsz;
-
-		pr_debug("%s: [%d] %08x %08x(%x)\n", __func__,
-			 i, da, pa, bytes);
-
-		iotlb_init_entry(&e, da, pa, flags);
-		err = iopgtable_store_entry(obj, &e);
-		if (err)
-			goto err_out;
-
-		da += bytes;
-	}
-	return 0;
-
-err_out:
-	da = new->da_start;
-
-	for_each_sg(sgt->sgl, sg, i, j) {
-		size_t bytes;
-
-		bytes = iopgtable_clear_entry(obj, da);
-
-		BUG_ON(!iopgsz_ok(bytes));
-
-		da += bytes;
-	}
-	return err;
-}
-
-/* release 'da' <-> 'pa' mapping */
-static void unmap_iovm_area(struct iommu *obj, struct iovm_struct *area)
-{
-	u32 start;
-	size_t total = area->da_end - area->da_start;
-
-	BUG_ON((!total) || !IS_ALIGNED(total, PAGE_SIZE));
-
-	start = area->da_start;
-	while (total > 0) {
-		size_t bytes;
-
-		bytes = iopgtable_clear_entry(obj, start);
-		if (bytes == 0)
-			bytes = PAGE_SIZE;
-		else
-			dev_dbg(obj->dev, "%s: unmap %08x(%x) %08x\n",
-				__func__, start, bytes, area->flags);
-
-		BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE));
-
-		total -= bytes;
-		start += bytes;
-	}
-	BUG_ON(total);
-}
-
-/* template function for all unmapping */
-static struct sg_table *unmap_vm_area(struct iommu *obj, const u32 da,
-				      void (*fn)(const void *), u32 flags)
-{
-	struct sg_table *sgt = NULL;
-	struct iovm_struct *area;
-
-	if (!IS_ALIGNED(da, PAGE_SIZE)) {
-		dev_err(obj->dev, "%s: alignment err(%08x)\n", __func__, da);
-		return NULL;
-	}
-
-	mutex_lock(&obj->mmap_lock);
-
-	area = __find_iovm_area(obj, da);
-	if (!area) {
-		dev_dbg(obj->dev, "%s: no da area(%08x)\n", __func__, da);
-		goto out;
-	}
-
-	if ((area->flags & flags) != flags) {
-		dev_err(obj->dev, "%s: wrong flags(%08x)\n", __func__,
-			area->flags);
-		goto out;
-	}
-	sgt = (struct sg_table *)area->sgt;
-
-	unmap_iovm_area(obj, area);
-
-	fn(area->va);
-
-	dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n", __func__,
-		area->da_start, da, area->da_end,
-		area->da_end - area->da_start, area->flags);
-
-	free_iovm_area(obj, area);
-out:
-	mutex_unlock(&obj->mmap_lock);
-
-	return sgt;
-}
-
-static u32 map_iommu_region(struct iommu *obj, u32 da,
-	      const struct sg_table *sgt, void *va, size_t bytes, u32 flags)
-{
-	int err = -ENOMEM;
-	struct iovm_struct *new;
-
-	mutex_lock(&obj->mmap_lock);
-
-	new = alloc_iovm_area(obj, da, bytes, flags);
-	if (IS_ERR(new)) {
-		err = PTR_ERR(new);
-		goto err_alloc_iovma;
-	}
-	new->va = va;
-	new->sgt = sgt;
-
-	if (map_iovm_area(obj, new, sgt, new->flags))
-		goto err_map;
-
-	mutex_unlock(&obj->mmap_lock);
-
-	dev_dbg(obj->dev, "%s: da:%08x(%x) flags:%08x va:%p\n",
-		__func__, new->da_start, bytes, new->flags, va);
-
-	return new->da_start;
-
-err_map:
-	free_iovm_area(obj, new);
-err_alloc_iovma:
-	mutex_unlock(&obj->mmap_lock);
-	return err;
-}
-
-static inline u32 __iommu_vmap(struct iommu *obj, u32 da,
-		 const struct sg_table *sgt, void *va, size_t bytes, u32 flags)
-{
-	return map_iommu_region(obj, da, sgt, va, bytes, flags);
-}
-
-/**
- * iommu_vmap  -  (d)-(p)-(v) address mapper
- * @obj:	objective iommu
- * @sgt:	address of scatter gather table
- * @flags:	iovma and page property
- *
- * Creates 1-n-1 mapping with given @sgt and returns @da.
- * All @sgt element must be io page size aligned.
- */
-u32 iommu_vmap(struct iommu *obj, u32 da, const struct sg_table *sgt,
-		 u32 flags)
-{
-	size_t bytes;
-	void *va = NULL;
-
-	if (!obj || !obj->dev || !sgt)
-		return -EINVAL;
-
-	bytes = sgtable_len(sgt);
-	if (!bytes)
-		return -EINVAL;
-	bytes = PAGE_ALIGN(bytes);
-
-	if (flags & IOVMF_MMIO) {
-		va = vmap_sg(sgt);
-		if (IS_ERR(va))
-			return PTR_ERR(va);
-	}
-
-	flags |= IOVMF_DISCONT;
-	flags |= IOVMF_MMIO;
-
-	da = __iommu_vmap(obj, da, sgt, va, bytes, flags);
-	if (IS_ERR_VALUE(da))
-		vunmap_sg(va);
-
-	return da;
-}
-EXPORT_SYMBOL_GPL(iommu_vmap);
-
-/**
- * iommu_vunmap  -  release virtual mapping obtained by 'iommu_vmap()'
- * @obj:	objective iommu
- * @da:		iommu device virtual address
- *
- * Free the iommu virtually contiguous memory area starting at
- * @da, which was returned by 'iommu_vmap()'.
- */
-struct sg_table *iommu_vunmap(struct iommu *obj, u32 da)
-{
-	struct sg_table *sgt;
-	/*
-	 * 'sgt' is allocated before 'iommu_vmalloc()' is called.
-	 * Just returns 'sgt' to the caller to free
-	 */
-	sgt = unmap_vm_area(obj, da, vunmap_sg, IOVMF_DISCONT | IOVMF_MMIO);
-	if (!sgt)
-		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
-	return sgt;
-}
-EXPORT_SYMBOL_GPL(iommu_vunmap);
-
-/**
- * iommu_vmalloc  -  (d)-(p)-(v) address allocator and mapper
- * @obj:	objective iommu
- * @da:		contiguous iommu virtual memory
- * @bytes:	allocation size
- * @flags:	iovma and page property
- *
- * Allocate @bytes linearly and creates 1-n-1 mapping and returns
- * @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set.
- */
-u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
-{
-	void *va;
-	struct sg_table *sgt;
-
-	if (!obj || !obj->dev || !bytes)
-		return -EINVAL;
-
-	bytes = PAGE_ALIGN(bytes);
-
-	va = vmalloc(bytes);
-	if (!va)
-		return -ENOMEM;
-
-	flags |= IOVMF_DISCONT;
-	flags |= IOVMF_ALLOC;
-
-	sgt = sgtable_alloc(bytes, flags, da, 0);
-	if (IS_ERR(sgt)) {
-		da = PTR_ERR(sgt);
-		goto err_sgt_alloc;
-	}
-	sgtable_fill_vmalloc(sgt, va);
-
-	da = __iommu_vmap(obj, da, sgt, va, bytes, flags);
-	if (IS_ERR_VALUE(da))
-		goto err_iommu_vmap;
-
-	return da;
-
-err_iommu_vmap:
-	sgtable_drain_vmalloc(sgt);
-	sgtable_free(sgt);
-err_sgt_alloc:
-	vfree(va);
-	return da;
-}
-EXPORT_SYMBOL_GPL(iommu_vmalloc);
-
-/**
- * iommu_vfree  -  release memory allocated by 'iommu_vmalloc()'
- * @obj:	objective iommu
- * @da:		iommu device virtual address
- *
- * Frees the iommu virtually continuous memory area starting at
- * @da, as obtained from 'iommu_vmalloc()'.
- */
-void iommu_vfree(struct iommu *obj, const u32 da)
-{
-	struct sg_table *sgt;
-
-	sgt = unmap_vm_area(obj, da, vfree, IOVMF_DISCONT | IOVMF_ALLOC);
-	if (!sgt)
-		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
-	sgtable_free(sgt);
-}
-EXPORT_SYMBOL_GPL(iommu_vfree);
-
-static u32 __iommu_kmap(struct iommu *obj, u32 da, u32 pa, void *va,
-			  size_t bytes, u32 flags)
-{
-	struct sg_table *sgt;
-
-	sgt = sgtable_alloc(bytes, flags, da, pa);
-	if (IS_ERR(sgt))
-		return PTR_ERR(sgt);
-
-	sgtable_fill_kmalloc(sgt, pa, da, bytes);
-
-	da = map_iommu_region(obj, da, sgt, va, bytes, flags);
-	if (IS_ERR_VALUE(da)) {
-		sgtable_drain_kmalloc(sgt);
-		sgtable_free(sgt);
-	}
-
-	return da;
-}
-
-/**
- * iommu_kmap  -  (d)-(p)-(v) address mapper
- * @obj:	objective iommu
- * @da:		contiguous iommu virtual memory
- * @pa:		contiguous physical memory
- * @flags:	iovma and page property
- *
- * Creates 1-1-1 mapping and returns @da again, which can be
- * adjusted if 'IOVMF_DA_FIXED' is not set.
- */
-u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
-		 u32 flags)
-{
-	void *va;
-
-	if (!obj || !obj->dev || !bytes)
-		return -EINVAL;
-
-	bytes = PAGE_ALIGN(bytes);
-
-	va = ioremap(pa, bytes);
-	if (!va)
-		return -ENOMEM;
-
-	flags |= IOVMF_LINEAR;
-	flags |= IOVMF_MMIO;
-
-	da = __iommu_kmap(obj, da, pa, va, bytes, flags);
-	if (IS_ERR_VALUE(da))
-		iounmap(va);
-
-	return da;
-}
-EXPORT_SYMBOL_GPL(iommu_kmap);
-
-/**
- * iommu_kunmap  -  release virtual mapping obtained by 'iommu_kmap()'
- * @obj:	objective iommu
- * @da:		iommu device virtual address
- *
- * Frees the iommu virtually contiguous memory area starting at
- * @da, which was passed to and was returned by'iommu_kmap()'.
- */
-void iommu_kunmap(struct iommu *obj, u32 da)
-{
-	struct sg_table *sgt;
-	typedef void (*func_t)(const void *);
-
-	sgt = unmap_vm_area(obj, da, (func_t)iounmap,
-			    IOVMF_LINEAR | IOVMF_MMIO);
-	if (!sgt)
-		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
-	sgtable_free(sgt);
-}
-EXPORT_SYMBOL_GPL(iommu_kunmap);
-
-/**
- * iommu_kmalloc  -  (d)-(p)-(v) address allocator and mapper
- * @obj:	objective iommu
- * @da:		contiguous iommu virtual memory
- * @bytes:	bytes for allocation
- * @flags:	iovma and page property
- *
- * Allocate @bytes linearly and creates 1-1-1 mapping and returns
- * @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set.
- */
-u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
-{
-	void *va;
-	u32 pa;
-
-	if (!obj || !obj->dev || !bytes)
-		return -EINVAL;
-
-	bytes = PAGE_ALIGN(bytes);
-
-	va = kmalloc(bytes, GFP_KERNEL | GFP_DMA);
-	if (!va)
-		return -ENOMEM;
-	pa = virt_to_phys(va);
-
-	flags |= IOVMF_LINEAR;
-	flags |= IOVMF_ALLOC;
-
-	da = __iommu_kmap(obj, da, pa, va, bytes, flags);
-	if (IS_ERR_VALUE(da))
-		kfree(va);
-
-	return da;
-}
-EXPORT_SYMBOL_GPL(iommu_kmalloc);
-
-/**
- * iommu_kfree  -  release virtual mapping obtained by 'iommu_kmalloc()'
- * @obj:	objective iommu
- * @da:		iommu device virtual address
- *
- * Frees the iommu virtually contiguous memory area starting at
- * @da, which was passed to and was returned by'iommu_kmalloc()'.
- */
-void iommu_kfree(struct iommu *obj, u32 da)
-{
-	struct sg_table *sgt;
-
-	sgt = unmap_vm_area(obj, da, kfree, IOVMF_LINEAR | IOVMF_ALLOC);
-	if (!sgt)
-		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
-	sgtable_free(sgt);
-}
-EXPORT_SYMBOL_GPL(iommu_kfree);
-
-
-static int __init iovmm_init(void)
-{
-	const unsigned long flags = SLAB_HWCACHE_ALIGN;
-	struct kmem_cache *p;
-
-	p = kmem_cache_create("iovm_area_cache", sizeof(struct iovm_struct), 0,
-			      flags, NULL);
-	if (!p)
-		return -ENOMEM;
-	iovm_area_cachep = p;
-
-	return 0;
-}
-module_init(iovmm_init);
-
-static void __exit iovmm_exit(void)
-{
-	kmem_cache_destroy(iovm_area_cachep);
-}
-module_exit(iovmm_exit);
-
-MODULE_DESCRIPTION("omap iommu: simple virtual address space management");
-MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
-MODULE_LICENSE("GPL v2");
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/Kconfig linux-libre-3.2-gnu/arch/arm/plat-omap/Kconfig
--- linux-libre-3.1-gnu/arch/arm/plat-omap/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,8 @@
 	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
 	select GENERIC_IRQ_CHIP
+	select HAVE_IDE
+	select NEED_MACH_MEMORY_H
 	help
 	  "Systems based on omap7xx, omap15xx or omap16xx"
 
@@ -132,18 +134,6 @@
 	  This can also be changed at runtime (via the mbox_kfifo_size
 	  module parameter).
 
-config OMAP_IOMMU
-	tristate
-
-config OMAP_IOMMU_DEBUG
-       tristate "Export OMAP IOMMU internals in DebugFS"
-       depends on OMAP_IOMMU && DEBUG_FS
-       help
-         Select this to see extensive information about
-         the internal state of OMAP IOMMU in debugfs.
-
-         Say N unless you know you need this.
-
 config OMAP_IOMMU_IVA2
 	bool
 
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/mailbox.c linux-libre-3.2-gnu/arch/arm/plat-omap/mailbox.c
--- linux-libre-3.1-gnu/arch/arm/plat-omap/mailbox.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/mailbox.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/kfifo.h>
 #include <linux/err.h>
 #include <linux/notifier.h>
+#include <linux/module.h>
 
 #include <plat/mailbox.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/Makefile linux-libre-3.2-gnu/arch/arm/plat-omap/Makefile
--- linux-libre-3.1-gnu/arch/arm/plat-omap/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -18,8 +18,6 @@
 obj-$(CONFIG_ARCH_OMAP4) += omap_device.o
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
-obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
-obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o
 
 obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/mcbsp.c linux-libre-3.2-gnu/arch/arm/plat-omap/mcbsp.c
--- linux-libre-3.1-gnu/arch/arm/plat-omap/mcbsp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/mcbsp.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,45 +24,40 @@
 #include <linux/slab.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"
-#include "../mach-omap2/cm-regbits-34xx.h"
-
 struct omap_mcbsp **mcbsp_ptr;
-int omap_mcbsp_count, omap_mcbsp_cache_size;
+int omap_mcbsp_count;
+
+#define omap_mcbsp_check_valid_id(id)	(id < omap_mcbsp_count)
+#define id_to_mcbsp_ptr(id)		mcbsp_ptr[id];
 
 static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
 {
-	if (cpu_class_is_omap1()) {
-		((u16 *)mcbsp->reg_cache)[reg / sizeof(u16)] = (u16)val;
-		__raw_writew((u16)val, mcbsp->io_base + reg);
-	} else if (cpu_is_omap2420()) {
-		((u16 *)mcbsp->reg_cache)[reg / sizeof(u32)] = (u16)val;
-		__raw_writew((u16)val, mcbsp->io_base + reg);
+	void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
+
+	if (mcbsp->pdata->reg_size == 2) {
+		((u16 *)mcbsp->reg_cache)[reg] = (u16)val;
+		__raw_writew((u16)val, addr);
 	} else {
-		((u32 *)mcbsp->reg_cache)[reg / sizeof(u32)] = val;
-		__raw_writel(val, mcbsp->io_base + reg);
+		((u32 *)mcbsp->reg_cache)[reg] = val;
+		__raw_writel(val, addr);
 	}
 }
 
 static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
 {
-	if (cpu_class_is_omap1()) {
-		return !from_cache ? __raw_readw(mcbsp->io_base + reg) :
-				((u16 *)mcbsp->reg_cache)[reg / sizeof(u16)];
-	} else if (cpu_is_omap2420()) {
-		return !from_cache ? __raw_readw(mcbsp->io_base + reg) :
-				((u16 *)mcbsp->reg_cache)[reg / sizeof(u32)];
+	void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
+
+	if (mcbsp->pdata->reg_size == 2) {
+		return !from_cache ? __raw_readw(addr) :
+				     ((u16 *)mcbsp->reg_cache)[reg];
 	} else {
-		return !from_cache ? __raw_readl(mcbsp->io_base + reg) :
-				((u32 *)mcbsp->reg_cache)[reg / sizeof(u32)];
+		return !from_cache ? __raw_readl(addr) :
+				     ((u32 *)mcbsp->reg_cache)[reg];
 	}
 }
 
-#ifdef CONFIG_ARCH_OMAP3
 static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
 {
 	__raw_writel(val, mcbsp->st_data->io_base_st + reg);
@@ -72,7 +67,6 @@
 {
 	return __raw_readl(mcbsp->st_data->io_base_st + reg);
 }
-#endif
 
 #define MCBSP_READ(mcbsp, reg) \
 		omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 0)
@@ -187,7 +181,7 @@
 	MCBSP_WRITE(mcbsp, MCR2, config->mcr2);
 	MCBSP_WRITE(mcbsp, MCR1, config->mcr1);
 	MCBSP_WRITE(mcbsp, PCR0, config->pcr0);
-	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	if (mcbsp->pdata->has_ccr) {
 		MCBSP_WRITE(mcbsp, XCCR, config->xccr);
 		MCBSP_WRITE(mcbsp, RCCR, config->rccr);
 	}
@@ -239,46 +233,28 @@
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
 
-	data_reg = mcbsp->phys_dma_base;
-
-	if (mcbsp->mcbsp_config_type < MCBSP_CONFIG_TYPE2) {
+	if (mcbsp->pdata->reg_size == 2) {
 		if (stream)
-			data_reg += OMAP_MCBSP_REG_DRR1;
+			data_reg = OMAP_MCBSP_REG_DRR1;
 		else
-			data_reg += OMAP_MCBSP_REG_DXR1;
+			data_reg = OMAP_MCBSP_REG_DXR1;
 	} else {
 		if (stream)
-			data_reg += OMAP_MCBSP_REG_DRR;
+			data_reg = OMAP_MCBSP_REG_DRR;
 		else
-			data_reg += OMAP_MCBSP_REG_DXR;
+			data_reg = OMAP_MCBSP_REG_DXR;
 	}
 
-	return data_reg;
+	return mcbsp->phys_dma_base + data_reg * mcbsp->pdata->reg_step;
 }
 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
-	 * are enabled or sidetones start sounding ugly.
-	 */
-	w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
-	w &= ~(1 << (mcbsp->id - 2));
-	omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
+	if (mcbsp->pdata->enable_st_clock)
+		mcbsp->pdata->enable_st_clock(mcbsp->id, 1);
 
 	/* Enable McBSP Sidetone */
 	w = MCBSP_READ(mcbsp, SSELCR);
@@ -292,9 +268,6 @@
 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));
@@ -302,17 +275,13 @@
 	w = MCBSP_READ(mcbsp, SSELCR);
 	MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN));
 
-	w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
-	w |= 1 << (mcbsp->id - 2);
-	omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
+	if (mcbsp->pdata->enable_st_clock)
+		mcbsp->pdata->enable_st_clock(mcbsp->id, 0);
 }
 
 static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir)
 {
 	u16 val, i;
-	struct omap_device *od;
-
-	od = find_omap_device_by_dev(mcbsp->dev);
 
 	val = MCBSP_ST_READ(mcbsp, SSELCR);
 
@@ -340,9 +309,6 @@
 {
 	u16 w;
 	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
-	struct omap_device *od;
-
-	od = find_omap_device_by_dev(mcbsp->dev);
 
 	w = MCBSP_ST_READ(mcbsp, SSELCR);
 
@@ -525,14 +491,13 @@
 {
 	struct omap_mcbsp *mcbsp;
 
-	if (!cpu_is_omap34xx() && !cpu_is_omap44xx())
-		return;
-
 	if (!omap_mcbsp_check_valid_id(id)) {
 		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
 		return;
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
+	if (mcbsp->pdata->buffer_size == 0)
+		return;
 
 	if (threshold && threshold <= mcbsp->max_tx_thres)
 		MCBSP_WRITE(mcbsp, THRSH2, threshold - 1);
@@ -548,14 +513,13 @@
 {
 	struct omap_mcbsp *mcbsp;
 
-	if (!cpu_is_omap34xx() && !cpu_is_omap44xx())
-		return;
-
 	if (!omap_mcbsp_check_valid_id(id)) {
 		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
 		return;
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
+	if (mcbsp->pdata->buffer_size == 0)
+		return;
 
 	if (threshold && threshold <= mcbsp->max_rx_thres)
 		MCBSP_WRITE(mcbsp, THRSH1, threshold - 1);
@@ -625,6 +589,8 @@
 		return -ENODEV;
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
+	if (mcbsp->pdata->buffer_size == 0)
+		return 0;
 
 	/* Returns the number of free locations in the buffer */
 	buffstat = MCBSP_READ(mcbsp, XBUFFSTAT);
@@ -648,6 +614,8 @@
 		return -ENODEV;
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
+	if (mcbsp->pdata->buffer_size == 0)
+		return 0;
 
 	/* Returns the number of used locations in the buffer */
 	buffstat = MCBSP_READ(mcbsp, RBUFFSTAT);
@@ -683,46 +651,6 @@
 }
 EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode);
 
-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()) {
-		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()) {
-		/*
-		 * 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.
-		 */
-
-		MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
-	}
-}
-#else
-static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) {}
-static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) {}
-static inline void omap_st_start(struct omap_mcbsp *mcbsp) {}
-static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {}
-#endif
-
 int omap_mcbsp_request(unsigned int id)
 {
 	struct omap_mcbsp *mcbsp;
@@ -735,7 +663,7 @@
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
 
-	reg_cache = kzalloc(omap_mcbsp_cache_size, GFP_KERNEL);
+	reg_cache = kzalloc(mcbsp->reg_cache_size, GFP_KERNEL);
 	if (!reg_cache) {
 		return -ENOMEM;
 	}
@@ -757,8 +685,9 @@
 
 	pm_runtime_get_sync(mcbsp->dev);
 
-	/* Do procedure specific to omap34xx arch, if applicable */
-	omap34xx_mcbsp_request(mcbsp);
+	/* Enable wakeup behavior */
+	if (mcbsp->pdata->has_wakeup)
+		MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
 
 	/*
 	 * Make sure that transmitter, receiver and sample-rate generator are
@@ -795,8 +724,9 @@
 	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
 		mcbsp->pdata->ops->free(id);
 
-	/* Do procedure specific to omap34xx arch, if applicable */
-	omap34xx_mcbsp_free(mcbsp);
+	/* Disable wakeup behavior */
+	if (mcbsp->pdata->has_wakeup)
+		MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
 
 	pm_runtime_put_sync(mcbsp->dev);
 
@@ -825,8 +755,9 @@
 	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
 		mcbsp->pdata->ops->free(id);
 
-	/* Do procedure specific to omap34xx arch, if applicable */
-	omap34xx_mcbsp_free(mcbsp);
+	/* Disable wakeup behavior */
+	if (mcbsp->pdata->has_wakeup)
+		MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
 
 	pm_runtime_put_sync(mcbsp->dev);
 
@@ -866,7 +797,7 @@
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
 
-	if (cpu_is_omap34xx())
+	if (mcbsp->st_data)
 		omap_st_start(mcbsp);
 
 	/* Only enable SRG, if McBSP is master */
@@ -904,7 +835,7 @@
 		MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7));
 	}
 
-	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	if (mcbsp->pdata->has_ccr) {
 		/* Release the transmitter and receiver */
 		w = MCBSP_READ_CACHE(mcbsp, XCCR);
 		w &= ~(tx ? XDISABLE : 0);
@@ -934,7 +865,7 @@
 
 	/* Reset transmitter */
 	tx &= 1;
-	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	if (mcbsp->pdata->has_ccr) {
 		w = MCBSP_READ_CACHE(mcbsp, XCCR);
 		w |= (tx ? XDISABLE : 0);
 		MCBSP_WRITE(mcbsp, XCCR, w);
@@ -944,7 +875,7 @@
 
 	/* Reset receiver */
 	rx &= 1;
-	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	if (mcbsp->pdata->has_ccr) {
 		w = MCBSP_READ_CACHE(mcbsp, RCCR);
 		w |= (rx ? RDISABLE : 0);
 		MCBSP_WRITE(mcbsp, RCCR, w);
@@ -961,39 +892,72 @@
 		MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6));
 	}
 
-	if (cpu_is_omap34xx())
+	if (mcbsp->st_data)
 		omap_st_stop(mcbsp);
 }
 EXPORT_SYMBOL(omap_mcbsp_stop);
 
-/*
- * The following functions are only required on an OMAP1-only build.
- * mach-omap2/mcbsp.c contains the real functions
- */
-#ifndef CONFIG_ARCH_OMAP2PLUS
 int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
 {
-	WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
-	     __func__);
-	return -EINVAL;
+	struct omap_mcbsp *mcbsp;
+	const char *src;
+
+	if (!omap_mcbsp_check_valid_id(id)) {
+		pr_err("%s: Invalid id (%d)\n", __func__, id + 1);
+		return -EINVAL;
+	}
+	mcbsp = id_to_mcbsp_ptr(id);
+
+	if (fck_src_id == MCBSP_CLKS_PAD_SRC)
+		src = "clks_ext";
+	else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
+		src = "clks_fclk";
+	else
+		return -EINVAL;
+
+	if (mcbsp->pdata->set_clk_src)
+		return mcbsp->pdata->set_clk_src(mcbsp->dev, mcbsp->fclk, src);
+	else
+		return -EINVAL;
 }
+EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
 
 void omap2_mcbsp1_mux_clkr_src(u8 mux)
 {
-	WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
-	     __func__);
-	return;
+	struct omap_mcbsp *mcbsp;
+	const char *src;
+
+	if (mux == CLKR_SRC_CLKR)
+		src = "clkr";
+	else if (mux == CLKR_SRC_CLKX)
+		src = "clkx";
+	else
+		return;
+
+	mcbsp = id_to_mcbsp_ptr(0);
+	if (mcbsp->pdata->mux_signal)
+		mcbsp->pdata->mux_signal(mcbsp->dev, "clkr", src);
 }
+EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src);
 
 void omap2_mcbsp1_mux_fsr_src(u8 mux)
 {
-	WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
-	     __func__);
-	return;
+	struct omap_mcbsp *mcbsp;
+	const char *src;
+
+	if (mux == FSR_SRC_FSR)
+		src = "fsr";
+	else if (mux == FSR_SRC_FSX)
+		src = "fsx";
+	else
+		return;
+
+	mcbsp = id_to_mcbsp_ptr(0);
+	if (mcbsp->pdata->mux_signal)
+		mcbsp->pdata->mux_signal(mcbsp->dev, "fsr", src);
 }
-#endif
+EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src);
 
-#ifdef CONFIG_ARCH_OMAP3
 #define max_thres(m)			(mcbsp->pdata->buffer_size)
 #define valid_threshold(m, val)		((val) <= max_thres(m))
 #define THRESHOLD_PROP_BUILDER(prop)					\
@@ -1084,6 +1048,17 @@
 
 static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store);
 
+static const struct attribute *additional_attrs[] = {
+	&dev_attr_max_tx_thres.attr,
+	&dev_attr_max_rx_thres.attr,
+	&dev_attr_dma_op_mode.attr,
+	NULL,
+};
+
+static const struct attribute_group additional_attr_group = {
+	.attrs = (struct attribute **)additional_attrs,
+};
+
 static ssize_t st_taps_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
@@ -1142,27 +1117,6 @@
 
 static DEVICE_ATTR(st_taps, 0644, st_taps_show, st_taps_store);
 
-static const struct attribute *additional_attrs[] = {
-	&dev_attr_max_tx_thres.attr,
-	&dev_attr_max_rx_thres.attr,
-	&dev_attr_dma_op_mode.attr,
-	NULL,
-};
-
-static const struct attribute_group additional_attr_group = {
-	.attrs = (struct attribute **)additional_attrs,
-};
-
-static inline int __devinit omap_additional_add(struct device *dev)
-{
-	return sysfs_create_group(&dev->kobj, &additional_attr_group);
-}
-
-static inline void __devexit omap_additional_remove(struct device *dev)
-{
-	sysfs_remove_group(&dev->kobj, &additional_attr_group);
-}
-
 static const struct attribute *sidetone_attrs[] = {
 	&dev_attr_st_taps.attr,
 	NULL,
@@ -1172,10 +1126,9 @@
 	.attrs = (struct attribute **)sidetone_attrs,
 };
 
-static int __devinit omap_st_add(struct omap_mcbsp *mcbsp)
+static int __devinit omap_st_add(struct omap_mcbsp *mcbsp,
+				 struct resource *res)
 {
-	struct platform_device *pdev;
-	struct resource *res;
 	struct omap_mcbsp_st_data *st_data;
 	int err;
 
@@ -1185,9 +1138,6 @@
 		goto err1;
 	}
 
-	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;
@@ -1214,59 +1164,10 @@
 {
 	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
 
-	if (st_data) {
-		sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
-		iounmap(st_data->io_base_st);
-		kfree(st_data);
-	}
-}
-
-static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp)
-{
-	mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
-	if (cpu_is_omap34xx()) {
-		/*
-		 * Initially configure the maximum thresholds to a safe value.
-		 * The McBSP FIFO usage with these values should not go under
-		 * 16 locations.
-		 * If the whole FIFO without safety buffer is used, than there
-		 * is a possibility that the DMA will be not able to push the
-		 * new data on time, causing channel shifts in runtime.
-		 */
-		mcbsp->max_tx_thres = max_thres(mcbsp) - 0x10;
-		mcbsp->max_rx_thres = max_thres(mcbsp) - 0x10;
-		/*
-		 * REVISIT: Set dmap_op_mode to THRESHOLD as default
-		 * for mcbsp2 instances.
-		 */
-		if (omap_additional_add(mcbsp->dev))
-			dev_warn(mcbsp->dev,
-				"Unable to create additional controls\n");
-
-		if (mcbsp->id == 2 || mcbsp->id == 3)
-			if (omap_st_add(mcbsp))
-				dev_warn(mcbsp->dev,
-				 "Unable to create sidetone controls\n");
-
-	} else {
-		mcbsp->max_tx_thres = -EINVAL;
-		mcbsp->max_rx_thres = -EINVAL;
-	}
-}
-
-static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp)
-{
-	if (cpu_is_omap34xx()) {
-		omap_additional_remove(mcbsp->dev);
-
-		if (mcbsp->id == 2 || mcbsp->id == 3)
-			omap_st_remove(mcbsp);
-	}
+	sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
+	iounmap(st_data->io_base_st);
+	kfree(st_data);
 }
-#else
-static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) {}
-static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) {}
-#endif /* CONFIG_ARCH_OMAP3 */
 
 /*
  * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
@@ -1316,7 +1217,7 @@
 		}
 	}
 	mcbsp->phys_base = res->start;
-	omap_mcbsp_cache_size = resource_size(res);
+	mcbsp->reg_cache_size = resource_size(res);
 	mcbsp->io_base = ioremap(res->start, resource_size(res));
 	if (!mcbsp->io_base) {
 		ret = -ENOMEM;
@@ -1364,15 +1265,52 @@
 	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);
+	mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
+	if (mcbsp->pdata->buffer_size) {
+		/*
+		 * Initially configure the maximum thresholds to a safe value.
+		 * The McBSP FIFO usage with these values should not go under
+		 * 16 locations.
+		 * If the whole FIFO without safety buffer is used, than there
+		 * is a possibility that the DMA will be not able to push the
+		 * new data on time, causing channel shifts in runtime.
+		 */
+		mcbsp->max_tx_thres = max_thres(mcbsp) - 0x10;
+		mcbsp->max_rx_thres = max_thres(mcbsp) - 0x10;
+
+		ret = sysfs_create_group(&mcbsp->dev->kobj,
+					 &additional_attr_group);
+		if (ret) {
+			dev_err(mcbsp->dev,
+				"Unable to create additional controls\n");
+			goto err_thres;
+		}
+	} else {
+		mcbsp->max_tx_thres = -EINVAL;
+		mcbsp->max_rx_thres = -EINVAL;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sidetone");
+	if (res) {
+		ret = omap_st_add(mcbsp, res);
+		if (ret) {
+			dev_err(mcbsp->dev,
+				"Unable to create sidetone controls\n");
+			goto err_st;
+		}
+	}
 
 	return 0;
 
+err_st:
+	if (mcbsp->pdata->buffer_size)
+		sysfs_remove_group(&mcbsp->dev->kobj,
+				   &additional_attr_group);
+err_thres:
+	clk_put(mcbsp->fclk);
 err_res:
 	iounmap(mcbsp->io_base);
 err_ioremap:
@@ -1392,7 +1330,12 @@
 				mcbsp->pdata->ops->free)
 			mcbsp->pdata->ops->free(mcbsp->id);
 
-		omap34xx_device_exit(mcbsp);
+		if (mcbsp->pdata->buffer_size)
+			sysfs_remove_group(&mcbsp->dev->kobj,
+					   &additional_attr_group);
+
+		if (mcbsp->st_data)
+			omap_st_remove(mcbsp);
 
 		clk_put(mcbsp->fclk);
 
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/omap_device.c linux-libre-3.2-gnu/arch/arm/plat-omap/omap_device.c
--- linux-libre-3.1-gnu/arch/arm/plat-omap/omap_device.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/omap_device.c	2012-01-04 18:55:44.000000000 -0500
@@ -78,6 +78,7 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/err.h>
@@ -85,6 +86,8 @@
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/notifier.h>
 
 #include <plat/omap_device.h>
 #include <plat/omap_hwmod.h>
@@ -94,6 +97,23 @@
 #define USE_WAKEUP_LAT			0
 #define IGNORE_WAKEUP_LAT		1
 
+static int omap_device_register(struct platform_device *pdev);
+static int omap_early_device_register(struct platform_device *pdev);
+static struct omap_device *omap_device_alloc(struct platform_device *pdev,
+				      struct omap_hwmod **ohs, int oh_cnt,
+				      struct omap_device_pm_latency *pm_lats,
+				      int pm_lats_cnt);
+static void omap_device_delete(struct omap_device *od);
+
+
+static struct omap_device_pm_latency omap_default_latency[] = {
+	{
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func   = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	}
+};
+
 /* Private functions */
 
 /**
@@ -114,7 +134,7 @@
 {
 	struct timespec a, b, c;
 
-	pr_debug("omap_device: %s: activating\n", od->pdev.name);
+	dev_dbg(&od->pdev->dev, "omap_device: activating\n");
 
 	while (od->pm_lat_level > 0) {
 		struct omap_device_pm_latency *odpl;
@@ -138,25 +158,24 @@
 		c = timespec_sub(b, a);
 		act_lat = timespec_to_ns(&c);
 
-		pr_debug("omap_device: %s: pm_lat %d: activate: elapsed time "
-			 "%llu nsec\n", od->pdev.name, od->pm_lat_level,
-			 act_lat);
+		dev_dbg(&od->pdev->dev,
+			"omap_device: pm_lat %d: activate: elapsed time "
+			"%llu nsec\n", od->pm_lat_level, act_lat);
 
 		if (act_lat > odpl->activate_lat) {
 			odpl->activate_lat_worst = act_lat;
 			if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
 				odpl->activate_lat = act_lat;
-				pr_warning("omap_device: %s.%d: new worst case "
-					   "activate latency %d: %llu\n",
-					   od->pdev.name, od->pdev.id,
-					   od->pm_lat_level, act_lat);
+				dev_dbg(&od->pdev->dev,
+					"new worst case activate latency "
+					"%d: %llu\n",
+					od->pm_lat_level, act_lat);
 			} else
-				pr_warning("omap_device: %s.%d: activate "
-					   "latency %d higher than exptected. "
-					   "(%llu > %d)\n",
-					   od->pdev.name, od->pdev.id,
-					   od->pm_lat_level, act_lat,
-					   odpl->activate_lat);
+				dev_warn(&od->pdev->dev,
+					 "activate latency %d "
+					 "higher than exptected. (%llu > %d)\n",
+					 od->pm_lat_level, act_lat,
+					 odpl->activate_lat);
 		}
 
 		od->dev_wakeup_lat -= odpl->activate_lat;
@@ -183,7 +202,7 @@
 {
 	struct timespec a, b, c;
 
-	pr_debug("omap_device: %s: deactivating\n", od->pdev.name);
+	dev_dbg(&od->pdev->dev, "omap_device: deactivating\n");
 
 	while (od->pm_lat_level < od->pm_lats_cnt) {
 		struct omap_device_pm_latency *odpl;
@@ -206,28 +225,26 @@
 		c = timespec_sub(b, a);
 		deact_lat = timespec_to_ns(&c);
 
-		pr_debug("omap_device: %s: pm_lat %d: deactivate: elapsed time "
-			 "%llu nsec\n", od->pdev.name, od->pm_lat_level,
-			 deact_lat);
+		dev_dbg(&od->pdev->dev,
+			"omap_device: pm_lat %d: deactivate: elapsed time "
+			"%llu nsec\n", od->pm_lat_level, deact_lat);
 
 		if (deact_lat > odpl->deactivate_lat) {
 			odpl->deactivate_lat_worst = deact_lat;
 			if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
 				odpl->deactivate_lat = deact_lat;
-				pr_warning("omap_device: %s.%d: new worst case "
-					   "deactivate latency %d: %llu\n",
-					   od->pdev.name, od->pdev.id,
-					   od->pm_lat_level, deact_lat);
+				dev_dbg(&od->pdev->dev,
+					"new worst case deactivate latency "
+					"%d: %llu\n",
+					od->pm_lat_level, deact_lat);
 			} else
-				pr_warning("omap_device: %s.%d: deactivate "
-					   "latency %d higher than exptected. "
-					   "(%llu > %d)\n",
-					   od->pdev.name, od->pdev.id,
-					   od->pm_lat_level, deact_lat,
-					   odpl->deactivate_lat);
+				dev_warn(&od->pdev->dev,
+					 "deactivate latency %d "
+					 "higher than exptected. (%llu > %d)\n",
+					 od->pm_lat_level, deact_lat,
+					 odpl->deactivate_lat);
 		}
 
-
 		od->dev_wakeup_lat += odpl->activate_lat;
 
 		od->pm_lat_level++;
@@ -245,28 +262,27 @@
 	if (!clk_alias || !clk_name)
 		return;
 
-	pr_debug("omap_device: %s: Creating %s -> %s\n",
-		 dev_name(&od->pdev.dev), clk_alias, clk_name);
+	dev_dbg(&od->pdev->dev, "Creating %s -> %s\n", clk_alias, clk_name);
 
-	r = clk_get_sys(dev_name(&od->pdev.dev), clk_alias);
+	r = clk_get_sys(dev_name(&od->pdev->dev), clk_alias);
 	if (!IS_ERR(r)) {
-		pr_warning("omap_device: %s: alias %s already exists\n",
-			   dev_name(&od->pdev.dev), clk_alias);
+		dev_warn(&od->pdev->dev,
+			 "alias %s already exists\n", clk_alias);
 		clk_put(r);
 		return;
 	}
 
 	r = omap_clk_get_by_name(clk_name);
 	if (IS_ERR(r)) {
-		pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
-		       dev_name(&od->pdev.dev), clk_name);
+		dev_err(&od->pdev->dev,
+			"omap_clk_get_by_name for %s failed\n", clk_name);
 		return;
 	}
 
-	l = clkdev_alloc(r, clk_alias, dev_name(&od->pdev.dev));
+	l = clkdev_alloc(r, clk_alias, dev_name(&od->pdev->dev));
 	if (!l) {
-		pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
-		       dev_name(&od->pdev.dev), clk_alias);
+		dev_err(&od->pdev->dev,
+			"clkdev_alloc for %s failed\n", clk_alias);
 		return;
 	}
 
@@ -304,6 +320,96 @@
 }
 
 
+static struct dev_pm_domain omap_device_pm_domain;
+
+/**
+ * omap_device_build_from_dt - build an omap_device with multiple hwmods
+ * @pdev_name: name of the platform_device driver to use
+ * @pdev_id: this platform_device's connection ID
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ * @is_early_device: should the device be registered as an early device or not
+ *
+ * Function for building an omap_device already registered from device-tree
+ *
+ * Returns 0 or PTR_ERR() on error.
+ */
+static int omap_device_build_from_dt(struct platform_device *pdev)
+{
+	struct omap_hwmod **hwmods;
+	struct omap_device *od;
+	struct omap_hwmod *oh;
+	struct device_node *node = pdev->dev.of_node;
+	const char *oh_name;
+	int oh_cnt, i, ret = 0;
+
+	oh_cnt = of_property_count_strings(node, "ti,hwmods");
+	if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
+		dev_warn(&pdev->dev, "No 'hwmods' to build omap_device\n");
+		return -ENODEV;
+	}
+
+	hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+	if (!hwmods) {
+		ret = -ENOMEM;
+		goto odbfd_exit;
+	}
+
+	for (i = 0; i < oh_cnt; i++) {
+		of_property_read_string_index(node, "ti,hwmods", i, &oh_name);
+		oh = omap_hwmod_lookup(oh_name);
+		if (!oh) {
+			dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n",
+				oh_name);
+			ret = -EINVAL;
+			goto odbfd_exit1;
+		}
+		hwmods[i] = oh;
+	}
+
+	od = omap_device_alloc(pdev, hwmods, oh_cnt, NULL, 0);
+	if (!od) {
+		dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
+			oh_name);
+		ret = PTR_ERR(od);
+		goto odbfd_exit1;
+	}
+
+	if (of_get_property(node, "ti,no_idle_on_suspend", NULL))
+		omap_device_disable_idle_on_suspend(pdev);
+
+	pdev->dev.pm_domain = &omap_device_pm_domain;
+
+odbfd_exit1:
+	kfree(hwmods);
+odbfd_exit:
+	return ret;
+}
+
+static int _omap_device_notifier_call(struct notifier_block *nb,
+				      unsigned long event, void *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	switch (event) {
+	case BUS_NOTIFY_ADD_DEVICE:
+		if (pdev->dev.of_node)
+			omap_device_build_from_dt(pdev);
+		break;
+
+	case BUS_NOTIFY_DEL_DEVICE:
+		if (pdev->archdata.od)
+			omap_device_delete(pdev->archdata.od);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+
 /* Public functions for use by core code */
 
 /**
@@ -321,7 +427,7 @@
  * return the context loss counter for that hwmod, otherwise return
  * zero.
  */
-u32 omap_device_get_context_loss_count(struct platform_device *pdev)
+int omap_device_get_context_loss_count(struct platform_device *pdev)
 {
 	struct omap_device *od;
 	u32 ret = 0;
@@ -343,7 +449,7 @@
  * much memory to allocate before calling
  * omap_device_fill_resources().  Returns the count.
  */
-int omap_device_count_resources(struct omap_device *od)
+static int omap_device_count_resources(struct omap_device *od)
 {
 	int c = 0;
 	int i;
@@ -352,7 +458,7 @@
 		c += omap_hwmod_count_resources(od->hwmods[i]);
 
 	pr_debug("omap_device: %s: counted %d total resources across %d "
-		 "hwmods\n", od->pdev.name, c, od->hwmods_cnt);
+		 "hwmods\n", od->pdev->name, c, od->hwmods_cnt);
 
 	return c;
 }
@@ -374,7 +480,8 @@
  * functions to get device resources.  Hacking around the existing
  * platform_device code wastes memory.  Returns 0.
  */
-int omap_device_fill_resources(struct omap_device *od, struct resource *res)
+static int omap_device_fill_resources(struct omap_device *od,
+				      struct resource *res)
 {
 	int c = 0;
 	int i, r;
@@ -389,6 +496,113 @@
 }
 
 /**
+ * omap_device_alloc - allocate an omap_device
+ * @pdev: platform_device that will be included in this omap_device
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ *
+ * Convenience function for allocating an omap_device structure and filling
+ * hwmods, resources and pm_latency attributes.
+ *
+ * Returns an struct omap_device pointer or ERR_PTR() on error;
+ */
+static struct omap_device *omap_device_alloc(struct platform_device *pdev,
+					struct omap_hwmod **ohs, int oh_cnt,
+					struct omap_device_pm_latency *pm_lats,
+					int pm_lats_cnt)
+{
+	int ret = -ENOMEM;
+	struct omap_device *od;
+	struct resource *res = NULL;
+	int i, res_count;
+	struct omap_hwmod **hwmods;
+
+	od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
+	if (!od) {
+		ret = -ENOMEM;
+		goto oda_exit1;
+	}
+	od->hwmods_cnt = oh_cnt;
+
+	hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+	if (!hwmods)
+		goto oda_exit2;
+
+	od->hwmods = hwmods;
+	od->pdev = pdev;
+
+	/*
+	 * HACK: Ideally the resources from DT should match, and hwmod
+	 * should just add the missing ones. Since the name is not
+	 * properly populated by DT, stick to hwmod resources only.
+	 */
+	if (pdev->num_resources && pdev->resource)
+		dev_warn(&pdev->dev, "%s(): resources already allocated %d\n",
+			__func__, pdev->num_resources);
+
+	res_count = omap_device_count_resources(od);
+	if (res_count > 0) {
+		dev_dbg(&pdev->dev, "%s(): resources allocated from hwmod %d\n",
+			__func__, res_count);
+		res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
+		if (!res)
+			goto oda_exit3;
+
+		omap_device_fill_resources(od, res);
+
+		ret = platform_device_add_resources(pdev, res, res_count);
+		kfree(res);
+
+		if (ret)
+			goto oda_exit3;
+	}
+
+	if (!pm_lats) {
+		pm_lats = omap_default_latency;
+		pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
+	}
+
+	od->pm_lats_cnt = pm_lats_cnt;
+	od->pm_lats = kmemdup(pm_lats,
+			sizeof(struct omap_device_pm_latency) * pm_lats_cnt,
+			GFP_KERNEL);
+	if (!od->pm_lats)
+		goto oda_exit3;
+
+	pdev->archdata.od = od;
+
+	for (i = 0; i < oh_cnt; i++) {
+		hwmods[i]->od = od;
+		_add_hwmod_clocks_clkdev(od, hwmods[i]);
+	}
+
+	return od;
+
+oda_exit3:
+	kfree(hwmods);
+oda_exit2:
+	kfree(od);
+oda_exit1:
+	dev_err(&pdev->dev, "omap_device: build failed (%d)\n", ret);
+
+	return ERR_PTR(ret);
+}
+
+static void omap_device_delete(struct omap_device *od)
+{
+	if (!od)
+		return;
+
+	od->pdev->archdata.od = NULL;
+	kfree(od->pm_lats);
+	kfree(od->hwmods);
+	kfree(od);
+}
+
+/**
  * omap_device_build - build and register an omap_device with one omap_hwmod
  * @pdev_name: name of the platform_device driver to use
  * @pdev_id: this platform_device's connection ID
@@ -405,7 +619,7 @@
  * information.  Returns ERR_PTR(-EINVAL) if @oh is NULL; otherwise,
  * passes along the return value of omap_device_build_ss().
  */
-struct omap_device *omap_device_build(const char *pdev_name, int pdev_id,
+struct platform_device *omap_device_build(const char *pdev_name, int pdev_id,
 				      struct omap_hwmod *oh, void *pdata,
 				      int pdata_len,
 				      struct omap_device_pm_latency *pm_lats,
@@ -438,18 +652,15 @@
  * platform_device record.  Returns an ERR_PTR() on error, or passes
  * along the return value of omap_device_register().
  */
-struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
+struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 					 struct omap_hwmod **ohs, int oh_cnt,
 					 void *pdata, int pdata_len,
 					 struct omap_device_pm_latency *pm_lats,
 					 int pm_lats_cnt, int is_early_device)
 {
 	int ret = -ENOMEM;
+	struct platform_device *pdev;
 	struct omap_device *od;
-	char *pdev_name2;
-	struct resource *res = NULL;
-	int i, res_count;
-	struct omap_hwmod **hwmods;
 
 	if (!ohs || oh_cnt == 0 || !pdev_name)
 		return ERR_PTR(-EINVAL);
@@ -457,72 +668,40 @@
 	if (!pdata && pdata_len > 0)
 		return ERR_PTR(-EINVAL);
 
-	pr_debug("omap_device: %s: building with %d hwmods\n", pdev_name,
-		 oh_cnt);
-
-	od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
-	if (!od)
-		return ERR_PTR(-ENOMEM);
+	pdev = platform_device_alloc(pdev_name, pdev_id);
+	if (!pdev) {
+		ret = -ENOMEM;
+		goto odbs_exit;
+	}
 
-	od->hwmods_cnt = oh_cnt;
+	/* Set the dev_name early to allow dev_xxx in omap_device_alloc */
+	if (pdev->id != -1)
+		dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
+	else
+		dev_set_name(&pdev->dev, "%s", pdev->name);
 
-	hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt,
-			 GFP_KERNEL);
-	if (!hwmods)
+	od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt);
+	if (!od)
 		goto odbs_exit1;
 
-	memcpy(hwmods, ohs, sizeof(struct omap_hwmod *) * oh_cnt);
-	od->hwmods = hwmods;
-
-	pdev_name2 = kzalloc(strlen(pdev_name) + 1, GFP_KERNEL);
-	if (!pdev_name2)
-		goto odbs_exit2;
-	strcpy(pdev_name2, pdev_name);
-
-	od->pdev.name = pdev_name2;
-	od->pdev.id = pdev_id;
-
-	res_count = omap_device_count_resources(od);
-	if (res_count > 0) {
-		res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
-		if (!res)
-			goto odbs_exit3;
-	}
-	omap_device_fill_resources(od, res);
-
-	od->pdev.num_resources = res_count;
-	od->pdev.resource = res;
-
-	ret = platform_device_add_data(&od->pdev, pdata, pdata_len);
+	ret = platform_device_add_data(pdev, pdata, pdata_len);
 	if (ret)
-		goto odbs_exit4;
-
-	od->pm_lats = pm_lats;
-	od->pm_lats_cnt = pm_lats_cnt;
+		goto odbs_exit2;
 
 	if (is_early_device)
-		ret = omap_early_device_register(od);
+		ret = omap_early_device_register(pdev);
 	else
-		ret = omap_device_register(od);
-
-	for (i = 0; i < oh_cnt; i++) {
-		hwmods[i]->od = od;
-		_add_hwmod_clocks_clkdev(od, hwmods[i]);
-	}
-
+		ret = omap_device_register(pdev);
 	if (ret)
-		goto odbs_exit4;
+		goto odbs_exit2;
 
-	return od;
+	return pdev;
 
-odbs_exit4:
-	kfree(res);
-odbs_exit3:
-	kfree(pdev_name2);
 odbs_exit2:
-	kfree(hwmods);
+	omap_device_delete(od);
 odbs_exit1:
-	kfree(od);
+	platform_device_put(pdev);
+odbs_exit:
 
 	pr_err("omap_device: %s: build failed (%d)\n", pdev_name, ret);
 
@@ -538,11 +717,11 @@
  * platform_early_add_device() on the underlying platform_device.
  * Returns 0 by default.
  */
-int omap_early_device_register(struct omap_device *od)
+static int omap_early_device_register(struct platform_device *pdev)
 {
 	struct platform_device *devices[1];
 
-	devices[0] = &(od->pdev);
+	devices[0] = pdev;
 	early_platform_add_devices(devices, 1);
 	return 0;
 }
@@ -638,13 +817,13 @@
  * platform_device_register() on the underlying platform_device.
  * Returns the return value of platform_device_register().
  */
-int omap_device_register(struct omap_device *od)
+static int omap_device_register(struct platform_device *pdev)
 {
-	pr_debug("omap_device: %s: registering\n", od->pdev.name);
+	pr_debug("omap_device: %s: registering\n", pdev->name);
 
-	od->pdev.dev.parent = &omap_device_parent;
-	od->pdev.dev.pm_domain = &omap_device_pm_domain;
-	return platform_device_register(&od->pdev);
+	pdev->dev.parent = &omap_device_parent;
+	pdev->dev.pm_domain = &omap_device_pm_domain;
+	return platform_device_add(pdev);
 }
 
 
@@ -671,8 +850,9 @@
 	od = to_omap_device(pdev);
 
 	if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
-		WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
-		     od->pdev.name, od->pdev.id, __func__, od->_state);
+		dev_warn(&pdev->dev,
+			 "omap_device: %s() called from invalid state %d\n",
+			 __func__, od->_state);
 		return -EINVAL;
 	}
 
@@ -710,8 +890,9 @@
 	od = to_omap_device(pdev);
 
 	if (od->_state != OMAP_DEVICE_STATE_ENABLED) {
-		WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
-		     od->pdev.name, od->pdev.id, __func__, od->_state);
+		dev_warn(&pdev->dev,
+			 "omap_device: %s() called from invalid state %d\n",
+			 __func__, od->_state);
 		return -EINVAL;
 	}
 
@@ -742,8 +923,9 @@
 
 	if (od->_state != OMAP_DEVICE_STATE_ENABLED &&
 	    od->_state != OMAP_DEVICE_STATE_IDLE) {
-		WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
-		     od->pdev.name, od->pdev.id, __func__, od->_state);
+		dev_warn(&pdev->dev,
+			 "omap_device: %s() called from invalid state %d\n",
+			 __func__, od->_state);
 		return -EINVAL;
 	}
 
@@ -837,6 +1019,42 @@
 	return omap_hwmod_get_mpu_rt_va(od->hwmods[0]);
 }
 
+/**
+ * omap_device_get_by_hwmod_name() - convert a hwmod name to
+ * device pointer.
+ * @oh_name: name of the hwmod device
+ *
+ * Returns back a struct device * pointer associated with a hwmod
+ * device represented by a hwmod_name
+ */
+struct device *omap_device_get_by_hwmod_name(const char *oh_name)
+{
+	struct omap_hwmod *oh;
+
+	if (!oh_name) {
+		WARN(1, "%s: no hwmod name!\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (IS_ERR_OR_NULL(oh)) {
+		WARN(1, "%s: no hwmod for %s\n", __func__,
+			oh_name);
+		return ERR_PTR(oh ? PTR_ERR(oh) : -ENODEV);
+	}
+	if (IS_ERR_OR_NULL(oh->od)) {
+		WARN(1, "%s: no omap_device for %s\n", __func__,
+			oh_name);
+		return ERR_PTR(oh->od ? PTR_ERR(oh->od) : -ENODEV);
+	}
+
+	if (IS_ERR_OR_NULL(oh->od->pdev))
+		return ERR_PTR(oh->od->pdev ? PTR_ERR(oh->od->pdev) : -ENODEV);
+
+	return &oh->od->pdev->dev;
+}
+EXPORT_SYMBOL(omap_device_get_by_hwmod_name);
+
 /*
  * Public functions intended for use in omap_device_pm_latency
  * .activate_func and .deactivate_func function pointers
@@ -917,8 +1135,13 @@
 	.parent         = &platform_bus,
 };
 
+static struct notifier_block platform_nb = {
+	.notifier_call = _omap_device_notifier_call,
+};
+
 static int __init omap_device_init(void)
 {
+	bus_register_notifier(&platform_bus_type, &platform_nb);
 	return device_register(&omap_device_parent);
 }
 core_initcall(omap_device_init);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/omap-pm-noop.c linux-libre-3.2-gnu/arch/arm/plat-omap/omap-pm-noop.c
--- linux-libre-3.1-gnu/arch/arm/plat-omap/omap-pm-noop.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/omap-pm-noop.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,7 @@
 #include <plat/omap_device.h>
 
 static bool off_mode_enabled;
-static u32 dummy_context_loss_counter;
+static int dummy_context_loss_counter;
 
 /*
  * Device-driver-originated constraints (via board-*.c files)
@@ -311,22 +311,32 @@
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
 
-u32 omap_pm_get_dev_context_loss_count(struct device *dev)
+int omap_pm_get_dev_context_loss_count(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	u32 count;
+	int count;
 
 	if (WARN_ON(!dev))
-		return 0;
+		return -ENODEV;
 
 	if (dev->parent == &omap_device_parent) {
 		count = omap_device_get_context_loss_count(pdev);
 	} else {
 		WARN_ONCE(off_mode_enabled, "omap_pm: using dummy context loss counter; device %s should be converted to omap_device",
 			  dev_name(dev));
-		if (off_mode_enabled)
-			dummy_context_loss_counter++;
+
 		count = dummy_context_loss_counter;
+
+		if (off_mode_enabled) {
+			count++;
+			/*
+			 * Context loss count has to be a non-negative value.
+			 * Clear the sign bit to get a value range from 0 to
+			 * INT_MAX.
+			 */
+			count &= INT_MAX;
+			dummy_context_loss_counter = count;
+		}
 	}
 
 	pr_debug("OMAP PM: context loss count for dev %s = %d\n",
@@ -337,7 +347,7 @@
 
 #else
 
-u32 omap_pm_get_dev_context_loss_count(struct device *dev)
+int omap_pm_get_dev_context_loss_count(struct device *dev)
 {
 	return dummy_context_loss_counter;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/plat-omap/sram.c linux-libre-3.2-gnu/arch/arm/plat-omap/sram.c
--- linux-libre-3.1-gnu/arch/arm/plat-omap/sram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-omap/sram.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/omapfb.h>
 
 #include <asm/tlb.h>
 #include <asm/cacheflush.h>
@@ -29,10 +28,8 @@
 #include <plat/sram.h>
 #include <plat/board.h>
 #include <plat/cpu.h>
-#include <plat/vram.h>
 
 #include "sram.h"
-#include "fb.h"
 
 /* XXX These "sideways" includes are a sign that something is wrong */
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
@@ -41,16 +38,9 @@
 #endif
 
 #define OMAP1_SRAM_PA		0x20000000
-#define OMAP1_SRAM_VA		VMALLOC_END
 #define OMAP2_SRAM_PUB_PA	(OMAP2_SRAM_PA + 0xf800)
-#define OMAP2_SRAM_VA		0xfe400000
-#define OMAP2_SRAM_PUB_VA	(OMAP2_SRAM_VA + 0x800)
-#define OMAP3_SRAM_VA           0xfe400000
 #define OMAP3_SRAM_PUB_PA       (OMAP3_SRAM_PA + 0x8000)
-#define OMAP3_SRAM_PUB_VA       (OMAP3_SRAM_VA + 0x8000)
-#define OMAP4_SRAM_VA		0xfe400000
 #define OMAP4_SRAM_PUB_PA	(OMAP4_SRAM_PA + 0x4000)
-#define OMAP4_SRAM_PUB_VA	(OMAP4_SRAM_VA + 0x4000)
 
 #if defined(CONFIG_ARCH_OMAP2PLUS)
 #define SRAM_BOOTLOADER_SZ	0x00
@@ -73,9 +63,9 @@
 #define ROUND_DOWN(value,boundary)	((value) & (~((boundary)-1)))
 
 static unsigned long omap_sram_start;
-static unsigned long omap_sram_base;
+static void __iomem *omap_sram_base;
 static unsigned long omap_sram_size;
-static unsigned long omap_sram_ceil;
+static void __iomem *omap_sram_ceil;
 
 /*
  * Depending on the target RAMFS firewall setup, the public usable amount of
@@ -112,12 +102,9 @@
  */
 static void __init omap_detect_sram(void)
 {
-	unsigned long reserved;
-
 	if (cpu_class_is_omap2()) {
 		if (is_sram_locked()) {
 			if (cpu_is_omap34xx()) {
-				omap_sram_base = OMAP3_SRAM_PUB_VA;
 				omap_sram_start = OMAP3_SRAM_PUB_PA;
 				if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) ||
 				    (omap_type() == OMAP2_DEVICE_TYPE_SEC)) {
@@ -126,25 +113,20 @@
 					omap_sram_size = 0x8000; /* 32K */
 				}
 			} else if (cpu_is_omap44xx()) {
-				omap_sram_base = OMAP4_SRAM_PUB_VA;
 				omap_sram_start = OMAP4_SRAM_PUB_PA;
 				omap_sram_size = 0xa000; /* 40K */
 			} else {
-				omap_sram_base = OMAP2_SRAM_PUB_VA;
 				omap_sram_start = OMAP2_SRAM_PUB_PA;
 				omap_sram_size = 0x800; /* 2K */
 			}
 		} else {
 			if (cpu_is_omap34xx()) {
-				omap_sram_base = OMAP3_SRAM_VA;
 				omap_sram_start = OMAP3_SRAM_PA;
 				omap_sram_size = 0x10000; /* 64K */
 			} else if (cpu_is_omap44xx()) {
-				omap_sram_base = OMAP4_SRAM_VA;
 				omap_sram_start = OMAP4_SRAM_PA;
 				omap_sram_size = 0xe000; /* 56K */
 			} else {
-				omap_sram_base = OMAP2_SRAM_VA;
 				omap_sram_start = OMAP2_SRAM_PA;
 				if (cpu_is_omap242x())
 					omap_sram_size = 0xa0000; /* 640K */
@@ -153,7 +135,6 @@
 			}
 		}
 	} else {
-		omap_sram_base = OMAP1_SRAM_VA;
 		omap_sram_start = OMAP1_SRAM_PA;
 
 		if (cpu_is_omap7xx())
@@ -170,35 +151,14 @@
 			omap_sram_size = 0x4000;
 		}
 	}
-	reserved = omapfb_reserve_sram(omap_sram_start, omap_sram_base,
-				       omap_sram_size,
-				       omap_sram_start + SRAM_BOOTLOADER_SZ,
-				       omap_sram_size - SRAM_BOOTLOADER_SZ);
-	omap_sram_size -= reserved;
-
-	reserved = omap_vram_reserve_sram(omap_sram_start, omap_sram_base,
-			omap_sram_size,
-			omap_sram_start + SRAM_BOOTLOADER_SZ,
-			omap_sram_size - SRAM_BOOTLOADER_SZ);
-	omap_sram_size -= reserved;
-
-	omap_sram_ceil = omap_sram_base + omap_sram_size;
 }
 
-static struct map_desc omap_sram_io_desc[] __initdata = {
-	{	/* .length gets filled in at runtime */
-		.virtual	= OMAP1_SRAM_VA,
-		.pfn		= __phys_to_pfn(OMAP1_SRAM_PA),
-		.type		= MT_MEMORY
-	}
-};
-
 /*
  * Note that we cannot use ioremap for SRAM, as clock init needs SRAM early.
  */
 static void __init omap_map_sram(void)
 {
-	unsigned long base;
+	int cached = 1;
 
 	if (omap_sram_size == 0)
 		return;
@@ -211,28 +171,18 @@
 		 * the ARM may attempt to write cache lines back to SDRAM
 		 * which will cause the system to hang.
 		 */
-		omap_sram_io_desc[0].type = MT_MEMORY_NONCACHED;
+		cached = 0;
 	}
 
-	omap_sram_io_desc[0].virtual = omap_sram_base;
-	base = omap_sram_start;
-	base = ROUND_DOWN(base, PAGE_SIZE);
-	omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
-	omap_sram_io_desc[0].length = ROUND_DOWN(omap_sram_size, PAGE_SIZE);
-	iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
-
-	pr_info("SRAM: Mapped pa 0x%08llx to va 0x%08lx size: 0x%lx\n",
-		(long long) __pfn_to_phys(omap_sram_io_desc[0].pfn),
-		omap_sram_io_desc[0].virtual,
-		omap_sram_io_desc[0].length);
+	omap_sram_start = ROUND_DOWN(omap_sram_start, PAGE_SIZE);
+	omap_sram_base = __arm_ioremap_exec(omap_sram_start, omap_sram_size,
+						cached);
+	if (!omap_sram_base) {
+		pr_err("SRAM: Could not map\n");
+		return;
+	}
 
-	/*
-	 * Normally devicemaps_init() would flush caches and tlb after
-	 * mdesc->map_io(), but since we're called from map_io(), we
-	 * must do it here.
-	 */
-	local_flush_tlb_all();
-	flush_cache_all();
+	omap_sram_ceil = omap_sram_base + omap_sram_size;
 
 	/*
 	 * Looks like we need to preserve some bootloader code at the
@@ -251,13 +201,18 @@
  */
 void *omap_sram_push_address(unsigned long size)
 {
-	if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
+	unsigned long available, new_ceil = (unsigned long)omap_sram_ceil;
+
+	available = omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ);
+
+	if (size > available) {
 		pr_err("Not enough space in SRAM\n");
 		return NULL;
 	}
 
-	omap_sram_ceil -= size;
-	omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, FNCPY_ALIGN);
+	new_ceil -= size;
+	new_ceil = ROUND_DOWN(new_ceil, FNCPY_ALIGN);
+	omap_sram_ceil = IOMEM(new_ceil);
 
 	return (void *)omap_sram_ceil;
 }
diff -druN linux-libre-3.1-gnu/arch/arm/plat-orion/gpio.c linux-libre-3.2-gnu/arch/arm/plat-orion/gpio.c
--- linux-libre-3.1-gnu/arch/arm/plat-orion/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-orion/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -384,12 +384,16 @@
 	struct orion_gpio_chip *ochip;
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
+	char gc_label[16];
 
 	if (orion_gpio_chip_count == ARRAY_SIZE(orion_gpio_chips))
 		return;
 
+	snprintf(gc_label, sizeof(gc_label), "orion_gpio%d",
+		orion_gpio_chip_count);
+
 	ochip = orion_gpio_chips + orion_gpio_chip_count;
-	ochip->chip.label = "orion_gpio";
+	ochip->chip.label = kstrdup(gc_label, GFP_KERNEL);
 	ochip->chip.request = orion_gpio_request;
 	ochip->chip.direction_input = orion_gpio_direction_input;
 	ochip->chip.get = orion_gpio_get;
diff -druN linux-libre-3.1-gnu/arch/arm/plat-orion/include/plat/gpio.h linux-libre-3.2-gnu/arch/arm/plat-orion/include/plat/gpio.h
--- linux-libre-3.1-gnu/arch/arm/plat-orion/include/plat/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-orion/include/plat/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -12,15 +12,7 @@
 #define __PLAT_GPIO_H
 
 #include <linux/init.h>
-#include <asm-generic/gpio.h>
-
-/*
- * GENERIC_GPIO primitives.
- */
-#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
+#include <linux/types.h>
 
 /*
  * Orion-specific GPIO API extensions.
diff -druN linux-libre-3.1-gnu/arch/arm/plat-pxa/gpio.c linux-libre-3.2-gnu/arch/arm/plat-pxa/gpio.c
--- linux-libre-3.1-gnu/arch/arm/plat-pxa/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-pxa/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,338 +0,0 @@
-/*
- *  linux/arch/arm/plat-pxa/gpio.c
- *
- *  Generic PXA GPIO handling
- *
- *  Author:	Nicolas Pitre
- *  Created:	Jun 15, 2001
- *  Copyright:	MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-#include <linux/slab.h>
-
-#include <mach/gpio.h>
-
-int pxa_last_gpio;
-
-struct pxa_gpio_chip {
-	struct gpio_chip chip;
-	void __iomem	*regbase;
-	char label[10];
-
-	unsigned long	irq_mask;
-	unsigned long	irq_edge_rise;
-	unsigned long	irq_edge_fall;
-
-#ifdef CONFIG_PM
-	unsigned long	saved_gplr;
-	unsigned long	saved_gpdr;
-	unsigned long	saved_grer;
-	unsigned long	saved_gfer;
-#endif
-};
-
-static DEFINE_SPINLOCK(gpio_lock);
-static struct pxa_gpio_chip *pxa_gpio_chips;
-
-#define for_each_gpio_chip(i, c)			\
-	for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++)
-
-static inline void __iomem *gpio_chip_base(struct gpio_chip *c)
-{
-	return container_of(c, struct pxa_gpio_chip, chip)->regbase;
-}
-
-static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio)
-{
-	return &pxa_gpio_chips[gpio_to_bank(gpio)];
-}
-
-static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	void __iomem *base = gpio_chip_base(chip);
-	uint32_t value, mask = 1 << offset;
-	unsigned long flags;
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	value = __raw_readl(base + GPDR_OFFSET);
-	if (__gpio_is_inverted(chip->base + offset))
-		value |= mask;
-	else
-		value &= ~mask;
-	__raw_writel(value, base + GPDR_OFFSET);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-	return 0;
-}
-
-static int pxa_gpio_direction_output(struct gpio_chip *chip,
-				     unsigned offset, int value)
-{
-	void __iomem *base = gpio_chip_base(chip);
-	uint32_t tmp, mask = 1 << offset;
-	unsigned long flags;
-
-	__raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	tmp = __raw_readl(base + GPDR_OFFSET);
-	if (__gpio_is_inverted(chip->base + offset))
-		tmp &= ~mask;
-	else
-		tmp |= mask;
-	__raw_writel(tmp, base + GPDR_OFFSET);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-	return 0;
-}
-
-static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset);
-}
-
-static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	__raw_writel(1 << offset, gpio_chip_base(chip) +
-				(value ? GPSR_OFFSET : GPCR_OFFSET));
-}
-
-static int __init pxa_init_gpio_chip(int gpio_end)
-{
-	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
-	struct pxa_gpio_chip *chips;
-
-	chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL);
-	if (chips == NULL) {
-		pr_err("%s: failed to allocate GPIO chips\n", __func__);
-		return -ENOMEM;
-	}
-
-	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
-		struct gpio_chip *c = &chips[i].chip;
-
-		sprintf(chips[i].label, "gpio-%d", i);
-		chips[i].regbase = (void __iomem *)GPIO_BANK(i);
-
-		c->base  = gpio;
-		c->label = chips[i].label;
-
-		c->direction_input  = pxa_gpio_direction_input;
-		c->direction_output = pxa_gpio_direction_output;
-		c->get = pxa_gpio_get;
-		c->set = pxa_gpio_set;
-
-		/* number of GPIOs on last bank may be less than 32 */
-		c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32;
-		gpiochip_add(c);
-	}
-	pxa_gpio_chips = chips;
-	return 0;
-}
-
-/* Update only those GRERx and GFERx edge detection register bits if those
- * bits are set in c->irq_mask
- */
-static inline void update_edge_detect(struct pxa_gpio_chip *c)
-{
-	uint32_t grer, gfer;
-
-	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask;
-	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask;
-	grer |= c->irq_edge_rise & c->irq_mask;
-	gfer |= c->irq_edge_fall & c->irq_mask;
-	__raw_writel(grer, c->regbase + GRER_OFFSET);
-	__raw_writel(gfer, c->regbase + GFER_OFFSET);
-}
-
-static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
-{
-	struct pxa_gpio_chip *c;
-	int gpio = irq_to_gpio(d->irq);
-	unsigned long gpdr, mask = GPIO_bit(gpio);
-
-	c = gpio_to_pxachip(gpio);
-
-	if (type == IRQ_TYPE_PROBE) {
-		/* Don't mess with enabled GPIOs using preconfigured edges or
-		 * GPIOs set to alternate function or to output during probe
-		 */
-		if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio))
-			return 0;
-
-		if (__gpio_is_occupied(gpio))
-			return 0;
-
-		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
-	}
-
-	gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
-
-	if (__gpio_is_inverted(gpio))
-		__raw_writel(gpdr | mask,  c->regbase + GPDR_OFFSET);
-	else
-		__raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET);
-
-	if (type & IRQ_TYPE_EDGE_RISING)
-		c->irq_edge_rise |= mask;
-	else
-		c->irq_edge_rise &= ~mask;
-
-	if (type & IRQ_TYPE_EDGE_FALLING)
-		c->irq_edge_fall |= mask;
-	else
-		c->irq_edge_fall &= ~mask;
-
-	update_edge_detect(c);
-
-	pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, d->irq, gpio,
-		((type & IRQ_TYPE_EDGE_RISING)  ? " rising"  : ""),
-		((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : ""));
-	return 0;
-}
-
-static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
-{
-	struct pxa_gpio_chip *c;
-	int loop, gpio, gpio_base, n;
-	unsigned long gedr;
-
-	do {
-		loop = 0;
-		for_each_gpio_chip(gpio, c) {
-			gpio_base = c->chip.base;
-
-			gedr = __raw_readl(c->regbase + GEDR_OFFSET);
-			gedr = gedr & c->irq_mask;
-			__raw_writel(gedr, c->regbase + GEDR_OFFSET);
-
-			n = find_first_bit(&gedr, BITS_PER_LONG);
-			while (n < BITS_PER_LONG) {
-				loop = 1;
-
-				generic_handle_irq(gpio_to_irq(gpio_base + n));
-				n = find_next_bit(&gedr, BITS_PER_LONG, n + 1);
-			}
-		}
-	} while (loop);
-}
-
-static void pxa_ack_muxed_gpio(struct irq_data *d)
-{
-	int gpio = irq_to_gpio(d->irq);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
-
-	__raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET);
-}
-
-static void pxa_mask_muxed_gpio(struct irq_data *d)
-{
-	int gpio = irq_to_gpio(d->irq);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
-	uint32_t grer, gfer;
-
-	c->irq_mask &= ~GPIO_bit(gpio);
-
-	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio);
-	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio);
-	__raw_writel(grer, c->regbase + GRER_OFFSET);
-	__raw_writel(gfer, c->regbase + GFER_OFFSET);
-}
-
-static void pxa_unmask_muxed_gpio(struct irq_data *d)
-{
-	int gpio = irq_to_gpio(d->irq);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
-
-	c->irq_mask |= GPIO_bit(gpio);
-	update_edge_detect(c);
-}
-
-static struct irq_chip pxa_muxed_gpio_chip = {
-	.name		= "GPIO",
-	.irq_ack	= pxa_ack_muxed_gpio,
-	.irq_mask	= pxa_mask_muxed_gpio,
-	.irq_unmask	= pxa_unmask_muxed_gpio,
-	.irq_set_type	= pxa_gpio_irq_type,
-};
-
-void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn)
-{
-	struct pxa_gpio_chip *c;
-	int gpio, irq;
-
-	pxa_last_gpio = end;
-
-	/* Initialize GPIO chips */
-	pxa_init_gpio_chip(end);
-
-	/* clear all GPIO edge detects */
-	for_each_gpio_chip(gpio, c) {
-		__raw_writel(0, c->regbase + GFER_OFFSET);
-		__raw_writel(0, c->regbase + GRER_OFFSET);
-		__raw_writel(~0,c->regbase + GEDR_OFFSET);
-	}
-
-	for (irq  = gpio_to_irq(start); irq <= gpio_to_irq(end); 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 */
-	irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler);
-	pxa_muxed_gpio_chip.irq_set_wake = fn;
-}
-
-#ifdef CONFIG_PM
-static int pxa_gpio_suspend(void)
-{
-	struct pxa_gpio_chip *c;
-	int gpio;
-
-	for_each_gpio_chip(gpio, c) {
-		c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET);
-		c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
-		c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET);
-		c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET);
-
-		/* Clear GPIO transition detect bits */
-		__raw_writel(0xffffffff, c->regbase + GEDR_OFFSET);
-	}
-	return 0;
-}
-
-static void pxa_gpio_resume(void)
-{
-	struct pxa_gpio_chip *c;
-	int gpio;
-
-	for_each_gpio_chip(gpio, c) {
-		/* restore level with set/clear */
-		__raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET);
-		__raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET);
-
-		__raw_writel(c->saved_grer, c->regbase + GRER_OFFSET);
-		__raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET);
-		__raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET);
-	}
-}
-#else
-#define pxa_gpio_suspend	NULL
-#define pxa_gpio_resume		NULL
-#endif
-
-struct syscore_ops pxa_gpio_syscore_ops = {
-	.suspend	= pxa_gpio_suspend,
-	.resume		= pxa_gpio_resume,
-};
diff -druN linux-libre-3.1-gnu/arch/arm/plat-pxa/include/plat/gpio.h linux-libre-3.2-gnu/arch/arm/plat-pxa/include/plat/gpio.h
--- linux-libre-3.1-gnu/arch/arm/plat-pxa/include/plat/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-pxa/include/plat/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,35 +1,10 @@
 #ifndef __PLAT_GPIO_H
 #define __PLAT_GPIO_H
 
-struct irq_data;
-
-/*
- * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
- * one set of registers. The register offsets are organized below:
- *
- *           GPLR    GPDR    GPSR    GPCR    GRER    GFER    GEDR
- * BANK 0 - 0x0000  0x000C  0x0018  0x0024  0x0030  0x003C  0x0048
- * BANK 1 - 0x0004  0x0010  0x001C  0x0028  0x0034  0x0040  0x004C
- * BANK 2 - 0x0008  0x0014  0x0020  0x002C  0x0038  0x0044  0x0050
- *
- * BANK 3 - 0x0100  0x010C  0x0118  0x0124  0x0130  0x013C  0x0148
- * BANK 4 - 0x0104  0x0110  0x011C  0x0128  0x0134  0x0140  0x014C
- * BANK 5 - 0x0108  0x0114  0x0120  0x012C  0x0138  0x0144  0x0150
- *
- * NOTE:
- *   BANK 3 is only available on PXA27x and later processors.
- *   BANK 4 and 5 are only available on PXA935
- */
-
-#define GPIO_BANK(n)	(GPIO_REGS_VIRT + BANK_OFF(n))
+#define __ARM_GPIOLIB_COMPLEX
 
-#define GPLR_OFFSET	0x00
-#define GPDR_OFFSET	0x0C
-#define GPSR_OFFSET	0x18
-#define GPCR_OFFSET	0x24
-#define GRER_OFFSET	0x30
-#define GFER_OFFSET	0x3C
-#define GEDR_OFFSET	0x48
+/* The individual machine provides register offsets and NR_BUILTIN_GPIO */
+#include <mach/gpio-pxa.h>
 
 static inline int gpio_get_value(unsigned gpio)
 {
@@ -52,13 +27,4 @@
 
 #define gpio_cansleep		__gpio_cansleep
 
-/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85).
- * Those cases currently cause holes in the GPIO number space, the
- * actual number of the last GPIO is recorded by 'pxa_last_gpio'.
- */
-extern int pxa_last_gpio;
-
-typedef int (*set_wake_t)(struct irq_data *d, unsigned int on);
-
-extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn);
 #endif /* __PLAT_GPIO_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-pxa/include/plat/gpio-pxa.h linux-libre-3.2-gnu/arch/arm/plat-pxa/include/plat/gpio-pxa.h
--- linux-libre-3.1-gnu/arch/arm/plat-pxa/include/plat/gpio-pxa.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-pxa/include/plat/gpio-pxa.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,44 @@
+#ifndef __PLAT_PXA_GPIO_H
+#define __PLAT_PXA_GPIO_H
+
+struct irq_data;
+
+/*
+ * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
+ * one set of registers. The register offsets are organized below:
+ *
+ *           GPLR    GPDR    GPSR    GPCR    GRER    GFER    GEDR
+ * BANK 0 - 0x0000  0x000C  0x0018  0x0024  0x0030  0x003C  0x0048
+ * BANK 1 - 0x0004  0x0010  0x001C  0x0028  0x0034  0x0040  0x004C
+ * BANK 2 - 0x0008  0x0014  0x0020  0x002C  0x0038  0x0044  0x0050
+ *
+ * BANK 3 - 0x0100  0x010C  0x0118  0x0124  0x0130  0x013C  0x0148
+ * BANK 4 - 0x0104  0x0110  0x011C  0x0128  0x0134  0x0140  0x014C
+ * BANK 5 - 0x0108  0x0114  0x0120  0x012C  0x0138  0x0144  0x0150
+ *
+ * NOTE:
+ *   BANK 3 is only available on PXA27x and later processors.
+ *   BANK 4 and 5 are only available on PXA935
+ */
+
+#define GPIO_BANK(n)	(GPIO_REGS_VIRT + BANK_OFF(n))
+
+#define GPLR_OFFSET	0x00
+#define GPDR_OFFSET	0x0C
+#define GPSR_OFFSET	0x18
+#define GPCR_OFFSET	0x24
+#define GRER_OFFSET	0x30
+#define GFER_OFFSET	0x3C
+#define GEDR_OFFSET	0x48
+
+/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85).
+ * Those cases currently cause holes in the GPIO number space, the
+ * actual number of the last GPIO is recorded by 'pxa_last_gpio'.
+ */
+extern int pxa_last_gpio;
+
+typedef int (*set_wake_t)(struct irq_data *d, unsigned int on);
+
+extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn);
+
+#endif /* __PLAT_PXA_GPIO_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-pxa/include/plat/mfp.h linux-libre-3.2-gnu/arch/arm/plat-pxa/include/plat/mfp.h
--- linux-libre-3.1-gnu/arch/arm/plat-pxa/include/plat/mfp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-pxa/include/plat/mfp.h	2012-01-04 18:55:44.000000000 -0500
@@ -456,7 +456,7 @@
 
 #define MFP_ADDR_END	{ MFP_PIN_INVALID, 0 }
 
-void __init mfp_init_base(unsigned long mfpr_base);
+void __init mfp_init_base(void __iomem *mfpr_base);
 void __init mfp_init_addr(struct mfp_addr_map *map);
 
 /*
diff -druN linux-libre-3.1-gnu/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h linux-libre-3.2-gnu/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
--- linux-libre-3.1-gnu/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,19 @@
 	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
 };
 
+/*
+ * Current pxa3xx_nand controller has two chip select which
+ * both be workable.
+ *
+ * Notice should be taken that:
+ * When you want to use this feature, you should not enable the
+ * keep configuration feature, for two chip select could be
+ * attached with different nand chip. The different page size
+ * and timing requirement make the keep configuration impossible.
+ */
+
+/* The max num of chip select current support */
+#define NUM_CHIP_SELECT		(2)
 struct pxa3xx_nand_platform_data {
 
 	/* the data flash bus is shared between the Static Memory
@@ -52,8 +65,11 @@
 	/* allow platform code to keep OBM/bootloader defined NFC config */
 	int	keep_config;
 
-	const struct mtd_partition		*parts;
-	unsigned int				nr_parts;
+	/* indicate how many chip selects will be used */
+	int	num_cs;
+
+	const struct mtd_partition		*parts[NUM_CHIP_SELECT];
+	unsigned int				nr_parts[NUM_CHIP_SELECT];
 
 	const struct pxa3xx_nand_flash * 	flash;
 	size_t					num_flash;
diff -druN linux-libre-3.1-gnu/arch/arm/plat-pxa/Makefile linux-libre-3.2-gnu/arch/arm/plat-pxa/Makefile
--- linux-libre-3.1-gnu/arch/arm/plat-pxa/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-pxa/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,6 @@
 
 obj-y	:= dma.o
 
-obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
 obj-$(CONFIG_PXA3xx)		+= mfp.o
 obj-$(CONFIG_PXA95x)		+= mfp.o
 obj-$(CONFIG_ARCH_MMP)		+= mfp.o
diff -druN linux-libre-3.1-gnu/arch/arm/plat-pxa/mfp.c linux-libre-3.2-gnu/arch/arm/plat-pxa/mfp.c
--- linux-libre-3.1-gnu/arch/arm/plat-pxa/mfp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-pxa/mfp.c	2012-01-04 18:55:44.000000000 -0500
@@ -229,7 +229,7 @@
 	spin_unlock_irqrestore(&mfp_spin_lock, flags);
 }
 
-void __init mfp_init_base(unsigned long mfpr_base)
+void __init mfp_init_base(void __iomem *mfpr_base)
 {
 	int i;
 
@@ -237,7 +237,7 @@
 	for (i = 0; i < ARRAY_SIZE(mfp_table); i++)
 		mfp_table[i].config = -1;
 
-	mfpr_mmio_base = (void __iomem *)mfpr_base;
+	mfpr_mmio_base = mfpr_base;
 }
 
 void __init mfp_init_addr(struct mfp_addr_map *map)
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/cpu.c linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/cpu.c
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -215,19 +215,18 @@
 
 void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 {
-	unsigned long idcode = 0x0;
-
 	/* initialise the io descriptors we need for initialisation */
 	iotable_init(mach_desc, size);
 	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
 
 	if (cpu_architecture() >= CPU_ARCH_ARMv5) {
-		idcode = s3c24xx_read_idcode_v5();
+		samsung_cpu_id = s3c24xx_read_idcode_v5();
 	} else {
-		idcode = s3c24xx_read_idcode_v4();
+		samsung_cpu_id = s3c24xx_read_idcode_v4();
 	}
+	s3c24xx_init_cpu();
 
 	arm_pm_restart = s3c24xx_pm_restart;
 
-	s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
+	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
 }
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
 */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/cpufreq.h>
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/devs.c linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/devs.c
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/devs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/devs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,528 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/devs.c
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Base S3C24XX platform 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/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <mach/fb.h>
-#include <mach/hardware.h>
-#include <mach/dma.h>
-#include <mach/irqs.h>
-#include <asm/irq.h>
-
-#include <plat/regs-serial.h>
-#include <plat/udc.h>
-#include <plat/mci.h>
-
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <plat/regs-spi.h>
-#include <plat/ts.h>
-
-/* Serial port registrations */
-
-static struct resource s3c2410_uart0_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART0,
-		.end   = S3C2410_PA_UART0 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX0,
-		.end   = IRQ_S3CUART_ERR0,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static struct resource s3c2410_uart1_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART1,
-		.end   = S3C2410_PA_UART1 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX1,
-		.end   = IRQ_S3CUART_ERR1,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static struct resource s3c2410_uart2_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART2,
-		.end   = S3C2410_PA_UART2 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX2,
-		.end   = IRQ_S3CUART_ERR2,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static struct resource s3c2410_uart3_resource[] = {
-	[0] = {
-		.start = S3C2443_PA_UART3,
-		.end   = S3C2443_PA_UART3 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX3,
-		.end   = IRQ_S3CUART_ERR3,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = {
-	[0] = {
-		.resources	= s3c2410_uart0_resource,
-		.nr_resources	= ARRAY_SIZE(s3c2410_uart0_resource),
-	},
-	[1] = {
-		.resources	= s3c2410_uart1_resource,
-		.nr_resources	= ARRAY_SIZE(s3c2410_uart1_resource),
-	},
-	[2] = {
-		.resources	= s3c2410_uart2_resource,
-		.nr_resources	= ARRAY_SIZE(s3c2410_uart2_resource),
-	},
-	[3] = {
-		.resources	= s3c2410_uart3_resource,
-		.nr_resources	= ARRAY_SIZE(s3c2410_uart3_resource),
-	},
-};
-
-/* LCD Controller */
-
-static struct resource s3c_lcd_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_LCD,
-		.end   = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_LCD,
-		.end   = IRQ_LCD,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-static u64 s3c_device_lcd_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_lcd = {
-	.name		  = "s3c2410-lcd",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_lcd_resource),
-	.resource	  = s3c_lcd_resource,
-	.dev              = {
-		.dma_mask		= &s3c_device_lcd_dmamask,
-		.coherent_dma_mask	= 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_lcd);
-
-void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
-{
-	struct s3c2410fb_mach_info *npd;
-
-	npd = s3c_set_platdata(pd, sizeof(*npd), &s3c_device_lcd);
-	if (npd) {
-		npd->displays = kmemdup(pd->displays,
-			sizeof(struct s3c2410fb_display) * npd->num_displays,
-			GFP_KERNEL);
-		if (!npd->displays)
-			printk(KERN_ERR "no memory for LCD display data\n");
-	} else {
-		printk(KERN_ERR "no memory for LCD platform data\n");
-	}
-}
-
-/* Touchscreen */
-
-static struct resource s3c_ts_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_ADC,
-		.end   = S3C24XX_PA_ADC + S3C24XX_SZ_ADC - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_TC,
-		.end   = IRQ_TC,
-		.flags = IORESOURCE_IRQ,
-	},
-
-};
-
-struct platform_device s3c_device_ts = {
-	.name		  = "s3c2410-ts",
-	.id		  = -1,
-	.dev.parent	= &s3c_device_adc.dev,
-	.num_resources	  = ARRAY_SIZE(s3c_ts_resource),
-	.resource	  = s3c_ts_resource,
-};
-EXPORT_SYMBOL(s3c_device_ts);
-
-void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
-{
-	s3c_set_platdata(hard_s3c2410ts_info,
-			 sizeof(struct s3c2410_ts_mach_info), &s3c_device_ts);
-}
-
-/* USB Device (Gadget)*/
-
-static struct resource s3c_usbgadget_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_USBDEV,
-		.end   = S3C24XX_PA_USBDEV + S3C24XX_SZ_USBDEV - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_USBD,
-		.end   = IRQ_USBD,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-struct platform_device s3c_device_usbgadget = {
-	.name		  = "s3c2410-usbgadget",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_usbgadget_resource),
-	.resource	  = s3c_usbgadget_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_usbgadget);
-
-void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd)
-{
-	s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usbgadget);
-}
-
-/* USB High Speed 2.0 Device (Gadget) */
-static struct resource s3c_hsudc_resource[] = {
-	[0] = {
-		.start	= S3C2416_PA_HSUDC,
-		.end	= S3C2416_PA_HSUDC + S3C2416_SZ_HSUDC - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_USBD,
-		.end	= IRQ_USBD,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static u64 s3c_hsudc_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s3c_device_usb_hsudc = {
-	.name		= "s3c-hsudc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s3c_hsudc_resource),
-	.resource	= s3c_hsudc_resource,
-	.dev		= {
-		.dma_mask		= &s3c_hsudc_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd)
-{
-	s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usb_hsudc);
-}
-
-/* IIS */
-
-static struct resource s3c_iis_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_IIS,
-		.end   = S3C24XX_PA_IIS + S3C24XX_SZ_IIS -1,
-		.flags = IORESOURCE_MEM,
-	}
-};
-
-static u64 s3c_device_iis_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_iis = {
-	.name		  = "s3c24xx-iis",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_iis_resource),
-	.resource	  = s3c_iis_resource,
-	.dev              = {
-		.dma_mask = &s3c_device_iis_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_iis);
-
-/* RTC */
-
-static struct resource s3c_rtc_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_RTC,
-		.end   = S3C24XX_PA_RTC + 0xff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_RTC,
-		.end   = IRQ_RTC,
-		.flags = IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start = IRQ_TICK,
-		.end   = IRQ_TICK,
-		.flags = IORESOURCE_IRQ
-	}
-};
-
-struct platform_device s3c_device_rtc = {
-	.name		  = "s3c2410-rtc",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_rtc_resource),
-	.resource	  = s3c_rtc_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_rtc);
-
-/* ADC */
-
-static struct resource s3c_adc_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_ADC,
-		.end   = S3C24XX_PA_ADC + S3C24XX_SZ_ADC - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_TC,
-		.end   = IRQ_TC,
-		.flags = IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start = IRQ_ADC,
-		.end   = IRQ_ADC,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-struct platform_device s3c_device_adc = {
-	.name		  = "s3c24xx-adc",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_adc_resource),
-	.resource	  = s3c_adc_resource,
-};
-
-/* SDI */
-
-static struct resource s3c_sdi_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_SDI,
-		.end   = S3C24XX_PA_SDI + S3C24XX_SZ_SDI - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_SDI,
-		.end   = IRQ_SDI,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-struct platform_device s3c_device_sdi = {
-	.name		  = "s3c2410-sdi",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_sdi_resource),
-	.resource	  = s3c_sdi_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_sdi);
-
-void __init s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata)
-{
-	s3c_set_platdata(pdata, sizeof(struct s3c24xx_mci_pdata),
-			 &s3c_device_sdi);
-}
-
-
-/* SPI (0) */
-
-static struct resource s3c_spi0_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_SPI,
-		.end   = S3C24XX_PA_SPI + 0x1f,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_SPI0,
-		.end   = IRQ_SPI0,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-static u64 s3c_device_spi0_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_spi0 = {
-	.name		  = "s3c2410-spi",
-	.id		  = 0,
-	.num_resources	  = ARRAY_SIZE(s3c_spi0_resource),
-	.resource	  = s3c_spi0_resource,
-        .dev              = {
-                .dma_mask = &s3c_device_spi0_dmamask,
-                .coherent_dma_mask = 0xffffffffUL
-        }
-};
-
-EXPORT_SYMBOL(s3c_device_spi0);
-
-/* SPI (1) */
-
-static struct resource s3c_spi1_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_SPI + S3C2410_SPI1,
-		.end   = S3C24XX_PA_SPI + S3C2410_SPI1 + 0x1f,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_SPI1,
-		.end   = IRQ_SPI1,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-static u64 s3c_device_spi1_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_spi1 = {
-	.name		  = "s3c2410-spi",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s3c_spi1_resource),
-	.resource	  = s3c_spi1_resource,
-        .dev              = {
-                .dma_mask = &s3c_device_spi1_dmamask,
-                .coherent_dma_mask = 0xffffffffUL
-        }
-};
-
-EXPORT_SYMBOL(s3c_device_spi1);
-
-#ifdef CONFIG_CPU_S3C2440
-
-/* Camif Controller */
-
-static struct resource s3c_camif_resource[] = {
-	[0] = {
-		.start = S3C2440_PA_CAMIF,
-		.end   = S3C2440_PA_CAMIF + S3C2440_SZ_CAMIF - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_CAM,
-		.end   = IRQ_CAM,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-static u64 s3c_device_camif_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_camif = {
-	.name		  = "s3c2440-camif",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_camif_resource),
-	.resource	  = s3c_camif_resource,
-	.dev              = {
-		.dma_mask = &s3c_device_camif_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_camif);
-
-/* AC97 */
-
-static struct resource s3c_ac97_resource[] = {
-	[0] = {
-		.start = S3C2440_PA_AC97,
-		.end   = S3C2440_PA_AC97 + S3C2440_SZ_AC97 -1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3C244x_AC97,
-		.end   = IRQ_S3C244x_AC97,
-		.flags = IORESOURCE_IRQ,
-	},
-	[2] = {
-		.name  = "PCM out",
-		.start = DMACH_PCM_OUT,
-		.end   = DMACH_PCM_OUT,
-		.flags = IORESOURCE_DMA,
-	},
-	[3] = {
-		.name  = "PCM in",
-		.start = DMACH_PCM_IN,
-		.end   = DMACH_PCM_IN,
-		.flags = IORESOURCE_DMA,
-	},
-	[4] = {
-		.name  = "Mic in",
-		.start = DMACH_MIC_IN,
-		.end   = DMACH_MIC_IN,
-		.flags = IORESOURCE_DMA,
-	},
-};
-
-static u64 s3c_device_audio_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_ac97 = {
-	.name		  = "samsung-ac97",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_ac97_resource),
-	.resource	  = s3c_ac97_resource,
-	.dev              = {
-		.dma_mask = &s3c_device_audio_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_ac97);
-
-/* ASoC I2S */
-
-struct platform_device s3c2412_device_iis = {
-	.name		  = "s3c2412-iis",
-	.id		  = -1,
-	.dev              = {
-		.dma_mask = &s3c_device_audio_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c2412_device_iis);
-
-#endif // CONFIG_CPU_S32440
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/dev-uart.c linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/dev-uart.c
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/dev-uart.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/dev-uart.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,100 @@
+/* linux/arch/arm/plat-s3c24xx/dev-uart.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Base S3C24XX UART resource and platform 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/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+#include <plat/regs-serial.h>
+
+/* Serial port registrations */
+
+static struct resource s3c2410_uart0_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART0,
+		.end   = S3C2410_PA_UART0 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX0,
+		.end   = IRQ_S3CUART_ERR0,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource s3c2410_uart1_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART1,
+		.end   = S3C2410_PA_UART1 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX1,
+		.end   = IRQ_S3CUART_ERR1,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource s3c2410_uart2_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART2,
+		.end   = S3C2410_PA_UART2 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX2,
+		.end   = IRQ_S3CUART_ERR2,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource s3c2410_uart3_resource[] = {
+	[0] = {
+		.start = S3C2443_PA_UART3,
+		.end   = S3C2443_PA_UART3 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX3,
+		.end   = IRQ_S3CUART_ERR3,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = {
+	[0] = {
+		.resources	= s3c2410_uart0_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart0_resource),
+	},
+	[1] = {
+		.resources	= s3c2410_uart1_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart1_resource),
+	},
+	[2] = {
+		.resources	= s3c2410_uart2_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart2_resource),
+	},
+	[3] = {
+		.resources	= s3c2410_uart3_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart3_resource),
+	},
+};
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/dma.c linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/dma.c
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -1094,14 +1094,14 @@
  *
  * configure the dma source/destination hardware type and address
  *
- * source:    S3C2410_DMASRC_HW: source is hardware
- *            S3C2410_DMASRC_MEM: source is memory
+ * source:    DMA_FROM_DEVICE: source is hardware
+ *            DMA_TO_DEVICE: source is memory
  *
  * devaddr:   physical address of the source
 */
 
 int s3c2410_dma_devconfig(enum dma_ch channel,
-			  enum s3c2410_dmasrc source,
+			  enum dma_data_direction source,
 			  unsigned long devaddr)
 {
 	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
@@ -1131,7 +1131,7 @@
 	 hwcfg |= S3C2410_DISRCC_INC;
 
 	switch (source) {
-	case S3C2410_DMASRC_HW:
+	case DMA_FROM_DEVICE:
 		/* source is hardware */
 		pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
 			 __func__, devaddr, hwcfg);
@@ -1142,7 +1142,7 @@
 		chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
 		break;
 
-	case S3C2410_DMASRC_MEM:
+	case DMA_TO_DEVICE:
 		/* source is memory */
 		pr_debug("%s: mem source, devaddr=%08lx, hwcfg=%d\n",
 			 __func__, devaddr, hwcfg);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/gpio.c linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/gpio.c
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,96 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/gpio.c
- *
- * Copyright (c) 2004-2010 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX GPIO support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/gpio-fns.h>
-#include <asm/irq.h>
-
-#include <mach/regs-gpio.h>
-
-#include <plat/gpio-core.h>
-
-/* gpiolib wrappers until these are totally eliminated */
-
-void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
-{
-	int ret;
-
-	WARN_ON(to);	/* should be none of these left */
-
-	if (!to) {
-		/* if pull is enabled, try first with up, and if that
-		 * fails, try using down */
-
-		ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
-		if (ret)
-			s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
-	} else {
-		s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
-	}
-}
-EXPORT_SYMBOL(s3c2410_gpio_pullup);
-
-void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
-{
-	/* do this via gpiolib until all users removed */
-
-	gpio_request(pin, "temporary");
-	gpio_set_value(pin, to);
-	gpio_free(pin);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_setpin);
-
-unsigned int s3c2410_gpio_getpin(unsigned int pin)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned long offs = pin - chip->chip.base;
-
-	return __raw_readl(chip->base + 0x04) & (1<< offs);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_getpin);
-
-unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
-{
-	unsigned long flags;
-	unsigned long misccr;
-
-	local_irq_save(flags);
-	misccr = __raw_readl(S3C24XX_MISCCR);
-	misccr &= ~clear;
-	misccr ^= change;
-	__raw_writel(misccr, S3C24XX_MISCCR);
-	local_irq_restore(flags);
-
-	return misccr;
-}
-
-EXPORT_SYMBOL(s3c2410_modify_misccr);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/gpiolib.c linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/gpiolib.c
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/gpiolib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/gpiolib.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,229 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/gpiolib.c
- *
- * Copyright (c) 2008-2010 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX GPIOlib support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/sysdev.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <plat/pm.h>
-
-#include <mach/regs-gpio.h>
-
-static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
-{
-	return -EINVAL;
-}
-
-static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
-					unsigned offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long flags;
-	unsigned long dat;
-	unsigned long con;
-
-	local_irq_save(flags);
-
-	con = __raw_readl(base + 0x00);
-	dat = __raw_readl(base + 0x04);
-
-	dat &= ~(1 << offset);
-	if (value)
-		dat |= 1 << offset;
-
-	__raw_writel(dat, base + 0x04);
-
-	con &= ~(1 << offset);
-
-	__raw_writel(con, base + 0x00);
-	__raw_writel(dat, base + 0x04);
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-static int s3c24xx_gpiolib_bankf_toirq(struct gpio_chip *chip, unsigned offset)
-{
-	if (offset < 4)
-		return IRQ_EINT0 + offset;
-	
-	if (offset < 8)
-		return IRQ_EINT4 + offset - 4;
-	
-	return -EINVAL;
-}
-
-static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = {
-	.set_config	= s3c_gpio_setcfg_s3c24xx_a,
-	.get_config	= s3c_gpio_getcfg_s3c24xx_a,
-};
-
-struct s3c_gpio_cfg s3c24xx_gpiocfg_default = {
-	.set_config	= s3c_gpio_setcfg_s3c24xx,
-	.get_config	= s3c_gpio_getcfg_s3c24xx,
-};
-
-struct s3c_gpio_chip s3c24xx_gpios[] = {
-	[0] = {
-		.base	= S3C2410_GPACON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_1bit),
-		.config	= &s3c24xx_gpiocfg_banka,
-		.chip	= {
-			.base			= S3C2410_GPA(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOA",
-			.ngpio			= 24,
-			.direction_input	= s3c24xx_gpiolib_banka_input,
-			.direction_output	= s3c24xx_gpiolib_banka_output,
-		},
-	},
-	[1] = {
-		.base	= S3C2410_GPBCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPB(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOB",
-			.ngpio			= 16,
-		},
-	},
-	[2] = {
-		.base	= S3C2410_GPCCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPC(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOC",
-			.ngpio			= 16,
-		},
-	},
-	[3] = {
-		.base	= S3C2410_GPDCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPD(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOD",
-			.ngpio			= 16,
-		},
-	},
-	[4] = {
-		.base	= S3C2410_GPECON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPE(0),
-			.label			= "GPIOE",
-			.owner			= THIS_MODULE,
-			.ngpio			= 16,
-		},
-	},
-	[5] = {
-		.base	= S3C2410_GPFCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPF(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOF",
-			.ngpio			= 8,
-			.to_irq			= s3c24xx_gpiolib_bankf_toirq,
-		},
-	},
-	[6] = {
-		.base	= S3C2410_GPGCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.irq_base = IRQ_EINT8,
-		.chip	= {
-			.base			= S3C2410_GPG(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOG",
-			.ngpio			= 16,
-			.to_irq			= samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= S3C2410_GPHCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPH(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOH",
-			.ngpio			= 11,
-		},
-	},
-		/* GPIOS for the S3C2443 and later devices. */
-	{
-		.base	= S3C2440_GPJCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPJ(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOJ",
-			.ngpio			= 16,
-		},
-	}, {
-		.base	= S3C2443_GPKCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPK(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOK",
-			.ngpio			= 16,
-		},
-	}, {
-		.base	= S3C2443_GPLCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPL(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOL",
-			.ngpio			= 15,
-		},
-	}, {
-		.base	= S3C2443_GPMCON,
-		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
-		.chip	= {
-			.base			= S3C2410_GPM(0),
-			.owner			= THIS_MODULE,
-			.label			= "GPIOM",
-			.ngpio			= 2,
-		},
-	},
-};
-
-
-static __init int s3c24xx_gpiolib_init(void)
-{
-	struct s3c_gpio_chip *chip = s3c24xx_gpios;
-	int gpn;
-
-	for (gpn = 0; gpn < ARRAY_SIZE(s3c24xx_gpios); gpn++, chip++) {
-		if (!chip->config)
-			chip->config = &s3c24xx_gpiocfg_default;
-
-		s3c_gpiolib_add(chip);
-	}
-
-	return 0;
-}
-
-core_initcall(s3c24xx_gpiolib_init);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/mach/clkdev.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/mach/clkdev.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/mach/clkdev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef __MACH_CLKDEV_H__
-#define __MACH_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do {} while (0)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,55 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h
- *
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C24xx - pwm clock and timer support
- */
-
-/**
- * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @cfg: 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 == S3C2410_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 << (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 0;
-}
-
-/**
- * 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) - 1;
-}
-
-#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/audio-simtec.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/audio-simtec.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/audio-simtec.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/audio-simtec.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,37 +0,0 @@
-/* arch/arm/plat-s3c24xx/include/plat/audio-simtec.h
- *
- * Copyright 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Simtec Audio support.
-*/
-
-/**
- * struct s3c24xx_audio_simtec_pdata - platform data for simtec audio
- * @use_mpllin: Select codec clock from MPLLin
- * @output_cdclk: Need to output CDCLK to the codec
- * @have_mic: Set if we have a MIC socket
- * @have_lout: Set if we have a LineOut socket
- * @amp_gpio: GPIO pin to enable the AMP
- * @amp_gain: Option GPIO to control AMP gain
- */
-struct s3c24xx_audio_simtec_pdata {
-	unsigned int	use_mpllin:1;
-	unsigned int	output_cdclk:1;
-
-	unsigned int	have_mic:1;
-	unsigned int	have_lout:1;
-
-	int		amp_gpio;
-	int		amp_gain[2];
-
-	void	(*startup)(void);
-};
-
-extern int simtec_audio_add(const char *codec_name, bool has_lr_routing,
-			    struct s3c24xx_audio_simtec_pdata *pdata);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/common-smdk.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/common-smdk.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/common-smdk.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/common-smdk.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/common-smdk.h
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Common code for SMDK2410 and SMDK2440 boards
- *
- * http://www.fluff.org/ben/smdk2440/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-extern void smdk_machine_init(void);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,287 +0,0 @@
-/* arch/arm/plat-s3c/include/plat/cpu-freq.h
- *
- * Copyright (c) 2006-2009 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C CPU frequency scaling support - core support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <plat/cpu-freq.h>
-
-struct seq_file;
-
-#define MAX_BANKS (8)
-#define S3C2412_MAX_IO	(8)
-
-/**
- * struct s3c2410_iobank_timing - IO bank timings for S3C2410 style timings
- * @bankcon: The cached version of settings in this structure.
- * @tacp:
- * @tacs: Time from address valid to nCS asserted.
- * @tcos: Time from nCS asserted to nOE or nWE asserted.
- * @tacc: Time that nOE or nWE is asserted.
- * @tcoh: Time nCS is held after nOE or nWE are released.
- * @tcah: Time address is held for after
- * @nwait_en: Whether nWAIT is enabled for this bank.
- *
- * This structure represents the IO timings for a S3C2410 style IO bank
- * used by the CPU frequency support if it needs to change the settings
- * of the IO.
- */
-struct s3c2410_iobank_timing {
-	unsigned long	bankcon;
-	unsigned int	tacp;
-	unsigned int	tacs;
-	unsigned int	tcos;
-	unsigned int	tacc;
-	unsigned int	tcoh;		/* nCS hold afrer nOE/nWE */
-	unsigned int	tcah;		/* Address hold after nCS */
-	unsigned char	nwait_en;	/* nWait enabled for bank. */
-};
-
-/**
- * struct s3c2412_iobank_timing - io timings for PL092 (S3C2412) style IO
- * @idcy: The idle cycle time between transactions.
- * @wstrd: nCS release to end of read cycle.
- * @wstwr: nCS release to end of write cycle.
- * @wstoen: nCS assertion to nOE assertion time.
- * @wstwen: nCS assertion to nWE assertion time.
- * @wstbrd: Burst ready delay.
- * @smbidcyr: Register cache for smbidcyr value.
- * @smbwstrd: Register cache for smbwstrd value.
- * @smbwstwr: Register cache for smbwstwr value.
- * @smbwstoen: Register cache for smbwstoen value.
- * @smbwstwen: Register cache for smbwstwen value.
- * @smbwstbrd: Register cache for smbwstbrd value.
- *
- * Timing information for a IO bank on an S3C2412 or similar system which
- * uses a PL093 block.
- */
-struct s3c2412_iobank_timing {
-	unsigned int	idcy;
-	unsigned int	wstrd;
-	unsigned int	wstwr;
-	unsigned int	wstoen;
-	unsigned int	wstwen;
-	unsigned int	wstbrd;
-
-	/* register cache */
-	unsigned char	smbidcyr;
-	unsigned char	smbwstrd;
-	unsigned char	smbwstwr;
-	unsigned char	smbwstoen;
-	unsigned char	smbwstwen;
-	unsigned char	smbwstbrd;
-};
-
-union s3c_iobank {
-	struct s3c2410_iobank_timing	*io_2410;
-	struct s3c2412_iobank_timing	*io_2412;
-};
-
-/**
- * struct s3c_iotimings - Chip IO timings holder
- * @bank: The timings for each IO bank.
- */
-struct s3c_iotimings {
-	union s3c_iobank	bank[MAX_BANKS];
-};
-
-/**
- * struct s3c_plltab - PLL table information.
- * @vals: List of PLL values.
- * @size: Size of the PLL table @vals.
- */
-struct s3c_plltab {
-	struct s3c_pllval	*vals;
-	int			 size;
-};
-
-/**
- * struct s3c_cpufreq_config - current cpu frequency configuration
- * @freq: The current settings for the core clocks.
- * @max: Maxium settings, derived from core, board and user settings.
- * @pll: The PLL table entry for the current PLL settings.
- * @divs: The divisor settings for the core clocks.
- * @info: The current core driver information.
- * @board: The information for the board we are running on.
- * @lock_pll: Set if the PLL settings cannot be changed.
- *
- * This is for the core drivers that need to know information about
- * the current settings and values. It should not be needed by any
- * device drivers.
-*/
-struct s3c_cpufreq_config {
-	struct s3c_freq		freq;
-	struct s3c_freq		max;
-	struct cpufreq_frequency_table pll;
-	struct s3c_clkdivs	divs;
-	struct s3c_cpufreq_info *info;	/* for core, not drivers */
-	struct s3c_cpufreq_board *board;
-
-	unsigned int	lock_pll:1;
-};
-
-/**
- * struct s3c_cpufreq_info - Information for the CPU frequency driver.
- * @name: The name of this implementation.
- * @max: The maximum frequencies for the system.
- * @latency: Transition latency to give to cpufreq.
- * @locktime_m: The lock-time in uS for the MPLL.
- * @locktime_u: The lock-time in uS for the UPLL.
- * @locttime_bits: The number of bits each LOCKTIME field.
- * @need_pll: Set if this driver needs to change the PLL values to achieve
- *	any frequency changes. This is really only need by devices like the
- *	S3C2410 where there is no or limited divider between the PLL and the
- *	ARMCLK.
- * @resume_clocks: Update the clocks on resume.
- * @get_iotiming: Get the current IO timing data, mainly for use at start.
- * @set_iotiming: Update the IO timings from the cached copies calculated
- *	from the @calc_iotiming entry when changing the frequency.
- * @calc_iotiming: Calculate and update the cached copies of the IO timings
- *	from the newly calculated frequencies.
- * @calc_freqtable: Calculate (fill in) the given frequency table from the
- *	current frequency configuration. If the table passed in is NULL,
- *	then the return is the number of elements to be filled for allocation
- *	of the table.
- * @set_refresh: Set the memory refresh configuration.
- * @set_fvco: Set the PLL frequencies.
- * @set_divs: Update the clock divisors.
- * @calc_divs: Calculate the clock divisors.
- */
-struct s3c_cpufreq_info {
-	const char		*name;
-	struct s3c_freq		max;
-
-	unsigned int		latency;
-
-	unsigned int		locktime_m;
-	unsigned int		locktime_u;
-	unsigned char		locktime_bits;
-
-	unsigned int		need_pll:1;
-
-	/* driver routines */
-
-	void		(*resume_clocks)(void);
-
-	int		(*get_iotiming)(struct s3c_cpufreq_config *cfg,
-					struct s3c_iotimings *timings);
-
-	void		(*set_iotiming)(struct s3c_cpufreq_config *cfg,
-					struct s3c_iotimings *timings);
-
-	int		(*calc_iotiming)(struct s3c_cpufreq_config *cfg,
-					 struct s3c_iotimings *timings);
-
-	int		(*calc_freqtable)(struct s3c_cpufreq_config *cfg,
-					  struct cpufreq_frequency_table *t,
-					  size_t table_size);
-
-	void		(*debug_io_show)(struct seq_file *seq,
-					 struct s3c_cpufreq_config *cfg,
-					 union s3c_iobank *iob);
-
-	void		(*set_refresh)(struct s3c_cpufreq_config *cfg);
-	void		(*set_fvco)(struct s3c_cpufreq_config *cfg);
-	void		(*set_divs)(struct s3c_cpufreq_config *cfg);
-	int		(*calc_divs)(struct s3c_cpufreq_config *cfg);
-};
-
-extern int s3c_cpufreq_register(struct s3c_cpufreq_info *info);
-
-extern int s3c_plltab_register(struct cpufreq_frequency_table *plls, unsigned int plls_no);
-
-/* exports and utilities for debugfs */
-extern struct s3c_cpufreq_config *s3c_cpufreq_getconfig(void);
-extern struct s3c_iotimings *s3c_cpufreq_getiotimings(void);
-
-extern void s3c2410_iotiming_debugfs(struct seq_file *seq,
-				     struct s3c_cpufreq_config *cfg,
-				     union s3c_iobank *iob);
-
-extern void s3c2412_iotiming_debugfs(struct seq_file *seq,
-				     struct s3c_cpufreq_config *cfg,
-				     union s3c_iobank *iob);
-
-#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUGFS
-#define s3c_cpufreq_debugfs_call(x) x
-#else
-#define s3c_cpufreq_debugfs_call(x) NULL
-#endif
-
-/* Useful utility functions. */
-
-extern struct clk *s3c_cpufreq_clk_get(struct device *, const char *);
-
-/* S3C2410 and compatible exported functions */
-
-extern void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg);
-extern void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg);
-
-#ifdef CONFIG_S3C2410_IOTIMING
-extern int s3c2410_iotiming_calc(struct s3c_cpufreq_config *cfg,
-				 struct s3c_iotimings *iot);
-
-extern int s3c2410_iotiming_get(struct s3c_cpufreq_config *cfg,
-				struct s3c_iotimings *timings);
-
-extern void s3c2410_iotiming_set(struct s3c_cpufreq_config *cfg,
-				 struct s3c_iotimings *iot);
-#else
-#define s3c2410_iotiming_calc NULL
-#define s3c2410_iotiming_get NULL
-#define s3c2410_iotiming_set NULL
-#endif /* CONFIG_S3C2410_IOTIMING */
-
-/* S3C2412 compatible routines */
-
-extern int s3c2412_iotiming_get(struct s3c_cpufreq_config *cfg,
-				struct s3c_iotimings *timings);
-
-extern int s3c2412_iotiming_get(struct s3c_cpufreq_config *cfg,
-				struct s3c_iotimings *timings);
-
-extern int s3c2412_iotiming_calc(struct s3c_cpufreq_config *cfg,
-				 struct s3c_iotimings *iot);
-
-extern void s3c2412_iotiming_set(struct s3c_cpufreq_config *cfg,
-				 struct s3c_iotimings *iot);
-
-#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUG
-#define s3c_freq_dbg(x...) printk(KERN_INFO x)
-#else
-#define s3c_freq_dbg(x...) do { if (0) printk(x); } while (0)
-#endif /* CONFIG_CPU_FREQ_S3C24XX_DEBUG */
-
-#ifdef CONFIG_CPU_FREQ_S3C24XX_IODEBUG
-#define s3c_freq_iodbg(x...) printk(KERN_INFO x)
-#else
-#define s3c_freq_iodbg(x...) do { if (0) printk(x); } while (0)
-#endif /* CONFIG_CPU_FREQ_S3C24XX_IODEBUG */
-
-static inline int s3c_cpufreq_addfreq(struct cpufreq_frequency_table *table,
-				      int index, size_t table_size,
-				      unsigned int freq)
-{
-	if (index < 0)
-		return index;
-
-	if (table) {
-		if (index >= table_size)
-			return -ENOMEM;
-
-		s3c_freq_dbg("%s: { %d = %u kHz }\n",
-			     __func__, index, freq);
-
-		table[index].index = index;
-		table[index].frequency = freq;
-	}
-
-	return index + 1;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/fiq.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/fiq.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/fiq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/fiq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/fiq.h
- *
- * Copyright (c) 2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C24XX CPU FIQ support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-extern int s3c24xx_set_fiq(unsigned int irq, bool on);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/irq.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/irq.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/irq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,115 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/irq.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C24XX CPU IRQ 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 <mach/hardware.h>
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
-
-#define irqdbf(x...)
-#define irqdbf2(x...)
-
-#define EXTINT_OFF (IRQ_EINT4 - 4)
-
-/* these are exported for arch/arm/mach-* usage */
-extern struct irq_chip s3c_irq_level_chip;
-extern struct irq_chip s3c_irq_chip;
-
-static inline void
-s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
-		int subcheck)
-{
-	unsigned long mask;
-	unsigned long submask;
-
-	submask = __raw_readl(S3C2410_INTSUBMSK);
-	mask = __raw_readl(S3C2410_INTMSK);
-
-	submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
-
-	/* check to see if we need to mask the parent IRQ */
-
-	if ((submask  & subcheck) == subcheck) {
-		__raw_writel(mask | parentbit, S3C2410_INTMSK);
-	}
-
-	/* write back masks */
-	__raw_writel(submask, S3C2410_INTSUBMSK);
-
-}
-
-static inline void
-s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
-{
-	unsigned long mask;
-	unsigned long submask;
-
-	submask = __raw_readl(S3C2410_INTSUBMSK);
-	mask = __raw_readl(S3C2410_INTMSK);
-
-	submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
-	mask &= ~parentbit;
-
-	/* write back masks */
-	__raw_writel(submask, S3C2410_INTSUBMSK);
-	__raw_writel(mask, S3C2410_INTMSK);
-}
-
-
-static inline void
-s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
-{
-	unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
-
-	s3c_irqsub_mask(irqno, parentmask, group);
-
-	__raw_writel(bit, S3C2410_SUBSRCPND);
-
-	/* only ack parent if we've got all the irqs (seems we must
-	 * ack, all and hope that the irq system retriggers ok when
-	 * the interrupt goes off again)
-	 */
-
-	if (1) {
-		__raw_writel(parentmask, S3C2410_SRCPND);
-		__raw_writel(parentmask, S3C2410_INTPND);
-	}
-}
-
-static inline void
-s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
-{
-	unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
-
-	__raw_writel(bit, S3C2410_SUBSRCPND);
-
-	/* only ack parent if we've got all the irqs (seems we must
-	 * ack, all and hope that the irq system retriggers ok when
-	 * the interrupt goes off again)
-	 */
-
-	if (1) {
-		__raw_writel(parentmask, S3C2410_SRCPND);
-		__raw_writel(parentmask, S3C2410_INTPND);
-	}
-}
-
-/* exported for use in arch/arm/mach-s3c2410 */
-
-#ifdef CONFIG_PM
-extern int s3c_irq_wake(struct irq_data *data, unsigned int state);
-#else
-#define s3c_irq_wake NULL
-#endif
-
-extern int s3c_irqext_type(struct irq_data *d, unsigned int type);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/map.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/map.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/map.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/map.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,100 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/map.h
- *
- * Copyright (c) 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX - 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_PLAT_S3C24XX_MAP_H
-#define __ASM_PLAT_S3C24XX_MAP_H
-
-/* interrupt controller is the first thing we put in, to make
- * the assembly code for the irq detection easier
- */
-#define S3C24XX_VA_IRQ	   S3C_VA_IRQ
-#define S3C2410_PA_IRQ	   (0x4A000000)
-#define S3C24XX_SZ_IRQ	   SZ_1M
-
-/* memory controller registers */
-#define S3C24XX_VA_MEMCTRL S3C_VA_MEM
-#define S3C2410_PA_MEMCTRL (0x48000000)
-#define S3C24XX_SZ_MEMCTRL SZ_1M
-
-/* UARTs */
-#define S3C24XX_VA_UART	   S3C_VA_UART
-#define S3C2410_PA_UART	   (0x50000000)
-#define S3C24XX_SZ_UART	   SZ_1M
-#define S3C_UART_OFFSET	   (0x4000)
-
-#define S3C_VA_UARTx(uart) (S3C_VA_UART + ((uart * S3C_UART_OFFSET)))
-
-/* Timers */
-#define S3C24XX_VA_TIMER   S3C_VA_TIMER
-#define S3C2410_PA_TIMER   (0x51000000)
-#define S3C24XX_SZ_TIMER   SZ_1M
-
-/* Clock and Power management */
-#define S3C24XX_VA_CLKPWR  S3C_VA_SYS
-#define S3C24XX_SZ_CLKPWR  SZ_1M
-
-/* USB Device port */
-#define S3C2410_PA_USBDEV  (0x52000000)
-#define S3C24XX_SZ_USBDEV  SZ_1M
-
-/* Watchdog */
-#define S3C24XX_VA_WATCHDOG S3C_VA_WATCHDOG
-#define S3C2410_PA_WATCHDOG (0x53000000)
-#define S3C24XX_SZ_WATCHDOG SZ_1M
-
-/* Standard size definitions for peripheral blocks. */
-
-#define S3C24XX_SZ_IIS		SZ_1M
-#define S3C24XX_SZ_ADC		SZ_1M
-#define S3C24XX_SZ_SPI		SZ_1M
-#define S3C24XX_SZ_SDI		SZ_1M
-#define S3C24XX_SZ_NAND		SZ_1M
-
-/* GPIO ports */
-
-/* the calculation for the VA of this must ensure that
- * it is the same distance apart from the UART in the
- * phsyical address space, as the initial mapping for the IO
- * is done as a 1:1 mapping. This puts it (currently) at
- * 0xFA800000, which is not in the way of any current mapping
- * by the base system.
-*/
-
-#define S3C2410_PA_GPIO	   (0x56000000)
-#define S3C24XX_VA_GPIO	   ((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)
-#define S3C24XX_SZ_GPIO	   SZ_1M
-
-
-/* ISA style IO, for each machine to sort out mappings for, if it
- * implements it. We reserve two 16M regions for ISA.
- */
-
-#define S3C24XX_VA_ISA_WORD  S3C2410_ADDR(0x02000000)
-#define S3C24XX_VA_ISA_BYTE  S3C2410_ADDR(0x03000000)
-
-/* deal with the registers that move under the 2412/2413 */
-
-#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
-#ifndef __ASSEMBLY__
-extern void __iomem *s3c24xx_va_gpio2;
-#endif
-#ifdef CONFIG_CPU_S3C2412_ONLY
-#define S3C24XX_VA_GPIO2 (S3C24XX_VA_GPIO + 0x10)
-#else
-#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2
-#endif
-#else
-#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO
-#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO
-#endif
-
-#endif /* __ASM_PLAT_S3C24XX_MAP_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/mci.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/mci.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/mci.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/mci.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-#ifndef _ARCH_MCI_H
-#define _ARCH_MCI_H
-
-/**
- * struct s3c24xx_mci_pdata - sd/mmc controller platform data
- * @no_wprotect: Set this to indicate there is no write-protect switch.
- * @no_detect: Set this if there is no detect switch.
- * @wprotect_invert: Invert the default sense of the write protect switch.
- * @detect_invert: Invert the default sense of the write protect switch.
- * @use_dma: Set to allow the use of DMA.
- * @gpio_detect: GPIO number for the card detect line.
- * @gpio_wprotect: GPIO number for the write protect line.
- * @ocr_avail: The mask of the available power states, non-zero to use.
- * @set_power: Callback to control the power mode.
- *
- * The @gpio_detect is used for card detection when @no_wprotect is unset,
- * and the default sense is that 0 returned from gpio_get_value() means
- * that a card is inserted. If @detect_invert is set, then the value from
- * gpio_get_value() is inverted, which makes 1 mean card inserted.
- *
- * The driver will use @gpio_wprotect to signal whether the card is write
- * protected if @no_wprotect is not set. A 0 returned from gpio_get_value()
- * means the card is read/write, and 1 means read-only. The @wprotect_invert
- * will invert the value returned from gpio_get_value().
- *
- * Card power is set by @ocr_availa, using MCC_VDD_ constants if it is set
- * to a non-zero value, otherwise the default of 3.2-3.4V is used.
- */
-struct s3c24xx_mci_pdata {
-	unsigned int	no_wprotect : 1;
-	unsigned int	no_detect : 1;
-	unsigned int	wprotect_invert : 1;
-	unsigned int	detect_invert : 1;   /* set => detect active high. */
-	unsigned int	use_dma : 1;
-
-	unsigned int	gpio_detect;
-	unsigned int	gpio_wprotect;
-	unsigned long	ocr_avail;
-	void		(*set_power)(unsigned char power_mode,
-				     unsigned short vdd);
-};
-
-/**
- * s3c24xx_mci_set_platdata - set platform data for mmc/sdi device
- * @pdata: The platform data
- *
- * Copy the platform data supplied by @pdata so that this can be marked
- * __initdata.
- */
-extern void s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata);
-
-#endif /* _ARCH_NCI_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/pll.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/pll.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/pll.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/pll.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,62 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/include/plat/pll.h
- *
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C24xx - common pll registers and code
- */
-
-#define S3C24XX_PLLCON_MDIVSHIFT	12
-#define S3C24XX_PLLCON_PDIVSHIFT	4
-#define S3C24XX_PLLCON_SDIVSHIFT	0
-#define S3C24XX_PLLCON_MDIVMASK		((1<<(1+(19-12)))-1)
-#define S3C24XX_PLLCON_PDIVMASK		((1<<5)-1)
-#define S3C24XX_PLLCON_SDIVMASK		3
-
-#include <asm/div64.h>
-
-static inline unsigned int
-s3c24xx_get_pll(unsigned int pllval, unsigned int baseclk)
-{
-	unsigned int mdiv, pdiv, sdiv;
-	uint64_t fvco;
-
-	mdiv = pllval >> S3C24XX_PLLCON_MDIVSHIFT;
-	pdiv = pllval >> S3C24XX_PLLCON_PDIVSHIFT;
-	sdiv = pllval >> S3C24XX_PLLCON_SDIVSHIFT;
-
-	mdiv &= S3C24XX_PLLCON_MDIVMASK;
-	pdiv &= S3C24XX_PLLCON_PDIVMASK;
-	sdiv &= S3C24XX_PLLCON_SDIVMASK;
-
-	fvco = (uint64_t)baseclk * (mdiv + 8);
-	do_div(fvco, (pdiv + 2) << sdiv);
-
-	return (unsigned int)fvco;
-}
-
-#define S3C2416_PLL_M_SHIFT	(14)
-#define S3C2416_PLL_P_SHIFT	(5)
-#define S3C2416_PLL_S_MASK	(7)
-#define S3C2416_PLL_M_MASK	((1 << 10) - 1)
-#define S3C2416_PLL_P_MASK	(63)
-
-static inline unsigned int
-s3c2416_get_pll(unsigned int pllval, unsigned int baseclk)
-{
-	unsigned int m, p, s;
-	uint64_t fvco;
-
-	m = pllval >> S3C2416_PLL_M_SHIFT;
-	p = pllval >> S3C2416_PLL_P_SHIFT;
-
-	s = pllval & S3C2416_PLL_S_MASK;
-	m &= S3C2416_PLL_M_MASK;
-	p &= S3C2416_PLL_P_MASK;
-
-	fvco = (uint64_t)baseclk * m;
-	do_div(fvco, (p << s));
-
-	return (unsigned int)fvco;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/regs-dma.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/regs-dma.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/regs-dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/regs-dma.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,145 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/dma.h
- *
- * Copyright (C) 2003-2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Samsung S3C24XX DMA support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* DMA Register definitions */
-
-#define S3C2410_DMA_DISRC		(0x00)
-#define S3C2410_DMA_DISRCC		(0x04)
-#define S3C2410_DMA_DIDST		(0x08)
-#define S3C2410_DMA_DIDSTC		(0x0C)
-#define S3C2410_DMA_DCON		(0x10)
-#define S3C2410_DMA_DSTAT		(0x14)
-#define S3C2410_DMA_DCSRC		(0x18)
-#define S3C2410_DMA_DCDST		(0x1C)
-#define S3C2410_DMA_DMASKTRIG		(0x20)
-#define S3C2412_DMA_DMAREQSEL		(0x24)
-#define S3C2443_DMA_DMAREQSEL		(0x24)
-
-#define S3C2410_DISRCC_INC		(1<<0)
-#define S3C2410_DISRCC_APB		(1<<1)
-
-#define S3C2410_DMASKTRIG_STOP		(1<<2)
-#define S3C2410_DMASKTRIG_ON		(1<<1)
-#define S3C2410_DMASKTRIG_SWTRIG	(1<<0)
-
-#define S3C2410_DCON_DEMAND		(0<<31)
-#define S3C2410_DCON_HANDSHAKE		(1<<31)
-#define S3C2410_DCON_SYNC_PCLK		(0<<30)
-#define S3C2410_DCON_SYNC_HCLK		(1<<30)
-
-#define S3C2410_DCON_INTREQ		(1<<29)
-
-#define S3C2410_DCON_CH0_XDREQ0		(0<<24)
-#define S3C2410_DCON_CH0_UART0		(1<<24)
-#define S3C2410_DCON_CH0_SDI		(2<<24)
-#define S3C2410_DCON_CH0_TIMER		(3<<24)
-#define S3C2410_DCON_CH0_USBEP1		(4<<24)
-
-#define S3C2410_DCON_CH1_XDREQ1		(0<<24)
-#define S3C2410_DCON_CH1_UART1		(1<<24)
-#define S3C2410_DCON_CH1_I2SSDI		(2<<24)
-#define S3C2410_DCON_CH1_SPI		(3<<24)
-#define S3C2410_DCON_CH1_USBEP2		(4<<24)
-
-#define S3C2410_DCON_CH2_I2SSDO		(0<<24)
-#define S3C2410_DCON_CH2_I2SSDI		(1<<24)
-#define S3C2410_DCON_CH2_SDI		(2<<24)
-#define S3C2410_DCON_CH2_TIMER		(3<<24)
-#define S3C2410_DCON_CH2_USBEP3		(4<<24)
-
-#define S3C2410_DCON_CH3_UART2		(0<<24)
-#define S3C2410_DCON_CH3_SDI		(1<<24)
-#define S3C2410_DCON_CH3_SPI		(2<<24)
-#define S3C2410_DCON_CH3_TIMER		(3<<24)
-#define S3C2410_DCON_CH3_USBEP4		(4<<24)
-
-#define S3C2410_DCON_SRCSHIFT		(24)
-#define S3C2410_DCON_SRCMASK		(7<<24)
-
-#define S3C2410_DCON_BYTE		(0<<20)
-#define S3C2410_DCON_HALFWORD		(1<<20)
-#define S3C2410_DCON_WORD		(2<<20)
-
-#define S3C2410_DCON_AUTORELOAD		(0<<22)
-#define S3C2410_DCON_NORELOAD		(1<<22)
-#define S3C2410_DCON_HWTRIG		(1<<23)
-
-#ifdef CONFIG_CPU_S3C2440
-#define S3C2440_DIDSTC_CHKINT		(1<<2)
-
-#define S3C2440_DCON_CH0_I2SSDO		(5<<24)
-#define S3C2440_DCON_CH0_PCMIN		(6<<24)
-
-#define S3C2440_DCON_CH1_PCMOUT		(5<<24)
-#define S3C2440_DCON_CH1_SDI		(6<<24)
-
-#define S3C2440_DCON_CH2_PCMIN		(5<<24)
-#define S3C2440_DCON_CH2_MICIN		(6<<24)
-
-#define S3C2440_DCON_CH3_MICIN		(5<<24)
-#define S3C2440_DCON_CH3_PCMOUT		(6<<24)
-#endif
-
-#ifdef CONFIG_CPU_S3C2412
-
-#define S3C2412_DMAREQSEL_SRC(x)	((x)<<1)
-
-#define S3C2412_DMAREQSEL_HW		(1)
-
-#define S3C2412_DMAREQSEL_SPI0TX	S3C2412_DMAREQSEL_SRC(0)
-#define S3C2412_DMAREQSEL_SPI0RX	S3C2412_DMAREQSEL_SRC(1)
-#define S3C2412_DMAREQSEL_SPI1TX	S3C2412_DMAREQSEL_SRC(2)
-#define S3C2412_DMAREQSEL_SPI1RX	S3C2412_DMAREQSEL_SRC(3)
-#define S3C2412_DMAREQSEL_I2STX		S3C2412_DMAREQSEL_SRC(4)
-#define S3C2412_DMAREQSEL_I2SRX		S3C2412_DMAREQSEL_SRC(5)
-#define S3C2412_DMAREQSEL_TIMER		S3C2412_DMAREQSEL_SRC(9)
-#define S3C2412_DMAREQSEL_SDI		S3C2412_DMAREQSEL_SRC(10)
-#define S3C2412_DMAREQSEL_USBEP1	S3C2412_DMAREQSEL_SRC(13)
-#define S3C2412_DMAREQSEL_USBEP2	S3C2412_DMAREQSEL_SRC(14)
-#define S3C2412_DMAREQSEL_USBEP3	S3C2412_DMAREQSEL_SRC(15)
-#define S3C2412_DMAREQSEL_USBEP4	S3C2412_DMAREQSEL_SRC(16)
-#define S3C2412_DMAREQSEL_XDREQ0	S3C2412_DMAREQSEL_SRC(17)
-#define S3C2412_DMAREQSEL_XDREQ1	S3C2412_DMAREQSEL_SRC(18)
-#define S3C2412_DMAREQSEL_UART0_0	S3C2412_DMAREQSEL_SRC(19)
-#define S3C2412_DMAREQSEL_UART0_1	S3C2412_DMAREQSEL_SRC(20)
-#define S3C2412_DMAREQSEL_UART1_0	S3C2412_DMAREQSEL_SRC(21)
-#define S3C2412_DMAREQSEL_UART1_1	S3C2412_DMAREQSEL_SRC(22)
-#define S3C2412_DMAREQSEL_UART2_0	S3C2412_DMAREQSEL_SRC(23)
-#define S3C2412_DMAREQSEL_UART2_1	S3C2412_DMAREQSEL_SRC(24)
-
-#endif
-
-#define S3C2443_DMAREQSEL_SRC(x)	((x)<<1)
-
-#define S3C2443_DMAREQSEL_HW		(1)
-
-#define S3C2443_DMAREQSEL_SPI0TX	S3C2443_DMAREQSEL_SRC(0)
-#define S3C2443_DMAREQSEL_SPI0RX	S3C2443_DMAREQSEL_SRC(1)
-#define S3C2443_DMAREQSEL_SPI1TX	S3C2443_DMAREQSEL_SRC(2)
-#define S3C2443_DMAREQSEL_SPI1RX	S3C2443_DMAREQSEL_SRC(3)
-#define S3C2443_DMAREQSEL_I2STX		S3C2443_DMAREQSEL_SRC(4)
-#define S3C2443_DMAREQSEL_I2SRX		S3C2443_DMAREQSEL_SRC(5)
-#define S3C2443_DMAREQSEL_TIMER		S3C2443_DMAREQSEL_SRC(9)
-#define S3C2443_DMAREQSEL_SDI		S3C2443_DMAREQSEL_SRC(10)
-#define S3C2443_DMAREQSEL_XDREQ0	S3C2443_DMAREQSEL_SRC(17)
-#define S3C2443_DMAREQSEL_XDREQ1	S3C2443_DMAREQSEL_SRC(18)
-#define S3C2443_DMAREQSEL_UART0_0	S3C2443_DMAREQSEL_SRC(19)
-#define S3C2443_DMAREQSEL_UART0_1	S3C2443_DMAREQSEL_SRC(20)
-#define S3C2443_DMAREQSEL_UART1_0	S3C2443_DMAREQSEL_SRC(21)
-#define S3C2443_DMAREQSEL_UART1_1	S3C2443_DMAREQSEL_SRC(22)
-#define S3C2443_DMAREQSEL_UART2_0	S3C2443_DMAREQSEL_SRC(23)
-#define S3C2443_DMAREQSEL_UART2_1	S3C2443_DMAREQSEL_SRC(24)
-#define S3C2443_DMAREQSEL_UART3_0	S3C2443_DMAREQSEL_SRC(25)
-#define S3C2443_DMAREQSEL_UART3_1	S3C2443_DMAREQSEL_SRC(26)
-#define S3C2443_DMAREQSEL_PCMOUT	S3C2443_DMAREQSEL_SRC(27)
-#define S3C2443_DMAREQSEL_PCMIN 	S3C2443_DMAREQSEL_SRC(28)
-#define S3C2443_DMAREQSEL_MICIN		S3C2443_DMAREQSEL_SRC(29)
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/regs-iis.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/regs-iis.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/regs-iis.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/regs-iis.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-iis.h
- *
- * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
- *		      http://www.simtec.co.uk/products/SWLINUX/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * S3C2410 IIS register definition
-*/
-
-#ifndef __ASM_ARCH_REGS_IIS_H
-#define __ASM_ARCH_REGS_IIS_H
-
-#define S3C2410_IISCON	 (0x00)
-
-#define S3C2410_IISCON_LRINDEX	  (1<<8)
-#define S3C2410_IISCON_TXFIFORDY  (1<<7)
-#define S3C2410_IISCON_RXFIFORDY  (1<<6)
-#define S3C2410_IISCON_TXDMAEN	  (1<<5)
-#define S3C2410_IISCON_RXDMAEN	  (1<<4)
-#define S3C2410_IISCON_TXIDLE	  (1<<3)
-#define S3C2410_IISCON_RXIDLE	  (1<<2)
-#define S3C2410_IISCON_PSCEN	  (1<<1)
-#define S3C2410_IISCON_IISEN	  (1<<0)
-
-#define S3C2410_IISMOD	 (0x04)
-
-#define S3C2440_IISMOD_MPLL	  (1<<9)
-#define S3C2410_IISMOD_SLAVE	  (1<<8)
-#define S3C2410_IISMOD_NOXFER	  (0<<6)
-#define S3C2410_IISMOD_RXMODE	  (1<<6)
-#define S3C2410_IISMOD_TXMODE	  (2<<6)
-#define S3C2410_IISMOD_TXRXMODE	  (3<<6)
-#define S3C2410_IISMOD_LR_LLOW	  (0<<5)
-#define S3C2410_IISMOD_LR_RLOW	  (1<<5)
-#define S3C2410_IISMOD_IIS	  (0<<4)
-#define S3C2410_IISMOD_MSB	  (1<<4)
-#define S3C2410_IISMOD_8BIT	  (0<<3)
-#define S3C2410_IISMOD_16BIT	  (1<<3)
-#define S3C2410_IISMOD_BITMASK	  (1<<3)
-#define S3C2410_IISMOD_256FS	  (0<<2)
-#define S3C2410_IISMOD_384FS	  (1<<2)
-#define S3C2410_IISMOD_16FS	  (0<<0)
-#define S3C2410_IISMOD_32FS	  (1<<0)
-#define S3C2410_IISMOD_48FS	  (2<<0)
-#define S3C2410_IISMOD_FS_MASK	  (3<<0)
-
-#define S3C2410_IISPSR		(0x08)
-#define S3C2410_IISPSR_INTMASK	(31<<5)
-#define S3C2410_IISPSR_INTSHIFT	(5)
-#define S3C2410_IISPSR_EXTMASK	(31<<0)
-#define S3C2410_IISPSR_EXTSHFIT	(0)
-
-#define S3C2410_IISFCON  (0x0c)
-
-#define S3C2410_IISFCON_TXDMA	  (1<<15)
-#define S3C2410_IISFCON_RXDMA	  (1<<14)
-#define S3C2410_IISFCON_TXENABLE  (1<<13)
-#define S3C2410_IISFCON_RXENABLE  (1<<12)
-#define S3C2410_IISFCON_TXMASK	  (0x3f << 6)
-#define S3C2410_IISFCON_TXSHIFT	  (6)
-#define S3C2410_IISFCON_RXMASK	  (0x3f)
-#define S3C2410_IISFCON_RXSHIFT	  (0)
-
-#define S3C2410_IISFIFO  (0x10)
-#endif /* __ASM_ARCH_REGS_IIS_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/regs-spi.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/regs-spi.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/regs-spi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/regs-spi.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-spi.h
- *
- * Copyright (c) 2004 Fetron GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * S3C2410 SPI register definition
-*/
-
-#ifndef __ASM_ARCH_REGS_SPI_H
-#define __ASM_ARCH_REGS_SPI_H
-
-#define S3C2410_SPI1	(0x20)
-#define S3C2412_SPI1	(0x100)
-
-#define S3C2410_SPCON	(0x00)
-
-#define S3C2412_SPCON_RXFIFO_RB2	(0<<14)
-#define S3C2412_SPCON_RXFIFO_RB4	(1<<14)
-#define S3C2412_SPCON_RXFIFO_RB12	(2<<14)
-#define S3C2412_SPCON_RXFIFO_RB14	(3<<14)
-#define S3C2412_SPCON_TXFIFO_RB2	(0<<12)
-#define S3C2412_SPCON_TXFIFO_RB4	(1<<12)
-#define S3C2412_SPCON_TXFIFO_RB12	(2<<12)
-#define S3C2412_SPCON_TXFIFO_RB14	(3<<12)
-#define S3C2412_SPCON_RXFIFO_RESET	(1<<11) /* RxFIFO reset */
-#define S3C2412_SPCON_TXFIFO_RESET	(1<<10) /* TxFIFO reset */
-#define S3C2412_SPCON_RXFIFO_EN		(1<<9)  /* RxFIFO Enable */
-#define S3C2412_SPCON_TXFIFO_EN		(1<<8)  /* TxFIFO Enable */
-
-#define S3C2412_SPCON_DIRC_RX	  (1<<7)
-
-#define S3C2410_SPCON_SMOD_DMA	  (2<<5)	/* DMA mode */
-#define S3C2410_SPCON_SMOD_INT	  (1<<5)	/* interrupt mode */
-#define S3C2410_SPCON_SMOD_POLL   (0<<5)	/* polling mode */
-#define S3C2410_SPCON_ENSCK	  (1<<4)	/* Enable SCK */
-#define S3C2410_SPCON_MSTR	  (1<<3)	/* Master/Slave select
-						   0: slave, 1: master */
-#define S3C2410_SPCON_CPOL_HIGH	  (1<<2)	/* Clock polarity select */
-#define S3C2410_SPCON_CPOL_LOW	  (0<<2)	/* Clock polarity select */
-
-#define S3C2410_SPCON_CPHA_FMTB	  (1<<1)	/* Clock Phase Select */
-#define S3C2410_SPCON_CPHA_FMTA	  (0<<1)	/* Clock Phase Select */
-
-#define S3C2410_SPCON_TAGD	  (1<<0)	/* Tx auto garbage data mode */
-
-
-#define S3C2410_SPSTA	 (0x04)
-
-#define S3C2412_SPSTA_RXFIFO_AE		(1<<11)
-#define S3C2412_SPSTA_TXFIFO_AE		(1<<10)
-#define S3C2412_SPSTA_RXFIFO_ERROR	(1<<9)
-#define S3C2412_SPSTA_TXFIFO_ERROR	(1<<8)
-#define S3C2412_SPSTA_RXFIFO_FIFO	(1<<7)
-#define S3C2412_SPSTA_RXFIFO_EMPTY	(1<<6)
-#define S3C2412_SPSTA_TXFIFO_NFULL	(1<<5)
-#define S3C2412_SPSTA_TXFIFO_EMPTY	(1<<4)
-
-#define S3C2410_SPSTA_DCOL	  (1<<2)	/* Data Collision Error */
-#define S3C2410_SPSTA_MULD	  (1<<1)	/* Multi Master Error */
-#define S3C2410_SPSTA_READY	  (1<<0)	/* Data Tx/Rx ready */
-#define S3C2412_SPSTA_READY_ORG	  (1<<3)
-
-#define S3C2410_SPPIN	 (0x08)
-
-#define S3C2410_SPPIN_ENMUL	  (1<<2)	/* Multi Master Error detect */
-#define S3C2410_SPPIN_RESERVED	  (1<<1)
-#define S3C2410_SPPIN_KEEP	  (1<<0)	/* Master Out keep */
-
-#define S3C2410_SPPRE	 (0x0C)
-#define S3C2410_SPTDAT	 (0x10)
-#define S3C2410_SPRDAT	 (0x14)
-
-#define S3C2412_TXFIFO	 (0x18)
-#define S3C2412_RXFIFO	 (0x18)
-#define S3C2412_SPFIC	 (0x24)
-
-
-#endif /* __ASM_ARCH_REGS_SPI_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/regs-udc.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/regs-udc.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/regs-udc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/regs-udc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,153 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-udc.h
- *
- * Copyright (C) 2004 Herbert Poetzl <herbert@13thfloor.at>
- *
- * This include file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
-*/
-
-#ifndef __ASM_ARCH_REGS_UDC_H
-#define __ASM_ARCH_REGS_UDC_H
-
-#define S3C2410_USBDREG(x) (x)
-
-#define S3C2410_UDC_FUNC_ADDR_REG	S3C2410_USBDREG(0x0140)
-#define S3C2410_UDC_PWR_REG		S3C2410_USBDREG(0x0144)
-#define S3C2410_UDC_EP_INT_REG		S3C2410_USBDREG(0x0148)
-
-#define S3C2410_UDC_USB_INT_REG		S3C2410_USBDREG(0x0158)
-#define S3C2410_UDC_EP_INT_EN_REG	S3C2410_USBDREG(0x015c)
-
-#define S3C2410_UDC_USB_INT_EN_REG	S3C2410_USBDREG(0x016c)
-
-#define S3C2410_UDC_FRAME_NUM1_REG	S3C2410_USBDREG(0x0170)
-#define S3C2410_UDC_FRAME_NUM2_REG	S3C2410_USBDREG(0x0174)
-
-#define S3C2410_UDC_EP0_FIFO_REG	S3C2410_USBDREG(0x01c0)
-#define S3C2410_UDC_EP1_FIFO_REG	S3C2410_USBDREG(0x01c4)
-#define S3C2410_UDC_EP2_FIFO_REG	S3C2410_USBDREG(0x01c8)
-#define S3C2410_UDC_EP3_FIFO_REG	S3C2410_USBDREG(0x01cc)
-#define S3C2410_UDC_EP4_FIFO_REG	S3C2410_USBDREG(0x01d0)
-
-#define S3C2410_UDC_EP1_DMA_CON		S3C2410_USBDREG(0x0200)
-#define S3C2410_UDC_EP1_DMA_UNIT	S3C2410_USBDREG(0x0204)
-#define S3C2410_UDC_EP1_DMA_FIFO	S3C2410_USBDREG(0x0208)
-#define S3C2410_UDC_EP1_DMA_TTC_L	S3C2410_USBDREG(0x020c)
-#define S3C2410_UDC_EP1_DMA_TTC_M	S3C2410_USBDREG(0x0210)
-#define S3C2410_UDC_EP1_DMA_TTC_H	S3C2410_USBDREG(0x0214)
-
-#define S3C2410_UDC_EP2_DMA_CON		S3C2410_USBDREG(0x0218)
-#define S3C2410_UDC_EP2_DMA_UNIT	S3C2410_USBDREG(0x021c)
-#define S3C2410_UDC_EP2_DMA_FIFO	S3C2410_USBDREG(0x0220)
-#define S3C2410_UDC_EP2_DMA_TTC_L	S3C2410_USBDREG(0x0224)
-#define S3C2410_UDC_EP2_DMA_TTC_M	S3C2410_USBDREG(0x0228)
-#define S3C2410_UDC_EP2_DMA_TTC_H	S3C2410_USBDREG(0x022c)
-
-#define S3C2410_UDC_EP3_DMA_CON		S3C2410_USBDREG(0x0240)
-#define S3C2410_UDC_EP3_DMA_UNIT	S3C2410_USBDREG(0x0244)
-#define S3C2410_UDC_EP3_DMA_FIFO	S3C2410_USBDREG(0x0248)
-#define S3C2410_UDC_EP3_DMA_TTC_L	S3C2410_USBDREG(0x024c)
-#define S3C2410_UDC_EP3_DMA_TTC_M	S3C2410_USBDREG(0x0250)
-#define S3C2410_UDC_EP3_DMA_TTC_H	S3C2410_USBDREG(0x0254)
-
-#define S3C2410_UDC_EP4_DMA_CON		S3C2410_USBDREG(0x0258)
-#define S3C2410_UDC_EP4_DMA_UNIT	S3C2410_USBDREG(0x025c)
-#define S3C2410_UDC_EP4_DMA_FIFO	S3C2410_USBDREG(0x0260)
-#define S3C2410_UDC_EP4_DMA_TTC_L	S3C2410_USBDREG(0x0264)
-#define S3C2410_UDC_EP4_DMA_TTC_M	S3C2410_USBDREG(0x0268)
-#define S3C2410_UDC_EP4_DMA_TTC_H	S3C2410_USBDREG(0x026c)
-
-#define S3C2410_UDC_INDEX_REG		S3C2410_USBDREG(0x0178)
-
-/* indexed registers */
-
-#define S3C2410_UDC_MAXP_REG		S3C2410_USBDREG(0x0180)
-
-#define S3C2410_UDC_EP0_CSR_REG		S3C2410_USBDREG(0x0184)
-
-#define S3C2410_UDC_IN_CSR1_REG		S3C2410_USBDREG(0x0184)
-#define S3C2410_UDC_IN_CSR2_REG		S3C2410_USBDREG(0x0188)
-
-#define S3C2410_UDC_OUT_CSR1_REG	S3C2410_USBDREG(0x0190)
-#define S3C2410_UDC_OUT_CSR2_REG	S3C2410_USBDREG(0x0194)
-#define S3C2410_UDC_OUT_FIFO_CNT1_REG	S3C2410_USBDREG(0x0198)
-#define S3C2410_UDC_OUT_FIFO_CNT2_REG	S3C2410_USBDREG(0x019c)
-
-#define S3C2410_UDC_FUNCADDR_UPDATE	(1<<7)
-
-#define S3C2410_UDC_PWR_ISOUP		(1<<7) // R/W
-#define S3C2410_UDC_PWR_RESET		(1<<3) // R
-#define S3C2410_UDC_PWR_RESUME		(1<<2) // R/W
-#define S3C2410_UDC_PWR_SUSPEND		(1<<1) // R
-#define S3C2410_UDC_PWR_ENSUSPEND	(1<<0) // R/W
-
-#define S3C2410_UDC_PWR_DEFAULT		0x00
-
-#define S3C2410_UDC_INT_EP4		(1<<4) // R/W (clear only)
-#define S3C2410_UDC_INT_EP3		(1<<3) // R/W (clear only)
-#define S3C2410_UDC_INT_EP2		(1<<2) // R/W (clear only)
-#define S3C2410_UDC_INT_EP1		(1<<1) // R/W (clear only)
-#define S3C2410_UDC_INT_EP0		(1<<0) // R/W (clear only)
-
-#define S3C2410_UDC_USBINT_RESET	(1<<2) // R/W (clear only)
-#define S3C2410_UDC_USBINT_RESUME	(1<<1) // R/W (clear only)
-#define S3C2410_UDC_USBINT_SUSPEND	(1<<0) // R/W (clear only)
-
-#define S3C2410_UDC_INTE_EP4		(1<<4) // R/W
-#define S3C2410_UDC_INTE_EP3		(1<<3) // R/W
-#define S3C2410_UDC_INTE_EP2		(1<<2) // R/W
-#define S3C2410_UDC_INTE_EP1		(1<<1) // R/W
-#define S3C2410_UDC_INTE_EP0		(1<<0) // R/W
-
-#define S3C2410_UDC_USBINTE_RESET	(1<<2) // R/W
-#define S3C2410_UDC_USBINTE_SUSPEND	(1<<0) // R/W
-
-
-#define S3C2410_UDC_INDEX_EP0		(0x00)
-#define S3C2410_UDC_INDEX_EP1		(0x01) // ??
-#define S3C2410_UDC_INDEX_EP2		(0x02) // ??
-#define S3C2410_UDC_INDEX_EP3		(0x03) // ??
-#define S3C2410_UDC_INDEX_EP4		(0x04) // ??
-
-#define S3C2410_UDC_ICSR1_CLRDT		(1<<6) // R/W
-#define S3C2410_UDC_ICSR1_SENTSTL	(1<<5) // R/W (clear only)
-#define S3C2410_UDC_ICSR1_SENDSTL	(1<<4) // R/W
-#define S3C2410_UDC_ICSR1_FFLUSH	(1<<3) // W   (set only)
-#define S3C2410_UDC_ICSR1_UNDRUN	(1<<2) // R/W (clear only)
-#define S3C2410_UDC_ICSR1_PKTRDY	(1<<0) // R/W (set only)
-
-#define S3C2410_UDC_ICSR2_AUTOSET	(1<<7) // R/W
-#define S3C2410_UDC_ICSR2_ISO		(1<<6) // R/W
-#define S3C2410_UDC_ICSR2_MODEIN	(1<<5) // R/W
-#define S3C2410_UDC_ICSR2_DMAIEN	(1<<4) // R/W
-
-#define S3C2410_UDC_OCSR1_CLRDT		(1<<7) // R/W
-#define S3C2410_UDC_OCSR1_SENTSTL	(1<<6) // R/W (clear only)
-#define S3C2410_UDC_OCSR1_SENDSTL	(1<<5) // R/W
-#define S3C2410_UDC_OCSR1_FFLUSH	(1<<4) // R/W
-#define S3C2410_UDC_OCSR1_DERROR	(1<<3) // R
-#define S3C2410_UDC_OCSR1_OVRRUN	(1<<2) // R/W (clear only)
-#define S3C2410_UDC_OCSR1_PKTRDY	(1<<0) // R/W (clear only)
-
-#define S3C2410_UDC_OCSR2_AUTOCLR	(1<<7) // R/W
-#define S3C2410_UDC_OCSR2_ISO		(1<<6) // R/W
-#define S3C2410_UDC_OCSR2_DMAIEN	(1<<5) // R/W
-
-#define S3C2410_UDC_EP0_CSR_OPKRDY	(1<<0)
-#define S3C2410_UDC_EP0_CSR_IPKRDY	(1<<1)
-#define S3C2410_UDC_EP0_CSR_SENTSTL	(1<<2)
-#define S3C2410_UDC_EP0_CSR_DE		(1<<3)
-#define S3C2410_UDC_EP0_CSR_SE		(1<<4)
-#define S3C2410_UDC_EP0_CSR_SENDSTL	(1<<5)
-#define S3C2410_UDC_EP0_CSR_SOPKTRDY	(1<<6)
-#define S3C2410_UDC_EP0_CSR_SSE	(1<<7)
-
-#define S3C2410_UDC_MAXP_8		(1<<0)
-#define S3C2410_UDC_MAXP_16		(1<<1)
-#define S3C2410_UDC_MAXP_32		(1<<2)
-#define S3C2410_UDC_MAXP_64		(1<<3)
-
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/s3c2410.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/s3c2410.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/s3c2410.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/s3c2410.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2410.h
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2410 machine directory
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-#ifdef CONFIG_CPU_S3C2410
-
-extern  int s3c2410_init(void);
-extern  int s3c2410a_init(void);
-
-extern void s3c2410_map_io(void);
-
-extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2410_init_clocks(int xtal);
-
-#else
-#define s3c2410_init_clocks NULL
-#define s3c2410_init_uarts NULL
-#define s3c2410_map_io NULL
-#define s3c2410_init NULL
-#define s3c2410a_init NULL
-#endif
-
-extern int s3c2410_baseclk_add(void);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/s3c2412.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/s3c2412.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/s3c2412.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/s3c2412.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2412.h
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2412 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.
-*/
-
-#ifdef CONFIG_CPU_S3C2412
-
-extern  int s3c2412_init(void);
-
-extern void s3c2412_map_io(void);
-
-extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2412_init_clocks(int xtal);
-
-extern  int s3c2412_baseclk_add(void);
-#else
-#define s3c2412_init_clocks NULL
-#define s3c2412_init_uarts NULL
-#define s3c2412_map_io NULL
-#define s3c2412_init NULL
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/s3c2416.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/s3c2416.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/s3c2416.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/s3c2416.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,31 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2443.h
- *
- * Copyright (c) 2009 Yauhen Kharuzhy <jekhor@gmail.com>
- *
- * Header file for s3c2416 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.
-*/
-
-#ifdef CONFIG_CPU_S3C2416
-
-struct s3c2410_uartcfg;
-
-extern  int s3c2416_init(void);
-
-extern void s3c2416_map_io(void);
-
-extern void s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2416_init_clocks(int xtal);
-
-extern  int s3c2416_baseclk_add(void);
-
-#else
-#define s3c2416_init_clocks NULL
-#define s3c2416_init_uarts NULL
-#define s3c2416_map_io NULL
-#define s3c2416_init NULL
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/s3c2443.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/s3c2443.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/s3c2443.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/s3c2443.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2443.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2443 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.
-*/
-
-#ifdef CONFIG_CPU_S3C2443
-
-struct s3c2410_uartcfg;
-
-extern  int s3c2443_init(void);
-
-extern void s3c2443_map_io(void);
-
-extern void s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2443_init_clocks(int xtal);
-
-extern  int s3c2443_baseclk_add(void);
-
-#else
-#define s3c2443_init_clocks NULL
-#define s3c2443_init_uarts NULL
-#define s3c2443_map_io NULL
-#define s3c2443_init NULL
-#endif
-
-/* common code used by s3c2443 and others.
- * note, not to be used outside of arch/arm/mach-s3c* */
-
-struct clk;	/* some files don't need clk.h otherwise */
-
-typedef unsigned int (*pll_fn)(unsigned int reg, unsigned int base);
-typedef unsigned int (*fdiv_fn)(unsigned long clkcon0);
-
-extern void s3c2443_common_setup_clocks(pll_fn get_mpll, fdiv_fn fdiv);
-extern void s3c2443_common_init_clocks(int xtal, pll_fn get_mpll, fdiv_fn fdiv);
-
-extern int s3c2443_clkcon_enable_h(struct clk *clk, int enable);
-extern int s3c2443_clkcon_enable_p(struct clk *clk, int enable);
-extern int s3c2443_clkcon_enable_s(struct clk *clk, int enable);
-
-extern struct clksrc_clk clk_epllref;
-extern struct clksrc_clk clk_esysclk;
-extern struct clksrc_clk clk_msysclk;
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/s3c244x.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/s3c244x.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/s3c244x.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/s3c244x.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/include/plat/s3c244x.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C2440 and S3C2442 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.
-*/
-
-#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
-
-extern void s3c244x_map_io(void);
-
-extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c244x_init_clocks(int xtal);
-
-#else
-#define s3c244x_init_clocks NULL
-#define s3c244x_init_uarts NULL
-#endif
-
-#ifdef CONFIG_CPU_S3C2440
-extern  int s3c2440_init(void);
-
-extern void s3c2440_map_io(void);
-#else
-#define s3c2440_init NULL
-#define s3c2440_map_io NULL
-#endif
-
-#ifdef CONFIG_CPU_S3C2442
-extern  int s3c2442_init(void);
-
-extern void s3c2442_map_io(void);
-#else
-#define s3c2442_init NULL
-#define s3c2442_map_io NULL
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/udc.h linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/udc.h
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/include/plat/udc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/include/plat/udc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,57 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/udc.h
- *
- * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *
- *  Changelog:
- *	14-Mar-2005	RTP	Created file
- *	02-Aug-2005	RTP	File rename
- *	07-Sep-2005	BJD	Minor cleanups, changed cmd to enum
- *	18-Jan-2007	HMW	Add per-platform vbus_draw function
-*/
-
-#ifndef __ASM_ARM_ARCH_UDC_H
-#define __ASM_ARM_ARCH_UDC_H
-
-enum s3c2410_udc_cmd_e {
-	S3C2410_UDC_P_ENABLE	= 1,	/* Pull-up enable        */
-	S3C2410_UDC_P_DISABLE	= 2,	/* Pull-up disable       */
-	S3C2410_UDC_P_RESET	= 3,	/* UDC reset, in case of */
-};
-
-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;
-};
-
-extern void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *);
-
-/**
- * s3c24xx_hsudc_platdata - Platform data for USB High-Speed gadget controller.
- * @epnum: Number of endpoints to be instantiated by the controller driver.
- * @gpio_init: Platform specific USB related GPIO initialization.
- * @gpio_uninit: Platform specific USB releted GPIO uninitialzation.
- *
- * Representation of platform data for the S3C24XX USB 2.0 High Speed gadget
- * controllers.
- */
-struct s3c24xx_hsudc_platdata {
-	unsigned int	epnum;
-	void		(*gpio_init)(void);
-	void		(*gpio_uninit)(void);
-};
-
-extern void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd);
-
-#endif /* __ASM_ARM_ARCH_UDC_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/Kconfig linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/Kconfig
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@
 	select NO_IOPORT
 	select ARCH_REQUIRE_GPIOLIB
 	select S3C_DEV_NAND
-	select S3C_GPIO_CFG_S3C24XX
 	help
 	  Base platform code for any Samsung S3C24XX device
 
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/Makefile linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/Makefile
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -14,9 +14,7 @@
 
 obj-y				+= cpu.o
 obj-y				+= irq.o
-obj-y				+= devs.o
-obj-y				+= gpio.o
-obj-y				+= gpiolib.o
+obj-y				+= dev-uart.o
 obj-y				+= clock.o
 obj-$(CONFIG_S3C24XX_DCLK)	+= clock-dclk.o
 
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/s3c2443-clock.c linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/s3c2443-clock.c
--- linux-libre-3.1-gnu/arch/arm/plat-s3c24xx/s3c2443-clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s3c24xx/s3c2443-clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -160,6 +160,124 @@
 	},
 };
 
+/* armdiv
+ *
+ * this clock is sourced from msysclk and can have a number of
+ * divider values applied to it to then be fed into armclk.
+*/
+
+static unsigned int *armdiv;
+static int nr_armdiv;
+static int armdivmask;
+
+static unsigned long s3c2443_armclk_roundrate(struct clk *clk,
+					      unsigned long rate)
+{
+	unsigned long parent = clk_get_rate(clk->parent);
+	unsigned long calc;
+	unsigned best = 256; /* bigger than any value */
+	unsigned div;
+	int ptr;
+
+	if (!nr_armdiv)
+		return -EINVAL;
+
+	for (ptr = 0; ptr < nr_armdiv; ptr++) {
+		div = armdiv[ptr];
+		if (div) {
+			/* cpufreq provides 266mhz as 266666000 not 266666666 */
+			calc = (parent / div / 1000) * 1000;
+			if (calc <= rate && div < best)
+				best = div;
+		}
+	}
+
+	return parent / best;
+}
+
+static unsigned long s3c2443_armclk_getrate(struct clk *clk)
+{
+	unsigned long rate = clk_get_rate(clk->parent);
+	unsigned long clkcon0;
+	int val;
+
+	if (!nr_armdiv || !armdivmask)
+		return -EINVAL;
+
+	clkcon0 = __raw_readl(S3C2443_CLKDIV0);
+	clkcon0 &= armdivmask;
+	val = clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT;
+
+	return rate / armdiv[val];
+}
+
+static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent = clk_get_rate(clk->parent);
+	unsigned long calc;
+	unsigned div;
+	unsigned best = 256; /* bigger than any value */
+	int ptr;
+	int val = -1;
+
+	if (!nr_armdiv || !armdivmask)
+		return -EINVAL;
+
+	for (ptr = 0; ptr < nr_armdiv; ptr++) {
+		div = armdiv[ptr];
+		if (div) {
+			/* cpufreq provides 266mhz as 266666000 not 266666666 */
+			calc = (parent / div / 1000) * 1000;
+			if (calc <= rate && div < best) {
+				best = div;
+				val = ptr;
+			}
+		}
+	}
+
+	if (val >= 0) {
+		unsigned long clkcon0;
+
+		clkcon0 = __raw_readl(S3C2443_CLKDIV0);
+		clkcon0 &= ~armdivmask;
+		clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT;
+		__raw_writel(clkcon0, S3C2443_CLKDIV0);
+	}
+
+	return (val == -1) ? -EINVAL : 0;
+}
+
+static struct clk clk_armdiv = {
+	.name		= "armdiv",
+	.parent		= &clk_msysclk.clk,
+	.ops		= &(struct clk_ops) {
+		.round_rate = s3c2443_armclk_roundrate,
+		.get_rate = s3c2443_armclk_getrate,
+		.set_rate = s3c2443_armclk_setrate,
+	},
+};
+
+/* armclk
+ *
+ * this is the clock fed into the ARM core itself, from armdiv or from hclk.
+ */
+
+static struct clk *clk_arm_sources[] = {
+	[0] = &clk_armdiv,
+	[1] = &clk_h,
+};
+
+static struct clksrc_clk clk_arm = {
+	.clk	= {
+		.name		= "armclk",
+	},
+	.sources = &(struct clksrc_sources) {
+		.sources = clk_arm_sources,
+		.nr_sources = ARRAY_SIZE(clk_arm_sources),
+	},
+	.reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 },
+};
+
 /* usbhost
  *
  * usb host bus-clock, usually 48MHz to provide USB bus clock timing
@@ -205,9 +323,64 @@
 	},
 };
 
+static struct clk clk_i2s_ext = {
+	.name		= "i2s-ext",
+};
+
+/* i2s_eplldiv
+ *
+ * This clock is the output from the I2S divisor of ESYSCLK, and is separate
+ * from the mux that comes after it (cannot merge into one single clock)
+*/
+
+static struct clksrc_clk clk_i2s_eplldiv = {
+	.clk	= {
+		.name		= "i2s-eplldiv",
+		.parent		= &clk_esysclk.clk,
+	},
+	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
+};
+
+/* i2s-ref
+ *
+ * i2s bus reference clock, selectable from external, esysclk or epllref
+ *
+ * Note, this used to be two clocks, but was compressed into one.
+*/
+
+static struct clk *clk_i2s_srclist[] = {
+	[0] = &clk_i2s_eplldiv.clk,
+	[1] = &clk_i2s_ext,
+	[2] = &clk_epllref.clk,
+	[3] = &clk_epllref.clk,
+};
+
+static struct clksrc_clk clk_i2s = {
+	.clk	= {
+		.name		= "i2s-if",
+		.ctrlbit	= S3C2443_SCLKCON_I2SCLK,
+		.enable		= s3c2443_clkcon_enable_s,
+
+	},
+	.sources = &(struct clksrc_sources) {
+		.sources = clk_i2s_srclist,
+		.nr_sources = ARRAY_SIZE(clk_i2s_srclist),
+	},
+	.reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
+};
 
 static struct clk init_clocks_off[] = {
 	{
+		.name		= "iis",
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_IIS,
+	}, {
+		.name		= "hsspi",
+		.parent		= &clk_p,
+		.enable		= s3c2443_clkcon_enable_p,
+		.ctrlbit	= S3C2443_PCLKCON_HSSPI,
+	}, {
 		.name		= "adc",
 		.parent		= &clk_p,
 		.enable		= s3c2443_clkcon_enable_p,
@@ -253,6 +426,7 @@
 		.ctrlbit	= S3C2443_HCLKCON_DMA5,
 	}, {
 		.name		= "hsmmc",
+		.devname	= "s3c-sdhci.1",
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_HSMMC,
@@ -347,8 +521,7 @@
 
 /* EPLLCON compatible enough to get on/off information */
 
-void __init_or_cpufreq s3c2443_common_setup_clocks(pll_fn get_mpll,
-						   fdiv_fn get_fdiv)
+void __init_or_cpufreq s3c2443_common_setup_clocks(pll_fn get_mpll)
 {
 	unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
 	unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON);
@@ -368,7 +541,7 @@
 	pll = get_mpll(mpllcon, xtal);
 	clk_msysclk.clk.rate = pll;
 
-	fclk = pll / get_fdiv(clkdiv0);
+	fclk = clk_get_rate(&clk_armdiv);
 	hclk = s3c2443_prediv_getrate(&clk_prediv);
 	hclk /= s3c2443_get_hdiv(clkdiv0);
 	pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1);
@@ -403,20 +576,29 @@
 	&clk_ext,
 	&clk_epll,
 	&clk_usb_bus,
+	&clk_armdiv,
 };
 
 static struct clksrc_clk *clksrcs[] __initdata = {
+	&clk_i2s_eplldiv,
+	&clk_i2s,
 	&clk_usb_bus_host,
 	&clk_epllref,
 	&clk_esysclk,
 	&clk_msysclk,
+	&clk_arm,
 };
 
 void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
-				       fdiv_fn get_fdiv)
+				       unsigned int *divs, int nr_divs,
+				       int divmask)
 {
 	int ptr;
 
+	armdiv = divs;
+	nr_armdiv = nr_divs;
+	armdivmask = divmask;
+
 	/* s3c2443 parents h and p clocks from prediv */
 	clk_h.parent = &clk_prediv;
 	clk_p.parent = &clk_prediv;
@@ -437,5 +619,5 @@
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
-	s3c2443_common_setup_clocks(get_mpll, get_fdiv);
+	s3c2443_common_setup_clocks(get_mpll);
 }
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/cpu.c linux-libre-3.2-gnu/arch/arm/plat-s5p/cpu.c
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,48 +33,66 @@
 static const char name_s5pc100[] = "S5PC100";
 static const char name_s5pv210[] = "S5PV210/S5PC110";
 static const char name_exynos4210[] = "EXYNOS4210";
+static const char name_exynos4212[] = "EXYNOS4212";
+static const char name_exynos4412[] = "EXYNOS4412";
 
 static struct cpu_table cpu_ids[] __initdata = {
 	{
-		.idcode		= 0x56440100,
-		.idmask		= 0xfffff000,
+		.idcode		= S5P6440_CPU_ID,
+		.idmask		= S5P64XX_CPU_MASK,
 		.map_io		= s5p6440_map_io,
 		.init_clocks	= s5p6440_init_clocks,
 		.init_uarts	= s5p6440_init_uarts,
 		.init		= s5p64x0_init,
 		.name		= name_s5p6440,
 	}, {
-		.idcode		= 0x36450000,
-		.idmask		= 0xfffff000,
+		.idcode		= S5P6450_CPU_ID,
+		.idmask		= S5P64XX_CPU_MASK,
 		.map_io		= s5p6450_map_io,
 		.init_clocks	= s5p6450_init_clocks,
 		.init_uarts	= s5p6450_init_uarts,
 		.init		= s5p64x0_init,
 		.name		= name_s5p6450,
 	}, {
-		.idcode		= 0x43100000,
-		.idmask		= 0xfffff000,
+		.idcode		= S5PC100_CPU_ID,
+		.idmask		= S5PC100_CPU_MASK,
 		.map_io		= s5pc100_map_io,
 		.init_clocks	= s5pc100_init_clocks,
 		.init_uarts	= s5pc100_init_uarts,
 		.init		= s5pc100_init,
 		.name		= name_s5pc100,
 	}, {
-		.idcode		= 0x43110000,
-		.idmask		= 0xfffff000,
+		.idcode		= S5PV210_CPU_ID,
+		.idmask		= S5PV210_CPU_MASK,
 		.map_io		= s5pv210_map_io,
 		.init_clocks	= s5pv210_init_clocks,
 		.init_uarts	= s5pv210_init_uarts,
 		.init		= s5pv210_init,
 		.name		= name_s5pv210,
 	}, {
-		.idcode		= 0x43210000,
-		.idmask		= 0xfffe0000,
+		.idcode		= EXYNOS4210_CPU_ID,
+		.idmask		= EXYNOS4_CPU_MASK,
 		.map_io		= exynos4_map_io,
 		.init_clocks	= exynos4_init_clocks,
 		.init_uarts	= exynos4_init_uarts,
-		.init		= exynos4_init,
+		.init		= exynos_init,
 		.name		= name_exynos4210,
+	}, {
+		.idcode		= EXYNOS4212_CPU_ID,
+		.idmask		= EXYNOS4_CPU_MASK,
+		.map_io		= exynos4_map_io,
+		.init_clocks	= exynos4_init_clocks,
+		.init_uarts	= exynos4_init_uarts,
+		.init		= exynos_init,
+		.name		= name_exynos4212,
+	}, {
+		.idcode		= EXYNOS4412_CPU_ID,
+		.idmask		= EXYNOS4_CPU_MASK,
+		.map_io		= exynos4_map_io,
+		.init_clocks	= exynos4_init_clocks,
+		.init_uarts	= exynos4_init_uarts,
+		.init		= exynos_init,
+		.name		= name_exynos4412,
 	},
 };
 
@@ -114,13 +132,13 @@
 void __init s5p_init_io(struct map_desc *mach_desc,
 			int size, void __iomem *cpuid_addr)
 {
-	unsigned long idcode;
-
 	/* initialize the io descriptors we need for initialization */
 	iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc));
 	if (mach_desc)
 		iotable_init(mach_desc, size);
 
-	idcode = __raw_readl(cpuid_addr);
-	s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
+	/* detect cpu id and rev. */
+	s5p_init_cpu(cpuid_addr);
+
+	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
 }
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-csis0.c linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-csis0.c
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-csis0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-csis0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
- *
- * S5P series device definition for MIPI-CSIS channel 0
- *
- * This program is free software; you can 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/platform_device.h>
-#include <mach/map.h>
-
-static struct resource s5p_mipi_csis0_resource[] = {
-	[0] = {
-		.start = S5P_PA_MIPI_CSIS0,
-		.end   = S5P_PA_MIPI_CSIS0 + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_MIPI_CSIS0,
-		.end   = IRQ_MIPI_CSIS0,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device s5p_device_mipi_csis0 = {
-	.name		  = "s5p-mipi-csis",
-	.id		  = 0,
-	.num_resources	  = ARRAY_SIZE(s5p_mipi_csis0_resource),
-	.resource	  = s5p_mipi_csis0_resource,
-};
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-csis1.c linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-csis1.c
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-csis1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-csis1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
- *
- * S5P series device definition for MIPI-CSIS channel 1
- *
- * This program is free software; you can 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/platform_device.h>
-#include <mach/map.h>
-
-static struct resource s5p_mipi_csis1_resource[] = {
-	[0] = {
-		.start = S5P_PA_MIPI_CSIS1,
-		.end   = S5P_PA_MIPI_CSIS1 + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_MIPI_CSIS1,
-		.end   = IRQ_MIPI_CSIS1,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s5p_device_mipi_csis1 = {
-	.name		  = "s5p-mipi-csis",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s5p_mipi_csis1_resource),
-	.resource	  = s5p_mipi_csis1_resource,
-};
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-ehci.c linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-ehci.c
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-ehci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-ehci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2011 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/platform_device.h>
-#include <mach/irqs.h>
-#include <mach/map.h>
-#include <plat/devs.h>
-#include <plat/ehci.h>
-#include <plat/usb-phy.h>
-
-/* USB EHCI Host Controller registration */
-static struct resource s5p_ehci_resource[] = {
-	[0] = {
-		.start	= S5P_PA_EHCI,
-		.end	= S5P_PA_EHCI + SZ_256 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_USB_HOST,
-		.end	= IRQ_USB_HOST,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static u64 s5p_device_ehci_dmamask = 0xffffffffUL;
-
-struct platform_device s5p_device_ehci = {
-	.name		= "s5p-ehci",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p_ehci_resource),
-	.resource	= s5p_ehci_resource,
-	.dev		= {
-		.dma_mask = &s5p_device_ehci_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-void __init s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd)
-{
-	struct s5p_ehci_platdata *npd;
-
-	npd = s3c_set_platdata(pd, sizeof(struct s5p_ehci_platdata),
-			&s5p_device_ehci);
-
-	if (!npd->phy_init)
-		npd->phy_init = s5p_usb_phy_init;
-	if (!npd->phy_exit)
-		npd->phy_exit = s5p_usb_phy_exit;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-fimc0.c linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-fimc0.c
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-fimc0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-fimc0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/* linux/arch/arm/plat-s5p/dev-fimc0.c
- *
- * Copyright (c) 2010 Samsung Electronics
- *
- * Base S5P FIMC0 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_fimc0_resource[] = {
-	[0] = {
-		.start	= S5P_PA_FIMC0,
-		.end	= S5P_PA_FIMC0 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_FIMC0,
-		.end	= IRQ_FIMC0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 s5p_fimc0_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device s5p_device_fimc0 = {
-	.name		= "s5p-fimc",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5p_fimc0_resource),
-	.resource	= s5p_fimc0_resource,
-	.dev		= {
-		.dma_mask		= &s5p_fimc0_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-fimc1.c linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-fimc1.c
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-fimc1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-fimc1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/* linux/arch/arm/plat-s5p/dev-fimc1.c
- *
- * Copyright (c) 2010 Samsung Electronics
- *
- * Base S5P FIMC1 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_fimc1_resource[] = {
-	[0] = {
-		.start	= S5P_PA_FIMC1,
-		.end	= S5P_PA_FIMC1 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_FIMC1,
-		.end	= IRQ_FIMC1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 s5p_fimc1_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device s5p_device_fimc1 = {
-	.name		= "s5p-fimc",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5p_fimc1_resource),
-	.resource	= s5p_fimc1_resource,
-	.dev		= {
-		.dma_mask		= &s5p_fimc1_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-fimc2.c linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-fimc2.c
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-fimc2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-fimc2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/* linux/arch/arm/plat-s5p/dev-fimc2.c
- *
- * Copyright (c) 2010 Samsung Electronics
- *
- * Base S5P FIMC2 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_fimc2_resource[] = {
-	[0] = {
-		.start	= S5P_PA_FIMC2,
-		.end	= S5P_PA_FIMC2 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_FIMC2,
-		.end	= IRQ_FIMC2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 s5p_fimc2_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device s5p_device_fimc2 = {
-	.name		= "s5p-fimc",
-	.id		= 2,
-	.num_resources	= ARRAY_SIZE(s5p_fimc2_resource),
-	.resource	= s5p_fimc2_resource,
-	.dev		= {
-		.dma_mask		= &s5p_fimc2_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-fimc3.c linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-fimc3.c
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-fimc3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-fimc3.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/* 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-3.1-gnu/arch/arm/plat-s5p/dev-fimd0.c linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-fimd0.c
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-fimd0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-fimd0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,67 +0,0 @@
-/* linux/arch/arm/plat-s5p/dev-fimd0.c
- *
- * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Core file for Samsung Display Controller (FIMD) 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/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-#include <linux/fb.h>
-#include <linux/gfp.h>
-#include <linux/dma-mapping.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/fb.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s5p_fimd0_resource[] = {
-	[0] = {
-		.start	= S5P_PA_FIMD0,
-		.end	= S5P_PA_FIMD0 + SZ_32K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_FIMD0_VSYNC,
-		.end	= IRQ_FIMD0_VSYNC,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_FIMD0_FIFO,
-		.end	= IRQ_FIMD0_FIFO,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= IRQ_FIMD0_SYSTEM,
-		.end	= IRQ_FIMD0_SYSTEM,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 fimd0_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5p_device_fimd0 = {
-	.name		= "s5p-fb",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5p_fimd0_resource),
-	.resource	= s5p_fimd0_resource,
-	.dev		= {
-		.dma_mask		= &fimd0_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-void __init s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd)
-{
-	s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
-			&s5p_device_fimd0);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-mfc.c linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-mfc.c
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-mfc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-mfc.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,56 +22,6 @@
 #include <plat/irqs.h>
 #include <plat/mfc.h>
 
-static struct resource s5p_mfc_resource[] = {
-	[0] = {
-		.start	= S5P_PA_MFC,
-		.end	= S5P_PA_MFC + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_MFC,
-		.end	= IRQ_MFC,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device s5p_device_mfc = {
-	.name		= "s5p-mfc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p_mfc_resource),
-	.resource	= s5p_mfc_resource,
-};
-
-/*
- * MFC hardware has 2 memory interfaces which are modelled as two separate
- * platform devices to let dma-mapping distinguish between them.
- *
- * MFC parent device (s5p_device_mfc) must be registered before memory
- * interface specific devices (s5p_device_mfc_l and s5p_device_mfc_r).
- */
-
-static u64 s5p_mfc_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device s5p_device_mfc_l = {
-	.name		= "s5p-mfc-l",
-	.id		= -1,
-	.dev		= {
-		.parent			= &s5p_device_mfc.dev,
-		.dma_mask		= &s5p_mfc_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-struct platform_device s5p_device_mfc_r = {
-	.name		= "s5p-mfc-r",
-	.id		= -1,
-	.dev		= {
-		.parent			= &s5p_device_mfc.dev,
-		.dma_mask		= &s5p_mfc_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
 struct s5p_mfc_reserved_mem {
 	phys_addr_t	base;
 	unsigned long	size;
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-onenand.c linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-onenand.c
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-onenand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-onenand.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-/* linux/arch/arm/plat-s5p/dev-onenand.c
- *
- * Copyright 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- *  Copyright (c) 2008-2010 Samsung Electronics
- *  Kyungmin Park <kyungmin.park@samsung.com>
- *
- * S5P series device definition for OneNAND devices
- *
- * This program is free software; you can 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 <mach/map.h>
-
-static struct resource s5p_onenand_resources[] = {
-	[0] = {
-		.start	= S5P_PA_ONENAND,
-		.end	= S5P_PA_ONENAND + SZ_128K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= S5P_PA_ONENAND_DMA,
-		.end	= S5P_PA_ONENAND_DMA + SZ_8K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= IRQ_ONENAND_AUDI,
-		.end	= IRQ_ONENAND_AUDI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s5p_device_onenand = {
-	.name		= "s5pc110-onenand",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p_onenand_resources),
-	.resource	= s5p_onenand_resources,
-};
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-pmu.c linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-pmu.c
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-pmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-pmu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-/*
- * linux/arch/arm/plat-s5p/dev-pmu.c
- *
- * 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/platform_device.h>
-#include <asm/pmu.h>
-#include <mach/irqs.h>
-
-static struct resource s5p_pmu_resource = {
-	.start	= IRQ_PMU,
-	.end	= IRQ_PMU,
-	.flags	= IORESOURCE_IRQ,
-};
-
-struct platform_device s5p_device_pmu = {
-	.name		= "arm-pmu",
-	.id		= ARM_PMU_DEVICE_CPU,
-	.num_resources	= 1,
-	.resource	= &s5p_pmu_resource,
-};
-
-static int __init s5p_pmu_init(void)
-{
-	platform_device_register(&s5p_device_pmu);
-	return 0;
-}
-arch_initcall(s5p_pmu_init);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-uart.c linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-uart.c
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/dev-uart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/dev-uart.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,20 +32,10 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S5P_UART_RX0,
-		.end	= IRQ_S5P_UART_RX0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S5P_UART_TX0,
-		.end	= IRQ_S5P_UART_TX0,
+		.start	= IRQ_UART0,
+		.end	= IRQ_UART0,
 		.flags	= IORESOURCE_IRQ,
 	},
-	[3] = {
-		.start	= IRQ_S5P_UART_ERR0,
-		.end	= IRQ_S5P_UART_ERR0,
-		.flags	= IORESOURCE_IRQ,
-	}
 };
 
 static struct resource s5p_uart1_resource[] = {
@@ -55,18 +45,8 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S5P_UART_RX1,
-		.end	= IRQ_S5P_UART_RX1,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S5P_UART_TX1,
-		.end	= IRQ_S5P_UART_TX1,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= IRQ_S5P_UART_ERR1,
-		.end	= IRQ_S5P_UART_ERR1,
+		.start	= IRQ_UART1,
+		.end	= IRQ_UART1,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -78,18 +58,8 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S5P_UART_RX2,
-		.end	= IRQ_S5P_UART_RX2,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S5P_UART_TX2,
-		.end	= IRQ_S5P_UART_TX2,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= IRQ_S5P_UART_ERR2,
-		.end	= IRQ_S5P_UART_ERR2,
+		.start	= IRQ_UART2,
+		.end	= IRQ_UART2,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -102,18 +72,8 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S5P_UART_RX3,
-		.end	= IRQ_S5P_UART_RX3,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S5P_UART_TX3,
-		.end	= IRQ_S5P_UART_TX3,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= IRQ_S5P_UART_ERR3,
-		.end	= IRQ_S5P_UART_ERR3,
+		.start	= IRQ_UART3,
+		.end	= IRQ_UART3,
 		.flags	= IORESOURCE_IRQ,
 	},
 #endif
@@ -127,18 +87,8 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S5P_UART_RX4,
-		.end	= IRQ_S5P_UART_RX4,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S5P_UART_TX4,
-		.end	= IRQ_S5P_UART_TX4,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= IRQ_S5P_UART_ERR4,
-		.end	= IRQ_S5P_UART_ERR4,
+		.start	= IRQ_UART4,
+		.end	= IRQ_UART4,
 		.flags	= IORESOURCE_IRQ,
 	},
 #endif
@@ -152,18 +102,8 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_S5P_UART_RX5,
-		.end	= IRQ_S5P_UART_RX5,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S5P_UART_TX5,
-		.end	= IRQ_S5P_UART_TX5,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= IRQ_S5P_UART_ERR5,
-		.end	= IRQ_S5P_UART_ERR5,
+		.start	= IRQ_UART5,
+		.end	= IRQ_UART5,
 		.flags	= IORESOURCE_IRQ,
 	},
 #endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/camport.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/camport.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/camport.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/camport.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- * 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-3.1-gnu/arch/arm/plat-s5p/include/plat/ehci.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/ehci.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/ehci.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/ehci.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#ifndef __PLAT_S5P_EHCI_H
-#define __PLAT_S5P_EHCI_H
-
-struct s5p_ehci_platdata {
-	int (*phy_init)(struct platform_device *pdev, int type);
-	int (*phy_exit)(struct platform_device *pdev, int type);
-};
-
-extern void s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd);
-
-#endif /* __PLAT_S5P_EHCI_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/exynos4.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/exynos4.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/exynos4.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/exynos4.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-/* 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-3.1-gnu/arch/arm/plat-s5p/include/plat/irqs.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/irqs.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/irqs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/irqs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,115 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/irqs.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P Common IRQ 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_IRQS_H
-#define __ASM_PLAT_S5P_IRQS_H __FILE__
-
-/* we keep the first set of CPU IRQs out of the range of
- * the ISA space, so that the PC104 has them to itself
- * and we don't end up having to do horrible things to the
- * standard ISA drivers....
- *
- * note, since we're using the VICs, our start must be a
- * mulitple of 32 to allow the common code to work
- */
-
-#define S5P_IRQ_OFFSET		(32)
-
-#define S5P_IRQ(x)		((x) + S5P_IRQ_OFFSET)
-
-#define S5P_VIC0_BASE		S5P_IRQ(0)
-#define S5P_VIC1_BASE		S5P_IRQ(32)
-#define S5P_VIC2_BASE		S5P_IRQ(64)
-#define S5P_VIC3_BASE		S5P_IRQ(96)
-
-#define VIC_BASE(x)		(S5P_VIC0_BASE + ((x)*32))
-
-#define IRQ_VIC0_BASE		S5P_VIC0_BASE
-#define IRQ_VIC1_BASE		S5P_VIC1_BASE
-#define IRQ_VIC2_BASE		S5P_VIC2_BASE
-
-/* UART interrupts, each UART has 4 intterupts per channel so
- * use the space between the ISA and S3C main interrupts. Note, these
- * are not in the same order as the S3C24XX series! */
-
-#define IRQ_S5P_UART_BASE0	(16)
-#define IRQ_S5P_UART_BASE1	(20)
-#define IRQ_S5P_UART_BASE2	(24)
-#define IRQ_S5P_UART_BASE3	(28)
-
-#define UART_IRQ_RXD		(0)
-#define UART_IRQ_ERR		(1)
-#define UART_IRQ_TXD		(2)
-
-#define IRQ_S5P_UART_RX0	(IRQ_S5P_UART_BASE0 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX0	(IRQ_S5P_UART_BASE0 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR0	(IRQ_S5P_UART_BASE0 + UART_IRQ_ERR)
-
-#define IRQ_S5P_UART_RX1	(IRQ_S5P_UART_BASE1 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX1	(IRQ_S5P_UART_BASE1 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR1	(IRQ_S5P_UART_BASE1 + UART_IRQ_ERR)
-
-#define IRQ_S5P_UART_RX2	(IRQ_S5P_UART_BASE2 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX2	(IRQ_S5P_UART_BASE2 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR2	(IRQ_S5P_UART_BASE2 + UART_IRQ_ERR)
-
-#define IRQ_S5P_UART_RX3	(IRQ_S5P_UART_BASE3 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX3	(IRQ_S5P_UART_BASE3 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR3	(IRQ_S5P_UART_BASE3 + UART_IRQ_ERR)
-
-/* S3C compatibilty defines */
-#define IRQ_S3CUART_RX0		IRQ_S5P_UART_RX0
-#define IRQ_S3CUART_RX1		IRQ_S5P_UART_RX1
-#define IRQ_S3CUART_RX2		IRQ_S5P_UART_RX2
-#define IRQ_S3CUART_RX3		IRQ_S5P_UART_RX3
-
-/* VIC based IRQs */
-
-#define S5P_IRQ_VIC0(x)		(S5P_VIC0_BASE + (x))
-#define S5P_IRQ_VIC1(x)		(S5P_VIC1_BASE + (x))
-#define S5P_IRQ_VIC2(x)		(S5P_VIC2_BASE + (x))
-#define S5P_IRQ_VIC3(x)		(S5P_VIC3_BASE + (x))
-
-#define S5P_TIMER_IRQ(x)	(11 + (x))
-
-#define IRQ_TIMER0		S5P_TIMER_IRQ(0)
-#define IRQ_TIMER1		S5P_TIMER_IRQ(1)
-#define IRQ_TIMER2		S5P_TIMER_IRQ(2)
-#define IRQ_TIMER3		S5P_TIMER_IRQ(3)
-#define IRQ_TIMER4		S5P_TIMER_IRQ(4)
-
-#define IRQ_EINT(x)		((x) < 16 ? ((x) + S5P_EINT_BASE1) \
-					: ((x) - 16 + S5P_EINT_BASE2))
-
-#define EINT_OFFSET(irq)	((irq) < S5P_EINT_BASE2 ? \
-						((irq) - S5P_EINT_BASE1) : \
-						((irq) + 16 - S5P_EINT_BASE2))
-
-#define IRQ_EINT_BIT(x)		EINT_OFFSET(x)
-
-/* Typically only a few gpio chips require gpio interrupt support.
-   To avoid memory waste irq descriptors are allocated only for
-   S5P_GPIOINT_GROUP_COUNT chips, each with total number of
-   S5P_GPIOINT_GROUP_SIZE pins/irqs. Each GPIOINT group can be assiged
-   to any gpio chip with the s5p_register_gpio_interrupt() function */
-#define S5P_GPIOINT_GROUP_COUNT 4
-#define S5P_GPIOINT_GROUP_SIZE	8
-#define S5P_GPIOINT_COUNT	(S5P_GPIOINT_GROUP_COUNT * S5P_GPIOINT_GROUP_SIZE)
-
-/* IRQ types common for all s5p platforms */
-#define S5P_IRQ_TYPE_LEVEL_LOW		(0x00)
-#define S5P_IRQ_TYPE_LEVEL_HIGH		(0x01)
-#define S5P_IRQ_TYPE_EDGE_FALLING	(0x02)
-#define S5P_IRQ_TYPE_EDGE_RISING	(0x03)
-#define S5P_IRQ_TYPE_EDGE_BOTH		(0x04)
-
-#endif /* __ASM_PLAT_S5P_IRQS_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/map-s5p.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/map-s5p.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/map-s5p.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/map-s5p.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/map-s5p.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P - 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_PLAT_MAP_S5P_H
-#define __ASM_PLAT_MAP_S5P_H __FILE__
-
-#define S5P_VA_CHIPID		S3C_ADDR(0x02000000)
-#define S5P_VA_CMU		S3C_ADDR(0x02100000)
-#define S5P_VA_PMU		S3C_ADDR(0x02180000)
-#define S5P_VA_GPIO		S3C_ADDR(0x02200000)
-#define S5P_VA_GPIO1		S5P_VA_GPIO
-#define S5P_VA_GPIO2		S3C_ADDR(0x02240000)
-#define S5P_VA_GPIO3		S3C_ADDR(0x02280000)
-
-#define S5P_VA_SYSRAM		S3C_ADDR(0x02400000)
-#define S5P_VA_DMC0		S3C_ADDR(0x02440000)
-#define S5P_VA_DMC1		S3C_ADDR(0x02480000)
-#define S5P_VA_SROMC		S3C_ADDR(0x024C0000)
-
-#define S5P_VA_SYSTIMER		S3C_ADDR(0x02500000)
-#define S5P_VA_L2CC		S3C_ADDR(0x02600000)
-
-#define S5P_VA_COMBINER_BASE	S3C_ADDR(0x02700000)
-#define S5P_VA_COMBINER(x)	(S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10)
-
-#define S5P_VA_COREPERI_BASE	S3C_ADDR(0x02800000)
-#define S5P_VA_COREPERI(x)	(S5P_VA_COREPERI_BASE + (x))
-#define S5P_VA_SCU		S5P_VA_COREPERI(0x0)
-#define S5P_VA_TWD		S5P_VA_COREPERI(0x600)
-
-#define S5P_VA_GIC_CPU		S3C_ADDR(0x02810000)
-#define S5P_VA_GIC_DIST		S3C_ADDR(0x02820000)
-
-#define S3C_VA_USB_HSPHY	S3C_ADDR(0x02900000)
-
-#define VA_VIC(x)		(S3C_VA_IRQ + ((x) * 0x10000))
-#define VA_VIC0			VA_VIC(0)
-#define VA_VIC1			VA_VIC(1)
-#define VA_VIC2			VA_VIC(2)
-#define VA_VIC3			VA_VIC(3)
-
-#define S5P_VA_UART(x)		(S3C_VA_UART + ((x) * S3C_UART_OFFSET))
-#define S5P_VA_UART0		S5P_VA_UART(0)
-#define S5P_VA_UART1		S5P_VA_UART(1)
-#define S5P_VA_UART2		S5P_VA_UART(2)
-#define S5P_VA_UART3		S5P_VA_UART(3)
-
-#ifndef S3C_UART_OFFSET
-#define S3C_UART_OFFSET		(0x400)
-#endif
-
-#endif /* __ASM_PLAT_MAP_S5P_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/mfc.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/mfc.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/mfc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/mfc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-/*
- * 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 as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#ifndef __PLAT_S5P_MFC_H
-#define __PLAT_S5P_MFC_H
-
-/**
- * s5p_mfc_reserve_mem - function to early reserve memory for MFC driver
- * @rbase:	base address for MFC 'right' memory interface
- * @rsize:	size of the memory reserved for MFC 'right' interface
- * @lbase:	base address for MFC 'left' memory interface
- * @lsize:	size of the memory reserved for MFC 'left' interface
- *
- * This function reserves system memory for both MFC device memory
- * interfaces and registers it to respective struct device entries as
- * coherent memory.
- */
-void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
-				phys_addr_t lbase, unsigned int lsize);
-
-#endif /* __PLAT_S5P_MFC_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/mipi_csis.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/mipi_csis.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/mipi_csis.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/mipi_csis.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/*
- * 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-3.1-gnu/arch/arm/plat-s5p/include/plat/pll.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/pll.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/pll.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/pll.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,153 +0,0 @@
-/* arch/arm/plat-s5p/include/plat/pll.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P PLL code
- *
- * Based on arch/arm/plat-s3c64xx/include/plat/pll.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.
-*/
-
-#define PLL45XX_MDIV_MASK	(0x3FF)
-#define PLL45XX_PDIV_MASK	(0x3F)
-#define PLL45XX_SDIV_MASK	(0x7)
-#define PLL45XX_MDIV_SHIFT	(16)
-#define PLL45XX_PDIV_SHIFT	(8)
-#define PLL45XX_SDIV_SHIFT	(0)
-
-#include <asm/div64.h>
-
-enum pll45xx_type_t {
-	pll_4500,
-	pll_4502,
-	pll_4508
-};
-
-static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
-					    enum pll45xx_type_t pll_type)
-{
-	u32 mdiv, pdiv, sdiv;
-	u64 fvco = baseclk;
-
-	mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
-	pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
-	sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
-
-	if (pll_type == pll_4508)
-		sdiv = sdiv - 1;
-
-	fvco *= mdiv;
-	do_div(fvco, (pdiv << sdiv));
-
-	return (unsigned long)fvco;
-}
-
-#define PLL46XX_KDIV_MASK	(0xFFFF)
-#define PLL4650C_KDIV_MASK	(0xFFF)
-#define PLL46XX_MDIV_MASK	(0x1FF)
-#define PLL46XX_PDIV_MASK	(0x3F)
-#define PLL46XX_SDIV_MASK	(0x7)
-#define PLL46XX_MDIV_SHIFT	(16)
-#define PLL46XX_PDIV_SHIFT	(8)
-#define PLL46XX_SDIV_SHIFT	(0)
-
-enum pll46xx_type_t {
-	pll_4600,
-	pll_4650,
-	pll_4650c,
-};
-
-static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
-					    u32 pll_con0, u32 pll_con1,
-					    enum pll46xx_type_t pll_type)
-{
-	unsigned long result;
-	u32 mdiv, pdiv, sdiv, kdiv;
-	u64 tmp;
-
-	mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
-	pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
-	sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
-	kdiv = pll_con1 & PLL46XX_KDIV_MASK;
-
-	if (pll_type == pll_4650c)
-		kdiv = pll_con1 & PLL4650C_KDIV_MASK;
-	else
-		kdiv = pll_con1 & PLL46XX_KDIV_MASK;
-
-	tmp = baseclk;
-
-	if (pll_type == pll_4600) {
-		tmp *= (mdiv << 16) + kdiv;
-		do_div(tmp, (pdiv << sdiv));
-		result = tmp >> 16;
-	} else {
-		tmp *= (mdiv << 10) + kdiv;
-		do_div(tmp, (pdiv << sdiv));
-		result = tmp >> 10;
-	}
-
-	return result;
-}
-
-#define PLL90XX_MDIV_MASK	(0xFF)
-#define PLL90XX_PDIV_MASK	(0x3F)
-#define PLL90XX_SDIV_MASK	(0x7)
-#define PLL90XX_KDIV_MASK	(0xffff)
-#define PLL90XX_MDIV_SHIFT	(16)
-#define PLL90XX_PDIV_SHIFT	(8)
-#define PLL90XX_SDIV_SHIFT	(0)
-#define PLL90XX_KDIV_SHIFT	(0)
-
-static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
-					    u32 pll_con, u32 pll_conk)
-{
-	unsigned long result;
-	u32 mdiv, pdiv, sdiv, kdiv;
-	u64 tmp;
-
-	mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK;
-	pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK;
-	sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
-	kdiv = pll_conk & PLL90XX_KDIV_MASK;
-
-	/* We need to multiple baseclk by mdiv (the integer part) and kdiv
-	 * which is in 2^16ths, so shift mdiv up (does not overflow) and
-	 * add kdiv before multiplying. The use of tmp is to avoid any
-	 * overflows before shifting bac down into result when multipling
-	 * by the mdiv and kdiv pair.
-	 */
-
-	tmp = baseclk;
-	tmp *= (mdiv << 16) + kdiv;
-	do_div(tmp, (pdiv << sdiv));
-	result = tmp >> 16;
-
-	return result;
-}
-
-#define PLL65XX_MDIV_MASK	(0x3FF)
-#define PLL65XX_PDIV_MASK	(0x3F)
-#define PLL65XX_SDIV_MASK	(0x7)
-#define PLL65XX_MDIV_SHIFT	(16)
-#define PLL65XX_PDIV_SHIFT	(8)
-#define PLL65XX_SDIV_SHIFT	(0)
-
-static inline unsigned long s5p_get_pll65xx(unsigned long baseclk, u32 pll_con)
-{
-	u32 mdiv, pdiv, sdiv;
-	u64 fvco = baseclk;
-
-	mdiv = (pll_con >> PLL65XX_MDIV_SHIFT) & PLL65XX_MDIV_MASK;
-	pdiv = (pll_con >> PLL65XX_PDIV_SHIFT) & PLL65XX_PDIV_MASK;
-	sdiv = (pll_con >> PLL65XX_SDIV_SHIFT) & PLL65XX_SDIV_MASK;
-
-	fvco *= mdiv;
-	do_div(fvco, (pdiv << sdiv));
-
-	return (unsigned long)fvco;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/regs-srom.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/regs-srom.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/regs-srom.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/regs-srom.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,54 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/regs-srom.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P SROMC 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_PLAT_S5P_REGS_SROM_H
-#define __ASM_PLAT_S5P_REGS_SROM_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_SROMREG(x)		(S5P_VA_SROMC + (x))
-
-#define S5P_SROM_BW		S5P_SROMREG(0x0)
-#define S5P_SROM_BC0		S5P_SROMREG(0x4)
-#define S5P_SROM_BC1		S5P_SROMREG(0x8)
-#define S5P_SROM_BC2		S5P_SROMREG(0xc)
-#define S5P_SROM_BC3		S5P_SROMREG(0x10)
-#define S5P_SROM_BC4		S5P_SROMREG(0x14)
-#define S5P_SROM_BC5		S5P_SROMREG(0x18)
-
-/* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */
-
-#define S5P_SROM_BW__DATAWIDTH__SHIFT		0
-#define S5P_SROM_BW__ADDRMODE__SHIFT		1
-#define S5P_SROM_BW__WAITENABLE__SHIFT		2
-#define S5P_SROM_BW__BYTEENABLE__SHIFT		3
-
-#define S5P_SROM_BW__CS_MASK			0xf
-
-#define S5P_SROM_BW__NCS0__SHIFT		0
-#define S5P_SROM_BW__NCS1__SHIFT		4
-#define S5P_SROM_BW__NCS2__SHIFT		8
-#define S5P_SROM_BW__NCS3__SHIFT		12
-#define S5P_SROM_BW__NCS4__SHIFT		16
-#define S5P_SROM_BW__NCS5__SHIFT		20
-
-/* applies to same to BCS0 - BCS3 */
-
-#define S5P_SROM_BCX__PMC__SHIFT		0
-#define S5P_SROM_BCX__TACP__SHIFT		4
-#define S5P_SROM_BCX__TCAH__SHIFT		8
-#define S5P_SROM_BCX__TCOH__SHIFT		12
-#define S5P_SROM_BCX__TACC__SHIFT		16
-#define S5P_SROM_BCX__TCOS__SHIFT		24
-#define S5P_SROM_BCX__TACS__SHIFT		28
-
-#endif /* __ASM_PLAT_S5P_REGS_SROM_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/reset.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/reset.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/reset.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/reset.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/reset.h
- *
- * 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.
-*/
-
-#ifndef __ASM_PLAT_S5P_RESET_H
-#define __ASM_PLAT_S5P_RESET_H __FILE__
-
-extern void (*s5p_reset_hook)(void);
-
-#endif /* __ASM_PLAT_S5P_RESET_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/s5p6440.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/s5p6440.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/s5p6440.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/s5p6440.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-/* arch/arm/plat-s5p/include/plat/s5p6440.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Header file for s5p6440 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 S5P6440 related SoCs */
-
-extern void s5p6440_register_clocks(void);
-extern void s5p6440_setup_clocks(void);
-
-#ifdef CONFIG_CPU_S5P6440
-
-extern  int s5p64x0_init(void);
-extern void s5p6440_init_irq(void);
-extern void s5p6440_map_io(void);
-extern void s5p6440_init_clocks(int xtal);
-
-extern void s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-#else
-#define s5p6440_init_clocks NULL
-#define s5p6440_init_uarts NULL
-#define s5p6440_map_io NULL
-#define s5p64x0_init NULL
-#endif
-
-/* S5P6440 timer */
-
-extern struct sys_timer s5p6440_timer;
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/s5p6450.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/s5p6450.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/s5p6450.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/s5p6450.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-/* arch/arm/plat-s5p/include/plat/s5p6450.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Header file for s5p6450 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 S5P6450 related SoCs */
-
-extern void s5p6450_register_clocks(void);
-extern void s5p6450_setup_clocks(void);
-
-#ifdef CONFIG_CPU_S5P6450
-
-extern  int s5p64x0_init(void);
-extern void s5p6450_init_irq(void);
-extern void s5p6450_map_io(void);
-extern void s5p6450_init_clocks(int xtal);
-
-extern void s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-#else
-#define s5p6450_init_clocks NULL
-#define s5p6450_init_uarts NULL
-#define s5p6450_map_io NULL
-#define s5p64x0_init NULL
-#endif
-
-/* S5P6450 timer */
-
-extern struct sys_timer s5p6450_timer;
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/s5pc100.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/s5pc100.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/s5pc100.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/s5pc100.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/* arch/arm/plat-s5p/include/plat/s5pc100.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Header file for s5pc100 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 S5PC100 related SoCs */
-
-extern void s5pc100_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-extern void s5pc100_register_clocks(void);
-extern void s5pc100_setup_clocks(void);
-
-#ifdef CONFIG_CPU_S5PC100
-
-extern  int s5pc100_init(void);
-extern void s5pc100_init_irq(void);
-extern void s5pc100_map_io(void);
-extern void s5pc100_init_clocks(int xtal);
-
-#define s5pc100_init_uarts s5pc100_common_init_uarts
-
-#else
-#define s5pc100_init_clocks NULL
-#define s5pc100_init_uarts NULL
-#define s5pc100_map_io NULL
-#define s5pc100_init NULL
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/s5p-clock.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/s5p-clock.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/s5p-clock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/s5p-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,55 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/s5p-clock.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Header file for s5p 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.
-*/
-
-#ifndef __ASM_PLAT_S5P_CLOCK_H
-#define __ASM_PLAT_S5P_CLOCK_H __FILE__
-
-#include <linux/clk.h>
-
-#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
-
-#define clk_fin_apll clk_ext_xtal_mux
-#define clk_fin_mpll clk_ext_xtal_mux
-#define clk_fin_epll clk_ext_xtal_mux
-#define clk_fin_dpll clk_ext_xtal_mux
-#define clk_fin_vpll clk_ext_xtal_mux
-#define clk_fin_hpll clk_ext_xtal_mux
-
-extern struct clk clk_ext_xtal_mux;
-extern struct clk clk_xusbxti;
-extern struct clk clk_48m;
-extern struct clk s5p_clk_27m;
-extern struct clk clk_fout_apll;
-extern struct clk clk_fout_mpll;
-extern struct clk clk_fout_epll;
-extern struct clk clk_fout_dpll;
-extern struct clk clk_fout_vpll;
-extern struct clk clk_arm;
-extern struct clk clk_vpll;
-
-extern struct clksrc_sources clk_src_apll;
-extern struct clksrc_sources clk_src_mpll;
-extern struct clksrc_sources clk_src_epll;
-extern struct clksrc_sources clk_src_dpll;
-
-extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);
-
-/* Common EPLL operations for S5P platform */
-extern int s5p_epll_enable(struct clk *clk, int enable);
-extern unsigned long s5p_epll_get_rate(struct clk *clk);
-
-/* SPDIF clk operations common for S5PC100/V210/C110 and Exynos4 */
-extern int s5p_spdif_set_rate(struct clk *clk, unsigned long rate);
-extern unsigned long s5p_spdif_get_rate(struct clk *clk);
-
-extern struct clk_ops s5p_sclk_spdif_ops;
-#endif /* __ASM_PLAT_S5P_CLOCK_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/s5p-time.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/s5p-time.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/s5p-time.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/s5p-time.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,40 +0,0 @@
-/* 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-3.1-gnu/arch/arm/plat-s5p/include/plat/s5pv210.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/s5pv210.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/s5pv210.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/s5pv210.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/s5pv210.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Header file for s5pv210 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 S5PV210 related SoCs */
-
-extern void s5pv210_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-extern void s5pv210_register_clocks(void);
-extern void s5pv210_setup_clocks(void);
-
-#ifdef CONFIG_CPU_S5PV210
-
-extern  int s5pv210_init(void);
-extern void s5pv210_init_irq(void);
-extern void s5pv210_map_io(void);
-extern void s5pv210_init_clocks(int xtal);
-
-#define s5pv210_init_uarts s5pv210_common_init_uarts
-
-#else
-#define s5pv210_init_clocks NULL
-#define s5pv210_init_uarts NULL
-#define s5pv210_map_io NULL
-#define s5pv210_init NULL
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/sysmmu.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/sysmmu.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/sysmmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/sysmmu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,95 +0,0 @@
-/* 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-3.1-gnu/arch/arm/plat-s5p/include/plat/system-reset.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/system-reset.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/system-reset.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/system-reset.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,31 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/system-reset.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Based on arch/arm/mach-s3c2410/include/mach/system-reset.h
- *
- * S5P - System define for arch_reset()
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <plat/watchdog-reset.h>
-
-void (*s5p_reset_hook)(void);
-
-static void arch_reset(char mode, const char *cmd)
-{
-	/* SWRESET support in s5p_reset_hook() */
-
-	if (s5p_reset_hook)
-		s5p_reset_hook();
-
-	/* Perform reset using Watchdog reset
-	 * if there is no s5p_reset_hook()
-	 */
-
-	arch_wdt_reset();
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/usb-phy.h linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/usb-phy.h
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/include/plat/usb-phy.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/include/plat/usb-phy.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#ifndef __PLAT_S5P_USB_PHY_H
-#define __PLAT_S5P_USB_PHY_H
-
-enum s5p_usb_phy_type {
-	S5P_USB_PHY_DEVICE,
-	S5P_USB_PHY_HOST,
-};
-
-extern int s5p_usb_phy_init(struct platform_device *pdev, int type);
-extern int s5p_usb_phy_exit(struct platform_device *pdev, int type);
-
-#endif /* __PLAT_S5P_REGS_USB_PHY_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/irq.c linux-libre-3.2-gnu/arch/arm/plat-s5p/irq.c
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,42 +17,10 @@
 
 #include <asm/hardware/vic.h>
 
-#include <linux/serial_core.h>
 #include <mach/map.h>
 #include <plat/regs-timer.h>
-#include <plat/regs-serial.h>
 #include <plat/cpu.h>
 #include <plat/irq-vic-timer.h>
-#include <plat/irq-uart.h>
-
-/*
- * Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
- * are consecutive when looking up the interrupt in the demux routines.
- */
-static struct s3c_uart_irq uart_irqs[] = {
-	[0] = {
-		.regs		= S5P_VA_UART0,
-		.base_irq	= IRQ_S5P_UART_BASE0,
-		.parent_irq	= IRQ_UART0,
-	},
-	[1] = {
-		.regs		= S5P_VA_UART1,
-		.base_irq	= IRQ_S5P_UART_BASE1,
-		.parent_irq	= IRQ_UART1,
-	},
-	[2] = {
-		.regs		= S5P_VA_UART2,
-		.base_irq	= IRQ_S5P_UART_BASE2,
-		.parent_irq	= IRQ_UART2,
-	},
-#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
-	[3] = {
-		.regs		= S5P_VA_UART3,
-		.base_irq	= IRQ_S5P_UART_BASE3,
-		.parent_irq	= IRQ_UART3,
-	},
-#endif
-};
 
 void __init s5p_init_irq(u32 *vic, u32 num_vic)
 {
@@ -65,6 +33,4 @@
 #endif
 
 	s3c_init_vic_timer_irq(5, IRQ_TIMER0);
-
-	s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));
 }
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/irq-gpioint.c linux-libre-3.2-gnu/arch/arm/plat-s5p/irq-gpioint.c
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/irq-gpioint.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/irq-gpioint.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,7 +37,7 @@
 	int			start;
 	int			nr_groups;
 	int			irq;
-	struct s3c_gpio_chip	**chips;
+	struct samsung_gpio_chip	**chips;
 	void			(*handler)(unsigned int, struct irq_desc *);
 };
 
@@ -87,7 +87,7 @@
 	chained_irq_enter(chip, desc);
 
 	for (group = 0; group < bank->nr_groups; group++) {
-		struct s3c_gpio_chip *chip = bank->chips[group];
+		struct samsung_gpio_chip *chip = bank->chips[group];
 		if (!chip)
 			continue;
 
@@ -110,7 +110,7 @@
 	chained_irq_exit(chip, desc);
 }
 
-static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
+static __init int s5p_gpioint_add(struct samsung_gpio_chip *chip)
 {
 	static int used_gpioint_groups = 0;
 	int group = chip->group;
@@ -131,7 +131,7 @@
 		return -EINVAL;
 
 	if (!bank->handler) {
-		bank->chips = kzalloc(sizeof(struct s3c_gpio_chip *) *
+		bank->chips = kzalloc(sizeof(struct samsung_gpio_chip *) *
 				      bank->nr_groups, GFP_KERNEL);
 		if (!bank->chips)
 			return -ENOMEM;
@@ -174,7 +174,7 @@
 
 int __init s5p_register_gpio_interrupt(int pin)
 {
-	struct s3c_gpio_chip *my_chip = s3c_gpiolib_getchip(pin);
+	struct samsung_gpio_chip *my_chip = samsung_gpiolib_getchip(pin);
 	int offset, group;
 	int ret;
 
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/Kconfig linux-libre-3.2-gnu/arch/arm/plat-s5p/Kconfig
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
 
 config PLAT_S5P
 	bool
-	depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS4)
+	depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
 	default y
 	select ARM_VIC if !ARCH_EXYNOS4
 	select ARM_GIC if ARCH_EXYNOS4
@@ -16,13 +16,9 @@
 	select S3C_GPIO_TRACK
 	select S5P_GPIO_DRVSTR
 	select SAMSUNG_GPIOLIB_4BIT
-	select S3C_GPIO_CFG_S3C64XX
-	select S3C_GPIO_PULL_UPDOWN
-	select S3C_GPIO_CFG_S3C24XX
 	select PLAT_SAMSUNG
 	select SAMSUNG_CLKSRC
 	select SAMSUNG_IRQ_VIC_TIMER
-	select SAMSUNG_IRQ_UART
 	help
 	  Base platform code for Samsung's S5P series SoC.
 
@@ -43,6 +39,12 @@
 	help
 	  Use the High Resolution timer support
 
+config S5P_PM
+	bool
+	help
+	  Common code for power management support on S5P and newer SoCs
+	  Note: Do not select this for S5P6440 and S5P6450.
+
 comment "System MMU"
 
 config S5P_SYSTEM_MMU
@@ -51,6 +53,12 @@
 	help
 	  Say Y here if you want to enable System MMU
 
+config S5P_SLEEP
+	bool
+	help
+	  Internal config node to apply common S5P sleep management code.
+	  Can be selected by S5P and newer SoCs with similar sleep procedure.
+
 config S5P_DEV_FIMC0
 	bool
 	help
@@ -76,6 +84,11 @@
 	help
 	  Compile in platform device definitions for FIMD controller 0
 
+config S5P_DEV_I2C_HDMIPHY
+	bool
+	help
+	  Compile in platform device definitions for I2C HDMIPHY controller
+
 config S5P_DEV_MFC
 	bool
 	help
@@ -96,6 +109,11 @@
 	help
 	  Compile in platform device definitions for MIPI-CSIS channel 1
 
+config S5P_DEV_TV
+	bool
+	help
+	  Compile in platform device definition for TV interface
+
 config S5P_DEV_USB_EHCI
 	bool
 	help
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/Makefile linux-libre-3.2-gnu/arch/arm/plat-s5p/Makefile
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,6 @@
 
 # Core files
 
-obj-y				+= dev-pmu.o
 obj-y				+= dev-uart.o
 obj-y				+= cpu.o
 obj-y				+= clock.o
@@ -20,19 +19,10 @@
 obj-$(CONFIG_S5P_EXT_INT)	+= irq-eint.o
 obj-$(CONFIG_S5P_GPIO_INT)	+= irq-gpioint.o
 obj-$(CONFIG_S5P_SYSTEM_MMU)	+= sysmmu.o
-obj-$(CONFIG_PM)		+= pm.o
-obj-$(CONFIG_PM)		+= irq-pm.o
+obj-$(CONFIG_S5P_PM)		+= pm.o irq-pm.o
+obj-$(CONFIG_S5P_SLEEP)		+= sleep.o
 obj-$(CONFIG_S5P_HRT) 		+= s5p-time.o
 
 # devices
 obj-$(CONFIG_S5P_DEV_MFC)	+= dev-mfc.o
-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_FIMD0)	+= dev-fimd0.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_DEV_USB_EHCI)	+= dev-ehci.o
 obj-$(CONFIG_S5P_SETUP_MIPIPHY)	+= setup-mipiphy.o
diff -druN linux-libre-3.1-gnu/arch/arm/plat-s5p/sleep.S linux-libre-3.2-gnu/arch/arm/plat-s5p/sleep.S
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/sleep.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/sleep.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,49 @@
+/* linux/arch/arm/plat-s5p/sleep.S
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Common S5P Sleep Code
+ * Based on S3C64XX sleep code by:
+ *	Ben Dooks, (c) 2008 Simtec Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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>
+
+	.text
+
+	/*
+	 * 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-3.1-gnu/arch/arm/plat-s5p/sysmmu.c linux-libre-3.2-gnu/arch/arm/plat-s5p/sysmmu.c
--- linux-libre-3.1-gnu/arch/arm/plat-s5p/sysmmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-s5p/sysmmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/export.h>
 
 #include <asm/pgtable.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/adc.c linux-libre-3.2-gnu/arch/arm/plat-samsung/adc.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/adc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/adc.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,8 @@
 
 enum s3c_cpu_type {
 	TYPE_ADCV1, /* S3C24XX */
+	TYPE_ADCV11, /* S3C2443 */
+	TYPE_ADCV12, /* S3C2416, S3C2450 */
 	TYPE_ADCV2, /* S3C64XX, S5P64X0, S5PC100 */
 	TYPE_ADCV3, /* S5PV210, S5PC110, EXYNOS4210 */
 };
@@ -98,13 +100,17 @@
 
 	client->select_cb(client, 1);
 
-	con &= ~S3C2410_ADCCON_MUXMASK;
+	if (cpu == TYPE_ADCV1 || cpu == TYPE_ADCV2)
+		con &= ~S3C2410_ADCCON_MUXMASK;
 	con &= ~S3C2410_ADCCON_STDBM;
 	con &= ~S3C2410_ADCCON_STARTMASK;
 
 	if (!client->is_ts) {
 		if (cpu == TYPE_ADCV3)
 			writel(client->channel & 0xf, adc->regs + S5P_ADCMUX);
+		else if (cpu == TYPE_ADCV11 || cpu == TYPE_ADCV12)
+			writel(client->channel & 0xf,
+						adc->regs + S3C2443_ADCMUX);
 		else
 			con |= S3C2410_ADCCON_SELMUX(client->channel);
 	}
@@ -293,13 +299,13 @@
 
 	client->nr_samples--;
 
-	if (cpu != TYPE_ADCV1) {
-		/* S3C64XX/S5P ADC resolution is 12-bit */
-		data0 &= 0xfff;
-		data1 &= 0xfff;
-	} else {
+	if (cpu == TYPE_ADCV1 || cpu == TYPE_ADCV11) {
 		data0 &= 0x3ff;
 		data1 &= 0x3ff;
+	} else {
+		/* S3C2416/S3C64XX/S5P ADC resolution is 12-bit */
+		data0 &= 0xfff;
+		data1 &= 0xfff;
 	}
 
 	if (client->convert_cb)
@@ -320,7 +326,7 @@
 	}
 
 exit:
-	if (cpu != TYPE_ADCV1) {
+	if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3) {
 		/* Clear ADC interrupt */
 		writel(0, adc->regs + S3C64XX_ADCCLRINT);
 	}
@@ -332,6 +338,7 @@
 	struct device *dev = &pdev->dev;
 	struct adc_device *adc;
 	struct resource *regs;
+	enum s3c_cpu_type cpu = platform_get_device_id(pdev)->driver_data;
 	int ret;
 	unsigned tmp;
 
@@ -394,10 +401,13 @@
 	clk_enable(adc->clk);
 
 	tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
-	if (platform_get_device_id(pdev)->driver_data != TYPE_ADCV1) {
-		/* Enable 12-bit ADC resolution */
+
+	/* Enable 12-bit ADC resolution */
+	if (cpu == TYPE_ADCV12)
+		tmp |= S3C2416_ADCCON_RESSEL;
+	if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3)
 		tmp |= S3C64XX_ADCCON_RESSEL;
-	}
+
 	writel(tmp, adc->regs + S3C2410_ADCCON);
 
 	dev_info(dev, "attached adc driver\n");
@@ -464,6 +474,7 @@
 	struct platform_device *pdev = container_of(dev,
 			struct platform_device, dev);
 	struct adc_device *adc = platform_get_drvdata(pdev);
+	enum s3c_cpu_type cpu = platform_get_device_id(pdev)->driver_data;
 	int ret;
 	unsigned long tmp;
 
@@ -474,9 +485,13 @@
 	enable_irq(adc->irq);
 
 	tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
+
 	/* Enable 12-bit ADC resolution */
-	if (platform_get_device_id(pdev)->driver_data != TYPE_ADCV1)
+	if (cpu == TYPE_ADCV12)
+		tmp |= S3C2416_ADCCON_RESSEL;
+	if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3)
 		tmp |= S3C64XX_ADCCON_RESSEL;
+
 	writel(tmp, adc->regs + S3C2410_ADCCON);
 
 	return 0;
@@ -492,6 +507,12 @@
 		.name           = "s3c24xx-adc",
 		.driver_data    = TYPE_ADCV1,
 	}, {
+		.name		= "s3c2443-adc",
+		.driver_data	= TYPE_ADCV11,
+	}, {
+		.name		= "s3c2416-adc",
+		.driver_data	= TYPE_ADCV12,
+	}, {
 		.name           = "s3c64xx-adc",
 		.driver_data    = TYPE_ADCV2,
 	}, {
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/cpu.c linux-libre-3.2-gnu/arch/arm/plat-samsung/cpu.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/cpu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,58 @@
+/* linux/arch/arm/plat-samsung/cpu.c
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung 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.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+
+#include <mach/map.h>
+#include <plat/cpu.h>
+
+unsigned long samsung_cpu_id;
+static unsigned int samsung_cpu_rev;
+
+unsigned int samsung_rev(void)
+{
+	return samsung_cpu_rev;
+}
+EXPORT_SYMBOL(samsung_rev);
+
+void __init s3c24xx_init_cpu(void)
+{
+	/* nothing here yet */
+
+	samsung_cpu_rev = 0;
+}
+
+void __init s3c64xx_init_cpu(void)
+{
+	samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0x118);
+	if (!samsung_cpu_id) {
+		/*
+		 * S3C6400 has the ID register in a different place,
+		 * and needs a write before it can be read.
+		 */
+		__raw_writel(0x0, S3C_VA_SYS + 0xA1C);
+		samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0xA1C);
+	}
+
+	samsung_cpu_rev = 0;
+}
+
+void __init s5p_init_cpu(void __iomem *cpuid_addr)
+{
+	samsung_cpu_id = __raw_readl(cpuid_addr);
+	samsung_cpu_rev = samsung_cpu_id & 0xFF;
+}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-adc.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-adc.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-adc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-adc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-adc.c
- *
- * Copyright 2010 Maurus Cuelenaere
- *
- * S3C64xx series device definition for ADC 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/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/adc.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_adc_resource[] = {
-	[0] = {
-		.start = SAMSUNG_PA_ADC,
-		.end   = SAMSUNG_PA_ADC + SZ_256 - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_TC,
-		.end   = IRQ_TC,
-		.flags = IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start = IRQ_ADC,
-		.end   = IRQ_ADC,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_adc = {
-	.name		= "samsung-adc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s3c_adc_resource),
-	.resource	= s3c_adc_resource,
-};
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-asocdma.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-asocdma.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-asocdma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-asocdma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-asocdma.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 <plat/devs.h>
-
-static u64 audio_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device samsung_asoc_dma = {
-	.name		  = "samsung-audio",
-	.id		  = -1,
-	.dev              = {
-		.dma_mask = &audio_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	}
-};
-EXPORT_SYMBOL(samsung_asoc_dma);
-
-struct platform_device samsung_asoc_idma = {
-	.name		= "samsung-idma",
-	.id		= -1,
-	.dev		= {
-		.dma_mask		= &audio_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	}
-};
-EXPORT_SYMBOL(samsung_asoc_idma);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-backlight.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-backlight.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-backlight.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-backlight.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/pwm_backlight.h>
 
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-fb.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-fb.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-fb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-fb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,63 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-fb.c
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for framebuffer 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/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-#include <linux/fb.h>
-#include <linux/gfp.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/fb.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_fb_resource[] = {
-	[0] = {
-		.start = S3C_PA_FB,
-		.end   = S3C_PA_FB + SZ_16K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_LCD_VSYNC,
-		.end   = IRQ_LCD_VSYNC,
-		.flags = IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start = IRQ_LCD_FIFO,
-		.end   = IRQ_LCD_FIFO,
-		.flags = IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start = IRQ_LCD_SYSTEM,
-		.end   = IRQ_LCD_SYSTEM,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_fb = {
-	.name		  = "s3c-fb",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_fb_resource),
-	.resource	  = s3c_fb_resource,
-	.dev.dma_mask	  = &s3c_device_fb.dev.coherent_dma_mask,
-	.dev.coherent_dma_mask = 0xffffffffUL,
-};
-
-void __init s3c_fb_set_platdata(struct s3c_fb_platdata *pd)
-{
-	s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
-			 &s3c_device_fb);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-hsmmc1.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-hsmmc1.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-hsmmc1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-hsmmc1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,79 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-hsmmc1.c
- *
- * Copyright (c) 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for hsmmc device 1
- *
- * This program is free software; you can 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/mmc/host.h>
-
-#include <mach/map.h>
-#include <plat/sdhci.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-#define S3C_SZ_HSMMC	(0x1000)
-
-static struct resource s3c_hsmmc1_resource[] = {
-	[0] = {
-		.start = S3C_PA_HSMMC1,
-		.end   = S3C_PA_HSMMC1 + S3C_SZ_HSMMC - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_HSMMC1,
-		.end   = IRQ_HSMMC1,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static u64 s3c_device_hsmmc1_dmamask = 0xffffffffUL;
-
-struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata = {
-	.max_width	= 4,
-	.host_caps	= (MMC_CAP_4_BIT_DATA |
-			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
-};
-
-struct platform_device s3c_device_hsmmc1 = {
-	.name		= "s3c-sdhci",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s3c_hsmmc1_resource),
-	.resource	= s3c_hsmmc1_resource,
-	.dev		= {
-		.dma_mask		= &s3c_device_hsmmc1_dmamask,
-		.coherent_dma_mask	= 0xffffffffUL,
-		.platform_data		= &s3c_hsmmc1_def_platdata,
-	},
-};
-
-void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd)
-{
-	struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata;
-
-	set->cd_type = pd->cd_type;
-	set->ext_cd_init = pd->ext_cd_init;
-	set->ext_cd_cleanup = pd->ext_cd_cleanup;
-	set->ext_cd_gpio = pd->ext_cd_gpio;
-	set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
-
-	if (pd->max_width)
-		set->max_width = pd->max_width;
-	if (pd->cfg_gpio)
-		set->cfg_gpio = pd->cfg_gpio;
-	if (pd->cfg_card)
-		set->cfg_card = pd->cfg_card;
-	if (pd->host_caps)
-		set->host_caps |= pd->host_caps;
-	if (pd->clk_type)
-		set->clk_type = pd->clk_type;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-hsmmc2.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-hsmmc2.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-hsmmc2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-hsmmc2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,80 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-hsmmc2.c
- *
- * Copyright (c) 2009 Samsung Electronics
- * Copyright (c) 2009 Maurus Cuelenaere
- *
- * Based on arch/arm/plat-s3c/dev-hsmmc1.c
- * original file Copyright (c) 2008 Simtec Electronics
- *
- * S3C series device definition for hsmmc device 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/platform_device.h>
-#include <linux/mmc/host.h>
-
-#include <mach/map.h>
-#include <plat/sdhci.h>
-#include <plat/devs.h>
-
-#define S3C_SZ_HSMMC	(0x1000)
-
-static struct resource s3c_hsmmc2_resource[] = {
-	[0] = {
-		.start = S3C_PA_HSMMC2,
-		.end   = S3C_PA_HSMMC2 + S3C_SZ_HSMMC - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_HSMMC2,
-		.end   = IRQ_HSMMC2,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static u64 s3c_device_hsmmc2_dmamask = 0xffffffffUL;
-
-struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata = {
-	.max_width	= 4,
-	.host_caps	= (MMC_CAP_4_BIT_DATA |
-			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
-};
-
-struct platform_device s3c_device_hsmmc2 = {
-	.name		= "s3c-sdhci",
-	.id		= 2,
-	.num_resources	= ARRAY_SIZE(s3c_hsmmc2_resource),
-	.resource	= s3c_hsmmc2_resource,
-	.dev		= {
-		.dma_mask		= &s3c_device_hsmmc2_dmamask,
-		.coherent_dma_mask	= 0xffffffffUL,
-		.platform_data		= &s3c_hsmmc2_def_platdata,
-	},
-};
-
-void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd)
-{
-	struct s3c_sdhci_platdata *set = &s3c_hsmmc2_def_platdata;
-
-	set->cd_type = pd->cd_type;
-	set->ext_cd_init = pd->ext_cd_init;
-	set->ext_cd_cleanup = pd->ext_cd_cleanup;
-	set->ext_cd_gpio = pd->ext_cd_gpio;
-	set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
-
-	if (pd->max_width)
-		set->max_width = pd->max_width;
-	if (pd->cfg_gpio)
-		set->cfg_gpio = pd->cfg_gpio;
-	if (pd->cfg_card)
-		set->cfg_card = pd->cfg_card;
-	if (pd->host_caps)
-		set->host_caps |= pd->host_caps;
-	if (pd->clk_type)
-		set->clk_type = pd->clk_type;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-hsmmc3.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-hsmmc3.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-hsmmc3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-hsmmc3.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-hsmmc3.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright (c) 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * Based on arch/arm/plat-samsung/dev-hsmmc1.c
- *
- * Samsung device definition for hsmmc device 3
- *
- * This program is free software; you can 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/mmc/host.h>
-
-#include <mach/map.h>
-#include <plat/sdhci.h>
-#include <plat/devs.h>
-
-#define S3C_SZ_HSMMC	(0x1000)
-
-static struct resource s3c_hsmmc3_resource[] = {
-	[0] = {
-		.start	= S3C_PA_HSMMC3,
-		.end	= S3C_PA_HSMMC3 + S3C_SZ_HSMMC - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_HSMMC3,
-		.end	= IRQ_HSMMC3,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static u64 s3c_device_hsmmc3_dmamask = 0xffffffffUL;
-
-struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata = {
-	.max_width	= 4,
-	.host_caps	= (MMC_CAP_4_BIT_DATA |
-			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
-};
-
-struct platform_device s3c_device_hsmmc3 = {
-	.name		= "s3c-sdhci",
-	.id		= 3,
-	.num_resources	= ARRAY_SIZE(s3c_hsmmc3_resource),
-	.resource	= s3c_hsmmc3_resource,
-	.dev		= {
-		.dma_mask		= &s3c_device_hsmmc3_dmamask,
-		.coherent_dma_mask	= 0xffffffffUL,
-		.platform_data		= &s3c_hsmmc3_def_platdata,
-	},
-};
-
-void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd)
-{
-	struct s3c_sdhci_platdata *set = &s3c_hsmmc3_def_platdata;
-
-	set->cd_type = pd->cd_type;
-	set->ext_cd_init = pd->ext_cd_init;
-	set->ext_cd_cleanup = pd->ext_cd_cleanup;
-	set->ext_cd_gpio = pd->ext_cd_gpio;
-	set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
-
-	if (pd->max_width)
-		set->max_width = pd->max_width;
-	if (pd->cfg_gpio)
-		set->cfg_gpio = pd->cfg_gpio;
-	if (pd->cfg_card)
-		set->cfg_card = pd->cfg_card;
-	if (pd->host_caps)
-		set->host_caps |= pd->host_caps;
-	if (pd->clk_type)
-		set->clk_type = pd->clk_type;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-hsmmc.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-hsmmc.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-hsmmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-hsmmc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,79 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-hsmmc.c
- *
- * Copyright (c) 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for hsmmc devices
- *
- * This program is free software; you can 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/mmc/host.h>
-
-#include <mach/map.h>
-#include <plat/sdhci.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-#define S3C_SZ_HSMMC	(0x1000)
-
-static struct resource s3c_hsmmc_resource[] = {
-	[0] = {
-		.start = S3C_PA_HSMMC0,
-		.end   = S3C_PA_HSMMC0 + S3C_SZ_HSMMC - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_HSMMC0,
-		.end   = IRQ_HSMMC0,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static u64 s3c_device_hsmmc_dmamask = 0xffffffffUL;
-
-struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata = {
-	.max_width	= 4,
-	.host_caps	= (MMC_CAP_4_BIT_DATA |
-			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
-};
-
-struct platform_device s3c_device_hsmmc0 = {
-	.name		= "s3c-sdhci",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s3c_hsmmc_resource),
-	.resource	= s3c_hsmmc_resource,
-	.dev		= {
-		.dma_mask		= &s3c_device_hsmmc_dmamask,
-		.coherent_dma_mask	= 0xffffffffUL,
-		.platform_data		= &s3c_hsmmc0_def_platdata,
-	},
-};
-
-void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd)
-{
-	struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata;
-
-	set->cd_type = pd->cd_type;
-	set->ext_cd_init = pd->ext_cd_init;
-	set->ext_cd_cleanup = pd->ext_cd_cleanup;
-	set->ext_cd_gpio = pd->ext_cd_gpio;
-	set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
-
-	if (pd->max_width)
-		set->max_width = pd->max_width;
-	if (pd->cfg_gpio)
-		set->cfg_gpio = pd->cfg_gpio;
-	if (pd->cfg_card)
-		set->cfg_card = pd->cfg_card;
-	if (pd->host_caps)
-		set->host_caps |= pd->host_caps;
-	if (pd->clk_type)
-		set->clk_type = pd->clk_type;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-hwmon.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-hwmon.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-hwmon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-hwmon.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-hwmon.c
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * Adapted for HWMON by Maurus Cuelenaere
- *
- * Samsung series device definition for HWMON
- *
- * This program is free software; you can 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 <plat/devs.h>
-#include <plat/hwmon.h>
-
-struct platform_device s3c_device_hwmon = {
-	.name		= "s3c-hwmon",
-	.id		= -1,
-	.dev.parent	= &s3c_device_adc.dev,
-};
-
-void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd)
-{
-	s3c_set_platdata(pd, sizeof(struct s3c_hwmon_pdata),
-			 &s3c_device_hwmon);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-i2c0.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-i2c0.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-i2c0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-i2c0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-i2c0.c
- *
- * Copyright 2008-2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for i2c device 0
- *
- * This program is free software; you can 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/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start = S3C_PA_IIC,
-		.end   = S3C_PA_IIC + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_IIC,
-		.end   = IRQ_IIC,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_i2c0 = {
-	.name		  = "s3c2410-i2c",
-#ifdef CONFIG_S3C_DEV_I2C1
-	.id		  = 0,
-#else
-	.id		  = -1,
-#endif
-	.num_resources	  = ARRAY_SIZE(s3c_i2c_resource),
-	.resource	  = s3c_i2c_resource,
-};
-
-struct s3c2410_platform_i2c default_i2c_data __initdata = {
-	.flags		= 0,
-	.slave_addr	= 0x10,
-	.frequency	= 100*1000,
-	.sda_delay	= 100,
-};
-
-void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd)
-		pd = &default_i2c_data;
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s3c_device_i2c0);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c0_cfg_gpio;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-i2c1.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-i2c1.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-i2c1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-i2c1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-i2c1.c
- *
- * Copyright 2008-2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for i2c device 1
- *
- * This program is free software; you can 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/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start = S3C_PA_IIC1,
-		.end   = S3C_PA_IIC1 + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_IIC1,
-		.end   = IRQ_IIC1,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_i2c1 = {
-	.name		  = "s3c2410-i2c",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s3c_i2c_resource),
-	.resource	  = s3c_i2c_resource,
-};
-
-void __init s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd) {
-		pd = &default_i2c_data;
-		pd->bus_num = 1;
-	}
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s3c_device_i2c1);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c1_cfg_gpio;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-i2c2.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-i2c2.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-i2c2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-i2c2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,62 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-i2c2.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S3C series device definition for i2c device 2
- *
- * Based on plat-samsung/dev-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.
-*/
-
-#include <linux/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start = S3C_PA_IIC2,
-		.end   = S3C_PA_IIC2 + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_IIC2,
-		.end   = IRQ_IIC2,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_i2c2 = {
-	.name		  = "s3c2410-i2c",
-	.id		  = 2,
-	.num_resources	  = ARRAY_SIZE(s3c_i2c_resource),
-	.resource	  = s3c_i2c_resource,
-};
-
-void __init s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd) {
-		pd = &default_i2c_data;
-		pd->bus_num = 2;
-	}
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s3c_device_i2c2);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c2_cfg_gpio;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-i2c3.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-i2c3.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-i2c3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-i2c3.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-i2c3.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P series device definition for i2c device 3
- *
- * This program is free software; you can 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/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start	= S3C_PA_IIC3,
-		.end	= S3C_PA_IIC3 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_IIC3,
-		.end	= IRQ_IIC3,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_i2c3 = {
-	.name		= "s3c2440-i2c",
-	.id		= 3,
-	.num_resources	= ARRAY_SIZE(s3c_i2c_resource),
-	.resource	= s3c_i2c_resource,
-};
-
-void __init s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd) {
-		pd = &default_i2c_data;
-		pd->bus_num = 3;
-	}
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s3c_device_i2c3);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c3_cfg_gpio;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-i2c4.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-i2c4.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-i2c4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-i2c4.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-i2c4.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P series device definition for i2c device 3
- *
- * This program is free software; you can 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/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start	= S3C_PA_IIC4,
-		.end	= S3C_PA_IIC4 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_IIC4,
-		.end	= IRQ_IIC4,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_i2c4 = {
-	.name		= "s3c2440-i2c",
-	.id		= 4,
-	.num_resources	= ARRAY_SIZE(s3c_i2c_resource),
-	.resource	= s3c_i2c_resource,
-};
-
-void __init s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd) {
-		pd = &default_i2c_data;
-		pd->bus_num = 4;
-	}
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s3c_device_i2c4);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c4_cfg_gpio;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-i2c5.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-i2c5.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-i2c5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-i2c5.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-i2c3.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P series device definition for i2c device 3
- *
- * This program is free software; you can 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/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start	= S3C_PA_IIC5,
-		.end	= S3C_PA_IIC5 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_IIC5,
-		.end	= IRQ_IIC5,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_i2c5 = {
-	.name		= "s3c2440-i2c",
-	.id		= 5,
-	.num_resources	= ARRAY_SIZE(s3c_i2c_resource),
-	.resource	= s3c_i2c_resource,
-};
-
-void __init s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd) {
-		pd = &default_i2c_data;
-		pd->bus_num = 5;
-	}
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s3c_device_i2c5);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c5_cfg_gpio;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-i2c6.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-i2c6.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-i2c6.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-i2c6.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-i2c6.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P series device definition for i2c device 6
- *
- * This program is free software; you can 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/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start	= S3C_PA_IIC6,
-		.end	= S3C_PA_IIC6 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_IIC6,
-		.end	= IRQ_IIC6,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_i2c6 = {
-	.name		= "s3c2440-i2c",
-	.id		= 6,
-	.num_resources	= ARRAY_SIZE(s3c_i2c_resource),
-	.resource	= s3c_i2c_resource,
-};
-
-void __init s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd) {
-		pd = &default_i2c_data;
-		pd->bus_num = 6;
-	}
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s3c_device_i2c6);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c6_cfg_gpio;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-i2c7.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-i2c7.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-i2c7.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-i2c7.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-i2c7.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P series device definition for i2c device 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-	[0] = {
-		.start	= S3C_PA_IIC7,
-		.end	= S3C_PA_IIC7 + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_IIC7,
-		.end	= IRQ_IIC7,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_i2c7 = {
-	.name		= "s3c2440-i2c",
-	.id		= 7,
-	.num_resources	= ARRAY_SIZE(s3c_i2c_resource),
-	.resource	= s3c_i2c_resource,
-};
-
-void __init s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-	struct s3c2410_platform_i2c *npd;
-
-	if (!pd) {
-		pd = &default_i2c_data;
-		pd->bus_num = 7;
-	}
-
-	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-			       &s3c_device_i2c7);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c7_cfg_gpio;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-ide.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-ide.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-ide.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-ide.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-ide.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Samsung CF-ATA device 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.
-*/
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-
-#include <mach/map.h>
-#include <plat/ata.h>
-#include <plat/devs.h>
-
-static struct resource s3c_cfcon_resource[] = {
-	[0] = {
-		.start	= SAMSUNG_PA_CFCON,
-		.end	= SAMSUNG_PA_CFCON + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_CFCON,
-		.end	= IRQ_CFCON,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_cfcon = {
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s3c_cfcon_resource),
-	.resource	= s3c_cfcon_resource,
-};
-
-void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata)
-{
-	s3c_set_platdata(pdata, sizeof(struct s3c_ide_platdata),
-			 &s3c_device_cfcon);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-keypad.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-keypad.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-keypad.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/*
- * linux/arch/arm/plat-samsung/dev-keypad.c
- *
- * 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/platform_device.h>
-#include <mach/irqs.h>
-#include <mach/map.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/keypad.h>
-
-static struct resource samsung_keypad_resources[] = {
-	[0] = {
-		.start	= SAMSUNG_PA_KEYPAD,
-		.end	= SAMSUNG_PA_KEYPAD + 0x20 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_KEYPAD,
-		.end	= IRQ_KEYPAD,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device samsung_device_keypad = {
-	.name		= "samsung-keypad",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(samsung_keypad_resources),
-	.resource	= samsung_keypad_resources,
-};
-
-void __init samsung_keypad_set_platdata(struct samsung_keypad_platdata *pd)
-{
-	struct samsung_keypad_platdata *npd;
-
-	npd = s3c_set_platdata(pd, sizeof(struct samsung_keypad_platdata),
-			&samsung_device_keypad);
-
-	if (!npd->cfg_gpio)
-		npd->cfg_gpio = samsung_keypad_cfg_gpio;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-nand.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-nand.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-nand.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,125 +0,0 @@
-/*
- * S3C series device definition for nand 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-
-#include <mach/map.h>
-#include <plat/devs.h>
-#include <plat/nand.h>
-
-static struct resource s3c_nand_resource[] = {
-	[0] = {
-		.start = S3C_PA_NAND,
-		.end   = S3C_PA_NAND + SZ_1M,
-		.flags = IORESOURCE_MEM,
-	}
-};
-
-struct platform_device s3c_device_nand = {
-	.name		  = "s3c2410-nand",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_nand_resource),
-	.resource	  = s3c_nand_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_nand);
-
-/**
- * s3c_nand_copy_set() - copy nand set data
- * @set: The new structure, directly copied from the old.
- *
- * Copy all the fields from the NAND set field from what is probably __initdata
- * to new kernel memory. The code returns 0 if the copy happened correctly or
- * an error code for the calling function to display.
- *
- * Note, we currently do not try and look to see if we've already copied the
- * data in a previous set.
- */
-static int __init s3c_nand_copy_set(struct s3c2410_nand_set *set)
-{
-	void *ptr;
-	int size;
-
-	size = sizeof(struct mtd_partition) * set->nr_partitions;
-	if (size) {
-		ptr = kmemdup(set->partitions, size, GFP_KERNEL);
-		set->partitions = ptr;
-
-		if (!ptr)
-			return -ENOMEM;
-	}
-	
-	if (set->nr_map && set->nr_chips) {
-		size = sizeof(int) * set->nr_chips;
-		ptr = kmemdup(set->nr_map, size, GFP_KERNEL);
-		set->nr_map = ptr;
-
-		if (!ptr)
-			return -ENOMEM;
-	}
-
-	if (set->ecc_layout) {
-		ptr = kmemdup(set->ecc_layout,
-			      sizeof(struct nand_ecclayout), GFP_KERNEL);
-		set->ecc_layout = ptr;
-
-		if (!ptr)
-			return -ENOMEM;
-	}
-	
-	return 0;
-}
-
-void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
-{
-	struct s3c2410_platform_nand *npd;
-	int size;
-	int ret;
-
-	/* note, if we get a failure in allocation, we simply drop out of the
-	 * function. If there is so little memory available at initialisation
-	 * time then there is little chance the system is going to run.
-	 */ 
-
-	npd = s3c_set_platdata(nand, sizeof(struct s3c2410_platform_nand),
-				&s3c_device_nand);
-	if (!npd)
-		return;
-
-	/* now see if we need to copy any of the nand set data */
-
-	size = sizeof(struct s3c2410_nand_set) * npd->nr_sets;
-	if (size) {
-		struct s3c2410_nand_set *from = npd->sets;
-		struct s3c2410_nand_set *to;
-		int i;
-
-		to = kmemdup(from, size, GFP_KERNEL);
-		npd->sets = to;	/* set, even if we failed */
-
-		if (!to) {
-			printk(KERN_ERR "%s: no memory for sets\n", __func__);
-			return;
-		}
-		
-		for (i = 0; i < npd->nr_sets; i++) {
-			ret = s3c_nand_copy_set(to);
-			if (ret) {
-				printk(KERN_ERR "%s: failed to copy set %d\n",
-				__func__, i);
-				return;
-			}
-			to++;
-		}
-	}
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-onenand.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-onenand.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-onenand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-onenand.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/*
- * linux/arch/arm/plat-samsung/dev-onenand.c
- *
- *  Copyright (c) 2008-2010 Samsung Electronics
- *  Kyungmin Park <kyungmin.park@samsung.com>
- *
- * S3C64XX/S5PC100 series device definition for OneNAND devices
- *
- * This program is free software; you can 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 <mach/map.h>
-
-static struct resource s3c_onenand_resources[] = {
-	[0] = {
-		.start	= S3C_PA_ONENAND,
-		.end	= S3C_PA_ONENAND + 0x400 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= S3C_PA_ONENAND_BUF,
-		.end	= S3C_PA_ONENAND_BUF + S3C_SZ_ONENAND_BUF - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= IRQ_ONENAND,
-		.end	= IRQ_ONENAND,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_onenand = {
-	.name		= "samsung-onenand",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s3c_onenand_resources),
-	.resource	= s3c_onenand_resources,
-};
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-pwm.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-pwm.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-pwm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-pwm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-/* 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-3.1-gnu/arch/arm/plat-samsung/dev-rtc.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-rtc.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-rtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-rtc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-rtc.c
- *
- * Copyright 2009 by Maurus Cuelenaere <mcuelenaere@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-
-static struct resource s3c_rtc_resource[] = {
-	[0] = {
-		.start	= S3C_PA_RTC,
-		.end	= S3C_PA_RTC + 0xff,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_RTC_ALARM,
-		.end	= IRQ_RTC_ALARM,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_RTC_TIC,
-		.end	= IRQ_RTC_TIC,
-		.flags	= IORESOURCE_IRQ
-	}
-};
-
-struct platform_device s3c_device_rtc = {
-	.name		= "s3c64xx-rtc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s3c_rtc_resource),
-	.resource	= s3c_rtc_resource,
-};
-EXPORT_SYMBOL(s3c_device_rtc);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/devs.c linux-libre-3.2-gnu/arch/arm/plat-samsung/devs.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/devs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/devs.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1463 @@
+/* linux/arch/arm/plat-samsung/devs.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Base SAMSUNG platform 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/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/gfp.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mmc/host.h>
+#include <linux/ioport.h>
+
+#include <asm/irq.h>
+#include <asm/pmu.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/dma.h>
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/adc.h>
+#include <plat/ata.h>
+#include <plat/ehci.h>
+#include <plat/fb.h>
+#include <plat/fb-s3c2410.h>
+#include <plat/hwmon.h>
+#include <plat/iic.h>
+#include <plat/keypad.h>
+#include <plat/mci.h>
+#include <plat/nand.h>
+#include <plat/sdhci.h>
+#include <plat/ts.h>
+#include <plat/udc.h>
+#include <plat/usb-control.h>
+#include <plat/usb-phy.h>
+#include <plat/regs-iic.h>
+#include <plat/regs-serial.h>
+#include <plat/regs-spi.h>
+
+static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
+
+/* AC97 */
+#ifdef CONFIG_CPU_S3C2440
+static struct resource s3c_ac97_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C2440_PA_AC97, S3C2440_SZ_AC97),
+	[1] = DEFINE_RES_IRQ(IRQ_S3C244X_AC97),
+	[2] = DEFINE_RES_DMA_NAMED(DMACH_PCM_OUT, "PCM out"),
+	[3] = DEFINE_RES_DMA_NAMED(DMACH_PCM_IN, "PCM in"),
+	[4] = DEFINE_RES_DMA_NAMED(DMACH_MIC_IN, "Mic in"),
+};
+
+struct platform_device s3c_device_ac97 = {
+	.name		= "samsung-ac97",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_ac97_resource),
+	.resource	= s3c_ac97_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+#endif /* CONFIG_CPU_S3C2440 */
+
+/* ADC */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_adc_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_ADC, S3C24XX_SZ_ADC),
+	[1] = DEFINE_RES_IRQ(IRQ_TC),
+	[2] = DEFINE_RES_IRQ(IRQ_ADC),
+};
+
+struct platform_device s3c_device_adc = {
+	.name		= "s3c24xx-adc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_adc_resource),
+	.resource	= s3c_adc_resource,
+};
+#endif /* CONFIG_PLAT_S3C24XX */
+
+#if defined(CONFIG_SAMSUNG_DEV_ADC)
+static struct resource s3c_adc_resource[] = {
+	[0] = DEFINE_RES_MEM(SAMSUNG_PA_ADC, SZ_256),
+	[1] = DEFINE_RES_IRQ(IRQ_TC),
+	[2] = DEFINE_RES_IRQ(IRQ_ADC),
+};
+
+struct platform_device s3c_device_adc = {
+	.name		= "samsung-adc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_adc_resource),
+	.resource	= s3c_adc_resource,
+};
+#endif /* CONFIG_SAMSUNG_DEV_ADC */
+
+/* Camif Controller */
+
+#ifdef CONFIG_CPU_S3C2440
+static struct resource s3c_camif_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C2440_PA_CAMIF, S3C2440_SZ_CAMIF),
+	[1] = DEFINE_RES_IRQ(IRQ_CAM),
+};
+
+struct platform_device s3c_device_camif = {
+	.name		= "s3c2440-camif",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_camif_resource),
+	.resource	= s3c_camif_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+#endif /* CONFIG_CPU_S3C2440 */
+
+/* ASOC DMA */
+
+struct platform_device samsung_asoc_dma = {
+	.name		= "samsung-audio",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+
+struct platform_device samsung_asoc_idma = {
+	.name		= "samsung-idma",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+
+/* FB */
+
+#ifdef CONFIG_S3C_DEV_FB
+static struct resource s3c_fb_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_FB, SZ_16K),
+	[1] = DEFINE_RES_IRQ(IRQ_LCD_VSYNC),
+	[2] = DEFINE_RES_IRQ(IRQ_LCD_FIFO),
+	[3] = DEFINE_RES_IRQ(IRQ_LCD_SYSTEM),
+};
+
+struct platform_device s3c_device_fb = {
+	.name		= "s3c-fb",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_fb_resource),
+	.resource	= s3c_fb_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+void __init s3c_fb_set_platdata(struct s3c_fb_platdata *pd)
+{
+	s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
+			 &s3c_device_fb);
+}
+#endif /* CONFIG_S3C_DEV_FB */
+
+/* FIMC */
+
+#ifdef CONFIG_S5P_DEV_FIMC0
+static struct resource s5p_fimc0_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_FIMC0, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_FIMC0),
+};
+
+struct platform_device s5p_device_fimc0 = {
+	.name		= "s5p-fimc",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s5p_fimc0_resource),
+	.resource	= s5p_fimc0_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device s5p_device_fimc_md = {
+	.name	= "s5p-fimc-md",
+	.id	= -1,
+};
+#endif /* CONFIG_S5P_DEV_FIMC0 */
+
+#ifdef CONFIG_S5P_DEV_FIMC1
+static struct resource s5p_fimc1_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_FIMC1, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_FIMC1),
+};
+
+struct platform_device s5p_device_fimc1 = {
+	.name		= "s5p-fimc",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(s5p_fimc1_resource),
+	.resource	= s5p_fimc1_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+#endif /* CONFIG_S5P_DEV_FIMC1 */
+
+#ifdef CONFIG_S5P_DEV_FIMC2
+static struct resource s5p_fimc2_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_FIMC2, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_FIMC2),
+};
+
+struct platform_device s5p_device_fimc2 = {
+	.name		= "s5p-fimc",
+	.id		= 2,
+	.num_resources	= ARRAY_SIZE(s5p_fimc2_resource),
+	.resource	= s5p_fimc2_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+#endif /* CONFIG_S5P_DEV_FIMC2 */
+
+#ifdef CONFIG_S5P_DEV_FIMC3
+static struct resource s5p_fimc3_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_FIMC3, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_FIMC3),
+};
+
+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		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+#endif /* CONFIG_S5P_DEV_FIMC3 */
+
+/* FIMD0 */
+
+#ifdef CONFIG_S5P_DEV_FIMD0
+static struct resource s5p_fimd0_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_FIMD0, SZ_32K),
+	[1] = DEFINE_RES_IRQ(IRQ_FIMD0_VSYNC),
+	[2] = DEFINE_RES_IRQ(IRQ_FIMD0_FIFO),
+	[3] = DEFINE_RES_IRQ(IRQ_FIMD0_SYSTEM),
+};
+
+struct platform_device s5p_device_fimd0 = {
+	.name		= "s5p-fb",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s5p_fimd0_resource),
+	.resource	= s5p_fimd0_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+void __init s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd)
+{
+	s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
+			 &s5p_device_fimd0);
+}
+#endif /* CONFIG_S5P_DEV_FIMD0 */
+
+/* HWMON */
+
+#ifdef CONFIG_S3C_DEV_HWMON
+struct platform_device s3c_device_hwmon = {
+	.name		= "s3c-hwmon",
+	.id		= -1,
+	.dev.parent	= &s3c_device_adc.dev,
+};
+
+void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd)
+{
+	s3c_set_platdata(pd, sizeof(struct s3c_hwmon_pdata),
+			 &s3c_device_hwmon);
+}
+#endif /* CONFIG_S3C_DEV_HWMON */
+
+/* HSMMC */
+
+#ifdef CONFIG_S3C_DEV_HSMMC
+static struct resource s3c_hsmmc_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_HSMMC0, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_HSMMC0),
+};
+
+struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata = {
+	.max_width	= 4,
+	.host_caps	= (MMC_CAP_4_BIT_DATA |
+			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
+};
+
+struct platform_device s3c_device_hsmmc0 = {
+	.name		= "s3c-sdhci",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s3c_hsmmc_resource),
+	.resource	= s3c_hsmmc_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &s3c_hsmmc0_def_platdata,
+	},
+};
+
+void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd)
+{
+	s3c_sdhci_set_platdata(pd, &s3c_hsmmc0_def_platdata);
+}
+#endif /* CONFIG_S3C_DEV_HSMMC */
+
+#ifdef CONFIG_S3C_DEV_HSMMC1
+static struct resource s3c_hsmmc1_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_HSMMC1, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_HSMMC1),
+};
+
+struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata = {
+	.max_width	= 4,
+	.host_caps	= (MMC_CAP_4_BIT_DATA |
+			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
+};
+
+struct platform_device s3c_device_hsmmc1 = {
+	.name		= "s3c-sdhci",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(s3c_hsmmc1_resource),
+	.resource	= s3c_hsmmc1_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &s3c_hsmmc1_def_platdata,
+	},
+};
+
+void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd)
+{
+	s3c_sdhci_set_platdata(pd, &s3c_hsmmc1_def_platdata);
+}
+#endif /* CONFIG_S3C_DEV_HSMMC1 */
+
+/* HSMMC2 */
+
+#ifdef CONFIG_S3C_DEV_HSMMC2
+static struct resource s3c_hsmmc2_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_HSMMC2, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_HSMMC2),
+};
+
+struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata = {
+	.max_width	= 4,
+	.host_caps	= (MMC_CAP_4_BIT_DATA |
+			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
+};
+
+struct platform_device s3c_device_hsmmc2 = {
+	.name		= "s3c-sdhci",
+	.id		= 2,
+	.num_resources	= ARRAY_SIZE(s3c_hsmmc2_resource),
+	.resource	= s3c_hsmmc2_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &s3c_hsmmc2_def_platdata,
+	},
+};
+
+void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd)
+{
+	s3c_sdhci_set_platdata(pd, &s3c_hsmmc2_def_platdata);
+}
+#endif /* CONFIG_S3C_DEV_HSMMC2 */
+
+#ifdef CONFIG_S3C_DEV_HSMMC3
+static struct resource s3c_hsmmc3_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_HSMMC3, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_HSMMC3),
+};
+
+struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata = {
+	.max_width	= 4,
+	.host_caps	= (MMC_CAP_4_BIT_DATA |
+			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
+};
+
+struct platform_device s3c_device_hsmmc3 = {
+	.name		= "s3c-sdhci",
+	.id		= 3,
+	.num_resources	= ARRAY_SIZE(s3c_hsmmc3_resource),
+	.resource	= s3c_hsmmc3_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &s3c_hsmmc3_def_platdata,
+	},
+};
+
+void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd)
+{
+	s3c_sdhci_set_platdata(pd, &s3c_hsmmc3_def_platdata);
+}
+#endif /* CONFIG_S3C_DEV_HSMMC3 */
+
+/* I2C */
+
+static struct resource s3c_i2c0_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_IIC, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC),
+};
+
+struct platform_device s3c_device_i2c0 = {
+	.name		= "s3c2410-i2c",
+#ifdef CONFIG_S3C_DEV_I2C1
+	.id		= 0,
+#else
+	.id		= -1,
+#endif
+	.num_resources	= ARRAY_SIZE(s3c_i2c0_resource),
+	.resource	= s3c_i2c0_resource,
+};
+
+struct s3c2410_platform_i2c default_i2c_data __initdata = {
+	.flags		= 0,
+	.slave_addr	= 0x10,
+	.frequency	= 100*1000,
+	.sda_delay	= 100,
+};
+
+void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd)
+		pd = &default_i2c_data;
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c0);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c0_cfg_gpio;
+}
+
+#ifdef CONFIG_S3C_DEV_I2C1
+static struct resource s3c_i2c1_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_IIC1, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC1),
+};
+
+struct platform_device s3c_device_i2c1 = {
+	.name		= "s3c2410-i2c",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(s3c_i2c1_resource),
+	.resource	= s3c_i2c1_resource,
+};
+
+void __init s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 1;
+	}
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c1);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c1_cfg_gpio;
+}
+#endif /* CONFIG_S3C_DEV_I2C1 */
+
+#ifdef CONFIG_S3C_DEV_I2C2
+static struct resource s3c_i2c2_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_IIC2, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC2),
+};
+
+struct platform_device s3c_device_i2c2 = {
+	.name		= "s3c2410-i2c",
+	.id		= 2,
+	.num_resources	= ARRAY_SIZE(s3c_i2c2_resource),
+	.resource	= s3c_i2c2_resource,
+};
+
+void __init s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 2;
+	}
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c2);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c2_cfg_gpio;
+}
+#endif /* CONFIG_S3C_DEV_I2C2 */
+
+#ifdef CONFIG_S3C_DEV_I2C3
+static struct resource s3c_i2c3_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_IIC3, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC3),
+};
+
+struct platform_device s3c_device_i2c3 = {
+	.name		= "s3c2440-i2c",
+	.id		= 3,
+	.num_resources	= ARRAY_SIZE(s3c_i2c3_resource),
+	.resource	= s3c_i2c3_resource,
+};
+
+void __init s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 3;
+	}
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c3);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c3_cfg_gpio;
+}
+#endif /*CONFIG_S3C_DEV_I2C3 */
+
+#ifdef CONFIG_S3C_DEV_I2C4
+static struct resource s3c_i2c4_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_IIC4, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC4),
+};
+
+struct platform_device s3c_device_i2c4 = {
+	.name		= "s3c2440-i2c",
+	.id		= 4,
+	.num_resources	= ARRAY_SIZE(s3c_i2c4_resource),
+	.resource	= s3c_i2c4_resource,
+};
+
+void __init s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 4;
+	}
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c4);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c4_cfg_gpio;
+}
+#endif /*CONFIG_S3C_DEV_I2C4 */
+
+#ifdef CONFIG_S3C_DEV_I2C5
+static struct resource s3c_i2c5_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_IIC5, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC5),
+};
+
+struct platform_device s3c_device_i2c5 = {
+	.name		= "s3c2440-i2c",
+	.id		= 5,
+	.num_resources	= ARRAY_SIZE(s3c_i2c5_resource),
+	.resource	= s3c_i2c5_resource,
+};
+
+void __init s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 5;
+	}
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c5);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c5_cfg_gpio;
+}
+#endif /*CONFIG_S3C_DEV_I2C5 */
+
+#ifdef CONFIG_S3C_DEV_I2C6
+static struct resource s3c_i2c6_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_IIC6, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC6),
+};
+
+struct platform_device s3c_device_i2c6 = {
+	.name		= "s3c2440-i2c",
+	.id		= 6,
+	.num_resources	= ARRAY_SIZE(s3c_i2c6_resource),
+	.resource	= s3c_i2c6_resource,
+};
+
+void __init s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 6;
+	}
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c6);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c6_cfg_gpio;
+}
+#endif /* CONFIG_S3C_DEV_I2C6 */
+
+#ifdef CONFIG_S3C_DEV_I2C7
+static struct resource s3c_i2c7_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_IIC7, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC7),
+};
+
+struct platform_device s3c_device_i2c7 = {
+	.name		= "s3c2440-i2c",
+	.id		= 7,
+	.num_resources	= ARRAY_SIZE(s3c_i2c7_resource),
+	.resource	= s3c_i2c7_resource,
+};
+
+void __init s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 7;
+	}
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c7);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c7_cfg_gpio;
+}
+#endif /* CONFIG_S3C_DEV_I2C7 */
+
+/* I2C HDMIPHY */
+
+#ifdef CONFIG_S5P_DEV_I2C_HDMIPHY
+static struct resource s5p_i2c_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_IIC_HDMIPHY, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_IIC_HDMIPHY),
+};
+
+struct platform_device s5p_device_i2c_hdmiphy = {
+	.name		= "s3c2440-hdmiphy-i2c",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p_i2c_resource),
+	.resource	= s5p_i2c_resource,
+};
+
+void __init s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd) {
+		pd = &default_i2c_data;
+
+		if (soc_is_exynos4210())
+			pd->bus_num = 8;
+		else if (soc_is_s5pv210())
+			pd->bus_num = 3;
+		else
+			pd->bus_num = 0;
+	}
+
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s5p_device_i2c_hdmiphy);
+}
+#endif /* CONFIG_S5P_DEV_I2C_HDMIPHY */
+
+/* I2S */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_iis_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_IIS, S3C24XX_SZ_IIS),
+};
+
+struct platform_device s3c_device_iis = {
+	.name		= "s3c24xx-iis",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_iis_resource),
+	.resource	= s3c_iis_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+#endif /* CONFIG_PLAT_S3C24XX */
+
+#ifdef CONFIG_CPU_S3C2440
+struct platform_device s3c2412_device_iis = {
+	.name		= "s3c2412-iis",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+#endif /* CONFIG_CPU_S3C2440 */
+
+/* IDE CFCON */
+
+#ifdef CONFIG_SAMSUNG_DEV_IDE
+static struct resource s3c_cfcon_resource[] = {
+	[0] = DEFINE_RES_MEM(SAMSUNG_PA_CFCON, SZ_16K),
+	[1] = DEFINE_RES_IRQ(IRQ_CFCON),
+};
+
+struct platform_device s3c_device_cfcon = {
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s3c_cfcon_resource),
+	.resource	= s3c_cfcon_resource,
+};
+
+void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata)
+{
+	s3c_set_platdata(pdata, sizeof(struct s3c_ide_platdata),
+			 &s3c_device_cfcon);
+}
+#endif /* CONFIG_SAMSUNG_DEV_IDE */
+
+/* KEYPAD */
+
+#ifdef CONFIG_SAMSUNG_DEV_KEYPAD
+static struct resource samsung_keypad_resources[] = {
+	[0] = DEFINE_RES_MEM(SAMSUNG_PA_KEYPAD, SZ_32),
+	[1] = DEFINE_RES_IRQ(IRQ_KEYPAD),
+};
+
+struct platform_device samsung_device_keypad = {
+	.name		= "samsung-keypad",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(samsung_keypad_resources),
+	.resource	= samsung_keypad_resources,
+};
+
+void __init samsung_keypad_set_platdata(struct samsung_keypad_platdata *pd)
+{
+	struct samsung_keypad_platdata *npd;
+
+	npd = s3c_set_platdata(pd, sizeof(struct samsung_keypad_platdata),
+			&samsung_device_keypad);
+
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = samsung_keypad_cfg_gpio;
+}
+#endif /* CONFIG_SAMSUNG_DEV_KEYPAD */
+
+/* LCD Controller */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_lcd_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_LCD, S3C24XX_SZ_LCD),
+	[1] = DEFINE_RES_IRQ(IRQ_LCD),
+};
+
+struct platform_device s3c_device_lcd = {
+	.name		= "s3c2410-lcd",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_lcd_resource),
+	.resource	= s3c_lcd_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+
+void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
+{
+	struct s3c2410fb_mach_info *npd;
+
+	npd = s3c_set_platdata(pd, sizeof(*npd), &s3c_device_lcd);
+	if (npd) {
+		npd->displays = kmemdup(pd->displays,
+			sizeof(struct s3c2410fb_display) * npd->num_displays,
+			GFP_KERNEL);
+		if (!npd->displays)
+			printk(KERN_ERR "no memory for LCD display data\n");
+	} else {
+		printk(KERN_ERR "no memory for LCD platform data\n");
+	}
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* MFC */
+
+#ifdef CONFIG_S5P_DEV_MFC
+static struct resource s5p_mfc_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_MFC, SZ_64K),
+	[1] = DEFINE_RES_IRQ(IRQ_MFC),
+};
+
+struct platform_device s5p_device_mfc = {
+	.name		= "s5p-mfc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p_mfc_resource),
+	.resource	= s5p_mfc_resource,
+};
+
+/*
+ * MFC hardware has 2 memory interfaces which are modelled as two separate
+ * platform devices to let dma-mapping distinguish between them.
+ *
+ * MFC parent device (s5p_device_mfc) must be registered before memory
+ * interface specific devices (s5p_device_mfc_l and s5p_device_mfc_r).
+ */
+
+struct platform_device s5p_device_mfc_l = {
+	.name		= "s5p-mfc-l",
+	.id		= -1,
+	.dev		= {
+		.parent			= &s5p_device_mfc.dev,
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device s5p_device_mfc_r = {
+	.name		= "s5p-mfc-r",
+	.id		= -1,
+	.dev		= {
+		.parent			= &s5p_device_mfc.dev,
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+#endif /* CONFIG_S5P_DEV_MFC */
+
+/* MIPI CSIS */
+
+#ifdef CONFIG_S5P_DEV_CSIS0
+static struct resource s5p_mipi_csis0_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_MIPI_CSIS0, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_MIPI_CSIS0),
+};
+
+struct platform_device s5p_device_mipi_csis0 = {
+	.name		= "s5p-mipi-csis",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s5p_mipi_csis0_resource),
+	.resource	= s5p_mipi_csis0_resource,
+};
+#endif /* CONFIG_S5P_DEV_CSIS0 */
+
+#ifdef CONFIG_S5P_DEV_CSIS1
+static struct resource s5p_mipi_csis1_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_MIPI_CSIS1, SZ_4K),
+	[1] = DEFINE_RES_IRQ(IRQ_MIPI_CSIS1),
+};
+
+struct platform_device s5p_device_mipi_csis1 = {
+	.name		= "s5p-mipi-csis",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(s5p_mipi_csis1_resource),
+	.resource	= s5p_mipi_csis1_resource,
+};
+#endif
+
+/* NAND */
+
+#ifdef CONFIG_S3C_DEV_NAND
+static struct resource s3c_nand_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_NAND, SZ_1M),
+};
+
+struct platform_device s3c_device_nand = {
+	.name		= "s3c2410-nand",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_nand_resource),
+	.resource	= s3c_nand_resource,
+};
+
+/*
+ * s3c_nand_copy_set() - copy nand set data
+ * @set: The new structure, directly copied from the old.
+ *
+ * Copy all the fields from the NAND set field from what is probably __initdata
+ * to new kernel memory. The code returns 0 if the copy happened correctly or
+ * an error code for the calling function to display.
+ *
+ * Note, we currently do not try and look to see if we've already copied the
+ * data in a previous set.
+ */
+static int __init s3c_nand_copy_set(struct s3c2410_nand_set *set)
+{
+	void *ptr;
+	int size;
+
+	size = sizeof(struct mtd_partition) * set->nr_partitions;
+	if (size) {
+		ptr = kmemdup(set->partitions, size, GFP_KERNEL);
+		set->partitions = ptr;
+
+		if (!ptr)
+			return -ENOMEM;
+	}
+
+	if (set->nr_map && set->nr_chips) {
+		size = sizeof(int) * set->nr_chips;
+		ptr = kmemdup(set->nr_map, size, GFP_KERNEL);
+		set->nr_map = ptr;
+
+		if (!ptr)
+			return -ENOMEM;
+	}
+
+	if (set->ecc_layout) {
+		ptr = kmemdup(set->ecc_layout,
+			      sizeof(struct nand_ecclayout), GFP_KERNEL);
+		set->ecc_layout = ptr;
+
+		if (!ptr)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
+{
+	struct s3c2410_platform_nand *npd;
+	int size;
+	int ret;
+
+	/* note, if we get a failure in allocation, we simply drop out of the
+	 * function. If there is so little memory available at initialisation
+	 * time then there is little chance the system is going to run.
+	 */
+
+	npd = s3c_set_platdata(nand, sizeof(struct s3c2410_platform_nand),
+				&s3c_device_nand);
+	if (!npd)
+		return;
+
+	/* now see if we need to copy any of the nand set data */
+
+	size = sizeof(struct s3c2410_nand_set) * npd->nr_sets;
+	if (size) {
+		struct s3c2410_nand_set *from = npd->sets;
+		struct s3c2410_nand_set *to;
+		int i;
+
+		to = kmemdup(from, size, GFP_KERNEL);
+		npd->sets = to;	/* set, even if we failed */
+
+		if (!to) {
+			printk(KERN_ERR "%s: no memory for sets\n", __func__);
+			return;
+		}
+
+		for (i = 0; i < npd->nr_sets; i++) {
+			ret = s3c_nand_copy_set(to);
+			if (ret) {
+				printk(KERN_ERR "%s: failed to copy set %d\n",
+				__func__, i);
+				return;
+			}
+			to++;
+		}
+	}
+}
+#endif /* CONFIG_S3C_DEV_NAND */
+
+/* ONENAND */
+
+#ifdef CONFIG_S3C_DEV_ONENAND
+static struct resource s3c_onenand_resources[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_ONENAND, SZ_1K),
+	[1] = DEFINE_RES_MEM(S3C_PA_ONENAND_BUF, S3C_SZ_ONENAND_BUF),
+	[2] = DEFINE_RES_IRQ(IRQ_ONENAND),
+};
+
+struct platform_device s3c_device_onenand = {
+	.name		= "samsung-onenand",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s3c_onenand_resources),
+	.resource	= s3c_onenand_resources,
+};
+#endif /* CONFIG_S3C_DEV_ONENAND */
+
+#ifdef CONFIG_S3C64XX_DEV_ONENAND1
+static struct resource s3c64xx_onenand1_resources[] = {
+	[0] = DEFINE_RES_MEM(S3C64XX_PA_ONENAND1, SZ_1K),
+	[1] = DEFINE_RES_MEM(S3C64XX_PA_ONENAND1_BUF, S3C64XX_SZ_ONENAND1_BUF),
+	[2] = DEFINE_RES_IRQ(IRQ_ONENAND1),
+};
+
+struct platform_device s3c64xx_device_onenand1 = {
+	.name		= "samsung-onenand",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(s3c64xx_onenand1_resources),
+	.resource	= s3c64xx_onenand1_resources,
+};
+
+void s3c64xx_onenand1_set_platdata(struct onenand_platform_data *pdata)
+{
+	s3c_set_platdata(pdata, sizeof(struct onenand_platform_data),
+			 &s3c64xx_device_onenand1);
+}
+#endif /* CONFIG_S3C64XX_DEV_ONENAND1 */
+
+#ifdef CONFIG_S5P_DEV_ONENAND
+static struct resource s5p_onenand_resources[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_ONENAND, SZ_128K),
+	[1] = DEFINE_RES_MEM(S5P_PA_ONENAND_DMA, SZ_8K),
+	[2] = DEFINE_RES_IRQ(IRQ_ONENAND_AUDI),
+};
+
+struct platform_device s5p_device_onenand = {
+	.name		= "s5pc110-onenand",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p_onenand_resources),
+	.resource	= s5p_onenand_resources,
+};
+#endif /* CONFIG_S5P_DEV_ONENAND */
+
+/* PMU */
+
+#ifdef CONFIG_PLAT_S5P
+static struct resource s5p_pmu_resource[] = {
+	DEFINE_RES_IRQ(IRQ_PMU)
+};
+
+struct platform_device s5p_device_pmu = {
+	.name		= "arm-pmu",
+	.id		= ARM_PMU_DEVICE_CPU,
+	.num_resources	= ARRAY_SIZE(s5p_pmu_resource),
+	.resource	= s5p_pmu_resource,
+};
+
+static int __init s5p_pmu_init(void)
+{
+	platform_device_register(&s5p_device_pmu);
+	return 0;
+}
+arch_initcall(s5p_pmu_init);
+#endif /* CONFIG_PLAT_S5P */
+
+/* PWM Timer */
+
+#ifdef CONFIG_SAMSUNG_DEV_PWM
+
+#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) },
+};
+#endif /* CONFIG_SAMSUNG_DEV_PWM */
+
+/* RTC */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_rtc_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_RTC, SZ_256),
+	[1] = DEFINE_RES_IRQ(IRQ_RTC),
+	[2] = DEFINE_RES_IRQ(IRQ_TICK),
+};
+
+struct platform_device s3c_device_rtc = {
+	.name		= "s3c2410-rtc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_rtc_resource),
+	.resource	= s3c_rtc_resource,
+};
+#endif /* CONFIG_PLAT_S3C24XX */
+
+#ifdef CONFIG_S3C_DEV_RTC
+static struct resource s3c_rtc_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_RTC, SZ_256),
+	[1] = DEFINE_RES_IRQ(IRQ_RTC_ALARM),
+	[2] = DEFINE_RES_IRQ(IRQ_RTC_TIC),
+};
+
+struct platform_device s3c_device_rtc = {
+	.name		= "s3c64xx-rtc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_rtc_resource),
+	.resource	= s3c_rtc_resource,
+};
+#endif /* CONFIG_S3C_DEV_RTC */
+
+/* SDI */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_sdi_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_SDI, S3C24XX_SZ_SDI),
+	[1] = DEFINE_RES_IRQ(IRQ_SDI),
+};
+
+struct platform_device s3c_device_sdi = {
+	.name		= "s3c2410-sdi",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_sdi_resource),
+	.resource	= s3c_sdi_resource,
+};
+
+void __init s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata)
+{
+	s3c_set_platdata(pdata, sizeof(struct s3c24xx_mci_pdata),
+			 &s3c_device_sdi);
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* SPI */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_spi0_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_SPI, SZ_32),
+	[1] = DEFINE_RES_IRQ(IRQ_SPI0),
+};
+
+struct platform_device s3c_device_spi0 = {
+	.name		= "s3c2410-spi",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s3c_spi0_resource),
+	.resource	= s3c_spi0_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+
+static struct resource s3c_spi1_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_SPI1, SZ_32),
+	[1] = DEFINE_RES_IRQ(IRQ_SPI1),
+};
+
+struct platform_device s3c_device_spi1 = {
+	.name		= "s3c2410-spi",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(s3c_spi1_resource),
+	.resource	= s3c_spi1_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* Touchscreen */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_ts_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_ADC, S3C24XX_SZ_ADC),
+	[1] = DEFINE_RES_IRQ(IRQ_TC),
+};
+
+struct platform_device s3c_device_ts = {
+	.name		= "s3c2410-ts",
+	.id		= -1,
+	.dev.parent	= &s3c_device_adc.dev,
+	.num_resources	= ARRAY_SIZE(s3c_ts_resource),
+	.resource	= s3c_ts_resource,
+};
+
+void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
+{
+	s3c_set_platdata(hard_s3c2410ts_info,
+			 sizeof(struct s3c2410_ts_mach_info), &s3c_device_ts);
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+#ifdef CONFIG_SAMSUNG_DEV_TS
+static struct resource s3c_ts_resource[] = {
+	[0] = DEFINE_RES_MEM(SAMSUNG_PA_ADC, SZ_256),
+	[1] = DEFINE_RES_IRQ(IRQ_TC),
+};
+
+static struct s3c2410_ts_mach_info default_ts_data __initdata = {
+	.delay			= 10000,
+	.presc			= 49,
+	.oversampling_shift	= 2,
+};
+
+struct platform_device s3c_device_ts = {
+	.name		= "s3c64xx-ts",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_ts_resource),
+	.resource	= s3c_ts_resource,
+};
+
+void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd)
+{
+	if (!pd)
+		pd = &default_ts_data;
+
+	s3c_set_platdata(pd, sizeof(struct s3c2410_ts_mach_info),
+			 &s3c_device_ts);
+}
+#endif /* CONFIG_SAMSUNG_DEV_TS */
+
+/* TV */
+
+#ifdef CONFIG_S5P_DEV_TV
+
+static struct resource s5p_hdmi_resources[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_HDMI, SZ_1M),
+	[1] = DEFINE_RES_IRQ(IRQ_HDMI),
+};
+
+struct platform_device s5p_device_hdmi = {
+	.name		= "s5p-hdmi",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p_hdmi_resources),
+	.resource	= s5p_hdmi_resources,
+};
+
+static struct resource s5p_sdo_resources[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_SDO, SZ_64K),
+	[1] = DEFINE_RES_IRQ(IRQ_SDO),
+};
+
+struct platform_device s5p_device_sdo = {
+	.name		= "s5p-sdo",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p_sdo_resources),
+	.resource	= s5p_sdo_resources,
+};
+
+static struct resource s5p_mixer_resources[] = {
+	[0] = DEFINE_RES_MEM_NAMED(S5P_PA_MIXER, SZ_64K, "mxr"),
+	[1] = DEFINE_RES_MEM_NAMED(S5P_PA_VP, SZ_64K, "vp"),
+	[2] = DEFINE_RES_IRQ_NAMED(IRQ_MIXER, "irq"),
+};
+
+struct platform_device s5p_device_mixer = {
+	.name		= "s5p-mixer",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p_mixer_resources),
+	.resource	= s5p_mixer_resources,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+#endif /* CONFIG_S5P_DEV_TV */
+
+/* USB */
+
+#ifdef CONFIG_S3C_DEV_USB_HOST
+static struct resource s3c_usb_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_USBHOST, SZ_256),
+	[1] = DEFINE_RES_IRQ(IRQ_USBH),
+};
+
+struct platform_device s3c_device_ohci = {
+	.name		= "s3c2410-ohci",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_usb_resource),
+	.resource	= s3c_usb_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+
+/*
+ * s3c_ohci_set_platdata - initialise OHCI device platform data
+ * @info: The platform data.
+ *
+ * This call copies the @info passed in and sets the device .platform_data
+ * field to that copy. The @info is copied so that the original can be marked
+ * __initdata.
+ */
+
+void __init s3c_ohci_set_platdata(struct s3c2410_hcd_info *info)
+{
+	s3c_set_platdata(info, sizeof(struct s3c2410_hcd_info),
+			 &s3c_device_ohci);
+}
+#endif /* CONFIG_S3C_DEV_USB_HOST */
+
+/* USB Device (Gadget) */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_usbgadget_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_USBDEV, S3C24XX_SZ_USBDEV),
+	[1] = DEFINE_RES_IRQ(IRQ_USBD),
+};
+
+struct platform_device s3c_device_usbgadget = {
+	.name		= "s3c2410-usbgadget",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_usbgadget_resource),
+	.resource	= s3c_usbgadget_resource,
+};
+
+void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd)
+{
+	s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usbgadget);
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* USB EHCI Host Controller */
+
+#ifdef CONFIG_S5P_DEV_USB_EHCI
+static struct resource s5p_ehci_resource[] = {
+	[0] = DEFINE_RES_MEM(S5P_PA_EHCI, SZ_256),
+	[1] = DEFINE_RES_IRQ(IRQ_USB_HOST),
+};
+
+struct platform_device s5p_device_ehci = {
+	.name		= "s5p-ehci",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p_ehci_resource),
+	.resource	= s5p_ehci_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+
+void __init s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd)
+{
+	struct s5p_ehci_platdata *npd;
+
+	npd = s3c_set_platdata(pd, sizeof(struct s5p_ehci_platdata),
+			&s5p_device_ehci);
+
+	if (!npd->phy_init)
+		npd->phy_init = s5p_usb_phy_init;
+	if (!npd->phy_exit)
+		npd->phy_exit = s5p_usb_phy_exit;
+}
+#endif /* CONFIG_S5P_DEV_USB_EHCI */
+
+/* USB HSOTG */
+
+#ifdef CONFIG_S3C_DEV_USB_HSOTG
+static struct resource s3c_usb_hsotg_resources[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_USB_HSOTG, SZ_16K),
+	[1] = DEFINE_RES_IRQ(IRQ_OTG),
+};
+
+struct platform_device s3c_device_usb_hsotg = {
+	.name		= "s3c-hsotg",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_usb_hsotg_resources),
+	.resource	= s3c_usb_hsotg_resources,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+#endif /* CONFIG_S3C_DEV_USB_HSOTG */
+
+/* USB High Spped 2.0 Device (Gadget) */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_hsudc_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C2416_PA_HSUDC, S3C2416_SZ_HSUDC),
+	[1] = DEFINE_RES_IRQ(IRQ_USBD),
+};
+
+struct platform_device s3c_device_usb_hsudc = {
+	.name		= "s3c-hsudc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_hsudc_resource),
+	.resource	= s3c_hsudc_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd)
+{
+	s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usb_hsudc);
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* WDT */
+
+#ifdef CONFIG_S3C_DEV_WDT
+static struct resource s3c_wdt_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C_PA_WDT, SZ_1K),
+	[1] = DEFINE_RES_IRQ(IRQ_WDT),
+};
+
+struct platform_device s3c_device_wdt = {
+	.name		= "s3c2410-wdt",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_wdt_resource),
+	.resource	= s3c_wdt_resource,
+};
+#endif /* CONFIG_S3C_DEV_WDT */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-ts.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-ts.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-ts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-ts.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/* linux/arch/arm/mach-s3c64xx/dev-ts.c
- *
- * Copyright (c) 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org>
- *
- * Adapted by Maurus Cuelenaere for s3c64xx
- *
- * S3C64XX series device definition for touchscreen 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/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-#include <plat/ts.h>
-
-static struct resource s3c_ts_resource[] = {
-	[0] = {
-		.start = SAMSUNG_PA_ADC,
-		.end   = SAMSUNG_PA_ADC + SZ_256 - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_TC,
-		.end   = IRQ_TC,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_ts = {
-	.name		= "s3c64xx-ts",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s3c_ts_resource),
-	.resource	= s3c_ts_resource,
-};
-
-void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd)
-{
-	s3c_set_platdata(pd, sizeof(struct s3c2410_ts_mach_info),
-			 &s3c_device_ts);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-usb.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-usb.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-usb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-usb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-usb.c
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for USB host
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-#include <plat/usb-control.h>
-
-static struct resource s3c_usb_resource[] = {
-	[0] = {
-		.start = S3C_PA_USBHOST,
-		.end   = S3C_PA_USBHOST + 0x100 - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_USBH,
-		.end   = IRQ_USBH,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static u64 s3c_device_usb_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_ohci = {
-	.name		  = "s3c2410-ohci",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_usb_resource),
-	.resource	  = s3c_usb_resource,
-	.dev              = {
-		.dma_mask = &s3c_device_usb_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_ohci);
-
-/**
- * s3c_ohci_set_platdata - initialise OHCI device platform data
- * @info: The platform data.
- *
- * This call copies the @info passed in and sets the device .platform_data
- * field to that copy. The @info is copied so that the original can be marked
- * __initdata.
- */
-void __init s3c_ohci_set_platdata(struct s3c2410_hcd_info *info)
-{
-	s3c_set_platdata(info, sizeof(struct s3c2410_hcd_info),
-			 &s3c_device_ohci);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-usb-hsotg.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-usb-hsotg.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-usb-hsotg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-usb-hsotg.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,48 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-usb-hsotg.c
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for USB high-speed UDC/OtG block
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-
-static struct resource s3c_usb_hsotg_resources[] = {
-	[0] = {
-		.start	= S3C_PA_USB_HSOTG,
-		.end	= S3C_PA_USB_HSOTG + 0x10000 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_OTG,
-		.end	= IRQ_OTG,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 s3c_hsotg_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s3c_device_usb_hsotg = {
-	.name		= "s3c-hsotg",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s3c_usb_hsotg_resources),
-	.resource	= s3c_usb_hsotg_resources,
-	.dev		= {
-		.dma_mask		= &s3c_hsotg_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-wdt.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-wdt.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dev-wdt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dev-wdt.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,40 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-wdt.c
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C series device definition for the watchdog 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 <mach/map.h>
-
-#include <plat/devs.h>
-
-static struct resource s3c_wdt_resource[] = {
-	[0] = {
-		.start	= S3C_PA_WDT,
-		.end	= S3C_PA_WDT + SZ_1K,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_WDT,
-		.end	= IRQ_WDT,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device s3c_device_wdt = {
-	.name		= "s3c2410-wdt",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s3c_wdt_resource),
-	.resource	= s3c_wdt_resource,
-};
-EXPORT_SYMBOL(s3c_device_wdt);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/dma-ops.c linux-libre-3.2-gnu/arch/arm/plat-samsung/dma-ops.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/dma-ops.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/dma-ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,132 @@
+/* linux/arch/arm/plat-samsung/dma-ops.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung DMA Operations
+ *
+ * This program is free software; you can 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/amba/pl330.h>
+#include <linux/scatterlist.h>
+#include <linux/export.h>
+
+#include <mach/dma.h>
+
+static inline bool pl330_filter(struct dma_chan *chan, void *param)
+{
+	struct dma_pl330_peri *peri = chan->private;
+	return peri->peri_id == (unsigned)param;
+}
+
+static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
+				struct samsung_dma_info *info)
+{
+	struct dma_chan *chan;
+	dma_cap_mask_t mask;
+	struct dma_slave_config slave_config;
+
+	dma_cap_zero(mask);
+	dma_cap_set(info->cap, mask);
+
+	chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
+
+	if (info->direction == DMA_FROM_DEVICE) {
+		memset(&slave_config, 0, sizeof(struct dma_slave_config));
+		slave_config.direction = info->direction;
+		slave_config.src_addr = info->fifo;
+		slave_config.src_addr_width = info->width;
+		slave_config.src_maxburst = 1;
+		dmaengine_slave_config(chan, &slave_config);
+	} else if (info->direction == DMA_TO_DEVICE) {
+		memset(&slave_config, 0, sizeof(struct dma_slave_config));
+		slave_config.direction = info->direction;
+		slave_config.dst_addr = info->fifo;
+		slave_config.dst_addr_width = info->width;
+		slave_config.dst_maxburst = 1;
+		dmaengine_slave_config(chan, &slave_config);
+	}
+
+	return (unsigned)chan;
+}
+
+static int samsung_dmadev_release(unsigned ch,
+			struct s3c2410_dma_client *client)
+{
+	dma_release_channel((struct dma_chan *)ch);
+
+	return 0;
+}
+
+static int samsung_dmadev_prepare(unsigned ch,
+			struct samsung_dma_prep_info *info)
+{
+	struct scatterlist sg;
+	struct dma_chan *chan = (struct dma_chan *)ch;
+	struct dma_async_tx_descriptor *desc;
+
+	switch (info->cap) {
+	case DMA_SLAVE:
+		sg_init_table(&sg, 1);
+		sg_dma_len(&sg) = info->len;
+		sg_set_page(&sg, pfn_to_page(PFN_DOWN(info->buf)),
+			    info->len, offset_in_page(info->buf));
+		sg_dma_address(&sg) = info->buf;
+
+		desc = chan->device->device_prep_slave_sg(chan,
+			&sg, 1, info->direction, DMA_PREP_INTERRUPT);
+		break;
+	case DMA_CYCLIC:
+		desc = chan->device->device_prep_dma_cyclic(chan,
+			info->buf, info->len, info->period, info->direction);
+		break;
+	default:
+		dev_err(&chan->dev->device, "unsupported format\n");
+		return -EFAULT;
+	}
+
+	if (!desc) {
+		dev_err(&chan->dev->device, "cannot prepare cyclic dma\n");
+		return -EFAULT;
+	}
+
+	desc->callback = info->fp;
+	desc->callback_param = info->fp_param;
+
+	dmaengine_submit((struct dma_async_tx_descriptor *)desc);
+
+	return 0;
+}
+
+static inline int samsung_dmadev_trigger(unsigned ch)
+{
+	dma_async_issue_pending((struct dma_chan *)ch);
+
+	return 0;
+}
+
+static inline int samsung_dmadev_flush(unsigned ch)
+{
+	return dmaengine_terminate_all((struct dma_chan *)ch);
+}
+
+struct samsung_dma_ops dmadev_ops = {
+	.request	= samsung_dmadev_request,
+	.release	= samsung_dmadev_release,
+	.prepare	= samsung_dmadev_prepare,
+	.trigger	= samsung_dmadev_trigger,
+	.started	= NULL,
+	.flush		= samsung_dmadev_flush,
+	.stop		= samsung_dmadev_flush,
+};
+
+void *samsung_dmadev_get_ops(void)
+{
+	return &dmadev_ops;
+}
+EXPORT_SYMBOL(samsung_dmadev_get_ops);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/gpio.c linux-libre-3.2-gnu/arch/arm/plat-samsung/gpio.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,167 +0,0 @@
-/* linux/arch/arm/plat-s3c/gpio.c
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series GPIO core
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/spinlock.h>
-
-#include <plat/gpio-core.h>
-
-#ifdef CONFIG_S3C_GPIO_TRACK
-struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
-
-static __init void s3c_gpiolib_track(struct s3c_gpio_chip *chip)
-{
-	unsigned int gpn;
-	int i;
-
-	gpn = chip->chip.base;
-	for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
-		BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
-		s3c_gpios[gpn] = chip;
-	}
-}
-#endif /* CONFIG_S3C_GPIO_TRACK */
-
-/* Default routines for controlling GPIO, based on the original S3C24XX
- * GPIO functions which deal with the case where each gpio bank of the
- * chip is as following:
- *
- * base + 0x00: Control register, 2 bits per gpio
- *	        gpio n: 2 bits starting at (2*n)
- *		00 = input, 01 = output, others mean special-function
- * base + 0x04: Data register, 1 bit per gpio
- *		bit n: data bit n
-*/
-
-static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long flags;
-	unsigned long con;
-
-	s3c_gpio_lock(ourchip, flags);
-
-	con = __raw_readl(base + 0x00);
-	con &= ~(3 << (offset * 2));
-
-	__raw_writel(con, base + 0x00);
-
-	s3c_gpio_unlock(ourchip, flags);
-	return 0;
-}
-
-static int s3c_gpiolib_output(struct gpio_chip *chip,
-			      unsigned offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long flags;
-	unsigned long dat;
-	unsigned long con;
-
-	s3c_gpio_lock(ourchip, flags);
-
-	dat = __raw_readl(base + 0x04);
-	dat &= ~(1 << offset);
-	if (value)
-		dat |= 1 << offset;
-	__raw_writel(dat, base + 0x04);
-
-	con = __raw_readl(base + 0x00);
-	con &= ~(3 << (offset * 2));
-	con |= 1 << (offset * 2);
-
-	__raw_writel(con, base + 0x00);
-	__raw_writel(dat, base + 0x04);
-
-	s3c_gpio_unlock(ourchip, flags);
-	return 0;
-}
-
-static void s3c_gpiolib_set(struct gpio_chip *chip,
-			    unsigned offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long flags;
-	unsigned long dat;
-
-	s3c_gpio_lock(ourchip, flags);
-
-	dat = __raw_readl(base + 0x04);
-	dat &= ~(1 << offset);
-	if (value)
-		dat |= 1 << offset;
-	__raw_writel(dat, base + 0x04);
-
-	s3c_gpio_unlock(ourchip, flags);
-}
-
-static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	unsigned long val;
-
-	val = __raw_readl(ourchip->base + 0x04);
-	val >>= offset;
-	val &= 1;
-
-	return val;
-}
-
-__init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
-{
-	struct gpio_chip *gc = &chip->chip;
-	int ret;
-
-	BUG_ON(!chip->base);
-	BUG_ON(!gc->label);
-	BUG_ON(!gc->ngpio);
-
-	spin_lock_init(&chip->lock);
-
-	if (!gc->direction_input)
-		gc->direction_input = s3c_gpiolib_input;
-	if (!gc->direction_output)
-		gc->direction_output = s3c_gpiolib_output;
-	if (!gc->set)
-		gc->set = s3c_gpiolib_set;
-	if (!gc->get)
-		gc->get = s3c_gpiolib_get;
-
-#ifdef CONFIG_PM
-	if (chip->pm != NULL) {
-		if (!chip->pm->save || !chip->pm->resume)
-			printk(KERN_ERR "gpio: %s has missing PM functions\n",
-			       gc->label);
-	} else
-		printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
-#endif
-
-	/* gpiochip_add() prints own failure message on error. */
-	ret = gpiochip_add(gc);
-	if (ret >= 0)
-		s3c_gpiolib_track(chip);
-}
-
-int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
-{
-	struct s3c_gpio_chip *s3c_chip = container_of(chip,
-			struct s3c_gpio_chip, chip);
-
-	return s3c_chip->irq_base + offset;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/gpio-config.c linux-libre-3.2-gnu/arch/arm/plat-samsung/gpio-config.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/gpio-config.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/gpio-config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,431 +0,0 @@
-/* linux/arch/arm/plat-s3c/gpio-config.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008-2010 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series GPIO configuration core
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned long flags;
-	int offset;
-	int ret;
-
-	if (!chip)
-		return -EINVAL;
-
-	offset = pin - chip->chip.base;
-
-	s3c_gpio_lock(chip, flags);
-	ret = s3c_gpio_do_setcfg(chip, offset, config);
-	s3c_gpio_unlock(chip, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c_gpio_cfgpin);
-
-int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
-			  unsigned int cfg)
-{
-	int ret;
-
-	for (; nr > 0; nr--, start++) {
-		ret = s3c_gpio_cfgpin(start, cfg);
-		if (ret != 0)
-			return ret;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
-
-int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
-			  unsigned int cfg, s3c_gpio_pull_t pull)
-{
-	int ret;
-
-	for (; nr > 0; nr--, start++) {
-		s3c_gpio_setpull(start, pull);
-		ret = s3c_gpio_cfgpin(start, cfg);
-		if (ret != 0)
-			return ret;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
-
-unsigned s3c_gpio_getcfg(unsigned int pin)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned long flags;
-	unsigned ret = 0;
-	int offset;
-
-	if (chip) {
-		offset = pin - chip->chip.base;
-
-		s3c_gpio_lock(chip, flags);
-		ret = s3c_gpio_do_getcfg(chip, offset);
-		s3c_gpio_unlock(chip, flags);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c_gpio_getcfg);
-
-
-int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned long flags;
-	int offset, ret;
-
-	if (!chip)
-		return -EINVAL;
-
-	offset = pin - chip->chip.base;
-
-	s3c_gpio_lock(chip, flags);
-	ret = s3c_gpio_do_setpull(chip, offset, pull);
-	s3c_gpio_unlock(chip, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c_gpio_setpull);
-
-s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned long flags;
-	int offset;
-	u32 pup = 0;
-
-	if (chip) {
-		offset = pin - chip->chip.base;
-
-		s3c_gpio_lock(chip, flags);
-		pup = s3c_gpio_do_getpull(chip, offset);
-		s3c_gpio_unlock(chip, flags);
-	}
-
-	return (__force s3c_gpio_pull_t)pup;
-}
-EXPORT_SYMBOL(s3c_gpio_getpull);
-
-#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
-int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-			      unsigned int off, unsigned int cfg)
-{
-	void __iomem *reg = chip->base;
-	unsigned int shift = off;
-	u32 con;
-
-	if (s3c_gpio_is_cfg_special(cfg)) {
-		cfg &= 0xf;
-
-		/* Map output to 0, and SFN2 to 1 */
-		cfg -= 1;
-		if (cfg > 1)
-			return -EINVAL;
-
-		cfg <<= shift;
-	}
-
-	con = __raw_readl(reg);
-	con &= ~(0x1 << shift);
-	con |= cfg;
-	__raw_writel(con, reg);
-
-	return 0;
-}
-
-unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-				   unsigned int off)
-{
-	u32 con;
-
-	con = __raw_readl(chip->base);
-	con >>= off;
-	con &= 1;
-	con++;
-
-	return S3C_GPIO_SFN(con);
-}
-
-int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
-			    unsigned int off, unsigned int cfg)
-{
-	void __iomem *reg = chip->base;
-	unsigned int shift = off * 2;
-	u32 con;
-
-	if (s3c_gpio_is_cfg_special(cfg)) {
-		cfg &= 0xf;
-		if (cfg > 3)
-			return -EINVAL;
-
-		cfg <<= shift;
-	}
-
-	con = __raw_readl(reg);
-	con &= ~(0x3 << shift);
-	con |= cfg;
-	__raw_writel(con, reg);
-
-	return 0;
-}
-
-unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip,
-				     unsigned int off)
-{
-	u32 con;
-
-	con = __raw_readl(chip->base);
-	con >>= off * 2;
-	con &= 3;
-
-	/* this conversion works for IN and OUT as well as special mode */
-	return S3C_GPIO_SPECIAL(con);
-}
-#endif
-
-#ifdef CONFIG_S3C_GPIO_CFG_S3C64XX
-int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-				 unsigned int off, unsigned int cfg)
-{
-	void __iomem *reg = chip->base;
-	unsigned int shift = (off & 7) * 4;
-	u32 con;
-
-	if (off < 8 && chip->chip.ngpio > 8)
-		reg -= 4;
-
-	if (s3c_gpio_is_cfg_special(cfg)) {
-		cfg &= 0xf;
-		cfg <<= shift;
-	}
-
-	con = __raw_readl(reg);
-	con &= ~(0xf << shift);
-	con |= cfg;
-	__raw_writel(con, reg);
-
-	return 0;
-}
-
-unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-				      unsigned int off)
-{
-	void __iomem *reg = chip->base;
-	unsigned int shift = (off & 7) * 4;
-	u32 con;
-
-	if (off < 8 && chip->chip.ngpio > 8)
-		reg -= 4;
-
-	con = __raw_readl(reg);
-	con >>= shift;
-	con &= 0xf;
-
-	/* this conversion works for IN and OUT as well as special mode */
-	return S3C_GPIO_SPECIAL(con);
-}
-
-#endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */
-
-#ifdef CONFIG_S3C_GPIO_PULL_UPDOWN
-int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
-			    unsigned int off, s3c_gpio_pull_t pull)
-{
-	void __iomem *reg = chip->base + 0x08;
-	int shift = off * 2;
-	u32 pup;
-
-	pup = __raw_readl(reg);
-	pup &= ~(3 << shift);
-	pup |= pull << shift;
-	__raw_writel(pup, reg);
-
-	return 0;
-}
-
-s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
-					unsigned int off)
-{
-	void __iomem *reg = chip->base + 0x08;
-	int shift = off * 2;
-	u32 pup = __raw_readl(reg);
-
-	pup >>= shift;
-	pup &= 0x3;
-	return (__force s3c_gpio_pull_t)pup;
-}
-
-#ifdef CONFIG_S3C_GPIO_PULL_S3C2443
-int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip,
-				unsigned int off, s3c_gpio_pull_t pull)
-{
-	switch (pull) {
-	case S3C_GPIO_PULL_NONE:
-		pull = 0x01;
-		break;
-	case S3C_GPIO_PULL_UP:
-		pull = 0x00;
-		break;
-	case S3C_GPIO_PULL_DOWN:
-		pull = 0x02;
-		break;
-	}
-	return s3c_gpio_setpull_updown(chip, off, pull);
-}
-
-s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip,
-					unsigned int off)
-{
-	s3c_gpio_pull_t pull;
-
-	pull = s3c_gpio_getpull_updown(chip, off);
-
-	switch (pull) {
-	case 0x00:
-		pull = S3C_GPIO_PULL_UP;
-		break;
-	case 0x01:
-	case 0x03:
-		pull = S3C_GPIO_PULL_NONE;
-		break;
-	case 0x02:
-		pull = S3C_GPIO_PULL_DOWN;
-		break;
-	}
-
-	return pull;
-}
-#endif
-#endif
-
-#if defined(CONFIG_S3C_GPIO_PULL_UP) || defined(CONFIG_S3C_GPIO_PULL_DOWN)
-static int s3c_gpio_setpull_1(struct s3c_gpio_chip *chip,
-			 unsigned int off, s3c_gpio_pull_t pull,
-			 s3c_gpio_pull_t updown)
-{
-	void __iomem *reg = chip->base + 0x08;
-	u32 pup = __raw_readl(reg);
-
-	if (pull == updown)
-		pup &= ~(1 << off);
-	else if (pull == S3C_GPIO_PULL_NONE)
-		pup |= (1 << off);
-	else
-		return -EINVAL;
-
-	__raw_writel(pup, reg);
-	return 0;
-}
-
-static s3c_gpio_pull_t s3c_gpio_getpull_1(struct s3c_gpio_chip *chip,
-				     unsigned int off, s3c_gpio_pull_t updown)
-{
-	void __iomem *reg = chip->base + 0x08;
-	u32 pup = __raw_readl(reg);
-
-	pup &= (1 << off);
-	return pup ? S3C_GPIO_PULL_NONE : updown;
-}
-#endif /* CONFIG_S3C_GPIO_PULL_UP || CONFIG_S3C_GPIO_PULL_DOWN */
-
-#ifdef CONFIG_S3C_GPIO_PULL_UP
-s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
-				     unsigned int off)
-{
-	return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
-}
-
-int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
-			 unsigned int off, s3c_gpio_pull_t pull)
-{
-	return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
-}
-#endif /* CONFIG_S3C_GPIO_PULL_UP */
-
-#ifdef CONFIG_S3C_GPIO_PULL_DOWN
-s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
-				     unsigned int off)
-{
-	return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
-}
-
-int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
-			 unsigned int off, s3c_gpio_pull_t pull)
-{
-	return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
-}
-#endif /* CONFIG_S3C_GPIO_PULL_DOWN */
-
-#ifdef CONFIG_S5P_GPIO_DRVSTR
-s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned int off;
-	void __iomem *reg;
-	int shift;
-	u32 drvstr;
-
-	if (!chip)
-		return -EINVAL;
-
-	off = pin - chip->chip.base;
-	shift = off * 2;
-	reg = chip->base + 0x0C;
-
-	drvstr = __raw_readl(reg);
-	drvstr = drvstr >> shift;
-	drvstr &= 0x3;
-
-	return (__force s5p_gpio_drvstr_t)drvstr;
-}
-EXPORT_SYMBOL(s5p_gpio_get_drvstr);
-
-int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned int off;
-	void __iomem *reg;
-	int shift;
-	u32 tmp;
-
-	if (!chip)
-		return -EINVAL;
-
-	off = pin - chip->chip.base;
-	shift = off * 2;
-	reg = chip->base + 0x0C;
-
-	tmp = __raw_readl(reg);
-	tmp &= ~(0x3 << shift);
-	tmp |= drvstr << shift;
-
-	__raw_writel(tmp, reg);
-
-	return 0;
-}
-EXPORT_SYMBOL(s5p_gpio_set_drvstr);
-#endif	/* CONFIG_S5P_GPIO_DRVSTR */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/adc-core.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/adc-core.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/adc-core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/adc-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
 /* re-define device name depending on support. */
 static inline void s3c_adc_setname(char *name)
 {
-#ifdef CONFIG_SAMSUNG_DEV_ADC
+#if defined(CONFIG_SAMSUNG_DEV_ADC) || defined(CONFIG_PLAT_S3C24XX)
 	s3c_device_adc.name = name;
 #endif
 }
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/audio-simtec.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/audio-simtec.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/audio-simtec.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/audio-simtec.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,37 @@
+/* arch/arm/plat-samsung/include/plat/audio-simtec.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Simtec Audio support.
+*/
+
+/**
+ * struct s3c24xx_audio_simtec_pdata - platform data for simtec audio
+ * @use_mpllin: Select codec clock from MPLLin
+ * @output_cdclk: Need to output CDCLK to the codec
+ * @have_mic: Set if we have a MIC socket
+ * @have_lout: Set if we have a LineOut socket
+ * @amp_gpio: GPIO pin to enable the AMP
+ * @amp_gain: Option GPIO to control AMP gain
+ */
+struct s3c24xx_audio_simtec_pdata {
+	unsigned int	use_mpllin:1;
+	unsigned int	output_cdclk:1;
+
+	unsigned int	have_mic:1;
+	unsigned int	have_lout:1;
+
+	int		amp_gpio;
+	int		amp_gain[2];
+
+	void	(*startup)(void);
+};
+
+extern int simtec_audio_add(const char *codec_name, bool has_lr_routing,
+			    struct s3c24xx_audio_simtec_pdata *pdata);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/camport.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/camport.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/camport.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/camport.h	2012-01-04 18:55:44.000000000 -0500
@@ -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_SAMSUNG_CAMPORT_H_
+#define __PLAT_SAMSUNG_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 /* __PLAT_SAMSUNG_CAMPORT_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/common-smdk.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/common-smdk.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/common-smdk.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/common-smdk.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,15 @@
+/* linux/arch/arm/plat-samsung/include/plat/common-smdk.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Common code for SMDK2410 and SMDK2440 boards
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+extern void smdk_machine_init(void);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/cpu-freq-core.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/cpu-freq-core.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/cpu-freq-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/cpu-freq-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,293 @@
+/* arch/arm/plat-samsung/include/plat/cpu-freq-core.h
+ *
+ * Copyright (c) 2006-2009 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C CPU frequency scaling support - core support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <plat/cpu-freq.h>
+
+struct seq_file;
+
+#define MAX_BANKS (8)
+#define S3C2412_MAX_IO	(8)
+
+/**
+ * struct s3c2410_iobank_timing - IO bank timings for S3C2410 style timings
+ * @bankcon: The cached version of settings in this structure.
+ * @tacp:
+ * @tacs: Time from address valid to nCS asserted.
+ * @tcos: Time from nCS asserted to nOE or nWE asserted.
+ * @tacc: Time that nOE or nWE is asserted.
+ * @tcoh: Time nCS is held after nOE or nWE are released.
+ * @tcah: Time address is held for after
+ * @nwait_en: Whether nWAIT is enabled for this bank.
+ *
+ * This structure represents the IO timings for a S3C2410 style IO bank
+ * used by the CPU frequency support if it needs to change the settings
+ * of the IO.
+ */
+struct s3c2410_iobank_timing {
+	unsigned long	bankcon;
+	unsigned int	tacp;
+	unsigned int	tacs;
+	unsigned int	tcos;
+	unsigned int	tacc;
+	unsigned int	tcoh;		/* nCS hold afrer nOE/nWE */
+	unsigned int	tcah;		/* Address hold after nCS */
+	unsigned char	nwait_en;	/* nWait enabled for bank. */
+};
+
+/**
+ * struct s3c2412_iobank_timing - io timings for PL092 (S3C2412) style IO
+ * @idcy: The idle cycle time between transactions.
+ * @wstrd: nCS release to end of read cycle.
+ * @wstwr: nCS release to end of write cycle.
+ * @wstoen: nCS assertion to nOE assertion time.
+ * @wstwen: nCS assertion to nWE assertion time.
+ * @wstbrd: Burst ready delay.
+ * @smbidcyr: Register cache for smbidcyr value.
+ * @smbwstrd: Register cache for smbwstrd value.
+ * @smbwstwr: Register cache for smbwstwr value.
+ * @smbwstoen: Register cache for smbwstoen value.
+ * @smbwstwen: Register cache for smbwstwen value.
+ * @smbwstbrd: Register cache for smbwstbrd value.
+ *
+ * Timing information for a IO bank on an S3C2412 or similar system which
+ * uses a PL093 block.
+ */
+struct s3c2412_iobank_timing {
+	unsigned int	idcy;
+	unsigned int	wstrd;
+	unsigned int	wstwr;
+	unsigned int	wstoen;
+	unsigned int	wstwen;
+	unsigned int	wstbrd;
+
+	/* register cache */
+	unsigned char	smbidcyr;
+	unsigned char	smbwstrd;
+	unsigned char	smbwstwr;
+	unsigned char	smbwstoen;
+	unsigned char	smbwstwen;
+	unsigned char	smbwstbrd;
+};
+
+union s3c_iobank {
+	struct s3c2410_iobank_timing	*io_2410;
+	struct s3c2412_iobank_timing	*io_2412;
+};
+
+/**
+ * struct s3c_iotimings - Chip IO timings holder
+ * @bank: The timings for each IO bank.
+ */
+struct s3c_iotimings {
+	union s3c_iobank	bank[MAX_BANKS];
+};
+
+/**
+ * struct s3c_plltab - PLL table information.
+ * @vals: List of PLL values.
+ * @size: Size of the PLL table @vals.
+ */
+struct s3c_plltab {
+	struct s3c_pllval	*vals;
+	int			 size;
+};
+
+/**
+ * struct s3c_cpufreq_config - current cpu frequency configuration
+ * @freq: The current settings for the core clocks.
+ * @max: Maxium settings, derived from core, board and user settings.
+ * @pll: The PLL table entry for the current PLL settings.
+ * @divs: The divisor settings for the core clocks.
+ * @info: The current core driver information.
+ * @board: The information for the board we are running on.
+ * @lock_pll: Set if the PLL settings cannot be changed.
+ *
+ * This is for the core drivers that need to know information about
+ * the current settings and values. It should not be needed by any
+ * device drivers.
+*/
+struct s3c_cpufreq_config {
+	struct s3c_freq		freq;
+	struct s3c_freq		max;
+	struct cpufreq_frequency_table pll;
+	struct s3c_clkdivs	divs;
+	struct s3c_cpufreq_info *info;	/* for core, not drivers */
+	struct s3c_cpufreq_board *board;
+
+	unsigned int	lock_pll:1;
+};
+
+/**
+ * struct s3c_cpufreq_info - Information for the CPU frequency driver.
+ * @name: The name of this implementation.
+ * @max: The maximum frequencies for the system.
+ * @latency: Transition latency to give to cpufreq.
+ * @locktime_m: The lock-time in uS for the MPLL.
+ * @locktime_u: The lock-time in uS for the UPLL.
+ * @locttime_bits: The number of bits each LOCKTIME field.
+ * @need_pll: Set if this driver needs to change the PLL values to achieve
+ *	any frequency changes. This is really only need by devices like the
+ *	S3C2410 where there is no or limited divider between the PLL and the
+ *	ARMCLK.
+ * @resume_clocks: Update the clocks on resume.
+ * @get_iotiming: Get the current IO timing data, mainly for use at start.
+ * @set_iotiming: Update the IO timings from the cached copies calculated
+ *	from the @calc_iotiming entry when changing the frequency.
+ * @calc_iotiming: Calculate and update the cached copies of the IO timings
+ *	from the newly calculated frequencies.
+ * @calc_freqtable: Calculate (fill in) the given frequency table from the
+ *	current frequency configuration. If the table passed in is NULL,
+ *	then the return is the number of elements to be filled for allocation
+ *	of the table.
+ * @set_refresh: Set the memory refresh configuration.
+ * @set_fvco: Set the PLL frequencies.
+ * @set_divs: Update the clock divisors.
+ * @calc_divs: Calculate the clock divisors.
+ */
+struct s3c_cpufreq_info {
+	const char		*name;
+	struct s3c_freq		max;
+
+	unsigned int		latency;
+
+	unsigned int		locktime_m;
+	unsigned int		locktime_u;
+	unsigned char		locktime_bits;
+
+	unsigned int		need_pll:1;
+
+	/* driver routines */
+
+	void		(*resume_clocks)(void);
+
+	int		(*get_iotiming)(struct s3c_cpufreq_config *cfg,
+					struct s3c_iotimings *timings);
+
+	void		(*set_iotiming)(struct s3c_cpufreq_config *cfg,
+					struct s3c_iotimings *timings);
+
+	int		(*calc_iotiming)(struct s3c_cpufreq_config *cfg,
+					 struct s3c_iotimings *timings);
+
+	int		(*calc_freqtable)(struct s3c_cpufreq_config *cfg,
+					  struct cpufreq_frequency_table *t,
+					  size_t table_size);
+
+	void		(*debug_io_show)(struct seq_file *seq,
+					 struct s3c_cpufreq_config *cfg,
+					 union s3c_iobank *iob);
+
+	void		(*set_refresh)(struct s3c_cpufreq_config *cfg);
+	void		(*set_fvco)(struct s3c_cpufreq_config *cfg);
+	void		(*set_divs)(struct s3c_cpufreq_config *cfg);
+	int		(*calc_divs)(struct s3c_cpufreq_config *cfg);
+};
+
+extern int s3c_cpufreq_register(struct s3c_cpufreq_info *info);
+
+extern int s3c_plltab_register(struct cpufreq_frequency_table *plls,
+			       unsigned int plls_no);
+
+/* exports and utilities for debugfs */
+extern struct s3c_cpufreq_config *s3c_cpufreq_getconfig(void);
+extern struct s3c_iotimings *s3c_cpufreq_getiotimings(void);
+
+#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUGFS
+#define s3c_cpufreq_debugfs_call(x) x
+#else
+#define s3c_cpufreq_debugfs_call(x) NULL
+#endif
+
+/* Useful utility functions. */
+
+extern struct clk *s3c_cpufreq_clk_get(struct device *, const char *);
+
+/* S3C2410 and compatible exported functions */
+
+extern void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg);
+extern void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg);
+
+#ifdef CONFIG_S3C2410_IOTIMING
+extern void s3c2410_iotiming_debugfs(struct seq_file *seq,
+				     struct s3c_cpufreq_config *cfg,
+				     union s3c_iobank *iob);
+
+extern int s3c2410_iotiming_calc(struct s3c_cpufreq_config *cfg,
+				 struct s3c_iotimings *iot);
+
+extern int s3c2410_iotiming_get(struct s3c_cpufreq_config *cfg,
+				struct s3c_iotimings *timings);
+
+extern void s3c2410_iotiming_set(struct s3c_cpufreq_config *cfg,
+				 struct s3c_iotimings *iot);
+#else
+#define s3c2410_iotiming_debugfs NULL
+#define s3c2410_iotiming_calc NULL
+#define s3c2410_iotiming_get NULL
+#define s3c2410_iotiming_set NULL
+#endif /* CONFIG_S3C2410_IOTIMING */
+
+/* S3C2412 compatible routines */
+
+#ifdef CONFIG_S3C2412_IOTIMING
+extern void s3c2412_iotiming_debugfs(struct seq_file *seq,
+				     struct s3c_cpufreq_config *cfg,
+				     union s3c_iobank *iob);
+
+extern int s3c2412_iotiming_get(struct s3c_cpufreq_config *cfg,
+				struct s3c_iotimings *timings);
+
+extern int s3c2412_iotiming_calc(struct s3c_cpufreq_config *cfg,
+				 struct s3c_iotimings *iot);
+
+extern void s3c2412_iotiming_set(struct s3c_cpufreq_config *cfg,
+				 struct s3c_iotimings *iot);
+#else
+#define s3c2412_iotiming_debugfs NULL
+#define s3c2412_iotiming_calc NULL
+#define s3c2412_iotiming_get NULL
+#define s3c2412_iotiming_set NULL
+#endif /* CONFIG_S3C2412_IOTIMING */
+
+#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUG
+#define s3c_freq_dbg(x...) printk(KERN_INFO x)
+#else
+#define s3c_freq_dbg(x...) do { if (0) printk(x); } while (0)
+#endif /* CONFIG_CPU_FREQ_S3C24XX_DEBUG */
+
+#ifdef CONFIG_CPU_FREQ_S3C24XX_IODEBUG
+#define s3c_freq_iodbg(x...) printk(KERN_INFO x)
+#else
+#define s3c_freq_iodbg(x...) do { if (0) printk(x); } while (0)
+#endif /* CONFIG_CPU_FREQ_S3C24XX_IODEBUG */
+
+static inline int s3c_cpufreq_addfreq(struct cpufreq_frequency_table *table,
+				      int index, size_t table_size,
+				      unsigned int freq)
+{
+	if (index < 0)
+		return index;
+
+	if (table) {
+		if (index >= table_size)
+			return -ENOMEM;
+
+		s3c_freq_dbg("%s: { %d = %u kHz }\n",
+			     __func__, index, freq);
+
+		table[index].index = index;
+		table[index].frequency = freq;
+	}
+
+	return index + 1;
+}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/cpu.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/cpu.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/cpu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/cpu.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,9 +1,12 @@
 /* linux/arch/arm/plat-samsung/include/plat/cpu.h
  *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
  * Copyright (c) 2004-2005 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * Header file for S3C24XX CPU support
+ * Header file for Samsung 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
@@ -15,6 +18,108 @@
 #ifndef __SAMSUNG_PLAT_CPU_H
 #define __SAMSUNG_PLAT_CPU_H
 
+extern unsigned long samsung_cpu_id;
+
+#define S3C24XX_CPU_ID		0x32400000
+#define S3C24XX_CPU_MASK	0xFFF00000
+
+#define S3C6400_CPU_ID		0x36400000
+#define S3C6410_CPU_ID		0x36410000
+#define S3C64XX_CPU_MASK	0xFFFFF000
+
+#define S5P6440_CPU_ID		0x56440000
+#define S5P6450_CPU_ID		0x36450000
+#define S5P64XX_CPU_MASK	0xFFFFF000
+
+#define S5PC100_CPU_ID		0x43100000
+#define S5PC100_CPU_MASK	0xFFFFF000
+
+#define S5PV210_CPU_ID		0x43110000
+#define S5PV210_CPU_MASK	0xFFFFF000
+
+#define EXYNOS4210_CPU_ID	0x43210000
+#define EXYNOS4212_CPU_ID	0x43220000
+#define EXYNOS4412_CPU_ID	0xE4412200
+#define EXYNOS4_CPU_MASK	0xFFFE0000
+
+#define IS_SAMSUNG_CPU(name, id, mask)		\
+static inline int is_samsung_##name(void)	\
+{						\
+	return ((samsung_cpu_id & mask) == (id & mask));	\
+}
+
+IS_SAMSUNG_CPU(s3c24xx, S3C24XX_CPU_ID, S3C24XX_CPU_MASK)
+IS_SAMSUNG_CPU(s3c6400, S3C6400_CPU_ID, S3C64XX_CPU_MASK)
+IS_SAMSUNG_CPU(s3c6410, S3C6410_CPU_ID, S3C64XX_CPU_MASK)
+IS_SAMSUNG_CPU(s5p6440, S5P6440_CPU_ID, S5P64XX_CPU_MASK)
+IS_SAMSUNG_CPU(s5p6450, S5P6450_CPU_ID, S5P64XX_CPU_MASK)
+IS_SAMSUNG_CPU(s5pc100, S5PC100_CPU_ID, S5PC100_CPU_MASK)
+IS_SAMSUNG_CPU(s5pv210, S5PV210_CPU_ID, S5PV210_CPU_MASK)
+IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK)
+IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK)
+IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK)
+
+#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \
+    defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2440) || \
+    defined(CONFIG_CPU_S3C2442) || defined(CONFIG_CPU_S3C244X) || \
+    defined(CONFIG_CPU_S3C2443)
+# define soc_is_s3c24xx()	is_samsung_s3c24xx()
+#else
+# define soc_is_s3c24xx()	0
+#endif
+
+#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
+# define soc_is_s3c64xx()	(is_samsung_s3c6400() || is_samsung_s3c6410())
+#else
+# define soc_is_s3c64xx()	0
+#endif
+
+#if defined(CONFIG_CPU_S5P6440)
+# define soc_is_s5p6440()	is_samsung_s5p6440()
+#else
+# define soc_is_s5p6440()	0
+#endif
+
+#if defined(CONFIG_CPU_S5P6450)
+# define soc_is_s5p6450()	is_samsung_s5p6450()
+#else
+# define soc_is_s5p6450()	0
+#endif
+
+#if defined(CONFIG_CPU_S5PC100)
+# define soc_is_s5pc100()	is_samsung_s5pc100()
+#else
+# define soc_is_s5pc100()	0
+#endif
+
+#if defined(CONFIG_CPU_S5PV210)
+# define soc_is_s5pv210()	is_samsung_s5pv210()
+#else
+# define soc_is_s5pv210()	0
+#endif
+
+#if defined(CONFIG_CPU_EXYNOS4210)
+# define soc_is_exynos4210()	is_samsung_exynos4210()
+#else
+# define soc_is_exynos4210()	0
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS4212)
+# define soc_is_exynos4212()	is_samsung_exynos4212()
+#else
+# define soc_is_exynos4212()	0
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS4412)
+# define soc_is_exynos4412()	is_samsung_exynos4412()
+#else
+# define soc_is_exynos4412()	0
+#endif
+
+#define EXYNOS4210_REV_0	(0x0)
+#define EXYNOS4210_REV_1_0	(0x10)
+#define EXYNOS4210_REV_1_1	(0x11)
+
 #define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
 
 #ifndef MHZ
@@ -55,6 +160,12 @@
 extern void s5p_init_io(struct map_desc *mach_desc,
 			int size, void __iomem *cpuid_addr);
 
+extern void s3c24xx_init_cpu(void);
+extern void s3c64xx_init_cpu(void);
+extern void s5p_init_cpu(void __iomem *cpuid_addr);
+
+extern unsigned int samsung_rev(void);
+
 extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 
 extern void s3c24xx_init_clocks(int xtal);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/devs.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/devs.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/devs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/devs.h	2012-01-04 18:55:44.000000000 -0500
@@ -30,30 +30,24 @@
 extern struct platform_device *s3c24xx_uart_devs[];
 extern struct platform_device *s3c24xx_uart_src[];
 
-extern struct platform_device s3c_device_timer[];
-
+extern struct platform_device s3c64xx_device_ac97;
 extern struct platform_device s3c64xx_device_iis0;
 extern struct platform_device s3c64xx_device_iis1;
 extern struct platform_device s3c64xx_device_iisv4;
-
-extern struct platform_device s3c64xx_device_spi0;
-extern struct platform_device s3c64xx_device_spi1;
-
-extern struct platform_device samsung_asoc_dma;
-extern struct platform_device samsung_asoc_idma;
-
+extern struct platform_device s3c64xx_device_onenand1;
 extern struct platform_device s3c64xx_device_pcm0;
 extern struct platform_device s3c64xx_device_pcm1;
+extern struct platform_device s3c64xx_device_spi0;
+extern struct platform_device s3c64xx_device_spi1;
 
-extern struct platform_device s3c64xx_device_ac97;
-
-extern struct platform_device s3c_device_ts;
-
+extern struct platform_device s3c_device_adc;
+extern struct platform_device s3c_device_cfcon;
 extern struct platform_device s3c_device_fb;
-extern struct platform_device s5p_device_fimd0;
-extern struct platform_device s3c_device_ohci;
-extern struct platform_device s3c_device_lcd;
-extern struct platform_device s3c_device_wdt;
+extern struct platform_device s3c_device_hwmon;
+extern struct platform_device s3c_device_hsmmc0;
+extern struct platform_device s3c_device_hsmmc1;
+extern struct platform_device s3c_device_hsmmc2;
+extern struct platform_device s3c_device_hsmmc3;
 extern struct platform_device s3c_device_i2c0;
 extern struct platform_device s3c_device_i2c1;
 extern struct platform_device s3c_device_i2c2;
@@ -62,93 +56,90 @@
 extern struct platform_device s3c_device_i2c5;
 extern struct platform_device s3c_device_i2c6;
 extern struct platform_device s3c_device_i2c7;
+extern struct platform_device s3c_device_iis;
+extern struct platform_device s3c_device_lcd;
+extern struct platform_device s3c_device_nand;
+extern struct platform_device s3c_device_ohci;
+extern struct platform_device s3c_device_onenand;
 extern struct platform_device s3c_device_rtc;
-extern struct platform_device s3c_device_adc;
 extern struct platform_device s3c_device_sdi;
-extern struct platform_device s3c_device_iis;
-extern struct platform_device s3c_device_hwmon;
-extern struct platform_device s3c_device_hsmmc0;
-extern struct platform_device s3c_device_hsmmc1;
-extern struct platform_device s3c_device_hsmmc2;
-extern struct platform_device s3c_device_hsmmc3;
-extern struct platform_device s3c_device_cfcon;
-
 extern struct platform_device s3c_device_spi0;
 extern struct platform_device s3c_device_spi1;
-
-extern struct platform_device s5pc100_device_spi0;
-extern struct platform_device s5pc100_device_spi1;
-extern struct platform_device s5pc100_device_spi2;
-extern struct platform_device s5pv210_device_spi0;
-extern struct platform_device s5pv210_device_spi1;
-extern struct platform_device s5p64x0_device_spi0;
-extern struct platform_device s5p64x0_device_spi1;
-
-extern struct platform_device s3c_device_hwmon;
-
-extern struct platform_device s3c_device_nand;
-extern struct platform_device s3c_device_onenand;
-extern struct platform_device s3c64xx_device_onenand1;
-extern struct platform_device s5p_device_onenand;
-
+extern struct platform_device s3c_device_ts;
+extern struct platform_device s3c_device_timer[];
 extern struct platform_device s3c_device_usbgadget;
-extern struct platform_device s3c_device_usb_hsudc;
 extern struct platform_device s3c_device_usb_hsotg;
+extern struct platform_device s3c_device_usb_hsudc;
+extern struct platform_device s3c_device_wdt;
 
-extern struct platform_device s5pv210_device_ac97;
-extern struct platform_device s5pv210_device_pcm0;
-extern struct platform_device s5pv210_device_pcm1;
-extern struct platform_device s5pv210_device_pcm2;
-extern struct platform_device s5pv210_device_iis0;
-extern struct platform_device s5pv210_device_iis1;
-extern struct platform_device s5pv210_device_iis2;
-extern struct platform_device s5pv210_device_spdif;
-
-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 exynos4_device_dwmci;
+extern struct platform_device s5p_device_ehci;
+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_fimc_md;
+extern struct platform_device s5p_device_fimd0;
+extern struct platform_device s5p_device_hdmi;
+extern struct platform_device s5p_device_i2c_hdmiphy;
+extern struct platform_device s5p_device_mfc;
+extern struct platform_device s5p_device_mfc_l;
+extern struct platform_device s5p_device_mfc_r;
+extern struct platform_device s5p_device_mipi_csis0;
+extern struct platform_device s5p_device_mipi_csis1;
+extern struct platform_device s5p_device_mixer;
+extern struct platform_device s5p_device_onenand;
+extern struct platform_device s5p_device_sdo;
 
-extern struct platform_device s5p6440_device_pcm;
 extern struct platform_device s5p6440_device_iis;
+extern struct platform_device s5p6440_device_pcm;
 
 extern struct platform_device s5p6450_device_iis0;
 extern struct platform_device s5p6450_device_iis1;
 extern struct platform_device s5p6450_device_iis2;
 extern struct platform_device s5p6450_device_pcm0;
 
+extern struct platform_device s5p64x0_device_spi0;
+extern struct platform_device s5p64x0_device_spi1;
+
 extern struct platform_device s5pc100_device_ac97;
-extern struct platform_device s5pc100_device_pcm0;
-extern struct platform_device s5pc100_device_pcm1;
 extern struct platform_device s5pc100_device_iis0;
 extern struct platform_device s5pc100_device_iis1;
 extern struct platform_device s5pc100_device_iis2;
+extern struct platform_device s5pc100_device_pcm0;
+extern struct platform_device s5pc100_device_pcm1;
 extern struct platform_device s5pc100_device_spdif;
+extern struct platform_device s5pc100_device_spi0;
+extern struct platform_device s5pc100_device_spi1;
+extern struct platform_device s5pc100_device_spi2;
 
-extern struct platform_device samsung_device_keypad;
-
-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_mfc;
-extern struct platform_device s5p_device_mfc_l;
-extern struct platform_device s5p_device_mfc_r;
-extern struct platform_device s5p_device_mipi_csis0;
-extern struct platform_device s5p_device_mipi_csis1;
-
-extern struct platform_device s5p_device_ehci;
+extern struct platform_device s5pv210_device_ac97;
+extern struct platform_device s5pv210_device_iis0;
+extern struct platform_device s5pv210_device_iis1;
+extern struct platform_device s5pv210_device_iis2;
+extern struct platform_device s5pv210_device_pcm0;
+extern struct platform_device s5pv210_device_pcm1;
+extern struct platform_device s5pv210_device_pcm2;
+extern struct platform_device s5pv210_device_spdif;
+extern struct platform_device s5pv210_device_spi0;
+extern struct platform_device s5pv210_device_spi1;
 
+extern struct platform_device exynos4_device_ac97;
+extern struct platform_device exynos4_device_ahci;
+extern struct platform_device exynos4_device_dwmci;
+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_pcm0;
+extern struct platform_device exynos4_device_pcm1;
+extern struct platform_device exynos4_device_pcm2;
+extern struct platform_device exynos4_device_pd[];
+extern struct platform_device exynos4_device_spdif;
 extern struct platform_device exynos4_device_sysmmu;
 
+extern struct platform_device samsung_asoc_dma;
+extern struct platform_device samsung_asoc_idma;
+extern struct platform_device samsung_device_keypad;
+
 /* s3c2440 specific devices */
 
 #ifdef CONFIG_CPU_S3C2440
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/dma.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/dma.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/dma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -10,17 +10,14 @@
  * published by the Free Software Foundation.
 */
 
+#include <linux/dma-mapping.h>
+
 enum s3c2410_dma_buffresult {
 	S3C2410_RES_OK,
 	S3C2410_RES_ERR,
 	S3C2410_RES_ABORT
 };
 
-enum s3c2410_dmasrc {
-	S3C2410_DMASRC_HW,		/* source is memory */
-	S3C2410_DMASRC_MEM		/* source is hardware */
-};
-
 /* enum s3c2410_chan_op
  *
  * operation codes passed to the DMA code by the user, and also used
@@ -112,7 +109,7 @@
 */
 
 extern int s3c2410_dma_devconfig(enum dma_ch channel,
-		enum s3c2410_dmasrc source, unsigned long devaddr);
+		enum dma_data_direction source, unsigned long devaddr);
 
 /* s3c2410_dma_getposition
  *
@@ -126,3 +123,4 @@
 extern int s3c2410_dma_set_buffdone_fn(enum dma_ch, s3c2410_dma_cbfn_t rtn);
 
 
+#include <plat/dma-ops.h>
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/dma-ops.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/dma-ops.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/dma-ops.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/dma-ops.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,63 @@
+/* arch/arm/plat-samsung/include/plat/dma-ops.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung DMA support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __SAMSUNG_DMA_OPS_H_
+#define __SAMSUNG_DMA_OPS_H_ __FILE__
+
+#include <linux/dmaengine.h>
+
+struct samsung_dma_prep_info {
+	enum dma_transaction_type cap;
+	enum dma_data_direction direction;
+	dma_addr_t buf;
+	unsigned long period;
+	unsigned long len;
+	void (*fp)(void *data);
+	void *fp_param;
+};
+
+struct samsung_dma_info {
+	enum dma_transaction_type cap;
+	enum dma_data_direction direction;
+	enum dma_slave_buswidth width;
+	dma_addr_t fifo;
+	struct s3c2410_dma_client *client;
+};
+
+struct samsung_dma_ops {
+	unsigned (*request)(enum dma_ch ch, struct samsung_dma_info *info);
+	int (*release)(unsigned ch, struct s3c2410_dma_client *client);
+	int (*prepare)(unsigned ch, struct samsung_dma_prep_info *info);
+	int (*trigger)(unsigned ch);
+	int (*started)(unsigned ch);
+	int (*flush)(unsigned ch);
+	int (*stop)(unsigned ch);
+};
+
+extern void *samsung_dmadev_get_ops(void);
+extern void *s3c_dma_get_ops(void);
+
+static inline void *__samsung_dma_get_ops(void)
+{
+	if (samsung_dma_is_dmadev())
+		return samsung_dmadev_get_ops();
+	else
+		return s3c_dma_get_ops();
+}
+
+/*
+ * samsung_dma_get_ops
+ * get the set of samsung dma operations
+ */
+#define samsung_dma_get_ops() __samsung_dma_get_ops()
+
+#endif /* __SAMSUNG_DMA_OPS_H_ */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/dma-pl330.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/dma-pl330.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/dma-pl330.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/dma-pl330.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+#ifndef __DMA_PL330_H_
+#define __DMA_PL330_H_ __FILE__
+
+/*
+ * PL330 can assign any channel to communicate with
+ * any of the peripherals attched to the DMAC.
+ * For the sake of consistency across client drivers,
+ * We keep the channel names unchanged and only add
+ * missing peripherals are added.
+ * Order is not important since DMA PL330 API driver
+ * use these just as IDs.
+ */
+enum dma_ch {
+	DMACH_UART0_RX,
+	DMACH_UART0_TX,
+	DMACH_UART1_RX,
+	DMACH_UART1_TX,
+	DMACH_UART2_RX,
+	DMACH_UART2_TX,
+	DMACH_UART3_RX,
+	DMACH_UART3_TX,
+	DMACH_UART4_RX,
+	DMACH_UART4_TX,
+	DMACH_UART5_RX,
+	DMACH_UART5_TX,
+	DMACH_USI_RX,
+	DMACH_USI_TX,
+	DMACH_IRDA,
+	DMACH_I2S0_RX,
+	DMACH_I2S0_TX,
+	DMACH_I2S0S_TX,
+	DMACH_I2S1_RX,
+	DMACH_I2S1_TX,
+	DMACH_I2S2_RX,
+	DMACH_I2S2_TX,
+	DMACH_SPI0_RX,
+	DMACH_SPI0_TX,
+	DMACH_SPI1_RX,
+	DMACH_SPI1_TX,
+	DMACH_SPI2_RX,
+	DMACH_SPI2_TX,
+	DMACH_AC97_MICIN,
+	DMACH_AC97_PCMIN,
+	DMACH_AC97_PCMOUT,
+	DMACH_EXTERNAL,
+	DMACH_PWM,
+	DMACH_SPDIF,
+	DMACH_HSI_RX,
+	DMACH_HSI_TX,
+	DMACH_PCM0_TX,
+	DMACH_PCM0_RX,
+	DMACH_PCM1_TX,
+	DMACH_PCM1_RX,
+	DMACH_PCM2_TX,
+	DMACH_PCM2_RX,
+	DMACH_MSM_REQ3,
+	DMACH_MSM_REQ2,
+	DMACH_MSM_REQ1,
+	DMACH_MSM_REQ0,
+	DMACH_SLIMBUS0_RX,
+	DMACH_SLIMBUS0_TX,
+	DMACH_SLIMBUS0AUX_RX,
+	DMACH_SLIMBUS0AUX_TX,
+	DMACH_SLIMBUS1_RX,
+	DMACH_SLIMBUS1_TX,
+	DMACH_SLIMBUS2_RX,
+	DMACH_SLIMBUS2_TX,
+	DMACH_SLIMBUS3_RX,
+	DMACH_SLIMBUS3_TX,
+	DMACH_SLIMBUS4_RX,
+	DMACH_SLIMBUS4_TX,
+	DMACH_SLIMBUS5_RX,
+	DMACH_SLIMBUS5_TX,
+	/* END Marker, also used to denote a reserved channel */
+	DMACH_MAX,
+};
+
+struct s3c2410_dma_client {
+	char	*name;
+};
+
+static inline bool samsung_dma_has_circular(void)
+{
+	return true;
+}
+
+static inline bool samsung_dma_is_dmadev(void)
+{
+	return true;
+}
+
+#include <plat/dma-ops.h>
+
+#endif	/* __DMA_PL330_H_ */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -18,11 +18,6 @@
 #define DMA_CH_VALID		(1<<31)
 #define DMA_CH_NEVER		(1<<30)
 
-struct s3c24xx_dma_addr {
-	unsigned long		from;
-	unsigned long		to;
-};
-
 /* struct s3c24xx_dma_map
  *
  * this holds the mapping information for the channel selected
@@ -31,7 +26,6 @@
 
 struct s3c24xx_dma_map {
 	const char		*name;
-	struct s3c24xx_dma_addr  hw_addr;
 
 	unsigned long		 channels[S3C_DMA_CHANNELS];
 	unsigned long		 channels_rx[S3C_DMA_CHANNELS];
@@ -47,7 +41,7 @@
 
 	void	(*direction)(struct s3c2410_dma_chan *chan,
 			     struct s3c24xx_dma_map *map,
-			     enum s3c2410_dmasrc dir);
+			     enum dma_data_direction dir);
 };
 
 extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/ehci.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/ehci.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/ehci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/ehci.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef __PLAT_SAMSUNG_EHCI_H
+#define __PLAT_SAMSUNG_EHCI_H __FILE__
+
+struct s5p_ehci_platdata {
+	int (*phy_init)(struct platform_device *pdev, int type);
+	int (*phy_exit)(struct platform_device *pdev, int type);
+};
+
+extern void s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd);
+
+#endif /* __PLAT_SAMSUNG_EHCI_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/exynos4.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/exynos4.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/exynos4.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/exynos4.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/* linux/arch/arm/plat-samsung/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 exynos4210_register_clocks(void);
+extern void exynos4212_register_clocks(void);
+extern void exynos4_setup_clocks(void);
+
+#ifdef CONFIG_ARCH_EXYNOS
+extern  int exynos_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 exynos_init NULL
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/fb.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/fb.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/fb.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/fb.h	2012-01-04 18:55:44.000000000 -0500
@@ -109,4 +109,11 @@
  */
 extern void exynos4_fimd0_gpio_setup_24bpp(void);
 
+/**
+ * s5p64x0_fb_gpio_setup_24bpp() - S5P6440/S5P6450 setup function for 24bpp LCD
+ *
+ * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
+ */
+extern void s5p64x0_fb_gpio_setup_24bpp(void);
+
 #endif /* __PLAT_S3C_FB_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/fb-s3c2410.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/fb-s3c2410.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/fb-s3c2410.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/fb-s3c2410.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,72 @@
+/* arch/arm/plat-samsung/include/plat/fb-s3c2410.h
+ *
+ * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ * Inspired by pxafb.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_PLAT_FB_S3C2410_H
+#define __ASM_PLAT_FB_S3C2410_H __FILE__
+
+struct s3c2410fb_hw {
+	unsigned long	lcdcon1;
+	unsigned long	lcdcon2;
+	unsigned long	lcdcon3;
+	unsigned long	lcdcon4;
+	unsigned long	lcdcon5;
+};
+
+/* LCD description */
+struct s3c2410fb_display {
+	/* LCD type */
+	unsigned type;
+
+	/* Screen size */
+	unsigned short width;
+	unsigned short height;
+
+	/* Screen info */
+	unsigned short xres;
+	unsigned short yres;
+	unsigned short bpp;
+
+	unsigned pixclock;		/* pixclock in picoseconds */
+	unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */
+	unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
+	unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */
+	unsigned short upper_margin;	/* value in lines (TFT) or 0 (STN) */
+	unsigned short lower_margin;	/* value in lines (TFT) or 0 (STN) */
+	unsigned short vsync_len;	/* value in lines (TFT) or 0 (STN) */
+
+	/* lcd configuration registers */
+	unsigned long	lcdcon5;
+};
+
+struct s3c2410fb_mach_info {
+
+	struct s3c2410fb_display *displays;	/* attached diplays info */
+	unsigned num_displays;			/* number of defined displays */
+	unsigned default_display;
+
+	/* GPIOs */
+
+	unsigned long	gpcup;
+	unsigned long	gpcup_mask;
+	unsigned long	gpccon;
+	unsigned long	gpccon_mask;
+	unsigned long	gpdup;
+	unsigned long	gpdup_mask;
+	unsigned long	gpdcon;
+	unsigned long	gpdcon_mask;
+
+	/* lpc3600 control register */
+	unsigned long	lpcsel;
+};
+
+extern void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *);
+
+#endif /* __ASM_PLAT_FB_S3C2410_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/fiq.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/fiq.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/fiq.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/fiq.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,13 @@
+/* linux/arch/arm/plat-samsung/include/plat/fiq.h
+ *
+ * Copyright (c) 2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C24XX CPU FIQ support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+extern int s3c24xx_set_fiq(unsigned int irq, bool on);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg.h	2012-01-04 18:55:44.000000000 -0500
@@ -24,14 +24,16 @@
 #ifndef __PLAT_GPIO_CFG_H
 #define __PLAT_GPIO_CFG_H __FILE__
 
-typedef unsigned int __bitwise__ s3c_gpio_pull_t;
+#include<linux/types.h>
+
+typedef unsigned int __bitwise__ samsung_gpio_pull_t;
 typedef unsigned int __bitwise__ s5p_gpio_drvstr_t;
 
 /* forward declaration if gpio-core.h hasn't been included */
-struct s3c_gpio_chip;
+struct samsung_gpio_chip;
 
 /**
- * struct s3c_gpio_cfg GPIO configuration
+ * struct samsung_gpio_cfg GPIO configuration
  * @cfg_eint: Configuration setting when used for external interrupt source
  * @get_pull: Read the current pull configuration for the GPIO
  * @set_pull: Set the current pull configuraiton for the GPIO
@@ -44,20 +46,20 @@
  * per-bank configuration information that other systems such as the
  * external interrupt code will need.
  *
- * @sa s3c_gpio_cfgpin
+ * @sa samsung_gpio_cfgpin
  * @sa s3c_gpio_getcfg
  * @sa s3c_gpio_setpull
  * @sa s3c_gpio_getpull
  */
-struct s3c_gpio_cfg {
+struct samsung_gpio_cfg {
 	unsigned int	cfg_eint;
 
-	s3c_gpio_pull_t	(*get_pull)(struct s3c_gpio_chip *chip, unsigned offs);
-	int		(*set_pull)(struct s3c_gpio_chip *chip, unsigned offs,
-				    s3c_gpio_pull_t pull);
+	samsung_gpio_pull_t	(*get_pull)(struct samsung_gpio_chip *chip, unsigned offs);
+	int		(*set_pull)(struct samsung_gpio_chip *chip, unsigned offs,
+				    samsung_gpio_pull_t pull);
 
-	unsigned (*get_config)(struct s3c_gpio_chip *chip, unsigned offs);
-	int	 (*set_config)(struct s3c_gpio_chip *chip, unsigned offs,
+	unsigned (*get_config)(struct samsung_gpio_chip *chip, unsigned offs);
+	int	 (*set_config)(struct samsung_gpio_chip *chip, unsigned offs,
 			       unsigned config);
 };
 
@@ -69,7 +71,7 @@
 #define S3C_GPIO_OUTPUT	(S3C_GPIO_SPECIAL(1))
 #define S3C_GPIO_SFN(x)	(S3C_GPIO_SPECIAL(x))
 
-#define s3c_gpio_is_cfg_special(_cfg) \
+#define samsung_gpio_is_cfg_special(_cfg) \
 	(((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK)
 
 /**
@@ -128,9 +130,9 @@
  * 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)
-#define S3C_GPIO_PULL_DOWN	((__force s3c_gpio_pull_t)0x01)
-#define S3C_GPIO_PULL_UP	((__force s3c_gpio_pull_t)0x02)
+#define S3C_GPIO_PULL_NONE	((__force samsung_gpio_pull_t)0x00)
+#define S3C_GPIO_PULL_DOWN	((__force samsung_gpio_pull_t)0x01)
+#define S3C_GPIO_PULL_UP	((__force samsung_gpio_pull_t)0x02)
 
 /**
  * s3c_gpio_setpull() - set the state of a gpio pin pull resistor
@@ -143,7 +145,7 @@
  *
  * @pull is one of S3C_GPIO_PULL_NONE, S3C_GPIO_PULL_DOWN or S3C_GPIO_PULL_UP.
 */
-extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull);
+extern int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull);
 
 /**
  * s3c_gpio_getpull() - get the pull resistor state of a gpio pin
@@ -151,7 +153,7 @@
  *
  * Read the pull resistor value for the specified pin.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
+extern samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
 
 /* configure `all` aspects of an gpio */
 
@@ -170,7 +172,7 @@
  * @sa s3c_gpio_cfgpin_range
  */
 extern int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
-				 unsigned int cfg, s3c_gpio_pull_t pull);
+				 unsigned int cfg, samsung_gpio_pull_t pull);
 
 static inline int s3c_gpio_cfgrange_nopull(unsigned int pin, unsigned int size,
 					   unsigned int cfg)
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,11 +1,11 @@
-/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg-helper.h
+/* linux/arch/arm/plat-samsung/include/plat/gpio-cfg-helper.h
  *
  * Copyright 2008 Openmoko, Inc.
  * Copyright 2008 Simtec Electronics
  *	http://armlinux.simtec.co.uk/
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * S3C Platform - GPIO pin configuration helper definitions
+ * Samsung Platform - GPIO pin configuration helper 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
@@ -24,120 +24,30 @@
  * by disabling interrupts.
 */
 
-static inline int s3c_gpio_do_setcfg(struct s3c_gpio_chip *chip,
-				     unsigned int off, unsigned int config)
+static inline int samsung_gpio_do_setcfg(struct samsung_gpio_chip *chip,
+					 unsigned int off, unsigned int config)
 {
 	return (chip->config->set_config)(chip, off, config);
 }
 
-static inline unsigned s3c_gpio_do_getcfg(struct s3c_gpio_chip *chip,
-					  unsigned int off)
+static inline unsigned samsung_gpio_do_getcfg(struct samsung_gpio_chip *chip,
+					      unsigned int off)
 {
 	return (chip->config->get_config)(chip, off);
 }
 
-static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip,
-				      unsigned int off, s3c_gpio_pull_t pull)
+static inline int samsung_gpio_do_setpull(struct samsung_gpio_chip *chip,
+					  unsigned int off, samsung_gpio_pull_t pull)
 {
 	return (chip->config->set_pull)(chip, off, pull);
 }
 
-static inline s3c_gpio_pull_t s3c_gpio_do_getpull(struct s3c_gpio_chip *chip,
-						  unsigned int off)
+static inline samsung_gpio_pull_t samsung_gpio_do_getpull(struct samsung_gpio_chip *chip,
+							  unsigned int off)
 {
 	return chip->config->get_pull(chip, off);
 }
 
-/**
- * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @cfg: The configuration value to set.
- *
- * This helper deal with the GPIO cases where the control register
- * has two bits of configuration per gpio, which have the following
- * functions:
- *	00 = input
- *	01 = output
- *	1x = special function
-*/
-extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
-				   unsigned int off, unsigned int cfg);
-
-/**
- * s3c_gpio_getcfg_s3c24xx - S3C24XX style GPIO configuration read.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- *
- * The reverse of s3c_gpio_setcfg_s3c24xx(). Will return a value whicg
- * could be directly passed back to s3c_gpio_setcfg_s3c24xx(), from the
- * S3C_GPIO_SPECIAL() macro.
- */
-unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip,
-				     unsigned int off);
-
-/**
- * s3c_gpio_setcfg_s3c24xx_a - S3C24XX style GPIO configuration (Bank A)
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @cfg: The configuration value to set.
- *
- * This helper deal with the GPIO cases where the control register
- * has one bit of configuration for the gpio, where setting the bit
- * means the pin is in special function mode and unset means output.
-*/
-extern int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-				     unsigned int off, unsigned int cfg);
-
-
-/**
- * s3c_gpio_getcfg_s3c24xx_a - S3C24XX style GPIO configuration read (Bank A)
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- *
- * The reverse of s3c_gpio_setcfg_s3c24xx_a() turning an GPIO into a usable
- * GPIO configuration value.
- *
- * @sa s3c_gpio_getcfg_s3c24xx
- * @sa s3c_gpio_getcfg_s3c64xx_4bit
- */
-extern unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-					  unsigned int off);
-
-/**
- * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @cfg: The configuration value to set.
- *
- * This helper deal with the GPIO cases where the control register has 4 bits
- * of control per GPIO, generally in the form of:
- *	0000 = Input
- *	0001 = Output
- *	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
- * each case.
-*/
-extern int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-					unsigned int off, unsigned int cfg);
-
-
-/**
- * s3c_gpio_getcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config read.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- *
- * The reverse of s3c_gpio_setcfg_s3c64xx_4bit(), turning a gpio configuration
- * register setting into a value the software can use, such as could be passed
- * to s3c_gpio_setcfg_s3c64xx_4bit().
- *
- * @sa s3c_gpio_getcfg_s3c24xx
- */
-extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-					     unsigned int off);
-
 /* Pull-{up,down} resistor controls.
  *
  * S3C2410,S3C2440 = Pull-UP,
@@ -147,7 +57,7 @@
  */
 
 /**
- * s3c_gpio_setpull_1up() - Pull configuration for choice of up or none.
+ * s3c24xx_gpio_setpull_1up() - Pull configuration for choice of up or none.
  * @chip: The gpio chip that is being configured.
  * @off: The offset for the GPIO being configured.
  * @param: pull: The pull mode being requested.
@@ -155,11 +65,11 @@
  * This is a helper function for the case where we have GPIOs with one
  * bit configuring the presence of a pull-up resistor.
  */
-extern int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
-				unsigned int off, s3c_gpio_pull_t pull);
+extern int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
+				    unsigned int off, samsung_gpio_pull_t pull);
 
 /**
- * s3c_gpio_setpull_1down() - Pull configuration for choice of down or none
+ * s3c24xx_gpio_setpull_1down() - Pull configuration for choice of down or none
  * @chip: The gpio chip that is being configured
  * @off: The offset for the GPIO being configured
  * @param: pull: The pull mode being requested
@@ -167,11 +77,13 @@
  * This is a helper function for the case where we have GPIOs with one
  * bit configuring the presence of a pull-down resistor.
  */
-extern int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
-				  unsigned int off, s3c_gpio_pull_t pull);
+extern int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
+				      unsigned int off, samsung_gpio_pull_t pull);
 
 /**
- * s3c_gpio_setpull_upown() - Pull configuration for choice of up, down or none
+ * samsung_gpio_setpull_upown() - Pull configuration for choice of up,
+ * down or none
+ *
  * @chip: The gpio chip that is being configured.
  * @off: The offset for the GPIO being configured.
  * @param: pull: The pull mode being requested.
@@ -183,45 +95,46 @@
  *	01 = Pull-up resistor connected
  *	10 = Pull-down resistor connected
  */
-extern int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
-				   unsigned int off, s3c_gpio_pull_t pull);
-
+extern int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
+				       unsigned int off, samsung_gpio_pull_t pull);
 
 /**
- * s3c_gpio_getpull_updown() - Get configuration for choice of up, down or none
+ * samsung_gpio_getpull_updown() - Get configuration for choice of up,
+ * down or none
+ *
  * @chip: The gpio chip that the GPIO pin belongs to
  * @off: The offset to the pin to get the configuration of.
  *
- * This helper function reads the state of the pull-{up,down} resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_upown.
+ * This helper function reads the state of the pull-{up,down} resistor
+ * for the given GPIO in the same case as samsung_gpio_setpull_upown.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
-					       unsigned int off);
+extern samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
+						       unsigned int off);
 
 /**
- * s3c_gpio_getpull_1up() - Get configuration for choice of up or none
+ * s3c24xx_gpio_getpull_1up() - Get configuration for choice of up or none
  * @chip: The gpio chip that the GPIO pin belongs to
  * @off: The offset to the pin to get the configuration of.
  *
  * This helper function reads the state of the pull-up resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_1up.
+ * given GPIO in the same case as s3c24xx_gpio_setpull_1up.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
-					    unsigned int off);
+extern samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
+						    unsigned int off);
 
 /**
- * s3c_gpio_getpull_1down() - Get configuration for choice of down or none
+ * s3c24xx_gpio_getpull_1down() - Get configuration for choice of down or none
  * @chip: The gpio chip that the GPIO pin belongs to
  * @off: The offset to the pin to get the configuration of.
  *
  * This helper function reads the state of the pull-down resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_1down.
+ * given GPIO in the same case as s3c24xx_gpio_setpull_1down.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
-					    unsigned int off);
+extern samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
+						      unsigned int off);
 
 /**
- * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443.
+ * s3c2443_gpio_setpull() - Pull configuration for s3c2443.
  * @chip: The gpio chip that is being configured.
  * @off: The offset for the GPIO being configured.
  * @param: pull: The pull mode being requested.
@@ -233,19 +146,18 @@
  *	10 = Pull-down resistor connected
  *	x1 = No pull up resistor
  */
-extern int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip,
-				    unsigned int off, s3c_gpio_pull_t pull);
+extern int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
+				unsigned int off, samsung_gpio_pull_t pull);
 
 /**
- * s3c_gpio_getpull_s3c2443() - Get configuration for s3c2443 pull resistors
+ * s3c2443_gpio_getpull() - Get configuration for s3c2443 pull resistors
  * @chip: The gpio chip that the GPIO pin belongs to.
  * @off: The offset to the pin to get the configuration of.
  *
  * This helper function reads the state of the pull-{up,down} resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_upown.
+ * given GPIO in the same case as samsung_gpio_setpull_upown.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip,
+extern samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
 						unsigned int off);
 
 #endif /* __PLAT_GPIO_CFG_HELPERS_H */
-
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/gpio-core.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/gpio-core.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/gpio-core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/gpio-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -25,22 +25,22 @@
  * specific code.
 */
 
-struct s3c_gpio_chip;
+struct samsung_gpio_chip;
 
 /**
- * struct s3c_gpio_pm - power management (suspend/resume) information
+ * struct samsung_gpio_pm - power management (suspend/resume) information
  * @save: Routine to save the state of the GPIO block
  * @resume: Routine to resume the GPIO block.
  */
-struct s3c_gpio_pm {
-	void (*save)(struct s3c_gpio_chip *chip);
-	void (*resume)(struct s3c_gpio_chip *chip);
+struct samsung_gpio_pm {
+	void (*save)(struct samsung_gpio_chip *chip);
+	void (*resume)(struct samsung_gpio_chip *chip);
 };
 
-struct s3c_gpio_cfg;
+struct samsung_gpio_cfg;
 
 /**
- * struct s3c_gpio_chip - wrapper for specific implementation of gpio
+ * struct samsung_gpio_chip - wrapper for specific implementation of gpio
  * @chip: The chip structure to be exported via gpiolib.
  * @base: The base pointer to the gpio configuration registers.
  * @group: The group register number for gpio interrupt support.
@@ -60,10 +60,10 @@
  * CPU cores trying to get one lock for different GPIO banks, where each
  * bank of GPIO has its own register space and configuration registers.
  */
-struct s3c_gpio_chip {
+struct samsung_gpio_chip {
 	struct gpio_chip	chip;
-	struct s3c_gpio_cfg	*config;
-	struct s3c_gpio_pm	*pm;
+	struct samsung_gpio_cfg	*config;
+	struct samsung_gpio_pm	*pm;
 	void __iomem		*base;
 	int			irq_base;
 	int			group;
@@ -73,58 +73,11 @@
 #endif
 };
 
-static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
+static inline struct samsung_gpio_chip *to_samsung_gpio(struct gpio_chip *gpc)
 {
-	return container_of(gpc, struct s3c_gpio_chip, chip);
+	return container_of(gpc, struct samsung_gpio_chip, chip);
 }
 
-/** s3c_gpiolib_add() - add the s3c specific version of a gpio_chip.
- * @chip: The chip to register
- *
- * This is a wrapper to gpiochip_add() that takes our specific gpio chip
- * information and makes the necessary alterations for the platform and
- * notes the information for use with the configuration systems and any
- * other parts of the system.
- */
-extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip);
-
-/* CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
- * for use with the configuration calls, and other parts of the s3c gpiolib
- * support code.
- *
- * Not all s3c support code will need this, as some configurations of cpu
- * may only support one or two different configuration options and have an
- * easy gpio to s3c_gpio_chip mapping function. If this is the case, then
- * the machine support file should provide its own s3c_gpiolib_getchip()
- * and any other necessary functions.
- */
-
-/**
- * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
- * @chip: The gpio chip that is being configured.
- * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
- *
- * This helper deal with the GPIO cases where the control register has 4 bits
- * of control per GPIO, generally in the form of:
- * 0000 = Input
- * 0001 = Output
- * 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
- * (samsung_gpiolib_add_4bit2_chips)for each case.
- */
-extern void samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
-					   int nr_chips);
-extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
-					    int nr_chips);
-extern void samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
-					   int nr_chips);
-
-extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip);
-extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip);
-
-
 /**
  * samsung_gpiolib_to_irq - convert gpio pin to irq number
  * @chip: The gpio chip that the pin belongs to.
@@ -136,36 +89,36 @@
 extern int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset);
 
 /* exported for core SoC support to change */
-extern struct s3c_gpio_cfg s3c24xx_gpiocfg_default;
+extern struct samsung_gpio_cfg s3c24xx_gpiocfg_default;
 
 #ifdef CONFIG_S3C_GPIO_TRACK
-extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
+extern struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
 
-static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip)
+static inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int chip)
 {
 	return (chip < S3C_GPIO_END) ? s3c_gpios[chip] : NULL;
 }
 #else
-/* machine specific code should provide s3c_gpiolib_getchip */
+/* machine specific code should provide samsung_gpiolib_getchip */
 
 #include <mach/gpio-track.h>
 
-static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
+static inline void s3c_gpiolib_track(struct samsung_gpio_chip *chip) { }
 #endif
 
 #ifdef CONFIG_PM
-extern struct s3c_gpio_pm s3c_gpio_pm_1bit;
-extern struct s3c_gpio_pm s3c_gpio_pm_2bit;
-extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
+extern struct samsung_gpio_pm samsung_gpio_pm_1bit;
+extern struct samsung_gpio_pm samsung_gpio_pm_2bit;
+extern struct samsung_gpio_pm samsung_gpio_pm_4bit;
 #define __gpio_pm(x) x
 #else
-#define s3c_gpio_pm_1bit NULL
-#define s3c_gpio_pm_2bit NULL
-#define s3c_gpio_pm_4bit NULL
+#define samsung_gpio_pm_1bit NULL
+#define samsung_gpio_pm_2bit NULL
+#define samsung_gpio_pm_4bit NULL
 #define __gpio_pm(x) NULL
 
 #endif /* CONFIG_PM */
 
 /* locking wrappers to deal with multiple access to the same gpio bank */
-#define s3c_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl)
-#define s3c_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl)
+#define samsung_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl)
+#define samsung_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl)
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/gpio-fns.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/gpio-fns.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/gpio-fns.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/gpio-fns.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,98 @@
+/* arch/arm/mach-s3c2410/include/mach/gpio-fns.h
+ *
+ * Copyright (c) 2003-2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - hardware
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __MACH_GPIO_FNS_H
+#define __MACH_GPIO_FNS_H __FILE__
+
+/* These functions are in the to-be-removed category and it is strongly
+ * encouraged not to use these in new code. They will be marked deprecated
+ * very soon.
+ *
+ * Most of the functionality can be either replaced by the gpiocfg calls
+ * for the s3c platform or by the generic GPIOlib API.
+ *
+ * As of 2.6.35-rc, these will be removed, with the few drivers using them
+ * either replaced or given a wrapper until the calls can be removed.
+*/
+
+#include <plat/gpio-cfg.h>
+
+static inline void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int cfg)
+{
+	/* 1:1 mapping between cfgpin and setcfg calls at the moment */
+	s3c_gpio_cfgpin(pin, cfg);
+}
+
+/* external functions for GPIO support
+ *
+ * These allow various different clients to access the same GPIO
+ * registers without conflicting. If your driver only owns the entire
+ * GPIO register, then it is safe to ioremap/__raw_{read|write} to it.
+*/
+
+extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
+
+/* s3c2410_gpio_getirq
+ *
+ * turn the given pin number into the corresponding IRQ number
+ *
+ * returns:
+ *	< 0 = no interrupt for this pin
+ *	>=0 = interrupt number for the pin
+*/
+
+extern int s3c2410_gpio_getirq(unsigned int pin);
+
+/* s3c2410_gpio_irqfilter
+ *
+ * set the irq filtering on the given pin
+ *
+ * on = 0 => disable filtering
+ *      1 => enable filtering
+ *
+ * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
+ *          width of filter (0 through 63)
+ *
+ *
+*/
+
+extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+				  unsigned int config);
+
+/* s3c2410_gpio_pullup
+ *
+ * This call should be replaced with s3c_gpio_setpull().
+ *
+ * As a note, there is currently no distinction between pull-up and pull-down
+ * in the s3c24xx series devices with only an on/off configuration.
+ */
+
+/* s3c2410_gpio_pullup
+ *
+ * configure the pull-up control on the given pin
+ *
+ * to = 1 => disable the pull-up
+ *      0 => enable the pull-up
+ *
+ * eg;
+ *
+ *   s3c2410_gpio_pullup(S3C2410_GPB(0), 0);
+ *   s3c2410_gpio_pullup(S3C2410_GPE(8), 0);
+*/
+
+extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
+
+extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
+
+extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
+
+#endif /* __MACH_GPIO_FNS_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/iic.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/iic.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/iic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/iic.h	2012-01-04 18:55:44.000000000 -0500
@@ -60,6 +60,7 @@
 extern void s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *i2c);
 extern void s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *i2c);
 extern void s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *i2c);
+extern void s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *i2c);
 
 /* defined by architecture to configure gpio */
 extern void s3c_i2c0_cfg_gpio(struct platform_device *dev);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/irq.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/irq.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/irq.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,116 @@
+/* linux/arch/arm/plat-samsung/include/plat/irq.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C24XX CPU IRQ 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 <mach/hardware.h>
+#include <mach/regs-irq.h>
+#include <mach/regs-gpio.h>
+
+#define irqdbf(x...)
+#define irqdbf2(x...)
+
+#define EXTINT_OFF (IRQ_EINT4 - 4)
+
+/* these are exported for arch/arm/mach-* usage */
+extern struct irq_chip s3c_irq_level_chip;
+extern struct irq_chip s3c_irq_chip;
+
+static inline void s3c_irqsub_mask(unsigned int irqno,
+				   unsigned int parentbit,
+				   int subcheck)
+{
+	unsigned long mask;
+	unsigned long submask;
+
+	submask = __raw_readl(S3C2410_INTSUBMSK);
+	mask = __raw_readl(S3C2410_INTMSK);
+
+	submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
+
+	/* check to see if we need to mask the parent IRQ */
+
+	if ((submask  & subcheck) == subcheck)
+		__raw_writel(mask | parentbit, S3C2410_INTMSK);
+
+	/* write back masks */
+	__raw_writel(submask, S3C2410_INTSUBMSK);
+
+}
+
+static inline void s3c_irqsub_unmask(unsigned int irqno,
+				     unsigned int parentbit)
+{
+	unsigned long mask;
+	unsigned long submask;
+
+	submask = __raw_readl(S3C2410_INTSUBMSK);
+	mask = __raw_readl(S3C2410_INTMSK);
+
+	submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
+	mask &= ~parentbit;
+
+	/* write back masks */
+	__raw_writel(submask, S3C2410_INTSUBMSK);
+	__raw_writel(mask, S3C2410_INTMSK);
+}
+
+
+static inline void s3c_irqsub_maskack(unsigned int irqno,
+				      unsigned int parentmask,
+				      unsigned int group)
+{
+	unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
+
+	s3c_irqsub_mask(irqno, parentmask, group);
+
+	__raw_writel(bit, S3C2410_SUBSRCPND);
+
+	/* only ack parent if we've got all the irqs (seems we must
+	 * ack, all and hope that the irq system retriggers ok when
+	 * the interrupt goes off again)
+	 */
+
+	if (1) {
+		__raw_writel(parentmask, S3C2410_SRCPND);
+		__raw_writel(parentmask, S3C2410_INTPND);
+	}
+}
+
+static inline void s3c_irqsub_ack(unsigned int irqno,
+				  unsigned int parentmask,
+				  unsigned int group)
+{
+	unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
+
+	__raw_writel(bit, S3C2410_SUBSRCPND);
+
+	/* only ack parent if we've got all the irqs (seems we must
+	 * ack, all and hope that the irq system retriggers ok when
+	 * the interrupt goes off again)
+	 */
+
+	if (1) {
+		__raw_writel(parentmask, S3C2410_SRCPND);
+		__raw_writel(parentmask, S3C2410_INTPND);
+	}
+}
+
+/* exported for use in arch/arm/mach-s3c2410 */
+
+#ifdef CONFIG_PM
+extern int s3c_irq_wake(struct irq_data *data, unsigned int state);
+#else
+#define s3c_irq_wake NULL
+#endif
+
+extern int s3c_irqext_type(struct irq_data *d, unsigned int type);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/irqs.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/irqs.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/irqs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,80 @@
+/* linux/arch/arm/plat-samsung/include/plat/irqs.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P Common IRQ 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_SAMSUNG_IRQS_H
+#define __PLAT_SAMSUNG_IRQS_H __FILE__
+
+/* we keep the first set of CPU IRQs out of the range of
+ * the ISA space, so that the PC104 has them to itself
+ * and we don't end up having to do horrible things to the
+ * standard ISA drivers....
+ *
+ * note, since we're using the VICs, our start must be a
+ * mulitple of 32 to allow the common code to work
+ */
+
+#define S5P_IRQ_OFFSET		(32)
+
+#define S5P_IRQ(x)		((x) + S5P_IRQ_OFFSET)
+
+#define S5P_VIC0_BASE		S5P_IRQ(0)
+#define S5P_VIC1_BASE		S5P_IRQ(32)
+#define S5P_VIC2_BASE		S5P_IRQ(64)
+#define S5P_VIC3_BASE		S5P_IRQ(96)
+
+#define VIC_BASE(x)		(S5P_VIC0_BASE + ((x)*32))
+
+#define IRQ_VIC0_BASE		S5P_VIC0_BASE
+#define IRQ_VIC1_BASE		S5P_VIC1_BASE
+#define IRQ_VIC2_BASE		S5P_VIC2_BASE
+
+/* VIC based IRQs */
+
+#define S5P_IRQ_VIC0(x)		(S5P_VIC0_BASE + (x))
+#define S5P_IRQ_VIC1(x)		(S5P_VIC1_BASE + (x))
+#define S5P_IRQ_VIC2(x)		(S5P_VIC2_BASE + (x))
+#define S5P_IRQ_VIC3(x)		(S5P_VIC3_BASE + (x))
+
+#define S5P_TIMER_IRQ(x)	(11 + (x))
+
+#define IRQ_TIMER0		S5P_TIMER_IRQ(0)
+#define IRQ_TIMER1		S5P_TIMER_IRQ(1)
+#define IRQ_TIMER2		S5P_TIMER_IRQ(2)
+#define IRQ_TIMER3		S5P_TIMER_IRQ(3)
+#define IRQ_TIMER4		S5P_TIMER_IRQ(4)
+
+#define IRQ_EINT(x)		((x) < 16 ? ((x) + S5P_EINT_BASE1) \
+					: ((x) - 16 + S5P_EINT_BASE2))
+
+#define EINT_OFFSET(irq)	((irq) < S5P_EINT_BASE2 ? \
+						((irq) - S5P_EINT_BASE1) : \
+						((irq) + 16 - S5P_EINT_BASE2))
+
+#define IRQ_EINT_BIT(x)		EINT_OFFSET(x)
+
+/* Typically only a few gpio chips require gpio interrupt support.
+   To avoid memory waste irq descriptors are allocated only for
+   S5P_GPIOINT_GROUP_COUNT chips, each with total number of
+   S5P_GPIOINT_GROUP_SIZE pins/irqs. Each GPIOINT group can be assiged
+   to any gpio chip with the s5p_register_gpio_interrupt() function */
+#define S5P_GPIOINT_GROUP_COUNT 4
+#define S5P_GPIOINT_GROUP_SIZE	8
+#define S5P_GPIOINT_COUNT	(S5P_GPIOINT_GROUP_COUNT * S5P_GPIOINT_GROUP_SIZE)
+
+/* IRQ types common for all s5p platforms */
+#define S5P_IRQ_TYPE_LEVEL_LOW		(0x00)
+#define S5P_IRQ_TYPE_LEVEL_HIGH		(0x01)
+#define S5P_IRQ_TYPE_EDGE_FALLING	(0x02)
+#define S5P_IRQ_TYPE_EDGE_RISING	(0x03)
+#define S5P_IRQ_TYPE_EDGE_BOTH		(0x04)
+
+#endif /* __PLAT_SAMSUNG_IRQS_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/map-s3c.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/map-s3c.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/map-s3c.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/map-s3c.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,84 @@
+/* linux/arch/arm/plat-samsung/include/plat/map-s3c.h
+ *
+ * Copyright (c) 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX - 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_PLAT_MAP_S3C_H
+#define __ASM_PLAT_MAP_S3C_H __FILE__
+
+#define S3C24XX_VA_IRQ		S3C_VA_IRQ
+#define S3C24XX_VA_MEMCTRL	S3C_VA_MEM
+#define S3C24XX_VA_UART		S3C_VA_UART
+
+#define S3C24XX_VA_TIMER	S3C_VA_TIMER
+#define S3C24XX_VA_CLKPWR	S3C_VA_SYS
+#define S3C24XX_VA_WATCHDOG	S3C_VA_WATCHDOG
+
+#define S3C2412_VA_SSMC		S3C_ADDR_CPU(0x00000000)
+#define S3C2412_VA_EBI		S3C_ADDR_CPU(0x00010000)
+
+#define S3C2410_PA_UART		(0x50000000)
+#define S3C24XX_PA_UART		S3C2410_PA_UART
+
+#ifndef S3C_UART_OFFSET
+#define S3C_UART_OFFSET		(0x400)
+#endif
+
+/*
+ * GPIO ports
+ *
+ * the calculation for the VA of this must ensure that
+ * it is the same distance apart from the UART in the
+ * phsyical address space, as the initial mapping for the IO
+ * is done as a 1:1 mapping. This puts it (currently) at
+ * 0xFA800000, which is not in the way of any current mapping
+ * by the base system.
+*/
+
+#define S3C2410_PA_GPIO		(0x56000000)
+#define S3C24XX_PA_GPIO		S3C2410_PA_GPIO
+
+#define S3C24XX_VA_GPIO		((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)
+#define S3C64XX_VA_GPIO		S3C_ADDR_CPU(0x00000000)
+
+#define S3C64XX_VA_MODEM	S3C_ADDR_CPU(0x00100000)
+#define S3C64XX_VA_USB_HSPHY	S3C_ADDR_CPU(0x00200000)
+
+#define S3C_VA_USB_HSPHY	S3C64XX_VA_USB_HSPHY
+
+/*
+ * ISA style IO, for each machine to sort out mappings for,
+ * if it implements it. We reserve two 16M regions for ISA.
+ */
+
+#define S3C2410_ADDR(x)		S3C_ADDR(x)
+
+#define S3C24XX_VA_ISA_WORD	S3C2410_ADDR(0x02000000)
+#define S3C24XX_VA_ISA_BYTE	S3C2410_ADDR(0x03000000)
+
+/* deal with the registers that move under the 2412/2413 */
+
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+#ifndef __ASSEMBLY__
+extern void __iomem *s3c24xx_va_gpio2;
+#endif
+#ifdef CONFIG_CPU_S3C2412_ONLY
+#define S3C24XX_VA_GPIO2	(S3C24XX_VA_GPIO + 0x10)
+#else
+#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2
+#endif
+#else
+#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO
+#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO
+#endif
+
+#include <plat/map-s5p.h>
+
+#endif /* __ASM_PLAT_MAP_S3C_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/map-s5p.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/map-s5p.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/map-s5p.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/map-s5p.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,61 @@
+/* linux/arch/arm/plat-samsung/include/plat/map-s5p.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P - 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_PLAT_MAP_S5P_H
+#define __ASM_PLAT_MAP_S5P_H __FILE__
+
+#define S5P_VA_CHIPID		S3C_ADDR(0x02000000)
+#define S5P_VA_CMU		S3C_ADDR(0x02100000)
+#define S5P_VA_PMU		S3C_ADDR(0x02180000)
+#define S5P_VA_GPIO		S3C_ADDR(0x02200000)
+#define S5P_VA_GPIO1		S5P_VA_GPIO
+#define S5P_VA_GPIO2		S3C_ADDR(0x02240000)
+#define S5P_VA_GPIO3		S3C_ADDR(0x02280000)
+
+#define S5P_VA_SYSRAM		S3C_ADDR(0x02400000)
+#define S5P_VA_DMC0		S3C_ADDR(0x02440000)
+#define S5P_VA_DMC1		S3C_ADDR(0x02480000)
+#define S5P_VA_SROMC		S3C_ADDR(0x024C0000)
+
+#define S5P_VA_SYSTIMER		S3C_ADDR(0x02500000)
+#define S5P_VA_L2CC		S3C_ADDR(0x02600000)
+
+#define S5P_VA_COMBINER_BASE	S3C_ADDR(0x02700000)
+#define S5P_VA_COMBINER(x)	(S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10)
+
+#define S5P_VA_COREPERI_BASE	S3C_ADDR(0x02800000)
+#define S5P_VA_COREPERI(x)	(S5P_VA_COREPERI_BASE + (x))
+#define S5P_VA_SCU		S5P_VA_COREPERI(0x0)
+#define S5P_VA_TWD		S5P_VA_COREPERI(0x600)
+
+#define S5P_VA_GIC_CPU		S3C_ADDR(0x02810000)
+#define S5P_VA_GIC_DIST		S3C_ADDR(0x02820000)
+
+#define VA_VIC(x)		(S3C_VA_IRQ + ((x) * 0x10000))
+#define VA_VIC0			VA_VIC(0)
+#define VA_VIC1			VA_VIC(1)
+#define VA_VIC2			VA_VIC(2)
+#define VA_VIC3			VA_VIC(3)
+
+#define S5P_VA_UART(x)		(S3C_VA_UART + ((x) * S3C_UART_OFFSET))
+#define S5P_VA_UART0		S5P_VA_UART(0)
+#define S5P_VA_UART1		S5P_VA_UART(1)
+#define S5P_VA_UART2		S5P_VA_UART(2)
+#define S5P_VA_UART3		S5P_VA_UART(3)
+
+#ifndef S3C_UART_OFFSET
+#define S3C_UART_OFFSET		(0x400)
+#endif
+
+#include <plat/map-s3c.h>
+
+#endif /* __ASM_PLAT_MAP_S5P_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/mci.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/mci.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/mci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/mci.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,52 @@
+#ifndef _ARCH_MCI_H
+#define _ARCH_MCI_H
+
+/**
+ * struct s3c24xx_mci_pdata - sd/mmc controller platform data
+ * @no_wprotect: Set this to indicate there is no write-protect switch.
+ * @no_detect: Set this if there is no detect switch.
+ * @wprotect_invert: Invert the default sense of the write protect switch.
+ * @detect_invert: Invert the default sense of the write protect switch.
+ * @use_dma: Set to allow the use of DMA.
+ * @gpio_detect: GPIO number for the card detect line.
+ * @gpio_wprotect: GPIO number for the write protect line.
+ * @ocr_avail: The mask of the available power states, non-zero to use.
+ * @set_power: Callback to control the power mode.
+ *
+ * The @gpio_detect is used for card detection when @no_wprotect is unset,
+ * and the default sense is that 0 returned from gpio_get_value() means
+ * that a card is inserted. If @detect_invert is set, then the value from
+ * gpio_get_value() is inverted, which makes 1 mean card inserted.
+ *
+ * The driver will use @gpio_wprotect to signal whether the card is write
+ * protected if @no_wprotect is not set. A 0 returned from gpio_get_value()
+ * means the card is read/write, and 1 means read-only. The @wprotect_invert
+ * will invert the value returned from gpio_get_value().
+ *
+ * Card power is set by @ocr_availa, using MCC_VDD_ constants if it is set
+ * to a non-zero value, otherwise the default of 3.2-3.4V is used.
+ */
+struct s3c24xx_mci_pdata {
+	unsigned int	no_wprotect:1;
+	unsigned int	no_detect:1;
+	unsigned int	wprotect_invert:1;
+	unsigned int	detect_invert:1;	/* set => detect active high */
+	unsigned int	use_dma:1;
+
+	unsigned int	gpio_detect;
+	unsigned int	gpio_wprotect;
+	unsigned long	ocr_avail;
+	void		(*set_power)(unsigned char power_mode,
+				     unsigned short vdd);
+};
+
+/**
+ * s3c24xx_mci_set_platdata - set platform data for mmc/sdi device
+ * @pdata: The platform data
+ *
+ * Copy the platform data supplied by @pdata so that this can be marked
+ * __initdata.
+ */
+extern void s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata);
+
+#endif /* _ARCH_NCI_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/mfc.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/mfc.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/mfc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/mfc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,27 @@
+/*
+ * 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 as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __PLAT_SAMSUNG_MFC_H
+#define __PLAT_SAMSUNG_MFC_H __FILE__
+
+/**
+ * s5p_mfc_reserve_mem - function to early reserve memory for MFC driver
+ * @rbase:	base address for MFC 'right' memory interface
+ * @rsize:	size of the memory reserved for MFC 'right' interface
+ * @lbase:	base address for MFC 'left' memory interface
+ * @lsize:	size of the memory reserved for MFC 'left' interface
+ *
+ * This function reserves system memory for both MFC device memory
+ * interfaces and registers it to respective struct device entries as
+ * coherent memory.
+ */
+void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
+				phys_addr_t lbase, unsigned int lsize);
+
+#endif /* __PLAT_SAMSUNG_MFC_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/mipi_csis.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/mipi_csis.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/mipi_csis.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/mipi_csis.h	2012-01-04 18:55:44.000000000 -0500
@@ -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_SAMSUNG_MIPI_CSIS_H_
+#define __PLAT_SAMSUNG_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_SAMSUNG_MIPI_CSIS_H_ */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/pll6553x.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/pll6553x.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/pll6553x.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/pll6553x.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-/* arch/arm/plat-samsung/include/plat/pll6553x.h
- *	partially from arch/arm/mach-s3c64xx/include/mach/pll.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * Samsung PLL6553x PLL 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.
-*/
-
-/* S3C6400 and compatible (S3C2416, etc.) EPLL code */
-
-#define PLL6553X_MDIV_MASK	((1 << (23-16)) - 1)
-#define PLL6553X_PDIV_MASK	((1 << (13-8)) - 1)
-#define PLL6553X_SDIV_MASK	((1 << (2-0)) - 1)
-#define PLL6553X_MDIV_SHIFT	(16)
-#define PLL6553X_PDIV_SHIFT	(8)
-#define PLL6553X_SDIV_SHIFT	(0)
-#define PLL6553X_KDIV_MASK	(0xffff)
-
-static inline unsigned long s3c_get_pll6553x(unsigned long baseclk,
-					     u32 pll0, u32 pll1)
-{
-	unsigned long result;
-	u32 mdiv, pdiv, sdiv, kdiv;
-	u64 tmp;
-
-	mdiv = (pll0 >> PLL6553X_MDIV_SHIFT) & PLL6553X_MDIV_MASK;
-	pdiv = (pll0 >> PLL6553X_PDIV_SHIFT) & PLL6553X_PDIV_MASK;
-	sdiv = (pll0 >> PLL6553X_SDIV_SHIFT) & PLL6553X_SDIV_MASK;
-	kdiv = pll1 & PLL6553X_KDIV_MASK;
-
-	/* We need to multiple baseclk by mdiv (the integer part) and kdiv
-	 * which is in 2^16ths, so shift mdiv up (does not overflow) and
-	 * add kdiv before multiplying. The use of tmp is to avoid any
-	 * overflows before shifting bac down into result when multipling
-	 * by the mdiv and kdiv pair.
-	 */
-
-	tmp = baseclk;
-	tmp *= (mdiv << 16) + kdiv;
-	do_div(tmp, (pdiv << sdiv));
-	result = tmp >> 16;
-
-	return result;
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/pll.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/pll.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/pll.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/pll.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,323 @@
+/* linux/arch/arm/plat-samsung/include/plat/pll.h
+ *
+ * Copyright (c) 2009-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/
+ *
+ * Samsung PLL codes
+ *
+ * This program is free software; you can 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/div64.h>
+
+#define S3C24XX_PLL_MDIV_MASK		(0xFF)
+#define S3C24XX_PLL_PDIV_MASK		(0x1F)
+#define S3C24XX_PLL_SDIV_MASK		(0x3)
+#define S3C24XX_PLL_MDIV_SHIFT		(12)
+#define S3C24XX_PLL_PDIV_SHIFT		(4)
+#define S3C24XX_PLL_SDIV_SHIFT		(0)
+
+static inline unsigned int s3c24xx_get_pll(unsigned int pllval,
+					   unsigned int baseclk)
+{
+	unsigned int mdiv, pdiv, sdiv;
+	uint64_t fvco;
+
+	mdiv = (pllval >> S3C24XX_PLL_MDIV_SHIFT) & S3C24XX_PLL_MDIV_MASK;
+	pdiv = (pllval >> S3C24XX_PLL_PDIV_SHIFT) & S3C24XX_PLL_PDIV_MASK;
+	sdiv = (pllval >> S3C24XX_PLL_SDIV_SHIFT) & S3C24XX_PLL_SDIV_MASK;
+
+	fvco = (uint64_t)baseclk * (mdiv + 8);
+	do_div(fvco, (pdiv + 2) << sdiv);
+
+	return (unsigned int)fvco;
+}
+
+#define S3C2416_PLL_MDIV_MASK		(0x3FF)
+#define S3C2416_PLL_PDIV_MASK		(0x3F)
+#define S3C2416_PLL_SDIV_MASK		(0x7)
+#define S3C2416_PLL_MDIV_SHIFT		(14)
+#define S3C2416_PLL_PDIV_SHIFT		(5)
+#define S3C2416_PLL_SDIV_SHIFT		(0)
+
+static inline unsigned int s3c2416_get_pll(unsigned int pllval,
+					   unsigned int baseclk)
+{
+	unsigned int mdiv, pdiv, sdiv;
+	uint64_t fvco;
+
+	mdiv = (pllval >> S3C2416_PLL_MDIV_SHIFT) & S3C2416_PLL_MDIV_MASK;
+	pdiv = (pllval >> S3C2416_PLL_PDIV_SHIFT) & S3C2416_PLL_PDIV_MASK;
+	sdiv = (pllval >> S3C2416_PLL_SDIV_SHIFT) & S3C2416_PLL_SDIV_MASK;
+
+	fvco = (uint64_t)baseclk * mdiv;
+	do_div(fvco, (pdiv << sdiv));
+
+	return (unsigned int)fvco;
+}
+
+#define S3C6400_PLL_MDIV_MASK		(0x3FF)
+#define S3C6400_PLL_PDIV_MASK		(0x3F)
+#define S3C6400_PLL_SDIV_MASK		(0x7)
+#define S3C6400_PLL_MDIV_SHIFT		(16)
+#define S3C6400_PLL_PDIV_SHIFT		(8)
+#define S3C6400_PLL_SDIV_SHIFT		(0)
+
+static inline unsigned long s3c6400_get_pll(unsigned long baseclk,
+					    u32 pllcon)
+{
+	u32 mdiv, pdiv, sdiv;
+	u64 fvco = baseclk;
+
+	mdiv = (pllcon >> S3C6400_PLL_MDIV_SHIFT) & S3C6400_PLL_MDIV_MASK;
+	pdiv = (pllcon >> S3C6400_PLL_PDIV_SHIFT) & S3C6400_PLL_PDIV_MASK;
+	sdiv = (pllcon >> S3C6400_PLL_SDIV_SHIFT) & S3C6400_PLL_SDIV_MASK;
+
+	fvco *= mdiv;
+	do_div(fvco, (pdiv << sdiv));
+
+	return (unsigned long)fvco;
+}
+
+#define PLL6553X_MDIV_MASK	(0x7F)
+#define PLL6553X_PDIV_MASK	(0x1F)
+#define PLL6553X_SDIV_MASK	(0x3)
+#define PLL6553X_KDIV_MASK	(0xFFFF)
+#define PLL6553X_MDIV_SHIFT	(16)
+#define PLL6553X_PDIV_SHIFT	(8)
+#define PLL6553X_SDIV_SHIFT	(0)
+
+static inline unsigned long s3c_get_pll6553x(unsigned long baseclk,
+					     u32 pll_con0, u32 pll_con1)
+{
+	unsigned long result;
+	u32 mdiv, pdiv, sdiv, kdiv;
+	u64 tmp;
+
+	mdiv = (pll_con0 >> PLL6553X_MDIV_SHIFT) & PLL6553X_MDIV_MASK;
+	pdiv = (pll_con0 >> PLL6553X_PDIV_SHIFT) & PLL6553X_PDIV_MASK;
+	sdiv = (pll_con0 >> PLL6553X_SDIV_SHIFT) & PLL6553X_SDIV_MASK;
+	kdiv = pll_con1 & PLL6553X_KDIV_MASK;
+
+	/*
+	 * We need to multiple baseclk by mdiv (the integer part) and kdiv
+	 * which is in 2^16ths, so shift mdiv up (does not overflow) and
+	 * add kdiv before multiplying. The use of tmp is to avoid any
+	 * overflows before shifting bac down into result when multipling
+	 * by the mdiv and kdiv pair.
+	 */
+
+	tmp = baseclk;
+	tmp *= (mdiv << 16) + kdiv;
+	do_div(tmp, (pdiv << sdiv));
+	result = tmp >> 16;
+
+	return result;
+}
+
+#define PLL35XX_MDIV_MASK	(0x3FF)
+#define PLL35XX_PDIV_MASK	(0x3F)
+#define PLL35XX_SDIV_MASK	(0x7)
+#define PLL35XX_MDIV_SHIFT	(16)
+#define PLL35XX_PDIV_SHIFT	(8)
+#define PLL35XX_SDIV_SHIFT	(0)
+
+static inline unsigned long s5p_get_pll35xx(unsigned long baseclk, u32 pll_con)
+{
+	u32 mdiv, pdiv, sdiv;
+	u64 fvco = baseclk;
+
+	mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
+	pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
+	sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
+
+	fvco *= mdiv;
+	do_div(fvco, (pdiv << sdiv));
+
+	return (unsigned long)fvco;
+}
+
+#define PLL36XX_KDIV_MASK	(0xFFFF)
+#define PLL36XX_MDIV_MASK	(0x1FF)
+#define PLL36XX_PDIV_MASK	(0x3F)
+#define PLL36XX_SDIV_MASK	(0x7)
+#define PLL36XX_MDIV_SHIFT	(16)
+#define PLL36XX_PDIV_SHIFT	(8)
+#define PLL36XX_SDIV_SHIFT	(0)
+
+static inline unsigned long s5p_get_pll36xx(unsigned long baseclk,
+					    u32 pll_con0, u32 pll_con1)
+{
+	unsigned long result;
+	u32 mdiv, pdiv, sdiv, kdiv;
+	u64 tmp;
+
+	mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
+	pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
+	sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
+	kdiv = pll_con1 & PLL36XX_KDIV_MASK;
+
+	tmp = baseclk;
+
+	tmp *= (mdiv << 16) + kdiv;
+	do_div(tmp, (pdiv << sdiv));
+	result = tmp >> 16;
+
+	return result;
+}
+
+#define PLL45XX_MDIV_MASK	(0x3FF)
+#define PLL45XX_PDIV_MASK	(0x3F)
+#define PLL45XX_SDIV_MASK	(0x7)
+#define PLL45XX_MDIV_SHIFT	(16)
+#define PLL45XX_PDIV_SHIFT	(8)
+#define PLL45XX_SDIV_SHIFT	(0)
+
+enum pll45xx_type_t {
+	pll_4500,
+	pll_4502,
+	pll_4508
+};
+
+static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
+					    enum pll45xx_type_t pll_type)
+{
+	u32 mdiv, pdiv, sdiv;
+	u64 fvco = baseclk;
+
+	mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
+	pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
+	sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
+
+	if (pll_type == pll_4508)
+		sdiv = sdiv - 1;
+
+	fvco *= mdiv;
+	do_div(fvco, (pdiv << sdiv));
+
+	return (unsigned long)fvco;
+}
+
+/* CON0 bit-fields */
+#define PLL46XX_MDIV_MASK	(0x1FF)
+#define PLL46XX_PDIV_MASK	(0x3F)
+#define PLL46XX_SDIV_MASK	(0x7)
+#define PLL46XX_LOCKED_SHIFT	(29)
+#define PLL46XX_MDIV_SHIFT	(16)
+#define PLL46XX_PDIV_SHIFT	(8)
+#define PLL46XX_SDIV_SHIFT	(0)
+
+/* CON1 bit-fields */
+#define PLL46XX_MRR_MASK	(0x1F)
+#define PLL46XX_MFR_MASK	(0x3F)
+#define PLL46XX_KDIV_MASK	(0xFFFF)
+#define PLL4650C_KDIV_MASK	(0xFFF)
+#define PLL46XX_MRR_SHIFT	(24)
+#define PLL46XX_MFR_SHIFT	(16)
+#define PLL46XX_KDIV_SHIFT	(0)
+
+enum pll46xx_type_t {
+	pll_4600,
+	pll_4650,
+	pll_4650c,
+};
+
+static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
+					    u32 pll_con0, u32 pll_con1,
+					    enum pll46xx_type_t pll_type)
+{
+	unsigned long result;
+	u32 mdiv, pdiv, sdiv, kdiv;
+	u64 tmp;
+
+	mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
+	pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
+	sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
+	kdiv = pll_con1 & PLL46XX_KDIV_MASK;
+
+	if (pll_type == pll_4650c)
+		kdiv = pll_con1 & PLL4650C_KDIV_MASK;
+	else
+		kdiv = pll_con1 & PLL46XX_KDIV_MASK;
+
+	tmp = baseclk;
+
+	if (pll_type == pll_4600) {
+		tmp *= (mdiv << 16) + kdiv;
+		do_div(tmp, (pdiv << sdiv));
+		result = tmp >> 16;
+	} else {
+		tmp *= (mdiv << 10) + kdiv;
+		do_div(tmp, (pdiv << sdiv));
+		result = tmp >> 10;
+	}
+
+	return result;
+}
+
+#define PLL90XX_MDIV_MASK	(0xFF)
+#define PLL90XX_PDIV_MASK	(0x3F)
+#define PLL90XX_SDIV_MASK	(0x7)
+#define PLL90XX_KDIV_MASK	(0xffff)
+#define PLL90XX_LOCKED_SHIFT	(29)
+#define PLL90XX_MDIV_SHIFT	(16)
+#define PLL90XX_PDIV_SHIFT	(8)
+#define PLL90XX_SDIV_SHIFT	(0)
+#define PLL90XX_KDIV_SHIFT	(0)
+
+static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
+					    u32 pll_con, u32 pll_conk)
+{
+	unsigned long result;
+	u32 mdiv, pdiv, sdiv, kdiv;
+	u64 tmp;
+
+	mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK;
+	pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK;
+	sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
+	kdiv = pll_conk & PLL90XX_KDIV_MASK;
+
+	/*
+	 * We need to multiple baseclk by mdiv (the integer part) and kdiv
+	 * which is in 2^16ths, so shift mdiv up (does not overflow) and
+	 * add kdiv before multiplying. The use of tmp is to avoid any
+	 * overflows before shifting bac down into result when multipling
+	 * by the mdiv and kdiv pair.
+	 */
+
+	tmp = baseclk;
+	tmp *= (mdiv << 16) + kdiv;
+	do_div(tmp, (pdiv << sdiv));
+	result = tmp >> 16;
+
+	return result;
+}
+
+#define PLL65XX_MDIV_MASK	(0x3FF)
+#define PLL65XX_PDIV_MASK	(0x3F)
+#define PLL65XX_SDIV_MASK	(0x7)
+#define PLL65XX_MDIV_SHIFT	(16)
+#define PLL65XX_PDIV_SHIFT	(8)
+#define PLL65XX_SDIV_SHIFT	(0)
+
+static inline unsigned long s5p_get_pll65xx(unsigned long baseclk, u32 pll_con)
+{
+	u32 mdiv, pdiv, sdiv;
+	u64 fvco = baseclk;
+
+	mdiv = (pll_con >> PLL65XX_MDIV_SHIFT) & PLL65XX_MDIV_MASK;
+	pdiv = (pll_con >> PLL65XX_PDIV_SHIFT) & PLL65XX_PDIV_MASK;
+	sdiv = (pll_con >> PLL65XX_SDIV_SHIFT) & PLL65XX_SDIV_MASK;
+
+	fvco *= mdiv;
+	do_div(fvco, (pdiv << sdiv));
+
+	return (unsigned long)fvco;
+}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/pm.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/pm.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/pm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/pm.h	2012-01-04 18:55:44.000000000 -0500
@@ -165,20 +165,20 @@
 extern void s3c_pm_configure_extint(void);
 
 /**
- * s3c_pm_restore_gpios() - restore the state of the gpios after sleep.
+ * samsung_pm_restore_gpios() - restore the state of the gpios after sleep.
  *
  * Restore the state of the GPIO pins after sleep, which may involve ensuring
  * that we do not glitch the state of the pins from that the bootloader's
  * resume code has done.
 */
-extern void s3c_pm_restore_gpios(void);
+extern void samsung_pm_restore_gpios(void);
 
 /**
- * s3c_pm_save_gpios() - save the state of the GPIOs for restoring after sleep.
+ * samsung_pm_save_gpios() - save the state of the GPIOs for restoring after sleep.
  *
- * Save the GPIO states for resotration on resume. See s3c_pm_restore_gpios().
+ * Save the GPIO states for resotration on resume. See samsung_pm_restore_gpios().
  */
-extern void s3c_pm_save_gpios(void);
+extern void samsung_pm_save_gpios(void);
 
 extern void s3c_pm_save_core(void);
 extern void s3c_pm_restore_core(void);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/pwm-clock.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/pwm-clock.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/pwm-clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/pwm-clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,81 @@
+/* linux/arch/arm/plat-samsung/include/plat/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/
+ *
+ * SAMSUNG - 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_PLAT_PWM_CLOCK_H
+#define __ASM_PLAT_PWM_CLOCK_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)
+{
+	if (soc_is_s3c24xx())
+		return tcfg == S3C2410_TCFG1_MUX_TCLK;
+	else if (soc_is_s3c64xx() || soc_is_s5pc100())
+		return tcfg >= S3C64XX_TCFG1_MUX_TCLK;
+	else if (soc_is_s5p6440() || soc_is_s5p6450())
+		return 0;
+	else
+		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)
+{
+	if (soc_is_s3c24xx())
+		return 1 << (tcfg1 + 1);
+	else
+		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)
+{
+	if (soc_is_s3c24xx())
+		return 0;
+	else
+		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)
+{
+	if (soc_is_s3c24xx())
+		return ilog2(div) - 1;
+	else
+		return ilog2(div);
+}
+#endif /* __ASM_PLAT_PWM_CLOCK_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/regs-adc.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/regs-adc.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/regs-adc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/regs-adc.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #define S3C2410_ADCDAT0	   S3C2410_ADCREG(0x0C)
 #define S3C2410_ADCDAT1	   S3C2410_ADCREG(0x10)
 #define S3C64XX_ADCUPDN		S3C2410_ADCREG(0x14)
+#define S3C2443_ADCMUX		S3C2410_ADCREG(0x18)
 #define S3C64XX_ADCCLRINT	S3C2410_ADCREG(0x18)
 #define S5P_ADCMUX		S3C2410_ADCREG(0x1C)
 #define S3C64XX_ADCCLRINTPNDNUP	S3C2410_ADCREG(0x20)
@@ -33,6 +34,7 @@
 #define S3C2410_ADCCON_PRSCVLMASK	(0xFF<<6)
 #define S3C2410_ADCCON_SELMUX(x)	(((x)&0x7)<<3)
 #define S3C2410_ADCCON_MUXMASK		(0x7<<3)
+#define S3C2416_ADCCON_RESSEL		(1 << 3)
 #define S3C2410_ADCCON_STDBM		(1<<2)
 #define S3C2410_ADCCON_READ_START	(1<<1)
 #define S3C2410_ADCCON_ENABLE_START	(1<<0)
@@ -40,6 +42,7 @@
 
 
 /* ADCTSC Register Bits */
+#define S3C2443_ADCTSC_UD_SEN		(1 << 8)
 #define S3C2410_ADCTSC_YM_SEN		(1<<7)
 #define S3C2410_ADCTSC_YP_SEN		(1<<6)
 #define S3C2410_ADCTSC_XM_SEN		(1<<5)
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/regs-dma.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/regs-dma.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/regs-dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/regs-dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,151 @@
+/* arch/arm/plat-samsung/include/plat/regs-dma.h
+ *
+ * Copyright (C) 2003-2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C24XX DMA support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_REGS_DMA_H
+#define __ASM_PLAT_REGS_DMA_H __FILE__
+
+#define S3C2410_DMA_DISRC		(0x00)
+#define S3C2410_DMA_DISRCC		(0x04)
+#define S3C2410_DMA_DIDST		(0x08)
+#define S3C2410_DMA_DIDSTC		(0x0C)
+#define S3C2410_DMA_DCON		(0x10)
+#define S3C2410_DMA_DSTAT		(0x14)
+#define S3C2410_DMA_DCSRC		(0x18)
+#define S3C2410_DMA_DCDST		(0x1C)
+#define S3C2410_DMA_DMASKTRIG		(0x20)
+#define S3C2412_DMA_DMAREQSEL		(0x24)
+#define S3C2443_DMA_DMAREQSEL		(0x24)
+
+#define S3C2410_DISRCC_INC		(1 << 0)
+#define S3C2410_DISRCC_APB		(1 << 1)
+
+#define S3C2410_DMASKTRIG_STOP		(1 << 2)
+#define S3C2410_DMASKTRIG_ON		(1 << 1)
+#define S3C2410_DMASKTRIG_SWTRIG	(1 << 0)
+
+#define S3C2410_DCON_DEMAND		(0 << 31)
+#define S3C2410_DCON_HANDSHAKE		(1 << 31)
+#define S3C2410_DCON_SYNC_PCLK		(0 << 30)
+#define S3C2410_DCON_SYNC_HCLK		(1 << 30)
+
+#define S3C2410_DCON_INTREQ		(1 << 29)
+
+#define S3C2410_DCON_CH0_XDREQ0		(0 << 24)
+#define S3C2410_DCON_CH0_UART0		(1 << 24)
+#define S3C2410_DCON_CH0_SDI		(2 << 24)
+#define S3C2410_DCON_CH0_TIMER		(3 << 24)
+#define S3C2410_DCON_CH0_USBEP1		(4 << 24)
+
+#define S3C2410_DCON_CH1_XDREQ1		(0 << 24)
+#define S3C2410_DCON_CH1_UART1		(1 << 24)
+#define S3C2410_DCON_CH1_I2SSDI		(2 << 24)
+#define S3C2410_DCON_CH1_SPI		(3 << 24)
+#define S3C2410_DCON_CH1_USBEP2		(4 << 24)
+
+#define S3C2410_DCON_CH2_I2SSDO		(0 << 24)
+#define S3C2410_DCON_CH2_I2SSDI		(1 << 24)
+#define S3C2410_DCON_CH2_SDI		(2 << 24)
+#define S3C2410_DCON_CH2_TIMER		(3 << 24)
+#define S3C2410_DCON_CH2_USBEP3		(4 << 24)
+
+#define S3C2410_DCON_CH3_UART2		(0 << 24)
+#define S3C2410_DCON_CH3_SDI		(1 << 24)
+#define S3C2410_DCON_CH3_SPI		(2 << 24)
+#define S3C2410_DCON_CH3_TIMER		(3 << 24)
+#define S3C2410_DCON_CH3_USBEP4		(4 << 24)
+
+#define S3C2410_DCON_SRCSHIFT		(24)
+#define S3C2410_DCON_SRCMASK		(7 << 24)
+
+#define S3C2410_DCON_BYTE		(0 << 20)
+#define S3C2410_DCON_HALFWORD		(1 << 20)
+#define S3C2410_DCON_WORD		(2 << 20)
+
+#define S3C2410_DCON_AUTORELOAD		(0 << 22)
+#define S3C2410_DCON_NORELOAD		(1 << 22)
+#define S3C2410_DCON_HWTRIG		(1 << 23)
+
+#ifdef CONFIG_CPU_S3C2440
+
+#define S3C2440_DIDSTC_CHKINT		(1 << 2)
+
+#define S3C2440_DCON_CH0_I2SSDO		(5 << 24)
+#define S3C2440_DCON_CH0_PCMIN		(6 << 24)
+
+#define S3C2440_DCON_CH1_PCMOUT		(5 << 24)
+#define S3C2440_DCON_CH1_SDI		(6 << 24)
+
+#define S3C2440_DCON_CH2_PCMIN		(5 << 24)
+#define S3C2440_DCON_CH2_MICIN		(6 << 24)
+
+#define S3C2440_DCON_CH3_MICIN		(5 << 24)
+#define S3C2440_DCON_CH3_PCMOUT		(6 << 24)
+#endif /* CONFIG_CPU_S3C2440 */
+
+#ifdef CONFIG_CPU_S3C2412
+
+#define S3C2412_DMAREQSEL_SRC(x)	((x) << 1)
+
+#define S3C2412_DMAREQSEL_HW		(1)
+
+#define S3C2412_DMAREQSEL_SPI0TX	S3C2412_DMAREQSEL_SRC(0)
+#define S3C2412_DMAREQSEL_SPI0RX	S3C2412_DMAREQSEL_SRC(1)
+#define S3C2412_DMAREQSEL_SPI1TX	S3C2412_DMAREQSEL_SRC(2)
+#define S3C2412_DMAREQSEL_SPI1RX	S3C2412_DMAREQSEL_SRC(3)
+#define S3C2412_DMAREQSEL_I2STX		S3C2412_DMAREQSEL_SRC(4)
+#define S3C2412_DMAREQSEL_I2SRX		S3C2412_DMAREQSEL_SRC(5)
+#define S3C2412_DMAREQSEL_TIMER		S3C2412_DMAREQSEL_SRC(9)
+#define S3C2412_DMAREQSEL_SDI		S3C2412_DMAREQSEL_SRC(10)
+#define S3C2412_DMAREQSEL_USBEP1	S3C2412_DMAREQSEL_SRC(13)
+#define S3C2412_DMAREQSEL_USBEP2	S3C2412_DMAREQSEL_SRC(14)
+#define S3C2412_DMAREQSEL_USBEP3	S3C2412_DMAREQSEL_SRC(15)
+#define S3C2412_DMAREQSEL_USBEP4	S3C2412_DMAREQSEL_SRC(16)
+#define S3C2412_DMAREQSEL_XDREQ0	S3C2412_DMAREQSEL_SRC(17)
+#define S3C2412_DMAREQSEL_XDREQ1	S3C2412_DMAREQSEL_SRC(18)
+#define S3C2412_DMAREQSEL_UART0_0	S3C2412_DMAREQSEL_SRC(19)
+#define S3C2412_DMAREQSEL_UART0_1	S3C2412_DMAREQSEL_SRC(20)
+#define S3C2412_DMAREQSEL_UART1_0	S3C2412_DMAREQSEL_SRC(21)
+#define S3C2412_DMAREQSEL_UART1_1	S3C2412_DMAREQSEL_SRC(22)
+#define S3C2412_DMAREQSEL_UART2_0	S3C2412_DMAREQSEL_SRC(23)
+#define S3C2412_DMAREQSEL_UART2_1	S3C2412_DMAREQSEL_SRC(24)
+#endif /* CONFIG_CPU_S3C2412 */
+
+#ifdef CONFIG_CPU_S3C2443
+
+#define S3C2443_DMAREQSEL_SRC(x)	((x) << 1)
+
+#define S3C2443_DMAREQSEL_HW		(1)
+
+#define S3C2443_DMAREQSEL_SPI0TX	S3C2443_DMAREQSEL_SRC(0)
+#define S3C2443_DMAREQSEL_SPI0RX	S3C2443_DMAREQSEL_SRC(1)
+#define S3C2443_DMAREQSEL_SPI1TX	S3C2443_DMAREQSEL_SRC(2)
+#define S3C2443_DMAREQSEL_SPI1RX	S3C2443_DMAREQSEL_SRC(3)
+#define S3C2443_DMAREQSEL_I2STX		S3C2443_DMAREQSEL_SRC(4)
+#define S3C2443_DMAREQSEL_I2SRX		S3C2443_DMAREQSEL_SRC(5)
+#define S3C2443_DMAREQSEL_TIMER		S3C2443_DMAREQSEL_SRC(9)
+#define S3C2443_DMAREQSEL_SDI		S3C2443_DMAREQSEL_SRC(10)
+#define S3C2443_DMAREQSEL_XDREQ0	S3C2443_DMAREQSEL_SRC(17)
+#define S3C2443_DMAREQSEL_XDREQ1	S3C2443_DMAREQSEL_SRC(18)
+#define S3C2443_DMAREQSEL_UART0_0	S3C2443_DMAREQSEL_SRC(19)
+#define S3C2443_DMAREQSEL_UART0_1	S3C2443_DMAREQSEL_SRC(20)
+#define S3C2443_DMAREQSEL_UART1_0	S3C2443_DMAREQSEL_SRC(21)
+#define S3C2443_DMAREQSEL_UART1_1	S3C2443_DMAREQSEL_SRC(22)
+#define S3C2443_DMAREQSEL_UART2_0	S3C2443_DMAREQSEL_SRC(23)
+#define S3C2443_DMAREQSEL_UART2_1	S3C2443_DMAREQSEL_SRC(24)
+#define S3C2443_DMAREQSEL_UART3_0	S3C2443_DMAREQSEL_SRC(25)
+#define S3C2443_DMAREQSEL_UART3_1	S3C2443_DMAREQSEL_SRC(26)
+#define S3C2443_DMAREQSEL_PCMOUT	S3C2443_DMAREQSEL_SRC(27)
+#define S3C2443_DMAREQSEL_PCMIN		S3C2443_DMAREQSEL_SRC(28)
+#define S3C2443_DMAREQSEL_MICIN		S3C2443_DMAREQSEL_SRC(29)
+#endif /* CONFIG_CPU_S3C2443 */
+
+#endif /* __ASM_PLAT_REGS_DMA_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/regs-iis.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/regs-iis.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/regs-iis.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/regs-iis.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,70 @@
+/* arch/arm/plat-samsung/include/plat/regs-iis.h
+ *
+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
+ *		      http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * S3C2410 IIS register definition
+*/
+
+#ifndef __ASM_ARCH_REGS_IIS_H
+#define __ASM_ARCH_REGS_IIS_H
+
+#define S3C2410_IISCON			(0x00)
+
+#define S3C2410_IISCON_LRINDEX		(1 << 8)
+#define S3C2410_IISCON_TXFIFORDY	(1 << 7)
+#define S3C2410_IISCON_RXFIFORDY	(1 << 6)
+#define S3C2410_IISCON_TXDMAEN		(1 << 5)
+#define S3C2410_IISCON_RXDMAEN		(1 << 4)
+#define S3C2410_IISCON_TXIDLE		(1 << 3)
+#define S3C2410_IISCON_RXIDLE		(1 << 2)
+#define S3C2410_IISCON_PSCEN		(1 << 1)
+#define S3C2410_IISCON_IISEN		(1 << 0)
+
+#define S3C2410_IISMOD			(0x04)
+
+#define S3C2440_IISMOD_MPLL		(1 << 9)
+#define S3C2410_IISMOD_SLAVE		(1 << 8)
+#define S3C2410_IISMOD_NOXFER		(0 << 6)
+#define S3C2410_IISMOD_RXMODE		(1 << 6)
+#define S3C2410_IISMOD_TXMODE		(2 << 6)
+#define S3C2410_IISMOD_TXRXMODE		(3 << 6)
+#define S3C2410_IISMOD_LR_LLOW		(0 << 5)
+#define S3C2410_IISMOD_LR_RLOW		(1 << 5)
+#define S3C2410_IISMOD_IIS		(0 << 4)
+#define S3C2410_IISMOD_MSB		(1 << 4)
+#define S3C2410_IISMOD_8BIT		(0 << 3)
+#define S3C2410_IISMOD_16BIT		(1 << 3)
+#define S3C2410_IISMOD_BITMASK		(1 << 3)
+#define S3C2410_IISMOD_256FS		(0 << 2)
+#define S3C2410_IISMOD_384FS		(1 << 2)
+#define S3C2410_IISMOD_16FS		(0 << 0)
+#define S3C2410_IISMOD_32FS		(1 << 0)
+#define S3C2410_IISMOD_48FS		(2 << 0)
+#define S3C2410_IISMOD_FS_MASK		(3 << 0)
+
+#define S3C2410_IISPSR			(0x08)
+
+#define S3C2410_IISPSR_INTMASK		(31 << 5)
+#define S3C2410_IISPSR_INTSHIFT		(5)
+#define S3C2410_IISPSR_EXTMASK		(31 << 0)
+#define S3C2410_IISPSR_EXTSHFIT		(0)
+
+#define S3C2410_IISFCON			(0x0c)
+
+#define S3C2410_IISFCON_TXDMA		(1 << 15)
+#define S3C2410_IISFCON_RXDMA		(1 << 14)
+#define S3C2410_IISFCON_TXENABLE	(1 << 13)
+#define S3C2410_IISFCON_RXENABLE	(1 << 12)
+#define S3C2410_IISFCON_TXMASK		(0x3f << 6)
+#define S3C2410_IISFCON_TXSHIFT		(6)
+#define S3C2410_IISFCON_RXMASK		(0x3f)
+#define S3C2410_IISFCON_RXSHIFT		(0)
+
+#define S3C2410_IISFIFO			(0x10)
+
+#endif /* __ASM_ARCH_REGS_IIS_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/regs-serial.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/regs-serial.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/regs-serial.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/regs-serial.h	2012-01-04 18:55:44.000000000 -0500
@@ -186,6 +186,11 @@
 #define S3C64XX_UINTSP		0x34
 #define S3C64XX_UINTM		0x38
 
+#define S3C64XX_UINTM_RXD	(0)
+#define S3C64XX_UINTM_TXD	(2)
+#define S3C64XX_UINTM_RXD_MSK	(1 << S3C64XX_UINTM_RXD)
+#define S3C64XX_UINTM_TXD_MSK	(1 << S3C64XX_UINTM_TXD)
+
 /* Following are specific to S5PV210 */
 #define S5PV210_UCON_CLKMASK	(1<<10)
 #define S5PV210_UCON_PCLK	(0<<10)
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/regs-spi.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/regs-spi.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/regs-spi.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/regs-spi.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,48 @@
+/* arch/arm/plat-samsung/include/plat/regs-spi.h
+ *
+ * Copyright (c) 2004 Fetron GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * S3C2410 SPI register definition
+*/
+
+#ifndef __ASM_ARCH_REGS_SPI_H
+#define __ASM_ARCH_REGS_SPI_H
+
+#define S3C2410_SPI1		(0x20)
+#define S3C2412_SPI1		(0x100)
+
+#define S3C2410_SPCON		(0x00)
+
+#define S3C2410_SPCON_SMOD_DMA	(2 << 5)	/* DMA mode */
+#define S3C2410_SPCON_SMOD_INT	(1 << 5)	/* interrupt mode */
+#define S3C2410_SPCON_SMOD_POLL	(0 << 5)	/* polling mode */
+#define S3C2410_SPCON_ENSCK	(1 << 4)	/* Enable SCK */
+#define S3C2410_SPCON_MSTR	(1 << 3)	/* Master:1, Slave:0 select */
+#define S3C2410_SPCON_CPOL_HIGH	(1 << 2)	/* Clock polarity select */
+#define S3C2410_SPCON_CPOL_LOW	(0 << 2)	/* Clock polarity select */
+
+#define S3C2410_SPCON_CPHA_FMTB	(1 << 1)	/* Clock Phase Select */
+#define S3C2410_SPCON_CPHA_FMTA	(0 << 1)	/* Clock Phase Select */
+
+#define S3C2410_SPSTA		(0x04)
+
+#define S3C2410_SPSTA_DCOL	(1 << 2)	/* Data Collision Error */
+#define S3C2410_SPSTA_MULD	(1 << 1)	/* Multi Master Error */
+#define S3C2410_SPSTA_READY	(1 << 0)	/* Data Tx/Rx ready */
+#define S3C2412_SPSTA_READY_ORG	(1 << 3)
+
+#define S3C2410_SPPIN		(0x08)
+
+#define S3C2410_SPPIN_ENMUL	(1 << 2)	/* Multi Master Error detect */
+#define S3C2410_SPPIN_RESERVED	(1 << 1)
+#define S3C2410_SPPIN_KEEP	(1 << 0)	/* Master Out keep */
+
+#define S3C2410_SPPRE		(0x0C)
+#define S3C2410_SPTDAT		(0x10)
+#define S3C2410_SPRDAT		(0x14)
+
+#endif /* __ASM_ARCH_REGS_SPI_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/regs-srom.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/regs-srom.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/regs-srom.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/regs-srom.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,54 @@
+/* linux/arch/arm/plat-samsung/include/plat/regs-srom.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P SROMC 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 __PLAT_SAMSUNG_REGS_SROM_H
+#define __PLAT_SAMSUNG_REGS_SROM_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_SROMREG(x)		(S5P_VA_SROMC + (x))
+
+#define S5P_SROM_BW		S5P_SROMREG(0x0)
+#define S5P_SROM_BC0		S5P_SROMREG(0x4)
+#define S5P_SROM_BC1		S5P_SROMREG(0x8)
+#define S5P_SROM_BC2		S5P_SROMREG(0xc)
+#define S5P_SROM_BC3		S5P_SROMREG(0x10)
+#define S5P_SROM_BC4		S5P_SROMREG(0x14)
+#define S5P_SROM_BC5		S5P_SROMREG(0x18)
+
+/* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */
+
+#define S5P_SROM_BW__DATAWIDTH__SHIFT		0
+#define S5P_SROM_BW__ADDRMODE__SHIFT		1
+#define S5P_SROM_BW__WAITENABLE__SHIFT		2
+#define S5P_SROM_BW__BYTEENABLE__SHIFT		3
+
+#define S5P_SROM_BW__CS_MASK			0xf
+
+#define S5P_SROM_BW__NCS0__SHIFT		0
+#define S5P_SROM_BW__NCS1__SHIFT		4
+#define S5P_SROM_BW__NCS2__SHIFT		8
+#define S5P_SROM_BW__NCS3__SHIFT		12
+#define S5P_SROM_BW__NCS4__SHIFT		16
+#define S5P_SROM_BW__NCS5__SHIFT		20
+
+/* applies to same to BCS0 - BCS3 */
+
+#define S5P_SROM_BCX__PMC__SHIFT		0
+#define S5P_SROM_BCX__TACP__SHIFT		4
+#define S5P_SROM_BCX__TCAH__SHIFT		8
+#define S5P_SROM_BCX__TCOH__SHIFT		12
+#define S5P_SROM_BCX__TACC__SHIFT		16
+#define S5P_SROM_BCX__TCOS__SHIFT		24
+#define S5P_SROM_BCX__TACS__SHIFT		28
+
+#endif /* __PLAT_SAMSUNG_REGS_SROM_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/regs-udc.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/regs-udc.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/regs-udc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/regs-udc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,151 @@
+/* arch/arm/plat-samsung/include/plat/regs-udc.h
+ *
+ * Copyright (C) 2004 Herbert Poetzl <herbert@13thfloor.at>
+ *
+ * This include file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+*/
+
+#ifndef __ASM_ARCH_REGS_UDC_H
+#define __ASM_ARCH_REGS_UDC_H
+
+#define S3C2410_USBDREG(x) (x)
+
+#define S3C2410_UDC_FUNC_ADDR_REG	S3C2410_USBDREG(0x0140)
+#define S3C2410_UDC_PWR_REG		S3C2410_USBDREG(0x0144)
+#define S3C2410_UDC_EP_INT_REG		S3C2410_USBDREG(0x0148)
+
+#define S3C2410_UDC_USB_INT_REG		S3C2410_USBDREG(0x0158)
+#define S3C2410_UDC_EP_INT_EN_REG	S3C2410_USBDREG(0x015c)
+
+#define S3C2410_UDC_USB_INT_EN_REG	S3C2410_USBDREG(0x016c)
+
+#define S3C2410_UDC_FRAME_NUM1_REG	S3C2410_USBDREG(0x0170)
+#define S3C2410_UDC_FRAME_NUM2_REG	S3C2410_USBDREG(0x0174)
+
+#define S3C2410_UDC_EP0_FIFO_REG	S3C2410_USBDREG(0x01c0)
+#define S3C2410_UDC_EP1_FIFO_REG	S3C2410_USBDREG(0x01c4)
+#define S3C2410_UDC_EP2_FIFO_REG	S3C2410_USBDREG(0x01c8)
+#define S3C2410_UDC_EP3_FIFO_REG	S3C2410_USBDREG(0x01cc)
+#define S3C2410_UDC_EP4_FIFO_REG	S3C2410_USBDREG(0x01d0)
+
+#define S3C2410_UDC_EP1_DMA_CON		S3C2410_USBDREG(0x0200)
+#define S3C2410_UDC_EP1_DMA_UNIT	S3C2410_USBDREG(0x0204)
+#define S3C2410_UDC_EP1_DMA_FIFO	S3C2410_USBDREG(0x0208)
+#define S3C2410_UDC_EP1_DMA_TTC_L	S3C2410_USBDREG(0x020c)
+#define S3C2410_UDC_EP1_DMA_TTC_M	S3C2410_USBDREG(0x0210)
+#define S3C2410_UDC_EP1_DMA_TTC_H	S3C2410_USBDREG(0x0214)
+
+#define S3C2410_UDC_EP2_DMA_CON		S3C2410_USBDREG(0x0218)
+#define S3C2410_UDC_EP2_DMA_UNIT	S3C2410_USBDREG(0x021c)
+#define S3C2410_UDC_EP2_DMA_FIFO	S3C2410_USBDREG(0x0220)
+#define S3C2410_UDC_EP2_DMA_TTC_L	S3C2410_USBDREG(0x0224)
+#define S3C2410_UDC_EP2_DMA_TTC_M	S3C2410_USBDREG(0x0228)
+#define S3C2410_UDC_EP2_DMA_TTC_H	S3C2410_USBDREG(0x022c)
+
+#define S3C2410_UDC_EP3_DMA_CON		S3C2410_USBDREG(0x0240)
+#define S3C2410_UDC_EP3_DMA_UNIT	S3C2410_USBDREG(0x0244)
+#define S3C2410_UDC_EP3_DMA_FIFO	S3C2410_USBDREG(0x0248)
+#define S3C2410_UDC_EP3_DMA_TTC_L	S3C2410_USBDREG(0x024c)
+#define S3C2410_UDC_EP3_DMA_TTC_M	S3C2410_USBDREG(0x0250)
+#define S3C2410_UDC_EP3_DMA_TTC_H	S3C2410_USBDREG(0x0254)
+
+#define S3C2410_UDC_EP4_DMA_CON		S3C2410_USBDREG(0x0258)
+#define S3C2410_UDC_EP4_DMA_UNIT	S3C2410_USBDREG(0x025c)
+#define S3C2410_UDC_EP4_DMA_FIFO	S3C2410_USBDREG(0x0260)
+#define S3C2410_UDC_EP4_DMA_TTC_L	S3C2410_USBDREG(0x0264)
+#define S3C2410_UDC_EP4_DMA_TTC_M	S3C2410_USBDREG(0x0268)
+#define S3C2410_UDC_EP4_DMA_TTC_H	S3C2410_USBDREG(0x026c)
+
+#define S3C2410_UDC_INDEX_REG		S3C2410_USBDREG(0x0178)
+
+/* indexed registers */
+
+#define S3C2410_UDC_MAXP_REG		S3C2410_USBDREG(0x0180)
+
+#define S3C2410_UDC_EP0_CSR_REG		S3C2410_USBDREG(0x0184)
+
+#define S3C2410_UDC_IN_CSR1_REG		S3C2410_USBDREG(0x0184)
+#define S3C2410_UDC_IN_CSR2_REG		S3C2410_USBDREG(0x0188)
+
+#define S3C2410_UDC_OUT_CSR1_REG	S3C2410_USBDREG(0x0190)
+#define S3C2410_UDC_OUT_CSR2_REG	S3C2410_USBDREG(0x0194)
+#define S3C2410_UDC_OUT_FIFO_CNT1_REG	S3C2410_USBDREG(0x0198)
+#define S3C2410_UDC_OUT_FIFO_CNT2_REG	S3C2410_USBDREG(0x019c)
+
+#define S3C2410_UDC_FUNCADDR_UPDATE	(1 << 7)
+
+#define S3C2410_UDC_PWR_ISOUP		(1 << 7) /* R/W */
+#define S3C2410_UDC_PWR_RESET		(1 << 3) /* R   */
+#define S3C2410_UDC_PWR_RESUME		(1 << 2) /* R/W */
+#define S3C2410_UDC_PWR_SUSPEND		(1 << 1) /* R   */
+#define S3C2410_UDC_PWR_ENSUSPEND	(1 << 0) /* R/W */
+
+#define S3C2410_UDC_PWR_DEFAULT		(0x00)
+
+#define S3C2410_UDC_INT_EP4		(1 << 4) /* R/W (clear only) */
+#define S3C2410_UDC_INT_EP3		(1 << 3) /* R/W (clear only) */
+#define S3C2410_UDC_INT_EP2		(1 << 2) /* R/W (clear only) */
+#define S3C2410_UDC_INT_EP1		(1 << 1) /* R/W (clear only) */
+#define S3C2410_UDC_INT_EP0		(1 << 0) /* R/W (clear only) */
+
+#define S3C2410_UDC_USBINT_RESET	(1 << 2) /* R/W (clear only) */
+#define S3C2410_UDC_USBINT_RESUME	(1 << 1) /* R/W (clear only) */
+#define S3C2410_UDC_USBINT_SUSPEND	(1 << 0) /* R/W (clear only) */
+
+#define S3C2410_UDC_INTE_EP4		(1 << 4) /* R/W */
+#define S3C2410_UDC_INTE_EP3		(1 << 3) /* R/W */
+#define S3C2410_UDC_INTE_EP2		(1 << 2) /* R/W */
+#define S3C2410_UDC_INTE_EP1		(1 << 1) /* R/W */
+#define S3C2410_UDC_INTE_EP0		(1 << 0) /* R/W */
+
+#define S3C2410_UDC_USBINTE_RESET	(1 << 2) /* R/W */
+#define S3C2410_UDC_USBINTE_SUSPEND	(1 << 0) /* R/W */
+
+#define S3C2410_UDC_INDEX_EP0		(0x00)
+#define S3C2410_UDC_INDEX_EP1		(0x01)
+#define S3C2410_UDC_INDEX_EP2		(0x02)
+#define S3C2410_UDC_INDEX_EP3		(0x03)
+#define S3C2410_UDC_INDEX_EP4		(0x04)
+
+#define S3C2410_UDC_ICSR1_CLRDT		(1 << 6) /* R/W */
+#define S3C2410_UDC_ICSR1_SENTSTL	(1 << 5) /* R/W (clear only) */
+#define S3C2410_UDC_ICSR1_SENDSTL	(1 << 4) /* R/W */
+#define S3C2410_UDC_ICSR1_FFLUSH	(1 << 3) /* W   (set only) */
+#define S3C2410_UDC_ICSR1_UNDRUN	(1 << 2) /* R/W (clear only) */
+#define S3C2410_UDC_ICSR1_PKTRDY	(1 << 0) /* R/W (set only) */
+
+#define S3C2410_UDC_ICSR2_AUTOSET	(1 << 7) /* R/W */
+#define S3C2410_UDC_ICSR2_ISO		(1 << 6) /* R/W */
+#define S3C2410_UDC_ICSR2_MODEIN	(1 << 5) /* R/W */
+#define S3C2410_UDC_ICSR2_DMAIEN	(1 << 4) /* R/W */
+
+#define S3C2410_UDC_OCSR1_CLRDT		(1 << 7) /* R/W */
+#define S3C2410_UDC_OCSR1_SENTSTL	(1 << 6) /* R/W (clear only) */
+#define S3C2410_UDC_OCSR1_SENDSTL	(1 << 5) /* R/W */
+#define S3C2410_UDC_OCSR1_FFLUSH	(1 << 4) /* R/W */
+#define S3C2410_UDC_OCSR1_DERROR	(1 << 3) /* R   */
+#define S3C2410_UDC_OCSR1_OVRRUN	(1 << 2) /* R/W (clear only) */
+#define S3C2410_UDC_OCSR1_PKTRDY	(1 << 0) /* R/W (clear only) */
+
+#define S3C2410_UDC_OCSR2_AUTOCLR	(1 << 7) /* R/W */
+#define S3C2410_UDC_OCSR2_ISO		(1 << 6) /* R/W */
+#define S3C2410_UDC_OCSR2_DMAIEN	(1 << 5) /* R/W */
+
+#define S3C2410_UDC_EP0_CSR_OPKRDY	(1 << 0)
+#define S3C2410_UDC_EP0_CSR_IPKRDY	(1 << 1)
+#define S3C2410_UDC_EP0_CSR_SENTSTL	(1 << 2)
+#define S3C2410_UDC_EP0_CSR_DE		(1 << 3)
+#define S3C2410_UDC_EP0_CSR_SE		(1 << 4)
+#define S3C2410_UDC_EP0_CSR_SENDSTL	(1 << 5)
+#define S3C2410_UDC_EP0_CSR_SOPKTRDY	(1 << 6)
+#define S3C2410_UDC_EP0_CSR_SSE		(1 << 7)
+
+#define S3C2410_UDC_MAXP_8		(1 << 0)
+#define S3C2410_UDC_MAXP_16		(1 << 1)
+#define S3C2410_UDC_MAXP_32		(1 << 2)
+#define S3C2410_UDC_MAXP_64		(1 << 3)
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/reset.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/reset.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/reset.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/reset.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+/* linux/arch/arm/plat-samsung/include/plat/reset.h
+ *
+ * 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.
+*/
+
+#ifndef __PLAT_SAMSUNG_RESET_H
+#define __PLAT_SAMSUNG_RESET_H __FILE__
+
+extern void (*s5p_reset_hook)(void);
+
+#endif /* __PLAT_SAMSUNG_RESET_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c2410.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c2410.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c2410.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c2410.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,33 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c2410.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2410 machine directory
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#ifdef CONFIG_CPU_S3C2410
+
+extern  int s3c2410_init(void);
+extern  int s3c2410a_init(void);
+
+extern void s3c2410_map_io(void);
+
+extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2410_init_clocks(int xtal);
+
+#else
+#define s3c2410_init_clocks NULL
+#define s3c2410_init_uarts NULL
+#define s3c2410_map_io NULL
+#define s3c2410_init NULL
+#define s3c2410a_init NULL
+#endif
+
+extern int s3c2410_baseclk_add(void);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c2412.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c2412.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c2412.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c2412.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c2412.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2412 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.
+*/
+
+#ifdef CONFIG_CPU_S3C2412
+
+extern  int s3c2412_init(void);
+
+extern void s3c2412_map_io(void);
+
+extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2412_init_clocks(int xtal);
+
+extern  int s3c2412_baseclk_add(void);
+#else
+#define s3c2412_init_clocks NULL
+#define s3c2412_init_uarts NULL
+#define s3c2412_map_io NULL
+#define s3c2412_init NULL
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c2416.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c2416.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c2416.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c2416.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,31 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c2416.h
+ *
+ * Copyright (c) 2009 Yauhen Kharuzhy <jekhor@gmail.com>
+ *
+ * Header file for s3c2416 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.
+*/
+
+#ifdef CONFIG_CPU_S3C2416
+
+struct s3c2410_uartcfg;
+
+extern  int s3c2416_init(void);
+
+extern void s3c2416_map_io(void);
+
+extern void s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2416_init_clocks(int xtal);
+
+extern  int s3c2416_baseclk_add(void);
+
+#else
+#define s3c2416_init_clocks NULL
+#define s3c2416_init_uarts NULL
+#define s3c2416_map_io NULL
+#define s3c2416_init NULL
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c2443.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c2443.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c2443.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c2443.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,52 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c2443.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2443 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.
+*/
+
+#ifdef CONFIG_CPU_S3C2443
+
+struct s3c2410_uartcfg;
+
+extern  int s3c2443_init(void);
+
+extern void s3c2443_map_io(void);
+
+extern void s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2443_init_clocks(int xtal);
+
+extern  int s3c2443_baseclk_add(void);
+
+#else
+#define s3c2443_init_clocks NULL
+#define s3c2443_init_uarts NULL
+#define s3c2443_map_io NULL
+#define s3c2443_init NULL
+#endif
+
+/* common code used by s3c2443 and others.
+ * note, not to be used outside of arch/arm/mach-s3c* */
+
+struct clk;	/* some files don't need clk.h otherwise */
+
+typedef unsigned int (*pll_fn)(unsigned int reg, unsigned int base);
+
+extern void s3c2443_common_setup_clocks(pll_fn get_mpll);
+extern void s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
+				       unsigned int *divs, int nr_divs,
+				       int divmask);
+
+extern int s3c2443_clkcon_enable_h(struct clk *clk, int enable);
+extern int s3c2443_clkcon_enable_p(struct clk *clk, int enable);
+extern int s3c2443_clkcon_enable_s(struct clk *clk, int enable);
+
+extern struct clksrc_clk clk_epllref;
+extern struct clksrc_clk clk_esysclk;
+extern struct clksrc_clk clk_msysclk;
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c244x.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c244x.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c244x.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c244x.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,42 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c244x.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C2440 and S3C2442 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.
+*/
+
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
+
+extern void s3c244x_map_io(void);
+
+extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c244x_init_clocks(int xtal);
+
+#else
+#define s3c244x_init_clocks NULL
+#define s3c244x_init_uarts NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2440
+extern  int s3c2440_init(void);
+
+extern void s3c2440_map_io(void);
+#else
+#define s3c2440_init NULL
+#define s3c2440_map_io NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2442
+extern  int s3c2442_init(void);
+
+extern void s3c2442_map_io(void);
+#else
+#define s3c2442_init NULL
+#define s3c2442_map_io NULL
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c6400.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c6400.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c6400.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c6400.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,36 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c6400.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * Header file for s3c6400 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 S3C6400 related SoCs */
+
+extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s3c6400_setup_clocks(void);
+
+extern void s3c64xx_register_clocks(unsigned long xtal, unsigned armclk_limit);
+
+#ifdef CONFIG_CPU_S3C6400
+
+extern  int s3c6400_init(void);
+extern void s3c6400_init_irq(void);
+extern void s3c6400_map_io(void);
+extern void s3c6400_init_clocks(int xtal);
+
+#define s3c6400_init_uarts s3c6400_common_init_uarts
+
+#else
+#define s3c6400_init_clocks NULL
+#define s3c6400_init_uarts NULL
+#define s3c6400_map_io NULL
+#define s3c6400_init NULL
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c6410.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c6410.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c6410.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c6410.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c6410.h
+ *
+ * Copyright 2008 Openmoko,  Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * Header file for s3c6410 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.
+*/
+
+#ifdef CONFIG_CPU_S3C6410
+
+extern  int s3c6410_init(void);
+extern void s3c6410_init_irq(void);
+extern void s3c6410_map_io(void);
+extern void s3c6410_init_clocks(int xtal);
+
+#define s3c6410_init_uarts s3c6400_common_init_uarts
+
+#else
+#define s3c6410_init_clocks NULL
+#define s3c6410_init_uarts NULL
+#define s3c6410_map_io NULL
+#define s3c6410_init NULL
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +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.
- */
-
-#ifndef	__S3C_DMA_PL330_H_
-#define	__S3C_DMA_PL330_H_
-
-#define S3C2410_DMAF_AUTOSTART		(1 << 0)
-#define S3C2410_DMAF_CIRCULAR		(1 << 1)
-
-/*
- * PL330 can assign any channel to communicate with
- * any of the peripherals attched to the DMAC.
- * For the sake of consistency across client drivers,
- * We keep the channel names unchanged and only add
- * missing peripherals are added.
- * Order is not important since S3C PL330 API driver
- * use these just as IDs.
- */
-enum dma_ch {
-	DMACH_UART0_RX,
-	DMACH_UART0_TX,
-	DMACH_UART1_RX,
-	DMACH_UART1_TX,
-	DMACH_UART2_RX,
-	DMACH_UART2_TX,
-	DMACH_UART3_RX,
-	DMACH_UART3_TX,
-	DMACH_UART4_RX,
-	DMACH_UART4_TX,
-	DMACH_UART5_RX,
-	DMACH_UART5_TX,
-	DMACH_USI_RX,
-	DMACH_USI_TX,
-	DMACH_IRDA,
-	DMACH_I2S0_RX,
-	DMACH_I2S0_TX,
-	DMACH_I2S0S_TX,
-	DMACH_I2S1_RX,
-	DMACH_I2S1_TX,
-	DMACH_I2S2_RX,
-	DMACH_I2S2_TX,
-	DMACH_SPI0_RX,
-	DMACH_SPI0_TX,
-	DMACH_SPI1_RX,
-	DMACH_SPI1_TX,
-	DMACH_SPI2_RX,
-	DMACH_SPI2_TX,
-	DMACH_AC97_MICIN,
-	DMACH_AC97_PCMIN,
-	DMACH_AC97_PCMOUT,
-	DMACH_EXTERNAL,
-	DMACH_PWM,
-	DMACH_SPDIF,
-	DMACH_HSI_RX,
-	DMACH_HSI_TX,
-	DMACH_PCM0_TX,
-	DMACH_PCM0_RX,
-	DMACH_PCM1_TX,
-	DMACH_PCM1_RX,
-	DMACH_PCM2_TX,
-	DMACH_PCM2_RX,
-	DMACH_MSM_REQ3,
-	DMACH_MSM_REQ2,
-	DMACH_MSM_REQ1,
-	DMACH_MSM_REQ0,
-	DMACH_SLIMBUS0_RX,
-	DMACH_SLIMBUS0_TX,
-	DMACH_SLIMBUS0AUX_RX,
-	DMACH_SLIMBUS0AUX_TX,
-	DMACH_SLIMBUS1_RX,
-	DMACH_SLIMBUS1_TX,
-	DMACH_SLIMBUS2_RX,
-	DMACH_SLIMBUS2_TX,
-	DMACH_SLIMBUS3_RX,
-	DMACH_SLIMBUS3_TX,
-	DMACH_SLIMBUS4_RX,
-	DMACH_SLIMBUS4_TX,
-	DMACH_SLIMBUS5_RX,
-	DMACH_SLIMBUS5_TX,
-	/* END Marker, also used to denote a reserved channel */
-	DMACH_MAX,
-};
-
-static inline bool s3c_dma_has_circular(void)
-{
-	return true;
-}
-
-#include <plat/dma.h>
-
-#endif	/* __S3C_DMA_PL330_H_ */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
- *
- * 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.
- */
-
-#ifndef __S3C_PL330_PDATA_H
-#define __S3C_PL330_PDATA_H
-
-#include <plat/s3c-dma-pl330.h>
-
-/*
- * Every PL330 DMAC has max 32 peripheral interfaces,
- * of which some may be not be really used in your
- * DMAC's configuration.
- * Populate this array of 32 peri i/fs with relevant
- * channel IDs for used peri i/f and DMACH_MAX for
- * those unused.
- *
- * The platforms just need to provide this info
- * to the S3C DMA API driver for PL330.
- */
-struct s3c_pl330_platdata {
-	enum dma_ch peri[32];
-};
-
-#endif /* __S3C_PL330_PDATA_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s5p6440.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s5p6440.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s5p6440.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s5p6440.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,36 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5p6440.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Header file for s5p6440 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 S5P6440 related SoCs */
+
+extern void s5p6440_register_clocks(void);
+extern void s5p6440_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5P6440
+
+extern  int s5p64x0_init(void);
+extern void s5p6440_init_irq(void);
+extern void s5p6440_map_io(void);
+extern void s5p6440_init_clocks(int xtal);
+
+extern void s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+#else
+#define s5p6440_init_clocks NULL
+#define s5p6440_init_uarts NULL
+#define s5p6440_map_io NULL
+#define s5p64x0_init NULL
+#endif
+
+/* S5P6440 timer */
+
+extern struct sys_timer s5p6440_timer;
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s5p6450.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s5p6450.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s5p6450.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s5p6450.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,36 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5p6450.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Header file for s5p6450 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 S5P6450 related SoCs */
+
+extern void s5p6450_register_clocks(void);
+extern void s5p6450_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5P6450
+
+extern  int s5p64x0_init(void);
+extern void s5p6450_init_irq(void);
+extern void s5p6450_map_io(void);
+extern void s5p6450_init_clocks(int xtal);
+
+extern void s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+#else
+#define s5p6450_init_clocks NULL
+#define s5p6450_init_uarts NULL
+#define s5p6450_map_io NULL
+#define s5p64x0_init NULL
+#endif
+
+/* S5P6450 timer */
+
+extern struct sys_timer s5p6450_timer;
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s5pc100.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s5pc100.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s5pc100.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s5pc100.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,33 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5pc100.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Header file for s5pc100 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 S5PC100 related SoCs */
+
+extern void s5pc100_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s5pc100_register_clocks(void);
+extern void s5pc100_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5PC100
+
+extern  int s5pc100_init(void);
+extern void s5pc100_init_irq(void);
+extern void s5pc100_map_io(void);
+extern void s5pc100_init_clocks(int xtal);
+
+#define s5pc100_init_uarts s5pc100_common_init_uarts
+
+#else
+#define s5pc100_init_clocks NULL
+#define s5pc100_init_uarts NULL
+#define s5pc100_map_io NULL
+#define s5pc100_init NULL
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s5p-clock.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s5p-clock.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s5p-clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s5p-clock.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,55 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5p-clock.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Header file for s5p 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.
+*/
+
+#ifndef __ASM_PLAT_S5P_CLOCK_H
+#define __ASM_PLAT_S5P_CLOCK_H __FILE__
+
+#include <linux/clk.h>
+
+#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
+
+#define clk_fin_apll clk_ext_xtal_mux
+#define clk_fin_mpll clk_ext_xtal_mux
+#define clk_fin_epll clk_ext_xtal_mux
+#define clk_fin_dpll clk_ext_xtal_mux
+#define clk_fin_vpll clk_ext_xtal_mux
+#define clk_fin_hpll clk_ext_xtal_mux
+
+extern struct clk clk_ext_xtal_mux;
+extern struct clk clk_xusbxti;
+extern struct clk clk_48m;
+extern struct clk s5p_clk_27m;
+extern struct clk clk_fout_apll;
+extern struct clk clk_fout_mpll;
+extern struct clk clk_fout_epll;
+extern struct clk clk_fout_dpll;
+extern struct clk clk_fout_vpll;
+extern struct clk clk_arm;
+extern struct clk clk_vpll;
+
+extern struct clksrc_sources clk_src_apll;
+extern struct clksrc_sources clk_src_mpll;
+extern struct clksrc_sources clk_src_epll;
+extern struct clksrc_sources clk_src_dpll;
+
+extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);
+
+/* Common EPLL operations for S5P platform */
+extern int s5p_epll_enable(struct clk *clk, int enable);
+extern unsigned long s5p_epll_get_rate(struct clk *clk);
+
+/* SPDIF clk operations common for S5PC100/V210/C110 and Exynos4 */
+extern int s5p_spdif_set_rate(struct clk *clk, unsigned long rate);
+extern unsigned long s5p_spdif_get_rate(struct clk *clk);
+
+extern struct clk_ops s5p_sclk_spdif_ops;
+#endif /* __ASM_PLAT_S5P_CLOCK_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s5p-time.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s5p-time.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s5p-time.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s5p-time.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,40 @@
+/* linux/arch/arm/plat-samsung/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-3.1-gnu/arch/arm/plat-samsung/include/plat/s5pv210.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s5pv210.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/s5pv210.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/s5pv210.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,33 @@
+/* linux/arch/arm/plat-samsung/include/plat/s5pv210.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Header file for s5pv210 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 S5PV210 related SoCs */
+
+extern void s5pv210_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s5pv210_register_clocks(void);
+extern void s5pv210_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5PV210
+
+extern  int s5pv210_init(void);
+extern void s5pv210_init_irq(void);
+extern void s5pv210_map_io(void);
+extern void s5pv210_init_clocks(int xtal);
+
+#define s5pv210_init_uarts s5pv210_common_init_uarts
+
+#else
+#define s5pv210_init_clocks NULL
+#define s5pv210_init_uarts NULL
+#define s5pv210_map_io NULL
+#define s5pv210_init NULL
+#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/sdhci.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/sdhci.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/sdhci.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/sdhci.h	2012-01-04 18:55:44.000000000 -0500
@@ -55,10 +55,6 @@
  *		 cd_type == S3C_SDHCI_CD_GPIO
  * @ext_cd_gpio_invert: invert values for external CD gpio line
  * @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 dependent on
- *	      the card and speed of operation.
  *
  * Initialisation data specific to either the machine or the platform
  * for the device driver to use or call-back when configuring gpio or
@@ -80,12 +76,15 @@
 						      int state));
 
 	void	(*cfg_gpio)(struct platform_device *dev, int width);
-	void	(*cfg_card)(struct platform_device *dev,
-			    void __iomem *regbase,
-			    struct mmc_ios *ios,
-			    struct mmc_card *card);
 };
 
+/* s3c_sdhci_set_platdata() - common helper for setting SDHCI platform data
+ * @pd: The default platform data for this device.
+ * @set: Pointer to the platform data to fill in.
+ */
+extern void s3c_sdhci_set_platdata(struct s3c_sdhci_platdata *pd,
+				    struct s3c_sdhci_platdata *set);
+
 /**
  * s3c_sdhci0_set_platdata - Set platform data for S3C SDHCI device.
  * @pd: Platform data to register to device.
@@ -132,17 +131,11 @@
 #ifdef CONFIG_S3C2416_SETUP_SDHCI
 extern char *s3c2416_hsmmc_clksrcs[4];
 
-extern void s3c2416_setup_sdhci_cfg_card(struct platform_device *dev,
-					   void __iomem *r,
-					   struct mmc_ios *ios,
-					   struct mmc_card *card);
-
 static inline void s3c2416_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
 	s3c_hsmmc0_def_platdata.clocks = s3c2416_hsmmc_clksrcs;
 	s3c_hsmmc0_def_platdata.cfg_gpio = s3c2416_setup_sdhci0_cfg_gpio;
-	s3c_hsmmc0_def_platdata.cfg_card = s3c2416_setup_sdhci_cfg_card;
 #endif /* CONFIG_S3C_DEV_HSMMC */
 }
 
@@ -151,7 +144,6 @@
 #ifdef CONFIG_S3C_DEV_HSMMC1
 	s3c_hsmmc1_def_platdata.clocks = s3c2416_hsmmc_clksrcs;
 	s3c_hsmmc1_def_platdata.cfg_gpio = s3c2416_setup_sdhci1_cfg_gpio;
-	s3c_hsmmc1_def_platdata.cfg_card = s3c2416_setup_sdhci_cfg_card;
 #endif /* CONFIG_S3C_DEV_HSMMC1 */
 }
 
@@ -165,17 +157,11 @@
 #ifdef CONFIG_S3C64XX_SETUP_SDHCI
 extern char *s3c64xx_hsmmc_clksrcs[4];
 
-extern void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev,
-					 void __iomem *r,
-					 struct mmc_ios *ios,
-					 struct mmc_card *card);
-
 static inline void s3c6400_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
 	s3c_hsmmc0_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
 	s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
-	s3c_hsmmc0_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -184,7 +170,6 @@
 #ifdef CONFIG_S3C_DEV_HSMMC1
 	s3c_hsmmc1_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
 	s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
-	s3c_hsmmc1_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -193,21 +178,14 @@
 #ifdef CONFIG_S3C_DEV_HSMMC2
 	s3c_hsmmc2_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
 	s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio;
-	s3c_hsmmc2_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
 #endif
 }
 
-extern void s3c6410_setup_sdhci_cfg_card(struct platform_device *dev,
-					 void __iomem *r,
-					 struct mmc_ios *ios,
-					 struct mmc_card *card);
-
 static inline void s3c6410_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
 	s3c_hsmmc0_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
 	s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
-	s3c_hsmmc0_def_platdata.cfg_card = s3c6410_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -216,7 +194,6 @@
 #ifdef CONFIG_S3C_DEV_HSMMC1
 	s3c_hsmmc1_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
 	s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
-	s3c_hsmmc1_def_platdata.cfg_card = s3c6410_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -225,7 +202,6 @@
 #ifdef CONFIG_S3C_DEV_HSMMC2
 	s3c_hsmmc2_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
 	s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio;
-	s3c_hsmmc2_def_platdata.cfg_card = s3c6410_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -244,17 +220,11 @@
 #ifdef CONFIG_S5PC100_SETUP_SDHCI
 extern char *s5pc100_hsmmc_clksrcs[4];
 
-extern void s5pc100_setup_sdhci0_cfg_card(struct platform_device *dev,
-					   void __iomem *r,
-					   struct mmc_ios *ios,
-					   struct mmc_card *card);
-
 static inline void s5pc100_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
 	s3c_hsmmc0_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
 	s3c_hsmmc0_def_platdata.cfg_gpio = s5pc100_setup_sdhci0_cfg_gpio;
-	s3c_hsmmc0_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card;
 #endif
 }
 
@@ -263,7 +233,6 @@
 #ifdef CONFIG_S3C_DEV_HSMMC1
 	s3c_hsmmc1_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
 	s3c_hsmmc1_def_platdata.cfg_gpio = s5pc100_setup_sdhci1_cfg_gpio;
-	s3c_hsmmc1_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card;
 #endif
 }
 
@@ -272,7 +241,6 @@
 #ifdef CONFIG_S3C_DEV_HSMMC2
 	s3c_hsmmc2_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
 	s3c_hsmmc2_def_platdata.cfg_gpio = s5pc100_setup_sdhci2_cfg_gpio;
-	s3c_hsmmc2_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card;
 #endif
 }
 
@@ -288,17 +256,11 @@
 #ifdef CONFIG_S5PV210_SETUP_SDHCI
 extern char *s5pv210_hsmmc_clksrcs[4];
 
-extern void s5pv210_setup_sdhci_cfg_card(struct platform_device *dev,
-					   void __iomem *r,
-					   struct mmc_ios *ios,
-					   struct mmc_card *card);
-
 static inline void s5pv210_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
 	s3c_hsmmc0_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
 	s3c_hsmmc0_def_platdata.cfg_gpio = s5pv210_setup_sdhci0_cfg_gpio;
-	s3c_hsmmc0_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -307,7 +269,6 @@
 #ifdef CONFIG_S3C_DEV_HSMMC1
 	s3c_hsmmc1_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
 	s3c_hsmmc1_def_platdata.cfg_gpio = s5pv210_setup_sdhci1_cfg_gpio;
-	s3c_hsmmc1_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -316,7 +277,6 @@
 #ifdef CONFIG_S3C_DEV_HSMMC2
 	s3c_hsmmc2_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
 	s3c_hsmmc2_def_platdata.cfg_gpio = s5pv210_setup_sdhci2_cfg_gpio;
-	s3c_hsmmc2_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -325,7 +285,6 @@
 #ifdef CONFIG_S3C_DEV_HSMMC3
 	s3c_hsmmc3_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
 	s3c_hsmmc3_def_platdata.cfg_gpio = s5pv210_setup_sdhci3_cfg_gpio;
-	s3c_hsmmc3_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -341,17 +300,11 @@
 #ifdef CONFIG_EXYNOS4_SETUP_SDHCI
 extern char *exynos4_hsmmc_clksrcs[4];
 
-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 exynos4_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
 	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
 }
 
@@ -360,7 +313,6 @@
 #ifdef CONFIG_S3C_DEV_HSMMC1
 	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
 }
 
@@ -369,7 +321,6 @@
 #ifdef CONFIG_S3C_DEV_HSMMC2
 	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
 }
 
@@ -378,7 +329,6 @@
 #ifdef CONFIG_S3C_DEV_HSMMC3
 	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
 }
 
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/sysmmu.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/sysmmu.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/sysmmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/sysmmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,95 @@
+/* linux/arch/arm/plat-samsung/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 __PLAT_SAMSUNG_SYSMMU_H
+#define __PLAT_SAMSUNG_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-3.1-gnu/arch/arm/plat-samsung/include/plat/system-reset.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/system-reset.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/system-reset.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/system-reset.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,31 @@
+/* linux/arch/arm/plat-samsung/include/plat/system-reset.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Based on arch/arm/mach-s3c2410/include/mach/system-reset.h
+ *
+ * S5P - System define for arch_reset()
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <plat/watchdog-reset.h>
+
+void (*s5p_reset_hook)(void);
+
+static void arch_reset(char mode, const char *cmd)
+{
+	/* SWRESET support in s5p_reset_hook() */
+
+	if (s5p_reset_hook)
+		s5p_reset_hook();
+
+	/* Perform reset using Watchdog reset
+	 * if there is no s5p_reset_hook()
+	 */
+
+	arch_wdt_reset();
+}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/tv-core.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/tv-core.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/tv-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/tv-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/plat-samsung/include/plat/tv.h
+ *
+ * Copyright 2011 Samsung Electronics Co., Ltd.
+ *	Tomasz Stanislawski <t.stanislaws@samsung.com>
+ *
+ * Samsung TV driver core 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 __SAMSUNG_PLAT_TV_H
+#define __SAMSUNG_PLAT_TV_H __FILE__
+
+/*
+ * These functions are only for use with the core support code, such as
+ * the CPU-specific initialization code.
+ */
+
+/* Re-define device name to differentiate the subsystem in various SoCs. */
+static inline void s5p_hdmi_setname(char *name)
+{
+#ifdef CONFIG_S5P_DEV_TV
+	s5p_device_hdmi.name = name;
+#endif
+}
+
+static inline void s5p_mixer_setname(char *name)
+{
+#ifdef CONFIG_S5P_DEV_TV
+	s5p_device_mixer.name = name;
+#endif
+}
+
+static inline void s5p_sdo_setname(char *name)
+{
+#ifdef CONFIG_S5P_DEV_TV
+	s5p_device_sdo.name = name;
+#endif
+}
+
+#endif /* __SAMSUNG_PLAT_TV_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/udc.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/udc.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/udc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/udc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,57 @@
+/* arch/arm/plat-samsung/include/plat/udc.h
+ *
+ * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *
+ *  Changelog:
+ *	14-Mar-2005	RTP	Created file
+ *	02-Aug-2005	RTP	File rename
+ *	07-Sep-2005	BJD	Minor cleanups, changed cmd to enum
+ *	18-Jan-2007	HMW	Add per-platform vbus_draw function
+*/
+
+#ifndef __ASM_ARM_ARCH_UDC_H
+#define __ASM_ARM_ARCH_UDC_H
+
+enum s3c2410_udc_cmd_e {
+	S3C2410_UDC_P_ENABLE	= 1,	/* Pull-up enable        */
+	S3C2410_UDC_P_DISABLE	= 2,	/* Pull-up disable       */
+	S3C2410_UDC_P_RESET	= 3,	/* UDC reset, in case of */
+};
+
+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;
+};
+
+extern void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *);
+
+/**
+ * s3c24xx_hsudc_platdata - Platform data for USB High-Speed gadget controller.
+ * @epnum: Number of endpoints to be instantiated by the controller driver.
+ * @gpio_init: Platform specific USB related GPIO initialization.
+ * @gpio_uninit: Platform specific USB releted GPIO uninitialzation.
+ *
+ * Representation of platform data for the S3C24XX USB 2.0 High Speed gadget
+ * controllers.
+ */
+struct s3c24xx_hsudc_platdata {
+	unsigned int	epnum;
+	void		(*gpio_init)(void);
+	void		(*gpio_uninit)(void);
+};
+
+extern void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd);
+
+#endif /* __ASM_ARM_ARCH_UDC_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/usb-phy.h linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/usb-phy.h
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/include/plat/usb-phy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/include/plat/usb-phy.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef __PLAT_SAMSUNG_USB_PHY_H
+#define __PLAT_SAMSUNG_USB_PHY_H __FILE__
+
+enum s5p_usb_phy_type {
+	S5P_USB_PHY_DEVICE,
+	S5P_USB_PHY_HOST,
+};
+
+extern int s5p_usb_phy_init(struct platform_device *pdev, int type);
+extern int s5p_usb_phy_exit(struct platform_device *pdev, int type);
+
+#endif /* __PLAT_SAMSUNG_USB_PHY_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/irq-uart.c linux-libre-3.2-gnu/arch/arm/plat-samsung/irq-uart.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/irq-uart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/irq-uart.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,96 +0,0 @@
-/* arch/arm/plat-samsung/irq-uart.c
- *	originally part of arch/arm/plat-s3c64xx/irq.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * Samsung- UART Interrupt handling
- *
- * This program is free software; you can 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/serial_core.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/map.h>
-#include <plat/irq-uart.h>
-#include <plat/regs-serial.h>
-#include <plat/cpu.h>
-
-/* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
- * are consecutive when looking up the interrupt in the demux routines.
- */
-static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
-{
-	struct s3c_uart_irq *uirq = desc->irq_data.handler_data;
-	struct irq_chip *chip = irq_get_chip(irq);
-	u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP);
-	int base = uirq->base_irq;
-
-	chained_irq_enter(chip, desc);
-
-	if (pend & (1 << 0))
-		generic_handle_irq(base);
-	if (pend & (1 << 1))
-		generic_handle_irq(base + 1);
-	if (pend & (1 << 2))
-		generic_handle_irq(base + 2);
-	if (pend & (1 << 3))
-		generic_handle_irq(base + 3);
-
-	chained_irq_exit(chip, desc);
-}
-
-static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq)
-{
-	void __iomem *reg_base = uirq->regs;
-	struct irq_chip_generic *gc;
-	struct irq_chip_type *ct;
-
-	/* mask all interrupts at the start. */
-	__raw_writel(0xf, reg_base + S3C64XX_UINTM);
-
-	gc = irq_alloc_generic_chip("s3c-uart", 1, uirq->base_irq, reg_base,
-				    handle_level_irq);
-
-	if (!gc) {
-		pr_err("%s: irq_alloc_generic_chip for IRQ %u failed\n",
-		       __func__, uirq->base_irq);
-		return;
-	}
-
-	ct = gc->chip_types;
-	ct->chip.irq_ack = irq_gc_ack_set_bit;
-	ct->chip.irq_mask = irq_gc_mask_set_bit;
-	ct->chip.irq_unmask = irq_gc_mask_clr_bit;
-	ct->regs.ack = S3C64XX_UINTP;
-	ct->regs.mask = S3C64XX_UINTM;
-	irq_setup_generic_chip(gc, IRQ_MSK(4), IRQ_GC_INIT_MASK_CACHE,
-			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
-
-	irq_set_handler_data(uirq->parent_irq, uirq);
-	irq_set_chained_handler(uirq->parent_irq, s3c_irq_demux_uart);
-}
-
-/**
- * s3c_init_uart_irqs() - initialise UART IRQs and the necessary demuxing
- * @irq: The interrupt data for registering
- * @nr_irqs: The number of interrupt descriptions in @irq.
- *
- * Register the UART interrupts specified by @irq including the demuxing
- * routines. This supports the S3C6400 and newer style of devices.
- */
-void __init s3c_init_uart_irqs(struct s3c_uart_irq *irq, unsigned int nr_irqs)
-{
-	for (; nr_irqs > 0; nr_irqs--, irq++)
-		s3c_init_uart_irq(irq);
-}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/Kconfig linux-libre-3.2-gnu/arch/arm/plat-samsung/Kconfig
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -65,11 +65,6 @@
        help
          Internal configuration to build the VIC timer interrupt code.
 
-config SAMSUNG_IRQ_UART
-       bool
-       help
-         Internal configuration to build the IRQ UART demux code.
-
 # options for gpio configuration support
 
 config SAMSUNG_GPIOLIB_4BIT
@@ -79,39 +74,12 @@
 	  configuration. GPIOlib shall be compiled only for S3C64XX and S5P
 	  series of processors.
 
-config S3C_GPIO_CFG_S3C24XX
-	bool
-	help
-	  Internal configuration to enable S3C24XX style GPIO configuration
-	  functions.
-
 config S3C_GPIO_CFG_S3C64XX
 	bool
 	help
 	  Internal configuration to enable S3C64XX style GPIO configuration
 	  functions.
 
-config S3C_GPIO_PULL_UPDOWN
-	bool
-	help
-	  Internal configuration to enable the correct GPIO pull helper
-
-config S3C_GPIO_PULL_S3C2443
-	bool
-	select S3C_GPIO_PULL_UPDOWN
-	help
-	  Internal configuration to enable the correct GPIO pull helper for S3C2443-style GPIO
-
-config S3C_GPIO_PULL_DOWN
-	bool
-	help
-	  Internal configuration to enable the correct GPIO pull helper
-
-config S3C_GPIO_PULL_UP
-	bool
-	help
-	  Internal configuration to enable the correct GPIO pull helper
-
 config S5P_GPIO_DRVSTR
 	bool
 	help
@@ -300,11 +268,14 @@
 	help
 	  Internal configuration for S3C DMA core
 
-config S3C_PL330_DMA
+config SAMSUNG_DMADEV
 	bool
-	select PL330
+	select DMADEVICES
+	select PL330_DMA if (CPU_EXYNOS4210 || CPU_S5PV210 || CPU_S5PC100 || \
+					CPU_S5P6450 || CPU_S5P6440)
+	select ARM_AMBA
 	help
-	  S3C DMA API Driver for PL330 DMAC.
+	  Use DMA device engine for PL330 DMAC.
 
 comment "Power management"
 
@@ -367,4 +338,11 @@
 	help
 	  Say Y here if you want to control Power Domain by Runtime PM.
 
+config DEBUG_S3C_UART
+	depends on PLAT_SAMSUNG
+	int
+	default "0" if DEBUG_S3C_UART0
+	default "1" if DEBUG_S3C_UART1
+	default "2" if DEBUG_S3C_UART2
+
 endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/Makefile linux-libre-3.2-gnu/arch/arm/plat-samsung/Makefile
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-# arch/arm/plat-s3c64xx/Makefile
+# arch/arm/plat-samsung/Makefile
 #
 # Copyright 2009 Simtec Electronics
 #
@@ -11,17 +11,13 @@
 
 # Objects we always build independent of SoC choice
 
-obj-y				+= init.o
+obj-y				+= init.o cpu.o
 obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET)   += time.o
 obj-y				+= clock.o
 obj-y				+= pwm-clock.o
-obj-y				+= gpio.o
-obj-y				+= gpio-config.o
-obj-y				+= dev-asocdma.o
 
 obj-$(CONFIG_SAMSUNG_CLKSRC)	+= clock-clksrc.o
 
-obj-$(CONFIG_SAMSUNG_IRQ_UART)	+= irq-uart.o
 obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o
 
 # ADC
@@ -32,40 +28,16 @@
 
 obj-y				+= platformdata.o
 
-obj-$(CONFIG_S3C_DEV_HSMMC)	+= dev-hsmmc.o
-obj-$(CONFIG_S3C_DEV_HSMMC1)	+= dev-hsmmc1.o
-obj-$(CONFIG_S3C_DEV_HSMMC2)	+= dev-hsmmc2.o
-obj-$(CONFIG_S3C_DEV_HSMMC3)	+= dev-hsmmc3.o
-obj-$(CONFIG_S3C_DEV_HWMON)	+= dev-hwmon.o
-obj-y				+= dev-i2c0.o
-obj-$(CONFIG_S3C_DEV_I2C1)	+= dev-i2c1.o
-obj-$(CONFIG_S3C_DEV_I2C2)	+= dev-i2c2.o
-obj-$(CONFIG_S3C_DEV_I2C3)	+= dev-i2c3.o
-obj-$(CONFIG_S3C_DEV_I2C4)	+= dev-i2c4.o
-obj-$(CONFIG_S3C_DEV_I2C5)	+= dev-i2c5.o
-obj-$(CONFIG_S3C_DEV_I2C6)	+= dev-i2c6.o
-obj-$(CONFIG_S3C_DEV_I2C7)	+= dev-i2c7.o
-obj-$(CONFIG_S3C_DEV_FB)	+= dev-fb.o
+obj-y				+= devs.o
 obj-y				+= dev-uart.o
-obj-$(CONFIG_S3C_DEV_USB_HOST)	+= dev-usb.o
-obj-$(CONFIG_S3C_DEV_USB_HSOTG)	+= dev-usb-hsotg.o
-obj-$(CONFIG_S3C_DEV_WDT)	+= dev-wdt.o
-obj-$(CONFIG_S3C_DEV_NAND)	+= dev-nand.o
-obj-$(CONFIG_S3C_DEV_ONENAND)	+= dev-onenand.o
-obj-$(CONFIG_S3C_DEV_RTC)	+= dev-rtc.o
 
-obj-$(CONFIG_SAMSUNG_DEV_ADC)	+= dev-adc.o
-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
 obj-$(CONFIG_SAMSUNG_DEV_BACKLIGHT)	+= dev-backlight.o
 
 # DMA support
 
-obj-$(CONFIG_S3C_DMA)		+= dma.o
+obj-$(CONFIG_S3C_DMA)		+= dma.o s3c-dma-ops.o
 
-obj-$(CONFIG_S3C_PL330_DMA)	+= s3c-pl330.o
+obj-$(CONFIG_SAMSUNG_DMADEV)	+= dma-ops.o
 
 # PM support
 
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/pd.c linux-libre-3.2-gnu/arch/arm/plat-samsung/pd.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/pd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/pd.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
 */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
 #include <linux/pm_runtime.h>
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/platformdata.c linux-libre-3.2-gnu/arch/arm/plat-samsung/platformdata.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/platformdata.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/platformdata.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,10 +10,12 @@
 */
 
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/platform_device.h>
 
 #include <plat/devs.h>
+#include <plat/sdhci.h>
 
 void __init *s3c_set_platdata(void *pd, size_t pdsize,
 			      struct platform_device *pdev)
@@ -35,3 +37,22 @@
 	pdev->dev.platform_data = npd;
 	return npd;
 }
+
+void s3c_sdhci_set_platdata(struct s3c_sdhci_platdata *pd,
+			     struct s3c_sdhci_platdata *set)
+{
+	set->cd_type = pd->cd_type;
+	set->ext_cd_init = pd->ext_cd_init;
+	set->ext_cd_cleanup = pd->ext_cd_cleanup;
+	set->ext_cd_gpio = pd->ext_cd_gpio;
+	set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
+
+	if (pd->max_width)
+		set->max_width = pd->max_width;
+	if (pd->cfg_gpio)
+		set->cfg_gpio = pd->cfg_gpio;
+	if (pd->host_caps)
+		set->host_caps |= pd->host_caps;
+	if (pd->clk_type)
+		set->clk_type = pd->clk_type;
+}
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/pm.c linux-libre-3.2-gnu/arch/arm/plat-samsung/pm.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -268,8 +268,8 @@
 
 	/* save all necessary core registers not covered by the drivers */
 
-	s3c_pm_save_gpios();
-	s3c_pm_saved_gpios();
+	samsung_pm_save_gpios();
+	samsung_pm_saved_gpios();
 	s3c_pm_save_uarts();
 	s3c_pm_save_core();
 
@@ -306,7 +306,7 @@
 
 	s3c_pm_restore_core();
 	s3c_pm_restore_uarts();
-	s3c_pm_restore_gpios();
+	samsung_pm_restore_gpios();
 	s3c_pm_restored_gpios();
 
 	s3c_pm_debug_init();
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/pm-gpio.c linux-libre-3.2-gnu/arch/arm/plat-samsung/pm-gpio.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/pm-gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/pm-gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,13 +28,13 @@
 #define OFFS_DAT	(0x04)
 #define OFFS_UP		(0x08)
 
-static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_1bit_save(struct samsung_gpio_chip *chip)
 {
 	chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
 	chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
 }
 
-static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_1bit_resume(struct samsung_gpio_chip *chip)
 {
 	void __iomem *base = chip->base;
 	u32 old_gpcon = __raw_readl(base + OFFS_CON);
@@ -60,12 +60,12 @@
 		  chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
 }
 
-struct s3c_gpio_pm s3c_gpio_pm_1bit = {
-	.save	= s3c_gpio_pm_1bit_save,
-	.resume = s3c_gpio_pm_1bit_resume,
+struct samsung_gpio_pm samsung_gpio_pm_1bit = {
+	.save	= samsung_gpio_pm_1bit_save,
+	.resume = samsung_gpio_pm_1bit_resume,
 };
 
-static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_2bit_save(struct samsung_gpio_chip *chip)
 {
 	chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
 	chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
@@ -95,7 +95,7 @@
 }
 
 /**
- * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank
+ * samsung_gpio_pm_2bit_resume() - restore the given GPIO bank
  * @chip: The chip information to resume.
  *
  * Restore one of the GPIO banks that was saved during suspend. This is
@@ -121,7 +121,7 @@
  * [1] this assumes that writing to a pin DAT whilst in SFN will set the
  *     state for when it is next output.
  */
-static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_2bit_resume(struct samsung_gpio_chip *chip)
 {
 	void __iomem *base = chip->base;
 	u32 old_gpcon = __raw_readl(base + OFFS_CON);
@@ -187,13 +187,13 @@
 		  chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
 }
 
-struct s3c_gpio_pm s3c_gpio_pm_2bit = {
-	.save	= s3c_gpio_pm_2bit_save,
-	.resume = s3c_gpio_pm_2bit_resume,
+struct samsung_gpio_pm samsung_gpio_pm_2bit = {
+	.save	= samsung_gpio_pm_2bit_save,
+	.resume = samsung_gpio_pm_2bit_resume,
 };
 
 #if defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_PLAT_S5P)
-static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_4bit_save(struct samsung_gpio_chip *chip)
 {
 	chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
 	chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
@@ -203,7 +203,7 @@
 		chip->pm_save[0] = __raw_readl(chip->base - 4);
 }
 
-static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
+static u32 samsung_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
 {
 	u32 old, new, mask;
 	u32 change_mask = 0x0;
@@ -242,14 +242,14 @@
 	return change_mask;
 }
 
-static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
+static void samsung_gpio_pm_4bit_con(struct samsung_gpio_chip *chip, int index)
 {
 	void __iomem *con = chip->base + (index * 4);
 	u32 old_gpcon = __raw_readl(con);
 	u32 gps_gpcon = chip->pm_save[index + 1];
 	u32 gpcon, mask;
 
-	mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
+	mask = samsung_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
 
 	gpcon = old_gpcon & ~mask;
 	gpcon |= gps_gpcon & mask;
@@ -257,7 +257,7 @@
 	__raw_writel(gpcon, con);
 }
 
-static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_4bit_resume(struct samsung_gpio_chip *chip)
 {
 	void __iomem *base = chip->base;
 	u32 old_gpcon[2];
@@ -269,10 +269,10 @@
 	old_gpcon[0] = 0;
 	old_gpcon[1] = __raw_readl(base + OFFS_CON);
 
-	s3c_gpio_pm_4bit_con(chip, 0);
+	samsung_gpio_pm_4bit_con(chip, 0);
 	if (chip->chip.ngpio > 8) {
 		old_gpcon[0] = __raw_readl(base - 4);
-		s3c_gpio_pm_4bit_con(chip, -1);
+		samsung_gpio_pm_4bit_con(chip, -1);
 	}
 
 	/* Now change the configurations that require DAT,CON */
@@ -298,19 +298,19 @@
 			  old_gpdat, gps_gpdat);
 }
 
-struct s3c_gpio_pm s3c_gpio_pm_4bit = {
-	.save	= s3c_gpio_pm_4bit_save,
-	.resume = s3c_gpio_pm_4bit_resume,
+struct samsung_gpio_pm samsung_gpio_pm_4bit = {
+	.save	= samsung_gpio_pm_4bit_save,
+	.resume = samsung_gpio_pm_4bit_resume,
 };
 #endif /* CONFIG_ARCH_S3C64XX || CONFIG_PLAT_S5P */
 
 /**
- * s3c_pm_save_gpio() - save gpio chip data for suspend
+ * samsung_pm_save_gpio() - save gpio chip data for suspend
  * @ourchip: The chip for suspend.
  */
-static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip)
+static void samsung_pm_save_gpio(struct samsung_gpio_chip *ourchip)
 {
-	struct s3c_gpio_pm *pm = ourchip->pm;
+	struct samsung_gpio_pm *pm = ourchip->pm;
 
 	if (pm == NULL || pm->save == NULL)
 		S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
@@ -319,24 +319,24 @@
 }
 
 /**
- * s3c_pm_save_gpios() - Save the state of the GPIO banks.
+ * samsung_pm_save_gpios() - Save the state of the GPIO banks.
  *
  * For all the GPIO banks, save the state of each one ready for going
  * into a suspend mode.
  */
-void s3c_pm_save_gpios(void)
+void samsung_pm_save_gpios(void)
 {
-	struct s3c_gpio_chip *ourchip;
+	struct samsung_gpio_chip *ourchip;
 	unsigned int gpio_nr;
 
 	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
-		ourchip = s3c_gpiolib_getchip(gpio_nr);
+		ourchip = samsung_gpiolib_getchip(gpio_nr);
 		if (!ourchip) {
 			gpio_nr++;
 			continue;
 		}
 
-		s3c_pm_save_gpio(ourchip);
+		samsung_pm_save_gpio(ourchip);
 
 		S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
 			  ourchip->chip.label,
@@ -351,12 +351,12 @@
 }
 
 /**
- * s3c_pm_resume_gpio() - restore gpio chip data after suspend
+ * samsung_pm_resume_gpio() - restore gpio chip data after suspend
  * @ourchip: The suspended chip.
  */
-static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
+static void samsung_pm_resume_gpio(struct samsung_gpio_chip *ourchip)
 {
-	struct s3c_gpio_pm *pm = ourchip->pm;
+	struct samsung_gpio_pm *pm = ourchip->pm;
 
 	if (pm == NULL || pm->resume == NULL)
 		S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
@@ -364,19 +364,19 @@
 		pm->resume(ourchip);
 }
 
-void s3c_pm_restore_gpios(void)
+void samsung_pm_restore_gpios(void)
 {
-	struct s3c_gpio_chip *ourchip;
+	struct samsung_gpio_chip *ourchip;
 	unsigned int gpio_nr;
 
 	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
-		ourchip = s3c_gpiolib_getchip(gpio_nr);
+		ourchip = samsung_gpiolib_getchip(gpio_nr);
 		if (!ourchip) {
 			gpio_nr++;
 			continue;
 		}
 
-		s3c_pm_resume_gpio(ourchip);
+		samsung_pm_resume_gpio(ourchip);
 
 		gpio_nr += ourchip->chip.ngpio;
 		gpio_nr += CONFIG_S3C_GPIO_SPACE;
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/pwm.c linux-libre-3.2-gnu/arch/arm/plat-samsung/pwm.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/pwm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/pwm.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  * the Free Software Foundation; either version 2 of the License.
 */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -299,6 +299,9 @@
 		goto err_clk_tin;
 	}
 
+	clk_enable(pwm->clk);
+	clk_enable(pwm->clk_div);
+
 	local_irq_save(flags);
 
 	tcon = __raw_readl(S3C2410_TCON);
@@ -326,6 +329,8 @@
 	return 0;
 
  err_clk_tdiv:
+	clk_disable(pwm->clk_div);
+	clk_disable(pwm->clk);
 	clk_put(pwm->clk_div);
 
  err_clk_tin:
@@ -340,6 +345,8 @@
 {
 	struct pwm_device *pwm = platform_get_drvdata(pdev);
 
+	clk_disable(pwm->clk_div);
+	clk_disable(pwm->clk);
 	clk_put(pwm->clk_div);
 	clk_put(pwm->clk);
 	kfree(pwm);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/pwm-clock.c linux-libre-3.2-gnu/arch/arm/plat-samsung/pwm-clock.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/pwm-clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/pwm-clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,7 @@
 #include <plat/cpu.h>
 
 #include <plat/regs-timer.h>
-#include <mach/pwm-clock.h>
+#include <plat/pwm-clock.h>
 
 /* Each of the timers 0 through 5 go through the following
  * clock tree, with the inputs depending on the timers.
@@ -339,8 +339,17 @@
 	unsigned long bits;
 	unsigned long shift = S3C2410_TCFG1_SHIFT(id);
 
+	unsigned long mux_tclk;
+
+	if (soc_is_s3c24xx())
+		mux_tclk = S3C2410_TCFG1_MUX_TCLK;
+	else if (soc_is_s5p6440() || soc_is_s5p6450())
+		mux_tclk = 0;
+	else
+		mux_tclk = S3C64XX_TCFG1_MUX_TCLK;
+
 	if (parent == s3c24xx_pwmclk_tclk(id))
-		bits = S3C_TCFG1_MUX_TCLK << shift;
+		bits = mux_tclk << shift;
 	else if (parent == s3c24xx_pwmclk_tdiv(id))
 		bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift;
 	else
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/s3c-dma-ops.c linux-libre-3.2-gnu/arch/arm/plat-samsung/s3c-dma-ops.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/s3c-dma-ops.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/s3c-dma-ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,131 @@
+/* linux/arch/arm/plat-samsung/s3c-dma-ops.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung S3C-DMA Operations
+ *
+ * This program is free software; you can 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/slab.h>
+#include <linux/types.h>
+#include <linux/export.h>
+
+#include <mach/dma.h>
+
+struct cb_data {
+	void (*fp) (void *);
+	void *fp_param;
+	unsigned ch;
+	struct list_head node;
+};
+
+static LIST_HEAD(dma_list);
+
+static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param,
+		       int size, enum s3c2410_dma_buffresult res)
+{
+	struct cb_data *data = param;
+
+	data->fp(data->fp_param);
+}
+
+static unsigned s3c_dma_request(enum dma_ch dma_ch,
+				 struct samsung_dma_info *info)
+{
+	struct cb_data *data;
+
+	if (s3c2410_dma_request(dma_ch, info->client, NULL) < 0) {
+		s3c2410_dma_free(dma_ch, info->client);
+		return 0;
+	}
+
+	data = kzalloc(sizeof(struct cb_data), GFP_KERNEL);
+	data->ch = dma_ch;
+	list_add_tail(&data->node, &dma_list);
+
+	s3c2410_dma_devconfig(dma_ch, info->direction, info->fifo);
+
+	if (info->cap == DMA_CYCLIC)
+		s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
+
+	s3c2410_dma_config(dma_ch, info->width);
+
+	return (unsigned)dma_ch;
+}
+
+static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)
+{
+	struct cb_data *data;
+
+	list_for_each_entry(data, &dma_list, node)
+		if (data->ch == ch)
+			break;
+	list_del(&data->node);
+
+	s3c2410_dma_free(ch, client);
+	kfree(data);
+
+	return 0;
+}
+
+static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)
+{
+	struct cb_data *data;
+	int len = (info->cap == DMA_CYCLIC) ? info->period : info->len;
+
+	list_for_each_entry(data, &dma_list, node)
+		if (data->ch == ch)
+			break;
+
+	if (!data->fp) {
+		s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb);
+		data->fp = info->fp;
+		data->fp_param = info->fp_param;
+	}
+
+	s3c2410_dma_enqueue(ch, (void *)data, info->buf, len);
+
+	return 0;
+}
+
+static inline int s3c_dma_trigger(unsigned ch)
+{
+	return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
+}
+
+static inline int s3c_dma_started(unsigned ch)
+{
+	return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
+}
+
+static inline int s3c_dma_flush(unsigned ch)
+{
+	return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
+}
+
+static inline int s3c_dma_stop(unsigned ch)
+{
+	return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
+}
+
+static struct samsung_dma_ops s3c_dma_ops = {
+	.request	= s3c_dma_request,
+	.release	= s3c_dma_release,
+	.prepare	= s3c_dma_prepare,
+	.trigger	= s3c_dma_trigger,
+	.started	= s3c_dma_started,
+	.flush		= s3c_dma_flush,
+	.stop		= s3c_dma_stop,
+};
+
+void *s3c_dma_get_ops(void)
+{
+	return &s3c_dma_ops;
+}
+EXPORT_SYMBOL(s3c_dma_get_ops);
diff -druN linux-libre-3.1-gnu/arch/arm/plat-samsung/s3c-pl330.c linux-libre-3.2-gnu/arch/arm/plat-samsung/s3c-pl330.c
--- linux-libre-3.1-gnu/arch/arm/plat-samsung/s3c-pl330.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-samsung/s3c-pl330.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1244 +0,0 @@
-/* linux/arch/arm/plat-samsung/s3c-pl330.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 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/module.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <asm/hardware/pl330.h>
-
-#include <plat/s3c-pl330-pdata.h>
-
-/**
- * struct s3c_pl330_dmac - Logical representation of a PL330 DMAC.
- * @busy_chan: Number of channels currently busy.
- * @peri: List of IDs of peripherals this DMAC can work with.
- * @node: To attach to the global list of DMACs.
- * @pi: PL330 configuration info for the DMAC.
- * @kmcache: Pool to quickly allocate xfers for all channels in the dmac.
- * @clk: Pointer of DMAC operation clock.
- */
-struct s3c_pl330_dmac {
-	unsigned		busy_chan;
-	enum dma_ch		*peri;
-	struct list_head	node;
-	struct pl330_info	*pi;
-	struct kmem_cache	*kmcache;
-	struct clk		*clk;
-};
-
-/**
- * struct s3c_pl330_xfer - A request submitted by S3C DMA clients.
- * @token: Xfer ID provided by the client.
- * @node: To attach to the list of xfers on a channel.
- * @px: Xfer for PL330 core.
- * @chan: Owner channel of this xfer.
- */
-struct s3c_pl330_xfer {
-	void			*token;
-	struct list_head	node;
-	struct pl330_xfer	px;
-	struct s3c_pl330_chan	*chan;
-};
-
-/**
- * struct s3c_pl330_chan - Logical channel to communicate with
- * 	a Physical peripheral.
- * @pl330_chan_id: Token of a hardware channel thread of PL330 DMAC.
- * 	NULL if the channel is available to be acquired.
- * @id: ID of the peripheral that this channel can communicate with.
- * @options: Options specified by the client.
- * @sdaddr: Address provided via s3c2410_dma_devconfig.
- * @node: To attach to the global list of channels.
- * @lrq: Pointer to the last submitted pl330_req to PL330 core.
- * @xfer_list: To manage list of xfers enqueued.
- * @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 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
- * 	channel is available to be acquired.
- */
-struct s3c_pl330_chan {
-	void				*pl330_chan_id;
-	enum dma_ch			id;
-	unsigned int			options;
-	unsigned long			sdaddr;
-	struct list_head		node;
-	struct pl330_req		*lrq;
-	struct list_head		xfer_list;
-	struct pl330_req		req[2];
-	s3c2410_dma_cbfn_t		callback_fn;
-	struct pl330_reqcfg		rqcfg;
-	struct s3c_pl330_xfer		*xfer_head;
-	struct s3c_pl330_dmac		*dmac;
-	struct s3c2410_dma_client	*client;
-};
-
-/* All DMACs in the platform */
-static LIST_HEAD(dmac_list);
-
-/* All channels to peripherals in the platform */
-static LIST_HEAD(chan_list);
-
-/*
- * Since we add resources(DMACs and Channels) to the global pool,
- * we need to guard access to the resources using a global lock
- */
-static DEFINE_SPINLOCK(res_lock);
-
-/* Returns the channel with ID 'id' in the chan_list */
-static struct s3c_pl330_chan *id_to_chan(const enum dma_ch id)
-{
-	struct s3c_pl330_chan *ch;
-
-	list_for_each_entry(ch, &chan_list, node)
-		if (ch->id == id)
-			return ch;
-
-	return NULL;
-}
-
-/* Allocate a new channel with ID 'id' and add to chan_list */
-static void chan_add(const enum dma_ch id)
-{
-	struct s3c_pl330_chan *ch = id_to_chan(id);
-
-	/* Return if the channel already exists */
-	if (ch)
-		return;
-
-	ch = kmalloc(sizeof(*ch), GFP_KERNEL);
-	/* Return silently to work with other channels */
-	if (!ch)
-		return;
-
-	ch->id = id;
-	ch->dmac = NULL;
-
-	list_add_tail(&ch->node, &chan_list);
-}
-
-/* If the channel is not yet acquired by any client */
-static bool chan_free(struct s3c_pl330_chan *ch)
-{
-	if (!ch)
-		return false;
-
-	/* Channel points to some DMAC only when it's acquired */
-	return ch->dmac ? false : true;
-}
-
-/*
- * Returns 0 is peripheral i/f is invalid or not present on the dmac.
- * Index + 1, otherwise.
- */
-static unsigned iface_of_dmac(struct s3c_pl330_dmac *dmac, enum dma_ch ch_id)
-{
-	enum dma_ch *id = dmac->peri;
-	int i;
-
-	/* Discount invalid markers */
-	if (ch_id == DMACH_MAX)
-		return 0;
-
-	for (i = 0; i < PL330_MAX_PERI; i++)
-		if (id[i] == ch_id)
-			return i + 1;
-
-	return 0;
-}
-
-/* If all channel threads of the DMAC are busy */
-static inline bool dmac_busy(struct s3c_pl330_dmac *dmac)
-{
-	struct pl330_info *pi = dmac->pi;
-
-	return (dmac->busy_chan < pi->pcfg.num_chan) ? false : true;
-}
-
-/*
- * Returns the number of free channels that
- * can be handled by this dmac only.
- */
-static unsigned ch_onlyby_dmac(struct s3c_pl330_dmac *dmac)
-{
-	enum dma_ch *id = dmac->peri;
-	struct s3c_pl330_dmac *d;
-	struct s3c_pl330_chan *ch;
-	unsigned found, count = 0;
-	enum dma_ch p;
-	int i;
-
-	for (i = 0; i < PL330_MAX_PERI; i++) {
-		p = id[i];
-		ch = id_to_chan(p);
-
-		if (p == DMACH_MAX || !chan_free(ch))
-			continue;
-
-		found = 0;
-		list_for_each_entry(d, &dmac_list, node) {
-			if (d != dmac && iface_of_dmac(d, ch->id)) {
-				found = 1;
-				break;
-			}
-		}
-		if (!found)
-			count++;
-	}
-
-	return count;
-}
-
-/*
- * Measure of suitability of 'dmac' handling 'ch'
- *
- * 0 indicates 'dmac' can not handle 'ch' either
- * because it is not supported by the hardware or
- * because all dmac channels are currently busy.
- *
- * >0 vlaue indicates 'dmac' has the capability.
- * The bigger the value the more suitable the dmac.
- */
-#define MAX_SUIT	UINT_MAX
-#define MIN_SUIT	0
-
-static unsigned suitablility(struct s3c_pl330_dmac *dmac,
-		struct s3c_pl330_chan *ch)
-{
-	struct pl330_info *pi = dmac->pi;
-	enum dma_ch *id = dmac->peri;
-	struct s3c_pl330_dmac *d;
-	unsigned s;
-	int i;
-
-	s = MIN_SUIT;
-	/* If all the DMAC channel threads are busy */
-	if (dmac_busy(dmac))
-		return s;
-
-	for (i = 0; i < PL330_MAX_PERI; i++)
-		if (id[i] == ch->id)
-			break;
-
-	/* If the 'dmac' can't talk to 'ch' */
-	if (i == PL330_MAX_PERI)
-		return s;
-
-	s = MAX_SUIT;
-	list_for_each_entry(d, &dmac_list, node) {
-		/*
-		 * If some other dmac can talk to this
-		 * peri and has some channel free.
-		 */
-		if (d != dmac && iface_of_dmac(d, ch->id) && !dmac_busy(d)) {
-			s = 0;
-			break;
-		}
-	}
-	if (s)
-		return s;
-
-	s = 100;
-
-	/* Good if free chans are more, bad otherwise */
-	s += (pi->pcfg.num_chan - dmac->busy_chan) - ch_onlyby_dmac(dmac);
-
-	return s;
-}
-
-/* More than one DMAC may have capability to transfer data with the
- * peripheral. This function assigns most suitable DMAC to manage the
- * channel and hence communicate with the peripheral.
- */
-static struct s3c_pl330_dmac *map_chan_to_dmac(struct s3c_pl330_chan *ch)
-{
-	struct s3c_pl330_dmac *d, *dmac = NULL;
-	unsigned sn, sl = MIN_SUIT;
-
-	list_for_each_entry(d, &dmac_list, node) {
-		sn = suitablility(d, ch);
-
-		if (sn == MAX_SUIT)
-			return d;
-
-		if (sn > sl)
-			dmac = d;
-	}
-
-	return dmac;
-}
-
-/* Acquire the channel for peripheral 'id' */
-static struct s3c_pl330_chan *chan_acquire(const enum dma_ch id)
-{
-	struct s3c_pl330_chan *ch = id_to_chan(id);
-	struct s3c_pl330_dmac *dmac;
-
-	/* If the channel doesn't exist or is already acquired */
-	if (!ch || !chan_free(ch)) {
-		ch = NULL;
-		goto acq_exit;
-	}
-
-	dmac = map_chan_to_dmac(ch);
-	/* If couldn't map */
-	if (!dmac) {
-		ch = NULL;
-		goto acq_exit;
-	}
-
-	dmac->busy_chan++;
-	ch->dmac = dmac;
-
-acq_exit:
-	return ch;
-}
-
-/* Delete xfer from the queue */
-static inline void del_from_queue(struct s3c_pl330_xfer *xfer)
-{
-	struct s3c_pl330_xfer *t;
-	struct s3c_pl330_chan *ch;
-	int found;
-
-	if (!xfer)
-		return;
-
-	ch = xfer->chan;
-
-	/* Make sure xfer is in the queue */
-	found = 0;
-	list_for_each_entry(t, &ch->xfer_list, node)
-		if (t == xfer) {
-			found = 1;
-			break;
-		}
-
-	if (!found)
-		return;
-
-	/* If xfer is last entry in the queue */
-	if (xfer->node.next == &ch->xfer_list)
-		t = list_entry(ch->xfer_list.next,
-				struct s3c_pl330_xfer, node);
-	else
-		t = list_entry(xfer->node.next,
-				struct s3c_pl330_xfer, node);
-
-	/* If there was only one node left */
-	if (t == xfer)
-		ch->xfer_head = NULL;
-	else if (ch->xfer_head == xfer)
-		ch->xfer_head = t;
-
-	list_del(&xfer->node);
-}
-
-/* Provides pointer to the next xfer in the queue.
- * If CIRCULAR option is set, the list is left intact,
- * otherwise the xfer is removed from the list.
- * Forced delete 'pluck' can be set to override the CIRCULAR option.
- */
-static struct s3c_pl330_xfer *get_from_queue(struct s3c_pl330_chan *ch,
-		int pluck)
-{
-	struct s3c_pl330_xfer *xfer = ch->xfer_head;
-
-	if (!xfer)
-		return NULL;
-
-	/* If xfer is last entry in the queue */
-	if (xfer->node.next == &ch->xfer_list)
-		ch->xfer_head = list_entry(ch->xfer_list.next,
-					struct s3c_pl330_xfer, node);
-	else
-		ch->xfer_head = list_entry(xfer->node.next,
-					struct s3c_pl330_xfer, node);
-
-	if (pluck || !(ch->options & S3C2410_DMAF_CIRCULAR))
-		del_from_queue(xfer);
-
-	return xfer;
-}
-
-static inline void add_to_queue(struct s3c_pl330_chan *ch,
-		struct s3c_pl330_xfer *xfer, int front)
-{
-	struct pl330_xfer *xt;
-
-	/* If queue empty */
-	if (ch->xfer_head == NULL)
-		ch->xfer_head = xfer;
-
-	xt = &ch->xfer_head->px;
-	/* If the head already submitted (CIRCULAR head) */
-	if (ch->options & S3C2410_DMAF_CIRCULAR &&
-		(xt == ch->req[0].x || xt == ch->req[1].x))
-		ch->xfer_head = xfer;
-
-	/* If this is a resubmission, it should go at the head */
-	if (front) {
-		ch->xfer_head = xfer;
-		list_add(&xfer->node, &ch->xfer_list);
-	} else {
-		list_add_tail(&xfer->node, &ch->xfer_list);
-	}
-}
-
-static inline void _finish_off(struct s3c_pl330_xfer *xfer,
-		enum s3c2410_dma_buffresult res, int ffree)
-{
-	struct s3c_pl330_chan *ch;
-
-	if (!xfer)
-		return;
-
-	ch = xfer->chan;
-
-	/* Do callback */
-	if (ch->callback_fn)
-		ch->callback_fn(NULL, xfer->token, xfer->px.bytes, res);
-
-	/* Force Free or if buffer is not needed anymore */
-	if (ffree || !(ch->options & S3C2410_DMAF_CIRCULAR))
-		kmem_cache_free(ch->dmac->kmcache, xfer);
-}
-
-static inline int s3c_pl330_submit(struct s3c_pl330_chan *ch,
-		struct pl330_req *r)
-{
-	struct s3c_pl330_xfer *xfer;
-	int ret = 0;
-
-	/* If already submitted */
-	if (r->x)
-		return 0;
-
-	xfer = get_from_queue(ch, 0);
-	if (xfer) {
-		r->x = &xfer->px;
-
-		/* Use max bandwidth for M<->M xfers */
-		if (r->rqtype == MEMTOMEM) {
-			struct pl330_info *pi = xfer->chan->dmac->pi;
-			int burst = 1 << ch->rqcfg.brst_size;
-			u32 bytes = r->x->bytes;
-			int bl;
-
-			bl = pi->pcfg.data_bus_width / 8;
-			bl *= pi->pcfg.data_buf_dep;
-			bl /= burst;
-
-			/* src/dst_burst_len can't be more than 16 */
-			if (bl > 16)
-				bl = 16;
-
-			while (bl > 1) {
-				if (!(bytes % (bl * burst)))
-					break;
-				bl--;
-			}
-
-			ch->rqcfg.brst_len = bl;
-		} else {
-			ch->rqcfg.brst_len = 1;
-		}
-
-		ret = pl330_submit_req(ch->pl330_chan_id, r);
-
-		/* If submission was successful */
-		if (!ret) {
-			ch->lrq = r; /* latest submitted req */
-			return 0;
-		}
-
-		r->x = NULL;
-
-		/* If both of the PL330 ping-pong buffers filled */
-		if (ret == -EAGAIN) {
-			dev_err(ch->dmac->pi->dev, "%s:%d!\n",
-				__func__, __LINE__);
-			/* Queue back again */
-			add_to_queue(ch, xfer, 1);
-			ret = 0;
-		} else {
-			dev_err(ch->dmac->pi->dev, "%s:%d!\n",
-				__func__, __LINE__);
-			_finish_off(xfer, S3C2410_RES_ERR, 0);
-		}
-	}
-
-	return ret;
-}
-
-static void s3c_pl330_rq(struct s3c_pl330_chan *ch,
-	struct pl330_req *r, enum pl330_op_err err)
-{
-	unsigned long flags;
-	struct s3c_pl330_xfer *xfer;
-	struct pl330_xfer *xl = r->x;
-	enum s3c2410_dma_buffresult res;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	r->x = NULL;
-
-	s3c_pl330_submit(ch, r);
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	/* Map result to S3C DMA API */
-	if (err == PL330_ERR_NONE)
-		res = S3C2410_RES_OK;
-	else if (err == PL330_ERR_ABORT)
-		res = S3C2410_RES_ABORT;
-	else
-		res = S3C2410_RES_ERR;
-
-	/* If last request had some xfer */
-	if (xl) {
-		xfer = container_of(xl, struct s3c_pl330_xfer, px);
-		_finish_off(xfer, res, 0);
-	} else {
-		dev_info(ch->dmac->pi->dev, "%s:%d No Xfer?!\n",
-			__func__, __LINE__);
-	}
-}
-
-static void s3c_pl330_rq0(void *token, enum pl330_op_err err)
-{
-	struct pl330_req *r = token;
-	struct s3c_pl330_chan *ch = container_of(r,
-					struct s3c_pl330_chan, req[0]);
-	s3c_pl330_rq(ch, r, err);
-}
-
-static void s3c_pl330_rq1(void *token, enum pl330_op_err err)
-{
-	struct pl330_req *r = token;
-	struct s3c_pl330_chan *ch = container_of(r,
-					struct s3c_pl330_chan, req[1]);
-	s3c_pl330_rq(ch, r, err);
-}
-
-/* Release an acquired channel */
-static void chan_release(struct s3c_pl330_chan *ch)
-{
-	struct s3c_pl330_dmac *dmac;
-
-	if (chan_free(ch))
-		return;
-
-	dmac = ch->dmac;
-	ch->dmac = NULL;
-	dmac->busy_chan--;
-}
-
-int s3c2410_dma_ctrl(enum dma_ch id, enum s3c2410_chan_op op)
-{
-	struct s3c_pl330_xfer *xfer;
-	enum pl330_chan_op pl330op;
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int idx, ret;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch)) {
-		ret = -EINVAL;
-		goto ctrl_exit;
-	}
-
-	switch (op) {
-	case S3C2410_DMAOP_START:
-		/* Make sure both reqs are enqueued */
-		idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-		s3c_pl330_submit(ch, &ch->req[idx]);
-		s3c_pl330_submit(ch, &ch->req[1 - idx]);
-		pl330op = PL330_OP_START;
-		break;
-
-	case S3C2410_DMAOP_STOP:
-		pl330op = PL330_OP_ABORT;
-		break;
-
-	case S3C2410_DMAOP_FLUSH:
-		pl330op = PL330_OP_FLUSH;
-		break;
-
-	case S3C2410_DMAOP_PAUSE:
-	case S3C2410_DMAOP_RESUME:
-	case S3C2410_DMAOP_TIMEOUT:
-	case S3C2410_DMAOP_STARTED:
-		spin_unlock_irqrestore(&res_lock, flags);
-		return 0;
-
-	default:
-		spin_unlock_irqrestore(&res_lock, flags);
-		return -EINVAL;
-	}
-
-	ret = pl330_chan_ctrl(ch->pl330_chan_id, pl330op);
-
-	if (pl330op == PL330_OP_START) {
-		spin_unlock_irqrestore(&res_lock, flags);
-		return ret;
-	}
-
-	idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-	/* Abort the current xfer */
-	if (ch->req[idx].x) {
-		xfer = container_of(ch->req[idx].x,
-				struct s3c_pl330_xfer, px);
-
-		/* Drop xfer during FLUSH */
-		if (pl330op == PL330_OP_FLUSH)
-			del_from_queue(xfer);
-
-		ch->req[idx].x = NULL;
-
-		spin_unlock_irqrestore(&res_lock, flags);
-		_finish_off(xfer, S3C2410_RES_ABORT,
-				pl330op == PL330_OP_FLUSH ? 1 : 0);
-		spin_lock_irqsave(&res_lock, flags);
-	}
-
-	/* Flush the whole queue */
-	if (pl330op == PL330_OP_FLUSH) {
-
-		if (ch->req[1 - idx].x) {
-			xfer = container_of(ch->req[1 - idx].x,
-					struct s3c_pl330_xfer, px);
-
-			del_from_queue(xfer);
-
-			ch->req[1 - idx].x = NULL;
-
-			spin_unlock_irqrestore(&res_lock, flags);
-			_finish_off(xfer, S3C2410_RES_ABORT, 1);
-			spin_lock_irqsave(&res_lock, flags);
-		}
-
-		/* Finish off the remaining in the queue */
-		xfer = ch->xfer_head;
-		while (xfer) {
-
-			del_from_queue(xfer);
-
-			spin_unlock_irqrestore(&res_lock, flags);
-			_finish_off(xfer, S3C2410_RES_ABORT, 1);
-			spin_lock_irqsave(&res_lock, flags);
-
-			xfer = ch->xfer_head;
-		}
-	}
-
-ctrl_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_ctrl);
-
-int s3c2410_dma_enqueue(enum dma_ch id, void *token,
-			dma_addr_t addr, int size)
-{
-	struct s3c_pl330_chan *ch;
-	struct s3c_pl330_xfer *xfer;
-	unsigned long flags;
-	int idx, ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	/* Error if invalid or free channel */
-	if (!ch || chan_free(ch)) {
-		ret = -EINVAL;
-		goto enq_exit;
-	}
-
-	/* Error if size is unaligned */
-	if (ch->rqcfg.brst_size && size % (1 << ch->rqcfg.brst_size)) {
-		ret = -EINVAL;
-		goto enq_exit;
-	}
-
-	xfer = kmem_cache_alloc(ch->dmac->kmcache, GFP_ATOMIC);
-	if (!xfer) {
-		ret = -ENOMEM;
-		goto enq_exit;
-	}
-
-	xfer->token = token;
-	xfer->chan = ch;
-	xfer->px.bytes = size;
-	xfer->px.next = NULL; /* Single request */
-
-	/* For S3C DMA API, direction is always fixed for all xfers */
-	if (ch->req[0].rqtype == MEMTODEV) {
-		xfer->px.src_addr = addr;
-		xfer->px.dst_addr = ch->sdaddr;
-	} else {
-		xfer->px.src_addr = ch->sdaddr;
-		xfer->px.dst_addr = addr;
-	}
-
-	add_to_queue(ch, xfer, 0);
-
-	/* Try submitting on either request */
-	idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-	if (!ch->req[idx].x)
-		s3c_pl330_submit(ch, &ch->req[idx]);
-	else
-		s3c_pl330_submit(ch, &ch->req[1 - idx]);
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	if (ch->options & S3C2410_DMAF_AUTOSTART)
-		s3c2410_dma_ctrl(id, S3C2410_DMAOP_START);
-
-	return 0;
-
-enq_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_enqueue);
-
-int s3c2410_dma_request(enum dma_ch id,
-			struct s3c2410_dma_client *client,
-			void *dev)
-{
-	struct s3c_pl330_dmac *dmac;
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = chan_acquire(id);
-	if (!ch) {
-		ret = -EBUSY;
-		goto req_exit;
-	}
-
-	dmac = ch->dmac;
-
-	ch->pl330_chan_id = pl330_request_channel(dmac->pi);
-	if (!ch->pl330_chan_id) {
-		chan_release(ch);
-		ret = -EBUSY;
-		goto req_exit;
-	}
-
-	ch->client = client;
-	ch->options = 0; /* Clear any option */
-	ch->callback_fn = NULL; /* Clear any callback */
-	ch->lrq = NULL;
-
-	ch->rqcfg.brst_size = 2; /* Default word size */
-	ch->rqcfg.swap = SWAP_NO;
-	ch->rqcfg.scctl = SCCTRL0; /* Noncacheable and nonbufferable */
-	ch->rqcfg.dcctl = DCCTRL0; /* Noncacheable and nonbufferable */
-	ch->rqcfg.privileged = 0;
-	ch->rqcfg.insnaccess = 0;
-
-	/* Set invalid direction */
-	ch->req[0].rqtype = DEVTODEV;
-	ch->req[1].rqtype = ch->req[0].rqtype;
-
-	ch->req[0].cfg = &ch->rqcfg;
-	ch->req[1].cfg = ch->req[0].cfg;
-
-	ch->req[0].peri = iface_of_dmac(dmac, id) - 1; /* Original index */
-	ch->req[1].peri = ch->req[0].peri;
-
-	ch->req[0].token = &ch->req[0];
-	ch->req[0].xfer_cb = s3c_pl330_rq0;
-	ch->req[1].token = &ch->req[1];
-	ch->req[1].xfer_cb = s3c_pl330_rq1;
-
-	ch->req[0].x = NULL;
-	ch->req[1].x = NULL;
-
-	/* Reset xfer list */
-	INIT_LIST_HEAD(&ch->xfer_list);
-	ch->xfer_head = NULL;
-
-req_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_request);
-
-int s3c2410_dma_free(enum dma_ch id, struct s3c2410_dma_client *client)
-{
-	struct s3c_pl330_chan *ch;
-	struct s3c_pl330_xfer *xfer;
-	unsigned long flags;
-	int ret = 0;
-	unsigned idx;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch))
-		goto free_exit;
-
-	/* Refuse if someone else wanted to free the channel */
-	if (ch->client != client) {
-		ret = -EBUSY;
-		goto free_exit;
-	}
-
-	/* Stop any active xfer, Flushe the queue and do callbacks */
-	pl330_chan_ctrl(ch->pl330_chan_id, PL330_OP_FLUSH);
-
-	/* Abort the submitted requests */
-	idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-	if (ch->req[idx].x) {
-		xfer = container_of(ch->req[idx].x,
-				struct s3c_pl330_xfer, px);
-
-		ch->req[idx].x = NULL;
-		del_from_queue(xfer);
-
-		spin_unlock_irqrestore(&res_lock, flags);
-		_finish_off(xfer, S3C2410_RES_ABORT, 1);
-		spin_lock_irqsave(&res_lock, flags);
-	}
-
-	if (ch->req[1 - idx].x) {
-		xfer = container_of(ch->req[1 - idx].x,
-				struct s3c_pl330_xfer, px);
-
-		ch->req[1 - idx].x = NULL;
-		del_from_queue(xfer);
-
-		spin_unlock_irqrestore(&res_lock, flags);
-		_finish_off(xfer, S3C2410_RES_ABORT, 1);
-		spin_lock_irqsave(&res_lock, flags);
-	}
-
-	/* Pluck and Abort the queued requests in order */
-	do {
-		xfer = get_from_queue(ch, 1);
-
-		spin_unlock_irqrestore(&res_lock, flags);
-		_finish_off(xfer, S3C2410_RES_ABORT, 1);
-		spin_lock_irqsave(&res_lock, flags);
-	} while (xfer);
-
-	ch->client = NULL;
-
-	pl330_release_channel(ch->pl330_chan_id);
-
-	ch->pl330_chan_id = NULL;
-
-	chan_release(ch);
-
-free_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_free);
-
-int s3c2410_dma_config(enum dma_ch id, int xferunit)
-{
-	struct s3c_pl330_chan *ch;
-	struct pl330_info *pi;
-	unsigned long flags;
-	int i, dbwidth, ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch)) {
-		ret = -EINVAL;
-		goto cfg_exit;
-	}
-
-	pi = ch->dmac->pi;
-	dbwidth = pi->pcfg.data_bus_width / 8;
-
-	/* Max size of xfer can be pcfg.data_bus_width */
-	if (xferunit > dbwidth) {
-		ret = -EINVAL;
-		goto cfg_exit;
-	}
-
-	i = 0;
-	while (xferunit != (1 << i))
-		i++;
-
-	/* If valid value */
-	if (xferunit == (1 << i))
-		ch->rqcfg.brst_size = i;
-	else
-		ret = -EINVAL;
-
-cfg_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_config);
-
-/* Options that are supported by this driver */
-#define S3C_PL330_FLAGS (S3C2410_DMAF_CIRCULAR | S3C2410_DMAF_AUTOSTART)
-
-int s3c2410_dma_setflags(enum dma_ch id, unsigned int options)
-{
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch) || options & ~(S3C_PL330_FLAGS))
-		ret = -EINVAL;
-	else
-		ch->options = options;
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_setflags);
-
-int s3c2410_dma_set_buffdone_fn(enum dma_ch id, s3c2410_dma_cbfn_t rtn)
-{
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch))
-		ret = -EINVAL;
-	else
-		ch->callback_fn = rtn;
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
-
-int s3c2410_dma_devconfig(enum dma_ch id, enum s3c2410_dmasrc source,
-			  unsigned long address)
-{
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch)) {
-		ret = -EINVAL;
-		goto devcfg_exit;
-	}
-
-	switch (source) {
-	case S3C2410_DMASRC_HW: /* P->M */
-		ch->req[0].rqtype = DEVTOMEM;
-		ch->req[1].rqtype = DEVTOMEM;
-		ch->rqcfg.src_inc = 0;
-		ch->rqcfg.dst_inc = 1;
-		break;
-	case S3C2410_DMASRC_MEM: /* M->P */
-		ch->req[0].rqtype = MEMTODEV;
-		ch->req[1].rqtype = MEMTODEV;
-		ch->rqcfg.src_inc = 1;
-		ch->rqcfg.dst_inc = 0;
-		break;
-	default:
-		ret = -EINVAL;
-		goto devcfg_exit;
-	}
-
-	ch->sdaddr = address;
-
-devcfg_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_devconfig);
-
-int s3c2410_dma_getposition(enum dma_ch id, dma_addr_t *src, dma_addr_t *dst)
-{
-	struct s3c_pl330_chan *ch = id_to_chan(id);
-	struct pl330_chanstatus status;
-	int ret;
-
-	if (!ch || chan_free(ch))
-		return -EINVAL;
-
-	ret = pl330_chan_status(ch->pl330_chan_id, &status);
-	if (ret < 0)
-		return ret;
-
-	*src = status.src_addr;
-	*dst = status.dst_addr;
-
-	return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_getposition);
-
-static irqreturn_t pl330_irq_handler(int irq, void *data)
-{
-	if (pl330_update(data))
-		return IRQ_HANDLED;
-	else
-		return IRQ_NONE;
-}
-
-static int pl330_probe(struct platform_device *pdev)
-{
-	struct s3c_pl330_dmac *s3c_pl330_dmac;
-	struct s3c_pl330_platdata *pl330pd;
-	struct pl330_info *pl330_info;
-	struct resource *res;
-	int i, ret, irq;
-
-	pl330pd = pdev->dev.platform_data;
-
-	/* Can't do without the list of _32_ peripherals */
-	if (!pl330pd || !pl330pd->peri) {
-		dev_err(&pdev->dev, "platform data missing!\n");
-		return -ENODEV;
-	}
-
-	pl330_info = kzalloc(sizeof(*pl330_info), GFP_KERNEL);
-	if (!pl330_info)
-		return -ENOMEM;
-
-	pl330_info->pl330_data = NULL;
-	pl330_info->dev = &pdev->dev;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		ret = -ENODEV;
-		goto probe_err1;
-	}
-
-	request_mem_region(res->start, resource_size(res), pdev->name);
-
-	pl330_info->base = ioremap(res->start, resource_size(res));
-	if (!pl330_info->base) {
-		ret = -ENXIO;
-		goto probe_err2;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		ret = irq;
-		goto probe_err3;
-	}
-
-	ret = request_irq(irq, pl330_irq_handler, 0,
-			dev_name(&pdev->dev), pl330_info);
-	if (ret)
-		goto probe_err4;
-
-	/* Allocate a new DMAC */
-	s3c_pl330_dmac = kmalloc(sizeof(*s3c_pl330_dmac), GFP_KERNEL);
-	if (!s3c_pl330_dmac) {
-		ret = -ENOMEM;
-		goto probe_err5;
-	}
-
-	/* Get operation clock and enable it */
-	s3c_pl330_dmac->clk = clk_get(&pdev->dev, "pdma");
-	if (IS_ERR(s3c_pl330_dmac->clk)) {
-		dev_err(&pdev->dev, "Cannot get operation clock.\n");
-		ret = -EINVAL;
-		goto probe_err6;
-	}
-	clk_enable(s3c_pl330_dmac->clk);
-
-	ret = pl330_add(pl330_info);
-	if (ret)
-		goto probe_err7;
-
-	/* Hook the info */
-	s3c_pl330_dmac->pi = pl330_info;
-
-	/* No busy channels */
-	s3c_pl330_dmac->busy_chan = 0;
-
-	s3c_pl330_dmac->kmcache = kmem_cache_create(dev_name(&pdev->dev),
-				sizeof(struct s3c_pl330_xfer), 0, 0, NULL);
-
-	if (!s3c_pl330_dmac->kmcache) {
-		ret = -ENOMEM;
-		goto probe_err8;
-	}
-
-	/* Get the list of peripherals */
-	s3c_pl330_dmac->peri = pl330pd->peri;
-
-	/* Attach to the list of DMACs */
-	list_add_tail(&s3c_pl330_dmac->node, &dmac_list);
-
-	/* Create a channel for each peripheral in the DMAC
-	 * that is, if it doesn't already exist
-	 */
-	for (i = 0; i < PL330_MAX_PERI; i++)
-		if (s3c_pl330_dmac->peri[i] != DMACH_MAX)
-			chan_add(s3c_pl330_dmac->peri[i]);
-
-	printk(KERN_INFO
-		"Loaded driver for PL330 DMAC-%d %s\n",	pdev->id, pdev->name);
-	printk(KERN_INFO
-		"\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n",
-		pl330_info->pcfg.data_buf_dep,
-		pl330_info->pcfg.data_bus_width / 8, pl330_info->pcfg.num_chan,
-		pl330_info->pcfg.num_peri, pl330_info->pcfg.num_events);
-
-	return 0;
-
-probe_err8:
-	pl330_del(pl330_info);
-probe_err7:
-	clk_disable(s3c_pl330_dmac->clk);
-	clk_put(s3c_pl330_dmac->clk);
-probe_err6:
-	kfree(s3c_pl330_dmac);
-probe_err5:
-	free_irq(irq, pl330_info);
-probe_err4:
-probe_err3:
-	iounmap(pl330_info->base);
-probe_err2:
-	release_mem_region(res->start, resource_size(res));
-probe_err1:
-	kfree(pl330_info);
-
-	return ret;
-}
-
-static int pl330_remove(struct platform_device *pdev)
-{
-	struct s3c_pl330_dmac *dmac, *d;
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int del, found;
-
-	if (!pdev->dev.platform_data)
-		return -EINVAL;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	found = 0;
-	list_for_each_entry(d, &dmac_list, node)
-		if (d->pi->dev == &pdev->dev) {
-			found = 1;
-			break;
-		}
-
-	if (!found) {
-		spin_unlock_irqrestore(&res_lock, flags);
-		return 0;
-	}
-
-	dmac = d;
-
-	/* Remove all Channels that are managed only by this DMAC */
-	list_for_each_entry(ch, &chan_list, node) {
-
-		/* Only channels that are handled by this DMAC */
-		if (iface_of_dmac(dmac, ch->id))
-			del = 1;
-		else
-			continue;
-
-		/* Don't remove if some other DMAC has it too */
-		list_for_each_entry(d, &dmac_list, node)
-			if (d != dmac && iface_of_dmac(d, ch->id)) {
-				del = 0;
-				break;
-			}
-
-		if (del) {
-			spin_unlock_irqrestore(&res_lock, flags);
-			s3c2410_dma_free(ch->id, ch->client);
-			spin_lock_irqsave(&res_lock, flags);
-			list_del(&ch->node);
-			kfree(ch);
-		}
-	}
-
-	/* Disable operation clock */
-	clk_disable(dmac->clk);
-	clk_put(dmac->clk);
-
-	/* Remove the DMAC */
-	list_del(&dmac->node);
-	kfree(dmac);
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return 0;
-}
-
-static struct platform_driver pl330_driver = {
-	.driver		= {
-		.owner	= THIS_MODULE,
-		.name	= "s3c-pl330",
-	},
-	.probe		= pl330_probe,
-	.remove		= pl330_remove,
-};
-
-static int __init pl330_init(void)
-{
-	return platform_driver_register(&pl330_driver);
-}
-module_init(pl330_init);
-
-static void __exit pl330_exit(void)
-{
-	platform_driver_unregister(&pl330_driver);
-	return;
-}
-module_exit(pl330_exit);
-
-MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
-MODULE_DESCRIPTION("Driver for PL330 DMA Controller");
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/arch/arm/plat-spear/include/plat/debug-macro.S linux-libre-3.2-gnu/arch/arm/plat-spear/include/plat/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/plat-spear/include/plat/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-spear/include/plat/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/amba/serial.h>
 #include <mach/hardware.h>
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		mov	\rp, #SPEAR_DBG_UART_BASE		@ Physical base
 		mov	\rv, #VA_SPEAR_DBG_UART_BASE		@ Virtual base
 		.endm
diff -druN linux-libre-3.1-gnu/arch/arm/plat-spear/include/plat/gpio.h linux-libre-3.2-gnu/arch/arm/plat-spear/include/plat/gpio.h
--- linux-libre-3.1-gnu/arch/arm/plat-spear/include/plat/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-spear/include/plat/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,24 +1 @@
-/*
- * arch/arm/plat-spear/include/plat/gpio.h
- *
- * GPIO macros for SPEAr platform
- *
- * Copyright (C) 2009 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_GPIO_H
-#define __PLAT_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-#define gpio_to_irq	__gpio_to_irq
-
-#endif /* __PLAT_GPIO_H */
+/* empty */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-spear/include/plat/memory.h linux-libre-3.2-gnu/arch/arm/plat-spear/include/plat/memory.h
--- linux-libre-3.1-gnu/arch/arm/plat-spear/include/plat/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-spear/include/plat/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/memory.h
- *
- * Memory map for SPEAr platform
- *
- * Copyright (C) 2009 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_MEMORY_H
-#define __PLAT_MEMORY_H
-
-/* Physical DRAM offset */
-#define PLAT_PHYS_OFFSET		UL(0x00000000)
-
-#endif /* __PLAT_MEMORY_H */
diff -druN linux-libre-3.1-gnu/arch/arm/plat-tcc/include/mach/debug-macro.S linux-libre-3.2-gnu/arch/arm/plat-tcc/include/mach/debug-macro.S
--- linux-libre-3.1-gnu/arch/arm/plat-tcc/include/mach/debug-macro.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-tcc/include/mach/debug-macro.S	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
  *
  */
 
-		.macro	addruart, rp, rv
+		.macro	addruart, rp, rv, tmp
 		moveq	\rp, #0x90000000	@ physical base address
 		movne	\rv, #0xF1000000	@ virtual base
 		orr	\rp, \rp, #0x00007000	@ UART0
diff -druN linux-libre-3.1-gnu/arch/arm/plat-tcc/include/mach/memory.h linux-libre-3.2-gnu/arch/arm/plat-tcc/include/mach/memory.h
--- linux-libre-3.1-gnu/arch/arm/plat-tcc/include/mach/memory.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-tcc/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 1999 ARM Limited
- * Copyright (C) 2000 RidgeRun, Inc.
- * Copyright (C) 2008-2009 Telechips
- * Copyright (C) 2010 Hans J. Koch <hjk@linutronix.de>
- *
- * Licensed under the terms of the GPL v2.
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET		UL(0x20000000)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/arm/plat-versatile/platsmp.c linux-libre-3.2-gnu/arch/arm/plat-versatile/platsmp.c
--- linux-libre-3.1-gnu/arch/arm/plat-versatile/platsmp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/plat-versatile/platsmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -77,7 +77,7 @@
 	 * since we haven't sent them a soft interrupt, they shouldn't
 	 * be there.
 	 */
-	write_pen_release(cpu);
+	write_pen_release(cpu_logical_map(cpu));
 
 	/*
 	 * Send the secondary CPU a soft interrupt, thereby causing
diff -druN linux-libre-3.1-gnu/arch/arm/tools/mach-types linux-libre-3.2-gnu/arch/arm/tools/mach-types
--- linux-libre-3.1-gnu/arch/arm/tools/mach-types	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/tools/mach-types	2012-01-04 18:55:44.000000000 -0500
@@ -12,10 +12,9 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# 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>
+# This is a cut-down version of the file; it contains only machines that
+# are merged into mainline or have been edited in the machine database
+# within the last 12 months.  References to machine_is_NAME() do not count!
 #
 # Last update: Sat May 7 08:48:24 2011
 #
@@ -65,6 +64,7 @@
 h7202			ARCH_H7202		H7202			162
 iq80321			ARCH_IQ80321		IQ80321			169
 ks8695			ARCH_KS8695		KS8695			180
+karo			ARCH_KARO		KARO			190
 smdk2410		ARCH_SMDK2410		SMDK2410		193
 ceiva			ARCH_CEIVA		CEIVA			200
 voiceblue		MACH_VOICEBLUE		VOICEBLUE		218
@@ -188,6 +188,7 @@
 davinci_evm		MACH_DAVINCI_EVM	DAVINCI_EVM		901
 palmz72			MACH_PALMZ72		PALMZ72			904
 nxdb500			MACH_NXDB500		NXDB500			905
+apf9328			MACH_APF9328		APF9328			906
 palmt5			MACH_PALMT5		PALMT5			917
 palmtc			MACH_PALMTC		PALMTC			918
 omap_apollon		MACH_OMAP_APOLLON	OMAP_APOLLON		919
@@ -271,10 +272,12 @@
 ts_x09			MACH_TS209		TS209			1565
 at91cap9adk		MACH_AT91CAP9ADK	AT91CAP9ADK		1566
 mx31moboard		MACH_MX31MOBOARD	MX31MOBOARD		1574
+vision_ep9307		MACH_VISION_EP9307	VISION_EP9307		1578
 terastation_pro2	MACH_TERASTATION_PRO2	TERASTATION_PRO2	1584
 linkstation_pro		MACH_LINKSTATION_PRO	LINKSTATION_PRO		1585
 e350			MACH_E350		E350			1596
 ts409			MACH_TS409		TS409			1601
+rsi_ews			MACH_RSI_EWS		RSI_EWS			1609
 cm_x300			MACH_CM_X300		CM_X300			1616
 at91sam9g20ek		MACH_AT91SAM9G20EK	AT91SAM9G20EK		1624
 smdk6410		MACH_SMDK6410		SMDK6410		1626
@@ -331,6 +334,7 @@
 tavorevb		MACH_TAVOREVB		TAVOREVB		1827
 saar			MACH_SAAR		SAAR			1828
 at91sam9m10g45ek	MACH_AT91SAM9M10G45EK	AT91SAM9M10G45EK	1830
+usb_a9g20		MACH_USB_A9G20		USB_A9G20		1841
 mxlads			MACH_MXLADS		MXLADS			1851
 linkstation_mini	MACH_LINKSTATION_MINI	LINKSTATION_MINI	1858
 afeb9260		MACH_AFEB9260		AFEB9260		1859
@@ -369,6 +373,7 @@
 sheevaplug		MACH_SHEEVAPLUG		SHEEVAPLUG		2097
 avengers_lite		MACH_AVENGERS_LITE	AVENGERS_LITE		2104
 mx51_babbage		MACH_MX51_BABBAGE	MX51_BABBAGE		2125
+tx37			MACH_TX37		TX37			2127
 rd78x00_masa		MACH_RD78X00_MASA	RD78X00_MASA		2135
 dm355_leopard		MACH_DM355_LEOPARD	DM355_LEOPARD		2138
 ts219			MACH_TS219		TS219			2139
@@ -379,6 +384,7 @@
 magx_zn5		MACH_MAGX_ZN5		MAGX_ZN5		2162
 btmavb101		MACH_BTMAVB101		BTMAVB101		2172
 btmawb101		MACH_BTMAWB101		BTMAWB101		2173
+tx25			MACH_TX25		TX25			2177
 omap3_torpedo		MACH_OMAP3_TORPEDO	OMAP3_TORPEDO		2178
 anw6410			MACH_ANW6410		ANW6410			2183
 imx27_visstrim_m10	MACH_IMX27_VISSTRIM_M10	IMX27_VISSTRIM_M10	2187
@@ -423,6 +429,7 @@
 raumfeld_connector	MACH_RAUMFELD_CONNECTOR	RAUMFELD_CONNECTOR	2414
 raumfeld_speaker	MACH_RAUMFELD_SPEAKER	RAUMFELD_SPEAKER	2415
 tnetv107x		MACH_TNETV107X		TNETV107X		2418
+mx51_m2id		MACH_MX51_M2ID		MX51_M2ID		2428
 smdkv210		MACH_SMDKV210		SMDKV210		2456
 omap_zoom3		MACH_OMAP_ZOOM3		OMAP_ZOOM3		2464
 omap_3630sdp		MACH_OMAP_3630SDP	OMAP_3630SDP		2465
@@ -433,14 +440,17 @@
 ts41x			MACH_TS41X		TS41X			2502
 phy3250			MACH_PHY3250		PHY3250			2511
 mini6410		MACH_MINI6410		MINI6410		2520
+tx51			MACH_TX51		TX51			2529
 mx28evk			MACH_MX28EVK		MX28EVK			2531
 smartq5			MACH_SMARTQ5		SMARTQ5			2534
 davinci_dm6467tevm	MACH_DAVINCI_DM6467TEVM	DAVINCI_DM6467TEVM	2548
 mxt_td60		MACH_MXT_TD60		MXT_TD60		2550
 riot_bei2		MACH_RIOT_BEI2		RIOT_BEI2		2576
 riot_x37		MACH_RIOT_X37		RIOT_X37		2578
+pca101			MACH_PCA101		PCA101			2595
 capc7117		MACH_CAPC7117		CAPC7117		2612
 icontrol		MACH_ICONTROL		ICONTROL		2624
+gplugd			MACH_GPLUGD		GPLUGD			2625
 qsd8x50a_st1_5		MACH_QSD8X50A_ST1_5	QSD8X50A_ST1_5		2627
 mx23evk			MACH_MX23EVK		MX23EVK			2629
 ap4evb			MACH_AP4EVB		AP4EVB			2630
@@ -1113,3 +1123,6 @@
 thales_adc		MACH_THALES_ADC		THALES_ADC		3492
 ubisys_p9d_evp		MACH_UBISYS_P9D_EVP	UBISYS_P9D_EVP		3493
 atdgp318		MACH_ATDGP318		ATDGP318		3494
+m28evk			MACH_M28EVK		M28EVK			3613
+smdk4212		MACH_SMDK4212		SMDK4212		3638
+smdk4412		MACH_SMDK4412		SMDK4412		3765
diff -druN linux-libre-3.1-gnu/arch/arm/vfp/Makefile linux-libre-3.2-gnu/arch/arm/vfp/Makefile
--- linux-libre-3.1-gnu/arch/arm/vfp/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/vfp/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
 # ccflags-y := -DDEBUG
 # asflags-y := -DDEBUG
 
-KBUILD_AFLAGS	:=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp)
+KBUILD_AFLAGS	:=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp -mfloat-abi=soft)
 LDFLAGS		+=--no-warn-mismatch
 
 obj-y			+= vfp.o
diff -druN linux-libre-3.1-gnu/arch/arm/vfp/vfpmodule.c linux-libre-3.2-gnu/arch/arm/vfp/vfpmodule.c
--- linux-libre-3.1-gnu/arch/arm/vfp/vfpmodule.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/arm/vfp/vfpmodule.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,9 +8,9 @@
  * 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/cpu.h>
+#include <linux/cpu_pm.h>
 #include <linux/kernel.h>
 #include <linux/notifier.h>
 #include <linux/signal.h>
@@ -68,7 +68,7 @@
 /*
  * Force a reload of the VFP context from the thread structure.  We do
  * this by ensuring that access to the VFP hardware is disabled, and
- * clear last_VFP_context.  Must be called from non-preemptible context.
+ * clear vfp_current_hw_state.  Must be called from non-preemptible context.
  */
 static void vfp_force_reload(unsigned int cpu, struct thread_info *thread)
 {
@@ -436,9 +436,7 @@
 	set_copro_access(access | CPACC_FULL(10) | CPACC_FULL(11));
 }
 
-#ifdef CONFIG_PM
-#include <linux/syscore_ops.h>
-
+#ifdef CONFIG_CPU_PM
 static int vfp_pm_suspend(void)
 {
 	struct thread_info *ti = current_thread_info();
@@ -468,19 +466,33 @@
 	fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
 }
 
-static struct syscore_ops vfp_pm_syscore_ops = {
-	.suspend	= vfp_pm_suspend,
-	.resume		= vfp_pm_resume,
+static int vfp_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd,
+	void *v)
+{
+	switch (cmd) {
+	case CPU_PM_ENTER:
+		vfp_pm_suspend();
+		break;
+	case CPU_PM_ENTER_FAILED:
+	case CPU_PM_EXIT:
+		vfp_pm_resume();
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block vfp_cpu_pm_notifier_block = {
+	.notifier_call = vfp_cpu_pm_notifier,
 };
 
 static void vfp_pm_init(void)
 {
-	register_syscore_ops(&vfp_pm_syscore_ops);
+	cpu_pm_register_notifier(&vfp_cpu_pm_notifier_block);
 }
 
 #else
 static inline void vfp_pm_init(void) { }
-#endif /* CONFIG_PM */
+#endif /* CONFIG_CPU_PM */
 
 /*
  * Ensure that the VFP state stored in 'thread->vfpstate' is up to date
diff -druN linux-libre-3.1-gnu/arch/avr32/boards/atngw100/setup.c linux-libre-3.2-gnu/arch/avr32/boards/atngw100/setup.c
--- linux-libre-3.1-gnu/arch/avr32/boards/atngw100/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/avr32/boards/atngw100/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -90,11 +90,6 @@
 	},
 };
 
-static struct mtd_partition *nand_part_info(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(nand_partitions);
-	return nand_partitions;
-}
 
 static struct atmel_nand_data atngw100mkii_nand_data __initdata = {
 	.cle		= 21,
@@ -102,7 +97,8 @@
 	.rdy_pin	= GPIO_PIN_PB(28),
 	.enable_pin	= GPIO_PIN_PE(23),
 	.bus_width_16	= true,
-	.partition_info	= nand_part_info,
+	.parts		= nand_partitions,
+	.num_parts	= ARRAY_SIZE(nand_partitions),
 };
 #endif
 
diff -druN linux-libre-3.1-gnu/arch/avr32/boards/atstk1000/atstk1002.c linux-libre-3.2-gnu/arch/avr32/boards/atstk1000/atstk1002.c
--- linux-libre-3.1-gnu/arch/avr32/boards/atstk1000/atstk1002.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/avr32/boards/atstk1000/atstk1002.c	2012-01-04 18:55:44.000000000 -0500
@@ -90,18 +90,13 @@
 	},
 };
 
-static struct mtd_partition *nand_part_info(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(nand_partitions);
-	return nand_partitions;
-}
-
 static struct atmel_nand_data atstk1006_nand_data __initdata = {
 	.cle		= 21,
 	.ale		= 22,
 	.rdy_pin	= GPIO_PIN_PB(30),
 	.enable_pin	= GPIO_PIN_PB(29),
-	.partition_info	= nand_part_info,
+	.parts		= nand_partitions,
+	.num_parts	= ARRAY_SIZE(num_partitions),
 };
 #endif
 
diff -druN linux-libre-3.1-gnu/arch/avr32/mach-at32ap/clock.c linux-libre-3.2-gnu/arch/avr32/mach-at32ap/clock.c
--- linux-libre-3.1-gnu/arch/avr32/mach-at32ap/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/avr32/mach-at32ap/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  */
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <linux/device.h>
 #include <linux/string.h>
 #include <linux/list.h>
diff -druN linux-libre-3.1-gnu/arch/avr32/mach-at32ap/cpufreq.c linux-libre-3.2-gnu/arch/avr32/mach-at32ap/cpufreq.c
--- linux-libre-3.1-gnu/arch/avr32/mach-at32ap/cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/avr32/mach-at32ap/cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <asm/system.h>
 
 static struct clk *cpuclk;
diff -druN linux-libre-3.1-gnu/arch/avr32/mach-at32ap/include/mach/board.h linux-libre-3.2-gnu/arch/avr32/mach-at32ap/include/mach/board.h
--- linux-libre-3.1-gnu/arch/avr32/mach-at32ap/include/mach/board.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/avr32/mach-at32ap/include/mach/board.h	2012-01-04 18:55:44.000000000 -0500
@@ -128,7 +128,8 @@
 	u8	ale;		/* address line number connected to ALE */
 	u8	cle;		/* address line number connected to CLE */
 	u8	bus_width_16;	/* buswidth is 16 bit */
-	struct mtd_partition *(*partition_info)(int size, int *num_partitions);
+	struct mtd_partition *parts;
+	unsigned int	num_parts;
 };
 struct platform_device *
 at32_add_device_nand(unsigned int id, struct atmel_nand_data *data);
diff -druN linux-libre-3.1-gnu/arch/avr32/mach-at32ap/intc.c linux-libre-3.2-gnu/arch/avr32/mach-at32ap/intc.c
--- linux-libre-3.1-gnu/arch/avr32/mach-at32ap/intc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/avr32/mach-at32ap/intc.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/syscore_ops.h>
+#include <linux/export.h>
 
 #include <asm/io.h>
 
diff -druN linux-libre-3.1-gnu/arch/avr32/mach-at32ap/pio.c linux-libre-3.2-gnu/arch/avr32/mach-at32ap/pio.c
--- linux-libre-3.1-gnu/arch/avr32/mach-at32ap/pio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/avr32/mach-at32ap/pio.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 
 #include <linux/clk.h>
 #include <linux/debugfs.h>
+#include <linux/export.h>
 #include <linux/fs.h>
 #include <linux/platform_device.h>
 #include <linux/irq.h>
diff -druN linux-libre-3.1-gnu/arch/avr32/mm/dma-coherent.c linux-libre-3.2-gnu/arch/avr32/mm/dma-coherent.c
--- linux-libre-3.1-gnu/arch/avr32/mm/dma-coherent.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/avr32/mm/dma-coherent.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 
 #include <linux/dma-mapping.h>
 #include <linux/gfp.h>
+#include <linux/export.h>
 
 #include <asm/addrspace.h>
 #include <asm/cacheflush.h>
diff -druN linux-libre-3.1-gnu/arch/blackfin/configs/BF548-EZKIT_defconfig linux-libre-3.2-gnu/arch/blackfin/configs/BF548-EZKIT_defconfig
--- linux-libre-3.1-gnu/arch/blackfin/configs/BF548-EZKIT_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/configs/BF548-EZKIT_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,6 @@
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_ELF_CORE is not set
@@ -40,7 +39,6 @@
 CONFIG_EBIU_FCTLVAL=0x6
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
-CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -55,7 +53,6 @@
 CONFIG_CAN=m
 CONFIG_CAN_RAW=m
 CONFIG_CAN_BCM=m
-CONFIG_CAN_DEV=m
 CONFIG_CAN_BFIN=m
 CONFIG_IRDA=m
 CONFIG_IRLAN=m
@@ -67,7 +64,6 @@
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_FW_LOADER=m
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
@@ -105,12 +101,12 @@
 CONFIG_TOUCHSCREEN_AD7877=m
 CONFIG_INPUT_MISC=y
 # CONFIG_SERIO is not set
-# CONFIG_DEVKMEM is not set
+# CONFIG_LEGACY_PTYS is not set
 CONFIG_BFIN_JTAG_COMM=m
+# CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_BFIN=y
 CONFIG_SERIAL_BFIN_CONSOLE=y
 CONFIG_SERIAL_BFIN_UART1=y
-# CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -163,6 +159,7 @@
 CONFIG_USB_OTG_BLACKLIST_HUB=y
 CONFIG_USB_MON=y
 CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_BLACKFIN=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_BLOCK=m
@@ -185,8 +182,6 @@
 CONFIG_NFS_V3=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
 CONFIG_CIFS=y
 CONFIG_NLS_CODEPAGE_437=m
 CONFIG_NLS_CODEPAGE_936=m
@@ -196,7 +191,6 @@
 CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_FTRACE is not set
 CONFIG_DEBUG_MMRS=y
 CONFIG_DEBUG_HWERR=y
@@ -206,5 +200,4 @@
 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-3.1-gnu/arch/blackfin/include/asm/atomic.h linux-libre-3.2-gnu/arch/blackfin/include/asm/atomic.h
--- linux-libre-3.1-gnu/arch/blackfin/include/asm/atomic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/include/asm/atomic.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2009 Analog Devices Inc.
+ * Copyright 2004-2011 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -7,111 +7,27 @@
 #ifndef __ARCH_BLACKFIN_ATOMIC__
 #define __ARCH_BLACKFIN_ATOMIC__
 
-#ifndef CONFIG_SMP
-# include <asm-generic/atomic.h>
-#else
-
-#include <linux/types.h>
-#include <asm/system.h>	/* local_irq_XXX() */
-
-/*
- * Atomic operations that C can't guarantee us.  Useful for
- * resource counting etc..
- */
-
-#define ATOMIC_INIT(i)	{ (i) }
-#define atomic_set(v, i)	(((v)->counter) = i)
+#ifdef CONFIG_SMP
 
-#define atomic_read(v)	__raw_uncached_fetch_asm(&(v)->counter)
+#include <linux/linkage.h>
 
 asmlinkage int __raw_uncached_fetch_asm(const volatile int *ptr);
-
 asmlinkage int __raw_atomic_update_asm(volatile int *ptr, int value);
-
 asmlinkage int __raw_atomic_clear_asm(volatile int *ptr, int value);
-
 asmlinkage int __raw_atomic_set_asm(volatile int *ptr, int value);
-
 asmlinkage int __raw_atomic_xor_asm(volatile int *ptr, int value);
-
 asmlinkage int __raw_atomic_test_asm(const volatile int *ptr, int value);
 
-static inline void atomic_add(int i, atomic_t *v)
-{
-	__raw_atomic_update_asm(&v->counter, i);
-}
-
-static inline void atomic_sub(int i, atomic_t *v)
-{
-	__raw_atomic_update_asm(&v->counter, -i);
-}
-
-static inline int atomic_add_return(int i, atomic_t *v)
-{
-	return __raw_atomic_update_asm(&v->counter, i);
-}
-
-static inline int atomic_sub_return(int i, atomic_t *v)
-{
-	return __raw_atomic_update_asm(&v->counter, -i);
-}
-
-static inline void atomic_inc(volatile atomic_t *v)
-{
-	__raw_atomic_update_asm(&v->counter, 1);
-}
-
-static inline void atomic_dec(volatile atomic_t *v)
-{
-	__raw_atomic_update_asm(&v->counter, -1);
-}
-
-static inline void atomic_clear_mask(int mask, atomic_t *v)
-{
-	__raw_atomic_clear_asm(&v->counter, mask);
-}
-
-static inline void atomic_set_mask(int mask, atomic_t *v)
-{
-	__raw_atomic_set_asm(&v->counter, mask);
-}
-
-/* Atomic operations are already serializing */
-#define smp_mb__before_atomic_dec()    barrier()
-#define smp_mb__after_atomic_dec() barrier()
-#define smp_mb__before_atomic_inc()    barrier()
-#define smp_mb__after_atomic_inc() barrier()
-
-#define atomic_add_negative(a, v)	(atomic_add_return((a), (v)) < 0)
-#define atomic_dec_return(v) atomic_sub_return(1,(v))
-#define atomic_inc_return(v) atomic_add_return(1,(v))
-
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-#define __atomic_add_unless(v, a, u)				\
-({								\
-	int c, old;						\
-	c = atomic_read(v);					\
-	while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
-		c = old;					\
-	c;							\
-})
-
-/*
- * atomic_inc_and_test - increment and test
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1
- * and returns true if the result is zero, or false for all
- * other cases.
- */
-#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
+#define atomic_read(v) __raw_uncached_fetch_asm(&(v)->counter)
 
-#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
-#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+#define atomic_add_return(i, v) __raw_atomic_update_asm(&(v)->counter, i)
+#define atomic_sub_return(i, v) __raw_atomic_update_asm(&(v)->counter, -(i))
 
+#define atomic_clear_mask(m, v) __raw_atomic_clear_asm(&(v)->counter, m)
+#define atomic_set_mask(m, v)   __raw_atomic_set_asm(&(v)->counter, m)
 
 #endif
 
+#include <asm-generic/atomic.h>
+
 #endif
diff -druN linux-libre-3.1-gnu/arch/blackfin/include/asm/bfin_serial.h linux-libre-3.2-gnu/arch/blackfin/include/asm/bfin_serial.h
--- linux-libre-3.1-gnu/arch/blackfin/include/asm/bfin_serial.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/include/asm/bfin_serial.h	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,8 @@
 struct bfin_serial_port {
 	struct uart_port port;
 	unsigned int old_status;
+	int tx_irq;
+	int rx_irq;
 	int status_irq;
 #ifndef BFIN_UART_BF54X_STYLE
 	unsigned int lsr;
diff -druN linux-libre-3.1-gnu/arch/blackfin/include/asm/Kbuild linux-libre-3.2-gnu/arch/blackfin/include/asm/Kbuild
--- linux-libre-3.1-gnu/arch/blackfin/include/asm/Kbuild	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/include/asm/Kbuild	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 generic-y += local.h
 generic-y += mman.h
 generic-y += msgbuf.h
+generic-y += mutex.h
 generic-y += param.h
 generic-y += percpu.h
 generic-y += pgalloc.h
diff -druN linux-libre-3.1-gnu/arch/blackfin/include/asm/mutex.h linux-libre-3.2-gnu/arch/blackfin/include/asm/mutex.h
--- linux-libre-3.1-gnu/arch/blackfin/include/asm/mutex.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/mutex-dec.h>
diff -druN linux-libre-3.1-gnu/arch/blackfin/include/asm/uaccess.h linux-libre-3.2-gnu/arch/blackfin/include/asm/uaccess.h
--- linux-libre-3.1-gnu/arch/blackfin/include/asm/uaccess.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/include/asm/uaccess.h	2012-01-04 18:55:44.000000000 -0500
@@ -195,17 +195,17 @@
 copy_from_user(void *to, const void __user *from, unsigned long n)
 {
 	if (access_ok(VERIFY_READ, from, n))
-		memcpy(to, from, n);
+		memcpy(to, (const void __force *)from, n);
 	else
 		return n;
 	return 0;
 }
 
 static inline unsigned long __must_check
-copy_to_user(void *to, const void __user *from, unsigned long n)
+copy_to_user(void __user *to, const void *from, unsigned long n)
 {
 	if (access_ok(VERIFY_WRITE, to, n))
-		memcpy(to, from, n);
+		memcpy((void __force *)to, from, n);
 	else
 		return n;
 	return 0;
diff -druN linux-libre-3.1-gnu/arch/blackfin/Kconfig linux-libre-3.2-gnu/arch/blackfin/Kconfig
--- linux-libre-3.1-gnu/arch/blackfin/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -248,10 +248,6 @@
 	depends on SMP && HOTPLUG
 	default y
 
-config HAVE_LEGACY_PER_CPU_AREA
-	def_bool y
-	depends on SMP
-
 config BF_REV_MIN
 	int
 	default 0 if (BF51x || BF52x || (BF54x && !BF54xM))
diff -druN linux-libre-3.1-gnu/arch/blackfin/kernel/dma-mapping.c linux-libre-3.2-gnu/arch/blackfin/kernel/dma-mapping.c
--- linux-libre-3.1-gnu/arch/blackfin/kernel/dma-mapping.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/kernel/dma-mapping.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/spinlock.h>
 #include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
+#include <linux/export.h>
 
 static spinlock_t dma_page_lock;
 static unsigned long *dma_page;
diff -druN linux-libre-3.1-gnu/arch/blackfin/kernel/kgdb_test.c linux-libre-3.2-gnu/arch/blackfin/kernel/kgdb_test.c
--- linux-libre-3.1-gnu/arch/blackfin/kernel/kgdb_test.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/kernel/kgdb_test.c	2012-01-04 18:55:44.000000000 -0500
@@ -50,8 +50,7 @@
 
 #endif
 
-
-int kgdb_test(char *name, int len, int count, int z)
+noinline int kgdb_test(char *name, int len, int count, int z)
 {
 	pr_alert("kgdb name(%d): %s, %d, %d\n", len, name, count, z);
 	count = z;
diff -druN linux-libre-3.1-gnu/arch/blackfin/kernel/Makefile linux-libre-3.2-gnu/arch/blackfin/kernel/Makefile
--- linux-libre-3.1-gnu/arch/blackfin/kernel/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,6 @@
 
 # the kgdb test puts code into L2 and without linker
 # relaxation, we need to force long calls to/from it
-CFLAGS_kgdb_test.o := -mlong-calls -O0
+CFLAGS_kgdb_test.o := -mlong-calls
 
 obj-$(CONFIG_DEBUG_MMRS)             += debug-mmrs.o
diff -druN linux-libre-3.1-gnu/arch/blackfin/kernel/perf_event.c linux-libre-3.2-gnu/arch/blackfin/kernel/perf_event.c
--- linux-libre-3.1-gnu/arch/blackfin/kernel/perf_event.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/kernel/perf_event.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/perf_event.h>
 #include <asm/bfin_pfmon.h>
diff -druN linux-libre-3.1-gnu/arch/blackfin/kernel/sys_bfin.c linux-libre-3.2-gnu/arch/blackfin/kernel/sys_bfin.c
--- linux-libre-3.1-gnu/arch/blackfin/kernel/sys_bfin.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/kernel/sys_bfin.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
 
 #if defined(CONFIG_FB) || defined(CONFIG_FB_MODULE)
 #include <linux/fb.h>
+#include <linux/export.h>
 unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr,
 	unsigned long len, unsigned long pgoff, unsigned long flags)
 {
diff -druN linux-libre-3.1-gnu/arch/blackfin/kernel/time.c linux-libre-3.2-gnu/arch/blackfin/kernel/time.c
--- linux-libre-3.1-gnu/arch/blackfin/kernel/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/kernel/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,7 +25,6 @@
 
 static struct irqaction bfin_timer_irq = {
 	.name = "Blackfin Timer Tick",
-	.flags = IRQF_DISABLED
 };
 
 #if defined(CONFIG_IPIPE)
diff -druN linux-libre-3.1-gnu/arch/blackfin/kernel/time-ts.c linux-libre-3.2-gnu/arch/blackfin/kernel/time-ts.c
--- linux-libre-3.1-gnu/arch/blackfin/kernel/time-ts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/kernel/time-ts.c	2012-01-04 18:55:44.000000000 -0500
@@ -188,8 +188,7 @@
 
 static struct irqaction gptmr0_irq = {
 	.name		= "Blackfin GPTimer0",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | \
-			  IRQF_IRQPOLL | IRQF_PERCPU,
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL | IRQF_PERCPU,
 	.handler	= bfin_gptmr0_interrupt,
 };
 
@@ -297,8 +296,7 @@
 
 static struct irqaction coretmr_irq = {
 	.name		= "Blackfin CoreTimer",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | \
-			  IRQF_IRQPOLL | IRQF_PERCPU,
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL | IRQF_PERCPU,
 	.handler	= bfin_coretmr_interrupt,
 };
 
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf518/boards/ezbrd.c linux-libre-3.2-gnu/arch/blackfin/mach-bf518/boards/ezbrd.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf518/boards/ezbrd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf518/boards/ezbrd.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -372,8 +373,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -415,8 +421,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf518/boards/tcm-bf518.c linux-libre-3.2-gnu/arch/blackfin/mach-bf518/boards/tcm-bf518.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf518/boards/tcm-bf518.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf518/boards/tcm-bf518.c	2012-01-04 18:55:44.000000000 -0500
@@ -309,8 +309,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -352,8 +357,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf527/boards/ad7160eval.c linux-libre-3.2-gnu/arch/blackfin/mach-bf527/boards/ad7160eval.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf527/boards/ad7160eval.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf527/boards/ad7160eval.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -380,8 +381,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -423,8 +429,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf527/boards/cm_bf527.c linux-libre-3.2-gnu/arch/blackfin/mach-bf527/boards/cm_bf527.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf527/boards/cm_bf527.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf527/boards/cm_bf527.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -539,8 +540,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -582,8 +588,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf527/boards/ezbrd.c linux-libre-3.2-gnu/arch/blackfin/mach-bf527/boards/ezbrd.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf527/boards/ezbrd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf527/boards/ezbrd.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -417,8 +418,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -460,8 +466,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf527/boards/ezkit.c linux-libre-3.2-gnu/arch/blackfin/mach-bf527/boards/ezkit.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf527/boards/ezkit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf527/boards/ezkit.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -710,8 +711,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -753,8 +759,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf527/boards/tll6527m.c linux-libre-3.2-gnu/arch/blackfin/mach-bf527/boards/tll6527m.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf527/boards/tll6527m.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf527/boards/tll6527m.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -495,8 +496,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -539,8 +545,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf533/boards/blackstamp.c linux-libre-3.2-gnu/arch/blackfin/mach-bf533/boards/blackstamp.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf533/boards/blackstamp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf533/boards/blackstamp.c	2012-01-04 18:55:44.000000000 -0500
@@ -193,8 +193,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX + 1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf533/boards/cm_bf533.c linux-libre-3.2-gnu/arch/blackfin/mach-bf533/boards/cm_bf533.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf533/boards/cm_bf533.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf533/boards/cm_bf533.c	2012-01-04 18:55:44.000000000 -0500
@@ -221,8 +221,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX + 1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf533/boards/ezkit.c linux-libre-3.2-gnu/arch/blackfin/mach-bf533/boards/ezkit.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf533/boards/ezkit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf533/boards/ezkit.c	2012-01-04 18:55:44.000000000 -0500
@@ -292,8 +292,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX + 1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf533/boards/H8606.c linux-libre-3.2-gnu/arch/blackfin/mach-bf533/boards/H8606.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf533/boards/H8606.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf533/boards/H8606.c	2012-01-04 18:55:44.000000000 -0500
@@ -54,7 +54,8 @@
 	[2] = {
 		.start	= IRQ_PF10,
 		.end	= IRQ_PF10,
-		.flags	= (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IRQF_SHARED | IRQF_TRIGGER_HIGH),
+		.flags	= (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE |
+		           IORESOURCE_IRQ_SHAREABLE),
 	},
 };
 
@@ -237,8 +238,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX + 1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf533/boards/ip0x.c linux-libre-3.2-gnu/arch/blackfin/mach-bf533/boards/ip0x.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf533/boards/ip0x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf533/boards/ip0x.c	2012-01-04 18:55:44.000000000 -0500
@@ -151,8 +151,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX + 1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf533/boards/stamp.c linux-libre-3.2-gnu/arch/blackfin/mach-bf533/boards/stamp.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf533/boards/stamp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf533/boards/stamp.c	2012-01-04 18:55:44.000000000 -0500
@@ -298,8 +298,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX + 1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf537/boards/cm_bf537e.c linux-libre-3.2-gnu/arch/blackfin/mach-bf537/boards/cm_bf537e.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf537/boards/cm_bf537e.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf537/boards/cm_bf537e.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/etherdevice.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
@@ -305,8 +306,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -366,8 +372,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -605,7 +616,7 @@
 
 static struct pata_platform_info bfin_pata_platform_data = {
 	.ioport_shift = 2,
-	.irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+	.irq_type = IRQF_TRIGGER_HIGH,
 };
 
 static struct resource bfin_pata_resources[] = {
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf537/boards/cm_bf537u.c linux-libre-3.2-gnu/arch/blackfin/mach-bf537/boards/cm_bf537u.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf537/boards/cm_bf537u.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf537/boards/cm_bf537u.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 
 #include <linux/device.h>
 #include <linux/etherdevice.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -306,8 +307,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -349,8 +355,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -570,7 +581,7 @@
 
 static struct pata_platform_info bfin_pata_platform_data = {
 	.ioport_shift = 2,
-	.irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+	.irq_type = IRQF_TRIGGER_HIGH,
 };
 
 static struct resource bfin_pata_resources[] = {
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf537/boards/dnp5370.c linux-libre-3.2-gnu/arch/blackfin/mach-bf537/boards/dnp5370.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf537/boards/dnp5370.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf537/boards/dnp5370.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -236,8 +237,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -280,8 +286,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end   = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end   = IRQ_UART1_RX+1,
+		.end   = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf537/boards/minotaur.c linux-libre-3.2-gnu/arch/blackfin/mach-bf537/boards/minotaur.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf537/boards/minotaur.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf537/boards/minotaur.c	2012-01-04 18:55:44.000000000 -0500
@@ -240,8 +240,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -283,8 +288,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf537/boards/pnav10.c linux-libre-3.2-gnu/arch/blackfin/mach-bf537/boards/pnav10.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf537/boards/pnav10.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf537/boards/pnav10.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 
 #include <linux/device.h>
 #include <linux/etherdevice.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -100,6 +101,7 @@
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 #include <linux/bfin_mac.h>
+#include <linux/export.h>
 static const unsigned short bfin_mac_peripherals[] = P_RMII0;
 
 static struct bfin_phydev_platform_data bfin_phydev_data[] = {
@@ -308,8 +310,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -351,8 +358,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf537/boards/stamp.c linux-libre-3.2-gnu/arch/blackfin/mach-bf537/boards/stamp.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf537/boards/stamp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf537/boards/stamp.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -962,10 +963,10 @@
 	},
 #endif
 
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
-	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \
+	|| defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
 	{
-		.modalias = "ad183x",
+		.modalias = "ad1836",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 4,
@@ -984,9 +985,9 @@
 	},
 #endif
 
-#if defined(CONFIG_SND_BF5XX_SOC_ADAV80X) || defined(CONFIG_SND_BF5XX_SOC_ADAV80X_MODULE)
+#if defined(CONFIG_SND_SOC_ADAV80X) || defined(CONFIG_SND_SOC_ADV80X_MODULE)
 	{
-		.modalias = "adav80x",
+		.modalias = "adav801",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
@@ -1566,8 +1567,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -1621,8 +1627,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -2101,7 +2112,7 @@
 	},
 #endif
 
-#if defined(CONFIG_SND_BF5XX_SOC_ADAV80X) || defined(CONFIG_SND_BF5XX_SOC_ADAV80X_MODULE)
+#if defined(CONFIG_SND_SOC_ADAV80X) || defined(CONFIG_SND_SOC_ADAV80X_MODULE)
 	{
 		I2C_BOARD_INFO("adav803", 0x10),
 	},
@@ -2134,23 +2145,6 @@
 	},
 #endif
 
-#if defined(CONFIG_AD7414) || defined(CONFIG_AD7414_MODULE)
-	{
-		I2C_BOARD_INFO("ad7414", 0x9),
-		.irq = IRQ_PG5,
-		.irq_flags = IRQF_TRIGGER_LOW,
-	},
-#endif
-
-#if defined(CONFIG_AD7416) || defined(CONFIG_AD7416_MODULE)
-	{
-		I2C_BOARD_INFO("ad7417", 0xb),
-		.irq = IRQ_PG5,
-		.irq_flags = IRQF_TRIGGER_LOW,
-		.platform_data = (void *)GPIO_PF4,
-	},
-#endif
-
 #if defined(CONFIG_ADE7854_I2C) || defined(CONFIG_ADE7854_I2C_MODULE)
 	{
 		I2C_BOARD_INFO("ade7854", 0x38),
@@ -2161,15 +2155,6 @@
 	{
 		I2C_BOARD_INFO("adt75", 0x9),
 		.irq = IRQ_PG5,
-		.irq_flags = IRQF_TRIGGER_LOW,
-	},
-#endif
-
-#if defined(CONFIG_ADT7408) || defined(CONFIG_ADT7408_MODULE)
-	{
-		I2C_BOARD_INFO("adt7408", 0x18),
-		.irq = IRQ_PG5,
-		.irq_flags = IRQF_TRIGGER_LOW,
 	},
 #endif
 
@@ -2178,7 +2163,6 @@
 		I2C_BOARD_INFO("adt7410", 0x48),
 		/* CT critical temperature event. line 0 */
 		.irq = IRQ_PG5,
-		.irq_flags = IRQF_TRIGGER_LOW,
 		.platform_data = (void *)&adt7410_platform_data,
 	},
 #endif
@@ -2187,7 +2171,6 @@
 	{
 		I2C_BOARD_INFO("ad7291", 0x20),
 		.irq = IRQ_PG5,
-		.irq_flags = IRQF_TRIGGER_LOW,
 	},
 #endif
 
@@ -2275,6 +2258,11 @@
 		I2C_BOARD_INFO("adau1361", 0x38),
 	},
 #endif
+#if defined(CONFIG_SND_SOC_ADAU1701) || defined(CONFIG_SND_SOC_ADAU1701_MODULE)
+	{
+		I2C_BOARD_INFO("adau1701", 0x34),
+	},
+#endif
 #if defined(CONFIG_AD525X_DPOT) || defined(CONFIG_AD525X_DPOT_MODULE)
 	{
 		I2C_BOARD_INFO("ad5258", 0x18),
@@ -2388,7 +2376,7 @@
 #define PATA_INT	IRQ_PF5
 static struct pata_platform_info bfin_pata_platform_data = {
 	.ioport_shift = 1,
-	.irq_flags = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+	.irq_flags = IRQF_TRIGGER_HIGH,
 };
 
 static struct resource bfin_pata_resources[] = {
@@ -2540,13 +2528,21 @@
 };
 #endif
 
-#if defined(CONFIG_SND_BF5XX_SOC_AD73311) || defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE)
+#if defined(CONFIG_SND_SOC_AD73311) || defined(CONFIG_SND_SOC_AD73311_MODULE)
 static struct platform_device bfin_ad73311_codec_device = {
 	.name = "ad73311",
 	.id = -1,
 };
 #endif
 
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X) || \
+	defined(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X_MODULE)
+static struct platform_device bfin_eval_adav801_device = {
+	.name = "bfin-eval-adav801",
+	.id = -1,
+};
+#endif
+
 #if defined(CONFIG_SND_BF5XX_SOC_I2S) || defined(CONFIG_SND_BF5XX_SOC_I2S_MODULE)
 static struct platform_device bfin_i2s = {
 	.name = "bfin-i2s",
@@ -2661,6 +2657,20 @@
 };
 #endif
 
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373) || \
+	defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373_MODULE)
+static struct platform_device bf5xx_adau1373_device = {
+	.name = "bfin-eval-adau1373",
+};
+#endif
+
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701) || \
+	defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701_MODULE)
+static struct platform_device bf5xx_adau1701_device = {
+	.name = "bfin-eval-adau1701",
+};
+#endif
+
 static struct platform_device *stamp_devices[] __initdata = {
 
 	&bfin_dpmc,
@@ -2782,7 +2792,7 @@
 	&bfin_ac97_pcm,
 #endif
 
-#if defined(CONFIG_SND_BF5XX_SOC_AD73311) || defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE)
+#if defined(CONFIG_SND_SOC_AD73311) || defined(CONFIG_SND_SOC_AD73311_MODULE)
 	&bfin_ad73311_codec_device,
 #endif
 
@@ -2821,6 +2831,21 @@
 	defined(CONFIG_IIO_GPIO_TRIGGER_MODULE)
 	&iio_gpio_trigger,
 #endif
+
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373) || \
+	defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373_MODULE)
+	&bf5xx_adau1373_device,
+#endif
+
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701) || \
+	defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701_MODULE)
+	&bf5xx_adau1701_device,
+#endif
+
+#if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X) || \
+	defined(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X_MODULE)
+	&bfin_eval_adav801_device,
+#endif
 };
 
 static int __init net2272_init(void)
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf537/boards/tcm_bf537.c linux-libre-3.2-gnu/arch/blackfin/mach-bf537/boards/tcm_bf537.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf537/boards/tcm_bf537.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf537/boards/tcm_bf537.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 
 #include <linux/device.h>
 #include <linux/etherdevice.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -306,8 +307,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -349,8 +355,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -572,7 +583,7 @@
 
 static struct pata_platform_info bfin_pata_platform_data = {
 	.ioport_shift = 2,
-	.irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+	.irq_type = IRQF_TRIGGER_HIGH,
 };
 
 static struct resource bfin_pata_resources[] = {
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf538/boards/ezkit.c linux-libre-3.2-gnu/arch/blackfin/mach-bf538/boards/ezkit.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf538/boards/ezkit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf538/boards/ezkit.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,8 +49,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -104,8 +109,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -147,8 +157,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART2_TX,
+		.end = IRQ_UART2_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART2_RX,
-		.end = IRQ_UART2_RX+1,
+		.end = IRQ_UART2_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf548/boards/cm_bf548.c linux-libre-3.2-gnu/arch/blackfin/mach-bf548/boards/cm_bf548.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf548/boards/cm_bf548.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf548/boards/cm_bf548.c	2012-01-04 18:55:44.000000000 -0500
@@ -135,8 +135,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -178,8 +183,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -237,8 +247,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART2_TX,
+		.end = IRQ_UART2_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART2_RX,
-		.end = IRQ_UART2_RX+1,
+		.end = IRQ_UART2_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -280,8 +295,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART3_TX,
+		.end = IRQ_UART3_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART3_RX,
-		.end = IRQ_UART3_RX+1,
+		.end = IRQ_UART3_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf548/boards/ezkit.c linux-libre-3.2-gnu/arch/blackfin/mach-bf548/boards/ezkit.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf548/boards/ezkit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf548/boards/ezkit.c	2012-01-04 18:55:44.000000000 -0500
@@ -241,8 +241,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART0_TX,
+		.end = IRQ_UART0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART0_RX,
-		.end = IRQ_UART0_RX+1,
+		.end = IRQ_UART0_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -284,8 +289,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART1_TX,
+		.end = IRQ_UART1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART1_RX,
-		.end = IRQ_UART1_RX+1,
+		.end = IRQ_UART1_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -343,8 +353,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART2_TX,
+		.end = IRQ_UART2_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART2_RX,
-		.end = IRQ_UART2_RX+1,
+		.end = IRQ_UART2_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -386,8 +401,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART3_TX,
+		.end = IRQ_UART3_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART3_RX,
-		.end = IRQ_UART3_RX+1,
+		.end = IRQ_UART3_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf561/boards/acvilon.c linux-libre-3.2-gnu/arch/blackfin/mach-bf561/boards/acvilon.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf561/boards/acvilon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf561/boards/acvilon.c	2012-01-04 18:55:44.000000000 -0500
@@ -203,8 +203,13 @@
 	 .flags = IORESOURCE_MEM,
 	 },
 	{
+	 .start = IRQ_UART_TX,
+	 .end = IRQ_UART_TX,
+	 .flags = IORESOURCE_IRQ,
+	 },
+	{
 	 .start = IRQ_UART_RX,
-	 .end = IRQ_UART_RX + 1,
+	 .end = IRQ_UART_RX,
 	 .flags = IORESOURCE_IRQ,
 	 },
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf561/boards/cm_bf561.c linux-libre-3.2-gnu/arch/blackfin/mach-bf561/boards/cm_bf561.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf561/boards/cm_bf561.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf561/boards/cm_bf561.c	2012-01-04 18:55:44.000000000 -0500
@@ -277,8 +277,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART_TX,
+		.end = IRQ_UART_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART_RX,
-		.end = IRQ_UART_RX+1,
+		.end = IRQ_UART_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
@@ -348,7 +353,7 @@
 
 static struct pata_platform_info bfin_pata_platform_data = {
 	.ioport_shift = 2,
-	.irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
+	.irq_type = IRQF_TRIGGER_HIGH,
 };
 
 static struct resource bfin_pata_resources[] = {
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf561/boards/ezkit.c linux-libre-3.2-gnu/arch/blackfin/mach-bf561/boards/ezkit.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf561/boards/ezkit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf561/boards/ezkit.c	2012-01-04 18:55:44.000000000 -0500
@@ -172,8 +172,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART_TX,
+		.end = IRQ_UART_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART_RX,
-		.end = IRQ_UART_RX+1,
+		.end = IRQ_UART_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf561/boards/tepla.c linux-libre-3.2-gnu/arch/blackfin/mach-bf561/boards/tepla.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf561/boards/tepla.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf561/boards/tepla.c	2012-01-04 18:55:44.000000000 -0500
@@ -51,8 +51,13 @@
 		.flags = IORESOURCE_MEM,
 	},
 	{
+		.start = IRQ_UART_TX,
+		.end = IRQ_UART_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
 		.start = IRQ_UART_RX,
-		.end = IRQ_UART_RX+1,
+		.end = IRQ_UART_RX,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-bf561/smp.c linux-libre-3.2-gnu/arch/blackfin/mach-bf561/smp.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-bf561/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-bf561/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -114,7 +114,7 @@
 	int ret;
 	const char *name = (irq == IRQ_SUPPLE_0) ? supple0 : supple1;
 
-	ret = request_irq(irq, handler, IRQF_DISABLED | IRQF_PERCPU, name, handler);
+	ret = request_irq(irq, handler, IRQF_PERCPU, name, handler);
 	if (ret)
 		panic("Cannot request %s for IPI service", name);
 }
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-common/cpufreq.c linux-libre-3.2-gnu/arch/blackfin/mach-common/cpufreq.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-common/cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-common/cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
diff -druN linux-libre-3.1-gnu/arch/blackfin/mach-common/smp.c linux-libre-3.2-gnu/arch/blackfin/mach-common/smp.c
--- linux-libre-3.1-gnu/arch/blackfin/mach-common/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mach-common/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -295,10 +295,15 @@
 
 void smp_send_reschedule(int cpu)
 {
+	cpumask_t callmap;
 	/* simply trigger an ipi */
 	if (cpu_is_offline(cpu))
 		return;
-	platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
+
+	cpumask_clear(&callmap);
+	cpumask_set_cpu(cpu, &callmap);
+
+	smp_send_message(callmap, BFIN_IPI_RESCHEDULE, NULL, NULL, 0);
 
 	return;
 }
diff -druN linux-libre-3.1-gnu/arch/blackfin/mm/init.c linux-libre-3.2-gnu/arch/blackfin/mm/init.c
--- linux-libre-3.1-gnu/arch/blackfin/mm/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/blackfin/mm/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 #include <linux/swap.h>
 #include <linux/bootmem.h>
 #include <linux/uaccess.h>
+#include <linux/export.h>
 #include <asm/bfin-global.h>
 #include <asm/pda.h>
 #include <asm/cplbinit.h>
diff -druN linux-libre-3.1-gnu/arch/cris/arch-v10/drivers/Kconfig linux-libre-3.2-gnu/arch/cris/arch-v10/drivers/Kconfig
--- linux-libre-3.1-gnu/arch/cris/arch-v10/drivers/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/cris/arch-v10/drivers/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,8 @@
 config ETRAX_ETHERNET
 	bool "Ethernet support"
 	depends on ETRAX_ARCH_V10
-	select NET_ETHERNET
+	select ETHERNET
+	select NET_CORE
 	select MII
 	help
 	  This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet
diff -druN linux-libre-3.1-gnu/arch/cris/arch-v10/Kconfig linux-libre-3.2-gnu/arch/cris/arch-v10/Kconfig
--- linux-libre-3.1-gnu/arch/cris/arch-v10/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/cris/arch-v10/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -24,8 +24,8 @@
 	help
 	  The ETRAX network driver is responsible for flashing LED's when
 	  packets arrive and are sent.  It uses macros defined in
-	  <file:include/asm-cris/io.h>, and those macros are defined after what
-	  YOU choose in this option.  The actual bits used are configured
+	  <file:arch/cris/include/asm/io.h>, and those macros are defined after
+	  what YOU choose in this option.  The actual bits used are configured
 	  separately.  Select this if the LEDs are on port PA.  Some products
 	  put the leds on PB or a memory-mapped latch (CSP0) instead.
 
@@ -34,8 +34,8 @@
 	help
 	  The ETRAX network driver is responsible for flashing LED's when
 	  packets arrive and are sent.  It uses macros defined in
-	  <file:include/asm-cris/io.h>, and those macros are defined after what
-	  YOU choose in this option.  The actual bits used are configured
+	  <file:arch/cris/include/asm/io.h>, and those macros are defined after
+	  what YOU choose in this option.  The actual bits used are configured
 	  separately.  Select this if the LEDs are on port PB.  Some products
 	  put the leds on PA or a memory-mapped latch (CSP0) instead.
 
@@ -44,8 +44,8 @@
 	help
 	  The ETRAX network driver is responsible for flashing LED's when
 	  packets arrive and are sent. It uses macros defined in
-	  <file:include/asm-cris/io.h>, and those macros are defined after what
-	  YOU choose in this option.  The actual bits used are configured
+	  <file:arch/cris/include/asm/io.h>, and those macros are defined after
+	  what YOU choose in this option.  The actual bits used are configured
 	  separately.  Select this if the LEDs are on a memory-mapped latch
 	  using chip select CSP0, this is mapped at 0x90000000.
 	  Some products put the leds on PA or PB instead.
diff -druN linux-libre-3.1-gnu/arch/cris/arch-v10/kernel/kgdb.c linux-libre-3.2-gnu/arch/cris/arch-v10/kernel/kgdb.c
--- linux-libre-3.1-gnu/arch/cris/arch-v10/kernel/kgdb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/cris/arch-v10/kernel/kgdb.c	2012-01-04 18:55:44.000000000 -0500
@@ -694,7 +694,7 @@
                 /* Valid mem address. */
                 for (i = 0; i < count; i++) {
                         ch = *mem++;
-			buf = pack_hex_byte(buf, ch);
+			buf = hex_byte_pack(buf, ch);
                 }
         }
         
@@ -868,7 +868,7 @@
 	/* Send trap type (converted to signal) */
 
 	*ptr++ = 'T';
-	ptr = pack_hex_byte(ptr, sigval);
+	ptr = hex_byte_pack(ptr, sigval);
 
 	/* Send register contents. We probably only need to send the
 	 * PC, frame pointer and stack pointer here. Other registers will be
@@ -881,7 +881,7 @@
                 status = read_register (regno, &reg_cont);
                 
 		if (status == SUCCESS) {
-			ptr = pack_hex_byte(ptr, regno);
+			ptr = hex_byte_pack(ptr, regno);
                         *ptr++ = ':';
 
                         ptr = mem2hex(ptr, (unsigned char *)&reg_cont,
diff -druN linux-libre-3.1-gnu/arch/cris/arch-v32/drivers/Kconfig linux-libre-3.2-gnu/arch/cris/arch-v32/drivers/Kconfig
--- linux-libre-3.1-gnu/arch/cris/arch-v32/drivers/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/cris/arch-v32/drivers/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,8 @@
 config ETRAX_ETHERNET
 	bool "Ethernet support"
 	depends on ETRAX_ARCH_V32
-	select NET_ETHERNET
+	select ETHERNET
+	select NET_CORE
 	select MII
 	help
 	  This option enables the ETRAX FS built-in 10/100Mbit Ethernet
diff -druN linux-libre-3.1-gnu/arch/cris/arch-v32/drivers/mach-a3/nandflash.c linux-libre-3.2-gnu/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
--- linux-libre-3.1-gnu/arch/cris/arch-v32/drivers/mach-a3/nandflash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/cris/arch-v32/drivers/mach-a3/nandflash.c	2012-01-04 18:55:44.000000000 -0500
@@ -163,7 +163,7 @@
 	this->ecc.mode = NAND_ECC_SOFT;
 
 	/* Enable the following for a flash based bad block table */
-	/* this->options = NAND_USE_FLASH_BBT; */
+	/* this->bbt_options = NAND_BBT_USE_FLASH; */
 
 	/* Scan to find existence of the device */
 	if (nand_scan(crisv32_mtd, 1)) {
diff -druN linux-libre-3.1-gnu/arch/cris/arch-v32/drivers/mach-fs/nandflash.c linux-libre-3.2-gnu/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
--- linux-libre-3.1-gnu/arch/cris/arch-v32/drivers/mach-fs/nandflash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/cris/arch-v32/drivers/mach-fs/nandflash.c	2012-01-04 18:55:44.000000000 -0500
@@ -154,7 +154,7 @@
 	this->ecc.mode = NAND_ECC_SOFT;
 
 	/* Enable the following for a flash based bad block table */
-	/* this->options = NAND_USE_FLASH_BBT; */
+	/* this->bbt_options = NAND_BBT_USE_FLASH; */
 
 	/* Scan to find existence of the device */
 	if (nand_scan(crisv32_mtd, 1)) {
diff -druN linux-libre-3.1-gnu/arch/cris/arch-v32/kernel/kgdb.c linux-libre-3.2-gnu/arch/cris/arch-v32/kernel/kgdb.c
--- linux-libre-3.1-gnu/arch/cris/arch-v32/kernel/kgdb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/cris/arch-v32/kernel/kgdb.c	2012-01-04 18:55:44.000000000 -0500
@@ -677,7 +677,7 @@
                 /* Valid mem address. */
 		for (i = 0; i < count; i++) {
 			ch = *mem++;
-			buf = pack_hex_byte(buf, ch);
+			buf = hex_byte_pack(buf, ch);
 		}
         }
         /* Terminate properly. */
@@ -695,7 +695,7 @@
 	mem += count - 1;
 	for (i = 0; i < count; i++) {
 		ch = *mem--;
-		buf = pack_hex_byte(buf, ch);
+		buf = hex_byte_pack(buf, ch);
         }
 
         /* Terminate properly. */
@@ -880,7 +880,7 @@
 	/* Send trap type (converted to signal) */
 
 	*ptr++ = 'T';
-	ptr = pack_hex_byte(ptr, sigval);
+	ptr = hex_byte_pack(ptr, sigval);
 
 	if (((reg.exs & 0xff00) >> 8) == 0xc) {
 
@@ -988,26 +988,26 @@
 	}
 	/* Only send PC, frame and stack pointer. */
 	read_register(PC, &reg_cont);
-	ptr = pack_hex_byte(ptr, PC);
+	ptr = hex_byte_pack(ptr, PC);
 	*ptr++ = ':';
 	ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[PC]);
 	*ptr++ = ';';
 
 	read_register(R8, &reg_cont);
-	ptr = pack_hex_byte(ptr, R8);
+	ptr = hex_byte_pack(ptr, R8);
 	*ptr++ = ':';
 	ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[R8]);
 	*ptr++ = ';';
 
 	read_register(SP, &reg_cont);
-	ptr = pack_hex_byte(ptr, SP);
+	ptr = hex_byte_pack(ptr, SP);
 	*ptr++ = ':';
 	ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[SP]);
 	*ptr++ = ';';
 
 	/* Send ERP as well; this will save us an entire register fetch in some cases. */
         read_register(ERP, &reg_cont);
-	ptr = pack_hex_byte(ptr, ERP);
+	ptr = hex_byte_pack(ptr, ERP);
         *ptr++ = ':';
         ptr = mem2hex(ptr, (unsigned char *)&reg_cont, register_size[ERP]);
         *ptr++ = ';';
diff -druN linux-libre-3.1-gnu/arch/cris/arch-v32/lib/nand_init.S linux-libre-3.2-gnu/arch/cris/arch-v32/lib/nand_init.S
--- linux-libre-3.1-gnu/arch/cris/arch-v32/lib/nand_init.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/cris/arch-v32/lib/nand_init.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,178 +0,0 @@
-##=============================================================================
-##
-##      nand_init.S
-##
-##      The bootrom copies data from the NAND flash to the internal RAM but
-##      due to a bug/feature we can only trust the 256 first bytes. So this
-##      code copies more data from NAND flash to internal RAM. Obvioulsy this
-##      code must fit in the first 256 bytes so alter with care.
-##
-##	Some notes about the bug/feature for future reference:
-##        The bootrom copies the first 127 KB from NAND flash to internal
-##        memory. The problem is that it does a bytewise copy. NAND flashes
-##        does autoincrement on the address so for a 16-bite device each
-##        read/write increases the address by two. So the copy loop in the
-##        bootrom will discard every second byte. This is solved by inserting
-##        zeroes in every second byte in the first erase block.
-##
-##        The bootrom also incorrectly assumes that it can read the flash
-##        linear with only one read command but the flash will actually
-##        switch between normal area and spare area if you do that so we
-##        can't trust more than the first 256 bytes.
-##
-##=============================================================================
-
-#include <arch/hwregs/asm/reg_map_asm.h>
-#include <arch/hwregs/asm/gio_defs_asm.h>
-#include <arch/hwregs/asm/pinmux_defs_asm.h>
-#include <arch/hwregs/asm/bif_core_defs_asm.h>
-#include <arch/hwregs/asm/config_defs_asm.h>
-
-;; There are 8-bit NAND flashes and 16-bit NAND flashes.
-;; We need to treat them slightly different.
-#if CONFIG_ETRAX_FLASH_BUSWIDTH==2
-#define PAGE_SIZE 256
-#else
-#error 2
-#define PAGE_SIZE 512
-#endif
-#define ERASE_BLOCK 16384
-
-;; GPIO pins connected to NAND flash
-#define CE 4
-#define CLE 5
-#define ALE 6
-#define BY 7
-
-;; Address space for NAND flash
-#define NAND_RD_ADDR 0x90000000
-#define NAND_WR_ADDR 0x94000000
-
-#define READ_CMD 0x00
-
-;; Readability macros
-#define CSP_MASK \
-	REG_MASK(bif_core, rw_grp3_cfg, gated_csp0) | \
-	REG_MASK(bif_core, rw_grp3_cfg, gated_csp1)
-#define CSP_VAL \
-	REG_STATE(bif_core, rw_grp3_cfg, gated_csp0, rd) | \
-	REG_STATE(bif_core, rw_grp3_cfg, gated_csp1, wr)
-
-;;----------------------------------------------------------------------------
-;; Macros to set/clear GPIO bits
-
-.macro SET x
-	or.b   (1<<\x),$r9
-	move.d $r9, [$r2]
-.endm
-
-.macro CLR x
-	and.b  ~(1<<\x),$r9
-	move.d $r9, [$r2]
-.endm
-
-;;----------------------------------------------------------------------------
-
-nand_boot:
-	;; Check if nand boot was selected
-	move.d REG_ADDR(config, regi_config, r_bootsel), $r0
-	move.d [$r0], $r0
-	and.d  REG_MASK(config, r_bootsel, boot_mode), $r0
-	cmp.d  REG_STATE(config, r_bootsel, boot_mode, nand), $r0
-	bne normal_boot ; No NAND boot
-	nop
-
-copy_nand_to_ram:
-	;; copy_nand_to_ram
-	;; Arguments
-	;;   r10 - destination
-	;;   r11 - source offset
-	;;   r12 - size
-	;;   r13 - Address to jump to after completion
-	;; Note : r10-r12 are clobbered on return
-	;; Registers used:
-	;;   r0 - NAND_RD_ADDR
-	;;   r1 - NAND_WR_ADDR
-	;;   r2 - reg_gio_rw_pa_dout
-	;;   r3 - reg_gio_r_pa_din
-	;;   r4 - tmp
-	;;   r5 - byte counter within a page
-	;;   r6 - reg_pinmux_rw_pa
-	;;   r7 - reg_gio_rw_pa_oe
-	;;   r8 - reg_bif_core_rw_grp3_cfg
-	;;   r9 - reg_gio_rw_pa_dout shadow
-	move.d 0x90000000, $r0
-	move.d 0x94000000, $r1
-	move.d REG_ADDR(gio, regi_gio, rw_pa_dout), $r2
-	move.d REG_ADDR(gio, regi_gio, r_pa_din), $r3
-	move.d REG_ADDR(pinmux, regi_pinmux, rw_pa), $r6
-	move.d REG_ADDR(gio, regi_gio, rw_pa_oe), $r7
-	move.d REG_ADDR(bif_core, regi_bif_core, rw_grp3_cfg), $r8
-
-#if CONFIG_ETRAX_FLASH_BUSWIDTH==2
-	lsrq	1, $r11
-#endif
-	;; Set up GPIO
-	move.d [$r2], $r9
-	move.d [$r7], $r4
-	or.b (1<<ALE) | (1 << CLE) | (1<<CE), $r4
-	move.d $r4, [$r7]
-
-	;; Set up bif
-	move.d [$r8], $r4
-	and.d CSP_MASK, $r4
-	or.d CSP_VAL, $r4
-	move.d $r4, [$r8]
-
-1:	;; Copy one page
-	CLR CE
-	SET CLE
-	moveq	READ_CMD, $r4
-	move.b	$r4, [$r1]
-	moveq	20, $r4
-2:	bne	2b
-	subq	1, $r4
-	CLR CLE
-	SET ALE
-	clear.w [$r1] 		; Column address = 0
-	move.d	$r11, $r4
-	lsrq	8, $r4
-	move.b	$r4, [$r1]	; Row address
-	lsrq	8, $r4
-	move.b	$r4, [$r1]	; Row address
-	moveq	20, $r4
-2:	bne	2b
-	subq	1, $r4
-	CLR ALE
-2:	move.d	[$r3], $r4
-	and.d	1 << BY, $r4
-	beq 2b
-	movu.w  PAGE_SIZE, $r5
-2:	; Copy one byte/word
-#if CONFIG_ETRAX_FLASH_BUSWIDTH==2
-	move.w  [$r0], $r4
-#else
-	move.b  [$r0], $r4
-#endif
-	subq	1, $r5
-	bne	2b
-#if CONFIG_ETRAX_FLASH_BUSWIDTH==2
-	move.w  $r4, [$r10+]
-	subu.w	PAGE_SIZE*2, $r12
-#else
-	move.b  $r4, [$r10+]
-	subu.w	PAGE_SIZE, $r12
-#endif
-	bpl	1b
-	addu.w	PAGE_SIZE, $r11
-
-	;; End of copy
-	jump	$r13
-	nop
-
-	;; This will warn if the code above is too large. If you consider
-	;; to remove this you don't understand the bug/feature.
-	.org 256
-	.org ERASE_BLOCK
-
-normal_boot:
diff -druN linux-libre-3.1-gnu/arch/cris/Kconfig linux-libre-3.2-gnu/arch/cris/Kconfig
--- linux-libre-3.1-gnu/arch/cris/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/cris/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -282,8 +282,8 @@
 	  Enables drivers for the Real-Time Clock battery-backed chips on
 	  some products. The kernel reads the time when booting, and
 	  the date can be set using ioctl(fd, RTC_SET_TIME, &rt) with rt a
-	  rtc_time struct (see <file:include/asm-cris/rtc.h>) on the /dev/rtc
-	  device.  You can check the time with cat /proc/rtc, but
+	  rtc_time struct (see <file:arch/cris/include/asm/rtc.h>) on the
+	  /dev/rtc device.  You can check the time with cat /proc/rtc, but
 	  normal time reading should be done using libc function time and
 	  friends.
 
diff -druN linux-libre-3.1-gnu/arch/frv/kernel/gdb-stub.c linux-libre-3.2-gnu/arch/frv/kernel/gdb-stub.c
--- linux-libre-3.1-gnu/arch/frv/kernel/gdb-stub.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/frv/kernel/gdb-stub.c	2012-01-04 18:55:44.000000000 -0500
@@ -672,7 +672,7 @@
 	if ((uint32_t)mem&1 && count>=1) {
 		if (!gdbstub_read_byte(mem,ch))
 			return NULL;
-		buf = pack_hex_byte(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[0]);
 		mem++;
 		count--;
 	}
@@ -680,8 +680,8 @@
 	if ((uint32_t)mem&3 && count>=2) {
 		if (!gdbstub_read_word(mem,(uint16_t *)ch))
 			return NULL;
-		buf = pack_hex_byte(buf, ch[0]);
-		buf = pack_hex_byte(buf, ch[1]);
+		buf = hex_byte_pack(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[1]);
 		mem += 2;
 		count -= 2;
 	}
@@ -689,10 +689,10 @@
 	while (count>=4) {
 		if (!gdbstub_read_dword(mem,(uint32_t *)ch))
 			return NULL;
-		buf = pack_hex_byte(buf, ch[0]);
-		buf = pack_hex_byte(buf, ch[1]);
-		buf = pack_hex_byte(buf, ch[2]);
-		buf = pack_hex_byte(buf, ch[3]);
+		buf = hex_byte_pack(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[1]);
+		buf = hex_byte_pack(buf, ch[2]);
+		buf = hex_byte_pack(buf, ch[3]);
 		mem += 4;
 		count -= 4;
 	}
@@ -700,8 +700,8 @@
 	if (count>=2) {
 		if (!gdbstub_read_word(mem,(uint16_t *)ch))
 			return NULL;
-		buf = pack_hex_byte(buf, ch[0]);
-		buf = pack_hex_byte(buf, ch[1]);
+		buf = hex_byte_pack(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[1]);
 		mem += 2;
 		count -= 2;
 	}
@@ -709,7 +709,7 @@
 	if (count>=1) {
 		if (!gdbstub_read_byte(mem,ch))
 			return NULL;
-		buf = pack_hex_byte(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[0]);
 	}
 
 	*buf = 0;
@@ -1498,21 +1498,21 @@
 		ptr = mem2hex(title, ptr, sizeof(title) - 1,0);
 
 		hx = hex_asc_hi(brr >> 24);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(brr >> 24);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_hi(brr >> 16);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(brr >> 16);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_hi(brr >> 8);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(brr >> 8);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_hi(brr);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(brr);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 
 		ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
 		*ptr = 0;
@@ -1526,10 +1526,10 @@
 
 	/* Send trap type (converted to signal) */
 	*ptr++ = 'T';
-	ptr = pack_hex_byte(ptr, sigval);
+	ptr = hex_byte_pack(ptr, sigval);
 
 	/* Send Error PC */
-	ptr = pack_hex_byte(ptr, GDB_REG_PC);
+	ptr = hex_byte_pack(ptr, GDB_REG_PC);
 	*ptr++ = ':';
 	ptr = mem2hex(&__debug_frame->pc, ptr, 4, 0);
 	*ptr++ = ';';
@@ -1537,7 +1537,7 @@
 	/*
 	 * Send frame pointer
 	 */
-	ptr = pack_hex_byte(ptr, GDB_REG_FP);
+	ptr = hex_byte_pack(ptr, GDB_REG_FP);
 	*ptr++ = ':';
 	ptr = mem2hex(&__debug_frame->fp, ptr, 4, 0);
 	*ptr++ = ';';
@@ -1545,7 +1545,7 @@
 	/*
 	 * Send stack pointer
 	 */
-	ptr = pack_hex_byte(ptr, GDB_REG_SP);
+	ptr = hex_byte_pack(ptr, GDB_REG_SP);
 	*ptr++ = ':';
 	ptr = mem2hex(&__debug_frame->sp, ptr, 4, 0);
 	*ptr++ = ';';
diff -druN linux-libre-3.1-gnu/arch/h8300/include/asm/gpio.h linux-libre-3.2-gnu/arch/h8300/include/asm/gpio.h
--- linux-libre-3.1-gnu/arch/h8300/include/asm/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/h8300/include/asm/gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-#ifndef _H8300_GPIO_H
-#define _H8300_GPIO_H
-
-#define H8300_GPIO_P1 0
-#define H8300_GPIO_P2 1
-#define H8300_GPIO_P3 2
-#define H8300_GPIO_P4 3
-#define H8300_GPIO_P5 4
-#define H8300_GPIO_P6 5
-#define H8300_GPIO_P7 6
-#define H8300_GPIO_P8 7
-#define H8300_GPIO_P9 8
-#define H8300_GPIO_PA 9
-#define H8300_GPIO_PB 10
-#define H8300_GPIO_PC 11
-#define H8300_GPIO_PD 12
-#define H8300_GPIO_PE 13
-#define H8300_GPIO_PF 14
-#define H8300_GPIO_PG 15
-#define H8300_GPIO_PH 16
-
-#define H8300_GPIO_B7 0x80
-#define H8300_GPIO_B6 0x40
-#define H8300_GPIO_B5 0x20
-#define H8300_GPIO_B4 0x10
-#define H8300_GPIO_B3 0x08
-#define H8300_GPIO_B2 0x04
-#define H8300_GPIO_B1 0x02
-#define H8300_GPIO_B0 0x01
-
-#define H8300_GPIO_INPUT 0
-#define H8300_GPIO_OUTPUT 1
-
-#define H8300_GPIO_RESERVE(port, bits) \
-        h8300_reserved_gpio(port, bits)
-
-#define H8300_GPIO_FREE(port, bits) \
-        h8300_free_gpio(port, bits)
-
-#define H8300_GPIO_DDR(port, bit, dir) \
-        h8300_set_gpio_dir(((port) << 8) | (bit), dir)
-
-#define H8300_GPIO_GETDIR(port, bit) \
-        h8300_get_gpio_dir(((port) << 8) | (bit))
-
-extern int h8300_reserved_gpio(int port, int bits);
-extern int h8300_free_gpio(int port, int bits);
-extern int h8300_set_gpio_dir(int port_bit, int dir);
-extern int h8300_get_gpio_dir(int port_bit);
-extern int h8300_init_gpio(void);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/h8300/include/asm/gpio-internal.h linux-libre-3.2-gnu/arch/h8300/include/asm/gpio-internal.h
--- linux-libre-3.1-gnu/arch/h8300/include/asm/gpio-internal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/h8300/include/asm/gpio-internal.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,52 @@
+#ifndef _H8300_GPIO_H
+#define _H8300_GPIO_H
+
+#define H8300_GPIO_P1 0
+#define H8300_GPIO_P2 1
+#define H8300_GPIO_P3 2
+#define H8300_GPIO_P4 3
+#define H8300_GPIO_P5 4
+#define H8300_GPIO_P6 5
+#define H8300_GPIO_P7 6
+#define H8300_GPIO_P8 7
+#define H8300_GPIO_P9 8
+#define H8300_GPIO_PA 9
+#define H8300_GPIO_PB 10
+#define H8300_GPIO_PC 11
+#define H8300_GPIO_PD 12
+#define H8300_GPIO_PE 13
+#define H8300_GPIO_PF 14
+#define H8300_GPIO_PG 15
+#define H8300_GPIO_PH 16
+
+#define H8300_GPIO_B7 0x80
+#define H8300_GPIO_B6 0x40
+#define H8300_GPIO_B5 0x20
+#define H8300_GPIO_B4 0x10
+#define H8300_GPIO_B3 0x08
+#define H8300_GPIO_B2 0x04
+#define H8300_GPIO_B1 0x02
+#define H8300_GPIO_B0 0x01
+
+#define H8300_GPIO_INPUT 0
+#define H8300_GPIO_OUTPUT 1
+
+#define H8300_GPIO_RESERVE(port, bits) \
+        h8300_reserved_gpio(port, bits)
+
+#define H8300_GPIO_FREE(port, bits) \
+        h8300_free_gpio(port, bits)
+
+#define H8300_GPIO_DDR(port, bit, dir) \
+        h8300_set_gpio_dir(((port) << 8) | (bit), dir)
+
+#define H8300_GPIO_GETDIR(port, bit) \
+        h8300_get_gpio_dir(((port) << 8) | (bit))
+
+extern int h8300_reserved_gpio(int port, int bits);
+extern int h8300_free_gpio(int port, int bits);
+extern int h8300_set_gpio_dir(int port_bit, int dir);
+extern int h8300_get_gpio_dir(int port_bit);
+extern int h8300_init_gpio(void);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/h8300/Kconfig linux-libre-3.2-gnu/arch/h8300/Kconfig
--- linux-libre-3.1-gnu/arch/h8300/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/h8300/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -160,7 +160,7 @@
 
 config HW_CONSOLE
 	bool
-	depends on VT && !S390 && !UM
+	depends on VT
 	default y
 
 comment "Unix98 PTY support"
@@ -195,7 +195,7 @@
 
 source "drivers/char/pcmcia/Kconfig"
 
-source "drivers/serial/Kconfig"
+source "drivers/tty/serial/Kconfig"
 
 source "drivers/i2c/Kconfig"
 
diff -druN linux-libre-3.1-gnu/arch/h8300/platform/h8300h/irq.c linux-libre-3.2-gnu/arch/h8300/platform/h8300h/irq.c
--- linux-libre-3.1-gnu/arch/h8300/platform/h8300h/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/h8300/platform/h8300h/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
 #include <asm/traps.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/gpio.h>
+#include <asm/gpio-internal.h>
 #include <asm/regs306x.h>
 
 const int __initdata h8300_saved_vectors[] = {
diff -druN linux-libre-3.1-gnu/arch/h8300/platform/h8s/irq.c linux-libre-3.2-gnu/arch/h8300/platform/h8s/irq.c
--- linux-libre-3.1-gnu/arch/h8300/platform/h8s/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/h8300/platform/h8s/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 #include <asm/traps.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/gpio.h>
+#include <asm/gpio-internal.h>
 #include <asm/regs267x.h>
 
 /* saved vector list */
diff -druN linux-libre-3.1-gnu/arch/hexagon/configs/comet_defconfig linux-libre-3.2-gnu/arch/hexagon/configs/comet_defconfig
--- linux-libre-3.1-gnu/arch/hexagon/configs/comet_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/configs/comet_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,85 @@
+CONFIG_SMP=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_HZ_100=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_CROSS_COMPILE="hexagon-"
+CONFIG_LOCALVERSION="-smp"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_NBD=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_PHYLIB=y
+CONFIG_NET_ETHERNET=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_CONSOLE_TRANSLATIONS is not set
+CONFIG_LEGACY_PTY_COUNT=64
+# CONFIG_DEVKMEM is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_SPI=y
+CONFIG_SPI_DEBUG=y
+CONFIG_SPI_BITBANG=y
+# CONFIG_HWMON is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+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_QUOTA=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+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_CRYPTO_MD5=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_LIBCRC32C=y
+CONFIG_FRAME_WARN=0
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_INFO=y
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/asm-offsets.h linux-libre-3.2-gnu/arch/hexagon/include/asm/asm-offsets.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/asm-offsets.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/asm-offsets.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/atomic.h linux-libre-3.2-gnu/arch/hexagon/include/asm/atomic.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/atomic.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/atomic.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,164 @@
+/*
+ * Atomic operations for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_ATOMIC_H
+#define _ASM_ATOMIC_H
+
+#include <linux/types.h>
+
+#define ATOMIC_INIT(i)		{ (i) }
+#define atomic_set(v, i)	((v)->counter = (i))
+
+/**
+ * atomic_read - reads a word, atomically
+ * @v: pointer to atomic value
+ *
+ * Assumes all word reads on our architecture are atomic.
+ */
+#define atomic_read(v)		((v)->counter)
+
+/**
+ * atomic_xchg - atomic
+ * @v: pointer to memory to change
+ * @new: new value (technically passed in a register -- see xchg)
+ */
+#define atomic_xchg(v, new)	(xchg(&((v)->counter), (new)))
+
+
+/**
+ * atomic_cmpxchg - atomic compare-and-exchange values
+ * @v: pointer to value to change
+ * @old:  desired old value to match
+ * @new:  new value to put in
+ *
+ * Parameters are then pointer, value-in-register, value-in-register,
+ * and the output is the old value.
+ *
+ * Apparently this is complicated for archs that don't support
+ * the memw_locked like we do (or it's broken or whatever).
+ *
+ * Kind of the lynchpin of the rest of the generically defined routines.
+ * Remember V2 had that bug with dotnew predicate set by memw_locked.
+ *
+ * "old" is "expected" old val, __oldval is actual old value
+ */
+static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+	int __oldval;
+
+	asm volatile(
+		"1:	%0 = memw_locked(%1);\n"
+		"	{ P0 = cmp.eq(%0,%2);\n"
+		"	  if (!P0.new) jump:nt 2f; }\n"
+		"	memw_locked(%1,P0) = %3;\n"
+		"	if (!P0) jump 1b;\n"
+		"2:\n"
+		: "=&r" (__oldval)
+		: "r" (&v->counter), "r" (old), "r" (new)
+		: "memory", "p0"
+	);
+
+	return __oldval;
+}
+
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+	int output;
+
+	__asm__ __volatile__ (
+		"1:	%0 = memw_locked(%1);\n"
+		"	%0 = add(%0,%2);\n"
+		"	memw_locked(%1,P3)=%0;\n"
+		"	if !P3 jump 1b;\n"
+		: "=&r" (output)
+		: "r" (&v->counter), "r" (i)
+		: "memory", "p3"
+	);
+	return output;
+
+}
+
+#define atomic_add(i, v) atomic_add_return(i, (v))
+
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+	int output;
+	__asm__ __volatile__ (
+		"1:	%0 = memw_locked(%1);\n"
+		"	%0 = sub(%0,%2);\n"
+		"	memw_locked(%1,P3)=%0\n"
+		"	if !P3 jump 1b;\n"
+		: "=&r" (output)
+		: "r" (&v->counter), "r" (i)
+		: "memory", "p3"
+	);
+	return output;
+}
+
+#define atomic_sub(i, v) atomic_sub_return(i, (v))
+
+/**
+ * atomic_add_unless - add unless the number is a given value
+ * @v: pointer to value
+ * @a: amount to add
+ * @u: unless value is equal to u
+ *
+ * Returns 1 if the add happened, 0 if it didn't.
+ */
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
+{
+	int output, __oldval;
+	asm volatile(
+		"1:	%0 = memw_locked(%2);"
+		"	{"
+		"		p3 = cmp.eq(%0, %4);"
+		"		if (p3.new) jump:nt 2f;"
+		"		%0 = add(%0, %3);"
+		"		%1 = #0;"
+		"	}"
+		"	memw_locked(%2, p3) = %0;"
+		"	{"
+		"		if !p3 jump 1b;"
+		"		%1 = #1;"
+		"	}"
+		"2:"
+		: "=&r" (__oldval), "=&r" (output)
+		: "r" (v), "r" (a), "r" (u)
+		: "memory", "p3"
+	);
+	return output;
+}
+
+#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
+#define atomic_inc(v) atomic_add(1, (v))
+#define atomic_dec(v) atomic_sub(1, (v))
+
+#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0)
+#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+#define atomic_sub_and_test(i, v) (atomic_sub_return(i, (v)) == 0)
+#define atomic_add_negative(i, v) (atomic_add_return(i, (v)) < 0)
+
+
+#define atomic_inc_return(v) (atomic_add_return(1, v))
+#define atomic_dec_return(v) (atomic_sub_return(1, v))
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/bitops.h linux-libre-3.2-gnu/arch/hexagon/include/asm/bitops.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/bitops.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/bitops.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,301 @@
+/*
+ * Bit operations for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_BITOPS_H
+#define _ASM_BITOPS_H
+
+#include <linux/compiler.h>
+#include <asm/byteorder.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+
+#ifdef __KERNEL__
+
+#define smp_mb__before_clear_bit()	barrier()
+#define smp_mb__after_clear_bit()	barrier()
+
+/*
+ * The offset calculations for these are based on BITS_PER_LONG == 32
+ * (i.e. I get to shift by #5-2 (32 bits per long, 4 bytes per access),
+ * mask by 0x0000001F)
+ *
+ * Typically, R10 is clobbered for address, R11 bit nr, and R12 is temp
+ */
+
+/**
+ * test_and_clear_bit - clear a bit and return its old value
+ * @nr:  bit number to clear
+ * @addr:  pointer to memory
+ */
+static inline int test_and_clear_bit(int nr, volatile void *addr)
+{
+	int oldval;
+
+	__asm__ __volatile__ (
+	"	{R10 = %1; R11 = asr(%2,#5); }\n"
+	"	{R10 += asl(R11,#2); R11 = and(%2,#0x1f)}\n"
+	"1:	R12 = memw_locked(R10);\n"
+	"	{ P0 = tstbit(R12,R11); R12 = clrbit(R12,R11); }\n"
+	"	memw_locked(R10,P1) = R12;\n"
+	"	{if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+	: "=&r" (oldval)
+	: "r" (addr), "r" (nr)
+	: "r10", "r11", "r12", "p0", "p1", "memory"
+	);
+
+	return oldval;
+}
+
+/**
+ * test_and_set_bit - set a bit and return its old value
+ * @nr:  bit number to set
+ * @addr:  pointer to memory
+ */
+static inline int test_and_set_bit(int nr, volatile void *addr)
+{
+	int oldval;
+
+	__asm__ __volatile__ (
+	"	{R10 = %1; R11 = asr(%2,#5); }\n"
+	"	{R10 += asl(R11,#2); R11 = and(%2,#0x1f)}\n"
+	"1:	R12 = memw_locked(R10);\n"
+	"	{ P0 = tstbit(R12,R11); R12 = setbit(R12,R11); }\n"
+	"	memw_locked(R10,P1) = R12;\n"
+	"	{if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+	: "=&r" (oldval)
+	: "r" (addr), "r" (nr)
+	: "r10", "r11", "r12", "p0", "p1", "memory"
+	);
+
+
+	return oldval;
+
+}
+
+/**
+ * test_and_change_bit - toggle a bit and return its old value
+ * @nr:  bit number to set
+ * @addr:  pointer to memory
+ */
+static inline int test_and_change_bit(int nr, volatile void *addr)
+{
+	int oldval;
+
+	__asm__ __volatile__ (
+	"	{R10 = %1; R11 = asr(%2,#5); }\n"
+	"	{R10 += asl(R11,#2); R11 = and(%2,#0x1f)}\n"
+	"1:	R12 = memw_locked(R10);\n"
+	"	{ P0 = tstbit(R12,R11); R12 = togglebit(R12,R11); }\n"
+	"	memw_locked(R10,P1) = R12;\n"
+	"	{if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+	: "=&r" (oldval)
+	: "r" (addr), "r" (nr)
+	: "r10", "r11", "r12", "p0", "p1", "memory"
+	);
+
+	return oldval;
+
+}
+
+/*
+ * Atomic, but doesn't care about the return value.
+ * Rewrite later to save a cycle or two.
+ */
+
+static inline void clear_bit(int nr, volatile void *addr)
+{
+	test_and_clear_bit(nr, addr);
+}
+
+static inline void set_bit(int nr, volatile void *addr)
+{
+	test_and_set_bit(nr, addr);
+}
+
+static inline void change_bit(int nr, volatile void *addr)
+{
+	test_and_change_bit(nr, addr);
+}
+
+
+/*
+ * These are allowed to be non-atomic.  In fact the generic flavors are
+ * in non-atomic.h.  Would it be better to use intrinsics for this?
+ *
+ * OK, writes in our architecture do not invalidate LL/SC, so this has to
+ * be atomic, particularly for things like slab_lock and slab_unlock.
+ *
+ */
+static inline void __clear_bit(int nr, volatile unsigned long *addr)
+{
+	test_and_clear_bit(nr, addr);
+}
+
+static inline void __set_bit(int nr, volatile unsigned long *addr)
+{
+	test_and_set_bit(nr, addr);
+}
+
+static inline void __change_bit(int nr, volatile unsigned long *addr)
+{
+	test_and_change_bit(nr, addr);
+}
+
+/*  Apparently, at least some of these are allowed to be non-atomic  */
+static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
+{
+	return test_and_clear_bit(nr, addr);
+}
+
+static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
+{
+	return test_and_set_bit(nr, addr);
+}
+
+static inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
+{
+	return test_and_change_bit(nr, addr);
+}
+
+static inline int __test_bit(int nr, const volatile unsigned long *addr)
+{
+	int retval;
+
+	asm volatile(
+	"{P0 = tstbit(%1,%2); if (P0.new) %0 = #1; if (!P0.new) %0 = #0;}\n"
+	: "=&r" (retval)
+	: "r" (addr[BIT_WORD(nr)]), "r" (nr % BITS_PER_LONG)
+	: "p0"
+	);
+
+	return retval;
+}
+
+#define test_bit(nr, addr) __test_bit(nr, addr)
+
+/*
+ * ffz - find first zero in word.
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+static inline long ffz(int x)
+{
+	int r;
+
+	asm("%0 = ct1(%1);\n"
+		: "=&r" (r)
+		: "r" (x));
+	return r;
+}
+
+/*
+ * fls - find last (most-significant) bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as ffs.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
+ */
+static inline long fls(int x)
+{
+	int r;
+
+	asm("{ %0 = cl0(%1);}\n"
+		"%0 = sub(#32,%0);\n"
+		: "=&r" (r)
+		: "r" (x)
+		: "p0");
+
+	return r;
+}
+
+/*
+ * ffs - find first bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+static inline long ffs(int x)
+{
+	int r;
+
+	asm("{ P0 = cmp.eq(%1,#0); %0 = ct0(%1);}\n"
+		"{ if P0 %0 = #0; if !P0 %0 = add(%0,#1);}\n"
+		: "=&r" (r)
+		: "r" (x)
+		: "p0");
+
+	return r;
+}
+
+/*
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ *
+ * bits_per_long assumed to be 32
+ * numbering starts at 0 I think (instead of 1 like ffs)
+ */
+static inline unsigned long __ffs(unsigned long word)
+{
+	int num;
+
+	asm("%0 = ct0(%1);\n"
+		: "=&r" (num)
+		: "r" (word));
+
+	return num;
+}
+
+/*
+ * __fls - find last (most-significant) set bit in a long word
+ * @word: the word to search
+ *
+ * Undefined if no set bit exists, so code should check against 0 first.
+ * bits_per_long assumed to be 32
+ */
+static inline unsigned long __fls(unsigned long word)
+{
+	int num;
+
+	asm("%0 = cl0(%1);\n"
+		"%0 = sub(#31,%0);\n"
+		: "=&r" (num)
+		: "r" (word));
+
+	return num;
+}
+
+#include <asm-generic/bitops/lock.h>
+#include <asm-generic/bitops/find.h>
+
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
+
+#include <asm-generic/bitops/le.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+
+#endif /* __KERNEL__ */
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/bitsperlong.h linux-libre-3.2-gnu/arch/hexagon/include/asm/bitsperlong.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/bitsperlong.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#ifndef __ASM_HEXAGON_BITSPERLONG_H
+#define __ASM_HEXAGON_BITSPERLONG_H
+
+#define __BITS_PER_LONG 32
+
+#include <asm-generic/bitsperlong.h>
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/byteorder.h linux-libre-3.2-gnu/arch/hexagon/include/asm/byteorder.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/byteorder.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/byteorder.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_BYTEORDER_H
+#define _ASM_BYTEORDER_H
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#  define __BYTEORDER_HAS_U64__
+#endif
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _ASM_BYTEORDER_H */
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/cacheflush.h linux-libre-3.2-gnu/arch/hexagon/include/asm/cacheflush.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/cacheflush.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/cacheflush.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,99 @@
+/*
+ * Cache flush operations for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_CACHEFLUSH_H
+#define _ASM_CACHEFLUSH_H
+
+#include <linux/cache.h>
+#include <linux/mm.h>
+#include <asm/string.h>
+#include <asm-generic/cacheflush.h>
+
+/* Cache flushing:
+ *
+ *  - flush_cache_all() flushes entire cache
+ *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
+ *  - flush_cache_range(vma, start, end) flushes a range of pages
+ *  - flush_icache_range(start, end) flush a range of instructions
+ *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
+ *  - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
+ *
+ *  Need to doublecheck which one is really needed for ptrace stuff to work.
+ */
+#define LINESIZE	32
+#define LINEBITS	5
+
+/*
+ * Flush Dcache range through current map.
+ */
+extern void flush_dcache_range(unsigned long start, unsigned long end);
+
+/*
+ * Flush Icache range through current map.
+ */
+#undef flush_icache_range
+extern void flush_icache_range(unsigned long start, unsigned long end);
+
+/*
+ * Memory-management related flushes are there to ensure in non-physically
+ * indexed cache schemes that stale lines belonging to a given ASID aren't
+ * in the cache to confuse things.  The prototype Hexagon Virtual Machine
+ * only uses a single ASID for all user-mode maps, which should
+ * mean that they aren't necessary.  A brute-force, flush-everything
+ * implementation, with the name xxxxx_hexagon() is present in
+ * arch/hexagon/mm/cache.c, but let's not wire it up until we know
+ * it is needed.
+ */
+extern void flush_cache_all_hexagon(void);
+
+/*
+ * This may or may not ever have to be non-null, depending on the
+ * virtual machine MMU.  For a native kernel, it's definitiely  a no-op
+ *
+ * This is also the place where deferred cache coherency stuff seems
+ * to happen, classically...  but instead we do it like ia64 and
+ * clean the cache when the PTE is set.
+ *
+ */
+static inline void update_mmu_cache(struct vm_area_struct *vma,
+					unsigned long address, pte_t *ptep)
+{
+	/*  generic_ptrace_pokedata doesn't wind up here, does it?  */
+}
+
+#undef copy_to_user_page
+static inline void copy_to_user_page(struct vm_area_struct *vma,
+					     struct page *page,
+					     unsigned long vaddr,
+					     void *dst, void *src, int len)
+{
+	memcpy(dst, src, len);
+	if (vma->vm_flags & VM_EXEC) {
+		flush_icache_range((unsigned long) dst,
+		(unsigned long) dst + len);
+	}
+}
+
+
+extern void hexagon_inv_dcache_range(unsigned long start, unsigned long end);
+extern void hexagon_clean_dcache_range(unsigned long start, unsigned long end);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/cache.h linux-libre-3.2-gnu/arch/hexagon/include/asm/cache.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/cache.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/cache.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,34 @@
+/*
+ * Cache definitions for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef __ASM_CACHE_H
+#define __ASM_CACHE_H
+
+/* Bytes per L1 cache line */
+#define L1_CACHE_SHIFT		(5)
+#define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
+
+#define __cacheline_aligned	__aligned(L1_CACHE_BYTES)
+#define ____cacheline_aligned	__aligned(L1_CACHE_BYTES)
+
+/* See http://kerneltrap.org/node/15100  */
+#define __read_mostly
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/checksum.h linux-libre-3.2-gnu/arch/hexagon/include/asm/checksum.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/checksum.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/checksum.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_CHECKSUM_H
+#define _ASM_CHECKSUM_H
+
+#define do_csum	do_csum
+unsigned int do_csum(const void *voidptr, int len);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+#define csum_partial_copy_nocheck csum_partial_copy_nocheck
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+					int len, __wsum sum);
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+#define csum_tcpudp_nofold csum_tcpudp_nofold
+__wsum csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
+	unsigned short len, unsigned short proto, __wsum sum);
+
+#define csum_tcpudp_magic csum_tcpudp_magic
+__sum16 csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
+	unsigned short len, unsigned short proto, __wsum sum);
+
+#include <asm-generic/checksum.h>
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/delay.h linux-libre-3.2-gnu/arch/hexagon/include/asm/delay.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/delay.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/delay.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_DELAY_H
+#define _ASM_DELAY_H
+
+#include <asm/param.h>
+
+extern void __udelay(unsigned long usecs);
+
+#define udelay(usecs) __udelay((usecs))
+
+#endif /* _ASM_DELAY_H */
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/dma.h linux-libre-3.2-gnu/arch/hexagon/include/asm/dma.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/dma.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_DMA_H
+#define _ASM_DMA_H
+
+#include <asm/io.h>
+
+#define MAX_DMA_CHANNELS 1
+#define MAX_DMA_ADDRESS  (PAGE_OFFSET)
+
+extern size_t hexagon_coherent_pool_size;
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/dma-mapping.h linux-libre-3.2-gnu/arch/hexagon/include/asm/dma-mapping.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/dma-mapping.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/dma-mapping.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,101 @@
+/*
+ * DMA operations for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_DMA_MAPPING_H
+#define _ASM_DMA_MAPPING_H
+
+#include <linux/types.h>
+#include <linux/cache.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-debug.h>
+#include <linux/dma-attrs.h>
+#include <asm/io.h>
+
+struct device;
+extern int bad_dma_address;
+
+extern struct dma_map_ops *dma_ops;
+
+#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 struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+	if (unlikely(dev == NULL))
+		return NULL;
+
+	return dma_ops;
+}
+
+extern int dma_supported(struct device *dev, u64 mask);
+extern int dma_set_mask(struct device *dev, u64 mask);
+extern int dma_is_consistent(struct device *dev, dma_addr_t dma_handle);
+extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+			   enum dma_data_direction direction);
+
+#include <asm-generic/dma-mapping-common.h>
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+	if (!dev->dma_mask)
+		return 0;
+	return addr + size - 1 <= *dev->dma_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 (dma_addr == bad_dma_address);
+}
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+				       dma_addr_t *dma_handle, gfp_t flag)
+{
+	void *ret;
+	struct dma_map_ops *ops = get_dma_ops(dev);
+
+	BUG_ON(!dma_ops);
+
+	ret = ops->alloc_coherent(dev, size, dma_handle, flag);
+
+	debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
+
+	return ret;
+}
+
+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);
+
+	BUG_ON(!dma_ops);
+
+	dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
+
+	debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/elf.h linux-libre-3.2-gnu/arch/hexagon/include/asm/elf.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/elf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/elf.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,229 @@
+/*
+ * ELF definitions for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ELF_H
+#define __ASM_ELF_H
+
+#include <asm/ptrace.h>
+#include <asm/user.h>
+
+/*
+ * This should really be in linux/elf-em.h.
+ */
+#define EM_HEXAGON	164   /* QUALCOMM Hexagon */
+
+struct elf32_hdr;
+
+/*
+ * ELF header e_flags defines.
+ */
+
+/*  should have stuff like "CPU type" and maybe "ABI version", etc  */
+
+/* Hexagon relocations */
+  /* V2 */
+#define R_HEXAGON_NONE           0
+#define R_HEXAGON_B22_PCREL      1
+#define R_HEXAGON_B15_PCREL      2
+#define R_HEXAGON_B7_PCREL       3
+#define R_HEXAGON_LO16           4
+#define R_HEXAGON_HI16           5
+#define R_HEXAGON_32             6
+#define R_HEXAGON_16             7
+#define R_HEXAGON_8              8
+#define R_HEXAGON_GPREL16_0      9
+#define R_HEXAGON_GPREL16_1     10
+#define R_HEXAGON_GPREL16_2     11
+#define R_HEXAGON_GPREL16_3     12
+#define R_HEXAGON_HL16          13
+  /* V3 */
+#define R_HEXAGON_B13_PCREL     14
+  /* V4 */
+#define R_HEXAGON_B9_PCREL      15
+  /* V4 (extenders) */
+#define R_HEXAGON_B32_PCREL_X   16
+#define R_HEXAGON_32_6_X        17
+  /* V4 (extended) */
+#define R_HEXAGON_B22_PCREL_X   18
+#define R_HEXAGON_B15_PCREL_X   19
+#define R_HEXAGON_B13_PCREL_X   20
+#define R_HEXAGON_B9_PCREL_X    21
+#define R_HEXAGON_B7_PCREL_X    22
+#define R_HEXAGON_16_X          23
+#define R_HEXAGON_12_X          24
+#define R_HEXAGON_11_X          25
+#define R_HEXAGON_10_X          26
+#define R_HEXAGON_9_X           27
+#define R_HEXAGON_8_X           28
+#define R_HEXAGON_7_X           29
+#define R_HEXAGON_6_X           30
+  /* V2 PIC */
+#define R_HEXAGON_32_PCREL      31
+#define R_HEXAGON_COPY          32
+#define R_HEXAGON_GLOB_DAT      33
+#define R_HEXAGON_JMP_SLOT      34
+#define R_HEXAGON_RELATIVE      35
+#define R_HEXAGON_PLT_B22_PCREL 36
+#define R_HEXAGON_GOTOFF_LO16   37
+#define R_HEXAGON_GOTOFF_HI16   38
+#define R_HEXAGON_GOTOFF_32     39
+#define R_HEXAGON_GOT_LO16      40
+#define R_HEXAGON_GOT_HI16      41
+#define R_HEXAGON_GOT_32        42
+#define R_HEXAGON_GOT_16        43
+
+/*
+ * ELF register definitions..
+ */
+typedef unsigned long elf_greg_t;
+
+typedef struct user_regs_struct elf_gregset_t;
+#define ELF_NGREG (sizeof(elf_gregset_t)/sizeof(unsigned long))
+
+/*  Placeholder  */
+typedef unsigned long elf_fpregset_t;
+
+/*
+ * Bypass the whole "regsets" thing for now and use the define.
+ */
+
+#define ELF_CORE_COPY_REGS(DEST, REGS)	\
+do {					\
+	DEST.r0 = REGS->r00;		\
+	DEST.r1 = REGS->r01;		\
+	DEST.r2 = REGS->r02;		\
+	DEST.r3 = REGS->r03;		\
+	DEST.r4 = REGS->r04;		\
+	DEST.r5 = REGS->r05;		\
+	DEST.r6 = REGS->r06;		\
+	DEST.r7 = REGS->r07;		\
+	DEST.r8 = REGS->r08;		\
+	DEST.r9 = REGS->r09;		\
+	DEST.r10 = REGS->r10;		\
+	DEST.r11 = REGS->r11;		\
+	DEST.r12 = REGS->r12;		\
+	DEST.r13 = REGS->r13;		\
+	DEST.r14 = REGS->r14;		\
+	DEST.r15 = REGS->r15;		\
+	DEST.r16 = REGS->r16;		\
+	DEST.r17 = REGS->r17;		\
+	DEST.r18 = REGS->r18;		\
+	DEST.r19 = REGS->r19;		\
+	DEST.r20 = REGS->r20;		\
+	DEST.r21 = REGS->r21;		\
+	DEST.r22 = REGS->r22;		\
+	DEST.r23 = REGS->r23;		\
+	DEST.r24 = REGS->r24;		\
+	DEST.r25 = REGS->r25;		\
+	DEST.r26 = REGS->r26;		\
+	DEST.r27 = REGS->r27;		\
+	DEST.r28 = REGS->r28;		\
+	DEST.r29 = pt_psp(REGS);	\
+	DEST.r30 = REGS->r30;		\
+	DEST.r31 = REGS->r31;		\
+	DEST.sa0 = REGS->sa0;		\
+	DEST.lc0 = REGS->lc0;		\
+	DEST.sa1 = REGS->sa1;		\
+	DEST.lc1 = REGS->lc1;		\
+	DEST.m0 = REGS->m0;		\
+	DEST.m1 = REGS->m1;		\
+	DEST.usr = REGS->usr;		\
+	DEST.p3_0 = REGS->preds;	\
+	DEST.gp = REGS->gp;		\
+	DEST.ugp = REGS->ugp;		\
+	DEST.pc = pt_elr(REGS);	\
+	DEST.cause = pt_cause(REGS);	\
+	DEST.badva = pt_badva(REGS);	\
+} while (0);
+
+
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ * Checks the machine and ABI type.
+ */
+#define elf_check_arch(hdr)	((hdr)->e_machine == EM_HEXAGON)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA	ELFDATA2LSB
+#define ELF_ARCH	EM_HEXAGON
+
+#ifdef CONFIG_HEXAGON_ARCH_V2
+#define ELF_CORE_EFLAGS 0x1
+#endif
+
+#ifdef CONFIG_HEXAGON_ARCH_V3
+#define ELF_CORE_EFLAGS 0x2
+#endif
+
+#ifdef CONFIG_HEXAGON_ARCH_V4
+#define ELF_CORE_EFLAGS 0x3
+#endif
+
+/*
+ * Some architectures have ld.so set up a pointer to a function
+ * to be registered using atexit, to facilitate cleanup.  So that
+ * static executables will be well-behaved, we would null the register
+ * in question here, in the pt_regs structure passed.  For now,
+ * leave it a null macro.
+ */
+#define ELF_PLAT_INIT(regs, load_addr) do { } while (0)
+
+#define USE_ELF_CORE_DUMP
+#define CORE_DUMP_USE_REGSET
+
+/* Hrm is this going to cause problems for changing PAGE_SIZE?  */
+#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         0x08000000UL
+
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
+#define ELF_HWCAP	(0)
+
+/*
+ * This yields a string that ld.so will use to load implementation
+ * specific libraries for optimization.  This is more specific in
+ * intent than poking at uname or /proc/cpuinfo.
+ */
+#define ELF_PLATFORM  (NULL)
+
+#ifdef __KERNEL__
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#endif
+
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+				       int uses_interp);
+
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/fixmap.h linux-libre-3.2-gnu/arch/hexagon/include/asm/fixmap.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/fixmap.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/fixmap.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,73 @@
+/*
+ * Fixmap support for Hexagon - enough to support highmem features
+ *
+ * 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.
+ */
+
+#ifndef _ASM_FIXMAP_H
+#define _ASM_FIXMAP_H
+
+/*
+ * A lot of the fixmap info is already in mem-layout.h
+ */
+#include <asm/mem-layout.h>
+
+/*
+ * Full fixmap support involves set_fixmap() functions, but
+ * these may not be needed if all we're after is an area for
+ * highmem kernel mappings.
+ */
+#define	__fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
+#define	__virt_to_fix(x)	((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
+
+extern void __this_fixmap_does_not_exist(void);
+
+/**
+ * fix_to_virt -- "index to address" translation.
+ *
+ * If anyone tries to use the idx directly without translation,
+ * we catch the bug with a NULL-deference kernel oops. Illegal
+ * ranges of incoming indices are caught too.
+ */
+static inline unsigned long fix_to_virt(const unsigned int idx)
+{
+	/*
+	 * This branch gets completely eliminated after inlining,
+	 * except when someone tries to use fixaddr indices in an
+	 * illegal way. (such as mixing up address types or using
+	 * out-of-range indices).
+	 *
+	 * If it doesn't get removed, the linker will complain
+	 * loudly with a reasonably clear error message..
+	 */
+	if (idx >= __end_of_fixed_addresses)
+		__this_fixmap_does_not_exist();
+
+	return __fix_to_virt(idx);
+}
+
+static inline unsigned long virt_to_fix(const unsigned long vaddr)
+{
+	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
+	return __virt_to_fix(vaddr);
+}
+
+#define kmap_get_fixmap_pte(vaddr) \
+	pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), \
+				(vaddr)), (vaddr)), (vaddr))
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/fpu.h linux-libre-3.2-gnu/arch/hexagon/include/asm/fpu.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/fpu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/fpu.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,4 @@
+/*
+ * If the FPU is used inside the kernel,
+ * kernel_fpu_end() will be defined here.
+ */
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/futex.h linux-libre-3.2-gnu/arch/hexagon/include/asm/futex.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/futex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/futex.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,137 @@
+#ifndef _ASM_HEXAGON_FUTEX_H
+#define _ASM_HEXAGON_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <linux/uaccess.h>
+#include <asm/errno.h>
+
+/* XXX TODO-- need to add sync barriers! */
+
+#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
+	__asm__ __volatile( \
+	"1: %0 = memw_locked(%3);\n" \
+	    /* For example: %1 = %4 */ \
+	    insn \
+	"2: memw_locked(%3,p2) = %1;\n" \
+	"   if !p2 jump 1b;\n" \
+	"   %1 = #0;\n" \
+	"3:\n" \
+	".section .fixup,\"ax\"\n" \
+	"4: %1 = #%5;\n" \
+	"   jump 3b\n" \
+	".previous\n" \
+	".section __ex_table,\"a\"\n" \
+	".long 1b,4b,2b,4b\n" \
+	".previous\n" \
+	: "=&r" (oldval), "=&r" (ret), "+m" (*uaddr) \
+	: "r" (uaddr), "r" (oparg), "i" (-EFAULT) \
+	: "p2", "memory")
+
+
+static inline int
+futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+{
+	int op = (encoded_op >> 28) & 7;
+	int cmp = (encoded_op >> 24) & 15;
+	int oparg = (encoded_op << 8) >> 20;
+	int cmparg = (encoded_op << 20) >> 20;
+	int oldval = 0, ret;
+	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+		oparg = 1 << oparg;
+
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+		return -EFAULT;
+
+	pagefault_disable();
+
+	switch (op) {
+	case FUTEX_OP_SET:
+		__futex_atomic_op("%1 = %4\n", ret, oldval, uaddr, oparg);
+		break;
+	case FUTEX_OP_ADD:
+		__futex_atomic_op("%1 = add(%0,%4)\n", ret, oldval, uaddr,
+				  oparg);
+		break;
+	case FUTEX_OP_OR:
+		__futex_atomic_op("%1 = or(%0,%4)\n", ret, oldval, uaddr,
+				  oparg);
+		break;
+	case FUTEX_OP_ANDN:
+		__futex_atomic_op("%1 = not(%4); %1 = and(%0,%1)\n", ret,
+				  oldval, uaddr, oparg);
+		break;
+	case FUTEX_OP_XOR:
+		__futex_atomic_op("%1 = xor(%0,%4)\n", ret, oldval, uaddr,
+				  oparg);
+		break;
+	default:
+		ret = -ENOSYS;
+	}
+
+	pagefault_enable();
+
+	if (!ret) {
+		switch (cmp) {
+		case FUTEX_OP_CMP_EQ:
+			ret = (oldval == cmparg);
+			break;
+		case FUTEX_OP_CMP_NE:
+			ret = (oldval != cmparg);
+			break;
+		case FUTEX_OP_CMP_LT:
+			ret = (oldval < cmparg);
+			break;
+		case FUTEX_OP_CMP_GE:
+			ret = (oldval >= cmparg);
+			break;
+		case FUTEX_OP_CMP_LE:
+			ret = (oldval <= cmparg);
+			break;
+		case FUTEX_OP_CMP_GT:
+			ret = (oldval > cmparg);
+			break;
+		default:
+			ret = -ENOSYS;
+		}
+	}
+	return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval,
+			      u32 newval)
+{
+	int prev;
+	int ret;
+
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+		return -EFAULT;
+
+	__asm__ __volatile__ (
+	"1: %1 = memw_locked(%3)\n"
+	"   {\n"
+	"      p2 = cmp.eq(%1,%4)\n"
+	"      if !p2.new jump:NT 3f\n"
+	"   }\n"
+	"2: memw_locked(%3,p2) = %5\n"
+	"   if !p2 jump 1b\n"
+	"3:\n"
+	".section .fixup,\"ax\"\n"
+	"4: %0 = #%6\n"
+	"   jump 3b\n"
+	".previous\n"
+	".section __ex_table,\"a\"\n"
+	".long 1b,4b,2b,4b\n"
+	".previous\n"
+	: "+r" (ret), "=&r" (prev), "+m" (*uaddr)
+	: "r" (uaddr), "r" (oldval), "r" (newval), "i"(-EFAULT)
+	: "p2", "memory");
+
+	*uval = prev;
+	return ret;
+}
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_HEXAGON_FUTEX_H */
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/hexagon_vm.h linux-libre-3.2-gnu/arch/hexagon/include/asm/hexagon_vm.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/hexagon_vm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/hexagon_vm.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,281 @@
+/*
+ * Declarations for to Hexagon Virtal Machine.
+ *
+ * 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.
+ */
+
+#ifndef ASM_HEXAGON_VM_H
+#define ASM_HEXAGON_VM_H
+
+/*
+ * In principle, a Linux kernel for the VM could
+ * selectively define the virtual instructions
+ * as inline assembler macros, but for a first pass,
+ * we'll use subroutines for both the VM and the native
+ * kernels.  It's costing a subroutine call/return,
+ * but it makes for a single set of entry points
+ * for tracing/debugging.
+ */
+
+/*
+ * Lets make this stuff visible only if configured,
+ * so we can unconditionally include the file.
+ */
+
+#ifndef __ASSEMBLY__
+
+enum VM_CACHE_OPS {
+	ickill,
+	dckill,
+	l2kill,
+	dccleaninva,
+	icinva,
+	idsync,
+	fetch_cfg
+};
+
+enum VM_INT_OPS {
+	nop,
+	globen,
+	globdis,
+	locen,
+	locdis,
+	affinity,
+	get,
+	peek,
+	status,
+	post,
+	clear
+};
+
+extern void _K_VM_event_vector(void);
+
+void __vmrte(void);
+long __vmsetvec(void *);
+long __vmsetie(long);
+long __vmgetie(void);
+long __vmintop(enum VM_INT_OPS, long, long, long, long);
+long __vmclrmap(void *, unsigned long);
+long __vmnewmap(void *);
+long __vmcache(enum VM_CACHE_OPS op, unsigned long addr, unsigned long len);
+unsigned long long __vmgettime(void);
+long __vmsettime(unsigned long long);
+long __vmstart(void *, void *);
+void __vmstop(void);
+long __vmwait(void);
+void __vmyield(void);
+long __vmvpid(void);
+
+static inline long __vmcache_ickill(void)
+{
+	return __vmcache(ickill, 0, 0);
+}
+
+static inline long __vmcache_dckill(void)
+{
+	return __vmcache(dckill, 0, 0);
+}
+
+static inline long __vmcache_l2kill(void)
+{
+	return __vmcache(l2kill, 0, 0);
+}
+
+static inline long __vmcache_dccleaninva(unsigned long addr, unsigned long len)
+{
+	return __vmcache(dccleaninva, addr, len);
+}
+
+static inline long __vmcache_icinva(unsigned long addr, unsigned long len)
+{
+	return __vmcache(icinva, addr, len);
+}
+
+static inline long __vmcache_idsync(unsigned long addr,
+					   unsigned long len)
+{
+	return __vmcache(idsync, addr, len);
+}
+
+static inline long __vmcache_fetch_cfg(unsigned long val)
+{
+	return __vmcache(fetch_cfg, val, 0);
+}
+
+/* interrupt operations  */
+
+static inline long __vmintop_nop(void)
+{
+	return __vmintop(nop, 0, 0, 0, 0);
+}
+
+static inline long __vmintop_globen(long i)
+{
+	return __vmintop(globen, i, 0, 0, 0);
+}
+
+static inline long __vmintop_globdis(long i)
+{
+	return __vmintop(globdis, i, 0, 0, 0);
+}
+
+static inline long __vmintop_locen(long i)
+{
+	return __vmintop(locen, i, 0, 0, 0);
+}
+
+static inline long __vmintop_locdis(long i)
+{
+	return __vmintop(locdis, i, 0, 0, 0);
+}
+
+static inline long __vmintop_affinity(long i, long cpu)
+{
+	return __vmintop(locdis, i, cpu, 0, 0);
+}
+
+static inline long __vmintop_get(void)
+{
+	return __vmintop(get, 0, 0, 0, 0);
+}
+
+static inline long __vmintop_peek(void)
+{
+	return __vmintop(peek, 0, 0, 0, 0);
+}
+
+static inline long __vmintop_status(long i)
+{
+	return __vmintop(status, i, 0, 0, 0);
+}
+
+static inline long __vmintop_post(long i)
+{
+	return __vmintop(post, i, 0, 0, 0);
+}
+
+static inline long __vmintop_clear(long i)
+{
+	return __vmintop(clear, i, 0, 0, 0);
+}
+
+#else /* Only assembly code should reference these */
+
+#define HVM_TRAP1_VMRTE			1
+#define HVM_TRAP1_VMSETVEC		2
+#define HVM_TRAP1_VMSETIE		3
+#define HVM_TRAP1_VMGETIE		4
+#define HVM_TRAP1_VMINTOP		5
+#define HVM_TRAP1_VMCLRMAP		10
+#define HVM_TRAP1_VMNEWMAP		11
+#define HVM_TRAP1_FORMERLY_VMWIRE	12
+#define HVM_TRAP1_VMCACHE		13
+#define HVM_TRAP1_VMGETTIME		14
+#define HVM_TRAP1_VMSETTIME		15
+#define HVM_TRAP1_VMWAIT		16
+#define HVM_TRAP1_VMYIELD		17
+#define HVM_TRAP1_VMSTART		18
+#define HVM_TRAP1_VMSTOP		19
+#define HVM_TRAP1_VMVPID		20
+#define HVM_TRAP1_VMSETREGS		21
+#define HVM_TRAP1_VMGETREGS		22
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * Constants for virtual instruction parameters and return values
+ */
+
+/* vmsetie arguments */
+
+#define VM_INT_DISABLE	0
+#define VM_INT_ENABLE	1
+
+/* vmsetimask arguments */
+
+#define VM_INT_UNMASK	0
+#define VM_INT_MASK	1
+
+#define VM_NEWMAP_TYPE_LINEAR	0
+#define VM_NEWMAP_TYPE_PGTABLES	1
+
+
+/*
+ * Event Record definitions useful to both C and Assembler
+ */
+
+/* VMEST Layout */
+
+#define HVM_VMEST_UM_SFT	31
+#define HVM_VMEST_UM_MSK	1
+#define HVM_VMEST_IE_SFT	30
+#define HVM_VMEST_IE_MSK	1
+#define HVM_VMEST_EVENTNUM_SFT	16
+#define HVM_VMEST_EVENTNUM_MSK	0xff
+#define HVM_VMEST_CAUSE_SFT	0
+#define HVM_VMEST_CAUSE_MSK	0xffff
+
+/*
+ * The initial program gets to find a system environment descriptor
+ * on its stack when it begins exection. The first word is a version
+ * code to indicate what is there.  Zero means nothing more.
+ */
+
+#define HEXAGON_VM_SED_NULL	0
+
+/*
+ * Event numbers for vector binding
+ */
+
+#define HVM_EV_RESET		0
+#define HVM_EV_MACHCHECK	1
+#define HVM_EV_GENEX		2
+#define HVM_EV_TRAP		8
+#define HVM_EV_INTR		15
+/* These shoud be nuked as soon as we know the VM is up to spec v0.1.1 */
+#define HVM_EV_INTR_0		16
+#define HVM_MAX_INTR		240
+
+/*
+ * Cause values for General Exception
+ */
+
+#define HVM_GE_C_BUS	0x01
+#define HVM_GE_C_XPROT	0x11
+#define HVM_GE_C_XUSER	0x14
+#define HVM_GE_C_INVI	0x15
+#define HVM_GE_C_PRIVI	0x1B
+#define HVM_GE_C_XMAL	0x1C
+#define HVM_GE_C_RMAL	0x20
+#define HVM_GE_C_WMAL	0x21
+#define HVM_GE_C_RPROT	0x22
+#define HVM_GE_C_WPROT	0x23
+#define HVM_GE_C_RUSER	0x24
+#define HVM_GE_C_WUSER	0x25
+#define HVM_GE_C_CACHE	0x28
+
+/*
+ * Cause codes for Machine Check
+ */
+
+#define	HVM_MCHK_C_DOWN		0x00
+#define	HVM_MCHK_C_BADSP	0x01
+#define	HVM_MCHK_C_BADEX	0x02
+#define	HVM_MCHK_C_BADPT	0x03
+#define	HVM_MCHK_C_REGWR	0x29
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/intrinsics.h linux-libre-3.2-gnu/arch/hexagon/include/asm/intrinsics.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/intrinsics.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/intrinsics.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_HEXAGON_INTRINSICS_H
+#define _ASM_HEXAGON_INTRINSICS_H
+
+#define HEXAGON_P_vrmpyhacc_PP	__builtin_HEXAGON_M2_vrmac_s0
+#define HEXAGON_P_vrmpyh_PP	__builtin_HEXAGON_M2_vrmpy_s0
+#define HEXAGON_R_cl0_R		__builtin_HEXAGON_S2_cl0
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/io.h linux-libre-3.2-gnu/arch/hexagon/include/asm/io.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/io.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,326 @@
+/*
+ * IO definitions for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <asm/string.h>
+#include <asm/mem-layout.h>
+#include <asm/iomap.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+/*
+ * We don't have PCI yet.
+ * _IO_BASE is pointing at what should be unused virtual space.
+ */
+#define IO_SPACE_LIMIT 0xffff
+#define _IO_BASE ((void __iomem *)0xfe000000)
+
+extern int remap_area_pages(unsigned long start, unsigned long phys_addr,
+				unsigned long end, unsigned long flags);
+
+extern void __iounmap(const volatile void __iomem *addr);
+
+/* Defined in lib/io.c, needed for smc91x driver. */
+extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
+extern void __raw_writesw(void __iomem *addr, const void *data, int wordlen);
+
+extern void __raw_readsl(const void __iomem *addr, void *data, int wordlen);
+extern void __raw_writesl(void __iomem *addr, const void *data, int wordlen);
+
+#define readsw(p, d, l)	__raw_readsw(p, d, l)
+#define writesw(p, d, l) __raw_writesw(p, d, l)
+
+#define readsl(p, d, l)   __raw_readsl(p, d, l)
+#define writesl(p, d, l)  __raw_writesl(p, d, l)
+
+/*
+ * virt_to_phys - map virtual address to physical
+ * @address:  address to map
+ */
+static inline unsigned long virt_to_phys(volatile void *address)
+{
+	return __pa(address);
+}
+
+/*
+ * phys_to_virt - map physical address to virtual
+ * @address: address to map
+ */
+static inline void *phys_to_virt(unsigned long address)
+{
+	return __va(address);
+}
+
+/*
+ * convert a physical pointer to a virtual kernel pointer for
+ * /dev/mem access.
+ */
+#define xlate_dev_kmem_ptr(p)    __va(p)
+#define xlate_dev_mem_ptr(p)    __va(p)
+
+/*
+ * IO port access primitives.  Hexagon doesn't have special IO access
+ * instructions; all I/O is memory mapped.
+ *
+ * in/out are used for "ports", but we don't have "port instructions",
+ * so these are really just memory mapped too.
+ */
+
+/*
+ * readb - read byte from memory mapped device
+ * @addr:  pointer to memory
+ *
+ * Operates on "I/O bus memory space"
+ */
+static inline u8 readb(const volatile void __iomem *addr)
+{
+	u8 val;
+	asm volatile(
+		"%0 = memb(%1);"
+		: "=&r" (val)
+		: "r" (addr)
+	);
+	return val;
+}
+
+static inline u16 readw(const volatile void __iomem *addr)
+{
+	u16 val;
+	asm volatile(
+		"%0 = memh(%1);"
+		: "=&r" (val)
+		: "r" (addr)
+	);
+	return val;
+}
+
+static inline u32 readl(const volatile void __iomem *addr)
+{
+	u32 val;
+	asm volatile(
+		"%0 = memw(%1);"
+		: "=&r" (val)
+		: "r" (addr)
+	);
+	return val;
+}
+
+/*
+ * writeb - write a byte to a memory location
+ * @data: data to write to
+ * @addr:  pointer to memory
+ *
+ */
+static inline void writeb(u8 data, volatile void __iomem *addr)
+{
+	asm volatile(
+		"memb(%0) = %1;"
+		:
+		: "r" (addr), "r" (data)
+		: "memory"
+	);
+}
+
+static inline void writew(u16 data, volatile void __iomem *addr)
+{
+	asm volatile(
+		"memh(%0) = %1;"
+		:
+		: "r" (addr), "r" (data)
+		: "memory"
+	);
+
+}
+
+static inline void writel(u32 data, volatile void __iomem *addr)
+{
+	asm volatile(
+		"memw(%0) = %1;"
+		:
+		: "r" (addr), "r" (data)
+		: "memory"
+	);
+}
+
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
+
+/*
+ * Need an mtype somewhere in here, for cache type deals?
+ * This is probably too long for an inline.
+ */
+void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size);
+
+static inline void __iomem *ioremap(unsigned long phys_addr, unsigned long size)
+{
+	return ioremap_nocache(phys_addr, size);
+}
+
+static inline void iounmap(volatile void __iomem *addr)
+{
+	__iounmap(addr);
+}
+
+#define __raw_writel writel
+
+static inline void memcpy_fromio(void *dst, const volatile void __iomem *src,
+	int count)
+{
+	memcpy(dst, (void *) src, count);
+}
+
+static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
+	int count)
+{
+	memcpy((void *) dst, src, count);
+}
+
+#define PCI_IO_ADDR	(volatile void __iomem *)
+
+/*
+ * inb - read byte from I/O port or something
+ * @port:  address in I/O space
+ *
+ * Operates on "I/O bus I/O space"
+ */
+static inline u8 inb(unsigned long port)
+{
+	return readb(_IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline u16 inw(unsigned long port)
+{
+	return readw(_IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline u32 inl(unsigned long port)
+{
+	return readl(_IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+/*
+ * outb - write a byte to a memory location
+ * @data: data to write to
+ * @addr:  address in I/O space
+ */
+static inline void outb(u8 data, unsigned long port)
+{
+	writeb(data, _IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline void outw(u16 data, unsigned long port)
+{
+	writew(data, _IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline void outl(u32 data, unsigned long port)
+{
+	writel(data, _IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+#define outb_p outb
+#define outw_p outw
+#define outl_p outl
+
+#define inb_p inb
+#define inw_p inw
+#define inl_p inl
+
+static inline void insb(unsigned long port, void *buffer, int count)
+{
+	if (count) {
+		u8 *buf = buffer;
+		do {
+			u8 x = inb(port);
+			*buf++ = x;
+		} while (--count);
+	}
+}
+
+static inline void insw(unsigned long port, void *buffer, int count)
+{
+	if (count) {
+		u16 *buf = buffer;
+		do {
+			u16 x = inw(port);
+			*buf++ = x;
+		} while (--count);
+	}
+}
+
+static inline void insl(unsigned long port, void *buffer, int count)
+{
+	if (count) {
+		u32 *buf = buffer;
+		do {
+			u32 x = inw(port);
+			*buf++ = x;
+		} while (--count);
+	}
+}
+
+static inline void outsb(unsigned long port, const void *buffer, int count)
+{
+	if (count) {
+		const u8 *buf = buffer;
+		do {
+			outb(*buf++, port);
+		} while (--count);
+	}
+}
+
+static inline void outsw(unsigned long port, const void *buffer, int count)
+{
+	if (count) {
+		const u16 *buf = buffer;
+		do {
+			outw(*buf++, port);
+		} while (--count);
+	}
+}
+
+static inline void outsl(unsigned long port, const void *buffer, int count)
+{
+	if (count) {
+		const u32 *buf = buffer;
+		do {
+			outl(*buf++, port);
+		} while (--count);
+	}
+}
+
+#define flush_write_buffers() do { } while (0)
+
+#endif /* __KERNEL__ */
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/irqflags.h linux-libre-3.2-gnu/arch/hexagon/include/asm/irqflags.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/irqflags.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/irqflags.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,62 @@
+/*
+ * IRQ support for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#include <asm/hexagon_vm.h>
+#include <linux/types.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	return __vmgetie();
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	return __vmsetie(VM_INT_DISABLE);
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return !flags;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return !__vmgetie();
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	__vmsetie(VM_INT_ENABLE);
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	__vmsetie(VM_INT_DISABLE);
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	__vmsetie(flags);
+}
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/irq.h linux-libre-3.2-gnu/arch/hexagon/include/asm/irq.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/irq.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_IRQ_H_
+#define _ASM_IRQ_H_
+
+/* Number of first-level interrupts associated with the CPU core. */
+#define HEXAGON_CPUINTS 32
+
+/*
+ * Must define NR_IRQS before including <asm-generic/irq.h>
+ * 64 == the two SIRC's, 176 == the two gpio's
+ *
+ * IRQ configuration is still in flux; defining this to a comfortably
+ * large number.
+ */
+#define NR_IRQS 512
+
+#include <asm-generic/irq.h>
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/Kbuild linux-libre-3.2-gnu/arch/hexagon/include/asm/Kbuild
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/Kbuild	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/Kbuild	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,58 @@
+include include/asm-generic/Kbuild.asm
+
+header-y += registers.h
+header-y += ucontext.h
+header-y += user.h
+
+generic-y += auxvec.h
+generic-y += bug.h
+generic-y += bugs.h
+generic-y += cpumask.h
+generic-y += cputime.h
+generic-y += current.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += fb.h
+generic-y += fcntl.h
+generic-y += ftrace.h
+generic-y += hardirq.h
+generic-y += hw_irq.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += iomap.h
+generic-y += ipcbuf.h
+generic-y += ipc.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
+generic-y += local64.h
+generic-y += local.h
+generic-y += local.h
+generic-y += mman.h
+generic-y += msgbuf.h
+generic-y += pci.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += posix_types.h
+generic-y += resource.h
+generic-y += rwsem.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += segment.h
+generic-y += sembuf.h
+generic-y += shmbuf.h
+generic-y += shmparam.h
+generic-y += siginfo.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += statfs.h
+generic-y += stat.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += topology.h
+generic-y += types.h
+generic-y += ucontext.h
+generic-y += unaligned.h
+generic-y += xor.h
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/kgdb.h linux-libre-3.2-gnu/arch/hexagon/include/asm/kgdb.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/kgdb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/kgdb.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,43 @@
+/*
+ * arch/hexagon/include/asm/kgdb.h - Hexagon KGDB Support
+ *
+ * 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 __HEXAGON_KGDB_H__
+#define __HEXAGON_KGDB_H__
+
+#define BREAK_INSTR_SIZE 4
+#define CACHE_FLUSH_IS_SAFE   1
+#define BUFMAX       ((NUMREGBYTES * 2) + 512)
+
+static inline void arch_kgdb_breakpoint(void)
+{
+	asm("trap0(#0xDB)");
+}
+
+/* Registers:
+ * 32 gpr + sa0/1 + lc0/1 + m0/1 + gp + ugp + pred + pc = 42 total.
+ * vm regs = psp+elr+est+badva = 4
+ * syscall+restart = 2 more
+ * so 48 = 42 +4 + 2
+ */
+#define DBG_USER_REGS 42
+#define DBG_MAX_REG_NUM (DBG_USER_REGS + 6)
+#define NUMREGBYTES  (DBG_MAX_REG_NUM*4)
+
+#endif /* __HEXAGON_KGDB_H__ */
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/linkage.h linux-libre-3.2-gnu/arch/hexagon/include/asm/linkage.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/linkage.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/linkage.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+#define __ALIGN		.align 4
+#define __ALIGN_STR	".align 4"
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/mem-layout.h linux-libre-3.2-gnu/arch/hexagon/include/asm/mem-layout.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/mem-layout.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/mem-layout.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,112 @@
+/*
+ * Memory layout definitions for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_HEXAGON_MEM_LAYOUT_H
+#define _ASM_HEXAGON_MEM_LAYOUT_H
+
+#include <linux/const.h>
+
+/*
+ * Have to do this for ginormous numbers, else they get printed as
+ * negative numbers, which the linker no likey when you try to
+ * assign it to the location counter.
+ */
+
+#define PAGE_OFFSET			_AC(0xc0000000, UL)
+
+/*
+ * LOAD_ADDRESS is the physical/linear address of where in memory
+ * the kernel gets loaded. The 12 least significant bits must be zero (0)
+ * due to limitations on setting the EVB
+ *
+ */
+
+#ifndef LOAD_ADDRESS
+#define LOAD_ADDRESS			0x00000000
+#endif
+
+#define TASK_SIZE			(PAGE_OFFSET)
+
+/*  not sure how these are used yet  */
+#define STACK_TOP			TASK_SIZE
+#define STACK_TOP_MAX			TASK_SIZE
+
+#ifndef __ASSEMBLY__
+enum fixed_addresses {
+	FIX_KMAP_BEGIN,
+	FIX_KMAP_END,  /*  check for per-cpuism  */
+	__end_of_fixed_addresses
+};
+
+#define MIN_KERNEL_SEG 0x300   /* From 0xc0000000 */
+extern int max_kernel_seg;
+
+/*
+ * Start of vmalloc virtual address space for kernel;
+ * supposed to be based on the amount of physical memory available
+ */
+
+#define VMALLOC_START (PAGE_OFFSET + VMALLOC_OFFSET + \
+	(unsigned long)high_memory)
+
+/* Gap between physical ram and vmalloc space for guard purposes. */
+#define VMALLOC_OFFSET PAGE_SIZE
+
+/*
+ * Create the space between VMALLOC_START and FIXADDR_TOP backwards
+ * from the ... "top".
+ *
+ * Permanent IO mappings will live at 0xfexx_xxxx
+ * Hypervisor occupies the last 16MB page at 0xffxxxxxx
+ */
+
+#define FIXADDR_TOP     0xfe000000
+#define FIXADDR_SIZE    (__end_of_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_START   (FIXADDR_TOP - FIXADDR_SIZE)
+
+/*
+ * "permanent kernel mappings", defined as long-lasting mappings of
+ * high-memory page frames into the kernel address space.
+ */
+
+#define LAST_PKMAP	PTRS_PER_PTE
+#define LAST_PKMAP_MASK	(LAST_PKMAP - 1)
+#define PKMAP_NR(virt)	((virt - PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr)	(PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+/*
+ * To the "left" of the fixed map space is the kmap space
+ *
+ * "Permanent Kernel Mappings"; fancy (or less fancy) PTE table
+ * that looks like it's actually walked.
+ * Need to check the alignment/shift usage; some archs use
+ * PMD_MASK on this value
+ */
+#define PKMAP_BASE (FIXADDR_START-PAGE_SIZE*LAST_PKMAP)
+
+/*
+ * 2 pages of guard gap between where vmalloc area ends
+ * and pkmap_base begins.
+ */
+#define VMALLOC_END (PKMAP_BASE-PAGE_SIZE*2)
+#endif /*  !__ASSEMBLY__  */
+
+
+#endif /* _ASM_HEXAGON_MEM_LAYOUT_H */
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/mmu_context.h linux-libre-3.2-gnu/arch/hexagon/include/asm/mmu_context.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/mmu_context.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/mmu_context.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,100 @@
+/*
+ * MM context support for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_MMU_CONTEXT_H
+#define _ASM_MMU_CONTEXT_H
+
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/mem-layout.h>
+
+static inline void destroy_context(struct mm_struct *mm)
+{
+}
+
+/*
+ * VM port hides all TLB management, so "lazy TLB" isn't very
+ * meaningful.  Even for ports to architectures with visble TLBs,
+ * this is almost invariably a null function.
+ */
+static inline void enter_lazy_tlb(struct mm_struct *mm,
+	struct task_struct *tsk)
+{
+}
+
+/*
+ * Architecture-specific actions, if any, for memory map deactivation.
+ */
+static inline void deactivate_mm(struct task_struct *tsk,
+	struct mm_struct *mm)
+{
+}
+
+/**
+ * init_new_context - initialize context related info for new mm_struct instance
+ * @tsk: pointer to a task struct
+ * @mm: pointer to a new mm struct
+ */
+static inline int init_new_context(struct task_struct *tsk,
+					struct mm_struct *mm)
+{
+	/* mm->context is set up by pgd_alloc */
+	return 0;
+}
+
+/*
+ *  Switch active mm context
+ */
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+				struct task_struct *tsk)
+{
+	int l1;
+
+	/*
+	 * For virtual machine, we have to update system map if it's been
+	 * touched.
+	 */
+	if (next->context.generation < prev->context.generation) {
+		for (l1 = MIN_KERNEL_SEG; l1 <= max_kernel_seg; l1++)
+			next->pgd[l1] = init_mm.pgd[l1];
+
+		next->context.generation = prev->context.generation;
+	}
+
+	__vmnewmap((void *)next->context.ptbase);
+}
+
+/*
+ *  Activate new memory map for task
+ */
+static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	switch_mm(prev, next, current_thread_info()->task);
+	local_irq_restore(flags);
+}
+
+/*  Generic hooks for arch_dup_mmap and arch_exit_mmap  */
+#include <asm-generic/mm_hooks.h>
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/mmu.h linux-libre-3.2-gnu/arch/hexagon/include/asm/mmu.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/mmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/mmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_MMU_H
+#define _ASM_MMU_H
+
+#include <asm/vdso.h>
+
+/*
+ * Architecture-specific state for a mm_struct.
+ * For the Hexagon Virtual Machine, it can be a copy
+ * of the pointer to the page table base.
+ */
+struct mm_context {
+	unsigned long long generation;
+	unsigned long ptbase;
+	struct hexagon_vdso *vdso;
+};
+
+typedef struct mm_context mm_context_t;
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/module.h linux-libre-3.2-gnu/arch/hexagon/include/asm/module.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/module.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/module.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_MODULE_H
+#define _ASM_MODULE_H
+
+#include <asm-generic/module.h>
+
+#define MODULE_ARCH_VERMAGIC __stringify(PROCESSOR_MODEL_NAME) " "
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/mutex.h linux-libre-3.2-gnu/arch/hexagon/include/asm/mutex.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/mutex.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,8 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+#include <asm-generic/mutex-xchg.h>
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/page.h linux-libre-3.2-gnu/arch/hexagon/include/asm/page.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/page.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/page.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,157 @@
+/*
+ * Page management definitions for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_PAGE_H
+#define _ASM_PAGE_H
+
+#include <linux/const.h>
+
+/*  This is probably not the most graceful way to handle this.  */
+
+#ifdef CONFIG_PAGE_SIZE_4KB
+#define PAGE_SHIFT 12
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_4KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_16KB
+#define PAGE_SHIFT 14
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_16KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define PAGE_SHIFT 16
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_64KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_256KB
+#define PAGE_SHIFT 18
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_256KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_1MB
+#define PAGE_SHIFT 20
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_1MB
+#endif
+
+/*
+ *  These should be defined in hugetlb.h, but apparently not.
+ *  "Huge" for us should be 4MB or 16MB, which are both represented
+ *  in L1 PTE's.  Right now, it's set up for 4MB.
+ */
+#ifdef CONFIG_HUGETLB_PAGE
+#define HPAGE_SHIFT 22
+#define HPAGE_SIZE (1UL << HPAGE_SHIFT)
+#define HPAGE_MASK (~(HPAGE_SIZE-1))
+#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT-PAGE_SHIFT)
+#define HVM_HUGEPAGE_SIZE 0x5
+#endif
+
+#define PAGE_SIZE  (1UL << PAGE_SHIFT)
+#define PAGE_MASK  (~((1 << PAGE_SHIFT) - 1))
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+/*
+ * This is for PFN_DOWN, which mm.h needs.  Seems the right place to pull it in.
+ */
+#include <linux/pfn.h>
+
+/*
+ * We implement a two-level architecture-specific page table structure.
+ * Null intermediate page table level (pmd, pud) definitions will come from
+ * asm-generic/pagetable-nopmd.h and asm-generic/pagetable-nopud.h
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct page *pgtable_t;
+
+#define pte_val(x)     ((x).pte)
+#define 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) })
+
+/*
+ * We need a __pa and a __va routine for kernel space.
+ * MIPS says they're only used during mem_init.
+ * also, check if we need a PHYS_OFFSET.
+ */
+#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
+#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
+
+/* The "page frame" descriptor is defined in linux/mm.h */
+struct page;
+
+/* Returns page frame descriptor for virtual address. */
+#define virt_to_page(kaddr) pfn_to_page(PFN_DOWN(__pa(kaddr)))
+
+/* Default vm area behavior is non-executable.  */
+#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \
+				VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#define pfn_valid(pfn) ((pfn) < max_mapnr)
+#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+
+/*  Need to not use a define for linesize; may move this to another file.  */
+static inline void clear_page(void *page)
+{
+	/*  This can only be done on pages with L1 WB cache */
+	asm volatile(
+		"	loop0(1f,%1);\n"
+		"1:	{ dczeroa(%0);\n"
+		"	  %0 = add(%0,#32); }:endloop0\n"
+		: "+r" (page)
+		: "r" (PAGE_SIZE/32)
+		: "lc0", "sa0", "memory"
+	);
+}
+
+#define copy_page(to, from)	memcpy((to), (from), PAGE_SIZE)
+
+/*
+ * Under assumption that kernel always "sees" user map...
+ */
+#define clear_user_page(page, vaddr, pg)	clear_page(page)
+#define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
+
+/*
+ * page_to_phys - convert page to physical address
+ * @page - pointer to page entry in mem_map
+ */
+#define page_to_phys(page)      (page_to_pfn(page) << PAGE_SHIFT)
+
+/*
+ * For port to Hexagon Virtual Machine, MAYBE we check for attempts
+ * to reference reserved HVM space, but in any case, the VM will be
+ * protected.
+ */
+#define kern_addr_valid(addr)   (1)
+
+#include <asm-generic/memory_model.h>
+/* XXX Todo: implement assembly-optimized version of getorder. */
+#include <asm-generic/getorder.h>
+
+#endif /* ifdef __ASSEMBLY__ */
+#endif /* ifdef __KERNEL__ */
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/param.h linux-libre-3.2-gnu/arch/hexagon/include/asm/param.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/param.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/param.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_PARAM_H
+#define _ASM_PARAM_H
+
+#define EXEC_PAGESIZE	16384
+
+#include <asm-generic/param.h>
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/perf_event.h linux-libre-3.2-gnu/arch/hexagon/include/asm/perf_event.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/perf_event.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/perf_event.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_PERF_EVENT_H
+#define _ASM_PERF_EVENT_H
+
+#define PERF_EVENT_INDEX_OFFSET	0
+
+#endif /* _ASM_PERF_EVENT_H */
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/pgalloc.h linux-libre-3.2-gnu/arch/hexagon/include/asm/pgalloc.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/pgalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/pgalloc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,146 @@
+/*
+ * Page table support for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_PGALLOC_H
+#define _ASM_PGALLOC_H
+
+#include <asm/mem-layout.h>
+#include <asm/atomic.h>
+
+#define check_pgt_cache() do {} while (0)
+
+extern unsigned long long kmap_generation;
+
+/*
+ * Page table creation interface
+ */
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	pgd_t *pgd;
+
+	pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+
+	/*
+	 * There may be better ways to do this, but to ensure
+	 * that new address spaces always contain the kernel
+	 * base mapping, and to ensure that the user area is
+	 * initially marked invalid, initialize the new map
+	 * map with a copy of the kernel's persistent map.
+	 */
+
+	memcpy(pgd, swapper_pg_dir, PTRS_PER_PGD*sizeof(pgd_t *));
+	mm->context.generation = kmap_generation;
+
+	/* Physical version is what is passed to virtual machine on switch */
+	mm->context.ptbase = __pa(pgd);
+
+	return pgd;
+}
+
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+	free_page((unsigned long) pgd);
+}
+
+static inline struct page *pte_alloc_one(struct mm_struct *mm,
+					 unsigned long address)
+{
+	struct page *pte;
+
+	pte = alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+
+	if (pte)
+		pgtable_page_ctor(pte);
+
+	return pte;
+}
+
+/* _kernel variant gets to use a different allocator */
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+					  unsigned long address)
+{
+	gfp_t flags =  GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO;
+	return (pte_t *) __get_free_page(flags);
+}
+
+static inline void pte_free(struct mm_struct *mm, struct page *pte)
+{
+	pgtable_page_dtor(pte);
+	__free_page(pte);
+}
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	free_page((unsigned long)pte);
+}
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+				pgtable_t pte)
+{
+	/*
+	 * Conveniently, zero in 3 LSB means indirect 4K page table.
+	 * Not so convenient when you're trying to vary the page size.
+	 */
+	set_pmd(pmd, __pmd(((unsigned long)page_to_pfn(pte) << PAGE_SHIFT) |
+		HEXAGON_L1_PTE_SIZE));
+}
+
+/*
+ * Other architectures seem to have ways of making all processes
+ * share the same pmd's for their kernel mappings, but the v0.3
+ * Hexagon VM spec has a "monolithic" L1 table for user and kernel
+ * segments.  We track "generations" of the kernel map to minimize
+ * overhead, and update the "slave" copies of the kernel mappings
+ * as part of switch_mm.  However, we still need to update the
+ * kernel map of the active thread who's calling pmd_populate_kernel...
+ */
+static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
+				       pte_t *pte)
+{
+	extern spinlock_t kmap_gen_lock;
+	pmd_t *ppmd;
+	int pmdindex;
+
+	spin_lock(&kmap_gen_lock);
+	kmap_generation++;
+	mm->context.generation = kmap_generation;
+	current->active_mm->context.generation = kmap_generation;
+	spin_unlock(&kmap_gen_lock);
+
+	set_pmd(pmd, __pmd(((unsigned long)__pa(pte)) | HEXAGON_L1_PTE_SIZE));
+
+	/*
+	 * Now the "slave" copy of the current thread.
+	 * This is pointer arithmetic, not byte addresses!
+	 */
+	pmdindex = (pgd_t *)pmd - mm->pgd;
+	ppmd = (pmd_t *)current->active_mm->pgd + pmdindex;
+	set_pmd(ppmd, __pmd(((unsigned long)__pa(pte)) | HEXAGON_L1_PTE_SIZE));
+	if (pmdindex > max_kernel_seg)
+		max_kernel_seg = pmdindex;
+}
+
+#define __pte_free_tlb(tlb, pte, addr)		\
+do {						\
+	pgtable_page_dtor((pte));		\
+	tlb_remove_page((tlb), (pte));		\
+} while (0)
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/pgtable.h linux-libre-3.2-gnu/arch/hexagon/include/asm/pgtable.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/pgtable.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/pgtable.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,518 @@
+/*
+ * Page table support for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_PGTABLE_H
+#define _ASM_PGTABLE_H
+
+/*
+ * Page table definitions for Qualcomm Hexagon processor.
+ */
+#include <linux/swap.h>
+#include <asm/page.h>
+#include <asm-generic/pgtable-nopmd.h>
+
+/* A handy thing to have if one has the RAM. Declared in head.S */
+extern unsigned long empty_zero_page;
+extern unsigned long zero_page_mask;
+
+/*
+ * The PTE model described here is that of the Hexagon Virtual Machine,
+ * which autonomously walks 2-level page tables.  At a lower level, we
+ * also describe the RISCish software-loaded TLB entry structure of
+ * the underlying Hexagon processor. A kernel built to run on the
+ * virtual machine has no need to know about the underlying hardware.
+ */
+#include <asm/vm_mmu.h>
+
+/*
+ * To maximize the comfort level for the PTE manipulation macros,
+ * define the "well known" architecture-specific bits.
+ */
+#define _PAGE_READ	__HVM_PTE_R
+#define _PAGE_WRITE	__HVM_PTE_W
+#define _PAGE_EXECUTE	__HVM_PTE_X
+#define _PAGE_USER	__HVM_PTE_U
+
+/*
+ * We have a total of 4 "soft" bits available in the abstract PTE.
+ * The two mandatory software bits are Dirty and Accessed.
+ * To make nonlinear swap work according to the more recent
+ * model, we want a low order "Present" bit to indicate whether
+ * the PTE describes MMU programming or swap space.
+ */
+#define _PAGE_PRESENT	(1<<0)
+#define _PAGE_DIRTY	(1<<1)
+#define _PAGE_ACCESSED	(1<<2)
+
+/*
+ * _PAGE_FILE is only meaningful if _PAGE_PRESENT is false, while
+ * _PAGE_DIRTY is only meaningful if _PAGE_PRESENT is true.
+ * So we can overload the bit...
+ */
+#define _PAGE_FILE	_PAGE_DIRTY /* set:  pagecache, unset = swap */
+
+/*
+ * For now, let's say that Valid and Present are the same thing.
+ * Alternatively, we could say that it's the "or" of R, W, and X
+ * permissions.
+ */
+#define _PAGE_VALID	_PAGE_PRESENT
+
+/*
+ * We're not defining _PAGE_GLOBAL here, since there's no concept
+ * of global pages or ASIDs exposed to the Hexagon Virtual Machine,
+ * and we want to use the same page table structures and macros in
+ * the native kernel as we do in the virtual machine kernel.
+ * So we'll put up with a bit of inefficiency for now...
+ */
+
+/*
+ * Top "FOURTH" level (pgd), which for the Hexagon VM is really
+ * only the second from the bottom, pgd and pud both being collapsed.
+ * Each entry represents 4MB of virtual address space, 4K of table
+ * thus maps the full 4GB.
+ */
+#define PGDIR_SHIFT 22
+#define PTRS_PER_PGD 1024
+
+#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
+
+#ifdef CONFIG_PAGE_SIZE_4KB
+#define PTRS_PER_PTE 1024
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_16KB
+#define PTRS_PER_PTE 256
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define PTRS_PER_PTE 64
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_256KB
+#define PTRS_PER_PTE 16
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_1MB
+#define PTRS_PER_PTE 4
+#endif
+
+/*  Any bigger and the PTE disappears.  */
+#define pgd_ERROR(e) \
+	printk(KERN_ERR "%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__,\
+		pgd_val(e))
+
+/*
+ * Page Protection Constants. Includes (in this variant) cache attributes.
+ */
+extern unsigned long _dflt_cache_att;
+
+#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _PAGE_USER | \
+				_dflt_cache_att)
+#define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_USER | \
+				_PAGE_READ | _PAGE_EXECUTE | _dflt_cache_att)
+#define PAGE_COPY	PAGE_READONLY
+#define PAGE_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER | \
+				_PAGE_READ | _PAGE_EXECUTE | _dflt_cache_att)
+#define PAGE_COPY_EXEC	PAGE_EXEC
+#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
+				_PAGE_EXECUTE | _PAGE_WRITE | _dflt_cache_att)
+#define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | _PAGE_READ | \
+				_PAGE_WRITE | _PAGE_EXECUTE | _dflt_cache_att)
+
+
+/*
+ * Aliases for mapping mmap() protection bits to page protections.
+ * These get used for static initialization, so using the _dflt_cache_att
+ * variable for the default cache attribute isn't workable. If the
+ * default gets changed at boot time, the boot option code has to
+ * update data structures like the protaction_map[] array.
+ */
+#define CACHEDEF	(CACHE_DEFAULT << 6)
+
+/* Private (copy-on-write) page protections. */
+#define __P000 __pgprot(_PAGE_PRESENT | _PAGE_USER | CACHEDEF)
+#define __P001 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | CACHEDEF)
+#define __P010 __P000	/* Write-only copy-on-write */
+#define __P011 __P001	/* Read/Write copy-on-write */
+#define __P100 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+			_PAGE_EXECUTE | CACHEDEF)
+#define __P101 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_EXECUTE | \
+			_PAGE_READ | CACHEDEF)
+#define __P110 __P100	/* Write/execute copy-on-write */
+#define __P111 __P101	/* Read/Write/Execute, copy-on-write */
+
+/* Shared page protections. */
+#define __S000 __P000
+#define __S001 __P001
+#define __S010 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+			_PAGE_WRITE | CACHEDEF)
+#define __S011 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
+			_PAGE_WRITE | CACHEDEF)
+#define __S100 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+			_PAGE_EXECUTE | CACHEDEF)
+#define __S101 __P101
+#define __S110 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+			_PAGE_EXECUTE | _PAGE_WRITE | CACHEDEF)
+#define __S111 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
+			_PAGE_EXECUTE | _PAGE_WRITE | CACHEDEF)
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];  /* located in head.S */
+
+/* Seems to be zero even in architectures where the zero page is firewalled? */
+#define FIRST_USER_ADDRESS 0
+#define pte_special(pte)	0
+#define pte_mkspecial(pte)	(pte)
+
+/*  HUGETLB not working currently  */
+#ifdef CONFIG_HUGETLB_PAGE
+#define pte_mkhuge(pte) __pte((pte_val(pte) & ~0x3) | HVM_HUGEPAGE_SIZE)
+#endif
+
+/*
+ * For now, assume that higher-level code will do TLB/MMU invalidations
+ * and don't insert that overhead into this low-level function.
+ */
+extern void sync_icache_dcache(pte_t pte);
+
+#define pte_present_exec_user(pte) \
+	((pte_val(pte) & (_PAGE_EXECUTE | _PAGE_USER)) == \
+	(_PAGE_EXECUTE | _PAGE_USER))
+
+static inline void set_pte(pte_t *ptep, pte_t pteval)
+{
+	/*  should really be using pte_exec, if it weren't declared later. */
+	if (pte_present_exec_user(pteval))
+		sync_icache_dcache(pteval);
+
+	*ptep = pteval;
+}
+
+/*
+ * For the Hexagon Virtual Machine MMU (or its emulation), a null/invalid
+ * L1 PTE (PMD/PGD) has 7 in the least significant bits. For the L2 PTE
+ * (Linux PTE), the key is to have bits 11..9 all zero.  We'd use 0x7
+ * as a universal null entry, but some of those least significant bits
+ * are interpreted by software.
+ */
+#define _NULL_PMD	0x7
+#define _NULL_PTE	0x0
+
+static inline void pmd_clear(pmd_t *pmd_entry_ptr)
+{
+	 pmd_val(*pmd_entry_ptr) = _NULL_PMD;
+}
+
+/*
+ * Conveniently, a null PTE value is invalid.
+ */
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
+				pte_t *ptep)
+{
+	pte_val(*ptep) = _NULL_PTE;
+}
+
+#ifdef NEED_PMD_INDEX_DESPITE_BEING_2_LEVEL
+/**
+ * pmd_index - returns the index of the entry in the PMD page
+ * which would control the given virtual address
+ */
+#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+
+#endif
+
+/**
+ * pgd_index - returns the index of the entry in the PGD page
+ * which would control the given virtual address
+ *
+ * This returns the *index* for the address in the pgd_t
+ */
+#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+
+/*
+ * pgd_offset - find an offset in a page-table-directory
+ */
+#define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr))
+
+/*
+ * pgd_offset_k - get kernel (init_mm) pgd entry pointer for addr
+ */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/**
+ * pmd_none - check if pmd_entry is mapped
+ * @pmd_entry:  pmd entry
+ *
+ * MIPS checks it against that "invalid pte table" thing.
+ */
+static inline int pmd_none(pmd_t pmd)
+{
+	return pmd_val(pmd) == _NULL_PMD;
+}
+
+/**
+ * pmd_present - is there a page table behind this?
+ * Essentially the inverse of pmd_none.  We maybe
+ * save an inline instruction by defining it this
+ * way, instead of simply "!pmd_none".
+ */
+static inline int pmd_present(pmd_t pmd)
+{
+	return pmd_val(pmd) != (unsigned long)_NULL_PMD;
+}
+
+/**
+ * pmd_bad - check if a PMD entry is "bad". That might mean swapped out.
+ * As we have no known cause of badness, it's null, as it is for many
+ * architectures.
+ */
+static inline int pmd_bad(pmd_t pmd)
+{
+	return 0;
+}
+
+/*
+ * pmd_page - converts a PMD entry to a page pointer
+ */
+#define pmd_page(pmd)  (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+/**
+ * pte_none - check if pte is mapped
+ * @pte: pte_t entry
+ */
+static inline int pte_none(pte_t pte)
+{
+	return pte_val(pte) == _NULL_PTE;
+};
+
+/*
+ * pte_present - check if page is present
+ */
+static inline int pte_present(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_PRESENT;
+}
+
+/* mk_pte - make a PTE out of a page pointer and protection bits */
+#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
+
+/* pte_page - returns a page (frame pointer/descriptor?) based on a PTE */
+#define pte_page(x) pfn_to_page(pte_pfn(x))
+
+/* pte_mkold - mark PTE as not recently accessed */
+static inline pte_t pte_mkold(pte_t pte)
+{
+	pte_val(pte) &= ~_PAGE_ACCESSED;
+	return pte;
+}
+
+/* pte_mkyoung - mark PTE as recently accessed */
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_ACCESSED;
+	return pte;
+}
+
+/* pte_mkclean - mark page as in sync with backing store */
+static inline pte_t pte_mkclean(pte_t pte)
+{
+	pte_val(pte) &= ~_PAGE_DIRTY;
+	return pte;
+}
+
+/* pte_mkdirty - mark page as modified */
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_DIRTY;
+	return pte;
+}
+
+/* pte_young - "is PTE marked as accessed"? */
+static inline int pte_young(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_ACCESSED;
+}
+
+/* pte_dirty - "is PTE dirty?" */
+static inline int pte_dirty(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_DIRTY;
+}
+
+/* pte_modify - set protection bits on PTE */
+static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
+{
+	pte_val(pte) &= PAGE_MASK;
+	pte_val(pte) |= pgprot_val(prot);
+	return pte;
+}
+
+/* pte_wrprotect - mark page as not writable */
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+	pte_val(pte) &= ~_PAGE_WRITE;
+	return pte;
+}
+
+/* pte_mkwrite - mark page as writable */
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_WRITE;
+	return pte;
+}
+
+/* pte_mkexec - mark PTE as executable */
+static inline pte_t pte_mkexec(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_EXECUTE;
+	return pte;
+}
+
+/* pte_read - "is PTE marked as readable?" */
+static inline int pte_read(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_READ;
+}
+
+/* pte_write - "is PTE marked as writable?" */
+static inline int pte_write(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_WRITE;
+}
+
+
+/* pte_exec - "is PTE marked as executable?" */
+static inline int pte_exec(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_EXECUTE;
+}
+
+/* __pte_to_swp_entry - extract swap entry from PTE */
+#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
+
+/* __swp_entry_to_pte - extract PTE from swap entry */
+#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
+
+/* pfn_pte - convert page number and protection value to page table entry */
+#define pfn_pte(pfn, pgprot) __pte((pfn << PAGE_SHIFT) | pgprot_val(pgprot))
+
+/* pte_pfn - convert pte to page frame number */
+#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
+
+/*
+ * set_pte_at - update page table and do whatever magic may be
+ * necessary to make the underlying hardware/firmware take note.
+ *
+ * VM may require a virtual instruction to alert the MMU.
+ */
+#define set_pte_at(mm, addr, ptep, pte) set_pte(ptep, pte)
+
+/*
+ * May need to invoke the virtual machine as well...
+ */
+#define pte_unmap(pte)		do { } while (0)
+#define pte_unmap_nested(pte)	do { } while (0)
+
+/*
+ * pte_offset_map - returns the linear address of the page table entry
+ * corresponding to an address
+ */
+#define pte_offset_map(dir, address)                                    \
+	((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
+
+#define pte_offset_map_nested(pmd, addr) pte_offset_map(pmd, addr)
+
+/* pte_offset_kernel - kernel version of pte_offset */
+#define pte_offset_kernel(dir, address) \
+	((pte_t *) (unsigned long) __va(pmd_val(*dir) & PAGE_MASK) \
+				+  __pte_offset(address))
+
+/* ZERO_PAGE - returns the globally shared zero page */
+#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page))
+
+#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+
+/* Nothing special about IO remapping at this point */
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+	remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+/*  I think this is in case we have page table caches; needed by init/main.c  */
+#define pgtable_cache_init()    do { } while (0)
+
+/*
+ * Swap/file PTE definitions.  If _PAGE_PRESENT is zero, the rest of the
+ * PTE is interpreted as swap information.  Depending on the _PAGE_FILE
+ * bit, the remaining free bits are eitehr interpreted as a file offset
+ * or a swap type/offset tuple.  Rather than have the TLB fill handler
+ * test _PAGE_PRESENT, we're going to reserve the permissions bits
+ * and set them to all zeros for swap entries, which speeds up the
+ * miss handler at the cost of 3 bits of offset.  That trade-off can
+ * be revisited if necessary, but Hexagon processor architecture and
+ * target applications suggest a lot of TLB misses and not much swap space.
+ *
+ * Format of swap PTE:
+ *	bit	0:	Present (zero)
+ *	bit	1:	_PAGE_FILE (zero)
+ *	bits	2-6:	swap type (arch independent layer uses 5 bits max)
+ *	bits	7-9:	bits 2:0 of offset
+ *	bits 10-12:	effectively _PAGE_PROTNONE (all zero)
+ *	bits 13-31:  bits 21:3 of swap offset
+ *
+ * Format of file PTE:
+ *	bit	0:	Present (zero)
+ *	bit	1:	_PAGE_FILE (zero)
+ *	bits	2-9:	bits 7:0 of offset
+ *	bits 10-12:	effectively _PAGE_PROTNONE (all zero)
+ *	bits 13-31:  bits 26:8 of swap offset
+ *
+ * The split offset makes some of the following macros a little gnarly,
+ * but there's plenty of precedent for this sort of thing.
+ */
+#define PTE_FILE_MAX_BITS     27
+
+/* Used for swap PTEs */
+#define __swp_type(swp_pte)		(((swp_pte).val >> 2) & 0x1f)
+
+#define __swp_offset(swp_pte) \
+	((((swp_pte).val >> 7) & 0x7) | (((swp_pte).val >> 10) & 0x003ffff8))
+
+#define __swp_entry(type, offset) \
+	((swp_entry_t)	{ \
+		((type << 2) | \
+		 ((offset & 0x3ffff8) << 10) | ((offset & 0x7) << 7)) })
+
+/* Used for file PTEs */
+#define pte_file(pte) \
+	((pte_val(pte) & (_PAGE_FILE | _PAGE_PRESENT)) == _PAGE_FILE)
+
+#define pte_to_pgoff(pte) \
+	(((pte_val(pte) >> 2) & 0xff) | ((pte_val(pte) >> 5) & 0x07ffff00))
+
+#define pgoff_to_pte(off) \
+	((pte_t) { ((((off) & 0x7ffff00) << 5) | (((off) & 0xff) << 2)\
+	| _PAGE_FILE) })
+
+/*  Oh boy.  There are a lot of possible arch overrides found in this file.  */
+#include <asm-generic/pgtable.h>
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/processor.h linux-libre-3.2-gnu/arch/hexagon/include/asm/processor.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/processor.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/processor.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,123 @@
+/*
+ * Process/processor support for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_PROCESSOR_H
+#define _ASM_PROCESSOR_H
+
+#ifndef __ASSEMBLY__
+
+#include <asm/mem-layout.h>
+#include <asm/registers.h>
+#include <asm/hexagon_vm.h>
+
+/*  must be a macro  */
+#define current_text_addr() ({ __label__ _l; _l: &&_l; })
+
+/*  task_struct, defined elsewhere, is the "process descriptor" */
+struct task_struct;
+
+/*  this is defined in arch/process.c  */
+extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+extern unsigned long thread_saved_pc(struct task_struct *tsk);
+
+extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
+
+/*
+ * thread_struct is supposed to be for context switch data.
+ * Specifically, to hold the state necessary to perform switch_to...
+ */
+struct thread_struct {
+	void *switch_sp;
+};
+
+/*
+ * initializes thread_struct
+ * The only thing we have in there is switch_sp
+ * which doesn't really need to be initialized.
+ */
+
+#define INIT_THREAD { \
+}
+
+#define cpu_relax() __vmyield()
+
+/*
+ * "Unlazying all lazy status" occurs here.
+ */
+static inline void prepare_to_copy(struct task_struct *tsk)
+{
+}
+
+/*
+ * Decides where the kernel will search for a free chunk of vm space during
+ * mmaps.
+ * See also arch_get_unmapped_area.
+ * Doesn't affect if you have MAX_FIXED in the page flags set though...
+ *
+ * Apparently the convention is that ld.so will ask for "unmapped" private
+ * memory to be allocated SOMEWHERE, but it also asks for memory explicitly
+ * via MAP_FIXED at the lower * addresses starting at VA=0x0.
+ *
+ * If the two requests collide, you get authentic segfaulting action, so
+ * you have to kick the "unmapped" base requests higher up.
+ */
+#define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE/3))
+
+
+#define task_pt_regs(task) \
+	((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE) - 1)
+
+#define KSTK_EIP(tsk) (pt_elr(task_pt_regs(tsk)))
+#define KSTK_ESP(tsk) (pt_psp(task_pt_regs(tsk)))
+
+/*  Free all resources held by a thread; defined in process.c  */
+extern void release_thread(struct task_struct *dead_task);
+
+/* Get wait channel for task P.  */
+extern unsigned long get_wchan(struct task_struct *p);
+
+/*  The following stuff is pretty HEXAGON specific.  */
+
+/*  This is really just here for __switch_to.
+    Offsets are pulled via asm-offsets.c  */
+
+/*
+ * No real reason why VM and native switch stacks should be different.
+ * Ultimately this should merge.  Note that Rev C. ABI called out only
+ * R24-27 as callee saved GPRs needing explicit attention (R29-31 being
+ * dealt with automagically by allocframe), but the current ABI has
+ * more, R16-R27.  By saving more, the worst case is that we waste some
+ * cycles if building with the old compilers.
+ */
+
+struct hexagon_switch_stack {
+	unsigned long long	r1716;
+	unsigned long long	r1918;
+	unsigned long long	r2120;
+	unsigned long long	r2322;
+	unsigned long long	r2524;
+	unsigned long long	r2726;
+	unsigned long		fp;
+	unsigned long		lr;
+};
+
+#endif /* !__ASSEMBLY__ */
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/ptrace.h linux-libre-3.2-gnu/arch/hexagon/include/asm/ptrace.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/ptrace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/ptrace.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * Ptrace definitions for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_PTRACE_H
+#define _ASM_PTRACE_H
+
+#include <asm/registers.h>
+
+#define instruction_pointer(regs) pt_elr(regs)
+#define user_stack_pointer(regs) ((regs)->r29)
+
+#define profile_pc(regs) instruction_pointer(regs)
+
+/* kprobe-based event tracer support */
+extern int regs_query_register_offset(const char *name);
+extern const char *regs_query_register_name(unsigned int offset);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/registers.h linux-libre-3.2-gnu/arch/hexagon/include/asm/registers.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/registers.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/registers.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,236 @@
+/*
+ * Register definitions for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_REGISTERS_H
+#define _ASM_REGISTERS_H
+
+#define SP r29
+
+#ifndef __ASSEMBLY__
+
+/*  See kernel/entry.S for further documentation.  */
+
+/*
+ * Entry code copies the event record out of guest registers into
+ * this structure (which is on the stack).
+ */
+
+struct hvm_event_record {
+	unsigned long vmel;     /* Event Linkage (return address) */
+	unsigned long vmest;    /* Event context - pre-event SSR values */
+	unsigned long vmpsp;    /* Previous stack pointer */
+	unsigned long vmbadva;  /* Bad virtual address for addressing events */
+};
+
+struct pt_regs {
+	long restart_r0;        /* R0 checkpoint for syscall restart */
+	long syscall_nr;        /* Only used in system calls */
+	union {
+		struct {
+			unsigned long usr;
+			unsigned long preds;
+		};
+		long long int predsusr;
+	};
+	union {
+		struct {
+			unsigned long m0;
+			unsigned long m1;
+		};
+		long long int m1m0;
+	};
+	union {
+		struct {
+			unsigned long sa1;
+			unsigned long lc1;
+		};
+		long long int lc1sa1;
+	};
+	union {
+		struct {
+			unsigned long sa0;
+			unsigned long lc0;
+		};
+		long long int lc0sa0;
+	};
+	union {
+		struct {
+			unsigned long gp;
+			unsigned long ugp;
+		};
+		long long int ugpgp;
+	};
+	/*
+	* Be extremely careful with rearranging these, if at all.  Some code
+	* assumes the 32 registers exist exactly like this in memory;
+	* e.g. kernel/ptrace.c
+	* e.g. kernel/signal.c (restore_sigcontext)
+	*/
+	union {
+		struct {
+			unsigned long r00;
+			unsigned long r01;
+		};
+		long long int r0100;
+	};
+	union {
+		struct {
+			unsigned long r02;
+			unsigned long r03;
+		};
+		long long int r0302;
+	};
+	union {
+		struct {
+			unsigned long r04;
+			unsigned long r05;
+		};
+		long long int r0504;
+	};
+	union {
+		struct {
+			unsigned long r06;
+			unsigned long r07;
+		};
+		long long int r0706;
+	};
+	union {
+		struct {
+			unsigned long r08;
+			unsigned long r09;
+		};
+		long long int r0908;
+	};
+	union {
+	       struct {
+			unsigned long r10;
+			unsigned long r11;
+	       };
+	       long long int r1110;
+	};
+	union {
+	       struct {
+			unsigned long r12;
+			unsigned long r13;
+	       };
+	       long long int r1312;
+	};
+	union {
+	       struct {
+			unsigned long r14;
+			unsigned long r15;
+	       };
+	       long long int r1514;
+	};
+	union {
+		struct {
+			unsigned long r16;
+			unsigned long r17;
+		};
+		long long int r1716;
+	};
+	union {
+		struct {
+			unsigned long r18;
+			unsigned long r19;
+		};
+		long long int r1918;
+	};
+	union {
+		struct {
+			unsigned long r20;
+			unsigned long r21;
+		};
+		long long int r2120;
+	};
+	union {
+		struct {
+			unsigned long r22;
+			unsigned long r23;
+		};
+		long long int r2322;
+	};
+	union {
+		struct {
+			unsigned long r24;
+			unsigned long r25;
+		};
+		long long int r2524;
+	};
+	union {
+		struct {
+			unsigned long r26;
+			unsigned long r27;
+		};
+		long long int r2726;
+	};
+	union {
+		struct {
+			unsigned long r28;
+			unsigned long r29;
+	       };
+	       long long int r2928;
+	};
+	union {
+		struct {
+			unsigned long r30;
+			unsigned long r31;
+		};
+		long long int r3130;
+	};
+	/* VM dispatch pushes event record onto stack - we can build on it */
+	struct hvm_event_record hvmer;
+};
+
+/* Defines to conveniently access the values  */
+
+/*
+ * As of the VM spec 0.5, these registers are now set/retrieved via a
+ * VM call.  On the in-bound side, we just fetch the values
+ * at the entry points and stuff them into the old record in pt_regs.
+ * However, on the outbound side, probably at VM rte, we set the
+ * registers back.
+ */
+
+#define pt_elr(regs) ((regs)->hvmer.vmel)
+#define pt_set_elr(regs, val) ((regs)->hvmer.vmel = (val))
+#define pt_cause(regs) ((regs)->hvmer.vmest & (HVM_VMEST_CAUSE_MSK))
+#define user_mode(regs) \
+	(((regs)->hvmer.vmest & (HVM_VMEST_UM_MSK << HVM_VMEST_UM_SFT)) != 0)
+#define ints_enabled(regs) \
+	(((regs)->hvmer.vmest & (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)) != 0)
+#define pt_psp(regs) ((regs)->hvmer.vmpsp)
+#define pt_badva(regs) ((regs)->hvmer.vmbadva)
+
+#define pt_set_rte_sp(regs, sp) do {\
+	pt_psp(regs) = (sp);\
+	(regs)->SP = (unsigned long) &((regs)->hvmer);\
+	} while (0)
+
+#define pt_set_kmode(regs) \
+	(regs)->hvmer.vmest = (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)
+
+#define pt_set_usermode(regs) \
+	(regs)->hvmer.vmest = (HVM_VMEST_UM_MSK << HVM_VMEST_UM_SFT) \
+			    | (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)
+
+#endif  /*  ifndef __ASSEMBLY  */
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/setup.h linux-libre-3.2-gnu/arch/hexagon/include/asm/setup.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/setup.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/setup.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_SETUP_H
+#define _ASM_SETUP_H
+
+#include <linux/init.h>
+#include <asm-generic/setup.h>
+
+extern char external_cmdline_buffer;
+
+void __init setup_arch_memory(void);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/sigcontext.h linux-libre-3.2-gnu/arch/hexagon/include/asm/sigcontext.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/sigcontext.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/sigcontext.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_SIGCONTEXT_H
+#define _ASM_SIGCONTEXT_H
+
+#include <asm/user.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 {
+	struct user_regs_struct sc_regs;
+} __aligned(8);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/signal.h linux-libre-3.2-gnu/arch/hexagon/include/asm/signal.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/signal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/signal.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_SIGNAL_H
+#define _ASM_SIGNAL_H
+
+extern unsigned long __rt_sigtramp_template[2];
+
+#include <asm-generic/signal.h>
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/smp.h linux-libre-3.2-gnu/arch/hexagon/include/asm/smp.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/smp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/smp.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,44 @@
+/*
+ * SMP definitions for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef __ASM_SMP_H
+#define __ASM_SMP_H
+
+#include <linux/cpumask.h>
+
+#define raw_smp_processor_id() (current_thread_info()->cpu)
+
+enum ipi_message_type {
+	IPI_NOP = 0,
+	IPI_RESCHEDULE = 1,
+	IPI_CALL_FUNC,
+	IPI_CALL_FUNC_SINGLE,
+	IPI_CPU_STOP,
+	IPI_TIMER,
+};
+
+extern void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg);
+extern void smp_start_cpus(void);
+extern void arch_send_call_function_single_ipi(int cpu);
+extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
+
+extern void smp_vm_unmask_irq(void *info);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/spinlock.h linux-libre-3.2-gnu/arch/hexagon/include/asm/spinlock.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/spinlock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/spinlock.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,186 @@
+/*
+ * Spinlock support for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_SPINLOCK_H
+#define _ASM_SPINLOCK_H
+
+#include <asm/irqflags.h>
+
+/*
+ * This file is pulled in for SMP builds.
+ * Really need to check all the barrier stuff for "true" SMP
+ */
+
+/*
+ * Read locks:
+ * - load the lock value
+ * - increment it
+ * - if the lock value is still negative, go back and try again.
+ * - unsuccessful store is unsuccessful.  Go back and try again.  Loser.
+ * - successful store new lock value if positive -> lock acquired
+ */
+static inline void arch_read_lock(arch_rwlock_t *lock)
+{
+	__asm__ __volatile__(
+		"1:	R6 = memw_locked(%0);\n"
+		"	{ P3 = cmp.ge(R6,#0); R6 = add(R6,#1);}\n"
+		"	{ if !P3 jump 1b; }\n"
+		"	memw_locked(%0,P3) = R6;\n"
+		"	{ if !P3 jump 1b; }\n"
+		:
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+
+}
+
+static inline void arch_read_unlock(arch_rwlock_t *lock)
+{
+	__asm__ __volatile__(
+		"1:	R6 = memw_locked(%0);\n"
+		"	R6 = add(R6,#-1);\n"
+		"	memw_locked(%0,P3) = R6\n"
+		"	if !P3 jump 1b;\n"
+		:
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+
+}
+
+/*  I think this returns 0 on fail, 1 on success.  */
+static inline int arch_read_trylock(arch_rwlock_t *lock)
+{
+	int temp;
+	__asm__ __volatile__(
+		"	R6 = memw_locked(%1);\n"
+		"	{ %0 = #0; P3 = cmp.ge(R6,#0); R6 = add(R6,#1);}\n"
+		"	{ if !P3 jump 1f; }\n"
+		"	memw_locked(%1,P3) = R6;\n"
+		"	{ %0 = P3 }\n"
+		"1:\n"
+		: "=&r" (temp)
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+	return temp;
+}
+
+static inline int arch_read_can_lock(arch_rwlock_t *rwlock)
+{
+	return rwlock->lock == 0;
+}
+
+static inline int arch_write_can_lock(arch_rwlock_t *rwlock)
+{
+	return rwlock->lock == 0;
+}
+
+/*  Stuffs a -1 in the lock value?  */
+static inline void arch_write_lock(arch_rwlock_t *lock)
+{
+	__asm__ __volatile__(
+		"1:	R6 = memw_locked(%0)\n"
+		"	{ P3 = cmp.eq(R6,#0);  R6 = #-1;}\n"
+		"	{ if !P3 jump 1b; }\n"
+		"	memw_locked(%0,P3) = R6;\n"
+		"	{ if !P3 jump 1b; }\n"
+		:
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+}
+
+
+static inline int arch_write_trylock(arch_rwlock_t *lock)
+{
+	int temp;
+	__asm__ __volatile__(
+		"	R6 = memw_locked(%1)\n"
+		"	{ %0 = #0; P3 = cmp.eq(R6,#0);  R6 = #-1;}\n"
+		"	{ if !P3 jump 1f; }\n"
+		"	memw_locked(%1,P3) = R6;\n"
+		"	%0 = P3;\n"
+		"1:\n"
+		: "=&r" (temp)
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+	return temp;
+
+}
+
+static inline void arch_write_unlock(arch_rwlock_t *lock)
+{
+	smp_mb();
+	lock->lock = 0;
+}
+
+static inline void arch_spin_lock(arch_spinlock_t *lock)
+{
+	__asm__ __volatile__(
+		"1:	R6 = memw_locked(%0);\n"
+		"	P3 = cmp.eq(R6,#0);\n"
+		"	{ if !P3 jump 1b; R6 = #1; }\n"
+		"	memw_locked(%0,P3) = R6;\n"
+		"	{ if !P3 jump 1b; }\n"
+		:
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t *lock)
+{
+	smp_mb();
+	lock->lock = 0;
+}
+
+static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
+{
+	int temp;
+	__asm__ __volatile__(
+		"	R6 = memw_locked(%1);\n"
+		"	P3 = cmp.eq(R6,#0);\n"
+		"	{ if !P3 jump 1f; R6 = #1; %0 = #0; }\n"
+		"	memw_locked(%1,P3) = R6;\n"
+		"	%0 = P3;\n"
+		"1:\n"
+		: "=&r" (temp)
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+	return temp;
+}
+
+/*
+ * SMP spinlocks are intended to allow only a single CPU at the lock
+ */
+#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
+#define arch_spin_unlock_wait(lock) \
+	do {while (arch_spin_is_locked(lock)) cpu_relax(); } while (0)
+#define arch_spin_is_locked(x) ((x)->lock != 0)
+
+#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
+#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/spinlock_types.h linux-libre-3.2-gnu/arch/hexagon/include/asm/spinlock_types.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/spinlock_types.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/spinlock_types.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,42 @@
+/*
+ * Spinlock support for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_SPINLOCK_TYPES_H
+#define _ASM_SPINLOCK_TYPES_H
+
+#include <linux/version.h>
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+	volatile unsigned int lock;
+} arch_spinlock_t;
+
+#define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 }
+
+typedef struct {
+	volatile unsigned int lock;
+} arch_rwlock_t;
+
+#define __ARCH_RW_LOCK_UNLOCKED		{ 0 }
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/string.h linux-libre-3.2-gnu/arch/hexagon/include/asm/string.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/string.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/string.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_STRING_H_
+#define _ASM_STRING_H_
+
+#ifdef __KERNEL__
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
+
+/*  ToDo:  use dczeroa, accelerate the compiler-constant zero case  */
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *__to, int c, size_t __n);
+#endif
+
+
+#endif /* _ASM_STRING_H_ */
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/suspend.h linux-libre-3.2-gnu/arch/hexagon/include/asm/suspend.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/suspend.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/suspend.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_SUSPEND_H
+#define _ASM_SUSPEND_H
+
+static inline int arch_prepare_suspend(void)
+{
+	return 0;
+}
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/swab.h linux-libre-3.2-gnu/arch/hexagon/include/asm/swab.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/swab.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/swab.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_SWAB_H
+#define _ASM_SWAB_H
+
+#define __SWAB_64_THRU_32__
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/syscall.h linux-libre-3.2-gnu/arch/hexagon/include/asm/syscall.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/syscall.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/syscall.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,54 @@
+/*
+ * Syscall support for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_HEXAGON_SYSCALL_H
+#define _ASM_HEXAGON_SYSCALL_H
+
+typedef long (*syscall_fn)(unsigned long, unsigned long,
+	unsigned long, unsigned long,
+	unsigned long, unsigned long);
+
+asmlinkage int sys_execve(char __user *ufilename, char __user * __user *argv,
+			  char __user * __user *envp);
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+			 unsigned long parent_tidp, unsigned long child_tidp);
+
+#define sys_execve	sys_execve
+#define sys_clone	sys_clone
+
+#include <asm-generic/syscalls.h>
+
+extern void *sys_call_table[];
+
+static inline long syscall_get_nr(struct task_struct *task,
+				  struct pt_regs *regs)
+{
+	return regs->r06;
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+					 struct pt_regs *regs,
+					 unsigned int i, unsigned int n,
+					 unsigned long *args)
+{
+	BUG_ON(i + n > 6);
+	memcpy(args, &(&regs->r00)[i], n * sizeof(args[0]));
+}
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/system.h linux-libre-3.2-gnu/arch/hexagon/include/asm/system.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/system.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,126 @@
+/*
+ * System level definitions for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_SYSTEM_H
+#define _ASM_SYSTEM_H
+
+#include <linux/linkage.h>
+#include <linux/irqflags.h>
+#include <asm/atomic.h>
+#include <asm/hexagon_vm.h>
+
+struct thread_struct;
+
+extern struct task_struct *__switch_to(struct task_struct *,
+	struct task_struct *,
+	struct task_struct *);
+
+#define switch_to(p, n, r) do {\
+	r = __switch_to((p), (n), (r));\
+} while (0)
+
+
+#define rmb()				barrier()
+#define read_barrier_depends()		barrier()
+#define wmb()				barrier()
+#define mb()				barrier()
+#define smp_rmb()			barrier()
+#define smp_read_barrier_depends()	barrier()
+#define smp_wmb()			barrier()
+#define smp_mb()			barrier()
+#define smp_mb__before_atomic_dec()	barrier()
+#define smp_mb__after_atomic_dec()	barrier()
+#define smp_mb__before_atomic_inc()	barrier()
+#define smp_mb__after_atomic_inc()	barrier()
+
+/*
+ * __xchg - atomically exchange a register and a memory location
+ * @x: value to swap
+ * @ptr: pointer to memory
+ * @size:  size of the value
+ *
+ * Only 4 bytes supported currently.
+ *
+ * Note:  there was an errata for V2 about .new's and memw_locked.
+ *
+ */
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+				   int size)
+{
+	unsigned long retval;
+
+	/*  Can't seem to use printk or panic here, so just stop  */
+	if (size != 4) do { asm volatile("brkpt;\n"); } while (1);
+
+	__asm__ __volatile__ (
+	"1:	%0 = memw_locked(%1);\n"    /*  load into retval */
+	"	memw_locked(%1,P0) = %2;\n" /*  store into memory */
+	"	if !P0 jump 1b;\n"
+	: "=&r" (retval)
+	: "r" (ptr), "r" (x)
+	: "memory", "p0"
+	);
+	return retval;
+}
+
+/*
+ * Atomically swap the contents of a register with memory.  Should be atomic
+ * between multiple CPU's and within interrupts on the same CPU.
+ */
+#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
+	sizeof(*(ptr))))
+
+/*  Set a value and use a memory barrier.  Used by the scheduler somewhere.  */
+#define set_mb(var, value) \
+	do { var = value; mb(); } while (0)
+
+/*
+ *  see rt-mutex-design.txt; cmpxchg supposedly checks if *ptr == A and swaps.
+ *  looks just like atomic_cmpxchg on our arch currently with a bunch of
+ *  variable casting.
+ */
+#define __HAVE_ARCH_CMPXCHG 1
+
+#define cmpxchg(ptr, old, new)					\
+({								\
+	__typeof__(ptr) __ptr = (ptr);				\
+	__typeof__(*(ptr)) __old = (old);			\
+	__typeof__(*(ptr)) __new = (new);			\
+	__typeof__(*(ptr)) __oldval = 0;			\
+								\
+	asm volatile(						\
+		"1:	%0 = memw_locked(%1);\n"		\
+		"	{ P0 = cmp.eq(%0,%2);\n"		\
+		"	  if (!P0.new) jump:nt 2f; }\n"		\
+		"	memw_locked(%1,p0) = %3;\n"		\
+		"	if (!P0) jump 1b;\n"			\
+		"2:\n"						\
+		: "=&r" (__oldval)				\
+		: "r" (__ptr), "r" (__old), "r" (__new)		\
+		: "memory", "p0"				\
+	);							\
+	__oldval;						\
+})
+
+/*  Should probably shoot for an 8-byte aligned stack pointer  */
+#define STACK_MASK (~7)
+#define arch_align_stack(x) (x & STACK_MASK)
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/thread_info.h linux-libre-3.2-gnu/arch/hexagon/include/asm/thread_info.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/thread_info.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/thread_info.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,154 @@
+/*
+ * Thread support for the Hexagon architecture
+ *
+ * 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.
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>
+#include <asm/registers.h>
+#include <asm/page.h>
+#endif
+
+#define THREAD_SHIFT		12
+#define THREAD_SIZE		(1<<THREAD_SHIFT)
+
+#if THREAD_SHIFT >= PAGE_SHIFT
+#define THREAD_SIZE_ORDER	(THREAD_SHIFT - PAGE_SHIFT)
+#else  /*  don't use standard allocator  */
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+extern struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node);
+extern void free_thread_info(struct thread_info *ti);
+#endif
+
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+	unsigned long seg;
+} mm_segment_t;
+
+/*
+ * This is union'd with the "bottom" of the kernel stack.
+ * It keeps track of thread info which is handy for routines
+ * to access quickly.
+ */
+
+struct thread_info {
+	struct task_struct	*task;		/* main task structure */
+	struct exec_domain      *exec_domain;   /* execution domain */
+	unsigned long		flags;          /* low level flags */
+	__u32                   cpu;            /* current cpu */
+	int                     preempt_count;  /* 0=>preemptible,<0=>BUG */
+	mm_segment_t            addr_limit;     /* segmentation sux */
+	/*
+	 * used for syscalls somehow;
+	 * seems to have a function pointer and four arguments
+	 */
+	struct restart_block    restart_block;
+	/* Points to the current pt_regs frame  */
+	struct pt_regs		*regs;
+	/*
+	 * saved kernel sp at switch_to time;
+	 * not sure if this is used (it's not in the VM model it seems;
+	 * see thread_struct)
+	 */
+	unsigned long		sp;
+};
+
+#else /* !__ASSEMBLY__ */
+
+#include <asm/asm-offsets.h>
+
+#endif  /* __ASSEMBLY__  */
+
+/*  looks like "linux/hardirq.h" uses this.  */
+
+#define PREEMPT_ACTIVE		0x10000000
+
+#ifndef __ASSEMBLY__
+
+#define INIT_THREAD_INFO(tsk)                   \
+{                                               \
+	.task           = &tsk,                 \
+	.exec_domain    = &default_exec_domain, \
+	.flags          = 0,                    \
+	.cpu            = 0,                    \
+	.preempt_count  = 1,                    \
+	.addr_limit     = KERNEL_DS,            \
+	.restart_block = {                      \
+		.fn = do_no_restart_syscall,    \
+	},                                      \
+	.sp = 0,				\
+	.regs = NULL,			\
+}
+
+#define init_thread_info        (init_thread_union.thread_info)
+#define init_stack              (init_thread_union.stack)
+
+/* Tacky preprocessor trickery */
+#define	qqstr(s) qstr(s)
+#define qstr(s) #s
+#define QUOTED_THREADINFO_REG qqstr(THREADINFO_REG)
+
+register struct thread_info *__current_thread_info asm(QUOTED_THREADINFO_REG);
+#define current_thread_info()  __current_thread_info
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files
+ *   may need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+
+#define TIF_SYSCALL_TRACE       0       /* syscall trace active */
+#define TIF_NOTIFY_RESUME       1       /* resumption notification requested */
+#define TIF_SIGPENDING          2       /* signal pending */
+#define TIF_NEED_RESCHED        3       /* rescheduling necessary */
+#define TIF_SINGLESTEP          4       /* restore ss @ return to usr mode */
+#define TIF_IRET                5       /* return with iret */
+#define TIF_RESTORE_SIGMASK     6       /* restore sig mask in do_signal() */
+/* true if poll_idle() is polling TIF_NEED_RESCHED */
+#define TIF_POLLING_NRFLAG      16
+#define TIF_MEMDIE              17      /* OOM killer killed process */
+
+#define _TIF_SYSCALL_TRACE      (1 << TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME      (1 << TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING         (1 << TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED       (1 << TIF_NEED_RESCHED)
+#define _TIF_SINGLESTEP         (1 << TIF_SINGLESTEP)
+#define _TIF_IRET               (1 << TIF_IRET)
+#define _TIF_RESTORE_SIGMASK    (1 << TIF_RESTORE_SIGMASK)
+#define _TIF_POLLING_NRFLAG     (1 << TIF_POLLING_NRFLAG)
+
+/* work to do on interrupt/exception return - All but TIF_SYSCALL_TRACE */
+#define _TIF_WORK_MASK          (0x0000FFFF & ~_TIF_SYSCALL_TRACE)
+
+/* work to do on any return to u-space */
+#define _TIF_ALLWORK_MASK       0x0000FFFF
+
+#endif /* __KERNEL__ */
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/time.h linux-libre-3.2-gnu/arch/hexagon/include/asm/time.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/time.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/time.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+#ifndef ASM_TIME_H
+#define ASM_TIME_H
+
+extern cycles_t        pcycle_freq_mhz;
+extern cycles_t        thread_freq_mhz;
+extern cycles_t        sleep_clk_freq;
+
+void setup_percpu_clockdev(void);
+void ipi_timer(void);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/timer-regs.h linux-libre-3.2-gnu/arch/hexagon/include/asm/timer-regs.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/timer-regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/timer-regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,39 @@
+/*
+ * Timer support for Hexagon
+ *
+ * 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.
+ */
+
+#ifndef _ASM_TIMER_REGS_H
+#define _ASM_TIMER_REGS_H
+
+/*  This stuff should go into a platform specific file  */
+#define TCX0_CLK_RATE		19200
+#define TIMER_ENABLE		0
+#define TIMER_CLR_ON_MATCH	1
+
+/*
+ * 8x50 HDD Specs 5-8.  Simulator co-sim not fixed until
+ * release 1.1, and then it's "adjustable" and probably not defaulted.
+ */
+#define RTOS_TIMER_INT		3
+#ifdef CONFIG_HEXAGON_COMET
+#define RTOS_TIMER_REGS_ADDR	0xAB000000UL
+#endif
+#define SLEEP_CLK_RATE		32000
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/timex.h linux-libre-3.2-gnu/arch/hexagon/include/asm/timex.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/timex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/timex.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_TIMEX_H
+#define _ASM_TIMEX_H
+
+#include <asm-generic/timex.h>
+#include <asm/timer-regs.h>
+
+/* Using TCX0 as our clock.  CLOCK_TICK_RATE scheduled to be removed. */
+#define CLOCK_TICK_RATE              TCX0_CLK_RATE
+
+#define ARCH_HAS_READ_CURRENT_TIMER
+
+static inline int read_current_timer(unsigned long *timer_val)
+{
+	*timer_val = (unsigned long) __vmgettime();
+	return 0;
+}
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/tlbflush.h linux-libre-3.2-gnu/arch/hexagon/include/asm/tlbflush.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/tlbflush.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/tlbflush.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,58 @@
+/*
+ * TLB flush support for Hexagon
+ *
+ * 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.
+ */
+
+#ifndef _ASM_TLBFLUSH_H
+#define _ASM_TLBFLUSH_H
+
+#include <linux/mm.h>
+#include <asm/processor.h>
+
+/*
+ * TLB flushing -- in "SMP", these routines get defined to be the
+ * ones from smp.c, else they are some local flavors.
+ */
+
+/*
+ * These functions are commonly macros, but in the interests of
+ * VM vs. native implementation and code size, we simply declare
+ * the function prototypes here.
+ */
+extern void tlb_flush_all(void);
+extern void flush_tlb_mm(struct mm_struct *mm);
+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
+extern void flush_tlb_range(struct vm_area_struct *vma,
+				unsigned long start, unsigned long end);
+extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+extern void flush_tlb_one(unsigned long);
+
+/*
+ * "This is called in munmap when we have freed up some page-table pages.
+ * We don't need to do anything here..."
+ *
+ * The VM kernel doesn't walk page tables, and they are passed to the VMM
+ * by logical address. There doesn't seem to be any possibility that they
+ * could be referenced by the VM kernel based on a stale mapping, since
+ * they would only be located by consulting the mm structure, and they
+ * will have been purged from that structure by the munmap.  Seems like
+ * a noop on HVM as well.
+ */
+#define flush_tlb_pgtables(mm, start, end)
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/tlb.h linux-libre-3.2-gnu/arch/hexagon/include/asm/tlb.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/tlb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/tlb.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_TLB_H
+#define _ASM_TLB_H
+
+#include <linux/pagemap.h>
+#include <asm/tlbflush.h>
+
+/*
+ * We don't need any special per-pte or per-vma handling...
+ */
+#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)
+
+/*
+ * .. because we flush the whole mm when it fills up
+ */
+#define tlb_flush(tlb)		flush_tlb_mm((tlb)->mm)
+
+#include <asm-generic/tlb.h>
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/traps.h linux-libre-3.2-gnu/arch/hexagon/include/asm/traps.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/traps.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/traps.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ * Trap support for Hexagon
+ *
+ * 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.
+ */
+
+#ifndef _ASM_HEXAGON_TRAPS_H
+#define _ASM_HEXAGON_TRAPS_H
+
+#include <asm/registers.h>
+
+extern int die(const char *str, struct pt_regs *regs, long err);
+extern int die_if_kernel(char *str, struct pt_regs *regs, long err);
+
+#endif /* _ASM_HEXAGON_TRAPS_H */
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/uaccess.h linux-libre-3.2-gnu/arch/hexagon/include/asm/uaccess.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/uaccess.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/uaccess.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,116 @@
+/*
+ * User memory access support for Hexagon
+ *
+ * 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.
+ */
+
+#ifndef _ASM_UACCESS_H
+#define _ASM_UACCESS_H
+/*
+ * User space memory access functions
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/segment.h>
+#include <asm/sections.h>
+
+/*
+ * access_ok: - Checks if a user space pointer is valid
+ * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE.  Note that
+ *        %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe
+ *        to write to a block, it is always safe to read from it.
+ * @addr: User space pointer to start of block to check
+ * @size: Size of block to check
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Checks if a pointer to a block of memory in user space is valid.
+ *
+ * Returns true (nonzero) if the memory block *may* be valid, false (zero)
+ * if it is definitely invalid.
+ *
+ * User address space in Hexagon, like x86, goes to 0xbfffffff, so the
+ * simple MSB-based tests used by MIPS won't work.  Some further
+ * optimization is probably possible here, but for now, keep it
+ * reasonably simple and not *too* slow.  After all, we've got the
+ * MMU for backup.
+ */
+#define VERIFY_READ     0
+#define VERIFY_WRITE    1
+
+#define __access_ok(addr, size) \
+	((get_fs().seg == KERNEL_DS.seg) || \
+	(((unsigned long)addr < get_fs().seg) && \
+	  (unsigned long)size < (get_fs().seg - (unsigned long)addr)))
+
+/*
+ * When a kernel-mode page fault is taken, the faulting instruction
+ * address is checked against a table of exception_table_entries.
+ * Each entry is a tuple of the address of an instruction that may
+ * be authorized to fault, and the address at which execution should
+ * be resumed instead of the faulting instruction, so as to effect
+ * a workaround.
+ */
+
+/*  Assembly somewhat optimized copy routines  */
+unsigned long __copy_from_user_hexagon(void *to, const void __user *from,
+				     unsigned long n);
+unsigned long __copy_to_user_hexagon(void __user *to, const void *from,
+				   unsigned long n);
+
+#define __copy_from_user(to, from, n) __copy_from_user_hexagon(to, from, n)
+#define __copy_to_user(to, from, n) __copy_to_user_hexagon(to, from, n)
+
+/*
+ * XXX todo: some additonal performance gain is possible by
+ * implementing __copy_to/from_user_inatomic, which is much
+ * like __copy_to/from_user, but performs slightly less checking.
+ */
+
+__kernel_size_t __clear_user_hexagon(void __user *dest, unsigned long count);
+#define __clear_user(a, s) __clear_user_hexagon((a), (s))
+
+#define __strncpy_from_user(dst, src, n) hexagon_strncpy_from_user(dst, src, n)
+
+/*  get around the ifndef in asm-generic/uaccess.h  */
+#define __strnlen_user __strnlen_user
+
+extern long __strnlen_user(const char __user *src, long n);
+
+static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
+					     long n);
+
+#include <asm-generic/uaccess.h>
+
+/*  Todo:  an actual accelerated version of this.  */
+static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
+					     long n)
+{
+	long res = __strnlen_user(src, n);
+
+	/* return from strnlen can't be zero -- that would be rubbish. */
+
+	if (res > n) {
+		copy_from_user(dst, src, n);
+		return n;
+	} else {
+		copy_from_user(dst, src, res);
+		return res-1;
+	}
+}
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/unistd.h linux-libre-3.2-gnu/arch/hexagon/include/asm/unistd.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/unistd.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,36 @@
+/*
+ * Syscall support for Hexagon
+ *
+ * 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.
+ */
+
+#if !defined(_ASM_HEXAGON_UNISTD_H) || defined(__SYSCALL)
+#define _ASM_HEXAGON_UNISTD_H
+
+/*
+ *  The kernel pulls this unistd.h in three different ways:
+ *  1.  the "normal" way which gets all the __NR defines
+ *  2.  with __SYSCALL defined to produce function declarations
+ *  3.  with __SYSCALL defined to produce syscall table initialization
+ *  See also:  syscalltab.c
+ */
+
+#define sys_mmap2 sys_mmap_pgoff
+
+#include <asm-generic/unistd.h>
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/user.h linux-libre-3.2-gnu/arch/hexagon/include/asm/user.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/user.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/user.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+#ifndef HEXAGON_ASM_USER_H
+#define HEXAGON_ASM_USER_H
+
+/*
+ * Layout for registers passed in elf core dumps to userspace.
+ *
+ * Basically a rearranged subset of "pt_regs".
+ *
+ * Interested parties:  libc, gdb...
+ */
+
+struct user_regs_struct {
+	unsigned long r0;
+	unsigned long r1;
+	unsigned long r2;
+	unsigned long r3;
+	unsigned long r4;
+	unsigned long r5;
+	unsigned long r6;
+	unsigned long r7;
+	unsigned long r8;
+	unsigned long r9;
+	unsigned long r10;
+	unsigned long r11;
+	unsigned long r12;
+	unsigned long r13;
+	unsigned long r14;
+	unsigned long r15;
+	unsigned long r16;
+	unsigned long r17;
+	unsigned long r18;
+	unsigned long r19;
+	unsigned long r20;
+	unsigned long r21;
+	unsigned long r22;
+	unsigned long r23;
+	unsigned long r24;
+	unsigned long r25;
+	unsigned long r26;
+	unsigned long r27;
+	unsigned long r28;
+	unsigned long r29;
+	unsigned long r30;
+	unsigned long r31;
+	unsigned long sa0;
+	unsigned long lc0;
+	unsigned long sa1;
+	unsigned long lc1;
+	unsigned long m0;
+	unsigned long m1;
+	unsigned long usr;
+	unsigned long p3_0;
+	unsigned long gp;
+	unsigned long ugp;
+	unsigned long pc;
+	unsigned long cause;
+	unsigned long badva;
+	unsigned long pad1;  /* pad out to 48 words total */
+	unsigned long pad2;  /* pad out to 48 words total */
+	unsigned long pad3;  /* pad out to 48 words total */
+};
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/vdso.h linux-libre-3.2-gnu/arch/hexagon/include/asm/vdso.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/vdso.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/vdso.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,30 @@
+/*
+ * vDSO implementation for Hexagon
+ *
+ * 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 __ASM_VDSO_H
+#define __ASM_VDSO_H
+
+#include <linux/types.h>
+
+struct hexagon_vdso {
+	u32 rt_signal_trampoline[2];
+};
+
+#endif /* __ASM_VDSO_H */
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/vm_fault.h linux-libre-3.2-gnu/arch/hexagon/include/asm/vm_fault.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/vm_fault.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/vm_fault.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_HEXAGON_VM_FAULT_H
+#define _ASM_HEXAGON_VM_FAULT_H
+
+extern void execute_protection_fault(struct pt_regs *);
+extern void write_protection_fault(struct pt_regs *);
+extern void read_protection_fault(struct pt_regs *);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/include/asm/vm_mmu.h linux-libre-3.2-gnu/arch/hexagon/include/asm/vm_mmu.h
--- linux-libre-3.1-gnu/arch/hexagon/include/asm/vm_mmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/include/asm/vm_mmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,111 @@
+/*
+ * Hexagon VM page table entry definitions
+ *
+ * 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.
+ */
+
+#ifndef _ASM_VM_MMU_H
+#define _ASM_VM_MMU_H
+
+/*
+ * Shift, mask, and other constants for the Hexagon Virtual Machine
+ * page tables.
+ *
+ * Virtual machine MMU allows first-level entries to either be
+ * single-level lookup PTEs for very large pages, or PDEs pointing
+ * to second-level PTEs for smaller pages. If PTE is single-level,
+ * the least significant bits cannot be used as software bits to encode
+ * virtual memory subsystem information about the page, and that state
+ * must be maintained in some parallel data structure.
+ */
+
+/* S or Page Size field in PDE */
+#define	__HVM_PDE_S		(0x7 << 0)
+#define __HVM_PDE_S_4KB		0
+#define __HVM_PDE_S_16KB	1
+#define __HVM_PDE_S_64KB	2
+#define __HVM_PDE_S_256KB	3
+#define __HVM_PDE_S_1MB		4
+#define __HVM_PDE_S_4MB		5
+#define __HVM_PDE_S_16MB	6
+#define __HVM_PDE_S_INVALID	7
+
+/* Masks for L2 page table pointer, as function of page size */
+#define __HVM_PDE_PTMASK_4KB	0xfffff000
+#define __HVM_PDE_PTMASK_16KB	0xfffffc00
+#define __HVM_PDE_PTMASK_64KB	0xffffff00
+#define __HVM_PDE_PTMASK_256KB	0xffffffc0
+#define __HVM_PDE_PTMASK_1MB	0xfffffff0
+
+/*
+ * Virtual Machine PTE Bits/Fields
+ */
+#define __HVM_PTE_T		(1<<4)
+#define __HVM_PTE_U		(1<<5)
+#define	__HVM_PTE_C		(0x7<<6)
+#define __HVM_PTE_CVAL(pte)	(((pte) & __HVM_PTE_C) >> 6)
+#define __HVM_PTE_R		(1<<9)
+#define __HVM_PTE_W		(1<<10)
+#define __HVM_PTE_X		(1<<11)
+
+/*
+ * Cache Attributes, to be shifted as necessary for virtual/physical PTEs
+ */
+
+#define __HEXAGON_C_WB		0x0	/* Write-back, no L2 */
+#define	__HEXAGON_C_WT		0x1	/* Write-through, no L2 */
+#define	__HEXAGON_C_DEV		0x4	/* Device register space */
+#define	__HEXAGON_C_WT_L2	0x5	/* Write-through, with L2 */
+/* this really should be #if CONFIG_HEXAGON_ARCH = 2 but that's not defined */
+#if defined(CONFIG_HEXAGON_COMET) || defined(CONFIG_QDSP6_ST1)
+#define __HEXAGON_C_UNC		__HEXAGON_C_DEV
+#else
+#define	__HEXAGON_C_UNC		0x6	/* Uncached memory */
+#endif
+#define	__HEXAGON_C_WB_L2	0x7	/* Write-back, with L2 */
+
+/*
+ * This can be overriden, but we're defaulting to the most aggressive
+ * cache policy, the better to find bugs sooner.
+ */
+
+#define	CACHE_DEFAULT	__HEXAGON_C_WB_L2
+
+/* Masks for physical page address, as a function of page size */
+
+#define __HVM_PTE_PGMASK_4KB	0xfffff000
+#define __HVM_PTE_PGMASK_16KB	0xffffc000
+#define __HVM_PTE_PGMASK_64KB	0xffff0000
+#define __HVM_PTE_PGMASK_256KB	0xfffc0000
+#define __HVM_PTE_PGMASK_1MB	0xfff00000
+
+/* Masks for single-level large page lookups */
+
+#define __HVM_PTE_PGMASK_4MB	0xffc00000
+#define __HVM_PTE_PGMASK_16MB	0xff000000
+
+/*
+ * "Big kernel page mappings" (see vm_init_segtable.S)
+ * are currently 16MB
+ */
+
+#define BIG_KERNEL_PAGE_SHIFT 24
+#define BIG_KERNEL_PAGE_SIZE (1 << BIG_KERNEL_PAGE_SHIFT)
+
+
+
+#endif /* _ASM_VM_MMU_H */
diff -druN linux-libre-3.1-gnu/arch/hexagon/Kconfig linux-libre-3.2-gnu/arch/hexagon/Kconfig
--- linux-libre-3.1-gnu/arch/hexagon/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,220 @@
+# Hexagon configuration
+comment "Linux Kernel Configuration for Hexagon"
+
+config HEXAGON
+	def_bool y
+	select HAVE_OPROFILE
+	select USE_GENERIC_SMP_HELPERS if SMP
+	# Other pending projects/to-do items.
+	# select HAVE_REGS_AND_STACK_ACCESS_API
+	# select HAVE_HW_BREAKPOINT if PERF_EVENTS
+	# select ARCH_HAS_CPU_IDLE_WAIT
+	# select ARCH_WANT_OPTIONAL_GPIOLIB
+	# select ARCH_REQUIRE_GPIOLIB
+	# select HAVE_CLK
+	# select IRQ_PER_CPU
+	select HAVE_IRQ_WORK
+	# select GENERIC_PENDING_IRQ if SMP
+	select GENERIC_ATOMIC64
+	select HAVE_PERF_EVENTS
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_HARDIRQS_NO__DO_IRQ
+	select GENERIC_HARDIRQS_NO_DEPRECATED
+	# GENERIC_ALLOCATOR is used by dma_alloc_coherent()
+	select GENERIC_ALLOCATOR
+	select GENERIC_IRQ_SHOW
+	select HAVE_ARCH_KGDB
+	select HAVE_ARCH_TRACEHOOK
+	select NO_IOPORT
+	# mostly generic routines, with some accelerated ones
+	---help---
+	  Qualcomm Hexagon is a processor architecture designed for high
+	  performance and low power across a wide variety of applications.
+
+config HEXAGON_ARCH_V1
+	bool
+
+config HEXAGON_ARCH_V2
+	bool
+
+config HEXAGON_ARCH_V3
+	bool
+
+config HEXAGON_ARCH_V4
+	bool
+
+config FRAME_POINTER
+	def_bool y
+
+config LOCKDEP_SUPPORT
+	def_bool y
+
+config PCI
+	def_bool n
+
+config EARLY_PRINTK
+	def_bool y
+
+config KTIME_SCALAR
+	def_bool y
+
+config MMU
+	def_bool y
+
+config TRACE_IRQFLAGS_SUPPORT
+	def_bool y
+
+config GENERIC_CSUM
+	def_bool y
+
+#
+# Use the generic interrupt handling code in kernel/irq/:
+#
+config GENERIC_IRQ_PROBE
+	def_bool y
+
+config GENERIC_IOMAP
+	def_bool y
+
+#config ZONE_DMA
+#	bool
+#	default y
+
+config HAS_DMA
+	bool
+	select HAVE_DMA_ATTRS
+	default y
+
+config NEED_SG_DMA_LENGTH
+	def_bool y
+
+config RWSEM_GENERIC_SPINLOCK
+	def_bool n
+
+config RWSEM_XCHGADD_ALGORITHM
+	def_bool y
+
+config GENERIC_FIND_NEXT_BIT
+	def_bool y
+
+config GENERIC_HWEIGHT
+	def_bool y
+
+config GENERIC_TIME
+	def_bool y
+
+config GENERIC_CLOCKEVENTS
+	def_bool y
+
+config GENERIC_CLOCKEVENTS_BROADCAST
+	def_bool y
+
+config STACKTRACE_SUPPORT
+	def_bool y
+	select STACKTRACE
+
+config GENERIC_BUG
+	def_bool y
+	depends on BUG
+
+config BUG
+	def_bool y
+
+menu "Machine selection"
+
+choice
+	prompt "System type"
+	default HEXAGON_ARCH_V2
+
+config HEXAGON_COMET
+	bool "Comet Board"
+	select HEXAGON_ARCH_V2
+	---help---
+	  Support for the Comet platform.
+
+endchoice
+
+config HEXAGON_VM
+	def_bool y
+
+config CMDLINE
+	string "Default kernel command string"
+	default ""
+	help
+	  On some platforms, there is currently no way for the boot loader
+	  to pass arguments to the kernel. For these, you should supply some
+	  command-line options at build time by entering them here.  At a
+	  minimum, you should specify the memory size and the root device
+	  (e.g., mem=64M root=/dev/nfs).
+
+config HEXAGON_ANGEL_TRAPS
+	bool "Use Angel Traps"
+	default n
+	---help---
+	  Enable angel debug traps (for printk's).
+
+config SMP
+	bool "Multi-Processing support"
+	---help---
+	  Enables SMP support in the kernel.  If unsure, say "Y"
+
+config NR_CPUS
+	int "Maximum number of CPUs" if SMP
+	range 2 6 if SMP
+	default "1" if !SMP
+	default "6" if SMP
+	---help---
+	  This allows you to specify the maximum number of CPUs which this
+	  kernel will support.  The maximum supported value is 6 and the
+	  minimum value which makes sense is 2.
+
+	  This is purely to save memory - each supported CPU adds
+	  approximately eight kilobytes to the kernel image.
+
+choice
+	prompt "Kernel page size"
+	default PAGE_SIZE_4KB
+	---help---
+	  Changes the default page size; use with caution.
+
+config PAGE_SIZE_4KB
+	bool "4KB"
+
+config PAGE_SIZE_16KB
+	bool "16KB"
+
+config PAGE_SIZE_64KB
+	bool "64KB"
+
+config PAGE_SIZE_256KB
+	bool "256KB"
+
+endchoice
+
+source "mm/Kconfig"
+
+source "kernel/Kconfig.hz"
+source "kernel/time/Kconfig"
+
+config GENERIC_GPIO
+	bool "Generic GPIO support"
+	default n
+
+endmenu
+
+source "init/Kconfig"
+source "drivers/Kconfig"
+source "fs/Kconfig"
+
+menu "Executable File Formats"
+source "fs/Kconfig.binfmt"
+endmenu
+
+source "net/Kconfig"
+source "security/Kconfig"
+source "crypto/Kconfig"
+source "lib/Kconfig"
+
+menu "Kernel hacking"
+source "lib/Kconfig.debug"
+endmenu
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/asm-offsets.c linux-libre-3.2-gnu/arch/hexagon/kernel/asm-offsets.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/asm-offsets.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/asm-offsets.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 1996 David S. Miller
+ * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ *
+ * 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/compat.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/kbuild.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+
+/*  This file is used to produce asm/linkerscript constants from header
+    files typically used in c.  Specifically, it generates asm-offsets.h  */
+
+int main(void)
+{
+	COMMENT("This is a comment.");
+	/*  might get these from somewhere else.  */
+	DEFINE(_PAGE_SIZE, PAGE_SIZE);
+	DEFINE(_PAGE_SHIFT, PAGE_SHIFT);
+	BLANK();
+
+	COMMENT("Hexagon pt_regs definitions");
+	OFFSET(_PT_SYSCALL_NR, pt_regs, syscall_nr);
+	OFFSET(_PT_UGPGP, pt_regs, ugpgp);
+	OFFSET(_PT_R3130, pt_regs, r3130);
+	OFFSET(_PT_R2928, pt_regs, r2928);
+	OFFSET(_PT_R2726, pt_regs, r2726);
+	OFFSET(_PT_R2524, pt_regs, r2524);
+	OFFSET(_PT_R2322, pt_regs, r2322);
+	OFFSET(_PT_R2120, pt_regs, r2120);
+	OFFSET(_PT_R1918, pt_regs, r1918);
+	OFFSET(_PT_R1716, pt_regs, r1716);
+	OFFSET(_PT_R1514, pt_regs, r1514);
+	OFFSET(_PT_R1312, pt_regs, r1312);
+	OFFSET(_PT_R1110, pt_regs, r1110);
+	OFFSET(_PT_R0908, pt_regs, r0908);
+	OFFSET(_PT_R0706, pt_regs, r0706);
+	OFFSET(_PT_R0504, pt_regs, r0504);
+	OFFSET(_PT_R0302, pt_regs, r0302);
+	OFFSET(_PT_R0100, pt_regs, r0100);
+	OFFSET(_PT_LC0SA0, pt_regs, lc0sa0);
+	OFFSET(_PT_LC1SA1, pt_regs, lc1sa1);
+	OFFSET(_PT_M1M0, pt_regs, m1m0);
+	OFFSET(_PT_PREDSUSR, pt_regs, predsusr);
+	OFFSET(_PT_EVREC, pt_regs, hvmer);
+	OFFSET(_PT_ER_VMEL, pt_regs, hvmer.vmel);
+	OFFSET(_PT_ER_VMEST, pt_regs, hvmer.vmest);
+	OFFSET(_PT_ER_VMPSP, pt_regs, hvmer.vmpsp);
+	OFFSET(_PT_ER_VMBADVA, pt_regs, hvmer.vmbadva);
+	DEFINE(_PT_REGS_SIZE, sizeof(struct pt_regs));
+	BLANK();
+
+	COMMENT("Hexagon thread_info definitions");
+	OFFSET(_THREAD_INFO_FLAGS, thread_info, flags);
+	OFFSET(_THREAD_INFO_PT_REGS, thread_info, regs);
+	OFFSET(_THREAD_INFO_SP, thread_info, sp);
+	DEFINE(_THREAD_SIZE, THREAD_SIZE);
+	BLANK();
+
+	COMMENT("Hexagon hexagon_switch_stack definitions");
+	OFFSET(_SWITCH_R1716, hexagon_switch_stack, r1716);
+	OFFSET(_SWITCH_R1918, hexagon_switch_stack, r1918);
+	OFFSET(_SWITCH_R2120, hexagon_switch_stack, r2120);
+	OFFSET(_SWITCH_R2322, hexagon_switch_stack, r2322);
+
+	OFFSET(_SWITCH_R2524, hexagon_switch_stack, r2524);
+	OFFSET(_SWITCH_R2726, hexagon_switch_stack, r2726);
+	OFFSET(_SWITCH_FP, hexagon_switch_stack, fp);
+	OFFSET(_SWITCH_LR, hexagon_switch_stack, lr);
+	DEFINE(_SWITCH_STACK_SIZE, sizeof(struct hexagon_switch_stack));
+	BLANK();
+
+	COMMENT("Hexagon task_struct definitions");
+	OFFSET(_TASK_THREAD_INFO, task_struct, stack);
+	OFFSET(_TASK_STRUCT_THREAD, task_struct, thread);
+
+	COMMENT("Hexagon thread_struct definitions");
+	OFFSET(_THREAD_STRUCT_SWITCH_SP, thread_struct, switch_sp);
+
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/dma.c linux-libre-3.2-gnu/arch/hexagon/kernel/dma.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,220 @@
+/*
+ * DMA implementation for Hexagon
+ *
+ * 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/dma-mapping.h>
+#include <linux/bootmem.h>
+#include <linux/genalloc.h>
+#include <asm/dma-mapping.h>
+
+struct dma_map_ops *dma_ops;
+EXPORT_SYMBOL(dma_ops);
+
+int bad_dma_address;  /*  globals are automatically initialized to zero  */
+
+int dma_supported(struct device *dev, u64 mask)
+{
+	if (mask == DMA_BIT_MASK(32))
+		return 1;
+	else
+		return 0;
+}
+EXPORT_SYMBOL(dma_supported);
+
+int dma_set_mask(struct device *dev, u64 mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, mask))
+		return -EIO;
+
+	*dev->dma_mask = mask;
+
+	return 0;
+}
+EXPORT_SYMBOL(dma_set_mask);
+
+static struct gen_pool *coherent_pool;
+
+
+/* Allocates from a pool of uncached memory that was reserved at boot time */
+
+void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
+				 dma_addr_t *dma_addr, gfp_t flag)
+{
+	void *ret;
+
+	if (coherent_pool == NULL) {
+		coherent_pool = gen_pool_create(PAGE_SHIFT, -1);
+
+		if (coherent_pool == NULL)
+			panic("Can't create %s() memory pool!", __func__);
+		else
+			gen_pool_add(coherent_pool,
+				(PAGE_OFFSET + (max_low_pfn << PAGE_SHIFT)),
+				hexagon_coherent_pool_size, -1);
+	}
+
+	ret = (void *) gen_pool_alloc(coherent_pool, size);
+
+	if (ret) {
+		memset(ret, 0, size);
+		*dma_addr = (dma_addr_t) (ret - PAGE_OFFSET);
+	} else
+		*dma_addr = ~0;
+
+	return ret;
+}
+
+static void hexagon_free_coherent(struct device *dev, size_t size, void *vaddr,
+				  dma_addr_t dma_addr)
+{
+	gen_pool_free(coherent_pool, (unsigned long) vaddr, size);
+}
+
+static int check_addr(const char *name, struct device *hwdev,
+		      dma_addr_t bus, size_t size)
+{
+	if (hwdev && hwdev->dma_mask && !dma_capable(hwdev, bus, size)) {
+		if (*hwdev->dma_mask >= DMA_BIT_MASK(32))
+			printk(KERN_ERR
+				"%s: overflow %Lx+%zu of device mask %Lx\n",
+				name, (long long)bus, size,
+				(long long)*hwdev->dma_mask);
+		return 0;
+	}
+	return 1;
+}
+
+static int hexagon_map_sg(struct device *hwdev, struct scatterlist *sg,
+			  int nents, enum dma_data_direction dir,
+			  struct dma_attrs *attrs)
+{
+	struct scatterlist *s;
+	int i;
+
+	WARN_ON(nents == 0 || sg[0].length == 0);
+
+	for_each_sg(sg, s, nents, i) {
+		s->dma_address = sg_phys(s);
+		if (!check_addr("map_sg", hwdev, s->dma_address, s->length))
+			return 0;
+
+		s->dma_length = s->length;
+
+		flush_dcache_range(PAGE_OFFSET + s->dma_address,
+				   PAGE_OFFSET + s->dma_address + s->length);
+	}
+
+	return nents;
+}
+
+/*
+ * address is virtual
+ */
+static inline void dma_sync(void *addr, size_t size,
+			    enum dma_data_direction dir)
+{
+	switch (dir) {
+	case DMA_TO_DEVICE:
+		hexagon_clean_dcache_range((unsigned long) addr,
+		(unsigned long) addr + size);
+		break;
+	case DMA_FROM_DEVICE:
+		hexagon_inv_dcache_range((unsigned long) addr,
+		(unsigned long) addr + size);
+		break;
+	case DMA_BIDIRECTIONAL:
+		flush_dcache_range((unsigned long) addr,
+		(unsigned long) addr + size);
+		break;
+	default:
+		BUG();
+	}
+}
+
+static inline void *dma_addr_to_virt(dma_addr_t dma_addr)
+{
+	return phys_to_virt((unsigned long) dma_addr);
+}
+
+/**
+ * hexagon_map_page() - maps an address for device DMA
+ * @dev:	pointer to DMA device
+ * @page:	pointer to page struct of DMA memory
+ * @offset:	offset within page
+ * @size:	size of memory to map
+ * @dir:	transfer direction
+ * @attrs:	pointer to DMA attrs (not used)
+ *
+ * Called to map a memory address to a DMA address prior
+ * to accesses to/from device.
+ *
+ * We don't particularly have many hoops to jump through
+ * so far.  Straight translation between phys and virtual.
+ *
+ * DMA is not cache coherent so sync is necessary; this
+ * seems to be a convenient place to do it.
+ *
+ */
+static dma_addr_t hexagon_map_page(struct device *dev, struct page *page,
+				   unsigned long offset, size_t size,
+				   enum dma_data_direction dir,
+				   struct dma_attrs *attrs)
+{
+	dma_addr_t bus = page_to_phys(page) + offset;
+	WARN_ON(size == 0);
+
+	if (!check_addr("map_single", dev, bus, size))
+		return bad_dma_address;
+
+	dma_sync(dma_addr_to_virt(bus), size, dir);
+
+	return bus;
+}
+
+static void hexagon_sync_single_for_cpu(struct device *dev,
+					dma_addr_t dma_handle, size_t size,
+					enum dma_data_direction dir)
+{
+	dma_sync(dma_addr_to_virt(dma_handle), size, dir);
+}
+
+static void hexagon_sync_single_for_device(struct device *dev,
+					dma_addr_t dma_handle, size_t size,
+					enum dma_data_direction dir)
+{
+	dma_sync(dma_addr_to_virt(dma_handle), size, dir);
+}
+
+struct dma_map_ops hexagon_dma_ops = {
+	.alloc_coherent	= hexagon_dma_alloc_coherent,
+	.free_coherent	= hexagon_free_coherent,
+	.map_sg		= hexagon_map_sg,
+	.map_page	= hexagon_map_page,
+	.sync_single_for_cpu = hexagon_sync_single_for_cpu,
+	.sync_single_for_device = hexagon_sync_single_for_device,
+	.is_phys	= 1,
+};
+
+void __init hexagon_dma_init(void)
+{
+	if (dma_ops)
+		return;
+
+	dma_ops = &hexagon_dma_ops;
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/head.S linux-libre-3.2-gnu/arch/hexagon/kernel/head.S
--- linux-libre-3.1-gnu/arch/hexagon/kernel/head.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/head.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,162 @@
+/*
+ * Early kernel startup code for Hexagon
+ *
+ * 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/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+#include <asm/mem-layout.h>
+#include <asm/vm_mmu.h>
+#include <asm/page.h>
+
+	__INIT
+ENTRY(stext)
+	/*
+	 * VMM will already have set up true vector page, MMU, etc.
+	 * To set up initial kernel identity map, we have to pass
+	 * the VMM a pointer to some canonical page tables. In
+	 * this implementation, we're assuming that we've got
+	 * them precompiled. Generate value in R24, as we'll need
+	 * it again shortly.
+	 */
+	r24.L = #LO(swapper_pg_dir)
+	r24.H = #HI(swapper_pg_dir)
+
+	/*
+	 * Symbol is kernel segment address, but we need
+	 * the logical/physical address.
+	 */
+	r24 = asl(r24, #2)
+	r24 = lsr(r24, #2)
+
+	r0 = r24
+
+	/*
+	 * Initialize a 16MB PTE to make the virtual and physical
+	 * addresses where the kernel was loaded be identical.
+	 */
+#define PTE_BITS ( __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X	\
+		  | __HEXAGON_C_WB_L2 << 6			\
+		  | __HVM_PDE_S_4MB)
+
+	r1 = pc
+	r2.H = #0xffc0
+	r2.L = #0x0000
+	r1 = and(r1,r2)		/* round PC to 4MB boundary	*/
+	r2 = lsr(r1, #22)	/* 4MB page number		*/
+	r2 = asl(r2, #2)	/* times sizeof(PTE) (4bytes)	*/
+	r0 = add(r0,r2)		/* r0 = address of correct PTE	*/
+	r2 = #PTE_BITS
+	r1 = add(r1,r2)		/* r1 = 4MB PTE for the first entry	*/
+	r2.h = #0x0040
+	r2.l = #0x0000		/* 4MB	*/
+	memw(r0 ++ #4) = r1
+	r1 = add(r1, r2)
+	memw(r0 ++ #4) = r1
+
+	r0 = r24
+
+	/*
+	 * The subroutine wrapper around the virtual instruction touches
+	 * no memory, so we should be able to use it even here.
+	 */
+	call	__vmnewmap;
+
+	/*  Jump into virtual address range.  */
+
+	r31.h = #hi(__head_s_vaddr_target)
+	r31.l = #lo(__head_s_vaddr_target)
+	jumpr r31
+
+	/*  Insert trippy space effects.  */
+
+__head_s_vaddr_target:
+	/*
+	 * Tear down VA=PA translation now that we are running
+	 * in the desgnated kernel segments.
+	 */
+	r0 = #__HVM_PDE_S_INVALID
+	r1 = r24
+	loop0(1f,#0x100)
+1:
+	{
+		memw(R1 ++ #4) = R0
+	}:endloop0
+
+	r0 = r24
+	call __vmnewmap
+
+	/*  Go ahead and install the trap0 return so angel calls work  */
+	r0.h = #hi(_K_provisional_vec)
+	r0.l = #lo(_K_provisional_vec)
+	call __vmsetvec
+
+	/*
+	 * OK, at this point we should start to be much more careful,
+	 * we're going to enter C code and start touching memory
+	 * in all sorts of places.
+	 * This means:
+	 *      SGP needs to be OK
+	 *	Need to lock shared resources
+	 *	A bunch of other things that will cause
+	 * 	all kinds of painful bugs
+	 */
+
+	/*
+	 * Stack pointer should be pointed at the init task's
+	 * thread stack, which should have been declared in arch/init_task.c.
+	 * So uhhhhh...
+	 * It's accessible via the init_thread_union, which is a union
+	 * of a thread_info struct and a stack; of course, the top
+	 * of the stack is not for you.  The end of the stack
+	 * is simply init_thread_union + THREAD_SIZE.
+	 */
+
+	{r29.H = #HI(init_thread_union); r0.H = #HI(_THREAD_SIZE); }
+	{r29.L = #LO(init_thread_union); r0.L = #LO(_THREAD_SIZE); }
+
+	/*  initialize the register used to point to current_thread_info */
+	/*  Fixme:  THREADINFO_REG can't be R2 because of that memset thing. */
+	{r29 = add(r29,r0); THREADINFO_REG = r29; }
+
+	/*  Hack:  zero bss; */
+	{ r0.L = #LO(__bss_start);  r1 = #0; r2.l = #LO(__bss_stop); }
+	{ r0.H = #HI(__bss_start);           r2.h = #HI(__bss_stop); }
+
+	r2 = sub(r2,r0);
+	call memset;
+
+	/* Time to make the doughnuts.   */
+	call start_kernel
+
+	/*
+	 * Should not reach here.
+	 */
+1:
+	jump 1b
+
+.p2align PAGE_SHIFT
+ENTRY(external_cmdline_buffer)
+        .fill _PAGE_SIZE,1,0
+
+.data
+.p2align PAGE_SHIFT
+ENTRY(empty_zero_page)
+        .fill _PAGE_SIZE,1,0
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/hexagon_ksyms.c linux-libre-3.2-gnu/arch/hexagon/kernel/hexagon_ksyms.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/hexagon_ksyms.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/hexagon_ksyms.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,40 @@
+/*
+ * Export of symbols defined in assembly files and/or libgcc.
+ *
+ * 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 <asm/hexagon_vm.h>
+#include <asm/uaccess.h>
+
+EXPORT_SYMBOL(__copy_from_user_hexagon);
+EXPORT_SYMBOL(__copy_to_user_hexagon);
+EXPORT_SYMBOL(__vmgetie);
+EXPORT_SYMBOL(__vmsetie);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+
+#define DECLARE_EXPORT(name)     \
+	extern void name(void); EXPORT_SYMBOL(name)
+
+/* Symbols found in libgcc that assorted kernel modules need */
+DECLARE_EXPORT(__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes);
+
+DECLARE_EXPORT(__hexagon_divsi3);
+DECLARE_EXPORT(__hexagon_modsi3);
+DECLARE_EXPORT(__hexagon_udivsi3);
+DECLARE_EXPORT(__hexagon_umodsi3);
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/init_task.c linux-libre-3.2-gnu/arch/hexagon/kernel/init_task.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/init_task.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/init_task.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,54 @@
+/*
+ * Init task definition
+ *
+ * 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/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init_task.h>
+#include <linux/fs.h>
+#include <linux/mqueue.h>
+#include <asm/thread_info.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 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.
+ */
+union thread_union init_thread_union
+	__attribute__((__section__(".data.init_task"),
+		__aligned__(THREAD_SIZE))) = {
+			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-3.1-gnu/arch/hexagon/kernel/irq_cpu.c linux-libre-3.2-gnu/arch/hexagon/kernel/irq_cpu.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/irq_cpu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/irq_cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,90 @@
+/*
+ * First-level interrupt controller model for Hexagon.
+ *
+ * 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/interrupt.h>
+#include <asm/irq.h>
+#include <asm/hexagon_vm.h>
+
+static void mask_irq(struct irq_data *data)
+{
+	__vmintop_locdis((long) data->irq);
+}
+
+static void mask_irq_num(unsigned int irq)
+{
+	__vmintop_locdis((long) irq);
+}
+
+static void unmask_irq(struct irq_data *data)
+{
+	__vmintop_locen((long) data->irq);
+}
+
+/*  This is actually all we need for handle_fasteoi_irq  */
+static void eoi_irq(struct irq_data *data)
+{
+	__vmintop_globen((long) data->irq);
+}
+
+/* Power mamangement wake call. We don't need this, however,
+ * if this is absent, then an -ENXIO error is returned to the
+ * msm_serial driver, and it fails to correctly initialize.
+ * This is a bug in the msm_serial driver, but, for now, we
+ * work around it here, by providing this bogus handler.
+ * XXX FIXME!!! remove this when msm_serial is fixed.
+ */
+static int set_wake(struct irq_data *data, unsigned int on)
+{
+	return 0;
+}
+
+static struct irq_chip hexagon_irq_chip = {
+	.name		= "HEXAGON",
+	.irq_mask	= mask_irq,
+	.irq_unmask	= unmask_irq,
+	.irq_set_wake	= set_wake,
+	.irq_eoi	= eoi_irq
+};
+
+/**
+ * The hexagon core comes with a first-level interrupt controller
+ * with 32 total possible interrupts.  When the core is embedded
+ * into different systems/platforms, it is typically wrapped by
+ * macro cells that provide one or more second-level interrupt
+ * controllers that are cascaded into one or more of the first-level
+ * interrupts handled here. The precise wiring of these other
+ * irqs varies from platform to platform, and are set up & configured
+ * in the platform-specific files.
+ *
+ * The first-level interrupt controller is wrapped by the VM, which
+ * virtualizes the interrupt controller for us.  It provides a very
+ * simple, fast & efficient API, and so the fasteoi handler is
+ * appropriate for this case.
+ */
+void __init init_IRQ(void)
+{
+	int irq;
+
+	for (irq = 0; irq < HEXAGON_CPUINTS; irq++) {
+		mask_irq_num(irq);
+		irq_set_chip_and_handler(irq, &hexagon_irq_chip,
+						 handle_fasteoi_irq);
+	}
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/kgdb.c linux-libre-3.2-gnu/arch/hexagon/kernel/kgdb.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/kgdb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/kgdb.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,254 @@
+/*
+ * arch/hexagon/kernel/kgdb.c - Hexagon KGDB Support
+ *
+ * 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/kdebug.h>
+#include <linux/kgdb.h>
+
+/* All registers are 4 bytes, for now */
+#define GDB_SIZEOF_REG 4
+
+/* The register names are used during printing of the regs;
+ * Keep these at three letters to pretty-print. */
+struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
+	{ " r0", GDB_SIZEOF_REG, offsetof(struct pt_regs, r00)},
+	{ " r1", GDB_SIZEOF_REG, offsetof(struct pt_regs, r01)},
+	{ " r2", GDB_SIZEOF_REG, offsetof(struct pt_regs, r02)},
+	{ " r3", GDB_SIZEOF_REG, offsetof(struct pt_regs, r03)},
+	{ " r4", GDB_SIZEOF_REG, offsetof(struct pt_regs, r04)},
+	{ " r5", GDB_SIZEOF_REG, offsetof(struct pt_regs, r05)},
+	{ " r6", GDB_SIZEOF_REG, offsetof(struct pt_regs, r06)},
+	{ " r7", GDB_SIZEOF_REG, offsetof(struct pt_regs, r07)},
+	{ " r8", GDB_SIZEOF_REG, offsetof(struct pt_regs, r08)},
+	{ " r9", GDB_SIZEOF_REG, offsetof(struct pt_regs, r09)},
+	{ "r10", GDB_SIZEOF_REG, offsetof(struct pt_regs, r10)},
+	{ "r11", GDB_SIZEOF_REG, offsetof(struct pt_regs, r11)},
+	{ "r12", GDB_SIZEOF_REG, offsetof(struct pt_regs, r12)},
+	{ "r13", GDB_SIZEOF_REG, offsetof(struct pt_regs, r13)},
+	{ "r14", GDB_SIZEOF_REG, offsetof(struct pt_regs, r14)},
+	{ "r15", GDB_SIZEOF_REG, offsetof(struct pt_regs, r15)},
+	{ "r16", GDB_SIZEOF_REG, offsetof(struct pt_regs, r16)},
+	{ "r17", GDB_SIZEOF_REG, offsetof(struct pt_regs, r17)},
+	{ "r18", GDB_SIZEOF_REG, offsetof(struct pt_regs, r18)},
+	{ "r19", GDB_SIZEOF_REG, offsetof(struct pt_regs, r19)},
+	{ "r20", GDB_SIZEOF_REG, offsetof(struct pt_regs, r20)},
+	{ "r21", GDB_SIZEOF_REG, offsetof(struct pt_regs, r21)},
+	{ "r22", GDB_SIZEOF_REG, offsetof(struct pt_regs, r22)},
+	{ "r23", GDB_SIZEOF_REG, offsetof(struct pt_regs, r23)},
+	{ "r24", GDB_SIZEOF_REG, offsetof(struct pt_regs, r24)},
+	{ "r25", GDB_SIZEOF_REG, offsetof(struct pt_regs, r25)},
+	{ "r26", GDB_SIZEOF_REG, offsetof(struct pt_regs, r26)},
+	{ "r27", GDB_SIZEOF_REG, offsetof(struct pt_regs, r27)},
+	{ "r28", GDB_SIZEOF_REG, offsetof(struct pt_regs, r28)},
+	{ "r29", GDB_SIZEOF_REG, offsetof(struct pt_regs, r29)},
+	{ "r30", GDB_SIZEOF_REG, offsetof(struct pt_regs, r30)},
+	{ "r31", GDB_SIZEOF_REG, offsetof(struct pt_regs, r31)},
+
+	{ "usr", GDB_SIZEOF_REG, offsetof(struct pt_regs, usr)},
+	{ "preds", GDB_SIZEOF_REG, offsetof(struct pt_regs, preds)},
+	{ " m0", GDB_SIZEOF_REG, offsetof(struct pt_regs, m0)},
+	{ " m1", GDB_SIZEOF_REG, offsetof(struct pt_regs, m1)},
+	{ "sa0", GDB_SIZEOF_REG, offsetof(struct pt_regs, sa0)},
+	{ "sa1", GDB_SIZEOF_REG, offsetof(struct pt_regs, sa1)},
+	{ "lc0", GDB_SIZEOF_REG, offsetof(struct pt_regs, lc0)},
+	{ "lc1", GDB_SIZEOF_REG, offsetof(struct pt_regs, lc1)},
+	{ " gp", GDB_SIZEOF_REG, offsetof(struct pt_regs, gp)},
+	{ "ugp", GDB_SIZEOF_REG, offsetof(struct pt_regs, ugp)},
+	{ "psp", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmpsp)},
+	{ "elr", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmel)},
+	{ "est", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmest)},
+	{ "badva", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmbadva)},
+	{ "restart_r0", GDB_SIZEOF_REG, offsetof(struct pt_regs, restart_r0)},
+	{ "syscall_nr", GDB_SIZEOF_REG, offsetof(struct pt_regs, syscall_nr)},
+};
+
+struct kgdb_arch arch_kgdb_ops = {
+	/* trap0(#0xDB) 0x0cdb0054 */
+	.gdb_bpt_instr = {0x54, 0x00, 0xdb, 0x0c},
+};
+
+char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
+{
+	if (regno >= DBG_MAX_REG_NUM || regno < 0)
+		return NULL;
+
+	*((unsigned long *) mem) = *((unsigned long *) ((void *)regs +
+		dbg_reg_def[regno].offset));
+
+	return dbg_reg_def[regno].name;
+}
+
+int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
+{
+	if (regno >= DBG_MAX_REG_NUM || regno < 0)
+		return -EINVAL;
+
+	*((unsigned long *) ((void *)regs + dbg_reg_def[regno].offset)) =
+		*((unsigned long *) mem);
+
+	return 0;
+}
+
+void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
+{
+	instruction_pointer(regs) = pc;
+}
+
+#ifdef CONFIG_SMP
+
+/**
+ * kgdb_roundup_cpus - Get other CPUs into a holding pattern
+ * @flags: Current IRQ state
+ *
+ * On SMP systems, we need to get the attention of the other CPUs
+ * and get them be in a known state.  This should do what is needed
+ * to get the other CPUs to call kgdb_wait(). Note that on some arches,
+ * the NMI approach is not used for rounding up all the CPUs. For example,
+ * in case of MIPS, smp_call_function() is used to roundup CPUs. In
+ * this case, we have to make sure that interrupts are enabled before
+ * calling smp_call_function(). The argument to this function is
+ * the flags that will be used when restoring the interrupts. There is
+ * local_irq_save() call before kgdb_roundup_cpus().
+ *
+ * On non-SMP systems, this is not called.
+ */
+
+static void hexagon_kgdb_nmi_hook(void *ignored)
+{
+	kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
+}
+
+void kgdb_roundup_cpus(unsigned long flags)
+{
+	local_irq_enable();
+	smp_call_function(hexagon_kgdb_nmi_hook, NULL, 0);
+	local_irq_disable();
+}
+#endif
+
+
+/*  Not yet working  */
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs,
+				 struct task_struct *task)
+{
+	struct pt_regs *thread_regs;
+
+	if (task == NULL)
+		return;
+
+	/* Initialize to zero */
+	memset(gdb_regs, 0, NUMREGBYTES);
+
+	/* Otherwise, we have only some registers from switch_to() */
+	thread_regs = task_pt_regs(task);
+	gdb_regs[0] = thread_regs->r00;
+}
+
+/**
+ * kgdb_arch_handle_exception - Handle architecture specific GDB packets.
+ * @vector: The error vector of the exception that happened.
+ * @signo: The signal number of the exception that happened.
+ * @err_code: The error code of the exception that happened.
+ * @remcom_in_buffer: The buffer of the packet we have read.
+ * @remcom_out_buffer: The buffer of %BUFMAX bytes to write a packet into.
+ * @regs: The &struct pt_regs of the current process.
+ *
+ * This function MUST handle the 'c' and 's' command packets,
+ * as well packets to set / remove a hardware breakpoint, if used.
+ * If there are additional packets which the hardware needs to handle,
+ * they are handled here.  The code should return -1 if it wants to
+ * process more packets, and a %0 or %1 if it wants to exit from the
+ * kgdb callback.
+ *
+ * Not yet working.
+ */
+int kgdb_arch_handle_exception(int vector, int signo, int err_code,
+			       char *remcom_in_buffer, char *remcom_out_buffer,
+			       struct pt_regs *linux_regs)
+{
+	switch (remcom_in_buffer[0]) {
+	case 's':
+	case 'c':
+		return 0;
+	}
+	/* Stay in the debugger. */
+	return -1;
+}
+
+static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+{
+	/* cpu roundup */
+	if (atomic_read(&kgdb_active) != -1) {
+		kgdb_nmicallback(smp_processor_id(), args->regs);
+		return NOTIFY_STOP;
+	}
+
+	if (user_mode(args->regs))
+		return NOTIFY_DONE;
+
+	if (kgdb_handle_exception(args->trapnr & 0xff, args->signr, args->err,
+				    args->regs))
+		return NOTIFY_DONE;
+
+	return NOTIFY_STOP;
+}
+
+static int
+kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
+{
+	unsigned long flags;
+	int ret;
+
+	local_irq_save(flags);
+	ret = __kgdb_notify(ptr, cmd);
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static struct notifier_block kgdb_notifier = {
+	.notifier_call = kgdb_notify,
+
+	/*
+	 * Lowest-prio notifier priority, we want to be notified last:
+	 */
+	.priority = -INT_MAX,
+};
+
+/**
+ * kgdb_arch_init - Perform any architecture specific initalization.
+ *
+ * This function will handle the initalization of any architecture
+ * specific callbacks.
+ */
+int kgdb_arch_init(void)
+{
+	return register_die_notifier(&kgdb_notifier);
+}
+
+/**
+ * kgdb_arch_exit - Perform any architecture specific uninitalization.
+ *
+ * This function will handle the uninitalization of any architecture
+ * specific callbacks, for dynamic registration and unregistration.
+ */
+void kgdb_arch_exit(void)
+{
+	unregister_die_notifier(&kgdb_notifier);
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/Makefile linux-libre-3.2-gnu/arch/hexagon/kernel/Makefile
--- linux-libre-3.1-gnu/arch/hexagon/kernel/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+extra-y := head.o vmlinux.lds init_task.o
+
+obj-$(CONFIG_SMP) += smp.o topology.o
+
+obj-y += setup.o irq_cpu.o traps.o syscalltab.o signal.o time.o
+obj-y += process.o syscall.o trampoline.o reset.o ptrace.o
+obj-y += vdso.o
+
+obj-$(CONFIG_KGDB)    += kgdb.o
+obj-$(CONFIG_MODULES) += module.o hexagon_ksyms.o
+
+# Modules required to work with the Hexagon Virtual Machine
+obj-y += vm_entry.o vm_events.o vm_switch.o vm_ops.o vm_init_segtable.o
+obj-y += vm_vectors.o
+
+obj-$(CONFIG_HAS_DMA) += dma.o
+
+obj-$(CONFIG_STACKTRACE) += stacktrace.o
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/module.c linux-libre-3.2-gnu/arch/hexagon/kernel/module.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/module.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/module.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,162 @@
+/*
+ * Kernel module loader for Hexagon
+ *
+ * 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 <asm/module.h>
+#include <linux/elf.h>
+#include <linux/module.h>
+#include <linux/moduleloader.h>
+#include <linux/vmalloc.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt , ...)
+#endif
+
+/*
+ * module_frob_arch_sections - tweak got/plt sections.
+ * @hdr - pointer to elf header
+ * @sechdrs - pointer to elf load section headers
+ * @secstrings - symbol names
+ * @mod - pointer to module
+ */
+int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
+				char *secstrings,
+				struct module *mod)
+{
+	unsigned int i;
+	int found = 0;
+
+	/* Look for .plt and/or .got.plt and/or .init.plt sections */
+	for (i = 0; i < hdr->e_shnum; i++) {
+		DEBUGP("Section %d is %s\n", i,
+		       secstrings + sechdrs[i].sh_name);
+		if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0)
+			found = i+1;
+		if (strcmp(secstrings + sechdrs[i].sh_name, ".got.plt") == 0)
+			found = i+1;
+		if (strcmp(secstrings + sechdrs[i].sh_name, ".rela.plt") == 0)
+			found = i+1;
+	}
+
+	/* At this time, we don't support modules comiled with -shared */
+	if (found) {
+		printk(KERN_WARNING
+			"Module '%s' contains unexpected .plt/.got sections.\n",
+			mod->name);
+		/*  return -ENOEXEC;  */
+	}
+
+	return 0;
+}
+
+/*
+ * apply_relocate_add - perform rela relocations.
+ * @sechdrs - pointer to section headers
+ * @strtab - some sort of start address?
+ * @symindex - symbol index offset or something?
+ * @relsec - address to relocate to?
+ * @module - pointer to module
+ *
+ * Perform rela relocations.
+ */
+int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
+			unsigned int symindex, unsigned int relsec,
+			struct module *module)
+{
+	unsigned int i;
+	Elf32_Sym *sym;
+	uint32_t *location;
+	uint32_t value;
+	unsigned int nrelocs = sechdrs[relsec].sh_size / sizeof(Elf32_Rela);
+	Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Word sym_info = sechdrs[relsec].sh_info;
+	Elf32_Sym *sym_base = (Elf32_Sym *) sechdrs[symindex].sh_addr;
+	void *loc_base = (void *) sechdrs[sym_info].sh_addr;
+
+	DEBUGP("Applying relocations in section %u to section %u base=%p\n",
+	       relsec, sym_info, loc_base);
+
+	for (i = 0; i < nrelocs; i++) {
+
+		/* Symbol to relocate */
+		sym = sym_base + ELF32_R_SYM(rela[i].r_info);
+
+		/* Where to make the change */
+		location = loc_base + rela[i].r_offset;
+
+		/* `Everything is relative'. */
+		value = sym->st_value + rela[i].r_addend;
+
+		DEBUGP("%d: value=%08x loc=%p reloc=%d symbol=%s\n",
+		       i, value, location, ELF32_R_TYPE(rela[i].r_info),
+		       sym->st_name ?
+		       &strtab[sym->st_name] : "(anonymous)");
+
+		switch (ELF32_R_TYPE(rela[i].r_info)) {
+		case R_HEXAGON_B22_PCREL: {
+			int dist = (int)(value - (uint32_t)location);
+			if ((dist < -0x00800000) ||
+			    (dist >= 0x00800000)) {
+				printk(KERN_ERR
+				       "%s: %s: %08x=%08x-%08x %s\n",
+				       module->name,
+				       "R_HEXAGON_B22_PCREL reloc out of range",
+				       dist, value, (uint32_t)location,
+				       sym->st_name ?
+				       &strtab[sym->st_name] : "(anonymous)");
+				return -ENOEXEC;
+			}
+			DEBUGP("B22_PCREL contents: %08X.\n", *location);
+			*location &= ~0x01ff3fff;
+			*location |= 0x00003fff & dist;
+			*location |= 0x01ff0000 & (dist<<2);
+			DEBUGP("Contents after reloc: %08x\n", *location);
+			break;
+		}
+		case R_HEXAGON_HI16:
+			value = (value>>16) & 0xffff;
+			/* fallthrough */
+		case R_HEXAGON_LO16:
+			*location &= ~0x00c03fff;
+			*location |= value & 0x3fff;
+			*location |= (value & 0xc000) << 8;
+			break;
+		case R_HEXAGON_32:
+			*location = value;
+			break;
+		case R_HEXAGON_32_PCREL:
+			*location = value - (uint32_t)location;
+			break;
+		case R_HEXAGON_PLT_B22_PCREL:
+		case R_HEXAGON_GOTOFF_LO16:
+		case R_HEXAGON_GOTOFF_HI16:
+			printk(KERN_ERR "%s: GOT/PLT relocations unsupported\n",
+			       module->name);
+			return -ENOEXEC;
+		default:
+			printk(KERN_ERR "%s: unknown relocation: %u\n",
+			       module->name,
+			       ELF32_R_TYPE(rela[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/process.c linux-libre-3.2-gnu/arch/hexagon/kernel/process.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/process.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,279 @@
+/*
+ * Process creation support for Hexagon
+ *
+ * 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/sched.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/tick.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+
+/*
+ * Kernel thread creation.  The desired kernel function is "wrapped"
+ * in the kernel_thread_helper function, which does cleanup
+ * afterwards.
+ */
+static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *))
+{
+	do_exit(fn(arg));
+}
+
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+	struct pt_regs regs;
+
+	memset(&regs, 0, sizeof(regs));
+	/*
+	 * Yes, we're exploting illicit knowledge of the ABI here.
+	 */
+	regs.r00 = (unsigned long) arg;
+	regs.r01 = (unsigned long) fn;
+	pt_set_elr(&regs, (unsigned long)kernel_thread_helper);
+	pt_set_kmode(&regs);
+
+	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+}
+EXPORT_SYMBOL(kernel_thread);
+
+/*
+ * Program thread launch.  Often defined as a macro in processor.h,
+ * but we're shooting for a small footprint and it's not an inner-loop
+ * performance-critical operation.
+ *
+ * The Hexagon ABI specifies that R28 is zero'ed before program launch,
+ * so that gets automatically done here.  If we ever stop doing that here,
+ * we'll probably want to define the ELF_PLAT_INIT macro.
+ */
+void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
+{
+	/* Set to run with user-mode data segmentation */
+	set_fs(USER_DS);
+	/* We want to zero all data-containing registers. Is this overkill? */
+	memset(regs, 0, sizeof(*regs));
+	/* We might want to also zero all Processor registers here */
+	pt_set_usermode(regs);
+	pt_set_elr(regs, pc);
+	pt_set_rte_sp(regs, sp);
+}
+
+/*
+ *  Spin, or better still, do a hardware or VM wait instruction
+ *  If hardware or VM offer wait termination even though interrupts
+ *  are disabled.
+ */
+static void default_idle(void)
+{
+	__vmwait();
+}
+
+void (*idle_sleep)(void) = default_idle;
+
+void cpu_idle(void)
+{
+	while (1) {
+		tick_nohz_stop_sched_tick(1);
+		local_irq_disable();
+		while (!need_resched()) {
+			idle_sleep();
+			/*  interrupts wake us up, but aren't serviced  */
+			local_irq_enable();	/* service interrupt   */
+			local_irq_disable();
+		}
+		local_irq_enable();
+		tick_nohz_restart_sched_tick();
+		schedule();
+	}
+}
+
+/*
+ *  Return saved PC of a blocked thread
+ */
+unsigned long thread_saved_pc(struct task_struct *tsk)
+{
+	return 0;
+}
+
+/*
+ * Copy architecture-specific thread state
+ */
+int copy_thread(unsigned long clone_flags, unsigned long usp,
+		unsigned long unused, struct task_struct *p,
+		struct pt_regs *regs)
+{
+	struct thread_info *ti = task_thread_info(p);
+	struct hexagon_switch_stack *ss;
+	struct pt_regs *childregs;
+	asmlinkage void ret_from_fork(void);
+
+	childregs = (struct pt_regs *) (((unsigned long) ti + THREAD_SIZE) -
+					sizeof(*childregs));
+
+	memcpy(childregs, regs, sizeof(*childregs));
+	ti->regs = childregs;
+
+	/*
+	 * Establish kernel stack pointer and initial PC for new thread
+	 */
+	ss = (struct hexagon_switch_stack *) ((unsigned long) childregs -
+						    sizeof(*ss));
+	ss->lr = (unsigned long)ret_from_fork;
+	p->thread.switch_sp = ss;
+
+	/* If User mode thread, set pt_reg stack pointer as per parameter */
+	if (user_mode(childregs)) {
+		pt_set_rte_sp(childregs, usp);
+
+		/* Child sees zero return value */
+		childregs->r00 = 0;
+
+		/*
+		 * The clone syscall has the C signature:
+		 * int [r0] clone(int flags [r0],
+		 *           void *child_frame [r1],
+		 *           void *parent_tid [r2],
+		 *           void *child_tid [r3],
+		 *           void *thread_control_block [r4]);
+		 * ugp is used to provide TLS support.
+		 */
+		if (clone_flags & CLONE_SETTLS)
+			childregs->ugp = childregs->r04;
+
+		/*
+		 * Parent sees new pid -- not necessary, not even possible at
+		 * this point in the fork process
+		 * Might also want to set things like ti->addr_limit
+		 */
+	} else {
+		/*
+		 * If kernel thread, resume stack is kernel stack base.
+		 * Note that this is pointer arithmetic on pt_regs *
+		 */
+		pt_set_rte_sp(childregs, (unsigned long)(childregs + 1));
+		/*
+		 * We need the current thread_info fast path pointer
+		 * set up in pt_regs.  The register to be used is
+		 * parametric for assembler code, but the mechanism
+		 * doesn't drop neatly into C.  Needs to be fixed.
+		 */
+		childregs->THREADINFO_REG = (unsigned long) ti;
+	}
+
+	/*
+	 * thread_info pointer is pulled out of task_struct "stack"
+	 * field on switch_to.
+	 */
+	p->stack = (void *)ti;
+
+	return 0;
+}
+
+/*
+ * Release any architecture-specific resources locked by thread
+ */
+void release_thread(struct task_struct *dead_task)
+{
+}
+
+/*
+ * Free any architecture-specific thread data structures, etc.
+ */
+void exit_thread(void)
+{
+}
+
+/*
+ * Some archs flush debug and FPU info here
+ */
+void flush_thread(void)
+{
+}
+
+/*
+ * The "wait channel" terminology is archaic, but what we want
+ * is an identification of the point at which the scheduler
+ * was invoked by a blocked thread.
+ */
+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 hexagon_switch_stack *)p->thread.switch_sp)->fp;
+	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;
+}
+
+/*
+ * Borrowed from PowerPC -- basically allow smaller kernel stacks if we
+ * go crazy with the page sizes.
+ */
+#if THREAD_SHIFT < PAGE_SHIFT
+
+static struct kmem_cache *thread_info_cache;
+
+struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node)
+{
+	struct thread_info *ti;
+
+	ti = kmem_cache_alloc_node(thread_info_cache, GFP_KERNEL, node);
+	if (unlikely(ti == NULL))
+		return NULL;
+#ifdef CONFIG_DEBUG_STACK_USAGE
+	memset(ti, 0, THREAD_SIZE);
+#endif
+	return ti;
+}
+
+void free_thread_info(struct thread_info *ti)
+{
+	kmem_cache_free(thread_info_cache, ti);
+}
+
+/*  Weak symbol; called by init/main.c  */
+
+void thread_info_cache_init(void)
+{
+	thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
+					      THREAD_SIZE, 0, NULL);
+	BUG_ON(thread_info_cache == NULL);
+}
+
+#endif /* THREAD_SHIFT < PAGE_SHIFT */
+
+/*
+ * Required placeholder.
+ */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
+{
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/ptrace.c linux-libre-3.2-gnu/arch/hexagon/kernel/ptrace.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/ptrace.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/ptrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,180 @@
+/*
+ * Ptrace support for Hexagon
+ *
+ * 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 <generated/compile.h>
+
+#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/regset.h>
+#include <linux/user.h>
+
+#include <asm/system.h>
+#include <asm/user.h>
+
+static int genregs_get(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	int ret;
+	unsigned int dummy;
+	struct pt_regs *regs = task_pt_regs(target);
+
+
+	if (!regs)
+		return -EIO;
+
+	/* The general idea here is that the copyout must happen in
+	 * exactly the same order in which the userspace expects these
+	 * regs. Now, the sequence in userspace does not match the
+	 * sequence in the kernel, so everything past the 32 gprs
+	 * happens one at a time.
+	 */
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  &regs->r00, 0, 32*sizeof(unsigned long));
+
+#define ONEXT(KPT_REG, USR_REG) \
+	if (!ret) \
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, \
+			KPT_REG, offsetof(struct user_regs_struct, USR_REG), \
+			offsetof(struct user_regs_struct, USR_REG) + \
+				 sizeof(unsigned long));
+
+	/* Must be exactly same sequence as struct user_regs_struct */
+	ONEXT(&regs->sa0, sa0);
+	ONEXT(&regs->lc0, lc0);
+	ONEXT(&regs->sa1, sa1);
+	ONEXT(&regs->lc1, lc1);
+	ONEXT(&regs->m0, m0);
+	ONEXT(&regs->m1, m1);
+	ONEXT(&regs->usr, usr);
+	ONEXT(&regs->preds, p3_0);
+	ONEXT(&regs->gp, gp);
+	ONEXT(&regs->ugp, ugp);
+	ONEXT(&pt_elr(regs), pc);
+	dummy = pt_cause(regs);
+	ONEXT(&dummy, cause);
+	ONEXT(&pt_badva(regs), badva);
+
+	/* Pad the rest with zeros, if needed */
+	if (!ret)
+		ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+					offsetof(struct user_regs_struct, pad1), -1);
+	return ret;
+}
+
+static int genregs_set(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+	unsigned long bucket;
+	struct pt_regs *regs = task_pt_regs(target);
+
+	if (!regs)
+		return -EIO;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &regs->r00, 0, 32*sizeof(unsigned long));
+
+#define INEXT(KPT_REG, USR_REG) \
+	if (!ret) \
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
+			KPT_REG, offsetof(struct user_regs_struct, USR_REG), \
+			offsetof(struct user_regs_struct, USR_REG) + \
+				sizeof(unsigned long));
+
+	/* Must be exactly same sequence as struct user_regs_struct */
+	INEXT(&regs->sa0, sa0);
+	INEXT(&regs->lc0, lc0);
+	INEXT(&regs->sa1, sa1);
+	INEXT(&regs->lc1, lc1);
+	INEXT(&regs->m0, m0);
+	INEXT(&regs->m1, m1);
+	INEXT(&regs->usr, usr);
+	INEXT(&regs->preds, p3_0);
+	INEXT(&regs->gp, gp);
+	INEXT(&regs->ugp, ugp);
+	INEXT(&pt_elr(regs), pc);
+
+	/* CAUSE and BADVA aren't writeable. */
+	INEXT(&bucket, cause);
+	INEXT(&bucket, badva);
+
+	/* Ignore the rest, if needed */
+	if (!ret)
+		ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+					offsetof(struct user_regs_struct, pad1), -1);
+
+	if (ret)
+		return ret;
+
+	/*
+	 * This is special; SP is actually restored by the VM via the
+	 * special event record which is set by the special trap.
+	 */
+	regs->hvmer.vmpsp = regs->r29;
+	return 0;
+}
+
+enum hexagon_regset {
+	REGSET_GENERAL,
+};
+
+static const struct user_regset hexagon_regsets[] = {
+	[REGSET_GENERAL] = {
+		.core_note_type = NT_PRSTATUS,
+		.n = ELF_NGREG,
+		.size = sizeof(unsigned long),
+		.align = sizeof(unsigned long),
+		.get = genregs_get,
+		.set = genregs_set,
+	},
+};
+
+static const struct user_regset_view hexagon_user_view = {
+	.name = UTS_MACHINE,
+	.e_machine = ELF_ARCH,
+	.ei_osabi = ELF_OSABI,
+	.regsets = hexagon_regsets,
+	.n = ARRAY_SIZE(hexagon_regsets)
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+	return &hexagon_user_view;
+}
+
+void ptrace_disable(struct task_struct *child)
+{
+	/* Boilerplate - resolves to null inline if no HW single-step */
+	user_disable_single_step(child);
+}
+
+long arch_ptrace(struct task_struct *child, long request,
+		 unsigned long addr, unsigned long data)
+{
+	return ptrace_request(child, request, addr, data);
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/reset.c linux-libre-3.2-gnu/arch/hexagon/kernel/reset.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/reset.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/reset.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,38 @@
+/*
+ * 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/smp.h>
+#include <asm/hexagon_vm.h>
+
+void machine_power_off(void)
+{
+	smp_send_stop();
+	__vmstop();
+}
+
+void machine_halt(void)
+{
+}
+
+void machine_restart(char *cmd)
+{
+}
+
+void pm_power_off(void)
+{
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/setup.c linux-libre-3.2-gnu/arch/hexagon/kernel/setup.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/setup.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,145 @@
+/*
+ * Arch related setup for Hexagon
+ *
+ * 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/init.h>
+#include <linux/bootmem.h>
+#include <linux/mmzone.h>
+#include <linux/mm.h>
+#include <linux/seq_file.h>
+#include <linux/console.h>
+#include <linux/of_fdt.h>
+#include <asm/io.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/processor.h>
+#include <asm/hexagon_vm.h>
+#include <asm/vm_mmu.h>
+#include <asm/time.h>
+#ifdef CONFIG_OF
+#include <asm/prom.h>
+#endif
+
+char cmd_line[COMMAND_LINE_SIZE];
+static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
+
+int on_simulator;
+
+void __cpuinit calibrate_delay(void)
+{
+	loops_per_jiffy = thread_freq_mhz * 1000000 / HZ;
+}
+
+/*
+ * setup_arch -  high level architectural setup routine
+ * @cmdline_p: pointer to pointer to command-line arguments
+ */
+
+void __init setup_arch(char **cmdline_p)
+{
+	char *p = &external_cmdline_buffer;
+
+	/*
+	 * These will eventually be pulled in via either some hypervisor
+	 * or devicetree description.  Hardwiring for now.
+	 */
+	pcycle_freq_mhz = 600;
+	thread_freq_mhz = 100;
+	sleep_clk_freq = 32000;
+
+	/*
+	 * Set up event bindings to handle exceptions and interrupts.
+	 */
+	__vmsetvec(_K_VM_event_vector);
+
+	/*
+	 * Simulator has a few differences from the hardware.
+	 * For now, check uninitialized-but-mapped memory
+	 * prior to invoking setup_arch_memory().
+	 */
+	if (*(int *)((unsigned long)_end + 8) == 0x1f1f1f1f)
+		on_simulator = 1;
+	else
+		on_simulator = 0;
+
+	if (p[0] != '\0')
+		strlcpy(boot_command_line, p, COMMAND_LINE_SIZE);
+	else
+		strlcpy(boot_command_line, default_command_line,
+			COMMAND_LINE_SIZE);
+
+	/*
+	 * boot_command_line and the value set up by setup_arch
+	 * are both picked up by the init code. If no reason to
+	 * make them different, pass the same pointer back.
+	 */
+	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
+	*cmdline_p = cmd_line;
+
+	parse_early_param();
+
+	setup_arch_memory();
+
+#ifdef CONFIG_SMP
+	smp_start_cpus();
+#endif
+}
+
+/*
+ * Functions for dumping CPU info via /proc
+ * Probably should move to kernel/proc.c or something.
+ */
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < nr_cpu_ids ? (void *)((unsigned long) *pos + 1) : 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)
+{
+}
+
+/*
+ * Eventually this will dump information about
+ * CPU properties like ISA level, TLB size, etc.
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+	int cpu = (unsigned long) v - 1;
+
+	seq_printf(m, "processor\t: %d\n", cpu);
+	seq_printf(m, "model name\t: Hexagon Virtual Machine\n");
+	seq_printf(m, "BogoMips\t: %lu.%02lu\n",
+		(loops_per_jiffy * HZ) / 500000,
+		((loops_per_jiffy * HZ) / 5000) % 100);
+	seq_printf(m, "\n");
+	return 0;
+}
+
+const struct seq_operations cpuinfo_op = {
+	.start  = &c_start,
+	.next   = &c_next,
+	.stop   = &c_stop,
+	.show   = &show_cpuinfo,
+};
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/signal.c linux-libre-3.2-gnu/arch/hexagon/kernel/signal.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/signal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/signal.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,345 @@
+/*
+ * Signal support for Hexagon processor
+ *
+ * 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/linkage.h>
+#include <linux/syscalls.h>
+#include <linux/freezer.h>
+#include <linux/tracehook.h>
+#include <asm/registers.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <asm/ucontext.h>
+#include <asm/cacheflush.h>
+#include <asm/signal.h>
+#include <asm/vdso.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+struct rt_sigframe {
+	unsigned long tramp[2];
+	struct siginfo info;
+	struct ucontext uc;
+};
+
+static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+			  size_t frame_size)
+{
+	unsigned long sp = regs->r29;
+
+	/* Switch to signal stack if appropriate */
+	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
+		sp = current->sas_ss_sp + current->sas_ss_size;
+
+	return (void __user *)((sp - frame_size) & ~(sizeof(long long) - 1));
+}
+
+static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
+{
+	unsigned long tmp;
+	int err = 0;
+
+	err |= copy_to_user(&sc->sc_regs.r0, &regs->r00,
+			    32*sizeof(unsigned long));
+
+	err |= __put_user(regs->sa0, &sc->sc_regs.sa0);
+	err |= __put_user(regs->lc0, &sc->sc_regs.lc0);
+	err |= __put_user(regs->sa1, &sc->sc_regs.sa1);
+	err |= __put_user(regs->lc1, &sc->sc_regs.lc1);
+	err |= __put_user(regs->m0, &sc->sc_regs.m0);
+	err |= __put_user(regs->m1, &sc->sc_regs.m1);
+	err |= __put_user(regs->usr, &sc->sc_regs.usr);
+	err |= __put_user(regs->preds, &sc->sc_regs.p3_0);
+	err |= __put_user(regs->gp, &sc->sc_regs.gp);
+	err |= __put_user(regs->ugp, &sc->sc_regs.ugp);
+
+	tmp = pt_elr(regs); err |= __put_user(tmp, &sc->sc_regs.pc);
+	tmp = pt_cause(regs); err |= __put_user(tmp, &sc->sc_regs.cause);
+	tmp = pt_badva(regs); err |= __put_user(tmp, &sc->sc_regs.badva);
+
+	return err;
+}
+
+static int restore_sigcontext(struct pt_regs *regs,
+			      struct sigcontext __user *sc)
+{
+	unsigned long tmp;
+	int err = 0;
+
+	err |= copy_from_user(&regs->r00, &sc->sc_regs.r0,
+			      32 * sizeof(unsigned long));
+
+	err |= __get_user(regs->sa0, &sc->sc_regs.sa0);
+	err |= __get_user(regs->lc0, &sc->sc_regs.lc0);
+	err |= __get_user(regs->sa1, &sc->sc_regs.sa1);
+	err |= __get_user(regs->lc1, &sc->sc_regs.lc1);
+	err |= __get_user(regs->m0, &sc->sc_regs.m0);
+	err |= __get_user(regs->m1, &sc->sc_regs.m1);
+	err |= __get_user(regs->usr, &sc->sc_regs.usr);
+	err |= __get_user(regs->preds, &sc->sc_regs.p3_0);
+	err |= __get_user(regs->gp, &sc->sc_regs.gp);
+	err |= __get_user(regs->ugp, &sc->sc_regs.ugp);
+
+	err |= __get_user(tmp, &sc->sc_regs.pc); pt_set_elr(regs, tmp);
+
+	return err;
+}
+
+/*
+ * Setup signal stack frame with siginfo structure
+ */
+static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
+			  sigset_t *set,  struct pt_regs *regs)
+{
+	int err = 0;
+	struct rt_sigframe __user *frame;
+	struct hexagon_vdso *vdso = current->mm->context.vdso;
+
+	frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(struct rt_sigframe)))
+		goto	sigsegv;
+
+	if (copy_siginfo_to_user(&frame->info, info))
+		goto	sigsegv;
+
+	/* The on-stack signal trampoline is no longer executed;
+	 * however, the libgcc signal frame unwinding code checks for
+	 * the presence of these two numeric magic values.
+	 */
+	err |= __put_user(0x7800d166, &frame->tramp[0]);
+	err |= __put_user(0x5400c004, &frame->tramp[1]);
+	err |= setup_sigcontext(regs, &frame->uc.uc_mcontext);
+	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+	if (err)
+		goto sigsegv;
+
+	/* Load r0/r1 pair with signumber/siginfo pointer... */
+	regs->r0100 = ((unsigned long long)((unsigned long)&frame->info) << 32)
+		| (unsigned long long)signr;
+	regs->r02 = (unsigned long) &frame->uc;
+	regs->r31 = (unsigned long) vdso->rt_signal_trampoline;
+	pt_psp(regs) = (unsigned long) frame;
+	pt_set_elr(regs, (unsigned long)ka->sa.sa_handler);
+
+	return 0;
+
+sigsegv:
+	force_sigsegv(signr, current);
+	return -EFAULT;
+}
+
+/*
+ * Setup invocation of signal handler
+ */
+static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
+			 sigset_t *oldset, struct pt_regs *regs)
+{
+	int rc;
+
+	/*
+	 * If we're handling a signal that aborted a system call,
+	 * set up the error return value before adding the signal
+	 * frame to the stack.
+	 */
+
+	if (regs->syscall_nr >= 0) {
+		switch (regs->r00) {
+		case -ERESTART_RESTARTBLOCK:
+		case -ERESTARTNOHAND:
+			regs->r00 = -EINTR;
+			break;
+		case -ERESTARTSYS:
+			if (!(ka->sa.sa_flags & SA_RESTART)) {
+				regs->r00 = -EINTR;
+				break;
+			}
+			/* Fall through */
+		case -ERESTARTNOINTR:
+			regs->r06 = regs->syscall_nr;
+			pt_set_elr(regs, pt_elr(regs) - 4);
+			regs->r00 = regs->restart_r0;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/*
+	 * Set up the stack frame; not doing the SA_SIGINFO thing.  We
+	 * only set up the rt_frame flavor.
+	 */
+	rc = setup_rt_frame(sig, ka, info, oldset, regs);
+
+	/* If there was an error on setup, no signal was delivered. */
+	if (rc)
+		return rc;
+
+	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);
+
+	return 0;
+}
+
+/*
+ * Called from return-from-event code.
+ */
+static void do_signal(struct pt_regs *regs)
+{
+	struct k_sigaction sigact;
+	siginfo_t info;
+	int signo;
+
+	if (!user_mode(regs))
+		return;
+
+	if (try_to_freeze())
+		goto no_signal;
+
+	signo = get_signal_to_deliver(&info, &sigact, regs, NULL);
+
+	if (signo > 0) {
+		sigset_t *oldset;
+
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			oldset = &current->saved_sigmask;
+		else
+			oldset = &current->blocked;
+
+		if (handle_signal(signo, &info, &sigact, oldset, regs) == 0) {
+			/*
+			 * Successful delivery case.  The saved sigmask is
+			 * stored in the signal frame, and will be restored
+			 * by sigreturn.  We can clear the TIF flag.
+			 */
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+			tracehook_signal_handler(signo, &info, &sigact, regs,
+				test_thread_flag(TIF_SINGLESTEP));
+		}
+		return;
+	}
+
+no_signal:
+	/*
+	 * If we came from a system call, handle the restart.
+	 */
+	if (regs->syscall_nr >= 0) {
+		switch (regs->r00) {
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
+			regs->r06 = regs->syscall_nr;
+			break;
+		case -ERESTART_RESTARTBLOCK:
+			regs->r06 = __NR_restart_syscall;
+			break;
+		default:
+			goto no_restart;
+		}
+		pt_set_elr(regs, pt_elr(regs) - 4);
+		regs->r00 = regs->restart_r0;
+	}
+
+no_restart:
+	/* If there's no signal to deliver, 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);
+	}
+}
+
+void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
+{
+	if (thread_info_flags & _TIF_SIGPENDING)
+		do_signal(regs);
+
+	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
+		clear_thread_flag(TIF_NOTIFY_RESUME);
+		if (current->replacement_session_keyring)
+			key_replace_session_keyring();
+	}
+}
+
+/*
+ * Architecture-specific wrappers for signal-related system calls
+ */
+asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
+{
+	struct pt_regs *regs = current_thread_info()->regs;
+
+	return do_sigaltstack(uss, uoss, regs->r29);
+}
+
+asmlinkage int sys_rt_sigreturn(void)
+{
+	struct pt_regs *regs = current_thread_info()->regs;
+	struct rt_sigframe __user *frame;
+	sigset_t blocked;
+
+	frame = (struct rt_sigframe __user *)pt_psp(regs);
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__copy_from_user(&blocked, &frame->uc.uc_sigmask, sizeof(blocked)))
+		goto badframe;
+
+	sigdelsetmask(&blocked, ~_BLOCKABLE);
+	spin_lock_irq(&current->sighand->siglock);
+	current->blocked = blocked;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
+		goto badframe;
+
+	/* Restore the user's stack as well */
+	pt_psp(regs) = regs->r29;
+
+	/*
+	 * Leave a trace in the stack frame that this was a sigreturn.
+	 * If the system call is to replay, we've already restored the
+	 * number in the GPR slot and it will be regenerated on the
+	 * new system call trap entry. Note that if restore_sigcontext()
+	 * did something other than a bulk copy of the pt_regs struct,
+	 * we could avoid this assignment by simply not overwriting
+	 * regs->syscall_nr.
+	 */
+	regs->syscall_nr = __NR_rt_sigreturn;
+
+	/*
+	 * If we were meticulous, we'd only call this if we knew that
+	 * we were actually going to use an alternate stack, and we'd
+	 * consider any error to be fatal.  What we do here, in common
+	 * with many other architectures, is call it blindly and only
+	 * consider the -EFAULT return case to be proof of a problem.
+	 */
+	if (do_sigaltstack(&frame->uc.uc_stack, NULL, pt_psp(regs)) == -EFAULT)
+		goto badframe;
+
+	return 0;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/smp.c linux-libre-3.2-gnu/arch/hexagon/kernel/smp.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/smp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,276 @@
+/*
+ * SMP support for Hexagon
+ *
+ * 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/err.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/percpu.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+
+#include <asm/system.h>  /*  xchg  */
+#include <asm/time.h>    /*  timer_interrupt  */
+#include <asm/hexagon_vm.h>
+
+#define BASE_IPI_IRQ 26
+
+/*
+ * cpu_possible_map needs to be filled out prior to setup_per_cpu_areas
+ * (which is prior to any of our smp_prepare_cpu crap), in order to set
+ * up the...  per_cpu areas.
+ */
+
+struct ipi_data {
+	unsigned long bits;
+};
+
+static DEFINE_PER_CPU(struct ipi_data, ipi_data);
+
+static inline void __handle_ipi(unsigned long *ops, struct ipi_data *ipi,
+				int cpu)
+{
+	unsigned long msg = 0;
+	do {
+		msg = find_next_bit(ops, BITS_PER_LONG, msg+1);
+
+		switch (msg) {
+
+		case IPI_TIMER:
+			ipi_timer();
+			break;
+
+		case IPI_CALL_FUNC:
+			generic_smp_call_function_interrupt();
+			break;
+
+		case IPI_CALL_FUNC_SINGLE:
+			generic_smp_call_function_single_interrupt();
+			break;
+
+		case IPI_CPU_STOP:
+			/*
+			 * call vmstop()
+			 */
+			__vmstop();
+			break;
+
+		case IPI_RESCHEDULE:
+			scheduler_ipi();
+			break;
+		}
+	} while (msg < BITS_PER_LONG);
+}
+
+/*  Used for IPI call from other CPU's to unmask int  */
+void smp_vm_unmask_irq(void *info)
+{
+	__vmintop_locen((long) info);
+}
+
+
+/*
+ * This is based on Alpha's IPI stuff.
+ * Supposed to take (int, void*) as args now.
+ * Specifically, first arg is irq, second is the irq_desc.
+ */
+
+irqreturn_t handle_ipi(int irq, void *desc)
+{
+	int cpu = smp_processor_id();
+	struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
+	unsigned long ops;
+
+	while ((ops = xchg(&ipi->bits, 0)) != 0)
+		__handle_ipi(&ops, ipi, cpu);
+	return IRQ_HANDLED;
+}
+
+void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg)
+{
+	unsigned long flags;
+	unsigned long cpu;
+	unsigned long retval;
+
+	local_irq_save(flags);
+
+	for_each_cpu(cpu, cpumask) {
+		struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
+
+		set_bit(msg, &ipi->bits);
+		/*  Possible barrier here  */
+		retval = __vmintop_post(BASE_IPI_IRQ+cpu);
+
+		if (retval != 0) {
+			printk(KERN_ERR "interrupt %ld not configured?\n",
+				BASE_IPI_IRQ+cpu);
+		}
+	}
+
+	local_irq_restore(flags);
+}
+
+static struct irqaction ipi_intdesc = {
+	.handler = handle_ipi,
+	.flags = IRQF_TRIGGER_RISING,
+	.name = "ipi_handler"
+};
+
+void __init smp_prepare_boot_cpu(void)
+{
+}
+
+/*
+ * interrupts should already be disabled from the VM
+ * SP should already be correct; need to set THREADINFO_REG
+ * to point to current thread info
+ */
+
+void __cpuinit start_secondary(void)
+{
+	unsigned int cpu;
+	unsigned long thread_ptr;
+
+	/*  Calculate thread_info pointer from stack pointer  */
+	__asm__ __volatile__(
+		"%0 = SP;\n"
+		: "=r" (thread_ptr)
+	);
+
+	thread_ptr = thread_ptr & ~(THREAD_SIZE-1);
+
+	__asm__ __volatile__(
+		QUOTED_THREADINFO_REG " = %0;\n"
+		:
+		: "r" (thread_ptr)
+	);
+
+	/*  Set the memory struct  */
+	atomic_inc(&init_mm.mm_count);
+	current->active_mm = &init_mm;
+
+	cpu = smp_processor_id();
+
+	setup_irq(BASE_IPI_IRQ + cpu, &ipi_intdesc);
+
+	/*  Register the clock_event dummy  */
+	setup_percpu_clockdev();
+
+	printk(KERN_INFO "%s cpu %d\n", __func__, current_thread_info()->cpu);
+
+	set_cpu_online(cpu, true);
+	while (!cpumask_test_cpu(cpu, cpu_active_mask))
+		cpu_relax();
+	local_irq_enable();
+
+	cpu_idle();
+}
+
+
+/*
+ * called once for each present cpu
+ * apparently starts up the CPU and then
+ * maintains control until "cpu_online(cpu)" is set.
+ */
+
+int __cpuinit __cpu_up(unsigned int cpu)
+{
+	struct task_struct *idle;
+	struct thread_info *thread;
+	void *stack_start;
+
+	/*  Create new init task for the CPU  */
+	idle = fork_idle(cpu);
+	if (IS_ERR(idle))
+		panic(KERN_ERR "fork_idle failed\n");
+
+	thread = (struct thread_info *)idle->stack;
+	thread->cpu = cpu;
+
+	/*  Boot to the head.  */
+	stack_start =  ((void *) thread) + THREAD_SIZE;
+	__vmstart(start_secondary, stack_start);
+
+	while (!cpu_isset(cpu, cpu_online_map))
+		barrier();
+
+	return 0;
+}
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+	int i;
+
+	/*
+	 * should eventually have some sort of machine
+	 * descriptor that has this stuff
+	 */
+
+	/*  Right now, let's just fake it. */
+	for (i = 0; i < max_cpus; i++)
+		cpu_set(i, cpu_present_map);
+
+	/*  Also need to register the interrupts for IPI  */
+	if (max_cpus > 1)
+		setup_irq(BASE_IPI_IRQ, &ipi_intdesc);
+}
+
+void smp_send_reschedule(int cpu)
+{
+	send_ipi(cpumask_of(cpu), IPI_RESCHEDULE);
+}
+
+void smp_send_stop(void)
+{
+	struct cpumask targets;
+	cpumask_copy(&targets, cpu_online_mask);
+	cpumask_clear_cpu(smp_processor_id(), &targets);
+	send_ipi(&targets, IPI_CPU_STOP);
+}
+
+void arch_send_call_function_single_ipi(int cpu)
+{
+	send_ipi(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+}
+
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+{
+	send_ipi(mask, IPI_CALL_FUNC);
+}
+
+int setup_profiling_timer(unsigned int multiplier)
+{
+	return -EINVAL;
+}
+
+void smp_start_cpus(void)
+{
+	int i;
+
+	for (i = 0; i < NR_CPUS; i++)
+		cpu_set(i, cpu_possible_map);
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/stacktrace.c linux-libre-3.2-gnu/arch/hexagon/kernel/stacktrace.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/stacktrace.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/stacktrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,66 @@
+/*
+ * Stacktrace support for Hexagon
+ *
+ * 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/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/thread_info.h>
+#include <linux/module.h>
+
+register unsigned long current_frame_pointer asm("r30");
+
+struct stackframe {
+	unsigned long fp;
+	unsigned long rets;
+};
+
+/*
+ * Save stack-backtrace addresses into a stack_trace buffer.
+ */
+void save_stack_trace(struct stack_trace *trace)
+{
+	unsigned long low, high;
+	unsigned long fp;
+	struct stackframe *frame;
+	int skip = trace->skip;
+
+	low = (unsigned long)task_stack_page(current);
+	high = low + THREAD_SIZE;
+	fp = current_frame_pointer;
+
+	while (fp >= low && fp <= (high - sizeof(*frame))) {
+		frame = (struct stackframe *)fp;
+
+		if (skip) {
+			skip--;
+		} else {
+			trace->entries[trace->nr_entries++] = frame->rets;
+			if (trace->nr_entries >= trace->max_entries)
+				break;
+		}
+
+		/*
+		 * The next frame must be at a higher address than the
+		 * current frame.
+		 */
+		low = fp + sizeof(*frame);
+		fp = frame->fp;
+	}
+}
+EXPORT_SYMBOL_GPL(save_stack_trace);
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/syscall.c linux-libre-3.2-gnu/arch/hexagon/kernel/syscall.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/syscall.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/syscall.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,90 @@
+/*
+ * Hexagon system calls
+ *
+ * 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/file.h>
+#include <linux/fs.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/unistd.h>
+#include <asm/mman.h>
+#include <asm/registers.h>
+
+/*
+ * System calls with architecture-specific wrappers.
+ * See signal.c for signal-related system call wrappers.
+ */
+
+asmlinkage int sys_execve(char __user *ufilename,
+			  const char __user *const __user *argv,
+			  const char __user *const __user *envp)
+{
+	struct pt_regs *pregs = current_thread_info()->regs;
+	char *filename;
+	int retval;
+
+	filename = getname(ufilename);
+	retval = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		return retval;
+
+	retval = do_execve(filename, argv, envp, pregs);
+	putname(filename);
+
+	return retval;
+}
+
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+			 unsigned long parent_tidp, unsigned long child_tidp)
+{
+	struct pt_regs *pregs = current_thread_info()->regs;
+
+	if (!newsp)
+		newsp = pregs->SP;
+	return do_fork(clone_flags, newsp, pregs, 0, (int __user *)parent_tidp,
+		       (int __user *)child_tidp);
+}
+
+/*
+ * Do a system call from the kernel, so as to have a proper pt_regs
+ * and recycle the sys_execvpe infrustructure.
+ */
+int kernel_execve(const char *filename,
+		  const char *const argv[], const char *const envp[])
+{
+	register unsigned long __a0 asm("r0") = (unsigned long) filename;
+	register unsigned long __a1 asm("r1") = (unsigned long) argv;
+	register unsigned long __a2 asm("r2") = (unsigned long) envp;
+	int retval;
+
+	__asm__ volatile(
+		"	R6 = #%4;\n"
+		"	trap0(#1);\n"
+		"	%0 = R0;\n"
+		: "=r" (retval)
+		: "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve)
+	);
+
+	return retval;
+}
+EXPORT_SYMBOL(kernel_execve);
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/syscalltab.c linux-libre-3.2-gnu/arch/hexagon/kernel/syscalltab.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/syscalltab.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/syscalltab.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,32 @@
+/*
+ * System call table for Hexagon
+ *
+ * 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/syscalls.h>
+#include <linux/signal.h>
+#include <linux/unistd.h>
+
+#include <asm/syscall.h>
+
+#undef __SYSCALL
+#define __SYSCALL(nr, call) [nr] = (call),
+
+void *sys_call_table[__NR_syscalls] = {
+#include <asm/unistd.h>
+};
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/time.c linux-libre-3.2-gnu/arch/hexagon/kernel/time.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/time.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,250 @@
+/*
+ * Time related functions for Hexagon architecture
+ *
+ * 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/init.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/timer-regs.h>
+#include <asm/hexagon_vm.h>
+
+/*
+ * For the clocksource we need:
+ *	pcycle frequency (600MHz)
+ * For the loops_per_jiffy we need:
+ *	thread/cpu frequency (100MHz)
+ * And for the timer, we need:
+ *	sleep clock rate
+ */
+
+cycles_t	pcycle_freq_mhz;
+cycles_t	thread_freq_mhz;
+cycles_t	sleep_clk_freq;
+
+static struct resource rtos_timer_resources[] = {
+	{
+		.start	= RTOS_TIMER_REGS_ADDR,
+		.end	= RTOS_TIMER_REGS_ADDR+PAGE_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device rtos_timer_device = {
+	.name		= "rtos_timer",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(rtos_timer_resources),
+	.resource	= rtos_timer_resources,
+};
+
+/*  A lot of this stuff should move into a platform specific section.  */
+struct adsp_hw_timer_struct {
+	u32 match;   /*  Match value  */
+	u32 count;
+	u32 enable;  /*  [1] - CLR_ON_MATCH_EN, [0] - EN  */
+	u32 clear;   /*  one-shot register that clears the count  */
+};
+
+/*  Look for "TCX0" for related constants.  */
+static __iomem struct adsp_hw_timer_struct *rtos_timer;
+
+static cycle_t timer_get_cycles(struct clocksource *cs)
+{
+	return (cycle_t) __vmgettime();
+}
+
+static struct clocksource hexagon_clocksource = {
+	.name		= "pcycles",
+	.rating		= 250,
+	.read		= timer_get_cycles,
+	.mask		= CLOCKSOURCE_MASK(64),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int set_next_event(unsigned long delta, struct clock_event_device *evt)
+{
+	/*  Assuming the timer will be disabled when we enter here.  */
+
+	iowrite32(1, &rtos_timer->clear);
+	iowrite32(0, &rtos_timer->clear);
+
+	iowrite32(delta, &rtos_timer->match);
+	iowrite32(1 << TIMER_ENABLE, &rtos_timer->enable);
+	return 0;
+}
+
+/*
+ * Sets the mode (periodic, shutdown, oneshot, etc) of a timer.
+ */
+static void set_mode(enum clock_event_mode mode,
+	struct clock_event_device *evt)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		/* XXX implement me */
+	default:
+		break;
+	}
+}
+
+#ifdef CONFIG_SMP
+/*  Broadcast mechanism  */
+static void broadcast(const struct cpumask *mask)
+{
+	send_ipi(mask, IPI_TIMER);
+}
+#endif
+
+static struct clock_event_device hexagon_clockevent_dev = {
+	.name		= "clockevent",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 400,
+	.irq		= RTOS_TIMER_INT,
+	.set_next_event = set_next_event,
+	.set_mode	= set_mode,
+#ifdef CONFIG_SMP
+	.broadcast	= broadcast,
+#endif
+};
+
+#ifdef CONFIG_SMP
+static DEFINE_PER_CPU(struct clock_event_device, clock_events);
+
+void setup_percpu_clockdev(void)
+{
+	int cpu = smp_processor_id();
+	struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
+	struct clock_event_device *dummy_clock_dev =
+		&per_cpu(clock_events, cpu);
+
+	memcpy(dummy_clock_dev, ce_dev, sizeof(*dummy_clock_dev));
+	INIT_LIST_HEAD(&dummy_clock_dev->list);
+
+	dummy_clock_dev->features = CLOCK_EVT_FEAT_DUMMY;
+	dummy_clock_dev->cpumask = cpumask_of(cpu);
+	dummy_clock_dev->mode = CLOCK_EVT_MODE_UNUSED;
+
+	clockevents_register_device(dummy_clock_dev);
+}
+
+/*  Called from smp.c for each CPU's timer ipi call  */
+void ipi_timer(void)
+{
+	int cpu = smp_processor_id();
+	struct clock_event_device *ce_dev = &per_cpu(clock_events, cpu);
+
+	ce_dev->event_handler(ce_dev);
+}
+#endif /* CONFIG_SMP */
+
+static irqreturn_t timer_interrupt(int irq, void *devid)
+{
+	struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
+
+	iowrite32(0, &rtos_timer->enable);
+	ce_dev->event_handler(ce_dev);
+
+	return IRQ_HANDLED;
+}
+
+/*  This should also be pulled from devtree  */
+static struct irqaction rtos_timer_intdesc = {
+	.handler = timer_interrupt,
+	.flags = IRQF_TIMER | IRQF_TRIGGER_RISING,
+	.name = "rtos_timer"
+};
+
+/*
+ * time_init_deferred - called by start_kernel to set up timer/clock source
+ *
+ * Install the IRQ handler for the clock, setup timers.
+ * This is done late, as that way, we can use ioremap().
+ *
+ * This runs just before the delay loop is calibrated, and
+ * is used for delay calibration.
+ */
+void __init time_init_deferred(void)
+{
+	struct resource *resource = NULL;
+	struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
+	struct device_node *dn;
+	struct resource r;
+	int err;
+
+	ce_dev->cpumask = cpu_all_mask;
+
+	if (!resource)
+		resource = rtos_timer_device.resource;
+
+	/*  ioremap here means this has to run later, after paging init  */
+	rtos_timer = ioremap(resource->start, resource->end
+		- resource->start + 1);
+
+	if (!rtos_timer) {
+		release_mem_region(resource->start, resource->end
+			- resource->start + 1);
+	}
+	clocksource_register_khz(&hexagon_clocksource, pcycle_freq_mhz * 1000);
+
+	/*  Note: the sim generic RTOS clock is apparently really 18750Hz  */
+
+	/*
+	 * Last arg is some guaranteed seconds for which the conversion will
+	 * work without overflow.
+	 */
+	clockevents_calc_mult_shift(ce_dev, sleep_clk_freq, 4);
+
+	ce_dev->max_delta_ns = clockevent_delta2ns(0x7fffffff, ce_dev);
+	ce_dev->min_delta_ns = clockevent_delta2ns(0xf, ce_dev);
+
+#ifdef CONFIG_SMP
+	setup_percpu_clockdev();
+#endif
+
+	clockevents_register_device(ce_dev);
+	setup_irq(ce_dev->irq, &rtos_timer_intdesc);
+}
+
+void __init time_init(void)
+{
+	late_time_init = time_init_deferred;
+}
+
+/*
+ * This could become parametric or perhaps even computed at run-time,
+ * but for now we take the observed simulator jitter.
+ */
+static long long fudgefactor = 350;  /* Maybe lower if kernel optimized. */
+
+void __udelay(unsigned long usecs)
+{
+	unsigned long long start = __vmgettime();
+	unsigned long long finish = (pcycle_freq_mhz * usecs) - fudgefactor;
+
+	while ((__vmgettime() - start) < finish)
+		cpu_relax(); /*  not sure how this improves readability  */
+}
+EXPORT_SYMBOL(__udelay);
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/topology.c linux-libre-3.2-gnu/arch/hexagon/kernel/topology.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/topology.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/topology.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,52 @@
+/*
+ * CPU topology for Hexagon
+ *
+ * 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/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/node.h>
+#include <linux/nodemask.h>
+#include <linux/percpu.h>
+
+/*  Swiped from MIPS.  */
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+static int __init topology_init(void)
+{
+	int i, ret;
+
+	for_each_present_cpu(i) {
+
+		/*
+		 * register_cpu takes a per_cpu pointer and
+		 * just points it at another per_cpu struct...
+		 */
+
+		ret = register_cpu(&per_cpu(cpu_devices, i), i);
+		if (ret)
+			printk(KERN_WARNING "topology_init: register_cpu %d "
+			       "failed (%d)\n", i, ret);
+	}
+
+	return 0;
+}
+
+subsys_initcall(topology_init);
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/trampoline.S linux-libre-3.2-gnu/arch/hexagon/kernel/trampoline.S
--- linux-libre-3.1-gnu/arch/hexagon/kernel/trampoline.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/trampoline.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+/*
+ * Trampoline sequences to be copied onto user stack.
+ * This consumes a little more space than hand-assembling
+ * immediate constants for use in C, but is more portable
+ * to future tweaks to the Hexagon instruction set.
+ */
+
+#include <asm/unistd.h>
+
+/*  Sig trampolines - call sys_sigreturn or sys_rt_sigreturn as appropriate */
+
+/*  plain sigreturn is gone.  */
+
+	.globl __rt_sigtramp_template
+__rt_sigtramp_template:
+	r6 = #__NR_rt_sigreturn;
+	trap0(#1);
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/traps.c linux-libre-3.2-gnu/arch/hexagon/kernel/traps.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/traps.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/traps.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,454 @@
+/*
+ * Kernel traps/events for Hexagon processor
+ *
+ * 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/init.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+#include <linux/kdebug.h>
+#include <linux/syscalls.h>
+#include <linux/signal.h>
+#include <linux/tracehook.h>
+#include <asm/traps.h>
+#include <asm/vm_fault.h>
+#include <asm/syscall.h>
+#include <asm/registers.h>
+#include <asm/unistd.h>
+#include <asm/sections.h>
+#ifdef CONFIG_KGDB
+# include <linux/kgdb.h>
+#endif
+
+#define TRAP_SYSCALL	1
+#define TRAP_DEBUG	0xdb
+
+void __init trap_init(void)
+{
+}
+
+#ifdef CONFIG_GENERIC_BUG
+/* Maybe should resemble arch/sh/kernel/traps.c ?? */
+int is_valid_bugaddr(unsigned long addr)
+{
+	return 1;
+}
+#endif /* CONFIG_GENERIC_BUG */
+
+static const char *ex_name(int ex)
+{
+	switch (ex) {
+	case HVM_GE_C_XPROT:
+	case HVM_GE_C_XUSER:
+		return "Execute protection fault";
+	case HVM_GE_C_RPROT:
+	case HVM_GE_C_RUSER:
+		return "Read protection fault";
+	case HVM_GE_C_WPROT:
+	case HVM_GE_C_WUSER:
+		return "Write protection fault";
+	case HVM_GE_C_XMAL:
+		return "Misaligned instruction";
+	case HVM_GE_C_RMAL:
+		return "Misaligned data load";
+	case HVM_GE_C_WMAL:
+		return "Misaligned data store";
+	case HVM_GE_C_INVI:
+	case HVM_GE_C_PRIVI:
+		return "Illegal instruction";
+	case HVM_GE_C_BUS:
+		return "Precise bus error";
+	case HVM_GE_C_CACHE:
+		return "Cache error";
+
+	case 0xdb:
+		return "Debugger trap";
+
+	default:
+		return "Unrecognized exception";
+	}
+}
+
+static void do_show_stack(struct task_struct *task, unsigned long *fp,
+			  unsigned long ip)
+{
+	int kstack_depth_to_print = 24;
+	unsigned long offset, size;
+	const char *name = NULL;
+	unsigned long *newfp;
+	unsigned long low, high;
+	char tmpstr[128];
+	char *modname;
+	int i;
+
+	if (task == NULL)
+		task = current;
+
+	printk(KERN_INFO "CPU#%d, %s/%d, Call Trace:\n",
+	       raw_smp_processor_id(), task->comm,
+	       task_pid_nr(task));
+
+	if (fp == NULL) {
+		if (task == current) {
+			asm("%0 = r30" : "=r" (fp));
+		} else {
+			fp = (unsigned long *)
+			     ((struct hexagon_switch_stack *)
+			     task->thread.switch_sp)->fp;
+		}
+	}
+
+	if ((((unsigned long) fp) & 0x3) || ((unsigned long) fp < 0x1000)) {
+		printk(KERN_INFO "-- Corrupt frame pointer %p\n", fp);
+		return;
+	}
+
+	/* Saved link reg is one word above FP */
+	if (!ip)
+		ip = *(fp+1);
+
+	/* Expect kernel stack to be in-bounds */
+	low = (unsigned long)task_stack_page(task);
+	high = low + THREAD_SIZE - 8;
+	low += sizeof(struct thread_info);
+
+	for (i = 0; i < kstack_depth_to_print; i++) {
+
+		name = kallsyms_lookup(ip, &size, &offset, &modname, tmpstr);
+
+		printk(KERN_INFO "[%p] 0x%lx: %s + 0x%lx", fp, ip, name,
+			offset);
+		if (((unsigned long) fp < low) || (high < (unsigned long) fp))
+			printk(KERN_CONT " (FP out of bounds!)");
+		if (modname)
+			printk(KERN_CONT " [%s] ", modname);
+		printk(KERN_CONT "\n");
+
+		newfp = (unsigned long *) *fp;
+
+		if (((unsigned long) newfp) & 0x3) {
+			printk(KERN_INFO "-- Corrupt frame pointer %p\n",
+				newfp);
+			break;
+		}
+
+		/* Attempt to continue past exception. */
+		if (0 == newfp) {
+			struct pt_regs *regs = (struct pt_regs *) (((void *)fp)
+						+ 8);
+
+			if (regs->syscall_nr != -1) {
+				printk(KERN_INFO "-- trap0 -- syscall_nr: %ld",
+					regs->syscall_nr);
+				printk(KERN_CONT "  psp: %lx  elr: %lx\n",
+					 pt_psp(regs), pt_elr(regs));
+				break;
+			} else {
+				/* really want to see more ... */
+				kstack_depth_to_print += 6;
+				printk(KERN_INFO "-- %s (0x%lx)  badva: %lx\n",
+					ex_name(pt_cause(regs)), pt_cause(regs),
+					pt_badva(regs));
+			}
+
+			newfp = (unsigned long *) regs->r30;
+			ip = pt_elr(regs);
+		} else {
+			ip = *(newfp + 1);
+		}
+
+		/* If link reg is null, we are done. */
+		if (ip == 0x0)
+			break;
+
+		/* If newfp isn't larger, we're tracing garbage. */
+		if (newfp > fp)
+			fp = newfp;
+		else
+			break;
+	}
+}
+
+void show_stack(struct task_struct *task, unsigned long *fp)
+{
+	/* Saved link reg is one word above FP */
+	do_show_stack(task, fp, 0);
+}
+
+void dump_stack(void)
+{
+	unsigned long *fp;
+	asm("%0 = r30" : "=r" (fp));
+	show_stack(current, fp);
+}
+EXPORT_SYMBOL(dump_stack);
+
+int die(const char *str, struct pt_regs *regs, long err)
+{
+	static struct {
+		spinlock_t lock;
+		int counter;
+	} die = {
+		.lock = __SPIN_LOCK_UNLOCKED(die.lock),
+		.counter = 0
+	};
+
+	console_verbose();
+	oops_enter();
+
+	spin_lock_irq(&die.lock);
+	bust_spinlocks(1);
+	printk(KERN_EMERG "Oops: %s[#%d]:\n", str, ++die.counter);
+
+	if (notify_die(DIE_OOPS, str, regs, err, pt_cause(regs), SIGSEGV) ==
+	    NOTIFY_STOP)
+		return 1;
+
+	print_modules();
+	show_regs(regs);
+	do_show_stack(current, &regs->r30, pt_elr(regs));
+
+	bust_spinlocks(0);
+	add_taint(TAINT_DIE);
+
+	spin_unlock_irq(&die.lock);
+
+	if (in_interrupt())
+		panic("Fatal exception in interrupt");
+
+	if (panic_on_oops)
+		panic("Fatal exception");
+
+	oops_exit();
+	do_exit(err);
+	return 0;
+}
+
+int die_if_kernel(char *str, struct pt_regs *regs, long err)
+{
+	if (!user_mode(regs))
+		return die(str, regs, err);
+	else
+		return 0;
+}
+
+/*
+ * It's not clear that misaligned fetches are ever recoverable.
+ */
+static void misaligned_instruction(struct pt_regs *regs)
+{
+	die_if_kernel("Misaligned Instruction", regs, 0);
+	force_sig(SIGBUS, current);
+}
+
+/*
+ * Misaligned loads and stores, on the other hand, can be
+ * emulated, and probably should be, some day.  But for now
+ * they will be considered fatal.
+ */
+static void misaligned_data_load(struct pt_regs *regs)
+{
+	die_if_kernel("Misaligned Data Load", regs, 0);
+	force_sig(SIGBUS, current);
+}
+
+static void misaligned_data_store(struct pt_regs *regs)
+{
+	die_if_kernel("Misaligned Data Store", regs, 0);
+	force_sig(SIGBUS, current);
+}
+
+static void illegal_instruction(struct pt_regs *regs)
+{
+	die_if_kernel("Illegal Instruction", regs, 0);
+	force_sig(SIGILL, current);
+}
+
+/*
+ * Precise bus errors may be recoverable with a a retry,
+ * but for now, treat them as irrecoverable.
+ */
+static void precise_bus_error(struct pt_regs *regs)
+{
+	die_if_kernel("Precise Bus Error", regs, 0);
+	force_sig(SIGBUS, current);
+}
+
+/*
+ * If anything is to be done here other than panic,
+ * it will probably be complex and migrate to another
+ * source module.  For now, just die.
+ */
+static void cache_error(struct pt_regs *regs)
+{
+	die("Cache Error", regs, 0);
+}
+
+/*
+ * General exception handler
+ */
+void do_genex(struct pt_regs *regs)
+{
+	/*
+	 * Decode Cause and Dispatch
+	 */
+	switch (pt_cause(regs)) {
+	case HVM_GE_C_XPROT:
+	case HVM_GE_C_XUSER:
+		execute_protection_fault(regs);
+		break;
+	case HVM_GE_C_RPROT:
+	case HVM_GE_C_RUSER:
+		read_protection_fault(regs);
+		break;
+	case HVM_GE_C_WPROT:
+	case HVM_GE_C_WUSER:
+		write_protection_fault(regs);
+		break;
+	case HVM_GE_C_XMAL:
+		misaligned_instruction(regs);
+		break;
+	case HVM_GE_C_RMAL:
+		misaligned_data_load(regs);
+		break;
+	case HVM_GE_C_WMAL:
+		misaligned_data_store(regs);
+		break;
+	case HVM_GE_C_INVI:
+	case HVM_GE_C_PRIVI:
+		illegal_instruction(regs);
+		break;
+	case HVM_GE_C_BUS:
+		precise_bus_error(regs);
+		break;
+	case HVM_GE_C_CACHE:
+		cache_error(regs);
+		break;
+	default:
+		/* Halt and catch fire */
+		panic("Unrecognized exception 0x%lx\n", pt_cause(regs));
+		break;
+	}
+}
+
+/* Indirect system call dispatch */
+long sys_syscall(void)
+{
+	printk(KERN_ERR "sys_syscall invoked!\n");
+	return -ENOSYS;
+}
+
+void do_trap0(struct pt_regs *regs)
+{
+	unsigned long syscallret = 0;
+	syscall_fn syscall;
+
+	switch (pt_cause(regs)) {
+	case TRAP_SYSCALL:
+		/* System call is trap0 #1 */
+
+		/* allow strace to catch syscall args  */
+		if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE) &&
+			tracehook_report_syscall_entry(regs)))
+			return;  /*  return -ENOSYS somewhere?  */
+
+		/* Interrupts should be re-enabled for syscall processing */
+		__vmsetie(VM_INT_ENABLE);
+
+		/*
+		 * System call number is in r6, arguments in r0..r5.
+		 * Fortunately, no Linux syscall has more than 6 arguments,
+		 * and Hexagon ABI passes first 6 arguments in registers.
+		 * 64-bit arguments are passed in odd/even register pairs.
+		 * Fortunately, we have no system calls that take more
+		 * than three arguments with more than one 64-bit value.
+		 * Should that change, we'd need to redesign to copy
+		 * between user and kernel stacks.
+		 */
+		regs->syscall_nr = regs->r06;
+
+		/*
+		 * GPR R0 carries the first parameter, and is also used
+		 * to report the return value.  We need a backup of
+		 * the user's value in case we need to do a late restart
+		 * of the system call.
+		 */
+		regs->restart_r0 = regs->r00;
+
+		if ((unsigned long) regs->syscall_nr >= __NR_syscalls) {
+			regs->r00 = -1;
+		} else {
+			syscall = (syscall_fn)
+				  (sys_call_table[regs->syscall_nr]);
+			syscallret = syscall(regs->r00, regs->r01,
+				   regs->r02, regs->r03,
+				   regs->r04, regs->r05);
+		}
+
+		/*
+		 * If it was a sigreturn system call, don't overwrite
+		 * r0 value in stack frame with return value.
+		 *
+		 * __NR_sigreturn doesn't seem to exist in new unistd.h
+		 */
+
+		if (regs->syscall_nr != __NR_rt_sigreturn)
+			regs->r00 = syscallret;
+
+		/* allow strace to get the syscall return state  */
+		if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE)))
+			tracehook_report_syscall_exit(regs, 0);
+
+		break;
+	case TRAP_DEBUG:
+		/* Trap0 0xdb is debug breakpoint */
+		if (user_mode(regs)) {
+			struct siginfo info;
+
+			info.si_signo = SIGTRAP;
+			info.si_errno = 0;
+			/*
+			 * Some architecures add some per-thread state
+			 * to distinguish between breakpoint traps and
+			 * trace traps.  We may want to do that, and
+			 * set the si_code value appropriately, or we
+			 * may want to use a different trap0 flavor.
+			 */
+			info.si_code = TRAP_BRKPT;
+			info.si_addr = (void __user *) pt_elr(regs);
+			send_sig_info(SIGTRAP, &info, current);
+		} else {
+#ifdef CONFIG_KGDB
+			kgdb_handle_exception(pt_cause(regs), SIGTRAP,
+					      TRAP_BRKPT, regs);
+#endif
+		}
+		break;
+	}
+	/* Ignore other trap0 codes for now, especially 0 (Angel calls) */
+}
+
+/*
+ * Machine check exception handler
+ */
+void do_machcheck(struct pt_regs *regs)
+{
+	/* Halt and catch fire */
+	__vmstop();
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/vdso.c linux-libre-3.2-gnu/arch/hexagon/kernel/vdso.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/vdso.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/vdso.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,100 @@
+/*
+ * vDSO implementation for Hexagon
+ *
+ * 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/err.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+
+#include <asm/vdso.h>
+
+static struct page *vdso_page;
+
+/* Create a vDSO page holding the signal trampoline.
+ * We want this for a non-executable stack.
+ */
+static int __init vdso_init(void)
+{
+	struct hexagon_vdso *vdso;
+
+	vdso_page = alloc_page(GFP_KERNEL);
+	if (!vdso_page)
+		panic("Cannot allocate vdso");
+
+	vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL);
+	if (!vdso)
+		panic("Cannot map vdso");
+	clear_page(vdso);
+
+	/* Install the signal trampoline; currently looks like this:
+	 *	r6 = #__NR_rt_sigreturn;
+	 *	trap0(#1);
+	 */
+	vdso->rt_signal_trampoline[0] = __rt_sigtramp_template[0];
+	vdso->rt_signal_trampoline[1] = __rt_sigtramp_template[1];
+
+	vunmap(vdso);
+
+	return 0;
+}
+arch_initcall(vdso_init);
+
+/*
+ * Called from binfmt_elf.  Create a VMA for the vDSO page.
+ */
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+	int ret;
+	unsigned long vdso_base;
+	struct mm_struct *mm = current->mm;
+
+	down_write(&mm->mmap_sem);
+
+	/* Try to get it loaded right near ld.so/glibc. */
+	vdso_base = STACK_TOP;
+
+	vdso_base = get_unmapped_area(NULL, vdso_base, PAGE_SIZE, 0, 0);
+	if (IS_ERR_VALUE(vdso_base)) {
+		ret = vdso_base;
+		goto up_fail;
+	}
+
+	/* MAYWRITE to allow gdb to COW and set breakpoints. */
+	ret = install_special_mapping(mm, vdso_base, PAGE_SIZE,
+				      VM_READ|VM_EXEC|
+				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+				      VM_ALWAYSDUMP,
+				      &vdso_page);
+
+	if (ret)
+		goto up_fail;
+
+	mm->context.vdso = (void *)vdso_base;
+
+up_fail:
+	up_write(&mm->mmap_sem);
+	return ret;
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
+		return "[vdso]";
+	return NULL;
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/vm_entry.S linux-libre-3.2-gnu/arch/hexagon/kernel/vm_entry.S
--- linux-libre-3.1-gnu/arch/hexagon/kernel/vm_entry.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/vm_entry.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,269 @@
+/*
+ * Event entry/exit for Hexagon
+ *
+ * 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 <asm/asm-offsets.h>  /*  assembly-safer versions of C defines */
+#include <asm/mem-layout.h>   /*  sigh, except for page_offset  */
+#include <asm/hexagon_vm.h>
+#include <asm/thread_info.h>
+
+/*
+ * Entry into guest-mode Linux under Hexagon Virtual Machine.
+ * Stack pointer points to event record - build pt_regs on top of it,
+ * set up a plausible C stack frame, and dispatch to the C handler.
+ * On return, do vmrte virtual instruction with SP where we started.
+ *
+ * VM Spec 0.5 uses a trap to fetch HVM record now.
+ */
+
+/*
+ * Save full register state, while setting up thread_info struct
+ * pointer derived from kernel stack pointer in THREADINFO_REG
+ * register, putting prior thread_info.regs pointer in a callee-save
+ * register (R24, which had better not ever be assigned to THREADINFO_REG),
+ * and updating thread_info.regs to point to current stack frame,
+ * so as to support nested events in kernel mode.
+ *
+ * As this is common code, we set the pt_regs system call number
+ * to -1 for all events.  It will be replaced with the system call
+ * number in the case where we decode a system call (trap0(#1)).
+ */
+
+#define save_pt_regs()\
+	memd(R0 + #_PT_R3130) = R31:30; \
+	{ memw(R0 + #_PT_R2928) = R28; \
+	  R31 = memw(R0 + #_PT_ER_VMPSP); }\
+	{ memw(R0 + #(_PT_R2928 + 4)) = R31; \
+	  R31 = ugp; } \
+	{ memd(R0 + #_PT_R2726) = R27:26; \
+	  R30 = gp ; } \
+	memd(R0 + #_PT_R2524) = R25:24; \
+	memd(R0 + #_PT_R2322) = R23:22; \
+	memd(R0 + #_PT_R2120) = R21:20; \
+	memd(R0 + #_PT_R1918) = R19:18; \
+	memd(R0 + #_PT_R1716) = R17:16; \
+	memd(R0 + #_PT_R1514) = R15:14; \
+	memd(R0 + #_PT_R1312) = R13:12; \
+	{ memd(R0 + #_PT_R1110) = R11:10; \
+	  R15 = lc0; } \
+	{ memd(R0 + #_PT_R0908) = R9:8; \
+	  R14 = sa0; } \
+	{ memd(R0 + #_PT_R0706) = R7:6; \
+	  R13 = lc1; } \
+	{ memd(R0 + #_PT_R0504) = R5:4; \
+	  R12 = sa1; } \
+	{ memd(R0 + #_PT_UGPGP) = R31:30; \
+	  R11 = m1; \
+	  R2.H = #HI(_THREAD_SIZE); } \
+	{ memd(R0 + #_PT_LC0SA0) = R15:14; \
+	  R10 = m0; \
+	  R2.L = #LO(_THREAD_SIZE); } \
+	{ memd(R0 + #_PT_LC1SA1) = R13:12; \
+	  R15 = p3:0; \
+	  R2 = neg(R2); } \
+	{ memd(R0 + #_PT_M1M0) = R11:10; \
+	  R14  = usr; \
+	  R2 = and(R0,R2); } \
+	{ memd(R0 + #_PT_PREDSUSR) =  R15:14; \
+	  THREADINFO_REG = R2; } \
+	{ r24 = memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS); \
+	  memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R0; \
+	  R2 = #-1; } \
+	{ memw(R0 + #_PT_SYSCALL_NR) = R2; \
+	  R30 = #0; }
+
+/*
+ * Restore registers and thread_info.regs state. THREADINFO_REG
+ * is assumed to still be sane, and R24 to have been correctly
+ * preserved. Don't restore R29 (SP) until later.
+ */
+
+#define restore_pt_regs() \
+	{ memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R24; \
+	  R15:14 = memd(R0 + #_PT_PREDSUSR); } \
+	{ R11:10 = memd(R0 + #_PT_M1M0); \
+	  p3:0 = R15; } \
+	{ R13:12 = memd(R0 + #_PT_LC1SA1); \
+	  usr = R14; } \
+	{ R15:14 = memd(R0 + #_PT_LC0SA0); \
+	  m1 = R11; } \
+	{ R3:2 = memd(R0 + #_PT_R0302); \
+	  m0 = R10; } \
+	{ R5:4 = memd(R0 + #_PT_R0504); \
+	  lc1 = R13; } \
+	{ R7:6 = memd(R0 + #_PT_R0706); \
+	  sa1 = R12; } \
+	{ R9:8 = memd(R0 + #_PT_R0908); \
+	  lc0 = R15; } \
+	{ R11:10 = memd(R0 + #_PT_R1110); \
+	  sa0 = R14; } \
+	{ R13:12 = memd(R0 + #_PT_R1312); \
+	  R15:14 = memd(R0 + #_PT_R1514); } \
+	{ R17:16 = memd(R0 + #_PT_R1716); \
+	  R19:18 = memd(R0 + #_PT_R1918); } \
+	{ R21:20 = memd(R0 + #_PT_R2120); \
+	  R23:22 = memd(R0 + #_PT_R2322); } \
+	{ R25:24 = memd(R0 + #_PT_R2524); \
+	  R27:26 = memd(R0 + #_PT_R2726); } \
+	R31:30 = memd(R0 + #_PT_UGPGP); \
+	{ R28 = memw(R0 + #_PT_R2928); \
+	  ugp = R31; } \
+	{ R31:30 = memd(R0 + #_PT_R3130); \
+	  gp = R30; }
+
+	/*
+	 * Clears off enough space for the rest of pt_regs; evrec is a part
+	 * of pt_regs in HVM mode.  Save R0/R1, set handler's address in R1.
+	 * R0 is the address of pt_regs and is the parameter to save_pt_regs.
+	 */
+
+/*
+ * Since the HVM isn't automagically pushing the EVREC onto the stack anymore,
+ * we'll subract the entire size out and then fill it in ourselves.
+ * Need to save off R0, R1, R2, R3 immediately.
+ */
+
+#define	vm_event_entry(CHandler) \
+	{ \
+		R29 = add(R29, #-(_PT_REGS_SIZE)); \
+		memd(R29 + #(_PT_R0100 + -_PT_REGS_SIZE)) = R1:0; \
+	} \
+	{ \
+		memd(R29 +#_PT_R0302) = R3:2; \
+	} \
+	trap1(#HVM_TRAP1_VMGETREGS); \
+	{ \
+		memd(R29 + #_PT_ER_VMEL) = R1:0; \
+		R0 = R29; \
+		R1.L = #LO(CHandler); \
+	} \
+	{ \
+		memd(R29 + #_PT_ER_VMPSP) = R3:2; \
+		R1.H = #HI(CHandler); \
+		jump event_dispatch; \
+	}
+
+.text
+	/*
+	 * Do bulk save/restore in one place.
+	 * Adds a jump to dispatch latency, but
+	 * saves hundreds of bytes.
+	 */
+
+event_dispatch:
+	save_pt_regs()
+	callr	r1
+
+	/*
+	 * If we were in kernel mode, we don't need to check scheduler
+	 * or signals if CONFIG_PREEMPT is not set.  If set, then it has
+	 * to jump to a need_resched kind of block.
+	 * BTW, CONFIG_PREEMPT is not supported yet.
+	 */
+
+#ifdef CONFIG_PREEMPT
+	R0 = #VM_INT_DISABLE
+	trap1(#HVM_TRAP1_VMSETIE)
+#endif
+
+	/*  "Nested control path" -- if the previous mode was kernel  */
+	R0 = memw(R29 + #_PT_ER_VMEST);
+	P0 = tstbit(R0, #HVM_VMEST_UM_SFT);
+	if !P0 jump restore_all;
+	/*
+	 * Returning from system call, normally coming back from user mode
+	 */
+return_from_syscall:
+	/*  Disable interrupts while checking TIF  */
+	R0 = #VM_INT_DISABLE
+	trap1(#HVM_TRAP1_VMSETIE)
+
+	/*
+	 * Coming back from the C-world, our thread info pointer
+	 * should be in the designated register (usually R19)
+	 */
+	R1.L = #LO(_TIF_ALLWORK_MASK)
+	{
+		R1.H = #HI(_TIF_ALLWORK_MASK);
+		R0 = memw(THREADINFO_REG + #_THREAD_INFO_FLAGS);
+	}
+
+	/*
+	 * Compare against the "return to userspace" _TIF_WORK_MASK
+	 */
+	R1 = and(R1,R0);
+	{ P0 = cmp.eq(R1,#0); if (!P0.new) jump:t work_pending;}
+	jump restore_all;  /*  we're outta here!  */
+
+work_pending:
+	{
+		P0 = tstbit(R1, #TIF_NEED_RESCHED);
+		if (!P0.new) jump:nt work_notifysig;
+	}
+	call schedule
+	jump return_from_syscall;  /*  check for more work  */
+
+work_notifysig:
+	/*  this is the part that's kind of fuzzy.  */
+	R1 = and(R0, #(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME));
+	P0 = cmp.eq(R1, #0);
+	if P0 jump restore_all
+	R1 = R0; 	/* unsigned long thread_info_flags */
+	R0 = R29;	/* regs should still be at top of stack  */
+	call do_notify_resume
+
+restore_all:
+	/* Disable interrupts, if they weren't already, before reg restore.  */
+	R0 = #VM_INT_DISABLE
+	trap1(#HVM_TRAP1_VMSETIE)
+
+	/*  do the setregs here for VM 0.5  */
+	/*  R29 here should already be pointing at pt_regs  */
+	R1:0 = memd(R29 + #_PT_ER_VMEL);
+	R3:2 = memd(R29 + #_PT_ER_VMPSP);
+	trap1(#HVM_TRAP1_VMSETREGS);
+
+	R0 = R29
+	restore_pt_regs()
+	R1:0 = memd(R29 + #_PT_R0100);
+	R29 = add(R29, #_PT_REGS_SIZE);
+	trap1(#HVM_TRAP1_VMRTE)
+	/* Notreached */
+
+	.globl _K_enter_genex
+_K_enter_genex:
+	vm_event_entry(do_genex)
+
+	.globl _K_enter_interrupt
+_K_enter_interrupt:
+	vm_event_entry(arch_do_IRQ)
+
+	.globl _K_enter_trap0
+_K_enter_trap0:
+	vm_event_entry(do_trap0)
+
+	.globl _K_enter_machcheck
+_K_enter_machcheck:
+	vm_event_entry(do_machcheck)
+
+
+	.globl ret_from_fork
+ret_from_fork:
+	call schedule_tail
+	jump return_from_syscall
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/vm_events.c linux-libre-3.2-gnu/arch/hexagon/kernel/vm_events.c
--- linux-libre-3.1-gnu/arch/hexagon/kernel/vm_events.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/vm_events.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,101 @@
+/*
+ * Mostly IRQ support for Hexagon
+ *
+ * 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 <asm/registers.h>
+#include <linux/irq.h>
+#include <linux/hardirq.h>
+#include <asm/system.h>
+
+/*
+ * show_regs - print pt_regs structure
+ * @regs: pointer to pt_regs
+ *
+ * To-do:  add all the accessor definitions to registers.h
+ *
+ * Will make this routine a lot easier to write.
+ */
+void show_regs(struct pt_regs *regs)
+{
+	printk(KERN_EMERG "restart_r0: \t0x%08lx   syscall_nr: %ld\n",
+	       regs->restart_r0, regs->syscall_nr);
+	printk(KERN_EMERG "preds: \t\t0x%08lx\n", regs->preds);
+	printk(KERN_EMERG "lc0: \t0x%08lx   sa0: 0x%08lx   m0:  0x%08lx\n",
+	       regs->lc0, regs->sa0, regs->m0);
+	printk(KERN_EMERG "lc1: \t0x%08lx   sa1: 0x%08lx   m1:  0x%08lx\n",
+	       regs->lc1, regs->sa1, regs->m1);
+	printk(KERN_EMERG "gp: \t0x%08lx   ugp: 0x%08lx   usr: 0x%08lx\n",
+	       regs->gp, regs->ugp, regs->usr);
+	printk(KERN_EMERG "r0: \t0x%08lx %08lx %08lx %08lx\n", regs->r00,
+		regs->r01,
+		regs->r02,
+		regs->r03);
+	printk(KERN_EMERG "r4:  \t0x%08lx %08lx %08lx %08lx\n", regs->r04,
+		regs->r05,
+		regs->r06,
+		regs->r07);
+	printk(KERN_EMERG "r8:  \t0x%08lx %08lx %08lx %08lx\n", regs->r08,
+		regs->r09,
+		regs->r10,
+		regs->r11);
+	printk(KERN_EMERG "r12: \t0x%08lx %08lx %08lx %08lx\n", regs->r12,
+		regs->r13,
+		regs->r14,
+		regs->r15);
+	printk(KERN_EMERG "r16: \t0x%08lx %08lx %08lx %08lx\n", regs->r16,
+		regs->r17,
+		regs->r18,
+		regs->r19);
+	printk(KERN_EMERG "r20: \t0x%08lx %08lx %08lx %08lx\n", regs->r20,
+		regs->r21,
+		regs->r22,
+		regs->r23);
+	printk(KERN_EMERG "r24: \t0x%08lx %08lx %08lx %08lx\n", regs->r24,
+		regs->r25,
+		regs->r26,
+		regs->r27);
+	printk(KERN_EMERG "r28: \t0x%08lx %08lx %08lx %08lx\n", regs->r28,
+		regs->r29,
+		regs->r30,
+		regs->r31);
+
+	printk(KERN_EMERG "elr: \t0x%08lx   cause: 0x%08lx   user_mode: %d\n",
+		pt_elr(regs), pt_cause(regs), user_mode(regs));
+	printk(KERN_EMERG "psp: \t0x%08lx   badva: 0x%08lx   int_enabled: %d\n",
+		pt_psp(regs), pt_badva(regs), ints_enabled(regs));
+}
+
+void dummy_handler(struct pt_regs *regs)
+{
+	unsigned int elr = pt_elr(regs);
+	printk(KERN_ERR "Unimplemented handler; ELR=0x%08x\n", elr);
+}
+
+
+void arch_do_IRQ(struct pt_regs *regs)
+{
+	int irq = pt_cause(regs);
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
+	irq_enter();
+	generic_handle_irq(irq);
+	irq_exit();
+	set_irq_regs(old_regs);
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/vm_init_segtable.S linux-libre-3.2-gnu/arch/hexagon/kernel/vm_init_segtable.S
--- linux-libre-3.1-gnu/arch/hexagon/kernel/vm_init_segtable.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/vm_init_segtable.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,442 @@
+/*
+ * Initial page table for Linux kernel under Hexagon VM,
+ *
+ * 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.
+ */
+
+/*
+ * These tables are pre-computed and linked into kernel.
+ */
+
+#include <asm/vm_mmu.h>
+/*  #include <asm/iomap.h>  */
+
+/*
+ * Start with mapping PA=0 to both VA=0x0 and VA=0xc000000 as 16MB large pages.
+ * No user mode access, RWX, write-back cache.  The entry needs
+ * to be replicated for all 4 virtual segments mapping to the page.
+ */
+
+/* "Big Kernel Page"  */
+#define BKP(pa) (((pa) & __HVM_PTE_PGMASK_4MB)		\
+		| __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X	\
+		| __HEXAGON_C_WB_L2 << 6			\
+		| __HVM_PDE_S_16MB)
+
+/*  No cache version  */
+
+#define BKPG_IO(pa) (((pa) & __HVM_PTE_PGMASK_16MB) \
+			| __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X \
+			| __HVM_PDE_S_16MB | __HEXAGON_C_DEV << 6 )
+
+#define FOURK_IO(pa) (((pa) & __HVM_PTE_PGMASK_4KB) \
+			| __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X \
+			| __HEXAGON_C_DEV << 6 )
+
+#define L2_PTR(pa) (((pa) & __HVM_PTE_PGMASK_4KB) \
+			| __HVM_PDE_S_4KB  )
+
+#define X __HVM_PDE_S_INVALID
+
+	.p2align 12
+	.globl swapper_pg_dir
+	.globl _K_init_segtable
+swapper_pg_dir:
+/* VA 0x00000000 */
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+/* VA 0x40000000 */
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+/* VA 0x80000000 */
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+/*0xa8*/.word X,X,X,X
+#ifdef CONFIG_COMET_EARLY_UART_DEBUG
+UART_PTE_ENTRY:
+/*0xa9*/.word BKPG_IO(0xa9000000),BKPG_IO(0xa9000000),BKPG_IO(0xa9000000),BKPG_IO(0xa9000000)
+#else
+/*0xa9*/.word X,X,X,X
+#endif
+/*0xaa*/.word X,X,X,X
+/*0xab*/.word X,X,X,X
+/*0xac*/.word X,X,X,X
+/*0xad*/.word X,X,X,X
+/*0xae*/.word X,X,X,X
+/*0xaf*/.word X,X,X,X
+/*0xb0*/.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+_K_init_segtable:
+/* VA 0xC0000000 */
+	.word BKP(0x00000000), BKP(0x00400000), BKP(0x00800000), BKP(0x00c00000)
+	.word BKP(0x01000000), BKP(0x01400000), BKP(0x01800000), BKP(0x01c00000)
+	.word BKP(0x02000000), BKP(0x02400000), BKP(0x02800000), BKP(0x02c00000)
+	.word BKP(0x03000000), BKP(0x03400000), BKP(0x03800000), BKP(0x03c00000)
+	.word BKP(0x04000000), BKP(0x04400000), BKP(0x04800000), BKP(0x04c00000)
+	.word BKP(0x05000000), BKP(0x05400000), BKP(0x05800000), BKP(0x05c00000)
+	.word BKP(0x06000000), BKP(0x06400000), BKP(0x06800000), BKP(0x06c00000)
+	.word BKP(0x07000000), BKP(0x07400000), BKP(0x07800000), BKP(0x07c00000)
+
+	.word BKP(0x08000000), BKP(0x08400000), BKP(0x08800000), BKP(0x08c00000)
+	.word BKP(0x09000000), BKP(0x09400000), BKP(0x09800000), BKP(0x09c00000)
+	.word BKP(0x0a000000), BKP(0x0a400000), BKP(0x0a800000), BKP(0x0ac00000)
+	.word BKP(0x0b000000), BKP(0x0b400000), BKP(0x0b800000), BKP(0x0bc00000)
+	.word BKP(0x0c000000), BKP(0x0c400000), BKP(0x0c800000), BKP(0x0cc00000)
+	.word BKP(0x0d000000), BKP(0x0d400000), BKP(0x0d800000), BKP(0x0dc00000)
+	.word BKP(0x0e000000), BKP(0x0e400000), BKP(0x0e800000), BKP(0x0ec00000)
+	.word BKP(0x0f000000), BKP(0x0f400000), BKP(0x0f800000), BKP(0x0fc00000)
+
+	.word BKP(0x10000000), BKP(0x10400000), BKP(0x10800000), BKP(0x10c00000)
+	.word BKP(0x11000000), BKP(0x11400000), BKP(0x11800000), BKP(0x11c00000)
+	.word BKP(0x12000000), BKP(0x12400000), BKP(0x12800000), BKP(0x12c00000)
+	.word BKP(0x13000000), BKP(0x13400000), BKP(0x13800000), BKP(0x13c00000)
+	.word BKP(0x14000000), BKP(0x14400000), BKP(0x14800000), BKP(0x14c00000)
+	.word BKP(0x15000000), BKP(0x15400000), BKP(0x15800000), BKP(0x15c00000)
+	.word BKP(0x16000000), BKP(0x16400000), BKP(0x16800000), BKP(0x16c00000)
+	.word BKP(0x17000000), BKP(0x17400000), BKP(0x17800000), BKP(0x17c00000)
+
+	.word BKP(0x18000000), BKP(0x18400000), BKP(0x18800000), BKP(0x18c00000)
+	.word BKP(0x19000000), BKP(0x19400000), BKP(0x19800000), BKP(0x19c00000)
+	.word BKP(0x1a000000), BKP(0x1a400000), BKP(0x1a800000), BKP(0x1ac00000)
+	.word BKP(0x1b000000), BKP(0x1b400000), BKP(0x1b800000), BKP(0x1bc00000)
+	.word BKP(0x1c000000), BKP(0x1c400000), BKP(0x1c800000), BKP(0x1cc00000)
+	.word BKP(0x1d000000), BKP(0x1d400000), BKP(0x1d800000), BKP(0x1dc00000)
+	.word BKP(0x1e000000), BKP(0x1e400000), BKP(0x1e800000), BKP(0x1ec00000)
+	.word BKP(0x1f000000), BKP(0x1f400000), BKP(0x1f800000), BKP(0x1fc00000)
+
+	.word BKP(0x20000000), BKP(0x20400000), BKP(0x20800000), BKP(0x20c00000)
+	.word BKP(0x21000000), BKP(0x21400000), BKP(0x21800000), BKP(0x21c00000)
+	.word BKP(0x22000000), BKP(0x22400000), BKP(0x22800000), BKP(0x22c00000)
+	.word BKP(0x23000000), BKP(0x23400000), BKP(0x23800000), BKP(0x23c00000)
+	.word BKP(0x24000000), BKP(0x24400000), BKP(0x24800000), BKP(0x24c00000)
+	.word BKP(0x25000000), BKP(0x25400000), BKP(0x25800000), BKP(0x25c00000)
+	.word BKP(0x26000000), BKP(0x26400000), BKP(0x26800000), BKP(0x26c00000)
+	.word BKP(0x27000000), BKP(0x27400000), BKP(0x27800000), BKP(0x27c00000)
+
+	.word BKP(0x28000000), BKP(0x28400000), BKP(0x28800000), BKP(0x28c00000)
+	.word BKP(0x29000000), BKP(0x29400000), BKP(0x29800000), BKP(0x29c00000)
+	.word BKP(0x2a000000), BKP(0x2a400000), BKP(0x2a800000), BKP(0x2ac00000)
+	.word BKP(0x2b000000), BKP(0x2b400000), BKP(0x2b800000), BKP(0x2bc00000)
+	.word BKP(0x2c000000), BKP(0x2c400000), BKP(0x2c800000), BKP(0x2cc00000)
+	.word BKP(0x2d000000), BKP(0x2d400000), BKP(0x2d800000), BKP(0x2dc00000)
+	.word BKP(0x2e000000), BKP(0x2e400000), BKP(0x2e800000), BKP(0x2ec00000)
+	.word BKP(0x2f000000), BKP(0x2f400000), BKP(0x2f800000), BKP(0x2fc00000)
+
+	.word BKP(0x30000000), BKP(0x30400000), BKP(0x30800000), BKP(0x30c00000)
+	.word BKP(0x31000000), BKP(0x31400000), BKP(0x31800000), BKP(0x31c00000)
+	.word BKP(0x32000000), BKP(0x32400000), BKP(0x32800000), BKP(0x32c00000)
+	.word BKP(0x33000000), BKP(0x33400000), BKP(0x33800000), BKP(0x33c00000)
+	.word BKP(0x34000000), BKP(0x34400000), BKP(0x34800000), BKP(0x34c00000)
+	.word BKP(0x35000000), BKP(0x35400000), BKP(0x35800000), BKP(0x35c00000)
+	.word BKP(0x36000000), BKP(0x36400000), BKP(0x36800000), BKP(0x36c00000)
+	.word BKP(0x37000000), BKP(0x37400000), BKP(0x37800000), BKP(0x37c00000)
+
+	.word BKP(0x38000000), BKP(0x38400000), BKP(0x38800000), BKP(0x38c00000)
+	.word BKP(0x39000000), BKP(0x39400000), BKP(0x39800000), BKP(0x39c00000)
+	.word BKP(0x3a000000), BKP(0x3a400000), BKP(0x3a800000), BKP(0x3ac00000)
+	.word BKP(0x3b000000), BKP(0x3b400000), BKP(0x3b800000), BKP(0x3bc00000)
+	.word BKP(0x3c000000), BKP(0x3c400000), BKP(0x3c800000), BKP(0x3cc00000)
+	.word BKP(0x3d000000), BKP(0x3d400000), BKP(0x3d800000), BKP(0x3dc00000)
+_K_io_map:
+	.word X,X,X,X /* 0x3e000000 - device IO early remap */
+	.word X,X,X,X /* 0x3f000000 - hypervisor space*/
+
+#if 0
+/*
+ * This is in here as an example for devices which need to be mapped really
+ * early.
+ */
+	.p2align 12
+	.globl _K_io_kmap
+	.globl _K_init_devicetable
+_K_init_devicetable:  /*  Should be 4MB worth of entries  */
+	.word FOURK_IO(MSM_GPIO1_PHYS),FOURK_IO(MSM_GPIO2_PHYS),FOURK_IO(MSM_SIRC_PHYS),X
+	.word FOURK_IO(TLMM_GPIO1_PHYS),X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/vmlinux.lds.S linux-libre-3.2-gnu/arch/hexagon/kernel/vmlinux.lds.S
--- linux-libre-3.1-gnu/arch/hexagon/kernel/vmlinux.lds.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/vmlinux.lds.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,88 @@
+/*
+ * Linker script for Hexagon kernel
+ *
+ * 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.
+ */
+
+#define LOAD_OFFSET PAGE_OFFSET
+
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/asm-offsets.h>	/*  Most of the kernel defines are here  */
+#include <asm/mem-layout.h>	/*  except for page_offset  */
+#include <asm/cache.h>		/*  and now we're pulling cache line size  */
+OUTPUT_ARCH(hexagon)
+ENTRY(stext)
+
+jiffies = jiffies_64;
+
+/*
+See asm-generic/vmlinux.lds.h for expansion of some of these macros.
+See asm-generic/sections.h for seemingly required labels.
+*/
+
+#define PAGE_SIZE _PAGE_SIZE
+
+/*  This LOAD_OFFSET is temporary for debugging on the simulator; it may change
+    for hypervisor pseudo-physical memory.  */
+
+
+SECTIONS
+{
+	. = PAGE_OFFSET + LOAD_ADDRESS;
+
+	__init_begin = .;
+	HEAD_TEXT_SECTION
+	INIT_TEXT_SECTION(PAGE_SIZE)
+	PERCPU_SECTION(L1_CACHE_BYTES)
+	__init_end = .;
+
+        . = ALIGN(_PAGE_SIZE);
+	_stext = .;
+	.text : AT(ADDR(.text) - LOAD_OFFSET) {
+		_text = .;
+		TEXT_TEXT
+		SCHED_TEXT
+		LOCK_TEXT
+		KPROBES_TEXT
+		*(.fixup)
+	}
+	_etext = .;
+
+	INIT_DATA_SECTION(PAGE_SIZE)
+
+	_sdata = .;
+		RW_DATA_SECTION(32,PAGE_SIZE,PAGE_SIZE)
+		RO_DATA_SECTION(PAGE_SIZE)
+	_edata = .;
+
+	EXCEPTION_TABLE(16)
+	NOTES
+
+	BSS_SECTION(_PAGE_SIZE, _PAGE_SIZE, _PAGE_SIZE)
+
+	_end = .;
+
+	/DISCARD/ : {
+		EXIT_TEXT
+		EXIT_DATA
+		EXIT_CALL
+	}
+
+	STABS_DEBUG
+	DWARF_DEBUG
+
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/vm_ops.S linux-libre-3.2-gnu/arch/hexagon/kernel/vm_ops.S
--- linux-libre-3.1-gnu/arch/hexagon/kernel/vm_ops.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/vm_ops.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,102 @@
+/*
+ * Hexagon VM instruction support
+ *
+ * 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/linkage.h>
+#include <asm/hexagon_vm.h>
+
+/*
+ * C wrappers for virtual machine "instructions".  These
+ * could be, and perhaps some day will be, handled as in-line
+ * macros, but for tracing/debugging it's handy to have
+ * a single point of invocation for each of them.
+ * Conveniently, they take paramters and return values
+ * consistent with the ABI calling convention.
+ */
+
+ENTRY(__vmrte)
+	trap1(#HVM_TRAP1_VMRTE);
+	jumpr	R31;
+
+ENTRY(__vmsetvec)
+	trap1(#HVM_TRAP1_VMSETVEC);
+	jumpr	R31;
+
+ENTRY(__vmsetie)
+	trap1(#HVM_TRAP1_VMSETIE);
+	jumpr	R31;
+
+ENTRY(__vmgetie)
+	trap1(#HVM_TRAP1_VMGETIE);
+	jumpr	R31;
+
+ENTRY(__vmintop)
+	trap1(#HVM_TRAP1_VMINTOP);
+	jumpr	R31;
+
+ENTRY(__vmclrmap)
+	trap1(#HVM_TRAP1_VMCLRMAP);
+	jumpr	R31;
+
+ENTRY(__vmnewmap)
+	r1 = #VM_NEWMAP_TYPE_PGTABLES;
+	trap1(#HVM_TRAP1_VMNEWMAP);
+	jumpr	R31;
+
+ENTRY(__vmcache)
+	trap1(#HVM_TRAP1_VMCACHE);
+	jumpr	R31;
+
+ENTRY(__vmgettime)
+	trap1(#HVM_TRAP1_VMGETTIME);
+	jumpr	R31;
+
+ENTRY(__vmsettime)
+	trap1(#HVM_TRAP1_VMSETTIME);
+	jumpr	R31;
+
+ENTRY(__vmwait)
+	trap1(#HVM_TRAP1_VMWAIT);
+	jumpr	R31;
+
+ENTRY(__vmyield)
+	trap1(#HVM_TRAP1_VMYIELD);
+	jumpr	R31;
+
+ENTRY(__vmstart)
+	trap1(#HVM_TRAP1_VMSTART);
+	jumpr	R31;
+
+ENTRY(__vmstop)
+	trap1(#HVM_TRAP1_VMSTOP);
+	jumpr	R31;
+
+ENTRY(__vmvpid)
+	trap1(#HVM_TRAP1_VMVPID);
+	jumpr	R31;
+
+/*  Probably not actually going to use these; see vm_entry.S  */
+
+ENTRY(__vmsetregs)
+	trap1(#HVM_TRAP1_VMSETREGS);
+	jumpr	R31;
+
+ENTRY(__vmgetregs)
+	trap1(#HVM_TRAP1_VMGETREGS);
+	jumpr	R31;
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/vm_switch.S linux-libre-3.2-gnu/arch/hexagon/kernel/vm_switch.S
--- linux-libre-3.1-gnu/arch/hexagon/kernel/vm_switch.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/vm_switch.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,95 @@
+/*
+ * Context switch support for Hexagon
+ *
+ * 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 <asm/asm-offsets.h>
+
+.text
+
+/*
+ * The register used as a fast-path thread information pointer
+ * is determined as a kernel configuration option.  If it happens
+ * to be a callee-save register, we're going to be saving and
+ * restoring it twice here.
+ *
+ * This code anticipates a revised ABI where R20-23 are added
+ * to the set of callee-save registers, but this should be
+ * backward compatible to legacy tools.
+ */
+
+
+/*
+ *	void switch_to(struct task_struct *prev,
+ *		struct task_struct *next, struct task_struct *last);
+ */
+	.p2align 2
+	.globl __switch_to
+	.type	__switch_to, @function
+
+/*
+ * When we exit the wormhole, we need to store the previous task
+ * in the new R0's pointer.  Technically it should be R2, but they should
+ * be the same; seems like a legacy thing.  In short, don't butcher
+ * R0, let it go back out unmolested.
+ */
+
+__switch_to:
+	/*
+	 * Push callee-saves onto "prev" stack.
+	 * Here, we're sneaky because the LR and FP
+	 * storage of the thread_stack structure
+	 * is automagically allocated by allocframe,
+	 * so we pass struct size less 8.
+	 */
+	allocframe(#(_SWITCH_STACK_SIZE - 8));
+	memd(R29+#(_SWITCH_R2726))=R27:26;
+	memd(R29+#(_SWITCH_R2524))=R25:24;
+	memd(R29+#(_SWITCH_R2322))=R23:22;
+	memd(R29+#(_SWITCH_R2120))=R21:20;
+	memd(R29+#(_SWITCH_R1918))=R19:18;
+	memd(R29+#(_SWITCH_R1716))=R17:16;
+	/* Stash thread_info pointer in task_struct */
+	memw(R0+#_TASK_THREAD_INFO) = THREADINFO_REG;
+	memw(R0 +#(_TASK_STRUCT_THREAD + _THREAD_STRUCT_SWITCH_SP)) = R29;
+	/* Switch to "next" stack and restore callee saves from there */
+	R29 = memw(R1 + #(_TASK_STRUCT_THREAD + _THREAD_STRUCT_SWITCH_SP));
+	{
+	    R27:26 = memd(R29+#(_SWITCH_R2726));
+	    R25:24 = memd(R29+#(_SWITCH_R2524));
+	}
+	{
+	    R23:22 = memd(R29+#(_SWITCH_R2322));
+	    R21:20 = memd(R29+#(_SWITCH_R2120));
+	}
+	{
+	    R19:18 = memd(R29+#(_SWITCH_R1918));
+	    R17:16 = memd(R29+#(_SWITCH_R1716));
+	}
+	{
+	    /* THREADINFO_REG is currently one of the callee-saved regs
+	     * above, and so be sure to re-load it last.
+	     */
+	    THREADINFO_REG = memw(R1 + #_TASK_THREAD_INFO);
+	    R31:30 = memd(R29+#_SWITCH_FP);
+	}
+	{
+	    R29 = add(R29,#_SWITCH_STACK_SIZE);
+	    jumpr R31;
+	}
+	.size	__switch_to, .-__switch_to
diff -druN linux-libre-3.1-gnu/arch/hexagon/kernel/vm_vectors.S linux-libre-3.2-gnu/arch/hexagon/kernel/vm_vectors.S
--- linux-libre-3.1-gnu/arch/hexagon/kernel/vm_vectors.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/kernel/vm_vectors.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,48 @@
+/*
+ * Event jump tables
+ *
+ * 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 <asm/hexagon_vm.h>
+
+.text
+
+/*  This is registered early on to allow angel  */
+.global _K_provisional_vec
+_K_provisional_vec:
+	jump 1f;
+	jump 1f;
+	jump 1f;
+	jump 1f;
+	jump 1f;
+	trap1(#HVM_TRAP1_VMRTE)
+	jump 1f;
+	jump 1f;
+
+
+.global _K_VM_event_vector
+_K_VM_event_vector:
+1:
+	jump 1b;  /*  Reset  */
+	jump _K_enter_machcheck;
+	jump _K_enter_genex;
+	jump 1b;  /*  3 Rsvd  */
+	jump 1b;  /*  4 Rsvd  */
+	jump _K_enter_trap0;
+	jump 1b;  /*  6 Rsvd  */
+	jump _K_enter_interrupt;
diff -druN linux-libre-3.1-gnu/arch/hexagon/lib/checksum.c linux-libre-3.2-gnu/arch/hexagon/lib/checksum.c
--- linux-libre-3.1-gnu/arch/hexagon/lib/checksum.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/lib/checksum.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,203 @@
+/*
+ * Checksum functions for Hexagon
+ *
+ * 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.
+ */
+
+/*  This was derived from arch/alpha/lib/checksum.c  */
+
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/byteorder.h>
+#include <net/checksum.h>
+#include <linux/uaccess.h>
+#include <asm/intrinsics.h>
+
+
+/*  Vector value operations  */
+#define SIGN(x, y)	((0x8000ULL*x)<<y)
+#define CARRY(x, y)	((0x0002ULL*x)<<y)
+#define SELECT(x, y)	((0x0001ULL*x)<<y)
+
+#define VR_NEGATE(a, b, c, d)	(SIGN(a, 48) + SIGN(b, 32) + SIGN(c, 16) \
+	+ SIGN(d, 0))
+#define VR_CARRY(a, b, c, d)	(CARRY(a, 48) + CARRY(b, 32) + CARRY(c, 16) \
+	+ CARRY(d, 0))
+#define VR_SELECT(a, b, c, d)	(SELECT(a, 48) + SELECT(b, 32) + SELECT(c, 16) \
+	+ SELECT(d, 0))
+
+
+/* optimized HEXAGON V3 intrinsic version */
+static inline unsigned short from64to16(u64 x)
+{
+	u64 sum;
+
+	sum = HEXAGON_P_vrmpyh_PP(x^VR_NEGATE(1, 1, 1, 1),
+			     VR_SELECT(1, 1, 1, 1));
+	sum += VR_CARRY(0, 0, 1, 0);
+	sum = HEXAGON_P_vrmpyh_PP(sum, VR_SELECT(0, 0, 1, 1));
+
+	return 0xFFFF & sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented.
+ */
+__sum16 csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
+			  unsigned short len, unsigned short proto,
+			  __wsum sum)
+{
+	return (__force __sum16)~from64to16(
+		(__force u64)saddr + (__force u64)daddr +
+		(__force u64)sum + ((len + proto) << 8));
+}
+
+__wsum csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
+			  unsigned short len, unsigned short proto,
+			  __wsum sum)
+{
+	u64 result;
+
+	result = (__force u64)saddr + (__force u64)daddr +
+		 (__force u64)sum + ((len + proto) << 8);
+
+	/* Fold down to 32-bits so we don't lose in the typedef-less
+	   network stack.  */
+	/* 64 to 33 */
+	result = (result & 0xffffffffUL) + (result >> 32);
+	/* 33 to 32 */
+	result = (result & 0xffffffffUL) + (result >> 32);
+	return (__force __wsum)result;
+}
+EXPORT_SYMBOL(csum_tcpudp_nofold);
+
+/*
+ * Do a 64-bit checksum on an arbitrary memory area..
+ *
+ * This isn't a great routine, but it's not _horrible_ either. The
+ * inner loop could be unrolled a bit further, and there are better
+ * ways to do the carry, but this is reasonable.
+ */
+
+/* optimized HEXAGON intrinsic version, with over read fixed */
+unsigned int do_csum(const void *voidptr, int len)
+{
+	u64 sum0, sum1, x0, x1, *ptr8_o, *ptr8_e, *ptr8;
+	int i, start, mid, end, mask;
+	const char *ptr = voidptr;
+	unsigned short *ptr2;
+	unsigned int *ptr4;
+
+	if (len <= 0)
+		return 0;
+
+	start = 0xF & (16-(((int) ptr) & 0xF)) ;
+	mask  = 0x7fffffffUL >> HEXAGON_R_cl0_R(len);
+	start = start & mask ;
+
+	mid = len - start;
+	end = mid & 0xF;
+	mid = mid>>4;
+	sum0 = mid << 18;
+	sum1 = 0;
+
+	if (start & 1)
+		sum0 += (u64) (ptr[0] << 8);
+	ptr2 = (unsigned short *) &ptr[start & 1];
+	if (start & 2)
+		sum1 += (u64) ptr2[0];
+	ptr4 = (unsigned int *) &ptr[start & 3];
+	if (start & 4) {
+		sum0 = HEXAGON_P_vrmpyhacc_PP(sum0,
+			VR_NEGATE(0, 0, 1, 1)^((u64)ptr4[0]),
+			VR_SELECT(0, 0, 1, 1));
+		sum0 += VR_SELECT(0, 0, 1, 0);
+	}
+	ptr8 = (u64 *) &ptr[start & 7];
+	if (start & 8) {
+		sum1 = HEXAGON_P_vrmpyhacc_PP(sum1,
+			VR_NEGATE(1, 1, 1, 1)^(ptr8[0]),
+			VR_SELECT(1, 1, 1, 1));
+		sum1 += VR_CARRY(0, 0, 1, 0);
+	}
+	ptr8_o = (u64 *) (ptr + start);
+	ptr8_e = (u64 *) (ptr + start + 8);
+
+	if (mid) {
+		x0 = *ptr8_e; ptr8_e += 2;
+		x1 = *ptr8_o; ptr8_o += 2;
+		if (mid > 1)
+			for (i = 0; i < mid-1; i++) {
+				sum0 = HEXAGON_P_vrmpyhacc_PP(sum0,
+					x0^VR_NEGATE(1, 1, 1, 1),
+					VR_SELECT(1, 1, 1, 1));
+				sum1 = HEXAGON_P_vrmpyhacc_PP(sum1,
+					x1^VR_NEGATE(1, 1, 1, 1),
+					VR_SELECT(1, 1, 1, 1));
+				x0 = *ptr8_e; ptr8_e += 2;
+				x1 = *ptr8_o; ptr8_o += 2;
+			}
+		sum0 = HEXAGON_P_vrmpyhacc_PP(sum0, x0^VR_NEGATE(1, 1, 1, 1),
+			VR_SELECT(1, 1, 1, 1));
+		sum1 = HEXAGON_P_vrmpyhacc_PP(sum1, x1^VR_NEGATE(1, 1, 1, 1),
+			VR_SELECT(1, 1, 1, 1));
+	}
+
+	ptr4 = (unsigned int *) &ptr[start + (mid * 16) + (end & 8)];
+	if (end & 4) {
+		sum1 = HEXAGON_P_vrmpyhacc_PP(sum1,
+			VR_NEGATE(0, 0, 1, 1)^((u64)ptr4[0]),
+			VR_SELECT(0, 0, 1, 1));
+		sum1 += VR_SELECT(0, 0, 1, 0);
+	}
+	ptr2 = (unsigned short *) &ptr[start + (mid * 16) + (end & 12)];
+	if (end & 2)
+		sum0 += (u64) ptr2[0];
+
+	if (end & 1)
+		sum1 += (u64) ptr[start + (mid * 16) + (end & 14)];
+
+	ptr8 = (u64 *) &ptr[start + (mid * 16)];
+	if (end & 8) {
+		sum0 = HEXAGON_P_vrmpyhacc_PP(sum0,
+			VR_NEGATE(1, 1, 1, 1)^(ptr8[0]),
+			VR_SELECT(1, 1, 1, 1));
+		sum0 += VR_CARRY(0, 0, 1, 0);
+	}
+	sum0 = HEXAGON_P_vrmpyh_PP((sum0+sum1)^VR_NEGATE(0, 0, 0, 1),
+		VR_SELECT(0, 0, 1, 1));
+	sum0 += VR_NEGATE(0, 0, 0, 1);
+	sum0 = HEXAGON_P_vrmpyh_PP(sum0, VR_SELECT(0, 0, 1, 1));
+
+	if (start & 1)
+		sum0 = (sum0 << 8) | (0xFF & (sum0 >> 8));
+
+	return 0xFFFF & sum0;
+}
+
+/*
+ * 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-3.1-gnu/arch/hexagon/lib/io.c linux-libre-3.2-gnu/arch/hexagon/lib/io.c
--- linux-libre-3.1-gnu/arch/hexagon/lib/io.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/lib/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,91 @@
+/*
+ * I/O access functions for Hexagon
+ *
+ * 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 <asm/io.h>
+
+/*  These are all FIFO routines!  */
+
+/*
+ * __raw_readsw - read words a short at a time
+ * @addr:  source address
+ * @data:  data address
+ * @len: number of shorts to read
+ */
+void __raw_readsw(const void __iomem *addr, void *data, int len)
+{
+	const volatile short int *src = (short int *) addr;
+	short int *dst = (short int *) data;
+
+	if ((u32)data & 0x1)
+		panic("unaligned pointer to readsw");
+
+	while (len-- > 0)
+		*dst++ = *src;
+
+}
+
+/*
+ * __raw_writesw - read words a short at a time
+ * @addr:  source address
+ * @data:  data address
+ * @len: number of shorts to read
+ */
+void __raw_writesw(void __iomem *addr, const void *data, int len)
+{
+	const short int *src = (short int *)data;
+	volatile short int *dst = (short int *)addr;
+
+	if ((u32)data & 0x1)
+		panic("unaligned pointer to writesw");
+
+	while (len-- > 0)
+		*dst = *src++;
+
+
+}
+
+/*  Pretty sure len is pre-adjusted for the length of the access already */
+void __raw_readsl(const void __iomem *addr, void *data, int len)
+{
+	const volatile long *src = (long *) addr;
+	long *dst = (long *) data;
+
+	if ((u32)data & 0x3)
+		panic("unaligned pointer to readsl");
+
+	while (len-- > 0)
+		*dst++ = *src;
+
+
+}
+
+void __raw_writesl(void __iomem *addr, const void *data, int len)
+{
+	const long *src = (long *)data;
+	volatile long *dst = (long *)addr;
+
+	if ((u32)data & 0x3)
+		panic("unaligned pointer to writesl");
+
+	while (len-- > 0)
+		*dst = *src++;
+
+
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/lib/Makefile linux-libre-3.2-gnu/arch/hexagon/lib/Makefile
--- linux-libre-3.1-gnu/arch/hexagon/lib/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/lib/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,4 @@
+#
+# Makefile for hexagon-specific library files.
+#
+obj-y = checksum.o io.o memcpy.o memset.o
diff -druN linux-libre-3.1-gnu/arch/hexagon/lib/memcpy.S linux-libre-3.2-gnu/arch/hexagon/lib/memcpy.S
--- linux-libre-3.1-gnu/arch/hexagon/lib/memcpy.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/lib/memcpy.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,543 @@
+/*
+ * 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.
+ */
+
+/*
+ * Description
+ *
+ *   library function for memcpy where length bytes are copied from
+ *   ptr_in to ptr_out. ptr_out is returned unchanged.
+ *   Allows any combination of alignment on input and output pointers
+ *   and length from 0 to 2^32-1
+ *
+ * Restrictions
+ *   The arrays should not overlap, the program will produce undefined output
+ *   if they do.
+ *   For blocks less than 16 bytes a byte by byte copy is performed. For
+ *   8byte alignments, and length multiples, a dword copy is performed up to
+ *   96bytes
+ * History
+ *
+ *   DJH  5/15/09 Initial version 1.0
+ *   DJH  6/ 1/09 Version 1.1 modified ABI to inlcude R16-R19
+ *   DJH  7/12/09 Version 1.2 optimized codesize down to 760 was 840
+ *   DJH 10/14/09 Version 1.3 added special loop for aligned case, was
+ *                            overreading bloated codesize back up to 892
+ *   DJH  4/20/10 Version 1.4 fixed Ldword_loop_epilog loop to prevent loads
+ *                            occuring if only 1 left outstanding, fixes bug
+ *                            # 3888, corrected for all alignments. Peeled off
+ *                            1 32byte chunk from kernel loop and extended 8byte
+ *                            loop at end to solve all combinations and prevent
+ *                            over read.  Fixed Ldword_loop_prolog to prevent
+ *                            overread for blocks less than 48bytes. Reduced
+ *                            codesize to 752 bytes
+ *   DJH  4/21/10 version 1.5 1.4 fix broke code for input block ends not
+ *                            aligned to dword boundaries,underwriting by 1
+ *                            byte, added detection for this and fixed. A
+ *                            little bloat.
+ *   DJH  4/23/10 version 1.6 corrected stack error, R20 was not being restored
+ *                            always, fixed the error of R20 being modified
+ *                            before it was being saved
+ * Natural c model
+ * ===============
+ * void * memcpy(char * ptr_out, char * ptr_in, int length) {
+ *   int i;
+ *   if(length) for(i=0; i < length; i++) { ptr_out[i] = ptr_in[i]; }
+ *   return(ptr_out);
+ * }
+ *
+ * Optimized memcpy function
+ * =========================
+ * void * memcpy(char * ptr_out, char * ptr_in, int len) {
+ *   int i, prolog, kernel, epilog, mask;
+ *   u8 offset;
+ *   s64 data0, dataF8, data70;
+ *
+ *   s64 * ptr8_in;
+ *   s64 * ptr8_out;
+ *   s32 * ptr4;
+ *   s16 * ptr2;
+ *
+ *   offset = ((int) ptr_in) & 7;
+ *   ptr8_in = (s64 *) &ptr_in[-offset];   //read in the aligned pointers
+ *
+ *   data70 = *ptr8_in++;
+ *   dataF8 = *ptr8_in++;
+ *
+ *   data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *
+ *   prolog = 32 - ((int) ptr_out);
+ *   mask  = 0x7fffffff >> HEXAGON_R_cl0_R(len);
+ *   prolog = prolog & mask;
+ *   kernel = len - prolog;
+ *   epilog = kernel & 0x1F;
+ *   kernel = kernel>>5;
+ *
+ *   if (prolog & 1) { ptr_out[0] = (u8) data0; data0 >>= 8; ptr_out += 1;}
+ *   ptr2 = (s16 *) &ptr_out[0];
+ *   if (prolog & 2) { ptr2[0] = (u16) data0;  data0 >>= 16; ptr_out += 2;}
+ *   ptr4 = (s32 *) &ptr_out[0];
+ *   if (prolog & 4) { ptr4[0] = (u32) data0;  data0 >>= 32; ptr_out += 4;}
+ *
+ *   offset = offset + (prolog & 7);
+ *   if (offset >= 8) {
+ *     data70 = dataF8;
+ *     dataF8 = *ptr8_in++;
+ *   }
+ *   offset = offset & 0x7;
+ *
+ *   prolog = prolog >> 3;
+ *   if (prolog) for (i=0; i < prolog; i++) {
+ *       data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       data70 = dataF8;
+ *       dataF8 = *ptr8_in++;
+ *   }
+ *   if(kernel) { kernel -= 1; epilog += 32; }
+ *   if(kernel) for(i=0; i < kernel; i++) {
+ *       data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       data70 = *ptr8_in++;
+ *
+ *       data0 = HEXAGON_P_valignb_PPp(data70, dataF8, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       dataF8 = *ptr8_in++;
+ *
+ *       data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       data70 = *ptr8_in++;
+ *
+ *       data0 = HEXAGON_P_valignb_PPp(data70, dataF8, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       dataF8 = *ptr8_in++;
+ *   }
+ *   epilogdws = epilog >> 3;
+ *   if (epilogdws) for (i=0; i < epilogdws; i++) {
+ *       data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       data70 = dataF8;
+ *       dataF8 = *ptr8_in++;
+ *   }
+ *   data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *
+ *   ptr4 = (s32 *) &ptr_out[0];
+ *   if (epilog & 4) { ptr4[0] = (u32) data0; data0 >>= 32; ptr_out += 4;}
+ *   ptr2 = (s16 *) &ptr_out[0];
+ *   if (epilog & 2) { ptr2[0] = (u16) data0; data0 >>= 16; ptr_out += 2;}
+ *   if (epilog & 1) { *ptr_out++ = (u8) data0; }
+ *
+ *   return(ptr_out - length);
+ * }
+ *
+ * Codesize : 784 bytes
+ */
+
+
+#define ptr_out		R0	/*  destination  pounter  */
+#define ptr_in		R1	/*  source pointer  */
+#define len		R2	/*  length of copy in bytes  */
+
+#define data70		R13:12	/*  lo 8 bytes of non-aligned transfer  */
+#define dataF8		R11:10	/*  hi 8 bytes of non-aligned transfer  */
+#define ldata0		R7:6	/*  even 8 bytes chunks  */
+#define ldata1		R25:24	/*  odd 8 bytes chunks  */
+#define data1		R7	/*  lower 8 bytes of ldata1  */
+#define data0		R6	/*  lower 8 bytes of ldata0  */
+
+#define ifbyte		p0	/*  if transfer has bytes in epilog/prolog  */
+#define ifhword		p0	/*  if transfer has shorts in epilog/prolog  */
+#define ifword		p0	/*  if transfer has words in epilog/prolog  */
+#define noprolog	p0	/*  no prolog, xfer starts at 32byte  */
+#define nokernel	p1	/*  no 32byte multiple block in the transfer  */
+#define noepilog	p0	/*  no epilog, xfer ends on 32byte boundary  */
+#define align		p2	/*  alignment of input rel to 8byte boundary  */
+#define kernel1		p0	/*  kernel count == 1  */
+
+#define dalign		R25	/*  rel alignment of input to output data  */
+#define star3		R16	/*  number bytes in prolog - dwords  */
+#define rest		R8	/*  length - prolog bytes  */
+#define back		R7	/*  nr bytes > dword boundary in src block  */
+#define epilog		R3	/*  bytes in epilog  */
+#define inc		R15:14	/*  inc kernel by -1 and defetch ptr by 32  */
+#define kernel		R4	/*  number of 32byte chunks in kernel  */
+#define ptr_in_p_128	R5	/*  pointer for prefetch of input data  */
+#define mask		R8	/*  mask used to determine prolog size  */
+#define shift		R8	/*  used to work a shifter to extract bytes  */
+#define shift2		R5	/*  in epilog to workshifter to extract bytes */
+#define prolog		R15	/*  bytes in  prolog  */
+#define epilogdws	R15	/*  number dwords in epilog  */
+#define shiftb		R14	/*  used to extract bytes  */
+#define offset		R9	/*  same as align in reg  */
+#define ptr_out_p_32	R17	/*  pointer to output dczero  */
+#define align888	R14	/*  if simple dword loop can be used  */
+#define len8		R9	/*  number of dwords in length  */
+#define over		R20	/*  nr of bytes > last inp buf dword boundary */
+
+#define ptr_in_p_128kernel	R5:4	/*  packed fetch pointer & kernel cnt */
+
+	.section .text
+	.p2align 4
+        .global memcpy
+        .type memcpy, @function
+memcpy:
+{
+	p2 = cmp.eq(len, #0);		/*  =0 */
+	align888 = or(ptr_in, ptr_out);	/*  %8 < 97 */
+	p0 = cmp.gtu(len, #23);		/*  %1, <24 */
+	p1 = cmp.eq(ptr_in, ptr_out);	/*  attempt to overwrite self */
+}
+{
+	p1 = or(p2, p1);
+	p3 = cmp.gtu(len, #95);		/*  %8 < 97 */
+	align888 = or(align888, len);	/*  %8 < 97 */
+	len8 = lsr(len, #3);		/*  %8 < 97 */
+}
+{
+	dcfetch(ptr_in);		/*  zero/ptrin=ptrout causes fetch */
+	p2 = bitsclr(align888, #7);	/*  %8 < 97  */
+	if(p1) jumpr r31;		/*  =0  */
+}
+{
+	p2 = and(p2,!p3);			/*  %8 < 97  */
+	if (p2.new) len = add(len, #-8);	/*  %8 < 97  */
+	if (p2.new) jump:NT .Ldwordaligned; 	/*  %8 < 97  */
+}
+{
+	if(!p0) jump .Lbytes23orless;	/*  %1, <24  */
+	mask.l = #LO(0x7fffffff);
+	/*  all bytes before line multiples of data  */
+	prolog = sub(#0, ptr_out);
+}
+{
+	/*  save r31 on stack, decrement sp by 16  */
+	allocframe(#24);
+	mask.h = #HI(0x7fffffff);
+	ptr_in_p_128 = add(ptr_in, #32);
+	back = cl0(len);
+}
+{
+	memd(sp+#0) = R17:16;		/*  save r16,r17 on stack6  */
+	r31.l = #LO(.Lmemcpy_return);	/*  set up final return pointer  */
+	prolog &= lsr(mask, back);
+	offset = and(ptr_in, #7);
+}
+{
+	memd(sp+#8) = R25:24;		/*  save r25,r24 on stack  */
+	dalign = sub(ptr_out, ptr_in);
+	r31.h = #HI(.Lmemcpy_return);	/*  set up final return pointer  */
+}
+{
+	/*  see if there if input buffer end if aligned  */
+	over = add(len, ptr_in);
+	back = add(len, offset);
+	memd(sp+#16) = R21:20;		/*  save r20,r21 on stack  */
+}
+{
+	noprolog = bitsclr(prolog, #7);
+	prolog = and(prolog, #31);
+	dcfetch(ptr_in_p_128);
+	ptr_in_p_128 = add(ptr_in_p_128, #32);
+}
+{
+	kernel = sub(len, prolog);
+	shift = asl(prolog, #3);
+	star3 = and(prolog, #7);
+	ptr_in = and(ptr_in, #-8);
+}
+{
+	prolog = lsr(prolog, #3);
+	epilog = and(kernel, #31);
+	ptr_out_p_32 = add(ptr_out, prolog);
+	over = and(over, #7);
+}
+{
+	p3 = cmp.gtu(back, #8);
+	kernel = lsr(kernel, #5);
+	dcfetch(ptr_in_p_128);
+	ptr_in_p_128 = add(ptr_in_p_128, #32);
+}
+{
+	p1 = cmp.eq(prolog, #0);
+	if(!p1.new) prolog = add(prolog, #1);
+	dcfetch(ptr_in_p_128);	/*  reserve the line 64bytes on  */
+	ptr_in_p_128 = add(ptr_in_p_128, #32);
+}
+{
+	nokernel = cmp.eq(kernel,#0);
+	dcfetch(ptr_in_p_128);	/* reserve the line 64bytes on  */
+	ptr_in_p_128 = add(ptr_in_p_128, #32);
+	shiftb = and(shift, #8);
+}
+{
+	dcfetch(ptr_in_p_128);		/*  reserve the line 64bytes on  */
+	ptr_in_p_128 = add(ptr_in_p_128, #32);
+	if(nokernel) jump .Lskip64;
+	p2 = cmp.eq(kernel, #1);	/*  skip ovr if kernel == 0  */
+}
+{
+	dczeroa(ptr_out_p_32);
+	/*  don't advance pointer  */
+	if(!p2) ptr_out_p_32 = add(ptr_out_p_32, #32);
+}
+{
+	dalign = and(dalign, #31);
+	dczeroa(ptr_out_p_32);
+}
+.Lskip64:
+{
+	data70 = memd(ptr_in++#16);
+	if(p3) dataF8 = memd(ptr_in+#8);
+	if(noprolog) jump .Lnoprolog32;
+	align = offset;
+}
+/*  upto initial 7 bytes  */
+{
+	ldata0 = valignb(dataF8, data70, align);
+	ifbyte = tstbit(shift,#3);
+	offset = add(offset, star3);
+}
+{
+	if(ifbyte) memb(ptr_out++#1) = data0;
+	ldata0 = lsr(ldata0, shiftb);
+	shiftb = and(shift, #16);
+	ifhword = tstbit(shift,#4);
+}
+{
+	if(ifhword) memh(ptr_out++#2) = data0;
+	ldata0 = lsr(ldata0, shiftb);
+	ifword = tstbit(shift,#5);
+	p2 = cmp.gtu(offset, #7);
+}
+{
+	if(ifword) memw(ptr_out++#4) = data0;
+	if(p2) data70 = dataF8;
+	if(p2) dataF8 = memd(ptr_in++#8);	/*  another 8 bytes  */
+	align = offset;
+}
+.Lnoprolog32:
+{
+	p3 = sp1loop0(.Ldword_loop_prolog, prolog)
+	rest = sub(len, star3);	/*  whats left after the loop  */
+	p0 = cmp.gt(over, #0);
+}
+	if(p0) rest = add(rest, #16);
+.Ldword_loop_prolog:
+{
+	if(p3) memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(dataF8, data70, align);
+	p0 = cmp.gt(rest, #16);
+}
+{
+	data70 = dataF8;
+	if(p0) dataF8 = memd(ptr_in++#8);
+	rest = add(rest, #-8);
+}:endloop0
+.Lkernel:
+{
+	/*  kernel is at least 32bytes  */
+	p3 = cmp.gtu(kernel, #0);
+	/*  last itn. remove edge effects  */
+	if(p3.new) kernel = add(kernel, #-1);
+	/*  dealt with in last dword loop  */
+	if(p3.new) epilog = add(epilog, #32);
+}
+{
+	nokernel = cmp.eq(kernel, #0);		/*  after adjustment, recheck */
+	if(nokernel.new) jump:NT .Lepilog;	/*  likely not taken  */
+	inc = combine(#32, #-1);
+	p3 = cmp.gtu(dalign, #24);
+}
+{
+	if(p3) jump .Lodd_alignment;
+}
+{
+	loop0(.Loword_loop_25to31, kernel);
+	kernel1 = cmp.gtu(kernel, #1);
+	rest = kernel;
+}
+	.falign
+.Loword_loop_25to31:
+{
+	dcfetch(ptr_in_p_128);	/*  prefetch 4 lines ahead  */
+	if(kernel1) ptr_out_p_32 = add(ptr_out_p_32, #32);
+}
+{
+	dczeroa(ptr_out_p_32);	/*  reserve the next 32bytes in cache  */
+	p3 = cmp.eq(kernel, rest);
+}
+{
+	/*  kernel -= 1  */
+	ptr_in_p_128kernel = vaddw(ptr_in_p_128kernel, inc);
+	/*  kill write on first iteration  */
+	if(!p3) memd(ptr_out++#8) = ldata1;
+	ldata1 = valignb(dataF8, data70, align);
+	data70 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(data70, dataF8, align);
+	dataF8 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata1;
+	ldata1 = valignb(dataF8, data70, align);
+	data70 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(data70, dataF8, align);
+	dataF8 = memd(ptr_in++#8);
+	kernel1 = cmp.gtu(kernel, #1);
+}:endloop0
+{
+	memd(ptr_out++#8) = ldata1;
+	jump .Lepilog;
+}
+.Lodd_alignment:
+{
+	loop0(.Loword_loop_00to24, kernel);
+	kernel1 = cmp.gtu(kernel, #1);
+	rest = add(kernel, #-1);
+}
+	.falign
+.Loword_loop_00to24:
+{
+	dcfetch(ptr_in_p_128);	/*  prefetch 4 lines ahead  */
+	ptr_in_p_128kernel = vaddw(ptr_in_p_128kernel, inc);
+	if(kernel1) ptr_out_p_32 = add(ptr_out_p_32, #32);
+}
+{
+	dczeroa(ptr_out_p_32);	/*  reserve the next 32bytes in cache  */
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(dataF8, data70, align);
+	data70 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(data70, dataF8, align);
+	dataF8 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(dataF8, data70, align);
+	data70 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(data70, dataF8, align);
+	dataF8 = memd(ptr_in++#8);
+	kernel1 = cmp.gtu(kernel, #1);
+}:endloop0
+.Lepilog:
+{
+	noepilog = cmp.eq(epilog,#0);
+	epilogdws = lsr(epilog, #3);
+	kernel = and(epilog, #7);
+}
+{
+	if(noepilog) jumpr r31;
+	if(noepilog) ptr_out = sub(ptr_out, len);
+	p3 = cmp.eq(epilogdws, #0);
+	shift2 = asl(epilog, #3);
+}
+{
+	shiftb = and(shift2, #32);
+	ifword = tstbit(epilog,#2);
+	if(p3) jump .Lepilog60;
+	if(!p3) epilog = add(epilog, #-16);
+}
+{
+	loop0(.Ldword_loop_epilog, epilogdws);
+	/*  stop criteria is lsbs unless = 0 then its 8  */
+	p3 = cmp.eq(kernel, #0);
+	if(p3.new) kernel= #8;
+	p1 = cmp.gt(over, #0);
+}
+	/*  if not aligned to end of buffer execute 1 more iteration  */
+	if(p1) kernel= #0;
+.Ldword_loop_epilog:
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(dataF8, data70, align);
+	p3 = cmp.gt(epilog, kernel);
+}
+{
+	data70 = dataF8;
+	if(p3) dataF8 = memd(ptr_in++#8);
+	epilog = add(epilog, #-8);
+}:endloop0
+/* copy last 7 bytes */
+.Lepilog60:
+{
+	if(ifword) memw(ptr_out++#4) = data0;
+	ldata0 = lsr(ldata0, shiftb);
+	ifhword = tstbit(epilog,#1);
+	shiftb = and(shift2, #16);
+}
+{
+	if(ifhword) memh(ptr_out++#2) = data0;
+	ldata0 = lsr(ldata0, shiftb);
+	ifbyte = tstbit(epilog,#0);
+	if(ifbyte.new) len = add(len, #-1);
+}
+{
+	if(ifbyte) memb(ptr_out) = data0;
+	ptr_out = sub(ptr_out, len);	/*  return dest pointer  */
+        jumpr r31;
+}
+/*  do byte copy for small n  */
+.Lbytes23orless:
+{
+	p3 = sp1loop0(.Lbyte_copy, len);
+	len = add(len, #-1);
+}
+.Lbyte_copy:
+{
+	data0 = memb(ptr_in++#1);
+	if(p3) memb(ptr_out++#1) = data0;
+}:endloop0
+{
+	memb(ptr_out) = data0;
+	ptr_out = sub(ptr_out, len);
+	jumpr r31;
+}
+/*  do dword copies for aligned in, out and length  */
+.Ldwordaligned:
+{
+	p3 = sp1loop0(.Ldword_copy, len8);
+}
+.Ldword_copy:
+{
+	if(p3) memd(ptr_out++#8) = ldata0;
+	ldata0 = memd(ptr_in++#8);
+}:endloop0
+{
+	memd(ptr_out) = ldata0;
+	ptr_out = sub(ptr_out, len);
+	jumpr r31;	/*  return to function caller  */
+}
+.Lmemcpy_return:
+	r21:20 = memd(sp+#16);	/*  restore r20+r21  */
+{
+	r25:24 = memd(sp+#8);	/*  restore r24+r25  */
+	r17:16 = memd(sp+#0);	/*  restore r16+r17  */
+}
+	deallocframe;	/*  restore r31 and incrment stack by 16  */
+	jumpr r31
diff -druN linux-libre-3.1-gnu/arch/hexagon/lib/memset.S linux-libre-3.2-gnu/arch/hexagon/lib/memset.S
--- linux-libre-3.1-gnu/arch/hexagon/lib/memset.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/lib/memset.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,315 @@
+/*
+ * 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.
+ */
+
+
+/* HEXAGON assembly optimized memset */
+/* Replaces the standard library function memset */
+
+
+        .macro HEXAGON_OPT_FUNC_BEGIN name
+	.text
+	.p2align 4
+	.globl \name
+	.type  \name, @function
+\name:
+	.endm
+
+	.macro HEXAGON_OPT_FUNC_FINISH name
+	.size  \name, . - \name
+	.endm
+
+/* FUNCTION: memset (v2 version) */
+#if __HEXAGON_ARCH__ < 3
+HEXAGON_OPT_FUNC_BEGIN memset
+	{
+		r6 = #8
+		r7 = extractu(r0, #3 , #0)
+		p0 = cmp.eq(r2, #0)
+		p1 = cmp.gtu(r2, #7)
+	}
+	{
+		r4 = vsplatb(r1)
+		r8 = r0           /* leave r0 intact for return val  */
+		r9 = sub(r6, r7)  /* bytes until double alignment  */
+		if p0 jumpr r31   /* count == 0, so return  */
+	}
+	{
+		r3 = #0
+		r7 = #0
+		p0 = tstbit(r9, #0)
+		if p1 jump 2f /* skip byte loop */
+	}
+
+/* less than 8 bytes to set, so just set a byte at a time and return  */
+
+		loop0(1f, r2) /* byte loop */
+	.falign
+1: /* byte loop */
+	{
+		memb(r8++#1) = r4
+	}:endloop0
+		jumpr r31
+	.falign
+2: /* skip byte loop */
+	{
+		r6 = #1
+		p0 = tstbit(r9, #1)
+		p1 = cmp.eq(r2, #1)
+		if !p0 jump 3f /* skip initial byte store */
+	}
+	{
+		memb(r8++#1) = r4
+		r3:2 = sub(r3:2, r7:6)
+		if p1 jumpr r31
+	}
+	.falign
+3: /* skip initial byte store */
+	{
+		r6 = #2
+		p0 = tstbit(r9, #2)
+		p1 = cmp.eq(r2, #2)
+		if !p0 jump 4f /* skip initial half store */
+	}
+	{
+		memh(r8++#2) = r4
+		r3:2 = sub(r3:2, r7:6)
+		if p1 jumpr r31
+	}
+	.falign
+4: /* skip initial half store */
+	{
+		r6 = #4
+		p0 = cmp.gtu(r2, #7)
+		p1 = cmp.eq(r2, #4)
+		if !p0 jump 5f /* skip initial word store */
+	}
+	{
+		memw(r8++#4) = r4
+		r3:2 = sub(r3:2, r7:6)
+		p0 = cmp.gtu(r2, #11)
+		if p1 jumpr r31
+	}
+	.falign
+5: /* skip initial word store */
+	{
+		r10 = lsr(r2, #3)
+		p1 = cmp.eq(r3, #1)
+		if !p0 jump 7f /* skip double loop */
+	}
+	{
+		r5 = r4
+		r6 = #8
+		loop0(6f, r10) /* double loop */
+	}
+
+/* set bytes a double word at a time  */
+
+	.falign
+6: /* double loop */
+	{
+		memd(r8++#8) = r5:4
+		r3:2 = sub(r3:2, r7:6)
+		p1 = cmp.eq(r2, #8)
+	}:endloop0
+	.falign
+7: /* skip double loop */
+	{
+		p0 = tstbit(r2, #2)
+		if p1 jumpr r31
+	}
+	{
+		r6 = #4
+		p0 = tstbit(r2, #1)
+		p1 = cmp.eq(r2, #4)
+		if !p0 jump 8f /* skip final word store */
+	}
+	{
+		memw(r8++#4) = r4
+		r3:2 = sub(r3:2, r7:6)
+		if p1 jumpr r31
+	}
+	.falign
+8: /* skip final word store */
+	{
+		p1 = cmp.eq(r2, #2)
+		if !p0 jump 9f /* skip final half store */
+	}
+	{
+		memh(r8++#2) = r4
+		if p1 jumpr r31
+	}
+	.falign
+9: /* skip final half store */
+	{
+		memb(r8++#1) = r4
+		jumpr r31
+	}
+HEXAGON_OPT_FUNC_FINISH memset
+#endif
+
+
+/*  FUNCTION: memset (v3 and higher version)  */
+#if __HEXAGON_ARCH__ >= 3
+HEXAGON_OPT_FUNC_BEGIN memset
+	{
+		r7=vsplatb(r1)
+		r6 = r0
+		if (r2==#0) jump:nt .L1
+	}
+	{
+		r5:4=combine(r7,r7)
+		p0 = cmp.gtu(r2,#8)
+		if (p0.new) jump:nt .L3
+	}
+	{
+		r3 = r0
+		loop0(.L47,r2)
+	}
+	.falign
+.L47:
+	{
+		memb(r3++#1) = r1
+	}:endloop0 /* start=.L47 */
+		jumpr r31
+.L3:
+	{
+		p0 = tstbit(r0,#0)
+		if (!p0.new) jump:nt .L8
+		p1 = cmp.eq(r2, #1)
+	}
+	{
+		r6 = add(r0, #1)
+		r2 = add(r2,#-1)
+		memb(r0) = r1
+		if (p1) jump .L1
+	}
+.L8:
+	{
+		p0 = tstbit(r6,#1)
+		if (!p0.new) jump:nt .L10
+	}
+	{
+		r2 = add(r2,#-2)
+		memh(r6++#2) = r7
+		p0 = cmp.eq(r2, #2)
+		if (p0.new) jump:nt .L1
+	}
+.L10:
+	{
+		p0 = tstbit(r6,#2)
+		if (!p0.new) jump:nt .L12
+	}
+	{
+		r2 = add(r2,#-4)
+		memw(r6++#4) = r7
+		p0 = cmp.eq(r2, #4)
+		if (p0.new) jump:nt .L1
+	}
+.L12:
+	{
+		p0 = cmp.gtu(r2,#127)
+		if (!p0.new) jump:nt .L14
+	}
+		r3 = and(r6,#31)
+		if (r3==#0) jump:nt .L17
+	{
+		memd(r6++#8) = r5:4
+		r2 = add(r2,#-8)
+	}
+		r3 = and(r6,#31)
+		if (r3==#0) jump:nt .L17
+	{
+		memd(r6++#8) = r5:4
+		r2 = add(r2,#-8)
+	}
+		r3 = and(r6,#31)
+		if (r3==#0) jump:nt .L17
+	{
+		memd(r6++#8) = r5:4
+		r2 = add(r2,#-8)
+	}
+.L17:
+	{
+		r3 = lsr(r2,#5)
+		if (r1!=#0) jump:nt .L18
+	}
+	{
+		r8 = r3
+		r3 = r6
+		loop0(.L46,r3)
+	}
+	.falign
+.L46:
+	{
+		dczeroa(r6)
+		r6 = add(r6,#32)
+		r2 = add(r2,#-32)
+	}:endloop0 /* start=.L46 */
+.L14:
+	{
+		p0 = cmp.gtu(r2,#7)
+		if (!p0.new) jump:nt .L28
+		r8 = lsr(r2,#3)
+	}
+		loop0(.L44,r8)
+	.falign
+.L44:
+	{
+		memd(r6++#8) = r5:4
+		r2 = add(r2,#-8)
+	}:endloop0 /* start=.L44 */
+.L28:
+	{
+		p0 = tstbit(r2,#2)
+		if (!p0.new) jump:nt .L33
+	}
+	{
+		r2 = add(r2,#-4)
+		memw(r6++#4) = r7
+	}
+.L33:
+	{
+		p0 = tstbit(r2,#1)
+		if (!p0.new) jump:nt .L35
+	}
+	{
+		r2 = add(r2,#-2)
+		memh(r6++#2) = r7
+	}
+.L35:
+		p0 = cmp.eq(r2,#1)
+		if (p0) memb(r6) = r1
+.L1:
+		jumpr r31
+.L18:
+		loop0(.L45,r3)
+	.falign
+.L45:
+		dczeroa(r6)
+	{
+		memd(r6++#8) = r5:4
+		r2 = add(r2,#-32)
+	}
+		memd(r6++#8) = r5:4
+		memd(r6++#8) = r5:4
+	{
+		memd(r6++#8) = r5:4
+	}:endloop0 /* start=.L45  */
+		jump .L14
+HEXAGON_OPT_FUNC_FINISH memset
+#endif
diff -druN linux-libre-3.1-gnu/arch/hexagon/Makefile linux-libre-3.2-gnu/arch/hexagon/Makefile
--- linux-libre-3.1-gnu/arch/hexagon/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,58 @@
+#  Makefile for the Hexagon arch
+
+KBUILD_DEFCONFIG = comet_defconfig
+
+# Do not use GP-relative jumps
+KBUILD_CFLAGS += -G0
+LDFLAGS_vmlinux += -G0
+
+# Do not use single-byte enums; these will overflow.
+KBUILD_CFLAGS += -fno-short-enums
+
+# Modules must use either long-calls, or use pic/plt.
+# Use long-calls for now, it's easier.  And faster.
+# CFLAGS_MODULE += -fPIC
+# LDFLAGS_MODULE += -shared
+CFLAGS_MODULE += -mlong-calls
+
+cflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
+cflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
+cflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
+cflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
+
+aflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
+aflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
+aflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
+aflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
+
+ldflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
+ldflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
+ldflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
+ldflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
+
+KBUILD_CFLAGS += $(cflags-y)
+KBUILD_AFLAGS += $(aflags-y)
+
+#  no KBUILD_LDFLAGS?
+LDFLAGS += $(ldflags-y)
+
+# Thread-info register will be r19.  This value is not configureable;
+# it is hard-coded in several files.
+TIR_NAME := r19
+KBUILD_CFLAGS += -ffixed-$(TIR_NAME) -DTHREADINFO_REG=$(TIR_NAME) -D__linux__
+KBUILD_AFLAGS += -DTHREADINFO_REG=$(TIR_NAME)
+
+LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
+libs-y += $(LIBGCC)
+
+head-y := arch/hexagon/kernel/head.o \
+	arch/hexagon/kernel/init_task.o
+
+core-y += arch/hexagon/kernel/ \
+	arch/hexagon/mm/ \
+	arch/hexagon/lib/
+
+#	arch/hexagon/platform/common/
+#
+#core-$(CONFIG_HEXAGON_COMET)		+= arch/hexagon/platform/comet/
+#machine-$(CONFIG_HEXAGON_COMET)		:= comet
diff -druN linux-libre-3.1-gnu/arch/hexagon/mm/cache.c linux-libre-3.2-gnu/arch/hexagon/mm/cache.c
--- linux-libre-3.1-gnu/arch/hexagon/mm/cache.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/mm/cache.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,128 @@
+/*
+ * Cache management functions for Hexagon
+ *
+ * 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/mm.h>
+#include <asm/cacheflush.h>
+#include <asm/hexagon_vm.h>
+
+#define spanlines(start, end) \
+	(((end - (start & ~(LINESIZE - 1))) >> LINEBITS) + 1)
+
+void flush_dcache_range(unsigned long start, unsigned long end)
+{
+	unsigned long lines = spanlines(start, end-1);
+	unsigned long i, flags;
+
+	start &= ~(LINESIZE - 1);
+
+	local_irq_save(flags);
+
+	for (i = 0; i < lines; i++) {
+		__asm__ __volatile__ (
+		"	dccleaninva(%0);	"
+		:
+		: "r" (start)
+		);
+		start += LINESIZE;
+	}
+	local_irq_restore(flags);
+}
+
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+	unsigned long lines = spanlines(start, end-1);
+	unsigned long i, flags;
+
+	start &= ~(LINESIZE - 1);
+
+	local_irq_save(flags);
+
+	for (i = 0; i < lines; i++) {
+		__asm__ __volatile__ (
+			"	dccleana(%0); "
+			"	icinva(%0);	"
+			:
+			: "r" (start)
+		);
+		start += LINESIZE;
+	}
+	__asm__ __volatile__ (
+		"isync"
+	);
+	local_irq_restore(flags);
+}
+
+void hexagon_clean_dcache_range(unsigned long start, unsigned long end)
+{
+	unsigned long lines = spanlines(start, end-1);
+	unsigned long i, flags;
+
+	start &= ~(LINESIZE - 1);
+
+	local_irq_save(flags);
+
+	for (i = 0; i < lines; i++) {
+		__asm__ __volatile__ (
+		"	dccleana(%0);	"
+		:
+		: "r" (start)
+		);
+		start += LINESIZE;
+	}
+	local_irq_restore(flags);
+}
+
+void hexagon_inv_dcache_range(unsigned long start, unsigned long end)
+{
+	unsigned long lines = spanlines(start, end-1);
+	unsigned long i, flags;
+
+	start &= ~(LINESIZE - 1);
+
+	local_irq_save(flags);
+
+	for (i = 0; i < lines; i++) {
+		__asm__ __volatile__ (
+		"	dcinva(%0);	"
+		:
+		: "r" (start)
+		);
+		start += LINESIZE;
+	}
+	local_irq_restore(flags);
+}
+
+
+
+
+/*
+ * This is just really brutal and shouldn't be used anyways,
+ * especially on V2.  Left here just in case.
+ */
+void flush_cache_all_hexagon(void)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+	__vmcache_ickill();
+	__vmcache_dckill();
+	__vmcache_l2kill();
+	local_irq_restore(flags);
+	mb();
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/mm/copy_from_user.S linux-libre-3.2-gnu/arch/hexagon/mm/copy_from_user.S
--- linux-libre-3.1-gnu/arch/hexagon/mm/copy_from_user.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/mm/copy_from_user.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,114 @@
+/*
+ * User memory copy functions for kernel
+ *
+ * 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.
+ */
+
+/*
+ * The right way to do this involves valignb
+ * The easy way to do this is only speed up src/dest similar alignment.
+ */
+
+/*
+ * Copy to/from user are the same, except that for packets with a load and
+ * a store, I don't know how to tell which kind of exception we got.
+ * Therefore, we duplicate the function, and handle faulting addresses
+ * differently for each function
+ */
+
+/*
+ * copy from user: loads can fault
+ */
+#define src_sav r13
+#define dst_sav r12
+#define src_dst_sav r13:12
+#define d_dbuf r15:14
+#define w_dbuf r15
+
+#define dst r0
+#define src r1
+#define bytes r2
+#define loopcount r5
+
+#define FUNCNAME __copy_from_user_hexagon
+#include "copy_user_template.S"
+
+	/* LOAD FAULTS from COPY_FROM_USER */
+
+	/* Alignment loop.  r2 has been updated. Return it. */
+	.falign
+1009:
+2009:
+4009:
+	{
+		r0 = r2
+		jumpr r31
+	}
+	/* Normal copy loops. Do epilog. Use src-src_sav to compute distance */
+	/* X - (A - B) == X + B - A */
+	.falign
+8089:
+	{
+		memd(dst) = d_dbuf
+		r2 += sub(src_sav,src)
+	}
+	{
+		r0 = r2
+		jumpr r31
+	}
+	.falign
+4089:
+	{
+		memw(dst) = w_dbuf
+		r2 += sub(src_sav,src)
+	}
+	{
+		r0 = r2
+		jumpr r31
+	}
+	.falign
+2089:
+	{
+		memh(dst) = w_dbuf
+		r2 += sub(src_sav,src)
+	}
+	{
+		r0 = r2
+		jumpr r31
+	}
+	.falign
+1089:
+	{
+		memb(dst) = w_dbuf
+		r2 += sub(src_sav,src)
+	}
+	{
+		r0 = r2
+		jumpr r31
+	}
+
+	/* COPY FROM USER: only loads can fail */
+
+	.section __ex_table,"a"
+	.long 1000b,1009b
+	.long 2000b,2009b
+	.long 4000b,4009b
+	.long 8080b,8089b
+	.long 4080b,4089b
+	.long 2080b,2089b
+	.long 1080b,1089b
+	.previous
diff -druN linux-libre-3.1-gnu/arch/hexagon/mm/copy_to_user.S linux-libre-3.2-gnu/arch/hexagon/mm/copy_to_user.S
--- linux-libre-3.1-gnu/arch/hexagon/mm/copy_to_user.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/mm/copy_to_user.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,92 @@
+/*
+ * User memory copying routines for the Hexagon Kernel
+ *
+ * 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.
+ */
+
+/* The right way to do this involves valignb
+ * The easy way to do this is only speed up src/dest similar alignment.
+ */
+
+/*
+ * Copy to/from user are the same, except that for packets with a load and
+ * a store, I don't know how to tell which kind of exception we got.
+ * Therefore, we duplicate the function, and handle faulting addresses
+ * differently for each function
+ */
+
+/*
+ * copy to user: stores can fault
+ */
+#define src_sav r13
+#define dst_sav r12
+#define src_dst_sav r13:12
+#define d_dbuf r15:14
+#define w_dbuf r15
+
+#define dst r0
+#define src r1
+#define bytes r2
+#define loopcount r5
+
+#define FUNCNAME __copy_to_user_hexagon
+#include "copy_user_template.S"
+
+	/* STORE FAULTS from COPY_TO_USER */
+	.falign
+1109:
+2109:
+4109:
+	/* Alignment loop.  r2 has been updated.  Return it. */
+	{
+		r0 = r2
+		jumpr r31
+	}
+	/* Normal copy loops.  Use dst-dst_sav to compute distance */
+	/* dst holds best write, no need to unwind any loops */
+	/* X - (A - B) == X + B - A */
+	.falign
+8189:
+8199:
+4189:
+4199:
+2189:
+2199:
+1189:
+1199:
+	{
+		r2 += sub(dst_sav,dst)
+	}
+	{
+		r0 = r2
+		jumpr r31
+	}
+
+	/* COPY TO USER: only stores can fail */
+	.section __ex_table,"a"
+	.long 1100b,1109b
+	.long 2100b,2109b
+	.long 4100b,4109b
+	.long 8180b,8189b
+	.long 8190b,8199b
+	.long 4180b,4189b
+	.long 4190b,4199b
+	.long 2180b,2189b
+	.long 2190b,2199b
+	.long 1180b,1189b
+	.long 1190b,1199b
+	.previous
diff -druN linux-libre-3.1-gnu/arch/hexagon/mm/copy_user_template.S linux-libre-3.2-gnu/arch/hexagon/mm/copy_user_template.S
--- linux-libre-3.1-gnu/arch/hexagon/mm/copy_user_template.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/mm/copy_user_template.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,185 @@
+/*
+ * 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.
+ */
+
+/* Numerology:
+ * WXYZ
+ * W: width in bytes
+ * X: Load=0, Store=1
+ * Y: Location 0=preamble,8=loop,9=epilog
+ * Z: Location=0,handler=9
+ */
+	.text
+	.global FUNCNAME
+	.type FUNCNAME, @function
+	.p2align 5
+FUNCNAME:
+	{
+		p0 = cmp.gtu(bytes,#0)
+		if (!p0.new) jump:nt .Ldone
+		r3 = or(dst,src)
+		r4 = xor(dst,src)
+	}
+	{
+		p1 = cmp.gtu(bytes,#15)
+		p0 = bitsclr(r3,#7)
+		if (!p0.new) jump:nt .Loop_not_aligned_8
+		src_dst_sav = combine(src,dst)
+	}
+
+	{
+		loopcount = lsr(bytes,#3)
+		if (!p1) jump .Lsmall
+	}
+	p3=sp1loop0(.Loop8,loopcount)
+.Loop8:
+8080:
+8180:
+	{
+		if (p3) memd(dst++#8) = d_dbuf
+		d_dbuf = memd(src++#8)
+	}:endloop0
+8190:
+	{
+		memd(dst++#8) = d_dbuf
+		bytes -= asl(loopcount,#3)
+		jump .Lsmall
+	}
+
+.Loop_not_aligned_8:
+	{
+		p0 = bitsclr(r4,#7)
+		if (p0.new) jump:nt .Lalign
+	}
+	{
+		p0 = bitsclr(r3,#3)
+		if (!p0.new) jump:nt .Loop_not_aligned_4
+		p1 = cmp.gtu(bytes,#7)
+	}
+
+	{
+		if (!p1) jump .Lsmall
+		loopcount = lsr(bytes,#2)
+	}
+	p3=sp1loop0(.Loop4,loopcount)
+.Loop4:
+4080:
+4180:
+	{
+		if (p3) memw(dst++#4) = w_dbuf
+		w_dbuf = memw(src++#4)
+	}:endloop0
+4190:
+	{
+		memw(dst++#4) = w_dbuf
+		bytes -= asl(loopcount,#2)
+		jump .Lsmall
+	}
+
+.Loop_not_aligned_4:
+	{
+		p0 = bitsclr(r3,#1)
+		if (!p0.new) jump:nt .Loop_not_aligned
+		p1 = cmp.gtu(bytes,#3)
+	}
+
+	{
+		if (!p1) jump .Lsmall
+		loopcount = lsr(bytes,#1)
+	}
+	p3=sp1loop0(.Loop2,loopcount)
+.Loop2:
+2080:
+2180:
+	{
+		if (p3) memh(dst++#2) = w_dbuf
+		w_dbuf = memuh(src++#2)
+	}:endloop0
+2190:
+	{
+		memh(dst++#2) = w_dbuf
+		bytes -= asl(loopcount,#1)
+		jump .Lsmall
+	}
+
+.Loop_not_aligned: /* Works for as small as one byte */
+	p3=sp1loop0(.Loop1,bytes)
+.Loop1:
+1080:
+1180:
+	{
+		if (p3) memb(dst++#1) = w_dbuf
+		w_dbuf = memub(src++#1)
+	}:endloop0
+	/* Done */
+1190:
+	{
+		memb(dst) = w_dbuf
+		jumpr r31
+		r0 = #0
+	}
+
+.Lsmall:
+	{
+		p0 = cmp.gtu(bytes,#0)
+		if (p0.new) jump:nt .Loop_not_aligned
+	}
+.Ldone:
+	{
+		r0 = #0
+		jumpr r31
+	}
+	.falign
+.Lalign:
+1000:
+	{
+		if (p0.new) w_dbuf = memub(src)
+		p0 = tstbit(src,#0)
+		if (!p1) jump .Lsmall
+	}
+1100:
+	{
+		if (p0) memb(dst++#1) = w_dbuf
+		if (p0) bytes = add(bytes,#-1)
+		if (p0) src = add(src,#1)
+	}
+2000:
+	{
+		if (p0.new) w_dbuf = memuh(src)
+		p0 = tstbit(src,#1)
+		if (!p1) jump .Lsmall
+	}
+2100:
+	{
+		if (p0) memh(dst++#2) = w_dbuf
+		if (p0) bytes = add(bytes,#-2)
+		if (p0) src = add(src,#2)
+	}
+4000:
+	{
+		if (p0.new) w_dbuf = memw(src)
+		p0 = tstbit(src,#2)
+		if (!p1) jump .Lsmall
+	}
+4100:
+	{
+		if (p0) memw(dst++#4) = w_dbuf
+		if (p0) bytes = add(bytes,#-4)
+		if (p0) src = add(src,#4)
+		jump FUNCNAME
+	}
+	.size FUNCNAME,.-FUNCNAME
diff -druN linux-libre-3.1-gnu/arch/hexagon/mm/init.c linux-libre-3.2-gnu/arch/hexagon/mm/init.c
--- linux-libre-3.1-gnu/arch/hexagon/mm/init.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/mm/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,276 @@
+/*
+ * Memory subsystem initialization for Hexagon
+ *
+ * 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/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <asm/atomic.h>
+#include <linux/highmem.h>
+#include <asm/tlb.h>
+#include <asm/sections.h>
+#include <asm/vm_mmu.h>
+
+/*
+ * Define a startpg just past the end of the kernel image and a lastpg
+ * that corresponds to the end of real or simulated platform memory.
+ */
+#define bootmem_startpg (PFN_UP(((unsigned long) _end) - PAGE_OFFSET))
+
+unsigned long bootmem_lastpg;  /*  Should be set by platform code  */
+
+/*  Set as variable to limit PMD copies  */
+int max_kernel_seg = 0x303;
+
+/*  think this should be (page_size-1) the way it's used...*/
+unsigned long zero_page_mask;
+
+/*  indicate pfn's of high memory  */
+unsigned long highstart_pfn, highend_pfn;
+
+/* struct mmu_gather defined in asm-generic.h;  */
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+/* Default cache attribute for newly created page tables */
+unsigned long _dflt_cache_att = CACHEDEF;
+
+/*
+ * The current "generation" of kernel map, which should not roll
+ * over until Hell freezes over.  Actual bound in years needs to be
+ * calculated to confirm.
+ */
+DEFINE_SPINLOCK(kmap_gen_lock);
+
+/*  checkpatch says don't init this to 0.  */
+unsigned long long kmap_generation;
+
+/*
+ * mem_init - initializes memory
+ *
+ * Frees up bootmem
+ * Fixes up more stuff for HIGHMEM
+ * Calculates and displays memory available/used
+ */
+void __init mem_init(void)
+{
+	/*  No idea where this is actually declared.  Seems to evade LXR.  */
+	totalram_pages += free_all_bootmem();
+	num_physpages = bootmem_lastpg;	/*  seriously, what?  */
+
+	printk(KERN_INFO "totalram_pages = %ld\n", totalram_pages);
+
+	/*
+	 *  To-Do:  someone somewhere should wipe out the bootmem map
+	 *  after we're done?
+	 */
+
+	/*
+	 * This can be moved to some more virtual-memory-specific
+	 * initialization hook at some point.  Set the init_mm
+	 * descriptors "context" value to point to the initial
+	 * kernel segment table's physical address.
+	 */
+	init_mm.context.ptbase = __pa(init_mm.pgd);
+}
+
+/*
+ * free_initmem - frees memory used by stuff declared with __init
+ *
+ * Todo:  free pages between __init_begin and __init_end; possibly
+ * some devtree related stuff as well.
+ */
+void __init_refok free_initmem(void)
+{
+}
+
+/*
+ * free_initrd_mem - frees...  initrd memory.
+ * @start - start of init memory
+ * @end - end of init memory
+ *
+ * Apparently has to be passed the address of the initrd memory.
+ *
+ * Wrapped by #ifdef CONFIG_BLKDEV_INITRD
+ */
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+}
+
+void sync_icache_dcache(pte_t pte)
+{
+	unsigned long addr;
+	struct page *page;
+
+	page = pte_page(pte);
+	addr = (unsigned long) page_address(page);
+
+	__vmcache_idsync(addr, PAGE_SIZE);
+}
+
+/*
+ * In order to set up page allocator "nodes",
+ * somebody has to call free_area_init() for UMA.
+ *
+ * In this mode, we only have one pg_data_t
+ * structure: contig_mem_data.
+ */
+void __init paging_init(void)
+{
+	unsigned long zones_sizes[MAX_NR_ZONES] = {0, };
+
+	/*
+	 *  This is not particularly well documented anywhere, but
+	 *  give ZONE_NORMAL all the memory, including the big holes
+	 *  left by the kernel+bootmem_map which are already left as reserved
+	 *  in the bootmem_map; free_area_init should see those bits and
+	 *  adjust accordingly.
+	 */
+
+	zones_sizes[ZONE_NORMAL] = max_low_pfn;
+
+	free_area_init(zones_sizes);  /*  sets up the zonelists and mem_map  */
+
+	/*
+	 * Start of high memory area.  Will probably need something more
+	 * fancy if we...  get more fancy.
+	 */
+	high_memory = (void *)((bootmem_lastpg + 1) << PAGE_SHIFT);
+}
+
+#ifndef DMA_RESERVE
+#define DMA_RESERVE		(4)
+#endif
+
+#define DMA_CHUNKSIZE		(1<<22)
+#define DMA_RESERVED_BYTES	(DMA_RESERVE * DMA_CHUNKSIZE)
+
+/*
+ * Pick out the memory size.  We look for mem=size,
+ * where size is "size[KkMm]"
+ */
+static int __init early_mem(char *p)
+{
+	unsigned long size;
+	char *endp;
+
+	size = memparse(p, &endp);
+
+	bootmem_lastpg = PFN_DOWN(size);
+
+	return 0;
+}
+early_param("mem", early_mem);
+
+size_t hexagon_coherent_pool_size = (size_t) (DMA_RESERVE << 22);
+
+void __init setup_arch_memory(void)
+{
+	int bootmap_size;
+	/*  XXX Todo: this probably should be cleaned up  */
+	u32 *segtable = (u32 *) &swapper_pg_dir[0];
+	u32 *segtable_end;
+
+	/*
+	 * Set up boot memory allocator
+	 *
+	 * The Gorman book also talks about these functions.
+	 * This needs to change for highmem setups.
+	 */
+
+	/* Memory size needs to be a multiple of 16M */
+	bootmem_lastpg = PFN_DOWN((bootmem_lastpg << PAGE_SHIFT) &
+		~((BIG_KERNEL_PAGE_SIZE) - 1));
+
+	/*
+	 * Reserve the top DMA_RESERVE bytes of RAM for DMA (uncached)
+	 * memory allocation
+	 */
+	bootmap_size = init_bootmem(bootmem_startpg, bootmem_lastpg -
+				    PFN_DOWN(DMA_RESERVED_BYTES));
+
+	printk(KERN_INFO "bootmem_startpg:  0x%08lx\n", bootmem_startpg);
+	printk(KERN_INFO "bootmem_lastpg:  0x%08lx\n", bootmem_lastpg);
+	printk(KERN_INFO "bootmap_size:  %d\n", bootmap_size);
+	printk(KERN_INFO "max_low_pfn:  0x%08lx\n", max_low_pfn);
+
+	/*
+	 * The default VM page tables (will be) populated with
+	 * VA=PA+PAGE_OFFSET mapping.  We go in and invalidate entries
+	 * higher than what we have memory for.
+	 */
+
+	/*  this is pointer arithmetic; each entry covers 4MB  */
+	segtable = segtable + (PAGE_OFFSET >> 22);
+
+	/*  this actually only goes to the end of the first gig  */
+	segtable_end = segtable + (1<<(30-22));
+
+	/*  Move forward to the start of empty pages  */
+	segtable += bootmem_lastpg >> (22-PAGE_SHIFT);
+
+	{
+	    int i;
+
+	    for (i = 1 ; i <= DMA_RESERVE ; i++)
+		segtable[-i] = ((segtable[-i] & __HVM_PTE_PGMASK_4MB)
+				| __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X
+				| __HEXAGON_C_UNC << 6
+				| __HVM_PDE_S_4MB);
+	}
+
+	printk(KERN_INFO "clearing segtable from %p to %p\n", segtable,
+		segtable_end);
+	while (segtable < (segtable_end-8))
+		*(segtable++) = __HVM_PDE_S_INVALID;
+	/* stop the pointer at the device I/O 4MB page  */
+
+	printk(KERN_INFO "segtable = %p (should be equal to _K_io_map)\n",
+		segtable);
+
+#if 0
+	/*  Other half of the early device table from vm_init_segtable. */
+	printk(KERN_INFO "&_K_init_devicetable = 0x%08x\n",
+		(unsigned long) _K_init_devicetable-PAGE_OFFSET);
+	*segtable = ((u32) (unsigned long) _K_init_devicetable-PAGE_OFFSET) |
+		__HVM_PDE_S_4KB;
+	printk(KERN_INFO "*segtable = 0x%08x\n", *segtable);
+#endif
+
+	/*
+	 * Free all the memory that wasn't taken up by the bootmap, the DMA
+	 * reserve, or kernel itself.
+	 */
+	free_bootmem(PFN_PHYS(bootmem_startpg)+bootmap_size,
+		     PFN_PHYS(bootmem_lastpg - bootmem_startpg) - bootmap_size -
+		     DMA_RESERVED_BYTES);
+
+	/*
+	 *  The bootmem allocator seemingly just lives to feed memory
+	 *  to the paging system
+	 */
+	printk(KERN_INFO "PAGE_SIZE=%lu\n", PAGE_SIZE);
+	paging_init();  /*  See Gorman Book, 2.3  */
+
+	/*
+	 *  At this point, the page allocator is kind of initialized, but
+	 *  apparently no pages are available (just like with the bootmem
+	 *  allocator), and need to be freed themselves via mem_init(),
+	 *  which is called by start_kernel() later on in the process
+	 */
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/mm/ioremap.c linux-libre-3.2-gnu/arch/hexagon/mm/ioremap.c
--- linux-libre-3.1-gnu/arch/hexagon/mm/ioremap.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/mm/ioremap.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,56 @@
+/*
+ * I/O remap functions for Hexagon
+ *
+ * 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/io.h>
+#include <linux/vmalloc.h>
+
+void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size)
+{
+	unsigned long last_addr, addr;
+	unsigned long offset = phys_addr & ~PAGE_MASK;
+	struct vm_struct *area;
+
+	pgprot_t prot = __pgprot(_PAGE_PRESENT|_PAGE_READ|_PAGE_WRITE
+					|(__HEXAGON_C_DEV << 6));
+
+	last_addr = phys_addr + size - 1;
+
+	/*  Wrapping not allowed  */
+	if (!size || (last_addr < phys_addr))
+		return NULL;
+
+	/*  Rounds up to next page size, including whole-page offset */
+	size = PAGE_ALIGN(offset + size);
+
+	area = get_vm_area(size, VM_IOREMAP);
+	addr = (unsigned long)area->addr;
+
+	if (ioremap_page_range(addr, addr+size, phys_addr, prot)) {
+		vunmap((void *)addr);
+		return NULL;
+	}
+
+	return (void __iomem *) (offset + addr);
+}
+
+void __iounmap(const volatile void __iomem *addr)
+{
+	vunmap((void *) ((unsigned long) addr & PAGE_MASK));
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/mm/Makefile linux-libre-3.2-gnu/arch/hexagon/mm/Makefile
--- linux-libre-3.1-gnu/arch/hexagon/mm/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/mm/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,6 @@
+#
+# Makefile for Hexagon memory management subsystem
+#
+
+obj-y := init.o pgalloc.o ioremap.o uaccess.o vm_fault.o cache.o
+obj-y += copy_to_user.o copy_from_user.o strnlen_user.o vm_tlb.o
diff -druN linux-libre-3.1-gnu/arch/hexagon/mm/pgalloc.c linux-libre-3.2-gnu/arch/hexagon/mm/pgalloc.c
--- linux-libre-3.1-gnu/arch/hexagon/mm/pgalloc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/mm/pgalloc.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+/*
+ * 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/init.h>
+
+void __init pgtable_cache_init(void)
+{
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/mm/strnlen_user.S linux-libre-3.2-gnu/arch/hexagon/mm/strnlen_user.S
--- linux-libre-3.1-gnu/arch/hexagon/mm/strnlen_user.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/mm/strnlen_user.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,139 @@
+/*
+ * User string length functions for kernel
+ *
+ * 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.
+ */
+
+#define isrc	r0
+#define max	r1	/*  Do not change!  */
+
+#define end	r2
+#define tmp1	r3
+
+#define obo	r6	/*  off-by-one  */
+#define start	r7
+#define mod8	r8
+#define dbuf    r15:14
+#define dcmp	r13:12
+
+/*
+ * The vector mask version of this turned out *really* badly.
+ * The hardware loop version also turned out *really* badly.
+ * Seems straight pointer arithmetic basically wins here.
+ */
+
+#define fname __strnlen_user
+
+	.text
+	.global fname
+	.type fname, @function
+	.p2align 5  /*  why?  */
+fname:
+	{
+		mod8 = and(isrc,#7);
+		end = add(isrc,max);
+		start = isrc;
+	}
+	{
+		P0 = cmp.eq(mod8,#0);
+		mod8 = and(end,#7);
+		dcmp = #0;
+		if (P0.new) jump:t dw_loop;	/*  fire up the oven  */
+	}
+
+alignment_loop:
+fail_1:	{
+		tmp1 = memb(start++#1);
+	}
+	{
+		P0 = cmp.eq(tmp1,#0);
+		if (P0.new) jump:nt exit_found;
+		P1 = cmp.gtu(end,start);
+		mod8 = and(start,#7);
+	}
+	{
+		if (!P1) jump exit_error;  /*  hit the end  */
+		P0 = cmp.eq(mod8,#0);
+	}
+	{
+		if (!P0) jump alignment_loop;
+	}
+
+
+
+dw_loop:
+fail_2:	{
+		dbuf = memd(start);
+		obo = add(start,#1);
+	}
+	{
+		P0 = vcmpb.eq(dbuf,dcmp);
+	}
+	{
+		tmp1 = P0;
+		P0 = cmp.gtu(end,start);
+	}
+	{
+		tmp1 = ct0(tmp1);
+		mod8 = and(end,#7);
+		if (!P0) jump end_check;
+	}
+	{
+		P0 = cmp.eq(tmp1,#32);
+		if (!P0.new) jump:nt exit_found;
+		if (!P0.new) start = add(obo,tmp1);
+	}
+	{
+		start = add(start,#8);
+		jump dw_loop;
+	}	/*  might be nice to combine these jumps...   */
+
+
+end_check:
+	{
+		P0 = cmp.gt(tmp1,mod8);
+		if (P0.new) jump:nt exit_error;	/*  neverfound!  */
+		start = add(obo,tmp1);
+	}
+
+exit_found:
+	{
+		R0 = sub(start,isrc);
+		jumpr R31;
+	}
+
+exit_error:
+	{
+		R0 = add(max,#1);
+		jumpr R31;
+	}
+
+	/*  Uh, what does the "fixup" return here?  */
+	.falign
+fix_1:
+	{
+		R0 = #0;
+		jumpr R31;
+	}
+
+	.size fname,.-fname
+
+
+.section __ex_table,"a"
+.long fail_1,fix_1
+.long fail_2,fix_1
+.previous
diff -druN linux-libre-3.1-gnu/arch/hexagon/mm/uaccess.c linux-libre-3.2-gnu/arch/hexagon/mm/uaccess.c
--- linux-libre-3.1-gnu/arch/hexagon/mm/uaccess.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/mm/uaccess.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+/*
+ * Support for user memory access from kernel.  This will
+ * probably be inlined for performance at some point, but
+ * for ease of debug, and to a lesser degree for code size,
+ * we implement here as subroutines.
+ */
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+/*
+ * For clear_user(), exploit previously defined copy_to_user function
+ * and the fact that we've got a handy zero page defined in kernel/head.S
+ *
+ * dczero here would be even faster.
+ */
+__kernel_size_t __clear_user_hexagon(void __user *dest, unsigned long count)
+{
+	long uncleared;
+
+	while (count > PAGE_SIZE) {
+		uncleared = __copy_to_user_hexagon(dest, &empty_zero_page,
+						PAGE_SIZE);
+		if (uncleared)
+			return count - (PAGE_SIZE - uncleared);
+		count -= PAGE_SIZE;
+		dest += PAGE_SIZE;
+	}
+	if (count)
+		count = __copy_to_user_hexagon(dest, &empty_zero_page, count);
+
+	return count;
+}
+
+unsigned long clear_user_hexagon(void __user *dest, unsigned long count)
+{
+	if (!access_ok(VERIFY_WRITE, dest, count))
+		return count;
+	else
+		return __clear_user_hexagon(dest, count);
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/mm/vm_fault.c linux-libre-3.2-gnu/arch/hexagon/mm/vm_fault.c
--- linux-libre-3.1-gnu/arch/hexagon/mm/vm_fault.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/mm/vm_fault.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,187 @@
+/*
+ * Memory fault handling for Hexagon
+ *
+ * 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.
+ */
+
+/*
+ * Page fault handling for the Hexagon Virtual Machine.
+ * Can also be called by a native port emulating the HVM
+ * execptions.
+ */
+
+#include <asm/pgtable.h>
+#include <asm/traps.h>
+#include <asm/uaccess.h>
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/module.h>
+#include <linux/hardirq.h>
+
+/*
+ * Decode of hardware exception sends us to one of several
+ * entry points.  At each, we generate canonical arguments
+ * for handling by the abstract memory management code.
+ */
+#define FLT_IFETCH     -1
+#define FLT_LOAD        0
+#define FLT_STORE       1
+
+
+/*
+ * Canonical page fault handler
+ */
+void do_page_fault(unsigned long address, long cause, struct pt_regs *regs)
+{
+	struct vm_area_struct *vma;
+	struct mm_struct *mm = current->mm;
+	siginfo_t info;
+	int si_code = SEGV_MAPERR;
+	int fault;
+	const struct exception_table_entry *fixup;
+
+	/*
+	 * If we're in an interrupt or have no user context,
+	 * then must not take the fault.
+	 */
+	if (unlikely(in_interrupt() || !mm))
+		goto no_context;
+
+	local_irq_enable();
+
+	down_read(&mm->mmap_sem);
+	vma = find_vma(mm, address);
+	if (!vma)
+		goto bad_area;
+
+	if (vma->vm_start <= address)
+		goto good_area;
+
+	if (!(vma->vm_flags & VM_GROWSDOWN))
+		goto bad_area;
+
+	if (expand_stack(vma, address))
+		goto bad_area;
+
+good_area:
+	/* Address space is OK.  Now check access rights. */
+	si_code = SEGV_ACCERR;
+
+	switch (cause) {
+	case FLT_IFETCH:
+		if (!(vma->vm_flags & VM_EXEC))
+			goto bad_area;
+		break;
+	case FLT_LOAD:
+		if (!(vma->vm_flags & VM_READ))
+			goto bad_area;
+		break;
+	case FLT_STORE:
+		if (!(vma->vm_flags & VM_WRITE))
+			goto bad_area;
+		break;
+	}
+
+	fault = handle_mm_fault(mm, vma, address, (cause > 0));
+
+	/* The most common case -- we are done. */
+	if (likely(!(fault & VM_FAULT_ERROR))) {
+		if (fault & VM_FAULT_MAJOR)
+			current->maj_flt++;
+		else
+			current->min_flt++;
+
+		up_read(&mm->mmap_sem);
+		return;
+	}
+
+	up_read(&mm->mmap_sem);
+
+	/* Handle copyin/out exception cases */
+	if (!user_mode(regs))
+		goto no_context;
+
+	if (fault & VM_FAULT_OOM) {
+		pagefault_out_of_memory();
+		return;
+	}
+
+	/* User-mode address is in the memory map, but we are
+	 * unable to fix up the page fault.
+	 */
+	if (fault & VM_FAULT_SIGBUS) {
+		info.si_signo = SIGBUS;
+		info.si_code = BUS_ADRERR;
+	}
+	/* Address is not in the memory map */
+	else {
+		info.si_signo = SIGSEGV;
+		info.si_code = SEGV_ACCERR;
+	}
+	info.si_errno = 0;
+	info.si_addr = (void __user *)address;
+	force_sig_info(info.si_code, &info, current);
+	return;
+
+bad_area:
+	up_read(&mm->mmap_sem);
+
+	if (user_mode(regs)) {
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		info.si_code = si_code;
+		info.si_addr = (void *)address;
+		force_sig_info(SIGSEGV, &info, current);
+		return;
+	}
+	/* Kernel-mode fault falls through */
+
+no_context:
+	fixup = search_exception_tables(pt_elr(regs));
+	if (fixup) {
+		pt_set_elr(regs, fixup->fixup);
+		return;
+	}
+
+	/* Things are looking very, very bad now */
+	bust_spinlocks(1);
+	printk(KERN_EMERG "Unable to handle kernel paging request at "
+		"virtual address 0x%08lx, regs %p\n", address, regs);
+	die("Bad Kernel VA", regs, SIGKILL);
+}
+
+
+void read_protection_fault(struct pt_regs *regs)
+{
+	unsigned long badvadr = pt_badva(regs);
+
+	do_page_fault(badvadr, FLT_LOAD, regs);
+}
+
+void write_protection_fault(struct pt_regs *regs)
+{
+	unsigned long badvadr = pt_badva(regs);
+
+	do_page_fault(badvadr, FLT_STORE, regs);
+}
+
+void execute_protection_fault(struct pt_regs *regs)
+{
+	unsigned long badvadr = pt_badva(regs);
+
+	do_page_fault(badvadr, FLT_IFETCH, regs);
+}
diff -druN linux-libre-3.1-gnu/arch/hexagon/mm/vm_tlb.c linux-libre-3.2-gnu/arch/hexagon/mm/vm_tlb.c
--- linux-libre-3.1-gnu/arch/hexagon/mm/vm_tlb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/hexagon/mm/vm_tlb.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,93 @@
+/*
+ * Hexagon Virtual Machine TLB functions
+ *
+ * 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.
+ */
+
+/*
+ * The Hexagon Virtual Machine conceals the real workings of
+ * the TLB, but there are one or two functions that need to
+ * be instantiated for it, differently from a native build.
+ */
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/hexagon_vm.h>
+
+/*
+ * Initial VM implementation has only one map active at a time, with
+ * TLB purgings on changes.  So either we're nuking the current map,
+ * or it's a no-op.  This operation is messy on true SMPs where other
+ * processors must be induced to flush the copies in their local TLBs,
+ * but Hexagon thread-based virtual processors share the same MMU.
+ */
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+			unsigned long end)
+{
+	struct mm_struct *mm = vma->vm_mm;
+
+	if (mm->context.ptbase == current->active_mm->context.ptbase)
+		__vmclrmap((void *)start, end - start);
+}
+
+/*
+ * Flush a page from the kernel virtual map - used by highmem
+ */
+void flush_tlb_one(unsigned long vaddr)
+{
+	__vmclrmap((void *)vaddr, PAGE_SIZE);
+}
+
+/*
+ * Flush all TLBs across all CPUs, virtual or real.
+ * A single Hexagon core has 6 thread contexts but
+ * only one TLB.
+ */
+void tlb_flush_all(void)
+{
+	/*  should probably use that fixaddr end or whateve label  */
+	__vmclrmap(0, 0xffff0000);
+}
+
+/*
+ * Flush TLB entries associated with a given mm_struct mapping.
+ */
+void flush_tlb_mm(struct mm_struct *mm)
+{
+	/* Current Virtual Machine has only one map active at a time */
+	if (current->active_mm->context.ptbase == mm->context.ptbase)
+		tlb_flush_all();
+}
+
+/*
+ * Flush TLB state associated with a page of a vma.
+ */
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long vaddr)
+{
+	struct mm_struct *mm = vma->vm_mm;
+
+	if (mm->context.ptbase  == current->active_mm->context.ptbase)
+		__vmclrmap((void *)vaddr, PAGE_SIZE);
+}
+
+/*
+ * Flush TLB entries associated with a kernel address range.
+ * Like flush range, but without the check on the vma->vm_mm.
+ */
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+		__vmclrmap((void *)start, end - start);
+}
diff -druN linux-libre-3.1-gnu/arch/ia64/configs/generic_defconfig linux-libre-3.2-gnu/arch/ia64/configs/generic_defconfig
--- linux-libre-3.1-gnu/arch/ia64/configs/generic_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/configs/generic_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -87,6 +87,7 @@
 CONFIG_NET_TULIP=y
 CONFIG_TULIP=m
 CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=m
 CONFIG_E1000=y
 CONFIG_IGB=y
@@ -234,4 +235,4 @@
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_T10DIF=y
 CONFIG_MISC_DEVICES=y
-CONFIG_DMAR=y
+CONFIG_INTEL_IOMMU=y
diff -druN linux-libre-3.1-gnu/arch/ia64/configs/gensparse_defconfig linux-libre-3.2-gnu/arch/ia64/configs/gensparse_defconfig
--- linux-libre-3.1-gnu/arch/ia64/configs/gensparse_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/configs/gensparse_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -75,6 +75,7 @@
 CONFIG_NET_TULIP=y
 CONFIG_TULIP=m
 CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=m
 CONFIG_E1000=y
 CONFIG_TIGON3=y
diff -druN linux-libre-3.1-gnu/arch/ia64/configs/tiger_defconfig linux-libre-3.2-gnu/arch/ia64/configs/tiger_defconfig
--- linux-libre-3.1-gnu/arch/ia64/configs/tiger_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/configs/tiger_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -77,6 +77,7 @@
 CONFIG_NET_TULIP=y
 CONFIG_TULIP=m
 CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=m
 CONFIG_E1000=y
 CONFIG_TIGON3=y
diff -druN linux-libre-3.1-gnu/arch/ia64/configs/xen_domu_defconfig linux-libre-3.2-gnu/arch/ia64/configs/xen_domu_defconfig
--- linux-libre-3.1-gnu/arch/ia64/configs/xen_domu_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/configs/xen_domu_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -80,6 +80,7 @@
 CONFIG_NET_TULIP=y
 CONFIG_TULIP=m
 CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=m
 CONFIG_E1000=y
 CONFIG_TIGON3=y
diff -druN linux-libre-3.1-gnu/arch/ia64/configs/zx1_defconfig linux-libre-3.2-gnu/arch/ia64/configs/zx1_defconfig
--- linux-libre-3.1-gnu/arch/ia64/configs/zx1_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/configs/zx1_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -57,6 +57,7 @@
 CONFIG_TULIP_NAPI=y
 CONFIG_TULIP_NAPI_HW_MITIGATION=y
 CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=y
 CONFIG_E1000=y
 CONFIG_TIGON3=y
diff -druN linux-libre-3.1-gnu/arch/ia64/dig/Makefile linux-libre-3.2-gnu/arch/ia64/dig/Makefile
--- linux-libre-3.1-gnu/arch/ia64/dig/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/dig/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 #
 
 obj-y := setup.o
-ifeq ($(CONFIG_DMAR), y)
+ifeq ($(CONFIG_INTEL_IOMMU), y)
 obj-$(CONFIG_IA64_GENERIC) += machvec.o machvec_vtd.o
 else
 obj-$(CONFIG_IA64_GENERIC) += machvec.o
diff -druN linux-libre-3.1-gnu/arch/ia64/hp/common/hwsw_iommu.c linux-libre-3.2-gnu/arch/ia64/hp/common/hwsw_iommu.c
--- linux-libre-3.1-gnu/arch/ia64/hp/common/hwsw_iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/hp/common/hwsw_iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/swiotlb.h>
+#include <linux/export.h>
 #include <asm/machvec.h>
 
 extern struct dma_map_ops sba_dma_ops, swiotlb_dma_ops;
diff -druN linux-libre-3.1-gnu/arch/ia64/hp/common/sba_iommu.c linux-libre-3.2-gnu/arch/ia64/hp/common/sba_iommu.c
--- linux-libre-3.1-gnu/arch/ia64/hp/common/sba_iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/hp/common/sba_iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -915,7 +915,7 @@
  * @dir:  R/W or both.
  * @attrs: optional dma attributes
  *
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
  */
 static dma_addr_t sba_map_page(struct device *dev, struct page *page,
 			       unsigned long poff, size_t size,
@@ -1044,7 +1044,7 @@
  * @dir:  R/W or both.
  * @attrs: optional dma attributes
  *
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
  */
 static void sba_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
 			   enum dma_data_direction dir, struct dma_attrs *attrs)
@@ -1127,7 +1127,7 @@
  * @size:  number of bytes mapped in driver buffer.
  * @dma_handle:  IOVA of new buffer.
  *
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
  */
 static void *
 sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flags)
@@ -1190,7 +1190,7 @@
  * @vaddr:  virtual address IOVA of "consistent" buffer.
  * @dma_handler:  IO virtual address of "consistent" buffer.
  *
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
  */
 static void sba_free_coherent (struct device *dev, size_t size, void *vaddr,
 			       dma_addr_t dma_handle)
@@ -1453,7 +1453,7 @@
  * @dir:  R/W or both.
  * @attrs: optional dma attributes
  *
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
  */
 static int sba_map_sg_attrs(struct device *dev, struct scatterlist *sglist,
 			    int nents, enum dma_data_direction dir,
@@ -1549,7 +1549,7 @@
  * @dir:  R/W or both.
  * @attrs: optional dma attributes
  *
- * See Documentation/PCI/PCI-DMA-mapping.txt
+ * See Documentation/DMA-API-HOWTO.txt
  */
 static void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
 			       int nents, enum dma_data_direction dir,
diff -druN linux-libre-3.1-gnu/arch/ia64/hp/sim/simeth.c linux-libre-3.2-gnu/arch/ia64/hp/sim/simeth.c
--- linux-libre-3.1-gnu/arch/ia64/hp/sim/simeth.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/hp/sim/simeth.c	2012-01-04 18:55:44.000000000 -0500
@@ -172,7 +172,7 @@
 	.ndo_stop		= simeth_close,
 	.ndo_start_xmit		= simeth_tx,
 	.ndo_get_stats		= simeth_get_stats,
-	.ndo_set_multicast_list	= set_multicast_list, /* not yet used */
+	.ndo_set_rx_mode	= set_multicast_list, /* not yet used */
 
 };
 
diff -druN linux-libre-3.1-gnu/arch/ia64/include/asm/cputime.h linux-libre-3.2-gnu/arch/ia64/include/asm/cputime.h
--- linux-libre-3.1-gnu/arch/ia64/include/asm/cputime.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/include/asm/cputime.h	2012-01-04 18:55:44.000000000 -0500
@@ -60,6 +60,7 @@
  */
 #define cputime_to_usecs(__ct)		((__ct) / NSEC_PER_USEC)
 #define usecs_to_cputime(__usecs)	((__usecs) * NSEC_PER_USEC)
+#define usecs_to_cputime64(__usecs)	usecs_to_cputime(__usecs)
 
 /*
  * Convert cputime <-> seconds
diff -druN linux-libre-3.1-gnu/arch/ia64/include/asm/device.h linux-libre-3.2-gnu/arch/ia64/include/asm/device.h
--- linux-libre-3.1-gnu/arch/ia64/include/asm/device.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/include/asm/device.h	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
 #ifdef CONFIG_ACPI
 	void	*acpi_handle;
 #endif
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
 	void *iommu; /* hook for IOMMU specific extension */
 #endif
 };
diff -druN linux-libre-3.1-gnu/arch/ia64/include/asm/iommu.h linux-libre-3.2-gnu/arch/ia64/include/asm/iommu.h
--- linux-libre-3.1-gnu/arch/ia64/include/asm/iommu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/include/asm/iommu.h	2012-01-04 18:55:44.000000000 -0500
@@ -7,12 +7,14 @@
 
 extern void pci_iommu_shutdown(void);
 extern void no_iommu_init(void);
+#ifdef	CONFIG_INTEL_IOMMU
 extern int force_iommu, no_iommu;
-extern int iommu_detected;
-#ifdef	CONFIG_DMAR
 extern int iommu_pass_through;
+extern int iommu_detected;
 #else
 #define iommu_pass_through	(0)
+#define no_iommu		(1)
+#define iommu_detected		(0)
 #endif
 extern void iommu_dma_init(void);
 extern void machvec_init(const char *name);
diff -druN linux-libre-3.1-gnu/arch/ia64/include/asm/pci.h linux-libre-3.2-gnu/arch/ia64/include/asm/pci.h
--- linux-libre-3.1-gnu/arch/ia64/include/asm/pci.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/include/asm/pci.h	2012-01-04 18:55:44.000000000 -0500
@@ -139,7 +139,7 @@
 	return channel ? isa_irq_to_vector(15) : isa_irq_to_vector(14);
 }
 
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
 extern void pci_iommu_alloc(void);
 #endif
 #endif /* _ASM_IA64_PCI_H */
diff -druN linux-libre-3.1-gnu/arch/ia64/include/asm/unistd.h linux-libre-3.2-gnu/arch/ia64/include/asm/unistd.h
--- linux-libre-3.1-gnu/arch/ia64/include/asm/unistd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -321,11 +321,13 @@
 #define __NR_syncfs			1329
 #define __NR_setns			1330
 #define __NR_sendmmsg			1331
+#define __NR_process_vm_readv		1332
+#define __NR_process_vm_writev		1333
 
 #ifdef __KERNEL__
 
 
-#define NR_syscalls			308 /* length of syscall table */
+#define NR_syscalls			310 /* length of syscall table */
 
 /*
  * The following defines stop scripts/checksyscalls.sh from complaining about
diff -druN linux-libre-3.1-gnu/arch/ia64/include/asm/xen/grant_table.h linux-libre-3.2-gnu/arch/ia64/include/asm/xen/grant_table.h
--- linux-libre-3.1-gnu/arch/ia64/include/asm/xen/grant_table.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/include/asm/xen/grant_table.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/******************************************************************************
- * arch/ia64/include/asm/xen/grant_table.h
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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_IA64_XEN_GRANT_TABLE_H
-#define _ASM_IA64_XEN_GRANT_TABLE_H
-
-struct vm_struct *xen_alloc_vm_area(unsigned long size);
-void xen_free_vm_area(struct vm_struct *area);
-
-#endif /* _ASM_IA64_XEN_GRANT_TABLE_H */
diff -druN linux-libre-3.1-gnu/arch/ia64/include/asm/xen/interface.h linux-libre-3.2-gnu/arch/ia64/include/asm/xen/interface.h
--- linux-libre-3.1-gnu/arch/ia64/include/asm/xen/interface.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/include/asm/xen/interface.h	2012-01-04 18:55:44.000000000 -0500
@@ -76,6 +76,7 @@
 DEFINE_GUEST_HANDLE(int);
 DEFINE_GUEST_HANDLE(long);
 DEFINE_GUEST_HANDLE(void);
+DEFINE_GUEST_HANDLE(uint64_t);
 
 typedef unsigned long xen_pfn_t;
 DEFINE_GUEST_HANDLE(xen_pfn_t);
diff -druN linux-libre-3.1-gnu/arch/ia64/Kconfig linux-libre-3.2-gnu/arch/ia64/Kconfig
--- linux-libre-3.1-gnu/arch/ia64/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -92,7 +92,7 @@
 	def_bool y
 
 config GENERIC_GPIO
-	def_bool y
+	bool
 
 config DMI
 	bool
diff -druN linux-libre-3.1-gnu/arch/ia64/kernel/acpi.c linux-libre-3.2-gnu/arch/ia64/kernel/acpi.c
--- linux-libre-3.1-gnu/arch/ia64/kernel/acpi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/kernel/acpi.c	2012-01-04 18:55:44.000000000 -0500
@@ -88,7 +88,7 @@
 	struct acpi_table_rsdp *rsdp;
 	struct acpi_table_xsdt *xsdt;
 	struct acpi_table_header *hdr;
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
 	u64 i, nentries;
 #endif
 
@@ -125,7 +125,7 @@
 		return "xen";
 	}
 
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
 	/* Look for Intel IOMMU */
 	nentries = (hdr->length - sizeof(*hdr)) /
 			 sizeof(xsdt->table_offset_entry[0]);
diff -druN linux-libre-3.1-gnu/arch/ia64/kernel/dma-mapping.c linux-libre-3.2-gnu/arch/ia64/kernel/dma-mapping.c
--- linux-libre-3.1-gnu/arch/ia64/kernel/dma-mapping.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/kernel/dma-mapping.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,5 @@
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 
 /* Set this to 1 if there is a HW IOMMU in the system */
 int iommu_detected __read_mostly;
diff -druN linux-libre-3.1-gnu/arch/ia64/kernel/entry.S linux-libre-3.2-gnu/arch/ia64/kernel/entry.S
--- linux-libre-3.1-gnu/arch/ia64/kernel/entry.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/kernel/entry.S	2012-01-04 18:55:44.000000000 -0500
@@ -1777,6 +1777,8 @@
 	data8 sys_syncfs
 	data8 sys_setns				// 1330
 	data8 sys_sendmmsg
+	data8 sys_process_vm_readv
+	data8 sys_process_vm_writev
 
 	.org sys_call_table + 8*NR_syscalls	// guard against failures to increase NR_syscalls
 #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
diff -druN linux-libre-3.1-gnu/arch/ia64/kernel/Makefile linux-libre-3.2-gnu/arch/ia64/kernel/Makefile
--- linux-libre-3.1-gnu/arch/ia64/kernel/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,7 @@
 ifneq ($(CONFIG_IA64_ESI),)
 obj-y				+= esi_stub.o	# must be in kernel proper
 endif
-obj-$(CONFIG_DMAR)		+= pci-dma.o
+obj-$(CONFIG_INTEL_IOMMU)	+= pci-dma.o
 obj-$(CONFIG_SWIOTLB)		+= pci-swiotlb.o
 
 obj-$(CONFIG_BINFMT_ELF)	+= elfcore.o
diff -druN linux-libre-3.1-gnu/arch/ia64/kernel/msi_ia64.c linux-libre-3.2-gnu/arch/ia64/kernel/msi_ia64.c
--- linux-libre-3.1-gnu/arch/ia64/kernel/msi_ia64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/kernel/msi_ia64.c	2012-01-04 18:55:44.000000000 -0500
@@ -131,7 +131,7 @@
 	return ia64_teardown_msi_irq(irq);
 }
 
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
 #ifdef CONFIG_SMP
 static int dmar_msi_set_affinity(struct irq_data *data,
 				 const struct cpumask *mask, bool force)
@@ -210,5 +210,5 @@
 				      "edge");
 	return 0;
 }
-#endif /* CONFIG_DMAR */
+#endif /* CONFIG_INTEL_IOMMU */
 
diff -druN linux-libre-3.1-gnu/arch/ia64/kernel/pci-dma.c linux-libre-3.2-gnu/arch/ia64/kernel/pci-dma.c
--- linux-libre-3.1-gnu/arch/ia64/kernel/pci-dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/kernel/pci-dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 
 #include <asm/system.h>
 
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
 
 #include <linux/kernel.h>
 
diff -druN linux-libre-3.1-gnu/arch/ia64/kernel/topology.c linux-libre-3.2-gnu/arch/ia64/kernel/topology.c
--- linux-libre-3.1-gnu/arch/ia64/kernel/topology.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/kernel/topology.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/bootmem.h>
 #include <linux/nodemask.h>
 #include <linux/notifier.h>
+#include <linux/export.h>
 #include <asm/mmzone.h>
 #include <asm/numa.h>
 #include <asm/cpu.h>
diff -druN linux-libre-3.1-gnu/arch/ia64/kvm/kvm-ia64.c linux-libre-3.2-gnu/arch/ia64/kvm/kvm-ia64.c
--- linux-libre-3.1-gnu/arch/ia64/kvm/kvm-ia64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/kvm/kvm-ia64.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 #include <linux/uaccess.h>
 #include <linux/iommu.h>
 #include <linux/intel-iommu.h>
+#include <linux/pci.h>
 
 #include <asm/pgtable.h>
 #include <asm/gcc_intrin.h>
@@ -204,7 +205,7 @@
 		r = KVM_COALESCED_MMIO_PAGE_OFFSET;
 		break;
 	case KVM_CAP_IOMMU:
-		r = iommu_found();
+		r = iommu_present(&pci_bus_type);
 		break;
 	default:
 		r = 0;
diff -druN linux-libre-3.1-gnu/arch/ia64/pci/pci.c linux-libre-3.2-gnu/arch/ia64/pci/pci.c
--- linux-libre-3.1-gnu/arch/ia64/pci/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/pci/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/bootmem.h>
+#include <linux/export.h>
 
 #include <asm/machvec.h>
 #include <asm/page.h>
diff -druN linux-libre-3.1-gnu/arch/ia64/sn/kernel/io_acpi_init.c linux-libre-3.2-gnu/arch/ia64/sn/kernel/io_acpi_init.c
--- linux-libre-3.1-gnu/arch/ia64/sn/kernel/io_acpi_init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/sn/kernel/io_acpi_init.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include "xtalk/hubdev.h"
 #include <linux/acpi.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 
 
 /*
diff -druN linux-libre-3.1-gnu/arch/ia64/sn/kernel/io_init.c linux-libre-3.2-gnu/arch/ia64/sn/kernel/io_init.c
--- linux-libre-3.1-gnu/arch/ia64/sn/kernel/io_init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/sn/kernel/io_init.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <asm/sn/types.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/io.h>
diff -druN linux-libre-3.1-gnu/arch/ia64/sn/kernel/sn2/sn_hwperf.c linux-libre-3.2-gnu/arch/ia64/sn/kernel/sn2/sn_hwperf.c
--- linux-libre-3.1-gnu/arch/ia64/sn/kernel/sn2/sn_hwperf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/sn/kernel/sn2/sn_hwperf.c	2012-01-04 18:55:44.000000000 -0500
@@ -615,11 +615,15 @@
 		}
 	}
 
-	if (cpu == SN_HWPERF_ARG_ANY_CPU || cpu == get_cpu()) {
-		/* don't care, or already on correct cpu */
+	if (cpu == SN_HWPERF_ARG_ANY_CPU) {
+		/* don't care which cpu */
 		sn_hwperf_call_sal(op_info);
-	}
-	else {
+	} else if (cpu == get_cpu()) {
+		/* already on correct cpu */
+		sn_hwperf_call_sal(op_info);
+		put_cpu();
+	} else {
+		put_cpu();
 		if (use_ipi) {
 			/* use an interprocessor interrupt to call SAL */
 			smp_call_function_single(cpu, sn_hwperf_call_sal,
diff -druN linux-libre-3.1-gnu/arch/ia64/sn/pci/pcibr/pcibr_dma.c linux-libre-3.2-gnu/arch/ia64/sn/pci/pcibr/pcibr_dma.c
--- linux-libre-3.1-gnu/arch/ia64/sn/pci/pcibr/pcibr_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/sn/pci/pcibr/pcibr_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 
 #include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/export.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/geo.h>
 #include <asm/sn/pcibr_provider.h>
diff -druN linux-libre-3.1-gnu/arch/ia64/sn/pci/pcibr/pcibr_provider.c linux-libre-3.2-gnu/arch/ia64/sn/pci/pcibr/pcibr_provider.c
--- linux-libre-3.1-gnu/arch/ia64/sn/pci/pcibr/pcibr_provider.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/sn/pci/pcibr/pcibr_provider.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
+#include <linux/export.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/geo.h>
 #include <asm/sn/pcibr_provider.h>
diff -druN linux-libre-3.1-gnu/arch/ia64/sn/pci/tioca_provider.c linux-libre-3.2-gnu/arch/ia64/sn/pci/tioca_provider.c
--- linux-libre-3.1-gnu/arch/ia64/sn/pci/tioca_provider.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/sn/pci/tioca_provider.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/pci.h>
 #include <linux/bitmap.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/io.h>
diff -druN linux-libre-3.1-gnu/arch/ia64/xen/grant-table.c linux-libre-3.2-gnu/arch/ia64/xen/grant-table.c
--- linux-libre-3.1-gnu/arch/ia64/xen/grant-table.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/xen/grant-table.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,68 +31,6 @@
 
 #include <asm/xen/hypervisor.h>
 
-struct vm_struct *xen_alloc_vm_area(unsigned long size)
-{
-	int order;
-	unsigned long virt;
-	unsigned long nr_pages;
-	struct vm_struct *area;
-
-	order = get_order(size);
-	virt = __get_free_pages(GFP_KERNEL, order);
-	if (virt == 0)
-		goto err0;
-	nr_pages = 1 << order;
-	scrub_pages(virt, nr_pages);
-
-	area = kmalloc(sizeof(*area), GFP_KERNEL);
-	if (area == NULL)
-		goto err1;
-
-	area->flags = VM_IOREMAP;
-	area->addr = (void *)virt;
-	area->size = size;
-	area->pages = NULL;
-	area->nr_pages = nr_pages;
-	area->phys_addr = 0;	/* xenbus_map_ring_valloc uses this field!  */
-
-	return area;
-
-err1:
-	free_pages(virt, order);
-err0:
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(xen_alloc_vm_area);
-
-void xen_free_vm_area(struct vm_struct *area)
-{
-	unsigned int order = get_order(area->size);
-	unsigned long i;
-	unsigned long phys_addr = __pa(area->addr);
-
-	/* This area is used for foreign page mappping.
-	 * So underlying machine page may not be assigned. */
-	for (i = 0; i < (1 << order); i++) {
-		unsigned long ret;
-		unsigned long gpfn = (phys_addr >> PAGE_SHIFT) + i;
-		struct xen_memory_reservation reservation = {
-			.nr_extents   = 1,
-			.address_bits = 0,
-			.extent_order = 0,
-			.domid        = DOMID_SELF
-		};
-		set_xen_guest_handle(reservation.extent_start, &gpfn);
-		ret = HYPERVISOR_memory_op(XENMEM_populate_physmap,
-					   &reservation);
-		BUG_ON(ret != 1);
-	}
-	free_pages((unsigned long)area->addr, order);
-	kfree(area);
-}
-EXPORT_SYMBOL_GPL(xen_free_vm_area);
-
-
 /****************************************************************************
  * grant table hack
  * cmd: GNTTABOP_xxx
diff -druN linux-libre-3.1-gnu/arch/ia64/xen/hypervisor.c linux-libre-3.2-gnu/arch/ia64/xen/hypervisor.c
--- linux-libre-3.1-gnu/arch/ia64/xen/hypervisor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/ia64/xen/hypervisor.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include <linux/efi.h>
+#include <linux/export.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/privop.h>
 
diff -druN linux-libre-3.1-gnu/arch/m32r/Kconfig linux-libre-3.2-gnu/arch/m32r/Kconfig
--- linux-libre-3.1-gnu/arch/m32r/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m32r/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 	select HAVE_GENERIC_HARDIRQS
 	select GENERIC_IRQ_PROBE
 	select GENERIC_IRQ_SHOW
+	select GENERIC_ATOMIC64
 
 config SBUS
 	bool
@@ -322,13 +323,6 @@
 	default "1"
 	depends on NEED_MULTIPLE_NODES
 
-# turning this on wastes a bunch of space.
-# Summit needs it only when NUMA is on
-config BOOT_IOREMAP
-	bool
-	depends on NUMA
-	default n
-
 endmenu
 
 
diff -druN linux-libre-3.1-gnu/arch/m68k/amiga/amiints.c linux-libre-3.2-gnu/arch/m68k/amiga/amiints.c
--- linux-libre-3.1-gnu/arch/m68k/amiga/amiints.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/amiga/amiints.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,43 +1,15 @@
 /*
- * linux/arch/m68k/amiga/amiints.c -- Amiga Linux interrupt handling code
+ * Amiga Linux interrupt handling code
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
  * for more details.
- *
- * 11/07/96: rewritten interrupt handling, irq lists are exists now only for
- *           this sources where it makes sense (VERTB/PORTS/EXTER) and you must
- *           be careful that dev_id for this sources is unique since this the
- *           only possibility to distinguish between different handlers for
- *           free_irq. irq lists also have different irq flags:
- *           - IRQ_FLG_FAST: handler is inserted at top of list (after other
- *                           fast handlers)
- *           - IRQ_FLG_SLOW: handler is inserted at bottom of list and before
- *                           they're executed irq level is set to the previous
- *                           one, but handlers don't need to be reentrant, if
- *                           reentrance occurred, slow handlers will be just
- *                           called again.
- *           The whole interrupt handling for CIAs is moved to cia.c
- *           /Roman Zippel
- *
- * 07/08/99: rewamp of the interrupt handling - we now have two types of
- *           interrupts, normal and fast handlers, fast handlers being
- *           marked with IRQF_DISABLED and runs with all other interrupts
- *           disabled. Normal interrupts disable their own source but
- *           run with all other interrupt sources enabled.
- *           PORTS and EXTER interrupts are always shared even if the
- *           drivers do not explicitly mark this when calling
- *           request_irq which they really should do.
- *           This is similar to the way interrupts are handled on all
- *           other architectures and makes a ton of sense besides
- *           having the advantage of making it easier to share
- *           drivers.
- *           /Jes
  */
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
+#include <linux/irq.h>
 
 #include <asm/irq.h>
 #include <asm/traps.h>
@@ -45,56 +17,6 @@
 #include <asm/amigaints.h>
 #include <asm/amipcmcia.h>
 
-static void amiga_enable_irq(unsigned int irq);
-static void amiga_disable_irq(unsigned int irq);
-static irqreturn_t ami_int1(int irq, void *dev_id);
-static irqreturn_t ami_int3(int irq, void *dev_id);
-static irqreturn_t ami_int4(int irq, void *dev_id);
-static irqreturn_t ami_int5(int irq, void *dev_id);
-
-static struct irq_controller amiga_irq_controller = {
-	.name		= "amiga",
-	.lock		= __SPIN_LOCK_UNLOCKED(amiga_irq_controller.lock),
-	.enable		= amiga_enable_irq,
-	.disable	= amiga_disable_irq,
-};
-
-/*
- * void amiga_init_IRQ(void)
- *
- * Parameters:	None
- *
- * Returns:	Nothing
- *
- * This function should be called during kernel startup to initialize
- * the amiga IRQ handling routines.
- */
-
-void __init amiga_init_IRQ(void)
-{
-	if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL))
-		pr_err("Couldn't register int%d\n", 1);
-	if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL))
-		pr_err("Couldn't register int%d\n", 3);
-	if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL))
-		pr_err("Couldn't register int%d\n", 4);
-	if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL))
-		pr_err("Couldn't register int%d\n", 5);
-
-	m68k_setup_irq_controller(&amiga_irq_controller, IRQ_USER, AMI_STD_IRQS);
-
-	/* turn off PCMCIA interrupts */
-	if (AMIGAHW_PRESENT(PCMCIA))
-		gayle.inten = GAYLE_IRQ_IDE;
-
-	/* turn off all interrupts and enable the master interrupt bit */
-	amiga_custom.intena = 0x7fff;
-	amiga_custom.intreq = 0x7fff;
-	amiga_custom.intena = IF_SETCLR | IF_INTEN;
-
-	cia_init_IRQ(&ciaa_base);
-	cia_init_IRQ(&ciab_base);
-}
 
 /*
  * Enable/disable a particular machine specific interrupt source.
@@ -103,112 +25,150 @@
  * internal data, that may not be changed by the interrupt at the same time.
  */
 
-static void amiga_enable_irq(unsigned int irq)
+static void amiga_irq_enable(struct irq_data *data)
 {
-	amiga_custom.intena = IF_SETCLR | (1 << (irq - IRQ_USER));
+	amiga_custom.intena = IF_SETCLR | (1 << (data->irq - IRQ_USER));
 }
 
-static void amiga_disable_irq(unsigned int irq)
+static void amiga_irq_disable(struct irq_data *data)
 {
-	amiga_custom.intena = 1 << (irq - IRQ_USER);
+	amiga_custom.intena = 1 << (data->irq - IRQ_USER);
 }
 
+static struct irq_chip amiga_irq_chip = {
+	.name		= "amiga",
+	.irq_enable	= amiga_irq_enable,
+	.irq_disable	= amiga_irq_disable,
+};
+
+
 /*
  * The builtin Amiga hardware interrupt handlers.
  */
 
-static irqreturn_t ami_int1(int irq, void *dev_id)
+static void ami_int1(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
 	/* if serial transmit buffer empty, interrupt */
 	if (ints & IF_TBE) {
 		amiga_custom.intreq = IF_TBE;
-		m68k_handle_int(IRQ_AMIGA_TBE);
+		generic_handle_irq(IRQ_AMIGA_TBE);
 	}
 
 	/* if floppy disk transfer complete, interrupt */
 	if (ints & IF_DSKBLK) {
 		amiga_custom.intreq = IF_DSKBLK;
-		m68k_handle_int(IRQ_AMIGA_DSKBLK);
+		generic_handle_irq(IRQ_AMIGA_DSKBLK);
 	}
 
 	/* if software interrupt set, interrupt */
 	if (ints & IF_SOFT) {
 		amiga_custom.intreq = IF_SOFT;
-		m68k_handle_int(IRQ_AMIGA_SOFT);
+		generic_handle_irq(IRQ_AMIGA_SOFT);
 	}
-	return IRQ_HANDLED;
 }
 
-static irqreturn_t ami_int3(int irq, void *dev_id)
+static void ami_int3(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
 	/* if a blitter interrupt */
 	if (ints & IF_BLIT) {
 		amiga_custom.intreq = IF_BLIT;
-		m68k_handle_int(IRQ_AMIGA_BLIT);
+		generic_handle_irq(IRQ_AMIGA_BLIT);
 	}
 
 	/* if a copper interrupt */
 	if (ints & IF_COPER) {
 		amiga_custom.intreq = IF_COPER;
-		m68k_handle_int(IRQ_AMIGA_COPPER);
+		generic_handle_irq(IRQ_AMIGA_COPPER);
 	}
 
 	/* if a vertical blank interrupt */
 	if (ints & IF_VERTB) {
 		amiga_custom.intreq = IF_VERTB;
-		m68k_handle_int(IRQ_AMIGA_VERTB);
+		generic_handle_irq(IRQ_AMIGA_VERTB);
 	}
-	return IRQ_HANDLED;
 }
 
-static irqreturn_t ami_int4(int irq, void *dev_id)
+static void ami_int4(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
 	/* if audio 0 interrupt */
 	if (ints & IF_AUD0) {
 		amiga_custom.intreq = IF_AUD0;
-		m68k_handle_int(IRQ_AMIGA_AUD0);
+		generic_handle_irq(IRQ_AMIGA_AUD0);
 	}
 
 	/* if audio 1 interrupt */
 	if (ints & IF_AUD1) {
 		amiga_custom.intreq = IF_AUD1;
-		m68k_handle_int(IRQ_AMIGA_AUD1);
+		generic_handle_irq(IRQ_AMIGA_AUD1);
 	}
 
 	/* if audio 2 interrupt */
 	if (ints & IF_AUD2) {
 		amiga_custom.intreq = IF_AUD2;
-		m68k_handle_int(IRQ_AMIGA_AUD2);
+		generic_handle_irq(IRQ_AMIGA_AUD2);
 	}
 
 	/* if audio 3 interrupt */
 	if (ints & IF_AUD3) {
 		amiga_custom.intreq = IF_AUD3;
-		m68k_handle_int(IRQ_AMIGA_AUD3);
+		generic_handle_irq(IRQ_AMIGA_AUD3);
 	}
-	return IRQ_HANDLED;
 }
 
-static irqreturn_t ami_int5(int irq, void *dev_id)
+static void ami_int5(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
 	/* if serial receive buffer full interrupt */
 	if (ints & IF_RBF) {
 		/* acknowledge of IF_RBF must be done by the serial interrupt */
-		m68k_handle_int(IRQ_AMIGA_RBF);
+		generic_handle_irq(IRQ_AMIGA_RBF);
 	}
 
 	/* if a disk sync interrupt */
 	if (ints & IF_DSKSYN) {
 		amiga_custom.intreq = IF_DSKSYN;
-		m68k_handle_int(IRQ_AMIGA_DSKSYN);
+		generic_handle_irq(IRQ_AMIGA_DSKSYN);
 	}
-	return IRQ_HANDLED;
+}
+
+
+/*
+ * void amiga_init_IRQ(void)
+ *
+ * Parameters:	None
+ *
+ * Returns:	Nothing
+ *
+ * This function should be called during kernel startup to initialize
+ * the amiga IRQ handling routines.
+ */
+
+void __init amiga_init_IRQ(void)
+{
+	m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER,
+				  AMI_STD_IRQS);
+
+	irq_set_chained_handler(IRQ_AUTO_1, ami_int1);
+	irq_set_chained_handler(IRQ_AUTO_3, ami_int3);
+	irq_set_chained_handler(IRQ_AUTO_4, ami_int4);
+	irq_set_chained_handler(IRQ_AUTO_5, ami_int5);
+
+	/* turn off PCMCIA interrupts */
+	if (AMIGAHW_PRESENT(PCMCIA))
+		gayle.inten = GAYLE_IRQ_IDE;
+
+	/* turn off all interrupts and enable the master interrupt bit */
+	amiga_custom.intena = 0x7fff;
+	amiga_custom.intreq = 0x7fff;
+	amiga_custom.intena = IF_SETCLR | IF_INTEN;
+
+	cia_init_IRQ(&ciaa_base);
+	cia_init_IRQ(&ciab_base);
 }
diff -druN linux-libre-3.1-gnu/arch/m68k/amiga/cia.c linux-libre-3.2-gnu/arch/m68k/amiga/cia.c
--- linux-libre-3.1-gnu/arch/m68k/amiga/cia.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/amiga/cia.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,13 +93,14 @@
 	amiga_custom.intreq = base->int_mask;
 	for (; ints; mach_irq++, ints >>= 1) {
 		if (ints & 1)
-			m68k_handle_int(mach_irq);
+			generic_handle_irq(mach_irq);
 	}
 	return IRQ_HANDLED;
 }
 
-static void cia_enable_irq(unsigned int irq)
+static void cia_irq_enable(struct irq_data *data)
 {
+	unsigned int irq = data->irq;
 	unsigned char mask;
 
 	if (irq >= IRQ_AMIGA_CIAB) {
@@ -113,19 +114,20 @@
 	}
 }
 
-static void cia_disable_irq(unsigned int irq)
+static void cia_irq_disable(struct irq_data *data)
 {
+	unsigned int irq = data->irq;
+
 	if (irq >= IRQ_AMIGA_CIAB)
 		cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB));
 	else
 		cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA));
 }
 
-static struct irq_controller cia_irq_controller = {
+static struct irq_chip cia_irq_chip = {
 	.name		= "cia",
-	.lock		= __SPIN_LOCK_UNLOCKED(cia_irq_controller.lock),
-	.enable		= cia_enable_irq,
-	.disable	= cia_disable_irq,
+	.irq_enable	= cia_irq_enable,
+	.irq_disable	= cia_irq_disable,
 };
 
 /*
@@ -134,9 +136,9 @@
  * into this chain.
  */
 
-static void auto_enable_irq(unsigned int irq)
+static void auto_irq_enable(struct irq_data *data)
 {
-	switch (irq) {
+	switch (data->irq) {
 	case IRQ_AUTO_2:
 		amiga_custom.intena = IF_SETCLR | IF_PORTS;
 		break;
@@ -146,9 +148,9 @@
 	}
 }
 
-static void auto_disable_irq(unsigned int irq)
+static void auto_irq_disable(struct irq_data *data)
 {
-	switch (irq) {
+	switch (data->irq) {
 	case IRQ_AUTO_2:
 		amiga_custom.intena = IF_PORTS;
 		break;
@@ -158,24 +160,25 @@
 	}
 }
 
-static struct irq_controller auto_irq_controller = {
+static struct irq_chip auto_irq_chip = {
 	.name		= "auto",
-	.lock		= __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock),
-	.enable		= auto_enable_irq,
-	.disable	= auto_disable_irq,
+	.irq_enable	= auto_irq_enable,
+	.irq_disable	= auto_irq_disable,
 };
 
 void __init cia_init_IRQ(struct ciabase *base)
 {
-	m68k_setup_irq_controller(&cia_irq_controller, base->cia_irq, CIA_IRQS);
+	m68k_setup_irq_controller(&cia_irq_chip, handle_simple_irq,
+				  base->cia_irq, CIA_IRQS);
 
 	/* clear any pending interrupt and turn off all interrupts */
 	cia_set_irq(base, CIA_ICR_ALL);
 	cia_able_irq(base, CIA_ICR_ALL);
 
 	/* override auto int and install CIA handler */
-	m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1);
-	m68k_irq_startup(base->handler_irq);
+	m68k_setup_irq_controller(&auto_irq_chip, handle_simple_irq,
+				  base->handler_irq, 1);
+	m68k_irq_startup_irq(base->handler_irq);
 	if (request_irq(base->handler_irq, cia_handler, IRQF_SHARED,
 			base->name, base))
 		pr_err("Couldn't register %s interrupt\n", base->name);
diff -druN linux-libre-3.1-gnu/arch/m68k/apollo/dn_ints.c linux-libre-3.2-gnu/arch/m68k/apollo/dn_ints.c
--- linux-libre-3.1-gnu/arch/m68k/apollo/dn_ints.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/apollo/dn_ints.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,19 +1,13 @@
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
-#include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/apollohw.h>
 
-void dn_process_int(unsigned int irq, struct pt_regs *fp)
+unsigned int apollo_irq_startup(struct irq_data *data)
 {
-	__m68k_handle_int(irq, fp);
-
-	*(volatile unsigned char *)(pica)=0x20;
-	*(volatile unsigned char *)(picb)=0x20;
-}
+	unsigned int irq = data->irq;
 
-int apollo_irq_startup(unsigned int irq)
-{
 	if (irq < 8)
 		*(volatile unsigned char *)(pica+1) &= ~(1 << irq);
 	else
@@ -21,24 +15,33 @@
 	return 0;
 }
 
-void apollo_irq_shutdown(unsigned int irq)
+void apollo_irq_shutdown(struct irq_data *data)
 {
+	unsigned int irq = data->irq;
+
 	if (irq < 8)
 		*(volatile unsigned char *)(pica+1) |= (1 << irq);
 	else
 		*(volatile unsigned char *)(picb+1) |= (1 << (irq - 8));
 }
 
-static struct irq_controller apollo_irq_controller = {
+void apollo_irq_eoi(struct irq_data *data)
+{
+	*(volatile unsigned char *)(pica) = 0x20;
+	*(volatile unsigned char *)(picb) = 0x20;
+}
+
+static struct irq_chip apollo_irq_chip = {
 	.name           = "apollo",
-	.lock           = __SPIN_LOCK_UNLOCKED(apollo_irq_controller.lock),
-	.startup        = apollo_irq_startup,
-	.shutdown       = apollo_irq_shutdown,
+	.irq_startup    = apollo_irq_startup,
+	.irq_shutdown   = apollo_irq_shutdown,
+	.irq_eoi	= apollo_irq_eoi,
 };
 
 
 void __init dn_init_IRQ(void)
 {
-	m68k_setup_user_interrupt(VEC_USER + 96, 16, dn_process_int);
-	m68k_setup_irq_controller(&apollo_irq_controller, IRQ_APOLLO, 16);
+	m68k_setup_user_interrupt(VEC_USER + 96, 16);
+	m68k_setup_irq_controller(&apollo_irq_chip, handle_fasteoi_irq,
+				  IRQ_APOLLO, 16);
 }
diff -druN linux-libre-3.1-gnu/arch/m68k/atari/ataints.c linux-libre-3.2-gnu/arch/m68k/atari/ataints.c
--- linux-libre-3.1-gnu/arch/m68k/atari/ataints.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/atari/ataints.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,243 +60,7 @@
  * <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP,
  * TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can
  * be allocated by atari_register_vme_int().
- *
- * Each interrupt can be of three types:
- *
- *  - SLOW: The handler runs with all interrupts enabled, except the one it
- *    was called by (to avoid reentering). This should be the usual method.
- *    But it is currently possible only for MFP ints, since only the MFP
- *    offers an easy way to mask interrupts.
- *
- *  - FAST: The handler runs with all interrupts disabled. This should be used
- *    only for really fast handlers, that just do actions immediately
- *    necessary, and let the rest do a bottom half or task queue.
- *
- *  - PRIORITIZED: The handler can be interrupted by higher-level ints
- *    (greater IPL, no MFP priorities!). This is the method of choice for ints
- *    which should be slow, but are not from a MFP.
- *
- * The feature of more than one handler for one int source is still there, but
- * only applicable if all handers are of the same type. To not slow down
- * processing of ints with only one handler by the chaining feature, the list
- * calling function atari_call_irq_list() is only plugged in at the time the
- * second handler is registered.
- *
- * Implementation notes: For fast-as-possible int handling, there are separate
- * entry points for each type (slow/fast/prio). The assembler handler calls
- * the irq directly in the usual case, no C wrapper is involved. In case of
- * multiple handlers, atari_call_irq_list() is registered as handler and calls
- * in turn the real irq's. To ease access from assembler level to the irq
- * function pointer and accompanying data, these two are stored in a separate
- * array, irq_handler[]. The rest of data (type, name) are put into a second
- * array, irq_param, that is accessed from C only. For each slow interrupt (32
- * in all) there are separate handler functions, which makes it possible to
- * hard-code the MFP register address and value, are necessary to mask the
- * int. If there'd be only one generic function, lots of calculations would be
- * needed to determine MFP register and int mask from the vector number :-(
- *
- * Furthermore, slow ints may not lower the IPL below its previous value
- * (before the int happened). This is needed so that an int of class PRIO, on
- * that this int may be stacked, cannot be reentered. This feature is
- * implemented as follows: If the stack frame format is 1 (throwaway), the int
- * is not stacked, and the IPL is anded with 0xfbff, resulting in a new level
- * 2, which still blocks the HSYNC, but no interrupts of interest. If the
- * frame format is 0, the int is nested, and the old IPL value can be found in
- * the sr copy in the frame.
- */
-
-#if 0
-
-#define	NUM_INT_SOURCES	(8 + NUM_ATARI_SOURCES)
-
-typedef void (*asm_irq_handler)(void);
-
-struct irqhandler {
-	irqreturn_t (*handler)(int, void *, struct pt_regs *);
-	void	*dev_id;
-};
-
-struct irqparam {
-	unsigned long	flags;
-	const char	*devname;
-};
-
-/*
- * Array with irq's and their parameter data. This array is accessed from low
- * level assembler code, so an element size of 8 allows usage of index scaling
- * addressing mode.
  */
-static struct irqhandler irq_handler[NUM_INT_SOURCES];
-
-/*
- * This array hold the rest of parameters of int handlers: type
- * (slow,fast,prio) and the name of the handler. These values are only
- * accessed from C
- */
-static struct irqparam irq_param[NUM_INT_SOURCES];
-
-/* check for valid int number (complex, sigh...) */
-#define	IS_VALID_INTNO(n)											\
-	((n) > 0 &&														\
-	 /* autovec and ST-MFP ok anyway */								\
-	 (((n) < TTMFP_SOURCE_BASE) ||									\
-	  /* TT-MFP ok if present */									\
-	  ((n) >= TTMFP_SOURCE_BASE && (n) < SCC_SOURCE_BASE &&			\
-	   ATARIHW_PRESENT(TT_MFP)) ||									\
-	  /* SCC ok if present and number even */						\
-	  ((n) >= SCC_SOURCE_BASE && (n) < VME_SOURCE_BASE &&			\
-	   !((n) & 1) && ATARIHW_PRESENT(SCC)) ||						\
-	  /* greater numbers ok if they are registered VME vectors */		\
-	  ((n) >= VME_SOURCE_BASE && (n) < VME_SOURCE_BASE + VME_MAX_SOURCES && \
-		  free_vme_vec_bitmap & (1 << ((n) - VME_SOURCE_BASE)))))
-
-
-/*
- * Here start the assembler entry points for interrupts
- */
-
-#define IRQ_NAME(nr) atari_slow_irq_##nr##_handler(void)
-
-#define	BUILD_SLOW_IRQ(n)						   \
-asmlinkage void IRQ_NAME(n);						   \
-/* Dummy function to allow asm with operands.  */			   \
-void atari_slow_irq_##n##_dummy (void) {				   \
-__asm__ (__ALIGN_STR "\n"						   \
-"atari_slow_irq_" #n "_handler:\t"					   \
-"	addl	%6,%5\n"	/* preempt_count() += HARDIRQ_OFFSET */	   \
-	SAVE_ALL_INT "\n"						   \
-	GET_CURRENT(%%d0) "\n"						   \
-"	andb	#~(1<<(%c3&7)),%a4:w\n"	/* mask this interrupt */	   \
-	/* get old IPL from stack frame */				   \
-"	bfextu	%%sp@(%c2){#5,#3},%%d0\n"				   \
-"	movew	%%sr,%%d1\n"						   \
-"	bfins	%%d0,%%d1{#21,#3}\n"					   \
-"	movew	%%d1,%%sr\n"		/* set IPL = previous value */	   \
-"	addql	#1,%a0\n"						   \
-"	lea	%a1,%%a0\n"						   \
-"	pea	%%sp@\n"		/* push addr of frame */	   \
-"	movel	%%a0@(4),%%sp@-\n"	/* push handler data */		   \
-"	pea	(%c3+8)\n"		/* push int number */		   \
-"	movel	%%a0@,%%a0\n"						   \
-"	jbsr	%%a0@\n"		/* call the handler */		   \
-"	addql	#8,%%sp\n"						   \
-"	addql	#4,%%sp\n"						   \
-"	orw	#0x0600,%%sr\n"						   \
-"	andw	#0xfeff,%%sr\n"		/* set IPL = 6 again */		   \
-"	orb	#(1<<(%c3&7)),%a4:w\n"	/* now unmask the int again */	   \
-"	jbra	ret_from_interrupt\n"					   \
-	 : : "i" (&kstat_cpu(0).irqs[n+8]), "i" (&irq_handler[n+8]),	   \
-	     "n" (PT_OFF_SR), "n" (n),					   \
-	     "i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &st_mfp.int_mk_a)   \
-		        : (n & 16 ? &tt_mfp.int_mk_b : &st_mfp.int_mk_b)), \
-	     "m" (preempt_count()), "di" (HARDIRQ_OFFSET)		   \
-);									   \
-	for (;;);			/* fake noreturn */		   \
-}
-
-BUILD_SLOW_IRQ(0);
-BUILD_SLOW_IRQ(1);
-BUILD_SLOW_IRQ(2);
-BUILD_SLOW_IRQ(3);
-BUILD_SLOW_IRQ(4);
-BUILD_SLOW_IRQ(5);
-BUILD_SLOW_IRQ(6);
-BUILD_SLOW_IRQ(7);
-BUILD_SLOW_IRQ(8);
-BUILD_SLOW_IRQ(9);
-BUILD_SLOW_IRQ(10);
-BUILD_SLOW_IRQ(11);
-BUILD_SLOW_IRQ(12);
-BUILD_SLOW_IRQ(13);
-BUILD_SLOW_IRQ(14);
-BUILD_SLOW_IRQ(15);
-BUILD_SLOW_IRQ(16);
-BUILD_SLOW_IRQ(17);
-BUILD_SLOW_IRQ(18);
-BUILD_SLOW_IRQ(19);
-BUILD_SLOW_IRQ(20);
-BUILD_SLOW_IRQ(21);
-BUILD_SLOW_IRQ(22);
-BUILD_SLOW_IRQ(23);
-BUILD_SLOW_IRQ(24);
-BUILD_SLOW_IRQ(25);
-BUILD_SLOW_IRQ(26);
-BUILD_SLOW_IRQ(27);
-BUILD_SLOW_IRQ(28);
-BUILD_SLOW_IRQ(29);
-BUILD_SLOW_IRQ(30);
-BUILD_SLOW_IRQ(31);
-
-asm_irq_handler slow_handlers[32] = {
-	[0]	= atari_slow_irq_0_handler,
-	[1]	= atari_slow_irq_1_handler,
-	[2]	= atari_slow_irq_2_handler,
-	[3]	= atari_slow_irq_3_handler,
-	[4]	= atari_slow_irq_4_handler,
-	[5]	= atari_slow_irq_5_handler,
-	[6]	= atari_slow_irq_6_handler,
-	[7]	= atari_slow_irq_7_handler,
-	[8]	= atari_slow_irq_8_handler,
-	[9]	= atari_slow_irq_9_handler,
-	[10]	= atari_slow_irq_10_handler,
-	[11]	= atari_slow_irq_11_handler,
-	[12]	= atari_slow_irq_12_handler,
-	[13]	= atari_slow_irq_13_handler,
-	[14]	= atari_slow_irq_14_handler,
-	[15]	= atari_slow_irq_15_handler,
-	[16]	= atari_slow_irq_16_handler,
-	[17]	= atari_slow_irq_17_handler,
-	[18]	= atari_slow_irq_18_handler,
-	[19]	= atari_slow_irq_19_handler,
-	[20]	= atari_slow_irq_20_handler,
-	[21]	= atari_slow_irq_21_handler,
-	[22]	= atari_slow_irq_22_handler,
-	[23]	= atari_slow_irq_23_handler,
-	[24]	= atari_slow_irq_24_handler,
-	[25]	= atari_slow_irq_25_handler,
-	[26]	= atari_slow_irq_26_handler,
-	[27]	= atari_slow_irq_27_handler,
-	[28]	= atari_slow_irq_28_handler,
-	[29]	= atari_slow_irq_29_handler,
-	[30]	= atari_slow_irq_30_handler,
-	[31]	= atari_slow_irq_31_handler
-};
-
-asmlinkage void atari_fast_irq_handler( void );
-asmlinkage void atari_prio_irq_handler( void );
-
-/* Dummy function to allow asm with operands.  */
-void atari_fast_prio_irq_dummy (void) {
-__asm__ (__ALIGN_STR "\n"
-"atari_fast_irq_handler:\n\t"
-	"orw	#0x700,%%sr\n"		/* disable all interrupts */
-"atari_prio_irq_handler:\n\t"
-	"addl	%3,%2\n\t"		/* preempt_count() += HARDIRQ_OFFSET */
-	SAVE_ALL_INT "\n\t"
-	GET_CURRENT(%%d0) "\n\t"
-	/* get vector number from stack frame and convert to source */
-	"bfextu	%%sp@(%c1){#4,#10},%%d0\n\t"
-	"subw	#(0x40-8),%%d0\n\t"
-	"jpl	1f\n\t"
-	"addw	#(0x40-8-0x18),%%d0\n"
-    "1:\tlea	%a0,%%a0\n\t"
-	"addql	#1,%%a0@(%%d0:l:4)\n\t"
-	"lea	irq_handler,%%a0\n\t"
-	"lea	%%a0@(%%d0:l:8),%%a0\n\t"
-	"pea	%%sp@\n\t"		/* push frame address */
-	"movel	%%a0@(4),%%sp@-\n\t"	/* push handler data */
-	"movel	%%d0,%%sp@-\n\t"	/* push int number */
-	"movel	%%a0@,%%a0\n\t"
-	"jsr	%%a0@\n\t"		/* and call the handler */
-	"addql	#8,%%sp\n\t"
-	"addql	#4,%%sp\n\t"
-	"jbra	ret_from_interrupt"
-	 : : "i" (&kstat_cpu(0).irqs), "n" (PT_OFF_FORMATVEC),
-	     "m" (preempt_count()), "di" (HARDIRQ_OFFSET)
-);
-	for (;;);
-}
-#endif
 
 /*
  * Bitmap for free interrupt vector numbers
@@ -320,31 +84,44 @@
 
 extern int atari_SCC_reset_done;
 
-static int atari_startup_irq(unsigned int irq)
+static unsigned int atari_irq_startup(struct irq_data *data)
 {
-	m68k_irq_startup(irq);
+	unsigned int irq = data->irq;
+
+	m68k_irq_startup(data);
 	atari_turnon_irq(irq);
 	atari_enable_irq(irq);
 	return 0;
 }
 
-static void atari_shutdown_irq(unsigned int irq)
+static void atari_irq_shutdown(struct irq_data *data)
 {
+	unsigned int irq = data->irq;
+
 	atari_disable_irq(irq);
 	atari_turnoff_irq(irq);
-	m68k_irq_shutdown(irq);
+	m68k_irq_shutdown(data);
 
 	if (irq == IRQ_AUTO_4)
 	    vectors[VEC_INT4] = falcon_hblhandler;
 }
 
-static struct irq_controller atari_irq_controller = {
+static void atari_irq_enable(struct irq_data *data)
+{
+	atari_enable_irq(data->irq);
+}
+
+static void atari_irq_disable(struct irq_data *data)
+{
+	atari_disable_irq(data->irq);
+}
+
+static struct irq_chip atari_irq_chip = {
 	.name		= "atari",
-	.lock		= __SPIN_LOCK_UNLOCKED(atari_irq_controller.lock),
-	.startup	= atari_startup_irq,
-	.shutdown	= atari_shutdown_irq,
-	.enable		= atari_enable_irq,
-	.disable	= atari_disable_irq,
+	.irq_startup	= atari_irq_startup,
+	.irq_shutdown	= atari_irq_shutdown,
+	.irq_enable	= atari_irq_enable,
+	.irq_disable	= atari_irq_disable,
 };
 
 /*
@@ -360,8 +137,9 @@
 
 void __init atari_init_IRQ(void)
 {
-	m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER, NULL);
-	m68k_setup_irq_controller(&atari_irq_controller, 1, NUM_ATARI_SOURCES - 1);
+	m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER);
+	m68k_setup_irq_controller(&atari_irq_chip, handle_simple_irq, 1,
+				  NUM_ATARI_SOURCES - 1);
 
 	/* Initialize the MFP(s) */
 
diff -druN linux-libre-3.1-gnu/arch/m68k/atari/time.c linux-libre-3.2-gnu/arch/m68k/atari/time.c
--- linux-libre-3.1-gnu/arch/m68k/atari/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/atari/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 
 #include <asm/atariints.h>
 
diff -druN linux-libre-3.1-gnu/arch/m68k/bvme6000/config.c linux-libre-3.2-gnu/arch/m68k/bvme6000/config.c
--- linux-libre-3.1-gnu/arch/m68k/bvme6000/config.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/bvme6000/config.c	2012-01-04 18:55:44.000000000 -0500
@@ -86,7 +86,7 @@
  */
 static void __init bvme6000_init_IRQ(void)
 {
-	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+	m68k_setup_user_interrupt(VEC_USER, 192);
 }
 
 void __init config_bvme6000(void)
diff -druN linux-libre-3.1-gnu/arch/m68k/emu/nfblock.c linux-libre-3.2-gnu/arch/m68k/emu/nfblock.c
--- linux-libre-3.1-gnu/arch/m68k/emu/nfblock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/emu/nfblock.c	2012-01-04 18:55:44.000000000 -0500
@@ -59,7 +59,7 @@
 	struct gendisk *disk;
 };
 
-static int nfhd_make_request(struct request_queue *queue, struct bio *bio)
+static void nfhd_make_request(struct request_queue *queue, struct bio *bio)
 {
 	struct nfhd_device *dev = queue->queuedata;
 	struct bio_vec *bvec;
@@ -76,7 +76,6 @@
 		sec += len;
 	}
 	bio_endio(bio, 0);
-	return 0;
 }
 
 static int nfhd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
diff -druN linux-libre-3.1-gnu/arch/m68k/hp300/time.c linux-libre-3.2-gnu/arch/m68k/hp300/time.c
--- linux-libre-3.1-gnu/arch/m68k/hp300/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/hp300/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -70,7 +70,7 @@
 
   asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE));
 
-  if (request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector))
+  if (request_irq(IRQ_AUTO_6, hp300_tick, 0, "timer tick", vector))
     pr_err("Couldn't register timer interrupt\n");
 
   out_8(CLOCKBASE + CLKCR2, 0x1);		/* select CR1 */
diff -druN linux-libre-3.1-gnu/arch/m68k/include/asm/entry.h linux-libre-3.2-gnu/arch/m68k/include/asm/entry.h
--- linux-libre-3.1-gnu/arch/m68k/include/asm/entry.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/include/asm/entry.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,254 @@
-#ifdef __uClinux__
-#include "entry_no.h"
+#ifndef __M68K_ENTRY_H
+#define __M68K_ENTRY_H
+
+#include <asm/setup.h>
+#include <asm/page.h>
+#ifdef __ASSEMBLY__
+#include <asm/thread_info.h>
+#endif
+
+/*
+ * Stack layout in 'ret_from_exception':
+ *
+ *	This allows access to the syscall arguments in registers d1-d5
+ *
+ *	 0(sp) - d1
+ *	 4(sp) - d2
+ *	 8(sp) - d3
+ *	 C(sp) - d4
+ *	10(sp) - d5
+ *	14(sp) - a0
+ *	18(sp) - a1
+ *	1C(sp) - a2
+ *	20(sp) - d0
+ *	24(sp) - orig_d0
+ *	28(sp) - stack adjustment
+ *	2C(sp) - [ sr              ] [ format & vector ]
+ *	2E(sp) - [ pc-hiword       ] [ sr              ]
+ *	30(sp) - [ pc-loword       ] [ pc-hiword       ]
+ *	32(sp) - [ format & vector ] [ pc-loword       ]
+ *		  ^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^
+ *			M68K		  COLDFIRE
+ */
+
+/* the following macro is used when enabling interrupts */
+#if defined(MACH_ATARI_ONLY)
+	/* block out HSYNC on the atari */
+#define ALLOWINT	(~0x400)
+#define	MAX_NOINT_IPL	3
 #else
-#include "entry_mm.h"
+	/* portable version */
+#define ALLOWINT	(~0x700)
+#define	MAX_NOINT_IPL	0
+#endif /* machine compilation types */
+
+#ifdef __ASSEMBLY__
+/*
+ * This defines the normal kernel pt-regs layout.
+ *
+ * regs a3-a6 and d6-d7 are preserved by C code
+ * the kernel doesn't mess with usp unless it needs to
+ */
+#define SWITCH_STACK_SIZE	(6*4+4)	/* includes return address */
+
+#ifdef CONFIG_COLDFIRE
+#ifdef CONFIG_COLDFIRE_SW_A7
+/*
+ * This is made a little more tricky on older ColdFires. There is no
+ * separate supervisor and user stack pointers. Need to artificially
+ * construct a usp in software... When doing this we need to disable
+ * interrupts, otherwise bad things will happen.
+ */
+.globl sw_usp
+.globl sw_ksp
+
+.macro SAVE_ALL_SYS
+	move	#0x2700,%sr		/* disable intrs */
+	btst	#5,%sp@(2)		/* from user? */
+	bnes	6f			/* no, skip */
+	movel	%sp,sw_usp		/* save user sp */
+	addql	#8,sw_usp		/* remove exception */
+	movel	sw_ksp,%sp		/* kernel sp */
+	subql	#8,%sp			/* room for exception */
+	clrl	%sp@-			/* stkadj */
+	movel	%d0,%sp@-		/* orig d0 */
+	movel	%d0,%sp@-		/* d0 */
+	lea	%sp@(-32),%sp		/* space for 8 regs */
+	moveml	%d1-%d5/%a0-%a2,%sp@
+	movel	sw_usp,%a0		/* get usp */
+	movel	%a0@-,%sp@(PT_OFF_PC)	/* copy exception program counter */
+	movel	%a0@-,%sp@(PT_OFF_FORMATVEC)/*copy exception format/vector/sr */
+	bra	7f
+	6:
+	clrl	%sp@-			/* stkadj */
+	movel	%d0,%sp@-		/* orig d0 */
+	movel	%d0,%sp@-		/* d0 */
+	lea	%sp@(-32),%sp		/* space for 8 regs */
+	moveml	%d1-%d5/%a0-%a2,%sp@
+	7:
+.endm
+
+.macro SAVE_ALL_INT
+	SAVE_ALL_SYS
+	moveq	#-1,%d0			/* not system call entry */
+	movel	%d0,%sp@(PT_OFF_ORIG_D0)
+.endm
+
+.macro RESTORE_USER
+	move	#0x2700,%sr		/* disable intrs */
+	movel	sw_usp,%a0		/* get usp */
+	movel	%sp@(PT_OFF_PC),%a0@-	/* copy exception program counter */
+	movel	%sp@(PT_OFF_FORMATVEC),%a0@-/*copy exception format/vector/sr */
+	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		/* stkadj */
+	addql	#8,%sp			/* remove exception */
+	movel	%sp,sw_ksp		/* save ksp */
+	subql	#8,sw_usp		/* set exception */
+	movel	sw_usp,%sp		/* restore usp */
+	rte
+.endm
+
+.macro RDUSP
+	movel	sw_usp,%a3
+.endm
+
+.macro WRUSP
+	movel	%a3,sw_usp
+.endm
+
+#else /* !CONFIG_COLDFIRE_SW_A7 */
+/*
+ * Modern ColdFire parts have separate supervisor and user stack
+ * pointers. Simple load and restore macros for this case.
+ */
+.macro SAVE_ALL_SYS
+	move	#0x2700,%sr		/* disable intrs */
+	clrl	%sp@-			/* stkadj */
+	movel	%d0,%sp@-		/* orig d0 */
+	movel	%d0,%sp@-		/* d0 */
+	lea	%sp@(-32),%sp		/* space for 8 regs */
+	moveml	%d1-%d5/%a0-%a2,%sp@
+.endm
+
+.macro SAVE_ALL_INT
+	move	#0x2700,%sr		/* disable intrs */
+	clrl	%sp@-			/* stkadj */
+	pea	-1:w			/* orig d0 */
+	movel	%d0,%sp@-		/* d0 */
+	lea	%sp@(-32),%sp		/* space for 8 regs */
+	moveml	%d1-%d5/%a0-%a2,%sp@
+.endm
+
+.macro RESTORE_USER
+	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		/* stkadj */
+	rte
+.endm
+
+.macro RDUSP
+	/*move	%usp,%a3*/
+	.word	0x4e6b
+.endm
+
+.macro WRUSP
+	/*move	%a3,%usp*/
+	.word	0x4e63
+.endm
+
+#endif /* !CONFIG_COLDFIRE_SW_A7 */
+
+.macro SAVE_SWITCH_STACK
+	lea	%sp@(-24),%sp		/* 6 regs */
+	moveml	%a3-%a6/%d6-%d7,%sp@
+.endm
+
+.macro RESTORE_SWITCH_STACK
+	moveml	%sp@,%a3-%a6/%d6-%d7
+	lea	%sp@(24),%sp		/* 6 regs */
+.endm
+
+#else /* !CONFIG_COLDFIRE */
+
+/*
+ * All other types of m68k parts (68000, 680x0, CPU32) have the same
+ * entry and exit code.
+ */
+
+/*
+ * a -1 in the orig_d0 field signifies
+ * that the stack frame is NOT for syscall
+ */
+.macro SAVE_ALL_INT
+	clrl	%sp@-			/* stk_adj */
+	pea	-1:w			/* orig d0 */
+	movel	%d0,%sp@-		/* d0 */
+	moveml	%d1-%d5/%a0-%a2,%sp@-
+.endm
+
+.macro SAVE_ALL_SYS
+	clrl	%sp@-			/* stk_adj */
+	movel	%d0,%sp@-		/* orig d0 */
+	movel	%d0,%sp@-		/* d0 */
+	moveml	%d1-%d5/%a0-%a2,%sp@-
+.endm
+
+.macro RESTORE_ALL
+	moveml	%sp@+,%a0-%a2/%d1-%d5
+	movel	%sp@+,%d0
+	addql	#4,%sp			/* orig d0 */
+	addl	%sp@+,%sp		/* stk adj */
+	rte
+.endm
+
+
+.macro SAVE_SWITCH_STACK
+	moveml	%a3-%a6/%d6-%d7,%sp@-
+.endm
+
+.macro RESTORE_SWITCH_STACK
+	moveml	%sp@+,%a3-%a6/%d6-%d7
+.endm
+
+#endif /* !CONFIG_COLDFIRE */
+
+/*
+ * Register %a2 is reserved and set to current task on MMU enabled systems.
+ * Non-MMU systems do not reserve %a2 in this way, and this definition is
+ * not used for them.
+ */
+#define curptr a2
+
+#define GET_CURRENT(tmp) get_current tmp
+.macro get_current reg=%d0
+	movel	%sp,\reg
+	andw	#-THREAD_SIZE,\reg
+	movel	\reg,%curptr
+	movel	%curptr@,%curptr
+.endm
+
+#else /* C source */
+
+#define STR(X) STR1(X)
+#define STR1(X) #X
+
+#define SAVE_ALL_INT				\
+	"clrl	%%sp@-;"    /* stk_adj */	\
+	"pea	-1:w;"	    /* orig d0 = -1 */	\
+	"movel	%%d0,%%sp@-;" /* d0 */		\
+	"moveml	%%d1-%%d5/%%a0-%%a2,%%sp@-"
+
+#define GET_CURRENT(tmp) \
+	"movel	%%sp,"#tmp"\n\t" \
+	"andw	#-"STR(THREAD_SIZE)","#tmp"\n\t" \
+	"movel	"#tmp",%%a2\n\t" \
+	"movel	%%a2@,%%a2"
+
 #endif
+
+#endif /* __M68K_ENTRY_H */
diff -druN linux-libre-3.1-gnu/arch/m68k/include/asm/entry_mm.h linux-libre-3.2-gnu/arch/m68k/include/asm/entry_mm.h
--- linux-libre-3.1-gnu/arch/m68k/include/asm/entry_mm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/include/asm/entry_mm.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,128 +0,0 @@
-#ifndef __M68K_ENTRY_H
-#define __M68K_ENTRY_H
-
-#include <asm/setup.h>
-#include <asm/page.h>
-#ifdef __ASSEMBLY__
-#include <asm/thread_info.h>
-#endif
-
-/*
- * Stack layout in 'ret_from_exception':
- *
- *	This allows access to the syscall arguments in registers d1-d5
- *
- *	 0(sp) - d1
- *	 4(sp) - d2
- *	 8(sp) - d3
- *	 C(sp) - d4
- *	10(sp) - d5
- *	14(sp) - a0
- *	18(sp) - a1
- *	1C(sp) - a2
- *	20(sp) - d0
- *	24(sp) - orig_d0
- *	28(sp) - stack adjustment
- *	2C(sp) - sr
- *	2E(sp) - pc
- *	32(sp) - format & vector
- */
-
-/*
- * 97/05/14 Andreas: Register %a2 is now set to the current task throughout
- *		     the whole kernel.
- */
-
-/* the following macro is used when enabling interrupts */
-#if defined(MACH_ATARI_ONLY)
-	/* block out HSYNC on the atari */
-#define ALLOWINT	(~0x400)
-#define	MAX_NOINT_IPL	3
-#else
-	/* portable version */
-#define ALLOWINT	(~0x700)
-#define	MAX_NOINT_IPL	0
-#endif /* machine compilation types */
-
-#ifdef __ASSEMBLY__
-
-#define curptr a2
-
-LFLUSH_I_AND_D = 0x00000808
-
-#define SAVE_ALL_INT save_all_int
-#define SAVE_ALL_SYS save_all_sys
-#define RESTORE_ALL restore_all
-/*
- * This defines the normal kernel pt-regs layout.
- *
- * regs a3-a6 and d6-d7 are preserved by C code
- * the kernel doesn't mess with usp unless it needs to
- */
-
-/*
- * a -1 in the orig_d0 field signifies
- * that the stack frame is NOT for syscall
- */
-.macro	save_all_int
-	clrl	%sp@-		| stk_adj
-	pea	-1:w		| orig d0
-	movel	%d0,%sp@-	| d0
-	moveml	%d1-%d5/%a0-%a1/%curptr,%sp@-
-.endm
-
-.macro	save_all_sys
-	clrl	%sp@-		| stk_adj
-	movel	%d0,%sp@-	| orig d0
-	movel	%d0,%sp@-	| d0
-	moveml	%d1-%d5/%a0-%a1/%curptr,%sp@-
-.endm
-
-.macro	restore_all
-	moveml	%sp@+,%a0-%a1/%curptr/%d1-%d5
-	movel	%sp@+,%d0
-	addql	#4,%sp		| orig d0
-	addl	%sp@+,%sp	| stk adj
-	rte
-.endm
-
-#define SWITCH_STACK_SIZE (6*4+4)	/* includes return address */
-
-#define SAVE_SWITCH_STACK save_switch_stack
-#define RESTORE_SWITCH_STACK restore_switch_stack
-#define GET_CURRENT(tmp) get_current tmp
-
-.macro	save_switch_stack
-	moveml	%a3-%a6/%d6-%d7,%sp@-
-.endm
-
-.macro	restore_switch_stack
-	moveml	%sp@+,%a3-%a6/%d6-%d7
-.endm
-
-.macro	get_current reg=%d0
-	movel	%sp,\reg
-	andw	#-THREAD_SIZE,\reg
-	movel	\reg,%curptr
-	movel	%curptr@,%curptr
-.endm
-
-#else /* C source */
-
-#define STR(X) STR1(X)
-#define STR1(X) #X
-
-#define SAVE_ALL_INT				\
-	"clrl	%%sp@-;"    /* stk_adj */	\
-	"pea	-1:w;"	    /* orig d0 = -1 */	\
-	"movel	%%d0,%%sp@-;" /* d0 */		\
-	"moveml	%%d1-%%d5/%%a0-%%a2,%%sp@-"
-#define GET_CURRENT(tmp) \
-	"movel	%%sp,"#tmp"\n\t" \
-	"andw	#-"STR(THREAD_SIZE)","#tmp"\n\t" \
-	"movel	"#tmp",%%a2\n\t" \
-	"movel	%%a2@,%%a2"
-
-#endif
-
-#endif /* __M68K_ENTRY_H */
diff -druN linux-libre-3.1-gnu/arch/m68k/include/asm/entry_no.h linux-libre-3.2-gnu/arch/m68k/include/asm/entry_no.h
--- linux-libre-3.1-gnu/arch/m68k/include/asm/entry_no.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/include/asm/entry_no.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,181 +0,0 @@
-#ifndef __M68KNOMMU_ENTRY_H
-#define __M68KNOMMU_ENTRY_H
-
-#include <asm/setup.h>
-#include <asm/page.h>
-
-/*
- * Stack layout in 'ret_from_exception':
- *
- * This allows access to the syscall arguments in registers d1-d5
- *
- *	 0(sp) - d1
- *	 4(sp) - d2
- *	 8(sp) - d3
- *	 C(sp) - d4
- *	10(sp) - d5
- *	14(sp) - a0
- *	18(sp) - a1
- *	1C(sp) - a2
- *	20(sp) - d0
- *	24(sp) - orig_d0
- *	28(sp) - stack adjustment
- *	2C(sp) - [ sr              ] [ format & vector ]
- *	2E(sp) - [ pc-hiword       ] [ sr              ]
- *	30(sp) - [ pc-loword       ] [ pc-hiword       ]
- *	32(sp) - [ format & vector ] [ pc-loword       ]
- *		  ^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^
- *			M68K		  COLDFIRE
- */
-
-#define ALLOWINT (~0x700)
-
-#ifdef __ASSEMBLY__
-
-#define SWITCH_STACK_SIZE (6*4+4)	/* Includes return address */
-
-/*
- * This defines the normal kernel pt-regs layout.
- *
- * regs are a2-a6 and d6-d7 preserved by C code
- * the kernel doesn't mess with usp unless it needs to
- */
-
-#ifdef CONFIG_COLDFIRE
-#ifdef CONFIG_COLDFIRE_SW_A7
-/*
- * This is made a little more tricky on older ColdFires. There is no
- * separate supervisor and user stack pointers. Need to artificially
- * construct a usp in software... When doing this we need to disable
- * interrupts, otherwise bad things will happen.
- */
-.globl sw_usp
-.globl sw_ksp
-
-.macro SAVE_ALL
-	move	#0x2700,%sr		/* disable intrs */
-	btst	#5,%sp@(2)		/* from user? */
-	bnes	6f			/* no, skip */
-	movel	%sp,sw_usp		/* save user sp */
-	addql	#8,sw_usp		/* remove exception */
-	movel	sw_ksp,%sp		/* kernel sp */
-	subql	#8,%sp			/* room for exception */
-	clrl	%sp@-			/* stkadj */
-	movel	%d0,%sp@-		/* orig d0 */
-	movel	%d0,%sp@-		/* d0 */
-	lea	%sp@(-32),%sp		/* space for 8 regs */
-	moveml	%d1-%d5/%a0-%a2,%sp@
-	movel	sw_usp,%a0		/* get usp */
-	movel	%a0@-,%sp@(PT_OFF_PC)	/* copy exception program counter */
-	movel	%a0@-,%sp@(PT_OFF_FORMATVEC)/*copy exception format/vector/sr */
-	bra	7f
-	6:
-	clrl	%sp@-			/* stkadj */
-	movel	%d0,%sp@-		/* orig d0 */
-	movel	%d0,%sp@-		/* d0 */
-	lea	%sp@(-32),%sp		/* space for 8 regs */
-	moveml	%d1-%d5/%a0-%a2,%sp@
-	7:
-.endm
-
-.macro RESTORE_USER
-	move	#0x2700,%sr		/* disable intrs */
-	movel	sw_usp,%a0		/* get usp */
-	movel	%sp@(PT_OFF_PC),%a0@-	/* copy exception program counter */
-	movel	%sp@(PT_OFF_FORMATVEC),%a0@-/*copy exception format/vector/sr */
-	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		/* stkadj */
-	addql	#8,%sp			/* remove exception */
-	movel	%sp,sw_ksp		/* save ksp */
-	subql	#8,sw_usp		/* set exception */
-	movel	sw_usp,%sp		/* restore usp */
-	rte
-.endm
-
-.macro RDUSP
-	movel	sw_usp,%a3
-.endm
-
-.macro WRUSP
-	movel	%a3,sw_usp
-.endm
-
-#else /* !CONFIG_COLDFIRE_SW_A7 */
-/*
- * Modern ColdFire parts have separate supervisor and user stack
- * pointers. Simple load and restore macros for this case.
- */
-.macro SAVE_ALL
-	move	#0x2700,%sr		/* disable intrs */
-	clrl	%sp@-			/* stkadj */
-	movel	%d0,%sp@-		/* orig d0 */
-	movel	%d0,%sp@-		/* d0 */
-	lea	%sp@(-32),%sp		/* space for 8 regs */
-	moveml	%d1-%d5/%a0-%a2,%sp@
-.endm
-
-.macro RESTORE_USER
-	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		/* stkadj */
-	rte
-.endm
-
-.macro RDUSP
-	/*move	%usp,%a3*/
-	.word	0x4e6b
-.endm
-
-.macro WRUSP
-	/*move	%a3,%usp*/
-	.word	0x4e63
-.endm
-
-#endif /* !CONFIG_COLDFIRE_SW_A7 */
-
-.macro SAVE_SWITCH_STACK
-	lea	%sp@(-24),%sp		/* 6 regs */
-	moveml	%a3-%a6/%d6-%d7,%sp@
-.endm
-
-.macro RESTORE_SWITCH_STACK
-	moveml	%sp@,%a3-%a6/%d6-%d7
-	lea	%sp@(24),%sp		/* 6 regs */
-.endm
-
-#else /* !CONFIG_COLDFIRE */
-
-/*
- * Standard 68k interrupt entry and exit macros.
- */
-.macro SAVE_ALL
-	clrl	%sp@-			/* stkadj */
-	movel	%d0,%sp@-		/* orig d0 */
-	movel	%d0,%sp@-		/* d0 */
-	moveml	%d1-%d5/%a0-%a2,%sp@-
-.endm
-
-.macro RESTORE_ALL
-	moveml	%sp@+,%a0-%a2/%d1-%d5
-	movel	%sp@+,%d0
-	addql	#4,%sp			/* orig d0 */
-	addl	%sp@+,%sp		/* stkadj */
-	rte
-.endm
-
-.macro SAVE_SWITCH_STACK
-	moveml	%a3-%a6/%d6-%d7,%sp@-
-.endm
-
-.macro RESTORE_SWITCH_STACK
-	moveml	%sp@+,%a3-%a6/%d6-%d7
-.endm
-
-#endif /* !COLDFIRE_SW_A7 */
-#endif /* __ASSEMBLY__ */
-#endif /* __M68KNOMMU_ENTRY_H */
diff -druN linux-libre-3.1-gnu/arch/m68k/include/asm/hardirq.h linux-libre-3.2-gnu/arch/m68k/include/asm/hardirq.h
--- linux-libre-3.1-gnu/arch/m68k/include/asm/hardirq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/include/asm/hardirq.h	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,11 @@
 
 #ifdef CONFIG_MMU
 
+static inline void ack_bad_irq(unsigned int irq)
+{
+	pr_crit("unexpected IRQ trap at vector %02x\n", irq);
+}
+
 /* entry.S is sensitive to the offsets of these fields */
 typedef struct {
 	unsigned int __softirq_pending;
diff -druN linux-libre-3.1-gnu/arch/m68k/include/asm/irq.h linux-libre-3.2-gnu/arch/m68k/include/asm/irq.h
--- linux-libre-3.1-gnu/arch/m68k/include/asm/irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/include/asm/irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -27,11 +27,6 @@
 
 #ifdef CONFIG_MMU
 
-#include <linux/linkage.h>
-#include <linux/hardirq.h>
-#include <linux/irqreturn.h>
-#include <linux/spinlock_types.h>
-
 /*
  * Interrupt source definitions
  * General interrupt sources are the level 1-7.
@@ -54,10 +49,6 @@
 
 #define IRQ_USER	8
 
-extern unsigned int irq_canonicalize(unsigned int irq);
-
-struct pt_regs;
-
 /*
  * various flags for request_irq() - the Amiga now uses the standard
  * mechanism like all other architectures - IRQF_DISABLED and
@@ -71,57 +62,27 @@
 #define IRQ_FLG_STD	(0x8000)	/* internally used		*/
 #endif
 
-/*
- * This structure is used to chain together the ISRs for a particular
- * interrupt source (if it supports chaining).
- */
-typedef struct irq_node {
-	irqreturn_t	(*handler)(int, void *);
-	void		*dev_id;
-	struct irq_node *next;
-	unsigned long	flags;
-	const char	*devname;
-} irq_node_t;
-
-/*
- * This structure has only 4 elements for speed reasons
- */
-struct irq_handler {
-	int		(*handler)(int, void *);
-	unsigned long	flags;
-	void		*dev_id;
-	const char	*devname;
-};
-
-struct irq_controller {
-	const char *name;
-	spinlock_t lock;
-	int (*startup)(unsigned int irq);
-	void (*shutdown)(unsigned int irq);
-	void (*enable)(unsigned int irq);
-	void (*disable)(unsigned int irq);
-};
-
-extern int m68k_irq_startup(unsigned int);
-extern void m68k_irq_shutdown(unsigned int);
-
-/*
- * This function returns a new irq_node_t
- */
-extern irq_node_t *new_irq_node(void);
-
-extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *));
-extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
-				      void (*handler)(unsigned int, struct pt_regs *));
-extern void m68k_setup_irq_controller(struct irq_controller *, unsigned int, unsigned int);
+struct irq_data;
+struct irq_chip;
+struct irq_desc;
+extern unsigned int m68k_irq_startup(struct irq_data *data);
+extern unsigned int m68k_irq_startup_irq(unsigned int irq);
+extern void m68k_irq_shutdown(struct irq_data *data);
+extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int,
+						      struct pt_regs *));
+extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt);
+extern void m68k_setup_irq_controller(struct irq_chip *,
+				      void (*handle)(unsigned int irq,
+						     struct irq_desc *desc),
+				      unsigned int irq, unsigned int cnt);
 
-asmlinkage void m68k_handle_int(unsigned int);
-asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *);
+extern unsigned int irq_canonicalize(unsigned int irq);
 
 #else
 #define irq_canonicalize(irq)  (irq)
 #endif /* CONFIG_MMU */
 
 asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
+extern atomic_t irq_err_count;
 
 #endif /* _M68K_IRQ_H_ */
diff -druN linux-libre-3.1-gnu/arch/m68k/include/asm/m520xsim.h linux-libre-3.2-gnu/arch/m68k/include/asm/m520xsim.h
--- linux-libre-3.1-gnu/arch/m68k/include/asm/m520xsim.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/include/asm/m520xsim.h	2012-01-04 18:55:44.000000000 -0500
@@ -90,15 +90,13 @@
 #define MCFGPIO_PDDR_FECH		0xFC0A4013
 #define MCFGPIO_PDDR_FECL		0xFC0A4014
 
-#define MCFGPIO_PPDSDR_BUSCTL		0xFC0A401A
-#define MCFGPIO_PPDSDR_BE		0xFC0A401B
-#define MCFGPIO_PPDSDR_CS		0xFC0A401C
-#define MCFGPIO_PPDSDR_FECI2C		0xFC0A401D
-#define MCFGPIO_PPDSDR_QSPI		0xFC0A401E
-#define MCFGPIO_PPDSDR_TIMER		0xFC0A401F
-#define MCFGPIO_PPDSDR_UART		0xFC0A4021
-#define MCFGPIO_PPDSDR_FECH		0xFC0A4021
-#define MCFGPIO_PPDSDR_FECL		0xFC0A4022
+#define MCFGPIO_PPDSDR_CS		0xFC0A401A
+#define MCFGPIO_PPDSDR_FECI2C		0xFC0A401B
+#define MCFGPIO_PPDSDR_QSPI		0xFC0A401C
+#define MCFGPIO_PPDSDR_TIMER		0xFC0A401D
+#define MCFGPIO_PPDSDR_UART		0xFC0A401E
+#define MCFGPIO_PPDSDR_FECH		0xFC0A401F
+#define MCFGPIO_PPDSDR_FECL		0xFC0A4020
 
 #define MCFGPIO_PCLRR_BUSCTL		0xFC0A4024
 #define MCFGPIO_PCLRR_BE		0xFC0A4025
@@ -113,11 +111,11 @@
 /*
  * Generic GPIO support
  */
-#define MCFGPIO_PODR			MCFGPIO_PODR_BUSCTL
-#define MCFGPIO_PDDR			MCFGPIO_PDDR_BUSCTL
-#define MCFGPIO_PPDR			MCFGPIO_PPDSDR_BUSCTL
-#define MCFGPIO_SETR			MCFGPIO_PPDSDR_BUSCTL
-#define MCFGPIO_CLRR			MCFGPIO_PCLRR_BUSCTL
+#define MCFGPIO_PODR			MCFGPIO_PODR_CS
+#define MCFGPIO_PDDR			MCFGPIO_PDDR_CS
+#define MCFGPIO_PPDR			MCFGPIO_PPDSDR_CS
+#define MCFGPIO_SETR			MCFGPIO_PPDSDR_CS
+#define MCFGPIO_CLRR			MCFGPIO_PCLRR_CS
 
 #define MCFGPIO_PIN_MAX			80
 #define MCFGPIO_IRQ_MAX			8
diff -druN linux-libre-3.1-gnu/arch/m68k/include/asm/macintosh.h linux-libre-3.2-gnu/arch/m68k/include/asm/macintosh.h
--- linux-libre-3.1-gnu/arch/m68k/include/asm/macintosh.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/include/asm/macintosh.h	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,8 @@
 extern void mac_poweroff(void);
 extern void mac_init_IRQ(void);
 extern int mac_irq_pending(unsigned int);
+extern void mac_irq_enable(struct irq_data *data);
+extern void mac_irq_disable(struct irq_data *data);
 
 /*
  *	Floppy driver magic hook - probably shouldn't be here
diff -druN linux-libre-3.1-gnu/arch/m68k/include/asm/mcfqspi.h linux-libre-3.2-gnu/arch/m68k/include/asm/mcfqspi.h
--- linux-libre-3.1-gnu/arch/m68k/include/asm/mcfqspi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/include/asm/mcfqspi.h	2012-01-04 18:55:44.000000000 -0500
@@ -24,9 +24,11 @@
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 #define	MCFQSPI_IOBASE		(MCF_IPSBAR + 0x340)
 #elif defined(CONFIG_M5249)
-#define MCFQSPI_IOBASE		(MCF_MBAR + 0x300)
-#elif defined(CONFIG_M520x) || defined(CONFIG_M532x)
-#define MCFQSPI_IOBASE		0xFC058000
+#define MCFQSPI_IOBASE         (MCF_MBAR + 0x300)
+#elif defined(CONFIG_M520x)
+#define MCFQSPI_IOBASE         0xFC05C000
+#elif defined(CONFIG_M532x)
+#define MCFQSPI_IOBASE         0xFC058000
 #endif
 #define MCFQSPI_IOSIZE		0x40
 
diff -druN linux-libre-3.1-gnu/arch/m68k/include/asm/page_no.h linux-libre-3.2-gnu/arch/m68k/include/asm/page_no.h
--- linux-libre-3.1-gnu/arch/m68k/include/asm/page_no.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/include/asm/page_no.h	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,9 @@
  
 extern unsigned long memory_start;
 extern unsigned long memory_end;
+extern unsigned long _rambase;
+extern unsigned long _ramstart;
+extern unsigned long _ramend;
 
 #define get_user_page(vaddr)		__get_free_page(GFP_KERNEL)
 #define free_user_page(page, addr)	free_page(addr)
diff -druN linux-libre-3.1-gnu/arch/m68k/include/asm/processor.h linux-libre-3.2-gnu/arch/m68k/include/asm/processor.h
--- linux-libre-3.1-gnu/arch/m68k/include/asm/processor.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/include/asm/processor.h	2012-01-04 18:55:44.000000000 -0500
@@ -135,6 +135,12 @@
 	wrusp(_usp);                                    \
 } while(0)
 
+static inline  int handle_kernel_fault(struct pt_regs *regs)
+{
+	/* Any fault in kernel is fatal on non-mmu */
+	return 0;
+}
+
 #endif
 
 /* Forward declaration, a strange C thing */
diff -druN linux-libre-3.1-gnu/arch/m68k/include/asm/q40ints.h linux-libre-3.2-gnu/arch/m68k/include/asm/q40ints.h
--- linux-libre-3.1-gnu/arch/m68k/include/asm/q40ints.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/include/asm/q40ints.h	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,3 @@
 #define Q40_IRQ10_MASK       (1<<5)
 #define Q40_IRQ14_MASK       (1<<6)
 #define Q40_IRQ15_MASK       (1<<7)
-
-extern unsigned long q40_probe_irq_on (void);
-extern int q40_probe_irq_off (unsigned long irqs);
diff -druN linux-libre-3.1-gnu/arch/m68k/include/asm/sections.h linux-libre-3.2-gnu/arch/m68k/include/asm/sections.h
--- linux-libre-3.1-gnu/arch/m68k/include/asm/sections.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/include/asm/sections.h	2012-01-04 18:55:44.000000000 -0500
@@ -3,4 +3,6 @@
 
 #include <asm-generic/sections.h>
 
+extern char _sbss[], _ebss[];
+
 #endif /* _ASM_M68K_SECTIONS_H */
diff -druN linux-libre-3.1-gnu/arch/m68k/include/asm/unistd.h linux-libre-3.2-gnu/arch/m68k/include/asm/unistd.h
--- linux-libre-3.1-gnu/arch/m68k/include/asm/unistd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -350,10 +350,12 @@
 #define __NR_clock_adjtime	342
 #define __NR_syncfs		343
 #define __NR_setns		344
+#define __NR_process_vm_readv	345
+#define __NR_process_vm_writev	346
 
 #ifdef __KERNEL__
 
-#define NR_syscalls		345
+#define NR_syscalls		347
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff -druN linux-libre-3.1-gnu/arch/m68k/Kconfig linux-libre-3.2-gnu/arch/m68k/Kconfig
--- linux-libre-3.1-gnu/arch/m68k/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -4,8 +4,8 @@
 	select HAVE_IDE
 	select HAVE_AOUT if MMU
 	select GENERIC_ATOMIC64 if MMU
-	select HAVE_GENERIC_HARDIRQS if !MMU
-	select GENERIC_IRQ_SHOW if !MMU
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_IRQ_SHOW
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS
 
 config RWSEM_GENERIC_SPINLOCK
@@ -21,6 +21,15 @@
 config ARCH_HAS_ILOG2_U64
 	bool
 
+config GENERIC_CLOCKEVENTS
+	bool
+
+config GENERIC_CMOS_UPDATE
+	def_bool !MMU
+
+config GENERIC_GPIO
+	bool
+
 config GENERIC_HWEIGHT
 	bool
 	default y
@@ -29,10 +38,16 @@
 	bool
 	default y
 
+config GENERIC_IOMAP
+	def_bool MMU
+
 config TIME_LOW_RES
 	bool
 	default y
 
+config ARCH_USES_GETTIMEOFFSET
+	def_bool MMU
+
 config NO_IOPORT
 	def_bool y
 
@@ -62,13 +77,31 @@
 	  Select if you want MMU-based virtualised addressing space
 	  support by paged memory management. If unsure, say 'Y'.
 
-menu "Platform dependent setup"
+config MMU_MOTOROLA
+	bool
 
-if MMU
-source arch/m68k/Kconfig.mmu
+config MMU_SUN3
+	bool
+	depends on MMU && !MMU_MOTOROLA
+
+menu "Platform setup"
+
+source arch/m68k/Kconfig.cpu
+
+source arch/m68k/Kconfig.machine
+
+source arch/m68k/Kconfig.bus
+
+endmenu
+
+menu "Kernel Features"
+
+if COLDFIRE
+source "kernel/Kconfig.preempt"
 endif
-if !MMU
-source arch/m68k/Kconfig.nommu
+
+if !MMU || COLDFIRE
+source "kernel/time/Kconfig"
 endif
 
 source "mm/Kconfig"
@@ -85,9 +118,9 @@
 menu "Power management options"
 
 config PM
-        bool "Power Management support"
-        help
-          Support processor power management modes
+	bool "Power Management support"
+	help
+	  Support processor power management modes
 
 endmenu
 endif
@@ -96,151 +129,7 @@
 
 source "drivers/Kconfig"
 
-if MMU
-
-menu "Character devices"
-
-config ATARI_MFPSER
-	tristate "Atari MFP serial support"
-	depends on ATARI
-	---help---
-	  If you like to use the MFP serial ports ("Modem1", "Serial1") under
-	  Linux, say Y. The driver equally supports all kinds of MFP serial
-	  ports and automatically detects whether Serial1 is available.
-
-	  To compile this driver as a module, choose M here.
-
-	  Note for Falcon users: You also have an MFP port, it's just not
-	  wired to the outside... But you could use the port under Linux.
-
-config ATARI_MIDI
-	tristate "Atari MIDI serial support"
-	depends on ATARI
-	help
-	  If you want to use your Atari's MIDI port in Linux, say Y.
-
-	  To compile this driver as a module, choose M here.
-
-config ATARI_DSP56K
-	tristate "Atari DSP56k support (EXPERIMENTAL)"
-	depends on ATARI && EXPERIMENTAL
-	help
-	  If you want to be able to use the DSP56001 in Falcons, say Y. This
-	  driver is still experimental, and if you don't know what it is, or
-	  if you don't have this processor, just say N.
-
-	  To compile this driver as a module, choose M here.
-
-config AMIGA_BUILTIN_SERIAL
-	tristate "Amiga builtin serial support"
-	depends on AMIGA
-	help
-	  If you want to use your Amiga's built-in serial port in Linux,
-	  answer Y.
-
-	  To compile this driver as a module, choose M here.
-
-config MULTIFACE_III_TTY
-	tristate "Multiface Card III serial support"
-	depends on AMIGA
-	help
-	  If you want to use a Multiface III card's serial port in Linux,
-	  answer Y.
-
-	  To compile this driver as a module, choose M here.
-
-config GVPIOEXT
-	tristate "GVP IO-Extender support"
-	depends on PARPORT=n && ZORRO
-	help
-	  If you want to use a GVP IO-Extender serial card in Linux, say Y.
-	  Otherwise, say N.
-
-config GVPIOEXT_LP
-	tristate "GVP IO-Extender parallel printer support"
-	depends on GVPIOEXT
-	help
-	  Say Y to enable driving a printer from the parallel port on your
-	  GVP IO-Extender card, N otherwise.
-
-config GVPIOEXT_PLIP
-	tristate "GVP IO-Extender PLIP support"
-	depends on GVPIOEXT
-	help
-	  Say Y to enable doing IP over the parallel port on your GVP
-	  IO-Extender card, N otherwise.
-
-config MAC_HID
-	bool
-	depends on INPUT_ADBHID
-	default y
-
-config HPDCA
-	tristate "HP DCA serial support"
-	depends on DIO && SERIAL_8250
-	help
-	  If you want to use the internal "DCA" serial ports on an HP300
-	  machine, say Y here.
-
-config HPAPCI
-	tristate "HP APCI serial support"
-	depends on HP300 && SERIAL_8250 && EXPERIMENTAL
-	help
-	  If you want to use the internal "APCI" serial ports on an HP400
-	  machine, say Y here.
-
-config MVME147_SCC
-	bool "SCC support for MVME147 serial ports"
-	depends on MVME147 && BROKEN
-	help
-	  This is the driver for the serial ports on the Motorola MVME147
-	  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
-	help
-	  This is the driver for the serial ports on the Motorola MVME162 and
-	  172 boards.  Everyone using one of these boards should say Y here.
-
-config BVME6000_SCC
-	bool "SCC support for BVME6000 serial ports"
-	depends on BVME6000 && BROKEN
-	help
-	  This is the driver for the serial ports on the BVME4000 and BVME6000
-	  boards from BVM Ltd.  Everyone using one of these boards should say
-	  Y here.
-
-config DN_SERIAL
-	bool "Support for DN serial port (dummy)"
-	depends on APOLLO
-
-config SERIAL_CONSOLE
-	bool "Support for serial port console"
-	depends on (AMIGA || ATARI || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_MIDI=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL)
-	---help---
-	  If you say Y here, it will be possible to use a serial port as the
-	  system console (the system console is the device which receives all
-	  kernel messages and warnings and which allows logins in single user
-	  mode). This could be useful if some terminal or printer is connected
-	  to that serial port.
-
-	  Even if you say Y here, the currently visible virtual console
-	  (/dev/tty0) will still be used as the system console by default, but
-	  you can alter that using a kernel command line option such as
-	  "console=ttyS1". (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 you don't have a VGA card installed and you say Y here, the
-	  kernel will automatically use the first serial line, /dev/ttyS0, as
-	  system console.
-
-	  If unsure, say N.
-
-endmenu
-
-endif
+source "arch/m68k/Kconfig.devices"
 
 source "fs/Kconfig"
 
diff -druN linux-libre-3.1-gnu/arch/m68k/Kconfig.bus linux-libre-3.2-gnu/arch/m68k/Kconfig.bus
--- linux-libre-3.1-gnu/arch/m68k/Kconfig.bus	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/m68k/Kconfig.bus	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,64 @@
+if MMU
+
+comment "Bus Support"
+
+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 NUBUS
+	bool
+	depends on MAC
+	default y
+
+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 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
+	def_bool ISA
+
+source "drivers/pci/Kconfig"
+
+source "drivers/zorro/Kconfig"
+
+endif
+
+if !MMU
+
+config ISA_DMA_API
+        def_bool !M5272
+
+source "drivers/pcmcia/Kconfig"
+
+endif
diff -druN linux-libre-3.1-gnu/arch/m68k/Kconfig.cpu linux-libre-3.2-gnu/arch/m68k/Kconfig.cpu
--- linux-libre-3.1-gnu/arch/m68k/Kconfig.cpu	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/m68k/Kconfig.cpu	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,429 @@
+comment "Processor Type"
+
+config M68000
+	bool
+	select CPU_HAS_NO_BITFIELDS
+	help
+	  The Freescale (was Motorola) 68000 CPU is the first generation of
+	  the well known M68K family of processors. The CPU core as well as
+	  being available as a stand alone CPU was also used in many
+	  System-On-Chip devices (eg 68328, 68302, etc). It does not contain
+	  a paging MMU.
+
+config MCPU32
+	bool
+	select CPU_HAS_NO_BITFIELDS
+	help
+	  The Freescale (was then Motorola) CPU32 is a CPU core that is
+	  based on the 68020 processor. For the most part it is used in
+	  System-On-Chip parts, and does not contain a paging MMU.
+
+config COLDFIRE
+	bool
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select CPU_HAS_NO_BITFIELDS
+	help
+	  The Freescale ColdFire family of processors is a modern derivitive
+	  of the 68000 processor family. They are mainly targeted at embedded
+	  applications, and are all System-On-Chip (SOC) devices, as opposed
+	  to stand alone CPUs. They implement a subset of the original 68000
+	  processor instruction set.
+
+config M68020
+	bool "68020 support"
+	depends on MMU
+	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 && !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 && !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 && !MMU_SUN3
+	help
+	  If you anticipate running this kernel on a computer with a MC68060
+	  processor, say Y. Otherwise, say N.
+
+config M68328
+	bool "MC68328"
+	depends on !MMU
+	select M68000
+	help
+	  Motorola 68328 processor support.
+
+config M68EZ328
+	bool "MC68EZ328"
+	depends on !MMU
+	select M68000
+	help
+	  Motorola 68EX328 processor support.
+
+config M68VZ328
+	bool "MC68VZ328"
+	depends on !MMU
+	select M68000
+	help
+	  Motorola 68VZ328 processor support.
+
+config M68360
+	bool "MC68360"
+	depends on !MMU
+	select MCPU32
+	help
+	  Motorola 68360 processor support.
+
+config M5206
+	bool "MCF5206"
+	depends on !MMU
+	select COLDFIRE
+	select COLDFIRE_SW_A7
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5206 processor support.
+
+config M5206e
+	bool "MCF5206e"
+	depends on !MMU
+	select COLDFIRE
+	select COLDFIRE_SW_A7
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5206e processor support.
+
+config M520x
+	bool "MCF520x"
+	depends on !MMU
+	select COLDFIRE
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CACHE_SPLIT
+	help
+	   Freescale Coldfire 5207/5208 processor support.
+
+config M523x
+	bool "MCF523x"
+	depends on !MMU
+	select COLDFIRE
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CACHE_SPLIT
+	select HAVE_IPSBAR
+	help
+	  Freescale Coldfire 5230/1/2/4/5 processor support
+
+config M5249
+	bool "MCF5249"
+	depends on !MMU
+	select COLDFIRE
+	select COLDFIRE_SW_A7
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5249 processor support.
+
+config M527x
+	bool
+
+config M5271
+	bool "MCF5271"
+	depends on !MMU
+	select COLDFIRE
+	select M527x
+	select HAVE_CACHE_SPLIT
+	select HAVE_IPSBAR
+	select GENERIC_CLOCKEVENTS
+	help
+	  Freescale (Motorola) ColdFire 5270/5271 processor support.
+
+config M5272
+	bool "MCF5272"
+	depends on !MMU
+	select COLDFIRE
+	select COLDFIRE_SW_A7
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5272 processor support.
+
+config M5275
+	bool "MCF5275"
+	depends on !MMU
+	select COLDFIRE
+	select M527x
+	select HAVE_CACHE_SPLIT
+	select HAVE_IPSBAR
+	select GENERIC_CLOCKEVENTS
+	help
+	  Freescale (Motorola) ColdFire 5274/5275 processor support.
+
+config M528x
+	bool "MCF528x"
+	depends on !MMU
+	select COLDFIRE
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CACHE_SPLIT
+	select HAVE_IPSBAR
+	help
+	  Motorola ColdFire 5280/5282 processor support.
+
+config M5307
+	bool "MCF5307"
+	depends on !MMU
+	select COLDFIRE
+	select COLDFIRE_SW_A7
+	select HAVE_CACHE_CB
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5307 processor support.
+
+config M532x
+	bool "MCF532x"
+	depends on !MMU
+	select COLDFIRE
+	select HAVE_CACHE_CB
+	help
+	  Freescale (Motorola) ColdFire 532x processor support.
+
+config M5407
+	bool "MCF5407"
+	depends on !MMU
+	select COLDFIRE
+	select COLDFIRE_SW_A7
+	select HAVE_CACHE_CB
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5407 processor support.
+
+config M54xx
+	bool
+
+config M547x
+	bool "MCF547x"
+	depends on !MMU
+	select COLDFIRE
+	select M54xx
+	select HAVE_CACHE_CB
+	select HAVE_MBAR
+	help
+	  Freescale ColdFire 5470/5471/5472/5473/5474/5475 processor support.
+
+config M548x
+	bool "MCF548x"
+	depends on !MMU
+	select COLDFIRE
+	select M54xx
+	select HAVE_CACHE_CB
+	select HAVE_MBAR
+	help
+	  Freescale ColdFire 5480/5481/5482/5483/5484/5485 processor support.
+
+
+comment "Processor Specific Options"
+
+config M68KFPU_EMU
+	bool "Math emulation support (EXPERIMENTAL)"
+	depends on MMU
+	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"
+	depends on MMU
+	---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
+	depends on MMU
+	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 ARCH_DISCONTIGMEM_ENABLE
+	def_bool MMU && !SINGLE_MEMORY_CHUNK
+
+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 M68K_L2_CACHE
+	bool
+	depends on MAC
+	default y
+
+config NODES_SHIFT
+	int
+	default "3"
+	depends on !SINGLE_MEMORY_CHUNK
+
+config FPU
+	bool
+
+config COLDFIRE_SW_A7
+	bool
+
+config HAVE_CACHE_SPLIT
+	bool
+
+config HAVE_CACHE_CB
+	bool
+
+config HAVE_MBAR
+	bool
+
+config HAVE_IPSBAR
+	bool
+
+config CLOCK_SET
+	bool "Enable setting the CPU clock frequency"
+	depends on COLDFIRE
+	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
+
diff -druN linux-libre-3.1-gnu/arch/m68k/Kconfig.devices linux-libre-3.2-gnu/arch/m68k/Kconfig.devices
--- linux-libre-3.1-gnu/arch/m68k/Kconfig.devices	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/m68k/Kconfig.devices	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,154 @@
+if MMU
+
+config ARCH_MAY_HAVE_PC_FDC
+	bool
+	depends on BROKEN && (Q40 || SUN3X)
+	default y
+
+menu "Platform devices"
+
+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 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 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.
+
+endmenu
+
+menu "Character devices"
+
+config ATARI_MFPSER
+	tristate "Atari MFP serial support"
+	depends on ATARI
+	---help---
+	  If you like to use the MFP serial ports ("Modem1", "Serial1") under
+	  Linux, say Y. The driver equally supports all kinds of MFP serial
+	  ports and automatically detects whether Serial1 is available.
+
+	  To compile this driver as a module, choose M here.
+
+	  Note for Falcon users: You also have an MFP port, it's just not
+	  wired to the outside... But you could use the port under Linux.
+
+config ATARI_MIDI
+	tristate "Atari MIDI serial support"
+	depends on ATARI
+	help
+	  If you want to use your Atari's MIDI port in Linux, say Y.
+
+	  To compile this driver as a module, choose M here.
+
+config ATARI_DSP56K
+	tristate "Atari DSP56k support (EXPERIMENTAL)"
+	depends on ATARI && EXPERIMENTAL
+	help
+	  If you want to be able to use the DSP56001 in Falcons, say Y. This
+	  driver is still experimental, and if you don't know what it is, or
+	  if you don't have this processor, just say N.
+
+	  To compile this driver as a module, choose M here.
+
+config AMIGA_BUILTIN_SERIAL
+	tristate "Amiga builtin serial support"
+	depends on AMIGA
+	help
+	  If you want to use your Amiga's built-in serial port in Linux,
+	  answer Y.
+
+	  To compile this driver as a module, choose M here.
+
+config MULTIFACE_III_TTY
+	tristate "Multiface Card III serial support"
+	depends on AMIGA
+	help
+	  If you want to use a Multiface III card's serial port in Linux,
+	  answer Y.
+
+	  To compile this driver as a module, choose M here.
+
+config HPDCA
+	tristate "HP DCA serial support"
+	depends on DIO && SERIAL_8250
+	help
+	  If you want to use the internal "DCA" serial ports on an HP300
+	  machine, say Y here.
+
+config HPAPCI
+	tristate "HP APCI serial support"
+	depends on HP300 && SERIAL_8250 && EXPERIMENTAL
+	help
+	  If you want to use the internal "APCI" serial ports on an HP400
+	  machine, say Y here.
+
+config DN_SERIAL
+	bool "Support for DN serial port (dummy)"
+	depends on APOLLO
+
+config SERIAL_CONSOLE
+	bool "Support for serial port console"
+	depends on (AMIGA || ATARI || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_MIDI=y || AMIGA_BUILTIN_SERIAL=y || MULTIFACE_III_TTY=y || SERIAL=y || SERIAL167 || DN_SERIAL)
+	---help---
+	  If you say Y here, it will be possible to use a serial port as the
+	  system console (the system console is the device which receives all
+	  kernel messages and warnings and which allows logins in single user
+	  mode). This could be useful if some terminal or printer is connected
+	  to that serial port.
+
+	  Even if you say Y here, the currently visible virtual console
+	  (/dev/tty0) will still be used as the system console by default, but
+	  you can alter that using a kernel command line option such as
+	  "console=ttyS1". (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 you don't have a VGA card installed and you say Y here, the
+	  kernel will automatically use the first serial line, /dev/ttyS0, as
+	  system console.
+
+	  If unsure, say N.
+
+endmenu
+
+endif
diff -druN linux-libre-3.1-gnu/arch/m68k/Kconfig.machine linux-libre-3.2-gnu/arch/m68k/Kconfig.machine
--- linux-libre-3.1-gnu/arch/m68k/Kconfig.machine	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/m68k/Kconfig.machine	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,583 @@
+comment "Machine Types"
+
+config AMIGA
+	bool "Amiga support"
+	depends on MMU
+	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"
+	depends on MMU
+	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"
+	depends on MMU
+	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 APOLLO
+	bool "Apollo support"
+	depends on MMU
+	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"
+	depends on MMU
+	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 MMU
+	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 MMU
+	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 MMU
+	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"
+	depends on MMU
+	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 SUN3X
+	bool "Sun3x support"
+	depends on MMU
+	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"
+	depends on MMU
+	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
+	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 PILOT
+	bool
+
+config PILOT3
+	bool "Pilot 1000/5000, PalmPilot Personal/Pro, or PalmIII support"
+	depends on M68328
+	select PILOT
+	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 ARNEWSH
+	bool
+
+config ARN5206
+	bool "Arnewsh 5206 board support"
+	depends on M5206
+	select ARNEWSH
+	help
+	  Support for the Arnewsh 5206 board.
+
+config FREESCALE
+	bool
+
+config M5206eC3
+	bool "Motorola M5206eC3 board support"
+	depends on M5206e
+	select FREESCALE
+	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
+	select FREESCALE
+	help
+	  Support for the Freescale Coldfire M5208EVB.
+
+config M5235EVB
+	bool "Freescale M5235EVB support"
+	depends on M523x
+	select FREESCALE
+	help
+	  Support for the Freescale M5235EVB board.
+
+config M5249C3
+	bool "Motorola M5249C3 board support"
+	depends on M5249
+	select FREESCALE
+	help
+	  Support for the Motorola M5249C3 board.
+
+config M5271EVB
+	bool "Freescale (Motorola) M5271EVB board support"
+	depends on M5271
+	select FREESCALE
+	help
+	  Support for the Freescale (Motorola) M5271EVB board.
+
+config M5275EVB
+	bool "Freescale (Motorola) M5275EVB board support"
+	depends on M5275
+	select FREESCALE
+	help
+	  Support for the Freescale (Motorola) M5275EVB board.
+
+config M5272C3
+	bool "Motorola M5272C3 board support"
+	depends on M5272
+	select FREESCALE
+	help
+	  Support for the Motorola M5272C3 board.
+
+config senTec
+	bool
+
+config COBRA5272
+	bool "senTec COBRA5272 board support"
+	depends on M5272
+	select senTec
+	help
+	  Support for the senTec COBRA5272 board.
+
+config AVNET
+	bool
+
+config AVNET5282
+	bool "Avnet 5282 board support"
+	depends on M528x
+	select AVNET
+	help
+	  Support for the Avnet 5282 board.
+
+config M5282EVB
+	bool "Motorola M5282EVB board support"
+	depends on M528x
+	select FREESCALE
+	help
+	  Support for the Motorola M5282EVB board.
+
+config COBRA5282
+	bool "senTec COBRA5282 board support"
+	depends on M528x
+	select senTec
+	help
+	  Support for the senTec COBRA5282 board.
+
+config SOM5282EM
+	bool "EMAC.Inc SOM5282EM board support"
+	depends on M528x
+	select EMAC_INC
+	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
+	select ARNEWSH
+	help
+	  Support for the Arnewsh 5307 board.
+
+config M5307C3
+	bool "Motorola M5307C3 board support"
+	depends on M5307
+	select FREESCALE
+	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
+	select FREESCALE
+	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
+	select FREESCALE
+	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 SNEHA
+	bool
+
+config CPU16B
+	bool "Sneha Technologies S.L. Sarasvati board support"
+	depends on M5272
+	select SNEHA
+	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 SAVANT
+	bool
+
+config SAVANTrosie1
+	bool "Savant Rosie1 board support"
+	depends on M523x
+	select SAVANT
+	help
+	  Support for the Savant Rosie1 board.
+
+
+if !MMU || COLDFIRE
+
+comment "Machine Options"
+
+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.
+
+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
+
+endif
diff -druN linux-libre-3.1-gnu/arch/m68k/Kconfig.mmu linux-libre-3.2-gnu/arch/m68k/Kconfig.mmu
--- linux-libre-3.1-gnu/arch/m68k/Kconfig.mmu	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/Kconfig.mmu	1969-12-31 19:00:00.000000000 -0500
@@ -1,411 +0,0 @@
-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 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-3.1-gnu/arch/m68k/Kconfig.nommu linux-libre-3.2-gnu/arch/m68k/Kconfig.nommu
--- linux-libre-3.1-gnu/arch/m68k/Kconfig.nommu	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/Kconfig.nommu	1969-12-31 19:00:00.000000000 -0500
@@ -1,787 +0,0 @@
-config FPU
-	bool
-	default n
-
-config GENERIC_GPIO
-	bool
-	default n
-
-config GENERIC_CMOS_UPDATE
-	bool
-	default y
-
-config GENERIC_CLOCKEVENTS
-	bool
-	default n
-
-config M68000
-	bool
-	select CPU_HAS_NO_BITFIELDS
-	help
-	  The Freescale (was Motorola) 68000 CPU is the first generation of
-	  the well known M68K family of processors. The CPU core as well as
-	  being available as a stand alone CPU was also used in many
-	  System-On-Chip devices (eg 68328, 68302, etc). It does not contain
-	  a paging MMU.
-
-config MCPU32
-	bool
-	select CPU_HAS_NO_BITFIELDS
-	help
-	  The Freescale (was then Motorola) CPU32 is a CPU core that is
-	  based on the 68020 processor. For the most part it is used in
-	  System-On-Chip parts, and does not contain a paging MMU.
-
-config COLDFIRE
-	bool
-	select GENERIC_GPIO
-	select ARCH_REQUIRE_GPIOLIB
-	select CPU_HAS_NO_BITFIELDS
-	help
-	  The Freescale ColdFire family of processors is a modern derivitive
-	  of the 68000 processor family. They are mainly targeted at embedded
-	  applications, and are all System-On-Chip (SOC) devices, as opposed
-	  to stand alone CPUs. They implement a subset of the original 68000
-	  processor instruction set.
-
-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"
-	select M68000
-	help
-	  Motorola 68328 processor support.
-
-config M68EZ328
-	bool "MC68EZ328"
-	select M68000
-	help
-	  Motorola 68EX328 processor support.
-
-config M68VZ328
-	bool "MC68VZ328"
-	select M68000
-	help
-	  Motorola 68VZ328 processor support.
-
-config M68360
-	bool "MC68360"
-	select MCPU32
-	help
-	  Motorola 68360 processor support.
-
-config M5206
-	bool "MCF5206"
-	select COLDFIRE
-	select COLDFIRE_SW_A7
-	select HAVE_MBAR
-	help
-	  Motorola ColdFire 5206 processor support.
-
-config M5206e
-	bool "MCF5206e"
-	select COLDFIRE
-	select COLDFIRE_SW_A7
-	select HAVE_MBAR
-	help
-	  Motorola ColdFire 5206e processor support.
-
-config M520x
-	bool "MCF520x"
-	select COLDFIRE
-	select GENERIC_CLOCKEVENTS
-	select HAVE_CACHE_SPLIT
-	help
-	   Freescale Coldfire 5207/5208 processor support.
-
-config M523x
-	bool "MCF523x"
-	select COLDFIRE
-	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
-	select COLDFIRE_SW_A7
-	select HAVE_MBAR
-	help
-	  Motorola ColdFire 5249 processor support.
-
-config M5271
-	bool "MCF5271"
-	select COLDFIRE
-	select HAVE_CACHE_SPLIT
-	select HAVE_IPSBAR
-	help
-	  Freescale (Motorola) ColdFire 5270/5271 processor support.
-
-config M5272
-	bool "MCF5272"
-	select COLDFIRE
-	select COLDFIRE_SW_A7
-	select HAVE_MBAR
-	help
-	  Motorola ColdFire 5272 processor support.
-
-config M5275
-	bool "MCF5275"
-	select COLDFIRE
-	select HAVE_CACHE_SPLIT
-	select HAVE_IPSBAR
-	help
-	  Freescale (Motorola) ColdFire 5274/5275 processor support.
-
-config M528x
-	bool "MCF528x"
-	select COLDFIRE
-	select GENERIC_CLOCKEVENTS
-	select HAVE_CACHE_SPLIT
-	select HAVE_IPSBAR
-	help
-	  Motorola ColdFire 5280/5282 processor support.
-
-config M5307
-	bool "MCF5307"
-	select COLDFIRE
-	select COLDFIRE_SW_A7
-	select HAVE_CACHE_CB
-	select HAVE_MBAR
-	help
-	  Motorola ColdFire 5307 processor support.
-
-config M532x
-	bool "MCF532x"
-	select COLDFIRE
-	select HAVE_CACHE_CB
-	help
-	  Freescale (Motorola) ColdFire 532x processor support.
-
-config M5407
-	bool "MCF5407"
-	select COLDFIRE
-	select COLDFIRE_SW_A7
-	select HAVE_CACHE_CB
-	select HAVE_MBAR
-	help
-	  Motorola ColdFire 5407 processor support.
-
-config M547x
-	bool "MCF547x"
-	select COLDFIRE
-	select HAVE_CACHE_CB
-	select HAVE_MBAR
-	help
-	  Freescale ColdFire 5470/5471/5472/5473/5474/5475 processor support.
-
-config M548x
-	bool "MCF548x"
-	select COLDFIRE
-	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 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-3.1-gnu/arch/m68k/kernel/dma_mm.c linux-libre-3.2-gnu/arch/m68k/kernel/dma_mm.c
--- linux-libre-3.1-gnu/arch/m68k/kernel/dma_mm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/kernel/dma_mm.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 
 #include <asm/pgalloc.h>
 
diff -druN linux-libre-3.1-gnu/arch/m68k/kernel/dma_no.c linux-libre-3.2-gnu/arch/m68k/kernel/dma_no.c
--- linux-libre-3.1-gnu/arch/m68k/kernel/dma_no.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/kernel/dma_no.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 #include <asm/cacheflush.h>
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
diff -druN linux-libre-3.1-gnu/arch/m68k/kernel/entry_mm.S linux-libre-3.2-gnu/arch/m68k/kernel/entry_mm.S
--- linux-libre-3.1-gnu/arch/m68k/kernel/entry_mm.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/kernel/entry_mm.S	2012-01-04 18:55:44.000000000 -0500
@@ -48,7 +48,7 @@
 .globl sys_fork, sys_clone, sys_vfork
 .globl ret_from_interrupt, bad_interrupt
 .globl auto_irqhandler_fixup
-.globl user_irqvec_fixup, user_irqhandler_fixup
+.globl user_irqvec_fixup
 
 .text
 ENTRY(buserr)
@@ -207,7 +207,7 @@
 	movel	%sp,%sp@-
 	movel	%d0,%sp@-		|  put vector # on stack
 auto_irqhandler_fixup = . + 2
-	jsr	__m68k_handle_int	|  process the IRQ
+	jsr	do_IRQ			|  process the IRQ
 	addql	#8,%sp			|  pop parameters off stack
 
 ret_from_interrupt:
@@ -240,8 +240,7 @@
 
 	movel	%sp,%sp@-
 	movel	%d0,%sp@-		|  put vector # on stack
-user_irqhandler_fixup = . + 2
-	jsr	__m68k_handle_int	|  process the IRQ
+	jsr	do_IRQ			|  process the IRQ
 	addql	#8,%sp			|  pop parameters off stack
 
 	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
diff -druN linux-libre-3.1-gnu/arch/m68k/kernel/entry_no.S linux-libre-3.2-gnu/arch/m68k/kernel/entry_no.S
--- linux-libre-3.1-gnu/arch/m68k/kernel/entry_no.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/kernel/entry_no.S	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,7 @@
 .globl sys_vfork
 
 ENTRY(buserr)
-	SAVE_ALL
+	SAVE_ALL_INT
 	moveq	#-1,%d0
 	movel	%d0,%sp@(PT_OFF_ORIG_D0)
 	movel	%sp,%sp@- 		/* stack frame pointer argument */
@@ -52,7 +52,7 @@
 	jra	ret_from_exception
 
 ENTRY(trap)
-	SAVE_ALL
+	SAVE_ALL_INT
 	moveq	#-1,%d0
 	movel	%d0,%sp@(PT_OFF_ORIG_D0)
 	movel	%sp,%sp@- 		/* stack frame pointer argument */
@@ -64,7 +64,7 @@
 
 .globl dbginterrupt
 ENTRY(dbginterrupt)
-	SAVE_ALL
+	SAVE_ALL_INT
 	moveq	#-1,%d0
 	movel	%d0,%sp@(PT_OFF_ORIG_D0)
 	movel	%sp,%sp@- 		/* stack frame pointer argument */
diff -druN linux-libre-3.1-gnu/arch/m68k/kernel/ints.c linux-libre-3.2-gnu/arch/m68k/kernel/ints.c
--- linux-libre-3.1-gnu/arch/m68k/kernel/ints.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/kernel/ints.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,25 +4,6 @@
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
  * for more details.
- *
- * 07/03/96: Timer initialization, and thus mach_sched_init(),
- *           removed from request_irq() and moved to init_time().
- *           We should therefore consider renaming our add_isr() and
- *           remove_isr() to request_irq() and free_irq()
- *           respectively, so they are compliant with the other
- *           architectures.                                     /Jes
- * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls.
- *           Removed irq list support, if any machine needs an irq server
- *           it must implement this itself (as it's already done), instead
- *           only default handler are used with mach_default_handler.
- *           request_irq got some flags different from other architectures:
- *           - IRQ_FLG_REPLACE : Replace an existing handler (the default one
- *                               can be replaced without this flag)
- *           - IRQ_FLG_LOCK : handler can't be replaced
- *           There are other machine depending flags, see there
- *           If you want to replace a default handler you should know what
- *           you're doing, since it might handle different other irq sources
- *           which must be served                               /Roman Zippel
  */
 
 #include <linux/module.h>
@@ -47,33 +28,22 @@
 #endif
 
 extern u32 auto_irqhandler_fixup[];
-extern u32 user_irqhandler_fixup[];
 extern u16 user_irqvec_fixup[];
 
-/* table for system interrupt handlers */
-static struct irq_node *irq_list[NR_IRQS];
-static struct irq_controller *irq_controller[NR_IRQS];
-static int irq_depth[NR_IRQS];
-
 static int m68k_first_user_vec;
 
-static struct irq_controller auto_irq_controller = {
+static struct irq_chip auto_irq_chip = {
 	.name		= "auto",
-	.lock		= __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock),
-	.startup	= m68k_irq_startup,
-	.shutdown	= m68k_irq_shutdown,
+	.irq_startup	= m68k_irq_startup,
+	.irq_shutdown	= m68k_irq_shutdown,
 };
 
-static struct irq_controller user_irq_controller = {
+static struct irq_chip user_irq_chip = {
 	.name		= "user",
-	.lock		= __SPIN_LOCK_UNLOCKED(user_irq_controller.lock),
-	.startup	= m68k_irq_startup,
-	.shutdown	= m68k_irq_shutdown,
+	.irq_startup	= m68k_irq_startup,
+	.irq_shutdown	= m68k_irq_shutdown,
 };
 
-#define NUM_IRQ_NODES 100
-static irq_node_t nodes[NUM_IRQ_NODES];
-
 /*
  * void init_IRQ(void)
  *
@@ -96,7 +66,7 @@
 	}
 
 	for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++)
-		irq_controller[i] = &auto_irq_controller;
+		irq_set_chip_and_handler(i, &auto_irq_chip, handle_simple_irq);
 
 	mach_init_IRQ();
 }
@@ -106,7 +76,7 @@
  * @handler: called from auto vector interrupts
  *
  * setup the handler to be called from auto vector interrupts instead of the
- * standard __m68k_handle_int(), it will be called with irq numbers in the range
+ * standard do_IRQ(), it will be called with irq numbers in the range
  * from IRQ_AUTO_1 - IRQ_AUTO_7.
  */
 void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *))
@@ -120,217 +90,49 @@
  * m68k_setup_user_interrupt
  * @vec: first user vector interrupt to handle
  * @cnt: number of active user vector interrupts
- * @handler: called from user vector interrupts
  *
  * setup user vector interrupts, this includes activating the specified range
  * of interrupts, only then these interrupts can be requested (note: this is
- * different from auto vector interrupts). An optional handler can be installed
- * to be called instead of the default __m68k_handle_int(), it will be called
- * with irq numbers starting from IRQ_USER.
+ * different from auto vector interrupts).
  */
-void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
-				      void (*handler)(unsigned int, struct pt_regs *))
+void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt)
 {
 	int i;
 
 	BUG_ON(IRQ_USER + cnt > NR_IRQS);
 	m68k_first_user_vec = vec;
 	for (i = 0; i < cnt; i++)
-		irq_controller[IRQ_USER + i] = &user_irq_controller;
+		irq_set_chip(IRQ_USER + i, &user_irq_chip);
 	*user_irqvec_fixup = vec - IRQ_USER;
-	if (handler)
-		*user_irqhandler_fixup = (u32)handler;
 	flush_icache();
 }
 
 /**
  * m68k_setup_irq_controller
- * @contr: irq controller which controls specified irq
+ * @chip: irq chip which controls specified irq
+ * @handle: flow handler which handles specified irq
  * @irq: first irq to be managed by the controller
+ * @cnt: number of irqs to be managed by the controller
  *
  * Change the controller for the specified range of irq, which will be used to
  * manage these irq. auto/user irq already have a default controller, which can
  * be changed as well, but the controller probably should use m68k_irq_startup/
  * m68k_irq_shutdown.
  */
-void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq,
+void m68k_setup_irq_controller(struct irq_chip *chip,
+			       irq_flow_handler_t handle, unsigned int irq,
 			       unsigned int cnt)
 {
 	int i;
 
-	for (i = 0; i < cnt; i++)
-		irq_controller[irq + i] = contr;
-}
-
-irq_node_t *new_irq_node(void)
-{
-	irq_node_t *node;
-	short i;
-
-	for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) {
-		if (!node->handler) {
-			memset(node, 0, sizeof(*node));
-			return node;
-		}
-	}
-
-	printk ("new_irq_node: out of nodes\n");
-	return NULL;
-}
-
-int setup_irq(unsigned int irq, struct irq_node *node)
-{
-	struct irq_controller *contr;
-	struct irq_node **prev;
-	unsigned long flags;
-
-	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
-		printk("%s: Incorrect IRQ %d from %s\n",
-		       __func__, irq, node->devname);
-		return -ENXIO;
-	}
-
-	spin_lock_irqsave(&contr->lock, flags);
-
-	prev = irq_list + irq;
-	if (*prev) {
-		/* Can't share interrupts unless both agree to */
-		if (!((*prev)->flags & node->flags & IRQF_SHARED)) {
-			spin_unlock_irqrestore(&contr->lock, flags);
-			return -EBUSY;
-		}
-		while (*prev)
-			prev = &(*prev)->next;
-	}
-
-	if (!irq_list[irq]) {
-		if (contr->startup)
-			contr->startup(irq);
-		else
-			contr->enable(irq);
-	}
-	node->next = NULL;
-	*prev = node;
-
-	spin_unlock_irqrestore(&contr->lock, flags);
-
-	return 0;
-}
-
-int request_irq(unsigned int irq,
-		irq_handler_t handler,
-		unsigned long flags, const char *devname, void *dev_id)
-{
-	struct irq_node *node;
-	int res;
-
-	node = new_irq_node();
-	if (!node)
-		return -ENOMEM;
-
-	node->handler = handler;
-	node->flags   = flags;
-	node->dev_id  = dev_id;
-	node->devname = devname;
-
-	res = setup_irq(irq, node);
-	if (res)
-		node->handler = NULL;
-
-	return res;
-}
-
-EXPORT_SYMBOL(request_irq);
-
-void free_irq(unsigned int irq, void *dev_id)
-{
-	struct irq_controller *contr;
-	struct irq_node **p, *node;
-	unsigned long flags;
-
-	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
-		printk("%s: Incorrect IRQ %d\n", __func__, irq);
-		return;
-	}
-
-	spin_lock_irqsave(&contr->lock, flags);
-
-	p = irq_list + irq;
-	while ((node = *p)) {
-		if (node->dev_id == dev_id)
-			break;
-		p = &node->next;
-	}
-
-	if (node) {
-		*p = node->next;
-		node->handler = NULL;
-	} else
-		printk("%s: Removing probably wrong IRQ %d\n",
-		       __func__, irq);
-
-	if (!irq_list[irq]) {
-		if (contr->shutdown)
-			contr->shutdown(irq);
-		else
-			contr->disable(irq);
-	}
-
-	spin_unlock_irqrestore(&contr->lock, flags);
-}
-
-EXPORT_SYMBOL(free_irq);
-
-void enable_irq(unsigned int irq)
-{
-	struct irq_controller *contr;
-	unsigned long flags;
-
-	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
-		printk("%s: Incorrect IRQ %d\n",
-		       __func__, irq);
-		return;
-	}
-
-	spin_lock_irqsave(&contr->lock, flags);
-	if (irq_depth[irq]) {
-		if (!--irq_depth[irq]) {
-			if (contr->enable)
-				contr->enable(irq);
-		}
-	} else
-		WARN_ON(1);
-	spin_unlock_irqrestore(&contr->lock, flags);
-}
-
-EXPORT_SYMBOL(enable_irq);
-
-void disable_irq(unsigned int irq)
-{
-	struct irq_controller *contr;
-	unsigned long flags;
-
-	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
-		printk("%s: Incorrect IRQ %d\n",
-		       __func__, irq);
-		return;
-	}
-
-	spin_lock_irqsave(&contr->lock, flags);
-	if (!irq_depth[irq]++) {
-		if (contr->disable)
-			contr->disable(irq);
+	for (i = 0; i < cnt; i++) {
+		irq_set_chip(irq + i, chip);
+		if (handle)
+			irq_set_handler(irq + i, handle);
 	}
-	spin_unlock_irqrestore(&contr->lock, flags);
 }
 
-EXPORT_SYMBOL(disable_irq);
-
-void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq")));
-
-EXPORT_SYMBOL(disable_irq_nosync);
-
-int m68k_irq_startup(unsigned int irq)
+unsigned int m68k_irq_startup_irq(unsigned int irq)
 {
 	if (irq <= IRQ_AUTO_7)
 		vectors[VEC_SPUR + irq] = auto_inthandler;
@@ -339,41 +141,21 @@
 	return 0;
 }
 
-void m68k_irq_shutdown(unsigned int irq)
+unsigned int m68k_irq_startup(struct irq_data *data)
 {
-	if (irq <= IRQ_AUTO_7)
-		vectors[VEC_SPUR + irq] = bad_inthandler;
-	else
-		vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler;
+	return m68k_irq_startup_irq(data->irq);
 }
 
-
-/*
- * Do we need these probe functions on the m68k?
- *
- *  ... may be useful with ISA devices
- */
-unsigned long probe_irq_on (void)
+void m68k_irq_shutdown(struct irq_data *data)
 {
-#ifdef CONFIG_Q40
-	if (MACH_IS_Q40)
-		return q40_probe_irq_on();
-#endif
-	return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_on);
+	unsigned int irq = data->irq;
 
-int probe_irq_off (unsigned long irqs)
-{
-#ifdef CONFIG_Q40
-	if (MACH_IS_Q40)
-		return q40_probe_irq_off(irqs);
-#endif
-	return 0;
+	if (irq <= IRQ_AUTO_7)
+		vectors[VEC_SPUR + irq] = bad_inthandler;
+	else
+		vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler;
 }
 
-EXPORT_SYMBOL(probe_irq_off);
 
 unsigned int irq_canonicalize(unsigned int irq)
 {
@@ -386,52 +168,9 @@
 
 EXPORT_SYMBOL(irq_canonicalize);
 
-asmlinkage void m68k_handle_int(unsigned int irq)
-{
-	struct irq_node *node;
-	kstat_cpu(0).irqs[irq]++;
-	node = irq_list[irq];
-	do {
-		node->handler(irq, node->dev_id);
-		node = node->next;
-	} while (node);
-}
-
-asmlinkage void __m68k_handle_int(unsigned int irq, struct pt_regs *regs)
-{
-	struct pt_regs *old_regs;
-	old_regs = set_irq_regs(regs);
-	m68k_handle_int(irq);
-	set_irq_regs(old_regs);
-}
 
 asmlinkage void handle_badint(struct pt_regs *regs)
 {
-	kstat_cpu(0).irqs[0]++;
-	printk("unexpected interrupt from %u\n", regs->vector);
-}
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-	struct irq_controller *contr;
-	struct irq_node *node;
-	int i = *(loff_t *) v;
-
-	/* autovector interrupts */
-	if (irq_list[i]) {
-		contr = irq_controller[i];
-		node = irq_list[i];
-		seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname);
-		while ((node = node->next))
-			seq_printf(p, ", %s", node->devname);
-		seq_puts(p, "\n");
-	}
-	return 0;
-}
-
-#ifdef CONFIG_PROC_FS
-void init_irq_proc(void)
-{
-	/* Insert /proc/irq driver here */
+	atomic_inc(&irq_err_count);
+	pr_warn("unexpected interrupt from %u\n", regs->vector);
 }
-#endif
diff -druN linux-libre-3.1-gnu/arch/m68k/kernel/Makefile linux-libre-3.2-gnu/arch/m68k/kernel/Makefile
--- linux-libre-3.1-gnu/arch/m68k/kernel/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,20 @@
-ifdef CONFIG_MMU
-include arch/m68k/kernel/Makefile_mm
-else
-include arch/m68k/kernel/Makefile_no
+#
+# Makefile for the linux kernel.
+#
+
+extra-$(CONFIG_MMU)	:= head.o
+extra-$(CONFIG_SUN3)	:= sun3-head.o
+extra-y			+= vmlinux.lds
+
+obj-y	:= entry.o irq.o m68k_ksyms.o module.o process.o ptrace.o setup.o \
+	   signal.o sys_m68k.o syscalltable.o time.o traps.o
+
+obj-$(CONFIG_MMU)	+= ints.o vectors.o
+
+ifndef CONFIG_MMU_SUN3
+obj-y			+= dma.o
 endif
+ifndef CONFIG_MMU
+obj-y			+= init_task.o
+endif
+
diff -druN linux-libre-3.1-gnu/arch/m68k/kernel/Makefile_mm linux-libre-3.2-gnu/arch/m68k/kernel/Makefile_mm
--- linux-libre-3.1-gnu/arch/m68k/kernel/Makefile_mm	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/kernel/Makefile_mm	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-#
-# 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 syscalltable.o
-
-devres-y = ../../../kernel/irq/devres.o
-
-obj-y$(CONFIG_MMU_SUN3) += dma.o	# no, it's not a typo
diff -druN linux-libre-3.1-gnu/arch/m68k/kernel/Makefile_no linux-libre-3.2-gnu/arch/m68k/kernel/Makefile_no
--- linux-libre-3.1-gnu/arch/m68k/kernel/Makefile_no	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/kernel/Makefile_no	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-3.1-gnu/arch/m68k/kernel/setup_no.c linux-libre-3.2-gnu/arch/m68k/kernel/setup_no.c
--- linux-libre-3.1-gnu/arch/m68k/kernel/setup_no.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/kernel/setup_no.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 #include <asm/irq.h>
 #include <asm/machdep.h>
 #include <asm/pgtable.h>
+#include <asm/sections.h>
 
 unsigned long memory_start;
 unsigned long memory_end;
@@ -80,9 +81,6 @@
 #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
diff -druN linux-libre-3.1-gnu/arch/m68k/kernel/syscalltable.S linux-libre-3.2-gnu/arch/m68k/kernel/syscalltable.S
--- linux-libre-3.1-gnu/arch/m68k/kernel/syscalltable.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/kernel/syscalltable.S	2012-01-04 18:55:44.000000000 -0500
@@ -365,4 +365,6 @@
 	.long sys_clock_adjtime
 	.long sys_syncfs
 	.long sys_setns
+	.long sys_process_vm_readv	/* 345 */
+	.long sys_process_vm_writev
 
diff -druN linux-libre-3.1-gnu/arch/m68k/kernel/traps.c linux-libre-3.2-gnu/arch/m68k/kernel/traps.c
--- linux-libre-3.1-gnu/arch/m68k/kernel/traps.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/kernel/traps.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,1107 @@
-#ifdef CONFIG_MMU
-#include "traps_mm.c"
+/*
+ *  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>
+
+
+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
-#include "traps_no.c"
+	[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);
+
+/*
+ * The vector number returned in the frame pointer may also contain
+ * the "fs" (Fault Status) bits on ColdFire. These are in the bottom
+ * 2 bits, and upper 2 bits. So we need to mask out the real vector
+ * number before using it in comparisons. You don't need to do this on
+ * real 68k parts, but it won't hurt either.
+ */
+
+void bad_super_trap (struct frame *fp)
+{
+	int vector = (fp->ptregs.vector >> 2) & 0xff;
+
+	console_verbose();
+	if (vector < ARRAY_SIZE(vec_names))
+		printk ("*** %s ***   FORMAT=%X\n",
+			vec_names[vector],
+			fp->ptregs.format);
+	else
+		printk ("*** Exception %d ***   FORMAT=%X\n",
+			vector, fp->ptregs.format);
+	if (vector == 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;
+	int vector = (fp->ptregs.vector >> 2) & 0xff;
+	siginfo_t info;
+
+	if (fp->ptregs.sr & PS_S) {
+		if (vector == VEC_TRACE) {
+			/* 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 (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:
+	    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);
+}
+
+asmlinkage void set_esp0(unsigned long ssp)
+{
+	current->thread.esp0 = ssp;
+}
+
+/*
+ * 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-3.1-gnu/arch/m68k/kernel/traps_mm.c linux-libre-3.2-gnu/arch/m68k/kernel/traps_mm.c
--- linux-libre-3.1-gnu/arch/m68k/kernel/traps_mm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/kernel/traps_mm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1207 +0,0 @@
-/*
- *  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-3.1-gnu/arch/m68k/kernel/traps_no.c linux-libre-3.2-gnu/arch/m68k/kernel/traps_no.c
--- linux-libre-3.1-gnu/arch/m68k/kernel/traps_no.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/kernel/traps_no.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,361 +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 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-3.1-gnu/arch/m68k/kernel/vectors.c linux-libre-3.2-gnu/arch/m68k/kernel/vectors.c
--- linux-libre-3.1-gnu/arch/m68k/kernel/vectors.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/m68k/kernel/vectors.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,145 @@
+/*
+ *  vectors.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/kernel.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <linux/kallsyms.h>
+
+#include <asm/setup.h>
+#include <asm/fpu.h>
+#include <asm/system.h>
+#include <asm/traps.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;
+	}
+}
+
diff -druN linux-libre-3.1-gnu/arch/m68k/kernel/vmlinux.lds_no.S linux-libre-3.2-gnu/arch/m68k/kernel/vmlinux.lds_no.S
--- linux-libre-3.1-gnu/arch/m68k/kernel/vmlinux.lds_no.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/kernel/vmlinux.lds_no.S	2012-01-04 18:55:44.000000000 -0500
@@ -77,7 +77,6 @@
 
 		*(.rodata) *(.rodata.*)
 		*(__vermagic)		/* Kernel version magic */
-		*(__markers_strings)
 		*(.rodata1)
 		*(.rodata.str1.1)
 
diff -druN linux-libre-3.1-gnu/arch/m68k/lib/memcpy.c linux-libre-3.2-gnu/arch/m68k/lib/memcpy.c
--- linux-libre-3.1-gnu/arch/m68k/lib/memcpy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/lib/memcpy.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,15 @@
 		from = cfrom;
 		n--;
 	}
+#if defined(CONFIG_M68000)
+	if ((long)from & 1) {
+		char *cto = to;
+		const char *cfrom = from;
+		for (; n; n--)
+			*cto++ = *cfrom++;
+		return xto;
+	}
+#endif
 	if (n > 2 && (long)to & 2) {
 		short *sto = to;
 		const short *sfrom = from;
diff -druN linux-libre-3.1-gnu/arch/m68k/mac/baboon.c linux-libre-3.2-gnu/arch/m68k/mac/baboon.c
--- linux-libre-3.1-gnu/arch/m68k/mac/baboon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/mac/baboon.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 
 #include <asm/traps.h>
 #include <asm/bootinfo.h>
@@ -20,9 +21,6 @@
 
 /* #define DEBUG_IRQS */
 
-extern void mac_enable_irq(unsigned int);
-extern void mac_disable_irq(unsigned int);
-
 int baboon_present;
 static volatile struct baboon *baboon;
 static unsigned char baboon_disabled;
@@ -53,7 +51,7 @@
  * Baboon interrupt handler. This works a lot like a VIA.
  */
 
-static irqreturn_t baboon_irq(int irq, void *dev_id)
+static void baboon_irq(unsigned int irq, struct irq_desc *desc)
 {
 	int irq_bit, irq_num;
 	unsigned char events;
@@ -64,15 +62,16 @@
 		(uint) baboon->mb_status);
 #endif
 
-	if (!(events = baboon->mb_ifr & 0x07))
-		return IRQ_NONE;
+	events = baboon->mb_ifr & 0x07;
+	if (!events)
+		return;
 
 	irq_num = IRQ_BABOON_0;
 	irq_bit = 1;
 	do {
 	        if (events & irq_bit) {
 			baboon->mb_ifr &= ~irq_bit;
-			m68k_handle_int(irq_num);
+			generic_handle_irq(irq_num);
 		}
 		irq_bit <<= 1;
 		irq_num++;
@@ -82,7 +81,6 @@
 	/* for now we need to smash all interrupts */
 	baboon->mb_ifr &= ~events;
 #endif
-	return IRQ_HANDLED;
 }
 
 /*
@@ -92,8 +90,7 @@
 void __init baboon_register_interrupts(void)
 {
 	baboon_disabled = 0;
-	if (request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon))
-		pr_err("Couldn't register baboon interrupt\n");
+	irq_set_chained_handler(IRQ_NUBUS_C, baboon_irq);
 }
 
 /*
@@ -111,7 +108,7 @@
 
 	baboon_disabled &= ~(1 << irq_idx);
 	if (!baboon_disabled)
-		mac_enable_irq(IRQ_NUBUS_C);
+		mac_irq_enable(irq_get_irq_data(IRQ_NUBUS_C));
 }
 
 void baboon_irq_disable(int irq)
@@ -124,7 +121,7 @@
 
 	baboon_disabled |= 1 << irq_idx;
 	if (baboon_disabled)
-		mac_disable_irq(IRQ_NUBUS_C);
+		mac_irq_disable(irq_get_irq_data(IRQ_NUBUS_C));
 }
 
 void baboon_irq_clear(int irq)
diff -druN linux-libre-3.1-gnu/arch/m68k/mac/iop.c linux-libre-3.2-gnu/arch/m68k/mac/iop.c
--- linux-libre-3.1-gnu/arch/m68k/mac/iop.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/mac/iop.c	2012-01-04 18:55:44.000000000 -0500
@@ -305,15 +305,13 @@
 {
 	if (iop_ism_present) {
 		if (oss_present) {
-			if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
-					IRQ_FLG_LOCK, "ISM IOP",
-					(void *) IOP_NUM_ISM))
+			if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq, 0,
+					"ISM IOP", (void *)IOP_NUM_ISM))
 				pr_err("Couldn't register ISM IOP interrupt\n");
 			oss_irq_enable(IRQ_MAC_ADB);
 		} else {
-			if (request_irq(IRQ_VIA2_0, iop_ism_irq,
-					IRQ_FLG_LOCK|IRQ_FLG_FAST, "ISM IOP",
-					(void *) IOP_NUM_ISM))
+			if (request_irq(IRQ_VIA2_0, iop_ism_irq, 0, "ISM IOP",
+					(void *)IOP_NUM_ISM))
 				pr_err("Couldn't register ISM IOP interrupt\n");
 		}
 		if (!iop_alive(iop_base[IOP_NUM_ISM])) {
diff -druN linux-libre-3.1-gnu/arch/m68k/mac/macints.c linux-libre-3.2-gnu/arch/m68k/mac/macints.c
--- linux-libre-3.1-gnu/arch/m68k/mac/macints.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/mac/macints.c	2012-01-04 18:55:44.000000000 -0500
@@ -190,14 +190,10 @@
 
 /* #define DEBUG_MACINTS */
 
-void mac_enable_irq(unsigned int irq);
-void mac_disable_irq(unsigned int irq);
-
-static struct irq_controller mac_irq_controller = {
+static struct irq_chip mac_irq_chip = {
 	.name		= "mac",
-	.lock		= __SPIN_LOCK_UNLOCKED(mac_irq_controller.lock),
-	.enable		= mac_enable_irq,
-	.disable	= mac_disable_irq,
+	.irq_enable	= mac_irq_enable,
+	.irq_disable	= mac_irq_disable,
 };
 
 void __init mac_init_IRQ(void)
@@ -205,7 +201,7 @@
 #ifdef DEBUG_MACINTS
 	printk("mac_init_IRQ(): Setting things up...\n");
 #endif
-	m68k_setup_irq_controller(&mac_irq_controller, IRQ_USER,
+	m68k_setup_irq_controller(&mac_irq_chip, handle_simple_irq, IRQ_USER,
 				  NUM_MAC_SOURCES - IRQ_USER);
 	/* Make sure the SONIC interrupt is cleared or things get ugly */
 #ifdef SHUTUP_SONIC
@@ -241,16 +237,17 @@
 }
 
 /*
- *  mac_enable_irq - enable an interrupt source
- * mac_disable_irq - disable an interrupt source
+ *  mac_irq_enable - enable an interrupt source
+ * mac_irq_disable - disable an interrupt source
  *   mac_clear_irq - clears a pending interrupt
- * mac_pending_irq - Returns the pending status of an IRQ (nonzero = pending)
+ * mac_irq_pending - returns the pending status of an IRQ (nonzero = pending)
  *
  * These routines are just dispatchers to the VIA/OSS/PSC routines.
  */
 
-void mac_enable_irq(unsigned int irq)
+void mac_irq_enable(struct irq_data *data)
 {
+	int irq = data->irq;
 	int irq_src = IRQ_SRC(irq);
 
 	switch(irq_src) {
@@ -283,8 +280,9 @@
 	}
 }
 
-void mac_disable_irq(unsigned int irq)
+void mac_irq_disable(struct irq_data *data)
 {
+	int irq = data->irq;
 	int irq_src = IRQ_SRC(irq);
 
 	switch(irq_src) {
@@ -370,7 +368,7 @@
 		break;
 	case 4:
 		if (psc_present)
-			psc_irq_pending(irq);
+			return psc_irq_pending(irq);
 		break;
 	}
 	return 0;
diff -druN linux-libre-3.1-gnu/arch/m68k/mac/misc.c linux-libre-3.2-gnu/arch/m68k/mac/misc.c
--- linux-libre-3.1-gnu/arch/m68k/mac/misc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/mac/misc.c	2012-01-04 18:55:44.000000000 -0500
@@ -304,35 +304,41 @@
 static long via_read_time(void)
 {
 	union {
-		__u8  cdata[4];
-		long  idata;
+		__u8 cdata[4];
+		long idata;
 	} result, last_result;
-	int	ct;
+	int count = 1;
+
+	via_pram_command(0x81, &last_result.cdata[3]);
+	via_pram_command(0x85, &last_result.cdata[2]);
+	via_pram_command(0x89, &last_result.cdata[1]);
+	via_pram_command(0x8D, &last_result.cdata[0]);
 
 	/*
 	 * The NetBSD guys say to loop until you get the same reading
 	 * twice in a row.
 	 */
 
-	ct = 0;
-	do {
-		if (++ct > 10) {
-			printk("via_read_time: couldn't get valid time, "
-			       "last read = 0x%08lx and 0x%08lx\n",
-			       last_result.idata, result.idata);
-			break;
-		}
-
-		last_result.idata = result.idata;
-		result.idata = 0;
-
+	while (1) {
 		via_pram_command(0x81, &result.cdata[3]);
 		via_pram_command(0x85, &result.cdata[2]);
 		via_pram_command(0x89, &result.cdata[1]);
 		via_pram_command(0x8D, &result.cdata[0]);
-	} while (result.idata != last_result.idata);
 
-	return result.idata - RTC_OFFSET;
+		if (result.idata == last_result.idata)
+			return result.idata - RTC_OFFSET;
+
+		if (++count > 10)
+			break;
+
+		last_result.idata = result.idata;
+	}
+
+	pr_err("via_read_time: failed to read a stable value; "
+	       "got 0x%08lx then 0x%08lx\n",
+	       last_result.idata, result.idata);
+
+	return 0;
 }
 
 /*
diff -druN linux-libre-3.1-gnu/arch/m68k/mac/oss.c linux-libre-3.2-gnu/arch/m68k/mac/oss.c
--- linux-libre-3.1-gnu/arch/m68k/mac/oss.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/mac/oss.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 
 #include <asm/bootinfo.h>
 #include <asm/macintosh.h>
@@ -29,10 +30,7 @@
 int oss_present;
 volatile struct mac_oss *oss;
 
-static irqreturn_t oss_irq(int, void *);
-static irqreturn_t oss_nubus_irq(int, void *);
-
-extern irqreturn_t via1_irq(int, void *);
+extern void via1_irq(unsigned int irq, struct irq_desc *desc);
 
 /*
  * Initialize the OSS
@@ -60,26 +58,6 @@
 }
 
 /*
- * Register the OSS and NuBus interrupt dispatchers.
- */
-
-void __init oss_register_interrupts(void)
-{
-	if (request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
-			"scsi", (void *) oss))
-		pr_err("Couldn't register %s interrupt\n", "scsi");
-	if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
-			"nubus", (void *) oss))
-		pr_err("Couldn't register %s interrupt\n", "nubus");
-	if (request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
-			"sound", (void *) oss))
-		pr_err("Couldn't register %s interrupt\n", "sound");
-	if (request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
-			"via1", (void *) via1))
-		pr_err("Couldn't register %s interrupt\n", "via1");
-}
-
-/*
  * Initialize OSS for Nubus access
  */
 
@@ -92,17 +70,17 @@
  * and SCSI; everything else is routed to its own autovector IRQ.
  */
 
-static irqreturn_t oss_irq(int irq, void *dev_id)
+static void oss_irq(unsigned int irq, struct irq_desc *desc)
 {
 	int events;
 
 	events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI);
 	if (!events)
-		return IRQ_NONE;
+		return;
 
 #ifdef DEBUG_IRQS
 	if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) {
-		printk("oss_irq: irq %d events = 0x%04X\n", irq,
+		printk("oss_irq: irq %u events = 0x%04X\n", irq,
 			(int) oss->irq_pending);
 	}
 #endif
@@ -113,11 +91,10 @@
 		/* FIXME: call sound handler */
 	} else if (events & OSS_IP_SCSI) {
 		oss->irq_pending &= ~OSS_IP_SCSI;
-		m68k_handle_int(IRQ_MAC_SCSI);
+		generic_handle_irq(IRQ_MAC_SCSI);
 	} else {
 		/* FIXME: error check here? */
 	}
-	return IRQ_HANDLED;
 }
 
 /*
@@ -126,13 +103,13 @@
  * Unlike the VIA/RBV this is on its own autovector interrupt level.
  */
 
-static irqreturn_t oss_nubus_irq(int irq, void *dev_id)
+static void oss_nubus_irq(unsigned int irq, struct irq_desc *desc)
 {
 	int events, irq_bit, i;
 
 	events = oss->irq_pending & OSS_IP_NUBUS;
 	if (!events)
-		return IRQ_NONE;
+		return;
 
 #ifdef DEBUG_NUBUS_INT
 	if (console_loglevel > 7) {
@@ -148,10 +125,21 @@
 		irq_bit >>= 1;
 		if (events & irq_bit) {
 			oss->irq_pending &= ~irq_bit;
-			m68k_handle_int(NUBUS_SOURCE_BASE + i);
+			generic_handle_irq(NUBUS_SOURCE_BASE + i);
 		}
 	} while(events & (irq_bit - 1));
-	return IRQ_HANDLED;
+}
+
+/*
+ * Register the OSS and NuBus interrupt dispatchers.
+ */
+
+void __init oss_register_interrupts(void)
+{
+	irq_set_chained_handler(OSS_IRQLEV_SCSI, oss_irq);
+	irq_set_chained_handler(OSS_IRQLEV_NUBUS, oss_nubus_irq);
+	irq_set_chained_handler(OSS_IRQLEV_SOUND, oss_irq);
+	irq_set_chained_handler(OSS_IRQLEV_VIA1, via1_irq);
 }
 
 /*
diff -druN linux-libre-3.1-gnu/arch/m68k/mac/psc.c linux-libre-3.2-gnu/arch/m68k/mac/psc.c
--- linux-libre-3.1-gnu/arch/m68k/mac/psc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/mac/psc.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 
 #include <asm/traps.h>
 #include <asm/bootinfo.h>
@@ -30,8 +31,6 @@
 int psc_present;
 volatile __u8 *psc;
 
-irqreturn_t psc_irq(int, void *);
-
 /*
  * Debugging dump, used in various places to see what's going on.
  */
@@ -112,52 +111,52 @@
 }
 
 /*
- * Register the PSC interrupt dispatchers for autovector interrupts 3-6.
- */
-
-void __init psc_register_interrupts(void)
-{
-	if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30))
-		pr_err("Couldn't register psc%d interrupt\n", 3);
-	if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40))
-		pr_err("Couldn't register psc%d interrupt\n", 4);
-	if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50))
-		pr_err("Couldn't register psc%d interrupt\n", 5);
-	if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60))
-		pr_err("Couldn't register psc%d interrupt\n", 6);
-}
-
-/*
  * PSC interrupt handler. It's a lot like the VIA interrupt handler.
  */
 
-irqreturn_t psc_irq(int irq, void *dev_id)
+static void psc_irq(unsigned int irq, struct irq_desc *desc)
 {
-	int pIFR	= pIFRbase + ((int) dev_id);
-	int pIER	= pIERbase + ((int) dev_id);
+	unsigned int offset = (unsigned int)irq_desc_get_handler_data(desc);
+	int pIFR	= pIFRbase + offset;
+	int pIER	= pIERbase + offset;
 	int irq_num;
 	unsigned char irq_bit, events;
 
 #ifdef DEBUG_IRQS
-	printk("psc_irq: irq %d pIFR = 0x%02X pIER = 0x%02X\n",
+	printk("psc_irq: irq %u pIFR = 0x%02X pIER = 0x%02X\n",
 		irq, (int) psc_read_byte(pIFR), (int) psc_read_byte(pIER));
 #endif
 
 	events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF;
 	if (!events)
-		return IRQ_NONE;
+		return;
 
 	irq_num = irq << 3;
 	irq_bit = 1;
 	do {
 		if (events & irq_bit) {
 			psc_write_byte(pIFR, irq_bit);
-			m68k_handle_int(irq_num);
+			generic_handle_irq(irq_num);
 		}
 		irq_num++;
 		irq_bit <<= 1;
 	} while (events >= irq_bit);
-	return IRQ_HANDLED;
+}
+
+/*
+ * Register the PSC interrupt dispatchers for autovector interrupts 3-6.
+ */
+
+void __init psc_register_interrupts(void)
+{
+	irq_set_chained_handler(IRQ_AUTO_3, psc_irq);
+	irq_set_handler_data(IRQ_AUTO_3, (void *)0x30);
+	irq_set_chained_handler(IRQ_AUTO_4, psc_irq);
+	irq_set_handler_data(IRQ_AUTO_4, (void *)0x40);
+	irq_set_chained_handler(IRQ_AUTO_5, psc_irq);
+	irq_set_handler_data(IRQ_AUTO_5, (void *)0x50);
+	irq_set_chained_handler(IRQ_AUTO_6, psc_irq);
+	irq_set_handler_data(IRQ_AUTO_6, (void *)0x60);
 }
 
 void psc_irq_enable(int irq) {
diff -druN linux-libre-3.1-gnu/arch/m68k/mac/via.c linux-libre-3.2-gnu/arch/m68k/mac/via.c
--- linux-libre-3.1-gnu/arch/m68k/mac/via.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/mac/via.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/irq.h>
 
 #include <asm/bootinfo.h>
 #include <asm/macintosh.h>
@@ -77,9 +78,6 @@
 static u8 nubus_disabled;
 
 void via_debug_dump(void);
-irqreturn_t via1_irq(int, void *);
-irqreturn_t via2_irq(int, void *);
-irqreturn_t via_nubus_irq(int, void *);
 void via_irq_enable(int irq);
 void via_irq_disable(int irq);
 void via_irq_clear(int irq);
@@ -281,40 +279,11 @@
 	via1[vT1CL] = MAC_CLOCK_LOW;
 	via1[vT1CH] = MAC_CLOCK_HIGH;
 
-	if (request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func))
+	if (request_irq(IRQ_MAC_TIMER_1, func, 0, "timer", func))
 		pr_err("Couldn't register %s interrupt\n", "timer");
 }
 
 /*
- * Register the interrupt dispatchers for VIA or RBV machines only.
- */
-
-void __init via_register_interrupts(void)
-{
-	if (via_alt_mapping) {
-		if (request_irq(IRQ_AUTO_1, via1_irq,
-				IRQ_FLG_LOCK|IRQ_FLG_FAST, "software",
-				(void *) via1))
-			pr_err("Couldn't register %s interrupt\n", "software");
-		if (request_irq(IRQ_AUTO_6, via1_irq,
-				IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
-				(void *) via1))
-			pr_err("Couldn't register %s interrupt\n", "via1");
-	} else {
-		if (request_irq(IRQ_AUTO_1, via1_irq,
-				IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
-				(void *) via1))
-			pr_err("Couldn't register %s interrupt\n", "via1");
-	}
-	if (request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
-			"via2", (void *) via2))
-		pr_err("Couldn't register %s interrupt\n", "via2");
-	if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq,
-			IRQ_FLG_LOCK|IRQ_FLG_FAST, "nubus", (void *) via2))
-		pr_err("Couldn't register %s interrupt\n", "nubus");
-}
-
-/*
  * Debugging dump, used in various places to see what's going on.
  */
 
@@ -446,48 +415,46 @@
  * via6522.c :-), disable/pending masks added.
  */
 
-irqreturn_t via1_irq(int irq, void *dev_id)
+void via1_irq(unsigned int irq, struct irq_desc *desc)
 {
 	int irq_num;
 	unsigned char irq_bit, events;
 
 	events = via1[vIFR] & via1[vIER] & 0x7F;
 	if (!events)
-		return IRQ_NONE;
+		return;
 
 	irq_num = VIA1_SOURCE_BASE;
 	irq_bit = 1;
 	do {
 		if (events & irq_bit) {
 			via1[vIFR] = irq_bit;
-			m68k_handle_int(irq_num);
+			generic_handle_irq(irq_num);
 		}
 		++irq_num;
 		irq_bit <<= 1;
 	} while (events >= irq_bit);
-	return IRQ_HANDLED;
 }
 
-irqreturn_t via2_irq(int irq, void *dev_id)
+static void via2_irq(unsigned int irq, struct irq_desc *desc)
 {
 	int irq_num;
 	unsigned char irq_bit, events;
 
 	events = via2[gIFR] & via2[gIER] & 0x7F;
 	if (!events)
-		return IRQ_NONE;
+		return;
 
 	irq_num = VIA2_SOURCE_BASE;
 	irq_bit = 1;
 	do {
 		if (events & irq_bit) {
 			via2[gIFR] = irq_bit | rbv_clear;
-			m68k_handle_int(irq_num);
+			generic_handle_irq(irq_num);
 		}
 		++irq_num;
 		irq_bit <<= 1;
 	} while (events >= irq_bit);
-	return IRQ_HANDLED;
 }
 
 /*
@@ -495,7 +462,7 @@
  * VIA2 dispatcher as a fast interrupt handler.
  */
 
-irqreturn_t via_nubus_irq(int irq, void *dev_id)
+void via_nubus_irq(unsigned int irq, struct irq_desc *desc)
 {
 	int slot_irq;
 	unsigned char slot_bit, events;
@@ -506,7 +473,7 @@
 	else
 		events &= ~via2[vDirA];
 	if (!events)
-		return IRQ_NONE;
+		return;
 
 	do {
 		slot_irq = IRQ_NUBUS_F;
@@ -514,7 +481,7 @@
 		do {
 			if (events & slot_bit) {
 				events &= ~slot_bit;
-				m68k_handle_int(slot_irq);
+				generic_handle_irq(slot_irq);
 			}
 			--slot_irq;
 			slot_bit >>= 1;
@@ -528,7 +495,24 @@
 		else
 			events &= ~via2[vDirA];
 	} while (events);
-	return IRQ_HANDLED;
+}
+
+/*
+ * Register the interrupt dispatchers for VIA or RBV machines only.
+ */
+
+void __init via_register_interrupts(void)
+{
+	if (via_alt_mapping) {
+		/* software interrupt */
+		irq_set_chained_handler(IRQ_AUTO_1, via1_irq);
+		/* via1 interrupt */
+		irq_set_chained_handler(IRQ_AUTO_6, via1_irq);
+	} else {
+		irq_set_chained_handler(IRQ_AUTO_1, via1_irq);
+	}
+	irq_set_chained_handler(IRQ_AUTO_2, via2_irq);
+	irq_set_chained_handler(IRQ_MAC_NUBUS, via_nubus_irq);
 }
 
 void via_irq_enable(int irq) {
diff -druN linux-libre-3.1-gnu/arch/m68k/Makefile linux-libre-3.2-gnu/arch/m68k/Makefile
--- linux-libre-3.1-gnu/arch/m68k/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,171 @@
+#
+# 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
+# Copyright (C) 2002,2011 Greg Ungerer <gerg@snapgear.com>
+#
+
 KBUILD_DEFCONFIG := multi_defconfig
 
+#
+#	Enable processor type. Ordering of these is important - we want to
+#	use the minimum processor type of the range we support. The logic
+#	for 680x0 will only allow use of the -m68060 or -m68040 if no other
+#	680x0 type is specified - and no option is specified for 68030 or
+#	68020. The other m68k/ColdFire types always specify some type of
+#	compiler cpu type flag.
+#
+ifndef CONFIG_M68040
+cpuflags-$(CONFIG_M68060)	:= -m68060
+endif
+ifndef CONFIG_M68060
+cpuflags-$(CONFIG_M68040)	:= -m68040
+endif
+cpuflags-$(CONFIG_M68030)	:=
+cpuflags-$(CONFIG_M68020)	:=
+cpuflags-$(CONFIG_M68360)	:= -m68332
+cpuflags-$(CONFIG_M68000)	:= -m68000
+cpuflags-$(CONFIG_M54xx)	:= $(call cc-option,-mcpu=5475,-m5200)
+cpuflags-$(CONFIG_M5407)	:= $(call cc-option,-mcpu=5407,-m5200)
+cpuflags-$(CONFIG_M532x)	:= $(call cc-option,-mcpu=532x,-m5307)
+cpuflags-$(CONFIG_M5307)	:= $(call cc-option,-mcpu=5307,-m5200)
+cpuflags-$(CONFIG_M528x)	:= $(call cc-option,-mcpu=528x,-m5307)
+cpuflags-$(CONFIG_M5275)	:= $(call cc-option,-mcpu=5275,-m5307)
+cpuflags-$(CONFIG_M5272)	:= $(call cc-option,-mcpu=5272,-m5307)
+cpuflags-$(CONFIG_M5271)	:= $(call cc-option,-mcpu=5271,-m5307)
+cpuflags-$(CONFIG_M523x)	:= $(call cc-option,-mcpu=523x,-m5307)
+cpuflags-$(CONFIG_M5249)	:= $(call cc-option,-mcpu=5249,-m5200)
+cpuflags-$(CONFIG_M520x)	:= $(call cc-option,-mcpu=5208,-m5200)
+cpuflags-$(CONFIG_M5206e)	:= $(call cc-option,-mcpu=5206e,-m5200)
+cpuflags-$(CONFIG_M5206)	:= $(call cc-option,-mcpu=5206,-m5200)
+
+KBUILD_AFLAGS += $(cpuflags-y)
+KBUILD_CFLAGS += $(cpuflags-y) -pipe
 ifdef CONFIG_MMU
-include $(srctree)/arch/m68k/Makefile_mm
+# without -fno-strength-reduce the 53c7xx.c driver fails ;-(
+KBUILD_CFLAGS += -fno-strength-reduce -ffixed-a2
 else
-include $(srctree)/arch/m68k/Makefile_no
+# we can use a m68k-linux-gcc toolchain with these in place
+KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
+KBUILD_CFLAGS += -D__uClinux__
+KBUILD_AFLAGS += -D__uClinux__
+endif
+
+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__
+
+
+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
+
+#
+# Select the assembler head startup code. Order is important. The default
+# head code is first, processor specific selections can override it after.
+#
+head-y				:= arch/m68k/kernel/head.o
+head-$(CONFIG_SUN3)		:= arch/m68k/kernel/sun3-head.o
+head-$(CONFIG_M68360)		:= arch/m68k/platform/68360/head.o
+head-$(CONFIG_M68000)		:= arch/m68k/platform/68328/head.o
+head-$(CONFIG_COLDFIRE)		:= arch/m68k/platform/coldfire/head.o
+
+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/
+core-$(CONFIG_M68360)		+= arch/m68k/platform/68360/
+core-$(CONFIG_M68000)		+= arch/m68k/platform/68328/
+core-$(CONFIG_M68EZ328)		+= arch/m68k/platform/68EZ328/
+core-$(CONFIG_M68VZ328)		+= arch/m68k/platform/68VZ328/
+core-$(CONFIG_COLDFIRE)		+= arch/m68k/platform/coldfire/
+core-$(CONFIG_M5206)		+= arch/m68k/platform/5206/
+core-$(CONFIG_M5206e)		+= arch/m68k/platform/5206/
+core-$(CONFIG_M520x)		+= arch/m68k/platform/520x/
+core-$(CONFIG_M523x)		+= arch/m68k/platform/523x/
+core-$(CONFIG_M5249)		+= arch/m68k/platform/5249/
+core-$(CONFIG_M527x)		+= arch/m68k/platform/527x/
+core-$(CONFIG_M5272)		+= arch/m68k/platform/5272/
+core-$(CONFIG_M528x)		+= arch/m68k/platform/528x/
+core-$(CONFIG_M5307)		+= arch/m68k/platform/5307/
+core-$(CONFIG_M532x)		+= arch/m68k/platform/532x/
+core-$(CONFIG_M5407)		+= arch/m68k/platform/5407/
+core-$(CONFIG_M54xx)		+= arch/m68k/platform/54xx/
+
+
+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-3.1-gnu/arch/m68k/Makefile_mm linux-libre-3.2-gnu/arch/m68k/Makefile_mm
--- linux-libre-3.1-gnu/arch/m68k/Makefile_mm	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/Makefile_mm	1969-12-31 19:00:00.000000000 -0500
@@ -1,121 +0,0 @@
-#
-# 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-3.1-gnu/arch/m68k/Makefile_no linux-libre-3.2-gnu/arch/m68k/Makefile_no
--- linux-libre-3.1-gnu/arch/m68k/Makefile_no	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/Makefile_no	1969-12-31 19:00:00.000000000 -0500
@@ -1,124 +0,0 @@
-#
-# 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)	:= 5206
-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-3.1-gnu/arch/m68k/mm/init_no.c linux-libre-3.2-gnu/arch/m68k/mm/init_no.c
--- linux-libre-3.1-gnu/arch/m68k/mm/init_no.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/mm/init_no.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 #include <linux/gfp.h>
 
 #include <asm/setup.h>
+#include <asm/sections.h>
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -44,9 +45,6 @@
  */
 void *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.
@@ -78,8 +76,6 @@
 {
 	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 */
@@ -95,9 +91,9 @@
 	/* 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;
+	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",
@@ -129,22 +125,21 @@
 {
 #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));
+	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) {
+	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++;
 	}
 	pr_notice("Freeing unused kernel memory: %luk freed (0x%x - 0x%x)\n",
-			(addr - PAGE_ALIGN((long) &__init_begin)) >> 10,
-			(int)(PAGE_ALIGN((unsigned long)(&__init_begin))),
+			(addr - PAGE_ALIGN((unsigned long) __init_begin)) >> 10,
+			(int)(PAGE_ALIGN((unsigned long) __init_begin)),
 			(int)(addr - PAGE_SIZE));
 #endif
 }
diff -druN linux-libre-3.1-gnu/arch/m68k/mvme147/config.c linux-libre-3.2-gnu/arch/m68k/mvme147/config.c
--- linux-libre-3.1-gnu/arch/m68k/mvme147/config.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/mvme147/config.c	2012-01-04 18:55:44.000000000 -0500
@@ -81,7 +81,7 @@
 
 void __init mvme147_init_IRQ(void)
 {
-	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+	m68k_setup_user_interrupt(VEC_USER, 192);
 }
 
 void __init config_mvme147(void)
@@ -114,8 +114,7 @@
 void mvme147_sched_init (irq_handler_t timer_routine)
 {
 	tick_handler = timer_routine;
-	if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQ_FLG_REPLACE,
-			"timer 1", NULL))
+	if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, 0, "timer 1", NULL))
 		pr_err("Couldn't register timer interrupt\n");
 
 	/* Init the clock with a value */
diff -druN linux-libre-3.1-gnu/arch/m68k/mvme16x/config.c linux-libre-3.2-gnu/arch/m68k/mvme16x/config.c
--- linux-libre-3.1-gnu/arch/m68k/mvme16x/config.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/mvme16x/config.c	2012-01-04 18:55:44.000000000 -0500
@@ -117,7 +117,7 @@
 
 static void __init mvme16x_init_IRQ (void)
 {
-	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+	m68k_setup_user_interrupt(VEC_USER, 192);
 }
 
 #define pcc2chip	((volatile u_char *)0xfff42000)
diff -druN linux-libre-3.1-gnu/arch/m68k/platform/520x/config.c linux-libre-3.2-gnu/arch/m68k/platform/520x/config.c
--- linux-libre-3.1-gnu/arch/m68k/platform/520x/config.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/platform/520x/config.c	2012-01-04 18:55:44.000000000 -0500
@@ -91,9 +91,9 @@
 	},
 };
 
-#define MCFQSPI_CS0    62
-#define MCFQSPI_CS1    63
-#define MCFQSPI_CS2    44
+#define MCFQSPI_CS0    46
+#define MCFQSPI_CS1    47
+#define MCFQSPI_CS2    27
 
 static int m520x_cs_setup(struct mcfqspi_cs_control *cs_control)
 {
diff -druN linux-libre-3.1-gnu/arch/m68k/platform/520x/gpio.c linux-libre-3.2-gnu/arch/m68k/platform/520x/gpio.c
--- linux-libre-3.1-gnu/arch/m68k/platform/520x/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/platform/520x/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,42 +38,6 @@
 	},
 	{
 		.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,
@@ -81,7 +45,7 @@
 			.direction_output	= mcf_gpio_direction_output,
 			.get			= mcf_gpio_get_value,
 			.set			= mcf_gpio_set_value_fast,
-			.base			= 25,
+			.base			= 9,
 			.ngpio			= 3,
 		},
 		.pddr				= (void __iomem *) MCFGPIO_PDDR_CS,
@@ -99,7 +63,7 @@
 			.direction_output	= mcf_gpio_direction_output,
 			.get			= mcf_gpio_get_value,
 			.set			= mcf_gpio_set_value_fast,
-			.base			= 32,
+			.base			= 16,
 			.ngpio			= 4,
 		},
 		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECI2C,
@@ -117,7 +81,7 @@
 			.direction_output	= mcf_gpio_direction_output,
 			.get			= mcf_gpio_get_value,
 			.set			= mcf_gpio_set_value_fast,
-			.base			= 40,
+			.base			= 24,
 			.ngpio			= 4,
 		},
 		.pddr				= (void __iomem *) MCFGPIO_PDDR_QSPI,
@@ -135,7 +99,7 @@
 			.direction_output	= mcf_gpio_direction_output,
 			.get			= mcf_gpio_get_value,
 			.set			= mcf_gpio_set_value_fast,
-			.base			= 48,
+			.base			= 32,
 			.ngpio			= 4,
 		},
 		.pddr				= (void __iomem *) MCFGPIO_PDDR_TIMER,
@@ -153,7 +117,7 @@
 			.direction_output	= mcf_gpio_direction_output,
 			.get			= mcf_gpio_get_value,
 			.set			= mcf_gpio_set_value_fast,
-			.base			= 56,
+			.base			= 40,
 			.ngpio			= 8,
 		},
 		.pddr				= (void __iomem *) MCFGPIO_PDDR_UART,
@@ -171,7 +135,7 @@
 			.direction_output	= mcf_gpio_direction_output,
 			.get			= mcf_gpio_get_value,
 			.set			= mcf_gpio_set_value_fast,
-			.base			= 64,
+			.base			= 48,
 			.ngpio			= 8,
 		},
 		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECH,
@@ -189,7 +153,7 @@
 			.direction_output	= mcf_gpio_direction_output,
 			.get			= mcf_gpio_get_value,
 			.set			= mcf_gpio_set_value_fast,
-			.base			= 72,
+			.base			= 56,
 			.ngpio			= 8,
 		},
 		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECL,
diff -druN linux-libre-3.1-gnu/arch/m68k/platform/68328/entry.S linux-libre-3.2-gnu/arch/m68k/platform/68328/entry.S
--- linux-libre-3.1-gnu/arch/m68k/platform/68328/entry.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/platform/68328/entry.S	2012-01-04 18:55:44.000000000 -0500
@@ -67,7 +67,7 @@
 	jra	ret_from_exception
 
 ENTRY(system_call)
-	SAVE_ALL
+	SAVE_ALL_SYS
 
 	/* save top of frame*/
 	pea	%sp@
@@ -129,7 +129,7 @@
  * This is the main interrupt handler, responsible for calling process_int()
  */
 inthandler1:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and	#0x3ff, %d0
 
@@ -140,7 +140,7 @@
 	bra	ret_from_interrupt
 
 inthandler2:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and	#0x3ff, %d0
 
@@ -151,7 +151,7 @@
 	bra	ret_from_interrupt
 
 inthandler3:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and	#0x3ff, %d0
 
@@ -162,7 +162,7 @@
 	bra	ret_from_interrupt
 
 inthandler4:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and	#0x3ff, %d0
 
@@ -173,7 +173,7 @@
 	bra	ret_from_interrupt
 
 inthandler5:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and	#0x3ff, %d0
 
@@ -184,7 +184,7 @@
 	bra	ret_from_interrupt
 
 inthandler6:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and	#0x3ff, %d0
 
@@ -195,7 +195,7 @@
 	bra	ret_from_interrupt
 
 inthandler7:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and	#0x3ff, %d0
 
@@ -206,7 +206,7 @@
 	bra	ret_from_interrupt
 
 inthandler:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and	#0x3ff, %d0
 
diff -druN linux-libre-3.1-gnu/arch/m68k/platform/68328/Makefile linux-libre-3.2-gnu/arch/m68k/platform/68328/Makefile
--- linux-libre-3.1-gnu/arch/m68k/platform/68328/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/platform/68328/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,10 @@
 # Makefile for arch/m68knommu/platform/68328.
 #
 
-head-y			= head-$(MODEL).o
+model-y			  := ram
+model-$(CONFIG_ROMKERNEL) := rom
+
+head-y			= head-$(model-y).o
 head-$(CONFIG_PILOT)	= head-pilot.o
 head-$(CONFIG_DRAGEN2)	= head-de2.o
 
diff -druN linux-libre-3.1-gnu/arch/m68k/platform/68360/entry.S linux-libre-3.2-gnu/arch/m68k/platform/68360/entry.S
--- linux-libre-3.1-gnu/arch/m68k/platform/68360/entry.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/platform/68360/entry.S	2012-01-04 18:55:44.000000000 -0500
@@ -63,7 +63,7 @@
 	jra	ret_from_exception
 
 ENTRY(system_call)
-	SAVE_ALL
+	SAVE_ALL_SYS
 
 	/* save top of frame*/
 	pea	%sp@
@@ -125,7 +125,7 @@
  * This is the main interrupt handler, responsible for calling do_IRQ()
  */
 inthandler:
-	SAVE_ALL
+	SAVE_ALL_INT
 	movew	%sp@(PT_OFF_FORMATVEC), %d0
 	and.l	#0x3ff, %d0
 	lsr.l   #0x02,  %d0
diff -druN linux-libre-3.1-gnu/arch/m68k/platform/68360/Makefile linux-libre-3.2-gnu/arch/m68k/platform/68360/Makefile
--- linux-libre-3.1-gnu/arch/m68k/platform/68360/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/platform/68360/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,10 +1,12 @@
 #
 # Makefile for arch/m68knommu/platform/68360.
 #
+model-y			  := ram
+model-$(CONFIG_ROMKERNEL) := rom
 
 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
+$(obj)/head.o: $(obj)/head-$(model-y).o
+	ln -sf head-$(model-y).o $(obj)/head.o
diff -druN linux-libre-3.1-gnu/arch/m68k/platform/coldfire/entry.S linux-libre-3.2-gnu/arch/m68k/platform/coldfire/entry.S
--- linux-libre-3.1-gnu/arch/m68k/platform/coldfire/entry.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/platform/coldfire/entry.S	2012-01-04 18:55:44.000000000 -0500
@@ -61,7 +61,7 @@
 	bra	1f
 
 ENTRY(system_call)
-	SAVE_ALL
+	SAVE_ALL_SYS
 	move	#0x2000,%sr		/* enable intrs again */
 
 	cmpl	#NR_syscalls,%d0
@@ -165,9 +165,7 @@
  * 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)
+	SAVE_ALL_INT
 
 	movew	%sp@(PT_OFF_FORMATVEC),%d0 /* put exception # in d0 */
 	andl	#0x03fc,%d0		/* mask out vector only */
diff -druN linux-libre-3.1-gnu/arch/m68k/q40/q40ints.c linux-libre-3.2-gnu/arch/m68k/q40/q40ints.c
--- linux-libre-3.1-gnu/arch/m68k/q40/q40ints.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/q40/q40ints.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,10 +15,10 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
-#include <asm/irq.h>
 #include <asm/traps.h>
 
 #include <asm/q40_master.h>
@@ -35,35 +35,36 @@
 */
 
 static void q40_irq_handler(unsigned int, struct pt_regs *fp);
-static void q40_enable_irq(unsigned int);
-static void q40_disable_irq(unsigned int);
+static void q40_irq_enable(struct irq_data *data);
+static void q40_irq_disable(struct irq_data *data);
 
 unsigned short q40_ablecount[35];
 unsigned short q40_state[35];
 
-static int q40_irq_startup(unsigned int irq)
+static unsigned int q40_irq_startup(struct irq_data *data)
 {
+	unsigned int irq = data->irq;
+
 	/* test for ISA ints not implemented by HW */
 	switch (irq) {
 	case 1: case 2: case 8: case 9:
 	case 11: case 12: case 13:
 		printk("%s: ISA IRQ %d not implemented by HW\n", __func__, irq);
-		return -ENXIO;
+		/* FIXME return -ENXIO; */
 	}
 	return 0;
 }
 
-static void q40_irq_shutdown(unsigned int irq)
+static void q40_irq_shutdown(struct irq_data *data)
 {
 }
 
-static struct irq_controller q40_irq_controller = {
+static struct irq_chip q40_irq_chip = {
 	.name		= "q40",
-	.lock		= __SPIN_LOCK_UNLOCKED(q40_irq_controller.lock),
-	.startup	= q40_irq_startup,
-	.shutdown	= q40_irq_shutdown,
-	.enable		= q40_enable_irq,
-	.disable	= q40_disable_irq,
+	.irq_startup	= q40_irq_startup,
+	.irq_shutdown	= q40_irq_shutdown,
+	.irq_enable	= q40_irq_enable,
+	.irq_disable	= q40_irq_disable,
 };
 
 /*
@@ -81,13 +82,14 @@
 
 void __init q40_init_IRQ(void)
 {
-	m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX);
+	m68k_setup_irq_controller(&q40_irq_chip, handle_simple_irq, 1,
+				  Q40_IRQ_MAX);
 
 	/* setup handler for ISA ints */
 	m68k_setup_auto_interrupt(q40_irq_handler);
 
-	m68k_irq_startup(IRQ_AUTO_2);
-	m68k_irq_startup(IRQ_AUTO_4);
+	m68k_irq_startup_irq(IRQ_AUTO_2);
+	m68k_irq_startup_irq(IRQ_AUTO_4);
 
 	/* now enable some ints.. */
 	master_outb(1, EXT_ENABLE_REG);  /* ISA IRQ 5-15 */
@@ -218,11 +220,11 @@
 	switch (irq) {
 	case 4:
 	case 6:
-		__m68k_handle_int(Q40_IRQ_SAMPLE, fp);
+		do_IRQ(Q40_IRQ_SAMPLE, fp);
 		return;
 	}
 	if (mir & Q40_IRQ_FRAME_MASK) {
-		__m68k_handle_int(Q40_IRQ_FRAME, fp);
+		do_IRQ(Q40_IRQ_FRAME, fp);
 		master_outb(-1, FRAME_CLEAR_REG);
 	}
 	if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) {
@@ -257,7 +259,7 @@
 					goto iirq;
 				}
 				q40_state[irq] |= IRQ_INPROGRESS;
-				__m68k_handle_int(irq, fp);
+				do_IRQ(irq, fp);
 				q40_state[irq] &= ~IRQ_INPROGRESS;
 
 				/* naively enable everything, if that fails than    */
@@ -288,25 +290,29 @@
 	mir = master_inb(IIRQ_REG);
 	/* should test whether keyboard irq is really enabled, doing it in defhand */
 	if (mir & Q40_IRQ_KEYB_MASK)
-		__m68k_handle_int(Q40_IRQ_KEYBOARD, fp);
+		do_IRQ(Q40_IRQ_KEYBOARD, fp);
 
 	return;
 }
 
-void q40_enable_irq(unsigned int irq)
+void q40_irq_enable(struct irq_data *data)
 {
+	unsigned int irq = data->irq;
+
 	if (irq >= 5 && irq <= 15) {
 		mext_disabled--;
 		if (mext_disabled > 0)
-			printk("q40_enable_irq : nested disable/enable\n");
+			printk("q40_irq_enable : nested disable/enable\n");
 		if (mext_disabled == 0)
 			master_outb(1, EXT_ENABLE_REG);
 	}
 }
 
 
-void q40_disable_irq(unsigned int irq)
+void q40_irq_disable(struct irq_data *data)
 {
+	unsigned int irq = data->irq;
+
 	/* disable ISA iqs : only do something if the driver has been
 	 * verified to be Q40 "compatible" - right now IDE, NE2K
 	 * Any driver should not attempt to sleep across disable_irq !!
@@ -319,13 +325,3 @@
 			printk("disable_irq nesting count %d\n",mext_disabled);
 	}
 }
-
-unsigned long q40_probe_irq_on(void)
-{
-	printk("irq probing not working - reconfigure the driver to avoid this\n");
-	return -1;
-}
-int q40_probe_irq_off(unsigned long irqs)
-{
-	return -1;
-}
diff -druN linux-libre-3.1-gnu/arch/m68k/q40/README linux-libre-3.2-gnu/arch/m68k/q40/README
--- linux-libre-3.1-gnu/arch/m68k/q40/README	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/q40/README	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,7 @@
 		char/joystick/*		# most of this should work, not
 				        # in default config.in
 	        block/q40ide.c		# startup for ide
-		      ide*		# see Documentation/ide.txt
+		      ide*		# see Documentation/ide/ide.txt
 		      floppy.c		# normal PC driver, DMA emu in asm/floppy.h
 					# and arch/m68k/kernel/entry.S
 					# see drivers/block/README.fd
diff -druN linux-libre-3.1-gnu/arch/m68k/sun3/sun3ints.c linux-libre-3.2-gnu/arch/m68k/sun3/sun3ints.c
--- linux-libre-3.1-gnu/arch/m68k/sun3/sun3ints.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/m68k/sun3/sun3ints.c	2012-01-04 18:55:44.000000000 -0500
@@ -51,25 +51,29 @@
 
 static irqreturn_t sun3_int7(int irq, void *dev_id)
 {
-	*sun3_intreg |=  (1 << irq);
-	if (!(kstat_cpu(0).irqs[irq] % 2000))
-		sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 16000) / 2000]);
+	unsigned int cnt;
+
+	cnt = kstat_irqs_cpu(irq, 0);
+	if (!(cnt % 2000))
+		sun3_leds(led_pattern[cnt % 16000 / 2000]);
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t sun3_int5(int irq, void *dev_id)
 {
+	unsigned int cnt;
+
 #ifdef CONFIG_SUN3
 	intersil_clear();
 #endif
-        *sun3_intreg |=  (1 << irq);
 #ifdef CONFIG_SUN3
 	intersil_clear();
 #endif
 	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]);
+	cnt = kstat_irqs_cpu(irq, 0);
+	if (!(cnt % 20))
+		sun3_leds(led_pattern[cnt % 160 / 20]);
 	return IRQ_HANDLED;
 }
 
@@ -79,29 +83,33 @@
 	return IRQ_HANDLED;
 }
 
-static void sun3_inthandle(unsigned int irq, struct pt_regs *fp)
+static void sun3_irq_enable(struct irq_data *data)
 {
-        *sun3_intreg &= ~(1 << irq);
+    sun3_enable_irq(data->irq);
+};
 
-	__m68k_handle_int(irq, fp);
-}
+static void sun3_irq_disable(struct irq_data *data)
+{
+    sun3_disable_irq(data->irq);
+};
 
-static struct irq_controller sun3_irq_controller = {
+static struct irq_chip sun3_irq_chip = {
 	.name		= "sun3",
-	.lock		= __SPIN_LOCK_UNLOCKED(sun3_irq_controller.lock),
-	.startup	= m68k_irq_startup,
-	.shutdown	= m68k_irq_shutdown,
-	.enable		= sun3_enable_irq,
-	.disable	= sun3_disable_irq,
+	.irq_startup	= m68k_irq_startup,
+	.irq_shutdown	= m68k_irq_shutdown,
+	.irq_enable	= sun3_irq_enable,
+	.irq_disable	= sun3_irq_disable,
+	.irq_mask	= sun3_irq_disable,
+	.irq_unmask	= sun3_irq_enable,
 };
 
 void __init sun3_init_IRQ(void)
 {
 	*sun3_intreg = 1;
 
-	m68k_setup_auto_interrupt(sun3_inthandle);
-	m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7);
-	m68k_setup_user_interrupt(VEC_USER, 128, NULL);
+	m68k_setup_irq_controller(&sun3_irq_chip, handle_level_irq, IRQ_AUTO_1,
+				  7);
+	m68k_setup_user_interrupt(VEC_USER, 128);
 
 	if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL))
 		pr_err("Couldn't register %s interrupt\n", "int5");
diff -druN linux-libre-3.1-gnu/arch/microblaze/include/asm/dma-mapping.h linux-libre-3.2-gnu/arch/microblaze/include/asm/dma-mapping.h
--- linux-libre-3.1-gnu/arch/microblaze/include/asm/dma-mapping.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/include/asm/dma-mapping.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
 #define _ASM_MICROBLAZE_DMA_MAPPING_H
 
 /*
- * See Documentation/PCI/PCI-DMA-mapping.txt and
+ * See Documentation/DMA-API-HOWTO.txt and
  * Documentation/DMA-API.txt for documentation.
  */
 
@@ -28,12 +28,12 @@
 #include <linux/dma-attrs.h>
 #include <asm/io.h>
 #include <asm-generic/dma-coherent.h>
+#include <asm/cacheflush.h>
 
 #define DMA_ERROR_CODE		(~(dma_addr_t)0x0)
 
 #define __dma_alloc_coherent(dev, gfp, size, handle)	NULL
 #define __dma_free_coherent(size, addr)		((void)0)
-#define __dma_sync(addr, size, rw)		((void)0)
 
 static inline unsigned long device_to_mask(struct device *dev)
 {
@@ -95,6 +95,22 @@
 
 #include <asm-generic/dma-mapping-common.h>
 
+static inline void __dma_sync(unsigned long paddr,
+			      size_t size, enum dma_data_direction direction)
+{
+	switch (direction) {
+	case DMA_TO_DEVICE:
+	case DMA_BIDIRECTIONAL:
+		flush_dcache_range(paddr, paddr + size);
+		break;
+	case DMA_FROM_DEVICE:
+		invalidate_dcache_range(paddr, paddr + size);
+		break;
+	default:
+		BUG();
+	}
+}
+
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
@@ -135,7 +151,7 @@
 		enum dma_data_direction direction)
 {
 	BUG_ON(direction == DMA_NONE);
-	__dma_sync(vaddr, size, (int)direction);
+	__dma_sync(virt_to_phys(vaddr), size, (int)direction);
 }
 
 #endif	/* _ASM_MICROBLAZE_DMA_MAPPING_H */
diff -druN linux-libre-3.1-gnu/arch/microblaze/include/asm/elf.h linux-libre-3.2-gnu/arch/microblaze/include/asm/elf.h
--- linux-libre-3.1-gnu/arch/microblaze/include/asm/elf.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/include/asm/elf.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,13 +16,15 @@
  * I've snaffled the value from the microblaze binutils source code
  * /binutils/microblaze/include/elf/microblaze.h
  */
-#define EM_XILINX_MICROBLAZE	0xbaab
-#define ELF_ARCH		EM_XILINX_MICROBLAZE
+#define EM_MICROBLAZE		189
+#define EM_MICROBLAZE_OLD	0xbaab
+#define ELF_ARCH		EM_MICROBLAZE
 
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
-#define elf_check_arch(x)	((x)->e_machine == EM_XILINX_MICROBLAZE)
+#define elf_check_arch(x)	((x)->e_machine == EM_MICROBLAZE \
+				 || (x)->e_machine == EM_MICROBLAZE_OLD)
 
 /*
  * These are used to set parameters in the core dumps.
diff -druN linux-libre-3.1-gnu/arch/microblaze/include/asm/namei.h linux-libre-3.2-gnu/arch/microblaze/include/asm/namei.h
--- linux-libre-3.1-gnu/arch/microblaze/include/asm/namei.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/include/asm/namei.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_NAMEI_H
-#define _ASM_MICROBLAZE_NAMEI_H
-
-#ifdef __KERNEL__
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-#define __emul_prefix() NULL
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_MICROBLAZE_NAMEI_H */
diff -druN linux-libre-3.1-gnu/arch/microblaze/include/asm/system.h linux-libre-3.2-gnu/arch/microblaze/include/asm/system.h
--- linux-libre-3.1-gnu/arch/microblaze/include/asm/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/include/asm/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,8 +17,6 @@
 #include <asm-generic/cmpxchg.h>
 #include <asm-generic/cmpxchg-local.h>
 
-#define __ARCH_WANT_INTERRUPTS_ON_CTXSW
-
 struct task_struct;
 struct thread_info;
 
@@ -96,11 +94,4 @@
 
 #define arch_align_stack(x) (x)
 
-/*
- * MicroBlaze doesn't handle unaligned accesses in hardware.
- *
- * Based on this we force the IP header alignment in network drivers.
- */
-#define NET_IP_ALIGN	2
-
 #endif /* _ASM_MICROBLAZE_SYSTEM_H */
diff -druN linux-libre-3.1-gnu/arch/microblaze/include/asm/uaccess.h linux-libre-3.2-gnu/arch/microblaze/include/asm/uaccess.h
--- linux-libre-3.1-gnu/arch/microblaze/include/asm/uaccess.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/include/asm/uaccess.h	2012-01-04 18:55:44.000000000 -0500
@@ -95,7 +95,7 @@
  *  - "addr", "addr + size" and "size" are all below the limit
  */
 #define access_ok(type, addr, size) \
-	(get_fs().seg > (((unsigned long)(addr)) | \
+	(get_fs().seg >= (((unsigned long)(addr)) | \
 		(size) | ((unsigned long)(addr) + (size))))
 
 /* || printk("access_ok failed for %s at 0x%08lx (size %d), seg 0x%08x\n",
diff -druN linux-libre-3.1-gnu/arch/microblaze/kernel/cpu/cpuinfo.c linux-libre-3.2-gnu/arch/microblaze/kernel/cpu/cpuinfo.c
--- linux-libre-3.1-gnu/arch/microblaze/kernel/cpu/cpuinfo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/kernel/cpu/cpuinfo.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 	{"8.00.a", 0x12},
 	{"8.00.b", 0x13},
 	{"8.10.a", 0x14},
+	{"8.20.a", 0x15},
 	{NULL, 0},
 };
 
diff -druN linux-libre-3.1-gnu/arch/microblaze/kernel/dma.c linux-libre-3.2-gnu/arch/microblaze/kernel/dma.c
--- linux-libre-3.1-gnu/arch/microblaze/kernel/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/kernel/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,8 +10,8 @@
 #include <linux/dma-mapping.h>
 #include <linux/gfp.h>
 #include <linux/dma-debug.h>
+#include <linux/export.h>
 #include <asm/bug.h>
-#include <asm/cacheflush.h>
 
 /*
  * Generic direct DMA implementation
@@ -21,21 +21,6 @@
  * can set archdata.dma_data to an unsigned long holding the offset. By
  * default the offset is PCI_DRAM_OFFSET.
  */
-static inline void __dma_sync_page(unsigned long paddr, unsigned long offset,
-				size_t size, enum dma_data_direction direction)
-{
-	switch (direction) {
-	case DMA_TO_DEVICE:
-	case DMA_BIDIRECTIONAL:
-		flush_dcache_range(paddr + offset, paddr + offset + size);
-		break;
-	case DMA_FROM_DEVICE:
-		invalidate_dcache_range(paddr + offset, paddr + offset + size);
-		break;
-	default:
-		BUG();
-	}
-}
 
 static unsigned long get_dma_direct_offset(struct device *dev)
 {
@@ -91,7 +76,7 @@
 	/* FIXME this part of code is untested */
 	for_each_sg(sgl, sg, nents, i) {
 		sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev);
-		__dma_sync_page(page_to_phys(sg_page(sg)), sg->offset,
+		__dma_sync(page_to_phys(sg_page(sg)) + sg->offset,
 							sg->length, direction);
 	}
 
@@ -116,7 +101,7 @@
 					     enum dma_data_direction direction,
 					     struct dma_attrs *attrs)
 {
-	__dma_sync_page(page_to_phys(page), offset, size, direction);
+	__dma_sync(page_to_phys(page) + offset, size, direction);
 	return page_to_phys(page) + offset + get_dma_direct_offset(dev);
 }
 
@@ -131,7 +116,63 @@
  * phys_to_virt is here because in __dma_sync_page is __virt_to_phys and
  * dma_address is physical address
  */
-	__dma_sync_page(dma_address, 0 , size, direction);
+	__dma_sync(dma_address, size, direction);
+}
+
+static inline void
+dma_direct_sync_single_for_cpu(struct device *dev,
+			       dma_addr_t dma_handle, size_t size,
+			       enum dma_data_direction direction)
+{
+	/*
+	 * It's pointless to flush the cache as the memory segment
+	 * is given to the CPU
+	 */
+
+	if (direction == DMA_FROM_DEVICE)
+		__dma_sync(dma_handle, size, direction);
+}
+
+static inline void
+dma_direct_sync_single_for_device(struct device *dev,
+				  dma_addr_t dma_handle, size_t size,
+				  enum dma_data_direction direction)
+{
+	/*
+	 * It's pointless to invalidate the cache if the device isn't
+	 * supposed to write to the relevant region
+	 */
+
+	if (direction == DMA_TO_DEVICE)
+		__dma_sync(dma_handle, size, direction);
+}
+
+static inline void
+dma_direct_sync_sg_for_cpu(struct device *dev,
+			   struct scatterlist *sgl, int nents,
+			   enum dma_data_direction direction)
+{
+	struct scatterlist *sg;
+	int i;
+
+	/* FIXME this part of code is untested */
+	if (direction == DMA_FROM_DEVICE)
+		for_each_sg(sgl, sg, nents, i)
+			__dma_sync(sg->dma_address, sg->length, direction);
+}
+
+static inline void
+dma_direct_sync_sg_for_device(struct device *dev,
+			      struct scatterlist *sgl, int nents,
+			      enum dma_data_direction direction)
+{
+	struct scatterlist *sg;
+	int i;
+
+	/* FIXME this part of code is untested */
+	if (direction == DMA_TO_DEVICE)
+		for_each_sg(sgl, sg, nents, i)
+			__dma_sync(sg->dma_address, sg->length, direction);
 }
 
 struct dma_map_ops dma_direct_ops = {
@@ -142,6 +183,10 @@
 	.dma_supported	= dma_direct_dma_supported,
 	.map_page	= dma_direct_map_page,
 	.unmap_page	= dma_direct_unmap_page,
+	.sync_single_for_cpu		= dma_direct_sync_single_for_cpu,
+	.sync_single_for_device		= dma_direct_sync_single_for_device,
+	.sync_sg_for_cpu		= dma_direct_sync_sg_for_cpu,
+	.sync_sg_for_device		= dma_direct_sync_sg_for_device,
 };
 EXPORT_SYMBOL(dma_direct_ops);
 
diff -druN linux-libre-3.1-gnu/arch/microblaze/kernel/exceptions.c linux-libre-3.2-gnu/arch/microblaze/kernel/exceptions.c
--- linux-libre-3.1-gnu/arch/microblaze/kernel/exceptions.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/kernel/exceptions.c	2012-01-04 18:55:44.000000000 -0500
@@ -119,7 +119,7 @@
 	case MICROBLAZE_DIV_ZERO_EXCEPTION:
 		if (user_mode(regs)) {
 			pr_debug("Divide by zero exception in user mode\n");
-			_exception(SIGILL, regs, FPE_INTDIV, addr);
+			_exception(SIGFPE, regs, FPE_INTDIV, addr);
 			return;
 		}
 		printk(KERN_WARNING "Divide by zero exception " \
diff -druN linux-libre-3.1-gnu/arch/microblaze/kernel/irq.c linux-libre-3.2-gnu/arch/microblaze/kernel/irq.c
--- linux-libre-3.1-gnu/arch/microblaze/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/irq.h>
 #include <linux/of_irq.h>
+#include <linux/export.h>
 
 #include <asm/prom.h>
 
diff -druN linux-libre-3.1-gnu/arch/microblaze/kernel/process.c linux-libre-3.2-gnu/arch/microblaze/kernel/process.c
--- linux-libre-3.1-gnu/arch/microblaze/kernel/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/kernel/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -179,6 +179,7 @@
 
 	ti->cpu_context.msr = (childregs->msr|MSR_VM);
 	ti->cpu_context.msr &= ~MSR_UMS; /* switch_to to kernel mode */
+	ti->cpu_context.msr &= ~MSR_IE;
 #endif
 	ti->cpu_context.r15 = (unsigned long)ret_from_fork - 8;
 
diff -druN linux-libre-3.1-gnu/arch/microblaze/kernel/ptrace.c linux-libre-3.2-gnu/arch/microblaze/kernel/ptrace.c
--- linux-libre-3.1-gnu/arch/microblaze/kernel/ptrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/kernel/ptrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -148,7 +148,7 @@
 		ret = -1L;
 
 	if (unlikely(current->audit_context))
-		audit_syscall_entry(EM_XILINX_MICROBLAZE, regs->r12,
+		audit_syscall_entry(EM_MICROBLAZE, regs->r12,
 				    regs->r5, regs->r6,
 				    regs->r7, regs->r8);
 
diff -druN linux-libre-3.1-gnu/arch/microblaze/kernel/timer.c linux-libre-3.2-gnu/arch/microblaze/kernel/timer.c
--- linux-libre-3.1-gnu/arch/microblaze/kernel/timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/kernel/timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -308,7 +308,8 @@
 {
 	if (timer_initialized) {
 		struct clocksource *cs = &clocksource_microblaze;
-		cycle_t cyc = cnt32_to_63(cs->read(NULL));
+
+		cycle_t cyc = cnt32_to_63(cs->read(NULL)) & LLONG_MAX;
 		return clocksource_cyc2ns(cyc, cs->mult, cs->shift);
 	}
 	return 0;
diff -druN linux-libre-3.1-gnu/arch/microblaze/lib/Makefile linux-libre-3.2-gnu/arch/microblaze/lib/Makefile
--- linux-libre-3.1-gnu/arch/microblaze/lib/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/lib/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -25,5 +25,6 @@
 lib-y += modsi3.o
 lib-y += muldi3.o
 lib-y += mulsi3.o
+lib-y += ucmpdi2.o
 lib-y += udivsi3.o
 lib-y += umodsi3.o
diff -druN linux-libre-3.1-gnu/arch/microblaze/lib/uaccess_old.S linux-libre-3.2-gnu/arch/microblaze/lib/uaccess_old.S
--- linux-libre-3.1-gnu/arch/microblaze/lib/uaccess_old.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/lib/uaccess_old.S	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 
 #include <linux/errno.h>
 #include <linux/linkage.h>
+#include <asm/page.h>
 
 /*
  * int __strncpy_user(char *to, char *from, int len);
@@ -33,8 +34,8 @@
 	 * r3 - temp count
 	 * r4 - temp val
 	 */
+	beqid	r7,3f
 	addik	r3,r7,0		/* temp_count = len */
-	beqi	r3,3f
 1:
 	lbu	r4,r6,r0
 	sb	r4,r5,r0
@@ -76,8 +77,8 @@
 .type  __strnlen_user, @function
 .align 4;
 __strnlen_user:
+	beqid	r6,3f
 	addik	r3,r6,0
-	beqi	r3,3f
 1:
 	lbu	r4,r5,r0
 	beqid	r4,2f		/* break on NUL */
@@ -102,6 +103,49 @@
 	.section	__ex_table,"a"
 	.word	1b,4b
 
+/* Loop unrolling for __copy_tofrom_user */
+#define COPY(offset)	\
+1:	lwi	r4 , r6, 0x0000 + offset;	\
+2:	lwi	r19, r6, 0x0004 + offset;	\
+3:	lwi	r20, r6, 0x0008 + offset;	\
+4:	lwi	r21, r6, 0x000C + offset;	\
+5:	lwi	r22, r6, 0x0010 + offset;	\
+6:	lwi	r23, r6, 0x0014 + offset;	\
+7:	lwi	r24, r6, 0x0018 + offset;	\
+8:	lwi	r25, r6, 0x001C + offset;	\
+9:	swi	r4 , r5, 0x0000 + offset;	\
+10:	swi	r19, r5, 0x0004 + offset;	\
+11:	swi	r20, r5, 0x0008 + offset;	\
+12:	swi	r21, r5, 0x000C + offset;	\
+13:	swi	r22, r5, 0x0010 + offset;	\
+14:	swi	r23, r5, 0x0014 + offset;	\
+15:	swi	r24, r5, 0x0018 + offset;	\
+16:	swi	r25, r5, 0x001C + offset;	\
+	.section __ex_table,"a";		\
+	.word	1b, 0f;				\
+	.word	2b, 0f;				\
+	.word	3b, 0f;				\
+	.word	4b, 0f;				\
+	.word	5b, 0f;				\
+	.word	6b, 0f;				\
+	.word	7b, 0f;				\
+	.word	8b, 0f;				\
+	.word	9b, 0f;				\
+	.word	10b, 0f;			\
+	.word	11b, 0f;			\
+	.word	12b, 0f;			\
+	.word	13b, 0f;			\
+	.word	14b, 0f;			\
+	.word	15b, 0f;			\
+	.word	16b, 0f;			\
+	.text
+
+#define COPY_80(offset)	\
+	COPY(0x00 + offset);\
+	COPY(0x20 + offset);\
+	COPY(0x40 + offset);\
+	COPY(0x60 + offset);
+
 /*
  * int __copy_tofrom_user(char *to, char *from, int len)
  * Return:
@@ -119,34 +163,79 @@
 	 * r7, r3 - count
 	 * r4 - tempval
 	 */
-	beqid	r7, 3f /* zero size is not likely */
-	andi	r3, r7, 0x3 /* filter add count */
-	bneid	r3, 4f /* if is odd value then byte copying */
+	beqid	r7, 0f /* zero size is not likely */
 	or	r3, r5, r6 /* find if is any to/from unaligned */
-	andi	r3, r3, 0x3 /* mask unaligned */
-	bneid	r3, 1f /* it is unaligned -> then jump */
+	or	r3, r3, r7 /* find if count is unaligned */
+	andi	r3, r3, 0x3 /* mask last 3 bits */
+	bneid	r3, bu1 /* if r3 is not zero then byte copying */
 	or	r3, r0, r0
 
-/* at least one 4 byte copy */
-5:	lw	r4, r6, r3
-6:	sw	r4, r5, r3
+	rsubi	r3, r7, PAGE_SIZE /* detect PAGE_SIZE */
+	beqid	r3, page;
+	or	r3, r0, r0
+
+w1:	lw	r4, r6, r3 /* at least one 4 byte copy */
+w2:	sw	r4, r5, r3
 	addik	r7, r7, -4
-	bneid	r7, 5b
+	bneid	r7, w1
 	addik	r3, r3, 4
 	addik	r3, r7, 0
 	rtsd	r15, 8
 	nop
-4:	or	r3, r0, r0
-1:	lbu	r4,r6,r3
-2:	sb	r4,r5,r3
+
+	.section	__ex_table,"a"
+	.word	w1, 0f;
+	.word	w2, 0f;
+	.text
+
+.align 4 /* Alignment is important to keep icache happy */
+page:	/* Create room on stack and save registers for storign values */
+	addik   r1, r1, -32
+	swi	r19, r1, 4
+	swi	r20, r1, 8
+	swi	r21, r1, 12
+	swi	r22, r1, 16
+	swi	r23, r1, 20
+	swi	r24, r1, 24
+	swi	r25, r1, 28
+loop:	/* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */
+	/* Loop unrolling to get performance boost */
+	COPY_80(0x000);
+	COPY_80(0x080);
+	COPY_80(0x100);
+	COPY_80(0x180);
+	/* copy loop */
+	addik	r6, r6, 0x200
+	addik	r7, r7, -0x200
+	bneid	r7, loop
+	addik	r5, r5, 0x200
+	/* Restore register content */
+	lwi	r19, r1, 4
+	lwi	r20, r1, 8
+	lwi	r21, r1, 12
+	lwi	r22, r1, 16
+	lwi	r23, r1, 20
+	lwi	r24, r1, 24
+	lwi	r25, r1, 28
+	addik   r1, r1, 32
+	/* return back */
+	addik	r3, r7, 0
+	rtsd	r15, 8
+	nop
+
+.align 4 /* Alignment is important to keep icache happy */
+bu1:	lbu	r4,r6,r3
+bu2:	sb	r4,r5,r3
 	addik	r7,r7,-1
-	bneid	r7,1b
+	bneid	r7,bu1
 	addik	r3,r3,1		/* delay slot */
-3:
+0:
 	addik	r3,r7,0
 	rtsd	r15,8
 	nop
 	.size   __copy_tofrom_user, . - __copy_tofrom_user
 
 	.section	__ex_table,"a"
-	.word	1b,3b,2b,3b,5b,3b,6b,3b
+	.word	bu1, 0b;
+	.word	bu2, 0b;
+	.text
diff -druN linux-libre-3.1-gnu/arch/microblaze/lib/ucmpdi2.c linux-libre-3.2-gnu/arch/microblaze/lib/ucmpdi2.c
--- linux-libre-3.1-gnu/arch/microblaze/lib/ucmpdi2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/microblaze/lib/ucmpdi2.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,20 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+word_type __ucmpdi2(unsigned long long a, unsigned long long b)
+{
+	const DWunion au = {.ll = a};
+	const DWunion bu = {.ll = b};
+
+	if ((unsigned int) au.s.high < (unsigned int) bu.s.high)
+		return 0;
+	else if ((unsigned int) au.s.high > (unsigned int) bu.s.high)
+		return 2;
+	if ((unsigned int) au.s.low < (unsigned int) bu.s.low)
+		return 0;
+	else if ((unsigned int) au.s.low > (unsigned int) bu.s.low)
+		return 2;
+	return 1;
+}
+EXPORT_SYMBOL(__ucmpdi2);
diff -druN linux-libre-3.1-gnu/arch/microblaze/mm/init.c linux-libre-3.2-gnu/arch/microblaze/mm/init.c
--- linux-libre-3.1-gnu/arch/microblaze/mm/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/mm/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/pfn.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
+#include <linux/export.h>
 
 #include <asm/page.h>
 #include <asm/mmu_context.h>
@@ -304,11 +305,11 @@
 	/* Map in all of RAM starting at CONFIG_KERNEL_START */
 	mapin_ram();
 
-#ifdef HIGHMEM_START_BOOL
-	ioremap_base = HIGHMEM_START;
+#ifdef CONFIG_HIGHMEM_START_BOOL
+	ioremap_base = CONFIG_HIGHMEM_START;
 #else
 	ioremap_base = 0xfe000000UL;	/* for now, could be 0xfffff000 */
-#endif /* CONFIG_HIGHMEM */
+#endif /* CONFIG_HIGHMEM_START_BOOL */
 	ioremap_bot = ioremap_base;
 
 	/* Initialize the context management stuff */
diff -druN linux-libre-3.1-gnu/arch/microblaze/pci/iomap.c linux-libre-3.2-gnu/arch/microblaze/pci/iomap.c
--- linux-libre-3.1-gnu/arch/microblaze/pci/iomap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/pci/iomap.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/mm.h>
+#include <linux/export.h>
 #include <asm/io.h>
 #include <asm/pci-bridge.h>
 
diff -druN linux-libre-3.1-gnu/arch/microblaze/pci/pci-common.c linux-libre-3.2-gnu/arch/microblaze/pci/pci-common.c
--- linux-libre-3.1-gnu/arch/microblaze/pci/pci-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/microblaze/pci/pci-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
+#include <linux/export.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/common/dbdma.c linux-libre-3.2-gnu/arch/mips/alchemy/common/dbdma.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/common/dbdma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/common/dbdma.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,8 +40,6 @@
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
 
-#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
-
 /*
  * The Descriptor Based DMA supports up to 16 channels.
  *
@@ -62,120 +60,96 @@
 			(dbdma_global_t *)KSEG1ADDR(AU1550_DBDMA_CONF_PHYS_ADDR);
 static int dbdma_initialized;
 
-static dbdev_tab_t dbdev_tab[] = {
-#ifdef CONFIG_SOC_AU1550
+static dbdev_tab_t *dbdev_tab;
+
+static dbdev_tab_t au1550_dbdev_tab[] __initdata = {
 	/* UARTS */
-	{ DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 },
-	{ DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 },
-	{ DSCR_CMD0_UART3_TX, DEV_FLAGS_OUT, 0, 8, 0x11400004, 0, 0 },
-	{ DSCR_CMD0_UART3_RX, DEV_FLAGS_IN, 0, 8, 0x11400000, 0, 0 },
+	{ AU1550_DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 },
+	{ AU1550_DSCR_CMD0_UART0_RX, DEV_FLAGS_IN,  0, 8, 0x11100000, 0, 0 },
+	{ AU1550_DSCR_CMD0_UART3_TX, DEV_FLAGS_OUT, 0, 8, 0x11400004, 0, 0 },
+	{ AU1550_DSCR_CMD0_UART3_RX, DEV_FLAGS_IN,  0, 8, 0x11400000, 0, 0 },
 
 	/* EXT DMA */
-	{ DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_DMA_REQ2, 0, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_DMA_REQ3, 0, 0, 0, 0x00000000, 0, 0 },
+	{ AU1550_DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 },
+	{ AU1550_DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 },
+	{ AU1550_DSCR_CMD0_DMA_REQ2, 0, 0, 0, 0x00000000, 0, 0 },
+	{ AU1550_DSCR_CMD0_DMA_REQ3, 0, 0, 0, 0x00000000, 0, 0 },
 
 	/* USB DEV */
-	{ DSCR_CMD0_USBDEV_RX0, DEV_FLAGS_IN, 4, 8, 0x10200000, 0, 0 },
-	{ DSCR_CMD0_USBDEV_TX0, DEV_FLAGS_OUT, 4, 8, 0x10200004, 0, 0 },
-	{ DSCR_CMD0_USBDEV_TX1, DEV_FLAGS_OUT, 4, 8, 0x10200008, 0, 0 },
-	{ DSCR_CMD0_USBDEV_TX2, DEV_FLAGS_OUT, 4, 8, 0x1020000c, 0, 0 },
-	{ DSCR_CMD0_USBDEV_RX3, DEV_FLAGS_IN, 4, 8, 0x10200010, 0, 0 },
-	{ DSCR_CMD0_USBDEV_RX4, DEV_FLAGS_IN, 4, 8, 0x10200014, 0, 0 },
-
-	/* PSC 0 */
-	{ DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 },
-	{ DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 },
-
-	/* PSC 1 */
-	{ DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 },
-	{ DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 },
-
-	/* PSC 2 */
-	{ DSCR_CMD0_PSC2_TX, DEV_FLAGS_OUT, 0, 0, 0x10a0001c, 0, 0 },
-	{ DSCR_CMD0_PSC2_RX, DEV_FLAGS_IN, 0, 0, 0x10a0001c, 0, 0 },
+	{ AU1550_DSCR_CMD0_USBDEV_RX0, DEV_FLAGS_IN,  4, 8, 0x10200000, 0, 0 },
+	{ AU1550_DSCR_CMD0_USBDEV_TX0, DEV_FLAGS_OUT, 4, 8, 0x10200004, 0, 0 },
+	{ AU1550_DSCR_CMD0_USBDEV_TX1, DEV_FLAGS_OUT, 4, 8, 0x10200008, 0, 0 },
+	{ AU1550_DSCR_CMD0_USBDEV_TX2, DEV_FLAGS_OUT, 4, 8, 0x1020000c, 0, 0 },
+	{ AU1550_DSCR_CMD0_USBDEV_RX3, DEV_FLAGS_IN,  4, 8, 0x10200010, 0, 0 },
+	{ AU1550_DSCR_CMD0_USBDEV_RX4, DEV_FLAGS_IN,  4, 8, 0x10200014, 0, 0 },
 
-	/* PSC 3 */
-	{ DSCR_CMD0_PSC3_TX, DEV_FLAGS_OUT, 0, 0, 0x10b0001c, 0, 0 },
-	{ DSCR_CMD0_PSC3_RX, DEV_FLAGS_IN, 0, 0, 0x10b0001c, 0, 0 },
+	/* PSCs */
+	{ AU1550_DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 },
+	{ AU1550_DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN,  0, 0, 0x11a0001c, 0, 0 },
+	{ AU1550_DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 },
+	{ AU1550_DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN,  0, 0, 0x11b0001c, 0, 0 },
+	{ AU1550_DSCR_CMD0_PSC2_TX, DEV_FLAGS_OUT, 0, 0, 0x10a0001c, 0, 0 },
+	{ AU1550_DSCR_CMD0_PSC2_RX, DEV_FLAGS_IN,  0, 0, 0x10a0001c, 0, 0 },
+	{ AU1550_DSCR_CMD0_PSC3_TX, DEV_FLAGS_OUT, 0, 0, 0x10b0001c, 0, 0 },
+	{ AU1550_DSCR_CMD0_PSC3_RX, DEV_FLAGS_IN,  0, 0, 0x10b0001c, 0, 0 },
 
-	{ DSCR_CMD0_PCI_WRITE, 0, 0, 0, 0x00000000, 0, 0 },	/* PCI */
-	{ DSCR_CMD0_NAND_FLASH, 0, 0, 0, 0x00000000, 0, 0 },	/* NAND */
+	{ AU1550_DSCR_CMD0_PCI_WRITE,  0, 0, 0, 0x00000000, 0, 0 },  /* PCI */
+	{ AU1550_DSCR_CMD0_NAND_FLASH, 0, 0, 0, 0x00000000, 0, 0 }, /* NAND */
 
 	/* MAC 0 */
-	{ DSCR_CMD0_MAC0_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_MAC0_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
+	{ AU1550_DSCR_CMD0_MAC0_RX, DEV_FLAGS_IN,  0, 0, 0x00000000, 0, 0 },
+	{ AU1550_DSCR_CMD0_MAC0_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
 
 	/* MAC 1 */
-	{ DSCR_CMD0_MAC1_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_MAC1_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
-
-#endif /* CONFIG_SOC_AU1550 */
-
-#ifdef CONFIG_SOC_AU1200
-	{ DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 },
-	{ DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 },
-	{ DSCR_CMD0_UART1_TX, DEV_FLAGS_OUT, 0, 8, 0x11200004, 0, 0 },
-	{ DSCR_CMD0_UART1_RX, DEV_FLAGS_IN, 0, 8, 0x11200000, 0, 0 },
+	{ AU1550_DSCR_CMD0_MAC1_RX, DEV_FLAGS_IN,  0, 0, 0x00000000, 0, 0 },
+	{ AU1550_DSCR_CMD0_MAC1_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
 
-	{ DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 },
+	{ DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+	{ DSCR_CMD0_ALWAYS,   DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+};
 
-	{ DSCR_CMD0_MAE_BE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_MAE_FE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+static dbdev_tab_t au1200_dbdev_tab[] __initdata = {
+	{ AU1200_DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 },
+	{ AU1200_DSCR_CMD0_UART0_RX, DEV_FLAGS_IN,  0, 8, 0x11100000, 0, 0 },
+	{ AU1200_DSCR_CMD0_UART1_TX, DEV_FLAGS_OUT, 0, 8, 0x11200004, 0, 0 },
+	{ AU1200_DSCR_CMD0_UART1_RX, DEV_FLAGS_IN,  0, 8, 0x11200000, 0, 0 },
 
-	{ DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 4, 8, 0x10600000, 0, 0 },
-	{ DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 4, 8, 0x10600004, 0, 0 },
-	{ DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 4, 8, 0x10680000, 0, 0 },
-	{ DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 4, 8, 0x10680004, 0, 0 },
+	{ AU1200_DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 },
 
-	{ DSCR_CMD0_AES_RX, DEV_FLAGS_IN , 4, 32, 0x10300008, 0, 0 },
-	{ DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 4, 32, 0x10300004, 0, 0 },
+	{ AU1200_DSCR_CMD0_MAE_BE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_MAE_FE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
 
-	{ DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 16, 0x11a0001c, 0, 0 },
-	{ DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 16, 0x11a0001c, 0, 0 },
-	{ DSCR_CMD0_PSC0_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 4, 8, 0x10600000, 0, 0 },
+	{ AU1200_DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN,  4, 8, 0x10600004, 0, 0 },
+	{ AU1200_DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 4, 8, 0x10680000, 0, 0 },
+	{ AU1200_DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN,  4, 8, 0x10680004, 0, 0 },
 
-	{ DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 16, 0x11b0001c, 0, 0 },
-	{ DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 16, 0x11b0001c, 0, 0 },
-	{ DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_AES_RX, DEV_FLAGS_IN , 4, 32, 0x10300008, 0, 0 },
+	{ AU1200_DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 4, 32, 0x10300004, 0, 0 },
 
-	{ DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 32, 0x14004020, 0, 0 },
-	{ DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 32, 0x14004040, 0, 0 },
-	{ DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 32, 0x14004060, 0, 0 },
-	{ DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_PSC0_TX,   DEV_FLAGS_OUT, 0, 16, 0x11a0001c, 0, 0 },
+	{ AU1200_DSCR_CMD0_PSC0_RX,   DEV_FLAGS_IN,  0, 16, 0x11a0001c, 0, 0 },
+	{ AU1200_DSCR_CMD0_PSC0_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_PSC1_TX,   DEV_FLAGS_OUT, 0, 16, 0x11b0001c, 0, 0 },
+	{ AU1200_DSCR_CMD0_PSC1_RX,   DEV_FLAGS_IN,  0, 16, 0x11b0001c, 0, 0 },
+	{ AU1200_DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
 
-	{ DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+	{ AU1200_DSCR_CMD0_CIM_RXA,  DEV_FLAGS_IN, 0, 32, 0x14004020, 0, 0 },
+	{ AU1200_DSCR_CMD0_CIM_RXB,  DEV_FLAGS_IN, 0, 32, 0x14004040, 0, 0 },
+	{ AU1200_DSCR_CMD0_CIM_RXC,  DEV_FLAGS_IN, 0, 32, 0x14004060, 0, 0 },
+	{ AU1200_DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
 
-#endif /* CONFIG_SOC_AU1200 */
+	{ AU1200_DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
 
 	{ DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
-
-	/* Provide 16 user definable device types */
-	{ ~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, 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, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
-	{ ~0, 0, 0, 0, 0, 0, 0 },
+	{ DSCR_CMD0_ALWAYS,   DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
 };
 
-#define DBDEV_TAB_SIZE	ARRAY_SIZE(dbdev_tab)
-
+/* 32 predefined plus 32 custom */
+#define DBDEV_TAB_SIZE		64
 
 static chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS];
 
@@ -1028,38 +1002,43 @@
 	.resume		= alchemy_dbdma_resume,
 };
 
-static int __init au1xxx_dbdma_init(void)
+static int __init dbdma_setup(unsigned int irq, dbdev_tab_t *idtable)
 {
-	int irq_nr, ret;
+	int ret;
+
+	dbdev_tab = kzalloc(sizeof(dbdev_tab_t) * DBDEV_TAB_SIZE, GFP_KERNEL);
+	if (!dbdev_tab)
+		return -ENOMEM;
+
+	memcpy(dbdev_tab, idtable, 32 * sizeof(dbdev_tab_t));
+	for (ret = 32; ret < DBDEV_TAB_SIZE; ret++)
+		dbdev_tab[ret].dev_id = ~0;
 
 	dbdma_gptr->ddma_config = 0;
 	dbdma_gptr->ddma_throttle = 0;
 	dbdma_gptr->ddma_inten = 0xffff;
 	au_sync();
 
-	switch (alchemy_get_cputype()) {
-	case ALCHEMY_CPU_AU1550:
-		irq_nr = AU1550_DDMA_INT;
-		break;
-	case ALCHEMY_CPU_AU1200:
-		irq_nr = AU1200_DDMA_INT;
-		break;
-	default:
-		return -ENODEV;
-	}
-
-	ret = request_irq(irq_nr, dbdma_interrupt, IRQF_DISABLED,
-			"Au1xxx dbdma", (void *)dbdma_gptr);
+	ret = request_irq(irq, dbdma_interrupt, IRQF_DISABLED, "dbdma",
+			  (void *)dbdma_gptr);
 	if (ret)
 		printk(KERN_ERR "Cannot grab DBDMA interrupt!\n");
 	else {
 		dbdma_initialized = 1;
-		printk(KERN_INFO "Alchemy DBDMA initialized\n");
 		register_syscore_ops(&alchemy_dbdma_syscore_ops);
 	}
 
 	return ret;
 }
-subsys_initcall(au1xxx_dbdma_init);
 
-#endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */
+static int __init alchemy_dbdma_init(void)
+{
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1550:
+		return dbdma_setup(AU1550_DDMA_INT, au1550_dbdev_tab);
+	case ALCHEMY_CPU_AU1200:
+		return dbdma_setup(AU1200_DDMA_INT, au1200_dbdev_tab);
+	}
+	return 0;
+}
+subsys_initcall(alchemy_dbdma_init);
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/common/dma.c linux-libre-3.2-gnu/arch/mips/alchemy/common/dma.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/common/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/common/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,8 +40,6 @@
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1000_dma.h>
 
-#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1500) || \
-    defined(CONFIG_SOC_AU1100)
 /*
  * A note on resource allocation:
  *
@@ -88,12 +86,12 @@
 	{ AU1000_AC97_PHYS_ADDR + 0x08, DMA_DW16 | DMA_DR },	/* AC97 RX c */
 	{ AU1000_UART3_PHYS_ADDR + 0x04, DMA_DW8 | DMA_NC },	/* UART3_TX */
 	{ AU1000_UART3_PHYS_ADDR + 0x00, DMA_DW8 | DMA_NC | DMA_DR }, /* UART3_RX */
-	{ AU1000_USBD_PHYS_ADDR + 0x00, DMA_DW8 | DMA_NC | DMA_DR }, /* EP0RD */
-	{ AU1000_USBD_PHYS_ADDR + 0x04, DMA_DW8 | DMA_NC }, /* EP0WR */
-	{ AU1000_USBD_PHYS_ADDR + 0x08, DMA_DW8 | DMA_NC }, /* EP2WR */
-	{ AU1000_USBD_PHYS_ADDR + 0x0c, DMA_DW8 | DMA_NC }, /* EP3WR */
-	{ AU1000_USBD_PHYS_ADDR + 0x10, DMA_DW8 | DMA_NC | DMA_DR }, /* EP4RD */
-	{ AU1000_USBD_PHYS_ADDR + 0x14, DMA_DW8 | DMA_NC | DMA_DR }, /* EP5RD */
+	{ AU1000_USB_UDC_PHYS_ADDR + 0x00, DMA_DW8 | DMA_NC | DMA_DR }, /* EP0RD */
+	{ AU1000_USB_UDC_PHYS_ADDR + 0x04, DMA_DW8 | DMA_NC }, /* EP0WR */
+	{ AU1000_USB_UDC_PHYS_ADDR + 0x08, DMA_DW8 | DMA_NC }, /* EP2WR */
+	{ AU1000_USB_UDC_PHYS_ADDR + 0x0c, DMA_DW8 | DMA_NC }, /* EP3WR */
+	{ AU1000_USB_UDC_PHYS_ADDR + 0x10, DMA_DW8 | DMA_NC | DMA_DR }, /* EP4RD */
+	{ AU1000_USB_UDC_PHYS_ADDR + 0x14, DMA_DW8 | DMA_NC | DMA_DR }, /* EP5RD */
 	/* on Au1500, these 2 are DMA_REQ2/3 (GPIO208/209) instead! */
 	{ AU1000_I2S_PHYS_ADDR + 0x00, DMA_DW32 | DMA_NC},	/* I2S TX */
 	{ AU1000_I2S_PHYS_ADDR + 0x00, DMA_DW32 | DMA_NC | DMA_DR}, /* I2S RX */
@@ -170,13 +168,13 @@
 	const struct dma_dev *dev;
 	int i, ret;
 
-#if defined(CONFIG_SOC_AU1100)
-	if (dev_id < 0 || dev_id >= (DMA_NUM_DEV + DMA_NUM_DEV_BANK2))
-		return -EINVAL;
-#else
-	if (dev_id < 0 || dev_id >= DMA_NUM_DEV)
-		return -EINVAL;
-#endif
+	if (alchemy_get_cputype() == ALCHEMY_CPU_AU1100) {
+		if (dev_id < 0 || dev_id >= (DMA_NUM_DEV + DMA_NUM_DEV_BANK2))
+			return -EINVAL;
+	} else {
+		if (dev_id < 0 || dev_id >= DMA_NUM_DEV)
+			return -EINVAL;
+	}
 
 	for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++)
 		if (au1000_dma_table[i].dev_id < 0)
@@ -239,30 +237,28 @@
 
 static int __init au1000_dma_init(void)
 {
-        int base, i;
+	int base, i;
 
-        switch (alchemy_get_cputype()) {
-        case ALCHEMY_CPU_AU1000:
-                base = AU1000_DMA_INT_BASE;
-                break;
-        case ALCHEMY_CPU_AU1500:
-                base = AU1500_DMA_INT_BASE;
-                break;
-        case ALCHEMY_CPU_AU1100:
-                base = AU1100_DMA_INT_BASE;
-                break;
-        default:
-                goto out;
-        }
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1000:
+		base = AU1000_DMA_INT_BASE;
+		break;
+	case ALCHEMY_CPU_AU1500:
+		base = AU1500_DMA_INT_BASE;
+		break;
+	case ALCHEMY_CPU_AU1100:
+		base = AU1100_DMA_INT_BASE;
+		break;
+	default:
+		goto out;
+	}
 
-        for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++)
-                au1000_dma_table[i].irq = base + i;
+	for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++)
+		au1000_dma_table[i].irq = base + i;
 
-        printk(KERN_INFO "Alchemy DMA initialized\n");
+	printk(KERN_INFO "Alchemy DMA initialized\n");
 
 out:
-        return 0;
+	return 0;
 }
 arch_initcall(au1000_dma_init);
-
-#endif /* AU1000 AU1500 AU1100 */
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/common/gpiolib-au1000.c linux-libre-3.2-gnu/arch/mips/alchemy/common/gpiolib-au1000.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/common/gpiolib-au1000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/common/gpiolib-au1000.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,126 +0,0 @@
-/*
- *  Copyright (C) 2007-2009, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
- *  	GPIOLIB support for Au1000, Au1500, Au1100, Au1550 and Au12x0.
- *
- *  This program is free software; you can redistribute	 it and/or modify it
- *  under  the terms of	 the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the	License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
- *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
- *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  Notes :
- * 	au1000 SoC have only one GPIO block : GPIO1
- * 	Au1100, Au15x0, Au12x0 have a second one : GPIO2
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-au1x00/gpio.h>
-
-static int gpio2_get(struct gpio_chip *chip, unsigned offset)
-{
-	return alchemy_gpio2_get_value(offset + ALCHEMY_GPIO2_BASE);
-}
-
-static void gpio2_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	alchemy_gpio2_set_value(offset + ALCHEMY_GPIO2_BASE, value);
-}
-
-static int gpio2_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	return alchemy_gpio2_direction_input(offset + ALCHEMY_GPIO2_BASE);
-}
-
-static int gpio2_direction_output(struct gpio_chip *chip, unsigned offset,
-				  int value)
-{
-	return alchemy_gpio2_direction_output(offset + ALCHEMY_GPIO2_BASE,
-						value);
-}
-
-static int gpio2_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	return alchemy_gpio2_to_irq(offset + ALCHEMY_GPIO2_BASE);
-}
-
-
-static int gpio1_get(struct gpio_chip *chip, unsigned offset)
-{
-	return alchemy_gpio1_get_value(offset + ALCHEMY_GPIO1_BASE);
-}
-
-static void gpio1_set(struct gpio_chip *chip,
-				unsigned offset, int value)
-{
-	alchemy_gpio1_set_value(offset + ALCHEMY_GPIO1_BASE, value);
-}
-
-static int gpio1_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	return alchemy_gpio1_direction_input(offset + ALCHEMY_GPIO1_BASE);
-}
-
-static int gpio1_direction_output(struct gpio_chip *chip,
-					unsigned offset, int value)
-{
-	return alchemy_gpio1_direction_output(offset + ALCHEMY_GPIO1_BASE,
-					     value);
-}
-
-static int gpio1_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	return alchemy_gpio1_to_irq(offset + ALCHEMY_GPIO1_BASE);
-}
-
-struct gpio_chip alchemy_gpio_chip[] = {
-	[0] = {
-		.label			= "alchemy-gpio1",
-		.direction_input	= gpio1_direction_input,
-		.direction_output	= gpio1_direction_output,
-		.get			= gpio1_get,
-		.set			= gpio1_set,
-		.to_irq			= gpio1_to_irq,
-		.base			= ALCHEMY_GPIO1_BASE,
-		.ngpio			= ALCHEMY_GPIO1_NUM,
-	},
-	[1] = {
-		.label                  = "alchemy-gpio2",
-		.direction_input        = gpio2_direction_input,
-		.direction_output       = gpio2_direction_output,
-		.get                    = gpio2_get,
-		.set                    = gpio2_set,
-		.to_irq			= gpio2_to_irq,
-		.base                   = ALCHEMY_GPIO2_BASE,
-		.ngpio                  = ALCHEMY_GPIO2_NUM,
-	},
-};
-
-static int __init alchemy_gpiolib_init(void)
-{
-	gpiochip_add(&alchemy_gpio_chip[0]);
-	if (alchemy_get_cputype() != ALCHEMY_CPU_AU1000)
-		gpiochip_add(&alchemy_gpio_chip[1]);
-
-	return 0;
-}
-arch_initcall(alchemy_gpiolib_init);
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/common/gpiolib.c linux-libre-3.2-gnu/arch/mips/alchemy/common/gpiolib.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/common/gpiolib.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/mips/alchemy/common/gpiolib.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,133 @@
+/*
+ *  Copyright (C) 2007-2009, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
+ *	GPIOLIB support for Alchemy chips.
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Notes :
+ *	This file must ONLY be built when CONFIG_GPIOLIB=y and
+ *	 CONFIG_ALCHEMY_GPIO_INDIRECT=n, otherwise compilation will fail!
+ *	au1000 SoC have only one GPIO block : GPIO1
+ *	Au1100, Au15x0, Au12x0 have a second one : GPIO2
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/gpio.h>
+#include <asm/mach-au1x00/gpio-au1000.h>
+
+static int gpio2_get(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio2_get_value(offset + ALCHEMY_GPIO2_BASE);
+}
+
+static void gpio2_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	alchemy_gpio2_set_value(offset + ALCHEMY_GPIO2_BASE, value);
+}
+
+static int gpio2_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio2_direction_input(offset + ALCHEMY_GPIO2_BASE);
+}
+
+static int gpio2_direction_output(struct gpio_chip *chip, unsigned offset,
+				  int value)
+{
+	return alchemy_gpio2_direction_output(offset + ALCHEMY_GPIO2_BASE,
+						value);
+}
+
+static int gpio2_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio2_to_irq(offset + ALCHEMY_GPIO2_BASE);
+}
+
+
+static int gpio1_get(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio1_get_value(offset + ALCHEMY_GPIO1_BASE);
+}
+
+static void gpio1_set(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	alchemy_gpio1_set_value(offset + ALCHEMY_GPIO1_BASE, value);
+}
+
+static int gpio1_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio1_direction_input(offset + ALCHEMY_GPIO1_BASE);
+}
+
+static int gpio1_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	return alchemy_gpio1_direction_output(offset + ALCHEMY_GPIO1_BASE,
+					     value);
+}
+
+static int gpio1_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio1_to_irq(offset + ALCHEMY_GPIO1_BASE);
+}
+
+struct gpio_chip alchemy_gpio_chip[] = {
+	[0] = {
+		.label			= "alchemy-gpio1",
+		.direction_input	= gpio1_direction_input,
+		.direction_output	= gpio1_direction_output,
+		.get			= gpio1_get,
+		.set			= gpio1_set,
+		.to_irq			= gpio1_to_irq,
+		.base			= ALCHEMY_GPIO1_BASE,
+		.ngpio			= ALCHEMY_GPIO1_NUM,
+	},
+	[1] = {
+		.label                  = "alchemy-gpio2",
+		.direction_input        = gpio2_direction_input,
+		.direction_output       = gpio2_direction_output,
+		.get                    = gpio2_get,
+		.set                    = gpio2_set,
+		.to_irq			= gpio2_to_irq,
+		.base                   = ALCHEMY_GPIO2_BASE,
+		.ngpio                  = ALCHEMY_GPIO2_NUM,
+	},
+};
+
+static int __init alchemy_gpiochip_init(void)
+{
+	int ret = 0;
+
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1000:
+		ret = gpiochip_add(&alchemy_gpio_chip[0]);
+		break;
+	case ALCHEMY_CPU_AU1500...ALCHEMY_CPU_AU1200:
+		ret = gpiochip_add(&alchemy_gpio_chip[0]);
+		ret |= gpiochip_add(&alchemy_gpio_chip[1]);
+		break;
+	}
+	return ret;
+}
+arch_initcall(alchemy_gpiochip_init);
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/common/Makefile linux-libre-3.2-gnu/arch/mips/alchemy/common/Makefile
--- linux-libre-3.1-gnu/arch/mips/alchemy/common/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/common/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -12,9 +12,5 @@
 
 # optional gpiolib support
 ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),)
- ifeq ($(CONFIG_GPIOLIB),y)
-  obj-$(CONFIG_ALCHEMY_GPIOINT_AU1000) += gpiolib-au1000.o
- endif
+ obj-$(CONFIG_GPIOLIB) += gpiolib.o
 endif
-
-obj-$(CONFIG_PCI)		+= pci.o
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/common/pci.c linux-libre-3.2-gnu/arch/mips/alchemy/common/pci.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/common/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/common/pci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,104 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Alchemy/AMD Au1x00 PCI support.
- *
- * Copyright 2001-2003, 2007-2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
- *
- *  Support for all devices (greater than 16) added by David Gathright.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU 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/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-/* TBD */
-static struct resource pci_io_resource = {
-	.start	= PCI_IO_START,
-	.end	= PCI_IO_END,
-	.name	= "PCI IO space",
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource pci_mem_resource = {
-	.start	= PCI_MEM_START,
-	.end	= PCI_MEM_END,
-	.name	= "PCI memory space",
-	.flags	= IORESOURCE_MEM
-};
-
-extern struct pci_ops au1x_pci_ops;
-
-static struct pci_controller au1x_controller = {
-	.pci_ops	= &au1x_pci_ops,
-	.io_resource	= &pci_io_resource,
-	.mem_resource	= &pci_mem_resource,
-};
-
-#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
-static unsigned long virt_io_addr;
-#endif
-
-static int __init au1x_pci_setup(void)
-{
-	extern void au1x_pci_cfg_init(void);
-
-#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
-	virt_io_addr = (unsigned long)ioremap(Au1500_PCI_IO_START,
-			Au1500_PCI_IO_END - Au1500_PCI_IO_START + 1);
-
-	if (!virt_io_addr) {
-		printk(KERN_ERR "Unable to ioremap pci space\n");
-		return 1;
-	}
-	au1x_controller.io_map_base = virt_io_addr;
-
-#ifdef CONFIG_DMA_NONCOHERENT
-	{
-		/*
-		 *  Set the NC bit in controller for Au1500 pre-AC silicon
-		 */
-		u32 prid = read_c0_prid();
-
-		if ((prid & 0xFF000000) == 0x01000000 && prid < 0x01030202) {
-			au_writel((1 << 16) | au_readl(Au1500_PCI_CFG),
-				  Au1500_PCI_CFG);
-			printk(KERN_INFO "Non-coherent PCI accesses enabled\n");
-		}
-	}
-#endif
-
-	set_io_port_base(virt_io_addr);
-#endif
-
-	au1x_pci_cfg_init();
-
-	register_pci_controller(&au1x_controller);
-	return 0;
-}
-
-arch_initcall(au1x_pci_setup);
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/common/platform.c linux-libre-3.2-gnu/arch/mips/alchemy/common/platform.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/common/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/common/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/serial_8250.h>
 #include <linux/slab.h>
 
-#include <asm/mach-au1x00/au1xxx.h>
+#include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
 #include <asm/mach-au1x00/au1100_mmc.h>
 #include <asm/mach-au1x00/au1xxx_eth.h>
@@ -111,270 +111,87 @@
 		printk(KERN_INFO "Alchemy: failed to register UARTs\n");
 }
 
-/* OHCI (USB full speed host controller) */
-static struct resource au1xxx_usb_ohci_resources[] = {
-	[0] = {
-		.start		= USB_OHCI_BASE,
-		.end		= USB_OHCI_BASE + USB_OHCI_LEN - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start		= FOR_PLATFORM_C_USB_HOST_INT,
-		.end		= FOR_PLATFORM_C_USB_HOST_INT,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-/* The dmamask must be set for OHCI to work */
-static u64 ohci_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device au1xxx_usb_ohci_device = {
-	.name		= "au1xxx-ohci",
-	.id		= 0,
-	.dev = {
-		.dma_mask		= &ohci_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.num_resources	= ARRAY_SIZE(au1xxx_usb_ohci_resources),
-	.resource	= au1xxx_usb_ohci_resources,
-};
-
-/*** AU1100 LCD controller ***/
 
-#ifdef CONFIG_FB_AU1100
-static struct resource au1100_lcd_resources[] = {
-	[0] = {
-		.start          = LCD_PHYS_ADDR,
-		.end            = LCD_PHYS_ADDR + 0x800 - 1,
-		.flags          = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start          = AU1100_LCD_INT,
-		.end            = AU1100_LCD_INT,
-		.flags          = IORESOURCE_IRQ,
-	}
-};
-
-static u64 au1100_lcd_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device au1100_lcd_device = {
-	.name           = "au1100-lcd",
-	.id             = 0,
-	.dev = {
-		.dma_mask               = &au1100_lcd_dmamask,
-		.coherent_dma_mask      = DMA_BIT_MASK(32),
-	},
-	.num_resources  = ARRAY_SIZE(au1100_lcd_resources),
-	.resource       = au1100_lcd_resources,
-};
-#endif
-
-#ifdef CONFIG_SOC_AU1200
-/* EHCI (USB high speed host controller) */
-static struct resource au1xxx_usb_ehci_resources[] = {
-	[0] = {
-		.start		= USB_EHCI_BASE,
-		.end		= USB_EHCI_BASE + USB_EHCI_LEN - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start		= AU1200_USB_INT,
-		.end		= AU1200_USB_INT,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static u64 ehci_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device au1xxx_usb_ehci_device = {
-	.name		= "au1xxx-ehci",
-	.id		= 0,
-	.dev = {
-		.dma_mask		= &ehci_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.num_resources	= ARRAY_SIZE(au1xxx_usb_ehci_resources),
-	.resource	= au1xxx_usb_ehci_resources,
-};
-
-/* Au1200 UDC (USB gadget controller) */
-static struct resource au1xxx_usb_gdt_resources[] = {
-	[0] = {
-		.start		= USB_UDC_BASE,
-		.end		= USB_UDC_BASE + USB_UDC_LEN - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start		= AU1200_USB_INT,
-		.end		= AU1200_USB_INT,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static u64 udc_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device au1xxx_usb_gdt_device = {
-	.name		= "au1xxx-udc",
-	.id		= 0,
-	.dev = {
-		.dma_mask		= &udc_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.num_resources	= ARRAY_SIZE(au1xxx_usb_gdt_resources),
-	.resource	= au1xxx_usb_gdt_resources,
-};
+/* The dmamask must be set for OHCI/EHCI to work */
+static u64 alchemy_ohci_dmamask = DMA_BIT_MASK(32);
+static u64 __maybe_unused alchemy_ehci_dmamask = DMA_BIT_MASK(32);
 
-/* Au1200 UOC (USB OTG controller) */
-static struct resource au1xxx_usb_otg_resources[] = {
-	[0] = {
-		.start		= USB_UOC_BASE,
-		.end		= USB_UOC_BASE + USB_UOC_LEN - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start		= AU1200_USB_INT,
-		.end		= AU1200_USB_INT,
-		.flags		= IORESOURCE_IRQ,
-	},
+static unsigned long alchemy_ohci_data[][2] __initdata = {
+	[ALCHEMY_CPU_AU1000] = { AU1000_USB_OHCI_PHYS_ADDR, AU1000_USB_HOST_INT },
+	[ALCHEMY_CPU_AU1500] = { AU1000_USB_OHCI_PHYS_ADDR, AU1500_USB_HOST_INT },
+	[ALCHEMY_CPU_AU1100] = { AU1000_USB_OHCI_PHYS_ADDR, AU1100_USB_HOST_INT },
+	[ALCHEMY_CPU_AU1550] = { AU1550_USB_OHCI_PHYS_ADDR, AU1550_USB_HOST_INT },
+	[ALCHEMY_CPU_AU1200] = { AU1200_USB_OHCI_PHYS_ADDR, AU1200_USB_INT },
 };
 
-static u64 uoc_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device au1xxx_usb_otg_device = {
-	.name		= "au1xxx-uoc",
-	.id		= 0,
-	.dev = {
-		.dma_mask		= &uoc_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.num_resources	= ARRAY_SIZE(au1xxx_usb_otg_resources),
-	.resource	= au1xxx_usb_otg_resources,
+static unsigned long alchemy_ehci_data[][2] __initdata = {
+	[ALCHEMY_CPU_AU1200] = { AU1200_USB_EHCI_PHYS_ADDR, AU1200_USB_INT },
 };
 
-static struct resource au1200_lcd_resources[] = {
-	[0] = {
-		.start          = LCD_PHYS_ADDR,
-		.end            = LCD_PHYS_ADDR + 0x800 - 1,
-		.flags          = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start          = AU1200_LCD_INT,
-		.end            = AU1200_LCD_INT,
-		.flags          = IORESOURCE_IRQ,
+static int __init _new_usbres(struct resource **r, struct platform_device **d)
+{
+	*r = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+	if (!*r)
+		return -ENOMEM;
+	*d = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
+	if (!*d) {
+		kfree(*r);
+		return -ENOMEM;
 	}
-};
 
-static u64 au1200_lcd_dmamask = DMA_BIT_MASK(32);
+	(*d)->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+	(*d)->num_resources = 2;
+	(*d)->resource = *r;
 
-static struct platform_device au1200_lcd_device = {
-	.name           = "au1200-lcd",
-	.id             = 0,
-	.dev = {
-		.dma_mask               = &au1200_lcd_dmamask,
-		.coherent_dma_mask      = DMA_BIT_MASK(32),
-	},
-	.num_resources  = ARRAY_SIZE(au1200_lcd_resources),
-	.resource       = au1200_lcd_resources,
-};
+	return 0;
+}
 
-static u64 au1xxx_mmc_dmamask =  DMA_BIT_MASK(32);
+static void __init alchemy_setup_usb(int ctype)
+{
+	struct resource *res;
+	struct platform_device *pdev;
 
-extern struct au1xmmc_platform_data au1xmmc_platdata[2];
+	/* setup OHCI0.  Every variant has one */
+	if (_new_usbres(&res, &pdev))
+		return;
 
-static struct resource au1200_mmc0_resources[] = {
-	[0] = {
-		.start          = AU1100_SD0_PHYS_ADDR,
-		.end            = AU1100_SD0_PHYS_ADDR + 0xfff,
-		.flags          = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start		= AU1200_SD_INT,
-		.end		= AU1200_SD_INT,
-		.flags		= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start		= DSCR_CMD0_SDMS_TX0,
-		.end		= DSCR_CMD0_SDMS_TX0,
-		.flags		= IORESOURCE_DMA,
-	},
-	[3] = {
-		.start          = DSCR_CMD0_SDMS_RX0,
-		.end		= DSCR_CMD0_SDMS_RX0,
-		.flags          = IORESOURCE_DMA,
-	}
-};
+	res[0].start = alchemy_ohci_data[ctype][0];
+	res[0].end = res[0].start + 0x100 - 1;
+	res[0].flags = IORESOURCE_MEM;
+	res[1].start = alchemy_ohci_data[ctype][1];
+	res[1].end = res[1].start;
+	res[1].flags = IORESOURCE_IRQ;
+	pdev->name = "au1xxx-ohci";
+	pdev->id = 0;
+	pdev->dev.dma_mask = &alchemy_ohci_dmamask;
 
-static struct platform_device au1200_mmc0_device = {
-	.name = "au1xxx-mmc",
-	.id = 0,
-	.dev = {
-		.dma_mask		= &au1xxx_mmc_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-		.platform_data		= &au1xmmc_platdata[0],
-	},
-	.num_resources	= ARRAY_SIZE(au1200_mmc0_resources),
-	.resource	= au1200_mmc0_resources,
-};
+	if (platform_device_register(pdev))
+		printk(KERN_INFO "Alchemy USB: cannot add OHCI0\n");
 
-#ifndef CONFIG_MIPS_DB1200
-static struct resource au1200_mmc1_resources[] = {
-	[0] = {
-		.start          = AU1100_SD1_PHYS_ADDR,
-		.end            = AU1100_SD1_PHYS_ADDR + 0xfff,
-		.flags          = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start		= AU1200_SD_INT,
-		.end		= AU1200_SD_INT,
-		.flags		= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start		= DSCR_CMD0_SDMS_TX1,
-		.end		= DSCR_CMD0_SDMS_TX1,
-		.flags		= IORESOURCE_DMA,
-	},
-	[3] = {
-		.start          = DSCR_CMD0_SDMS_RX1,
-		.end		= DSCR_CMD0_SDMS_RX1,
-		.flags          = IORESOURCE_DMA,
-	}
-};
 
-static struct platform_device au1200_mmc1_device = {
-	.name = "au1xxx-mmc",
-	.id = 1,
-	.dev = {
-		.dma_mask		= &au1xxx_mmc_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-		.platform_data		= &au1xmmc_platdata[1],
-	},
-	.num_resources	= ARRAY_SIZE(au1200_mmc1_resources),
-	.resource	= au1200_mmc1_resources,
-};
-#endif /* #ifndef CONFIG_MIPS_DB1200 */
-#endif /* #ifdef CONFIG_SOC_AU1200 */
+	/* setup EHCI0: Au1200 */
+	if (ctype == ALCHEMY_CPU_AU1200) {
+		if (_new_usbres(&res, &pdev))
+			return;
 
-/* All Alchemy demoboards with I2C have this #define in their headers */
-#ifdef SMBUS_PSC_BASE
-static struct resource pbdb_smbus_resources[] = {
-	{
-		.start	= CPHYSADDR(SMBUS_PSC_BASE),
-		.end	= CPHYSADDR(SMBUS_PSC_BASE + 0xfffff),
-		.flags	= IORESOURCE_MEM,
-	},
-};
+		res[0].start = alchemy_ehci_data[ctype][0];
+		res[0].end = res[0].start + 0x100 - 1;
+		res[0].flags = IORESOURCE_MEM;
+		res[1].start = alchemy_ehci_data[ctype][1];
+		res[1].end = res[1].start;
+		res[1].flags = IORESOURCE_IRQ;
+		pdev->name = "au1xxx-ehci";
+		pdev->id = 0;
+		pdev->dev.dma_mask = &alchemy_ehci_dmamask;
 
-static struct platform_device pbdb_smbus_device = {
-	.name		= "au1xpsc_smbus",
-	.id		= 0,	/* bus number */
-	.num_resources	= ARRAY_SIZE(pbdb_smbus_resources),
-	.resource	= pbdb_smbus_resources,
-};
-#endif
+		if (platform_device_register(pdev))
+			printk(KERN_INFO "Alchemy USB: cannot add EHCI0\n");
+	}
+}
 
 /* Macro to help defining the Ethernet MAC resources */
-#define MAC_RES_COUNT	3	/* MAC regs base, MAC enable reg, MAC INT */
-#define MAC_RES(_base, _enable, _irq)			\
+#define MAC_RES_COUNT	4	/* MAC regs, MAC en, MAC INT, MACDMA regs */
+#define MAC_RES(_base, _enable, _irq, _macdma)		\
 	{						\
 		.start	= _base,			\
 		.end	= _base + 0xffff,		\
@@ -389,28 +206,37 @@
 		.start	= _irq,				\
 		.end	= _irq,				\
 		.flags	= IORESOURCE_IRQ		\
+	},						\
+	{						\
+		.start	= _macdma,			\
+		.end	= _macdma + 0x1ff,		\
+		.flags	= IORESOURCE_MEM,		\
 	}
 
 static struct resource au1xxx_eth0_resources[][MAC_RES_COUNT] __initdata = {
 	[ALCHEMY_CPU_AU1000] = {
 		MAC_RES(AU1000_MAC0_PHYS_ADDR,
 			AU1000_MACEN_PHYS_ADDR,
-			AU1000_MAC0_DMA_INT)
+			AU1000_MAC0_DMA_INT,
+			AU1000_MACDMA0_PHYS_ADDR)
 	},
 	[ALCHEMY_CPU_AU1500] = {
 		MAC_RES(AU1500_MAC0_PHYS_ADDR,
 			AU1500_MACEN_PHYS_ADDR,
-			AU1500_MAC0_DMA_INT)
+			AU1500_MAC0_DMA_INT,
+			AU1000_MACDMA0_PHYS_ADDR)
 	},
 	[ALCHEMY_CPU_AU1100] = {
 		MAC_RES(AU1000_MAC0_PHYS_ADDR,
 			AU1000_MACEN_PHYS_ADDR,
-			AU1100_MAC0_DMA_INT)
+			AU1100_MAC0_DMA_INT,
+			AU1000_MACDMA0_PHYS_ADDR)
 	},
 	[ALCHEMY_CPU_AU1550] = {
 		MAC_RES(AU1000_MAC0_PHYS_ADDR,
 			AU1000_MACEN_PHYS_ADDR,
-			AU1550_MAC0_DMA_INT)
+			AU1550_MAC0_DMA_INT,
+			AU1000_MACDMA0_PHYS_ADDR)
 	},
 };
 
@@ -429,17 +255,20 @@
 	[ALCHEMY_CPU_AU1000] = {
 		MAC_RES(AU1000_MAC1_PHYS_ADDR,
 			AU1000_MACEN_PHYS_ADDR + 4,
-			AU1000_MAC1_DMA_INT)
+			AU1000_MAC1_DMA_INT,
+			AU1000_MACDMA1_PHYS_ADDR)
 	},
 	[ALCHEMY_CPU_AU1500] = {
 		MAC_RES(AU1500_MAC1_PHYS_ADDR,
 			AU1500_MACEN_PHYS_ADDR + 4,
-			AU1500_MAC1_DMA_INT)
+			AU1500_MAC1_DMA_INT,
+			AU1000_MACDMA1_PHYS_ADDR)
 	},
 	[ALCHEMY_CPU_AU1550] = {
 		MAC_RES(AU1000_MAC1_PHYS_ADDR,
 			AU1000_MACEN_PHYS_ADDR + 4,
-			AU1550_MAC1_DMA_INT)
+			AU1550_MAC1_DMA_INT,
+			AU1000_MACDMA1_PHYS_ADDR)
 	},
 };
 
@@ -521,36 +350,15 @@
 	}
 }
 
-static struct platform_device *au1xxx_platform_devices[] __initdata = {
-	&au1xxx_usb_ohci_device,
-#ifdef CONFIG_FB_AU1100
-	&au1100_lcd_device,
-#endif
-#ifdef CONFIG_SOC_AU1200
-	&au1xxx_usb_ehci_device,
-	&au1xxx_usb_gdt_device,
-	&au1xxx_usb_otg_device,
-	&au1200_lcd_device,
-	&au1200_mmc0_device,
-#ifndef CONFIG_MIPS_DB1200
-	&au1200_mmc1_device,
-#endif
-#endif
-#ifdef SMBUS_PSC_BASE
-	&pbdb_smbus_device,
-#endif
-};
-
 static int __init au1xxx_platform_init(void)
 {
-	int err, ctype = alchemy_get_cputype();
+	int ctype = alchemy_get_cputype();
 
 	alchemy_setup_uarts(ctype);
 	alchemy_setup_macs(ctype);
+	alchemy_setup_usb(ctype);
 
-	err = platform_add_devices(au1xxx_platform_devices,
-				   ARRAY_SIZE(au1xxx_platform_devices));
-	return err;
+	return 0;
 }
 
 arch_initcall(au1xxx_platform_init);
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/common/power.c linux-libre-3.2-gnu/arch/mips/alchemy/common/power.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/common/power.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/common/power.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,8 +37,6 @@
 #include <asm/uaccess.h>
 #include <asm/mach-au1x00/au1000.h>
 
-#ifdef CONFIG_PM
-
 /*
  * We need to save/restore a bunch of core registers that are
  * either volatile or reset to some state across a processor sleep.
@@ -49,7 +47,6 @@
  * We only have to save/restore registers that aren't otherwise
  * done as part of a driver pm_* function.
  */
-static unsigned int sleep_usb[2];
 static unsigned int sleep_sys_clocks[5];
 static unsigned int sleep_sys_pinfunc;
 static unsigned int sleep_static_memctlr[4][3];
@@ -57,31 +54,6 @@
 
 static void save_core_regs(void)
 {
-#ifndef CONFIG_SOC_AU1200
-	/* Shutdown USB host/device. */
-	sleep_usb[0] = au_readl(USB_HOST_CONFIG);
-
-	/* There appears to be some undocumented reset register.... */
-	au_writel(0, 0xb0100004);
-	au_sync();
-	au_writel(0, USB_HOST_CONFIG);
-	au_sync();
-
-	sleep_usb[1] = au_readl(USBD_ENABLE);
-	au_writel(0, USBD_ENABLE);
-	au_sync();
-
-#else	/* AU1200 */
-
-	/* enable access to OTG mmio so we can save OTG CAP/MUX.
-	 * FIXME: write an OTG driver and move this stuff there!
-	 */
-	au_writel(au_readl(USB_MSR_BASE + 4) | (1 << 6), USB_MSR_BASE + 4);
-	au_sync();
-	sleep_usb[0] = au_readl(0xb4020020);	/* OTG_CAP */
-	sleep_usb[1] = au_readl(0xb4020024);	/* OTG_MUX */
-#endif
-
 	/* Clocks and PLLs. */
 	sleep_sys_clocks[0] = au_readl(SYS_FREQCTRL0);
 	sleep_sys_clocks[1] = au_readl(SYS_FREQCTRL1);
@@ -125,22 +97,6 @@
 	au_writel(sleep_sys_pinfunc, SYS_PINFUNC);
 	au_sync();
 
-#ifndef CONFIG_SOC_AU1200
-	au_writel(sleep_usb[0], USB_HOST_CONFIG);
-	au_writel(sleep_usb[1], USBD_ENABLE);
-	au_sync();
-#else
-	/* enable access to OTG memory */
-	au_writel(au_readl(USB_MSR_BASE + 4) | (1 << 6), USB_MSR_BASE + 4);
-	au_sync();
-
-	/* restore OTG caps and port mux. */
-	au_writel(sleep_usb[0], 0xb4020020 + 0);	/* OTG_CAP */
-	au_sync();
-	au_writel(sleep_usb[1], 0xb4020020 + 4);	/* OTG_MUX */
-	au_sync();
-#endif
-
 	/* Restore the static memory controller configuration. */
 	au_writel(sleep_static_memctlr[0][0], MEM_STCFG0);
 	au_writel(sleep_static_memctlr[0][1], MEM_STTIME0);
@@ -174,5 +130,3 @@
 
 	restore_core_regs();
 }
-
-#endif	/* CONFIG_PM */
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/common/setup.c linux-libre-3.2-gnu/arch/mips/alchemy/common/setup.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/common/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/common/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -73,8 +73,8 @@
 /* This routine should be valid for all Au1x based boards */
 phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size)
 {
-	u32 start = (u32)Au1500_PCI_MEM_START;
-	u32 end   = (u32)Au1500_PCI_MEM_END;
+	unsigned long start = ALCHEMY_PCI_MEMWIN_START;
+	unsigned long end = ALCHEMY_PCI_MEMWIN_END;
 
 	/* Don't fixup 36-bit addresses */
 	if ((phys_addr >> 32) != 0)
@@ -82,7 +82,7 @@
 
 	/* Check for PCI memory window */
 	if (phys_addr >= start && (phys_addr + size - 1) <= end)
-		return (phys_t)((phys_addr - start) + Au1500_PCI_MEM_START);
+		return (phys_t)(AU1500_PCI_MEM_PHYS_ADDR + phys_addr);
 
 	/* default nop */
 	return phys_addr;
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/devboards/db1200/platform.c linux-libre-3.2-gnu/arch/mips/alchemy/devboards/db1200/platform.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/devboards/db1200/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/devboards/db1200/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -213,7 +213,12 @@
 		.start	= DB1200_IDE_INT,
 		.end	= DB1200_IDE_INT,
 		.flags	= IORESOURCE_IRQ,
-	}
+	},
+	[2] = {
+		.start	= AU1200_DSCR_CMD0_DMA_REQ1,
+		.end	= AU1200_DSCR_CMD0_DMA_REQ1,
+		.flags	= IORESOURCE_DMA,
+	},
 };
 
 static u64 ide_dmamask = DMA_BIT_MASK(32);
@@ -328,23 +333,85 @@
 	.brightness_set	= db1200_mmcled_set,
 };
 
-/* needed by arch/mips/alchemy/common/platform.c */
-struct au1xmmc_platform_data au1xmmc_platdata[] = {
+static struct au1xmmc_platform_data db1200mmc_platdata = {
+	.cd_setup	= db1200_mmc_cd_setup,
+	.set_power	= db1200_mmc_set_power,
+	.card_inserted	= db1200_mmc_card_inserted,
+	.card_readonly	= db1200_mmc_card_readonly,
+	.led		= &db1200_mmc_led,
+};
+
+static struct resource au1200_mmc0_resources[] = {
 	[0] = {
-		.cd_setup	= db1200_mmc_cd_setup,
-		.set_power	= db1200_mmc_set_power,
-		.card_inserted	= db1200_mmc_card_inserted,
-		.card_readonly	= db1200_mmc_card_readonly,
-		.led		= &db1200_mmc_led,
+		.start	= AU1100_SD0_PHYS_ADDR,
+		.end	= AU1100_SD0_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1200_SD_INT,
+		.end	= AU1200_SD_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= AU1200_DSCR_CMD0_SDMS_TX0,
+		.end	= AU1200_DSCR_CMD0_SDMS_TX0,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= AU1200_DSCR_CMD0_SDMS_RX0,
+		.end	= AU1200_DSCR_CMD0_SDMS_RX0,
+		.flags	= IORESOURCE_DMA,
+	}
+};
+
+static u64 au1xxx_mmc_dmamask =  DMA_BIT_MASK(32);
+
+static struct platform_device db1200_mmc0_dev = {
+	.name		= "au1xxx-mmc",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &au1xxx_mmc_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &db1200mmc_platdata,
+	},
+	.num_resources	= ARRAY_SIZE(au1200_mmc0_resources),
+	.resource	= au1200_mmc0_resources,
+};
+
+/**********************************************************************/
+
+static struct resource au1200_lcd_res[] = {
+	[0] = {
+		.start	= AU1200_LCD_PHYS_ADDR,
+		.end	= AU1200_LCD_PHYS_ADDR + 0x800 - 1,
+		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= AU1200_LCD_INT,
+		.end	= AU1200_LCD_INT,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static u64 au1200_lcd_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device au1200_lcd_dev = {
+	.name		= "au1200-lcd",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &au1200_lcd_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(au1200_lcd_res),
+	.resource	= au1200_lcd_res,
 };
 
 /**********************************************************************/
 
 static struct resource au1200_psc0_res[] = {
 	[0] = {
-		.start	= PSC0_PHYS_ADDR,
-		.end	= PSC0_PHYS_ADDR + 0x000fffff,
+		.start	= AU1550_PSC0_PHYS_ADDR,
+		.end	= AU1550_PSC0_PHYS_ADDR + 0xfff,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -353,13 +420,13 @@
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
-		.start	= DSCR_CMD0_PSC0_TX,
-		.end	= DSCR_CMD0_PSC0_TX,
+		.start	= AU1200_DSCR_CMD0_PSC0_TX,
+		.end	= AU1200_DSCR_CMD0_PSC0_TX,
 		.flags	= IORESOURCE_DMA,
 	},
 	[3] = {
-		.start	= DSCR_CMD0_PSC0_RX,
-		.end	= DSCR_CMD0_PSC0_RX,
+		.start	= AU1200_DSCR_CMD0_PSC0_RX,
+		.end	= AU1200_DSCR_CMD0_PSC0_RX,
 		.flags	= IORESOURCE_DMA,
 	},
 };
@@ -401,8 +468,8 @@
 
 static struct resource au1200_psc1_res[] = {
 	[0] = {
-		.start	= PSC1_PHYS_ADDR,
-		.end	= PSC1_PHYS_ADDR + 0x000fffff,
+		.start	= AU1550_PSC1_PHYS_ADDR,
+		.end	= AU1550_PSC1_PHYS_ADDR + 0xfff,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -411,17 +478,18 @@
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
-		.start	= DSCR_CMD0_PSC1_TX,
-		.end	= DSCR_CMD0_PSC1_TX,
+		.start	= AU1200_DSCR_CMD0_PSC1_TX,
+		.end	= AU1200_DSCR_CMD0_PSC1_TX,
 		.flags	= IORESOURCE_DMA,
 	},
 	[3] = {
-		.start	= DSCR_CMD0_PSC1_RX,
-		.end	= DSCR_CMD0_PSC1_RX,
+		.start	= AU1200_DSCR_CMD0_PSC1_RX,
+		.end	= AU1200_DSCR_CMD0_PSC1_RX,
 		.flags	= IORESOURCE_DMA,
 	},
 };
 
+/* AC97 or I2S device */
 static struct platform_device db1200_audio_dev = {
 	/* name assigned later based on switch setting */
 	.id		= 1,	/* PSC ID */
@@ -429,19 +497,34 @@
 	.resource	= au1200_psc1_res,
 };
 
+/* DB1200 ASoC card device */
+static struct platform_device db1200_sound_dev = {
+	/* name assigned later based on switch setting */
+	.id		= 1,	/* PSC ID */
+};
+
 static struct platform_device db1200_stac_dev = {
 	.name		= "ac97-codec",
 	.id		= 1,	/* on PSC1 */
 };
 
+static struct platform_device db1200_audiodma_dev = {
+	.name		= "au1xpsc-pcm",
+	.id		= 1,	/* PSC ID */
+};
+
 static struct platform_device *db1200_devs[] __initdata = {
 	NULL,		/* PSC0, selected by S6.8 */
 	&db1200_ide_dev,
+	&db1200_mmc0_dev,
+	&au1200_lcd_dev,
 	&db1200_eth_dev,
 	&db1200_rtc_dev,
 	&db1200_nand_dev,
+	&db1200_audiodma_dev,
 	&db1200_audio_dev,
 	&db1200_stac_dev,
+	&db1200_sound_dev,
 };
 
 static int __init db1200_dev_init(void)
@@ -501,41 +584,39 @@
 	if (sw == BCSR_SWITCHES_DIP_8) {
 		bcsr_mod(BCSR_RESETS, 0, BCSR_RESETS_PSC1MUX);
 		db1200_audio_dev.name = "au1xpsc_i2s";
+		db1200_sound_dev.name = "db1200-i2s";
 		printk(KERN_INFO " S6.7 ON : PSC1 mode I2S\n");
 	} else {
 		bcsr_mod(BCSR_RESETS, BCSR_RESETS_PSC1MUX, 0);
 		db1200_audio_dev.name = "au1xpsc_ac97";
+		db1200_sound_dev.name = "db1200-ac97";
 		printk(KERN_INFO " S6.7 OFF: PSC1 mode AC97\n");
 	}
 
 	/* Audio PSC clock is supplied externally. (FIXME: platdata!!) */
 	__raw_writel(PSC_SEL_CLK_SERCLK,
-		(void __iomem *)KSEG1ADDR(PSC1_PHYS_ADDR) + PSC_SEL_OFFSET);
+		(void __iomem *)KSEG1ADDR(AU1550_PSC1_PHYS_ADDR) + PSC_SEL_OFFSET);
 	wmb();
 
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR,
-				    PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
-				    DB1200_PC0_INT,
-				    DB1200_PC0_INSERT_INT,
-				    /*DB1200_PC0_STSCHG_INT*/0,
-				    DB1200_PC0_EJECT_INT,
-				    0);
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
+		DB1200_PC0_INT, DB1200_PC0_INSERT_INT,
+		/*DB1200_PC0_STSCHG_INT*/0, DB1200_PC0_EJECT_INT, 0);
 
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR + 0x004000000,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x004000000,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x004400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR   + 0x004000000,
-				    PCMCIA_IO_PHYS_ADDR   + 0x004010000 - 1,
-				    DB1200_PC1_INT,
-				    DB1200_PC1_INSERT_INT,
-				    /*DB1200_PC1_STSCHG_INT*/0,
-				    DB1200_PC1_EJECT_INT,
-				    1);
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004000000,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x004000000,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x004400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004000000,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004010000 - 1,
+		DB1200_PC1_INT, DB1200_PC1_INSERT_INT,
+		/*DB1200_PC1_STSCHG_INT*/0, DB1200_PC1_EJECT_INT, 1);
 
 	swapped = bcsr_read(BCSR_STATUS) & BCSR_STATUS_DB1200_SWAPBOOT;
 	db1x_register_norflash(64 << 20, 2, swapped);
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/devboards/db1x00/board_setup.c linux-libre-3.2-gnu/arch/mips/alchemy/devboards/db1x00/board_setup.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/devboards/db1x00/board_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/devboards/db1x00/board_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,24 +40,6 @@
 
 #include <prom.h>
 
-#ifdef CONFIG_MIPS_DB1500
-char irq_tab_alchemy[][5] __initdata = {
-	[12] = { -1, AU1500_PCI_INTA, 0xff, 0xff, 0xff }, /* IDSEL 12 - HPT371   */
-	[13] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, AU1500_PCI_INTC, AU1500_PCI_INTD }, /* IDSEL 13 - PCI slot */
-};
-
-#endif
-
-
-#ifdef CONFIG_MIPS_DB1550
-char irq_tab_alchemy[][5] __initdata = {
-	[11] = { -1, AU1550_PCI_INTC, 0xff, 0xff, 0xff }, /* IDSEL 11 - on-board HPT371 */
-	[12] = { -1, AU1550_PCI_INTB, AU1550_PCI_INTC, AU1550_PCI_INTD, AU1550_PCI_INTA }, /* IDSEL 12 - PCI slot 2 (left) */
-	[13] = { -1, AU1550_PCI_INTA, AU1550_PCI_INTB, AU1550_PCI_INTC, AU1550_PCI_INTD }, /* IDSEL 13 - PCI slot 1 (right) */
-};
-#endif
-
-
 #ifdef CONFIG_MIPS_BOSPORUS
 char irq_tab_alchemy[][5] __initdata = {
 	[11] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, 0xff, 0xff }, /* IDSEL 11 - miniPCI  */
@@ -91,12 +73,6 @@
 
 
 #ifdef CONFIG_MIPS_MIRAGE
-char irq_tab_alchemy[][5] __initdata = {
-	[11] = { -1, AU1500_PCI_INTD, 0xff, 0xff, 0xff }, /* IDSEL 11 - SMI VGX */
-	[12] = { -1, 0xff, 0xff, AU1500_PCI_INTC, 0xff }, /* IDSEL 12 - PNX1300 */
-	[13] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, 0xff, 0xff }, /* IDSEL 13 - miniPCI */
-};
-
 static void mirage_power_off(void)
 {
 	alchemy_gpio_direction_output(210, 1);
@@ -158,9 +134,7 @@
 	/* initialize board register space */
 	bcsr_init(bcsr1, bcsr2);
 
-	/* Not valid for Au1550 */
-#if defined(CONFIG_IRDA) && \
-   (defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100))
+#if defined(CONFIG_IRDA) && defined(CONFIG_AU1000_FIR)
 	{
 		u32 pin_func;
 
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/devboards/db1x00/platform.c linux-libre-3.2-gnu/arch/mips/alchemy/devboards/db1x00/platform.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/devboards/db1x00/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/devboards/db1x00/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,12 +19,17 @@
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 
-#include <asm/mach-au1x00/au1xxx.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1000_dma.h>
 #include <asm/mach-db1x00/bcsr.h>
 #include "../platform.h"
 
+struct pci_dev;
+
 /* DB1xxx PCMCIA interrupt sources:
  * CD0/1 	GPIO0/3
  * STSCHG0/1	GPIO1/4
@@ -85,34 +90,227 @@
 #endif
 #endif
 
+#ifdef CONFIG_PCI
+#ifdef CONFIG_MIPS_DB1500
+static int db1xxx_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+	if ((slot < 12) || (slot > 13) || pin == 0)
+		return -1;
+	if (slot == 12)
+		return (pin == 1) ? AU1500_PCI_INTA : 0xff;
+	if (slot == 13) {
+		switch (pin) {
+		case 1: return AU1500_PCI_INTA;
+		case 2: return AU1500_PCI_INTB;
+		case 3: return AU1500_PCI_INTC;
+		case 4: return AU1500_PCI_INTD;
+		}
+	}
+	return -1;
+}
+#endif
+
+#ifdef CONFIG_MIPS_DB1550
+static int db1xxx_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+	if ((slot < 11) || (slot > 13) || pin == 0)
+		return -1;
+	if (slot == 11)
+		return (pin == 1) ? AU1550_PCI_INTC : 0xff;
+	if (slot == 12) {
+		switch (pin) {
+		case 1: return AU1550_PCI_INTB;
+		case 2: return AU1550_PCI_INTC;
+		case 3: return AU1550_PCI_INTD;
+		case 4: return AU1550_PCI_INTA;
+		}
+	}
+	if (slot == 13) {
+		switch (pin) {
+		case 1: return AU1550_PCI_INTA;
+		case 2: return AU1550_PCI_INTB;
+		case 3: return AU1550_PCI_INTC;
+		case 4: return AU1550_PCI_INTD;
+		}
+	}
+	return -1;
+}
+#endif
+
+#ifdef CONFIG_MIPS_BOSPORUS
+static int db1xxx_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+	if ((slot < 11) || (slot > 13) || pin == 0)
+		return -1;
+	if (slot == 12)
+		return (pin == 1) ? AU1500_PCI_INTA : 0xff;
+	if (slot == 11) {
+		switch (pin) {
+		case 1: return AU1500_PCI_INTA;
+		case 2: return AU1500_PCI_INTB;
+		default: return 0xff;
+		}
+	}
+	if (slot == 13) {
+		switch (pin) {
+		case 1: return AU1500_PCI_INTA;
+		case 2: return AU1500_PCI_INTB;
+		case 3: return AU1500_PCI_INTC;
+		case 4: return AU1500_PCI_INTD;
+		}
+	}
+	return -1;
+}
+#endif
+
+#ifdef CONFIG_MIPS_MIRAGE
+static int db1xxx_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+	if ((slot < 11) || (slot > 13) || pin == 0)
+		return -1;
+	if (slot == 11)
+		return (pin == 1) ? AU1500_PCI_INTD : 0xff;
+	if (slot == 12)
+		return (pin == 3) ? AU1500_PCI_INTC : 0xff;
+	if (slot == 13) {
+		switch (pin) {
+		case 1: return AU1500_PCI_INTA;
+		case 2: return AU1500_PCI_INTB;
+		default: return 0xff;
+		}
+	}
+	return -1;
+}
+#endif
+
+static struct resource alchemy_pci_host_res[] = {
+	[0] = {
+		.start	= AU1500_PCI_PHYS_ADDR,
+		.end	= AU1500_PCI_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct alchemy_pci_platdata db1xxx_pci_pd = {
+	.board_map_irq	= db1xxx_map_pci_irq,
+};
+
+static struct platform_device db1xxx_pci_host_dev = {
+	.dev.platform_data = &db1xxx_pci_pd,
+	.name		= "alchemy-pci",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(alchemy_pci_host_res),
+	.resource	= alchemy_pci_host_res,
+};
+
+static int __init db15x0_pci_init(void)
+{
+	return platform_device_register(&db1xxx_pci_host_dev);
+}
+/* must be arch_initcall; MIPS PCI scans busses in a subsys_initcall */
+arch_initcall(db15x0_pci_init);
+#endif
+
+#ifdef CONFIG_MIPS_DB1100
+static struct resource au1100_lcd_resources[] = {
+	[0] = {
+		.start	= AU1100_LCD_PHYS_ADDR,
+		.end	= AU1100_LCD_PHYS_ADDR + 0x800 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1100_LCD_INT,
+		.end	= AU1100_LCD_INT,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static u64 au1100_lcd_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device au1100_lcd_device = {
+	.name		= "au1100-lcd",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &au1100_lcd_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(au1100_lcd_resources),
+	.resource	= au1100_lcd_resources,
+};
+#endif
+
+static struct resource alchemy_ac97c_res[] = {
+	[0] = {
+		.start	= AU1000_AC97_PHYS_ADDR,
+		.end	= AU1000_AC97_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMA_ID_AC97C_TX,
+		.end	= DMA_ID_AC97C_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMA_ID_AC97C_RX,
+		.end	= DMA_ID_AC97C_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct platform_device alchemy_ac97c_dev = {
+	.name		= "alchemy-ac97c",
+	.id		= -1,
+	.resource	= alchemy_ac97c_res,
+	.num_resources	= ARRAY_SIZE(alchemy_ac97c_res),
+};
+
+static struct platform_device alchemy_ac97c_dma_dev = {
+	.name		= "alchemy-pcm-dma",
+	.id		= 0,
+};
+
+static struct platform_device db1x00_codec_dev = {
+	.name		= "ac97-codec",
+	.id		= -1,
+};
+
+static struct platform_device db1x00_audio_dev = {
+	.name		= "db1000-audio",
+};
+
 static int __init db1xxx_dev_init(void)
 {
 #ifdef DB1XXX_HAS_PCMCIA
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR,
-				    PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
-				    DB1XXX_PCMCIA_CARD0,
-				    DB1XXX_PCMCIA_CD0,
-				    /*DB1XXX_PCMCIA_STSCHG0*/0,
-				    0,
-				    0);
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
+		DB1XXX_PCMCIA_CARD0, DB1XXX_PCMCIA_CD0,
+		/*DB1XXX_PCMCIA_STSCHG0*/0, 0, 0);
 
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR + 0x004000000,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x004000000,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x004400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR   + 0x004000000,
-				    PCMCIA_IO_PHYS_ADDR   + 0x004010000 - 1,
-				    DB1XXX_PCMCIA_CARD1,
-				    DB1XXX_PCMCIA_CD1,
-				    /*DB1XXX_PCMCIA_STSCHG1*/0,
-				    0,
-				    1);
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004000000,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x004000000,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x004400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004000000,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004010000 - 1,
+		DB1XXX_PCMCIA_CARD1, DB1XXX_PCMCIA_CD1,
+		/*DB1XXX_PCMCIA_STSCHG1*/0, 0, 1);
+#endif
+#ifdef CONFIG_MIPS_DB1100
+	platform_device_register(&au1100_lcd_device);
 #endif
 	db1x_register_norflash(BOARD_FLASH_SIZE, BOARD_FLASH_WIDTH, F_SWAPPED);
+
+	platform_device_register(&db1x00_codec_dev);
+	platform_device_register(&alchemy_ac97c_dma_dev);
+	platform_device_register(&alchemy_ac97c_dev);
+	platform_device_register(&db1x00_audio_dev);
+
 	return 0;
 }
 device_initcall(db1xxx_dev_init);
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/devboards/pb1100/platform.c linux-libre-3.2-gnu/arch/mips/alchemy/devboards/pb1100/platform.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/devboards/pb1100/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/devboards/pb1100/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,31 +19,58 @@
  */
 
 #include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
 
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-db1x00/bcsr.h>
 
 #include "../platform.h"
 
+static struct resource au1100_lcd_resources[] = {
+	[0] = {
+		.start	= AU1100_LCD_PHYS_ADDR,
+		.end	= AU1100_LCD_PHYS_ADDR + 0x800 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1100_LCD_INT,
+		.end	= AU1100_LCD_INT,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static u64 au1100_lcd_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device au1100_lcd_device = {
+	.name		= "au1100-lcd",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &au1100_lcd_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(au1100_lcd_resources),
+	.resource	= au1100_lcd_resources,
+};
+
 static int __init pb1100_dev_init(void)
 {
 	int swapped;
 
 	/* PCMCIA. single socket, identical to Pb1500 */
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR,
-				    PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
-				    AU1100_GPIO11_INT,	 /* card */
-				    AU1100_GPIO9_INT,	 /* insert */
-				    /*AU1100_GPIO10_INT*/0, /* stschg */
-				    0,			 /* eject */
-				    0);			 /* id */
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
+		AU1100_GPIO11_INT, AU1100_GPIO9_INT,	 /* card / insert */
+		/*AU1100_GPIO10_INT*/0, 0, 0); /* stschg / eject / id */
 
 	swapped = bcsr_read(BCSR_STATUS) &  BCSR_STATUS_DB1000_SWAPBOOT;
 	db1x_register_norflash(64 * 1024 * 1024, 4, swapped);
+	platform_device_register(&au1100_lcd_device);
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/devboards/pb1200/platform.c linux-libre-3.2-gnu/arch/mips/alchemy/devboards/pb1200/platform.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/devboards/pb1200/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/devboards/pb1200/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,9 +24,11 @@
 #include <linux/platform_device.h>
 #include <linux/smc91x.h>
 
-#include <asm/mach-au1x00/au1xxx.h>
+#include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1100_mmc.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
 #include <asm/mach-db1x00/bcsr.h>
+#include <asm/mach-pb1x00/pb1200.h>
 
 #include "../platform.h"
 
@@ -88,7 +90,7 @@
 	return (bcsr_read(BCSR_SIGSTAT) & BCSR_INT_SD1INSERT) ? 1 : 0;
 }
 
-const struct au1xmmc_platform_data au1xmmc_platdata[2] = {
+static struct au1xmmc_platform_data pb1200mmc_platdata[2] = {
 	[0] = {
 		.set_power	= pb1200mmc0_set_power,
 		.card_inserted	= pb1200mmc0_card_inserted,
@@ -105,6 +107,79 @@
 	},
 };
 
+static u64 au1xxx_mmc_dmamask =  DMA_BIT_MASK(32);
+
+static struct resource au1200_mmc0_res[] = {
+	[0] = {
+		.start	= AU1100_SD0_PHYS_ADDR,
+		.end	= AU1100_SD0_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1200_SD_INT,
+		.end	= AU1200_SD_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= AU1200_DSCR_CMD0_SDMS_TX0,
+		.end	= AU1200_DSCR_CMD0_SDMS_TX0,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= AU1200_DSCR_CMD0_SDMS_RX0,
+		.end	= AU1200_DSCR_CMD0_SDMS_RX0,
+		.flags	= IORESOURCE_DMA,
+	}
+};
+
+static struct platform_device pb1200_mmc0_dev = {
+	.name		= "au1xxx-mmc",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &au1xxx_mmc_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &pb1200mmc_platdata[0],
+	},
+	.num_resources	= ARRAY_SIZE(au1200_mmc0_res),
+	.resource	= au1200_mmc0_res,
+};
+
+static struct resource au1200_mmc1_res[] = {
+	[0] = {
+		.start	= AU1100_SD1_PHYS_ADDR,
+		.end	= AU1100_SD1_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1200_SD_INT,
+		.end	= AU1200_SD_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= AU1200_DSCR_CMD0_SDMS_TX1,
+		.end	= AU1200_DSCR_CMD0_SDMS_TX1,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= AU1200_DSCR_CMD0_SDMS_RX1,
+		.end	= AU1200_DSCR_CMD0_SDMS_RX1,
+		.flags	= IORESOURCE_DMA,
+	}
+};
+
+static struct platform_device pb1200_mmc1_dev = {
+	.name		= "au1xxx-mmc",
+	.id		= 1,
+	.dev = {
+		.dma_mask		= &au1xxx_mmc_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &pb1200mmc_platdata[1],
+	},
+	.num_resources	= ARRAY_SIZE(au1200_mmc1_res),
+	.resource	= au1200_mmc1_res,
+};
+
+
 static struct resource ide_resources[] = {
 	[0] = {
 		.start	= IDE_PHYS_ADDR,
@@ -115,7 +190,12 @@
 		.start	= IDE_INT,
 		.end	= IDE_INT,
 		.flags	= IORESOURCE_IRQ
-	}
+	},
+	[2] = {
+		.start	= AU1200_DSCR_CMD0_DMA_REQ1,
+		.end	= AU1200_DSCR_CMD0_DMA_REQ1,
+		.flags	= IORESOURCE_DMA,
+	},
 };
 
 static u64 ide_dmamask = DMA_BIT_MASK(32);
@@ -161,38 +241,94 @@
 	.resource	= smc91c111_resources
 };
 
+static struct resource au1200_psc0_res[] = {
+	[0] = {
+		.start	= AU1550_PSC0_PHYS_ADDR,
+		.end	= AU1550_PSC0_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1200_PSC0_INT,
+		.end	= AU1200_PSC0_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= AU1200_DSCR_CMD0_PSC0_TX,
+		.end	= AU1200_DSCR_CMD0_PSC0_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= AU1200_DSCR_CMD0_PSC0_RX,
+		.end	= AU1200_DSCR_CMD0_PSC0_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct platform_device pb1200_i2c_dev = {
+	.name		= "au1xpsc_smbus",
+	.id		= 0,	/* bus number */
+	.num_resources	= ARRAY_SIZE(au1200_psc0_res),
+	.resource	= au1200_psc0_res,
+};
+
+static struct resource au1200_lcd_res[] = {
+	[0] = {
+		.start	= AU1200_LCD_PHYS_ADDR,
+		.end	= AU1200_LCD_PHYS_ADDR + 0x800 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1200_LCD_INT,
+		.end	= AU1200_LCD_INT,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static u64 au1200_lcd_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device au1200_lcd_dev = {
+	.name		= "au1200-lcd",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &au1200_lcd_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(au1200_lcd_res),
+	.resource	= au1200_lcd_res,
+};
+
 static struct platform_device *board_platform_devices[] __initdata = {
 	&ide_device,
-	&smc91c111_device
+	&smc91c111_device,
+	&pb1200_i2c_dev,
+	&pb1200_mmc0_dev,
+	&pb1200_mmc1_dev,
+	&au1200_lcd_dev,
 };
 
 static int __init board_register_devices(void)
 {
 	int swapped;
 
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR,
-				    PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
-				    PB1200_PC0_INT,
-				    PB1200_PC0_INSERT_INT,
-				    /*PB1200_PC0_STSCHG_INT*/0,
-				    PB1200_PC0_EJECT_INT,
-				    0);
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
+		PB1200_PC0_INT, PB1200_PC0_INSERT_INT,
+		/*PB1200_PC0_STSCHG_INT*/0, PB1200_PC0_EJECT_INT, 0);
 
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR + 0x008000000,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x008400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x008000000,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x008400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR   + 0x008000000,
-				    PCMCIA_IO_PHYS_ADDR   + 0x008010000 - 1,
-				    PB1200_PC1_INT,
-				    PB1200_PC1_INSERT_INT,
-				    /*PB1200_PC1_STSCHG_INT*/0,
-				    PB1200_PC1_EJECT_INT,
-				    1);
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x008000000,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x008400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x008000000,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x008400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x008000000,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x008010000 - 1,
+		PB1200_PC1_INT, PB1200_PC1_INSERT_INT,
+		/*PB1200_PC1_STSCHG_INT*/0, PB1200_PC1_EJECT_INT, 1);
 
 	swapped = bcsr_read(BCSR_STATUS) &  BCSR_STATUS_DB1200_SWAPBOOT;
 	db1x_register_norflash(128 * 1024 * 1024, 2, swapped);
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/devboards/pb1500/board_setup.c linux-libre-3.2-gnu/arch/mips/alchemy/devboards/pb1500/board_setup.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/devboards/pb1500/board_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/devboards/pb1500/board_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,13 +33,6 @@
 
 #include <prom.h>
 
-
-char irq_tab_alchemy[][5] __initdata = {
-	[12] = { -1, AU1500_PCI_INTA, 0xff, 0xff, 0xff },   /* IDSEL 12 - HPT370	*/
-	[13] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, AU1500_PCI_INTC, AU1500_PCI_INTD },   /* IDSEL 13 - PCI slot */
-};
-
-
 const char *get_system_type(void)
 {
 	return "Alchemy Pb1500";
@@ -101,20 +94,18 @@
 #endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */
 
 #ifdef CONFIG_PCI
-	/* Setup PCI bus controller */
-	au_writel(0, Au1500_PCI_CMEM);
-	au_writel(0x00003fff, Au1500_CFG_BASE);
-#if defined(__MIPSEB__)
-	au_writel(0xf | (2 << 6) | (1 << 4), Au1500_PCI_CFG);
-#else
-	au_writel(0xf, Au1500_PCI_CFG);
-#endif
-	au_writel(0xf0000000, Au1500_PCI_MWMASK_DEV);
-	au_writel(0, Au1500_PCI_MWBASE_REV_CCL);
-	au_writel(0x02a00356, Au1500_PCI_STATCMD);
-	au_writel(0x00003c04, Au1500_PCI_HDRTYPE);
-	au_writel(0x00000008, Au1500_PCI_MBAR);
-	au_sync();
+	{
+		void __iomem *base =
+				(void __iomem *)KSEG1ADDR(AU1500_PCI_PHYS_ADDR);
+		/* Setup PCI bus controller */
+		__raw_writel(0x00003fff, base + PCI_REG_CMEM);
+		__raw_writel(0xf0000000, base + PCI_REG_MWMASK_DEV);
+		__raw_writel(0, base + PCI_REG_MWBASE_REV_CCL);
+		__raw_writel(0x02a00356, base + PCI_REG_STATCMD);
+		__raw_writel(0x00003c04, base + PCI_REG_PARAM);
+		__raw_writel(0x00000008, base + PCI_REG_MBAR);
+		wmb();
+	}
 #endif
 
 	/* Enable sys bus clock divider when IDLE state or no bus activity. */
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/devboards/pb1500/platform.c linux-libre-3.2-gnu/arch/mips/alchemy/devboards/pb1500/platform.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/devboards/pb1500/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/devboards/pb1500/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,32 +18,77 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-db1x00/bcsr.h>
 
 #include "../platform.h"
 
+static int pb1500_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+	if ((slot < 12) || (slot > 13) || pin == 0)
+		return -1;
+	if (slot == 12)
+		return (pin == 1) ? AU1500_PCI_INTA : 0xff;
+	if (slot == 13) {
+		switch (pin) {
+		case 1: return AU1500_PCI_INTA;
+		case 2: return AU1500_PCI_INTB;
+		case 3: return AU1500_PCI_INTC;
+		case 4: return AU1500_PCI_INTD;
+		}
+	}
+	return -1;
+}
+
+static struct resource alchemy_pci_host_res[] = {
+	[0] = {
+		.start	= AU1500_PCI_PHYS_ADDR,
+		.end	= AU1500_PCI_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct alchemy_pci_platdata pb1500_pci_pd = {
+	.board_map_irq	= pb1500_map_pci_irq,
+	.pci_cfg_set	= PCI_CONFIG_AEN | PCI_CONFIG_R2H | PCI_CONFIG_R1H |
+			  PCI_CONFIG_CH |
+#if defined(__MIPSEB__)
+			  PCI_CONFIG_SIC_HWA_DAT | PCI_CONFIG_SM,
+#else
+			  0,
+#endif
+};
+
+static struct platform_device pb1500_pci_host = {
+	.dev.platform_data = &pb1500_pci_pd,
+	.name		= "alchemy-pci",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(alchemy_pci_host_res),
+	.resource	= alchemy_pci_host_res,
+};
+
 static int __init pb1500_dev_init(void)
 {
 	int swapped;
 
-	/* PCMCIA. single socket, identical to Pb1500 */
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR,
-				    PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
-				    AU1500_GPIO11_INT,	 /* card */
-				    AU1500_GPIO9_INT,	 /* insert */
-				    /*AU1500_GPIO10_INT*/0, /* stschg */
-				    0,			 /* eject */
-				    0);			 /* id */
+	/* PCMCIA. single socket, identical to Pb1100 */
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
+		AU1500_GPIO11_INT, AU1500_GPIO9_INT,	 /* card / insert */
+		/*AU1500_GPIO10_INT*/0, 0, 0); /* stschg / eject / id */
 
 	swapped = bcsr_read(BCSR_STATUS) &  BCSR_STATUS_DB1000_SWAPBOOT;
 	db1x_register_norflash(64 * 1024 * 1024, 4, swapped);
+	platform_device_register(&pb1500_pci_host);
 
 	return 0;
 }
-device_initcall(pb1500_dev_init);
+arch_initcall(pb1500_dev_init);
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/devboards/pb1550/board_setup.c linux-libre-3.2-gnu/arch/mips/alchemy/devboards/pb1550/board_setup.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/devboards/pb1550/board_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/devboards/pb1550/board_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,12 +37,6 @@
 
 #include <prom.h>
 
-
-char irq_tab_alchemy[][5] __initdata = {
-	[12] = { -1, AU1550_PCI_INTB, AU1550_PCI_INTC, AU1550_PCI_INTD, AU1550_PCI_INTA }, /* IDSEL 12 - PCI slot 2 (left)  */
-	[13] = { -1, AU1550_PCI_INTA, AU1550_PCI_INTB, AU1550_PCI_INTC, AU1550_PCI_INTD }, /* IDSEL 13 - PCI slot 1 (right) */
-};
-
 const char *get_system_type(void)
 {
 	return "Alchemy Pb1550";
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/devboards/pb1550/platform.c linux-libre-3.2-gnu/arch/mips/alchemy/devboards/pb1550/platform.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/devboards/pb1550/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/devboards/pb1550/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,14 +18,89 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/init.h>
-
+#include <linux/platform_device.h>
 #include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
 #include <asm/mach-pb1x00/pb1550.h>
 #include <asm/mach-db1x00/bcsr.h>
 
 #include "../platform.h"
 
+static int pb1550_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+	if ((slot < 12) || (slot > 13) || pin == 0)
+		return -1;
+	if (slot == 12) {
+		switch (pin) {
+		case 1: return AU1500_PCI_INTB;
+		case 2: return AU1500_PCI_INTC;
+		case 3: return AU1500_PCI_INTD;
+		case 4: return AU1500_PCI_INTA;
+		}
+	}
+	if (slot == 13) {
+		switch (pin) {
+		case 1: return AU1500_PCI_INTA;
+		case 2: return AU1500_PCI_INTB;
+		case 3: return AU1500_PCI_INTC;
+		case 4: return AU1500_PCI_INTD;
+		}
+	}
+	return -1;
+}
+
+static struct resource alchemy_pci_host_res[] = {
+	[0] = {
+		.start	= AU1500_PCI_PHYS_ADDR,
+		.end	= AU1500_PCI_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct alchemy_pci_platdata pb1550_pci_pd = {
+	.board_map_irq	= pb1550_map_pci_irq,
+};
+
+static struct platform_device pb1550_pci_host = {
+	.dev.platform_data = &pb1550_pci_pd,
+	.name		= "alchemy-pci",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(alchemy_pci_host_res),
+	.resource	= alchemy_pci_host_res,
+};
+
+static struct resource au1550_psc2_res[] = {
+	[0] = {
+		.start	= AU1550_PSC2_PHYS_ADDR,
+		.end	= AU1550_PSC2_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1550_PSC2_INT,
+		.end	= AU1550_PSC2_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= AU1550_DSCR_CMD0_PSC2_TX,
+		.end	= AU1550_DSCR_CMD0_PSC2_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= AU1550_DSCR_CMD0_PSC2_RX,
+		.end	= AU1550_DSCR_CMD0_PSC2_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct platform_device pb1550_i2c_dev = {
+	.name		= "au1xpsc_smbus",
+	.id		= 0,	/* bus number */
+	.num_resources	= ARRAY_SIZE(au1550_psc2_res),
+	.resource	= au1550_psc2_res,
+};
+
 static int __init pb1550_dev_init(void)
 {
 	int swapped;
@@ -37,33 +112,29 @@
 	* drivers are used to shared irqs and b) statuschange isn't really use-
 	* ful anyway.
 	*/
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR,
-				    PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
-				    AU1550_GPIO201_205_INT,
-				    AU1550_GPIO0_INT,
-				    0,
-				    0,
-				    0);
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
+		AU1550_GPIO201_205_INT, AU1550_GPIO0_INT, 0, 0, 0);
 
-	db1x_register_pcmcia_socket(PCMCIA_ATTR_PHYS_ADDR + 0x008000000,
-				    PCMCIA_ATTR_PHYS_ADDR + 0x008400000 - 1,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x008000000,
-				    PCMCIA_MEM_PHYS_ADDR  + 0x008400000 - 1,
-				    PCMCIA_IO_PHYS_ADDR   + 0x008000000,
-				    PCMCIA_IO_PHYS_ADDR   + 0x008010000 - 1,
-				    AU1550_GPIO201_205_INT,
-				    AU1550_GPIO1_INT,
-				    0,
-				    0,
-				    1);
+	db1x_register_pcmcia_socket(
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x008000000,
+		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x008400000 - 1,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x008000000,
+		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x008400000 - 1,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x008000000,
+		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x008010000 - 1,
+		AU1550_GPIO201_205_INT, AU1550_GPIO1_INT, 0, 0, 1);
 
 	swapped = bcsr_read(BCSR_STATUS) & BCSR_STATUS_PB1550_SWAPBOOT;
 	db1x_register_norflash(128 * 1024 * 1024, 4, swapped);
+	platform_device_register(&pb1550_pci_host);
+	platform_device_register(&pb1550_i2c_dev);
 
 	return 0;
 }
-device_initcall(pb1550_dev_init);
+arch_initcall(pb1550_dev_init);
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/gpr/board_setup.c linux-libre-3.2-gnu/arch/mips/alchemy/gpr/board_setup.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/gpr/board_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/gpr/board_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,10 +36,6 @@
 
 #include <prom.h>
 
-char irq_tab_alchemy[][5] __initdata = {
-	[0] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, 0xff, 0xff },
-};
-
 static void gpr_reset(char *c)
 {
 	/* switch System-LED to orange (red# and green# on) */
@@ -76,12 +72,4 @@
 
 	/* Take away Reset of UMTS-card */
 	alchemy_gpio_direction_output(215, 1);
-
-#ifdef CONFIG_PCI
-#if defined(__MIPSEB__)
-	au_writel(0xf | (2 << 6) | (1 << 4), Au1500_PCI_CFG);
-#else
-	au_writel(0xf, Au1500_PCI_CFG);
-#endif
-#endif
 }
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/gpr/platform.c linux-libre-3.2-gnu/arch/mips/alchemy/gpr/platform.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/gpr/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/gpr/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -167,6 +167,45 @@
 	}
 };
 
+
+
+static struct resource alchemy_pci_host_res[] = {
+	[0] = {
+		.start	= AU1500_PCI_PHYS_ADDR,
+		.end	= AU1500_PCI_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static int gpr_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+	if ((slot == 0) && (pin == 1))
+		return AU1550_PCI_INTA;
+	else if ((slot == 0) && (pin == 2))
+		return AU1550_PCI_INTB;
+
+	return -1;
+}
+
+static struct alchemy_pci_platdata gpr_pci_pd = {
+	.board_map_irq	= gpr_map_pci_irq,
+	.pci_cfg_set	= PCI_CONFIG_AEN | PCI_CONFIG_R2H | PCI_CONFIG_R1H |
+			  PCI_CONFIG_CH |
+#if defined(__MIPSEB__)
+			  PCI_CONFIG_SIC_HWA_DAT | PCI_CONFIG_SM,
+#else
+			  0,
+#endif
+};
+
+static struct platform_device gpr_pci_host_dev = {
+	.dev.platform_data = &gpr_pci_pd,
+	.name		= "alchemy-pci",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(alchemy_pci_host_res),
+	.resource	= alchemy_pci_host_res,
+};
+
 static struct platform_device *gpr_devices[] __initdata = {
 	&gpr_wdt_device,
 	&gpr_mtd_device,
@@ -174,6 +213,14 @@
 	&gpr_led_devices,
 };
 
+static int __init gpr_pci_init(void)
+{
+	return platform_device_register(&gpr_pci_host_dev);
+}
+/* must be arch_initcall; MIPS PCI scans busses in a subsys_initcall */
+arch_initcall(gpr_pci_init);
+
+
 static int __init gpr_dev_init(void)
 {
 	i2c_register_board_info(0, gpr_i2c_info, ARRAY_SIZE(gpr_i2c_info));
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/Kconfig linux-libre-3.2-gnu/arch/mips/alchemy/Kconfig
--- linux-libre-3.1-gnu/arch/mips/alchemy/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -18,20 +18,20 @@
 	bool "4G Systems MTX-1 board"
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
-	select SOC_AU1500
+	select ALCHEMY_GPIOINT_AU1000
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
 
 config MIPS_BOSPORUS
 	bool "Alchemy Bosporus board"
-	select SOC_AU1500
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
 
 config MIPS_DB1000
 	bool "Alchemy DB1000 board"
-	select SOC_AU1000
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -39,14 +39,14 @@
 
 config MIPS_DB1100
 	bool "Alchemy DB1100 board"
-	select SOC_AU1100
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
 
 config MIPS_DB1200
 	bool "Alchemy DB1200 board"
-	select SOC_AU1200
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_COHERENT
 	select MIPS_DISABLE_OBSOLETE_IDE
 	select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -54,7 +54,7 @@
 
 config MIPS_DB1500
 	bool "Alchemy DB1500 board"
-	select SOC_AU1500
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select MIPS_DISABLE_OBSOLETE_IDE
@@ -64,7 +64,7 @@
 
 config MIPS_DB1550
 	bool "Alchemy DB1550 board"
-	select SOC_AU1550
+	select ALCHEMY_GPIOINT_AU1000
 	select HW_HAS_PCI
 	select DMA_NONCOHERENT
 	select MIPS_DISABLE_OBSOLETE_IDE
@@ -74,13 +74,13 @@
 config MIPS_MIRAGE
 	bool "Alchemy Mirage board"
 	select DMA_NONCOHERENT
-	select SOC_AU1500
+	select ALCHEMY_GPIOINT_AU1000
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
 
 config MIPS_PB1000
 	bool "Alchemy PB1000 board"
-	select SOC_AU1000
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select SWAP_IO_SPACE
@@ -89,7 +89,7 @@
 
 config MIPS_PB1100
 	bool "Alchemy PB1100 board"
-	select SOC_AU1100
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select SWAP_IO_SPACE
@@ -98,7 +98,7 @@
 
 config MIPS_PB1200
 	bool "Alchemy PB1200 board"
-	select SOC_AU1200
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select MIPS_DISABLE_OBSOLETE_IDE
 	select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -106,7 +106,7 @@
 
 config MIPS_PB1500
 	bool "Alchemy PB1500 board"
-	select SOC_AU1500
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -114,7 +114,7 @@
 
 config MIPS_PB1550
 	bool "Alchemy PB1550 board"
-	select SOC_AU1550
+	select ALCHEMY_GPIOINT_AU1000
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select MIPS_DISABLE_OBSOLETE_IDE
@@ -124,13 +124,13 @@
 config MIPS_XXS1500
 	bool "MyCable XXS1500 board"
 	select DMA_NONCOHERENT
-	select SOC_AU1500
+	select ALCHEMY_GPIOINT_AU1000
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
 
 config MIPS_GPR
 	bool "Trapeze ITS GPR board"
-	select SOC_AU1550
+	select ALCHEMY_GPIOINT_AU1000
 	select HW_HAS_PCI
 	select DMA_NONCOHERENT
 	select MIPS_DISABLE_OBSOLETE_IDE
@@ -138,23 +138,3 @@
 	select SYS_HAS_EARLY_PRINTK
 
 endchoice
-
-config SOC_AU1000
-	bool
-	select ALCHEMY_GPIOINT_AU1000
-
-config SOC_AU1100
-	bool
-	select ALCHEMY_GPIOINT_AU1000
-
-config SOC_AU1500
-	bool
-	select ALCHEMY_GPIOINT_AU1000
-
-config SOC_AU1550
-	bool
-	select ALCHEMY_GPIOINT_AU1000
-
-config SOC_AU1200
-	bool
-	select ALCHEMY_GPIOINT_AU1000
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/mtx-1/board_setup.c linux-libre-3.2-gnu/arch/mips/alchemy/mtx-1/board_setup.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/mtx-1/board_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/mtx-1/board_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,20 +38,6 @@
 
 #include <prom.h>
 
-char irq_tab_alchemy[][5] __initdata = {
-	[0] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTA, 0xff, 0xff }, /* IDSEL 00 - AdapterA-Slot0 (top) */
-	[1] = { -1, AU1500_PCI_INTB, AU1500_PCI_INTA, 0xff, 0xff }, /* IDSEL 01 - AdapterA-Slot1 (bottom) */
-	[2] = { -1, AU1500_PCI_INTC, AU1500_PCI_INTD, 0xff, 0xff }, /* IDSEL 02 - AdapterB-Slot0 (top) */
-	[3] = { -1, AU1500_PCI_INTD, AU1500_PCI_INTC, 0xff, 0xff }, /* IDSEL 03 - AdapterB-Slot1 (bottom) */
-	[4] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, 0xff, 0xff }, /* IDSEL 04 - AdapterC-Slot0 (top) */
-	[5] = { -1, AU1500_PCI_INTB, AU1500_PCI_INTA, 0xff, 0xff }, /* IDSEL 05 - AdapterC-Slot1 (bottom) */
-	[6] = { -1, AU1500_PCI_INTC, AU1500_PCI_INTD, 0xff, 0xff }, /* IDSEL 06 - AdapterD-Slot0 (top) */
-	[7] = { -1, AU1500_PCI_INTD, AU1500_PCI_INTC, 0xff, 0xff }, /* IDSEL 07 - AdapterD-Slot1 (bottom) */
-};
-
-extern int (*board_pci_idsel)(unsigned int devsel, int assert);
-int mtx1_pci_idsel(unsigned int devsel, int assert);
-
 static void mtx1_reset(char *c)
 {
 	/* Jump to the reset vector */
@@ -74,15 +60,6 @@
 	alchemy_gpio_direction_output(204, 0);
 #endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */
 
-#ifdef CONFIG_PCI
-#if defined(__MIPSEB__)
-	au_writel(0xf | (2 << 6) | (1 << 4), Au1500_PCI_CFG);
-#else
-	au_writel(0xf, Au1500_PCI_CFG);
-#endif
-	board_pci_idsel = mtx1_pci_idsel;
-#endif
-
 	/* Initialize sys_pinfunc */
 	au_writel(SYS_PF_NI2, SYS_PINFUNC);
 
@@ -104,23 +81,6 @@
 	printk(KERN_INFO "4G Systems MTX-1 Board\n");
 }
 
-int
-mtx1_pci_idsel(unsigned int devsel, int assert)
-{
-	/* This function is only necessary to support a proprietary Cardbus
-	 * adapter on the mtx-1 "singleboard" variant. It triggers a custom
-	 * logic chip connected to EXT_IO3 (GPIO1) to suppress IDSEL signals.
-	 */
-	if (assert && devsel != 0)
-		/* Suppress signal to Cardbus */
-		alchemy_gpio_set_value(1, 0);	/* set EXT_IO3 OFF */
-	else
-		alchemy_gpio_set_value(1, 1);	/* set EXT_IO3 ON */
-
-	udelay(1);
-	return 1;
-}
-
 static int __init mtx1_init_irq(void)
 {
 	irq_set_irq_type(AU1500_GPIO204_INT, IRQF_TRIGGER_HIGH);
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/mtx-1/platform.c linux-libre-3.2-gnu/arch/mips/alchemy/mtx-1/platform.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/mtx-1/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/mtx-1/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -135,7 +135,69 @@
 	.resource	= &mtx1_mtd_resource,
 };
 
+static struct resource alchemy_pci_host_res[] = {
+	[0] = {
+		.start	= AU1500_PCI_PHYS_ADDR,
+		.end	= AU1500_PCI_PHYS_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static int mtx1_pci_idsel(unsigned int devsel, int assert)
+{
+	/* This function is only necessary to support a proprietary Cardbus
+	 * adapter on the mtx-1 "singleboard" variant. It triggers a custom
+	 * logic chip connected to EXT_IO3 (GPIO1) to suppress IDSEL signals.
+	 */
+	if (assert && devsel != 0)
+		/* Suppress signal to Cardbus */
+		alchemy_gpio_set_value(1, 0);	/* set EXT_IO3 OFF */
+	else
+		alchemy_gpio_set_value(1, 1);	/* set EXT_IO3 ON */
+
+	udelay(1);
+	return 1;
+}
+
+static const char mtx1_irqtab[][5] = {
+	[0] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTA, 0xff, 0xff }, /* IDSEL 00 - AdapterA-Slot0 (top) */
+	[1] = { -1, AU1500_PCI_INTB, AU1500_PCI_INTA, 0xff, 0xff }, /* IDSEL 01 - AdapterA-Slot1 (bottom) */
+	[2] = { -1, AU1500_PCI_INTC, AU1500_PCI_INTD, 0xff, 0xff }, /* IDSEL 02 - AdapterB-Slot0 (top) */
+	[3] = { -1, AU1500_PCI_INTD, AU1500_PCI_INTC, 0xff, 0xff }, /* IDSEL 03 - AdapterB-Slot1 (bottom) */
+	[4] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, 0xff, 0xff }, /* IDSEL 04 - AdapterC-Slot0 (top) */
+	[5] = { -1, AU1500_PCI_INTB, AU1500_PCI_INTA, 0xff, 0xff }, /* IDSEL 05 - AdapterC-Slot1 (bottom) */
+	[6] = { -1, AU1500_PCI_INTC, AU1500_PCI_INTD, 0xff, 0xff }, /* IDSEL 06 - AdapterD-Slot0 (top) */
+	[7] = { -1, AU1500_PCI_INTD, AU1500_PCI_INTC, 0xff, 0xff }, /* IDSEL 07 - AdapterD-Slot1 (bottom) */
+};
+
+static int mtx1_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+	return mtx1_irqtab[slot][pin];
+}
+
+static struct alchemy_pci_platdata mtx1_pci_pd = {
+	.board_map_irq	 = mtx1_map_pci_irq,
+	.board_pci_idsel = mtx1_pci_idsel,
+	.pci_cfg_set	 = PCI_CONFIG_AEN | PCI_CONFIG_R2H | PCI_CONFIG_R1H |
+			   PCI_CONFIG_CH |
+#if defined(__MIPSEB__)
+			   PCI_CONFIG_SIC_HWA_DAT | PCI_CONFIG_SM,
+#else
+			   0,
+#endif
+};
+
+static struct platform_device mtx1_pci_host = {
+	.dev.platform_data = &mtx1_pci_pd,
+	.name		= "alchemy-pci",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(alchemy_pci_host_res),
+	.resource	= alchemy_pci_host_res,
+};
+
+
 static struct __initdata platform_device * mtx1_devs[] = {
+	&mtx1_pci_host,
 	&mtx1_gpio_leds,
 	&mtx1_wdt,
 	&mtx1_button,
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/xxs1500/board_setup.c linux-libre-3.2-gnu/arch/mips/alchemy/xxs1500/board_setup.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/xxs1500/board_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/xxs1500/board_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -70,14 +70,6 @@
 	/* Enable DTR (MCR bit 0) = USB power up */
 	__raw_writel(1, (void __iomem *)KSEG1ADDR(AU1000_UART3_PHYS_ADDR + 0x18));
 	wmb();
-
-#ifdef CONFIG_PCI
-#if defined(__MIPSEB__)
-	au_writel(0xf | (2 << 6) | (1 << 4), Au1500_PCI_CFG);
-#else
-	au_writel(0xf, Au1500_PCI_CFG);
-#endif
-#endif
 }
 
 static int __init xxs1500_init_irq(void)
diff -druN linux-libre-3.1-gnu/arch/mips/alchemy/xxs1500/platform.c linux-libre-3.2-gnu/arch/mips/alchemy/xxs1500/platform.c
--- linux-libre-3.1-gnu/arch/mips/alchemy/xxs1500/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/alchemy/xxs1500/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,20 +27,20 @@
 	{
 		.name	= "pcmcia-io",
 		.flags	= IORESOURCE_MEM,
-		.start	= PCMCIA_IO_PHYS_ADDR,
-		.end	= PCMCIA_IO_PHYS_ADDR + 0x000400000 - 1,
+		.start	= AU1000_PCMCIA_IO_PHYS_ADDR,
+		.end	= AU1000_PCMCIA_IO_PHYS_ADDR + 0x000400000 - 1,
 	},
 	{
 		.name	= "pcmcia-attr",
 		.flags	= IORESOURCE_MEM,
-		.start	= PCMCIA_ATTR_PHYS_ADDR,
-		.end	= PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
+		.start	= AU1000_PCMCIA_ATTR_PHYS_ADDR,
+		.end	= AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
 	},
 	{
 		.name	= "pcmcia-mem",
 		.flags	= IORESOURCE_MEM,
-		.start	= PCMCIA_MEM_PHYS_ADDR,
-		.end	= PCMCIA_MEM_PHYS_ADDR + 0x000400000 - 1,
+		.start	= AU1000_PCMCIA_MEM_PHYS_ADDR,
+		.end	= AU1000_PCMCIA_MEM_PHYS_ADDR + 0x000400000 - 1,
 	},
 };
 
diff -druN linux-libre-3.1-gnu/arch/mips/bcm47xx/gpio.c linux-libre-3.2-gnu/arch/mips/bcm47xx/gpio.c
--- linux-libre-3.1-gnu/arch/mips/bcm47xx/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/bcm47xx/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
  * Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
  */
 
+#include <linux/export.h>
 #include <linux/ssb/ssb.h>
 #include <linux/ssb/ssb_driver_chipcommon.h>
 #include <linux/ssb/ssb_driver_extif.h>
@@ -20,42 +21,82 @@
 
 int gpio_request(unsigned gpio, const char *tag)
 {
-	if (ssb_chipco_available(&ssb_bcm47xx.chipco) &&
-	    ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
-		return -EINVAL;
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
+		    ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
+			return -EINVAL;
 
-	if (ssb_extif_available(&ssb_bcm47xx.extif) &&
-	    ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
-		return -EINVAL;
+		if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
+		    ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
+			return -EINVAL;
 
-	if (test_and_set_bit(gpio, gpio_in_use))
-		return -EBUSY;
+		if (test_and_set_bit(gpio, gpio_in_use))
+			return -EBUSY;
 
-	return 0;
+		return 0;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
+			return -EINVAL;
+
+		if (test_and_set_bit(gpio, gpio_in_use))
+			return -EBUSY;
+
+		return 0;
+#endif
+	}
+	return -EINVAL;
 }
 EXPORT_SYMBOL(gpio_request);
 
 void gpio_free(unsigned gpio)
 {
-	if (ssb_chipco_available(&ssb_bcm47xx.chipco) &&
-	    ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
-		return;
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
+		    ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
+			return;
 
-	if (ssb_extif_available(&ssb_bcm47xx.extif) &&
-	    ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
+		if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
+		    ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
+			return;
+
+		clear_bit(gpio, gpio_in_use);
 		return;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
+			return;
 
-	clear_bit(gpio, gpio_in_use);
+		clear_bit(gpio, gpio_in_use);
+		return;
+#endif
+	}
 }
 EXPORT_SYMBOL(gpio_free);
 
 int gpio_to_irq(unsigned gpio)
 {
-	if (ssb_chipco_available(&ssb_bcm47xx.chipco))
-		return ssb_mips_irq(ssb_bcm47xx.chipco.dev) + 2;
-	else if (ssb_extif_available(&ssb_bcm47xx.extif))
-		return ssb_mips_irq(ssb_bcm47xx.extif.dev) + 2;
-	else
-		return -EINVAL;
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco))
+			return ssb_mips_irq(bcm47xx_bus.ssb.chipco.dev) + 2;
+		else if (ssb_extif_available(&bcm47xx_bus.ssb.extif))
+			return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2;
+		else
+			return -EINVAL;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		return bcma_core_mips_irq(bcm47xx_bus.bcma.bus.drv_cc.core) + 2;
+#endif
+	}
+	return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(gpio_to_irq);
diff -druN linux-libre-3.1-gnu/arch/mips/bcm47xx/irq.c linux-libre-3.2-gnu/arch/mips/bcm47xx/irq.c
--- linux-libre-3.1-gnu/arch/mips/bcm47xx/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/bcm47xx/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <asm/irq_cpu.h>
+#include <bcm47xx.h>
 
 void plat_irq_dispatch(void)
 {
@@ -51,5 +52,16 @@
 
 void __init arch_init_irq(void)
 {
+#ifdef CONFIG_BCM47XX_BCMA
+	if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) {
+		bcma_write32(bcm47xx_bus.bcma.bus.drv_mips.core,
+			     BCMA_MIPS_MIPS74K_INTMASK(5), 1 << 31);
+		/*
+		 * the kernel reads the timer irq from some register and thinks
+		 * it's #5, but we offset it by 2 and route to #7
+		 */
+		cp0_compare_irq = 7;
+	}
+#endif
 	mips_cpu_irq_init();
 }
diff -druN linux-libre-3.1-gnu/arch/mips/bcm47xx/Kconfig linux-libre-3.2-gnu/arch/mips/bcm47xx/Kconfig
--- linux-libre-3.1-gnu/arch/mips/bcm47xx/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/mips/bcm47xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,31 @@
+if BCM47XX
+
+config BCM47XX_SSB
+	bool "SSB Support for Broadcom BCM47XX"
+	select SYS_HAS_CPU_MIPS32_R1
+	select SSB
+	select SSB_DRIVER_MIPS
+	select SSB_DRIVER_EXTIF
+	select SSB_EMBEDDED
+	select SSB_B43_PCI_BRIDGE if PCI
+	select SSB_PCICORE_HOSTMODE if PCI
+	default y
+	help
+	 Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
+
+	 This will generate an image with support for SSB and MIPS32 R1 instruction set.
+
+config BCM47XX_BCMA
+	bool "BCMA Support for Broadcom BCM47XX"
+	select SYS_HAS_CPU_MIPS32_R2
+	select BCMA
+	select BCMA_HOST_SOC
+	select BCMA_DRIVER_MIPS
+	select BCMA_DRIVER_PCI_HOSTMODE if PCI
+	default y
+	help
+	 Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
+
+	 This will generate an image with support for BCMA and MIPS32 R2 instruction set.
+
+endif
diff -druN linux-libre-3.1-gnu/arch/mips/bcm47xx/Makefile linux-libre-3.2-gnu/arch/mips/bcm47xx/Makefile
--- linux-libre-3.1-gnu/arch/mips/bcm47xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/bcm47xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,4 +3,5 @@
 # under Linux.
 #
 
-obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
+obj-y 				+= gpio.o irq.o nvram.o prom.o serial.o setup.o time.o
+obj-$(CONFIG_BCM47XX_SSB)	+= wgt634u.o
diff -druN linux-libre-3.1-gnu/arch/mips/bcm47xx/nvram.c linux-libre-3.2-gnu/arch/mips/bcm47xx/nvram.c
--- linux-libre-3.1-gnu/arch/mips/bcm47xx/nvram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/bcm47xx/nvram.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,14 +26,35 @@
 /* Probe for NVRAM header */
 static void early_nvram_init(void)
 {
-	struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+#ifdef CONFIG_BCM47XX_SSB
+	struct ssb_mipscore *mcore_ssb;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	struct bcma_drv_cc *bcma_cc;
+#endif
 	struct nvram_header *header;
 	int i;
-	u32 base, lim, off;
+	u32 base = 0;
+	u32 lim = 0;
+	u32 off;
 	u32 *src, *dst;
 
-	base = mcore->flash_window;
-	lim = mcore->flash_window_size;
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		mcore_ssb = &bcm47xx_bus.ssb.mipscore;
+		base = mcore_ssb->flash_window;
+		lim = mcore_ssb->flash_window_size;
+		break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc;
+		base = bcma_cc->pflash.window;
+		lim = bcma_cc->pflash.window_size;
+		break;
+#endif
+	}
 
 	off = FLASH_MIN;
 	while (off <= lim) {
diff -druN linux-libre-3.1-gnu/arch/mips/bcm47xx/serial.c linux-libre-3.2-gnu/arch/mips/bcm47xx/serial.c
--- linux-libre-3.1-gnu/arch/mips/bcm47xx/serial.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/bcm47xx/serial.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,10 +23,11 @@
 	},
 };
 
-static int __init uart8250_init(void)
+#ifdef CONFIG_BCM47XX_SSB
+static int __init uart8250_init_ssb(void)
 {
 	int i;
-	struct ssb_mipscore *mcore = &(ssb_bcm47xx.mipscore);
+	struct ssb_mipscore *mcore = &(bcm47xx_bus.ssb.mipscore);
 
 	memset(&uart8250_data, 0,  sizeof(uart8250_data));
 
@@ -44,6 +45,47 @@
 	}
 	return platform_device_register(&uart8250_device);
 }
+#endif
+
+#ifdef CONFIG_BCM47XX_BCMA
+static int __init uart8250_init_bcma(void)
+{
+	int i;
+	struct bcma_drv_cc *cc = &(bcm47xx_bus.bcma.bus.drv_cc);
+
+	memset(&uart8250_data, 0,  sizeof(uart8250_data));
+
+	for (i = 0; i < cc->nr_serial_ports; i++) {
+		struct plat_serial8250_port *p = &(uart8250_data[i]);
+		struct bcma_serial_port *bcma_port;
+		bcma_port = &(cc->serial_ports[i]);
+
+		p->mapbase = (unsigned int) bcma_port->regs;
+		p->membase = (void *) bcma_port->regs;
+		p->irq = bcma_port->irq + 2;
+		p->uartclk = bcma_port->baud_base;
+		p->regshift = bcma_port->reg_shift;
+		p->iotype = UPIO_MEM;
+		p->flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+	}
+	return platform_device_register(&uart8250_device);
+}
+#endif
+
+static int __init uart8250_init(void)
+{
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		return uart8250_init_ssb();
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		return uart8250_init_bcma();
+#endif
+	}
+	return -EINVAL;
+}
 
 module_init(uart8250_init);
 
diff -druN linux-libre-3.1-gnu/arch/mips/bcm47xx/setup.c linux-libre-3.2-gnu/arch/mips/bcm47xx/setup.c
--- linux-libre-3.1-gnu/arch/mips/bcm47xx/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/bcm47xx/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,24 +26,40 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/ssb/ssb.h>
 #include <linux/ssb/ssb_embedded.h>
+#include <linux/bcma/bcma_soc.h>
 #include <asm/bootinfo.h>
 #include <asm/reboot.h>
 #include <asm/time.h>
 #include <bcm47xx.h>
 #include <asm/mach-bcm47xx/nvram.h>
 
-struct ssb_bus ssb_bcm47xx;
-EXPORT_SYMBOL(ssb_bcm47xx);
+union bcm47xx_bus bcm47xx_bus;
+EXPORT_SYMBOL(bcm47xx_bus);
+
+enum bcm47xx_bus_type bcm47xx_bus_type;
+EXPORT_SYMBOL(bcm47xx_bus_type);
 
 static void bcm47xx_machine_restart(char *command)
 {
 	printk(KERN_ALERT "Please stand by while rebooting the system...\n");
 	local_irq_disable();
 	/* Set the watchdog timer to reset immediately */
-	ssb_watchdog_timer_set(&ssb_bcm47xx, 1);
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
+		break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 1);
+		break;
+#endif
+	}
 	while (1)
 		cpu_relax();
 }
@@ -52,11 +68,23 @@
 {
 	/* Disable interrupts and watchdog and spin forever */
 	local_irq_disable();
-	ssb_watchdog_timer_set(&ssb_bcm47xx, 0);
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
+		break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 0);
+		break;
+#endif
+	}
 	while (1)
 		cpu_relax();
 }
 
+#ifdef CONFIG_BCM47XX_SSB
 #define READ_FROM_NVRAM(_outvar, name, buf) \
 	if (nvram_getprefix(prefix, name, buf, sizeof(buf)) >= 0)\
 		sprom->_outvar = simple_strtoul(buf, NULL, 0);
@@ -247,7 +275,7 @@
 	return 0;
 }
 
-void __init plat_mem_setup(void)
+static void __init bcm47xx_register_ssb(void)
 {
 	int err;
 	char buf[100];
@@ -258,12 +286,12 @@
 		printk(KERN_WARNING "bcm47xx: someone else already registered"
 			" a ssb SPROM callback handler (err %d)\n", err);
 
-	err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
+	err = ssb_bus_ssbbus_register(&(bcm47xx_bus.ssb), SSB_ENUM_BASE,
 				      bcm47xx_get_invariants);
 	if (err)
 		panic("Failed to initialize SSB bus (err %d)\n", err);
 
-	mcore = &ssb_bcm47xx.mipscore;
+	mcore = &bcm47xx_bus.ssb.mipscore;
 	if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
 		if (strstr(buf, "console=ttyS1")) {
 			struct ssb_serial_port port;
@@ -276,8 +304,57 @@
 			memcpy(&mcore->serial_ports[1], &port, sizeof(port));
 		}
 	}
+}
+#endif
+
+#ifdef CONFIG_BCM47XX_BCMA
+static void __init bcm47xx_register_bcma(void)
+{
+	int err;
+
+	err = bcma_host_soc_register(&bcm47xx_bus.bcma);
+	if (err)
+		panic("Failed to initialize BCMA bus (err %d)\n", err);
+}
+#endif
+
+void __init plat_mem_setup(void)
+{
+	struct cpuinfo_mips *c = &current_cpu_data;
+
+	if (c->cputype == CPU_74K) {
+		printk(KERN_INFO "bcm47xx: using bcma bus\n");
+#ifdef CONFIG_BCM47XX_BCMA
+		bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA;
+		bcm47xx_register_bcma();
+#endif
+	} else {
+		printk(KERN_INFO "bcm47xx: using ssb bus\n");
+#ifdef CONFIG_BCM47XX_SSB
+		bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB;
+		bcm47xx_register_ssb();
+#endif
+	}
 
 	_machine_restart = bcm47xx_machine_restart;
 	_machine_halt = bcm47xx_machine_halt;
 	pm_power_off = bcm47xx_machine_halt;
 }
+
+static int __init bcm47xx_register_bus_complete(void)
+{
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		/* Nothing to do */
+		break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_bus_register(&bcm47xx_bus.bcma.bus);
+		break;
+#endif
+	}
+	return 0;
+}
+device_initcall(bcm47xx_register_bus_complete);
diff -druN linux-libre-3.1-gnu/arch/mips/bcm47xx/time.c linux-libre-3.2-gnu/arch/mips/bcm47xx/time.c
--- linux-libre-3.1-gnu/arch/mips/bcm47xx/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/bcm47xx/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@
 
 void __init plat_time_init(void)
 {
-	unsigned long hz;
+	unsigned long hz = 0;
 
 	/*
 	 * Use deterministic values for initial counter interrupt
@@ -39,7 +39,19 @@
 	write_c0_count(0);
 	write_c0_compare(0xffff);
 
-	hz = ssb_cpu_clock(&ssb_bcm47xx.mipscore) / 2;
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2;
+		break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		hz = bcma_cpu_clock(&bcm47xx_bus.bcma.bus.drv_mips) / 2;
+		break;
+#endif
+	}
+
 	if (!hz)
 		hz = 100000000;
 
diff -druN linux-libre-3.1-gnu/arch/mips/bcm47xx/wgt634u.c linux-libre-3.2-gnu/arch/mips/bcm47xx/wgt634u.c
--- linux-libre-3.1-gnu/arch/mips/bcm47xx/wgt634u.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/bcm47xx/wgt634u.c	2012-01-04 18:55:44.000000000 -0500
@@ -108,7 +108,7 @@
 
 	/* Interrupts are shared, check if the current one is
 	   a GPIO interrupt. */
-	if (!ssb_chipco_irq_status(&ssb_bcm47xx.chipco,
+	if (!ssb_chipco_irq_status(&bcm47xx_bus.ssb.chipco,
 				   SSB_CHIPCO_IRQ_GPIO))
 		return IRQ_NONE;
 
@@ -132,22 +132,26 @@
 	 * machine. Use the MAC address as an heuristic. Netgear Inc. has
 	 * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
 	 */
+	u8 *et0mac;
 
-	u8 *et0mac = ssb_bcm47xx.sprom.et0mac;
+	if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB)
+		return -ENODEV;
+
+	et0mac = bcm47xx_bus.ssb.sprom.et0mac;
 
 	if (et0mac[0] == 0x00 &&
 	    ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) ||
 	     (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) {
-		struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+		struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore;
 
 		printk(KERN_INFO "WGT634U machine detected.\n");
 
 		if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET),
 				 gpio_interrupt, IRQF_SHARED,
-				 "WGT634U GPIO", &ssb_bcm47xx.chipco)) {
+				 "WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) {
 			gpio_direction_input(WGT634U_GPIO_RESET);
 			gpio_intmask(WGT634U_GPIO_RESET, 1);
-			ssb_chipco_irq_mask(&ssb_bcm47xx.chipco,
+			ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco,
 					    SSB_CHIPCO_IRQ_GPIO,
 					    SSB_CHIPCO_IRQ_GPIO);
 		}
diff -druN linux-libre-3.1-gnu/arch/mips/cavium-octeon/csrc-octeon.c linux-libre-3.2-gnu/arch/mips/cavium-octeon/csrc-octeon.c
--- linux-libre-3.1-gnu/arch/mips/cavium-octeon/csrc-octeon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/cavium-octeon/csrc-octeon.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  * Copyright (C) 2009, 2010 Cavium Networks, Inc.
  */
 #include <linux/clocksource.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/smp.h>
 
diff -druN linux-libre-3.1-gnu/arch/mips/cavium-octeon/dma-octeon.c linux-libre-3.2-gnu/arch/mips/cavium-octeon/dma-octeon.c
--- linux-libre-3.1-gnu/arch/mips/cavium-octeon/dma-octeon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/cavium-octeon/dma-octeon.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
 #include <linux/bootmem.h>
+#include <linux/export.h>
 #include <linux/swiotlb.h>
 #include <linux/types.h>
 #include <linux/init.h>
diff -druN linux-libre-3.1-gnu/arch/mips/cavium-octeon/flash_setup.c linux-libre-3.2-gnu/arch/mips/cavium-octeon/flash_setup.c
--- linux-libre-3.1-gnu/arch/mips/cavium-octeon/flash_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/cavium-octeon/flash_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  * Copyright (C) 2007, 2008 Cavium Networks
  */
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
@@ -16,8 +17,6 @@
 
 static struct map_info flash_map;
 static struct mtd_info *mymtd;
-static int nr_parts;
-static struct mtd_partition *parts;
 static const char *part_probe_types[] = {
 	"cmdlinepart",
 #ifdef CONFIG_MTD_REDBOOT_PARTS
@@ -60,11 +59,8 @@
 		mymtd = do_map_probe("cfi_probe", &flash_map);
 		if (mymtd) {
 			mymtd->owner = THIS_MODULE;
-
-			nr_parts = parse_mtd_partitions(mymtd,
-							part_probe_types,
-							&parts, 0);
-			mtd_device_register(mymtd, parts, nr_parts);
+			mtd_device_parse_register(mymtd, part_probe_types,
+						  0, NULL, 0);
 		} else {
 			pr_err("Failed to register MTD device for flash\n");
 		}
diff -druN linux-libre-3.1-gnu/arch/mips/cavium-octeon/smp.c linux-libre-3.2-gnu/arch/mips/cavium-octeon/smp.c
--- linux-libre-3.1-gnu/arch/mips/cavium-octeon/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/cavium-octeon/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -207,8 +207,9 @@
 	 * the other bits alone.
 	 */
 	cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffff);
-	if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_DISABLED,
-			"SMP-IPI", mailbox_interrupt)) {
+	if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt,
+			IRQF_PERCPU | IRQF_NO_THREAD, "SMP-IPI",
+			mailbox_interrupt)) {
 		panic("Cannot request_irq(OCTEON_IRQ_MBOX0)\n");
 	}
 }
diff -druN linux-libre-3.1-gnu/arch/mips/emma/common/prom.c linux-libre-3.2-gnu/arch/mips/emma/common/prom.c
--- linux-libre-3.1-gnu/arch/mips/emma/common/prom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/emma/common/prom.c	2012-01-04 18:55:44.000000000 -0500
@@ -50,7 +50,7 @@
 
 	/* arg[0] is "g", the rest is boot parameters */
 	for (i = 1; i < argc; i++) {
-		if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+		if (strlen(arcs_cmdline) + strlen(arg[i]) + 1
 		    >= sizeof(arcs_cmdline))
 			break;
 		strcat(arcs_cmdline, arg[i]);
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/cacheflush.h linux-libre-3.2-gnu/arch/mips/include/asm/cacheflush.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/cacheflush.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/cacheflush.h	2012-01-04 18:55:44.000000000 -0500
@@ -114,4 +114,28 @@
 extern void *kmap_coherent(struct page *page, unsigned long addr);
 extern void kunmap_coherent(void);
 
+#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
+static inline void flush_kernel_dcache_page(struct page *page)
+{
+	BUG_ON(cpu_has_dc_aliases && PageHighMem(page));
+}
+
+/*
+ * For now flush_kernel_vmap_range and invalidate_kernel_vmap_range both do a
+ * cache writeback and invalidate operation.
+ */
+extern void (*__flush_kernel_vmap_range)(unsigned long vaddr, int size);
+
+static inline void flush_kernel_vmap_range(void *vaddr, int size)
+{
+	if (cpu_has_dc_aliases)
+		__flush_kernel_vmap_range((unsigned long) vaddr, size);
+}
+
+static inline void invalidate_kernel_vmap_range(void *vaddr, int size)
+{
+	if (cpu_has_dc_aliases)
+		__flush_kernel_vmap_range((unsigned long) vaddr, size);
+}
+
 #endif /* _ASM_CACHEFLUSH_H */
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/compat.h linux-libre-3.2-gnu/arch/mips/include/asm/compat.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/compat.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/compat.h	2012-01-04 18:55:44.000000000 -0500
@@ -111,7 +111,8 @@
 	int		f_bavail;
 	compat_fsid_t	f_fsid;
 	int		f_namelen;
-	int		f_spare[6];
+	int		f_flags;
+	int		f_spare[5];
 };
 
 #define COMPAT_RLIM_INFINITY	0x7fffffffUL
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/cpu.h linux-libre-3.2-gnu/arch/mips/include/asm/cpu.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/cpu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/cpu.h	2012-01-04 18:55:44.000000000 -0500
@@ -135,6 +135,9 @@
 #define PRID_IMP_CAVIUM_CN50XX 0x0600
 #define PRID_IMP_CAVIUM_CN52XX 0x0700
 #define PRID_IMP_CAVIUM_CN63XX 0x9000
+#define PRID_IMP_CAVIUM_CN68XX 0x9100
+#define PRID_IMP_CAVIUM_CN66XX 0x9200
+#define PRID_IMP_CAVIUM_CN61XX 0x9300
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_INGENIC
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/io.h linux-libre-3.2-gnu/arch/mips/include/asm/io.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -329,14 +329,10 @@
 			"dsrl32	%L0, %L0, 0"			"\n\t"	\
 			"dsll32	%M0, %M0, 0"			"\n\t"	\
 			"or	%L0, %L0, %M0"			"\n\t"	\
-			".set	push"				"\n\t"	\
-			".set	noreorder"			"\n\t"	\
-			".set	nomacro"			"\n\t"	\
 			"sd	%L0, %2"			"\n\t"	\
-			".set	pop"				"\n\t"	\
 			".set	mips0"				"\n"	\
 			: "=r" (__tmp)					\
-			: "0" (__val), "R" (*__mem));			\
+			: "0" (__val), "m" (*__mem));			\
 		if (irq)						\
 			local_irq_restore(__flags);			\
 	} else								\
@@ -359,16 +355,12 @@
 			local_irq_save(__flags);			\
 		__asm__ __volatile__(					\
 			".set	mips3"		"\t\t# __readq"	"\n\t"	\
-			".set	push"				"\n\t"	\
-			".set	noreorder"			"\n\t"	\
-			".set	nomacro"			"\n\t"	\
 			"ld	%L0, %1"			"\n\t"	\
-			".set	pop"				"\n\t"	\
 			"dsra32	%M0, %L0, 0"			"\n\t"	\
 			"sll	%L0, %L0, 0"			"\n\t"	\
 			".set	mips0"				"\n"	\
 			: "=r" (__val)					\
-			: "R" (*__mem));				\
+			: "m" (*__mem));				\
 		if (irq)						\
 			local_irq_restore(__flags);			\
 	} else {							\
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/lasat/lasat.h linux-libre-3.2-gnu/arch/mips/include/asm/lasat/lasat.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/lasat/lasat.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/lasat/lasat.h	2012-01-04 18:55:44.000000000 -0500
@@ -41,10 +41,8 @@
 
 /*
  * The format of the data record in the EEPROM.
- * See Documentation/LASAT/eeprom.txt for a detailed description
- * of the fields in this struct, and the LASAT Hardware Configuration
- * field specification for a detailed description of the config
- * field.
+ * See the LASAT Hardware Configuration field specification for a detailed
+ * description of the config field.
  */
 #include <linux/types.h>
 
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/mach-au1x00/au1000.h linux-libre-3.2-gnu/arch/mips/include/asm/mach-au1x00/au1000.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/mach-au1x00/au1000.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/mach-au1x00/au1000.h	2012-01-04 18:55:44.000000000 -0500
@@ -245,6 +245,23 @@
 void alchemy_sleep_au1550(void);
 void au_sleep(void);
 
+/* USB: drivers/usb/host/alchemy-common.c */
+enum alchemy_usb_block {
+	ALCHEMY_USB_OHCI0,
+	ALCHEMY_USB_UDC0,
+	ALCHEMY_USB_EHCI0,
+	ALCHEMY_USB_OTG0,
+};
+int alchemy_usb_control(int block, int enable);
+
+/* PCI controller platform data */
+struct alchemy_pci_platdata {
+	int (*board_map_irq)(const struct pci_dev *d, u8 slot, u8 pin);
+	int (*board_pci_idsel)(unsigned int devsel, int assert);
+	/* bits to set/clear in PCI_CONFIG register */
+	unsigned long pci_cfg_set;
+	unsigned long pci_cfg_clr;
+};
 
 /* SOC Interrupt numbers */
 
@@ -575,38 +592,95 @@
 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
 
 /*
- * SDRAM register offsets
+ * Physical base addresses for integrated peripherals
+ * 0..au1000 1..au1500 2..au1100 3..au1550 4..au1200
  */
-#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1500) || \
-    defined(CONFIG_SOC_AU1100)
-#define MEM_SDMODE0		0x0000
-#define MEM_SDMODE1		0x0004
-#define MEM_SDMODE2		0x0008
-#define MEM_SDADDR0		0x000C
-#define MEM_SDADDR1		0x0010
-#define MEM_SDADDR2		0x0014
-#define MEM_SDREFCFG		0x0018
-#define MEM_SDPRECMD		0x001C
-#define MEM_SDAUTOREF		0x0020
-#define MEM_SDWRMD0		0x0024
-#define MEM_SDWRMD1		0x0028
-#define MEM_SDWRMD2		0x002C
-#define MEM_SDSLEEP		0x0030
-#define MEM_SDSMCKE		0x0034
 
-/*
- * MEM_SDMODE register content definitions
- */
+#define AU1000_AC97_PHYS_ADDR		0x10000000 /* 012 */
+#define AU1000_USB_OHCI_PHYS_ADDR	0x10100000 /* 012 */
+#define AU1000_USB_UDC_PHYS_ADDR	0x10200000 /* 0123 */
+#define AU1000_IRDA_PHYS_ADDR		0x10300000 /* 02 */
+#define AU1200_AES_PHYS_ADDR		0x10300000 /* 4 */
+#define AU1000_IC0_PHYS_ADDR		0x10400000 /* 01234 */
+#define AU1000_MAC0_PHYS_ADDR		0x10500000 /* 023 */
+#define AU1000_MAC1_PHYS_ADDR		0x10510000 /* 023 */
+#define AU1000_MACEN_PHYS_ADDR		0x10520000 /* 023 */
+#define AU1100_SD0_PHYS_ADDR		0x10600000 /* 24 */
+#define AU1100_SD1_PHYS_ADDR		0x10680000 /* 24 */
+#define AU1550_PSC2_PHYS_ADDR		0x10A00000 /* 3 */
+#define AU1550_PSC3_PHYS_ADDR		0x10B00000 /* 3 */
+#define AU1000_I2S_PHYS_ADDR		0x11000000 /* 02 */
+#define AU1500_MAC0_PHYS_ADDR		0x11500000 /* 1 */
+#define AU1500_MAC1_PHYS_ADDR		0x11510000 /* 1 */
+#define AU1500_MACEN_PHYS_ADDR		0x11520000 /* 1 */
+#define AU1000_UART0_PHYS_ADDR		0x11100000 /* 01234 */
+#define AU1200_SWCNT_PHYS_ADDR		0x1110010C /* 4 */
+#define AU1000_UART1_PHYS_ADDR		0x11200000 /* 0234 */
+#define AU1000_UART2_PHYS_ADDR		0x11300000 /* 0 */
+#define AU1000_UART3_PHYS_ADDR		0x11400000 /* 0123 */
+#define AU1000_SSI0_PHYS_ADDR		0x11600000 /* 02 */
+#define AU1000_SSI1_PHYS_ADDR		0x11680000 /* 02 */
+#define AU1500_GPIO2_PHYS_ADDR		0x11700000 /* 1234 */
+#define AU1000_IC1_PHYS_ADDR		0x11800000 /* 01234 */
+#define AU1000_SYS_PHYS_ADDR		0x11900000 /* 01234 */
+#define AU1550_PSC0_PHYS_ADDR		0x11A00000 /* 34 */
+#define AU1550_PSC1_PHYS_ADDR		0x11B00000 /* 34 */
+#define AU1000_MEM_PHYS_ADDR		0x14000000 /* 01234 */
+#define AU1000_STATIC_MEM_PHYS_ADDR	0x14001000 /* 01234 */
+#define AU1000_DMA_PHYS_ADDR		0x14002000 /* 012 */
+#define AU1550_DBDMA_PHYS_ADDR		0x14002000 /* 34 */
+#define AU1550_DBDMA_CONF_PHYS_ADDR	0x14003000 /* 34 */
+#define AU1000_MACDMA0_PHYS_ADDR	0x14004000 /* 0123 */
+#define AU1000_MACDMA1_PHYS_ADDR	0x14004200 /* 0123 */
+#define AU1200_CIM_PHYS_ADDR		0x14004000 /* 4 */
+#define AU1500_PCI_PHYS_ADDR		0x14005000 /* 13 */
+#define AU1550_PE_PHYS_ADDR		0x14008000 /* 3 */
+#define AU1200_MAEBE_PHYS_ADDR		0x14010000 /* 4 */
+#define AU1200_MAEFE_PHYS_ADDR		0x14012000 /* 4 */
+#define AU1550_USB_OHCI_PHYS_ADDR	0x14020000 /* 3 */
+#define AU1200_USB_CTL_PHYS_ADDR	0x14020000 /* 4 */
+#define AU1200_USB_OTG_PHYS_ADDR	0x14020020 /* 4 */
+#define AU1200_USB_OHCI_PHYS_ADDR	0x14020100 /* 4 */
+#define AU1200_USB_EHCI_PHYS_ADDR	0x14020200 /* 4 */
+#define AU1200_USB_UDC_PHYS_ADDR	0x14022000 /* 4 */
+#define AU1100_LCD_PHYS_ADDR		0x15000000 /* 2 */
+#define AU1200_LCD_PHYS_ADDR		0x15000000 /* 4 */
+#define AU1500_PCI_MEM_PHYS_ADDR	0x400000000ULL /* 13 */
+#define AU1500_PCI_IO_PHYS_ADDR		0x500000000ULL /* 13 */
+#define AU1500_PCI_CONFIG0_PHYS_ADDR	0x600000000ULL /* 13 */
+#define AU1500_PCI_CONFIG1_PHYS_ADDR	0x680000000ULL /* 13 */
+#define AU1000_PCMCIA_IO_PHYS_ADDR	0xF00000000ULL /* 01234 */
+#define AU1000_PCMCIA_ATTR_PHYS_ADDR	0xF40000000ULL /* 01234 */
+#define AU1000_PCMCIA_MEM_PHYS_ADDR	0xF80000000ULL /* 01234 */
+
+
+/* Au1000 SDRAM memory controller register offsets */
+#define AU1000_MEM_SDMODE0		0x0000
+#define AU1000_MEM_SDMODE1		0x0004
+#define AU1000_MEM_SDMODE2		0x0008
+#define AU1000_MEM_SDADDR0		0x000C
+#define AU1000_MEM_SDADDR1		0x0010
+#define AU1000_MEM_SDADDR2		0x0014
+#define AU1000_MEM_SDREFCFG		0x0018
+#define AU1000_MEM_SDPRECMD		0x001C
+#define AU1000_MEM_SDAUTOREF		0x0020
+#define AU1000_MEM_SDWRMD0		0x0024
+#define AU1000_MEM_SDWRMD1		0x0028
+#define AU1000_MEM_SDWRMD2		0x002C
+#define AU1000_MEM_SDSLEEP		0x0030
+#define AU1000_MEM_SDSMCKE		0x0034
+
+/* MEM_SDMODE register content definitions */
 #define MEM_SDMODE_F		(1 << 22)
 #define MEM_SDMODE_SR		(1 << 21)
 #define MEM_SDMODE_BS		(1 << 20)
 #define MEM_SDMODE_RS		(3 << 18)
 #define MEM_SDMODE_CS		(7 << 15)
-#define MEM_SDMODE_TRAS 	(15 << 11)
-#define MEM_SDMODE_TMRD 	(3 << 9)
+#define MEM_SDMODE_TRAS		(15 << 11)
+#define MEM_SDMODE_TMRD		(3 << 9)
 #define MEM_SDMODE_TWR		(3 << 7)
 #define MEM_SDMODE_TRP		(3 << 5)
-#define MEM_SDMODE_TRCD 	(3 << 3)
+#define MEM_SDMODE_TRCD		(3 << 3)
 #define MEM_SDMODE_TCL		(7 << 0)
 
 #define MEM_SDMODE_BS_2Bank	(0 << 20)
@@ -628,173 +702,43 @@
 #define MEM_SDMODE_TRCD_N(N)	((N) << 3)
 #define MEM_SDMODE_TCL_N(N)	((N) << 0)
 
-/*
- * MEM_SDADDR register contents definitions
- */
+/* MEM_SDADDR register contents definitions */
 #define MEM_SDADDR_E		(1 << 20)
-#define MEM_SDADDR_CSBA 	(0x03FF << 10)
+#define MEM_SDADDR_CSBA		(0x03FF << 10)
 #define MEM_SDADDR_CSMASK	(0x03FF << 0)
 #define MEM_SDADDR_CSBA_N(N)	((N) & (0x03FF << 22) >> 12)
 #define MEM_SDADDR_CSMASK_N(N)	((N)&(0x03FF << 22) >> 22)
 
-/*
- * MEM_SDREFCFG register content definitions
- */
+/* MEM_SDREFCFG register content definitions */
 #define MEM_SDREFCFG_TRC	(15 << 28)
 #define MEM_SDREFCFG_TRPM	(3 << 26)
 #define MEM_SDREFCFG_E		(1 << 25)
-#define MEM_SDREFCFG_RE 	(0x1ffffff << 0)
+#define MEM_SDREFCFG_RE		(0x1ffffff << 0)
 #define MEM_SDREFCFG_TRC_N(N)	((N) << MEM_SDREFCFG_TRC)
 #define MEM_SDREFCFG_TRPM_N(N)	((N) << MEM_SDREFCFG_TRPM)
 #define MEM_SDREFCFG_REF_N(N)	(N)
-#endif
-
-/***********************************************************************/
-
-/*
- * Au1550 SDRAM Register Offsets
- */
-
-/***********************************************************************/
-
-#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
-#define MEM_SDMODE0		0x0800
-#define MEM_SDMODE1		0x0808
-#define MEM_SDMODE2		0x0810
-#define MEM_SDADDR0		0x0820
-#define MEM_SDADDR1		0x0828
-#define MEM_SDADDR2		0x0830
-#define MEM_SDCONFIGA		0x0840
-#define MEM_SDCONFIGB		0x0848
-#define MEM_SDSTAT		0x0850
-#define MEM_SDERRADDR		0x0858
-#define MEM_SDSTRIDE0		0x0860
-#define MEM_SDSTRIDE1		0x0868
-#define MEM_SDSTRIDE2		0x0870
-#define MEM_SDWRMD0		0x0880
-#define MEM_SDWRMD1		0x0888
-#define MEM_SDWRMD2		0x0890
-#define MEM_SDPRECMD		0x08C0
-#define MEM_SDAUTOREF		0x08C8
-#define MEM_SDSREF		0x08D0
-#define MEM_SDSLEEP		MEM_SDSREF
-
-#endif
-
-/*
- * Physical base addresses for integrated peripherals
- * 0..au1000 1..au1500 2..au1100 3..au1550 4..au1200
- */
-
-#define AU1000_AC97_PHYS_ADDR		0x10000000 /* 012 */
-#define AU1000_USBD_PHYS_ADDR		0x10200000 /* 0123 */
-#define AU1000_IC0_PHYS_ADDR		0x10400000 /* 01234 */
-#define AU1000_MAC0_PHYS_ADDR		0x10500000 /* 023 */
-#define AU1000_MAC1_PHYS_ADDR		0x10510000 /* 023 */
-#define AU1000_MACEN_PHYS_ADDR		0x10520000 /* 023 */
-#define AU1100_SD0_PHYS_ADDR		0x10600000 /* 24 */
-#define AU1100_SD1_PHYS_ADDR		0x10680000 /* 24 */
-#define AU1000_I2S_PHYS_ADDR		0x11000000 /* 02 */
-#define AU1500_MAC0_PHYS_ADDR		0x11500000 /* 1 */
-#define AU1500_MAC1_PHYS_ADDR		0x11510000 /* 1 */
-#define AU1500_MACEN_PHYS_ADDR		0x11520000 /* 1 */
-#define AU1000_UART0_PHYS_ADDR		0x11100000 /* 01234 */
-#define AU1000_UART1_PHYS_ADDR		0x11200000 /* 0234 */
-#define AU1000_UART2_PHYS_ADDR		0x11300000 /* 0 */
-#define AU1000_UART3_PHYS_ADDR		0x11400000 /* 0123 */
-#define AU1500_GPIO2_PHYS_ADDR		0x11700000 /* 1234 */
-#define AU1000_IC1_PHYS_ADDR		0x11800000 /* 01234 */
-#define AU1000_SYS_PHYS_ADDR		0x11900000 /* 01234 */
-#define AU1000_DMA_PHYS_ADDR		0x14002000 /* 012 */
-#define AU1550_DBDMA_PHYS_ADDR		0x14002000 /* 34 */
-#define AU1550_DBDMA_CONF_PHYS_ADDR	0x14003000 /* 34 */
-#define AU1000_MACDMA0_PHYS_ADDR	0x14004000 /* 0123 */
-#define AU1000_MACDMA1_PHYS_ADDR	0x14004200 /* 0123 */
-
-
-#ifdef CONFIG_SOC_AU1000
-#define	MEM_PHYS_ADDR		0x14000000
-#define	STATIC_MEM_PHYS_ADDR	0x14001000
-#define	USBH_PHYS_ADDR		0x10100000
-#define	IRDA_PHYS_ADDR		0x10300000
-#define	SSI0_PHYS_ADDR		0x11600000
-#define	SSI1_PHYS_ADDR		0x11680000
-#define PCMCIA_IO_PHYS_ADDR	0xF00000000ULL
-#define PCMCIA_ATTR_PHYS_ADDR	0xF40000000ULL
-#define PCMCIA_MEM_PHYS_ADDR	0xF80000000ULL
-#endif
-
-/********************************************************************/
 
-#ifdef CONFIG_SOC_AU1500
-#define	MEM_PHYS_ADDR		0x14000000
-#define	STATIC_MEM_PHYS_ADDR	0x14001000
-#define	USBH_PHYS_ADDR		0x10100000
-#define PCI_PHYS_ADDR		0x14005000
-#define PCI_MEM_PHYS_ADDR	0x400000000ULL
-#define PCI_IO_PHYS_ADDR	0x500000000ULL
-#define PCI_CONFIG0_PHYS_ADDR	0x600000000ULL
-#define PCI_CONFIG1_PHYS_ADDR	0x680000000ULL
-#define PCMCIA_IO_PHYS_ADDR	0xF00000000ULL
-#define PCMCIA_ATTR_PHYS_ADDR	0xF40000000ULL
-#define PCMCIA_MEM_PHYS_ADDR	0xF80000000ULL
-#endif
-
-/********************************************************************/
-
-#ifdef CONFIG_SOC_AU1100
-#define	MEM_PHYS_ADDR		0x14000000
-#define	STATIC_MEM_PHYS_ADDR	0x14001000
-#define	USBH_PHYS_ADDR		0x10100000
-#define	IRDA_PHYS_ADDR		0x10300000
-#define	SSI0_PHYS_ADDR		0x11600000
-#define	SSI1_PHYS_ADDR		0x11680000
-#define LCD_PHYS_ADDR		0x15000000
-#define PCMCIA_IO_PHYS_ADDR	0xF00000000ULL
-#define PCMCIA_ATTR_PHYS_ADDR	0xF40000000ULL
-#define PCMCIA_MEM_PHYS_ADDR	0xF80000000ULL
-#endif
-
-/***********************************************************************/
-
-#ifdef CONFIG_SOC_AU1550
-#define	MEM_PHYS_ADDR		0x14000000
-#define	STATIC_MEM_PHYS_ADDR	0x14001000
-#define	USBH_PHYS_ADDR		0x14020000
-#define PCI_PHYS_ADDR		0x14005000
-#define PE_PHYS_ADDR		0x14008000
-#define PSC0_PHYS_ADDR		0x11A00000
-#define PSC1_PHYS_ADDR		0x11B00000
-#define PSC2_PHYS_ADDR		0x10A00000
-#define PSC3_PHYS_ADDR		0x10B00000
-#define PCI_MEM_PHYS_ADDR	0x400000000ULL
-#define PCI_IO_PHYS_ADDR	0x500000000ULL
-#define PCI_CONFIG0_PHYS_ADDR	0x600000000ULL
-#define PCI_CONFIG1_PHYS_ADDR	0x680000000ULL
-#define PCMCIA_IO_PHYS_ADDR	0xF00000000ULL
-#define PCMCIA_ATTR_PHYS_ADDR	0xF40000000ULL
-#define PCMCIA_MEM_PHYS_ADDR	0xF80000000ULL
-#endif
-
-/***********************************************************************/
-
-#ifdef CONFIG_SOC_AU1200
-#define	MEM_PHYS_ADDR		0x14000000
-#define	STATIC_MEM_PHYS_ADDR	0x14001000
-#define AES_PHYS_ADDR		0x10300000
-#define CIM_PHYS_ADDR		0x14004000
-#define USBM_PHYS_ADDR		0x14020000
-#define	USBH_PHYS_ADDR		0x14020100
-#define PSC0_PHYS_ADDR	 	0x11A00000
-#define PSC1_PHYS_ADDR	 	0x11B00000
-#define LCD_PHYS_ADDR		0x15000000
-#define SWCNT_PHYS_ADDR		0x1110010C
-#define MAEFE_PHYS_ADDR		0x14012000
-#define MAEBE_PHYS_ADDR		0x14010000
-#define PCMCIA_IO_PHYS_ADDR	0xF00000000ULL
-#define PCMCIA_ATTR_PHYS_ADDR	0xF40000000ULL
-#define PCMCIA_MEM_PHYS_ADDR	0xF80000000ULL
-#endif
+/* Au1550 SDRAM Register Offsets */
+#define AU1550_MEM_SDMODE0		0x0800
+#define AU1550_MEM_SDMODE1		0x0808
+#define AU1550_MEM_SDMODE2		0x0810
+#define AU1550_MEM_SDADDR0		0x0820
+#define AU1550_MEM_SDADDR1		0x0828
+#define AU1550_MEM_SDADDR2		0x0830
+#define AU1550_MEM_SDCONFIGA		0x0840
+#define AU1550_MEM_SDCONFIGB		0x0848
+#define AU1550_MEM_SDSTAT		0x0850
+#define AU1550_MEM_SDERRADDR		0x0858
+#define AU1550_MEM_SDSTRIDE0		0x0860
+#define AU1550_MEM_SDSTRIDE1		0x0868
+#define AU1550_MEM_SDSTRIDE2		0x0870
+#define AU1550_MEM_SDWRMD0		0x0880
+#define AU1550_MEM_SDWRMD1		0x0888
+#define AU1550_MEM_SDWRMD2		0x0890
+#define AU1550_MEM_SDPRECMD		0x08C0
+#define AU1550_MEM_SDAUTOREF		0x08C8
+#define AU1550_MEM_SDSREF		0x08D0
+#define AU1550_MEM_SDSLEEP		MEM_SDSREF
 
 /* Static Bus Controller */
 #define MEM_STCFG0		0xB4001000
@@ -813,80 +757,13 @@
 #define MEM_STTIME3		0xB4001034
 #define MEM_STADDR3		0xB4001038
 
-#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
 #define MEM_STNDCTL		0xB4001100
 #define MEM_STSTAT		0xB4001104
 
 #define MEM_STNAND_CMD		0x0
 #define MEM_STNAND_ADDR 	0x4
 #define MEM_STNAND_DATA 	0x20
-#endif
-
-
-
-
-/* Au1000 */
-#ifdef CONFIG_SOC_AU1000
-
-#define USB_OHCI_BASE		0x10100000	/* phys addr for ioremap */
-#define USB_HOST_CONFIG 	0xB017FFFC
-#define FOR_PLATFORM_C_USB_HOST_INT AU1000_USB_HOST_INT
-#endif /* CONFIG_SOC_AU1000 */
-
-/* Au1500 */
-#ifdef CONFIG_SOC_AU1500
-
-#define USB_OHCI_BASE		0x10100000	/* phys addr for ioremap */
-#define USB_HOST_CONFIG 	0xB017fffc
-#define FOR_PLATFORM_C_USB_HOST_INT AU1500_USB_HOST_INT
-#endif /* CONFIG_SOC_AU1500 */
-
-/* Au1100 */
-#ifdef CONFIG_SOC_AU1100
-
-#define USB_OHCI_BASE		0x10100000	/* phys addr for ioremap */
-#define USB_HOST_CONFIG 	0xB017FFFC
-#define FOR_PLATFORM_C_USB_HOST_INT AU1100_USB_HOST_INT
-#endif /* CONFIG_SOC_AU1100 */
-
-#ifdef CONFIG_SOC_AU1550
-
-#define USB_OHCI_BASE		0x14020000	/* phys addr for ioremap */
-#define USB_OHCI_LEN		0x00060000
-#define USB_HOST_CONFIG 	0xB4027ffc
-#define FOR_PLATFORM_C_USB_HOST_INT AU1550_USB_HOST_INT
-#endif /* CONFIG_SOC_AU1550 */
-
-
-#ifdef CONFIG_SOC_AU1200
-
-#define USB_UOC_BASE		0x14020020
-#define USB_UOC_LEN		0x20
-#define USB_OHCI_BASE		0x14020100
-#define USB_OHCI_LEN		0x100
-#define USB_EHCI_BASE		0x14020200
-#define USB_EHCI_LEN		0x100
-#define USB_UDC_BASE		0x14022000
-#define USB_UDC_LEN		0x2000
-#define USB_MSR_BASE		0xB4020000
-#define USB_MSR_MCFG		4
-#define USBMSRMCFG_OMEMEN	0
-#define USBMSRMCFG_OBMEN	1
-#define USBMSRMCFG_EMEMEN	2
-#define USBMSRMCFG_EBMEN	3
-#define USBMSRMCFG_DMEMEN	4
-#define USBMSRMCFG_DBMEN	5
-#define USBMSRMCFG_GMEMEN	6
-#define USBMSRMCFG_OHCCLKEN	16
-#define USBMSRMCFG_EHCCLKEN	17
-#define USBMSRMCFG_UDCCLKEN	18
-#define USBMSRMCFG_PHYPLLEN	19
-#define USBMSRMCFG_RDCOMB	30
-#define USBMSRMCFG_PFEN 	31
 
-#define FOR_PLATFORM_C_USB_HOST_INT AU1200_USB_INT
-
-#endif /* CONFIG_SOC_AU1200 */
 
 /* Programmable Counters 0 and 1 */
 #define SYS_BASE		0xB1900000
@@ -958,56 +835,6 @@
 #  define I2S_CONTROL_D 	(1 << 1)
 #  define I2S_CONTROL_CE	(1 << 0)
 
-/* USB Host Controller */
-#ifndef USB_OHCI_LEN
-#define USB_OHCI_LEN		0x00100000
-#endif
-
-#ifndef CONFIG_SOC_AU1200
-
-/* USB Device Controller */
-#define USBD_EP0RD		0xB0200000
-#define USBD_EP0WR		0xB0200004
-#define USBD_EP2WR		0xB0200008
-#define USBD_EP3WR		0xB020000C
-#define USBD_EP4RD		0xB0200010
-#define USBD_EP5RD		0xB0200014
-#define USBD_INTEN		0xB0200018
-#define USBD_INTSTAT		0xB020001C
-#  define USBDEV_INT_SOF	(1 << 12)
-#  define USBDEV_INT_HF_BIT	6
-#  define USBDEV_INT_HF_MASK	(0x3f << USBDEV_INT_HF_BIT)
-#  define USBDEV_INT_CMPLT_BIT	0
-#  define USBDEV_INT_CMPLT_MASK (0x3f << USBDEV_INT_CMPLT_BIT)
-#define USBD_CONFIG		0xB0200020
-#define USBD_EP0CS		0xB0200024
-#define USBD_EP2CS		0xB0200028
-#define USBD_EP3CS		0xB020002C
-#define USBD_EP4CS		0xB0200030
-#define USBD_EP5CS		0xB0200034
-#  define USBDEV_CS_SU		(1 << 14)
-#  define USBDEV_CS_NAK 	(1 << 13)
-#  define USBDEV_CS_ACK 	(1 << 12)
-#  define USBDEV_CS_BUSY	(1 << 11)
-#  define USBDEV_CS_TSIZE_BIT	1
-#  define USBDEV_CS_TSIZE_MASK	(0x3ff << USBDEV_CS_TSIZE_BIT)
-#  define USBDEV_CS_STALL	(1 << 0)
-#define USBD_EP0RDSTAT		0xB0200040
-#define USBD_EP0WRSTAT		0xB0200044
-#define USBD_EP2WRSTAT		0xB0200048
-#define USBD_EP3WRSTAT		0xB020004C
-#define USBD_EP4RDSTAT		0xB0200050
-#define USBD_EP5RDSTAT		0xB0200054
-#  define USBDEV_FSTAT_FLUSH	(1 << 6)
-#  define USBDEV_FSTAT_UF	(1 << 5)
-#  define USBDEV_FSTAT_OF	(1 << 4)
-#  define USBDEV_FSTAT_FCNT_BIT 0
-#  define USBDEV_FSTAT_FCNT_MASK (0x0f << USBDEV_FSTAT_FCNT_BIT)
-#define USBD_ENABLE		0xB0200058
-#  define USBDEV_ENABLE 	(1 << 1)
-#  define USBDEV_CE		(1 << 0)
-
-#endif /* !CONFIG_SOC_AU1200 */
 
 /* Ethernet Controllers  */
 
@@ -1322,7 +1149,6 @@
 #  define SYS_PF_MUST_BE_SET	((1 << 5) | (1 << 2))
 
 /* Au1200 only */
-#ifdef CONFIG_SOC_AU1200
 #define SYS_PINFUNC_DMA 	(1 << 31)
 #define SYS_PINFUNC_S0A 	(1 << 30)
 #define SYS_PINFUNC_S1A 	(1 << 29)
@@ -1350,7 +1176,6 @@
 #define SYS_PINFUNC_P0B 	(1 << 4)
 #define SYS_PINFUNC_U0T 	(1 << 3)
 #define SYS_PINFUNC_S1B 	(1 << 2)
-#endif
 
 /* Power Management */
 #define SYS_SCRATCH0		0xB1900018
@@ -1406,12 +1231,12 @@
 #  define SYS_CS_MI2_MASK	(0x7 << SYS_CS_MI2_BIT)
 #  define SYS_CS_DI2		(1 << 16)
 #  define SYS_CS_CI2		(1 << 15)
-#ifdef CONFIG_SOC_AU1100
+
 #  define SYS_CS_ML_BIT 	7
 #  define SYS_CS_ML_MASK	(0x7 << SYS_CS_ML_BIT)
 #  define SYS_CS_DL		(1 << 6)
 #  define SYS_CS_CL		(1 << 5)
-#else
+
 #  define SYS_CS_MUH_BIT	12
 #  define SYS_CS_MUH_MASK	(0x7 << SYS_CS_MUH_BIT)
 #  define SYS_CS_DUH		(1 << 11)
@@ -1420,7 +1245,7 @@
 #  define SYS_CS_MUD_MASK	(0x7 << SYS_CS_MUD_BIT)
 #  define SYS_CS_DUD		(1 << 6)
 #  define SYS_CS_CUD		(1 << 5)
-#endif
+
 #  define SYS_CS_MIR_BIT	2
 #  define SYS_CS_MIR_MASK	(0x7 << SYS_CS_MIR_BIT)
 #  define SYS_CS_DIR		(1 << 1)
@@ -1467,58 +1292,30 @@
 #  define AC97C_RS		(1 << 1)
 #  define AC97C_CE		(1 << 0)
 
-#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
-/* Au1500 PCI Controller */
-#define Au1500_CFG_BASE 	0xB4005000	/* virtual, KSEG1 addr */
-#define Au1500_PCI_CMEM 	(Au1500_CFG_BASE + 0)
-#define Au1500_PCI_CFG		(Au1500_CFG_BASE + 4)
-#  define PCI_ERROR		((1 << 22) | (1 << 23) | (1 << 24) | \
-				 (1 << 25) | (1 << 26) | (1 << 27))
-#define Au1500_PCI_B2BMASK_CCH	(Au1500_CFG_BASE + 8)
-#define Au1500_PCI_B2B0_VID	(Au1500_CFG_BASE + 0xC)
-#define Au1500_PCI_B2B1_ID	(Au1500_CFG_BASE + 0x10)
-#define Au1500_PCI_MWMASK_DEV	(Au1500_CFG_BASE + 0x14)
-#define Au1500_PCI_MWBASE_REV_CCL (Au1500_CFG_BASE + 0x18)
-#define Au1500_PCI_ERR_ADDR	(Au1500_CFG_BASE + 0x1C)
-#define Au1500_PCI_SPEC_INTACK	(Au1500_CFG_BASE + 0x20)
-#define Au1500_PCI_ID		(Au1500_CFG_BASE + 0x100)
-#define Au1500_PCI_STATCMD	(Au1500_CFG_BASE + 0x104)
-#define Au1500_PCI_CLASSREV	(Au1500_CFG_BASE + 0x108)
-#define Au1500_PCI_HDRTYPE	(Au1500_CFG_BASE + 0x10C)
-#define Au1500_PCI_MBAR 	(Au1500_CFG_BASE + 0x110)
-
-#define Au1500_PCI_HDR		0xB4005100	/* virtual, KSEG1 addr */
 
-/*
- * All of our structures, like PCI resource, have 32-bit members.
- * Drivers are expected to do an ioremap on the PCI MEM resource, but it's
- * hard to store 0x4 0000 0000 in a 32-bit type.  We require a small patch
- * to __ioremap to check for addresses between (u32)Au1500_PCI_MEM_START and
- * (u32)Au1500_PCI_MEM_END and change those to the full 36-bit PCI MEM
- * addresses.  For PCI I/O, it's simpler because we get to do the ioremap
- * ourselves and then adjust the device's resources.
+/* The PCI chip selects are outside the 32bit space, and since we can't
+ * just program the 36bit addresses into BARs, we have to take a chunk
+ * out of the 32bit space and reserve it for PCI.  When these addresses
+ * are ioremap()ed, they'll be fixed up to the real 36bit address before
+ * being passed to the real ioremap function.
  */
-#define Au1500_EXT_CFG		0x600000000ULL
-#define Au1500_EXT_CFG_TYPE1	0x680000000ULL
-#define Au1500_PCI_IO_START	0x500000000ULL
-#define Au1500_PCI_IO_END	0x5000FFFFFULL
-#define Au1500_PCI_MEM_START	0x440000000ULL
-#define Au1500_PCI_MEM_END	0x44FFFFFFFULL
+#define ALCHEMY_PCI_MEMWIN_START	(AU1500_PCI_MEM_PHYS_ADDR >> 4)
+#define ALCHEMY_PCI_MEMWIN_END		(ALCHEMY_PCI_MEMWIN_START + 0x0FFFFFFF)
 
-#define PCI_IO_START	0x00001000
-#define PCI_IO_END	0x000FFFFF
-#define PCI_MEM_START	0x40000000
-#define PCI_MEM_END	0x4FFFFFFF
+/* for PCI IO it's simpler because we get to do the ioremap ourselves and then
+ * adjust the device's resources.
+ */
+#define ALCHEMY_PCI_IOWIN_START		0x00001000
+#define ALCHEMY_PCI_IOWIN_END		0x0000FFFF
 
-#define PCI_FIRST_DEVFN (0 << 3)
-#define PCI_LAST_DEVFN	(19 << 3)
+#ifdef CONFIG_PCI
 
 #define IOPORT_RESOURCE_START	0x00001000	/* skip legacy probing */
 #define IOPORT_RESOURCE_END	0xffffffff
 #define IOMEM_RESOURCE_START	0x10000000
 #define IOMEM_RESOURCE_END	0xfffffffffULL
 
-#else /* Au1000 and Au1100 and Au1200 */
+#else
 
 /* Don't allow any legacy ports probing */
 #define IOPORT_RESOURCE_START	0x10000000
@@ -1526,13 +1323,77 @@
 #define IOMEM_RESOURCE_START	0x10000000
 #define IOMEM_RESOURCE_END	0xfffffffffULL
 
-#define PCI_IO_START	0
-#define PCI_IO_END	0
-#define PCI_MEM_START	0
-#define PCI_MEM_END	0
-#define PCI_FIRST_DEVFN 0
-#define PCI_LAST_DEVFN	0
-
 #endif
 
+/* PCI controller block register offsets */
+#define PCI_REG_CMEM		0x0000
+#define PCI_REG_CONFIG		0x0004
+#define PCI_REG_B2BMASK_CCH	0x0008
+#define PCI_REG_B2BBASE0_VID	0x000C
+#define PCI_REG_B2BBASE1_SID	0x0010
+#define PCI_REG_MWMASK_DEV	0x0014
+#define PCI_REG_MWBASE_REV_CCL	0x0018
+#define PCI_REG_ERR_ADDR	0x001C
+#define PCI_REG_SPEC_INTACK	0x0020
+#define PCI_REG_ID		0x0100
+#define PCI_REG_STATCMD		0x0104
+#define PCI_REG_CLASSREV	0x0108
+#define PCI_REG_PARAM		0x010C
+#define PCI_REG_MBAR		0x0110
+#define PCI_REG_TIMEOUT		0x0140
+
+/* PCI controller block register bits */
+#define PCI_CMEM_E		(1 << 28)	/* enable cacheable memory */
+#define PCI_CMEM_CMBASE(x)	(((x) & 0x3fff) << 14)
+#define PCI_CMEM_CMMASK(x)	((x) & 0x3fff)
+#define PCI_CONFIG_ERD		(1 << 27) /* pci error during R/W */
+#define PCI_CONFIG_ET		(1 << 26) /* error in target mode */
+#define PCI_CONFIG_EF		(1 << 25) /* fatal error */
+#define PCI_CONFIG_EP		(1 << 24) /* parity error */
+#define PCI_CONFIG_EM		(1 << 23) /* multiple errors */
+#define PCI_CONFIG_BM		(1 << 22) /* bad master error */
+#define PCI_CONFIG_PD		(1 << 20) /* PCI Disable */
+#define PCI_CONFIG_BME		(1 << 19) /* Byte Mask Enable for reads */
+#define PCI_CONFIG_NC		(1 << 16) /* mark mem access non-coherent */
+#define PCI_CONFIG_IA		(1 << 15) /* INTA# enabled (target mode) */
+#define PCI_CONFIG_IP		(1 << 13) /* int on PCI_PERR# */
+#define PCI_CONFIG_IS		(1 << 12) /* int on PCI_SERR# */
+#define PCI_CONFIG_IMM		(1 << 11) /* int on master abort */
+#define PCI_CONFIG_ITM		(1 << 10) /* int on target abort (as master) */
+#define PCI_CONFIG_ITT		(1 << 9)  /* int on target abort (as target) */
+#define PCI_CONFIG_IPB		(1 << 8)  /* int on PERR# in bus master acc */
+#define PCI_CONFIG_SIC_NO	(0 << 6)  /* no byte mask changes */
+#define PCI_CONFIG_SIC_BA_ADR	(1 << 6)  /* on byte/hw acc, invert adr bits */
+#define PCI_CONFIG_SIC_HWA_DAT	(2 << 6)  /* on halfword acc, swap data */
+#define PCI_CONFIG_SIC_ALL	(3 << 6)  /* swap data bytes on all accesses */
+#define PCI_CONFIG_ST		(1 << 5)  /* swap data by target transactions */
+#define PCI_CONFIG_SM		(1 << 4)  /* swap data from PCI ctl */
+#define PCI_CONFIG_AEN		(1 << 3)  /* enable internal arbiter */
+#define PCI_CONFIG_R2H		(1 << 2)  /* REQ2# to hi-prio arbiter */
+#define PCI_CONFIG_R1H		(1 << 1)  /* REQ1# to hi-prio arbiter */
+#define PCI_CONFIG_CH		(1 << 0)  /* PCI ctl to hi-prio arbiter */
+#define PCI_B2BMASK_B2BMASK(x)	(((x) & 0xffff) << 16)
+#define PCI_B2BMASK_CCH(x)	((x) & 0xffff) /* 16 upper bits of class code */
+#define PCI_B2BBASE0_VID_B0(x)	(((x) & 0xffff) << 16)
+#define PCI_B2BBASE0_VID_SV(x)	((x) & 0xffff)
+#define PCI_B2BBASE1_SID_B1(x)	(((x) & 0xffff) << 16)
+#define PCI_B2BBASE1_SID_SI(x)	((x) & 0xffff)
+#define PCI_MWMASKDEV_MWMASK(x) (((x) & 0xffff) << 16)
+#define PCI_MWMASKDEV_DEVID(x)	((x) & 0xffff)
+#define PCI_MWBASEREVCCL_BASE(x) (((x) & 0xffff) << 16)
+#define PCI_MWBASEREVCCL_REV(x)  (((x) & 0xff) << 8)
+#define PCI_MWBASEREVCCL_CCL(x)  ((x) & 0xff)
+#define PCI_ID_DID(x)		(((x) & 0xffff) << 16)
+#define PCI_ID_VID(x)		((x) & 0xffff)
+#define PCI_STATCMD_STATUS(x)	(((x) & 0xffff) << 16)
+#define PCI_STATCMD_CMD(x)	((x) & 0xffff)
+#define PCI_CLASSREV_CLASS(x)	(((x) & 0x00ffffff) << 8)
+#define PCI_CLASSREV_REV(x)	((x) & 0xff)
+#define PCI_PARAM_BIST(x)	(((x) & 0xff) << 24)
+#define PCI_PARAM_HT(x)		(((x) & 0xff) << 16)
+#define PCI_PARAM_LT(x)		(((x) & 0xff) << 8)
+#define PCI_PARAM_CLS(x)	((x) & 0xff)
+#define PCI_TIMEOUT_RETRIES(x)	(((x) & 0xff) << 8)	/* max retries */
+#define PCI_TIMEOUT_TO(x)	((x) & 0xff)	/* target ready timeout */
+
 #endif
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h linux-libre-3.2-gnu/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h	2012-01-04 18:55:44.000000000 -0500
@@ -126,66 +126,62 @@
 #define SW_STATUS_INUSE 	(1 << 0)
 
 /* Command 0 device IDs. */
-#ifdef CONFIG_SOC_AU1550
-#define DSCR_CMD0_UART0_TX	0
-#define DSCR_CMD0_UART0_RX	1
-#define DSCR_CMD0_UART3_TX	2
-#define DSCR_CMD0_UART3_RX	3
-#define DSCR_CMD0_DMA_REQ0	4
-#define DSCR_CMD0_DMA_REQ1	5
-#define DSCR_CMD0_DMA_REQ2	6
-#define DSCR_CMD0_DMA_REQ3	7
-#define DSCR_CMD0_USBDEV_RX0	8
-#define DSCR_CMD0_USBDEV_TX0	9
-#define DSCR_CMD0_USBDEV_TX1	10
-#define DSCR_CMD0_USBDEV_TX2	11
-#define DSCR_CMD0_USBDEV_RX3	12
-#define DSCR_CMD0_USBDEV_RX4	13
-#define DSCR_CMD0_PSC0_TX	14
-#define DSCR_CMD0_PSC0_RX	15
-#define DSCR_CMD0_PSC1_TX	16
-#define DSCR_CMD0_PSC1_RX	17
-#define DSCR_CMD0_PSC2_TX	18
-#define DSCR_CMD0_PSC2_RX	19
-#define DSCR_CMD0_PSC3_TX	20
-#define DSCR_CMD0_PSC3_RX	21
-#define DSCR_CMD0_PCI_WRITE	22
-#define DSCR_CMD0_NAND_FLASH	23
-#define DSCR_CMD0_MAC0_RX	24
-#define DSCR_CMD0_MAC0_TX	25
-#define DSCR_CMD0_MAC1_RX	26
-#define DSCR_CMD0_MAC1_TX	27
-#endif /* CONFIG_SOC_AU1550 */
+#define AU1550_DSCR_CMD0_UART0_TX	0
+#define AU1550_DSCR_CMD0_UART0_RX	1
+#define AU1550_DSCR_CMD0_UART3_TX	2
+#define AU1550_DSCR_CMD0_UART3_RX	3
+#define AU1550_DSCR_CMD0_DMA_REQ0	4
+#define AU1550_DSCR_CMD0_DMA_REQ1	5
+#define AU1550_DSCR_CMD0_DMA_REQ2	6
+#define AU1550_DSCR_CMD0_DMA_REQ3	7
+#define AU1550_DSCR_CMD0_USBDEV_RX0	8
+#define AU1550_DSCR_CMD0_USBDEV_TX0	9
+#define AU1550_DSCR_CMD0_USBDEV_TX1	10
+#define AU1550_DSCR_CMD0_USBDEV_TX2	11
+#define AU1550_DSCR_CMD0_USBDEV_RX3	12
+#define AU1550_DSCR_CMD0_USBDEV_RX4	13
+#define AU1550_DSCR_CMD0_PSC0_TX	14
+#define AU1550_DSCR_CMD0_PSC0_RX	15
+#define AU1550_DSCR_CMD0_PSC1_TX	16
+#define AU1550_DSCR_CMD0_PSC1_RX	17
+#define AU1550_DSCR_CMD0_PSC2_TX	18
+#define AU1550_DSCR_CMD0_PSC2_RX	19
+#define AU1550_DSCR_CMD0_PSC3_TX	20
+#define AU1550_DSCR_CMD0_PSC3_RX	21
+#define AU1550_DSCR_CMD0_PCI_WRITE	22
+#define AU1550_DSCR_CMD0_NAND_FLASH	23
+#define AU1550_DSCR_CMD0_MAC0_RX	24
+#define AU1550_DSCR_CMD0_MAC0_TX	25
+#define AU1550_DSCR_CMD0_MAC1_RX	26
+#define AU1550_DSCR_CMD0_MAC1_TX	27
 
-#ifdef CONFIG_SOC_AU1200
-#define DSCR_CMD0_UART0_TX	0
-#define DSCR_CMD0_UART0_RX	1
-#define DSCR_CMD0_UART1_TX	2
-#define DSCR_CMD0_UART1_RX	3
-#define DSCR_CMD0_DMA_REQ0	4
-#define DSCR_CMD0_DMA_REQ1	5
-#define DSCR_CMD0_MAE_BE	6
-#define DSCR_CMD0_MAE_FE	7
-#define DSCR_CMD0_SDMS_TX0	8
-#define DSCR_CMD0_SDMS_RX0	9
-#define DSCR_CMD0_SDMS_TX1	10
-#define DSCR_CMD0_SDMS_RX1	11
-#define DSCR_CMD0_AES_TX	13
-#define DSCR_CMD0_AES_RX	12
-#define DSCR_CMD0_PSC0_TX	14
-#define DSCR_CMD0_PSC0_RX	15
-#define DSCR_CMD0_PSC1_TX	16
-#define DSCR_CMD0_PSC1_RX	17
-#define DSCR_CMD0_CIM_RXA	18
-#define DSCR_CMD0_CIM_RXB	19
-#define DSCR_CMD0_CIM_RXC	20
-#define DSCR_CMD0_MAE_BOTH	21
-#define DSCR_CMD0_LCD		22
-#define DSCR_CMD0_NAND_FLASH	23
-#define DSCR_CMD0_PSC0_SYNC	24
-#define DSCR_CMD0_PSC1_SYNC	25
-#define DSCR_CMD0_CIM_SYNC	26
-#endif /* CONFIG_SOC_AU1200 */
+#define AU1200_DSCR_CMD0_UART0_TX	0
+#define AU1200_DSCR_CMD0_UART0_RX	1
+#define AU1200_DSCR_CMD0_UART1_TX	2
+#define AU1200_DSCR_CMD0_UART1_RX	3
+#define AU1200_DSCR_CMD0_DMA_REQ0	4
+#define AU1200_DSCR_CMD0_DMA_REQ1	5
+#define AU1200_DSCR_CMD0_MAE_BE		6
+#define AU1200_DSCR_CMD0_MAE_FE		7
+#define AU1200_DSCR_CMD0_SDMS_TX0	8
+#define AU1200_DSCR_CMD0_SDMS_RX0	9
+#define AU1200_DSCR_CMD0_SDMS_TX1	10
+#define AU1200_DSCR_CMD0_SDMS_RX1	11
+#define AU1200_DSCR_CMD0_AES_TX		13
+#define AU1200_DSCR_CMD0_AES_RX		12
+#define AU1200_DSCR_CMD0_PSC0_TX	14
+#define AU1200_DSCR_CMD0_PSC0_RX	15
+#define AU1200_DSCR_CMD0_PSC1_TX	16
+#define AU1200_DSCR_CMD0_PSC1_RX	17
+#define AU1200_DSCR_CMD0_CIM_RXA	18
+#define AU1200_DSCR_CMD0_CIM_RXB	19
+#define AU1200_DSCR_CMD0_CIM_RXC	20
+#define AU1200_DSCR_CMD0_MAE_BOTH	21
+#define AU1200_DSCR_CMD0_LCD		22
+#define AU1200_DSCR_CMD0_NAND_FLASH	23
+#define AU1200_DSCR_CMD0_PSC0_SYNC	24
+#define AU1200_DSCR_CMD0_PSC1_SYNC	25
+#define AU1200_DSCR_CMD0_CIM_SYNC	26
 
 #define DSCR_CMD0_THROTTLE	30
 #define DSCR_CMD0_ALWAYS	31
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/mach-au1x00/au1xxx.h linux-libre-3.2-gnu/arch/mips/include/asm/mach-au1x00/au1xxx.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/mach-au1x00/au1xxx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/mach-au1x00/au1xxx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +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.
- *
- *  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 _AU1XXX_H_
-#define _AU1XXX_H_
-
-#include <asm/mach-au1x00/au1000.h>
-
-#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || \
-    defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_DB1550)
-#include <asm/mach-db1x00/db1x00.h>
-
-#elif defined(CONFIG_MIPS_PB1550)
-#include <asm/mach-pb1x00/pb1550.h>
-
-#elif defined(CONFIG_MIPS_PB1200)
-#include <asm/mach-pb1x00/pb1200.h>
-
-#elif defined(CONFIG_MIPS_DB1200)
-#include <asm/mach-db1x00/db1200.h>
-
-#endif
-
-#endif /* _AU1XXX_H_ */
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/mach-au1x00/au1xxx_ide.h linux-libre-3.2-gnu/arch/mips/include/asm/mach-au1x00/au1xxx_ide.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/mach-au1x00/au1xxx_ide.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/mach-au1x00/au1xxx_ide.h	2012-01-04 18:55:44.000000000 -0500
@@ -58,6 +58,7 @@
 #endif
 	int			irq;
 	u32			regbase;
+	int			ddma_id;
 } _auide_hwif;
 
 /******************************************************************************/
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h linux-libre-3.2-gnu/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h	2012-01-04 18:55:44.000000000 -0500
@@ -33,19 +33,6 @@
 #ifndef _AU1000_PSC_H_
 #define _AU1000_PSC_H_
 
-/* The PSC base addresses.  */
-#ifdef CONFIG_SOC_AU1550
-#define PSC0_BASE_ADDR		0xb1a00000
-#define PSC1_BASE_ADDR		0xb1b00000
-#define PSC2_BASE_ADDR		0xb0a00000
-#define PSC3_BASE_ADDR		0xb0b00000
-#endif
-
-#ifdef CONFIG_SOC_AU1200
-#define PSC0_BASE_ADDR		0xb1a00000
-#define PSC1_BASE_ADDR		0xb1b00000
-#endif
-
 /*
  * The PSC select and control registers are common to all protocols.
  */
@@ -80,19 +67,6 @@
 #define PSC_AC97GPO_OFFSET	0x00000028
 #define PSC_AC97GPI_OFFSET	0x0000002c
 
-#define AC97_PSC_SEL		(AC97_PSC_BASE + PSC_SEL_OFFSET)
-#define AC97_PSC_CTRL		(AC97_PSC_BASE + PSC_CTRL_OFFSET)
-#define PSC_AC97CFG		(AC97_PSC_BASE + PSC_AC97CFG_OFFSET)
-#define PSC_AC97MSK		(AC97_PSC_BASE + PSC_AC97MSK_OFFSET)
-#define PSC_AC97PCR		(AC97_PSC_BASE + PSC_AC97PCR_OFFSET)
-#define PSC_AC97STAT		(AC97_PSC_BASE + PSC_AC97STAT_OFFSET)
-#define PSC_AC97EVNT		(AC97_PSC_BASE + PSC_AC97EVNT_OFFSET)
-#define PSC_AC97TXRX		(AC97_PSC_BASE + PSC_AC97TXRX_OFFSET)
-#define PSC_AC97CDC		(AC97_PSC_BASE + PSC_AC97CDC_OFFSET)
-#define PSC_AC97RST		(AC97_PSC_BASE + PSC_AC97RST_OFFSET)
-#define PSC_AC97GPO		(AC97_PSC_BASE + PSC_AC97GPO_OFFSET)
-#define PSC_AC97GPI		(AC97_PSC_BASE + PSC_AC97GPI_OFFSET)
-
 /* AC97 Config Register. */
 #define PSC_AC97CFG_RT_MASK	(3 << 30)
 #define PSC_AC97CFG_RT_FIFO1	(0 << 30)
@@ -394,19 +368,6 @@
 #define PSC_SPITXRX_LC		(1 << 29)
 #define PSC_SPITXRX_SR		(1 << 28)
 
-/* PSC in SMBus (I2C) Mode. */
-typedef struct	psc_smb {
-	u32	psc_sel;
-	u32	psc_ctrl;
-	u32	psc_smbcfg;
-	u32	psc_smbmsk;
-	u32	psc_smbpcr;
-	u32	psc_smbstat;
-	u32	psc_smbevnt;
-	u32	psc_smbtxrx;
-	u32	psc_smbtmr;
-} psc_smb_t;
-
 /* SMBus Config Register. */
 #define PSC_SMBCFG_RT_MASK	(3 << 30)
 #define PSC_SMBCFG_RT_FIFO1	(0 << 30)
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/mach-au1x00/gpio-au1000.h linux-libre-3.2-gnu/arch/mips/include/asm/mach-au1x00/gpio-au1000.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/mach-au1x00/gpio-au1000.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/mach-au1x00/gpio-au1000.h	2012-01-04 18:55:44.000000000 -0500
@@ -347,17 +347,6 @@
 
 /**********************************************************************/
 
-/* On Au1000, Au1500 and Au1100 GPIOs won't work as inputs before
- * SYS_PININPUTEN is written to at least once.  On Au1550/Au1200 this
- * register enables use of GPIOs as wake source.
- */
-static inline void alchemy_gpio1_input_enable(void)
-{
-	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
-	__raw_writel(0, base + SYS_PININPUTEN);	/* the write op is key */
-	wmb();
-}
-
 /* GPIO2 shared interrupts and control */
 
 static inline void __alchemy_gpio2_mod_int(int gpio2, int en)
@@ -561,6 +550,7 @@
 
 #ifndef CONFIG_GPIOLIB
 
+#ifdef CONFIG_ALCHEMY_GPIOINT_AU1000
 
 #ifndef CONFIG_ALCHEMY_GPIO_INDIRECT	/* case (4) */
 
@@ -665,24 +655,7 @@
 
 #endif	/* !CONFIG_ALCHEMY_GPIO_INDIRECT */
 
-
-#else	/* CONFIG GPIOLIB */
-
-
- /* using gpiolib to provide up to 2 gpio_chips for on-chip gpios */
-#ifndef CONFIG_ALCHEMY_GPIO_INDIRECT	/* case (2) */
-
-/* get everything through gpiolib */
-#define gpio_to_irq	__gpio_to_irq
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-#define irq_to_gpio	alchemy_irq_to_gpio
-
-#include <asm-generic/gpio.h>
-
-#endif	/* !CONFIG_ALCHEMY_GPIO_INDIRECT */
-
+#endif	/* CONFIG_ALCHEMY_GPIOINT_AU1000 */
 
 #endif	/* !CONFIG_GPIOLIB */
 
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/mach-au1x00/gpio.h linux-libre-3.2-gnu/arch/mips/include/asm/mach-au1x00/gpio.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/mach-au1x00/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/mach-au1x00/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,10 +1,83 @@
+/*
+ * Alchemy GPIO support.
+ *
+ * With CONFIG_GPIOLIB=y different types of on-chip GPIO can be supported within
+ *  the same kernel image.
+ * With CONFIG_GPIOLIB=n, your board must select ALCHEMY_GPIOINT_AU1XXX for the
+ *  appropriate CPU type (AU1000 currently).
+ */
+
 #ifndef _ALCHEMY_GPIO_H_
 #define _ALCHEMY_GPIO_H_
 
-#if defined(CONFIG_ALCHEMY_GPIOINT_AU1000)
-
+#include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/gpio-au1000.h>
 
-#endif
+/* On Au1000, Au1500 and Au1100 GPIOs won't work as inputs before
+ * SYS_PININPUTEN is written to at least once.  On Au1550/Au1200/Au1300 this
+ * register enables use of GPIOs as wake source.
+ */
+static inline void alchemy_gpio1_input_enable(void)
+{
+	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
+	__raw_writel(0, base + 0x110);		/* the write op is key */
+	wmb();
+}
+
+
+/* Linux gpio framework integration.
+*
+* 4 use cases of Alchemy GPIOS:
+*(1) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=y:
+*	Board must register gpiochips.
+*(2) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=n:
+*	A gpiochip for the 75 GPIOs is registered.
+*
+*(3) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=y:
+*	the boards' gpio.h must provide	the linux gpio wrapper functions,
+*
+*(4) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=n:
+*	inlinable gpio functions are provided which enable access to the
+*	Au1300 gpios only by using the numbers straight out of the data-
+*	sheets.
+
+* Cases 1 and 3 are intended for boards which want to provide their own
+* GPIO namespace and -operations (i.e. for example you have 8 GPIOs
+* which are in part provided by spare Au1300 GPIO pins and in part by
+* an external FPGA but you still want them to be accssible in linux
+* as gpio0-7. The board can of course use the alchemy_gpioX_* functions
+* as required).
+*/
+
+#ifdef CONFIG_GPIOLIB
+
+/* wraps the cpu-dependent irq_to_gpio functions */
+/* FIXME: gpiolib needs an irq_to_gpio hook */
+static inline int __au_irq_to_gpio(unsigned int irq)
+{
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1000...ALCHEMY_CPU_AU1200:
+		return alchemy_irq_to_gpio(irq);
+	}
+	return -EINVAL;
+}
+
+
+/* using gpiolib to provide up to 2 gpio_chips for on-chip gpios */
+#ifndef CONFIG_ALCHEMY_GPIO_INDIRECT	/* case (2) */
+
+/* get everything through gpiolib */
+#define gpio_to_irq	__gpio_to_irq
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+#define irq_to_gpio	__au_irq_to_gpio
+
+#include <asm-generic/gpio.h>
+
+#endif	/* !CONFIG_ALCHEMY_GPIO_INDIRECT */
+
+
+#endif	/* CONFIG_GPIOLIB */
 
 #endif	/* _ALCHEMY_GPIO_H_ */
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h linux-libre-3.2-gnu/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,29 @@
 #ifndef __ASM_BCM47XX_H
 #define __ASM_BCM47XX_H
 
-/* SSB bus */
-extern struct ssb_bus ssb_bcm47xx;
+#include <linux/ssb/ssb.h>
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_soc.h>
+
+enum bcm47xx_bus_type {
+#ifdef CONFIG_BCM47XX_SSB
+	BCM47XX_BUS_TYPE_SSB,
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	BCM47XX_BUS_TYPE_BCMA,
+#endif
+};
+
+union bcm47xx_bus {
+#ifdef CONFIG_BCM47XX_SSB
+	struct ssb_bus ssb;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	struct bcma_soc bcma;
+#endif
+};
+
+extern union bcm47xx_bus bcm47xx_bus;
+extern enum bcm47xx_bus_type bcm47xx_bus_type;
 
 #endif /* __ASM_BCM47XX_H */
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/mach-bcm47xx/gpio.h linux-libre-3.2-gnu/arch/mips/include/asm/mach-bcm47xx/gpio.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/mach-bcm47xx/gpio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/mach-bcm47xx/gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #define __BCM47XX_GPIO_H
 
 #include <linux/ssb/ssb_embedded.h>
+#include <linux/bcma/bcma.h>
 #include <asm/mach-bcm47xx/bcm47xx.h>
 
 #define BCM47XX_EXTIF_GPIO_LINES	5
@@ -21,45 +22,134 @@
 
 static inline int gpio_get_value(unsigned gpio)
 {
-	return ssb_gpio_in(&ssb_bcm47xx, 1 << gpio);
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio);
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		return bcma_chipco_gpio_in(&bcm47xx_bus.bcma.bus.drv_cc,
+					   1 << gpio);
+#endif
+	}
+	return -EINVAL;
 }
 
+#define gpio_get_value_cansleep	gpio_get_value
+
 static inline void gpio_set_value(unsigned gpio, int value)
 {
-	ssb_gpio_out(&ssb_bcm47xx, 1 << gpio, value ? 1 << gpio : 0);
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
+			     value ? 1 << gpio : 0);
+		return;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
+				     value ? 1 << gpio : 0);
+		return;
+#endif
+	}
 }
 
-static inline int gpio_direction_input(unsigned gpio)
+#define gpio_set_value_cansleep gpio_set_value
+
+static inline int gpio_cansleep(unsigned gpio)
 {
-	ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 0);
 	return 0;
 }
 
+static inline int gpio_is_valid(unsigned gpio)
+{
+	return gpio < (BCM47XX_EXTIF_GPIO_LINES + BCM47XX_CHIPCO_GPIO_LINES);
+}
+
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0);
+		return 0;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
+				       0);
+		return 0;
+#endif
+	}
+	return -EINVAL;
+}
+
 static inline int gpio_direction_output(unsigned gpio, int value)
 {
-	/* first set the gpio out value */
-	ssb_gpio_out(&ssb_bcm47xx, 1 << gpio, value ? 1 << gpio : 0);
-	/* then set the gpio mode */
-	ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 1 << gpio);
-	return 0;
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		/* first set the gpio out value */
+		ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
+			     value ? 1 << gpio : 0);
+		/* then set the gpio mode */
+		ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio);
+		return 0;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		/* first set the gpio out value */
+		bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
+				     value ? 1 << gpio : 0);
+		/* then set the gpio mode */
+		bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
+				       1 << gpio);
+		return 0;
+#endif
+	}
+	return -EINVAL;
 }
 
 static inline int gpio_intmask(unsigned gpio, int value)
 {
-	ssb_gpio_intmask(&ssb_bcm47xx, 1 << gpio,
-			 value ? 1 << gpio : 0);
-	return 0;
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio,
+				 value ? 1 << gpio : 0);
+		return 0;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_chipco_gpio_intmask(&bcm47xx_bus.bcma.bus.drv_cc,
+					 1 << gpio, value ? 1 << gpio : 0);
+		return 0;
+#endif
+	}
+	return -EINVAL;
 }
 
 static inline int gpio_polarity(unsigned gpio, int value)
 {
-	ssb_gpio_polarity(&ssb_bcm47xx, 1 << gpio,
-			  value ? 1 << gpio : 0);
-	return 0;
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio,
+				  value ? 1 << gpio : 0);
+		return 0;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_chipco_gpio_polarity(&bcm47xx_bus.bcma.bus.drv_cc,
+					  1 << gpio, value ? 1 << gpio : 0);
+		return 0;
+#endif
+	}
+	return -EINVAL;
 }
 
 
-/* cansleep wrappers */
-#include <asm-generic/gpio.h>
-
 #endif /* __BCM47XX_GPIO_H */
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/mach-db1x00/db1200.h linux-libre-3.2-gnu/arch/mips/include/asm/mach-db1x00/db1200.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/mach-db1x00/db1200.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/mach-db1x00/db1200.h	2012-01-04 18:55:44.000000000 -0500
@@ -46,8 +46,6 @@
 
 #define IDE_PHYS_ADDR		0x18800000
 #define IDE_REG_SHIFT		5
-#define IDE_DDMA_REQ		DSCR_CMD0_DMA_REQ1
-#define IDE_RQSIZE		128
 
 #define DB1200_IDE_PHYS_ADDR	IDE_PHYS_ADDR
 #define DB1200_IDE_PHYS_LEN	(16 << IDE_REG_SHIFT)
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/mach-db1x00/db1x00.h linux-libre-3.2-gnu/arch/mips/include/asm/mach-db1x00/db1x00.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/mach-db1x00/db1x00.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/mach-db1x00/db1x00.h	2012-01-04 18:55:44.000000000 -0500
@@ -31,15 +31,15 @@
 
 #ifdef CONFIG_MIPS_DB1550
 
-#define DBDMA_AC97_TX_CHAN	DSCR_CMD0_PSC1_TX
-#define DBDMA_AC97_RX_CHAN	DSCR_CMD0_PSC1_RX
-#define DBDMA_I2S_TX_CHAN	DSCR_CMD0_PSC3_TX
-#define DBDMA_I2S_RX_CHAN	DSCR_CMD0_PSC3_RX
+#define DBDMA_AC97_TX_CHAN	AU1550_DSCR_CMD0_PSC1_TX
+#define DBDMA_AC97_RX_CHAN	AU1550_DSCR_CMD0_PSC1_RX
+#define DBDMA_I2S_TX_CHAN	AU1550_DSCR_CMD0_PSC3_TX
+#define DBDMA_I2S_RX_CHAN	AU1550_DSCR_CMD0_PSC3_RX
 
-#define SPI_PSC_BASE		PSC0_BASE_ADDR
-#define AC97_PSC_BASE		PSC1_BASE_ADDR
-#define SMBUS_PSC_BASE		PSC2_BASE_ADDR
-#define I2S_PSC_BASE		PSC3_BASE_ADDR
+#define SPI_PSC_BASE		AU1550_PSC0_PHYS_ADDR
+#define AC97_PSC_BASE		AU1550_PSC1_PHYS_ADDR
+#define SMBUS_PSC_BASE		AU1550_PSC2_PHYS_ADDR
+#define I2S_PSC_BASE		AU1550_PSC3_PHYS_ADDR
 
 #define NAND_PHYS_ADDR		0x20000000
 
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/mach-pb1x00/pb1200.h linux-libre-3.2-gnu/arch/mips/include/asm/mach-pb1x00/pb1200.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/mach-pb1x00/pb1200.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/mach-pb1x00/pb1200.h	2012-01-04 18:55:44.000000000 -0500
@@ -28,23 +28,23 @@
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_psc.h>
 
-#define DBDMA_AC97_TX_CHAN	DSCR_CMD0_PSC1_TX
-#define DBDMA_AC97_RX_CHAN	DSCR_CMD0_PSC1_RX
-#define DBDMA_I2S_TX_CHAN	DSCR_CMD0_PSC1_TX
-#define DBDMA_I2S_RX_CHAN	DSCR_CMD0_PSC1_RX
+#define DBDMA_AC97_TX_CHAN	AU1200_DSCR_CMD0_PSC1_TX
+#define DBDMA_AC97_RX_CHAN	AU1200_DSCR_CMD0_PSC1_RX
+#define DBDMA_I2S_TX_CHAN	AU1200_DSCR_CMD0_PSC1_TX
+#define DBDMA_I2S_RX_CHAN	AU1200_DSCR_CMD0_PSC1_RX
 
 /*
  * SPI and SMB are muxed on the Pb1200 board.
  * Refer to board documentation.
  */
-#define SPI_PSC_BASE		PSC0_BASE_ADDR
-#define SMBUS_PSC_BASE		PSC0_BASE_ADDR
+#define SPI_PSC_BASE		AU1550_PSC0_PHYS_ADDR
+#define SMBUS_PSC_BASE		AU1550_PSC0_PHYS_ADDR
 /*
  * AC97 and I2S are muxed on the Pb1200 board.
  * Refer to board documentation.
  */
-#define AC97_PSC_BASE       PSC1_BASE_ADDR
-#define I2S_PSC_BASE	PSC1_BASE_ADDR
+#define AC97_PSC_BASE       AU1550_PSC1_PHYS_ADDR
+#define I2S_PSC_BASE	AU1550_PSC1_PHYS_ADDR
 
 
 #define BCSR_SYSTEM_VDDI	0x001F
@@ -76,8 +76,6 @@
 #define IDE_REG_SHIFT		5
 #define IDE_PHYS_LEN		(16 << IDE_REG_SHIFT)
 #define IDE_INT 		PB1200_IDE_INT
-#define IDE_DDMA_REQ		DSCR_CMD0_DMA_REQ1
-#define IDE_RQSIZE		128
 
 #define NAND_PHYS_ADDR 	0x1C000000
 
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/mach-pb1x00/pb1550.h linux-libre-3.2-gnu/arch/mips/include/asm/mach-pb1x00/pb1550.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/mach-pb1x00/pb1550.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/mach-pb1x00/pb1550.h	2012-01-04 18:55:44.000000000 -0500
@@ -30,15 +30,15 @@
 #include <linux/types.h>
 #include <asm/mach-au1x00/au1xxx_psc.h>
 
-#define DBDMA_AC97_TX_CHAN	DSCR_CMD0_PSC1_TX
-#define DBDMA_AC97_RX_CHAN	DSCR_CMD0_PSC1_RX
-#define DBDMA_I2S_TX_CHAN	DSCR_CMD0_PSC3_TX
-#define DBDMA_I2S_RX_CHAN	DSCR_CMD0_PSC3_RX
+#define DBDMA_AC97_TX_CHAN	AU1550_DSCR_CMD0_PSC1_TX
+#define DBDMA_AC97_RX_CHAN	AU1550_DSCR_CMD0_PSC1_RX
+#define DBDMA_I2S_TX_CHAN	AU1550_DSCR_CMD0_PSC3_TX
+#define DBDMA_I2S_RX_CHAN	AU1550_DSCR_CMD0_PSC3_RX
 
-#define SPI_PSC_BASE		PSC0_BASE_ADDR
-#define AC97_PSC_BASE		PSC1_BASE_ADDR
-#define SMBUS_PSC_BASE		PSC2_BASE_ADDR
-#define I2S_PSC_BASE		PSC3_BASE_ADDR
+#define SPI_PSC_BASE		AU1550_PSC0_PHYS_ADDR
+#define AC97_PSC_BASE		AU1550_PSC1_PHYS_ADDR
+#define SMBUS_PSC_BASE		AU1550_PSC2_PHYS_ADDR
+#define I2S_PSC_BASE		AU1550_PSC3_PHYS_ADDR
 
 /*
  * Timing values as described in databook, * ns value stripped of
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/mipsprom.h linux-libre-3.2-gnu/arch/mips/include/asm/mipsprom.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/mipsprom.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/mipsprom.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
-#ifndef __ASM_MIPS_PROM_H
-#define __ASM_MIPS_PROM_H
+#ifndef __ASM_MIPSPROM_H
+#define __ASM_MIPSPROM_H
 
 #define PROM_RESET		0
 #define PROM_EXEC		1
@@ -73,4 +73,4 @@
 
 extern char *prom_getenv(char *);
 
-#endif /* __ASM_MIPS_PROM_H */
+#endif /* __ASM_MIPSPROM_H */
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/mipsregs.h linux-libre-3.2-gnu/arch/mips/include/asm/mipsregs.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/mipsregs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/mipsregs.h	2012-01-04 18:55:44.000000000 -0500
@@ -1006,18 +1006,26 @@
 #define write_c0_perfctrl0(val)	__write_32bit_c0_register($25, 0, val)
 #define read_c0_perfcntr0()	__read_32bit_c0_register($25, 1)
 #define write_c0_perfcntr0(val)	__write_32bit_c0_register($25, 1, val)
+#define read_c0_perfcntr0_64()	__read_64bit_c0_register($25, 1)
+#define write_c0_perfcntr0_64(val) __write_64bit_c0_register($25, 1, val)
 #define read_c0_perfctrl1()	__read_32bit_c0_register($25, 2)
 #define write_c0_perfctrl1(val)	__write_32bit_c0_register($25, 2, val)
 #define read_c0_perfcntr1()	__read_32bit_c0_register($25, 3)
 #define write_c0_perfcntr1(val)	__write_32bit_c0_register($25, 3, val)
+#define read_c0_perfcntr1_64()	__read_64bit_c0_register($25, 3)
+#define write_c0_perfcntr1_64(val) __write_64bit_c0_register($25, 3, val)
 #define read_c0_perfctrl2()	__read_32bit_c0_register($25, 4)
 #define write_c0_perfctrl2(val)	__write_32bit_c0_register($25, 4, val)
 #define read_c0_perfcntr2()	__read_32bit_c0_register($25, 5)
 #define write_c0_perfcntr2(val)	__write_32bit_c0_register($25, 5, val)
+#define read_c0_perfcntr2_64()	__read_64bit_c0_register($25, 5)
+#define write_c0_perfcntr2_64(val) __write_64bit_c0_register($25, 5, val)
 #define read_c0_perfctrl3()	__read_32bit_c0_register($25, 6)
 #define write_c0_perfctrl3(val)	__write_32bit_c0_register($25, 6, val)
 #define read_c0_perfcntr3()	__read_32bit_c0_register($25, 7)
 #define write_c0_perfcntr3(val)	__write_32bit_c0_register($25, 7, val)
+#define read_c0_perfcntr3_64()	__read_64bit_c0_register($25, 7)
+#define write_c0_perfcntr3_64(val) __write_64bit_c0_register($25, 7, val)
 
 /* RM9000 PerfCount performance counter register */
 #define read_c0_perfcount()	__read_64bit_c0_register($25, 0)
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/prom.h linux-libre-3.2-gnu/arch/mips/include/asm/prom.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/prom.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/prom.h	2012-01-04 18:55:44.000000000 -0500
@@ -8,8 +8,8 @@
  * published by the Free Software Foundation.
  *
  */
-#ifndef __ASM_MIPS_PROM_H
-#define __ASM_MIPS_PROM_H
+#ifndef __ASM_PROM_H
+#define __ASM_PROM_H
 
 #ifdef CONFIG_OF
 #include <asm/bootinfo.h>
@@ -25,4 +25,4 @@
 static inline void device_tree_init(void) { }
 #endif /* CONFIG_OF */
 
-#endif /* _ASM_MIPS_PROM_H */
+#endif /* __ASM_PROM_H */
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/regdef.h linux-libre-3.2-gnu/arch/mips/include/asm/regdef.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/regdef.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/regdef.h	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,8 @@
  * Copyright (C) 1985 MIPS Computer Systems, Inc.
  * Copyright (C) 1994, 95, 99, 2003 by Ralf Baechle
  * Copyright (C) 1990 - 1992, 1999 Silicon Graphics, Inc.
+ * Copyright (C) 2011 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
  */
 #ifndef _ASM_REGDEF_H
 #define _ASM_REGDEF_H
@@ -30,9 +32,13 @@
 #define t2      $10
 #define t3      $11
 #define t4      $12
+#define ta0	$12
 #define t5      $13
+#define ta1	$13
 #define t6      $14
+#define ta2	$14
 #define t7      $15
+#define ta3	$15
 #define s0      $16     /* callee saved */
 #define s1      $17
 #define s2      $18
diff -druN linux-libre-3.1-gnu/arch/mips/include/asm/unistd.h linux-libre-3.2-gnu/arch/mips/include/asm/unistd.h
--- linux-libre-3.1-gnu/arch/mips/include/asm/unistd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -365,16 +365,18 @@
 #define __NR_syncfs			(__NR_Linux + 342)
 #define __NR_sendmmsg			(__NR_Linux + 343)
 #define __NR_setns			(__NR_Linux + 344)
+#define __NR_process_vm_readv		(__NR_Linux + 345)
+#define __NR_process_vm_writev		(__NR_Linux + 346)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls		344
+#define __NR_Linux_syscalls		346
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux			4000
-#define __NR_O32_Linux_syscalls		344
+#define __NR_O32_Linux_syscalls		346
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
@@ -686,16 +688,18 @@
 #define __NR_syncfs			(__NR_Linux + 301)
 #define __NR_sendmmsg			(__NR_Linux + 302)
 #define __NR_setns			(__NR_Linux + 303)
+#define __NR_process_vm_readv		(__NR_Linux + 304)
+#define __NR_process_vm_writev		(__NR_Linux + 305)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls		303
+#define __NR_Linux_syscalls		305
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux			5000
-#define __NR_64_Linux_syscalls		303
+#define __NR_64_Linux_syscalls		305
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
@@ -1012,16 +1016,18 @@
 #define __NR_syncfs			(__NR_Linux + 306)
 #define __NR_sendmmsg			(__NR_Linux + 307)
 #define __NR_setns			(__NR_Linux + 308)
+#define __NR_process_vm_readv		(__NR_Linux + 309)
+#define __NR_process_vm_writev		(__NR_Linux + 310)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls		308
+#define __NR_Linux_syscalls		310
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux			6000
-#define __NR_N32_Linux_syscalls		308
+#define __NR_N32_Linux_syscalls		310
 
 #ifdef __KERNEL__
 
diff -druN linux-libre-3.1-gnu/arch/mips/jz4740/gpio.c linux-libre-3.2-gnu/arch/mips/jz4740/gpio.c
--- linux-libre-3.1-gnu/arch/mips/jz4740/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/jz4740/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,8 +17,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-#include <linux/spinlock.h>
-#include <linux/syscore_ops.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
@@ -30,6 +28,8 @@
 
 #include <asm/mach-jz4740/base.h>
 
+#include "irq.h"
+
 #define JZ4740_GPIO_BASE_A (32*0)
 #define JZ4740_GPIO_BASE_B (32*1)
 #define JZ4740_GPIO_BASE_C (32*2)
@@ -77,14 +77,10 @@
 struct jz_gpio_chip {
 	unsigned int irq;
 	unsigned int irq_base;
-	uint32_t wakeup;
-	uint32_t suspend_mask;
 	uint32_t edge_trigger_both;
 
 	void __iomem *base;
 
-	spinlock_t lock;
-
 	struct gpio_chip gpio_chip;
 };
 
@@ -102,7 +98,8 @@
 
 static inline struct jz_gpio_chip *irq_to_jz_gpio_chip(struct irq_data *data)
 {
-	return irq_data_get_irq_chip_data(data);
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
+	return gc->private;
 }
 
 static inline void jz_gpio_write_bit(unsigned int gpio, unsigned int reg)
@@ -304,21 +301,15 @@
 {
 	uint32_t flag;
 	unsigned int gpio_irq;
-	unsigned int gpio_bank;
 	struct jz_gpio_chip *chip = irq_desc_get_handler_data(desc);
 
-	gpio_bank = JZ4740_IRQ_GPIO0 - irq;
-
 	flag = readl(chip->base + JZ_REG_GPIO_FLAG);
-
 	if (!flag)
 		return;
 
-	gpio_irq = __fls(flag);
-
-	jz_gpio_check_trigger_both(chip, irq);
+	gpio_irq = chip->irq_base + __fls(flag);
 
-	gpio_irq += (gpio_bank << 5) + JZ4740_IRQ_GPIO(0);
+	jz_gpio_check_trigger_both(chip, gpio_irq);
 
 	generic_handle_irq(gpio_irq);
 };
@@ -329,18 +320,12 @@
 	writel(IRQ_TO_BIT(data->irq), chip->base + reg);
 }
 
-static void jz_gpio_irq_mask(struct irq_data *data)
-{
-	jz_gpio_set_irq_bit(data, JZ_REG_GPIO_MASK_SET);
-};
-
 static void jz_gpio_irq_unmask(struct irq_data *data)
 {
 	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data);
 
 	jz_gpio_check_trigger_both(chip, data->irq);
-
-	jz_gpio_set_irq_bit(data, JZ_REG_GPIO_MASK_CLEAR);
+	irq_gc_unmask_enable_reg(data);
 };
 
 /* TODO: Check if function is gpio */
@@ -353,18 +338,13 @@
 
 static void jz_gpio_irq_shutdown(struct irq_data *data)
 {
-	jz_gpio_irq_mask(data);
+	irq_gc_mask_disable_reg(data);
 
 	/* Set direction to input */
 	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(struct irq_data *data)
-{
-	jz_gpio_set_irq_bit(data, JZ_REG_GPIO_FLAG_CLEAR);
-};
-
 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(data);
@@ -408,35 +388,13 @@
 static int jz_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
 {
 	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data);
-	spin_lock(&chip->lock);
-	if (on)
-		chip->wakeup |= IRQ_TO_BIT(data->irq);
-	else
-		chip->wakeup &= ~IRQ_TO_BIT(data->irq);
-	spin_unlock(&chip->lock);
 
+	irq_gc_set_wake(data, 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.
- */
-static struct lock_class_key gpio_lock_class;
-
 #define JZ4740_GPIO_CHIP(_bank) { \
 	.irq_base = JZ4740_IRQ_GPIO_BASE_ ## _bank, \
 	.gpio_chip = { \
@@ -458,64 +416,44 @@
 	JZ4740_GPIO_CHIP(D),
 };
 
-static void jz4740_gpio_suspend_chip(struct jz_gpio_chip *chip)
-{
-	chip->suspend_mask = readl(chip->base + JZ_REG_GPIO_MASK);
-	writel(~(chip->wakeup), chip->base + JZ_REG_GPIO_MASK_SET);
-	writel(chip->wakeup, chip->base + JZ_REG_GPIO_MASK_CLEAR);
-}
-
-static int jz4740_gpio_suspend(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); i++)
-		jz4740_gpio_suspend_chip(&jz4740_gpio_chips[i]);
-
-	return 0;
-}
-
-static void jz4740_gpio_resume_chip(struct jz_gpio_chip *chip)
+static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id)
 {
-	uint32_t mask = chip->suspend_mask;
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
 
-	writel(~mask, chip->base + JZ_REG_GPIO_MASK_CLEAR);
-	writel(mask, chip->base + JZ_REG_GPIO_MASK_SET);
-}
+	chip->base = ioremap(JZ4740_GPIO_BASE_ADDR + (id * 0x100), 0x100);
 
-static void jz4740_gpio_resume(void)
-{
-	int i;
+	chip->irq = JZ4740_IRQ_INTC_GPIO(id);
+	irq_set_handler_data(chip->irq, chip);
+	irq_set_chained_handler(chip->irq, jz_gpio_irq_demux_handler);
 
-	for (i = ARRAY_SIZE(jz4740_gpio_chips) - 1; i >= 0 ; i--)
-		jz4740_gpio_resume_chip(&jz4740_gpio_chips[i]);
-}
+	gc = irq_alloc_generic_chip(chip->gpio_chip.label, 1, chip->irq_base,
+		chip->base, handle_level_irq);
 
-static struct syscore_ops jz4740_gpio_syscore_ops = {
-	.suspend = jz4740_gpio_suspend,
-	.resume = jz4740_gpio_resume,
-};
+	gc->wake_enabled = IRQ_MSK(chip->gpio_chip.ngpio);
+	gc->private = chip;
 
-static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id)
-{
-	int irq;
+	ct = gc->chip_types;
+	ct->regs.enable = JZ_REG_GPIO_MASK_CLEAR;
+	ct->regs.disable = JZ_REG_GPIO_MASK_SET;
+	ct->regs.ack = JZ_REG_GPIO_FLAG_CLEAR;
 
-	spin_lock_init(&chip->lock);
+	ct->chip.name = "GPIO";
+	ct->chip.irq_mask = irq_gc_mask_disable_reg;
+	ct->chip.irq_unmask = jz_gpio_irq_unmask;
+	ct->chip.irq_ack = irq_gc_ack_set_bit;
+	ct->chip.irq_suspend = jz4740_irq_suspend;
+	ct->chip.irq_resume = jz4740_irq_resume;
+	ct->chip.irq_startup = jz_gpio_irq_startup;
+	ct->chip.irq_shutdown = jz_gpio_irq_shutdown;
+	ct->chip.irq_set_type = jz_gpio_irq_set_type;
+	ct->chip.irq_set_wake = jz_gpio_irq_set_wake;
+	ct->chip.flags = IRQCHIP_SET_TYPE_MASKED;
 
-	chip->base = ioremap(JZ4740_GPIO_BASE_ADDR + (id * 0x100), 0x100);
+	irq_setup_generic_chip(gc, IRQ_MSK(chip->gpio_chip.ngpio),
+		IRQ_GC_INIT_NESTED_LOCK, 0, IRQ_NOPROBE | IRQ_LEVEL);
 
 	gpiochip_add(&chip->gpio_chip);
-
-	chip->irq = JZ4740_IRQ_INTC_GPIO(id);
-	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) {
-		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);
-	}
 }
 
 static int __init jz4740_gpio_init(void)
@@ -525,8 +463,6 @@
 	for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i)
 		jz4740_gpio_chip_init(&jz4740_gpio_chips[i], i);
 
-	register_syscore_ops(&jz4740_gpio_syscore_ops);
-
 	printk(KERN_INFO "JZ4740 GPIO initialized\n");
 
 	return 0;
diff -druN linux-libre-3.1-gnu/arch/mips/jz4740/irq.c linux-libre-3.2-gnu/arch/mips/jz4740/irq.c
--- linux-libre-3.1-gnu/arch/mips/jz4740/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/jz4740/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,8 +32,6 @@
 #include <asm/mach-jz4740/base.h>
 
 static void __iomem *jz_intc_base;
-static uint32_t jz_intc_wakeup;
-static uint32_t jz_intc_saved;
 
 #define JZ_REG_INTC_STATUS	0x00
 #define JZ_REG_INTC_MASK	0x04
@@ -41,51 +39,36 @@
 #define JZ_REG_INTC_CLEAR_MASK	0x0c
 #define JZ_REG_INTC_PENDING	0x10
 
-#define IRQ_BIT(x) BIT((x) - JZ4740_IRQ_BASE)
-
-static inline unsigned long intc_irq_bit(struct irq_data *data)
+static irqreturn_t jz4740_cascade(int irq, void *data)
 {
-	return (unsigned long)irq_data_get_irq_chip_data(data);
-}
+	uint32_t irq_reg;
 
-static void intc_irq_unmask(struct irq_data *data)
-{
-	writel(intc_irq_bit(data), jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
-}
+	irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING);
 
-static void intc_irq_mask(struct irq_data *data)
-{
-	writel(intc_irq_bit(data), jz_intc_base + JZ_REG_INTC_SET_MASK);
+	if (irq_reg)
+		generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE);
+
+	return IRQ_HANDLED;
 }
 
-static int intc_irq_set_wake(struct irq_data *data, unsigned int on)
+static void jz4740_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask)
 {
-	if (on)
-		jz_intc_wakeup |= intc_irq_bit(data);
-	else
-		jz_intc_wakeup &= ~intc_irq_bit(data);
+	struct irq_chip_regs *regs = &gc->chip_types->regs;
 
-	return 0;
+	writel(mask, gc->reg_base + regs->enable);
+	writel(~mask, gc->reg_base + regs->disable);
 }
 
-static struct irq_chip intc_irq_type = {
-	.name =		"INTC",
-	.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)
+void jz4740_irq_suspend(struct irq_data *data)
 {
-	uint32_t irq_reg;
-
-	irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING);
-
-	if (irq_reg)
-		generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE);
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
+	jz4740_irq_set_mask(gc, gc->wake_active);
+}
 
-	return IRQ_HANDLED;
+void jz4740_irq_resume(struct irq_data *data)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
+	jz4740_irq_set_mask(gc, gc->mask_cache);
 }
 
 static struct irqaction jz4740_cascade_action = {
@@ -95,7 +78,9 @@
 
 void __init arch_init_irq(void)
 {
-	int i;
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+
 	mips_cpu_irq_init();
 
 	jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
@@ -103,10 +88,22 @@
 	/* Mask all irqs */
 	writel(0xffffffff, jz_intc_base + JZ_REG_INTC_SET_MASK);
 
-	for (i = JZ4740_IRQ_BASE; i < JZ4740_IRQ_BASE + 32; i++) {
-		irq_set_chip_data(i, (void *)IRQ_BIT(i));
-		irq_set_chip_and_handler(i, &intc_irq_type, handle_level_irq);
-	}
+	gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE, jz_intc_base,
+		handle_level_irq);
+
+	gc->wake_enabled = IRQ_MSK(32);
+
+	ct = gc->chip_types;
+	ct->regs.enable = JZ_REG_INTC_CLEAR_MASK;
+	ct->regs.disable = JZ_REG_INTC_SET_MASK;
+	ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
+	ct->chip.irq_mask = irq_gc_mask_disable_reg;
+	ct->chip.irq_mask_ack = irq_gc_mask_disable_reg;
+	ct->chip.irq_set_wake = irq_gc_set_wake;
+	ct->chip.irq_suspend = jz4740_irq_suspend;
+	ct->chip.irq_resume = jz4740_irq_resume;
+
+	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, IRQ_NOPROBE | IRQ_LEVEL);
 
 	setup_irq(2, &jz4740_cascade_action);
 }
@@ -122,19 +119,6 @@
 		spurious_interrupt();
 }
 
-void jz4740_intc_suspend(void)
-{
-	jz_intc_saved = readl(jz_intc_base + JZ_REG_INTC_MASK);
-	writel(~jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_SET_MASK);
-	writel(jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
-}
-
-void jz4740_intc_resume(void)
-{
-	writel(~jz_intc_saved, jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
-	writel(jz_intc_saved, jz_intc_base + JZ_REG_INTC_SET_MASK);
-}
-
 #ifdef CONFIG_DEBUG_FS
 
 static inline void intc_seq_reg(struct seq_file *s, const char *name,
diff -druN linux-libre-3.1-gnu/arch/mips/jz4740/irq.h linux-libre-3.2-gnu/arch/mips/jz4740/irq.h
--- linux-libre-3.1-gnu/arch/mips/jz4740/irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/jz4740/irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,9 @@
 #ifndef __MIPS_JZ4740_IRQ_H__
 #define __MIPS_JZ4740_IRQ_H__
 
-extern void jz4740_intc_suspend(void);
-extern void jz4740_intc_resume(void);
+#include <linux/irq.h>
+
+extern void jz4740_irq_suspend(struct irq_data *data);
+extern void jz4740_irq_resume(struct irq_data *data);
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/mips/jz4740/pm.c linux-libre-3.2-gnu/arch/mips/jz4740/pm.c
--- linux-libre-3.1-gnu/arch/mips/jz4740/pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/jz4740/pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,11 +21,9 @@
 #include <asm/mach-jz4740/clock.h>
 
 #include "clock.h"
-#include "irq.h"
 
 static int jz4740_pm_enter(suspend_state_t state)
 {
-	jz4740_intc_suspend();
 	jz4740_clock_suspend();
 
 	jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_SLEEP);
@@ -37,7 +35,6 @@
 	jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_IDLE);
 
 	jz4740_clock_resume();
-	jz4740_intc_resume();
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/arch/mips/Kconfig linux-libre-3.2-gnu/arch/mips/Kconfig
--- linux-libre-3.1-gnu/arch/mips/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,8 @@
 	select GENERIC_GPIO
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select SYS_SUPPORTS_ZBOOT
+	select USB_ARCH_HAS_OHCI
+	select USB_ARCH_HAS_EHCI
 
 config AR7
 	bool "Texas Instruments AR7"
@@ -92,15 +94,8 @@
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select IRQ_CPU
-	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
-	select SSB
-	select SSB_DRIVER_MIPS
-	select SSB_DRIVER_EXTIF
-	select SSB_EMBEDDED
-	select SSB_B43_PCI_BRIDGE if PCI
-	select SSB_PCICORE_HOSTMODE if PCI
 	select GENERIC_GPIO
 	select SYS_HAS_EARLY_PRINTK
 	select CFE
@@ -213,6 +208,7 @@
 	select SYS_HAS_EARLY_PRINTK
 	select HAVE_PWM
 	select HAVE_CLK
+	select GENERIC_IRQ_CHIP
 
 config LANTIQ
 	bool "Lantiq based platforms"
@@ -791,6 +787,7 @@
 
 source "arch/mips/alchemy/Kconfig"
 source "arch/mips/ath79/Kconfig"
+source "arch/mips/bcm47xx/Kconfig"
 source "arch/mips/bcm63xx/Kconfig"
 source "arch/mips/jazz/Kconfig"
 source "arch/mips/jz4740/Kconfig"
@@ -823,10 +820,6 @@
 	bool
 	default n
 
-config ARCH_SUPPORTS_OPROFILE
-	bool
-	default y if !MIPS_MT_SMTC
-
 config GENERIC_HWEIGHT
 	bool
 	default y
@@ -2098,7 +2091,7 @@
 
 config HW_PERF_EVENTS
 	bool "Enable hardware performance counter support for perf events"
-	depends on PERF_EVENTS && !MIPS_MT_SMTC && OPROFILE=n && CPU_MIPS32
+	depends on PERF_EVENTS && !MIPS_MT_SMTC && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON)
 	default y
 	help
 	  Enable hardware performance counter support for perf events. If
@@ -2258,16 +2251,6 @@
 
 source "kernel/Kconfig.preempt"
 
-config MIPS_INSANE_LARGE
-	bool "Support for large 64-bit configurations"
-	depends on CPU_R10000 && 64BIT
-	help
-	  MIPS R10000 does support a 44 bit / 16TB address space as opposed to
-	  previous 64-bit processors which only supported 40 bit / 1TB. If you
-	  need processes of more than 1TB virtual address space, say Y here.
-	  This will result in additional memory usage, so it is not
-	  recommended for normal users.
-
 config KEXEC
 	bool "Kexec system call (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/8250-platform.c linux-libre-3.2-gnu/arch/mips/kernel/8250-platform.c
--- linux-libre-3.1-gnu/arch/mips/kernel/8250-platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/8250-platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,6 @@
  *
  * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
  */
-#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/serial_8250.h>
 
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/cevt-r4k.c linux-libre-3.2-gnu/arch/mips/kernel/cevt-r4k.c
--- linux-libre-3.1-gnu/arch/mips/kernel/cevt-r4k.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/cevt-r4k.c	2012-01-04 18:55:44.000000000 -0500
@@ -103,19 +103,10 @@
 
 /*
  * Compare interrupt can be routed and latched outside the core,
- * so a single execution hazard barrier may not be enough to give
- * it time to clear as seen in the Cause register.  4 time the
- * pipeline depth seems reasonably conservative, and empirically
- * works better in configurations with high CPU/bus clock ratios.
+ * so wait up to worst case number of cycle counter ticks for timer interrupt
+ * changes to propagate to the cause register.
  */
-
-#define compare_change_hazard() \
-	do { \
-		irq_disable_hazard(); \
-		irq_disable_hazard(); \
-		irq_disable_hazard(); \
-		irq_disable_hazard(); \
-	} while (0)
+#define COMPARE_INT_SEEN_TICKS 50
 
 int c0_compare_int_usable(void)
 {
@@ -126,8 +117,12 @@
 	 * IP7 already pending?  Try to clear it by acking the timer.
 	 */
 	if (c0_compare_int_pending()) {
-		write_c0_compare(read_c0_count());
-		compare_change_hazard();
+		cnt = read_c0_count();
+		write_c0_compare(cnt);
+		back_to_back_c0_hazard();
+		while (read_c0_count() < (cnt  + COMPARE_INT_SEEN_TICKS))
+			if (!c0_compare_int_pending())
+				break;
 		if (c0_compare_int_pending())
 			return 0;
 	}
@@ -136,7 +131,7 @@
 		cnt = read_c0_count();
 		cnt += delta;
 		write_c0_compare(cnt);
-		compare_change_hazard();
+		back_to_back_c0_hazard();
 		if ((int)(read_c0_count() - cnt) < 0)
 		    break;
 		/* increase delta if the timer was already expired */
@@ -145,12 +140,17 @@
 	while ((int)(read_c0_count() - cnt) <= 0)
 		;	/* Wait for expiry  */
 
-	compare_change_hazard();
+	while (read_c0_count() < (cnt + COMPARE_INT_SEEN_TICKS))
+		if (c0_compare_int_pending())
+			break;
 	if (!c0_compare_int_pending())
 		return 0;
-
-	write_c0_compare(read_c0_count());
-	compare_change_hazard();
+	cnt = read_c0_count();
+	write_c0_compare(cnt);
+	back_to_back_c0_hazard();
+	while (read_c0_count() < (cnt + COMPARE_INT_SEEN_TICKS))
+		if (!c0_compare_int_pending())
+			break;
 	if (c0_compare_int_pending())
 		return 0;
 
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/cpufreq/loongson2_clock.c linux-libre-3.2-gnu/arch/mips/kernel/cpufreq/loongson2_clock.c
--- linux-libre-3.1-gnu/arch/mips/kernel/cpufreq/loongson2_clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/cpufreq/loongson2_clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  * for more details.
  */
 
+#include <linux/module.h>
 #include <linux/cpufreq.h>
 #include <linux/platform_device.h>
 
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/cpu-probe.c linux-libre-3.2-gnu/arch/mips/kernel/cpu-probe.c
--- linux-libre-3.1-gnu/arch/mips/kernel/cpu-probe.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/cpu-probe.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/ptrace.h>
 #include <linux/smp.h>
 #include <linux/stddef.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/bugs.h>
 #include <asm/cpu.h>
@@ -24,6 +24,7 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 #include <asm/watch.h>
+#include <asm/elf.h>
 #include <asm/spram.h>
 #include <asm/uaccess.h>
 
@@ -978,7 +979,10 @@
 platform:
 		set_elf_platform(cpu, "octeon");
 		break;
+	case PRID_IMP_CAVIUM_CN61XX:
 	case PRID_IMP_CAVIUM_CN63XX:
+	case PRID_IMP_CAVIUM_CN66XX:
+	case PRID_IMP_CAVIUM_CN68XX:
 		c->cputype = CPU_CAVIUM_OCTEON2;
 		__cpu_name[cpu] = "Cavium Octeon II";
 		set_elf_platform(cpu, "octeon2");
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/i8253.c linux-libre-3.2-gnu/arch/mips/kernel/i8253.c
--- linux-libre-3.1-gnu/arch/mips/kernel/i8253.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/i8253.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
  */
 #include <linux/clockchips.h>
 #include <linux/i8253.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/smp.h>
 #include <linux/irq.h>
 
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/init_task.c linux-libre-3.2-gnu/arch/mips/kernel/init_task.c
--- linux-libre-3.1-gnu/arch/mips/kernel/init_task.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/init_task.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 #include <linux/mm.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/init_task.h>
 #include <linux/fs.h>
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/irq.c linux-libre-3.2-gnu/arch/mips/kernel/irq.c
--- linux-libre-3.1-gnu/arch/mips/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
-#include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/mm.h>
 #include <linux/random.h>
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/irq-msc01.c linux-libre-3.2-gnu/arch/mips/kernel/irq-msc01.c
--- linux-libre-3.1-gnu/arch/mips/kernel/irq-msc01.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/irq-msc01.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@
  *
  * Copyright (C) 2004, 06 Ralf Baechle <ralf@linux-mips.org>
  */
-#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/Makefile linux-libre-3.2-gnu/arch/mips/kernel/Makefile
--- linux-libre-3.1-gnu/arch/mips/kernel/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,8 @@
 ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_early_printk.o = -pg
+CFLAGS_REMOVE_perf_event.o = -pg
+CFLAGS_REMOVE_perf_event_mipsxx.o = -pg
 endif
 
 obj-$(CONFIG_CEVT_BCM1480)	+= cevt-bcm1480.o
@@ -106,7 +108,8 @@
 
 obj-$(CONFIG_MIPS_CPUFREQ)	+= cpufreq/
 
-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
+obj-$(CONFIG_PERF_EVENTS)	+= perf_event.o
+obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event_mipsxx.o
 
 obj-$(CONFIG_JUMP_LABEL)	+= jump_label.o
 
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/mips_ksyms.c linux-libre-3.2-gnu/arch/mips/kernel/mips_ksyms.c
--- linux-libre-3.1-gnu/arch/mips/kernel/mips_ksyms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/mips_ksyms.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
  * Copyright (C) 1999, 2000, 01 Silicon Graphics, Inc.
  */
 #include <linux/interrupt.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/checksum.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/mips-mt.c linux-libre-3.2-gnu/arch/mips/kernel/mips-mt.c
--- linux-libre-3.1-gnu/arch/mips/kernel/mips-mt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/mips-mt.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/security.h>
 
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/module.c linux-libre-3.2-gnu/arch/mips/kernel/module.c
--- linux-libre-3.1-gnu/arch/mips/kernel/module.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/module.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,6 @@
 #include <linux/fs.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/jump_label.h>
 
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/perf_event.c linux-libre-3.2-gnu/arch/mips/kernel/perf_event.c
--- linux-libre-3.1-gnu/arch/mips/kernel/perf_event.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/perf_event.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,533 +14,16 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/cpumask.h>
-#include <linux/interrupt.h>
-#include <linux/smp.h>
-#include <linux/kernel.h>
 #include <linux/perf_event.h>
-#include <linux/uaccess.h>
 
-#include <asm/irq.h>
-#include <asm/irq_regs.h>
 #include <asm/stacktrace.h>
-#include <asm/time.h> /* For perf_irq */
-
-/* These are for 32bit counters. For 64bit ones, define them accordingly. */
-#define MAX_PERIOD	((1ULL << 32) - 1)
-#define VALID_COUNT	0x7fffffff
-#define TOTAL_BITS	32
-#define HIGHEST_BIT	31
-
-#define MIPS_MAX_HWEVENTS 4
-
-struct cpu_hw_events {
-	/* Array of events on this cpu. */
-	struct perf_event	*events[MIPS_MAX_HWEVENTS];
-
-	/*
-	 * Set the bit (indexed by the counter number) when the counter
-	 * is used for an event.
-	 */
-	unsigned long		used_mask[BITS_TO_LONGS(MIPS_MAX_HWEVENTS)];
-
-	/*
-	 * The borrowed MSB for the performance counter. A MIPS performance
-	 * counter uses its bit 31 (for 32bit counters) or bit 63 (for 64bit
-	 * counters) as a factor of determining whether a counter overflow
-	 * should be signaled. So here we use a separate MSB for each
-	 * counter to make things easy.
-	 */
-	unsigned long		msbs[BITS_TO_LONGS(MIPS_MAX_HWEVENTS)];
-
-	/*
-	 * Software copy of the control register for each performance counter.
-	 * MIPS CPUs vary in performance counters. They use this differently,
-	 * and even may not use it.
-	 */
-	unsigned int		saved_ctrl[MIPS_MAX_HWEVENTS];
-};
-DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
-	.saved_ctrl = {0},
-};
-
-/* The description of MIPS performance events. */
-struct mips_perf_event {
-	unsigned int event_id;
-	/*
-	 * MIPS performance counters are indexed starting from 0.
-	 * CNTR_EVEN indicates the indexes of the counters to be used are
-	 * even numbers.
-	 */
-	unsigned int cntr_mask;
-	#define CNTR_EVEN	0x55555555
-	#define CNTR_ODD	0xaaaaaaaa
-#ifdef CONFIG_MIPS_MT_SMP
-	enum {
-		T  = 0,
-		V  = 1,
-		P  = 2,
-	} range;
-#else
-	#define T
-	#define V
-	#define P
-#endif
-};
-
-static struct mips_perf_event raw_event;
-static DEFINE_MUTEX(raw_event_mutex);
-
-#define UNSUPPORTED_PERF_EVENT_ID 0xffffffff
-#define C(x) PERF_COUNT_HW_CACHE_##x
-
-struct mips_pmu {
-	const char	*name;
-	int		irq;
-	irqreturn_t	(*handle_irq)(int irq, void *dev);
-	int		(*handle_shared_irq)(void);
-	void		(*start)(void);
-	void		(*stop)(void);
-	int		(*alloc_counter)(struct cpu_hw_events *cpuc,
-					struct hw_perf_event *hwc);
-	u64		(*read_counter)(unsigned int idx);
-	void		(*write_counter)(unsigned int idx, u64 val);
-	void		(*enable_event)(struct hw_perf_event *evt, int idx);
-	void		(*disable_event)(int idx);
-	const struct mips_perf_event *(*map_raw_event)(u64 config);
-	const struct mips_perf_event (*general_event_map)[PERF_COUNT_HW_MAX];
-	const struct mips_perf_event (*cache_event_map)
-				[PERF_COUNT_HW_CACHE_MAX]
-				[PERF_COUNT_HW_CACHE_OP_MAX]
-				[PERF_COUNT_HW_CACHE_RESULT_MAX];
-	unsigned int	num_counters;
-};
-
-static const struct mips_pmu *mipspmu;
-
-static int
-mipspmu_event_set_period(struct perf_event *event,
-			struct hw_perf_event *hwc,
-			int idx)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	s64 left = local64_read(&hwc->period_left);
-	s64 period = hwc->sample_period;
-	int ret = 0;
-	u64 uleft;
-	unsigned long flags;
-
-	if (unlikely(left <= -period)) {
-		left = period;
-		local64_set(&hwc->period_left, left);
-		hwc->last_period = period;
-		ret = 1;
-	}
-
-	if (unlikely(left <= 0)) {
-		left += period;
-		local64_set(&hwc->period_left, left);
-		hwc->last_period = period;
-		ret = 1;
-	}
-
-	if (left > (s64)MAX_PERIOD)
-		left = MAX_PERIOD;
-
-	local64_set(&hwc->prev_count, (u64)-left);
-
-	local_irq_save(flags);
-	uleft = (u64)(-left) & MAX_PERIOD;
-	uleft > VALID_COUNT ?
-		set_bit(idx, cpuc->msbs) : clear_bit(idx, cpuc->msbs);
-	mipspmu->write_counter(idx, (u64)(-left) & VALID_COUNT);
-	local_irq_restore(flags);
-
-	perf_event_update_userpage(event);
-
-	return ret;
-}
-
-static void mipspmu_event_update(struct perf_event *event,
-			struct hw_perf_event *hwc,
-			int idx)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	unsigned long flags;
-	int shift = 64 - TOTAL_BITS;
-	s64 prev_raw_count, new_raw_count;
-	u64 delta;
-
-again:
-	prev_raw_count = local64_read(&hwc->prev_count);
-	local_irq_save(flags);
-	/* Make the counter value be a "real" one. */
-	new_raw_count = mipspmu->read_counter(idx);
-	if (new_raw_count & (test_bit(idx, cpuc->msbs) << HIGHEST_BIT)) {
-		new_raw_count &= VALID_COUNT;
-		clear_bit(idx, cpuc->msbs);
-	} else
-		new_raw_count |= (test_bit(idx, cpuc->msbs) << HIGHEST_BIT);
-	local_irq_restore(flags);
-
-	if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
-				new_raw_count) != prev_raw_count)
-		goto again;
-
-	delta = (new_raw_count << shift) - (prev_raw_count << shift);
-	delta >>= shift;
-
-	local64_add(delta, &event->count);
-	local64_sub(delta, &hwc->period_left);
-}
-
-static void mipspmu_start(struct perf_event *event, int flags)
-{
-	struct hw_perf_event *hwc = &event->hw;
-
-	if (!mipspmu)
-		return;
-
-	if (flags & PERF_EF_RELOAD)
-		WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
-
-	hwc->state = 0;
-
-	/* Set the period for the event. */
-	mipspmu_event_set_period(event, hwc, hwc->idx);
-
-	/* Enable the event. */
-	mipspmu->enable_event(hwc, hwc->idx);
-}
-
-static void mipspmu_stop(struct perf_event *event, int flags)
-{
-	struct hw_perf_event *hwc = &event->hw;
-
-	if (!mipspmu)
-		return;
-
-	if (!(hwc->state & PERF_HES_STOPPED)) {
-		/* We are working on a local event. */
-		mipspmu->disable_event(hwc->idx);
-		barrier();
-		mipspmu_event_update(event, hwc, hwc->idx);
-		hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
-	}
-}
-
-static int mipspmu_add(struct perf_event *event, int flags)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	struct hw_perf_event *hwc = &event->hw;
-	int idx;
-	int err = 0;
-
-	perf_pmu_disable(event->pmu);
-
-	/* To look for a free counter for this event. */
-	idx = mipspmu->alloc_counter(cpuc, hwc);
-	if (idx < 0) {
-		err = idx;
-		goto out;
-	}
-
-	/*
-	 * If there is an event in the counter we are going to use then
-	 * make sure it is disabled.
-	 */
-	event->hw.idx = idx;
-	mipspmu->disable_event(idx);
-	cpuc->events[idx] = event;
-
-	hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
-	if (flags & PERF_EF_START)
-		mipspmu_start(event, PERF_EF_RELOAD);
-
-	/* Propagate our changes to the userspace mapping. */
-	perf_event_update_userpage(event);
-
-out:
-	perf_pmu_enable(event->pmu);
-	return err;
-}
-
-static void mipspmu_del(struct perf_event *event, int flags)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	struct hw_perf_event *hwc = &event->hw;
-	int idx = hwc->idx;
-
-	WARN_ON(idx < 0 || idx >= mipspmu->num_counters);
-
-	mipspmu_stop(event, PERF_EF_UPDATE);
-	cpuc->events[idx] = NULL;
-	clear_bit(idx, cpuc->used_mask);
-
-	perf_event_update_userpage(event);
-}
-
-static void mipspmu_read(struct perf_event *event)
-{
-	struct hw_perf_event *hwc = &event->hw;
-
-	/* Don't read disabled counters! */
-	if (hwc->idx < 0)
-		return;
-
-	mipspmu_event_update(event, hwc, hwc->idx);
-}
-
-static void mipspmu_enable(struct pmu *pmu)
-{
-	if (mipspmu)
-		mipspmu->start();
-}
-
-static void mipspmu_disable(struct pmu *pmu)
-{
-	if (mipspmu)
-		mipspmu->stop();
-}
-
-static atomic_t active_events = ATOMIC_INIT(0);
-static DEFINE_MUTEX(pmu_reserve_mutex);
-static int (*save_perf_irq)(void);
-
-static int mipspmu_get_irq(void)
-{
-	int err;
-
-	if (mipspmu->irq >= 0) {
-		/* Request my own irq handler. */
-		err = request_irq(mipspmu->irq, mipspmu->handle_irq,
-			IRQF_DISABLED | IRQF_NOBALANCING,
-			"mips_perf_pmu", NULL);
-		if (err) {
-			pr_warning("Unable to request IRQ%d for MIPS "
-			   "performance counters!\n", mipspmu->irq);
-		}
-	} else if (cp0_perfcount_irq < 0) {
-		/*
-		 * We are sharing the irq number with the timer interrupt.
-		 */
-		save_perf_irq = perf_irq;
-		perf_irq = mipspmu->handle_shared_irq;
-		err = 0;
-	} else {
-		pr_warning("The platform hasn't properly defined its "
-			"interrupt controller.\n");
-		err = -ENOENT;
-	}
-
-	return err;
-}
-
-static void mipspmu_free_irq(void)
-{
-	if (mipspmu->irq >= 0)
-		free_irq(mipspmu->irq, NULL);
-	else if (cp0_perfcount_irq < 0)
-		perf_irq = save_perf_irq;
-}
-
-/*
- * mipsxx/rm9000/loongson2 have different performance counters, they have
- * specific low-level init routines.
- */
-static void reset_counters(void *arg);
-static int __hw_perf_event_init(struct perf_event *event);
-
-static void hw_perf_event_destroy(struct perf_event *event)
-{
-	if (atomic_dec_and_mutex_lock(&active_events,
-				&pmu_reserve_mutex)) {
-		/*
-		 * We must not call the destroy function with interrupts
-		 * disabled.
-		 */
-		on_each_cpu(reset_counters,
-			(void *)(long)mipspmu->num_counters, 1);
-		mipspmu_free_irq();
-		mutex_unlock(&pmu_reserve_mutex);
-	}
-}
-
-static int mipspmu_event_init(struct perf_event *event)
-{
-	int err = 0;
-
-	switch (event->attr.type) {
-	case PERF_TYPE_RAW:
-	case PERF_TYPE_HARDWARE:
-	case PERF_TYPE_HW_CACHE:
-		break;
-
-	default:
-		return -ENOENT;
-	}
-
-	if (!mipspmu || event->cpu >= nr_cpumask_bits ||
-		(event->cpu >= 0 && !cpu_online(event->cpu)))
-		return -ENODEV;
-
-	if (!atomic_inc_not_zero(&active_events)) {
-		if (atomic_read(&active_events) > MIPS_MAX_HWEVENTS) {
-			atomic_dec(&active_events);
-			return -ENOSPC;
-		}
-
-		mutex_lock(&pmu_reserve_mutex);
-		if (atomic_read(&active_events) == 0)
-			err = mipspmu_get_irq();
-
-		if (!err)
-			atomic_inc(&active_events);
-		mutex_unlock(&pmu_reserve_mutex);
-	}
-
-	if (err)
-		return err;
-
-	err = __hw_perf_event_init(event);
-	if (err)
-		hw_perf_event_destroy(event);
-
-	return err;
-}
-
-static struct pmu pmu = {
-	.pmu_enable	= mipspmu_enable,
-	.pmu_disable	= mipspmu_disable,
-	.event_init	= mipspmu_event_init,
-	.add		= mipspmu_add,
-	.del		= mipspmu_del,
-	.start		= mipspmu_start,
-	.stop		= mipspmu_stop,
-	.read		= mipspmu_read,
-};
-
-static inline unsigned int
-mipspmu_perf_event_encode(const struct mips_perf_event *pev)
-{
-/*
- * Top 8 bits for range, next 16 bits for cntr_mask, lowest 8 bits for
- * event_id.
- */
-#ifdef CONFIG_MIPS_MT_SMP
-	return ((unsigned int)pev->range << 24) |
-		(pev->cntr_mask & 0xffff00) |
-		(pev->event_id & 0xff);
-#else
-	return (pev->cntr_mask & 0xffff00) |
-		(pev->event_id & 0xff);
-#endif
-}
-
-static const struct mips_perf_event *
-mipspmu_map_general_event(int idx)
-{
-	const struct mips_perf_event *pev;
-
-	pev = ((*mipspmu->general_event_map)[idx].event_id ==
-		UNSUPPORTED_PERF_EVENT_ID ? ERR_PTR(-EOPNOTSUPP) :
-		&(*mipspmu->general_event_map)[idx]);
-
-	return pev;
-}
-
-static const struct mips_perf_event *
-mipspmu_map_cache_event(u64 config)
-{
-	unsigned int cache_type, cache_op, cache_result;
-	const struct mips_perf_event *pev;
-
-	cache_type = (config >> 0) & 0xff;
-	if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
-		return ERR_PTR(-EINVAL);
-
-	cache_op = (config >> 8) & 0xff;
-	if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
-		return ERR_PTR(-EINVAL);
-
-	cache_result = (config >> 16) & 0xff;
-	if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
-		return ERR_PTR(-EINVAL);
-
-	pev = &((*mipspmu->cache_event_map)
-					[cache_type]
-					[cache_op]
-					[cache_result]);
-
-	if (pev->event_id == UNSUPPORTED_PERF_EVENT_ID)
-		return ERR_PTR(-EOPNOTSUPP);
-
-	return pev;
-
-}
-
-static int validate_event(struct cpu_hw_events *cpuc,
-	       struct perf_event *event)
-{
-	struct hw_perf_event fake_hwc = event->hw;
-
-	/* Allow mixed event group. So return 1 to pass validation. */
-	if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF)
-		return 1;
-
-	return mipspmu->alloc_counter(cpuc, &fake_hwc) >= 0;
-}
-
-static int validate_group(struct perf_event *event)
-{
-	struct perf_event *sibling, *leader = event->group_leader;
-	struct cpu_hw_events fake_cpuc;
-
-	memset(&fake_cpuc, 0, sizeof(fake_cpuc));
-
-	if (!validate_event(&fake_cpuc, leader))
-		return -ENOSPC;
-
-	list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
-		if (!validate_event(&fake_cpuc, sibling))
-			return -ENOSPC;
-	}
-
-	if (!validate_event(&fake_cpuc, event))
-		return -ENOSPC;
-
-	return 0;
-}
-
-/* This is needed by specific irq handlers in perf_event_*.c */
-static void
-handle_associated_event(struct cpu_hw_events *cpuc,
-	int idx, struct perf_sample_data *data, struct pt_regs *regs)
-{
-	struct perf_event *event = cpuc->events[idx];
-	struct hw_perf_event *hwc = &event->hw;
-
-	mipspmu_event_update(event, hwc, idx);
-	data->period = event->hw.last_period;
-	if (!mipspmu_event_set_period(event, hwc, idx))
-		return;
-
-	if (perf_event_overflow(event, data, regs))
-		mipspmu->disable_event(idx);
-}
-
-#include "perf_event_mipsxx.c"
 
 /* Callchain handling code. */
 
 /*
  * Leave userspace callchain empty for now. When we find a way to trace
- * the user stack callchains, we add here.
+ * the user stack callchains, we will add it here.
  */
-void perf_callchain_user(struct perf_callchain_entry *entry,
-		    struct pt_regs *regs)
-{
-}
 
 static void save_raw_perf_callchain(struct perf_callchain_entry *entry,
 	unsigned long reg29)
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/perf_event_mipsxx.c linux-libre-3.2-gnu/arch/mips/kernel/perf_event_mipsxx.c
--- linux-libre-3.1-gnu/arch/mips/kernel/perf_event_mipsxx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/perf_event_mipsxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,13 +1,112 @@
-#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) || \
-    defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_SB1)
+/*
+ * Linux performance counter support for MIPS.
+ *
+ * Copyright (C) 2010 MIPS Technologies, Inc.
+ * Copyright (C) 2011 Cavium Networks, Inc.
+ * Author: Deng-Cheng Zhu
+ *
+ * This code is based on the implementation for ARM, which is in turn
+ * based on the sparc64 perf event code and the x86 code. Performance
+ * counter access is based on the MIPS Oprofile code. And the callchain
+ * support references the code of MIPS stacktrace.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/cpumask.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+#include <linux/kernel.h>
+#include <linux/perf_event.h>
+#include <linux/uaccess.h>
+
+#include <asm/irq.h>
+#include <asm/irq_regs.h>
+#include <asm/stacktrace.h>
+#include <asm/time.h> /* For perf_irq */
+
+#define MIPS_MAX_HWEVENTS 4
+
+struct cpu_hw_events {
+	/* Array of events on this cpu. */
+	struct perf_event	*events[MIPS_MAX_HWEVENTS];
+
+	/*
+	 * Set the bit (indexed by the counter number) when the counter
+	 * is used for an event.
+	 */
+	unsigned long		used_mask[BITS_TO_LONGS(MIPS_MAX_HWEVENTS)];
+
+	/*
+	 * Software copy of the control register for each performance counter.
+	 * MIPS CPUs vary in performance counters. They use this differently,
+	 * and even may not use it.
+	 */
+	unsigned int		saved_ctrl[MIPS_MAX_HWEVENTS];
+};
+DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
+	.saved_ctrl = {0},
+};
+
+/* The description of MIPS performance events. */
+struct mips_perf_event {
+	unsigned int event_id;
+	/*
+	 * MIPS performance counters are indexed starting from 0.
+	 * CNTR_EVEN indicates the indexes of the counters to be used are
+	 * even numbers.
+	 */
+	unsigned int cntr_mask;
+	#define CNTR_EVEN	0x55555555
+	#define CNTR_ODD	0xaaaaaaaa
+	#define CNTR_ALL	0xffffffff
+#ifdef CONFIG_MIPS_MT_SMP
+	enum {
+		T  = 0,
+		V  = 1,
+		P  = 2,
+	} range;
+#else
+	#define T
+	#define V
+	#define P
+#endif
+};
+
+static struct mips_perf_event raw_event;
+static DEFINE_MUTEX(raw_event_mutex);
+
+#define UNSUPPORTED_PERF_EVENT_ID 0xffffffff
+#define C(x) PERF_COUNT_HW_CACHE_##x
+
+struct mips_pmu {
+	u64		max_period;
+	u64		valid_count;
+	u64		overflow;
+	const char	*name;
+	int		irq;
+	u64		(*read_counter)(unsigned int idx);
+	void		(*write_counter)(unsigned int idx, u64 val);
+	const struct mips_perf_event *(*map_raw_event)(u64 config);
+	const struct mips_perf_event (*general_event_map)[PERF_COUNT_HW_MAX];
+	const struct mips_perf_event (*cache_event_map)
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX];
+	unsigned int	num_counters;
+};
+
+static struct mips_pmu mipspmu;
 
 #define M_CONFIG1_PC	(1 << 4)
 
-#define M_PERFCTL_EXL			(1UL      <<  0)
-#define M_PERFCTL_KERNEL		(1UL      <<  1)
-#define M_PERFCTL_SUPERVISOR		(1UL      <<  2)
-#define M_PERFCTL_USER			(1UL      <<  3)
-#define M_PERFCTL_INTERRUPT_ENABLE	(1UL      <<  4)
+#define M_PERFCTL_EXL			(1      <<  0)
+#define M_PERFCTL_KERNEL		(1      <<  1)
+#define M_PERFCTL_SUPERVISOR		(1      <<  2)
+#define M_PERFCTL_USER			(1      <<  3)
+#define M_PERFCTL_INTERRUPT_ENABLE	(1      <<  4)
 #define M_PERFCTL_EVENT(event)		(((event) & 0x3ff)  << 5)
 #define M_PERFCTL_VPEID(vpe)		((vpe)    << 16)
 #define M_PERFCTL_MT_EN(filter)		((filter) << 20)
@@ -15,8 +114,8 @@
 #define    M_TC_EN_VPE			M_PERFCTL_MT_EN(1)
 #define    M_TC_EN_TC			M_PERFCTL_MT_EN(2)
 #define M_PERFCTL_TCID(tcid)		((tcid)   << 22)
-#define M_PERFCTL_WIDE			(1UL      << 30)
-#define M_PERFCTL_MORE			(1UL      << 31)
+#define M_PERFCTL_WIDE			(1      << 30)
+#define M_PERFCTL_MORE			(1      << 31)
 
 #define M_PERFCTL_COUNT_EVENT_WHENEVER	(M_PERFCTL_EXL |		\
 					M_PERFCTL_KERNEL |		\
@@ -31,11 +130,12 @@
 #endif
 #define M_PERFCTL_EVENT_MASK		0xfe0
 
-#define M_COUNTER_OVERFLOW		(1UL      << 31)
 
 #ifdef CONFIG_MIPS_MT_SMP
 static int cpu_has_mipsmt_pertccounters;
 
+static DEFINE_RWLOCK(pmuint_rwlock);
+
 /*
  * FIXME: For VSMP, vpe_id() is redefined for Perf-events, because
  * cpu_data[cpuid].vpe_id reports 0 for _both_ CPUs.
@@ -49,209 +149,673 @@
 #endif
 
 /* Copied from op_model_mipsxx.c */
-static inline unsigned int vpe_shift(void)
+static unsigned int vpe_shift(void)
 {
 	if (num_possible_cpus() > 1)
 		return 1;
 
 	return 0;
 }
-#else /* !CONFIG_MIPS_MT_SMP */
-#define vpe_id()	0
 
-static inline unsigned int vpe_shift(void)
-{
-	return 0;
-}
-#endif /* CONFIG_MIPS_MT_SMP */
-
-static inline unsigned int
-counters_total_to_per_cpu(unsigned int counters)
+static unsigned int counters_total_to_per_cpu(unsigned int counters)
 {
 	return counters >> vpe_shift();
 }
 
-static inline unsigned int
-counters_per_cpu_to_total(unsigned int counters)
+static unsigned int counters_per_cpu_to_total(unsigned int counters)
 {
 	return counters << vpe_shift();
 }
 
-#define __define_perf_accessors(r, n, np)				\
-									\
-static inline unsigned int r_c0_ ## r ## n(void)			\
-{									\
-	unsigned int cpu = vpe_id();					\
-									\
-	switch (cpu) {							\
-	case 0:								\
-		return read_c0_ ## r ## n();				\
-	case 1:								\
-		return read_c0_ ## r ## np();				\
-	default:							\
-		BUG();							\
-	}								\
-	return 0;							\
-}									\
-									\
-static inline void w_c0_ ## r ## n(unsigned int value)			\
-{									\
-	unsigned int cpu = vpe_id();					\
-									\
-	switch (cpu) {							\
-	case 0:								\
-		write_c0_ ## r ## n(value);				\
-		return;							\
-	case 1:								\
-		write_c0_ ## r ## np(value);				\
-		return;							\
-	default:							\
-		BUG();							\
-	}								\
-	return;								\
-}									\
+#else /* !CONFIG_MIPS_MT_SMP */
+#define vpe_id()	0
 
-__define_perf_accessors(perfcntr, 0, 2)
-__define_perf_accessors(perfcntr, 1, 3)
-__define_perf_accessors(perfcntr, 2, 0)
-__define_perf_accessors(perfcntr, 3, 1)
+#endif /* CONFIG_MIPS_MT_SMP */
 
-__define_perf_accessors(perfctrl, 0, 2)
-__define_perf_accessors(perfctrl, 1, 3)
-__define_perf_accessors(perfctrl, 2, 0)
-__define_perf_accessors(perfctrl, 3, 1)
+static void resume_local_counters(void);
+static void pause_local_counters(void);
+static irqreturn_t mipsxx_pmu_handle_irq(int, void *);
+static int mipsxx_pmu_handle_shared_irq(void);
 
-static inline int __n_counters(void)
+static unsigned int mipsxx_pmu_swizzle_perf_idx(unsigned int idx)
 {
-	if (!(read_c0_config1() & M_CONFIG1_PC))
-		return 0;
-	if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
-		return 1;
-	if (!(read_c0_perfctrl1() & M_PERFCTL_MORE))
-		return 2;
-	if (!(read_c0_perfctrl2() & M_PERFCTL_MORE))
-		return 3;
-
-	return 4;
+	if (vpe_id() == 1)
+		idx = (idx + 2) & 3;
+	return idx;
 }
 
-static inline int n_counters(void)
+static u64 mipsxx_pmu_read_counter(unsigned int idx)
 {
-	int counters;
-
-	switch (current_cpu_type()) {
-	case CPU_R10000:
-		counters = 2;
-		break;
-
-	case CPU_R12000:
-	case CPU_R14000:
-		counters = 4;
-		break;
+	idx = mipsxx_pmu_swizzle_perf_idx(idx);
 
+	switch (idx) {
+	case 0:
+		/*
+		 * The counters are unsigned, we must cast to truncate
+		 * off the high bits.
+		 */
+		return (u32)read_c0_perfcntr0();
+	case 1:
+		return (u32)read_c0_perfcntr1();
+	case 2:
+		return (u32)read_c0_perfcntr2();
+	case 3:
+		return (u32)read_c0_perfcntr3();
 	default:
-		counters = __n_counters();
+		WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx);
+		return 0;
 	}
-
-	return counters;
 }
 
-static void reset_counters(void *arg)
+static u64 mipsxx_pmu_read_counter_64(unsigned int idx)
 {
-	int counters = (int)(long)arg;
-	switch (counters) {
-	case 4:
-		w_c0_perfctrl3(0);
-		w_c0_perfcntr3(0);
-	case 3:
-		w_c0_perfctrl2(0);
-		w_c0_perfcntr2(0);
-	case 2:
-		w_c0_perfctrl1(0);
-		w_c0_perfcntr1(0);
+	idx = mipsxx_pmu_swizzle_perf_idx(idx);
+
+	switch (idx) {
+	case 0:
+		return read_c0_perfcntr0_64();
 	case 1:
-		w_c0_perfctrl0(0);
-		w_c0_perfcntr0(0);
+		return read_c0_perfcntr1_64();
+	case 2:
+		return read_c0_perfcntr2_64();
+	case 3:
+		return read_c0_perfcntr3_64();
+	default:
+		WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx);
+		return 0;
 	}
 }
 
-static inline u64
-mipsxx_pmu_read_counter(unsigned int idx)
+static void mipsxx_pmu_write_counter(unsigned int idx, u64 val)
 {
+	idx = mipsxx_pmu_swizzle_perf_idx(idx);
+
 	switch (idx) {
 	case 0:
-		return r_c0_perfcntr0();
+		write_c0_perfcntr0(val);
+		return;
 	case 1:
-		return r_c0_perfcntr1();
+		write_c0_perfcntr1(val);
+		return;
 	case 2:
-		return r_c0_perfcntr2();
+		write_c0_perfcntr2(val);
+		return;
 	case 3:
-		return r_c0_perfcntr3();
-	default:
-		WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx);
-		return 0;
+		write_c0_perfcntr3(val);
+		return;
 	}
 }
 
-static inline void
-mipsxx_pmu_write_counter(unsigned int idx, u64 val)
+static void mipsxx_pmu_write_counter_64(unsigned int idx, u64 val)
 {
+	idx = mipsxx_pmu_swizzle_perf_idx(idx);
+
 	switch (idx) {
 	case 0:
-		w_c0_perfcntr0(val);
+		write_c0_perfcntr0_64(val);
 		return;
 	case 1:
-		w_c0_perfcntr1(val);
+		write_c0_perfcntr1_64(val);
 		return;
 	case 2:
-		w_c0_perfcntr2(val);
+		write_c0_perfcntr2_64(val);
 		return;
 	case 3:
-		w_c0_perfcntr3(val);
+		write_c0_perfcntr3_64(val);
 		return;
 	}
 }
 
-static inline unsigned int
-mipsxx_pmu_read_control(unsigned int idx)
+static unsigned int mipsxx_pmu_read_control(unsigned int idx)
 {
+	idx = mipsxx_pmu_swizzle_perf_idx(idx);
+
 	switch (idx) {
 	case 0:
-		return r_c0_perfctrl0();
+		return read_c0_perfctrl0();
 	case 1:
-		return r_c0_perfctrl1();
+		return read_c0_perfctrl1();
 	case 2:
-		return r_c0_perfctrl2();
+		return read_c0_perfctrl2();
 	case 3:
-		return r_c0_perfctrl3();
+		return read_c0_perfctrl3();
 	default:
 		WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx);
 		return 0;
 	}
 }
 
-static inline void
-mipsxx_pmu_write_control(unsigned int idx, unsigned int val)
+static void mipsxx_pmu_write_control(unsigned int idx, unsigned int val)
 {
+	idx = mipsxx_pmu_swizzle_perf_idx(idx);
+
 	switch (idx) {
 	case 0:
-		w_c0_perfctrl0(val);
+		write_c0_perfctrl0(val);
 		return;
 	case 1:
-		w_c0_perfctrl1(val);
+		write_c0_perfctrl1(val);
 		return;
 	case 2:
-		w_c0_perfctrl2(val);
+		write_c0_perfctrl2(val);
 		return;
 	case 3:
-		w_c0_perfctrl3(val);
+		write_c0_perfctrl3(val);
 		return;
 	}
 }
 
+static int mipsxx_pmu_alloc_counter(struct cpu_hw_events *cpuc,
+				    struct hw_perf_event *hwc)
+{
+	int i;
+
+	/*
+	 * We only need to care the counter mask. The range has been
+	 * checked definitely.
+	 */
+	unsigned long cntr_mask = (hwc->event_base >> 8) & 0xffff;
+
+	for (i = mipspmu.num_counters - 1; i >= 0; i--) {
+		/*
+		 * Note that some MIPS perf events can be counted by both
+		 * even and odd counters, wheresas many other are only by
+		 * even _or_ odd counters. This introduces an issue that
+		 * when the former kind of event takes the counter the
+		 * latter kind of event wants to use, then the "counter
+		 * allocation" for the latter event will fail. In fact if
+		 * they can be dynamically swapped, they both feel happy.
+		 * But here we leave this issue alone for now.
+		 */
+		if (test_bit(i, &cntr_mask) &&
+			!test_and_set_bit(i, cpuc->used_mask))
+			return i;
+	}
+
+	return -EAGAIN;
+}
+
+static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+
+	WARN_ON(idx < 0 || idx >= mipspmu.num_counters);
+
+	cpuc->saved_ctrl[idx] = M_PERFCTL_EVENT(evt->event_base & 0xff) |
+		(evt->config_base & M_PERFCTL_CONFIG_MASK) |
+		/* Make sure interrupt enabled. */
+		M_PERFCTL_INTERRUPT_ENABLE;
+	/*
+	 * We do not actually let the counter run. Leave it until start().
+	 */
+}
+
+static void mipsxx_pmu_disable_event(int idx)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	unsigned long flags;
+
+	WARN_ON(idx < 0 || idx >= mipspmu.num_counters);
+
+	local_irq_save(flags);
+	cpuc->saved_ctrl[idx] = mipsxx_pmu_read_control(idx) &
+		~M_PERFCTL_COUNT_EVENT_WHENEVER;
+	mipsxx_pmu_write_control(idx, cpuc->saved_ctrl[idx]);
+	local_irq_restore(flags);
+}
+
+static int mipspmu_event_set_period(struct perf_event *event,
+				    struct hw_perf_event *hwc,
+				    int idx)
+{
+	u64 left = local64_read(&hwc->period_left);
+	u64 period = hwc->sample_period;
+	int ret = 0;
+
+	if (unlikely((left + period) & (1ULL << 63))) {
+		/* left underflowed by more than period. */
+		left = period;
+		local64_set(&hwc->period_left, left);
+		hwc->last_period = period;
+		ret = 1;
+	} else	if (unlikely((left + period) <= period)) {
+		/* left underflowed by less than period. */
+		left += period;
+		local64_set(&hwc->period_left, left);
+		hwc->last_period = period;
+		ret = 1;
+	}
+
+	if (left > mipspmu.max_period) {
+		left = mipspmu.max_period;
+		local64_set(&hwc->period_left, left);
+	}
+
+	local64_set(&hwc->prev_count, mipspmu.overflow - left);
+
+	mipspmu.write_counter(idx, mipspmu.overflow - left);
+
+	perf_event_update_userpage(event);
+
+	return ret;
+}
+
+static void mipspmu_event_update(struct perf_event *event,
+				 struct hw_perf_event *hwc,
+				 int idx)
+{
+	u64 prev_raw_count, new_raw_count;
+	u64 delta;
+
+again:
+	prev_raw_count = local64_read(&hwc->prev_count);
+	new_raw_count = mipspmu.read_counter(idx);
+
+	if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+				new_raw_count) != prev_raw_count)
+		goto again;
+
+	delta = new_raw_count - prev_raw_count;
+
+	local64_add(delta, &event->count);
+	local64_sub(delta, &hwc->period_left);
+}
+
+static void mipspmu_start(struct perf_event *event, int flags)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	if (flags & PERF_EF_RELOAD)
+		WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+
+	hwc->state = 0;
+
+	/* Set the period for the event. */
+	mipspmu_event_set_period(event, hwc, hwc->idx);
+
+	/* Enable the event. */
+	mipsxx_pmu_enable_event(hwc, hwc->idx);
+}
+
+static void mipspmu_stop(struct perf_event *event, int flags)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	if (!(hwc->state & PERF_HES_STOPPED)) {
+		/* We are working on a local event. */
+		mipsxx_pmu_disable_event(hwc->idx);
+		barrier();
+		mipspmu_event_update(event, hwc, hwc->idx);
+		hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
+	}
+}
+
+static int mipspmu_add(struct perf_event *event, int flags)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	struct hw_perf_event *hwc = &event->hw;
+	int idx;
+	int err = 0;
+
+	perf_pmu_disable(event->pmu);
+
+	/* To look for a free counter for this event. */
+	idx = mipsxx_pmu_alloc_counter(cpuc, hwc);
+	if (idx < 0) {
+		err = idx;
+		goto out;
+	}
+
+	/*
+	 * If there is an event in the counter we are going to use then
+	 * make sure it is disabled.
+	 */
+	event->hw.idx = idx;
+	mipsxx_pmu_disable_event(idx);
+	cpuc->events[idx] = event;
+
+	hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+	if (flags & PERF_EF_START)
+		mipspmu_start(event, PERF_EF_RELOAD);
+
+	/* Propagate our changes to the userspace mapping. */
+	perf_event_update_userpage(event);
+
+out:
+	perf_pmu_enable(event->pmu);
+	return err;
+}
+
+static void mipspmu_del(struct perf_event *event, int flags)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	struct hw_perf_event *hwc = &event->hw;
+	int idx = hwc->idx;
+
+	WARN_ON(idx < 0 || idx >= mipspmu.num_counters);
+
+	mipspmu_stop(event, PERF_EF_UPDATE);
+	cpuc->events[idx] = NULL;
+	clear_bit(idx, cpuc->used_mask);
+
+	perf_event_update_userpage(event);
+}
+
+static void mipspmu_read(struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	/* Don't read disabled counters! */
+	if (hwc->idx < 0)
+		return;
+
+	mipspmu_event_update(event, hwc, hwc->idx);
+}
+
+static void mipspmu_enable(struct pmu *pmu)
+{
 #ifdef CONFIG_MIPS_MT_SMP
-static DEFINE_RWLOCK(pmuint_rwlock);
+	write_unlock(&pmuint_rwlock);
+#endif
+	resume_local_counters();
+}
+
+/*
+ * MIPS performance counters can be per-TC. The control registers can
+ * not be directly accessed accross 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
+ * counters on other CPUs alone. If any counter interrupt raises while
+ * we own the write lock, simply pause local counters on that CPU and
+ * spin in the handler. Also we know we won't be switched to another
+ * CPU after pausing local counters and before grabbing the lock.
+ */
+static void mipspmu_disable(struct pmu *pmu)
+{
+	pause_local_counters();
+#ifdef CONFIG_MIPS_MT_SMP
+	write_lock(&pmuint_rwlock);
 #endif
+}
+
+static atomic_t active_events = ATOMIC_INIT(0);
+static DEFINE_MUTEX(pmu_reserve_mutex);
+static int (*save_perf_irq)(void);
+
+static int mipspmu_get_irq(void)
+{
+	int err;
+
+	if (mipspmu.irq >= 0) {
+		/* Request my own irq handler. */
+		err = request_irq(mipspmu.irq, mipsxx_pmu_handle_irq,
+			IRQF_PERCPU | IRQF_NOBALANCING,
+			"mips_perf_pmu", NULL);
+		if (err) {
+			pr_warning("Unable to request IRQ%d for MIPS "
+			   "performance counters!\n", mipspmu.irq);
+		}
+	} else if (cp0_perfcount_irq < 0) {
+		/*
+		 * We are sharing the irq number with the timer interrupt.
+		 */
+		save_perf_irq = perf_irq;
+		perf_irq = mipsxx_pmu_handle_shared_irq;
+		err = 0;
+	} else {
+		pr_warning("The platform hasn't properly defined its "
+			"interrupt controller.\n");
+		err = -ENOENT;
+	}
+
+	return err;
+}
+
+static void mipspmu_free_irq(void)
+{
+	if (mipspmu.irq >= 0)
+		free_irq(mipspmu.irq, NULL);
+	else if (cp0_perfcount_irq < 0)
+		perf_irq = save_perf_irq;
+}
+
+/*
+ * mipsxx/rm9000/loongson2 have different performance counters, they have
+ * specific low-level init routines.
+ */
+static void reset_counters(void *arg);
+static int __hw_perf_event_init(struct perf_event *event);
+
+static void hw_perf_event_destroy(struct perf_event *event)
+{
+	if (atomic_dec_and_mutex_lock(&active_events,
+				&pmu_reserve_mutex)) {
+		/*
+		 * We must not call the destroy function with interrupts
+		 * disabled.
+		 */
+		on_each_cpu(reset_counters,
+			(void *)(long)mipspmu.num_counters, 1);
+		mipspmu_free_irq();
+		mutex_unlock(&pmu_reserve_mutex);
+	}
+}
+
+static int mipspmu_event_init(struct perf_event *event)
+{
+	int err = 0;
+
+	switch (event->attr.type) {
+	case PERF_TYPE_RAW:
+	case PERF_TYPE_HARDWARE:
+	case PERF_TYPE_HW_CACHE:
+		break;
+
+	default:
+		return -ENOENT;
+	}
+
+	if (event->cpu >= nr_cpumask_bits ||
+	    (event->cpu >= 0 && !cpu_online(event->cpu)))
+		return -ENODEV;
+
+	if (!atomic_inc_not_zero(&active_events)) {
+		if (atomic_read(&active_events) > MIPS_MAX_HWEVENTS) {
+			atomic_dec(&active_events);
+			return -EINVAL;
+		}
+
+		mutex_lock(&pmu_reserve_mutex);
+		if (atomic_read(&active_events) == 0)
+			err = mipspmu_get_irq();
+
+		if (!err)
+			atomic_inc(&active_events);
+		mutex_unlock(&pmu_reserve_mutex);
+	}
+
+	if (err)
+		return err;
+
+	err = __hw_perf_event_init(event);
+	if (err)
+		hw_perf_event_destroy(event);
+
+	return err;
+}
+
+static struct pmu pmu = {
+	.pmu_enable	= mipspmu_enable,
+	.pmu_disable	= mipspmu_disable,
+	.event_init	= mipspmu_event_init,
+	.add		= mipspmu_add,
+	.del		= mipspmu_del,
+	.start		= mipspmu_start,
+	.stop		= mipspmu_stop,
+	.read		= mipspmu_read,
+};
+
+static unsigned int mipspmu_perf_event_encode(const struct mips_perf_event *pev)
+{
+/*
+ * Top 8 bits for range, next 16 bits for cntr_mask, lowest 8 bits for
+ * event_id.
+ */
+#ifdef CONFIG_MIPS_MT_SMP
+	return ((unsigned int)pev->range << 24) |
+		(pev->cntr_mask & 0xffff00) |
+		(pev->event_id & 0xff);
+#else
+	return (pev->cntr_mask & 0xffff00) |
+		(pev->event_id & 0xff);
+#endif
+}
+
+static const struct mips_perf_event *mipspmu_map_general_event(int idx)
+{
+	const struct mips_perf_event *pev;
+
+	pev = ((*mipspmu.general_event_map)[idx].event_id ==
+		UNSUPPORTED_PERF_EVENT_ID ? ERR_PTR(-EOPNOTSUPP) :
+		&(*mipspmu.general_event_map)[idx]);
+
+	return pev;
+}
+
+static const struct mips_perf_event *mipspmu_map_cache_event(u64 config)
+{
+	unsigned int cache_type, cache_op, cache_result;
+	const struct mips_perf_event *pev;
+
+	cache_type = (config >> 0) & 0xff;
+	if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
+		return ERR_PTR(-EINVAL);
+
+	cache_op = (config >> 8) & 0xff;
+	if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
+		return ERR_PTR(-EINVAL);
+
+	cache_result = (config >> 16) & 0xff;
+	if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
+		return ERR_PTR(-EINVAL);
+
+	pev = &((*mipspmu.cache_event_map)
+					[cache_type]
+					[cache_op]
+					[cache_result]);
+
+	if (pev->event_id == UNSUPPORTED_PERF_EVENT_ID)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	return pev;
+
+}
+
+static int validate_event(struct cpu_hw_events *cpuc,
+	       struct perf_event *event)
+{
+	struct hw_perf_event fake_hwc = event->hw;
+
+	/* Allow mixed event group. So return 1 to pass validation. */
+	if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF)
+		return 1;
+
+	return mipsxx_pmu_alloc_counter(cpuc, &fake_hwc) >= 0;
+}
+
+static int validate_group(struct perf_event *event)
+{
+	struct perf_event *sibling, *leader = event->group_leader;
+	struct cpu_hw_events fake_cpuc;
+
+	memset(&fake_cpuc, 0, sizeof(fake_cpuc));
+
+	if (!validate_event(&fake_cpuc, leader))
+		return -EINVAL;
+
+	list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
+		if (!validate_event(&fake_cpuc, sibling))
+			return -EINVAL;
+	}
+
+	if (!validate_event(&fake_cpuc, event))
+		return -EINVAL;
+
+	return 0;
+}
+
+/* This is needed by specific irq handlers in perf_event_*.c */
+static void handle_associated_event(struct cpu_hw_events *cpuc,
+				    int idx, struct perf_sample_data *data,
+				    struct pt_regs *regs)
+{
+	struct perf_event *event = cpuc->events[idx];
+	struct hw_perf_event *hwc = &event->hw;
+
+	mipspmu_event_update(event, hwc, idx);
+	data->period = event->hw.last_period;
+	if (!mipspmu_event_set_period(event, hwc, idx))
+		return;
+
+	if (perf_event_overflow(event, data, regs))
+		mipsxx_pmu_disable_event(idx);
+}
+
+
+static int __n_counters(void)
+{
+	if (!(read_c0_config1() & M_CONFIG1_PC))
+		return 0;
+	if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
+		return 1;
+	if (!(read_c0_perfctrl1() & M_PERFCTL_MORE))
+		return 2;
+	if (!(read_c0_perfctrl2() & M_PERFCTL_MORE))
+		return 3;
+
+	return 4;
+}
+
+static int n_counters(void)
+{
+	int counters;
+
+	switch (current_cpu_type()) {
+	case CPU_R10000:
+		counters = 2;
+		break;
+
+	case CPU_R12000:
+	case CPU_R14000:
+		counters = 4;
+		break;
+
+	default:
+		counters = __n_counters();
+	}
+
+	return counters;
+}
+
+static void reset_counters(void *arg)
+{
+	int counters = (int)(long)arg;
+	switch (counters) {
+	case 4:
+		mipsxx_pmu_write_control(3, 0);
+		mipspmu.write_counter(3, 0);
+	case 3:
+		mipsxx_pmu_write_control(2, 0);
+		mipspmu.write_counter(2, 0);
+	case 2:
+		mipsxx_pmu_write_control(1, 0);
+		mipspmu.write_counter(1, 0);
+	case 1:
+		mipsxx_pmu_write_control(0, 0);
+		mipspmu.write_counter(0, 0);
+	}
+}
 
 /* 24K/34K/1004K cores can share the same event map. */
 static const struct mips_perf_event mipsxxcore_event_map
@@ -277,6 +841,16 @@
 	[PERF_COUNT_HW_BUS_CYCLES] = { UNSUPPORTED_PERF_EVENT_ID },
 };
 
+static const struct mips_perf_event octeon_event_map[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES] = { 0x01, CNTR_ALL },
+	[PERF_COUNT_HW_INSTRUCTIONS] = { 0x03, CNTR_ALL },
+	[PERF_COUNT_HW_CACHE_REFERENCES] = { 0x2b, CNTR_ALL },
+	[PERF_COUNT_HW_CACHE_MISSES] = { 0x2e, CNTR_ALL  },
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x08, CNTR_ALL },
+	[PERF_COUNT_HW_BRANCH_MISSES] = { 0x09, CNTR_ALL },
+	[PERF_COUNT_HW_BUS_CYCLES] = { 0x25, CNTR_ALL },
+};
+
 /* 24K/34K/1004K cores can share the same cache event map. */
 static const struct mips_perf_event mipsxxcore_cache_map
 				[PERF_COUNT_HW_CACHE_MAX]
@@ -510,10 +1084,105 @@
 },
 };
 
+
+static const struct mips_perf_event octeon_cache_map
+				[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)]	= { 0x2b, CNTR_ALL },
+		[C(RESULT_MISS)]	= { 0x2e, CNTR_ALL },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { 0x30, CNTR_ALL },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+[C(L1I)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { 0x18, CNTR_ALL },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { 0x19, CNTR_ALL },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+[C(LL)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+[C(DTLB)] = {
+	/*
+	 * Only general DTLB misses are counted use the same event for
+	 * read and write.
+	 */
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { 0x35, CNTR_ALL },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { 0x35, CNTR_ALL },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+[C(ITLB)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { 0x37, CNTR_ALL },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+[C(BPU)] = {
+	/* Using the same code for *HW_BRANCH* */
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+};
+
 #ifdef CONFIG_MIPS_MT_SMP
-static void
-check_and_calc_range(struct perf_event *event,
-			const struct mips_perf_event *pev)
+static void check_and_calc_range(struct perf_event *event,
+				 const struct mips_perf_event *pev)
 {
 	struct hw_perf_event *hwc = &event->hw;
 
@@ -536,9 +1205,8 @@
 		hwc->config_base |= M_TC_EN_ALL;
 }
 #else
-static void
-check_and_calc_range(struct perf_event *event,
-			const struct mips_perf_event *pev)
+static void check_and_calc_range(struct perf_event *event,
+				 const struct mips_perf_event *pev)
 {
 }
 #endif
@@ -560,7 +1228,7 @@
 	} else if (PERF_TYPE_RAW == event->attr.type) {
 		/* We are working on the global raw event. */
 		mutex_lock(&raw_event_mutex);
-		pev = mipspmu->map_raw_event(event->attr.config);
+		pev = mipspmu.map_raw_event(event->attr.config);
 	} else {
 		/* The event type is not (yet) supported. */
 		return -EOPNOTSUPP;
@@ -605,7 +1273,7 @@
 	hwc->config = 0;
 
 	if (!hwc->sample_period) {
-		hwc->sample_period  = MAX_PERIOD;
+		hwc->sample_period  = mipspmu.max_period;
 		hwc->last_period    = hwc->sample_period;
 		local64_set(&hwc->period_left, hwc->sample_period);
 	}
@@ -618,70 +1286,47 @@
 	}
 
 	event->destroy = hw_perf_event_destroy;
-
 	return err;
 }
 
 static void pause_local_counters(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	int counters = mipspmu->num_counters;
+	int ctr = mipspmu.num_counters;
 	unsigned long flags;
 
 	local_irq_save(flags);
-	switch (counters) {
-	case 4:
-		cpuc->saved_ctrl[3] = r_c0_perfctrl3();
-		w_c0_perfctrl3(cpuc->saved_ctrl[3] &
-			~M_PERFCTL_COUNT_EVENT_WHENEVER);
-	case 3:
-		cpuc->saved_ctrl[2] = r_c0_perfctrl2();
-		w_c0_perfctrl2(cpuc->saved_ctrl[2] &
-			~M_PERFCTL_COUNT_EVENT_WHENEVER);
-	case 2:
-		cpuc->saved_ctrl[1] = r_c0_perfctrl1();
-		w_c0_perfctrl1(cpuc->saved_ctrl[1] &
-			~M_PERFCTL_COUNT_EVENT_WHENEVER);
-	case 1:
-		cpuc->saved_ctrl[0] = r_c0_perfctrl0();
-		w_c0_perfctrl0(cpuc->saved_ctrl[0] &
-			~M_PERFCTL_COUNT_EVENT_WHENEVER);
-	}
+	do {
+		ctr--;
+		cpuc->saved_ctrl[ctr] = mipsxx_pmu_read_control(ctr);
+		mipsxx_pmu_write_control(ctr, cpuc->saved_ctrl[ctr] &
+					 ~M_PERFCTL_COUNT_EVENT_WHENEVER);
+	} while (ctr > 0);
 	local_irq_restore(flags);
 }
 
 static void resume_local_counters(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	int counters = mipspmu->num_counters;
-	unsigned long flags;
+	int ctr = mipspmu.num_counters;
 
-	local_irq_save(flags);
-	switch (counters) {
-	case 4:
-		w_c0_perfctrl3(cpuc->saved_ctrl[3]);
-	case 3:
-		w_c0_perfctrl2(cpuc->saved_ctrl[2]);
-	case 2:
-		w_c0_perfctrl1(cpuc->saved_ctrl[1]);
-	case 1:
-		w_c0_perfctrl0(cpuc->saved_ctrl[0]);
-	}
-	local_irq_restore(flags);
+	do {
+		ctr--;
+		mipsxx_pmu_write_control(ctr, cpuc->saved_ctrl[ctr]);
+	} while (ctr > 0);
 }
 
 static int mipsxx_pmu_handle_shared_irq(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct perf_sample_data data;
-	unsigned int counters = mipspmu->num_counters;
-	unsigned int counter;
+	unsigned int counters = mipspmu.num_counters;
+	u64 counter;
 	int handled = IRQ_NONE;
 	struct pt_regs *regs;
 
 	if (cpu_has_mips_r2 && !(read_c0_cause() & (1 << 26)))
 		return handled;
-
 	/*
 	 * First we pause the local counters, so that when we are locked
 	 * here, the counters are all paused. When it gets locked due to
@@ -702,13 +1347,9 @@
 #define HANDLE_COUNTER(n)						\
 	case n + 1:							\
 		if (test_bit(n, cpuc->used_mask)) {			\
-			counter = r_c0_perfcntr ## n();			\
-			if (counter & M_COUNTER_OVERFLOW) {		\
-				w_c0_perfcntr ## n(counter &		\
-						VALID_COUNT);		\
-				if (test_and_change_bit(n, cpuc->msbs))	\
-					handle_associated_event(cpuc,	\
-						n, &data, regs);	\
+			counter = mipspmu.read_counter(n);		\
+			if (counter & mipspmu.overflow) {		\
+				handle_associated_event(cpuc, n, &data, regs); \
 				handled = IRQ_HANDLED;			\
 			}						\
 		}
@@ -733,104 +1374,11 @@
 	return handled;
 }
 
-static irqreturn_t
-mipsxx_pmu_handle_irq(int irq, void *dev)
+static irqreturn_t mipsxx_pmu_handle_irq(int irq, void *dev)
 {
 	return mipsxx_pmu_handle_shared_irq();
 }
 
-static void mipsxx_pmu_start(void)
-{
-#ifdef CONFIG_MIPS_MT_SMP
-	write_unlock(&pmuint_rwlock);
-#endif
-	resume_local_counters();
-}
-
-/*
- * MIPS performance counters can be per-TC. The control registers can
- * 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
- * counters on other CPUs alone. If any counter interrupt raises while
- * we own the write lock, simply pause local counters on that CPU and
- * spin in the handler. Also we know we won't be switched to another
- * CPU after pausing local counters and before grabbing the lock.
- */
-static void mipsxx_pmu_stop(void)
-{
-	pause_local_counters();
-#ifdef CONFIG_MIPS_MT_SMP
-	write_lock(&pmuint_rwlock);
-#endif
-}
-
-static int
-mipsxx_pmu_alloc_counter(struct cpu_hw_events *cpuc,
-			struct hw_perf_event *hwc)
-{
-	int i;
-
-	/*
-	 * We only need to care the counter mask. The range has been
-	 * checked definitely.
-	 */
-	unsigned long cntr_mask = (hwc->event_base >> 8) & 0xffff;
-
-	for (i = mipspmu->num_counters - 1; i >= 0; i--) {
-		/*
-		 * Note that some MIPS perf events can be counted by both
-		 * even and odd counters, wheresas many other are only by
-		 * even _or_ odd counters. This introduces an issue that
-		 * when the former kind of event takes the counter the
-		 * latter kind of event wants to use, then the "counter
-		 * allocation" for the latter event will fail. In fact if
-		 * they can be dynamically swapped, they both feel happy.
-		 * But here we leave this issue alone for now.
-		 */
-		if (test_bit(i, &cntr_mask) &&
-			!test_and_set_bit(i, cpuc->used_mask))
-			return i;
-	}
-
-	return -EAGAIN;
-}
-
-static void
-mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	unsigned long flags;
-
-	WARN_ON(idx < 0 || idx >= mipspmu->num_counters);
-
-	local_irq_save(flags);
-	cpuc->saved_ctrl[idx] = M_PERFCTL_EVENT(evt->event_base & 0xff) |
-		(evt->config_base & M_PERFCTL_CONFIG_MASK) |
-		/* Make sure interrupt enabled. */
-		M_PERFCTL_INTERRUPT_ENABLE;
-	/*
-	 * We do not actually let the counter run. Leave it until start().
-	 */
-	local_irq_restore(flags);
-}
-
-static void
-mipsxx_pmu_disable_event(int idx)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	unsigned long flags;
-
-	WARN_ON(idx < 0 || idx >= mipspmu->num_counters);
-
-	local_irq_save(flags);
-	cpuc->saved_ctrl[idx] = mipsxx_pmu_read_control(idx) &
-		~M_PERFCTL_COUNT_EVENT_WHENEVER;
-	mipsxx_pmu_write_control(idx, cpuc->saved_ctrl[idx]);
-	local_irq_restore(flags);
-}
-
 /* 24K */
 #define IS_UNSUPPORTED_24K_EVENT(r, b)					\
 	((b) == 12 || (r) == 151 || (r) == 152 || (b) == 26 ||		\
@@ -892,8 +1440,7 @@
  * then 128 needs to be added to 15 as the input for the event config,
  * i.e., 143 (0x8F) to be used.
  */
-static const struct mips_perf_event *
-mipsxx_pmu_map_raw_event(u64 config)
+static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
 {
 	unsigned int raw_id = config & 0xff;
 	unsigned int base_id = raw_id & 0x7f;
@@ -970,40 +1517,44 @@
 	return &raw_event;
 }
 
-static struct mips_pmu mipsxxcore_pmu = {
-	.handle_irq = mipsxx_pmu_handle_irq,
-	.handle_shared_irq = mipsxx_pmu_handle_shared_irq,
-	.start = mipsxx_pmu_start,
-	.stop = mipsxx_pmu_stop,
-	.alloc_counter = mipsxx_pmu_alloc_counter,
-	.read_counter = mipsxx_pmu_read_counter,
-	.write_counter = mipsxx_pmu_write_counter,
-	.enable_event = mipsxx_pmu_enable_event,
-	.disable_event = mipsxx_pmu_disable_event,
-	.map_raw_event = mipsxx_pmu_map_raw_event,
-	.general_event_map = &mipsxxcore_event_map,
-	.cache_event_map = &mipsxxcore_cache_map,
-};
+static const struct mips_perf_event *octeon_pmu_map_raw_event(u64 config)
+{
+	unsigned int raw_id = config & 0xff;
+	unsigned int base_id = raw_id & 0x7f;
 
-static struct mips_pmu mipsxx74Kcore_pmu = {
-	.handle_irq = mipsxx_pmu_handle_irq,
-	.handle_shared_irq = mipsxx_pmu_handle_shared_irq,
-	.start = mipsxx_pmu_start,
-	.stop = mipsxx_pmu_stop,
-	.alloc_counter = mipsxx_pmu_alloc_counter,
-	.read_counter = mipsxx_pmu_read_counter,
-	.write_counter = mipsxx_pmu_write_counter,
-	.enable_event = mipsxx_pmu_enable_event,
-	.disable_event = mipsxx_pmu_disable_event,
-	.map_raw_event = mipsxx_pmu_map_raw_event,
-	.general_event_map = &mipsxx74Kcore_event_map,
-	.cache_event_map = &mipsxx74Kcore_cache_map,
-};
+
+	raw_event.cntr_mask = CNTR_ALL;
+	raw_event.event_id = base_id;
+
+	if (current_cpu_type() == CPU_CAVIUM_OCTEON2) {
+		if (base_id > 0x42)
+			return ERR_PTR(-EOPNOTSUPP);
+	} else {
+		if (base_id > 0x3a)
+			return ERR_PTR(-EOPNOTSUPP);
+	}
+
+	switch (base_id) {
+	case 0x00:
+	case 0x0f:
+	case 0x1e:
+	case 0x1f:
+	case 0x2f:
+	case 0x34:
+	case 0x3b ... 0x3f:
+		return ERR_PTR(-EOPNOTSUPP);
+	default:
+		break;
+	}
+
+	return &raw_event;
+}
 
 static int __init
 init_hw_perf_events(void)
 {
 	int counters, irq;
+	int counter_bits;
 
 	pr_info("Performance counters: ");
 
@@ -1035,32 +1586,36 @@
 	}
 #endif
 
-	on_each_cpu(reset_counters, (void *)(long)counters, 1);
+	mipspmu.map_raw_event = mipsxx_pmu_map_raw_event;
 
 	switch (current_cpu_type()) {
 	case CPU_24K:
-		mipsxxcore_pmu.name = "mips/24K";
-		mipsxxcore_pmu.num_counters = counters;
-		mipsxxcore_pmu.irq = irq;
-		mipspmu = &mipsxxcore_pmu;
+		mipspmu.name = "mips/24K";
+		mipspmu.general_event_map = &mipsxxcore_event_map;
+		mipspmu.cache_event_map = &mipsxxcore_cache_map;
 		break;
 	case CPU_34K:
-		mipsxxcore_pmu.name = "mips/34K";
-		mipsxxcore_pmu.num_counters = counters;
-		mipsxxcore_pmu.irq = irq;
-		mipspmu = &mipsxxcore_pmu;
+		mipspmu.name = "mips/34K";
+		mipspmu.general_event_map = &mipsxxcore_event_map;
+		mipspmu.cache_event_map = &mipsxxcore_cache_map;
 		break;
 	case CPU_74K:
-		mipsxx74Kcore_pmu.name = "mips/74K";
-		mipsxx74Kcore_pmu.num_counters = counters;
-		mipsxx74Kcore_pmu.irq = irq;
-		mipspmu = &mipsxx74Kcore_pmu;
+		mipspmu.name = "mips/74K";
+		mipspmu.general_event_map = &mipsxx74Kcore_event_map;
+		mipspmu.cache_event_map = &mipsxx74Kcore_cache_map;
 		break;
 	case CPU_1004K:
-		mipsxxcore_pmu.name = "mips/1004K";
-		mipsxxcore_pmu.num_counters = counters;
-		mipsxxcore_pmu.irq = irq;
-		mipspmu = &mipsxxcore_pmu;
+		mipspmu.name = "mips/1004K";
+		mipspmu.general_event_map = &mipsxxcore_event_map;
+		mipspmu.cache_event_map = &mipsxxcore_cache_map;
+		break;
+	case CPU_CAVIUM_OCTEON:
+	case CPU_CAVIUM_OCTEON_PLUS:
+	case CPU_CAVIUM_OCTEON2:
+		mipspmu.name = "octeon";
+		mipspmu.general_event_map = &octeon_event_map;
+		mipspmu.cache_event_map = &octeon_cache_map;
+		mipspmu.map_raw_event = octeon_pmu_map_raw_event;
 		break;
 	default:
 		pr_cont("Either hardware does not support performance "
@@ -1068,15 +1623,33 @@
 		return -ENODEV;
 	}
 
-	if (mipspmu)
-		pr_cont("%s PMU enabled, %d counters available to each "
-			"CPU, irq %d%s\n", mipspmu->name, counters, irq,
-			irq < 0 ? " (share with timer interrupt)" : "");
+	mipspmu.num_counters = counters;
+	mipspmu.irq = irq;
+
+	if (read_c0_perfctrl0() & M_PERFCTL_WIDE) {
+		mipspmu.max_period = (1ULL << 63) - 1;
+		mipspmu.valid_count = (1ULL << 63) - 1;
+		mipspmu.overflow = 1ULL << 63;
+		mipspmu.read_counter = mipsxx_pmu_read_counter_64;
+		mipspmu.write_counter = mipsxx_pmu_write_counter_64;
+		counter_bits = 64;
+	} else {
+		mipspmu.max_period = (1ULL << 31) - 1;
+		mipspmu.valid_count = (1ULL << 31) - 1;
+		mipspmu.overflow = 1ULL << 31;
+		mipspmu.read_counter = mipsxx_pmu_read_counter;
+		mipspmu.write_counter = mipsxx_pmu_write_counter;
+		counter_bits = 32;
+	}
+
+	on_each_cpu(reset_counters, (void *)(long)counters, 1);
+
+	pr_cont("%s PMU enabled, %d %d-bit counters available to each "
+		"CPU, irq %d%s\n", mipspmu.name, counters, counter_bits, irq,
+		irq < 0 ? " (share with timer interrupt)" : "");
 
 	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 
 	return 0;
 }
 early_initcall(init_hw_perf_events);
-
-#endif /* defined(CONFIG_CPU_MIPS32)... */
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/process.c linux-libre-3.2-gnu/arch/mips/kernel/process.c
--- linux-libre-3.1-gnu/arch/mips/kernel/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,13 +9,13 @@
  * Copyright (C) 2004 Thiemo Seufer
  */
 #include <linux/errno.h>
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/tick.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
+#include <linux/export.h>
 #include <linux/ptrace.h>
 #include <linux/mman.h>
 #include <linux/personality.h>
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/prom.c linux-libre-3.2-gnu/arch/mips/kernel/prom.c
--- linux-libre-3.1-gnu/arch/mips/kernel/prom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/prom.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/bootmem.h>
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/reset.c linux-libre-3.2-gnu/arch/mips/kernel/reset.c
--- linux-libre-3.1-gnu/arch/mips/kernel/reset.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/reset.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * Copyright (C) 2001 MIPS Technologies, Inc.
  */
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/pm.h>
 #include <linux/types.h>
 #include <linux/reboot.h>
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/rtlx.c linux-libre-3.2-gnu/arch/mips/kernel/rtlx.c
--- linux-libre-3.1-gnu/arch/mips/kernel/rtlx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/rtlx.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,6 @@
 
 #include <linux/device.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/scall32-o32.S linux-libre-3.2-gnu/arch/mips/kernel/scall32-o32.S
--- linux-libre-3.1-gnu/arch/mips/kernel/scall32-o32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/scall32-o32.S	2012-01-04 18:55:44.000000000 -0500
@@ -496,7 +496,7 @@
 	sys	sys_lookup_dcookie	4
 	sys	sys_epoll_create	1
 	sys	sys_epoll_ctl		4
-	sys	sys_epoll_wait		3	/* 4250 */
+	sys	sys_epoll_wait		4	/* 4250 */
 	sys	sys_remap_file_pages	5
 	sys	sys_set_tid_address	1
 	sys	sys_restart_syscall	0
@@ -591,6 +591,8 @@
 	sys	sys_syncfs		1
 	sys	sys_sendmmsg		4
 	sys	sys_setns		2
+	sys	sys_process_vm_readv	6	/* 4345 */
+	sys	sys_process_vm_writev	6
 	.endm
 
 	/* We pre-compute the number of _instruction_ bytes needed to
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/scall64-64.S linux-libre-3.2-gnu/arch/mips/kernel/scall64-64.S
--- linux-libre-3.1-gnu/arch/mips/kernel/scall64-64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/scall64-64.S	2012-01-04 18:55:44.000000000 -0500
@@ -430,4 +430,6 @@
 	PTR	sys_syncfs
 	PTR	sys_sendmmsg
 	PTR	sys_setns
+	PTR	sys_process_vm_readv
+	PTR	sys_process_vm_writev		/* 5305 */
 	.size	sys_call_table,.-sys_call_table
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/scall64-n32.S linux-libre-3.2-gnu/arch/mips/kernel/scall64-n32.S
--- linux-libre-3.1-gnu/arch/mips/kernel/scall64-n32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/scall64-n32.S	2012-01-04 18:55:44.000000000 -0500
@@ -430,4 +430,6 @@
 	PTR	sys_syncfs
 	PTR	compat_sys_sendmmsg
 	PTR	sys_setns
+	PTR	compat_sys_process_vm_readv
+	PTR	compat_sys_process_vm_writev	/* 6310 */
 	.size	sysn32_call_table,.-sysn32_call_table
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/scall64-o32.S linux-libre-3.2-gnu/arch/mips/kernel/scall64-o32.S
--- linux-libre-3.1-gnu/arch/mips/kernel/scall64-o32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/scall64-o32.S	2012-01-04 18:55:44.000000000 -0500
@@ -548,4 +548,6 @@
 	PTR	sys_syncfs
 	PTR	compat_sys_sendmmsg
 	PTR	sys_setns
+	PTR	compat_sys_process_vm_readv	/* 4345 */
+	PTR	compat_sys_process_vm_writev
 	.size	sys_call_table,.-sys_call_table
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/setup.c linux-libre-3.2-gnu/arch/mips/kernel/setup.c
--- linux-libre-3.1-gnu/arch/mips/kernel/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
  */
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/screen_info.h>
 #include <linux/bootmem.h>
 #include <linux/initrd.h>
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/spinlock_test.c linux-libre-3.2-gnu/arch/mips/kernel/spinlock_test.c
--- linux-libre-3.1-gnu/arch/mips/kernel/spinlock_test.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/spinlock_test.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
 #include <linux/hrtimer.h>
 #include <linux/fs.h>
 #include <linux/debugfs.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/spinlock.h>
 
 
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/stacktrace.c linux-libre-3.2-gnu/arch/mips/kernel/stacktrace.c
--- linux-libre-3.1-gnu/arch/mips/kernel/stacktrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/stacktrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
  */
 #include <linux/sched.h>
 #include <linux/stacktrace.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/stacktrace.h>
 
 /*
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/time.c linux-libre-3.2-gnu/arch/mips/kernel/time.c
--- linux-libre-3.1-gnu/arch/mips/kernel/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
 #include <linux/timex.h>
 #include <linux/smp.h>
 #include <linux/spinlock.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/cpu-features.h>
 #include <asm/div64.h>
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/traps.c linux-libre-3.2-gnu/arch/mips/kernel/traps.c
--- linux-libre-3.1-gnu/arch/mips/kernel/traps.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/traps.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/spinlock.h>
@@ -1597,7 +1596,8 @@
 	}
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-	cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
+	if (!cpu_data[cpu].asid_cache)
+		cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
 
 	atomic_inc(&init_mm.mm_count);
 	current->active_mm = &init_mm;
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/unaligned.c linux-libre-3.2-gnu/arch/mips/kernel/unaligned.c
--- linux-libre-3.1-gnu/arch/mips/kernel/unaligned.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/unaligned.c	2012-01-04 18:55:44.000000000 -0500
@@ -73,7 +73,6 @@
  *       Undo the partial store in this case.
  */
 #include <linux/mm.h>
-#include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
 #include <linux/sched.h>
diff -druN linux-libre-3.1-gnu/arch/mips/kernel/vpe.c linux-libre-3.2-gnu/arch/mips/kernel/vpe.c
--- linux-libre-3.1-gnu/arch/mips/kernel/vpe.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/kernel/vpe.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/device.h>
-#include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
diff -druN linux-libre-3.1-gnu/arch/mips/lantiq/clk.c linux-libre-3.2-gnu/arch/mips/lantiq/clk.c
--- linux-libre-3.1-gnu/arch/mips/lantiq/clk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/lantiq/clk.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  */
 #include <linux/io.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
diff -druN linux-libre-3.1-gnu/arch/mips/lantiq/devices.c linux-libre-3.2-gnu/arch/mips/lantiq/devices.c
--- linux-libre-3.1-gnu/arch/mips/lantiq/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/lantiq/devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
diff -druN linux-libre-3.1-gnu/arch/mips/lantiq/prom.c linux-libre-3.2-gnu/arch/mips/lantiq/prom.c
--- linux-libre-3.1-gnu/arch/mips/lantiq/prom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/lantiq/prom.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
  * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/clk.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
diff -druN linux-libre-3.1-gnu/arch/mips/lantiq/setup.c linux-libre-3.2-gnu/arch/mips/lantiq/setup.c
--- linux-libre-3.1-gnu/arch/mips/lantiq/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/lantiq/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <asm/bootinfo.h>
diff -druN linux-libre-3.1-gnu/arch/mips/lantiq/xway/clk-ase.c linux-libre-3.2-gnu/arch/mips/lantiq/xway/clk-ase.c
--- linux-libre-3.1-gnu/arch/mips/lantiq/xway/clk-ase.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/lantiq/xway/clk-ase.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  */
 
 #include <linux/io.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/clk.h>
 
diff -druN linux-libre-3.1-gnu/arch/mips/lantiq/xway/clk-xway.c linux-libre-3.2-gnu/arch/mips/lantiq/xway/clk-xway.c
--- linux-libre-3.1-gnu/arch/mips/lantiq/xway/clk-xway.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/lantiq/xway/clk-xway.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  */
 
 #include <linux/io.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/clk.h>
 
diff -druN linux-libre-3.1-gnu/arch/mips/lantiq/xway/devices.c linux-libre-3.2-gnu/arch/mips/lantiq/xway/devices.c
--- linux-libre-3.1-gnu/arch/mips/lantiq/xway/devices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/lantiq/xway/devices.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/mtd/physmap.h>
diff -druN linux-libre-3.1-gnu/arch/mips/lantiq/xway/dma.c linux-libre-3.2-gnu/arch/mips/lantiq/xway/dma.c
--- linux-libre-3.1-gnu/arch/mips/lantiq/xway/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/lantiq/xway/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 
 #include <lantiq_soc.h>
 #include <xway_dma.h>
diff -druN linux-libre-3.1-gnu/arch/mips/lantiq/xway/gpio.c linux-libre-3.2-gnu/arch/mips/lantiq/xway/gpio.c
--- linux-libre-3.1-gnu/arch/mips/lantiq/xway/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/lantiq/xway/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  */
 
 #include <linux/slab.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/ioport.h>
diff -druN linux-libre-3.1-gnu/arch/mips/lantiq/xway/gpio_ebu.c linux-libre-3.2-gnu/arch/mips/lantiq/xway/gpio_ebu.c
--- linux-libre-3.1-gnu/arch/mips/lantiq/xway/gpio_ebu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/lantiq/xway/gpio_ebu.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
diff -druN linux-libre-3.1-gnu/arch/mips/lantiq/xway/gpio_stp.c linux-libre-3.2-gnu/arch/mips/lantiq/xway/gpio_stp.c
--- linux-libre-3.1-gnu/arch/mips/lantiq/xway/gpio_stp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/lantiq/xway/gpio_stp.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
 
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
diff -druN linux-libre-3.1-gnu/arch/mips/lantiq/xway/prom-ase.c linux-libre-3.2-gnu/arch/mips/lantiq/xway/prom-ase.c
--- linux-libre-3.1-gnu/arch/mips/lantiq/xway/prom-ase.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/lantiq/xway/prom-ase.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
  *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/clk.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
diff -druN linux-libre-3.1-gnu/arch/mips/lantiq/xway/prom-xway.c linux-libre-3.2-gnu/arch/mips/lantiq/xway/prom-xway.c
--- linux-libre-3.1-gnu/arch/mips/lantiq/xway/prom-xway.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/lantiq/xway/prom-xway.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
  *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/clk.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
diff -druN linux-libre-3.1-gnu/arch/mips/lantiq/xway/reset.c linux-libre-3.2-gnu/arch/mips/lantiq/xway/reset.c
--- linux-libre-3.1-gnu/arch/mips/lantiq/xway/reset.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/lantiq/xway/reset.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/pm.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/reboot.h>
 
 #include <lantiq_soc.h>
diff -druN linux-libre-3.1-gnu/arch/mips/loongson/common/platform.c linux-libre-3.2-gnu/arch/mips/loongson/common/platform.c
--- linux-libre-3.1-gnu/arch/mips/loongson/common/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/loongson/common/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include <linux/err.h>
+#include <linux/smp.h>
 #include <linux/platform_device.h>
 
 static struct platform_device loongson2_cpufreq_device = {
diff -druN linux-libre-3.1-gnu/arch/mips/Makefile linux-libre-3.2-gnu/arch/mips/Makefile
--- linux-libre-3.1-gnu/arch/mips/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -226,7 +226,7 @@
 ifdef CONFIG_MIPS
 CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -xc /dev/null | \
 	egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \
-	sed -e 's/^\#define /-D/' -e "s/ /='/" -e "s/$$/'/")
+	sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/")
 ifdef CONFIG_64BIT
 CHECKFLAGS		+= -m64
 endif
@@ -286,16 +286,18 @@
 archprepare:
 ifdef CONFIG_MIPS32_N32
 	@echo '  Checking missing-syscalls for N32'
-	$(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=n32"
+	$(Q)$(MAKE) $(build)=. missing-syscalls missing_syscalls_flags="-mabi=n32"
 endif
 ifdef CONFIG_MIPS32_O32
 	@echo '  Checking missing-syscalls for O32'
-	$(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=32"
+	$(Q)$(MAKE) $(build)=. missing-syscalls missing_syscalls_flags="-mabi=32"
 endif
 
 install:
 	$(Q)install -D -m 755 vmlinux $(INSTALL_PATH)/vmlinux-$(KERNELRELEASE)
+ifdef CONFIG_SYS_SUPPORTS_ZBOOT
 	$(Q)install -D -m 755 vmlinuz $(INSTALL_PATH)/vmlinuz-$(KERNELRELEASE)
+endif
 	$(Q)install -D -m 644 .config $(INSTALL_PATH)/config-$(KERNELRELEASE)
 	$(Q)install -D -m 644 System.map $(INSTALL_PATH)/System.map-$(KERNELRELEASE)
 
diff -druN linux-libre-3.1-gnu/arch/mips/mm/cache.c linux-libre-3.2-gnu/arch/mips/mm/cache.c
--- linux-libre-3.1-gnu/arch/mips/mm/cache.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/mm/cache.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,11 @@
 void (*__flush_cache_vmap)(void);
 void (*__flush_cache_vunmap)(void);
 
+void (*__flush_kernel_vmap_range)(unsigned long vaddr, int size);
+void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size);
+
+EXPORT_SYMBOL_GPL(__flush_kernel_vmap_range);
+
 /* MIPS specific cache operations */
 void (*flush_cache_sigtramp)(unsigned long addr);
 void (*local_flush_data_cache_page)(void * addr);
diff -druN linux-libre-3.1-gnu/arch/mips/mm/c-octeon.c linux-libre-3.2-gnu/arch/mips/mm/c-octeon.c
--- linux-libre-3.1-gnu/arch/mips/mm/c-octeon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/mm/c-octeon.c	2012-01-04 18:55:44.000000000 -0500
@@ -169,6 +169,10 @@
 		octeon_flush_icache_all_cores(vma);
 }
 
+static void octeon_flush_kernel_vmap_range(unsigned long vaddr, int size)
+{
+	BUG();
+}
 
 /**
  * Probe Octeon's caches
@@ -273,6 +277,8 @@
 	flush_icache_range		= octeon_flush_icache_range;
 	local_flush_icache_range	= local_octeon_flush_icache_range;
 
+	__flush_kernel_vmap_range	= octeon_flush_kernel_vmap_range;
+
 	build_clear_page();
 	build_copy_page();
 }
diff -druN linux-libre-3.1-gnu/arch/mips/mm/c-r3k.c linux-libre-3.2-gnu/arch/mips/mm/c-r3k.c
--- linux-libre-3.1-gnu/arch/mips/mm/c-r3k.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/mm/c-r3k.c	2012-01-04 18:55:44.000000000 -0500
@@ -299,6 +299,11 @@
 	write_c0_status(flags);
 }
 
+static void r3k_flush_kernel_vmap_range(unsigned long vaddr, int size)
+{
+	BUG();
+}
+
 static void r3k_dma_cache_wback_inv(unsigned long start, unsigned long size)
 {
 	/* Catch bad driver code */
@@ -323,6 +328,8 @@
 	flush_icache_range = r3k_flush_icache_range;
 	local_flush_icache_range = r3k_flush_icache_range;
 
+	__flush_kernel_vmap_range = r3k_flush_kernel_vmap_range;
+
 	flush_cache_sigtramp = r3k_flush_cache_sigtramp;
 	local_flush_data_cache_page = local_r3k_flush_data_cache_page;
 	flush_data_cache_page = r3k_flush_data_cache_page;
diff -druN linux-libre-3.1-gnu/arch/mips/mm/c-r4k.c linux-libre-3.2-gnu/arch/mips/mm/c-r4k.c
--- linux-libre-3.1-gnu/arch/mips/mm/c-r4k.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/mm/c-r4k.c	2012-01-04 18:55:44.000000000 -0500
@@ -722,6 +722,39 @@
 		r4k_blast_icache();
 }
 
+struct flush_kernel_vmap_range_args {
+	unsigned long	vaddr;
+	int		size;
+};
+
+static inline void local_r4k_flush_kernel_vmap_range(void *args)
+{
+	struct flush_kernel_vmap_range_args *vmra = args;
+	unsigned long vaddr = vmra->vaddr;
+	int size = vmra->size;
+
+	/*
+	 * Aliases only affect the primary caches so don't bother with
+	 * S-caches or T-caches.
+	 */
+	if (cpu_has_safe_index_cacheops && size >= dcache_size)
+		r4k_blast_dcache();
+	else {
+		R4600_HIT_CACHEOP_WAR_IMPL;
+		blast_dcache_range(vaddr, vaddr + size);
+	}
+}
+
+static void r4k_flush_kernel_vmap_range(unsigned long vaddr, int size)
+{
+	struct flush_kernel_vmap_range_args args;
+
+	args.vaddr = (unsigned long) vaddr;
+	args.size = size;
+
+	r4k_on_each_cpu(local_r4k_flush_kernel_vmap_range, &args);
+}
+
 static inline void rm7k_erratum31(void)
 {
 	const unsigned long ic_lsize = 32;
@@ -1403,6 +1436,8 @@
 	flush_cache_page	= r4k_flush_cache_page;
 	flush_cache_range	= r4k_flush_cache_range;
 
+	__flush_kernel_vmap_range = r4k_flush_kernel_vmap_range;
+
 	flush_cache_sigtramp	= r4k_flush_cache_sigtramp;
 	flush_icache_all	= r4k_flush_icache_all;
 	local_flush_data_cache_page	= local_r4k_flush_data_cache_page;
diff -druN linux-libre-3.1-gnu/arch/mips/mm/c-tx39.c linux-libre-3.2-gnu/arch/mips/mm/c-tx39.c
--- linux-libre-3.1-gnu/arch/mips/mm/c-tx39.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/mm/c-tx39.c	2012-01-04 18:55:44.000000000 -0500
@@ -253,6 +253,11 @@
 	}
 }
 
+static void tx39_flush_kernel_vmap_range(unsigned long vaddr, int size)
+{
+	BUG();
+}
+
 static void tx39_dma_cache_wback_inv(unsigned long addr, unsigned long size)
 {
 	unsigned long end;
@@ -394,6 +399,8 @@
 		flush_icache_range = tx39_flush_icache_range;
 		local_flush_icache_range = tx39_flush_icache_range;
 
+		__flush_kernel_vmap_range = tx39_flush_kernel_vmap_range;
+
 		flush_cache_sigtramp = tx39_flush_cache_sigtramp;
 		local_flush_data_cache_page = local_tx39_flush_data_cache_page;
 		flush_data_cache_page = tx39_flush_data_cache_page;
diff -druN linux-libre-3.1-gnu/arch/mips/mm/tlb-r3k.c linux-libre-3.2-gnu/arch/mips/mm/tlb-r3k.c
--- linux-libre-3.1-gnu/arch/mips/mm/tlb-r3k.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/mm/tlb-r3k.c	2012-01-04 18:55:44.000000000 -0500
@@ -223,8 +223,8 @@
 	local_irq_restore(flags);
 }
 
-void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
-			    unsigned long entryhi, unsigned long pagemask)
+void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
+		     unsigned long entryhi, unsigned long pagemask)
 {
 	unsigned long flags;
 	unsigned long old_ctx;
diff -druN linux-libre-3.1-gnu/arch/mips/mm/tlb-r4k.c linux-libre-3.2-gnu/arch/mips/mm/tlb-r4k.c
--- linux-libre-3.1-gnu/arch/mips/mm/tlb-r4k.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/mm/tlb-r4k.c	2012-01-04 18:55:44.000000000 -0500
@@ -337,8 +337,8 @@
 	EXIT_CRITICAL(flags);
 }
 
-void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
-	unsigned long entryhi, unsigned long pagemask)
+void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
+		     unsigned long entryhi, unsigned long pagemask)
 {
 	unsigned long flags;
 	unsigned long wired;
diff -druN linux-libre-3.1-gnu/arch/mips/netlogic/Platform linux-libre-3.2-gnu/arch/mips/netlogic/Platform
--- linux-libre-3.1-gnu/arch/mips/netlogic/Platform	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/netlogic/Platform	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,11 @@
 cflags-$(CONFIG_NLM_COMMON)  += -I$(srctree)/arch/mips/include/asm/netlogic
 
 #
+# use mips64 if xlr is not available
+#
+cflags-$(CONFIG_NLM_XLR)	+= $(call cc-option,-march=xlr,-march=mips64)
+
+#
 # NETLOGIC XLR/XLS SoC, Simulator and boards
 #
 core-$(CONFIG_NLM_XLR)	      += arch/mips/netlogic/xlr/
diff -druN linux-libre-3.1-gnu/arch/mips/netlogic/xlr/setup.c linux-libre-3.2-gnu/arch/mips/netlogic/xlr/setup.c
--- linux-libre-3.1-gnu/arch/mips/netlogic/xlr/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/netlogic/xlr/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -53,7 +53,7 @@
 unsigned long nlm_common_ebase = 0x0;
 struct psb_info nlm_prom_info;
 
-static void nlm_early_serial_setup(void)
+static void __init nlm_early_serial_setup(void)
 {
 	struct uart_port s;
 	nlm_reg_t *uart_base;
@@ -101,7 +101,7 @@
 	/* Nothing yet */
 }
 
-static void build_arcs_cmdline(int *argv)
+static void __init build_arcs_cmdline(int *argv)
 {
 	int i, remain, len;
 	char *arg;
diff -druN linux-libre-3.1-gnu/arch/mips/netlogic/xlr/smpboot.S linux-libre-3.2-gnu/arch/mips/netlogic/xlr/smpboot.S
--- linux-libre-3.1-gnu/arch/mips/netlogic/xlr/smpboot.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/netlogic/xlr/smpboot.S	2012-01-04 18:55:44.000000000 -0500
@@ -32,17 +32,19 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <linux/init.h>
+
 #include <asm/asm.h>
 #include <asm/asm-offsets.h>
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
 
-
-/* Don't jump to linux function from Bootloader stack. Change it
- * here. Kernel might allocate bootloader memory before all the CPUs are
- * brought up (eg: Inode cache region) and we better don't overwrite this
- * memory
+/*
+ * Early code for secondary CPUs. This will get them out of the bootloader
+ * code and into linux. Needed because the bootloader area will be taken
+ * and initialized by linux.
  */
+	__CPUINIT
 NESTED(prom_pre_boot_secondary_cpus, 16, sp)
 	.set	mips64
 	mfc0	t0, $15, 1	# read ebase
@@ -73,7 +75,11 @@
 	jr	t0
 	nop
 END(prom_pre_boot_secondary_cpus)
+	__FINIT
 
+/*
+ * NMI code, used for CPU wakeup, copied to reset entry
+ */
 NESTED(nlm_boot_smp_nmi, 0, sp)
 	.set push
 	.set noat
diff -druN linux-libre-3.1-gnu/arch/mips/netlogic/xlr/smp.c linux-libre-3.2-gnu/arch/mips/netlogic/xlr/smp.c
--- linux-libre-3.1-gnu/arch/mips/netlogic/xlr/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/netlogic/xlr/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -158,6 +158,10 @@
 
 	num_cpus = 1;
 	for (i = 0; i < NR_CPUS; i++) {
+		/*
+		 * BSP is not set in nlm_cpu_ready array, it is only for
+		 * ASPs (goto see smpboot.S)
+		 */
 		if (nlm_cpu_ready[i]) {
 			cpu_set(i, phys_cpu_present_map);
 			__cpu_number_map[i] = num_cpus;
@@ -191,7 +195,7 @@
 
 unsigned long secondary_entry_point;
 
-int nlm_wakeup_secondary_cpus(u32 wakeup_mask)
+int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask)
 {
 	unsigned int tid, pid, ipi, i, boot_cpu;
 	void *reset_vec;
diff -druN linux-libre-3.1-gnu/arch/mips/nxp/pnx8550/common/pci.c linux-libre-3.2-gnu/arch/mips/nxp/pnx8550/common/pci.c
--- linux-libre-3.1-gnu/arch/mips/nxp/pnx8550/common/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/nxp/pnx8550/common/pci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,134 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *
- * Author: source@mvista.com
- *
- *  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/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <pci.h>
-#include <glb.h>
-#include <nand.h>
-
-static struct resource pci_io_resource = {
-	.start	= PNX8550_PCIIO + 0x1000,	/* reserve regacy I/O space */
-	.end	= PNX8550_PCIIO + PNX8550_PCIIO_SIZE,
-	.name	= "pci IO space",
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource pci_mem_resource = {
-	.start	= PNX8550_PCIMEM,
-	.end	= PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1,
-	.name	= "pci memory space",
-	.flags	= IORESOURCE_MEM
-};
-
-extern struct pci_ops pnx8550_pci_ops;
-
-static struct pci_controller pnx8550_controller = {
-	.pci_ops	= &pnx8550_pci_ops,
-	.io_map_base	= PNX8550_PORT_BASE,
-	.io_resource	= &pci_io_resource,
-	.mem_resource	= &pci_mem_resource,
-};
-
-/* Return the total size of DRAM-memory, (RANK0 + RANK1) */
-static inline unsigned long get_system_mem_size(void)
-{
-	/* Read IP2031_RANK0_ADDR_LO */
-	unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010);
-	/* Read IP2031_RANK1_ADDR_HI */
-	unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018);
-
-	return dram_r1_hi - dram_r0_lo + 1;
-}
-
-static int __init pnx8550_pci_setup(void)
-{
-	int pci_mem_code;
-	int mem_size = get_system_mem_size() >> 20;
-
-	/* Clear the Global 2 Register, PCI Inta Output Enable Registers
-	   Bit 1:Enable DAC Powerdown
-	  -> 0:DACs are enabled and are working normally
-	     1:DACs are powerdown
-	   Bit 0:Enable of PCI inta output
-	  -> 0 = Disable PCI inta output
-	     1 = Enable PCI inta output
-	*/
-	PNX8550_GLB2_ENAB_INTA_O = 0;
-
-	/* Calc the PCI mem size code */
-	if (mem_size >= 128)
-		pci_mem_code = SIZE_128M;
-	else if (mem_size >= 64)
-		pci_mem_code = SIZE_64M;
-	else if (mem_size >= 32)
-		pci_mem_code = SIZE_32M;
-	else
-		pci_mem_code = SIZE_16M;
-
-	/* Set PCI_XIO registers */
-	outl(pci_mem_resource.start, PCI_BASE | PCI_BASE1_LO);
-	outl(pci_mem_resource.end + 1, PCI_BASE | PCI_BASE1_HI);
-	outl(pci_io_resource.start, PCI_BASE | PCI_BASE2_LO);
-	outl(pci_io_resource.end, PCI_BASE | PCI_BASE2_HI);
-
-	/* Send memory transaction via PCI_BASE2 */
-	outl(0x00000001, PCI_BASE | PCI_IO);
-
-	/* Unlock the setup register */
-	outl(0xca, PCI_BASE | PCI_UNLOCKREG);
-
-	/*
-	 * BAR0 of PNX8550 (pci base 10) must be zero in order for ide
-	 * to work, and in order for bus_to_baddr to work without any
-	 * hacks.
-	 */
-	outl(0x00000000, PCI_BASE | PCI_BASE10);
-
-	/*
-	 *These two bars are set by default or the boot code.
-	 * However, it's safer to set them here so we're not boot
-	 * code dependent.
-	 */
-	outl(0x1be00000, PCI_BASE | PCI_BASE14);  /* PNX MMIO */
-	outl(PNX8550_NAND_BASE_ADDR, PCI_BASE | PCI_BASE18);  /* XIO      */
-
-	outl(PCI_EN_TA |
-	     PCI_EN_PCI2MMI |
-	     PCI_EN_XIO |
-	     PCI_SETUP_BASE18_SIZE(SIZE_32M) |
-	     PCI_SETUP_BASE18_EN |
-	     PCI_SETUP_BASE14_EN |
-	     PCI_SETUP_BASE10_PREF |
-	     PCI_SETUP_BASE10_SIZE(pci_mem_code) |
-	     PCI_SETUP_CFGMANAGE_EN |
-	     PCI_SETUP_PCIARB_EN,
-	     PCI_BASE |
-	     PCI_SETUP);	/* PCI_SETUP */
-	outl(0x00000000, PCI_BASE | PCI_CTRL);	/* PCI_CONTROL */
-
-	register_pci_controller(&pnx8550_controller);
-
-	return 0;
-}
-
-arch_initcall(pnx8550_pci_setup);
diff -druN linux-libre-3.1-gnu/arch/mips/nxp/pnx8550/common/setup.c linux-libre-3.2-gnu/arch/mips/nxp/pnx8550/common/setup.c
--- linux-libre-3.1-gnu/arch/mips/nxp/pnx8550/common/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/nxp/pnx8550/common/setup.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,143 +0,0 @@
-/*
- *
- * 2.6 port, Embedded Alley Solutions, Inc
- *
- *  Based on Per Hallsmark, per.hallsmark@mvista.com
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/serial_pnx8xxx.h>
-#include <linux/pm.h>
-
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/reboot.h>
-#include <asm/pgtable.h>
-#include <asm/time.h>
-
-#include <glb.h>
-#include <int.h>
-#include <pci.h>
-#include <uart.h>
-#include <nand.h>
-
-extern void __init board_setup(void);
-extern void pnx8550_machine_restart(char *);
-extern void pnx8550_machine_halt(void);
-extern void pnx8550_machine_power_off(void);
-extern struct resource ioport_resource;
-extern struct resource iomem_resource;
-extern char *prom_getcmdline(void);
-
-struct resource standard_io_resources[] = {
-	{
-		.start	= 0x00,
-		.end	= 0x1f,
-		.name	= "dma1",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0x40,
-		.end	= 0x5f,
-		.name	= "timer",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0x80,
-		.end	= 0x8f,
-		.name	= "dma page reg",
-		.flags	= IORESOURCE_BUSY
-	}, {
-		.start	= 0xc0,
-		.end	= 0xdf,
-		.name	= "dma2",
-		.flags	= IORESOURCE_BUSY
-	},
-};
-
-#define STANDARD_IO_RESOURCES ARRAY_SIZE(standard_io_resources)
-
-extern struct resource pci_io_resource;
-extern struct resource pci_mem_resource;
-
-/* Return the total size of DRAM-memory, (RANK0 + RANK1) */
-unsigned long get_system_mem_size(void)
-{
-	/* Read IP2031_RANK0_ADDR_LO */
-	unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010);
-	/* Read IP2031_RANK1_ADDR_HI */
-	unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018);
-
-	return dram_r1_hi - dram_r0_lo + 1;
-}
-
-int pnx8550_console_port = -1;
-
-void __init plat_mem_setup(void)
-{
-	int i;
-	char* argptr;
-
-	board_setup();  /* board specific setup */
-
-        _machine_restart = pnx8550_machine_restart;
-        _machine_halt = pnx8550_machine_halt;
-        pm_power_off = pnx8550_machine_power_off;
-
-	/* Clear the Global 2 Register, PCI Inta Output Enable Registers
-	   Bit 1:Enable DAC Powerdown
-	  -> 0:DACs are enabled and are working normally
-	     1:DACs are powerdown
-	   Bit 0:Enable of PCI inta output
-	  -> 0 = Disable PCI inta output
-	     1 = Enable PCI inta output
-	*/
-	PNX8550_GLB2_ENAB_INTA_O = 0;
-
-	/* IO/MEM resources. */
-	set_io_port_base(PNX8550_PORT_BASE);
-	ioport_resource.start = 0;
-	ioport_resource.end = ~0;
-	iomem_resource.start = 0;
-	iomem_resource.end = ~0;
-
-	/* Request I/O space for devices on this board */
-	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
-		request_resource(&ioport_resource, standard_io_resources + i);
-
-	/* Place the Mode Control bit for GPIO pin 16 in primary function */
-	/* Pin 16 is used by UART1, UA1_TX                                */
-	outl((PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_16_BIT) |
-			(PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_17_BIT),
-			PNX8550_GPIO_MC1);
-
-	argptr = prom_getcmdline();
-	if ((argptr = strstr(argptr, "console=ttyS")) != NULL) {
-		argptr += strlen("console=ttyS");
-		pnx8550_console_port = *argptr == '0' ? 0 : 1;
-
-		/* We must initialize the UART (console) before early printk */
-		/* Set LCR to 8-bit and BAUD to 38400 (no 5)                */
-		ip3106_lcr(UART_BASE, pnx8550_console_port) =
-			PNX8XXX_UART_LCR_8BIT;
-		ip3106_baud(UART_BASE, pnx8550_console_port) = 5;
-	}
-}
diff -druN linux-libre-3.1-gnu/arch/mips/pci/fixup-au1000.c linux-libre-3.2-gnu/arch/mips/pci/fixup-au1000.c
--- linux-libre-3.1-gnu/arch/mips/pci/fixup-au1000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/pci/fixup-au1000.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Board specific PCI fixups.
- *
- * Copyright 2001-2003, 2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-
-extern char irq_tab_alchemy[][5];
-
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	return irq_tab_alchemy[slot][pin];
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/arch/mips/pci/Makefile linux-libre-3.2-gnu/arch/mips/pci/Makefile
--- linux-libre-3.1-gnu/arch/mips/pci/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/pci/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -18,14 +18,13 @@
 obj-$(CONFIG_BCM47XX)		+= pci-bcm47xx.o
 obj-$(CONFIG_BCM63XX)		+= pci-bcm63xx.o fixup-bcm63xx.o \
 					ops-bcm63xx.o
+obj-$(CONFIG_MIPS_ALCHEMY)	+= pci-alchemy.o
 
 #
 # These are still pretty much in the old state, watch, go blind.
 #
 obj-$(CONFIG_LASAT)		+= pci-lasat.o
 obj-$(CONFIG_MIPS_COBALT)	+= fixup-cobalt.o
-obj-$(CONFIG_SOC_AU1500)	+= fixup-au1000.o ops-au1000.o
-obj-$(CONFIG_SOC_AU1550)	+= fixup-au1000.o ops-au1000.o
 obj-$(CONFIG_SOC_PNX8550)	+= fixup-pnx8550.o ops-pnx8550.o
 obj-$(CONFIG_LEMOTE_FULOONG2E)	+= fixup-fuloong2e.o ops-loongson2.o
 obj-$(CONFIG_LEMOTE_MACH2F)	+= fixup-lemote2f.o ops-loongson2.o
diff -druN linux-libre-3.1-gnu/arch/mips/pci/ops-au1000.c linux-libre-3.2-gnu/arch/mips/pci/ops-au1000.c
--- linux-libre-3.1-gnu/arch/mips/pci/ops-au1000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/pci/ops-au1000.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,308 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Alchemy/AMD Au1xx0 PCI support.
- *
- * Copyright 2001-2003, 2007-2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- *  Support for all devices (greater than 16) added by David Gathright.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU 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/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/vmalloc.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-#undef	DEBUG
-#ifdef	DEBUG
-#define DBG(x...) printk(KERN_DEBUG x)
-#else
-#define DBG(x...)
-#endif
-
-#define PCI_ACCESS_READ  0
-#define PCI_ACCESS_WRITE 1
-
-int (*board_pci_idsel)(unsigned int devsel, int assert);
-
-void mod_wired_entry(int entry, unsigned long entrylo0,
-		unsigned long entrylo1, unsigned long entryhi,
-		unsigned long pagemask)
-{
-	unsigned long old_pagemask;
-	unsigned long old_ctx;
-
-	/* Save old context and create impossible VPN2 value */
-	old_ctx = read_c0_entryhi() & 0xff;
-	old_pagemask = read_c0_pagemask();
-	write_c0_index(entry);
-	write_c0_pagemask(pagemask);
-	write_c0_entryhi(entryhi);
-	write_c0_entrylo0(entrylo0);
-	write_c0_entrylo1(entrylo1);
-	tlb_write_indexed();
-	write_c0_entryhi(old_ctx);
-	write_c0_pagemask(old_pagemask);
-}
-
-static struct vm_struct *pci_cfg_vm;
-static int pci_cfg_wired_entry;
-static unsigned long last_entryLo0, last_entryLo1;
-
-/*
- * We can't ioremap the entire pci config space because it's too large.
- * Nor can we call ioremap dynamically because some device drivers use
- * the PCI config routines from within interrupt handlers and that
- * becomes a problem in get_vm_area().  We use one wired TLB to handle
- * all config accesses for all busses.
- */
-void __init au1x_pci_cfg_init(void)
-{
-	/* Reserve a wired entry for PCI config accesses */
-	pci_cfg_vm = get_vm_area(0x2000, VM_IOREMAP);
-	if (!pci_cfg_vm)
-		panic(KERN_ERR "PCI unable to get vm area\n");
-	pci_cfg_wired_entry = read_c0_wired();
-	add_wired_entry(0, 0, (unsigned long)pci_cfg_vm->addr, PM_4K);
-	last_entryLo0 = last_entryLo1 = 0xffffffff;
-}
-
-static int config_access(unsigned char access_type, struct pci_bus *bus,
-			 unsigned int dev_fn, unsigned char where, u32 *data)
-{
-#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
-	unsigned int device = PCI_SLOT(dev_fn);
-	unsigned int function = PCI_FUNC(dev_fn);
-	unsigned long offset, status;
-	unsigned long cfg_base;
-	unsigned long flags;
-	int error = PCIBIOS_SUCCESSFUL;
-	unsigned long entryLo0, entryLo1;
-
-	if (device > 19) {
-		*data = 0xffffffff;
-		return -1;
-	}
-
-	local_irq_save(flags);
-	au_writel(((0x2000 << 16) | (au_readl(Au1500_PCI_STATCMD) & 0xffff)),
-			Au1500_PCI_STATCMD);
-	au_sync_udelay(1);
-
-	/*
-	 * Allow board vendors to implement their own off-chip IDSEL.
-	 * If it doesn't succeed, may as well bail out at this point.
-	 */
-	if (board_pci_idsel && board_pci_idsel(device, 1) == 0) {
-		*data = 0xffffffff;
-		local_irq_restore(flags);
-		return -1;
-	}
-
-	/* Setup the config window */
-	if (bus->number == 0)
-		cfg_base = (1 << device) << 11;
-	else
-		cfg_base = 0x80000000 | (bus->number << 16) | (device << 11);
-
-	/* Setup the lower bits of the 36-bit address */
-	offset = (function << 8) | (where & ~0x3);
-	/* Pick up any address that falls below the page mask */
-	offset |= cfg_base & ~PAGE_MASK;
-
-	/* Page boundary */
-	cfg_base = cfg_base & PAGE_MASK;
-
-	/*
-	 * To improve performance, if the current device is the same as
-	 * the last device accessed, we don't touch the TLB.
-	 */
-	entryLo0 = (6 << 26) | (cfg_base >> 6) | (2 << 3) | 7;
-	entryLo1 = (6 << 26) | (cfg_base >> 6) | (0x1000 >> 6) | (2 << 3) | 7;
-	if ((entryLo0 != last_entryLo0) || (entryLo1 != last_entryLo1)) {
-		mod_wired_entry(pci_cfg_wired_entry, entryLo0, entryLo1,
-				(unsigned long)pci_cfg_vm->addr, PM_4K);
-		last_entryLo0 = entryLo0;
-		last_entryLo1 = entryLo1;
-	}
-
-	if (access_type == PCI_ACCESS_WRITE)
-		au_writel(*data, (int)(pci_cfg_vm->addr + offset));
-	else
-		*data = au_readl((int)(pci_cfg_vm->addr + offset));
-
-	au_sync_udelay(2);
-
-	DBG("cfg_access %d bus->number %u dev %u at %x *data %x conf %lx\n",
-	    access_type, bus->number, device, where, *data, offset);
-
-	/* Check master abort */
-	status = au_readl(Au1500_PCI_STATCMD);
-
-	if (status & (1 << 29)) {
-		*data = 0xffffffff;
-		error = -1;
-		DBG("Au1x Master Abort\n");
-	} else if ((status >> 28) & 0xf) {
-		DBG("PCI ERR detected: device %u, status %lx\n",
-		    device, (status >> 28) & 0xf);
-
-		/* Clear errors */
-		au_writel(status & 0xf000ffff, Au1500_PCI_STATCMD);
-
-		*data = 0xffffffff;
-		error = -1;
-	}
-
-	/* Take away the IDSEL. */
-	if (board_pci_idsel)
-		(void)board_pci_idsel(device, 0);
-
-	local_irq_restore(flags);
-	return error;
-#endif
-}
-
-static int read_config_byte(struct pci_bus *bus, unsigned int devfn,
-			    int where,	u8 *val)
-{
-	u32 data;
-	int ret;
-
-	ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
-	if (where & 1)
-		data >>= 8;
-	if (where & 2)
-		data >>= 16;
-	*val = data & 0xff;
-	return ret;
-}
-
-static int read_config_word(struct pci_bus *bus, unsigned int devfn,
-			    int where, u16 *val)
-{
-	u32 data;
-	int ret;
-
-	ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
-	if (where & 2)
-		data >>= 16;
-	*val = data & 0xffff;
-	return ret;
-}
-
-static int read_config_dword(struct pci_bus *bus, unsigned int devfn,
-			     int where, u32 *val)
-{
-	int ret;
-
-	ret = config_access(PCI_ACCESS_READ, bus, devfn, where, val);
-	return ret;
-}
-
-static int write_config_byte(struct pci_bus *bus, unsigned int devfn,
-			     int where, u8 val)
-{
-	u32 data = 0;
-
-	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
-		return -1;
-
-	data = (data & ~(0xff << ((where & 3) << 3))) |
-	       (val << ((where & 3) << 3));
-
-	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
-		return -1;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int write_config_word(struct pci_bus *bus, unsigned int devfn,
-			     int where, u16 val)
-{
-	u32 data = 0;
-
-	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
-		return -1;
-
-	data = (data & ~(0xffff << ((where & 3) << 3))) |
-	       (val << ((where & 3) << 3));
-
-	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
-		return -1;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int write_config_dword(struct pci_bus *bus, unsigned int devfn,
-			      int where, u32 val)
-{
-	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val))
-		return -1;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int config_read(struct pci_bus *bus, unsigned int devfn,
-		       int where, int size, u32 *val)
-{
-	switch (size) {
-	case 1: {
-			u8 _val;
-			int rc = read_config_byte(bus, devfn, where, &_val);
-
-			*val = _val;
-			return rc;
-		}
-	case 2: {
-			u16 _val;
-			int rc = read_config_word(bus, devfn, where, &_val);
-
-			*val = _val;
-			return rc;
-		}
-	default:
-		return read_config_dword(bus, devfn, where, val);
-	}
-}
-
-static int config_write(struct pci_bus *bus, unsigned int devfn,
-			int where, int size, u32 val)
-{
-	switch (size) {
-	case 1:
-		return write_config_byte(bus, devfn, where, (u8) val);
-	case 2:
-		return write_config_word(bus, devfn, where, (u16) val);
-	default:
-		return write_config_dword(bus, devfn, where, val);
-	}
-}
-
-struct pci_ops au1x_pci_ops = {
-	config_read,
-	config_write
-};
diff -druN linux-libre-3.1-gnu/arch/mips/pci/pci-alchemy.c linux-libre-3.2-gnu/arch/mips/pci/pci-alchemy.c
--- linux-libre-3.1-gnu/arch/mips/pci/pci-alchemy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/mips/pci/pci-alchemy.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,517 @@
+/*
+ * Alchemy PCI host mode support.
+ *
+ * Copyright 2001-2003, 2007-2008 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc. <source@mvista.com>
+ *
+ * Support for all devices (greater than 16) added by David Gathright.
+ */
+
+#include <linux/export.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+
+#include <asm/mach-au1x00/au1000.h>
+
+#ifdef CONFIG_DEBUG_PCI
+#define DBG(x...) printk(KERN_DEBUG x)
+#else
+#define DBG(x...) do {} while (0)
+#endif
+
+#define PCI_ACCESS_READ		0
+#define PCI_ACCESS_WRITE	1
+
+struct alchemy_pci_context {
+	struct pci_controller alchemy_pci_ctrl;	/* leave as first member! */
+	void __iomem *regs;			/* ctrl base */
+	/* tools for wired entry for config space access */
+	unsigned long last_elo0;
+	unsigned long last_elo1;
+	int wired_entry;
+	struct vm_struct *pci_cfg_vm;
+
+	unsigned long pm[12];
+
+	int (*board_map_irq)(const struct pci_dev *d, u8 slot, u8 pin);
+	int (*board_pci_idsel)(unsigned int devsel, int assert);
+};
+
+/* IO/MEM resources for PCI. Keep the memres in sync with __fixup_bigphys_addr
+ * in arch/mips/alchemy/common/setup.c
+ */
+static struct resource alchemy_pci_def_memres = {
+	.start	= ALCHEMY_PCI_MEMWIN_START,
+	.end	= ALCHEMY_PCI_MEMWIN_END,
+	.name	= "PCI memory space",
+	.flags	= IORESOURCE_MEM
+};
+
+static struct resource alchemy_pci_def_iores = {
+	.start	= ALCHEMY_PCI_IOWIN_START,
+	.end	= ALCHEMY_PCI_IOWIN_END,
+	.name	= "PCI IO space",
+	.flags	= IORESOURCE_IO
+};
+
+static void mod_wired_entry(int entry, unsigned long entrylo0,
+		unsigned long entrylo1, unsigned long entryhi,
+		unsigned long pagemask)
+{
+	unsigned long old_pagemask;
+	unsigned long old_ctx;
+
+	/* Save old context and create impossible VPN2 value */
+	old_ctx = read_c0_entryhi() & 0xff;
+	old_pagemask = read_c0_pagemask();
+	write_c0_index(entry);
+	write_c0_pagemask(pagemask);
+	write_c0_entryhi(entryhi);
+	write_c0_entrylo0(entrylo0);
+	write_c0_entrylo1(entrylo1);
+	tlb_write_indexed();
+	write_c0_entryhi(old_ctx);
+	write_c0_pagemask(old_pagemask);
+}
+
+static void alchemy_pci_wired_entry(struct alchemy_pci_context *ctx)
+{
+	ctx->wired_entry = read_c0_wired();
+	add_wired_entry(0, 0, (unsigned long)ctx->pci_cfg_vm->addr, PM_4K);
+	ctx->last_elo0 = ctx->last_elo1 = ~0;
+}
+
+static int config_access(unsigned char access_type, struct pci_bus *bus,
+			 unsigned int dev_fn, unsigned char where, u32 *data)
+{
+	struct alchemy_pci_context *ctx = bus->sysdata;
+	unsigned int device = PCI_SLOT(dev_fn);
+	unsigned int function = PCI_FUNC(dev_fn);
+	unsigned long offset, status, cfg_base, flags, entryLo0, entryLo1, r;
+	int error = PCIBIOS_SUCCESSFUL;
+
+	if (device > 19) {
+		*data = 0xffffffff;
+		return -1;
+	}
+
+	/* YAMON on all db1xxx boards wipes the TLB and writes zero to C0_wired
+	 * on resume, clearing our wired entry.  Unfortunately the ->resume()
+	 * callback is called way way way too late (and ->suspend() too early)
+	 * to have them destroy and recreate it.  Instead just test if c0_wired
+	 * is now lower than the index we retrieved before suspending and then
+	 * recreate the entry if necessary.  Of course this is totally bonkers
+	 * and breaks as soon as someone else adds another wired entry somewhere
+	 * else.  Anyone have any ideas how to handle this better?
+	 */
+	if (unlikely(read_c0_wired() < ctx->wired_entry))
+		alchemy_pci_wired_entry(ctx);
+
+	local_irq_save(flags);
+	r = __raw_readl(ctx->regs + PCI_REG_STATCMD) & 0x0000ffff;
+	r |= PCI_STATCMD_STATUS(0x2000);
+	__raw_writel(r, ctx->regs + PCI_REG_STATCMD);
+	wmb();
+
+	/* Allow board vendors to implement their own off-chip IDSEL.
+	 * If it doesn't succeed, may as well bail out at this point.
+	 */
+	if (ctx->board_pci_idsel(device, 1) == 0) {
+		*data = 0xffffffff;
+		local_irq_restore(flags);
+		return -1;
+	}
+
+	/* Setup the config window */
+	if (bus->number == 0)
+		cfg_base = (1 << device) << 11;
+	else
+		cfg_base = 0x80000000 | (bus->number << 16) | (device << 11);
+
+	/* Setup the lower bits of the 36-bit address */
+	offset = (function << 8) | (where & ~0x3);
+	/* Pick up any address that falls below the page mask */
+	offset |= cfg_base & ~PAGE_MASK;
+
+	/* Page boundary */
+	cfg_base = cfg_base & PAGE_MASK;
+
+	/* To improve performance, if the current device is the same as
+	 * the last device accessed, we don't touch the TLB.
+	 */
+	entryLo0 = (6 << 26) | (cfg_base >> 6) | (2 << 3) | 7;
+	entryLo1 = (6 << 26) | (cfg_base >> 6) | (0x1000 >> 6) | (2 << 3) | 7;
+	if ((entryLo0 != ctx->last_elo0) || (entryLo1 != ctx->last_elo1)) {
+		mod_wired_entry(ctx->wired_entry, entryLo0, entryLo1,
+				(unsigned long)ctx->pci_cfg_vm->addr, PM_4K);
+		ctx->last_elo0 = entryLo0;
+		ctx->last_elo1 = entryLo1;
+	}
+
+	if (access_type == PCI_ACCESS_WRITE)
+		__raw_writel(*data, ctx->pci_cfg_vm->addr + offset);
+	else
+		*data = __raw_readl(ctx->pci_cfg_vm->addr + offset);
+	wmb();
+
+	DBG("alchemy-pci: cfg access %d bus %u dev %u at %x dat %x conf %lx\n",
+	    access_type, bus->number, device, where, *data, offset);
+
+	/* check for errors, master abort */
+	status = __raw_readl(ctx->regs + PCI_REG_STATCMD);
+	if (status & (1 << 29)) {
+		*data = 0xffffffff;
+		error = -1;
+		DBG("alchemy-pci: master abort on cfg access %d bus %d dev %d",
+		    access_type, bus->number, device);
+	} else if ((status >> 28) & 0xf) {
+		DBG("alchemy-pci: PCI ERR detected: dev %d, status %lx\n",
+		    device, (status >> 28) & 0xf);
+
+		/* clear errors */
+		__raw_writel(status & 0xf000ffff, ctx->regs + PCI_REG_STATCMD);
+
+		*data = 0xffffffff;
+		error = -1;
+	}
+
+	/* Take away the IDSEL. */
+	(void)ctx->board_pci_idsel(device, 0);
+
+	local_irq_restore(flags);
+	return error;
+}
+
+static int read_config_byte(struct pci_bus *bus, unsigned int devfn,
+			    int where,	u8 *val)
+{
+	u32 data;
+	int ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
+
+	if (where & 1)
+		data >>= 8;
+	if (where & 2)
+		data >>= 16;
+	*val = data & 0xff;
+	return ret;
+}
+
+static int read_config_word(struct pci_bus *bus, unsigned int devfn,
+			    int where, u16 *val)
+{
+	u32 data;
+	int ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
+
+	if (where & 2)
+		data >>= 16;
+	*val = data & 0xffff;
+	return ret;
+}
+
+static int read_config_dword(struct pci_bus *bus, unsigned int devfn,
+			     int where, u32 *val)
+{
+	return config_access(PCI_ACCESS_READ, bus, devfn, where, val);
+}
+
+static int write_config_byte(struct pci_bus *bus, unsigned int devfn,
+			     int where, u8 val)
+{
+	u32 data = 0;
+
+	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
+		return -1;
+
+	data = (data & ~(0xff << ((where & 3) << 3))) |
+	       (val << ((where & 3) << 3));
+
+	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
+		return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int write_config_word(struct pci_bus *bus, unsigned int devfn,
+			     int where, u16 val)
+{
+	u32 data = 0;
+
+	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
+		return -1;
+
+	data = (data & ~(0xffff << ((where & 3) << 3))) |
+	       (val << ((where & 3) << 3));
+
+	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
+		return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int write_config_dword(struct pci_bus *bus, unsigned int devfn,
+			      int where, u32 val)
+{
+	return config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val);
+}
+
+static int alchemy_pci_read(struct pci_bus *bus, unsigned int devfn,
+		       int where, int size, u32 *val)
+{
+	switch (size) {
+	case 1: {
+			u8 _val;
+			int rc = read_config_byte(bus, devfn, where, &_val);
+
+			*val = _val;
+			return rc;
+		}
+	case 2: {
+			u16 _val;
+			int rc = read_config_word(bus, devfn, where, &_val);
+
+			*val = _val;
+			return rc;
+		}
+	default:
+		return read_config_dword(bus, devfn, where, val);
+	}
+}
+
+static int alchemy_pci_write(struct pci_bus *bus, unsigned int devfn,
+			     int where, int size, u32 val)
+{
+	switch (size) {
+	case 1:
+		return write_config_byte(bus, devfn, where, (u8) val);
+	case 2:
+		return write_config_word(bus, devfn, where, (u16) val);
+	default:
+		return write_config_dword(bus, devfn, where, val);
+	}
+}
+
+static struct pci_ops alchemy_pci_ops = {
+	.read	= alchemy_pci_read,
+	.write	= alchemy_pci_write,
+};
+
+static int alchemy_pci_def_idsel(unsigned int devsel, int assert)
+{
+	return 1;	/* success */
+}
+
+static int __devinit alchemy_pci_probe(struct platform_device *pdev)
+{
+	struct alchemy_pci_platdata *pd = pdev->dev.platform_data;
+	struct alchemy_pci_context *ctx;
+	void __iomem *virt_io;
+	unsigned long val;
+	struct resource *r;
+	int ret;
+
+	/* need at least PCI IRQ mapping table */
+	if (!pd) {
+		dev_err(&pdev->dev, "need platform data for PCI setup\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx) {
+		dev_err(&pdev->dev, "no memory for pcictl context\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "no  pcictl ctrl regs resource\n");
+		ret = -ENODEV;
+		goto out1;
+	}
+
+	if (!request_mem_region(r->start, resource_size(r), pdev->name)) {
+		dev_err(&pdev->dev, "cannot claim pci regs\n");
+		ret = -ENODEV;
+		goto out1;
+	}
+
+	ctx->regs = ioremap_nocache(r->start, resource_size(r));
+	if (!ctx->regs) {
+		dev_err(&pdev->dev, "cannot map pci regs\n");
+		ret = -ENODEV;
+		goto out2;
+	}
+
+	/* map parts of the PCI IO area */
+	/* REVISIT: if this changes with a newer variant (doubt it) make this
+	 * a platform resource.
+	 */
+	virt_io = ioremap(AU1500_PCI_IO_PHYS_ADDR, 0x00100000);
+	if (!virt_io) {
+		dev_err(&pdev->dev, "cannot remap pci io space\n");
+		ret = -ENODEV;
+		goto out3;
+	}
+	ctx->alchemy_pci_ctrl.io_map_base = (unsigned long)virt_io;
+
+#ifdef CONFIG_DMA_NONCOHERENT
+	/* Au1500 revisions older than AD have borked coherent PCI */
+	if ((alchemy_get_cputype() == ALCHEMY_CPU_AU1500) &&
+	    (read_c0_prid() < 0x01030202)) {
+		val = __raw_readl(ctx->regs + PCI_REG_CONFIG);
+		val |= PCI_CONFIG_NC;
+		__raw_writel(val, ctx->regs + PCI_REG_CONFIG);
+		wmb();
+		dev_info(&pdev->dev, "non-coherent PCI on Au1500 AA/AB/AC\n");
+	}
+#endif
+
+	if (pd->board_map_irq)
+		ctx->board_map_irq = pd->board_map_irq;
+
+	if (pd->board_pci_idsel)
+		ctx->board_pci_idsel = pd->board_pci_idsel;
+	else
+		ctx->board_pci_idsel = alchemy_pci_def_idsel;
+
+	/* fill in relevant pci_controller members */
+	ctx->alchemy_pci_ctrl.pci_ops = &alchemy_pci_ops;
+	ctx->alchemy_pci_ctrl.mem_resource = &alchemy_pci_def_memres;
+	ctx->alchemy_pci_ctrl.io_resource = &alchemy_pci_def_iores;
+
+	/* we can't ioremap the entire pci config space because it's too large,
+	 * nor can we dynamically ioremap it because some drivers use the
+	 * PCI config routines from within atomic contex and that becomes a
+	 * problem in get_vm_area().  Instead we use one wired TLB entry to
+	 * handle all config accesses for all busses.
+	 */
+	ctx->pci_cfg_vm = get_vm_area(0x2000, VM_IOREMAP);
+	if (!ctx->pci_cfg_vm) {
+		dev_err(&pdev->dev, "unable to get vm area\n");
+		ret = -ENOMEM;
+		goto out4;
+	}
+	ctx->wired_entry = 8192;	/* impossibly high value */
+
+	set_io_port_base((unsigned long)ctx->alchemy_pci_ctrl.io_map_base);
+
+	/* board may want to modify bits in the config register, do it now */
+	val = __raw_readl(ctx->regs + PCI_REG_CONFIG);
+	val &= ~pd->pci_cfg_clr;
+	val |= pd->pci_cfg_set;
+	val &= ~PCI_CONFIG_PD;		/* clear disable bit */
+	__raw_writel(val, ctx->regs + PCI_REG_CONFIG);
+	wmb();
+
+	platform_set_drvdata(pdev, ctx);
+	register_pci_controller(&ctx->alchemy_pci_ctrl);
+
+	return 0;
+
+out4:
+	iounmap(virt_io);
+out3:
+	iounmap(ctx->regs);
+out2:
+	release_mem_region(r->start, resource_size(r));
+out1:
+	kfree(ctx);
+out:
+	return ret;
+}
+
+
+#ifdef CONFIG_PM
+/* save PCI controller register contents. */
+static int alchemy_pci_suspend(struct device *dev)
+{
+	struct alchemy_pci_context *ctx = dev_get_drvdata(dev);
+
+	ctx->pm[0]  = __raw_readl(ctx->regs + PCI_REG_CMEM);
+	ctx->pm[1]  = __raw_readl(ctx->regs + PCI_REG_CONFIG) & 0x0009ffff;
+	ctx->pm[2]  = __raw_readl(ctx->regs + PCI_REG_B2BMASK_CCH);
+	ctx->pm[3]  = __raw_readl(ctx->regs + PCI_REG_B2BBASE0_VID);
+	ctx->pm[4]  = __raw_readl(ctx->regs + PCI_REG_B2BBASE1_SID);
+	ctx->pm[5]  = __raw_readl(ctx->regs + PCI_REG_MWMASK_DEV);
+	ctx->pm[6]  = __raw_readl(ctx->regs + PCI_REG_MWBASE_REV_CCL);
+	ctx->pm[7]  = __raw_readl(ctx->regs + PCI_REG_ID);
+	ctx->pm[8]  = __raw_readl(ctx->regs + PCI_REG_CLASSREV);
+	ctx->pm[9]  = __raw_readl(ctx->regs + PCI_REG_PARAM);
+	ctx->pm[10] = __raw_readl(ctx->regs + PCI_REG_MBAR);
+	ctx->pm[11] = __raw_readl(ctx->regs + PCI_REG_TIMEOUT);
+
+	return 0;
+}
+
+static int alchemy_pci_resume(struct device *dev)
+{
+	struct alchemy_pci_context *ctx = dev_get_drvdata(dev);
+
+	__raw_writel(ctx->pm[0],  ctx->regs + PCI_REG_CMEM);
+	__raw_writel(ctx->pm[2],  ctx->regs + PCI_REG_B2BMASK_CCH);
+	__raw_writel(ctx->pm[3],  ctx->regs + PCI_REG_B2BBASE0_VID);
+	__raw_writel(ctx->pm[4],  ctx->regs + PCI_REG_B2BBASE1_SID);
+	__raw_writel(ctx->pm[5],  ctx->regs + PCI_REG_MWMASK_DEV);
+	__raw_writel(ctx->pm[6],  ctx->regs + PCI_REG_MWBASE_REV_CCL);
+	__raw_writel(ctx->pm[7],  ctx->regs + PCI_REG_ID);
+	__raw_writel(ctx->pm[8],  ctx->regs + PCI_REG_CLASSREV);
+	__raw_writel(ctx->pm[9],  ctx->regs + PCI_REG_PARAM);
+	__raw_writel(ctx->pm[10], ctx->regs + PCI_REG_MBAR);
+	__raw_writel(ctx->pm[11], ctx->regs + PCI_REG_TIMEOUT);
+	wmb();
+	__raw_writel(ctx->pm[1],  ctx->regs + PCI_REG_CONFIG);
+	wmb();
+
+	return 0;
+}
+
+static const struct dev_pm_ops alchemy_pci_pmops = {
+	.suspend	= alchemy_pci_suspend,
+	.resume		= alchemy_pci_resume,
+};
+
+#define ALCHEMY_PCICTL_PM	(&alchemy_pci_pmops)
+
+#else
+#define ALCHEMY_PCICTL_PM	NULL
+#endif
+
+static struct platform_driver alchemy_pcictl_driver = {
+	.probe		= alchemy_pci_probe,
+	.driver	= {
+		.name	= "alchemy-pci",
+		.owner	= THIS_MODULE,
+		.pm	= ALCHEMY_PCICTL_PM,
+	},
+};
+
+static int __init alchemy_pci_init(void)
+{
+	/* Au1500/Au1550 have PCI */
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1500:
+	case ALCHEMY_CPU_AU1550:
+		return platform_driver_register(&alchemy_pcictl_driver);
+	}
+	return 0;
+}
+arch_initcall(alchemy_pci_init);
+
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	struct alchemy_pci_context *ctx = dev->sysdata;
+	if (ctx && ctx->board_map_irq)
+		return ctx->board_map_irq(dev, slot, pin);
+	return -1;
+}
+
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/arch/mips/pci/pci-bcm47xx.c linux-libre-3.2-gnu/arch/mips/pci/pci-bcm47xx.c
--- linux-libre-3.1-gnu/arch/mips/pci/pci-bcm47xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/pci/pci-bcm47xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/ssb/ssb.h>
+#include <bcm47xx.h>
 
 int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
@@ -33,9 +34,13 @@
 
 int pcibios_plat_dev_init(struct pci_dev *dev)
 {
+#ifdef CONFIG_BCM47XX_SSB
 	int res;
 	u8 slot, pin;
 
+	if (bcm47xx_bus_type !=  BCM47XX_BUS_TYPE_SSB)
+		return 0;
+
 	res = ssb_pcibios_plat_dev_init(dev);
 	if (res < 0) {
 		printk(KERN_ALERT "PCI: Failed to init device %s\n",
@@ -55,5 +60,6 @@
 	}
 
 	dev->irq = res;
+#endif
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/arch/mips/pci/pci.c linux-libre-3.2-gnu/arch/mips/pci/pci.c
--- linux-libre-3.1-gnu/arch/mips/pci/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/pci/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/pci.h>
diff -druN linux-libre-3.1-gnu/arch/mips/pci/pci-ip27.c linux-libre-3.2-gnu/arch/mips/pci/pci-ip27.c
--- linux-libre-3.1-gnu/arch/mips/pci/pci-ip27.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/pci/pci-ip27.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/smp.h>
 #include <asm/sn/arch.h>
diff -druN linux-libre-3.1-gnu/arch/mips/pci/pci-lantiq.c linux-libre-3.2-gnu/arch/mips/pci/pci-lantiq.c
--- linux-libre-3.1-gnu/arch/mips/pci/pci-lantiq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/pci/pci-lantiq.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 
 #include <asm/pci.h>
diff -druN linux-libre-3.1-gnu/arch/mips/pmc-sierra/msp71xx/msp_serial.c linux-libre-3.2-gnu/arch/mips/pmc-sierra/msp71xx/msp_serial.c
--- linux-libre-3.1-gnu/arch/mips/pmc-sierra/msp71xx/msp_serial.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/pmc-sierra/msp71xx/msp_serial.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/serial.h>
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
+#include <linux/slab.h>
 
 #include <asm/bootinfo.h>
 #include <asm/io.h>
@@ -38,6 +39,55 @@
 #include <msp_int.h>
 #include <msp_regs.h>
 
+struct msp_uart_data {
+	int	last_lcr;
+};
+
+static void msp_serial_out(struct uart_port *p, int offset, int value)
+{
+	struct msp_uart_data *d = p->private_data;
+
+	if (offset == UART_LCR)
+		d->last_lcr = value;
+
+	offset <<= p->regshift;
+	writeb(value, p->membase + offset);
+}
+
+static unsigned int msp_serial_in(struct uart_port *p, int offset)
+{
+	offset <<= p->regshift;
+
+	return readb(p->membase + offset);
+}
+
+static int msp_serial_handle_irq(struct uart_port *p)
+{
+	struct msp_uart_data *d = p->private_data;
+	unsigned int iir = readb(p->membase + (UART_IIR << p->regshift));
+
+	if (serial8250_handle_irq(p, iir)) {
+		return 1;
+	} else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
+		/*
+		 * The DesignWare APB UART has an Busy Detect (0x07) interrupt
+		 * meaning an LCR write attempt occurred while the UART was
+		 * busy. The interrupt must be cleared by reading the UART
+		 * status register (USR) and the LCR re-written.
+		 *
+		 * Note: MSP reserves 0x20 bytes of address space for the UART
+		 * and the USR is mapped in a separate block at an offset of
+		 * 0xc0 from the start of the UART.
+		 */
+		(void)readb(p->membase + 0xc0);
+		writeb(d->last_lcr, p->membase + (UART_LCR << p->regshift));
+
+		return 1;
+	}
+
+	return 0;
+}
+
 void __init msp_serial_setup(void)
 {
 	char    *s;
@@ -59,13 +109,22 @@
 	up.irq          = MSP_INT_UART0;
 	up.uartclk      = uartclk;
 	up.regshift     = 2;
-	up.iotype       = UPIO_DWAPB; /* UPIO_MEM like */
+	up.iotype       = UPIO_MEM;
 	up.flags        = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
 	up.type         = PORT_16550A;
 	up.line         = 0;
-	up.private_data		= (void*)UART0_STATUS_REG;
-	if (early_serial_setup(&up))
-		printk(KERN_ERR "Early serial init of port 0 failed\n");
+	up.serial_out	= msp_serial_out;
+	up.serial_in	= msp_serial_in;
+	up.handle_irq	= msp_serial_handle_irq;
+	up.private_data	= kzalloc(sizeof(struct msp_uart_data), GFP_KERNEL);
+	if (!up.private_data) {
+		pr_err("failed to allocate uart private data\n");
+		return;
+	}
+	if (early_serial_setup(&up)) {
+		kfree(up.private_data);
+		pr_err("Early serial init of port 0 failed\n");
+	}
 
 	/* Initialize the second serial port, if one exists */
 	switch (mips_machtype) {
@@ -88,6 +147,8 @@
 	up.irq          = MSP_INT_UART1;
 	up.line         = 1;
 	up.private_data		= (void*)UART1_STATUS_REG;
-	if (early_serial_setup(&up))
-		printk(KERN_ERR "Early serial init of port 1 failed\n");
+	if (early_serial_setup(&up)) {
+		kfree(up.private_data);
+		pr_err("Early serial init of port 1 failed\n");
+	}
 }
diff -druN linux-libre-3.1-gnu/arch/mips/pmc-sierra/msp71xx/msp_setup.c linux-libre-3.2-gnu/arch/mips/pmc-sierra/msp71xx/msp_setup.c
--- linux-libre-3.1-gnu/arch/mips/pmc-sierra/msp71xx/msp_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/pmc-sierra/msp71xx/msp_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <asm/cacheflush.h>
 #include <asm/r4kcache.h>
 #include <asm/reboot.h>
+#include <asm/smp-ops.h>
 #include <asm/time.h>
 
 #include <msp_prom.h>
diff -druN linux-libre-3.1-gnu/arch/mips/pmc-sierra/yosemite/prom.c linux-libre-3.2-gnu/arch/mips/pmc-sierra/yosemite/prom.c
--- linux-libre-3.1-gnu/arch/mips/pmc-sierra/yosemite/prom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/pmc-sierra/yosemite/prom.c	2012-01-04 18:55:44.000000000 -0500
@@ -102,7 +102,7 @@
 
 	/* Get the boot parameters */
 	for (i = 1; i < argc; i++) {
-		if (strlen(arcs_cmdline) + strlen(arg[i] + 1) >=
+		if (strlen(arcs_cmdline) + strlen(arg[i]) + 1 >=
 		    sizeof(arcs_cmdline))
 			break;
 
diff -druN linux-libre-3.1-gnu/arch/mips/pmc-sierra/yosemite/py-console.c linux-libre-3.2-gnu/arch/mips/pmc-sierra/yosemite/py-console.c
--- linux-libre-3.1-gnu/arch/mips/pmc-sierra/yosemite/py-console.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/pmc-sierra/yosemite/py-console.c	2012-01-04 18:55:44.000000000 -0500
@@ -65,15 +65,11 @@
 
 	__asm__ __volatile__ (
 	"	.set	mips3		\n"
-	"	.set	push		\n"
-	"	.set	noreorder	\n"
-	"	.set	nomacro		\n"
 	"	ld	%0, %1		\n"
-	"	.set	pop		\n"
 	"	lbu	%0, (%0)	\n"
 	"	.set	mips0		\n"
 	: "=r" (res)
-	: "R" (vaddr));
+	: "m" (vaddr));
 
 	write_c0_status(sr);
 	ssnop_4();
@@ -93,15 +89,11 @@
 
 	__asm__ __volatile__ (
 	"	.set	mips3		\n"
-	"	.set	push		\n"
-	"	.set	noreorder	\n"
-	"	.set	nomacro		\n"
 	"	ld	%0, %1		\n"
-	"	.set	pop		\n"
 	"	sb	%2, (%0)	\n"
 	"	.set	mips0		\n"
 	: "=&r" (tmp)
-	: "R" (vaddr), "r" (c));
+	: "m" (vaddr), "r" (c));
 
 	write_c0_status(sr);
 	ssnop_4();
diff -druN linux-libre-3.1-gnu/arch/mips/pnx8550/common/prom.c linux-libre-3.2-gnu/arch/mips/pnx8550/common/prom.c
--- linux-libre-3.1-gnu/arch/mips/pnx8550/common/prom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/pnx8550/common/prom.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@
 }t_env_var;
 
 
-char * prom_getcmdline(void)
+char * __init prom_getcmdline(void)
 {
 	return &(arcs_cmdline[0]);
 }
diff -druN linux-libre-3.1-gnu/arch/mips/powertv/asic/Kconfig linux-libre-3.2-gnu/arch/mips/powertv/asic/Kconfig
--- linux-libre-3.1-gnu/arch/mips/powertv/asic/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/powertv/asic/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-config MIN_RUNTIME_RESOURCES
-	bool "Support for minimum runtime resources"
-	default n
-	depends on POWERTV
-	help
-	  Enables support for minimizing the number of (SA asic) runtime
-	  resources that are preallocated by the kernel.
-
-config MIN_RUNTIME_DOCSIS
-	bool "Support for minimum DOCSIS resource"
-	default y
-	depends on MIN_RUNTIME_RESOURCES
-	help
-	  Enables support for the preallocated DOCSIS resource.
-
-config MIN_RUNTIME_PMEM
-	bool "Support for minimum PMEM resource"
-	default y
-	depends on MIN_RUNTIME_RESOURCES
-	help
-	  Enables support for the preallocated Memory resource.
-
-config MIN_RUNTIME_TFTP
-	bool "Support for minimum TFTP resource"
-	default y
-	depends on MIN_RUNTIME_RESOURCES
-	help
-	  Enables support for the preallocated TFTP resource.
diff -druN linux-libre-3.1-gnu/arch/mips/powertv/Kconfig linux-libre-3.2-gnu/arch/mips/powertv/Kconfig
--- linux-libre-3.1-gnu/arch/mips/powertv/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/powertv/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,3 @@
-source "arch/mips/powertv/asic/Kconfig"
-
 config BOOTLOADER_DRIVER
 	bool "PowerTV Bootloader Driver Support"
 	default n
diff -druN linux-libre-3.1-gnu/arch/mips/powertv/pci/fixup-powertv.c linux-libre-3.2-gnu/arch/mips/powertv/pci/fixup-powertv.c
--- linux-libre-3.1-gnu/arch/mips/powertv/pci/fixup-powertv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/powertv/pci/fixup-powertv.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,5 @@
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <asm/mach-powertv/interrupts.h>
 #include "powertv-pci.h"
diff -druN linux-libre-3.1-gnu/arch/mips/powertv/powertv-usb.c linux-libre-3.2-gnu/arch/mips/powertv/powertv-usb.c
--- linux-libre-3.1-gnu/arch/mips/powertv/powertv-usb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/powertv/powertv-usb.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <asm/mach-powertv/asic.h>
diff -druN linux-libre-3.1-gnu/arch/mips/rb532/gpio.c linux-libre-3.2-gnu/arch/mips/rb532/gpio.c
--- linux-libre-3.1-gnu/arch/mips/rb532/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/rb532/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
+#include <linux/export.h>
 #include <linux/spinlock.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
diff -druN linux-libre-3.1-gnu/arch/mips/rb532/setup.c linux-libre-3.2-gnu/arch/mips/rb532/setup.c
--- linux-libre-3.1-gnu/arch/mips/rb532/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/rb532/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,6 +3,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/export.h>
 
 #include <asm/bootinfo.h>
 #include <asm/reboot.h>
diff -druN linux-libre-3.1-gnu/arch/mips/sgi-ip27/ip27-irq.c linux-libre-3.2-gnu/arch/mips/sgi-ip27/ip27-irq.c
--- linux-libre-3.1-gnu/arch/mips/sgi-ip27/ip27-irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/sgi-ip27/ip27-irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -337,12 +337,12 @@
 	.irq_unmask	= enable_bridge_irq,
 };
 
-void __devinit register_bridge_irq(unsigned int irq)
+void register_bridge_irq(unsigned int irq)
 {
 	irq_set_chip_and_handler(irq, &bridge_irq_type, handle_level_irq);
 }
 
-int __devinit request_bridge_irq(struct bridge_controller *bc)
+int request_bridge_irq(struct bridge_controller *bc)
 {
 	int irq = allocate_irqno();
 	int swlevel, cpu;
diff -druN linux-libre-3.1-gnu/arch/mips/txx9/generic/setup_tx4939.c linux-libre-3.2-gnu/arch/mips/txx9/generic/setup_tx4939.c
--- linux-libre-3.1-gnu/arch/mips/txx9/generic/setup_tx4939.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/txx9/generic/setup_tx4939.c	2012-01-04 18:55:44.000000000 -0500
@@ -321,7 +321,7 @@
 static u32 tx4939_get_eth_speed(struct net_device *dev)
 {
 	struct ethtool_cmd cmd;
-	if (dev_ethtool_get_settings(dev, &cmd))
+	if (__ethtool_get_settings(dev, &cmd))
 		return 100;	/* default 100Mbps */
 
 	return ethtool_cmd_speed(&cmd);
diff -druN linux-libre-3.1-gnu/arch/mips/txx9/generic/spi_eeprom.c linux-libre-3.2-gnu/arch/mips/txx9/generic/spi_eeprom.c
--- linux-libre-3.1-gnu/arch/mips/txx9/generic/spi_eeprom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/txx9/generic/spi_eeprom.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/device.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/eeprom.h>
diff -druN linux-libre-3.1-gnu/arch/mips/txx9/rbtx4939/setup.c linux-libre-3.2-gnu/arch/mips/txx9/rbtx4939/setup.c
--- linux-libre-3.1-gnu/arch/mips/txx9/rbtx4939/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/txx9/rbtx4939/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/interrupt.h>
diff -druN linux-libre-3.1-gnu/arch/mips/vr41xx/common/giu.c linux-libre-3.2-gnu/arch/mips/vr41xx/common/giu.c
--- linux-libre-3.1-gnu/arch/mips/vr41xx/common/giu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/vr41xx/common/giu.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/smp.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 
diff -druN linux-libre-3.1-gnu/arch/mips/vr41xx/common/rtc.c linux-libre-3.2-gnu/arch/mips/vr41xx/common/rtc.c
--- linux-libre-3.1-gnu/arch/mips/vr41xx/common/rtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mips/vr41xx/common/rtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/smp.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 
diff -druN linux-libre-3.1-gnu/arch/mn10300/Kconfig linux-libre-3.2-gnu/arch/mn10300/Kconfig
--- linux-libre-3.1-gnu/arch/mn10300/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mn10300/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -47,9 +47,6 @@
 config GENERIC_HWEIGHT
 	def_bool y
 
-config GENERIC_TIME
-	def_bool y
-
 config GENERIC_CLOCKEVENTS
 	def_bool y
 
@@ -195,7 +192,7 @@
 	  singleprocessor machines. On a singleprocessor machine, the kernel
 	  will run faster if you say N here.
 
-	  See also <file:Documentation/i386/IO-APIC.txt>,
+	  See also <file:Documentation/x86/i386/IO-APIC.txt>,
 	  <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
 	  <http://www.tldp.org/docs.html#howto>.
 
diff -druN linux-libre-3.1-gnu/arch/mn10300/kernel/gdb-stub.c linux-libre-3.2-gnu/arch/mn10300/kernel/gdb-stub.c
--- linux-libre-3.1-gnu/arch/mn10300/kernel/gdb-stub.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mn10300/kernel/gdb-stub.c	2012-01-04 18:55:44.000000000 -0500
@@ -798,7 +798,7 @@
 	if ((u32) mem & 1 && count >= 1) {
 		if (gdbstub_read_byte(mem, ch) != 0)
 			return 0;
-		buf = pack_hex_byte(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[0]);
 		mem++;
 		count--;
 	}
@@ -806,8 +806,8 @@
 	if ((u32) mem & 3 && count >= 2) {
 		if (gdbstub_read_word(mem, ch) != 0)
 			return 0;
-		buf = pack_hex_byte(buf, ch[0]);
-		buf = pack_hex_byte(buf, ch[1]);
+		buf = hex_byte_pack(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[1]);
 		mem += 2;
 		count -= 2;
 	}
@@ -815,10 +815,10 @@
 	while (count >= 4) {
 		if (gdbstub_read_dword(mem, ch) != 0)
 			return 0;
-		buf = pack_hex_byte(buf, ch[0]);
-		buf = pack_hex_byte(buf, ch[1]);
-		buf = pack_hex_byte(buf, ch[2]);
-		buf = pack_hex_byte(buf, ch[3]);
+		buf = hex_byte_pack(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[1]);
+		buf = hex_byte_pack(buf, ch[2]);
+		buf = hex_byte_pack(buf, ch[3]);
 		mem += 4;
 		count -= 4;
 	}
@@ -826,8 +826,8 @@
 	if (count >= 2) {
 		if (gdbstub_read_word(mem, ch) != 0)
 			return 0;
-		buf = pack_hex_byte(buf, ch[0]);
-		buf = pack_hex_byte(buf, ch[1]);
+		buf = hex_byte_pack(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[1]);
 		mem += 2;
 		count -= 2;
 	}
@@ -835,7 +835,7 @@
 	if (count >= 1) {
 		if (gdbstub_read_byte(mem, ch) != 0)
 			return 0;
-		buf = pack_hex_byte(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[0]);
 	}
 
 	*buf = 0;
@@ -1273,13 +1273,13 @@
 		ptr = mem2hex(title, ptr, sizeof(title) - 1, 0);
 
 		hx = hex_asc_hi(excep >> 8);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(excep >> 8);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_hi(excep);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(excep);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 
 		ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
 		*ptr = 0;
@@ -1291,21 +1291,21 @@
 		ptr = mem2hex(tbcberr, ptr, sizeof(tbcberr) - 1, 0);
 
 		hx = hex_asc_hi(bcberr >> 24);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(bcberr >> 24);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_hi(bcberr >> 16);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(bcberr >> 16);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_hi(bcberr >> 8);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(bcberr >> 8);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_hi(bcberr);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 		hx = hex_asc_lo(bcberr);
-		ptr = pack_hex_byte(ptr, hx);
+		ptr = hex_byte_pack(ptr, hx);
 
 		ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
 		*ptr = 0;
@@ -1321,12 +1321,12 @@
 	 * Send trap type (converted to signal)
 	 */
 	*ptr++ = 'T';
-	ptr = pack_hex_byte(ptr, sigval);
+	ptr = hex_byte_pack(ptr, sigval);
 
 	/*
 	 * Send Error PC
 	 */
-	ptr = pack_hex_byte(ptr, GDB_REGID_PC);
+	ptr = hex_byte_pack(ptr, GDB_REGID_PC);
 	*ptr++ = ':';
 	ptr = mem2hex(&regs->pc, ptr, 4, 0);
 	*ptr++ = ';';
@@ -1334,7 +1334,7 @@
 	/*
 	 * Send frame pointer
 	 */
-	ptr = pack_hex_byte(ptr, GDB_REGID_FP);
+	ptr = hex_byte_pack(ptr, GDB_REGID_FP);
 	*ptr++ = ':';
 	ptr = mem2hex(&regs->a3, ptr, 4, 0);
 	*ptr++ = ';';
@@ -1343,7 +1343,7 @@
 	 * Send stack pointer
 	 */
 	ssp = (unsigned long) (regs + 1);
-	ptr = pack_hex_byte(ptr, GDB_REGID_SP);
+	ptr = hex_byte_pack(ptr, GDB_REGID_SP);
 	*ptr++ = ':';
 	ptr = mem2hex(&ssp, ptr, 4, 0);
 	*ptr++ = ';';
diff -druN linux-libre-3.1-gnu/arch/mn10300/kernel/irq.c linux-libre-3.2-gnu/arch/mn10300/kernel/irq.c
--- linux-libre-3.1-gnu/arch/mn10300/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/mn10300/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -260,7 +260,6 @@
 /*
  * mark an interrupt to be ACK'd after interrupt handlers have been run rather
  * than before
- * - see Documentation/mn10300/features.txt
  */
 void mn10300_set_lateack_irq_type(int irq)
 {
diff -druN linux-libre-3.1-gnu/arch/openrisc/include/asm/dma-mapping.h linux-libre-3.2-gnu/arch/openrisc/include/asm/dma-mapping.h
--- linux-libre-3.1-gnu/arch/openrisc/include/asm/dma-mapping.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/openrisc/include/asm/dma-mapping.h	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
 #define __ASM_OPENRISC_DMA_MAPPING_H
 
 /*
- * See Documentation/PCI/PCI-DMA-mapping.txt and
+ * See Documentation/DMA-API-HOWTO.txt and
  * Documentation/DMA-API.txt for documentation.
  *
  * This file is written with the intention of eventually moving over
diff -druN linux-libre-3.1-gnu/arch/openrisc/Kconfig linux-libre-3.2-gnu/arch/openrisc/Kconfig
--- linux-libre-3.1-gnu/arch/openrisc/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/openrisc/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 #
 # For a description of the syntax of this configuration file,
-# see Documentation/kbuild/config-language.txt.
+# see Documentation/kbuild/kconfig-language.txt.
 #
 
 config OPENRISC
@@ -19,9 +19,6 @@
 config MMU
 	def_bool y
 
-config WISHBONE_BUS_BIG_ENDIAN
-	def_bool y
-
 config SYMBOL_PREFIX
         string
         default ""
@@ -160,15 +157,6 @@
 
 	  Say Y if you are unsure.
 
-config OPENRISC_EXCEPTION_DEBUG
-	bool "Print processor state at each exception"
-	default n
-	help
-	  This option will make your kernel unusable for all but kernel
-	  debugging.
-
-	  Say N if you are unsure.
-
 config OPENRISC_ESR_EXCEPTION_BUG_CHECK
 	bool "Check for possible ESR exception bug"
 	default n
diff -druN linux-libre-3.1-gnu/arch/parisc/include/asm/compat.h linux-libre-3.2-gnu/arch/parisc/include/asm/compat.h
--- linux-libre-3.1-gnu/arch/parisc/include/asm/compat.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/parisc/include/asm/compat.h	2012-01-04 18:55:44.000000000 -0500
@@ -105,7 +105,8 @@
 	__kernel_fsid_t	f_fsid;
 	s32		f_namelen;
 	s32		f_frsize;
-	s32		f_spare[5];
+	s32		f_flags;
+	s32		f_spare[4];
 };
 
 struct compat_sigcontext {
diff -druN linux-libre-3.1-gnu/arch/parisc/include/asm/dma-mapping.h linux-libre-3.2-gnu/arch/parisc/include/asm/dma-mapping.h
--- linux-libre-3.1-gnu/arch/parisc/include/asm/dma-mapping.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/parisc/include/asm/dma-mapping.h	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
 #include <asm/cacheflush.h>
 #include <asm/scatterlist.h>
 
-/* See Documentation/PCI/PCI-DMA-mapping.txt */
+/* See Documentation/DMA-API-HOWTO.txt */
 struct hppa_dma_ops {
 	int  (*dma_supported)(struct device *dev, u64 mask);
 	void *(*alloc_consistent)(struct device *dev, size_t size, dma_addr_t *iova, gfp_t flag);
diff -druN linux-libre-3.1-gnu/arch/parisc/Kconfig linux-libre-3.2-gnu/arch/parisc/Kconfig
--- linux-libre-3.1-gnu/arch/parisc/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/parisc/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -169,9 +169,7 @@
 
 choice
 	prompt "Kernel page size"
-	default PARISC_PAGE_SIZE_4KB  if !64BIT
-	default PARISC_PAGE_SIZE_4KB  if 64BIT
-#	default PARISC_PAGE_SIZE_16KB if 64BIT
+	default PARISC_PAGE_SIZE_4KB
 
 config PARISC_PAGE_SIZE_4KB
 	bool "4KB"
diff -druN linux-libre-3.1-gnu/arch/parisc/kernel/drivers.c linux-libre-3.2-gnu/arch/parisc/kernel/drivers.c
--- linux-libre-3.1-gnu/arch/parisc/kernel/drivers.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/parisc/kernel/drivers.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
+#include <linux/export.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/pdc.h>
diff -druN linux-libre-3.1-gnu/arch/parisc/kernel/pci-dma.c linux-libre-3.2-gnu/arch/parisc/kernel/pci-dma.c
--- linux-libre-3.1-gnu/arch/parisc/kernel/pci-dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/parisc/kernel/pci-dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
 ** PARISC 1.1 Dynamic DMA mapping support.
 ** This implementation is for PA-RISC platforms that do not support
 ** I/O TLBs (aka DMA address translation hardware).
-** See Documentation/PCI/PCI-DMA-mapping.txt for interface definitions.
+** See Documentation/DMA-API-HOWTO.txt for interface definitions.
 **
 **      (c) Copyright 1999,2000 Hewlett-Packard Company
 **      (c) Copyright 2000 Grant Grundler
@@ -26,6 +26,7 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <linux/scatterlist.h>
+#include <linux/export.h>
 
 #include <asm/cacheflush.h>
 #include <asm/dma.h>    /* for DMA_CHUNK_SIZE */
diff -druN linux-libre-3.1-gnu/arch/parisc/kernel/setup.c linux-libre-3.2-gnu/arch/parisc/kernel/setup.c
--- linux-libre-3.1-gnu/arch/parisc/kernel/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/parisc/kernel/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <linux/pci.h>
 #undef PCI_DEBUG
 #include <linux/proc_fs.h>
+#include <linux/export.h>
 
 #include <asm/processor.h>
 #include <asm/pdc.h>
diff -druN linux-libre-3.1-gnu/arch/parisc/lib/iomap.c linux-libre-3.2-gnu/arch/parisc/lib/iomap.c
--- linux-libre-3.1-gnu/arch/parisc/lib/iomap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/parisc/lib/iomap.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,7 @@
 
 #include <linux/ioport.h>
 #include <linux/pci.h>
+#include <linux/export.h>
 #include <asm/io.h>
 
 /*
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/charon.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/charon.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/charon.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/charon.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,236 @@
+/*
+ * charon board Device Tree Source
+ *
+ * Copyright (C) 2007 Semihalf
+ * Marian Balakowicz <m8@semihalf.com>
+ *
+ * Copyright (C) 2010 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 = "anon,charon";
+	compatible = "anon,charon";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&mpc5200_pic>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,5200@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;
+			i-cache-line-size = <32>;
+			d-cache-size = <0x4000>;	// L1, 16K
+			i-cache-size = <0x4000>;	// L1, 16K
+			timebase-frequency = <0>;	// from bootloader
+			bus-frequency = <0>;		// from bootloader
+			clock-frequency = <0>;		// from bootloader
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x08000000>;	// 128MB
+	};
+
+	soc5200@f0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc5200-immr";
+		ranges = <0 0xf0000000 0x0000c000>;
+		reg = <0xf0000000 0x00000100>;
+		bus-frequency = <0>;		// from bootloader
+		system-frequency = <0>;		// from bootloader
+
+		cdm@200 {
+			compatible = "fsl,mpc5200-cdm";
+			reg = <0x200 0x38>;
+		};
+
+		mpc5200_pic: interrupt-controller@500 {
+			// 5200 interrupts are encoded into two levels;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			compatible = "fsl,mpc5200-pic";
+			reg = <0x500 0x80>;
+		};
+
+		timer@600 {	// General Purpose Timer
+			compatible = "fsl,mpc5200-gpt";
+			reg = <0x600 0x10>;
+			interrupts = <1 9 0>;
+			fsl,has-wdt;
+		};
+
+		can@900 {
+			compatible = "fsl,mpc5200-mscan";
+			interrupts = <2 17 0>;
+			reg = <0x900 0x80>;
+		};
+
+		can@980 {
+			compatible = "fsl,mpc5200-mscan";
+			interrupts = <2 18 0>;
+			reg = <0x980 0x80>;
+		};
+
+		gpio_simple: gpio@b00 {
+			compatible = "fsl,mpc5200-gpio";
+			reg = <0xb00 0x40>;
+			interrupts = <1 7 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		usb@1000 {
+			compatible = "fsl,mpc5200-ohci","ohci-be";
+			reg = <0x1000 0xff>;
+			interrupts = <2 6 0>;
+		};
+
+		dma-controller@1200 {
+			device_type = "dma-controller";
+			compatible = "fsl,mpc5200-bestcomm";
+			reg = <0x1200 0x80>;
+			interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
+			              3 4 0  3 5 0  3 6 0  3 7 0
+			              3 8 0  3 9 0  3 10 0  3 11 0
+			              3 12 0  3 13 0  3 14 0  3 15 0>;
+		};
+
+		xlb@1f00 {
+			compatible = "fsl,mpc5200-xlb";
+			reg = <0x1f00 0x100>;
+		};
+
+		serial@2000 {		// PSC1
+			compatible = "fsl,mpc5200-psc-uart";
+			reg = <0x2000 0x100>;
+			interrupts = <2 1 0>;
+		};
+
+		serial@2400 {		// PSC3
+			compatible = "fsl,mpc5200-psc-uart";
+			reg = <0x2400 0x100>;
+			interrupts = <2 3 0>;
+		};
+
+		ethernet@3000 {
+			compatible = "fsl,mpc5200-fec";
+			reg = <0x3000 0x400>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <2 5 0>;
+			fixed-link = <1 1 100 0 0>;
+		};
+
+		mdio@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200-mdio";
+			reg = <0x3000 0x400>;       // fec range, since we need to setup fec interrupts
+			interrupts = <2 5 0>;   // these are for "mii command finished", not link changes & co.
+		};
+
+		ata@3a00 {
+			compatible = "fsl,mpc5200-ata";
+			reg = <0x3a00 0x100>;
+			interrupts = <2 7 0>;
+		};
+
+		i2c@3d00 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200-i2c","fsl-i2c";
+			reg = <0x3d00 0x40>;
+			interrupts = <2 15 0>;
+		};
+
+
+		i2c@3d40 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200-i2c","fsl-i2c";
+			reg = <0x3d40 0x40>;
+			interrupts = <2 16 0>;
+
+			dtt@28 {
+				compatible = "national,lm80";
+				reg = <0x28>;
+			};
+
+			rtc@68 {
+				compatible = "dallas,ds1374";
+				reg = <0x68>;
+			};
+		};
+
+		sram@8000 {
+			compatible = "fsl,mpc5200-sram";
+			reg = <0x8000 0x4000>;
+		};
+	};
+
+	localbus {
+		compatible = "fsl,mpc5200-lpb","simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges = <	0 0 0xfc000000 0x02000000
+				1 0 0xe0000000 0x04000000 // CS1 range, SM501
+				3 0 0xe8000000 0x00080000>;
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <4>;
+			device-width = <2>;
+			#size-cells = <1>;
+			#address-cells = <1>;
+		};
+
+		display@1,0 {
+			compatible = "smi,sm501";
+			reg = <1 0x00000000 0x00800000
+			       1 0x03e00000 0x00200000>;
+			mode = "640x480-32@60";
+			interrupts = <1 1 3>;
+			little-endian;
+		};
+
+		mram0@3,0 {
+			compatible = "mtd-ram";
+			reg = <3 0x00000 0x80000>;
+			bank-width = <1>;
+		};
+	};
+
+	pci@f0000d00 {
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		compatible = "fsl,mpc5200-pci";
+		reg = <0xf0000d00 0x100>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3
+				 0xc000 0 0 2 &mpc5200_pic 0 0 3
+				 0xc000 0 0 3 &mpc5200_pic 0 0 3
+				 0xc000 0 0 4 &mpc5200_pic 0 0 3>;
+		clock-frequency = <0>; // From boot loader
+		interrupts = <2 8 0 2 9 0 2 10 0>;
+		bus-range = <0 0>;
+		ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
+			  0x02000000 0 0x90000000 0x90000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/digsy_mtc.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/digsy_mtc.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/digsy_mtc.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/digsy_mtc.dts	2012-01-04 18:55:44.000000000 -0500
@@ -23,19 +23,26 @@
 
 	soc5200@f0000000 {
 		timer@600 {	// General Purpose Timer
+			#gpio-cells = <2>;
 			fsl,has-wdt;
+			gpio-controller;
 		};
 
-		rtc@800 {
-			status = "disabled";
+		timer@610 {
+			#gpio-cells = <2>;
+			gpio-controller;
 		};
 
-		can@900 {
+		rtc@800 {
 			status = "disabled";
 		};
 
-		can@980 {
-			status = "disabled";
+		spi@f00 {
+			msp430@0 {
+				compatible = "spidev";
+				spi-max-frequency = <32000>;
+				reg = <0>;
+			};
 		};
 
 		psc@2000 {		// PSC1
@@ -73,11 +80,16 @@
 		};
 
 		i2c@3d00 {
-			rtc@50 {
+			eeprom@50 {
 				compatible = "at,24c08";
 				reg = <0x50>;
 			};
 
+			rtc@56 {
+				compatible = "mc,rv3029c2";
+				reg = <0x56>;
+			};
+
 			rtc@68 {
 				compatible = "dallas,ds1339";
 				reg = <0x68>;
@@ -90,11 +102,22 @@
 	};
 
 	pci@f0000d00 {
-		status = "disabled";
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3
+				 0xc000 0 0 2 &mpc5200_pic 0 0 3
+				 0xc000 0 0 3 &mpc5200_pic 0 0 3
+				 0xc000 0 0 4 &mpc5200_pic 0 0 3>;
+		clock-frequency = <0>; // From boot loader
+		interrupts = <2 8 0 2 9 0 2 10 0>;
+		bus-range = <0 0>;
+		ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
+			  0x02000000 0 0x90000000 0x90000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
 	};
 
 	localbus {
-		ranges = <0 0 0xff000000 0x1000000>;
+		ranges = <0 0 0xff000000 0x1000000
+			  4 0 0x60000000 0x0001000>;
 
 		// 16-bit flash device at LocalPlus Bus CS0
 		flash@0,0 {
@@ -122,5 +145,25 @@
 				reg = <0x00f00000 0x100000>;
 			};
 		};
+
+		can@4,0 {
+			compatible = "nxp,sja1000";
+			reg = <4 0x000 0x80>;
+			nxp,external-clock-frequency = <24000000>;
+			interrupts = <1 2 3>; // Level-low
+		};
+
+		can@4,100 {
+			compatible = "nxp,sja1000";
+			reg = <4 0x100 0x80>;
+			nxp,external-clock-frequency = <24000000>;
+			interrupts = <1 2 3>;  // Level-low
+		};
+
+		serial@4,200 {
+			compatible = "nxp,sc28l92";
+			reg = <4 0x200 0x10>;
+			interrupts = <1 3 3>;
+		};
 	};
 };
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/gef_ppc9a.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/gef_ppc9a.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/gef_ppc9a.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/gef_ppc9a.dts	2012-01-04 18:55:44.000000000 -0500
@@ -269,14 +269,16 @@
 		enet0: ethernet@24000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
+			cell-index = <0>;
 			device_type = "network";
-			model = "eTSEC";
+			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
 			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
+			interrupts = <29 2 30  2 34 2>;
 			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
 			phy-connection-type = "gmii";
 
@@ -290,25 +292,48 @@
 					interrupt-parent = <&gef_pic>;
 					interrupts = <0x9 0x4>;
 					reg = <1>;
+					device_type = "ethernet-phy";
 				};
 				phy2: ethernet-phy@2 {
 					interrupt-parent = <&gef_pic>;
 					interrupts = <0x8 0x4>;
 					reg = <3>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
 				};
 			};
 		};
 
 		enet1: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <2>;
 			device_type = "network";
-			model = "eTSEC";
+			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <0x1f 0x2 0x20 0x2 0x21 0x2>;
+			interrupts = <31 2 32 2 33 2>;
 			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi2>;
 			phy-handle = <&phy2>;
 			phy-connection-type = "gmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/gef_sbc310.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/gef_sbc310.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/gef_sbc310.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/gef_sbc310.dts	2012-01-04 18:55:44.000000000 -0500
@@ -267,14 +267,16 @@
 		enet0: ethernet@24000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
+			cell-index = <0>;
 			device_type = "network";
-			model = "eTSEC";
+			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
 			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
+			interrupts = <29 2 30  2 34 2>;
 			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
 			phy-connection-type = "gmii";
 
@@ -288,25 +290,48 @@
 					interrupt-parent = <&gef_pic>;
 					interrupts = <0x9 0x4>;
 					reg = <1>;
+					device_type = "ethernet-phy";
 				};
 				phy2: ethernet-phy@2 {
 					interrupt-parent = <&gef_pic>;
 					interrupts = <0x8 0x4>;
 					reg = <3>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
 				};
 			};
 		};
 
 		enet1: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <2>;
 			device_type = "network";
-			model = "eTSEC";
+			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <0x1f 0x2 0x20 0x2 0x21 0x2>;
+			interrupts = <31 2 32 2 33 2>;
 			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi2>;
 			phy-handle = <&phy2>;
 			phy-connection-type = "gmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/gef_sbc610.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/gef_sbc610.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/gef_sbc610.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/gef_sbc610.dts	2012-01-04 18:55:44.000000000 -0500
@@ -267,14 +267,16 @@
 		enet0: ethernet@24000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
+			cell-index = <0>;
 			device_type = "network";
-			model = "eTSEC";
+			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
 			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
+			interrupts = <29 2 30  2 34 2>;
 			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
 			phy-connection-type = "gmii";
 
@@ -288,25 +290,48 @@
 					interrupt-parent = <&gef_pic>;
 					interrupts = <0x9 0x4>;
 					reg = <1>;
+					device_type = "ethernet-phy";
 				};
 				phy2: ethernet-phy@2 {
 					interrupt-parent = <&gef_pic>;
 					interrupts = <0x8 0x4>;
 					reg = <3>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
 				};
 			};
 		};
 
 		enet1: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <2>;
 			device_type = "network";
-			model = "eTSEC";
+			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			interrupts = <0x1f 0x2 0x20 0x2 0x21 0x2>;
+			interrupts = <31 2 32 2 33 2>;
 			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi2>;
 			phy-handle = <&phy2>;
 			phy-connection-type = "gmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/hcu4.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/hcu4.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/hcu4.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/hcu4.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,168 +0,0 @@
-/*
-* Device Tree Source for Netstal Maschinen HCU4
-* based on the IBM Walnut
-*
-* Copyright 2008
-* Niklaus Giger <niklaus.giger@member.fsf.org>
-*
-* Copyright 2007 IBM Corp.
-* Josh Boyer <jwboyer@linux.vnet.ibm.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.
-*/
-
-/dts-v1/;
-
-/ {
-	#address-cells = <0x1>;
-	#size-cells = <0x1>;
-	model = "netstal,hcu4";
-	compatible = "netstal,hcu4";
-	dcr-parent = <0x1>;
-
-	aliases {
-		ethernet0 = "/plb/opb/ethernet@ef600800";
-		serial0 = "/plb/opb/serial@ef600300";
-	};
-
-	cpus {
-		#address-cells = <0x1>;
-		#size-cells = <0x0>;
-
-		cpu@0 {
-			device_type = "cpu";
-			model = "PowerPC,405GPr";
-			reg = <0x0>;
-			clock-frequency = <0>;		/* Filled in by U-Boot */
-			timebase-frequency = <0x0>;	/* Filled in by U-Boot */
-			i-cache-line-size = <0x20>;
-			d-cache-line-size = <0x20>;
-			i-cache-size = <0x4000>;
-			d-cache-size = <0x4000>;
-			dcr-controller;
-			dcr-access-method = "native";
-			linux,phandle = <0x1>;
-		};
-	};
-
-	memory {
-		device_type = "memory";
-		reg = <0x0 0x0>;	/* Filled in by U-Boot */
-	};
-
-	UIC0: interrupt-controller {
-		compatible = "ibm,uic";
-		interrupt-controller;
-		cell-index = <0x0>;
-		dcr-reg = <0xc0 0x9>;
-		#address-cells = <0x0>;
-		#size-cells = <0x0>;
-		#interrupt-cells = <0x2>;
-		linux,phandle = <0x2>;
-	};
-
-	plb {
-		compatible = "ibm,plb3";
-		#address-cells = <0x1>;
-		#size-cells = <0x1>;
-		ranges;
-		clock-frequency = <0x0>;	/* Filled in by U-Boot */
-
-		SDRAM0: memory-controller {
-			compatible = "ibm,sdram-405gp";
-			dcr-reg = <0x10 0x2>;
-		};
-
-		MAL: mcmal {
-			compatible = "ibm,mcmal-405gp", "ibm,mcmal";
-			dcr-reg = <0x180 0x62>;
-			num-tx-chans = <0x1>;
-			num-rx-chans = <0x1>;
-			interrupt-parent = <0x2>;
-			interrupts = <0xb 0x4 0xc 0x4 0xa 0x4 0xd 0x4 0xe 0x4>;
-			linux,phandle = <0x3>;
-		};
-
-		POB0: opb {
-			compatible = "ibm,opb-405gp", "ibm,opb";
-			#address-cells = <0x1>;
-			#size-cells = <0x1>;
-			ranges = <0xef600000 0xef600000 0xa00000>;
-			dcr-reg = <0xa0 0x5>;
-			clock-frequency = <0x0>;	/* Filled in by U-Boot */
-
-			UART0: serial@ef600300 {
-				device_type = "serial";
-				compatible = "ns16550";
-				reg = <0xef600300 0x8>;
-				virtual-reg = <0xef600300>;
-				clock-frequency = <0x0>;/* Filled in by U-Boot */
-				current-speed = <0>;	/* Filled in by U-Boot */
-				interrupt-parent = <0x2>;
-				interrupts = <0x0 0x4>;
-			};
-
-			IIC: i2c@ef600500 {
-				compatible = "ibm,iic-405gp", "ibm,iic";
-				reg = <0xef600500 0x11>;
-				interrupt-parent = <0x2>;
-				interrupts = <0x2 0x4>;
-			};
-
-			GPIO: gpio@ef600700 {
-				compatible = "ibm,gpio-405gp";
-				reg = <0xef600700 0x20>;
-			};
-
-			EMAC: ethernet@ef600800 {
-				device_type = "network";
-				compatible = "ibm,emac-405gp", "ibm,emac";
-				interrupt-parent = <0x2>;
-				interrupts = <0xf 0x4 0x9 0x4>;
-				local-mac-address = [00 00 00 00 00 00];
-				reg = <0xef600800 0x70>;
-				mal-device = <0x3>;
-				mal-tx-channel = <0x0>;
-				mal-rx-channel = <0x0>;
-				cell-index = <0x0>;
-				max-frame-size = <0x5dc>;
-				rx-fifo-size = <0x1000>;
-				tx-fifo-size = <0x800>;
-				phy-mode = "rmii";
-				phy-map = <0x1>;
-			};
-		};
-
-		EBC0: ebc {
-			compatible = "ibm,ebc-405gp", "ibm,ebc";
-			dcr-reg = <0x12 0x2>;
-			#address-cells = <0x2>;
-			#size-cells = <0x1>;
-			clock-frequency = <0x0>;	/* Filled in by U-Boot */
-
-			sram@0,0 {
-				reg = <0x0 0x0 0x80000>;
-			};
-
-			flash@0,80000 {
-				compatible = "jedec-flash";
-				bank-width = <0x1>;
-				reg = <0x0 0x80000 0x80000>;
-				#address-cells = <0x1>;
-				#size-cells = <0x1>;
-
-				partition@0 {
-					label = "OpenBIOS";
-					reg = <0x0 0x80000>;
-					read-only;
-				};
-			};
-		};
-	};
-
-	chosen {
-		linux,stdout-path = "/plb/opb/serial@ef600300";
-	};
-};
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/ksi8560.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/ksi8560.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/ksi8560.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/ksi8560.dts	2012-01-04 18:55:44.000000000 -0500
@@ -306,7 +306,7 @@
 	localbus@fdf05000 {
 		#address-cells = <2>;
 		#size-cells = <1>;
-		compatible = "fsl,mpc8560-localbus";
+		compatible = "fsl,mpc8560-localbus", "simple-bus";
 		reg = <0xfdf05000 0x68>;
 
 		ranges = <0x0 0x0 0xe0000000 0x00800000
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/mgcoge.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/mgcoge.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/mgcoge.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/mgcoge.dts	2012-01-04 18:55:44.000000000 -0500
@@ -213,6 +213,15 @@
 				linux,network-index = <2>;
 				fsl,cpm-command = <0x16200300>;
 			};
+
+			usb@11b60 {
+				compatible = "fsl,mpc8272-cpm-usb";
+				mode = "peripheral";
+				reg = <0x11b60 0x40 0x8b00 0x100>;
+				interrupts = <11 8>;
+				interrupt-parent = <&PIC>;
+				usb-clock = <5>;
+			};
 		};
 
 		cpm2_pio_c: gpio-controller@10d40 {
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/mpc5200b.dtsi linux-libre-3.2-gnu/arch/powerpc/boot/dts/mpc5200b.dtsi
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/mpc5200b.dtsi	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/mpc5200b.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -147,6 +147,8 @@
 		};
 
 		spi@f00 {
+			#address-cells = <1>;
+			#size-cells = <0>;
 			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
 			reg = <0xf00 0x20>;
 			interrupts = <2 13 0 2 14 0>;
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/mpc8349emitx.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/mpc8349emitx.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/mpc8349emitx.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/mpc8349emitx.dts	2012-01-04 18:55:44.000000000 -0500
@@ -390,7 +390,8 @@
 		#address-cells = <2>;
 		#size-cells = <1>;
 		compatible = "fsl,mpc8349e-localbus",
-			     "fsl,pq2pro-localbus";
+			     "fsl,pq2pro-localbus",
+			     "simple-bus";
 		reg = <0xe0005000 0xd8>;
 		ranges = <0x0 0x0 0xfe000000 0x1000000	/* flash */
 			  0x1 0x0 0xf8000000 0x20000	/* VSC 7385 */
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p1010rdb.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/p1010rdb.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p1010rdb.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p1010rdb.dts	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,8 @@
 		ethernet2 = &enet2;
 		pci0 = &pci0;
 		pci1 = &pci1;
+		can0 = &can0;
+		can1 = &can1;
 	};
 
 	memory {
@@ -169,14 +171,6 @@
 			};
 		};
 
-		can0@1c000 {
-			fsl,flexcan-clock-source = "platform";
-		};
-
-		can1@1d000 {
-			fsl,flexcan-clock-source = "platform";
-		};
-
 		usb@22000 {
 			phy_type = "utmi";
 		};
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p1010si.dtsi linux-libre-3.2-gnu/arch/powerpc/boot/dts/p1010si.dtsi
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p1010si.dtsi	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p1010si.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -140,20 +140,18 @@
 			interrupt-parent = <&mpic>;
 		};
 
-		can0@1c000 {
-			compatible = "fsl,flexcan-v1.0";
+		can0: can@1c000 {
+			compatible = "fsl,p1010-flexcan";
 			reg = <0x1c000 0x1000>;
 			interrupts = <48 0x2>;
 			interrupt-parent = <&mpic>;
-			fsl,flexcan-clock-divider = <2>;
 		};
 
-		can1@1d000 {
-			compatible = "fsl,flexcan-v1.0";
+		can1: can@1d000 {
+			compatible = "fsl,p1010-flexcan";
 			reg = <0x1d000 0x1000>;
 			interrupts = <61 0x2>;
 			interrupt-parent = <&mpic>;
-			fsl,flexcan-clock-divider = <2>;
 		};
 
 		L2: l2-cache-controller@20000 {
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p1022ds.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/p1022ds.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p1022ds.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p1022ds.dts	2012-01-04 18:55:44.000000000 -0500
@@ -150,7 +150,7 @@
 		};
 
 		board-control@3,0 {
-			compatible = "fsl,p1022ds-pixis";
+			compatible = "fsl,p1022ds-fpga", "fsl,fpga-ngpixis";
 			reg = <3 0 0x30>;
 			interrupt-parent = <&mpic>;
 			/*
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p1023rds.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/p1023rds.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p1023rds.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p1023rds.dts	2012-01-04 18:55:44.000000000 -0500
@@ -449,6 +449,7 @@
 			interrupt-parent = <&mpic>;
 			interrupts = <16 2>;
 			interrupt-map-mask = <0xf800 0 0 7>;
+			/* IRQ[0:3] are pulled up on board, set to active-low */
 			interrupt-map = <
 				/* IDSEL 0x0 */
 				0000 0 0 1 &mpic 0 1
@@ -488,11 +489,15 @@
 			interrupt-parent = <&mpic>;
 			interrupts = <16 2>;
 			interrupt-map-mask = <0xf800 0 0 7>;
+			/*
+			 * IRQ[4:6] only for PCIe, set to active-high,
+			 * IRQ[7] is pulled up on board, set to active-low
+			 */
 			interrupt-map = <
 				/* IDSEL 0x0 */
-				0000 0 0 1 &mpic 4 1
-				0000 0 0 2 &mpic 5 1
-				0000 0 0 3 &mpic 6 1
+				0000 0 0 1 &mpic 4 2
+				0000 0 0 2 &mpic 5 2
+				0000 0 0 3 &mpic 6 2
 				0000 0 0 4 &mpic 7 1
 				>;
 			ranges = <0x2000000 0x0 0xa0000000
@@ -527,12 +532,16 @@
 			interrupt-parent = <&mpic>;
 			interrupts = <16 2>;
 			interrupt-map-mask = <0xf800 0 0 7>;
+			/*
+			 * IRQ[8:10] are pulled up on board, set to active-low
+			 * IRQ[11] only for PCIe, set to active-high,
+			 */
 			interrupt-map = <
 				/* IDSEL 0x0 */
 				0000 0 0 1 &mpic 8 1
 				0000 0 0 2 &mpic 9 1
 				0000 0 0 3 &mpic 10 1
-				0000 0 0 4 &mpic 11 1
+				0000 0 0 4 &mpic 11 2
 				>;
 			ranges = <0x2000000 0x0 0x80000000
 				  0x2000000 0x0 0x80000000
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p2020ds.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/p2020ds.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p2020ds.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p2020ds.dts	2012-01-04 18:55:44.000000000 -0500
@@ -118,6 +118,11 @@
 			};
 		};
 
+		board-control@3,0 {
+			compatible = "fsl,p2020ds-fpga", "fsl,fpga-ngpixis";
+			reg = <0x3 0x0 0x30>;
+		};
+
 		nand@4,0 {
 			compatible = "fsl,elbc-fcm-nand";
 			reg = <0x4 0x0 0x40000>;
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p2040rdb.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/p2040rdb.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p2040rdb.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p2040rdb.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,166 +0,0 @@
-/*
- * P2040RDB Device Tree Source
- *
- * Copyright 2011 Freescale Semiconductor Inc.
- *
- * 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 Freescale Semiconductor nor the
- *       names of its 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") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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/ "p2040si.dtsi"
-
-/ {
-	model = "fsl,P2040RDB";
-	compatible = "fsl,P2040RDB";
-	#address-cells = <2>;
-	#size-cells = <2>;
-	interrupt-parent = <&mpic>;
-
-	memory {
-		device_type = "memory";
-	};
-
-	soc: soc@ffe000000 {
-		spi@110000 {
-			flash@0 {
-				#address-cells = <1>;
-				#size-cells = <1>;
-				compatible = "spansion,s25sl12801";
-				reg = <0>;
-				spi-max-frequency = <40000000>; /* input clock */
-				partition@u-boot {
-					label = "u-boot";
-					reg = <0x00000000 0x00100000>;
-					read-only;
-				};
-				partition@kernel {
-					label = "kernel";
-					reg = <0x00100000 0x00500000>;
-					read-only;
-				};
-				partition@dtb {
-					label = "dtb";
-					reg = <0x00600000 0x00100000>;
-					read-only;
-				};
-				partition@fs {
-					label = "file system";
-					reg = <0x00700000 0x00900000>;
-				};
-			};
-		};
-
-		i2c@118000 {
-			lm75b@48 {
-				compatible = "nxp,lm75a";
-				reg = <0x48>;
-			};
-			eeprom@50 {
-				compatible = "at24,24c256";
-				reg = <0x50>;
-			};
-			rtc@68 {
-				compatible = "pericom,pt7c4338";
-				reg = <0x68>;
-			};
-		};
-
-		i2c@118100 {
-			eeprom@50 {
-				compatible = "at24,24c256";
-				reg = <0x50>;
-			};
-		};
-
-		usb0: usb@210000 {
-			phy_type = "utmi";
-		};
-
-		usb1: usb@211000 {
-			dr_mode = "host";
-			phy_type = "utmi";
-		};
-	};
-
-	localbus@ffe124000 {
-		reg = <0xf 0xfe124000 0 0x1000>;
-		ranges = <0 0 0xf 0xe8000000 0x08000000>;
-
-		flash@0,0 {
-			compatible = "cfi-flash";
-			reg = <0 0 0x08000000>;
-			bank-width = <2>;
-			device-width = <2>;
-		};
-	};
-
-	pci0: pcie@ffe200000 {
-		reg = <0xf 0xfe200000 0 0x1000>;
-		ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
-			  0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
-		pcie@0 {
-			ranges = <0x02000000 0 0xe0000000
-				  0x02000000 0 0xe0000000
-				  0 0x20000000
-
-				  0x01000000 0 0x00000000
-				  0x01000000 0 0x00000000
-				  0 0x00010000>;
-		};
-	};
-
-	pci1: pcie@ffe201000 {
-		reg = <0xf 0xfe201000 0 0x1000>;
-		ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
-			  0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
-		pcie@0 {
-			ranges = <0x02000000 0 0xe0000000
-				  0x02000000 0 0xe0000000
-				  0 0x20000000
-
-				  0x01000000 0 0x00000000
-				  0x01000000 0 0x00000000
-				  0 0x00010000>;
-		};
-	};
-
-	pci2: pcie@ffe202000 {
-		reg = <0xf 0xfe202000 0 0x1000>;
-		ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
-			  0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
-		pcie@0 {
-			ranges = <0x02000000 0 0xe0000000
-				  0x02000000 0 0xe0000000
-				  0 0x20000000
-
-				  0x01000000 0 0x00000000
-				  0x01000000 0 0x00000000
-				  0 0x00010000>;
-		};
-	};
-};
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p2040si.dtsi linux-libre-3.2-gnu/arch/powerpc/boot/dts/p2040si.dtsi
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p2040si.dtsi	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p2040si.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,623 +0,0 @@
-/*
- * P2040 Silicon Device Tree Source
- *
- * Copyright 2011 Freescale Semiconductor Inc.
- *
- * 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 Freescale Semiconductor nor the
- *       names of its 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") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
- */
-
-/dts-v1/;
-
-/ {
-	compatible = "fsl,P2040";
-	#address-cells = <2>;
-	#size-cells = <2>;
-	interrupt-parent = <&mpic>;
-
-	aliases {
-		ccsr = &soc;
-
-		serial0 = &serial0;
-		serial1 = &serial1;
-		serial2 = &serial2;
-		serial3 = &serial3;
-		pci0 = &pci0;
-		pci1 = &pci1;
-		pci2 = &pci2;
-		usb0 = &usb0;
-		usb1 = &usb1;
-		dma0 = &dma0;
-		dma1 = &dma1;
-		sdhc = &sdhc;
-		msi0 = &msi0;
-		msi1 = &msi1;
-		msi2 = &msi2;
-
-		crypto = &crypto;
-		sec_jr0 = &sec_jr0;
-		sec_jr1 = &sec_jr1;
-		sec_jr2 = &sec_jr2;
-		sec_jr3 = &sec_jr3;
-		rtic_a = &rtic_a;
-		rtic_b = &rtic_b;
-		rtic_c = &rtic_c;
-		rtic_d = &rtic_d;
-		sec_mon = &sec_mon;
-	};
-
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		cpu0: PowerPC,e500mc@0 {
-			device_type = "cpu";
-			reg = <0>;
-			next-level-cache = <&L2_0>;
-			L2_0: l2-cache {
-				next-level-cache = <&cpc>;
-			};
-		};
-		cpu1: PowerPC,e500mc@1 {
-			device_type = "cpu";
-			reg = <1>;
-			next-level-cache = <&L2_1>;
-			L2_1: l2-cache {
-				next-level-cache = <&cpc>;
-			};
-		};
-		cpu2: PowerPC,e500mc@2 {
-			device_type = "cpu";
-			reg = <2>;
-			next-level-cache = <&L2_2>;
-			L2_2: l2-cache {
-				next-level-cache = <&cpc>;
-			};
-		};
-		cpu3: PowerPC,e500mc@3 {
-			device_type = "cpu";
-			reg = <3>;
-			next-level-cache = <&L2_3>;
-			L2_3: l2-cache {
-				next-level-cache = <&cpc>;
-			};
-		};
-	};
-
-	soc: soc@ffe000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		device_type = "soc";
-		compatible = "simple-bus";
-		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
-		reg = <0xf 0xfe000000 0 0x00001000>;
-
-		soc-sram-error {
-			compatible = "fsl,soc-sram-error";
-			interrupts = <16 2 1 29>;
-		};
-
-		corenet-law@0 {
-			compatible = "fsl,corenet-law";
-			reg = <0x0 0x1000>;
-			fsl,num-laws = <32>;
-		};
-
-		memory-controller@8000 {
-			compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
-			reg = <0x8000 0x1000>;
-			interrupts = <16 2 1 23>;
-		};
-
-		cpc: l3-cache-controller@10000 {
-			compatible = "fsl,p2040-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
-			reg = <0x10000 0x1000>;
-			interrupts = <16 2 1 27>;
-		};
-
-		corenet-cf@18000 {
-			compatible = "fsl,corenet-cf";
-			reg = <0x18000 0x1000>;
-			interrupts = <16 2 1 31>;
-			fsl,ccf-num-csdids = <32>;
-			fsl,ccf-num-snoopids = <32>;
-		};
-
-		iommu@20000 {
-			compatible = "fsl,pamu-v1.0", "fsl,pamu";
-			reg = <0x20000 0x4000>;
-			interrupts = <
-				24 2 0 0
-				16 2 1 30>;
-		};
-
-		mpic: pic@40000 {
-			clock-frequency = <0>;
-			interrupt-controller;
-			#address-cells = <0>;
-			#interrupt-cells = <4>;
-			reg = <0x40000 0x40000>;
-			compatible = "fsl,mpic", "chrp,open-pic";
-			device_type = "open-pic";
-		};
-
-		msi0: msi@41600 {
-			compatible = "fsl,mpic-msi";
-			reg = <0x41600 0x200>;
-			msi-available-ranges = <0 0x100>;
-			interrupts = <
-				0xe0 0 0 0
-				0xe1 0 0 0
-				0xe2 0 0 0
-				0xe3 0 0 0
-				0xe4 0 0 0
-				0xe5 0 0 0
-				0xe6 0 0 0
-				0xe7 0 0 0>;
-		};
-
-		msi1: msi@41800 {
-			compatible = "fsl,mpic-msi";
-			reg = <0x41800 0x200>;
-			msi-available-ranges = <0 0x100>;
-			interrupts = <
-				0xe8 0 0 0
-				0xe9 0 0 0
-				0xea 0 0 0
-				0xeb 0 0 0
-				0xec 0 0 0
-				0xed 0 0 0
-				0xee 0 0 0
-				0xef 0 0 0>;
-		};
-
-		msi2: msi@41a00 {
-			compatible = "fsl,mpic-msi";
-			reg = <0x41a00 0x200>;
-			msi-available-ranges = <0 0x100>;
-			interrupts = <
-				0xf0 0 0 0
-				0xf1 0 0 0
-				0xf2 0 0 0
-				0xf3 0 0 0
-				0xf4 0 0 0
-				0xf5 0 0 0
-				0xf6 0 0 0
-				0xf7 0 0 0>;
-		};
-
-		guts: global-utilities@e0000 {
-			compatible = "fsl,qoriq-device-config-1.0";
-			reg = <0xe0000 0xe00>;
-			fsl,has-rstcr;
-			#sleep-cells = <1>;
-			fsl,liodn-bits = <12>;
-		};
-
-		pins: global-utilities@e0e00 {
-			compatible = "fsl,qoriq-pin-control-1.0";
-			reg = <0xe0e00 0x200>;
-			#sleep-cells = <2>;
-		};
-
-		clockgen: global-utilities@e1000 {
-			compatible = "fsl,p2040-clockgen", "fsl,qoriq-clockgen-1.0";
-			reg = <0xe1000 0x1000>;
-			clock-frequency = <0>;
-		};
-
-		rcpm: global-utilities@e2000 {
-			compatible = "fsl,qoriq-rcpm-1.0";
-			reg = <0xe2000 0x1000>;
-			#sleep-cells = <1>;
-		};
-
-		sfp: sfp@e8000 {
-			compatible = "fsl,p2040-sfp", "fsl,qoriq-sfp-1.0";
-			reg	   = <0xe8000 0x1000>;
-		};
-
-		serdes: serdes@ea000 {
-			compatible = "fsl,p2040-serdes";
-			reg	   = <0xea000 0x1000>;
-		};
-
-		dma0: dma@100300 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "fsl,p2040-dma", "fsl,eloplus-dma";
-			reg = <0x100300 0x4>;
-			ranges = <0x0 0x100100 0x200>;
-			cell-index = <0>;
-			dma-channel@0 {
-				compatible = "fsl,p2040-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x0 0x80>;
-				cell-index = <0>;
-				interrupts = <28 2 0 0>;
-			};
-			dma-channel@80 {
-				compatible = "fsl,p2040-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x80 0x80>;
-				cell-index = <1>;
-				interrupts = <29 2 0 0>;
-			};
-			dma-channel@100 {
-				compatible = "fsl,p2040-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x100 0x80>;
-				cell-index = <2>;
-				interrupts = <30 2 0 0>;
-			};
-			dma-channel@180 {
-				compatible = "fsl,p2040-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x180 0x80>;
-				cell-index = <3>;
-				interrupts = <31 2 0 0>;
-			};
-		};
-
-		dma1: dma@101300 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "fsl,p2040-dma", "fsl,eloplus-dma";
-			reg = <0x101300 0x4>;
-			ranges = <0x0 0x101100 0x200>;
-			cell-index = <1>;
-			dma-channel@0 {
-				compatible = "fsl,p2040-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x0 0x80>;
-				cell-index = <0>;
-				interrupts = <32 2 0 0>;
-			};
-			dma-channel@80 {
-				compatible = "fsl,p2040-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x80 0x80>;
-				cell-index = <1>;
-				interrupts = <33 2 0 0>;
-			};
-			dma-channel@100 {
-				compatible = "fsl,p2040-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x100 0x80>;
-				cell-index = <2>;
-				interrupts = <34 2 0 0>;
-			};
-			dma-channel@180 {
-				compatible = "fsl,p2040-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x180 0x80>;
-				cell-index = <3>;
-				interrupts = <35 2 0 0>;
-			};
-		};
-
-		spi@110000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,p2040-espi", "fsl,mpc8536-espi";
-			reg = <0x110000 0x1000>;
-			interrupts = <53 0x2 0 0>;
-			fsl,espi-num-chipselects = <4>;
-
-		};
-
-		sdhc: sdhc@114000 {
-			compatible = "fsl,p2040-esdhc", "fsl,esdhc";
-			reg = <0x114000 0x1000>;
-			interrupts = <48 2 0 0>;
-			sdhci,auto-cmd12;
-			clock-frequency = <0>;
-		};
-
-
-		i2c@118000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <0>;
-			compatible = "fsl-i2c";
-			reg = <0x118000 0x100>;
-			interrupts = <38 2 0 0>;
-			dfsrr;
-		};
-
-		i2c@118100 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <1>;
-			compatible = "fsl-i2c";
-			reg = <0x118100 0x100>;
-			interrupts = <38 2 0 0>;
-			dfsrr;
-		};
-
-		i2c@119000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <2>;
-			compatible = "fsl-i2c";
-			reg = <0x119000 0x100>;
-			interrupts = <39 2 0 0>;
-			dfsrr;
-		};
-
-		i2c@119100 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <3>;
-			compatible = "fsl-i2c";
-			reg = <0x119100 0x100>;
-			interrupts = <39 2 0 0>;
-			dfsrr;
-		};
-
-		serial0: serial@11c500 {
-			cell-index = <0>;
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <0x11c500 0x100>;
-			clock-frequency = <0>;
-			interrupts = <36 2 0 0>;
-		};
-
-		serial1: serial@11c600 {
-			cell-index = <1>;
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <0x11c600 0x100>;
-			clock-frequency = <0>;
-			interrupts = <36 2 0 0>;
-		};
-
-		serial2: serial@11d500 {
-			cell-index = <2>;
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <0x11d500 0x100>;
-			clock-frequency = <0>;
-			interrupts = <37 2 0 0>;
-		};
-
-		serial3: serial@11d600 {
-			cell-index = <3>;
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <0x11d600 0x100>;
-			clock-frequency = <0>;
-			interrupts = <37 2 0 0>;
-		};
-
-		gpio0: gpio@130000 {
-			compatible = "fsl,p2040-gpio", "fsl,qoriq-gpio";
-			reg = <0x130000 0x1000>;
-			interrupts = <55 2 0 0>;
-			#gpio-cells = <2>;
-			gpio-controller;
-		};
-
-		usb0: usb@210000 {
-			compatible = "fsl,p2040-usb2-mph",
-					"fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
-			reg = <0x210000 0x1000>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			interrupts = <44 0x2 0 0>;
-			port0;
-		};
-
-		usb1: usb@211000 {
-			compatible = "fsl,p2040-usb2-dr",
-					"fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
-			reg = <0x211000 0x1000>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			interrupts = <45 0x2 0 0>;
-		};
-
-		sata@220000 {
-			compatible = "fsl,p2040-sata", "fsl,pq-sata-v2";
-			reg = <0x220000 0x1000>;
-			interrupts = <68 0x2 0 0>;
-		};
-
-		sata@221000 {
-			compatible = "fsl,p2040-sata", "fsl,pq-sata-v2";
-			reg = <0x221000 0x1000>;
-			interrupts = <69 0x2 0 0>;
-		};
-
-		crypto: crypto@300000 {
-			compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x300000 0x10000>;
-			ranges = <0 0x300000 0x10000>;
-			interrupts = <92 2 0 0>;
-
-			sec_jr0: jr@1000 {
-				compatible = "fsl,sec-v4.2-job-ring",
-					     "fsl,sec-v4.0-job-ring";
-				reg = <0x1000 0x1000>;
-				interrupts = <88 2 0 0>;
-			};
-
-			sec_jr1: jr@2000 {
-				compatible = "fsl,sec-v4.2-job-ring",
-					     "fsl,sec-v4.0-job-ring";
-				reg = <0x2000 0x1000>;
-				interrupts = <89 2 0 0>;
-			};
-
-			sec_jr2: jr@3000 {
-				compatible = "fsl,sec-v4.2-job-ring",
-					     "fsl,sec-v4.0-job-ring";
-				reg = <0x3000 0x1000>;
-				interrupts = <90 2 0 0>;
-			};
-
-			sec_jr3: jr@4000 {
-				compatible = "fsl,sec-v4.2-job-ring",
-					     "fsl,sec-v4.0-job-ring";
-				reg = <0x4000 0x1000>;
-				interrupts = <91 2 0 0>;
-			};
-
-			rtic@6000 {
-				compatible = "fsl,sec-v4.2-rtic",
-					     "fsl,sec-v4.0-rtic";
-				#address-cells = <1>;
-				#size-cells = <1>;
-				reg = <0x6000 0x100>;
-				ranges = <0x0 0x6100 0xe00>;
-
-				rtic_a: rtic-a@0 {
-					compatible = "fsl,sec-v4.2-rtic-memory",
-						     "fsl,sec-v4.0-rtic-memory";
-					reg = <0x00 0x20 0x100 0x80>;
-				};
-
-				rtic_b: rtic-b@20 {
-					compatible = "fsl,sec-v4.2-rtic-memory",
-						     "fsl,sec-v4.0-rtic-memory";
-					reg = <0x20 0x20 0x200 0x80>;
-				};
-
-				rtic_c: rtic-c@40 {
-					compatible = "fsl,sec-v4.2-rtic-memory",
-						     "fsl,sec-v4.0-rtic-memory";
-					reg = <0x40 0x20 0x300 0x80>;
-				};
-
-				rtic_d: rtic-d@60 {
-					compatible = "fsl,sec-v4.2-rtic-memory",
-						     "fsl,sec-v4.0-rtic-memory";
-					reg = <0x60 0x20 0x500 0x80>;
-				};
-			};
-		};
-
-		sec_mon: sec_mon@314000 {
-			compatible = "fsl,sec-v4.2-mon", "fsl,sec-v4.0-mon";
-			reg = <0x314000 0x1000>;
-			interrupts = <93 2 0 0>;
-		};
-
-	};
-
-	localbus@ffe124000 {
-		compatible = "fsl,p2040-elbc", "fsl,elbc", "simple-bus";
-		interrupts = <25 2 0 0>;
-		#address-cells = <2>;
-		#size-cells = <1>;
-	};
-
-	pci0: pcie@ffe200000 {
-		compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
-		device_type = "pci";
-		#size-cells = <2>;
-		#address-cells = <3>;
-		bus-range = <0x0 0xff>;
-		clock-frequency = <0x1fca055>;
-		fsl,msi = <&msi0>;
-		interrupts = <16 2 1 15>;
-		pcie@0 {
-			reg = <0 0 0 0 0>;
-			#interrupt-cells = <1>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			device_type = "pci";
-			interrupts = <16 2 1 15>;
-			interrupt-map-mask = <0xf800 0 0 7>;
-			interrupt-map = <
-				/* IDSEL 0x0 */
-				0000 0 0 1 &mpic 40 1 0 0
-				0000 0 0 2 &mpic 1 1 0 0
-				0000 0 0 3 &mpic 2 1 0 0
-				0000 0 0 4 &mpic 3 1 0 0
-				>;
-		};
-	};
-
-	pci1: pcie@ffe201000 {
-		compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
-		device_type = "pci";
-		#size-cells = <2>;
-		#address-cells = <3>;
-		bus-range = <0 0xff>;
-		clock-frequency = <0x1fca055>;
-		fsl,msi = <&msi1>;
-		interrupts = <16 2 1 14>;
-		pcie@0 {
-			reg = <0 0 0 0 0>;
-			#interrupt-cells = <1>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			device_type = "pci";
-			interrupts = <16 2 1 14>;
-			interrupt-map-mask = <0xf800 0 0 7>;
-			interrupt-map = <
-				/* IDSEL 0x0 */
-				0000 0 0 1 &mpic 41 1 0 0
-				0000 0 0 2 &mpic 5 1 0 0
-				0000 0 0 3 &mpic 6 1 0 0
-				0000 0 0 4 &mpic 7 1 0 0
-				>;
-		};
-	};
-
-	pci2: pcie@ffe202000 {
-		compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
-		device_type = "pci";
-		#size-cells = <2>;
-		#address-cells = <3>;
-		bus-range = <0x0 0xff>;
-		clock-frequency = <0x1fca055>;
-		fsl,msi = <&msi2>;
-		interrupts = <16 2 1 13>;
-		pcie@0 {
-			reg = <0 0 0 0 0>;
-			#interrupt-cells = <1>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			device_type = "pci";
-			interrupts = <16 2 1 13>;
-			interrupt-map-mask = <0xf800 0 0 7>;
-			interrupt-map = <
-				/* IDSEL 0x0 */
-				0000 0 0 1 &mpic 42 1 0 0
-				0000 0 0 2 &mpic 9 1 0 0
-				0000 0 0 3 &mpic 10 1 0 0
-				0000 0 0 4 &mpic 11 1 0 0
-				>;
-		};
-	};
-};
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p2041rdb.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/p2041rdb.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p2041rdb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p2041rdb.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,165 @@
+/*
+ * P2041RDB Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ *       names of its 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") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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/ "p2041si.dtsi"
+
+/ {
+	model = "fsl,P2041RDB";
+	compatible = "fsl,P2041RDB";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	memory {
+		device_type = "memory";
+	};
+
+	dcsr: dcsr@f00000000 {
+		ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+	};
+
+	soc: soc@ffe000000 {
+		spi@110000 {
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "spansion,s25sl12801";
+				reg = <0>;
+				spi-max-frequency = <40000000>; /* input clock */
+				partition@u-boot {
+					label = "u-boot";
+					reg = <0x00000000 0x00100000>;
+					read-only;
+				};
+				partition@kernel {
+					label = "kernel";
+					reg = <0x00100000 0x00500000>;
+					read-only;
+				};
+				partition@dtb {
+					label = "dtb";
+					reg = <0x00600000 0x00100000>;
+					read-only;
+				};
+				partition@fs {
+					label = "file system";
+					reg = <0x00700000 0x00900000>;
+				};
+			};
+		};
+
+		i2c@118000 {
+			lm75b@48 {
+				compatible = "nxp,lm75a";
+				reg = <0x48>;
+			};
+			eeprom@50 {
+				compatible = "at24,24c256";
+				reg = <0x50>;
+			};
+			rtc@68 {
+				compatible = "pericom,pt7c4338";
+				reg = <0x68>;
+			};
+		};
+
+		i2c@118100 {
+			eeprom@50 {
+				compatible = "at24,24c256";
+				reg = <0x50>;
+			};
+		};
+
+		usb1: usb@211000 {
+			dr_mode = "host";
+		};
+	};
+
+	localbus@ffe124000 {
+		reg = <0xf 0xfe124000 0 0x1000>;
+		ranges = <0 0 0xf 0xe8000000 0x08000000>;
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x08000000>;
+			bank-width = <2>;
+			device-width = <2>;
+		};
+	};
+
+	pci0: pcie@ffe200000 {
+		reg = <0xf 0xfe200000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci1: pcie@ffe201000 {
+		reg = <0xf 0xfe201000 0 0x1000>;
+		ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+			  0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci2: pcie@ffe202000 {
+		reg = <0xf 0xfe202000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p2041si.dtsi linux-libre-3.2-gnu/arch/powerpc/boot/dts/p2041si.dtsi
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p2041si.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p2041si.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,692 @@
+/*
+ * P2041 Silicon Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ *       names of its 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") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/dts-v1/;
+
+/ {
+	compatible = "fsl,P2041";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	aliases {
+		ccsr = &soc;
+		dcsr = &dcsr;
+
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+		usb0 = &usb0;
+		usb1 = &usb1;
+		dma0 = &dma0;
+		dma1 = &dma1;
+		sdhc = &sdhc;
+		msi0 = &msi0;
+		msi1 = &msi1;
+		msi2 = &msi2;
+
+		crypto = &crypto;
+		sec_jr0 = &sec_jr0;
+		sec_jr1 = &sec_jr1;
+		sec_jr2 = &sec_jr2;
+		sec_jr3 = &sec_jr3;
+		rtic_a = &rtic_a;
+		rtic_b = &rtic_b;
+		rtic_c = &rtic_c;
+		rtic_d = &rtic_d;
+		sec_mon = &sec_mon;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: PowerPC,e500mc@0 {
+			device_type = "cpu";
+			reg = <0>;
+			next-level-cache = <&L2_0>;
+			L2_0: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu1: PowerPC,e500mc@1 {
+			device_type = "cpu";
+			reg = <1>;
+			next-level-cache = <&L2_1>;
+			L2_1: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu2: PowerPC,e500mc@2 {
+			device_type = "cpu";
+			reg = <2>;
+			next-level-cache = <&L2_2>;
+			L2_2: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu3: PowerPC,e500mc@3 {
+			device_type = "cpu";
+			reg = <3>;
+			next-level-cache = <&L2_3>;
+			L2_3: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+	};
+
+	dcsr: dcsr@f00000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,dcsr", "simple-bus";
+
+		dcsr-epu@0 {
+			compatible = "fsl,dcsr-epu";
+			interrupts = <52 2 0 0
+				      84 2 0 0
+				      85 2 0 0>;
+			interrupt-parent = <&mpic>;
+			reg = <0x0 0x1000>;
+		};
+		dcsr-npc {
+			compatible = "fsl,dcsr-npc";
+			reg = <0x1000 0x1000 0x1000000 0x8000>;
+		};
+		dcsr-nxc@2000 {
+			compatible = "fsl,dcsr-nxc";
+			reg = <0x2000 0x1000>;
+		};
+		dcsr-corenet {
+			compatible = "fsl,dcsr-corenet";
+			reg = <0x8000 0x1000 0xB0000 0x1000>;
+		};
+		dcsr-dpaa@9000 {
+			compatible = "fsl,p2041-dcsr-dpaa", "fsl,dcsr-dpaa";
+			reg = <0x9000 0x1000>;
+		};
+		dcsr-ocn@11000 {
+			compatible = "fsl,p2041-dcsr-ocn", "fsl,dcsr-ocn";
+			reg = <0x11000 0x1000>;
+		};
+		dcsr-ddr@12000 {
+			compatible = "fsl,dcsr-ddr";
+			dev-handle = <&ddr>;
+			reg = <0x12000 0x1000>;
+		};
+		dcsr-nal@18000 {
+			compatible = "fsl,p2041-dcsr-nal", "fsl,dcsr-nal";
+			reg = <0x18000 0x1000>;
+		};
+		dcsr-rcpm@22000 {
+			compatible = "fsl,p2041-dcsr-rcpm", "fsl,dcsr-rcpm";
+			reg = <0x22000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@40000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu0>;
+			reg = <0x40000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@41000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu1>;
+			reg = <0x41000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@42000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu2>;
+			reg = <0x42000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@43000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu3>;
+			reg = <0x43000 0x1000>;
+		};
+	};
+
+	soc: soc@ffe000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "simple-bus";
+		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+		reg = <0xf 0xfe000000 0 0x00001000>;
+
+		soc-sram-error {
+			compatible = "fsl,soc-sram-error";
+			interrupts = <16 2 1 29>;
+		};
+
+		corenet-law@0 {
+			compatible = "fsl,corenet-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <32>;
+		};
+
+		ddr: memory-controller@8000 {
+			compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+			reg = <0x8000 0x1000>;
+			interrupts = <16 2 1 23>;
+		};
+
+		cpc: l3-cache-controller@10000 {
+			compatible = "fsl,p2041-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
+			reg = <0x10000 0x1000>;
+			interrupts = <16 2 1 27>;
+		};
+
+		corenet-cf@18000 {
+			compatible = "fsl,corenet-cf";
+			reg = <0x18000 0x1000>;
+			interrupts = <16 2 1 31>;
+			fsl,ccf-num-csdids = <32>;
+			fsl,ccf-num-snoopids = <32>;
+		};
+
+		iommu@20000 {
+			compatible = "fsl,pamu-v1.0", "fsl,pamu";
+			reg = <0x20000 0x4000>;
+			interrupts = <
+				24 2 0 0
+				16 2 1 30>;
+		};
+
+		mpic: pic@40000 {
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <4>;
+			reg = <0x40000 0x40000>;
+			compatible = "fsl,mpic", "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		msi0: msi@41600 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41600 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0 0 0
+				0xe1 0 0 0
+				0xe2 0 0 0
+				0xe3 0 0 0
+				0xe4 0 0 0
+				0xe5 0 0 0
+				0xe6 0 0 0
+				0xe7 0 0 0>;
+		};
+
+		msi1: msi@41800 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41800 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe8 0 0 0
+				0xe9 0 0 0
+				0xea 0 0 0
+				0xeb 0 0 0
+				0xec 0 0 0
+				0xed 0 0 0
+				0xee 0 0 0
+				0xef 0 0 0>;
+		};
+
+		msi2: msi@41a00 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41a00 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xf0 0 0 0
+				0xf1 0 0 0
+				0xf2 0 0 0
+				0xf3 0 0 0
+				0xf4 0 0 0
+				0xf5 0 0 0
+				0xf6 0 0 0
+				0xf7 0 0 0>;
+		};
+
+		guts: global-utilities@e0000 {
+			compatible = "fsl,qoriq-device-config-1.0";
+			reg = <0xe0000 0xe00>;
+			fsl,has-rstcr;
+			#sleep-cells = <1>;
+			fsl,liodn-bits = <12>;
+		};
+
+		pins: global-utilities@e0e00 {
+			compatible = "fsl,qoriq-pin-control-1.0";
+			reg = <0xe0e00 0x200>;
+			#sleep-cells = <2>;
+		};
+
+		clockgen: global-utilities@e1000 {
+			compatible = "fsl,p2041-clockgen", "fsl,qoriq-clockgen-1.0";
+			reg = <0xe1000 0x1000>;
+			clock-frequency = <0>;
+		};
+
+		rcpm: global-utilities@e2000 {
+			compatible = "fsl,qoriq-rcpm-1.0";
+			reg = <0xe2000 0x1000>;
+			#sleep-cells = <1>;
+		};
+
+		sfp: sfp@e8000 {
+			compatible = "fsl,p2041-sfp", "fsl,qoriq-sfp-1.0";
+			reg	   = <0xe8000 0x1000>;
+		};
+
+		serdes: serdes@ea000 {
+			compatible = "fsl,p2041-serdes";
+			reg	   = <0xea000 0x1000>;
+		};
+
+		dma0: dma@100300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p2041-dma", "fsl,eloplus-dma";
+			reg = <0x100300 0x4>;
+			ranges = <0x0 0x100100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,p2041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupts = <28 2 0 0>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p2041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupts = <29 2 0 0>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p2041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupts = <30 2 0 0>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p2041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupts = <31 2 0 0>;
+			};
+		};
+
+		dma1: dma@101300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p2041-dma", "fsl,eloplus-dma";
+			reg = <0x101300 0x4>;
+			ranges = <0x0 0x101100 0x200>;
+			cell-index = <1>;
+			dma-channel@0 {
+				compatible = "fsl,p2041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupts = <32 2 0 0>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p2041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupts = <33 2 0 0>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p2041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupts = <34 2 0 0>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p2041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupts = <35 2 0 0>;
+			};
+		};
+
+		spi@110000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,p2041-espi", "fsl,mpc8536-espi";
+			reg = <0x110000 0x1000>;
+			interrupts = <53 0x2 0 0>;
+			fsl,espi-num-chipselects = <4>;
+		};
+
+		sdhc: sdhc@114000 {
+			compatible = "fsl,p2041-esdhc", "fsl,esdhc";
+			reg = <0x114000 0x1000>;
+			interrupts = <48 2 0 0>;
+			sdhci,auto-cmd12;
+			clock-frequency = <0>;
+		};
+
+		i2c@118000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x118000 0x100>;
+			interrupts = <38 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@118100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x118100 0x100>;
+			interrupts = <38 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@119000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <2>;
+			compatible = "fsl-i2c";
+			reg = <0x119000 0x100>;
+			interrupts = <39 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@119100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <3>;
+			compatible = "fsl-i2c";
+			reg = <0x119100 0x100>;
+			interrupts = <39 2 0 0>;
+			dfsrr;
+		};
+
+		serial0: serial@11c500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11c500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <36 2 0 0>;
+		};
+
+		serial1: serial@11c600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11c600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <36 2 0 0>;
+		};
+
+		serial2: serial@11d500 {
+			cell-index = <2>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11d500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <37 2 0 0>;
+		};
+
+		serial3: serial@11d600 {
+			cell-index = <3>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11d600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <37 2 0 0>;
+		};
+
+		gpio0: gpio@130000 {
+			compatible = "fsl,p2041-gpio", "fsl,qoriq-gpio";
+			reg = <0x130000 0x1000>;
+			interrupts = <55 2 0 0>;
+			#gpio-cells = <2>;
+			gpio-controller;
+		};
+
+		usb0: usb@210000 {
+			compatible = "fsl,p2041-usb2-mph",
+					"fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+			reg = <0x210000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <44 0x2 0 0>;
+			phy_type = "utmi";
+			port0;
+		};
+
+		usb1: usb@211000 {
+			compatible = "fsl,p2041-usb2-dr",
+					"fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+			reg = <0x211000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <45 0x2 0 0>;
+			phy_type = "utmi";
+		};
+
+		sata@220000 {
+			compatible = "fsl,p2041-sata", "fsl,pq-sata-v2";
+			reg = <0x220000 0x1000>;
+			interrupts = <68 0x2 0 0>;
+		};
+
+		sata@221000 {
+			compatible = "fsl,p2041-sata", "fsl,pq-sata-v2";
+			reg = <0x221000 0x1000>;
+			interrupts = <69 0x2 0 0>;
+		};
+
+		crypto: crypto@300000 {
+			compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x300000 0x10000>;
+			ranges = <0 0x300000 0x10000>;
+			interrupts = <92 2 0 0>;
+
+			sec_jr0: jr@1000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x1000 0x1000>;
+				interrupts = <88 2 0 0>;
+			};
+
+			sec_jr1: jr@2000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x2000 0x1000>;
+				interrupts = <89 2 0 0>;
+			};
+
+			sec_jr2: jr@3000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x3000 0x1000>;
+				interrupts = <90 2 0 0>;
+			};
+
+			sec_jr3: jr@4000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x4000 0x1000>;
+				interrupts = <91 2 0 0>;
+			};
+
+			rtic@6000 {
+				compatible = "fsl,sec-v4.2-rtic",
+					     "fsl,sec-v4.0-rtic";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x6000 0x100>;
+				ranges = <0x0 0x6100 0xe00>;
+
+				rtic_a: rtic-a@0 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x00 0x20 0x100 0x80>;
+				};
+
+				rtic_b: rtic-b@20 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x20 0x20 0x200 0x80>;
+				};
+
+				rtic_c: rtic-c@40 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x40 0x20 0x300 0x80>;
+				};
+
+				rtic_d: rtic-d@60 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x60 0x20 0x500 0x80>;
+				};
+			};
+		};
+
+		sec_mon: sec_mon@314000 {
+			compatible = "fsl,sec-v4.2-mon", "fsl,sec-v4.0-mon";
+			reg = <0x314000 0x1000>;
+			interrupts = <93 2 0 0>;
+		};
+
+	};
+
+	localbus@ffe124000 {
+		compatible = "fsl,p2041-elbc", "fsl,elbc", "simple-bus";
+		interrupts = <25 2 0 0>;
+		#address-cells = <2>;
+		#size-cells = <1>;
+	};
+
+	pci0: pcie@ffe200000 {
+		compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0x0 0xff>;
+		clock-frequency = <33333333>;
+		fsl,msi = <&msi0>;
+		interrupts = <16 2 1 15>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 15>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 40 1 0 0
+				0000 0 0 2 &mpic 1 1 0 0
+				0000 0 0 3 &mpic 2 1 0 0
+				0000 0 0 4 &mpic 3 1 0 0
+				>;
+		};
+	};
+
+	pci1: pcie@ffe201000 {
+		compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0 0xff>;
+		clock-frequency = <33333333>;
+		fsl,msi = <&msi1>;
+		interrupts = <16 2 1 14>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 14>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 41 1 0 0
+				0000 0 0 2 &mpic 5 1 0 0
+				0000 0 0 3 &mpic 6 1 0 0
+				0000 0 0 4 &mpic 7 1 0 0
+				>;
+		};
+	};
+
+	pci2: pcie@ffe202000 {
+		compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0x0 0xff>;
+		clock-frequency = <33333333>;
+		fsl,msi = <&msi2>;
+		interrupts = <16 2 1 13>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 13>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 42 1 0 0
+				0000 0 0 2 &mpic 9 1 0 0
+				0000 0 0 3 &mpic 10 1 0 0
+				0000 0 0 4 &mpic 11 1 0 0
+				>;
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p3041ds.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/p3041ds.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p3041ds.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p3041ds.dts	2012-01-04 18:55:44.000000000 -0500
@@ -45,6 +45,10 @@
 		device_type = "memory";
 	};
 
+	dcsr: dcsr@f00000000 {
+		ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+	};
+
 	soc: soc@ffe000000 {
 		spi@110000 {
 			flash@0 {
@@ -147,8 +151,8 @@
 		};
 
 		board-control@3,0 {
-			compatible = "fsl,p3041ds-pixis";
-			reg = <3 0 0x20>;
+			compatible = "fsl,p3041ds-fpga", "fsl,fpga-ngpixis";
+			reg = <3 0 0x30>;
 		};
 	};
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p3041si.dtsi linux-libre-3.2-gnu/arch/powerpc/boot/dts/p3041si.dtsi
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p3041si.dtsi	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p3041si.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
 
 	aliases {
 		ccsr = &soc;
+		dcsr = &dcsr;
 
 		serial0 = &serial0;
 		serial1 = &serial1;
@@ -114,6 +115,74 @@
 		};
 	};
 
+	dcsr: dcsr@f00000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,dcsr", "simple-bus";
+
+		dcsr-epu@0 {
+			compatible = "fsl,dcsr-epu";
+			interrupts = <52 2 0 0
+				      84 2 0 0
+				      85 2 0 0>;
+			interrupt-parent = <&mpic>;
+			reg = <0x0 0x1000>;
+		};
+		dcsr-npc {
+			compatible = "fsl,dcsr-npc";
+			reg = <0x1000 0x1000 0x1000000 0x8000>;
+		};
+		dcsr-nxc@2000 {
+			compatible = "fsl,dcsr-nxc";
+			reg = <0x2000 0x1000>;
+		};
+		dcsr-corenet {
+			compatible = "fsl,dcsr-corenet";
+			reg = <0x8000 0x1000 0xB0000 0x1000>;
+		};
+		dcsr-dpaa@9000 {
+			compatible = "fsl,p43041-dcsr-dpaa", "fsl,dcsr-dpaa";
+			reg = <0x9000 0x1000>;
+		};
+		dcsr-ocn@11000 {
+			compatible = "fsl,p43041-dcsr-ocn", "fsl,dcsr-ocn";
+			reg = <0x11000 0x1000>;
+		};
+		dcsr-ddr@12000 {
+			compatible = "fsl,dcsr-ddr";
+			dev-handle = <&ddr>;
+			reg = <0x12000 0x1000>;
+		};
+		dcsr-nal@18000 {
+			compatible = "fsl,p43041-dcsr-nal", "fsl,dcsr-nal";
+			reg = <0x18000 0x1000>;
+		};
+		dcsr-rcpm@22000 {
+			compatible = "fsl,p43041-dcsr-rcpm", "fsl,dcsr-rcpm";
+			reg = <0x22000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@40000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu0>;
+			reg = <0x40000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@41000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu1>;
+			reg = <0x41000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@42000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu2>;
+			reg = <0x42000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@43000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu3>;
+			reg = <0x43000 0x1000>;
+		};
+	};
+
 	soc: soc@ffe000000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -133,7 +202,7 @@
 			fsl,num-laws = <32>;
 		};
 
-		memory-controller@8000 {
+		ddr: memory-controller@8000 {
 			compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
 			reg = <0x8000 0x1000>;
 			interrupts = <16 2 1 23>;
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p3060qds.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/p3060qds.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p3060qds.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p3060qds.dts	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,238 @@
+/*
+ * P3060QDS Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ *       names of its 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") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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/ "p3060si.dtsi"
+
+/ {
+	model = "fsl,P3060QDS";
+	compatible = "fsl,P3060QDS";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	memory {
+		device_type = "memory";
+	};
+
+	dcsr: dcsr@f00000000 {
+		ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+	};
+
+	soc: soc@ffe000000 {
+		spi@110000 {
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "spansion,s25sl12801";
+				reg = <0>;
+				spi-max-frequency = <40000000>; /* input clock */
+				partition@u-boot {
+					label = "u-boot";
+					reg = <0x00000000 0x00100000>;
+					read-only;
+				};
+				partition@kernel {
+					label = "kernel";
+					reg = <0x00100000 0x00500000>;
+					read-only;
+				};
+				partition@dtb {
+					label = "dtb";
+					reg = <0x00600000 0x00100000>;
+					read-only;
+				};
+				partition@fs {
+					label = "file system";
+					reg = <0x00700000 0x00900000>;
+				};
+			};
+			flash@1 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "spansion,en25q32b";
+				reg = <1>;
+				spi-max-frequency = <40000000>; /* input clock */
+				partition@spi1 {
+					label = "spi1";
+					reg = <0x00000000 0x00400000>;
+				};
+			};
+			flash@2 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "atmel,at45db081d";
+				reg = <2>;
+				spi-max-frequency = <40000000>; /* input clock */
+				partition@spi1 {
+					label = "spi2";
+					reg = <0x00000000 0x00100000>;
+				};
+			};
+			flash@3 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "spansion,sst25wf040";
+				reg = <3>;
+				spi-max-frequency = <40000000>; /* input clock */
+				partition@spi3 {
+					label = "spi3";
+					reg = <0x00000000 0x00080000>;
+				};
+			};
+		};
+
+		i2c@118000 {
+			eeprom@51 {
+				compatible = "at24,24c256";
+				reg = <0x51>;
+			};
+			eeprom@53 {
+				compatible = "at24,24c256";
+				reg = <0x53>;
+			};
+			rtc@68 {
+				compatible = "dallas,ds3232";
+				reg = <0x68>;
+				interrupts = <0x1 0x1 0 0>;
+			};
+		};
+
+		usb0: usb@210000 {
+			phy_type = "ulpi";
+		};
+
+		usb1: usb@211000 {
+			dr_mode = "host";
+			phy_type = "ulpi";
+		};
+	};
+
+	rapidio@ffe0c0000 {
+		reg = <0xf 0xfe0c0000 0 0x11000>;
+
+		port1 {
+			ranges = <0 0 0xc 0x20000000 0 0x10000000>;
+		};
+		port2 {
+			ranges = <0 0 0xc 0x30000000 0 0x10000000>;
+		};
+	};
+
+	localbus@ffe124000 {
+		reg = <0xf 0xfe124000 0 0x1000>;
+		ranges = <0 0 0xf 0xe8000000 0x08000000
+			  2 0 0xf 0xffa00000 0x00040000
+			  3 0 0xf 0xffdf0000 0x00008000>;
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x08000000>;
+			bank-width = <2>;
+			device-width = <2>;
+		};
+
+		nand@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,elbc-fcm-nand";
+			reg = <0x2 0x0 0x40000>;
+
+			partition@0 {
+				label = "NAND U-Boot Image";
+				reg = <0x0 0x02000000>;
+				read-only;
+			};
+
+			partition@2000000 {
+				label = "NAND Root File System";
+				reg = <0x02000000 0x10000000>;
+			};
+
+			partition@12000000 {
+				label = "NAND Compressed RFS Image";
+				reg = <0x12000000 0x08000000>;
+			};
+
+			partition@1a000000 {
+				label = "NAND Linux Kernel Image";
+				reg = <0x1a000000 0x04000000>;
+			};
+
+			partition@1e000000 {
+				label = "NAND DTB Image";
+				reg = <0x1e000000 0x01000000>;
+			};
+
+			partition@1f000000 {
+				label = "NAND Writable User area";
+				reg = <0x1f000000 0x21000000>;
+			};
+		};
+
+		board-control@3,0 {
+			compatible = "fsl,p3060qds-fpga", "fsl,fpga-qixis";
+			reg = <3 0 0x100>;
+		};
+	};
+
+	pci0: pcie@ffe200000 {
+		reg = <0xf 0xfe200000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci1: pcie@ffe201000 {
+		reg = <0xf 0xfe201000 0 0x1000>;
+		ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+			  0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p3060si.dtsi linux-libre-3.2-gnu/arch/powerpc/boot/dts/p3060si.dtsi
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p3060si.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p3060si.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,719 @@
+/*
+ * P3060 Silicon Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * 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 Freescale Semiconductor nor the
+ *       names of its 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") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+/dts-v1/;
+
+/ {
+	compatible = "fsl,P3060";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	aliases {
+		ccsr = &soc;
+		dcsr = &dcsr;
+
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		usb0 = &usb0;
+		usb1 = &usb1;
+		dma0 = &dma0;
+		dma1 = &dma1;
+		msi0 = &msi0;
+		msi1 = &msi1;
+		msi2 = &msi2;
+
+		crypto = &crypto;
+		sec_jr0 = &sec_jr0;
+		sec_jr1 = &sec_jr1;
+		sec_jr2 = &sec_jr2;
+		sec_jr3 = &sec_jr3;
+		rtic_a = &rtic_a;
+		rtic_b = &rtic_b;
+		rtic_c = &rtic_c;
+		rtic_d = &rtic_d;
+		sec_mon = &sec_mon;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: PowerPC,e500mc@0 {
+			device_type = "cpu";
+			reg = <0>;
+			next-level-cache = <&L2_0>;
+			L2_0: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu1: PowerPC,e500mc@1 {
+			device_type = "cpu";
+			reg = <1>;
+			next-level-cache = <&L2_1>;
+			L2_1: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu4: PowerPC,e500mc@4 {
+			device_type = "cpu";
+			reg = <4>;
+			next-level-cache = <&L2_4>;
+			L2_4: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu5: PowerPC,e500mc@5 {
+			device_type = "cpu";
+			reg = <5>;
+			next-level-cache = <&L2_5>;
+			L2_5: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu6: PowerPC,e500mc@6 {
+			device_type = "cpu";
+			reg = <6>;
+			next-level-cache = <&L2_6>;
+			L2_6: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu7: PowerPC,e500mc@7 {
+			device_type = "cpu";
+			reg = <7>;
+			next-level-cache = <&L2_7>;
+			L2_7: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+	};
+
+	dcsr: dcsr@f00000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,dcsr", "simple-bus";
+
+		dcsr-epu@0 {
+			compatible = "fsl,dcsr-epu";
+			interrupts = <52 2 0 0
+				      84 2 0 0
+				      85 2 0 0>;
+			interrupt-parent = <&mpic>;
+			reg = <0x0 0x1000>;
+		};
+		dcsr-npc {
+			compatible = "fsl,dcsr-npc";
+			reg = <0x1000 0x1000 0x1000000 0x8000>;
+		};
+		dcsr-nxc@2000 {
+			compatible = "fsl,dcsr-nxc";
+			reg = <0x2000 0x1000>;
+		};
+		dcsr-corenet {
+			compatible = "fsl,dcsr-corenet";
+			reg = <0x8000 0x1000 0xB0000 0x1000>;
+		};
+		dcsr-dpaa@9000 {
+			compatible = "fsl,p3060-dcsr-dpaa", "fsl,dcsr-dpaa";
+			reg = <0x9000 0x1000>;
+		};
+		dcsr-ocn@11000 {
+			compatible = "fsl,p3060-dcsr-ocn", "fsl,dcsr-ocn";
+			reg = <0x11000 0x1000>;
+		};
+		dcsr-ddr@12000 {
+			compatible = "fsl,dcsr-ddr";
+			dev-handle = <&ddr>;
+			reg = <0x12000 0x1000>;
+		};
+		dcsr-nal@18000 {
+			compatible = "fsl,p3060-dcsr-nal", "fsl,dcsr-nal";
+			reg = <0x18000 0x1000>;
+		};
+		dcsr-rcpm@22000 {
+			compatible = "fsl,p3060-dcsr-rcpm", "fsl,dcsr-rcpm";
+			reg = <0x22000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@40000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu0>;
+			reg = <0x40000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@41000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu1>;
+			reg = <0x41000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@44000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu4>;
+			reg = <0x44000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@45000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu5>;
+			reg = <0x45000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@46000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu6>;
+			reg = <0x46000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@47000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu7>;
+			reg = <0x47000 0x1000>;
+		};
+	};
+
+	soc: soc@ffe000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "simple-bus";
+		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+		reg = <0xf 0xfe000000 0 0x00001000>;
+
+		soc-sram-error {
+			compatible = "fsl,soc-sram-error";
+			interrupts = <16 2 1 29>;
+		};
+
+		corenet-law@0 {
+			compatible = "fsl,corenet-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <32>;
+		};
+
+		ddr: memory-controller@8000 {
+			compatible = "fsl,qoriq-memory-controller-v4.4", "fsl,qoriq-memory-controller";
+			reg = <0x8000 0x1000>;
+			interrupts = <16 2 1 23>;
+		};
+
+		cpc: l3-cache-controller@10000 {
+			compatible = "fsl,p3060-l3-cache-controller", "cache";
+			reg = <0x10000 0x1000
+			       0x11000 0x1000>;
+			interrupts = <16 2 1 27>;
+		};
+
+		corenet-cf@18000 {
+			compatible = "fsl,corenet-cf";
+			reg = <0x18000 0x1000>;
+			interrupts = <16 2 1 31>;
+			fsl,ccf-num-csdids = <32>;
+			fsl,ccf-num-snoopids = <32>;
+		};
+
+		iommu@20000 {
+			compatible = "fsl,pamu-v1.0", "fsl,pamu";
+			reg = <0x20000 0x5000>;
+			interrupts = <
+				24 2 0 0
+				16 2 1 30>;
+		};
+
+		mpic: pic@40000 {
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <4>;
+			reg = <0x40000 0x40000>;
+			compatible = "fsl,mpic", "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		msi0: msi@41600 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41600 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0 0 0
+				0xe1 0 0 0
+				0xe2 0 0 0
+				0xe3 0 0 0
+				0xe4 0 0 0
+				0xe5 0 0 0
+				0xe6 0 0 0
+				0xe7 0 0 0>;
+		};
+
+		msi1: msi@41800 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41800 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe8 0 0 0
+				0xe9 0 0 0
+				0xea 0 0 0
+				0xeb 0 0 0
+				0xec 0 0 0
+				0xed 0 0 0
+				0xee 0 0 0
+				0xef 0 0 0>;
+		};
+
+		msi2: msi@41a00 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41a00 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xf0 0 0 0
+				0xf1 0 0 0
+				0xf2 0 0 0
+				0xf3 0 0 0
+				0xf4 0 0 0
+				0xf5 0 0 0
+				0xf6 0 0 0
+				0xf7 0 0 0>;
+		};
+
+		rmu: rmu@d3000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,srio-rmu";
+			reg = <0xd3000 0x500>;
+			ranges = <0x0 0xd3000 0x500>;
+
+			message-unit@0 {
+				compatible = "fsl,srio-msg-unit";
+				reg = <0x0 0x100>;
+				interrupts = <
+					60 2 0 0  /* msg1_tx_irq */
+					61 2 0 0>;/* msg1_rx_irq */
+			};
+			message-unit@100 {
+				compatible = "fsl,srio-msg-unit";
+				reg = <0x100 0x100>;
+				interrupts = <
+					62 2 0 0  /* msg2_tx_irq */
+					63 2 0 0>;/* msg2_rx_irq */
+			};
+			doorbell-unit@400 {
+				compatible = "fsl,srio-dbell-unit";
+				reg = <0x400 0x80>;
+				interrupts = <
+					56 2 0 0  /* bell_outb_irq */
+					57 2 0 0>;/* bell_inb_irq */
+			};
+			port-write-unit@4e0 {
+				compatible = "fsl,srio-port-write-unit";
+				reg = <0x4e0 0x20>;
+				interrupts = <16 2 1 11>;
+			};
+		};
+
+		guts: global-utilities@e0000 {
+			compatible = "fsl,qoriq-device-config-1.0";
+			reg = <0xe0000 0xe00>;
+			fsl,has-rstcr;
+			#sleep-cells = <1>;
+			fsl,liodn-bits = <12>;
+		};
+
+		pins: global-utilities@e0e00 {
+			compatible = "fsl,qoriq-pin-control-1.0";
+			reg = <0xe0e00 0x200>;
+			#sleep-cells = <2>;
+		};
+
+		clockgen: global-utilities@e1000 {
+			compatible = "fsl,p3060-clockgen", "fsl,qoriq-clockgen-1.0";
+			reg = <0xe1000 0x1000>;
+			clock-frequency = <0>;
+		};
+
+		rcpm: global-utilities@e2000 {
+			compatible = "fsl,qoriq-rcpm-1.0";
+			reg = <0xe2000 0x1000>;
+			#sleep-cells = <1>;
+		};
+
+		sfp: sfp@e8000 {
+			compatible = "fsl,p3060-sfp", "fsl,qoriq-sfp-1.0";
+			reg	   = <0xe8000 0x1000>;
+		};
+
+		serdes: serdes@ea000 {
+			compatible = "fsl,p3060-serdes";
+			reg	   = <0xea000 0x1000>;
+		};
+
+		dma0: dma@100300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p3060-dma", "fsl,eloplus-dma";
+			reg = <0x100300 0x4>;
+			ranges = <0x0 0x100100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,p3060-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupts = <28 2 0 0>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p3060-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupts = <29 2 0 0>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p3060-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupts = <30 2 0 0>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p3060-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupts = <31 2 0 0>;
+			};
+		};
+
+		dma1: dma@101300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p3060-dma", "fsl,eloplus-dma";
+			reg = <0x101300 0x4>;
+			ranges = <0x0 0x101100 0x200>;
+			cell-index = <1>;
+			dma-channel@0 {
+				compatible = "fsl,p3060-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupts = <32 2 0 0>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p3060-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupts = <33 2 0 0>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p3060-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupts = <34 2 0 0>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p3060-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupts = <35 2 0 0>;
+			};
+		};
+
+		spi@110000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,p3060-espi", "fsl,mpc8536-espi";
+			reg = <0x110000 0x1000>;
+			interrupts = <53 0x2 0 0>;
+			fsl,espi-num-chipselects = <4>;
+		};
+
+		i2c@118000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x118000 0x100>;
+			interrupts = <38 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@118100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x118100 0x100>;
+			interrupts = <38 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@119000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <2>;
+			compatible = "fsl-i2c";
+			reg = <0x119000 0x100>;
+			interrupts = <39 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@119100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <3>;
+			compatible = "fsl-i2c";
+			reg = <0x119100 0x100>;
+			interrupts = <39 2 0 0>;
+			dfsrr;
+		};
+
+		serial0: serial@11c500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11c500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <36 2 0 0>;
+		};
+
+		serial1: serial@11c600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11c600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <36 2 0 0>;
+		};
+
+		serial2: serial@11d500 {
+			cell-index = <2>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11d500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <37 2 0 0>;
+		};
+
+		serial3: serial@11d600 {
+			cell-index = <3>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11d600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <37 2 0 0>;
+		};
+
+		gpio0: gpio@130000 {
+			compatible = "fsl,p3060-gpio", "fsl,qoriq-gpio";
+			reg = <0x130000 0x1000>;
+			interrupts = <55 2 0 0>;
+			#gpio-cells = <2>;
+			gpio-controller;
+		};
+
+		usb0: usb@210000 {
+			compatible = "fsl,p3060-usb2-mph",
+					"fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+			reg = <0x210000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <44 0x2 0 0>;
+		};
+
+		usb1: usb@211000 {
+			compatible = "fsl,p3060-usb2-dr",
+					"fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+			reg = <0x211000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <45 0x2 0 0>;
+		};
+
+		crypto: crypto@300000 {
+			compatible = "fsl,sec-v4.1", "fsl,sec-v4.0";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x300000 0x10000>;
+			ranges = <0 0x300000 0x10000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <92 2 0 0>;
+
+			sec_jr0: jr@1000 {
+				compatible = "fsl,sec-v4.1-job-ring", "fsl,sec-v4.0-job-ring";
+				reg = <0x1000 0x1000>;
+				interrupt-parent = <&mpic>;
+				interrupts = <88 2 0 0>;
+			};
+
+			sec_jr1: jr@2000 {
+				compatible = "fsl,sec-v4.1-job-ring", "fsl,sec-v4.0-job-ring";
+				reg = <0x2000 0x1000>;
+				interrupt-parent = <&mpic>;
+				interrupts = <89 2 0 0>;
+			};
+
+			sec_jr2: jr@3000 {
+				compatible = "fsl,sec-v4.1-job-ring", "fsl,sec-v4.0-job-ring";
+				reg = <0x3000 0x1000>;
+				interrupt-parent = <&mpic>;
+				interrupts = <90 2 0 0>;
+			};
+
+			sec_jr3: jr@4000 {
+				compatible = "fsl,sec-v4.1-job-ring", "fsl,sec-v4.0-job-ring";
+				reg = <0x4000 0x1000>;
+				interrupt-parent = <&mpic>;
+				interrupts = <91 2 0 0>;
+			};
+
+			rtic@6000 {
+				compatible = "fsl,sec-v4.1-rtic", "fsl,sec-v4.0-rtic";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x6000 0x100>;
+				ranges = <0x0 0x6100 0xe00>;
+
+				rtic_a: rtic-a@0 {
+					compatible = "fsl,sec-v4.1-rtic-memory", "fsl,sec-v4.0-rtic-memory";
+					reg = <0x00 0x20 0x100 0x80>;
+				};
+
+				rtic_b: rtic-b@20 {
+					compatible = "fsl,sec-v4.1-rtic-memory", "fsl,sec-v4.0-rtic-memory";
+					reg = <0x20 0x20 0x200 0x80>;
+				};
+
+				rtic_c: rtic-c@40 {
+					compatible = "fsl,sec-v4.1-rtic-memory", "fsl,sec-v4.0-rtic-memory";
+					reg = <0x40 0x20 0x300 0x80>;
+				};
+
+				rtic_d: rtic-d@60 {
+					compatible = "fsl,sec-v4.1-rtic-memory", "fsl,sec-v4.0-rtic-memory";
+					reg = <0x60 0x20 0x500 0x80>;
+				};
+			};
+		};
+
+		sec_mon: sec_mon@314000 {
+			compatible = "fsl,sec-v4.1-mon", "fsl,sec-v4.0-mon";
+			reg = <0x314000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <93 2 0 0>;
+		};
+	};
+
+	rapidio@ffe0c0000 {
+		compatible = "fsl,srio";
+		interrupts = <16 2 1 11>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		fsl,srio-rmu-handle = <&rmu>;
+		ranges;
+
+		port1 {
+			#address-cells = <2>;
+			#size-cells = <2>;
+			cell-index = <1>;
+		};
+
+		port2 {
+			#address-cells = <2>;
+			#size-cells = <2>;
+			cell-index = <2>;
+		};
+	};
+
+	localbus@ffe124000 {
+		compatible = "fsl,p3060-elbc", "fsl,elbc", "simple-bus";
+		interrupts = <25 2 0 0>;
+		#address-cells = <2>;
+		#size-cells = <1>;
+	};
+
+	pci0: pcie@ffe200000 {
+		compatible = "fsl,p3060-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0x0 0xff>;
+		clock-frequency = <33333333>;
+		fsl,msi = <&msi0>;
+		interrupts = <16 2 1 15>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 15>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 40 1 0 0
+				0000 0 0 2 &mpic 1 1 0 0
+				0000 0 0 3 &mpic 2 1 0 0
+				0000 0 0 4 &mpic 3 1 0 0
+				>;
+		};
+	};
+
+	pci1: pcie@ffe201000 {
+		compatible = "fsl,p3060-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0 0xff>;
+		clock-frequency = <33333333>;
+		fsl,msi = <&msi1>;
+		interrupts = <16 2 1 14>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 14>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 41 1 0 0
+				0000 0 0 2 &mpic 5 1 0 0
+				0000 0 0 3 &mpic 6 1 0 0
+				0000 0 0 4 &mpic 7 1 0 0
+				>;
+		};
+	};
+};
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p4080ds.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/p4080ds.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p4080ds.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p4080ds.dts	2012-01-04 18:55:44.000000000 -0500
@@ -45,6 +45,10 @@
 		device_type = "memory";
 	};
 
+	dcsr: dcsr@f00000000 {
+		ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+	};
+
 	soc: soc@ffe000000 {
 		spi@110000 {
 			flash@0 {
@@ -108,7 +112,8 @@
 
 	localbus@ffe124000 {
 		reg = <0xf 0xfe124000 0 0x1000>;
-		ranges = <0 0 0xf 0xe8000000 0x08000000>;
+		ranges = <0 0 0xf 0xe8000000 0x08000000
+			  3 0 0xf 0xffdf0000 0x00008000>;
 
 		flash@0,0 {
 			compatible = "cfi-flash";
@@ -116,6 +121,11 @@
 			bank-width = <2>;
 			device-width = <2>;
 		};
+
+		board-control@3,0 {
+			compatible = "fsl,p4080ds-fpga", "fsl,fpga-ngpixis";
+			reg = <3 0 0x30>;
+		};
 	};
 
 	pci0: pcie@ffe200000 {
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p4080si.dtsi linux-libre-3.2-gnu/arch/powerpc/boot/dts/p4080si.dtsi
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p4080si.dtsi	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p4080si.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
 
 	aliases {
 		ccsr = &soc;
+		dcsr = &dcsr;
 
 		serial0 = &serial0;
 		serial1 = &serial1;
@@ -77,7 +78,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		cpu0: PowerPC,4080@0 {
+		cpu0: PowerPC,e500mc@0 {
 			device_type = "cpu";
 			reg = <0>;
 			next-level-cache = <&L2_0>;
@@ -85,7 +86,7 @@
 				next-level-cache = <&cpc>;
 			};
 		};
-		cpu1: PowerPC,4080@1 {
+		cpu1: PowerPC,e500mc@1 {
 			device_type = "cpu";
 			reg = <1>;
 			next-level-cache = <&L2_1>;
@@ -93,7 +94,7 @@
 				next-level-cache = <&cpc>;
 			};
 		};
-		cpu2: PowerPC,4080@2 {
+		cpu2: PowerPC,e500mc@2 {
 			device_type = "cpu";
 			reg = <2>;
 			next-level-cache = <&L2_2>;
@@ -101,7 +102,7 @@
 				next-level-cache = <&cpc>;
 			};
 		};
-		cpu3: PowerPC,4080@3 {
+		cpu3: PowerPC,e500mc@3 {
 			device_type = "cpu";
 			reg = <3>;
 			next-level-cache = <&L2_3>;
@@ -109,7 +110,7 @@
 				next-level-cache = <&cpc>;
 			};
 		};
-		cpu4: PowerPC,4080@4 {
+		cpu4: PowerPC,e500mc@4 {
 			device_type = "cpu";
 			reg = <4>;
 			next-level-cache = <&L2_4>;
@@ -117,7 +118,7 @@
 				next-level-cache = <&cpc>;
 			};
 		};
-		cpu5: PowerPC,4080@5 {
+		cpu5: PowerPC,e500mc@5 {
 			device_type = "cpu";
 			reg = <5>;
 			next-level-cache = <&L2_5>;
@@ -125,7 +126,7 @@
 				next-level-cache = <&cpc>;
 			};
 		};
-		cpu6: PowerPC,4080@6 {
+		cpu6: PowerPC,e500mc@6 {
 			device_type = "cpu";
 			reg = <6>;
 			next-level-cache = <&L2_6>;
@@ -133,7 +134,7 @@
 				next-level-cache = <&cpc>;
 			};
 		};
-		cpu7: PowerPC,4080@7 {
+		cpu7: PowerPC,e500mc@7 {
 			device_type = "cpu";
 			reg = <7>;
 			next-level-cache = <&L2_7>;
@@ -143,6 +144,99 @@
 		};
 	};
 
+	dcsr: dcsr@f00000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,dcsr", "simple-bus";
+
+		dcsr-epu@0 {
+			compatible = "fsl,dcsr-epu";
+			interrupts = <52 2 0 0
+				      84 2 0 0
+				      85 2 0 0>;
+			interrupt-parent = <&mpic>;
+			reg = <0x0 0x1000>;
+		};
+		dcsr-npc {
+			compatible = "fsl,dcsr-npc";
+			reg = <0x1000 0x1000 0x1000000 0x8000>;
+		};
+		dcsr-nxc@2000 {
+			compatible = "fsl,dcsr-nxc";
+			reg = <0x2000 0x1000>;
+		};
+		dcsr-corenet {
+			compatible = "fsl,dcsr-corenet";
+			reg = <0x8000 0x1000 0xB0000 0x1000>;
+		};
+		dcsr-dpaa@9000 {
+			compatible = "fsl,p4080-dcsr-dpaa", "fsl,dcsr-dpaa";
+			reg = <0x9000 0x1000>;
+		};
+		dcsr-ocn@11000 {
+			compatible = "fsl,p4080-dcsr-ocn", "fsl,dcsr-ocn";
+			reg = <0x11000 0x1000>;
+		};
+		dcsr-ddr@12000 {
+			compatible = "fsl,dcsr-ddr";
+			dev-handle = <&ddr1>;
+			reg = <0x12000 0x1000>;
+		};
+		dcsr-ddr@13000 {
+			compatible = "fsl,dcsr-ddr";
+			dev-handle = <&ddr2>;
+			reg = <0x13000 0x1000>;
+		};
+		dcsr-nal@18000 {
+			compatible = "fsl,p4080-dcsr-nal", "fsl,dcsr-nal";
+			reg = <0x18000 0x1000>;
+		};
+		dcsr-rcpm@22000 {
+			compatible = "fsl,p4080-dcsr-rcpm", "fsl,dcsr-rcpm";
+			reg = <0x22000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@40000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu0>;
+			reg = <0x40000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@41000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu1>;
+			reg = <0x41000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@42000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu2>;
+			reg = <0x42000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@43000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu3>;
+			reg = <0x43000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@44000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu4>;
+			reg = <0x44000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@45000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu5>;
+			reg = <0x45000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@46000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu6>;
+			reg = <0x46000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@47000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu7>;
+			reg = <0x47000 0x1000>;
+		};
+	};
+
 	soc: soc@ffe000000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -162,13 +256,13 @@
 			fsl,num-laws = <32>;
 		};
 
-		memory-controller@8000 {
+		ddr1: memory-controller@8000 {
 			compatible = "fsl,qoriq-memory-controller-v4.4", "fsl,qoriq-memory-controller";
 			reg = <0x8000 0x1000>;
 			interrupts = <16 2 1 23>;
 		};
 
-		memory-controller@9000 {
+		ddr2: memory-controller@9000 {
 			compatible = "fsl,qoriq-memory-controller-v4.4","fsl,qoriq-memory-controller";
 			reg = <0x9000 0x1000>;
 			interrupts = <16 2 1 22>;
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p5020ds.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/p5020ds.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p5020ds.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p5020ds.dts	2012-01-04 18:55:44.000000000 -0500
@@ -45,6 +45,10 @@
 		device_type = "memory";
 	};
 
+	dcsr: dcsr@f00000000 {
+		ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+	};
+
 	soc: soc@ffe000000 {
 		spi@110000 {
 			flash@0 {
@@ -147,8 +151,8 @@
 		};
 
 		board-control@3,0 {
-			compatible = "fsl,p5020ds-pixis";
-			reg = <3 0 0x20>;
+			compatible = "fsl,p5020ds-fpga", "fsl,fpga-ngpixis";
+			reg = <3 0 0x30>;
 		};
 	};
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/p5020si.dtsi linux-libre-3.2-gnu/arch/powerpc/boot/dts/p5020si.dtsi
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/p5020si.dtsi	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/p5020si.dtsi	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
 
 	aliases {
 		ccsr = &soc;
+		dcsr = &dcsr;
 
 		serial0 = &serial0;
 		serial1 = &serial1;
@@ -98,6 +99,69 @@
 		};
 	};
 
+	dcsr: dcsr@f00000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,dcsr", "simple-bus";
+
+		dcsr-epu@0 {
+			compatible = "fsl,dcsr-epu";
+			interrupts = <52 2 0 0
+				      84 2 0 0
+				      85 2 0 0>;
+			interrupt-parent = <&mpic>;
+			reg = <0x0 0x1000>;
+		};
+		dcsr-npc {
+			compatible = "fsl,dcsr-npc";
+			reg = <0x1000 0x1000 0x1000000 0x8000>;
+		};
+		dcsr-nxc@2000 {
+			compatible = "fsl,dcsr-nxc";
+			reg = <0x2000 0x1000>;
+		};
+		dcsr-corenet {
+			compatible = "fsl,dcsr-corenet";
+			reg = <0x8000 0x1000 0xB0000 0x1000>;
+		};
+		dcsr-dpaa@9000 {
+			compatible = "fsl,p5020-dcsr-dpaa", "fsl,dcsr-dpaa";
+			reg = <0x9000 0x1000>;
+		};
+		dcsr-ocn@11000 {
+			compatible = "fsl,p5020-dcsr-ocn", "fsl,dcsr-ocn";
+			reg = <0x11000 0x1000>;
+		};
+		dcsr-ddr@12000 {
+			compatible = "fsl,dcsr-ddr";
+			dev-handle = <&ddr1>;
+			reg = <0x12000 0x1000>;
+		};
+		dcsr-ddr@13000 {
+			compatible = "fsl,dcsr-ddr";
+			dev-handle = <&ddr2>;
+			reg = <0x13000 0x1000>;
+		};
+		dcsr-nal@18000 {
+			compatible = "fsl,p5020-dcsr-nal", "fsl,dcsr-nal";
+			reg = <0x18000 0x1000>;
+		};
+		dcsr-rcpm@22000 {
+			compatible = "fsl,p5020-dcsr-rcpm", "fsl,dcsr-rcpm";
+			reg = <0x22000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@40000 {
+			compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu0>;
+			reg = <0x40000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@41000 {
+			compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu1>;
+			reg = <0x41000 0x1000>;
+		};
+	};
+
 	soc: soc@ffe000000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -117,13 +181,13 @@
 			fsl,num-laws = <32>;
 		};
 
-		memory-controller@8000 {
+		ddr1: memory-controller@8000 {
 			compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
 			reg = <0x8000 0x1000>;
 			interrupts = <16 2 1 23>;
 		};
 
-		memory-controller@9000 {
+		ddr2: memory-controller@9000 {
 			compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
 			reg = <0x9000 0x1000>;
 			interrupts = <16 2 1 22>;
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/sbc8560.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/sbc8560.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/sbc8560.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/sbc8560.dts	2012-01-04 18:55:44.000000000 -0500
@@ -331,7 +331,7 @@
 	};
 
 	localbus@ff705000 {
-		compatible = "fsl,mpc8560-localbus";
+		compatible = "fsl,mpc8560-localbus", "simple-bus";
 		#address-cells = <2>;
 		#size-cells = <1>;
 		reg = <0xff705000 0x100>;	// BRx, ORx, etc.
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/dts/yosemite.dts linux-libre-3.2-gnu/arch/powerpc/boot/dts/yosemite.dts
--- linux-libre-3.1-gnu/arch/powerpc/boot/dts/yosemite.dts	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/dts/yosemite.dts	2012-01-04 18:55:44.000000000 -0500
@@ -138,6 +138,42 @@
 				clock-frequency = <0>; /* Filled in by zImage */
 				interrupts = <0x5 0x1>;
 				interrupt-parent = <&UIC1>;
+
+				nor_flash@0,0 {
+					compatible = "amd,s29gl256n", "cfi-flash";
+					bank-width = <2>;
+					reg = <0x00000000 0x00000000 0x04000000>;
+					#address-cells = <1>;
+					#size-cells = <1>;
+					partition@0 {
+						label = "kernel";
+						reg = <0x00000000 0x001e0000>;
+					};
+					partition@1e0000 {
+						label = "dtb";
+						reg = <0x001e0000 0x00020000>;
+					};
+					partition@200000 {
+						label = "ramdisk";
+						reg = <0x00200000 0x01400000>;
+					};
+					partition@1600000 {
+						label = "jffs2";
+						reg = <0x01600000 0x00400000>;
+					};
+					partition@1a00000 {
+						label = "user";
+						reg = <0x01a00000 0x02540000>;
+					};
+					partition@3f40000 {
+						label = "env";
+						reg = <0x03f40000 0x00040000>;
+					};
+					partition@3f80000 {
+						label = "u-boot";
+						reg = <0x03f80000 0x00080000>;
+					};
+				};
 			};
 
 			UART0: serial@ef600300 {
diff -druN linux-libre-3.1-gnu/arch/powerpc/boot/Makefile linux-libre-3.2-gnu/arch/powerpc/boot/Makefile
--- linux-libre-3.1-gnu/arch/powerpc/boot/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/boot/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -58,7 +58,7 @@
 libfdt       := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
 libfdtheader := fdt.h libfdt.h libfdt_internal.h
 
-$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o): \
+$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o epapr.o): \
 	$(addprefix $(obj)/,$(libfdtheader))
 
 src-wlib := string.S crt0.S crtsavres.S stdio.c main.c \
@@ -171,6 +171,7 @@
 		$(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux
 
 image-$(CONFIG_PPC_PSERIES)		+= zImage.pseries
+image-$(CONFIG_PPC_POWERNV)		+= zImage.pseries
 image-$(CONFIG_PPC_MAPLE)		+= zImage.maple
 image-$(CONFIG_PPC_IBM_CELL_BLADE)	+= zImage.pseries
 image-$(CONFIG_PPC_PS3)			+= dtbImage.ps3
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/40x/acadia_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/40x/acadia_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/40x/acadia_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/40x/acadia_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -44,12 +44,13 @@
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
 CONFIG_MII=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
-CONFIG_IBM_NEW_EMAC_DEBUG=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
+CONFIG_IBM_EMAC_DEBUG=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/40x/ep405_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/40x/ep405_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/40x/ep405_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/40x/ep405_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -42,8 +42,9 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/40x/hcu4_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/40x/hcu4_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/40x/hcu4_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/40x/hcu4_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,80 +0,0 @@
-CONFIG_40x=y
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_HCU4=y
-# CONFIG_WALNUT is not set
-CONFIG_SPARSE_IRQ=y
-CONFIG_PCI=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_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_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_CONNECTOR=y
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_OF_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=m
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_PROC_DEVICETREE=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=35000
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_OF_PLATFORM=y
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_CRYPTO=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
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/40x/kilauea_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/40x/kilauea_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/40x/kilauea_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/40x/kilauea_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -51,10 +51,11 @@
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/40x/makalu_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/40x/makalu_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/40x/makalu_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/40x/makalu_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -43,10 +43,11 @@
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/40x/walnut_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/40x/walnut_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/40x/walnut_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/40x/walnut_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -40,8 +40,9 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/44x/arches_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/44x/arches_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/44x/arches_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/44x/arches_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -44,10 +44,11 @@
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/44x/bamboo_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/44x/bamboo_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/44x/bamboo_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/44x/bamboo_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -32,8 +32,9 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/44x/bluestone_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/44x/bluestone_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/44x/bluestone_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/44x/bluestone_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -38,10 +38,11 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=2
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/44x/canyonlands_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/44x/canyonlands_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/44x/canyonlands_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/44x/canyonlands_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -49,10 +49,11 @@
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/44x/ebony_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/44x/ebony_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/44x/ebony_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/44x/ebony_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -40,8 +40,9 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/44x/eiger_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/44x/eiger_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/44x/eiger_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/44x/eiger_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -55,10 +55,11 @@
 CONFIG_FUSION_SAS=y
 CONFIG_I2O=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
 CONFIG_E1000E=y
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/44x/icon_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/44x/icon_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/44x/icon_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/44x/icon_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -56,8 +56,9 @@
 CONFIG_FUSION_CTL=y
 CONFIG_FUSION_LOGGING=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_WLAN is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/44x/katmai_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/44x/katmai_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/44x/katmai_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/44x/katmai_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -42,8 +42,9 @@
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_MACINTOSH_DRIVERS=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/44x/redwood_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/44x/redwood_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/44x/redwood_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/44x/redwood_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -53,11 +53,12 @@
 CONFIG_FUSION_SAS=y
 CONFIG_I2O=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=256
-CONFIG_IBM_NEW_EMAC_TXB=256
-CONFIG_IBM_NEW_EMAC_DEBUG=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=256
+CONFIG_IBM_EMAC_TXB=256
+CONFIG_IBM_EMAC_DEBUG=y
 CONFIG_E1000E=y
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/44x/sam440ep_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/44x/sam440ep_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/44x/sam440ep_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/44x/sam440ep_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -44,8 +44,9 @@
 # CONFIG_SATA_PMP is not set
 CONFIG_SATA_SIL=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 CONFIG_INPUT_FF_MEMLESS=m
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/44x/sequoia_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/44x/sequoia_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/44x/sequoia_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/44x/sequoia_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -46,8 +46,9 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/44x/taishan_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/44x/taishan_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/44x/taishan_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/44x/taishan_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -40,8 +40,9 @@
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_MACINTOSH_DRIVERS=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/44x/warp_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/44x/warp_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/44x/warp_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/44x/warp_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -54,9 +54,10 @@
 CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
 CONFIG_MII=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_IBM_EMAC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_INPUT is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/52xx/tqm5200_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/52xx/tqm5200_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/52xx/tqm5200_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/52xx/tqm5200_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,9 +1,10 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
+CONFIG_EMBEDDED=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_EPOLL is not set
@@ -17,7 +18,6 @@
 CONFIG_PPC_MPC5200_BUGFIX=y
 # CONFIG_PPC_PMAC is not set
 CONFIG_PPC_BESTCOMM=y
-CONFIG_SPARSE_IRQ=y
 CONFIG_PM=y
 # CONFIG_PCI is not set
 CONFIG_NET=y
@@ -38,17 +38,18 @@
 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
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_ROM=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_PLATRAM=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=32768
-# CONFIG_MISC_DEVICES is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_ATA=y
@@ -56,13 +57,11 @@
 CONFIG_PATA_PLATFORM=y
 CONFIG_NETDEVICES=y
 CONFIG_LXT_PHY=y
+CONFIG_FIXED_PHY=y
 CONFIG_NET_ETHERNET=y
 CONFIG_FEC_MPC52xx=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_MPC52xx=y
 CONFIG_SERIAL_MPC52xx_CONSOLE=y
 CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
@@ -70,7 +69,13 @@
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
+CONFIG_SENSORS_LM80=y
 CONFIG_WATCHDOG=y
+CONFIG_MFD_SM501=y
+CONFIG_FB=y
+CONFIG_FB_FOREIGN_ENDIAN=y
+CONFIG_FB_SM501=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_DEVICE_CLASS is not set
@@ -80,10 +85,10 @@
 CONFIG_USB_STORAGE=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_PROC_KCORE=y
@@ -102,7 +107,6 @@
 CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_CRYPTO_ECB=y
 CONFIG_CRYPTO_PCBC=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/85xx/p1023rds_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/85xx/p1023rds_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/85xx/p1023rds_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/85xx/p1023rds_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,7 @@
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
 CONFIG_CPM2=y
-CONFIG_MPC8xxx_GPIO=y
+CONFIG_GPIO_MPC8XXX=y
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_XES_MPC85xx=y
-CONFIG_MPC8xxx_GPIO=y
+CONFIG_GPIO_MPC8XXX=y
 CONFIG_HIGHMEM=y
 CONFIG_MATH_EMULATION=y
 CONFIG_SPARSE_IRQ=y
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/corenet32_smp_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/corenet32_smp_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/corenet32_smp_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/corenet32_smp_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -12,9 +12,7 @@
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_EMBEDDED=y
 CONFIG_PERF_EVENTS=y
 CONFIG_SLAB=y
@@ -23,8 +21,9 @@
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
-CONFIG_P2040_RDB=y
+CONFIG_P2041_RDB=y
 CONFIG_P3041_DS=y
+CONFIG_P3060_QDS=y
 CONFIG_P4080_DS=y
 CONFIG_P5020_DS=y
 CONFIG_HIGHMEM=y
@@ -69,7 +68,6 @@
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
@@ -107,7 +105,6 @@
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_LEGACY_PTYS is not set
-CONFIG_PPC_EPAPR_HV_BYTECHAN=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_EXTENDED=y
@@ -136,8 +133,6 @@
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_OF=y
-CONFIG_MMC_SDHCI_OF_ESDHC=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_MPC85XX=y
@@ -146,7 +141,6 @@
 CONFIG_RTC_DRV_CMOS=y
 CONFIG_UIO=y
 CONFIG_STAGING=y
-# CONFIG_STAGING_EXCLUDE_BUILD is not set
 CONFIG_VIRT_DRIVERS=y
 CONFIG_FSL_HV_MANAGER=y
 CONFIG_EXT2_FS=y
@@ -173,7 +167,6 @@
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_UTF8=m
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/corenet64_smp_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/corenet64_smp_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/corenet64_smp_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/corenet64_smp_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -11,10 +11,8 @@
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -25,7 +23,6 @@
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BINFMT_MISC=m
-# CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -93,10 +90,8 @@
 CONFIG_CRC_ITU_T=m
 CONFIG_FRAME_WARN=1024
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_VIRQ_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/mgcoge_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/mgcoge_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/mgcoge_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/mgcoge_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,15 +1,22 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
 CONFIG_SPARSE_IRQ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
+# CONFIG_RD_GZIP is not set
 CONFIG_KALLSYMS_ALL=y
+# CONFIG_PCSPKR_PLATFORM is not set
+CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
 # CONFIG_IOSCHED_CFQ is not set
+# CONFIG_PPC_PMAC is not set
 CONFIG_PPC_82xx=y
 CONFIG_MGCOGE=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BINFMT_MISC=y
 # CONFIG_SECCOMP is not set
 CONFIG_NET=y
@@ -24,11 +31,10 @@
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
 CONFIG_NETFILTER=y
+CONFIG_TIPC=y
 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_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLKDEVS=y
@@ -42,7 +48,6 @@
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
 CONFIG_FIXED_PHY=y
 CONFIG_NET_ETHERNET=y
@@ -50,6 +55,7 @@
 CONFIG_FS_ENET_MDIO_FCC=y
 # CONFIG_NETDEV_1000 is not set
 # 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
@@ -57,24 +63,24 @@
 CONFIG_SERIAL_CPM_CONSOLE=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
-# CONFIG_I2C_POWERMAC is not set
 CONFIG_I2C_CPM=y
 # CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_GADGET=y
+CONFIG_USB_FSL_USB2=y
+CONFIG_USB_G_SERIAL=y
+CONFIG_UIO=y
+CONFIG_UIO_PDRV=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_AUTOFS4_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_CRAMFS=y
+CONFIG_SQUASHFS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_PARTITION_ADVANCED=y
-# CONFIG_MAC_PARTITION is not set
 CONFIG_NLS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
@@ -82,7 +88,6 @@
 CONFIG_NLS_UTF8=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_DEBUG_INFO=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/mpc512x_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/mpc512x_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/mpc512x_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/mpc512x_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,9 +1,9 @@
 CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -13,10 +13,11 @@
 # CONFIG_PPC_CHRP is not set
 CONFIG_PPC_MPC512x=y
 CONFIG_MPC5121_ADS=y
+CONFIG_MPC5121_GENERIC=y
+CONFIG_PDM360NG=y
 # CONFIG_PPC_PMAC is not set
 CONFIG_NO_HZ=y
 CONFIG_HZ_1000=y
-CONFIG_SPARSE_IRQ=y
 # CONFIG_MIGRATION is not set
 # CONFIG_SECCOMP is not set
 # CONFIG_PCI is not set
@@ -35,18 +36,16 @@
 CONFIG_CAN_RAW=y
 CONFIG_CAN_BCM=y
 CONFIG_CAN_VCAN=y
-CONFIG_CAN_DEV=y
 CONFIG_CAN_MSCAN=y
 CONFIG_CAN_DEBUG_DEVICES=y
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 CONFIG_MTD=y
-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
@@ -63,6 +62,7 @@
 CONFIG_BLK_DEV_XIP=y
 CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
@@ -99,10 +99,14 @@
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
+CONFIG_SPI=y
+CONFIG_SPI_MPC512x_PSC=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_MPC8XXX=y
 # CONFIG_HWMON is not set
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
-# CONFIG_VIDEO_ALLOW_V4L1 is not set
 CONFIG_VIDEO_ADV_DEBUG=y
 # CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
 CONFIG_VIDEO_SAA711X=y
@@ -132,6 +136,5 @@
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/mpc5200_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/mpc5200_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/mpc5200_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/mpc5200_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -88,6 +88,18 @@
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_PCI is not set
+# CONFIG_SND_PPC is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_MPC5200_I2S=y
+CONFIG_SND_MPC52xx_SOC_PCM030=y
+CONFIG_SND_MPC52xx_SOC_EFIKA=y
 CONFIG_HID_DRAGONRISE=y
 CONFIG_HID_GYRATION=y
 CONFIG_HID_TWINHAN=y
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/mpc85xx_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/mpc85xx_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/mpc85xx_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/mpc85xx_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -10,10 +10,8 @@
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -41,7 +39,6 @@
 CONFIG_SBC8548=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
-CONFIG_MPC8xxx_GPIO=y
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -123,6 +120,7 @@
 CONFIG_I2C=y
 CONFIG_I2C_CPM=m
 CONFIG_I2C_MPC=y
+CONFIG_GPIO_MPC8XXX=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
@@ -206,7 +204,6 @@
 CONFIG_MAC_PARTITION=y
 CONFIG_CRC_T10DIF=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/mpc85xx_smp_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/mpc85xx_smp_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/mpc85xx_smp_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/mpc85xx_smp_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -12,10 +12,8 @@
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -42,7 +40,6 @@
 CONFIG_SBC8548=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
-CONFIG_MPC8xxx_GPIO=y
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -124,6 +121,7 @@
 CONFIG_I2C=y
 CONFIG_I2C_CPM=m
 CONFIG_I2C_MPC=y
+CONFIG_GPIO_MPC8XXX=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
@@ -207,10 +205,8 @@
 CONFIG_MAC_PARTITION=y
 CONFIG_CRC_T10DIF=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_VIRQ_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/ppc40x_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/ppc40x_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/ppc40x_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/ppc40x_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,6 @@
 CONFIG_PPC4xx_GPIO=y
 CONFIG_ACADIA=y
 CONFIG_EP405=y
-CONFIG_HCU4=y
 CONFIG_HOTFOOT=y
 CONFIG_KILAUEA=y
 CONFIG_MAKALU=y
@@ -50,8 +49,9 @@
 CONFIG_BLK_DEV_RAM_SIZE=35000
 CONFIG_XILINX_SYSACE=m
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 CONFIG_SERIO=m
 # CONFIG_SERIO_I8042 is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/ppc44x_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/ppc44x_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/ppc44x_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/ppc44x_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -52,6 +52,8 @@
 CONFIG_MTD_JEDECPROBE=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_NAND=m
+CONFIG_MTD_NAND_NDFC=m
 CONFIG_MTD_UBI=m
 CONFIG_MTD_UBI_GLUEBI=m
 CONFIG_PROC_DEVICETREE=y
@@ -63,8 +65,9 @@
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 CONFIG_TUN=m
-CONFIG_NET_ETHERNET=y
-CONFIG_IBM_NEW_EMAC=y
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_IBM=y
+CONFIG_IBM_EMAC=y
 # CONFIG_INPUT is not set
 CONFIG_SERIO=m
 # CONFIG_SERIO_I8042 is not set
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/ppc64_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/ppc64_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/ppc64_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/ppc64_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -485,3 +485,7 @@
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM_BOOK3S_64=m
+CONFIG_KVM_BOOK3S_64_HV=y
+CONFIG_VHOST_NET=m
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/ppc6xx_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/ppc6xx_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/ppc6xx_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/ppc6xx_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -70,7 +70,7 @@
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
 CONFIG_PPC_BESTCOMM=y
-CONFIG_MPC8xxx_GPIO=y
+CONFIG_GPIO_MPC8XXX=y
 CONFIG_MCU_MPC8349EMITX=m
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
diff -druN linux-libre-3.1-gnu/arch/powerpc/configs/pseries_defconfig linux-libre-3.2-gnu/arch/powerpc/configs/pseries_defconfig
--- linux-libre-3.1-gnu/arch/powerpc/configs/pseries_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/configs/pseries_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -362,3 +362,7 @@
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM_BOOK3S_64=m
+CONFIG_KVM_BOOK3S_64_HV=y
+CONFIG_VHOST_NET=m
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/atomic.h linux-libre-3.2-gnu/arch/powerpc/include/asm/atomic.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/atomic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/atomic.h	2012-01-04 18:55:44.000000000 -0500
@@ -49,13 +49,13 @@
 	int t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	lwarx	%0,0,%2		# atomic_add_return\n\
 	add	%0,%1,%0\n"
 	PPC405_ERR77(0,%2)
 "	stwcx.	%0,0,%2 \n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (t)
 	: "r" (a), "r" (&v->counter)
 	: "cc", "memory");
@@ -85,13 +85,13 @@
 	int t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	lwarx	%0,0,%2		# atomic_sub_return\n\
 	subf	%0,%1,%0\n"
 	PPC405_ERR77(0,%2)
 "	stwcx.	%0,0,%2 \n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (t)
 	: "r" (a), "r" (&v->counter)
 	: "cc", "memory");
@@ -119,13 +119,13 @@
 	int t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	lwarx	%0,0,%1		# atomic_inc_return\n\
 	addic	%0,%0,1\n"
 	PPC405_ERR77(0,%1)
 "	stwcx.	%0,0,%1 \n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (t)
 	: "r" (&v->counter)
 	: "cc", "xer", "memory");
@@ -163,13 +163,13 @@
 	int t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	lwarx	%0,0,%1		# atomic_dec_return\n\
 	addic	%0,%0,-1\n"
 	PPC405_ERR77(0,%1)
 "	stwcx.	%0,0,%1\n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (t)
 	: "r" (&v->counter)
 	: "cc", "xer", "memory");
@@ -194,7 +194,7 @@
 	int t;
 
 	__asm__ __volatile__ (
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	lwarx	%0,0,%1		# __atomic_add_unless\n\
 	cmpw	0,%0,%3 \n\
 	beq-	2f \n\
@@ -202,7 +202,7 @@
 	PPC405_ERR77(0,%2)
 "	stwcx.	%0,0,%1 \n\
 	bne-	1b \n"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 "	subf	%0,%2,%0 \n\
 2:"
 	: "=&r" (t)
@@ -226,7 +226,7 @@
 	int t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	lwarx	%0,0,%1		# atomic_dec_if_positive\n\
 	cmpwi	%0,1\n\
 	addi	%0,%0,-1\n\
@@ -234,7 +234,7 @@
 	PPC405_ERR77(0,%1)
 "	stwcx.	%0,0,%1\n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	"\n\
 2:"	: "=&b" (t)
 	: "r" (&v->counter)
@@ -285,12 +285,12 @@
 	long t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	ldarx	%0,0,%2		# atomic64_add_return\n\
 	add	%0,%1,%0\n\
 	stdcx.	%0,0,%2 \n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (t)
 	: "r" (a), "r" (&v->counter)
 	: "cc", "memory");
@@ -319,12 +319,12 @@
 	long t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	ldarx	%0,0,%2		# atomic64_sub_return\n\
 	subf	%0,%1,%0\n\
 	stdcx.	%0,0,%2 \n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (t)
 	: "r" (a), "r" (&v->counter)
 	: "cc", "memory");
@@ -351,12 +351,12 @@
 	long t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	ldarx	%0,0,%1		# atomic64_inc_return\n\
 	addic	%0,%0,1\n\
 	stdcx.	%0,0,%1 \n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (t)
 	: "r" (&v->counter)
 	: "cc", "xer", "memory");
@@ -393,12 +393,12 @@
 	long t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	ldarx	%0,0,%1		# atomic64_dec_return\n\
 	addic	%0,%0,-1\n\
 	stdcx.	%0,0,%1\n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	: "=&r" (t)
 	: "r" (&v->counter)
 	: "cc", "xer", "memory");
@@ -418,13 +418,13 @@
 	long t;
 
 	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	ldarx	%0,0,%1		# atomic64_dec_if_positive\n\
 	addic.	%0,%0,-1\n\
 	blt-	2f\n\
 	stdcx.	%0,0,%1\n\
 	bne-	1b"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 	"\n\
 2:"	: "=&r" (t)
 	: "r" (&v->counter)
@@ -450,14 +450,14 @@
 	long t;
 
 	__asm__ __volatile__ (
-	PPC_RELEASE_BARRIER
+	PPC_ATOMIC_ENTRY_BARRIER
 "1:	ldarx	%0,0,%1		# __atomic_add_unless\n\
 	cmpd	0,%0,%3 \n\
 	beq-	2f \n\
 	add	%0,%2,%0 \n"
 "	stdcx.	%0,0,%1 \n\
 	bne-	1b \n"
-	PPC_ACQUIRE_BARRIER
+	PPC_ATOMIC_EXIT_BARRIER
 "	subf	%0,%2,%0 \n\
 2:"
 	: "=&r" (t)
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/bitops.h linux-libre-3.2-gnu/arch/powerpc/include/asm/bitops.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/bitops.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/bitops.h	2012-01-04 18:55:44.000000000 -0500
@@ -124,14 +124,14 @@
 	return (old & mask);				\
 }
 
-DEFINE_TESTOP(test_and_set_bits, or, PPC_RELEASE_BARRIER,
-	      PPC_ACQUIRE_BARRIER, 0)
+DEFINE_TESTOP(test_and_set_bits, or, PPC_ATOMIC_ENTRY_BARRIER,
+	      PPC_ATOMIC_EXIT_BARRIER, 0)
 DEFINE_TESTOP(test_and_set_bits_lock, or, "",
 	      PPC_ACQUIRE_BARRIER, 1)
-DEFINE_TESTOP(test_and_clear_bits, andc, PPC_RELEASE_BARRIER,
-	      PPC_ACQUIRE_BARRIER, 0)
-DEFINE_TESTOP(test_and_change_bits, xor, PPC_RELEASE_BARRIER,
-	      PPC_ACQUIRE_BARRIER, 0)
+DEFINE_TESTOP(test_and_clear_bits, andc, PPC_ATOMIC_ENTRY_BARRIER,
+	      PPC_ATOMIC_EXIT_BARRIER, 0)
+DEFINE_TESTOP(test_and_change_bits, xor, PPC_ATOMIC_ENTRY_BARRIER,
+	      PPC_ATOMIC_EXIT_BARRIER, 0)
 
 static __inline__ int test_and_set_bit(unsigned long nr,
 				       volatile unsigned long *addr)
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/compat.h linux-libre-3.2-gnu/arch/powerpc/include/asm/compat.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/compat.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/compat.h	2012-01-04 18:55:44.000000000 -0500
@@ -100,7 +100,8 @@
 	compat_fsid_t	f_fsid;
 	int		f_namelen;	/* SunOS ignores this field. */
 	int		f_frsize;
-	int		f_spare[5];
+	int		f_flags;
+	int		f_spare[4];
 };
 
 #define COMPAT_RLIM_OLD_INFINITY	0x7fffffff
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/cputime.h linux-libre-3.2-gnu/arch/powerpc/include/asm/cputime.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/cputime.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/cputime.h	2012-01-04 18:55:44.000000000 -0500
@@ -150,6 +150,8 @@
 	return ct;
 }
 
+#define usecs_to_cputime64(us)		usecs_to_cputime(us)
+
 /*
  * Convert cputime <-> seconds
  */
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/device.h linux-libre-3.2-gnu/arch/powerpc/include/asm/device.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/device.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/device.h	2012-01-04 18:55:44.000000000 -0500
@@ -37,4 +37,6 @@
 	u64 dma_mask;
 };
 
+#define ARCH_HAS_DMA_GET_REQUIRED_MASK
+
 #endif /* _ASM_POWERPC_DEVICE_H */
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/firmware.h linux-libre-3.2-gnu/arch/powerpc/include/asm/firmware.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/firmware.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/firmware.h	2012-01-04 18:55:44.000000000 -0500
@@ -48,6 +48,8 @@
 #define FW_FEATURE_CMO		ASM_CONST(0x0000000002000000)
 #define FW_FEATURE_VPHN		ASM_CONST(0x0000000004000000)
 #define FW_FEATURE_XCMO		ASM_CONST(0x0000000008000000)
+#define FW_FEATURE_OPAL		ASM_CONST(0x0000000010000000)
+#define FW_FEATURE_OPALv2	ASM_CONST(0x0000000020000000)
 
 #ifndef __ASSEMBLY__
 
@@ -65,6 +67,8 @@
 	FW_FEATURE_PSERIES_ALWAYS = 0,
 	FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
 	FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
+	FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2,
+	FW_FEATURE_POWERNV_ALWAYS = 0,
 	FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
 	FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
 	FW_FEATURE_CELLEB_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_BEAT,
@@ -78,6 +82,9 @@
 #ifdef CONFIG_PPC_ISERIES
 		FW_FEATURE_ISERIES_POSSIBLE |
 #endif
+#ifdef CONFIG_PPC_POWERNV
+		FW_FEATURE_POWERNV_POSSIBLE |
+#endif
 #ifdef CONFIG_PPC_PS3
 		FW_FEATURE_PS3_POSSIBLE |
 #endif
@@ -95,6 +102,9 @@
 #ifdef CONFIG_PPC_ISERIES
 		FW_FEATURE_ISERIES_ALWAYS &
 #endif
+#ifdef CONFIG_PPC_POWERNV
+		FW_FEATURE_POWERNV_ALWAYS &
+#endif
 #ifdef CONFIG_PPC_PS3
 		FW_FEATURE_PS3_ALWAYS &
 #endif
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/floppy.h linux-libre-3.2-gnu/arch/powerpc/include/asm/floppy.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/floppy.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/floppy.h	2012-01-04 18:55:44.000000000 -0500
@@ -108,10 +108,10 @@
 {
 	if (can_use_virtual_dma)
 		return request_irq(FLOPPY_IRQ, floppy_hardint,
-				   IRQF_DISABLED, "floppy", NULL);
+				   0, "floppy", NULL);
 	else
 		return request_irq(FLOPPY_IRQ, floppy_interrupt,
-				   IRQF_DISABLED, "floppy", NULL);
+				   0, "floppy", NULL);
 }
 
 static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/futex.h linux-libre-3.2-gnu/arch/powerpc/include/asm/futex.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/futex.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/futex.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,12 +11,13 @@
 
 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
   __asm__ __volatile ( \
-	PPC_RELEASE_BARRIER \
+	PPC_ATOMIC_ENTRY_BARRIER \
 "1:	lwarx	%0,0,%2\n" \
 	insn \
 	PPC405_ERR77(0, %2) \
 "2:	stwcx.	%1,0,%2\n" \
 	"bne-	1b\n" \
+	PPC_ATOMIC_EXIT_BARRIER \
 	"li	%1,0\n" \
 "3:	.section .fixup,\"ax\"\n" \
 "4:	li	%1,%3\n" \
@@ -92,14 +93,14 @@
 		return -EFAULT;
 
         __asm__ __volatile__ (
-        PPC_RELEASE_BARRIER
+        PPC_ATOMIC_ENTRY_BARRIER
 "1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
         cmpw    0,%1,%4\n\
         bne-    3f\n"
         PPC405_ERR77(0,%3)
 "2:     stwcx.  %5,0,%3\n\
         bne-    1b\n"
-        PPC_ACQUIRE_BARRIER
+        PPC_ATOMIC_EXIT_BARRIER
 "3:	.section .fixup,\"ax\"\n\
 4:	li	%0,%6\n\
 	b	3b\n\
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/hugetlb.h linux-libre-3.2-gnu/arch/powerpc/include/asm/hugetlb.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/hugetlb.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/hugetlb.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,15 +1,60 @@
 #ifndef _ASM_POWERPC_HUGETLB_H
 #define _ASM_POWERPC_HUGETLB_H
 
+#ifdef CONFIG_HUGETLB_PAGE
 #include <asm/page.h>
 
+extern struct kmem_cache *hugepte_cache;
+extern void __init reserve_hugetlb_gpages(void);
+
+static inline pte_t *hugepd_page(hugepd_t hpd)
+{
+	BUG_ON(!hugepd_ok(hpd));
+	return (pte_t *)((hpd.pd & ~HUGEPD_SHIFT_MASK) | PD_HUGE);
+}
+
+static inline unsigned int hugepd_shift(hugepd_t hpd)
+{
+	return hpd.pd & HUGEPD_SHIFT_MASK;
+}
+
+static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr,
+				    unsigned pdshift)
+{
+	/*
+	 * On 32-bit, we have multiple higher-level table entries that point to
+	 * the same hugepte.  Just use the first one since they're all
+	 * identical.  So for that case, idx=0.
+	 */
+	unsigned long idx = 0;
+
+	pte_t *dir = hugepd_page(*hpdp);
+#ifdef CONFIG_PPC64
+	idx = (addr & ((1UL << pdshift) - 1)) >> hugepd_shift(*hpdp);
+#endif
+
+	return dir + idx;
+}
+
 pte_t *huge_pte_offset_and_shift(struct mm_struct *mm,
 				 unsigned long addr, unsigned *shift);
 
 void flush_dcache_icache_hugepage(struct page *page);
 
+#if defined(CONFIG_PPC_MM_SLICES) || defined(CONFIG_PPC_SUBPAGE_PROT)
 int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
 			   unsigned long len);
+#else
+static inline int is_hugepage_only_range(struct mm_struct *mm,
+					 unsigned long addr,
+					 unsigned long len)
+{
+	return 0;
+}
+#endif
+
+void book3e_hugetlb_preload(struct mm_struct *mm, unsigned long ea, pte_t pte);
+void flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
 
 void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
 			    unsigned long end, unsigned long floor,
@@ -50,8 +95,11 @@
 static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
 					    unsigned long addr, pte_t *ptep)
 {
-	unsigned long old = pte_update(mm, addr, ptep, ~0UL, 1);
-	return __pte(old);
+#ifdef CONFIG_PPC64
+	return __pte(pte_update(mm, addr, ptep, ~0UL, 1));
+#else
+	return __pte(pte_update(ptep, ~0UL, 0));
+#endif
 }
 
 static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
@@ -93,4 +141,15 @@
 {
 }
 
+#else /* ! CONFIG_HUGETLB_PAGE */
+static inline void reserve_hugetlb_gpages(void)
+{
+	pr_err("Cannot reserve gpages without hugetlb enabled\n");
+}
+static inline void flush_hugetlb_page(struct vm_area_struct *vma,
+				      unsigned long vmaddr)
+{
+}
+#endif
+
 #endif /* _ASM_POWERPC_HUGETLB_H */
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/kexec.h linux-libre-3.2-gnu/arch/powerpc/include/asm/kexec.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/kexec.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/kexec.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
 #define _ASM_POWERPC_KEXEC_H
 #ifdef __KERNEL__
 
-#ifdef CONFIG_FSL_BOOKE
+#if defined(CONFIG_FSL_BOOKE) || defined(CONFIG_44x)
 
 /*
  * On FSL-BookE we setup a 1:1 mapping which covers the first 2GiB of memory
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/kvm_book3s_64.h linux-libre-3.2-gnu/arch/powerpc/include/asm/kvm_book3s_64.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/kvm_book3s_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/kvm_book3s_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -29,4 +29,37 @@
 
 #define SPAPR_TCE_SHIFT		12
 
+static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
+					     unsigned long pte_index)
+{
+	unsigned long rb, va_low;
+
+	rb = (v & ~0x7fUL) << 16;		/* AVA field */
+	va_low = pte_index >> 3;
+	if (v & HPTE_V_SECONDARY)
+		va_low = ~va_low;
+	/* xor vsid from AVA */
+	if (!(v & HPTE_V_1TB_SEG))
+		va_low ^= v >> 12;
+	else
+		va_low ^= v >> 24;
+	va_low &= 0x7ff;
+	if (v & HPTE_V_LARGE) {
+		rb |= 1;			/* L field */
+		if (cpu_has_feature(CPU_FTR_ARCH_206) &&
+		    (r & 0xff000)) {
+			/* non-16MB large page, must be 64k */
+			/* (masks depend on page size) */
+			rb |= 0x1000;		/* page encoding in LP field */
+			rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
+			rb |= (va_low & 0xfe);	/* AVAL field (P7 doesn't seem to care) */
+		}
+	} else {
+		/* 4kB page */
+		rb |= (va_low & 0x7ff) << 12;	/* remaining 11b of VA */
+	}
+	rb |= (v >> 54) & 0x300;		/* B field */
+	return rb;
+}
+
 #endif /* __ASM_KVM_BOOK3S_64_H__ */
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/kvm_book3s_asm.h linux-libre-3.2-gnu/arch/powerpc/include/asm/kvm_book3s_asm.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/kvm_book3s_asm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/kvm_book3s_asm.h	2012-01-04 18:55:44.000000000 -0500
@@ -75,6 +75,8 @@
 	ulong scratch0;
 	ulong scratch1;
 	u8 in_guest;
+	u8 restore_hid5;
+	u8 napping;
 
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 	struct kvm_vcpu *kvm_vcpu;
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/kvm_book3s.h linux-libre-3.2-gnu/arch/powerpc/include/asm/kvm_book3s.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/kvm_book3s.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/kvm_book3s.h	2012-01-04 18:55:44.000000000 -0500
@@ -139,15 +139,14 @@
 extern int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu);
 extern pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn);
 
-extern void kvmppc_handler_lowmem_trampoline(void);
-extern void kvmppc_handler_trampoline_enter(void);
-extern void kvmppc_rmcall(ulong srr0, ulong srr1);
+extern void kvmppc_entry_trampoline(void);
 extern void kvmppc_hv_entry_trampoline(void);
 extern void kvmppc_load_up_fpu(void);
 extern void kvmppc_load_up_altivec(void);
 extern void kvmppc_load_up_vsx(void);
 extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst);
 extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst);
+extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd);
 
 static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
 {
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/kvm.h linux-libre-3.2-gnu/arch/powerpc/include/asm/kvm.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/kvm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/kvm.h	2012-01-04 18:55:44.000000000 -0500
@@ -276,6 +276,11 @@
 #define KVM_INTERRUPT_UNSET	-2U
 #define KVM_INTERRUPT_SET_LEVEL	-3U
 
+#define KVM_CPU_440		1
+#define KVM_CPU_E500V2		2
+#define KVM_CPU_3S_32		3
+#define KVM_CPU_3S_64		4
+
 /* for KVM_CAP_SPAPR_TCE */
 struct kvm_create_spapr_tce {
 	__u64 liobn;
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/kvm_host.h linux-libre-3.2-gnu/arch/powerpc/include/asm/kvm_host.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/kvm_host.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/kvm_host.h	2012-01-04 18:55:44.000000000 -0500
@@ -198,21 +198,29 @@
  */
 struct kvmppc_vcore {
 	int n_runnable;
-	int n_blocked;
+	int n_busy;
 	int num_threads;
 	int entry_exit_count;
 	int n_woken;
 	int nap_count;
+	int napping_threads;
 	u16 pcpu;
-	u8 vcore_running;
+	u8 vcore_state;
 	u8 in_guest;
 	struct list_head runnable_threads;
 	spinlock_t lock;
+	wait_queue_head_t wq;
 };
 
 #define VCORE_ENTRY_COUNT(vc)	((vc)->entry_exit_count & 0xff)
 #define VCORE_EXIT_COUNT(vc)	((vc)->entry_exit_count >> 8)
 
+/* Values for vcore_state */
+#define VCORE_INACTIVE	0
+#define VCORE_RUNNING	1
+#define VCORE_EXITING	2
+#define VCORE_SLEEPING	3
+
 struct kvmppc_pte {
 	ulong eaddr;
 	u64 vpage;
@@ -258,14 +266,6 @@
 	ulong host_stack;
 	u32 host_pid;
 #ifdef CONFIG_PPC_BOOK3S
-	ulong host_msr;
-	ulong host_r2;
-	void *host_retip;
-	ulong trampoline_lowmem;
-	ulong trampoline_enter;
-	ulong highmem_handler;
-	ulong rmcall;
-	ulong host_paca_phys;
 	struct kvmppc_slb slb[64];
 	int slb_max;		/* 1 + index of last valid entry in slb[] */
 	int slb_nr;		/* total number of entries in SLB */
@@ -389,6 +389,9 @@
 	u8 dcr_is_write;
 	u8 osi_needed;
 	u8 osi_enabled;
+	u8 papr_enabled;
+	u8 sane;
+	u8 cpu_type;
 	u8 hcall_needed;
 
 	u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */
@@ -408,11 +411,13 @@
 	struct dtl *dtl;
 	struct dtl *dtl_end;
 
+	wait_queue_head_t *wqp;
 	struct kvmppc_vcore *vcore;
 	int ret;
 	int trap;
 	int state;
 	int ptid;
+	bool timer_running;
 	wait_queue_head_t cpu_run;
 
 	struct kvm_vcpu_arch_shared *shared;
@@ -428,8 +433,9 @@
 #endif
 };
 
-#define KVMPPC_VCPU_BUSY_IN_HOST	0
-#define KVMPPC_VCPU_BLOCKED		1
+/* Values for vcpu->arch.state */
+#define KVMPPC_VCPU_STOPPED		0
+#define KVMPPC_VCPU_BUSY_IN_HOST	1
 #define KVMPPC_VCPU_RUNNABLE		2
 
 #endif /* __POWERPC_KVM_HOST_H__ */
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/kvm_ppc.h linux-libre-3.2-gnu/arch/powerpc/include/asm/kvm_ppc.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/kvm_ppc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/kvm_ppc.h	2012-01-04 18:55:44.000000000 -0500
@@ -66,6 +66,7 @@
 extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu);
 extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu);
 extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb);
+extern int kvmppc_sanity_check(struct kvm_vcpu *vcpu);
 
 /* Core-specific hooks */
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/lv1call.h linux-libre-3.2-gnu/arch/powerpc/include/asm/lv1call.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/lv1call.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/lv1call.h	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #if !defined(__ASSEMBLY__)
 
 #include <linux/types.h>
+#include <linux/export.h>
 
 /* lv1 call declaration macros */
 
@@ -315,7 +316,7 @@
 LV1_CALL(gpu_context_iomap,                             5, 0, 221 )
 LV1_CALL(gpu_context_attribute,                         6, 0, 225 )
 LV1_CALL(gpu_context_intr,                              1, 1, 227 )
-LV1_CALL(gpu_attribute,                                 5, 0, 228 )
+LV1_CALL(gpu_attribute,                                 3, 0, 228 )
 LV1_CALL(get_rtc,                                       0, 2, 232 )
 LV1_CALL(set_ppe_periodic_tracer_frequency,             1, 0, 240 )
 LV1_CALL(start_ppe_periodic_tracer,                     5, 0, 241 )
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/machdep.h linux-libre-3.2-gnu/arch/powerpc/include/asm/machdep.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/machdep.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/machdep.h	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 
 #include <asm/setup.h>
 
@@ -85,8 +86,9 @@
 	void		(*pci_dma_dev_setup)(struct pci_dev *dev);
 	void		(*pci_dma_bus_setup)(struct pci_bus *bus);
 
-	/* Platform set_dma_mask override */
+	/* Platform set_dma_mask and dma_get_required_mask overrides */
 	int		(*dma_set_mask)(struct device *dev, u64 dma_mask);
+	u64		(*dma_get_required_mask)(struct device *dev);
 
 	int		(*probe)(void);
 	void		(*setup_arch)(void); /* Optional, may be NULL */
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/mmu-book3e.h linux-libre-3.2-gnu/arch/powerpc/include/asm/mmu-book3e.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/mmu-book3e.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/mmu-book3e.h	2012-01-04 18:55:44.000000000 -0500
@@ -66,6 +66,7 @@
 #define MAS2_M			0x00000004
 #define MAS2_G			0x00000002
 #define MAS2_E			0x00000001
+#define MAS2_WIMGE_MASK		0x0000001f
 #define MAS2_EPN_MASK(size)		(~0 << (size + 10))
 #define MAS2_VAL(addr, size, flags)	((addr) & MAS2_EPN_MASK(size) | (flags))
 
@@ -80,6 +81,7 @@
 #define MAS3_SW			0x00000004
 #define MAS3_UR			0x00000002
 #define MAS3_SR			0x00000001
+#define MAS3_BAP_MASK		0x0000003f
 #define MAS3_SPSIZE		0x0000003e
 #define MAS3_SPSIZE_SHIFT	1
 
@@ -212,6 +214,11 @@
 	unsigned int	id;
 	unsigned int	active;
 	unsigned long	vdso_base;
+#ifdef CONFIG_PPC_MM_SLICES
+	u64 low_slices_psize;   /* SLB page size encodings */
+	u64 high_slices_psize;  /* 4 bits per slice for now */
+	u16 user_psize;         /* page size index */
+#endif
 } mm_context_t;
 
 /* Page size definitions, common between 32 and 64-bit
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/mmu.h linux-libre-3.2-gnu/arch/powerpc/include/asm/mmu.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/mmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/mmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -175,14 +175,16 @@
 #define MMU_PAGE_64K_AP	3	/* "Admixed pages" (hash64 only) */
 #define MMU_PAGE_256K	4
 #define MMU_PAGE_1M	5
-#define MMU_PAGE_8M	6
-#define MMU_PAGE_16M	7
-#define MMU_PAGE_256M	8
-#define MMU_PAGE_1G	9
-#define MMU_PAGE_16G	10
-#define MMU_PAGE_64G	11
-#define MMU_PAGE_COUNT	12
+#define MMU_PAGE_4M	6
+#define MMU_PAGE_8M	7
+#define MMU_PAGE_16M	8
+#define MMU_PAGE_64M	9
+#define MMU_PAGE_256M	10
+#define MMU_PAGE_1G	11
+#define MMU_PAGE_16G	12
+#define MMU_PAGE_64G	13
 
+#define MMU_PAGE_COUNT	14
 
 #if defined(CONFIG_PPC_STD_MMU_64)
 /* 64-bit classic hash table MMU */
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/mmu-hash64.h linux-libre-3.2-gnu/arch/powerpc/include/asm/mmu-hash64.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/mmu-hash64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/mmu-hash64.h	2012-01-04 18:55:44.000000000 -0500
@@ -262,8 +262,7 @@
 extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
 			     unsigned long pstart, unsigned long prot,
 			     int psize, int ssize);
-extern void add_gpage(unsigned long addr, unsigned long page_size,
-			  unsigned long number_of_pages);
+extern void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages);
 extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr);
 
 extern void hpte_init_native(void);
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/mpic.h linux-libre-3.2-gnu/arch/powerpc/include/asm/mpic.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/mpic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/mpic.h	2012-01-04 18:55:44.000000000 -0500
@@ -273,8 +273,6 @@
 	unsigned int		irq_count;
 	/* Number of sources */
 	unsigned int		num_sources;
-	/* Number of CPUs */
-	unsigned int		num_cpus;
 	/* default senses array */
 	unsigned char		*senses;
 	unsigned int		senses_count;
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/opal.h linux-libre-3.2-gnu/arch/powerpc/include/asm/opal.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/opal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/opal.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,443 @@
+/*
+ * PowerNV OPAL definitions.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef __OPAL_H
+#define __OPAL_H
+
+/****** Takeover interface ********/
+
+/* PAPR H-Call used to querty the HAL existence and/or instanciate
+ * it from within pHyp (tech preview only).
+ *
+ * This is exclusively used in prom_init.c
+ */
+
+#ifndef __ASSEMBLY__
+
+struct opal_takeover_args {
+	u64	k_image;		/* r4 */
+	u64	k_size;			/* r5 */
+	u64	k_entry;		/* r6 */
+	u64	k_entry2;		/* r7 */
+	u64	hal_addr;		/* r8 */
+	u64	rd_image;		/* r9 */
+	u64	rd_size;		/* r10 */
+	u64	rd_loc;			/* r11 */
+};
+
+extern long opal_query_takeover(u64 *hal_size, u64 *hal_align);
+
+extern long opal_do_takeover(struct opal_takeover_args *args);
+
+struct rtas_args;
+extern int opal_enter_rtas(struct rtas_args *args,
+			   unsigned long data,
+			   unsigned long entry);
+
+#endif /* __ASSEMBLY__ */
+
+/****** OPAL APIs ******/
+
+/* Return codes */
+#define OPAL_SUCCESS 		0
+#define OPAL_PARAMETER		-1
+#define OPAL_BUSY		-2
+#define OPAL_PARTIAL		-3
+#define OPAL_CONSTRAINED	-4
+#define OPAL_CLOSED		-5
+#define OPAL_HARDWARE		-6
+#define OPAL_UNSUPPORTED	-7
+#define OPAL_PERMISSION		-8
+#define OPAL_NO_MEM		-9
+#define OPAL_RESOURCE		-10
+#define OPAL_INTERNAL_ERROR	-11
+#define OPAL_BUSY_EVENT		-12
+#define OPAL_HARDWARE_FROZEN	-13
+
+/* API Tokens (in r0) */
+#define OPAL_CONSOLE_WRITE			1
+#define OPAL_CONSOLE_READ			2
+#define OPAL_RTC_READ				3
+#define OPAL_RTC_WRITE				4
+#define OPAL_CEC_POWER_DOWN			5
+#define OPAL_CEC_REBOOT				6
+#define OPAL_READ_NVRAM				7
+#define OPAL_WRITE_NVRAM			8
+#define OPAL_HANDLE_INTERRUPT			9
+#define OPAL_POLL_EVENTS			10
+#define OPAL_PCI_SET_HUB_TCE_MEMORY		11
+#define OPAL_PCI_SET_PHB_TCE_MEMORY		12
+#define OPAL_PCI_CONFIG_READ_BYTE		13
+#define OPAL_PCI_CONFIG_READ_HALF_WORD  	14
+#define OPAL_PCI_CONFIG_READ_WORD		15
+#define OPAL_PCI_CONFIG_WRITE_BYTE		16
+#define OPAL_PCI_CONFIG_WRITE_HALF_WORD		17
+#define OPAL_PCI_CONFIG_WRITE_WORD		18
+#define OPAL_SET_XIVE				19
+#define OPAL_GET_XIVE				20
+#define OPAL_GET_COMPLETION_TOKEN_STATUS	21 /* obsolete */
+#define OPAL_REGISTER_OPAL_EXCEPTION_HANDLER	22
+#define OPAL_PCI_EEH_FREEZE_STATUS		23
+#define OPAL_PCI_SHPC				24
+#define OPAL_CONSOLE_WRITE_BUFFER_SPACE		25
+#define OPAL_PCI_EEH_FREEZE_CLEAR		26
+#define OPAL_PCI_PHB_MMIO_ENABLE		27
+#define OPAL_PCI_SET_PHB_MEM_WINDOW		28
+#define OPAL_PCI_MAP_PE_MMIO_WINDOW		29
+#define OPAL_PCI_SET_PHB_TABLE_MEMORY		30
+#define OPAL_PCI_SET_PE				31
+#define OPAL_PCI_SET_PELTV			32
+#define OPAL_PCI_SET_MVE			33
+#define OPAL_PCI_SET_MVE_ENABLE			34
+#define OPAL_PCI_GET_XIVE_REISSUE		35
+#define OPAL_PCI_SET_XIVE_REISSUE		36
+#define OPAL_PCI_SET_XIVE_PE			37
+#define OPAL_GET_XIVE_SOURCE			38
+#define OPAL_GET_MSI_32				39
+#define OPAL_GET_MSI_64				40
+#define OPAL_START_CPU				41
+#define OPAL_QUERY_CPU_STATUS			42
+#define OPAL_WRITE_OPPANEL			43
+#define OPAL_PCI_MAP_PE_DMA_WINDOW		44
+#define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL		45
+#define OPAL_PCI_RESET				49
+
+#ifndef __ASSEMBLY__
+
+/* Other enums */
+enum OpalVendorApiTokens {
+	OPAL_START_VENDOR_API_RANGE = 1000, OPAL_END_VENDOR_API_RANGE = 1999
+};
+enum OpalFreezeState {
+	OPAL_EEH_STOPPED_NOT_FROZEN = 0,
+	OPAL_EEH_STOPPED_MMIO_FREEZE = 1,
+	OPAL_EEH_STOPPED_DMA_FREEZE = 2,
+	OPAL_EEH_STOPPED_MMIO_DMA_FREEZE = 3,
+	OPAL_EEH_STOPPED_RESET = 4,
+	OPAL_EEH_STOPPED_TEMP_UNAVAIL = 5,
+	OPAL_EEH_STOPPED_PERM_UNAVAIL = 6
+};
+enum OpalEehFreezeActionToken {
+	OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO = 1,
+	OPAL_EEH_ACTION_CLEAR_FREEZE_DMA = 2,
+	OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3
+};
+enum OpalPciStatusToken {
+	OPAL_EEH_PHB_NO_ERROR = 0,
+	OPAL_EEH_PHB_FATAL = 1,
+	OPAL_EEH_PHB_RECOVERABLE = 2,
+	OPAL_EEH_PHB_BUS_ERROR = 3,
+	OPAL_EEH_PCI_NO_DEVSEL = 4,
+	OPAL_EEH_PCI_TA = 5,
+	OPAL_EEH_PCIEX_UR = 6,
+	OPAL_EEH_PCIEX_CA = 7,
+	OPAL_EEH_PCI_MMIO_ERROR = 8,
+	OPAL_EEH_PCI_DMA_ERROR = 9
+};
+enum OpalShpcAction {
+	OPAL_SHPC_GET_LINK_STATE = 0,
+	OPAL_SHPC_GET_SLOT_STATE = 1
+};
+enum OpalShpcLinkState {
+	OPAL_SHPC_LINK_DOWN = 0,
+	OPAL_SHPC_LINK_UP = 1
+};
+enum OpalMmioWindowType {
+	OPAL_M32_WINDOW_TYPE = 1,
+	OPAL_M64_WINDOW_TYPE = 2,
+	OPAL_IO_WINDOW_TYPE = 3
+};
+enum OpalShpcSlotState {
+	OPAL_SHPC_DEV_NOT_PRESENT = 0,
+	OPAL_SHPC_DEV_PRESENT = 1
+};
+enum OpalExceptionHandler {
+	OPAL_MACHINE_CHECK_HANDLER = 1,
+	OPAL_HYPERVISOR_MAINTENANCE_HANDLER = 2,
+	OPAL_SOFTPATCH_HANDLER = 3
+};
+enum OpalPendingState {
+	OPAL_EVENT_OPAL_INTERNAL = 0x1,
+	OPAL_EVENT_NVRAM = 0x2,
+	OPAL_EVENT_RTC = 0x4,
+	OPAL_EVENT_CONSOLE_OUTPUT = 0x8,
+	OPAL_EVENT_CONSOLE_INPUT = 0x10
+};
+
+/* Machine check related definitions */
+enum OpalMCE_Version {
+	OpalMCE_V1 = 1,
+};
+
+enum OpalMCE_Severity {
+	OpalMCE_SEV_NO_ERROR = 0,
+	OpalMCE_SEV_WARNING = 1,
+	OpalMCE_SEV_ERROR_SYNC = 2,
+	OpalMCE_SEV_FATAL = 3,
+};
+
+enum OpalMCE_Disposition {
+	OpalMCE_DISPOSITION_RECOVERED = 0,
+	OpalMCE_DISPOSITION_NOT_RECOVERED = 1,
+};
+
+enum OpalMCE_Initiator {
+	OpalMCE_INITIATOR_UNKNOWN = 0,
+	OpalMCE_INITIATOR_CPU = 1,
+};
+
+enum OpalMCE_ErrorType {
+	OpalMCE_ERROR_TYPE_UNKNOWN = 0,
+	OpalMCE_ERROR_TYPE_UE = 1,
+	OpalMCE_ERROR_TYPE_SLB = 2,
+	OpalMCE_ERROR_TYPE_ERAT = 3,
+	OpalMCE_ERROR_TYPE_TLB = 4,
+};
+
+enum OpalMCE_UeErrorType {
+	OpalMCE_UE_ERROR_INDETERMINATE = 0,
+	OpalMCE_UE_ERROR_IFETCH = 1,
+	OpalMCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2,
+	OpalMCE_UE_ERROR_LOAD_STORE = 3,
+	OpalMCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4,
+};
+
+enum OpalMCE_SlbErrorType {
+	OpalMCE_SLB_ERROR_INDETERMINATE = 0,
+	OpalMCE_SLB_ERROR_PARITY = 1,
+	OpalMCE_SLB_ERROR_MULTIHIT = 2,
+};
+
+enum OpalMCE_EratErrorType {
+	OpalMCE_ERAT_ERROR_INDETERMINATE = 0,
+	OpalMCE_ERAT_ERROR_PARITY = 1,
+	OpalMCE_ERAT_ERROR_MULTIHIT = 2,
+};
+
+enum OpalMCE_TlbErrorType {
+	OpalMCE_TLB_ERROR_INDETERMINATE = 0,
+	OpalMCE_TLB_ERROR_PARITY = 1,
+	OpalMCE_TLB_ERROR_MULTIHIT = 2,
+};
+
+enum OpalThreadStatus {
+	OPAL_THREAD_INACTIVE = 0x0,
+	OPAL_THREAD_STARTED = 0x1
+};
+
+enum OpalPciBusCompare {
+	OpalPciBusAny	= 0,	/* Any bus number match */
+	OpalPciBus3Bits	= 2,	/* Match top 3 bits of bus number */
+	OpalPciBus4Bits	= 3,	/* Match top 4 bits of bus number */
+	OpalPciBus5Bits	= 4,	/* Match top 5 bits of bus number */
+	OpalPciBus6Bits	= 5,	/* Match top 6 bits of bus number */
+	OpalPciBus7Bits	= 6,	/* Match top 7 bits of bus number */
+	OpalPciBusAll	= 7,	/* Match bus number exactly */
+};
+
+enum OpalDeviceCompare {
+	OPAL_IGNORE_RID_DEVICE_NUMBER = 0,
+	OPAL_COMPARE_RID_DEVICE_NUMBER = 1
+};
+
+enum OpalFuncCompare {
+	OPAL_IGNORE_RID_FUNCTION_NUMBER = 0,
+	OPAL_COMPARE_RID_FUNCTION_NUMBER = 1
+};
+
+enum OpalPeAction {
+	OPAL_UNMAP_PE = 0,
+	OPAL_MAP_PE = 1
+};
+
+enum OpalPciResetAndReinitScope {
+	OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3,
+	OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5,
+	OPAL_PCI_IODA_RESET = 6,
+};
+
+enum OpalPciResetState { OPAL_DEASSERT_RESET = 0, OPAL_ASSERT_RESET = 1 };
+
+struct opal_machine_check_event {
+	enum OpalMCE_Version	version:8;	/* 0x00 */
+	uint8_t			in_use;		/* 0x01 */
+	enum OpalMCE_Severity	severity:8;	/* 0x02 */
+	enum OpalMCE_Initiator	initiator:8;	/* 0x03 */
+	enum OpalMCE_ErrorType	error_type:8;	/* 0x04 */
+	enum OpalMCE_Disposition disposition:8; /* 0x05 */
+	uint8_t			reserved_1[2];	/* 0x06 */
+	uint64_t		gpr3;		/* 0x08 */
+	uint64_t		srr0;		/* 0x10 */
+	uint64_t		srr1;		/* 0x18 */
+	union {					/* 0x20 */
+		struct {
+			enum OpalMCE_UeErrorType ue_error_type:8;
+			uint8_t		effective_address_provided;
+			uint8_t		physical_address_provided;
+			uint8_t		reserved_1[5];
+			uint64_t	effective_address;
+			uint64_t	physical_address;
+			uint8_t		reserved_2[8];
+		} ue_error;
+
+		struct {
+			enum OpalMCE_SlbErrorType slb_error_type:8;
+			uint8_t		effective_address_provided;
+			uint8_t		reserved_1[6];
+			uint64_t	effective_address;
+			uint8_t		reserved_2[16];
+		} slb_error;
+
+		struct {
+			enum OpalMCE_EratErrorType erat_error_type:8;
+			uint8_t		effective_address_provided;
+			uint8_t		reserved_1[6];
+			uint64_t	effective_address;
+			uint8_t		reserved_2[16];
+		} erat_error;
+
+		struct {
+			enum OpalMCE_TlbErrorType tlb_error_type:8;
+			uint8_t		effective_address_provided;
+			uint8_t		reserved_1[6];
+			uint64_t	effective_address;
+			uint8_t		reserved_2[16];
+		} tlb_error;
+	} u;
+};
+
+typedef struct oppanel_line {
+	/* XXX */
+} oppanel_line_t;
+
+/* API functions */
+int64_t opal_console_write(int64_t term_number, int64_t *length,
+			   const uint8_t *buffer);
+int64_t opal_console_read(int64_t term_number, int64_t *length,
+			  uint8_t *buffer);
+int64_t opal_console_write_buffer_space(int64_t term_number,
+					int64_t *length);
+int64_t opal_rtc_read(uint32_t *year_month_day,
+		      uint64_t *hour_minute_second_millisecond);
+int64_t opal_rtc_write(uint32_t year_month_day,
+		       uint64_t hour_minute_second_millisecond);
+int64_t opal_cec_power_down(uint64_t request);
+int64_t opal_cec_reboot(void);
+int64_t opal_read_nvram(uint64_t buffer, uint64_t size, uint64_t offset);
+int64_t opal_write_nvram(uint64_t buffer, uint64_t size, uint64_t offset);
+int64_t opal_handle_interrupt(uint64_t isn, uint64_t *outstanding_event_mask);
+int64_t opal_poll_events(uint64_t *outstanding_event_mask);
+int64_t opal_pci_set_hub_tce_memory(uint64_t hub_id, uint64_t tce_mem_addr,
+				    uint64_t tce_mem_size);
+int64_t opal_pci_set_phb_tce_memory(uint64_t phb_id, uint64_t tce_mem_addr,
+				    uint64_t tce_mem_size);
+int64_t opal_pci_config_read_byte(uint64_t phb_id, uint64_t bus_dev_func,
+				  uint64_t offset, uint8_t *data);
+int64_t opal_pci_config_read_half_word(uint64_t phb_id, uint64_t bus_dev_func,
+				       uint64_t offset, uint16_t *data);
+int64_t opal_pci_config_read_word(uint64_t phb_id, uint64_t bus_dev_func,
+				  uint64_t offset, uint32_t *data);
+int64_t opal_pci_config_write_byte(uint64_t phb_id, uint64_t bus_dev_func,
+				   uint64_t offset, uint8_t data);
+int64_t opal_pci_config_write_half_word(uint64_t phb_id, uint64_t bus_dev_func,
+					uint64_t offset, uint16_t data);
+int64_t opal_pci_config_write_word(uint64_t phb_id, uint64_t bus_dev_func,
+				   uint64_t offset, uint32_t data);
+int64_t opal_set_xive(uint32_t isn, uint16_t server, uint8_t priority);
+int64_t opal_get_xive(uint32_t isn, uint16_t *server, uint8_t *priority);
+int64_t opal_register_exception_handler(uint64_t opal_exception,
+					uint64_t handler_address,
+					uint64_t glue_cache_line);
+int64_t opal_pci_eeh_freeze_status(uint64_t phb_id, uint64_t pe_number,
+				   uint8_t *freeze_state,
+				   uint16_t *pci_error_type,
+				   uint64_t *phb_status);
+int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number,
+				  uint64_t eeh_action_token);
+int64_t opal_pci_shpc(uint64_t phb_id, uint64_t shpc_action, uint8_t *state);
+
+
+
+int64_t opal_pci_phb_mmio_enable(uint64_t phb_id, uint16_t window_type,
+				 uint16_t window_num, uint16_t enable);
+int64_t opal_pci_set_phb_mem_window(uint64_t phb_id, uint16_t window_type,
+				    uint16_t window_num,
+				    uint64_t starting_real_address,
+				    uint64_t starting_pci_address,
+				    uint16_t segment_size);
+int64_t opal_pci_map_pe_mmio_window(uint64_t phb_id, uint16_t pe_number,
+				    uint16_t window_type, uint16_t window_num,
+				    uint16_t segment_num);
+int64_t opal_pci_set_phb_table_memory(uint64_t phb_id, uint64_t rtt_addr,
+				      uint64_t ivt_addr, uint64_t ivt_len,
+				      uint64_t reject_array_addr,
+				      uint64_t peltv_addr);
+int64_t opal_pci_set_pe(uint64_t phb_id, uint64_t pe_number, uint64_t bus_dev_func,
+			uint8_t bus_compare, uint8_t dev_compare, uint8_t func_compare,
+			uint8_t pe_action);
+int64_t opal_pci_set_peltv(uint64_t phb_id, uint32_t parent_pe, uint32_t child_pe,
+			   uint8_t state);
+int64_t opal_pci_set_mve(uint64_t phb_id, uint32_t mve_number, uint32_t pe_number);
+int64_t opal_pci_set_mve_enable(uint64_t phb_id, uint32_t mve_number,
+				uint32_t state);
+int64_t opal_pci_get_xive_reissue(uint64_t phb_id, uint32_t xive_number,
+				  uint8_t *p_bit, uint8_t *q_bit);
+int64_t opal_pci_set_xive_reissue(uint64_t phb_id, uint32_t xive_number,
+				  uint8_t p_bit, uint8_t q_bit);
+int64_t opal_pci_set_xive_pe(uint64_t phb_id, uint32_t pe_number,
+			     uint32_t xive_num);
+int64_t opal_get_xive_source(uint64_t phb_id, uint32_t xive_num,
+			     int32_t *interrupt_source_number);
+int64_t opal_get_msi_32(uint64_t phb_id, uint32_t mve_number, uint32_t xive_num,
+			uint8_t msi_range, uint32_t *msi_address,
+			uint32_t *message_data);
+int64_t opal_get_msi_64(uint64_t phb_id, uint32_t mve_number,
+			uint32_t xive_num, uint8_t msi_range,
+			uint64_t *msi_address, uint32_t *message_data);
+int64_t opal_start_cpu(uint64_t thread_number, uint64_t start_address);
+int64_t opal_query_cpu_status(uint64_t thread_number, uint8_t *thread_status);
+int64_t opal_write_oppanel(oppanel_line_t *lines, uint64_t num_lines);
+int64_t opal_pci_map_pe_dma_window(uint64_t phb_id, uint16_t pe_number, uint16_t window_id,
+				   uint16_t tce_levels, uint64_t tce_table_addr,
+				   uint64_t tce_table_size, uint64_t tce_page_size);
+int64_t opal_pci_map_pe_dma_window_real(uint64_t phb_id, uint16_t pe_number,
+					uint16_t dma_window_number, uint64_t pci_start_addr,
+					uint64_t pci_mem_size);
+int64_t opal_pci_reset(uint64_t phb_id, uint8_t reset_scope, uint8_t assert_state);
+
+/* Internal functions */
+extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
+
+extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
+extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
+
+extern void hvc_opal_init_early(void);
+
+/* Internal functions */
+extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
+				   int depth, void *data);
+
+extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
+extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
+
+extern void hvc_opal_init_early(void);
+
+struct rtc_time;
+extern int opal_set_rtc_time(struct rtc_time *tm);
+extern void opal_get_rtc_time(struct rtc_time *tm);
+extern unsigned long opal_get_boot_time(void);
+extern void opal_nvram_init(void);
+
+extern int opal_machine_check(struct pt_regs *regs);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __OPAL_H */
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/paca.h linux-libre-3.2-gnu/arch/powerpc/include/asm/paca.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/paca.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/paca.h	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@
 #define get_slb_shadow()	(get_paca()->slb_shadow_ptr)
 
 struct task_struct;
+struct opal_machine_check_event;
 
 /*
  * Defines the layout of the paca.
@@ -135,6 +136,13 @@
 	u8 io_sync;			/* writel() needs spin_unlock sync */
 	u8 irq_work_pending;		/* IRQ_WORK interrupt while soft-disable */
 
+#ifdef CONFIG_PPC_POWERNV
+	/* Pointer to OPAL machine check event structure set by the
+	 * early exception handler for use by high level C handler
+	 */
+	struct opal_machine_check_event *opal_mc_evt;
+#endif
+
 	/* Stuff for accurate time accounting */
 	u64 user_time;			/* accumulated usermode TB ticks */
 	u64 system_time;		/* accumulated system TB ticks */
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/page_64.h linux-libre-3.2-gnu/arch/powerpc/include/asm/page_64.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/page_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/page_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -64,17 +64,6 @@
 /* Log 2 of page table size */
 extern u64 ppc64_pft_size;
 
-/* Large pages size */
-#ifdef CONFIG_HUGETLB_PAGE
-extern unsigned int HPAGE_SHIFT;
-#else
-#define HPAGE_SHIFT PAGE_SHIFT
-#endif
-#define HPAGE_SIZE		((1UL) << HPAGE_SHIFT)
-#define HPAGE_MASK		(~(HPAGE_SIZE - 1))
-#define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
-#define HUGE_MAX_HSTATE		(MMU_PAGE_COUNT-1)
-
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_PPC_MM_SLICES
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/page.h linux-libre-3.2-gnu/arch/powerpc/include/asm/page.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/page.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/page.h	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,18 @@
 
 #define PAGE_SIZE		(ASM_CONST(1) << PAGE_SHIFT)
 
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_HUGETLB_PAGE
+extern unsigned int HPAGE_SHIFT;
+#else
+#define HPAGE_SHIFT PAGE_SHIFT
+#endif
+#define HPAGE_SIZE		((1UL) << HPAGE_SHIFT)
+#define HPAGE_MASK		(~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
+#define HUGE_MAX_HSTATE		(MMU_PAGE_COUNT-1)
+#endif
+
 /* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */
 #define __HAVE_ARCH_GATE_AREA		1
 
@@ -158,6 +170,24 @@
 #define is_kernel_addr(x)	((x) >= PAGE_OFFSET)
 #endif
 
+/*
+ * Use the top bit of the higher-level page table entries to indicate whether
+ * the entries we point to contain hugepages.  This works because we know that
+ * the page tables live in kernel space.  If we ever decide to support having
+ * page tables at arbitrary addresses, this breaks and will have to change.
+ */
+#ifdef CONFIG_PPC64
+#define PD_HUGE 0x8000000000000000
+#else
+#define PD_HUGE 0x80000000
+#endif
+
+/*
+ * Some number of bits at the level of the page table that points to
+ * a hugepte are used to encode the size.  This masks those bits.
+ */
+#define HUGEPD_SHIFT_MASK     0x3f
+
 #ifndef __ASSEMBLY__
 
 #undef STRICT_MM_TYPECHECKS
@@ -243,7 +273,6 @@
 #endif
 
 typedef struct { signed long pd; } hugepd_t;
-#define HUGEPD_SHIFT_MASK     0x3f
 
 #ifdef CONFIG_HUGETLB_PAGE
 static inline int hugepd_ok(hugepd_t hpd)
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/pte-book3e.h linux-libre-3.2-gnu/arch/powerpc/include/asm/pte-book3e.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/pte-book3e.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/pte-book3e.h	2012-01-04 18:55:44.000000000 -0500
@@ -72,6 +72,9 @@
 #define	PTE_RPN_SHIFT	(24)
 #endif
 
+#define PTE_WIMGE_SHIFT (19)
+#define PTE_BAP_SHIFT	(2)
+
 /* On 32-bit, we never clear the top part of the PTE */
 #ifdef CONFIG_PPC32
 #define _PTE_NONE_MASK	0xffffffff00000000ULL
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/qe.h linux-libre-3.2-gnu/arch/powerpc/include/asm/qe.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/qe.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/qe.h	2012-01-04 18:55:44.000000000 -0500
@@ -196,7 +196,7 @@
 
 /* Structure that defines QE firmware binary files.
  *
- * See Documentation/powerpc/qe-firmware.txt for a description of these
+ * See Documentation/powerpc/qe_firmware.txt for a description of these
  * fields.
  */
 struct qe_firmware {
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/reg_booke.h linux-libre-3.2-gnu/arch/powerpc/include/asm/reg_booke.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/reg_booke.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/reg_booke.h	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,7 @@
 
 #define MSR_		MSR_ME | MSR_CE
 #define MSR_KERNEL	MSR_ | MSR_64BIT
-#define MSR_USER32	MSR_ | MSR_PR | MSR_EE | MSR_DE
+#define MSR_USER32	MSR_ | MSR_PR | MSR_EE
 #define MSR_USER64	MSR_USER32 | MSR_64BIT
 #elif defined (CONFIG_40x)
 #define MSR_KERNEL	(MSR_ME|MSR_RI|MSR_IR|MSR_DR|MSR_CE)
@@ -548,6 +548,9 @@
 #define L1CSR1_ICFI	0x00000002	/* Instr Cache Flash Invalidate */
 #define L1CSR1_ICE	0x00000001	/* Instr Cache Enable */
 
+/* Bit definitions for L1CSR2. */
+#define L1CSR2_DCWS	0x40000000	/* Data Cache write shadow */
+
 /* Bit definitions for L2CSR0. */
 #define L2CSR0_L2E	0x80000000	/* L2 Cache Enable */
 #define L2CSR0_L2PE	0x40000000	/* L2 Cache Parity/ECC Enable */
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/rtas.h linux-libre-3.2-gnu/arch/powerpc/include/asm/rtas.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/rtas.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/rtas.h	2012-01-04 18:55:44.000000000 -0500
@@ -249,10 +249,12 @@
 #define ERR_FLAG_ALREADY_LOGGED	0x0
 #define ERR_FLAG_BOOT		0x1 	/* log was pulled from NVRAM on boot */
 #define ERR_TYPE_RTAS_LOG	0x2	/* from rtas event-scan */
-#define ERR_TYPE_KERNEL_PANIC	0x4	/* from panic() */
+#define ERR_TYPE_KERNEL_PANIC	0x4	/* from die()/panic() */
+#define ERR_TYPE_KERNEL_PANIC_GZ 0x8	/* ditto, compressed */
 
 /* All the types and not flags */
-#define ERR_TYPE_MASK	(ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC)
+#define ERR_TYPE_MASK \
+	(ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC | ERR_TYPE_KERNEL_PANIC_GZ)
 
 #define RTAS_DEBUG KERN_DEBUG "RTAS: "
  
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/sections.h linux-libre-3.2-gnu/arch/powerpc/include/asm/sections.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/sections.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/sections.h	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
 
 #ifdef __powerpc64__
 
-extern char _end[];
+extern char __end_interrupts[];
 
 static inline int in_kernel_text(unsigned long addr)
 {
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/smp.h linux-libre-3.2-gnu/arch/powerpc/include/asm/smp.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/smp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/smp.h	2012-01-04 18:55:44.000000000 -0500
@@ -65,6 +65,7 @@
 void generic_cpu_die(unsigned int cpu);
 void generic_mach_cpu_die(void);
 void generic_set_cpu_dead(unsigned int cpu);
+int generic_check_cpu_restart(unsigned int cpu);
 #endif
 
 #ifdef CONFIG_PPC64
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/sparsemem.h linux-libre-3.2-gnu/arch/powerpc/include/asm/sparsemem.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/sparsemem.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/sparsemem.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
 #endif /* CONFIG_SPARSEMEM */
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-extern void create_section_mapping(unsigned long start, unsigned long end);
+extern int create_section_mapping(unsigned long start, unsigned long end);
 extern int remove_section_mapping(unsigned long start, unsigned long end);
 #ifdef CONFIG_NUMA
 extern int hot_add_scn_to_nid(unsigned long scn_addr);
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/spu.h linux-libre-3.2-gnu/arch/powerpc/include/asm/spu.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/spu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/spu.h	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 
 #include <linux/workqueue.h>
 #include <linux/sysdev.h>
+#include <linux/mutex.h>
 
 #define LS_SIZE (256 * 1024)
 #define LS_ADDR_MASK (LS_SIZE - 1)
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/synch.h linux-libre-3.2-gnu/arch/powerpc/include/asm/synch.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/synch.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/synch.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 extern unsigned int __start___lwsync_fixup, __stop___lwsync_fixup;
 extern void do_lwsync_fixups(unsigned long value, void *fixup_start,
 			     void *fixup_end);
+extern void do_final_fixups(void);
 
 static inline void eieio(void)
 {
@@ -41,11 +42,15 @@
 	START_LWSYNC_SECTION(97);			\
 	isync;						\
 	MAKE_LWSYNC_SECTION_ENTRY(97, __lwsync_fixup);
-#define PPC_ACQUIRE_BARRIER	"\n" stringify_in_c(__PPC_ACQUIRE_BARRIER)
-#define PPC_RELEASE_BARRIER	stringify_in_c(LWSYNC) "\n"
+#define PPC_ACQUIRE_BARRIER	 "\n" stringify_in_c(__PPC_ACQUIRE_BARRIER)
+#define PPC_RELEASE_BARRIER	 stringify_in_c(LWSYNC) "\n"
+#define PPC_ATOMIC_ENTRY_BARRIER "\n" stringify_in_c(LWSYNC) "\n"
+#define PPC_ATOMIC_EXIT_BARRIER	 "\n" stringify_in_c(sync) "\n"
 #else
 #define PPC_ACQUIRE_BARRIER
 #define PPC_RELEASE_BARRIER
+#define PPC_ATOMIC_ENTRY_BARRIER
+#define PPC_ATOMIC_EXIT_BARRIER
 #endif
 
 #endif /* __KERNEL__ */
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/systbl.h linux-libre-3.2-gnu/arch/powerpc/include/asm/systbl.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/systbl.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/systbl.h	2012-01-04 18:55:44.000000000 -0500
@@ -354,3 +354,5 @@
 SYSCALL_SPU(syncfs)
 COMPAT_SYS_SPU(sendmmsg)
 SYSCALL_SPU(setns)
+COMPAT_SYS(process_vm_readv)
+COMPAT_SYS(process_vm_writev)
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/topology.h linux-libre-3.2-gnu/arch/powerpc/include/asm/topology.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/topology.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/topology.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,14 +19,10 @@
 #define RECLAIM_DISTANCE 10
 
 /*
- * Before going off node we want the VM to try and reclaim from the local
- * node. It does this if the remote distance is larger than RECLAIM_DISTANCE.
- * With the default REMOTE_DISTANCE of 20 and the default RECLAIM_DISTANCE of
- * 20, we never reclaim and go off node straight away.
- *
- * To fix this we choose a smaller value of RECLAIM_DISTANCE.
+ * Avoid creating an extra level of balancing (SD_ALLNODES) on the largest
+ * POWER7 boxes which have a maximum of 32 nodes.
  */
-#define RECLAIM_DISTANCE 10
+#define SD_NODES_PER_DOMAIN 32
 
 #include <asm/mmzone.h>
 
@@ -69,11 +65,11 @@
 	.forkexec_idx		= 0,					\
 									\
 	.flags			= 1*SD_LOAD_BALANCE			\
-				| 1*SD_BALANCE_NEWIDLE			\
+				| 0*SD_BALANCE_NEWIDLE			\
 				| 1*SD_BALANCE_EXEC			\
 				| 1*SD_BALANCE_FORK			\
 				| 0*SD_BALANCE_WAKE			\
-				| 0*SD_WAKE_AFFINE			\
+				| 1*SD_WAKE_AFFINE			\
 				| 0*SD_PREFER_LOCAL			\
 				| 0*SD_SHARE_CPUPOWER			\
 				| 0*SD_POWERSAVINGS_BALANCE		\
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/udbg.h linux-libre-3.2-gnu/arch/powerpc/include/asm/udbg.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/udbg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/udbg.h	2012-01-04 18:55:44.000000000 -0500
@@ -54,6 +54,10 @@
 extern void __init udbg_init_cpm(void);
 extern void __init udbg_init_usbgecko(void);
 extern void __init udbg_init_wsp(void);
+extern void __init udbg_init_ehv_bc(void);
+extern void __init udbg_init_ps3gelic(void);
+extern void __init udbg_init_debug_opal_raw(void);
+extern void __init udbg_init_debug_opal_hvsi(void);
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_UDBG_H */
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/unistd.h linux-libre-3.2-gnu/arch/powerpc/include/asm/unistd.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/unistd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -373,10 +373,12 @@
 #define __NR_syncfs		348
 #define __NR_sendmmsg		349
 #define __NR_setns		350
+#define __NR_process_vm_readv	351
+#define __NR_process_vm_writev	352
 
 #ifdef __KERNEL__
 
-#define __NR_syscalls		351
+#define __NR_syscalls		353
 
 #define __NR__exit __NR_exit
 #define NR_syscalls	__NR_syscalls
diff -druN linux-libre-3.1-gnu/arch/powerpc/include/asm/xics.h linux-libre-3.2-gnu/arch/powerpc/include/asm/xics.h
--- linux-libre-3.1-gnu/arch/powerpc/include/asm/xics.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/include/asm/xics.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,8 +15,8 @@
 #define	DEFAULT_PRIORITY	5
 
 /*
- * Mark IPIs as higher priority so we can take them inside interrupts that
- * arent marked IRQF_DISABLED
+ * Mark IPIs as higher priority so we can take them inside interrupts
+ * FIXME: still true now?
  */
 #define IPI_PRIORITY		4
 
@@ -27,10 +27,18 @@
 #define MAX_NUM_PRIORITIES	3
 
 /* Native ICP */
+#ifdef CONFIG_PPC_ICP_NATIVE
 extern int icp_native_init(void);
+#else
+static inline int icp_native_init(void) { return -ENODEV; }
+#endif
 
 /* PAPR ICP */
+#ifdef CONFIG_PPC_ICP_HV
 extern int icp_hv_init(void);
+#else
+static inline int icp_hv_init(void) { return -ENODEV; }
+#endif
 
 /* ICP ops */
 struct icp_ops {
@@ -51,7 +59,18 @@
 extern int ics_native_init(void);
 
 /* RTAS ICS */
+#ifdef CONFIG_PPC_ICS_RTAS
 extern int ics_rtas_init(void);
+#else
+static inline int ics_rtas_init(void) { return -ENODEV; }
+#endif
+
+/* HAL ICS */
+#ifdef CONFIG_PPC_POWERNV
+extern int ics_opal_init(void);
+#else
+static inline int ics_opal_init(void) { return -ENODEV; }
+#endif
 
 /* ICS instance, hooked up to chip_data of an irq */
 struct ics {
diff -druN linux-libre-3.1-gnu/arch/powerpc/Kconfig linux-libre-3.2-gnu/arch/powerpc/Kconfig
--- linux-libre-3.1-gnu/arch/powerpc/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -323,7 +323,7 @@
 
 config HOTPLUG_CPU
 	bool "Support for enabling/disabling CPUs"
-	depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
+	depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC || PPC_POWERNV)
 	---help---
 	  Say Y here to be able to disable and re-enable individual
 	  CPUs at runtime on SMP machines.
@@ -345,7 +345,7 @@
 
 config KEXEC
 	bool "kexec system call (EXPERIMENTAL)"
-	depends on (PPC_BOOK3S || FSL_BOOKE) && EXPERIMENTAL
+	depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP && !PPC_47x)) && EXPERIMENTAL
 	help
 	  kexec is a system call that implements the ability to shutdown your
 	  current kernel, and to start another kernel.  It is like a reboot
@@ -379,10 +379,6 @@
 
 	  If unsure, say "N"
 
-config PPCBUG_NVRAM
-	bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC
-	default y if PPC_PREP
-
 config IRQ_ALL_CPUS
 	bool "Distribute interrupts on all CPUs by default"
 	depends on SMP && !MV64360
@@ -429,8 +425,7 @@
 	def_bool y
 
 config SYS_SUPPORTS_HUGETLBFS
-       def_bool y
-       depends on PPC_BOOK3S_64
+	bool
 
 source "mm/Kconfig"
 
@@ -656,6 +651,8 @@
 
 config FSL_SOC
 	bool
+	select HAVE_CAN_FLEXCAN if NET && CAN
+	select PPC_CLOCK if CAN_FLEXCAN
 
 config FSL_PCI
  	bool
@@ -744,24 +741,6 @@
 	depends on PCI_8260 && !8272
 	default y
 
-choice
-	prompt "IDMA channel for PCI 9 workaround"
-	depends on 8260_PCI9
-
-config 8260_PCI9_IDMA1
-	bool "IDMA1"
-
-config 8260_PCI9_IDMA2
-	bool "IDMA2"
-
-config 8260_PCI9_IDMA3
-	bool "IDMA3"
-
-config 8260_PCI9_IDMA4
-	bool "IDMA4"
-
-endchoice
-
 source "drivers/pci/pcie/Kconfig"
 
 source "drivers/pci/Kconfig"
diff -druN linux-libre-3.1-gnu/arch/powerpc/Kconfig.debug linux-libre-3.2-gnu/arch/powerpc/Kconfig.debug
--- linux-libre-3.1-gnu/arch/powerpc/Kconfig.debug	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/Kconfig.debug	2012-01-04 18:55:44.000000000 -0500
@@ -141,9 +141,6 @@
 
 config PPC_EARLY_DEBUG
 	bool "Early debugging (dangerous)"
-	# PPC_EARLY_DEBUG on 440 leaves AS=1 mappings above the TLB high water
-	# mark, which doesn't work with current 440 KVM.
-	depends on !KVM
 	help
 	  Say Y to enable some early debugging facilities that may be available
 	  for your processor/board combination. Those facilities are hacks
@@ -222,7 +219,9 @@
 
 config PPC_EARLY_DEBUG_44x
 	bool "Early serial debugging for IBM/AMCC 44x CPUs"
-	depends on 44x
+	# PPC_EARLY_DEBUG on 440 leaves AS=1 mappings above the TLB high water
+	# mark, which doesn't work with current 440 KVM.
+	depends on 44x && !KVM
 	help
 	  Select this to enable early debugging for IBM 44x chips via the
 	  inbuilt serial port.  If you enable this, ensure you set
@@ -258,8 +257,35 @@
 	depends on PPC_WSP
 	select PPC_UDBG_16550
 
+config PPC_EARLY_DEBUG_PS3GELIC
+	bool "Early debugging through the PS3 Ethernet port"
+	depends on PPC_PS3
+	select PS3GELIC_UDBG
+	help
+	  Select this to enable early debugging for the PlayStation3 via
+	  UDP broadcasts sent out through the Ethernet port.
+
+config PPC_EARLY_DEBUG_OPAL_RAW
+	bool "OPAL raw console"
+	depends on HVC_OPAL
+	help
+	  Select this to enable early debugging for the PowerNV platform
+	  using a "raw" console
+
+config PPC_EARLY_DEBUG_OPAL_HVSI
+	bool "OPAL hvsi console"
+	depends on HVC_OPAL
+	help
+	  Select this to enable early debugging for the PowerNV platform
+	  using an "hvsi" console
+
 endchoice
 
+config PPC_EARLY_DEBUG_OPAL
+	def_bool y
+	depends on PPC_EARLY_DEBUG_OPAL_RAW || PPC_EARLY_DEBUG_OPAL_HVSI
+
+
 config PPC_EARLY_DEBUG_HVSI_VTERMNO
 	hex "vterm number to use with early debug HVSI"
 	depends on PPC_EARLY_DEBUG_LPAR_HVSI
@@ -268,6 +294,18 @@
 	  You probably want 0x30000000 for your first serial port and
 	  0x30000001 for your second one
 
+config PPC_EARLY_DEBUG_OPAL_VTERMNO
+	hex "vterm number to use with OPAL early debug"
+	depends on PPC_EARLY_DEBUG_OPAL
+	default "0"
+	help
+	  This correspond to which /dev/hvcN you want to use for early
+	  debug.
+
+	  On OPAL v1 (takeover) this should always be 0
+	  On OPAL v2, this will be 0 for network console and 1 or 2 for
+	  the machine built-in serial ports.
+
 config PPC_EARLY_DEBUG_44x_PHYSLOW
 	hex "Low 32 bits of early debug UART physical address"
 	depends on PPC_EARLY_DEBUG_44x
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/asm-offsets.c linux-libre-3.2-gnu/arch/powerpc/kernel/asm-offsets.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/asm-offsets.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/asm-offsets.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,10 +44,14 @@
 #include <asm/compat.h>
 #include <asm/mmu.h>
 #include <asm/hvcall.h>
+#include <asm/xics.h>
 #endif
 #ifdef CONFIG_PPC_ISERIES
 #include <asm/iseries/alpaca.h>
 #endif
+#ifdef CONFIG_PPC_POWERNV
+#include <asm/opal.h>
+#endif
 #if defined(CONFIG_KVM) || defined(CONFIG_KVM_GUEST)
 #include <linux/kvm_host.h>
 #endif
@@ -449,8 +453,6 @@
 #ifdef CONFIG_PPC_BOOK3S
 	DEFINE(VCPU_KVM, offsetof(struct kvm_vcpu, kvm));
 	DEFINE(VCPU_VCPUID, offsetof(struct kvm_vcpu, vcpu_id));
-	DEFINE(VCPU_HOST_RETIP, offsetof(struct kvm_vcpu, arch.host_retip));
-	DEFINE(VCPU_HOST_MSR, offsetof(struct kvm_vcpu, arch.host_msr));
 	DEFINE(VCPU_PURR, offsetof(struct kvm_vcpu, arch.purr));
 	DEFINE(VCPU_SPURR, offsetof(struct kvm_vcpu, arch.spurr));
 	DEFINE(VCPU_DSCR, offsetof(struct kvm_vcpu, arch.dscr));
@@ -458,14 +460,12 @@
 	DEFINE(VCPU_UAMOR, offsetof(struct kvm_vcpu, arch.uamor));
 	DEFINE(VCPU_CTRL, offsetof(struct kvm_vcpu, arch.ctrl));
 	DEFINE(VCPU_DABR, offsetof(struct kvm_vcpu, arch.dabr));
-	DEFINE(VCPU_TRAMPOLINE_LOWMEM, offsetof(struct kvm_vcpu, arch.trampoline_lowmem));
-	DEFINE(VCPU_TRAMPOLINE_ENTER, offsetof(struct kvm_vcpu, arch.trampoline_enter));
-	DEFINE(VCPU_HIGHMEM_HANDLER, offsetof(struct kvm_vcpu, arch.highmem_handler));
-	DEFINE(VCPU_RMCALL, offsetof(struct kvm_vcpu, arch.rmcall));
 	DEFINE(VCPU_HFLAGS, offsetof(struct kvm_vcpu, arch.hflags));
 	DEFINE(VCPU_DEC, offsetof(struct kvm_vcpu, arch.dec));
 	DEFINE(VCPU_DEC_EXPIRES, offsetof(struct kvm_vcpu, arch.dec_expires));
 	DEFINE(VCPU_PENDING_EXC, offsetof(struct kvm_vcpu, arch.pending_exceptions));
+	DEFINE(VCPU_CEDED, offsetof(struct kvm_vcpu, arch.ceded));
+	DEFINE(VCPU_PRODDED, offsetof(struct kvm_vcpu, arch.prodded));
 	DEFINE(VCPU_VPA, offsetof(struct kvm_vcpu, arch.vpa));
 	DEFINE(VCPU_MMCR, offsetof(struct kvm_vcpu, arch.mmcr));
 	DEFINE(VCPU_PMC, offsetof(struct kvm_vcpu, arch.pmc));
@@ -481,6 +481,7 @@
 	DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_count));
 	DEFINE(VCORE_NAP_COUNT, offsetof(struct kvmppc_vcore, nap_count));
 	DEFINE(VCORE_IN_GUEST, offsetof(struct kvmppc_vcore, in_guest));
+	DEFINE(VCORE_NAPPING_THREADS, offsetof(struct kvmppc_vcore, napping_threads));
 	DEFINE(VCPU_SVCPU, offsetof(struct kvmppc_vcpu_book3s, shadow_vcpu) -
 			   offsetof(struct kvmppc_vcpu_book3s, vcpu));
 	DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige));
@@ -537,6 +538,8 @@
 	HSTATE_FIELD(HSTATE_SCRATCH0, scratch0);
 	HSTATE_FIELD(HSTATE_SCRATCH1, scratch1);
 	HSTATE_FIELD(HSTATE_IN_GUEST, in_guest);
+	HSTATE_FIELD(HSTATE_RESTORE_HID5, restore_hid5);
+	HSTATE_FIELD(HSTATE_NAPPING, napping);
 
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 	HSTATE_FIELD(HSTATE_KVM_VCPU, kvm_vcpu);
@@ -549,6 +552,7 @@
 	HSTATE_FIELD(HSTATE_DSCR, host_dscr);
 	HSTATE_FIELD(HSTATE_DABR, dabr);
 	HSTATE_FIELD(HSTATE_DECEXP, dec_expires);
+	DEFINE(IPI_PRIORITY, IPI_PRIORITY);
 #endif /* CONFIG_KVM_BOOK3S_64_HV */
 
 #else /* CONFIG_PPC_BOOK3S */
@@ -609,5 +613,12 @@
 					arch.timing_last_enter.tv32.tbl));
 #endif
 
+#ifdef CONFIG_PPC_POWERNV
+	DEFINE(OPAL_MC_GPR3, offsetof(struct opal_machine_check_event, gpr3));
+	DEFINE(OPAL_MC_SRR0, offsetof(struct opal_machine_check_event, srr0));
+	DEFINE(OPAL_MC_SRR1, offsetof(struct opal_machine_check_event, srr1));
+	DEFINE(PACA_OPAL_MC_EVT, offsetof(struct paca_struct, opal_mc_evt));
+#endif
+
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/btext.c linux-libre-3.2-gnu/arch/powerpc/kernel/btext.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/btext.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/btext.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/memblock.h>
 
 #include <asm/sections.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/clock.c linux-libre-3.2-gnu/arch/powerpc/kernel/clock.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/errno.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/clk_interface.h>
 
 struct clk_interface clk_functions;
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/cputable.c linux-libre-3.2-gnu/arch/powerpc/kernel/cputable.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/cputable.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/cputable.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/sched.h>
 #include <linux/threads.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/oprofile_impl.h>
 #include <asm/cputable.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/crash.c linux-libre-3.2-gnu/arch/powerpc/kernel/crash.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/crash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/crash.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/reboot.h>
 #include <linux/kexec.h>
 #include <linux/bootmem.h>
+#include <linux/export.h>
 #include <linux/crash_dump.h>
 #include <linux/delay.h>
 #include <linux/elf.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/dma.c linux-libre-3.2-gnu/arch/powerpc/kernel/dma.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/dma-debug.h>
 #include <linux/gfp.h>
 #include <linux/memblock.h>
+#include <linux/export.h>
 #include <asm/bug.h>
 #include <asm/abs_addr.h>
 #include <asm/machdep.h>
@@ -96,6 +97,18 @@
 #endif
 }
 
+static u64 dma_direct_get_required_mask(struct device *dev)
+{
+	u64 end, mask;
+
+	end = memblock_end_of_DRAM() + get_dma_offset(dev);
+
+	mask = 1ULL << (fls64(end) - 1);
+	mask += mask - 1;
+
+	return mask;
+}
+
 static inline dma_addr_t dma_direct_map_page(struct device *dev,
 					     struct page *page,
 					     unsigned long offset,
@@ -137,13 +150,14 @@
 #endif
 
 struct dma_map_ops dma_direct_ops = {
-	.alloc_coherent	= dma_direct_alloc_coherent,
-	.free_coherent	= dma_direct_free_coherent,
-	.map_sg		= dma_direct_map_sg,
-	.unmap_sg	= dma_direct_unmap_sg,
-	.dma_supported	= dma_direct_dma_supported,
-	.map_page	= dma_direct_map_page,
-	.unmap_page	= dma_direct_unmap_page,
+	.alloc_coherent			= dma_direct_alloc_coherent,
+	.free_coherent			= dma_direct_free_coherent,
+	.map_sg				= dma_direct_map_sg,
+	.unmap_sg			= dma_direct_unmap_sg,
+	.dma_supported			= dma_direct_dma_supported,
+	.map_page			= dma_direct_map_page,
+	.unmap_page			= dma_direct_unmap_page,
+	.get_required_mask		= dma_direct_get_required_mask,
 #ifdef CONFIG_NOT_COHERENT_CACHE
 	.sync_single_for_cpu 		= dma_direct_sync_single,
 	.sync_single_for_device 	= dma_direct_sync_single,
@@ -170,6 +184,23 @@
 }
 EXPORT_SYMBOL(dma_set_mask);
 
+u64 dma_get_required_mask(struct device *dev)
+{
+	struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+	if (ppc_md.dma_get_required_mask)
+		return ppc_md.dma_get_required_mask(dev);
+
+	if (unlikely(dma_ops == NULL))
+		return 0;
+
+	if (dma_ops->get_required_mask)
+		return dma_ops->get_required_mask(dev);
+
+	return DMA_BIT_MASK(8 * sizeof(dma_addr_t));
+}
+EXPORT_SYMBOL_GPL(dma_get_required_mask);
+
 static int __init dma_init(void)
 {
        dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/dma-iommu.c linux-libre-3.2-gnu/arch/powerpc/kernel/dma-iommu.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/dma-iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/dma-iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,7 @@
  * busses using the iommu infrastructure
  */
 
+#include <linux/export.h>
 #include <asm/iommu.h>
 
 /*
@@ -90,13 +91,27 @@
 		return 1;
 }
 
+static u64 dma_iommu_get_required_mask(struct device *dev)
+{
+	struct iommu_table *tbl = get_iommu_table_base(dev);
+	u64 mask;
+	if (!tbl)
+		return 0;
+
+	mask = 1ULL < (fls_long(tbl->it_offset + tbl->it_size) - 1);
+	mask += mask - 1;
+
+	return mask;
+}
+
 struct dma_map_ops dma_iommu_ops = {
-	.alloc_coherent	= dma_iommu_alloc_coherent,
-	.free_coherent	= dma_iommu_free_coherent,
-	.map_sg		= dma_iommu_map_sg,
-	.unmap_sg	= dma_iommu_unmap_sg,
-	.dma_supported	= dma_iommu_dma_supported,
-	.map_page	= dma_iommu_map_page,
-	.unmap_page	= dma_iommu_unmap_page,
+	.alloc_coherent		= dma_iommu_alloc_coherent,
+	.free_coherent		= dma_iommu_free_coherent,
+	.map_sg			= dma_iommu_map_sg,
+	.unmap_sg		= dma_iommu_unmap_sg,
+	.dma_supported		= dma_iommu_dma_supported,
+	.map_page		= dma_iommu_map_page,
+	.unmap_page		= dma_iommu_unmap_page,
+	.get_required_mask	= dma_iommu_get_required_mask,
 };
 EXPORT_SYMBOL(dma_iommu_ops);
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/dma-swiotlb.c linux-libre-3.2-gnu/arch/powerpc/kernel/dma-swiotlb.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/dma-swiotlb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/dma-swiotlb.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,21 @@
 
 unsigned int ppc_swiotlb_enable;
 
+static u64 swiotlb_powerpc_get_required(struct device *dev)
+{
+	u64 end, mask, max_direct_dma_addr = dev->archdata.max_direct_dma_addr;
+
+	end = memblock_end_of_DRAM();
+	if (max_direct_dma_addr && end > max_direct_dma_addr)
+		end = max_direct_dma_addr;
+	end += get_dma_offset(dev);
+
+	mask = 1ULL << (fls64(end) - 1);
+	mask += mask - 1;
+
+	return mask;
+}
+
 /*
  * At the moment, all platforms that use this code only require
  * swiotlb to be used if we're operating on HIGHMEM.  Since
@@ -44,6 +59,7 @@
 	.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
 	.sync_sg_for_device = swiotlb_sync_sg_for_device,
 	.mapping_error = swiotlb_dma_mapping_error,
+	.get_required_mask = swiotlb_powerpc_get_required,
 };
 
 void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev)
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/entry_32.S linux-libre-3.2-gnu/arch/powerpc/kernel/entry_32.S
--- linux-libre-3.1-gnu/arch/powerpc/kernel/entry_32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/entry_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -215,7 +215,22 @@
 	stw	r9,8(r1)
 	stw	r11,12(r1)
 	stw	r3,ORIG_GPR3(r1)
+	/*
+	 * The trace_hardirqs_off will use CALLER_ADDR0 and CALLER_ADDR1.
+	 * If from user mode there is only one stack frame on the stack, and
+	 * accessing CALLER_ADDR1 will cause oops. So we need create a dummy
+	 * stack frame to make trace_hardirqs_off happy.
+	 */
+	andi.	r12,r12,MSR_PR
+	beq	11f
+	stwu	r1,-16(r1)
 	bl	trace_hardirqs_off
+	addi	r1,r1,16
+	b	12f
+
+11:
+	bl	trace_hardirqs_off
+12:
 	lwz	r0,GPR0(r1)
 	lwz	r3,ORIG_GPR3(r1)
 	lwz	r4,GPR4(r1)
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/exceptions-64s.S linux-libre-3.2-gnu/arch/powerpc/kernel/exceptions-64s.S
--- linux-libre-3.1-gnu/arch/powerpc/kernel/exceptions-64s.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/exceptions-64s.S	2012-01-04 18:55:44.000000000 -0500
@@ -267,7 +267,7 @@
 
 #ifdef CONFIG_CBE_RAS
 	STD_EXCEPTION_HV(0x1200, 0x1202, cbe_system_error)
-	KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1202)
+	KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1202)
 #endif /* CONFIG_CBE_RAS */
 
 	STD_EXCEPTION_PSERIES(0x1300, 0x1300, instruction_breakpoint)
@@ -275,7 +275,7 @@
 
 #ifdef CONFIG_CBE_RAS
 	STD_EXCEPTION_HV(0x1600, 0x1602, cbe_maintenance)
-	KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1602)
+	KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1602)
 #endif /* CONFIG_CBE_RAS */
 
 	STD_EXCEPTION_PSERIES(0x1700, 0x1700, altivec_assist)
@@ -283,7 +283,7 @@
 
 #ifdef CONFIG_CBE_RAS
 	STD_EXCEPTION_HV(0x1800, 0x1802, cbe_thermal)
-	KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1802)
+	KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1802)
 #endif /* CONFIG_CBE_RAS */
 
 	. = 0x3000
@@ -427,16 +427,6 @@
 	b	.				/* prevent spec. execution */
 #endif /* __DISABLED__ */
 
-/* KVM's trampoline code needs to be close to the interrupt handlers */
-
-#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
-#ifdef CONFIG_KVM_BOOK3S_PR
-#include "../kvm/book3s_rmhandlers.S"
-#else
-#include "../kvm/book3s_hv_rmhandlers.S"
-#endif
-#endif
-
 	.align	7
 	.globl	__end_interrupts
 __end_interrupts:
@@ -1143,7 +1133,7 @@
 	rfid
 	b	.	/* prevent speculative execution */
 
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 /*
  * Data area reserved for FWNMI option.
  * This address (0x7000) is fixed by the RPA.
@@ -1151,7 +1141,7 @@
 	.= 0x7000
 	.globl fwnmi_data_area
 fwnmi_data_area:
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
 
 	/* iSeries does not use the FWNMI stuff, so it is safe to put
 	 * this here, even if we later allow kernels that will boot on
@@ -1176,9 +1166,12 @@
 
 #endif /* CONFIG_PPC_ISERIES */
 
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
+	/* pseries and powernv need to keep the whole page from
+	 * 0x7000 to 0x8000 free for use by the firmware
+	 */
         . = 0x8000
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
 
 /*
  * Space for CPU0's segment table.
@@ -1193,3 +1186,19 @@
 	.globl initial_stab
 initial_stab:
 	.space	4096
+#ifdef CONFIG_PPC_POWERNV
+_GLOBAL(opal_mc_secondary_handler)
+	HMT_MEDIUM
+	SET_SCRATCH0(r13)
+	GET_PACA(r13)
+	clrldi	r3,r3,2
+	tovirt(r3,r3)
+	std	r3,PACA_OPAL_MC_EVT(r13)
+	ld	r13,OPAL_MC_SRR0(r3)
+	mtspr	SPRN_SRR0,r13
+	ld	r13,OPAL_MC_SRR1(r3)
+	mtspr	SPRN_SRR1,r13
+	ld	r3,OPAL_MC_GPR3(r3)
+	GET_SCRATCH0(r13)
+	b	machine_check_pSeries
+#endif /* CONFIG_PPC_POWERNV */
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/firmware.c linux-libre-3.2-gnu/arch/powerpc/kernel/firmware.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/firmware.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/firmware.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,8 @@
  *  2 of the License, or (at your option) any later version.
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/cache.h>
 
 #include <asm/firmware.h>
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/head_32.S linux-libre-3.2-gnu/arch/powerpc/kernel/head_32.S
--- linux-libre-3.1-gnu/arch/powerpc/kernel/head_32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/head_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -139,8 +139,7 @@
 	trap
 #endif /* CONFIG_PPC_PMAC */
 
-1:	mr	r31,r3			/* save parameters */
-	mr	r30,r4
+1:	mr	r31,r3			/* save device tree ptr */
 	li	r24,0			/* cpu # */
 
 /*
@@ -964,8 +963,8 @@
  * Do early platform-specific initialization,
  * and set up the MMU.
  */
-	mr	r3,r31
-	mr	r4,r30
+	li	r3,0
+	mr	r4,r31
 	bl	machine_init
 	bl	__save_cpu_setup
 	bl	MMU_init
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/head_40x.S linux-libre-3.2-gnu/arch/powerpc/kernel/head_40x.S
--- linux-libre-3.1-gnu/arch/powerpc/kernel/head_40x.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/head_40x.S	2012-01-04 18:55:44.000000000 -0500
@@ -58,13 +58,7 @@
 _ENTRY(_stext);
 _ENTRY(_start);
 
-	/* Save parameters we are passed.
-	*/
-	mr	r31,r3
-	mr	r30,r4
-	mr	r29,r5
-	mr	r28,r6
-	mr	r27,r7
+	mr	r31,r3			/* save device tree ptr */
 
 	/* We have to turn on the MMU right away so we get cache modes
 	 * set correctly.
@@ -849,11 +843,8 @@
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-	mr	r3,r31
-	mr	r4,r30
-	mr	r5,r29
-	mr	r6,r28
-	mr	r7,r27
+	li	r3,0
+	mr	r4,r31
 	bl	machine_init
 	bl	MMU_init
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/head_44x.S linux-libre-3.2-gnu/arch/powerpc/kernel/head_44x.S
--- linux-libre-3.1-gnu/arch/powerpc/kernel/head_44x.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/head_44x.S	2012-01-04 18:55:44.000000000 -0500
@@ -61,14 +61,7 @@
 	 * of abatron_pteptrs
 	 */
 	nop
-/*
- * Save parameters we are passed
- */
-	mr	r31,r3
-	mr	r30,r4
-	mr	r29,r5
-	mr	r28,r6
-	mr	r27,r7
+	mr	r31,r3		/* save device tree ptr */
 	li	r24,0		/* CPU number */
 
 	bl	init_cpu_state
@@ -120,11 +113,8 @@
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-	mr	r3,r31
-	mr	r4,r30
-	mr	r5,r29
-	mr	r6,r28
-	mr	r7,r27
+	li	r3,0
+	mr	r4,r31
 	bl	machine_init
 	bl	MMU_init
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/head_64.S linux-libre-3.2-gnu/arch/powerpc/kernel/head_64.S
--- linux-libre-3.1-gnu/arch/powerpc/kernel/head_64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/head_64.S	2012-01-04 18:55:44.000000000 -0500
@@ -51,6 +51,11 @@
  *  For pSeries or server processors:
  *   1. The MMU is off & open firmware is running in real mode.
  *   2. The kernel is entered at __start
+ * -or- For OPAL entry:
+ *   1. The MMU is off, processor in HV mode, primary CPU enters at 0
+ *      with device-tree in gpr3. We also get OPAL base in r8 and
+ *	entry in r9 for debugging purposes
+ *   2. Secondary processors enter at 0x60 with PIR in gpr3
  *
  *  For iSeries:
  *   1. The MMU is on (as it always is for iSeries)
@@ -331,6 +336,11 @@
 	/* Save parameters */
 	mr	r31,r3
 	mr	r30,r4
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+	/* Save OPAL entry */
+	mr	r28,r8
+	mr	r29,r9
+#endif
 
 #ifdef CONFIG_PPC_BOOK3E
 	bl	.start_initialization_book3e
@@ -674,9 +684,9 @@
 _GLOBAL(relative_toc)
 	mflr	r0
 	bcl	20,31,$+4
-0:	mflr	r9
-	ld	r2,(p_toc - 0b)(r9)
-	add	r2,r2,r9
+0:	mflr	r11
+	ld	r2,(p_toc - 0b)(r11)
+	add	r2,r2,r11
 	mtlr	r0
 	blr
 
@@ -707,6 +717,12 @@
 	bdnz	3b
 4:
 
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+	/* Setup OPAL entry */
+	std	r28,0(r11);
+	std	r29,8(r11);
+#endif
+
 #ifndef CONFIG_PPC_BOOK3E
 	mfmsr	r6
 	ori	r6,r6,MSR_RI
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/head_8xx.S linux-libre-3.2-gnu/arch/powerpc/kernel/head_8xx.S
--- linux-libre-3.1-gnu/arch/powerpc/kernel/head_8xx.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/head_8xx.S	2012-01-04 18:55:44.000000000 -0500
@@ -76,11 +76,7 @@
  */
 	.globl	__start
 __start:
-	mr	r31,r3			/* save parameters */
-	mr	r30,r4
-	mr	r29,r5
-	mr	r28,r6
-	mr	r27,r7
+	mr	r31,r3			/* save device tree ptr */
 
 	/* We have to turn on the MMU right away so we get cache modes
 	 * set correctly.
@@ -723,11 +719,8 @@
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-	mr	r3,r31
-	mr	r4,r30
-	mr	r5,r29
-	mr	r6,r28
-	mr	r7,r27
+	li	r3,0
+	mr	r4,r31
 	bl	machine_init
 	bl	MMU_init
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/head_fsl_booke.S linux-libre-3.2-gnu/arch/powerpc/kernel/head_fsl_booke.S
--- linux-libre-3.1-gnu/arch/powerpc/kernel/head_fsl_booke.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/head_fsl_booke.S	2012-01-04 18:55:44.000000000 -0500
@@ -63,17 +63,30 @@
 	 * of abatron_pteptrs
 	 */
 	nop
-/*
- * Save parameters we are passed
- */
-	mr	r31,r3
-	mr	r30,r4
-	mr	r29,r5
-	mr	r28,r6
-	mr	r27,r7
-	li	r25,0		/* phys kernel start (low) */
-	li	r24,0		/* CPU number */
-	li	r23,0		/* phys kernel start (high) */
+
+	/* Translate device tree address to physical, save in r30/r31 */
+	mfmsr	r16
+	mfspr	r17,SPRN_PID
+	rlwinm	r17,r17,16,0x3fff0000	/* turn PID into MAS6[SPID] */
+	rlwimi	r17,r16,28,0x00000001	/* turn MSR[DS] into MAS6[SAS] */
+	mtspr	SPRN_MAS6,r17
+
+	tlbsx	0,r3			/* must succeed */
+
+	mfspr	r16,SPRN_MAS1
+	mfspr	r20,SPRN_MAS3
+	rlwinm	r17,r16,25,0x1f		/* r17 = log2(page size) */
+	li	r18,1024
+	slw	r18,r18,r17		/* r18 = page size */
+	addi	r18,r18,-1
+	and	r19,r3,r18		/* r19 = page offset */
+	andc	r31,r20,r18		/* r31 = page base */
+	or	r31,r31,r19		/* r31 = devtree phys addr */
+	mfspr	r30,SPRN_MAS7
+
+	li	r25,0			/* phys kernel start (low) */
+	li	r24,0			/* CPU number */
+	li	r23,0			/* phys kernel start (high) */
 
 /* We try to not make any assumptions about how the boot loader
  * setup or used the TLBs.  We invalidate all mappings from the
@@ -198,11 +211,8 @@
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-	mr	r3,r31
-	mr	r4,r30
-	mr	r5,r29
-	mr	r6,r28
-	mr	r7,r27
+	mr	r3,r30
+	mr	r4,r31
 	bl	machine_init
 	bl	MMU_init
 
@@ -236,8 +246,24 @@
  * if we find the pte (fall through):
  *   r11 is low pte word
  *   r12 is pointer to the pte
+ *   r10 is the pshift from the PGD, if we're a hugepage
  */
 #ifdef CONFIG_PTE_64BIT
+#ifdef CONFIG_HUGETLB_PAGE
+#define FIND_PTE	\
+	rlwinm	r12, r10, 13, 19, 29;	/* Compute pgdir/pmd offset */	\
+	lwzx	r11, r12, r11;		/* Get pgd/pmd entry */		\
+	rlwinm.	r12, r11, 0, 0, 20;	/* Extract pt base address */	\
+	blt	1000f;			/* Normal non-huge page */	\
+	beq	2f;			/* Bail if no table */		\
+	oris	r11, r11, PD_HUGE@h;	/* Put back address bit */	\
+	andi.	r10, r11, HUGEPD_SHIFT_MASK@l; /* extract size field */	\
+	xor	r12, r10, r11;		/* drop size bits from pointer */ \
+	b	1001f;							\
+1000:	rlwimi	r12, r10, 23, 20, 28;	/* Compute pte address */	\
+	li	r10, 0;			/* clear r10 */			\
+1001:	lwz	r11, 4(r12);		/* Get pte entry */
+#else
 #define FIND_PTE	\
 	rlwinm	r12, r10, 13, 19, 29;	/* Compute pgdir/pmd offset */	\
 	lwzx	r11, r12, r11;		/* Get pgd/pmd entry */		\
@@ -245,7 +271,8 @@
 	beq	2f;			/* Bail if no table */		\
 	rlwimi	r12, r10, 23, 20, 28;	/* Compute pte address */	\
 	lwz	r11, 4(r12);		/* Get pte entry */
-#else
+#endif /* HUGEPAGE */
+#else /* !PTE_64BIT */
 #define FIND_PTE	\
 	rlwimi	r11, r10, 12, 20, 29;	/* Create L1 (pgdir/pmd) address */	\
 	lwz	r11, 0(r11);		/* Get L1 entry */			\
@@ -402,8 +429,8 @@
 
 #ifdef CONFIG_PTE_64BIT
 #ifdef CONFIG_SMP
-	subf	r10,r11,r12		/* create false data dep */
-	lwzx	r13,r11,r10		/* Get upper pte bits */
+	subf	r13,r11,r12		/* create false data dep */
+	lwzx	r13,r11,r13		/* Get upper pte bits */
 #else
 	lwz	r13,0(r12)		/* Get upper pte bits */
 #endif
@@ -483,8 +510,8 @@
 
 #ifdef CONFIG_PTE_64BIT
 #ifdef CONFIG_SMP
-	subf	r10,r11,r12		/* create false data dep */
-	lwzx	r13,r11,r10		/* Get upper pte bits */
+	subf	r13,r11,r12		/* create false data dep */
+	lwzx	r13,r11,r13		/* Get upper pte bits */
 #else
 	lwz	r13,0(r12)		/* Get upper pte bits */
 #endif
@@ -548,7 +575,7 @@
 /*
  * Both the instruction and data TLB miss get to this
  * point to load the TLB.
- *	r10 - available to use
+ *	r10 - tsize encoding (if HUGETLB_PAGE) or available to use
  *	r11 - TLB (info from Linux PTE)
  *	r12 - available to use
  *	r13 - upper bits of PTE (if PTE_64BIT) or available to use
@@ -558,21 +585,73 @@
  *	Upon exit, we reload everything and RFI.
  */
 finish_tlb_load:
+#ifdef CONFIG_HUGETLB_PAGE
+	cmpwi	6, r10, 0			/* check for huge page */
+	beq	6, finish_tlb_load_cont    	/* !huge */
+
+	/* Alas, we need more scratch registers for hugepages */
+	mfspr	r12, SPRN_SPRG_THREAD
+	stw	r14, THREAD_NORMSAVE(4)(r12)
+	stw	r15, THREAD_NORMSAVE(5)(r12)
+	stw	r16, THREAD_NORMSAVE(6)(r12)
+	stw	r17, THREAD_NORMSAVE(7)(r12)
+
+	/* Get the next_tlbcam_idx percpu var */
+#ifdef CONFIG_SMP
+	lwz	r12, THREAD_INFO-THREAD(r12)
+	lwz	r15, TI_CPU(r12)
+	lis     r14, __per_cpu_offset@h
+	ori     r14, r14, __per_cpu_offset@l
+	rlwinm  r15, r15, 2, 0, 29
+	lwzx    r16, r14, r15
+#else
+	li	r16, 0
+#endif
+	lis     r17, next_tlbcam_idx@h
+	ori	r17, r17, next_tlbcam_idx@l
+	add	r17, r17, r16			/* r17 = *next_tlbcam_idx */
+	lwz     r15, 0(r17)			/* r15 = next_tlbcam_idx */
+
+	lis	r14, MAS0_TLBSEL(1)@h		/* select TLB1 (TLBCAM) */
+	rlwimi	r14, r15, 16, 4, 15		/* next_tlbcam_idx entry */
+	mtspr	SPRN_MAS0, r14
+
+	/* Extract TLB1CFG(NENTRY) */
+	mfspr	r16, SPRN_TLB1CFG
+	andi.	r16, r16, 0xfff
+
+	/* Update next_tlbcam_idx, wrapping when necessary */
+	addi	r15, r15, 1
+	cmpw	r15, r16
+	blt 	100f
+	lis	r14, tlbcam_index@h
+	ori	r14, r14, tlbcam_index@l
+	lwz	r15, 0(r14)
+100:	stw	r15, 0(r17)
+
+	/*
+	 * Calc MAS1_TSIZE from r10 (which has pshift encoded)
+	 * tlb_enc = (pshift - 10).
+	 */
+	subi	r15, r10, 10
+	mfspr	r16, SPRN_MAS1
+	rlwimi	r16, r15, 7, 20, 24
+	mtspr	SPRN_MAS1, r16
+
+	/* copy the pshift for use later */
+	mr	r14, r10
+
+	/* fall through */
+
+#endif /* CONFIG_HUGETLB_PAGE */
+
 	/*
 	 * We set execute, because we don't have the granularity to
 	 * properly set this at the page level (Linux problem).
 	 * Many of these bits are software only.  Bits we don't set
 	 * here we (properly should) assume have the appropriate value.
 	 */
-
-	mfspr	r12, SPRN_MAS2
-#ifdef CONFIG_PTE_64BIT
-	rlwimi	r12, r11, 32-19, 27, 31	/* extract WIMGE from pte */
-#else
-	rlwimi	r12, r11, 26, 27, 31	/* extract WIMGE from pte */
-#endif
-	mtspr	SPRN_MAS2, r12
-
+finish_tlb_load_cont:
 #ifdef CONFIG_PTE_64BIT
 	rlwinm	r12, r11, 32-2, 26, 31	/* Move in perm bits */
 	andi.	r10, r11, _PAGE_DIRTY
@@ -581,22 +660,40 @@
 	andc	r12, r12, r10
 1:	rlwimi	r12, r13, 20, 0, 11	/* grab RPN[32:43] */
 	rlwimi	r12, r11, 20, 12, 19	/* grab RPN[44:51] */
-	mtspr	SPRN_MAS3, r12
+2:	mtspr	SPRN_MAS3, r12
 BEGIN_MMU_FTR_SECTION
 	srwi	r10, r13, 12		/* grab RPN[12:31] */
 	mtspr	SPRN_MAS7, r10
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)
 #else
 	li	r10, (_PAGE_EXEC | _PAGE_PRESENT)
+	mr	r13, r11
 	rlwimi	r10, r11, 31, 29, 29	/* extract _PAGE_DIRTY into SW */
 	and	r12, r11, r10
 	andi.	r10, r11, _PAGE_USER	/* Test for _PAGE_USER */
 	slwi	r10, r12, 1
 	or	r10, r10, r12
 	iseleq	r12, r12, r10
-	rlwimi	r11, r12, 0, 20, 31	/* Extract RPN from PTE and merge with perms */
-	mtspr	SPRN_MAS3, r11
+	rlwimi	r13, r12, 0, 20, 31	/* Get RPN from PTE, merge w/ perms */
+	mtspr	SPRN_MAS3, r13
 #endif
+
+	mfspr	r12, SPRN_MAS2
+#ifdef CONFIG_PTE_64BIT
+	rlwimi	r12, r11, 32-19, 27, 31	/* extract WIMGE from pte */
+#else
+	rlwimi	r12, r11, 26, 27, 31	/* extract WIMGE from pte */
+#endif
+#ifdef CONFIG_HUGETLB_PAGE
+	beq	6, 3f			/* don't mask if page isn't huge */
+	li	r13, 1
+	slw	r13, r13, r14
+	subi	r13, r13, 1
+	rlwinm	r13, r13, 0, 0, 19	/* bottom bits used for WIMGE/etc */
+	andc	r12, r12, r13		/* mask off ea bits within the page */
+#endif
+3:	mtspr	SPRN_MAS2, r12
+
 #ifdef CONFIG_E200
 	/* Round robin TLB1 entries assignment */
 	mfspr	r12, SPRN_MAS0
@@ -622,11 +719,19 @@
 	mtspr	SPRN_MAS0,r12
 #endif /* CONFIG_E200 */
 
+tlb_write_entry:
 	tlbwe
 
 	/* Done...restore registers and get out of here.  */
 	mfspr	r10, SPRN_SPRG_THREAD
-	lwz	r11, THREAD_NORMSAVE(3)(r10)
+#ifdef CONFIG_HUGETLB_PAGE
+	beq	6, 8f /* skip restore for 4k page faults */
+	lwz	r14, THREAD_NORMSAVE(4)(r10)
+	lwz	r15, THREAD_NORMSAVE(5)(r10)
+	lwz	r16, THREAD_NORMSAVE(6)(r10)
+	lwz	r17, THREAD_NORMSAVE(7)(r10)
+#endif
+8:	lwz	r11, THREAD_NORMSAVE(3)(r10)
 	mtcr	r11
 	lwz	r13, THREAD_NORMSAVE(2)(r10)
 	lwz	r12, THREAD_NORMSAVE(1)(r10)
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/hw_breakpoint.c linux-libre-3.2-gnu/arch/powerpc/kernel/hw_breakpoint.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/hw_breakpoint.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/hw_breakpoint.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,6 @@
 #include <linux/kprobes.h>
 #include <linux/percpu.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/smp.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/ibmebus.c linux-libre-3.2-gnu/arch/powerpc/kernel/ibmebus.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/ibmebus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/ibmebus.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,12 +37,14 @@
  */
 
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/console.h>
 #include <linux/kobject.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/of.h>
 #include <linux/slab.h>
+#include <linux/stat.h>
 #include <linux/of_platform.h>
 #include <asm/ibmebus.h>
 #include <asm/abs_addr.h>
@@ -125,17 +127,23 @@
 
 static int ibmebus_dma_supported(struct device *dev, u64 mask)
 {
-	return 1;
+	return mask == DMA_BIT_MASK(64);
+}
+
+static u64 ibmebus_dma_get_required_mask(struct device *dev)
+{
+	return DMA_BIT_MASK(64);
 }
 
 static struct dma_map_ops ibmebus_dma_ops = {
-	.alloc_coherent = ibmebus_alloc_coherent,
-	.free_coherent  = ibmebus_free_coherent,
-	.map_sg         = ibmebus_map_sg,
-	.unmap_sg       = ibmebus_unmap_sg,
-	.dma_supported  = ibmebus_dma_supported,
-	.map_page       = ibmebus_map_page,
-	.unmap_page     = ibmebus_unmap_page,
+	.alloc_coherent     = ibmebus_alloc_coherent,
+	.free_coherent      = ibmebus_free_coherent,
+	.map_sg             = ibmebus_map_sg,
+	.unmap_sg           = ibmebus_unmap_sg,
+	.dma_supported      = ibmebus_dma_supported,
+	.get_required_mask  = ibmebus_dma_get_required_mask,
+	.map_page           = ibmebus_map_page,
+	.unmap_page         = ibmebus_unmap_page,
 };
 
 static int ibmebus_match_path(struct device *dev, void *data)
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/idle_e500.S linux-libre-3.2-gnu/arch/powerpc/kernel/idle_e500.S
--- linux-libre-3.1-gnu/arch/powerpc/kernel/idle_e500.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/idle_e500.S	2012-01-04 18:55:44.000000000 -0500
@@ -26,7 +26,7 @@
 	ori	r4,r4,_TLF_NAPPING	/* so when we take an exception */
 	stw	r4,TI_LOCAL_FLAGS(r3)	/* it will return to our caller */
 
-#ifdef CONFIG_E500MC
+#ifdef CONFIG_PPC_E500MC
 	wrteei	1
 1:	wait
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/init_task.c linux-libre-3.2-gnu/arch/powerpc/kernel/init_task.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/init_task.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/init_task.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 #include <linux/mm.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/init_task.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/io.c linux-libre-3.2-gnu/arch/powerpc/kernel/io.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/io.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/compiler.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/io.h>
 #include <asm/firmware.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/iomap.c linux-libre-3.2-gnu/arch/powerpc/kernel/iomap.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/iomap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/iomap.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/mm.h>
+#include <linux/export.h>
 #include <asm/io.h>
 #include <asm/pci-bridge.h>
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/iommu.c linux-libre-3.2-gnu/arch/powerpc/kernel/iommu.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -501,6 +501,14 @@
 	tbl->it_map = page_address(page);
 	memset(tbl->it_map, 0, sz);
 
+	/*
+	 * Reserve page 0 so it will not be used for any mappings.
+	 * This avoids buggy drivers that consider page 0 to be invalid
+	 * to crash the machine or even lose data.
+	 */
+	if (tbl->it_offset == 0)
+		set_bit(0, tbl->it_map);
+
 	tbl->it_hint = 0;
 	tbl->it_largehint = tbl->it_halfpoint;
 	spin_lock_init(&tbl->it_lock);
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/io-workarounds.c linux-libre-3.2-gnu/arch/powerpc/kernel/io-workarounds.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/io-workarounds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/io-workarounds.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
+#include <linux/sched.h>	/* for init_mm */
 
 #include <asm/io.h>
 #include <asm/machdep.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/irq.c linux-libre-3.2-gnu/arch/powerpc/kernel/irq.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@
 
 #undef DEBUG
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/threads.h>
 #include <linux/kernel_stat.h>
 #include <linux/signal.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/isa-bridge.c linux-libre-3.2-gnu/arch/powerpc/kernel/isa-bridge.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/isa-bridge.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/isa-bridge.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/string.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/notifier.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/jump_label.c linux-libre-3.2-gnu/arch/powerpc/kernel/jump_label.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/jump_label.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/jump_label.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/jump_label.h>
 #include <asm/code-patching.h>
 
+#ifdef HAVE_JUMP_LABEL
 void arch_jump_label_transform(struct jump_entry *entry,
 			       enum jump_label_type type)
 {
@@ -21,3 +22,4 @@
 	else
 		patch_instruction(addr, PPC_INST_NOP);
 }
+#endif
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/kvm.c linux-libre-3.2-gnu/arch/powerpc/kernel/kvm.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/kvm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/kvm.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 
 #include <linux/kvm_host.h>
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/kvm_para.h>
 #include <linux/slab.h>
 #include <linux/of.h>
@@ -131,7 +132,6 @@
 	/* On relocatable kernels interrupts handlers and our code
 	   can be in different regions, so we don't patch them */
 
-	extern u32 __end_interrupts;
 	if ((ulong)inst < (ulong)&__end_interrupts)
 		return;
 #endif
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/legacy_serial.c linux-libre-3.2-gnu/arch/powerpc/kernel/legacy_serial.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/legacy_serial.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/legacy_serial.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
 #include <linux/pci.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/serial_reg.h>
 #include <asm/io.h>
 #include <asm/mmu.h>
 #include <asm/prom.h>
@@ -47,6 +48,24 @@
 static unsigned int legacy_serial_count;
 static int legacy_serial_console = -1;
 
+static unsigned int tsi_serial_in(struct uart_port *p, int offset)
+{
+	unsigned int tmp;
+	offset = offset << p->regshift;
+	if (offset == UART_IIR) {
+		tmp = readl(p->membase + (UART_IIR & ~3));
+		return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
+	} else
+		return readb(p->membase + offset);
+}
+
+static void tsi_serial_out(struct uart_port *p, int offset, int value)
+{
+	offset = offset << p->regshift;
+	if (!((offset == UART_IER) && (value & UART_IER_UUE)))
+		writeb(value, p->membase + offset);
+}
+
 static int __init add_legacy_port(struct device_node *np, int want_index,
 				  int iotype, phys_addr_t base,
 				  phys_addr_t taddr, unsigned long irq,
@@ -102,6 +121,7 @@
 		legacy_serial_ports[index].iobase = base;
 	else
 		legacy_serial_ports[index].mapbase = base;
+
 	legacy_serial_ports[index].iotype = iotype;
 	legacy_serial_ports[index].uartclk = clock;
 	legacy_serial_ports[index].irq = irq;
@@ -112,6 +132,11 @@
 	legacy_serial_infos[index].speed = spd ? be32_to_cpup(spd) : 0;
 	legacy_serial_infos[index].irq_check_parent = irq_check_parent;
 
+	if (iotype == UPIO_TSI) {
+		legacy_serial_ports[index].serial_in = tsi_serial_in;
+		legacy_serial_ports[index].serial_out = tsi_serial_out;
+	}
+
 	printk(KERN_DEBUG "Found legacy serial port %d for %s\n",
 	       index, np->full_name);
 	printk(KERN_DEBUG "  %s=%llx, taddr=%llx, irq=%lx, clk=%d, speed=%d\n",
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/machine_kexec_64.c linux-libre-3.2-gnu/arch/powerpc/kernel/machine_kexec_64.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/machine_kexec_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/machine_kexec_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,8 +74,7 @@
 	}
 
 	/* We also should not overwrite the tce tables */
-	for (node = of_find_node_by_type(NULL, "pci"); node != NULL;
-			node = of_find_node_by_type(node, "pci")) {
+	for_each_node_by_type(node, "pci") {
 		basep = of_get_property(node, "linux,tce-base", NULL);
 		sizep = of_get_property(node, "linux,tce-size", NULL);
 		if (basep == NULL || sizep == NULL)
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/misc_32.S linux-libre-3.2-gnu/arch/powerpc/kernel/misc_32.S
--- linux-libre-3.1-gnu/arch/powerpc/kernel/misc_32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/misc_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,8 @@
  * kexec bits:
  * Copyright (C) 2002-2003 Eric Biederman  <ebiederm@xmission.com>
  * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ * PPC44x port. Copyright (C) 2011,  IBM Corporation
+ * 		Author: Suzuki Poulose <suzuki@in.ibm.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -736,6 +738,175 @@
 	mr      r5, r31
 
 	li	r0, 0
+#elif defined(CONFIG_44x)  && !defined(CONFIG_PPC_47x)
+
+/*
+ * Code for setting up 1:1 mapping for PPC440x for KEXEC
+ *
+ * We cannot switch off the MMU on PPC44x.
+ * So we:
+ * 1) Invalidate all the mappings except the one we are running from.
+ * 2) Create a tmp mapping for our code in the other address space(TS) and
+ *    jump to it. Invalidate the entry we started in.
+ * 3) Create a 1:1 mapping for 0-2GiB in chunks of 256M in original TS.
+ * 4) Jump to the 1:1 mapping in original TS.
+ * 5) Invalidate the tmp mapping.
+ *
+ * - Based on the kexec support code for FSL BookE
+ * - Doesn't support 47x yet.
+ *
+ */
+	/* Save our parameters */
+	mr	r29, r3
+	mr	r30, r4
+	mr	r31, r5
+
+	/* Load our MSR_IS and TID to MMUCR for TLB search */
+	mfspr	r3,SPRN_PID
+	mfmsr	r4
+	andi.	r4,r4,MSR_IS@l
+	beq	wmmucr
+	oris	r3,r3,PPC44x_MMUCR_STS@h
+wmmucr:
+	mtspr	SPRN_MMUCR,r3
+	sync
+
+	/*
+	 * Invalidate all the TLB entries except the current entry
+	 * where we are running from
+	 */
+	bl	0f				/* Find our address */
+0:	mflr	r5				/* Make it accessible */
+	tlbsx	r23,0,r5			/* Find entry we are in */
+	li	r4,0				/* Start at TLB entry 0 */
+	li	r3,0				/* Set PAGEID inval value */
+1:	cmpw	r23,r4				/* Is this our entry? */
+	beq	skip				/* If so, skip the inval */
+	tlbwe	r3,r4,PPC44x_TLB_PAGEID		/* If not, inval the entry */
+skip:
+	addi	r4,r4,1				/* Increment */
+	cmpwi	r4,64				/* Are we done?	*/
+	bne	1b				/* If not, repeat */
+	isync
+
+	/* Create a temp mapping and jump to it */
+	andi.	r6, r23, 1		/* Find the index to use */
+	addi	r24, r6, 1		/* r24 will contain 1 or 2 */
+
+	mfmsr	r9			/* get the MSR */
+	rlwinm	r5, r9, 27, 31, 31	/* Extract the MSR[IS] */
+	xori	r7, r5, 1		/* Use the other address space */
+
+	/* Read the current mapping entries */
+	tlbre	r3, r23, PPC44x_TLB_PAGEID
+	tlbre	r4, r23, PPC44x_TLB_XLAT
+	tlbre	r5, r23, PPC44x_TLB_ATTRIB
+
+	/* Save our current XLAT entry */
+	mr	r25, r4
+
+	/* Extract the TLB PageSize */
+	li	r10, 1 			/* r10 will hold PageSize */
+	rlwinm	r11, r3, 0, 24, 27	/* bits 24-27 */
+
+	/* XXX: As of now we use 256M, 4K pages */
+	cmpwi	r11, PPC44x_TLB_256M
+	bne	tlb_4k
+	rotlwi	r10, r10, 28		/* r10 = 256M */
+	b	write_out
+tlb_4k:
+	cmpwi	r11, PPC44x_TLB_4K
+	bne	default
+	rotlwi	r10, r10, 12		/* r10 = 4K */
+	b	write_out
+default:
+	rotlwi	r10, r10, 10		/* r10 = 1K */
+
+write_out:
+	/*
+	 * Write out the tmp 1:1 mapping for this code in other address space
+	 * Fixup  EPN = RPN , TS=other address space
+	 */
+	insrwi	r3, r7, 1, 23		/* Bit 23 is TS for PAGEID field */
+
+	/* Write out the tmp mapping entries */
+	tlbwe	r3, r24, PPC44x_TLB_PAGEID
+	tlbwe	r4, r24, PPC44x_TLB_XLAT
+	tlbwe	r5, r24, PPC44x_TLB_ATTRIB
+
+	subi	r11, r10, 1		/* PageOffset Mask = PageSize - 1 */
+	not	r10, r11		/* Mask for PageNum */
+
+	/* Switch to other address space in MSR */
+	insrwi	r9, r7, 1, 26		/* Set MSR[IS] = r7 */
+
+	bl	1f
+1:	mflr	r8
+	addi	r8, r8, (2f-1b)		/* Find the target offset */
+
+	/* Jump to the tmp mapping */
+	mtspr	SPRN_SRR0, r8
+	mtspr	SPRN_SRR1, r9
+	rfi
+
+2:
+	/* Invalidate the entry we were executing from */
+	li	r3, 0
+	tlbwe	r3, r23, PPC44x_TLB_PAGEID
+
+	/* attribute fields. rwx for SUPERVISOR mode */
+	li	r5, 0
+	ori	r5, r5, (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
+
+	/* Create 1:1 mapping in 256M pages */
+	xori	r7, r7, 1			/* Revert back to Original TS */
+
+	li	r8, 0				/* PageNumber */
+	li	r6, 3				/* TLB Index, start at 3  */
+
+next_tlb:
+	rotlwi	r3, r8, 28			/* Create EPN (bits 0-3) */
+	mr	r4, r3				/* RPN = EPN  */
+	ori	r3, r3, (PPC44x_TLB_VALID | PPC44x_TLB_256M) /* SIZE = 256M, Valid */
+	insrwi	r3, r7, 1, 23			/* Set TS from r7 */
+
+	tlbwe	r3, r6, PPC44x_TLB_PAGEID	/* PageID field : EPN, V, SIZE */
+	tlbwe	r4, r6, PPC44x_TLB_XLAT		/* Address translation : RPN   */
+	tlbwe	r5, r6, PPC44x_TLB_ATTRIB	/* Attributes */
+
+	addi	r8, r8, 1			/* Increment PN */
+	addi	r6, r6, 1			/* Increment TLB Index */
+	cmpwi	r8, 8				/* Are we done ? */
+	bne	next_tlb
+	isync
+
+	/* Jump to the new mapping 1:1 */
+	li	r9,0
+	insrwi	r9, r7, 1, 26			/* Set MSR[IS] = r7 */
+
+	bl	1f
+1:	mflr	r8
+	and	r8, r8, r11			/* Get our offset within page */
+	addi	r8, r8, (2f-1b)
+
+	and	r5, r25, r10			/* Get our target PageNum */
+	or	r8, r8, r5			/* Target jump address */
+
+	mtspr	SPRN_SRR0, r8
+	mtspr	SPRN_SRR1, r9
+	rfi
+2:
+	/* Invalidate the tmp entry we used */
+	li	r3, 0
+	tlbwe	r3, r24, PPC44x_TLB_PAGEID
+	sync
+
+	/* Restore the parameters */
+	mr	r3, r29
+	mr	r4, r30
+	mr	r5, r31
+
+	li	r0, 0
 #else
 	li	r0, 0
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/module.c linux-libre-3.2-gnu/arch/powerpc/kernel/module.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/module.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/module.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,6 @@
     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/elf.h>
 #include <linux/moduleloader.h>
 #include <linux/err.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/of_platform.c linux-libre-3.2-gnu/arch/powerpc/kernel/of_platform.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/of_platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/of_platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/mod_devicetable.h>
 #include <linux/pci.h>
 #include <linux/of.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/paca.c linux-libre-3.2-gnu/arch/powerpc/kernel/paca.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/paca.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/paca.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  */
 
 #include <linux/smp.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/memblock.h>
 
 #include <asm/firmware.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/pci_32.c linux-libre-3.2-gnu/arch/powerpc/kernel/pci_32.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/pci_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/pci_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/list.h>
 #include <linux/of.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/pci_64.c linux-libre-3.2-gnu/arch/powerpc/kernel/pci_64.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/pci_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/pci_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/export.h>
 #include <linux/mm.h>
 #include <linux/list.h>
 #include <linux/syscalls.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/pci-common.c linux-libre-3.2-gnu/arch/powerpc/kernel/pci-common.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/pci-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/pci-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/export.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
 #include <linux/mm.h>
@@ -1730,6 +1731,17 @@
 
 	if (mode == PCI_PROBE_NORMAL)
 		hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
+
+	/* Configure PCI Express settings */
+	if (bus && !pci_has_flag(PCI_PROBE_ONLY)) {
+		struct pci_bus *child;
+		list_for_each_entry(child, &bus->children, node) {
+			struct pci_dev *self = child->self;
+			if (!self)
+				continue;
+			pcie_bus_configure_settings(child, self->pcie_mpss);
+		}
+	}
 }
 
 static void fixup_hide_host_resource_fsl(struct pci_dev *dev)
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/pci_dn.c linux-libre-3.2-gnu/arch/powerpc/kernel/pci_dn.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/pci_dn.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/pci_dn.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/string.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/gfp.h>
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/pci_of_scan.c linux-libre-3.2-gnu/arch/powerpc/kernel/pci_of_scan.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/pci_of_scan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/pci_of_scan.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
  */
 
 #include <linux/pci.h>
+#include <linux/export.h>
 #include <asm/pci-bridge.h>
 #include <asm/prom.h>
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/pmc.c linux-libre-3.2-gnu/arch/powerpc/kernel/pmc.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/pmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/pmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 
 #include <linux/errno.h>
 #include <linux/spinlock.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/processor.h>
 #include <asm/cputable.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/power6-pmu.c linux-libre-3.2-gnu/arch/powerpc/kernel/power6-pmu.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/power6-pmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/power6-pmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -487,8 +487,8 @@
  */
 static int power6_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
 	[C(L1D)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
-		[C(OP_READ)] = {	0x80082,	0x80080		},
-		[C(OP_WRITE)] = {	0x80086,	0x80088		},
+		[C(OP_READ)] = {	0x280030,	0x80080		},
+		[C(OP_WRITE)] = {	0x180032,	0x80088		},
 		[C(OP_PREFETCH)] = {	0x810a4,	0		},
 	},
 	[C(L1I)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/power7-pmu.c linux-libre-3.2-gnu/arch/powerpc/kernel/power7-pmu.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/power7-pmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/power7-pmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -297,6 +297,8 @@
 
 static int power7_generic_events[] = {
 	[PERF_COUNT_HW_CPU_CYCLES] = 0x1e,
+	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x100f8, /* GCT_NOSLOT_CYC */
+	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x4000a,  /* CMPLU_STALL */
 	[PERF_COUNT_HW_INSTRUCTIONS] = 2,
 	[PERF_COUNT_HW_CACHE_REFERENCES] = 0xc880,	/* LD_REF_L1_LSU*/
 	[PERF_COUNT_HW_CACHE_MISSES] = 0x400f0,		/* LD_MISS_L1	*/
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/ppc_ksyms.c linux-libre-3.2-gnu/arch/powerpc/kernel/ppc_ksyms.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/ppc_ksyms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/ppc_ksyms.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/threads.h>
 #include <linux/smp.h>
 #include <linux/sched.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/process.c linux-libre-3.2-gnu/arch/powerpc/kernel/process.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/init.h>
 #include <linux/prctl.h>
 #include <linux/init_task.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kallsyms.h>
 #include <linux/mqueue.h>
 #include <linux/hardirq.h>
@@ -486,28 +486,6 @@
 	new_thread = &new->thread;
 	old_thread = &current->thread;
 
-#if defined(CONFIG_PPC_BOOK3E_64)
-	/* XXX Current Book3E code doesn't deal with kernel side DBCR0,
-	 * we always hold the user values, so we set it now.
-	 *
-	 * However, we ensure the kernel MSR:DE is appropriately cleared too
-	 * to avoid spurrious single step exceptions in the kernel.
-	 *
-	 * This will have to change to merge with the ppc32 code at some point,
-	 * but I don't like much what ppc32 is doing today so there's some
-	 * thinking needed there
-	 */
-	if ((new_thread->dbcr0 | old_thread->dbcr0) & DBCR0_IDM) {
-		u32 dbcr0;
-
-		mtmsr(mfmsr() & ~MSR_DE);
-		isync();
-		dbcr0 = mfspr(SPRN_DBCR0);
-		dbcr0 = (dbcr0 & DBCR0_EDM) | new_thread->dbcr0;
-		mtspr(SPRN_DBCR0, dbcr0);
-	}
-#endif /* CONFIG_PPC64_BOOK3E */
-
 #ifdef CONFIG_PPC64
 	/*
 	 * Collect processor utilization data per process
@@ -657,7 +635,7 @@
 	if ((regs->trap != 0xc00) && cpu_has_feature(CPU_FTR_CFAR))
 		printk("CFAR: "REG"\n", regs->orig_gpr3);
 	if (trap == 0x300 || trap == 0x600)
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
 		printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr);
 #else
 		printk("DAR: "REG", DSISR: %08lx\n", regs->dar, regs->dsisr);
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/prom.c linux-libre-3.2-gnu/arch/powerpc/kernel/prom.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/prom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/prom.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,7 @@
 #include <linux/delay.h>
 #include <linux/initrd.h>
 #include <linux/bitops.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kexec.h>
 #include <linux/debugfs.h>
 #include <linux/irq.h>
@@ -54,6 +54,8 @@
 #include <asm/pci-bridge.h>
 #include <asm/phyp_dump.h>
 #include <asm/kexec.h>
+#include <asm/opal.h>
+
 #include <mm/mmu_decl.h>
 
 #ifdef DEBUG
@@ -707,11 +709,23 @@
 	of_scan_flat_dt(early_init_dt_scan_rtas, NULL);
 #endif
 
+#ifdef CONFIG_PPC_POWERNV
+	/* Some machines might need OPAL info for debugging, grab it now. */
+	of_scan_flat_dt(early_init_dt_scan_opal, NULL);
+#endif
+
 #ifdef CONFIG_PHYP_DUMP
 	/* scan tree to see if dump occurred during last boot */
 	of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
 #endif
 
+	/* Pre-initialize the cmd_line with the content of boot_commmand_line,
+	 * which will be empty except when the content of the variable has
+	 * been overriden by a bootloading mechanism. This happens typically
+	 * with HAL takeover
+	 */
+	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
+
 	/* Retrieve various informations from the /chosen node of the
 	 * device-tree, including the platform type, initrd location and
 	 * size, TCE reserve, and more ...
@@ -723,12 +737,15 @@
 
 	of_scan_flat_dt(early_init_dt_scan_root, NULL);
 	of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
-	setup_initial_memory_limit(memstart_addr, first_memblock_size);
 
 	/* Save command line for /proc/cmdline and then parse parameters */
 	strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
 	parse_early_param();
 
+	/* make sure we've parsed cmdline for mem= before this */
+	if (memory_limit)
+		first_memblock_size = min(first_memblock_size, memory_limit);
+	setup_initial_memory_limit(memstart_addr, first_memblock_size);
 	/* Reserve MEMBLOCK regions used by kernel, initrd, dt, etc... */
 	memblock_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
 	/* If relocatable, reserve first 32k for interrupt vectors etc. */
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/prom_init.c linux-libre-3.2-gnu/arch/powerpc/kernel/prom_init.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/prom_init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/prom_init.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@
 #include <asm/btext.h>
 #include <asm/sections.h>
 #include <asm/machdep.h>
+#include <asm/opal.h>
 
 #include <linux/linux_logo.h>
 
@@ -139,7 +140,9 @@
 
 typedef u32 cell_t;
 
-extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
+extern void __start(unsigned long r3, unsigned long r4, unsigned long r5,
+		    unsigned long r6, unsigned long r7, unsigned long r8,
+		    unsigned long r9);
 
 #ifdef CONFIG_PPC64
 extern int enter_prom(struct prom_args *args, unsigned long entry);
@@ -185,6 +188,7 @@
 #define PLATFORM_LPAR		0x0001
 #define PLATFORM_POWERMAC	0x0400
 #define PLATFORM_GENERIC	0x0500
+#define PLATFORM_OPAL		0x0600
 
 static int __initdata of_platform;
 
@@ -644,7 +648,7 @@
 	}
 }
 
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 /*
  * There are two methods for telling firmware what our capabilities are.
  * Newer machines have an "ibm,client-architecture-support" method on the
@@ -1274,6 +1278,284 @@
 	prom_printf("  ram_top      : %x\n", RELOC(ram_top));
 }
 
+static void __init prom_close_stdin(void)
+{
+	struct prom_t *_prom = &RELOC(prom);
+	ihandle val;
+
+	if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0)
+		call_prom("close", 1, 0, val);
+}
+
+#ifdef CONFIG_PPC_POWERNV
+
+static u64 __initdata prom_opal_size;
+static u64 __initdata prom_opal_align;
+static int __initdata prom_rtas_start_cpu;
+static u64 __initdata prom_rtas_data;
+static u64 __initdata prom_rtas_entry;
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+static u64 __initdata prom_opal_base;
+static u64 __initdata prom_opal_entry;
+#endif
+
+/* XXX Don't change this structure without updating opal-takeover.S */
+static struct opal_secondary_data {
+	s64				ack;	/*  0 */
+	u64				go;	/*  8 */
+	struct opal_takeover_args	args;	/* 16 */
+} opal_secondary_data;
+
+extern char opal_secondary_entry;
+
+static void prom_query_opal(void)
+{
+	long rc;
+
+	/* We must not query for OPAL presence on a machine that
+	 * supports TNK takeover (970 blades), as this uses the same
+	 * h-call with different arguments and will crash
+	 */
+	if (PHANDLE_VALID(call_prom("finddevice", 1, 1,
+				    ADDR("/tnk-memory-map")))) {
+		prom_printf("TNK takeover detected, skipping OPAL check\n");
+		return;
+	}
+
+	prom_printf("Querying for OPAL presence... ");
+	rc = opal_query_takeover(&RELOC(prom_opal_size),
+				 &RELOC(prom_opal_align));
+	prom_debug("(rc = %ld) ", rc);
+	if (rc != 0) {
+		prom_printf("not there.\n");
+		return;
+	}
+	RELOC(of_platform) = PLATFORM_OPAL;
+	prom_printf(" there !\n");
+	prom_debug("  opal_size  = 0x%lx\n", RELOC(prom_opal_size));
+	prom_debug("  opal_align = 0x%lx\n", RELOC(prom_opal_align));
+	if (RELOC(prom_opal_align) < 0x10000)
+		RELOC(prom_opal_align) = 0x10000;
+}
+
+static int prom_rtas_call(int token, int nargs, int nret, int *outputs, ...)
+{
+	struct rtas_args rtas_args;
+	va_list list;
+	int i;
+
+	rtas_args.token = token;
+	rtas_args.nargs = nargs;
+	rtas_args.nret  = nret;
+	rtas_args.rets  = (rtas_arg_t *)&(rtas_args.args[nargs]);
+	va_start(list, outputs);
+	for (i = 0; i < nargs; ++i)
+		rtas_args.args[i] = va_arg(list, rtas_arg_t);
+	va_end(list);
+
+	for (i = 0; i < nret; ++i)
+		rtas_args.rets[i] = 0;
+
+	opal_enter_rtas(&rtas_args, RELOC(prom_rtas_data),
+			RELOC(prom_rtas_entry));
+
+	if (nret > 1 && outputs != NULL)
+		for (i = 0; i < nret-1; ++i)
+			outputs[i] = rtas_args.rets[i+1];
+	return (nret > 0)? rtas_args.rets[0]: 0;
+}
+
+static void __init prom_opal_hold_cpus(void)
+{
+	int i, cnt, cpu, rc;
+	long j;
+	phandle node;
+	char type[64];
+	u32 servers[8];
+	struct prom_t *_prom = &RELOC(prom);
+	void *entry = (unsigned long *)&RELOC(opal_secondary_entry);
+	struct opal_secondary_data *data = &RELOC(opal_secondary_data);
+
+	prom_debug("prom_opal_hold_cpus: start...\n");
+	prom_debug("    - entry       = 0x%x\n", entry);
+	prom_debug("    - data        = 0x%x\n", data);
+
+	data->ack = -1;
+	data->go = 0;
+
+	/* look for cpus */
+	for (node = 0; prom_next_node(&node); ) {
+		type[0] = 0;
+		prom_getprop(node, "device_type", type, sizeof(type));
+		if (strcmp(type, RELOC("cpu")) != 0)
+			continue;
+
+		/* Skip non-configured cpus. */
+		if (prom_getprop(node, "status", type, sizeof(type)) > 0)
+			if (strcmp(type, RELOC("okay")) != 0)
+				continue;
+
+		cnt = prom_getprop(node, "ibm,ppc-interrupt-server#s", servers,
+			     sizeof(servers));
+		if (cnt == PROM_ERROR)
+			break;
+		cnt >>= 2;
+		for (i = 0; i < cnt; i++) {
+			cpu = servers[i];
+			prom_debug("CPU %d ... ", cpu);
+			if (cpu == _prom->cpu) {
+				prom_debug("booted !\n");
+				continue;
+			}
+			prom_debug("starting ... ");
+
+			/* Init the acknowledge var which will be reset by
+			 * the secondary cpu when it awakens from its OF
+			 * spinloop.
+			 */
+			data->ack = -1;
+			rc = prom_rtas_call(RELOC(prom_rtas_start_cpu), 3, 1,
+					    NULL, cpu, entry, data);
+			prom_debug("rtas rc=%d ...", rc);
+
+			for (j = 0; j < 100000000 && data->ack == -1; j++) {
+				HMT_low();
+				mb();
+			}
+			HMT_medium();
+			if (data->ack != -1)
+				prom_debug("done, PIR=0x%x\n", data->ack);
+			else
+				prom_debug("timeout !\n");
+		}
+	}
+	prom_debug("prom_opal_hold_cpus: end...\n");
+}
+
+static void prom_opal_takeover(void)
+{
+	struct opal_secondary_data *data = &RELOC(opal_secondary_data);
+	struct opal_takeover_args *args = &data->args;
+	u64 align = RELOC(prom_opal_align);
+	u64 top_addr, opal_addr;
+
+	args->k_image	= (u64)RELOC(_stext);
+	args->k_size	= _end - _stext;
+	args->k_entry	= 0;
+	args->k_entry2	= 0x60;
+
+	top_addr = _ALIGN_UP(args->k_size, align);
+
+	if (RELOC(prom_initrd_start) != 0) {
+		args->rd_image = RELOC(prom_initrd_start);
+		args->rd_size = RELOC(prom_initrd_end) - args->rd_image;
+		args->rd_loc = top_addr;
+		top_addr = _ALIGN_UP(args->rd_loc + args->rd_size, align);
+	}
+
+	/* Pickup an address for the HAL. We want to go really high
+	 * up to avoid problem with future kexecs. On the other hand
+	 * we don't want to be all over the TCEs on P5IOC2 machines
+	 * which are going to be up there too. We assume the machine
+	 * has plenty of memory, and we ask for the HAL for now to
+	 * be just below the 1G point, or above the initrd
+	 */
+	opal_addr = _ALIGN_DOWN(0x40000000 - RELOC(prom_opal_size), align);
+	if (opal_addr < top_addr)
+		opal_addr = top_addr;
+	args->hal_addr = opal_addr;
+
+	/* Copy the command line to the kernel image */
+	strlcpy(RELOC(boot_command_line), RELOC(prom_cmd_line),
+		COMMAND_LINE_SIZE);
+
+	prom_debug("  k_image    = 0x%lx\n", args->k_image);
+	prom_debug("  k_size     = 0x%lx\n", args->k_size);
+	prom_debug("  k_entry    = 0x%lx\n", args->k_entry);
+	prom_debug("  k_entry2   = 0x%lx\n", args->k_entry2);
+	prom_debug("  hal_addr   = 0x%lx\n", args->hal_addr);
+	prom_debug("  rd_image   = 0x%lx\n", args->rd_image);
+	prom_debug("  rd_size    = 0x%lx\n", args->rd_size);
+	prom_debug("  rd_loc     = 0x%lx\n", args->rd_loc);
+	prom_printf("Performing OPAL takeover,this can take a few minutes..\n");
+	prom_close_stdin();
+	mb();
+	data->go = 1;
+	for (;;)
+		opal_do_takeover(args);
+}
+
+/*
+ * Allocate room for and instantiate OPAL
+ */
+static void __init prom_instantiate_opal(void)
+{
+	phandle opal_node;
+	ihandle opal_inst;
+	u64 base, entry;
+	u64 size = 0, align = 0x10000;
+	u32 rets[2];
+
+	prom_debug("prom_instantiate_opal: start...\n");
+
+	opal_node = call_prom("finddevice", 1, 1, ADDR("/ibm,opal"));
+	prom_debug("opal_node: %x\n", opal_node);
+	if (!PHANDLE_VALID(opal_node))
+		return;
+
+	prom_getprop(opal_node, "opal-runtime-size", &size, sizeof(size));
+	if (size == 0)
+		return;
+	prom_getprop(opal_node, "opal-runtime-alignment", &align,
+		     sizeof(align));
+
+	base = alloc_down(size, align, 0);
+	if (base == 0) {
+		prom_printf("OPAL allocation failed !\n");
+		return;
+	}
+
+	opal_inst = call_prom("open", 1, 1, ADDR("/ibm,opal"));
+	if (!IHANDLE_VALID(opal_inst)) {
+		prom_printf("opening opal package failed (%x)\n", opal_inst);
+		return;
+	}
+
+	prom_printf("instantiating opal at 0x%x...", base);
+
+	if (call_prom_ret("call-method", 4, 3, rets,
+			  ADDR("load-opal-runtime"),
+			  opal_inst,
+			  base >> 32, base & 0xffffffff) != 0
+	    || (rets[0] == 0 && rets[1] == 0)) {
+		prom_printf(" failed\n");
+		return;
+	}
+	entry = (((u64)rets[0]) << 32) | rets[1];
+
+	prom_printf(" done\n");
+
+	reserve_mem(base, size);
+
+	prom_debug("opal base     = 0x%x\n", base);
+	prom_debug("opal align    = 0x%x\n", align);
+	prom_debug("opal entry    = 0x%x\n", entry);
+	prom_debug("opal size     = 0x%x\n", (long)size);
+
+	prom_setprop(opal_node, "/ibm,opal", "opal-base-address",
+		     &base, sizeof(base));
+	prom_setprop(opal_node, "/ibm,opal", "opal-entry-address",
+		     &entry, sizeof(entry));
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+	RELOC(prom_opal_base) = base;
+	RELOC(prom_opal_entry) = entry;
+#endif
+	prom_debug("prom_instantiate_opal: end...\n");
+}
+
+#endif /* CONFIG_PPC_POWERNV */
 
 /*
  * Allocate room for and instantiate RTAS
@@ -1297,10 +1579,8 @@
 		return;
 
 	base = alloc_down(size, PAGE_SIZE, 0);
-	if (base == 0) {
-		prom_printf("RTAS allocation failed !\n");
-		return;
-	}
+	if (base == 0)
+		prom_panic("Could not allocate memory for RTAS\n");
 
 	rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
 	if (!IHANDLE_VALID(rtas_inst)) {
@@ -1326,6 +1606,12 @@
 	prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
 		     &entry, sizeof(entry));
 
+#ifdef CONFIG_PPC_POWERNV
+	/* PowerVN takeover hack */
+	RELOC(prom_rtas_data) = base;
+	RELOC(prom_rtas_entry) = entry;
+	prom_getprop(rtas_node, "start-cpu", &RELOC(prom_rtas_start_cpu), 4);
+#endif
 	prom_debug("rtas base     = 0x%x\n", base);
 	prom_debug("rtas entry    = 0x%x\n", entry);
 	prom_debug("rtas size     = 0x%x\n", (long)size);
@@ -1543,7 +1829,7 @@
 		*acknowledge = (unsigned long)-1;
 
 		if (reg != _prom->cpu) {
-			/* Primary Thread of non-boot cpu */
+			/* Primary Thread of non-boot cpu or any thread */
 			prom_printf("starting cpu hw idx %lu... ", reg);
 			call_prom("start-cpu", 3, 0, node,
 				  secondary_hold, reg);
@@ -1652,15 +1938,6 @@
 		prom_setprop(val, path, "linux,boot-display", NULL, 0);
 }
 
-static void __init prom_close_stdin(void)
-{
-	struct prom_t *_prom = &RELOC(prom);
-	ihandle val;
-
-	if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0)
-		call_prom("close", 1, 0, val);
-}
-
 static int __init prom_find_machine_type(void)
 {
 	struct prom_t *_prom = &RELOC(prom);
@@ -1671,7 +1948,7 @@
 	int x;
 #endif
 
-	/* Look for a PowerMac */
+	/* Look for a PowerMac or a Cell */
 	len = prom_getprop(_prom->root, "compatible",
 			   compat, sizeof(compat)-1);
 	if (len > 0) {
@@ -1697,7 +1974,11 @@
 		}
 	}
 #ifdef CONFIG_PPC64
-	/* If not a mac, try to figure out if it's an IBM pSeries or any other
+	/* Try to detect OPAL */
+	if (PHANDLE_VALID(call_prom("finddevice", 1, 1, ADDR("/ibm,opal"))))
+		return PLATFORM_OPAL;
+
+	/* Try to figure out if it's an IBM pSeries or any other
 	 * PAPR compliant platform. We assume it is if :
 	 *  - /device_type is "chrp" (please, do NOT use that for future
 	 *    non-IBM designs !
@@ -1924,7 +2205,7 @@
 	unsigned long soff;
 	unsigned char *valp;
 	static char pname[MAX_PROPERTY_NAME];
-	int l, room;
+	int l, room, has_phandle = 0;
 
 	dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
 
@@ -2008,19 +2289,26 @@
 		valp = make_room(mem_start, mem_end, l, 4);
 		call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);
 		*mem_start = _ALIGN(*mem_start, 4);
+
+		if (!strcmp(RELOC(pname), RELOC("phandle")))
+			has_phandle = 1;
 	}
 
-	/* Add a "linux,phandle" property. */
-	soff = dt_find_string(RELOC("linux,phandle"));
-	if (soff == 0)
-		prom_printf("WARNING: Can't find string index for"
-			    " <linux-phandle> node %s\n", path);
-	else {
-		dt_push_token(OF_DT_PROP, mem_start, mem_end);
-		dt_push_token(4, mem_start, mem_end);
-		dt_push_token(soff, mem_start, mem_end);
-		valp = make_room(mem_start, mem_end, 4, 4);
-		*(u32 *)valp = node;
+	/* Add a "linux,phandle" property if no "phandle" property already
+	 * existed (can happen with OPAL)
+	 */
+	if (!has_phandle) {
+		soff = dt_find_string(RELOC("linux,phandle"));
+		if (soff == 0)
+			prom_printf("WARNING: Can't find string index for"
+				    " <linux-phandle> node %s\n", path);
+		else {
+			dt_push_token(OF_DT_PROP, mem_start, mem_end);
+			dt_push_token(4, mem_start, mem_end);
+			dt_push_token(soff, mem_start, mem_end);
+			valp = make_room(mem_start, mem_end, 4, 4);
+			*(u32 *)valp = node;
+		}
 	}
 
 	/* do all our children */
@@ -2504,6 +2792,7 @@
 #endif /* CONFIG_BLK_DEV_INITRD */
 }
 
+
 /*
  * We enter here early on, when the Open Firmware prom is still
  * handling exceptions and the MMU hash table for us.
@@ -2553,6 +2842,7 @@
 	 * between pSeries SMP and pSeries LPAR
 	 */
 	RELOC(of_platform) = prom_find_machine_type();
+	prom_printf("Detected machine type: %x\n", RELOC(of_platform));
 
 #ifndef CONFIG_RELOCATABLE
 	/* Bail if this is a kdump kernel. */
@@ -2565,7 +2855,7 @@
 	 */
 	prom_check_initrd(r3, r4);
 
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 	/*
 	 * On pSeries, inform the firmware about our capabilities
 	 */
@@ -2611,14 +2901,33 @@
 #endif
 
 	/*
-	 * On non-powermacs, try to instantiate RTAS and puts all CPUs
-	 * in spin-loops. PowerMacs don't have a working RTAS and use
-	 * a different way to spin CPUs
+	 * On non-powermacs, try to instantiate RTAS. PowerMacs don't
+	 * have a usable RTAS implementation.
 	 */
-	if (RELOC(of_platform) != PLATFORM_POWERMAC) {
+	if (RELOC(of_platform) != PLATFORM_POWERMAC &&
+	    RELOC(of_platform) != PLATFORM_OPAL)
 		prom_instantiate_rtas();
+
+#ifdef CONFIG_PPC_POWERNV
+	/* Detect HAL and try instanciating it & doing takeover */
+	if (RELOC(of_platform) == PLATFORM_PSERIES_LPAR) {
+		prom_query_opal();
+		if (RELOC(of_platform) == PLATFORM_OPAL) {
+			prom_opal_hold_cpus();
+			prom_opal_takeover();
+		}
+	} else if (RELOC(of_platform) == PLATFORM_OPAL)
+		prom_instantiate_opal();
+#endif
+
+	/*
+	 * On non-powermacs, put all CPUs in spin-loops.
+	 *
+	 * PowerMacs use a different mechanism to spin CPUs
+	 */
+	if (RELOC(of_platform) != PLATFORM_POWERMAC &&
+	    RELOC(of_platform) != PLATFORM_OPAL)
 		prom_hold_cpus();
-	}
 
 	/*
 	 * Fill in some infos for use by the kernel later on
@@ -2685,7 +2994,13 @@
 	reloc_got2(-offset);
 #endif
 
-	__start(hdr, kbase, 0);
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+	/* OPAL early debug gets the OPAL base & entry in r8 and r9 */
+	__start(hdr, kbase, 0, 0, 0,
+		RELOC(prom_opal_base), RELOC(prom_opal_entry));
+#else
+	__start(hdr, kbase, 0, 0, 0, 0, 0);
+#endif
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/prom_init_check.sh linux-libre-3.2-gnu/arch/powerpc/kernel/prom_init_check.sh
--- linux-libre-3.1-gnu/arch/powerpc/kernel/prom_init_check.sh	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/prom_init_check.sh	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,9 @@
 _end enter_prom memcpy memset reloc_offset __secondary_hold
 __secondary_hold_acknowledge __secondary_hold_spinloop __start
 strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224
-reloc_got2 kernstart_addr memstart_addr linux_banner"
+reloc_got2 kernstart_addr memstart_addr linux_banner _stext
+opal_query_takeover opal_do_takeover opal_enter_rtas opal_secondary_entry
+boot_command_line"
 
 NM="$1"
 OBJ="$2"
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/prom_parse.c linux-libre-3.2-gnu/arch/powerpc/kernel/prom_parse.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/prom_parse.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/prom_parse.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,6 @@
 
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/etherdevice.h>
 #include <linux/of_address.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/ptrace.c linux-libre-3.2-gnu/arch/powerpc/kernel/ptrace.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/ptrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/ptrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,9 +30,6 @@
 #include <linux/seccomp.h>
 #include <linux/audit.h>
 #include <trace/syscall.h>
-#ifdef CONFIG_PPC32
-#include <linux/module.h>
-#endif
 #include <linux/hw_breakpoint.h>
 #include <linux/perf_event.h>
 
@@ -1497,9 +1494,14 @@
 		if (index < PT_FPR0) {
 			tmp = ptrace_get_reg(child, (int) index);
 		} else {
+			unsigned int fpidx = index - PT_FPR0;
+
 			flush_fp_to_thread(child);
-			tmp = ((unsigned long *)child->thread.fpr)
-				[TS_FPRWIDTH * (index - PT_FPR0)];
+			if (fpidx < (PT_FPSCR - PT_FPR0))
+				tmp = ((unsigned long *)child->thread.fpr)
+					[fpidx * TS_FPRWIDTH];
+			else
+				tmp = child->thread.fpscr.val;
 		}
 		ret = put_user(tmp, datalp);
 		break;
@@ -1525,9 +1527,14 @@
 		if (index < PT_FPR0) {
 			ret = ptrace_put_reg(child, index, data);
 		} else {
+			unsigned int fpidx = index - PT_FPR0;
+
 			flush_fp_to_thread(child);
-			((unsigned long *)child->thread.fpr)
-				[TS_FPRWIDTH * (index - PT_FPR0)] = data;
+			if (fpidx < (PT_FPSCR - PT_FPR0))
+				((unsigned long *)child->thread.fpr)
+					[fpidx * TS_FPRWIDTH] = data;
+			else
+				child->thread.fpscr.val = data;
 			ret = 0;
 		}
 		break;
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/rtas.c linux-libre-3.2-gnu/arch/powerpc/kernel/rtas.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/rtas.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/rtas.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/capability.h>
 #include <linux/delay.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/setup_32.c linux-libre-3.2-gnu/arch/powerpc/kernel/setup_32.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/setup_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/setup_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -107,6 +107,8 @@
 			 PTRRELOC(&__start___lwsync_fixup),
 			 PTRRELOC(&__stop___lwsync_fixup));
 
+	do_final_fixups();
+
 	return KERNELBASE + offset;
 }
 
@@ -117,7 +119,7 @@
  * This is called very early on the boot process, after a minimal
  * MMU environment has been set up but before MMU_init is called.
  */
-notrace void __init machine_init(unsigned long dt_ptr)
+notrace void __init machine_init(u64 dt_ptr)
 {
 	lockdep_init();
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/setup_64.c linux-libre-3.2-gnu/arch/powerpc/kernel/setup_64.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/setup_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/setup_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
 
 #undef DEBUG
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/init.h>
@@ -278,14 +278,14 @@
 
 	DBG(" -> initialize_cache_info()\n");
 
-	for (np = NULL; (np = of_find_node_by_type(np, "cpu"));) {
+	for_each_node_by_type(np, "cpu") {
 		num_cpus += 1;
 
-		/* We're assuming *all* of the CPUs have the same
+		/*
+		 * We're assuming *all* of the CPUs have the same
 		 * d-cache and i-cache sizes... -Peter
 		 */
-
-		if ( num_cpus == 1 ) {
+		if (num_cpus == 1) {
 			const u32 *sizep, *lsizep;
 			u32 size, lsize;
 
@@ -294,10 +294,13 @@
 			sizep = of_get_property(np, "d-cache-size", NULL);
 			if (sizep != NULL)
 				size = *sizep;
-			lsizep = of_get_property(np, "d-cache-block-size", NULL);
+			lsizep = of_get_property(np, "d-cache-block-size",
+						 NULL);
 			/* fallback if block size missing */
 			if (lsizep == NULL)
-				lsizep = of_get_property(np, "d-cache-line-size", NULL);
+				lsizep = of_get_property(np,
+							 "d-cache-line-size",
+							 NULL);
 			if (lsizep != NULL)
 				lsize = *lsizep;
 			if (sizep == 0 || lsizep == 0)
@@ -314,9 +317,12 @@
 			sizep = of_get_property(np, "i-cache-size", NULL);
 			if (sizep != NULL)
 				size = *sizep;
-			lsizep = of_get_property(np, "i-cache-block-size", NULL);
+			lsizep = of_get_property(np, "i-cache-block-size",
+						 NULL);
 			if (lsizep == NULL)
-				lsizep = of_get_property(np, "i-cache-line-size", NULL);
+				lsizep = of_get_property(np,
+							 "i-cache-line-size",
+							 NULL);
 			if (lsizep != NULL)
 				lsize = *lsizep;
 			if (sizep == 0 || lsizep == 0)
@@ -353,6 +359,7 @@
 			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
 	do_lwsync_fixups(cur_cpu_spec->cpu_features,
 			 &__start___lwsync_fixup, &__stop___lwsync_fixup);
+	do_final_fixups();
 
 	/*
 	 * Unflatten the device-tree passed by prom_init or kexec
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/setup-common.c linux-libre-3.2-gnu/arch/powerpc/kernel/setup-common.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/setup-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/setup-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
 
 #undef DEBUG
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/init.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/signal_32.c linux-libre-3.2-gnu/arch/powerpc/kernel/signal_32.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/signal_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/signal_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -97,7 +97,7 @@
 	compat_sigset_t	cset;
 
 	switch (_NSIG_WORDS) {
-	case 4: cset.sig[5] = set->sig[3] & 0xffffffffull;
+	case 4: cset.sig[6] = set->sig[3] & 0xffffffffull;
 		cset.sig[7] = set->sig[3] >> 32;
 	case 3: cset.sig[4] = set->sig[2] & 0xffffffffull;
 		cset.sig[5] = set->sig[2] >> 32;
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/signal_64.c linux-libre-3.2-gnu/arch/powerpc/kernel/signal_64.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/signal_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/signal_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,6 @@
 #include <linux/stddef.h>
 #include <linux/elf.h>
 #include <linux/ptrace.h>
-#include <linux/module.h>
 #include <linux/ratelimit.h>
 
 #include <asm/sigcontext.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/smp.c linux-libre-3.2-gnu/arch/powerpc/kernel/smp.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
@@ -70,6 +70,10 @@
 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))
+
+/* State of each CPU during hotplug phases */
+static DEFINE_PER_CPU(int, cpu_state) = { 0 };
+
 #else
 static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
 #define get_idle_for_cpu(x)      (idle_thread_array[(x)])
@@ -104,12 +108,25 @@
 	 * cpu_start field to become non-zero After we set cpu_start,
 	 * the processor will continue on to secondary_start
 	 */
-	paca[nr].cpu_start = 1;
-	smp_mb();
+	if (!paca[nr].cpu_start) {
+		paca[nr].cpu_start = 1;
+		smp_mb();
+		return 0;
+	}
+
+#ifdef CONFIG_HOTPLUG_CPU
+	/*
+	 * Ok it's not there, so it might be soft-unplugged, let's
+	 * try to bring it back
+	 */
+	per_cpu(cpu_state, nr) = CPU_UP_PREPARE;
+	smp_wmb();
+	smp_send_reschedule(nr);
+#endif /* CONFIG_HOTPLUG_CPU */
 
 	return 0;
 }
-#endif
+#endif /* CONFIG_PPC64 */
 
 static irqreturn_t call_function_action(int irq, void *data)
 {
@@ -170,7 +187,7 @@
 		return 1;
 	}
 #endif
-	err = request_irq(virq, smp_ipi_action[msg], IRQF_DISABLED|IRQF_PERCPU,
+	err = request_irq(virq, smp_ipi_action[msg], IRQF_PERCPU,
 			  smp_ipi_name[msg], 0);
 	WARN(err < 0, "unable to request_irq %d for %s (rc %d)\n",
 		virq, smp_ipi_name[msg], err);
@@ -357,8 +374,6 @@
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-/* State of each CPU during hotplug phases */
-static DEFINE_PER_CPU(int, cpu_state) = { 0 };
 
 int generic_cpu_disable(void)
 {
@@ -406,6 +421,11 @@
 {
 	per_cpu(cpu_state, cpu) = CPU_DEAD;
 }
+
+int generic_check_cpu_restart(unsigned int cpu)
+{
+	return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE;
+}
 #endif
 
 struct create_idle {
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/stacktrace.c linux-libre-3.2-gnu/arch/powerpc/kernel/stacktrace.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/stacktrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/stacktrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
  *      2 of the License, or (at your option) any later version.
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/stacktrace.h>
 #include <asm/ptrace.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/swsusp_64.c linux-libre-3.2-gnu/arch/powerpc/kernel/swsusp_64.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/swsusp_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/swsusp_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <asm/system.h>
 #include <asm/iommu.h>
 #include <linux/irq.h>
+#include <linux/sched.h>
 #include <linux/interrupt.h>
 
 void do_after_copyback(void)
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/swsusp.c linux-libre-3.2-gnu/arch/powerpc/kernel/swsusp.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/swsusp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/swsusp.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,6 @@
 void restore_processor_state(void)
 {
 #ifdef CONFIG_PPC32
-	switch_mmu_context(NULL, current->active_mm);
+	switch_mmu_context(current->active_mm, current->active_mm);
 #endif
 }
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/sysfs.c linux-libre-3.2-gnu/arch/powerpc/kernel/sysfs.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
 #include <linux/percpu.h>
 #include <linux/init.h>
 #include <linux/sched.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/nodemask.h>
 #include <linux/cpumask.h>
 #include <linux/notifier.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/time.c linux-libre-3.2-gnu/arch/powerpc/kernel/time.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,7 @@
  */
 
 #include <linux/errno.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/param.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/traps.c linux-libre-3.2-gnu/arch/powerpc/kernel/traps.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/traps.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/traps.c	2012-01-04 18:55:44.000000000 -0500
@@ -457,7 +457,14 @@
 
 	if (reason & MCSR_DCPERR_MC) {
 		printk("Data Cache Parity Error\n");
-		recoverable = 0;
+
+		/*
+		 * In write shadow mode we auto-recover from the error, but it
+		 * may still get logged and cause a machine check.  We should
+		 * only treat the non-write shadow case as non-recoverable.
+		 */
+		if (!(mfspr(SPRN_L1CSR2) & L1CSR2_DCWS))
+			recoverable = 0;
 	}
 
 	if (reason & MCSR_L2MMU_MHIT) {
@@ -1291,14 +1298,12 @@
 
 		if (user_mode(regs)) {
 			current->thread.dbcr0 &= ~DBCR0_IC;
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 			if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0,
 					       current->thread.dbcr1))
 				regs->msr |= MSR_DE;
 			else
 				/* Make sure the IDM bit is off */
 				current->thread.dbcr0 &= ~DBCR0_IDM;
-#endif
 		}
 
 		_exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/udbg.c linux-libre-3.2-gnu/arch/powerpc/kernel/udbg.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/udbg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/udbg.c	2012-01-04 18:55:44.000000000 -0500
@@ -67,6 +67,14 @@
 	udbg_init_usbgecko();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_WSP)
 	udbg_init_wsp();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_EHV_BC)
+	udbg_init_ehv_bc();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_PS3GELIC)
+	udbg_init_ps3gelic();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_OPAL_RAW)
+	udbg_init_debug_opal_raw();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_OPAL_HVSI)
+	udbg_init_debug_opal_hvsi();
 #endif
 
 #ifdef CONFIG_PPC_EARLY_DEBUG
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/vdso.c linux-libre-3.2-gnu/arch/powerpc/kernel/vdso.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/vdso.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/vdso.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@
  *  2 of the License, or (at your option) any later version.
  */
 
-#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kernel/vio.c linux-libre-3.2-gnu/arch/powerpc/kernel/vio.c
--- linux-libre-3.1-gnu/arch/powerpc/kernel/vio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kernel/vio.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,11 +15,12 @@
  */
 
 #include <linux/types.h>
+#include <linux/stat.h>
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/console.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/kobject.h>
@@ -605,15 +606,20 @@
         return dma_iommu_ops.dma_supported(dev, mask);
 }
 
-struct dma_map_ops vio_dma_mapping_ops = {
-	.alloc_coherent = vio_dma_iommu_alloc_coherent,
-	.free_coherent  = vio_dma_iommu_free_coherent,
-	.map_sg         = vio_dma_iommu_map_sg,
-	.unmap_sg       = vio_dma_iommu_unmap_sg,
-	.map_page       = vio_dma_iommu_map_page,
-	.unmap_page     = vio_dma_iommu_unmap_page,
-	.dma_supported  = vio_dma_iommu_dma_supported,
+static u64 vio_dma_get_required_mask(struct device *dev)
+{
+        return dma_iommu_ops.get_required_mask(dev);
+}
 
+struct dma_map_ops vio_dma_mapping_ops = {
+	.alloc_coherent    = vio_dma_iommu_alloc_coherent,
+	.free_coherent     = vio_dma_iommu_free_coherent,
+	.map_sg            = vio_dma_iommu_map_sg,
+	.unmap_sg          = vio_dma_iommu_unmap_sg,
+	.map_page          = vio_dma_iommu_map_page,
+	.unmap_page        = vio_dma_iommu_unmap_page,
+	.dma_supported     = vio_dma_iommu_dma_supported,
+	.get_required_mask = vio_dma_get_required_mask,
 };
 
 /**
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/44x.c linux-libre-3.2-gnu/arch/powerpc/kvm/44x.c
--- linux-libre-3.1-gnu/arch/powerpc/kvm/44x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/44x.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/kvm_host.h>
 #include <linux/slab.h>
 #include <linux/err.h>
+#include <linux/export.h>
 
 #include <asm/reg.h>
 #include <asm/cputable.h>
@@ -78,6 +79,8 @@
 	for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++)
 		vcpu_44x->shadow_refs[i].gtlb_index = -1;
 
+	vcpu->arch.cpu_type = KVM_CPU_440;
+
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_32_sr.S linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_32_sr.S
--- linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_32_sr.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_32_sr.S	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,7 @@
 	 * R1 = host R1
 	 * R2 = host R2
 	 * R3 = shadow vcpu
-	 * all other volatile GPRS = free
+	 * all other volatile GPRS = free except R4, R6
 	 * SVCPU[CR]  = guest CR
 	 * SVCPU[XER] = guest XER
 	 * SVCPU[CTR] = guest CTR
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_64_mmu.c linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_64_mmu.c
--- linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_64_mmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_64_mmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -128,7 +128,13 @@
 	dprintk("MMU: page=0x%x sdr1=0x%llx pteg=0x%llx vsid=0x%llx\n",
 		page, vcpu_book3s->sdr1, pteg, slbe->vsid);
 
-	r = gfn_to_hva(vcpu_book3s->vcpu.kvm, pteg >> PAGE_SHIFT);
+	/* When running a PAPR guest, SDR1 contains a HVA address instead
+           of a GPA */
+	if (vcpu_book3s->vcpu.arch.papr_enabled)
+		r = pteg;
+	else
+		r = gfn_to_hva(vcpu_book3s->vcpu.kvm, pteg >> PAGE_SHIFT);
+
 	if (kvm_is_error_hva(r))
 		return r;
 	return r | (pteg & ~PAGE_MASK);
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_64_slb.S linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_64_slb.S
--- linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_64_slb.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_64_slb.S	2012-01-04 18:55:44.000000000 -0500
@@ -53,7 +53,7 @@
 	 * R1 = host R1
 	 * R2 = host R2
 	 * R3 = shadow vcpu
-	 * all other volatile GPRS = free
+	 * all other volatile GPRS = free except R4, R6
 	 * SVCPU[CR]  = guest CR
 	 * SVCPU[XER] = guest XER
 	 * SVCPU[CTR] = guest CTR
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/book3s.c linux-libre-3.2-gnu/arch/powerpc/kvm/book3s.c
--- linux-libre-3.1-gnu/arch/powerpc/kvm/book3s.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/book3s.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 
 #include <linux/kvm_host.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 
 #include <asm/reg.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_emulate.c linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_emulate.c
--- linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_emulate.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_emulate.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,6 +63,25 @@
  * function pointers, so let's just disable the define. */
 #undef mfsrin
 
+enum priv_level {
+	PRIV_PROBLEM = 0,
+	PRIV_SUPER = 1,
+	PRIV_HYPER = 2,
+};
+
+static bool spr_allowed(struct kvm_vcpu *vcpu, enum priv_level level)
+{
+	/* PAPR VMs only access supervisor SPRs */
+	if (vcpu->arch.papr_enabled && (level > PRIV_SUPER))
+		return false;
+
+	/* Limit user space to its own small SPR set */
+	if ((vcpu->arch.shared->msr & MSR_PR) && level > PRIV_PROBLEM)
+		return false;
+
+	return true;
+}
+
 int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                            unsigned int inst, int *advance)
 {
@@ -296,6 +315,8 @@
 
 	switch (sprn) {
 	case SPRN_SDR1:
+		if (!spr_allowed(vcpu, PRIV_HYPER))
+			goto unprivileged;
 		to_book3s(vcpu)->sdr1 = spr_val;
 		break;
 	case SPRN_DSISR:
@@ -390,6 +411,7 @@
 	case SPRN_PMC4_GEKKO:
 	case SPRN_WPAR_GEKKO:
 		break;
+unprivileged:
 	default:
 		printk(KERN_INFO "KVM: invalid SPR write: %d\n", sprn);
 #ifndef DEBUG_SPR
@@ -421,6 +443,8 @@
 		break;
 	}
 	case SPRN_SDR1:
+		if (!spr_allowed(vcpu, PRIV_HYPER))
+			goto unprivileged;
 		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->sdr1);
 		break;
 	case SPRN_DSISR:
@@ -449,6 +473,10 @@
 	case SPRN_HID5:
 		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[5]);
 		break;
+	case SPRN_CFAR:
+	case SPRN_PURR:
+		kvmppc_set_gpr(vcpu, rt, 0);
+		break;
 	case SPRN_GQR0:
 	case SPRN_GQR1:
 	case SPRN_GQR2:
@@ -476,6 +504,7 @@
 		kvmppc_set_gpr(vcpu, rt, 0);
 		break;
 	default:
+unprivileged:
 		printk(KERN_INFO "KVM: invalid SPR read: %d\n", sprn);
 #ifndef DEBUG_SPR
 		emulated = EMULATE_FAIL;
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_exports.c linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_exports.c
--- linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_exports.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_exports.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,15 +17,13 @@
  * Authors: Alexander Graf <agraf@suse.de>
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/kvm_book3s.h>
 
 #ifdef CONFIG_KVM_BOOK3S_64_HV
 EXPORT_SYMBOL_GPL(kvmppc_hv_entry_trampoline);
 #else
-EXPORT_SYMBOL_GPL(kvmppc_handler_trampoline_enter);
-EXPORT_SYMBOL_GPL(kvmppc_handler_lowmem_trampoline);
-EXPORT_SYMBOL_GPL(kvmppc_rmcall);
+EXPORT_SYMBOL_GPL(kvmppc_entry_trampoline);
 EXPORT_SYMBOL_GPL(kvmppc_load_up_fpu);
 #ifdef CONFIG_ALTIVEC
 EXPORT_SYMBOL_GPL(kvmppc_load_up_altivec);
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_hv_builtin.c linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_hv_builtin.c
--- linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_hv_builtin.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_hv_builtin.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 
 #include <linux/kvm_host.h>
 #include <linux/preempt.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/bootmem.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_hv.c linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_hv.c
--- linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_hv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_hv.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/preempt.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 #include <linux/fs.h>
 #include <linux/anon_inodes.h>
 #include <linux/cpumask.h>
@@ -43,6 +44,7 @@
 #include <asm/processor.h>
 #include <asm/cputhreads.h>
 #include <asm/page.h>
+#include <asm/hvcall.h>
 #include <linux/gfp.h>
 #include <linux/sched.h>
 #include <linux/vmalloc.h>
@@ -62,6 +64,8 @@
 /* #define EXIT_DEBUG_SIMPLE */
 /* #define EXIT_DEBUG_INT */
 
+static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
+
 void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
 	local_paca->kvm_hstate.kvm_vcpu = vcpu;
@@ -72,40 +76,10 @@
 {
 }
 
-static void kvmppc_vcpu_blocked(struct kvm_vcpu *vcpu);
-static void kvmppc_vcpu_unblocked(struct kvm_vcpu *vcpu);
-
-void kvmppc_vcpu_block(struct kvm_vcpu *vcpu)
-{
-	u64 now;
-	unsigned long dec_nsec;
-
-	now = get_tb();
-	if (now >= vcpu->arch.dec_expires && !kvmppc_core_pending_dec(vcpu))
-		kvmppc_core_queue_dec(vcpu);
-	if (vcpu->arch.pending_exceptions)
-		return;
-	if (vcpu->arch.dec_expires != ~(u64)0) {
-		dec_nsec = (vcpu->arch.dec_expires - now) * NSEC_PER_SEC /
-			tb_ticks_per_sec;
-		hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec),
-			      HRTIMER_MODE_REL);
-	}
-
-	kvmppc_vcpu_blocked(vcpu);
-
-	kvm_vcpu_block(vcpu);
-	vcpu->stat.halt_wakeup++;
-
-	if (vcpu->arch.dec_expires != ~(u64)0)
-		hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
-
-	kvmppc_vcpu_unblocked(vcpu);
-}
-
 void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
 {
 	vcpu->arch.shregs.msr = msr;
+	kvmppc_end_cede(vcpu);
 }
 
 void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
@@ -257,15 +231,6 @@
 
 	switch (req) {
 	case H_CEDE:
-		vcpu->arch.shregs.msr |= MSR_EE;
-		vcpu->arch.ceded = 1;
-		smp_mb();
-		if (!vcpu->arch.prodded)
-			kvmppc_vcpu_block(vcpu);
-		else
-			vcpu->arch.prodded = 0;
-		smp_mb();
-		vcpu->arch.ceded = 0;
 		break;
 	case H_PROD:
 		target = kvmppc_get_gpr(vcpu, 4);
@@ -388,20 +353,6 @@
 		break;
 	}
 
-
-	if (!(r & RESUME_HOST)) {
-		/* To avoid clobbering exit_reason, only check for signals if
-		 * we aren't already exiting to userspace for some other
-		 * reason. */
-		if (signal_pending(tsk)) {
-			vcpu->stat.signal_exits++;
-			run->exit_reason = KVM_EXIT_INTR;
-			r = -EINTR;
-		} else {
-			kvmppc_core_deliver_interrupts(vcpu);
-		}
-	}
-
 	return r;
 }
 
@@ -479,13 +430,9 @@
 	kvmppc_mmu_book3s_hv_init(vcpu);
 
 	/*
-	 * Some vcpus may start out in stopped state.  If we initialize
-	 * them to busy-in-host state they will stop other vcpus in the
-	 * vcore from running.  Instead we initialize them to blocked
-	 * state, effectively considering them to be stopped until we
-	 * see the first run ioctl for them.
+	 * We consider the vcpu stopped until we see the first run ioctl for it.
 	 */
-	vcpu->arch.state = KVMPPC_VCPU_BLOCKED;
+	vcpu->arch.state = KVMPPC_VCPU_STOPPED;
 
 	init_waitqueue_head(&vcpu->arch.cpu_run);
 
@@ -496,6 +443,7 @@
 		if (vcore) {
 			INIT_LIST_HEAD(&vcore->runnable_threads);
 			spin_lock_init(&vcore->lock);
+			init_waitqueue_head(&vcore->wq);
 		}
 		kvm->arch.vcores[core] = vcore;
 	}
@@ -506,10 +454,12 @@
 
 	spin_lock(&vcore->lock);
 	++vcore->num_threads;
-	++vcore->n_blocked;
 	spin_unlock(&vcore->lock);
 	vcpu->arch.vcore = vcore;
 
+	vcpu->arch.cpu_type = KVM_CPU_3S_64;
+	kvmppc_sanity_check(vcpu);
+
 	return vcpu;
 
 free_vcpu:
@@ -524,30 +474,31 @@
 	kfree(vcpu);
 }
 
-static void kvmppc_vcpu_blocked(struct kvm_vcpu *vcpu)
+static void kvmppc_set_timer(struct kvm_vcpu *vcpu)
 {
-	struct kvmppc_vcore *vc = vcpu->arch.vcore;
+	unsigned long dec_nsec, now;
 
-	spin_lock(&vc->lock);
-	vcpu->arch.state = KVMPPC_VCPU_BLOCKED;
-	++vc->n_blocked;
-	if (vc->n_runnable > 0 &&
-	    vc->n_runnable + vc->n_blocked == vc->num_threads) {
-		vcpu = list_first_entry(&vc->runnable_threads, struct kvm_vcpu,
-					arch.run_list);
-		wake_up(&vcpu->arch.cpu_run);
+	now = get_tb();
+	if (now > vcpu->arch.dec_expires) {
+		/* decrementer has already gone negative */
+		kvmppc_core_queue_dec(vcpu);
+		kvmppc_core_deliver_interrupts(vcpu);
+		return;
 	}
-	spin_unlock(&vc->lock);
+	dec_nsec = (vcpu->arch.dec_expires - now) * NSEC_PER_SEC
+		   / tb_ticks_per_sec;
+	hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec),
+		      HRTIMER_MODE_REL);
+	vcpu->arch.timer_running = 1;
 }
 
-static void kvmppc_vcpu_unblocked(struct kvm_vcpu *vcpu)
+static void kvmppc_end_cede(struct kvm_vcpu *vcpu)
 {
-	struct kvmppc_vcore *vc = vcpu->arch.vcore;
-
-	spin_lock(&vc->lock);
-	vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
-	--vc->n_blocked;
-	spin_unlock(&vc->lock);
+	vcpu->arch.ceded = 0;
+	if (vcpu->arch.timer_running) {
+		hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
+		vcpu->arch.timer_running = 0;
+	}
 }
 
 extern int __kvmppc_vcore_entry(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
@@ -562,6 +513,7 @@
 		return;
 	vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
 	--vc->n_runnable;
+	++vc->n_busy;
 	/* decrement the physical thread id of each following vcpu */
 	v = vcpu;
 	list_for_each_entry_continue(v, &vc->runnable_threads, arch.run_list)
@@ -575,15 +527,20 @@
 	struct paca_struct *tpaca;
 	struct kvmppc_vcore *vc = vcpu->arch.vcore;
 
+	if (vcpu->arch.timer_running) {
+		hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
+		vcpu->arch.timer_running = 0;
+	}
 	cpu = vc->pcpu + vcpu->arch.ptid;
 	tpaca = &paca[cpu];
 	tpaca->kvm_hstate.kvm_vcpu = vcpu;
 	tpaca->kvm_hstate.kvm_vcore = vc;
+	tpaca->kvm_hstate.napping = 0;
+	vcpu->cpu = vc->pcpu;
 	smp_wmb();
-#ifdef CONFIG_PPC_ICP_NATIVE
+#if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP)
 	if (vcpu->arch.ptid) {
 		tpaca->cpu_start = 0x80;
-		tpaca->kvm_hstate.in_guest = KVM_GUEST_MODE_GUEST;
 		wmb();
 		xics_wake_cpu(cpu);
 		++vc->n_woken;
@@ -631,9 +588,10 @@
  */
 static int kvmppc_run_core(struct kvmppc_vcore *vc)
 {
-	struct kvm_vcpu *vcpu, *vnext;
+	struct kvm_vcpu *vcpu, *vcpu0, *vnext;
 	long ret;
 	u64 now;
+	int ptid;
 
 	/* don't start if any threads have a signal pending */
 	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
@@ -652,29 +610,50 @@
 		goto out;
 	}
 
+	/*
+	 * Assign physical thread IDs, first to non-ceded vcpus
+	 * and then to ceded ones.
+	 */
+	ptid = 0;
+	vcpu0 = NULL;
+	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
+		if (!vcpu->arch.ceded) {
+			if (!ptid)
+				vcpu0 = vcpu;
+			vcpu->arch.ptid = ptid++;
+		}
+	}
+	if (!vcpu0)
+		return 0;		/* nothing to run */
+	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
+		if (vcpu->arch.ceded)
+			vcpu->arch.ptid = ptid++;
+
 	vc->n_woken = 0;
 	vc->nap_count = 0;
 	vc->entry_exit_count = 0;
-	vc->vcore_running = 1;
+	vc->vcore_state = VCORE_RUNNING;
 	vc->in_guest = 0;
 	vc->pcpu = smp_processor_id();
+	vc->napping_threads = 0;
 	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
 		kvmppc_start_thread(vcpu);
-	vcpu = list_first_entry(&vc->runnable_threads, struct kvm_vcpu,
-				arch.run_list);
 
+	preempt_disable();
 	spin_unlock(&vc->lock);
 
-	preempt_disable();
 	kvm_guest_enter();
-	__kvmppc_vcore_entry(NULL, vcpu);
+	__kvmppc_vcore_entry(NULL, vcpu0);
 
-	/* wait for secondary threads to finish writing their state to memory */
 	spin_lock(&vc->lock);
+	/* disable sending of IPIs on virtual external irqs */
+	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
+		vcpu->cpu = -1;
+	/* wait for secondary threads to finish writing their state to memory */
 	if (vc->nap_count < vc->n_woken)
 		kvmppc_wait_for_nap(vc);
 	/* prevent other vcpu threads from doing kvmppc_start_thread() now */
-	vc->vcore_running = 2;
+	vc->vcore_state = VCORE_EXITING;
 	spin_unlock(&vc->lock);
 
 	/* make sure updates to secondary vcpu structs are visible now */
@@ -690,22 +669,26 @@
 		if (now < vcpu->arch.dec_expires &&
 		    kvmppc_core_pending_dec(vcpu))
 			kvmppc_core_dequeue_dec(vcpu);
-		if (!vcpu->arch.trap) {
-			if (signal_pending(vcpu->arch.run_task)) {
-				vcpu->arch.kvm_run->exit_reason = KVM_EXIT_INTR;
-				vcpu->arch.ret = -EINTR;
-			}
-			continue;		/* didn't get to run */
-		}
-		ret = kvmppc_handle_exit(vcpu->arch.kvm_run, vcpu,
-					 vcpu->arch.run_task);
+
+		ret = RESUME_GUEST;
+		if (vcpu->arch.trap)
+			ret = kvmppc_handle_exit(vcpu->arch.kvm_run, vcpu,
+						 vcpu->arch.run_task);
+
 		vcpu->arch.ret = ret;
 		vcpu->arch.trap = 0;
+
+		if (vcpu->arch.ceded) {
+			if (ret != RESUME_GUEST)
+				kvmppc_end_cede(vcpu);
+			else
+				kvmppc_set_timer(vcpu);
+		}
 	}
 
 	spin_lock(&vc->lock);
  out:
-	vc->vcore_running = 0;
+	vc->vcore_state = VCORE_INACTIVE;
 	list_for_each_entry_safe(vcpu, vnext, &vc->runnable_threads,
 				 arch.run_list) {
 		if (vcpu->arch.ret != RESUME_GUEST) {
@@ -717,82 +700,130 @@
 	return 1;
 }
 
-static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+/*
+ * Wait for some other vcpu thread to execute us, and
+ * wake us up when we need to handle something in the host.
+ */
+static void kvmppc_wait_for_exec(struct kvm_vcpu *vcpu, int wait_state)
 {
-	int ptid;
-	int wait_state;
-	struct kvmppc_vcore *vc;
 	DEFINE_WAIT(wait);
 
-	/* No need to go into the guest when all we do is going out */
-	if (signal_pending(current)) {
-		kvm_run->exit_reason = KVM_EXIT_INTR;
-		return -EINTR;
+	prepare_to_wait(&vcpu->arch.cpu_run, &wait, wait_state);
+	if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE)
+		schedule();
+	finish_wait(&vcpu->arch.cpu_run, &wait);
+}
+
+/*
+ * All the vcpus in this vcore are idle, so wait for a decrementer
+ * or external interrupt to one of the vcpus.  vc->lock is held.
+ */
+static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
+{
+	DEFINE_WAIT(wait);
+	struct kvm_vcpu *v;
+	int all_idle = 1;
+
+	prepare_to_wait(&vc->wq, &wait, TASK_INTERRUPTIBLE);
+	vc->vcore_state = VCORE_SLEEPING;
+	spin_unlock(&vc->lock);
+	list_for_each_entry(v, &vc->runnable_threads, arch.run_list) {
+		if (!v->arch.ceded || v->arch.pending_exceptions) {
+			all_idle = 0;
+			break;
+		}
 	}
+	if (all_idle)
+		schedule();
+	finish_wait(&vc->wq, &wait);
+	spin_lock(&vc->lock);
+	vc->vcore_state = VCORE_INACTIVE;
+}
 
-	/* On PPC970, check that we have an RMA region */
-	if (!vcpu->kvm->arch.rma && cpu_has_feature(CPU_FTR_ARCH_201))
-		return -EPERM;
+static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+{
+	int n_ceded;
+	int prev_state;
+	struct kvmppc_vcore *vc;
+	struct kvm_vcpu *v, *vn;
 
 	kvm_run->exit_reason = 0;
 	vcpu->arch.ret = RESUME_GUEST;
 	vcpu->arch.trap = 0;
 
-	flush_fp_to_thread(current);
-	flush_altivec_to_thread(current);
-	flush_vsx_to_thread(current);
-
 	/*
 	 * Synchronize with other threads in this virtual core
 	 */
 	vc = vcpu->arch.vcore;
 	spin_lock(&vc->lock);
-	/* This happens the first time this is called for a vcpu */
-	if (vcpu->arch.state == KVMPPC_VCPU_BLOCKED)
-		--vc->n_blocked;
-	vcpu->arch.state = KVMPPC_VCPU_RUNNABLE;
-	ptid = vc->n_runnable;
+	vcpu->arch.ceded = 0;
 	vcpu->arch.run_task = current;
 	vcpu->arch.kvm_run = kvm_run;
-	vcpu->arch.ptid = ptid;
+	prev_state = vcpu->arch.state;
+	vcpu->arch.state = KVMPPC_VCPU_RUNNABLE;
 	list_add_tail(&vcpu->arch.run_list, &vc->runnable_threads);
 	++vc->n_runnable;
 
-	wait_state = TASK_INTERRUPTIBLE;
-	while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE) {
-		if (signal_pending(current)) {
-			if (!vc->vcore_running) {
-				kvm_run->exit_reason = KVM_EXIT_INTR;
-				vcpu->arch.ret = -EINTR;
-				break;
-			}
-			/* have to wait for vcore to stop executing guest */
-			wait_state = TASK_UNINTERRUPTIBLE;
-			smp_send_reschedule(vc->pcpu);
+	/*
+	 * This happens the first time this is called for a vcpu.
+	 * If the vcore is already running, we may be able to start
+	 * this thread straight away and have it join in.
+	 */
+	if (prev_state == KVMPPC_VCPU_STOPPED) {
+		if (vc->vcore_state == VCORE_RUNNING &&
+		    VCORE_EXIT_COUNT(vc) == 0) {
+			vcpu->arch.ptid = vc->n_runnable - 1;
+			kvmppc_start_thread(vcpu);
 		}
 
-		if (!vc->vcore_running &&
-		    vc->n_runnable + vc->n_blocked == vc->num_threads) {
-			/* we can run now */
-			if (kvmppc_run_core(vc))
-				continue;
+	} else if (prev_state == KVMPPC_VCPU_BUSY_IN_HOST)
+		--vc->n_busy;
+
+	while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE &&
+	       !signal_pending(current)) {
+		if (vc->n_busy || vc->vcore_state != VCORE_INACTIVE) {
+			spin_unlock(&vc->lock);
+			kvmppc_wait_for_exec(vcpu, TASK_INTERRUPTIBLE);
+			spin_lock(&vc->lock);
+			continue;
 		}
+		n_ceded = 0;
+		list_for_each_entry(v, &vc->runnable_threads, arch.run_list)
+			n_ceded += v->arch.ceded;
+		if (n_ceded == vc->n_runnable)
+			kvmppc_vcore_blocked(vc);
+		else
+			kvmppc_run_core(vc);
 
-		if (vc->vcore_running == 1 && VCORE_EXIT_COUNT(vc) == 0)
-			kvmppc_start_thread(vcpu);
+		list_for_each_entry_safe(v, vn, &vc->runnable_threads,
+					 arch.run_list) {
+			kvmppc_core_deliver_interrupts(v);
+			if (signal_pending(v->arch.run_task)) {
+				kvmppc_remove_runnable(vc, v);
+				v->stat.signal_exits++;
+				v->arch.kvm_run->exit_reason = KVM_EXIT_INTR;
+				v->arch.ret = -EINTR;
+				wake_up(&v->arch.cpu_run);
+			}
+		}
+	}
 
-		/* wait for other threads to come in, or wait for vcore */
-		prepare_to_wait(&vcpu->arch.cpu_run, &wait, wait_state);
-		spin_unlock(&vc->lock);
-		schedule();
-		finish_wait(&vcpu->arch.cpu_run, &wait);
-		spin_lock(&vc->lock);
+	if (signal_pending(current)) {
+		if (vc->vcore_state == VCORE_RUNNING ||
+		    vc->vcore_state == VCORE_EXITING) {
+			spin_unlock(&vc->lock);
+			kvmppc_wait_for_exec(vcpu, TASK_UNINTERRUPTIBLE);
+			spin_lock(&vc->lock);
+		}
+		if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE) {
+			kvmppc_remove_runnable(vc, vcpu);
+			vcpu->stat.signal_exits++;
+			kvm_run->exit_reason = KVM_EXIT_INTR;
+			vcpu->arch.ret = -EINTR;
+		}
 	}
 
-	if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE)
-		kvmppc_remove_runnable(vc, vcpu);
 	spin_unlock(&vc->lock);
-
 	return vcpu->arch.ret;
 }
 
@@ -800,6 +831,26 @@
 {
 	int r;
 
+	if (!vcpu->arch.sane) {
+		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		return -EINVAL;
+	}
+
+	/* No need to go into the guest when all we'll do is come back out */
+	if (signal_pending(current)) {
+		run->exit_reason = KVM_EXIT_INTR;
+		return -EINTR;
+	}
+
+	/* On PPC970, check that we have an RMA region */
+	if (!vcpu->kvm->arch.rma && cpu_has_feature(CPU_FTR_ARCH_201))
+		return -EPERM;
+
+	flush_fp_to_thread(current);
+	flush_altivec_to_thread(current);
+	flush_vsx_to_thread(current);
+	vcpu->arch.wqp = &vcpu->arch.vcore->wq;
+
 	do {
 		r = kvmppc_run_vcpu(run, vcpu);
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_hv_rmhandlers.S linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_hv_rmhandlers.S
--- linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_hv_rmhandlers.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_hv_rmhandlers.S	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,10 @@
 #include <asm/ppc_asm.h>
 #include <asm/kvm_asm.h>
 #include <asm/reg.h>
+#include <asm/mmu.h>
 #include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/hvcall.h>
 #include <asm/asm-offsets.h>
 #include <asm/exception-64s.h>
 
@@ -49,7 +52,7 @@
 	b	.
 
 /*
- * Call kvmppc_handler_trampoline_enter in real mode.
+ * Call kvmppc_hv_entry in real mode.
  * Must be called with interrupts hard-disabled.
  *
  * Input Registers:
@@ -89,6 +92,12 @@
 kvm_start_guest:
 	ld	r1,PACAEMERGSP(r13)
 	subi	r1,r1,STACK_FRAME_OVERHEAD
+	ld	r2,PACATOC(r13)
+
+	/* were we napping due to cede? */
+	lbz	r0,HSTATE_NAPPING(r13)
+	cmpwi	r0,0
+	bne	kvm_end_cede
 
 	/* get vcpu pointer */
 	ld	r4, HSTATE_KVM_VCPU(r13)
@@ -276,15 +285,9 @@
 	cmpwi	r0,0
 	beq	20b
 
-	/* Set LPCR.  Set the MER bit if there is a pending external irq. */
+	/* Set LPCR and RMOR. */
 10:	ld	r8,KVM_LPCR(r9)
-	ld	r0,VCPU_PENDING_EXC(r4)
-	li	r7,(1 << BOOK3S_IRQPRIO_EXTERNAL)
-	oris	r7,r7,(1 << BOOK3S_IRQPRIO_EXTERNAL_LEVEL)@h
-	and.	r0,r0,r7
-	beq	11f
-	ori	r8,r8,LPCR_MER
-11:	mtspr	SPRN_LPCR,r8
+	mtspr	SPRN_LPCR,r8
 	ld	r8,KVM_RMOR(r9)
 	mtspr	SPRN_RMOR,r8
 	isync
@@ -448,19 +451,50 @@
 	mtctr	r6
 	mtxer	r7
 
-	/* Move SRR0 and SRR1 into the respective regs */
+kvmppc_cede_reentry:		/* r4 = vcpu, r13 = paca */
 	ld	r6, VCPU_SRR0(r4)
 	ld	r7, VCPU_SRR1(r4)
-	mtspr	SPRN_SRR0, r6
-	mtspr	SPRN_SRR1, r7
-
 	ld	r10, VCPU_PC(r4)
+	ld	r11, VCPU_MSR(r4)	/* r11 = vcpu->arch.msr & ~MSR_HV */
 
-	ld	r11, VCPU_MSR(r4)	/* r10 = vcpu->arch.msr & ~MSR_HV */
 	rldicl	r11, r11, 63 - MSR_HV_LG, 1
 	rotldi	r11, r11, 1 + MSR_HV_LG
 	ori	r11, r11, MSR_ME
 
+	/* Check if we can deliver an external or decrementer interrupt now */
+	ld	r0,VCPU_PENDING_EXC(r4)
+	li	r8,(1 << BOOK3S_IRQPRIO_EXTERNAL)
+	oris	r8,r8,(1 << BOOK3S_IRQPRIO_EXTERNAL_LEVEL)@h
+	and	r0,r0,r8
+	cmpdi	cr1,r0,0
+	andi.	r0,r11,MSR_EE
+	beq	cr1,11f
+BEGIN_FTR_SECTION
+	mfspr	r8,SPRN_LPCR
+	ori	r8,r8,LPCR_MER
+	mtspr	SPRN_LPCR,r8
+	isync
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+	beq	5f
+	li	r0,BOOK3S_INTERRUPT_EXTERNAL
+12:	mr	r6,r10
+	mr	r10,r0
+	mr	r7,r11
+	li	r11,(MSR_ME << 1) | 1	/* synthesize MSR_SF | MSR_ME */
+	rotldi	r11,r11,63
+	b	5f
+11:	beq	5f
+	mfspr	r0,SPRN_DEC
+	cmpwi	r0,0
+	li	r0,BOOK3S_INTERRUPT_DECREMENTER
+	blt	12b
+
+	/* Move SRR0 and SRR1 into the respective regs */
+5:	mtspr	SPRN_SRR0, r6
+	mtspr	SPRN_SRR1, r7
+	li	r0,0
+	stb	r0,VCPU_CEDED(r4)	/* cancel cede */
+
 fast_guest_return:
 	mtspr	SPRN_HSRR0,r10
 	mtspr	SPRN_HSRR1,r11
@@ -574,21 +608,20 @@
 	/* See if this is something we can handle in real mode */
 	cmpwi	r12,BOOK3S_INTERRUPT_SYSCALL
 	beq	hcall_try_real_mode
-hcall_real_cont:
 
 	/* Check for mediated interrupts (could be done earlier really ...) */
 BEGIN_FTR_SECTION
 	cmpwi	r12,BOOK3S_INTERRUPT_EXTERNAL
 	bne+	1f
-	ld	r5,VCPU_KVM(r9)
-	ld	r5,KVM_LPCR(r5)
 	andi.	r0,r11,MSR_EE
 	beq	1f
+	mfspr	r5,SPRN_LPCR
 	andi.	r0,r5,LPCR_MER
 	bne	bounce_ext_interrupt
 1:
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
+hcall_real_cont:		/* r9 = vcpu, r12 = trap, r13 = paca */
 	/* Save DEC */
 	mfspr	r5,SPRN_DEC
 	mftb	r6
@@ -682,7 +715,7 @@
 	slbia
 	ptesync
 
-hdec_soon:
+hdec_soon:			/* r9 = vcpu, r12 = trap, r13 = paca */
 BEGIN_FTR_SECTION
 	b	32f
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
@@ -700,6 +733,7 @@
 	addi	r0,r3,0x100
 	stwcx.	r0,0,r6
 	bne	41b
+	lwsync
 
 	/*
 	 * At this point we have an interrupt that we have to pass
@@ -713,18 +747,39 @@
 	 * interrupt, since the other threads will already be on their
 	 * way here in that case.
 	 */
+	cmpwi	r3,0x100	/* Are we the first here? */
+	bge	43f
+	cmpwi	r3,1		/* Are any other threads in the guest? */
+	ble	43f
 	cmpwi	r12,BOOK3S_INTERRUPT_HV_DECREMENTER
 	beq	40f
-	cmpwi	r3,0x100	/* Are we the first here? */
-	bge	40f
-	cmpwi	r3,1
-	ble	40f
 	li	r0,0
 	mtspr	SPRN_HDEC,r0
 40:
+	/*
+	 * Send an IPI to any napping threads, since an HDEC interrupt
+	 * doesn't wake CPUs up from nap.
+	 */
+	lwz	r3,VCORE_NAPPING_THREADS(r5)
+	lwz	r4,VCPU_PTID(r9)
+	li	r0,1
+	sldi	r0,r0,r4
+	andc.	r3,r3,r0		/* no sense IPI'ing ourselves */
+	beq	43f
+	mulli	r4,r4,PACA_SIZE		/* get paca for thread 0 */
+	subf	r6,r4,r13
+42:	andi.	r0,r3,1
+	beq	44f
+	ld	r8,HSTATE_XICS_PHYS(r6)	/* get thread's XICS reg addr */
+	li	r0,IPI_PRIORITY
+	li	r7,XICS_QIRR
+	stbcix	r0,r7,r8		/* trigger the IPI */
+44:	srdi.	r3,r3,1
+	addi	r6,r6,PACA_SIZE
+	bne	42b
 
 	/* Secondary threads wait for primary to do partition switch */
-	ld	r4,VCPU_KVM(r9)		/* pointer to struct kvm */
+43:	ld	r4,VCPU_KVM(r9)		/* pointer to struct kvm */
 	ld	r5,HSTATE_KVM_VCORE(r13)
 	lwz	r3,VCPU_PTID(r9)
 	cmpwi	r3,0
@@ -1077,7 +1132,6 @@
 hcall_real_fallback:
 	li	r12,BOOK3S_INTERRUPT_SYSCALL
 	ld	r9, HSTATE_KVM_VCPU(r13)
-	ld	r11, VCPU_MSR(r9)
 
 	b	hcall_real_cont
 
@@ -1139,7 +1193,7 @@
 	.long	0		/* 0xd4 */
 	.long	0		/* 0xd8 */
 	.long	0		/* 0xdc */
-	.long	0		/* 0xe0 */
+	.long	.kvmppc_h_cede - hcall_real_table
 	.long	0		/* 0xe4 */
 	.long	0		/* 0xe8 */
 	.long	0		/* 0xec */
@@ -1168,7 +1222,8 @@
 	mtspr	SPRN_SRR0,r10
 	mtspr	SPRN_SRR1,r11
 	li	r10,BOOK3S_INTERRUPT_EXTERNAL
-	LOAD_REG_IMMEDIATE(r11,MSR_SF | MSR_ME);
+	li	r11,(MSR_ME << 1) | 1	/* synthesize MSR_SF | MSR_ME */
+	rotldi	r11,r11,63
 	b	fast_guest_return
 
 _GLOBAL(kvmppc_h_set_dabr)
@@ -1177,6 +1232,178 @@
 	li	r3,0
 	blr
 
+_GLOBAL(kvmppc_h_cede)
+	ori	r11,r11,MSR_EE
+	std	r11,VCPU_MSR(r3)
+	li	r0,1
+	stb	r0,VCPU_CEDED(r3)
+	sync			/* order setting ceded vs. testing prodded */
+	lbz	r5,VCPU_PRODDED(r3)
+	cmpwi	r5,0
+	bne	1f
+	li	r0,0		/* set trap to 0 to say hcall is handled */
+	stw	r0,VCPU_TRAP(r3)
+	li	r0,H_SUCCESS
+	std	r0,VCPU_GPR(r3)(r3)
+BEGIN_FTR_SECTION
+	b	2f		/* just send it up to host on 970 */
+END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
+
+	/*
+	 * Set our bit in the bitmask of napping threads unless all the
+	 * other threads are already napping, in which case we send this
+	 * up to the host.
+	 */
+	ld	r5,HSTATE_KVM_VCORE(r13)
+	lwz	r6,VCPU_PTID(r3)
+	lwz	r8,VCORE_ENTRY_EXIT(r5)
+	clrldi	r8,r8,56
+	li	r0,1
+	sld	r0,r0,r6
+	addi	r6,r5,VCORE_NAPPING_THREADS
+31:	lwarx	r4,0,r6
+	or	r4,r4,r0
+	PPC_POPCNTW(r7,r4)
+	cmpw	r7,r8
+	bge	2f
+	stwcx.	r4,0,r6
+	bne	31b
+	li	r0,1
+	stb	r0,HSTATE_NAPPING(r13)
+	/* order napping_threads update vs testing entry_exit_count */
+	lwsync
+	mr	r4,r3
+	lwz	r7,VCORE_ENTRY_EXIT(r5)
+	cmpwi	r7,0x100
+	bge	33f		/* another thread already exiting */
+
+/*
+ * Although not specifically required by the architecture, POWER7
+ * preserves the following registers in nap mode, even if an SMT mode
+ * switch occurs: SLB entries, PURR, SPURR, AMOR, UAMOR, AMR, SPRG0-3,
+ * DAR, DSISR, DABR, DABRX, DSCR, PMCx, MMCRx, SIAR, SDAR.
+ */
+	/* Save non-volatile GPRs */
+	std	r14, VCPU_GPR(r14)(r3)
+	std	r15, VCPU_GPR(r15)(r3)
+	std	r16, VCPU_GPR(r16)(r3)
+	std	r17, VCPU_GPR(r17)(r3)
+	std	r18, VCPU_GPR(r18)(r3)
+	std	r19, VCPU_GPR(r19)(r3)
+	std	r20, VCPU_GPR(r20)(r3)
+	std	r21, VCPU_GPR(r21)(r3)
+	std	r22, VCPU_GPR(r22)(r3)
+	std	r23, VCPU_GPR(r23)(r3)
+	std	r24, VCPU_GPR(r24)(r3)
+	std	r25, VCPU_GPR(r25)(r3)
+	std	r26, VCPU_GPR(r26)(r3)
+	std	r27, VCPU_GPR(r27)(r3)
+	std	r28, VCPU_GPR(r28)(r3)
+	std	r29, VCPU_GPR(r29)(r3)
+	std	r30, VCPU_GPR(r30)(r3)
+	std	r31, VCPU_GPR(r31)(r3)
+
+	/* save FP state */
+	bl	.kvmppc_save_fp
+
+	/*
+	 * Take a nap until a decrementer or external interrupt occurs,
+	 * with PECE1 (wake on decr) and PECE0 (wake on external) set in LPCR
+	 */
+	li	r0,0x80
+	stb	r0,PACAPROCSTART(r13)
+	mfspr	r5,SPRN_LPCR
+	ori	r5,r5,LPCR_PECE0 | LPCR_PECE1
+	mtspr	SPRN_LPCR,r5
+	isync
+	li	r0, 0
+	std	r0, HSTATE_SCRATCH0(r13)
+	ptesync
+	ld	r0, HSTATE_SCRATCH0(r13)
+1:	cmpd	r0, r0
+	bne	1b
+	nap
+	b	.
+
+kvm_end_cede:
+	/* Woken by external or decrementer interrupt */
+	ld	r1, HSTATE_HOST_R1(r13)
+	ld	r2, PACATOC(r13)
+
+	/* If we're a secondary thread and we got here by an IPI, ack it */
+	ld	r4,HSTATE_KVM_VCPU(r13)
+	lwz	r3,VCPU_PTID(r4)
+	cmpwi	r3,0
+	beq	27f
+	mfspr	r3,SPRN_SRR1
+	rlwinm	r3,r3,44-31,0x7		/* extract wake reason field */
+	cmpwi	r3,4			/* was it an external interrupt? */
+	bne	27f
+	ld	r5, HSTATE_XICS_PHYS(r13)
+	li	r0,0xff
+	li	r6,XICS_QIRR
+	li	r7,XICS_XIRR
+	lwzcix	r8,r5,r7		/* ack the interrupt */
+	sync
+	stbcix	r0,r5,r6		/* clear it */
+	stwcix	r8,r5,r7		/* EOI it */
+27:
+	/* load up FP state */
+	bl	kvmppc_load_fp
+
+	/* Load NV GPRS */
+	ld	r14, VCPU_GPR(r14)(r4)
+	ld	r15, VCPU_GPR(r15)(r4)
+	ld	r16, VCPU_GPR(r16)(r4)
+	ld	r17, VCPU_GPR(r17)(r4)
+	ld	r18, VCPU_GPR(r18)(r4)
+	ld	r19, VCPU_GPR(r19)(r4)
+	ld	r20, VCPU_GPR(r20)(r4)
+	ld	r21, VCPU_GPR(r21)(r4)
+	ld	r22, VCPU_GPR(r22)(r4)
+	ld	r23, VCPU_GPR(r23)(r4)
+	ld	r24, VCPU_GPR(r24)(r4)
+	ld	r25, VCPU_GPR(r25)(r4)
+	ld	r26, VCPU_GPR(r26)(r4)
+	ld	r27, VCPU_GPR(r27)(r4)
+	ld	r28, VCPU_GPR(r28)(r4)
+	ld	r29, VCPU_GPR(r29)(r4)
+	ld	r30, VCPU_GPR(r30)(r4)
+	ld	r31, VCPU_GPR(r31)(r4)
+
+	/* clear our bit in vcore->napping_threads */
+33:	ld	r5,HSTATE_KVM_VCORE(r13)
+	lwz	r3,VCPU_PTID(r4)
+	li	r0,1
+	sld	r0,r0,r3
+	addi	r6,r5,VCORE_NAPPING_THREADS
+32:	lwarx	r7,0,r6
+	andc	r7,r7,r0
+	stwcx.	r7,0,r6
+	bne	32b
+	li	r0,0
+	stb	r0,HSTATE_NAPPING(r13)
+
+	/* see if any other thread is already exiting */
+	lwz	r0,VCORE_ENTRY_EXIT(r5)
+	cmpwi	r0,0x100
+	blt	kvmppc_cede_reentry	/* if not go back to guest */
+
+	/* some threads are exiting, so go to the guest exit path */
+	b	hcall_real_fallback
+
+	/* cede when already previously prodded case */
+1:	li	r0,0
+	stb	r0,VCPU_PRODDED(r3)
+	sync			/* order testing prodded vs. clearing ceded */
+	stb	r0,VCPU_CEDED(r3)
+	li	r3,H_SUCCESS
+	blr
+
+	/* we've ceded but we want to give control to the host */
+2:	li	r3,H_TOO_HARD
+	blr
+
 secondary_too_late:
 	ld	r5,HSTATE_KVM_VCORE(r13)
 	HMT_LOW
@@ -1194,14 +1421,20 @@
 	slbmte	r6,r5
 1:	addi	r11,r11,16
 	.endr
-	b	50f
 
 secondary_nap:
-	/* Clear any pending IPI */
-50:	ld	r5, HSTATE_XICS_PHYS(r13)
+	/* Clear any pending IPI - assume we're a secondary thread */
+	ld	r5, HSTATE_XICS_PHYS(r13)
+	li	r7, XICS_XIRR
+	lwzcix	r3, r5, r7		/* ack any pending interrupt */
+	rlwinm.	r0, r3, 0, 0xffffff	/* any pending? */
+	beq	37f
+	sync
 	li	r0, 0xff
 	li	r6, XICS_QIRR
-	stbcix	r0, r5, r6
+	stbcix	r0, r5, r6		/* clear the IPI */
+	stwcix	r3, r5, r7		/* EOI it */
+37:	sync
 
 	/* increment the nap count and then go to nap mode */
 	ld	r4, HSTATE_KVM_VCORE(r13)
@@ -1211,13 +1444,12 @@
 	addi	r3, r3, 1
 	stwcx.	r3, 0, r4
 	bne	51b
-	isync
 
+	li	r3, LPCR_PECE0
 	mfspr	r4, SPRN_LPCR
-	li	r0, LPCR_PECE
-	andc	r4, r4, r0
-	ori	r4, r4, LPCR_PECE0	/* exit nap on interrupt */
+	rlwimi	r4, r3, 0, LPCR_PECE0 | LPCR_PECE1
 	mtspr	SPRN_LPCR, r4
+	isync
 	li	r0, 0
 	std	r0, HSTATE_SCRATCH0(r13)
 	ptesync
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_hv_rm_mmu.c linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_hv_rm_mmu.c
--- linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_hv_rm_mmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_hv_rm_mmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -110,39 +110,6 @@
 	return H_SUCCESS;
 }
 
-static unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
-				      unsigned long pte_index)
-{
-	unsigned long rb, va_low;
-
-	rb = (v & ~0x7fUL) << 16;		/* AVA field */
-	va_low = pte_index >> 3;
-	if (v & HPTE_V_SECONDARY)
-		va_low = ~va_low;
-	/* xor vsid from AVA */
-	if (!(v & HPTE_V_1TB_SEG))
-		va_low ^= v >> 12;
-	else
-		va_low ^= v >> 24;
-	va_low &= 0x7ff;
-	if (v & HPTE_V_LARGE) {
-		rb |= 1;			/* L field */
-		if (cpu_has_feature(CPU_FTR_ARCH_206) &&
-		    (r & 0xff000)) {
-			/* non-16MB large page, must be 64k */
-			/* (masks depend on page size) */
-			rb |= 0x1000;		/* page encoding in LP field */
-			rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
-			rb |= (va_low & 0xfe);	/* AVAL field (P7 doesn't seem to care) */
-		}
-	} else {
-		/* 4kB page */
-		rb |= (va_low & 0x7ff) << 12;	/* remaining 11b of VA */
-	}
-	rb |= (v >> 54) & 0x300;		/* B field */
-	return rb;
-}
-
 #define LOCK_TOKEN	(*(u32 *)(&get_paca()->lock_token))
 
 static inline int try_lock_tlbie(unsigned int *lock)
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_interrupts.S linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_interrupts.S
--- linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_interrupts.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_interrupts.S	2012-01-04 18:55:44.000000000 -0500
@@ -29,27 +29,11 @@
 #define ULONG_SIZE 		8
 #define FUNC(name) 		GLUE(.,name)
 
-#define GET_SHADOW_VCPU_R13
-
-#define DISABLE_INTERRUPTS	\
-	mfmsr   r0;		\
-	rldicl  r0,r0,48,1;	\
-	rotldi  r0,r0,16;	\
-	mtmsrd  r0,1;		\
-
 #elif defined(CONFIG_PPC_BOOK3S_32)
 
 #define ULONG_SIZE              4
 #define FUNC(name)		name
 
-#define GET_SHADOW_VCPU_R13	\
-	lwz	r13, (THREAD + THREAD_KVM_SVCPU)(r2)
-
-#define DISABLE_INTERRUPTS	\
-	mfmsr   r0;		\
-	rlwinm  r0,r0,0,17,15;	\
-	mtmsr   r0;		\
-
 #endif /* CONFIG_PPC_BOOK3S_XX */
 
 
@@ -108,44 +92,17 @@
 
 kvm_start_lightweight:
 
-	GET_SHADOW_VCPU_R13
-	PPC_LL	r3, VCPU_HIGHMEM_HANDLER(r4)
-	PPC_STL	r3, HSTATE_VMHANDLER(r13)
-
-	PPC_LL	r10, VCPU_SHADOW_MSR(r4)	/* r10 = vcpu->arch.shadow_msr */
-
-	DISABLE_INTERRUPTS
-
 #ifdef CONFIG_PPC_BOOK3S_64
-	/* Some guests may need to have dcbz set to 32 byte length.
-	 *
-	 * Usually we ensure that by patching the guest's instructions
-	 * to trap on dcbz and emulate it in the hypervisor.
-	 *
-	 * If we can, we should tell the CPU to use 32 byte dcbz though,
-	 * because that's a lot faster.
-	 */
-
 	PPC_LL	r3, VCPU_HFLAGS(r4)
-	rldicl.	r3, r3, 0, 63		/* CR = ((r3 & 1) == 0) */
-	beq	no_dcbz32_on
-
-	mfspr   r3,SPRN_HID5
-	ori     r3, r3, 0x80		/* XXX HID5_dcbz32 = 0x80 */
-	mtspr   SPRN_HID5,r3
-
-no_dcbz32_on:
-
+	rldicl	r3, r3, 0, 63		/* r3 &= 1 */
+	stb	r3, HSTATE_RESTORE_HID5(r13)
 #endif /* CONFIG_PPC_BOOK3S_64 */
 
-	PPC_LL	r6, VCPU_RMCALL(r4)
-	mtctr	r6
-
-	PPC_LL	r3, VCPU_TRAMPOLINE_ENTER(r4)
-	LOAD_REG_IMMEDIATE(r4, MSR_KERNEL & ~(MSR_IR | MSR_DR))
+	PPC_LL	r4, VCPU_SHADOW_MSR(r4)	/* get shadow_msr */
 
 	/* Jump to segment patching handler and into our guest */
-	bctr
+	bl	FUNC(kvmppc_entry_trampoline)
+	nop
 
 /*
  * This is the handler in module memory. It gets jumped at from the
@@ -170,21 +127,6 @@
 	/* R7 = vcpu */
 	PPC_LL	r7, GPR4(r1)
 
-#ifdef CONFIG_PPC_BOOK3S_64
-
-	PPC_LL	r5, VCPU_HFLAGS(r7)
-	rldicl.	r5, r5, 0, 63		/* CR = ((r5 & 1) == 0) */
-	beq	no_dcbz32_off
-
-	li	r4, 0
-	mfspr   r5,SPRN_HID5
-	rldimi  r5,r4,6,56
-	mtspr   SPRN_HID5,r5
-
-no_dcbz32_off:
-
-#endif /* CONFIG_PPC_BOOK3S_64 */
-
 	PPC_STL	r14, VCPU_GPR(r14)(r7)
 	PPC_STL	r15, VCPU_GPR(r15)(r7)
 	PPC_STL	r16, VCPU_GPR(r16)(r7)
@@ -204,67 +146,6 @@
 	PPC_STL	r30, VCPU_GPR(r30)(r7)
 	PPC_STL	r31, VCPU_GPR(r31)(r7)
 
-	/* Restore host msr -> SRR1 */
-	PPC_LL	r6, VCPU_HOST_MSR(r7)
-
-	/*
-	 * For some interrupts, we need to call the real Linux
-	 * handler, so it can do work for us. This has to happen
-	 * as if the interrupt arrived from the kernel though,
-	 * so let's fake it here where most state is restored.
-	 *
-	 * Call Linux for hardware interrupts/decrementer
-	 * r3 = address of interrupt handler (exit reason)
-	 */
-
-	cmpwi	r12, BOOK3S_INTERRUPT_EXTERNAL
-	beq	call_linux_handler
-	cmpwi	r12, BOOK3S_INTERRUPT_DECREMENTER
-	beq	call_linux_handler
-	cmpwi	r12, BOOK3S_INTERRUPT_PERFMON
-	beq	call_linux_handler
-
-	/* Back to EE=1 */
-	mtmsr	r6
-	sync
-	b	kvm_return_point
-
-call_linux_handler:
-
-	/*
-	 * If we land here we need to jump back to the handler we
-	 * came from.
-	 *
-	 * We have a page that we can access from real mode, so let's
-	 * jump back to that and use it as a trampoline to get back into the
-	 * interrupt handler!
-	 *
-	 * R3 still contains the exit code,
-	 * R5 VCPU_HOST_RETIP and
-	 * R6 VCPU_HOST_MSR
-	 */
-
-	/* Restore host IP -> SRR0 */
-	PPC_LL	r5, VCPU_HOST_RETIP(r7)
-
-	/* XXX Better move to a safe function?
-	 *     What if we get an HTAB flush in between mtsrr0 and mtsrr1? */
-
-	mtlr	r12
-
-	PPC_LL	r4, VCPU_TRAMPOLINE_LOWMEM(r7)
-	mtsrr0	r4
-	LOAD_REG_IMMEDIATE(r3, MSR_KERNEL & ~(MSR_IR | MSR_DR))
-	mtsrr1	r3
-
-	RFI
-
-.global kvm_return_point
-kvm_return_point:
-
-	/* Jump back to lightweight entry if we're supposed to */
-	/* go back into the guest */
-
 	/* Pass the exit number as 3rd argument to kvmppc_handle_exit */
 	mr	r5, r12
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_pr.c linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_pr.c
--- linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_pr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_pr.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/kvm_host.h>
+#include <linux/export.h>
 #include <linux/err.h>
 #include <linux/slab.h>
 
@@ -152,14 +153,18 @@
 		kvmppc_mmu_book3s_64_init(vcpu);
 		to_book3s(vcpu)->hior = 0xfff00000;
 		to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL;
+		vcpu->arch.cpu_type = KVM_CPU_3S_64;
 	} else
 #endif
 	{
 		kvmppc_mmu_book3s_32_init(vcpu);
 		to_book3s(vcpu)->hior = 0;
 		to_book3s(vcpu)->msr_mask = 0xffffffffULL;
+		vcpu->arch.cpu_type = KVM_CPU_3S_32;
 	}
 
+	kvmppc_sanity_check(vcpu);
+
 	/* If we are in hypervisor level on 970, we can tell the CPU to
 	 * treat DCBZ as 32 bytes store */
 	vcpu->arch.hflags &= ~BOOK3S_HFLAG_DCBZ32;
@@ -646,7 +651,29 @@
 		break;
 	}
 	case BOOK3S_INTERRUPT_SYSCALL:
-		if (vcpu->arch.osi_enabled &&
+		if (vcpu->arch.papr_enabled &&
+		    (kvmppc_get_last_inst(vcpu) == 0x44000022) &&
+		    !(vcpu->arch.shared->msr & MSR_PR)) {
+			/* SC 1 papr hypercalls */
+			ulong cmd = kvmppc_get_gpr(vcpu, 3);
+			int i;
+
+#ifdef CONFIG_KVM_BOOK3S_64_PR
+			if (kvmppc_h_pr(vcpu, cmd) == EMULATE_DONE) {
+				r = RESUME_GUEST;
+				break;
+			}
+#endif
+
+			run->papr_hcall.nr = cmd;
+			for (i = 0; i < 9; ++i) {
+				ulong gpr = kvmppc_get_gpr(vcpu, 4 + i);
+				run->papr_hcall.args[i] = gpr;
+			}
+			run->exit_reason = KVM_EXIT_PAPR_HCALL;
+			vcpu->arch.hcall_needed = 1;
+			r = RESUME_HOST;
+		} else if (vcpu->arch.osi_enabled &&
 		    (((u32)kvmppc_get_gpr(vcpu, 3)) == OSI_SC_MAGIC_R3) &&
 		    (((u32)kvmppc_get_gpr(vcpu, 4)) == OSI_SC_MAGIC_R4)) {
 			/* MOL hypercalls */
@@ -841,8 +868,6 @@
 	if (!p)
 		goto uninit_vcpu;
 
-	vcpu->arch.host_retip = kvm_return_point;
-	vcpu->arch.host_msr = mfmsr();
 #ifdef CONFIG_PPC_BOOK3S_64
 	/* default to book3s_64 (970fx) */
 	vcpu->arch.pvr = 0x3C0301;
@@ -853,16 +878,6 @@
 	kvmppc_set_pvr(vcpu, vcpu->arch.pvr);
 	vcpu->arch.slb_nr = 64;
 
-	/* remember where some real-mode handlers are */
-	vcpu->arch.trampoline_lowmem = __pa(kvmppc_handler_lowmem_trampoline);
-	vcpu->arch.trampoline_enter = __pa(kvmppc_handler_trampoline_enter);
-	vcpu->arch.highmem_handler = (ulong)kvmppc_handler_highmem;
-#ifdef CONFIG_PPC_BOOK3S_64
-	vcpu->arch.rmcall = *(ulong*)kvmppc_rmcall;
-#else
-	vcpu->arch.rmcall = (ulong)kvmppc_rmcall;
-#endif
-
 	vcpu->arch.shadow_msr = MSR_USER64;
 
 	err = kvmppc_mmu_init(vcpu);
@@ -908,6 +923,12 @@
 #endif
 	ulong ext_msr;
 
+	/* Check if we can run the vcpu at all */
+	if (!vcpu->arch.sane) {
+		kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		return -EINVAL;
+	}
+
 	/* No need to go into the guest when all we do is going out */
 	if (signal_pending(current)) {
 		kvm_run->exit_reason = KVM_EXIT_INTR;
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_pr_papr.c linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_pr_papr.c
--- linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_pr_papr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_pr_papr.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2011. Freescale Inc. All rights reserved.
+ *
+ * Authors:
+ *    Alexander Graf <agraf@suse.de>
+ *    Paul Mackerras <paulus@samba.org>
+ *
+ * Description:
+ *
+ * Hypercall handling for running PAPR guests in PR KVM on Book 3S
+ * processors.
+ *
+ * This program is free software; you can 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/uaccess.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
+
+static unsigned long get_pteg_addr(struct kvm_vcpu *vcpu, long pte_index)
+{
+	struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
+	unsigned long pteg_addr;
+
+	pte_index <<= 4;
+	pte_index &= ((1 << ((vcpu_book3s->sdr1 & 0x1f) + 11)) - 1) << 7 | 0x70;
+	pteg_addr = vcpu_book3s->sdr1 & 0xfffffffffffc0000ULL;
+	pteg_addr |= pte_index;
+
+	return pteg_addr;
+}
+
+static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
+{
+	long flags = kvmppc_get_gpr(vcpu, 4);
+	long pte_index = kvmppc_get_gpr(vcpu, 5);
+	unsigned long pteg[2 * 8];
+	unsigned long pteg_addr, i, *hpte;
+
+	pte_index &= ~7UL;
+	pteg_addr = get_pteg_addr(vcpu, pte_index);
+
+	copy_from_user(pteg, (void __user *)pteg_addr, sizeof(pteg));
+	hpte = pteg;
+
+	if (likely((flags & H_EXACT) == 0)) {
+		pte_index &= ~7UL;
+		for (i = 0; ; ++i) {
+			if (i == 8)
+				return H_PTEG_FULL;
+			if ((*hpte & HPTE_V_VALID) == 0)
+				break;
+			hpte += 2;
+		}
+	} else {
+		i = kvmppc_get_gpr(vcpu, 5) & 7UL;
+		hpte += i * 2;
+	}
+
+	hpte[0] = kvmppc_get_gpr(vcpu, 6);
+	hpte[1] = kvmppc_get_gpr(vcpu, 7);
+	copy_to_user((void __user *)pteg_addr, pteg, sizeof(pteg));
+	kvmppc_set_gpr(vcpu, 3, H_SUCCESS);
+	kvmppc_set_gpr(vcpu, 4, pte_index | i);
+
+	return EMULATE_DONE;
+}
+
+static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
+{
+	unsigned long flags= kvmppc_get_gpr(vcpu, 4);
+	unsigned long pte_index = kvmppc_get_gpr(vcpu, 5);
+	unsigned long avpn = kvmppc_get_gpr(vcpu, 6);
+	unsigned long v = 0, pteg, rb;
+	unsigned long pte[2];
+
+	pteg = get_pteg_addr(vcpu, pte_index);
+	copy_from_user(pte, (void __user *)pteg, sizeof(pte));
+
+	if ((pte[0] & HPTE_V_VALID) == 0 ||
+	    ((flags & H_AVPN) && (pte[0] & ~0x7fUL) != avpn) ||
+	    ((flags & H_ANDCOND) && (pte[0] & avpn) != 0)) {
+		kvmppc_set_gpr(vcpu, 3, H_NOT_FOUND);
+		return EMULATE_DONE;
+	}
+
+	copy_to_user((void __user *)pteg, &v, sizeof(v));
+
+	rb = compute_tlbie_rb(pte[0], pte[1], pte_index);
+	vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
+
+	kvmppc_set_gpr(vcpu, 3, H_SUCCESS);
+	kvmppc_set_gpr(vcpu, 4, pte[0]);
+	kvmppc_set_gpr(vcpu, 5, pte[1]);
+
+	return EMULATE_DONE;
+}
+
+static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
+{
+	unsigned long flags = kvmppc_get_gpr(vcpu, 4);
+	unsigned long pte_index = kvmppc_get_gpr(vcpu, 5);
+	unsigned long avpn = kvmppc_get_gpr(vcpu, 6);
+	unsigned long rb, pteg, r, v;
+	unsigned long pte[2];
+
+	pteg = get_pteg_addr(vcpu, pte_index);
+	copy_from_user(pte, (void __user *)pteg, sizeof(pte));
+
+	if ((pte[0] & HPTE_V_VALID) == 0 ||
+	    ((flags & H_AVPN) && (pte[0] & ~0x7fUL) != avpn)) {
+		kvmppc_set_gpr(vcpu, 3, H_NOT_FOUND);
+		return EMULATE_DONE;
+	}
+
+	v = pte[0];
+	r = pte[1];
+	r &= ~(HPTE_R_PP0 | HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_HI |
+	       HPTE_R_KEY_LO);
+	r |= (flags << 55) & HPTE_R_PP0;
+	r |= (flags << 48) & HPTE_R_KEY_HI;
+	r |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
+
+	pte[1] = r;
+
+	rb = compute_tlbie_rb(v, r, pte_index);
+	vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
+	copy_to_user((void __user *)pteg, pte, sizeof(pte));
+
+	kvmppc_set_gpr(vcpu, 3, H_SUCCESS);
+
+	return EMULATE_DONE;
+}
+
+int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
+{
+	switch (cmd) {
+	case H_ENTER:
+		return kvmppc_h_pr_enter(vcpu);
+	case H_REMOVE:
+		return kvmppc_h_pr_remove(vcpu);
+	case H_PROTECT:
+		return kvmppc_h_pr_protect(vcpu);
+	case H_BULK_REMOVE:
+		/* We just flush all PTEs, so user space can
+		   handle the HPT modifications */
+		kvmppc_mmu_pte_flush(vcpu, 0, 0);
+		break;
+	case H_CEDE:
+		kvm_vcpu_block(vcpu);
+		vcpu->stat.halt_wakeup++;
+		return EMULATE_DONE;
+	}
+
+	return EMULATE_FAIL;
+}
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_rmhandlers.S linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_rmhandlers.S
--- linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_rmhandlers.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_rmhandlers.S	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <asm/ppc_asm.h>
 #include <asm/kvm_asm.h>
 #include <asm/reg.h>
+#include <asm/mmu.h>
 #include <asm/page.h>
 #include <asm/asm-offsets.h>
 
@@ -35,10 +36,10 @@
 
 #if defined(CONFIG_PPC_BOOK3S_64)
 
-#define LOAD_SHADOW_VCPU(reg)	GET_PACA(reg)					
-#define MSR_NOIRQ		MSR_KERNEL & ~(MSR_IR | MSR_DR)
 #define FUNC(name) 		GLUE(.,name)
+#define MTMSR_EERI(reg)		mtmsrd	(reg),1
 
+	.globl	kvmppc_skip_interrupt
 kvmppc_skip_interrupt:
 	/*
 	 * Here all GPRs are unchanged from when the interrupt happened
@@ -51,6 +52,7 @@
 	rfid
 	b	.
 
+	.globl	kvmppc_skip_Hinterrupt
 kvmppc_skip_Hinterrupt:
 	/*
 	 * Here all GPRs are unchanged from when the interrupt happened
@@ -65,8 +67,8 @@
 
 #elif defined(CONFIG_PPC_BOOK3S_32)
 
-#define MSR_NOIRQ		MSR_KERNEL
 #define FUNC(name)		name
+#define MTMSR_EERI(reg)		mtmsr	(reg)
 
 .macro INTERRUPT_TRAMPOLINE intno
 
@@ -167,40 +169,24 @@
 #endif
 
 /*
- * This trampoline brings us back to a real mode handler
- *
- * Input Registers:
- *
- * R5 = SRR0
- * R6 = SRR1
- * LR = real-mode IP
+ * Call kvmppc_handler_trampoline_enter in real mode
  *
+ * On entry, r4 contains the guest shadow MSR
  */
-.global kvmppc_handler_lowmem_trampoline
-kvmppc_handler_lowmem_trampoline:
+_GLOBAL(kvmppc_entry_trampoline)
+	mfmsr	r5
+	LOAD_REG_ADDR(r7, kvmppc_handler_trampoline_enter)
+	toreal(r7)
 
-	mtsrr0	r5
+	li	r9, MSR_RI
+	ori	r9, r9, MSR_EE
+	andc	r9, r5, r9	/* Clear EE and RI in MSR value */
+	li	r6, MSR_IR | MSR_DR
+	ori	r6, r6, MSR_EE
+	andc	r6, r5, r6	/* Clear EE, DR and IR in MSR value */
+	MTMSR_EERI(r9)		/* Clear EE and RI in MSR */
+	mtsrr0	r7		/* before we set srr0/1 */
 	mtsrr1	r6
-	blr
-kvmppc_handler_lowmem_trampoline_end:
-
-/*
- * Call a function in real mode
- *
- * Input Registers:
- *
- * R3 = function
- * R4 = MSR
- * R5 = scratch register
- *
- */
-_GLOBAL(kvmppc_rmcall)
-	LOAD_REG_IMMEDIATE(r5, MSR_NOIRQ)
-	mtmsr	r5		/* Disable relocation and interrupts, so mtsrr
-				   doesn't get interrupted */
-	sync
-	mtsrr0	r3
-	mtsrr1	r4
 	RFI
 
 #if defined(CONFIG_PPC_BOOK3S_32)
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_segment.S linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_segment.S
--- linux-libre-3.1-gnu/arch/powerpc/kvm/book3s_segment.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/book3s_segment.S	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 
 #define GET_SHADOW_VCPU(reg)    \
 	mr	reg, r13
+#define MTMSR_EERI(reg)		mtmsrd	(reg),1
 
 #elif defined(CONFIG_PPC_BOOK3S_32)
 
@@ -30,6 +31,7 @@
 	tophys(reg, r2);       			\
 	lwz     reg, (THREAD + THREAD_KVM_SVCPU)(reg);	\
 	tophys(reg, reg)
+#define MTMSR_EERI(reg)		mtmsr	(reg)
 
 #endif
 
@@ -57,10 +59,12 @@
 	/* Required state:
 	 *
 	 * MSR = ~IR|DR
-	 * R13 = PACA
 	 * R1 = host R1
 	 * R2 = host R2
-	 * R10 = guest MSR
+	 * R4 = guest shadow MSR
+	 * R5 = normal host MSR
+	 * R6 = current host MSR (EE, IR, DR off)
+	 * LR = highmem guest exit code
 	 * all other volatile GPRS = free
 	 * SVCPU[CR] = guest CR
 	 * SVCPU[XER] = guest XER
@@ -71,15 +75,15 @@
 	/* r3 = shadow vcpu */
 	GET_SHADOW_VCPU(r3)
 
+	/* Save guest exit handler address and MSR */
+	mflr	r0
+	PPC_STL	r0, HSTATE_VMHANDLER(r3)
+	PPC_STL	r5, HSTATE_HOST_MSR(r3)
+
 	/* Save R1/R2 in the PACA (64-bit) or shadow_vcpu (32-bit) */
 	PPC_STL	r1, HSTATE_HOST_R1(r3)
 	PPC_STL	r2, HSTATE_HOST_R2(r3)
 
-	/* Move SRR0 and SRR1 into the respective regs */
-	PPC_LL  r9, SVCPU_PC(r3)
-	mtsrr0	r9
-	mtsrr1	r10
-
 	/* Activate guest mode, so faults get handled by KVM */
 	li	r11, KVM_GUEST_MODE_GUEST
 	stb	r11, HSTATE_IN_GUEST(r3)
@@ -87,17 +91,46 @@
 	/* Switch to guest segment. This is subarch specific. */
 	LOAD_GUEST_SEGMENTS
 
+#ifdef CONFIG_PPC_BOOK3S_64
+	/* Some guests may need to have dcbz set to 32 byte length.
+	 *
+	 * Usually we ensure that by patching the guest's instructions
+	 * to trap on dcbz and emulate it in the hypervisor.
+	 *
+	 * If we can, we should tell the CPU to use 32 byte dcbz though,
+	 * because that's a lot faster.
+	 */
+	lbz	r0, HSTATE_RESTORE_HID5(r3)
+	cmpwi	r0, 0
+	beq	no_dcbz32_on
+
+	mfspr   r0,SPRN_HID5
+	ori     r0, r0, 0x80		/* XXX HID5_dcbz32 = 0x80 */
+	mtspr   SPRN_HID5,r0
+no_dcbz32_on:
+
+#endif /* CONFIG_PPC_BOOK3S_64 */
+
 	/* Enter guest */
 
-	PPC_LL	r4, SVCPU_CTR(r3)
-	PPC_LL	r5, SVCPU_LR(r3)
-	lwz	r6, SVCPU_CR(r3)
-	lwz	r7, SVCPU_XER(r3)
+	PPC_LL	r8, SVCPU_CTR(r3)
+	PPC_LL	r9, SVCPU_LR(r3)
+	lwz	r10, SVCPU_CR(r3)
+	lwz	r11, SVCPU_XER(r3)
 
-	mtctr	r4
-	mtlr	r5
-	mtcr	r6
-	mtxer	r7
+	mtctr	r8
+	mtlr	r9
+	mtcr	r10
+	mtxer	r11
+
+	/* Move SRR0 and SRR1 into the respective regs */
+	PPC_LL  r9, SVCPU_PC(r3)
+	/* First clear RI in our current MSR value */
+	li	r0, MSR_RI
+	andc	r6, r6, r0
+	MTMSR_EERI(r6)
+	mtsrr0	r9
+	mtsrr1	r4
 
 	PPC_LL	r0, SVCPU_R0(r3)
 	PPC_LL	r1, SVCPU_R1(r3)
@@ -213,11 +246,16 @@
 	beq	ld_last_inst
 	cmpwi	r12, BOOK3S_INTERRUPT_PROGRAM
 	beq	ld_last_inst
+	cmpwi	r12, BOOK3S_INTERRUPT_SYSCALL
+	beq	ld_last_prev_inst
 	cmpwi	r12, BOOK3S_INTERRUPT_ALIGNMENT
 	beq-	ld_last_inst
 
 	b	no_ld_last_inst
 
+ld_last_prev_inst:
+	addi	r3, r3, -4
+
 ld_last_inst:
 	/* Save off the guest instruction we're at */
 
@@ -254,6 +292,43 @@
 	/* Switch back to host MMU */
 	LOAD_HOST_SEGMENTS
 
+#ifdef CONFIG_PPC_BOOK3S_64
+
+	lbz	r5, HSTATE_RESTORE_HID5(r13)
+	cmpwi	r5, 0
+	beq	no_dcbz32_off
+
+	li	r4, 0
+	mfspr   r5,SPRN_HID5
+	rldimi  r5,r4,6,56
+	mtspr   SPRN_HID5,r5
+
+no_dcbz32_off:
+
+#endif /* CONFIG_PPC_BOOK3S_64 */
+
+	/*
+	 * For some interrupts, we need to call the real Linux
+	 * handler, so it can do work for us. This has to happen
+	 * as if the interrupt arrived from the kernel though,
+	 * so let's fake it here where most state is restored.
+	 *
+	 * Having set up SRR0/1 with the address where we want
+	 * to continue with relocation on (potentially in module
+	 * space), we either just go straight there with rfi[d],
+	 * or we jump to an interrupt handler with bctr if there
+	 * is an interrupt to be handled first.  In the latter
+	 * case, the rfi[d] at the end of the interrupt handler
+	 * will get us back to where we want to continue.
+	 */
+
+	cmpwi	r12, BOOK3S_INTERRUPT_EXTERNAL
+	beq	1f
+	cmpwi	r12, BOOK3S_INTERRUPT_DECREMENTER
+	beq	1f
+	cmpwi	r12, BOOK3S_INTERRUPT_PERFMON
+1:	mtctr	r12
+
 	/* Register usage at this point:
 	 *
 	 * R1       = host R1
@@ -264,13 +339,15 @@
 	 *
 	 */
 
-	/* RFI into the highmem handler */
-	mfmsr	r7
-	ori	r7, r7, MSR_IR|MSR_DR|MSR_RI|MSR_ME	/* Enable paging */
-	mtsrr1	r7
-	/* Load highmem handler address */
+	PPC_LL	r6, HSTATE_HOST_MSR(r13)
 	PPC_LL	r8, HSTATE_VMHANDLER(r13)
+
+	/* Restore host msr -> SRR1 */
+	mtsrr1	r6
+	/* Load highmem handler address */
 	mtsrr0	r8
 
+	/* RFI into the highmem handler, or jump to interrupt handler */
+	beqctr
 	RFI
 kvmppc_handler_trampoline_exit_end:
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/booke.c linux-libre-3.2-gnu/arch/powerpc/kvm/booke.c
--- linux-libre-3.1-gnu/arch/powerpc/kvm/booke.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/booke.c	2012-01-04 18:55:44.000000000 -0500
@@ -316,6 +316,11 @@
 {
 	int ret;
 
+	if (!vcpu->arch.sane) {
+		kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		return -EINVAL;
+	}
+
 	local_irq_disable();
 	kvm_guest_enter();
 	ret = __kvmppc_vcpu_run(kvm_run, vcpu);
@@ -618,6 +623,7 @@
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
 	int i;
+	int r;
 
 	vcpu->arch.pc = 0;
 	vcpu->arch.shared->msr = 0;
@@ -634,7 +640,9 @@
 
 	kvmppc_init_timing_stats(vcpu);
 
-	return kvmppc_core_vcpu_setup(vcpu);
+	r = kvmppc_core_vcpu_setup(vcpu);
+	kvmppc_sanity_check(vcpu);
+	return r;
 }
 
 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/e500.c linux-libre-3.2-gnu/arch/powerpc/kvm/e500.c
--- linux-libre-3.1-gnu/arch/powerpc/kvm/e500.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/e500.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/kvm_host.h>
 #include <linux/slab.h>
 #include <linux/err.h>
+#include <linux/export.h>
 
 #include <asm/reg.h>
 #include <asm/cputable.h>
@@ -73,6 +74,8 @@
 	/* Since booke kvm only support one core, update all vcpus' PIR to 0 */
 	vcpu->vcpu_id = 0;
 
+	vcpu->arch.cpu_type = KVM_CPU_E500V2;
+
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/Makefile linux-libre-3.2-gnu/arch/powerpc/kvm/Makefile
--- linux-libre-3.1-gnu/arch/powerpc/kvm/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -43,18 +43,22 @@
 	fpu.o \
 	book3s_paired_singles.o \
 	book3s_pr.o \
+	book3s_pr_papr.o \
 	book3s_emulate.o \
 	book3s_interrupts.o \
 	book3s_mmu_hpte.o \
 	book3s_64_mmu_host.o \
 	book3s_64_mmu.o \
 	book3s_32_mmu.o
+kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_PR) := \
+	book3s_rmhandlers.o
 
 kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
 	book3s_hv.o \
 	book3s_hv_interrupts.o \
 	book3s_64_mmu_hv.o
 kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
+	book3s_hv_rmhandlers.o \
 	book3s_hv_rm_mmu.o \
 	book3s_64_vio_hv.o \
 	book3s_hv_builtin.o
diff -druN linux-libre-3.1-gnu/arch/powerpc/kvm/powerpc.c linux-libre-3.2-gnu/arch/powerpc/kvm/powerpc.c
--- linux-libre-3.1-gnu/arch/powerpc/kvm/powerpc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/kvm/powerpc.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,6 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/kvm_host.h>
-#include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/hrtimer.h>
 #include <linux/fs.h>
@@ -39,12 +38,8 @@
 
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
 {
-#ifndef CONFIG_KVM_BOOK3S_64_HV
 	return !(v->arch.shared->msr & MSR_WE) ||
 	       !!(v->arch.pending_exceptions);
-#else
-	return !(v->arch.ceded) || !!(v->arch.pending_exceptions);
-#endif
 }
 
 int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
@@ -95,6 +90,31 @@
 	return r;
 }
 
+int kvmppc_sanity_check(struct kvm_vcpu *vcpu)
+{
+	int r = false;
+
+	/* We have to know what CPU to virtualize */
+	if (!vcpu->arch.pvr)
+		goto out;
+
+	/* PAPR only works with book3s_64 */
+	if ((vcpu->arch.cpu_type != KVM_CPU_3S_64) && vcpu->arch.papr_enabled)
+		goto out;
+
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+	/* HV KVM can only do PAPR mode for now */
+	if (!vcpu->arch.papr_enabled)
+		goto out;
+#endif
+
+	r = true;
+
+out:
+	vcpu->arch.sane = r;
+	return r ? 0 : -EINVAL;
+}
+
 int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu)
 {
 	enum emulation_result er;
@@ -188,6 +208,7 @@
 	case KVM_CAP_PPC_BOOKE_SREGS:
 #else
 	case KVM_CAP_PPC_SEGSTATE:
+	case KVM_CAP_PPC_PAPR:
 #endif
 	case KVM_CAP_PPC_UNSET_IRQ:
 	case KVM_CAP_PPC_IRQ_LEVEL:
@@ -258,6 +279,7 @@
 {
 	struct kvm_vcpu *vcpu;
 	vcpu = kvmppc_core_vcpu_create(kvm, id);
+	vcpu->arch.wqp = &vcpu->wq;
 	if (!IS_ERR(vcpu))
 		kvmppc_create_vcpu_debugfs(vcpu, id);
 	return vcpu;
@@ -289,8 +311,8 @@
 
 	kvmppc_core_queue_dec(vcpu);
 
-	if (waitqueue_active(&vcpu->wq)) {
-		wake_up_interruptible(&vcpu->wq);
+	if (waitqueue_active(vcpu->arch.wqp)) {
+		wake_up_interruptible(vcpu->arch.wqp);
 		vcpu->stat.halt_wakeup++;
 	}
 }
@@ -543,13 +565,15 @@
 
 int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
 {
-	if (irq->irq == KVM_INTERRUPT_UNSET)
+	if (irq->irq == KVM_INTERRUPT_UNSET) {
 		kvmppc_core_dequeue_external(vcpu, irq);
-	else
-		kvmppc_core_queue_external(vcpu, irq);
+		return 0;
+	}
 
-	if (waitqueue_active(&vcpu->wq)) {
-		wake_up_interruptible(&vcpu->wq);
+	kvmppc_core_queue_external(vcpu, irq);
+
+	if (waitqueue_active(vcpu->arch.wqp)) {
+		wake_up_interruptible(vcpu->arch.wqp);
 		vcpu->stat.halt_wakeup++;
 	} else if (vcpu->cpu != -1) {
 		smp_send_reschedule(vcpu->cpu);
@@ -571,11 +595,18 @@
 		r = 0;
 		vcpu->arch.osi_enabled = true;
 		break;
+	case KVM_CAP_PPC_PAPR:
+		r = 0;
+		vcpu->arch.papr_enabled = true;
+		break;
 	default:
 		r = -EINVAL;
 		break;
 	}
 
+	if (!r)
+		r = kvmppc_sanity_check(vcpu);
+
 	return r;
 }
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/lib/checksum_wrappers_64.c linux-libre-3.2-gnu/arch/powerpc/lib/checksum_wrappers_64.c
--- linux-libre-3.1-gnu/arch/powerpc/lib/checksum_wrappers_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/lib/checksum_wrappers_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
  *
  * Author: Anton Blanchard <anton@au.ibm.com>
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <asm/checksum.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/lib/devres.c linux-libre-3.2-gnu/arch/powerpc/lib/devres.c
--- linux-libre-3.1-gnu/arch/powerpc/lib/devres.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/lib/devres.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
 #include <linux/device.h>	/* devres_*(), devm_ioremap_release() */
 #include <linux/gfp.h>
 #include <linux/io.h>		/* ioremap_prot() */
-#include <linux/module.h>	/* EXPORT_SYMBOL() */
+#include <linux/export.h>	/* EXPORT_SYMBOL() */
 
 /**
  * devm_ioremap_prot - Managed ioremap_prot()
diff -druN linux-libre-3.1-gnu/arch/powerpc/lib/feature-fixups.c linux-libre-3.2-gnu/arch/powerpc/lib/feature-fixups.c
--- linux-libre-3.1-gnu/arch/powerpc/lib/feature-fixups.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/lib/feature-fixups.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
 #include <linux/init.h>
 #include <asm/cputable.h>
 #include <asm/code-patching.h>
+#include <asm/page.h>
+#include <asm/sections.h>
 
 
 struct fixup_entry {
@@ -128,6 +130,27 @@
 	}
 }
 
+void do_final_fixups(void)
+{
+#if defined(CONFIG_PPC64) && defined(CONFIG_RELOCATABLE)
+	int *src, *dest;
+	unsigned long length;
+
+	if (PHYSICAL_START == 0)
+		return;
+
+	src = (int *)(KERNELBASE + PHYSICAL_START);
+	dest = (int *)KERNELBASE;
+	length = (__end_interrupts - _stext) / sizeof(int);
+
+	while (length--) {
+		patch_instruction(dest, *src);
+		src++;
+		dest++;
+	}
+#endif
+}
+
 #ifdef CONFIG_FTR_FIXUP_SELFTEST
 
 #define check(x)	\
diff -druN linux-libre-3.1-gnu/arch/powerpc/lib/locks.c linux-libre-3.2-gnu/arch/powerpc/lib/locks.c
--- linux-libre-3.1-gnu/arch/powerpc/lib/locks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/lib/locks.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/stringify.h>
 #include <linux/smp.h>
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/lib/rheap.c linux-libre-3.2-gnu/arch/powerpc/lib/rheap.c
--- linux-libre-3.1-gnu/arch/powerpc/lib/rheap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/lib/rheap.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/mm.h>
 #include <linux/err.h>
 #include <linux/slab.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/Makefile linux-libre-3.2-gnu/arch/powerpc/Makefile
--- linux-libre-3.1-gnu/arch/powerpc/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -255,12 +255,6 @@
 		echo 'disable kernel modules' ; \
 		false ; \
 	fi
-	@if ! /bin/echo dssall | $(AS) -many -o $(TOUT) >/dev/null 2>&1 ; then \
-		echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build ' ; \
-		echo 'correctly with old versions of binutils.' ; \
-		echo '*** Please upgrade your binutils to 2.12.1 or newer' ; \
-		false ; \
-	fi
 
 CLEAN_FILES += $(TOUT)
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/math-emu/math_efp.c linux-libre-3.2-gnu/arch/powerpc/math-emu/math_efp.c
--- linux-libre-3.1-gnu/arch/powerpc/math-emu/math_efp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/math-emu/math_efp.c	2012-01-04 18:55:44.000000000 -0500
@@ -171,10 +171,6 @@
 	case EFDNABS:	ret = XA;	break;
 	case EFDNEG:	ret = XA;	break;
 	case EFDSUB:	ret = AB;	break;
-
-	default:
-		printk(KERN_ERR "\nOoops! SPE instruction no type found.");
-		printk(KERN_ERR "\ninst code: %08lx\n", speinsn);
 	}
 
 	return ret;
@@ -195,7 +191,7 @@
 
 	type = insn_type(speinsn);
 	if (type == NOTYPE)
-		return -ENOSYS;
+		goto illegal;
 
 	func = speinsn & 0x7ff;
 	fc = (speinsn >> 21) & 0x1f;
@@ -212,12 +208,10 @@
 
 	__FPU_FPSCR = mfspr(SPRN_SPEFSCR);
 
-#ifdef DEBUG
-	printk("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
-	printk("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
-	printk("va: %08x  %08x\n", va.wp[0], va.wp[1]);
-	printk("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
-#endif
+	pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
+	pr_debug("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
+	pr_debug("va: %08x  %08x\n", va.wp[0], va.wp[1]);
+	pr_debug("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
 
 	switch (src) {
 	case SPFP: {
@@ -235,10 +229,8 @@
 			break;
 		}
 
-#ifdef DEBUG
-		printk("SA: %ld %08lx %ld (%ld)\n", SA_s, SA_f, SA_e, SA_c);
-		printk("SB: %ld %08lx %ld (%ld)\n", SB_s, SB_f, SB_e, SB_c);
-#endif
+		pr_debug("SA: %ld %08lx %ld (%ld)\n", SA_s, SA_f, SA_e, SA_c);
+		pr_debug("SB: %ld %08lx %ld (%ld)\n", SB_s, SB_f, SB_e, SB_c);
 
 		switch (func) {
 		case EFSABS:
@@ -305,10 +297,10 @@
 			FP_DECL_D(DB);
 			FP_CLEAR_EXCEPTIONS;
 			FP_UNPACK_DP(DB, vb.dp);
-#ifdef DEBUG
-			printk("DB: %ld %08lx %08lx %ld (%ld)\n",
+
+			pr_debug("DB: %ld %08lx %08lx %ld (%ld)\n",
 					DB_s, DB_f1, DB_f0, DB_e, DB_c);
-#endif
+
 			FP_CONV(S, D, 1, 2, SR, DB);
 			goto pack_s;
 		}
@@ -332,9 +324,8 @@
 		break;
 
 pack_s:
-#ifdef DEBUG
-		printk("SR: %ld %08lx %ld (%ld)\n", SR_s, SR_f, SR_e, SR_c);
-#endif
+		pr_debug("SR: %ld %08lx %ld (%ld)\n", SR_s, SR_f, SR_e, SR_c);
+
 		FP_PACK_SP(vc.wp + 1, SR);
 		goto update_regs;
 
@@ -365,12 +356,10 @@
 			break;
 		}
 
-#ifdef DEBUG
-		printk("DA: %ld %08lx %08lx %ld (%ld)\n",
+		pr_debug("DA: %ld %08lx %08lx %ld (%ld)\n",
 				DA_s, DA_f1, DA_f0, DA_e, DA_c);
-		printk("DB: %ld %08lx %08lx %ld (%ld)\n",
+		pr_debug("DB: %ld %08lx %08lx %ld (%ld)\n",
 				DB_s, DB_f1, DB_f0, DB_e, DB_c);
-#endif
 
 		switch (func) {
 		case EFDABS:
@@ -438,10 +427,10 @@
 			FP_DECL_S(SB);
 			FP_CLEAR_EXCEPTIONS;
 			FP_UNPACK_SP(SB, vb.wp + 1);
-#ifdef DEBUG
-			printk("SB: %ld %08lx %ld (%ld)\n",
+
+			pr_debug("SB: %ld %08lx %ld (%ld)\n",
 					SB_s, SB_f, SB_e, SB_c);
-#endif
+
 			FP_CONV(D, S, 2, 1, DR, SB);
 			goto pack_d;
 		}
@@ -471,10 +460,9 @@
 		break;
 
 pack_d:
-#ifdef DEBUG
-		printk("DR: %ld %08lx %08lx %ld (%ld)\n",
+		pr_debug("DR: %ld %08lx %08lx %ld (%ld)\n",
 				DR_s, DR_f1, DR_f0, DR_e, DR_c);
-#endif
+
 		FP_PACK_DP(vc.dp, DR);
 		goto update_regs;
 
@@ -511,12 +499,14 @@
 			break;
 		}
 
-#ifdef DEBUG
-		printk("SA0: %ld %08lx %ld (%ld)\n", SA0_s, SA0_f, SA0_e, SA0_c);
-		printk("SA1: %ld %08lx %ld (%ld)\n", SA1_s, SA1_f, SA1_e, SA1_c);
-		printk("SB0: %ld %08lx %ld (%ld)\n", SB0_s, SB0_f, SB0_e, SB0_c);
-		printk("SB1: %ld %08lx %ld (%ld)\n", SB1_s, SB1_f, SB1_e, SB1_c);
-#endif
+		pr_debug("SA0: %ld %08lx %ld (%ld)\n",
+				SA0_s, SA0_f, SA0_e, SA0_c);
+		pr_debug("SA1: %ld %08lx %ld (%ld)\n",
+				SA1_s, SA1_f, SA1_e, SA1_c);
+		pr_debug("SB0: %ld %08lx %ld (%ld)\n",
+				SB0_s, SB0_f, SB0_e, SB0_c);
+		pr_debug("SB1: %ld %08lx %ld (%ld)\n",
+				SB1_s, SB1_f, SB1_e, SB1_c);
 
 		switch (func) {
 		case EVFSABS:
@@ -605,10 +595,11 @@
 		break;
 
 pack_vs:
-#ifdef DEBUG
-		printk("SR0: %ld %08lx %ld (%ld)\n", SR0_s, SR0_f, SR0_e, SR0_c);
-		printk("SR1: %ld %08lx %ld (%ld)\n", SR1_s, SR1_f, SR1_e, SR1_c);
-#endif
+		pr_debug("SR0: %ld %08lx %ld (%ld)\n",
+				SR0_s, SR0_f, SR0_e, SR0_c);
+		pr_debug("SR1: %ld %08lx %ld (%ld)\n",
+				SR1_s, SR1_f, SR1_e, SR1_c);
+
 		FP_PACK_SP(vc.wp, SR0);
 		FP_PACK_SP(vc.wp + 1, SR1);
 		goto update_regs;
@@ -646,14 +637,12 @@
 	current->thread.evr[fc] = vc.wp[0];
 	regs->gpr[fc] = vc.wp[1];
 
-#ifdef DEBUG
-	printk("ccr = %08lx\n", regs->ccr);
-	printk("cur exceptions = %08x spefscr = %08lx\n",
+	pr_debug("ccr = %08lx\n", regs->ccr);
+	pr_debug("cur exceptions = %08x spefscr = %08lx\n",
 			FP_CUR_EXCEPTIONS, __FPU_FPSCR);
-	printk("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
-	printk("va: %08x  %08x\n", va.wp[0], va.wp[1]);
-	printk("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
-#endif
+	pr_debug("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
+	pr_debug("va: %08x  %08x\n", va.wp[0], va.wp[1]);
+	pr_debug("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
 
 	return 0;
 
@@ -661,9 +650,7 @@
 	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
+		pr_debug("re-issue efp inst: %08lx\n", speinsn);
 		return 0;
 	}
 
@@ -685,13 +672,20 @@
 	type = insn_type(speinsn & 0x7ff);
 	if (type == XCR) return -ENOSYS;
 
+	__FPU_FPSCR = mfspr(SPRN_SPEFSCR);
+	pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
+
+	/* No need to round if the result is exact */
+	if (!(__FPU_FPSCR & FP_EX_INEXACT))
+		return 0;
+
 	fc = (speinsn >> 21) & 0x1f;
 	s_lo = regs->gpr[fc] & SIGN_BIT_S;
 	s_hi = current->thread.evr[fc] & SIGN_BIT_S;
 	fgpr.wp[0] = current->thread.evr[fc];
 	fgpr.wp[1] = regs->gpr[fc];
 
-	__FPU_FPSCR = mfspr(SPRN_SPEFSCR);
+	pr_debug("round fgpr: %08x  %08x\n", fgpr.wp[0], fgpr.wp[1]);
 
 	switch ((speinsn >> 5) & 0x7) {
 	/* Since SPE instructions on E500 core can handle round to nearest
@@ -731,6 +725,8 @@
 	current->thread.evr[fc] = fgpr.wp[0];
 	regs->gpr[fc] = fgpr.wp[1];
 
+	pr_debug("  to fgpr: %08x  %08x\n", fgpr.wp[0], fgpr.wp[1]);
+
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/dma-noncoherent.c linux-libre-3.2-gnu/arch/powerpc/mm/dma-noncoherent.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/dma-noncoherent.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/dma-noncoherent.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/types.h>
 #include <linux/highmem.h>
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 
 #include <asm/tlbflush.h>
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/fsl_booke_mmu.c linux-libre-3.2-gnu/arch/powerpc/mm/fsl_booke_mmu.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/fsl_booke_mmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/fsl_booke_mmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -101,17 +101,17 @@
 
 /*
  * Set up a variable-size TLB entry (tlbcam). The parameters are not checked;
- * in particular size must be a power of 4 between 4k and 256M (or 1G, for cpus
- * that support extended page sizes).  Note that while some cpus support a
- * page size of 4G, we don't allow its use here.
+ * in particular size must be a power of 4 between 4k and the max supported by
+ * an implementation; max may further be limited by what can be represented in
+ * an unsigned long (for example, 32-bit implementations cannot support a 4GB
+ * size).
  */
 static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
 		unsigned long size, unsigned long flags, unsigned int pid)
 {
-	unsigned int tsize, lz;
+	unsigned int tsize;
 
-	asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (size));
-	tsize = 21 - lz;
+	tsize = __ilog2(size) - 10;
 
 #ifdef CONFIG_SMP
 	if ((flags & _PAGE_NO_CACHE) == 0)
@@ -146,29 +146,36 @@
 	loadcam_entry(index);
 }
 
+unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
+			  phys_addr_t phys)
+{
+	unsigned int camsize = __ilog2(ram) & ~1U;
+	unsigned int align = __ffs(virt | phys) & ~1U;
+	unsigned long max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf;
+
+	/* Convert (4^max) kB to (2^max) bytes */
+	max_cam = max_cam * 2 + 10;
+
+	if (camsize > align)
+		camsize = align;
+	if (camsize > max_cam)
+		camsize = max_cam;
+
+	return 1UL << camsize;
+}
+
 unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx)
 {
 	int i;
 	unsigned long virt = PAGE_OFFSET;
 	phys_addr_t phys = memstart_addr;
 	unsigned long amount_mapped = 0;
-	unsigned long max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf;
-
-	/* Convert (4^max) kB to (2^max) bytes */
-	max_cam = max_cam * 2 + 10;
 
 	/* Calculate CAM values */
 	for (i = 0; ram && i < max_cam_idx; i++) {
-		unsigned int camsize = __ilog2(ram) & ~1U;
-		unsigned int align = __ffs(virt | phys) & ~1U;
 		unsigned long cam_sz;
 
-		if (camsize > align)
-			camsize = align;
-		if (camsize > max_cam)
-			camsize = max_cam;
-
-		cam_sz = 1UL << camsize;
+		cam_sz = calc_cam_sz(ram, virt, phys);
 		settlbcam(i, virt, phys, cam_sz, PAGE_KERNEL_X, 0);
 
 		ram -= cam_sz;
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/gup.c linux-libre-3.2-gnu/arch/powerpc/mm/gup.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/gup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/gup.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,16 +16,6 @@
 
 #ifdef __HAVE_ARCH_PTE_SPECIAL
 
-static inline void get_huge_page_tail(struct page *page)
-{
-	/*
-	 * __split_huge_page_refcount() cannot run
-	 * from under us.
-	 */
-	VM_BUG_ON(atomic_read(&page->_count) < 0);
-	atomic_inc(&page->_count);
-}
-
 /*
  * The performance critical leaf functions are made noinline otherwise gcc
  * inlines everything into a single function which results in too much
@@ -57,8 +47,6 @@
 			put_page(page);
 			return 0;
 		}
-		if (PageTail(page))
-			get_huge_page_tail(page);
 		pages[*nr] = page;
 		(*nr)++;
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/hash_utils_64.c linux-libre-3.2-gnu/arch/powerpc/mm/hash_utils_64.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/hash_utils_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/hash_utils_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/sysctl.h>
+#include <linux/export.h>
 #include <linux/ctype.h>
 #include <linux/cache.h>
 #include <linux/init.h>
@@ -105,9 +106,6 @@
 int mmu_highuser_ssize = MMU_SEGSIZE_256M;
 u16 mmu_slb_size = 64;
 EXPORT_SYMBOL_GPL(mmu_slb_size);
-#ifdef CONFIG_HUGETLB_PAGE
-unsigned int HPAGE_SHIFT;
-#endif
 #ifdef CONFIG_PPC_64K_PAGES
 int mmu_ci_restrictions;
 #endif
@@ -534,11 +532,11 @@
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-void create_section_mapping(unsigned long start, unsigned long end)
+int create_section_mapping(unsigned long start, unsigned long end)
 {
-	BUG_ON(htab_bolt_mapping(start, end, __pa(start),
+	return htab_bolt_mapping(start, end, __pa(start),
 				 pgprot_val(PAGE_KERNEL), mmu_linear_psize,
-				 mmu_kernel_ssize));
+				 mmu_kernel_ssize);
 }
 
 int remove_section_mapping(unsigned long start, unsigned long end)
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/hugetlbpage-book3e.c linux-libre-3.2-gnu/arch/powerpc/mm/hugetlbpage-book3e.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/hugetlbpage-book3e.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/mm/hugetlbpage-book3e.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,121 @@
+/*
+ * PPC Huge TLB Page Support for Book3E MMU
+ *
+ * Copyright (C) 2009 David Gibson, IBM Corporation.
+ * Copyright (C) 2011 Becky Bruce, Freescale Semiconductor
+ *
+ */
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+
+static inline int mmu_get_tsize(int psize)
+{
+	return mmu_psize_defs[psize].enc;
+}
+
+static inline int book3e_tlb_exists(unsigned long ea, unsigned long pid)
+{
+	int found = 0;
+
+	mtspr(SPRN_MAS6, pid << 16);
+	if (mmu_has_feature(MMU_FTR_USE_TLBRSRV)) {
+		asm volatile(
+			"li	%0,0\n"
+			"tlbsx.	0,%1\n"
+			"bne	1f\n"
+			"li	%0,1\n"
+			"1:\n"
+			: "=&r"(found) : "r"(ea));
+	} else {
+		asm volatile(
+			"tlbsx	0,%1\n"
+			"mfspr	%0,0x271\n"
+			"srwi	%0,%0,31\n"
+			: "=&r"(found) : "r"(ea));
+	}
+
+	return found;
+}
+
+void book3e_hugetlb_preload(struct mm_struct *mm, unsigned long ea, pte_t pte)
+{
+	unsigned long mas1, mas2;
+	u64 mas7_3;
+	unsigned long psize, tsize, shift;
+	unsigned long flags;
+
+#ifdef CONFIG_PPC_FSL_BOOK3E
+	int index, lz, ncams;
+	struct vm_area_struct *vma;
+#endif
+
+	if (unlikely(is_kernel_addr(ea)))
+		return;
+
+#ifdef CONFIG_PPC_MM_SLICES
+	psize = mmu_get_tsize(get_slice_psize(mm, ea));
+	tsize = mmu_get_psize(psize);
+	shift = mmu_psize_defs[psize].shift;
+#else
+	vma = find_vma(mm, ea);
+	psize = vma_mmu_pagesize(vma);	/* returns actual size in bytes */
+	asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (psize));
+	shift = 31 - lz;
+	tsize = 21 - lz;
+#endif
+
+	/*
+	 * We can't be interrupted while we're setting up the MAS
+	 * regusters or after we've confirmed that no tlb exists.
+	 */
+	local_irq_save(flags);
+
+	if (unlikely(book3e_tlb_exists(ea, mm->context.id))) {
+		local_irq_restore(flags);
+		return;
+	}
+
+#ifdef CONFIG_PPC_FSL_BOOK3E
+	ncams = mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY;
+
+	/* We have to use the CAM(TLB1) on FSL parts for hugepages */
+	index = __get_cpu_var(next_tlbcam_idx);
+	mtspr(SPRN_MAS0, MAS0_ESEL(index) | MAS0_TLBSEL(1));
+
+	/* Just round-robin the entries and wrap when we hit the end */
+	if (unlikely(index == ncams - 1))
+		__get_cpu_var(next_tlbcam_idx) = tlbcam_index;
+	else
+		__get_cpu_var(next_tlbcam_idx)++;
+#endif
+	mas1 = MAS1_VALID | MAS1_TID(mm->context.id) | MAS1_TSIZE(tsize);
+	mas2 = ea & ~((1UL << shift) - 1);
+	mas2 |= (pte_val(pte) >> PTE_WIMGE_SHIFT) & MAS2_WIMGE_MASK;
+	mas7_3 = (u64)pte_pfn(pte) << PAGE_SHIFT;
+	mas7_3 |= (pte_val(pte) >> PTE_BAP_SHIFT) & MAS3_BAP_MASK;
+	if (!pte_dirty(pte))
+		mas7_3 &= ~(MAS3_SW|MAS3_UW);
+
+	mtspr(SPRN_MAS1, mas1);
+	mtspr(SPRN_MAS2, mas2);
+
+	if (mmu_has_feature(MMU_FTR_USE_PAIRED_MAS)) {
+		mtspr(SPRN_MAS7_MAS3, mas7_3);
+	} else {
+		mtspr(SPRN_MAS7, upper_32_bits(mas7_3));
+		mtspr(SPRN_MAS3, lower_32_bits(mas7_3));
+	}
+
+	asm volatile ("tlbwe");
+
+	local_irq_restore(flags);
+}
+
+void flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
+{
+	struct hstate *hstate = hstate_file(vma->vm_file);
+	unsigned long tsize = huge_page_shift(hstate) - 10;
+
+	__flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr, tsize, 0);
+
+}
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/hugetlbpage.c linux-libre-3.2-gnu/arch/powerpc/mm/hugetlbpage.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/hugetlbpage.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/hugetlbpage.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,8 @@
 /*
- * PPC64 (POWER4) Huge TLB Page Support for Kernel.
+ * PPC Huge TLB Page Support for Kernel.
  *
  * Copyright (C) 2003 David Gibson, IBM Corporation.
+ * Copyright (C) 2011 Becky Bruce, Freescale Semiconductor
  *
  * Based on the IA-32 version:
  * Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com>
@@ -11,24 +12,40 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/hugetlb.h>
+#include <linux/of_fdt.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+#include <linux/moduleparam.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
+#include <asm/setup.h>
 
 #define PAGE_SHIFT_64K	16
 #define PAGE_SHIFT_16M	24
 #define PAGE_SHIFT_16G	34
 
-#define MAX_NUMBER_GPAGES	1024
+unsigned int HPAGE_SHIFT;
 
-/* Tracks the 16G pages after the device tree is scanned and before the
- * huge_boot_pages list is ready.  */
-static unsigned long gpage_freearray[MAX_NUMBER_GPAGES];
+/*
+ * Tracks gpages after the device tree is scanned and before the
+ * huge_boot_pages list is ready.  On 64-bit implementations, this is
+ * just used to track 16G pages and so is a single array.  32-bit
+ * implementations may have more than one gpage size due to limitations
+ * of the memory allocators, so we need multiple arrays
+ */
+#ifdef CONFIG_PPC64
+#define MAX_NUMBER_GPAGES	1024
+static u64 gpage_freearray[MAX_NUMBER_GPAGES];
 static unsigned nr_gpages;
-
-/* Flag to mark huge PD pointers.  This means pmd_bad() and pud_bad()
- * will choke on pointers to hugepte tables, which is handy for
- * catching screwups early. */
+#else
+#define MAX_NUMBER_GPAGES	128
+struct psize_gpages {
+	u64 gpage_list[MAX_NUMBER_GPAGES];
+	unsigned int nr_gpages;
+};
+static struct psize_gpages gpage_freearray[MMU_PAGE_COUNT];
+#endif
 
 static inline int shift_to_mmu_psize(unsigned int shift)
 {
@@ -49,25 +66,6 @@
 
 #define hugepd_none(hpd)	((hpd).pd == 0)
 
-static inline pte_t *hugepd_page(hugepd_t hpd)
-{
-	BUG_ON(!hugepd_ok(hpd));
-	return (pte_t *)((hpd.pd & ~HUGEPD_SHIFT_MASK) | 0xc000000000000000);
-}
-
-static inline unsigned int hugepd_shift(hugepd_t hpd)
-{
-	return hpd.pd & HUGEPD_SHIFT_MASK;
-}
-
-static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr, unsigned pdshift)
-{
-	unsigned long idx = (addr & ((1UL << pdshift) - 1)) >> hugepd_shift(*hpdp);
-	pte_t *dir = hugepd_page(*hpdp);
-
-	return dir + idx;
-}
-
 pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift)
 {
 	pgd_t *pg;
@@ -93,7 +91,7 @@
 			if (is_hugepd(pm))
 				hpdp = (hugepd_t *)pm;
 			else if (!pmd_none(*pm)) {
-				return pte_offset_map(pm, ea);
+				return pte_offset_kernel(pm, ea);
 			}
 		}
 	}
@@ -114,8 +112,18 @@
 static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
 			   unsigned long address, unsigned pdshift, unsigned pshift)
 {
-	pte_t *new = kmem_cache_zalloc(PGT_CACHE(pdshift - pshift),
-				       GFP_KERNEL|__GFP_REPEAT);
+	struct kmem_cache *cachep;
+	pte_t *new;
+
+#ifdef CONFIG_PPC64
+	cachep = PGT_CACHE(pdshift - pshift);
+#else
+	int i;
+	int num_hugepd = 1 << (pshift - pdshift);
+	cachep = hugepte_cache;
+#endif
+
+	new = kmem_cache_zalloc(cachep, GFP_KERNEL|__GFP_REPEAT);
 
 	BUG_ON(pshift > HUGEPD_SHIFT_MASK);
 	BUG_ON((unsigned long)new & HUGEPD_SHIFT_MASK);
@@ -124,10 +132,31 @@
 		return -ENOMEM;
 
 	spin_lock(&mm->page_table_lock);
+#ifdef CONFIG_PPC64
 	if (!hugepd_none(*hpdp))
-		kmem_cache_free(PGT_CACHE(pdshift - pshift), new);
+		kmem_cache_free(cachep, new);
 	else
-		hpdp->pd = ((unsigned long)new & ~0x8000000000000000) | pshift;
+		hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift;
+#else
+	/*
+	 * We have multiple higher-level entries that point to the same
+	 * actual pte location.  Fill in each as we go and backtrack on error.
+	 * We need all of these so the DTLB pgtable walk code can find the
+	 * right higher-level entry without knowing if it's a hugepage or not.
+	 */
+	for (i = 0; i < num_hugepd; i++, hpdp++) {
+		if (unlikely(!hugepd_none(*hpdp)))
+			break;
+		else
+			hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift;
+	}
+	/* If we bailed from the for loop early, an error occurred, clean up */
+	if (i < num_hugepd) {
+		for (i = i - 1 ; i >= 0; i--, hpdp--)
+			hpdp->pd = 0;
+		kmem_cache_free(cachep, new);
+	}
+#endif
 	spin_unlock(&mm->page_table_lock);
 	return 0;
 }
@@ -169,11 +198,132 @@
 	return hugepte_offset(hpdp, addr, pdshift);
 }
 
+#ifdef CONFIG_PPC32
 /* Build list of addresses of gigantic pages.  This function is used in early
  * boot before the buddy or bootmem allocator is setup.
  */
-void add_gpage(unsigned long addr, unsigned long page_size,
-	unsigned long number_of_pages)
+void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages)
+{
+	unsigned int idx = shift_to_mmu_psize(__ffs(page_size));
+	int i;
+
+	if (addr == 0)
+		return;
+
+	gpage_freearray[idx].nr_gpages = number_of_pages;
+
+	for (i = 0; i < number_of_pages; i++) {
+		gpage_freearray[idx].gpage_list[i] = addr;
+		addr += page_size;
+	}
+}
+
+/*
+ * Moves the gigantic page addresses from the temporary list to the
+ * huge_boot_pages list.
+ */
+int alloc_bootmem_huge_page(struct hstate *hstate)
+{
+	struct huge_bootmem_page *m;
+	int idx = shift_to_mmu_psize(hstate->order + PAGE_SHIFT);
+	int nr_gpages = gpage_freearray[idx].nr_gpages;
+
+	if (nr_gpages == 0)
+		return 0;
+
+#ifdef CONFIG_HIGHMEM
+	/*
+	 * If gpages can be in highmem we can't use the trick of storing the
+	 * data structure in the page; allocate space for this
+	 */
+	m = alloc_bootmem(sizeof(struct huge_bootmem_page));
+	m->phys = gpage_freearray[idx].gpage_list[--nr_gpages];
+#else
+	m = phys_to_virt(gpage_freearray[idx].gpage_list[--nr_gpages]);
+#endif
+
+	list_add(&m->list, &huge_boot_pages);
+	gpage_freearray[idx].nr_gpages = nr_gpages;
+	gpage_freearray[idx].gpage_list[nr_gpages] = 0;
+	m->hstate = hstate;
+
+	return 1;
+}
+/*
+ * Scan the command line hugepagesz= options for gigantic pages; store those in
+ * a list that we use to allocate the memory once all options are parsed.
+ */
+
+unsigned long gpage_npages[MMU_PAGE_COUNT];
+
+static int __init do_gpage_early_setup(char *param, char *val)
+{
+	static phys_addr_t size;
+	unsigned long npages;
+
+	/*
+	 * The hugepagesz and hugepages cmdline options are interleaved.  We
+	 * use the size variable to keep track of whether or not this was done
+	 * properly and skip over instances where it is incorrect.  Other
+	 * command-line parsing code will issue warnings, so we don't need to.
+	 *
+	 */
+	if ((strcmp(param, "default_hugepagesz") == 0) ||
+	    (strcmp(param, "hugepagesz") == 0)) {
+		size = memparse(val, NULL);
+	} else if (strcmp(param, "hugepages") == 0) {
+		if (size != 0) {
+			if (sscanf(val, "%lu", &npages) <= 0)
+				npages = 0;
+			gpage_npages[shift_to_mmu_psize(__ffs(size))] = npages;
+			size = 0;
+		}
+	}
+	return 0;
+}
+
+
+/*
+ * This function allocates physical space for pages that are larger than the
+ * buddy allocator can handle.  We want to allocate these in highmem because
+ * the amount of lowmem is limited.  This means that this function MUST be
+ * called before lowmem_end_addr is set up in MMU_init() in order for the lmb
+ * allocate to grab highmem.
+ */
+void __init reserve_hugetlb_gpages(void)
+{
+	static __initdata char cmdline[COMMAND_LINE_SIZE];
+	phys_addr_t size, base;
+	int i;
+
+	strlcpy(cmdline, boot_command_line, COMMAND_LINE_SIZE);
+	parse_args("hugetlb gpages", cmdline, NULL, 0, &do_gpage_early_setup);
+
+	/*
+	 * Walk gpage list in reverse, allocating larger page sizes first.
+	 * Skip over unsupported sizes, or sizes that have 0 gpages allocated.
+	 * When we reach the point in the list where pages are no longer
+	 * considered gpages, we're done.
+	 */
+	for (i = MMU_PAGE_COUNT-1; i >= 0; i--) {
+		if (mmu_psize_defs[i].shift == 0 || gpage_npages[i] == 0)
+			continue;
+		else if (mmu_psize_to_shift(i) < (MAX_ORDER + PAGE_SHIFT))
+			break;
+
+		size = (phys_addr_t)(1ULL << mmu_psize_to_shift(i));
+		base = memblock_alloc_base(size * gpage_npages[i], size,
+					   MEMBLOCK_ALLOC_ANYWHERE);
+		add_gpage(base, size, gpage_npages[i]);
+	}
+}
+
+#else /* PPC64 */
+
+/* Build list of addresses of gigantic pages.  This function is used in early
+ * boot before the buddy or bootmem allocator is setup.
+ */
+void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages)
 {
 	if (!addr)
 		return;
@@ -199,19 +349,79 @@
 	m->hstate = hstate;
 	return 1;
 }
+#endif
 
 int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
 {
 	return 0;
 }
 
+#ifdef CONFIG_PPC32
+#define HUGEPD_FREELIST_SIZE \
+	((PAGE_SIZE - sizeof(struct hugepd_freelist)) / sizeof(pte_t))
+
+struct hugepd_freelist {
+	struct rcu_head	rcu;
+	unsigned int index;
+	void *ptes[0];
+};
+
+static DEFINE_PER_CPU(struct hugepd_freelist *, hugepd_freelist_cur);
+
+static void hugepd_free_rcu_callback(struct rcu_head *head)
+{
+	struct hugepd_freelist *batch =
+		container_of(head, struct hugepd_freelist, rcu);
+	unsigned int i;
+
+	for (i = 0; i < batch->index; i++)
+		kmem_cache_free(hugepte_cache, batch->ptes[i]);
+
+	free_page((unsigned long)batch);
+}
+
+static void hugepd_free(struct mmu_gather *tlb, void *hugepte)
+{
+	struct hugepd_freelist **batchp;
+
+	batchp = &__get_cpu_var(hugepd_freelist_cur);
+
+	if (atomic_read(&tlb->mm->mm_users) < 2 ||
+	    cpumask_equal(mm_cpumask(tlb->mm),
+			  cpumask_of(smp_processor_id()))) {
+		kmem_cache_free(hugepte_cache, hugepte);
+		return;
+	}
+
+	if (*batchp == NULL) {
+		*batchp = (struct hugepd_freelist *)__get_free_page(GFP_ATOMIC);
+		(*batchp)->index = 0;
+	}
+
+	(*batchp)->ptes[(*batchp)->index++] = hugepte;
+	if ((*batchp)->index == HUGEPD_FREELIST_SIZE) {
+		call_rcu_sched(&(*batchp)->rcu, hugepd_free_rcu_callback);
+		*batchp = NULL;
+	}
+}
+#endif
+
 static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshift,
 			      unsigned long start, unsigned long end,
 			      unsigned long floor, unsigned long ceiling)
 {
 	pte_t *hugepte = hugepd_page(*hpdp);
-	unsigned shift = hugepd_shift(*hpdp);
+	int i;
+
 	unsigned long pdmask = ~((1UL << pdshift) - 1);
+	unsigned int num_hugepd = 1;
+
+#ifdef CONFIG_PPC64
+	unsigned int shift = hugepd_shift(*hpdp);
+#else
+	/* Note: On 32-bit the hpdp may be the first of several */
+	num_hugepd = (1 << (hugepd_shift(*hpdp) - pdshift));
+#endif
 
 	start &= pdmask;
 	if (start < floor)
@@ -224,9 +434,15 @@
 	if (end - 1 > ceiling - 1)
 		return;
 
-	hpdp->pd = 0;
+	for (i = 0; i < num_hugepd; i++, hpdp++)
+		hpdp->pd = 0;
+
 	tlb->need_flush = 1;
+#ifdef CONFIG_PPC64
 	pgtable_free_tlb(tlb, hugepte, pdshift - shift);
+#else
+	hugepd_free(tlb, hugepte);
+#endif
 }
 
 static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
@@ -331,18 +547,27 @@
 	 * too.
 	 */
 
-	pgd = pgd_offset(tlb->mm, addr);
 	do {
 		next = pgd_addr_end(addr, end);
+		pgd = pgd_offset(tlb->mm, addr);
 		if (!is_hugepd(pgd)) {
 			if (pgd_none_or_clear_bad(pgd))
 				continue;
 			hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling);
 		} else {
+#ifdef CONFIG_PPC32
+			/*
+			 * Increment next by the size of the huge mapping since
+			 * on 32-bit there may be more than one entry at the pgd
+			 * level for a single hugepage, but all of them point to
+			 * the same kmem cache that holds the hugepte.
+			 */
+			next = addr + (1 << hugepd_shift(*(hugepd_t *)pgd));
+#endif
 			free_hugepd_range(tlb, (hugepd_t *)pgd, PGDIR_SHIFT,
 					  addr, next, floor, ceiling);
 		}
-	} while (pgd++, addr = next, addr != end);
+	} while (addr = next, addr != end);
 }
 
 struct page *
@@ -390,7 +615,7 @@
 {
 	unsigned long mask;
 	unsigned long pte_end;
-	struct page *head, *page;
+	struct page *head, *page, *tail;
 	pte_t pte;
 	int refs;
 
@@ -413,6 +638,7 @@
 	head = pte_page(pte);
 
 	page = head + ((addr & (sz-1)) >> PAGE_SHIFT);
+	tail = page;
 	do {
 		VM_BUG_ON(compound_head(page) != head);
 		pages[*nr] = page;
@@ -428,10 +654,20 @@
 
 	if (unlikely(pte_val(pte) != pte_val(*ptep))) {
 		/* Could be optimized better */
-		while (*nr) {
-			put_page(page);
-			(*nr)--;
-		}
+		*nr -= refs;
+		while (refs--)
+			put_page(head);
+		return 0;
+	}
+
+	/*
+	 * Any tail page need their mapcount reference taken before we
+	 * return.
+	 */
+	while (refs--) {
+		if (PageTail(tail))
+			get_huge_page_tail(tail);
+		tail++;
 	}
 
 	return 1;
@@ -466,17 +702,35 @@
 					unsigned long len, unsigned long pgoff,
 					unsigned long flags)
 {
+#ifdef CONFIG_PPC_MM_SLICES
 	struct hstate *hstate = hstate_file(file);
 	int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate));
 
 	return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0);
+#else
+	return get_unmapped_area(file, addr, len, pgoff, flags);
+#endif
 }
 
 unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)
 {
+#ifdef CONFIG_PPC_MM_SLICES
 	unsigned int psize = get_slice_psize(vma->vm_mm, vma->vm_start);
 
 	return 1UL << mmu_psize_to_shift(psize);
+#else
+	if (!is_vm_hugetlb_page(vma))
+		return PAGE_SIZE;
+
+	return huge_page_size(hstate_vma(vma));
+#endif
+}
+
+static inline bool is_power_of_4(unsigned long x)
+{
+	if (is_power_of_2(x))
+		return (__ilog2(x) % 2) ? false : true;
+	return false;
 }
 
 static int __init add_huge_page_size(unsigned long long size)
@@ -486,9 +740,14 @@
 
 	/* Check that it is a page size supported by the hardware and
 	 * that it fits within pagetable and slice limits. */
+#ifdef CONFIG_PPC_FSL_BOOK3E
+	if ((size < PAGE_SIZE) || !is_power_of_4(size))
+		return -EINVAL;
+#else
 	if (!is_power_of_2(size)
 	    || (shift > SLICE_HIGH_SHIFT) || (shift <= PAGE_SHIFT))
 		return -EINVAL;
+#endif
 
 	if ((mmu_psize = shift_to_mmu_psize(shift)) < 0)
 		return -EINVAL;
@@ -525,6 +784,46 @@
 }
 __setup("hugepagesz=", hugepage_setup_sz);
 
+#ifdef CONFIG_FSL_BOOKE
+struct kmem_cache *hugepte_cache;
+static int __init hugetlbpage_init(void)
+{
+	int psize;
+
+	for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
+		unsigned shift;
+
+		if (!mmu_psize_defs[psize].shift)
+			continue;
+
+		shift = mmu_psize_to_shift(psize);
+
+		/* Don't treat normal page sizes as huge... */
+		if (shift != PAGE_SHIFT)
+			if (add_huge_page_size(1ULL << shift) < 0)
+				continue;
+	}
+
+	/*
+	 * Create a kmem cache for hugeptes.  The bottom bits in the pte have
+	 * size information encoded in them, so align them to allow this
+	 */
+	hugepte_cache =  kmem_cache_create("hugepte-cache", sizeof(pte_t),
+					   HUGEPD_SHIFT_MASK + 1, 0, NULL);
+	if (hugepte_cache == NULL)
+		panic("%s: Unable to create kmem cache for hugeptes\n",
+		      __func__);
+
+	/* Default hpage size = 4M */
+	if (mmu_psize_defs[MMU_PAGE_4M].shift)
+		HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_4M].shift;
+	else
+		panic("%s: Unable to set default huge page size\n", __func__);
+
+
+	return 0;
+}
+#else
 static int __init hugetlbpage_init(void)
 {
 	int psize;
@@ -567,15 +866,23 @@
 
 	return 0;
 }
-
+#endif
 module_init(hugetlbpage_init);
 
 void flush_dcache_icache_hugepage(struct page *page)
 {
 	int i;
+	void *start;
 
 	BUG_ON(!PageCompound(page));
 
-	for (i = 0; i < (1UL << compound_order(page)); i++)
-		__flush_dcache_icache(page_address(page+i));
+	for (i = 0; i < (1UL << compound_order(page)); i++) {
+		if (!PageHighMem(page)) {
+			__flush_dcache_icache(page_address(page+i));
+		} else {
+			start = kmap_atomic(page+i, KM_PPC_SYNC_ICACHE);
+			__flush_dcache_icache(start);
+			kunmap_atomic(start, KM_PPC_SYNC_ICACHE);
+		}
+	}
 }
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/init_32.c linux-libre-3.2-gnu/arch/powerpc/mm/init_32.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/init_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/init_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,8 @@
 #include <linux/pagemap.h>
 #include <linux/memblock.h>
 #include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/hugetlb.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
@@ -44,6 +46,7 @@
 #include <asm/tlb.h>
 #include <asm/sections.h>
 #include <asm/system.h>
+#include <asm/hugetlb.h>
 
 #include "mmu_decl.h"
 
@@ -123,6 +126,12 @@
 	/* parse args from command line */
 	MMU_setup();
 
+	/*
+	 * Reserve gigantic pages for hugetlb.  This MUST occur before
+	 * lowmem_end_addr is initialized below.
+	 */
+	reserve_hugetlb_gpages();
+
 	if (memblock.memory.cnt > 1) {
 #ifndef CONFIG_WII
 		memblock.memory.cnt = 1;
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/Makefile linux-libre-3.2-gnu/arch/powerpc/mm/Makefile
--- linux-libre-3.1-gnu/arch/powerpc/mm/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 ifeq ($(CONFIG_HUGETLB_PAGE),y)
 obj-y				+= hugetlbpage.o
 obj-$(CONFIG_PPC_STD_MMU_64)	+= hugetlbpage-hash64.o
+obj-$(CONFIG_PPC_BOOK3E_MMU)	+= hugetlbpage-book3e.o
 endif
 obj-$(CONFIG_PPC_SUBPAGE_PROT)	+= subpage-prot.o
 obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/mem.c linux-libre-3.2-gnu/arch/powerpc/mm/mem.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/mem.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
  *
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -34,6 +34,7 @@
 #include <linux/suspend.h>
 #include <linux/memblock.h>
 #include <linux/hugetlb.h>
+#include <linux/slab.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
@@ -123,7 +124,8 @@
 	pgdata = NODE_DATA(nid);
 
 	start = (unsigned long)__va(start);
-	create_section_mapping(start, start + size);
+	if (create_section_mapping(start, start + size))
+		return -EINVAL;
 
 	/* this should work for most non-highmem platforms */
 	zone = pgdata->node_zones;
@@ -548,4 +550,38 @@
 		return;
 	hash_preload(vma->vm_mm, address, access, trap);
 #endif /* CONFIG_PPC_STD_MMU */
+#if (defined(CONFIG_PPC_BOOK3E_64) || defined(CONFIG_PPC_FSL_BOOK3E)) \
+	&& defined(CONFIG_HUGETLB_PAGE)
+	if (is_vm_hugetlb_page(vma))
+		book3e_hugetlb_preload(vma->vm_mm, address, *ptep);
+#endif
+}
+
+/*
+ * System memory should not be in /proc/iomem but various tools expect it
+ * (eg kdump).
+ */
+static int add_system_ram_resources(void)
+{
+	struct memblock_region *reg;
+
+	for_each_memblock(memory, reg) {
+		struct resource *res;
+		unsigned long base = reg->base;
+		unsigned long size = reg->size;
+
+		res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+		WARN_ON(!res);
+
+		if (res) {
+			res->name = "System RAM";
+			res->start = base;
+			res->end = base + size - 1;
+			res->flags = IORESOURCE_MEM;
+			WARN_ON(request_resource(&iomem_resource, res) < 0);
+		}
+	}
+
+	return 0;
 }
+subsys_initcall(add_system_ram_resources);
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/mmu_context_hash32.c linux-libre-3.2-gnu/arch/powerpc/mm/mmu_context_hash32.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/mmu_context_hash32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/mmu_context_hash32.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/export.h>
 
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/mmu_context_hash64.c linux-libre-3.2-gnu/arch/powerpc/mm/mmu_context_hash64.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/mmu_context_hash64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/mmu_context_hash64.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <linux/idr.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/gfp.h>
 #include <linux/slab.h>
 
@@ -136,8 +136,8 @@
 	if (!mm || !acop)
 		return -EINVAL;
 
-	/* We need to make sure mm_users doesn't change */
-	down_read(&mm->mmap_sem);
+	/* The page_table_lock ensures mm_users won't change under us */
+	spin_lock(&mm->page_table_lock);
 	spin_lock(mm->context.cop_lockp);
 
 	if (mm->context.cop_pid == COP_PID_NONE) {
@@ -164,7 +164,7 @@
 
 out:
 	spin_unlock(mm->context.cop_lockp);
-	up_read(&mm->mmap_sem);
+	spin_unlock(&mm->page_table_lock);
 
 	return ret;
 }
@@ -185,8 +185,8 @@
 	if (WARN_ON_ONCE(!mm))
 		return;
 
-	/* We need to make sure mm_users doesn't change */
-	down_read(&mm->mmap_sem);
+	/* The page_table_lock ensures mm_users won't change under us */
+	spin_lock(&mm->page_table_lock);
 	spin_lock(mm->context.cop_lockp);
 
 	mm->context.acop &= ~acop;
@@ -213,7 +213,7 @@
 	}
 
 	spin_unlock(mm->context.cop_lockp);
-	up_read(&mm->mmap_sem);
+	spin_unlock(&mm->page_table_lock);
 }
 EXPORT_SYMBOL_GPL(drop_cop);
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/mmu_context_nohash.c linux-libre-3.2-gnu/arch/powerpc/mm/mmu_context_nohash.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/mmu_context_nohash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/mmu_context_nohash.c	2012-01-04 18:55:44.000000000 -0500
@@ -292,6 +292,11 @@
 	mm->context.id = MMU_NO_CONTEXT;
 	mm->context.active = 0;
 
+#ifdef CONFIG_PPC_MM_SLICES
+	if (slice_mm_new_context(mm))
+		slice_set_user_psize(mm, mmu_virtual_psize);
+#endif
+
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/mmu_decl.h linux-libre-3.2-gnu/arch/powerpc/mm/mmu_decl.h
--- linux-libre-3.1-gnu/arch/powerpc/mm/mmu_decl.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/mmu_decl.h	2012-01-04 18:55:44.000000000 -0500
@@ -142,6 +142,8 @@
 
 #elif defined(CONFIG_PPC_FSL_BOOK3E)
 extern unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx);
+extern unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
+				 phys_addr_t phys);
 #ifdef CONFIG_PPC32
 extern void MMU_init_hw(void);
 extern unsigned long mmu_mapin_ram(unsigned long top);
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/numa.c linux-libre-3.2-gnu/arch/powerpc/mm/numa.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/numa.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/numa.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/mmzone.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/nodemask.h>
 #include <linux/cpu.h>
 #include <linux/notifier.h>
@@ -315,7 +315,10 @@
 	struct device_node *root;
 	const char *vec5;
 
-	root = of_find_node_by_path("/rtas");
+	if (firmware_has_feature(FW_FEATURE_OPAL))
+		root = of_find_node_by_path("/ibm,opal");
+	else
+		root = of_find_node_by_path("/rtas");
 	if (!root)
 		root = of_find_node_by_path("/");
 
@@ -344,12 +347,19 @@
 
 #define VEC5_AFFINITY_BYTE	5
 #define VEC5_AFFINITY		0x80
-	chosen = of_find_node_by_path("/chosen");
-	if (chosen) {
-		vec5 = of_get_property(chosen, "ibm,architecture-vec-5", NULL);
-		if (vec5 && (vec5[VEC5_AFFINITY_BYTE] & VEC5_AFFINITY)) {
-			dbg("Using form 1 affinity\n");
-			form1_affinity = 1;
+
+	if (firmware_has_feature(FW_FEATURE_OPAL))
+		form1_affinity = 1;
+	else {
+		chosen = of_find_node_by_path("/chosen");
+		if (chosen) {
+			vec5 = of_get_property(chosen,
+					       "ibm,architecture-vec-5", NULL);
+			if (vec5 && (vec5[VEC5_AFFINITY_BYTE] &
+							VEC5_AFFINITY)) {
+				dbg("Using form 1 affinity\n");
+				form1_affinity = 1;
+			}
 		}
 	}
 
@@ -709,8 +719,7 @@
 
 static int __init parse_numa_properties(void)
 {
-	struct device_node *cpu = NULL;
-	struct device_node *memory = NULL;
+	struct device_node *memory;
 	int default_nid = 0;
 	unsigned long i;
 
@@ -732,6 +741,7 @@
 	 * each node to be onlined must have NODE_DATA etc backing it.
 	 */
 	for_each_present_cpu(i) {
+		struct device_node *cpu;
 		int nid;
 
 		cpu = of_get_cpu_node(i, NULL);
@@ -750,8 +760,8 @@
 	}
 
 	get_n_mem_cells(&n_mem_addr_cells, &n_mem_size_cells);
-	memory = NULL;
-	while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
+
+	for_each_node_by_type(memory, "memory") {
 		unsigned long start;
 		unsigned long size;
 		int nid;
@@ -800,8 +810,9 @@
 	}
 
 	/*
-	 * Now do the same thing for each MEMBLOCK listed in the ibm,dynamic-memory
-	 * property in the ibm,dynamic-reconfiguration-memory node.
+	 * Now do the same thing for each MEMBLOCK listed in the
+	 * ibm,dynamic-memory property in the
+	 * ibm,dynamic-reconfiguration-memory node.
 	 */
 	memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
 	if (memory)
@@ -1187,10 +1198,10 @@
  */
 int hot_add_node_scn_to_nid(unsigned long scn_addr)
 {
-	struct device_node *memory = NULL;
+	struct device_node *memory;
 	int nid = -1;
 
-	while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
+	for_each_node_by_type(memory, "memory") {
 		unsigned long start, size;
 		int ranges;
 		const unsigned int *memcell_buf;
@@ -1214,11 +1225,12 @@
 			break;
 		}
 
-		of_node_put(memory);
 		if (nid >= 0)
 			break;
 	}
 
+	of_node_put(memory);
+
 	return nid;
 }
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/pgtable_64.c linux-libre-3.2-gnu/arch/powerpc/mm/pgtable_64.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/pgtable_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/pgtable_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/pgtable.c linux-libre-3.2-gnu/arch/powerpc/mm/pgtable.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/pgtable.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/pgtable.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/percpu.h>
 #include <linux/hardirq.h>
+#include <linux/hugetlb.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
@@ -212,7 +213,7 @@
 	entry = set_access_flags_filter(entry, vma, dirty);
 	changed = !pte_same(*(ptep), entry);
 	if (changed) {
-		if (!(vma->vm_flags & VM_HUGETLB))
+		if (!is_vm_hugetlb_page(vma))
 			assert_pte_locked(vma->vm_mm, address);
 		__ptep_set_access_flags(ptep, entry);
 		flush_tlb_page_nohash(vma, address);
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/slice.c linux-libre-3.2-gnu/arch/powerpc/mm/slice.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/slice.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/slice.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,7 @@
 #include <linux/pagemap.h>
 #include <linux/err.h>
 #include <linux/spinlock.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/mman.h>
 #include <asm/mmu.h>
 #include <asm/spu.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/tlb_hash32.c linux-libre-3.2-gnu/arch/powerpc/mm/tlb_hash32.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/tlb_hash32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/tlb_hash32.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
+#include <linux/export.h>
 
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/tlb_low_64e.S linux-libre-3.2-gnu/arch/powerpc/mm/tlb_low_64e.S
--- linux-libre-3.1-gnu/arch/powerpc/mm/tlb_low_64e.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/tlb_low_64e.S	2012-01-04 18:55:44.000000000 -0500
@@ -553,24 +553,24 @@
 	rldicl	r11,r16,64-VPTE_PGD_SHIFT,64-PGD_INDEX_SIZE-3
 	clrrdi	r10,r11,3
 	ldx	r15,r10,r15
-	cmpldi	cr0,r15,0
-	beq	virt_page_table_tlb_miss_fault
+	cmpdi	cr0,r15,0
+	bge	virt_page_table_tlb_miss_fault
 
 #ifndef CONFIG_PPC_64K_PAGES
 	/* Get to PUD entry */
 	rldicl	r11,r16,64-VPTE_PUD_SHIFT,64-PUD_INDEX_SIZE-3
 	clrrdi	r10,r11,3
 	ldx	r15,r10,r15
-	cmpldi	cr0,r15,0
-	beq	virt_page_table_tlb_miss_fault
+	cmpdi	cr0,r15,0
+	bge	virt_page_table_tlb_miss_fault
 #endif /* CONFIG_PPC_64K_PAGES */
 
 	/* Get to PMD entry */
 	rldicl	r11,r16,64-VPTE_PMD_SHIFT,64-PMD_INDEX_SIZE-3
 	clrrdi	r10,r11,3
 	ldx	r15,r10,r15
-	cmpldi	cr0,r15,0
-	beq	virt_page_table_tlb_miss_fault
+	cmpdi	cr0,r15,0
+	bge	virt_page_table_tlb_miss_fault
 
 	/* Ok, we're all right, we can now create a kernel translation for
 	 * a 4K or 64K page from r16 -> r15.
@@ -802,24 +802,24 @@
 	rldicl	r11,r16,64-(PGDIR_SHIFT-3),64-PGD_INDEX_SIZE-3
 	clrrdi	r10,r11,3
 	ldx	r15,r10,r15
-	cmpldi	cr0,r15,0
-	beq	htw_tlb_miss_fault
+	cmpdi	cr0,r15,0
+	bge	htw_tlb_miss_fault
 
 #ifndef CONFIG_PPC_64K_PAGES
 	/* Get to PUD entry */
 	rldicl	r11,r16,64-(PUD_SHIFT-3),64-PUD_INDEX_SIZE-3
 	clrrdi	r10,r11,3
 	ldx	r15,r10,r15
-	cmpldi	cr0,r15,0
-	beq	htw_tlb_miss_fault
+	cmpdi	cr0,r15,0
+	bge	htw_tlb_miss_fault
 #endif /* CONFIG_PPC_64K_PAGES */
 
 	/* Get to PMD entry */
 	rldicl	r11,r16,64-(PMD_SHIFT-3),64-PMD_INDEX_SIZE-3
 	clrrdi	r10,r11,3
 	ldx	r15,r10,r15
-	cmpldi	cr0,r15,0
-	beq	htw_tlb_miss_fault
+	cmpdi	cr0,r15,0
+	bge	htw_tlb_miss_fault
 
 	/* Ok, we're all right, we can now create an indirect entry for
 	 * a 1M or 256M page.
diff -druN linux-libre-3.1-gnu/arch/powerpc/mm/tlb_nohash.c linux-libre-3.2-gnu/arch/powerpc/mm/tlb_nohash.c
--- linux-libre-3.1-gnu/arch/powerpc/mm/tlb_nohash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/mm/tlb_nohash.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/highmem.h>
@@ -36,14 +37,49 @@
 #include <linux/spinlock.h>
 #include <linux/memblock.h>
 #include <linux/of_fdt.h>
+#include <linux/hugetlb.h>
 
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
 #include <asm/code-patching.h>
+#include <asm/hugetlb.h>
 
 #include "mmu_decl.h"
 
-#ifdef CONFIG_PPC_BOOK3E
+/*
+ * This struct lists the sw-supported page sizes.  The hardawre MMU may support
+ * other sizes not listed here.   The .ind field is only used on MMUs that have
+ * indirect page table entries.
+ */
+#ifdef CONFIG_PPC_BOOK3E_MMU
+#ifdef CONFIG_FSL_BOOKE
+struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
+	[MMU_PAGE_4K] = {
+		.shift	= 12,
+		.enc	= BOOK3E_PAGESZ_4K,
+	},
+	[MMU_PAGE_4M] = {
+		.shift	= 22,
+		.enc	= BOOK3E_PAGESZ_4M,
+	},
+	[MMU_PAGE_16M] = {
+		.shift	= 24,
+		.enc	= BOOK3E_PAGESZ_16M,
+	},
+	[MMU_PAGE_64M] = {
+		.shift	= 26,
+		.enc	= BOOK3E_PAGESZ_64M,
+	},
+	[MMU_PAGE_256M] = {
+		.shift	= 28,
+		.enc	= BOOK3E_PAGESZ_256M,
+	},
+	[MMU_PAGE_1G] = {
+		.shift	= 30,
+		.enc	= BOOK3E_PAGESZ_1GB,
+	},
+};
+#else
 struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
 	[MMU_PAGE_4K] = {
 		.shift	= 12,
@@ -77,6 +113,8 @@
 		.enc	= BOOK3E_PAGESZ_1GB,
 	},
 };
+#endif /* CONFIG_FSL_BOOKE */
+
 static inline int mmu_get_tsize(int psize)
 {
 	return mmu_psize_defs[psize].enc;
@@ -87,7 +125,7 @@
 	/* This isn't used on !Book3E for now */
 	return 0;
 }
-#endif
+#endif /* CONFIG_PPC_BOOK3E_MMU */
 
 /* The variables below are currently only used on 64-bit Book3E
  * though this will probably be made common with other nohash
@@ -266,6 +304,11 @@
 
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
 {
+#ifdef CONFIG_HUGETLB_PAGE
+	if (is_vm_hugetlb_page(vma))
+		flush_hugetlb_page(vma, vmaddr);
+#endif
+
 	__flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr,
 			 mmu_get_tsize(mmu_virtual_psize), 0);
 }
@@ -600,13 +643,28 @@
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
 				phys_addr_t first_memblock_size)
 {
-	/* On Embedded 64-bit, we adjust the RMA size to match
+	/* On non-FSL Embedded 64-bit, we adjust the RMA size to match
 	 * the bolted TLB entry. We know for now that only 1G
 	 * entries are supported though that may eventually
-	 * change. We crop it to the size of the first MEMBLOCK to
+	 * change.
+	 *
+	 * on FSL Embedded 64-bit, we adjust the RMA size to match the
+	 * first bolted TLB entry size.  We still limit max to 1G even if
+	 * the TLB could cover more.  This is due to what the early init
+	 * code is setup to do.
+	 *
+	 * We crop it to the size of the first MEMBLOCK to
 	 * avoid going over total available memory just in case...
 	 */
-	ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
+#ifdef CONFIG_PPC_FSL_BOOK3E
+	if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
+		unsigned long linear_sz;
+		linear_sz = calc_cam_sz(first_memblock_size, PAGE_OFFSET,
+					first_memblock_base);
+		ppc64_rma_size = min_t(u64, linear_sz, 0x40000000);
+	} else
+#endif
+		ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
 
 	/* Finally limit subsequent allocations */
 	memblock_set_current_limit(first_memblock_base + ppc64_rma_size);
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/40x/hcu4.c linux-libre-3.2-gnu/arch/powerpc/platforms/40x/hcu4.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/40x/hcu4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/40x/hcu4.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-/*
- * Architecture- / platform-specific boot-time initialization code for
- * IBM PowerPC 4xx based boards. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
- * <dan@net4x.com>.
- *
- * Copyright(c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Rewritten and ported to the merged powerpc tree:
- * Copyright 2007 IBM Corporation
- * Josh Boyer <jwboyer@linux.vnet.ibm.com>
- *
- * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/init.h>
-#include <linux/of_platform.h>
-
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/time.h>
-#include <asm/uic.h>
-#include <asm/ppc4xx.h>
-
-static __initdata struct of_device_id hcu4_of_bus[] = {
-	{ .compatible = "ibm,plb3", },
-	{ .compatible = "ibm,opb", },
-	{ .compatible = "ibm,ebc", },
-	{},
-};
-
-static int __init hcu4_device_probe(void)
-{
-	of_platform_bus_probe(NULL, hcu4_of_bus, NULL);
-	return 0;
-}
-machine_device_initcall(hcu4, hcu4_device_probe);
-
-static int __init hcu4_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-
-	if (!of_flat_dt_is_compatible(root, "netstal,hcu4"))
-		return 0;
-
-	return 1;
-}
-
-define_machine(hcu4) {
-	.name			= "HCU4",
-	.probe			= hcu4_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-3.1-gnu/arch/powerpc/platforms/40x/Kconfig linux-libre-3.2-gnu/arch/powerpc/platforms/40x/Kconfig
--- linux-libre-3.1-gnu/arch/powerpc/platforms/40x/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/40x/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -32,14 +32,6 @@
 	help
 	  This option enables support for the EP405/EP405PC boards.
 
-config HCU4
-	bool "Hcu4"
-	depends on 40x
-	default n
-	select 405GPR
-	help
-	  This option enables support for the Nestal Maschinen HCU4 board.
-
 config HOTFOOT
         bool "Hotfoot"
 	depends on 40x
@@ -115,11 +107,6 @@
 	help
 	  This option enables the simple PowerPC 40x platform support.
 
-# 40x specific CPU modules, selected based on the board above.
-config NP405H
-	bool
-	#depends on ASH
-
 # OAK doesn't exist but wanted to keep this around for any future 403GCX boards
 config 403GCX
 	bool
@@ -130,21 +117,21 @@
 	bool
 	select IBM405_ERR77
 	select IBM405_ERR51
-	select IBM_NEW_EMAC_ZMII
+	select IBM_EMAC_ZMII
 
 config 405EP
 	bool
 
 config 405EX
 	bool
-	select IBM_NEW_EMAC_EMAC4
-	select IBM_NEW_EMAC_RGMII
+	select IBM_EMAC_EMAC4
+	select IBM_EMAC_RGMII
 
 config 405EZ
 	bool
-	select IBM_NEW_EMAC_NO_FLOW_CTRL
-	select IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
-	select IBM_NEW_EMAC_MAL_COMMON_ERR
+	select IBM_EMAC_NO_FLOW_CTRL
+	select IBM_EMAC_MAL_CLR_ICINTSTAT
+	select IBM_EMAC_MAL_COMMON_ERR
 
 config 405GPR
 	bool
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/40x/Makefile linux-libre-3.2-gnu/arch/powerpc/platforms/40x/Makefile
--- linux-libre-3.1-gnu/arch/powerpc/platforms/40x/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/40x/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,3 @@
-obj-$(CONFIG_HCU4)				+= hcu4.o
 obj-$(CONFIG_WALNUT)				+= walnut.o
 obj-$(CONFIG_XILINX_VIRTEX_GENERIC_BOARD)	+= virtex.o
 obj-$(CONFIG_EP405)				+= ep405.o
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/44x/Kconfig linux-libre-3.2-gnu/arch/powerpc/platforms/44x/Kconfig
--- linux-libre-3.1-gnu/arch/powerpc/platforms/44x/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/44x/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,7 @@
 	default n
 	select PPC44x_SIMPLE
 	select APM821xx
-	select IBM_NEW_EMAC_RGMII
+	select IBM_EMAC_RGMII
 	help
 	  This option enables support for the APM APM821xx Evaluation board.
 
@@ -122,8 +122,8 @@
 	select PPC4xx_PCI_EXPRESS
 	select PCI_MSI
 	select PPC4xx_MSI
-	select IBM_NEW_EMAC_RGMII
-	select IBM_NEW_EMAC_ZMII
+	select IBM_EMAC_RGMII
+	select IBM_EMAC_ZMII
 	help
 	  This option enables support for the AMCC PPC460EX evaluation board.
 
@@ -135,8 +135,8 @@
 	select 460EX # Odd since it uses 460GT but the effects are the same
 	select PCI
 	select PPC4xx_PCI_EXPRESS
-	select IBM_NEW_EMAC_RGMII
-	select IBM_NEW_EMAC_ZMII
+	select IBM_EMAC_RGMII
+	select IBM_EMAC_ZMII
 	help
 	  This option enables support for the AMCC PPC460GT evaluation board.
 
@@ -161,7 +161,7 @@
 	select 460SX
 	select PCI
 	select PPC4xx_PCI_EXPRESS
-	select IBM_NEW_EMAC_RGMII
+	select IBM_EMAC_RGMII
 	help
 	  This option enables support for the AMCC PPC460SX evaluation board.
 
@@ -260,59 +260,59 @@
 	bool
 	select PPC_FPU
 	select IBM440EP_ERR42
-	select IBM_NEW_EMAC_ZMII
+	select IBM_EMAC_ZMII
 	select USB_ARCH_HAS_OHCI
 
 config 440EPX
 	bool
 	select PPC_FPU
-	select IBM_NEW_EMAC_EMAC4
-	select IBM_NEW_EMAC_RGMII
-	select IBM_NEW_EMAC_ZMII
+	select IBM_EMAC_EMAC4
+	select IBM_EMAC_RGMII
+	select IBM_EMAC_ZMII
 
 config 440GRX
 	bool
-	select IBM_NEW_EMAC_EMAC4
-	select IBM_NEW_EMAC_RGMII
-	select IBM_NEW_EMAC_ZMII
+	select IBM_EMAC_EMAC4
+	select IBM_EMAC_RGMII
+	select IBM_EMAC_ZMII
 
 config 440GP
 	bool
-	select IBM_NEW_EMAC_ZMII
+	select IBM_EMAC_ZMII
 
 config 440GX
 	bool
-	select IBM_NEW_EMAC_EMAC4
-	select IBM_NEW_EMAC_RGMII
-	select IBM_NEW_EMAC_ZMII #test only
-	select IBM_NEW_EMAC_TAH  #test only
+	select IBM_EMAC_EMAC4
+	select IBM_EMAC_RGMII
+	select IBM_EMAC_ZMII #test only
+	select IBM_EMAC_TAH  #test only
 
 config 440SP
 	bool
 
 config 440SPe
 	bool
-	select IBM_NEW_EMAC_EMAC4
+	select IBM_EMAC_EMAC4
 
 config 460EX
 	bool
 	select PPC_FPU
-	select IBM_NEW_EMAC_EMAC4
-	select IBM_NEW_EMAC_TAH
+	select IBM_EMAC_EMAC4
+	select IBM_EMAC_TAH
 
 config 460SX
 	bool
 	select PPC_FPU
-	select IBM_NEW_EMAC_EMAC4
-	select IBM_NEW_EMAC_RGMII
-	select IBM_NEW_EMAC_ZMII
-	select IBM_NEW_EMAC_TAH
+	select IBM_EMAC_EMAC4
+	select IBM_EMAC_RGMII
+	select IBM_EMAC_ZMII
+	select IBM_EMAC_TAH
 
 config APM821xx
 	bool
 	select PPC_FPU
-	select IBM_NEW_EMAC_EMAC4
-	select IBM_NEW_EMAC_TAH
+	select IBM_EMAC_EMAC4
+	select IBM_EMAC_TAH
 
 # 44x errata/workaround config symbols, selected by the CPU models above
 config IBM440EP_ERR42
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/44x/warp.c linux-libre-3.2-gnu/arch/powerpc/platforms/44x/warp.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/44x/warp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/44x/warp.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/of_gpio.h>
 #include <linux/of_i2c.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 
 #include <asm/machdep.h>
 #include <asm/prom.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/512x/clock.c linux-libre-3.2-gnu/arch/powerpc/platforms/512x/clock.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/512x/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/512x/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <linux/module.h>
 #include <linux/string.h>
 #include <linux/clk.h>
 #include <linux/mutex.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/512x/Kconfig linux-libre-3.2-gnu/arch/powerpc/platforms/512x/Kconfig
--- linux-libre-3.1-gnu/arch/powerpc/platforms/512x/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/512x/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
 	select PPC_CLOCK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 
 config MPC5121_ADS
 	bool "Freescale MPC5121E ADS"
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/512x/mpc512x_shared.c linux-libre-3.2-gnu/arch/powerpc/platforms/512x/mpc512x_shared.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/512x/mpc512x_shared.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/512x/mpc512x_shared.c	2012-01-04 18:55:44.000000000 -0500
@@ -66,8 +66,8 @@
 	bool		in_use;
 };
 
-unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel,
-				      int monitor_port)
+u32 mpc512x_get_pixel_format(enum fsl_diu_monitor_port port,
+			     unsigned int bits_per_pixel)
 {
 	switch (bits_per_pixel) {
 	case 32:
@@ -80,11 +80,12 @@
 	return 0x00000400;
 }
 
-void mpc512x_set_gamma_table(int monitor_port, char *gamma_table_base)
+void mpc512x_set_gamma_table(enum fsl_diu_monitor_port port,
+			     char *gamma_table_base)
 {
 }
 
-void mpc512x_set_monitor_port(int monitor_port)
+void mpc512x_set_monitor_port(enum fsl_diu_monitor_port port)
 {
 }
 
@@ -182,14 +183,10 @@
 	iounmap(ccm);
 }
 
-ssize_t mpc512x_show_monitor_port(int monitor_port, char *buf)
-{
-	return sprintf(buf, "0 - 5121 LCD\n");
-}
-
-int mpc512x_set_sysfs_monitor_port(int val)
+enum fsl_diu_monitor_port
+mpc512x_valid_monitor_port(enum fsl_diu_monitor_port port)
 {
-	return 0;
+	return FSL_DIU_PORT_DVI;
 }
 
 static struct fsl_diu_shared_fb __attribute__ ((__aligned__(8))) diu_shared_fb;
@@ -256,7 +253,7 @@
 	}
 
 	mode = in_be32(&diu_reg->diu_mode);
-	if (mode != MFB_MODE1) {
+	if (mode == MFB_MODE0) {
 		pr_info("%s: DIU OFF\n", __func__);
 		goto out;
 	}
@@ -332,8 +329,7 @@
 	diu_ops.set_gamma_table		= mpc512x_set_gamma_table;
 	diu_ops.set_monitor_port	= mpc512x_set_monitor_port;
 	diu_ops.set_pixel_clock		= mpc512x_set_pixel_clock;
-	diu_ops.show_monitor_port	= mpc512x_show_monitor_port;
-	diu_ops.set_sysfs_monitor_port	= mpc512x_set_sysfs_monitor_port;
+	diu_ops.valid_monitor_port	= mpc512x_valid_monitor_port;
 	diu_ops.release_bootmem		= mpc512x_release_bootmem;
 #endif
 }
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/52xx/mpc5200_simple.c linux-libre-3.2-gnu/arch/powerpc/platforms/52xx/mpc5200_simple.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/52xx/mpc5200_simple.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/52xx/mpc5200_simple.c	2012-01-04 18:55:44.000000000 -0500
@@ -50,6 +50,7 @@
 
 /* list of the supported boards */
 static const char *board[] __initdata = {
+	"anon,charon",
 	"intercontrol,digsy-mtc",
 	"manroland,mucmc52",
 	"manroland,uc101",
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/52xx/mpc52xx_common.c linux-libre-3.2-gnu/arch/powerpc/platforms/52xx/mpc52xx_common.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/52xx/mpc52xx_common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/52xx/mpc52xx_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/spinlock.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
+#include <linux/export.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/mpc52xx.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/52xx/mpc52xx_gpt.c linux-libre-3.2-gnu/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/52xx/mpc52xx_gpt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/52xx/mpc52xx_gpt.c	2012-01-04 18:55:44.000000000 -0500
@@ -67,6 +67,7 @@
 #include <linux/watchdog.h>
 #include <linux/miscdevice.h>
 #include <linux/uaccess.h>
+#include <linux/module.h>
 #include <asm/div64.h>
 #include <asm/mpc52xx.h>
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c linux-libre-3.2-gnu/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/spinlock.h>
+#include <linux/module.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/mpc52xx.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/82xx/km82xx.c linux-libre-3.2-gnu/arch/powerpc/platforms/82xx/km82xx.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/82xx/km82xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/82xx/km82xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,6 +49,9 @@
 };
 
 static __initdata struct cpm_pin km82xx_pins[] = {
+	/* SMC1 */
+	{2, 4, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{2, 5, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
 
 	/* SMC2 */
 	{0, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
@@ -137,6 +140,7 @@
 	}
 
 	cpm2_smc_clk_setup(CPM_CLK_SMC2, CPM_BRG8);
+	cpm2_smc_clk_setup(CPM_CLK_SMC1, CPM_BRG7);
 	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);
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/83xx/Kconfig linux-libre-3.2-gnu/arch/powerpc/platforms/83xx/Kconfig
--- linux-libre-3.1-gnu/arch/powerpc/platforms/83xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/83xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -114,18 +114,21 @@
 
 endif
 
-# used for usb
+# used for usb & gpio
 config PPC_MPC831x
 	bool
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 
 # used for math-emu
 config PPC_MPC832x
 	bool
 
-# used for usb
+# used for usb & gpio
 config PPC_MPC834x
 	bool
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 
-# used for usb
+# used for usb & gpio
 config PPC_MPC837x
 	bool
+	select ARCH_WANT_OPTIONAL_GPIOLIB
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c linux-libre-3.2-gnu/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,8 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/reboot.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 
@@ -30,6 +32,7 @@
  */
 #define MCU_REG_CTRL	0x20
 #define MCU_CTRL_POFF	0x40
+#define MCU_CTRL_BTN	0x80
 
 #define MCU_NUM_GPIO	2
 
@@ -42,13 +45,55 @@
 
 static struct mcu *glob_mcu;
 
+struct task_struct *shutdown_thread;
+static int shutdown_thread_fn(void *data)
+{
+	int ret;
+	struct mcu *mcu = glob_mcu;
+
+	while (!kthread_should_stop()) {
+		ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
+		if (ret < 0)
+			pr_err("MCU status reg read failed.\n");
+		mcu->reg_ctrl = ret;
+
+
+		if (mcu->reg_ctrl & MCU_CTRL_BTN) {
+			i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL,
+						  mcu->reg_ctrl & ~MCU_CTRL_BTN);
+
+			ctrl_alt_del();
+		}
+
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ);
+	}
+
+	return 0;
+}
+
+static ssize_t show_status(struct device *d,
+			   struct device_attribute *attr, char *buf)
+{
+	int ret;
+	struct mcu *mcu = glob_mcu;
+
+	ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
+	if (ret < 0)
+		return -ENODEV;
+	mcu->reg_ctrl = ret;
+
+	return sprintf(buf, "%02x\n", ret);
+}
+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
+
 static void mcu_power_off(void)
 {
 	struct mcu *mcu = glob_mcu;
 
 	pr_info("Sending power-off request to the MCU...\n");
 	mutex_lock(&mcu->lock);
-	i2c_smbus_write_byte_data(glob_mcu->client, MCU_REG_CTRL,
+	i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL,
 				  mcu->reg_ctrl | MCU_CTRL_POFF);
 	mutex_unlock(&mcu->lock);
 }
@@ -130,6 +175,13 @@
 		dev_info(&client->dev, "will provide power-off service\n");
 	}
 
+	if (device_create_file(&client->dev, &dev_attr_status))
+		dev_err(&client->dev,
+			"couldn't create device file for status\n");
+
+	shutdown_thread = kthread_run(shutdown_thread_fn, NULL,
+				      "mcu-i2c-shdn");
+
 	return 0;
 err:
 	kfree(mcu);
@@ -141,6 +193,10 @@
 	struct mcu *mcu = i2c_get_clientdata(client);
 	int ret;
 
+	kthread_stop(shutdown_thread);
+
+	device_remove_file(&client->dev, &dev_attr_status);
+
 	if (glob_mcu == mcu) {
 		ppc_md.power_off = NULL;
 		glob_mcu = NULL;
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/83xx/suspend.c linux-libre-3.2-gnu/arch/powerpc/platforms/83xx/suspend.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/83xx/suspend.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/83xx/suspend.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/suspend.h>
 #include <linux/fsl_devices.h>
 #include <linux/of_platform.h>
+#include <linux/export.h>
 
 #include <asm/reg.h>
 #include <asm/io.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/Kconfig linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/Kconfig
--- linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -80,7 +80,7 @@
 config P1022_DS
 	bool "Freescale P1022 DS"
 	select DEFAULT_UIMAGE
-	select CONFIG_PHYS_64BIT	# The DTS has 36-bit addresses
+	select PHYS_64BIT	# The DTS has 36-bit addresses
 	select SWIOTLB
 	help
 	  This option enables support for the Freescale P1022DS reference board.
@@ -171,17 +171,18 @@
 	help
 	  This option enables support for the Wind River SBC8560 board
 
-config P2040_RDB
-	bool "Freescale P2040 RDB"
+config P2041_RDB
+	bool "Freescale P2041 RDB"
 	select DEFAULT_UIMAGE
 	select PPC_E500MC
 	select PHYS_64BIT
 	select SWIOTLB
-	select MPC8xxx_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select GPIO_MPC8XXX
 	select HAS_RAPIDIO
 	select PPC_EPAPR_HV_PIC
 	help
-	  This option enables support for the P2040 RDB board
+	  This option enables support for the P2041 RDB board
 
 config P3041_DS
 	bool "Freescale P3041 DS"
@@ -189,19 +190,33 @@
 	select PPC_E500MC
 	select PHYS_64BIT
 	select SWIOTLB
-	select MPC8xxx_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select GPIO_MPC8XXX
 	select HAS_RAPIDIO
 	select PPC_EPAPR_HV_PIC
 	help
 	  This option enables support for the P3041 DS board
 
+config P3060_QDS
+	bool "Freescale P3060 QDS"
+	select DEFAULT_UIMAGE
+	select PPC_E500MC
+	select PHYS_64BIT
+	select SWIOTLB
+	select GPIO_MPC8XXX
+	select HAS_RAPIDIO
+	select PPC_EPAPR_HV_PIC
+	help
+	  This option enables support for the P3060 QDS board
+
 config P4080_DS
 	bool "Freescale P4080 DS"
 	select DEFAULT_UIMAGE
 	select PPC_E500MC
 	select PHYS_64BIT
 	select SWIOTLB
-	select MPC8xxx_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select GPIO_MPC8XXX
 	select HAS_RAPIDIO
 	select PPC_EPAPR_HV_PIC
 	help
@@ -216,7 +231,8 @@
 	select PPC_E500MC
 	select PHYS_64BIT
 	select SWIOTLB
-	select MPC8xxx_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select GPIO_MPC8XXX
 	select HAS_RAPIDIO
 	select PPC_EPAPR_HV_PIC
 	help
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/Makefile linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/Makefile
--- linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -13,8 +13,9 @@
 obj-$(CONFIG_P1010_RDB)   += p1010rdb.o
 obj-$(CONFIG_P1022_DS)    += p1022_ds.o
 obj-$(CONFIG_P1023_RDS)   += p1023_rds.o
-obj-$(CONFIG_P2040_RDB)   += p2040_rdb.o corenet_ds.o
+obj-$(CONFIG_P2041_RDB)   += p2041_rdb.o corenet_ds.o
 obj-$(CONFIG_P3041_DS)    += p3041_ds.o corenet_ds.o
+obj-$(CONFIG_P3060_QDS)   += p3060_qds.o corenet_ds.o
 obj-$(CONFIG_P4080_DS)    += p4080_ds.o corenet_ds.o
 obj-$(CONFIG_P5020_DS)    += p5020_ds.o corenet_ds.o
 obj-$(CONFIG_STX_GP3)	  += stx_gp3.o
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/mpc85xx_cds.c linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/mpc85xx_cds.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/mpc85xx_cds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/mpc85xx_cds.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,6 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/initrd.h>
-#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/fsl_devices.h>
 #include <linux/of_platform.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/mpc85xx_mds.c linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/mpc85xx_mds.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/mpc85xx_mds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/mpc85xx_mds.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,6 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/initrd.h>
-#include <linux/module.h>
 #include <linux/fsl_devices.h>
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/p1022_ds.c linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/p1022_ds.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/p1022_ds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/p1022_ds.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,8 +93,8 @@
  * The Area Descriptor is a 32-bit value that determine which bits in each
  * pixel are to be used for each color.
  */
-static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel,
-	int monitor_port)
+static u32 p1022ds_get_pixel_format(enum fsl_diu_monitor_port port,
+				    unsigned int bits_per_pixel)
 {
 	switch (bits_per_pixel) {
 	case 32:
@@ -118,7 +118,8 @@
  * On some boards, the gamma table for some ports may need to be modified.
  * This is not the case on the P1022DS, so we do nothing.
 */
-static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base)
+static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port,
+				    char *gamma_table_base)
 {
 }
 
@@ -126,38 +127,43 @@
  * p1022ds_set_monitor_port: switch the output to a different monitor port
  *
  */
-static void p1022ds_set_monitor_port(int monitor_port)
+static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
 {
-	struct device_node *pixis_node;
+	struct device_node *np;
 	void __iomem *pixis;
 	u8 __iomem *brdcfg1;
 
-	pixis_node = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis");
-	if (!pixis_node) {
+	np = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga");
+	if (!np)
+		/* older device trees used "fsl,p1022ds-pixis" */
+		np = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis");
+	if (!np) {
 		pr_err("p1022ds: missing ngPIXIS node\n");
 		return;
 	}
 
-	pixis = of_iomap(pixis_node, 0);
+	pixis = of_iomap(np, 0);
 	if (!pixis) {
 		pr_err("p1022ds: could not map ngPIXIS registers\n");
 		return;
 	}
 	brdcfg1 = pixis + 9;	/* BRDCFG1 is at offset 9 in the ngPIXIS */
 
-	switch (monitor_port) {
-	case 0: /* DVI */
+	switch (port) {
+	case FSL_DIU_PORT_DVI:
+		printk(KERN_INFO "%s:%u\n", __func__, __LINE__);
 		/* Enable the DVI port, disable the DFP and the backlight */
 		clrsetbits_8(brdcfg1, PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT,
 			     PX_BRDCFG1_DVIEN);
 		break;
-	case 1: /* Single link LVDS */
+	case FSL_DIU_PORT_LVDS:
+		printk(KERN_INFO "%s:%u\n", __func__, __LINE__);
 		/* Enable the DFP port, disable the DVI and the backlight */
 		clrsetbits_8(brdcfg1, PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT,
 			     PX_BRDCFG1_DFPEN);
 		break;
 	default:
-		pr_err("p1022ds: unsupported monitor port %i\n", monitor_port);
+		pr_err("p1022ds: unsupported monitor port %i\n", port);
 	}
 
 	iounmap(pixis);
@@ -214,23 +220,18 @@
 }
 
 /**
- * p1022ds_show_monitor_port: show the current monitor
- *
- * This function returns a string indicating whether the current monitor is
- * set to DVI or LVDS.
- */
-ssize_t p1022ds_show_monitor_port(int monitor_port, char *buf)
-{
-	return sprintf(buf, "%c0 - DVI\n%c1 - Single link LVDS\n",
-		monitor_port == 0 ? '*' : ' ', monitor_port == 1 ? '*' : ' ');
-}
-
-/**
- * p1022ds_set_sysfs_monitor_port: set the monitor port for sysfs
+ * p1022ds_valid_monitor_port: set the monitor port for sysfs
  */
-int p1022ds_set_sysfs_monitor_port(int val)
+enum fsl_diu_monitor_port
+p1022ds_valid_monitor_port(enum fsl_diu_monitor_port port)
 {
-	return val < 2 ? val : 0;
+	switch (port) {
+	case FSL_DIU_PORT_DVI:
+	case FSL_DIU_PORT_LVDS:
+		return port;
+	default:
+		return FSL_DIU_PORT_DVI; /* Dual-link LVDS is not supported */
+	}
 }
 
 #endif
@@ -305,8 +306,7 @@
 	diu_ops.set_gamma_table		= p1022ds_set_gamma_table;
 	diu_ops.set_monitor_port	= p1022ds_set_monitor_port;
 	diu_ops.set_pixel_clock		= p1022ds_set_pixel_clock;
-	diu_ops.show_monitor_port	= p1022ds_show_monitor_port;
-	diu_ops.set_sysfs_monitor_port	= p1022ds_set_sysfs_monitor_port;
+	diu_ops.valid_monitor_port	= p1022ds_valid_monitor_port;
 #endif
 
 #ifdef CONFIG_SMP
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/p2040_rdb.c linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/p2040_rdb.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/p2040_rdb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/p2040_rdb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,88 +0,0 @@
-/*
- * P2040 RDB Setup
- *
- * Copyright 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/phy.h>
-
-#include <asm/system.h>
-#include <asm/time.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <mm/mmu_decl.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/mpic.h>
-
-#include <linux/of_platform.h>
-#include <sysdev/fsl_soc.h>
-#include <sysdev/fsl_pci.h>
-#include <asm/ehv_pic.h>
-
-#include "corenet_ds.h"
-
-/*
- * Called very early, device-tree isn't unflattened
- */
-static int __init p2040_rdb_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-#ifdef CONFIG_SMP
-	extern struct smp_ops_t smp_85xx_ops;
-#endif
-
-	if (of_flat_dt_is_compatible(root, "fsl,P2040RDB"))
-		return 1;
-
-	/* Check if we're running under the Freescale hypervisor */
-	if (of_flat_dt_is_compatible(root, "fsl,P2040RDB-hv")) {
-		ppc_md.init_IRQ = ehv_pic_init;
-		ppc_md.get_irq = ehv_pic_get_irq;
-		ppc_md.restart = fsl_hv_restart;
-		ppc_md.power_off = fsl_hv_halt;
-		ppc_md.halt = fsl_hv_halt;
-#ifdef CONFIG_SMP
-		/*
-		 * Disable the timebase sync operations because we can't write
-		 * to the timebase registers under the hypervisor.
-		  */
-		smp_85xx_ops.give_timebase = NULL;
-		smp_85xx_ops.take_timebase = NULL;
-#endif
-		return 1;
-	}
-
-	return 0;
-}
-
-define_machine(p2040_rdb) {
-	.name			= "P2040 RDB",
-	.probe			= p2040_rdb_probe,
-	.setup_arch		= corenet_ds_setup_arch,
-	.init_IRQ		= corenet_ds_pic_init,
-#ifdef CONFIG_PCI
-	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
-#endif
-	.get_irq		= mpic_get_coreint_irq,
-	.restart		= fsl_rstcr_restart,
-	.calibrate_decr		= generic_calibrate_decr,
-	.progress		= udbg_progress,
-	.power_save		= e500_idle,
-};
-
-machine_device_initcall(p2040_rdb, corenet_ds_publish_devices);
-
-#ifdef CONFIG_SWIOTLB
-machine_arch_initcall(p2040_rdb, swiotlb_setup_bus_notifier);
-#endif
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/p2041_rdb.c linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/p2041_rdb.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/p2041_rdb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/p2041_rdb.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,88 @@
+/*
+ * P2041 RDB Setup
+ *
+ * Copyright 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/phy.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include <asm/ehv_pic.h>
+
+#include "corenet_ds.h"
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p2041_rdb_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+	extern struct smp_ops_t smp_85xx_ops;
+#endif
+
+	if (of_flat_dt_is_compatible(root, "fsl,P2041RDB"))
+		return 1;
+
+	/* Check if we're running under the Freescale hypervisor */
+	if (of_flat_dt_is_compatible(root, "fsl,P2041RDB-hv")) {
+		ppc_md.init_IRQ = ehv_pic_init;
+		ppc_md.get_irq = ehv_pic_get_irq;
+		ppc_md.restart = fsl_hv_restart;
+		ppc_md.power_off = fsl_hv_halt;
+		ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+		/*
+		 * Disable the timebase sync operations because we can't write
+		 * to the timebase registers under the hypervisor.
+		  */
+		smp_85xx_ops.give_timebase = NULL;
+		smp_85xx_ops.take_timebase = NULL;
+#endif
+		return 1;
+	}
+
+	return 0;
+}
+
+define_machine(p2041_rdb) {
+	.name			= "P2041 RDB",
+	.probe			= p2041_rdb_probe,
+	.setup_arch		= corenet_ds_setup_arch,
+	.init_IRQ		= corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+	.get_irq		= mpic_get_coreint_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+	.power_save		= e500_idle,
+};
+
+machine_device_initcall(p2041_rdb, corenet_ds_publish_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(p2041_rdb, swiotlb_setup_bus_notifier);
+#endif
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/p3060_qds.c linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/p3060_qds.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/p3060_qds.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/p3060_qds.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,77 @@
+/*
+ * P3060 QDS Setup
+ *
+ * Copyright 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/phy.h>
+#include <asm/machdep.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include <asm/ehv_pic.h>
+#include "corenet_ds.h"
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p3060_qds_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+	extern struct smp_ops_t smp_85xx_ops;
+#endif
+
+	if (of_flat_dt_is_compatible(root, "fsl,P3060QDS"))
+		return 1;
+
+	/* Check if we're running under the Freescale hypervisor */
+	if (of_flat_dt_is_compatible(root, "fsl,P3060QDS-hv")) {
+		ppc_md.init_IRQ = ehv_pic_init;
+		ppc_md.get_irq = ehv_pic_get_irq;
+		ppc_md.restart = fsl_hv_restart;
+		ppc_md.power_off = fsl_hv_halt;
+		ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+		/*
+		 * Disable the timebase sync operations because we can't write
+		 * to the timebase registers under the hypervisor.
+		 */
+		smp_85xx_ops.give_timebase = NULL;
+		smp_85xx_ops.take_timebase = NULL;
+#endif
+		return 1;
+	}
+
+	return 0;
+}
+
+define_machine(p3060_qds) {
+	.name			= "P3060 QDS",
+	.probe			= p3060_qds_probe,
+	.setup_arch		= corenet_ds_setup_arch,
+	.init_IRQ		= corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+	.get_irq		= mpic_get_coreint_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+	.power_save		= e500_idle,
+};
+
+machine_device_initcall(p3060_qds, corenet_ds_publish_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(p3060_qds, swiotlb_setup_bus_notifier);
+#endif
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/sbc8548.c linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/sbc8548.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/sbc8548.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/sbc8548.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,7 +26,6 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/initrd.h>
-#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/fsl_devices.h>
 #include <linux/of_platform.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/sbc8560.c linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/sbc8560.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/sbc8560.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/sbc8560.c	2012-01-04 18:55:44.000000000 -0500
@@ -283,7 +283,7 @@
 
 	of_address_to_resource(np, 0, &res);
 
-	printk(KERN_INFO "sbc8560: Found BRSTCR at i/o 0x%x\n", res.start);
+	printk(KERN_INFO "sbc8560: Found BRSTCR at %pR\n", &res);
 
 	brstcr = ioremap(res.start, resource_size(&res));
 	if(!brstcr)
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/smp.c linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/smp.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/85xx/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/85xx/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,10 +48,11 @@
 	const u64 *cpu_rel_addr;
 	__iomem u32 *bptr_vaddr;
 	struct device_node *np;
-	int n = 0;
+	int n = 0, hw_cpu = get_hard_smp_processor_id(nr);
 	int ioremappable;
 
-	WARN_ON (nr < 0 || nr >= NR_CPUS);
+	WARN_ON(nr < 0 || nr >= NR_CPUS);
+	WARN_ON(hw_cpu < 0 || hw_cpu >= NR_CPUS);
 
 	pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr);
 
@@ -79,7 +80,7 @@
 
 	local_irq_save(flags);
 
-	out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr);
+	out_be32(bptr_vaddr + BOOT_ENTRY_PIR, hw_cpu);
 #ifdef CONFIG_PPC32
 	out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start));
 
@@ -88,7 +89,7 @@
 				(ulong)(bptr_vaddr + SIZE_BOOT_ENTRY));
 
 	/* Wait a bit for the CPU to ack. */
-	while ((__secondary_hold_acknowledge != nr) && (++n < 1000))
+	while ((__secondary_hold_acknowledge != hw_cpu) && (++n < 1000))
 		mdelay(1);
 #else
 	smp_generic_kick_cpu(nr);
@@ -206,7 +207,7 @@
 	if ( !timeout )
 		printk(KERN_ERR "Unable to bring down secondary cpu(s)");
 
-	for (i = 0; i < num_cpus; i++)
+	for_each_online_cpu(i)
 	{
 		if ( i == smp_processor_id() ) continue;
 		mpic_reset_core(i);
@@ -243,6 +244,7 @@
 		 * If left NULL, .message_pass defaults to
 		 * smp_muxed_ipi_message_pass
 		 */
+		smp_85xx_ops.message_pass = NULL;
 		smp_85xx_ops.cause_ipi = doorbell_cause_ipi;
 	}
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/86xx/gef_gpio.c linux-libre-3.2-gnu/arch/powerpc/platforms/86xx/gef_gpio.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/86xx/gef_gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/86xx/gef_gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/of_gpio.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define GEF_GPIO_DIRECT		0x00
 #define GEF_GPIO_IN		0x04
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/86xx/Kconfig linux-libre-3.2-gnu/arch/powerpc/platforms/86xx/Kconfig
--- linux-libre-3.1-gnu/arch/powerpc/platforms/86xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/86xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@
 	depends on 6xx
 	select FSL_SOC
 	select ALTIVEC
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 	help
 	  The Freescale E600 SoCs have 74xx cores.
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/86xx/mpc8610_hpcd.c linux-libre-3.2-gnu/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/86xx/mpc8610_hpcd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/86xx/mpc8610_hpcd.c	2012-01-04 18:55:44.000000000 -0500
@@ -152,10 +152,10 @@
 	(c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \
 	(c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT))
 
-unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel,
-						int monitor_port)
+u32 mpc8610hpcd_get_pixel_format(enum fsl_diu_monitor_port port,
+				 unsigned int bits_per_pixel)
 {
-	static const unsigned long pixelformat[][3] = {
+	static const u32 pixelformat[][3] = {
 		{
 			MAKE_AD(3, 0, 2, 1, 3, 8, 8, 8, 8),
 			MAKE_AD(4, 2, 0, 1, 2, 8, 8, 8, 0),
@@ -170,7 +170,8 @@
 	unsigned int arch_monitor;
 
 	/* The DVI port is mis-wired on revision 1 of this board. */
-	arch_monitor = ((*pixis_arch == 0x01) && (monitor_port == 0))? 0 : 1;
+	arch_monitor =
+		((*pixis_arch == 0x01) && (port == FSL_DIU_PORT_DVI)) ? 0 : 1;
 
 	switch (bits_per_pixel) {
 	case 32:
@@ -185,10 +186,11 @@
 	}
 }
 
-void mpc8610hpcd_set_gamma_table(int monitor_port, char *gamma_table_base)
+void mpc8610hpcd_set_gamma_table(enum fsl_diu_monitor_port port,
+				 char *gamma_table_base)
 {
 	int i;
-	if (monitor_port == 2) {		/* dual link LVDS */
+	if (port == FSL_DIU_PORT_DLVDS) {
 		for (i = 0; i < 256*3; i++)
 			gamma_table_base[i] = (gamma_table_base[i] << 2) |
 					 ((gamma_table_base[i] >> 6) & 0x03);
@@ -199,17 +201,21 @@
 #define PX_BRDCFG0_DLINK	(1 << 4)
 #define PX_BRDCFG0_DIU_MASK	(PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK)
 
-void mpc8610hpcd_set_monitor_port(int monitor_port)
+void mpc8610hpcd_set_monitor_port(enum fsl_diu_monitor_port port)
 {
-	static const u8 bdcfg[] = {
-		PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK,
-		PX_BRDCFG0_DLINK,
-		0,
-	};
-
-	if (monitor_port < 3)
+	switch (port) {
+	case FSL_DIU_PORT_DVI:
 		clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK,
-			     bdcfg[monitor_port]);
+			     PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK);
+		break;
+	case FSL_DIU_PORT_LVDS:
+		clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK,
+			     PX_BRDCFG0_DLINK);
+		break;
+	case FSL_DIU_PORT_DLVDS:
+		clrbits8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK);
+		break;
+	}
 }
 
 /**
@@ -262,20 +268,10 @@
 	iounmap(guts);
 }
 
-ssize_t mpc8610hpcd_show_monitor_port(int monitor_port, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE,
-			"%c0 - DVI\n"
-			"%c1 - Single link LVDS\n"
-			"%c2 - Dual link LVDS\n",
-			monitor_port == 0 ? '*' : ' ',
-			monitor_port == 1 ? '*' : ' ',
-			monitor_port == 2 ? '*' : ' ');
-}
-
-int mpc8610hpcd_set_sysfs_monitor_port(int val)
+enum fsl_diu_monitor_port
+mpc8610hpcd_valid_monitor_port(enum fsl_diu_monitor_port port)
 {
-	return val < 3 ? val : 0;
+	return port;
 }
 
 #endif
@@ -307,8 +303,7 @@
 	diu_ops.set_gamma_table		= mpc8610hpcd_set_gamma_table;
 	diu_ops.set_monitor_port	= mpc8610hpcd_set_monitor_port;
 	diu_ops.set_pixel_clock		= mpc8610hpcd_set_pixel_clock;
-	diu_ops.show_monitor_port	= mpc8610hpcd_show_monitor_port;
-	diu_ops.set_sysfs_monitor_port	= mpc8610hpcd_set_sysfs_monitor_port;
+	diu_ops.valid_monitor_port	= mpc8610hpcd_valid_monitor_port;
 #endif
 
 	pixis_node = of_find_compatible_node(NULL, NULL, "fsl,fpga-pixis");
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/8xx/tqm8xx_setup.c linux-libre-3.2-gnu/arch/powerpc/platforms/8xx/tqm8xx_setup.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/8xx/tqm8xx_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/8xx/tqm8xx_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
 #include <linux/param.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/axon_msi.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/axon_msi.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/axon_msi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/axon_msi.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/msi.h>
+#include <linux/export.h>
 #include <linux/of_platform.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/beat.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/beat.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/beat.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/beat.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/rtc.h>
@@ -230,7 +230,7 @@
 		}
 		ev->virq = virq;
 
-		rc = request_irq(virq, ev->handler, IRQF_DISABLED,
+		rc = request_irq(virq, ev->handler, 0,
 				      ev->typecode, NULL);
 		if (rc != 0) {
 			printk(KERN_ERR "Beat: failed to request virtual IRQ"
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/beat_spu_priv1.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/beat_spu_priv1.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/beat_spu_priv1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/beat_spu_priv1.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,8 +18,6 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include <linux/module.h>
-
 #include <asm/types.h>
 #include <asm/spu.h>
 #include <asm/spu_priv1.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/beat_wrapper.h linux-libre-3.2-gnu/arch/powerpc/platforms/cell/beat_wrapper.h
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/beat_wrapper.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/beat_wrapper.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 #ifndef BEAT_HCALL
+#include <linux/string.h>
 #include "beat_syscall.h"
 
 /* defined in hvCall.S */
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/cbe_cpufreq.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/cbe_cpufreq.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/cbe_cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/cbe_cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include <linux/cpufreq.h>
+#include <linux/module.h>
 #include <linux/of_platform.h>
 
 #include <asm/machdep.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/timer.h>
+#include <linux/module.h>
 #include <linux/of_platform.h>
 
 #include <asm/processor.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/cbe_powerbutton.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/cbe_powerbutton.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/cbe_powerbutton.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/cbe_powerbutton.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include <linux/input.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <asm/pmi.h>
 #include <asm/prom.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/cbe_regs.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/cbe_regs.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/cbe_regs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/cbe_regs.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
 
 #include <linux/percpu.h>
 #include <linux/types.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/celleb_scc_pciex.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/celleb_scc_pciex.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/celleb_scc_pciex.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/celleb_scc_pciex.c	2012-01-04 18:55:44.000000000 -0500
@@ -514,7 +514,7 @@
 	virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
 				     oirq.size);
 	if (request_irq(virq, pciex_handle_internal_irq,
-			IRQF_DISABLED, "pciex", (void *)phb)) {
+			0, "pciex", (void *)phb)) {
 		pr_err("PCIEXC:Failed to request irq\n");
 		goto error;
 	}
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/celleb_setup.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/celleb_setup.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/celleb_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/celleb_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/cpu.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/cpufreq_spudemand.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/cpufreq_spudemand.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/cpufreq_spudemand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/cpufreq_spudemand.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 
 #include <linux/cpufreq.h>
 #include <linux/sched.h>
+#include <linux/module.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 #include <linux/atomic.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/interrupt.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/interrupt.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/interrupt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/interrupt.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/percpu.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/iommu.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/iommu.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -412,8 +412,7 @@
 			IIC_IRQ_IOEX_ATI | (iommu->nid << IIC_IRQ_NODE_SHIFT));
 	BUG_ON(virq == NO_IRQ);
 
-	ret = request_irq(virq, ioc_interrupt, IRQF_DISABLED,
-			iommu->name, iommu);
+	ret = request_irq(virq, ioc_interrupt, 0, iommu->name, iommu);
 	BUG_ON(ret);
 
 	/* set the IOC segment table origin register (and turn on the iommu) */
@@ -1159,6 +1158,26 @@
 }
 __setup("iommu_fixed=", setup_iommu_fixed);
 
+static u64 cell_dma_get_required_mask(struct device *dev)
+{
+	struct dma_map_ops *dma_ops;
+
+	if (!dev->dma_mask)
+		return 0;
+
+	if (!iommu_fixed_disabled &&
+			cell_iommu_get_fixed_address(dev) != OF_BAD_ADDR)
+		return DMA_BIT_MASK(64);
+
+	dma_ops = get_dma_ops(dev);
+	if (dma_ops->get_required_mask)
+		return dma_ops->get_required_mask(dev);
+
+	WARN_ONCE(1, "no get_required_mask in %p ops", dma_ops);
+
+	return DMA_BIT_MASK(64);
+}
+
 static int __init cell_iommu_init(void)
 {
 	struct device_node *np;
@@ -1175,6 +1194,7 @@
 
 	/* Setup various ppc_md. callbacks */
 	ppc_md.pci_dma_dev_setup = cell_pci_dma_dev_setup;
+	ppc_md.dma_get_required_mask = cell_dma_get_required_mask;
 	ppc_md.tce_build = tce_build_cell;
 	ppc_md.tce_free = tce_free_cell;
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/Kconfig linux-libre-3.2-gnu/arch/powerpc/platforms/cell/Kconfig
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -17,10 +17,10 @@
 	select PPC_CELL_COMMON
 	select MPIC
 	select PPC_IO_WORKAROUNDS
-	select IBM_NEW_EMAC_EMAC4
-	select IBM_NEW_EMAC_RGMII
-	select IBM_NEW_EMAC_ZMII #test only
-	select IBM_NEW_EMAC_TAH  #test only
+	select IBM_EMAC_EMAC4
+	select IBM_EMAC_RGMII
+	select IBM_EMAC_ZMII #test only
+	select IBM_EMAC_TAH  #test only
 	default n
 
 config PPC_IBM_CELL_BLADE
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/pmu.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/pmu.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/pmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/pmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/types.h>
+#include <linux/export.h>
 #include <asm/io.h>
 #include <asm/irq_regs.h>
 #include <asm/machdep.h>
@@ -391,7 +392,7 @@
 		}
 
 		rc = request_irq(irq, cbe_pm_irq,
-				 IRQF_DISABLED, "cbe-pmu-0", NULL);
+				 0, "cbe-pmu-0", NULL);
 		if (rc) {
 			printk("ERROR: Request for irq on node %d failed\n",
 			       node);
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/qpace_setup.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/qpace_setup.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/qpace_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/qpace_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/console.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/setup.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/setup.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
+#include <linux/export.h>
 #include <linux/unistd.h>
 #include <linux/user.h>
 #include <linux/reboot.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/smp.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/smp.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,6 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spu_base.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spu_base.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spu_base.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spu_base.c	2012-01-04 18:55:44.000000000 -0500
@@ -442,8 +442,7 @@
 		snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0",
 			 spu->number);
 		ret = request_irq(spu->irqs[0], spu_irq_class_0,
-				  IRQF_DISABLED,
-				  spu->irq_c0, spu);
+				  0, spu->irq_c0, spu);
 		if (ret)
 			goto bail0;
 	}
@@ -451,8 +450,7 @@
 		snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1",
 			 spu->number);
 		ret = request_irq(spu->irqs[1], spu_irq_class_1,
-				  IRQF_DISABLED,
-				  spu->irq_c1, spu);
+				  0, spu->irq_c1, spu);
 		if (ret)
 			goto bail1;
 	}
@@ -460,8 +458,7 @@
 		snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2",
 			 spu->number);
 		ret = request_irq(spu->irqs[2], spu_irq_class_2,
-				  IRQF_DISABLED,
-				  spu->irq_c2, spu);
+				  0, spu->irq_c2, spu);
 		if (ret)
 			goto bail2;
 	}
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spu_callbacks.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spu_callbacks.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spu_callbacks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spu_callbacks.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
 #undef DEBUG
 
 #include <linux/kallsyms.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/syscalls.h>
 
 #include <asm/spu.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spu_fault.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spu_fault.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spu_fault.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spu_fault.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,7 @@
  */
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/backing_ops.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/backing_ops.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/backing_ops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/backing_ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/context.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/context.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/context.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/context.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,9 +22,9 @@
 
 #include <linux/fs.h>
 #include <linux/mm.h>
-#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/atomic.h>
+#include <linux/sched.h>
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
 #include "spufs.h"
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/coredump.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/coredump.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/coredump.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/coredump.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,7 +26,6 @@
 #include <linux/fs.h>
 #include <linux/gfp.h>
 #include <linux/list.h>
-#include <linux/module.h>
 #include <linux/syscalls.h>
 
 #include <asm/uaccess.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/fault.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/fault.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/fault.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/fault.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,6 @@
  */
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/module.h>
 
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/file.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/file.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/file.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/file.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,7 @@
 
 #include <linux/fs.h>
 #include <linux/ioctl.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/pagemap.h>
 #include <linux/poll.h>
 #include <linux/ptrace.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/hw_ops.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/hw_ops.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/hw_ops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/hw_ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/sched.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/sched.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/sched.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/sched.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,6 @@
 
 #undef DEBUG
 
-#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/switch.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/switch.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/switch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/switch.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/errno.h>
 #include <linux/hardirq.h>
 #include <linux/sched.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/syscalls.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/syscalls.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spufs/syscalls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spufs/syscalls.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/file.h>
 #include <linux/fs.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/slab.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spu_manage.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spu_manage.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spu_manage.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spu_manage.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/list.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/ptrace.h>
 #include <linux/wait.h>
 #include <linux/mm.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spu_notify.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spu_notify.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spu_notify.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spu_notify.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,8 @@
 
 #undef DEBUG
 
-#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/notifier.h>
 #include <asm/spu.h>
 #include "spufs/spufs.h"
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spu_priv1_mmio.c linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spu_priv1_mmio.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/cell/spu_priv1_mmio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/cell/spu_priv1_mmio.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,6 @@
 
 #include <linux/interrupt.h>
 #include <linux/list.h>
-#include <linux/module.h>
 #include <linux/ptrace.h>
 #include <linux/wait.h>
 #include <linux/mm.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/embedded6xx/holly.c linux-libre-3.2-gnu/arch/powerpc/platforms/embedded6xx/holly.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/embedded6xx/holly.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/embedded6xx/holly.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/tty.h>
 #include <linux/serial_core.h>
 #include <linux/of_platform.h>
+#include <linux/module.h>
 
 #include <asm/system.h>
 #include <asm/time.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/embedded6xx/Kconfig linux-libre-3.2-gnu/arch/powerpc/platforms/embedded6xx/Kconfig
--- linux-libre-3.1-gnu/arch/powerpc/platforms/embedded6xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/embedded6xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -87,10 +87,6 @@
 config MPC10X_OPENPIC
 	bool
 
-config MPC10X_STORE_GATHERING
-	bool "Enable MPC10x store gathering"
-	depends on MPC10X_BRIDGE
-
 config GAMECUBE_COMMON
 	bool
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c linux-libre-3.2-gnu/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/pci.h>
 #include <linux/kdev_t.h>
 #include <linux/console.h>
+#include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/seq_file.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/embedded6xx/storcenter.c linux-libre-3.2-gnu/arch/powerpc/platforms/embedded6xx/storcenter.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/embedded6xx/storcenter.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/embedded6xx/storcenter.c	2012-01-04 18:55:44.000000000 -0500
@@ -77,7 +77,7 @@
 }
 
 /*
- * Interrupt setup and service.  Interrrupts on the turbostation come
+ * Interrupt setup and service.  Interrupts on the turbostation come
  * from the four PCI slots plus onboard 8241 devices: I2C, DUART.
  */
 static void __init storcenter_init_IRQ(void)
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/hvlpconfig.c linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/hvlpconfig.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/hvlpconfig.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/hvlpconfig.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/iseries/hv_lp_config.h>
 #include "it_lp_naca.h"
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/iommu.c linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/iommu.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/list.h>
 #include <linux/pci.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 
 #include <asm/iommu.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/ksyms.c linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/ksyms.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/ksyms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/ksyms.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
  *      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/export.h>
 
 #include <asm/hw_irq.h>
 #include <asm/iseries/hv_call_sc.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/lpardata.c linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/lpardata.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/lpardata.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/lpardata.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,6 @@
  */
 #include <linux/types.h>
 #include <linux/threads.h>
-#include <linux/module.h>
 #include <linux/bitops.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/lpevents.c linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/lpevents.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/lpevents.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/lpevents.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
 #include <linux/bootmem.h>
 #include <linux/seq_file.h>
 #include <linux/proc_fs.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/system.h>
 #include <asm/paca.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/mf.c linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/mf.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/mf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/mf.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 #include <linux/completion.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 #include <linux/proc_fs.h>
 #include <linux/dma-mapping.h>
 #include <linux/bcd.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/pci.c linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/pci.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,6 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/of.h>
 #include <linux/ratelimit.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/setup.c linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/setup.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/smp.h>
 #include <linux/param.h>
 #include <linux/string.h>
+#include <linux/export.h>
 #include <linux/seq_file.h>
 #include <linux/kdev_t.h>
 #include <linux/kexec.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/smp.c linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/smp.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,6 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/vio.c linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/vio.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/vio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/vio.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/slab.h>
 #include <linux/completion.h>
 #include <linux/proc_fs.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/firmware.h>
 #include <asm/vio.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/viopath.c linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/viopath.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/iseries/viopath.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/iseries/viopath.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,7 @@
  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/Kconfig linux-libre-3.2-gnu/arch/powerpc/platforms/Kconfig
--- linux-libre-3.1-gnu/arch/powerpc/platforms/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 menu "Platform support"
 
+source "arch/powerpc/platforms/powernv/Kconfig"
 source "arch/powerpc/platforms/pseries/Kconfig"
 source "arch/powerpc/platforms/iseries/Kconfig"
 source "arch/powerpc/platforms/chrp/Kconfig"
@@ -333,16 +334,6 @@
 
 source "arch/powerpc/sysdev/bestcomm/Kconfig"
 
-config MPC8xxx_GPIO
-	bool "MPC512x/MPC8xxx GPIO support"
-	depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \
-		   FSL_SOC_BOOKE || PPC_86xx
-	select GENERIC_GPIO
-	select ARCH_REQUIRE_GPIOLIB
-	help
-	  Say Y here if you're going to use hardware that connects to the
-	  MPC512x/831x/834x/837x/8572/8610 GPIOs.
-
 config SIMPLE_GPIO
 	bool "Support for simple, memory-mapped GPIO controllers"
 	depends on PPC
@@ -355,8 +346,8 @@
 	  on-board peripherals.
 
 config MCU_MPC8349EMITX
-	tristate "MPC8349E-mITX MCU driver"
-	depends on I2C && PPC_83xx
+	bool "MPC8349E-mITX MCU driver"
+	depends on I2C=y && PPC_83xx
 	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	help
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/Kconfig.cputype linux-libre-3.2-gnu/arch/powerpc/platforms/Kconfig.cputype
--- linux-libre-3.1-gnu/arch/powerpc/platforms/Kconfig.cputype	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/Kconfig.cputype	2012-01-04 18:55:44.000000000 -0500
@@ -69,6 +69,7 @@
 	bool "Server processors"
 	select PPC_FPU
 	select PPC_HAVE_PMU_SUPPORT
+	select SYS_SUPPORTS_HUGETLBFS
 
 config PPC_BOOK3E_64
 	bool "Embedded processors"
@@ -173,6 +174,7 @@
 config FSL_BOOKE
 	bool
 	depends on (E200 || E500) && PPC32
+	select SYS_SUPPORTS_HUGETLBFS if PHYS_64BIT
 	default y
 
 # this is for common code between PPC32 & PPC64 FSL BOOKE
@@ -282,21 +284,13 @@
 	def_bool y
 	depends on !PPC_STD_MMU
 
-config PPC_MMU_NOHASH_32
-	def_bool y
-	depends on PPC_MMU_NOHASH && PPC32
-
-config PPC_MMU_NOHASH_64
-	def_bool y
-	depends on PPC_MMU_NOHASH && PPC64
-
 config PPC_BOOK3E_MMU
 	def_bool y
 	depends on FSL_BOOKE || PPC_BOOK3E
 
 config PPC_MM_SLICES
 	bool
-	default y if HUGETLB_PAGE || (PPC_STD_MMU_64 && PPC_64K_PAGES)
+	default y if (PPC64 && HUGETLB_PAGE) || (PPC_STD_MMU_64 && PPC_64K_PAGES)
 	default n
 
 config VIRT_CPU_ACCOUNTING
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/Makefile linux-libre-3.2-gnu/arch/powerpc/platforms/Makefile
--- linux-libre-3.1-gnu/arch/powerpc/platforms/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 obj-$(CONFIG_PPC_83xx)		+= 83xx/
 obj-$(CONFIG_FSL_SOC_BOOKE)	+= 85xx/
 obj-$(CONFIG_PPC_86xx)		+= 86xx/
+obj-$(CONFIG_PPC_POWERNV)	+= powernv/
 obj-$(CONFIG_PPC_PSERIES)	+= pseries/
 obj-$(CONFIG_PPC_ISERIES)	+= iseries/
 obj-$(CONFIG_PPC_MAPLE)		+= maple/
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/maple/setup.c linux-libre-3.2-gnu/arch/powerpc/platforms/maple/setup.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/maple/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/maple/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pasemi/cpufreq.c linux-libre-3.2-gnu/arch/powerpc/platforms/pasemi/cpufreq.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pasemi/cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pasemi/cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 
 #include <linux/cpufreq.h>
 #include <linux/timer.h>
+#include <linux/module.h>
 
 #include <asm/hw_irq.h>
 #include <asm/io.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pasemi/dma_lib.c linux-libre-3.2-gnu/arch/powerpc/platforms/pasemi/dma_lib.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pasemi/dma_lib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pasemi/dma_lib.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,10 +19,11 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/sched.h>
 
 #include <asm/pasemi_dma.h>
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pasemi/setup.c linux-libre-3.2-gnu/arch/powerpc/platforms/pasemi/setup.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pasemi/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pasemi/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/console.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/of_platform.h>
 #include <linux/gfp.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powermac/backlight.c linux-libre-3.2-gnu/arch/powerpc/platforms/powermac/backlight.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powermac/backlight.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powermac/backlight.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/adb.h>
 #include <linux/pmu.h>
 #include <linux/atomic.h>
+#include <linux/export.h>
 #include <asm/prom.h>
 #include <asm/backlight.h>
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powermac/feature.c linux-libre-3.2-gnu/arch/powerpc/platforms/powermac/feature.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powermac/feature.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powermac/feature.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/adb.h>
 #include <linux/pmu.h>
 #include <linux/ioport.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <asm/sections.h>
 #include <asm/errno.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powermac/low_i2c.c linux-libre-3.2-gnu/arch/powerpc/platforms/powermac/low_i2c.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powermac/low_i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powermac/low_i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,7 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/adb.h>
 #include <linux/pmu.h>
 #include <linux/delay.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powermac/nvram.c linux-libre-3.2-gnu/arch/powerpc/platforms/powermac/nvram.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powermac/nvram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powermac/nvram.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  *
  *  Todo: - add support for the OF persistent properties
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
 #include <linux/string.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powermac/pic.c linux-libre-3.2-gnu/arch/powerpc/platforms/powermac/pic.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powermac/pic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powermac/pic.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,6 @@
 #include <linux/syscore_ops.h>
 #include <linux/adb.h>
 #include <linux/pmu.h>
-#include <linux/module.h>
 
 #include <asm/sections.h>
 #include <asm/io.h>
@@ -273,7 +272,6 @@
 
 static struct irqaction gatwick_cascade_action = {
 	.handler	= gatwick_action,
-	.flags		= IRQF_DISABLED,
 	.name		= "cascade",
 };
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powermac/setup.c linux-libre-3.2-gnu/arch/powerpc/platforms/powermac/setup.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powermac/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powermac/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
+#include <linux/export.h>
 #include <linux/user.h>
 #include <linux/tty.h>
 #include <linux/string.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powermac/smp.c linux-libre-3.2-gnu/arch/powerpc/platforms/powermac/smp.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powermac/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powermac/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -200,7 +200,7 @@
 
 	if (psurge_secondary_virq)
 		rc = request_irq(psurge_secondary_virq, psurge_ipi_intr,
-			IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL);
+			IRQF_PERCPU, "IPI", NULL);
 
 	if (rc)
 		pr_err("Failed to setup secondary cpu IPI\n");
@@ -408,7 +408,7 @@
 
 static struct irqaction psurge_irqaction = {
 	.handler = psurge_ipi_intr,
-	.flags = IRQF_DISABLED|IRQF_PERCPU,
+	.flags = IRQF_PERCPU,
 	.name = "primary IPI",
 };
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/Kconfig linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/Kconfig
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+config PPC_POWERNV
+	depends on PPC64 && PPC_BOOK3S
+	bool "IBM PowerNV (Non-Virtualized) platform support"
+	select PPC_NATIVE
+	select PPC_XICS
+	select PPC_ICP_NATIVE
+	select PPC_P7_NAP
+	select PPC_PCI_CHOICE if EMBEDDED
+	default y
+
+config PPC_POWERNV_RTAS
+	depends on PPC_POWERNV
+	bool "Support for RTAS based PowerNV platforms such as BML"
+	default y
+	select PPC_ICS_RTAS
+	select PPC_RTAS
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/Makefile linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/Makefile
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+obj-y			+= setup.o opal-takeover.o opal-wrappers.o opal.o
+obj-y			+= opal-rtc.o opal-nvram.o
+
+obj-$(CONFIG_SMP)	+= smp.o
+obj-$(CONFIG_PCI)	+= pci.o pci-p5ioc2.o
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/opal.c linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/opal.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/opal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/opal.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,322 @@
+/*
+ * PowerNV OPAL high level interfaces
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/interrupt.h>
+#include <asm/opal.h>
+#include <asm/firmware.h>
+
+#include "powernv.h"
+
+struct opal {
+	u64 base;
+	u64 entry;
+} opal;
+
+static struct device_node *opal_node;
+static DEFINE_SPINLOCK(opal_write_lock);
+extern u64 opal_mc_secondary_handler[];
+
+int __init early_init_dt_scan_opal(unsigned long node,
+				   const char *uname, int depth, void *data)
+{
+	const void *basep, *entryp;
+	unsigned long basesz, entrysz;
+	u64 glue;
+
+	if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
+		return 0;
+
+	basep  = of_get_flat_dt_prop(node, "opal-base-address", &basesz);
+	entryp = of_get_flat_dt_prop(node, "opal-entry-address", &entrysz);
+
+	if (!basep || !entryp)
+		return 1;
+
+	opal.base = of_read_number(basep, basesz/4);
+	opal.entry = of_read_number(entryp, entrysz/4);
+
+	pr_debug("OPAL Base  = 0x%llx (basep=%p basesz=%ld)\n",
+		 opal.base, basep, basesz);
+	pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%ld)\n",
+		 opal.entry, entryp, entrysz);
+
+	powerpc_firmware_features |= FW_FEATURE_OPAL;
+	if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) {
+		powerpc_firmware_features |= FW_FEATURE_OPALv2;
+		printk("OPAL V2 detected !\n");
+	} else {
+		printk("OPAL V1 detected !\n");
+	}
+
+	/* Hookup some exception handlers. We use the fwnmi area at 0x7000
+	 * to provide the glue space to OPAL
+	 */
+	glue = 0x7000;
+	opal_register_exception_handler(OPAL_MACHINE_CHECK_HANDLER,
+					__pa(opal_mc_secondary_handler[0]),
+					glue);
+	glue += 128;
+	opal_register_exception_handler(OPAL_HYPERVISOR_MAINTENANCE_HANDLER,
+					0, glue);
+	glue += 128;
+	opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);
+
+	return 1;
+}
+
+int opal_get_chars(uint32_t vtermno, char *buf, int count)
+{
+	s64 len, rc;
+	u64 evt;
+
+	if (!opal.entry)
+		return -ENODEV;
+	opal_poll_events(&evt);
+	if ((evt & OPAL_EVENT_CONSOLE_INPUT) == 0)
+		return 0;
+	len = count;
+	rc = opal_console_read(vtermno, &len, buf);
+	if (rc == OPAL_SUCCESS)
+		return len;
+	return 0;
+}
+
+int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
+{
+	int written = 0;
+	s64 len, rc;
+	unsigned long flags;
+	u64 evt;
+
+	if (!opal.entry)
+		return -ENODEV;
+
+	/* We want put_chars to be atomic to avoid mangling of hvsi
+	 * packets. To do that, we first test for room and return
+	 * -EAGAIN if there isn't enough.
+	 *
+	 * Unfortunately, opal_console_write_buffer_space() doesn't
+	 * appear to work on opal v1, so we just assume there is
+	 * enough room and be done with it
+	 */
+	spin_lock_irqsave(&opal_write_lock, flags);
+	if (firmware_has_feature(FW_FEATURE_OPALv2)) {
+		rc = opal_console_write_buffer_space(vtermno, &len);
+		if (rc || len < total_len) {
+			spin_unlock_irqrestore(&opal_write_lock, flags);
+			/* Closed -> drop characters */
+			if (rc)
+				return total_len;
+			opal_poll_events(&evt);
+			return -EAGAIN;
+		}
+	}
+
+	/* We still try to handle partial completions, though they
+	 * should no longer happen.
+	 */
+	rc = OPAL_BUSY;
+	while(total_len > 0 && (rc == OPAL_BUSY ||
+				rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) {
+		len = total_len;
+		rc = opal_console_write(vtermno, &len, data);
+		if (rc == OPAL_SUCCESS) {
+			total_len -= len;
+			data += len;
+			written += len;
+		}
+		/* This is a bit nasty but we need that for the console to
+		 * flush when there aren't any interrupts. We will clean
+		 * things a bit later to limit that to synchronous path
+		 * such as the kernel console and xmon/udbg
+		 */
+		do
+			opal_poll_events(&evt);
+		while(rc == OPAL_SUCCESS && (evt & OPAL_EVENT_CONSOLE_OUTPUT));
+	}
+	spin_unlock_irqrestore(&opal_write_lock, flags);
+	return written;
+}
+
+int opal_machine_check(struct pt_regs *regs)
+{
+	struct opal_machine_check_event *opal_evt = get_paca()->opal_mc_evt;
+	struct opal_machine_check_event evt;
+	const char *level, *sevstr, *subtype;
+	static const char *opal_mc_ue_types[] = {
+		"Indeterminate",
+		"Instruction fetch",
+		"Page table walk ifetch",
+		"Load/Store",
+		"Page table walk Load/Store",
+	};
+	static const char *opal_mc_slb_types[] = {
+		"Indeterminate",
+		"Parity",
+		"Multihit",
+	};
+	static const char *opal_mc_erat_types[] = {
+		"Indeterminate",
+		"Parity",
+		"Multihit",
+	};
+	static const char *opal_mc_tlb_types[] = {
+		"Indeterminate",
+		"Parity",
+		"Multihit",
+	};
+
+	/* Copy the event structure and release the original */
+	evt = *opal_evt;
+	opal_evt->in_use = 0;
+
+	/* Print things out */
+	if (evt.version != OpalMCE_V1) {
+		pr_err("Machine Check Exception, Unknown event version %d !\n",
+		       evt.version);
+		return 0;
+	}
+	switch(evt.severity) {
+	case OpalMCE_SEV_NO_ERROR:
+		level = KERN_INFO;
+		sevstr = "Harmless";
+		break;
+	case OpalMCE_SEV_WARNING:
+		level = KERN_WARNING;
+		sevstr = "";
+		break;
+	case OpalMCE_SEV_ERROR_SYNC:
+		level = KERN_ERR;
+		sevstr = "Severe";
+		break;
+	case OpalMCE_SEV_FATAL:
+	default:
+		level = KERN_ERR;
+		sevstr = "Fatal";
+		break;
+	}
+
+	printk("%s%s Machine check interrupt [%s]\n", level, sevstr,
+	       evt.disposition == OpalMCE_DISPOSITION_RECOVERED ?
+	       "Recovered" : "[Not recovered");
+	printk("%s  Initiator: %s\n", level,
+	       evt.initiator == OpalMCE_INITIATOR_CPU ? "CPU" : "Unknown");
+	switch(evt.error_type) {
+	case OpalMCE_ERROR_TYPE_UE:
+		subtype = evt.u.ue_error.ue_error_type <
+			ARRAY_SIZE(opal_mc_ue_types) ?
+			opal_mc_ue_types[evt.u.ue_error.ue_error_type]
+			: "Unknown";
+		printk("%s  Error type: UE [%s]\n", level, subtype);
+		if (evt.u.ue_error.effective_address_provided)
+			printk("%s    Effective address: %016llx\n",
+			       level, evt.u.ue_error.effective_address);
+		if (evt.u.ue_error.physical_address_provided)
+			printk("%s      Physial address: %016llx\n",
+			       level, evt.u.ue_error.physical_address);
+		break;
+	case OpalMCE_ERROR_TYPE_SLB:
+		subtype = evt.u.slb_error.slb_error_type <
+			ARRAY_SIZE(opal_mc_slb_types) ?
+			opal_mc_slb_types[evt.u.slb_error.slb_error_type]
+			: "Unknown";
+		printk("%s  Error type: SLB [%s]\n", level, subtype);
+		if (evt.u.slb_error.effective_address_provided)
+			printk("%s    Effective address: %016llx\n",
+			       level, evt.u.slb_error.effective_address);
+		break;
+	case OpalMCE_ERROR_TYPE_ERAT:
+		subtype = evt.u.erat_error.erat_error_type <
+			ARRAY_SIZE(opal_mc_erat_types) ?
+			opal_mc_erat_types[evt.u.erat_error.erat_error_type]
+			: "Unknown";
+		printk("%s  Error type: ERAT [%s]\n", level, subtype);
+		if (evt.u.erat_error.effective_address_provided)
+			printk("%s    Effective address: %016llx\n",
+			       level, evt.u.erat_error.effective_address);
+		break;
+	case OpalMCE_ERROR_TYPE_TLB:
+		subtype = evt.u.tlb_error.tlb_error_type <
+			ARRAY_SIZE(opal_mc_tlb_types) ?
+			opal_mc_tlb_types[evt.u.tlb_error.tlb_error_type]
+			: "Unknown";
+		printk("%s  Error type: TLB [%s]\n", level, subtype);
+		if (evt.u.tlb_error.effective_address_provided)
+			printk("%s    Effective address: %016llx\n",
+			       level, evt.u.tlb_error.effective_address);
+		break;
+	default:
+	case OpalMCE_ERROR_TYPE_UNKNOWN:
+		printk("%s  Error type: Unknown\n", level);
+		break;
+	}
+	return evt.severity == OpalMCE_SEV_FATAL ? 0 : 1;
+}
+
+static irqreturn_t opal_interrupt(int irq, void *data)
+{
+	uint64_t events;
+
+	opal_handle_interrupt(virq_to_hw(irq), &events);
+
+	/* XXX TODO: Do something with the events */
+
+	return IRQ_HANDLED;
+}
+
+static int __init opal_init(void)
+{
+	struct device_node *np, *consoles;
+	const u32 *irqs;
+	int rc, i, irqlen;
+
+	opal_node = of_find_node_by_path("/ibm,opal");
+	if (!opal_node) {
+		pr_warn("opal: Node not found\n");
+		return -ENODEV;
+	}
+	if (firmware_has_feature(FW_FEATURE_OPALv2))
+		consoles = of_find_node_by_path("/ibm,opal/consoles");
+	else
+		consoles = of_node_get(opal_node);
+
+	/* Register serial ports */
+	for_each_child_of_node(consoles, np) {
+		if (strcmp(np->name, "serial"))
+			continue;
+		of_platform_device_create(np, NULL, NULL);
+	}
+	of_node_put(consoles);
+
+	/* Find all OPAL interrupts and request them */
+	irqs = of_get_property(opal_node, "opal-interrupts", &irqlen);
+	pr_debug("opal: Found %d interrupts reserved for OPAL\n",
+		 irqs ? (irqlen / 4) : 0);
+	for (i = 0; irqs && i < (irqlen / 4); i++, irqs++) {
+		unsigned int hwirq = be32_to_cpup(irqs);
+		unsigned int irq = irq_create_mapping(NULL, hwirq);
+		if (irq == NO_IRQ) {
+			pr_warning("opal: Failed to map irq 0x%x\n", hwirq);
+			continue;
+		}
+		rc = request_irq(irq, opal_interrupt, 0, "opal", NULL);
+		if (rc)
+			pr_warning("opal: Error %d requesting irq %d"
+				   " (0x%x)\n", rc, irq, hwirq);
+	}
+	return 0;
+}
+subsys_initcall(opal_init);
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/opal-nvram.c linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/opal-nvram.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/opal-nvram.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/opal-nvram.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,88 @@
+/*
+ * PowerNV nvram code.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of.h>
+
+#include <asm/opal.h>
+#include <asm/machdep.h>
+
+static unsigned int nvram_size;
+
+static ssize_t opal_nvram_size(void)
+{
+	return nvram_size;
+}
+
+static ssize_t opal_nvram_read(char *buf, size_t count, loff_t *index)
+{
+	s64 rc;
+	int off;
+
+	if (*index >= nvram_size)
+		return 0;
+	off = *index;
+	if ((off + count) > nvram_size)
+		count = nvram_size - off;
+	rc = opal_read_nvram(__pa(buf), count, off);
+	if (rc != OPAL_SUCCESS)
+		return -EIO;
+	*index += count;
+	return count;
+}
+
+static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index)
+{
+	s64 rc = OPAL_BUSY;
+	int off;
+
+	if (*index >= nvram_size)
+		return 0;
+	off = *index;
+	if ((off + count) > nvram_size)
+		count = nvram_size - off;
+
+	while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+		rc = opal_write_nvram(__pa(buf), count, off);
+		if (rc == OPAL_BUSY_EVENT)
+			opal_poll_events(NULL);
+	}
+	*index += count;
+	return count;
+}
+
+void __init opal_nvram_init(void)
+{
+	struct device_node *np;
+	const u32 *nbytes_p;
+
+	np = of_find_compatible_node(NULL, NULL, "ibm,opal-nvram");
+	if (np == NULL)
+		return;
+
+	nbytes_p = of_get_property(np, "#bytes", NULL);
+	if (!nbytes_p) {
+		of_node_put(np);
+		return;
+	}
+	nvram_size = *nbytes_p;
+
+	printk(KERN_INFO "OPAL nvram setup, %u bytes\n", nvram_size);
+	of_node_put(np);
+
+	ppc_md.nvram_read = opal_nvram_read;
+	ppc_md.nvram_write = opal_nvram_write;
+	ppc_md.nvram_size = opal_nvram_size;
+}
+
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/opal-rtc.c linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/opal-rtc.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/opal-rtc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/opal-rtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,97 @@
+/*
+ * PowerNV Real Time Clock.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+#include <linux/delay.h>
+
+#include <asm/opal.h>
+#include <asm/firmware.h>
+
+static void opal_to_tm(u32 y_m_d, u64 h_m_s_ms, struct rtc_time *tm)
+{
+	tm->tm_year	= ((bcd2bin(y_m_d >> 24) * 100) +
+			   bcd2bin((y_m_d >> 16) & 0xff)) - 1900;
+	tm->tm_mon	= bcd2bin((y_m_d >> 8) & 0xff) - 1;
+	tm->tm_mday	= bcd2bin(y_m_d & 0xff);
+	tm->tm_hour	= bcd2bin((h_m_s_ms >> 56) & 0xff);
+	tm->tm_min	= bcd2bin((h_m_s_ms >> 48) & 0xff);
+	tm->tm_sec	= bcd2bin((h_m_s_ms >> 40) & 0xff);
+
+        GregorianDay(tm);
+}
+
+unsigned long __init opal_get_boot_time(void)
+{
+	struct rtc_time tm;
+	u32 y_m_d;
+	u64 h_m_s_ms;
+	long rc = OPAL_BUSY;
+
+	while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+		rc = opal_rtc_read(&y_m_d, &h_m_s_ms);
+		if (rc == OPAL_BUSY_EVENT)
+			opal_poll_events(NULL);
+		else
+			mdelay(10);
+	}
+	if (rc != OPAL_SUCCESS)
+		return 0;
+	opal_to_tm(y_m_d, h_m_s_ms, &tm);
+	return mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+		      tm.tm_hour, tm.tm_min, tm.tm_sec);
+}
+
+void opal_get_rtc_time(struct rtc_time *tm)
+{
+	long rc = OPAL_BUSY;
+	u32 y_m_d;
+	u64 h_m_s_ms;
+
+	while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+		rc = opal_rtc_read(&y_m_d, &h_m_s_ms);
+		if (rc == OPAL_BUSY_EVENT)
+			opal_poll_events(NULL);
+		else
+			mdelay(10);
+	}
+	if (rc != OPAL_SUCCESS)
+		return;
+	opal_to_tm(y_m_d, h_m_s_ms, tm);
+}
+
+int opal_set_rtc_time(struct rtc_time *tm)
+{
+	long rc = OPAL_BUSY;
+	u32 y_m_d = 0;
+	u64 h_m_s_ms = 0;
+
+	y_m_d |= ((u32)bin2bcd((tm->tm_year + 1900) / 100)) << 24;
+	y_m_d |= ((u32)bin2bcd((tm->tm_year + 1900) % 100)) << 16;
+	y_m_d |= ((u32)bin2bcd((tm->tm_mon + 1))) << 8;
+	y_m_d |= ((u32)bin2bcd(tm->tm_mday));
+
+	h_m_s_ms |= ((u64)bin2bcd(tm->tm_hour)) << 56;
+	h_m_s_ms |= ((u64)bin2bcd(tm->tm_min)) << 48;
+	h_m_s_ms |= ((u64)bin2bcd(tm->tm_sec)) << 40;
+
+	while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+		rc = opal_rtc_write(y_m_d, h_m_s_ms);
+		if (rc == OPAL_BUSY_EVENT)
+			opal_poll_events(NULL);
+		else
+			mdelay(10);
+	}
+	return rc == OPAL_SUCCESS ? 0 : -EIO;
+}
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/opal-takeover.S linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/opal-takeover.S
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/opal-takeover.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/opal-takeover.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,140 @@
+/*
+ * PowerNV OPAL takeover assembly code, for use by prom_init.c
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/hvcall.h>
+#include <asm/asm-offsets.h>
+#include <asm/opal.h>
+
+#define STK_PARAM(i)	(48 + ((i)-3)*8)
+
+#define H_HAL_TAKEOVER			0x5124
+#define H_HAL_TAKEOVER_QUERY_MAGIC	-1
+
+	.text
+_GLOBAL(opal_query_takeover)
+	mfcr	r0
+	stw	r0,8(r1)
+	std	r3,STK_PARAM(r3)(r1)
+	std	r4,STK_PARAM(r4)(r1)
+	li	r3,H_HAL_TAKEOVER
+	li	r4,H_HAL_TAKEOVER_QUERY_MAGIC
+	HVSC
+	ld	r10,STK_PARAM(r3)(r1)
+	std	r4,0(r10)
+	ld	r10,STK_PARAM(r4)(r1)
+	std	r5,0(r10)
+	lwz	r0,8(r1)
+	mtcrf	0xff,r0
+	blr
+
+_GLOBAL(opal_do_takeover)
+	mfcr	r0
+	stw	r0,8(r1)
+	mflr	r0
+	std	r0,16(r1)
+	bl	__opal_do_takeover
+	ld	r0,16(r1)
+	mtlr	r0
+	lwz	r0,8(r1)
+	mtcrf	0xff,r0
+	blr
+
+__opal_do_takeover:
+	ld	r4,0(r3)
+	ld	r5,0x8(r3)
+	ld	r6,0x10(r3)
+	ld	r7,0x18(r3)
+	ld	r8,0x20(r3)
+	ld	r9,0x28(r3)
+	ld	r10,0x30(r3)
+	ld	r11,0x38(r3)
+	li	r3,H_HAL_TAKEOVER
+	HVSC
+	blr
+
+	.globl opal_secondary_entry
+opal_secondary_entry:
+	mr	r31,r3
+	mfmsr	r11
+	li	r12,(MSR_SF | MSR_ISF)@highest
+	sldi	r12,r12,48
+	or	r11,r11,r12
+	mtmsrd	r11
+	isync
+	mfspr	r4,SPRN_PIR
+	std	r4,0(r3)
+1:	HMT_LOW
+	ld	r4,8(r3)
+	cmpli	cr0,r4,0
+	beq	1b
+	HMT_MEDIUM
+1:	addi	r3,r31,16
+	bl	__opal_do_takeover
+	b	1b
+
+_GLOBAL(opal_enter_rtas)
+	mflr	r0
+	std	r0,16(r1)
+        stdu	r1,-PROM_FRAME_SIZE(r1)	/* Save SP and create stack space */
+
+	/* Because PROM is running in 32b mode, it clobbers the high order half
+	 * of all registers that it saves.  We therefore save those registers
+	 * PROM might touch to the stack.  (r0, r3-r13 are caller saved)
+	*/
+	SAVE_GPR(2, r1)
+	SAVE_GPR(13, r1)
+	SAVE_8GPRS(14, r1)
+	SAVE_10GPRS(22, r1)
+	mfcr	r10
+	mfmsr	r11
+	std	r10,_CCR(r1)
+	std	r11,_MSR(r1)
+
+	/* Get the PROM entrypoint */
+	mtlr	r5
+
+	/* Switch MSR to 32 bits mode
+	 */
+        li      r12,1
+        rldicr  r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
+        andc    r11,r11,r12
+        li      r12,1
+        rldicr  r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
+        andc    r11,r11,r12
+        mtmsrd  r11
+        isync
+
+	/* Enter RTAS here... */
+	blrl
+
+	/* Just make sure that r1 top 32 bits didn't get
+	 * corrupt by OF
+	 */
+	rldicl	r1,r1,0,32
+
+	/* Restore the MSR (back to 64 bits) */
+	ld	r0,_MSR(r1)
+	MTMSRD(r0)
+        isync
+
+	/* Restore other registers */
+	REST_GPR(2, r1)
+	REST_GPR(13, r1)
+	REST_8GPRS(14, r1)
+	REST_10GPRS(22, r1)
+	ld	r4,_CCR(r1)
+	mtcr	r4
+
+        addi	r1,r1,PROM_FRAME_SIZE
+	ld	r0,16(r1)
+	mtlr    r0
+	blr
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,101 @@
+/*
+ * PowerNV OPAL API wrappers
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/hvcall.h>
+#include <asm/asm-offsets.h>
+#include <asm/opal.h>
+
+/* TODO:
+ *
+ * - Trace irqs in/off (needs saving/restoring all args, argh...)
+ * - Get r11 feed up by Dave so I can have better register usage
+ */
+#define OPAL_CALL(name, token)		\
+ _GLOBAL(name);				\
+	mflr	r0;			\
+	mfcr	r12;			\
+	std	r0,16(r1);		\
+	std	r12,8(r1);		\
+	std	r1,PACAR1(r13);		\
+	li	r0,0;			\
+	mfmsr	r12;			\
+	ori	r0,r0,MSR_EE;		\
+	std	r12,PACASAVEDMSR(r13);	\
+	andc	r12,r12,r0;		\
+	mtmsrd	r12,1;			\
+	LOAD_REG_ADDR(r0,.opal_return);	\
+	mtlr	r0;			\
+	li	r0,MSR_DR|MSR_IR;	\
+	andc	r12,r12,r0;		\
+	li	r0,token;		\
+	mtspr	SPRN_HSRR1,r12;		\
+	LOAD_REG_ADDR(r11,opal);	\
+	ld	r12,8(r11);		\
+	ld	r2,0(r11);		\
+	mtspr	SPRN_HSRR0,r12;		\
+	hrfid
+
+_STATIC(opal_return)
+	ld	r2,PACATOC(r13);
+	ld	r4,8(r1);
+	ld	r5,16(r1);
+	ld	r6,PACASAVEDMSR(r13);
+	mtspr	SPRN_SRR0,r5;
+	mtspr	SPRN_SRR1,r6;
+	mtcr	r4;
+	rfid
+
+OPAL_CALL(opal_console_write,			OPAL_CONSOLE_WRITE);
+OPAL_CALL(opal_console_read,			OPAL_CONSOLE_READ);
+OPAL_CALL(opal_console_write_buffer_space,	OPAL_CONSOLE_WRITE_BUFFER_SPACE);
+OPAL_CALL(opal_rtc_read,			OPAL_RTC_READ);
+OPAL_CALL(opal_rtc_write,			OPAL_RTC_WRITE);
+OPAL_CALL(opal_cec_power_down,			OPAL_CEC_POWER_DOWN);
+OPAL_CALL(opal_cec_reboot,			OPAL_CEC_REBOOT);
+OPAL_CALL(opal_read_nvram,			OPAL_READ_NVRAM);
+OPAL_CALL(opal_write_nvram,			OPAL_WRITE_NVRAM);
+OPAL_CALL(opal_handle_interrupt,		OPAL_HANDLE_INTERRUPT);
+OPAL_CALL(opal_poll_events,			OPAL_POLL_EVENTS);
+OPAL_CALL(opal_pci_set_hub_tce_memory,		OPAL_PCI_SET_HUB_TCE_MEMORY);
+OPAL_CALL(opal_pci_set_phb_tce_memory,		OPAL_PCI_SET_PHB_TCE_MEMORY);
+OPAL_CALL(opal_pci_config_read_byte,		OPAL_PCI_CONFIG_READ_BYTE);
+OPAL_CALL(opal_pci_config_read_half_word,	OPAL_PCI_CONFIG_READ_HALF_WORD);
+OPAL_CALL(opal_pci_config_read_word,		OPAL_PCI_CONFIG_READ_WORD);
+OPAL_CALL(opal_pci_config_write_byte,		OPAL_PCI_CONFIG_WRITE_BYTE);
+OPAL_CALL(opal_pci_config_write_half_word,	OPAL_PCI_CONFIG_WRITE_HALF_WORD);
+OPAL_CALL(opal_pci_config_write_word,		OPAL_PCI_CONFIG_WRITE_WORD);
+OPAL_CALL(opal_set_xive,			OPAL_SET_XIVE);
+OPAL_CALL(opal_get_xive,			OPAL_GET_XIVE);
+OPAL_CALL(opal_register_exception_handler,	OPAL_REGISTER_OPAL_EXCEPTION_HANDLER);
+OPAL_CALL(opal_pci_eeh_freeze_status,		OPAL_PCI_EEH_FREEZE_STATUS);
+OPAL_CALL(opal_pci_eeh_freeze_clear,		OPAL_PCI_EEH_FREEZE_CLEAR);
+OPAL_CALL(opal_pci_shpc,			OPAL_PCI_SHPC);
+OPAL_CALL(opal_pci_phb_mmio_enable,		OPAL_PCI_PHB_MMIO_ENABLE);
+OPAL_CALL(opal_pci_set_phb_mem_window,		OPAL_PCI_SET_PHB_MEM_WINDOW);
+OPAL_CALL(opal_pci_map_pe_mmio_window,		OPAL_PCI_MAP_PE_MMIO_WINDOW);
+OPAL_CALL(opal_pci_set_phb_table_memory,	OPAL_PCI_SET_PHB_TABLE_MEMORY);
+OPAL_CALL(opal_pci_set_pe,			OPAL_PCI_SET_PE);
+OPAL_CALL(opal_pci_set_peltv,			OPAL_PCI_SET_PELTV);
+OPAL_CALL(opal_pci_set_mve,			OPAL_PCI_SET_MVE);
+OPAL_CALL(opal_pci_set_mve_enable,		OPAL_PCI_SET_MVE_ENABLE);
+OPAL_CALL(opal_pci_get_xive_reissue,		OPAL_PCI_GET_XIVE_REISSUE);
+OPAL_CALL(opal_pci_set_xive_reissue,		OPAL_PCI_SET_XIVE_REISSUE);
+OPAL_CALL(opal_pci_set_xive_pe,			OPAL_PCI_SET_XIVE_PE);
+OPAL_CALL(opal_get_xive_source,			OPAL_GET_XIVE_SOURCE);
+OPAL_CALL(opal_get_msi_32,			OPAL_GET_MSI_32);
+OPAL_CALL(opal_get_msi_64,			OPAL_GET_MSI_64);
+OPAL_CALL(opal_start_cpu,			OPAL_START_CPU);
+OPAL_CALL(opal_query_cpu_status,		OPAL_QUERY_CPU_STATUS);
+OPAL_CALL(opal_write_oppanel,			OPAL_WRITE_OPPANEL);
+OPAL_CALL(opal_pci_map_pe_dma_window,		OPAL_PCI_MAP_PE_DMA_WINDOW);
+OPAL_CALL(opal_pci_map_pe_dma_window_real,	OPAL_PCI_MAP_PE_DMA_WINDOW_REAL);
+OPAL_CALL(opal_pci_reset,			OPAL_PCI_RESET);
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/pci.c linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/pci.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,427 @@
+/*
+ * Support PCI/PCIe on PowerNV platforms
+ *
+ * Currently supports only P5IOC2
+ *
+ * Copyright 2011 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/msi.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/opal.h>
+#include <asm/iommu.h>
+#include <asm/tce.h>
+#include <asm/abs_addr.h>
+
+#include "powernv.h"
+#include "pci.h"
+
+/* Delay in usec */
+#define PCI_RESET_DELAY_US	3000000
+
+#define cfg_dbg(fmt...)	do { } while(0)
+//#define cfg_dbg(fmt...)	printk(fmt)
+
+#ifdef CONFIG_PCI_MSI
+static int pnv_msi_check_device(struct pci_dev* pdev, int nvec, int type)
+{
+	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+	struct pnv_phb *phb = hose->private_data;
+
+	return (phb && phb->msi_map) ? 0 : -ENODEV;
+}
+
+static unsigned int pnv_get_one_msi(struct pnv_phb *phb)
+{
+	unsigned int id;
+
+	spin_lock(&phb->lock);
+	id = find_next_zero_bit(phb->msi_map, phb->msi_count, phb->msi_next);
+	if (id >= phb->msi_count && phb->msi_next)
+		id = find_next_zero_bit(phb->msi_map, phb->msi_count, 0);
+	if (id >= phb->msi_count) {
+		spin_unlock(&phb->lock);
+		return 0;
+	}
+	__set_bit(id, phb->msi_map);
+	spin_unlock(&phb->lock);
+	return id + phb->msi_base;
+}
+
+static void pnv_put_msi(struct pnv_phb *phb, unsigned int hwirq)
+{
+	unsigned int id;
+
+	if (WARN_ON(hwirq < phb->msi_base ||
+		    hwirq >= (phb->msi_base + phb->msi_count)))
+		return;
+	id = hwirq - phb->msi_base;
+	spin_lock(&phb->lock);
+	__clear_bit(id, phb->msi_map);
+	spin_unlock(&phb->lock);
+}
+
+static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+{
+	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+	struct pnv_phb *phb = hose->private_data;
+	struct msi_desc *entry;
+	struct msi_msg msg;
+	unsigned int hwirq, virq;
+	int rc;
+
+	if (WARN_ON(!phb))
+		return -ENODEV;
+
+	list_for_each_entry(entry, &pdev->msi_list, list) {
+		if (!entry->msi_attrib.is_64 && !phb->msi32_support) {
+			pr_warn("%s: Supports only 64-bit MSIs\n",
+				pci_name(pdev));
+			return -ENXIO;
+		}
+		hwirq = pnv_get_one_msi(phb);
+		if (!hwirq) {
+			pr_warn("%s: Failed to find a free MSI\n",
+				pci_name(pdev));
+			return -ENOSPC;
+		}
+		virq = irq_create_mapping(NULL, hwirq);
+		if (virq == NO_IRQ) {
+			pr_warn("%s: Failed to map MSI to linux irq\n",
+				pci_name(pdev));
+			pnv_put_msi(phb, hwirq);
+			return -ENOMEM;
+		}
+		rc = phb->msi_setup(phb, pdev, hwirq, entry->msi_attrib.is_64,
+				    &msg);
+		if (rc) {
+			pr_warn("%s: Failed to setup MSI\n", pci_name(pdev));
+			irq_dispose_mapping(virq);
+			pnv_put_msi(phb, hwirq);
+			return rc;
+		}
+		irq_set_msi_desc(virq, entry);
+		write_msi_msg(virq, &msg);
+	}
+	return 0;
+}
+
+static void pnv_teardown_msi_irqs(struct pci_dev *pdev)
+{
+	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+	struct pnv_phb *phb = hose->private_data;
+	struct msi_desc *entry;
+
+	if (WARN_ON(!phb))
+		return;
+
+	list_for_each_entry(entry, &pdev->msi_list, list) {
+		if (entry->irq == NO_IRQ)
+			continue;
+		irq_set_msi_desc(entry->irq, NULL);
+		pnv_put_msi(phb, virq_to_hw(entry->irq));
+		irq_dispose_mapping(entry->irq);
+	}
+}
+#endif /* CONFIG_PCI_MSI */
+
+static void pnv_pci_config_check_eeh(struct pnv_phb *phb, struct pci_bus *bus,
+				     u32 bdfn)
+{
+	s64	rc;
+	u8	fstate;
+	u16	pcierr;
+	u32	pe_no;
+
+	/* Get PE# if we support IODA */
+	pe_no = phb->bdfn_to_pe ? phb->bdfn_to_pe(phb, bus, bdfn & 0xff) : 0;
+
+	/* Read freeze status */
+	rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, &fstate, &pcierr,
+					NULL);
+	if (rc) {
+		pr_warning("PCI %d: Failed to read EEH status for PE#%d,"
+			   " err %lld\n", phb->hose->global_number, pe_no, rc);
+		return;
+	}
+	cfg_dbg(" -> EEH check, bdfn=%04x PE%d fstate=%x\n",
+		bdfn, pe_no, fstate);
+	if (fstate != 0) {
+		rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
+					      OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
+		if (rc) {
+			pr_warning("PCI %d: Failed to clear EEH freeze state"
+				   " for PE#%d, err %lld\n",
+				   phb->hose->global_number, pe_no, rc);
+		}
+	}
+}
+
+static int pnv_pci_read_config(struct pci_bus *bus,
+			       unsigned int devfn,
+			       int where, int size, u32 *val)
+{
+	struct pci_controller *hose = pci_bus_to_host(bus);
+	struct pnv_phb *phb = hose->private_data;
+	u32 bdfn = (((uint64_t)bus->number) << 8) | devfn;
+	s64 rc;
+
+	if (hose == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	switch (size) {
+	case 1: {
+		u8 v8;
+		rc = opal_pci_config_read_byte(phb->opal_id, bdfn, where, &v8);
+		*val = (rc == OPAL_SUCCESS) ? v8 : 0xff;
+		break;
+	}
+	case 2: {
+		u16 v16;
+		rc = opal_pci_config_read_half_word(phb->opal_id, bdfn, where,
+						   &v16);
+		*val = (rc == OPAL_SUCCESS) ? v16 : 0xffff;
+		break;
+	}
+	case 4: {
+		u32 v32;
+		rc = opal_pci_config_read_word(phb->opal_id, bdfn, where, &v32);
+		*val = (rc == OPAL_SUCCESS) ? v32 : 0xffffffff;
+		break;
+	}
+	default:
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+	cfg_dbg("pnv_pci_read_config bus: %x devfn: %x +%x/%x -> %08x\n",
+		bus->number, devfn, where, size, *val);
+
+	/* Check if the PHB got frozen due to an error (no response) */
+	pnv_pci_config_check_eeh(phb, bus, bdfn);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pnv_pci_write_config(struct pci_bus *bus,
+				unsigned int devfn,
+				int where, int size, u32 val)
+{
+	struct pci_controller *hose = pci_bus_to_host(bus);
+	struct pnv_phb *phb = hose->private_data;
+	u32 bdfn = (((uint64_t)bus->number) << 8) | devfn;
+
+	if (hose == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	cfg_dbg("pnv_pci_write_config bus: %x devfn: %x +%x/%x -> %08x\n",
+		bus->number, devfn, where, size, val);
+	switch (size) {
+	case 1:
+		opal_pci_config_write_byte(phb->opal_id, bdfn, where, val);
+		break;
+	case 2:
+		opal_pci_config_write_half_word(phb->opal_id, bdfn, where, val);
+		break;
+	case 4:
+		opal_pci_config_write_word(phb->opal_id, bdfn, where, val);
+		break;
+	default:
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+	/* Check if the PHB got frozen due to an error (no response) */
+	pnv_pci_config_check_eeh(phb, bus, bdfn);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops pnv_pci_ops = {
+	.read = pnv_pci_read_config,
+	.write = pnv_pci_write_config,
+};
+
+static int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
+			 unsigned long uaddr, enum dma_data_direction direction,
+			 struct dma_attrs *attrs)
+{
+	u64 proto_tce;
+	u64 *tcep;
+	u64 rpn;
+
+	proto_tce = TCE_PCI_READ; // Read allowed
+
+	if (direction != DMA_TO_DEVICE)
+		proto_tce |= TCE_PCI_WRITE;
+
+	tcep = ((u64 *)tbl->it_base) + index;
+
+	while (npages--) {
+		/* can't move this out since we might cross LMB boundary */
+		rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+		*tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+
+		uaddr += TCE_PAGE_SIZE;
+		tcep++;
+	}
+	return 0;
+}
+
+static void pnv_tce_free(struct iommu_table *tbl, long index, long npages)
+{
+	u64 *tcep = ((u64 *)tbl->it_base) + index;
+
+	while (npages--)
+		*(tcep++) = 0;
+}
+
+void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
+			       void *tce_mem, u64 tce_size,
+			       u64 dma_offset)
+{
+	tbl->it_blocksize = 16;
+	tbl->it_base = (unsigned long)tce_mem;
+	tbl->it_offset = dma_offset >> IOMMU_PAGE_SHIFT;
+	tbl->it_index = 0;
+	tbl->it_size = tce_size >> 3;
+	tbl->it_busno = 0;
+	tbl->it_type = TCE_PCI;
+}
+
+static struct iommu_table * __devinit
+pnv_pci_setup_bml_iommu(struct pci_controller *hose)
+{
+	struct iommu_table *tbl;
+	const __be64 *basep;
+	const __be32 *sizep;
+
+	basep = of_get_property(hose->dn, "linux,tce-base", NULL);
+	sizep = of_get_property(hose->dn, "linux,tce-size", NULL);
+	if (basep == NULL || sizep == NULL) {
+		pr_err("PCI: %s has missing tce entries !\n", hose->dn->full_name);
+		return NULL;
+	}
+	tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, hose->node);
+	if (WARN_ON(!tbl))
+		return NULL;
+	pnv_pci_setup_iommu_table(tbl, __va(be64_to_cpup(basep)),
+				  be32_to_cpup(sizep), 0);
+	iommu_init_table(tbl, hose->node);
+	return tbl;
+}
+
+static void __devinit pnv_pci_dma_fallback_setup(struct pci_controller *hose,
+						 struct pci_dev *pdev)
+{
+	struct device_node *np = pci_bus_to_OF_node(hose->bus);
+	struct pci_dn *pdn;
+
+	if (np == NULL)
+		return;
+	pdn = PCI_DN(np);
+	if (!pdn->iommu_table)
+		pdn->iommu_table = pnv_pci_setup_bml_iommu(hose);
+	if (!pdn->iommu_table)
+		return;
+	set_iommu_table_base(&pdev->dev, pdn->iommu_table);
+}
+
+static void __devinit pnv_pci_dma_dev_setup(struct pci_dev *pdev)
+{
+	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+	struct pnv_phb *phb = hose->private_data;
+
+	/* If we have no phb structure, try to setup a fallback based on
+	 * the device-tree (RTAS PCI for example)
+	 */
+	if (phb && phb->dma_dev_setup)
+		phb->dma_dev_setup(phb, pdev);
+	else
+		pnv_pci_dma_fallback_setup(hose, pdev);
+}
+
+static int pnv_pci_probe_mode(struct pci_bus *bus)
+{
+	struct pci_controller *hose = pci_bus_to_host(bus);
+	const __be64 *tstamp;
+	u64 now, target;
+
+
+	/* We hijack this as a way to ensure we have waited long
+	 * enough since the reset was lifted on the PCI bus
+	 */
+	if (bus != hose->bus)
+		return PCI_PROBE_NORMAL;
+	tstamp = of_get_property(hose->dn, "reset-clear-timestamp", NULL);
+	if (!tstamp || !*tstamp)
+		return PCI_PROBE_NORMAL;
+
+	now = mftb() / tb_ticks_per_usec;
+	target = (be64_to_cpup(tstamp) / tb_ticks_per_usec)
+		+ PCI_RESET_DELAY_US;
+
+	pr_devel("pci %04d: Reset target: 0x%llx now: 0x%llx\n",
+		 hose->global_number, target, now);
+
+	if (now < target)
+		msleep((target - now + 999) / 1000);
+
+	return PCI_PROBE_NORMAL;
+}
+
+void __init pnv_pci_init(void)
+{
+	struct device_node *np;
+
+	pci_set_flags(PCI_CAN_SKIP_ISA_ALIGN);
+
+	/* We do not want to just probe */
+	pci_probe_only = 0;
+
+	/* OPAL absent, try POPAL first then RTAS detection of PHBs */
+	if (!firmware_has_feature(FW_FEATURE_OPAL)) {
+#ifdef CONFIG_PPC_POWERNV_RTAS
+		init_pci_config_tokens();
+		find_and_init_phbs();
+#endif /* CONFIG_PPC_POWERNV_RTAS */
+	} else {
+		/* OPAL is here, do our normal stuff */
+
+		/* Look for p5ioc2 IO-Hubs */
+		for_each_compatible_node(np, NULL, "ibm,p5ioc2")
+			pnv_pci_init_p5ioc2_hub(np);
+	}
+
+	/* Setup the linkage between OF nodes and PHBs */
+	pci_devs_phb_init();
+
+	/* Configure IOMMU DMA hooks */
+	ppc_md.pci_dma_dev_setup = pnv_pci_dma_dev_setup;
+	ppc_md.tce_build = pnv_tce_build;
+	ppc_md.tce_free = pnv_tce_free;
+	ppc_md.pci_probe_mode = pnv_pci_probe_mode;
+	set_pci_dma_ops(&dma_iommu_ops);
+
+	/* Configure MSIs */
+#ifdef CONFIG_PCI_MSI
+	ppc_md.msi_check_device = pnv_msi_check_device;
+	ppc_md.setup_msi_irqs = pnv_setup_msi_irqs;
+	ppc_md.teardown_msi_irqs = pnv_teardown_msi_irqs;
+#endif
+}
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/pci.h linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/pci.h
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/pci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/pci.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,48 @@
+#ifndef __POWERNV_PCI_H
+#define __POWERNV_PCI_H
+
+struct pci_dn;
+
+enum pnv_phb_type {
+	PNV_PHB_P5IOC2,
+	PNV_PHB_IODA1,
+	PNV_PHB_IODA2,
+};
+
+struct pnv_phb {
+	struct pci_controller	*hose;
+	enum pnv_phb_type	type;
+	u64			opal_id;
+	void __iomem		*regs;
+	spinlock_t		lock;
+
+#ifdef CONFIG_PCI_MSI
+	unsigned long		*msi_map;
+	unsigned int		msi_base;
+	unsigned int		msi_count;
+	unsigned int		msi_next;
+	unsigned int		msi32_support;
+#endif
+	int (*msi_setup)(struct pnv_phb *phb, struct pci_dev *dev,
+			 unsigned int hwirq, unsigned int is_64,
+			 struct msi_msg *msg);
+	void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev);
+	void (*fixup_phb)(struct pci_controller *hose);
+	u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn);
+
+	union {
+		struct {
+			struct iommu_table iommu_table;
+		} p5ioc2;
+	};
+};
+
+extern struct pci_ops pnv_pci_ops;
+
+extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
+				      void *tce_mem, u64 tce_size,
+				      u64 dma_offset);
+extern void pnv_pci_init_p5ioc2_hub(struct device_node *np);
+
+
+#endif /* __POWERNV_PCI_H */
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/pci-p5ioc2.c linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/pci-p5ioc2.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/pci-p5ioc2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/pci-p5ioc2.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,234 @@
+/*
+ * Support PCI/PCIe on PowerNV platforms
+ *
+ * Currently supports only P5IOC2
+ *
+ * Copyright 2011 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/msi.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/opal.h>
+#include <asm/iommu.h>
+#include <asm/tce.h>
+#include <asm/abs_addr.h>
+
+#include "powernv.h"
+#include "pci.h"
+
+/* For now, use a fixed amount of TCE memory for each p5ioc2
+ * hub, 16M will do
+ */
+#define P5IOC2_TCE_MEMORY	0x01000000
+
+#ifdef CONFIG_PCI_MSI
+static int pnv_pci_p5ioc2_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
+				    unsigned int hwirq, unsigned int is_64,
+				    struct msi_msg *msg)
+{
+	if (WARN_ON(!is_64))
+		return -ENXIO;
+	msg->data = hwirq - phb->msi_base;
+	msg->address_hi = 0x10000000;
+	msg->address_lo = 0;
+
+	return 0;
+}
+
+static void pnv_pci_init_p5ioc2_msis(struct pnv_phb *phb)
+{
+	unsigned int bmap_size;
+	const __be32 *prop = of_get_property(phb->hose->dn,
+					     "ibm,opal-msi-ranges", NULL);
+	if (!prop)
+		return;
+
+	/* Don't do MSI's on p5ioc2 PCI-X are they are not properly
+	 * verified in HW
+	 */
+	if (of_device_is_compatible(phb->hose->dn, "ibm,p5ioc2-pcix"))
+		return;
+	phb->msi_base = be32_to_cpup(prop);
+	phb->msi_count = be32_to_cpup(prop + 1);
+	bmap_size = BITS_TO_LONGS(phb->msi_count) * sizeof(unsigned long);
+	phb->msi_map = zalloc_maybe_bootmem(bmap_size, GFP_KERNEL);
+	if (!phb->msi_map) {
+		pr_err("PCI %d: Failed to allocate MSI bitmap !\n",
+		       phb->hose->global_number);
+		return;
+	}
+	phb->msi_setup = pnv_pci_p5ioc2_msi_setup;
+	phb->msi32_support = 0;
+	pr_info(" Allocated bitmap for %d MSIs (base IRQ 0x%x)\n",
+		phb->msi_count, phb->msi_base);
+}
+#else
+static void pnv_pci_init_p5ioc2_msis(struct pnv_phb *phb) { }
+#endif /* CONFIG_PCI_MSI */
+
+static void __devinit pnv_pci_p5ioc2_dma_dev_setup(struct pnv_phb *phb,
+						   struct pci_dev *pdev)
+{
+	if (phb->p5ioc2.iommu_table.it_map == NULL)
+		iommu_init_table(&phb->p5ioc2.iommu_table, phb->hose->node);
+
+	set_iommu_table_base(&pdev->dev, &phb->p5ioc2.iommu_table);
+}
+
+static void __init pnv_pci_init_p5ioc2_phb(struct device_node *np,
+					   void *tce_mem, u64 tce_size)
+{
+	struct pnv_phb *phb;
+	const u64 *prop64;
+	u64 phb_id;
+	int64_t rc;
+	static int primary = 1;
+
+	pr_info(" Initializing p5ioc2 PHB %s\n", np->full_name);
+
+	prop64 = of_get_property(np, "ibm,opal-phbid", NULL);
+	if (!prop64) {
+		pr_err("  Missing \"ibm,opal-phbid\" property !\n");
+		return;
+	}
+	phb_id = be64_to_cpup(prop64);
+	pr_devel("  PHB-ID  : 0x%016llx\n", phb_id);
+	pr_devel("  TCE AT  : 0x%016lx\n", __pa(tce_mem));
+	pr_devel("  TCE SZ  : 0x%016llx\n", tce_size);
+
+	rc = opal_pci_set_phb_tce_memory(phb_id, __pa(tce_mem), tce_size);
+	if (rc != OPAL_SUCCESS) {
+		pr_err("  Failed to set TCE memory, OPAL error %lld\n", rc);
+		return;
+	}
+
+	phb = alloc_bootmem(sizeof(struct pnv_phb));
+	if (phb) {
+		memset(phb, 0, sizeof(struct pnv_phb));
+		phb->hose = pcibios_alloc_controller(np);
+	}
+	if (!phb || !phb->hose) {
+		pr_err("  Failed to allocate PCI controller\n");
+		return;
+	}
+
+	spin_lock_init(&phb->lock);
+	phb->hose->first_busno = 0;
+	phb->hose->last_busno = 0xff;
+	phb->hose->private_data = phb;
+	phb->opal_id = phb_id;
+	phb->type = PNV_PHB_P5IOC2;
+
+	phb->regs = of_iomap(np, 0);
+
+	if (phb->regs == NULL)
+		pr_err("  Failed to map registers !\n");
+	else {
+		pr_devel("  P_BUID     = 0x%08x\n", in_be32(phb->regs + 0x100));
+		pr_devel("  P_IOSZ     = 0x%08x\n", in_be32(phb->regs + 0x1b0));
+		pr_devel("  P_IO_ST    = 0x%08x\n", in_be32(phb->regs + 0x1e0));
+		pr_devel("  P_MEM1_H   = 0x%08x\n", in_be32(phb->regs + 0x1a0));
+		pr_devel("  P_MEM1_L   = 0x%08x\n", in_be32(phb->regs + 0x190));
+		pr_devel("  P_MSZ1_L   = 0x%08x\n", in_be32(phb->regs + 0x1c0));
+		pr_devel("  P_MEM_ST   = 0x%08x\n", in_be32(phb->regs + 0x1d0));
+		pr_devel("  P_MEM2_H   = 0x%08x\n", in_be32(phb->regs + 0x2c0));
+		pr_devel("  P_MEM2_L   = 0x%08x\n", in_be32(phb->regs + 0x2b0));
+		pr_devel("  P_MSZ2_H   = 0x%08x\n", in_be32(phb->regs + 0x2d0));
+		pr_devel("  P_MSZ2_L   = 0x%08x\n", in_be32(phb->regs + 0x2e0));
+	}
+
+	/* Interpret the "ranges" property */
+	/* This also maps the I/O region and sets isa_io/mem_base */
+	pci_process_bridge_OF_ranges(phb->hose, np, primary);
+	primary = 0;
+
+	phb->hose->ops = &pnv_pci_ops;
+
+	/* Setup MSI support */
+	pnv_pci_init_p5ioc2_msis(phb);
+
+	/* Setup TCEs */
+	phb->dma_dev_setup = pnv_pci_p5ioc2_dma_dev_setup;
+	pnv_pci_setup_iommu_table(&phb->p5ioc2.iommu_table,
+				  tce_mem, tce_size, 0);
+}
+
+void __init pnv_pci_init_p5ioc2_hub(struct device_node *np)
+{
+	struct device_node *phbn;
+	const u64 *prop64;
+	u64 hub_id;
+	void *tce_mem;
+	uint64_t tce_per_phb;
+	int64_t rc;
+	int phb_count = 0;
+
+	pr_info("Probing p5ioc2 IO-Hub %s\n", np->full_name);
+
+	prop64 = of_get_property(np, "ibm,opal-hubid", NULL);
+	if (!prop64) {
+		pr_err(" Missing \"ibm,opal-hubid\" property !\n");
+		return;
+	}
+	hub_id = be64_to_cpup(prop64);
+	pr_info(" HUB-ID : 0x%016llx\n", hub_id);
+
+	/* Currently allocate 16M of TCE memory for every Hub
+	 *
+	 * XXX TODO: Make it chip local if possible
+	 */
+	tce_mem = __alloc_bootmem(P5IOC2_TCE_MEMORY, P5IOC2_TCE_MEMORY,
+				  __pa(MAX_DMA_ADDRESS));
+	if (!tce_mem) {
+		pr_err(" Failed to allocate TCE Memory !\n");
+		return;
+	}
+	pr_debug(" TCE    : 0x%016lx..0x%016lx\n",
+		__pa(tce_mem), __pa(tce_mem) + P5IOC2_TCE_MEMORY - 1);
+	rc = opal_pci_set_hub_tce_memory(hub_id, __pa(tce_mem),
+					P5IOC2_TCE_MEMORY);
+	if (rc != OPAL_SUCCESS) {
+		pr_err(" Failed to allocate TCE memory, OPAL error %lld\n", rc);
+		return;
+	}
+
+	/* Count child PHBs */
+	for_each_child_of_node(np, phbn) {
+		if (of_device_is_compatible(phbn, "ibm,p5ioc2-pcix") ||
+		    of_device_is_compatible(phbn, "ibm,p5ioc2-pciex"))
+			phb_count++;
+	}
+
+	/* Calculate how much TCE space we can give per PHB */
+	tce_per_phb = __rounddown_pow_of_two(P5IOC2_TCE_MEMORY / phb_count);
+	pr_info(" Allocating %lld MB of TCE memory per PHB\n",
+		tce_per_phb >> 20);
+
+	/* Initialize PHBs */
+	for_each_child_of_node(np, phbn) {
+		if (of_device_is_compatible(phbn, "ibm,p5ioc2-pcix") ||
+		    of_device_is_compatible(phbn, "ibm,p5ioc2-pciex")) {
+			pnv_pci_init_p5ioc2_phb(phbn, tce_mem, tce_per_phb);
+			tce_mem += tce_per_phb;
+		}
+	}
+}
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/powernv.h linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/powernv.h
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/powernv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/powernv.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+#ifndef _POWERNV_H
+#define _POWERNV_H
+
+#ifdef CONFIG_SMP
+extern void pnv_smp_init(void);
+#else
+static inline void pnv_smp_init(void) { }
+#endif
+
+#ifdef CONFIG_PCI
+extern void pnv_pci_init(void);
+#else
+static inline void pnv_pci_init(void) { }
+#endif
+
+#endif /* _POWERNV_H */
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/setup.c linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/setup.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/setup.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,196 @@
+/*
+ * PowerNV setup code.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#undef DEBUG
+
+#include <linux/cpu.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/of.h>
+#include <linux/interrupt.h>
+#include <linux/bug.h>
+
+#include <asm/machdep.h>
+#include <asm/firmware.h>
+#include <asm/xics.h>
+#include <asm/rtas.h>
+#include <asm/opal.h>
+#include <asm/xics.h>
+
+#include "powernv.h"
+
+static void __init pnv_setup_arch(void)
+{
+	/* Initialize SMP */
+	pnv_smp_init();
+
+	/* Setup PCI */
+	pnv_pci_init();
+
+	/* Setup RTC and NVRAM callbacks */
+	if (firmware_has_feature(FW_FEATURE_OPAL))
+		opal_nvram_init();
+
+	/* Enable NAP mode */
+	powersave_nap = 1;
+
+	/* XXX PMCS */
+}
+
+static void __init pnv_init_early(void)
+{
+#ifdef CONFIG_HVC_OPAL
+	if (firmware_has_feature(FW_FEATURE_OPAL))
+		hvc_opal_init_early();
+	else
+#endif
+		add_preferred_console("hvc", 0, NULL);
+}
+
+static void __init pnv_init_IRQ(void)
+{
+	xics_init();
+
+	WARN_ON(!ppc_md.get_irq);
+}
+
+static void pnv_show_cpuinfo(struct seq_file *m)
+{
+	struct device_node *root;
+	const char *model = "";
+
+	root = of_find_node_by_path("/");
+	if (root)
+		model = of_get_property(root, "model", NULL);
+	seq_printf(m, "machine\t\t: PowerNV %s\n", model);
+	if (firmware_has_feature(FW_FEATURE_OPALv2))
+		seq_printf(m, "firmware\t: OPAL v2\n");
+	else if (firmware_has_feature(FW_FEATURE_OPAL))
+		seq_printf(m, "firmware\t: OPAL v1\n");
+	else
+		seq_printf(m, "firmware\t: BML\n");
+	of_node_put(root);
+}
+
+static void  __noreturn pnv_restart(char *cmd)
+{
+	long rc = OPAL_BUSY;
+
+	while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+		rc = opal_cec_reboot();
+		if (rc == OPAL_BUSY_EVENT)
+			opal_poll_events(NULL);
+		else
+			mdelay(10);
+	}
+	for (;;)
+		opal_poll_events(NULL);
+}
+
+static void __noreturn pnv_power_off(void)
+{
+	long rc = OPAL_BUSY;
+
+	while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+		rc = opal_cec_power_down(0);
+		if (rc == OPAL_BUSY_EVENT)
+			opal_poll_events(NULL);
+		else
+			mdelay(10);
+	}
+	for (;;)
+		opal_poll_events(NULL);
+}
+
+static void __noreturn pnv_halt(void)
+{
+	pnv_power_off();
+}
+
+static void pnv_progress(char *s, unsigned short hex)
+{
+}
+
+#ifdef CONFIG_KEXEC
+static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
+{
+	xics_kexec_teardown_cpu(secondary);
+}
+#endif /* CONFIG_KEXEC */
+
+static void __init pnv_setup_machdep_opal(void)
+{
+	ppc_md.get_boot_time = opal_get_boot_time;
+	ppc_md.get_rtc_time = opal_get_rtc_time;
+	ppc_md.set_rtc_time = opal_set_rtc_time;
+	ppc_md.restart = pnv_restart;
+	ppc_md.power_off = pnv_power_off;
+	ppc_md.halt = pnv_halt;
+	ppc_md.machine_check_exception = opal_machine_check;
+}
+
+#ifdef CONFIG_PPC_POWERNV_RTAS
+static void __init pnv_setup_machdep_rtas(void)
+{
+	if (rtas_token("get-time-of-day") != RTAS_UNKNOWN_SERVICE) {
+		ppc_md.get_boot_time = rtas_get_boot_time;
+		ppc_md.get_rtc_time = rtas_get_rtc_time;
+		ppc_md.set_rtc_time = rtas_set_rtc_time;
+	}
+	ppc_md.restart = rtas_restart;
+	ppc_md.power_off = rtas_power_off;
+	ppc_md.halt = rtas_halt;
+}
+#endif /* CONFIG_PPC_POWERNV_RTAS */
+
+static int __init pnv_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (!of_flat_dt_is_compatible(root, "ibm,powernv"))
+		return 0;
+
+	hpte_init_native();
+
+	if (firmware_has_feature(FW_FEATURE_OPAL))
+		pnv_setup_machdep_opal();
+#ifdef CONFIG_PPC_POWERNV_RTAS
+	else if (rtas.base)
+		pnv_setup_machdep_rtas();
+#endif /* CONFIG_PPC_POWERNV_RTAS */
+
+	pr_debug("PowerNV detected !\n");
+
+	return 1;
+}
+
+define_machine(powernv) {
+	.name			= "PowerNV",
+	.probe			= pnv_probe,
+	.init_early		= pnv_init_early,
+	.setup_arch		= pnv_setup_arch,
+	.init_IRQ		= pnv_init_IRQ,
+	.show_cpuinfo		= pnv_show_cpuinfo,
+	.progress		= pnv_progress,
+	.power_save             = power7_idle,
+	.calibrate_decr		= generic_calibrate_decr,
+#ifdef CONFIG_KEXEC
+	.kexec_cpu_down		= pnv_kexec_cpu_down,
+#endif
+};
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/smp.c linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/smp.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/powernv/smp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/powernv/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,182 @@
+/*
+ * SMP support for PowerNV machines.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/cpu.h>
+
+#include <asm/irq.h>
+#include <asm/smp.h>
+#include <asm/paca.h>
+#include <asm/machdep.h>
+#include <asm/cputable.h>
+#include <asm/firmware.h>
+#include <asm/system.h>
+#include <asm/rtas.h>
+#include <asm/vdso_datapage.h>
+#include <asm/cputhreads.h>
+#include <asm/xics.h>
+#include <asm/opal.h>
+
+#include "powernv.h"
+
+#ifdef DEBUG
+#include <asm/udbg.h>
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+static void __cpuinit pnv_smp_setup_cpu(int cpu)
+{
+	if (cpu != boot_cpuid)
+		xics_setup_cpu();
+}
+
+static int pnv_smp_cpu_bootable(unsigned int nr)
+{
+	/* Special case - we inhibit secondary thread startup
+	 * during boot if the user requests it.
+	 */
+	if (system_state < SYSTEM_RUNNING && cpu_has_feature(CPU_FTR_SMT)) {
+		if (!smt_enabled_at_boot && cpu_thread_in_core(nr) != 0)
+			return 0;
+		if (smt_enabled_at_boot
+		    && cpu_thread_in_core(nr) >= smt_enabled_at_boot)
+			return 0;
+	}
+
+	return 1;
+}
+
+int __devinit pnv_smp_kick_cpu(int nr)
+{
+	unsigned int pcpu = get_hard_smp_processor_id(nr);
+	unsigned long start_here = __pa(*((unsigned long *)
+					  generic_secondary_smp_init));
+	long rc;
+
+	BUG_ON(nr < 0 || nr >= NR_CPUS);
+
+	/* On OPAL v2 the CPU are still spinning inside OPAL itself,
+	 * get them back now
+	 */
+	if (firmware_has_feature(FW_FEATURE_OPALv2)) {
+		pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", nr, pcpu);
+		rc = opal_start_cpu(pcpu, start_here);
+		if (rc != OPAL_SUCCESS)
+			pr_warn("OPAL Error %ld starting CPU %d\n",
+				rc, nr);
+	}
+	return smp_generic_kick_cpu(nr);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+static int pnv_smp_cpu_disable(void)
+{
+	int cpu = smp_processor_id();
+
+	/* This is identical to pSeries... might consolidate by
+	 * moving migrate_irqs_away to a ppc_md with default to
+	 * the generic fixup_irqs. --BenH.
+	 */
+	set_cpu_online(cpu, false);
+	vdso_data->processorCount--;
+	if (cpu == boot_cpuid)
+		boot_cpuid = cpumask_any(cpu_online_mask);
+	xics_migrate_irqs_away();
+	return 0;
+}
+
+static void pnv_smp_cpu_kill_self(void)
+{
+	unsigned int cpu;
+
+	/* If powersave_nap is enabled, use NAP mode, else just
+	 * spin aimlessly
+	 */
+	if (!powersave_nap) {
+		generic_mach_cpu_die();
+		return;
+	}
+
+	/* Standard hot unplug procedure */
+	local_irq_disable();
+	idle_task_exit();
+	current->active_mm = NULL; /* for sanity */
+	cpu = smp_processor_id();
+	DBG("CPU%d offline\n", cpu);
+	generic_set_cpu_dead(cpu);
+	smp_wmb();
+
+	/* We don't want to take decrementer interrupts while we are offline,
+	 * so clear LPCR:PECE1. We keep PECE2 enabled.
+	 */
+	mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
+	while (!generic_check_cpu_restart(cpu)) {
+		power7_idle();
+		if (!generic_check_cpu_restart(cpu)) {
+			DBG("CPU%d Unexpected exit while offline !\n", cpu);
+			/* We may be getting an IPI, so we re-enable
+			 * interrupts to process it, it will be ignored
+			 * since we aren't online (hopefully)
+			 */
+			local_irq_enable();
+			local_irq_disable();
+		}
+	}
+	mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_PECE1);
+	DBG("CPU%d coming online...\n", cpu);
+}
+
+#endif /* CONFIG_HOTPLUG_CPU */
+
+static struct smp_ops_t pnv_smp_ops = {
+	.message_pass	= smp_muxed_ipi_message_pass,
+	.cause_ipi	= NULL,	/* Filled at runtime by xics_smp_probe() */
+	.probe		= xics_smp_probe,
+	.kick_cpu	= pnv_smp_kick_cpu,
+	.setup_cpu	= pnv_smp_setup_cpu,
+	.cpu_bootable	= pnv_smp_cpu_bootable,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_disable	= pnv_smp_cpu_disable,
+	.cpu_die	= generic_cpu_die,
+#endif /* CONFIG_HOTPLUG_CPU */
+};
+
+/* This is called very early during platform setup_arch */
+void __init pnv_smp_init(void)
+{
+	smp_ops = &pnv_smp_ops;
+
+	/* XXX We don't yet have a proper entry point from HAL, for
+	 * now we rely on kexec-style entry from BML
+	 */
+
+#ifdef CONFIG_PPC_RTAS
+	/* Non-lpar has additional take/give timebase */
+	if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
+		smp_ops->give_timebase = rtas_give_timebase;
+		smp_ops->take_timebase = rtas_take_timebase;
+	}
+#endif /* CONFIG_PPC_RTAS */
+
+#ifdef CONFIG_HOTPLUG_CPU
+	ppc_md.cpu_die	= pnv_smp_cpu_kill_self;
+#endif
+}
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/prep/Kconfig linux-libre-3.2-gnu/arch/powerpc/platforms/prep/Kconfig
--- linux-libre-3.1-gnu/arch/powerpc/platforms/prep/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/prep/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -21,12 +21,3 @@
 	  or pass the 'noresidual' option to the kernel.
 
 	  If you are running a PReP system, say Y here, otherwise say N.
-
-config PROC_PREPRESIDUAL
-	bool "Support for reading of PReP Residual Data in /proc"
-	depends on PREP_RESIDUAL && PROC_FS
-	help
-	  Enabling this option will create a /proc/residual file which allows
-	  you to get at the residual data on PReP systems.  You will need a tool
-	  (lsresidual) to parse it.  If you aren't on a PReP system, you don't
-	  want this.
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/device-init.c linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/device-init.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/device-init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/device-init.c	2012-01-04 18:55:44.000000000 -0500
@@ -825,7 +825,7 @@
 
 	spin_lock_init(&dev.lock);
 
-	res = request_irq(irq, ps3_notification_interrupt, IRQF_DISABLED,
+	res = request_irq(irq, ps3_notification_interrupt, 0,
 			  "ps3_notification", &dev);
 	if (res) {
 		pr_err("%s:%u: request_irq failed %d\n", __func__, __LINE__,
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/exports.c linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/exports.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/exports.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/exports.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,8 +18,6 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/module.h>
-
 #define LV1_CALL(name, in, out, num)                          \
   extern s64 _lv1_##name(LV1_##in##_IN_##out##_OUT_ARG_DECL); \
   EXPORT_SYMBOL(_lv1_##name);
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/gelic_udbg.c linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/gelic_udbg.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/gelic_udbg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/gelic_udbg.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,273 @@
+/*
+ * udbg debug output routine via GELIC UDP broadcasts
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation
+ * Copyright (C) 2010 Hector Martin <hector@marcansoft.com>
+ * Copyright (C) 2011 Andre Heider <a.heider@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.
+ *
+ */
+
+#include <asm/io.h>
+#include <asm/udbg.h>
+#include <asm/lv1call.h>
+
+#define GELIC_BUS_ID 1
+#define GELIC_DEVICE_ID 0
+#define GELIC_DEBUG_PORT 18194
+#define GELIC_MAX_MESSAGE_SIZE 1000
+
+#define GELIC_LV1_GET_MAC_ADDRESS 1
+#define GELIC_LV1_GET_VLAN_ID 4
+#define GELIC_LV1_VLAN_TX_ETHERNET_0 2
+
+#define GELIC_DESCR_DMA_STAT_MASK 0xf0000000
+#define GELIC_DESCR_DMA_CARDOWNED 0xa0000000
+
+#define GELIC_DESCR_TX_DMA_IKE 0x00080000
+#define GELIC_DESCR_TX_DMA_NO_CHKSUM 0x00000000
+#define GELIC_DESCR_TX_DMA_FRAME_TAIL 0x00040000
+
+#define GELIC_DESCR_DMA_CMD_NO_CHKSUM (GELIC_DESCR_DMA_CARDOWNED | \
+				       GELIC_DESCR_TX_DMA_IKE | \
+				       GELIC_DESCR_TX_DMA_NO_CHKSUM)
+
+static u64 bus_addr;
+
+struct gelic_descr {
+	/* as defined by the hardware */
+	__be32 buf_addr;
+	__be32 buf_size;
+	__be32 next_descr_addr;
+	__be32 dmac_cmd_status;
+	__be32 result_size;
+	__be32 valid_size;	/* all zeroes for tx */
+	__be32 data_status;
+	__be32 data_error;	/* all zeroes for tx */
+} __attribute__((aligned(32)));
+
+struct debug_block {
+	struct gelic_descr descr;
+	u8 pkt[1520];
+} __packed;
+
+struct ethhdr {
+	u8 dest[6];
+	u8 src[6];
+	u16 type;
+} __packed;
+
+struct vlantag {
+	u16 vlan;
+	u16 subtype;
+} __packed;
+
+struct iphdr {
+	u8 ver_len;
+	u8 dscp_ecn;
+	u16 total_length;
+	u16 ident;
+	u16 frag_off_flags;
+	u8 ttl;
+	u8 proto;
+	u16 checksum;
+	u32 src;
+	u32 dest;
+} __packed;
+
+struct udphdr {
+	u16 src;
+	u16 dest;
+	u16 len;
+	u16 checksum;
+} __packed;
+
+static __iomem struct ethhdr *h_eth;
+static __iomem struct vlantag *h_vlan;
+static __iomem struct iphdr *h_ip;
+static __iomem struct udphdr *h_udp;
+
+static __iomem char *pmsg;
+static __iomem char *pmsgc;
+
+static __iomem struct debug_block dbg __attribute__((aligned(32)));
+
+static int header_size;
+
+static void map_dma_mem(int bus_id, int dev_id, void *start, size_t len,
+			u64 *real_bus_addr)
+{
+	s64 result;
+	u64 real_addr = ((u64)start) & 0x0fffffffffffffffUL;
+	u64 real_end = real_addr + len;
+	u64 map_start = real_addr & ~0xfff;
+	u64 map_end = (real_end + 0xfff) & ~0xfff;
+	u64 bus_addr = 0;
+
+	u64 flags = 0xf800000000000000UL;
+
+	result = lv1_allocate_device_dma_region(bus_id, dev_id,
+						map_end - map_start, 12, 0,
+						&bus_addr);
+	if (result)
+		lv1_panic(0);
+
+	result = lv1_map_device_dma_region(bus_id, dev_id, map_start,
+					   bus_addr, map_end - map_start,
+					   flags);
+	if (result)
+		lv1_panic(0);
+
+	*real_bus_addr = bus_addr + real_addr - map_start;
+}
+
+static int unmap_dma_mem(int bus_id, int dev_id, u64 bus_addr, size_t len)
+{
+	s64 result;
+	u64 real_bus_addr;
+
+	real_bus_addr = bus_addr & ~0xfff;
+	len += bus_addr - real_bus_addr;
+	len = (len + 0xfff) & ~0xfff;
+
+	result = lv1_unmap_device_dma_region(bus_id, dev_id, real_bus_addr,
+					     len);
+	if (result)
+		return result;
+
+	return lv1_free_device_dma_region(bus_id, dev_id, real_bus_addr);
+}
+
+static void gelic_debug_init(void)
+{
+	s64 result;
+	u64 v2;
+	u64 mac;
+	u64 vlan_id;
+
+	result = lv1_open_device(GELIC_BUS_ID, GELIC_DEVICE_ID, 0);
+	if (result)
+		lv1_panic(0);
+
+	map_dma_mem(GELIC_BUS_ID, GELIC_DEVICE_ID, &dbg, sizeof(dbg),
+		    &bus_addr);
+
+	memset(&dbg, 0, sizeof(dbg));
+
+	dbg.descr.buf_addr = bus_addr + offsetof(struct debug_block, pkt);
+
+	wmb();
+
+	result = lv1_net_control(GELIC_BUS_ID, GELIC_DEVICE_ID,
+				 GELIC_LV1_GET_MAC_ADDRESS, 0, 0, 0,
+				 &mac, &v2);
+	if (result)
+		lv1_panic(0);
+
+	mac <<= 16;
+
+	h_eth = (struct ethhdr *)dbg.pkt;
+
+	memset(&h_eth->dest, 0xff, 6);
+	memcpy(&h_eth->src, &mac, 6);
+
+	header_size = sizeof(struct ethhdr);
+
+	result = lv1_net_control(GELIC_BUS_ID, GELIC_DEVICE_ID,
+				 GELIC_LV1_GET_VLAN_ID,
+				 GELIC_LV1_VLAN_TX_ETHERNET_0, 0, 0,
+				 &vlan_id, &v2);
+	if (!result) {
+		h_eth->type = 0x8100;
+
+		header_size += sizeof(struct vlantag);
+		h_vlan = (struct vlantag *)(h_eth + 1);
+		h_vlan->vlan = vlan_id;
+		h_vlan->subtype = 0x0800;
+		h_ip = (struct iphdr *)(h_vlan + 1);
+	} else {
+		h_eth->type = 0x0800;
+		h_ip = (struct iphdr *)(h_eth + 1);
+	}
+
+	header_size += sizeof(struct iphdr);
+	h_ip->ver_len = 0x45;
+	h_ip->ttl = 10;
+	h_ip->proto = 0x11;
+	h_ip->src = 0x00000000;
+	h_ip->dest = 0xffffffff;
+
+	header_size += sizeof(struct udphdr);
+	h_udp = (struct udphdr *)(h_ip + 1);
+	h_udp->src = GELIC_DEBUG_PORT;
+	h_udp->dest = GELIC_DEBUG_PORT;
+
+	pmsgc = pmsg = (char *)(h_udp + 1);
+}
+
+static void gelic_debug_shutdown(void)
+{
+	if (bus_addr)
+		unmap_dma_mem(GELIC_BUS_ID, GELIC_DEVICE_ID,
+			      bus_addr, sizeof(dbg));
+	lv1_close_device(GELIC_BUS_ID, GELIC_DEVICE_ID);
+}
+
+static void gelic_sendbuf(int msgsize)
+{
+	u16 *p;
+	u32 sum;
+	int i;
+
+	dbg.descr.buf_size = header_size + msgsize;
+	h_ip->total_length = msgsize + sizeof(struct udphdr) +
+			     sizeof(struct iphdr);
+	h_udp->len = msgsize + sizeof(struct udphdr);
+
+	h_ip->checksum = 0;
+	sum = 0;
+	p = (u16 *)h_ip;
+	for (i = 0; i < 5; i++)
+		sum += *p++;
+	h_ip->checksum = ~(sum + (sum >> 16));
+
+	dbg.descr.dmac_cmd_status = GELIC_DESCR_DMA_CMD_NO_CHKSUM |
+				    GELIC_DESCR_TX_DMA_FRAME_TAIL;
+	dbg.descr.result_size = 0;
+	dbg.descr.data_status = 0;
+
+	wmb();
+
+	lv1_net_start_tx_dma(GELIC_BUS_ID, GELIC_DEVICE_ID, bus_addr, 0);
+
+	while ((dbg.descr.dmac_cmd_status & GELIC_DESCR_DMA_STAT_MASK) ==
+	       GELIC_DESCR_DMA_CARDOWNED)
+		cpu_relax();
+}
+
+static void ps3gelic_udbg_putc(char ch)
+{
+	*pmsgc++ = ch;
+	if (ch == '\n' || (pmsgc-pmsg) >= GELIC_MAX_MESSAGE_SIZE) {
+		gelic_sendbuf(pmsgc-pmsg);
+		pmsgc = pmsg;
+	}
+}
+
+void __init udbg_init_ps3gelic(void)
+{
+	gelic_debug_init();
+	udbg_putc = ps3gelic_udbg_putc;
+}
+
+void udbg_shutdown_ps3gelic(void)
+{
+	udbg_putc = NULL;
+	gelic_debug_shutdown();
+}
+EXPORT_SYMBOL(udbg_shutdown_ps3gelic);
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/interrupt.c linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/interrupt.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/interrupt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/interrupt.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/irq.h>
 
 #include <asm/machdep.h>
@@ -88,6 +88,7 @@
 	struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN)));
 	u64 ppe_id;
 	u64 thread_id;
+	unsigned long ipi_mask;
 };
 
 static DEFINE_PER_CPU(struct ps3_private, ps3_private);
@@ -144,7 +145,11 @@
 static void ps3_chip_eoi(struct irq_data *d)
 {
 	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);
+
+	/* non-IPIs are EOIed here. */
+
+	if (!test_bit(63 - d->irq, &pd->ipi_mask))
+		lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, d->irq);
 }
 
 /**
@@ -691,6 +696,16 @@
 		cpu, virq, pd->bmp.ipi_debug_brk_mask);
 }
 
+void __init ps3_register_ipi_irq(unsigned int cpu, unsigned int virq)
+{
+	struct ps3_private *pd = &per_cpu(ps3_private, cpu);
+
+	set_bit(63 - virq, &pd->ipi_mask);
+
+	DBG("%s:%d: cpu %u, virq %u, ipi_mask %lxh\n", __func__, __LINE__,
+		cpu, virq, pd->ipi_mask);
+}
+
 static unsigned int ps3_get_irq(void)
 {
 	struct ps3_private *pd = &__get_cpu_var(ps3_private);
@@ -720,6 +735,12 @@
 		BUG();
 	}
 #endif
+
+	/* IPIs are EOIed here. */
+
+	if (test_bit(63 - plug, &pd->ipi_mask))
+		lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, plug);
+
 	return plug;
 }
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/Kconfig linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/Kconfig
--- linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -148,4 +148,16 @@
 	  profiling support of the Cell processor with programs like
 	  oprofile and perfmon2, then say Y or M, otherwise say N.
 
+config PS3GELIC_UDBG
+	bool "PS3 udbg output via UDP broadcasts on Ethernet"
+	depends on PPC_PS3
+	help
+	  Enables udbg early debugging output by sending broadcast UDP
+	  via the Ethernet port (UDP port number 18194).
+
+	  This driver uses a trivial implementation and is independent
+	  from the main network driver.
+
+	  If in doubt, say N here.
+
 endmenu
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/Makefile linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/Makefile
--- linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,7 @@
 obj-y += interrupt.o exports.o os-area.o
 obj-y += system-bus.o
 
+obj-$(CONFIG_PS3GELIC_UDBG) += gelic_udbg.o
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_SPU_BASE) += spu.o
 obj-y += device-init.o
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/mm.c linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/mm.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/mm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/mm.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/memory_hotplug.h>
 #include <linux/memblock.h>
 #include <linux/slab.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/os-area.c linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/os-area.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/os-area.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/os-area.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/workqueue.h>
 #include <linux/fs.h>
 #include <linux/syscalls.h>
+#include <linux/export.h>
 #include <linux/ctype.h>
 #include <linux/memblock.h>
 #include <linux/of.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/platform.h linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/platform.h
--- linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/platform.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/platform.h	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@
 void ps3_init_IRQ(void);
 void ps3_shutdown_IRQ(int cpu);
 void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq);
+void __init ps3_register_ipi_irq(unsigned int cpu, unsigned int virq);
 
 /* smp */
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/repository.c linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/repository.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/repository.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/repository.c	2012-01-04 18:55:44.000000000 -0500
@@ -184,7 +184,7 @@
 	enum ps3_bus_type *bus_type)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_PME,
 		make_first_field("bus", bus_index),
@@ -199,7 +199,7 @@
 	unsigned int *num_dev)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_PME,
 		make_first_field("bus", bus_index),
@@ -239,7 +239,7 @@
 	unsigned int dev_index, enum ps3_dev_type *dev_type)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_PME,
 		make_first_field("bus", bus_index),
@@ -256,8 +256,8 @@
 	enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id)
 {
 	int result;
-	u64 v1;
-	u64 v2;
+	u64 v1 = 0;
+	u64 v2 = 0;
 
 	result = read_node(PS3_LPAR_ID_PME,
 		make_first_field("bus", bus_index),
@@ -275,7 +275,7 @@
 	enum ps3_reg_type *reg_type)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_PME,
 		make_first_field("bus", bus_index),
@@ -615,7 +615,7 @@
 	unsigned int dev_index, unsigned int *num_regions)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_PME,
 		make_first_field("bus", bus_index),
@@ -631,7 +631,7 @@
 	unsigned int *region_id)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_PME,
 	    make_first_field("bus", bus_index),
@@ -786,7 +786,7 @@
 int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_CURRENT,
 		make_first_field("bi", 0),
@@ -805,7 +805,7 @@
 int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_CURRENT,
 		make_first_field("bi", 0),
@@ -827,8 +827,8 @@
 	enum ps3_spu_resource_type *resource_type, unsigned int *resource_id)
 {
 	int result;
-	u64 v1;
-	u64 v2;
+	u64 v1 = 0;
+	u64 v2 = 0;
 
 	result = read_node(PS3_LPAR_ID_CURRENT,
 		make_first_field("bi", 0),
@@ -854,7 +854,7 @@
 int ps3_repository_read_boot_dat_size(unsigned int *size)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_CURRENT,
 		make_first_field("bi", 0),
@@ -869,7 +869,7 @@
 int ps3_repository_read_vuart_av_port(unsigned int *port)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_CURRENT,
 		make_first_field("bi", 0),
@@ -884,7 +884,7 @@
 int ps3_repository_read_vuart_sysmgr_port(unsigned int *port)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_CURRENT,
 		make_first_field("bi", 0),
@@ -919,7 +919,7 @@
 int ps3_repository_read_num_be(unsigned int *num_be)
 {
 	int result;
-	u64 v1;
+	u64 v1 = 0;
 
 	result = read_node(PS3_LPAR_ID_PME,
 		make_first_field("ben", 0),
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/setup.c linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/setup.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/fs.h>
 #include <linux/root_dev.h>
 #include <linux/console.h>
+#include <linux/export.h>
 #include <linux/bootmem.h>
 
 #include <asm/machdep.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/smp.c linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/smp.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -59,46 +59,49 @@
 
 static int ps3_smp_probe(void)
 {
-	return 2;
-}
+	int cpu;
 
-static void __init ps3_smp_setup_cpu(int cpu)
-{
-	int result;
-	unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
-	int i;
+	for (cpu = 0; cpu < 2; cpu++) {
+		int result;
+		unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
+		int i;
 
-	DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
+		DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
 
-	/*
-	 * Check assumptions on ps3_ipi_virqs[] indexing. If this
-	 * check fails, then a different mapping of PPC_MSG_
-	 * to index needs to be setup.
-	 */
+		/*
+		* Check assumptions on ps3_ipi_virqs[] indexing. If this
+		* check fails, then a different mapping of PPC_MSG_
+		* to index needs to be setup.
+		*/
 
-	BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION    != 0);
-	BUILD_BUG_ON(PPC_MSG_RESCHEDULE       != 1);
-	BUILD_BUG_ON(PPC_MSG_CALL_FUNC_SINGLE != 2);
-	BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK   != 3);
+		BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION    != 0);
+		BUILD_BUG_ON(PPC_MSG_RESCHEDULE       != 1);
+		BUILD_BUG_ON(PPC_MSG_CALL_FUNC_SINGLE != 2);
+		BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK   != 3);
 
-	for (i = 0; i < MSG_COUNT; i++) {
-		result = ps3_event_receive_port_setup(cpu, &virqs[i]);
+		for (i = 0; i < MSG_COUNT; i++) {
+			result = ps3_event_receive_port_setup(cpu, &virqs[i]);
 
-		if (result)
-			continue;
+			if (result)
+				continue;
 
-		DBG("%s:%d: (%d, %d) => virq %u\n",
-			__func__, __LINE__, cpu, i, virqs[i]);
+			DBG("%s:%d: (%d, %d) => virq %u\n",
+				__func__, __LINE__, cpu, i, virqs[i]);
 
-		result = smp_request_message_ipi(virqs[i], i);
+			result = smp_request_message_ipi(virqs[i], i);
 
-		if (result)
-			virqs[i] = NO_IRQ;
-	}
+			if (result)
+				virqs[i] = NO_IRQ;
+			else
+				ps3_register_ipi_irq(cpu, virqs[i]);
+		}
 
-	ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]);
+		ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]);
 
-	DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
+		DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
+	}
+
+	return 2;
 }
 
 void ps3_smp_cleanup_cpu(int cpu)
@@ -121,7 +124,6 @@
 	.probe		= ps3_smp_probe,
 	.message_pass	= ps3_smp_message_pass,
 	.kick_cpu	= smp_generic_kick_cpu,
-	.setup_cpu	= ps3_smp_setup_cpu,
 };
 
 void smp_init_ps3(void)
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/spu.c linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/spu.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/spu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/spu.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/mmzone.h>
+#include <linux/export.h>
 #include <linux/io.h>
 #include <linux/mm.h>
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/system-bus.c linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/system-bus.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/ps3/system-bus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/ps3/system-bus.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/slab.h>
@@ -695,12 +695,18 @@
 	return mask >= DMA_BIT_MASK(32);
 }
 
+static u64 ps3_dma_get_required_mask(struct device *_dev)
+{
+	return DMA_BIT_MASK(32);
+}
+
 static struct dma_map_ops ps3_sb_dma_ops = {
 	.alloc_coherent = ps3_alloc_coherent,
 	.free_coherent = ps3_free_coherent,
 	.map_sg = ps3_sb_map_sg,
 	.unmap_sg = ps3_sb_unmap_sg,
 	.dma_supported = ps3_dma_supported,
+	.get_required_mask = ps3_dma_get_required_mask,
 	.map_page = ps3_sb_map_page,
 	.unmap_page = ps3_unmap_page,
 };
@@ -711,6 +717,7 @@
 	.map_sg = ps3_ioc0_map_sg,
 	.unmap_sg = ps3_ioc0_unmap_sg,
 	.dma_supported = ps3_dma_supported,
+	.get_required_mask = ps3_dma_get_required_mask,
 	.map_page = ps3_ioc0_map_page,
 	.unmap_page = ps3_unmap_page,
 };
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/dlpar.c linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/dlpar.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/dlpar.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/dlpar.c	2012-01-04 18:55:44.000000000 -0500
@@ -112,6 +112,7 @@
 	dlpar_free_one_cc_node(dn);
 }
 
+#define COMPLETE	0
 #define NEXT_SIBLING    1
 #define NEXT_CHILD      2
 #define NEXT_PROPERTY   3
@@ -158,6 +159,9 @@
 		spin_unlock(&rtas_data_buf_lock);
 
 		switch (rc) {
+		case COMPLETE:
+			break;
+
 		case NEXT_SIBLING:
 			dn = dlpar_parse_cc_node(ccwa);
 			if (!dn)
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/eeh.c linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/eeh.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/eeh.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/eeh.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/sched.h>	/* for init_mm */
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/pci.h>
@@ -29,6 +30,7 @@
 #include <linux/rbtree.h>
 #include <linux/seq_file.h>
 #include <linux/spinlock.h>
+#include <linux/export.h>
 #include <linux/of.h>
 
 #include <linux/atomic.h>
@@ -1338,7 +1340,7 @@
 static int __init eeh_init_proc(void)
 {
 	if (machine_is(pseries))
-		proc_create("ppc64/eeh", 0, NULL, &proc_eeh_operations);
+		proc_create("powerpc/eeh", 0, NULL, &proc_eeh_operations);
 	return 0;
 }
 __initcall(eeh_init_proc);
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/eeh_event.c linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/eeh_event.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/eeh_event.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/eeh_event.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
+#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/eeh_sysfs.c linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/eeh_sysfs.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/eeh_sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/eeh_sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
  * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com>
  */
 #include <linux/pci.h>
+#include <linux/stat.h>
 #include <asm/ppc-pci.h>
 #include <asm/pci-bridge.h>
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/hotplug-cpu.c linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/hotplug-cpu.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/hotplug-cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/hotplug-cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/sched.h>	/* for idle_task_exit */
 #include <linux/cpu.h>
 #include <asm/system.h>
 #include <asm/prom.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/hvconsole.c linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/hvconsole.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/hvconsole.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/hvconsole.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,8 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/errno.h>
 #include <asm/hvcall.h>
 #include <asm/hvconsole.h>
 #include "plpar_wrappers.h"
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/io_event_irq.c linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/io_event_irq.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/io_event_irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/io_event_irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
 
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/of.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/iommu.c linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/iommu.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/spinlock.h>
+#include <linux/sched.h>	/* for show_stack */
 #include <linux/string.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
@@ -939,14 +940,14 @@
 	if (ret) {
 		dev_info(&dev->dev, "failed to map direct window for %s: %d\n",
 			 dn->full_name, ret);
-		goto out_clear_window;
+		goto out_free_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;
+		goto out_free_window;
 	}
 
 	window->device = pdn;
@@ -958,6 +959,9 @@
 	dma_addr = of_read_number(&create.addr_hi, 2);
 	goto out_unlock;
 
+out_free_window:
+	kfree(window);
+
 out_clear_window:
 	remove_ddw(pdn);
 
@@ -1077,12 +1081,38 @@
 	return 0;
 }
 
+static u64 dma_get_required_mask_pSeriesLP(struct device *dev)
+{
+	if (!dev->dma_mask)
+		return 0;
+
+	if (!disable_ddw && dev_is_pci(dev)) {
+		struct pci_dev *pdev = to_pci_dev(dev);
+		struct device_node *dn;
+
+		dn = pci_device_to_OF_node(pdev);
+
+		/* search upwards for ibm,dma-window */
+		for (; dn && PCI_DN(dn) && !PCI_DN(dn)->iommu_table;
+				dn = dn->parent)
+			if (of_get_property(dn, "ibm,dma-window", NULL))
+				break;
+		/* if there is a ibm,ddw-applicable property require 64 bits */
+		if (dn && PCI_DN(dn) &&
+				of_get_property(dn, "ibm,ddw-applicable", NULL))
+			return DMA_BIT_MASK(64);
+	}
+
+	return dma_iommu_ops.get_required_mask(dev);
+}
+
 #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
+#define dma_get_required_mask_pSeriesLP	NULL
 #endif /* !CONFIG_PCI */
 
 static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
@@ -1186,6 +1216,7 @@
 		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;
+		ppc_md.dma_get_required_mask = dma_get_required_mask_pSeriesLP;
 	} else {
 		ppc_md.tce_build = tce_build_pSeries;
 		ppc_md.tce_free  = tce_free_pSeries;
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/Kconfig linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/Kconfig
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 	select PPC_UDBG_16550
 	select PPC_NATIVE
 	select PPC_PCI_CHOICE if EXPERT
+	select ZLIB_DEFLATE
 	default y
 
 config PPC_SPLPAR
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/lpar.c linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/lpar.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/lpar.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/lpar.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/kernel.h>
 #include <linux/dma-mapping.h>
 #include <linux/console.h>
+#include <linux/export.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/page.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/mobility.c linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/mobility.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/mobility.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/mobility.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/kobject.h>
 #include <linux/smp.h>
+#include <linux/stat.h>
 #include <linux/completion.h>
 #include <linux/device.h>
 #include <linux/delay.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/nvram.c linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/nvram.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/nvram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/nvram.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/kmsg_dump.h>
+#include <linux/ctype.h>
+#include <linux/zlib.h>
 #include <asm/uaccess.h>
 #include <asm/nvram.h>
 #include <asm/rtas.h>
@@ -78,8 +80,41 @@
 #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;
+/*
+ * For capturing and compressing an oops or panic report...
+
+ * big_oops_buf[] holds the uncompressed text we're capturing.
+ *
+ * oops_buf[] holds the compressed text, preceded by a prefix.
+ * The prefix is just a u16 holding the length of the compressed* text.
+ * (*Or uncompressed, if compression fails.)  oops_buf[] gets written
+ * to NVRAM.
+ *
+ * oops_len points to the prefix.  oops_data points to the compressed text.
+ *
+ * +- oops_buf
+ * |		+- oops_data
+ * v		v
+ * +------------+-----------------------------------------------+
+ * | length	| text                                          |
+ * | (2 bytes)	| (oops_data_sz bytes)                          |
+ * +------------+-----------------------------------------------+
+ * ^
+ * +- oops_len
+ *
+ * We preallocate these buffers during init to avoid kmalloc during oops/panic.
+ */
+static size_t big_oops_buf_sz;
+static char *big_oops_buf, *oops_buf;
+static u16 *oops_len;
+static char *oops_data;
+static size_t oops_data_sz;
+
+/* Compression parameters */
+#define COMPR_LEVEL 6
+#define WINDOW_BITS 12
+#define MEM_LEVEL 4
+static struct z_stream_s stream;
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
@@ -387,11 +422,44 @@
 						sizeof(rtas_log_partition));
 	}
 	oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
+	if (!oops_buf) {
+		pr_err("nvram: No memory for %s partition\n",
+						oops_log_partition.name);
+		return;
+	}
+	oops_len = (u16*) oops_buf;
+	oops_data = oops_buf + sizeof(u16);
+	oops_data_sz = oops_log_partition.size - sizeof(u16);
+
+	/*
+	 * Figure compression (preceded by elimination of each line's <n>
+	 * severity prefix) will reduce the oops/panic report to at most
+	 * 45% of its original size.
+	 */
+	big_oops_buf_sz = (oops_data_sz * 100) / 45;
+	big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
+	if (big_oops_buf) {
+		stream.workspace = kmalloc(zlib_deflate_workspacesize(
+				WINDOW_BITS, MEM_LEVEL), GFP_KERNEL);
+		if (!stream.workspace) {
+			pr_err("nvram: No memory for compression workspace; "
+				"skipping compression of %s partition data\n",
+				oops_log_partition.name);
+			kfree(big_oops_buf);
+			big_oops_buf = NULL;
+		}
+	} else {
+		pr_err("No memory for uncompressed %s data; "
+			"skipping compression\n", oops_log_partition.name);
+		stream.workspace = NULL;
+	}
+
 	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;
+		kfree(big_oops_buf);
+		kfree(stream.workspace);
 	}
 }
 
@@ -473,7 +541,83 @@
 						NVRAM_RTAS_READ_TIMEOUT);
 }
 
-/* our kmsg_dump callback */
+/* Squeeze out each line's <n> severity prefix. */
+static size_t elide_severities(char *buf, size_t len)
+{
+	char *in, *out, *buf_end = buf + len;
+	/* Assume a <n> at the very beginning marks the start of a line. */
+	int newline = 1;
+
+	in = out = buf;
+	while (in < buf_end) {
+		if (newline && in+3 <= buf_end &&
+				*in == '<' && isdigit(in[1]) && in[2] == '>') {
+			in += 3;
+			newline = 0;
+		} else {
+			newline = (*in == '\n');
+			*out++ = *in++;
+		}
+	}
+	return out - buf;
+}
+
+/* Derived from logfs_compress() */
+static int nvram_compress(const void *in, void *out, size_t inlen,
+							size_t outlen)
+{
+	int err, ret;
+
+	ret = -EIO;
+	err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
+						MEM_LEVEL, Z_DEFAULT_STRATEGY);
+	if (err != Z_OK)
+		goto error;
+
+	stream.next_in = in;
+	stream.avail_in = inlen;
+	stream.total_in = 0;
+	stream.next_out = out;
+	stream.avail_out = outlen;
+	stream.total_out = 0;
+
+	err = zlib_deflate(&stream, Z_FINISH);
+	if (err != Z_STREAM_END)
+		goto error;
+
+	err = zlib_deflateEnd(&stream);
+	if (err != Z_OK)
+		goto error;
+
+	if (stream.total_out >= stream.total_in)
+		goto error;
+
+	ret = stream.total_out;
+error:
+	return ret;
+}
+
+/* Compress the text from big_oops_buf into oops_buf. */
+static int zip_oops(size_t text_len)
+{
+	int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
+								oops_data_sz);
+	if (zipped_len < 0) {
+		pr_err("nvram: compression failed; returned %d\n", zipped_len);
+		pr_err("nvram: logging uncompressed oops/panic report\n");
+		return -1;
+	}
+	*oops_len = (u16) zipped_len;
+	return 0;
+}
+
+/*
+ * This is our kmsg_dump callback, called after an oops or panic report
+ * has been written to the printk buffer.  We want to capture as much
+ * of the printk buffer as possible.  First, capture as much as we can
+ * that we think will compress sufficiently to fit in the lnx,oops-log
+ * partition.  If that's too much, go back and capture uncompressed text.
+ */
 static void oops_to_nvram(struct kmsg_dumper *dumper,
 		enum kmsg_dump_reason reason,
 		const char *old_msgs, unsigned long old_len,
@@ -482,6 +626,8 @@
 	static unsigned int oops_count = 0;
 	static bool panicking = false;
 	size_t text_len;
+	unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ;
+	int rc = -1;
 
 	switch (reason) {
 	case KMSG_DUMP_RESTART:
@@ -509,8 +655,19 @@
 	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);
+	if (big_oops_buf) {
+		text_len = capture_last_msgs(old_msgs, old_len,
+			new_msgs, new_len, big_oops_buf, big_oops_buf_sz);
+		text_len = elide_severities(big_oops_buf, text_len);
+		rc = zip_oops(text_len);
+	}
+	if (rc != 0) {
+		text_len = capture_last_msgs(old_msgs, old_len,
+				new_msgs, new_len, oops_data, oops_data_sz);
+		err_type = ERR_TYPE_KERNEL_PANIC;
+		*oops_len = (u16) text_len;
+	}
+
 	(void) nvram_write_os_partition(&oops_log_partition, oops_buf,
-		(int) text_len, ERR_TYPE_KERNEL_PANIC, ++oops_count);
+		(int) (sizeof(*oops_len) + *oops_len), err_type, ++oops_count);
 }
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/pci_dlpar.c linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/pci_dlpar.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/pci_dlpar.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/pci_dlpar.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
  */
 
 #include <linux/pci.h>
+#include <linux/export.h>
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
 #include <asm/firmware.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/plpar_wrappers.h linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/plpar_wrappers.h
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/plpar_wrappers.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/plpar_wrappers.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,10 @@
 #ifndef _PSERIES_PLPAR_WRAPPERS_H
 #define _PSERIES_PLPAR_WRAPPERS_H
 
+#include <linux/string.h>
+
 #include <asm/hvcall.h>
+#include <asm/paca.h>
 #include <asm/page.h>
 
 /* Get state of physical CPU from query_cpu_stopped */
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/setup.c linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/setup.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,7 +34,7 @@
 #include <linux/pci.h>
 #include <linux/utsname.h>
 #include <linux/adb.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/seq_file.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/smp.c linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/smp.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,6 @@
 
 
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/suspend.c linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/suspend.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/pseries/suspend.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/pseries/suspend.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 
 #include <linux/delay.h>
 #include <linux/suspend.h>
+#include <linux/stat.h>
 #include <asm/firmware.h>
 #include <asm/hvcall.h>
 #include <asm/machdep.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/ics.c linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/ics.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/ics.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/ics.c	2012-01-04 18:55:44.000000000 -0500
@@ -710,3 +710,51 @@
 	/* We need to patch our irq chip's EOI to point to the right ICP */
 	wsp_irq_chip.irq_eoi = icp_ops->eoi;
 }
+
+#ifdef CONFIG_PCI_MSI
+static void wsp_ics_msi_unmask_irq(struct irq_data *d)
+{
+	wsp_chip_unmask_irq(d);
+	unmask_msi_irq(d);
+}
+
+static unsigned int wsp_ics_msi_startup(struct irq_data *d)
+{
+	wsp_ics_msi_unmask_irq(d);
+	return 0;
+}
+
+static void wsp_ics_msi_mask_irq(struct irq_data *d)
+{
+	mask_msi_irq(d);
+	wsp_chip_mask_irq(d);
+}
+
+/*
+ * we do it this way because we reassinge default EOI handling in
+ * irq_init() above
+ */
+static void wsp_ics_eoi(struct irq_data *data)
+{
+	wsp_irq_chip.irq_eoi(data);
+}
+
+static struct irq_chip wsp_ics_msi = {
+	.name = "WSP ICS MSI",
+	.irq_startup = wsp_ics_msi_startup,
+	.irq_mask = wsp_ics_msi_mask_irq,
+	.irq_unmask = wsp_ics_msi_unmask_irq,
+	.irq_eoi = wsp_ics_eoi,
+	.irq_set_affinity = wsp_chip_set_affinity
+};
+
+void wsp_ics_set_msi_chip(unsigned int irq)
+{
+	irq_set_chip(irq, &wsp_ics_msi);
+}
+
+void wsp_ics_set_std_chip(unsigned int irq)
+{
+	irq_set_chip(irq, &wsp_irq_chip);
+}
+#endif /* CONFIG_PCI_MSI */
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/ics.h linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/ics.h
--- linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/ics.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/ics.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,4 +17,9 @@
 extern int wsp_ics_alloc_irq(struct device_node *dn, int num);
 extern void wsp_ics_free_irq(struct device_node *dn, unsigned int irq);
 
+#ifdef CONFIG_PCI_MSI
+extern void wsp_ics_set_msi_chip(unsigned int irq);
+extern void wsp_ics_set_std_chip(unsigned int irq);
+#endif /* CONFIG_PCI_MSI */
+
 #endif /* __ICS_H */
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/Kconfig linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/Kconfig
--- linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,12 @@
 config PPC_WSP
 	bool
+	select PPC_A2
+	select PPC_SCOM
+	select PPC_XICS
+	select PPC_ICP_NATIVE
+	select PCI
+	select PPC_IO_WORKAROUNDS if PCI
+	select PPC_INDIRECT_PIO if PCI
 	default n
 
 menu "WSP platform selection"
@@ -7,13 +14,9 @@
 
 config PPC_PSR2
 	bool "PSR-2 platform"
-	select PPC_A2
 	select GENERIC_TBSYNC
-	select PPC_SCOM
 	select EPAPR_BOOT
 	select PPC_WSP
-	select PPC_XICS
-	select PPC_ICP_NATIVE
 	default y
 
 endmenu
@@ -21,8 +24,3 @@
 config PPC_A2_DD2
 	bool "Support for DD2 based A2/WSP systems"
 	depends on PPC_A2
-
-config WORKAROUND_ERRATUM_463
-	depends on PPC_A2_DD2
-	bool "Workaround erratum 463"
-	default y
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/Makefile linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/Makefile
--- linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,3 +4,5 @@
 obj-$(CONFIG_PPC_PSR2)		+= psr2.o opb_pic.o
 obj-$(CONFIG_PPC_WSP)		+= scom_wsp.o
 obj-$(CONFIG_SMP)		+= smp.o scom_smp.o
+obj-$(CONFIG_PCI)		+= wsp_pci.o
+obj-$(CONFIG_PCI_MSI)		+= msi.o
\ No newline at end of file
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/msi.c linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/msi.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/msi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/msi.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2011 Michael Ellerman, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/msi.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include "msi.h"
+#include "ics.h"
+#include "wsp_pci.h"
+
+/* Magic addresses for 32 & 64-bit MSIs with hardcoded MVE 0 */
+#define MSI_ADDR_32		0xFFFF0000ul
+#define MSI_ADDR_64		0x1000000000000000ul
+
+int wsp_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+	struct pci_controller *phb;
+	struct msi_desc *entry;
+	struct msi_msg msg;
+	unsigned int virq;
+	int hwirq;
+
+	phb = pci_bus_to_host(dev->bus);
+	if (!phb)
+		return -ENOENT;
+
+	entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
+	if (entry->msi_attrib.is_64) {
+		msg.address_lo = 0;
+		msg.address_hi = MSI_ADDR_64 >> 32;
+	} else {
+		msg.address_lo = MSI_ADDR_32;
+		msg.address_hi = 0;
+	}
+
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		hwirq = wsp_ics_alloc_irq(phb->dn, 1);
+		if (hwirq < 0) {
+			dev_warn(&dev->dev, "wsp_msi: hwirq alloc failed!\n");
+			return hwirq;
+		}
+
+		virq = irq_create_mapping(NULL, hwirq);
+		if (virq == NO_IRQ) {
+			dev_warn(&dev->dev, "wsp_msi: virq alloc failed!\n");
+			return -1;
+		}
+
+		dev_dbg(&dev->dev, "wsp_msi: allocated irq %#x/%#x\n",
+			hwirq, virq);
+
+		wsp_ics_set_msi_chip(virq);
+		irq_set_msi_desc(virq, entry);
+		msg.data = hwirq & XIVE_ADDR_MASK;
+		write_msi_msg(virq, &msg);
+	}
+
+	return 0;
+}
+
+void wsp_teardown_msi_irqs(struct pci_dev *dev)
+{
+	struct pci_controller *phb;
+	struct msi_desc *entry;
+	int hwirq;
+
+	phb = pci_bus_to_host(dev->bus);
+
+	dev_dbg(&dev->dev, "wsp_msi: tearing down msi irqs\n");
+
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		if (entry->irq == NO_IRQ)
+			continue;
+
+		irq_set_msi_desc(entry->irq, NULL);
+		wsp_ics_set_std_chip(entry->irq);
+
+		hwirq = virq_to_hw(entry->irq);
+		/* In this order to avoid racing with irq_create_mapping() */
+		irq_dispose_mapping(entry->irq);
+		wsp_ics_free_irq(phb->dn, hwirq);
+	}
+}
+
+void wsp_setup_phb_msi(struct pci_controller *phb)
+{
+	/* Create a single MVE at offset 0 that matches everything */
+	out_be64(phb->cfg_data + PCIE_REG_IODA_ADDR, PCIE_REG_IODA_AD_TBL_MVT);
+	out_be64(phb->cfg_data + PCIE_REG_IODA_DATA0, 1ull << 63);
+
+	ppc_md.setup_msi_irqs = wsp_setup_msi_irqs;
+	ppc_md.teardown_msi_irqs = wsp_teardown_msi_irqs;
+}
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/msi.h linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/msi.h
--- linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/msi.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/msi.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2011 Michael Ellerman, IBM Corp.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ */
+
+#ifndef __WSP_MSI_H
+#define __WSP_MSI_H
+
+#ifdef CONFIG_PCI_MSI
+extern void wsp_setup_phb_msi(struct pci_controller *phb);
+#else
+static inline void wsp_setup_phb_msi(struct pci_controller *phb) { }
+#endif
+
+#endif /* __WSP_MSI_H */
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/psr2.c linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/psr2.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/psr2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/psr2.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,6 +63,10 @@
 #ifdef CONFIG_SMP
 	a2_setup_smp();
 #endif
+#ifdef CONFIG_PCI
+	wsp_setup_pci();
+#endif
+
 }
 
 static int __init psr2_probe(void)
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/wsp.h linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/wsp.h
--- linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/wsp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/wsp.h	2012-01-04 18:55:44.000000000 -0500
@@ -3,6 +3,9 @@
 
 #include <asm/wsp.h>
 
+/* Devtree compatible strings for major devices */
+#define PCIE_COMPATIBLE     "ibm,wsp-pciex"
+
 extern void wsp_setup_pci(void);
 extern void scom_init_wsp(void);
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/wsp_pci.c linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/wsp_pci.c
--- linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/wsp_pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/wsp_pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1133 @@
+/*
+ * Copyright 2010 Ben Herrenschmidt, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/debugfs.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/iommu.h>
+#include <asm/io-workarounds.h>
+
+#include "wsp.h"
+#include "wsp_pci.h"
+#include "msi.h"
+
+
+/* Max number of TVTs for one table. Only 32-bit tables can use
+ * multiple TVTs and so the max currently supported is thus 8
+ * since only 2G of DMA space is supported
+ */
+#define MAX_TABLE_TVT_COUNT		8
+
+struct wsp_dma_table {
+	struct list_head	link;
+	struct iommu_table	table;
+	struct wsp_phb	*phb;
+	struct page		*tces[MAX_TABLE_TVT_COUNT];
+};
+
+/* We support DMA regions from 0...2G in 32bit space (no support for
+ * 64-bit DMA just yet). Each device gets a separate TCE table (TVT
+ * entry) with validation enabled (though not supported by SimiCS
+ * just yet).
+ *
+ * To simplify things, we divide this 2G space into N regions based
+ * on the constant below which could be turned into a tunable eventually
+ *
+ * We then assign dynamically those regions to devices as they show up.
+ *
+ * We use a bitmap as an allocator for these.
+ *
+ * Tables are allocated/created dynamically as devices are discovered,
+ * multiple TVT entries are used if needed
+ *
+ * When 64-bit DMA support is added we should simply use a separate set
+ * of larger regions (the HW supports 64 TVT entries). We can
+ * additionally create a bypass region in 64-bit space for performances
+ * though that would have a cost in term of security.
+ *
+ * If you set NUM_DMA32_REGIONS to 1, then a single table is shared
+ * for all devices and bus/dev/fn validation is disabled
+ *
+ * Note that a DMA32 region cannot be smaller than 256M so the max
+ * supported here for now is 8. We don't yet support sharing regions
+ * between multiple devices so the max number of devices supported
+ * is MAX_TABLE_TVT_COUNT.
+ */
+#define NUM_DMA32_REGIONS	1
+
+struct wsp_phb {
+	struct pci_controller	*hose;
+
+	/* Lock controlling access to the list of dma tables.
+	 * It does -not- protect against dma_* operations on
+	 * those tables, those should be stopped before an entry
+	 * is removed from the list.
+	 *
+	 * The lock is also used for error handling operations
+	 */
+	spinlock_t		lock;
+	struct list_head	dma_tables;
+	unsigned long		dma32_map;
+	unsigned long		dma32_base;
+	unsigned int		dma32_num_regions;
+	unsigned long		dma32_region_size;
+
+	/* Debugfs stuff */
+	struct dentry		*ddir;
+
+	struct list_head	all;
+};
+static LIST_HEAD(wsp_phbs);
+
+//#define cfg_debug(fmt...)	pr_debug(fmt)
+#define cfg_debug(fmt...)
+
+
+static int wsp_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
+				  int offset, int len, u32 *val)
+{
+	struct pci_controller *hose;
+	int suboff;
+	u64 addr;
+
+	hose = pci_bus_to_host(bus);
+	if (hose == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (offset >= 0x1000)
+		return  PCIBIOS_BAD_REGISTER_NUMBER;
+	addr = PCIE_REG_CA_ENABLE |
+		((u64)bus->number) << PCIE_REG_CA_BUS_SHIFT |
+		((u64)devfn) << PCIE_REG_CA_FUNC_SHIFT |
+		((u64)offset & ~3) << PCIE_REG_CA_REG_SHIFT;
+	suboff = offset & 3;
+
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+
+	switch (len) {
+	case 1:
+		addr |= (0x8ul >> suboff) << PCIE_REG_CA_BE_SHIFT;
+		out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+		*val = (in_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA)
+			>> (suboff << 3)) & 0xff;
+		cfg_debug("read 1 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%02x\n",
+			  bus->number, devfn >> 3, devfn & 7,
+			  offset, suboff, addr, *val);
+		break;
+	case 2:
+		addr |= (0xcul >> suboff) << PCIE_REG_CA_BE_SHIFT;
+		out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+		*val = (in_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA)
+			>> (suboff << 3)) & 0xffff;
+		cfg_debug("read 2 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%04x\n",
+			  bus->number, devfn >> 3, devfn & 7,
+			  offset, suboff, addr, *val);
+		break;
+	default:
+		addr |= 0xful << PCIE_REG_CA_BE_SHIFT;
+		out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+		*val = in_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA);
+		cfg_debug("read 4 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%08x\n",
+			  bus->number, devfn >> 3, devfn & 7,
+			  offset, suboff, addr, *val);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int wsp_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
+				   int offset, int len, u32 val)
+{
+	struct pci_controller *hose;
+	int suboff;
+	u64 addr;
+
+	hose = pci_bus_to_host(bus);
+	if (hose == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (offset >= 0x1000)
+		return  PCIBIOS_BAD_REGISTER_NUMBER;
+	addr = PCIE_REG_CA_ENABLE |
+		((u64)bus->number) << PCIE_REG_CA_BUS_SHIFT |
+		((u64)devfn) << PCIE_REG_CA_FUNC_SHIFT |
+		((u64)offset & ~3) << PCIE_REG_CA_REG_SHIFT;
+	suboff = offset & 3;
+
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		addr |= (0x8ul >> suboff) << PCIE_REG_CA_BE_SHIFT;
+		val <<= suboff << 3;
+		out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+		out_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA, val);
+		cfg_debug("write 1 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%02x\n",
+			  bus->number, devfn >> 3, devfn & 7,
+			  offset, suboff, addr, val);
+		break;
+	case 2:
+		addr |= (0xcul >> suboff) << PCIE_REG_CA_BE_SHIFT;
+		val <<= suboff << 3;
+		out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+		out_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA, val);
+		cfg_debug("write 2 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%04x\n",
+			  bus->number, devfn >> 3, devfn & 7,
+			  offset, suboff, addr, val);
+		break;
+	default:
+		addr |= 0xful << PCIE_REG_CA_BE_SHIFT;
+		out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+		out_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA, val);
+		cfg_debug("write 4 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%08x\n",
+			  bus->number, devfn >> 3, devfn & 7,
+			  offset, suboff, addr, val);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops wsp_pcie_pci_ops =
+{
+	.read = wsp_pcie_read_config,
+	.write = wsp_pcie_write_config,
+};
+
+#define TCE_SHIFT		12
+#define TCE_PAGE_SIZE		(1 << TCE_SHIFT)
+#define TCE_PCI_WRITE		0x2		 /* write from PCI allowed */
+#define TCE_PCI_READ		0x1	 	 /* read from PCI allowed */
+#define TCE_RPN_MASK		0x3fffffffffful  /* 42-bit RPN (4K pages) */
+#define TCE_RPN_SHIFT		12
+
+//#define dma_debug(fmt...)	pr_debug(fmt)
+#define dma_debug(fmt...)
+
+static int tce_build_wsp(struct iommu_table *tbl, long index, long npages,
+			   unsigned long uaddr, enum dma_data_direction direction,
+			   struct dma_attrs *attrs)
+{
+	struct wsp_dma_table *ptbl = container_of(tbl,
+						    struct wsp_dma_table,
+						    table);
+	u64 proto_tce;
+	u64 *tcep;
+	u64 rpn;
+
+	proto_tce = TCE_PCI_READ;
+#ifdef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
+	proto_tce |= TCE_PCI_WRITE;
+#else
+	if (direction != DMA_TO_DEVICE)
+		proto_tce |= TCE_PCI_WRITE;
+#endif
+
+	/* XXX Make this faster by factoring out the page address for
+	 * within a TCE table
+	 */
+	while (npages--) {
+		/* We don't use it->base as the table can be scattered */
+		tcep = (u64 *)page_address(ptbl->tces[index >> 16]);
+		tcep += (index & 0xffff);
+
+		/* can't move this out since we might cross LMB boundary */
+		rpn = __pa(uaddr) >> TCE_SHIFT;
+		*tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+
+		dma_debug("[DMA] TCE %p set to 0x%016llx (dma addr: 0x%lx)\n",
+			  tcep, *tcep, (tbl->it_offset + index) << IOMMU_PAGE_SHIFT);
+
+		uaddr += TCE_PAGE_SIZE;
+		index++;
+	}
+	return 0;
+}
+
+static void tce_free_wsp(struct iommu_table *tbl, long index, long npages)
+{
+	struct wsp_dma_table *ptbl = container_of(tbl,
+						    struct wsp_dma_table,
+						    table);
+#ifndef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
+	struct pci_controller *hose = ptbl->phb->hose;
+#endif
+	u64 *tcep;
+
+	/* XXX Make this faster by factoring out the page address for
+	 * within a TCE table. Also use line-kill option to kill multiple
+	 * TCEs at once
+	 */
+	while (npages--) {
+		/* We don't use it->base as the table can be scattered */
+		tcep = (u64 *)page_address(ptbl->tces[index >> 16]);
+		tcep += (index & 0xffff);
+		dma_debug("[DMA] TCE %p cleared\n", tcep);
+		*tcep = 0;
+#ifndef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
+		/* Don't write there since it would pollute other MMIO accesses */
+		out_be64(hose->cfg_data + PCIE_REG_TCE_KILL,
+			 PCIE_REG_TCEKILL_SINGLE | PCIE_REG_TCEKILL_PS_4K |
+			 (__pa(tcep) & PCIE_REG_TCEKILL_ADDR_MASK));
+#endif
+		index++;
+	}
+}
+
+static struct wsp_dma_table *wsp_pci_create_dma32_table(struct wsp_phb *phb,
+							    unsigned int region,
+							    struct pci_dev *validate)
+{
+	struct pci_controller *hose = phb->hose;
+	unsigned long size = phb->dma32_region_size;
+	unsigned long addr = phb->dma32_region_size * region + phb->dma32_base;
+	struct wsp_dma_table *tbl;
+	int tvts_per_table, i, tvt, nid;
+	unsigned long flags;
+
+	nid = of_node_to_nid(phb->hose->dn);
+
+	/* Calculate how many TVTs are needed */
+	tvts_per_table = size / 0x10000000;
+	if (tvts_per_table == 0)
+		tvts_per_table = 1;
+
+	/* Calculate the base TVT index. We know all tables have the same
+	 * size so we just do a simple multiply here
+	 */
+	tvt = region * tvts_per_table;
+
+	pr_debug("         Region : %d\n", region);
+	pr_debug("      DMA range : 0x%08lx..0x%08lx\n", addr, addr + size - 1);
+	pr_debug(" Number of TVTs : %d\n", tvts_per_table);
+	pr_debug("       Base TVT : %d\n", tvt);
+	pr_debug("         Node   : %d\n", nid);
+
+	tbl = kzalloc_node(sizeof(struct wsp_dma_table), GFP_KERNEL, nid);
+	if (!tbl)
+		return ERR_PTR(-ENOMEM);
+	tbl->phb = phb;
+
+	/* Create as many TVTs as needed, each represents 256M at most */
+	for (i = 0; i < tvts_per_table; i++) {
+		u64 tvt_data1, tvt_data0;
+
+		/* Allocate table. We use a 4K TCE size for now always so
+		 * one table is always 8 * (258M / 4K) == 512K
+		 */
+		tbl->tces[i] = alloc_pages_node(nid, GFP_KERNEL, get_order(0x80000));
+		if (tbl->tces[i] == NULL)
+			goto fail;
+		memset(page_address(tbl->tces[i]), 0, 0x80000);
+
+		pr_debug(" TCE table %d at : %p\n", i, page_address(tbl->tces[i]));
+
+		/* Table size. We currently set it to be the whole 256M region */
+		tvt_data0 = 2ull << IODA_TVT0_TCE_TABLE_SIZE_SHIFT;
+		/* IO page size set to 4K */
+		tvt_data1 = 1ull << IODA_TVT1_IO_PAGE_SIZE_SHIFT;
+		/* Shift in the address */
+		tvt_data0 |= __pa(page_address(tbl->tces[i])) << IODA_TVT0_TTA_SHIFT;
+
+		/* Validation stuff. We only validate fully bus/dev/fn for now
+		 * one day maybe we can group devices but that isn't the case
+		 * at the moment
+		 */
+		if (validate) {
+			tvt_data0 |= IODA_TVT0_BUSNUM_VALID_MASK;
+			tvt_data0 |= validate->bus->number;
+			tvt_data1 |= IODA_TVT1_DEVNUM_VALID;
+			tvt_data1 |= ((u64)PCI_SLOT(validate->devfn))
+				<< IODA_TVT1_DEVNUM_VALUE_SHIFT;
+			tvt_data1 |= IODA_TVT1_FUNCNUM_VALID;
+			tvt_data1 |= ((u64)PCI_FUNC(validate->devfn))
+				<< IODA_TVT1_FUNCNUM_VALUE_SHIFT;
+		}
+
+		/* XX PE number is always 0 for now */
+
+		/* Program the values using the PHB lock */
+		spin_lock_irqsave(&phb->lock, flags);
+		out_be64(hose->cfg_data + PCIE_REG_IODA_ADDR,
+			 (tvt + i) | PCIE_REG_IODA_AD_TBL_TVT);
+		out_be64(hose->cfg_data + PCIE_REG_IODA_DATA1, tvt_data1);
+		out_be64(hose->cfg_data + PCIE_REG_IODA_DATA0, tvt_data0);
+		spin_unlock_irqrestore(&phb->lock, flags);
+	}
+
+	/* Init bits and pieces */
+	tbl->table.it_blocksize = 16;
+	tbl->table.it_offset = addr >> IOMMU_PAGE_SHIFT;
+	tbl->table.it_size = size >> IOMMU_PAGE_SHIFT;
+
+	/*
+	 * It's already blank but we clear it anyway.
+	 * Consider an aditiona interface that makes cleaing optional
+	 */
+	iommu_init_table(&tbl->table, nid);
+
+	list_add(&tbl->link, &phb->dma_tables);
+	return tbl;
+
+ fail:
+	pr_debug("  Failed to allocate a 256M TCE table !\n");
+	for (i = 0; i < tvts_per_table; i++)
+		if (tbl->tces[i])
+			__free_pages(tbl->tces[i], get_order(0x80000));
+	kfree(tbl);
+	return ERR_PTR(-ENOMEM);
+}
+
+static void __devinit wsp_pci_dma_dev_setup(struct pci_dev *pdev)
+{
+	struct dev_archdata *archdata = &pdev->dev.archdata;
+	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+	struct wsp_phb *phb = hose->private_data;
+	struct wsp_dma_table *table = NULL;
+	unsigned long flags;
+	int i;
+
+	/* Don't assign an iommu table to a bridge */
+	if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+		return;
+
+	pr_debug("%s: Setting up DMA...\n", pci_name(pdev));
+
+	spin_lock_irqsave(&phb->lock, flags);
+
+	/* If only one region, check if it already exist */
+	if (phb->dma32_num_regions == 1) {
+		spin_unlock_irqrestore(&phb->lock, flags);
+		if (list_empty(&phb->dma_tables))
+			table = wsp_pci_create_dma32_table(phb, 0, NULL);
+		else
+			table = list_first_entry(&phb->dma_tables,
+						 struct wsp_dma_table,
+						 link);
+	} else {
+		/* else find a free region */
+		for (i = 0; i < phb->dma32_num_regions && !table; i++) {
+			if (__test_and_set_bit(i, &phb->dma32_map))
+				continue;
+			spin_unlock_irqrestore(&phb->lock, flags);
+			table = wsp_pci_create_dma32_table(phb, i, pdev);
+		}
+	}
+
+	/* Check if we got an error */
+	if (IS_ERR(table)) {
+		pr_err("%s: Failed to create DMA table, err %ld !\n",
+		       pci_name(pdev), PTR_ERR(table));
+		return;
+	}
+
+	/* Or a valid table */
+	if (table) {
+		pr_info("%s: Setup iommu: 32-bit DMA region 0x%08lx..0x%08lx\n",
+			pci_name(pdev),
+			table->table.it_offset << IOMMU_PAGE_SHIFT,
+			(table->table.it_offset << IOMMU_PAGE_SHIFT)
+			+ phb->dma32_region_size - 1);
+		archdata->dma_data.iommu_table_base = &table->table;
+		return;
+	}
+
+	/* Or no room */
+	spin_unlock_irqrestore(&phb->lock, flags);
+	pr_err("%s: Out of DMA space !\n", pci_name(pdev));
+}
+
+static void __init wsp_pcie_configure_hw(struct pci_controller *hose)
+{
+	u64 val;
+	int i;
+
+#define DUMP_REG(x) \
+	pr_debug("%-30s : 0x%016llx\n", #x, in_be64(hose->cfg_data + x))
+
+#ifdef CONFIG_WSP_DD1_WORKAROUND_BAD_PCIE_CLASS
+	/* WSP DD1 has a bogus class code by default in the PCI-E
+	 * root complex's built-in P2P bridge */
+	val = in_be64(hose->cfg_data + PCIE_REG_SYS_CFG1);
+	pr_debug("PCI-E SYS_CFG1 : 0x%llx\n", val);
+	out_be64(hose->cfg_data + PCIE_REG_SYS_CFG1,
+		 (val & ~PCIE_REG_SYS_CFG1_CLASS_CODE) | (PCI_CLASS_BRIDGE_PCI << 8));
+	pr_debug("PCI-E SYS_CFG1 : 0x%llx\n", in_be64(hose->cfg_data + PCIE_REG_SYS_CFG1));
+#endif /* CONFIG_WSP_DD1_WORKAROUND_BAD_PCIE_CLASS */
+
+#ifdef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
+	/* XXX Disable TCE caching, it doesn't work on DD1 */
+	out_be64(hose->cfg_data + 0xe50,
+		 in_be64(hose->cfg_data + 0xe50) | (3ull << 62));
+	printk("PCI-E DEBUG CONTROL 5 = 0x%llx\n", in_be64(hose->cfg_data + 0xe50));
+#endif
+
+	/* Configure M32A and IO. IO is hard wired to be 1M for now */
+	out_be64(hose->cfg_data + PCIE_REG_IO_BASE_ADDR, hose->io_base_phys);
+	out_be64(hose->cfg_data + PCIE_REG_IO_BASE_MASK,
+		 (~(hose->io_resource.end - hose->io_resource.start)) &
+		 0x3fffffff000ul);
+	out_be64(hose->cfg_data + PCIE_REG_IO_START_ADDR, 0 | 1);
+
+	out_be64(hose->cfg_data + PCIE_REG_M32A_BASE_ADDR,
+		 hose->mem_resources[0].start);
+	printk("Want to write to M32A_BASE_MASK : 0x%llx\n",
+		 (~(hose->mem_resources[0].end -
+		    hose->mem_resources[0].start)) & 0x3ffffff0000ul);
+	out_be64(hose->cfg_data + PCIE_REG_M32A_BASE_MASK,
+		 (~(hose->mem_resources[0].end -
+		    hose->mem_resources[0].start)) & 0x3ffffff0000ul);
+	out_be64(hose->cfg_data + PCIE_REG_M32A_START_ADDR,
+		 (hose->mem_resources[0].start - hose->pci_mem_offset) | 1);
+
+	/* Clear all TVT entries
+	 *
+	 * XX Might get TVT count from device-tree
+	 */
+	for (i = 0; i < IODA_TVT_COUNT; i++) {
+		out_be64(hose->cfg_data + PCIE_REG_IODA_ADDR,
+			 PCIE_REG_IODA_AD_TBL_TVT | i);
+		out_be64(hose->cfg_data + PCIE_REG_IODA_DATA1, 0);
+		out_be64(hose->cfg_data + PCIE_REG_IODA_DATA0, 0);
+	}
+
+	/* Kill the TCE cache */
+	out_be64(hose->cfg_data + PCIE_REG_PHB_CONFIG,
+		 in_be64(hose->cfg_data + PCIE_REG_PHB_CONFIG) |
+		 PCIE_REG_PHBC_64B_TCE_EN);
+
+	/* Enable 32 & 64-bit MSIs, IO space and M32A */
+	val = PCIE_REG_PHBC_32BIT_MSI_EN |
+	      PCIE_REG_PHBC_IO_EN |
+	      PCIE_REG_PHBC_64BIT_MSI_EN |
+	      PCIE_REG_PHBC_M32A_EN;
+	if (iommu_is_off)
+		val |= PCIE_REG_PHBC_DMA_XLATE_BYPASS;
+	pr_debug("Will write config: 0x%llx\n", val);
+	out_be64(hose->cfg_data + PCIE_REG_PHB_CONFIG, val);
+
+	/* Enable error reporting */
+	out_be64(hose->cfg_data + 0xe00,
+		 in_be64(hose->cfg_data + 0xe00) | 0x0008000000000000ull);
+
+	/* Mask an error that's generated when doing config space probe
+	 *
+	 * XXX Maybe we should only mask it around config space cycles... that or
+	 * ignore it when we know we had a config space cycle recently ?
+	 */
+	out_be64(hose->cfg_data + PCIE_REG_DMA_ERR_STATUS_MASK, 0x8000000000000000ull);
+	out_be64(hose->cfg_data + PCIE_REG_DMA_ERR1_STATUS_MASK, 0x8000000000000000ull);
+
+	/* Enable UTL errors, for now, all of them got to UTL irq 1
+	 *
+	 * We similarily mask one UTL error caused apparently during normal
+	 * probing. We also mask the link up error
+	 */
+	out_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_ERR_SEV, 0);
+	out_be64(hose->cfg_data + PCIE_UTL_RC_ERR_SEVERITY, 0);
+	out_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_ERROR_SEV, 0);
+	out_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_IRQ_EN, 0xffffffff00000000ull);
+	out_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_IRQ_EN, 0xff5fffff00000000ull);
+	out_be64(hose->cfg_data + PCIE_UTL_EP_ERR_IRQ_EN, 0xffffffff00000000ull);
+
+	DUMP_REG(PCIE_REG_IO_BASE_ADDR);
+	DUMP_REG(PCIE_REG_IO_BASE_MASK);
+	DUMP_REG(PCIE_REG_IO_START_ADDR);
+	DUMP_REG(PCIE_REG_M32A_BASE_ADDR);
+	DUMP_REG(PCIE_REG_M32A_BASE_MASK);
+	DUMP_REG(PCIE_REG_M32A_START_ADDR);
+	DUMP_REG(PCIE_REG_M32B_BASE_ADDR);
+	DUMP_REG(PCIE_REG_M32B_BASE_MASK);
+	DUMP_REG(PCIE_REG_M32B_START_ADDR);
+	DUMP_REG(PCIE_REG_M64_BASE_ADDR);
+	DUMP_REG(PCIE_REG_M64_BASE_MASK);
+	DUMP_REG(PCIE_REG_M64_START_ADDR);
+	DUMP_REG(PCIE_REG_PHB_CONFIG);
+}
+
+static void wsp_pci_wait_io_idle(struct wsp_phb *phb, unsigned long port)
+{
+	u64 val;
+	int i;
+
+	for (i = 0; i < 10000; i++) {
+		val = in_be64(phb->hose->cfg_data + 0xe08);
+		if ((val & 0x1900000000000000ull) == 0x0100000000000000ull)
+			return;
+		udelay(1);
+	}
+	pr_warning("PCI IO timeout on domain %d port 0x%lx\n",
+		   phb->hose->global_number, port);
+}
+
+#define DEF_PCI_AC_RET_pio(name, ret, at, al, aa)		\
+static ret wsp_pci_##name at					\
+{								\
+	struct iowa_bus *bus;					\
+	struct wsp_phb *phb;					\
+	unsigned long flags;					\
+	ret rval;						\
+	bus = iowa_pio_find_bus(aa);				\
+	WARN_ON(!bus);						\
+	phb = bus->private;					\
+	spin_lock_irqsave(&phb->lock, flags);			\
+	wsp_pci_wait_io_idle(phb, aa);				\
+	rval = __do_##name al;					\
+	spin_unlock_irqrestore(&phb->lock, flags);		\
+	return rval;						\
+}
+
+#define DEF_PCI_AC_NORET_pio(name, at, al, aa)			\
+static void wsp_pci_##name at					\
+{								\
+	struct iowa_bus *bus;					\
+	struct wsp_phb *phb;					\
+	unsigned long flags;					\
+	bus = iowa_pio_find_bus(aa);				\
+	WARN_ON(!bus);						\
+	phb = bus->private;					\
+	spin_lock_irqsave(&phb->lock, flags);			\
+	wsp_pci_wait_io_idle(phb, aa);				\
+	__do_##name al;						\
+	spin_unlock_irqrestore(&phb->lock, flags);		\
+}
+
+#define DEF_PCI_AC_RET_mem(name, ret, at, al, aa)
+#define DEF_PCI_AC_NORET_mem(name, at, al, aa)
+
+#define DEF_PCI_AC_RET(name, ret, at, al, space, aa)		\
+	DEF_PCI_AC_RET_##space(name, ret, at, al, aa)
+
+#define DEF_PCI_AC_NORET(name, at, al, space, aa)		\
+	DEF_PCI_AC_NORET_##space(name, at, al, aa)		\
+
+
+#include <asm/io-defs.h>
+
+#undef DEF_PCI_AC_RET
+#undef DEF_PCI_AC_NORET
+
+static struct ppc_pci_io wsp_pci_iops = {
+	.inb = wsp_pci_inb,
+	.inw = wsp_pci_inw,
+	.inl = wsp_pci_inl,
+	.outb = wsp_pci_outb,
+	.outw = wsp_pci_outw,
+	.outl = wsp_pci_outl,
+	.insb = wsp_pci_insb,
+	.insw = wsp_pci_insw,
+	.insl = wsp_pci_insl,
+	.outsb = wsp_pci_outsb,
+	.outsw = wsp_pci_outsw,
+	.outsl = wsp_pci_outsl,
+};
+
+static int __init wsp_setup_one_phb(struct device_node *np)
+{
+	struct pci_controller *hose;
+	struct wsp_phb *phb;
+
+	pr_info("PCI: Setting up PCIe host bridge 0x%s\n", np->full_name);
+
+	phb = zalloc_maybe_bootmem(sizeof(struct wsp_phb), GFP_KERNEL);
+	if (!phb)
+		return -ENOMEM;
+	hose = pcibios_alloc_controller(np);
+	if (!hose) {
+		/* Can't really free the phb */
+		return -ENOMEM;
+	}
+	hose->private_data = phb;
+	phb->hose = hose;
+
+	INIT_LIST_HEAD(&phb->dma_tables);
+	spin_lock_init(&phb->lock);
+
+	/* XXX Use bus-range property ? */
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	/* We use cfg_data as the address for the whole bridge MMIO space
+	 */
+	hose->cfg_data = of_iomap(hose->dn, 0);
+
+	pr_debug("PCIe registers mapped at 0x%p\n", hose->cfg_data);
+
+	/* Get the ranges of the device-tree */
+	pci_process_bridge_OF_ranges(hose, np, 0);
+
+	/* XXX Force re-assigning of everything for now */
+	pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC |
+		      PCI_ENABLE_PROC_DOMAINS);
+	pci_probe_only = 0;
+
+	/* Calculate how the TCE space is divided */
+	phb->dma32_base		= 0;
+	phb->dma32_num_regions	= NUM_DMA32_REGIONS;
+	if (phb->dma32_num_regions > MAX_TABLE_TVT_COUNT) {
+		pr_warning("IOMMU: Clamped to %d DMA32 regions\n",
+			   MAX_TABLE_TVT_COUNT);
+		phb->dma32_num_regions = MAX_TABLE_TVT_COUNT;
+	}
+	phb->dma32_region_size	= 0x80000000 / phb->dma32_num_regions;
+
+	BUG_ON(!is_power_of_2(phb->dma32_region_size));
+
+	/* Setup config ops */
+	hose->ops = &wsp_pcie_pci_ops;
+
+	/* Configure the HW */
+	wsp_pcie_configure_hw(hose);
+
+	/* Instanciate IO workarounds */
+	iowa_register_bus(hose, &wsp_pci_iops, NULL, phb);
+#ifdef CONFIG_PCI_MSI
+	wsp_setup_phb_msi(hose);
+#endif
+
+	/* Add to global list */
+	list_add(&phb->all, &wsp_phbs);
+
+	return 0;
+}
+
+void __init wsp_setup_pci(void)
+{
+	struct device_node *np;
+	int rc;
+
+	/* Find host bridges */
+	for_each_compatible_node(np, "pciex", PCIE_COMPATIBLE) {
+		rc = wsp_setup_one_phb(np);
+		if (rc)
+			pr_err("Failed to setup PCIe bridge %s, rc=%d\n",
+			       np->full_name, rc);
+	}
+
+	/* Establish device-tree linkage */
+	pci_devs_phb_init();
+
+	/* Set DMA ops to use TCEs */
+	if (iommu_is_off) {
+		pr_info("PCI-E: Disabled TCEs, using direct DMA\n");
+		set_pci_dma_ops(&dma_direct_ops);
+	} else {
+		ppc_md.pci_dma_dev_setup = wsp_pci_dma_dev_setup;
+		ppc_md.tce_build = tce_build_wsp;
+		ppc_md.tce_free = tce_free_wsp;
+		set_pci_dma_ops(&dma_iommu_ops);
+	}
+}
+
+#define err_debug(fmt...)	pr_debug(fmt)
+//#define err_debug(fmt...)
+
+static int __init wsp_pci_get_err_irq_no_dt(struct device_node *np)
+{
+	const u32 *prop;
+	int hw_irq;
+
+	/* Ok, no interrupts property, let's try to find our child P2P */
+	np = of_get_next_child(np, NULL);
+	if (np == NULL)
+		return 0;
+
+	/* Grab it's interrupt map */
+	prop = of_get_property(np, "interrupt-map", NULL);
+	if (prop == NULL)
+		return 0;
+
+	/* Grab one of the interrupts in there, keep the low 4 bits */
+	hw_irq = prop[5] & 0xf;
+
+	/* 0..4 for PHB 0 and 5..9 for PHB 1 */
+	if (hw_irq < 5)
+		hw_irq = 4;
+	else
+		hw_irq = 9;
+	hw_irq |= prop[5] & ~0xf;
+
+	err_debug("PCI: Using 0x%x as error IRQ for %s\n",
+		  hw_irq, np->parent->full_name);
+	return irq_create_mapping(NULL, hw_irq);
+}
+
+static const struct {
+	u32 offset;
+	const char *name;
+} wsp_pci_regs[] = {
+#define DREG(x) { PCIE_REG_##x, #x }
+#define DUTL(x) { PCIE_UTL_##x, "UTL_" #x }
+	/* Architected registers except CONFIG_ and IODA
+         * to avoid side effects
+	 */
+	DREG(DMA_CHAN_STATUS),
+	DREG(CPU_LOADSTORE_STATUS),
+	DREG(LOCK0),
+	DREG(LOCK1),
+	DREG(PHB_CONFIG),
+	DREG(IO_BASE_ADDR),
+	DREG(IO_BASE_MASK),
+	DREG(IO_START_ADDR),
+	DREG(M32A_BASE_ADDR),
+	DREG(M32A_BASE_MASK),
+	DREG(M32A_START_ADDR),
+	DREG(M32B_BASE_ADDR),
+	DREG(M32B_BASE_MASK),
+	DREG(M32B_START_ADDR),
+	DREG(M64_BASE_ADDR),
+	DREG(M64_BASE_MASK),
+	DREG(M64_START_ADDR),
+	DREG(TCE_KILL),
+	DREG(LOCK2),
+	DREG(PHB_GEN_CAP),
+	DREG(PHB_TCE_CAP),
+	DREG(PHB_IRQ_CAP),
+	DREG(PHB_EEH_CAP),
+	DREG(PAPR_ERR_INJ_CONTROL),
+	DREG(PAPR_ERR_INJ_ADDR),
+	DREG(PAPR_ERR_INJ_MASK),
+
+	/* UTL core regs */
+	DUTL(SYS_BUS_CONTROL),
+	DUTL(STATUS),
+	DUTL(SYS_BUS_AGENT_STATUS),
+	DUTL(SYS_BUS_AGENT_ERR_SEV),
+	DUTL(SYS_BUS_AGENT_IRQ_EN),
+	DUTL(SYS_BUS_BURST_SZ_CONF),
+	DUTL(REVISION_ID),
+	DUTL(OUT_POST_HDR_BUF_ALLOC),
+	DUTL(OUT_POST_DAT_BUF_ALLOC),
+	DUTL(IN_POST_HDR_BUF_ALLOC),
+	DUTL(IN_POST_DAT_BUF_ALLOC),
+	DUTL(OUT_NP_BUF_ALLOC),
+	DUTL(IN_NP_BUF_ALLOC),
+	DUTL(PCIE_TAGS_ALLOC),
+	DUTL(GBIF_READ_TAGS_ALLOC),
+
+	DUTL(PCIE_PORT_CONTROL),
+	DUTL(PCIE_PORT_STATUS),
+	DUTL(PCIE_PORT_ERROR_SEV),
+	DUTL(PCIE_PORT_IRQ_EN),
+	DUTL(RC_STATUS),
+	DUTL(RC_ERR_SEVERITY),
+	DUTL(RC_IRQ_EN),
+	DUTL(EP_STATUS),
+	DUTL(EP_ERR_SEVERITY),
+	DUTL(EP_ERR_IRQ_EN),
+	DUTL(PCI_PM_CTRL1),
+	DUTL(PCI_PM_CTRL2),
+
+	/* PCIe stack regs */
+	DREG(SYSTEM_CONFIG1),
+	DREG(SYSTEM_CONFIG2),
+	DREG(EP_SYSTEM_CONFIG),
+	DREG(EP_FLR),
+	DREG(EP_BAR_CONFIG),
+	DREG(LINK_CONFIG),
+	DREG(PM_CONFIG),
+	DREG(DLP_CONTROL),
+	DREG(DLP_STATUS),
+	DREG(ERR_REPORT_CONTROL),
+	DREG(SLOT_CONTROL1),
+	DREG(SLOT_CONTROL2),
+	DREG(UTL_CONFIG),
+	DREG(BUFFERS_CONFIG),
+	DREG(ERROR_INJECT),
+	DREG(SRIOV_CONFIG),
+	DREG(PF0_SRIOV_STATUS),
+	DREG(PF1_SRIOV_STATUS),
+	DREG(PORT_NUMBER),
+	DREG(POR_SYSTEM_CONFIG),
+
+	/* Internal logic regs */
+	DREG(PHB_VERSION),
+	DREG(RESET),
+	DREG(PHB_CONTROL),
+	DREG(PHB_TIMEOUT_CONTROL1),
+	DREG(PHB_QUIESCE_DMA),
+	DREG(PHB_DMA_READ_TAG_ACTV),
+	DREG(PHB_TCE_READ_TAG_ACTV),
+
+	/* FIR registers */
+	DREG(LEM_FIR_ACCUM),
+	DREG(LEM_FIR_AND_MASK),
+	DREG(LEM_FIR_OR_MASK),
+	DREG(LEM_ACTION0),
+	DREG(LEM_ACTION1),
+	DREG(LEM_ERROR_MASK),
+	DREG(LEM_ERROR_AND_MASK),
+	DREG(LEM_ERROR_OR_MASK),
+
+	/* Error traps registers */
+	DREG(PHB_ERR_STATUS),
+	DREG(PHB_ERR_STATUS),
+	DREG(PHB_ERR1_STATUS),
+	DREG(PHB_ERR_INJECT),
+	DREG(PHB_ERR_LEM_ENABLE),
+	DREG(PHB_ERR_IRQ_ENABLE),
+	DREG(PHB_ERR_FREEZE_ENABLE),
+	DREG(PHB_ERR_SIDE_ENABLE),
+	DREG(PHB_ERR_LOG_0),
+	DREG(PHB_ERR_LOG_1),
+	DREG(PHB_ERR_STATUS_MASK),
+	DREG(PHB_ERR1_STATUS_MASK),
+	DREG(MMIO_ERR_STATUS),
+	DREG(MMIO_ERR1_STATUS),
+	DREG(MMIO_ERR_INJECT),
+	DREG(MMIO_ERR_LEM_ENABLE),
+	DREG(MMIO_ERR_IRQ_ENABLE),
+	DREG(MMIO_ERR_FREEZE_ENABLE),
+	DREG(MMIO_ERR_SIDE_ENABLE),
+	DREG(MMIO_ERR_LOG_0),
+	DREG(MMIO_ERR_LOG_1),
+	DREG(MMIO_ERR_STATUS_MASK),
+	DREG(MMIO_ERR1_STATUS_MASK),
+	DREG(DMA_ERR_STATUS),
+	DREG(DMA_ERR1_STATUS),
+	DREG(DMA_ERR_INJECT),
+	DREG(DMA_ERR_LEM_ENABLE),
+	DREG(DMA_ERR_IRQ_ENABLE),
+	DREG(DMA_ERR_FREEZE_ENABLE),
+	DREG(DMA_ERR_SIDE_ENABLE),
+	DREG(DMA_ERR_LOG_0),
+	DREG(DMA_ERR_LOG_1),
+	DREG(DMA_ERR_STATUS_MASK),
+	DREG(DMA_ERR1_STATUS_MASK),
+
+	/* Debug and Trace registers */
+	DREG(PHB_DEBUG_CONTROL0),
+	DREG(PHB_DEBUG_STATUS0),
+	DREG(PHB_DEBUG_CONTROL1),
+	DREG(PHB_DEBUG_STATUS1),
+	DREG(PHB_DEBUG_CONTROL2),
+	DREG(PHB_DEBUG_STATUS2),
+	DREG(PHB_DEBUG_CONTROL3),
+	DREG(PHB_DEBUG_STATUS3),
+	DREG(PHB_DEBUG_CONTROL4),
+	DREG(PHB_DEBUG_STATUS4),
+	DREG(PHB_DEBUG_CONTROL5),
+	DREG(PHB_DEBUG_STATUS5),
+
+	/* Don't seem to exist ...
+	DREG(PHB_DEBUG_CONTROL6),
+	DREG(PHB_DEBUG_STATUS6),
+	*/
+};
+
+static int wsp_pci_regs_show(struct seq_file *m, void *private)
+{
+	struct wsp_phb *phb = m->private;
+	struct pci_controller *hose = phb->hose;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(wsp_pci_regs); i++) {
+		/* Skip write-only regs */
+		if (wsp_pci_regs[i].offset == 0xc08 ||
+		    wsp_pci_regs[i].offset == 0xc10 ||
+		    wsp_pci_regs[i].offset == 0xc38 ||
+		    wsp_pci_regs[i].offset == 0xc40)
+			continue;
+		seq_printf(m, "0x%03x: 0x%016llx %s\n",
+			   wsp_pci_regs[i].offset,
+			   in_be64(hose->cfg_data + wsp_pci_regs[i].offset),
+			   wsp_pci_regs[i].name);
+	}
+	return 0;
+}
+
+static int wsp_pci_regs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, wsp_pci_regs_show, inode->i_private);
+}
+
+static const struct file_operations wsp_pci_regs_fops = {
+	.open = wsp_pci_regs_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int wsp_pci_reg_set(void *data, u64 val)
+{
+	out_be64((void __iomem *)data, val);
+	return 0;
+}
+
+static int wsp_pci_reg_get(void *data, u64 *val)
+{
+	*val = in_be64((void __iomem *)data);
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(wsp_pci_reg_fops, wsp_pci_reg_get, wsp_pci_reg_set, "0x%llx\n");
+
+static irqreturn_t wsp_pci_err_irq(int irq, void *dev_id)
+{
+	struct wsp_phb *phb = dev_id;
+	struct pci_controller *hose = phb->hose;
+	irqreturn_t handled = IRQ_NONE;
+	struct wsp_pcie_err_log_data ed;
+
+	pr_err("PCI: Error interrupt on %s (PHB %d)\n",
+	       hose->dn->full_name, hose->global_number);
+ again:
+	memset(&ed, 0, sizeof(ed));
+
+	/* Read and clear UTL errors */
+	ed.utl_sys_err = in_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_STATUS);
+	if (ed.utl_sys_err)
+		out_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_STATUS, ed.utl_sys_err);
+	ed.utl_port_err = in_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_STATUS);
+	if (ed.utl_port_err)
+		out_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_STATUS, ed.utl_port_err);
+	ed.utl_rc_err = in_be64(hose->cfg_data + PCIE_UTL_RC_STATUS);
+	if (ed.utl_rc_err)
+		out_be64(hose->cfg_data + PCIE_UTL_RC_STATUS, ed.utl_rc_err);
+
+	/* Read and clear main trap errors */
+	ed.phb_err = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR_STATUS);
+	if (ed.phb_err) {
+		ed.phb_err1 = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR1_STATUS);
+		ed.phb_log0 = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR_LOG_0);
+		ed.phb_log1 = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR_LOG_1);
+		out_be64(hose->cfg_data + PCIE_REG_PHB_ERR1_STATUS, 0);
+		out_be64(hose->cfg_data + PCIE_REG_PHB_ERR_STATUS, 0);
+	}
+	ed.mmio_err = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_STATUS);
+	if (ed.mmio_err) {
+		ed.mmio_err1 = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR1_STATUS);
+		ed.mmio_log0 = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_LOG_0);
+		ed.mmio_log1 = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_LOG_1);
+		out_be64(hose->cfg_data + PCIE_REG_MMIO_ERR1_STATUS, 0);
+		out_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_STATUS, 0);
+	}
+	ed.dma_err = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR_STATUS);
+	if (ed.dma_err) {
+		ed.dma_err1 = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR1_STATUS);
+		ed.dma_log0 = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR_LOG_0);
+		ed.dma_log1 = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR_LOG_1);
+		out_be64(hose->cfg_data + PCIE_REG_DMA_ERR1_STATUS, 0);
+		out_be64(hose->cfg_data + PCIE_REG_DMA_ERR_STATUS, 0);
+	}
+
+	/* Now print things out */
+	if (ed.phb_err) {
+		pr_err("   PHB Error Status      : 0x%016llx\n", ed.phb_err);
+		pr_err("   PHB First Error Status: 0x%016llx\n", ed.phb_err1);
+		pr_err("   PHB Error Log 0       : 0x%016llx\n", ed.phb_log0);
+		pr_err("   PHB Error Log 1       : 0x%016llx\n", ed.phb_log1);
+	}
+	if (ed.mmio_err) {
+		pr_err("  MMIO Error Status      : 0x%016llx\n", ed.mmio_err);
+		pr_err("  MMIO First Error Status: 0x%016llx\n", ed.mmio_err1);
+		pr_err("  MMIO Error Log 0       : 0x%016llx\n", ed.mmio_log0);
+		pr_err("  MMIO Error Log 1       : 0x%016llx\n", ed.mmio_log1);
+	}
+	if (ed.dma_err) {
+		pr_err("   DMA Error Status      : 0x%016llx\n", ed.dma_err);
+		pr_err("   DMA First Error Status: 0x%016llx\n", ed.dma_err1);
+		pr_err("   DMA Error Log 0       : 0x%016llx\n", ed.dma_log0);
+		pr_err("   DMA Error Log 1       : 0x%016llx\n", ed.dma_log1);
+	}
+	if (ed.utl_sys_err)
+		pr_err("   UTL Sys Error Status  : 0x%016llx\n", ed.utl_sys_err);
+	if (ed.utl_port_err)
+		pr_err("   UTL Port Error Status : 0x%016llx\n", ed.utl_port_err);
+	if (ed.utl_rc_err)
+		pr_err("   UTL RC Error Status   : 0x%016llx\n", ed.utl_rc_err);
+
+	/* Interrupts are caused by the error traps. If we had any error there
+	 * we loop again in case the UTL buffered some new stuff between
+	 * going there and going to the traps
+	 */
+	if (ed.dma_err || ed.mmio_err || ed.phb_err) {
+		handled = IRQ_HANDLED;
+		goto again;
+	}
+	return handled;
+}
+
+static void __init wsp_setup_pci_err_reporting(struct wsp_phb *phb)
+{
+	struct pci_controller *hose = phb->hose;
+	int err_irq, i, rc;
+	char fname[16];
+
+	/* Create a debugfs file for that PHB */
+	sprintf(fname, "phb%d", phb->hose->global_number);
+	phb->ddir = debugfs_create_dir(fname, powerpc_debugfs_root);
+
+	/* Some useful debug output */
+	if (phb->ddir) {
+		struct dentry *d = debugfs_create_dir("regs", phb->ddir);
+		char tmp[64];
+
+		for (i = 0; i < ARRAY_SIZE(wsp_pci_regs); i++) {
+			sprintf(tmp, "%03x_%s", wsp_pci_regs[i].offset,
+				wsp_pci_regs[i].name);
+			debugfs_create_file(tmp, 0600, d,
+					    hose->cfg_data + wsp_pci_regs[i].offset,
+					    &wsp_pci_reg_fops);
+		}
+		debugfs_create_file("all_regs", 0600, phb->ddir, phb, &wsp_pci_regs_fops);
+	}
+
+	/* Find the IRQ number for that PHB */
+	err_irq = irq_of_parse_and_map(hose->dn, 0);
+	if (err_irq == 0)
+		/* XXX Error IRQ lacking from device-tree */
+		err_irq = wsp_pci_get_err_irq_no_dt(hose->dn);
+	if (err_irq == 0) {
+		pr_err("PCI: Failed to fetch error interrupt for %s\n",
+		       hose->dn->full_name);
+		return;
+	}
+	/* Request it */
+	rc = request_irq(err_irq, wsp_pci_err_irq, 0, "wsp_pci error", phb);
+	if (rc) {
+		pr_err("PCI: Failed to request interrupt for %s\n",
+		       hose->dn->full_name);
+	}
+	/* Enable interrupts for all errors for now */
+	out_be64(hose->cfg_data + PCIE_REG_PHB_ERR_IRQ_ENABLE, 0xffffffffffffffffull);
+	out_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_IRQ_ENABLE, 0xffffffffffffffffull);
+	out_be64(hose->cfg_data + PCIE_REG_DMA_ERR_IRQ_ENABLE, 0xffffffffffffffffull);
+}
+
+/*
+ * This is called later to hookup with the error interrupt
+ */
+static int __init wsp_setup_pci_late(void)
+{
+	struct wsp_phb *phb;
+
+	list_for_each_entry(phb, &wsp_phbs, all)
+		wsp_setup_pci_err_reporting(phb);
+
+	return 0;
+}
+arch_initcall(wsp_setup_pci_late);
diff -druN linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/wsp_pci.h linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/wsp_pci.h
--- linux-libre-3.1-gnu/arch/powerpc/platforms/wsp/wsp_pci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/platforms/wsp/wsp_pci.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2010 Ben Herrenschmidt, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef __WSP_PCI_H
+#define __WSP_PCI_H
+
+/* Architected registers */
+#define PCIE_REG_DMA_CHAN_STATUS	0x110
+#define PCIE_REG_CPU_LOADSTORE_STATUS	0x120
+
+#define PCIE_REG_CONFIG_DATA		0x130
+#define PCIE_REG_LOCK0			0x138
+#define PCIE_REG_CONFIG_ADDRESS		0x140
+#define   PCIE_REG_CA_ENABLE			0x8000000000000000ull
+#define	  PCIE_REG_CA_BUS_MASK			0x0ff0000000000000ull
+#define   PCIE_REG_CA_BUS_SHIFT			(20+32)
+#define   PCIE_REG_CA_DEV_MASK			0x000f800000000000ull
+#define   PCIE_REG_CA_DEV_SHIFT			(15+32)
+#define   PCIE_REG_CA_FUNC_MASK			0x0000700000000000ull
+#define   PCIE_REG_CA_FUNC_SHIFT		(12+32)
+#define   PCIE_REG_CA_REG_MASK			0x00000fff00000000ull
+#define   PCIE_REG_CA_REG_SHIFT			( 0+32)
+#define   PCIE_REG_CA_BE_MASK			0x00000000f0000000ull
+#define   PCIE_REG_CA_BE_SHIFT			(   28)
+#define PCIE_REG_LOCK1			0x148
+
+#define PCIE_REG_PHB_CONFIG		0x160
+#define   PCIE_REG_PHBC_64B_TCE_EN		0x2000000000000000ull
+#define   PCIE_REG_PHBC_MMIO_DMA_FREEZE_EN	0x1000000000000000ull
+#define   PCIE_REG_PHBC_32BIT_MSI_EN		0x0080000000000000ull
+#define   PCIE_REG_PHBC_M64_EN			0x0040000000000000ull
+#define   PCIE_REG_PHBC_IO_EN			0x0008000000000000ull
+#define   PCIE_REG_PHBC_64BIT_MSI_EN		0x0002000000000000ull
+#define   PCIE_REG_PHBC_M32A_EN			0x0000800000000000ull
+#define   PCIE_REG_PHBC_M32B_EN			0x0000400000000000ull
+#define   PCIE_REG_PHBC_MSI_PE_VALIDATE		0x0000200000000000ull
+#define   PCIE_REG_PHBC_DMA_XLATE_BYPASS	0x0000100000000000ull
+
+#define PCIE_REG_IO_BASE_ADDR		0x170
+#define PCIE_REG_IO_BASE_MASK		0x178
+#define PCIE_REG_IO_START_ADDR		0x180
+
+#define PCIE_REG_M32A_BASE_ADDR		0x190
+#define PCIE_REG_M32A_BASE_MASK		0x198
+#define PCIE_REG_M32A_START_ADDR	0x1a0
+
+#define PCIE_REG_M32B_BASE_ADDR		0x1b0
+#define PCIE_REG_M32B_BASE_MASK		0x1b8
+#define PCIE_REG_M32B_START_ADDR	0x1c0
+
+#define PCIE_REG_M64_BASE_ADDR		0x1e0
+#define PCIE_REG_M64_BASE_MASK		0x1e8
+#define PCIE_REG_M64_START_ADDR		0x1f0
+
+#define PCIE_REG_TCE_KILL		0x210
+#define   PCIE_REG_TCEKILL_SINGLE	0x8000000000000000ull
+#define   PCIE_REG_TCEKILL_ADDR_MASK	0x000003fffffffff8ull
+#define   PCIE_REG_TCEKILL_PS_4K	0
+#define   PCIE_REG_TCEKILL_PS_64K	1
+#define   PCIE_REG_TCEKILL_PS_16M	2
+#define   PCIE_REG_TCEKILL_PS_16G	3
+
+#define PCIE_REG_IODA_ADDR		0x220
+#define   PCIE_REG_IODA_AD_AUTOINC	0x8000000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_MVT	0x0005000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_PELT	0x0006000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_PESTA	0x0007000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_PESTB	0x0008000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_TVT	0x0009000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_TCE	0x000a000000000000ull
+#define PCIE_REG_IODA_DATA0		0x228
+#define PCIE_REG_IODA_DATA1		0x230
+
+#define PCIE_REG_LOCK2			0x240
+
+#define PCIE_REG_PHB_GEN_CAP		0x250
+#define PCIE_REG_PHB_TCE_CAP		0x258
+#define PCIE_REG_PHB_IRQ_CAP		0x260
+#define PCIE_REG_PHB_EEH_CAP		0x268
+
+#define PCIE_REG_PAPR_ERR_INJ_CONTROL	0x2b0
+#define PCIE_REG_PAPR_ERR_INJ_ADDR	0x2b8
+#define PCIE_REG_PAPR_ERR_INJ_MASK	0x2c0
+
+
+#define PCIE_REG_SYS_CFG1		0x600
+#define   PCIE_REG_SYS_CFG1_CLASS_CODE	0x0000000000ffffffull
+
+#define IODA_TVT0_TTA_MASK		0x000fffffffff0000ull
+#define IODA_TVT0_TTA_SHIFT		4
+#define IODA_TVT0_BUSNUM_VALID_MASK	0x000000000000e000ull
+#define IODA_TVT0_TCE_TABLE_SIZE_MASK	0x0000000000001f00ull
+#define IODA_TVT0_TCE_TABLE_SIZE_SHIFT	8
+#define IODA_TVT0_BUSNUM_VALUE_MASK	0x00000000000000ffull
+#define IODA_TVT0_BUSNUM_VALID_SHIFT	0
+#define IODA_TVT1_DEVNUM_VALID		0x2000000000000000ull
+#define IODA_TVT1_DEVNUM_VALUE_MASK	0x1f00000000000000ull
+#define IODA_TVT1_DEVNUM_VALUE_SHIFT	56
+#define IODA_TVT1_FUNCNUM_VALID		0x0008000000000000ull
+#define IODA_TVT1_FUNCNUM_VALUE_MASK	0x0007000000000000ull
+#define IODA_TVT1_FUNCNUM_VALUE_SHIFT	48
+#define IODA_TVT1_IO_PAGE_SIZE_MASK	0x00001f0000000000ull
+#define IODA_TVT1_IO_PAGE_SIZE_SHIFT	40
+#define IODA_TVT1_PE_NUMBER_MASK	0x000000000000003full
+#define IODA_TVT1_PE_NUMBER_SHIFT	0
+
+#define IODA_TVT_COUNT			64
+
+/* UTL Core registers */
+#define PCIE_UTL_SYS_BUS_CONTROL	0x400
+#define PCIE_UTL_STATUS			0x408
+#define PCIE_UTL_SYS_BUS_AGENT_STATUS	0x410
+#define PCIE_UTL_SYS_BUS_AGENT_ERR_SEV	0x418
+#define PCIE_UTL_SYS_BUS_AGENT_IRQ_EN	0x420
+#define PCIE_UTL_SYS_BUS_BURST_SZ_CONF	0x440
+#define PCIE_UTL_REVISION_ID		0x448
+
+#define PCIE_UTL_OUT_POST_HDR_BUF_ALLOC	0x4c0
+#define PCIE_UTL_OUT_POST_DAT_BUF_ALLOC	0x4d0
+#define PCIE_UTL_IN_POST_HDR_BUF_ALLOC	0x4e0
+#define PCIE_UTL_IN_POST_DAT_BUF_ALLOC	0x4f0
+#define PCIE_UTL_OUT_NP_BUF_ALLOC	0x500
+#define PCIE_UTL_IN_NP_BUF_ALLOC	0x510
+#define PCIE_UTL_PCIE_TAGS_ALLOC	0x520
+#define PCIE_UTL_GBIF_READ_TAGS_ALLOC	0x530
+
+#define PCIE_UTL_PCIE_PORT_CONTROL	0x540
+#define PCIE_UTL_PCIE_PORT_STATUS	0x548
+#define PCIE_UTL_PCIE_PORT_ERROR_SEV	0x550
+#define PCIE_UTL_PCIE_PORT_IRQ_EN	0x558
+#define PCIE_UTL_RC_STATUS		0x560
+#define PCIE_UTL_RC_ERR_SEVERITY	0x568
+#define PCIE_UTL_RC_IRQ_EN		0x570
+#define PCIE_UTL_EP_STATUS		0x578
+#define PCIE_UTL_EP_ERR_SEVERITY	0x580
+#define PCIE_UTL_EP_ERR_IRQ_EN		0x588
+
+#define PCIE_UTL_PCI_PM_CTRL1		0x590
+#define PCIE_UTL_PCI_PM_CTRL2		0x598
+
+/* PCIe stack registers */
+#define PCIE_REG_SYSTEM_CONFIG1		0x600
+#define PCIE_REG_SYSTEM_CONFIG2		0x608
+#define PCIE_REG_EP_SYSTEM_CONFIG	0x618
+#define PCIE_REG_EP_FLR			0x620
+#define PCIE_REG_EP_BAR_CONFIG		0x628
+#define PCIE_REG_LINK_CONFIG		0x630
+#define PCIE_REG_PM_CONFIG		0x640
+#define PCIE_REG_DLP_CONTROL		0x650
+#define PCIE_REG_DLP_STATUS		0x658
+#define PCIE_REG_ERR_REPORT_CONTROL	0x660
+#define PCIE_REG_SLOT_CONTROL1		0x670
+#define PCIE_REG_SLOT_CONTROL2		0x678
+#define PCIE_REG_UTL_CONFIG		0x680
+#define PCIE_REG_BUFFERS_CONFIG		0x690
+#define PCIE_REG_ERROR_INJECT		0x698
+#define PCIE_REG_SRIOV_CONFIG		0x6a0
+#define PCIE_REG_PF0_SRIOV_STATUS	0x6a8
+#define PCIE_REG_PF1_SRIOV_STATUS	0x6b0
+#define PCIE_REG_PORT_NUMBER		0x700
+#define PCIE_REG_POR_SYSTEM_CONFIG	0x708
+
+/* PHB internal logic registers */
+#define PCIE_REG_PHB_VERSION		0x800
+#define PCIE_REG_RESET			0x808
+#define PCIE_REG_PHB_CONTROL		0x810
+#define PCIE_REG_PHB_TIMEOUT_CONTROL1	0x878
+#define PCIE_REG_PHB_QUIESCE_DMA	0x888
+#define PCIE_REG_PHB_DMA_READ_TAG_ACTV	0x900
+#define PCIE_REG_PHB_TCE_READ_TAG_ACTV	0x908
+
+/* FIR registers */
+#define PCIE_REG_LEM_FIR_ACCUM		0xc00
+#define PCIE_REG_LEM_FIR_AND_MASK	0xc08
+#define PCIE_REG_LEM_FIR_OR_MASK	0xc10
+#define PCIE_REG_LEM_ACTION0		0xc18
+#define PCIE_REG_LEM_ACTION1		0xc20
+#define PCIE_REG_LEM_ERROR_MASK		0xc30
+#define PCIE_REG_LEM_ERROR_AND_MASK	0xc38
+#define PCIE_REG_LEM_ERROR_OR_MASK	0xc40
+
+/* PHB Error registers */
+#define PCIE_REG_PHB_ERR_STATUS		0xc80
+#define PCIE_REG_PHB_ERR1_STATUS	0xc88
+#define PCIE_REG_PHB_ERR_INJECT		0xc90
+#define PCIE_REG_PHB_ERR_LEM_ENABLE	0xc98
+#define PCIE_REG_PHB_ERR_IRQ_ENABLE	0xca0
+#define PCIE_REG_PHB_ERR_FREEZE_ENABLE	0xca8
+#define PCIE_REG_PHB_ERR_SIDE_ENABLE	0xcb8
+#define PCIE_REG_PHB_ERR_LOG_0		0xcc0
+#define PCIE_REG_PHB_ERR_LOG_1		0xcc8
+#define PCIE_REG_PHB_ERR_STATUS_MASK	0xcd0
+#define PCIE_REG_PHB_ERR1_STATUS_MASK	0xcd8
+
+#define PCIE_REG_MMIO_ERR_STATUS	0xd00
+#define PCIE_REG_MMIO_ERR1_STATUS	0xd08
+#define PCIE_REG_MMIO_ERR_INJECT	0xd10
+#define PCIE_REG_MMIO_ERR_LEM_ENABLE	0xd18
+#define PCIE_REG_MMIO_ERR_IRQ_ENABLE	0xd20
+#define PCIE_REG_MMIO_ERR_FREEZE_ENABLE	0xd28
+#define PCIE_REG_MMIO_ERR_SIDE_ENABLE	0xd38
+#define PCIE_REG_MMIO_ERR_LOG_0		0xd40
+#define PCIE_REG_MMIO_ERR_LOG_1		0xd48
+#define PCIE_REG_MMIO_ERR_STATUS_MASK	0xd50
+#define PCIE_REG_MMIO_ERR1_STATUS_MASK	0xd58
+
+#define PCIE_REG_DMA_ERR_STATUS		0xd80
+#define PCIE_REG_DMA_ERR1_STATUS	0xd88
+#define PCIE_REG_DMA_ERR_INJECT		0xd90
+#define PCIE_REG_DMA_ERR_LEM_ENABLE	0xd98
+#define PCIE_REG_DMA_ERR_IRQ_ENABLE	0xda0
+#define PCIE_REG_DMA_ERR_FREEZE_ENABLE	0xda8
+#define PCIE_REG_DMA_ERR_SIDE_ENABLE	0xdb8
+#define PCIE_REG_DMA_ERR_LOG_0		0xdc0
+#define PCIE_REG_DMA_ERR_LOG_1		0xdc8
+#define PCIE_REG_DMA_ERR_STATUS_MASK	0xdd0
+#define PCIE_REG_DMA_ERR1_STATUS_MASK	0xdd8
+
+/* Shortcuts for access to the above using the PHB definitions
+ * with an offset
+ */
+#define PCIE_REG_ERR_PHB_OFFSET		0x0
+#define PCIE_REG_ERR_MMIO_OFFSET	0x80
+#define PCIE_REG_ERR_DMA_OFFSET		0x100
+
+/* Debug and Trace registers */
+#define PCIE_REG_PHB_DEBUG_CONTROL0	0xe00
+#define PCIE_REG_PHB_DEBUG_STATUS0	0xe08
+#define PCIE_REG_PHB_DEBUG_CONTROL1	0xe10
+#define PCIE_REG_PHB_DEBUG_STATUS1	0xe18
+#define PCIE_REG_PHB_DEBUG_CONTROL2	0xe20
+#define PCIE_REG_PHB_DEBUG_STATUS2	0xe28
+#define PCIE_REG_PHB_DEBUG_CONTROL3	0xe30
+#define PCIE_REG_PHB_DEBUG_STATUS3	0xe38
+#define PCIE_REG_PHB_DEBUG_CONTROL4	0xe40
+#define PCIE_REG_PHB_DEBUG_STATUS4	0xe48
+#define PCIE_REG_PHB_DEBUG_CONTROL5	0xe50
+#define PCIE_REG_PHB_DEBUG_STATUS5	0xe58
+#define PCIE_REG_PHB_DEBUG_CONTROL6	0xe60
+#define PCIE_REG_PHB_DEBUG_STATUS6	0xe68
+
+/* Definition for PCIe errors */
+struct wsp_pcie_err_log_data {
+	__u64	phb_err;
+	__u64	phb_err1;
+	__u64	phb_log0;
+	__u64	phb_log1;
+	__u64	mmio_err;
+	__u64	mmio_err1;
+	__u64	mmio_log0;
+	__u64	mmio_log1;
+	__u64	dma_err;
+	__u64	dma_err1;
+	__u64	dma_log0;
+	__u64	dma_log1;
+	__u64	utl_sys_err;
+	__u64	utl_port_err;
+	__u64	utl_rc_err;
+	__u64	unused;
+};
+
+#endif /* __WSP_PCI_H */
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/axonram.c linux-libre-3.2-gnu/arch/powerpc/sysdev/axonram.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/axonram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/axonram.c	2012-01-04 18:55:44.000000000 -0500
@@ -104,7 +104,7 @@
  * axon_ram_make_request - make_request() method for block device
  * @queue, @bio: see blk_queue_make_request()
  */
-static int
+static void
 axon_ram_make_request(struct request_queue *queue, struct bio *bio)
 {
 	struct axon_ram_bank *bank = bio->bi_bdev->bd_disk->private_data;
@@ -113,7 +113,6 @@
 	struct bio_vec *vec;
 	unsigned int transfered;
 	unsigned short idx;
-	int rc = 0;
 
 	phys_mem = bank->io_addr + (bio->bi_sector << AXON_RAM_SECTOR_SHIFT);
 	phys_end = bank->io_addr + bank->size;
@@ -121,8 +120,7 @@
 	bio_for_each_segment(vec, bio, idx) {
 		if (unlikely(phys_mem + vec->bv_len > phys_end)) {
 			bio_io_error(bio);
-			rc = -ERANGE;
-			break;
+			return;
 		}
 
 		user_mem = page_address(vec->bv_page) + vec->bv_offset;
@@ -135,8 +133,6 @@
 		transfered += vec->bv_len;
 	}
 	bio_endio(bio, 0);
-
-	return rc;
 }
 
 /**
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/bestcomm/sram.c linux-libre-3.2-gnu/arch/powerpc/sysdev/bestcomm/sram.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/bestcomm/sram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/bestcomm/sram.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,7 @@
 
 #include <linux/err.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/cpm_common.c linux-libre-3.2-gnu/arch/powerpc/sysdev/cpm_common.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/cpm_common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/cpm_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
  *
  * Author: Scott Wood <scottwood@freescale.com>
  *
- * Copyright 2007 Freescale Semiconductor, Inc.
+ * Copyright 2007-2008,2010 Freescale Semiconductor, Inc.
  *
  * Some parts derived from commproc.c/cpm2_common.c, which is:
  * Copyright (c) 1997 Dan error_act (dmalek@jlc.net)
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/of_device.h>
 #include <linux/spinlock.h>
+#include <linux/export.h>
 #include <linux/of.h>
 #include <linux/slab.h>
 
@@ -146,6 +147,7 @@
 	spin_lock_irqsave(&cpm_muram_lock, flags);
 	cpm_muram_info.alignment = align;
 	start = rh_alloc(&cpm_muram_info, size, "commproc");
+	memset(cpm_muram_addr(start), 0, size);
 	spin_unlock_irqrestore(&cpm_muram_lock, flags);
 
 	return start;
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/dcr.c linux-libre-3.2-gnu/arch/powerpc/sysdev/dcr.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/dcr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/dcr.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <asm/prom.h>
 #include <asm/dcr.h>
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/ehv_pic.c linux-libre-3.2-gnu/arch/powerpc/sysdev/ehv_pic.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/ehv_pic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/ehv_pic.c	2012-01-04 18:55:44.000000000 -0500
@@ -280,6 +280,7 @@
 
 	if (!ehv_pic->irqhost) {
 		of_node_put(np);
+		kfree(ehv_pic);
 		return;
 	}
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/fsl_gtm.c linux-libre-3.2-gnu/arch/powerpc/sysdev/fsl_gtm.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/fsl_gtm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/fsl_gtm.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/spinlock.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <asm/fsl_gtm.h>
 
 #define GTCFR_STP(x)		((x) & 1 ? 1 << 5 : 1 << 1)
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/fsl_lbc.c linux-libre-3.2-gnu/arch/powerpc/sysdev/fsl_lbc.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/fsl_lbc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/fsl_lbc.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/compiler.h>
 #include <linux/spinlock.h>
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/slab.h>
+#include <linux/sched.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/mod_devicetable.h>
@@ -327,6 +328,7 @@
 err:
 	iounmap(fsl_lbc_ctrl_dev->regs);
 	kfree(fsl_lbc_ctrl_dev);
+	fsl_lbc_ctrl_dev = NULL;
 	return ret;
 }
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/fsl_msi.c linux-libre-3.2-gnu/arch/powerpc/sysdev/fsl_msi.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/fsl_msi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/fsl_msi.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@
 
 struct fsl_msi_feature {
 	u32 fsl_pic_ip;
-	u32 msiir_offset;
+	u32 msiir_offset; /* Offset of MSIIR, relative to start of MSIR bank */
 };
 
 struct fsl_msi_cascade_data {
@@ -126,10 +126,19 @@
 {
 	struct fsl_msi *msi_data = fsl_msi_data;
 	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
-	u64 base = fsl_pci_immrbar_base(hose);
+	u64 address; /* Physical address of the MSIIR */
+	int len;
+	const u64 *reg;
 
-	msg->address_lo = msi_data->msi_addr_lo + lower_32_bits(base);
-	msg->address_hi = msi_data->msi_addr_hi + upper_32_bits(base);
+	/* If the msi-address-64 property exists, then use it */
+	reg = of_get_property(hose->dn, "msi-address-64", &len);
+	if (reg && (len == sizeof(u64)))
+		address = be64_to_cpup(reg);
+	else
+		address = fsl_pci_immrbar_base(hose) + msi_data->msiir_offset;
+
+	msg->address_lo = lower_32_bits(address);
+	msg->address_hi = upper_32_bits(address);
 
 	msg->data = hwirq;
 
@@ -296,7 +305,7 @@
 	}
 
 	msi->msi_virqs[irq_index] = virt_msir;
-	cascade_data->index = offset + irq_index;
+	cascade_data->index = offset;
 	cascade_data->msi_data = msi;
 	irq_set_handler_data(virt_msir, cascade_data);
 	irq_set_chained_handler(virt_msir, fsl_msi_cascade);
@@ -359,8 +368,7 @@
 
 	msi->irqhost->host_data = msi;
 
-	msi->msi_addr_hi = 0x0;
-	msi->msi_addr_lo = features->msiir_offset + (res.start & 0xfffff);
+	msi->msiir_offset = features->msiir_offset + (res.start & 0xfffff);
 
 	rc = fsl_msi_init_allocator(msi);
 	if (rc) {
@@ -376,8 +384,10 @@
 		goto error_out;
 	}
 
-	if (!p)
+	if (!p) {
 		p = all_avail;
+		len = sizeof(all_avail);
+	}
 
 	for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) {
 		if (p[i * 2] % IRQS_PER_MSI_REG ||
@@ -393,7 +403,7 @@
 		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);
+			err = fsl_msi_setup_hwirq(msi, dev, offset + j, irq_index);
 			if (err)
 				goto error_out;
 		}
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/fsl_msi.h linux-libre-3.2-gnu/arch/powerpc/sysdev/fsl_msi.h
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/fsl_msi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/fsl_msi.h	2012-01-04 18:55:44.000000000 -0500
@@ -28,8 +28,7 @@
 
 	unsigned long cascade_irq;
 
-	u32 msi_addr_lo;
-	u32 msi_addr_hi;
+	u32 msiir_offset; /* Offset of MSIIR, relative to start of CCSR */
 	void __iomem *msi_regs;
 	u32 feature;
 	int msi_virqs[NR_MSI_REG];
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/fsl_pmc.c linux-libre-3.2-gnu/arch/powerpc/sysdev/fsl_pmc.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/fsl_pmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/fsl_pmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/errno.h>
+#include <linux/export.h>
 #include <linux/suspend.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/fsl_rio.c linux-libre-3.2-gnu/arch/powerpc/sysdev/fsl_rio.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/fsl_rio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/fsl_rio.c	2012-01-04 18:55:44.000000000 -0500
@@ -1608,6 +1608,7 @@
 	return 0;
 err:
 	iounmap(priv->regs_win);
+	release_resource(&port->iores);
 err_res:
 	kfree(priv);
 err_priv:
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/fsl_soc.c linux-libre-3.2-gnu/arch/powerpc/sysdev/fsl_soc.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/fsl_soc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/fsl_soc.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/major.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/fsl_soc.h linux-libre-3.2-gnu/arch/powerpc/sysdev/fsl_soc.h
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/fsl_soc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/fsl_soc.h	2012-01-04 18:55:44.000000000 -0500
@@ -22,15 +22,24 @@
 extern void fsl_rstcr_restart(char *cmd);
 
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+
+/* The different ports that the DIU can be connected to */
+enum fsl_diu_monitor_port {
+	FSL_DIU_PORT_DVI,	/* DVI */
+	FSL_DIU_PORT_LVDS,	/* Single-link LVDS */
+	FSL_DIU_PORT_DLVDS	/* Dual-link LVDS */
+};
+
 struct platform_diu_data_ops {
-	unsigned int (*get_pixel_format) (unsigned int bits_per_pixel,
-		int monitor_port);
-	void (*set_gamma_table) (int monitor_port, char *gamma_table_base);
-	void (*set_monitor_port) (int monitor_port);
-	void (*set_pixel_clock) (unsigned int pixclock);
-	ssize_t (*show_monitor_port) (int monitor_port, char *buf);
-	int (*set_sysfs_monitor_port) (int val);
-	void (*release_bootmem) (void);
+	u32 (*get_pixel_format)(enum fsl_diu_monitor_port port,
+		unsigned int bpp);
+	void (*set_gamma_table)(enum fsl_diu_monitor_port port,
+		char *gamma_table_base);
+	void (*set_monitor_port)(enum fsl_diu_monitor_port port);
+	void (*set_pixel_clock)(unsigned int pixclock);
+	enum fsl_diu_monitor_port (*valid_monitor_port)
+		(enum fsl_diu_monitor_port port);
+	void (*release_bootmem)(void);
 };
 
 extern struct platform_diu_data_ops diu_ops;
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/Makefile linux-libre-3.2-gnu/arch/powerpc/sysdev/Makefile
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,6 @@
 obj-$(CONFIG_FSL_PMC)		+= fsl_pmc.o
 obj-$(CONFIG_FSL_LBC)		+= fsl_lbc.o
 obj-$(CONFIG_FSL_GTM)		+= fsl_gtm.o
-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_FSL_RIO)		+= fsl_rio.o
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/mpc5xxx_clocks.c linux-libre-3.2-gnu/arch/powerpc/sysdev/mpc5xxx_clocks.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/mpc5xxx_clocks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/mpc5xxx_clocks.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 
 #include <linux/kernel.h>
 #include <linux/of_platform.h>
+#include <linux/export.h>
 
 unsigned int
 mpc5xxx_get_bus_frequency(struct device_node *node)
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/mpc8xx_pic.c linux-libre-3.2-gnu/arch/powerpc/sysdev/mpc8xx_pic.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/mpc8xx_pic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/mpc8xx_pic.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,4 @@
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/stddef.h>
 #include <linux/init.h>
 #include <linux/sched.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/mpc8xxx_gpio.c linux-libre-3.2-gnu/arch/powerpc/sysdev/mpc8xxx_gpio.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/mpc8xxx_gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/mpc8xxx_gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,395 +0,0 @@
-/*
- * GPIOs on MPC512x/8349/8572/8610 and compatible
- *
- * Copyright (C) 2008 Peter Korsgaard <jacmet@sunsite.dk>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/irq.h>
-
-#define MPC8XXX_GPIO_PINS	32
-
-#define GPIO_DIR		0x00
-#define GPIO_ODR		0x04
-#define GPIO_DAT		0x08
-#define GPIO_IER		0x0c
-#define GPIO_IMR		0x10
-#define GPIO_ICR		0x14
-#define GPIO_ICR2		0x18
-
-struct mpc8xxx_gpio_chip {
-	struct of_mm_gpio_chip mm_gc;
-	spinlock_t lock;
-
-	/*
-	 * shadowed data register to be able to clear/set output pins in
-	 * open drain mode safely
-	 */
-	u32 data;
-	struct irq_host *irq;
-	void *of_dev_id_data;
-};
-
-static inline u32 mpc8xxx_gpio2mask(unsigned int gpio)
-{
-	return 1u << (MPC8XXX_GPIO_PINS - 1 - gpio);
-}
-
-static inline struct mpc8xxx_gpio_chip *
-to_mpc8xxx_gpio_chip(struct of_mm_gpio_chip *mm)
-{
-	return container_of(mm, struct mpc8xxx_gpio_chip, mm_gc);
-}
-
-static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm)
-{
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
-
-	mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT);
-}
-
-/* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs
- * defined as output cannot be determined by reading GPDAT register,
- * so we use shadow data register instead. The status of input pins
- * is determined by reading GPDAT register.
- */
-static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
-	u32 val;
-	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
-
-	val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR);
-
-	return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio);
-}
-
-static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
-
-	return in_be32(mm->regs + GPIO_DAT) & mpc8xxx_gpio2mask(gpio);
-}
-
-static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
-	unsigned long flags;
-
-	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-
-	if (val)
-		mpc8xxx_gc->data |= mpc8xxx_gpio2mask(gpio);
-	else
-		mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask(gpio);
-
-	out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data);
-
-	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-}
-
-static int mpc8xxx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
-	unsigned long flags;
-
-	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-
-	clrbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio));
-
-	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-
-	return 0;
-}
-
-static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
-	unsigned long flags;
-
-	mpc8xxx_gpio_set(gc, gpio, val);
-
-	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-
-	setbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio));
-
-	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-
-	return 0;
-}
-
-static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
-{
-	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
-
-	if (mpc8xxx_gc->irq && offset < MPC8XXX_GPIO_PINS)
-		return irq_create_mapping(mpc8xxx_gc->irq, offset);
-	else
-		return -ENXIO;
-}
-
-static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *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;
-
-	mask = in_be32(mm->regs + GPIO_IER) & in_be32(mm->regs + GPIO_IMR);
-	if (mask)
-		generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq,
-						     32 - ffs(mask)));
-}
-
-static void mpc8xxx_irq_unmask(struct irq_data *d)
-{
-	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(irqd_to_hwirq(d)));
-
-	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-}
-
-static void mpc8xxx_irq_mask(struct irq_data *d)
-{
-	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(irqd_to_hwirq(d)));
-
-	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-}
-
-static void mpc8xxx_irq_ack(struct irq_data *d)
-{
-	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(irqd_to_hwirq(d)));
-}
-
-static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-	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;
-
-	switch (flow_type) {
-	case IRQ_TYPE_EDGE_FALLING:
-		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-		setbits32(mm->regs + GPIO_ICR,
-			  mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
-		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(irqd_to_hwirq(d)));
-		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-	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 = irqd_to_hwirq(d);
-	void __iomem *reg;
-	unsigned int shift;
-	unsigned long flags;
-
-	if (gpio < 16) {
-		reg = mm->regs + GPIO_ICR;
-		shift = (15 - gpio) * 2;
-	} else {
-		reg = mm->regs + GPIO_ICR2;
-		shift = (15 - (gpio % 16)) * 2;
-	}
-
-	switch (flow_type) {
-	case IRQ_TYPE_EDGE_FALLING:
-	case IRQ_TYPE_LEVEL_LOW:
-		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-		clrsetbits_be32(reg, 3 << shift, 2 << shift);
-		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-		break;
-
-	case IRQ_TYPE_EDGE_RISING:
-	case IRQ_TYPE_LEVEL_HIGH:
-		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-		clrsetbits_be32(reg, 3 << shift, 1 << shift);
-		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-		break;
-
-	case IRQ_TYPE_EDGE_BOTH:
-		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-		clrbits32(reg, 3 << shift);
-		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct irq_chip mpc8xxx_irq_chip = {
-	.name		= "mpc8xxx-gpio",
-	.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,
-				irq_hw_number_t hw)
-{
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data;
-
-	if (mpc8xxx_gc->of_dev_id_data)
-		mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data;
-
-	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;
-}
-
-static int mpc8xxx_gpio_irq_xlate(struct irq_host *h, struct device_node *ct,
-				  const u32 *intspec, unsigned int intsize,
-				  irq_hw_number_t *out_hwirq,
-				  unsigned int *out_flags)
-
-{
-	/* interrupt sense values coming from the device tree equal either
-	 * EDGE_FALLING or EDGE_BOTH
-	 */
-	*out_hwirq = intspec[0];
-	*out_flags = intspec[1];
-
-	return 0;
-}
-
-static struct irq_host_ops mpc8xxx_gpio_irq_ops = {
-	.map	= mpc8xxx_gpio_irq_map,
-	.xlate	= mpc8xxx_gpio_irq_xlate,
-};
-
-static struct of_device_id mpc8xxx_gpio_ids[] __initdata = {
-	{ .compatible = "fsl,mpc8349-gpio", },
-	{ .compatible = "fsl,mpc8572-gpio", },
-	{ .compatible = "fsl,mpc8610-gpio", },
-	{ .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, },
-	{ .compatible = "fsl,qoriq-gpio",   },
-	{}
-};
-
-static void __init mpc8xxx_add_controller(struct device_node *np)
-{
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc;
-	struct of_mm_gpio_chip *mm_gc;
-	struct gpio_chip *gc;
-	const struct of_device_id *id;
-	unsigned hwirq;
-	int ret;
-
-	mpc8xxx_gc = kzalloc(sizeof(*mpc8xxx_gc), GFP_KERNEL);
-	if (!mpc8xxx_gc) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	spin_lock_init(&mpc8xxx_gc->lock);
-
-	mm_gc = &mpc8xxx_gc->mm_gc;
-	gc = &mm_gc->gc;
-
-	mm_gc->save_regs = mpc8xxx_gpio_save_regs;
-	gc->ngpio = MPC8XXX_GPIO_PINS;
-	gc->direction_input = mpc8xxx_gpio_dir_in;
-	gc->direction_output = mpc8xxx_gpio_dir_out;
-	if (of_device_is_compatible(np, "fsl,mpc8572-gpio"))
-		gc->get = mpc8572_gpio_get;
-	else
-		gc->get = mpc8xxx_gpio_get;
-	gc->set = mpc8xxx_gpio_set;
-	gc->to_irq = mpc8xxx_gpio_to_irq;
-
-	ret = of_mm_gpiochip_add(np, mm_gc);
-	if (ret)
-		goto err;
-
-	hwirq = irq_of_parse_and_map(np, 0);
-	if (hwirq == NO_IRQ)
-		goto skip_irq;
-
-	mpc8xxx_gc->irq =
-		irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, MPC8XXX_GPIO_PINS,
-			       &mpc8xxx_gpio_irq_ops, MPC8XXX_GPIO_PINS);
-	if (!mpc8xxx_gc->irq)
-		goto skip_irq;
-
-	id = of_match_node(mpc8xxx_gpio_ids, np);
-	if (id)
-		mpc8xxx_gc->of_dev_id_data = id->data;
-
-	mpc8xxx_gc->irq->host_data = mpc8xxx_gc;
-
-	/* ack and mask all irqs */
-	out_be32(mm_gc->regs + GPIO_IER, 0xffffffff);
-	out_be32(mm_gc->regs + GPIO_IMR, 0);
-
-	irq_set_handler_data(hwirq, mpc8xxx_gc);
-	irq_set_chained_handler(hwirq, mpc8xxx_gpio_irq_cascade);
-
-skip_irq:
-	return;
-
-err:
-	pr_err("%s: registration failed with status %d\n",
-	       np->full_name, ret);
-	kfree(mpc8xxx_gc);
-
-	return;
-}
-
-static int __init mpc8xxx_add_gpiochips(void)
-{
-	struct device_node *np;
-
-	for_each_matching_node(np, mpc8xxx_gpio_ids)
-		mpc8xxx_add_controller(np);
-
-	return 0;
-}
-arch_initcall(mpc8xxx_add_gpiochips);
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/mpic.c linux-libre-3.2-gnu/arch/powerpc/sysdev/mpic.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/mpic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/mpic.c	2012-01-04 18:55:44.000000000 -0500
@@ -800,8 +800,6 @@
 	 * IPIs are marked IRQ_PER_CPU. This has the side effect of
 	 * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from
 	 * applying to them. We EOI them late to avoid re-entering.
-	 * We mark IPI's with IRQF_DISABLED as they must run with
-	 * irqs disabled.
 	 */
 	mpic_eoi(mpic);
 }
@@ -1285,13 +1283,11 @@
 			   mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
 			   | MPIC_GREG_GCONF_MCK);
 
-	/* Read feature register, calculate num CPUs and, for non-ISU
-	 * MPICs, num sources as well. On ISU MPICs, sources are counted
-	 * as ISUs are added
+	/*
+	 * Read feature register.  For non-ISU MPICs, num sources as well. On
+	 * ISU MPICs, sources are counted as ISUs are added
 	 */
 	greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
-	mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK)
-			  >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
 	if (isu_size == 0) {
 		if (flags & MPIC_BROKEN_FRR_NIRQS)
 			mpic->num_sources = mpic->irq_count;
@@ -1301,10 +1297,18 @@
 				 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
 	}
 
+	/*
+	 * The MPIC driver will crash if there are more cores than we
+	 * can initialize, so we may as well catch that problem here.
+	 */
+	BUG_ON(num_possible_cpus() > MPIC_MAX_CPUS);
+
 	/* Map the per-CPU registers */
-	for (i = 0; i < mpic->num_cpus; i++) {
-		mpic_map(mpic, node, paddr, &mpic->cpuregs[i],
-			 MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE),
+	for_each_possible_cpu(i) {
+		unsigned int cpu = get_hard_smp_processor_id(i);
+
+		mpic_map(mpic, node, paddr, &mpic->cpuregs[cpu],
+			 MPIC_INFO(CPU_BASE) + cpu * MPIC_INFO(CPU_STRIDE),
 			 0x1000);
 	}
 
@@ -1343,7 +1347,7 @@
 	}
 	printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %llx,"
 	       " max %d CPUs\n",
-	       name, vers, (unsigned long long)paddr, mpic->num_cpus);
+	       name, vers, (unsigned long long)paddr, num_possible_cpus());
 	printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n",
 	       mpic->isu_size, mpic->isu_shift, mpic->isu_mask);
 
@@ -1742,6 +1746,7 @@
 	struct mpic *mpic = mpic_primary;
 	u32 pir;
 	int cpuid = get_hard_smp_processor_id(cpu);
+	int i;
 
 	/* Set target bit for core reset */
 	pir = mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT));
@@ -1753,6 +1758,15 @@
 	pir &= ~(1 << cpuid);
 	mpic_write(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT), pir);
 	mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT));
+
+	/* Perform 15 EOI on each reset core to clear pending interrupts.
+	 * This is required for FSL CoreNet based devices */
+	if (mpic->flags & MPIC_FSL) {
+		for (i = 0; i < 15; i++) {
+			_mpic_write(mpic->reg_type, &mpic->cpuregs[cpuid],
+				      MPIC_CPU_EOI, 0);
+		}
+	}
 }
 #endif /* CONFIG_SMP */
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/mv64x60_pci.c linux-libre-3.2-gnu/arch/powerpc/sysdev/mv64x60_pci.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/mv64x60_pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/mv64x60_pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/stat.h>
 #include <linux/pci.h>
 
 #include <asm/prom.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/pmi.c linux-libre-3.2-gnu/arch/powerpc/sysdev/pmi.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/pmi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/pmi.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/completion.h>
 #include <linux/spinlock.h>
+#include <linux/module.h>
 #include <linux/workqueue.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/ppc4xx_msi.c linux-libre-3.2-gnu/arch/powerpc/sysdev/ppc4xx_msi.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/ppc4xx_msi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/ppc4xx_msi.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/msi.h>
 #include <linux/of_platform.h>
 #include <linux/interrupt.h>
+#include <linux/export.h>
 #include <asm/prom.h>
 #include <asm/hw_irq.h>
 #include <asm/ppc-pci.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/ppc4xx_pci.c linux-libre-3.2-gnu/arch/powerpc/sysdev/ppc4xx_pci.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/ppc4xx_pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/ppc4xx_pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -834,7 +834,7 @@
 	return 3;
 }
 
-static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
 	u32 val = 1 << 24;
 
@@ -872,12 +872,12 @@
 	return ppc4xx_pciex_port_reset_sdr(port);
 }
 
-static int ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
 	return ppc440spe_pciex_init_port_hw(port);
 }
 
-static int ppc440speB_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc440speB_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
 	int rc = ppc440spe_pciex_init_port_hw(port);
 
@@ -936,7 +936,7 @@
 	return 2;
 }
 
-static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
 	u32 val;
 	u32 utlset1;
@@ -1092,6 +1092,10 @@
 	mtdcri(SDR0, PESDR1_460SX_HSSSLEW, 0xFFFF0000);
 	mtdcri(SDR0, PESDR2_460SX_HSSSLEW, 0xFFFF0000);
 
+	/* Set HSS PRBS enabled */
+	mtdcri(SDR0, PESDR0_460SX_HSSCTLSET, 0x00001130);
+	mtdcri(SDR0, PESDR2_460SX_HSSCTLSET, 0x00001130);
+
 	udelay(100);
 
 	/* De-assert PLLRESET */
@@ -1122,7 +1126,7 @@
 	return 2;
 }
 
-static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
 
 	if (port->endpoint)
@@ -1132,9 +1136,6 @@
 		dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2,
 				0, 0x01000000);
 
-	/*Gen-1*/
-	mtdcri(SDR0, port->sdr_base + PESDRn_460SX_RCEI, 0x08000000);
-
 	dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
 			(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL),
 			PESDRx_RCSSET_RSTPYN);
@@ -1148,14 +1149,42 @@
 {
 	/* Max 128 Bytes */
 	out_be32 (port->utl_base + PEUTL_PBBSZ,   0x00000000);
+	/* Assert VRB and TXE - per datasheet turn off addr validation */
+	out_be32(port->utl_base + PEUTL_PCTL,  0x80800000);
 	return 0;
 }
 
+static void __init ppc460sx_pciex_check_link(struct ppc4xx_pciex_port *port)
+{
+	void __iomem *mbase;
+	int attempt = 50;
+
+	port->link = 0;
+
+	mbase = ioremap(port->cfg_space.start + 0x10000000, 0x1000);
+	if (mbase == NULL) {
+		printk(KERN_ERR "%s: Can't map internal config space !",
+			port->node->full_name);
+		goto done;
+	}
+
+	while (attempt && (0 == (in_le32(mbase + PECFG_460SX_DLLSTA)
+			& PECFG_460SX_DLLSTA_LINKUP))) {
+		attempt--;
+		mdelay(10);
+	}
+	if (attempt)
+		port->link = 1;
+done:
+	iounmap(mbase);
+
+}
+
 static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = {
 	.core_init	= ppc460sx_pciex_core_init,
 	.port_init_hw	= ppc460sx_pciex_init_port_hw,
 	.setup_utl	= ppc460sx_pciex_init_utl,
-	.check_link	= ppc4xx_pciex_check_link_sdr,
+	.check_link	= ppc460sx_pciex_check_link,
 };
 
 #endif /* CONFIG_44x */
@@ -1189,7 +1218,7 @@
 	mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x00101000);
 }
 
-static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
 	u32 val;
 
@@ -1338,15 +1367,15 @@
 	if (rc != 0)
 		return rc;
 
-	if (ppc4xx_pciex_hwops->check_link)
-		ppc4xx_pciex_hwops->check_link(port);
-
 	/*
 	 * Initialize mapping: disable all regions and configure
 	 * CFG and REG regions based on resources in the device tree
 	 */
 	ppc4xx_pciex_port_init_mapping(port);
 
+	if (ppc4xx_pciex_hwops->check_link)
+		ppc4xx_pciex_hwops->check_link(port);
+
 	/*
 	 * Map UTL
 	 */
@@ -1360,13 +1389,23 @@
 		ppc4xx_pciex_hwops->setup_utl(port);
 
 	/*
-	 * Check for VC0 active and assert RDY.
+	 * Check for VC0 active or PLL Locked and assert RDY.
 	 */
 	if (port->sdr_base) {
-		if (port->link &&
-		    ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS,
-					     1 << 16, 1 << 16, 5000)) {
-			printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index);
+		if (of_device_is_compatible(port->node,
+				"ibm,plb-pciex-460sx")){
+			if (port->link && ppc4xx_pciex_wait_on_sdr(port,
+					PESDRn_RCSSTS,
+					1 << 12, 1 << 12, 5000)) {
+				printk(KERN_INFO "PCIE%d: PLL not locked\n",
+						port->index);
+				port->link = 0;
+			}
+		} else if (port->link &&
+			ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS,
+				1 << 16, 1 << 16, 5000)) {
+			printk(KERN_INFO "PCIE%d: VC0 not active\n",
+					port->index);
 			port->link = 0;
 		}
 
@@ -1573,8 +1612,15 @@
 		dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah);
 		dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal);
 		dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff);
-		/* Note that 3 here means enabled | single region */
-		dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3);
+		/*Enabled and single region */
+		if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
+			dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
+				sa | DCRO_PEGPL_460SX_OMR1MSKL_UOT
+					| DCRO_PEGPL_OMRxMSKL_VAL);
+		else
+			dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
+				sa | DCRO_PEGPL_OMR1MSKL_UOT
+					| DCRO_PEGPL_OMRxMSKL_VAL);
 		break;
 	case 1:
 		out_le32(mbase + PECFG_POM1LAH, pciah);
@@ -1582,8 +1628,8 @@
 		dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah);
 		dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal);
 		dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff);
-		/* Note that 3 here means enabled | single region */
-		dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3);
+		dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL,
+				sa | DCRO_PEGPL_OMRxMSKL_VAL);
 		break;
 	case 2:
 		out_le32(mbase + PECFG_POM2LAH, pciah);
@@ -1592,7 +1638,9 @@
 		dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal);
 		dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff);
 		/* Note that 3 here means enabled | IO space !!! */
-		dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, sa | 3);
+		dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL,
+				sa | DCRO_PEGPL_OMR3MSKL_IO
+					| DCRO_PEGPL_OMRxMSKL_VAL);
 		break;
 	}
 
@@ -1693,6 +1741,9 @@
 		if (res->flags & IORESOURCE_PREFETCH)
 			sa |= 0x8;
 
+		if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
+			sa |= PCI_BASE_ADDRESS_MEM_TYPE_64;
+
 		out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
 		out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa));
 
@@ -1854,6 +1905,10 @@
 	}
 	out_le16(mbase + 0x202, val);
 
+	/* Enable Bus master, memory, and io space */
+	if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
+		out_le16(mbase + 0x204, 0x7);
+
 	if (!port->endpoint) {
 		/* Set Class Code to PCI-PCI bridge and Revision Id to 1 */
 		out_le32(mbase + 0x208, 0x06040001);
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/ppc4xx_pci.h linux-libre-3.2-gnu/arch/powerpc/sysdev/ppc4xx_pci.h
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/ppc4xx_pci.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/ppc4xx_pci.h	2012-01-04 18:55:44.000000000 -0500
@@ -464,6 +464,18 @@
 #define PECFG_POM2LAL		0x390
 #define PECFG_POM2LAH		0x394
 
+/* 460sx only */
+#define PECFG_460SX_DLLSTA     0x3f8
+
+/* 460sx Bit Mappings */
+#define PECFG_460SX_DLLSTA_LINKUP	 0x00000010
+#define DCRO_PEGPL_460SX_OMR1MSKL_UOT	 0x00000004
+
+/* PEGPL Bit Mappings */
+#define DCRO_PEGPL_OMRxMSKL_VAL	 0x00000001
+#define DCRO_PEGPL_OMR1MSKL_UOT	 0x00000002
+#define DCRO_PEGPL_OMR3MSKL_IO	 0x00000002
+
 /* SDR Bit Mappings */
 #define PESDRx_RCSSET_HLDPLB	0x10000000
 #define PESDRx_RCSSET_RSTGU	0x01000000
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/ppc4xx_soc.c linux-libre-3.2-gnu/arch/powerpc/sysdev/ppc4xx_soc.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/ppc4xx_soc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/ppc4xx_soc.c	2012-01-04 18:55:44.000000000 -0500
@@ -115,7 +115,7 @@
 	}
 
 	/* Install error handler */
-	if (request_irq(irq, l2c_error_handler, IRQF_DISABLED, "L2C", 0) < 0) {
+	if (request_irq(irq, l2c_error_handler, 0, "L2C", 0) < 0) {
 		printk(KERN_ERR "Cannot install L2C error handler"
 		       ", cache is not enabled\n");
 		of_node_put(np);
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/qe_lib/gpio.c linux-libre-3.2-gnu/arch/powerpc/sysdev/qe_lib/gpio.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/qe_lib/gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/qe_lib/gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/of_gpio.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <asm/qe.h>
 
 struct qe_gpio_chip {
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/qe_lib/qe.c linux-libre-3.2-gnu/arch/powerpc/sysdev/qe_lib/qe.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/qe_lib/qe.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/qe_lib/qe.c	2012-01-04 18:55:44.000000000 -0500
@@ -216,7 +216,7 @@
 	/* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says
 	   that the BRG divisor must be even if you're not using divide-by-16
 	   mode. */
-	if (!div16 && (divisor & 1))
+	if (!div16 && (divisor & 1) && (divisor > 3))
 		divisor++;
 
 	tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
@@ -382,7 +382,7 @@
 /*
  * Upload a microcode to the I-RAM at a specific address.
  *
- * See Documentation/powerpc/qe-firmware.txt for information on QE microcode
+ * See Documentation/powerpc/qe_firmware.txt for information on QE microcode
  * uploading.
  *
  * Currently, only version 1 is supported, so the 'version' field must be
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/qe_lib/ucc.c linux-libre-3.2-gnu/arch/powerpc/sysdev/qe_lib/ucc.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/qe_lib/ucc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/qe_lib/ucc.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/errno.h>
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/irq.h>
 #include <asm/io.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/qe_lib/ucc_fast.c linux-libre-3.2-gnu/arch/powerpc/sysdev/qe_lib/ucc_fast.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/qe_lib/ucc_fast.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/qe_lib/ucc_fast.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/stddef.h>
 #include <linux/interrupt.h>
 #include <linux/err.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/io.h>
 #include <asm/immap_qe.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/qe_lib/ucc_slow.c linux-libre-3.2-gnu/arch/powerpc/sysdev/qe_lib/ucc_slow.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/qe_lib/ucc_slow.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/qe_lib/ucc_slow.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/stddef.h>
 #include <linux/interrupt.h>
 #include <linux/err.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/io.h>
 #include <asm/immap_qe.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/qe_lib/usb.c linux-libre-3.2-gnu/arch/powerpc/sysdev/qe_lib/usb.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/qe_lib/usb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/qe_lib/usb.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/export.h>
 #include <linux/io.h>
 #include <asm/immap_qe.h>
 #include <asm/qe.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/rtc_cmos_setup.c linux-libre-3.2-gnu/arch/powerpc/sysdev/rtc_cmos_setup.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/rtc_cmos_setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/rtc_cmos_setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/platform_device.h>
 #include <linux/err.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/mc146818rtc.h>
 
 #include <asm/prom.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/scom.c linux-libre-3.2-gnu/arch/powerpc/sysdev/scom.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/scom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/scom.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <asm/prom.h>
 #include <asm/scom.h>
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/simple_gpio.c linux-libre-3.2-gnu/arch/powerpc/sysdev/simple_gpio.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/simple_gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/simple_gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/tsi108_dev.c linux-libre-3.2-gnu/arch/powerpc/sysdev/tsi108_dev.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/tsi108_dev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/tsi108_dev.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/major.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/of_net.h>
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/uic.c linux-libre-3.2-gnu/arch/powerpc/sysdev/uic.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/uic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/uic.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,7 +47,7 @@
 	int index;
 	int dcrbase;
 
-	spinlock_t lock;
+	raw_spinlock_t lock;
 
 	/* The remapper for this UIC */
 	struct irq_host	*irqhost;
@@ -61,14 +61,14 @@
 	u32 er, sr;
 
 	sr = 1 << (31-src);
-	spin_lock_irqsave(&uic->lock, flags);
+	raw_spin_lock_irqsave(&uic->lock, flags);
 	/* ack level-triggered interrupts here */
 	if (irqd_is_level_type(d))
 		mtdcr(uic->dcrbase + UIC_SR, sr);
 	er = mfdcr(uic->dcrbase + UIC_ER);
 	er |= sr;
 	mtdcr(uic->dcrbase + UIC_ER, er);
-	spin_unlock_irqrestore(&uic->lock, flags);
+	raw_spin_unlock_irqrestore(&uic->lock, flags);
 }
 
 static void uic_mask_irq(struct irq_data *d)
@@ -78,11 +78,11 @@
 	unsigned long flags;
 	u32 er;
 
-	spin_lock_irqsave(&uic->lock, flags);
+	raw_spin_lock_irqsave(&uic->lock, flags);
 	er = mfdcr(uic->dcrbase + UIC_ER);
 	er &= ~(1 << (31 - src));
 	mtdcr(uic->dcrbase + UIC_ER, er);
-	spin_unlock_irqrestore(&uic->lock, flags);
+	raw_spin_unlock_irqrestore(&uic->lock, flags);
 }
 
 static void uic_ack_irq(struct irq_data *d)
@@ -91,9 +91,9 @@
 	unsigned int src = irqd_to_hwirq(d);
 	unsigned long flags;
 
-	spin_lock_irqsave(&uic->lock, flags);
+	raw_spin_lock_irqsave(&uic->lock, flags);
 	mtdcr(uic->dcrbase + UIC_SR, 1 << (31-src));
-	spin_unlock_irqrestore(&uic->lock, flags);
+	raw_spin_unlock_irqrestore(&uic->lock, flags);
 }
 
 static void uic_mask_ack_irq(struct irq_data *d)
@@ -104,7 +104,7 @@
 	u32 er, sr;
 
 	sr = 1 << (31-src);
-	spin_lock_irqsave(&uic->lock, flags);
+	raw_spin_lock_irqsave(&uic->lock, flags);
 	er = mfdcr(uic->dcrbase + UIC_ER);
 	er &= ~sr;
 	mtdcr(uic->dcrbase + UIC_ER, er);
@@ -118,7 +118,7 @@
 	 */
 	if (!irqd_is_level_type(d))
 		mtdcr(uic->dcrbase + UIC_SR, sr);
-	spin_unlock_irqrestore(&uic->lock, flags);
+	raw_spin_unlock_irqrestore(&uic->lock, flags);
 }
 
 static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type)
@@ -152,7 +152,7 @@
 
 	mask = ~(1 << (31 - src));
 
-	spin_lock_irqsave(&uic->lock, flags);
+	raw_spin_lock_irqsave(&uic->lock, flags);
 	tr = mfdcr(uic->dcrbase + UIC_TR);
 	pr = mfdcr(uic->dcrbase + UIC_PR);
 	tr = (tr & mask) | (trigger << (31-src));
@@ -161,7 +161,7 @@
 	mtdcr(uic->dcrbase + UIC_PR, pr);
 	mtdcr(uic->dcrbase + UIC_TR, tr);
 
-	spin_unlock_irqrestore(&uic->lock, flags);
+	raw_spin_unlock_irqrestore(&uic->lock, flags);
 
 	return 0;
 }
@@ -254,7 +254,7 @@
 	if (! uic)
 		return NULL; /* FIXME: panic? */
 
-	spin_lock_init(&uic->lock);
+	raw_spin_lock_init(&uic->lock);
 	indexp = of_get_property(node, "cell-index", &len);
 	if (!indexp || (len != sizeof(u32))) {
 		printk(KERN_ERR "uic: Device node %s has missing or invalid "
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/xics/icp-native.c linux-libre-3.2-gnu/arch/powerpc/sysdev/xics/icp-native.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/xics/icp-native.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/xics/icp-native.c	2012-01-04 18:55:44.000000000 -0500
@@ -276,7 +276,7 @@
 #endif
 };
 
-int icp_native_init(void)
+int __init icp_native_init(void)
 {
 	struct device_node *np;
 	u32 indx = 0;
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/xics/ics-opal.c linux-libre-3.2-gnu/arch/powerpc/sysdev/xics/ics-opal.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/xics/ics-opal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/xics/ics-opal.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,244 @@
+/*
+ * ICS backend for OPAL managed interrupts.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/of.h>
+#include <linux/spinlock.h>
+#include <linux/msi.h>
+
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/errno.h>
+#include <asm/xics.h>
+#include <asm/opal.h>
+#include <asm/firmware.h>
+
+static int ics_opal_mangle_server(int server)
+{
+	/* No link for now */
+	return server << 2;
+}
+
+static int ics_opal_unmangle_server(int server)
+{
+	/* No link for now */
+	return server >> 2;
+}
+
+static void ics_opal_unmask_irq(struct irq_data *d)
+{
+	unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+	int64_t rc;
+	int server;
+
+	pr_devel("ics-hal: unmask virq %d [hw 0x%x]\n", d->irq, hw_irq);
+
+	if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
+		return;
+
+	server = xics_get_irq_server(d->irq, d->affinity, 0);
+	server = ics_opal_mangle_server(server);
+
+	rc = opal_set_xive(hw_irq, server, DEFAULT_PRIORITY);
+	if (rc != OPAL_SUCCESS)
+		pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)"
+		       " error %lld\n",
+		       __func__, d->irq, hw_irq, server, rc);
+}
+
+static unsigned int ics_opal_startup(struct irq_data *d)
+{
+#ifdef CONFIG_PCI_MSI
+	/*
+	 * 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 (d->msi_desc)
+		unmask_msi_irq(d);
+#endif
+
+	/* unmask it */
+	ics_opal_unmask_irq(d);
+	return 0;
+}
+
+static void ics_opal_mask_real_irq(unsigned int hw_irq)
+{
+	int server = ics_opal_mangle_server(xics_default_server);
+	int64_t rc;
+
+	if (hw_irq == XICS_IPI)
+		return;
+
+	/* Have to set XIVE to 0xff to be able to remove a slot */
+	rc = opal_set_xive(hw_irq, server, 0xff);
+	if (rc != OPAL_SUCCESS)
+		pr_err("%s: opal_set_xive(0xff) irq=%u returned %lld\n",
+		       __func__, hw_irq, rc);
+}
+
+static void ics_opal_mask_irq(struct irq_data *d)
+{
+	unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+
+	pr_devel("ics-hal: mask virq %d [hw 0x%x]\n", d->irq, hw_irq);
+
+	if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
+		return;
+	ics_opal_mask_real_irq(hw_irq);
+}
+
+static int ics_opal_set_affinity(struct irq_data *d,
+				 const struct cpumask *cpumask,
+				 bool force)
+{
+	unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+	int16_t server;
+	int8_t priority;
+	int64_t rc;
+	int wanted_server;
+
+	if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
+		return -1;
+
+	rc = opal_get_xive(hw_irq, &server, &priority);
+	if (rc != OPAL_SUCCESS) {
+		pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)"
+		       " error %lld\n",
+		       __func__, d->irq, hw_irq, server, rc);
+		return -1;
+	}
+
+	wanted_server = xics_get_irq_server(d->irq, cpumask, 1);
+	if (wanted_server < 0) {
+		char cpulist[128];
+		cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
+		pr_warning("%s: No online cpus in the mask %s for irq %d\n",
+			   __func__, cpulist, d->irq);
+		return -1;
+	}
+	server = ics_opal_mangle_server(wanted_server);
+
+	pr_devel("ics-hal: set-affinity irq %d [hw 0x%x] server: 0x%x/0x%x\n",
+		 d->irq, hw_irq, wanted_server, server);
+
+	rc = opal_set_xive(hw_irq, server, priority);
+	if (rc != OPAL_SUCCESS) {
+		pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)"
+		       " error %lld\n",
+		       __func__, d->irq, hw_irq, server, rc);
+		return -1;
+	}
+	return 0;
+}
+
+static struct irq_chip ics_opal_irq_chip = {
+	.name = "OPAL ICS",
+	.irq_startup = ics_opal_startup,
+	.irq_mask = ics_opal_mask_irq,
+	.irq_unmask = ics_opal_unmask_irq,
+	.irq_eoi = NULL, /* Patched at init time */
+	.irq_set_affinity = ics_opal_set_affinity
+};
+
+static int ics_opal_map(struct ics *ics, unsigned int virq);
+static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec);
+static long ics_opal_get_server(struct ics *ics, unsigned long vec);
+
+static int ics_opal_host_match(struct ics *ics, struct device_node *node)
+{
+	return 1;
+}
+
+/* Only one global & state struct ics */
+static struct ics ics_hal = {
+	.map		= ics_opal_map,
+	.mask_unknown	= ics_opal_mask_unknown,
+	.get_server	= ics_opal_get_server,
+	.host_match	= ics_opal_host_match,
+};
+
+static int ics_opal_map(struct ics *ics, unsigned int virq)
+{
+	unsigned int hw_irq = (unsigned int)virq_to_hw(virq);
+	int64_t rc;
+	int16_t server;
+	int8_t priority;
+
+	if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS))
+		return -EINVAL;
+
+	/* Check if HAL knows about this interrupt */
+	rc = opal_get_xive(hw_irq, &server, &priority);
+	if (rc != OPAL_SUCCESS)
+		return -ENXIO;
+
+	irq_set_chip_and_handler(virq, &ics_opal_irq_chip, handle_fasteoi_irq);
+	irq_set_chip_data(virq, &ics_hal);
+
+	return 0;
+}
+
+static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec)
+{
+	int64_t rc;
+	int16_t server;
+	int8_t priority;
+
+	/* Check if HAL knows about this interrupt */
+	rc = opal_get_xive(vec, &server, &priority);
+	if (rc != OPAL_SUCCESS)
+		return;
+
+	ics_opal_mask_real_irq(vec);
+}
+
+static long ics_opal_get_server(struct ics *ics, unsigned long vec)
+{
+	int64_t rc;
+	int16_t server;
+	int8_t priority;
+
+	/* Check if HAL knows about this interrupt */
+	rc = opal_get_xive(vec, &server, &priority);
+	if (rc != OPAL_SUCCESS)
+		return -1;
+	return ics_opal_unmangle_server(server);
+}
+
+int __init ics_opal_init(void)
+{
+	if (!firmware_has_feature(FW_FEATURE_OPAL))
+		return -ENODEV;
+
+	/* We need to patch our irq chip's EOI to point to the
+	 * right ICP
+	 */
+	ics_opal_irq_chip.irq_eoi = icp_ops->eoi;
+
+	/* Register ourselves */
+	xics_register_ics(&ics_hal);
+
+	pr_info("ICS OPAL backend registered\n");
+
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/xics/Makefile linux-libre-3.2-gnu/arch/powerpc/sysdev/xics/Makefile
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/xics/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/xics/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,3 +4,4 @@
 obj-$(CONFIG_PPC_ICP_NATIVE)	+= icp-native.o
 obj-$(CONFIG_PPC_ICP_HV)	+= icp-hv.o
 obj-$(CONFIG_PPC_ICS_RTAS)	+= ics-rtas.o
+obj-$(CONFIG_PPC_POWERNV)	+= ics-opal.o
diff -druN linux-libre-3.1-gnu/arch/powerpc/sysdev/xics/xics-common.c linux-libre-3.2-gnu/arch/powerpc/sysdev/xics/xics-common.c
--- linux-libre-3.1-gnu/arch/powerpc/sysdev/xics/xics-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/sysdev/xics/xics-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -134,11 +134,10 @@
 	BUG_ON(ipi == NO_IRQ);
 
 	/*
-	 * IPIs are marked IRQF_DISABLED as they must run with irqs
-	 * disabled, and PERCPU.  The handler was set in map.
+	 * IPIs are marked IRQF_PERCPU. The handler was set in map.
 	 */
 	BUG_ON(request_irq(ipi, icp_ops->ipi_action,
-			   IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL));
+			   IRQF_PERCPU, "IPI", NULL));
 }
 
 int __init xics_smp_probe(void)
@@ -409,14 +408,10 @@
 	int rc = -1;
 
 	/* Fist locate ICP */
-#ifdef CONFIG_PPC_ICP_HV
 	if (firmware_has_feature(FW_FEATURE_LPAR))
 		rc = icp_hv_init();
-#endif
-#ifdef CONFIG_PPC_ICP_NATIVE
 	if (rc < 0)
 		rc = icp_native_init();
-#endif
 	if (rc < 0) {
 		pr_warning("XICS: Cannot find a Presentation Controller !\n");
 		return;
@@ -429,9 +424,9 @@
 	xics_ipi_chip.irq_eoi = icp_ops->eoi;
 
 	/* Now locate ICS */
-#ifdef CONFIG_PPC_ICS_RTAS
 	rc = ics_rtas_init();
-#endif
+	if (rc < 0)
+		rc = ics_opal_init();
 	if (rc < 0)
 		pr_warning("XICS: Cannot find a Source Controller !\n");
 
diff -druN linux-libre-3.1-gnu/arch/powerpc/xmon/xmon.c linux-libre-3.2-gnu/arch/powerpc/xmon/xmon.c
--- linux-libre-3.1-gnu/arch/powerpc/xmon/xmon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/powerpc/xmon/xmon.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/delay.h>
 #include <linux/kallsyms.h>
 #include <linux/cpumask.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sysrq.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -340,8 +340,8 @@
 
 static inline int unrecoverable_excp(struct pt_regs *regs)
 {
-#ifdef CONFIG_4xx
-	/* We have no MSR_RI bit on 4xx, so we simply return false */
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOK3E)
+	/* We have no MSR_RI bit on 4xx or Book3e, so we simply return false */
 	return 0;
 #else
 	return ((regs->msr & MSR_RI) == 0);
diff -druN linux-libre-3.1-gnu/arch/s390/boot/compressed/misc.c linux-libre-3.2-gnu/arch/s390/boot/compressed/misc.c
--- linux-libre-3.1-gnu/arch/s390/boot/compressed/misc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/boot/compressed/misc.c	2012-01-04 18:55:44.000000000 -0500
@@ -61,7 +61,7 @@
 
 extern _sclp_print_early(const char *);
 
-int puts(const char *s)
+static int puts(const char *s)
 {
 	_sclp_print_early(s);
 	return 0;
diff -druN linux-libre-3.1-gnu/arch/s390/crypto/crypt_s390.h linux-libre-3.2-gnu/arch/s390/crypto/crypt_s390.h
--- linux-libre-3.1-gnu/arch/s390/crypto/crypt_s390.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/crypto/crypt_s390.h	2012-01-04 18:55:44.000000000 -0500
@@ -368,9 +368,12 @@
 
 	if (facility_mask & CRYPT_S390_MSA && !test_facility(17))
 		return 0;
-	if (facility_mask & CRYPT_S390_MSA3 && !test_facility(76))
+
+	if (facility_mask & CRYPT_S390_MSA3 &&
+	    (!test_facility(2) || !test_facility(76)))
 		return 0;
-	if (facility_mask & CRYPT_S390_MSA4 && !test_facility(77))
+	if (facility_mask & CRYPT_S390_MSA4 &&
+	    (!test_facility(2) || !test_facility(77)))
 		return 0;
 
 	switch (func & CRYPT_S390_OP_MASK) {
diff -druN linux-libre-3.1-gnu/arch/s390/crypto/sha_common.c linux-libre-3.2-gnu/arch/s390/crypto/sha_common.c
--- linux-libre-3.1-gnu/arch/s390/crypto/sha_common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/crypto/sha_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
  */
 
 #include <crypto/internal/hash.h>
+#include <linux/module.h>
 #include "sha.h"
 #include "crypt_s390.h"
 
diff -druN linux-libre-3.1-gnu/arch/s390/defconfig linux-libre-3.2-gnu/arch/s390/defconfig
--- linux-libre-3.1-gnu/arch/s390/defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -68,7 +68,7 @@
 CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
diff -druN linux-libre-3.1-gnu/arch/s390/hypfs/hypfs_diag.c linux-libre-3.2-gnu/arch/s390/hypfs/hypfs_diag.c
--- linux-libre-3.1-gnu/arch/s390/hypfs/hypfs_diag.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/hypfs/hypfs_diag.c	2012-01-04 18:55:44.000000000 -0500
@@ -562,10 +562,9 @@
 	void *base;
 
 	buf_size = PAGE_SIZE * (diag204_buf_pages + 1) + sizeof(d204->hdr);
-	base = vmalloc(buf_size);
+	base = vzalloc(buf_size);
 	if (!base)
 		return -ENOMEM;
-	memset(base, 0, buf_size);
 	d204 = page_align_ptr(base + sizeof(d204->hdr)) - sizeof(d204->hdr);
 	rc = diag204_do_store(d204->buf, diag204_buf_pages);
 	if (rc) {
diff -druN linux-libre-3.1-gnu/arch/s390/hypfs/inode.c linux-libre-3.2-gnu/arch/s390/hypfs/inode.c
--- linux-libre-3.1-gnu/arch/s390/hypfs/inode.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/hypfs/inode.c	2012-01-04 18:55:44.000000000 -0500
@@ -108,9 +108,7 @@
 		ret->i_gid = hypfs_info->gid;
 		ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
 		if (mode & S_IFDIR)
-			ret->i_nlink = 2;
-		else
-			ret->i_nlink = 1;
+			set_nlink(ret, 2);
 	}
 	return ret;
 }
@@ -361,7 +359,7 @@
 	} else if (mode & S_IFDIR) {
 		inode->i_op = &simple_dir_inode_operations;
 		inode->i_fop = &simple_dir_operations;
-		parent->d_inode->i_nlink++;
+		inc_nlink(parent->d_inode);
 	} else
 		BUG();
 	inode->i_private = data;
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/ccwdev.h linux-libre-3.2-gnu/arch/s390/include/asm/ccwdev.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/ccwdev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/ccwdev.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
 #include <asm/fcx.h>
+#include <asm/irq.h>
 
 /* structs from asm/cio.h */
 struct irb;
@@ -127,6 +128,7 @@
  * @restore: callback for restoring after hibernation
  * @uc_handler: callback for unit check handler
  * @driver: embedded device driver structure
+ * @int_class: interruption class to use for accounting interrupts
  */
 struct ccw_driver {
 	struct ccw_device_id *ids;
@@ -144,6 +146,7 @@
 	int (*restore)(struct ccw_device *);
 	enum uc_todo (*uc_handler) (struct ccw_device *, struct irb *);
 	struct device_driver driver;
+	enum interruption_class int_class;
 };
 
 extern struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv,
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/compat.h linux-libre-3.2-gnu/arch/s390/include/asm/compat.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/compat.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/compat.h	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #define PSW32_MASK_IO		0x02000000UL
 #define PSW32_MASK_EXT		0x01000000UL
 #define PSW32_MASK_KEY		0x00F00000UL
+#define PSW32_MASK_BASE		0x00080000UL	/* Always one */
 #define PSW32_MASK_MCHECK	0x00040000UL
 #define PSW32_MASK_WAIT		0x00020000UL
 #define PSW32_MASK_PSTATE	0x00010000UL
@@ -19,21 +20,19 @@
 #define PSW32_MASK_CC		0x00003000UL
 #define PSW32_MASK_PM		0x00000f00UL
 
-#define PSW32_ADDR_AMODE31	0x80000000UL
+#define PSW32_MASK_USER		0x00003F00UL
+
+#define PSW32_ADDR_AMODE	0x80000000UL
 #define PSW32_ADDR_INSN		0x7FFFFFFFUL
 
-#define PSW32_BASE_BITS		0x00080000UL
+#define PSW32_DEFAULT_KEY	(((u32) PAGE_DEFAULT_ACC) << 20)
 
 #define PSW32_ASC_PRIMARY	0x00000000UL
 #define PSW32_ASC_ACCREG	0x00004000UL
 #define PSW32_ASC_SECONDARY	0x00008000UL
 #define PSW32_ASC_HOME		0x0000C000UL
 
-#define PSW32_MASK_MERGE(CURRENT,NEW) \
-	(((CURRENT) & ~(PSW32_MASK_CC|PSW32_MASK_PM)) | \
-	 ((NEW) & (PSW32_MASK_CC|PSW32_MASK_PM)))
-
-extern long psw32_user_bits;
+extern u32 psw32_user_bits;
 
 #define COMPAT_USER_HZ		100
 #define COMPAT_UTS_MACHINE	"s390\0\0\0\0"
@@ -131,7 +130,8 @@
 	compat_fsid_t	f_fsid;
 	s32		f_namelen;
 	s32		f_frsize;
-	s32		f_spare[6];
+	s32		f_flags;
+	s32		f_spare[5];
 };
 
 #define COMPAT_RLIM_OLD_INFINITY	0x7fffffff
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/cputime.h linux-libre-3.2-gnu/arch/s390/include/asm/cputime.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/cputime.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/cputime.h	2012-01-04 18:55:44.000000000 -0500
@@ -87,6 +87,8 @@
 	return (cputime_t) m * 4096;
 }
 
+#define usecs_to_cputime64(m)		usecs_to_cputime(m)
+
 /*
  * Convert cputime to milliseconds and back.
  */
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/ipl.h linux-libre-3.2-gnu/arch/s390/include/asm/ipl.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/ipl.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/ipl.h	2012-01-04 18:55:44.000000000 -0500
@@ -168,5 +168,6 @@
 
 extern int diag308(unsigned long subcode, void *addr);
 extern void diag308_reset(void);
+extern void store_status(void);
 
 #endif /* _ASM_S390_IPL_H */
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/irq.h linux-libre-3.2-gnu/arch/s390/include/asm/irq.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,8 @@
 	EXTERNAL_INTERRUPT,
 	IO_INTERRUPT,
 	EXTINT_CLK,
-	EXTINT_IPI,
+	EXTINT_EXC,
+	EXTINT_EMS,
 	EXTINT_TMR,
 	EXTINT_TLA,
 	EXTINT_PFL,
@@ -17,8 +18,8 @@
 	EXTINT_SCP,
 	EXTINT_IUC,
 	EXTINT_CPM,
+	IOINT_CIO,
 	IOINT_QAI,
-	IOINT_QDI,
 	IOINT_DAS,
 	IOINT_C15,
 	IOINT_C70,
@@ -28,6 +29,7 @@
 	IOINT_CLW,
 	IOINT_CTC,
 	IOINT_APB,
+	IOINT_CSC,
 	NMI_NMI,
 	NR_IRQS,
 };
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/kexec.h linux-libre-3.2-gnu/arch/s390/include/asm/kexec.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/kexec.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/kexec.h	2012-01-04 18:55:44.000000000 -0500
@@ -30,9 +30,15 @@
 /* Not more than 2GB */
 #define KEXEC_CONTROL_MEMORY_LIMIT (1UL<<31)
 
+/* Maximum address we can use for the crash control pages */
+#define KEXEC_CRASH_CONTROL_MEMORY_LIMIT (-1UL)
+
 /* Allocate one page for the pdp and the second for the code */
 #define KEXEC_CONTROL_PAGE_SIZE 4096
 
+/* Alignment of crashkernel memory */
+#define KEXEC_CRASH_MEM_ALIGN HPAGE_SIZE
+
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_S390
 
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/kvm_host.h linux-libre-3.2-gnu/arch/s390/include/asm/kvm_host.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/kvm_host.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/kvm_host.h	2012-01-04 18:55:44.000000000 -0500
@@ -47,7 +47,7 @@
 #define KVM_HPAGE_MASK(x)	(~(KVM_HPAGE_SIZE(x) - 1))
 #define KVM_PAGES_PER_HPAGE(x)	(KVM_HPAGE_SIZE(x) / PAGE_SIZE)
 
-#define CPUSTAT_HOST       0x80000000
+#define CPUSTAT_STOPPED    0x80000000
 #define CPUSTAT_WAIT       0x10000000
 #define CPUSTAT_ECALL_PEND 0x08000000
 #define CPUSTAT_STOP_INT   0x04000000
@@ -119,6 +119,7 @@
 	u32 instruction_lctlg;
 	u32 exit_program_interruption;
 	u32 exit_instr_and_program;
+	u32 deliver_external_call;
 	u32 deliver_emergency_signal;
 	u32 deliver_service_signal;
 	u32 deliver_virtio_interrupt;
@@ -138,11 +139,14 @@
 	u32 instruction_stfl;
 	u32 instruction_tprot;
 	u32 instruction_sigp_sense;
+	u32 instruction_sigp_sense_running;
+	u32 instruction_sigp_external_call;
 	u32 instruction_sigp_emergency;
 	u32 instruction_sigp_stop;
 	u32 instruction_sigp_arch;
 	u32 instruction_sigp_prefix;
 	u32 instruction_sigp_restart;
+	u32 diagnose_10;
 	u32 diagnose_44;
 };
 
@@ -174,6 +178,10 @@
 	__u32 address;
 };
 
+struct kvm_s390_extcall_info {
+	__u16 code;
+};
+
 struct kvm_s390_emerg_info {
 	__u16 code;
 };
@@ -186,6 +194,7 @@
 		struct kvm_s390_ext_info ext;
 		struct kvm_s390_pgm_info pgm;
 		struct kvm_s390_emerg_info emerg;
+		struct kvm_s390_extcall_info extcall;
 		struct kvm_s390_prefix_info prefix;
 	};
 };
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/lowcore.h linux-libre-3.2-gnu/arch/s390/include/asm/lowcore.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/lowcore.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/lowcore.h	2012-01-04 18:55:44.000000000 -0500
@@ -151,10 +151,8 @@
 	 */
 	__u32	ipib;				/* 0x0e00 */
 	__u32	ipib_checksum;			/* 0x0e04 */
-
-	/* 64 bit save area */
-	__u64	save_area_64;			/* 0x0e08 */
-	__u8	pad_0x0e10[0x0f00-0x0e10];	/* 0x0e10 */
+	__u32	vmcore_info;			/* 0x0e08 */
+	__u8	pad_0x0e0c[0x0f00-0x0e0c];	/* 0x0e0c */
 
 	/* Extended facility list */
 	__u64	stfle_fac_list[32];		/* 0x0f00 */
@@ -290,9 +288,7 @@
 	 */
 	__u64	ipib;				/* 0x0e00 */
 	__u32	ipib_checksum;			/* 0x0e08 */
-
-	/* 64 bit save area */
-	__u64	save_area_64;			/* 0x0e0c */
+	__u64	vmcore_info;			/* 0x0e0c */
 	__u8	pad_0x0e14[0x0f00-0x0e14];	/* 0x0e14 */
 
 	/* Extended facility list */
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/page.h linux-libre-3.2-gnu/arch/s390/include/asm/page.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/page.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/page.h	2012-01-04 18:55:44.000000000 -0500
@@ -177,6 +177,7 @@
 struct page;
 void arch_free_page(struct page *page, int order);
 void arch_alloc_page(struct page *page, int order);
+void arch_set_page_states(int make_stable);
 
 static inline int devmem_is_allowed(unsigned long pfn)
 {
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/pgtable.h linux-libre-3.2-gnu/arch/s390/include/asm/pgtable.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/pgtable.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/pgtable.h	2012-01-04 18:55:44.000000000 -0500
@@ -593,14 +593,16 @@
 	unsigned long address, bits;
 	unsigned char skey;
 
+	if (!pte_present(*ptep))
+		return pgste;
 	address = pte_val(*ptep) & PAGE_MASK;
 	skey = page_get_storage_key(address);
 	bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED);
 	/* Clear page changed & referenced bit in the storage key */
-	if (bits) {
-		skey ^= bits;
-		page_set_storage_key(address, skey, 1);
-	}
+	if (bits & _PAGE_CHANGED)
+		page_set_storage_key(address, skey ^ bits, 1);
+	else if (bits)
+		page_reset_referenced(address);
 	/* Transfer page changed & referenced bit to guest bits in pgste */
 	pgste_val(pgste) |= bits << 48;		/* RCP_GR_BIT & RCP_GC_BIT */
 	/* Get host changed & referenced bits from pgste */
@@ -625,6 +627,8 @@
 #ifdef CONFIG_PGSTE
 	int young;
 
+	if (!pte_present(*ptep))
+		return pgste;
 	young = page_reset_referenced(pte_val(*ptep) & PAGE_MASK);
 	/* Transfer page referenced bit to pte software bit (host view) */
 	if (young || (pgste_val(pgste) & RCP_HR_BIT))
@@ -638,13 +642,15 @@
 
 }
 
-static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste)
+static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste, pte_t entry)
 {
 #ifdef CONFIG_PGSTE
 	unsigned long address;
 	unsigned long okey, nkey;
 
-	address = pte_val(*ptep) & PAGE_MASK;
+	if (!pte_present(entry))
+		return;
+	address = pte_val(entry) & PAGE_MASK;
 	okey = nkey = page_get_storage_key(address);
 	nkey &= ~(_PAGE_ACC_BITS | _PAGE_FP_BIT);
 	/* Set page access key and fetch protection bit from pgste */
@@ -696,7 +702,9 @@
 int gmap_map_segment(struct gmap *gmap, unsigned long from,
 		     unsigned long to, unsigned long length);
 int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len);
+unsigned long __gmap_fault(unsigned long address, struct gmap *);
 unsigned long gmap_fault(unsigned long address, struct gmap *);
+void gmap_discard(unsigned long from, unsigned long to, struct gmap *);
 
 /*
  * Certain architectures need to do special things when PTEs
@@ -710,7 +718,7 @@
 
 	if (mm_has_pgste(mm)) {
 		pgste = pgste_get_lock(ptep);
-		pgste_set_pte(ptep, pgste);
+		pgste_set_pte(ptep, pgste, entry);
 		*ptep = entry;
 		pgste_set_unlock(ptep, pgste);
 	} else
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/processor.h linux-libre-3.2-gnu/arch/s390/include/asm/processor.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/processor.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/processor.h	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,8 @@
 
 extern void s390_adjust_jiffies(void);
 extern int get_cpu_capability(unsigned int *);
+extern const struct seq_operations cpuinfo_op;
+extern int sysctl_ieee_emulation_warnings;
 
 /*
  * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit.
@@ -118,17 +120,17 @@
 /*
  * Do necessary setup to start up a new thread.
  */
-#define start_thread(regs, new_psw, new_stackp) do {		\
-	regs->psw.mask	= psw_user_bits;			\
-	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;		\
-	regs->gprs[15]	= new_stackp;				\
+#define start_thread(regs, new_psw, new_stackp) do {			\
+	regs->psw.mask	= psw_user_bits | PSW_MASK_EA | PSW_MASK_BA;	\
+	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;			\
+	regs->gprs[15]	= new_stackp;					\
 } while (0)
 
-#define start_thread31(regs, new_psw, new_stackp) do {		\
-	regs->psw.mask	= psw_user32_bits;			\
-	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;		\
-	regs->gprs[15]	= new_stackp;				\
-	crst_table_downgrade(current->mm, 1UL << 31);		\
+#define start_thread31(regs, new_psw, new_stackp) do {			\
+	regs->psw.mask	= psw_user_bits | PSW_MASK_BA;			\
+	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;			\
+	regs->gprs[15]	= new_stackp;					\
+	crst_table_downgrade(current->mm, 1UL << 31);			\
 } while (0)
 
 /* Forward declaration, a strange C thing */
@@ -187,7 +189,6 @@
  * Set PSW mask to specified value, while leaving the
  * PSW addr pointing to the next instruction.
  */
-
 static inline void __load_psw_mask (unsigned long mask)
 {
 	unsigned long addr;
@@ -212,26 +213,37 @@
 		: "=&d" (addr), "=Q" (psw) : "Q" (psw) : "memory", "cc");
 #endif /* __s390x__ */
 }
- 
+
 /*
- * Function to stop a processor until an interruption occurred
+ * Rewind PSW instruction address by specified number of bytes.
  */
-static inline void enabled_wait(void)
+static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc)
 {
-	__load_psw_mask(PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
-			PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_DEFAULT_KEY);
-}
+#ifndef __s390x__
+	if (psw.addr & PSW_ADDR_AMODE)
+		/* 31 bit mode */
+		return (psw.addr - ilc) | PSW_ADDR_AMODE;
+	/* 24 bit mode */
+	return (psw.addr - ilc) & ((1UL << 24) - 1);
+#else
+	unsigned long mask;
 
+	mask = (psw.mask & PSW_MASK_EA) ? -1UL :
+	       (psw.mask & PSW_MASK_BA) ? (1UL << 31) - 1 :
+					  (1UL << 24) - 1;
+	return (psw.addr - ilc) & mask;
+#endif
+}
+ 
 /*
  * Function to drop a processor into disabled wait state
  */
-
 static inline void ATTRIB_NORET disabled_wait(unsigned long code)
 {
         unsigned long ctl_buf;
         psw_t dw_psw;
 
-        dw_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT;
+	dw_psw.mask = PSW_MASK_BASE | PSW_MASK_WAIT | PSW_MASK_BA | PSW_MASK_EA;
         dw_psw.addr = code;
         /* 
          * Store status and then load disabled wait psw,
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/ptrace.h linux-libre-3.2-gnu/arch/s390/include/asm/ptrace.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/ptrace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/ptrace.h	2012-01-04 18:55:44.000000000 -0500
@@ -230,17 +230,21 @@
 #define PSW_MASK_IO		0x02000000UL
 #define PSW_MASK_EXT		0x01000000UL
 #define PSW_MASK_KEY		0x00F00000UL
+#define PSW_MASK_BASE		0x00080000UL	/* always one */
 #define PSW_MASK_MCHECK		0x00040000UL
 #define PSW_MASK_WAIT		0x00020000UL
 #define PSW_MASK_PSTATE		0x00010000UL
 #define PSW_MASK_ASC		0x0000C000UL
 #define PSW_MASK_CC		0x00003000UL
 #define PSW_MASK_PM		0x00000F00UL
+#define PSW_MASK_EA		0x00000000UL
+#define PSW_MASK_BA		0x00000000UL
+
+#define PSW_MASK_USER		0x00003F00UL
 
 #define PSW_ADDR_AMODE		0x80000000UL
 #define PSW_ADDR_INSN		0x7FFFFFFFUL
 
-#define PSW_BASE_BITS		0x00080000UL
 #define PSW_DEFAULT_KEY		(((unsigned long) PAGE_DEFAULT_ACC) << 20)
 
 #define PSW_ASC_PRIMARY		0x00000000UL
@@ -254,6 +258,7 @@
 #define PSW_MASK_DAT		0x0400000000000000UL
 #define PSW_MASK_IO		0x0200000000000000UL
 #define PSW_MASK_EXT		0x0100000000000000UL
+#define PSW_MASK_BASE		0x0000000000000000UL
 #define PSW_MASK_KEY		0x00F0000000000000UL
 #define PSW_MASK_MCHECK		0x0004000000000000UL
 #define PSW_MASK_WAIT		0x0002000000000000UL
@@ -261,12 +266,14 @@
 #define PSW_MASK_ASC		0x0000C00000000000UL
 #define PSW_MASK_CC		0x0000300000000000UL
 #define PSW_MASK_PM		0x00000F0000000000UL
+#define PSW_MASK_EA		0x0000000100000000UL
+#define PSW_MASK_BA		0x0000000080000000UL
+
+#define PSW_MASK_USER		0x00003F0180000000UL
 
 #define PSW_ADDR_AMODE		0x0000000000000000UL
 #define PSW_ADDR_INSN		0xFFFFFFFFFFFFFFFFUL
 
-#define PSW_BASE_BITS		0x0000000180000000UL
-#define PSW_BASE32_BITS		0x0000000080000000UL
 #define PSW_DEFAULT_KEY		(((unsigned long) PAGE_DEFAULT_ACC) << 52)
 
 #define PSW_ASC_PRIMARY		0x0000000000000000UL
@@ -279,18 +286,7 @@
 #ifdef __KERNEL__
 extern long psw_kernel_bits;
 extern long psw_user_bits;
-#ifdef CONFIG_64BIT
-extern long psw_user32_bits;
 #endif
-#endif
-
-/* This macro merges a NEW PSW mask specified by the user into
-   the currently active PSW mask CURRENT, modifying only those
-   bits in CURRENT that the user may be allowed to change: this
-   is the condition code and the program mask bits.  */
-#define PSW_MASK_MERGE(CURRENT,NEW) \
-	(((CURRENT) & ~(PSW_MASK_CC|PSW_MASK_PM)) | \
-	 ((NEW) & (PSW_MASK_CC|PSW_MASK_PM)))
 
 /*
  * The s390_regs structure is used to define the elf_gregset_t.
@@ -328,8 +324,7 @@
 	psw_t psw;
 	unsigned long gprs[NUM_GPRS];
 	unsigned long orig_gpr2;
-	unsigned short ilc;
-	unsigned short svcnr;
+	unsigned int svc_code;
 };
 
 /*
@@ -487,6 +482,8 @@
 #define PTRACE_POKETEXT_AREA	      0x5004
 #define PTRACE_POKEDATA_AREA 	      0x5005
 #define PTRACE_GET_LAST_BREAK	      0x5006
+#define PTRACE_PEEK_SYSTEM_CALL       0x5007
+#define PTRACE_POKE_SYSTEM_CALL	      0x5008
 
 /*
  * PT_PROT definition is loosely based on hppa bsd definition in
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/qdio.h linux-libre-3.2-gnu/arch/s390/include/asm/qdio.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/qdio.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/qdio.h	2012-01-04 18:55:44.000000000 -0500
@@ -46,6 +46,8 @@
 	u32	 : 16;
 } __attribute__ ((packed));
 
+#define QDR_AC_MULTI_BUFFER_ENABLE 0x01
+
 /**
  * struct qdr - queue description record (QDR)
  * @qfmt: queue format
@@ -123,6 +125,40 @@
 };
 
 /**
+ * struct qaob - queue asynchronous operation block
+ * @res0: reserved parameters
+ * @res1: reserved parameter
+ * @res2: reserved parameter
+ * @res3: reserved parameter
+ * @aorc: asynchronous operation return code
+ * @flags: internal flags
+ * @cbtbs: control block type
+ * @sb_count: number of storage blocks
+ * @sba: storage block element addresses
+ * @dcount: size of storage block elements
+ * @user0: user defineable value
+ * @res4: reserved paramater
+ * @user1: user defineable value
+ * @user2: user defineable value
+ */
+struct qaob {
+	u64 res0[6];
+	u8 res1;
+	u8 res2;
+	u8 res3;
+	u8 aorc;
+	u8 flags;
+	u16 cbtbs;
+	u8 sb_count;
+	u64 sba[QDIO_MAX_ELEMENTS_PER_BUFFER];
+	u16 dcount[QDIO_MAX_ELEMENTS_PER_BUFFER];
+	u64 user0;
+	u64 res4[2];
+	u64 user1;
+	u64 user2;
+} __attribute__ ((packed, aligned(256)));
+
+/**
  * struct slib - storage list information block (SLIB)
  * @nsliba: next SLIB address (if any)
  * @sla: SL address
@@ -222,9 +258,46 @@
 	u8 val[QDIO_MAX_BUFFERS_PER_Q];
 } __attribute__ ((packed, aligned(256)));
 
+#define CHSC_AC2_MULTI_BUFFER_AVAILABLE	0x0080
+#define CHSC_AC2_MULTI_BUFFER_ENABLED	0x0040
 #define CHSC_AC2_DATA_DIV_AVAILABLE	0x0010
 #define CHSC_AC2_DATA_DIV_ENABLED	0x0002
 
+/**
+ * struct qdio_outbuf_state - SBAL related asynchronous operation information
+ *   (for communication with upper layer programs)
+ *   (only required for use with completion queues)
+ * @flags: flags indicating state of buffer
+ * @aob: pointer to QAOB used for the particular SBAL
+ * @user: pointer to upper layer program's state information related to SBAL
+ *        (stored in user1 data of QAOB)
+ */
+struct qdio_outbuf_state {
+	u8 flags;
+	struct qaob *aob;
+	void *user;
+};
+
+#define QDIO_OUTBUF_STATE_FLAG_NONE	0x00
+#define QDIO_OUTBUF_STATE_FLAG_PENDING	0x01
+
+#define CHSC_AC1_INITIATE_INPUTQ	0x80
+
+
+/* qdio adapter-characteristics-1 flag */
+#define AC1_SIGA_INPUT_NEEDED		0x40	/* process input queues */
+#define AC1_SIGA_OUTPUT_NEEDED		0x20	/* process output queues */
+#define AC1_SIGA_SYNC_NEEDED		0x10	/* ask hypervisor to sync */
+#define AC1_AUTOMATIC_SYNC_ON_THININT	0x08	/* set by hypervisor */
+#define AC1_AUTOMATIC_SYNC_ON_OUT_PCI	0x04	/* set by hypervisor */
+#define AC1_SC_QEBSM_AVAILABLE		0x02	/* available for subchannel */
+#define AC1_SC_QEBSM_ENABLED		0x01	/* enabled for subchannel */
+
+#define CHSC_AC2_DATA_DIV_AVAILABLE	0x0010
+#define CHSC_AC2_DATA_DIV_ENABLED	0x0002
+
+#define CHSC_AC3_FORMAT2_CQ_AVAILABLE	0x8000
+
 struct qdio_ssqd_desc {
 	u8 flags;
 	u8:8;
@@ -243,8 +316,7 @@
 	u64 sch_token;
 	u8 mro;
 	u8 mri;
-	u8:8;
-	u8 sbalic;
+	u16 qdioac3;
 	u16:16;
 	u8:8;
 	u8 mmwc;
@@ -280,13 +352,16 @@
  * @no_output_qs: number of output queues
  * @input_handler: handler to be called for input queues
  * @output_handler: handler to be called for output queues
+ * @queue_start_poll: polling handlers (one per input queue or NULL)
  * @int_parm: interruption parameter
  * @input_sbal_addr_array:  address of no_input_qs * 128 pointers
  * @output_sbal_addr_array: address of no_output_qs * 128 pointers
+ * @output_sbal_state_array: no_output_qs * 128 state info (for CQ or NULL)
  */
 struct qdio_initialize {
 	struct ccw_device *cdev;
 	unsigned char q_format;
+	unsigned char qdr_ac;
 	unsigned char adapter_name[8];
 	unsigned int qib_param_field_format;
 	unsigned char *qib_param_field;
@@ -297,11 +372,12 @@
 	unsigned int no_output_qs;
 	qdio_handler_t *input_handler;
 	qdio_handler_t *output_handler;
-	void (*queue_start_poll) (struct ccw_device *, int, unsigned long);
+	void (**queue_start_poll) (struct ccw_device *, int, unsigned long);
 	int scan_threshold;
 	unsigned long int_parm;
 	void **input_sbal_addr_array;
 	void **output_sbal_addr_array;
+	struct qdio_outbuf_state *output_sbal_state_array;
 };
 
 #define QDIO_STATE_INACTIVE		0x00000002 /* after qdio_cleanup */
@@ -316,6 +392,7 @@
 extern int qdio_allocate(struct qdio_initialize *);
 extern int qdio_establish(struct qdio_initialize *);
 extern int qdio_activate(struct ccw_device *);
+extern void qdio_release_aob(struct qaob *);
 extern int do_QDIO(struct ccw_device *, unsigned int, int, unsigned int,
 		   unsigned int);
 extern int qdio_start_irq(struct ccw_device *, int);
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/reset.h linux-libre-3.2-gnu/arch/s390/include/asm/reset.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/reset.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/reset.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,5 +17,5 @@
 
 extern void register_reset_call(struct reset_call *reset);
 extern void unregister_reset_call(struct reset_call *reset);
-extern void s390_reset_system(void);
+extern void s390_reset_system(void (*func)(void *), void *data);
 #endif /* _ASM_S390_RESET_H */
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/setup.h linux-libre-3.2-gnu/arch/s390/include/asm/setup.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/setup.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/setup.h	2012-01-04 18:55:44.000000000 -0500
@@ -26,15 +26,21 @@
 #define IPL_DEVICE        (*(unsigned long *)  (0x10404))
 #define INITRD_START      (*(unsigned long *)  (0x1040C))
 #define INITRD_SIZE       (*(unsigned long *)  (0x10414))
+#define OLDMEM_BASE	  (*(unsigned long *)  (0x1041C))
+#define OLDMEM_SIZE	  (*(unsigned long *)  (0x10424))
 #else /* __s390x__ */
 #define IPL_DEVICE        (*(unsigned long *)  (0x10400))
 #define INITRD_START      (*(unsigned long *)  (0x10408))
 #define INITRD_SIZE       (*(unsigned long *)  (0x10410))
+#define OLDMEM_BASE	  (*(unsigned long *)  (0x10418))
+#define OLDMEM_SIZE	  (*(unsigned long *)  (0x10420))
 #endif /* __s390x__ */
 #define COMMAND_LINE      ((char *)            (0x10480))
 
 #define CHUNK_READ_WRITE 0
 #define CHUNK_READ_ONLY  1
+#define CHUNK_OLDMEM	 4
+#define CHUNK_CRASHK	 5
 
 struct mem_chunk {
 	unsigned long addr;
@@ -48,6 +54,8 @@
 extern unsigned long memory_end;
 
 void detect_memory_layout(struct mem_chunk chunk[]);
+void create_mem_hole(struct mem_chunk memory_chunk[], unsigned long addr,
+		     unsigned long size, int type);
 
 #define PRIMARY_SPACE_MODE	0
 #define ACCESS_REGISTER_MODE	1
@@ -74,6 +82,7 @@
 #define MACHINE_FLAG_LPAR	(1UL << 12)
 #define MACHINE_FLAG_SPP	(1UL << 13)
 #define MACHINE_FLAG_TOPOLOGY	(1UL << 14)
+#define MACHINE_FLAG_STCKF	(1UL << 15)
 
 #define MACHINE_IS_VM		(S390_lowcore.machine_flags & MACHINE_FLAG_VM)
 #define MACHINE_IS_KVM		(S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
@@ -92,6 +101,7 @@
 #define MACHINE_HAS_PFMF	(0)
 #define MACHINE_HAS_SPP		(0)
 #define MACHINE_HAS_TOPOLOGY	(0)
+#define MACHINE_HAS_STCKF	(0)
 #else /* __s390x__ */
 #define MACHINE_HAS_IEEE	(1)
 #define MACHINE_HAS_CSP		(1)
@@ -103,9 +113,11 @@
 #define MACHINE_HAS_PFMF	(S390_lowcore.machine_flags & MACHINE_FLAG_PFMF)
 #define MACHINE_HAS_SPP		(S390_lowcore.machine_flags & MACHINE_FLAG_SPP)
 #define MACHINE_HAS_TOPOLOGY	(S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
+#define MACHINE_HAS_STCKF	(S390_lowcore.machine_flags & MACHINE_FLAG_STCKF)
 #endif /* __s390x__ */
 
 #define ZFCPDUMP_HSA_SIZE	(32UL<<20)
+#define ZFCPDUMP_HSA_SIZE_MAX	(64UL<<20)
 
 /*
  * Console mode. Override with conmode=
@@ -134,10 +146,14 @@
 #define IPL_DEVICE        0x10404
 #define INITRD_START      0x1040C
 #define INITRD_SIZE       0x10414
+#define OLDMEM_BASE	  0x1041C
+#define OLDMEM_SIZE	  0x10424
 #else /* __s390x__ */
 #define IPL_DEVICE        0x10400
 #define INITRD_START      0x10408
 #define INITRD_SIZE       0x10410
+#define OLDMEM_BASE	  0x10418
+#define OLDMEM_SIZE	  0x10420
 #endif /* __s390x__ */
 #define COMMAND_LINE      0x10480
 
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/sfp-util.h linux-libre-3.2-gnu/arch/s390/include/asm/sfp-util.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/sfp-util.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/sfp-util.h	2012-01-04 18:55:44.000000000 -0500
@@ -72,6 +72,6 @@
 
 #define UDIV_NEEDS_NORMALIZATION 0
 
-#define abort() return 0
+#define abort() BUG()
 
 #define __BYTE_ORDER __BIG_ENDIAN
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/smp.h linux-libre-3.2-gnu/arch/s390/include/asm/smp.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/smp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/smp.h	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 extern void smp_switch_to_ipl_cpu(void (*func)(void *), void *);
 extern void smp_switch_to_cpu(void (*)(void *), void *, unsigned long sp,
 			      int from, int to);
+extern void smp_restart_with_online_cpu(void);
 extern void smp_restart_cpu(void);
 
 /*
@@ -64,6 +65,10 @@
 	func(data);
 }
 
+static inline void smp_restart_with_online_cpu(void)
+{
+}
+
 #define smp_vcpu_scheduled	(1)
 
 #endif /* CONFIG_SMP */
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/spinlock.h linux-libre-3.2-gnu/arch/s390/include/asm/spinlock.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/spinlock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/spinlock.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,8 @@
 
 #include <linux/smp.h>
 
+extern int spin_retry;
+
 static inline int
 _raw_compare_and_swap(volatile unsigned int *lock,
 		      unsigned int old, unsigned int new)
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/syscall.h linux-libre-3.2-gnu/arch/s390/include/asm/syscall.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/syscall.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/syscall.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #define _ASM_SYSCALL_H	1
 
 #include <linux/sched.h>
+#include <linux/err.h>
 #include <asm/ptrace.h>
 
 /*
@@ -25,7 +26,8 @@
 static inline long syscall_get_nr(struct task_struct *task,
 				  struct pt_regs *regs)
 {
-	return regs->svcnr ? regs->svcnr : -1;
+	return test_tsk_thread_flag(task, TIF_SYSCALL) ?
+		(regs->svc_code & 0xffff) : -1;
 }
 
 static inline void syscall_rollback(struct task_struct *task,
@@ -37,7 +39,7 @@
 static inline long syscall_get_error(struct task_struct *task,
 				     struct pt_regs *regs)
 {
-	return (regs->gprs[2] >= -4096UL) ? -regs->gprs[2] : 0;
+	return IS_ERR_VALUE(regs->gprs[2]) ? regs->gprs[2] : 0;
 }
 
 static inline long syscall_get_return_value(struct task_struct *task,
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/system.h linux-libre-3.2-gnu/arch/s390/include/asm/system.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,8 @@
 
 struct task_struct;
 
+extern int sysctl_userprocess_debug;
+
 extern struct task_struct *__switch_to(void *, void *);
 extern void update_per_regs(struct task_struct *task);
 
@@ -114,6 +116,8 @@
 extern void cmma_init(void);
 extern int memcpy_real(void *, void *, size_t);
 extern void copy_to_absolute_zero(void *dest, void *src, size_t count);
+extern int copy_to_user_real(void __user *dest, void *src, size_t count);
+extern int copy_from_user_real(void *dest, void __user *src, size_t count);
 
 #define finish_arch_switch(prev) do {					     \
 	set_fs(current->thread.mm_segment);				     \
@@ -210,8 +214,10 @@
 	__load_psw_mask(mask | (arch_local_save_flags() & ~(-1UL >> 8)));
 }
 
-#define local_mcck_enable()  __set_psw_mask(psw_kernel_bits)
-#define local_mcck_disable() __set_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK)
+#define local_mcck_enable() \
+	__set_psw_mask(psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK)
+#define local_mcck_disable() \
+	__set_psw_mask(psw_kernel_bits | PSW_MASK_DAT)
 
 #ifdef CONFIG_SMP
 
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/thread_info.h linux-libre-3.2-gnu/arch/s390/include/asm/thread_info.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/thread_info.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/thread_info.h	2012-01-04 18:55:44.000000000 -0500
@@ -48,6 +48,7 @@
 	unsigned int		cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
 	struct restart_block	restart_block;
+	unsigned int		system_call;
 	__u64			user_timer;
 	__u64			system_timer;
 	unsigned long		last_break;	/* last breaking-event-address. */
@@ -84,10 +85,10 @@
 /*
  * thread information flags bit numbers
  */
+#define TIF_SYSCALL		0	/* inside a system call */
 #define TIF_NOTIFY_RESUME	1	/* callback before returning to user */
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
-#define TIF_RESTART_SVC		4	/* restart svc with new svc number */
 #define TIF_PER_TRAP		6	/* deliver sigtrap on return to user */
 #define TIF_MCCK_PENDING	7	/* machine check handling is pending */
 #define TIF_SYSCALL_TRACE	8	/* syscall trace active */
@@ -103,11 +104,11 @@
 #define TIF_SINGLE_STEP		20	/* This task is single stepped */
 #define TIF_FREEZE		21	/* thread is freezing for suspend */
 
+#define _TIF_SYSCALL		(1<<TIF_SYSCALL)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
-#define _TIF_RESTART_SVC	(1<<TIF_RESTART_SVC)
 #define _TIF_PER_TRAP		(1<<TIF_PER_TRAP)
 #define _TIF_MCCK_PENDING	(1<<TIF_MCCK_PENDING)
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -117,7 +118,7 @@
 #define _TIF_SIE		(1<<TIF_SIE)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT		(1<<TIF_31BIT)
-#define _TIF_SINGLE_STEP	(1<<TIF_FREEZE)
+#define _TIF_SINGLE_STEP	(1<<TIF_SINGLE_STEP)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
 
 #ifdef CONFIG_64BIT
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/timex.h linux-libre-3.2-gnu/arch/s390/include/asm/timex.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/timex.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/timex.h	2012-01-04 18:55:44.000000000 -0500
@@ -86,6 +86,17 @@
 	asm volatile("stcke %0" : "=Q" (*clk) : : "cc");
 }
 
+static inline unsigned long long get_clock_fast(void)
+{
+	unsigned long long clk;
+
+	if (MACHINE_HAS_STCKF)
+		asm volatile(".insn	s,0xb27c0000,%0" : "=Q" (clk) : : "cc");
+	else
+		clk = get_clock();
+	return clk;
+}
+
 static inline unsigned long long get_clock_xt(void)
 {
 	unsigned char clk[16];
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/tlbflush.h linux-libre-3.2-gnu/arch/s390/include/asm/tlbflush.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/tlbflush.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/tlbflush.h	2012-01-04 18:55:44.000000000 -0500
@@ -59,6 +59,7 @@
 }
 #else
 #define __tlb_flush_full(mm)	__tlb_flush_local()
+#define __tlb_flush_global()	__tlb_flush_local()
 #endif
 
 /*
diff -druN linux-libre-3.1-gnu/arch/s390/include/asm/unistd.h linux-libre-3.2-gnu/arch/s390/include/asm/unistd.h
--- linux-libre-3.1-gnu/arch/s390/include/asm/unistd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -277,7 +277,9 @@
 #define __NR_clock_adjtime	337
 #define __NR_syncfs		338
 #define __NR_setns		339
-#define NR_syscalls 340
+#define __NR_process_vm_readv	340
+#define __NR_process_vm_writev	341
+#define NR_syscalls 342
 
 /* 
  * There are some system calls that are not present on 64 bit, some
diff -druN linux-libre-3.1-gnu/arch/s390/Kconfig linux-libre-3.2-gnu/arch/s390/Kconfig
--- linux-libre-3.1-gnu/arch/s390/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -91,6 +91,7 @@
 	select HAVE_ARCH_MUTEX_CPU_RELAX
 	select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
 	select HAVE_RCU_TABLE_FREE if SMP
+	select ARCH_SAVE_PAGE_KEYS if HIBERNATION
 	select ARCH_INLINE_SPIN_TRYLOCK
 	select ARCH_INLINE_SPIN_TRYLOCK_BH
 	select ARCH_INLINE_SPIN_LOCK
@@ -568,6 +569,17 @@
 	  current kernel, and to start another kernel.  It is like a reboot
 	  but is independent of hardware/microcode support.
 
+config CRASH_DUMP
+	bool "kernel crash dumps"
+	depends on 64BIT
+	select KEXEC
+	help
+	  Generate crash dump after being started by kexec.
+	  Crash dump kernels are loaded in the main kernel with kexec-tools
+	  into a specially reserved region and then later executed after
+	  a crash by kdump/kexec.
+	  For more details see Documentation/kdump/kdump.txt
+
 config ZFCPDUMP
 	def_bool n
 	prompt "zfcpdump support"
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/asm-offsets.c linux-libre-3.2-gnu/arch/s390/kernel/asm-offsets.c
--- linux-libre-3.1-gnu/arch/s390/kernel/asm-offsets.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/asm-offsets.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,8 +45,7 @@
 	DEFINE(__PT_PSW, offsetof(struct pt_regs, psw));
 	DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs));
 	DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2));
-	DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc));
-	DEFINE(__PT_SVCNR, offsetof(struct pt_regs, svcnr));
+	DEFINE(__PT_SVC_CODE, offsetof(struct pt_regs, svc_code));
 	DEFINE(__PT_SIZE, sizeof(struct pt_regs));
 	BLANK();
 	DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain));
@@ -141,7 +140,6 @@
 	DEFINE(__LC_FPREGS_SAVE_AREA, offsetof(struct _lowcore, floating_pt_save_area));
 	DEFINE(__LC_GPREGS_SAVE_AREA, offsetof(struct _lowcore, gpregs_save_area));
 	DEFINE(__LC_CREGS_SAVE_AREA, offsetof(struct _lowcore, cregs_save_area));
-	DEFINE(__LC_SAVE_AREA_64, offsetof(struct _lowcore, save_area_64));
 #ifdef CONFIG_32BIT
 	DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr));
 #else /* CONFIG_32BIT */
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/base.S linux-libre-3.2-gnu/arch/s390/kernel/base.S
--- linux-libre-3.1-gnu/arch/s390/kernel/base.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/base.S	2012-01-04 18:55:44.000000000 -0500
@@ -86,6 +86,8 @@
 ENTRY(diag308_reset)
 	larl	%r4,.Lctlregs		# Save control registers
 	stctg	%c0,%c15,0(%r4)
+	larl	%r4,.Lfpctl		# Floating point control register
+	stfpc	0(%r4)
 	larl	%r4,.Lrestart_psw	# Setup restart PSW at absolute 0
 	lghi	%r3,0
 	lg	%r4,0(%r4)		# Save PSW
@@ -99,6 +101,8 @@
 	sam64				# Switch to 64 bit addressing mode
 	larl	%r4,.Lctlregs		# Restore control registers
 	lctlg	%c0,%c15,0(%r4)
+	larl	%r4,.Lfpctl		# Restore floating point ctl register
+	lfpc	0(%r4)
 	br	%r14
 .align 16
 .Lrestart_psw:
@@ -110,6 +114,8 @@
 	.rept	16
 	.quad	0
 	.endr
+.Lfpctl:
+	.long	0
 	.previous
 
 #else /* CONFIG_64BIT */
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/compat_linux.c linux-libre-3.2-gnu/arch/s390/kernel/compat_linux.c
--- linux-libre-3.1-gnu/arch/s390/kernel/compat_linux.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/compat_linux.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,12 +60,9 @@
 
 #include "compat_linux.h"
 
-long psw_user32_bits	= (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
-			   PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
-			   PSW_MASK_PSTATE | PSW_DEFAULT_KEY);
-long psw32_user_bits	= (PSW32_BASE_BITS | PSW32_MASK_DAT | PSW32_ASC_HOME |
-			   PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK |
-			   PSW32_MASK_PSTATE);
+u32 psw32_user_bits = PSW32_MASK_DAT | PSW32_MASK_IO | PSW32_MASK_EXT |
+		      PSW32_DEFAULT_KEY | PSW32_MASK_BASE | PSW32_MASK_MCHECK |
+		      PSW32_MASK_PSTATE | PSW32_ASC_HOME;
  
 /* For this source file, we want overflow handling. */
 
@@ -365,12 +362,7 @@
 	if (set) {
 		if (copy_from_user (&s32, set, sizeof(compat_sigset_t)))
 			return -EFAULT;
-		switch (_NSIG_WORDS) {
-		case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
-		case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
-		case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
-		case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
-		}
+		s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
 	}
 	set_fs (KERNEL_DS);
 	ret = sys_rt_sigprocmask(how,
@@ -380,12 +372,8 @@
 	set_fs (old_fs);
 	if (ret) return ret;
 	if (oset) {
-		switch (_NSIG_WORDS) {
-		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
-		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
-		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
-		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
-		}
+		s32.sig[1] = (s.sig[0] >> 32);
+		s32.sig[0] = s.sig[0];
 		if (copy_to_user (oset, &s32, sizeof(compat_sigset_t)))
 			return -EFAULT;
 	}
@@ -404,12 +392,8 @@
 	ret = sys_rt_sigpending((sigset_t __force __user *) &s, sigsetsize);
 	set_fs (old_fs);
 	if (!ret) {
-		switch (_NSIG_WORDS) {
-		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
-		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
-		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
-		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
-		}
+		s32.sig[1] = (s.sig[0] >> 32);
+		s32.sig[0] = s.sig[0];
 		if (copy_to_user (set, &s32, sizeof(compat_sigset_t)))
 			return -EFAULT;
 	}
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/compat_signal.c linux-libre-3.2-gnu/arch/s390/kernel/compat_signal.c
--- linux-libre-3.1-gnu/arch/s390/kernel/compat_signal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/compat_signal.c	2012-01-04 18:55:44.000000000 -0500
@@ -141,7 +141,8 @@
 			break;
 		case __SI_FAULT >> 16:
 			err |= __get_user(tmp, &from->si_addr);
-			to->si_addr = (void __user *)(u64) (tmp & PSW32_ADDR_INSN);
+			to->si_addr = (void __force __user *)
+				(u64) (tmp & PSW32_ADDR_INSN);
 			break;
 		case __SI_POLL >> 16:
 			err |= __get_user(to->si_band, &from->si_band);
@@ -213,16 +214,8 @@
 		ret = get_user(sa_handler, &act->sa_handler);
 		ret |= __copy_from_user(&set32, &act->sa_mask,
 					sizeof(compat_sigset_t));
-		switch (_NSIG_WORDS) {
-		case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6]
-				| (((long)set32.sig[7]) << 32);
-		case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4]
-				| (((long)set32.sig[5]) << 32);
-		case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2]
-				| (((long)set32.sig[3]) << 32);
-		case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0]
-				| (((long)set32.sig[1]) << 32);
-		}
+		new_ka.sa.sa_mask.sig[0] =
+			set32.sig[0] | (((long)set32.sig[1]) << 32);
 		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 		
 		if (ret)
@@ -233,20 +226,8 @@
 	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
 	if (!ret && oact) {
-		switch (_NSIG_WORDS) {
-		case 4:
-			set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32);
-			set32.sig[6] = old_ka.sa.sa_mask.sig[3];
-		case 3:
-			set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32);
-			set32.sig[4] = old_ka.sa.sa_mask.sig[2];
-		case 2:
-			set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32);
-			set32.sig[2] = old_ka.sa.sa_mask.sig[1];
-		case 1:
-			set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
-			set32.sig[0] = old_ka.sa.sa_mask.sig[0];
-		}
+		set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
+		set32.sig[0] = old_ka.sa.sa_mask.sig[0];
 		ret = put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler);
 		ret |= __copy_to_user(&oact->sa_mask, &set32,
 				      sizeof(compat_sigset_t));
@@ -300,9 +281,10 @@
 	_s390_regs_common32 regs32;
 	int err, i;
 
-	regs32.psw.mask = PSW32_MASK_MERGE(psw32_user_bits,
-					   (__u32)(regs->psw.mask >> 32));
-	regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr;
+	regs32.psw.mask = psw32_user_bits |
+		((__u32)(regs->psw.mask >> 32) & PSW32_MASK_USER);
+	regs32.psw.addr = (__u32) regs->psw.addr |
+		(__u32)(regs->psw.mask & PSW_MASK_BA);
 	for (i = 0; i < NUM_GPRS; i++)
 		regs32.gprs[i] = (__u32) regs->gprs[i];
 	save_access_regs(current->thread.acrs);
@@ -327,8 +309,9 @@
 	err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
 	if (err)
 		return err;
-	regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask,
-				        (__u64)regs32.psw.mask << 32);
+	regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
+		(__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
+		(__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
 	regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
 	for (i = 0; i < NUM_GPRS; i++)
 		regs->gprs[i] = (__u64) regs32.gprs[i];
@@ -342,7 +325,7 @@
 		return err;
 
 	restore_fp_regs(&current->thread.fp_regs);
-	regs->svcnr = 0;	/* disable syscall checks */
+	clear_thread_flag(TIF_SYSCALL);	/* No longer in a system call */
 	return 0;
 }
 
@@ -496,11 +479,11 @@
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
 	if (ka->sa.sa_flags & SA_RESTORER) {
-		regs->gprs[14] = (__u64) ka->sa.sa_restorer;
+		regs->gprs[14] = (__u64) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
 	} else {
-		regs->gprs[14] = (__u64) frame->retcode;
+		regs->gprs[14] = (__u64) frame->retcode | PSW32_ADDR_AMODE;
 		if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
-		               (u16 __user *)(frame->retcode)))
+			       (u16 __force __user *)(frame->retcode)))
 			goto give_sigsegv;
         }
 
@@ -509,11 +492,12 @@
 		goto give_sigsegv;
 
 	/* Set up registers for signal handler */
-	regs->gprs[15] = (__u64) frame;
-	regs->psw.addr = (__u64) ka->sa.sa_handler;
+	regs->gprs[15] = (__force __u64) frame;
+	regs->psw.mask |= PSW_MASK_BA;		/* force amode 31 */
+	regs->psw.addr = (__force __u64) ka->sa.sa_handler;
 
 	regs->gprs[2] = map_signal(sig);
-	regs->gprs[3] = (__u64) &frame->sc;
+	regs->gprs[3] = (__force __u64) &frame->sc;
 
 	/* We forgot to include these in the sigcontext.
 	   To avoid breaking binary compatibility, they are passed as args. */
@@ -521,7 +505,7 @@
 	regs->gprs[5] = current->thread.prot_addr;
 
 	/* Place signal number on stack to allow backtrace from handler.  */
-	if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
+	if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
 		goto give_sigsegv;
 	return 0;
 
@@ -564,20 +548,21 @@
 	} else {
 		regs->gprs[14] = (__u64) frame->retcode;
 		err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
-		                  (u16 __user *)(frame->retcode));
+				  (u16 __force __user *)(frame->retcode));
 	}
 
 	/* Set up backchain. */
-	if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
+	if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
 		goto give_sigsegv;
 
 	/* Set up registers for signal handler */
-	regs->gprs[15] = (__u64) frame;
+	regs->gprs[15] = (__force __u64) frame;
+	regs->psw.mask |= PSW_MASK_BA;		/* force amode 31 */
 	regs->psw.addr = (__u64) ka->sa.sa_handler;
 
 	regs->gprs[2] = map_signal(sig);
-	regs->gprs[3] = (__u64) &frame->info;
-	regs->gprs[4] = (__u64) &frame->uc;
+	regs->gprs[3] = (__force __u64) &frame->info;
+	regs->gprs[4] = (__force __u64) &frame->uc;
 	return 0;
 
 give_sigsegv:
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/compat_wrapper.S linux-libre-3.2-gnu/arch/s390/kernel/compat_wrapper.S
--- linux-libre-3.1-gnu/arch/s390/kernel/compat_wrapper.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/compat_wrapper.S	2012-01-04 18:55:44.000000000 -0500
@@ -1623,8 +1623,27 @@
 	lgfr	%r2,%r2			# int
 	jg	sys_syncfs
 
-	.globl	sys_setns_wrapper
-sys_setns_wrapper:
+ENTRY(sys_setns_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	jg	sys_setns
+
+ENTRY(compat_sys_process_vm_readv_wrapper)
+	lgfr	%r2,%r2			# compat_pid_t
+	llgtr	%r3,%r3			# struct compat_iovec __user *
+	llgfr	%r4,%r4			# unsigned long
+	llgtr	%r5,%r5			# struct compat_iovec __user *
+	llgfr	%r6,%r6			# unsigned long
+	llgf	%r0,164(%r15)		# unsigned long
+	stg	%r0,160(%r15)
+	jg	sys_process_vm_readv
+
+ENTRY(compat_sys_process_vm_writev_wrapper)
+	lgfr	%r2,%r2			# compat_pid_t
+	llgtr	%r3,%r3			# struct compat_iovec __user *
+	llgfr	%r4,%r4			# unsigned long
+	llgtr	%r5,%r5			# struct compat_iovec __user *
+	llgfr	%r6,%r6			# unsigned long
+	llgf	%r0,164(%r15)		# unsigned long
+	stg	%r0,160(%r15)
+	jg	sys_process_vm_writev
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/crash_dump.c linux-libre-3.2-gnu/arch/s390/kernel/crash_dump.c
--- linux-libre-3.1-gnu/arch/s390/kernel/crash_dump.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/s390/kernel/crash_dump.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,426 @@
+/*
+ * S390 kdump implementation
+ *
+ * Copyright IBM Corp. 2011
+ * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
+ */
+
+#include <linux/crash_dump.h>
+#include <asm/lowcore.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/crash_dump.h>
+#include <linux/bootmem.h>
+#include <linux/elf.h>
+#include <asm/ipl.h>
+
+#define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y)))
+#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
+#define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y))))
+
+/*
+ * Copy one page from "oldmem"
+ *
+ * For the kdump reserved memory this functions performs a swap operation:
+ *  - [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE] is mapped to [0 - OLDMEM_SIZE].
+ *  - [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE]
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
+			 size_t csize, unsigned long offset, int userbuf)
+{
+	unsigned long src;
+
+	if (!csize)
+		return 0;
+
+	src = (pfn << PAGE_SHIFT) + offset;
+	if (src < OLDMEM_SIZE)
+		src += OLDMEM_BASE;
+	else if (src > OLDMEM_BASE &&
+		 src < OLDMEM_BASE + OLDMEM_SIZE)
+		src -= OLDMEM_BASE;
+	if (userbuf)
+		copy_to_user_real((void __force __user *) buf, (void *) src,
+				  csize);
+	else
+		memcpy_real(buf, (void *) src, csize);
+	return csize;
+}
+
+/*
+ * Copy memory from old kernel
+ */
+static int copy_from_oldmem(void *dest, void *src, size_t count)
+{
+	unsigned long copied = 0;
+	int rc;
+
+	if ((unsigned long) src < OLDMEM_SIZE) {
+		copied = min(count, OLDMEM_SIZE - (unsigned long) src);
+		rc = memcpy_real(dest, src + OLDMEM_BASE, copied);
+		if (rc)
+			return rc;
+	}
+	return memcpy_real(dest + copied, src + copied, count - copied);
+}
+
+/*
+ * Alloc memory and panic in case of ENOMEM
+ */
+static void *kzalloc_panic(int len)
+{
+	void *rc;
+
+	rc = kzalloc(len, GFP_KERNEL);
+	if (!rc)
+		panic("s390 kdump kzalloc (%d) failed", len);
+	return rc;
+}
+
+/*
+ * Get memory layout and create hole for oldmem
+ */
+static struct mem_chunk *get_memory_layout(void)
+{
+	struct mem_chunk *chunk_array;
+
+	chunk_array = kzalloc_panic(MEMORY_CHUNKS * sizeof(struct mem_chunk));
+	detect_memory_layout(chunk_array);
+	create_mem_hole(chunk_array, OLDMEM_BASE, OLDMEM_SIZE, CHUNK_CRASHK);
+	return chunk_array;
+}
+
+/*
+ * Initialize ELF note
+ */
+static void *nt_init(void *buf, Elf64_Word type, void *desc, int d_len,
+		     const char *name)
+{
+	Elf64_Nhdr *note;
+	u64 len;
+
+	note = (Elf64_Nhdr *)buf;
+	note->n_namesz = strlen(name) + 1;
+	note->n_descsz = d_len;
+	note->n_type = type;
+	len = sizeof(Elf64_Nhdr);
+
+	memcpy(buf + len, name, note->n_namesz);
+	len = roundup(len + note->n_namesz, 4);
+
+	memcpy(buf + len, desc, note->n_descsz);
+	len = roundup(len + note->n_descsz, 4);
+
+	return PTR_ADD(buf, len);
+}
+
+/*
+ * Initialize prstatus note
+ */
+static void *nt_prstatus(void *ptr, struct save_area *sa)
+{
+	struct elf_prstatus nt_prstatus;
+	static int cpu_nr = 1;
+
+	memset(&nt_prstatus, 0, sizeof(nt_prstatus));
+	memcpy(&nt_prstatus.pr_reg.gprs, sa->gp_regs, sizeof(sa->gp_regs));
+	memcpy(&nt_prstatus.pr_reg.psw, sa->psw, sizeof(sa->psw));
+	memcpy(&nt_prstatus.pr_reg.acrs, sa->acc_regs, sizeof(sa->acc_regs));
+	nt_prstatus.pr_pid = cpu_nr;
+	cpu_nr++;
+
+	return nt_init(ptr, NT_PRSTATUS, &nt_prstatus, sizeof(nt_prstatus),
+			 "CORE");
+}
+
+/*
+ * Initialize fpregset (floating point) note
+ */
+static void *nt_fpregset(void *ptr, struct save_area *sa)
+{
+	elf_fpregset_t nt_fpregset;
+
+	memset(&nt_fpregset, 0, sizeof(nt_fpregset));
+	memcpy(&nt_fpregset.fpc, &sa->fp_ctrl_reg, sizeof(sa->fp_ctrl_reg));
+	memcpy(&nt_fpregset.fprs, &sa->fp_regs, sizeof(sa->fp_regs));
+
+	return nt_init(ptr, NT_PRFPREG, &nt_fpregset, sizeof(nt_fpregset),
+		       "CORE");
+}
+
+/*
+ * Initialize timer note
+ */
+static void *nt_s390_timer(void *ptr, struct save_area *sa)
+{
+	return nt_init(ptr, NT_S390_TIMER, &sa->timer, sizeof(sa->timer),
+			 KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Initialize TOD clock comparator note
+ */
+static void *nt_s390_tod_cmp(void *ptr, struct save_area *sa)
+{
+	return nt_init(ptr, NT_S390_TODCMP, &sa->clk_cmp,
+		       sizeof(sa->clk_cmp), KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Initialize TOD programmable register note
+ */
+static void *nt_s390_tod_preg(void *ptr, struct save_area *sa)
+{
+	return nt_init(ptr, NT_S390_TODPREG, &sa->tod_reg,
+		       sizeof(sa->tod_reg), KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Initialize control register note
+ */
+static void *nt_s390_ctrs(void *ptr, struct save_area *sa)
+{
+	return nt_init(ptr, NT_S390_CTRS, &sa->ctrl_regs,
+		       sizeof(sa->ctrl_regs), KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Initialize prefix register note
+ */
+static void *nt_s390_prefix(void *ptr, struct save_area *sa)
+{
+	return nt_init(ptr, NT_S390_PREFIX, &sa->pref_reg,
+			 sizeof(sa->pref_reg), KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Fill ELF notes for one CPU with save area registers
+ */
+void *fill_cpu_elf_notes(void *ptr, struct save_area *sa)
+{
+	ptr = nt_prstatus(ptr, sa);
+	ptr = nt_fpregset(ptr, sa);
+	ptr = nt_s390_timer(ptr, sa);
+	ptr = nt_s390_tod_cmp(ptr, sa);
+	ptr = nt_s390_tod_preg(ptr, sa);
+	ptr = nt_s390_ctrs(ptr, sa);
+	ptr = nt_s390_prefix(ptr, sa);
+	return ptr;
+}
+
+/*
+ * Initialize prpsinfo note (new kernel)
+ */
+static void *nt_prpsinfo(void *ptr)
+{
+	struct elf_prpsinfo prpsinfo;
+
+	memset(&prpsinfo, 0, sizeof(prpsinfo));
+	prpsinfo.pr_sname = 'R';
+	strcpy(prpsinfo.pr_fname, "vmlinux");
+	return nt_init(ptr, NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo),
+		       KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Initialize vmcoreinfo note (new kernel)
+ */
+static void *nt_vmcoreinfo(void *ptr)
+{
+	char nt_name[11], *vmcoreinfo;
+	Elf64_Nhdr note;
+	void *addr;
+
+	if (copy_from_oldmem(&addr, &S390_lowcore.vmcore_info, sizeof(addr)))
+		return ptr;
+	memset(nt_name, 0, sizeof(nt_name));
+	if (copy_from_oldmem(&note, addr, sizeof(note)))
+		return ptr;
+	if (copy_from_oldmem(nt_name, addr + sizeof(note), sizeof(nt_name) - 1))
+		return ptr;
+	if (strcmp(nt_name, "VMCOREINFO") != 0)
+		return ptr;
+	vmcoreinfo = kzalloc_panic(note.n_descsz + 1);
+	if (copy_from_oldmem(vmcoreinfo, addr + 24, note.n_descsz))
+		return ptr;
+	vmcoreinfo[note.n_descsz + 1] = 0;
+	return nt_init(ptr, 0, vmcoreinfo, note.n_descsz, "VMCOREINFO");
+}
+
+/*
+ * Initialize ELF header (new kernel)
+ */
+static void *ehdr_init(Elf64_Ehdr *ehdr, int mem_chunk_cnt)
+{
+	memset(ehdr, 0, sizeof(*ehdr));
+	memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
+	ehdr->e_ident[EI_CLASS] = ELFCLASS64;
+	ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
+	ehdr->e_ident[EI_VERSION] = EV_CURRENT;
+	memset(ehdr->e_ident + EI_PAD, 0, EI_NIDENT - EI_PAD);
+	ehdr->e_type = ET_CORE;
+	ehdr->e_machine = EM_S390;
+	ehdr->e_version = EV_CURRENT;
+	ehdr->e_phoff = sizeof(Elf64_Ehdr);
+	ehdr->e_ehsize = sizeof(Elf64_Ehdr);
+	ehdr->e_phentsize = sizeof(Elf64_Phdr);
+	ehdr->e_phnum = mem_chunk_cnt + 1;
+	return ehdr + 1;
+}
+
+/*
+ * Return CPU count for ELF header (new kernel)
+ */
+static int get_cpu_cnt(void)
+{
+	int i, cpus = 0;
+
+	for (i = 0; zfcpdump_save_areas[i]; i++) {
+		if (zfcpdump_save_areas[i]->pref_reg == 0)
+			continue;
+		cpus++;
+	}
+	return cpus;
+}
+
+/*
+ * Return memory chunk count for ELF header (new kernel)
+ */
+static int get_mem_chunk_cnt(void)
+{
+	struct mem_chunk *chunk_array, *mem_chunk;
+	int i, cnt = 0;
+
+	chunk_array = get_memory_layout();
+	for (i = 0; i < MEMORY_CHUNKS; i++) {
+		mem_chunk = &chunk_array[i];
+		if (chunk_array[i].type != CHUNK_READ_WRITE &&
+		    chunk_array[i].type != CHUNK_READ_ONLY)
+			continue;
+		if (mem_chunk->size == 0)
+			continue;
+		cnt++;
+	}
+	kfree(chunk_array);
+	return cnt;
+}
+
+/*
+ * Relocate pointer in order to allow vmcore code access the data
+ */
+static inline unsigned long relocate(unsigned long addr)
+{
+	return OLDMEM_BASE + addr;
+}
+
+/*
+ * Initialize ELF loads (new kernel)
+ */
+static int loads_init(Elf64_Phdr *phdr, u64 loads_offset)
+{
+	struct mem_chunk *chunk_array, *mem_chunk;
+	int i;
+
+	chunk_array = get_memory_layout();
+	for (i = 0; i < MEMORY_CHUNKS; i++) {
+		mem_chunk = &chunk_array[i];
+		if (mem_chunk->size == 0)
+			break;
+		if (chunk_array[i].type != CHUNK_READ_WRITE &&
+		    chunk_array[i].type != CHUNK_READ_ONLY)
+			continue;
+		else
+			phdr->p_filesz = mem_chunk->size;
+		phdr->p_type = PT_LOAD;
+		phdr->p_offset = mem_chunk->addr;
+		phdr->p_vaddr = mem_chunk->addr;
+		phdr->p_paddr = mem_chunk->addr;
+		phdr->p_memsz = mem_chunk->size;
+		phdr->p_flags = PF_R | PF_W | PF_X;
+		phdr->p_align = PAGE_SIZE;
+		phdr++;
+	}
+	kfree(chunk_array);
+	return i;
+}
+
+/*
+ * Initialize notes (new kernel)
+ */
+static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
+{
+	struct save_area *sa;
+	void *ptr_start = ptr;
+	int i;
+
+	ptr = nt_prpsinfo(ptr);
+
+	for (i = 0; zfcpdump_save_areas[i]; i++) {
+		sa = zfcpdump_save_areas[i];
+		if (sa->pref_reg == 0)
+			continue;
+		ptr = fill_cpu_elf_notes(ptr, sa);
+	}
+	ptr = nt_vmcoreinfo(ptr);
+	memset(phdr, 0, sizeof(*phdr));
+	phdr->p_type = PT_NOTE;
+	phdr->p_offset = relocate(notes_offset);
+	phdr->p_filesz = (unsigned long) PTR_SUB(ptr, ptr_start);
+	phdr->p_memsz = phdr->p_filesz;
+	return ptr;
+}
+
+/*
+ * Create ELF core header (new kernel)
+ */
+static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz)
+{
+	Elf64_Phdr *phdr_notes, *phdr_loads;
+	int mem_chunk_cnt;
+	void *ptr, *hdr;
+	u32 alloc_size;
+	u64 hdr_off;
+
+	mem_chunk_cnt = get_mem_chunk_cnt();
+
+	alloc_size = 0x1000 + get_cpu_cnt() * 0x300 +
+		mem_chunk_cnt * sizeof(Elf64_Phdr);
+	hdr = kzalloc_panic(alloc_size);
+	/* Init elf header */
+	ptr = ehdr_init(hdr, mem_chunk_cnt);
+	/* Init program headers */
+	phdr_notes = ptr;
+	ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr));
+	phdr_loads = ptr;
+	ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr) * mem_chunk_cnt);
+	/* Init notes */
+	hdr_off = PTR_DIFF(ptr, hdr);
+	ptr = notes_init(phdr_notes, ptr, ((unsigned long) hdr) + hdr_off);
+	/* Init loads */
+	hdr_off = PTR_DIFF(ptr, hdr);
+	loads_init(phdr_loads, ((unsigned long) hdr) + hdr_off);
+	*elfcorebuf_sz = hdr_off;
+	*elfcorebuf = (void *) relocate((unsigned long) hdr);
+	BUG_ON(*elfcorebuf_sz > alloc_size);
+}
+
+/*
+ * Create kdump ELF core header in new kernel, if it has not been passed via
+ * the "elfcorehdr" kernel parameter
+ */
+static int setup_kdump_elfcorehdr(void)
+{
+	size_t elfcorebuf_sz;
+	char *elfcorebuf;
+
+	if (!OLDMEM_BASE || is_kdump_kernel())
+		return -EINVAL;
+	s390_elf_corehdr_create(&elfcorebuf, &elfcorebuf_sz);
+	elfcorehdr_addr = (unsigned long long) elfcorebuf;
+	elfcorehdr_size = elfcorebuf_sz;
+	return 0;
+}
+
+subsys_initcall(setup_kdump_elfcorehdr);
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/early.c linux-libre-3.2-gnu/arch/s390/kernel/early.c
--- linux-libre-3.1-gnu/arch/s390/kernel/early.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/early.c	2012-01-04 18:55:44.000000000 -0500
@@ -252,7 +252,7 @@
 {
 	psw_t psw;
 
-	psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+	psw.mask = PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA;
 	psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_ext_handler;
 	S390_lowcore.external_new_psw = psw;
 	psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
@@ -390,6 +390,8 @@
 		S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
 	if (test_facility(40))
 		S390_lowcore.machine_flags |= MACHINE_FLAG_SPP;
+	if (test_facility(25))
+		S390_lowcore.machine_flags |= MACHINE_FLAG_STCKF;
 #endif
 }
 
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/entry64.S linux-libre-3.2-gnu/arch/s390/kernel/entry64.S
--- linux-libre-3.1-gnu/arch/s390/kernel/entry64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/entry64.S	2012-01-04 18:55:44.000000000 -0500
@@ -43,19 +43,18 @@
 SP_R14	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 112
 SP_R15	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 120
 SP_ORIG_R2   =	STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
-SP_ILC	     =	STACK_FRAME_OVERHEAD + __PT_ILC
-SP_SVCNR      =	STACK_FRAME_OVERHEAD + __PT_SVCNR
+SP_SVC_CODE  =	STACK_FRAME_OVERHEAD + __PT_SVC_CODE
 SP_SIZE      =	STACK_FRAME_OVERHEAD + __PT_SIZE
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
 
 _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
-		 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_PER_TRAP )
+		 _TIF_MCCK_PENDING | _TIF_PER_TRAP )
 _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
 		 _TIF_MCCK_PENDING)
-_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
-		_TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8)
+_TIF_TRACE    = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
+		 _TIF_SYSCALL_TRACEPOINT)
 _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
 
 #define BASED(name) name-system_call(%r13)
@@ -249,9 +248,10 @@
 sysc_saveall:
 	SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_SAVE_AREA
-	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW
-	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
 	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
+	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW
+	mvc	SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+	oi	__TI_flags+7(%r12),_TIF_SYSCALL
 sysc_vtime:
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
 sysc_stime:
@@ -260,14 +260,14 @@
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 	LAST_BREAK
 sysc_do_svc:
-	llgh	%r7,SP_SVCNR(%r15)
+	llgh	%r7,SP_SVC_CODE+2(%r15)
 	slag	%r7,%r7,2	# shift and test for svc 0
 	jnz	sysc_nr_ok
 	# svc 0: system call number in %r1
 	llgfr	%r1,%r1		# clear high word in r1
 	cghi	%r1,NR_syscalls
 	jnl	sysc_nr_ok
-	sth	%r1,SP_SVCNR(%r15)
+	sth	%r1,SP_SVC_CODE+2(%r15)
 	slag	%r7,%r1,2	# shift and test for svc 0
 sysc_nr_ok:
 	larl	%r10,sys_call_table
@@ -277,7 +277,7 @@
 	larl	%r10,sys_call_table_emu  # use 31 bit emulation system calls
 sysc_noemu:
 #endif
-	tm	__TI_flags+6(%r12),_TIF_SYSCALL
+	tm	__TI_flags+6(%r12),_TIF_TRACE >> 8
 	mvc	SP_ARGS(8,%r15),SP_R7(%r15)
 	lgf	%r8,0(%r7,%r10) # load address of system call routine
 	jnz	sysc_tracesys
@@ -287,23 +287,19 @@
 sysc_return:
 	LOCKDEP_SYS_EXIT
 sysc_tif:
+	tm	SP_PSW+1(%r15),0x01	# returning to user ?
+	jno	sysc_restore
 	tm	__TI_flags+7(%r12),_TIF_WORK_SVC
 	jnz	sysc_work	# there is work to do (signals etc.)
+	ni	__TI_flags+7(%r12),255-_TIF_SYSCALL
 sysc_restore:
 	RESTORE_ALL __LC_RETURN_PSW,1
 sysc_done:
 
 #
-# There is work to do, but first we need to check if we return to userspace.
-#
-sysc_work:
-	tm	SP_PSW+1(%r15),0x01	# returning to user ?
-	jno	sysc_restore
-
-#
 # One of the work bits is on. Find out which one.
 #
-sysc_work_tif:
+sysc_work:
 	tm	__TI_flags+7(%r12),_TIF_MCCK_PENDING
 	jo	sysc_mcck_pending
 	tm	__TI_flags+7(%r12),_TIF_NEED_RESCHED
@@ -312,8 +308,6 @@
 	jo	sysc_sigpending
 	tm	__TI_flags+7(%r12),_TIF_NOTIFY_RESUME
 	jo	sysc_notify_resume
-	tm	__TI_flags+7(%r12),_TIF_RESTART_SVC
-	jo	sysc_restart
 	tm	__TI_flags+7(%r12),_TIF_PER_TRAP
 	jo	sysc_singlestep
 	j	sysc_return		# beware of critical section cleanup
@@ -339,11 +333,15 @@
 	ni	__TI_flags+7(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	brasl	%r14,do_signal		# call do_signal
-	tm	__TI_flags+7(%r12),_TIF_RESTART_SVC
-	jo	sysc_restart
-	tm	__TI_flags+7(%r12),_TIF_PER_TRAP
-	jo	sysc_singlestep
-	j	sysc_return
+	tm	__TI_flags+7(%r12),_TIF_SYSCALL
+	jno	sysc_return
+	lmg	%r2,%r6,SP_R2(%r15)	# load svc arguments
+	lghi	%r7,0			# svc 0 returns -ENOSYS
+	lh	%r1,SP_SVC_CODE+2(%r15)	# load new svc number
+	cghi	%r1,NR_syscalls
+	jnl	sysc_nr_ok		# invalid svc number -> do svc 0
+	slag	%r7,%r1,2
+	j	sysc_nr_ok		# restart svc
 
 #
 # _TIF_NOTIFY_RESUME is set, call do_notify_resume
@@ -354,23 +352,10 @@
 	jg	do_notify_resume	# call do_notify_resume
 
 #
-# _TIF_RESTART_SVC is set, set up registers and restart svc
-#
-sysc_restart:
-	ni	__TI_flags+7(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
-	lg	%r7,SP_R2(%r15)		# load new svc number
-	mvc	SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument
-	lmg	%r2,%r6,SP_R2(%r15)	# load svc arguments
-	sth	%r7,SP_SVCNR(%r15)
-	slag	%r7,%r7,2
-	j	sysc_nr_ok		# restart svc
-
-#
 # _TIF_PER_TRAP is set, call do_per_trap
 #
 sysc_singlestep:
-	ni	__TI_flags+7(%r12),255-_TIF_PER_TRAP	# clear TIF_PER_TRAP
-	xc	SP_SVCNR(2,%r15),SP_SVCNR(%r15)		# clear svc number
+	ni	__TI_flags+7(%r12),255-(_TIF_SYSCALL | _TIF_PER_TRAP)
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
 	larl	%r14,sysc_return	# load adr. of system return
 	jg	do_per_trap
@@ -382,7 +367,7 @@
 sysc_tracesys:
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	la	%r3,0
-	llgh	%r0,SP_SVCNR(%r15)
+	llgh	%r0,SP_SVC_CODE+2(%r15)
 	stg	%r0,SP_R2(%r15)
 	brasl	%r14,do_syscall_trace_enter
 	lghi	%r0,NR_syscalls
@@ -397,7 +382,7 @@
 	basr	%r14,%r8		# call sys_xxx
 	stg	%r2,SP_R2(%r15)		# store return value
 sysc_tracenogo:
-	tm	__TI_flags+6(%r12),_TIF_SYSCALL
+	tm	__TI_flags+6(%r12),_TIF_TRACE >> 8
 	jz	sysc_return
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	larl	%r14,sysc_return	# return point is sysc_return
@@ -470,7 +455,6 @@
 	jnz	pgm_per 		 # got per exception -> special case
 	SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_SAVE_AREA
-	xc	SP_ILC(4,%r15),SP_ILC(%r15)
 	mvc	SP_PSW(16,%r15),__LC_PGM_OLD_PSW
 	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
 	HANDLE_SIE_INTERCEPT
@@ -550,9 +534,10 @@
 pgm_svcper:
 	SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_SAVE_AREA
-	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW
-	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
 	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
+	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW
+	mvc	SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+	oi	__TI_flags+7(%r12),(_TIF_SYSCALL | _TIF_PER_TRAP)
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
 	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
@@ -561,7 +546,6 @@
 	mvc	__THREAD_per_cause(2,%r8),__LC_PER_CAUSE
 	mvc	__THREAD_per_address(8,%r8),__LC_PER_ADDRESS
 	mvc	__THREAD_per_paid(1,%r8),__LC_PER_PAID
-	oi	__TI_flags+7(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP
 	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
 	lmg	%r2,%r6,SP_R2(%r15)	# load svc arguments
 	j	sysc_do_svc
@@ -571,7 +555,6 @@
 #
 kernel_per:
 	REENABLE_IRQS
-	xc	SP_SVCNR(2,%r15),SP_SVCNR(%r15)	# clear svc number
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
 	brasl	%r14,do_per_trap
 	j	pgm_exit
@@ -869,12 +852,12 @@
 # PSW restart interrupt handler
 #
 ENTRY(psw_restart_int_handler)
-	stg	%r15,__LC_SAVE_AREA_64(%r0)	# save r15
+	stg	%r15,__LC_SAVE_AREA+120(%r0)	# save r15
 	larl	%r15,restart_stack		# load restart stack
 	lg	%r15,0(%r15)
 	aghi	%r15,-SP_SIZE			# make room for pt_regs
 	stmg	%r0,%r14,SP_R0(%r15)		# store gprs %r0-%r14 to stack
-	mvc	SP_R15(8,%r15),__LC_SAVE_AREA_64(%r0)# store saved %r15 to stack
+	mvc	SP_R15(8,%r15),__LC_SAVE_AREA+120(%r0)# store saved %r15 to stack
 	mvc	SP_PSW(16,%r15),__LC_RST_OLD_PSW(%r0)# store restart old psw
 	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # set backchain to 0
 	brasl	%r14,do_restart
@@ -972,9 +955,11 @@
 	stg	%r15,32(%r12)
 	stg	%r11,0(%r12)
 	CREATE_STACK_FRAME __LC_SAVE_AREA
-	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW
-	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
 	mvc	8(8,%r12),__LC_THREAD_INFO
+	lg	%r12,__LC_THREAD_INFO
+	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW
+	mvc	SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+	oi	__TI_flags+7(%r12),_TIF_SYSCALL
 cleanup_vtime:
 	clc	__LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24)
 	jhe	cleanup_stime
@@ -1096,6 +1081,7 @@
 	lghi	%r2,0
 	br	%r14
 sie_fault:
+	lctlg	%c1,%c1,__LC_USER_ASCE		# load primary asce
 	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
 	ni	__TI_flags+6(%r14),255-(_TIF_SIE>>8)
 	lg	%r14,__SF_EMPTY+8(%r15)		# load guest register save area
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/entry.h linux-libre-3.2-gnu/arch/s390/kernel/entry.h
--- linux-libre-3.1-gnu/arch/s390/kernel/entry.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/entry.h	2012-01-04 18:55:44.000000000 -0500
@@ -5,24 +5,33 @@
 #include <linux/signal.h>
 #include <asm/ptrace.h>
 
+
+extern void (*pgm_check_table[128])(struct pt_regs *, long, unsigned long);
+extern void *restart_stack;
+
+asmlinkage long do_syscall_trace_enter(struct pt_regs *regs);
+asmlinkage void do_syscall_trace_exit(struct pt_regs *regs);
+
 void do_protection_exception(struct pt_regs *, long, unsigned long);
 void do_dat_exception(struct pt_regs *, long, unsigned long);
 void do_asce_exception(struct pt_regs *, long, unsigned long);
 
-extern int sysctl_userprocess_debug;
-
 void do_per_trap(struct pt_regs *regs);
 void syscall_trace(struct pt_regs *regs, int entryexit);
 void kernel_stack_overflow(struct pt_regs * regs);
 void do_signal(struct pt_regs *regs);
 int handle_signal32(unsigned long sig, struct k_sigaction *ka,
 		    siginfo_t *info, sigset_t *oldset, struct pt_regs *regs);
+void do_notify_resume(struct pt_regs *regs);
 
 void do_extint(struct pt_regs *regs, unsigned int, unsigned int, unsigned long);
+void do_restart(void);
 int __cpuinit start_secondary(void *cpuvoid);
 void __init startup_init(void);
 void die(const char * str, struct pt_regs * regs, long err);
 
+void __init time_init(void);
+
 struct s390_mmap_arg_struct;
 struct fadvise64_64_args;
 struct old_sigaction;
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/entry.S linux-libre-3.2-gnu/arch/s390/kernel/entry.S
--- linux-libre-3.1-gnu/arch/s390/kernel/entry.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/entry.S	2012-01-04 18:55:44.000000000 -0500
@@ -43,16 +43,15 @@
 SP_R14	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 56
 SP_R15	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 60
 SP_ORIG_R2   =	STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
-SP_ILC	     =	STACK_FRAME_OVERHEAD + __PT_ILC
-SP_SVCNR     =	STACK_FRAME_OVERHEAD + __PT_SVCNR
+SP_SVC_CODE  =	STACK_FRAME_OVERHEAD + __PT_SVC_CODE
 SP_SIZE      =	STACK_FRAME_OVERHEAD + __PT_SIZE
 
 _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
-		 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_PER_TRAP )
+		 _TIF_MCCK_PENDING | _TIF_PER_TRAP )
 _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
 		 _TIF_MCCK_PENDING)
-_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
-		_TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8)
+_TIF_TRACE    = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
+		 _TIF_SYSCALL_TRACEPOINT)
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
@@ -228,9 +227,10 @@
 sysc_saveall:
 	SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_SAVE_AREA
-	mvc	SP_PSW(8,%r15),__LC_SVC_OLD_PSW
-	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
 	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
+	mvc	SP_PSW(8,%r15),__LC_SVC_OLD_PSW
+	mvc	SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+	oi	__TI_flags+3(%r12),_TIF_SYSCALL
 sysc_vtime:
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
 sysc_stime:
@@ -239,17 +239,17 @@
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 sysc_do_svc:
 	xr	%r7,%r7
-	icm	%r7,3,SP_SVCNR(%r15)	# load svc number and test for svc 0
+	icm	%r7,3,SP_SVC_CODE+2(%r15)# load svc number and test for svc 0
 	bnz	BASED(sysc_nr_ok)	# svc number > 0
 	# svc 0: system call number in %r1
 	cl	%r1,BASED(.Lnr_syscalls)
 	bnl	BASED(sysc_nr_ok)
-	sth	%r1,SP_SVCNR(%r15)
+	sth	%r1,SP_SVC_CODE+2(%r15)
 	lr	%r7,%r1 	  # copy svc number to %r7
 sysc_nr_ok:
 	sll	%r7,2		  # svc number *4
 	l	%r10,BASED(.Lsysc_table)
-	tm	__TI_flags+2(%r12),_TIF_SYSCALL
+	tm	__TI_flags+2(%r12),_TIF_TRACE >> 8
 	mvc	SP_ARGS(4,%r15),SP_R7(%r15)
 	l	%r8,0(%r7,%r10)	  # get system call addr.
 	bnz	BASED(sysc_tracesys)
@@ -259,23 +259,19 @@
 sysc_return:
 	LOCKDEP_SYS_EXIT
 sysc_tif:
+	tm	SP_PSW+1(%r15),0x01	# returning to user ?
+	bno	BASED(sysc_restore)
 	tm	__TI_flags+3(%r12),_TIF_WORK_SVC
 	bnz	BASED(sysc_work)  # there is work to do (signals etc.)
+	ni	__TI_flags+3(%r12),255-_TIF_SYSCALL
 sysc_restore:
 	RESTORE_ALL __LC_RETURN_PSW,1
 sysc_done:
 
 #
-# There is work to do, but first we need to check if we return to userspace.
-#
-sysc_work:
-	tm	SP_PSW+1(%r15),0x01	# returning to user ?
-	bno	BASED(sysc_restore)
-
-#
 # One of the work bits is on. Find out which one.
 #
-sysc_work_tif:
+sysc_work:
 	tm	__TI_flags+3(%r12),_TIF_MCCK_PENDING
 	bo	BASED(sysc_mcck_pending)
 	tm	__TI_flags+3(%r12),_TIF_NEED_RESCHED
@@ -284,8 +280,6 @@
 	bo	BASED(sysc_sigpending)
 	tm	__TI_flags+3(%r12),_TIF_NOTIFY_RESUME
 	bo	BASED(sysc_notify_resume)
-	tm	__TI_flags+3(%r12),_TIF_RESTART_SVC
-	bo	BASED(sysc_restart)
 	tm	__TI_flags+3(%r12),_TIF_PER_TRAP
 	bo	BASED(sysc_singlestep)
 	b	BASED(sysc_return)	# beware of critical section cleanup
@@ -314,11 +308,14 @@
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	l	%r1,BASED(.Ldo_signal)
 	basr	%r14,%r1		# call do_signal
-	tm	__TI_flags+3(%r12),_TIF_RESTART_SVC
-	bo	BASED(sysc_restart)
-	tm	__TI_flags+3(%r12),_TIF_PER_TRAP
-	bo	BASED(sysc_singlestep)
-	b	BASED(sysc_return)
+	tm	__TI_flags+3(%r12),_TIF_SYSCALL
+	bno	BASED(sysc_return)
+	lm	%r2,%r6,SP_R2(%r15)	# load svc arguments
+	xr	%r7,%r7			# svc 0 returns -ENOSYS
+	clc	SP_SVC_CODE+2(2,%r15),BASED(.Lnr_syscalls+2)
+	bnl	BASED(sysc_nr_ok)	# invalid svc number -> do svc 0
+	icm	%r7,3,SP_SVC_CODE+2(%r15)# load new svc number
+	b	BASED(sysc_nr_ok)	# restart svc
 
 #
 # _TIF_NOTIFY_RESUME is set, call do_notify_resume
@@ -329,24 +326,11 @@
 	la	%r14,BASED(sysc_return)
 	br	%r1			# call do_notify_resume
 
-
-#
-# _TIF_RESTART_SVC is set, set up registers and restart svc
-#
-sysc_restart:
-	ni	__TI_flags+3(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
-	l	%r7,SP_R2(%r15) 	# load new svc number
-	mvc	SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
-	lm	%r2,%r6,SP_R2(%r15)	# load svc arguments
-	sth	%r7,SP_SVCNR(%r15)
-	b	BASED(sysc_nr_ok)	# restart svc
-
 #
 # _TIF_PER_TRAP is set, call do_per_trap
 #
 sysc_singlestep:
-	ni	__TI_flags+3(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
-	xc	SP_SVCNR(2,%r15),SP_SVCNR(%r15)		# clear svc number
+	ni	__TI_flags+3(%r12),255-(_TIF_SYSCALL | _TIF_PER_TRAP)
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
 	l	%r1,BASED(.Lhandle_per)	# load adr. of per handler
 	la	%r14,BASED(sysc_return)	# load adr. of system return
@@ -361,7 +345,7 @@
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	la	%r3,0
 	xr	%r0,%r0
-	icm	%r0,3,SP_SVCNR(%r15)
+	icm	%r0,3,SP_SVC_CODE(%r15)
 	st	%r0,SP_R2(%r15)
 	basr	%r14,%r1
 	cl	%r2,BASED(.Lnr_syscalls)
@@ -376,7 +360,7 @@
 	basr	%r14,%r8		# call sys_xxx
 	st	%r2,SP_R2(%r15)		# store return value
 sysc_tracenogo:
-	tm	__TI_flags+2(%r12),_TIF_SYSCALL
+	tm	__TI_flags+2(%r12),_TIF_TRACE >> 8
 	bz	BASED(sysc_return)
 	l	%r1,BASED(.Ltrace_exit)
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
@@ -454,7 +438,6 @@
 	bnz	BASED(pgm_per)		# got per exception -> special case
 	SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_SAVE_AREA
-	xc	SP_ILC(4,%r15),SP_ILC(%r15)
 	mvc	SP_PSW(8,%r15),__LC_PGM_OLD_PSW
 	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
@@ -530,9 +513,10 @@
 pgm_svcper:
 	SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_SAVE_AREA
-	mvc	SP_PSW(8,%r15),__LC_SVC_OLD_PSW
-	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
 	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
+	mvc	SP_PSW(8,%r15),__LC_SVC_OLD_PSW
+	mvc	SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+	oi	__TI_flags+3(%r12),(_TIF_SYSCALL | _TIF_PER_TRAP)
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
 	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
@@ -540,7 +524,6 @@
 	mvc	__THREAD_per_cause(2,%r8),__LC_PER_CAUSE
 	mvc	__THREAD_per_address(4,%r8),__LC_PER_ADDRESS
 	mvc	__THREAD_per_paid(1,%r8),__LC_PER_PAID
-	oi	__TI_flags+3(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP
 	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
 	lm	%r2,%r6,SP_R2(%r15)	# load svc arguments
 	b	BASED(sysc_do_svc)
@@ -550,7 +533,6 @@
 #
 kernel_per:
 	REENABLE_IRQS
-	xc	SP_SVCNR(2,%r15),SP_SVCNR(%r15)
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
 	l	%r1,BASED(.Lhandle_per)	# load adr. of per handler
 	basr	%r14,%r1		# branch to do_single_step
@@ -853,13 +835,13 @@
 # PSW restart interrupt handler
 #
 ENTRY(psw_restart_int_handler)
-	st	%r15,__LC_SAVE_AREA_64(%r0)	# save r15
+	st	%r15,__LC_SAVE_AREA+48(%r0)	# save r15
 	basr	%r15,0
 0:	l	%r15,.Lrestart_stack-0b(%r15)	# load restart stack
 	l	%r15,0(%r15)
 	ahi	%r15,-SP_SIZE			# make room for pt_regs
 	stm	%r0,%r14,SP_R0(%r15)		# store gprs %r0-%r14 to stack
-	mvc	SP_R15(4,%r15),__LC_SAVE_AREA_64(%r0)# store saved %r15 to stack
+	mvc	SP_R15(4,%r15),__LC_SAVE_AREA+48(%r0)# store saved %r15 to stack
 	mvc	SP_PSW(8,%r15),__LC_RST_OLD_PSW(%r0) # store restart old psw
 	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # set backchain to 0
 	basr	%r14,0
@@ -965,9 +947,11 @@
 	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
 	st	%r15,12(%r12)
 	CREATE_STACK_FRAME __LC_SAVE_AREA
-	mvc	SP_PSW(8,%r15),__LC_SVC_OLD_PSW
-	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
 	mvc	0(4,%r12),__LC_THREAD_INFO
+	l	%r12,__LC_THREAD_INFO
+	mvc	SP_PSW(8,%r15),__LC_SVC_OLD_PSW
+	mvc	SP_SVC_CODE(4,%r15),__LC_SVC_ILC
+	oi	__TI_flags+3(%r12),_TIF_SYSCALL
 cleanup_vtime:
 	clc	__LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12)
 	bhe	BASED(cleanup_stime)
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/head31.S linux-libre-3.2-gnu/arch/s390/kernel/head31.S
--- linux-libre-3.1-gnu/arch/s390/kernel/head31.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/head31.S	2012-01-04 18:55:44.000000000 -0500
@@ -92,7 +92,7 @@
 .LPG3:
 # check control registers
 	stctl	%c0,%c15,0(%r15)
-	oi	2(%r15),0x40		# enable sigp emergency signal
+	oi	2(%r15),0x60		# enable sigp emergency & external call
 	oi	0(%r15),0x10		# switch on low address protection
 	lctl	%c0,%c15,0(%r15)
 
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/head64.S linux-libre-3.2-gnu/arch/s390/kernel/head64.S
--- linux-libre-3.1-gnu/arch/s390/kernel/head64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/head64.S	2012-01-04 18:55:44.000000000 -0500
@@ -90,7 +90,7 @@
 .LPG3:
 # check control registers
 	stctg	%c0,%c15,0(%r15)
-	oi	6(%r15),0x40		# enable sigp emergency signal
+	oi	6(%r15),0x60		# enable sigp emergency & external call
 	oi	4(%r15),0x10		# switch on low address proctection
 	lctlg	%c0,%c15,0(%r15)
 
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/head_kdump.S linux-libre-3.2-gnu/arch/s390/kernel/head_kdump.S
--- linux-libre-3.1-gnu/arch/s390/kernel/head_kdump.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/s390/kernel/head_kdump.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,119 @@
+/*
+ * S390 kdump lowlevel functions (new kernel)
+ *
+ * Copyright IBM Corp. 2011
+ * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
+ */
+
+#define DATAMOVER_ADDR	0x4000
+#define COPY_PAGE_ADDR	0x6000
+
+#ifdef CONFIG_CRASH_DUMP
+
+#
+# kdump entry (new kernel - not yet relocated)
+#
+# Note: This code has to be position independent
+#
+
+.align 2
+.Lep_startup_kdump:
+	lhi	%r1,2				# mode 2 = esame (dump)
+	sigp	%r1,%r0,0x12			# Switch to esame mode
+	sam64					# Switch to 64 bit addressing
+	basr	%r13,0
+.Lbase:
+	larl	%r2,.Lbase_addr			# Check, if we have been
+	lg	%r2,0(%r2)			# already relocated:
+	clgr	%r2,%r13			#
+	jne	.Lrelocate			# No : Start data mover
+	lghi	%r2,0				# Yes: Start kdump kernel
+	brasl	%r14,startup_kdump_relocated
+
+.Lrelocate:
+	larl	%r4,startup
+	lg	%r2,0x418(%r4)			# Get kdump base
+	lg	%r3,0x420(%r4)			# Get kdump size
+
+	larl	%r10,.Lcopy_start		# Source of data mover
+	lghi	%r8,DATAMOVER_ADDR		# Target of data mover
+	mvc	0(256,%r8),0(%r10)		# Copy data mover code
+
+	agr	%r8,%r2				# Copy data mover to
+	mvc	0(256,%r8),0(%r10)		# reserved mem
+
+	lghi	%r14,DATAMOVER_ADDR		# Jump to copied data mover
+	basr	%r14,%r14
+.Lbase_addr:
+	.quad	.Lbase
+
+#
+# kdump data mover code (runs at address DATAMOVER_ADDR)
+#
+# r2: kdump base address
+# r3: kdump size
+#
+.Lcopy_start:
+	basr	%r13,0				# Base
+0:
+	lgr	%r11,%r2			# Save kdump base address
+	lgr	%r12,%r2
+	agr	%r12,%r3			# Compute kdump end address
+
+	lghi	%r5,0
+	lghi	%r10,COPY_PAGE_ADDR		# Load copy page address
+1:
+	mvc	0(256,%r10),0(%r5)		# Copy old kernel to tmp
+	mvc	0(256,%r5),0(%r11)		# Copy new kernel to old
+	mvc	0(256,%r11),0(%r10)		# Copy tmp to new
+	aghi	%r11,256
+	aghi	%r5,256
+	clgr	%r11,%r12
+	jl	1b
+
+	lg	%r14,.Lstartup_kdump-0b(%r13)
+	basr	%r14,%r14			# Start relocated kernel
+.Lstartup_kdump:
+	.long	0x00000000,0x00000000 + startup_kdump_relocated
+.Lcopy_end:
+
+#
+# Startup of kdump (relocated new kernel)
+#
+.align 2
+startup_kdump_relocated:
+	basr	%r13,0
+0:
+	mvc	0(8,%r0),.Lrestart_psw-0b(%r13)	# Setup restart PSW
+	mvc	464(16,%r0),.Lpgm_psw-0b(%r13)	# Setup pgm check PSW
+	lhi	%r1,1				# Start new kernel
+	diag	%r1,%r1,0x308			# with diag 308
+
+.Lno_diag308:					# No diag 308
+	sam31					# Switch to 31 bit addr mode
+	sr	%r1,%r1				# Erase register r1
+	sr	%r2,%r2				# Erase register r2
+	sigp	%r1,%r2,0x12			# Switch to 31 bit arch mode
+	lpsw	0				# Start new kernel...
+.align	8
+.Lrestart_psw:
+	.long	0x00080000,0x80000000 + startup
+.Lpgm_psw:
+	.quad	0x0000000180000000,0x0000000000000000 + .Lno_diag308
+#else
+.align 2
+.Lep_startup_kdump:
+#ifdef CONFIG_64BIT
+	larl	%r13,startup_kdump_crash
+	lpswe	0(%r13)
+.align 8
+startup_kdump_crash:
+	.quad	0x0002000080000000,0x0000000000000000 + startup_kdump_crash
+#else
+	basr	%r13,0
+0:	lpsw	startup_kdump_crash-0b(%r13)
+.align 8
+startup_kdump_crash:
+	.long	0x000a0000,0x00000000 + startup_kdump_crash
+#endif /* CONFIG_64BIT */
+#endif /* CONFIG_CRASH_DUMP */
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/head.S linux-libre-3.2-gnu/arch/s390/kernel/head.S
--- linux-libre-3.1-gnu/arch/s390/kernel/head.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/head.S	2012-01-04 18:55:44.000000000 -0500
@@ -449,10 +449,28 @@
 #
 	.org	0x10000
 ENTRY(startup)
+	j	.Lep_startup_normal
+	.org	0x10008
+#
+# This is a list of s390 kernel entry points. At address 0x1000f the number of
+# valid entry points is stored.
+#
+# IMPORTANT: Do not change this table, it is s390 kernel ABI!
+#
+	.ascii	"S390EP"
+	.byte	0x00,0x01
+#
+# kdump startup-code at 0x10010, running in 64 bit absolute addressing mode
+#
+	.org	0x10010
+ENTRY(startup_kdump)
+	j	.Lep_startup_kdump
+.Lep_startup_normal:
 	basr	%r13,0			# get base
 .LPG0:
 	xc	0x200(256),0x200	# partially clear lowcore
 	xc	0x300(256),0x300
+	xc	0xe00(256),0xe00
 	stck	__LC_LAST_UPDATE_CLOCK
 	spt	5f-.LPG0(%r13)
 	mvc	__LC_LAST_UPDATE_TIMER(8),5f-.LPG0(%r13)
@@ -534,6 +552,8 @@
 	.align	8
 5:	.long	0x7fffffff,0xffffffff
 
+#include "head_kdump.S"
+
 #
 # params at 10400 (setup.h)
 #
@@ -541,6 +561,8 @@
 	.long	0,0			# IPL_DEVICE
 	.long	0,0			# INITRD_START
 	.long	0,0			# INITRD_SIZE
+	.long	0,0			# OLDMEM_BASE
+	.long	0,0			# OLDMEM_SIZE
 
 	.org	COMMAND_LINE
 	.byte	"root=/dev/ram0 ro"
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/ipl.c linux-libre-3.2-gnu/arch/s390/kernel/ipl.c
--- linux-libre-3.1-gnu/arch/s390/kernel/ipl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/ipl.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/ctype.h>
 #include <linux/fs.h>
 #include <linux/gfp.h>
+#include <linux/crash_dump.h>
 #include <asm/ipl.h>
 #include <asm/smp.h>
 #include <asm/setup.h>
@@ -26,6 +27,7 @@
 #include <asm/sclp.h>
 #include <asm/sigp.h>
 #include <asm/checksum.h>
+#include "entry.h"
 
 #define IPL_PARM_BLOCK_VERSION 0
 
@@ -275,8 +277,8 @@
 static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
 
 /* VM IPL PARM routines */
-size_t reipl_get_ascii_vmparm(char *dest, size_t size,
-				   const struct ipl_parameter_block *ipb)
+static size_t reipl_get_ascii_vmparm(char *dest, size_t size,
+				     const struct ipl_parameter_block *ipb)
 {
 	int i;
 	size_t len;
@@ -338,8 +340,8 @@
 	return count;
 }
 
-size_t reipl_append_ascii_scpdata(char *dest, size_t size,
-				  const struct ipl_parameter_block *ipb)
+static size_t reipl_append_ascii_scpdata(char *dest, size_t size,
+					 const struct ipl_parameter_block *ipb)
 {
 	size_t count;
 	size_t i;
@@ -1738,7 +1740,11 @@
 
 void do_restart(void)
 {
+	smp_restart_with_online_cpu();
 	smp_send_stop();
+#ifdef CONFIG_CRASH_DUMP
+	crash_kexec(NULL);
+#endif
 	on_restart_trigger.action->fn(&on_restart_trigger);
 	stop_run(&on_restart_trigger);
 }
@@ -2009,7 +2015,7 @@
 
 u32 dump_prefix_page;
 
-void s390_reset_system(void)
+void s390_reset_system(void (*func)(void *), void *data)
 {
 	struct _lowcore *lc;
 
@@ -2028,15 +2034,19 @@
 	__ctl_clear_bit(0,28);
 
 	/* Set new machine check handler */
-	S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
+	S390_lowcore.mcck_new_psw.mask = psw_kernel_bits | PSW_MASK_DAT;
 	S390_lowcore.mcck_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
 
 	/* Set new program check handler */
-	S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
+	S390_lowcore.program_new_psw.mask = psw_kernel_bits | PSW_MASK_DAT;
 	S390_lowcore.program_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
 
+	/* Store status at absolute zero */
+	store_status();
+
 	do_reset_calls();
+	if (func)
+		func(data);
 }
-
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/irq.c linux-libre-3.2-gnu/arch/s390/kernel/irq.c
--- linux-libre-3.1-gnu/arch/s390/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,8 @@
 	{.name = "EXT" },
 	{.name = "I/O" },
 	{.name = "CLK", .desc = "[EXT] Clock Comparator" },
-	{.name = "IPI", .desc = "[EXT] Signal Processor" },
+	{.name = "EXC", .desc = "[EXT] External Call" },
+	{.name = "EMS", .desc = "[EXT] Emergency Signal" },
 	{.name = "TMR", .desc = "[EXT] CPU Timer" },
 	{.name = "TAL", .desc = "[EXT] Timing Alert" },
 	{.name = "PFL", .desc = "[EXT] Pseudo Page Fault" },
@@ -42,8 +43,8 @@
 	{.name = "SCP", .desc = "[EXT] Service Call" },
 	{.name = "IUC", .desc = "[EXT] IUCV" },
 	{.name = "CPM", .desc = "[EXT] CPU Measurement" },
+	{.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt" },
 	{.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt" },
-	{.name = "QDI", .desc = "[I/O] QDIO Interrupt" },
 	{.name = "DAS", .desc = "[I/O] DASD" },
 	{.name = "C15", .desc = "[I/O] 3215" },
 	{.name = "C70", .desc = "[I/O] 3270" },
@@ -53,6 +54,7 @@
 	{.name = "CLW", .desc = "[I/O] CLAW" },
 	{.name = "CTC", .desc = "[I/O] CTC" },
 	{.name = "APB", .desc = "[I/O] AP Bus" },
+	{.name = "CSC", .desc = "[I/O] CHSC Subchannel" },
 	{.name = "NMI", .desc = "[NMI] Machine Check" },
 };
 
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/jump_label.c linux-libre-3.2-gnu/arch/s390/kernel/jump_label.c
--- linux-libre-3.1-gnu/arch/s390/kernel/jump_label.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/jump_label.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,26 +18,15 @@
 } __packed;
 
 struct insn_args {
-	unsigned long *target;
-	struct insn *insn;
-	ssize_t size;
+	struct jump_entry *entry;
+	enum jump_label_type type;
 };
 
-static int __arch_jump_label_transform(void *data)
-{
-	struct insn_args *args = data;
-	int rc;
-
-	rc = probe_kernel_write(args->target, args->insn, args->size);
-	WARN_ON_ONCE(rc < 0);
-	return 0;
-}
-
-void arch_jump_label_transform(struct jump_entry *entry,
-			       enum jump_label_type type)
+static void __jump_label_transform(struct jump_entry *entry,
+				   enum jump_label_type type)
 {
-	struct insn_args args;
 	struct insn insn;
+	int rc;
 
 	if (type == JUMP_LABEL_ENABLE) {
 		/* brcl 15,offset */
@@ -49,11 +38,33 @@
 		insn.offset = 0;
 	}
 
-	args.target = (void *) entry->code;
-	args.insn = &insn;
-	args.size = JUMP_LABEL_NOP_SIZE;
+	rc = probe_kernel_write((void *)entry->code, &insn, JUMP_LABEL_NOP_SIZE);
+	WARN_ON_ONCE(rc < 0);
+}
 
-	stop_machine(__arch_jump_label_transform, &args, NULL);
+static int __sm_arch_jump_label_transform(void *data)
+{
+	struct insn_args *args = data;
+
+	__jump_label_transform(args->entry, args->type);
+	return 0;
+}
+
+void arch_jump_label_transform(struct jump_entry *entry,
+			       enum jump_label_type type)
+{
+	struct insn_args args;
+
+	args.entry = entry;
+	args.type = type;
+
+	stop_machine(__sm_arch_jump_label_transform, &args, NULL);
+}
+
+void arch_jump_label_transform_static(struct jump_entry *entry,
+				      enum jump_label_type type)
+{
+	__jump_label_transform(entry, type);
 }
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/kprobes.c linux-libre-3.2-gnu/arch/s390/kernel/kprobes.c
--- linux-libre-3.1-gnu/arch/s390/kernel/kprobes.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/kprobes.c	2012-01-04 18:55:44.000000000 -0500
@@ -635,7 +635,7 @@
 	asm volatile(".word 0x0002");
 }
 
-void __kprobes jprobe_return_end(void)
+static void __used __kprobes jprobe_return_end(void)
 {
 	asm volatile("bcr 0,0");
 }
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/machine_kexec.c linux-libre-3.2-gnu/arch/s390/kernel/machine_kexec.c
--- linux-libre-3.1-gnu/arch/s390/kernel/machine_kexec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/machine_kexec.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,10 +1,11 @@
 /*
  * arch/s390/kernel/machine_kexec.c
  *
- * Copyright IBM Corp. 2005,2006
+ * Copyright IBM Corp. 2005,2011
  *
  * Author(s): Rolf Adelsberger,
  *	      Heiko Carstens <heiko.carstens@de.ibm.com>
+ *	      Michael Holzheu <holzheu@linux.vnet.ibm.com>
  */
 
 #include <linux/device.h>
@@ -21,12 +22,162 @@
 #include <asm/smp.h>
 #include <asm/reset.h>
 #include <asm/ipl.h>
+#include <asm/diag.h>
+#include <asm/asm-offsets.h>
 
 typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long);
 
 extern const unsigned char relocate_kernel[];
 extern const unsigned long long relocate_kernel_len;
 
+#ifdef CONFIG_CRASH_DUMP
+
+void *fill_cpu_elf_notes(void *ptr, struct save_area *sa);
+
+/*
+ * Create ELF notes for one CPU
+ */
+static void add_elf_notes(int cpu)
+{
+	struct save_area *sa = (void *) 4608 + store_prefix();
+	void *ptr;
+
+	memcpy((void *) (4608UL + sa->pref_reg), sa, sizeof(*sa));
+	ptr = (u64 *) per_cpu_ptr(crash_notes, cpu);
+	ptr = fill_cpu_elf_notes(ptr, sa);
+	memset(ptr, 0, sizeof(struct elf_note));
+}
+
+/*
+ * Store status of next available physical CPU
+ */
+static int store_status_next(int start_cpu, int this_cpu)
+{
+	struct save_area *sa = (void *) 4608 + store_prefix();
+	int cpu, rc;
+
+	for (cpu = start_cpu; cpu < 65536; cpu++) {
+		if (cpu == this_cpu)
+			continue;
+		do {
+			rc = raw_sigp(cpu, sigp_stop_and_store_status);
+		} while (rc == sigp_busy);
+		if (rc != sigp_order_code_accepted)
+			continue;
+		if (sa->pref_reg)
+			return cpu;
+	}
+	return -1;
+}
+
+/*
+ * Initialize CPU ELF notes
+ */
+void setup_regs(void)
+{
+	unsigned long sa = S390_lowcore.prefixreg_save_area + SAVE_AREA_BASE;
+	int cpu, this_cpu, phys_cpu = 0, first = 1;
+
+	this_cpu = stap();
+
+	if (!S390_lowcore.prefixreg_save_area)
+		first = 0;
+	for_each_online_cpu(cpu) {
+		if (first) {
+			add_elf_notes(cpu);
+			first = 0;
+			continue;
+		}
+		phys_cpu = store_status_next(phys_cpu, this_cpu);
+		if (phys_cpu == -1)
+			break;
+		add_elf_notes(cpu);
+		phys_cpu++;
+	}
+	/* Copy dump CPU store status info to absolute zero */
+	memcpy((void *) SAVE_AREA_BASE, (void *) sa, sizeof(struct save_area));
+}
+
+#endif
+
+/*
+ * Start kdump: We expect here that a store status has been done on our CPU
+ */
+static void __do_machine_kdump(void *image)
+{
+#ifdef CONFIG_CRASH_DUMP
+	int (*start_kdump)(int) = (void *)((struct kimage *) image)->start;
+
+	__load_psw_mask(PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA);
+	setup_regs();
+	start_kdump(1);
+#endif
+}
+
+/*
+ * Check if kdump checksums are valid: We call purgatory with parameter "0"
+ */
+static int kdump_csum_valid(struct kimage *image)
+{
+#ifdef CONFIG_CRASH_DUMP
+	int (*start_kdump)(int) = (void *)image->start;
+	int rc;
+
+	__arch_local_irq_stnsm(0xfb); /* disable DAT */
+	rc = start_kdump(0);
+	__arch_local_irq_stosm(0x04); /* enable DAT */
+	return rc ? 0 : -EINVAL;
+#else
+	return -EINVAL;
+#endif
+}
+
+/*
+ * Map or unmap crashkernel memory
+ */
+static void crash_map_pages(int enable)
+{
+	unsigned long size = resource_size(&crashk_res);
+
+	BUG_ON(crashk_res.start % KEXEC_CRASH_MEM_ALIGN ||
+	       size % KEXEC_CRASH_MEM_ALIGN);
+	if (enable)
+		vmem_add_mapping(crashk_res.start, size);
+	else
+		vmem_remove_mapping(crashk_res.start, size);
+}
+
+/*
+ * Map crashkernel memory
+ */
+void crash_map_reserved_pages(void)
+{
+	crash_map_pages(1);
+}
+
+/*
+ * Unmap crashkernel memory
+ */
+void crash_unmap_reserved_pages(void)
+{
+	crash_map_pages(0);
+}
+
+/*
+ * Give back memory to hypervisor before new kdump is loaded
+ */
+static int machine_kexec_prepare_kdump(void)
+{
+#ifdef CONFIG_CRASH_DUMP
+	if (MACHINE_IS_VM)
+		diag10_range(PFN_DOWN(crashk_res.start),
+			     PFN_DOWN(crashk_res.end - crashk_res.start + 1));
+	return 0;
+#else
+	return -EINVAL;
+#endif
+}
+
 int machine_kexec_prepare(struct kimage *image)
 {
 	void *reboot_code_buffer;
@@ -35,6 +186,9 @@
 	if (ipl_flags & IPL_NSS_VALID)
 		return -ENOSYS;
 
+	if (image->type == KEXEC_TYPE_CRASH)
+		return machine_kexec_prepare_kdump();
+
 	/* We don't support anything but the default image type for now. */
 	if (image->type != KEXEC_TYPE_DEFAULT)
 		return -EINVAL;
@@ -51,27 +205,53 @@
 {
 }
 
+void arch_crash_save_vmcoreinfo(void)
+{
+	VMCOREINFO_SYMBOL(lowcore_ptr);
+	VMCOREINFO_LENGTH(lowcore_ptr, NR_CPUS);
+}
+
 void machine_shutdown(void)
 {
 }
 
-static void __machine_kexec(void *data)
+/*
+ * Do normal kexec
+ */
+static void __do_machine_kexec(void *data)
 {
 	relocate_kernel_t data_mover;
 	struct kimage *image = data;
 
-	pfault_fini();
-	s390_reset_system();
-
 	data_mover = (relocate_kernel_t) page_to_phys(image->control_code_page);
 
 	/* Call the moving routine */
 	(*data_mover)(&image->head, image->start);
-	for (;;);
 }
 
+/*
+ * Reset system and call either kdump or normal kexec
+ */
+static void __machine_kexec(void *data)
+{
+	struct kimage *image = data;
+
+	pfault_fini();
+	if (image->type == KEXEC_TYPE_CRASH)
+		s390_reset_system(__do_machine_kdump, data);
+	else
+		s390_reset_system(__do_machine_kexec, data);
+	disabled_wait((unsigned long) __builtin_return_address(0));
+}
+
+/*
+ * Do either kdump or normal kexec. In case of kdump we first ask
+ * purgatory, if kdump checksums are valid.
+ */
 void machine_kexec(struct kimage *image)
 {
+	if (image->type == KEXEC_TYPE_CRASH && !kdump_csum_valid(image))
+		return;
 	tracer_disable();
 	smp_send_stop();
 	smp_switch_to_ipl_cpu(__machine_kexec, image);
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/Makefile linux-libre-3.2-gnu/arch/s390/kernel/Makefile
--- linux-libre-3.1-gnu/arch/s390/kernel/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -48,6 +48,7 @@
 obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
 obj-$(CONFIG_FTRACE_SYSCALLS)  += ftrace.o
+obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
 
 # Kexec part
 S390_KEXEC_OBJS := machine_kexec.o crash.o
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/mem_detect.c linux-libre-3.2-gnu/arch/s390/kernel/mem_detect.c
--- linux-libre-3.1-gnu/arch/s390/kernel/mem_detect.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/mem_detect.c	2012-01-04 18:55:44.000000000 -0500
@@ -62,3 +62,72 @@
 	arch_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(detect_memory_layout);
+
+/*
+ * Create memory hole with given address, size, and type
+ */
+void create_mem_hole(struct mem_chunk chunks[], unsigned long addr,
+		     unsigned long size, int type)
+{
+	unsigned long start, end, new_size;
+	int i;
+
+	for (i = 0; i < MEMORY_CHUNKS; i++) {
+		if (chunks[i].size == 0)
+			continue;
+		if (addr + size < chunks[i].addr)
+			continue;
+		if (addr >= chunks[i].addr + chunks[i].size)
+			continue;
+		start = max(addr, chunks[i].addr);
+		end = min(addr + size, chunks[i].addr + chunks[i].size);
+		new_size = end - start;
+		if (new_size == 0)
+			continue;
+		if (start == chunks[i].addr &&
+		    end == chunks[i].addr + chunks[i].size) {
+			/* Remove chunk */
+			chunks[i].type = type;
+		} else if (start == chunks[i].addr) {
+			/* Make chunk smaller at start */
+			if (i >= MEMORY_CHUNKS - 1)
+				panic("Unable to create memory hole");
+			memmove(&chunks[i + 1], &chunks[i],
+				sizeof(struct mem_chunk) *
+				(MEMORY_CHUNKS - (i + 1)));
+			chunks[i + 1].addr = chunks[i].addr + new_size;
+			chunks[i + 1].size = chunks[i].size - new_size;
+			chunks[i].size = new_size;
+			chunks[i].type = type;
+			i += 1;
+		} else if (end == chunks[i].addr + chunks[i].size) {
+			/* Make chunk smaller at end */
+			if (i >= MEMORY_CHUNKS - 1)
+				panic("Unable to create memory hole");
+			memmove(&chunks[i + 1], &chunks[i],
+				sizeof(struct mem_chunk) *
+				(MEMORY_CHUNKS - (i + 1)));
+			chunks[i + 1].addr = start;
+			chunks[i + 1].size = new_size;
+			chunks[i + 1].type = type;
+			chunks[i].size -= new_size;
+			i += 1;
+		} else {
+			/* Create memory hole */
+			if (i >= MEMORY_CHUNKS - 2)
+				panic("Unable to create memory hole");
+			memmove(&chunks[i + 2], &chunks[i],
+				sizeof(struct mem_chunk) *
+				(MEMORY_CHUNKS - (i + 2)));
+			chunks[i + 1].addr = addr;
+			chunks[i + 1].size = size;
+			chunks[i + 1].type = type;
+			chunks[i + 2].addr = addr + size;
+			chunks[i + 2].size =
+				chunks[i].addr + chunks[i].size - (addr + size);
+			chunks[i + 2].type = chunks[i].type;
+			chunks[i].size = addr - chunks[i].addr;
+			i += 2;
+		}
+	}
+}
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/process.c linux-libre-3.2-gnu/arch/s390/kernel/process.c
--- linux-libre-3.1-gnu/arch/s390/kernel/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/elfcore.h>
 #include <linux/smp.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
@@ -117,7 +118,8 @@
 	struct pt_regs regs;
 
 	memset(&regs, 0, sizeof(regs));
-	regs.psw.mask = psw_kernel_bits | PSW_MASK_IO | PSW_MASK_EXT;
+	regs.psw.mask = psw_kernel_bits |
+		PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
 	regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE;
 	regs.gprs[9] = (unsigned long) fn;
 	regs.gprs[10] = (unsigned long) arg;
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/processor.c linux-libre-3.2-gnu/arch/s390/kernel/processor.c
--- linux-libre-3.1-gnu/arch/s390/kernel/processor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/processor.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,7 +74,7 @@
 
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
-	return *pos < NR_CPUS ? (void *)((unsigned long) *pos + 1) : NULL;
+	return *pos < nr_cpu_ids ? (void *)((unsigned long) *pos + 1) : NULL;
 }
 
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/ptrace.c linux-libre-3.2-gnu/arch/s390/kernel/ptrace.c
--- linux-libre-3.1-gnu/arch/s390/kernel/ptrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/ptrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,34 +42,37 @@
 	REGSET_GENERAL,
 	REGSET_FP,
 	REGSET_LAST_BREAK,
+	REGSET_SYSTEM_CALL,
 	REGSET_GENERAL_EXTENDED,
 };
 
 void update_per_regs(struct task_struct *task)
 {
-	static const struct per_regs per_single_step = {
-		.control = PER_EVENT_IFETCH,
-		.start = 0,
-		.end = PSW_ADDR_INSN,
-	};
 	struct pt_regs *regs = task_pt_regs(task);
 	struct thread_struct *thread = &task->thread;
-	const struct per_regs *new;
-	struct per_regs old;
+	struct per_regs old, new;
 
-	/* TIF_SINGLE_STEP overrides the user specified PER registers. */
-	new = test_tsk_thread_flag(task, TIF_SINGLE_STEP) ?
-		&per_single_step : &thread->per_user;
+	/* Copy user specified PER registers */
+	new.control = thread->per_user.control;
+	new.start = thread->per_user.start;
+	new.end = thread->per_user.end;
+
+	/* merge TIF_SINGLE_STEP into user specified PER registers. */
+	if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) {
+		new.control |= PER_EVENT_IFETCH;
+		new.start = 0;
+		new.end = PSW_ADDR_INSN;
+	}
 
 	/* Take care of the PER enablement bit in the PSW. */
-	if (!(new->control & PER_EVENT_MASK)) {
+	if (!(new.control & PER_EVENT_MASK)) {
 		regs->psw.mask &= ~PSW_MASK_PER;
 		return;
 	}
 	regs->psw.mask |= PSW_MASK_PER;
 	__ctl_store(old, 9, 11);
-	if (memcmp(new, &old, sizeof(struct per_regs)) != 0)
-		__ctl_load(*new, 9, 11);
+	if (memcmp(&new, &old, sizeof(struct per_regs)) != 0)
+		__ctl_load(new, 9, 11);
 }
 
 void user_enable_single_step(struct task_struct *task)
@@ -166,8 +169,8 @@
 		 */
 		tmp = *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr);
 		if (addr == (addr_t) &dummy->regs.psw.mask)
-			/* Remove per bit from user psw. */
-			tmp &= ~PSW_MASK_PER;
+			/* Return a clean psw mask. */
+			tmp = psw_user_bits | (tmp & PSW_MASK_USER);
 
 	} else if (addr < (addr_t) &dummy->regs.orig_gpr2) {
 		/*
@@ -289,18 +292,10 @@
 		 * psw and gprs are stored on the stack
 		 */
 		if (addr == (addr_t) &dummy->regs.psw.mask &&
-#ifdef CONFIG_COMPAT
-		    data != PSW_MASK_MERGE(psw_user32_bits, data) &&
-#endif
-		    data != PSW_MASK_MERGE(psw_user_bits, data))
+		    ((data & ~PSW_MASK_USER) != psw_user_bits ||
+		     ((data & PSW_MASK_EA) && !(data & PSW_MASK_BA))))
 			/* Invalid psw mask. */
 			return -EINVAL;
-#ifndef CONFIG_64BIT
-		if (addr == (addr_t) &dummy->regs.psw.addr)
-			/* I'd like to reject addresses without the
-			   high order bit but older gdb's rely on it */
-			data |= PSW_ADDR_AMODE;
-#endif
 		*(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data;
 
 	} else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) {
@@ -495,21 +490,21 @@
 	__u32 tmp;
 
 	if (addr < (addr_t) &dummy32->regs.acrs) {
+		struct pt_regs *regs = task_pt_regs(child);
 		/*
 		 * psw and gprs are stored on the stack
 		 */
 		if (addr == (addr_t) &dummy32->regs.psw.mask) {
 			/* Fake a 31 bit psw mask. */
-			tmp = (__u32)(task_pt_regs(child)->psw.mask >> 32);
-			tmp = PSW32_MASK_MERGE(psw32_user_bits, tmp);
+			tmp = (__u32)(regs->psw.mask >> 32);
+			tmp = psw32_user_bits | (tmp & PSW32_MASK_USER);
 		} else if (addr == (addr_t) &dummy32->regs.psw.addr) {
 			/* Fake a 31 bit psw address. */
-			tmp = (__u32) task_pt_regs(child)->psw.addr |
-				PSW32_ADDR_AMODE31;
+			tmp = (__u32) regs->psw.addr |
+				(__u32)(regs->psw.mask & PSW_MASK_BA);
 		} else {
 			/* gpr 0-15 */
-			tmp = *(__u32 *)((addr_t) &task_pt_regs(child)->psw +
-					 addr*2 + 4);
+			tmp = *(__u32 *)((addr_t) &regs->psw + addr*2 + 4);
 		}
 	} else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) {
 		/*
@@ -594,24 +589,27 @@
 	addr_t offset;
 
 	if (addr < (addr_t) &dummy32->regs.acrs) {
+		struct pt_regs *regs = task_pt_regs(child);
 		/*
 		 * psw, gprs, acrs and orig_gpr2 are stored on the stack
 		 */
 		if (addr == (addr_t) &dummy32->regs.psw.mask) {
 			/* Build a 64 bit psw mask from 31 bit mask. */
-			if (tmp != PSW32_MASK_MERGE(psw32_user_bits, tmp))
+			if ((tmp & ~PSW32_MASK_USER) != psw32_user_bits)
 				/* Invalid psw mask. */
 				return -EINVAL;
-			task_pt_regs(child)->psw.mask =
-				PSW_MASK_MERGE(psw_user32_bits, (__u64) tmp << 32);
+			regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
+				(regs->psw.mask & PSW_MASK_BA) |
+				(__u64)(tmp & PSW32_MASK_USER) << 32;
 		} else if (addr == (addr_t) &dummy32->regs.psw.addr) {
 			/* Build a 64 bit psw address from 31 bit address. */
-			task_pt_regs(child)->psw.addr =
-				(__u64) tmp & PSW32_ADDR_INSN;
+			regs->psw.addr = (__u64) tmp & PSW32_ADDR_INSN;
+			/* Transfer 31 bit amode bit to psw mask. */
+			regs->psw.mask = (regs->psw.mask & ~PSW_MASK_BA) |
+				(__u64)(tmp & PSW32_ADDR_AMODE);
 		} else {
 			/* gpr 0-15 */
-			*(__u32*)((addr_t) &task_pt_regs(child)->psw
-				  + addr*2 + 4) = tmp;
+			*(__u32*)((addr_t) &regs->psw + addr*2 + 4) = tmp;
 		}
 	} else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) {
 		/*
@@ -735,7 +733,7 @@
 		 * debugger stored an invalid system call number. Skip
 		 * the system call and the system call restart handling.
 		 */
-		regs->svcnr = 0;
+		clear_thread_flag(TIF_SYSCALL);
 		ret = -1;
 	}
 
@@ -895,8 +893,36 @@
 	return 0;
 }
 
+static int s390_last_break_set(struct task_struct *target,
+			       const struct user_regset *regset,
+			       unsigned int pos, unsigned int count,
+			       const void *kbuf, const void __user *ubuf)
+{
+	return 0;
+}
+
 #endif
 
+static int s390_system_call_get(struct task_struct *target,
+				const struct user_regset *regset,
+				unsigned int pos, unsigned int count,
+				void *kbuf, void __user *ubuf)
+{
+	unsigned int *data = &task_thread_info(target)->system_call;
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				   data, 0, sizeof(unsigned int));
+}
+
+static int s390_system_call_set(struct task_struct *target,
+				const struct user_regset *regset,
+				unsigned int pos, unsigned int count,
+				const void *kbuf, const void __user *ubuf)
+{
+	unsigned int *data = &task_thread_info(target)->system_call;
+	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				  data, 0, sizeof(unsigned int));
+}
+
 static const struct user_regset s390_regsets[] = {
 	[REGSET_GENERAL] = {
 		.core_note_type = NT_PRSTATUS,
@@ -921,8 +947,17 @@
 		.size = sizeof(long),
 		.align = sizeof(long),
 		.get = s390_last_break_get,
+		.set = s390_last_break_set,
 	},
 #endif
+	[REGSET_SYSTEM_CALL] = {
+		.core_note_type = NT_S390_SYSTEM_CALL,
+		.n = 1,
+		.size = sizeof(unsigned int),
+		.align = sizeof(unsigned int),
+		.get = s390_system_call_get,
+		.set = s390_system_call_set,
+	},
 };
 
 static const struct user_regset_view user_s390_view = {
@@ -1078,6 +1113,14 @@
 	return 0;
 }
 
+static int s390_compat_last_break_set(struct task_struct *target,
+				      const struct user_regset *regset,
+				      unsigned int pos, unsigned int count,
+				      const void *kbuf, const void __user *ubuf)
+{
+	return 0;
+}
+
 static const struct user_regset s390_compat_regsets[] = {
 	[REGSET_GENERAL] = {
 		.core_note_type = NT_PRSTATUS,
@@ -1101,6 +1144,15 @@
 		.size = sizeof(long),
 		.align = sizeof(long),
 		.get = s390_compat_last_break_get,
+		.set = s390_compat_last_break_set,
+	},
+	[REGSET_SYSTEM_CALL] = {
+		.core_note_type = NT_S390_SYSTEM_CALL,
+		.n = 1,
+		.size = sizeof(compat_uint_t),
+		.align = sizeof(compat_uint_t),
+		.get = s390_system_call_get,
+		.set = s390_system_call_set,
 	},
 	[REGSET_GENERAL_EXTENDED] = {
 		.core_note_type = NT_S390_HIGH_GPRS,
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/reipl64.S linux-libre-3.2-gnu/arch/s390/kernel/reipl64.S
--- linux-libre-3.1-gnu/arch/s390/kernel/reipl64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/reipl64.S	2012-01-04 18:55:44.000000000 -0500
@@ -17,11 +17,11 @@
 #
 ENTRY(store_status)
 	/* Save register one and load save area base */
-	stg	%r1,__LC_SAVE_AREA_64(%r0)
+	stg	%r1,__LC_SAVE_AREA+120(%r0)
 	lghi	%r1,SAVE_AREA_BASE
 	/* General purpose registers */
 	stmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
-	lg	%r2,__LC_SAVE_AREA_64(%r0)
+	lg	%r2,__LC_SAVE_AREA+120(%r0)
 	stg	%r2,__LC_GPREGS_SAVE_AREA-SAVE_AREA_BASE+8(%r1)
 	/* Control registers */
 	stctg	%c0,%c15,__LC_CREGS_SAVE_AREA-SAVE_AREA_BASE(%r1)
@@ -62,8 +62,11 @@
 	larl	%r2,store_status
 	stg	%r2,__LC_PSW_SAVE_AREA-SAVE_AREA_BASE + 8(%r1)
 	br	%r14
-.align	8
+
+	.section .bss
+	.align	8
 .Lclkcmp:	.quad	0x0000000000000000
+	.previous
 
 #
 # do_reipl_asm
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/reipl.S linux-libre-3.2-gnu/arch/s390/kernel/reipl.S
--- linux-libre-3.1-gnu/arch/s390/kernel/reipl.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/reipl.S	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,12 @@
 #include <asm/asm-offsets.h>
 
 #
+# store_status: Empty implementation until kdump is supported on 31 bit
+#
+ENTRY(store_status)
+		br	%r14
+
+#
 # do_reipl_asm
 # Parameter: r2 = schid of reipl device
 #
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/setup.c linux-libre-3.2-gnu/arch/s390/kernel/setup.c
--- linux-libre-3.1-gnu/arch/s390/kernel/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,9 @@
 #include <linux/reboot.h>
 #include <linux/topology.h>
 #include <linux/ftrace.h>
+#include <linux/kexec.h>
+#include <linux/crash_dump.h>
+#include <linux/memory.h>
 
 #include <asm/ipl.h>
 #include <asm/uaccess.h>
@@ -57,12 +60,13 @@
 #include <asm/ebcdic.h>
 #include <asm/compat.h>
 #include <asm/kvm_virtio.h>
+#include <asm/diag.h>
 
-long psw_kernel_bits	= (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY |
-			   PSW_MASK_MCHECK | PSW_DEFAULT_KEY);
-long psw_user_bits	= (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
-			   PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
-			   PSW_MASK_PSTATE | PSW_DEFAULT_KEY);
+long psw_kernel_bits	= PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_PRIMARY |
+			  PSW_MASK_EA | PSW_MASK_BA;
+long psw_user_bits	= PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT |
+			  PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_MCHECK |
+			  PSW_MASK_PSTATE | PSW_ASC_HOME;
 
 /*
  * User copy operations.
@@ -207,6 +211,8 @@
 
 	if (ipl_info.type != IPL_TYPE_FCP_DUMP)
 		return;
+	if (OLDMEM_BASE)
+		return;
 	if (console_devno != -1)
 		sprintf(str, " cio_ignore=all,!0.0.%04x,!0.0.%04x",
 			ipl_info.data.fcp.dev_id.devno, console_devno);
@@ -274,22 +280,14 @@
 unsigned int user_mode = HOME_SPACE_MODE;
 EXPORT_SYMBOL_GPL(user_mode);
 
-static int set_amode_and_uaccess(unsigned long user_amode,
-				 unsigned long user32_amode)
+static int set_amode_primary(void)
 {
-	psw_user_bits = PSW_BASE_BITS | PSW_MASK_DAT | user_amode |
-			PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
-			PSW_MASK_PSTATE | PSW_DEFAULT_KEY;
+	psw_kernel_bits = (psw_kernel_bits & ~PSW_MASK_ASC) | PSW_ASC_HOME;
+	psw_user_bits = (psw_user_bits & ~PSW_MASK_ASC) | PSW_ASC_PRIMARY;
 #ifdef CONFIG_COMPAT
-	psw_user32_bits = PSW_BASE32_BITS | PSW_MASK_DAT | user_amode |
-			  PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
-			  PSW_MASK_PSTATE | PSW_DEFAULT_KEY;
-	psw32_user_bits = PSW32_BASE_BITS | PSW32_MASK_DAT | user32_amode |
-			  PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK |
-			  PSW32_MASK_PSTATE;
+	psw32_user_bits =
+		(psw32_user_bits & ~PSW32_MASK_ASC) | PSW32_ASC_PRIMARY;
 #endif
-	psw_kernel_bits = PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
-			  PSW_MASK_MCHECK | PSW_DEFAULT_KEY;
 
 	if (MACHINE_HAS_MVCOS) {
 		memcpy(&uaccess, &uaccess_mvcos_switch, sizeof(uaccess));
@@ -325,7 +323,7 @@
 static void setup_addressing_mode(void)
 {
 	if (user_mode == PRIMARY_SPACE_MODE) {
-		if (set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY))
+		if (set_amode_primary())
 			pr_info("Address spaces switched, "
 				"mvcos available\n");
 		else
@@ -344,24 +342,25 @@
 	 */
 	BUILD_BUG_ON(sizeof(struct _lowcore) != LC_PAGES * 4096);
 	lc = __alloc_bootmem_low(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0);
-	lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+	lc->restart_psw.mask = psw_kernel_bits;
 	lc->restart_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
-	if (user_mode != HOME_SPACE_MODE)
-		lc->restart_psw.mask |= PSW_ASC_HOME;
-	lc->external_new_psw.mask = psw_kernel_bits;
+	lc->external_new_psw.mask = psw_kernel_bits |
+		PSW_MASK_DAT | PSW_MASK_MCHECK;
 	lc->external_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) ext_int_handler;
-	lc->svc_new_psw.mask = psw_kernel_bits | PSW_MASK_IO | PSW_MASK_EXT;
+	lc->svc_new_psw.mask = psw_kernel_bits |
+		PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
 	lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call;
-	lc->program_new_psw.mask = psw_kernel_bits;
+	lc->program_new_psw.mask = psw_kernel_bits |
+		PSW_MASK_DAT | PSW_MASK_MCHECK;
 	lc->program_new_psw.addr =
-		PSW_ADDR_AMODE | (unsigned long)pgm_check_handler;
-	lc->mcck_new_psw.mask =
-		psw_kernel_bits & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT;
+		PSW_ADDR_AMODE | (unsigned long) pgm_check_handler;
+	lc->mcck_new_psw.mask = psw_kernel_bits;
 	lc->mcck_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
-	lc->io_new_psw.mask = psw_kernel_bits;
+	lc->io_new_psw.mask = psw_kernel_bits |
+		PSW_MASK_DAT | PSW_MASK_MCHECK;
 	lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
 	lc->clock_comparator = -1ULL;
 	lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
@@ -435,10 +434,14 @@
 	for (i = 0; i < MEMORY_CHUNKS; i++) {
 		if (!memory_chunk[i].size)
 			continue;
+		if (memory_chunk[i].type == CHUNK_OLDMEM ||
+		    memory_chunk[i].type == CHUNK_CRASHK)
+			continue;
 		res = alloc_bootmem_low(sizeof(*res));
 		res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
 		switch (memory_chunk[i].type) {
 		case CHUNK_READ_WRITE:
+		case CHUNK_CRASHK:
 			res->name = "System RAM";
 			break;
 		case CHUNK_READ_ONLY:
@@ -479,8 +482,9 @@
 	unsigned long max_mem;
 	int i;
 
+
 #ifdef CONFIG_ZFCPDUMP
-	if (ipl_info.type == IPL_TYPE_FCP_DUMP) {
+	if (ipl_info.type == IPL_TYPE_FCP_DUMP && !OLDMEM_BASE) {
 		memory_end = ZFCPDUMP_HSA_SIZE;
 		memory_end_set = 1;
 	}
@@ -545,11 +549,201 @@
 	 * Setup restart PSW for absolute zero lowcore. This is necesary
 	 * if PSW restart is done on an offline CPU that has lowcore zero
 	 */
-	psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+	psw.mask = PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
 	psw.addr = PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
 	copy_to_absolute_zero(&S390_lowcore.restart_psw, &psw, sizeof(psw));
 }
 
+static void __init setup_vmcoreinfo(void)
+{
+#ifdef CONFIG_KEXEC
+	unsigned long ptr = paddr_vmcoreinfo_note();
+
+	copy_to_absolute_zero(&S390_lowcore.vmcore_info, &ptr, sizeof(ptr));
+#endif
+}
+
+#ifdef CONFIG_CRASH_DUMP
+
+/*
+ * Find suitable location for crashkernel memory
+ */
+static unsigned long __init find_crash_base(unsigned long crash_size,
+					    char **msg)
+{
+	unsigned long crash_base;
+	struct mem_chunk *chunk;
+	int i;
+
+	if (memory_chunk[0].size < crash_size) {
+		*msg = "first memory chunk must be at least crashkernel size";
+		return 0;
+	}
+	if (OLDMEM_BASE && crash_size == OLDMEM_SIZE)
+		return OLDMEM_BASE;
+
+	for (i = MEMORY_CHUNKS - 1; i >= 0; i--) {
+		chunk = &memory_chunk[i];
+		if (chunk->size == 0)
+			continue;
+		if (chunk->type != CHUNK_READ_WRITE)
+			continue;
+		if (chunk->size < crash_size)
+			continue;
+		crash_base = (chunk->addr + chunk->size) - crash_size;
+		if (crash_base < crash_size)
+			continue;
+		if (crash_base < ZFCPDUMP_HSA_SIZE_MAX)
+			continue;
+		if (crash_base < (unsigned long) INITRD_START + INITRD_SIZE)
+			continue;
+		return crash_base;
+	}
+	*msg = "no suitable area found";
+	return 0;
+}
+
+/*
+ * Check if crash_base and crash_size is valid
+ */
+static int __init verify_crash_base(unsigned long crash_base,
+				    unsigned long crash_size,
+				    char **msg)
+{
+	struct mem_chunk *chunk;
+	int i;
+
+	/*
+	 * Because we do the swap to zero, we must have at least 'crash_size'
+	 * bytes free space before crash_base
+	 */
+	if (crash_size > crash_base) {
+		*msg = "crashkernel offset must be greater than size";
+		return -EINVAL;
+	}
+
+	/* First memory chunk must be at least crash_size */
+	if (memory_chunk[0].size < crash_size) {
+		*msg = "first memory chunk must be at least crashkernel size";
+		return -EINVAL;
+	}
+	/* Check if we fit into the respective memory chunk */
+	for (i = 0; i < MEMORY_CHUNKS; i++) {
+		chunk = &memory_chunk[i];
+		if (chunk->size == 0)
+			continue;
+		if (crash_base < chunk->addr)
+			continue;
+		if (crash_base >= chunk->addr + chunk->size)
+			continue;
+		/* we have found the memory chunk */
+		if (crash_base + crash_size > chunk->addr + chunk->size) {
+			*msg = "selected memory chunk is too small for "
+				"crashkernel memory";
+			return -EINVAL;
+		}
+		return 0;
+	}
+	*msg = "invalid memory range specified";
+	return -EINVAL;
+}
+
+/*
+ * Reserve kdump memory by creating a memory hole in the mem_chunk array
+ */
+static void __init reserve_kdump_bootmem(unsigned long addr, unsigned long size,
+					 int type)
+{
+
+	create_mem_hole(memory_chunk, addr, size, type);
+}
+
+/*
+ * When kdump is enabled, we have to ensure that no memory from
+ * the area [0 - crashkernel memory size] and
+ * [crashk_res.start - crashk_res.end] is set offline.
+ */
+static int kdump_mem_notifier(struct notifier_block *nb,
+			      unsigned long action, void *data)
+{
+	struct memory_notify *arg = data;
+
+	if (arg->start_pfn < PFN_DOWN(resource_size(&crashk_res)))
+		return NOTIFY_BAD;
+	if (arg->start_pfn > PFN_DOWN(crashk_res.end))
+		return NOTIFY_OK;
+	if (arg->start_pfn + arg->nr_pages - 1 < PFN_DOWN(crashk_res.start))
+		return NOTIFY_OK;
+	return NOTIFY_BAD;
+}
+
+static struct notifier_block kdump_mem_nb = {
+	.notifier_call = kdump_mem_notifier,
+};
+
+#endif
+
+/*
+ * Make sure that oldmem, where the dump is stored, is protected
+ */
+static void reserve_oldmem(void)
+{
+#ifdef CONFIG_CRASH_DUMP
+	if (!OLDMEM_BASE)
+		return;
+
+	reserve_kdump_bootmem(OLDMEM_BASE, OLDMEM_SIZE, CHUNK_OLDMEM);
+	reserve_kdump_bootmem(OLDMEM_SIZE, memory_end - OLDMEM_SIZE,
+			      CHUNK_OLDMEM);
+	if (OLDMEM_BASE + OLDMEM_SIZE == real_memory_size)
+		saved_max_pfn = PFN_DOWN(OLDMEM_BASE) - 1;
+	else
+		saved_max_pfn = PFN_DOWN(real_memory_size) - 1;
+#endif
+}
+
+/*
+ * Reserve memory for kdump kernel to be loaded with kexec
+ */
+static void __init reserve_crashkernel(void)
+{
+#ifdef CONFIG_CRASH_DUMP
+	unsigned long long crash_base, crash_size;
+	char *msg;
+	int rc;
+
+	rc = parse_crashkernel(boot_command_line, memory_end, &crash_size,
+			       &crash_base);
+	if (rc || crash_size == 0)
+		return;
+	crash_base = ALIGN(crash_base, KEXEC_CRASH_MEM_ALIGN);
+	crash_size = ALIGN(crash_size, KEXEC_CRASH_MEM_ALIGN);
+	if (register_memory_notifier(&kdump_mem_nb))
+		return;
+	if (!crash_base)
+		crash_base = find_crash_base(crash_size, &msg);
+	if (!crash_base) {
+		pr_info("crashkernel reservation failed: %s\n", msg);
+		unregister_memory_notifier(&kdump_mem_nb);
+		return;
+	}
+	if (verify_crash_base(crash_base, crash_size, &msg)) {
+		pr_info("crashkernel reservation failed: %s\n", msg);
+		unregister_memory_notifier(&kdump_mem_nb);
+		return;
+	}
+	if (!OLDMEM_BASE && MACHINE_IS_VM)
+		diag10_range(PFN_DOWN(crash_base), PFN_DOWN(crash_size));
+	crashk_res.start = crash_base;
+	crashk_res.end = crash_base + crash_size - 1;
+	insert_resource(&iomem_resource, &crashk_res);
+	reserve_kdump_bootmem(crash_base, crash_size, CHUNK_CRASHK);
+	pr_info("Reserving %lluMB of memory at %lluMB "
+		"for crashkernel (System RAM: %luMB)\n",
+		crash_size >> 20, crash_base >> 20, memory_end >> 20);
+#endif
+}
+
 static void __init
 setup_memory(void)
 {
@@ -580,6 +774,14 @@
 		if (PFN_PHYS(start_pfn) + bmap_size > INITRD_START) {
 			start = PFN_PHYS(start_pfn) + bmap_size + PAGE_SIZE;
 
+#ifdef CONFIG_CRASH_DUMP
+			if (OLDMEM_BASE) {
+				/* Move initrd behind kdump oldmem */
+				if (start + INITRD_SIZE > OLDMEM_BASE &&
+				    start < OLDMEM_BASE + OLDMEM_SIZE)
+					start = OLDMEM_BASE + OLDMEM_SIZE;
+			}
+#endif
 			if (start + INITRD_SIZE > memory_end) {
 				pr_err("initrd extends beyond end of "
 				       "memory (0x%08lx > 0x%08lx) "
@@ -610,7 +812,8 @@
 	for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
 		unsigned long start_chunk, end_chunk, pfn;
 
-		if (memory_chunk[i].type != CHUNK_READ_WRITE)
+		if (memory_chunk[i].type != CHUNK_READ_WRITE &&
+		    memory_chunk[i].type != CHUNK_CRASHK)
 			continue;
 		start_chunk = PFN_DOWN(memory_chunk[i].addr);
 		end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size);
@@ -644,6 +847,15 @@
 	reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size,
 			BOOTMEM_DEFAULT);
 
+#ifdef CONFIG_CRASH_DUMP
+	if (crashk_res.start)
+		reserve_bootmem(crashk_res.start,
+				crashk_res.end - crashk_res.start + 1,
+				BOOTMEM_DEFAULT);
+	if (is_kdump_kernel())
+		reserve_bootmem(elfcorehdr_addr - OLDMEM_BASE,
+				PAGE_ALIGN(elfcorehdr_size), BOOTMEM_DEFAULT);
+#endif
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (INITRD_START && INITRD_SIZE) {
 		if (INITRD_START + INITRD_SIZE <= memory_end) {
@@ -812,8 +1024,11 @@
 	setup_ipl();
 	setup_memory_end();
 	setup_addressing_mode();
+	reserve_oldmem();
+	reserve_crashkernel();
 	setup_memory();
 	setup_resources();
+	setup_vmcoreinfo();
 	setup_restart_psw();
 	setup_lowcore();
 
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/signal.c linux-libre-3.2-gnu/arch/s390/kernel/signal.c
--- linux-libre-3.1-gnu/arch/s390/kernel/signal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/signal.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/lowcore.h>
+#include <asm/compat.h>
 #include "entry.h"
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -116,7 +117,8 @@
 
 	/* Copy a 'clean' PSW mask to the user to avoid leaking
 	   information about whether PER is currently on.  */
-	user_sregs.regs.psw.mask = PSW_MASK_MERGE(psw_user_bits, regs->psw.mask);
+	user_sregs.regs.psw.mask = psw_user_bits |
+		(regs->psw.mask & PSW_MASK_USER);
 	user_sregs.regs.psw.addr = regs->psw.addr;
 	memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs));
 	memcpy(&user_sregs.regs.acrs, current->thread.acrs,
@@ -143,9 +145,13 @@
 	err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs));
 	if (err)
 		return err;
-	regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask,
-					user_sregs.regs.psw.mask);
-	regs->psw.addr = PSW_ADDR_AMODE | user_sregs.regs.psw.addr;
+	/* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */
+	regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
+		(user_sregs.regs.psw.mask & PSW_MASK_USER);
+	/* Check for invalid amode */
+	if (regs->psw.mask & PSW_MASK_EA)
+		regs->psw.mask |= PSW_MASK_BA;
+	regs->psw.addr = user_sregs.regs.psw.addr;
 	memcpy(&regs->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs));
 	memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
 	       sizeof(sregs->regs.acrs));
@@ -156,7 +162,7 @@
 	current->thread.fp_regs.fpc &= FPC_VALID_MASK;
 
 	restore_fp_regs(&current->thread.fp_regs);
-	regs->svcnr = 0;	/* disable syscall checks */
+	clear_thread_flag(TIF_SYSCALL);	/* No longer in a system call */
 	return 0;
 }
 
@@ -288,6 +294,7 @@
 
 	/* Set up registers for signal handler */
 	regs->gprs[15] = (unsigned long) frame;
+	regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA;	/* 64 bit amode */
 	regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
 
 	regs->gprs[2] = map_signal(sig);
@@ -356,6 +363,7 @@
 
 	/* Set up registers for signal handler */
 	regs->gprs[15] = (unsigned long) frame;
+	regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA;	/* 64 bit amode */
 	regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
 
 	regs->gprs[2] = map_signal(sig);
@@ -401,7 +409,6 @@
  */
 void do_signal(struct pt_regs *regs)
 {
-	unsigned long retval = 0, continue_addr = 0, restart_addr = 0;
 	siginfo_t info;
 	int signr;
 	struct k_sigaction ka;
@@ -421,54 +428,45 @@
 	else
 		oldset = &current->blocked;
 
-	/* Are we from a system call? */
-	if (regs->svcnr) {
-		continue_addr = regs->psw.addr;
-		restart_addr = continue_addr - regs->ilc;
-		retval = regs->gprs[2];
-
-		/* 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->gprs[2] = regs->orig_gpr2;
-			regs->psw.addr = restart_addr;
-			break;
-		case -ERESTART_RESTARTBLOCK:
-			regs->gprs[2] = -EINTR;
-		}
-		regs->svcnr = 0;	/* Don't deal with this again. */
-	}
-
-	/* Get signal to deliver.  When running under ptrace, at this point
-	   the debugger may change all our registers ... */
+	/*
+	 * Get signal to deliver. When running under ptrace, at this point
+	 * the debugger may change all our registers, including the system
+	 * call information.
+	 */
+	current_thread_info()->system_call =
+		test_thread_flag(TIF_SYSCALL) ? regs->svc_code : 0;
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
-	/* Depending on the signal settings we may need to revert the
-	   decision to restart the system call. */
-	if (signr > 0 && regs->psw.addr == restart_addr) {
-		if (retval == -ERESTARTNOHAND
-		    || (retval == -ERESTARTSYS
-			 && !(current->sighand->action[signr-1].sa.sa_flags
-			      & SA_RESTART))) {
-			regs->gprs[2] = -EINTR;
-			regs->psw.addr = continue_addr;
-		}
-	}
-
 	if (signr > 0) {
 		/* Whee!  Actually deliver the signal.  */
-		int ret;
-#ifdef CONFIG_COMPAT
-		if (is_compat_task()) {
-			ret = handle_signal32(signr, &ka, &info, oldset, regs);
-	        }
-		else
-#endif
-			ret = handle_signal(signr, &ka, &info, oldset, regs);
-		if (!ret) {
+		if (current_thread_info()->system_call) {
+			regs->svc_code = current_thread_info()->system_call;
+			/* Check for system call restarting. */
+			switch (regs->gprs[2]) {
+			case -ERESTART_RESTARTBLOCK:
+			case -ERESTARTNOHAND:
+				regs->gprs[2] = -EINTR;
+				break;
+			case -ERESTARTSYS:
+				if (!(ka.sa.sa_flags & SA_RESTART)) {
+					regs->gprs[2] = -EINTR;
+					break;
+				}
+			/* fallthrough */
+			case -ERESTARTNOINTR:
+				regs->gprs[2] = regs->orig_gpr2;
+				regs->psw.addr =
+					__rewind_psw(regs->psw,
+						     regs->svc_code >> 16);
+				break;
+			}
+		}
+		/* No longer in a system call */
+		clear_thread_flag(TIF_SYSCALL);
+
+		if ((is_compat_task() ?
+		     handle_signal32(signr, &ka, &info, oldset, regs) :
+		     handle_signal(signr, &ka, &info, oldset, regs)) == 0) {
 			/*
 			 * A signal was successfully delivered; the saved
 			 * sigmask will have been stored in the signal frame,
@@ -482,11 +480,30 @@
 			 * Let tracing know that we've done the handler setup.
 			 */
 			tracehook_signal_handler(signr, &info, &ka, regs,
-					test_thread_flag(TIF_SINGLE_STEP));
+					 test_thread_flag(TIF_SINGLE_STEP));
 		}
 		return;
 	}
 
+	/* No handlers present - check for system call restart */
+	clear_thread_flag(TIF_SYSCALL);
+	if (current_thread_info()->system_call) {
+		regs->svc_code = current_thread_info()->system_call;
+		switch (regs->gprs[2]) {
+		case -ERESTART_RESTARTBLOCK:
+			/* Restart with sys_restart_syscall */
+			regs->svc_code = __NR_restart_syscall;
+		/* fallthrough */
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
+			/* Restart system call with magic TIF bit. */
+			regs->gprs[2] = regs->orig_gpr2;
+			set_thread_flag(TIF_SYSCALL);
+			break;
+		}
+	}
+
 	/*
 	 * If there's no signal to deliver, we just put the saved sigmask back.
 	 */
@@ -494,13 +511,6 @@
 		clear_thread_flag(TIF_RESTORE_SIGMASK);
 		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
 	}
-
-	/* Restart a different system call. */
-	if (retval == -ERESTART_RESTARTBLOCK
-	    && regs->psw.addr == continue_addr) {
-		regs->gprs[2] = __NR_restart_syscall;
-		set_thread_flag(TIF_RESTART_SVC);
-	}
 }
 
 void do_notify_resume(struct pt_regs *regs)
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/smp.c linux-libre-3.2-gnu/arch/s390/kernel/smp.c
--- linux-libre-3.1-gnu/arch/s390/kernel/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,7 @@
 #include <linux/timex.h>
 #include <linux/bootmem.h>
 #include <linux/slab.h>
+#include <linux/crash_dump.h>
 #include <asm/asm-offsets.h>
 #include <asm/ipl.h>
 #include <asm/setup.h>
@@ -97,6 +98,29 @@
 	return raw_cpu_stopped(cpu_logical_map(cpu));
 }
 
+/*
+ * Ensure that PSW restart is done on an online CPU
+ */
+void smp_restart_with_online_cpu(void)
+{
+	int cpu;
+
+	for_each_online_cpu(cpu) {
+		if (stap() == __cpu_logical_map[cpu]) {
+			/* We are online: Enable DAT again and return */
+			__load_psw_mask(psw_kernel_bits | PSW_MASK_DAT);
+			return;
+		}
+	}
+	/* We are not online: Do PSW restart on an online CPU */
+	while (sigp(cpu, sigp_restart) == sigp_busy)
+		cpu_relax();
+	/* And stop ourself */
+	while (raw_sigp(stap(), sigp_stop) == sigp_busy)
+		cpu_relax();
+	for (;;);
+}
+
 void smp_switch_to_ipl_cpu(void (*func)(void *), void *data)
 {
 	struct _lowcore *lc, *current_lc;
@@ -106,14 +130,16 @@
 
 	if (smp_processor_id() == 0)
 		func(data);
-	__load_psw_mask(PSW_BASE_BITS | PSW_DEFAULT_KEY);
+	__load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE |
+			PSW_MASK_EA | PSW_MASK_BA);
 	/* Disable lowcore protection */
 	__ctl_clear_bit(0, 28);
 	current_lc = lowcore_ptr[smp_processor_id()];
 	lc = lowcore_ptr[0];
 	if (!lc)
 		lc = current_lc;
-	lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+	lc->restart_psw.mask =
+		PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
 	lc->restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) smp_restart_cpu;
 	if (!cpu_online(0))
 		smp_switch_to_cpu(func, data, 0, stap(), __cpu_logical_map[0]);
@@ -135,7 +161,7 @@
 	int cpu, rc;
 
 	/* Disable all interrupts/machine checks */
-	__load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK);
+	__load_psw_mask(psw_kernel_bits | PSW_MASK_DAT);
 	trace_hardirqs_off();
 
 	/* stop all processors */
@@ -161,7 +187,10 @@
 {
 	unsigned long bits;
 
-	kstat_cpu(smp_processor_id()).irqs[EXTINT_IPI]++;
+	if (ext_int_code == 0x1202)
+		kstat_cpu(smp_processor_id()).irqs[EXTINT_EXC]++;
+	else
+		kstat_cpu(smp_processor_id()).irqs[EXTINT_EMS]++;
 	/*
 	 * handle bit signal external calls
 	 */
@@ -183,12 +212,19 @@
  */
 static void smp_ext_bitcall(int cpu, int sig)
 {
+	int order;
+
 	/*
 	 * Set signaling bit in lowcore of target cpu and kick it
 	 */
 	set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast);
-	while (sigp(cpu, sigp_emergency_signal) == sigp_busy)
+	while (1) {
+		order = smp_vcpu_scheduled(cpu) ?
+			sigp_external_call : sigp_emergency_signal;
+		if (sigp(cpu, order) != sigp_busy)
+			break;
 		udelay(10);
+	}
 }
 
 void arch_send_call_function_ipi_mask(const struct cpumask *mask)
@@ -281,11 +317,13 @@
 }
 EXPORT_SYMBOL(smp_ctl_clear_bit);
 
-#ifdef CONFIG_ZFCPDUMP
+#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_CRASH_DUMP)
 
 static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
 {
-	if (ipl_info.type != IPL_TYPE_FCP_DUMP)
+	if (ipl_info.type != IPL_TYPE_FCP_DUMP && !OLDMEM_BASE)
+		return;
+	if (is_kdump_kernel())
 		return;
 	if (cpu >= NR_CPUS) {
 		pr_warning("CPU %i exceeds the maximum %i and is excluded from "
@@ -403,6 +441,18 @@
 	info = kmalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
 		panic("smp_detect_cpus failed to allocate memory\n");
+#ifdef CONFIG_CRASH_DUMP
+	if (OLDMEM_BASE && !is_kdump_kernel()) {
+		struct save_area *save_area;
+
+		save_area = kmalloc(sizeof(*save_area), GFP_KERNEL);
+		if (!save_area)
+			panic("could not allocate memory for save area\n");
+		copy_oldmem_page(1, (void *) save_area, sizeof(*save_area),
+				 0x200, 0);
+		zfcpdump_save_areas[0] = save_area;
+	}
+#endif
 	/* Use sigp detection algorithm if sclp doesn't work. */
 	if (sclp_get_cpu_info(info)) {
 		smp_use_sigp_detection = 1;
@@ -463,7 +513,8 @@
 	set_cpu_online(smp_processor_id(), true);
 	ipi_call_unlock();
 	__ctl_clear_bit(0, 28); /* Disable lowcore protection */
-	S390_lowcore.restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+	S390_lowcore.restart_psw.mask =
+		PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
 	S390_lowcore.restart_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
 	__ctl_set_bit(0, 28); /* Enable lowcore protection */
@@ -511,7 +562,8 @@
 	memset((char *)lowcore + 512, 0, sizeof(*lowcore) - 512);
 	lowcore->async_stack = async_stack + ASYNC_SIZE;
 	lowcore->panic_stack = panic_stack + PAGE_SIZE;
-	lowcore->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+	lowcore->restart_psw.mask =
+		PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
 	lowcore->restart_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
 	if (user_mode != HOME_SPACE_MODE)
@@ -712,6 +764,9 @@
 	/* request the 0x1201 emergency signal external interrupt */
 	if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0)
 		panic("Couldn't request external interrupt 0x1201");
+	/* request the 0x1202 external call external interrupt */
+	if (register_external_interrupt(0x1202, do_ext_call_interrupt) != 0)
+		panic("Couldn't request external interrupt 0x1202");
 
 	/* Reallocate current lowcore, but keep its contents. */
 	lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER);
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/suspend.c linux-libre-3.2-gnu/arch/s390/kernel/suspend.c
--- linux-libre-3.1-gnu/arch/s390/kernel/suspend.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/suspend.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,8 @@
  */
 
 #include <linux/pfn.h>
+#include <linux/suspend.h>
+#include <linux/mm.h>
 #include <asm/system.h>
 
 /*
@@ -14,6 +16,123 @@
  */
 extern const void __nosave_begin, __nosave_end;
 
+/*
+ * The restore of the saved pages in an hibernation image will set
+ * the change and referenced bits in the storage key for each page.
+ * Overindication of the referenced bits after an hibernation cycle
+ * does not cause any harm but the overindication of the change bits
+ * would cause trouble.
+ * Use the ARCH_SAVE_PAGE_KEYS hooks to save the storage key of each
+ * page to the most significant byte of the associated page frame
+ * number in the hibernation image.
+ */
+
+/*
+ * Key storage is allocated as a linked list of pages.
+ * The size of the keys array is (PAGE_SIZE - sizeof(long))
+ */
+struct page_key_data {
+	struct page_key_data *next;
+	unsigned char data[];
+};
+
+#define PAGE_KEY_DATA_SIZE	(PAGE_SIZE - sizeof(struct page_key_data *))
+
+static struct page_key_data *page_key_data;
+static struct page_key_data *page_key_rp, *page_key_wp;
+static unsigned long page_key_rx, page_key_wx;
+
+/*
+ * For each page in the hibernation image one additional byte is
+ * stored in the most significant byte of the page frame number.
+ * On suspend no additional memory is required but on resume the
+ * keys need to be memorized until the page data has been restored.
+ * Only then can the storage keys be set to their old state.
+ */
+unsigned long page_key_additional_pages(unsigned long pages)
+{
+	return DIV_ROUND_UP(pages, PAGE_KEY_DATA_SIZE);
+}
+
+/*
+ * Free page_key_data list of arrays.
+ */
+void page_key_free(void)
+{
+	struct page_key_data *pkd;
+
+	while (page_key_data) {
+		pkd = page_key_data;
+		page_key_data = pkd->next;
+		free_page((unsigned long) pkd);
+	}
+}
+
+/*
+ * Allocate page_key_data list of arrays with enough room to store
+ * one byte for each page in the hibernation image.
+ */
+int page_key_alloc(unsigned long pages)
+{
+	struct page_key_data *pk;
+	unsigned long size;
+
+	size = DIV_ROUND_UP(pages, PAGE_KEY_DATA_SIZE);
+	while (size--) {
+		pk = (struct page_key_data *) get_zeroed_page(GFP_KERNEL);
+		if (!pk) {
+			page_key_free();
+			return -ENOMEM;
+		}
+		pk->next = page_key_data;
+		page_key_data = pk;
+	}
+	page_key_rp = page_key_wp = page_key_data;
+	page_key_rx = page_key_wx = 0;
+	return 0;
+}
+
+/*
+ * Save the storage key into the upper 8 bits of the page frame number.
+ */
+void page_key_read(unsigned long *pfn)
+{
+	unsigned long addr;
+
+	addr = (unsigned long) page_address(pfn_to_page(*pfn));
+	*(unsigned char *) pfn = (unsigned char) page_get_storage_key(addr);
+}
+
+/*
+ * Extract the storage key from the upper 8 bits of the page frame number
+ * and store it in the page_key_data list of arrays.
+ */
+void page_key_memorize(unsigned long *pfn)
+{
+	page_key_wp->data[page_key_wx] = *(unsigned char *) pfn;
+	*(unsigned char *) pfn = 0;
+	if (++page_key_wx < PAGE_KEY_DATA_SIZE)
+		return;
+	page_key_wp = page_key_wp->next;
+	page_key_wx = 0;
+}
+
+/*
+ * Get the next key from the page_key_data list of arrays and set the
+ * storage key of the page referred by @address. If @address refers to
+ * a "safe" page the swsusp_arch_resume code will transfer the storage
+ * key from the buffer page to the original page.
+ */
+void page_key_write(void *address)
+{
+	page_set_storage_key((unsigned long) address,
+			     page_key_rp->data[page_key_rx], 0);
+	if (++page_key_rx >= PAGE_KEY_DATA_SIZE)
+		return;
+	page_key_rp = page_key_rp->next;
+	page_key_rx = 0;
+}
+
 int pfn_is_nosave(unsigned long pfn)
 {
 	unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin));
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/swsusp_asm64.S linux-libre-3.2-gnu/arch/s390/kernel/swsusp_asm64.S
--- linux-libre-3.1-gnu/arch/s390/kernel/swsusp_asm64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/swsusp_asm64.S	2012-01-04 18:55:44.000000000 -0500
@@ -136,11 +136,14 @@
 0:
 	lg	%r2,8(%r1)
 	lg	%r4,0(%r1)
+	iske	%r0,%r4
 	lghi	%r3,PAGE_SIZE
 	lghi	%r5,PAGE_SIZE
 1:
 	mvcle	%r2,%r4,0
 	jo	1b
+	lg	%r2,8(%r1)
+	sske	%r0,%r2
 	lg	%r1,16(%r1)
 	ltgr	%r1,%r1
 	jnz	0b
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/syscalls.S linux-libre-3.2-gnu/arch/s390/kernel/syscalls.S
--- linux-libre-3.1-gnu/arch/s390/kernel/syscalls.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/syscalls.S	2012-01-04 18:55:44.000000000 -0500
@@ -348,3 +348,5 @@
 SYSCALL(sys_clock_adjtime,sys_clock_adjtime,compat_sys_clock_adjtime_wrapper)
 SYSCALL(sys_syncfs,sys_syncfs,sys_syncfs_wrapper)
 SYSCALL(sys_setns,sys_setns,sys_setns_wrapper)
+SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wrapper) /* 340 */
+SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper)
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/sysinfo.c linux-libre-3.2-gnu/arch/s390/kernel/sysinfo.c
--- linux-libre-3.1-gnu/arch/s390/kernel/sysinfo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/sysinfo.c	2012-01-04 18:55:44.000000000 -0500
@@ -442,7 +442,7 @@
 		 */
 		FP_UNPACK_SP(SA, &fmil);
 		if ((info->capability >> 23) == 0)
-			FP_FROM_INT_S(SB, info->capability, 32, int);
+			FP_FROM_INT_S(SB, (long) info->capability, 64, long);
 		else
 			FP_UNPACK_SP(SB, &info->capability);
 		FP_DIV_S(SR, SA, SB);
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/time.c linux-libre-3.2-gnu/arch/s390/kernel/time.c
--- linux-libre-3.1-gnu/arch/s390/kernel/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,6 +48,7 @@
 #include <asm/timer.h>
 #include <asm/etr.h>
 #include <asm/cio.h>
+#include "entry.h"
 
 /* change this if you have some constant time drift */
 #define USECS_PER_JIFFY     ((unsigned long) 1000000/HZ)
@@ -109,10 +110,14 @@
 	set_clock_comparator(S390_lowcore.clock_comparator);
 }
 
-static int s390_next_event(unsigned long delta,
+static int s390_next_ktime(ktime_t expires,
 			   struct clock_event_device *evt)
 {
-	S390_lowcore.clock_comparator = get_clock() + delta;
+	u64 nsecs;
+
+	nsecs = ktime_to_ns(ktime_sub(expires, ktime_get_monotonic_offset()));
+	do_div(nsecs, 125);
+	S390_lowcore.clock_comparator = TOD_UNIX_EPOCH + (nsecs << 9);
 	set_clock_comparator(S390_lowcore.clock_comparator);
 	return 0;
 }
@@ -137,14 +142,15 @@
 	cpu = smp_processor_id();
 	cd = &per_cpu(comparators, cpu);
 	cd->name		= "comparator";
-	cd->features		= CLOCK_EVT_FEAT_ONESHOT;
+	cd->features		= CLOCK_EVT_FEAT_ONESHOT |
+				  CLOCK_EVT_FEAT_KTIME;
 	cd->mult		= 16777;
 	cd->shift		= 12;
 	cd->min_delta_ns	= 1;
 	cd->max_delta_ns	= LONG_MAX;
 	cd->rating		= 400;
 	cd->cpumask		= cpumask_of(cpu);
-	cd->set_next_event	= s390_next_event;
+	cd->set_next_ktime	= s390_next_ktime;
 	cd->set_mode		= s390_set_mode;
 
 	clockevents_register_device(cd);
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/topology.c linux-libre-3.2-gnu/arch/s390/kernel/topology.c
--- linux-libre-3.1-gnu/arch/s390/kernel/topology.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/topology.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,8 +68,10 @@
 	return mask;
 }
 
-static void add_cpus_to_mask(struct topology_cpu *tl_cpu,
-			     struct mask_info *book, struct mask_info *core)
+static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
+					  struct mask_info *book,
+					  struct mask_info *core,
+					  int z10)
 {
 	unsigned int cpu;
 
@@ -88,10 +90,16 @@
 			cpu_book_id[lcpu] = book->id;
 #endif
 			cpumask_set_cpu(lcpu, &core->mask);
-			cpu_core_id[lcpu] = core->id;
+			if (z10) {
+				cpu_core_id[lcpu] = rcpu;
+				core = core->next;
+			} else {
+				cpu_core_id[lcpu] = core->id;
+			}
 			smp_cpu_polarization[lcpu] = tl_cpu->pp;
 		}
 	}
+	return core;
 }
 
 static void clear_masks(void)
@@ -123,18 +131,41 @@
 {
 #ifdef CONFIG_SCHED_BOOK
 	struct mask_info *book = &book_info;
+	struct cpuid cpu_id;
 #else
 	struct mask_info *book = NULL;
 #endif
 	struct mask_info *core = &core_info;
 	union topology_entry *tle, *end;
+	int z10 = 0;
 
-
+#ifdef CONFIG_SCHED_BOOK
+	get_cpu_id(&cpu_id);
+	z10 = cpu_id.machine == 0x2097 || cpu_id.machine == 0x2098;
+#endif
 	spin_lock_irq(&topology_lock);
 	clear_masks();
 	tle = info->tle;
 	end = (union topology_entry *)((unsigned long)info + info->length);
 	while (tle < end) {
+#ifdef CONFIG_SCHED_BOOK
+		if (z10) {
+			switch (tle->nl) {
+			case 1:
+				book = book->next;
+				book->id = tle->container.id;
+				break;
+			case 0:
+				core = add_cpus_to_mask(&tle->cpu, book, core, z10);
+				break;
+			default:
+				clear_masks();
+				goto out;
+			}
+			tle = next_tle(tle);
+			continue;
+		}
+#endif
 		switch (tle->nl) {
 #ifdef CONFIG_SCHED_BOOK
 		case 2:
@@ -147,7 +178,7 @@
 			core->id = tle->container.id;
 			break;
 		case 0:
-			add_cpus_to_mask(&tle->cpu, book, core);
+			add_cpus_to_mask(&tle->cpu, book, core, z10);
 			break;
 		default:
 			clear_masks();
@@ -299,8 +330,8 @@
 }
 __initcall(init_topology_update);
 
-static void alloc_masks(struct sysinfo_15_1_x *info, struct mask_info *mask,
-			int offset)
+static void __init alloc_masks(struct sysinfo_15_1_x *info,
+			       struct mask_info *mask, int offset)
 {
 	int i, nr_masks;
 
@@ -328,8 +359,8 @@
 	for (i = 0; i < TOPOLOGY_NR_MAG; i++)
 		printk(" %d", info->mag[i]);
 	printk(" / %d\n", info->mnest);
-	alloc_masks(info, &core_info, 2);
+	alloc_masks(info, &core_info, 1);
 #ifdef CONFIG_SCHED_BOOK
-	alloc_masks(info, &book_info, 3);
+	alloc_masks(info, &book_info, 2);
 #endif
 }
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/traps.c linux-libre-3.2-gnu/arch/s390/kernel/traps.c
--- linux-libre-3.1-gnu/arch/s390/kernel/traps.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/traps.c	2012-01-04 18:55:44.000000000 -0500
@@ -200,7 +200,7 @@
 	       mask_bits(regs, PSW_MASK_PSTATE), mask_bits(regs, PSW_MASK_ASC),
 	       mask_bits(regs, PSW_MASK_CC), mask_bits(regs, PSW_MASK_PM));
 #ifdef CONFIG_64BIT
-	printk(" EA:%x", mask_bits(regs, PSW_BASE_BITS));
+	printk(" EA:%x", mask_bits(regs, PSW_MASK_EA | PSW_MASK_BA));
 #endif
 	printk("\n%s GPRS: " FOURLONG, mode,
 	       regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
@@ -334,7 +334,8 @@
 	info.si_signo = SIGTRAP;
 	info.si_errno = 0;
 	info.si_code = TRAP_HWBKPT;
-	info.si_addr = (void *) current->thread.per_event.address;
+	info.si_addr =
+		(void __force __user *) current->thread.per_event.address;
 	force_sig_info(SIGTRAP, &info, current);
 }
 
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/vmlinux.lds.S linux-libre-3.2-gnu/arch/s390/kernel/vmlinux.lds.S
--- linux-libre-3.1-gnu/arch/s390/kernel/vmlinux.lds.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/vmlinux.lds.S	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,8 @@
 
 	NOTES :text :note
 
+	.dummy : { *(.dummy) } :data
+
 	RODATA
 
 #ifdef CONFIG_SHARED_KERNEL
diff -druN linux-libre-3.1-gnu/arch/s390/kernel/vtime.c linux-libre-3.2-gnu/arch/s390/kernel/vtime.c
--- linux-libre-3.1-gnu/arch/s390/kernel/vtime.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kernel/vtime.c	2012-01-04 18:55:44.000000000 -0500
@@ -170,7 +170,8 @@
 	psw_t psw;
 
 	/* Wait for external, I/O or machine check interrupt. */
-	psw.mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_IO | PSW_MASK_EXT;
+	psw.mask = psw_kernel_bits | PSW_MASK_WAIT |
+		PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
 
 	idle->nohz_delay = 0;
 
@@ -183,7 +184,8 @@
 		 *	set_cpu_timer(VTIMER_MAX_SLICE);
 		 *	idle->idle_enter = get_clock();
 		 *	__load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
-		 *			   PSW_MASK_IO | PSW_MASK_EXT);
+		 *			   PSW_MASK_DAT | PSW_MASK_IO |
+		 *			   PSW_MASK_EXT | PSW_MASK_MCHECK);
 		 * The difference is that the inline assembly makes sure that
 		 * the last three instruction are stpt, stck and lpsw in that
 		 * order. This is done to increase the precision.
@@ -216,7 +218,8 @@
 		 *	vq->idle = get_cpu_timer();
 		 *	idle->idle_enter = get_clock();
 		 *	__load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
-		 *			   PSW_MASK_IO | PSW_MASK_EXT);
+		 *			   PSW_MASK_DAT | PSW_MASK_IO |
+		 *			   PSW_MASK_EXT | PSW_MASK_MCHECK);
 		 * The difference is that the inline assembly makes sure that
 		 * the last three instruction are stpt, stck and lpsw in that
 		 * order. This is done to increase the precision.
@@ -458,7 +461,7 @@
 }
 EXPORT_SYMBOL(add_virt_timer_periodic);
 
-int __mod_vtimer(struct vtimer_list *timer, __u64 expires, int periodic)
+static int __mod_vtimer(struct vtimer_list *timer, __u64 expires, int periodic)
 {
 	struct vtimer_queue *vq;
 	unsigned long flags;
diff -druN linux-libre-3.1-gnu/arch/s390/kvm/diag.c linux-libre-3.2-gnu/arch/s390/kvm/diag.c
--- linux-libre-3.1-gnu/arch/s390/kvm/diag.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kvm/diag.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * diag.c - handling diagnose instructions
  *
- * Copyright IBM Corp. 2008
+ * Copyright IBM Corp. 2008,2011
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
@@ -15,6 +15,34 @@
 #include <linux/kvm_host.h>
 #include "kvm-s390.h"
 
+static int diag_release_pages(struct kvm_vcpu *vcpu)
+{
+	unsigned long start, end;
+	unsigned long prefix  = vcpu->arch.sie_block->prefix;
+
+	start = vcpu->arch.guest_gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4];
+	end = vcpu->arch.guest_gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096;
+
+	if (start & ~PAGE_MASK || end & ~PAGE_MASK || start > end
+	    || start < 2 * PAGE_SIZE)
+		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+
+	VCPU_EVENT(vcpu, 5, "diag release pages %lX %lX", start, end);
+	vcpu->stat.diagnose_10++;
+
+	/* we checked for start > end above */
+	if (end < prefix || start >= prefix + 2 * PAGE_SIZE) {
+		gmap_discard(start, end, vcpu->arch.gmap);
+	} else {
+		if (start < prefix)
+			gmap_discard(start, prefix, vcpu->arch.gmap);
+		if (end >= prefix)
+			gmap_discard(prefix + 2 * PAGE_SIZE,
+				     end, vcpu->arch.gmap);
+	}
+	return 0;
+}
+
 static int __diag_time_slice_end(struct kvm_vcpu *vcpu)
 {
 	VCPU_EVENT(vcpu, 5, "%s", "diag time slice end");
@@ -42,7 +70,7 @@
 		return -EOPNOTSUPP;
 	}
 
-	atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
+	atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
 	vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM;
 	vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL;
 	vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT;
@@ -57,6 +85,8 @@
 	int code = (vcpu->arch.sie_block->ipb & 0xfff0000) >> 16;
 
 	switch (code) {
+	case 0x10:
+		return diag_release_pages(vcpu);
 	case 0x44:
 		return __diag_time_slice_end(vcpu);
 	case 0x308:
diff -druN linux-libre-3.1-gnu/arch/s390/kvm/intercept.c linux-libre-3.2-gnu/arch/s390/kvm/intercept.c
--- linux-libre-3.1-gnu/arch/s390/kvm/intercept.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kvm/intercept.c	2012-01-04 18:55:44.000000000 -0500
@@ -132,7 +132,6 @@
 	int rc = 0;
 
 	vcpu->stat.exit_stop_request++;
-	atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
 	spin_lock_bh(&vcpu->arch.local_int.lock);
 	if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
 		vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
@@ -149,6 +148,8 @@
 	}
 
 	if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) {
+		atomic_set_mask(CPUSTAT_STOPPED,
+				&vcpu->arch.sie_block->cpuflags);
 		vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP;
 		VCPU_EVENT(vcpu, 3, "%s", "cpu stopped");
 		rc = -EOPNOTSUPP;
diff -druN linux-libre-3.1-gnu/arch/s390/kvm/interrupt.c linux-libre-3.2-gnu/arch/s390/kvm/interrupt.c
--- linux-libre-3.1-gnu/arch/s390/kvm/interrupt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kvm/interrupt.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,11 @@
 				      struct kvm_s390_interrupt_info *inti)
 {
 	switch (inti->type) {
+	case KVM_S390_INT_EXTERNAL_CALL:
+		if (psw_extint_disabled(vcpu))
+			return 0;
+		if (vcpu->arch.sie_block->gcr[0] & 0x2000ul)
+			return 1;
 	case KVM_S390_INT_EMERGENCY:
 		if (psw_extint_disabled(vcpu))
 			return 0;
@@ -98,6 +103,7 @@
 				      struct kvm_s390_interrupt_info *inti)
 {
 	switch (inti->type) {
+	case KVM_S390_INT_EXTERNAL_CALL:
 	case KVM_S390_INT_EMERGENCY:
 	case KVM_S390_INT_SERVICE:
 	case KVM_S390_INT_VIRTIO:
@@ -143,6 +149,28 @@
 			exception = 1;
 		break;
 
+	case KVM_S390_INT_EXTERNAL_CALL:
+		VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call");
+		vcpu->stat.deliver_external_call++;
+		rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x1202);
+		if (rc == -EFAULT)
+			exception = 1;
+
+		rc = put_guest_u16(vcpu, __LC_CPU_ADDRESS, inti->extcall.code);
+		if (rc == -EFAULT)
+			exception = 1;
+
+		rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
+			 &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+		if (rc == -EFAULT)
+			exception = 1;
+
+		rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
+			__LC_EXT_NEW_PSW, sizeof(psw_t));
+		if (rc == -EFAULT)
+			exception = 1;
+		break;
+
 	case KVM_S390_INT_SERVICE:
 		VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x",
 			   inti->ext.ext_params);
@@ -224,6 +252,7 @@
 			offsetof(struct _lowcore, restart_psw), sizeof(psw_t));
 		if (rc == -EFAULT)
 			exception = 1;
+		atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
 		break;
 
 	case KVM_S390_PROGRAM_INT:
@@ -522,6 +551,7 @@
 		break;
 	case KVM_S390_PROGRAM_INT:
 	case KVM_S390_SIGP_STOP:
+	case KVM_S390_INT_EXTERNAL_CALL:
 	case KVM_S390_INT_EMERGENCY:
 	default:
 		kfree(inti);
@@ -581,6 +611,7 @@
 		break;
 	case KVM_S390_SIGP_STOP:
 	case KVM_S390_RESTART:
+	case KVM_S390_INT_EXTERNAL_CALL:
 	case KVM_S390_INT_EMERGENCY:
 		VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
 		inti->type = s390int->type;
diff -druN linux-libre-3.1-gnu/arch/s390/kvm/kvm-s390.c linux-libre-3.2-gnu/arch/s390/kvm/kvm-s390.c
--- linux-libre-3.1-gnu/arch/s390/kvm/kvm-s390.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kvm/kvm-s390.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,6 +46,7 @@
 	{ "instruction_lctlg", VCPU_STAT(instruction_lctlg) },
 	{ "instruction_lctl", VCPU_STAT(instruction_lctl) },
 	{ "deliver_emergency_signal", VCPU_STAT(deliver_emergency_signal) },
+	{ "deliver_external_call", VCPU_STAT(deliver_external_call) },
 	{ "deliver_service_signal", VCPU_STAT(deliver_service_signal) },
 	{ "deliver_virtio_interrupt", VCPU_STAT(deliver_virtio_interrupt) },
 	{ "deliver_stop_signal", VCPU_STAT(deliver_stop_signal) },
@@ -64,11 +65,14 @@
 	{ "instruction_stfl", VCPU_STAT(instruction_stfl) },
 	{ "instruction_tprot", VCPU_STAT(instruction_tprot) },
 	{ "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) },
+	{ "instruction_sigp_sense_running", VCPU_STAT(instruction_sigp_sense_running) },
+	{ "instruction_sigp_external_call", VCPU_STAT(instruction_sigp_external_call) },
 	{ "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) },
 	{ "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) },
 	{ "instruction_sigp_set_arch", VCPU_STAT(instruction_sigp_arch) },
 	{ "instruction_sigp_set_prefix", VCPU_STAT(instruction_sigp_prefix) },
 	{ "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) },
+	{ "diagnose_10", VCPU_STAT(diagnose_10) },
 	{ "diagnose_44", VCPU_STAT(diagnose_44) },
 	{ NULL }
 };
@@ -124,6 +128,7 @@
 	switch (ext) {
 	case KVM_CAP_S390_PSW:
 	case KVM_CAP_S390_GMAP:
+	case KVM_CAP_SYNC_MMU:
 		r = 1;
 		break;
 	default:
@@ -175,6 +180,8 @@
 	if (rc)
 		goto out_err;
 
+	rc = -ENOMEM;
+
 	kvm->arch.sca = (struct sca_block *) get_zeroed_page(GFP_KERNEL);
 	if (!kvm->arch.sca)
 		goto out_err;
@@ -265,10 +272,12 @@
 	restore_fp_regs(&vcpu->arch.guest_fpregs);
 	restore_access_regs(vcpu->arch.guest_acrs);
 	gmap_enable(vcpu->arch.gmap);
+	atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 {
+	atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
 	gmap_disable(vcpu->arch.gmap);
 	save_fp_regs(&vcpu->arch.guest_fpregs);
 	save_access_regs(vcpu->arch.guest_acrs);
@@ -296,7 +305,9 @@
 
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
-	atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | CPUSTAT_SM);
+	atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH |
+						    CPUSTAT_SM |
+						    CPUSTAT_STOPPED);
 	vcpu->arch.sie_block->ecb   = 6;
 	vcpu->arch.sie_block->eca   = 0xC1002001U;
 	vcpu->arch.sie_block->fac   = (int) (long) facilities;
@@ -312,11 +323,17 @@
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
 				      unsigned int id)
 {
-	struct kvm_vcpu *vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
-	int rc = -ENOMEM;
+	struct kvm_vcpu *vcpu;
+	int rc = -EINVAL;
 
+	if (id >= KVM_MAX_VCPUS)
+		goto out;
+
+	rc = -ENOMEM;
+
+	vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
 	if (!vcpu)
-		goto out_nomem;
+		goto out;
 
 	vcpu->arch.sie_block = (struct kvm_s390_sie_block *)
 					get_zeroed_page(GFP_KERNEL);
@@ -352,7 +369,7 @@
 	free_page((unsigned long)(vcpu->arch.sie_block));
 out_free_cpu:
 	kfree(vcpu);
-out_nomem:
+out:
 	return ERR_PTR(rc);
 }
 
@@ -386,6 +403,7 @@
 {
 	memcpy(&vcpu->arch.guest_acrs, &sregs->acrs, sizeof(sregs->acrs));
 	memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs));
+	restore_access_regs(vcpu->arch.guest_acrs);
 	return 0;
 }
 
@@ -401,6 +419,7 @@
 {
 	memcpy(&vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
 	vcpu->arch.guest_fpregs.fpc = fpu->fpc;
+	restore_fp_regs(&vcpu->arch.guest_fpregs);
 	return 0;
 }
 
@@ -415,7 +434,7 @@
 {
 	int rc = 0;
 
-	if (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_RUNNING)
+	if (!(atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOPPED))
 		rc = -EBUSY;
 	else {
 		vcpu->run->psw_mask = psw.mask;
@@ -488,7 +507,7 @@
 	if (vcpu->sigset_active)
 		sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
 
-	atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
+	atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
 
 	BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL);
 
diff -druN linux-libre-3.1-gnu/arch/s390/kvm/priv.c linux-libre-3.2-gnu/arch/s390/kvm/priv.c
--- linux-libre-3.1-gnu/arch/s390/kvm/priv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kvm/priv.c	2012-01-04 18:55:44.000000000 -0500
@@ -336,6 +336,7 @@
 	u64 address1 = disp1 + base1 ? vcpu->arch.guest_gprs[base1] : 0;
 	u64 address2 = disp2 + base2 ? vcpu->arch.guest_gprs[base2] : 0;
 	struct vm_area_struct *vma;
+	unsigned long user_address;
 
 	vcpu->stat.instruction_tprot++;
 
@@ -349,9 +350,14 @@
 		return -EOPNOTSUPP;
 
 
+	/* we must resolve the address without holding the mmap semaphore.
+	 * This is ok since the userspace hypervisor is not supposed to change
+	 * the mapping while the guest queries the memory. Otherwise the guest
+	 * might crash or get wrong info anyway. */
+	user_address = (unsigned long) __guestaddr_to_user(vcpu, address1);
+
 	down_read(&current->mm->mmap_sem);
-	vma = find_vma(current->mm,
-			(unsigned long) __guestaddr_to_user(vcpu, address1));
+	vma = find_vma(current->mm, user_address);
 	if (!vma) {
 		up_read(&current->mm->mmap_sem);
 		return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
diff -druN linux-libre-3.1-gnu/arch/s390/kvm/sigp.c linux-libre-3.2-gnu/arch/s390/kvm/sigp.c
--- linux-libre-3.1-gnu/arch/s390/kvm/sigp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/kvm/sigp.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,9 +31,11 @@
 #define SIGP_SET_PREFIX        0x0d
 #define SIGP_STORE_STATUS_ADDR 0x0e
 #define SIGP_SET_ARCH          0x12
+#define SIGP_SENSE_RUNNING     0x15
 
 /* cpu status bits */
 #define SIGP_STAT_EQUIPMENT_CHECK   0x80000000UL
+#define SIGP_STAT_NOT_RUNNING	    0x00000400UL
 #define SIGP_STAT_INCORRECT_STATE   0x00000200UL
 #define SIGP_STAT_INVALID_PARAMETER 0x00000100UL
 #define SIGP_STAT_EXT_CALL_PENDING  0x00000080UL
@@ -57,8 +59,8 @@
 	spin_lock(&fi->lock);
 	if (fi->local_int[cpu_addr] == NULL)
 		rc = 3; /* not operational */
-	else if (atomic_read(fi->local_int[cpu_addr]->cpuflags)
-		 & CPUSTAT_RUNNING) {
+	else if (!(atomic_read(fi->local_int[cpu_addr]->cpuflags)
+		  & CPUSTAT_STOPPED)) {
 		*reg &= 0xffffffff00000000UL;
 		rc = 1; /* status stored */
 	} else {
@@ -87,6 +89,7 @@
 		return -ENOMEM;
 
 	inti->type = KVM_S390_INT_EMERGENCY;
+	inti->emerg.code = vcpu->vcpu_id;
 
 	spin_lock(&fi->lock);
 	li = fi->local_int[cpu_addr];
@@ -103,9 +106,47 @@
 		wake_up_interruptible(&li->wq);
 	spin_unlock_bh(&li->lock);
 	rc = 0; /* order accepted */
+	VCPU_EVENT(vcpu, 4, "sent sigp emerg to cpu %x", cpu_addr);
+unlock:
+	spin_unlock(&fi->lock);
+	return rc;
+}
+
+static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr)
+{
+	struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
+	struct kvm_s390_local_interrupt *li;
+	struct kvm_s390_interrupt_info *inti;
+	int rc;
+
+	if (cpu_addr >= KVM_MAX_VCPUS)
+		return 3; /* not operational */
+
+	inti = kzalloc(sizeof(*inti), GFP_KERNEL);
+	if (!inti)
+		return -ENOMEM;
+
+	inti->type = KVM_S390_INT_EXTERNAL_CALL;
+	inti->extcall.code = vcpu->vcpu_id;
+
+	spin_lock(&fi->lock);
+	li = fi->local_int[cpu_addr];
+	if (li == NULL) {
+		rc = 3; /* not operational */
+		kfree(inti);
+		goto unlock;
+	}
+	spin_lock_bh(&li->lock);
+	list_add_tail(&inti->list, &li->list);
+	atomic_set(&li->active, 1);
+	atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
+	if (waitqueue_active(&li->wq))
+		wake_up_interruptible(&li->wq);
+	spin_unlock_bh(&li->lock);
+	rc = 0; /* order accepted */
+	VCPU_EVENT(vcpu, 4, "sent sigp ext call to cpu %x", cpu_addr);
 unlock:
 	spin_unlock(&fi->lock);
-	VCPU_EVENT(vcpu, 4, "sent sigp emerg to cpu %x", cpu_addr);
 	return rc;
 }
 
@@ -212,7 +253,7 @@
 
 	spin_lock_bh(&li->lock);
 	/* cpu must be in stopped state */
-	if (atomic_read(li->cpuflags) & CPUSTAT_RUNNING) {
+	if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
 		rc = 1; /* incorrect state */
 		*reg &= SIGP_STAT_INCORRECT_STATE;
 		kfree(inti);
@@ -236,6 +277,38 @@
 	return rc;
 }
 
+static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
+				unsigned long *reg)
+{
+	int rc;
+	struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
+
+	if (cpu_addr >= KVM_MAX_VCPUS)
+		return 3; /* not operational */
+
+	spin_lock(&fi->lock);
+	if (fi->local_int[cpu_addr] == NULL)
+		rc = 3; /* not operational */
+	else {
+		if (atomic_read(fi->local_int[cpu_addr]->cpuflags)
+		    & CPUSTAT_RUNNING) {
+			/* running */
+			rc = 1;
+		} else {
+			/* not running */
+			*reg &= 0xffffffff00000000UL;
+			*reg |= SIGP_STAT_NOT_RUNNING;
+			rc = 0;
+		}
+	}
+	spin_unlock(&fi->lock);
+
+	VCPU_EVENT(vcpu, 4, "sensed running status of cpu %x rc %x", cpu_addr,
+		   rc);
+
+	return rc;
+}
+
 int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
 {
 	int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
@@ -267,6 +340,10 @@
 		rc = __sigp_sense(vcpu, cpu_addr,
 				  &vcpu->arch.guest_gprs[r1]);
 		break;
+	case SIGP_EXTERNAL_CALL:
+		vcpu->stat.instruction_sigp_external_call++;
+		rc = __sigp_external_call(vcpu, cpu_addr);
+		break;
 	case SIGP_EMERGENCY:
 		vcpu->stat.instruction_sigp_emergency++;
 		rc = __sigp_emergency(vcpu, cpu_addr);
@@ -288,6 +365,11 @@
 		rc = __sigp_set_prefix(vcpu, cpu_addr, parameter,
 				       &vcpu->arch.guest_gprs[r1]);
 		break;
+	case SIGP_SENSE_RUNNING:
+		vcpu->stat.instruction_sigp_sense_running++;
+		rc = __sigp_sense_running(vcpu, cpu_addr,
+					  &vcpu->arch.guest_gprs[r1]);
+		break;
 	case SIGP_RESTART:
 		vcpu->stat.instruction_sigp_restart++;
 		/* user space must know about restart */
diff -druN linux-libre-3.1-gnu/arch/s390/lib/delay.c linux-libre-3.2-gnu/arch/s390/lib/delay.c
--- linux-libre-3.1-gnu/arch/s390/lib/delay.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/lib/delay.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,8 @@
 	u64 clock_saved;
 	u64 end;
 
-	mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
+	mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_WAIT |
+		PSW_MASK_EXT | PSW_MASK_MCHECK;
 	end = get_clock() + (usecs << 12);
 	clock_saved = local_tick_disable();
 	__ctl_store(cr0_saved, 0, 0);
diff -druN linux-libre-3.1-gnu/arch/s390/lib/uaccess_pt.c linux-libre-3.2-gnu/arch/s390/lib/uaccess_pt.c
--- linux-libre-3.1-gnu/arch/s390/lib/uaccess_pt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/lib/uaccess_pt.c	2012-01-04 18:55:44.000000000 -0500
@@ -342,7 +342,8 @@
 	if (segment_eq(get_fs(), KERNEL_DS))
 		return __futex_atomic_op_pt(op, uaddr, oparg, old);
 	spin_lock(&current->mm->page_table_lock);
-	uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
+	uaddr = (u32 __force __user *)
+		__dat_user_addr((__force unsigned long) uaddr);
 	if (!uaddr) {
 		spin_unlock(&current->mm->page_table_lock);
 		return -EFAULT;
@@ -378,7 +379,8 @@
 	if (segment_eq(get_fs(), KERNEL_DS))
 		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);
+	uaddr = (u32 __force __user *)
+		__dat_user_addr((__force unsigned long) uaddr);
 	if (!uaddr) {
 		spin_unlock(&current->mm->page_table_lock);
 		return -EFAULT;
diff -druN linux-libre-3.1-gnu/arch/s390/mm/fault.c linux-libre-3.2-gnu/arch/s390/mm/fault.c
--- linux-libre-3.1-gnu/arch/s390/mm/fault.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/mm/fault.c	2012-01-04 18:55:44.000000000 -0500
@@ -307,7 +307,7 @@
 
 #ifdef CONFIG_PGSTE
 	if (test_tsk_thread_flag(current, TIF_SIE) && S390_lowcore.gmap) {
-		address = gmap_fault(address,
+		address = __gmap_fault(address,
 				     (struct gmap *) S390_lowcore.gmap);
 		if (address == -EFAULT) {
 			fault = VM_FAULT_BADMAP;
@@ -393,7 +393,7 @@
 	int fault;
 
 	/* Protection exception is suppressing, decrement psw address. */
-	regs->psw.addr -= (pgm_int_code >> 16);
+	regs->psw.addr = __rewind_psw(regs->psw, pgm_int_code >> 16);
 	/*
 	 * Check for low-address protection.  This needs to be treated
 	 * as a special case because the translation exception code
@@ -454,7 +454,7 @@
 	struct pt_regs regs;
 	int access, fault;
 
-	regs.psw.mask = psw_kernel_bits;
+	regs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK;
 	if (!irqs_disabled())
 		regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT;
 	regs.psw.addr = (unsigned long) __builtin_return_address(0);
@@ -587,8 +587,13 @@
 		} else {
 			/* Completion interrupt was faster than initial
 			 * interrupt. Set pfault_wait to -1 so the initial
-			 * interrupt doesn't put the task to sleep. */
-			tsk->thread.pfault_wait = -1;
+			 * interrupt doesn't put the task to sleep.
+			 * If the task is not running, ignore the completion
+			 * interrupt since it must be a leftover of a PFAULT
+			 * CANCEL operation which didn't remove all pending
+			 * completion interrupts. */
+			if (tsk->state == TASK_RUNNING)
+				tsk->thread.pfault_wait = -1;
 		}
 		put_task_struct(tsk);
 	} else {
diff -druN linux-libre-3.1-gnu/arch/s390/mm/gup.c linux-libre-3.2-gnu/arch/s390/mm/gup.c
--- linux-libre-3.1-gnu/arch/s390/mm/gup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/mm/gup.c	2012-01-04 18:55:44.000000000 -0500
@@ -52,7 +52,7 @@
 		unsigned long end, int write, struct page **pages, int *nr)
 {
 	unsigned long mask, result;
-	struct page *head, *page;
+	struct page *head, *page, *tail;
 	int refs;
 
 	result = write ? 0 : _SEGMENT_ENTRY_RO;
@@ -64,6 +64,7 @@
 	refs = 0;
 	head = pmd_page(pmd);
 	page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
+	tail = page;
 	do {
 		VM_BUG_ON(compound_head(page) != head);
 		pages[*nr] = page;
@@ -81,6 +82,17 @@
 		*nr -= refs;
 		while (refs--)
 			put_page(head);
+		return 0;
+	}
+
+	/*
+	 * Any tail page need their mapcount reference taken before we
+	 * return.
+	 */
+	while (refs--) {
+		if (PageTail(tail))
+			get_huge_page_tail(tail);
+		tail++;
 	}
 
 	return 1;
diff -druN linux-libre-3.1-gnu/arch/s390/mm/init.c linux-libre-3.2-gnu/arch/s390/mm/init.c
--- linux-libre-3.1-gnu/arch/s390/mm/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/mm/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/pfn.h>
 #include <linux/poison.h>
 #include <linux/initrd.h>
+#include <linux/export.h>
 #include <linux/gfp.h>
 #include <asm/processor.h>
 #include <asm/system.h>
diff -druN linux-libre-3.1-gnu/arch/s390/mm/maccess.c linux-libre-3.2-gnu/arch/s390/mm/maccess.c
--- linux-libre-3.1-gnu/arch/s390/mm/maccess.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/mm/maccess.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/errno.h>
+#include <linux/gfp.h>
 #include <asm/system.h>
 
 /*
@@ -60,6 +61,9 @@
 	return copied < 0 ? -EFAULT : 0;
 }
 
+/*
+ * Copy memory in real mode (kernel to kernel)
+ */
 int memcpy_real(void *dest, void *src, size_t count)
 {
 	register unsigned long _dest asm("2") = (unsigned long) dest;
@@ -101,3 +105,55 @@
 	__ctl_load(cr0, 0, 0);
 	preempt_enable();
 }
+
+/*
+ * Copy memory from kernel (real) to user (virtual)
+ */
+int copy_to_user_real(void __user *dest, void *src, size_t count)
+{
+	int offs = 0, size, rc;
+	char *buf;
+
+	buf = (char *) __get_free_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	rc = -EFAULT;
+	while (offs < count) {
+		size = min(PAGE_SIZE, count - offs);
+		if (memcpy_real(buf, src + offs, size))
+			goto out;
+		if (copy_to_user(dest + offs, buf, size))
+			goto out;
+		offs += size;
+	}
+	rc = 0;
+out:
+	free_page((unsigned long) buf);
+	return rc;
+}
+
+/*
+ * Copy memory from user (virtual) to kernel (real)
+ */
+int copy_from_user_real(void *dest, void __user *src, size_t count)
+{
+	int offs = 0, size, rc;
+	char *buf;
+
+	buf = (char *) __get_free_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	rc = -EFAULT;
+	while (offs < count) {
+		size = min(PAGE_SIZE, count - offs);
+		if (copy_from_user(buf, src + offs, size))
+			goto out;
+		if (memcpy_real(dest + offs, buf, size))
+			goto out;
+		offs += size;
+	}
+	rc = 0;
+out:
+	free_page((unsigned long) buf);
+	return rc;
+}
diff -druN linux-libre-3.1-gnu/arch/s390/mm/mmap.c linux-libre-3.2-gnu/arch/s390/mm/mmap.c
--- linux-libre-3.1-gnu/arch/s390/mm/mmap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/mm/mmap.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 
 #include <linux/personality.h>
 #include <linux/mm.h>
+#include <linux/mman.h>
 #include <linux/module.h>
 #include <linux/random.h>
 #include <asm/pgalloc.h>
diff -druN linux-libre-3.1-gnu/arch/s390/mm/pageattr.c linux-libre-3.2-gnu/arch/s390/mm/pageattr.c
--- linux-libre-3.1-gnu/arch/s390/mm/pageattr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/mm/pageattr.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,7 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
+#include <asm/cacheflush.h>
 #include <asm/pgtable.h>
 
 static void change_page_attr(unsigned long addr, int numpages,
diff -druN linux-libre-3.1-gnu/arch/s390/mm/pgtable.c linux-libre-3.2-gnu/arch/s390/mm/pgtable.c
--- linux-libre-3.1-gnu/arch/s390/mm/pgtable.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/mm/pgtable.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 2007,2009
+ *    Copyright IBM Corp. 2007,2011
  *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
  */
 
@@ -222,6 +222,7 @@
 
 	/* Free all segment & region tables. */
 	down_read(&gmap->mm->mmap_sem);
+	spin_lock(&gmap->mm->page_table_lock);
 	list_for_each_entry_safe(page, next, &gmap->crst_list, lru) {
 		table = (unsigned long *) page_to_phys(page);
 		if ((*table & _REGION_ENTRY_TYPE_MASK) == 0)
@@ -230,6 +231,7 @@
 				gmap_unlink_segment(gmap, table);
 		__free_pages(page, ALLOC_ORDER);
 	}
+	spin_unlock(&gmap->mm->page_table_lock);
 	up_read(&gmap->mm->mmap_sem);
 	list_del(&gmap->list);
 	kfree(gmap);
@@ -256,6 +258,9 @@
 }
 EXPORT_SYMBOL_GPL(gmap_disable);
 
+/*
+ * gmap_alloc_table is assumed to be called with mmap_sem held
+ */
 static int gmap_alloc_table(struct gmap *gmap,
 			       unsigned long *table, unsigned long init)
 {
@@ -267,14 +272,12 @@
 		return -ENOMEM;
 	new = (unsigned long *) page_to_phys(page);
 	crst_table_init(new, init);
-	down_read(&gmap->mm->mmap_sem);
 	if (*table & _REGION_ENTRY_INV) {
 		list_add(&page->lru, &gmap->crst_list);
 		*table = (unsigned long) new | _REGION_ENTRY_LENGTH |
 			(*table & _REGION_ENTRY_TYPE_MASK);
 	} else
 		__free_pages(page, ALLOC_ORDER);
-	up_read(&gmap->mm->mmap_sem);
 	return 0;
 }
 
@@ -299,6 +302,7 @@
 
 	flush = 0;
 	down_read(&gmap->mm->mmap_sem);
+	spin_lock(&gmap->mm->page_table_lock);
 	for (off = 0; off < len; off += PMD_SIZE) {
 		/* Walk the guest addr space page table */
 		table = gmap->table + (((to + off) >> 53) & 0x7ff);
@@ -320,6 +324,7 @@
 		*table = _SEGMENT_ENTRY_INV;
 	}
 out:
+	spin_unlock(&gmap->mm->page_table_lock);
 	up_read(&gmap->mm->mmap_sem);
 	if (flush)
 		gmap_flush_tlb(gmap);
@@ -350,6 +355,7 @@
 
 	flush = 0;
 	down_read(&gmap->mm->mmap_sem);
+	spin_lock(&gmap->mm->page_table_lock);
 	for (off = 0; off < len; off += PMD_SIZE) {
 		/* Walk the gmap address space page table */
 		table = gmap->table + (((to + off) >> 53) & 0x7ff);
@@ -373,19 +379,24 @@
 		flush |= gmap_unlink_segment(gmap, table);
 		*table = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | (from + off);
 	}
+	spin_unlock(&gmap->mm->page_table_lock);
 	up_read(&gmap->mm->mmap_sem);
 	if (flush)
 		gmap_flush_tlb(gmap);
 	return 0;
 
 out_unmap:
+	spin_unlock(&gmap->mm->page_table_lock);
 	up_read(&gmap->mm->mmap_sem);
 	gmap_unmap_segment(gmap, to, len);
 	return -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(gmap_map_segment);
 
-unsigned long gmap_fault(unsigned long address, struct gmap *gmap)
+/*
+ * this function is assumed to be called with mmap_sem held
+ */
+unsigned long __gmap_fault(unsigned long address, struct gmap *gmap)
 {
 	unsigned long *table, vmaddr, segment;
 	struct mm_struct *mm;
@@ -445,16 +456,75 @@
 		page = pmd_page(*pmd);
 		mp = (struct gmap_pgtable *) page->index;
 		rmap->entry = table;
+		spin_lock(&mm->page_table_lock);
 		list_add(&rmap->list, &mp->mapper);
+		spin_unlock(&mm->page_table_lock);
 		/* Set gmap segment table entry to page table. */
 		*table = pmd_val(*pmd) & PAGE_MASK;
 		return vmaddr | (address & ~PMD_MASK);
 	}
 	return -EFAULT;
+}
+
+unsigned long gmap_fault(unsigned long address, struct gmap *gmap)
+{
+	unsigned long rc;
 
+	down_read(&gmap->mm->mmap_sem);
+	rc = __gmap_fault(address, gmap);
+	up_read(&gmap->mm->mmap_sem);
+
+	return rc;
 }
 EXPORT_SYMBOL_GPL(gmap_fault);
 
+void gmap_discard(unsigned long from, unsigned long to, struct gmap *gmap)
+{
+
+	unsigned long *table, address, size;
+	struct vm_area_struct *vma;
+	struct gmap_pgtable *mp;
+	struct page *page;
+
+	down_read(&gmap->mm->mmap_sem);
+	address = from;
+	while (address < to) {
+		/* Walk the gmap address space page table */
+		table = gmap->table + ((address >> 53) & 0x7ff);
+		if (unlikely(*table & _REGION_ENTRY_INV)) {
+			address = (address + PMD_SIZE) & PMD_MASK;
+			continue;
+		}
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+		table = table + ((address >> 42) & 0x7ff);
+		if (unlikely(*table & _REGION_ENTRY_INV)) {
+			address = (address + PMD_SIZE) & PMD_MASK;
+			continue;
+		}
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+		table = table + ((address >> 31) & 0x7ff);
+		if (unlikely(*table & _REGION_ENTRY_INV)) {
+			address = (address + PMD_SIZE) & PMD_MASK;
+			continue;
+		}
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+		table = table + ((address >> 20) & 0x7ff);
+		if (unlikely(*table & _SEGMENT_ENTRY_INV)) {
+			address = (address + PMD_SIZE) & PMD_MASK;
+			continue;
+		}
+		page = pfn_to_page(*table >> PAGE_SHIFT);
+		mp = (struct gmap_pgtable *) page->index;
+		vma = find_vma(gmap->mm, mp->vmaddr);
+		size = min(to - address, PMD_SIZE - (address & ~PMD_MASK));
+		zap_page_range(vma, mp->vmaddr | (address & ~PMD_MASK),
+			       size, NULL);
+		address = (address + PMD_SIZE) & PMD_MASK;
+	}
+	up_read(&gmap->mm->mmap_sem);
+}
+EXPORT_SYMBOL_GPL(gmap_discard);
+
 void gmap_unmap_notifier(struct mm_struct *mm, unsigned long *table)
 {
 	struct gmap_rmap *rmap, *next;
@@ -662,8 +732,9 @@
 
 void __tlb_remove_table(void *_table)
 {
-	void *table = (void *)((unsigned long) _table & PAGE_MASK);
-	unsigned type = (unsigned long) _table & ~PAGE_MASK;
+	const unsigned long mask = (FRAG_MASK << 4) | FRAG_MASK;
+	void *table = (void *)((unsigned long) _table & ~mask);
+	unsigned type = (unsigned long) _table & mask;
 
 	if (type)
 		__page_table_free_rcu(table, type);
diff -druN linux-libre-3.1-gnu/arch/s390/mm/vmem.c linux-libre-3.2-gnu/arch/s390/mm/vmem.c
--- linux-libre-3.1-gnu/arch/s390/mm/vmem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/mm/vmem.c	2012-01-04 18:55:44.000000000 -0500
@@ -335,6 +335,9 @@
 	ro_start = ((unsigned long)&_stext) & PAGE_MASK;
 	ro_end = PFN_ALIGN((unsigned long)&_eshared);
 	for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
+		if (memory_chunk[i].type == CHUNK_CRASHK ||
+		    memory_chunk[i].type == CHUNK_OLDMEM)
+			continue;
 		start = memory_chunk[i].addr;
 		end = memory_chunk[i].addr + memory_chunk[i].size;
 		if (start >= ro_end || end <= ro_start)
@@ -368,6 +371,9 @@
 	for (i = 0; i < MEMORY_CHUNKS; i++) {
 		if (!memory_chunk[i].size)
 			continue;
+		if (memory_chunk[i].type == CHUNK_CRASHK ||
+		    memory_chunk[i].type == CHUNK_OLDMEM)
+			continue;
 		seg = kzalloc(sizeof(*seg), GFP_KERNEL);
 		if (!seg)
 			panic("Out of memory...\n");
diff -druN linux-libre-3.1-gnu/arch/s390/oprofile/hwsampler.c linux-libre-3.2-gnu/arch/s390/oprofile/hwsampler.c
--- linux-libre-3.1-gnu/arch/s390/oprofile/hwsampler.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/oprofile/hwsampler.c	2012-01-04 18:55:44.000000000 -0500
@@ -994,7 +994,7 @@
  *
  * Returns 0 on success, !0 on failure.
  */
-int hwsampler_deallocate()
+int hwsampler_deallocate(void)
 {
 	int rc;
 
@@ -1035,7 +1035,7 @@
 	return cb->sample_overflow;
 }
 
-int hwsampler_setup()
+int hwsampler_setup(void)
 {
 	int rc;
 	int cpu;
@@ -1102,7 +1102,7 @@
 	return rc;
 }
 
-int hwsampler_shutdown()
+int hwsampler_shutdown(void)
 {
 	int rc;
 
@@ -1203,7 +1203,7 @@
  *
  * Returns 0 on success, !0 on failure.
  */
-int hwsampler_stop_all()
+int hwsampler_stop_all(void)
 {
 	int tmp_rc, rc, cpu;
 	struct hws_cpu_buffer *cb;
diff -druN linux-libre-3.1-gnu/arch/s390/oprofile/init.c linux-libre-3.2-gnu/arch/s390/oprofile/init.c
--- linux-libre-3.1-gnu/arch/s390/oprofile/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/s390/oprofile/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -88,7 +88,7 @@
 		return -EINVAL;
 
 	retval = oprofilefs_ulong_from_user(&val, buf, count);
-	if (retval)
+	if (retval <= 0)
 		return retval;
 
 	if (oprofile_started)
diff -druN linux-libre-3.1-gnu/arch/score/Kconfig linux-libre-3.2-gnu/arch/score/Kconfig
--- linux-libre-3.1-gnu/arch/score/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/score/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -52,16 +52,6 @@
 config GENERIC_CLOCKEVENTS
 	def_bool y
 
-config SCHED_NO_NO_OMIT_FRAME_POINTER
-	def_bool y
-
-config GENERIC_SYSCALL_TABLE
-	def_bool y
-
-config SCORE_L1_CACHE_SHIFT
-	int
-	default "4"
-
 menu "Kernel type"
 
 config 32BIT
@@ -96,15 +86,6 @@
 
 source "init/Kconfig"
 
-config PROBE_INITRD_HEADER
-	bool "Probe initrd header created by addinitrd"
-	depends on BLK_DEV_INITRD
-	help
-	  Probe initrd header at the last page of kernel image.
-	  Say Y here if you are using arch/score/boot/addinitrd.c to
-	  add initrd or initramfs image to the kernel image.
-	  Otherwise, say N.
-
 config MMU
 	def_bool y
 
diff -druN linux-libre-3.1-gnu/arch/sh/boards/board-espt.c linux-libre-3.2-gnu/arch/sh/boards/board-espt.c
--- linux-libre-3.1-gnu/arch/sh/boards/board-espt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/boards/board-espt.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,9 +13,9 @@
 #include <linux/interrupt.h>
 #include <linux/mtd/physmap.h>
 #include <linux/io.h>
+#include <linux/sh_eth.h>
 #include <asm/machvec.h>
 #include <asm/sizes.h>
-#include <asm/sh_eth.h>
 
 /* NOR Flash */
 static struct mtd_partition espt_nor_flash_partitions[] = {
diff -druN linux-libre-3.1-gnu/arch/sh/boards/board-secureedge5410.c linux-libre-3.2-gnu/arch/sh/boards/board-secureedge5410.c
--- linux-libre-3.1-gnu/arch/sh/boards/board-secureedge5410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/boards/board-secureedge5410.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,8 +41,7 @@
 	printk("SnapGear: EraseConfig init\n");
 
 	/* Setup "EraseConfig" switch on external IRQ 0 */
-	if (request_irq(irq, eraseconfig_interrupt, IRQF_DISABLED,
-				"Erase Config", NULL))
+	if (request_irq(irq, eraseconfig_interrupt, 0, "Erase Config", NULL))
 		printk("SnapGear: failed to register IRQ%d for Reset witch\n",
 				irq);
 	else
diff -druN linux-libre-3.1-gnu/arch/sh/boards/board-sh7757lcr.c linux-libre-3.2-gnu/arch/sh/boards/board-sh7757lcr.c
--- linux-libre-3.1-gnu/arch/sh/boards/board-sh7757lcr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/boards/board-sh7757lcr.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,8 +18,8 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mmcif.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/sh_eth.h>
 #include <cpu/sh7757.h>
-#include <asm/sh_eth.h>
 #include <asm/heartbeat.h>
 
 static struct resource heartbeat_resource = {
@@ -50,9 +50,9 @@
 #define GBECONT		0xffc10100
 #define GBECONT_RMII1	BIT(17)
 #define GBECONT_RMII0	BIT(16)
-static void sh7757_eth_set_mdio_gate(unsigned long addr)
+static void sh7757_eth_set_mdio_gate(void *addr)
 {
-	if ((addr & 0x00000fff) < 0x0800)
+	if (((unsigned long)addr & 0x00000fff) < 0x0800)
 		writel(readl(GBECONT) | GBECONT_RMII0, GBECONT);
 	else
 		writel(readl(GBECONT) | GBECONT_RMII1, GBECONT);
@@ -116,9 +116,9 @@
 	},
 };
 
-static void sh7757_eth_giga_set_mdio_gate(unsigned long addr)
+static void sh7757_eth_giga_set_mdio_gate(void *addr)
 {
-	if ((addr & 0x00000fff) < 0x0800) {
+	if (((unsigned long)addr & 0x00000fff) < 0x0800) {
 		gpio_set_value(GPIO_PTT4, 1);
 		writel(readl(GBECONT) & ~GBECONT_RMII0, GBECONT);
 	} else {
@@ -210,8 +210,12 @@
 };
 
 static struct sh_mmcif_dma sh7757lcr_mmcif_dma = {
-	.chan_priv_tx	= SHDMA_SLAVE_MMCIF_TX,
-	.chan_priv_rx	= SHDMA_SLAVE_MMCIF_RX,
+	.chan_priv_tx	= {
+		.slave_id = SHDMA_SLAVE_MMCIF_TX,
+	},
+	.chan_priv_rx	= {
+		.slave_id = SHDMA_SLAVE_MMCIF_RX,
+	}
 };
 
 static struct sh_mmcif_plat_data sh_mmcif_plat = {
diff -druN linux-libre-3.1-gnu/arch/sh/boards/mach-ap325rxa/setup.c linux-libre-3.2-gnu/arch/sh/boards/mach-ap325rxa/setup.c
--- linux-libre-3.1-gnu/arch/sh/boards/mach-ap325rxa/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/boards/mach-ap325rxa/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -345,9 +345,10 @@
 		.width = 640,
 		.height = 480,
 	},
-	.bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
-	SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8 |
-	SOCAM_DATA_ACTIVE_HIGH,
+	.mbus_param = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+	V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+	V4L2_MBUS_DATA_ACTIVE_HIGH,
+	.mbus_type = V4L2_MBUS_PARALLEL,
 	.set_capture = camera_set_capture,
 };
 
@@ -501,8 +502,7 @@
 };
 
 static struct ov772x_camera_info ov7725_info = {
-	.flags		= OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP | \
-			  OV772X_FLAG_8BIT,
+	.flags		= OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP,
 	.edgectrl	= OV772X_AUTO_EDGECTRL(0xf, 0),
 };
 
diff -druN linux-libre-3.1-gnu/arch/sh/boards/mach-cayman/irq.c linux-libre-3.2-gnu/arch/sh/boards/mach-cayman/irq.c
--- linux-libre-3.1-gnu/arch/sh/boards/mach-cayman/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/boards/mach-cayman/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,13 +46,11 @@
 static struct irqaction cayman_action_smsc = {
 	.name		= "Cayman SMSC Mux",
 	.handler	= cayman_interrupt_smsc,
-	.flags		= IRQF_DISABLED,
 };
 
 static struct irqaction cayman_action_pci2 = {
 	.name		= "Cayman PCI2 Mux",
 	.handler	= cayman_interrupt_pci2,
-	.flags		= IRQF_DISABLED,
 };
 
 static void enable_cayman_irq(struct irq_data *data)
diff -druN linux-libre-3.1-gnu/arch/sh/boards/mach-ecovec24/setup.c linux-libre-3.2-gnu/arch/sh/boards/mach-ecovec24/setup.c
--- linux-libre-3.1-gnu/arch/sh/boards/mach-ecovec24/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/boards/mach-ecovec24/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,13 +28,13 @@
 #include <linux/spi/mmc_spi.h>
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
+#include <linux/sh_eth.h>
 #include <video/sh_mobile_lcdc.h>
 #include <sound/sh_fsi.h>
 #include <media/sh_mobile_ceu.h>
 #include <media/tw9910.h>
 #include <media/mt9t112.h>
 #include <asm/heartbeat.h>
-#include <asm/sh_eth.h>
 #include <asm/clock.h>
 #include <asm/suspend.h>
 #include <cpu/sh7724.h>
@@ -248,6 +248,10 @@
 	.driver_param = {
 		.buswait_bwait		= 4,
 		.detection_delay	= 5,
+		.d0_tx_id = SHDMA_SLAVE_USB1D0_TX,
+		.d0_rx_id = SHDMA_SLAVE_USB1D0_RX,
+		.d1_tx_id = SHDMA_SLAVE_USB1D1_TX,
+		.d1_rx_id = SHDMA_SLAVE_USB1D1_RX,
 	},
 };
 
diff -druN linux-libre-3.1-gnu/arch/sh/boards/mach-hp6xx/hp6xx_apm.c linux-libre-3.2-gnu/arch/sh/boards/mach-hp6xx/hp6xx_apm.c
--- linux-libre-3.1-gnu/arch/sh/boards/mach-hp6xx/hp6xx_apm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/boards/mach-hp6xx/hp6xx_apm.c	2012-01-04 18:55:44.000000000 -0500
@@ -86,7 +86,7 @@
 	int ret;
 
 	ret = request_irq(HP680_BTN_IRQ, hp6x0_apm_interrupt,
-			  IRQF_DISABLED, MODNAME, NULL);
+			  0, MODNAME, NULL);
 	if (unlikely(ret < 0)) {
 		printk(KERN_ERR MODNAME ": IRQ %d request failed\n",
 		       HP680_BTN_IRQ);
diff -druN linux-libre-3.1-gnu/arch/sh/boards/mach-migor/setup.c linux-libre-3.2-gnu/arch/sh/boards/mach-migor/setup.c
--- linux-libre-3.1-gnu/arch/sh/boards/mach-migor/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/boards/mach-migor/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -448,9 +448,7 @@
 	},
 };
 
-static struct ov772x_camera_info ov7725_info = {
-	.flags		= OV772X_FLAG_8BIT,
-};
+static struct ov772x_camera_info ov7725_info;
 
 static struct soc_camera_link ov7725_link = {
 	.power		= ov7725_power,
diff -druN linux-libre-3.1-gnu/arch/sh/boards/mach-se/7724/setup.c linux-libre-3.2-gnu/arch/sh/boards/mach-se/7724/setup.c
--- linux-libre-3.1-gnu/arch/sh/boards/mach-se/7724/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/boards/mach-se/7724/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,12 +23,12 @@
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
 #include <linux/usb/r8a66597.h>
+#include <linux/sh_eth.h>
 #include <video/sh_mobile_lcdc.h>
 #include <media/sh_mobile_ceu.h>
 #include <sound/sh_fsi.h>
 #include <asm/io.h>
 #include <asm/heartbeat.h>
-#include <asm/sh_eth.h>
 #include <asm/clock.h>
 #include <asm/suspend.h>
 #include <cpu/sh7724.h>
diff -druN linux-libre-3.1-gnu/arch/sh/boards/mach-sh7763rdp/setup.c linux-libre-3.2-gnu/arch/sh/boards/mach-sh7763rdp/setup.c
--- linux-libre-3.1-gnu/arch/sh/boards/mach-sh7763rdp/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/boards/mach-sh7763rdp/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,8 +17,8 @@
 #include <linux/mtd/physmap.h>
 #include <linux/fb.h>
 #include <linux/io.h>
+#include <linux/sh_eth.h>
 #include <mach/sh7763rdp.h>
-#include <asm/sh_eth.h>
 #include <asm/sh7760fb.h>
 
 /* NOR Flash */
diff -druN linux-libre-3.1-gnu/arch/sh/boot/Makefile linux-libre-3.2-gnu/arch/sh/boot/Makefile
--- linux-libre-3.1-gnu/arch/sh/boot/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/boot/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 CONFIG_BOOT_LINK_OFFSET	?= 0x00800000
 CONFIG_ZERO_PAGE_OFFSET	?= 0x00001000
 CONFIG_ENTRY_OFFSET	?= 0x00001000
+CONFIG_PHYSICAL_START	?= $(CONFIG_MEMORY_START)
 
 suffix-y := bin
 suffix-$(CONFIG_KERNEL_GZIP)	:= gz
@@ -48,7 +49,7 @@
 	$(Q)$(MAKE) $(build)=$(obj)/romimage $@
 
 KERNEL_MEMORY	:= $(shell /bin/bash -c 'printf "0x%08x" \
-		     $$[$(CONFIG_MEMORY_START) & 0x1fffffff]')
+		     $$[$(CONFIG_PHYSICAL_START) & 0x1fffffff]')
 
 KERNEL_LOAD	:= $(shell /bin/bash -c 'printf "0x%08x" \
 		     $$[$(CONFIG_PAGE_OFFSET)  + \
@@ -114,4 +115,5 @@
 	@echo '  Image $@ is ready'
 
 export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \
-       CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET KERNEL_MEMORY suffix-y
+       CONFIG_PHYSICAL_START CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET \
+       KERNEL_MEMORY suffix-y
diff -druN linux-libre-3.1-gnu/arch/sh/drivers/dma/dmabrg.c linux-libre-3.2-gnu/arch/sh/drivers/dma/dmabrg.c
--- linux-libre-3.1-gnu/arch/sh/drivers/dma/dmabrg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/drivers/dma/dmabrg.c	2012-01-04 18:55:44.000000000 -0500
@@ -174,17 +174,17 @@
 	or = __raw_readl(DMAOR);
 	__raw_writel(or | DMAOR_BRG | DMAOR_DMEN, DMAOR);
 
-	ret = request_irq(DMABRGI0, dmabrg_irq, IRQF_DISABLED,
+	ret = request_irq(DMABRGI0, dmabrg_irq, 0,
 			"DMABRG USB address error", NULL);
 	if (ret)
 		goto out0;
 
-	ret = request_irq(DMABRGI1, dmabrg_irq, IRQF_DISABLED,
+	ret = request_irq(DMABRGI1, dmabrg_irq, 0,
 			"DMABRG Transfer End", NULL);
 	if (ret)
 		goto out1;
 
-	ret = request_irq(DMABRGI2, dmabrg_irq, IRQF_DISABLED,
+	ret = request_irq(DMABRGI2, dmabrg_irq, 0,
 			"DMABRG Transfer Half", NULL);
 	if (ret == 0)
 		return ret;
diff -druN linux-libre-3.1-gnu/arch/sh/drivers/dma/dma-g2.c linux-libre-3.2-gnu/arch/sh/drivers/dma/dma-g2.c
--- linux-libre-3.1-gnu/arch/sh/drivers/dma/dma-g2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/drivers/dma/dma-g2.c	2012-01-04 18:55:44.000000000 -0500
@@ -170,7 +170,7 @@
 {
 	int ret;
 
-	ret = request_irq(HW_EVENT_G2_DMA, g2_dma_interrupt, IRQF_DISABLED,
+	ret = request_irq(HW_EVENT_G2_DMA, g2_dma_interrupt, 0,
 			  "g2 DMA handler", &g2_dma_info);
 	if (unlikely(ret))
 		return -EINVAL;
diff -druN linux-libre-3.1-gnu/arch/sh/drivers/dma/dma-pvr2.c linux-libre-3.2-gnu/arch/sh/drivers/dma/dma-pvr2.c
--- linux-libre-3.1-gnu/arch/sh/drivers/dma/dma-pvr2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/drivers/dma/dma-pvr2.c	2012-01-04 18:55:44.000000000 -0500
@@ -70,7 +70,6 @@
 static struct irqaction pvr2_dma_irq = {
 	.name		= "pvr2 DMA handler",
 	.handler	= pvr2_dma_interrupt,
-	.flags		= IRQF_DISABLED,
 };
 
 static struct dma_ops pvr2_dma_ops = {
diff -druN linux-libre-3.1-gnu/arch/sh/drivers/dma/dma-sh.c linux-libre-3.2-gnu/arch/sh/drivers/dma/dma-sh.c
--- linux-libre-3.1-gnu/arch/sh/drivers/dma/dma-sh.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/drivers/dma/dma-sh.c	2012-01-04 18:55:44.000000000 -0500
@@ -95,7 +95,7 @@
 #if defined(CONFIG_SH_DMA_IRQ_MULTI)
 				IRQF_SHARED,
 #else
-				IRQF_DISABLED,
+				0,
 #endif
 				chan->dev_id, chan);
 }
@@ -305,7 +305,7 @@
 #if defined(CONFIG_SH_DMA_IRQ_MULTI)
 				IRQF_SHARED,
 #else
-				IRQF_DISABLED,
+				0,
 #endif
 				dmae_name[n], (void *)dmae_name[n]);
 		if (unlikely(i < 0)) {
diff -druN linux-libre-3.1-gnu/arch/sh/drivers/dma/dma-sysfs.c linux-libre-3.2-gnu/arch/sh/drivers/dma/dma-sysfs.c
--- linux-libre-3.1-gnu/arch/sh/drivers/dma/dma-sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/drivers/dma/dma-sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/stat.h>
 #include <linux/sysdev.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
diff -druN linux-libre-3.1-gnu/arch/sh/drivers/pci/pci.c linux-libre-3.2-gnu/arch/sh/drivers/pci/pci.c
--- linux-libre-3.1-gnu/arch/sh/drivers/pci/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/drivers/pci/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/io.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
+#include <linux/export.h>
 
 unsigned long PCIBIOS_MIN_IO = 0x0000;
 unsigned long PCIBIOS_MIN_MEM = 0;
diff -druN linux-libre-3.1-gnu/arch/sh/drivers/pci/pci-sh5.c linux-libre-3.2-gnu/arch/sh/drivers/pci/pci-sh5.c
--- linux-libre-3.1-gnu/arch/sh/drivers/pci/pci-sh5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/drivers/pci/pci-sh5.c	2012-01-04 18:55:44.000000000 -0500
@@ -107,13 +107,13 @@
 	u32 uval;
 
         if (request_irq(IRQ_ERR, pcish5_err_irq,
-                        IRQF_DISABLED, "PCI Error",NULL) < 0) {
+                        0, "PCI Error",NULL) < 0) {
                 printk(KERN_ERR "PCISH5: Cannot hook PCI_PERR interrupt\n");
                 return -EINVAL;
         }
 
         if (request_irq(IRQ_SERR, pcish5_serr_irq,
-                        IRQF_DISABLED, "PCI SERR interrupt", NULL) < 0) {
+                        0, "PCI SERR interrupt", NULL) < 0) {
                 printk(KERN_ERR "PCISH5: Cannot hook PCI_SERR interrupt\n");
                 return -EINVAL;
         }
diff -druN linux-libre-3.1-gnu/arch/sh/drivers/pci/pci-sh7780.c linux-libre-3.2-gnu/arch/sh/drivers/pci/pci-sh7780.c
--- linux-libre-3.1-gnu/arch/sh/drivers/pci/pci-sh7780.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/drivers/pci/pci-sh7780.c	2012-01-04 18:55:44.000000000 -0500
@@ -172,7 +172,7 @@
 		     PCI_STATUS_SIG_TARGET_ABORT | \
 		     PCI_STATUS_PARITY, hose->reg_base + PCI_STATUS);
 
-	ret = request_irq(hose->serr_irq, sh7780_pci_serr_irq, IRQF_DISABLED,
+	ret = request_irq(hose->serr_irq, sh7780_pci_serr_irq, 0,
 			  "PCI SERR interrupt", hose);
 	if (unlikely(ret)) {
 		printk(KERN_ERR "PCI: Failed hooking SERR IRQ\n");
diff -druN linux-libre-3.1-gnu/arch/sh/drivers/push-switch.c linux-libre-3.2-gnu/arch/sh/drivers/push-switch.c
--- linux-libre-3.1-gnu/arch/sh/drivers/push-switch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/drivers/push-switch.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,7 +63,7 @@
 	BUG_ON(!psw_info);
 
 	ret = request_irq(irq, psw_info->irq_handler,
-			  IRQF_DISABLED | psw_info->irq_flags,
+			  psw_info->irq_flags,
 			  psw_info->name ? psw_info->name : DRV_NAME, pdev);
 	if (unlikely(ret < 0))
 		goto err;
diff -druN linux-libre-3.1-gnu/arch/sh/include/asm/page.h linux-libre-3.2-gnu/arch/sh/include/asm/page.h
--- linux-libre-3.1-gnu/arch/sh/include/asm/page.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/include/asm/page.h	2012-01-04 18:55:44.000000000 -0500
@@ -113,6 +113,16 @@
 #define __MEMORY_SIZE		CONFIG_MEMORY_SIZE
 
 /*
+ * PHYSICAL_OFFSET is the offset in physical memory where the base
+ * of the kernel is loaded.
+ */
+#ifdef CONFIG_PHYSICAL_START
+#define PHYSICAL_OFFSET (CONFIG_PHYSICAL_START - __MEMORY_START)
+#else
+#define PHYSICAL_OFFSET 0
+#endif
+
+/*
  * PAGE_OFFSET is the virtual address of the start of kernel address
  * space.
  */
@@ -141,8 +151,13 @@
 #endif /* !__ASSEMBLY__ */
 
 #ifdef CONFIG_UNCACHED_MAPPING
+#if defined(CONFIG_29BIT)
+#define UNCAC_ADDR(addr)	P2SEGADDR(addr)
+#define CAC_ADDR(addr)		P1SEGADDR(addr)
+#else
 #define UNCAC_ADDR(addr)	((addr) - PAGE_OFFSET + uncached_start)
 #define CAC_ADDR(addr)		((addr) - uncached_start + PAGE_OFFSET)
+#endif
 #else
 #define UNCAC_ADDR(addr)	((addr))
 #define CAC_ADDR(addr)		((addr))
diff -druN linux-libre-3.1-gnu/arch/sh/include/asm/sh_eth.h linux-libre-3.2-gnu/arch/sh/include/asm/sh_eth.h
--- linux-libre-3.1-gnu/arch/sh/include/asm/sh_eth.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/include/asm/sh_eth.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,25 +0,0 @@
-#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;
-	unsigned ether_link_active_low:1;
-};
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/sh/include/asm/unistd_32.h linux-libre-3.2-gnu/arch/sh/include/asm/unistd_32.h
--- linux-libre-3.1-gnu/arch/sh/include/asm/unistd_32.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/include/asm/unistd_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -375,8 +375,10 @@
 #define __NR_syncfs		362
 #define __NR_sendmmsg		363
 #define __NR_setns		364
+#define __NR_process_vm_readv	365
+#define __NR_process_vm_writev	366
 
-#define NR_syscalls 365
+#define NR_syscalls 367
 
 #ifdef __KERNEL__
 
diff -druN linux-libre-3.1-gnu/arch/sh/include/asm/unistd_64.h linux-libre-3.2-gnu/arch/sh/include/asm/unistd_64.h
--- linux-libre-3.1-gnu/arch/sh/include/asm/unistd_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/include/asm/unistd_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -396,10 +396,12 @@
 #define __NR_syncfs		373
 #define __NR_sendmmsg		374
 #define __NR_setns		375
+#define __NR_process_vm_readv	376
+#define __NR_process_vm_writev	377
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 376
+#define NR_syscalls 378
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff -druN linux-libre-3.1-gnu/arch/sh/Kconfig linux-libre-3.2-gnu/arch/sh/Kconfig
--- linux-libre-3.1-gnu/arch/sh/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -101,10 +101,6 @@
 	def_bool y
 	depends on SMP && PREEMPT
 
-config SYS_SUPPORTS_PM
-	bool
-	depends on !SMP
-
 config ARCH_SUSPEND_POSSIBLE
 	def_bool n
 
@@ -649,7 +645,7 @@
 	  a specially reserved region and then later executed after
 	  a crash by kdump/kexec. The crash dump kernel must be compiled
 	  to a memory address not used by the main kernel using
-	  MEMORY_START.
+	  PHYSICAL_START.
 
 	  For more details see Documentation/kdump/kdump.txt
 
@@ -660,6 +656,17 @@
 	  Jump between original kernel and kexeced kernel and invoke
 	  code via KEXEC
 
+config PHYSICAL_START
+	hex "Physical address where the kernel is loaded" if (EXPERT || CRASH_DUMP)
+	default MEMORY_START
+	---help---
+	  This gives the physical address where the kernel is loaded
+	  and is ordinarily the same as MEMORY_START.
+
+	  Different values are primarily used in the case of kexec on panic
+	  where the fail safe kernel needs to run at a different address
+	  than the panic-ed kernel.
+
 config SECCOMP
 	bool "Enable seccomp to safely compute untrusted bytecode"
 	depends on PROC_FS
diff -druN linux-libre-3.1-gnu/arch/sh/kernel/cpu/sh2a/setup-sh7203.c linux-libre-3.2-gnu/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
--- linux-libre-3.1-gnu/arch/sh/kernel/cpu/sh2a/setup-sh7203.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/kernel/cpu/sh2a/setup-sh7203.c	2012-01-04 18:55:44.000000000 -0500
@@ -176,10 +176,12 @@
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xfffe8000,
 	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+			  SCSCR_REIE,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		=  { 192, 192, 192, 192 },
+	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -193,10 +195,12 @@
 static struct plat_sci_port scif1_platform_data = {
 	.mapbase	= 0xfffe8800,
 	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+			  SCSCR_REIE,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		=  { 196, 196, 196, 196 },
+	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -210,10 +214,12 @@
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase	= 0xfffe9000,
 	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+			  SCSCR_REIE,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		=  { 200, 200, 200, 200 },
+	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
@@ -227,10 +233,12 @@
 static struct plat_sci_port scif3_platform_data = {
 	.mapbase	= 0xfffe9800,
 	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+			  SCSCR_REIE,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
 	.irqs		=  { 204, 204, 204, 204 },
+	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif3_device = {
diff -druN linux-libre-3.1-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7757.c linux-libre-3.2-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
--- linux-libre-3.1-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7757.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7757.c	2012-01-04 18:55:44.000000000 -0500
@@ -113,7 +113,14 @@
 
 	/* MSTP32 clocks */
 	CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP004]),
-	CLKDEV_CON_ID("riic", &mstp_clks[MSTP000]),
+	CLKDEV_CON_ID("riic0", &mstp_clks[MSTP000]),
+	CLKDEV_CON_ID("riic1", &mstp_clks[MSTP000]),
+	CLKDEV_CON_ID("riic2", &mstp_clks[MSTP000]),
+	CLKDEV_CON_ID("riic3", &mstp_clks[MSTP000]),
+	CLKDEV_CON_ID("riic4", &mstp_clks[MSTP000]),
+	CLKDEV_CON_ID("riic5", &mstp_clks[MSTP000]),
+	CLKDEV_CON_ID("riic6", &mstp_clks[MSTP000]),
+	CLKDEV_CON_ID("riic7", &mstp_clks[MSTP000]),
 
 	CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[MSTP113]),
 	CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[MSTP114]),
@@ -121,6 +128,7 @@
 	CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP111]),
 	CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP110]),
 
+	CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP103]),
 	CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]),
 	CLKDEV_CON_ID("mmc0", &mstp_clks[MSTP220]),
 };
diff -druN linux-libre-3.1-gnu/arch/sh/kernel/cpu/sh4a/smp-shx3.c linux-libre-3.2-gnu/arch/sh/kernel/cpu/sh4a/smp-shx3.c
--- linux-libre-3.1-gnu/arch/sh/kernel/cpu/sh4a/smp-shx3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/kernel/cpu/sh4a/smp-shx3.c	2012-01-04 18:55:44.000000000 -0500
@@ -79,7 +79,7 @@
 
 	for (i = 0; i < SMP_MSG_NR; i++)
 		request_irq(104 + i, ipi_interrupt_handler,
-			    IRQF_DISABLED | IRQF_PERCPU, "IPI", (void *)(long)i);
+			    IRQF_PERCPU, "IPI", (void *)(long)i);
 
 	for (i = 0; i < max_cpus; i++)
 		set_cpu_present(i, true);
diff -druN linux-libre-3.1-gnu/arch/sh/kernel/cpu/shmobile/cpuidle.c linux-libre-3.2-gnu/arch/sh/kernel/cpu/shmobile/cpuidle.c
--- linux-libre-3.1-gnu/arch/sh/kernel/cpu/shmobile/cpuidle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/kernel/cpu/shmobile/cpuidle.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/io.h>
 #include <linux/suspend.h>
 #include <linux/cpuidle.h>
+#include <linux/export.h>
 #include <asm/suspend.h>
 #include <asm/uaccess.h>
 #include <asm/hwblk.h>
@@ -25,11 +26,12 @@
 };
 
 static int cpuidle_sleep_enter(struct cpuidle_device *dev,
-			       struct cpuidle_state *state)
+				struct cpuidle_driver *drv,
+				int index)
 {
 	unsigned long allowed_mode = arch_hwblk_sleep_mode();
 	ktime_t before, after;
-	int requested_state = state - &dev->states[0];
+	int requested_state = index;
 	int allowed_state;
 	int k;
 
@@ -46,11 +48,13 @@
 	 */
 	k = min_t(int, allowed_state, requested_state);
 
-	dev->last_state = &dev->states[k];
 	before = ktime_get();
 	sh_mobile_call_standby(cpuidle_mode[k]);
 	after = ktime_get();
-	return ktime_to_ns(ktime_sub(after, before)) >> 10;
+
+	dev->last_residency = (int)ktime_to_ns(ktime_sub(after, before)) >> 10;
+
+	return k;
 }
 
 static struct cpuidle_device cpuidle_dev;
@@ -62,19 +66,19 @@
 void sh_mobile_setup_cpuidle(void)
 {
 	struct cpuidle_device *dev = &cpuidle_dev;
+	struct cpuidle_driver *drv = &cpuidle_driver;
 	struct cpuidle_state *state;
 	int i;
 
-	cpuidle_register_driver(&cpuidle_driver);
 
 	for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
-		dev->states[i].name[0] = '\0';
-		dev->states[i].desc[0] = '\0';
+		drv->states[i].name[0] = '\0';
+		drv->states[i].desc[0] = '\0';
 	}
 
 	i = CPUIDLE_DRIVER_STATE_START;
 
-	state = &dev->states[i++];
+	state = &drv->states[i++];
 	snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
 	strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN);
 	state->exit_latency = 1;
@@ -84,10 +88,10 @@
 	state->flags |= CPUIDLE_FLAG_TIME_VALID;
 	state->enter = cpuidle_sleep_enter;
 
-	dev->safe_state = state;
+	drv->safe_state_index = i-1;
 
 	if (sh_mobile_sleep_supported & SUSP_SH_SF) {
-		state = &dev->states[i++];
+		state = &drv->states[i++];
 		snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
 		strncpy(state->desc, "SuperH Sleep Mode [SF]",
 			CPUIDLE_DESC_LEN);
@@ -100,7 +104,7 @@
 	}
 
 	if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) {
-		state = &dev->states[i++];
+		state = &drv->states[i++];
 		snprintf(state->name, CPUIDLE_NAME_LEN, "C3");
 		strncpy(state->desc, "SuperH Mobile Standby Mode [SF]",
 			CPUIDLE_DESC_LEN);
@@ -112,7 +116,10 @@
 		state->enter = cpuidle_sleep_enter;
 	}
 
+	drv->state_count = i;
 	dev->state_count = i;
 
+	cpuidle_register_driver(&cpuidle_driver);
+
 	cpuidle_register_device(dev);
 }
diff -druN linux-libre-3.1-gnu/arch/sh/kernel/perf_event.c linux-libre-3.2-gnu/arch/sh/kernel/perf_event.c
--- linux-libre-3.1-gnu/arch/sh/kernel/perf_event.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/kernel/perf_event.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/perf_event.h>
+#include <linux/export.h>
 #include <asm/processor.h>
 
 struct cpu_hw_events {
diff -druN linux-libre-3.1-gnu/arch/sh/kernel/setup.c linux-libre-3.2-gnu/arch/sh/kernel/setup.c
--- linux-libre-3.1-gnu/arch/sh/kernel/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/kernel/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -211,13 +211,16 @@
 	}
 
 	/*
-	 *  We don't know which RAM region contains kernel data,
-	 *  so we try it repeatedly and let the resource manager
-	 *  test it.
+	 * We don't know which RAM region contains kernel data or
+	 * the reserved crashkernel region, so try it repeatedly
+	 * and let the resource manager test it.
 	 */
 	request_resource(res, &code_resource);
 	request_resource(res, &data_resource);
 	request_resource(res, &bss_resource);
+#ifdef CONFIG_KEXEC
+	request_resource(res, &crashk_res);
+#endif
 
 	/*
 	 * Also make sure that there is a PMB mapping that covers this
diff -druN linux-libre-3.1-gnu/arch/sh/kernel/syscalls_32.S linux-libre-3.2-gnu/arch/sh/kernel/syscalls_32.S
--- linux-libre-3.1-gnu/arch/sh/kernel/syscalls_32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/kernel/syscalls_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -382,3 +382,5 @@
 	.long sys_syncfs
 	.long sys_sendmmsg
 	.long sys_setns
+	.long sys_process_vm_readv	/* 365 */
+	.long sys_process_vm_writev
diff -druN linux-libre-3.1-gnu/arch/sh/kernel/syscalls_64.S linux-libre-3.2-gnu/arch/sh/kernel/syscalls_64.S
--- linux-libre-3.1-gnu/arch/sh/kernel/syscalls_64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/kernel/syscalls_64.S	2012-01-04 18:55:44.000000000 -0500
@@ -402,3 +402,5 @@
 	.long sys_syncfs
 	.long sys_sendmmsg
 	.long sys_setns			/* 375 */
+	.long sys_process_vm_readv
+	.long sys_process_vm_writev
diff -druN linux-libre-3.1-gnu/arch/sh/kernel/topology.c linux-libre-3.2-gnu/arch/sh/kernel/topology.c
--- linux-libre-3.1-gnu/arch/sh/kernel/topology.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/kernel/topology.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,8 +11,10 @@
 #include <linux/cpumask.h>
 #include <linux/init.h>
 #include <linux/percpu.h>
+#include <linux/topology.h>
 #include <linux/node.h>
 #include <linux/nodemask.h>
+#include <linux/export.h>
 
 static DEFINE_PER_CPU(struct cpu, cpu_devices);
 
diff -druN linux-libre-3.1-gnu/arch/sh/kernel/vmlinux.lds.S linux-libre-3.2-gnu/arch/sh/kernel/vmlinux.lds.S
--- linux-libre-3.1-gnu/arch/sh/kernel/vmlinux.lds.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/kernel/vmlinux.lds.S	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,7 @@
 ENTRY(_start)
 SECTIONS
 {
-	. = PAGE_OFFSET + MEMORY_OFFSET + CONFIG_ZERO_PAGE_OFFSET;
+	. = PAGE_OFFSET + MEMORY_OFFSET + PHYSICAL_OFFSET + CONFIG_ZERO_PAGE_OFFSET;
 
 	_text = .;		/* Text and read-only data */
 
diff -druN linux-libre-3.1-gnu/arch/sh/Makefile linux-libre-3.2-gnu/arch/sh/Makefile
--- linux-libre-3.1-gnu/arch/sh/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -80,6 +80,7 @@
 defaultimage-$(CONFIG_SH_URQUELL)		:= uImage
 defaultimage-$(CONFIG_SH_MIGOR)			:= uImage
 defaultimage-$(CONFIG_SH_AP325RXA)		:= uImage
+defaultimage-$(CONFIG_SH_SH7757LCR)		:= uImage
 defaultimage-$(CONFIG_SH_7724_SOLUTION_ENGINE)	:= uImage
 defaultimage-$(CONFIG_SH_7206_SOLUTION_ENGINE)	:= vmlinux
 defaultimage-$(CONFIG_SH_7619_SOLUTION_ENGINE)	:= vmlinux
diff -druN linux-libre-3.1-gnu/arch/sh/mm/init.c linux-libre-3.2-gnu/arch/sh/mm/init.c
--- linux-libre-3.1-gnu/arch/sh/mm/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/mm/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <linux/memblock.h>
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 #include <asm/mmu_context.h>
 #include <asm/mmzone.h>
 #include <asm/kexec.h>
@@ -287,6 +288,8 @@
 static void __init early_reserve_mem(void)
 {
 	unsigned long start_pfn;
+	u32 zero_base = (u32)__MEMORY_START + (u32)PHYSICAL_OFFSET;
+	u32 start = zero_base + (u32)CONFIG_ZERO_PAGE_OFFSET;
 
 	/*
 	 * Partially used pages are not usable - thus
@@ -300,15 +303,13 @@
 	 * this catches the (definitely buggy) case of us accidentally
 	 * initializing the bootmem allocator with an invalid RAM area.
 	 */
-	memblock_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
-		    (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) -
-		    (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET));
+	memblock_reserve(start, (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) - start);
 
 	/*
 	 * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
 	 */
 	if (CONFIG_ZERO_PAGE_OFFSET != 0)
-		memblock_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET);
+		memblock_reserve(zero_base, CONFIG_ZERO_PAGE_OFFSET);
 
 	/*
 	 * Handle additional early reservations
diff -druN linux-libre-3.1-gnu/arch/sh/oprofile/common.c linux-libre-3.2-gnu/arch/sh/oprofile/common.c
--- linux-libre-3.1-gnu/arch/sh/oprofile/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sh/oprofile/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,7 +49,7 @@
 	return oprofile_perf_init(ops);
 }
 
-void __exit oprofile_arch_exit(void)
+void oprofile_arch_exit(void)
 {
 	oprofile_perf_exit();
 	kfree(sh_pmu_op_name);
@@ -60,5 +60,5 @@
 	ops->backtrace = sh_backtrace;
 	return -ENODEV;
 }
-void __exit oprofile_arch_exit(void) {}
+void oprofile_arch_exit(void) {}
 #endif /* CONFIG_HW_PERF_EVENTS */
diff -druN linux-libre-3.1-gnu/arch/sparc/include/asm/compat.h linux-libre-3.2-gnu/arch/sparc/include/asm/compat.h
--- linux-libre-3.1-gnu/arch/sparc/include/asm/compat.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/include/asm/compat.h	2012-01-04 18:55:44.000000000 -0500
@@ -134,7 +134,8 @@
 	compat_fsid_t	f_fsid;
 	int		f_namelen;	/* SunOS ignores this field. */
 	int		f_frsize;
-	int		f_spare[5];
+	int		f_flags;
+	int		f_spare[4];
 };
 
 #define COMPAT_RLIM_INFINITY 0x7fffffff
diff -druN linux-libre-3.1-gnu/arch/sparc/include/asm/pgtable_32.h linux-libre-3.2-gnu/arch/sparc/include/asm/pgtable_32.h
--- linux-libre-3.1-gnu/arch/sparc/include/asm/pgtable_32.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/include/asm/pgtable_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -431,10 +431,6 @@
 #define kern_addr_valid(addr) \
 	(test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap))
 
-extern int io_remap_pfn_range(struct vm_area_struct *vma,
-			      unsigned long from, unsigned long pfn,
-			      unsigned long size, pgprot_t prot);
-
 /*
  * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
  * its high 4 bits.  These macros/functions put it there or get it from there.
@@ -443,6 +439,22 @@
 #define GET_IOSPACE(pfn)		(pfn >> (BITS_PER_LONG - 4))
 #define GET_PFN(pfn)			(pfn & 0x0fffffffUL)
 
+extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
+			   unsigned long, pgprot_t);
+
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+				     unsigned long from, unsigned long pfn,
+				     unsigned long size, pgprot_t prot)
+{
+	unsigned long long offset, space, phys_base;
+
+	offset = ((unsigned long long) GET_PFN(pfn)) << PAGE_SHIFT;
+	space = GET_IOSPACE(pfn);
+	phys_base = offset | (space << 32ULL);
+
+	return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
+}
+
 #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
 ({									  \
diff -druN linux-libre-3.1-gnu/arch/sparc/include/asm/pgtable_64.h linux-libre-3.2-gnu/arch/sparc/include/asm/pgtable_64.h
--- linux-libre-3.1-gnu/arch/sparc/include/asm/pgtable_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/include/asm/pgtable_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -757,10 +757,6 @@
 
 extern int page_in_phys_avail(unsigned long paddr);
 
-extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
-			       unsigned long pfn,
-			       unsigned long size, pgprot_t prot);
-
 /*
  * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
  * its high 4 bits.  These macros/functions put it there or get it from there.
@@ -769,6 +765,22 @@
 #define GET_IOSPACE(pfn)		(pfn >> (BITS_PER_LONG - 4))
 #define GET_PFN(pfn)			(pfn & 0x0fffffffffffffffUL)
 
+extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
+			   unsigned long, pgprot_t);
+
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+				     unsigned long from, unsigned long pfn,
+				     unsigned long size, pgprot_t prot)
+{
+	unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
+	int space = GET_IOSPACE(pfn);
+	unsigned long phys_base;
+
+	phys_base = offset | (((unsigned long) space) << 32UL);
+
+	return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
+}
+
 #include <asm-generic/pgtable.h>
 
 /* We provide our own get_unmapped_area to cope with VA holes and
diff -druN linux-libre-3.1-gnu/arch/sparc/include/asm/termios.h linux-libre-3.2-gnu/arch/sparc/include/asm/termios.h
--- linux-libre-3.1-gnu/arch/sparc/include/asm/termios.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/include/asm/termios.h	2012-01-04 18:55:44.000000000 -0500
@@ -40,7 +40,6 @@
 };
 
 #ifdef __KERNEL__
-#include <linux/module.h>
 
 /*
  * c_cc characters in the termio structure.  Oh, how I love being
diff -druN linux-libre-3.1-gnu/arch/sparc/include/asm/unistd.h linux-libre-3.2-gnu/arch/sparc/include/asm/unistd.h
--- linux-libre-3.1-gnu/arch/sparc/include/asm/unistd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/include/asm/unistd.h	2012-01-04 18:55:44.000000000 -0500
@@ -406,8 +406,10 @@
 #define __NR_syncfs		335
 #define __NR_sendmmsg		336
 #define __NR_setns		337
+#define __NR_process_vm_readv	338
+#define __NR_process_vm_writev	339
 
-#define NR_syscalls		338
+#define NR_syscalls		340
 
 #ifdef __32bit_syscall_numbers__
 /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
diff -druN linux-libre-3.1-gnu/arch/sparc/Kconfig linux-libre-3.2-gnu/arch/sparc/Kconfig
--- linux-libre-3.1-gnu/arch/sparc/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -560,12 +560,7 @@
 	  Only choose N if you know in advance that you will not need to modify
 	  OpenPROM settings on the running system.
 
-# Makefile helpers
-config SPARC32_PCI
-	bool
-	default y
-	depends on SPARC32 && PCI
-
+# Makefile helper
 config SPARC64_PCI
 	bool
 	default y
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/apc.c linux-libre-3.2-gnu/arch/sparc/kernel/apc.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/apc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/apc.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/pm.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/module.h>
 
 #include <asm/io.h>
 #include <asm/oplib.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/auxio_32.c linux-libre-3.2-gnu/arch/sparc/kernel/auxio_32.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/auxio_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/auxio_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 #include <linux/spinlock.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/export.h>
 #include <asm/oplib.h>
 #include <asm/io.h>
 #include <asm/auxio.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/btext.c linux-libre-3.2-gnu/arch/sparc/kernel/btext.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/btext.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/btext.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/module.h>
 #include <linux/console.h>
 
 #include <asm/btext.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/central.c linux-libre-3.2-gnu/arch/sparc/kernel/central.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/central.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/central.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/of_device.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/cpu.c linux-libre-3.2-gnu/arch/sparc/kernel/cpu.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 
 #include <linux/seq_file.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/threads.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/cpumap.c linux-libre-3.2-gnu/arch/sparc/kernel/cpumap.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/cpumap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/cpumap.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
  * Copyright (C) 2009 Hong H. Pham <hong.pham@windriver.com>
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/dma.c linux-libre-3.2-gnu/arch/sparc/kernel/dma.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,4 @@
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-debug.h>
 
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/ds.c linux-libre-3.2-gnu/arch/sparc/kernel/ds.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/ds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/ds.c	2012-01-04 18:55:44.000000000 -0500
@@ -1181,13 +1181,11 @@
 
 	dp->rcv_buf_len = 4096;
 
-	dp->ds_states = kzalloc(sizeof(ds_states_template),
-				GFP_KERNEL);
+	dp->ds_states = kmemdup(ds_states_template,
+				sizeof(ds_states_template), GFP_KERNEL);
 	if (!dp->ds_states)
 		goto out_free_rcv_buf;
 
-	memcpy(dp->ds_states, ds_states_template,
-	       sizeof(ds_states_template));
 	dp->num_ds_states = ARRAY_SIZE(ds_states_template);
 
 	for (i = 0; i < dp->num_ds_states; i++)
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/ebus.c linux-libre-3.2-gnu/arch/sparc/kernel/ebus.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/ebus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/ebus.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
  * Copyright (C) 1999  David S. Miller (davem@redhat.com)
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/entry.h linux-libre-3.2-gnu/arch/sparc/kernel/entry.h
--- linux-libre-3.1-gnu/arch/sparc/kernel/entry.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/entry.h	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,9 @@
 extern void fpload(unsigned long *fpregs, unsigned long *fsr);
 
 #else /* CONFIG_SPARC32 */
+
+#include <asm/trap_block.h>
+
 struct popc_3insn_patch_entry {
 	unsigned int	addr;
 	unsigned int	insns[3];
@@ -57,6 +60,10 @@
 	__popc_6insn_patch_end;
 
 extern void __init per_cpu_patch(void);
+extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
+				    struct sun4v_1insn_patch_entry *);
+extern void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
+				    struct sun4v_2insn_patch_entry *);
 extern void __init sun4v_patch(void);
 extern void __init boot_cpu_id_too_large(int cpu);
 extern unsigned int dcache_parity_tl1_occurred;
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/hvapi.c linux-libre-3.2-gnu/arch/sparc/kernel/hvapi.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/hvapi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/hvapi.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
  * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
  */
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 
 #include <asm/hypervisor.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/idprom.c linux-libre-3.2-gnu/arch/sparc/kernel/idprom.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/idprom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/idprom.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/oplib.h>
 #include <asm/idprom.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/iommu.c linux-libre-3.2-gnu/arch/sparc/kernel/iommu.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/device.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/irq_32.c linux-libre-3.2-gnu/arch/sparc/kernel/irq_32.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/irq_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/irq_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
+#include <linux/export.h>
 
 #include <asm/cacheflush.h>
 #include <asm/cpudata.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/irq_64.c linux-libre-3.2-gnu/arch/sparc/kernel/irq_64.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/irq_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/irq_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,6 @@
  * Copyright (C) 1998  Jakub Jelinek    (jj@ultra.linux.cz)
  */
 
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/linkage.h>
 #include <linux/ptrace.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/jump_label.c linux-libre-3.2-gnu/arch/sparc/kernel/jump_label.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/jump_label.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/jump_label.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,12 +36,4 @@
 	put_online_cpus();
 }
 
-void arch_jump_label_text_poke_early(jump_label_t addr)
-{
-	u32 *insn_p = (u32 *) (unsigned long) addr;
-
-	*insn_p = 0x01000000;
-	flushi(insn_p);
-}
-
 #endif
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/ldc.c linux-libre-3.2-gnu/arch/sparc/kernel/ldc.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/ldc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/ldc.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/delay.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/leon_kernel.c linux-libre-3.2-gnu/arch/sparc/kernel/leon_kernel.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/leon_kernel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/leon_kernel.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/leon_pci.c linux-libre-3.2-gnu/arch/sparc/kernel/leon_pci.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/leon_pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/leon_pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/of_device.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/export.h>
 #include <asm/leon.h>
 #include <asm/leon_pci.h>
 
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/leon_pci_grpci2.c linux-libre-3.2-gnu/arch/sparc/kernel/leon_pci_grpci2.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/leon_pci_grpci2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/leon_pci_grpci2.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/io.h>
 #include <asm/leon.h>
 #include <asm/vaddrs.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/mdesc.c linux-libre-3.2-gnu/arch/sparc/kernel/mdesc.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/mdesc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/mdesc.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,11 +11,13 @@
 #include <linux/mm.h>
 #include <linux/miscdevice.h>
 #include <linux/bootmem.h>
+#include <linux/export.h>
 
 #include <asm/cpudata.h>
 #include <asm/hypervisor.h>
 #include <asm/mdesc.h>
 #include <asm/prom.h>
+#include <asm/uaccess.h>
 #include <asm/oplib.h>
 #include <asm/smp.h>
 
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/module.c linux-libre-3.2-gnu/arch/sparc/kernel/module.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/module.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/module.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,8 @@
 #include <asm/processor.h>
 #include <asm/spitfire.h>
 
+#include "entry.h"
+
 #ifdef CONFIG_SPARC64
 
 #include <linux/jump_label.h>
@@ -203,6 +205,29 @@
 }
 
 #ifdef CONFIG_SPARC64
+static void do_patch_sections(const Elf_Ehdr *hdr,
+			      const Elf_Shdr *sechdrs)
+{
+	const Elf_Shdr *s, *sun4v_1insn = NULL, *sun4v_2insn = NULL;
+	char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+	for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
+		if (!strcmp(".sun4v_1insn_patch", secstrings + s->sh_name))
+			sun4v_1insn = s;
+		if (!strcmp(".sun4v_2insn_patch", secstrings + s->sh_name))
+			sun4v_2insn = s;
+	}
+
+	if (sun4v_1insn && tlb_type == hypervisor) {
+		void *p = (void *) sun4v_1insn->sh_addr;
+		sun4v_patch_1insn_range(p, p + sun4v_1insn->sh_size);
+	}
+	if (sun4v_2insn && tlb_type == hypervisor) {
+		void *p = (void *) sun4v_2insn->sh_addr;
+		sun4v_patch_2insn_range(p, p + sun4v_2insn->sh_size);
+	}
+}
+
 int module_finalize(const Elf_Ehdr *hdr,
 		    const Elf_Shdr *sechdrs,
 		    struct module *me)
@@ -210,6 +235,8 @@
 	/* make jump label nops */
 	jump_label_apply_nops(me);
 
+	do_patch_sections(hdr, sechdrs);
+
 	/* Cheetah's I-cache is fully coherent.  */
 	if (tlb_type == spitfire) {
 		unsigned long va;
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/nmi.c linux-libre-3.2-gnu/arch/sparc/kernel/nmi.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/nmi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/nmi.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
 #include <linux/init.h>
 #include <linux/percpu.h>
 #include <linux/nmi.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kprobes.h>
 #include <linux/kernel_stat.h>
 #include <linux/reboot.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/of_device_32.c linux-libre-3.2-gnu/arch/sparc/kernel/of_device_32.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/of_device_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/of_device_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,6 @@
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/init.h>
-#include <linux/module.h>
 #include <linux/mod_devicetable.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/of_device_64.c linux-libre-3.2-gnu/arch/sparc/kernel/of_device_64.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/of_device_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/of_device_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,13 +2,14 @@
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/mod_devicetable.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/irq.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
+#include <asm/spitfire.h>
 
 #include "of_device_common.h"
 
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/of_device_common.c linux-libre-3.2-gnu/arch/sparc/kernel/of_device_common.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/of_device_common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/of_device_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/mod_devicetable.h>
 #include <linux/errno.h>
 #include <linux/irq.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/pci.c linux-libre-3.2-gnu/arch/sparc/kernel/pci.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
  * with minor modifications, see there for credits.
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/sched.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/pcic.c linux-libre-3.2-gnu/arch/sparc/kernel/pcic.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/pcic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/pcic.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/time.h>
 #include <linux/timex.h>
 #include <linux/interrupt.h>
+#include <linux/export.h>
 
 #include <asm/irq.h>
 #include <asm/oplib.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/pci_fire.c linux-libre-3.2-gnu/arch/sparc/kernel/pci_fire.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/pci_fire.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/pci_fire.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/msi.h>
+#include <linux/export.h>
 #include <linux/irq.h>
 #include <linux/of_device.h>
 
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/pci_psycho.c linux-libre-3.2-gnu/arch/sparc/kernel/pci_psycho.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/pci_psycho.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/pci_psycho.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/of_device.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/pci_sabre.c linux-libre-3.2-gnu/arch/sparc/kernel/pci_sabre.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/pci_sabre.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/pci_sabre.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/of_device.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/pci_schizo.c linux-libre-3.2-gnu/arch/sparc/kernel/pci_schizo.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/pci_schizo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/pci_schizo.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/of_device.h>
 
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/pci_sun4v.c linux-libre-3.2-gnu/arch/sparc/kernel/pci_sun4v.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/pci_sun4v.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/pci_sun4v.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/percpu.h>
 #include <linux/irq.h>
 #include <linux/msi.h>
+#include <linux/export.h>
 #include <linux/log2.h>
 #include <linux/of_device.h>
 
@@ -848,10 +849,10 @@
 	if (!irq)
 		return -ENOMEM;
 
-	if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE))
-		return -EINVAL;
 	if (pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_VALID))
 		return -EINVAL;
+	if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE))
+		return -EINVAL;
 
 	return irq;
 }
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/pcr.c linux-libre-3.2-gnu/arch/sparc/kernel/pcr.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/pcr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/pcr.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
  * Copyright (C) 2009 David S. Miller (davem@davemloft.net)
  */
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/irq.h>
 
@@ -13,6 +13,7 @@
 #include <asm/pil.h>
 #include <asm/pcr.h>
 #include <asm/nmi.h>
+#include <asm/spitfire.h>
 
 /* This code is shared between various users of the performance
  * counters.  Users will be oprofile, pseudo-NMI watchdog, and the
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/pmc.c linux-libre-3.2-gnu/arch/sparc/kernel/pmc.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/pmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/pmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/pm.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/module.h>
 
 #include <asm/io.h>
 #include <asm/oplib.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/power.c linux-libre-3.2-gnu/arch/sparc/kernel/power.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/power.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/power.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/reboot.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/process_64.c linux-libre-3.2-gnu/arch/sparc/kernel/process_64.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/process_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/process_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,7 @@
 #include <stdarg.h>
 
 #include <linux/errno.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/prom_32.c linux-libre-3.2-gnu/arch/sparc/kernel/prom_32.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/prom_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/prom_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,6 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
-#include <linux/module.h>
 
 #include <asm/prom.h>
 #include <asm/oplib.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/prom_64.c linux-libre-3.2-gnu/arch/sparc/kernel/prom_64.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/prom_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/prom_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,6 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/module.h>
 #include <linux/memblock.h>
 #include <linux/of.h>
 
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/prom_common.c linux-libre-3.2-gnu/arch/sparc/kernel/prom_common.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/prom_common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/prom_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/errno.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
@@ -58,12 +58,10 @@
 	void *new_val;
 	int err;
 
-	new_val = kmalloc(len, GFP_KERNEL);
+	new_val = kmemdup(val, len, GFP_KERNEL);
 	if (!new_val)
 		return -ENOMEM;
 
-	memcpy(new_val, val, len);
-
 	err = -ENODEV;
 
 	mutex_lock(&of_set_property_mutex);
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/reboot.c linux-libre-3.2-gnu/arch/sparc/kernel/reboot.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/reboot.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/reboot.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/reboot.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/pm.h>
 
 #include <asm/system.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/sbus.c linux-libre-3.2-gnu/arch/sparc/kernel/sbus.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/sbus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/sbus.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/of.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/setup_32.c linux-libre-3.2-gnu/arch/sparc/kernel/setup_32.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/setup_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/setup_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/root_dev.h>
 #include <linux/cpu.h>
 #include <linux/kdebug.h>
+#include <linux/export.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/setup_64.c linux-libre-3.2-gnu/arch/sparc/kernel/setup_64.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/setup_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/setup_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -234,40 +234,50 @@
 	}
 }
 
-void __init sun4v_patch(void)
+void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *start,
+			     struct sun4v_1insn_patch_entry *end)
 {
-	extern void sun4v_hvapi_init(void);
-	struct sun4v_1insn_patch_entry *p1;
-	struct sun4v_2insn_patch_entry *p2;
-
-	if (tlb_type != hypervisor)
-		return;
-
-	p1 = &__sun4v_1insn_patch;
-	while (p1 < &__sun4v_1insn_patch_end) {
-		unsigned long addr = p1->addr;
+	while (start < end) {
+		unsigned long addr = start->addr;
 
-		*(unsigned int *) (addr +  0) = p1->insn;
+		*(unsigned int *) (addr +  0) = start->insn;
 		wmb();
 		__asm__ __volatile__("flush	%0" : : "r" (addr +  0));
 
-		p1++;
+		start++;
 	}
+}
 
-	p2 = &__sun4v_2insn_patch;
-	while (p2 < &__sun4v_2insn_patch_end) {
-		unsigned long addr = p2->addr;
+void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
+			     struct sun4v_2insn_patch_entry *end)
+{
+	while (start < end) {
+		unsigned long addr = start->addr;
 
-		*(unsigned int *) (addr +  0) = p2->insns[0];
+		*(unsigned int *) (addr +  0) = start->insns[0];
 		wmb();
 		__asm__ __volatile__("flush	%0" : : "r" (addr +  0));
 
-		*(unsigned int *) (addr +  4) = p2->insns[1];
+		*(unsigned int *) (addr +  4) = start->insns[1];
 		wmb();
 		__asm__ __volatile__("flush	%0" : : "r" (addr +  4));
 
-		p2++;
+		start++;
 	}
+}
+
+void __init sun4v_patch(void)
+{
+	extern void sun4v_hvapi_init(void);
+
+	if (tlb_type != hypervisor)
+		return;
+
+	sun4v_patch_1insn_range(&__sun4v_1insn_patch,
+				&__sun4v_1insn_patch_end);
+
+	sun4v_patch_2insn_range(&__sun4v_2insn_patch,
+				&__sun4v_2insn_patch_end);
 
 	sun4v_hvapi_init();
 }
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/signal_32.c linux-libre-3.2-gnu/arch/sparc/kernel/signal_32.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/signal_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/signal_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -519,10 +519,26 @@
 	siginfo_t info;
 	int signr;
 
+	/* It's a lot of work and synchronization to add a new ptrace
+	 * register for GDB to save and restore in order to get
+	 * orig_i0 correct for syscall restarts when debugging.
+	 *
+	 * Although it should be the case that most of the global
+	 * registers are volatile across a system call, glibc already
+	 * depends upon that fact that we preserve them.  So we can't
+	 * just use any global register to save away the orig_i0 value.
+	 *
+	 * In particular %g2, %g3, %g4, and %g5 are all assumed to be
+	 * preserved across a system call trap by various pieces of
+	 * code in glibc.
+	 *
+	 * %g7 is used as the "thread register".   %g6 is not used in
+	 * any fixed manner.  %g6 is used as a scratch register and
+	 * a compiler temporary, but it's value is never used across
+	 * a system call.  Therefore %g6 is usable for orig_i0 storage.
+	 */
 	if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
-		restart_syscall = 1;
-	else
-		restart_syscall = 0;
+		regs->u_regs[UREG_G6] = orig_i0;
 
 	if (test_thread_flag(TIF_RESTORE_SIGMASK))
 		oldset = &current->saved_sigmask;
@@ -535,8 +551,12 @@
 	 * the software "in syscall" bit, directing us to not perform
 	 * a syscall restart.
 	 */
-	if (restart_syscall && !pt_regs_is_syscall(regs))
-		restart_syscall = 0;
+	restart_syscall = 0;
+	if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) {
+		restart_syscall = 1;
+		orig_i0 = regs->u_regs[UREG_G6];
+	}
+
 
 	if (signr > 0) {
 		if (restart_syscall)
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/signal32.c linux-libre-3.2-gnu/arch/sparc/kernel/signal32.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/signal32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/signal32.c	2012-01-04 18:55:44.000000000 -0500
@@ -822,21 +822,23 @@
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-void do_signal32(sigset_t *oldset, struct pt_regs * regs,
-		 int restart_syscall, unsigned long orig_i0)
+void do_signal32(sigset_t *oldset, struct pt_regs * regs)
 {
 	struct k_sigaction ka;
+	unsigned long orig_i0;
+	int restart_syscall;
 	siginfo_t info;
 	int signr;
 	
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
-	/* If the debugger messes with the program counter, it clears
-	 * the "in syscall" bit, directing us to not perform a syscall
-	 * restart.
-	 */
-	if (restart_syscall && !pt_regs_is_syscall(regs))
-		restart_syscall = 0;
+	restart_syscall = 0;
+	orig_i0 = 0;
+	if (pt_regs_is_syscall(regs) &&
+	    (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
+		restart_syscall = 1;
+		orig_i0 = regs->u_regs[UREG_G6];
+	}
 
 	if (signr > 0) {
 		if (restart_syscall)
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/signal_64.c linux-libre-3.2-gnu/arch/sparc/kernel/signal_64.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/signal_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/signal_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -529,11 +529,27 @@
 	siginfo_t info;
 	int signr;
 	
+	/* It's a lot of work and synchronization to add a new ptrace
+	 * register for GDB to save and restore in order to get
+	 * orig_i0 correct for syscall restarts when debugging.
+	 *
+	 * Although it should be the case that most of the global
+	 * registers are volatile across a system call, glibc already
+	 * depends upon that fact that we preserve them.  So we can't
+	 * just use any global register to save away the orig_i0 value.
+	 *
+	 * In particular %g2, %g3, %g4, and %g5 are all assumed to be
+	 * preserved across a system call trap by various pieces of
+	 * code in glibc.
+	 *
+	 * %g7 is used as the "thread register".   %g6 is not used in
+	 * any fixed manner.  %g6 is used as a scratch register and
+	 * a compiler temporary, but it's value is never used across
+	 * a system call.  Therefore %g6 is usable for orig_i0 storage.
+	 */
 	if (pt_regs_is_syscall(regs) &&
-	    (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
-		restart_syscall = 1;
-	} else
-		restart_syscall = 0;
+	    (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
+		regs->u_regs[UREG_G6] = orig_i0;
 
 	if (current_thread_info()->status & TS_RESTORE_SIGMASK)
 		oldset = &current->saved_sigmask;
@@ -542,22 +558,20 @@
 
 #ifdef CONFIG_COMPAT
 	if (test_thread_flag(TIF_32BIT)) {
-		extern void do_signal32(sigset_t *, struct pt_regs *,
-					int restart_syscall,
-					unsigned long orig_i0);
-		do_signal32(oldset, regs, restart_syscall, orig_i0);
+		extern void do_signal32(sigset_t *, struct pt_regs *);
+		do_signal32(oldset, regs);
 		return;
 	}
 #endif	
 
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
-	/* If the debugger messes with the program counter, it clears
-	 * the software "in syscall" bit, directing us to not perform
-	 * a syscall restart.
-	 */
-	if (restart_syscall && !pt_regs_is_syscall(regs))
-		restart_syscall = 0;
+	restart_syscall = 0;
+	if (pt_regs_is_syscall(regs) &&
+	    (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
+		restart_syscall = 1;
+		orig_i0 = regs->u_regs[UREG_G6];
+	}
 
 	if (signr > 0) {
 		if (restart_syscall)
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/sigutil_64.c linux-libre-3.2-gnu/arch/sparc/kernel/sigutil_64.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/sigutil_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/sigutil_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,7 @@
 #include <linux/types.h>
 #include <linux/thread_info.h>
 #include <linux/uaccess.h>
+#include <linux/errno.h>
 
 #include <asm/sigcontext.h>
 #include <asm/fpumacro.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/smp_64.c linux-libre-3.2-gnu/arch/sparc/kernel/smp_64.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/smp_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/smp_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
  * Copyright (C) 1997, 2007, 2008 David S. Miller (davem@davemloft.net)
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/sparc_ksyms_64.c linux-libre-3.2-gnu/arch/sparc/kernel/sparc_ksyms_64.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/sparc_ksyms_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/sparc_ksyms_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
  * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/stacktrace.c linux-libre-3.2-gnu/arch/sparc/kernel/stacktrace.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/stacktrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/stacktrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
 #include <linux/stacktrace.h>
 #include <linux/thread_info.h>
 #include <linux/ftrace.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/ptrace.h>
 #include <asm/stacktrace.h>
 
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/sys_sparc32.c linux-libre-3.2-gnu/arch/sparc/kernel/sys_sparc32.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/sys_sparc32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/sys_sparc32.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,6 @@
 #include <linux/uio.h>
 #include <linux/nfs_fs.h>
 #include <linux/quota.h>
-#include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/personality.h>
 #include <linux/stat.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/sys_sparc_64.c linux-libre-3.2-gnu/arch/sparc/kernel/sys_sparc_64.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/sys_sparc_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/sys_sparc_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/ipc.h>
 #include <linux/personality.h>
 #include <linux/random.h>
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <asm/uaccess.h>
 #include <asm/utrap.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/systbls_32.S linux-libre-3.2-gnu/arch/sparc/kernel/systbls_32.S
--- linux-libre-3.1-gnu/arch/sparc/kernel/systbls_32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/systbls_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -84,4 +84,4 @@
 /*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, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
-/*335*/	.long sys_syncfs, sys_sendmmsg, sys_setns
+/*335*/	.long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/systbls_64.S linux-libre-3.2-gnu/arch/sparc/kernel/systbls_64.S
--- linux-libre-3.1-gnu/arch/sparc/kernel/systbls_64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/systbls_64.S	2012-01-04 18:55:44.000000000 -0500
@@ -85,7 +85,7 @@
 /*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, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
-	.word sys_syncfs, compat_sys_sendmmsg, sys_setns
+	.word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev
 
 #endif /* CONFIG_COMPAT */
 
@@ -162,4 +162,4 @@
 /*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, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
-	.word sys_syncfs, sys_sendmmsg, sys_setns
+	.word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/time_64.c linux-libre-3.2-gnu/arch/sparc/kernel/time_64.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/time_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/time_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
  */
 
 #include <linux/errno.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/param.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/traps_32.c linux-libre-3.2-gnu/arch/sparc/kernel/traps_32.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/traps_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/traps_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/signal.h>
 #include <linux/smp.h>
 #include <linux/kdebug.h>
+#include <linux/export.h>
 
 #include <asm/delay.h>
 #include <asm/system.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/unaligned_32.c linux-libre-3.2-gnu/arch/sparc/kernel/unaligned_32.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/unaligned_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/unaligned_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,6 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/module.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 #include <asm/system.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/vio.c linux-libre-3.2-gnu/arch/sparc/kernel/vio.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/vio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/vio.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/irq.h>
+#include <linux/export.h>
 #include <linux/init.h>
 
 #include <asm/mdesc.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/viohs.c linux-libre-3.2-gnu/arch/sparc/kernel/viohs.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/viohs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/viohs.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/kernel/visemul.c linux-libre-3.2-gnu/arch/sparc/kernel/visemul.c
--- linux-libre-3.1-gnu/arch/sparc/kernel/visemul.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/kernel/visemul.c	2012-01-04 18:55:44.000000000 -0500
@@ -713,17 +713,17 @@
 			s16 b = (rs2 >> (i * 16)) & 0xffff;
 
 			if (a > b)
-				rd_val |= 1 << i;
+				rd_val |= 8 >> i;
 		}
 		break;
 
 	case FCMPGT32_OPF:
 		for (i = 0; i < 2; i++) {
-			s32 a = (rs1 >> (i * 32)) & 0xffff;
-			s32 b = (rs2 >> (i * 32)) & 0xffff;
+			s32 a = (rs1 >> (i * 32)) & 0xffffffff;
+			s32 b = (rs2 >> (i * 32)) & 0xffffffff;
 
 			if (a > b)
-				rd_val |= 1 << i;
+				rd_val |= 2 >> i;
 		}
 		break;
 
@@ -733,17 +733,17 @@
 			s16 b = (rs2 >> (i * 16)) & 0xffff;
 
 			if (a <= b)
-				rd_val |= 1 << i;
+				rd_val |= 8 >> i;
 		}
 		break;
 
 	case FCMPLE32_OPF:
 		for (i = 0; i < 2; i++) {
-			s32 a = (rs1 >> (i * 32)) & 0xffff;
-			s32 b = (rs2 >> (i * 32)) & 0xffff;
+			s32 a = (rs1 >> (i * 32)) & 0xffffffff;
+			s32 b = (rs2 >> (i * 32)) & 0xffffffff;
 
 			if (a <= b)
-				rd_val |= 1 << i;
+				rd_val |= 2 >> i;
 		}
 		break;
 
@@ -753,17 +753,17 @@
 			s16 b = (rs2 >> (i * 16)) & 0xffff;
 
 			if (a != b)
-				rd_val |= 1 << i;
+				rd_val |= 8 >> i;
 		}
 		break;
 
 	case FCMPNE32_OPF:
 		for (i = 0; i < 2; i++) {
-			s32 a = (rs1 >> (i * 32)) & 0xffff;
-			s32 b = (rs2 >> (i * 32)) & 0xffff;
+			s32 a = (rs1 >> (i * 32)) & 0xffffffff;
+			s32 b = (rs2 >> (i * 32)) & 0xffffffff;
 
 			if (a != b)
-				rd_val |= 1 << i;
+				rd_val |= 2 >> i;
 		}
 		break;
 
@@ -773,17 +773,17 @@
 			s16 b = (rs2 >> (i * 16)) & 0xffff;
 
 			if (a == b)
-				rd_val |= 1 << i;
+				rd_val |= 8 >> i;
 		}
 		break;
 
 	case FCMPEQ32_OPF:
 		for (i = 0; i < 2; i++) {
-			s32 a = (rs1 >> (i * 32)) & 0xffff;
-			s32 b = (rs2 >> (i * 32)) & 0xffff;
+			s32 a = (rs1 >> (i * 32)) & 0xffffffff;
+			s32 b = (rs2 >> (i * 32)) & 0xffffffff;
 
 			if (a == b)
-				rd_val |= 1 << i;
+				rd_val |= 2 >> i;
 		}
 		break;
 	}
diff -druN linux-libre-3.1-gnu/arch/sparc/lib/memcpy.S linux-libre-3.2-gnu/arch/sparc/lib/memcpy.S
--- linux-libre-3.1-gnu/arch/sparc/lib/memcpy.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/lib/memcpy.S	2012-01-04 18:55:44.000000000 -0500
@@ -7,40 +7,12 @@
  * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
 
-#ifdef __KERNEL__
-
-#define FUNC(x) 											\
+#define FUNC(x) 		\
 	.globl	x;		\
 	.type	x,@function;	\
-	.align	4;											\
+	.align	4;		\
 x:
 
-#undef FASTER_REVERSE
-#undef FASTER_NONALIGNED
-#define FASTER_ALIGNED
-
-/* In kernel these functions don't return a value.
- * One should use macros in asm/string.h for that purpose.
- * We return 0, so that bugs are more apparent.
- */
-#define SETUP_RETL
-#define RETL_INSN	clr	%o0
-
-#else
-
-/* libc */
-
-#include "DEFS.h"
-
-#define FASTER_REVERSE
-#define FASTER_NONALIGNED
-#define FASTER_ALIGNED
-
-#define SETUP_RETL	mov	%o0, %g6
-#define RETL_INSN	mov	%g6, %o0
-
-#endif
-
 /* Both these macros have to start with exactly the same insn */
 #define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
 	ldd	[%src + (offset) + 0x00], %t0; \
@@ -164,30 +136,6 @@
 	.text
 	.align	4
 
-#ifdef FASTER_REVERSE
-
-70:	/* rdword_align */
-
-	andcc		%o1, 1, %g0
-	be		4f
-	 andcc		%o1, 2, %g0
-
-	ldub		[%o1 - 1], %g2
-	sub		%o1, 1, %o1
-	stb		%g2, [%o0 - 1]
-	sub		%o2, 1, %o2
-	be		3f
-	 sub		%o0, 1, %o0
-4:
-	lduh		[%o1 - 2], %g2
-	sub		%o1, 2, %o1
-	sth		%g2, [%o0 - 2]
-	sub		%o2, 2, %o2
-	b		3f
-	 sub		%o0, 2, %o0
-
-#endif /* FASTER_REVERSE */
-
 0:
 	retl
 	 nop		! Only bcopy returns here and it retuns void...
@@ -198,7 +146,7 @@
 #endif
 FUNC(memmove)
 	cmp		%o0, %o1
-	SETUP_RETL
+	mov		%o0, %g7
 	bleu		9f
 	 sub		%o0, %o1, %o4
 
@@ -207,8 +155,6 @@
 	bleu		0f
 	 andcc		%o4, 3, %o5
 
-#ifndef FASTER_REVERSE
-
 	add		%o1, %o2, %o1
 	add		%o0, %o2, %o0
 	sub		%o1, 1, %o1
@@ -224,295 +170,7 @@
 	 sub		%o0, 1, %o0
 
 	retl
-	 RETL_INSN
-
-#else /* FASTER_REVERSE */
-
-	add		%o1, %o2, %o1
-	add		%o0, %o2, %o0
-	bne		77f
-	 cmp		%o2, 15
-	bleu		91f
-	 andcc		%o1, 3, %g0
-	bne		70b
-3:
-	 andcc		%o1, 4, %g0
-
-	be		2f
-	 mov		%o2, %g1
-
-	ld		[%o1 - 4], %o4
-	sub		%g1, 4, %g1
-	st		%o4, [%o0 - 4]
-	sub		%o1, 4, %o1
-	sub		%o0, 4, %o0
-2:
-	andcc		%g1, 0xffffff80, %g7
-	be		3f
-	 andcc		%o0, 4, %g0
-
-	be		74f + 4
-5:
-	RMOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
-	RMOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
-	RMOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
-	RMOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
-	subcc		%g7, 128, %g7
-	sub		%o1, 128, %o1
-	bne		5b
-	 sub		%o0, 128, %o0
-3:
-	andcc		%g1, 0x70, %g7
-	be		72f
-	 andcc		%g1, 8, %g0
-
-	sethi		%hi(72f), %o5
-	srl		%g7, 1, %o4
-	add		%g7, %o4, %o4
-	sub		%o1, %g7, %o1
-	sub		%o5, %o4, %o5
-	jmpl		%o5 + %lo(72f), %g0
-	 sub		%o0, %g7, %o0
-
-71:	/* rmemcpy_table */
-	RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
-	RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
-	RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
-	RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
-	RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
-	RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
-	RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
-
-72:	/* rmemcpy_table_end */
-
-	be		73f
-	 andcc		%g1, 4, %g0
-
-	ldd		[%o1 - 0x08], %g2
-	sub		%o0, 8, %o0
-	sub		%o1, 8, %o1
-	st		%g2, [%o0]
-	st		%g3, [%o0 + 0x04]
-
-73:	/* rmemcpy_last7 */
-
-	be		1f
-	 andcc		%g1, 2, %g0
-
-	ld		[%o1 - 4], %g2
-	sub		%o1, 4, %o1
-	st		%g2, [%o0 - 4]
-	sub		%o0, 4, %o0
-1:
-	be		1f
-	 andcc		%g1, 1, %g0
-
-	lduh		[%o1 - 2], %g2
-	sub		%o1, 2, %o1
-	sth		%g2, [%o0 - 2]
-	sub		%o0, 2, %o0
-1:
-	be		1f
-	 nop
-
-	ldub		[%o1 - 1], %g2
-	stb		%g2, [%o0 - 1]
-1:
-	retl
- 	 RETL_INSN
-
-74:	/* rldd_std */
-	RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
-	RMOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
-	RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
-	RMOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
-	subcc		%g7, 128, %g7
-	sub		%o1, 128, %o1
-	bne		74b
-	 sub		%o0, 128, %o0
-
-	andcc		%g1, 0x70, %g7
-	be		72b
-	 andcc		%g1, 8, %g0
-
-	sethi		%hi(72b), %o5
-	srl		%g7, 1, %o4
-	add		%g7, %o4, %o4
-	sub		%o1, %g7, %o1
-	sub		%o5, %o4, %o5
-	jmpl		%o5 + %lo(72b), %g0
-	 sub		%o0, %g7, %o0
-
-75:	/* rshort_end */
-
-	and		%o2, 0xe, %o3
-2:
-	sethi		%hi(76f), %o5
-	sll		%o3, 3, %o4
-	sub		%o0, %o3, %o0
-	sub		%o5, %o4, %o5
-	sub		%o1, %o3, %o1
-	jmpl		%o5 + %lo(76f), %g0
-	 andcc		%o2, 1, %g0
-
-	RMOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
-	RMOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
-	RMOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
-	RMOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
-	RMOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
-	RMOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
-	RMOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
-
-76:	/* rshort_table_end */
-
-	be		1f
-	 nop
-	ldub		[%o1 - 1], %g2
-	stb		%g2, [%o0 - 1]
-1:
-	retl
- 	 RETL_INSN
-
-91:	/* rshort_aligned_end */
-
-	bne		75b
-	 andcc		%o2, 8, %g0
-
-	be		1f
-	 andcc		%o2, 4, %g0
-
-	ld		[%o1 - 0x08], %g2
-	ld		[%o1 - 0x04], %g3
-	sub		%o1, 8, %o1
-	st		%g2, [%o0 - 0x08]
-	st		%g3, [%o0 - 0x04]
-	sub		%o0, 8, %o0
-1:
-	b		73b
-	 mov		%o2, %g1
-
-77:	/* rnon_aligned */
-	cmp		%o2, 15
-	bleu		75b
-	 andcc		%o0, 3, %g0
-	be		64f
-	 andcc		%o0, 1, %g0
-	be		63f
-	 andcc		%o0, 2, %g0
-	ldub		[%o1 - 1], %g5
-	sub		%o1, 1, %o1
-	stb		%g5, [%o0 - 1]
-	sub		%o0, 1, %o0
-	be		64f
-	 sub		%o2, 1, %o2
-63:
-	ldub		[%o1 - 1], %g5
-	sub		%o1, 2, %o1
-	stb		%g5, [%o0 - 1]
-	sub		%o0, 2, %o0
-	ldub		[%o1], %g5
-	sub		%o2, 2, %o2
-	stb		%g5, [%o0]
-64:	
-	and		%o1, 3, %g2
-	and		%o1, -4, %o1
-	and		%o2, 0xc, %g3
-	add		%o1, 4, %o1
-	cmp		%g3, 4
-	sll		%g2, 3, %g4
-	mov		32, %g2
-	be		4f
-	 sub		%g2, %g4, %g7
-
-	blu		3f
-	 cmp		%g3, 8
-
-	be		2f
-	 srl		%o2, 2, %g3
-
-	ld		[%o1 - 4], %o3
-	add		%o0, -8, %o0
-	ld		[%o1 - 8], %o4
-	add		%o1, -16, %o1
-	b		7f
-	 add		%g3, 1, %g3
-2:
-	ld		[%o1 - 4], %o4
-	add		%o0, -4, %o0
-	ld		[%o1 - 8], %g1
-	add		%o1, -12, %o1
-	b		8f
-	 add		%g3, 2, %g3
-3:
-	ld		[%o1 - 4], %o5
-	add		%o0, -12, %o0
-	ld		[%o1 - 8], %o3
-	add		%o1, -20, %o1
-	b		6f
-	 srl		%o2, 2, %g3
-4:
-	ld		[%o1 - 4], %g1
-	srl		%o2, 2, %g3
-	ld		[%o1 - 8], %o5
-	add		%o1, -24, %o1
-	add		%o0, -16, %o0
-	add		%g3, -1, %g3
-
-	ld		[%o1 + 12], %o3
-5:
-	sll		%o5, %g4, %g2
-	srl		%g1, %g7, %g5
-	or		%g2, %g5, %g2
-	st		%g2, [%o0 + 12]
-6:
-	ld		[%o1 + 8], %o4
-	sll		%o3, %g4, %g2
-	srl		%o5, %g7, %g5
-	or		%g2, %g5, %g2
-	st		%g2, [%o0 + 8]
-7:
-	ld		[%o1 + 4], %g1
-	sll		%o4, %g4, %g2
-	srl		%o3, %g7, %g5
-	or		%g2, %g5, %g2
-	st		%g2, [%o0 + 4]
-8:
-	ld		[%o1], %o5
-	sll		%g1, %g4, %g2
-	srl		%o4, %g7, %g5
-	addcc		%g3, -4, %g3
-	or		%g2, %g5, %g2
-	add		%o1, -16, %o1
-	st		%g2, [%o0]
-	add		%o0, -16, %o0
-	bne,a		5b	
-	 ld		[%o1 + 12], %o3
-	sll		%o5, %g4, %g2
-	srl		%g1, %g7, %g5
-	srl		%g4, 3, %g3
-	or		%g2, %g5, %g2
-	add		%o1, %g3, %o1
-	andcc		%o2, 2, %g0
-	st		%g2, [%o0 + 12]
-	be		1f
-	 andcc		%o2, 1, %g0
-	
-	ldub		[%o1 + 15], %g5
-	add		%o1, -2, %o1
-	stb		%g5, [%o0 + 11]
-	add		%o0, -2, %o0
-	ldub		[%o1 + 16], %g5
-	stb		%g5, [%o0 + 12]
-1:
-	be		1f
-	 nop
-	ldub		[%o1 + 15], %g5
-	stb		%g5, [%o0 + 11]
-1:
-	retl
-	 RETL_INSN
-
-#endif /* FASTER_REVERSE */
+	 mov		%g7, %o0
 
 /* NOTE: This code is executed just for the cases,
          where %src (=%o1) & 3 is != 0.
@@ -546,7 +204,7 @@
 FUNC(memcpy)	/* %o0=dst %o1=src %o2=len */
 
 	sub		%o0, %o1, %o4
-	SETUP_RETL
+	mov		%o0, %g7
 9:
 	andcc		%o4, 3, %o5
 0:
@@ -569,7 +227,7 @@
 	add		%o1, 4, %o1
 	add		%o0, 4, %o0
 2:
-	andcc		%g1, 0xffffff80, %g7
+	andcc		%g1, 0xffffff80, %g0
 	be		3f
 	 andcc		%o0, 4, %g0
 
@@ -579,22 +237,23 @@
 	MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
 	MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
 	MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
-	subcc		%g7, 128, %g7
+	sub		%g1, 128, %g1
 	add		%o1, 128, %o1
-	bne		5b
+	cmp		%g1, 128
+	bge		5b
 	 add		%o0, 128, %o0
 3:
-	andcc		%g1, 0x70, %g7
+	andcc		%g1, 0x70, %g4
 	be		80f
 	 andcc		%g1, 8, %g0
 
 	sethi		%hi(80f), %o5
-	srl		%g7, 1, %o4
-	add		%g7, %o4, %o4
-	add		%o1, %g7, %o1
+	srl		%g4, 1, %o4
+	add		%g4, %o4, %o4
+	add		%o1, %g4, %o1
 	sub		%o5, %o4, %o5
 	jmpl		%o5 + %lo(80f), %g0
-	 add		%o0, %g7, %o0
+	 add		%o0, %g4, %o0
 
 79:	/* memcpy_table */
 
@@ -641,43 +300,28 @@
 	stb		%g2, [%o0]
 1:
 	retl
- 	 RETL_INSN
+	 mov		%g7, %o0
 
 82:	/* ldd_std */
 	MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
 	MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
 	MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
 	MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
-	subcc		%g7, 128, %g7
+	subcc		%g1, 128, %g1
 	add		%o1, 128, %o1
-	bne		82b
+	cmp		%g1, 128
+	bge		82b
 	 add		%o0, 128, %o0
 
-#ifndef FASTER_ALIGNED
-
-	andcc		%g1, 0x70, %g7
-	be		80b
-	 andcc		%g1, 8, %g0
-
-	sethi		%hi(80b), %o5
-	srl		%g7, 1, %o4
-	add		%g7, %o4, %o4
-	add		%o1, %g7, %o1
-	sub		%o5, %o4, %o5
-	jmpl		%o5 + %lo(80b), %g0
-	 add		%o0, %g7, %o0
-
-#else /* FASTER_ALIGNED */
-
-	andcc		%g1, 0x70, %g7
+	andcc		%g1, 0x70, %g4
 	be		84f
 	 andcc		%g1, 8, %g0
 
 	sethi		%hi(84f), %o5
-	add		%o1, %g7, %o1
-	sub		%o5, %g7, %o5
+	add		%o1, %g4, %o1
+	sub		%o5, %g4, %o5
 	jmpl		%o5 + %lo(84f), %g0
-	 add		%o0, %g7, %o0
+	 add		%o0, %g4, %o0
 
 83:	/* amemcpy_table */
 
@@ -721,382 +365,132 @@
 	stb		%g2, [%o0]
 1:
 	retl
- 	 RETL_INSN
-
-#endif /* FASTER_ALIGNED */
+	 mov		%g7, %o0
 
 86:	/* non_aligned */
 	cmp		%o2, 6
 	bleu		88f
+	 nop
 
-#ifdef FASTER_NONALIGNED
-
-	 cmp		%o2, 256
-	bcc		87f
-
-#endif /* FASTER_NONALIGNED */
-
-	 andcc		%o0, 3, %g0
+	save		%sp, -96, %sp
+	andcc		%i0, 3, %g0
 	be		61f
-	 andcc		%o0, 1, %g0
+	 andcc		%i0, 1, %g0
 	be		60f
-	 andcc		%o0, 2, %g0
+	 andcc		%i0, 2, %g0
 
-	ldub		[%o1], %g5
-	add		%o1, 1, %o1
-	stb		%g5, [%o0]
-	sub		%o2, 1, %o2
+	ldub		[%i1], %g5
+	add		%i1, 1, %i1
+	stb		%g5, [%i0]
+	sub		%i2, 1, %i2
 	bne		61f
-	 add		%o0, 1, %o0
+	 add		%i0, 1, %i0
 60:
-	ldub		[%o1], %g3
-	add		%o1, 2, %o1
-	stb		%g3, [%o0]
-	sub		%o2, 2, %o2
-	ldub		[%o1 - 1], %g3
-	add		%o0, 2, %o0
-	stb		%g3, [%o0 - 1]
+	ldub		[%i1], %g3
+	add		%i1, 2, %i1
+	stb		%g3, [%i0]
+	sub		%i2, 2, %i2
+	ldub		[%i1 - 1], %g3
+	add		%i0, 2, %i0
+	stb		%g3, [%i0 - 1]
 61:
-	and		%o1, 3, %g2
-	and		%o2, 0xc, %g3
-	and		%o1, -4, %o1
+	and		%i1, 3, %g2
+	and		%i2, 0xc, %g3
+	and		%i1, -4, %i1
 	cmp		%g3, 4
 	sll		%g2, 3, %g4
 	mov		32, %g2
 	be		4f
-	 sub		%g2, %g4, %g7
+	 sub		%g2, %g4, %l0
 	
 	blu		3f
 	 cmp		%g3, 0x8
 
 	be		2f
-	 srl		%o2, 2, %g3
+	 srl		%i2, 2, %g3
 
-	ld		[%o1], %o3
-	add		%o0, -8, %o0
-	ld		[%o1 + 4], %o4
+	ld		[%i1], %i3
+	add		%i0, -8, %i0
+	ld		[%i1 + 4], %i4
 	b		8f
 	 add		%g3, 1, %g3
 2:
-	ld		[%o1], %o4
-	add		%o0, -12, %o0
-	ld		[%o1 + 4], %o5
+	ld		[%i1], %i4
+	add		%i0, -12, %i0
+	ld		[%i1 + 4], %i5
 	add		%g3, 2, %g3
 	b		9f
-	 add		%o1, -4, %o1
+	 add		%i1, -4, %i1
 3:
-	ld		[%o1], %g1
-	add		%o0, -4, %o0
-	ld		[%o1 + 4], %o3
-	srl		%o2, 2, %g3
+	ld		[%i1], %g1
+	add		%i0, -4, %i0
+	ld		[%i1 + 4], %i3
+	srl		%i2, 2, %g3
 	b		7f
-	 add		%o1, 4, %o1
+	 add		%i1, 4, %i1
 4:
-	ld		[%o1], %o5
-	cmp		%o2, 7
-	ld		[%o1 + 4], %g1
-	srl		%o2, 2, %g3
+	ld		[%i1], %i5
+	cmp		%i2, 7
+	ld		[%i1 + 4], %g1
+	srl		%i2, 2, %g3
 	bleu		10f
-	 add		%o1, 8, %o1
+	 add		%i1, 8, %i1
 
-	ld		[%o1], %o3
+	ld		[%i1], %i3
 	add		%g3, -1, %g3
 5:
-	sll		%o5, %g4, %g2
-	srl		%g1, %g7, %g5
+	sll		%i5, %g4, %g2
+	srl		%g1, %l0, %g5
 	or		%g2, %g5, %g2
-	st		%g2, [%o0]
+	st		%g2, [%i0]
 7:
-	ld		[%o1 + 4], %o4
+	ld		[%i1 + 4], %i4
 	sll		%g1, %g4, %g2
-	srl		%o3, %g7, %g5
+	srl		%i3, %l0, %g5
 	or		%g2, %g5, %g2
-	st		%g2, [%o0 + 4]
+	st		%g2, [%i0 + 4]
 8:
-	ld		[%o1 + 8], %o5
-	sll		%o3, %g4, %g2
-	srl		%o4, %g7, %g5
+	ld		[%i1 + 8], %i5
+	sll		%i3, %g4, %g2
+	srl		%i4, %l0, %g5
 	or		%g2, %g5, %g2
-	st		%g2, [%o0 + 8]
+	st		%g2, [%i0 + 8]
 9:
-	ld		[%o1 + 12], %g1
-	sll		%o4, %g4, %g2
-	srl		%o5, %g7, %g5
+	ld		[%i1 + 12], %g1
+	sll		%i4, %g4, %g2
+	srl		%i5, %l0, %g5
 	addcc		%g3, -4, %g3
 	or		%g2, %g5, %g2
-	add		%o1, 16, %o1
-	st		%g2, [%o0 + 12]
-	add		%o0, 16, %o0
+	add		%i1, 16, %i1
+	st		%g2, [%i0 + 12]
+	add		%i0, 16, %i0
 	bne,a		5b
-	 ld		[%o1], %o3
+	 ld		[%i1], %i3
 10:
-	sll		%o5, %g4, %g2
-	srl		%g1, %g7, %g5
-	srl		%g7, 3, %g3
+	sll		%i5, %g4, %g2
+	srl		%g1, %l0, %g5
+	srl		%l0, 3, %g3
 	or		%g2, %g5, %g2
-	sub		%o1, %g3, %o1
-	andcc		%o2, 2, %g0
-	st		%g2, [%o0]
+	sub		%i1, %g3, %i1
+	andcc		%i2, 2, %g0
+	st		%g2, [%i0]
 	be		1f
-	 andcc		%o2, 1, %g0
+	 andcc		%i2, 1, %g0
 
-	ldub		[%o1], %g2
-	add		%o1, 2, %o1
-	stb		%g2, [%o0 + 4]
-	add		%o0, 2, %o0
-	ldub		[%o1 - 1], %g2
-	stb		%g2, [%o0 + 3]
+	ldub		[%i1], %g2
+	add		%i1, 2, %i1
+	stb		%g2, [%i0 + 4]
+	add		%i0, 2, %i0
+	ldub		[%i1 - 1], %g2
+	stb		%g2, [%i0 + 3]
 1:
 	be		1f
 	 nop
-	ldub		[%o1], %g2
-	stb		%g2, [%o0 + 4]
-1:
-	retl
-	 RETL_INSN
-
-#ifdef FASTER_NONALIGNED
-
-87:	/* faster_nonaligned */
-
-	andcc		%o1, 3, %g0
-	be		3f
-	 andcc		%o1, 1, %g0
-
-	be		4f
-	 andcc		%o1, 2, %g0
-
-	ldub		[%o1], %g2
-	add		%o1, 1, %o1
-	stb		%g2, [%o0]
-	sub		%o2, 1, %o2
-	bne		3f
-	 add		%o0, 1, %o0
-4:
-	lduh		[%o1], %g2
-	add		%o1, 2, %o1
-	srl		%g2, 8, %g3
-	sub		%o2, 2, %o2
-	stb		%g3, [%o0]
-	add		%o0, 2, %o0
-	stb		%g2, [%o0 - 1]
-3:
-	 andcc		%o1, 4, %g0
-
-	bne		2f
-	 cmp		%o5, 1
-
-	ld		[%o1], %o4
-	srl		%o4, 24, %g2
-	stb		%g2, [%o0]
-	srl		%o4, 16, %g3
-	stb		%g3, [%o0 + 1]
-	srl		%o4, 8, %g2
-	stb		%g2, [%o0 + 2]
-	sub		%o2, 4, %o2
-	stb		%o4, [%o0 + 3]
-	add		%o1, 4, %o1
-	add		%o0, 4, %o0
-2:
-	be		33f
-	 cmp		%o5, 2
-	be		32f
-	 sub		%o2, 4, %o2
-31:
-	ld		[%o1], %g2
-	add		%o1, 4, %o1
-	srl		%g2, 24, %g3
-	and		%o0, 7, %g5
-	stb		%g3, [%o0]
-	cmp		%g5, 7
-	sll		%g2, 8, %g1
-	add		%o0, 4, %o0
-	be		41f
-	 and		%o2, 0xffffffc0, %o3
-	ld		[%o0 - 7], %o4
-4:
-	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	subcc		%o3, 64, %o3
-	add		%o1, 64, %o1
-	bne		4b
-	 add		%o0, 64, %o0
-
-	andcc		%o2, 0x30, %o3
-	be,a		1f
-	 srl		%g1, 16, %g2
-4:
-	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	subcc		%o3, 16, %o3
-	add		%o1, 16, %o1
-	bne		4b
-	 add		%o0, 16, %o0
-
-	srl		%g1, 16, %g2
-1:
-	st		%o4, [%o0 - 7]
-	sth		%g2, [%o0 - 3]
-	srl		%g1, 8, %g4
-	b		88f
-	 stb		%g4, [%o0 - 1]
-32:
-	ld		[%o1], %g2
-	add		%o1, 4, %o1
-	srl		%g2, 16, %g3
-	and		%o0, 7, %g5
-	sth		%g3, [%o0]
-	cmp		%g5, 6
-	sll		%g2, 16, %g1
-	add		%o0, 4, %o0
-	be		42f
-	 and		%o2, 0xffffffc0, %o3
-	ld		[%o0 - 6], %o4
-4:
-	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	subcc		%o3, 64, %o3
-	add		%o1, 64, %o1
-	bne		4b
-	 add		%o0, 64, %o0
-
-	andcc		%o2, 0x30, %o3
-	be,a		1f
-	 srl		%g1, 16, %g2
-4:
-	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	subcc		%o3, 16, %o3
-	add		%o1, 16, %o1
-	bne		4b
-	 add		%o0, 16, %o0
-
-	srl		%g1, 16, %g2
-1:
-	st		%o4, [%o0 - 6]
-	b		88f
-	 sth		%g2, [%o0 - 2]
-33:
-	ld		[%o1], %g2
-	sub		%o2, 4, %o2
-	srl		%g2, 24, %g3
-	and		%o0, 7, %g5
-	stb		%g3, [%o0]
-	cmp		%g5, 5
-	srl		%g2, 8, %g4
-	sll		%g2, 24, %g1
-	sth		%g4, [%o0 + 1]
-	add		%o1, 4, %o1
-	be		43f
-	 and		%o2, 0xffffffc0, %o3
-
-	ld		[%o0 - 1], %o4
-	add		%o0, 4, %o0
-4:
-	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
-	SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
-	SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
-	SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
-	subcc		%o3, 64, %o3
-	add		%o1, 64, %o1
-	bne		4b
-	 add		%o0, 64, %o0
-
-	andcc		%o2, 0x30, %o3
-	be,a		1f
-	 srl		%g1, 24, %g2
-4:
-	SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
-	subcc		%o3, 16, %o3
-	add		%o1, 16, %o1
-	bne		4b
-	 add		%o0, 16, %o0
-
-	srl		%g1, 24, %g2
-1:
-	st		%o4, [%o0 - 5]
-	b		88f
-	 stb		%g2, [%o0 - 1]
-41:
-	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	subcc		%o3, 64, %o3
-	add		%o1, 64, %o1
-	bne		41b
-	 add		%o0, 64, %o0
-	 
-	andcc		%o2, 0x30, %o3
-	be,a		1f
-	 srl		%g1, 16, %g2
-4:
-	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
-	subcc		%o3, 16, %o3
-	add		%o1, 16, %o1
-	bne		4b
-	 add		%o0, 16, %o0
-
-	srl		%g1, 16, %g2
-1:
-	sth		%g2, [%o0 - 3]
-	srl		%g1, 8, %g4
-	b		88f
-	 stb		%g4, [%o0 - 1]
-43:
-	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
-	subcc		%o3, 64, %o3
-	add		%o1, 64, %o1
-	bne		43b
-	 add		%o0, 64, %o0
-
-	andcc		%o2, 0x30, %o3
-	be,a		1f
-	 srl		%g1, 24, %g2
-4:
-	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
-	subcc		%o3, 16, %o3
-	add		%o1, 16, %o1
-	bne		4b
-	 add		%o0, 16, %o0
-
-	srl		%g1, 24, %g2
-1:
-	stb		%g2, [%o0 + 3]
-	b		88f
-	 add		%o0, 4, %o0
-42:
-	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	subcc		%o3, 64, %o3
-	add		%o1, 64, %o1
-	bne		42b
-	 add		%o0, 64, %o0
-	 
-	andcc		%o2, 0x30, %o3
-	be,a		1f
-	 srl		%g1, 16, %g2
-4:
-	SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
-	subcc		%o3, 16, %o3
-	add		%o1, 16, %o1
-	bne		4b
-	 add		%o0, 16, %o0
-
-	srl		%g1, 16, %g2
+	ldub		[%i1], %g2
+	stb		%g2, [%i0 + 4]
 1:
-	sth		%g2, [%o0 - 2]
-
-	/* Fall through */
-	 
-#endif /* FASTER_NONALIGNED */
+	ret
+	 restore	%g7, %g0, %o0
 
 88:	/* short_end */
 
@@ -1127,7 +521,7 @@
 	stb		%g2, [%o0]
 1:
 	retl
- 	 RETL_INSN
+	 mov		%g7, %o0
 
 90:	/* short_aligned_end */
 	bne		88b
diff -druN linux-libre-3.1-gnu/arch/sparc/mm/btfixup.c linux-libre-3.2-gnu/arch/sparc/mm/btfixup.c
--- linux-libre-3.1-gnu/arch/sparc/mm/btfixup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/mm/btfixup.c	2012-01-04 18:55:44.000000000 -0500
@@ -302,8 +302,7 @@
 				case 'i':	/* INT */
 					if ((insn & 0xc1c00000) == 0x01000000) /* %HI */
 						set_addr(addr, q[1], fmangled, (insn & 0xffc00000) | (p[1] >> 10));
-					else if ((insn & 0x80002000) == 0x80002000 &&
-					         (insn & 0x01800000) != 0x01800000) /* %LO */
+					else if ((insn & 0x80002000) == 0x80002000) /* %LO */
 						set_addr(addr, q[1], fmangled, (insn & 0xffffe000) | (p[1] & 0x3ff));
 					else {
 						prom_printf(insn_i, p, addr, insn);
diff -druN linux-libre-3.1-gnu/arch/sparc/mm/fault_32.c linux-libre-3.2-gnu/arch/sparc/mm/fault_32.c
--- linux-libre-3.1-gnu/arch/sparc/mm/fault_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/mm/fault_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,6 @@
 #include <linux/smp.h>
 #include <linux/perf_event.h>
 #include <linux/interrupt.h>
-#include <linux/module.h>
 #include <linux/kdebug.h>
 
 #include <asm/system.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/mm/generic_32.c linux-libre-3.2-gnu/arch/sparc/mm/generic_32.c
--- linux-libre-3.1-gnu/arch/sparc/mm/generic_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/mm/generic_32.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +0,0 @@
-/*
- * generic.c: Generic Sparc mm routines that are not dependent upon
- *            MMU type but are Sparc specific.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/pagemap.h>
-
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-
-/* Remap IO memory, the same way as remap_pfn_range(), but use
- * the obio memory space.
- *
- * They use a pgprot that sets PAGE_IO and does not check the
- * mem_map table as this is independent of normal memory.
- */
-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, unsigned long address, unsigned long size,
-	unsigned long offset, pgprot_t prot, int space)
-{
-	unsigned long end;
-
-	address &= ~PMD_MASK;
-	end = address + size;
-	if (end > PMD_SIZE)
-		end = PMD_SIZE;
-	do {
-		set_pte_at(mm, address, pte, mk_pte_io(offset, prot, space));
-		address += PAGE_SIZE;
-		offset += PAGE_SIZE;
-		pte++;
-	} while (address < end);
-}
-
-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
-	unsigned long offset, pgprot_t prot, int space)
-{
-	unsigned long end;
-
-	address &= ~PGDIR_MASK;
-	end = address + size;
-	if (end > PGDIR_SIZE)
-		end = PGDIR_SIZE;
-	offset -= address;
-	do {
-		pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
-		if (!pte)
-			return -ENOMEM;
-		io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
-		address = (address + PMD_SIZE) & PMD_MASK;
-		pmd++;
-	} while (address < end);
-	return 0;
-}
-
-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
-		       unsigned long pfn, unsigned long size, pgprot_t prot)
-{
-	int error = 0;
-	pgd_t * dir;
-	unsigned long beg = from;
-	unsigned long end = from + size;
-	struct mm_struct *mm = vma->vm_mm;
-	int space = GET_IOSPACE(pfn);
-	unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
-
-	/* See comment in mm/memory.c remap_pfn_range */
-	vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
-	vma->vm_pgoff = (offset >> PAGE_SHIFT) |
-		((unsigned long)space << 28UL);
-
-	offset -= from;
-	dir = pgd_offset(mm, from);
-	flush_cache_range(vma, beg, end);
-
-	while (from < end) {
-		pmd_t *pmd = pmd_alloc(mm, dir, from);
-		error = -ENOMEM;
-		if (!pmd)
-			break;
-		error = io_remap_pmd_range(mm, pmd, from, end - from, offset + from, prot, space);
-		if (error)
-			break;
-		from = (from + PGDIR_SIZE) & PGDIR_MASK;
-		dir++;
-	}
-
-	flush_tlb_range(vma, beg, end);
-	return error;
-}
-EXPORT_SYMBOL(io_remap_pfn_range);
diff -druN linux-libre-3.1-gnu/arch/sparc/mm/generic_64.c linux-libre-3.2-gnu/arch/sparc/mm/generic_64.c
--- linux-libre-3.1-gnu/arch/sparc/mm/generic_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/mm/generic_64.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,164 +0,0 @@
-/*
- * generic.c: Generic Sparc mm routines that are not dependent upon
- *            MMU type but are Sparc specific.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/pagemap.h>
-
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/tlbflush.h>
-
-/* Remap IO memory, the same way as remap_pfn_range(), but use
- * the obio memory space.
- *
- * They use a pgprot that sets PAGE_IO and does not check the
- * mem_map table as this is independent of normal memory.
- */
-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte,
-				      unsigned long address,
-				      unsigned long size,
-				      unsigned long offset, pgprot_t prot,
-				      int space)
-{
-	unsigned long end;
-
-	/* clear hack bit that was used as a write_combine side-effect flag */
-	offset &= ~0x1UL;
-	address &= ~PMD_MASK;
-	end = address + size;
-	if (end > PMD_SIZE)
-		end = PMD_SIZE;
-	do {
-		pte_t entry;
-		unsigned long curend = address + PAGE_SIZE;
-		
-		entry = mk_pte_io(offset, prot, space, PAGE_SIZE);
-		if (!(address & 0xffff)) {
-			if (PAGE_SIZE < (4 * 1024 * 1024) &&
-			    !(address & 0x3fffff) &&
-			    !(offset & 0x3ffffe) &&
-			    end >= address + 0x400000) {
-				entry = mk_pte_io(offset, prot, space,
-						  4 * 1024 * 1024);
-				curend = address + 0x400000;
-				offset += 0x400000;
-			} else if (PAGE_SIZE < (512 * 1024) &&
-				   !(address & 0x7ffff) &&
-				   !(offset & 0x7fffe) &&
-				   end >= address + 0x80000) {
-				entry = mk_pte_io(offset, prot, space,
-						  512 * 1024 * 1024);
-				curend = address + 0x80000;
-				offset += 0x80000;
-			} else if (PAGE_SIZE < (64 * 1024) &&
-				   !(offset & 0xfffe) &&
-				   end >= address + 0x10000) {
-				entry = mk_pte_io(offset, prot, space,
-						  64 * 1024);
-				curend = address + 0x10000;
-				offset += 0x10000;
-			} else
-				offset += PAGE_SIZE;
-		} else
-			offset += PAGE_SIZE;
-
-		if (pte_write(entry))
-			entry = pte_mkdirty(entry);
-		do {
-			BUG_ON(!pte_none(*pte));
-			set_pte_at(mm, address, pte, entry);
-			address += PAGE_SIZE;
-			pte_val(entry) += PAGE_SIZE;
-			pte++;
-		} while (address < curend);
-	} while (address < end);
-}
-
-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
-	unsigned long offset, pgprot_t prot, int space)
-{
-	unsigned long end;
-
-	address &= ~PGDIR_MASK;
-	end = address + size;
-	if (end > PGDIR_SIZE)
-		end = PGDIR_SIZE;
-	offset -= address;
-	do {
-		pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
-		if (!pte)
-			return -ENOMEM;
-		io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
-		pte_unmap(pte);
-		address = (address + PMD_SIZE) & PMD_MASK;
-		pmd++;
-	} while (address < end);
-	return 0;
-}
-
-static inline int io_remap_pud_range(struct mm_struct *mm, pud_t * pud, unsigned long address, unsigned long size,
-	unsigned long offset, pgprot_t prot, int space)
-{
-	unsigned long end;
-
-	address &= ~PUD_MASK;
-	end = address + size;
-	if (end > PUD_SIZE)
-		end = PUD_SIZE;
-	offset -= address;
-	do {
-		pmd_t *pmd = pmd_alloc(mm, pud, address);
-		if (!pud)
-			return -ENOMEM;
-		io_remap_pmd_range(mm, pmd, address, end - address, address + offset, prot, space);
-		address = (address + PUD_SIZE) & PUD_MASK;
-		pud++;
-	} while (address < end);
-	return 0;
-}
-
-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
-		unsigned long pfn, unsigned long size, pgprot_t prot)
-{
-	int error = 0;
-	pgd_t * dir;
-	unsigned long beg = from;
-	unsigned long end = from + size;
-	struct mm_struct *mm = vma->vm_mm;
-	int space = GET_IOSPACE(pfn);
-	unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
-	unsigned long phys_base;
-
-	phys_base = offset | (((unsigned long) space) << 32UL);
-
-	/* See comment in mm/memory.c remap_pfn_range */
-	vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
-	vma->vm_pgoff = phys_base >> PAGE_SHIFT;
-
-	offset -= from;
-	dir = pgd_offset(mm, from);
-	flush_cache_range(vma, beg, end);
-
-	while (from < end) {
-		pud_t *pud = pud_alloc(mm, dir, from);
-		error = -ENOMEM;
-		if (!pud)
-			break;
-		error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space);
-		if (error)
-			break;
-		from = (from + PGDIR_SIZE) & PGDIR_MASK;
-		dir++;
-	}
-
-	flush_tlb_range(vma, beg, end);
-	return error;
-}
-EXPORT_SYMBOL(io_remap_pfn_range);
diff -druN linux-libre-3.1-gnu/arch/sparc/mm/gup.c linux-libre-3.2-gnu/arch/sparc/mm/gup.c
--- linux-libre-3.1-gnu/arch/sparc/mm/gup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/mm/gup.c	2012-01-04 18:55:44.000000000 -0500
@@ -56,6 +56,8 @@
 			put_page(head);
 			return 0;
 		}
+		if (head != page)
+			get_huge_page_tail(page);
 
 		pages[*nr] = page;
 		(*nr)++;
diff -druN linux-libre-3.1-gnu/arch/sparc/mm/highmem.c linux-libre-3.2-gnu/arch/sparc/mm/highmem.c
--- linux-libre-3.1-gnu/arch/sparc/mm/highmem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/mm/highmem.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
  */
 #include <linux/mm.h>
 #include <linux/highmem.h>
+#include <linux/export.h>
 #include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/mm/hugetlbpage.c linux-libre-3.2-gnu/arch/sparc/mm/hugetlbpage.c
--- linux-libre-3.1-gnu/arch/sparc/mm/hugetlbpage.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/mm/hugetlbpage.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
diff -druN linux-libre-3.1-gnu/arch/sparc/mm/Makefile linux-libre-3.2-gnu/arch/sparc/mm/Makefile
--- linux-libre-3.1-gnu/arch/sparc/mm/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/sparc/mm/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,6 @@
 obj-y                   += fault_$(BITS).o
 obj-y                   += init_$(BITS).o
 obj-$(CONFIG_SPARC32)   += loadmmu.o
-obj-y                   += generic_$(BITS).o
 obj-$(CONFIG_SPARC32)   += extable.o btfixup.o srmmu.o iommu.o io-unit.o
 obj-$(CONFIG_SPARC32)   += hypersparc.o viking.o tsunami.o swift.o
 obj-$(CONFIG_SPARC_LEON)+= leon_mm.o
diff -druN linux-libre-3.1-gnu/arch/tile/configs/tilegx_defconfig linux-libre-3.2-gnu/arch/tile/configs/tilegx_defconfig
--- linux-libre-3.1-gnu/arch/tile/configs/tilegx_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/configs/tilegx_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,6 @@
 CONFIG_HAVE_SETUP_PER_CPU_AREA=y
 CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
 CONFIG_SYS_SUPPORTS_HUGETLBFS=y
-CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_DEFAULT_MIGRATION_COST=10000000
diff -druN linux-libre-3.1-gnu/arch/tile/configs/tilepro_defconfig linux-libre-3.2-gnu/arch/tile/configs/tilepro_defconfig
--- linux-libre-3.1-gnu/arch/tile/configs/tilepro_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/configs/tilepro_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,6 @@
 CONFIG_HAVE_SETUP_PER_CPU_AREA=y
 CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
 CONFIG_SYS_SUPPORTS_HUGETLBFS=y
-CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_DEFAULT_MIGRATION_COST=10000000
diff -druN linux-libre-3.1-gnu/arch/tile/include/arch/abi.h linux-libre-3.2-gnu/arch/tile/include/arch/abi.h
--- linux-libre-3.1-gnu/arch/tile/include/arch/abi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/include/arch/abi.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,13 +15,78 @@
 /**
  * @file
  *
- * ABI-related register definitions helpful when writing assembly code.
+ * ABI-related register definitions.
  */
 
 #ifndef __ARCH_ABI_H__
-#define __ARCH_ABI_H__
 
-#include <arch/chip.h>
+#if !defined __need_int_reg_t && !defined __DOXYGEN__
+# define __ARCH_ABI_H__
+# include <arch/chip.h>
+#endif
+
+/* Provide the basic machine types. */
+#ifndef __INT_REG_BITS
+
+/** Number of bits in a register. */
+#if defined __tilegx__
+# define __INT_REG_BITS 64
+#elif defined __tilepro__
+# define __INT_REG_BITS 32
+#elif !defined __need_int_reg_t
+# include <arch/chip.h>
+# define __INT_REG_BITS CHIP_WORD_SIZE()
+#else
+# error Unrecognized architecture with __need_int_reg_t
+#endif
+
+#if __INT_REG_BITS == 64
+
+#ifndef __ASSEMBLER__
+/** Unsigned type that can hold a register. */
+typedef unsigned long long __uint_reg_t;
+
+/** Signed type that can hold a register. */
+typedef long long __int_reg_t;
+#endif
+
+/** String prefix to use for printf(). */
+#define __INT_REG_FMT "ll"
+
+#else
+
+#ifndef __ASSEMBLER__
+/** Unsigned type that can hold a register. */
+typedef unsigned long __uint_reg_t;
+
+/** Signed type that can hold a register. */
+typedef long __int_reg_t;
+#endif
+
+/** String prefix to use for printf(). */
+#define __INT_REG_FMT "l"
+
+#endif
+#endif /* __INT_REG_BITS */
+
+
+#ifndef __need_int_reg_t
+
+
+#ifndef __ASSEMBLER__
+/** Unsigned type that can hold a register. */
+typedef __uint_reg_t uint_reg_t;
+
+/** Signed type that can hold a register. */
+typedef __int_reg_t int_reg_t;
+#endif
+
+/** String prefix to use for printf(). */
+#define INT_REG_FMT __INT_REG_FMT
+
+/** Number of bits in a register. */
+#define INT_REG_BITS __INT_REG_BITS
+
 
 /* Registers 0 - 55 are "normal", but some perform special roles. */
 
@@ -59,7 +124,7 @@
  * The ABI requires callers to allocate a caller state save area of
  * this many bytes at the bottom of each stack frame.
  */
-#define C_ABI_SAVE_AREA_SIZE (2 * (CHIP_WORD_SIZE() / 8))
+#define C_ABI_SAVE_AREA_SIZE (2 * (INT_REG_BITS / 8))
 
 /**
  * The operand to an 'info' opcode directing the backtracer to not
@@ -67,30 +132,10 @@
  */
 #define INFO_OP_CANNOT_BACKTRACE 2
 
-#ifndef __ASSEMBLER__
-#if CHIP_WORD_SIZE() > 32
 
-/** Unsigned type that can hold a register. */
-typedef unsigned long long uint_reg_t;
-
-/** Signed type that can hold a register. */
-typedef long long int_reg_t;
-
-/** String prefix to use for printf(). */
-#define INT_REG_FMT "ll"
-
-#elif !defined(__LP64__)   /* avoid confusion with LP64 cross-build tools */
-
-/** Unsigned type that can hold a register. */
-typedef unsigned long uint_reg_t;
-
-/** Signed type that can hold a register. */
-typedef long int_reg_t;
-
-/** String prefix to use for printf(). */
-#define INT_REG_FMT "l"
+#endif /* !__need_int_reg_t */
 
-#endif
-#endif /* __ASSEMBLER__ */
+/* Make sure we later can get all the definitions and declarations.  */
+#undef __need_int_reg_t
 
 #endif /* !__ARCH_ABI_H__ */
diff -druN linux-libre-3.1-gnu/arch/tile/include/arch/Kbuild linux-libre-3.2-gnu/arch/tile/include/arch/Kbuild
--- linux-libre-3.1-gnu/arch/tile/include/arch/Kbuild	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/tile/include/arch/Kbuild	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,17 @@
+header-y += abi.h
+header-y += chip.h
+header-y += chip_tile64.h
+header-y += chip_tilegx.h
+header-y += chip_tilepro.h
+header-y += icache.h
+header-y += interrupts.h
+header-y += interrupts_32.h
+header-y += interrupts_64.h
+header-y += opcode.h
+header-y += opcode_tilegx.h
+header-y += opcode_tilepro.h
+header-y += sim.h
+header-y += sim_def.h
+header-y += spr_def.h
+header-y += spr_def_32.h
+header-y += spr_def_64.h
diff -druN linux-libre-3.1-gnu/arch/tile/include/arch/opcode.h linux-libre-3.2-gnu/arch/tile/include/arch/opcode.h
--- linux-libre-3.1-gnu/arch/tile/include/arch/opcode.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/tile/include/arch/opcode.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#if defined(__tilepro__)
+#include <arch/opcode_tilepro.h>
+#elif defined(__tilegx__)
+#include <arch/opcode_tilegx.h>
+#else
+#error Unexpected Tilera chip type
+#endif
diff -druN linux-libre-3.1-gnu/arch/tile/include/arch/opcode_tilegx.h linux-libre-3.2-gnu/arch/tile/include/arch/opcode_tilegx.h
--- linux-libre-3.1-gnu/arch/tile/include/arch/opcode_tilegx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/tile/include/arch/opcode_tilegx.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1405 @@
+/* TILE-Gx opcode information.
+ *
+ * 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 __ARCH_OPCODE_H__
+#define __ARCH_OPCODE_H__
+
+#ifndef __ASSEMBLER__
+
+typedef unsigned long long tilegx_bundle_bits;
+
+/* These are the bits that determine if a bundle is in the X encoding. */
+#define TILEGX_BUNDLE_MODE_MASK ((tilegx_bundle_bits)3 << 62)
+
+enum
+{
+  /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */
+  TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE = 3,
+
+  /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */
+  TILEGX_NUM_PIPELINE_ENCODINGS = 5,
+
+  /* Log base 2 of TILEGX_BUNDLE_SIZE_IN_BYTES. */
+  TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES = 3,
+
+  /* Instructions take this many bytes. */
+  TILEGX_BUNDLE_SIZE_IN_BYTES = 1 << TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES,
+
+  /* Log base 2 of TILEGX_BUNDLE_ALIGNMENT_IN_BYTES. */
+  TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3,
+
+  /* Bundles should be aligned modulo this number of bytes. */
+  TILEGX_BUNDLE_ALIGNMENT_IN_BYTES =
+    (1 << TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES),
+
+  /* Number of registers (some are magic, such as network I/O). */
+  TILEGX_NUM_REGISTERS = 64,
+};
+
+/* Make a few "tile_" variables to simplify common code between
+   architectures.  */
+
+typedef tilegx_bundle_bits tile_bundle_bits;
+#define TILE_BUNDLE_SIZE_IN_BYTES TILEGX_BUNDLE_SIZE_IN_BYTES
+#define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEGX_BUNDLE_ALIGNMENT_IN_BYTES
+#define TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES \
+  TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES
+
+/* 64-bit pattern for a { bpt ; nop } bundle. */
+#define TILEGX_BPT_BUNDLE 0x286a44ae51485000ULL
+
+static __inline unsigned int
+get_BFEnd_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_BFOpcodeExtension_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 24)) & 0xf);
+}
+
+static __inline unsigned int
+get_BFStart_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3f);
+}
+
+static __inline unsigned int
+get_BrOff_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x0000003f) |
+         (((unsigned int)(n >> 37)) & 0x0001ffc0);
+}
+
+static __inline unsigned int
+get_BrType_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 54)) & 0x1f);
+}
+
+static __inline unsigned int
+get_Dest_Imm8_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x0000003f) |
+         (((unsigned int)(n >> 43)) & 0x000000c0);
+}
+
+static __inline unsigned int
+get_Dest_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Imm16_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xffff);
+}
+
+static __inline unsigned int
+get_Imm16_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xffff);
+}
+
+static __inline unsigned int
+get_Imm8OpcodeExtension_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 20)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8OpcodeExtension_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 51)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xff);
+}
+
+static __inline unsigned int
+get_JumpOff_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x7ffffff);
+}
+
+static __inline unsigned int
+get_JumpOpcodeExtension_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 58)) & 0x1);
+}
+
+static __inline unsigned int
+get_MF_Imm14_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x3fff);
+}
+
+static __inline unsigned int
+get_MT_Imm14_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x0000003f) |
+         (((unsigned int)(n >> 37)) & 0x00003fc0);
+}
+
+static __inline unsigned int
+get_Mode(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 62)) & 0x3);
+}
+
+static __inline unsigned int
+get_Opcode_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 28)) & 0x7);
+}
+
+static __inline unsigned int
+get_Opcode_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 59)) & 0x7);
+}
+
+static __inline unsigned int
+get_Opcode_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 27)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 58)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y2(tilegx_bundle_bits n)
+{
+  return (((n >> 26)) & 0x00000001) |
+         (((unsigned int)(n >> 56)) & 0x00000002);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x3);
+}
+
+static __inline unsigned int
+get_ShAmt_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_ShAmt_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_ShAmt_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_ShAmt_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_ShiftOpcodeExtension_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_ShiftOpcodeExtension_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_ShiftOpcodeExtension_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3);
+}
+
+static __inline unsigned int
+get_ShiftOpcodeExtension_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x3);
+}
+
+static __inline unsigned int
+get_SrcA_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 6)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 6)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y2(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 20)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcBDest_Y2(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 51)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_UnaryOpcodeExtension_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_UnaryOpcodeExtension_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_UnaryOpcodeExtension_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_UnaryOpcodeExtension_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+
+static __inline int
+sign_extend(int n, int num_bits)
+{
+  int shift = (int)(sizeof(int) * 8 - num_bits);
+  return (n << shift) >> shift;
+}
+
+
+
+static __inline tilegx_bundle_bits
+create_BFEnd_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_BFOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xf) << 24);
+}
+
+static __inline tilegx_bundle_bits
+create_BFStart_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_BrOff_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
+         (((tilegx_bundle_bits)(n & 0x0001ffc0)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_BrType_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x1f)) << 54);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_Imm8_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
+         (((tilegx_bundle_bits)(n & 0x000000c0)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 0);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 31);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 0);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 31);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm16_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xffff) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm16_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0xffff)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8OpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 20);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8OpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0xff)) << 51);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0xff)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0xff)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_JumpOff_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x7ffffff)) << 31);
+}
+
+static __inline tilegx_bundle_bits
+create_JumpOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x1)) << 58);
+}
+
+static __inline tilegx_bundle_bits
+create_MF_Imm14_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3fff)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_MT_Imm14_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
+         (((tilegx_bundle_bits)(n & 0x00003fc0)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_Mode(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3)) << 62);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x7) << 28);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x7)) << 59);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xf) << 27);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0xf)) << 58);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x00000001) << 26) |
+         (((tilegx_bundle_bits)(n & 0x00000002)) << 56);
+}
+
+static __inline tilegx_bundle_bits
+create_RRROpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3ff) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_RRROpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3ff)) << 49);
+}
+
+static __inline tilegx_bundle_bits
+create_RRROpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_RRROpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3)) << 49);
+}
+
+static __inline tilegx_bundle_bits
+create_ShAmt_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_ShAmt_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_ShAmt_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_ShAmt_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_ShiftOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3ff) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_ShiftOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3ff)) << 49);
+}
+
+static __inline tilegx_bundle_bits
+create_ShiftOpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_ShiftOpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3)) << 49);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 6);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 6);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 20);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcBDest_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 51);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcB_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcB_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcB_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcB_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_UnaryOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_UnaryOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_UnaryOpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_UnaryOpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+
+enum
+{
+  ADDI_IMM8_OPCODE_X0 = 1,
+  ADDI_IMM8_OPCODE_X1 = 1,
+  ADDI_OPCODE_Y0 = 0,
+  ADDI_OPCODE_Y1 = 1,
+  ADDLI_OPCODE_X0 = 1,
+  ADDLI_OPCODE_X1 = 0,
+  ADDXI_IMM8_OPCODE_X0 = 2,
+  ADDXI_IMM8_OPCODE_X1 = 2,
+  ADDXI_OPCODE_Y0 = 1,
+  ADDXI_OPCODE_Y1 = 2,
+  ADDXLI_OPCODE_X0 = 2,
+  ADDXLI_OPCODE_X1 = 1,
+  ADDXSC_RRR_0_OPCODE_X0 = 1,
+  ADDXSC_RRR_0_OPCODE_X1 = 1,
+  ADDX_RRR_0_OPCODE_X0 = 2,
+  ADDX_RRR_0_OPCODE_X1 = 2,
+  ADDX_RRR_0_OPCODE_Y0 = 0,
+  ADDX_SPECIAL_0_OPCODE_Y1 = 0,
+  ADD_RRR_0_OPCODE_X0 = 3,
+  ADD_RRR_0_OPCODE_X1 = 3,
+  ADD_RRR_0_OPCODE_Y0 = 1,
+  ADD_SPECIAL_0_OPCODE_Y1 = 1,
+  ANDI_IMM8_OPCODE_X0 = 3,
+  ANDI_IMM8_OPCODE_X1 = 3,
+  ANDI_OPCODE_Y0 = 2,
+  ANDI_OPCODE_Y1 = 3,
+  AND_RRR_0_OPCODE_X0 = 4,
+  AND_RRR_0_OPCODE_X1 = 4,
+  AND_RRR_5_OPCODE_Y0 = 0,
+  AND_RRR_5_OPCODE_Y1 = 0,
+  BEQZT_BRANCH_OPCODE_X1 = 16,
+  BEQZ_BRANCH_OPCODE_X1 = 17,
+  BFEXTS_BF_OPCODE_X0 = 4,
+  BFEXTU_BF_OPCODE_X0 = 5,
+  BFINS_BF_OPCODE_X0 = 6,
+  BF_OPCODE_X0 = 3,
+  BGEZT_BRANCH_OPCODE_X1 = 18,
+  BGEZ_BRANCH_OPCODE_X1 = 19,
+  BGTZT_BRANCH_OPCODE_X1 = 20,
+  BGTZ_BRANCH_OPCODE_X1 = 21,
+  BLBCT_BRANCH_OPCODE_X1 = 22,
+  BLBC_BRANCH_OPCODE_X1 = 23,
+  BLBST_BRANCH_OPCODE_X1 = 24,
+  BLBS_BRANCH_OPCODE_X1 = 25,
+  BLEZT_BRANCH_OPCODE_X1 = 26,
+  BLEZ_BRANCH_OPCODE_X1 = 27,
+  BLTZT_BRANCH_OPCODE_X1 = 28,
+  BLTZ_BRANCH_OPCODE_X1 = 29,
+  BNEZT_BRANCH_OPCODE_X1 = 30,
+  BNEZ_BRANCH_OPCODE_X1 = 31,
+  BRANCH_OPCODE_X1 = 2,
+  CMOVEQZ_RRR_0_OPCODE_X0 = 5,
+  CMOVEQZ_RRR_4_OPCODE_Y0 = 0,
+  CMOVNEZ_RRR_0_OPCODE_X0 = 6,
+  CMOVNEZ_RRR_4_OPCODE_Y0 = 1,
+  CMPEQI_IMM8_OPCODE_X0 = 4,
+  CMPEQI_IMM8_OPCODE_X1 = 4,
+  CMPEQI_OPCODE_Y0 = 3,
+  CMPEQI_OPCODE_Y1 = 4,
+  CMPEQ_RRR_0_OPCODE_X0 = 7,
+  CMPEQ_RRR_0_OPCODE_X1 = 5,
+  CMPEQ_RRR_3_OPCODE_Y0 = 0,
+  CMPEQ_RRR_3_OPCODE_Y1 = 2,
+  CMPEXCH4_RRR_0_OPCODE_X1 = 6,
+  CMPEXCH_RRR_0_OPCODE_X1 = 7,
+  CMPLES_RRR_0_OPCODE_X0 = 8,
+  CMPLES_RRR_0_OPCODE_X1 = 8,
+  CMPLES_RRR_2_OPCODE_Y0 = 0,
+  CMPLES_RRR_2_OPCODE_Y1 = 0,
+  CMPLEU_RRR_0_OPCODE_X0 = 9,
+  CMPLEU_RRR_0_OPCODE_X1 = 9,
+  CMPLEU_RRR_2_OPCODE_Y0 = 1,
+  CMPLEU_RRR_2_OPCODE_Y1 = 1,
+  CMPLTSI_IMM8_OPCODE_X0 = 5,
+  CMPLTSI_IMM8_OPCODE_X1 = 5,
+  CMPLTSI_OPCODE_Y0 = 4,
+  CMPLTSI_OPCODE_Y1 = 5,
+  CMPLTS_RRR_0_OPCODE_X0 = 10,
+  CMPLTS_RRR_0_OPCODE_X1 = 10,
+  CMPLTS_RRR_2_OPCODE_Y0 = 2,
+  CMPLTS_RRR_2_OPCODE_Y1 = 2,
+  CMPLTUI_IMM8_OPCODE_X0 = 6,
+  CMPLTUI_IMM8_OPCODE_X1 = 6,
+  CMPLTU_RRR_0_OPCODE_X0 = 11,
+  CMPLTU_RRR_0_OPCODE_X1 = 11,
+  CMPLTU_RRR_2_OPCODE_Y0 = 3,
+  CMPLTU_RRR_2_OPCODE_Y1 = 3,
+  CMPNE_RRR_0_OPCODE_X0 = 12,
+  CMPNE_RRR_0_OPCODE_X1 = 12,
+  CMPNE_RRR_3_OPCODE_Y0 = 1,
+  CMPNE_RRR_3_OPCODE_Y1 = 3,
+  CMULAF_RRR_0_OPCODE_X0 = 13,
+  CMULA_RRR_0_OPCODE_X0 = 14,
+  CMULFR_RRR_0_OPCODE_X0 = 15,
+  CMULF_RRR_0_OPCODE_X0 = 16,
+  CMULHR_RRR_0_OPCODE_X0 = 17,
+  CMULH_RRR_0_OPCODE_X0 = 18,
+  CMUL_RRR_0_OPCODE_X0 = 19,
+  CNTLZ_UNARY_OPCODE_X0 = 1,
+  CNTLZ_UNARY_OPCODE_Y0 = 1,
+  CNTTZ_UNARY_OPCODE_X0 = 2,
+  CNTTZ_UNARY_OPCODE_Y0 = 2,
+  CRC32_32_RRR_0_OPCODE_X0 = 20,
+  CRC32_8_RRR_0_OPCODE_X0 = 21,
+  DBLALIGN2_RRR_0_OPCODE_X0 = 22,
+  DBLALIGN2_RRR_0_OPCODE_X1 = 13,
+  DBLALIGN4_RRR_0_OPCODE_X0 = 23,
+  DBLALIGN4_RRR_0_OPCODE_X1 = 14,
+  DBLALIGN6_RRR_0_OPCODE_X0 = 24,
+  DBLALIGN6_RRR_0_OPCODE_X1 = 15,
+  DBLALIGN_RRR_0_OPCODE_X0 = 25,
+  DRAIN_UNARY_OPCODE_X1 = 1,
+  DTLBPR_UNARY_OPCODE_X1 = 2,
+  EXCH4_RRR_0_OPCODE_X1 = 16,
+  EXCH_RRR_0_OPCODE_X1 = 17,
+  FDOUBLE_ADDSUB_RRR_0_OPCODE_X0 = 26,
+  FDOUBLE_ADD_FLAGS_RRR_0_OPCODE_X0 = 27,
+  FDOUBLE_MUL_FLAGS_RRR_0_OPCODE_X0 = 28,
+  FDOUBLE_PACK1_RRR_0_OPCODE_X0 = 29,
+  FDOUBLE_PACK2_RRR_0_OPCODE_X0 = 30,
+  FDOUBLE_SUB_FLAGS_RRR_0_OPCODE_X0 = 31,
+  FDOUBLE_UNPACK_MAX_RRR_0_OPCODE_X0 = 32,
+  FDOUBLE_UNPACK_MIN_RRR_0_OPCODE_X0 = 33,
+  FETCHADD4_RRR_0_OPCODE_X1 = 18,
+  FETCHADDGEZ4_RRR_0_OPCODE_X1 = 19,
+  FETCHADDGEZ_RRR_0_OPCODE_X1 = 20,
+  FETCHADD_RRR_0_OPCODE_X1 = 21,
+  FETCHAND4_RRR_0_OPCODE_X1 = 22,
+  FETCHAND_RRR_0_OPCODE_X1 = 23,
+  FETCHOR4_RRR_0_OPCODE_X1 = 24,
+  FETCHOR_RRR_0_OPCODE_X1 = 25,
+  FINV_UNARY_OPCODE_X1 = 3,
+  FLUSHWB_UNARY_OPCODE_X1 = 4,
+  FLUSH_UNARY_OPCODE_X1 = 5,
+  FNOP_UNARY_OPCODE_X0 = 3,
+  FNOP_UNARY_OPCODE_X1 = 6,
+  FNOP_UNARY_OPCODE_Y0 = 3,
+  FNOP_UNARY_OPCODE_Y1 = 8,
+  FSINGLE_ADD1_RRR_0_OPCODE_X0 = 34,
+  FSINGLE_ADDSUB2_RRR_0_OPCODE_X0 = 35,
+  FSINGLE_MUL1_RRR_0_OPCODE_X0 = 36,
+  FSINGLE_MUL2_RRR_0_OPCODE_X0 = 37,
+  FSINGLE_PACK1_UNARY_OPCODE_X0 = 4,
+  FSINGLE_PACK1_UNARY_OPCODE_Y0 = 4,
+  FSINGLE_PACK2_RRR_0_OPCODE_X0 = 38,
+  FSINGLE_SUB1_RRR_0_OPCODE_X0 = 39,
+  ICOH_UNARY_OPCODE_X1 = 7,
+  ILL_UNARY_OPCODE_X1 = 8,
+  ILL_UNARY_OPCODE_Y1 = 9,
+  IMM8_OPCODE_X0 = 4,
+  IMM8_OPCODE_X1 = 3,
+  INV_UNARY_OPCODE_X1 = 9,
+  IRET_UNARY_OPCODE_X1 = 10,
+  JALRP_UNARY_OPCODE_X1 = 11,
+  JALRP_UNARY_OPCODE_Y1 = 10,
+  JALR_UNARY_OPCODE_X1 = 12,
+  JALR_UNARY_OPCODE_Y1 = 11,
+  JAL_JUMP_OPCODE_X1 = 0,
+  JRP_UNARY_OPCODE_X1 = 13,
+  JRP_UNARY_OPCODE_Y1 = 12,
+  JR_UNARY_OPCODE_X1 = 14,
+  JR_UNARY_OPCODE_Y1 = 13,
+  JUMP_OPCODE_X1 = 4,
+  J_JUMP_OPCODE_X1 = 1,
+  LD1S_ADD_IMM8_OPCODE_X1 = 7,
+  LD1S_OPCODE_Y2 = 0,
+  LD1S_UNARY_OPCODE_X1 = 15,
+  LD1U_ADD_IMM8_OPCODE_X1 = 8,
+  LD1U_OPCODE_Y2 = 1,
+  LD1U_UNARY_OPCODE_X1 = 16,
+  LD2S_ADD_IMM8_OPCODE_X1 = 9,
+  LD2S_OPCODE_Y2 = 2,
+  LD2S_UNARY_OPCODE_X1 = 17,
+  LD2U_ADD_IMM8_OPCODE_X1 = 10,
+  LD2U_OPCODE_Y2 = 3,
+  LD2U_UNARY_OPCODE_X1 = 18,
+  LD4S_ADD_IMM8_OPCODE_X1 = 11,
+  LD4S_OPCODE_Y2 = 1,
+  LD4S_UNARY_OPCODE_X1 = 19,
+  LD4U_ADD_IMM8_OPCODE_X1 = 12,
+  LD4U_OPCODE_Y2 = 2,
+  LD4U_UNARY_OPCODE_X1 = 20,
+  LDNA_UNARY_OPCODE_X1 = 21,
+  LDNT1S_ADD_IMM8_OPCODE_X1 = 13,
+  LDNT1S_UNARY_OPCODE_X1 = 22,
+  LDNT1U_ADD_IMM8_OPCODE_X1 = 14,
+  LDNT1U_UNARY_OPCODE_X1 = 23,
+  LDNT2S_ADD_IMM8_OPCODE_X1 = 15,
+  LDNT2S_UNARY_OPCODE_X1 = 24,
+  LDNT2U_ADD_IMM8_OPCODE_X1 = 16,
+  LDNT2U_UNARY_OPCODE_X1 = 25,
+  LDNT4S_ADD_IMM8_OPCODE_X1 = 17,
+  LDNT4S_UNARY_OPCODE_X1 = 26,
+  LDNT4U_ADD_IMM8_OPCODE_X1 = 18,
+  LDNT4U_UNARY_OPCODE_X1 = 27,
+  LDNT_ADD_IMM8_OPCODE_X1 = 19,
+  LDNT_UNARY_OPCODE_X1 = 28,
+  LD_ADD_IMM8_OPCODE_X1 = 20,
+  LD_OPCODE_Y2 = 3,
+  LD_UNARY_OPCODE_X1 = 29,
+  LNK_UNARY_OPCODE_X1 = 30,
+  LNK_UNARY_OPCODE_Y1 = 14,
+  LWNA_ADD_IMM8_OPCODE_X1 = 21,
+  MFSPR_IMM8_OPCODE_X1 = 22,
+  MF_UNARY_OPCODE_X1 = 31,
+  MM_BF_OPCODE_X0 = 7,
+  MNZ_RRR_0_OPCODE_X0 = 40,
+  MNZ_RRR_0_OPCODE_X1 = 26,
+  MNZ_RRR_4_OPCODE_Y0 = 2,
+  MNZ_RRR_4_OPCODE_Y1 = 2,
+  MODE_OPCODE_YA2 = 1,
+  MODE_OPCODE_YB2 = 2,
+  MODE_OPCODE_YC2 = 3,
+  MTSPR_IMM8_OPCODE_X1 = 23,
+  MULAX_RRR_0_OPCODE_X0 = 41,
+  MULAX_RRR_3_OPCODE_Y0 = 2,
+  MULA_HS_HS_RRR_0_OPCODE_X0 = 42,
+  MULA_HS_HS_RRR_9_OPCODE_Y0 = 0,
+  MULA_HS_HU_RRR_0_OPCODE_X0 = 43,
+  MULA_HS_LS_RRR_0_OPCODE_X0 = 44,
+  MULA_HS_LU_RRR_0_OPCODE_X0 = 45,
+  MULA_HU_HU_RRR_0_OPCODE_X0 = 46,
+  MULA_HU_HU_RRR_9_OPCODE_Y0 = 1,
+  MULA_HU_LS_RRR_0_OPCODE_X0 = 47,
+  MULA_HU_LU_RRR_0_OPCODE_X0 = 48,
+  MULA_LS_LS_RRR_0_OPCODE_X0 = 49,
+  MULA_LS_LS_RRR_9_OPCODE_Y0 = 2,
+  MULA_LS_LU_RRR_0_OPCODE_X0 = 50,
+  MULA_LU_LU_RRR_0_OPCODE_X0 = 51,
+  MULA_LU_LU_RRR_9_OPCODE_Y0 = 3,
+  MULX_RRR_0_OPCODE_X0 = 52,
+  MULX_RRR_3_OPCODE_Y0 = 3,
+  MUL_HS_HS_RRR_0_OPCODE_X0 = 53,
+  MUL_HS_HS_RRR_8_OPCODE_Y0 = 0,
+  MUL_HS_HU_RRR_0_OPCODE_X0 = 54,
+  MUL_HS_LS_RRR_0_OPCODE_X0 = 55,
+  MUL_HS_LU_RRR_0_OPCODE_X0 = 56,
+  MUL_HU_HU_RRR_0_OPCODE_X0 = 57,
+  MUL_HU_HU_RRR_8_OPCODE_Y0 = 1,
+  MUL_HU_LS_RRR_0_OPCODE_X0 = 58,
+  MUL_HU_LU_RRR_0_OPCODE_X0 = 59,
+  MUL_LS_LS_RRR_0_OPCODE_X0 = 60,
+  MUL_LS_LS_RRR_8_OPCODE_Y0 = 2,
+  MUL_LS_LU_RRR_0_OPCODE_X0 = 61,
+  MUL_LU_LU_RRR_0_OPCODE_X0 = 62,
+  MUL_LU_LU_RRR_8_OPCODE_Y0 = 3,
+  MZ_RRR_0_OPCODE_X0 = 63,
+  MZ_RRR_0_OPCODE_X1 = 27,
+  MZ_RRR_4_OPCODE_Y0 = 3,
+  MZ_RRR_4_OPCODE_Y1 = 3,
+  NAP_UNARY_OPCODE_X1 = 32,
+  NOP_UNARY_OPCODE_X0 = 5,
+  NOP_UNARY_OPCODE_X1 = 33,
+  NOP_UNARY_OPCODE_Y0 = 5,
+  NOP_UNARY_OPCODE_Y1 = 15,
+  NOR_RRR_0_OPCODE_X0 = 64,
+  NOR_RRR_0_OPCODE_X1 = 28,
+  NOR_RRR_5_OPCODE_Y0 = 1,
+  NOR_RRR_5_OPCODE_Y1 = 1,
+  ORI_IMM8_OPCODE_X0 = 7,
+  ORI_IMM8_OPCODE_X1 = 24,
+  OR_RRR_0_OPCODE_X0 = 65,
+  OR_RRR_0_OPCODE_X1 = 29,
+  OR_RRR_5_OPCODE_Y0 = 2,
+  OR_RRR_5_OPCODE_Y1 = 2,
+  PCNT_UNARY_OPCODE_X0 = 6,
+  PCNT_UNARY_OPCODE_Y0 = 6,
+  REVBITS_UNARY_OPCODE_X0 = 7,
+  REVBITS_UNARY_OPCODE_Y0 = 7,
+  REVBYTES_UNARY_OPCODE_X0 = 8,
+  REVBYTES_UNARY_OPCODE_Y0 = 8,
+  ROTLI_SHIFT_OPCODE_X0 = 1,
+  ROTLI_SHIFT_OPCODE_X1 = 1,
+  ROTLI_SHIFT_OPCODE_Y0 = 0,
+  ROTLI_SHIFT_OPCODE_Y1 = 0,
+  ROTL_RRR_0_OPCODE_X0 = 66,
+  ROTL_RRR_0_OPCODE_X1 = 30,
+  ROTL_RRR_6_OPCODE_Y0 = 0,
+  ROTL_RRR_6_OPCODE_Y1 = 0,
+  RRR_0_OPCODE_X0 = 5,
+  RRR_0_OPCODE_X1 = 5,
+  RRR_0_OPCODE_Y0 = 5,
+  RRR_0_OPCODE_Y1 = 6,
+  RRR_1_OPCODE_Y0 = 6,
+  RRR_1_OPCODE_Y1 = 7,
+  RRR_2_OPCODE_Y0 = 7,
+  RRR_2_OPCODE_Y1 = 8,
+  RRR_3_OPCODE_Y0 = 8,
+  RRR_3_OPCODE_Y1 = 9,
+  RRR_4_OPCODE_Y0 = 9,
+  RRR_4_OPCODE_Y1 = 10,
+  RRR_5_OPCODE_Y0 = 10,
+  RRR_5_OPCODE_Y1 = 11,
+  RRR_6_OPCODE_Y0 = 11,
+  RRR_6_OPCODE_Y1 = 12,
+  RRR_7_OPCODE_Y0 = 12,
+  RRR_7_OPCODE_Y1 = 13,
+  RRR_8_OPCODE_Y0 = 13,
+  RRR_9_OPCODE_Y0 = 14,
+  SHIFT_OPCODE_X0 = 6,
+  SHIFT_OPCODE_X1 = 6,
+  SHIFT_OPCODE_Y0 = 15,
+  SHIFT_OPCODE_Y1 = 14,
+  SHL16INSLI_OPCODE_X0 = 7,
+  SHL16INSLI_OPCODE_X1 = 7,
+  SHL1ADDX_RRR_0_OPCODE_X0 = 67,
+  SHL1ADDX_RRR_0_OPCODE_X1 = 31,
+  SHL1ADDX_RRR_7_OPCODE_Y0 = 1,
+  SHL1ADDX_RRR_7_OPCODE_Y1 = 1,
+  SHL1ADD_RRR_0_OPCODE_X0 = 68,
+  SHL1ADD_RRR_0_OPCODE_X1 = 32,
+  SHL1ADD_RRR_1_OPCODE_Y0 = 0,
+  SHL1ADD_RRR_1_OPCODE_Y1 = 0,
+  SHL2ADDX_RRR_0_OPCODE_X0 = 69,
+  SHL2ADDX_RRR_0_OPCODE_X1 = 33,
+  SHL2ADDX_RRR_7_OPCODE_Y0 = 2,
+  SHL2ADDX_RRR_7_OPCODE_Y1 = 2,
+  SHL2ADD_RRR_0_OPCODE_X0 = 70,
+  SHL2ADD_RRR_0_OPCODE_X1 = 34,
+  SHL2ADD_RRR_1_OPCODE_Y0 = 1,
+  SHL2ADD_RRR_1_OPCODE_Y1 = 1,
+  SHL3ADDX_RRR_0_OPCODE_X0 = 71,
+  SHL3ADDX_RRR_0_OPCODE_X1 = 35,
+  SHL3ADDX_RRR_7_OPCODE_Y0 = 3,
+  SHL3ADDX_RRR_7_OPCODE_Y1 = 3,
+  SHL3ADD_RRR_0_OPCODE_X0 = 72,
+  SHL3ADD_RRR_0_OPCODE_X1 = 36,
+  SHL3ADD_RRR_1_OPCODE_Y0 = 2,
+  SHL3ADD_RRR_1_OPCODE_Y1 = 2,
+  SHLI_SHIFT_OPCODE_X0 = 2,
+  SHLI_SHIFT_OPCODE_X1 = 2,
+  SHLI_SHIFT_OPCODE_Y0 = 1,
+  SHLI_SHIFT_OPCODE_Y1 = 1,
+  SHLXI_SHIFT_OPCODE_X0 = 3,
+  SHLXI_SHIFT_OPCODE_X1 = 3,
+  SHLX_RRR_0_OPCODE_X0 = 73,
+  SHLX_RRR_0_OPCODE_X1 = 37,
+  SHL_RRR_0_OPCODE_X0 = 74,
+  SHL_RRR_0_OPCODE_X1 = 38,
+  SHL_RRR_6_OPCODE_Y0 = 1,
+  SHL_RRR_6_OPCODE_Y1 = 1,
+  SHRSI_SHIFT_OPCODE_X0 = 4,
+  SHRSI_SHIFT_OPCODE_X1 = 4,
+  SHRSI_SHIFT_OPCODE_Y0 = 2,
+  SHRSI_SHIFT_OPCODE_Y1 = 2,
+  SHRS_RRR_0_OPCODE_X0 = 75,
+  SHRS_RRR_0_OPCODE_X1 = 39,
+  SHRS_RRR_6_OPCODE_Y0 = 2,
+  SHRS_RRR_6_OPCODE_Y1 = 2,
+  SHRUI_SHIFT_OPCODE_X0 = 5,
+  SHRUI_SHIFT_OPCODE_X1 = 5,
+  SHRUI_SHIFT_OPCODE_Y0 = 3,
+  SHRUI_SHIFT_OPCODE_Y1 = 3,
+  SHRUXI_SHIFT_OPCODE_X0 = 6,
+  SHRUXI_SHIFT_OPCODE_X1 = 6,
+  SHRUX_RRR_0_OPCODE_X0 = 76,
+  SHRUX_RRR_0_OPCODE_X1 = 40,
+  SHRU_RRR_0_OPCODE_X0 = 77,
+  SHRU_RRR_0_OPCODE_X1 = 41,
+  SHRU_RRR_6_OPCODE_Y0 = 3,
+  SHRU_RRR_6_OPCODE_Y1 = 3,
+  SHUFFLEBYTES_RRR_0_OPCODE_X0 = 78,
+  ST1_ADD_IMM8_OPCODE_X1 = 25,
+  ST1_OPCODE_Y2 = 0,
+  ST1_RRR_0_OPCODE_X1 = 42,
+  ST2_ADD_IMM8_OPCODE_X1 = 26,
+  ST2_OPCODE_Y2 = 1,
+  ST2_RRR_0_OPCODE_X1 = 43,
+  ST4_ADD_IMM8_OPCODE_X1 = 27,
+  ST4_OPCODE_Y2 = 2,
+  ST4_RRR_0_OPCODE_X1 = 44,
+  STNT1_ADD_IMM8_OPCODE_X1 = 28,
+  STNT1_RRR_0_OPCODE_X1 = 45,
+  STNT2_ADD_IMM8_OPCODE_X1 = 29,
+  STNT2_RRR_0_OPCODE_X1 = 46,
+  STNT4_ADD_IMM8_OPCODE_X1 = 30,
+  STNT4_RRR_0_OPCODE_X1 = 47,
+  STNT_ADD_IMM8_OPCODE_X1 = 31,
+  STNT_RRR_0_OPCODE_X1 = 48,
+  ST_ADD_IMM8_OPCODE_X1 = 32,
+  ST_OPCODE_Y2 = 3,
+  ST_RRR_0_OPCODE_X1 = 49,
+  SUBXSC_RRR_0_OPCODE_X0 = 79,
+  SUBXSC_RRR_0_OPCODE_X1 = 50,
+  SUBX_RRR_0_OPCODE_X0 = 80,
+  SUBX_RRR_0_OPCODE_X1 = 51,
+  SUBX_RRR_0_OPCODE_Y0 = 2,
+  SUBX_RRR_0_OPCODE_Y1 = 2,
+  SUB_RRR_0_OPCODE_X0 = 81,
+  SUB_RRR_0_OPCODE_X1 = 52,
+  SUB_RRR_0_OPCODE_Y0 = 3,
+  SUB_RRR_0_OPCODE_Y1 = 3,
+  SWINT0_UNARY_OPCODE_X1 = 34,
+  SWINT1_UNARY_OPCODE_X1 = 35,
+  SWINT2_UNARY_OPCODE_X1 = 36,
+  SWINT3_UNARY_OPCODE_X1 = 37,
+  TBLIDXB0_UNARY_OPCODE_X0 = 9,
+  TBLIDXB0_UNARY_OPCODE_Y0 = 9,
+  TBLIDXB1_UNARY_OPCODE_X0 = 10,
+  TBLIDXB1_UNARY_OPCODE_Y0 = 10,
+  TBLIDXB2_UNARY_OPCODE_X0 = 11,
+  TBLIDXB2_UNARY_OPCODE_Y0 = 11,
+  TBLIDXB3_UNARY_OPCODE_X0 = 12,
+  TBLIDXB3_UNARY_OPCODE_Y0 = 12,
+  UNARY_RRR_0_OPCODE_X0 = 82,
+  UNARY_RRR_0_OPCODE_X1 = 53,
+  UNARY_RRR_1_OPCODE_Y0 = 3,
+  UNARY_RRR_1_OPCODE_Y1 = 3,
+  V1ADDI_IMM8_OPCODE_X0 = 8,
+  V1ADDI_IMM8_OPCODE_X1 = 33,
+  V1ADDUC_RRR_0_OPCODE_X0 = 83,
+  V1ADDUC_RRR_0_OPCODE_X1 = 54,
+  V1ADD_RRR_0_OPCODE_X0 = 84,
+  V1ADD_RRR_0_OPCODE_X1 = 55,
+  V1ADIFFU_RRR_0_OPCODE_X0 = 85,
+  V1AVGU_RRR_0_OPCODE_X0 = 86,
+  V1CMPEQI_IMM8_OPCODE_X0 = 9,
+  V1CMPEQI_IMM8_OPCODE_X1 = 34,
+  V1CMPEQ_RRR_0_OPCODE_X0 = 87,
+  V1CMPEQ_RRR_0_OPCODE_X1 = 56,
+  V1CMPLES_RRR_0_OPCODE_X0 = 88,
+  V1CMPLES_RRR_0_OPCODE_X1 = 57,
+  V1CMPLEU_RRR_0_OPCODE_X0 = 89,
+  V1CMPLEU_RRR_0_OPCODE_X1 = 58,
+  V1CMPLTSI_IMM8_OPCODE_X0 = 10,
+  V1CMPLTSI_IMM8_OPCODE_X1 = 35,
+  V1CMPLTS_RRR_0_OPCODE_X0 = 90,
+  V1CMPLTS_RRR_0_OPCODE_X1 = 59,
+  V1CMPLTUI_IMM8_OPCODE_X0 = 11,
+  V1CMPLTUI_IMM8_OPCODE_X1 = 36,
+  V1CMPLTU_RRR_0_OPCODE_X0 = 91,
+  V1CMPLTU_RRR_0_OPCODE_X1 = 60,
+  V1CMPNE_RRR_0_OPCODE_X0 = 92,
+  V1CMPNE_RRR_0_OPCODE_X1 = 61,
+  V1DDOTPUA_RRR_0_OPCODE_X0 = 161,
+  V1DDOTPUSA_RRR_0_OPCODE_X0 = 93,
+  V1DDOTPUS_RRR_0_OPCODE_X0 = 94,
+  V1DDOTPU_RRR_0_OPCODE_X0 = 162,
+  V1DOTPA_RRR_0_OPCODE_X0 = 95,
+  V1DOTPUA_RRR_0_OPCODE_X0 = 163,
+  V1DOTPUSA_RRR_0_OPCODE_X0 = 96,
+  V1DOTPUS_RRR_0_OPCODE_X0 = 97,
+  V1DOTPU_RRR_0_OPCODE_X0 = 164,
+  V1DOTP_RRR_0_OPCODE_X0 = 98,
+  V1INT_H_RRR_0_OPCODE_X0 = 99,
+  V1INT_H_RRR_0_OPCODE_X1 = 62,
+  V1INT_L_RRR_0_OPCODE_X0 = 100,
+  V1INT_L_RRR_0_OPCODE_X1 = 63,
+  V1MAXUI_IMM8_OPCODE_X0 = 12,
+  V1MAXUI_IMM8_OPCODE_X1 = 37,
+  V1MAXU_RRR_0_OPCODE_X0 = 101,
+  V1MAXU_RRR_0_OPCODE_X1 = 64,
+  V1MINUI_IMM8_OPCODE_X0 = 13,
+  V1MINUI_IMM8_OPCODE_X1 = 38,
+  V1MINU_RRR_0_OPCODE_X0 = 102,
+  V1MINU_RRR_0_OPCODE_X1 = 65,
+  V1MNZ_RRR_0_OPCODE_X0 = 103,
+  V1MNZ_RRR_0_OPCODE_X1 = 66,
+  V1MULTU_RRR_0_OPCODE_X0 = 104,
+  V1MULUS_RRR_0_OPCODE_X0 = 105,
+  V1MULU_RRR_0_OPCODE_X0 = 106,
+  V1MZ_RRR_0_OPCODE_X0 = 107,
+  V1MZ_RRR_0_OPCODE_X1 = 67,
+  V1SADAU_RRR_0_OPCODE_X0 = 108,
+  V1SADU_RRR_0_OPCODE_X0 = 109,
+  V1SHLI_SHIFT_OPCODE_X0 = 7,
+  V1SHLI_SHIFT_OPCODE_X1 = 7,
+  V1SHL_RRR_0_OPCODE_X0 = 110,
+  V1SHL_RRR_0_OPCODE_X1 = 68,
+  V1SHRSI_SHIFT_OPCODE_X0 = 8,
+  V1SHRSI_SHIFT_OPCODE_X1 = 8,
+  V1SHRS_RRR_0_OPCODE_X0 = 111,
+  V1SHRS_RRR_0_OPCODE_X1 = 69,
+  V1SHRUI_SHIFT_OPCODE_X0 = 9,
+  V1SHRUI_SHIFT_OPCODE_X1 = 9,
+  V1SHRU_RRR_0_OPCODE_X0 = 112,
+  V1SHRU_RRR_0_OPCODE_X1 = 70,
+  V1SUBUC_RRR_0_OPCODE_X0 = 113,
+  V1SUBUC_RRR_0_OPCODE_X1 = 71,
+  V1SUB_RRR_0_OPCODE_X0 = 114,
+  V1SUB_RRR_0_OPCODE_X1 = 72,
+  V2ADDI_IMM8_OPCODE_X0 = 14,
+  V2ADDI_IMM8_OPCODE_X1 = 39,
+  V2ADDSC_RRR_0_OPCODE_X0 = 115,
+  V2ADDSC_RRR_0_OPCODE_X1 = 73,
+  V2ADD_RRR_0_OPCODE_X0 = 116,
+  V2ADD_RRR_0_OPCODE_X1 = 74,
+  V2ADIFFS_RRR_0_OPCODE_X0 = 117,
+  V2AVGS_RRR_0_OPCODE_X0 = 118,
+  V2CMPEQI_IMM8_OPCODE_X0 = 15,
+  V2CMPEQI_IMM8_OPCODE_X1 = 40,
+  V2CMPEQ_RRR_0_OPCODE_X0 = 119,
+  V2CMPEQ_RRR_0_OPCODE_X1 = 75,
+  V2CMPLES_RRR_0_OPCODE_X0 = 120,
+  V2CMPLES_RRR_0_OPCODE_X1 = 76,
+  V2CMPLEU_RRR_0_OPCODE_X0 = 121,
+  V2CMPLEU_RRR_0_OPCODE_X1 = 77,
+  V2CMPLTSI_IMM8_OPCODE_X0 = 16,
+  V2CMPLTSI_IMM8_OPCODE_X1 = 41,
+  V2CMPLTS_RRR_0_OPCODE_X0 = 122,
+  V2CMPLTS_RRR_0_OPCODE_X1 = 78,
+  V2CMPLTUI_IMM8_OPCODE_X0 = 17,
+  V2CMPLTUI_IMM8_OPCODE_X1 = 42,
+  V2CMPLTU_RRR_0_OPCODE_X0 = 123,
+  V2CMPLTU_RRR_0_OPCODE_X1 = 79,
+  V2CMPNE_RRR_0_OPCODE_X0 = 124,
+  V2CMPNE_RRR_0_OPCODE_X1 = 80,
+  V2DOTPA_RRR_0_OPCODE_X0 = 125,
+  V2DOTP_RRR_0_OPCODE_X0 = 126,
+  V2INT_H_RRR_0_OPCODE_X0 = 127,
+  V2INT_H_RRR_0_OPCODE_X1 = 81,
+  V2INT_L_RRR_0_OPCODE_X0 = 128,
+  V2INT_L_RRR_0_OPCODE_X1 = 82,
+  V2MAXSI_IMM8_OPCODE_X0 = 18,
+  V2MAXSI_IMM8_OPCODE_X1 = 43,
+  V2MAXS_RRR_0_OPCODE_X0 = 129,
+  V2MAXS_RRR_0_OPCODE_X1 = 83,
+  V2MINSI_IMM8_OPCODE_X0 = 19,
+  V2MINSI_IMM8_OPCODE_X1 = 44,
+  V2MINS_RRR_0_OPCODE_X0 = 130,
+  V2MINS_RRR_0_OPCODE_X1 = 84,
+  V2MNZ_RRR_0_OPCODE_X0 = 131,
+  V2MNZ_RRR_0_OPCODE_X1 = 85,
+  V2MULFSC_RRR_0_OPCODE_X0 = 132,
+  V2MULS_RRR_0_OPCODE_X0 = 133,
+  V2MULTS_RRR_0_OPCODE_X0 = 134,
+  V2MZ_RRR_0_OPCODE_X0 = 135,
+  V2MZ_RRR_0_OPCODE_X1 = 86,
+  V2PACKH_RRR_0_OPCODE_X0 = 136,
+  V2PACKH_RRR_0_OPCODE_X1 = 87,
+  V2PACKL_RRR_0_OPCODE_X0 = 137,
+  V2PACKL_RRR_0_OPCODE_X1 = 88,
+  V2PACKUC_RRR_0_OPCODE_X0 = 138,
+  V2PACKUC_RRR_0_OPCODE_X1 = 89,
+  V2SADAS_RRR_0_OPCODE_X0 = 139,
+  V2SADAU_RRR_0_OPCODE_X0 = 140,
+  V2SADS_RRR_0_OPCODE_X0 = 141,
+  V2SADU_RRR_0_OPCODE_X0 = 142,
+  V2SHLI_SHIFT_OPCODE_X0 = 10,
+  V2SHLI_SHIFT_OPCODE_X1 = 10,
+  V2SHLSC_RRR_0_OPCODE_X0 = 143,
+  V2SHLSC_RRR_0_OPCODE_X1 = 90,
+  V2SHL_RRR_0_OPCODE_X0 = 144,
+  V2SHL_RRR_0_OPCODE_X1 = 91,
+  V2SHRSI_SHIFT_OPCODE_X0 = 11,
+  V2SHRSI_SHIFT_OPCODE_X1 = 11,
+  V2SHRS_RRR_0_OPCODE_X0 = 145,
+  V2SHRS_RRR_0_OPCODE_X1 = 92,
+  V2SHRUI_SHIFT_OPCODE_X0 = 12,
+  V2SHRUI_SHIFT_OPCODE_X1 = 12,
+  V2SHRU_RRR_0_OPCODE_X0 = 146,
+  V2SHRU_RRR_0_OPCODE_X1 = 93,
+  V2SUBSC_RRR_0_OPCODE_X0 = 147,
+  V2SUBSC_RRR_0_OPCODE_X1 = 94,
+  V2SUB_RRR_0_OPCODE_X0 = 148,
+  V2SUB_RRR_0_OPCODE_X1 = 95,
+  V4ADDSC_RRR_0_OPCODE_X0 = 149,
+  V4ADDSC_RRR_0_OPCODE_X1 = 96,
+  V4ADD_RRR_0_OPCODE_X0 = 150,
+  V4ADD_RRR_0_OPCODE_X1 = 97,
+  V4INT_H_RRR_0_OPCODE_X0 = 151,
+  V4INT_H_RRR_0_OPCODE_X1 = 98,
+  V4INT_L_RRR_0_OPCODE_X0 = 152,
+  V4INT_L_RRR_0_OPCODE_X1 = 99,
+  V4PACKSC_RRR_0_OPCODE_X0 = 153,
+  V4PACKSC_RRR_0_OPCODE_X1 = 100,
+  V4SHLSC_RRR_0_OPCODE_X0 = 154,
+  V4SHLSC_RRR_0_OPCODE_X1 = 101,
+  V4SHL_RRR_0_OPCODE_X0 = 155,
+  V4SHL_RRR_0_OPCODE_X1 = 102,
+  V4SHRS_RRR_0_OPCODE_X0 = 156,
+  V4SHRS_RRR_0_OPCODE_X1 = 103,
+  V4SHRU_RRR_0_OPCODE_X0 = 157,
+  V4SHRU_RRR_0_OPCODE_X1 = 104,
+  V4SUBSC_RRR_0_OPCODE_X0 = 158,
+  V4SUBSC_RRR_0_OPCODE_X1 = 105,
+  V4SUB_RRR_0_OPCODE_X0 = 159,
+  V4SUB_RRR_0_OPCODE_X1 = 106,
+  WH64_UNARY_OPCODE_X1 = 38,
+  XORI_IMM8_OPCODE_X0 = 20,
+  XORI_IMM8_OPCODE_X1 = 45,
+  XOR_RRR_0_OPCODE_X0 = 160,
+  XOR_RRR_0_OPCODE_X1 = 107,
+  XOR_RRR_5_OPCODE_Y0 = 3,
+  XOR_RRR_5_OPCODE_Y1 = 3
+};
+
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __ARCH_OPCODE_H__ */
diff -druN linux-libre-3.1-gnu/arch/tile/include/arch/opcode_tilepro.h linux-libre-3.2-gnu/arch/tile/include/arch/opcode_tilepro.h
--- linux-libre-3.1-gnu/arch/tile/include/arch/opcode_tilepro.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/tile/include/arch/opcode_tilepro.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1471 @@
+/* TILEPro opcode information.
+ *
+ * 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 __ARCH_OPCODE_H__
+#define __ARCH_OPCODE_H__
+
+#ifndef __ASSEMBLER__
+
+typedef unsigned long long tilepro_bundle_bits;
+
+/* This is the bit that determines if a bundle is in the Y encoding. */
+#define TILEPRO_BUNDLE_Y_ENCODING_MASK ((tilepro_bundle_bits)1 << 63)
+
+enum
+{
+  /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */
+  TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE = 3,
+
+  /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */
+  TILEPRO_NUM_PIPELINE_ENCODINGS = 5,
+
+  /* Log base 2 of TILEPRO_BUNDLE_SIZE_IN_BYTES. */
+  TILEPRO_LOG2_BUNDLE_SIZE_IN_BYTES = 3,
+
+  /* Instructions take this many bytes. */
+  TILEPRO_BUNDLE_SIZE_IN_BYTES = 1 << TILEPRO_LOG2_BUNDLE_SIZE_IN_BYTES,
+
+  /* Log base 2 of TILEPRO_BUNDLE_ALIGNMENT_IN_BYTES. */
+  TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3,
+
+  /* Bundles should be aligned modulo this number of bytes. */
+  TILEPRO_BUNDLE_ALIGNMENT_IN_BYTES =
+    (1 << TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES),
+
+  /* Log base 2 of TILEPRO_SN_INSTRUCTION_SIZE_IN_BYTES. */
+  TILEPRO_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES = 1,
+
+  /* Static network instructions take this many bytes. */
+  TILEPRO_SN_INSTRUCTION_SIZE_IN_BYTES =
+    (1 << TILEPRO_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES),
+
+  /* Number of registers (some are magic, such as network I/O). */
+  TILEPRO_NUM_REGISTERS = 64,
+
+  /* Number of static network registers. */
+  TILEPRO_NUM_SN_REGISTERS = 4
+};
+
+/* Make a few "tile_" variables to simplify common code between
+   architectures.  */
+
+typedef tilepro_bundle_bits tile_bundle_bits;
+#define TILE_BUNDLE_SIZE_IN_BYTES TILEPRO_BUNDLE_SIZE_IN_BYTES
+#define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEPRO_BUNDLE_ALIGNMENT_IN_BYTES
+#define TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES \
+  TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES
+
+/* 64-bit pattern for a { bpt ; nop } bundle. */
+#define TILEPRO_BPT_BUNDLE 0x400b3cae70166000ULL
+
+static __inline unsigned int
+get_BrOff_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_BrOff_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x00007fff) |
+         (((unsigned int)(n >> 20)) & 0x00018000);
+}
+
+static __inline unsigned int
+get_BrType_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0xf);
+}
+
+static __inline unsigned int
+get_Dest_Imm8_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x0000003f) |
+         (((unsigned int)(n >> 43)) & 0x000000c0);
+}
+
+static __inline unsigned int
+get_Dest_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 2)) & 0x3);
+}
+
+static __inline unsigned int
+get_Dest_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Imm16_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xffff);
+}
+
+static __inline unsigned int
+get_Imm16_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xffff);
+}
+
+static __inline unsigned int
+get_Imm8_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xff);
+}
+
+static __inline unsigned int
+get_ImmOpcodeExtension_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 20)) & 0x7f);
+}
+
+static __inline unsigned int
+get_ImmOpcodeExtension_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 51)) & 0x7f);
+}
+
+static __inline unsigned int
+get_ImmRROpcodeExtension_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 8)) & 0x3);
+}
+
+static __inline unsigned int
+get_JOffLong_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x00007fff) |
+         (((unsigned int)(n >> 20)) & 0x00018000) |
+         (((unsigned int)(n >> 14)) & 0x001e0000) |
+         (((unsigned int)(n >> 16)) & 0x07e00000) |
+         (((unsigned int)(n >> 31)) & 0x18000000);
+}
+
+static __inline unsigned int
+get_JOff_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x00007fff) |
+         (((unsigned int)(n >> 20)) & 0x00018000) |
+         (((unsigned int)(n >> 14)) & 0x001e0000) |
+         (((unsigned int)(n >> 16)) & 0x07e00000) |
+         (((unsigned int)(n >> 31)) & 0x08000000);
+}
+
+static __inline unsigned int
+get_MF_Imm15_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x00003fff) |
+         (((unsigned int)(n >> 44)) & 0x00004000);
+}
+
+static __inline unsigned int
+get_MMEnd_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x1f);
+}
+
+static __inline unsigned int
+get_MMEnd_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x1f);
+}
+
+static __inline unsigned int
+get_MMStart_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 23)) & 0x1f);
+}
+
+static __inline unsigned int
+get_MMStart_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 54)) & 0x1f);
+}
+
+static __inline unsigned int
+get_MT_Imm15_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x0000003f) |
+         (((unsigned int)(n >> 37)) & 0x00003fc0) |
+         (((unsigned int)(n >> 44)) & 0x00004000);
+}
+
+static __inline unsigned int
+get_Mode(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 63)) & 0x1);
+}
+
+static __inline unsigned int
+get_NoRegOpcodeExtension_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 10)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Opcode_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 28)) & 0x7);
+}
+
+static __inline unsigned int
+get_Opcode_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 59)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 27)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 59)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y2(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 56)) & 0x7);
+}
+
+static __inline unsigned int
+get_RROpcodeExtension_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 4)) & 0xf);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x1ff);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x1ff);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x3);
+}
+
+static __inline unsigned int
+get_RouteOpcodeExtension_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_S_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 27)) & 0x1);
+}
+
+static __inline unsigned int
+get_S_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 58)) & 0x1);
+}
+
+static __inline unsigned int
+get_ShAmt_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x1f);
+}
+
+static __inline unsigned int
+get_ShAmt_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x1f);
+}
+
+static __inline unsigned int
+get_ShAmt_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x1f);
+}
+
+static __inline unsigned int
+get_ShAmt_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x1f);
+}
+
+static __inline unsigned int
+get_SrcA_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 6)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 6)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y2(tilepro_bundle_bits n)
+{
+  return (((n >> 26)) & 0x00000001) |
+         (((unsigned int)(n >> 50)) & 0x0000003e);
+}
+
+static __inline unsigned int
+get_SrcBDest_Y2(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 20)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Src_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3);
+}
+
+static __inline unsigned int
+get_UnOpcodeExtension_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x1f);
+}
+
+static __inline unsigned int
+get_UnOpcodeExtension_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x1f);
+}
+
+static __inline unsigned int
+get_UnOpcodeExtension_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x1f);
+}
+
+static __inline unsigned int
+get_UnOpcodeExtension_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x1f);
+}
+
+static __inline unsigned int
+get_UnShOpcodeExtension_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 17)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_UnShOpcodeExtension_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 48)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_UnShOpcodeExtension_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 17)) & 0x7);
+}
+
+static __inline unsigned int
+get_UnShOpcodeExtension_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 48)) & 0x7);
+}
+
+
+static __inline int
+sign_extend(int n, int num_bits)
+{
+  int shift = (int)(sizeof(int) * 8 - num_bits);
+  return (n << shift) >> shift;
+}
+
+
+
+static __inline tilepro_bundle_bits
+create_BrOff_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3ff) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_BrOff_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x00007fff)) << 43) |
+         (((tilepro_bundle_bits)(n & 0x00018000)) << 20);
+}
+
+static __inline tilepro_bundle_bits
+create_BrType_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xf)) << 31);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_Imm8_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x0000003f)) << 31) |
+         (((tilepro_bundle_bits)(n & 0x000000c0)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 2);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 31);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 31);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm16_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xffff) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm16_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xffff)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm8_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm8_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm8_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xff)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm8_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm8_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xff)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_ImmOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x7f) << 20);
+}
+
+static __inline tilepro_bundle_bits
+create_ImmOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x7f)) << 51);
+}
+
+static __inline tilepro_bundle_bits
+create_ImmRROpcodeExtension_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 8);
+}
+
+static __inline tilepro_bundle_bits
+create_JOffLong_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x00007fff)) << 43) |
+         (((tilepro_bundle_bits)(n & 0x00018000)) << 20) |
+         (((tilepro_bundle_bits)(n & 0x001e0000)) << 14) |
+         (((tilepro_bundle_bits)(n & 0x07e00000)) << 16) |
+         (((tilepro_bundle_bits)(n & 0x18000000)) << 31);
+}
+
+static __inline tilepro_bundle_bits
+create_JOff_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x00007fff)) << 43) |
+         (((tilepro_bundle_bits)(n & 0x00018000)) << 20) |
+         (((tilepro_bundle_bits)(n & 0x001e0000)) << 14) |
+         (((tilepro_bundle_bits)(n & 0x07e00000)) << 16) |
+         (((tilepro_bundle_bits)(n & 0x08000000)) << 31);
+}
+
+static __inline tilepro_bundle_bits
+create_MF_Imm15_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x00003fff)) << 37) |
+         (((tilepro_bundle_bits)(n & 0x00004000)) << 44);
+}
+
+static __inline tilepro_bundle_bits
+create_MMEnd_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 18);
+}
+
+static __inline tilepro_bundle_bits
+create_MMEnd_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 49);
+}
+
+static __inline tilepro_bundle_bits
+create_MMStart_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 23);
+}
+
+static __inline tilepro_bundle_bits
+create_MMStart_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 54);
+}
+
+static __inline tilepro_bundle_bits
+create_MT_Imm15_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x0000003f)) << 31) |
+         (((tilepro_bundle_bits)(n & 0x00003fc0)) << 37) |
+         (((tilepro_bundle_bits)(n & 0x00004000)) << 44);
+}
+
+static __inline tilepro_bundle_bits
+create_Mode(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1)) << 63);
+}
+
+static __inline tilepro_bundle_bits
+create_NoRegOpcodeExtension_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xf) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 10);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x7) << 28);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xf)) << 59);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xf) << 27);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xf)) << 59);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x7)) << 56);
+}
+
+static __inline tilepro_bundle_bits
+create_RROpcodeExtension_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xf) << 4);
+}
+
+static __inline tilepro_bundle_bits
+create_RRROpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1ff) << 18);
+}
+
+static __inline tilepro_bundle_bits
+create_RRROpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1ff)) << 49);
+}
+
+static __inline tilepro_bundle_bits
+create_RRROpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 18);
+}
+
+static __inline tilepro_bundle_bits
+create_RRROpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3)) << 49);
+}
+
+static __inline tilepro_bundle_bits
+create_RouteOpcodeExtension_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3ff) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_S_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1) << 27);
+}
+
+static __inline tilepro_bundle_bits
+create_S_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1)) << 58);
+}
+
+static __inline tilepro_bundle_bits
+create_ShAmt_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_ShAmt_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_ShAmt_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_ShAmt_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcA_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 6);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcA_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 37);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcA_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 6);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcA_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 37);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcA_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x00000001) << 26) |
+         (((tilepro_bundle_bits)(n & 0x0000003e)) << 50);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcBDest_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 20);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcB_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcB_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcB_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcB_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_Src_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_UnOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_UnOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_UnOpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_UnOpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_UnShOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3ff) << 17);
+}
+
+static __inline tilepro_bundle_bits
+create_UnShOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3ff)) << 48);
+}
+
+static __inline tilepro_bundle_bits
+create_UnShOpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x7) << 17);
+}
+
+static __inline tilepro_bundle_bits
+create_UnShOpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x7)) << 48);
+}
+
+
+enum
+{
+  ADDBS_U_SPECIAL_0_OPCODE_X0 = 98,
+  ADDBS_U_SPECIAL_0_OPCODE_X1 = 68,
+  ADDB_SPECIAL_0_OPCODE_X0 = 1,
+  ADDB_SPECIAL_0_OPCODE_X1 = 1,
+  ADDHS_SPECIAL_0_OPCODE_X0 = 99,
+  ADDHS_SPECIAL_0_OPCODE_X1 = 69,
+  ADDH_SPECIAL_0_OPCODE_X0 = 2,
+  ADDH_SPECIAL_0_OPCODE_X1 = 2,
+  ADDIB_IMM_0_OPCODE_X0 = 1,
+  ADDIB_IMM_0_OPCODE_X1 = 1,
+  ADDIH_IMM_0_OPCODE_X0 = 2,
+  ADDIH_IMM_0_OPCODE_X1 = 2,
+  ADDI_IMM_0_OPCODE_X0 = 3,
+  ADDI_IMM_0_OPCODE_X1 = 3,
+  ADDI_IMM_1_OPCODE_SN = 1,
+  ADDI_OPCODE_Y0 = 9,
+  ADDI_OPCODE_Y1 = 7,
+  ADDLIS_OPCODE_X0 = 1,
+  ADDLIS_OPCODE_X1 = 2,
+  ADDLI_OPCODE_X0 = 2,
+  ADDLI_OPCODE_X1 = 3,
+  ADDS_SPECIAL_0_OPCODE_X0 = 96,
+  ADDS_SPECIAL_0_OPCODE_X1 = 66,
+  ADD_SPECIAL_0_OPCODE_X0 = 3,
+  ADD_SPECIAL_0_OPCODE_X1 = 3,
+  ADD_SPECIAL_0_OPCODE_Y0 = 0,
+  ADD_SPECIAL_0_OPCODE_Y1 = 0,
+  ADIFFB_U_SPECIAL_0_OPCODE_X0 = 4,
+  ADIFFH_SPECIAL_0_OPCODE_X0 = 5,
+  ANDI_IMM_0_OPCODE_X0 = 1,
+  ANDI_IMM_0_OPCODE_X1 = 4,
+  ANDI_OPCODE_Y0 = 10,
+  ANDI_OPCODE_Y1 = 8,
+  AND_SPECIAL_0_OPCODE_X0 = 6,
+  AND_SPECIAL_0_OPCODE_X1 = 4,
+  AND_SPECIAL_2_OPCODE_Y0 = 0,
+  AND_SPECIAL_2_OPCODE_Y1 = 0,
+  AULI_OPCODE_X0 = 3,
+  AULI_OPCODE_X1 = 4,
+  AVGB_U_SPECIAL_0_OPCODE_X0 = 7,
+  AVGH_SPECIAL_0_OPCODE_X0 = 8,
+  BBNST_BRANCH_OPCODE_X1 = 15,
+  BBNS_BRANCH_OPCODE_X1 = 14,
+  BBNS_OPCODE_SN = 63,
+  BBST_BRANCH_OPCODE_X1 = 13,
+  BBS_BRANCH_OPCODE_X1 = 12,
+  BBS_OPCODE_SN = 62,
+  BGEZT_BRANCH_OPCODE_X1 = 7,
+  BGEZ_BRANCH_OPCODE_X1 = 6,
+  BGEZ_OPCODE_SN = 61,
+  BGZT_BRANCH_OPCODE_X1 = 5,
+  BGZ_BRANCH_OPCODE_X1 = 4,
+  BGZ_OPCODE_SN = 58,
+  BITX_UN_0_SHUN_0_OPCODE_X0 = 1,
+  BITX_UN_0_SHUN_0_OPCODE_Y0 = 1,
+  BLEZT_BRANCH_OPCODE_X1 = 11,
+  BLEZ_BRANCH_OPCODE_X1 = 10,
+  BLEZ_OPCODE_SN = 59,
+  BLZT_BRANCH_OPCODE_X1 = 9,
+  BLZ_BRANCH_OPCODE_X1 = 8,
+  BLZ_OPCODE_SN = 60,
+  BNZT_BRANCH_OPCODE_X1 = 3,
+  BNZ_BRANCH_OPCODE_X1 = 2,
+  BNZ_OPCODE_SN = 57,
+  BPT_NOREG_RR_IMM_0_OPCODE_SN = 1,
+  BRANCH_OPCODE_X1 = 5,
+  BYTEX_UN_0_SHUN_0_OPCODE_X0 = 2,
+  BYTEX_UN_0_SHUN_0_OPCODE_Y0 = 2,
+  BZT_BRANCH_OPCODE_X1 = 1,
+  BZ_BRANCH_OPCODE_X1 = 0,
+  BZ_OPCODE_SN = 56,
+  CLZ_UN_0_SHUN_0_OPCODE_X0 = 3,
+  CLZ_UN_0_SHUN_0_OPCODE_Y0 = 3,
+  CRC32_32_SPECIAL_0_OPCODE_X0 = 9,
+  CRC32_8_SPECIAL_0_OPCODE_X0 = 10,
+  CTZ_UN_0_SHUN_0_OPCODE_X0 = 4,
+  CTZ_UN_0_SHUN_0_OPCODE_Y0 = 4,
+  DRAIN_UN_0_SHUN_0_OPCODE_X1 = 1,
+  DTLBPR_UN_0_SHUN_0_OPCODE_X1 = 2,
+  DWORD_ALIGN_SPECIAL_0_OPCODE_X0 = 95,
+  FINV_UN_0_SHUN_0_OPCODE_X1 = 3,
+  FLUSH_UN_0_SHUN_0_OPCODE_X1 = 4,
+  FNOP_NOREG_RR_IMM_0_OPCODE_SN = 3,
+  FNOP_UN_0_SHUN_0_OPCODE_X0 = 5,
+  FNOP_UN_0_SHUN_0_OPCODE_X1 = 5,
+  FNOP_UN_0_SHUN_0_OPCODE_Y0 = 5,
+  FNOP_UN_0_SHUN_0_OPCODE_Y1 = 1,
+  HALT_NOREG_RR_IMM_0_OPCODE_SN = 0,
+  ICOH_UN_0_SHUN_0_OPCODE_X1 = 6,
+  ILL_UN_0_SHUN_0_OPCODE_X1 = 7,
+  ILL_UN_0_SHUN_0_OPCODE_Y1 = 2,
+  IMM_0_OPCODE_SN = 0,
+  IMM_0_OPCODE_X0 = 4,
+  IMM_0_OPCODE_X1 = 6,
+  IMM_1_OPCODE_SN = 1,
+  IMM_OPCODE_0_X0 = 5,
+  INTHB_SPECIAL_0_OPCODE_X0 = 11,
+  INTHB_SPECIAL_0_OPCODE_X1 = 5,
+  INTHH_SPECIAL_0_OPCODE_X0 = 12,
+  INTHH_SPECIAL_0_OPCODE_X1 = 6,
+  INTLB_SPECIAL_0_OPCODE_X0 = 13,
+  INTLB_SPECIAL_0_OPCODE_X1 = 7,
+  INTLH_SPECIAL_0_OPCODE_X0 = 14,
+  INTLH_SPECIAL_0_OPCODE_X1 = 8,
+  INV_UN_0_SHUN_0_OPCODE_X1 = 8,
+  IRET_UN_0_SHUN_0_OPCODE_X1 = 9,
+  JALB_OPCODE_X1 = 13,
+  JALF_OPCODE_X1 = 12,
+  JALRP_SPECIAL_0_OPCODE_X1 = 9,
+  JALRR_IMM_1_OPCODE_SN = 3,
+  JALR_RR_IMM_0_OPCODE_SN = 5,
+  JALR_SPECIAL_0_OPCODE_X1 = 10,
+  JB_OPCODE_X1 = 11,
+  JF_OPCODE_X1 = 10,
+  JRP_SPECIAL_0_OPCODE_X1 = 11,
+  JRR_IMM_1_OPCODE_SN = 2,
+  JR_RR_IMM_0_OPCODE_SN = 4,
+  JR_SPECIAL_0_OPCODE_X1 = 12,
+  LBADD_IMM_0_OPCODE_X1 = 22,
+  LBADD_U_IMM_0_OPCODE_X1 = 23,
+  LB_OPCODE_Y2 = 0,
+  LB_UN_0_SHUN_0_OPCODE_X1 = 10,
+  LB_U_OPCODE_Y2 = 1,
+  LB_U_UN_0_SHUN_0_OPCODE_X1 = 11,
+  LHADD_IMM_0_OPCODE_X1 = 24,
+  LHADD_U_IMM_0_OPCODE_X1 = 25,
+  LH_OPCODE_Y2 = 2,
+  LH_UN_0_SHUN_0_OPCODE_X1 = 12,
+  LH_U_OPCODE_Y2 = 3,
+  LH_U_UN_0_SHUN_0_OPCODE_X1 = 13,
+  LNK_SPECIAL_0_OPCODE_X1 = 13,
+  LWADD_IMM_0_OPCODE_X1 = 26,
+  LWADD_NA_IMM_0_OPCODE_X1 = 27,
+  LW_NA_UN_0_SHUN_0_OPCODE_X1 = 24,
+  LW_OPCODE_Y2 = 4,
+  LW_UN_0_SHUN_0_OPCODE_X1 = 14,
+  MAXB_U_SPECIAL_0_OPCODE_X0 = 15,
+  MAXB_U_SPECIAL_0_OPCODE_X1 = 14,
+  MAXH_SPECIAL_0_OPCODE_X0 = 16,
+  MAXH_SPECIAL_0_OPCODE_X1 = 15,
+  MAXIB_U_IMM_0_OPCODE_X0 = 4,
+  MAXIB_U_IMM_0_OPCODE_X1 = 5,
+  MAXIH_IMM_0_OPCODE_X0 = 5,
+  MAXIH_IMM_0_OPCODE_X1 = 6,
+  MFSPR_IMM_0_OPCODE_X1 = 7,
+  MF_UN_0_SHUN_0_OPCODE_X1 = 15,
+  MINB_U_SPECIAL_0_OPCODE_X0 = 17,
+  MINB_U_SPECIAL_0_OPCODE_X1 = 16,
+  MINH_SPECIAL_0_OPCODE_X0 = 18,
+  MINH_SPECIAL_0_OPCODE_X1 = 17,
+  MINIB_U_IMM_0_OPCODE_X0 = 6,
+  MINIB_U_IMM_0_OPCODE_X1 = 8,
+  MINIH_IMM_0_OPCODE_X0 = 7,
+  MINIH_IMM_0_OPCODE_X1 = 9,
+  MM_OPCODE_X0 = 6,
+  MM_OPCODE_X1 = 7,
+  MNZB_SPECIAL_0_OPCODE_X0 = 19,
+  MNZB_SPECIAL_0_OPCODE_X1 = 18,
+  MNZH_SPECIAL_0_OPCODE_X0 = 20,
+  MNZH_SPECIAL_0_OPCODE_X1 = 19,
+  MNZ_SPECIAL_0_OPCODE_X0 = 21,
+  MNZ_SPECIAL_0_OPCODE_X1 = 20,
+  MNZ_SPECIAL_1_OPCODE_Y0 = 0,
+  MNZ_SPECIAL_1_OPCODE_Y1 = 1,
+  MOVEI_IMM_1_OPCODE_SN = 0,
+  MOVE_RR_IMM_0_OPCODE_SN = 8,
+  MTSPR_IMM_0_OPCODE_X1 = 10,
+  MULHHA_SS_SPECIAL_0_OPCODE_X0 = 22,
+  MULHHA_SS_SPECIAL_7_OPCODE_Y0 = 0,
+  MULHHA_SU_SPECIAL_0_OPCODE_X0 = 23,
+  MULHHA_UU_SPECIAL_0_OPCODE_X0 = 24,
+  MULHHA_UU_SPECIAL_7_OPCODE_Y0 = 1,
+  MULHHSA_UU_SPECIAL_0_OPCODE_X0 = 25,
+  MULHH_SS_SPECIAL_0_OPCODE_X0 = 26,
+  MULHH_SS_SPECIAL_6_OPCODE_Y0 = 0,
+  MULHH_SU_SPECIAL_0_OPCODE_X0 = 27,
+  MULHH_UU_SPECIAL_0_OPCODE_X0 = 28,
+  MULHH_UU_SPECIAL_6_OPCODE_Y0 = 1,
+  MULHLA_SS_SPECIAL_0_OPCODE_X0 = 29,
+  MULHLA_SU_SPECIAL_0_OPCODE_X0 = 30,
+  MULHLA_US_SPECIAL_0_OPCODE_X0 = 31,
+  MULHLA_UU_SPECIAL_0_OPCODE_X0 = 32,
+  MULHLSA_UU_SPECIAL_0_OPCODE_X0 = 33,
+  MULHLSA_UU_SPECIAL_5_OPCODE_Y0 = 0,
+  MULHL_SS_SPECIAL_0_OPCODE_X0 = 34,
+  MULHL_SU_SPECIAL_0_OPCODE_X0 = 35,
+  MULHL_US_SPECIAL_0_OPCODE_X0 = 36,
+  MULHL_UU_SPECIAL_0_OPCODE_X0 = 37,
+  MULLLA_SS_SPECIAL_0_OPCODE_X0 = 38,
+  MULLLA_SS_SPECIAL_7_OPCODE_Y0 = 2,
+  MULLLA_SU_SPECIAL_0_OPCODE_X0 = 39,
+  MULLLA_UU_SPECIAL_0_OPCODE_X0 = 40,
+  MULLLA_UU_SPECIAL_7_OPCODE_Y0 = 3,
+  MULLLSA_UU_SPECIAL_0_OPCODE_X0 = 41,
+  MULLL_SS_SPECIAL_0_OPCODE_X0 = 42,
+  MULLL_SS_SPECIAL_6_OPCODE_Y0 = 2,
+  MULLL_SU_SPECIAL_0_OPCODE_X0 = 43,
+  MULLL_UU_SPECIAL_0_OPCODE_X0 = 44,
+  MULLL_UU_SPECIAL_6_OPCODE_Y0 = 3,
+  MVNZ_SPECIAL_0_OPCODE_X0 = 45,
+  MVNZ_SPECIAL_1_OPCODE_Y0 = 1,
+  MVZ_SPECIAL_0_OPCODE_X0 = 46,
+  MVZ_SPECIAL_1_OPCODE_Y0 = 2,
+  MZB_SPECIAL_0_OPCODE_X0 = 47,
+  MZB_SPECIAL_0_OPCODE_X1 = 21,
+  MZH_SPECIAL_0_OPCODE_X0 = 48,
+  MZH_SPECIAL_0_OPCODE_X1 = 22,
+  MZ_SPECIAL_0_OPCODE_X0 = 49,
+  MZ_SPECIAL_0_OPCODE_X1 = 23,
+  MZ_SPECIAL_1_OPCODE_Y0 = 3,
+  MZ_SPECIAL_1_OPCODE_Y1 = 2,
+  NAP_UN_0_SHUN_0_OPCODE_X1 = 16,
+  NOP_NOREG_RR_IMM_0_OPCODE_SN = 2,
+  NOP_UN_0_SHUN_0_OPCODE_X0 = 6,
+  NOP_UN_0_SHUN_0_OPCODE_X1 = 17,
+  NOP_UN_0_SHUN_0_OPCODE_Y0 = 6,
+  NOP_UN_0_SHUN_0_OPCODE_Y1 = 3,
+  NOREG_RR_IMM_0_OPCODE_SN = 0,
+  NOR_SPECIAL_0_OPCODE_X0 = 50,
+  NOR_SPECIAL_0_OPCODE_X1 = 24,
+  NOR_SPECIAL_2_OPCODE_Y0 = 1,
+  NOR_SPECIAL_2_OPCODE_Y1 = 1,
+  ORI_IMM_0_OPCODE_X0 = 8,
+  ORI_IMM_0_OPCODE_X1 = 11,
+  ORI_OPCODE_Y0 = 11,
+  ORI_OPCODE_Y1 = 9,
+  OR_SPECIAL_0_OPCODE_X0 = 51,
+  OR_SPECIAL_0_OPCODE_X1 = 25,
+  OR_SPECIAL_2_OPCODE_Y0 = 2,
+  OR_SPECIAL_2_OPCODE_Y1 = 2,
+  PACKBS_U_SPECIAL_0_OPCODE_X0 = 103,
+  PACKBS_U_SPECIAL_0_OPCODE_X1 = 73,
+  PACKHB_SPECIAL_0_OPCODE_X0 = 52,
+  PACKHB_SPECIAL_0_OPCODE_X1 = 26,
+  PACKHS_SPECIAL_0_OPCODE_X0 = 102,
+  PACKHS_SPECIAL_0_OPCODE_X1 = 72,
+  PACKLB_SPECIAL_0_OPCODE_X0 = 53,
+  PACKLB_SPECIAL_0_OPCODE_X1 = 27,
+  PCNT_UN_0_SHUN_0_OPCODE_X0 = 7,
+  PCNT_UN_0_SHUN_0_OPCODE_Y0 = 7,
+  RLI_SHUN_0_OPCODE_X0 = 1,
+  RLI_SHUN_0_OPCODE_X1 = 1,
+  RLI_SHUN_0_OPCODE_Y0 = 1,
+  RLI_SHUN_0_OPCODE_Y1 = 1,
+  RL_SPECIAL_0_OPCODE_X0 = 54,
+  RL_SPECIAL_0_OPCODE_X1 = 28,
+  RL_SPECIAL_3_OPCODE_Y0 = 0,
+  RL_SPECIAL_3_OPCODE_Y1 = 0,
+  RR_IMM_0_OPCODE_SN = 0,
+  S1A_SPECIAL_0_OPCODE_X0 = 55,
+  S1A_SPECIAL_0_OPCODE_X1 = 29,
+  S1A_SPECIAL_0_OPCODE_Y0 = 1,
+  S1A_SPECIAL_0_OPCODE_Y1 = 1,
+  S2A_SPECIAL_0_OPCODE_X0 = 56,
+  S2A_SPECIAL_0_OPCODE_X1 = 30,
+  S2A_SPECIAL_0_OPCODE_Y0 = 2,
+  S2A_SPECIAL_0_OPCODE_Y1 = 2,
+  S3A_SPECIAL_0_OPCODE_X0 = 57,
+  S3A_SPECIAL_0_OPCODE_X1 = 31,
+  S3A_SPECIAL_5_OPCODE_Y0 = 1,
+  S3A_SPECIAL_5_OPCODE_Y1 = 1,
+  SADAB_U_SPECIAL_0_OPCODE_X0 = 58,
+  SADAH_SPECIAL_0_OPCODE_X0 = 59,
+  SADAH_U_SPECIAL_0_OPCODE_X0 = 60,
+  SADB_U_SPECIAL_0_OPCODE_X0 = 61,
+  SADH_SPECIAL_0_OPCODE_X0 = 62,
+  SADH_U_SPECIAL_0_OPCODE_X0 = 63,
+  SBADD_IMM_0_OPCODE_X1 = 28,
+  SB_OPCODE_Y2 = 5,
+  SB_SPECIAL_0_OPCODE_X1 = 32,
+  SEQB_SPECIAL_0_OPCODE_X0 = 64,
+  SEQB_SPECIAL_0_OPCODE_X1 = 33,
+  SEQH_SPECIAL_0_OPCODE_X0 = 65,
+  SEQH_SPECIAL_0_OPCODE_X1 = 34,
+  SEQIB_IMM_0_OPCODE_X0 = 9,
+  SEQIB_IMM_0_OPCODE_X1 = 12,
+  SEQIH_IMM_0_OPCODE_X0 = 10,
+  SEQIH_IMM_0_OPCODE_X1 = 13,
+  SEQI_IMM_0_OPCODE_X0 = 11,
+  SEQI_IMM_0_OPCODE_X1 = 14,
+  SEQI_OPCODE_Y0 = 12,
+  SEQI_OPCODE_Y1 = 10,
+  SEQ_SPECIAL_0_OPCODE_X0 = 66,
+  SEQ_SPECIAL_0_OPCODE_X1 = 35,
+  SEQ_SPECIAL_5_OPCODE_Y0 = 2,
+  SEQ_SPECIAL_5_OPCODE_Y1 = 2,
+  SHADD_IMM_0_OPCODE_X1 = 29,
+  SHL8II_IMM_0_OPCODE_SN = 3,
+  SHLB_SPECIAL_0_OPCODE_X0 = 67,
+  SHLB_SPECIAL_0_OPCODE_X1 = 36,
+  SHLH_SPECIAL_0_OPCODE_X0 = 68,
+  SHLH_SPECIAL_0_OPCODE_X1 = 37,
+  SHLIB_SHUN_0_OPCODE_X0 = 2,
+  SHLIB_SHUN_0_OPCODE_X1 = 2,
+  SHLIH_SHUN_0_OPCODE_X0 = 3,
+  SHLIH_SHUN_0_OPCODE_X1 = 3,
+  SHLI_SHUN_0_OPCODE_X0 = 4,
+  SHLI_SHUN_0_OPCODE_X1 = 4,
+  SHLI_SHUN_0_OPCODE_Y0 = 2,
+  SHLI_SHUN_0_OPCODE_Y1 = 2,
+  SHL_SPECIAL_0_OPCODE_X0 = 69,
+  SHL_SPECIAL_0_OPCODE_X1 = 38,
+  SHL_SPECIAL_3_OPCODE_Y0 = 1,
+  SHL_SPECIAL_3_OPCODE_Y1 = 1,
+  SHR1_RR_IMM_0_OPCODE_SN = 9,
+  SHRB_SPECIAL_0_OPCODE_X0 = 70,
+  SHRB_SPECIAL_0_OPCODE_X1 = 39,
+  SHRH_SPECIAL_0_OPCODE_X0 = 71,
+  SHRH_SPECIAL_0_OPCODE_X1 = 40,
+  SHRIB_SHUN_0_OPCODE_X0 = 5,
+  SHRIB_SHUN_0_OPCODE_X1 = 5,
+  SHRIH_SHUN_0_OPCODE_X0 = 6,
+  SHRIH_SHUN_0_OPCODE_X1 = 6,
+  SHRI_SHUN_0_OPCODE_X0 = 7,
+  SHRI_SHUN_0_OPCODE_X1 = 7,
+  SHRI_SHUN_0_OPCODE_Y0 = 3,
+  SHRI_SHUN_0_OPCODE_Y1 = 3,
+  SHR_SPECIAL_0_OPCODE_X0 = 72,
+  SHR_SPECIAL_0_OPCODE_X1 = 41,
+  SHR_SPECIAL_3_OPCODE_Y0 = 2,
+  SHR_SPECIAL_3_OPCODE_Y1 = 2,
+  SHUN_0_OPCODE_X0 = 7,
+  SHUN_0_OPCODE_X1 = 8,
+  SHUN_0_OPCODE_Y0 = 13,
+  SHUN_0_OPCODE_Y1 = 11,
+  SH_OPCODE_Y2 = 6,
+  SH_SPECIAL_0_OPCODE_X1 = 42,
+  SLTB_SPECIAL_0_OPCODE_X0 = 73,
+  SLTB_SPECIAL_0_OPCODE_X1 = 43,
+  SLTB_U_SPECIAL_0_OPCODE_X0 = 74,
+  SLTB_U_SPECIAL_0_OPCODE_X1 = 44,
+  SLTEB_SPECIAL_0_OPCODE_X0 = 75,
+  SLTEB_SPECIAL_0_OPCODE_X1 = 45,
+  SLTEB_U_SPECIAL_0_OPCODE_X0 = 76,
+  SLTEB_U_SPECIAL_0_OPCODE_X1 = 46,
+  SLTEH_SPECIAL_0_OPCODE_X0 = 77,
+  SLTEH_SPECIAL_0_OPCODE_X1 = 47,
+  SLTEH_U_SPECIAL_0_OPCODE_X0 = 78,
+  SLTEH_U_SPECIAL_0_OPCODE_X1 = 48,
+  SLTE_SPECIAL_0_OPCODE_X0 = 79,
+  SLTE_SPECIAL_0_OPCODE_X1 = 49,
+  SLTE_SPECIAL_4_OPCODE_Y0 = 0,
+  SLTE_SPECIAL_4_OPCODE_Y1 = 0,
+  SLTE_U_SPECIAL_0_OPCODE_X0 = 80,
+  SLTE_U_SPECIAL_0_OPCODE_X1 = 50,
+  SLTE_U_SPECIAL_4_OPCODE_Y0 = 1,
+  SLTE_U_SPECIAL_4_OPCODE_Y1 = 1,
+  SLTH_SPECIAL_0_OPCODE_X0 = 81,
+  SLTH_SPECIAL_0_OPCODE_X1 = 51,
+  SLTH_U_SPECIAL_0_OPCODE_X0 = 82,
+  SLTH_U_SPECIAL_0_OPCODE_X1 = 52,
+  SLTIB_IMM_0_OPCODE_X0 = 12,
+  SLTIB_IMM_0_OPCODE_X1 = 15,
+  SLTIB_U_IMM_0_OPCODE_X0 = 13,
+  SLTIB_U_IMM_0_OPCODE_X1 = 16,
+  SLTIH_IMM_0_OPCODE_X0 = 14,
+  SLTIH_IMM_0_OPCODE_X1 = 17,
+  SLTIH_U_IMM_0_OPCODE_X0 = 15,
+  SLTIH_U_IMM_0_OPCODE_X1 = 18,
+  SLTI_IMM_0_OPCODE_X0 = 16,
+  SLTI_IMM_0_OPCODE_X1 = 19,
+  SLTI_OPCODE_Y0 = 14,
+  SLTI_OPCODE_Y1 = 12,
+  SLTI_U_IMM_0_OPCODE_X0 = 17,
+  SLTI_U_IMM_0_OPCODE_X1 = 20,
+  SLTI_U_OPCODE_Y0 = 15,
+  SLTI_U_OPCODE_Y1 = 13,
+  SLT_SPECIAL_0_OPCODE_X0 = 83,
+  SLT_SPECIAL_0_OPCODE_X1 = 53,
+  SLT_SPECIAL_4_OPCODE_Y0 = 2,
+  SLT_SPECIAL_4_OPCODE_Y1 = 2,
+  SLT_U_SPECIAL_0_OPCODE_X0 = 84,
+  SLT_U_SPECIAL_0_OPCODE_X1 = 54,
+  SLT_U_SPECIAL_4_OPCODE_Y0 = 3,
+  SLT_U_SPECIAL_4_OPCODE_Y1 = 3,
+  SNEB_SPECIAL_0_OPCODE_X0 = 85,
+  SNEB_SPECIAL_0_OPCODE_X1 = 55,
+  SNEH_SPECIAL_0_OPCODE_X0 = 86,
+  SNEH_SPECIAL_0_OPCODE_X1 = 56,
+  SNE_SPECIAL_0_OPCODE_X0 = 87,
+  SNE_SPECIAL_0_OPCODE_X1 = 57,
+  SNE_SPECIAL_5_OPCODE_Y0 = 3,
+  SNE_SPECIAL_5_OPCODE_Y1 = 3,
+  SPECIAL_0_OPCODE_X0 = 0,
+  SPECIAL_0_OPCODE_X1 = 1,
+  SPECIAL_0_OPCODE_Y0 = 1,
+  SPECIAL_0_OPCODE_Y1 = 1,
+  SPECIAL_1_OPCODE_Y0 = 2,
+  SPECIAL_1_OPCODE_Y1 = 2,
+  SPECIAL_2_OPCODE_Y0 = 3,
+  SPECIAL_2_OPCODE_Y1 = 3,
+  SPECIAL_3_OPCODE_Y0 = 4,
+  SPECIAL_3_OPCODE_Y1 = 4,
+  SPECIAL_4_OPCODE_Y0 = 5,
+  SPECIAL_4_OPCODE_Y1 = 5,
+  SPECIAL_5_OPCODE_Y0 = 6,
+  SPECIAL_5_OPCODE_Y1 = 6,
+  SPECIAL_6_OPCODE_Y0 = 7,
+  SPECIAL_7_OPCODE_Y0 = 8,
+  SRAB_SPECIAL_0_OPCODE_X0 = 88,
+  SRAB_SPECIAL_0_OPCODE_X1 = 58,
+  SRAH_SPECIAL_0_OPCODE_X0 = 89,
+  SRAH_SPECIAL_0_OPCODE_X1 = 59,
+  SRAIB_SHUN_0_OPCODE_X0 = 8,
+  SRAIB_SHUN_0_OPCODE_X1 = 8,
+  SRAIH_SHUN_0_OPCODE_X0 = 9,
+  SRAIH_SHUN_0_OPCODE_X1 = 9,
+  SRAI_SHUN_0_OPCODE_X0 = 10,
+  SRAI_SHUN_0_OPCODE_X1 = 10,
+  SRAI_SHUN_0_OPCODE_Y0 = 4,
+  SRAI_SHUN_0_OPCODE_Y1 = 4,
+  SRA_SPECIAL_0_OPCODE_X0 = 90,
+  SRA_SPECIAL_0_OPCODE_X1 = 60,
+  SRA_SPECIAL_3_OPCODE_Y0 = 3,
+  SRA_SPECIAL_3_OPCODE_Y1 = 3,
+  SUBBS_U_SPECIAL_0_OPCODE_X0 = 100,
+  SUBBS_U_SPECIAL_0_OPCODE_X1 = 70,
+  SUBB_SPECIAL_0_OPCODE_X0 = 91,
+  SUBB_SPECIAL_0_OPCODE_X1 = 61,
+  SUBHS_SPECIAL_0_OPCODE_X0 = 101,
+  SUBHS_SPECIAL_0_OPCODE_X1 = 71,
+  SUBH_SPECIAL_0_OPCODE_X0 = 92,
+  SUBH_SPECIAL_0_OPCODE_X1 = 62,
+  SUBS_SPECIAL_0_OPCODE_X0 = 97,
+  SUBS_SPECIAL_0_OPCODE_X1 = 67,
+  SUB_SPECIAL_0_OPCODE_X0 = 93,
+  SUB_SPECIAL_0_OPCODE_X1 = 63,
+  SUB_SPECIAL_0_OPCODE_Y0 = 3,
+  SUB_SPECIAL_0_OPCODE_Y1 = 3,
+  SWADD_IMM_0_OPCODE_X1 = 30,
+  SWINT0_UN_0_SHUN_0_OPCODE_X1 = 18,
+  SWINT1_UN_0_SHUN_0_OPCODE_X1 = 19,
+  SWINT2_UN_0_SHUN_0_OPCODE_X1 = 20,
+  SWINT3_UN_0_SHUN_0_OPCODE_X1 = 21,
+  SW_OPCODE_Y2 = 7,
+  SW_SPECIAL_0_OPCODE_X1 = 64,
+  TBLIDXB0_UN_0_SHUN_0_OPCODE_X0 = 8,
+  TBLIDXB0_UN_0_SHUN_0_OPCODE_Y0 = 8,
+  TBLIDXB1_UN_0_SHUN_0_OPCODE_X0 = 9,
+  TBLIDXB1_UN_0_SHUN_0_OPCODE_Y0 = 9,
+  TBLIDXB2_UN_0_SHUN_0_OPCODE_X0 = 10,
+  TBLIDXB2_UN_0_SHUN_0_OPCODE_Y0 = 10,
+  TBLIDXB3_UN_0_SHUN_0_OPCODE_X0 = 11,
+  TBLIDXB3_UN_0_SHUN_0_OPCODE_Y0 = 11,
+  TNS_UN_0_SHUN_0_OPCODE_X1 = 22,
+  UN_0_SHUN_0_OPCODE_X0 = 11,
+  UN_0_SHUN_0_OPCODE_X1 = 11,
+  UN_0_SHUN_0_OPCODE_Y0 = 5,
+  UN_0_SHUN_0_OPCODE_Y1 = 5,
+  WH64_UN_0_SHUN_0_OPCODE_X1 = 23,
+  XORI_IMM_0_OPCODE_X0 = 2,
+  XORI_IMM_0_OPCODE_X1 = 21,
+  XOR_SPECIAL_0_OPCODE_X0 = 94,
+  XOR_SPECIAL_0_OPCODE_X1 = 65,
+  XOR_SPECIAL_2_OPCODE_Y0 = 3,
+  XOR_SPECIAL_2_OPCODE_Y1 = 3
+};
+
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __ARCH_OPCODE_H__ */
diff -druN linux-libre-3.1-gnu/arch/tile/include/asm/irq.h linux-libre-3.2-gnu/arch/tile/include/asm/irq.h
--- linux-libre-3.1-gnu/arch/tile/include/asm/irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/include/asm/irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -74,16 +74,6 @@
  */
 void tile_irq_activate(unsigned int irq, int tile_irq_type);
 
-/*
- * For onboard, non-PCI (e.g. TILE_IRQ_PERCPU) devices, drivers know
- * how to use enable/disable_percpu_irq() to manage interrupts on each
- * core.  We can't use the generic enable/disable_irq() because they
- * use a single reference count per irq, rather than per cpu per irq.
- */
-void enable_percpu_irq(unsigned int irq);
-void disable_percpu_irq(unsigned int irq);
-
-
 void setup_irq_regs(void);
 
 #endif /* _ASM_TILE_IRQ_H */
diff -druN linux-libre-3.1-gnu/arch/tile/include/asm/Kbuild linux-libre-3.2-gnu/arch/tile/include/asm/Kbuild
--- linux-libre-3.1-gnu/arch/tile/include/asm/Kbuild	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/include/asm/Kbuild	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,7 @@
 include include/asm-generic/Kbuild.asm
 
+header-y += ../arch/
+
 header-y += ucontext.h
 header-y += hardwall.h
 
diff -druN linux-libre-3.1-gnu/arch/tile/include/asm/opcode_constants_32.h linux-libre-3.2-gnu/arch/tile/include/asm/opcode_constants_32.h
--- linux-libre-3.1-gnu/arch/tile/include/asm/opcode_constants_32.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/include/asm/opcode_constants_32.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,480 +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.
- */
-
-/* This file is machine-generated; DO NOT EDIT! */
-
-
-#ifndef _TILE_OPCODE_CONSTANTS_H
-#define _TILE_OPCODE_CONSTANTS_H
-enum
-{
-  ADDBS_U_SPECIAL_0_OPCODE_X0 = 98,
-  ADDBS_U_SPECIAL_0_OPCODE_X1 = 68,
-  ADDB_SPECIAL_0_OPCODE_X0 = 1,
-  ADDB_SPECIAL_0_OPCODE_X1 = 1,
-  ADDHS_SPECIAL_0_OPCODE_X0 = 99,
-  ADDHS_SPECIAL_0_OPCODE_X1 = 69,
-  ADDH_SPECIAL_0_OPCODE_X0 = 2,
-  ADDH_SPECIAL_0_OPCODE_X1 = 2,
-  ADDIB_IMM_0_OPCODE_X0 = 1,
-  ADDIB_IMM_0_OPCODE_X1 = 1,
-  ADDIH_IMM_0_OPCODE_X0 = 2,
-  ADDIH_IMM_0_OPCODE_X1 = 2,
-  ADDI_IMM_0_OPCODE_X0 = 3,
-  ADDI_IMM_0_OPCODE_X1 = 3,
-  ADDI_IMM_1_OPCODE_SN = 1,
-  ADDI_OPCODE_Y0 = 9,
-  ADDI_OPCODE_Y1 = 7,
-  ADDLIS_OPCODE_X0 = 1,
-  ADDLIS_OPCODE_X1 = 2,
-  ADDLI_OPCODE_X0 = 2,
-  ADDLI_OPCODE_X1 = 3,
-  ADDS_SPECIAL_0_OPCODE_X0 = 96,
-  ADDS_SPECIAL_0_OPCODE_X1 = 66,
-  ADD_SPECIAL_0_OPCODE_X0 = 3,
-  ADD_SPECIAL_0_OPCODE_X1 = 3,
-  ADD_SPECIAL_0_OPCODE_Y0 = 0,
-  ADD_SPECIAL_0_OPCODE_Y1 = 0,
-  ADIFFB_U_SPECIAL_0_OPCODE_X0 = 4,
-  ADIFFH_SPECIAL_0_OPCODE_X0 = 5,
-  ANDI_IMM_0_OPCODE_X0 = 1,
-  ANDI_IMM_0_OPCODE_X1 = 4,
-  ANDI_OPCODE_Y0 = 10,
-  ANDI_OPCODE_Y1 = 8,
-  AND_SPECIAL_0_OPCODE_X0 = 6,
-  AND_SPECIAL_0_OPCODE_X1 = 4,
-  AND_SPECIAL_2_OPCODE_Y0 = 0,
-  AND_SPECIAL_2_OPCODE_Y1 = 0,
-  AULI_OPCODE_X0 = 3,
-  AULI_OPCODE_X1 = 4,
-  AVGB_U_SPECIAL_0_OPCODE_X0 = 7,
-  AVGH_SPECIAL_0_OPCODE_X0 = 8,
-  BBNST_BRANCH_OPCODE_X1 = 15,
-  BBNS_BRANCH_OPCODE_X1 = 14,
-  BBNS_OPCODE_SN = 63,
-  BBST_BRANCH_OPCODE_X1 = 13,
-  BBS_BRANCH_OPCODE_X1 = 12,
-  BBS_OPCODE_SN = 62,
-  BGEZT_BRANCH_OPCODE_X1 = 7,
-  BGEZ_BRANCH_OPCODE_X1 = 6,
-  BGEZ_OPCODE_SN = 61,
-  BGZT_BRANCH_OPCODE_X1 = 5,
-  BGZ_BRANCH_OPCODE_X1 = 4,
-  BGZ_OPCODE_SN = 58,
-  BITX_UN_0_SHUN_0_OPCODE_X0 = 1,
-  BITX_UN_0_SHUN_0_OPCODE_Y0 = 1,
-  BLEZT_BRANCH_OPCODE_X1 = 11,
-  BLEZ_BRANCH_OPCODE_X1 = 10,
-  BLEZ_OPCODE_SN = 59,
-  BLZT_BRANCH_OPCODE_X1 = 9,
-  BLZ_BRANCH_OPCODE_X1 = 8,
-  BLZ_OPCODE_SN = 60,
-  BNZT_BRANCH_OPCODE_X1 = 3,
-  BNZ_BRANCH_OPCODE_X1 = 2,
-  BNZ_OPCODE_SN = 57,
-  BPT_NOREG_RR_IMM_0_OPCODE_SN = 1,
-  BRANCH_OPCODE_X1 = 5,
-  BYTEX_UN_0_SHUN_0_OPCODE_X0 = 2,
-  BYTEX_UN_0_SHUN_0_OPCODE_Y0 = 2,
-  BZT_BRANCH_OPCODE_X1 = 1,
-  BZ_BRANCH_OPCODE_X1 = 0,
-  BZ_OPCODE_SN = 56,
-  CLZ_UN_0_SHUN_0_OPCODE_X0 = 3,
-  CLZ_UN_0_SHUN_0_OPCODE_Y0 = 3,
-  CRC32_32_SPECIAL_0_OPCODE_X0 = 9,
-  CRC32_8_SPECIAL_0_OPCODE_X0 = 10,
-  CTZ_UN_0_SHUN_0_OPCODE_X0 = 4,
-  CTZ_UN_0_SHUN_0_OPCODE_Y0 = 4,
-  DRAIN_UN_0_SHUN_0_OPCODE_X1 = 1,
-  DTLBPR_UN_0_SHUN_0_OPCODE_X1 = 2,
-  DWORD_ALIGN_SPECIAL_0_OPCODE_X0 = 95,
-  FINV_UN_0_SHUN_0_OPCODE_X1 = 3,
-  FLUSH_UN_0_SHUN_0_OPCODE_X1 = 4,
-  FNOP_NOREG_RR_IMM_0_OPCODE_SN = 3,
-  FNOP_UN_0_SHUN_0_OPCODE_X0 = 5,
-  FNOP_UN_0_SHUN_0_OPCODE_X1 = 5,
-  FNOP_UN_0_SHUN_0_OPCODE_Y0 = 5,
-  FNOP_UN_0_SHUN_0_OPCODE_Y1 = 1,
-  HALT_NOREG_RR_IMM_0_OPCODE_SN = 0,
-  ICOH_UN_0_SHUN_0_OPCODE_X1 = 6,
-  ILL_UN_0_SHUN_0_OPCODE_X1 = 7,
-  ILL_UN_0_SHUN_0_OPCODE_Y1 = 2,
-  IMM_0_OPCODE_SN = 0,
-  IMM_0_OPCODE_X0 = 4,
-  IMM_0_OPCODE_X1 = 6,
-  IMM_1_OPCODE_SN = 1,
-  IMM_OPCODE_0_X0 = 5,
-  INTHB_SPECIAL_0_OPCODE_X0 = 11,
-  INTHB_SPECIAL_0_OPCODE_X1 = 5,
-  INTHH_SPECIAL_0_OPCODE_X0 = 12,
-  INTHH_SPECIAL_0_OPCODE_X1 = 6,
-  INTLB_SPECIAL_0_OPCODE_X0 = 13,
-  INTLB_SPECIAL_0_OPCODE_X1 = 7,
-  INTLH_SPECIAL_0_OPCODE_X0 = 14,
-  INTLH_SPECIAL_0_OPCODE_X1 = 8,
-  INV_UN_0_SHUN_0_OPCODE_X1 = 8,
-  IRET_UN_0_SHUN_0_OPCODE_X1 = 9,
-  JALB_OPCODE_X1 = 13,
-  JALF_OPCODE_X1 = 12,
-  JALRP_SPECIAL_0_OPCODE_X1 = 9,
-  JALRR_IMM_1_OPCODE_SN = 3,
-  JALR_RR_IMM_0_OPCODE_SN = 5,
-  JALR_SPECIAL_0_OPCODE_X1 = 10,
-  JB_OPCODE_X1 = 11,
-  JF_OPCODE_X1 = 10,
-  JRP_SPECIAL_0_OPCODE_X1 = 11,
-  JRR_IMM_1_OPCODE_SN = 2,
-  JR_RR_IMM_0_OPCODE_SN = 4,
-  JR_SPECIAL_0_OPCODE_X1 = 12,
-  LBADD_IMM_0_OPCODE_X1 = 22,
-  LBADD_U_IMM_0_OPCODE_X1 = 23,
-  LB_OPCODE_Y2 = 0,
-  LB_UN_0_SHUN_0_OPCODE_X1 = 10,
-  LB_U_OPCODE_Y2 = 1,
-  LB_U_UN_0_SHUN_0_OPCODE_X1 = 11,
-  LHADD_IMM_0_OPCODE_X1 = 24,
-  LHADD_U_IMM_0_OPCODE_X1 = 25,
-  LH_OPCODE_Y2 = 2,
-  LH_UN_0_SHUN_0_OPCODE_X1 = 12,
-  LH_U_OPCODE_Y2 = 3,
-  LH_U_UN_0_SHUN_0_OPCODE_X1 = 13,
-  LNK_SPECIAL_0_OPCODE_X1 = 13,
-  LWADD_IMM_0_OPCODE_X1 = 26,
-  LWADD_NA_IMM_0_OPCODE_X1 = 27,
-  LW_NA_UN_0_SHUN_0_OPCODE_X1 = 24,
-  LW_OPCODE_Y2 = 4,
-  LW_UN_0_SHUN_0_OPCODE_X1 = 14,
-  MAXB_U_SPECIAL_0_OPCODE_X0 = 15,
-  MAXB_U_SPECIAL_0_OPCODE_X1 = 14,
-  MAXH_SPECIAL_0_OPCODE_X0 = 16,
-  MAXH_SPECIAL_0_OPCODE_X1 = 15,
-  MAXIB_U_IMM_0_OPCODE_X0 = 4,
-  MAXIB_U_IMM_0_OPCODE_X1 = 5,
-  MAXIH_IMM_0_OPCODE_X0 = 5,
-  MAXIH_IMM_0_OPCODE_X1 = 6,
-  MFSPR_IMM_0_OPCODE_X1 = 7,
-  MF_UN_0_SHUN_0_OPCODE_X1 = 15,
-  MINB_U_SPECIAL_0_OPCODE_X0 = 17,
-  MINB_U_SPECIAL_0_OPCODE_X1 = 16,
-  MINH_SPECIAL_0_OPCODE_X0 = 18,
-  MINH_SPECIAL_0_OPCODE_X1 = 17,
-  MINIB_U_IMM_0_OPCODE_X0 = 6,
-  MINIB_U_IMM_0_OPCODE_X1 = 8,
-  MINIH_IMM_0_OPCODE_X0 = 7,
-  MINIH_IMM_0_OPCODE_X1 = 9,
-  MM_OPCODE_X0 = 6,
-  MM_OPCODE_X1 = 7,
-  MNZB_SPECIAL_0_OPCODE_X0 = 19,
-  MNZB_SPECIAL_0_OPCODE_X1 = 18,
-  MNZH_SPECIAL_0_OPCODE_X0 = 20,
-  MNZH_SPECIAL_0_OPCODE_X1 = 19,
-  MNZ_SPECIAL_0_OPCODE_X0 = 21,
-  MNZ_SPECIAL_0_OPCODE_X1 = 20,
-  MNZ_SPECIAL_1_OPCODE_Y0 = 0,
-  MNZ_SPECIAL_1_OPCODE_Y1 = 1,
-  MOVEI_IMM_1_OPCODE_SN = 0,
-  MOVE_RR_IMM_0_OPCODE_SN = 8,
-  MTSPR_IMM_0_OPCODE_X1 = 10,
-  MULHHA_SS_SPECIAL_0_OPCODE_X0 = 22,
-  MULHHA_SS_SPECIAL_7_OPCODE_Y0 = 0,
-  MULHHA_SU_SPECIAL_0_OPCODE_X0 = 23,
-  MULHHA_UU_SPECIAL_0_OPCODE_X0 = 24,
-  MULHHA_UU_SPECIAL_7_OPCODE_Y0 = 1,
-  MULHHSA_UU_SPECIAL_0_OPCODE_X0 = 25,
-  MULHH_SS_SPECIAL_0_OPCODE_X0 = 26,
-  MULHH_SS_SPECIAL_6_OPCODE_Y0 = 0,
-  MULHH_SU_SPECIAL_0_OPCODE_X0 = 27,
-  MULHH_UU_SPECIAL_0_OPCODE_X0 = 28,
-  MULHH_UU_SPECIAL_6_OPCODE_Y0 = 1,
-  MULHLA_SS_SPECIAL_0_OPCODE_X0 = 29,
-  MULHLA_SU_SPECIAL_0_OPCODE_X0 = 30,
-  MULHLA_US_SPECIAL_0_OPCODE_X0 = 31,
-  MULHLA_UU_SPECIAL_0_OPCODE_X0 = 32,
-  MULHLSA_UU_SPECIAL_0_OPCODE_X0 = 33,
-  MULHLSA_UU_SPECIAL_5_OPCODE_Y0 = 0,
-  MULHL_SS_SPECIAL_0_OPCODE_X0 = 34,
-  MULHL_SU_SPECIAL_0_OPCODE_X0 = 35,
-  MULHL_US_SPECIAL_0_OPCODE_X0 = 36,
-  MULHL_UU_SPECIAL_0_OPCODE_X0 = 37,
-  MULLLA_SS_SPECIAL_0_OPCODE_X0 = 38,
-  MULLLA_SS_SPECIAL_7_OPCODE_Y0 = 2,
-  MULLLA_SU_SPECIAL_0_OPCODE_X0 = 39,
-  MULLLA_UU_SPECIAL_0_OPCODE_X0 = 40,
-  MULLLA_UU_SPECIAL_7_OPCODE_Y0 = 3,
-  MULLLSA_UU_SPECIAL_0_OPCODE_X0 = 41,
-  MULLL_SS_SPECIAL_0_OPCODE_X0 = 42,
-  MULLL_SS_SPECIAL_6_OPCODE_Y0 = 2,
-  MULLL_SU_SPECIAL_0_OPCODE_X0 = 43,
-  MULLL_UU_SPECIAL_0_OPCODE_X0 = 44,
-  MULLL_UU_SPECIAL_6_OPCODE_Y0 = 3,
-  MVNZ_SPECIAL_0_OPCODE_X0 = 45,
-  MVNZ_SPECIAL_1_OPCODE_Y0 = 1,
-  MVZ_SPECIAL_0_OPCODE_X0 = 46,
-  MVZ_SPECIAL_1_OPCODE_Y0 = 2,
-  MZB_SPECIAL_0_OPCODE_X0 = 47,
-  MZB_SPECIAL_0_OPCODE_X1 = 21,
-  MZH_SPECIAL_0_OPCODE_X0 = 48,
-  MZH_SPECIAL_0_OPCODE_X1 = 22,
-  MZ_SPECIAL_0_OPCODE_X0 = 49,
-  MZ_SPECIAL_0_OPCODE_X1 = 23,
-  MZ_SPECIAL_1_OPCODE_Y0 = 3,
-  MZ_SPECIAL_1_OPCODE_Y1 = 2,
-  NAP_UN_0_SHUN_0_OPCODE_X1 = 16,
-  NOP_NOREG_RR_IMM_0_OPCODE_SN = 2,
-  NOP_UN_0_SHUN_0_OPCODE_X0 = 6,
-  NOP_UN_0_SHUN_0_OPCODE_X1 = 17,
-  NOP_UN_0_SHUN_0_OPCODE_Y0 = 6,
-  NOP_UN_0_SHUN_0_OPCODE_Y1 = 3,
-  NOREG_RR_IMM_0_OPCODE_SN = 0,
-  NOR_SPECIAL_0_OPCODE_X0 = 50,
-  NOR_SPECIAL_0_OPCODE_X1 = 24,
-  NOR_SPECIAL_2_OPCODE_Y0 = 1,
-  NOR_SPECIAL_2_OPCODE_Y1 = 1,
-  ORI_IMM_0_OPCODE_X0 = 8,
-  ORI_IMM_0_OPCODE_X1 = 11,
-  ORI_OPCODE_Y0 = 11,
-  ORI_OPCODE_Y1 = 9,
-  OR_SPECIAL_0_OPCODE_X0 = 51,
-  OR_SPECIAL_0_OPCODE_X1 = 25,
-  OR_SPECIAL_2_OPCODE_Y0 = 2,
-  OR_SPECIAL_2_OPCODE_Y1 = 2,
-  PACKBS_U_SPECIAL_0_OPCODE_X0 = 103,
-  PACKBS_U_SPECIAL_0_OPCODE_X1 = 73,
-  PACKHB_SPECIAL_0_OPCODE_X0 = 52,
-  PACKHB_SPECIAL_0_OPCODE_X1 = 26,
-  PACKHS_SPECIAL_0_OPCODE_X0 = 102,
-  PACKHS_SPECIAL_0_OPCODE_X1 = 72,
-  PACKLB_SPECIAL_0_OPCODE_X0 = 53,
-  PACKLB_SPECIAL_0_OPCODE_X1 = 27,
-  PCNT_UN_0_SHUN_0_OPCODE_X0 = 7,
-  PCNT_UN_0_SHUN_0_OPCODE_Y0 = 7,
-  RLI_SHUN_0_OPCODE_X0 = 1,
-  RLI_SHUN_0_OPCODE_X1 = 1,
-  RLI_SHUN_0_OPCODE_Y0 = 1,
-  RLI_SHUN_0_OPCODE_Y1 = 1,
-  RL_SPECIAL_0_OPCODE_X0 = 54,
-  RL_SPECIAL_0_OPCODE_X1 = 28,
-  RL_SPECIAL_3_OPCODE_Y0 = 0,
-  RL_SPECIAL_3_OPCODE_Y1 = 0,
-  RR_IMM_0_OPCODE_SN = 0,
-  S1A_SPECIAL_0_OPCODE_X0 = 55,
-  S1A_SPECIAL_0_OPCODE_X1 = 29,
-  S1A_SPECIAL_0_OPCODE_Y0 = 1,
-  S1A_SPECIAL_0_OPCODE_Y1 = 1,
-  S2A_SPECIAL_0_OPCODE_X0 = 56,
-  S2A_SPECIAL_0_OPCODE_X1 = 30,
-  S2A_SPECIAL_0_OPCODE_Y0 = 2,
-  S2A_SPECIAL_0_OPCODE_Y1 = 2,
-  S3A_SPECIAL_0_OPCODE_X0 = 57,
-  S3A_SPECIAL_0_OPCODE_X1 = 31,
-  S3A_SPECIAL_5_OPCODE_Y0 = 1,
-  S3A_SPECIAL_5_OPCODE_Y1 = 1,
-  SADAB_U_SPECIAL_0_OPCODE_X0 = 58,
-  SADAH_SPECIAL_0_OPCODE_X0 = 59,
-  SADAH_U_SPECIAL_0_OPCODE_X0 = 60,
-  SADB_U_SPECIAL_0_OPCODE_X0 = 61,
-  SADH_SPECIAL_0_OPCODE_X0 = 62,
-  SADH_U_SPECIAL_0_OPCODE_X0 = 63,
-  SBADD_IMM_0_OPCODE_X1 = 28,
-  SB_OPCODE_Y2 = 5,
-  SB_SPECIAL_0_OPCODE_X1 = 32,
-  SEQB_SPECIAL_0_OPCODE_X0 = 64,
-  SEQB_SPECIAL_0_OPCODE_X1 = 33,
-  SEQH_SPECIAL_0_OPCODE_X0 = 65,
-  SEQH_SPECIAL_0_OPCODE_X1 = 34,
-  SEQIB_IMM_0_OPCODE_X0 = 9,
-  SEQIB_IMM_0_OPCODE_X1 = 12,
-  SEQIH_IMM_0_OPCODE_X0 = 10,
-  SEQIH_IMM_0_OPCODE_X1 = 13,
-  SEQI_IMM_0_OPCODE_X0 = 11,
-  SEQI_IMM_0_OPCODE_X1 = 14,
-  SEQI_OPCODE_Y0 = 12,
-  SEQI_OPCODE_Y1 = 10,
-  SEQ_SPECIAL_0_OPCODE_X0 = 66,
-  SEQ_SPECIAL_0_OPCODE_X1 = 35,
-  SEQ_SPECIAL_5_OPCODE_Y0 = 2,
-  SEQ_SPECIAL_5_OPCODE_Y1 = 2,
-  SHADD_IMM_0_OPCODE_X1 = 29,
-  SHL8II_IMM_0_OPCODE_SN = 3,
-  SHLB_SPECIAL_0_OPCODE_X0 = 67,
-  SHLB_SPECIAL_0_OPCODE_X1 = 36,
-  SHLH_SPECIAL_0_OPCODE_X0 = 68,
-  SHLH_SPECIAL_0_OPCODE_X1 = 37,
-  SHLIB_SHUN_0_OPCODE_X0 = 2,
-  SHLIB_SHUN_0_OPCODE_X1 = 2,
-  SHLIH_SHUN_0_OPCODE_X0 = 3,
-  SHLIH_SHUN_0_OPCODE_X1 = 3,
-  SHLI_SHUN_0_OPCODE_X0 = 4,
-  SHLI_SHUN_0_OPCODE_X1 = 4,
-  SHLI_SHUN_0_OPCODE_Y0 = 2,
-  SHLI_SHUN_0_OPCODE_Y1 = 2,
-  SHL_SPECIAL_0_OPCODE_X0 = 69,
-  SHL_SPECIAL_0_OPCODE_X1 = 38,
-  SHL_SPECIAL_3_OPCODE_Y0 = 1,
-  SHL_SPECIAL_3_OPCODE_Y1 = 1,
-  SHR1_RR_IMM_0_OPCODE_SN = 9,
-  SHRB_SPECIAL_0_OPCODE_X0 = 70,
-  SHRB_SPECIAL_0_OPCODE_X1 = 39,
-  SHRH_SPECIAL_0_OPCODE_X0 = 71,
-  SHRH_SPECIAL_0_OPCODE_X1 = 40,
-  SHRIB_SHUN_0_OPCODE_X0 = 5,
-  SHRIB_SHUN_0_OPCODE_X1 = 5,
-  SHRIH_SHUN_0_OPCODE_X0 = 6,
-  SHRIH_SHUN_0_OPCODE_X1 = 6,
-  SHRI_SHUN_0_OPCODE_X0 = 7,
-  SHRI_SHUN_0_OPCODE_X1 = 7,
-  SHRI_SHUN_0_OPCODE_Y0 = 3,
-  SHRI_SHUN_0_OPCODE_Y1 = 3,
-  SHR_SPECIAL_0_OPCODE_X0 = 72,
-  SHR_SPECIAL_0_OPCODE_X1 = 41,
-  SHR_SPECIAL_3_OPCODE_Y0 = 2,
-  SHR_SPECIAL_3_OPCODE_Y1 = 2,
-  SHUN_0_OPCODE_X0 = 7,
-  SHUN_0_OPCODE_X1 = 8,
-  SHUN_0_OPCODE_Y0 = 13,
-  SHUN_0_OPCODE_Y1 = 11,
-  SH_OPCODE_Y2 = 6,
-  SH_SPECIAL_0_OPCODE_X1 = 42,
-  SLTB_SPECIAL_0_OPCODE_X0 = 73,
-  SLTB_SPECIAL_0_OPCODE_X1 = 43,
-  SLTB_U_SPECIAL_0_OPCODE_X0 = 74,
-  SLTB_U_SPECIAL_0_OPCODE_X1 = 44,
-  SLTEB_SPECIAL_0_OPCODE_X0 = 75,
-  SLTEB_SPECIAL_0_OPCODE_X1 = 45,
-  SLTEB_U_SPECIAL_0_OPCODE_X0 = 76,
-  SLTEB_U_SPECIAL_0_OPCODE_X1 = 46,
-  SLTEH_SPECIAL_0_OPCODE_X0 = 77,
-  SLTEH_SPECIAL_0_OPCODE_X1 = 47,
-  SLTEH_U_SPECIAL_0_OPCODE_X0 = 78,
-  SLTEH_U_SPECIAL_0_OPCODE_X1 = 48,
-  SLTE_SPECIAL_0_OPCODE_X0 = 79,
-  SLTE_SPECIAL_0_OPCODE_X1 = 49,
-  SLTE_SPECIAL_4_OPCODE_Y0 = 0,
-  SLTE_SPECIAL_4_OPCODE_Y1 = 0,
-  SLTE_U_SPECIAL_0_OPCODE_X0 = 80,
-  SLTE_U_SPECIAL_0_OPCODE_X1 = 50,
-  SLTE_U_SPECIAL_4_OPCODE_Y0 = 1,
-  SLTE_U_SPECIAL_4_OPCODE_Y1 = 1,
-  SLTH_SPECIAL_0_OPCODE_X0 = 81,
-  SLTH_SPECIAL_0_OPCODE_X1 = 51,
-  SLTH_U_SPECIAL_0_OPCODE_X0 = 82,
-  SLTH_U_SPECIAL_0_OPCODE_X1 = 52,
-  SLTIB_IMM_0_OPCODE_X0 = 12,
-  SLTIB_IMM_0_OPCODE_X1 = 15,
-  SLTIB_U_IMM_0_OPCODE_X0 = 13,
-  SLTIB_U_IMM_0_OPCODE_X1 = 16,
-  SLTIH_IMM_0_OPCODE_X0 = 14,
-  SLTIH_IMM_0_OPCODE_X1 = 17,
-  SLTIH_U_IMM_0_OPCODE_X0 = 15,
-  SLTIH_U_IMM_0_OPCODE_X1 = 18,
-  SLTI_IMM_0_OPCODE_X0 = 16,
-  SLTI_IMM_0_OPCODE_X1 = 19,
-  SLTI_OPCODE_Y0 = 14,
-  SLTI_OPCODE_Y1 = 12,
-  SLTI_U_IMM_0_OPCODE_X0 = 17,
-  SLTI_U_IMM_0_OPCODE_X1 = 20,
-  SLTI_U_OPCODE_Y0 = 15,
-  SLTI_U_OPCODE_Y1 = 13,
-  SLT_SPECIAL_0_OPCODE_X0 = 83,
-  SLT_SPECIAL_0_OPCODE_X1 = 53,
-  SLT_SPECIAL_4_OPCODE_Y0 = 2,
-  SLT_SPECIAL_4_OPCODE_Y1 = 2,
-  SLT_U_SPECIAL_0_OPCODE_X0 = 84,
-  SLT_U_SPECIAL_0_OPCODE_X1 = 54,
-  SLT_U_SPECIAL_4_OPCODE_Y0 = 3,
-  SLT_U_SPECIAL_4_OPCODE_Y1 = 3,
-  SNEB_SPECIAL_0_OPCODE_X0 = 85,
-  SNEB_SPECIAL_0_OPCODE_X1 = 55,
-  SNEH_SPECIAL_0_OPCODE_X0 = 86,
-  SNEH_SPECIAL_0_OPCODE_X1 = 56,
-  SNE_SPECIAL_0_OPCODE_X0 = 87,
-  SNE_SPECIAL_0_OPCODE_X1 = 57,
-  SNE_SPECIAL_5_OPCODE_Y0 = 3,
-  SNE_SPECIAL_5_OPCODE_Y1 = 3,
-  SPECIAL_0_OPCODE_X0 = 0,
-  SPECIAL_0_OPCODE_X1 = 1,
-  SPECIAL_0_OPCODE_Y0 = 1,
-  SPECIAL_0_OPCODE_Y1 = 1,
-  SPECIAL_1_OPCODE_Y0 = 2,
-  SPECIAL_1_OPCODE_Y1 = 2,
-  SPECIAL_2_OPCODE_Y0 = 3,
-  SPECIAL_2_OPCODE_Y1 = 3,
-  SPECIAL_3_OPCODE_Y0 = 4,
-  SPECIAL_3_OPCODE_Y1 = 4,
-  SPECIAL_4_OPCODE_Y0 = 5,
-  SPECIAL_4_OPCODE_Y1 = 5,
-  SPECIAL_5_OPCODE_Y0 = 6,
-  SPECIAL_5_OPCODE_Y1 = 6,
-  SPECIAL_6_OPCODE_Y0 = 7,
-  SPECIAL_7_OPCODE_Y0 = 8,
-  SRAB_SPECIAL_0_OPCODE_X0 = 88,
-  SRAB_SPECIAL_0_OPCODE_X1 = 58,
-  SRAH_SPECIAL_0_OPCODE_X0 = 89,
-  SRAH_SPECIAL_0_OPCODE_X1 = 59,
-  SRAIB_SHUN_0_OPCODE_X0 = 8,
-  SRAIB_SHUN_0_OPCODE_X1 = 8,
-  SRAIH_SHUN_0_OPCODE_X0 = 9,
-  SRAIH_SHUN_0_OPCODE_X1 = 9,
-  SRAI_SHUN_0_OPCODE_X0 = 10,
-  SRAI_SHUN_0_OPCODE_X1 = 10,
-  SRAI_SHUN_0_OPCODE_Y0 = 4,
-  SRAI_SHUN_0_OPCODE_Y1 = 4,
-  SRA_SPECIAL_0_OPCODE_X0 = 90,
-  SRA_SPECIAL_0_OPCODE_X1 = 60,
-  SRA_SPECIAL_3_OPCODE_Y0 = 3,
-  SRA_SPECIAL_3_OPCODE_Y1 = 3,
-  SUBBS_U_SPECIAL_0_OPCODE_X0 = 100,
-  SUBBS_U_SPECIAL_0_OPCODE_X1 = 70,
-  SUBB_SPECIAL_0_OPCODE_X0 = 91,
-  SUBB_SPECIAL_0_OPCODE_X1 = 61,
-  SUBHS_SPECIAL_0_OPCODE_X0 = 101,
-  SUBHS_SPECIAL_0_OPCODE_X1 = 71,
-  SUBH_SPECIAL_0_OPCODE_X0 = 92,
-  SUBH_SPECIAL_0_OPCODE_X1 = 62,
-  SUBS_SPECIAL_0_OPCODE_X0 = 97,
-  SUBS_SPECIAL_0_OPCODE_X1 = 67,
-  SUB_SPECIAL_0_OPCODE_X0 = 93,
-  SUB_SPECIAL_0_OPCODE_X1 = 63,
-  SUB_SPECIAL_0_OPCODE_Y0 = 3,
-  SUB_SPECIAL_0_OPCODE_Y1 = 3,
-  SWADD_IMM_0_OPCODE_X1 = 30,
-  SWINT0_UN_0_SHUN_0_OPCODE_X1 = 18,
-  SWINT1_UN_0_SHUN_0_OPCODE_X1 = 19,
-  SWINT2_UN_0_SHUN_0_OPCODE_X1 = 20,
-  SWINT3_UN_0_SHUN_0_OPCODE_X1 = 21,
-  SW_OPCODE_Y2 = 7,
-  SW_SPECIAL_0_OPCODE_X1 = 64,
-  TBLIDXB0_UN_0_SHUN_0_OPCODE_X0 = 8,
-  TBLIDXB0_UN_0_SHUN_0_OPCODE_Y0 = 8,
-  TBLIDXB1_UN_0_SHUN_0_OPCODE_X0 = 9,
-  TBLIDXB1_UN_0_SHUN_0_OPCODE_Y0 = 9,
-  TBLIDXB2_UN_0_SHUN_0_OPCODE_X0 = 10,
-  TBLIDXB2_UN_0_SHUN_0_OPCODE_Y0 = 10,
-  TBLIDXB3_UN_0_SHUN_0_OPCODE_X0 = 11,
-  TBLIDXB3_UN_0_SHUN_0_OPCODE_Y0 = 11,
-  TNS_UN_0_SHUN_0_OPCODE_X1 = 22,
-  UN_0_SHUN_0_OPCODE_X0 = 11,
-  UN_0_SHUN_0_OPCODE_X1 = 11,
-  UN_0_SHUN_0_OPCODE_Y0 = 5,
-  UN_0_SHUN_0_OPCODE_Y1 = 5,
-  WH64_UN_0_SHUN_0_OPCODE_X1 = 23,
-  XORI_IMM_0_OPCODE_X0 = 2,
-  XORI_IMM_0_OPCODE_X1 = 21,
-  XOR_SPECIAL_0_OPCODE_X0 = 94,
-  XOR_SPECIAL_0_OPCODE_X1 = 65,
-  XOR_SPECIAL_2_OPCODE_Y0 = 3,
-  XOR_SPECIAL_2_OPCODE_Y1 = 3
-};
-
-#endif /* !_TILE_OPCODE_CONSTANTS_H */
diff -druN linux-libre-3.1-gnu/arch/tile/include/asm/opcode_constants_64.h linux-libre-3.2-gnu/arch/tile/include/asm/opcode_constants_64.h
--- linux-libre-3.1-gnu/arch/tile/include/asm/opcode_constants_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/include/asm/opcode_constants_64.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,609 +0,0 @@
-/*
- * 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.
- */
-
-/* This file is machine-generated; DO NOT EDIT! */
-
-
-#ifndef _TILE_OPCODE_CONSTANTS_H
-#define _TILE_OPCODE_CONSTANTS_H
-enum
-{
-  ADDI_IMM8_OPCODE_X0 = 1,
-  ADDI_IMM8_OPCODE_X1 = 1,
-  ADDI_OPCODE_Y0 = 0,
-  ADDI_OPCODE_Y1 = 1,
-  ADDLI_OPCODE_X0 = 1,
-  ADDLI_OPCODE_X1 = 0,
-  ADDXI_IMM8_OPCODE_X0 = 2,
-  ADDXI_IMM8_OPCODE_X1 = 2,
-  ADDXI_OPCODE_Y0 = 1,
-  ADDXI_OPCODE_Y1 = 2,
-  ADDXLI_OPCODE_X0 = 2,
-  ADDXLI_OPCODE_X1 = 1,
-  ADDXSC_RRR_0_OPCODE_X0 = 1,
-  ADDXSC_RRR_0_OPCODE_X1 = 1,
-  ADDX_RRR_0_OPCODE_X0 = 2,
-  ADDX_RRR_0_OPCODE_X1 = 2,
-  ADDX_RRR_0_OPCODE_Y0 = 0,
-  ADDX_SPECIAL_0_OPCODE_Y1 = 0,
-  ADD_RRR_0_OPCODE_X0 = 3,
-  ADD_RRR_0_OPCODE_X1 = 3,
-  ADD_RRR_0_OPCODE_Y0 = 1,
-  ADD_SPECIAL_0_OPCODE_Y1 = 1,
-  ANDI_IMM8_OPCODE_X0 = 3,
-  ANDI_IMM8_OPCODE_X1 = 3,
-  ANDI_OPCODE_Y0 = 2,
-  ANDI_OPCODE_Y1 = 3,
-  AND_RRR_0_OPCODE_X0 = 4,
-  AND_RRR_0_OPCODE_X1 = 4,
-  AND_RRR_5_OPCODE_Y0 = 0,
-  AND_RRR_5_OPCODE_Y1 = 0,
-  BEQZT_BRANCH_OPCODE_X1 = 16,
-  BEQZ_BRANCH_OPCODE_X1 = 17,
-  BFEXTS_BF_OPCODE_X0 = 4,
-  BFEXTU_BF_OPCODE_X0 = 5,
-  BFINS_BF_OPCODE_X0 = 6,
-  BF_OPCODE_X0 = 3,
-  BGEZT_BRANCH_OPCODE_X1 = 18,
-  BGEZ_BRANCH_OPCODE_X1 = 19,
-  BGTZT_BRANCH_OPCODE_X1 = 20,
-  BGTZ_BRANCH_OPCODE_X1 = 21,
-  BLBCT_BRANCH_OPCODE_X1 = 22,
-  BLBC_BRANCH_OPCODE_X1 = 23,
-  BLBST_BRANCH_OPCODE_X1 = 24,
-  BLBS_BRANCH_OPCODE_X1 = 25,
-  BLEZT_BRANCH_OPCODE_X1 = 26,
-  BLEZ_BRANCH_OPCODE_X1 = 27,
-  BLTZT_BRANCH_OPCODE_X1 = 28,
-  BLTZ_BRANCH_OPCODE_X1 = 29,
-  BNEZT_BRANCH_OPCODE_X1 = 30,
-  BNEZ_BRANCH_OPCODE_X1 = 31,
-  BRANCH_OPCODE_X1 = 2,
-  CMOVEQZ_RRR_0_OPCODE_X0 = 5,
-  CMOVEQZ_RRR_4_OPCODE_Y0 = 0,
-  CMOVNEZ_RRR_0_OPCODE_X0 = 6,
-  CMOVNEZ_RRR_4_OPCODE_Y0 = 1,
-  CMPEQI_IMM8_OPCODE_X0 = 4,
-  CMPEQI_IMM8_OPCODE_X1 = 4,
-  CMPEQI_OPCODE_Y0 = 3,
-  CMPEQI_OPCODE_Y1 = 4,
-  CMPEQ_RRR_0_OPCODE_X0 = 7,
-  CMPEQ_RRR_0_OPCODE_X1 = 5,
-  CMPEQ_RRR_3_OPCODE_Y0 = 0,
-  CMPEQ_RRR_3_OPCODE_Y1 = 2,
-  CMPEXCH4_RRR_0_OPCODE_X1 = 6,
-  CMPEXCH_RRR_0_OPCODE_X1 = 7,
-  CMPLES_RRR_0_OPCODE_X0 = 8,
-  CMPLES_RRR_0_OPCODE_X1 = 8,
-  CMPLES_RRR_2_OPCODE_Y0 = 0,
-  CMPLES_RRR_2_OPCODE_Y1 = 0,
-  CMPLEU_RRR_0_OPCODE_X0 = 9,
-  CMPLEU_RRR_0_OPCODE_X1 = 9,
-  CMPLEU_RRR_2_OPCODE_Y0 = 1,
-  CMPLEU_RRR_2_OPCODE_Y1 = 1,
-  CMPLTSI_IMM8_OPCODE_X0 = 5,
-  CMPLTSI_IMM8_OPCODE_X1 = 5,
-  CMPLTSI_OPCODE_Y0 = 4,
-  CMPLTSI_OPCODE_Y1 = 5,
-  CMPLTS_RRR_0_OPCODE_X0 = 10,
-  CMPLTS_RRR_0_OPCODE_X1 = 10,
-  CMPLTS_RRR_2_OPCODE_Y0 = 2,
-  CMPLTS_RRR_2_OPCODE_Y1 = 2,
-  CMPLTUI_IMM8_OPCODE_X0 = 6,
-  CMPLTUI_IMM8_OPCODE_X1 = 6,
-  CMPLTU_RRR_0_OPCODE_X0 = 11,
-  CMPLTU_RRR_0_OPCODE_X1 = 11,
-  CMPLTU_RRR_2_OPCODE_Y0 = 3,
-  CMPLTU_RRR_2_OPCODE_Y1 = 3,
-  CMPNE_RRR_0_OPCODE_X0 = 12,
-  CMPNE_RRR_0_OPCODE_X1 = 12,
-  CMPNE_RRR_3_OPCODE_Y0 = 1,
-  CMPNE_RRR_3_OPCODE_Y1 = 3,
-  CMULAF_RRR_0_OPCODE_X0 = 13,
-  CMULA_RRR_0_OPCODE_X0 = 14,
-  CMULFR_RRR_0_OPCODE_X0 = 15,
-  CMULF_RRR_0_OPCODE_X0 = 16,
-  CMULHR_RRR_0_OPCODE_X0 = 17,
-  CMULH_RRR_0_OPCODE_X0 = 18,
-  CMUL_RRR_0_OPCODE_X0 = 19,
-  CNTLZ_UNARY_OPCODE_X0 = 1,
-  CNTLZ_UNARY_OPCODE_Y0 = 1,
-  CNTTZ_UNARY_OPCODE_X0 = 2,
-  CNTTZ_UNARY_OPCODE_Y0 = 2,
-  CRC32_32_RRR_0_OPCODE_X0 = 20,
-  CRC32_8_RRR_0_OPCODE_X0 = 21,
-  DBLALIGN2_RRR_0_OPCODE_X0 = 22,
-  DBLALIGN2_RRR_0_OPCODE_X1 = 13,
-  DBLALIGN4_RRR_0_OPCODE_X0 = 23,
-  DBLALIGN4_RRR_0_OPCODE_X1 = 14,
-  DBLALIGN6_RRR_0_OPCODE_X0 = 24,
-  DBLALIGN6_RRR_0_OPCODE_X1 = 15,
-  DBLALIGN_RRR_0_OPCODE_X0 = 25,
-  DRAIN_UNARY_OPCODE_X1 = 1,
-  DTLBPR_UNARY_OPCODE_X1 = 2,
-  EXCH4_RRR_0_OPCODE_X1 = 16,
-  EXCH_RRR_0_OPCODE_X1 = 17,
-  FDOUBLE_ADDSUB_RRR_0_OPCODE_X0 = 26,
-  FDOUBLE_ADD_FLAGS_RRR_0_OPCODE_X0 = 27,
-  FDOUBLE_MUL_FLAGS_RRR_0_OPCODE_X0 = 28,
-  FDOUBLE_PACK1_RRR_0_OPCODE_X0 = 29,
-  FDOUBLE_PACK2_RRR_0_OPCODE_X0 = 30,
-  FDOUBLE_SUB_FLAGS_RRR_0_OPCODE_X0 = 31,
-  FDOUBLE_UNPACK_MAX_RRR_0_OPCODE_X0 = 32,
-  FDOUBLE_UNPACK_MIN_RRR_0_OPCODE_X0 = 33,
-  FETCHADD4_RRR_0_OPCODE_X1 = 18,
-  FETCHADDGEZ4_RRR_0_OPCODE_X1 = 19,
-  FETCHADDGEZ_RRR_0_OPCODE_X1 = 20,
-  FETCHADD_RRR_0_OPCODE_X1 = 21,
-  FETCHAND4_RRR_0_OPCODE_X1 = 22,
-  FETCHAND_RRR_0_OPCODE_X1 = 23,
-  FETCHOR4_RRR_0_OPCODE_X1 = 24,
-  FETCHOR_RRR_0_OPCODE_X1 = 25,
-  FINV_UNARY_OPCODE_X1 = 3,
-  FLUSHWB_UNARY_OPCODE_X1 = 4,
-  FLUSH_UNARY_OPCODE_X1 = 5,
-  FNOP_UNARY_OPCODE_X0 = 3,
-  FNOP_UNARY_OPCODE_X1 = 6,
-  FNOP_UNARY_OPCODE_Y0 = 3,
-  FNOP_UNARY_OPCODE_Y1 = 8,
-  FSINGLE_ADD1_RRR_0_OPCODE_X0 = 34,
-  FSINGLE_ADDSUB2_RRR_0_OPCODE_X0 = 35,
-  FSINGLE_MUL1_RRR_0_OPCODE_X0 = 36,
-  FSINGLE_MUL2_RRR_0_OPCODE_X0 = 37,
-  FSINGLE_PACK1_UNARY_OPCODE_X0 = 4,
-  FSINGLE_PACK1_UNARY_OPCODE_Y0 = 4,
-  FSINGLE_PACK2_RRR_0_OPCODE_X0 = 38,
-  FSINGLE_SUB1_RRR_0_OPCODE_X0 = 39,
-  ICOH_UNARY_OPCODE_X1 = 7,
-  ILL_UNARY_OPCODE_X1 = 8,
-  ILL_UNARY_OPCODE_Y1 = 9,
-  IMM8_OPCODE_X0 = 4,
-  IMM8_OPCODE_X1 = 3,
-  INV_UNARY_OPCODE_X1 = 9,
-  IRET_UNARY_OPCODE_X1 = 10,
-  JALRP_UNARY_OPCODE_X1 = 11,
-  JALRP_UNARY_OPCODE_Y1 = 10,
-  JALR_UNARY_OPCODE_X1 = 12,
-  JALR_UNARY_OPCODE_Y1 = 11,
-  JAL_JUMP_OPCODE_X1 = 0,
-  JRP_UNARY_OPCODE_X1 = 13,
-  JRP_UNARY_OPCODE_Y1 = 12,
-  JR_UNARY_OPCODE_X1 = 14,
-  JR_UNARY_OPCODE_Y1 = 13,
-  JUMP_OPCODE_X1 = 4,
-  J_JUMP_OPCODE_X1 = 1,
-  LD1S_ADD_IMM8_OPCODE_X1 = 7,
-  LD1S_OPCODE_Y2 = 0,
-  LD1S_UNARY_OPCODE_X1 = 15,
-  LD1U_ADD_IMM8_OPCODE_X1 = 8,
-  LD1U_OPCODE_Y2 = 1,
-  LD1U_UNARY_OPCODE_X1 = 16,
-  LD2S_ADD_IMM8_OPCODE_X1 = 9,
-  LD2S_OPCODE_Y2 = 2,
-  LD2S_UNARY_OPCODE_X1 = 17,
-  LD2U_ADD_IMM8_OPCODE_X1 = 10,
-  LD2U_OPCODE_Y2 = 3,
-  LD2U_UNARY_OPCODE_X1 = 18,
-  LD4S_ADD_IMM8_OPCODE_X1 = 11,
-  LD4S_OPCODE_Y2 = 1,
-  LD4S_UNARY_OPCODE_X1 = 19,
-  LD4U_ADD_IMM8_OPCODE_X1 = 12,
-  LD4U_OPCODE_Y2 = 2,
-  LD4U_UNARY_OPCODE_X1 = 20,
-  LDNA_UNARY_OPCODE_X1 = 21,
-  LDNT1S_ADD_IMM8_OPCODE_X1 = 13,
-  LDNT1S_UNARY_OPCODE_X1 = 22,
-  LDNT1U_ADD_IMM8_OPCODE_X1 = 14,
-  LDNT1U_UNARY_OPCODE_X1 = 23,
-  LDNT2S_ADD_IMM8_OPCODE_X1 = 15,
-  LDNT2S_UNARY_OPCODE_X1 = 24,
-  LDNT2U_ADD_IMM8_OPCODE_X1 = 16,
-  LDNT2U_UNARY_OPCODE_X1 = 25,
-  LDNT4S_ADD_IMM8_OPCODE_X1 = 17,
-  LDNT4S_UNARY_OPCODE_X1 = 26,
-  LDNT4U_ADD_IMM8_OPCODE_X1 = 18,
-  LDNT4U_UNARY_OPCODE_X1 = 27,
-  LDNT_ADD_IMM8_OPCODE_X1 = 19,
-  LDNT_UNARY_OPCODE_X1 = 28,
-  LD_ADD_IMM8_OPCODE_X1 = 20,
-  LD_OPCODE_Y2 = 3,
-  LD_UNARY_OPCODE_X1 = 29,
-  LNK_UNARY_OPCODE_X1 = 30,
-  LNK_UNARY_OPCODE_Y1 = 14,
-  LWNA_ADD_IMM8_OPCODE_X1 = 21,
-  MFSPR_IMM8_OPCODE_X1 = 22,
-  MF_UNARY_OPCODE_X1 = 31,
-  MM_BF_OPCODE_X0 = 7,
-  MNZ_RRR_0_OPCODE_X0 = 40,
-  MNZ_RRR_0_OPCODE_X1 = 26,
-  MNZ_RRR_4_OPCODE_Y0 = 2,
-  MNZ_RRR_4_OPCODE_Y1 = 2,
-  MODE_OPCODE_YA2 = 1,
-  MODE_OPCODE_YB2 = 2,
-  MODE_OPCODE_YC2 = 3,
-  MTSPR_IMM8_OPCODE_X1 = 23,
-  MULAX_RRR_0_OPCODE_X0 = 41,
-  MULAX_RRR_3_OPCODE_Y0 = 2,
-  MULA_HS_HS_RRR_0_OPCODE_X0 = 42,
-  MULA_HS_HS_RRR_9_OPCODE_Y0 = 0,
-  MULA_HS_HU_RRR_0_OPCODE_X0 = 43,
-  MULA_HS_LS_RRR_0_OPCODE_X0 = 44,
-  MULA_HS_LU_RRR_0_OPCODE_X0 = 45,
-  MULA_HU_HU_RRR_0_OPCODE_X0 = 46,
-  MULA_HU_HU_RRR_9_OPCODE_Y0 = 1,
-  MULA_HU_LS_RRR_0_OPCODE_X0 = 47,
-  MULA_HU_LU_RRR_0_OPCODE_X0 = 48,
-  MULA_LS_LS_RRR_0_OPCODE_X0 = 49,
-  MULA_LS_LS_RRR_9_OPCODE_Y0 = 2,
-  MULA_LS_LU_RRR_0_OPCODE_X0 = 50,
-  MULA_LU_LU_RRR_0_OPCODE_X0 = 51,
-  MULA_LU_LU_RRR_9_OPCODE_Y0 = 3,
-  MULX_RRR_0_OPCODE_X0 = 52,
-  MULX_RRR_3_OPCODE_Y0 = 3,
-  MUL_HS_HS_RRR_0_OPCODE_X0 = 53,
-  MUL_HS_HS_RRR_8_OPCODE_Y0 = 0,
-  MUL_HS_HU_RRR_0_OPCODE_X0 = 54,
-  MUL_HS_LS_RRR_0_OPCODE_X0 = 55,
-  MUL_HS_LU_RRR_0_OPCODE_X0 = 56,
-  MUL_HU_HU_RRR_0_OPCODE_X0 = 57,
-  MUL_HU_HU_RRR_8_OPCODE_Y0 = 1,
-  MUL_HU_LS_RRR_0_OPCODE_X0 = 58,
-  MUL_HU_LU_RRR_0_OPCODE_X0 = 59,
-  MUL_LS_LS_RRR_0_OPCODE_X0 = 60,
-  MUL_LS_LS_RRR_8_OPCODE_Y0 = 2,
-  MUL_LS_LU_RRR_0_OPCODE_X0 = 61,
-  MUL_LU_LU_RRR_0_OPCODE_X0 = 62,
-  MUL_LU_LU_RRR_8_OPCODE_Y0 = 3,
-  MZ_RRR_0_OPCODE_X0 = 63,
-  MZ_RRR_0_OPCODE_X1 = 27,
-  MZ_RRR_4_OPCODE_Y0 = 3,
-  MZ_RRR_4_OPCODE_Y1 = 3,
-  NAP_UNARY_OPCODE_X1 = 32,
-  NOP_UNARY_OPCODE_X0 = 5,
-  NOP_UNARY_OPCODE_X1 = 33,
-  NOP_UNARY_OPCODE_Y0 = 5,
-  NOP_UNARY_OPCODE_Y1 = 15,
-  NOR_RRR_0_OPCODE_X0 = 64,
-  NOR_RRR_0_OPCODE_X1 = 28,
-  NOR_RRR_5_OPCODE_Y0 = 1,
-  NOR_RRR_5_OPCODE_Y1 = 1,
-  ORI_IMM8_OPCODE_X0 = 7,
-  ORI_IMM8_OPCODE_X1 = 24,
-  OR_RRR_0_OPCODE_X0 = 65,
-  OR_RRR_0_OPCODE_X1 = 29,
-  OR_RRR_5_OPCODE_Y0 = 2,
-  OR_RRR_5_OPCODE_Y1 = 2,
-  PCNT_UNARY_OPCODE_X0 = 6,
-  PCNT_UNARY_OPCODE_Y0 = 6,
-  REVBITS_UNARY_OPCODE_X0 = 7,
-  REVBITS_UNARY_OPCODE_Y0 = 7,
-  REVBYTES_UNARY_OPCODE_X0 = 8,
-  REVBYTES_UNARY_OPCODE_Y0 = 8,
-  ROTLI_SHIFT_OPCODE_X0 = 1,
-  ROTLI_SHIFT_OPCODE_X1 = 1,
-  ROTLI_SHIFT_OPCODE_Y0 = 0,
-  ROTLI_SHIFT_OPCODE_Y1 = 0,
-  ROTL_RRR_0_OPCODE_X0 = 66,
-  ROTL_RRR_0_OPCODE_X1 = 30,
-  ROTL_RRR_6_OPCODE_Y0 = 0,
-  ROTL_RRR_6_OPCODE_Y1 = 0,
-  RRR_0_OPCODE_X0 = 5,
-  RRR_0_OPCODE_X1 = 5,
-  RRR_0_OPCODE_Y0 = 5,
-  RRR_0_OPCODE_Y1 = 6,
-  RRR_1_OPCODE_Y0 = 6,
-  RRR_1_OPCODE_Y1 = 7,
-  RRR_2_OPCODE_Y0 = 7,
-  RRR_2_OPCODE_Y1 = 8,
-  RRR_3_OPCODE_Y0 = 8,
-  RRR_3_OPCODE_Y1 = 9,
-  RRR_4_OPCODE_Y0 = 9,
-  RRR_4_OPCODE_Y1 = 10,
-  RRR_5_OPCODE_Y0 = 10,
-  RRR_5_OPCODE_Y1 = 11,
-  RRR_6_OPCODE_Y0 = 11,
-  RRR_6_OPCODE_Y1 = 12,
-  RRR_7_OPCODE_Y0 = 12,
-  RRR_7_OPCODE_Y1 = 13,
-  RRR_8_OPCODE_Y0 = 13,
-  RRR_9_OPCODE_Y0 = 14,
-  SHIFT_OPCODE_X0 = 6,
-  SHIFT_OPCODE_X1 = 6,
-  SHIFT_OPCODE_Y0 = 15,
-  SHIFT_OPCODE_Y1 = 14,
-  SHL16INSLI_OPCODE_X0 = 7,
-  SHL16INSLI_OPCODE_X1 = 7,
-  SHL1ADDX_RRR_0_OPCODE_X0 = 67,
-  SHL1ADDX_RRR_0_OPCODE_X1 = 31,
-  SHL1ADDX_RRR_7_OPCODE_Y0 = 1,
-  SHL1ADDX_RRR_7_OPCODE_Y1 = 1,
-  SHL1ADD_RRR_0_OPCODE_X0 = 68,
-  SHL1ADD_RRR_0_OPCODE_X1 = 32,
-  SHL1ADD_RRR_1_OPCODE_Y0 = 0,
-  SHL1ADD_RRR_1_OPCODE_Y1 = 0,
-  SHL2ADDX_RRR_0_OPCODE_X0 = 69,
-  SHL2ADDX_RRR_0_OPCODE_X1 = 33,
-  SHL2ADDX_RRR_7_OPCODE_Y0 = 2,
-  SHL2ADDX_RRR_7_OPCODE_Y1 = 2,
-  SHL2ADD_RRR_0_OPCODE_X0 = 70,
-  SHL2ADD_RRR_0_OPCODE_X1 = 34,
-  SHL2ADD_RRR_1_OPCODE_Y0 = 1,
-  SHL2ADD_RRR_1_OPCODE_Y1 = 1,
-  SHL3ADDX_RRR_0_OPCODE_X0 = 71,
-  SHL3ADDX_RRR_0_OPCODE_X1 = 35,
-  SHL3ADDX_RRR_7_OPCODE_Y0 = 3,
-  SHL3ADDX_RRR_7_OPCODE_Y1 = 3,
-  SHL3ADD_RRR_0_OPCODE_X0 = 72,
-  SHL3ADD_RRR_0_OPCODE_X1 = 36,
-  SHL3ADD_RRR_1_OPCODE_Y0 = 2,
-  SHL3ADD_RRR_1_OPCODE_Y1 = 2,
-  SHLI_SHIFT_OPCODE_X0 = 2,
-  SHLI_SHIFT_OPCODE_X1 = 2,
-  SHLI_SHIFT_OPCODE_Y0 = 1,
-  SHLI_SHIFT_OPCODE_Y1 = 1,
-  SHLXI_SHIFT_OPCODE_X0 = 3,
-  SHLXI_SHIFT_OPCODE_X1 = 3,
-  SHLX_RRR_0_OPCODE_X0 = 73,
-  SHLX_RRR_0_OPCODE_X1 = 37,
-  SHL_RRR_0_OPCODE_X0 = 74,
-  SHL_RRR_0_OPCODE_X1 = 38,
-  SHL_RRR_6_OPCODE_Y0 = 1,
-  SHL_RRR_6_OPCODE_Y1 = 1,
-  SHRSI_SHIFT_OPCODE_X0 = 4,
-  SHRSI_SHIFT_OPCODE_X1 = 4,
-  SHRSI_SHIFT_OPCODE_Y0 = 2,
-  SHRSI_SHIFT_OPCODE_Y1 = 2,
-  SHRS_RRR_0_OPCODE_X0 = 75,
-  SHRS_RRR_0_OPCODE_X1 = 39,
-  SHRS_RRR_6_OPCODE_Y0 = 2,
-  SHRS_RRR_6_OPCODE_Y1 = 2,
-  SHRUI_SHIFT_OPCODE_X0 = 5,
-  SHRUI_SHIFT_OPCODE_X1 = 5,
-  SHRUI_SHIFT_OPCODE_Y0 = 3,
-  SHRUI_SHIFT_OPCODE_Y1 = 3,
-  SHRUXI_SHIFT_OPCODE_X0 = 6,
-  SHRUXI_SHIFT_OPCODE_X1 = 6,
-  SHRUX_RRR_0_OPCODE_X0 = 76,
-  SHRUX_RRR_0_OPCODE_X1 = 40,
-  SHRU_RRR_0_OPCODE_X0 = 77,
-  SHRU_RRR_0_OPCODE_X1 = 41,
-  SHRU_RRR_6_OPCODE_Y0 = 3,
-  SHRU_RRR_6_OPCODE_Y1 = 3,
-  SHUFFLEBYTES_RRR_0_OPCODE_X0 = 78,
-  ST1_ADD_IMM8_OPCODE_X1 = 25,
-  ST1_OPCODE_Y2 = 0,
-  ST1_RRR_0_OPCODE_X1 = 42,
-  ST2_ADD_IMM8_OPCODE_X1 = 26,
-  ST2_OPCODE_Y2 = 1,
-  ST2_RRR_0_OPCODE_X1 = 43,
-  ST4_ADD_IMM8_OPCODE_X1 = 27,
-  ST4_OPCODE_Y2 = 2,
-  ST4_RRR_0_OPCODE_X1 = 44,
-  STNT1_ADD_IMM8_OPCODE_X1 = 28,
-  STNT1_RRR_0_OPCODE_X1 = 45,
-  STNT2_ADD_IMM8_OPCODE_X1 = 29,
-  STNT2_RRR_0_OPCODE_X1 = 46,
-  STNT4_ADD_IMM8_OPCODE_X1 = 30,
-  STNT4_RRR_0_OPCODE_X1 = 47,
-  STNT_ADD_IMM8_OPCODE_X1 = 31,
-  STNT_RRR_0_OPCODE_X1 = 48,
-  ST_ADD_IMM8_OPCODE_X1 = 32,
-  ST_OPCODE_Y2 = 3,
-  ST_RRR_0_OPCODE_X1 = 49,
-  SUBXSC_RRR_0_OPCODE_X0 = 79,
-  SUBXSC_RRR_0_OPCODE_X1 = 50,
-  SUBX_RRR_0_OPCODE_X0 = 80,
-  SUBX_RRR_0_OPCODE_X1 = 51,
-  SUBX_RRR_0_OPCODE_Y0 = 2,
-  SUBX_RRR_0_OPCODE_Y1 = 2,
-  SUB_RRR_0_OPCODE_X0 = 81,
-  SUB_RRR_0_OPCODE_X1 = 52,
-  SUB_RRR_0_OPCODE_Y0 = 3,
-  SUB_RRR_0_OPCODE_Y1 = 3,
-  SWINT0_UNARY_OPCODE_X1 = 34,
-  SWINT1_UNARY_OPCODE_X1 = 35,
-  SWINT2_UNARY_OPCODE_X1 = 36,
-  SWINT3_UNARY_OPCODE_X1 = 37,
-  TBLIDXB0_UNARY_OPCODE_X0 = 9,
-  TBLIDXB0_UNARY_OPCODE_Y0 = 9,
-  TBLIDXB1_UNARY_OPCODE_X0 = 10,
-  TBLIDXB1_UNARY_OPCODE_Y0 = 10,
-  TBLIDXB2_UNARY_OPCODE_X0 = 11,
-  TBLIDXB2_UNARY_OPCODE_Y0 = 11,
-  TBLIDXB3_UNARY_OPCODE_X0 = 12,
-  TBLIDXB3_UNARY_OPCODE_Y0 = 12,
-  UNARY_RRR_0_OPCODE_X0 = 82,
-  UNARY_RRR_0_OPCODE_X1 = 53,
-  UNARY_RRR_1_OPCODE_Y0 = 3,
-  UNARY_RRR_1_OPCODE_Y1 = 3,
-  V1ADDI_IMM8_OPCODE_X0 = 8,
-  V1ADDI_IMM8_OPCODE_X1 = 33,
-  V1ADDUC_RRR_0_OPCODE_X0 = 83,
-  V1ADDUC_RRR_0_OPCODE_X1 = 54,
-  V1ADD_RRR_0_OPCODE_X0 = 84,
-  V1ADD_RRR_0_OPCODE_X1 = 55,
-  V1ADIFFU_RRR_0_OPCODE_X0 = 85,
-  V1AVGU_RRR_0_OPCODE_X0 = 86,
-  V1CMPEQI_IMM8_OPCODE_X0 = 9,
-  V1CMPEQI_IMM8_OPCODE_X1 = 34,
-  V1CMPEQ_RRR_0_OPCODE_X0 = 87,
-  V1CMPEQ_RRR_0_OPCODE_X1 = 56,
-  V1CMPLES_RRR_0_OPCODE_X0 = 88,
-  V1CMPLES_RRR_0_OPCODE_X1 = 57,
-  V1CMPLEU_RRR_0_OPCODE_X0 = 89,
-  V1CMPLEU_RRR_0_OPCODE_X1 = 58,
-  V1CMPLTSI_IMM8_OPCODE_X0 = 10,
-  V1CMPLTSI_IMM8_OPCODE_X1 = 35,
-  V1CMPLTS_RRR_0_OPCODE_X0 = 90,
-  V1CMPLTS_RRR_0_OPCODE_X1 = 59,
-  V1CMPLTUI_IMM8_OPCODE_X0 = 11,
-  V1CMPLTUI_IMM8_OPCODE_X1 = 36,
-  V1CMPLTU_RRR_0_OPCODE_X0 = 91,
-  V1CMPLTU_RRR_0_OPCODE_X1 = 60,
-  V1CMPNE_RRR_0_OPCODE_X0 = 92,
-  V1CMPNE_RRR_0_OPCODE_X1 = 61,
-  V1DDOTPUA_RRR_0_OPCODE_X0 = 161,
-  V1DDOTPUSA_RRR_0_OPCODE_X0 = 93,
-  V1DDOTPUS_RRR_0_OPCODE_X0 = 94,
-  V1DDOTPU_RRR_0_OPCODE_X0 = 162,
-  V1DOTPA_RRR_0_OPCODE_X0 = 95,
-  V1DOTPUA_RRR_0_OPCODE_X0 = 163,
-  V1DOTPUSA_RRR_0_OPCODE_X0 = 96,
-  V1DOTPUS_RRR_0_OPCODE_X0 = 97,
-  V1DOTPU_RRR_0_OPCODE_X0 = 164,
-  V1DOTP_RRR_0_OPCODE_X0 = 98,
-  V1INT_H_RRR_0_OPCODE_X0 = 99,
-  V1INT_H_RRR_0_OPCODE_X1 = 62,
-  V1INT_L_RRR_0_OPCODE_X0 = 100,
-  V1INT_L_RRR_0_OPCODE_X1 = 63,
-  V1MAXUI_IMM8_OPCODE_X0 = 12,
-  V1MAXUI_IMM8_OPCODE_X1 = 37,
-  V1MAXU_RRR_0_OPCODE_X0 = 101,
-  V1MAXU_RRR_0_OPCODE_X1 = 64,
-  V1MINUI_IMM8_OPCODE_X0 = 13,
-  V1MINUI_IMM8_OPCODE_X1 = 38,
-  V1MINU_RRR_0_OPCODE_X0 = 102,
-  V1MINU_RRR_0_OPCODE_X1 = 65,
-  V1MNZ_RRR_0_OPCODE_X0 = 103,
-  V1MNZ_RRR_0_OPCODE_X1 = 66,
-  V1MULTU_RRR_0_OPCODE_X0 = 104,
-  V1MULUS_RRR_0_OPCODE_X0 = 105,
-  V1MULU_RRR_0_OPCODE_X0 = 106,
-  V1MZ_RRR_0_OPCODE_X0 = 107,
-  V1MZ_RRR_0_OPCODE_X1 = 67,
-  V1SADAU_RRR_0_OPCODE_X0 = 108,
-  V1SADU_RRR_0_OPCODE_X0 = 109,
-  V1SHLI_SHIFT_OPCODE_X0 = 7,
-  V1SHLI_SHIFT_OPCODE_X1 = 7,
-  V1SHL_RRR_0_OPCODE_X0 = 110,
-  V1SHL_RRR_0_OPCODE_X1 = 68,
-  V1SHRSI_SHIFT_OPCODE_X0 = 8,
-  V1SHRSI_SHIFT_OPCODE_X1 = 8,
-  V1SHRS_RRR_0_OPCODE_X0 = 111,
-  V1SHRS_RRR_0_OPCODE_X1 = 69,
-  V1SHRUI_SHIFT_OPCODE_X0 = 9,
-  V1SHRUI_SHIFT_OPCODE_X1 = 9,
-  V1SHRU_RRR_0_OPCODE_X0 = 112,
-  V1SHRU_RRR_0_OPCODE_X1 = 70,
-  V1SUBUC_RRR_0_OPCODE_X0 = 113,
-  V1SUBUC_RRR_0_OPCODE_X1 = 71,
-  V1SUB_RRR_0_OPCODE_X0 = 114,
-  V1SUB_RRR_0_OPCODE_X1 = 72,
-  V2ADDI_IMM8_OPCODE_X0 = 14,
-  V2ADDI_IMM8_OPCODE_X1 = 39,
-  V2ADDSC_RRR_0_OPCODE_X0 = 115,
-  V2ADDSC_RRR_0_OPCODE_X1 = 73,
-  V2ADD_RRR_0_OPCODE_X0 = 116,
-  V2ADD_RRR_0_OPCODE_X1 = 74,
-  V2ADIFFS_RRR_0_OPCODE_X0 = 117,
-  V2AVGS_RRR_0_OPCODE_X0 = 118,
-  V2CMPEQI_IMM8_OPCODE_X0 = 15,
-  V2CMPEQI_IMM8_OPCODE_X1 = 40,
-  V2CMPEQ_RRR_0_OPCODE_X0 = 119,
-  V2CMPEQ_RRR_0_OPCODE_X1 = 75,
-  V2CMPLES_RRR_0_OPCODE_X0 = 120,
-  V2CMPLES_RRR_0_OPCODE_X1 = 76,
-  V2CMPLEU_RRR_0_OPCODE_X0 = 121,
-  V2CMPLEU_RRR_0_OPCODE_X1 = 77,
-  V2CMPLTSI_IMM8_OPCODE_X0 = 16,
-  V2CMPLTSI_IMM8_OPCODE_X1 = 41,
-  V2CMPLTS_RRR_0_OPCODE_X0 = 122,
-  V2CMPLTS_RRR_0_OPCODE_X1 = 78,
-  V2CMPLTUI_IMM8_OPCODE_X0 = 17,
-  V2CMPLTUI_IMM8_OPCODE_X1 = 42,
-  V2CMPLTU_RRR_0_OPCODE_X0 = 123,
-  V2CMPLTU_RRR_0_OPCODE_X1 = 79,
-  V2CMPNE_RRR_0_OPCODE_X0 = 124,
-  V2CMPNE_RRR_0_OPCODE_X1 = 80,
-  V2DOTPA_RRR_0_OPCODE_X0 = 125,
-  V2DOTP_RRR_0_OPCODE_X0 = 126,
-  V2INT_H_RRR_0_OPCODE_X0 = 127,
-  V2INT_H_RRR_0_OPCODE_X1 = 81,
-  V2INT_L_RRR_0_OPCODE_X0 = 128,
-  V2INT_L_RRR_0_OPCODE_X1 = 82,
-  V2MAXSI_IMM8_OPCODE_X0 = 18,
-  V2MAXSI_IMM8_OPCODE_X1 = 43,
-  V2MAXS_RRR_0_OPCODE_X0 = 129,
-  V2MAXS_RRR_0_OPCODE_X1 = 83,
-  V2MINSI_IMM8_OPCODE_X0 = 19,
-  V2MINSI_IMM8_OPCODE_X1 = 44,
-  V2MINS_RRR_0_OPCODE_X0 = 130,
-  V2MINS_RRR_0_OPCODE_X1 = 84,
-  V2MNZ_RRR_0_OPCODE_X0 = 131,
-  V2MNZ_RRR_0_OPCODE_X1 = 85,
-  V2MULFSC_RRR_0_OPCODE_X0 = 132,
-  V2MULS_RRR_0_OPCODE_X0 = 133,
-  V2MULTS_RRR_0_OPCODE_X0 = 134,
-  V2MZ_RRR_0_OPCODE_X0 = 135,
-  V2MZ_RRR_0_OPCODE_X1 = 86,
-  V2PACKH_RRR_0_OPCODE_X0 = 136,
-  V2PACKH_RRR_0_OPCODE_X1 = 87,
-  V2PACKL_RRR_0_OPCODE_X0 = 137,
-  V2PACKL_RRR_0_OPCODE_X1 = 88,
-  V2PACKUC_RRR_0_OPCODE_X0 = 138,
-  V2PACKUC_RRR_0_OPCODE_X1 = 89,
-  V2SADAS_RRR_0_OPCODE_X0 = 139,
-  V2SADAU_RRR_0_OPCODE_X0 = 140,
-  V2SADS_RRR_0_OPCODE_X0 = 141,
-  V2SADU_RRR_0_OPCODE_X0 = 142,
-  V2SHLI_SHIFT_OPCODE_X0 = 10,
-  V2SHLI_SHIFT_OPCODE_X1 = 10,
-  V2SHLSC_RRR_0_OPCODE_X0 = 143,
-  V2SHLSC_RRR_0_OPCODE_X1 = 90,
-  V2SHL_RRR_0_OPCODE_X0 = 144,
-  V2SHL_RRR_0_OPCODE_X1 = 91,
-  V2SHRSI_SHIFT_OPCODE_X0 = 11,
-  V2SHRSI_SHIFT_OPCODE_X1 = 11,
-  V2SHRS_RRR_0_OPCODE_X0 = 145,
-  V2SHRS_RRR_0_OPCODE_X1 = 92,
-  V2SHRUI_SHIFT_OPCODE_X0 = 12,
-  V2SHRUI_SHIFT_OPCODE_X1 = 12,
-  V2SHRU_RRR_0_OPCODE_X0 = 146,
-  V2SHRU_RRR_0_OPCODE_X1 = 93,
-  V2SUBSC_RRR_0_OPCODE_X0 = 147,
-  V2SUBSC_RRR_0_OPCODE_X1 = 94,
-  V2SUB_RRR_0_OPCODE_X0 = 148,
-  V2SUB_RRR_0_OPCODE_X1 = 95,
-  V4ADDSC_RRR_0_OPCODE_X0 = 149,
-  V4ADDSC_RRR_0_OPCODE_X1 = 96,
-  V4ADD_RRR_0_OPCODE_X0 = 150,
-  V4ADD_RRR_0_OPCODE_X1 = 97,
-  V4INT_H_RRR_0_OPCODE_X0 = 151,
-  V4INT_H_RRR_0_OPCODE_X1 = 98,
-  V4INT_L_RRR_0_OPCODE_X0 = 152,
-  V4INT_L_RRR_0_OPCODE_X1 = 99,
-  V4PACKSC_RRR_0_OPCODE_X0 = 153,
-  V4PACKSC_RRR_0_OPCODE_X1 = 100,
-  V4SHLSC_RRR_0_OPCODE_X0 = 154,
-  V4SHLSC_RRR_0_OPCODE_X1 = 101,
-  V4SHL_RRR_0_OPCODE_X0 = 155,
-  V4SHL_RRR_0_OPCODE_X1 = 102,
-  V4SHRS_RRR_0_OPCODE_X0 = 156,
-  V4SHRS_RRR_0_OPCODE_X1 = 103,
-  V4SHRU_RRR_0_OPCODE_X0 = 157,
-  V4SHRU_RRR_0_OPCODE_X1 = 104,
-  V4SUBSC_RRR_0_OPCODE_X0 = 158,
-  V4SUBSC_RRR_0_OPCODE_X1 = 105,
-  V4SUB_RRR_0_OPCODE_X0 = 159,
-  V4SUB_RRR_0_OPCODE_X1 = 106,
-  WH64_UNARY_OPCODE_X1 = 38,
-  XORI_IMM8_OPCODE_X0 = 20,
-  XORI_IMM8_OPCODE_X1 = 45,
-  XOR_RRR_0_OPCODE_X0 = 160,
-  XOR_RRR_0_OPCODE_X1 = 107,
-  XOR_RRR_5_OPCODE_Y0 = 3,
-  XOR_RRR_5_OPCODE_Y1 = 3
-};
-
-#endif /* !_TILE_OPCODE_CONSTANTS_H */
diff -druN linux-libre-3.1-gnu/arch/tile/include/asm/opcode_constants.h linux-libre-3.2-gnu/arch/tile/include/asm/opcode_constants.h
--- linux-libre-3.1-gnu/arch/tile/include/asm/opcode_constants.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/include/asm/opcode_constants.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +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.
- */
-
-#ifndef _ASM_TILE_OPCODE_CONSTANTS_H
-#define _ASM_TILE_OPCODE_CONSTANTS_H
-
-#include <arch/chip.h>
-
-#if CHIP_WORD_SIZE() == 64
-#include <asm/opcode_constants_64.h>
-#else
-#include <asm/opcode_constants_32.h>
-#endif
-
-#endif /* _ASM_TILE_OPCODE_CONSTANTS_H */
diff -druN linux-libre-3.1-gnu/arch/tile/include/asm/opcode-tile_32.h linux-libre-3.2-gnu/arch/tile/include/asm/opcode-tile_32.h
--- linux-libre-3.1-gnu/arch/tile/include/asm/opcode-tile_32.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/include/asm/opcode-tile_32.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1513 +0,0 @@
-/* tile.h -- Header file for TILE opcode table
-   Copyright (C) 2005 Free Software Foundation, Inc.
-   Contributed by Tilera Corp. */
-
-#ifndef opcode_tile_h
-#define opcode_tile_h
-
-typedef unsigned long long tile_bundle_bits;
-
-
-enum
-{
-  TILE_MAX_OPERANDS = 5 /* mm */
-};
-
-typedef enum
-{
-  TILE_OPC_BPT,
-  TILE_OPC_INFO,
-  TILE_OPC_INFOL,
-  TILE_OPC_J,
-  TILE_OPC_JAL,
-  TILE_OPC_MOVE,
-  TILE_OPC_MOVE_SN,
-  TILE_OPC_MOVEI,
-  TILE_OPC_MOVEI_SN,
-  TILE_OPC_MOVELI,
-  TILE_OPC_MOVELI_SN,
-  TILE_OPC_MOVELIS,
-  TILE_OPC_PREFETCH,
-  TILE_OPC_RAISE,
-  TILE_OPC_ADD,
-  TILE_OPC_ADD_SN,
-  TILE_OPC_ADDB,
-  TILE_OPC_ADDB_SN,
-  TILE_OPC_ADDBS_U,
-  TILE_OPC_ADDBS_U_SN,
-  TILE_OPC_ADDH,
-  TILE_OPC_ADDH_SN,
-  TILE_OPC_ADDHS,
-  TILE_OPC_ADDHS_SN,
-  TILE_OPC_ADDI,
-  TILE_OPC_ADDI_SN,
-  TILE_OPC_ADDIB,
-  TILE_OPC_ADDIB_SN,
-  TILE_OPC_ADDIH,
-  TILE_OPC_ADDIH_SN,
-  TILE_OPC_ADDLI,
-  TILE_OPC_ADDLI_SN,
-  TILE_OPC_ADDLIS,
-  TILE_OPC_ADDS,
-  TILE_OPC_ADDS_SN,
-  TILE_OPC_ADIFFB_U,
-  TILE_OPC_ADIFFB_U_SN,
-  TILE_OPC_ADIFFH,
-  TILE_OPC_ADIFFH_SN,
-  TILE_OPC_AND,
-  TILE_OPC_AND_SN,
-  TILE_OPC_ANDI,
-  TILE_OPC_ANDI_SN,
-  TILE_OPC_AULI,
-  TILE_OPC_AVGB_U,
-  TILE_OPC_AVGB_U_SN,
-  TILE_OPC_AVGH,
-  TILE_OPC_AVGH_SN,
-  TILE_OPC_BBNS,
-  TILE_OPC_BBNS_SN,
-  TILE_OPC_BBNST,
-  TILE_OPC_BBNST_SN,
-  TILE_OPC_BBS,
-  TILE_OPC_BBS_SN,
-  TILE_OPC_BBST,
-  TILE_OPC_BBST_SN,
-  TILE_OPC_BGEZ,
-  TILE_OPC_BGEZ_SN,
-  TILE_OPC_BGEZT,
-  TILE_OPC_BGEZT_SN,
-  TILE_OPC_BGZ,
-  TILE_OPC_BGZ_SN,
-  TILE_OPC_BGZT,
-  TILE_OPC_BGZT_SN,
-  TILE_OPC_BITX,
-  TILE_OPC_BITX_SN,
-  TILE_OPC_BLEZ,
-  TILE_OPC_BLEZ_SN,
-  TILE_OPC_BLEZT,
-  TILE_OPC_BLEZT_SN,
-  TILE_OPC_BLZ,
-  TILE_OPC_BLZ_SN,
-  TILE_OPC_BLZT,
-  TILE_OPC_BLZT_SN,
-  TILE_OPC_BNZ,
-  TILE_OPC_BNZ_SN,
-  TILE_OPC_BNZT,
-  TILE_OPC_BNZT_SN,
-  TILE_OPC_BYTEX,
-  TILE_OPC_BYTEX_SN,
-  TILE_OPC_BZ,
-  TILE_OPC_BZ_SN,
-  TILE_OPC_BZT,
-  TILE_OPC_BZT_SN,
-  TILE_OPC_CLZ,
-  TILE_OPC_CLZ_SN,
-  TILE_OPC_CRC32_32,
-  TILE_OPC_CRC32_32_SN,
-  TILE_OPC_CRC32_8,
-  TILE_OPC_CRC32_8_SN,
-  TILE_OPC_CTZ,
-  TILE_OPC_CTZ_SN,
-  TILE_OPC_DRAIN,
-  TILE_OPC_DTLBPR,
-  TILE_OPC_DWORD_ALIGN,
-  TILE_OPC_DWORD_ALIGN_SN,
-  TILE_OPC_FINV,
-  TILE_OPC_FLUSH,
-  TILE_OPC_FNOP,
-  TILE_OPC_ICOH,
-  TILE_OPC_ILL,
-  TILE_OPC_INTHB,
-  TILE_OPC_INTHB_SN,
-  TILE_OPC_INTHH,
-  TILE_OPC_INTHH_SN,
-  TILE_OPC_INTLB,
-  TILE_OPC_INTLB_SN,
-  TILE_OPC_INTLH,
-  TILE_OPC_INTLH_SN,
-  TILE_OPC_INV,
-  TILE_OPC_IRET,
-  TILE_OPC_JALB,
-  TILE_OPC_JALF,
-  TILE_OPC_JALR,
-  TILE_OPC_JALRP,
-  TILE_OPC_JB,
-  TILE_OPC_JF,
-  TILE_OPC_JR,
-  TILE_OPC_JRP,
-  TILE_OPC_LB,
-  TILE_OPC_LB_SN,
-  TILE_OPC_LB_U,
-  TILE_OPC_LB_U_SN,
-  TILE_OPC_LBADD,
-  TILE_OPC_LBADD_SN,
-  TILE_OPC_LBADD_U,
-  TILE_OPC_LBADD_U_SN,
-  TILE_OPC_LH,
-  TILE_OPC_LH_SN,
-  TILE_OPC_LH_U,
-  TILE_OPC_LH_U_SN,
-  TILE_OPC_LHADD,
-  TILE_OPC_LHADD_SN,
-  TILE_OPC_LHADD_U,
-  TILE_OPC_LHADD_U_SN,
-  TILE_OPC_LNK,
-  TILE_OPC_LNK_SN,
-  TILE_OPC_LW,
-  TILE_OPC_LW_SN,
-  TILE_OPC_LW_NA,
-  TILE_OPC_LW_NA_SN,
-  TILE_OPC_LWADD,
-  TILE_OPC_LWADD_SN,
-  TILE_OPC_LWADD_NA,
-  TILE_OPC_LWADD_NA_SN,
-  TILE_OPC_MAXB_U,
-  TILE_OPC_MAXB_U_SN,
-  TILE_OPC_MAXH,
-  TILE_OPC_MAXH_SN,
-  TILE_OPC_MAXIB_U,
-  TILE_OPC_MAXIB_U_SN,
-  TILE_OPC_MAXIH,
-  TILE_OPC_MAXIH_SN,
-  TILE_OPC_MF,
-  TILE_OPC_MFSPR,
-  TILE_OPC_MINB_U,
-  TILE_OPC_MINB_U_SN,
-  TILE_OPC_MINH,
-  TILE_OPC_MINH_SN,
-  TILE_OPC_MINIB_U,
-  TILE_OPC_MINIB_U_SN,
-  TILE_OPC_MINIH,
-  TILE_OPC_MINIH_SN,
-  TILE_OPC_MM,
-  TILE_OPC_MNZ,
-  TILE_OPC_MNZ_SN,
-  TILE_OPC_MNZB,
-  TILE_OPC_MNZB_SN,
-  TILE_OPC_MNZH,
-  TILE_OPC_MNZH_SN,
-  TILE_OPC_MTSPR,
-  TILE_OPC_MULHH_SS,
-  TILE_OPC_MULHH_SS_SN,
-  TILE_OPC_MULHH_SU,
-  TILE_OPC_MULHH_SU_SN,
-  TILE_OPC_MULHH_UU,
-  TILE_OPC_MULHH_UU_SN,
-  TILE_OPC_MULHHA_SS,
-  TILE_OPC_MULHHA_SS_SN,
-  TILE_OPC_MULHHA_SU,
-  TILE_OPC_MULHHA_SU_SN,
-  TILE_OPC_MULHHA_UU,
-  TILE_OPC_MULHHA_UU_SN,
-  TILE_OPC_MULHHSA_UU,
-  TILE_OPC_MULHHSA_UU_SN,
-  TILE_OPC_MULHL_SS,
-  TILE_OPC_MULHL_SS_SN,
-  TILE_OPC_MULHL_SU,
-  TILE_OPC_MULHL_SU_SN,
-  TILE_OPC_MULHL_US,
-  TILE_OPC_MULHL_US_SN,
-  TILE_OPC_MULHL_UU,
-  TILE_OPC_MULHL_UU_SN,
-  TILE_OPC_MULHLA_SS,
-  TILE_OPC_MULHLA_SS_SN,
-  TILE_OPC_MULHLA_SU,
-  TILE_OPC_MULHLA_SU_SN,
-  TILE_OPC_MULHLA_US,
-  TILE_OPC_MULHLA_US_SN,
-  TILE_OPC_MULHLA_UU,
-  TILE_OPC_MULHLA_UU_SN,
-  TILE_OPC_MULHLSA_UU,
-  TILE_OPC_MULHLSA_UU_SN,
-  TILE_OPC_MULLL_SS,
-  TILE_OPC_MULLL_SS_SN,
-  TILE_OPC_MULLL_SU,
-  TILE_OPC_MULLL_SU_SN,
-  TILE_OPC_MULLL_UU,
-  TILE_OPC_MULLL_UU_SN,
-  TILE_OPC_MULLLA_SS,
-  TILE_OPC_MULLLA_SS_SN,
-  TILE_OPC_MULLLA_SU,
-  TILE_OPC_MULLLA_SU_SN,
-  TILE_OPC_MULLLA_UU,
-  TILE_OPC_MULLLA_UU_SN,
-  TILE_OPC_MULLLSA_UU,
-  TILE_OPC_MULLLSA_UU_SN,
-  TILE_OPC_MVNZ,
-  TILE_OPC_MVNZ_SN,
-  TILE_OPC_MVZ,
-  TILE_OPC_MVZ_SN,
-  TILE_OPC_MZ,
-  TILE_OPC_MZ_SN,
-  TILE_OPC_MZB,
-  TILE_OPC_MZB_SN,
-  TILE_OPC_MZH,
-  TILE_OPC_MZH_SN,
-  TILE_OPC_NAP,
-  TILE_OPC_NOP,
-  TILE_OPC_NOR,
-  TILE_OPC_NOR_SN,
-  TILE_OPC_OR,
-  TILE_OPC_OR_SN,
-  TILE_OPC_ORI,
-  TILE_OPC_ORI_SN,
-  TILE_OPC_PACKBS_U,
-  TILE_OPC_PACKBS_U_SN,
-  TILE_OPC_PACKHB,
-  TILE_OPC_PACKHB_SN,
-  TILE_OPC_PACKHS,
-  TILE_OPC_PACKHS_SN,
-  TILE_OPC_PACKLB,
-  TILE_OPC_PACKLB_SN,
-  TILE_OPC_PCNT,
-  TILE_OPC_PCNT_SN,
-  TILE_OPC_RL,
-  TILE_OPC_RL_SN,
-  TILE_OPC_RLI,
-  TILE_OPC_RLI_SN,
-  TILE_OPC_S1A,
-  TILE_OPC_S1A_SN,
-  TILE_OPC_S2A,
-  TILE_OPC_S2A_SN,
-  TILE_OPC_S3A,
-  TILE_OPC_S3A_SN,
-  TILE_OPC_SADAB_U,
-  TILE_OPC_SADAB_U_SN,
-  TILE_OPC_SADAH,
-  TILE_OPC_SADAH_SN,
-  TILE_OPC_SADAH_U,
-  TILE_OPC_SADAH_U_SN,
-  TILE_OPC_SADB_U,
-  TILE_OPC_SADB_U_SN,
-  TILE_OPC_SADH,
-  TILE_OPC_SADH_SN,
-  TILE_OPC_SADH_U,
-  TILE_OPC_SADH_U_SN,
-  TILE_OPC_SB,
-  TILE_OPC_SBADD,
-  TILE_OPC_SEQ,
-  TILE_OPC_SEQ_SN,
-  TILE_OPC_SEQB,
-  TILE_OPC_SEQB_SN,
-  TILE_OPC_SEQH,
-  TILE_OPC_SEQH_SN,
-  TILE_OPC_SEQI,
-  TILE_OPC_SEQI_SN,
-  TILE_OPC_SEQIB,
-  TILE_OPC_SEQIB_SN,
-  TILE_OPC_SEQIH,
-  TILE_OPC_SEQIH_SN,
-  TILE_OPC_SH,
-  TILE_OPC_SHADD,
-  TILE_OPC_SHL,
-  TILE_OPC_SHL_SN,
-  TILE_OPC_SHLB,
-  TILE_OPC_SHLB_SN,
-  TILE_OPC_SHLH,
-  TILE_OPC_SHLH_SN,
-  TILE_OPC_SHLI,
-  TILE_OPC_SHLI_SN,
-  TILE_OPC_SHLIB,
-  TILE_OPC_SHLIB_SN,
-  TILE_OPC_SHLIH,
-  TILE_OPC_SHLIH_SN,
-  TILE_OPC_SHR,
-  TILE_OPC_SHR_SN,
-  TILE_OPC_SHRB,
-  TILE_OPC_SHRB_SN,
-  TILE_OPC_SHRH,
-  TILE_OPC_SHRH_SN,
-  TILE_OPC_SHRI,
-  TILE_OPC_SHRI_SN,
-  TILE_OPC_SHRIB,
-  TILE_OPC_SHRIB_SN,
-  TILE_OPC_SHRIH,
-  TILE_OPC_SHRIH_SN,
-  TILE_OPC_SLT,
-  TILE_OPC_SLT_SN,
-  TILE_OPC_SLT_U,
-  TILE_OPC_SLT_U_SN,
-  TILE_OPC_SLTB,
-  TILE_OPC_SLTB_SN,
-  TILE_OPC_SLTB_U,
-  TILE_OPC_SLTB_U_SN,
-  TILE_OPC_SLTE,
-  TILE_OPC_SLTE_SN,
-  TILE_OPC_SLTE_U,
-  TILE_OPC_SLTE_U_SN,
-  TILE_OPC_SLTEB,
-  TILE_OPC_SLTEB_SN,
-  TILE_OPC_SLTEB_U,
-  TILE_OPC_SLTEB_U_SN,
-  TILE_OPC_SLTEH,
-  TILE_OPC_SLTEH_SN,
-  TILE_OPC_SLTEH_U,
-  TILE_OPC_SLTEH_U_SN,
-  TILE_OPC_SLTH,
-  TILE_OPC_SLTH_SN,
-  TILE_OPC_SLTH_U,
-  TILE_OPC_SLTH_U_SN,
-  TILE_OPC_SLTI,
-  TILE_OPC_SLTI_SN,
-  TILE_OPC_SLTI_U,
-  TILE_OPC_SLTI_U_SN,
-  TILE_OPC_SLTIB,
-  TILE_OPC_SLTIB_SN,
-  TILE_OPC_SLTIB_U,
-  TILE_OPC_SLTIB_U_SN,
-  TILE_OPC_SLTIH,
-  TILE_OPC_SLTIH_SN,
-  TILE_OPC_SLTIH_U,
-  TILE_OPC_SLTIH_U_SN,
-  TILE_OPC_SNE,
-  TILE_OPC_SNE_SN,
-  TILE_OPC_SNEB,
-  TILE_OPC_SNEB_SN,
-  TILE_OPC_SNEH,
-  TILE_OPC_SNEH_SN,
-  TILE_OPC_SRA,
-  TILE_OPC_SRA_SN,
-  TILE_OPC_SRAB,
-  TILE_OPC_SRAB_SN,
-  TILE_OPC_SRAH,
-  TILE_OPC_SRAH_SN,
-  TILE_OPC_SRAI,
-  TILE_OPC_SRAI_SN,
-  TILE_OPC_SRAIB,
-  TILE_OPC_SRAIB_SN,
-  TILE_OPC_SRAIH,
-  TILE_OPC_SRAIH_SN,
-  TILE_OPC_SUB,
-  TILE_OPC_SUB_SN,
-  TILE_OPC_SUBB,
-  TILE_OPC_SUBB_SN,
-  TILE_OPC_SUBBS_U,
-  TILE_OPC_SUBBS_U_SN,
-  TILE_OPC_SUBH,
-  TILE_OPC_SUBH_SN,
-  TILE_OPC_SUBHS,
-  TILE_OPC_SUBHS_SN,
-  TILE_OPC_SUBS,
-  TILE_OPC_SUBS_SN,
-  TILE_OPC_SW,
-  TILE_OPC_SWADD,
-  TILE_OPC_SWINT0,
-  TILE_OPC_SWINT1,
-  TILE_OPC_SWINT2,
-  TILE_OPC_SWINT3,
-  TILE_OPC_TBLIDXB0,
-  TILE_OPC_TBLIDXB0_SN,
-  TILE_OPC_TBLIDXB1,
-  TILE_OPC_TBLIDXB1_SN,
-  TILE_OPC_TBLIDXB2,
-  TILE_OPC_TBLIDXB2_SN,
-  TILE_OPC_TBLIDXB3,
-  TILE_OPC_TBLIDXB3_SN,
-  TILE_OPC_TNS,
-  TILE_OPC_TNS_SN,
-  TILE_OPC_WH64,
-  TILE_OPC_XOR,
-  TILE_OPC_XOR_SN,
-  TILE_OPC_XORI,
-  TILE_OPC_XORI_SN,
-  TILE_OPC_NONE
-} tile_mnemonic;
-
-/* 64-bit pattern for a { bpt ; nop } bundle. */
-#define TILE_BPT_BUNDLE 0x400b3cae70166000ULL
-
-
-#define TILE_ELF_MACHINE_CODE EM_TILEPRO
-
-#define TILE_ELF_NAME "elf32-tilepro"
-
-
-static __inline unsigned int
-get_BrOff_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_BrOff_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x00007fff) |
-         (((unsigned int)(n >> 20)) & 0x00018000);
-}
-
-static __inline unsigned int
-get_BrType_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0xf);
-}
-
-static __inline unsigned int
-get_Dest_Imm8_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x0000003f) |
-         (((unsigned int)(n >> 43)) & 0x000000c0);
-}
-
-static __inline unsigned int
-get_Dest_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 2)) & 0x3);
-}
-
-static __inline unsigned int
-get_Dest_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Imm16_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xffff);
-}
-
-static __inline unsigned int
-get_Imm16_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xffff);
-}
-
-static __inline unsigned int
-get_Imm8_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xff);
-}
-
-static __inline unsigned int
-get_ImmOpcodeExtension_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 20)) & 0x7f);
-}
-
-static __inline unsigned int
-get_ImmOpcodeExtension_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 51)) & 0x7f);
-}
-
-static __inline unsigned int
-get_ImmRROpcodeExtension_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 8)) & 0x3);
-}
-
-static __inline unsigned int
-get_JOffLong_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x00007fff) |
-         (((unsigned int)(n >> 20)) & 0x00018000) |
-         (((unsigned int)(n >> 14)) & 0x001e0000) |
-         (((unsigned int)(n >> 16)) & 0x07e00000) |
-         (((unsigned int)(n >> 31)) & 0x18000000);
-}
-
-static __inline unsigned int
-get_JOff_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x00007fff) |
-         (((unsigned int)(n >> 20)) & 0x00018000) |
-         (((unsigned int)(n >> 14)) & 0x001e0000) |
-         (((unsigned int)(n >> 16)) & 0x07e00000) |
-         (((unsigned int)(n >> 31)) & 0x08000000);
-}
-
-static __inline unsigned int
-get_MF_Imm15_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x00003fff) |
-         (((unsigned int)(n >> 44)) & 0x00004000);
-}
-
-static __inline unsigned int
-get_MMEnd_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x1f);
-}
-
-static __inline unsigned int
-get_MMEnd_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x1f);
-}
-
-static __inline unsigned int
-get_MMStart_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 23)) & 0x1f);
-}
-
-static __inline unsigned int
-get_MMStart_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 54)) & 0x1f);
-}
-
-static __inline unsigned int
-get_MT_Imm15_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x0000003f) |
-         (((unsigned int)(n >> 37)) & 0x00003fc0) |
-         (((unsigned int)(n >> 44)) & 0x00004000);
-}
-
-static __inline unsigned int
-get_Mode(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 63)) & 0x1);
-}
-
-static __inline unsigned int
-get_NoRegOpcodeExtension_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 10)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Opcode_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 28)) & 0x7);
-}
-
-static __inline unsigned int
-get_Opcode_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 59)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 27)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 59)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_Y2(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 56)) & 0x7);
-}
-
-static __inline unsigned int
-get_RROpcodeExtension_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 4)) & 0xf);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x1ff);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x1ff);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x3);
-}
-
-static __inline unsigned int
-get_RouteOpcodeExtension_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_S_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 27)) & 0x1);
-}
-
-static __inline unsigned int
-get_S_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 58)) & 0x1);
-}
-
-static __inline unsigned int
-get_ShAmt_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x1f);
-}
-
-static __inline unsigned int
-get_ShAmt_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x1f);
-}
-
-static __inline unsigned int
-get_ShAmt_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x1f);
-}
-
-static __inline unsigned int
-get_ShAmt_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x1f);
-}
-
-static __inline unsigned int
-get_SrcA_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 6)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 6)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y2(tile_bundle_bits n)
-{
-  return (((n >> 26)) & 0x00000001) |
-         (((unsigned int)(n >> 50)) & 0x0000003e);
-}
-
-static __inline unsigned int
-get_SrcBDest_Y2(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 20)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Src_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3);
-}
-
-static __inline unsigned int
-get_UnOpcodeExtension_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x1f);
-}
-
-static __inline unsigned int
-get_UnOpcodeExtension_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x1f);
-}
-
-static __inline unsigned int
-get_UnOpcodeExtension_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x1f);
-}
-
-static __inline unsigned int
-get_UnOpcodeExtension_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x1f);
-}
-
-static __inline unsigned int
-get_UnShOpcodeExtension_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 17)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_UnShOpcodeExtension_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 48)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_UnShOpcodeExtension_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 17)) & 0x7);
-}
-
-static __inline unsigned int
-get_UnShOpcodeExtension_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 48)) & 0x7);
-}
-
-
-static __inline int
-sign_extend(int n, int num_bits)
-{
-  int shift = (int)(sizeof(int) * 8 - num_bits);
-  return (n << shift) >> shift;
-}
-
-
-
-static __inline tile_bundle_bits
-create_BrOff_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3ff) << 0);
-}
-
-static __inline tile_bundle_bits
-create_BrOff_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x00007fff)) << 43) |
-         (((tile_bundle_bits)(n & 0x00018000)) << 20);
-}
-
-static __inline tile_bundle_bits
-create_BrType_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xf)) << 31);
-}
-
-static __inline tile_bundle_bits
-create_Dest_Imm8_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x0000003f)) << 31) |
-         (((tile_bundle_bits)(n & 0x000000c0)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_Dest_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 2);
-}
-
-static __inline tile_bundle_bits
-create_Dest_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 0);
-}
-
-static __inline tile_bundle_bits
-create_Dest_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 31);
-}
-
-static __inline tile_bundle_bits
-create_Dest_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 0);
-}
-
-static __inline tile_bundle_bits
-create_Dest_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 31);
-}
-
-static __inline tile_bundle_bits
-create_Imm16_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xffff) << 12);
-}
-
-static __inline tile_bundle_bits
-create_Imm16_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xffff)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_Imm8_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 0);
-}
-
-static __inline tile_bundle_bits
-create_Imm8_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 12);
-}
-
-static __inline tile_bundle_bits
-create_Imm8_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xff)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_Imm8_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 12);
-}
-
-static __inline tile_bundle_bits
-create_Imm8_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xff)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_ImmOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x7f) << 20);
-}
-
-static __inline tile_bundle_bits
-create_ImmOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x7f)) << 51);
-}
-
-static __inline tile_bundle_bits
-create_ImmRROpcodeExtension_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 8);
-}
-
-static __inline tile_bundle_bits
-create_JOffLong_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x00007fff)) << 43) |
-         (((tile_bundle_bits)(n & 0x00018000)) << 20) |
-         (((tile_bundle_bits)(n & 0x001e0000)) << 14) |
-         (((tile_bundle_bits)(n & 0x07e00000)) << 16) |
-         (((tile_bundle_bits)(n & 0x18000000)) << 31);
-}
-
-static __inline tile_bundle_bits
-create_JOff_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x00007fff)) << 43) |
-         (((tile_bundle_bits)(n & 0x00018000)) << 20) |
-         (((tile_bundle_bits)(n & 0x001e0000)) << 14) |
-         (((tile_bundle_bits)(n & 0x07e00000)) << 16) |
-         (((tile_bundle_bits)(n & 0x08000000)) << 31);
-}
-
-static __inline tile_bundle_bits
-create_MF_Imm15_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x00003fff)) << 37) |
-         (((tile_bundle_bits)(n & 0x00004000)) << 44);
-}
-
-static __inline tile_bundle_bits
-create_MMEnd_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 18);
-}
-
-static __inline tile_bundle_bits
-create_MMEnd_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 49);
-}
-
-static __inline tile_bundle_bits
-create_MMStart_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 23);
-}
-
-static __inline tile_bundle_bits
-create_MMStart_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 54);
-}
-
-static __inline tile_bundle_bits
-create_MT_Imm15_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x0000003f)) << 31) |
-         (((tile_bundle_bits)(n & 0x00003fc0)) << 37) |
-         (((tile_bundle_bits)(n & 0x00004000)) << 44);
-}
-
-static __inline tile_bundle_bits
-create_Mode(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1)) << 63);
-}
-
-static __inline tile_bundle_bits
-create_NoRegOpcodeExtension_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xf) << 0);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 10);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x7) << 28);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xf)) << 59);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xf) << 27);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xf)) << 59);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x7)) << 56);
-}
-
-static __inline tile_bundle_bits
-create_RROpcodeExtension_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xf) << 4);
-}
-
-static __inline tile_bundle_bits
-create_RRROpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1ff) << 18);
-}
-
-static __inline tile_bundle_bits
-create_RRROpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1ff)) << 49);
-}
-
-static __inline tile_bundle_bits
-create_RRROpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 18);
-}
-
-static __inline tile_bundle_bits
-create_RRROpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3)) << 49);
-}
-
-static __inline tile_bundle_bits
-create_RouteOpcodeExtension_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3ff) << 0);
-}
-
-static __inline tile_bundle_bits
-create_S_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1) << 27);
-}
-
-static __inline tile_bundle_bits
-create_S_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1)) << 58);
-}
-
-static __inline tile_bundle_bits
-create_ShAmt_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_ShAmt_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_ShAmt_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_ShAmt_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_SrcA_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 6);
-}
-
-static __inline tile_bundle_bits
-create_SrcA_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 37);
-}
-
-static __inline tile_bundle_bits
-create_SrcA_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 6);
-}
-
-static __inline tile_bundle_bits
-create_SrcA_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 37);
-}
-
-static __inline tile_bundle_bits
-create_SrcA_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x00000001) << 26) |
-         (((tile_bundle_bits)(n & 0x0000003e)) << 50);
-}
-
-static __inline tile_bundle_bits
-create_SrcBDest_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 20);
-}
-
-static __inline tile_bundle_bits
-create_SrcB_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_SrcB_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_SrcB_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_SrcB_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_Src_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 0);
-}
-
-static __inline tile_bundle_bits
-create_UnOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_UnOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_UnOpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_UnOpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_UnShOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3ff) << 17);
-}
-
-static __inline tile_bundle_bits
-create_UnShOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3ff)) << 48);
-}
-
-static __inline tile_bundle_bits
-create_UnShOpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x7) << 17);
-}
-
-static __inline tile_bundle_bits
-create_UnShOpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x7)) << 48);
-}
-
-
-
-typedef enum
-{
-  TILE_PIPELINE_X0,
-  TILE_PIPELINE_X1,
-  TILE_PIPELINE_Y0,
-  TILE_PIPELINE_Y1,
-  TILE_PIPELINE_Y2,
-} tile_pipeline;
-
-#define tile_is_x_pipeline(p) ((int)(p) <= (int)TILE_PIPELINE_X1)
-
-typedef enum
-{
-  TILE_OP_TYPE_REGISTER,
-  TILE_OP_TYPE_IMMEDIATE,
-  TILE_OP_TYPE_ADDRESS,
-  TILE_OP_TYPE_SPR
-} tile_operand_type;
-
-/* This is the bit that determines if a bundle is in the Y encoding. */
-#define TILE_BUNDLE_Y_ENCODING_MASK ((tile_bundle_bits)1 << 63)
-
-enum
-{
-  /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */
-  TILE_MAX_INSTRUCTIONS_PER_BUNDLE = 3,
-
-  /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */
-  TILE_NUM_PIPELINE_ENCODINGS = 5,
-
-  /* Log base 2 of TILE_BUNDLE_SIZE_IN_BYTES. */
-  TILE_LOG2_BUNDLE_SIZE_IN_BYTES = 3,
-
-  /* Instructions take this many bytes. */
-  TILE_BUNDLE_SIZE_IN_BYTES = 1 << TILE_LOG2_BUNDLE_SIZE_IN_BYTES,
-
-  /* Log base 2 of TILE_BUNDLE_ALIGNMENT_IN_BYTES. */
-  TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3,
-
-  /* Bundles should be aligned modulo this number of bytes. */
-  TILE_BUNDLE_ALIGNMENT_IN_BYTES =
-    (1 << TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES),
-
-  /* Log base 2 of TILE_SN_INSTRUCTION_SIZE_IN_BYTES. */
-  TILE_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES = 1,
-
-  /* Static network instructions take this many bytes. */
-  TILE_SN_INSTRUCTION_SIZE_IN_BYTES =
-    (1 << TILE_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES),
-
-  /* Number of registers (some are magic, such as network I/O). */
-  TILE_NUM_REGISTERS = 64,
-
-  /* Number of static network registers. */
-  TILE_NUM_SN_REGISTERS = 4
-};
-
-
-struct tile_operand
-{
-  /* Is this operand a register, immediate or address? */
-  tile_operand_type type;
-
-  /* The default relocation type for this operand.  */
-  signed int default_reloc : 16;
-
-  /* How many bits is this value? (used for range checking) */
-  unsigned int num_bits : 5;
-
-  /* Is the value signed? (used for range checking) */
-  unsigned int is_signed : 1;
-
-  /* Is this operand a source register? */
-  unsigned int is_src_reg : 1;
-
-  /* Is this operand written? (i.e. is it a destination register) */
-  unsigned int is_dest_reg : 1;
-
-  /* Is this operand PC-relative? */
-  unsigned int is_pc_relative : 1;
-
-  /* By how many bits do we right shift the value before inserting? */
-  unsigned int rightshift : 2;
-
-  /* Return the bits for this operand to be ORed into an existing bundle. */
-  tile_bundle_bits (*insert) (int op);
-
-  /* Extract this operand and return it. */
-  unsigned int (*extract) (tile_bundle_bits bundle);
-};
-
-
-extern const struct tile_operand tile_operands[];
-
-/* One finite-state machine per pipe for rapid instruction decoding. */
-extern const unsigned short * const
-tile_bundle_decoder_fsms[TILE_NUM_PIPELINE_ENCODINGS];
-
-
-struct tile_opcode
-{
-  /* The opcode mnemonic, e.g. "add" */
-  const char *name;
-
-  /* The enum value for this mnemonic. */
-  tile_mnemonic mnemonic;
-
-  /* A bit mask of which of the five pipes this instruction
-     is compatible with:
-     X0  0x01
-     X1  0x02
-     Y0  0x04
-     Y1  0x08
-     Y2  0x10 */
-  unsigned char pipes;
-
-  /* How many operands are there? */
-  unsigned char num_operands;
-
-  /* Which register does this write implicitly, or TREG_ZERO if none? */
-  unsigned char implicitly_written_register;
-
-  /* Can this be bundled with other instructions (almost always true). */
-  unsigned char can_bundle;
-
-  /* The description of the operands. Each of these is an
-   * index into the tile_operands[] table. */
-  unsigned char operands[TILE_NUM_PIPELINE_ENCODINGS][TILE_MAX_OPERANDS];
-
-};
-
-extern const struct tile_opcode tile_opcodes[];
-
-
-/* Used for non-textual disassembly into structs. */
-struct tile_decoded_instruction
-{
-  const struct tile_opcode *opcode;
-  const struct tile_operand *operands[TILE_MAX_OPERANDS];
-  int operand_values[TILE_MAX_OPERANDS];
-};
-
-
-/* Disassemble a bundle into a struct for machine processing. */
-extern int parse_insn_tile(tile_bundle_bits bits,
-                           unsigned int pc,
-                           struct tile_decoded_instruction
-                           decoded[TILE_MAX_INSTRUCTIONS_PER_BUNDLE]);
-
-
-/* Given a set of bundle bits and a specific pipe, returns which
- * instruction the bundle contains in that pipe.
- */
-extern const struct tile_opcode *
-find_opcode(tile_bundle_bits bits, tile_pipeline pipe);
-
-
-
-#endif /* opcode_tile_h */
diff -druN linux-libre-3.1-gnu/arch/tile/include/asm/opcode-tile_64.h linux-libre-3.2-gnu/arch/tile/include/asm/opcode-tile_64.h
--- linux-libre-3.1-gnu/arch/tile/include/asm/opcode-tile_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/include/asm/opcode-tile_64.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1248 +0,0 @@
-/* tile.h -- Header file for TILE opcode table
-   Copyright (C) 2005 Free Software Foundation, Inc.
-   Contributed by Tilera Corp. */
-
-#ifndef opcode_tile_h
-#define opcode_tile_h
-
-typedef unsigned long long tilegx_bundle_bits;
-
-
-enum
-{
-  TILEGX_MAX_OPERANDS = 4 /* bfexts */
-};
-
-typedef enum
-{
-  TILEGX_OPC_BPT,
-  TILEGX_OPC_INFO,
-  TILEGX_OPC_INFOL,
-  TILEGX_OPC_MOVE,
-  TILEGX_OPC_MOVEI,
-  TILEGX_OPC_MOVELI,
-  TILEGX_OPC_PREFETCH,
-  TILEGX_OPC_PREFETCH_ADD_L1,
-  TILEGX_OPC_PREFETCH_ADD_L1_FAULT,
-  TILEGX_OPC_PREFETCH_ADD_L2,
-  TILEGX_OPC_PREFETCH_ADD_L2_FAULT,
-  TILEGX_OPC_PREFETCH_ADD_L3,
-  TILEGX_OPC_PREFETCH_ADD_L3_FAULT,
-  TILEGX_OPC_PREFETCH_L1,
-  TILEGX_OPC_PREFETCH_L1_FAULT,
-  TILEGX_OPC_PREFETCH_L2,
-  TILEGX_OPC_PREFETCH_L2_FAULT,
-  TILEGX_OPC_PREFETCH_L3,
-  TILEGX_OPC_PREFETCH_L3_FAULT,
-  TILEGX_OPC_RAISE,
-  TILEGX_OPC_ADD,
-  TILEGX_OPC_ADDI,
-  TILEGX_OPC_ADDLI,
-  TILEGX_OPC_ADDX,
-  TILEGX_OPC_ADDXI,
-  TILEGX_OPC_ADDXLI,
-  TILEGX_OPC_ADDXSC,
-  TILEGX_OPC_AND,
-  TILEGX_OPC_ANDI,
-  TILEGX_OPC_BEQZ,
-  TILEGX_OPC_BEQZT,
-  TILEGX_OPC_BFEXTS,
-  TILEGX_OPC_BFEXTU,
-  TILEGX_OPC_BFINS,
-  TILEGX_OPC_BGEZ,
-  TILEGX_OPC_BGEZT,
-  TILEGX_OPC_BGTZ,
-  TILEGX_OPC_BGTZT,
-  TILEGX_OPC_BLBC,
-  TILEGX_OPC_BLBCT,
-  TILEGX_OPC_BLBS,
-  TILEGX_OPC_BLBST,
-  TILEGX_OPC_BLEZ,
-  TILEGX_OPC_BLEZT,
-  TILEGX_OPC_BLTZ,
-  TILEGX_OPC_BLTZT,
-  TILEGX_OPC_BNEZ,
-  TILEGX_OPC_BNEZT,
-  TILEGX_OPC_CLZ,
-  TILEGX_OPC_CMOVEQZ,
-  TILEGX_OPC_CMOVNEZ,
-  TILEGX_OPC_CMPEQ,
-  TILEGX_OPC_CMPEQI,
-  TILEGX_OPC_CMPEXCH,
-  TILEGX_OPC_CMPEXCH4,
-  TILEGX_OPC_CMPLES,
-  TILEGX_OPC_CMPLEU,
-  TILEGX_OPC_CMPLTS,
-  TILEGX_OPC_CMPLTSI,
-  TILEGX_OPC_CMPLTU,
-  TILEGX_OPC_CMPLTUI,
-  TILEGX_OPC_CMPNE,
-  TILEGX_OPC_CMUL,
-  TILEGX_OPC_CMULA,
-  TILEGX_OPC_CMULAF,
-  TILEGX_OPC_CMULF,
-  TILEGX_OPC_CMULFR,
-  TILEGX_OPC_CMULH,
-  TILEGX_OPC_CMULHR,
-  TILEGX_OPC_CRC32_32,
-  TILEGX_OPC_CRC32_8,
-  TILEGX_OPC_CTZ,
-  TILEGX_OPC_DBLALIGN,
-  TILEGX_OPC_DBLALIGN2,
-  TILEGX_OPC_DBLALIGN4,
-  TILEGX_OPC_DBLALIGN6,
-  TILEGX_OPC_DRAIN,
-  TILEGX_OPC_DTLBPR,
-  TILEGX_OPC_EXCH,
-  TILEGX_OPC_EXCH4,
-  TILEGX_OPC_FDOUBLE_ADD_FLAGS,
-  TILEGX_OPC_FDOUBLE_ADDSUB,
-  TILEGX_OPC_FDOUBLE_MUL_FLAGS,
-  TILEGX_OPC_FDOUBLE_PACK1,
-  TILEGX_OPC_FDOUBLE_PACK2,
-  TILEGX_OPC_FDOUBLE_SUB_FLAGS,
-  TILEGX_OPC_FDOUBLE_UNPACK_MAX,
-  TILEGX_OPC_FDOUBLE_UNPACK_MIN,
-  TILEGX_OPC_FETCHADD,
-  TILEGX_OPC_FETCHADD4,
-  TILEGX_OPC_FETCHADDGEZ,
-  TILEGX_OPC_FETCHADDGEZ4,
-  TILEGX_OPC_FETCHAND,
-  TILEGX_OPC_FETCHAND4,
-  TILEGX_OPC_FETCHOR,
-  TILEGX_OPC_FETCHOR4,
-  TILEGX_OPC_FINV,
-  TILEGX_OPC_FLUSH,
-  TILEGX_OPC_FLUSHWB,
-  TILEGX_OPC_FNOP,
-  TILEGX_OPC_FSINGLE_ADD1,
-  TILEGX_OPC_FSINGLE_ADDSUB2,
-  TILEGX_OPC_FSINGLE_MUL1,
-  TILEGX_OPC_FSINGLE_MUL2,
-  TILEGX_OPC_FSINGLE_PACK1,
-  TILEGX_OPC_FSINGLE_PACK2,
-  TILEGX_OPC_FSINGLE_SUB1,
-  TILEGX_OPC_ICOH,
-  TILEGX_OPC_ILL,
-  TILEGX_OPC_INV,
-  TILEGX_OPC_IRET,
-  TILEGX_OPC_J,
-  TILEGX_OPC_JAL,
-  TILEGX_OPC_JALR,
-  TILEGX_OPC_JALRP,
-  TILEGX_OPC_JR,
-  TILEGX_OPC_JRP,
-  TILEGX_OPC_LD,
-  TILEGX_OPC_LD1S,
-  TILEGX_OPC_LD1S_ADD,
-  TILEGX_OPC_LD1U,
-  TILEGX_OPC_LD1U_ADD,
-  TILEGX_OPC_LD2S,
-  TILEGX_OPC_LD2S_ADD,
-  TILEGX_OPC_LD2U,
-  TILEGX_OPC_LD2U_ADD,
-  TILEGX_OPC_LD4S,
-  TILEGX_OPC_LD4S_ADD,
-  TILEGX_OPC_LD4U,
-  TILEGX_OPC_LD4U_ADD,
-  TILEGX_OPC_LD_ADD,
-  TILEGX_OPC_LDNA,
-  TILEGX_OPC_LDNA_ADD,
-  TILEGX_OPC_LDNT,
-  TILEGX_OPC_LDNT1S,
-  TILEGX_OPC_LDNT1S_ADD,
-  TILEGX_OPC_LDNT1U,
-  TILEGX_OPC_LDNT1U_ADD,
-  TILEGX_OPC_LDNT2S,
-  TILEGX_OPC_LDNT2S_ADD,
-  TILEGX_OPC_LDNT2U,
-  TILEGX_OPC_LDNT2U_ADD,
-  TILEGX_OPC_LDNT4S,
-  TILEGX_OPC_LDNT4S_ADD,
-  TILEGX_OPC_LDNT4U,
-  TILEGX_OPC_LDNT4U_ADD,
-  TILEGX_OPC_LDNT_ADD,
-  TILEGX_OPC_LNK,
-  TILEGX_OPC_MF,
-  TILEGX_OPC_MFSPR,
-  TILEGX_OPC_MM,
-  TILEGX_OPC_MNZ,
-  TILEGX_OPC_MTSPR,
-  TILEGX_OPC_MUL_HS_HS,
-  TILEGX_OPC_MUL_HS_HU,
-  TILEGX_OPC_MUL_HS_LS,
-  TILEGX_OPC_MUL_HS_LU,
-  TILEGX_OPC_MUL_HU_HU,
-  TILEGX_OPC_MUL_HU_LS,
-  TILEGX_OPC_MUL_HU_LU,
-  TILEGX_OPC_MUL_LS_LS,
-  TILEGX_OPC_MUL_LS_LU,
-  TILEGX_OPC_MUL_LU_LU,
-  TILEGX_OPC_MULA_HS_HS,
-  TILEGX_OPC_MULA_HS_HU,
-  TILEGX_OPC_MULA_HS_LS,
-  TILEGX_OPC_MULA_HS_LU,
-  TILEGX_OPC_MULA_HU_HU,
-  TILEGX_OPC_MULA_HU_LS,
-  TILEGX_OPC_MULA_HU_LU,
-  TILEGX_OPC_MULA_LS_LS,
-  TILEGX_OPC_MULA_LS_LU,
-  TILEGX_OPC_MULA_LU_LU,
-  TILEGX_OPC_MULAX,
-  TILEGX_OPC_MULX,
-  TILEGX_OPC_MZ,
-  TILEGX_OPC_NAP,
-  TILEGX_OPC_NOP,
-  TILEGX_OPC_NOR,
-  TILEGX_OPC_OR,
-  TILEGX_OPC_ORI,
-  TILEGX_OPC_PCNT,
-  TILEGX_OPC_REVBITS,
-  TILEGX_OPC_REVBYTES,
-  TILEGX_OPC_ROTL,
-  TILEGX_OPC_ROTLI,
-  TILEGX_OPC_SHL,
-  TILEGX_OPC_SHL16INSLI,
-  TILEGX_OPC_SHL1ADD,
-  TILEGX_OPC_SHL1ADDX,
-  TILEGX_OPC_SHL2ADD,
-  TILEGX_OPC_SHL2ADDX,
-  TILEGX_OPC_SHL3ADD,
-  TILEGX_OPC_SHL3ADDX,
-  TILEGX_OPC_SHLI,
-  TILEGX_OPC_SHLX,
-  TILEGX_OPC_SHLXI,
-  TILEGX_OPC_SHRS,
-  TILEGX_OPC_SHRSI,
-  TILEGX_OPC_SHRU,
-  TILEGX_OPC_SHRUI,
-  TILEGX_OPC_SHRUX,
-  TILEGX_OPC_SHRUXI,
-  TILEGX_OPC_SHUFFLEBYTES,
-  TILEGX_OPC_ST,
-  TILEGX_OPC_ST1,
-  TILEGX_OPC_ST1_ADD,
-  TILEGX_OPC_ST2,
-  TILEGX_OPC_ST2_ADD,
-  TILEGX_OPC_ST4,
-  TILEGX_OPC_ST4_ADD,
-  TILEGX_OPC_ST_ADD,
-  TILEGX_OPC_STNT,
-  TILEGX_OPC_STNT1,
-  TILEGX_OPC_STNT1_ADD,
-  TILEGX_OPC_STNT2,
-  TILEGX_OPC_STNT2_ADD,
-  TILEGX_OPC_STNT4,
-  TILEGX_OPC_STNT4_ADD,
-  TILEGX_OPC_STNT_ADD,
-  TILEGX_OPC_SUB,
-  TILEGX_OPC_SUBX,
-  TILEGX_OPC_SUBXSC,
-  TILEGX_OPC_SWINT0,
-  TILEGX_OPC_SWINT1,
-  TILEGX_OPC_SWINT2,
-  TILEGX_OPC_SWINT3,
-  TILEGX_OPC_TBLIDXB0,
-  TILEGX_OPC_TBLIDXB1,
-  TILEGX_OPC_TBLIDXB2,
-  TILEGX_OPC_TBLIDXB3,
-  TILEGX_OPC_V1ADD,
-  TILEGX_OPC_V1ADDI,
-  TILEGX_OPC_V1ADDUC,
-  TILEGX_OPC_V1ADIFFU,
-  TILEGX_OPC_V1AVGU,
-  TILEGX_OPC_V1CMPEQ,
-  TILEGX_OPC_V1CMPEQI,
-  TILEGX_OPC_V1CMPLES,
-  TILEGX_OPC_V1CMPLEU,
-  TILEGX_OPC_V1CMPLTS,
-  TILEGX_OPC_V1CMPLTSI,
-  TILEGX_OPC_V1CMPLTU,
-  TILEGX_OPC_V1CMPLTUI,
-  TILEGX_OPC_V1CMPNE,
-  TILEGX_OPC_V1DDOTPU,
-  TILEGX_OPC_V1DDOTPUA,
-  TILEGX_OPC_V1DDOTPUS,
-  TILEGX_OPC_V1DDOTPUSA,
-  TILEGX_OPC_V1DOTP,
-  TILEGX_OPC_V1DOTPA,
-  TILEGX_OPC_V1DOTPU,
-  TILEGX_OPC_V1DOTPUA,
-  TILEGX_OPC_V1DOTPUS,
-  TILEGX_OPC_V1DOTPUSA,
-  TILEGX_OPC_V1INT_H,
-  TILEGX_OPC_V1INT_L,
-  TILEGX_OPC_V1MAXU,
-  TILEGX_OPC_V1MAXUI,
-  TILEGX_OPC_V1MINU,
-  TILEGX_OPC_V1MINUI,
-  TILEGX_OPC_V1MNZ,
-  TILEGX_OPC_V1MULTU,
-  TILEGX_OPC_V1MULU,
-  TILEGX_OPC_V1MULUS,
-  TILEGX_OPC_V1MZ,
-  TILEGX_OPC_V1SADAU,
-  TILEGX_OPC_V1SADU,
-  TILEGX_OPC_V1SHL,
-  TILEGX_OPC_V1SHLI,
-  TILEGX_OPC_V1SHRS,
-  TILEGX_OPC_V1SHRSI,
-  TILEGX_OPC_V1SHRU,
-  TILEGX_OPC_V1SHRUI,
-  TILEGX_OPC_V1SUB,
-  TILEGX_OPC_V1SUBUC,
-  TILEGX_OPC_V2ADD,
-  TILEGX_OPC_V2ADDI,
-  TILEGX_OPC_V2ADDSC,
-  TILEGX_OPC_V2ADIFFS,
-  TILEGX_OPC_V2AVGS,
-  TILEGX_OPC_V2CMPEQ,
-  TILEGX_OPC_V2CMPEQI,
-  TILEGX_OPC_V2CMPLES,
-  TILEGX_OPC_V2CMPLEU,
-  TILEGX_OPC_V2CMPLTS,
-  TILEGX_OPC_V2CMPLTSI,
-  TILEGX_OPC_V2CMPLTU,
-  TILEGX_OPC_V2CMPLTUI,
-  TILEGX_OPC_V2CMPNE,
-  TILEGX_OPC_V2DOTP,
-  TILEGX_OPC_V2DOTPA,
-  TILEGX_OPC_V2INT_H,
-  TILEGX_OPC_V2INT_L,
-  TILEGX_OPC_V2MAXS,
-  TILEGX_OPC_V2MAXSI,
-  TILEGX_OPC_V2MINS,
-  TILEGX_OPC_V2MINSI,
-  TILEGX_OPC_V2MNZ,
-  TILEGX_OPC_V2MULFSC,
-  TILEGX_OPC_V2MULS,
-  TILEGX_OPC_V2MULTS,
-  TILEGX_OPC_V2MZ,
-  TILEGX_OPC_V2PACKH,
-  TILEGX_OPC_V2PACKL,
-  TILEGX_OPC_V2PACKUC,
-  TILEGX_OPC_V2SADAS,
-  TILEGX_OPC_V2SADAU,
-  TILEGX_OPC_V2SADS,
-  TILEGX_OPC_V2SADU,
-  TILEGX_OPC_V2SHL,
-  TILEGX_OPC_V2SHLI,
-  TILEGX_OPC_V2SHLSC,
-  TILEGX_OPC_V2SHRS,
-  TILEGX_OPC_V2SHRSI,
-  TILEGX_OPC_V2SHRU,
-  TILEGX_OPC_V2SHRUI,
-  TILEGX_OPC_V2SUB,
-  TILEGX_OPC_V2SUBSC,
-  TILEGX_OPC_V4ADD,
-  TILEGX_OPC_V4ADDSC,
-  TILEGX_OPC_V4INT_H,
-  TILEGX_OPC_V4INT_L,
-  TILEGX_OPC_V4PACKSC,
-  TILEGX_OPC_V4SHL,
-  TILEGX_OPC_V4SHLSC,
-  TILEGX_OPC_V4SHRS,
-  TILEGX_OPC_V4SHRU,
-  TILEGX_OPC_V4SUB,
-  TILEGX_OPC_V4SUBSC,
-  TILEGX_OPC_WH64,
-  TILEGX_OPC_XOR,
-  TILEGX_OPC_XORI,
-  TILEGX_OPC_NONE
-} tilegx_mnemonic;
-
-/* 64-bit pattern for a { bpt ; nop } bundle. */
-#define TILEGX_BPT_BUNDLE 0x286a44ae51485000ULL
-
-
-#define TILE_ELF_MACHINE_CODE EM_TILE64
-
-#define TILE_ELF_NAME "elf32-tile64"
-
-
-static __inline unsigned int
-get_BFEnd_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_BFOpcodeExtension_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 24)) & 0xf);
-}
-
-static __inline unsigned int
-get_BFStart_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3f);
-}
-
-static __inline unsigned int
-get_BrOff_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x0000003f) |
-         (((unsigned int)(n >> 37)) & 0x0001ffc0);
-}
-
-static __inline unsigned int
-get_BrType_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 54)) & 0x1f);
-}
-
-static __inline unsigned int
-get_Dest_Imm8_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x0000003f) |
-         (((unsigned int)(n >> 43)) & 0x000000c0);
-}
-
-static __inline unsigned int
-get_Dest_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Imm16_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xffff);
-}
-
-static __inline unsigned int
-get_Imm16_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xffff);
-}
-
-static __inline unsigned int
-get_Imm8OpcodeExtension_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 20)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8OpcodeExtension_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 51)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xff);
-}
-
-static __inline unsigned int
-get_JumpOff_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x7ffffff);
-}
-
-static __inline unsigned int
-get_JumpOpcodeExtension_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 58)) & 0x1);
-}
-
-static __inline unsigned int
-get_MF_Imm14_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x3fff);
-}
-
-static __inline unsigned int
-get_MT_Imm14_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x0000003f) |
-         (((unsigned int)(n >> 37)) & 0x00003fc0);
-}
-
-static __inline unsigned int
-get_Mode(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 62)) & 0x3);
-}
-
-static __inline unsigned int
-get_Opcode_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 28)) & 0x7);
-}
-
-static __inline unsigned int
-get_Opcode_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 59)) & 0x7);
-}
-
-static __inline unsigned int
-get_Opcode_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 27)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 58)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_Y2(tilegx_bundle_bits n)
-{
-  return (((n >> 26)) & 0x00000001) |
-         (((unsigned int)(n >> 56)) & 0x00000002);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x3);
-}
-
-static __inline unsigned int
-get_ShAmt_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_ShAmt_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_ShAmt_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_ShAmt_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_ShiftOpcodeExtension_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_ShiftOpcodeExtension_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_ShiftOpcodeExtension_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3);
-}
-
-static __inline unsigned int
-get_ShiftOpcodeExtension_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x3);
-}
-
-static __inline unsigned int
-get_SrcA_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 6)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 6)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y2(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 20)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcBDest_Y2(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 51)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_UnaryOpcodeExtension_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_UnaryOpcodeExtension_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_UnaryOpcodeExtension_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_UnaryOpcodeExtension_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-
-static __inline int
-sign_extend(int n, int num_bits)
-{
-  int shift = (int)(sizeof(int) * 8 - num_bits);
-  return (n << shift) >> shift;
-}
-
-
-
-static __inline tilegx_bundle_bits
-create_BFEnd_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_BFOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xf) << 24);
-}
-
-static __inline tilegx_bundle_bits
-create_BFStart_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 18);
-}
-
-static __inline tilegx_bundle_bits
-create_BrOff_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
-         (((tilegx_bundle_bits)(n & 0x0001ffc0)) << 37);
-}
-
-static __inline tilegx_bundle_bits
-create_BrType_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x1f)) << 54);
-}
-
-static __inline tilegx_bundle_bits
-create_Dest_Imm8_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
-         (((tilegx_bundle_bits)(n & 0x000000c0)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_Dest_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 0);
-}
-
-static __inline tilegx_bundle_bits
-create_Dest_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 31);
-}
-
-static __inline tilegx_bundle_bits
-create_Dest_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 0);
-}
-
-static __inline tilegx_bundle_bits
-create_Dest_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 31);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm16_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xffff) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm16_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0xffff)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8OpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 20);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8OpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0xff)) << 51);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0xff)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0xff)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_JumpOff_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x7ffffff)) << 31);
-}
-
-static __inline tilegx_bundle_bits
-create_JumpOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x1)) << 58);
-}
-
-static __inline tilegx_bundle_bits
-create_MF_Imm14_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3fff)) << 37);
-}
-
-static __inline tilegx_bundle_bits
-create_MT_Imm14_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
-         (((tilegx_bundle_bits)(n & 0x00003fc0)) << 37);
-}
-
-static __inline tilegx_bundle_bits
-create_Mode(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3)) << 62);
-}
-
-static __inline tilegx_bundle_bits
-create_Opcode_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x7) << 28);
-}
-
-static __inline tilegx_bundle_bits
-create_Opcode_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x7)) << 59);
-}
-
-static __inline tilegx_bundle_bits
-create_Opcode_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xf) << 27);
-}
-
-static __inline tilegx_bundle_bits
-create_Opcode_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0xf)) << 58);
-}
-
-static __inline tilegx_bundle_bits
-create_Opcode_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x00000001) << 26) |
-         (((tilegx_bundle_bits)(n & 0x00000002)) << 56);
-}
-
-static __inline tilegx_bundle_bits
-create_RRROpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3ff) << 18);
-}
-
-static __inline tilegx_bundle_bits
-create_RRROpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3ff)) << 49);
-}
-
-static __inline tilegx_bundle_bits
-create_RRROpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 18);
-}
-
-static __inline tilegx_bundle_bits
-create_RRROpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3)) << 49);
-}
-
-static __inline tilegx_bundle_bits
-create_ShAmt_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_ShAmt_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_ShAmt_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_ShAmt_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_ShiftOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3ff) << 18);
-}
-
-static __inline tilegx_bundle_bits
-create_ShiftOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3ff)) << 49);
-}
-
-static __inline tilegx_bundle_bits
-create_ShiftOpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 18);
-}
-
-static __inline tilegx_bundle_bits
-create_ShiftOpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3)) << 49);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcA_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 6);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcA_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 37);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcA_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 6);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcA_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 37);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcA_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 20);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcBDest_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 51);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcB_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcB_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcB_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcB_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_UnaryOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_UnaryOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_UnaryOpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_UnaryOpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-
-typedef enum
-{
-  TILEGX_PIPELINE_X0,
-  TILEGX_PIPELINE_X1,
-  TILEGX_PIPELINE_Y0,
-  TILEGX_PIPELINE_Y1,
-  TILEGX_PIPELINE_Y2,
-} tilegx_pipeline;
-
-#define tilegx_is_x_pipeline(p) ((int)(p) <= (int)TILEGX_PIPELINE_X1)
-
-typedef enum
-{
-  TILEGX_OP_TYPE_REGISTER,
-  TILEGX_OP_TYPE_IMMEDIATE,
-  TILEGX_OP_TYPE_ADDRESS,
-  TILEGX_OP_TYPE_SPR
-} tilegx_operand_type;
-
-/* These are the bits that determine if a bundle is in the X encoding. */
-#define TILEGX_BUNDLE_MODE_MASK ((tilegx_bundle_bits)3 << 62)
-
-enum
-{
-  /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */
-  TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE = 3,
-
-  /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */
-  TILEGX_NUM_PIPELINE_ENCODINGS = 5,
-
-  /* Log base 2 of TILEGX_BUNDLE_SIZE_IN_BYTES. */
-  TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES = 3,
-
-  /* Instructions take this many bytes. */
-  TILEGX_BUNDLE_SIZE_IN_BYTES = 1 << TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES,
-
-  /* Log base 2 of TILEGX_BUNDLE_ALIGNMENT_IN_BYTES. */
-  TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3,
-
-  /* Bundles should be aligned modulo this number of bytes. */
-  TILEGX_BUNDLE_ALIGNMENT_IN_BYTES =
-    (1 << TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES),
-
-  /* Number of registers (some are magic, such as network I/O). */
-  TILEGX_NUM_REGISTERS = 64,
-};
-
-
-struct tilegx_operand
-{
-  /* Is this operand a register, immediate or address? */
-  tilegx_operand_type type;
-
-  /* The default relocation type for this operand.  */
-  signed int default_reloc : 16;
-
-  /* How many bits is this value? (used for range checking) */
-  unsigned int num_bits : 5;
-
-  /* Is the value signed? (used for range checking) */
-  unsigned int is_signed : 1;
-
-  /* Is this operand a source register? */
-  unsigned int is_src_reg : 1;
-
-  /* Is this operand written? (i.e. is it a destination register) */
-  unsigned int is_dest_reg : 1;
-
-  /* Is this operand PC-relative? */
-  unsigned int is_pc_relative : 1;
-
-  /* By how many bits do we right shift the value before inserting? */
-  unsigned int rightshift : 2;
-
-  /* Return the bits for this operand to be ORed into an existing bundle. */
-  tilegx_bundle_bits (*insert) (int op);
-
-  /* Extract this operand and return it. */
-  unsigned int (*extract) (tilegx_bundle_bits bundle);
-};
-
-
-extern const struct tilegx_operand tilegx_operands[];
-
-/* One finite-state machine per pipe for rapid instruction decoding. */
-extern const unsigned short * const
-tilegx_bundle_decoder_fsms[TILEGX_NUM_PIPELINE_ENCODINGS];
-
-
-struct tilegx_opcode
-{
-  /* The opcode mnemonic, e.g. "add" */
-  const char *name;
-
-  /* The enum value for this mnemonic. */
-  tilegx_mnemonic mnemonic;
-
-  /* A bit mask of which of the five pipes this instruction
-     is compatible with:
-     X0  0x01
-     X1  0x02
-     Y0  0x04
-     Y1  0x08
-     Y2  0x10 */
-  unsigned char pipes;
-
-  /* How many operands are there? */
-  unsigned char num_operands;
-
-  /* Which register does this write implicitly, or TREG_ZERO if none? */
-  unsigned char implicitly_written_register;
-
-  /* Can this be bundled with other instructions (almost always true). */
-  unsigned char can_bundle;
-
-  /* The description of the operands. Each of these is an
-   * index into the tilegx_operands[] table. */
-  unsigned char operands[TILEGX_NUM_PIPELINE_ENCODINGS][TILEGX_MAX_OPERANDS];
-
-};
-
-extern const struct tilegx_opcode tilegx_opcodes[];
-
-/* Used for non-textual disassembly into structs. */
-struct tilegx_decoded_instruction
-{
-  const struct tilegx_opcode *opcode;
-  const struct tilegx_operand *operands[TILEGX_MAX_OPERANDS];
-  long long operand_values[TILEGX_MAX_OPERANDS];
-};
-
-
-/* Disassemble a bundle into a struct for machine processing. */
-extern int parse_insn_tilegx(tilegx_bundle_bits bits,
-                             unsigned long long pc,
-                             struct tilegx_decoded_instruction
-                             decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]);
-
-
-
-#endif /* opcode_tilegx_h */
diff -druN linux-libre-3.1-gnu/arch/tile/include/asm/opcode-tile.h linux-libre-3.2-gnu/arch/tile/include/asm/opcode-tile.h
--- linux-libre-3.1-gnu/arch/tile/include/asm/opcode-tile.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/include/asm/opcode-tile.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,30 +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.
- */
-
-#ifndef _ASM_TILE_OPCODE_TILE_H
-#define _ASM_TILE_OPCODE_TILE_H
-
-#include <arch/chip.h>
-
-#if CHIP_WORD_SIZE() == 64
-#include <asm/opcode-tile_64.h>
-#else
-#include <asm/opcode-tile_32.h>
-#endif
-
-/* These definitions are not correct for TILE64, so just avoid them. */
-#undef TILE_ELF_MACHINE_CODE
-#undef TILE_ELF_NAME
-
-#endif /* _ASM_TILE_OPCODE_TILE_H */
diff -druN linux-libre-3.1-gnu/arch/tile/include/asm/sigcontext.h linux-libre-3.2-gnu/arch/tile/include/asm/sigcontext.h
--- linux-libre-3.1-gnu/arch/tile/include/asm/sigcontext.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/include/asm/sigcontext.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,8 @@
 #ifndef _ASM_TILE_SIGCONTEXT_H
 #define _ASM_TILE_SIGCONTEXT_H
 
+/* Don't pollute the namespace since <signal.h> includes this file. */
+#define __need_int_reg_t
 #include <arch/abi.h>
 
 /*
@@ -22,14 +24,14 @@
  * but is simplified since we know the fault is from userspace.
  */
 struct sigcontext {
-	uint_reg_t gregs[53];	/* General-purpose registers.  */
-	uint_reg_t tp;		/* Aliases gregs[TREG_TP].  */
-	uint_reg_t sp;		/* Aliases gregs[TREG_SP].  */
-	uint_reg_t lr;		/* Aliases gregs[TREG_LR].  */
-	uint_reg_t pc;		/* Program counter.  */
-	uint_reg_t ics;		/* In Interrupt Critical Section?  */
-	uint_reg_t faultnum;	/* Fault number.  */
-	uint_reg_t pad[5];
+	__uint_reg_t gregs[53];	/* General-purpose registers.  */
+	__uint_reg_t tp;	/* Aliases gregs[TREG_TP].  */
+	__uint_reg_t sp;	/* Aliases gregs[TREG_SP].  */
+	__uint_reg_t lr;	/* Aliases gregs[TREG_LR].  */
+	__uint_reg_t pc;	/* Program counter.  */
+	__uint_reg_t ics;	/* In Interrupt Critical Section?  */
+	__uint_reg_t faultnum;	/* Fault number.  */
+	__uint_reg_t pad[5];
 };
 
 #endif /* _ASM_TILE_SIGCONTEXT_H */
diff -druN linux-libre-3.1-gnu/arch/tile/include/asm/tile-desc_32.h linux-libre-3.2-gnu/arch/tile/include/asm/tile-desc_32.h
--- linux-libre-3.1-gnu/arch/tile/include/asm/tile-desc_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/tile/include/asm/tile-desc_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,553 @@
+/* TILEPro opcode information.
+ *
+ * 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 opcode_tilepro_h
+#define opcode_tilepro_h
+
+#include <arch/opcode.h>
+
+
+enum
+{
+  TILEPRO_MAX_OPERANDS = 5 /* mm */
+};
+
+typedef enum
+{
+  TILEPRO_OPC_BPT,
+  TILEPRO_OPC_INFO,
+  TILEPRO_OPC_INFOL,
+  TILEPRO_OPC_J,
+  TILEPRO_OPC_JAL,
+  TILEPRO_OPC_MOVE,
+  TILEPRO_OPC_MOVE_SN,
+  TILEPRO_OPC_MOVEI,
+  TILEPRO_OPC_MOVEI_SN,
+  TILEPRO_OPC_MOVELI,
+  TILEPRO_OPC_MOVELI_SN,
+  TILEPRO_OPC_MOVELIS,
+  TILEPRO_OPC_PREFETCH,
+  TILEPRO_OPC_RAISE,
+  TILEPRO_OPC_ADD,
+  TILEPRO_OPC_ADD_SN,
+  TILEPRO_OPC_ADDB,
+  TILEPRO_OPC_ADDB_SN,
+  TILEPRO_OPC_ADDBS_U,
+  TILEPRO_OPC_ADDBS_U_SN,
+  TILEPRO_OPC_ADDH,
+  TILEPRO_OPC_ADDH_SN,
+  TILEPRO_OPC_ADDHS,
+  TILEPRO_OPC_ADDHS_SN,
+  TILEPRO_OPC_ADDI,
+  TILEPRO_OPC_ADDI_SN,
+  TILEPRO_OPC_ADDIB,
+  TILEPRO_OPC_ADDIB_SN,
+  TILEPRO_OPC_ADDIH,
+  TILEPRO_OPC_ADDIH_SN,
+  TILEPRO_OPC_ADDLI,
+  TILEPRO_OPC_ADDLI_SN,
+  TILEPRO_OPC_ADDLIS,
+  TILEPRO_OPC_ADDS,
+  TILEPRO_OPC_ADDS_SN,
+  TILEPRO_OPC_ADIFFB_U,
+  TILEPRO_OPC_ADIFFB_U_SN,
+  TILEPRO_OPC_ADIFFH,
+  TILEPRO_OPC_ADIFFH_SN,
+  TILEPRO_OPC_AND,
+  TILEPRO_OPC_AND_SN,
+  TILEPRO_OPC_ANDI,
+  TILEPRO_OPC_ANDI_SN,
+  TILEPRO_OPC_AULI,
+  TILEPRO_OPC_AVGB_U,
+  TILEPRO_OPC_AVGB_U_SN,
+  TILEPRO_OPC_AVGH,
+  TILEPRO_OPC_AVGH_SN,
+  TILEPRO_OPC_BBNS,
+  TILEPRO_OPC_BBNS_SN,
+  TILEPRO_OPC_BBNST,
+  TILEPRO_OPC_BBNST_SN,
+  TILEPRO_OPC_BBS,
+  TILEPRO_OPC_BBS_SN,
+  TILEPRO_OPC_BBST,
+  TILEPRO_OPC_BBST_SN,
+  TILEPRO_OPC_BGEZ,
+  TILEPRO_OPC_BGEZ_SN,
+  TILEPRO_OPC_BGEZT,
+  TILEPRO_OPC_BGEZT_SN,
+  TILEPRO_OPC_BGZ,
+  TILEPRO_OPC_BGZ_SN,
+  TILEPRO_OPC_BGZT,
+  TILEPRO_OPC_BGZT_SN,
+  TILEPRO_OPC_BITX,
+  TILEPRO_OPC_BITX_SN,
+  TILEPRO_OPC_BLEZ,
+  TILEPRO_OPC_BLEZ_SN,
+  TILEPRO_OPC_BLEZT,
+  TILEPRO_OPC_BLEZT_SN,
+  TILEPRO_OPC_BLZ,
+  TILEPRO_OPC_BLZ_SN,
+  TILEPRO_OPC_BLZT,
+  TILEPRO_OPC_BLZT_SN,
+  TILEPRO_OPC_BNZ,
+  TILEPRO_OPC_BNZ_SN,
+  TILEPRO_OPC_BNZT,
+  TILEPRO_OPC_BNZT_SN,
+  TILEPRO_OPC_BYTEX,
+  TILEPRO_OPC_BYTEX_SN,
+  TILEPRO_OPC_BZ,
+  TILEPRO_OPC_BZ_SN,
+  TILEPRO_OPC_BZT,
+  TILEPRO_OPC_BZT_SN,
+  TILEPRO_OPC_CLZ,
+  TILEPRO_OPC_CLZ_SN,
+  TILEPRO_OPC_CRC32_32,
+  TILEPRO_OPC_CRC32_32_SN,
+  TILEPRO_OPC_CRC32_8,
+  TILEPRO_OPC_CRC32_8_SN,
+  TILEPRO_OPC_CTZ,
+  TILEPRO_OPC_CTZ_SN,
+  TILEPRO_OPC_DRAIN,
+  TILEPRO_OPC_DTLBPR,
+  TILEPRO_OPC_DWORD_ALIGN,
+  TILEPRO_OPC_DWORD_ALIGN_SN,
+  TILEPRO_OPC_FINV,
+  TILEPRO_OPC_FLUSH,
+  TILEPRO_OPC_FNOP,
+  TILEPRO_OPC_ICOH,
+  TILEPRO_OPC_ILL,
+  TILEPRO_OPC_INTHB,
+  TILEPRO_OPC_INTHB_SN,
+  TILEPRO_OPC_INTHH,
+  TILEPRO_OPC_INTHH_SN,
+  TILEPRO_OPC_INTLB,
+  TILEPRO_OPC_INTLB_SN,
+  TILEPRO_OPC_INTLH,
+  TILEPRO_OPC_INTLH_SN,
+  TILEPRO_OPC_INV,
+  TILEPRO_OPC_IRET,
+  TILEPRO_OPC_JALB,
+  TILEPRO_OPC_JALF,
+  TILEPRO_OPC_JALR,
+  TILEPRO_OPC_JALRP,
+  TILEPRO_OPC_JB,
+  TILEPRO_OPC_JF,
+  TILEPRO_OPC_JR,
+  TILEPRO_OPC_JRP,
+  TILEPRO_OPC_LB,
+  TILEPRO_OPC_LB_SN,
+  TILEPRO_OPC_LB_U,
+  TILEPRO_OPC_LB_U_SN,
+  TILEPRO_OPC_LBADD,
+  TILEPRO_OPC_LBADD_SN,
+  TILEPRO_OPC_LBADD_U,
+  TILEPRO_OPC_LBADD_U_SN,
+  TILEPRO_OPC_LH,
+  TILEPRO_OPC_LH_SN,
+  TILEPRO_OPC_LH_U,
+  TILEPRO_OPC_LH_U_SN,
+  TILEPRO_OPC_LHADD,
+  TILEPRO_OPC_LHADD_SN,
+  TILEPRO_OPC_LHADD_U,
+  TILEPRO_OPC_LHADD_U_SN,
+  TILEPRO_OPC_LNK,
+  TILEPRO_OPC_LNK_SN,
+  TILEPRO_OPC_LW,
+  TILEPRO_OPC_LW_SN,
+  TILEPRO_OPC_LW_NA,
+  TILEPRO_OPC_LW_NA_SN,
+  TILEPRO_OPC_LWADD,
+  TILEPRO_OPC_LWADD_SN,
+  TILEPRO_OPC_LWADD_NA,
+  TILEPRO_OPC_LWADD_NA_SN,
+  TILEPRO_OPC_MAXB_U,
+  TILEPRO_OPC_MAXB_U_SN,
+  TILEPRO_OPC_MAXH,
+  TILEPRO_OPC_MAXH_SN,
+  TILEPRO_OPC_MAXIB_U,
+  TILEPRO_OPC_MAXIB_U_SN,
+  TILEPRO_OPC_MAXIH,
+  TILEPRO_OPC_MAXIH_SN,
+  TILEPRO_OPC_MF,
+  TILEPRO_OPC_MFSPR,
+  TILEPRO_OPC_MINB_U,
+  TILEPRO_OPC_MINB_U_SN,
+  TILEPRO_OPC_MINH,
+  TILEPRO_OPC_MINH_SN,
+  TILEPRO_OPC_MINIB_U,
+  TILEPRO_OPC_MINIB_U_SN,
+  TILEPRO_OPC_MINIH,
+  TILEPRO_OPC_MINIH_SN,
+  TILEPRO_OPC_MM,
+  TILEPRO_OPC_MNZ,
+  TILEPRO_OPC_MNZ_SN,
+  TILEPRO_OPC_MNZB,
+  TILEPRO_OPC_MNZB_SN,
+  TILEPRO_OPC_MNZH,
+  TILEPRO_OPC_MNZH_SN,
+  TILEPRO_OPC_MTSPR,
+  TILEPRO_OPC_MULHH_SS,
+  TILEPRO_OPC_MULHH_SS_SN,
+  TILEPRO_OPC_MULHH_SU,
+  TILEPRO_OPC_MULHH_SU_SN,
+  TILEPRO_OPC_MULHH_UU,
+  TILEPRO_OPC_MULHH_UU_SN,
+  TILEPRO_OPC_MULHHA_SS,
+  TILEPRO_OPC_MULHHA_SS_SN,
+  TILEPRO_OPC_MULHHA_SU,
+  TILEPRO_OPC_MULHHA_SU_SN,
+  TILEPRO_OPC_MULHHA_UU,
+  TILEPRO_OPC_MULHHA_UU_SN,
+  TILEPRO_OPC_MULHHSA_UU,
+  TILEPRO_OPC_MULHHSA_UU_SN,
+  TILEPRO_OPC_MULHL_SS,
+  TILEPRO_OPC_MULHL_SS_SN,
+  TILEPRO_OPC_MULHL_SU,
+  TILEPRO_OPC_MULHL_SU_SN,
+  TILEPRO_OPC_MULHL_US,
+  TILEPRO_OPC_MULHL_US_SN,
+  TILEPRO_OPC_MULHL_UU,
+  TILEPRO_OPC_MULHL_UU_SN,
+  TILEPRO_OPC_MULHLA_SS,
+  TILEPRO_OPC_MULHLA_SS_SN,
+  TILEPRO_OPC_MULHLA_SU,
+  TILEPRO_OPC_MULHLA_SU_SN,
+  TILEPRO_OPC_MULHLA_US,
+  TILEPRO_OPC_MULHLA_US_SN,
+  TILEPRO_OPC_MULHLA_UU,
+  TILEPRO_OPC_MULHLA_UU_SN,
+  TILEPRO_OPC_MULHLSA_UU,
+  TILEPRO_OPC_MULHLSA_UU_SN,
+  TILEPRO_OPC_MULLL_SS,
+  TILEPRO_OPC_MULLL_SS_SN,
+  TILEPRO_OPC_MULLL_SU,
+  TILEPRO_OPC_MULLL_SU_SN,
+  TILEPRO_OPC_MULLL_UU,
+  TILEPRO_OPC_MULLL_UU_SN,
+  TILEPRO_OPC_MULLLA_SS,
+  TILEPRO_OPC_MULLLA_SS_SN,
+  TILEPRO_OPC_MULLLA_SU,
+  TILEPRO_OPC_MULLLA_SU_SN,
+  TILEPRO_OPC_MULLLA_UU,
+  TILEPRO_OPC_MULLLA_UU_SN,
+  TILEPRO_OPC_MULLLSA_UU,
+  TILEPRO_OPC_MULLLSA_UU_SN,
+  TILEPRO_OPC_MVNZ,
+  TILEPRO_OPC_MVNZ_SN,
+  TILEPRO_OPC_MVZ,
+  TILEPRO_OPC_MVZ_SN,
+  TILEPRO_OPC_MZ,
+  TILEPRO_OPC_MZ_SN,
+  TILEPRO_OPC_MZB,
+  TILEPRO_OPC_MZB_SN,
+  TILEPRO_OPC_MZH,
+  TILEPRO_OPC_MZH_SN,
+  TILEPRO_OPC_NAP,
+  TILEPRO_OPC_NOP,
+  TILEPRO_OPC_NOR,
+  TILEPRO_OPC_NOR_SN,
+  TILEPRO_OPC_OR,
+  TILEPRO_OPC_OR_SN,
+  TILEPRO_OPC_ORI,
+  TILEPRO_OPC_ORI_SN,
+  TILEPRO_OPC_PACKBS_U,
+  TILEPRO_OPC_PACKBS_U_SN,
+  TILEPRO_OPC_PACKHB,
+  TILEPRO_OPC_PACKHB_SN,
+  TILEPRO_OPC_PACKHS,
+  TILEPRO_OPC_PACKHS_SN,
+  TILEPRO_OPC_PACKLB,
+  TILEPRO_OPC_PACKLB_SN,
+  TILEPRO_OPC_PCNT,
+  TILEPRO_OPC_PCNT_SN,
+  TILEPRO_OPC_RL,
+  TILEPRO_OPC_RL_SN,
+  TILEPRO_OPC_RLI,
+  TILEPRO_OPC_RLI_SN,
+  TILEPRO_OPC_S1A,
+  TILEPRO_OPC_S1A_SN,
+  TILEPRO_OPC_S2A,
+  TILEPRO_OPC_S2A_SN,
+  TILEPRO_OPC_S3A,
+  TILEPRO_OPC_S3A_SN,
+  TILEPRO_OPC_SADAB_U,
+  TILEPRO_OPC_SADAB_U_SN,
+  TILEPRO_OPC_SADAH,
+  TILEPRO_OPC_SADAH_SN,
+  TILEPRO_OPC_SADAH_U,
+  TILEPRO_OPC_SADAH_U_SN,
+  TILEPRO_OPC_SADB_U,
+  TILEPRO_OPC_SADB_U_SN,
+  TILEPRO_OPC_SADH,
+  TILEPRO_OPC_SADH_SN,
+  TILEPRO_OPC_SADH_U,
+  TILEPRO_OPC_SADH_U_SN,
+  TILEPRO_OPC_SB,
+  TILEPRO_OPC_SBADD,
+  TILEPRO_OPC_SEQ,
+  TILEPRO_OPC_SEQ_SN,
+  TILEPRO_OPC_SEQB,
+  TILEPRO_OPC_SEQB_SN,
+  TILEPRO_OPC_SEQH,
+  TILEPRO_OPC_SEQH_SN,
+  TILEPRO_OPC_SEQI,
+  TILEPRO_OPC_SEQI_SN,
+  TILEPRO_OPC_SEQIB,
+  TILEPRO_OPC_SEQIB_SN,
+  TILEPRO_OPC_SEQIH,
+  TILEPRO_OPC_SEQIH_SN,
+  TILEPRO_OPC_SH,
+  TILEPRO_OPC_SHADD,
+  TILEPRO_OPC_SHL,
+  TILEPRO_OPC_SHL_SN,
+  TILEPRO_OPC_SHLB,
+  TILEPRO_OPC_SHLB_SN,
+  TILEPRO_OPC_SHLH,
+  TILEPRO_OPC_SHLH_SN,
+  TILEPRO_OPC_SHLI,
+  TILEPRO_OPC_SHLI_SN,
+  TILEPRO_OPC_SHLIB,
+  TILEPRO_OPC_SHLIB_SN,
+  TILEPRO_OPC_SHLIH,
+  TILEPRO_OPC_SHLIH_SN,
+  TILEPRO_OPC_SHR,
+  TILEPRO_OPC_SHR_SN,
+  TILEPRO_OPC_SHRB,
+  TILEPRO_OPC_SHRB_SN,
+  TILEPRO_OPC_SHRH,
+  TILEPRO_OPC_SHRH_SN,
+  TILEPRO_OPC_SHRI,
+  TILEPRO_OPC_SHRI_SN,
+  TILEPRO_OPC_SHRIB,
+  TILEPRO_OPC_SHRIB_SN,
+  TILEPRO_OPC_SHRIH,
+  TILEPRO_OPC_SHRIH_SN,
+  TILEPRO_OPC_SLT,
+  TILEPRO_OPC_SLT_SN,
+  TILEPRO_OPC_SLT_U,
+  TILEPRO_OPC_SLT_U_SN,
+  TILEPRO_OPC_SLTB,
+  TILEPRO_OPC_SLTB_SN,
+  TILEPRO_OPC_SLTB_U,
+  TILEPRO_OPC_SLTB_U_SN,
+  TILEPRO_OPC_SLTE,
+  TILEPRO_OPC_SLTE_SN,
+  TILEPRO_OPC_SLTE_U,
+  TILEPRO_OPC_SLTE_U_SN,
+  TILEPRO_OPC_SLTEB,
+  TILEPRO_OPC_SLTEB_SN,
+  TILEPRO_OPC_SLTEB_U,
+  TILEPRO_OPC_SLTEB_U_SN,
+  TILEPRO_OPC_SLTEH,
+  TILEPRO_OPC_SLTEH_SN,
+  TILEPRO_OPC_SLTEH_U,
+  TILEPRO_OPC_SLTEH_U_SN,
+  TILEPRO_OPC_SLTH,
+  TILEPRO_OPC_SLTH_SN,
+  TILEPRO_OPC_SLTH_U,
+  TILEPRO_OPC_SLTH_U_SN,
+  TILEPRO_OPC_SLTI,
+  TILEPRO_OPC_SLTI_SN,
+  TILEPRO_OPC_SLTI_U,
+  TILEPRO_OPC_SLTI_U_SN,
+  TILEPRO_OPC_SLTIB,
+  TILEPRO_OPC_SLTIB_SN,
+  TILEPRO_OPC_SLTIB_U,
+  TILEPRO_OPC_SLTIB_U_SN,
+  TILEPRO_OPC_SLTIH,
+  TILEPRO_OPC_SLTIH_SN,
+  TILEPRO_OPC_SLTIH_U,
+  TILEPRO_OPC_SLTIH_U_SN,
+  TILEPRO_OPC_SNE,
+  TILEPRO_OPC_SNE_SN,
+  TILEPRO_OPC_SNEB,
+  TILEPRO_OPC_SNEB_SN,
+  TILEPRO_OPC_SNEH,
+  TILEPRO_OPC_SNEH_SN,
+  TILEPRO_OPC_SRA,
+  TILEPRO_OPC_SRA_SN,
+  TILEPRO_OPC_SRAB,
+  TILEPRO_OPC_SRAB_SN,
+  TILEPRO_OPC_SRAH,
+  TILEPRO_OPC_SRAH_SN,
+  TILEPRO_OPC_SRAI,
+  TILEPRO_OPC_SRAI_SN,
+  TILEPRO_OPC_SRAIB,
+  TILEPRO_OPC_SRAIB_SN,
+  TILEPRO_OPC_SRAIH,
+  TILEPRO_OPC_SRAIH_SN,
+  TILEPRO_OPC_SUB,
+  TILEPRO_OPC_SUB_SN,
+  TILEPRO_OPC_SUBB,
+  TILEPRO_OPC_SUBB_SN,
+  TILEPRO_OPC_SUBBS_U,
+  TILEPRO_OPC_SUBBS_U_SN,
+  TILEPRO_OPC_SUBH,
+  TILEPRO_OPC_SUBH_SN,
+  TILEPRO_OPC_SUBHS,
+  TILEPRO_OPC_SUBHS_SN,
+  TILEPRO_OPC_SUBS,
+  TILEPRO_OPC_SUBS_SN,
+  TILEPRO_OPC_SW,
+  TILEPRO_OPC_SWADD,
+  TILEPRO_OPC_SWINT0,
+  TILEPRO_OPC_SWINT1,
+  TILEPRO_OPC_SWINT2,
+  TILEPRO_OPC_SWINT3,
+  TILEPRO_OPC_TBLIDXB0,
+  TILEPRO_OPC_TBLIDXB0_SN,
+  TILEPRO_OPC_TBLIDXB1,
+  TILEPRO_OPC_TBLIDXB1_SN,
+  TILEPRO_OPC_TBLIDXB2,
+  TILEPRO_OPC_TBLIDXB2_SN,
+  TILEPRO_OPC_TBLIDXB3,
+  TILEPRO_OPC_TBLIDXB3_SN,
+  TILEPRO_OPC_TNS,
+  TILEPRO_OPC_TNS_SN,
+  TILEPRO_OPC_WH64,
+  TILEPRO_OPC_XOR,
+  TILEPRO_OPC_XOR_SN,
+  TILEPRO_OPC_XORI,
+  TILEPRO_OPC_XORI_SN,
+  TILEPRO_OPC_NONE
+} tilepro_mnemonic;
+
+
+
+
+typedef enum
+{
+  TILEPRO_PIPELINE_X0,
+  TILEPRO_PIPELINE_X1,
+  TILEPRO_PIPELINE_Y0,
+  TILEPRO_PIPELINE_Y1,
+  TILEPRO_PIPELINE_Y2,
+} tilepro_pipeline;
+
+#define tilepro_is_x_pipeline(p) ((int)(p) <= (int)TILEPRO_PIPELINE_X1)
+
+typedef enum
+{
+  TILEPRO_OP_TYPE_REGISTER,
+  TILEPRO_OP_TYPE_IMMEDIATE,
+  TILEPRO_OP_TYPE_ADDRESS,
+  TILEPRO_OP_TYPE_SPR
+} tilepro_operand_type;
+
+struct tilepro_operand
+{
+  /* Is this operand a register, immediate or address? */
+  tilepro_operand_type type;
+
+  /* The default relocation type for this operand.  */
+  signed int default_reloc : 16;
+
+  /* How many bits is this value? (used for range checking) */
+  unsigned int num_bits : 5;
+
+  /* Is the value signed? (used for range checking) */
+  unsigned int is_signed : 1;
+
+  /* Is this operand a source register? */
+  unsigned int is_src_reg : 1;
+
+  /* Is this operand written? (i.e. is it a destination register) */
+  unsigned int is_dest_reg : 1;
+
+  /* Is this operand PC-relative? */
+  unsigned int is_pc_relative : 1;
+
+  /* By how many bits do we right shift the value before inserting? */
+  unsigned int rightshift : 2;
+
+  /* Return the bits for this operand to be ORed into an existing bundle. */
+  tilepro_bundle_bits (*insert) (int op);
+
+  /* Extract this operand and return it. */
+  unsigned int (*extract) (tilepro_bundle_bits bundle);
+};
+
+
+extern const struct tilepro_operand tilepro_operands[];
+
+/* One finite-state machine per pipe for rapid instruction decoding. */
+extern const unsigned short * const
+tilepro_bundle_decoder_fsms[TILEPRO_NUM_PIPELINE_ENCODINGS];
+
+
+struct tilepro_opcode
+{
+  /* The opcode mnemonic, e.g. "add" */
+  const char *name;
+
+  /* The enum value for this mnemonic. */
+  tilepro_mnemonic mnemonic;
+
+  /* A bit mask of which of the five pipes this instruction
+     is compatible with:
+     X0  0x01
+     X1  0x02
+     Y0  0x04
+     Y1  0x08
+     Y2  0x10 */
+  unsigned char pipes;
+
+  /* How many operands are there? */
+  unsigned char num_operands;
+
+  /* Which register does this write implicitly, or TREG_ZERO if none? */
+  unsigned char implicitly_written_register;
+
+  /* Can this be bundled with other instructions (almost always true). */
+  unsigned char can_bundle;
+
+  /* The description of the operands. Each of these is an
+   * index into the tilepro_operands[] table. */
+  unsigned char operands[TILEPRO_NUM_PIPELINE_ENCODINGS][TILEPRO_MAX_OPERANDS];
+
+};
+
+extern const struct tilepro_opcode tilepro_opcodes[];
+
+
+/* Used for non-textual disassembly into structs. */
+struct tilepro_decoded_instruction
+{
+  const struct tilepro_opcode *opcode;
+  const struct tilepro_operand *operands[TILEPRO_MAX_OPERANDS];
+  int operand_values[TILEPRO_MAX_OPERANDS];
+};
+
+
+/* Disassemble a bundle into a struct for machine processing. */
+extern int parse_insn_tilepro(tilepro_bundle_bits bits,
+                              unsigned int pc,
+                              struct tilepro_decoded_instruction
+                              decoded[TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE]);
+
+
+/* Given a set of bundle bits and a specific pipe, returns which
+ * instruction the bundle contains in that pipe.
+ */
+extern const struct tilepro_opcode *
+find_opcode(tilepro_bundle_bits bits, tilepro_pipeline pipe);
+
+
+
+#endif /* opcode_tilepro_h */
diff -druN linux-libre-3.1-gnu/arch/tile/include/asm/tile-desc_64.h linux-libre-3.2-gnu/arch/tile/include/asm/tile-desc_64.h
--- linux-libre-3.1-gnu/arch/tile/include/asm/tile-desc_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/tile/include/asm/tile-desc_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,483 @@
+/* TILE-Gx opcode information.
+ *
+ * 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 opcode_tile_h
+#define opcode_tile_h
+
+#include <arch/opcode.h>
+
+
+enum
+{
+  TILEGX_MAX_OPERANDS = 4 /* bfexts */
+};
+
+typedef enum
+{
+  TILEGX_OPC_BPT,
+  TILEGX_OPC_INFO,
+  TILEGX_OPC_INFOL,
+  TILEGX_OPC_MOVE,
+  TILEGX_OPC_MOVEI,
+  TILEGX_OPC_MOVELI,
+  TILEGX_OPC_PREFETCH,
+  TILEGX_OPC_PREFETCH_ADD_L1,
+  TILEGX_OPC_PREFETCH_ADD_L1_FAULT,
+  TILEGX_OPC_PREFETCH_ADD_L2,
+  TILEGX_OPC_PREFETCH_ADD_L2_FAULT,
+  TILEGX_OPC_PREFETCH_ADD_L3,
+  TILEGX_OPC_PREFETCH_ADD_L3_FAULT,
+  TILEGX_OPC_PREFETCH_L1,
+  TILEGX_OPC_PREFETCH_L1_FAULT,
+  TILEGX_OPC_PREFETCH_L2,
+  TILEGX_OPC_PREFETCH_L2_FAULT,
+  TILEGX_OPC_PREFETCH_L3,
+  TILEGX_OPC_PREFETCH_L3_FAULT,
+  TILEGX_OPC_RAISE,
+  TILEGX_OPC_ADD,
+  TILEGX_OPC_ADDI,
+  TILEGX_OPC_ADDLI,
+  TILEGX_OPC_ADDX,
+  TILEGX_OPC_ADDXI,
+  TILEGX_OPC_ADDXLI,
+  TILEGX_OPC_ADDXSC,
+  TILEGX_OPC_AND,
+  TILEGX_OPC_ANDI,
+  TILEGX_OPC_BEQZ,
+  TILEGX_OPC_BEQZT,
+  TILEGX_OPC_BFEXTS,
+  TILEGX_OPC_BFEXTU,
+  TILEGX_OPC_BFINS,
+  TILEGX_OPC_BGEZ,
+  TILEGX_OPC_BGEZT,
+  TILEGX_OPC_BGTZ,
+  TILEGX_OPC_BGTZT,
+  TILEGX_OPC_BLBC,
+  TILEGX_OPC_BLBCT,
+  TILEGX_OPC_BLBS,
+  TILEGX_OPC_BLBST,
+  TILEGX_OPC_BLEZ,
+  TILEGX_OPC_BLEZT,
+  TILEGX_OPC_BLTZ,
+  TILEGX_OPC_BLTZT,
+  TILEGX_OPC_BNEZ,
+  TILEGX_OPC_BNEZT,
+  TILEGX_OPC_CLZ,
+  TILEGX_OPC_CMOVEQZ,
+  TILEGX_OPC_CMOVNEZ,
+  TILEGX_OPC_CMPEQ,
+  TILEGX_OPC_CMPEQI,
+  TILEGX_OPC_CMPEXCH,
+  TILEGX_OPC_CMPEXCH4,
+  TILEGX_OPC_CMPLES,
+  TILEGX_OPC_CMPLEU,
+  TILEGX_OPC_CMPLTS,
+  TILEGX_OPC_CMPLTSI,
+  TILEGX_OPC_CMPLTU,
+  TILEGX_OPC_CMPLTUI,
+  TILEGX_OPC_CMPNE,
+  TILEGX_OPC_CMUL,
+  TILEGX_OPC_CMULA,
+  TILEGX_OPC_CMULAF,
+  TILEGX_OPC_CMULF,
+  TILEGX_OPC_CMULFR,
+  TILEGX_OPC_CMULH,
+  TILEGX_OPC_CMULHR,
+  TILEGX_OPC_CRC32_32,
+  TILEGX_OPC_CRC32_8,
+  TILEGX_OPC_CTZ,
+  TILEGX_OPC_DBLALIGN,
+  TILEGX_OPC_DBLALIGN2,
+  TILEGX_OPC_DBLALIGN4,
+  TILEGX_OPC_DBLALIGN6,
+  TILEGX_OPC_DRAIN,
+  TILEGX_OPC_DTLBPR,
+  TILEGX_OPC_EXCH,
+  TILEGX_OPC_EXCH4,
+  TILEGX_OPC_FDOUBLE_ADD_FLAGS,
+  TILEGX_OPC_FDOUBLE_ADDSUB,
+  TILEGX_OPC_FDOUBLE_MUL_FLAGS,
+  TILEGX_OPC_FDOUBLE_PACK1,
+  TILEGX_OPC_FDOUBLE_PACK2,
+  TILEGX_OPC_FDOUBLE_SUB_FLAGS,
+  TILEGX_OPC_FDOUBLE_UNPACK_MAX,
+  TILEGX_OPC_FDOUBLE_UNPACK_MIN,
+  TILEGX_OPC_FETCHADD,
+  TILEGX_OPC_FETCHADD4,
+  TILEGX_OPC_FETCHADDGEZ,
+  TILEGX_OPC_FETCHADDGEZ4,
+  TILEGX_OPC_FETCHAND,
+  TILEGX_OPC_FETCHAND4,
+  TILEGX_OPC_FETCHOR,
+  TILEGX_OPC_FETCHOR4,
+  TILEGX_OPC_FINV,
+  TILEGX_OPC_FLUSH,
+  TILEGX_OPC_FLUSHWB,
+  TILEGX_OPC_FNOP,
+  TILEGX_OPC_FSINGLE_ADD1,
+  TILEGX_OPC_FSINGLE_ADDSUB2,
+  TILEGX_OPC_FSINGLE_MUL1,
+  TILEGX_OPC_FSINGLE_MUL2,
+  TILEGX_OPC_FSINGLE_PACK1,
+  TILEGX_OPC_FSINGLE_PACK2,
+  TILEGX_OPC_FSINGLE_SUB1,
+  TILEGX_OPC_ICOH,
+  TILEGX_OPC_ILL,
+  TILEGX_OPC_INV,
+  TILEGX_OPC_IRET,
+  TILEGX_OPC_J,
+  TILEGX_OPC_JAL,
+  TILEGX_OPC_JALR,
+  TILEGX_OPC_JALRP,
+  TILEGX_OPC_JR,
+  TILEGX_OPC_JRP,
+  TILEGX_OPC_LD,
+  TILEGX_OPC_LD1S,
+  TILEGX_OPC_LD1S_ADD,
+  TILEGX_OPC_LD1U,
+  TILEGX_OPC_LD1U_ADD,
+  TILEGX_OPC_LD2S,
+  TILEGX_OPC_LD2S_ADD,
+  TILEGX_OPC_LD2U,
+  TILEGX_OPC_LD2U_ADD,
+  TILEGX_OPC_LD4S,
+  TILEGX_OPC_LD4S_ADD,
+  TILEGX_OPC_LD4U,
+  TILEGX_OPC_LD4U_ADD,
+  TILEGX_OPC_LD_ADD,
+  TILEGX_OPC_LDNA,
+  TILEGX_OPC_LDNA_ADD,
+  TILEGX_OPC_LDNT,
+  TILEGX_OPC_LDNT1S,
+  TILEGX_OPC_LDNT1S_ADD,
+  TILEGX_OPC_LDNT1U,
+  TILEGX_OPC_LDNT1U_ADD,
+  TILEGX_OPC_LDNT2S,
+  TILEGX_OPC_LDNT2S_ADD,
+  TILEGX_OPC_LDNT2U,
+  TILEGX_OPC_LDNT2U_ADD,
+  TILEGX_OPC_LDNT4S,
+  TILEGX_OPC_LDNT4S_ADD,
+  TILEGX_OPC_LDNT4U,
+  TILEGX_OPC_LDNT4U_ADD,
+  TILEGX_OPC_LDNT_ADD,
+  TILEGX_OPC_LNK,
+  TILEGX_OPC_MF,
+  TILEGX_OPC_MFSPR,
+  TILEGX_OPC_MM,
+  TILEGX_OPC_MNZ,
+  TILEGX_OPC_MTSPR,
+  TILEGX_OPC_MUL_HS_HS,
+  TILEGX_OPC_MUL_HS_HU,
+  TILEGX_OPC_MUL_HS_LS,
+  TILEGX_OPC_MUL_HS_LU,
+  TILEGX_OPC_MUL_HU_HU,
+  TILEGX_OPC_MUL_HU_LS,
+  TILEGX_OPC_MUL_HU_LU,
+  TILEGX_OPC_MUL_LS_LS,
+  TILEGX_OPC_MUL_LS_LU,
+  TILEGX_OPC_MUL_LU_LU,
+  TILEGX_OPC_MULA_HS_HS,
+  TILEGX_OPC_MULA_HS_HU,
+  TILEGX_OPC_MULA_HS_LS,
+  TILEGX_OPC_MULA_HS_LU,
+  TILEGX_OPC_MULA_HU_HU,
+  TILEGX_OPC_MULA_HU_LS,
+  TILEGX_OPC_MULA_HU_LU,
+  TILEGX_OPC_MULA_LS_LS,
+  TILEGX_OPC_MULA_LS_LU,
+  TILEGX_OPC_MULA_LU_LU,
+  TILEGX_OPC_MULAX,
+  TILEGX_OPC_MULX,
+  TILEGX_OPC_MZ,
+  TILEGX_OPC_NAP,
+  TILEGX_OPC_NOP,
+  TILEGX_OPC_NOR,
+  TILEGX_OPC_OR,
+  TILEGX_OPC_ORI,
+  TILEGX_OPC_PCNT,
+  TILEGX_OPC_REVBITS,
+  TILEGX_OPC_REVBYTES,
+  TILEGX_OPC_ROTL,
+  TILEGX_OPC_ROTLI,
+  TILEGX_OPC_SHL,
+  TILEGX_OPC_SHL16INSLI,
+  TILEGX_OPC_SHL1ADD,
+  TILEGX_OPC_SHL1ADDX,
+  TILEGX_OPC_SHL2ADD,
+  TILEGX_OPC_SHL2ADDX,
+  TILEGX_OPC_SHL3ADD,
+  TILEGX_OPC_SHL3ADDX,
+  TILEGX_OPC_SHLI,
+  TILEGX_OPC_SHLX,
+  TILEGX_OPC_SHLXI,
+  TILEGX_OPC_SHRS,
+  TILEGX_OPC_SHRSI,
+  TILEGX_OPC_SHRU,
+  TILEGX_OPC_SHRUI,
+  TILEGX_OPC_SHRUX,
+  TILEGX_OPC_SHRUXI,
+  TILEGX_OPC_SHUFFLEBYTES,
+  TILEGX_OPC_ST,
+  TILEGX_OPC_ST1,
+  TILEGX_OPC_ST1_ADD,
+  TILEGX_OPC_ST2,
+  TILEGX_OPC_ST2_ADD,
+  TILEGX_OPC_ST4,
+  TILEGX_OPC_ST4_ADD,
+  TILEGX_OPC_ST_ADD,
+  TILEGX_OPC_STNT,
+  TILEGX_OPC_STNT1,
+  TILEGX_OPC_STNT1_ADD,
+  TILEGX_OPC_STNT2,
+  TILEGX_OPC_STNT2_ADD,
+  TILEGX_OPC_STNT4,
+  TILEGX_OPC_STNT4_ADD,
+  TILEGX_OPC_STNT_ADD,
+  TILEGX_OPC_SUB,
+  TILEGX_OPC_SUBX,
+  TILEGX_OPC_SUBXSC,
+  TILEGX_OPC_SWINT0,
+  TILEGX_OPC_SWINT1,
+  TILEGX_OPC_SWINT2,
+  TILEGX_OPC_SWINT3,
+  TILEGX_OPC_TBLIDXB0,
+  TILEGX_OPC_TBLIDXB1,
+  TILEGX_OPC_TBLIDXB2,
+  TILEGX_OPC_TBLIDXB3,
+  TILEGX_OPC_V1ADD,
+  TILEGX_OPC_V1ADDI,
+  TILEGX_OPC_V1ADDUC,
+  TILEGX_OPC_V1ADIFFU,
+  TILEGX_OPC_V1AVGU,
+  TILEGX_OPC_V1CMPEQ,
+  TILEGX_OPC_V1CMPEQI,
+  TILEGX_OPC_V1CMPLES,
+  TILEGX_OPC_V1CMPLEU,
+  TILEGX_OPC_V1CMPLTS,
+  TILEGX_OPC_V1CMPLTSI,
+  TILEGX_OPC_V1CMPLTU,
+  TILEGX_OPC_V1CMPLTUI,
+  TILEGX_OPC_V1CMPNE,
+  TILEGX_OPC_V1DDOTPU,
+  TILEGX_OPC_V1DDOTPUA,
+  TILEGX_OPC_V1DDOTPUS,
+  TILEGX_OPC_V1DDOTPUSA,
+  TILEGX_OPC_V1DOTP,
+  TILEGX_OPC_V1DOTPA,
+  TILEGX_OPC_V1DOTPU,
+  TILEGX_OPC_V1DOTPUA,
+  TILEGX_OPC_V1DOTPUS,
+  TILEGX_OPC_V1DOTPUSA,
+  TILEGX_OPC_V1INT_H,
+  TILEGX_OPC_V1INT_L,
+  TILEGX_OPC_V1MAXU,
+  TILEGX_OPC_V1MAXUI,
+  TILEGX_OPC_V1MINU,
+  TILEGX_OPC_V1MINUI,
+  TILEGX_OPC_V1MNZ,
+  TILEGX_OPC_V1MULTU,
+  TILEGX_OPC_V1MULU,
+  TILEGX_OPC_V1MULUS,
+  TILEGX_OPC_V1MZ,
+  TILEGX_OPC_V1SADAU,
+  TILEGX_OPC_V1SADU,
+  TILEGX_OPC_V1SHL,
+  TILEGX_OPC_V1SHLI,
+  TILEGX_OPC_V1SHRS,
+  TILEGX_OPC_V1SHRSI,
+  TILEGX_OPC_V1SHRU,
+  TILEGX_OPC_V1SHRUI,
+  TILEGX_OPC_V1SUB,
+  TILEGX_OPC_V1SUBUC,
+  TILEGX_OPC_V2ADD,
+  TILEGX_OPC_V2ADDI,
+  TILEGX_OPC_V2ADDSC,
+  TILEGX_OPC_V2ADIFFS,
+  TILEGX_OPC_V2AVGS,
+  TILEGX_OPC_V2CMPEQ,
+  TILEGX_OPC_V2CMPEQI,
+  TILEGX_OPC_V2CMPLES,
+  TILEGX_OPC_V2CMPLEU,
+  TILEGX_OPC_V2CMPLTS,
+  TILEGX_OPC_V2CMPLTSI,
+  TILEGX_OPC_V2CMPLTU,
+  TILEGX_OPC_V2CMPLTUI,
+  TILEGX_OPC_V2CMPNE,
+  TILEGX_OPC_V2DOTP,
+  TILEGX_OPC_V2DOTPA,
+  TILEGX_OPC_V2INT_H,
+  TILEGX_OPC_V2INT_L,
+  TILEGX_OPC_V2MAXS,
+  TILEGX_OPC_V2MAXSI,
+  TILEGX_OPC_V2MINS,
+  TILEGX_OPC_V2MINSI,
+  TILEGX_OPC_V2MNZ,
+  TILEGX_OPC_V2MULFSC,
+  TILEGX_OPC_V2MULS,
+  TILEGX_OPC_V2MULTS,
+  TILEGX_OPC_V2MZ,
+  TILEGX_OPC_V2PACKH,
+  TILEGX_OPC_V2PACKL,
+  TILEGX_OPC_V2PACKUC,
+  TILEGX_OPC_V2SADAS,
+  TILEGX_OPC_V2SADAU,
+  TILEGX_OPC_V2SADS,
+  TILEGX_OPC_V2SADU,
+  TILEGX_OPC_V2SHL,
+  TILEGX_OPC_V2SHLI,
+  TILEGX_OPC_V2SHLSC,
+  TILEGX_OPC_V2SHRS,
+  TILEGX_OPC_V2SHRSI,
+  TILEGX_OPC_V2SHRU,
+  TILEGX_OPC_V2SHRUI,
+  TILEGX_OPC_V2SUB,
+  TILEGX_OPC_V2SUBSC,
+  TILEGX_OPC_V4ADD,
+  TILEGX_OPC_V4ADDSC,
+  TILEGX_OPC_V4INT_H,
+  TILEGX_OPC_V4INT_L,
+  TILEGX_OPC_V4PACKSC,
+  TILEGX_OPC_V4SHL,
+  TILEGX_OPC_V4SHLSC,
+  TILEGX_OPC_V4SHRS,
+  TILEGX_OPC_V4SHRU,
+  TILEGX_OPC_V4SUB,
+  TILEGX_OPC_V4SUBSC,
+  TILEGX_OPC_WH64,
+  TILEGX_OPC_XOR,
+  TILEGX_OPC_XORI,
+  TILEGX_OPC_NONE
+} tilegx_mnemonic;
+
+
+
+typedef enum
+{
+  TILEGX_PIPELINE_X0,
+  TILEGX_PIPELINE_X1,
+  TILEGX_PIPELINE_Y0,
+  TILEGX_PIPELINE_Y1,
+  TILEGX_PIPELINE_Y2,
+} tilegx_pipeline;
+
+#define tilegx_is_x_pipeline(p) ((int)(p) <= (int)TILEGX_PIPELINE_X1)
+
+typedef enum
+{
+  TILEGX_OP_TYPE_REGISTER,
+  TILEGX_OP_TYPE_IMMEDIATE,
+  TILEGX_OP_TYPE_ADDRESS,
+  TILEGX_OP_TYPE_SPR
+} tilegx_operand_type;
+
+struct tilegx_operand
+{
+  /* Is this operand a register, immediate or address? */
+  tilegx_operand_type type;
+
+  /* The default relocation type for this operand.  */
+  signed int default_reloc : 16;
+
+  /* How many bits is this value? (used for range checking) */
+  unsigned int num_bits : 5;
+
+  /* Is the value signed? (used for range checking) */
+  unsigned int is_signed : 1;
+
+  /* Is this operand a source register? */
+  unsigned int is_src_reg : 1;
+
+  /* Is this operand written? (i.e. is it a destination register) */
+  unsigned int is_dest_reg : 1;
+
+  /* Is this operand PC-relative? */
+  unsigned int is_pc_relative : 1;
+
+  /* By how many bits do we right shift the value before inserting? */
+  unsigned int rightshift : 2;
+
+  /* Return the bits for this operand to be ORed into an existing bundle. */
+  tilegx_bundle_bits (*insert) (int op);
+
+  /* Extract this operand and return it. */
+  unsigned int (*extract) (tilegx_bundle_bits bundle);
+};
+
+
+extern const struct tilegx_operand tilegx_operands[];
+
+/* One finite-state machine per pipe for rapid instruction decoding. */
+extern const unsigned short * const
+tilegx_bundle_decoder_fsms[TILEGX_NUM_PIPELINE_ENCODINGS];
+
+
+struct tilegx_opcode
+{
+  /* The opcode mnemonic, e.g. "add" */
+  const char *name;
+
+  /* The enum value for this mnemonic. */
+  tilegx_mnemonic mnemonic;
+
+  /* A bit mask of which of the five pipes this instruction
+     is compatible with:
+     X0  0x01
+     X1  0x02
+     Y0  0x04
+     Y1  0x08
+     Y2  0x10 */
+  unsigned char pipes;
+
+  /* How many operands are there? */
+  unsigned char num_operands;
+
+  /* Which register does this write implicitly, or TREG_ZERO if none? */
+  unsigned char implicitly_written_register;
+
+  /* Can this be bundled with other instructions (almost always true). */
+  unsigned char can_bundle;
+
+  /* The description of the operands. Each of these is an
+   * index into the tilegx_operands[] table. */
+  unsigned char operands[TILEGX_NUM_PIPELINE_ENCODINGS][TILEGX_MAX_OPERANDS];
+
+};
+
+extern const struct tilegx_opcode tilegx_opcodes[];
+
+/* Used for non-textual disassembly into structs. */
+struct tilegx_decoded_instruction
+{
+  const struct tilegx_opcode *opcode;
+  const struct tilegx_operand *operands[TILEGX_MAX_OPERANDS];
+  long long operand_values[TILEGX_MAX_OPERANDS];
+};
+
+
+/* Disassemble a bundle into a struct for machine processing. */
+extern int parse_insn_tilegx(tilegx_bundle_bits bits,
+                             unsigned long long pc,
+                             struct tilegx_decoded_instruction
+                             decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]);
+
+
+
+#endif /* opcode_tilegx_h */
diff -druN linux-libre-3.1-gnu/arch/tile/include/asm/tile-desc.h linux-libre-3.2-gnu/arch/tile/include/asm/tile-desc.h
--- linux-libre-3.1-gnu/arch/tile/include/asm/tile-desc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/tile/include/asm/tile-desc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+/*
+ * 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 __tilegx__
+#include <asm/tile-desc_32.h>
+#else
+#include <asm/tile-desc_64.h>
+#endif
diff -druN linux-libre-3.1-gnu/arch/tile/Kconfig linux-libre-3.2-gnu/arch/tile/Kconfig
--- linux-libre-3.1-gnu/arch/tile/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -46,9 +46,6 @@
 config SYS_SUPPORTS_HUGETLBFS
 	def_bool y
 
-config GENERIC_TIME
-	def_bool y
-
 config GENERIC_CLOCKEVENTS
 	def_bool y
 
diff -druN linux-libre-3.1-gnu/arch/tile/kernel/backtrace.c linux-libre-3.2-gnu/arch/tile/kernel/backtrace.c
--- linux-libre-3.1-gnu/arch/tile/kernel/backtrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/kernel/backtrace.c	2012-01-04 18:55:44.000000000 -0500
@@ -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
@@ -15,13 +15,11 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <asm/backtrace.h>
-#include <asm/opcode-tile.h>
+#include <asm/tile-desc.h>
 #include <arch/abi.h>
 
 #ifdef __tilegx__
-#define tile_bundle_bits tilegx_bundle_bits
 #define TILE_MAX_INSTRUCTIONS_PER_BUNDLE TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE
-#define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEGX_BUNDLE_ALIGNMENT_IN_BYTES
 #define tile_decoded_instruction tilegx_decoded_instruction
 #define tile_mnemonic tilegx_mnemonic
 #define parse_insn_tile parse_insn_tilegx
@@ -35,7 +33,18 @@
 #define OPCODE_STORE TILEGX_OPC_ST
 typedef long long bt_int_reg_t;
 #else
-#define OPCODE_STORE TILE_OPC_SW
+#define TILE_MAX_INSTRUCTIONS_PER_BUNDLE TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE
+#define tile_decoded_instruction tilepro_decoded_instruction
+#define tile_mnemonic tilepro_mnemonic
+#define parse_insn_tile parse_insn_tilepro
+#define TILE_OPC_IRET TILEPRO_OPC_IRET
+#define TILE_OPC_ADDI TILEPRO_OPC_ADDI
+#define TILE_OPC_ADDLI TILEPRO_OPC_ADDLI
+#define TILE_OPC_INFO TILEPRO_OPC_INFO
+#define TILE_OPC_INFOL TILEPRO_OPC_INFOL
+#define TILE_OPC_JRP TILEPRO_OPC_JRP
+#define TILE_OPC_MOVE TILEPRO_OPC_MOVE
+#define OPCODE_STORE TILEPRO_OPC_SW
 typedef int bt_int_reg_t;
 #endif
 
diff -druN linux-libre-3.1-gnu/arch/tile/kernel/irq.c linux-libre-3.2-gnu/arch/tile/kernel/irq.c
--- linux-libre-3.1-gnu/arch/tile/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -152,14 +152,13 @@
  * Remove an irq from the disabled mask.  If we're in an interrupt
  * context, defer enabling the HW interrupt until we leave.
  */
-void enable_percpu_irq(unsigned int irq)
+static void tile_irq_chip_enable(struct irq_data *d)
 {
-	get_cpu_var(irq_disable_mask) &= ~(1UL << irq);
+	get_cpu_var(irq_disable_mask) &= ~(1UL << d->irq);
 	if (__get_cpu_var(irq_depth) == 0)
-		unmask_irqs(1UL << irq);
+		unmask_irqs(1UL << d->irq);
 	put_cpu_var(irq_disable_mask);
 }
-EXPORT_SYMBOL(enable_percpu_irq);
 
 /*
  * Add an irq to the disabled mask.  We disable the HW interrupt
@@ -167,13 +166,12 @@
  * in an interrupt context, the return path is careful to avoid
  * unmasking a newly disabled interrupt.
  */
-void disable_percpu_irq(unsigned int irq)
+static void tile_irq_chip_disable(struct irq_data *d)
 {
-	get_cpu_var(irq_disable_mask) |= (1UL << irq);
-	mask_irqs(1UL << irq);
+	get_cpu_var(irq_disable_mask) |= (1UL << d->irq);
+	mask_irqs(1UL << d->irq);
 	put_cpu_var(irq_disable_mask);
 }
-EXPORT_SYMBOL(disable_percpu_irq);
 
 /* Mask an interrupt. */
 static void tile_irq_chip_mask(struct irq_data *d)
@@ -209,6 +207,8 @@
 
 static struct irq_chip tile_irq_chip = {
 	.name = "tile_irq_chip",
+	.irq_enable = tile_irq_chip_enable,
+	.irq_disable = tile_irq_chip_disable,
 	.irq_ack = tile_irq_chip_ack,
 	.irq_eoi = tile_irq_chip_eoi,
 	.irq_mask = tile_irq_chip_mask,
diff -druN linux-libre-3.1-gnu/arch/tile/kernel/module.c linux-libre-3.2-gnu/arch/tile/kernel/module.c
--- linux-libre-3.1-gnu/arch/tile/kernel/module.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/kernel/module.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,9 +20,9 @@
 #include <linux/fs.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <asm/opcode-tile.h>
 #include <asm/pgtable.h>
 #include <asm/homecache.h>
+#include <arch/opcode.h>
 
 #ifdef __tilegx__
 # define Elf_Rela Elf64_Rela
diff -druN linux-libre-3.1-gnu/arch/tile/kernel/pci.c linux-libre-3.2-gnu/arch/tile/kernel/pci.c
--- linux-libre-3.1-gnu/arch/tile/kernel/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/kernel/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
+#include <linux/export.h>
 
 #include <asm/processor.h>
 #include <asm/sections.h>
diff -druN linux-libre-3.1-gnu/arch/tile/kernel/pci-dma.c linux-libre-3.2-gnu/arch/tile/kernel/pci-dma.c
--- linux-libre-3.1-gnu/arch/tile/kernel/pci-dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/kernel/pci-dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 #include <asm/tlbflush.h>
 #include <asm/homecache.h>
 
diff -druN linux-libre-3.1-gnu/arch/tile/kernel/single_step.c linux-libre-3.2-gnu/arch/tile/kernel/single_step.c
--- linux-libre-3.1-gnu/arch/tile/kernel/single_step.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/kernel/single_step.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,9 +25,8 @@
 #include <linux/types.h>
 #include <linux/err.h>
 #include <asm/cacheflush.h>
-#include <asm/opcode-tile.h>
-#include <asm/opcode_constants.h>
 #include <arch/abi.h>
+#include <arch/opcode.h>
 
 #define signExtend17(val) sign_extend((val), 17)
 #define TILE_X1_MASK (0xffffffffULL << 31)
@@ -118,7 +117,7 @@
 	int val_reg, addr_reg, err, val;
 
 	/* Get address and value registers */
-	if (bundle & TILE_BUNDLE_Y_ENCODING_MASK) {
+	if (bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK) {
 		addr_reg = get_SrcA_Y2(bundle);
 		val_reg = get_SrcBDest_Y2(bundle);
 	} else if (mem_op == MEMOP_LOAD || mem_op == MEMOP_LOAD_POSTINCR) {
@@ -229,7 +228,7 @@
 	}
 	++unaligned_fixup_count;
 
-	if (bundle & TILE_BUNDLE_Y_ENCODING_MASK) {
+	if (bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK) {
 		/* Convert the Y2 instruction to a prefetch. */
 		bundle &= ~(create_SrcBDest_Y2(-1) |
 			    create_Opcode_Y2(-1));
@@ -389,7 +388,7 @@
 	state->branch_next_pc = 0;
 	state->update = 0;
 
-	if (!(bundle & TILE_BUNDLE_Y_ENCODING_MASK)) {
+	if (!(bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK)) {
 		/* two wide, check for control flow */
 		int opcode = get_Opcode_X1(bundle);
 
diff -druN linux-libre-3.1-gnu/arch/tile/kernel/sysfs.c linux-libre-3.2-gnu/arch/tile/kernel/sysfs.c
--- linux-libre-3.1-gnu/arch/tile/kernel/sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/kernel/sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/cpu.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
+#include <linux/stat.h>
 #include <hv/hypervisor.h>
 
 /* Return a string queried from the hypervisor, truncated to page size. */
diff -druN linux-libre-3.1-gnu/arch/tile/kernel/tile-desc_32.c linux-libre-3.2-gnu/arch/tile/kernel/tile-desc_32.c
--- linux-libre-3.1-gnu/arch/tile/kernel/tile-desc_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/kernel/tile-desc_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,23 @@
+/* TILEPro opcode information.
+ *
+ * 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.
+ *
+ *
+ *
+ *
+ *
+ */
+
 /* This define is BFD_RELOC_##x for real bfd, or -1 for everyone else. */
 #define BFD_RELOC(x) -1
 
@@ -6,1217 +26,1217 @@
 #define TREG_SN 56
 #define TREG_ZERO 63
 
-/* FIXME: Rename this. */
-#include <asm/opcode-tile.h>
-
 #include <linux/stddef.h>
+#include <asm/tile-desc.h>
 
-const struct tile_opcode tile_opcodes[395] =
+const struct tilepro_opcode tilepro_opcodes[395] =
 {
- { "bpt", TILE_OPC_BPT, 0x2, 0, TREG_ZERO, 0,
+ { "bpt", TILEPRO_OPC_BPT, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "info", TILE_OPC_INFO, 0xf, 1, TREG_ZERO, 1,
+  { "info", TILEPRO_OPC_INFO, 0xf, 1, TREG_ZERO, 1,
     { { 0 }, { 1 }, { 2 }, { 3 }, { 0, } },
   },
-  { "infol", TILE_OPC_INFOL, 0x3, 1, TREG_ZERO, 1,
+  { "infol", TILEPRO_OPC_INFOL, 0x3, 1, TREG_ZERO, 1,
     { { 4 }, { 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "j", TILE_OPC_J, 0x2, 1, TREG_ZERO, 1,
+  { "j", TILEPRO_OPC_J, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 6 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jal", TILE_OPC_JAL, 0x2, 1, TREG_LR, 1,
+  { "jal", TILEPRO_OPC_JAL, 0x2, 1, TREG_LR, 1,
     { { 0, }, { 6 }, { 0, }, { 0, }, { 0, } },
   },
-  { "move", TILE_OPC_MOVE, 0xf, 2, TREG_ZERO, 1,
+  { "move", TILEPRO_OPC_MOVE, 0xf, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 9, 10 }, { 11, 12 }, { 13, 14 }, { 0, } },
   },
-  { "move.sn", TILE_OPC_MOVE_SN, 0x3, 2, TREG_SN, 1,
+  { "move.sn", TILEPRO_OPC_MOVE_SN, 0x3, 2, TREG_SN, 1,
     { { 7, 8 }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "movei", TILE_OPC_MOVEI, 0xf, 2, TREG_ZERO, 1,
+  { "movei", TILEPRO_OPC_MOVEI, 0xf, 2, TREG_ZERO, 1,
     { { 7, 0 }, { 9, 1 }, { 11, 2 }, { 13, 3 }, { 0, } },
   },
-  { "movei.sn", TILE_OPC_MOVEI_SN, 0x3, 2, TREG_SN, 1,
+  { "movei.sn", TILEPRO_OPC_MOVEI_SN, 0x3, 2, TREG_SN, 1,
     { { 7, 0 }, { 9, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "moveli", TILE_OPC_MOVELI, 0x3, 2, TREG_ZERO, 1,
+  { "moveli", TILEPRO_OPC_MOVELI, 0x3, 2, TREG_ZERO, 1,
     { { 7, 4 }, { 9, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "moveli.sn", TILE_OPC_MOVELI_SN, 0x3, 2, TREG_SN, 1,
+  { "moveli.sn", TILEPRO_OPC_MOVELI_SN, 0x3, 2, TREG_SN, 1,
     { { 7, 4 }, { 9, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "movelis", TILE_OPC_MOVELIS, 0x3, 2, TREG_SN, 1,
+  { "movelis", TILEPRO_OPC_MOVELIS, 0x3, 2, TREG_SN, 1,
     { { 7, 4 }, { 9, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "prefetch", TILE_OPC_PREFETCH, 0x12, 1, TREG_ZERO, 1,
+  { "prefetch", TILEPRO_OPC_PREFETCH, 0x12, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 15 } },
   },
-  { "raise", TILE_OPC_RAISE, 0x2, 0, TREG_ZERO, 1,
+  { "raise", TILEPRO_OPC_RAISE, 0x2, 0, TREG_ZERO, 1,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "add", TILE_OPC_ADD, 0xf, 3, TREG_ZERO, 1,
+  { "add", TILEPRO_OPC_ADD, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "add.sn", TILE_OPC_ADD_SN, 0x3, 3, TREG_SN, 1,
+  { "add.sn", TILEPRO_OPC_ADD_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addb", TILE_OPC_ADDB, 0x3, 3, TREG_ZERO, 1,
+  { "addb", TILEPRO_OPC_ADDB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addb.sn", TILE_OPC_ADDB_SN, 0x3, 3, TREG_SN, 1,
+  { "addb.sn", TILEPRO_OPC_ADDB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addbs_u", TILE_OPC_ADDBS_U, 0x3, 3, TREG_ZERO, 1,
+  { "addbs_u", TILEPRO_OPC_ADDBS_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addbs_u.sn", TILE_OPC_ADDBS_U_SN, 0x3, 3, TREG_SN, 1,
+  { "addbs_u.sn", TILEPRO_OPC_ADDBS_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addh", TILE_OPC_ADDH, 0x3, 3, TREG_ZERO, 1,
+  { "addh", TILEPRO_OPC_ADDH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addh.sn", TILE_OPC_ADDH_SN, 0x3, 3, TREG_SN, 1,
+  { "addh.sn", TILEPRO_OPC_ADDH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addhs", TILE_OPC_ADDHS, 0x3, 3, TREG_ZERO, 1,
+  { "addhs", TILEPRO_OPC_ADDHS, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addhs.sn", TILE_OPC_ADDHS_SN, 0x3, 3, TREG_SN, 1,
+  { "addhs.sn", TILEPRO_OPC_ADDHS_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addi", TILE_OPC_ADDI, 0xf, 3, TREG_ZERO, 1,
+  { "addi", TILEPRO_OPC_ADDI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "addi.sn", TILE_OPC_ADDI_SN, 0x3, 3, TREG_SN, 1,
+  { "addi.sn", TILEPRO_OPC_ADDI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addib", TILE_OPC_ADDIB, 0x3, 3, TREG_ZERO, 1,
+  { "addib", TILEPRO_OPC_ADDIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addib.sn", TILE_OPC_ADDIB_SN, 0x3, 3, TREG_SN, 1,
+  { "addib.sn", TILEPRO_OPC_ADDIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addih", TILE_OPC_ADDIH, 0x3, 3, TREG_ZERO, 1,
+  { "addih", TILEPRO_OPC_ADDIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addih.sn", TILE_OPC_ADDIH_SN, 0x3, 3, TREG_SN, 1,
+  { "addih.sn", TILEPRO_OPC_ADDIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addli", TILE_OPC_ADDLI, 0x3, 3, TREG_ZERO, 1,
+  { "addli", TILEPRO_OPC_ADDLI, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 4 }, { 9, 10, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addli.sn", TILE_OPC_ADDLI_SN, 0x3, 3, TREG_SN, 1,
+  { "addli.sn", TILEPRO_OPC_ADDLI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 4 }, { 9, 10, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addlis", TILE_OPC_ADDLIS, 0x3, 3, TREG_SN, 1,
+  { "addlis", TILEPRO_OPC_ADDLIS, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 4 }, { 9, 10, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "adds", TILE_OPC_ADDS, 0x3, 3, TREG_ZERO, 1,
+  { "adds", TILEPRO_OPC_ADDS, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "adds.sn", TILE_OPC_ADDS_SN, 0x3, 3, TREG_SN, 1,
+  { "adds.sn", TILEPRO_OPC_ADDS_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "adiffb_u", TILE_OPC_ADIFFB_U, 0x1, 3, TREG_ZERO, 1,
+  { "adiffb_u", TILEPRO_OPC_ADIFFB_U, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "adiffb_u.sn", TILE_OPC_ADIFFB_U_SN, 0x1, 3, TREG_SN, 1,
+  { "adiffb_u.sn", TILEPRO_OPC_ADIFFB_U_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "adiffh", TILE_OPC_ADIFFH, 0x1, 3, TREG_ZERO, 1,
+  { "adiffh", TILEPRO_OPC_ADIFFH, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "adiffh.sn", TILE_OPC_ADIFFH_SN, 0x1, 3, TREG_SN, 1,
+  { "adiffh.sn", TILEPRO_OPC_ADIFFH_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "and", TILE_OPC_AND, 0xf, 3, TREG_ZERO, 1,
+  { "and", TILEPRO_OPC_AND, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "and.sn", TILE_OPC_AND_SN, 0x3, 3, TREG_SN, 1,
+  { "and.sn", TILEPRO_OPC_AND_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "andi", TILE_OPC_ANDI, 0xf, 3, TREG_ZERO, 1,
+  { "andi", TILEPRO_OPC_ANDI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "andi.sn", TILE_OPC_ANDI_SN, 0x3, 3, TREG_SN, 1,
+  { "andi.sn", TILEPRO_OPC_ANDI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "auli", TILE_OPC_AULI, 0x3, 3, TREG_ZERO, 1,
+  { "auli", TILEPRO_OPC_AULI, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 4 }, { 9, 10, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "avgb_u", TILE_OPC_AVGB_U, 0x1, 3, TREG_ZERO, 1,
+  { "avgb_u", TILEPRO_OPC_AVGB_U, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "avgb_u.sn", TILE_OPC_AVGB_U_SN, 0x1, 3, TREG_SN, 1,
+  { "avgb_u.sn", TILEPRO_OPC_AVGB_U_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "avgh", TILE_OPC_AVGH, 0x1, 3, TREG_ZERO, 1,
+  { "avgh", TILEPRO_OPC_AVGH, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "avgh.sn", TILE_OPC_AVGH_SN, 0x1, 3, TREG_SN, 1,
+  { "avgh.sn", TILEPRO_OPC_AVGH_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbns", TILE_OPC_BBNS, 0x2, 2, TREG_ZERO, 1,
+  { "bbns", TILEPRO_OPC_BBNS, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbns.sn", TILE_OPC_BBNS_SN, 0x2, 2, TREG_SN, 1,
+  { "bbns.sn", TILEPRO_OPC_BBNS_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbnst", TILE_OPC_BBNST, 0x2, 2, TREG_ZERO, 1,
+  { "bbnst", TILEPRO_OPC_BBNST, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbnst.sn", TILE_OPC_BBNST_SN, 0x2, 2, TREG_SN, 1,
+  { "bbnst.sn", TILEPRO_OPC_BBNST_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbs", TILE_OPC_BBS, 0x2, 2, TREG_ZERO, 1,
+  { "bbs", TILEPRO_OPC_BBS, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbs.sn", TILE_OPC_BBS_SN, 0x2, 2, TREG_SN, 1,
+  { "bbs.sn", TILEPRO_OPC_BBS_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbst", TILE_OPC_BBST, 0x2, 2, TREG_ZERO, 1,
+  { "bbst", TILEPRO_OPC_BBST, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbst.sn", TILE_OPC_BBST_SN, 0x2, 2, TREG_SN, 1,
+  { "bbst.sn", TILEPRO_OPC_BBST_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgez", TILE_OPC_BGEZ, 0x2, 2, TREG_ZERO, 1,
+  { "bgez", TILEPRO_OPC_BGEZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgez.sn", TILE_OPC_BGEZ_SN, 0x2, 2, TREG_SN, 1,
+  { "bgez.sn", TILEPRO_OPC_BGEZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgezt", TILE_OPC_BGEZT, 0x2, 2, TREG_ZERO, 1,
+  { "bgezt", TILEPRO_OPC_BGEZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgezt.sn", TILE_OPC_BGEZT_SN, 0x2, 2, TREG_SN, 1,
+  { "bgezt.sn", TILEPRO_OPC_BGEZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgz", TILE_OPC_BGZ, 0x2, 2, TREG_ZERO, 1,
+  { "bgz", TILEPRO_OPC_BGZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgz.sn", TILE_OPC_BGZ_SN, 0x2, 2, TREG_SN, 1,
+  { "bgz.sn", TILEPRO_OPC_BGZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgzt", TILE_OPC_BGZT, 0x2, 2, TREG_ZERO, 1,
+  { "bgzt", TILEPRO_OPC_BGZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgzt.sn", TILE_OPC_BGZT_SN, 0x2, 2, TREG_SN, 1,
+  { "bgzt.sn", TILEPRO_OPC_BGZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bitx", TILE_OPC_BITX, 0x5, 2, TREG_ZERO, 1,
+  { "bitx", TILEPRO_OPC_BITX, 0x5, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 0, }, { 11, 12 }, { 0, }, { 0, } },
   },
-  { "bitx.sn", TILE_OPC_BITX_SN, 0x1, 2, TREG_SN, 1,
+  { "bitx.sn", TILEPRO_OPC_BITX_SN, 0x1, 2, TREG_SN, 1,
     { { 7, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "blez", TILE_OPC_BLEZ, 0x2, 2, TREG_ZERO, 1,
+  { "blez", TILEPRO_OPC_BLEZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blez.sn", TILE_OPC_BLEZ_SN, 0x2, 2, TREG_SN, 1,
+  { "blez.sn", TILEPRO_OPC_BLEZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blezt", TILE_OPC_BLEZT, 0x2, 2, TREG_ZERO, 1,
+  { "blezt", TILEPRO_OPC_BLEZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blezt.sn", TILE_OPC_BLEZT_SN, 0x2, 2, TREG_SN, 1,
+  { "blezt.sn", TILEPRO_OPC_BLEZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blz", TILE_OPC_BLZ, 0x2, 2, TREG_ZERO, 1,
+  { "blz", TILEPRO_OPC_BLZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blz.sn", TILE_OPC_BLZ_SN, 0x2, 2, TREG_SN, 1,
+  { "blz.sn", TILEPRO_OPC_BLZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blzt", TILE_OPC_BLZT, 0x2, 2, TREG_ZERO, 1,
+  { "blzt", TILEPRO_OPC_BLZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blzt.sn", TILE_OPC_BLZT_SN, 0x2, 2, TREG_SN, 1,
+  { "blzt.sn", TILEPRO_OPC_BLZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bnz", TILE_OPC_BNZ, 0x2, 2, TREG_ZERO, 1,
+  { "bnz", TILEPRO_OPC_BNZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bnz.sn", TILE_OPC_BNZ_SN, 0x2, 2, TREG_SN, 1,
+  { "bnz.sn", TILEPRO_OPC_BNZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bnzt", TILE_OPC_BNZT, 0x2, 2, TREG_ZERO, 1,
+  { "bnzt", TILEPRO_OPC_BNZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bnzt.sn", TILE_OPC_BNZT_SN, 0x2, 2, TREG_SN, 1,
+  { "bnzt.sn", TILEPRO_OPC_BNZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bytex", TILE_OPC_BYTEX, 0x5, 2, TREG_ZERO, 1,
+  { "bytex", TILEPRO_OPC_BYTEX, 0x5, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 0, }, { 11, 12 }, { 0, }, { 0, } },
   },
-  { "bytex.sn", TILE_OPC_BYTEX_SN, 0x1, 2, TREG_SN, 1,
+  { "bytex.sn", TILEPRO_OPC_BYTEX_SN, 0x1, 2, TREG_SN, 1,
     { { 7, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "bz", TILE_OPC_BZ, 0x2, 2, TREG_ZERO, 1,
+  { "bz", TILEPRO_OPC_BZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bz.sn", TILE_OPC_BZ_SN, 0x2, 2, TREG_SN, 1,
+  { "bz.sn", TILEPRO_OPC_BZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bzt", TILE_OPC_BZT, 0x2, 2, TREG_ZERO, 1,
+  { "bzt", TILEPRO_OPC_BZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bzt.sn", TILE_OPC_BZT_SN, 0x2, 2, TREG_SN, 1,
+  { "bzt.sn", TILEPRO_OPC_BZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "clz", TILE_OPC_CLZ, 0x5, 2, TREG_ZERO, 1,
+  { "clz", TILEPRO_OPC_CLZ, 0x5, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 0, }, { 11, 12 }, { 0, }, { 0, } },
   },
-  { "clz.sn", TILE_OPC_CLZ_SN, 0x1, 2, TREG_SN, 1,
+  { "clz.sn", TILEPRO_OPC_CLZ_SN, 0x1, 2, TREG_SN, 1,
     { { 7, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "crc32_32", TILE_OPC_CRC32_32, 0x1, 3, TREG_ZERO, 1,
+  { "crc32_32", TILEPRO_OPC_CRC32_32, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "crc32_32.sn", TILE_OPC_CRC32_32_SN, 0x1, 3, TREG_SN, 1,
+  { "crc32_32.sn", TILEPRO_OPC_CRC32_32_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "crc32_8", TILE_OPC_CRC32_8, 0x1, 3, TREG_ZERO, 1,
+  { "crc32_8", TILEPRO_OPC_CRC32_8, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "crc32_8.sn", TILE_OPC_CRC32_8_SN, 0x1, 3, TREG_SN, 1,
+  { "crc32_8.sn", TILEPRO_OPC_CRC32_8_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "ctz", TILE_OPC_CTZ, 0x5, 2, TREG_ZERO, 1,
+  { "ctz", TILEPRO_OPC_CTZ, 0x5, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 0, }, { 11, 12 }, { 0, }, { 0, } },
   },
-  { "ctz.sn", TILE_OPC_CTZ_SN, 0x1, 2, TREG_SN, 1,
+  { "ctz.sn", TILEPRO_OPC_CTZ_SN, 0x1, 2, TREG_SN, 1,
     { { 7, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "drain", TILE_OPC_DRAIN, 0x2, 0, TREG_ZERO, 0,
+  { "drain", TILEPRO_OPC_DRAIN, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "dtlbpr", TILE_OPC_DTLBPR, 0x2, 1, TREG_ZERO, 1,
+  { "dtlbpr", TILEPRO_OPC_DTLBPR, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "dword_align", TILE_OPC_DWORD_ALIGN, 0x1, 3, TREG_ZERO, 1,
+  { "dword_align", TILEPRO_OPC_DWORD_ALIGN, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "dword_align.sn", TILE_OPC_DWORD_ALIGN_SN, 0x1, 3, TREG_SN, 1,
+  { "dword_align.sn", TILEPRO_OPC_DWORD_ALIGN_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "finv", TILE_OPC_FINV, 0x2, 1, TREG_ZERO, 1,
+  { "finv", TILEPRO_OPC_FINV, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "flush", TILE_OPC_FLUSH, 0x2, 1, TREG_ZERO, 1,
+  { "flush", TILEPRO_OPC_FLUSH, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "fnop", TILE_OPC_FNOP, 0xf, 0, TREG_ZERO, 1,
+  { "fnop", TILEPRO_OPC_FNOP, 0xf, 0, TREG_ZERO, 1,
     { {  }, {  }, {  }, {  }, { 0, } },
   },
-  { "icoh", TILE_OPC_ICOH, 0x2, 1, TREG_ZERO, 1,
+  { "icoh", TILEPRO_OPC_ICOH, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "ill", TILE_OPC_ILL, 0xa, 0, TREG_ZERO, 1,
+  { "ill", TILEPRO_OPC_ILL, 0xa, 0, TREG_ZERO, 1,
     { { 0, }, {  }, { 0, }, {  }, { 0, } },
   },
-  { "inthb", TILE_OPC_INTHB, 0x3, 3, TREG_ZERO, 1,
+  { "inthb", TILEPRO_OPC_INTHB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "inthb.sn", TILE_OPC_INTHB_SN, 0x3, 3, TREG_SN, 1,
+  { "inthb.sn", TILEPRO_OPC_INTHB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "inthh", TILE_OPC_INTHH, 0x3, 3, TREG_ZERO, 1,
+  { "inthh", TILEPRO_OPC_INTHH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "inthh.sn", TILE_OPC_INTHH_SN, 0x3, 3, TREG_SN, 1,
+  { "inthh.sn", TILEPRO_OPC_INTHH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "intlb", TILE_OPC_INTLB, 0x3, 3, TREG_ZERO, 1,
+  { "intlb", TILEPRO_OPC_INTLB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "intlb.sn", TILE_OPC_INTLB_SN, 0x3, 3, TREG_SN, 1,
+  { "intlb.sn", TILEPRO_OPC_INTLB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "intlh", TILE_OPC_INTLH, 0x3, 3, TREG_ZERO, 1,
+  { "intlh", TILEPRO_OPC_INTLH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "intlh.sn", TILE_OPC_INTLH_SN, 0x3, 3, TREG_SN, 1,
+  { "intlh.sn", TILEPRO_OPC_INTLH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "inv", TILE_OPC_INV, 0x2, 1, TREG_ZERO, 1,
+  { "inv", TILEPRO_OPC_INV, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "iret", TILE_OPC_IRET, 0x2, 0, TREG_ZERO, 1,
+  { "iret", TILEPRO_OPC_IRET, 0x2, 0, TREG_ZERO, 1,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "jalb", TILE_OPC_JALB, 0x2, 1, TREG_LR, 1,
+  { "jalb", TILEPRO_OPC_JALB, 0x2, 1, TREG_LR, 1,
     { { 0, }, { 22 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jalf", TILE_OPC_JALF, 0x2, 1, TREG_LR, 1,
+  { "jalf", TILEPRO_OPC_JALF, 0x2, 1, TREG_LR, 1,
     { { 0, }, { 22 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jalr", TILE_OPC_JALR, 0x2, 1, TREG_LR, 1,
+  { "jalr", TILEPRO_OPC_JALR, 0x2, 1, TREG_LR, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jalrp", TILE_OPC_JALRP, 0x2, 1, TREG_LR, 1,
+  { "jalrp", TILEPRO_OPC_JALRP, 0x2, 1, TREG_LR, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jb", TILE_OPC_JB, 0x2, 1, TREG_ZERO, 1,
+  { "jb", TILEPRO_OPC_JB, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 22 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jf", TILE_OPC_JF, 0x2, 1, TREG_ZERO, 1,
+  { "jf", TILEPRO_OPC_JF, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 22 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jr", TILE_OPC_JR, 0x2, 1, TREG_ZERO, 1,
+  { "jr", TILEPRO_OPC_JR, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jrp", TILE_OPC_JRP, 0x2, 1, TREG_ZERO, 1,
+  { "jrp", TILEPRO_OPC_JRP, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lb", TILE_OPC_LB, 0x12, 2, TREG_ZERO, 1,
+  { "lb", TILEPRO_OPC_LB, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 23, 15 } },
   },
-  { "lb.sn", TILE_OPC_LB_SN, 0x2, 2, TREG_SN, 1,
+  { "lb.sn", TILEPRO_OPC_LB_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lb_u", TILE_OPC_LB_U, 0x12, 2, TREG_ZERO, 1,
+  { "lb_u", TILEPRO_OPC_LB_U, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 23, 15 } },
   },
-  { "lb_u.sn", TILE_OPC_LB_U_SN, 0x2, 2, TREG_SN, 1,
+  { "lb_u.sn", TILEPRO_OPC_LB_U_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lbadd", TILE_OPC_LBADD, 0x2, 3, TREG_ZERO, 1,
+  { "lbadd", TILEPRO_OPC_LBADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lbadd.sn", TILE_OPC_LBADD_SN, 0x2, 3, TREG_SN, 1,
+  { "lbadd.sn", TILEPRO_OPC_LBADD_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lbadd_u", TILE_OPC_LBADD_U, 0x2, 3, TREG_ZERO, 1,
+  { "lbadd_u", TILEPRO_OPC_LBADD_U, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lbadd_u.sn", TILE_OPC_LBADD_U_SN, 0x2, 3, TREG_SN, 1,
+  { "lbadd_u.sn", TILEPRO_OPC_LBADD_U_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lh", TILE_OPC_LH, 0x12, 2, TREG_ZERO, 1,
+  { "lh", TILEPRO_OPC_LH, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 23, 15 } },
   },
-  { "lh.sn", TILE_OPC_LH_SN, 0x2, 2, TREG_SN, 1,
+  { "lh.sn", TILEPRO_OPC_LH_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lh_u", TILE_OPC_LH_U, 0x12, 2, TREG_ZERO, 1,
+  { "lh_u", TILEPRO_OPC_LH_U, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 23, 15 } },
   },
-  { "lh_u.sn", TILE_OPC_LH_U_SN, 0x2, 2, TREG_SN, 1,
+  { "lh_u.sn", TILEPRO_OPC_LH_U_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lhadd", TILE_OPC_LHADD, 0x2, 3, TREG_ZERO, 1,
+  { "lhadd", TILEPRO_OPC_LHADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lhadd.sn", TILE_OPC_LHADD_SN, 0x2, 3, TREG_SN, 1,
+  { "lhadd.sn", TILEPRO_OPC_LHADD_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lhadd_u", TILE_OPC_LHADD_U, 0x2, 3, TREG_ZERO, 1,
+  { "lhadd_u", TILEPRO_OPC_LHADD_U, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lhadd_u.sn", TILE_OPC_LHADD_U_SN, 0x2, 3, TREG_SN, 1,
+  { "lhadd_u.sn", TILEPRO_OPC_LHADD_U_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lnk", TILE_OPC_LNK, 0x2, 1, TREG_ZERO, 1,
+  { "lnk", TILEPRO_OPC_LNK, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lnk.sn", TILE_OPC_LNK_SN, 0x2, 1, TREG_SN, 1,
+  { "lnk.sn", TILEPRO_OPC_LNK_SN, 0x2, 1, TREG_SN, 1,
     { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lw", TILE_OPC_LW, 0x12, 2, TREG_ZERO, 1,
+  { "lw", TILEPRO_OPC_LW, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 23, 15 } },
   },
-  { "lw.sn", TILE_OPC_LW_SN, 0x2, 2, TREG_SN, 1,
+  { "lw.sn", TILEPRO_OPC_LW_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lw_na", TILE_OPC_LW_NA, 0x2, 2, TREG_ZERO, 1,
+  { "lw_na", TILEPRO_OPC_LW_NA, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lw_na.sn", TILE_OPC_LW_NA_SN, 0x2, 2, TREG_SN, 1,
+  { "lw_na.sn", TILEPRO_OPC_LW_NA_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lwadd", TILE_OPC_LWADD, 0x2, 3, TREG_ZERO, 1,
+  { "lwadd", TILEPRO_OPC_LWADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lwadd.sn", TILE_OPC_LWADD_SN, 0x2, 3, TREG_SN, 1,
+  { "lwadd.sn", TILEPRO_OPC_LWADD_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lwadd_na", TILE_OPC_LWADD_NA, 0x2, 3, TREG_ZERO, 1,
+  { "lwadd_na", TILEPRO_OPC_LWADD_NA, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lwadd_na.sn", TILE_OPC_LWADD_NA_SN, 0x2, 3, TREG_SN, 1,
+  { "lwadd_na.sn", TILEPRO_OPC_LWADD_NA_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxb_u", TILE_OPC_MAXB_U, 0x3, 3, TREG_ZERO, 1,
+  { "maxb_u", TILEPRO_OPC_MAXB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxb_u.sn", TILE_OPC_MAXB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "maxb_u.sn", TILEPRO_OPC_MAXB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxh", TILE_OPC_MAXH, 0x3, 3, TREG_ZERO, 1,
+  { "maxh", TILEPRO_OPC_MAXH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxh.sn", TILE_OPC_MAXH_SN, 0x3, 3, TREG_SN, 1,
+  { "maxh.sn", TILEPRO_OPC_MAXH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxib_u", TILE_OPC_MAXIB_U, 0x3, 3, TREG_ZERO, 1,
+  { "maxib_u", TILEPRO_OPC_MAXIB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxib_u.sn", TILE_OPC_MAXIB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "maxib_u.sn", TILEPRO_OPC_MAXIB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxih", TILE_OPC_MAXIH, 0x3, 3, TREG_ZERO, 1,
+  { "maxih", TILEPRO_OPC_MAXIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxih.sn", TILE_OPC_MAXIH_SN, 0x3, 3, TREG_SN, 1,
+  { "maxih.sn", TILEPRO_OPC_MAXIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mf", TILE_OPC_MF, 0x2, 0, TREG_ZERO, 1,
+  { "mf", TILEPRO_OPC_MF, 0x2, 0, TREG_ZERO, 1,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "mfspr", TILE_OPC_MFSPR, 0x2, 2, TREG_ZERO, 1,
+  { "mfspr", TILEPRO_OPC_MFSPR, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 25 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minb_u", TILE_OPC_MINB_U, 0x3, 3, TREG_ZERO, 1,
+  { "minb_u", TILEPRO_OPC_MINB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minb_u.sn", TILE_OPC_MINB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "minb_u.sn", TILEPRO_OPC_MINB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minh", TILE_OPC_MINH, 0x3, 3, TREG_ZERO, 1,
+  { "minh", TILEPRO_OPC_MINH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minh.sn", TILE_OPC_MINH_SN, 0x3, 3, TREG_SN, 1,
+  { "minh.sn", TILEPRO_OPC_MINH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minib_u", TILE_OPC_MINIB_U, 0x3, 3, TREG_ZERO, 1,
+  { "minib_u", TILEPRO_OPC_MINIB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minib_u.sn", TILE_OPC_MINIB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "minib_u.sn", TILEPRO_OPC_MINIB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minih", TILE_OPC_MINIH, 0x3, 3, TREG_ZERO, 1,
+  { "minih", TILEPRO_OPC_MINIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minih.sn", TILE_OPC_MINIH_SN, 0x3, 3, TREG_SN, 1,
+  { "minih.sn", TILEPRO_OPC_MINIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mm", TILE_OPC_MM, 0x3, 5, TREG_ZERO, 1,
+  { "mm", TILEPRO_OPC_MM, 0x3, 5, TREG_ZERO, 1,
     { { 7, 8, 16, 26, 27 }, { 9, 10, 17, 28, 29 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mnz", TILE_OPC_MNZ, 0xf, 3, TREG_ZERO, 1,
+  { "mnz", TILEPRO_OPC_MNZ, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "mnz.sn", TILE_OPC_MNZ_SN, 0x3, 3, TREG_SN, 1,
+  { "mnz.sn", TILEPRO_OPC_MNZ_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mnzb", TILE_OPC_MNZB, 0x3, 3, TREG_ZERO, 1,
+  { "mnzb", TILEPRO_OPC_MNZB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mnzb.sn", TILE_OPC_MNZB_SN, 0x3, 3, TREG_SN, 1,
+  { "mnzb.sn", TILEPRO_OPC_MNZB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mnzh", TILE_OPC_MNZH, 0x3, 3, TREG_ZERO, 1,
+  { "mnzh", TILEPRO_OPC_MNZH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mnzh.sn", TILE_OPC_MNZH_SN, 0x3, 3, TREG_SN, 1,
+  { "mnzh.sn", TILEPRO_OPC_MNZH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mtspr", TILE_OPC_MTSPR, 0x2, 2, TREG_ZERO, 1,
+  { "mtspr", TILEPRO_OPC_MTSPR, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 30, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhh_ss", TILE_OPC_MULHH_SS, 0x5, 3, TREG_ZERO, 1,
+  { "mulhh_ss", TILEPRO_OPC_MULHH_SS, 0x5, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 11, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulhh_ss.sn", TILE_OPC_MULHH_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhh_ss.sn", TILEPRO_OPC_MULHH_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhh_su", TILE_OPC_MULHH_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhh_su", TILEPRO_OPC_MULHH_SU, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhh_su.sn", TILE_OPC_MULHH_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhh_su.sn", TILEPRO_OPC_MULHH_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhh_uu", TILE_OPC_MULHH_UU, 0x5, 3, TREG_ZERO, 1,
+  { "mulhh_uu", TILEPRO_OPC_MULHH_UU, 0x5, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 11, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulhh_uu.sn", TILE_OPC_MULHH_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhh_uu.sn", TILEPRO_OPC_MULHH_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhha_ss", TILE_OPC_MULHHA_SS, 0x5, 3, TREG_ZERO, 1,
+  { "mulhha_ss", TILEPRO_OPC_MULHHA_SS, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulhha_ss.sn", TILE_OPC_MULHHA_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhha_ss.sn", TILEPRO_OPC_MULHHA_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhha_su", TILE_OPC_MULHHA_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhha_su", TILEPRO_OPC_MULHHA_SU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhha_su.sn", TILE_OPC_MULHHA_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhha_su.sn", TILEPRO_OPC_MULHHA_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhha_uu", TILE_OPC_MULHHA_UU, 0x5, 3, TREG_ZERO, 1,
+  { "mulhha_uu", TILEPRO_OPC_MULHHA_UU, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulhha_uu.sn", TILE_OPC_MULHHA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhha_uu.sn", TILEPRO_OPC_MULHHA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhhsa_uu", TILE_OPC_MULHHSA_UU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhhsa_uu", TILEPRO_OPC_MULHHSA_UU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhhsa_uu.sn", TILE_OPC_MULHHSA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhhsa_uu.sn", TILEPRO_OPC_MULHHSA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_ss", TILE_OPC_MULHL_SS, 0x1, 3, TREG_ZERO, 1,
+  { "mulhl_ss", TILEPRO_OPC_MULHL_SS, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_ss.sn", TILE_OPC_MULHL_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhl_ss.sn", TILEPRO_OPC_MULHL_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_su", TILE_OPC_MULHL_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhl_su", TILEPRO_OPC_MULHL_SU, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_su.sn", TILE_OPC_MULHL_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhl_su.sn", TILEPRO_OPC_MULHL_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_us", TILE_OPC_MULHL_US, 0x1, 3, TREG_ZERO, 1,
+  { "mulhl_us", TILEPRO_OPC_MULHL_US, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_us.sn", TILE_OPC_MULHL_US_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhl_us.sn", TILEPRO_OPC_MULHL_US_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_uu", TILE_OPC_MULHL_UU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhl_uu", TILEPRO_OPC_MULHL_UU, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_uu.sn", TILE_OPC_MULHL_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhl_uu.sn", TILEPRO_OPC_MULHL_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_ss", TILE_OPC_MULHLA_SS, 0x1, 3, TREG_ZERO, 1,
+  { "mulhla_ss", TILEPRO_OPC_MULHLA_SS, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_ss.sn", TILE_OPC_MULHLA_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhla_ss.sn", TILEPRO_OPC_MULHLA_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_su", TILE_OPC_MULHLA_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhla_su", TILEPRO_OPC_MULHLA_SU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_su.sn", TILE_OPC_MULHLA_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhla_su.sn", TILEPRO_OPC_MULHLA_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_us", TILE_OPC_MULHLA_US, 0x1, 3, TREG_ZERO, 1,
+  { "mulhla_us", TILEPRO_OPC_MULHLA_US, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_us.sn", TILE_OPC_MULHLA_US_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhla_us.sn", TILEPRO_OPC_MULHLA_US_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_uu", TILE_OPC_MULHLA_UU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhla_uu", TILEPRO_OPC_MULHLA_UU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_uu.sn", TILE_OPC_MULHLA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhla_uu.sn", TILEPRO_OPC_MULHLA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhlsa_uu", TILE_OPC_MULHLSA_UU, 0x5, 3, TREG_ZERO, 1,
+  { "mulhlsa_uu", TILEPRO_OPC_MULHLSA_UU, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulhlsa_uu.sn", TILE_OPC_MULHLSA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhlsa_uu.sn", TILEPRO_OPC_MULHLSA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulll_ss", TILE_OPC_MULLL_SS, 0x5, 3, TREG_ZERO, 1,
+  { "mulll_ss", TILEPRO_OPC_MULLL_SS, 0x5, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 11, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulll_ss.sn", TILE_OPC_MULLL_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mulll_ss.sn", TILEPRO_OPC_MULLL_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulll_su", TILE_OPC_MULLL_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mulll_su", TILEPRO_OPC_MULLL_SU, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulll_su.sn", TILE_OPC_MULLL_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulll_su.sn", TILEPRO_OPC_MULLL_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulll_uu", TILE_OPC_MULLL_UU, 0x5, 3, TREG_ZERO, 1,
+  { "mulll_uu", TILEPRO_OPC_MULLL_UU, 0x5, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 11, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulll_uu.sn", TILE_OPC_MULLL_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulll_uu.sn", TILEPRO_OPC_MULLL_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mullla_ss", TILE_OPC_MULLLA_SS, 0x5, 3, TREG_ZERO, 1,
+  { "mullla_ss", TILEPRO_OPC_MULLLA_SS, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mullla_ss.sn", TILE_OPC_MULLLA_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mullla_ss.sn", TILEPRO_OPC_MULLLA_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mullla_su", TILE_OPC_MULLLA_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mullla_su", TILEPRO_OPC_MULLLA_SU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mullla_su.sn", TILE_OPC_MULLLA_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mullla_su.sn", TILEPRO_OPC_MULLLA_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mullla_uu", TILE_OPC_MULLLA_UU, 0x5, 3, TREG_ZERO, 1,
+  { "mullla_uu", TILEPRO_OPC_MULLLA_UU, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mullla_uu.sn", TILE_OPC_MULLLA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mullla_uu.sn", TILEPRO_OPC_MULLLA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulllsa_uu", TILE_OPC_MULLLSA_UU, 0x1, 3, TREG_ZERO, 1,
+  { "mulllsa_uu", TILEPRO_OPC_MULLLSA_UU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulllsa_uu.sn", TILE_OPC_MULLLSA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulllsa_uu.sn", TILEPRO_OPC_MULLLSA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mvnz", TILE_OPC_MVNZ, 0x5, 3, TREG_ZERO, 1,
+  { "mvnz", TILEPRO_OPC_MVNZ, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mvnz.sn", TILE_OPC_MVNZ_SN, 0x1, 3, TREG_SN, 1,
+  { "mvnz.sn", TILEPRO_OPC_MVNZ_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mvz", TILE_OPC_MVZ, 0x5, 3, TREG_ZERO, 1,
+  { "mvz", TILEPRO_OPC_MVZ, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mvz.sn", TILE_OPC_MVZ_SN, 0x1, 3, TREG_SN, 1,
+  { "mvz.sn", TILEPRO_OPC_MVZ_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mz", TILE_OPC_MZ, 0xf, 3, TREG_ZERO, 1,
+  { "mz", TILEPRO_OPC_MZ, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "mz.sn", TILE_OPC_MZ_SN, 0x3, 3, TREG_SN, 1,
+  { "mz.sn", TILEPRO_OPC_MZ_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mzb", TILE_OPC_MZB, 0x3, 3, TREG_ZERO, 1,
+  { "mzb", TILEPRO_OPC_MZB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mzb.sn", TILE_OPC_MZB_SN, 0x3, 3, TREG_SN, 1,
+  { "mzb.sn", TILEPRO_OPC_MZB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mzh", TILE_OPC_MZH, 0x3, 3, TREG_ZERO, 1,
+  { "mzh", TILEPRO_OPC_MZH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mzh.sn", TILE_OPC_MZH_SN, 0x3, 3, TREG_SN, 1,
+  { "mzh.sn", TILEPRO_OPC_MZH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "nap", TILE_OPC_NAP, 0x2, 0, TREG_ZERO, 0,
+  { "nap", TILEPRO_OPC_NAP, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "nop", TILE_OPC_NOP, 0xf, 0, TREG_ZERO, 1,
+  { "nop", TILEPRO_OPC_NOP, 0xf, 0, TREG_ZERO, 1,
     { {  }, {  }, {  }, {  }, { 0, } },
   },
-  { "nor", TILE_OPC_NOR, 0xf, 3, TREG_ZERO, 1,
+  { "nor", TILEPRO_OPC_NOR, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "nor.sn", TILE_OPC_NOR_SN, 0x3, 3, TREG_SN, 1,
+  { "nor.sn", TILEPRO_OPC_NOR_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "or", TILE_OPC_OR, 0xf, 3, TREG_ZERO, 1,
+  { "or", TILEPRO_OPC_OR, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "or.sn", TILE_OPC_OR_SN, 0x3, 3, TREG_SN, 1,
+  { "or.sn", TILEPRO_OPC_OR_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "ori", TILE_OPC_ORI, 0xf, 3, TREG_ZERO, 1,
+  { "ori", TILEPRO_OPC_ORI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "ori.sn", TILE_OPC_ORI_SN, 0x3, 3, TREG_SN, 1,
+  { "ori.sn", TILEPRO_OPC_ORI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packbs_u", TILE_OPC_PACKBS_U, 0x3, 3, TREG_ZERO, 1,
+  { "packbs_u", TILEPRO_OPC_PACKBS_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packbs_u.sn", TILE_OPC_PACKBS_U_SN, 0x3, 3, TREG_SN, 1,
+  { "packbs_u.sn", TILEPRO_OPC_PACKBS_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packhb", TILE_OPC_PACKHB, 0x3, 3, TREG_ZERO, 1,
+  { "packhb", TILEPRO_OPC_PACKHB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packhb.sn", TILE_OPC_PACKHB_SN, 0x3, 3, TREG_SN, 1,
+  { "packhb.sn", TILEPRO_OPC_PACKHB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packhs", TILE_OPC_PACKHS, 0x3, 3, TREG_ZERO, 1,
+  { "packhs", TILEPRO_OPC_PACKHS, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packhs.sn", TILE_OPC_PACKHS_SN, 0x3, 3, TREG_SN, 1,
+  { "packhs.sn", TILEPRO_OPC_PACKHS_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packlb", TILE_OPC_PACKLB, 0x3, 3, TREG_ZERO, 1,
+  { "packlb", TILEPRO_OPC_PACKLB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packlb.sn", TILE_OPC_PACKLB_SN, 0x3, 3, TREG_SN, 1,
+  { "packlb.sn", TILEPRO_OPC_PACKLB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "pcnt", TILE_OPC_PCNT, 0x5, 2, TREG_ZERO, 1,
+  { "pcnt", TILEPRO_OPC_PCNT, 0x5, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 0, }, { 11, 12 }, { 0, }, { 0, } },
   },
-  { "pcnt.sn", TILE_OPC_PCNT_SN, 0x1, 2, TREG_SN, 1,
+  { "pcnt.sn", TILEPRO_OPC_PCNT_SN, 0x1, 2, TREG_SN, 1,
     { { 7, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "rl", TILE_OPC_RL, 0xf, 3, TREG_ZERO, 1,
+  { "rl", TILEPRO_OPC_RL, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "rl.sn", TILE_OPC_RL_SN, 0x3, 3, TREG_SN, 1,
+  { "rl.sn", TILEPRO_OPC_RL_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "rli", TILE_OPC_RLI, 0xf, 3, TREG_ZERO, 1,
+  { "rli", TILEPRO_OPC_RLI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 11, 12, 34 }, { 13, 14, 35 }, { 0, } },
   },
-  { "rli.sn", TILE_OPC_RLI_SN, 0x3, 3, TREG_SN, 1,
+  { "rli.sn", TILEPRO_OPC_RLI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "s1a", TILE_OPC_S1A, 0xf, 3, TREG_ZERO, 1,
+  { "s1a", TILEPRO_OPC_S1A, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "s1a.sn", TILE_OPC_S1A_SN, 0x3, 3, TREG_SN, 1,
+  { "s1a.sn", TILEPRO_OPC_S1A_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "s2a", TILE_OPC_S2A, 0xf, 3, TREG_ZERO, 1,
+  { "s2a", TILEPRO_OPC_S2A, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "s2a.sn", TILE_OPC_S2A_SN, 0x3, 3, TREG_SN, 1,
+  { "s2a.sn", TILEPRO_OPC_S2A_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "s3a", TILE_OPC_S3A, 0xf, 3, TREG_ZERO, 1,
+  { "s3a", TILEPRO_OPC_S3A, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "s3a.sn", TILE_OPC_S3A_SN, 0x3, 3, TREG_SN, 1,
+  { "s3a.sn", TILEPRO_OPC_S3A_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadab_u", TILE_OPC_SADAB_U, 0x1, 3, TREG_ZERO, 1,
+  { "sadab_u", TILEPRO_OPC_SADAB_U, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadab_u.sn", TILE_OPC_SADAB_U_SN, 0x1, 3, TREG_SN, 1,
+  { "sadab_u.sn", TILEPRO_OPC_SADAB_U_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadah", TILE_OPC_SADAH, 0x1, 3, TREG_ZERO, 1,
+  { "sadah", TILEPRO_OPC_SADAH, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadah.sn", TILE_OPC_SADAH_SN, 0x1, 3, TREG_SN, 1,
+  { "sadah.sn", TILEPRO_OPC_SADAH_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadah_u", TILE_OPC_SADAH_U, 0x1, 3, TREG_ZERO, 1,
+  { "sadah_u", TILEPRO_OPC_SADAH_U, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadah_u.sn", TILE_OPC_SADAH_U_SN, 0x1, 3, TREG_SN, 1,
+  { "sadah_u.sn", TILEPRO_OPC_SADAH_U_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadb_u", TILE_OPC_SADB_U, 0x1, 3, TREG_ZERO, 1,
+  { "sadb_u", TILEPRO_OPC_SADB_U, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadb_u.sn", TILE_OPC_SADB_U_SN, 0x1, 3, TREG_SN, 1,
+  { "sadb_u.sn", TILEPRO_OPC_SADB_U_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadh", TILE_OPC_SADH, 0x1, 3, TREG_ZERO, 1,
+  { "sadh", TILEPRO_OPC_SADH, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadh.sn", TILE_OPC_SADH_SN, 0x1, 3, TREG_SN, 1,
+  { "sadh.sn", TILEPRO_OPC_SADH_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadh_u", TILE_OPC_SADH_U, 0x1, 3, TREG_ZERO, 1,
+  { "sadh_u", TILEPRO_OPC_SADH_U, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadh_u.sn", TILE_OPC_SADH_U_SN, 0x1, 3, TREG_SN, 1,
+  { "sadh_u.sn", TILEPRO_OPC_SADH_U_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sb", TILE_OPC_SB, 0x12, 2, TREG_ZERO, 1,
+  { "sb", TILEPRO_OPC_SB, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 17 }, { 0, }, { 0, }, { 15, 36 } },
   },
-  { "sbadd", TILE_OPC_SBADD, 0x2, 3, TREG_ZERO, 1,
+  { "sbadd", TILEPRO_OPC_SBADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 24, 17, 37 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seq", TILE_OPC_SEQ, 0xf, 3, TREG_ZERO, 1,
+  { "seq", TILEPRO_OPC_SEQ, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "seq.sn", TILE_OPC_SEQ_SN, 0x3, 3, TREG_SN, 1,
+  { "seq.sn", TILEPRO_OPC_SEQ_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqb", TILE_OPC_SEQB, 0x3, 3, TREG_ZERO, 1,
+  { "seqb", TILEPRO_OPC_SEQB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqb.sn", TILE_OPC_SEQB_SN, 0x3, 3, TREG_SN, 1,
+  { "seqb.sn", TILEPRO_OPC_SEQB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqh", TILE_OPC_SEQH, 0x3, 3, TREG_ZERO, 1,
+  { "seqh", TILEPRO_OPC_SEQH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqh.sn", TILE_OPC_SEQH_SN, 0x3, 3, TREG_SN, 1,
+  { "seqh.sn", TILEPRO_OPC_SEQH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqi", TILE_OPC_SEQI, 0xf, 3, TREG_ZERO, 1,
+  { "seqi", TILEPRO_OPC_SEQI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "seqi.sn", TILE_OPC_SEQI_SN, 0x3, 3, TREG_SN, 1,
+  { "seqi.sn", TILEPRO_OPC_SEQI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqib", TILE_OPC_SEQIB, 0x3, 3, TREG_ZERO, 1,
+  { "seqib", TILEPRO_OPC_SEQIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqib.sn", TILE_OPC_SEQIB_SN, 0x3, 3, TREG_SN, 1,
+  { "seqib.sn", TILEPRO_OPC_SEQIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqih", TILE_OPC_SEQIH, 0x3, 3, TREG_ZERO, 1,
+  { "seqih", TILEPRO_OPC_SEQIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqih.sn", TILE_OPC_SEQIH_SN, 0x3, 3, TREG_SN, 1,
+  { "seqih.sn", TILEPRO_OPC_SEQIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sh", TILE_OPC_SH, 0x12, 2, TREG_ZERO, 1,
+  { "sh", TILEPRO_OPC_SH, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 17 }, { 0, }, { 0, }, { 15, 36 } },
   },
-  { "shadd", TILE_OPC_SHADD, 0x2, 3, TREG_ZERO, 1,
+  { "shadd", TILEPRO_OPC_SHADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 24, 17, 37 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shl", TILE_OPC_SHL, 0xf, 3, TREG_ZERO, 1,
+  { "shl", TILEPRO_OPC_SHL, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "shl.sn", TILE_OPC_SHL_SN, 0x3, 3, TREG_SN, 1,
+  { "shl.sn", TILEPRO_OPC_SHL_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlb", TILE_OPC_SHLB, 0x3, 3, TREG_ZERO, 1,
+  { "shlb", TILEPRO_OPC_SHLB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlb.sn", TILE_OPC_SHLB_SN, 0x3, 3, TREG_SN, 1,
+  { "shlb.sn", TILEPRO_OPC_SHLB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlh", TILE_OPC_SHLH, 0x3, 3, TREG_ZERO, 1,
+  { "shlh", TILEPRO_OPC_SHLH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlh.sn", TILE_OPC_SHLH_SN, 0x3, 3, TREG_SN, 1,
+  { "shlh.sn", TILEPRO_OPC_SHLH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shli", TILE_OPC_SHLI, 0xf, 3, TREG_ZERO, 1,
+  { "shli", TILEPRO_OPC_SHLI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 11, 12, 34 }, { 13, 14, 35 }, { 0, } },
   },
-  { "shli.sn", TILE_OPC_SHLI_SN, 0x3, 3, TREG_SN, 1,
+  { "shli.sn", TILEPRO_OPC_SHLI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlib", TILE_OPC_SHLIB, 0x3, 3, TREG_ZERO, 1,
+  { "shlib", TILEPRO_OPC_SHLIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlib.sn", TILE_OPC_SHLIB_SN, 0x3, 3, TREG_SN, 1,
+  { "shlib.sn", TILEPRO_OPC_SHLIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlih", TILE_OPC_SHLIH, 0x3, 3, TREG_ZERO, 1,
+  { "shlih", TILEPRO_OPC_SHLIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlih.sn", TILE_OPC_SHLIH_SN, 0x3, 3, TREG_SN, 1,
+  { "shlih.sn", TILEPRO_OPC_SHLIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shr", TILE_OPC_SHR, 0xf, 3, TREG_ZERO, 1,
+  { "shr", TILEPRO_OPC_SHR, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "shr.sn", TILE_OPC_SHR_SN, 0x3, 3, TREG_SN, 1,
+  { "shr.sn", TILEPRO_OPC_SHR_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrb", TILE_OPC_SHRB, 0x3, 3, TREG_ZERO, 1,
+  { "shrb", TILEPRO_OPC_SHRB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrb.sn", TILE_OPC_SHRB_SN, 0x3, 3, TREG_SN, 1,
+  { "shrb.sn", TILEPRO_OPC_SHRB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrh", TILE_OPC_SHRH, 0x3, 3, TREG_ZERO, 1,
+  { "shrh", TILEPRO_OPC_SHRH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrh.sn", TILE_OPC_SHRH_SN, 0x3, 3, TREG_SN, 1,
+  { "shrh.sn", TILEPRO_OPC_SHRH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shri", TILE_OPC_SHRI, 0xf, 3, TREG_ZERO, 1,
+  { "shri", TILEPRO_OPC_SHRI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 11, 12, 34 }, { 13, 14, 35 }, { 0, } },
   },
-  { "shri.sn", TILE_OPC_SHRI_SN, 0x3, 3, TREG_SN, 1,
+  { "shri.sn", TILEPRO_OPC_SHRI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrib", TILE_OPC_SHRIB, 0x3, 3, TREG_ZERO, 1,
+  { "shrib", TILEPRO_OPC_SHRIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrib.sn", TILE_OPC_SHRIB_SN, 0x3, 3, TREG_SN, 1,
+  { "shrib.sn", TILEPRO_OPC_SHRIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrih", TILE_OPC_SHRIH, 0x3, 3, TREG_ZERO, 1,
+  { "shrih", TILEPRO_OPC_SHRIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrih.sn", TILE_OPC_SHRIH_SN, 0x3, 3, TREG_SN, 1,
+  { "shrih.sn", TILEPRO_OPC_SHRIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slt", TILE_OPC_SLT, 0xf, 3, TREG_ZERO, 1,
+  { "slt", TILEPRO_OPC_SLT, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "slt.sn", TILE_OPC_SLT_SN, 0x3, 3, TREG_SN, 1,
+  { "slt.sn", TILEPRO_OPC_SLT_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slt_u", TILE_OPC_SLT_U, 0xf, 3, TREG_ZERO, 1,
+  { "slt_u", TILEPRO_OPC_SLT_U, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "slt_u.sn", TILE_OPC_SLT_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slt_u.sn", TILEPRO_OPC_SLT_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltb", TILE_OPC_SLTB, 0x3, 3, TREG_ZERO, 1,
+  { "sltb", TILEPRO_OPC_SLTB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltb.sn", TILE_OPC_SLTB_SN, 0x3, 3, TREG_SN, 1,
+  { "sltb.sn", TILEPRO_OPC_SLTB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltb_u", TILE_OPC_SLTB_U, 0x3, 3, TREG_ZERO, 1,
+  { "sltb_u", TILEPRO_OPC_SLTB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltb_u.sn", TILE_OPC_SLTB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "sltb_u.sn", TILEPRO_OPC_SLTB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slte", TILE_OPC_SLTE, 0xf, 3, TREG_ZERO, 1,
+  { "slte", TILEPRO_OPC_SLTE, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "slte.sn", TILE_OPC_SLTE_SN, 0x3, 3, TREG_SN, 1,
+  { "slte.sn", TILEPRO_OPC_SLTE_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slte_u", TILE_OPC_SLTE_U, 0xf, 3, TREG_ZERO, 1,
+  { "slte_u", TILEPRO_OPC_SLTE_U, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "slte_u.sn", TILE_OPC_SLTE_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slte_u.sn", TILEPRO_OPC_SLTE_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteb", TILE_OPC_SLTEB, 0x3, 3, TREG_ZERO, 1,
+  { "slteb", TILEPRO_OPC_SLTEB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteb.sn", TILE_OPC_SLTEB_SN, 0x3, 3, TREG_SN, 1,
+  { "slteb.sn", TILEPRO_OPC_SLTEB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteb_u", TILE_OPC_SLTEB_U, 0x3, 3, TREG_ZERO, 1,
+  { "slteb_u", TILEPRO_OPC_SLTEB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteb_u.sn", TILE_OPC_SLTEB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slteb_u.sn", TILEPRO_OPC_SLTEB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteh", TILE_OPC_SLTEH, 0x3, 3, TREG_ZERO, 1,
+  { "slteh", TILEPRO_OPC_SLTEH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteh.sn", TILE_OPC_SLTEH_SN, 0x3, 3, TREG_SN, 1,
+  { "slteh.sn", TILEPRO_OPC_SLTEH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteh_u", TILE_OPC_SLTEH_U, 0x3, 3, TREG_ZERO, 1,
+  { "slteh_u", TILEPRO_OPC_SLTEH_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteh_u.sn", TILE_OPC_SLTEH_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slteh_u.sn", TILEPRO_OPC_SLTEH_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slth", TILE_OPC_SLTH, 0x3, 3, TREG_ZERO, 1,
+  { "slth", TILEPRO_OPC_SLTH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slth.sn", TILE_OPC_SLTH_SN, 0x3, 3, TREG_SN, 1,
+  { "slth.sn", TILEPRO_OPC_SLTH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slth_u", TILE_OPC_SLTH_U, 0x3, 3, TREG_ZERO, 1,
+  { "slth_u", TILEPRO_OPC_SLTH_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slth_u.sn", TILE_OPC_SLTH_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slth_u.sn", TILEPRO_OPC_SLTH_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slti", TILE_OPC_SLTI, 0xf, 3, TREG_ZERO, 1,
+  { "slti", TILEPRO_OPC_SLTI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "slti.sn", TILE_OPC_SLTI_SN, 0x3, 3, TREG_SN, 1,
+  { "slti.sn", TILEPRO_OPC_SLTI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slti_u", TILE_OPC_SLTI_U, 0xf, 3, TREG_ZERO, 1,
+  { "slti_u", TILEPRO_OPC_SLTI_U, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "slti_u.sn", TILE_OPC_SLTI_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slti_u.sn", TILEPRO_OPC_SLTI_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltib", TILE_OPC_SLTIB, 0x3, 3, TREG_ZERO, 1,
+  { "sltib", TILEPRO_OPC_SLTIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltib.sn", TILE_OPC_SLTIB_SN, 0x3, 3, TREG_SN, 1,
+  { "sltib.sn", TILEPRO_OPC_SLTIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltib_u", TILE_OPC_SLTIB_U, 0x3, 3, TREG_ZERO, 1,
+  { "sltib_u", TILEPRO_OPC_SLTIB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltib_u.sn", TILE_OPC_SLTIB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "sltib_u.sn", TILEPRO_OPC_SLTIB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltih", TILE_OPC_SLTIH, 0x3, 3, TREG_ZERO, 1,
+  { "sltih", TILEPRO_OPC_SLTIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltih.sn", TILE_OPC_SLTIH_SN, 0x3, 3, TREG_SN, 1,
+  { "sltih.sn", TILEPRO_OPC_SLTIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltih_u", TILE_OPC_SLTIH_U, 0x3, 3, TREG_ZERO, 1,
+  { "sltih_u", TILEPRO_OPC_SLTIH_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltih_u.sn", TILE_OPC_SLTIH_U_SN, 0x3, 3, TREG_SN, 1,
+  { "sltih_u.sn", TILEPRO_OPC_SLTIH_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sne", TILE_OPC_SNE, 0xf, 3, TREG_ZERO, 1,
+  { "sne", TILEPRO_OPC_SNE, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "sne.sn", TILE_OPC_SNE_SN, 0x3, 3, TREG_SN, 1,
+  { "sne.sn", TILEPRO_OPC_SNE_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sneb", TILE_OPC_SNEB, 0x3, 3, TREG_ZERO, 1,
+  { "sneb", TILEPRO_OPC_SNEB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sneb.sn", TILE_OPC_SNEB_SN, 0x3, 3, TREG_SN, 1,
+  { "sneb.sn", TILEPRO_OPC_SNEB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sneh", TILE_OPC_SNEH, 0x3, 3, TREG_ZERO, 1,
+  { "sneh", TILEPRO_OPC_SNEH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sneh.sn", TILE_OPC_SNEH_SN, 0x3, 3, TREG_SN, 1,
+  { "sneh.sn", TILEPRO_OPC_SNEH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sra", TILE_OPC_SRA, 0xf, 3, TREG_ZERO, 1,
+  { "sra", TILEPRO_OPC_SRA, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "sra.sn", TILE_OPC_SRA_SN, 0x3, 3, TREG_SN, 1,
+  { "sra.sn", TILEPRO_OPC_SRA_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "srab", TILE_OPC_SRAB, 0x3, 3, TREG_ZERO, 1,
+  { "srab", TILEPRO_OPC_SRAB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "srab.sn", TILE_OPC_SRAB_SN, 0x3, 3, TREG_SN, 1,
+  { "srab.sn", TILEPRO_OPC_SRAB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "srah", TILE_OPC_SRAH, 0x3, 3, TREG_ZERO, 1,
+  { "srah", TILEPRO_OPC_SRAH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "srah.sn", TILE_OPC_SRAH_SN, 0x3, 3, TREG_SN, 1,
+  { "srah.sn", TILEPRO_OPC_SRAH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "srai", TILE_OPC_SRAI, 0xf, 3, TREG_ZERO, 1,
+  { "srai", TILEPRO_OPC_SRAI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 11, 12, 34 }, { 13, 14, 35 }, { 0, } },
   },
-  { "srai.sn", TILE_OPC_SRAI_SN, 0x3, 3, TREG_SN, 1,
+  { "srai.sn", TILEPRO_OPC_SRAI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sraib", TILE_OPC_SRAIB, 0x3, 3, TREG_ZERO, 1,
+  { "sraib", TILEPRO_OPC_SRAIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sraib.sn", TILE_OPC_SRAIB_SN, 0x3, 3, TREG_SN, 1,
+  { "sraib.sn", TILEPRO_OPC_SRAIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sraih", TILE_OPC_SRAIH, 0x3, 3, TREG_ZERO, 1,
+  { "sraih", TILEPRO_OPC_SRAIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sraih.sn", TILE_OPC_SRAIH_SN, 0x3, 3, TREG_SN, 1,
+  { "sraih.sn", TILEPRO_OPC_SRAIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sub", TILE_OPC_SUB, 0xf, 3, TREG_ZERO, 1,
+  { "sub", TILEPRO_OPC_SUB, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "sub.sn", TILE_OPC_SUB_SN, 0x3, 3, TREG_SN, 1,
+  { "sub.sn", TILEPRO_OPC_SUB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subb", TILE_OPC_SUBB, 0x3, 3, TREG_ZERO, 1,
+  { "subb", TILEPRO_OPC_SUBB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subb.sn", TILE_OPC_SUBB_SN, 0x3, 3, TREG_SN, 1,
+  { "subb.sn", TILEPRO_OPC_SUBB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subbs_u", TILE_OPC_SUBBS_U, 0x3, 3, TREG_ZERO, 1,
+  { "subbs_u", TILEPRO_OPC_SUBBS_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subbs_u.sn", TILE_OPC_SUBBS_U_SN, 0x3, 3, TREG_SN, 1,
+  { "subbs_u.sn", TILEPRO_OPC_SUBBS_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subh", TILE_OPC_SUBH, 0x3, 3, TREG_ZERO, 1,
+  { "subh", TILEPRO_OPC_SUBH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subh.sn", TILE_OPC_SUBH_SN, 0x3, 3, TREG_SN, 1,
+  { "subh.sn", TILEPRO_OPC_SUBH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subhs", TILE_OPC_SUBHS, 0x3, 3, TREG_ZERO, 1,
+  { "subhs", TILEPRO_OPC_SUBHS, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subhs.sn", TILE_OPC_SUBHS_SN, 0x3, 3, TREG_SN, 1,
+  { "subhs.sn", TILEPRO_OPC_SUBHS_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subs", TILE_OPC_SUBS, 0x3, 3, TREG_ZERO, 1,
+  { "subs", TILEPRO_OPC_SUBS, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subs.sn", TILE_OPC_SUBS_SN, 0x3, 3, TREG_SN, 1,
+  { "subs.sn", TILEPRO_OPC_SUBS_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sw", TILE_OPC_SW, 0x12, 2, TREG_ZERO, 1,
+  { "sw", TILEPRO_OPC_SW, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 17 }, { 0, }, { 0, }, { 15, 36 } },
   },
-  { "swadd", TILE_OPC_SWADD, 0x2, 3, TREG_ZERO, 1,
+  { "swadd", TILEPRO_OPC_SWADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 24, 17, 37 }, { 0, }, { 0, }, { 0, } },
   },
-  { "swint0", TILE_OPC_SWINT0, 0x2, 0, TREG_ZERO, 0,
+  { "swint0", TILEPRO_OPC_SWINT0, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "swint1", TILE_OPC_SWINT1, 0x2, 0, TREG_ZERO, 0,
+  { "swint1", TILEPRO_OPC_SWINT1, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "swint2", TILE_OPC_SWINT2, 0x2, 0, TREG_ZERO, 0,
+  { "swint2", TILEPRO_OPC_SWINT2, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "swint3", TILE_OPC_SWINT3, 0x2, 0, TREG_ZERO, 0,
+  { "swint3", TILEPRO_OPC_SWINT3, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "tblidxb0", TILE_OPC_TBLIDXB0, 0x5, 2, TREG_ZERO, 1,
+  { "tblidxb0", TILEPRO_OPC_TBLIDXB0, 0x5, 2, TREG_ZERO, 1,
     { { 21, 8 }, { 0, }, { 31, 12 }, { 0, }, { 0, } },
   },
-  { "tblidxb0.sn", TILE_OPC_TBLIDXB0_SN, 0x1, 2, TREG_SN, 1,
+  { "tblidxb0.sn", TILEPRO_OPC_TBLIDXB0_SN, 0x1, 2, TREG_SN, 1,
     { { 21, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "tblidxb1", TILE_OPC_TBLIDXB1, 0x5, 2, TREG_ZERO, 1,
+  { "tblidxb1", TILEPRO_OPC_TBLIDXB1, 0x5, 2, TREG_ZERO, 1,
     { { 21, 8 }, { 0, }, { 31, 12 }, { 0, }, { 0, } },
   },
-  { "tblidxb1.sn", TILE_OPC_TBLIDXB1_SN, 0x1, 2, TREG_SN, 1,
+  { "tblidxb1.sn", TILEPRO_OPC_TBLIDXB1_SN, 0x1, 2, TREG_SN, 1,
     { { 21, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "tblidxb2", TILE_OPC_TBLIDXB2, 0x5, 2, TREG_ZERO, 1,
+  { "tblidxb2", TILEPRO_OPC_TBLIDXB2, 0x5, 2, TREG_ZERO, 1,
     { { 21, 8 }, { 0, }, { 31, 12 }, { 0, }, { 0, } },
   },
-  { "tblidxb2.sn", TILE_OPC_TBLIDXB2_SN, 0x1, 2, TREG_SN, 1,
+  { "tblidxb2.sn", TILEPRO_OPC_TBLIDXB2_SN, 0x1, 2, TREG_SN, 1,
     { { 21, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "tblidxb3", TILE_OPC_TBLIDXB3, 0x5, 2, TREG_ZERO, 1,
+  { "tblidxb3", TILEPRO_OPC_TBLIDXB3, 0x5, 2, TREG_ZERO, 1,
     { { 21, 8 }, { 0, }, { 31, 12 }, { 0, }, { 0, } },
   },
-  { "tblidxb3.sn", TILE_OPC_TBLIDXB3_SN, 0x1, 2, TREG_SN, 1,
+  { "tblidxb3.sn", TILEPRO_OPC_TBLIDXB3_SN, 0x1, 2, TREG_SN, 1,
     { { 21, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "tns", TILE_OPC_TNS, 0x2, 2, TREG_ZERO, 1,
+  { "tns", TILEPRO_OPC_TNS, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "tns.sn", TILE_OPC_TNS_SN, 0x2, 2, TREG_SN, 1,
+  { "tns.sn", TILEPRO_OPC_TNS_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "wh64", TILE_OPC_WH64, 0x2, 1, TREG_ZERO, 1,
+  { "wh64", TILEPRO_OPC_WH64, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "xor", TILE_OPC_XOR, 0xf, 3, TREG_ZERO, 1,
+  { "xor", TILEPRO_OPC_XOR, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "xor.sn", TILE_OPC_XOR_SN, 0x3, 3, TREG_SN, 1,
+  { "xor.sn", TILEPRO_OPC_XOR_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "xori", TILE_OPC_XORI, 0x3, 3, TREG_ZERO, 1,
+  { "xori", TILEPRO_OPC_XORI, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "xori.sn", TILE_OPC_XORI_SN, 0x3, 3, TREG_SN, 1,
+  { "xori.sn", TILEPRO_OPC_XORI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { NULL, TILE_OPC_NONE, 0, 0, TREG_ZERO, 0, { { 0, } },
+  { NULL, TILEPRO_OPC_NONE, 0, 0, TREG_ZERO, 0, { { 0, } },
   }
 };
 #define BITFIELD(start, size) ((start) | (((1 << (size)) - 1) << 6))
-#define CHILD(array_index) (TILE_OPC_NONE + (array_index))
+#define CHILD(array_index) (TILEPRO_OPC_NONE + (array_index))
 
 static const unsigned short decode_X0_fsm[1153] =
 {
   BITFIELD(22, 9) /* index 0 */,
   CHILD(513), CHILD(530), CHILD(547), CHILD(564), CHILD(596), CHILD(613),
-  CHILD(630), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, CHILD(663), CHILD(680), CHILD(697), CHILD(714), CHILD(746),
-  CHILD(763), CHILD(780), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, CHILD(813), CHILD(813), CHILD(813),
+  CHILD(630), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(663), CHILD(680), CHILD(697),
+  CHILD(714), CHILD(746), CHILD(763), CHILD(780), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
@@ -1227,7 +1247,7 @@
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
-  CHILD(813), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
+  CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(828), CHILD(828),
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
@@ -1237,7 +1257,8 @@
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
-  CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(843),
+  CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
+  CHILD(828), CHILD(828), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
@@ -1248,333 +1269,371 @@
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
-  CHILD(843), CHILD(843), CHILD(843), CHILD(873), CHILD(878), CHILD(883),
-  CHILD(903), CHILD(908), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(913),
-  CHILD(918), CHILD(923), CHILD(943), CHILD(948), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, CHILD(953), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(988), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, CHILD(993),
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, CHILD(1076), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(873), CHILD(878), CHILD(883), CHILD(903), CHILD(908),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(913),
+  CHILD(918), CHILD(923), CHILD(943), CHILD(948), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(953), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(988), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, CHILD(993), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(1076), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(18, 4) /* index 513 */,
-  TILE_OPC_NONE, TILE_OPC_ADDB, TILE_OPC_ADDH, TILE_OPC_ADD,
-  TILE_OPC_ADIFFB_U, TILE_OPC_ADIFFH, TILE_OPC_AND, TILE_OPC_AVGB_U,
-  TILE_OPC_AVGH, TILE_OPC_CRC32_32, TILE_OPC_CRC32_8, TILE_OPC_INTHB,
-  TILE_OPC_INTHH, TILE_OPC_INTLB, TILE_OPC_INTLH, TILE_OPC_MAXB_U,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDB, TILEPRO_OPC_ADDH, TILEPRO_OPC_ADD,
+  TILEPRO_OPC_ADIFFB_U, TILEPRO_OPC_ADIFFH, TILEPRO_OPC_AND,
+  TILEPRO_OPC_AVGB_U, TILEPRO_OPC_AVGH, TILEPRO_OPC_CRC32_32,
+  TILEPRO_OPC_CRC32_8, TILEPRO_OPC_INTHB, TILEPRO_OPC_INTHH,
+  TILEPRO_OPC_INTLB, TILEPRO_OPC_INTLH, TILEPRO_OPC_MAXB_U,
   BITFIELD(18, 4) /* index 530 */,
-  TILE_OPC_MAXH, TILE_OPC_MINB_U, TILE_OPC_MINH, TILE_OPC_MNZB, TILE_OPC_MNZH,
-  TILE_OPC_MNZ, TILE_OPC_MULHHA_SS, TILE_OPC_MULHHA_SU, TILE_OPC_MULHHA_UU,
-  TILE_OPC_MULHHSA_UU, TILE_OPC_MULHH_SS, TILE_OPC_MULHH_SU,
-  TILE_OPC_MULHH_UU, TILE_OPC_MULHLA_SS, TILE_OPC_MULHLA_SU,
-  TILE_OPC_MULHLA_US,
+  TILEPRO_OPC_MAXH, TILEPRO_OPC_MINB_U, TILEPRO_OPC_MINH, TILEPRO_OPC_MNZB,
+  TILEPRO_OPC_MNZH, TILEPRO_OPC_MNZ, TILEPRO_OPC_MULHHA_SS,
+  TILEPRO_OPC_MULHHA_SU, TILEPRO_OPC_MULHHA_UU, TILEPRO_OPC_MULHHSA_UU,
+  TILEPRO_OPC_MULHH_SS, TILEPRO_OPC_MULHH_SU, TILEPRO_OPC_MULHH_UU,
+  TILEPRO_OPC_MULHLA_SS, TILEPRO_OPC_MULHLA_SU, TILEPRO_OPC_MULHLA_US,
   BITFIELD(18, 4) /* index 547 */,
-  TILE_OPC_MULHLA_UU, TILE_OPC_MULHLSA_UU, TILE_OPC_MULHL_SS,
-  TILE_OPC_MULHL_SU, TILE_OPC_MULHL_US, TILE_OPC_MULHL_UU, TILE_OPC_MULLLA_SS,
-  TILE_OPC_MULLLA_SU, TILE_OPC_MULLLA_UU, TILE_OPC_MULLLSA_UU,
-  TILE_OPC_MULLL_SS, TILE_OPC_MULLL_SU, TILE_OPC_MULLL_UU, TILE_OPC_MVNZ,
-  TILE_OPC_MVZ, TILE_OPC_MZB,
+  TILEPRO_OPC_MULHLA_UU, TILEPRO_OPC_MULHLSA_UU, TILEPRO_OPC_MULHL_SS,
+  TILEPRO_OPC_MULHL_SU, TILEPRO_OPC_MULHL_US, TILEPRO_OPC_MULHL_UU,
+  TILEPRO_OPC_MULLLA_SS, TILEPRO_OPC_MULLLA_SU, TILEPRO_OPC_MULLLA_UU,
+  TILEPRO_OPC_MULLLSA_UU, TILEPRO_OPC_MULLL_SS, TILEPRO_OPC_MULLL_SU,
+  TILEPRO_OPC_MULLL_UU, TILEPRO_OPC_MVNZ, TILEPRO_OPC_MVZ, TILEPRO_OPC_MZB,
   BITFIELD(18, 4) /* index 564 */,
-  TILE_OPC_MZH, TILE_OPC_MZ, TILE_OPC_NOR, CHILD(581), TILE_OPC_PACKHB,
-  TILE_OPC_PACKLB, TILE_OPC_RL, TILE_OPC_S1A, TILE_OPC_S2A, TILE_OPC_S3A,
-  TILE_OPC_SADAB_U, TILE_OPC_SADAH, TILE_OPC_SADAH_U, TILE_OPC_SADB_U,
-  TILE_OPC_SADH, TILE_OPC_SADH_U,
+  TILEPRO_OPC_MZH, TILEPRO_OPC_MZ, TILEPRO_OPC_NOR, CHILD(581),
+  TILEPRO_OPC_PACKHB, TILEPRO_OPC_PACKLB, TILEPRO_OPC_RL, TILEPRO_OPC_S1A,
+  TILEPRO_OPC_S2A, TILEPRO_OPC_S3A, TILEPRO_OPC_SADAB_U, TILEPRO_OPC_SADAH,
+  TILEPRO_OPC_SADAH_U, TILEPRO_OPC_SADB_U, TILEPRO_OPC_SADH,
+  TILEPRO_OPC_SADH_U,
   BITFIELD(12, 2) /* index 581 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(586),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(586),
   BITFIELD(14, 2) /* index 586 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(591),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(591),
   BITFIELD(16, 2) /* index 591 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_MOVE,
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_MOVE,
   BITFIELD(18, 4) /* index 596 */,
-  TILE_OPC_SEQB, TILE_OPC_SEQH, TILE_OPC_SEQ, TILE_OPC_SHLB, TILE_OPC_SHLH,
-  TILE_OPC_SHL, TILE_OPC_SHRB, TILE_OPC_SHRH, TILE_OPC_SHR, TILE_OPC_SLTB,
-  TILE_OPC_SLTB_U, TILE_OPC_SLTEB, TILE_OPC_SLTEB_U, TILE_OPC_SLTEH,
-  TILE_OPC_SLTEH_U, TILE_OPC_SLTE,
+  TILEPRO_OPC_SEQB, TILEPRO_OPC_SEQH, TILEPRO_OPC_SEQ, TILEPRO_OPC_SHLB,
+  TILEPRO_OPC_SHLH, TILEPRO_OPC_SHL, TILEPRO_OPC_SHRB, TILEPRO_OPC_SHRH,
+  TILEPRO_OPC_SHR, TILEPRO_OPC_SLTB, TILEPRO_OPC_SLTB_U, TILEPRO_OPC_SLTEB,
+  TILEPRO_OPC_SLTEB_U, TILEPRO_OPC_SLTEH, TILEPRO_OPC_SLTEH_U,
+  TILEPRO_OPC_SLTE,
   BITFIELD(18, 4) /* index 613 */,
-  TILE_OPC_SLTE_U, TILE_OPC_SLTH, TILE_OPC_SLTH_U, TILE_OPC_SLT,
-  TILE_OPC_SLT_U, TILE_OPC_SNEB, TILE_OPC_SNEH, TILE_OPC_SNE, TILE_OPC_SRAB,
-  TILE_OPC_SRAH, TILE_OPC_SRA, TILE_OPC_SUBB, TILE_OPC_SUBH, TILE_OPC_SUB,
-  TILE_OPC_XOR, TILE_OPC_DWORD_ALIGN,
+  TILEPRO_OPC_SLTE_U, TILEPRO_OPC_SLTH, TILEPRO_OPC_SLTH_U, TILEPRO_OPC_SLT,
+  TILEPRO_OPC_SLT_U, TILEPRO_OPC_SNEB, TILEPRO_OPC_SNEH, TILEPRO_OPC_SNE,
+  TILEPRO_OPC_SRAB, TILEPRO_OPC_SRAH, TILEPRO_OPC_SRA, TILEPRO_OPC_SUBB,
+  TILEPRO_OPC_SUBH, TILEPRO_OPC_SUB, TILEPRO_OPC_XOR, TILEPRO_OPC_DWORD_ALIGN,
   BITFIELD(18, 3) /* index 630 */,
   CHILD(639), CHILD(642), CHILD(645), CHILD(648), CHILD(651), CHILD(654),
   CHILD(657), CHILD(660),
   BITFIELD(21, 1) /* index 639 */,
-  TILE_OPC_ADDS, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDS, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 642 */,
-  TILE_OPC_SUBS, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBS, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 645 */,
-  TILE_OPC_ADDBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDBS_U, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 648 */,
-  TILE_OPC_ADDHS, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDHS, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 651 */,
-  TILE_OPC_SUBBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBBS_U, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 654 */,
-  TILE_OPC_SUBHS, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBHS, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 657 */,
-  TILE_OPC_PACKHS, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKHS, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 660 */,
-  TILE_OPC_PACKBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKBS_U, TILEPRO_OPC_NONE,
   BITFIELD(18, 4) /* index 663 */,
-  TILE_OPC_NONE, TILE_OPC_ADDB_SN, TILE_OPC_ADDH_SN, TILE_OPC_ADD_SN,
-  TILE_OPC_ADIFFB_U_SN, TILE_OPC_ADIFFH_SN, TILE_OPC_AND_SN,
-  TILE_OPC_AVGB_U_SN, TILE_OPC_AVGH_SN, TILE_OPC_CRC32_32_SN,
-  TILE_OPC_CRC32_8_SN, TILE_OPC_INTHB_SN, TILE_OPC_INTHH_SN,
-  TILE_OPC_INTLB_SN, TILE_OPC_INTLH_SN, TILE_OPC_MAXB_U_SN,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDB_SN, TILEPRO_OPC_ADDH_SN,
+  TILEPRO_OPC_ADD_SN, TILEPRO_OPC_ADIFFB_U_SN, TILEPRO_OPC_ADIFFH_SN,
+  TILEPRO_OPC_AND_SN, TILEPRO_OPC_AVGB_U_SN, TILEPRO_OPC_AVGH_SN,
+  TILEPRO_OPC_CRC32_32_SN, TILEPRO_OPC_CRC32_8_SN, TILEPRO_OPC_INTHB_SN,
+  TILEPRO_OPC_INTHH_SN, TILEPRO_OPC_INTLB_SN, TILEPRO_OPC_INTLH_SN,
+  TILEPRO_OPC_MAXB_U_SN,
   BITFIELD(18, 4) /* index 680 */,
-  TILE_OPC_MAXH_SN, TILE_OPC_MINB_U_SN, TILE_OPC_MINH_SN, TILE_OPC_MNZB_SN,
-  TILE_OPC_MNZH_SN, TILE_OPC_MNZ_SN, TILE_OPC_MULHHA_SS_SN,
-  TILE_OPC_MULHHA_SU_SN, TILE_OPC_MULHHA_UU_SN, TILE_OPC_MULHHSA_UU_SN,
-  TILE_OPC_MULHH_SS_SN, TILE_OPC_MULHH_SU_SN, TILE_OPC_MULHH_UU_SN,
-  TILE_OPC_MULHLA_SS_SN, TILE_OPC_MULHLA_SU_SN, TILE_OPC_MULHLA_US_SN,
+  TILEPRO_OPC_MAXH_SN, TILEPRO_OPC_MINB_U_SN, TILEPRO_OPC_MINH_SN,
+  TILEPRO_OPC_MNZB_SN, TILEPRO_OPC_MNZH_SN, TILEPRO_OPC_MNZ_SN,
+  TILEPRO_OPC_MULHHA_SS_SN, TILEPRO_OPC_MULHHA_SU_SN,
+  TILEPRO_OPC_MULHHA_UU_SN, TILEPRO_OPC_MULHHSA_UU_SN,
+  TILEPRO_OPC_MULHH_SS_SN, TILEPRO_OPC_MULHH_SU_SN, TILEPRO_OPC_MULHH_UU_SN,
+  TILEPRO_OPC_MULHLA_SS_SN, TILEPRO_OPC_MULHLA_SU_SN,
+  TILEPRO_OPC_MULHLA_US_SN,
   BITFIELD(18, 4) /* index 697 */,
-  TILE_OPC_MULHLA_UU_SN, TILE_OPC_MULHLSA_UU_SN, TILE_OPC_MULHL_SS_SN,
-  TILE_OPC_MULHL_SU_SN, TILE_OPC_MULHL_US_SN, TILE_OPC_MULHL_UU_SN,
-  TILE_OPC_MULLLA_SS_SN, TILE_OPC_MULLLA_SU_SN, TILE_OPC_MULLLA_UU_SN,
-  TILE_OPC_MULLLSA_UU_SN, TILE_OPC_MULLL_SS_SN, TILE_OPC_MULLL_SU_SN,
-  TILE_OPC_MULLL_UU_SN, TILE_OPC_MVNZ_SN, TILE_OPC_MVZ_SN, TILE_OPC_MZB_SN,
+  TILEPRO_OPC_MULHLA_UU_SN, TILEPRO_OPC_MULHLSA_UU_SN,
+  TILEPRO_OPC_MULHL_SS_SN, TILEPRO_OPC_MULHL_SU_SN, TILEPRO_OPC_MULHL_US_SN,
+  TILEPRO_OPC_MULHL_UU_SN, TILEPRO_OPC_MULLLA_SS_SN, TILEPRO_OPC_MULLLA_SU_SN,
+  TILEPRO_OPC_MULLLA_UU_SN, TILEPRO_OPC_MULLLSA_UU_SN,
+  TILEPRO_OPC_MULLL_SS_SN, TILEPRO_OPC_MULLL_SU_SN, TILEPRO_OPC_MULLL_UU_SN,
+  TILEPRO_OPC_MVNZ_SN, TILEPRO_OPC_MVZ_SN, TILEPRO_OPC_MZB_SN,
   BITFIELD(18, 4) /* index 714 */,
-  TILE_OPC_MZH_SN, TILE_OPC_MZ_SN, TILE_OPC_NOR_SN, CHILD(731),
-  TILE_OPC_PACKHB_SN, TILE_OPC_PACKLB_SN, TILE_OPC_RL_SN, TILE_OPC_S1A_SN,
-  TILE_OPC_S2A_SN, TILE_OPC_S3A_SN, TILE_OPC_SADAB_U_SN, TILE_OPC_SADAH_SN,
-  TILE_OPC_SADAH_U_SN, TILE_OPC_SADB_U_SN, TILE_OPC_SADH_SN,
-  TILE_OPC_SADH_U_SN,
+  TILEPRO_OPC_MZH_SN, TILEPRO_OPC_MZ_SN, TILEPRO_OPC_NOR_SN, CHILD(731),
+  TILEPRO_OPC_PACKHB_SN, TILEPRO_OPC_PACKLB_SN, TILEPRO_OPC_RL_SN,
+  TILEPRO_OPC_S1A_SN, TILEPRO_OPC_S2A_SN, TILEPRO_OPC_S3A_SN,
+  TILEPRO_OPC_SADAB_U_SN, TILEPRO_OPC_SADAH_SN, TILEPRO_OPC_SADAH_U_SN,
+  TILEPRO_OPC_SADB_U_SN, TILEPRO_OPC_SADH_SN, TILEPRO_OPC_SADH_U_SN,
   BITFIELD(12, 2) /* index 731 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, CHILD(736),
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, CHILD(736),
   BITFIELD(14, 2) /* index 736 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, CHILD(741),
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, CHILD(741),
   BITFIELD(16, 2) /* index 741 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_MOVE_SN,
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN,
+  TILEPRO_OPC_MOVE_SN,
   BITFIELD(18, 4) /* index 746 */,
-  TILE_OPC_SEQB_SN, TILE_OPC_SEQH_SN, TILE_OPC_SEQ_SN, TILE_OPC_SHLB_SN,
-  TILE_OPC_SHLH_SN, TILE_OPC_SHL_SN, TILE_OPC_SHRB_SN, TILE_OPC_SHRH_SN,
-  TILE_OPC_SHR_SN, TILE_OPC_SLTB_SN, TILE_OPC_SLTB_U_SN, TILE_OPC_SLTEB_SN,
-  TILE_OPC_SLTEB_U_SN, TILE_OPC_SLTEH_SN, TILE_OPC_SLTEH_U_SN,
-  TILE_OPC_SLTE_SN,
+  TILEPRO_OPC_SEQB_SN, TILEPRO_OPC_SEQH_SN, TILEPRO_OPC_SEQ_SN,
+  TILEPRO_OPC_SHLB_SN, TILEPRO_OPC_SHLH_SN, TILEPRO_OPC_SHL_SN,
+  TILEPRO_OPC_SHRB_SN, TILEPRO_OPC_SHRH_SN, TILEPRO_OPC_SHR_SN,
+  TILEPRO_OPC_SLTB_SN, TILEPRO_OPC_SLTB_U_SN, TILEPRO_OPC_SLTEB_SN,
+  TILEPRO_OPC_SLTEB_U_SN, TILEPRO_OPC_SLTEH_SN, TILEPRO_OPC_SLTEH_U_SN,
+  TILEPRO_OPC_SLTE_SN,
   BITFIELD(18, 4) /* index 763 */,
-  TILE_OPC_SLTE_U_SN, TILE_OPC_SLTH_SN, TILE_OPC_SLTH_U_SN, TILE_OPC_SLT_SN,
-  TILE_OPC_SLT_U_SN, TILE_OPC_SNEB_SN, TILE_OPC_SNEH_SN, TILE_OPC_SNE_SN,
-  TILE_OPC_SRAB_SN, TILE_OPC_SRAH_SN, TILE_OPC_SRA_SN, TILE_OPC_SUBB_SN,
-  TILE_OPC_SUBH_SN, TILE_OPC_SUB_SN, TILE_OPC_XOR_SN, TILE_OPC_DWORD_ALIGN_SN,
+  TILEPRO_OPC_SLTE_U_SN, TILEPRO_OPC_SLTH_SN, TILEPRO_OPC_SLTH_U_SN,
+  TILEPRO_OPC_SLT_SN, TILEPRO_OPC_SLT_U_SN, TILEPRO_OPC_SNEB_SN,
+  TILEPRO_OPC_SNEH_SN, TILEPRO_OPC_SNE_SN, TILEPRO_OPC_SRAB_SN,
+  TILEPRO_OPC_SRAH_SN, TILEPRO_OPC_SRA_SN, TILEPRO_OPC_SUBB_SN,
+  TILEPRO_OPC_SUBH_SN, TILEPRO_OPC_SUB_SN, TILEPRO_OPC_XOR_SN,
+  TILEPRO_OPC_DWORD_ALIGN_SN,
   BITFIELD(18, 3) /* index 780 */,
   CHILD(789), CHILD(792), CHILD(795), CHILD(798), CHILD(801), CHILD(804),
   CHILD(807), CHILD(810),
   BITFIELD(21, 1) /* index 789 */,
-  TILE_OPC_ADDS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDS_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 792 */,
-  TILE_OPC_SUBS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBS_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 795 */,
-  TILE_OPC_ADDBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 798 */,
-  TILE_OPC_ADDHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 801 */,
-  TILE_OPC_SUBBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 804 */,
-  TILE_OPC_SUBHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 807 */,
-  TILE_OPC_PACKHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 810 */,
-  TILE_OPC_PACKBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(6, 2) /* index 813 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, CHILD(818),
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  CHILD(818),
   BITFIELD(8, 2) /* index 818 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, CHILD(823),
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  CHILD(823),
   BITFIELD(10, 2) /* index 823 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_MOVELI_SN,
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  TILEPRO_OPC_MOVELI_SN,
   BITFIELD(6, 2) /* index 828 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, CHILD(833),
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, CHILD(833),
   BITFIELD(8, 2) /* index 833 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, CHILD(838),
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, CHILD(838),
   BITFIELD(10, 2) /* index 838 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_MOVELI,
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_MOVELI,
   BITFIELD(0, 2) /* index 843 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(848),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(848),
   BITFIELD(2, 2) /* index 848 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(853),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(853),
   BITFIELD(4, 2) /* index 853 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(858),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(858),
   BITFIELD(6, 2) /* index 858 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(863),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(863),
   BITFIELD(8, 2) /* index 863 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(868),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(868),
   BITFIELD(10, 2) /* index 868 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_INFOL,
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_INFOL,
   BITFIELD(20, 2) /* index 873 */,
-  TILE_OPC_NONE, TILE_OPC_ADDIB, TILE_OPC_ADDIH, TILE_OPC_ADDI,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDIB, TILEPRO_OPC_ADDIH, TILEPRO_OPC_ADDI,
   BITFIELD(20, 2) /* index 878 */,
-  TILE_OPC_MAXIB_U, TILE_OPC_MAXIH, TILE_OPC_MINIB_U, TILE_OPC_MINIH,
+  TILEPRO_OPC_MAXIB_U, TILEPRO_OPC_MAXIH, TILEPRO_OPC_MINIB_U,
+  TILEPRO_OPC_MINIH,
   BITFIELD(20, 2) /* index 883 */,
-  CHILD(888), TILE_OPC_SEQIB, TILE_OPC_SEQIH, TILE_OPC_SEQI,
+  CHILD(888), TILEPRO_OPC_SEQIB, TILEPRO_OPC_SEQIH, TILEPRO_OPC_SEQI,
   BITFIELD(6, 2) /* index 888 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(893),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(893),
   BITFIELD(8, 2) /* index 893 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(898),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(898),
   BITFIELD(10, 2) /* index 898 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_MOVEI,
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_MOVEI,
   BITFIELD(20, 2) /* index 903 */,
-  TILE_OPC_SLTIB, TILE_OPC_SLTIB_U, TILE_OPC_SLTIH, TILE_OPC_SLTIH_U,
+  TILEPRO_OPC_SLTIB, TILEPRO_OPC_SLTIB_U, TILEPRO_OPC_SLTIH,
+  TILEPRO_OPC_SLTIH_U,
   BITFIELD(20, 2) /* index 908 */,
-  TILE_OPC_SLTI, TILE_OPC_SLTI_U, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_SLTI, TILEPRO_OPC_SLTI_U, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(20, 2) /* index 913 */,
-  TILE_OPC_NONE, TILE_OPC_ADDIB_SN, TILE_OPC_ADDIH_SN, TILE_OPC_ADDI_SN,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDIB_SN, TILEPRO_OPC_ADDIH_SN,
+  TILEPRO_OPC_ADDI_SN,
   BITFIELD(20, 2) /* index 918 */,
-  TILE_OPC_MAXIB_U_SN, TILE_OPC_MAXIH_SN, TILE_OPC_MINIB_U_SN,
-  TILE_OPC_MINIH_SN,
+  TILEPRO_OPC_MAXIB_U_SN, TILEPRO_OPC_MAXIH_SN, TILEPRO_OPC_MINIB_U_SN,
+  TILEPRO_OPC_MINIH_SN,
   BITFIELD(20, 2) /* index 923 */,
-  CHILD(928), TILE_OPC_SEQIB_SN, TILE_OPC_SEQIH_SN, TILE_OPC_SEQI_SN,
+  CHILD(928), TILEPRO_OPC_SEQIB_SN, TILEPRO_OPC_SEQIH_SN, TILEPRO_OPC_SEQI_SN,
   BITFIELD(6, 2) /* index 928 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, CHILD(933),
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, CHILD(933),
   BITFIELD(8, 2) /* index 933 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, CHILD(938),
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, CHILD(938),
   BITFIELD(10, 2) /* index 938 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_MOVEI_SN,
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN,
+  TILEPRO_OPC_MOVEI_SN,
   BITFIELD(20, 2) /* index 943 */,
-  TILE_OPC_SLTIB_SN, TILE_OPC_SLTIB_U_SN, TILE_OPC_SLTIH_SN,
-  TILE_OPC_SLTIH_U_SN,
+  TILEPRO_OPC_SLTIB_SN, TILEPRO_OPC_SLTIB_U_SN, TILEPRO_OPC_SLTIH_SN,
+  TILEPRO_OPC_SLTIH_U_SN,
   BITFIELD(20, 2) /* index 948 */,
-  TILE_OPC_SLTI_SN, TILE_OPC_SLTI_U_SN, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_SLTI_SN, TILEPRO_OPC_SLTI_U_SN, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE,
   BITFIELD(20, 2) /* index 953 */,
-  TILE_OPC_NONE, CHILD(958), TILE_OPC_XORI, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, CHILD(958), TILEPRO_OPC_XORI, TILEPRO_OPC_NONE,
   BITFIELD(0, 2) /* index 958 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(963),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(963),
   BITFIELD(2, 2) /* index 963 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(968),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(968),
   BITFIELD(4, 2) /* index 968 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(973),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(973),
   BITFIELD(6, 2) /* index 973 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(978),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(978),
   BITFIELD(8, 2) /* index 978 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(983),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(983),
   BITFIELD(10, 2) /* index 983 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_INFO,
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_INFO,
   BITFIELD(20, 2) /* index 988 */,
-  TILE_OPC_NONE, TILE_OPC_ANDI_SN, TILE_OPC_XORI_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ANDI_SN, TILEPRO_OPC_XORI_SN,
+  TILEPRO_OPC_NONE,
   BITFIELD(17, 5) /* index 993 */,
-  TILE_OPC_NONE, TILE_OPC_RLI, TILE_OPC_SHLIB, TILE_OPC_SHLIH, TILE_OPC_SHLI,
-  TILE_OPC_SHRIB, TILE_OPC_SHRIH, TILE_OPC_SHRI, TILE_OPC_SRAIB,
-  TILE_OPC_SRAIH, TILE_OPC_SRAI, CHILD(1026), TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_RLI, TILEPRO_OPC_SHLIB, TILEPRO_OPC_SHLIH,
+  TILEPRO_OPC_SHLI, TILEPRO_OPC_SHRIB, TILEPRO_OPC_SHRIH, TILEPRO_OPC_SHRI,
+  TILEPRO_OPC_SRAIB, TILEPRO_OPC_SRAIH, TILEPRO_OPC_SRAI, CHILD(1026),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(12, 4) /* index 1026 */,
-  TILE_OPC_NONE, CHILD(1043), CHILD(1046), CHILD(1049), CHILD(1052),
+  TILEPRO_OPC_NONE, CHILD(1043), CHILD(1046), CHILD(1049), CHILD(1052),
   CHILD(1055), CHILD(1058), CHILD(1061), CHILD(1064), CHILD(1067),
-  CHILD(1070), CHILD(1073), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE,
+  CHILD(1070), CHILD(1073), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1043 */,
-  TILE_OPC_BITX, TILE_OPC_NONE,
+  TILEPRO_OPC_BITX, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1046 */,
-  TILE_OPC_BYTEX, TILE_OPC_NONE,
+  TILEPRO_OPC_BYTEX, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1049 */,
-  TILE_OPC_CLZ, TILE_OPC_NONE,
+  TILEPRO_OPC_CLZ, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1052 */,
-  TILE_OPC_CTZ, TILE_OPC_NONE,
+  TILEPRO_OPC_CTZ, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1055 */,
-  TILE_OPC_FNOP, TILE_OPC_NONE,
+  TILEPRO_OPC_FNOP, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1058 */,
-  TILE_OPC_NOP, TILE_OPC_NONE,
+  TILEPRO_OPC_NOP, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1061 */,
-  TILE_OPC_PCNT, TILE_OPC_NONE,
+  TILEPRO_OPC_PCNT, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1064 */,
-  TILE_OPC_TBLIDXB0, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB0, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1067 */,
-  TILE_OPC_TBLIDXB1, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB1, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1070 */,
-  TILE_OPC_TBLIDXB2, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB2, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1073 */,
-  TILE_OPC_TBLIDXB3, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB3, TILEPRO_OPC_NONE,
   BITFIELD(17, 5) /* index 1076 */,
-  TILE_OPC_NONE, TILE_OPC_RLI_SN, TILE_OPC_SHLIB_SN, TILE_OPC_SHLIH_SN,
-  TILE_OPC_SHLI_SN, TILE_OPC_SHRIB_SN, TILE_OPC_SHRIH_SN, TILE_OPC_SHRI_SN,
-  TILE_OPC_SRAIB_SN, TILE_OPC_SRAIH_SN, TILE_OPC_SRAI_SN, CHILD(1109),
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_RLI_SN, TILEPRO_OPC_SHLIB_SN,
+  TILEPRO_OPC_SHLIH_SN, TILEPRO_OPC_SHLI_SN, TILEPRO_OPC_SHRIB_SN,
+  TILEPRO_OPC_SHRIH_SN, TILEPRO_OPC_SHRI_SN, TILEPRO_OPC_SRAIB_SN,
+  TILEPRO_OPC_SRAIH_SN, TILEPRO_OPC_SRAI_SN, CHILD(1109), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(12, 4) /* index 1109 */,
-  TILE_OPC_NONE, CHILD(1126), CHILD(1129), CHILD(1132), CHILD(1135),
+  TILEPRO_OPC_NONE, CHILD(1126), CHILD(1129), CHILD(1132), CHILD(1135),
   CHILD(1055), CHILD(1058), CHILD(1138), CHILD(1141), CHILD(1144),
-  CHILD(1147), CHILD(1150), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE,
+  CHILD(1147), CHILD(1150), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1126 */,
-  TILE_OPC_BITX_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_BITX_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1129 */,
-  TILE_OPC_BYTEX_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_BYTEX_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1132 */,
-  TILE_OPC_CLZ_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_CLZ_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1135 */,
-  TILE_OPC_CTZ_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_CTZ_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1138 */,
-  TILE_OPC_PCNT_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_PCNT_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1141 */,
-  TILE_OPC_TBLIDXB0_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB0_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1144 */,
-  TILE_OPC_TBLIDXB1_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB1_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1147 */,
-  TILE_OPC_TBLIDXB2_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB2_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1150 */,
-  TILE_OPC_TBLIDXB3_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB3_SN, TILEPRO_OPC_NONE,
 };
 
 static const unsigned short decode_X1_fsm[1540] =
 {
   BITFIELD(54, 9) /* index 0 */,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, CHILD(513), CHILD(561), CHILD(594),
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(641), CHILD(689),
-  CHILD(722), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(766),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  CHILD(513), CHILD(561), CHILD(594), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(641),
+  CHILD(689), CHILD(722), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(766),
   CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766),
   CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766),
   CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766),
@@ -1596,594 +1655,641 @@
   CHILD(826), CHILD(826), CHILD(826), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
-  CHILD(843), CHILD(860), CHILD(899), CHILD(923), CHILD(932), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, CHILD(941), CHILD(950), CHILD(974), CHILD(983),
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, CHILD(992),
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  CHILD(1334), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(843), CHILD(860), CHILD(899), CHILD(923), CHILD(932),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  CHILD(941), CHILD(950), CHILD(974), CHILD(983), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, CHILD(992),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(1334),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(49, 5) /* index 513 */,
-  TILE_OPC_NONE, TILE_OPC_ADDB, TILE_OPC_ADDH, TILE_OPC_ADD, TILE_OPC_AND,
-  TILE_OPC_INTHB, TILE_OPC_INTHH, TILE_OPC_INTLB, TILE_OPC_INTLH,
-  TILE_OPC_JALRP, TILE_OPC_JALR, TILE_OPC_JRP, TILE_OPC_JR, TILE_OPC_LNK,
-  TILE_OPC_MAXB_U, TILE_OPC_MAXH, TILE_OPC_MINB_U, TILE_OPC_MINH,
-  TILE_OPC_MNZB, TILE_OPC_MNZH, TILE_OPC_MNZ, TILE_OPC_MZB, TILE_OPC_MZH,
-  TILE_OPC_MZ, TILE_OPC_NOR, CHILD(546), TILE_OPC_PACKHB, TILE_OPC_PACKLB,
-  TILE_OPC_RL, TILE_OPC_S1A, TILE_OPC_S2A, TILE_OPC_S3A,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDB, TILEPRO_OPC_ADDH, TILEPRO_OPC_ADD,
+  TILEPRO_OPC_AND, TILEPRO_OPC_INTHB, TILEPRO_OPC_INTHH, TILEPRO_OPC_INTLB,
+  TILEPRO_OPC_INTLH, TILEPRO_OPC_JALRP, TILEPRO_OPC_JALR, TILEPRO_OPC_JRP,
+  TILEPRO_OPC_JR, TILEPRO_OPC_LNK, TILEPRO_OPC_MAXB_U, TILEPRO_OPC_MAXH,
+  TILEPRO_OPC_MINB_U, TILEPRO_OPC_MINH, TILEPRO_OPC_MNZB, TILEPRO_OPC_MNZH,
+  TILEPRO_OPC_MNZ, TILEPRO_OPC_MZB, TILEPRO_OPC_MZH, TILEPRO_OPC_MZ,
+  TILEPRO_OPC_NOR, CHILD(546), TILEPRO_OPC_PACKHB, TILEPRO_OPC_PACKLB,
+  TILEPRO_OPC_RL, TILEPRO_OPC_S1A, TILEPRO_OPC_S2A, TILEPRO_OPC_S3A,
   BITFIELD(43, 2) /* index 546 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(551),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(551),
   BITFIELD(45, 2) /* index 551 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(556),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(556),
   BITFIELD(47, 2) /* index 556 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_MOVE,
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_MOVE,
   BITFIELD(49, 5) /* index 561 */,
-  TILE_OPC_SB, TILE_OPC_SEQB, TILE_OPC_SEQH, TILE_OPC_SEQ, TILE_OPC_SHLB,
-  TILE_OPC_SHLH, TILE_OPC_SHL, TILE_OPC_SHRB, TILE_OPC_SHRH, TILE_OPC_SHR,
-  TILE_OPC_SH, TILE_OPC_SLTB, TILE_OPC_SLTB_U, TILE_OPC_SLTEB,
-  TILE_OPC_SLTEB_U, TILE_OPC_SLTEH, TILE_OPC_SLTEH_U, TILE_OPC_SLTE,
-  TILE_OPC_SLTE_U, TILE_OPC_SLTH, TILE_OPC_SLTH_U, TILE_OPC_SLT,
-  TILE_OPC_SLT_U, TILE_OPC_SNEB, TILE_OPC_SNEH, TILE_OPC_SNE, TILE_OPC_SRAB,
-  TILE_OPC_SRAH, TILE_OPC_SRA, TILE_OPC_SUBB, TILE_OPC_SUBH, TILE_OPC_SUB,
+  TILEPRO_OPC_SB, TILEPRO_OPC_SEQB, TILEPRO_OPC_SEQH, TILEPRO_OPC_SEQ,
+  TILEPRO_OPC_SHLB, TILEPRO_OPC_SHLH, TILEPRO_OPC_SHL, TILEPRO_OPC_SHRB,
+  TILEPRO_OPC_SHRH, TILEPRO_OPC_SHR, TILEPRO_OPC_SH, TILEPRO_OPC_SLTB,
+  TILEPRO_OPC_SLTB_U, TILEPRO_OPC_SLTEB, TILEPRO_OPC_SLTEB_U,
+  TILEPRO_OPC_SLTEH, TILEPRO_OPC_SLTEH_U, TILEPRO_OPC_SLTE,
+  TILEPRO_OPC_SLTE_U, TILEPRO_OPC_SLTH, TILEPRO_OPC_SLTH_U, TILEPRO_OPC_SLT,
+  TILEPRO_OPC_SLT_U, TILEPRO_OPC_SNEB, TILEPRO_OPC_SNEH, TILEPRO_OPC_SNE,
+  TILEPRO_OPC_SRAB, TILEPRO_OPC_SRAH, TILEPRO_OPC_SRA, TILEPRO_OPC_SUBB,
+  TILEPRO_OPC_SUBH, TILEPRO_OPC_SUB,
   BITFIELD(49, 4) /* index 594 */,
   CHILD(611), CHILD(614), CHILD(617), CHILD(620), CHILD(623), CHILD(626),
-  CHILD(629), CHILD(632), CHILD(635), CHILD(638), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(629), CHILD(632), CHILD(635), CHILD(638), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 611 */,
-  TILE_OPC_SW, TILE_OPC_NONE,
+  TILEPRO_OPC_SW, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 614 */,
-  TILE_OPC_XOR, TILE_OPC_NONE,
+  TILEPRO_OPC_XOR, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 617 */,
-  TILE_OPC_ADDS, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 620 */,
-  TILE_OPC_SUBS, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 623 */,
-  TILE_OPC_ADDBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDBS_U, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 626 */,
-  TILE_OPC_ADDHS, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDHS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 629 */,
-  TILE_OPC_SUBBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBBS_U, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 632 */,
-  TILE_OPC_SUBHS, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBHS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 635 */,
-  TILE_OPC_PACKHS, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKHS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 638 */,
-  TILE_OPC_PACKBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKBS_U, TILEPRO_OPC_NONE,
   BITFIELD(49, 5) /* index 641 */,
-  TILE_OPC_NONE, TILE_OPC_ADDB_SN, TILE_OPC_ADDH_SN, TILE_OPC_ADD_SN,
-  TILE_OPC_AND_SN, TILE_OPC_INTHB_SN, TILE_OPC_INTHH_SN, TILE_OPC_INTLB_SN,
-  TILE_OPC_INTLH_SN, TILE_OPC_JALRP, TILE_OPC_JALR, TILE_OPC_JRP, TILE_OPC_JR,
-  TILE_OPC_LNK_SN, TILE_OPC_MAXB_U_SN, TILE_OPC_MAXH_SN, TILE_OPC_MINB_U_SN,
-  TILE_OPC_MINH_SN, TILE_OPC_MNZB_SN, TILE_OPC_MNZH_SN, TILE_OPC_MNZ_SN,
-  TILE_OPC_MZB_SN, TILE_OPC_MZH_SN, TILE_OPC_MZ_SN, TILE_OPC_NOR_SN,
-  CHILD(674), TILE_OPC_PACKHB_SN, TILE_OPC_PACKLB_SN, TILE_OPC_RL_SN,
-  TILE_OPC_S1A_SN, TILE_OPC_S2A_SN, TILE_OPC_S3A_SN,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDB_SN, TILEPRO_OPC_ADDH_SN,
+  TILEPRO_OPC_ADD_SN, TILEPRO_OPC_AND_SN, TILEPRO_OPC_INTHB_SN,
+  TILEPRO_OPC_INTHH_SN, TILEPRO_OPC_INTLB_SN, TILEPRO_OPC_INTLH_SN,
+  TILEPRO_OPC_JALRP, TILEPRO_OPC_JALR, TILEPRO_OPC_JRP, TILEPRO_OPC_JR,
+  TILEPRO_OPC_LNK_SN, TILEPRO_OPC_MAXB_U_SN, TILEPRO_OPC_MAXH_SN,
+  TILEPRO_OPC_MINB_U_SN, TILEPRO_OPC_MINH_SN, TILEPRO_OPC_MNZB_SN,
+  TILEPRO_OPC_MNZH_SN, TILEPRO_OPC_MNZ_SN, TILEPRO_OPC_MZB_SN,
+  TILEPRO_OPC_MZH_SN, TILEPRO_OPC_MZ_SN, TILEPRO_OPC_NOR_SN, CHILD(674),
+  TILEPRO_OPC_PACKHB_SN, TILEPRO_OPC_PACKLB_SN, TILEPRO_OPC_RL_SN,
+  TILEPRO_OPC_S1A_SN, TILEPRO_OPC_S2A_SN, TILEPRO_OPC_S3A_SN,
   BITFIELD(43, 2) /* index 674 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, CHILD(679),
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, CHILD(679),
   BITFIELD(45, 2) /* index 679 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, CHILD(684),
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, CHILD(684),
   BITFIELD(47, 2) /* index 684 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_MOVE_SN,
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN,
+  TILEPRO_OPC_MOVE_SN,
   BITFIELD(49, 5) /* index 689 */,
-  TILE_OPC_SB, TILE_OPC_SEQB_SN, TILE_OPC_SEQH_SN, TILE_OPC_SEQ_SN,
-  TILE_OPC_SHLB_SN, TILE_OPC_SHLH_SN, TILE_OPC_SHL_SN, TILE_OPC_SHRB_SN,
-  TILE_OPC_SHRH_SN, TILE_OPC_SHR_SN, TILE_OPC_SH, TILE_OPC_SLTB_SN,
-  TILE_OPC_SLTB_U_SN, TILE_OPC_SLTEB_SN, TILE_OPC_SLTEB_U_SN,
-  TILE_OPC_SLTEH_SN, TILE_OPC_SLTEH_U_SN, TILE_OPC_SLTE_SN,
-  TILE_OPC_SLTE_U_SN, TILE_OPC_SLTH_SN, TILE_OPC_SLTH_U_SN, TILE_OPC_SLT_SN,
-  TILE_OPC_SLT_U_SN, TILE_OPC_SNEB_SN, TILE_OPC_SNEH_SN, TILE_OPC_SNE_SN,
-  TILE_OPC_SRAB_SN, TILE_OPC_SRAH_SN, TILE_OPC_SRA_SN, TILE_OPC_SUBB_SN,
-  TILE_OPC_SUBH_SN, TILE_OPC_SUB_SN,
+  TILEPRO_OPC_SB, TILEPRO_OPC_SEQB_SN, TILEPRO_OPC_SEQH_SN,
+  TILEPRO_OPC_SEQ_SN, TILEPRO_OPC_SHLB_SN, TILEPRO_OPC_SHLH_SN,
+  TILEPRO_OPC_SHL_SN, TILEPRO_OPC_SHRB_SN, TILEPRO_OPC_SHRH_SN,
+  TILEPRO_OPC_SHR_SN, TILEPRO_OPC_SH, TILEPRO_OPC_SLTB_SN,
+  TILEPRO_OPC_SLTB_U_SN, TILEPRO_OPC_SLTEB_SN, TILEPRO_OPC_SLTEB_U_SN,
+  TILEPRO_OPC_SLTEH_SN, TILEPRO_OPC_SLTEH_U_SN, TILEPRO_OPC_SLTE_SN,
+  TILEPRO_OPC_SLTE_U_SN, TILEPRO_OPC_SLTH_SN, TILEPRO_OPC_SLTH_U_SN,
+  TILEPRO_OPC_SLT_SN, TILEPRO_OPC_SLT_U_SN, TILEPRO_OPC_SNEB_SN,
+  TILEPRO_OPC_SNEH_SN, TILEPRO_OPC_SNE_SN, TILEPRO_OPC_SRAB_SN,
+  TILEPRO_OPC_SRAH_SN, TILEPRO_OPC_SRA_SN, TILEPRO_OPC_SUBB_SN,
+  TILEPRO_OPC_SUBH_SN, TILEPRO_OPC_SUB_SN,
   BITFIELD(49, 4) /* index 722 */,
   CHILD(611), CHILD(739), CHILD(742), CHILD(745), CHILD(748), CHILD(751),
-  CHILD(754), CHILD(757), CHILD(760), CHILD(763), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(754), CHILD(757), CHILD(760), CHILD(763), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 739 */,
-  TILE_OPC_XOR_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_XOR_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 742 */,
-  TILE_OPC_ADDS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDS_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 745 */,
-  TILE_OPC_SUBS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBS_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 748 */,
-  TILE_OPC_ADDBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 751 */,
-  TILE_OPC_ADDHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 754 */,
-  TILE_OPC_SUBBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 757 */,
-  TILE_OPC_SUBHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 760 */,
-  TILE_OPC_PACKHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 763 */,
-  TILE_OPC_PACKBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(37, 2) /* index 766 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, CHILD(771),
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  CHILD(771),
   BITFIELD(39, 2) /* index 771 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, CHILD(776),
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  CHILD(776),
   BITFIELD(41, 2) /* index 776 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_MOVELI_SN,
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  TILEPRO_OPC_MOVELI_SN,
   BITFIELD(37, 2) /* index 781 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, CHILD(786),
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, CHILD(786),
   BITFIELD(39, 2) /* index 786 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, CHILD(791),
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, CHILD(791),
   BITFIELD(41, 2) /* index 791 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_MOVELI,
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_MOVELI,
   BITFIELD(31, 2) /* index 796 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(801),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(801),
   BITFIELD(33, 2) /* index 801 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(806),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(806),
   BITFIELD(35, 2) /* index 806 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(811),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(811),
   BITFIELD(37, 2) /* index 811 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(816),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(816),
   BITFIELD(39, 2) /* index 816 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(821),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(821),
   BITFIELD(41, 2) /* index 821 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_INFOL,
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_INFOL,
   BITFIELD(31, 4) /* index 826 */,
-  TILE_OPC_BZ, TILE_OPC_BZT, TILE_OPC_BNZ, TILE_OPC_BNZT, TILE_OPC_BGZ,
-  TILE_OPC_BGZT, TILE_OPC_BGEZ, TILE_OPC_BGEZT, TILE_OPC_BLZ, TILE_OPC_BLZT,
-  TILE_OPC_BLEZ, TILE_OPC_BLEZT, TILE_OPC_BBS, TILE_OPC_BBST, TILE_OPC_BBNS,
-  TILE_OPC_BBNST,
+  TILEPRO_OPC_BZ, TILEPRO_OPC_BZT, TILEPRO_OPC_BNZ, TILEPRO_OPC_BNZT,
+  TILEPRO_OPC_BGZ, TILEPRO_OPC_BGZT, TILEPRO_OPC_BGEZ, TILEPRO_OPC_BGEZT,
+  TILEPRO_OPC_BLZ, TILEPRO_OPC_BLZT, TILEPRO_OPC_BLEZ, TILEPRO_OPC_BLEZT,
+  TILEPRO_OPC_BBS, TILEPRO_OPC_BBST, TILEPRO_OPC_BBNS, TILEPRO_OPC_BBNST,
   BITFIELD(31, 4) /* index 843 */,
-  TILE_OPC_BZ_SN, TILE_OPC_BZT_SN, TILE_OPC_BNZ_SN, TILE_OPC_BNZT_SN,
-  TILE_OPC_BGZ_SN, TILE_OPC_BGZT_SN, TILE_OPC_BGEZ_SN, TILE_OPC_BGEZT_SN,
-  TILE_OPC_BLZ_SN, TILE_OPC_BLZT_SN, TILE_OPC_BLEZ_SN, TILE_OPC_BLEZT_SN,
-  TILE_OPC_BBS_SN, TILE_OPC_BBST_SN, TILE_OPC_BBNS_SN, TILE_OPC_BBNST_SN,
+  TILEPRO_OPC_BZ_SN, TILEPRO_OPC_BZT_SN, TILEPRO_OPC_BNZ_SN,
+  TILEPRO_OPC_BNZT_SN, TILEPRO_OPC_BGZ_SN, TILEPRO_OPC_BGZT_SN,
+  TILEPRO_OPC_BGEZ_SN, TILEPRO_OPC_BGEZT_SN, TILEPRO_OPC_BLZ_SN,
+  TILEPRO_OPC_BLZT_SN, TILEPRO_OPC_BLEZ_SN, TILEPRO_OPC_BLEZT_SN,
+  TILEPRO_OPC_BBS_SN, TILEPRO_OPC_BBST_SN, TILEPRO_OPC_BBNS_SN,
+  TILEPRO_OPC_BBNST_SN,
   BITFIELD(51, 3) /* index 860 */,
-  TILE_OPC_NONE, TILE_OPC_ADDIB, TILE_OPC_ADDIH, TILE_OPC_ADDI, CHILD(869),
-  TILE_OPC_MAXIB_U, TILE_OPC_MAXIH, TILE_OPC_MFSPR,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDIB, TILEPRO_OPC_ADDIH, TILEPRO_OPC_ADDI,
+  CHILD(869), TILEPRO_OPC_MAXIB_U, TILEPRO_OPC_MAXIH, TILEPRO_OPC_MFSPR,
   BITFIELD(31, 2) /* index 869 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(874),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(874),
   BITFIELD(33, 2) /* index 874 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(879),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(879),
   BITFIELD(35, 2) /* index 879 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(884),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(884),
   BITFIELD(37, 2) /* index 884 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(889),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(889),
   BITFIELD(39, 2) /* index 889 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(894),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(894),
   BITFIELD(41, 2) /* index 894 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_INFO,
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_INFO,
   BITFIELD(51, 3) /* index 899 */,
-  TILE_OPC_MINIB_U, TILE_OPC_MINIH, TILE_OPC_MTSPR, CHILD(908),
-  TILE_OPC_SEQIB, TILE_OPC_SEQIH, TILE_OPC_SEQI, TILE_OPC_SLTIB,
+  TILEPRO_OPC_MINIB_U, TILEPRO_OPC_MINIH, TILEPRO_OPC_MTSPR, CHILD(908),
+  TILEPRO_OPC_SEQIB, TILEPRO_OPC_SEQIH, TILEPRO_OPC_SEQI, TILEPRO_OPC_SLTIB,
   BITFIELD(37, 2) /* index 908 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(913),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(913),
   BITFIELD(39, 2) /* index 913 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(918),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(918),
   BITFIELD(41, 2) /* index 918 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_MOVEI,
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_MOVEI,
   BITFIELD(51, 3) /* index 923 */,
-  TILE_OPC_SLTIB_U, TILE_OPC_SLTIH, TILE_OPC_SLTIH_U, TILE_OPC_SLTI,
-  TILE_OPC_SLTI_U, TILE_OPC_XORI, TILE_OPC_LBADD, TILE_OPC_LBADD_U,
+  TILEPRO_OPC_SLTIB_U, TILEPRO_OPC_SLTIH, TILEPRO_OPC_SLTIH_U,
+  TILEPRO_OPC_SLTI, TILEPRO_OPC_SLTI_U, TILEPRO_OPC_XORI, TILEPRO_OPC_LBADD,
+  TILEPRO_OPC_LBADD_U,
   BITFIELD(51, 3) /* index 932 */,
-  TILE_OPC_LHADD, TILE_OPC_LHADD_U, TILE_OPC_LWADD, TILE_OPC_LWADD_NA,
-  TILE_OPC_SBADD, TILE_OPC_SHADD, TILE_OPC_SWADD, TILE_OPC_NONE,
+  TILEPRO_OPC_LHADD, TILEPRO_OPC_LHADD_U, TILEPRO_OPC_LWADD,
+  TILEPRO_OPC_LWADD_NA, TILEPRO_OPC_SBADD, TILEPRO_OPC_SHADD,
+  TILEPRO_OPC_SWADD, TILEPRO_OPC_NONE,
   BITFIELD(51, 3) /* index 941 */,
-  TILE_OPC_NONE, TILE_OPC_ADDIB_SN, TILE_OPC_ADDIH_SN, TILE_OPC_ADDI_SN,
-  TILE_OPC_ANDI_SN, TILE_OPC_MAXIB_U_SN, TILE_OPC_MAXIH_SN, TILE_OPC_MFSPR,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDIB_SN, TILEPRO_OPC_ADDIH_SN,
+  TILEPRO_OPC_ADDI_SN, TILEPRO_OPC_ANDI_SN, TILEPRO_OPC_MAXIB_U_SN,
+  TILEPRO_OPC_MAXIH_SN, TILEPRO_OPC_MFSPR,
   BITFIELD(51, 3) /* index 950 */,
-  TILE_OPC_MINIB_U_SN, TILE_OPC_MINIH_SN, TILE_OPC_MTSPR, CHILD(959),
-  TILE_OPC_SEQIB_SN, TILE_OPC_SEQIH_SN, TILE_OPC_SEQI_SN, TILE_OPC_SLTIB_SN,
+  TILEPRO_OPC_MINIB_U_SN, TILEPRO_OPC_MINIH_SN, TILEPRO_OPC_MTSPR, CHILD(959),
+  TILEPRO_OPC_SEQIB_SN, TILEPRO_OPC_SEQIH_SN, TILEPRO_OPC_SEQI_SN,
+  TILEPRO_OPC_SLTIB_SN,
   BITFIELD(37, 2) /* index 959 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, CHILD(964),
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, CHILD(964),
   BITFIELD(39, 2) /* index 964 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, CHILD(969),
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, CHILD(969),
   BITFIELD(41, 2) /* index 969 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_MOVEI_SN,
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN,
+  TILEPRO_OPC_MOVEI_SN,
   BITFIELD(51, 3) /* index 974 */,
-  TILE_OPC_SLTIB_U_SN, TILE_OPC_SLTIH_SN, TILE_OPC_SLTIH_U_SN,
-  TILE_OPC_SLTI_SN, TILE_OPC_SLTI_U_SN, TILE_OPC_XORI_SN, TILE_OPC_LBADD_SN,
-  TILE_OPC_LBADD_U_SN,
+  TILEPRO_OPC_SLTIB_U_SN, TILEPRO_OPC_SLTIH_SN, TILEPRO_OPC_SLTIH_U_SN,
+  TILEPRO_OPC_SLTI_SN, TILEPRO_OPC_SLTI_U_SN, TILEPRO_OPC_XORI_SN,
+  TILEPRO_OPC_LBADD_SN, TILEPRO_OPC_LBADD_U_SN,
   BITFIELD(51, 3) /* index 983 */,
-  TILE_OPC_LHADD_SN, TILE_OPC_LHADD_U_SN, TILE_OPC_LWADD_SN,
-  TILE_OPC_LWADD_NA_SN, TILE_OPC_SBADD, TILE_OPC_SHADD, TILE_OPC_SWADD,
-  TILE_OPC_NONE,
+  TILEPRO_OPC_LHADD_SN, TILEPRO_OPC_LHADD_U_SN, TILEPRO_OPC_LWADD_SN,
+  TILEPRO_OPC_LWADD_NA_SN, TILEPRO_OPC_SBADD, TILEPRO_OPC_SHADD,
+  TILEPRO_OPC_SWADD, TILEPRO_OPC_NONE,
   BITFIELD(46, 7) /* index 992 */,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(1121),
-  CHILD(1121), CHILD(1121), CHILD(1121), CHILD(1124), CHILD(1124),
-  CHILD(1124), CHILD(1124), CHILD(1127), CHILD(1127), CHILD(1127),
-  CHILD(1127), CHILD(1130), CHILD(1130), CHILD(1130), CHILD(1130),
-  CHILD(1133), CHILD(1133), CHILD(1133), CHILD(1133), CHILD(1136),
-  CHILD(1136), CHILD(1136), CHILD(1136), CHILD(1139), CHILD(1139),
-  CHILD(1139), CHILD(1139), CHILD(1142), CHILD(1142), CHILD(1142),
-  CHILD(1142), CHILD(1145), CHILD(1145), CHILD(1145), CHILD(1145),
-  CHILD(1148), CHILD(1148), CHILD(1148), CHILD(1148), CHILD(1151),
-  CHILD(1242), CHILD(1290), CHILD(1323), TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  CHILD(1121), CHILD(1121), CHILD(1121), CHILD(1121), CHILD(1124),
+  CHILD(1124), CHILD(1124), CHILD(1124), CHILD(1127), CHILD(1127),
+  CHILD(1127), CHILD(1127), CHILD(1130), CHILD(1130), CHILD(1130),
+  CHILD(1130), CHILD(1133), CHILD(1133), CHILD(1133), CHILD(1133),
+  CHILD(1136), CHILD(1136), CHILD(1136), CHILD(1136), CHILD(1139),
+  CHILD(1139), CHILD(1139), CHILD(1139), CHILD(1142), CHILD(1142),
+  CHILD(1142), CHILD(1142), CHILD(1145), CHILD(1145), CHILD(1145),
+  CHILD(1145), CHILD(1148), CHILD(1148), CHILD(1148), CHILD(1148),
+  CHILD(1151), CHILD(1242), CHILD(1290), CHILD(1323), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1121 */,
-  TILE_OPC_RLI, TILE_OPC_NONE,
+  TILEPRO_OPC_RLI, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1124 */,
-  TILE_OPC_SHLIB, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLIB, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1127 */,
-  TILE_OPC_SHLIH, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLIH, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1130 */,
-  TILE_OPC_SHLI, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLI, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1133 */,
-  TILE_OPC_SHRIB, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRIB, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1136 */,
-  TILE_OPC_SHRIH, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRIH, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1139 */,
-  TILE_OPC_SHRI, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRI, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1142 */,
-  TILE_OPC_SRAIB, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAIB, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1145 */,
-  TILE_OPC_SRAIH, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAIH, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1148 */,
-  TILE_OPC_SRAI, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAI, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 1151 */,
-  TILE_OPC_NONE, CHILD(1160), CHILD(1163), CHILD(1166), CHILD(1169),
+  TILEPRO_OPC_NONE, CHILD(1160), CHILD(1163), CHILD(1166), CHILD(1169),
   CHILD(1172), CHILD(1175), CHILD(1178),
   BITFIELD(53, 1) /* index 1160 */,
-  TILE_OPC_DRAIN, TILE_OPC_NONE,
+  TILEPRO_OPC_DRAIN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1163 */,
-  TILE_OPC_DTLBPR, TILE_OPC_NONE,
+  TILEPRO_OPC_DTLBPR, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1166 */,
-  TILE_OPC_FINV, TILE_OPC_NONE,
+  TILEPRO_OPC_FINV, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1169 */,
-  TILE_OPC_FLUSH, TILE_OPC_NONE,
+  TILEPRO_OPC_FLUSH, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1172 */,
-  TILE_OPC_FNOP, TILE_OPC_NONE,
+  TILEPRO_OPC_FNOP, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1175 */,
-  TILE_OPC_ICOH, TILE_OPC_NONE,
+  TILEPRO_OPC_ICOH, TILEPRO_OPC_NONE,
   BITFIELD(31, 2) /* index 1178 */,
   CHILD(1183), CHILD(1211), CHILD(1239), CHILD(1239),
   BITFIELD(53, 1) /* index 1183 */,
-  CHILD(1186), TILE_OPC_NONE,
+  CHILD(1186), TILEPRO_OPC_NONE,
   BITFIELD(33, 2) /* index 1186 */,
-  TILE_OPC_ILL, TILE_OPC_ILL, TILE_OPC_ILL, CHILD(1191),
+  TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, CHILD(1191),
   BITFIELD(35, 2) /* index 1191 */,
-  TILE_OPC_ILL, CHILD(1196), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1196), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(37, 2) /* index 1196 */,
-  TILE_OPC_ILL, CHILD(1201), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1201), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(39, 2) /* index 1201 */,
-  TILE_OPC_ILL, CHILD(1206), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1206), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(41, 2) /* index 1206 */,
-  TILE_OPC_ILL, TILE_OPC_ILL, TILE_OPC_BPT, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, TILEPRO_OPC_BPT, TILEPRO_OPC_ILL,
   BITFIELD(53, 1) /* index 1211 */,
-  CHILD(1214), TILE_OPC_NONE,
+  CHILD(1214), TILEPRO_OPC_NONE,
   BITFIELD(33, 2) /* index 1214 */,
-  TILE_OPC_ILL, TILE_OPC_ILL, TILE_OPC_ILL, CHILD(1219),
+  TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, CHILD(1219),
   BITFIELD(35, 2) /* index 1219 */,
-  TILE_OPC_ILL, CHILD(1224), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1224), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(37, 2) /* index 1224 */,
-  TILE_OPC_ILL, CHILD(1229), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1229), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(39, 2) /* index 1229 */,
-  TILE_OPC_ILL, CHILD(1234), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1234), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(41, 2) /* index 1234 */,
-  TILE_OPC_ILL, TILE_OPC_ILL, TILE_OPC_RAISE, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, TILEPRO_OPC_RAISE, TILEPRO_OPC_ILL,
   BITFIELD(53, 1) /* index 1239 */,
-  TILE_OPC_ILL, TILE_OPC_NONE,
+  TILEPRO_OPC_ILL, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 1242 */,
   CHILD(1251), CHILD(1254), CHILD(1257), CHILD(1275), CHILD(1278),
   CHILD(1281), CHILD(1284), CHILD(1287),
   BITFIELD(53, 1) /* index 1251 */,
-  TILE_OPC_INV, TILE_OPC_NONE,
+  TILEPRO_OPC_INV, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1254 */,
-  TILE_OPC_IRET, TILE_OPC_NONE,
+  TILEPRO_OPC_IRET, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1257 */,
-  CHILD(1260), TILE_OPC_NONE,
+  CHILD(1260), TILEPRO_OPC_NONE,
   BITFIELD(31, 2) /* index 1260 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, CHILD(1265),
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, CHILD(1265),
   BITFIELD(33, 2) /* index 1265 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, CHILD(1270),
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, CHILD(1270),
   BITFIELD(35, 2) /* index 1270 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_PREFETCH,
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_PREFETCH,
   BITFIELD(53, 1) /* index 1275 */,
-  TILE_OPC_LB_U, TILE_OPC_NONE,
+  TILEPRO_OPC_LB_U, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1278 */,
-  TILE_OPC_LH, TILE_OPC_NONE,
+  TILEPRO_OPC_LH, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1281 */,
-  TILE_OPC_LH_U, TILE_OPC_NONE,
+  TILEPRO_OPC_LH_U, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1284 */,
-  TILE_OPC_LW, TILE_OPC_NONE,
+  TILEPRO_OPC_LW, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1287 */,
-  TILE_OPC_MF, TILE_OPC_NONE,
+  TILEPRO_OPC_MF, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 1290 */,
   CHILD(1299), CHILD(1302), CHILD(1305), CHILD(1308), CHILD(1311),
   CHILD(1314), CHILD(1317), CHILD(1320),
   BITFIELD(53, 1) /* index 1299 */,
-  TILE_OPC_NAP, TILE_OPC_NONE,
+  TILEPRO_OPC_NAP, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1302 */,
-  TILE_OPC_NOP, TILE_OPC_NONE,
+  TILEPRO_OPC_NOP, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1305 */,
-  TILE_OPC_SWINT0, TILE_OPC_NONE,
+  TILEPRO_OPC_SWINT0, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1308 */,
-  TILE_OPC_SWINT1, TILE_OPC_NONE,
+  TILEPRO_OPC_SWINT1, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1311 */,
-  TILE_OPC_SWINT2, TILE_OPC_NONE,
+  TILEPRO_OPC_SWINT2, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1314 */,
-  TILE_OPC_SWINT3, TILE_OPC_NONE,
+  TILEPRO_OPC_SWINT3, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1317 */,
-  TILE_OPC_TNS, TILE_OPC_NONE,
+  TILEPRO_OPC_TNS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1320 */,
-  TILE_OPC_WH64, TILE_OPC_NONE,
+  TILEPRO_OPC_WH64, TILEPRO_OPC_NONE,
   BITFIELD(43, 2) /* index 1323 */,
-  CHILD(1328), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(1328), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(45, 1) /* index 1328 */,
-  CHILD(1331), TILE_OPC_NONE,
+  CHILD(1331), TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1331 */,
-  TILE_OPC_LW_NA, TILE_OPC_NONE,
+  TILEPRO_OPC_LW_NA, TILEPRO_OPC_NONE,
   BITFIELD(46, 7) /* index 1334 */,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(1463),
-  CHILD(1463), CHILD(1463), CHILD(1463), CHILD(1466), CHILD(1466),
-  CHILD(1466), CHILD(1466), CHILD(1469), CHILD(1469), CHILD(1469),
-  CHILD(1469), CHILD(1472), CHILD(1472), CHILD(1472), CHILD(1472),
-  CHILD(1475), CHILD(1475), CHILD(1475), CHILD(1475), CHILD(1478),
-  CHILD(1478), CHILD(1478), CHILD(1478), CHILD(1481), CHILD(1481),
-  CHILD(1481), CHILD(1481), CHILD(1484), CHILD(1484), CHILD(1484),
-  CHILD(1484), CHILD(1487), CHILD(1487), CHILD(1487), CHILD(1487),
-  CHILD(1490), CHILD(1490), CHILD(1490), CHILD(1490), CHILD(1151),
-  CHILD(1493), CHILD(1517), CHILD(1529), TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  CHILD(1463), CHILD(1463), CHILD(1463), CHILD(1463), CHILD(1466),
+  CHILD(1466), CHILD(1466), CHILD(1466), CHILD(1469), CHILD(1469),
+  CHILD(1469), CHILD(1469), CHILD(1472), CHILD(1472), CHILD(1472),
+  CHILD(1472), CHILD(1475), CHILD(1475), CHILD(1475), CHILD(1475),
+  CHILD(1478), CHILD(1478), CHILD(1478), CHILD(1478), CHILD(1481),
+  CHILD(1481), CHILD(1481), CHILD(1481), CHILD(1484), CHILD(1484),
+  CHILD(1484), CHILD(1484), CHILD(1487), CHILD(1487), CHILD(1487),
+  CHILD(1487), CHILD(1490), CHILD(1490), CHILD(1490), CHILD(1490),
+  CHILD(1151), CHILD(1493), CHILD(1517), CHILD(1529), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1463 */,
-  TILE_OPC_RLI_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_RLI_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1466 */,
-  TILE_OPC_SHLIB_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLIB_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1469 */,
-  TILE_OPC_SHLIH_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLIH_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1472 */,
-  TILE_OPC_SHLI_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLI_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1475 */,
-  TILE_OPC_SHRIB_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRIB_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1478 */,
-  TILE_OPC_SHRIH_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRIH_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1481 */,
-  TILE_OPC_SHRI_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRI_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1484 */,
-  TILE_OPC_SRAIB_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAIB_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1487 */,
-  TILE_OPC_SRAIH_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAIH_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1490 */,
-  TILE_OPC_SRAI_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAI_SN, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 1493 */,
   CHILD(1251), CHILD(1254), CHILD(1502), CHILD(1505), CHILD(1508),
   CHILD(1511), CHILD(1514), CHILD(1287),
   BITFIELD(53, 1) /* index 1502 */,
-  TILE_OPC_LB_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LB_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1505 */,
-  TILE_OPC_LB_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LB_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1508 */,
-  TILE_OPC_LH_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LH_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1511 */,
-  TILE_OPC_LH_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LH_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1514 */,
-  TILE_OPC_LW_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LW_SN, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 1517 */,
   CHILD(1299), CHILD(1302), CHILD(1305), CHILD(1308), CHILD(1311),
   CHILD(1314), CHILD(1526), CHILD(1320),
   BITFIELD(53, 1) /* index 1526 */,
-  TILE_OPC_TNS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_TNS_SN, TILEPRO_OPC_NONE,
   BITFIELD(43, 2) /* index 1529 */,
-  CHILD(1534), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(1534), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(45, 1) /* index 1534 */,
-  CHILD(1537), TILE_OPC_NONE,
+  CHILD(1537), TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1537 */,
-  TILE_OPC_LW_NA_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LW_NA_SN, TILEPRO_OPC_NONE,
 };
 
 static const unsigned short decode_Y0_fsm[168] =
 {
   BITFIELD(27, 4) /* index 0 */,
-  TILE_OPC_NONE, CHILD(17), CHILD(22), CHILD(27), CHILD(47), CHILD(52),
-  CHILD(57), CHILD(62), CHILD(67), TILE_OPC_ADDI, CHILD(72), CHILD(102),
-  TILE_OPC_SEQI, CHILD(117), TILE_OPC_SLTI, TILE_OPC_SLTI_U,
+  TILEPRO_OPC_NONE, CHILD(17), CHILD(22), CHILD(27), CHILD(47), CHILD(52),
+  CHILD(57), CHILD(62), CHILD(67), TILEPRO_OPC_ADDI, CHILD(72), CHILD(102),
+  TILEPRO_OPC_SEQI, CHILD(117), TILEPRO_OPC_SLTI, TILEPRO_OPC_SLTI_U,
   BITFIELD(18, 2) /* index 17 */,
-  TILE_OPC_ADD, TILE_OPC_S1A, TILE_OPC_S2A, TILE_OPC_SUB,
+  TILEPRO_OPC_ADD, TILEPRO_OPC_S1A, TILEPRO_OPC_S2A, TILEPRO_OPC_SUB,
   BITFIELD(18, 2) /* index 22 */,
-  TILE_OPC_MNZ, TILE_OPC_MVNZ, TILE_OPC_MVZ, TILE_OPC_MZ,
+  TILEPRO_OPC_MNZ, TILEPRO_OPC_MVNZ, TILEPRO_OPC_MVZ, TILEPRO_OPC_MZ,
   BITFIELD(18, 2) /* index 27 */,
-  TILE_OPC_AND, TILE_OPC_NOR, CHILD(32), TILE_OPC_XOR,
+  TILEPRO_OPC_AND, TILEPRO_OPC_NOR, CHILD(32), TILEPRO_OPC_XOR,
   BITFIELD(12, 2) /* index 32 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(37),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(37),
   BITFIELD(14, 2) /* index 37 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(42),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(42),
   BITFIELD(16, 2) /* index 42 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_MOVE,
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_MOVE,
   BITFIELD(18, 2) /* index 47 */,
-  TILE_OPC_RL, TILE_OPC_SHL, TILE_OPC_SHR, TILE_OPC_SRA,
+  TILEPRO_OPC_RL, TILEPRO_OPC_SHL, TILEPRO_OPC_SHR, TILEPRO_OPC_SRA,
   BITFIELD(18, 2) /* index 52 */,
-  TILE_OPC_SLTE, TILE_OPC_SLTE_U, TILE_OPC_SLT, TILE_OPC_SLT_U,
+  TILEPRO_OPC_SLTE, TILEPRO_OPC_SLTE_U, TILEPRO_OPC_SLT, TILEPRO_OPC_SLT_U,
   BITFIELD(18, 2) /* index 57 */,
-  TILE_OPC_MULHLSA_UU, TILE_OPC_S3A, TILE_OPC_SEQ, TILE_OPC_SNE,
+  TILEPRO_OPC_MULHLSA_UU, TILEPRO_OPC_S3A, TILEPRO_OPC_SEQ, TILEPRO_OPC_SNE,
   BITFIELD(18, 2) /* index 62 */,
-  TILE_OPC_MULHH_SS, TILE_OPC_MULHH_UU, TILE_OPC_MULLL_SS, TILE_OPC_MULLL_UU,
+  TILEPRO_OPC_MULHH_SS, TILEPRO_OPC_MULHH_UU, TILEPRO_OPC_MULLL_SS,
+  TILEPRO_OPC_MULLL_UU,
   BITFIELD(18, 2) /* index 67 */,
-  TILE_OPC_MULHHA_SS, TILE_OPC_MULHHA_UU, TILE_OPC_MULLLA_SS,
-  TILE_OPC_MULLLA_UU,
+  TILEPRO_OPC_MULHHA_SS, TILEPRO_OPC_MULHHA_UU, TILEPRO_OPC_MULLLA_SS,
+  TILEPRO_OPC_MULLLA_UU,
   BITFIELD(0, 2) /* index 72 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(77),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(77),
   BITFIELD(2, 2) /* index 77 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(82),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(82),
   BITFIELD(4, 2) /* index 82 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(87),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(87),
   BITFIELD(6, 2) /* index 87 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(92),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(92),
   BITFIELD(8, 2) /* index 92 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(97),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(97),
   BITFIELD(10, 2) /* index 97 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_INFO,
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_INFO,
   BITFIELD(6, 2) /* index 102 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(107),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(107),
   BITFIELD(8, 2) /* index 107 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(112),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(112),
   BITFIELD(10, 2) /* index 112 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_MOVEI,
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_MOVEI,
   BITFIELD(15, 5) /* index 117 */,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_RLI,
-  TILE_OPC_RLI, TILE_OPC_RLI, TILE_OPC_RLI, TILE_OPC_SHLI, TILE_OPC_SHLI,
-  TILE_OPC_SHLI, TILE_OPC_SHLI, TILE_OPC_SHRI, TILE_OPC_SHRI, TILE_OPC_SHRI,
-  TILE_OPC_SHRI, TILE_OPC_SRAI, TILE_OPC_SRAI, TILE_OPC_SRAI, TILE_OPC_SRAI,
-  CHILD(150), CHILD(159), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_RLI, TILEPRO_OPC_RLI, TILEPRO_OPC_RLI, TILEPRO_OPC_RLI,
+  TILEPRO_OPC_SHLI, TILEPRO_OPC_SHLI, TILEPRO_OPC_SHLI, TILEPRO_OPC_SHLI,
+  TILEPRO_OPC_SHRI, TILEPRO_OPC_SHRI, TILEPRO_OPC_SHRI, TILEPRO_OPC_SHRI,
+  TILEPRO_OPC_SRAI, TILEPRO_OPC_SRAI, TILEPRO_OPC_SRAI, TILEPRO_OPC_SRAI,
+  CHILD(150), CHILD(159), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(12, 3) /* index 150 */,
-  TILE_OPC_NONE, TILE_OPC_BITX, TILE_OPC_BYTEX, TILE_OPC_CLZ, TILE_OPC_CTZ,
-  TILE_OPC_FNOP, TILE_OPC_NOP, TILE_OPC_PCNT,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_BITX, TILEPRO_OPC_BYTEX, TILEPRO_OPC_CLZ,
+  TILEPRO_OPC_CTZ, TILEPRO_OPC_FNOP, TILEPRO_OPC_NOP, TILEPRO_OPC_PCNT,
   BITFIELD(12, 3) /* index 159 */,
-  TILE_OPC_TBLIDXB0, TILE_OPC_TBLIDXB1, TILE_OPC_TBLIDXB2, TILE_OPC_TBLIDXB3,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB0, TILEPRO_OPC_TBLIDXB1, TILEPRO_OPC_TBLIDXB2,
+  TILEPRO_OPC_TBLIDXB3, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE,
 };
 
 static const unsigned short decode_Y1_fsm[140] =
 {
   BITFIELD(59, 4) /* index 0 */,
-  TILE_OPC_NONE, CHILD(17), CHILD(22), CHILD(27), CHILD(47), CHILD(52),
-  CHILD(57), TILE_OPC_ADDI, CHILD(62), CHILD(92), TILE_OPC_SEQI, CHILD(107),
-  TILE_OPC_SLTI, TILE_OPC_SLTI_U, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, CHILD(17), CHILD(22), CHILD(27), CHILD(47), CHILD(52),
+  CHILD(57), TILEPRO_OPC_ADDI, CHILD(62), CHILD(92), TILEPRO_OPC_SEQI,
+  CHILD(107), TILEPRO_OPC_SLTI, TILEPRO_OPC_SLTI_U, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE,
   BITFIELD(49, 2) /* index 17 */,
-  TILE_OPC_ADD, TILE_OPC_S1A, TILE_OPC_S2A, TILE_OPC_SUB,
+  TILEPRO_OPC_ADD, TILEPRO_OPC_S1A, TILEPRO_OPC_S2A, TILEPRO_OPC_SUB,
   BITFIELD(49, 2) /* index 22 */,
-  TILE_OPC_NONE, TILE_OPC_MNZ, TILE_OPC_MZ, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_MNZ, TILEPRO_OPC_MZ, TILEPRO_OPC_NONE,
   BITFIELD(49, 2) /* index 27 */,
-  TILE_OPC_AND, TILE_OPC_NOR, CHILD(32), TILE_OPC_XOR,
+  TILEPRO_OPC_AND, TILEPRO_OPC_NOR, CHILD(32), TILEPRO_OPC_XOR,
   BITFIELD(43, 2) /* index 32 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(37),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(37),
   BITFIELD(45, 2) /* index 37 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(42),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(42),
   BITFIELD(47, 2) /* index 42 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_MOVE,
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_MOVE,
   BITFIELD(49, 2) /* index 47 */,
-  TILE_OPC_RL, TILE_OPC_SHL, TILE_OPC_SHR, TILE_OPC_SRA,
+  TILEPRO_OPC_RL, TILEPRO_OPC_SHL, TILEPRO_OPC_SHR, TILEPRO_OPC_SRA,
   BITFIELD(49, 2) /* index 52 */,
-  TILE_OPC_SLTE, TILE_OPC_SLTE_U, TILE_OPC_SLT, TILE_OPC_SLT_U,
+  TILEPRO_OPC_SLTE, TILEPRO_OPC_SLTE_U, TILEPRO_OPC_SLT, TILEPRO_OPC_SLT_U,
   BITFIELD(49, 2) /* index 57 */,
-  TILE_OPC_NONE, TILE_OPC_S3A, TILE_OPC_SEQ, TILE_OPC_SNE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_S3A, TILEPRO_OPC_SEQ, TILEPRO_OPC_SNE,
   BITFIELD(31, 2) /* index 62 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(67),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(67),
   BITFIELD(33, 2) /* index 67 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(72),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(72),
   BITFIELD(35, 2) /* index 72 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(77),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(77),
   BITFIELD(37, 2) /* index 77 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(82),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(82),
   BITFIELD(39, 2) /* index 82 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(87),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(87),
   BITFIELD(41, 2) /* index 87 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_INFO,
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_INFO,
   BITFIELD(37, 2) /* index 92 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(97),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(97),
   BITFIELD(39, 2) /* index 97 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(102),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(102),
   BITFIELD(41, 2) /* index 102 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_MOVEI,
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_MOVEI,
   BITFIELD(48, 3) /* index 107 */,
-  TILE_OPC_NONE, TILE_OPC_RLI, TILE_OPC_SHLI, TILE_OPC_SHRI, TILE_OPC_SRAI,
-  CHILD(116), TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_RLI, TILEPRO_OPC_SHLI, TILEPRO_OPC_SHRI,
+  TILEPRO_OPC_SRAI, CHILD(116), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 116 */,
-  TILE_OPC_NONE, CHILD(125), CHILD(130), CHILD(135), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, CHILD(125), CHILD(130), CHILD(135), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(46, 2) /* index 125 */,
-  TILE_OPC_FNOP, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_FNOP, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(46, 2) /* index 130 */,
-  TILE_OPC_ILL, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_ILL, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(46, 2) /* index 135 */,
-  TILE_OPC_NOP, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NOP, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
 };
 
 static const unsigned short decode_Y2_fsm[24] =
 {
   BITFIELD(56, 3) /* index 0 */,
-  CHILD(9), TILE_OPC_LB_U, TILE_OPC_LH, TILE_OPC_LH_U, TILE_OPC_LW,
-  TILE_OPC_SB, TILE_OPC_SH, TILE_OPC_SW,
+  CHILD(9), TILEPRO_OPC_LB_U, TILEPRO_OPC_LH, TILEPRO_OPC_LH_U,
+  TILEPRO_OPC_LW, TILEPRO_OPC_SB, TILEPRO_OPC_SH, TILEPRO_OPC_SW,
   BITFIELD(20, 2) /* index 9 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, CHILD(14),
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, CHILD(14),
   BITFIELD(22, 2) /* index 14 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, CHILD(19),
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, CHILD(19),
   BITFIELD(24, 2) /* index 19 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_PREFETCH,
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_PREFETCH,
 };
 
 #undef BITFIELD
 #undef CHILD
 const unsigned short * const
-tile_bundle_decoder_fsms[TILE_NUM_PIPELINE_ENCODINGS] =
+tilepro_bundle_decoder_fsms[TILEPRO_NUM_PIPELINE_ENCODINGS] =
 {
   decode_X0_fsm,
   decode_X1_fsm,
@@ -2191,220 +2297,220 @@
   decode_Y1_fsm,
   decode_Y2_fsm
 };
-const struct tile_operand tile_operands[43] =
+const struct tilepro_operand tilepro_operands[43] =
 {
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM8_X0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM8_X0),
     8, 1, 0, 0, 0, 0,
     create_Imm8_X0, get_Imm8_X0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM8_X1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM8_X1),
     8, 1, 0, 0, 0, 0,
     create_Imm8_X1, get_Imm8_X1
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM8_Y0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM8_Y0),
     8, 1, 0, 0, 0, 0,
     create_Imm8_Y0, get_Imm8_Y0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM8_Y1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM8_Y1),
     8, 1, 0, 0, 0, 0,
     create_Imm8_Y1, get_Imm8_Y1
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM16_X0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM16_X0),
     16, 1, 0, 0, 0, 0,
     create_Imm16_X0, get_Imm16_X0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM16_X1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM16_X1),
     16, 1, 0, 0, 0, 0,
     create_Imm16_X1, get_Imm16_X1
   },
   {
-    TILE_OP_TYPE_ADDRESS, BFD_RELOC(TILE_JOFFLONG_X1),
-    29, 1, 0, 0, 1, TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
+    TILEPRO_OP_TYPE_ADDRESS, BFD_RELOC(TILEPRO_JOFFLONG_X1),
+    29, 1, 0, 0, 1, TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
     create_JOffLong_X1, get_JOffLong_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 0, 1, 0, 0,
     create_Dest_X0, get_Dest_X0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcA_X0, get_SrcA_X0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 0, 1, 0, 0,
     create_Dest_X1, get_Dest_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcA_X1, get_SrcA_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 0, 1, 0, 0,
     create_Dest_Y0, get_Dest_Y0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcA_Y0, get_SrcA_Y0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 0, 1, 0, 0,
     create_Dest_Y1, get_Dest_Y1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcA_Y1, get_SrcA_Y1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcA_Y2, get_SrcA_Y2
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcB_X0, get_SrcB_X0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcB_X1, get_SrcB_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcB_Y0, get_SrcB_Y0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcB_Y1, get_SrcB_Y1
   },
   {
-    TILE_OP_TYPE_ADDRESS, BFD_RELOC(TILE_BROFF_X1),
-    17, 1, 0, 0, 1, TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
+    TILEPRO_OP_TYPE_ADDRESS, BFD_RELOC(TILEPRO_BROFF_X1),
+    17, 1, 0, 0, 1, TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
     create_BrOff_X1, get_BrOff_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 1, 0, 0,
     create_Dest_X0, get_Dest_X0
   },
   {
-    TILE_OP_TYPE_ADDRESS, BFD_RELOC(NONE),
-    28, 1, 0, 0, 1, TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
+    TILEPRO_OP_TYPE_ADDRESS, BFD_RELOC(NONE),
+    28, 1, 0, 0, 1, TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
     create_JOff_X1, get_JOff_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 0, 1, 0, 0,
     create_SrcBDest_Y2, get_SrcBDest_Y2
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 1, 0, 0,
     create_SrcA_X1, get_SrcA_X1
   },
   {
-    TILE_OP_TYPE_SPR, BFD_RELOC(TILE_MF_IMM15_X1),
+    TILEPRO_OP_TYPE_SPR, BFD_RELOC(TILEPRO_MF_IMM15_X1),
     15, 0, 0, 0, 0, 0,
     create_MF_Imm15_X1, get_MF_Imm15_X1
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_MMSTART_X0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_MMSTART_X0),
     5, 0, 0, 0, 0, 0,
     create_MMStart_X0, get_MMStart_X0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_MMEND_X0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_MMEND_X0),
     5, 0, 0, 0, 0, 0,
     create_MMEnd_X0, get_MMEnd_X0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_MMSTART_X1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_MMSTART_X1),
     5, 0, 0, 0, 0, 0,
     create_MMStart_X1, get_MMStart_X1
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_MMEND_X1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_MMEND_X1),
     5, 0, 0, 0, 0, 0,
     create_MMEnd_X1, get_MMEnd_X1
   },
   {
-    TILE_OP_TYPE_SPR, BFD_RELOC(TILE_MT_IMM15_X1),
+    TILEPRO_OP_TYPE_SPR, BFD_RELOC(TILEPRO_MT_IMM15_X1),
     15, 0, 0, 0, 0, 0,
     create_MT_Imm15_X1, get_MT_Imm15_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 1, 0, 0,
     create_Dest_Y0, get_Dest_Y0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SHAMT_X0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_SHAMT_X0),
     5, 0, 0, 0, 0, 0,
     create_ShAmt_X0, get_ShAmt_X0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SHAMT_X1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_SHAMT_X1),
     5, 0, 0, 0, 0, 0,
     create_ShAmt_X1, get_ShAmt_X1
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SHAMT_Y0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_SHAMT_Y0),
     5, 0, 0, 0, 0, 0,
     create_ShAmt_Y0, get_ShAmt_Y0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SHAMT_Y1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_SHAMT_Y1),
     5, 0, 0, 0, 0, 0,
     create_ShAmt_Y1, get_ShAmt_Y1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcBDest_Y2, get_SrcBDest_Y2
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_DEST_IMM8_X1),
     8, 1, 0, 0, 0, 0,
     create_Dest_Imm8_X1, get_Dest_Imm8_X1
   },
   {
-    TILE_OP_TYPE_ADDRESS, BFD_RELOC(TILE_SN_BROFF),
-    10, 1, 0, 0, 1, TILE_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES,
+    TILEPRO_OP_TYPE_ADDRESS, BFD_RELOC(NONE),
+    10, 1, 0, 0, 1, TILEPRO_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES,
     create_BrOff_SN, get_BrOff_SN
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SN_UIMM8),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE),
     8, 0, 0, 0, 0, 0,
     create_Imm8_SN, get_Imm8_SN
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SN_IMM8),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE),
     8, 1, 0, 0, 0, 0,
     create_Imm8_SN, get_Imm8_SN
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     2, 0, 0, 1, 0, 0,
     create_Dest_SN, get_Dest_SN
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     2, 0, 1, 0, 0, 0,
     create_Src_SN, get_Src_SN
   }
@@ -2416,10 +2522,10 @@
 /* Given a set of bundle bits and a specific pipe, returns which
  * instruction the bundle contains in that pipe.
  */
-const struct tile_opcode *
-find_opcode(tile_bundle_bits bits, tile_pipeline pipe)
+const struct tilepro_opcode *
+find_opcode(tilepro_bundle_bits bits, tilepro_pipeline pipe)
 {
-  const unsigned short *table = tile_bundle_decoder_fsms[pipe];
+  const unsigned short *table = tilepro_bundle_decoder_fsms[pipe];
   int index = 0;
 
   while (1)
@@ -2429,51 +2535,51 @@
       ((unsigned int)(bits >> (bitspec & 63))) & (bitspec >> 6);
 
     unsigned short next = table[index + 1 + bitfield];
-    if (next <= TILE_OPC_NONE)
-      return &tile_opcodes[next];
+    if (next <= TILEPRO_OPC_NONE)
+      return &tilepro_opcodes[next];
 
-    index = next - TILE_OPC_NONE;
+    index = next - TILEPRO_OPC_NONE;
   }
 }
 
 
 int
-parse_insn_tile(tile_bundle_bits bits,
-                unsigned int pc,
-                struct tile_decoded_instruction
-                decoded[TILE_MAX_INSTRUCTIONS_PER_BUNDLE])
+parse_insn_tilepro(tilepro_bundle_bits bits,
+                   unsigned int pc,
+                   struct tilepro_decoded_instruction
+                   decoded[TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE])
 {
   int num_instructions = 0;
   int pipe;
 
   int min_pipe, max_pipe;
-  if ((bits & TILE_BUNDLE_Y_ENCODING_MASK) == 0)
+  if ((bits & TILEPRO_BUNDLE_Y_ENCODING_MASK) == 0)
   {
-    min_pipe = TILE_PIPELINE_X0;
-    max_pipe = TILE_PIPELINE_X1;
+    min_pipe = TILEPRO_PIPELINE_X0;
+    max_pipe = TILEPRO_PIPELINE_X1;
   }
   else
   {
-    min_pipe = TILE_PIPELINE_Y0;
-    max_pipe = TILE_PIPELINE_Y2;
+    min_pipe = TILEPRO_PIPELINE_Y0;
+    max_pipe = TILEPRO_PIPELINE_Y2;
   }
 
   /* For each pipe, find an instruction that fits. */
   for (pipe = min_pipe; pipe <= max_pipe; pipe++)
   {
-    const struct tile_opcode *opc;
-    struct tile_decoded_instruction *d;
+    const struct tilepro_opcode *opc;
+    struct tilepro_decoded_instruction *d;
     int i;
 
     d = &decoded[num_instructions++];
-    opc = find_opcode (bits, (tile_pipeline)pipe);
+    opc = find_opcode (bits, (tilepro_pipeline)pipe);
     d->opcode = opc;
 
     /* Decode each operand, sign extending, etc. as appropriate. */
     for (i = 0; i < opc->num_operands; i++)
     {
-      const struct tile_operand *op =
-        &tile_operands[opc->operands[pipe][i]];
+      const struct tilepro_operand *op =
+        &tilepro_operands[opc->operands[pipe][i]];
       int opval = op->extract (bits);
       if (op->is_signed)
       {
@@ -2483,9 +2589,9 @@
       }
 
       /* Adjust PC-relative scaled branch offsets. */
-      if (op->type == TILE_OP_TYPE_ADDRESS)
+      if (op->type == TILEPRO_OP_TYPE_ADDRESS)
       {
-        opval *= TILE_BUNDLE_SIZE_IN_BYTES;
+        opval *= TILEPRO_BUNDLE_SIZE_IN_BYTES;
         opval += (int)pc;
       }
 
diff -druN linux-libre-3.1-gnu/arch/tile/kernel/tile-desc_64.c linux-libre-3.2-gnu/arch/tile/kernel/tile-desc_64.c
--- linux-libre-3.1-gnu/arch/tile/kernel/tile-desc_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/kernel/tile-desc_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,23 @@
+/* TILE-Gx opcode information.
+ *
+ * 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.
+ *
+ *
+ *
+ *
+ *
+ */
+
 /* This define is BFD_RELOC_##x for real bfd, or -1 for everyone else. */
 #define BFD_RELOC(x) -1
 
@@ -6,10 +26,8 @@
 #define TREG_SN 56
 #define TREG_ZERO 63
 
-/* FIXME: Rename this. */
-#include <asm/opcode-tile_64.h>
-
 #include <linux/stddef.h>
+#include <asm/tile-desc.h>
 
 const struct tilegx_opcode tilegx_opcodes[334] =
 {
@@ -2040,12 +2058,12 @@
     create_BrOff_X1, get_BrOff_X1
   },
   {
-    TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE),
+    TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_MMSTART_X0),
     6, 0, 0, 0, 0, 0,
     create_BFStart_X0, get_BFStart_X0
   },
   {
-    TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE),
+    TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_MMEND_X0),
     6, 0, 0, 0, 0, 0,
     create_BFEnd_X0, get_BFEnd_X0
   },
diff -druN linux-libre-3.1-gnu/arch/tile/kernel/traps.c linux-libre-3.2-gnu/arch/tile/kernel/traps.c
--- linux-libre-3.1-gnu/arch/tile/kernel/traps.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/kernel/traps.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,13 +19,12 @@
 #include <linux/reboot.h>
 #include <linux/uaccess.h>
 #include <linux/ptrace.h>
-#include <asm/opcode-tile.h>
-#include <asm/opcode_constants.h>
 #include <asm/stack.h>
 #include <asm/traps.h>
 
 #include <arch/interrupts.h>
 #include <arch/spr_def.h>
+#include <arch/opcode.h>
 
 void __init trap_init(void)
 {
@@ -135,7 +134,7 @@
 	if (get_UnaryOpcodeExtension_X1(bundle) != ILL_UNARY_OPCODE_X1)
 		return 0;
 #else
-	if (bundle & TILE_BUNDLE_Y_ENCODING_MASK)
+	if (bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK)
 		return 0;
 	if (get_Opcode_X1(bundle) != SHUN_0_OPCODE_X1)
 		return 0;
diff -druN linux-libre-3.1-gnu/arch/tile/lib/exports.c linux-libre-3.2-gnu/arch/tile/lib/exports.c
--- linux-libre-3.1-gnu/arch/tile/lib/exports.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/lib/exports.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,9 @@
 EXPORT_SYMBOL(current_text_addr);
 EXPORT_SYMBOL(dump_stack);
 
+/* arch/tile/kernel/head.S */
+EXPORT_SYMBOL(empty_zero_page);
+
 /* arch/tile/lib/, various memcpy files */
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(__copy_to_user_inatomic);
@@ -79,8 +82,6 @@
 int64_t __moddi3(int64_t dividend, int64_t divisor);
 EXPORT_SYMBOL(__moddi3);
 #ifndef __tilegx__
-uint64_t __ll_mul(uint64_t n0, uint64_t n1);
-EXPORT_SYMBOL(__ll_mul);
 int64_t __muldi3(int64_t, int64_t);
 EXPORT_SYMBOL(__muldi3);
 uint64_t __lshrdi3(uint64_t, unsigned int);
diff -druN linux-libre-3.1-gnu/arch/tile/mm/homecache.c linux-libre-3.2-gnu/arch/tile/mm/homecache.c
--- linux-libre-3.1-gnu/arch/tile/mm/homecache.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/tile/mm/homecache.c	2012-01-04 18:55:44.000000000 -0500
@@ -449,9 +449,12 @@
 	VM_BUG_ON(!virt_addr_valid((void *)addr));
 	page = virt_to_page((void *)addr);
 	if (put_page_testzero(page)) {
-		int pages = (1 << order);
 		homecache_change_page_home(page, order, initial_page_home());
-		while (pages--)
-			__free_page(page++);
+		if (order == 0) {
+			free_hot_cold_page(page, 0);
+		} else {
+			init_page_count(page);
+			__free_pages(page, order);
+		}
 	}
 }
diff -druN linux-libre-3.1-gnu/arch/um/defconfig linux-libre-3.2-gnu/arch/um/defconfig
--- linux-libre-3.1-gnu/arch/um/defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@
 # CONFIG_STACKTRACE_SUPPORT is not set
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_BUG=y
-CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_IRQ_RELEASE_METHOD=y
 CONFIG_HZ=100
diff -druN linux-libre-3.1-gnu/arch/um/drivers/chan.h linux-libre-3.2-gnu/arch/um/drivers/chan.h
--- linux-libre-3.1-gnu/arch/um/drivers/chan.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/um/drivers/chan.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,50 @@
+/* 
+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __CHAN_KERN_H__
+#define __CHAN_KERN_H__
+
+#include <linux/tty.h>
+#include <linux/list.h>
+#include <linux/console.h>
+#include "chan_user.h"
+#include "line.h"
+
+struct chan {
+	struct list_head list;
+	struct list_head free_list;
+	struct line *line;
+	char *dev;
+	unsigned int primary:1;
+	unsigned int input:1;
+	unsigned int output:1;
+	unsigned int opened:1;
+	unsigned int enabled:1;
+	int fd;
+	const struct chan_ops *ops;
+	void *data;
+};
+
+extern void chan_interrupt(struct list_head *chans, struct delayed_work *task,
+			   struct tty_struct *tty, int irq);
+extern int parse_chan_pair(char *str, struct line *line, int device,
+			   const struct chan_opts *opts, char **error_out);
+extern int write_chan(struct list_head *chans, const char *buf, int len,
+			     int write_irq);
+extern int console_write_chan(struct list_head *chans, const char *buf, 
+			      int len);
+extern int console_open_chan(struct line *line, struct console *co);
+extern void deactivate_chan(struct list_head *chans, int irq);
+extern void reactivate_chan(struct list_head *chans, int irq);
+extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
+extern int enable_chan(struct line *line);
+extern void close_chan(struct list_head *chans, int delay_free_irq);
+extern int chan_window_size(struct list_head *chans, 
+			     unsigned short *rows_out, 
+			     unsigned short *cols_out);
+extern int chan_config_string(struct list_head *chans, char *str, int size,
+			      char **error_out);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/um/drivers/chan_kern.c linux-libre-3.2-gnu/arch/um/drivers/chan_kern.c
--- linux-libre-3.1-gnu/arch/um/drivers/chan_kern.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/chan_kern.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 #include <linux/slab.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
-#include "chan_kern.h"
+#include "chan.h"
 #include "os.h"
 
 #ifdef CONFIG_NOCONFIG_CHAN
@@ -358,11 +358,11 @@
 	return 0;
 }
 
-static void free_one_chan(struct chan *chan, int delay_free_irq)
+static void free_one_chan(struct chan *chan)
 {
 	list_del(&chan->list);
 
-	close_one_chan(chan, delay_free_irq);
+	close_one_chan(chan, 0);
 
 	if (chan->ops->free != NULL)
 		(*chan->ops->free)(chan->data);
@@ -372,14 +372,14 @@
 	kfree(chan);
 }
 
-static void free_chan(struct list_head *chans, int delay_free_irq)
+static void free_chan(struct list_head *chans)
 {
 	struct list_head *ele, *next;
 	struct chan *chan;
 
 	list_for_each_safe(ele, next, chans) {
 		chan = list_entry(ele, struct chan, list);
-		free_one_chan(chan, delay_free_irq);
+		free_one_chan(chan);
 	}
 }
 
@@ -547,7 +547,7 @@
 	char *in, *out;
 
 	if (!list_empty(chans)) {
-		free_chan(chans, 0);
+		free_chan(chans);
 		INIT_LIST_HEAD(chans);
 	}
 
diff -druN linux-libre-3.1-gnu/arch/um/drivers/chan_user.c linux-libre-3.2-gnu/arch/um/drivers/chan_user.c
--- linux-libre-3.1-gnu/arch/um/drivers/chan_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/chan_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,10 +11,8 @@
 #include <termios.h>
 #include <sys/ioctl.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 void generic_close(int fd, void *unused)
 {
@@ -283,7 +281,12 @@
 		return;
 
 	pid = tcgetpgrp(fd);
-	if (!is_skas_winch(pid, fd, tty) && (pid == -1)) {
+	if (is_skas_winch(pid, fd, tty)) {
+		register_winch_irq(-1, fd, -1, tty, 0);
+		return;
+	}
+
+	if (pid == -1) {
 		thread = winch_tramp(fd, tty, &thread_fd, &stack);
 		if (thread < 0)
 			return;
diff -druN linux-libre-3.1-gnu/arch/um/drivers/chan_user.h linux-libre-3.2-gnu/arch/um/drivers/chan_user.h
--- linux-libre-3.1-gnu/arch/um/drivers/chan_user.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/um/drivers/chan_user.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __CHAN_USER_H__
+#define __CHAN_USER_H__
+
+#include "init.h"
+
+struct chan_opts {
+	void (*const announce)(char *dev_name, int dev);
+	char *xterm_title;
+	const int raw;
+};
+
+enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
+
+struct chan_ops {
+	char *type;
+	void *(*init)(char *, int, const struct chan_opts *);
+	int (*open)(int, int, int, void *, char **);
+	void (*close)(int, void *);
+	int (*read)(int, char *, void *);
+	int (*write)(int, const char *, int, void *);
+	int (*console_write)(int, const char *, int);
+	int (*window_size)(int, void *, unsigned short *, unsigned short *);
+	void (*free)(void *);
+	int winch;
+};
+
+extern const struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops,
+	tty_ops, xterm_ops;
+
+extern void generic_close(int fd, void *unused);
+extern int generic_read(int fd, char *c_out, void *unused);
+extern int generic_write(int fd, const char *buf, int n, void *unused);
+extern int generic_console_write(int fd, const char *buf, int n);
+extern int generic_window_size(int fd, void *unused, unsigned short *rows_out,
+			       unsigned short *cols_out);
+extern void generic_free(void *data);
+
+struct tty_struct;
+extern void register_winch(int fd,  struct tty_struct *tty);
+extern void register_winch_irq(int fd, int tty_fd, int pid,
+			       struct tty_struct *tty, unsigned long stack);
+
+#define __channel_help(fn, prefix) \
+__uml_help(fn, prefix "[0-9]*=<channel description>\n" \
+"    Attach a console or serial line to a host channel.  See\n" \
+"    http://user-mode-linux.sourceforge.net/old/input.html for a complete\n" \
+"    description of this switch.\n\n" \
+);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/um/drivers/cow_sys.h linux-libre-3.2-gnu/arch/um/drivers/cow_sys.h
--- linux-libre-3.1-gnu/arch/um/drivers/cow_sys.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/cow_sys.h	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,6 @@
 
 #include "kern_util.h"
 #include "os.h"
-#include "user.h"
 #include "um_malloc.h"
 
 static inline void *cow_malloc(int size)
diff -druN linux-libre-3.1-gnu/arch/um/drivers/daemon_user.c linux-libre-3.2-gnu/arch/um/drivers/daemon_user.c
--- linux-libre-3.1-gnu/arch/um/drivers/daemon_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/daemon_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,6 @@
 #include "net_user.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 enum request_type { REQ_NEW_CONTROL };
 
diff -druN linux-libre-3.1-gnu/arch/um/drivers/fd.c linux-libre-3.2-gnu/arch/um/drivers/fd.c
--- linux-libre-3.1-gnu/arch/um/drivers/fd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/fd.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,10 +9,8 @@
 #include <errno.h>
 #include <termios.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 struct fd_chan {
 	int fd;
diff -druN linux-libre-3.1-gnu/arch/um/drivers/harddog_user.c linux-libre-3.2-gnu/arch/um/drivers/harddog_user.c
--- linux-libre-3.1-gnu/arch/um/drivers/harddog_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/harddog_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,6 @@
 #include <unistd.h>
 #include <errno.h>
 #include "os.h"
-#include "user.h"
 
 struct dog_data {
 	int stdin;
diff -druN linux-libre-3.1-gnu/arch/um/drivers/line.c linux-libre-3.2-gnu/arch/um/drivers/line.c
--- linux-libre-3.1-gnu/arch/um/drivers/line.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/line.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
 #include "linux/kd.h"
 #include "linux/sched.h"
 #include "linux/slab.h"
-#include "chan_kern.h"
+#include "chan.h"
 #include "irq_kern.h"
 #include "irq_user.h"
 #include "kern_util.h"
diff -druN linux-libre-3.1-gnu/arch/um/drivers/line.h linux-libre-3.2-gnu/arch/um/drivers/line.h
--- linux-libre-3.1-gnu/arch/um/drivers/line.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/um/drivers/line.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,106 @@
+/* 
+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __LINE_H__
+#define __LINE_H__
+
+#include "linux/list.h"
+#include "linux/workqueue.h"
+#include "linux/tty.h"
+#include "linux/interrupt.h"
+#include "linux/spinlock.h"
+#include "linux/mutex.h"
+#include "chan_user.h"
+#include "mconsole_kern.h"
+
+/* There's only one modifiable field in this - .mc.list */
+struct line_driver {
+	const char *name;
+	const char *device_name;
+	const short major;
+	const short minor_start;
+	const short type;
+	const short subtype;
+	const int read_irq;
+	const char *read_irq_name;
+	const int write_irq;
+	const char *write_irq_name;
+	struct mc_device mc;
+};
+
+struct line {
+	struct tty_struct *tty;
+	spinlock_t count_lock;
+	unsigned long count;
+	int valid;
+
+	char *init_str;
+	int init_pri;
+	struct list_head chan_list;
+
+	/*This lock is actually, mostly, local to*/
+	spinlock_t lock;
+	int throttled;
+	/* Yes, this is a real circular buffer.
+	 * XXX: And this should become a struct kfifo!
+	 *
+	 * buffer points to a buffer allocated on demand, of length
+	 * LINE_BUFSIZE, head to the start of the ring, tail to the end.*/
+	char *buffer;
+	char *head;
+	char *tail;
+
+	int sigio;
+	struct delayed_work task;
+	const struct line_driver *driver;
+	int have_irq;
+};
+
+#define LINE_INIT(str, d) \
+	{ .count_lock =	__SPIN_LOCK_UNLOCKED((str).count_lock), \
+	  .init_str =	str,	\
+	  .init_pri =	INIT_STATIC, \
+	  .valid =	1, \
+	  .lock =	__SPIN_LOCK_UNLOCKED((str).lock), \
+	  .driver =	d }
+
+extern void line_close(struct tty_struct *tty, struct file * filp);
+extern int line_open(struct line *lines, struct tty_struct *tty);
+extern int line_setup(struct line *lines, unsigned int sizeof_lines,
+		      char *init, char **error_out);
+extern int line_write(struct tty_struct *tty, const unsigned char *buf,
+		      int len);
+extern int line_put_char(struct tty_struct *tty, unsigned char ch);
+extern void line_set_termios(struct tty_struct *tty, struct ktermios * old);
+extern int line_chars_in_buffer(struct tty_struct *tty);
+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, unsigned int cmd,
+				unsigned long arg);
+extern void line_throttle(struct tty_struct *tty);
+extern void line_unthrottle(struct tty_struct *tty);
+
+extern char *add_xterm_umid(char *base);
+extern int line_setup_irq(int fd, int input, int output, struct line *line,
+			  void *data);
+extern void line_close_chan(struct line *line);
+extern struct tty_driver *register_lines(struct line_driver *line_driver,
+					 const struct tty_operations *driver,
+					 struct line *lines, int nlines);
+extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
+extern void close_lines(struct line *lines, int nlines);
+
+extern int line_config(struct line *lines, unsigned int sizeof_lines,
+		       char *str, const struct chan_opts *opts,
+		       char **error_out);
+extern int line_id(char **str, int *start_out, int *end_out);
+extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n,
+		       char **error_out);
+extern int line_get_config(char *dev, struct line *lines,
+			   unsigned int sizeof_lines, char *str,
+			   int size, char **error_out);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/um/drivers/mconsole.h linux-libre-3.2-gnu/arch/um/drivers/mconsole.h
--- linux-libre-3.1-gnu/arch/um/drivers/mconsole.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/um/drivers/mconsole.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MCONSOLE_H__
+#define __MCONSOLE_H__
+
+#ifndef __KERNEL__
+#include <stdint.h>
+#define u32 uint32_t
+#endif
+
+#include "sysdep/ptrace.h"
+
+#define MCONSOLE_MAGIC (0xcafebabe)
+#define MCONSOLE_MAX_DATA (512)
+#define MCONSOLE_VERSION 2
+
+struct mconsole_request {
+	u32 magic;
+	u32 version;
+	u32 len;
+	char data[MCONSOLE_MAX_DATA];
+};
+
+struct mconsole_reply {
+	u32 err;
+	u32 more;
+	u32 len;
+	char data[MCONSOLE_MAX_DATA];
+};
+
+struct mconsole_notify {
+	u32 magic;
+	u32 version;
+	enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG,
+	       MCONSOLE_USER_NOTIFY } type;
+	u32 len;
+	char data[MCONSOLE_MAX_DATA];
+};
+
+struct mc_request;
+
+enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC };
+
+struct mconsole_command
+{
+	char *command;
+	void (*handler)(struct mc_request *req);
+	enum mc_context context;
+};
+
+struct mc_request
+{
+	int len;
+	int as_interrupt;
+
+	int originating_fd;
+	unsigned int originlen;
+	unsigned char origin[128];			/* sockaddr_un */
+
+	struct mconsole_request request;
+	struct mconsole_command *cmd;
+	struct uml_pt_regs regs;
+};
+
+extern char mconsole_socket_name[];
+
+extern int mconsole_unlink_socket(void);
+extern int mconsole_reply_len(struct mc_request *req, const char *reply,
+			      int len, int err, int more);
+extern int mconsole_reply(struct mc_request *req, const char *str, int err,
+			  int more);
+
+extern void mconsole_version(struct mc_request *req);
+extern void mconsole_help(struct mc_request *req);
+extern void mconsole_halt(struct mc_request *req);
+extern void mconsole_reboot(struct mc_request *req);
+extern void mconsole_config(struct mc_request *req);
+extern void mconsole_remove(struct mc_request *req);
+extern void mconsole_sysrq(struct mc_request *req);
+extern void mconsole_cad(struct mc_request *req);
+extern void mconsole_stop(struct mc_request *req);
+extern void mconsole_go(struct mc_request *req);
+extern void mconsole_log(struct mc_request *req);
+extern void mconsole_proc(struct mc_request *req);
+extern void mconsole_stack(struct mc_request *req);
+
+extern int mconsole_get_request(int fd, struct mc_request *req);
+extern int mconsole_notify(char *sock_name, int type, const void *data,
+			   int len);
+extern char *mconsole_notify_socket(void);
+extern void lock_notify(void);
+extern void unlock_notify(void);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/um/drivers/mconsole_kern.h linux-libre-3.2-gnu/arch/um/drivers/mconsole_kern.h
--- linux-libre-3.1-gnu/arch/um/drivers/mconsole_kern.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/um/drivers/mconsole_kern.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MCONSOLE_KERN_H__
+#define __MCONSOLE_KERN_H__
+
+#include "linux/list.h"
+#include "mconsole.h"
+
+struct mconsole_entry {
+	struct list_head list;
+	struct mc_request request;
+};
+
+/* All these methods are called in process context. */
+struct mc_device {
+	struct list_head list;
+	char *name;
+	int (*config)(char *, char **);
+	int (*get_config)(char *, char *, int, char **);
+	int (*id)(char **, int *, int *);
+	int (*remove)(int, char **);
+};
+
+#define CONFIG_CHUNK(str, size, current, chunk, end) \
+do { \
+	current += strlen(chunk); \
+	if(current >= size) \
+		str = NULL; \
+	if(str != NULL){ \
+		strcpy(str, chunk); \
+		str += strlen(chunk); \
+	} \
+	if(end) \
+		current++; \
+} while(0)
+
+#ifdef CONFIG_MCONSOLE
+
+extern void mconsole_register_dev(struct mc_device *new);
+
+#else
+
+static inline void mconsole_register_dev(struct mc_device *new)
+{
+}
+
+#endif
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/um/drivers/mconsole_user.c linux-libre-3.2-gnu/arch/um/drivers/mconsole_user.c
--- linux-libre-3.1-gnu/arch/um/drivers/mconsole_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/mconsole_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,9 +10,7 @@
 #include <sys/socket.h>
 #include <sys/uio.h>
 #include <sys/un.h>
-#include "kern_constants.h"
 #include "mconsole.h"
-#include "user.h"
 
 static struct mconsole_command commands[] = {
 	/*
diff -druN linux-libre-3.1-gnu/arch/um/drivers/net_kern.c linux-libre-3.2-gnu/arch/um/drivers/net_kern.c
--- linux-libre-3.1-gnu/arch/um/drivers/net_kern.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/net_kern.c	2012-01-04 18:55:44.000000000 -0500
@@ -368,7 +368,7 @@
 	.ndo_open 		= uml_net_open,
 	.ndo_stop 		= uml_net_close,
 	.ndo_start_xmit 	= uml_net_start_xmit,
-	.ndo_set_multicast_list = uml_net_set_multicast_list,
+	.ndo_set_rx_mode	= uml_net_set_multicast_list,
 	.ndo_tx_timeout 	= uml_net_tx_timeout,
 	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_change_mtu 	= uml_net_change_mtu,
diff -druN linux-libre-3.1-gnu/arch/um/drivers/net_user.c linux-libre-3.2-gnu/arch/um/drivers/net_user.c
--- linux-libre-3.1-gnu/arch/um/drivers/net_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/net_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,10 +12,8 @@
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include "net_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 int tap_open_common(void *dev, char *gate_addr)
 {
diff -druN linux-libre-3.1-gnu/arch/um/drivers/pcap_user.c linux-libre-3.2-gnu/arch/um/drivers/pcap_user.c
--- linux-libre-3.1-gnu/arch/um/drivers/pcap_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/pcap_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,9 +9,7 @@
 #include <asm/types.h>
 #include "net_user.h"
 #include "pcap_user.h"
-#include "kern_constants.h"
 #include "um_malloc.h"
-#include "user.h"
 
 #define PCAP_FD(p) (*(int *)(p))
 
diff -druN linux-libre-3.1-gnu/arch/um/drivers/port_user.c linux-libre-3.2-gnu/arch/um/drivers/port_user.c
--- linux-libre-3.1-gnu/arch/um/drivers/port_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/port_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,11 +10,9 @@
 #include <unistd.h>
 #include <netinet/in.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "port.h"
 #include "um_malloc.h"
-#include "user.h"
 
 struct port_chan {
 	int raw;
diff -druN linux-libre-3.1-gnu/arch/um/drivers/pty.c linux-libre-3.2-gnu/arch/um/drivers/pty.c
--- linux-libre-3.1-gnu/arch/um/drivers/pty.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/pty.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,10 +12,8 @@
 #include <termios.h>
 #include <sys/stat.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 struct pty_chan {
 	void (*announce)(char *dev_name, int dev);
diff -druN linux-libre-3.1-gnu/arch/um/drivers/slip_user.c linux-libre-3.2-gnu/arch/um/drivers/slip_user.c
--- linux-libre-3.1-gnu/arch/um/drivers/slip_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/slip_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,12 +11,10 @@
 #include <string.h>
 #include <sys/termios.h>
 #include <sys/wait.h>
-#include "kern_constants.h"
 #include "net_user.h"
 #include "os.h"
 #include "slip.h"
 #include "um_malloc.h"
-#include "user.h"
 
 static int slip_user_init(void *data, void *dev)
 {
diff -druN linux-libre-3.1-gnu/arch/um/drivers/slirp_user.c linux-libre-3.2-gnu/arch/um/drivers/slirp_user.c
--- linux-libre-3.1-gnu/arch/um/drivers/slirp_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/slirp_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,11 +7,9 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/wait.h>
-#include "kern_constants.h"
 #include "net_user.h"
 #include "os.h"
 #include "slirp.h"
-#include "user.h"
 
 static int slirp_user_init(void *data, void *dev)
 {
diff -druN linux-libre-3.1-gnu/arch/um/drivers/ssl.c linux-libre-3.2-gnu/arch/um/drivers/ssl.c
--- linux-libre-3.1-gnu/arch/um/drivers/ssl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/ssl.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,10 +12,8 @@
 #include "linux/console.h"
 #include "asm/termbits.h"
 #include "asm/irq.h"
-#include "line.h"
 #include "ssl.h"
-#include "chan_kern.h"
-#include "kern.h"
+#include "chan.h"
 #include "init.h"
 #include "irq_user.h"
 #include "mconsole_kern.h"
diff -druN linux-libre-3.1-gnu/arch/um/drivers/stdio_console.c linux-libre-3.2-gnu/arch/um/drivers/stdio_console.c
--- linux-libre-3.1-gnu/arch/um/drivers/stdio_console.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/stdio_console.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,8 +20,7 @@
 #include "asm/current.h"
 #include "asm/irq.h"
 #include "stdio_console.h"
-#include "line.h"
-#include "chan_kern.h"
+#include "chan.h"
 #include "irq_user.h"
 #include "mconsole_kern.h"
 #include "init.h"
diff -druN linux-libre-3.1-gnu/arch/um/drivers/tty.c linux-libre-3.2-gnu/arch/um/drivers/tty.c
--- linux-libre-3.1-gnu/arch/um/drivers/tty.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/tty.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,10 +7,8 @@
 #include <fcntl.h>
 #include <termios.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 struct tty_chan {
 	char *dev;
diff -druN linux-libre-3.1-gnu/arch/um/drivers/ubd_kern.c linux-libre-3.2-gnu/arch/um/drivers/ubd_kern.c
--- linux-libre-3.1-gnu/arch/um/drivers/ubd_kern.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/ubd_kern.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,7 +46,6 @@
 #include "asm/tlbflush.h"
 #include "mem_user.h"
 #include "kern_util.h"
-#include "kern.h"
 #include "mconsole_kern.h"
 #include "init.h"
 #include "irq_user.h"
@@ -54,7 +53,6 @@
 #include "ubd_user.h"
 #include "os.h"
 #include "mem.h"
-#include "mem_kern.h"
 #include "cow.h"
 
 enum ubd_req { UBD_READ, UBD_WRITE };
@@ -513,8 +511,37 @@
 static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out)
 {
 	char *file;
+	int fd;
+	int err;
 
-	file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file;
+	__u32 version;
+	__u32 align;
+	char *backing_file;
+	time_t mtime;
+	unsigned long long size;
+	int sector_size;
+	int bitmap_offset;
+
+	if (ubd_dev->file && ubd_dev->cow.file) {
+		file = ubd_dev->cow.file;
+
+		goto out;
+	}
+
+	fd = os_open_file(ubd_dev->file, global_openflags, 0);
+	if (fd < 0)
+		return fd;
+
+	err = read_cow_header(file_reader, &fd, &version, &backing_file, \
+		&mtime, &size, &sector_size, &align, &bitmap_offset);
+	os_close_file(fd);
+
+	if(err == -EINVAL)
+		file = ubd_dev->file;
+	else
+		file = backing_file;
+
+out:
 	return os_file_size(file, size_out);
 }
 
diff -druN linux-libre-3.1-gnu/arch/um/drivers/ubd_user.c linux-libre-3.2-gnu/arch/um/drivers/ubd_user.c
--- linux-libre-3.1-gnu/arch/um/drivers/ubd_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/ubd_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,6 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include "asm/types.h"
-#include "user.h"
 #include "ubd_user.h"
 #include "os.h"
 #include "cow.h"
diff -druN linux-libre-3.1-gnu/arch/um/drivers/ubd_user.h linux-libre-3.2-gnu/arch/um/drivers/ubd_user.h
--- linux-libre-3.1-gnu/arch/um/drivers/ubd_user.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/um/drivers/ubd_user.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+/* 
+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 RidgeRun, Inc (glonnon@ridgerun.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_UBD_USER_H
+#define __UM_UBD_USER_H
+
+extern void ignore_sigwinch_sig(void);
+extern int start_io_thread(unsigned long sp, int *fds_out);
+extern int io_thread(void *arg);
+extern int kernel_fd;
+
+#endif
+
diff -druN linux-libre-3.1-gnu/arch/um/drivers/umcast_user.c linux-libre-3.2-gnu/arch/um/drivers/umcast_user.c
--- linux-libre-3.1-gnu/arch/um/drivers/umcast_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/umcast_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,11 +15,9 @@
 #include <unistd.h>
 #include <errno.h>
 #include <netinet/in.h>
-#include "kern_constants.h"
 #include "umcast.h"
 #include "net_user.h"
 #include "um_malloc.h"
-#include "user.h"
 
 static struct sockaddr_in *new_addr(char *addr, unsigned short port)
 {
diff -druN linux-libre-3.1-gnu/arch/um/drivers/vde_user.c linux-libre-3.2-gnu/arch/um/drivers/vde_user.c
--- linux-libre-3.1-gnu/arch/um/drivers/vde_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/vde_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,10 +6,8 @@
 #include <stddef.h>
 #include <errno.h>
 #include <libvdeplug.h>
-#include "kern_constants.h"
 #include "net_user.h"
 #include "um_malloc.h"
-#include "user.h"
 #include "vde.h"
 
 static int vde_user_init(void *data, void *dev)
diff -druN linux-libre-3.1-gnu/arch/um/drivers/xterm.c linux-libre-3.2-gnu/arch/um/drivers/xterm.c
--- linux-libre-3.1-gnu/arch/um/drivers/xterm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/drivers/xterm.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,10 +11,8 @@
 #include <string.h>
 #include <termios.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 #include "xterm.h"
 
 struct xterm_chan {
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/apic.h linux-libre-3.2-gnu/arch/um/include/asm/apic.h
--- linux-libre-3.1-gnu/arch/um/include/asm/apic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/apic.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,4 +0,0 @@
-#ifndef __UM_APIC_H
-#define __UM_APIC_H
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/arch_hweight.h linux-libre-3.2-gnu/arch/um/include/asm/arch_hweight.h
--- linux-libre-3.1-gnu/arch/um/include/asm/arch_hweight.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/arch_hweight.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASM_UM_HWEIGHT_H
-#define _ASM_UM_HWEIGHT_H
-
-#include <asm-generic/bitops/arch_hweight.h>
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/bug.h linux-libre-3.2-gnu/arch/um/include/asm/bug.h
--- linux-libre-3.1-gnu/arch/um/include/asm/bug.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/bug.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __UM_BUG_H
-#define __UM_BUG_H
-
-#include <asm-generic/bug.h>
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/checksum.h linux-libre-3.2-gnu/arch/um/include/asm/checksum.h
--- linux-libre-3.1-gnu/arch/um/include/asm/checksum.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/checksum.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __UM_CHECKSUM_H
-#define __UM_CHECKSUM_H
-
-#include "sysdep/checksum.h"
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/cputime.h linux-libre-3.2-gnu/arch/um/include/asm/cputime.h
--- linux-libre-3.1-gnu/arch/um/include/asm/cputime.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/cputime.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __UM_CPUTIME_H
-#define __UM_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __UM_CPUTIME_H */
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/desc.h linux-libre-3.2-gnu/arch/um/include/asm/desc.h
--- linux-libre-3.1-gnu/arch/um/include/asm/desc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/desc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-#ifndef __UM_DESC_H
-#define __UM_DESC_H
-
-/* Taken from asm-i386/desc.h, it's the only thing we need. The rest wouldn't
- * compile, and has never been used. */
-#define LDT_empty(info) (\
-	(info)->base_addr	== 0	&& \
-	(info)->limit		== 0	&& \
-	(info)->contents	== 0	&& \
-	(info)->read_exec_only	== 1	&& \
-	(info)->seg_32bit	== 0	&& \
-	(info)->limit_in_pages	== 0	&& \
-	(info)->seg_not_present	== 1	&& \
-	(info)->useable		== 0	)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/device.h linux-libre-3.2-gnu/arch/um/include/asm/device.h
--- linux-libre-3.1-gnu/arch/um/include/asm/device.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/device.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#include <asm-generic/device.h>
-
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/emergency-restart.h linux-libre-3.2-gnu/arch/um/include/asm/emergency-restart.h
--- linux-libre-3.1-gnu/arch/um/include/asm/emergency-restart.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/emergency-restart.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/ftrace.h linux-libre-3.2-gnu/arch/um/include/asm/ftrace.h
--- linux-libre-3.1-gnu/arch/um/include/asm/ftrace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/ftrace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-/* empty */
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/futex.h linux-libre-3.2-gnu/arch/um/include/asm/futex.h
--- linux-libre-3.1-gnu/arch/um/include/asm/futex.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/futex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
-
-#include <asm-generic/futex.h>
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/hardirq.h linux-libre-3.2-gnu/arch/um/include/asm/hardirq.h
--- linux-libre-3.1-gnu/arch/um/include/asm/hardirq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/hardirq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/hardirq.h>
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/hw_irq.h linux-libre-3.2-gnu/arch/um/include/asm/hw_irq.h
--- linux-libre-3.1-gnu/arch/um/include/asm/hw_irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/hw_irq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef _ASM_UM_HW_IRQ_H
-#define _ASM_UM_HW_IRQ_H
-
-#include "asm/irq.h"
-#include "asm/archparam.h"
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/irqflags.h linux-libre-3.2-gnu/arch/um/include/asm/irqflags.h
--- linux-libre-3.1-gnu/arch/um/include/asm/irqflags.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/irqflags.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,42 @@
 #ifndef __UM_IRQFLAGS_H
 #define __UM_IRQFLAGS_H
 
-/* Empty for now */
+extern int get_signals(void);
+extern int set_signals(int enable);
+extern void block_signals(void);
+extern void unblock_signals(void);
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	return get_signals();
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	set_signals(flags);
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	unblock_signals();
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	block_signals();
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags;
+	flags = arch_local_save_flags();
+	arch_local_irq_disable();
+	return flags;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_local_save_flags() == 0;
+}
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/irq_regs.h linux-libre-3.2-gnu/arch/um/include/asm/irq_regs.h
--- linux-libre-3.1-gnu/arch/um/include/asm/irq_regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/irq_regs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/irq_vectors.h linux-libre-3.2-gnu/arch/um/include/asm/irq_vectors.h
--- linux-libre-3.1-gnu/arch/um/include/asm/irq_vectors.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/irq_vectors.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_IRQ_VECTORS_H
-#define __UM_IRQ_VECTORS_H
-
-#endif
-
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/Kbuild linux-libre-3.2-gnu/arch/um/include/asm/Kbuild
--- linux-libre-3.1-gnu/arch/um/include/asm/Kbuild	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/um/include/asm/Kbuild	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,3 @@
+generic-y += bug.h cputime.h device.h emergency-restart.h futex.h hardirq.h
+generic-y += hw_irq.h irq_regs.h kdebug.h percpu.h sections.h topology.h xor.h
+generic-y += ftrace.h
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/kdebug.h linux-libre-3.2-gnu/arch/um/include/asm/kdebug.h
--- linux-libre-3.1-gnu/arch/um/include/asm/kdebug.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/kdebug.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/mmu_context.h linux-libre-3.2-gnu/arch/um/include/asm/mmu_context.h
--- linux-libre-3.1-gnu/arch/um/include/asm/mmu_context.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/mmu_context.h	2012-01-04 18:55:44.000000000 -0500
@@ -6,15 +6,12 @@
 #ifndef __UM_MMU_CONTEXT_H
 #define __UM_MMU_CONTEXT_H
 
-#include "linux/sched.h"
-#include "um_mmu.h"
+#include <linux/sched.h>
+#include <asm/mmu.h>
 
 extern void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm);
 extern void arch_exit_mmap(struct mm_struct *mm);
 
-#define get_mmu_context(task) do ; while(0)
-#define activate_context(tsk) do ; while(0)
-
 #define deactivate_mm(tsk,mm)	do { } while (0)
 
 extern void force_flush_all(void);
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/mmu.h linux-libre-3.2-gnu/arch/um/include/asm/mmu.h
--- linux-libre-3.1-gnu/arch/um/include/asm/mmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/mmu.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,12 +1,24 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Licensed under the GPL
  */
 
-#ifndef __MMU_H
-#define __MMU_H
+#ifndef __ARCH_UM_MMU_H
+#define __ARCH_UM_MMU_H
 
-#include "um_mmu.h"
+#include "mm_id.h"
+#include <asm/mm_context.h>
 
-#endif
+typedef struct mm_context {
+	struct mm_id id;
+	struct uml_arch_mm_context arch;
+	struct page **stub_pages;
+} mm_context_t;
+
+extern void __switch_mm(struct mm_id * mm_idp);
 
+/* Avoid tangled inclusion with asm/ldt.h */
+extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm);
+extern void free_ldt(struct mm_context *mm);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/page.h linux-libre-3.2-gnu/arch/um/include/asm/page.h
--- linux-libre-3.1-gnu/arch/um/include/asm/page.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/page.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 struct page;
 
 #include <linux/types.h>
-#include <sysdep/vm-flags.h>
+#include <asm/vm-flags.h>
 
 /*
  * These are used to make use of C type-checking..
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/page_offset.h linux-libre-3.2-gnu/arch/um/include/asm/page_offset.h
--- linux-libre-3.1-gnu/arch/um/include/asm/page_offset.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/page_offset.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#define PAGE_OFFSET_RAW (uml_physmem)
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/pda.h linux-libre-3.2-gnu/arch/um/include/asm/pda.h
--- linux-libre-3.1-gnu/arch/um/include/asm/pda.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/pda.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_PDA_X86_64_H
-#define __UM_PDA_X86_64_H
-
-/* XXX */
-struct foo {
-	unsigned int __softirq_pending;
-	unsigned int __nmi_count;
-};
-
-extern struct foo me;
-
-#define read_pda(me) (&me)
-
-#endif
-
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/percpu.h linux-libre-3.2-gnu/arch/um/include/asm/percpu.h
--- linux-libre-3.1-gnu/arch/um/include/asm/percpu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/percpu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __UM_PERCPU_H
-#define __UM_PERCPU_H
-
-#include <asm-generic/percpu.h>
-
-#endif /* __UM_PERCPU_H */
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/ptrace-generic.h linux-libre-3.2-gnu/arch/um/include/asm/ptrace-generic.h
--- linux-libre-3.1-gnu/arch/um/include/asm/ptrace-generic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/ptrace-generic.h	2012-01-04 18:55:44.000000000 -0500
@@ -23,17 +23,10 @@
 #define PT_REGS_IP(r) UPT_IP(&(r)->regs)
 #define PT_REGS_SP(r) UPT_SP(&(r)->regs)
 
-#define PT_REG(r, reg) UPT_REG(&(r)->regs, reg)
-#define PT_REGS_SET(r, reg, val) UPT_SET(&(r)->regs, reg, val)
-
-#define PT_REGS_SET_SYSCALL_RETURN(r, res) \
-	UPT_SET_SYSCALL_RETURN(&(r)->regs, res)
 #define PT_REGS_RESTART_SYSCALL(r) UPT_RESTART_SYSCALL(&(r)->regs)
 
 #define PT_REGS_SYSCALL_NR(r) UPT_SYSCALL_NR(&(r)->regs)
 
-#define PT_REGS_SC(r) UPT_SC(&(r)->regs)
-
 #define instruction_pointer(regs) PT_REGS_IP(regs)
 
 struct task_struct;
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/required-features.h linux-libre-3.2-gnu/arch/um/include/asm/required-features.h
--- linux-libre-3.1-gnu/arch/um/include/asm/required-features.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/required-features.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-#ifndef __UM_REQUIRED_FEATURES_H
-#define __UM_REQUIRED_FEATURES_H
-
-/*
- * Nothing to see, just need something for the i386 and x86_64 asm
- * headers to include.
- */
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/sections.h linux-libre-3.2-gnu/arch/um/include/asm/sections.h
--- linux-libre-3.1-gnu/arch/um/include/asm/sections.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/sections.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef _UM_SECTIONS_H
-#define _UM_SECTIONS_H
-
-/* nothing to see, move along */
-#include <asm-generic/sections.h>
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/segment.h linux-libre-3.2-gnu/arch/um/include/asm/segment.h
--- linux-libre-3.1-gnu/arch/um/include/asm/segment.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/segment.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#ifndef __UM_SEGMENT_H
-#define __UM_SEGMENT_H
-
-extern int host_gdt_entry_tls_min;
-
-#define GDT_ENTRY_TLS_ENTRIES 3
-#define GDT_ENTRY_TLS_MIN host_gdt_entry_tls_min
-#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/system.h linux-libre-3.2-gnu/arch/um/include/asm/system.h
--- linux-libre-3.1-gnu/arch/um/include/asm/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/system.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,47 +0,0 @@
-#ifndef __UM_SYSTEM_GENERIC_H
-#define __UM_SYSTEM_GENERIC_H
-
-#include "sysdep/system.h"
-
-extern int get_signals(void);
-extern int set_signals(int enable);
-extern void block_signals(void);
-extern void unblock_signals(void);
-
-static inline unsigned long arch_local_save_flags(void)
-{
-	return get_signals();
-}
-
-static inline void arch_local_irq_restore(unsigned long flags)
-{
-	set_signals(flags);
-}
-
-static inline void arch_local_irq_enable(void)
-{
-	unblock_signals();
-}
-
-static inline void arch_local_irq_disable(void)
-{
-	block_signals();
-}
-
-static inline unsigned long arch_local_irq_save(void)
-{
-	unsigned long flags;
-	flags = arch_local_save_flags();
-	arch_local_irq_disable();
-	return flags;
-}
-
-static inline bool arch_irqs_disabled(void)
-{
-	return arch_local_save_flags() == 0;
-}
-
-extern void *_switch_to(void *prev, void *next, void *last);
-#define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/topology.h linux-libre-3.2-gnu/arch/um/include/asm/topology.h
--- linux-libre-3.1-gnu/arch/um/include/asm/topology.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/topology.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASM_UM_TOPOLOGY_H
-#define _ASM_UM_TOPOLOGY_H
-
-#include <asm-generic/topology.h>
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/uaccess.h linux-libre-3.2-gnu/arch/um/include/asm/uaccess.h
--- linux-libre-3.1-gnu/arch/um/include/asm/uaccess.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/uaccess.h	2012-01-04 18:55:44.000000000 -0500
@@ -6,15 +6,15 @@
 #ifndef __UM_UACCESS_H
 #define __UM_UACCESS_H
 
-#include <asm/errno.h>
-#include <asm/processor.h>
-
 /* thread_info has a mm_segment_t in it, so put the definition up here */
 typedef struct {
 	unsigned long seg;
 } mm_segment_t;
 
-#include "linux/thread_info.h"
+#include <linux/thread_info.h>
+#include <linux/errno.h>
+#include <asm/processor.h>
+#include <asm/elf.h>
 
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
@@ -38,7 +38,86 @@
 
 #define segment_eq(a, b) ((a).seg == (b).seg)
 
-#include "um_uaccess.h"
+#define __under_task_size(addr, size) \
+	(((unsigned long) (addr) < TASK_SIZE) && \
+	 (((unsigned long) (addr) + (size)) < TASK_SIZE))
+
+#define __access_ok_vsyscall(type, addr, size) \
+	 ((type == VERIFY_READ) && \
+	  ((unsigned long) (addr) >= FIXADDR_USER_START) && \
+	  ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
+	  ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))
+
+#define __addr_range_nowrap(addr, size) \
+	((unsigned long) (addr) <= ((unsigned long) (addr) + (size)))
+
+#define access_ok(type, addr, size) \
+	(__addr_range_nowrap(addr, size) && \
+	 (__under_task_size(addr, size) || \
+	  __access_ok_vsyscall(type, addr, size) || \
+	  segment_eq(get_fs(), KERNEL_DS)))
+
+extern int copy_from_user(void *to, const void __user *from, int n);
+extern int copy_to_user(void __user *to, const void *from, int n);
+
+/*
+ * strncpy_from_user: - Copy a NUL terminated string from userspace.
+ * @dst:   Destination address, in kernel space.  This buffer must be at
+ *         least @count bytes long.
+ * @src:   Source address, in user space.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
+ *
+ * Copies a NUL-terminated string from userspace to kernel space.
+ *
+ * On success, returns the length of the string (not including the trailing
+ * NUL).
+ *
+ * If access to userspace fails, returns -EFAULT (some data may have been
+ * copied).
+ *
+ * If @count is smaller than the length of the string, copies @count bytes
+ * and returns @count.
+ */
+
+extern int strncpy_from_user(char *dst, const char __user *src, int count);
+
+/*
+ * __clear_user: - Zero a block of memory in user space, with less checking.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
+extern int __clear_user(void __user *mem, int len);
+
+/*
+ * clear_user: - Zero a block of memory in user space.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
+extern int clear_user(void __user *mem, int len);
+
+/*
+ * strlen_user: - Get the size of a string in user space.
+ * @str: The string to measure.
+ * @n:   The maximum valid length
+ *
+ * Get the size of a NUL-terminated string in user space.
+ *
+ * Returns the size of the string INCLUDING the terminating NUL.
+ * On exception, returns 0.
+ * If the string is too long, returns a value greater than @n.
+ */
+extern int strnlen_user(const void __user *str, int len);
 
 #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
 
diff -druN linux-libre-3.1-gnu/arch/um/include/asm/xor.h linux-libre-3.2-gnu/arch/um/include/asm/xor.h
--- linux-libre-3.1-gnu/arch/um/include/asm/xor.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/asm/xor.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __UM_XOR_H
-#define __UM_XOR_H
-
-#include "asm-generic/xor.h"
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/as-layout.h linux-libre-3.2-gnu/arch/um/include/shared/as-layout.h
--- linux-libre-3.1-gnu/arch/um/include/shared/as-layout.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/as-layout.h	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 #ifndef __START_H__
 #define __START_H__
 
-#include "kern_constants.h"
+#include <generated/asm-offsets.h>
 
 /*
  * Stolen from linux/const.h, which can't be directly included since
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/chan_kern.h linux-libre-3.2-gnu/arch/um/include/shared/chan_kern.h
--- linux-libre-3.1-gnu/arch/um/include/shared/chan_kern.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/chan_kern.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/* 
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __CHAN_KERN_H__
-#define __CHAN_KERN_H__
-
-#include "linux/tty.h"
-#include "linux/list.h"
-#include "linux/console.h"
-#include "chan_user.h"
-#include "line.h"
-
-struct chan {
-	struct list_head list;
-	struct list_head free_list;
-	struct line *line;
-	char *dev;
-	unsigned int primary:1;
-	unsigned int input:1;
-	unsigned int output:1;
-	unsigned int opened:1;
-	unsigned int enabled:1;
-	int fd;
-	const struct chan_ops *ops;
-	void *data;
-};
-
-extern void chan_interrupt(struct list_head *chans, struct delayed_work *task,
-			   struct tty_struct *tty, int irq);
-extern int parse_chan_pair(char *str, struct line *line, int device,
-			   const struct chan_opts *opts, char **error_out);
-extern int write_chan(struct list_head *chans, const char *buf, int len,
-			     int write_irq);
-extern int console_write_chan(struct list_head *chans, const char *buf, 
-			      int len);
-extern int console_open_chan(struct line *line, struct console *co);
-extern void deactivate_chan(struct list_head *chans, int irq);
-extern void reactivate_chan(struct list_head *chans, int irq);
-extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
-extern int enable_chan(struct line *line);
-extern void close_chan(struct list_head *chans, int delay_free_irq);
-extern int chan_window_size(struct list_head *chans, 
-			     unsigned short *rows_out, 
-			     unsigned short *cols_out);
-extern int chan_config_string(struct list_head *chans, char *str, int size,
-			      char **error_out);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/chan_user.h linux-libre-3.2-gnu/arch/um/include/shared/chan_user.h
--- linux-libre-3.1-gnu/arch/um/include/shared/chan_user.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/chan_user.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __CHAN_USER_H__
-#define __CHAN_USER_H__
-
-#include "init.h"
-
-struct chan_opts {
-	void (*const announce)(char *dev_name, int dev);
-	char *xterm_title;
-	const int raw;
-};
-
-enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
-
-struct chan_ops {
-	char *type;
-	void *(*init)(char *, int, const struct chan_opts *);
-	int (*open)(int, int, int, void *, char **);
-	void (*close)(int, void *);
-	int (*read)(int, char *, void *);
-	int (*write)(int, const char *, int, void *);
-	int (*console_write)(int, const char *, int);
-	int (*window_size)(int, void *, unsigned short *, unsigned short *);
-	void (*free)(void *);
-	int winch;
-};
-
-extern const struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops,
-	tty_ops, xterm_ops;
-
-extern void generic_close(int fd, void *unused);
-extern int generic_read(int fd, char *c_out, void *unused);
-extern int generic_write(int fd, const char *buf, int n, void *unused);
-extern int generic_console_write(int fd, const char *buf, int n);
-extern int generic_window_size(int fd, void *unused, unsigned short *rows_out,
-			       unsigned short *cols_out);
-extern void generic_free(void *data);
-
-struct tty_struct;
-extern void register_winch(int fd,  struct tty_struct *tty);
-extern void register_winch_irq(int fd, int tty_fd, int pid,
-			       struct tty_struct *tty, unsigned long stack);
-
-#define __channel_help(fn, prefix) \
-__uml_help(fn, prefix "[0-9]*=<channel description>\n" \
-"    Attach a console or serial line to a host channel.  See\n" \
-"    http://user-mode-linux.sourceforge.net/old/input.html for a complete\n" \
-"    description of this switch.\n\n" \
-);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/common-offsets.h linux-libre-3.2-gnu/arch/um/include/shared/common-offsets.h
--- linux-libre-3.1-gnu/arch/um/include/shared/common-offsets.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/common-offsets.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,6 @@
 
 DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
 
-OFFSET(HOST_TASK_REGS, task_struct, thread.regs);
 OFFSET(HOST_TASK_PID, task_struct, pid);
 
 DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE);
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/initrd.h linux-libre-3.2-gnu/arch/um/include/shared/initrd.h
--- linux-libre-3.1-gnu/arch/um/include/shared/initrd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/initrd.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __INITRD_USER_H__
-#define __INITRD_USER_H__
-
-extern int load_initrd(char *filename, void *buf, int size);
-
-#endif
-
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/kern.h linux-libre-3.2-gnu/arch/um/include/shared/kern.h
--- linux-libre-3.1-gnu/arch/um/include/shared/kern.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/kern.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,28 +13,10 @@
  * includes.
  */
 
-extern int errno;
-
-extern int clone(int (*proc)(void *), void *sp, int flags, void *data);
-extern int sleep(int);
 extern int printf(const char *fmt, ...);
-extern char *strerror(int errnum);
-extern char *ptsname(int __fd);
-extern int munmap(void *, int);
 extern void *sbrk(int increment);
-extern void *malloc(int size);
-extern void perror(char *err);
-extern int kill(int pid, int sig);
-extern int getuid(void);
-extern int getgid(void);
 extern int pause(void);
-extern int write(int, const void *, int);
 extern void exit(int);
-extern int close(int);
-extern int read(unsigned int, char *, int);
-extern int pipe(int *);
-extern int sched_yield(void);
-extern int ptrace(int op, int pid, long addr, long data);
 
 #endif
 
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/kern_util.h linux-libre-3.2-gnu/arch/um/include/shared/kern_util.h
--- linux-libre-3.1-gnu/arch/um/include/shared/kern_util.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/kern_util.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,6 @@
 extern void free_stack(unsigned long stack, int order);
 
 extern int do_signal(void);
-extern void copy_sc(struct uml_pt_regs *regs, void *from);
 extern void interrupt_end(void);
 extern void relay_signal(int sig, struct uml_pt_regs *regs);
 
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/ldt.h linux-libre-3.2-gnu/arch/um/include/shared/ldt.h
--- linux-libre-3.1-gnu/arch/um/include/shared/ldt.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/ldt.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
- * Licensed under the GPL
- *
- * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
- */
-
-#ifndef __ASM_LDT_H
-#define __ASM_LDT_H
-
-#include <linux/mutex.h>
-#include <sysdep/host_ldt.h>
-
-extern void ldt_host_info(void);
-
-#define LDT_PAGES_MAX \
-	((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
-#define LDT_ENTRIES_PER_PAGE \
-	(PAGE_SIZE/LDT_ENTRY_SIZE)
-#define LDT_DIRECT_ENTRIES \
-	((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE)
-
-struct ldt_entry {
-	__u32 a;
-	__u32 b;
-};
-
-typedef struct uml_ldt {
-	int entry_count;
-	struct mutex lock;
-	union {
-		struct ldt_entry * pages[LDT_PAGES_MAX];
-		struct ldt_entry entries[LDT_DIRECT_ENTRIES];
-	} u;
-} uml_ldt_t;
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/line.h linux-libre-3.2-gnu/arch/um/include/shared/line.h
--- linux-libre-3.1-gnu/arch/um/include/shared/line.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/line.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,106 +0,0 @@
-/* 
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __LINE_H__
-#define __LINE_H__
-
-#include "linux/list.h"
-#include "linux/workqueue.h"
-#include "linux/tty.h"
-#include "linux/interrupt.h"
-#include "linux/spinlock.h"
-#include "linux/mutex.h"
-#include "chan_user.h"
-#include "mconsole_kern.h"
-
-/* There's only one modifiable field in this - .mc.list */
-struct line_driver {
-	const char *name;
-	const char *device_name;
-	const short major;
-	const short minor_start;
-	const short type;
-	const short subtype;
-	const int read_irq;
-	const char *read_irq_name;
-	const int write_irq;
-	const char *write_irq_name;
-	struct mc_device mc;
-};
-
-struct line {
-	struct tty_struct *tty;
-	spinlock_t count_lock;
-	unsigned long count;
-	int valid;
-
-	char *init_str;
-	int init_pri;
-	struct list_head chan_list;
-
-	/*This lock is actually, mostly, local to*/
-	spinlock_t lock;
-	int throttled;
-	/* Yes, this is a real circular buffer.
-	 * XXX: And this should become a struct kfifo!
-	 *
-	 * buffer points to a buffer allocated on demand, of length
-	 * LINE_BUFSIZE, head to the start of the ring, tail to the end.*/
-	char *buffer;
-	char *head;
-	char *tail;
-
-	int sigio;
-	struct delayed_work task;
-	const struct line_driver *driver;
-	int have_irq;
-};
-
-#define LINE_INIT(str, d) \
-	{ .count_lock =	__SPIN_LOCK_UNLOCKED((str).count_lock), \
-	  .init_str =	str,	\
-	  .init_pri =	INIT_STATIC, \
-	  .valid =	1, \
-	  .lock =	__SPIN_LOCK_UNLOCKED((str).lock), \
-	  .driver =	d }
-
-extern void line_close(struct tty_struct *tty, struct file * filp);
-extern int line_open(struct line *lines, struct tty_struct *tty);
-extern int line_setup(struct line *lines, unsigned int sizeof_lines,
-		      char *init, char **error_out);
-extern int line_write(struct tty_struct *tty, const unsigned char *buf,
-		      int len);
-extern int line_put_char(struct tty_struct *tty, unsigned char ch);
-extern void line_set_termios(struct tty_struct *tty, struct ktermios * old);
-extern int line_chars_in_buffer(struct tty_struct *tty);
-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, unsigned int cmd,
-				unsigned long arg);
-extern void line_throttle(struct tty_struct *tty);
-extern void line_unthrottle(struct tty_struct *tty);
-
-extern char *add_xterm_umid(char *base);
-extern int line_setup_irq(int fd, int input, int output, struct line *line,
-			  void *data);
-extern void line_close_chan(struct line *line);
-extern struct tty_driver *register_lines(struct line_driver *line_driver,
-					 const struct tty_operations *driver,
-					 struct line *lines, int nlines);
-extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
-extern void close_lines(struct line *lines, int nlines);
-
-extern int line_config(struct line *lines, unsigned int sizeof_lines,
-		       char *str, const struct chan_opts *opts,
-		       char **error_out);
-extern int line_id(char **str, int *start_out, int *end_out);
-extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n,
-		       char **error_out);
-extern int line_get_config(char *dev, struct line *lines,
-			   unsigned int sizeof_lines, char *str,
-			   int size, char **error_out);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/mconsole.h linux-libre-3.2-gnu/arch/um/include/shared/mconsole.h
--- linux-libre-3.1-gnu/arch/um/include/shared/mconsole.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/mconsole.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __MCONSOLE_H__
-#define __MCONSOLE_H__
-
-#ifndef __KERNEL__
-#include <stdint.h>
-#define u32 uint32_t
-#endif
-
-#include "sysdep/ptrace.h"
-
-#define MCONSOLE_MAGIC (0xcafebabe)
-#define MCONSOLE_MAX_DATA (512)
-#define MCONSOLE_VERSION 2
-
-struct mconsole_request {
-	u32 magic;
-	u32 version;
-	u32 len;
-	char data[MCONSOLE_MAX_DATA];
-};
-
-struct mconsole_reply {
-	u32 err;
-	u32 more;
-	u32 len;
-	char data[MCONSOLE_MAX_DATA];
-};
-
-struct mconsole_notify {
-	u32 magic;
-	u32 version;
-	enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG,
-	       MCONSOLE_USER_NOTIFY } type;
-	u32 len;
-	char data[MCONSOLE_MAX_DATA];
-};
-
-struct mc_request;
-
-enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC };
-
-struct mconsole_command
-{
-	char *command;
-	void (*handler)(struct mc_request *req);
-	enum mc_context context;
-};
-
-struct mc_request
-{
-	int len;
-	int as_interrupt;
-
-	int originating_fd;
-	unsigned int originlen;
-	unsigned char origin[128];			/* sockaddr_un */
-
-	struct mconsole_request request;
-	struct mconsole_command *cmd;
-	struct uml_pt_regs regs;
-};
-
-extern char mconsole_socket_name[];
-
-extern int mconsole_unlink_socket(void);
-extern int mconsole_reply_len(struct mc_request *req, const char *reply,
-			      int len, int err, int more);
-extern int mconsole_reply(struct mc_request *req, const char *str, int err,
-			  int more);
-
-extern void mconsole_version(struct mc_request *req);
-extern void mconsole_help(struct mc_request *req);
-extern void mconsole_halt(struct mc_request *req);
-extern void mconsole_reboot(struct mc_request *req);
-extern void mconsole_config(struct mc_request *req);
-extern void mconsole_remove(struct mc_request *req);
-extern void mconsole_sysrq(struct mc_request *req);
-extern void mconsole_cad(struct mc_request *req);
-extern void mconsole_stop(struct mc_request *req);
-extern void mconsole_go(struct mc_request *req);
-extern void mconsole_log(struct mc_request *req);
-extern void mconsole_proc(struct mc_request *req);
-extern void mconsole_stack(struct mc_request *req);
-
-extern int mconsole_get_request(int fd, struct mc_request *req);
-extern int mconsole_notify(char *sock_name, int type, const void *data,
-			   int len);
-extern char *mconsole_notify_socket(void);
-extern void lock_notify(void);
-extern void unlock_notify(void);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/mconsole_kern.h linux-libre-3.2-gnu/arch/um/include/shared/mconsole_kern.h
--- linux-libre-3.1-gnu/arch/um/include/shared/mconsole_kern.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/mconsole_kern.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __MCONSOLE_KERN_H__
-#define __MCONSOLE_KERN_H__
-
-#include "linux/list.h"
-#include "mconsole.h"
-
-struct mconsole_entry {
-	struct list_head list;
-	struct mc_request request;
-};
-
-/* All these methods are called in process context. */
-struct mc_device {
-	struct list_head list;
-	char *name;
-	int (*config)(char *, char **);
-	int (*get_config)(char *, char *, int, char **);
-	int (*id)(char **, int *, int *);
-	int (*remove)(int, char **);
-};
-
-#define CONFIG_CHUNK(str, size, current, chunk, end) \
-do { \
-	current += strlen(chunk); \
-	if(current >= size) \
-		str = NULL; \
-	if(str != NULL){ \
-		strcpy(str, chunk); \
-		str += strlen(chunk); \
-	} \
-	if(end) \
-		current++; \
-} while(0)
-
-#ifdef CONFIG_MCONSOLE
-
-extern void mconsole_register_dev(struct mc_device *new);
-
-#else
-
-static inline void mconsole_register_dev(struct mc_device *new)
-{
-}
-
-#endif
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/mem_kern.h linux-libre-3.2-gnu/arch/um/include/shared/mem_kern.h
--- linux-libre-3.1-gnu/arch/um/include/shared/mem_kern.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/mem_kern.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __MEM_KERN_H__
-#define __MEM_KERN_H__
-
-#include "linux/list.h"
-#include "linux/types.h"
-
-struct remapper {
-	struct list_head list;
-	int (*proc)(int, unsigned long, int, __u64);
-};
-
-extern void register_remapper(struct remapper *info);
-
-#endif
-
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/os.h linux-libre-3.2-gnu/arch/um/include/shared/os.h
--- linux-libre-3.1-gnu/arch/um/include/shared/os.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/os.h	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,6 @@
 #include "irq_user.h"
 #include "longjmp.h"
 #include "mm_id.h"
-#include "sysdep/tls.h"
 
 #define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
 
@@ -203,12 +202,6 @@
 extern int can_drop_memory(void);
 extern void os_flush_stdout(void);
 
-/* uaccess.c */
-extern unsigned long __do_user_copy(void *to, const void *from, int n,
-				    void **fault_addr, jmp_buf **fault_catcher,
-				    void (*op)(void *to, const void *from,
-					       int n), int *faulted_out);
-
 /* execvp.c */
 extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
 /* helper.c */
@@ -218,10 +211,6 @@
 extern int helper_wait(int pid);
 
 
-/* tls.c */
-extern int os_set_thread_area(user_desc_t *info, int pid);
-extern int os_get_thread_area(user_desc_t *info, int pid);
-
 /* umid.c */
 extern int umid_file_name(char *name, char *buf, int len);
 extern int set_umid(char *name);
@@ -231,7 +220,7 @@
 extern void timer_init(void);
 extern void set_sigstack(void *sig_stack, int size);
 extern void remove_sigstack(void);
-extern void set_handler(int sig, void (*handler)(int), int flags, ...);
+extern void set_handler(int sig);
 extern int change_sig(int signal, int on);
 extern void block_signals(void);
 extern void unblock_signals(void);
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/process.h linux-libre-3.2-gnu/arch/um/include/shared/process.h
--- linux-libre-3.1-gnu/arch/um/include/shared/process.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/process.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __PROCESS_H__
-#define __PROCESS_H__
-
-#include <signal.h>
-
-/* Copied from linux/compiler-gcc.h since we can't include it directly */
-#define barrier() __asm__ __volatile__("": : :"memory")
-
-extern void sig_handler(int sig, struct sigcontext *sc);
-extern void alarm_handler(int sig, struct sigcontext *sc);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/ptrace_user.h linux-libre-3.2-gnu/arch/um/include/shared/ptrace_user.h
--- linux-libre-3.1-gnu/arch/um/include/shared/ptrace_user.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/ptrace_user.h	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,8 @@
 #ifndef __PTRACE_USER_H__
 #define __PTRACE_USER_H__
 
-#include "sysdep/ptrace_user.h"
+#include <sys/ptrace.h>
+#include <sysdep/ptrace_user.h>
 
 extern int ptrace_getregs(long pid, unsigned long *regs_out);
 extern int ptrace_setregs(long pid, unsigned long *regs_in);
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/skas_ptregs.h linux-libre-3.2-gnu/arch/um/include/shared/skas_ptregs.h
--- linux-libre-3.1-gnu/arch/um/include/shared/skas_ptregs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/skas_ptregs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __SKAS_PT_REGS_
-#define __SKAS_PT_REGS_
-
-#include <user_constants.h>
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/syscall.h linux-libre-3.2-gnu/arch/um/include/shared/syscall.h
--- linux-libre-3.1-gnu/arch/um/include/shared/syscall.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/syscall.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSCALL_USER_H
-#define __SYSCALL_USER_H
-
-extern int record_syscall_start(int syscall);
-extern void record_syscall_end(int index, long result);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/task.h linux-libre-3.2-gnu/arch/um/include/shared/task.h
--- linux-libre-3.1-gnu/arch/um/include/shared/task.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/task.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-#ifndef __TASK_H
-#define __TASK_H
-
-#include <kern_constants.h>
-
-#define TASK_REGS(task) ((struct uml_pt_regs *) &(((char *) (task))[HOST_TASK_REGS]))
-#define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID]))
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/tlb.h linux-libre-3.2-gnu/arch/um/include/shared/tlb.h
--- linux-libre-3.1-gnu/arch/um/include/shared/tlb.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/tlb.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __TLB_H__
-#define __TLB_H__
-
-#include "um_mmu.h"
-
-extern void force_flush_all(void);
-extern int flush_tlb_kernel_range_common(unsigned long start,
-					 unsigned long end);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/ubd_user.h linux-libre-3.2-gnu/arch/um/include/shared/ubd_user.h
--- linux-libre-3.1-gnu/arch/um/include/shared/ubd_user.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/ubd_user.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Copyright (C) 2001 RidgeRun, Inc (glonnon@ridgerun.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_UBD_USER_H
-#define __UM_UBD_USER_H
-
-extern void ignore_sigwinch_sig(void);
-extern int start_io_thread(unsigned long sp, int *fds_out);
-extern int io_thread(void *arg);
-extern int kernel_fd;
-
-#endif
-
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/um_malloc.h linux-libre-3.2-gnu/arch/um/include/shared/um_malloc.h
--- linux-libre-3.1-gnu/arch/um/include/shared/um_malloc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/um_malloc.h	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 #ifndef __UM_MALLOC_H__
 #define __UM_MALLOC_H__
 
-#include "kern_constants.h"
+#include <generated/asm-offsets.h>
 
 extern void *uml_kmalloc(int size, int flags);
 extern void kfree(const void *ptr);
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/um_mmu.h linux-libre-3.2-gnu/arch/um/include/shared/um_mmu.h
--- linux-libre-3.1-gnu/arch/um/include/shared/um_mmu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/um_mmu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,24 +0,0 @@
-/* 
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __ARCH_UM_MMU_H
-#define __ARCH_UM_MMU_H
-
-#include "mm_id.h"
-#include "ldt.h"
-
-typedef struct mm_context {
-	struct mm_id id;
-	struct uml_ldt ldt;
-	struct page **stub_pages;
-} mm_context_t;
-
-extern void __switch_mm(struct mm_id * mm_idp);
-
-/* Avoid tangled inclusion with asm/ldt.h */
-extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm);
-extern void free_ldt(struct mm_context *mm);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/um_uaccess.h linux-libre-3.2-gnu/arch/um/include/shared/um_uaccess.h
--- linux-libre-3.1-gnu/arch/um/include/shared/um_uaccess.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/um_uaccess.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,97 +0,0 @@
-/* 
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __ARCH_UM_UACCESS_H
-#define __ARCH_UM_UACCESS_H
-
-#include <asm/elf.h>
-#include <asm/fixmap.h>
-#include "sysdep/archsetjmp.h"
-
-#define __under_task_size(addr, size) \
-	(((unsigned long) (addr) < TASK_SIZE) && \
-	 (((unsigned long) (addr) + (size)) < TASK_SIZE))
-
-#define __access_ok_vsyscall(type, addr, size) \
-	 ((type == VERIFY_READ) && \
-	  ((unsigned long) (addr) >= FIXADDR_USER_START) && \
-	  ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
-	  ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))
-
-#define __addr_range_nowrap(addr, size) \
-	((unsigned long) (addr) <= ((unsigned long) (addr) + (size)))
-
-#define access_ok(type, addr, size) \
-	(__addr_range_nowrap(addr, size) && \
-	 (__under_task_size(addr, size) || \
-	  __access_ok_vsyscall(type, addr, size) || \
-	  segment_eq(get_fs(), KERNEL_DS)))
-
-extern int copy_from_user(void *to, const void __user *from, int n);
-extern int copy_to_user(void __user *to, const void *from, int n);
-
-extern int __do_copy_to_user(void *to, const void *from, int n,
-			     void **fault_addr, jmp_buf **fault_catcher);
-
-/*
- * strncpy_from_user: - Copy a NUL terminated string from userspace.
- * @dst:   Destination address, in kernel space.  This buffer must be at
- *         least @count bytes long.
- * @src:   Source address, in user space.
- * @count: Maximum number of bytes to copy, including the trailing NUL.
- *
- * Copies a NUL-terminated string from userspace to kernel space.
- *
- * On success, returns the length of the string (not including the trailing
- * NUL).
- *
- * If access to userspace fails, returns -EFAULT (some data may have been
- * copied).
- *
- * If @count is smaller than the length of the string, copies @count bytes
- * and returns @count.
- */
-
-extern int strncpy_from_user(char *dst, const char __user *src, int count);
-
-/*
- * __clear_user: - Zero a block of memory in user space, with less checking.
- * @to:   Destination address, in user space.
- * @n:    Number of bytes to zero.
- *
- * Zero a block of memory in user space.  Caller must check
- * the specified block with access_ok() before calling this function.
- *
- * Returns number of bytes that could not be cleared.
- * On success, this will be zero.
- */
-extern int __clear_user(void __user *mem, int len);
-
-/*
- * clear_user: - Zero a block of memory in user space.
- * @to:   Destination address, in user space.
- * @n:    Number of bytes to zero.
- *
- * Zero a block of memory in user space.
- *
- * Returns number of bytes that could not be cleared.
- * On success, this will be zero.
- */
-extern int clear_user(void __user *mem, int len);
-
-/*
- * strlen_user: - Get the size of a string in user space.
- * @str: The string to measure.
- * @n:   The maximum valid length
- *
- * Get the size of a NUL-terminated string in user space.
- *
- * Returns the size of the string INCLUDING the terminating NUL.
- * On exception, returns 0.
- * If the string is too long, returns a value greater than @n.
- */
-extern int strnlen_user(const void __user *str, int len);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/include/shared/user.h linux-libre-3.2-gnu/arch/um/include/shared/user.h
--- linux-libre-3.1-gnu/arch/um/include/shared/user.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/include/shared/user.h	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
 #ifndef __USER_H__
 #define __USER_H__
 
-#include "kern_constants.h"
+#include <generated/asm-offsets.h>
 
 /*
  * The usual definition - copied here because the kernel provides its own,
@@ -36,10 +36,11 @@
 }
 #endif
 
-extern void schedule(void);
 extern int in_aton(char *str);
-extern int open_gdb_chan(void);
 extern size_t strlcpy(char *, const char *, size_t);
 extern size_t strlcat(char *, const char *, size_t);
 
+/* Copied from linux/compiler-gcc.h since we can't include it directly */
+#define barrier() __asm__ __volatile__("": : :"memory")
+
 #endif
diff -druN linux-libre-3.1-gnu/arch/um/Kconfig.char linux-libre-3.2-gnu/arch/um/Kconfig.char
--- linux-libre-3.1-gnu/arch/um/Kconfig.char	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/Kconfig.char	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,4 @@
-
-menu "Character Devices"
+menu "UML Character Devices"
 
 config STDERR_CONSOLE
 	bool "stderr console"
@@ -105,92 +104,6 @@
           this if you expect the UML that you build to be run in environments
           which don't have a set of /dev/pty* devices.
 
-config UNIX98_PTYS
-	bool "Unix98 PTY support"
-	help
-	  A pseudo terminal (PTY) is a software device consisting of two
-	  halves: a master and a slave. The slave device behaves identical to
-	  a physical terminal; the master device is used by a process to
-	  read data from and write data to the slave, thereby emulating a
-	  terminal. Typical programs for the master side are telnet servers
-	  and xterms.
-
-	  Linux has traditionally used the BSD-like names /dev/ptyxx for
-	  masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
-	  has a number of problems. The GNU C library glibc 2.1 and later,
-	  however, supports the Unix98 naming standard: in order to acquire a
-	  pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
-	  terminal is then made available to the process and the pseudo
-	  terminal slave can be accessed as /dev/pts/<number>. What was
-	  traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
-
-	  All modern Linux systems use the Unix98 ptys.  Say Y unless
-	  you're on an embedded system and want to conserve memory.
-
-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 RAW_DRIVER
-        tristate "RAW driver (/dev/raw/rawN)"
-	depends on BLOCK
-        help
-          The raw driver permits block devices to be bound to /dev/raw/rawN.
-          Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
-          See the raw(8) manpage for more details.
-
-          Applications should preferably open the device (eg /dev/hda1)
-          with the O_DIRECT flag.
-
-config MAX_RAW_DEVS
-        int "Maximum number of RAW devices to support (1-8192)"
-        depends on RAW_DRIVER
-        default "256"
-        help
-          The maximum number of RAW devices that are supported.
-          Default is 256. Increase this number in case you need lots of
-          raw devices.
-
-config LEGACY_PTY_COUNT
-	int "Maximum number of legacy PTY in use"
-	depends on LEGACY_PTYS
-	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 WATCHDOG
-	bool "Watchdog Timer Support"
-
-config WATCHDOG_NOWAYOUT
-	bool "Disable watchdog shutdown on close"
-	depends on WATCHDOG
-
-config SOFT_WATCHDOG
-	tristate "Software Watchdog"
-	depends on WATCHDOG
-
-config UML_WATCHDOG
-	tristate "UML watchdog"
-	depends on WATCHDOG
-
 config UML_SOUND
 	tristate "Sound support"
 	help
@@ -211,29 +124,4 @@
 	tristate
 	default UML_SOUND
 
-#It is selected elsewhere, so kconfig would warn without this.
-config HW_RANDOM
-	tristate
-	default n
-
-config UML_RANDOM
-	tristate "Hardware random number generator"
-	help
-	  This option enables UML's "hardware" random number generator.  It
-	  attaches itself to the host's /dev/random, supplying as much entropy
-	  as the host has, rather than the small amount the UML gets from its
-	  own drivers.  It registers itself as a standard hardware random number
-	  generator, major 10, minor 183, and the canonical device name is
-	  /dev/hwrng.
-	  The way to make use of this is to install the rng-tools package
-	  (check your distro, or download from
-	  http://sourceforge.net/projects/gkernel/).  rngd periodically reads
-	  /dev/hwrng and injects the entropy into /dev/random.
-
-config MMAPPER
-	tristate "iomem emulation driver"
-	help
-	  This driver allows a host file to be used as emulated IO memory inside
-	  UML.
-
 endmenu
diff -druN linux-libre-3.1-gnu/arch/um/Kconfig.rest linux-libre-3.2-gnu/arch/um/Kconfig.rest
--- linux-libre-3.1-gnu/arch/um/Kconfig.rest	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/Kconfig.rest	2012-01-04 18:55:44.000000000 -0500
@@ -2,20 +2,14 @@
 
 source "kernel/Kconfig.freezer"
 
-source "drivers/block/Kconfig"
-
 source "arch/um/Kconfig.char"
 
-source "drivers/base/Kconfig"
+source "drivers/Kconfig"
 
 source "net/Kconfig"
 
 source "arch/um/Kconfig.net"
 
-source "drivers/net/Kconfig"
-
-source "drivers/connector/Kconfig"
-
 source "fs/Kconfig"
 
 source "security/Kconfig"
@@ -24,19 +18,4 @@
 
 source "lib/Kconfig"
 
-source "drivers/scsi/Kconfig"
-
-source "drivers/md/Kconfig"
-
-if BROKEN
-	source "drivers/mtd/Kconfig"
-endif
-
-source "drivers/leds/Kconfig"
-
-#This is just to shut up some Kconfig warnings, so no prompt.
-config INPUT
-	tristate
-	default n
-
 source "arch/um/Kconfig.debug"
diff -druN linux-libre-3.1-gnu/arch/um/Kconfig.um linux-libre-3.2-gnu/arch/um/Kconfig.um
--- linux-libre-3.1-gnu/arch/um/Kconfig.um	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/Kconfig.um	2012-01-04 18:55:44.000000000 -0500
@@ -148,5 +148,11 @@
 	  be 1 << order pages.  The default is OK unless you're running Valgrind
 	  on UML, in which case, set this to 3.
 
+config MMAPPER
+	tristate "iomem emulation driver"
+	help
+	  This driver allows a host file to be used as emulated IO memory inside
+	  UML.
+
 config NO_DMA
 	def_bool y
diff -druN linux-libre-3.1-gnu/arch/um/Kconfig.x86 linux-libre-3.2-gnu/arch/um/Kconfig.x86
--- linux-libre-3.1-gnu/arch/um/Kconfig.x86	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/Kconfig.x86	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-mainmenu "User Mode Linux/$SUBARCH $KERNELVERSION Kernel Configuration"
-
-source "arch/um/Kconfig.common"
-
-menu "UML-specific options"
-
-menu "Host processor type and features"
-
-config CMPXCHG_LOCAL
-	bool
-	default n
-
-config CMPXCHG_DOUBLE
-	bool
-	default n
-
-source "arch/x86/Kconfig.cpu"
-
-endmenu
-
-config UML_X86
-	def_bool y
-	select GENERIC_FIND_FIRST_BIT
-
-config 64BIT
-	bool
-	default SUBARCH = "x86_64"
-
-config X86_32
-	def_bool !64BIT
-	select HAVE_AOUT
-
-config X86_64
-	def_bool 64BIT
-
-config RWSEM_XCHGADD_ALGORITHM
-	def_bool X86_XADD && 64BIT
-
-config RWSEM_GENERIC_SPINLOCK
-	def_bool !RWSEM_XCHGADD_ALGORITHM
-
-config 3_LEVEL_PGTABLES
-	bool "Three-level pagetables (EXPERIMENTAL)" if !64BIT
-	default 64BIT
-	depends on EXPERIMENTAL
-	help
-	Three-level pagetables will let UML have more than 4G of physical
-	memory.  All the memory that can't be mapped directly will be treated
-	as high memory.
-
-	However, this it experimental on 32-bit architectures, so if unsure say
-	N (on x86-64 it's automatically enabled, instead, as it's safe there).
-
-config ARCH_HAS_SC_SIGNALS
-	def_bool !64BIT
-
-config ARCH_REUSE_HOST_VSYSCALL_AREA
-	def_bool !64BIT
-
-config SMP_BROKEN
-	def_bool 64BIT
-
-config GENERIC_HWEIGHT
-	def_bool y
-
-source "arch/um/Kconfig.um"
-
-endmenu
-
-source "arch/um/Kconfig.rest"
diff -druN linux-libre-3.1-gnu/arch/um/kernel/exec.c linux-libre-3.2-gnu/arch/um/kernel/exec.c
--- linux-libre-3.1-gnu/arch/um/kernel/exec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/kernel/exec.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,14 +3,15 @@
  * Licensed under the GPL
  */
 
-#include "linux/stddef.h"
-#include "linux/fs.h"
-#include "linux/ptrace.h"
-#include "linux/sched.h"
-#include "linux/slab.h"
-#include "asm/current.h"
-#include "asm/processor.h"
-#include "asm/uaccess.h"
+#include <linux/stddef.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <asm/current.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
 #include "as-layout.h"
 #include "mem_user.h"
 #include "skas.h"
@@ -41,6 +42,7 @@
 	PT_REGS_IP(regs) = eip;
 	PT_REGS_SP(regs) = esp;
 }
+EXPORT_SYMBOL(start_thread);
 
 static long execve1(const char *file,
 		    const char __user *const __user *argv,
diff -druN linux-libre-3.1-gnu/arch/um/kernel/gmon_syms.c linux-libre-3.2-gnu/arch/um/kernel/gmon_syms.c
--- linux-libre-3.1-gnu/arch/um/kernel/gmon_syms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/kernel/gmon_syms.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,18 +7,3 @@
 
 extern void __bb_init_func(void *)  __attribute__((weak));
 EXPORT_SYMBOL(__bb_init_func);
-
-/*
- * This is defined (and referred to in profiling stub code) only by some GCC
- * versions in libgcov.
- *
- * Since SuSE backported the fix, we cannot handle it depending on GCC version.
- * So, unconditionally export it. But also give it a weak declaration, which
- * will be overridden by any other one.
- */
-
-extern void __gcov_init(void *) __attribute__((weak));
-EXPORT_SYMBOL(__gcov_init);
-
-extern void __gcov_merge_add(void *) __attribute__((weak));
-EXPORT_SYMBOL(__gcov_merge_add);
diff -druN linux-libre-3.1-gnu/arch/um/kernel/initrd.c linux-libre-3.2-gnu/arch/um/kernel/initrd.c
--- linux-libre-3.1-gnu/arch/um/kernel/initrd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/kernel/initrd.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,12 +7,12 @@
 #include "linux/bootmem.h"
 #include "linux/initrd.h"
 #include "asm/types.h"
-#include "initrd.h"
 #include "init.h"
 #include "os.h"
 
 /* Changed by uml_initrd_setup, which is a setup */
 static char *initrd __initdata = NULL;
+static int load_initrd(char *filename, void *buf, int size);
 
 static int __init read_initrd(void)
 {
@@ -62,7 +62,7 @@
 "    name of the file containing the image.\n\n"
 );
 
-int load_initrd(char *filename, void *buf, int size)
+static int load_initrd(char *filename, void *buf, int size)
 {
 	int fd, n;
 
diff -druN linux-libre-3.1-gnu/arch/um/kernel/irq.c linux-libre-3.2-gnu/arch/um/kernel/irq.c
--- linux-libre-3.1-gnu/arch/um/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -258,6 +258,7 @@
 
 	ignore_sigio_fd(fd);
 }
+EXPORT_SYMBOL(deactivate_fd);
 
 /*
  * Called just before shutdown in order to provide a clean exec
diff -druN linux-libre-3.1-gnu/arch/um/kernel/ksyms.c linux-libre-3.2-gnu/arch/um/kernel/ksyms.c
--- linux-libre-3.1-gnu/arch/um/kernel/ksyms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/kernel/ksyms.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,33 +3,11 @@
  * Licensed under the GPL
  */
 
-#include "linux/module.h"
-#include "linux/syscalls.h"
-#include "asm/tlbflush.h"
-#include "asm/uaccess.h"
-#include "as-layout.h"
-#include "kern_util.h"
-#include "mem_user.h"
+#include <linux/module.h>
 #include "os.h"
 
-EXPORT_SYMBOL(uml_physmem);
 EXPORT_SYMBOL(set_signals);
 EXPORT_SYMBOL(get_signals);
-EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(sys_waitpid);
-EXPORT_SYMBOL(flush_tlb_range);
-
-EXPORT_SYMBOL(high_physmem);
-EXPORT_SYMBOL(empty_zero_page);
-EXPORT_SYMBOL(handle_page_fault);
-EXPORT_SYMBOL(find_iomem);
-
-EXPORT_SYMBOL(strnlen_user);
-EXPORT_SYMBOL(strncpy_from_user);
-EXPORT_SYMBOL(copy_to_user);
-EXPORT_SYMBOL(copy_from_user);
-EXPORT_SYMBOL(clear_user);
-EXPORT_SYMBOL(uml_strdup);
 
 EXPORT_SYMBOL(os_stat_fd);
 EXPORT_SYMBOL(os_stat_file);
@@ -57,24 +35,10 @@
 EXPORT_SYMBOL(os_accept_connection);
 EXPORT_SYMBOL(os_rcv_fd);
 EXPORT_SYMBOL(run_helper);
-EXPORT_SYMBOL(start_thread);
 EXPORT_SYMBOL(os_major);
 EXPORT_SYMBOL(os_minor);
 EXPORT_SYMBOL(os_makedev);
 
 EXPORT_SYMBOL(add_sigio_fd);
 EXPORT_SYMBOL(ignore_sigio_fd);
-EXPORT_SYMBOL(deactivate_fd);
 EXPORT_SYMBOL(sigio_broken);
-
-#ifdef CONFIG_SMP
-
-/* required for SMP */
-
-extern void __write_lock_failed(rwlock_t *rw);
-EXPORT_SYMBOL(__write_lock_failed);
-
-extern void __read_lock_failed(rwlock_t *rw);
-EXPORT_SYMBOL(__read_lock_failed);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/kernel/Makefile linux-libre-3.2-gnu/arch/um/kernel/Makefile
--- linux-libre-3.1-gnu/arch/um/kernel/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
 
 obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
 	physmem.o process.o ptrace.o reboot.o sigio.o \
-	signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \
+	signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o \
 	um_arch.o umid.o skas/
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
diff -druN linux-libre-3.1-gnu/arch/um/kernel/mem.c linux-libre-3.2-gnu/arch/um/kernel/mem.c
--- linux-libre-3.1-gnu/arch/um/kernel/mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/kernel/mem.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@
  */
 
 #include <linux/stddef.h>
+#include <linux/module.h>
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
 #include <linux/mm.h>
@@ -20,6 +21,7 @@
 
 /* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
 unsigned long *empty_zero_page = NULL;
+EXPORT_SYMBOL(empty_zero_page);
 /* allocated in paging_init and unchanged thereafter */
 static unsigned long *empty_bad_page = NULL;
 
diff -druN linux-libre-3.1-gnu/arch/um/kernel/physmem.c linux-libre-3.2-gnu/arch/um/kernel/physmem.c
--- linux-libre-3.1-gnu/arch/um/kernel/physmem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/kernel/physmem.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,20 +3,22 @@
  * Licensed under the GPL
  */
 
-#include "linux/bootmem.h"
-#include "linux/mm.h"
-#include "linux/pfn.h"
-#include "asm/page.h"
-#include "as-layout.h"
-#include "init.h"
-#include "kern.h"
-#include "mem_user.h"
-#include "os.h"
+#include <linux/module.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/pfn.h>
+#include <asm/page.h>
+#include <as-layout.h>
+#include <init.h>
+#include <kern.h>
+#include <mem_user.h>
+#include <os.h>
 
 static int physmem_fd = -1;
 
 /* Changed during early boot */
 unsigned long high_physmem;
+EXPORT_SYMBOL(high_physmem);
 
 extern unsigned long long physmem_size;
 
@@ -184,6 +186,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(find_iomem);
 
 static int setup_iomem(void)
 {
diff -druN linux-libre-3.1-gnu/arch/um/kernel/process.c linux-libre-3.2-gnu/arch/um/kernel/process.c
--- linux-libre-3.1-gnu/arch/um/kernel/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/kernel/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,12 +20,12 @@
 #include <linux/threads.h>
 #include <asm/current.h>
 #include <asm/pgtable.h>
+#include <asm/mmu_context.h>
 #include <asm/uaccess.h>
 #include "as-layout.h"
 #include "kern_util.h"
 #include "os.h"
 #include "skas.h"
-#include "tlb.h"
 
 /*
  * This is a per-cpu array.  A processor only modifies its entry and it only
@@ -78,6 +78,7 @@
 		      &current->thread.regs, 0, NULL, NULL);
 	return pid;
 }
+EXPORT_SYMBOL(kernel_thread);
 
 static inline void set_current(struct task_struct *task)
 {
@@ -286,6 +287,7 @@
 {
 	return kstrdup(string, GFP_KERNEL);
 }
+EXPORT_SYMBOL(uml_strdup);
 
 int copy_to_user_proc(void __user *to, void *from, int size)
 {
diff -druN linux-libre-3.1-gnu/arch/um/kernel/signal.c linux-libre-3.2-gnu/arch/um/kernel/signal.c
--- linux-libre-3.1-gnu/arch/um/kernel/signal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/kernel/signal.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,6 @@
 #include <asm/unistd.h>
 #include "frame_kern.h"
 #include "kern_util.h"
-#include <sysdep/sigcontext.h>
 
 EXPORT_SYMBOL(block_signals);
 EXPORT_SYMBOL(unblock_signals);
diff -druN linux-libre-3.1-gnu/arch/um/kernel/skas/clone.c linux-libre-3.2-gnu/arch/um/kernel/skas/clone.c
--- linux-libre-3.1-gnu/arch/um/kernel/skas/clone.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/kernel/skas/clone.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,6 @@
 #include <asm/unistd.h>
 #include <sys/time.h>
 #include "as-layout.h"
-#include "kern_constants.h"
 #include "ptrace_user.h"
 #include "stub-data.h"
 #include "sysdep/stub.h"
diff -druN linux-libre-3.1-gnu/arch/um/kernel/skas/uaccess.c linux-libre-3.2-gnu/arch/um/kernel/skas/uaccess.c
--- linux-libre-3.1-gnu/arch/um/kernel/skas/uaccess.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/kernel/skas/uaccess.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
 #include <linux/err.h>
 #include <linux/highmem.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <asm/current.h>
 #include <asm/page.h>
@@ -149,6 +150,7 @@
 	       buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to):
 	       n;
 }
+EXPORT_SYMBOL(copy_from_user);
 
 static int copy_chunk_to_user(unsigned long to, int len, void *arg)
 {
@@ -170,6 +172,7 @@
 	       buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) :
 	       n;
 }
+EXPORT_SYMBOL(copy_to_user);
 
 static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
 {
@@ -204,6 +207,7 @@
 		return -EFAULT;
 	return strnlen(dst, count);
 }
+EXPORT_SYMBOL(strncpy_from_user);
 
 static int clear_chunk(unsigned long addr, int len, void *unused)
 {
@@ -226,6 +230,7 @@
 	return access_ok(VERIFY_WRITE, mem, len) ?
 	       buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len;
 }
+EXPORT_SYMBOL(clear_user);
 
 static int strnlen_chunk(unsigned long str, int len, void *arg)
 {
@@ -251,3 +256,4 @@
 		return count + 1;
 	return -EFAULT;
 }
+EXPORT_SYMBOL(strnlen_user);
diff -druN linux-libre-3.1-gnu/arch/um/kernel/tlb.c linux-libre-3.2-gnu/arch/um/kernel/tlb.c
--- linux-libre-3.1-gnu/arch/um/kernel/tlb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/kernel/tlb.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@
  */
 
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -11,7 +12,6 @@
 #include "mem_user.h"
 #include "os.h"
 #include "skas.h"
-#include "tlb.h"
 
 struct host_vm_change {
 	struct host_vm_op {
@@ -287,7 +287,7 @@
 	}
 }
 
-int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
+static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
 {
 	struct mm_struct *mm;
 	pgd_t *pgd;
@@ -499,6 +499,7 @@
 		flush_tlb_kernel_range_common(start, end);
 	else fix_range(vma->vm_mm, start, end, 0);
 }
+EXPORT_SYMBOL(flush_tlb_range);
 
 void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
 			unsigned long end)
diff -druN linux-libre-3.1-gnu/arch/um/kernel/trap.c linux-libre-3.2-gnu/arch/um/kernel/trap.c
--- linux-libre-3.1-gnu/arch/um/kernel/trap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/kernel/trap.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/hardirq.h>
+#include <linux/module.h>
 #include <asm/current.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -14,7 +15,6 @@
 #include "kern_util.h"
 #include "os.h"
 #include "skas.h"
-#include "sysdep/sigcontext.h"
 
 /*
  * Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by
@@ -112,6 +112,7 @@
 	pagefault_out_of_memory();
 	return 0;
 }
+EXPORT_SYMBOL(handle_page_fault);
 
 static void show_segv_info(struct uml_pt_regs *regs)
 {
diff -druN linux-libre-3.1-gnu/arch/um/kernel/uaccess.c linux-libre-3.2-gnu/arch/um/kernel/uaccess.c
--- linux-libre-3.1-gnu/arch/um/kernel/uaccess.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/kernel/uaccess.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-/*
- * These are here rather than tt/uaccess.c because skas mode needs them in
- * order to do SIGBUS recovery when a tmpfs mount runs out of room.
- */
-
-#include <linux/string.h>
-#include "os.h"
-
-static void __do_copy(void *to, const void *from, int n)
-{
-	memcpy(to, from, n);
-}
-
-
-int __do_copy_to_user(void *to, const void *from, int n,
-		      void **fault_addr, jmp_buf **fault_catcher)
-{
-	unsigned long fault;
-	int faulted;
-
-	fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
-			       __do_copy, &faulted);
-	if (!faulted)
-		return 0;
-	else
-		return n - (fault - (unsigned long) to);
-}
diff -druN linux-libre-3.1-gnu/arch/um/kernel/um_arch.c linux-libre-3.2-gnu/arch/um/kernel/um_arch.c
--- linux-libre-3.1-gnu/arch/um/kernel/um_arch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/kernel/um_arch.c	2012-01-04 18:55:44.000000000 -0500
@@ -102,6 +102,8 @@
 
 /* Set in linux_main */
 unsigned long uml_physmem;
+EXPORT_SYMBOL(uml_physmem);
+
 unsigned long uml_reserved; /* Also modified in mem_init */
 unsigned long start_vm;
 unsigned long end_vm;
diff -druN linux-libre-3.1-gnu/arch/um/Makefile linux-libre-3.2-gnu/arch/um/Makefile
--- linux-libre-3.1-gnu/arch/um/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -20,15 +20,27 @@
 
 MODE_INCLUDE	+= -I$(srctree)/$(ARCH_DIR)/include/shared/skas
 
+HEADER_ARCH 	:= $(SUBARCH)
+
+# Additional ARCH settings for x86
+ifeq ($(SUBARCH),i386)
+        HEADER_ARCH := x86
+endif
+ifeq ($(SUBARCH),x86_64)
+        HEADER_ARCH := x86
+endif
+
+HOST_DIR := arch/$(HEADER_ARCH)
+
 include $(srctree)/$(ARCH_DIR)/Makefile-skas
+include $(srctree)/$(HOST_DIR)/Makefile.um
+
+core-y += $(HOST_DIR)/um/
 
 SHARED_HEADERS	:= $(ARCH_DIR)/include/shared
 ARCH_INCLUDE	:= -I$(srctree)/$(SHARED_HEADERS)
-ARCH_INCLUDE	+= -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)/shared
-ifneq ($(KBUILD_SRC),)
-ARCH_INCLUDE	+= -I$(SHARED_HEADERS)
-endif
-KBUILD_CPPFLAGS += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)
+ARCH_INCLUDE	+= -I$(srctree)/$(HOST_DIR)/um/shared
+KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/um
 
 # -Dvmap=kernel_vmap prevents anything from referencing the libpcap.o symbol so
 # named - it's a common symbol in libpcap, so we get a binary which crashes.
@@ -47,14 +59,12 @@
 
 USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\
 	$(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \
-	$(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64
-
-include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
+	$(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64 -idirafter include
 
 #This will adjust *FLAGS accordingly to the platform.
 include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS)
 
-KBUILD_CPPFLAGS += -I$(srctree)/arch/$(HEADER_ARCH)/include
+KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/include
 
 # -Derrno=kernel_errno - This turns all kernel references to errno into
 # kernel_errno to separate them from the libc errno.  This allows -fno-common
@@ -84,10 +94,9 @@
   echo '		   find in the kernel root.'
 endef
 
-KBUILD_KCONFIG := arch/um/Kconfig.$(HEADER_ARCH)
+KBUILD_KCONFIG := $(HOST_DIR)/um/Kconfig
 
-archprepare: $(SHARED_HEADERS)/user_constants.h
-archprepare: $(SHARED_HEADERS)/kern_constants.h
+archprepare: include/generated/user_constants.h
 
 LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
 LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib
@@ -118,9 +127,7 @@
 
 # When cleaning we don't include .config, so we don't include
 # TT or skas makefiles and don't clean skas_ptregs.h.
-CLEAN_FILES += linux x.i gmon.out \
-	$(SHARED_HEADERS)/user_constants.h \
-	$(SHARED_HEADERS)/kern_constants.h
+CLEAN_FILES += linux x.i gmon.out
 
 archclean:
 	@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
@@ -128,8 +135,8 @@
 
 # Generated files
 
-$(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s: FORCE
-	$(Q)$(MAKE) $(build)=$(ARCH_DIR)/sys-$(SUBARCH) $@
+$(HOST_DIR)/um/user-offsets.s: FORCE
+	$(Q)$(MAKE) $(build)=$(HOST_DIR)/um $@
 
 define filechk_gen-asm-offsets
         (set -e; \
@@ -144,11 +151,7 @@
          echo ""; )
 endef
 
-$(SHARED_HEADERS)/user_constants.h: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s
+include/generated/user_constants.h: $(HOST_DIR)/um/user-offsets.s
 	$(call filechk,gen-asm-offsets)
 
-$(SHARED_HEADERS)/kern_constants.h:
-	$(Q)mkdir -p $(dir $@)
-	$(Q)echo '#include "../../../../include/generated/asm-offsets.h"' >$@
-
-export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS HEADER_ARCH DEV_NULL_PATH
+export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS DEV_NULL_PATH
diff -druN linux-libre-3.1-gnu/arch/um/Makefile-i386 linux-libre-3.2-gnu/arch/um/Makefile-i386
--- linux-libre-3.1-gnu/arch/um/Makefile-i386	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/Makefile-i386	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-core-y += arch/um/sys-i386/ arch/x86/crypto/
-
-TOP_ADDR := $(CONFIG_TOP_ADDR)
-
-START := 0x8048000
-
-LDFLAGS			+= -m elf_i386
-ELF_ARCH		:= $(SUBARCH)
-ELF_FORMAT 		:= elf32-$(SUBARCH)
-OBJCOPYFLAGS  		:= -O binary -R .note -R .comment -S
-HEADER_ARCH		:= x86
-CHECKFLAGS	+= -D__i386__
-
-ifeq ("$(origin SUBARCH)", "command line")
-ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)")
-KBUILD_CFLAGS		+= $(call cc-option,-m32)
-KBUILD_AFLAGS		+= $(call cc-option,-m32)
-LINK-y			+= $(call cc-option,-m32)
-UML_OBJCOPYFLAGS	+= -F $(ELF_FORMAT)
-
-export LDFLAGS HOSTCFLAGS HOSTLDFLAGS UML_OBJCOPYFLAGS
-endif
-endif
-
-# First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y.
-include $(srctree)/arch/x86/Makefile_32.cpu
-
-# prevent gcc from keeping the stack 16 byte aligned. Taken from i386.
-cflags-y += $(call cc-option,-mpreferred-stack-boundary=2)
-
-# Prevent sprintf in nfsd from being converted to strcpy and resulting in
-# an unresolved reference.
-cflags-y += -ffreestanding
-
-# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
-# a lot more stack due to the lack of sharing of stacklots.  Also, gcc
-# 4.3.0 needs -funit-at-a-time for extern inline functions.
-KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \
-			echo $(call cc-option,-fno-unit-at-a-time); \
-			else echo $(call cc-option,-funit-at-a-time); fi ;)
-
-KBUILD_CFLAGS += $(cflags-y)
diff -druN linux-libre-3.1-gnu/arch/um/Makefile-x86_64 linux-libre-3.2-gnu/arch/um/Makefile-x86_64
--- linux-libre-3.1-gnu/arch/um/Makefile-x86_64	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/Makefile-x86_64	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-# Copyright 2003 - 2004 Pathscale, Inc
-# Released under the GPL
-
-core-y += arch/um/sys-x86_64/ arch/x86/crypto/
-START := 0x60000000
-
-_extra_flags_ = -fno-builtin -m64
-
-KBUILD_CFLAGS += $(_extra_flags_)
-
-CHECKFLAGS  += -m64 -D__x86_64__
-KBUILD_AFLAGS += -m64
-LDFLAGS += -m elf_x86_64
-KBUILD_CPPFLAGS += -m64
-
-ELF_ARCH := i386:x86-64
-ELF_FORMAT := elf64-x86-64
-HEADER_ARCH := x86
-
-# Not on all 64-bit distros /lib is a symlink to /lib64. PLD is an example.
-
-LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64
-LINK-y += -m64
-
-# Do unit-at-a-time unconditionally on x86_64, following the host
-KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time)
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/aio.c linux-libre-3.2-gnu/arch/um/os-Linux/aio.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/aio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/aio.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,10 +11,8 @@
 #include <asm/unistd.h>
 #include "aio.h"
 #include "init.h"
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
-#include "user.h"
 
 struct aio_thread_req {
 	enum aio_type type;
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/drivers/ethertap_user.c linux-libre-3.2-gnu/arch/um/os-Linux/drivers/ethertap_user.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/drivers/ethertap_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/drivers/ethertap_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,11 +13,9 @@
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include "etap.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "net_user.h"
 #include "um_malloc.h"
-#include "user.h"
 
 #define MAX_PACKET ETH_MAX_PACKET
 
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/drivers/tuntap_user.c linux-libre-3.2-gnu/arch/um/os-Linux/drivers/tuntap_user.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/drivers/tuntap_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/drivers/tuntap_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,11 +13,9 @@
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include <sys/uio.h>
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
 #include "tuntap.h"
-#include "user.h"
 
 static int tuntap_user_init(void *data, void *dev)
 {
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/elf_aux.c linux-libre-3.2-gnu/arch/um/os-Linux/elf_aux.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/elf_aux.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/elf_aux.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,6 @@
 #include "init.h"
 #include "elf_user.h"
 #include "mem_user.h"
-#include <kern_constants.h>
 
 typedef Elf32_auxv_t elf_auxv_t;
 
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/file.c linux-libre-3.2-gnu/arch/um/os-Linux/file.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/file.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/file.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,9 +13,7 @@
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/un.h>
-#include "kern_constants.h"
 #include "os.h"
-#include "user.h"
 
 static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
 {
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/helper.c linux-libre-3.2-gnu/arch/um/os-Linux/helper.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/helper.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/helper.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,11 +10,9 @@
 #include <linux/limits.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 struct helper_data {
 	void (*pre_exec)(void*);
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/internal.h linux-libre-3.2-gnu/arch/um/os-Linux/internal.h
--- linux-libre-3.1-gnu/arch/um/os-Linux/internal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/um/os-Linux/internal.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+void alarm_handler(int, mcontext_t *);
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/irq.c linux-libre-3.2-gnu/arch/um/os-Linux/irq.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,11 +9,8 @@
 #include <signal.h>
 #include <string.h>
 #include "irq_user.h"
-#include "kern_constants.h"
 #include "os.h"
-#include "process.h"
 #include "um_malloc.h"
-#include "user.h"
 
 /*
  * Locked by irq_lock in arch/um/kernel/irq.c.  Changed by os_create_pollfd
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/main.c linux-libre-3.2-gnu/arch/um/os-Linux/main.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/main.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,7 +12,6 @@
 #include <sys/resource.h>
 #include "as-layout.h"
 #include "init.h"
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
 #include "um_malloc.h"
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/Makefile linux-libre-3.2-gnu/arch/um/os-Linux/Makefile
--- linux-libre-3.1-gnu/arch/um/os-Linux/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,14 +4,14 @@
 #
 
 obj-y = aio.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
-	registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \
-	umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/
+	registers.o sigio.o signal.o start_up.o time.o tty.o \
+	umid.o user_syms.o util.o drivers/ skas/
 
 obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o
 
 USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \
 	main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \
-	tty.o tls.o uaccess.o umid.o util.o
+	tty.o umid.o util.o
 
 CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
 
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/mem.c linux-libre-3.2-gnu/arch/um/os-Linux/mem.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/mem.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,9 +14,7 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include "init.h"
-#include "kern_constants.h"
 #include "os.h"
-#include "user.h"
 
 /* Modified by which_tmpdir, which is called during early boot */
 static char *default_tmpdir = "/tmp";
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/process.c linux-libre-3.2-gnu/arch/um/os-Linux/process.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,12 +13,9 @@
 #include <sys/wait.h>
 #include <asm/unistd.h>
 #include "init.h"
-#include "kern_constants.h"
 #include "longjmp.h"
 #include "os.h"
-#include "process.h"
 #include "skas_ptrace.h"
-#include "user.h"
 
 #define ARBITRARY_ADDR -1
 #define FAILURE_PID    -1
@@ -237,21 +234,13 @@
 
 void init_new_thread_signals(void)
 {
-	set_handler(SIGSEGV, (__sighandler_t) sig_handler, SA_ONSTACK,
-		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
-	set_handler(SIGTRAP, (__sighandler_t) sig_handler, SA_ONSTACK,
-		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
-	set_handler(SIGFPE, (__sighandler_t) sig_handler, SA_ONSTACK,
-		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
-	set_handler(SIGILL, (__sighandler_t) sig_handler, SA_ONSTACK,
-		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
-	set_handler(SIGBUS, (__sighandler_t) sig_handler, SA_ONSTACK,
-		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
+	set_handler(SIGSEGV);
+	set_handler(SIGTRAP);
+	set_handler(SIGFPE);
+	set_handler(SIGILL);
+	set_handler(SIGBUS);
 	signal(SIGHUP, SIG_IGN);
-
-	set_handler(SIGIO, (__sighandler_t) sig_handler,
-		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM,
-		    SIGVTALRM, -1);
+	set_handler(SIGIO);
 	signal(SIGWINCH, SIG_IGN);
 	signal(SIGTERM, SIG_DFL);
 }
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/sigio.c linux-libre-3.2-gnu/arch/um/os-Linux/sigio.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/sigio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/sigio.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,14 +11,11 @@
 #include <sched.h>
 #include <signal.h>
 #include <string.h>
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "init.h"
 #include "os.h"
-#include "process.h"
 #include "sigio.h"
 #include "um_malloc.h"
-#include "user.h"
 
 /*
  * Protected by sigio_lock(), also used by sigio_cleanup, which is an
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/signal.c linux-libre-3.2-gnu/arch/um/os-Linux/signal.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/signal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/signal.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,13 +12,7 @@
 #include "as-layout.h"
 #include "kern_util.h"
 #include "os.h"
-#include "process.h"
-#include "sysdep/barrier.h"
-#include "sysdep/sigcontext.h"
-#include "user.h"
-
-/* Copied from linux/compiler-gcc.h since we can't include it directly */
-#define barrier() __asm__ __volatile__("": : :"memory")
+#include "sysdep/mcontext.h"
 
 void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
 	[SIGTRAP]	= relay_signal,
@@ -30,7 +24,7 @@
 	[SIGIO]		= sigio_handler,
 	[SIGVTALRM]	= timer_handler };
 
-static void sig_handler_common(int sig, struct sigcontext *sc)
+static void sig_handler_common(int sig, mcontext_t *mc)
 {
 	struct uml_pt_regs r;
 	int save_errno = errno;
@@ -38,8 +32,8 @@
 	r.is_user = 0;
 	if (sig == SIGSEGV) {
 		/* For segfaults, we want the data from the sigcontext. */
-		copy_sc(&r, sc);
-		GET_FAULTINFO_FROM_SC(r.faultinfo, sc);
+		get_regs_from_mc(&r, mc);
+		GET_FAULTINFO_FROM_MC(r.faultinfo, mc);
 	}
 
 	/* enable signals if sig isn't IRQ signal */
@@ -66,7 +60,7 @@
 static int signals_enabled;
 static unsigned int signals_pending;
 
-void sig_handler(int sig, struct sigcontext *sc)
+void sig_handler(int sig, mcontext_t *mc)
 {
 	int enabled;
 
@@ -78,23 +72,23 @@
 
 	block_signals();
 
-	sig_handler_common(sig, sc);
+	sig_handler_common(sig, mc);
 
 	set_signals(enabled);
 }
 
-static void real_alarm_handler(struct sigcontext *sc)
+static void real_alarm_handler(mcontext_t *mc)
 {
 	struct uml_pt_regs regs;
 
-	if (sc != NULL)
-		copy_sc(&regs, sc);
+	if (mc != NULL)
+		get_regs_from_mc(&regs, mc);
 	regs.is_user = 0;
 	unblock_signals();
 	timer_handler(SIGVTALRM, &regs);
 }
 
-void alarm_handler(int sig, struct sigcontext *sc)
+void alarm_handler(int sig, mcontext_t *mc)
 {
 	int enabled;
 
@@ -106,14 +100,13 @@
 
 	block_signals();
 
-	real_alarm_handler(sc);
+	real_alarm_handler(mc);
 	set_signals(enabled);
 }
 
 void timer_init(void)
 {
-	set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
-		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1);
+	set_handler(SIGVTALRM);
 }
 
 void set_sigstack(void *sig_stack, int size)
@@ -126,10 +119,23 @@
 		panic("enabling signal stack failed, errno = %d\n", errno);
 }
 
-static void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
+static void (*handlers[_NSIG])(int sig, mcontext_t *mc) = {
+	[SIGSEGV] = sig_handler,
+	[SIGBUS] = sig_handler,
+	[SIGILL] = sig_handler,
+	[SIGFPE] = sig_handler,
+	[SIGTRAP] = sig_handler,
 
-void handle_signal(int sig, struct sigcontext *sc)
+	[SIGIO] = sig_handler,
+	[SIGWINCH] = sig_handler,
+	[SIGVTALRM] = alarm_handler
+};
+
+
+static void hard_handler(int sig, siginfo_t *info, void *p)
 {
+	struct ucontext *uc = p;
+	mcontext_t *mc = &uc->uc_mcontext;
 	unsigned long pending = 1UL << sig;
 
 	do {
@@ -155,7 +161,7 @@
 		while ((sig = ffs(pending)) != 0){
 			sig--;
 			pending &= ~(1 << sig);
-			(*handlers[sig])(sig, sc);
+			(*handlers[sig])(sig, mc);
 		}
 
 		/*
@@ -169,28 +175,26 @@
 	} while (pending);
 }
 
-extern void hard_handler(int sig);
-
-void set_handler(int sig, void (*handler)(int), int flags, ...)
+void set_handler(int sig)
 {
 	struct sigaction action;
-	va_list ap;
+	int flags = SA_SIGINFO | SA_ONSTACK;
 	sigset_t sig_mask;
-	int mask;
 
-	handlers[sig] = (void (*)(int, struct sigcontext *)) handler;
-	action.sa_handler = hard_handler;
+	action.sa_sigaction = hard_handler;
 
+	/* block irq ones */
 	sigemptyset(&action.sa_mask);
-
-	va_start(ap, flags);
-	while ((mask = va_arg(ap, int)) != -1)
-		sigaddset(&action.sa_mask, mask);
-	va_end(ap);
+	sigaddset(&action.sa_mask, SIGVTALRM);
+	sigaddset(&action.sa_mask, SIGIO);
+	sigaddset(&action.sa_mask, SIGWINCH);
 
 	if (sig == SIGSEGV)
 		flags |= SA_NODEFER;
 
+	if (sigismember(&action.sa_mask, sig))
+		flags |= SA_RESTART; /* if it's an irq signal */
+
 	action.sa_flags = flags;
 	action.sa_restorer = NULL;
 	if (sigaction(sig, &action, NULL) < 0)
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/skas/mem.c linux-libre-3.2-gnu/arch/um/os-Linux/skas/mem.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/skas/mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/skas/mem.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@
 #include <string.h>
 #include <sys/mman.h>
 #include "init.h"
-#include "kern_constants.h"
 #include "as-layout.h"
 #include "mm_id.h"
 #include "os.h"
@@ -17,7 +16,6 @@
 #include "ptrace_user.h"
 #include "registers.h"
 #include "skas.h"
-#include "user.h"
 #include "sysdep/ptrace.h"
 #include "sysdep/stub.h"
 
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/skas/process.c linux-libre-3.2-gnu/arch/um/os-Linux/skas/process.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/skas/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/skas/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,31 +9,23 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/mman.h>
-#include <sys/ptrace.h>
 #include <sys/wait.h>
 #include <asm/unistd.h>
 #include "as-layout.h"
-#include "chan_user.h"
-#include "kern_constants.h"
+#include "init.h"
 #include "kern_util.h"
 #include "mem.h"
 #include "os.h"
-#include "process.h"
 #include "proc_mm.h"
 #include "ptrace_user.h"
 #include "registers.h"
 #include "skas.h"
 #include "skas_ptrace.h"
-#include "user.h"
 #include "sysdep/stub.h"
 
 int is_skas_winch(int pid, int fd, void *data)
 {
-	if (pid != getpgrp())
-		return 0;
-
-	register_winch_irq(-1, fd, -1, data, 0);
-	return 1;
+	return pid == getpgrp();
 }
 
 static int ptrace_dump_regs(int pid)
@@ -169,7 +161,7 @@
 
 	if (!local_using_sysemu)
 	{
-		err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
+		err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
 			     __NR_getpid);
 		if (err < 0) {
 			printk(UM_KERN_ERR "handle_trap - nullifying syscall "
@@ -257,8 +249,8 @@
 
 		set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);
 		sigemptyset(&sa.sa_mask);
-		sa.sa_flags = SA_ONSTACK | SA_NODEFER;
-		sa.sa_handler = (void *) v;
+		sa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO;
+		sa.sa_sigaction = (void *) v;
 		sa.sa_restorer = NULL;
 		if (sigaction(SIGSEGV, &sa, NULL) < 0) {
 			printk(UM_KERN_ERR "userspace_tramp - setting SIGSEGV "
@@ -661,8 +653,7 @@
 {
 	int n;
 
-	set_handler(SIGWINCH, (__sighandler_t) sig_handler,
-		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGVTALRM, -1);
+	set_handler(SIGWINCH);
 
 	/*
 	 * Can't use UML_SETJMP or UML_LONGJMP here because they save
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/start_up.c linux-libre-3.2-gnu/arch/um/os-Linux/start_up.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/start_up.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/start_up.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,12 +13,10 @@
 #include <signal.h>
 #include <string.h>
 #include <sys/mman.h>
-#include <sys/ptrace.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <asm/unistd.h>
 #include "init.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "mem_user.h"
 #include "ptrace_user.h"
@@ -225,7 +223,7 @@
 		goto fail;
 	}
 
-	n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid());
+	n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, os_getpid());
 	if (n < 0) {
 		non_fatal("check_sysemu : failed to modify system call "
 			  "return");
@@ -261,7 +259,7 @@
 					  "doesn't singlestep");
 				goto fail;
 			}
-			n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
+			n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET,
 				   os_getpid());
 			if (n < 0)
 				fatal_perror("check_sysemu : failed to modify "
@@ -317,10 +315,10 @@
 			fatal("check_ptrace : expected (SIGTRAP|0x80), "
 			       "got status = %d", status);
 
-		syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
+		syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET,
 				 0);
 		if (syscall == __NR_getpid) {
-			n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
+			n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
 				   __NR_getppid);
 			if (n < 0)
 				fatal_perror("check_ptrace : failed to modify "
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/sys-i386/Makefile linux-libre-3.2-gnu/arch/um/os-Linux/sys-i386/Makefile
--- linux-libre-3.1-gnu/arch/um/os-Linux/sys-i386/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/sys-i386/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#
-# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
-# Licensed under the GPL
-#
-
-obj-y = registers.o signal.o task_size.o tls.o
-
-USER_OBJS := $(obj-y)
-
-include arch/um/scripts/Makefile.rules
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/sys-i386/registers.c linux-libre-3.2-gnu/arch/um/os-Linux/sys-i386/registers.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/sys-i386/registers.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/sys-i386/registers.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2004 PathScale, Inc
- * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <errno.h>
-#include <sys/ptrace.h>
-#include <sys/user.h>
-#include "kern_constants.h"
-#include "longjmp.h"
-#include "user.h"
-#include "sysdep/ptrace_user.h"
-
-int save_fp_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-int restore_fp_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-int save_fpx_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-int restore_fpx_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-unsigned long get_thread_reg(int reg, jmp_buf *buf)
-{
-	switch (reg) {
-	case EIP:
-		return buf[0]->__eip;
-	case UESP:
-		return buf[0]->__esp;
-	case EBP:
-		return buf[0]->__ebp;
-	default:
-		printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
-		       reg);
-		return 0;
-	}
-}
-
-int have_fpx_regs = 1;
-
-int get_fp_registers(int pid, unsigned long *regs)
-{
-	if (have_fpx_regs)
-		return save_fpx_registers(pid, regs);
-	else
-		return save_fp_registers(pid, regs);
-}
-
-int put_fp_registers(int pid, unsigned long *regs)
-{
-	if (have_fpx_regs)
-		return restore_fpx_registers(pid, regs);
-	else
-		return restore_fp_registers(pid, regs);
-}
-
-void arch_init_registers(int pid)
-{
-	struct user_fpxregs_struct fpx_regs;
-	int err;
-
-	err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs);
-	if (!err)
-		return;
-
-	if (errno != EIO)
-		panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
-		      errno);
-
-	have_fpx_regs = 0;
-}
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/sys-i386/signal.c linux-libre-3.2-gnu/arch/um/os-Linux/sys-i386/signal.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/sys-i386/signal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/sys-i386/signal.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-/*
- * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-
-extern void handle_signal(int sig, struct sigcontext *sc);
-
-void hard_handler(int sig)
-{
-	handle_signal(sig, (struct sigcontext *) (&sig + 1));
-}
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/sys-i386/task_size.c linux-libre-3.2-gnu/arch/um/os-Linux/sys-i386/task_size.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/sys-i386/task_size.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/sys-i386/task_size.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,139 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <sys/mman.h>
-#include "longjmp.h"
-#include "kern_constants.h"
-
-static jmp_buf buf;
-
-static void segfault(int sig)
-{
-	longjmp(buf, 1);
-}
-
-static int page_ok(unsigned long page)
-{
-	unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT);
-	unsigned long n = ~0UL;
-	void *mapped = NULL;
-	int ok = 0;
-
-	/*
-	 * First see if the page is readable.  If it is, it may still
-	 * be a VDSO, so we go on to see if it's writable.  If not
-	 * then try mapping memory there.  If that fails, then we're
-	 * still in the kernel area.  As a sanity check, we'll fail if
-	 * the mmap succeeds, but gives us an address different from
-	 * what we wanted.
-	 */
-	if (setjmp(buf) == 0)
-		n = *address;
-	else {
-		mapped = mmap(address, UM_KERN_PAGE_SIZE,
-			      PROT_READ | PROT_WRITE,
-			      MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-		if (mapped == MAP_FAILED)
-			return 0;
-		if (mapped != address)
-			goto out;
-	}
-
-	/*
-	 * Now, is it writeable?  If so, then we're in user address
-	 * space.  If not, then try mprotecting it and try the write
-	 * again.
-	 */
-	if (setjmp(buf) == 0) {
-		*address = n;
-		ok = 1;
-		goto out;
-	} else if (mprotect(address, UM_KERN_PAGE_SIZE,
-			    PROT_READ | PROT_WRITE) != 0)
-		goto out;
-
-	if (setjmp(buf) == 0) {
-		*address = n;
-		ok = 1;
-	}
-
- out:
-	if (mapped != NULL)
-		munmap(mapped, UM_KERN_PAGE_SIZE);
-	return ok;
-}
-
-unsigned long os_get_top_address(void)
-{
-	struct sigaction sa, old;
-	unsigned long bottom = 0;
-	/*
-	 * A 32-bit UML on a 64-bit host gets confused about the VDSO at
-	 * 0xffffe000.  It is mapped, is readable, can be reprotected writeable
-	 * and written.  However, exec discovers later that it can't be
-	 * unmapped.  So, just set the highest address to be checked to just
-	 * below it.  This might waste some address space on 4G/4G 32-bit
-	 * hosts, but shouldn't hurt otherwise.
-	 */
-	unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT;
-	unsigned long test, original;
-
-	printf("Locating the bottom of the address space ... ");
-	fflush(stdout);
-
-	/*
-	 * We're going to be longjmping out of the signal handler, so
-	 * SA_DEFER needs to be set.
-	 */
-	sa.sa_handler = segfault;
-	sigemptyset(&sa.sa_mask);
-	sa.sa_flags = SA_NODEFER;
-	if (sigaction(SIGSEGV, &sa, &old)) {
-		perror("os_get_top_address");
-		exit(1);
-	}
-
-	/* Manually scan the address space, bottom-up, until we find
-	 * the first valid page (or run out of them).
-	 */
-	for (bottom = 0; bottom < top; bottom++) {
-		if (page_ok(bottom))
-			break;
-	}
-
-	/* If we've got this far, we ran out of pages. */
-	if (bottom == top) {
-		fprintf(stderr, "Unable to determine bottom of address "
-			"space.\n");
-		exit(1);
-	}
-
-	printf("0x%x\n", bottom << UM_KERN_PAGE_SHIFT);
-	printf("Locating the top of the address space ... ");
-	fflush(stdout);
-
-	original = bottom;
-
-	/* This could happen with a 4G/4G split */
-	if (page_ok(top))
-		goto out;
-
-	do {
-		test = bottom + (top - bottom) / 2;
-		if (page_ok(test))
-			bottom = test;
-		else
-			top = test;
-	} while (top - bottom > 1);
-
-out:
-	/* Restore the old SIGSEGV handling */
-	if (sigaction(SIGSEGV, &old, NULL)) {
-		perror("os_get_top_address");
-		exit(1);
-	}
-	top <<= UM_KERN_PAGE_SHIFT;
-	printf("0x%x\n", top);
-
-	return top;
-}
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/sys-i386/tls.c linux-libre-3.2-gnu/arch/um/os-Linux/sys-i386/tls.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/sys-i386/tls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/sys-i386/tls.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-#include <errno.h>
-#include <linux/unistd.h>
-
-#include <sys/syscall.h>
-#include <unistd.h>
-
-#include "sysdep/tls.h"
-#include "user.h"
-
-/* Checks whether host supports TLS, and sets *tls_min according to the value
- * valid on the host.
- * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */
-void check_host_supports_tls(int *supports_tls, int *tls_min) {
-	/* Values for x86 and x86_64.*/
-	int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64};
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(val); i++) {
-		user_desc_t info;
-		info.entry_number = val[i];
-
-		if (syscall(__NR_get_thread_area, &info) == 0) {
-			*tls_min = val[i];
-			*supports_tls = 1;
-			return;
-		} else {
-			if (errno == EINVAL)
-				continue;
-			else if (errno == ENOSYS)
-				*supports_tls = 0;
-				return;
-		}
-	}
-
-	*supports_tls = 0;
-}
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/sys-x86_64/Makefile linux-libre-3.2-gnu/arch/um/os-Linux/sys-x86_64/Makefile
--- linux-libre-3.1-gnu/arch/um/os-Linux/sys-x86_64/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/sys-x86_64/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#
-# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
-# Licensed under the GPL
-#
-
-obj-y = registers.o prctl.o signal.o task_size.o
-
-USER_OBJS := $(obj-y)
-
-include arch/um/scripts/Makefile.rules
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/sys-x86_64/prctl.c linux-libre-3.2-gnu/arch/um/os-Linux/sys-x86_64/prctl.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/sys-x86_64/prctl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/sys-x86_64/prctl.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-/*
- * Copyright (C) 2007 Jeff Dike (jdike@{addtoit.com,linux.intel.com})
- * Licensed under the GPL
- */
-
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
-
-int os_arch_prctl(int pid, int code, unsigned long *addr)
-{
-        return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) addr, code);
-}
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/sys-x86_64/registers.c linux-libre-3.2-gnu/arch/um/os-Linux/sys-x86_64/registers.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/sys-x86_64/registers.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/sys-x86_64/registers.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2006 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <errno.h>
-#include <sys/ptrace.h>
-#define __FRAME_OFFSETS
-#include <asm/ptrace.h>
-#include "kern_constants.h"
-#include "longjmp.h"
-#include "user.h"
-
-int save_fp_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-int restore_fp_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-unsigned long get_thread_reg(int reg, jmp_buf *buf)
-{
-	switch (reg) {
-	case RIP:
-		return buf[0]->__rip;
-	case RSP:
-		return buf[0]->__rsp;
-	case RBP:
-		return buf[0]->__rbp;
-	default:
-		printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
-		       reg);
-		return 0;
-	}
-}
-
-int get_fp_registers(int pid, unsigned long *regs)
-{
-	return save_fp_registers(pid, regs);
-}
-
-int put_fp_registers(int pid, unsigned long *regs)
-{
-	return restore_fp_registers(pid, regs);
-}
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/sys-x86_64/signal.c linux-libre-3.2-gnu/arch/um/os-Linux/sys-x86_64/signal.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/sys-x86_64/signal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/sys-x86_64/signal.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-
-extern void handle_signal(int sig, struct sigcontext *sc);
-
-void hard_handler(int sig)
-{
-	struct ucontext *uc;
-	asm("movq %%rdx, %0" : "=r" (uc));
-
-	handle_signal(sig, (struct sigcontext *) &uc->uc_mcontext);
-}
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/sys-x86_64/task_size.c linux-libre-3.2-gnu/arch/um/os-Linux/sys-x86_64/task_size.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/sys-x86_64/task_size.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/sys-x86_64/task_size.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-unsigned long os_get_top_address(unsigned long shift)
-{
-	/* The old value of CONFIG_TOP_ADDR */
-	return 0x7fc0000000;
-}
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/time.c linux-libre-3.2-gnu/arch/um/os-Linux/time.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,11 +8,9 @@
 #include <signal.h>
 #include <time.h>
 #include <sys/time.h>
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
-#include "process.h"
-#include "user.h"
+#include "internal.h"
 
 int set_interval(void)
 {
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/tls.c linux-libre-3.2-gnu/arch/um/os-Linux/tls.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/tls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/tls.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-#include <errno.h>
-#include <sys/ptrace.h>
-#include "sysdep/tls.h"
-
-/* TLS support - we basically rely on the host's one.*/
-
-#ifndef PTRACE_GET_THREAD_AREA
-#define PTRACE_GET_THREAD_AREA 25
-#endif
-
-#ifndef PTRACE_SET_THREAD_AREA
-#define PTRACE_SET_THREAD_AREA 26
-#endif
-
-int os_set_thread_area(user_desc_t *info, int pid)
-{
-	int ret;
-
-	ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number,
-		     (unsigned long) info);
-	if (ret < 0)
-		ret = -errno;
-	return ret;
-}
-
-int os_get_thread_area(user_desc_t *info, int pid)
-{
-	int ret;
-
-	ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number,
-		     (unsigned long) info);
-	if (ret < 0)
-		ret = -errno;
-	return ret;
-}
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/tty.c linux-libre-3.2-gnu/arch/um/os-Linux/tty.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/tty.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/tty.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,10 +7,8 @@
 #include <unistd.h>
 #include <errno.h>
 #include <fcntl.h>
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
-#include "user.h"
 
 struct grantpt_info {
 	int fd;
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/uaccess.c linux-libre-3.2-gnu/arch/um/os-Linux/uaccess.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/uaccess.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/uaccess.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <stddef.h>
-#include "longjmp.h"
-
-unsigned long __do_user_copy(void *to, const void *from, int n,
-			     void **fault_addr, jmp_buf **fault_catcher,
-			     void (*op)(void *to, const void *from,
-					int n), int *faulted_out)
-{
-	unsigned long *faddrp = (unsigned long *) fault_addr, ret;
-
-	jmp_buf jbuf;
-	*fault_catcher = &jbuf;
-	if (UML_SETJMP(&jbuf) == 0) {
-		(*op)(to, from, n);
-		ret = 0;
-		*faulted_out = 0;
-	}
-	else {
-		ret = *faddrp;
-		*faulted_out = 1;
-	}
-	*fault_addr = NULL;
-	*fault_catcher = NULL;
-	return ret;
-}
-
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/umid.c linux-libre-3.2-gnu/arch/um/os-Linux/umid.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/umid.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/umid.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,9 +13,7 @@
 #include <unistd.h>
 #include <sys/stat.h>
 #include "init.h"
-#include "kern_constants.h"
 #include "os.h"
-#include "user.h"
 
 #define UML_DIR "~/.uml/"
 
diff -druN linux-libre-3.1-gnu/arch/um/os-Linux/util.c linux-libre-3.2-gnu/arch/um/os-Linux/util.c
--- linux-libre-3.1-gnu/arch/um/os-Linux/util.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/os-Linux/util.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,9 +13,7 @@
 #include <wait.h>
 #include <sys/mman.h>
 #include <sys/utsname.h>
-#include "kern_constants.h"
 #include "os.h"
-#include "user.h"
 
 void stack_protections(unsigned long address)
 {
diff -druN linux-libre-3.1-gnu/arch/um/scripts/Makefile.rules linux-libre-3.2-gnu/arch/um/scripts/Makefile.rules
--- linux-libre-3.1-gnu/arch/um/scripts/Makefile.rules	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/scripts/Makefile.rules	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
 $(USER_OBJS:.o=.%): \
-	c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(basetarget).o)
+	c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include user.h $(CFLAGS_$(basetarget).o)
 $(USER_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
 	-Dunix -D__unix__ -D__$(SUBARCH)__ $(CF)
 
@@ -25,8 +25,3 @@
 define unprofile
 	$(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
 endef
-
-ifdef subarch-obj-y
-obj-y += subarch.o
-subarch-y = $(addprefix ../../$(HEADER_ARCH)/,$(subarch-obj-y))
-endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/asm/archparam.h linux-libre-3.2-gnu/arch/um/sys-i386/asm/archparam.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/asm/archparam.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/asm/archparam.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_ARCHPARAM_I386_H
-#define __UM_ARCHPARAM_I386_H
-
-#ifdef CONFIG_X86_PAE
-#define LAST_PKMAP 512
-#else
-#define LAST_PKMAP 1024
-#endif
-
-#endif
-
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/asm/elf.h linux-libre-3.2-gnu/arch/um/sys-i386/asm/elf.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/asm/elf.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/asm/elf.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-#ifndef __UM_ELF_I386_H
-#define __UM_ELF_I386_H
-
-#include <asm/user.h>
-#include "skas.h"
-
-#define R_386_NONE	0
-#define R_386_32	1
-#define R_386_PC32	2
-#define R_386_GOT32	3
-#define R_386_PLT32	4
-#define R_386_COPY	5
-#define R_386_GLOB_DAT	6
-#define R_386_JMP_SLOT	7
-#define R_386_RELATIVE	8
-#define R_386_GOTOFF	9
-#define R_386_GOTPC	10
-#define R_386_NUM	11
-
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct user_i387_struct elf_fpregset_t;
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) \
-	(((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
-
-#define ELF_CLASS	ELFCLASS32
-#define ELF_DATA        ELFDATA2LSB
-#define ELF_ARCH        EM_386
-
-#define ELF_PLAT_INIT(regs, load_addr) do { \
-	PT_REGS_EBX(regs) = 0; \
-	PT_REGS_ECX(regs) = 0; \
-	PT_REGS_EDX(regs) = 0; \
-	PT_REGS_ESI(regs) = 0; \
-	PT_REGS_EDI(regs) = 0; \
-	PT_REGS_EBP(regs) = 0; \
-	PT_REGS_EAX(regs) = 0; \
-} while (0)
-
-#define ELF_EXEC_PAGESIZE 4096
-
-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
-
-/* Shamelessly stolen from include/asm-i386/elf.h */
-
-#define ELF_CORE_COPY_REGS(pr_reg, regs) do {	\
-	pr_reg[0] = PT_REGS_EBX(regs);		\
-	pr_reg[1] = PT_REGS_ECX(regs);		\
-	pr_reg[2] = PT_REGS_EDX(regs);		\
-	pr_reg[3] = PT_REGS_ESI(regs);		\
-	pr_reg[4] = PT_REGS_EDI(regs);		\
-	pr_reg[5] = PT_REGS_EBP(regs);		\
-	pr_reg[6] = PT_REGS_EAX(regs);		\
-	pr_reg[7] = PT_REGS_DS(regs);		\
-	pr_reg[8] = PT_REGS_ES(regs);		\
-	/* fake once used fs and gs selectors? */	\
-	pr_reg[9] = PT_REGS_DS(regs);		\
-	pr_reg[10] = PT_REGS_DS(regs);		\
-	pr_reg[11] = PT_REGS_SYSCALL_NR(regs);	\
-	pr_reg[12] = PT_REGS_IP(regs);		\
-	pr_reg[13] = PT_REGS_CS(regs);		\
-	pr_reg[14] = PT_REGS_EFLAGS(regs);	\
-	pr_reg[15] = PT_REGS_SP(regs);		\
-	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);
-
-#define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu)
-
-extern long elf_aux_hwcap;
-#define ELF_HWCAP (elf_aux_hwcap)
-
-extern char * elf_aux_platform;
-#define ELF_PLATFORM (elf_aux_platform)
-
-#define SET_PERSONALITY(ex) do { } while (0)
-
-extern unsigned long vsyscall_ehdr;
-extern unsigned long vsyscall_end;
-extern unsigned long __kernel_vsyscall;
-
-#define VSYSCALL_BASE vsyscall_ehdr
-#define VSYSCALL_END vsyscall_end
-
-/*
- * This is the range that is readable by user mode, and things
- * acting like user mode such as get_user_pages.
- */
-#define FIXADDR_USER_START      VSYSCALL_BASE
-#define FIXADDR_USER_END        VSYSCALL_END
-
-#define __HAVE_ARCH_GATE_AREA 1
-
-/*
- * Architecture-neutral AT_ values in 0-17, leave some room
- * for more of them, start the x86-specific ones at 32.
- */
-#define AT_SYSINFO		32
-#define AT_SYSINFO_EHDR		33
-
-#define ARCH_DLINFO						\
-do {								\
-	if ( vsyscall_ehdr ) {					\
-		NEW_AUX_ENT(AT_SYSINFO,	__kernel_vsyscall);	\
-		NEW_AUX_ENT(AT_SYSINFO_EHDR, vsyscall_ehdr);	\
-	}							\
-} while (0)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/asm/module.h linux-libre-3.2-gnu/arch/um/sys-i386/asm/module.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/asm/module.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/asm/module.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-#ifndef __UM_MODULE_I386_H
-#define __UM_MODULE_I386_H
-
-/* UML is simple */
-struct mod_arch_specific
-{
-};
-
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Ehdr Elf32_Ehdr
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/asm/processor.h linux-libre-3.2-gnu/arch/um/sys-i386/asm/processor.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/asm/processor.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/asm/processor.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_PROCESSOR_I386_H
-#define __UM_PROCESSOR_I386_H
-
-#include "linux/string.h"
-#include <sysdep/host_ldt.h>
-#include "asm/segment.h"
-
-extern int host_has_cmov;
-
-/* include faultinfo structure */
-#include "sysdep/faultinfo.h"
-
-struct uml_tls_struct {
-	struct user_desc tls;
-	unsigned flushed:1;
-	unsigned present:1;
-};
-
-struct arch_thread {
-	struct uml_tls_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
-	unsigned long debugregs[8];
-	int debugregs_seq;
-	struct faultinfo faultinfo;
-};
-
-#define INIT_ARCH_THREAD { \
-	.tls_array  		= { [ 0 ... GDT_ENTRY_TLS_ENTRIES - 1 ] = \
-				    { .present = 0, .flushed = 0 } }, \
-	.debugregs  		= { [ 0 ... 7 ] = 0 }, \
-	.debugregs_seq		= 0, \
-	.faultinfo		= { 0, 0, 0 } \
-}
-
-static inline void arch_flush_thread(struct arch_thread *thread)
-{
-	/* Clear any TLS still hanging */
-	memset(&thread->tls_array, 0, sizeof(thread->tls_array));
-}
-
-static inline void arch_copy_thread(struct arch_thread *from,
-                                    struct arch_thread *to)
-{
-        memcpy(&to->tls_array, &from->tls_array, sizeof(from->tls_array));
-}
-
-#include <asm/user.h>
-
-/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
-static inline void rep_nop(void)
-{
-	__asm__ __volatile__("rep;nop": : :"memory");
-}
-
-#define cpu_relax()	rep_nop()
-
-/*
- * Default implementation of macro that returns current
- * instruction pointer ("program counter"). Stolen
- * from asm-i386/processor.h
- */
-#define current_text_addr() \
-	({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
-
-#define ARCH_IS_STACKGROW(address) \
-       (address + 32 >= UPT_SP(&current->thread.regs.regs))
-
-#define KSTK_EIP(tsk) KSTK_REG(tsk, EIP)
-#define KSTK_ESP(tsk) KSTK_REG(tsk, UESP)
-#define KSTK_EBP(tsk) KSTK_REG(tsk, EBP)
-
-#include "asm/processor-generic.h"
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/asm/ptrace.h linux-libre-3.2-gnu/arch/um/sys-i386/asm/ptrace.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/asm/ptrace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/asm/ptrace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_PTRACE_I386_H
-#define __UM_PTRACE_I386_H
-
-#define HOST_AUDIT_ARCH AUDIT_ARCH_I386
-
-#include "linux/compiler.h"
-#include "asm/ptrace-generic.h"
-
-#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs)
-#define PT_REGS_EBX(r) UPT_EBX(&(r)->regs)
-#define PT_REGS_ECX(r) UPT_ECX(&(r)->regs)
-#define PT_REGS_EDX(r) UPT_EDX(&(r)->regs)
-#define PT_REGS_ESI(r) UPT_ESI(&(r)->regs)
-#define PT_REGS_EDI(r) UPT_EDI(&(r)->regs)
-#define PT_REGS_EBP(r) UPT_EBP(&(r)->regs)
-
-#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
-#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
-#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
-#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
-#define PT_REGS_FS(r) UPT_FS(&(r)->regs)
-#define PT_REGS_GS(r) UPT_GS(&(r)->regs)
-
-#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
-
-#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_EAX(r)
-#define PT_REGS_SYSCALL_RET(r) PT_REGS_EAX(r)
-#define PT_FIX_EXEC_STACK(sp) do ; while(0)
-
-#define profile_pc(regs) PT_REGS_IP(regs)
-
-#define user_mode(r) UPT_IS_USER(&(r)->regs)
-
-/*
- * Forward declaration to avoid including sysdep/tls.h, which causes a
- * circular include, and compilation failures.
- */
-struct user_desc;
-
-extern int ptrace_get_thread_area(struct task_struct *child, int idx,
-                                  struct user_desc __user *user_desc);
-
-extern int ptrace_set_thread_area(struct task_struct *child, int idx,
-                                  struct user_desc __user *user_desc);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/atomic64_cx8_32.S linux-libre-3.2-gnu/arch/um/sys-i386/atomic64_cx8_32.S
--- linux-libre-3.1-gnu/arch/um/sys-i386/atomic64_cx8_32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/atomic64_cx8_32.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,225 +0,0 @@
-/*
- * 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-3.1-gnu/arch/um/sys-i386/bug.c linux-libre-3.2-gnu/arch/um/sys-i386/bug.c
--- linux-libre-3.1-gnu/arch/um/sys-i386/bug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/bug.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL V2
- */
-
-#include <linux/uaccess.h>
-#include <asm/errno.h>
-
-/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
- * that's not relevant in skas mode.
- */
-
-int is_valid_bugaddr(unsigned long eip)
-{
-	unsigned short ud2;
-
-	if (probe_kernel_address((unsigned short __user *)eip, ud2))
-		return 0;
-
-	return ud2 == 0x0b0f;
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/bugs.c linux-libre-3.2-gnu/arch/um/sys-i386/bugs.c
--- linux-libre-3.1-gnu/arch/um/sys-i386/bugs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/bugs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-#include "kern_constants.h"
-#include "kern_util.h"
-#include "longjmp.h"
-#include "task.h"
-#include "user.h"
-#include "sysdep/ptrace.h"
-
-/* Set during early boot */
-static int host_has_cmov = 1;
-static jmp_buf cmov_test_return;
-
-static void cmov_sigill_test_handler(int sig)
-{
-	host_has_cmov = 0;
-	longjmp(cmov_test_return, 1);
-}
-
-void arch_check_bugs(void)
-{
-	struct sigaction old, new;
-
-	printk(UM_KERN_INFO "Checking for host processor cmov support...");
-	new.sa_handler = cmov_sigill_test_handler;
-
-	/* Make sure that SIGILL is enabled after the handler longjmps back */
-	new.sa_flags = SA_NODEFER;
-	sigemptyset(&new.sa_mask);
-	sigaction(SIGILL, &new, &old);
-
-	if (setjmp(cmov_test_return) == 0) {
-		unsigned long foo = 0;
-		__asm__ __volatile__("cmovz %0, %1" : "=r" (foo) : "0" (foo));
-		printk(UM_KERN_CONT "Yes\n");
-	} else
-		printk(UM_KERN_CONT "No\n");
-
-	sigaction(SIGILL, &old, &new);
-}
-
-void arch_examine_signal(int sig, struct uml_pt_regs *regs)
-{
-	unsigned char tmp[2];
-
-	/*
-	 * This is testing for a cmov (0x0f 0x4x) instruction causing a
-	 * SIGILL in init.
-	 */
-	if ((sig != SIGILL) || (TASK_PID(get_current()) != 1))
-		return;
-
-	if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) {
-		printk(UM_KERN_ERR "SIGILL in init, could not read "
-		       "instructions!\n");
-		return;
-	}
-
-	if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
-		return;
-
-	if (host_has_cmov == 0)
-		printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
-		       "processor doesn't implement.  Boot a filesystem "
-		       "compiled for older processors");
-	else if (host_has_cmov == 1)
-		printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
-		       "processor claims to implement");
-	else
-		printk(UM_KERN_ERR "Bad value for host_has_cmov (%d)",
-			host_has_cmov);
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/checksum.S linux-libre-3.2-gnu/arch/um/sys-i386/checksum.S
--- linux-libre-3.1-gnu/arch/um/sys-i386/checksum.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/checksum.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,458 +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>
- *              Pentium Pro/II routines:
- *              Alexander Kjeldaas <astor@guardian.no>
- *              Finn Arne Gangstad <finnag@guardian.no>
- *		Lots of code moved from tcp.c and ip.c; see those files
- *		for more names.
- *
- * Changes:     Ingo Molnar, converted csum_partial_copy() to 2.1 exception
- *			     handling.
- *		Andi Kleen,  add zeroing on error
- *                   converted to pure assembler
- *
- *		This program is free software; you can redistribute it and/or
- *		modify it under the terms of the GNU General Public License
- *		as published by the Free Software Foundation; either version
- *		2 of the License, or (at your option) any later version.
- */
-
-#include <asm/errno.h>
-				
-/*
- * computes a partial checksum, e.g. for TCP/UDP fragments
- */
-
-/*	
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
- */
-		
-.text
-.align 4
-.globl csum_partial
-		
-#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
-
-	  /*		
-	   * Experiments with Ethernet and SLIP connections show that buff
-	   * is aligned on either a 2-byte or 4-byte boundary.  We get at
-	   * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
-	   * Fortunately, it is easy to convert 2-byte alignment to 4-byte
-	   * alignment for the unrolled loop.
-	   */		
-csum_partial:
-	pushl %esi
-	pushl %ebx
-	movl 20(%esp),%eax	# Function arg: unsigned int sum
-	movl 16(%esp),%ecx	# Function arg: int len
-	movl 12(%esp),%esi	# Function arg: unsigned char *buff
-	testl $2, %esi		# Check alignment.
-	jz 2f			# Jump if alignment is ok.
-	subl $2, %ecx		# Alignment uses up two bytes.
-	jae 1f			# Jump if we had at least two bytes.
-	addl $2, %ecx		# ecx was < 2.  Deal with it.
-	jmp 4f
-1:	movw (%esi), %bx
-	addl $2, %esi
-	addw %bx, %ax
-	adcl $0, %eax
-2:
-	movl %ecx, %edx
-	shrl $5, %ecx
-	jz 2f
-	testl %esi, %esi
-1:	movl (%esi), %ebx
-	adcl %ebx, %eax
-	movl 4(%esi), %ebx
-	adcl %ebx, %eax
-	movl 8(%esi), %ebx
-	adcl %ebx, %eax
-	movl 12(%esi), %ebx
-	adcl %ebx, %eax
-	movl 16(%esi), %ebx
-	adcl %ebx, %eax
-	movl 20(%esi), %ebx
-	adcl %ebx, %eax
-	movl 24(%esi), %ebx
-	adcl %ebx, %eax
-	movl 28(%esi), %ebx
-	adcl %ebx, %eax
-	lea 32(%esi), %esi
-	dec %ecx
-	jne 1b
-	adcl $0, %eax
-2:	movl %edx, %ecx
-	andl $0x1c, %edx
-	je 4f
-	shrl $2, %edx		# This clears CF
-3:	adcl (%esi), %eax
-	lea 4(%esi), %esi
-	dec %edx
-	jne 3b
-	adcl $0, %eax
-4:	andl $3, %ecx
-	jz 7f
-	cmpl $2, %ecx
-	jb 5f
-	movw (%esi),%cx
-	leal 2(%esi),%esi
-	je 6f
-	shll $16,%ecx
-5:	movb (%esi),%cl
-6:	addl %ecx,%eax
-	adcl $0, %eax 
-7:	
-	popl %ebx
-	popl %esi
-	ret
-
-#else
-
-/* Version for PentiumII/PPro */
-
-csum_partial:
-	pushl %esi
-	pushl %ebx
-	movl 20(%esp),%eax	# Function arg: unsigned int sum
-	movl 16(%esp),%ecx	# Function arg: int len
-	movl 12(%esp),%esi	# Function arg:	const unsigned char *buf
-
-	testl $2, %esi         
-	jnz 30f                 
-10:
-	movl %ecx, %edx
-	movl %ecx, %ebx
-	andl $0x7c, %ebx
-	shrl $7, %ecx
-	addl %ebx,%esi
-	shrl $2, %ebx  
-	negl %ebx
-	lea 45f(%ebx,%ebx,2), %ebx
-	testl %esi, %esi
-	jmp *%ebx
-
-	# Handle 2-byte-aligned regions
-20:	addw (%esi), %ax
-	lea 2(%esi), %esi
-	adcl $0, %eax
-	jmp 10b
-
-30:	subl $2, %ecx          
-	ja 20b                 
-	je 32f
-	movzbl (%esi),%ebx	# csumming 1 byte, 2-aligned
-	addl %ebx, %eax
-	adcl $0, %eax
-	jmp 80f
-32:
-	addw (%esi), %ax	# csumming 2 bytes, 2-aligned
-	adcl $0, %eax
-	jmp 80f
-
-40: 
-	addl -128(%esi), %eax
-	adcl -124(%esi), %eax
-	adcl -120(%esi), %eax
-	adcl -116(%esi), %eax   
-	adcl -112(%esi), %eax   
-	adcl -108(%esi), %eax
-	adcl -104(%esi), %eax
-	adcl -100(%esi), %eax
-	adcl -96(%esi), %eax
-	adcl -92(%esi), %eax
-	adcl -88(%esi), %eax
-	adcl -84(%esi), %eax
-	adcl -80(%esi), %eax
-	adcl -76(%esi), %eax
-	adcl -72(%esi), %eax
-	adcl -68(%esi), %eax
-	adcl -64(%esi), %eax     
-	adcl -60(%esi), %eax     
-	adcl -56(%esi), %eax     
-	adcl -52(%esi), %eax   
-	adcl -48(%esi), %eax   
-	adcl -44(%esi), %eax
-	adcl -40(%esi), %eax
-	adcl -36(%esi), %eax
-	adcl -32(%esi), %eax
-	adcl -28(%esi), %eax
-	adcl -24(%esi), %eax
-	adcl -20(%esi), %eax
-	adcl -16(%esi), %eax
-	adcl -12(%esi), %eax
-	adcl -8(%esi), %eax
-	adcl -4(%esi), %eax
-45:
-	lea 128(%esi), %esi
-	adcl $0, %eax
-	dec %ecx
-	jge 40b
-	movl %edx, %ecx
-50:	andl $3, %ecx
-	jz 80f
-
-	# Handle the last 1-3 bytes without jumping
-	notl %ecx		# 1->2, 2->1, 3->0, higher bits are masked
-	movl $0xffffff,%ebx	# by the shll and shrl instructions
-	shll $3,%ecx
-	shrl %cl,%ebx
-	andl -128(%esi),%ebx	# esi is 4-aligned so should be ok
-	addl %ebx,%eax
-	adcl $0,%eax
-80: 
-	popl %ebx
-	popl %esi
-	ret
-				
-#endif
-
-/*
-unsigned int csum_partial_copy_generic (const char *src, char *dst,
-				  int len, int sum, int *src_err_ptr, int *dst_err_ptr)
- */ 
-
-/*
- * Copy from ds while checksumming, otherwise like csum_partial
- *
- * The macros SRC and DST specify the type of access for the instruction.
- * thus we can call a custom exception handler for all access types.
- *
- * FIXME: could someone double-check whether I haven't mixed up some SRC and
- *	  DST definitions? It's damn hard to trigger all cases.  I hope I got
- *	  them all but there's no guarantee.
- */
-
-#define SRC(y...)			\
-	9999: y;			\
-	.section __ex_table, "a";	\
-	.long 9999b, 6001f	;	\
-	.previous
-
-#define DST(y...)			\
-	9999: y;			\
-	.section __ex_table, "a";	\
-	.long 9999b, 6002f	;	\
-	.previous
-
-.align 4
-
-#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
-
-#define ARGBASE 16		
-#define FP		12
-
-csum_partial_copy_generic_i386:
-	subl  $4,%esp	
-	pushl %edi
-	pushl %esi
-	pushl %ebx
-	movl ARGBASE+16(%esp),%eax	# sum
-	movl ARGBASE+12(%esp),%ecx	# len
-	movl ARGBASE+4(%esp),%esi	# src
-	movl ARGBASE+8(%esp),%edi	# dst
-
-	testl $2, %edi			# Check alignment. 
-	jz 2f				# Jump if alignment is ok.
-	subl $2, %ecx			# Alignment uses up two bytes.
-	jae 1f				# Jump if we had at least two bytes.
-	addl $2, %ecx			# ecx was < 2.  Deal with it.
-	jmp 4f
-SRC(1:	movw (%esi), %bx	)
-	addl $2, %esi
-DST(	movw %bx, (%edi)	)
-	addl $2, %edi
-	addw %bx, %ax	
-	adcl $0, %eax
-2:
-	movl %ecx, FP(%esp)
-	shrl $5, %ecx
-	jz 2f
-	testl %esi, %esi
-SRC(1:	movl (%esi), %ebx	)
-SRC(	movl 4(%esi), %edx	)
-	adcl %ebx, %eax
-DST(	movl %ebx, (%edi)	)
-	adcl %edx, %eax
-DST(	movl %edx, 4(%edi)	)
-
-SRC(	movl 8(%esi), %ebx	)
-SRC(	movl 12(%esi), %edx	)
-	adcl %ebx, %eax
-DST(	movl %ebx, 8(%edi)	)
-	adcl %edx, %eax
-DST(	movl %edx, 12(%edi)	)
-
-SRC(	movl 16(%esi), %ebx 	)
-SRC(	movl 20(%esi), %edx	)
-	adcl %ebx, %eax
-DST(	movl %ebx, 16(%edi)	)
-	adcl %edx, %eax
-DST(	movl %edx, 20(%edi)	)
-
-SRC(	movl 24(%esi), %ebx	)
-SRC(	movl 28(%esi), %edx	)
-	adcl %ebx, %eax
-DST(	movl %ebx, 24(%edi)	)
-	adcl %edx, %eax
-DST(	movl %edx, 28(%edi)	)
-
-	lea 32(%esi), %esi
-	lea 32(%edi), %edi
-	dec %ecx
-	jne 1b
-	adcl $0, %eax
-2:	movl FP(%esp), %edx
-	movl %edx, %ecx
-	andl $0x1c, %edx
-	je 4f
-	shrl $2, %edx			# This clears CF
-SRC(3:	movl (%esi), %ebx	)
-	adcl %ebx, %eax
-DST(	movl %ebx, (%edi)	)
-	lea 4(%esi), %esi
-	lea 4(%edi), %edi
-	dec %edx
-	jne 3b
-	adcl $0, %eax
-4:	andl $3, %ecx
-	jz 7f
-	cmpl $2, %ecx
-	jb 5f
-SRC(	movw (%esi), %cx	)
-	leal 2(%esi), %esi
-DST(	movw %cx, (%edi)	)
-	leal 2(%edi), %edi
-	je 6f
-	shll $16,%ecx
-SRC(5:	movb (%esi), %cl	)
-DST(	movb %cl, (%edi)	)
-6:	addl %ecx, %eax
-	adcl $0, %eax
-7:
-5000:
-
-# Exception handler:
-.section .fixup, "ax"							
-
-6001:
-	movl ARGBASE+20(%esp), %ebx	# src_err_ptr
-	movl $-EFAULT, (%ebx)
-
-	# zero the complete destination - computing the rest
-	# is too much work 
-	movl ARGBASE+8(%esp), %edi	# dst
-	movl ARGBASE+12(%esp), %ecx	# len
-	xorl %eax,%eax
-	rep ; stosb
-
-	jmp 5000b
-
-6002:
-	movl ARGBASE+24(%esp), %ebx	# dst_err_ptr
-	movl $-EFAULT,(%ebx)
-	jmp 5000b
-
-.previous
-
-	popl %ebx
-	popl %esi
-	popl %edi
-	popl %ecx			# equivalent to addl $4,%esp
-	ret	
-
-#else
-
-/* Version for PentiumII/PPro */
-
-#define ROUND1(x) \
-	SRC(movl x(%esi), %ebx	)	;	\
-	addl %ebx, %eax			;	\
-	DST(movl %ebx, x(%edi)	)	; 
-
-#define ROUND(x) \
-	SRC(movl x(%esi), %ebx	)	;	\
-	adcl %ebx, %eax			;	\
-	DST(movl %ebx, x(%edi)	)	;
-
-#define ARGBASE 12
-		
-csum_partial_copy_generic_i386:
-	pushl %ebx
-	pushl %edi
-	pushl %esi
-	movl ARGBASE+4(%esp),%esi	#src
-	movl ARGBASE+8(%esp),%edi	#dst	
-	movl ARGBASE+12(%esp),%ecx	#len
-	movl ARGBASE+16(%esp),%eax	#sum
-#	movl %ecx, %edx  
-	movl %ecx, %ebx  
-	movl %esi, %edx
-	shrl $6, %ecx     
-	andl $0x3c, %ebx  
-	negl %ebx
-	subl %ebx, %esi  
-	subl %ebx, %edi  
-	lea  -1(%esi),%edx
-	andl $-32,%edx
-	lea 3f(%ebx,%ebx), %ebx
-	testl %esi, %esi 
-	jmp *%ebx
-1:	addl $64,%esi
-	addl $64,%edi 
-	SRC(movb -32(%edx),%bl)	; SRC(movb (%edx),%bl)
-	ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52)	
-	ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36)	
-	ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20)	
-	ROUND (-16) ROUND(-12) ROUND(-8)  ROUND(-4)	
-3:	adcl $0,%eax
-	addl $64, %edx
-	dec %ecx
-	jge 1b
-4:	movl ARGBASE+12(%esp),%edx	#len
-	andl $3, %edx
-	jz 7f
-	cmpl $2, %edx
-	jb 5f
-SRC(	movw (%esi), %dx         )
-	leal 2(%esi), %esi
-DST(	movw %dx, (%edi)         )
-	leal 2(%edi), %edi
-	je 6f
-	shll $16,%edx
-5:
-SRC(	movb (%esi), %dl         )
-DST(	movb %dl, (%edi)         )
-6:	addl %edx, %eax
-	adcl $0, %eax
-7:
-.section .fixup, "ax"
-6001:	movl	ARGBASE+20(%esp), %ebx	# src_err_ptr	
-	movl $-EFAULT, (%ebx)
-	# zero the complete destination (computing the rest is too much work)
-	movl ARGBASE+8(%esp),%edi	# dst
-	movl ARGBASE+12(%esp),%ecx	# len
-	xorl %eax,%eax
-	rep; stosb
-	jmp 7b
-6002:	movl ARGBASE+24(%esp), %ebx	# dst_err_ptr
-	movl $-EFAULT, (%ebx)
-	jmp  7b			
-.previous				
-
-	popl %esi
-	popl %edi
-	popl %ebx
-	ret
-				
-#undef ROUND
-#undef ROUND1		
-		
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/delay.c linux-libre-3.2-gnu/arch/um/sys-i386/delay.c
--- linux-libre-3.1-gnu/arch/um/sys-i386/delay.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/delay.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
- * Mostly copied from arch/x86/lib/delay.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/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <asm/param.h>
-
-void __delay(unsigned long loops)
-{
-	asm volatile(
-		"test %0,%0\n"
-		"jz 3f\n"
-		"jmp 1f\n"
-
-		".align 16\n"
-		"1: jmp 2f\n"
-
-		".align 16\n"
-		"2: dec %0\n"
-		" jnz 2b\n"
-		"3: dec %0\n"
-
-		: /* we don't need output */
-		: "a" (loops)
-	);
-}
-EXPORT_SYMBOL(__delay);
-
-inline void __const_udelay(unsigned long xloops)
-{
-	int d0;
-
-	xloops *= 4;
-	asm("mull %%edx"
-		: "=d" (xloops), "=&a" (d0)
-		: "1" (xloops), "0"
-		(loops_per_jiffy * (HZ/4)));
-
-	__delay(++xloops);
-}
-EXPORT_SYMBOL(__const_udelay);
-
-void __udelay(unsigned long usecs)
-{
-	__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
-}
-EXPORT_SYMBOL(__udelay);
-
-void __ndelay(unsigned long nsecs)
-{
-	__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
-}
-EXPORT_SYMBOL(__ndelay);
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/elfcore.c linux-libre-3.2-gnu/arch/um/sys-i386/elfcore.c
--- linux-libre-3.1-gnu/arch/um/sys-i386/elfcore.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/elfcore.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-#include <linux/elf.h>
-#include <linux/coredump.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-
-#include <asm/elf.h>
-
-
-Elf32_Half elf_core_extra_phdrs(void)
-{
-	return vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0;
-}
-
-int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
-			       unsigned long limit)
-{
-	if ( vsyscall_ehdr ) {
-		const struct elfhdr *const ehdrp =
-			(struct elfhdr *) vsyscall_ehdr;
-		const struct elf_phdr *const phdrp =
-			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
-		int i;
-		Elf32_Off ofs = 0;
-
-		for (i = 0; i < ehdrp->e_phnum; ++i) {
-			struct elf_phdr phdr = phdrp[i];
-
-			if (phdr.p_type == PT_LOAD) {
-				ofs = phdr.p_offset = offset;
-				offset += phdr.p_filesz;
-			} else {
-				phdr.p_offset += ofs;
-			}
-			phdr.p_paddr = 0; /* match other core phdrs */
-			*size += sizeof(phdr);
-			if (*size > limit
-			    || !dump_write(file, &phdr, sizeof(phdr)))
-				return 0;
-		}
-	}
-	return 1;
-}
-
-int elf_core_write_extra_data(struct file *file, size_t *size,
-			      unsigned long limit)
-{
-	if ( vsyscall_ehdr ) {
-		const struct elfhdr *const ehdrp =
-			(struct elfhdr *) vsyscall_ehdr;
-		const struct elf_phdr *const phdrp =
-			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
-		int i;
-
-		for (i = 0; i < ehdrp->e_phnum; ++i) {
-			if (phdrp[i].p_type == PT_LOAD) {
-				void *addr = (void *) phdrp[i].p_vaddr;
-				size_t filesz = phdrp[i].p_filesz;
-
-				*size += filesz;
-				if (*size > limit
-				    || !dump_write(file, addr, filesz))
-					return 0;
-			}
-		}
-	}
-	return 1;
-}
-
-size_t elf_core_extra_data_size(void)
-{
-	if ( vsyscall_ehdr ) {
-		const struct elfhdr *const ehdrp =
-			(struct elfhdr *)vsyscall_ehdr;
-		const struct elf_phdr *const phdrp =
-			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
-		int i;
-
-		for (i = 0; i < ehdrp->e_phnum; ++i)
-			if (phdrp[i].p_type == PT_LOAD)
-				return (size_t) phdrp[i].p_filesz;
-	}
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/fault.c linux-libre-3.2-gnu/arch/um/sys-i386/fault.c
--- linux-libre-3.1-gnu/arch/um/sys-i386/fault.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/fault.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/* 
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include "sysdep/ptrace.h"
-
-/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
-struct exception_table_entry
-{
-	unsigned long insn;
-	unsigned long fixup;
-};
-
-const struct exception_table_entry *search_exception_tables(unsigned long add);
-
-/* Compare this to arch/i386/mm/extable.c:fixup_exception() */
-int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
-{
-	const struct exception_table_entry *fixup;
-
-	fixup = search_exception_tables(address);
-	if (fixup != 0) {
-		UPT_IP(regs) = fixup->fixup;
-		return 1;
-	}
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/ksyms.c linux-libre-3.2-gnu/arch/um/sys-i386/ksyms.c
--- linux-libre-3.1-gnu/arch/um/sys-i386/ksyms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/ksyms.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-#include "linux/module.h"
-#include "asm/checksum.h"
-
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial);
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/ldt.c linux-libre-3.2-gnu/arch/um/sys-i386/ldt.c
--- linux-libre-3.1-gnu/arch/um/sys-i386/ldt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/ldt.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,502 +0,0 @@
-/*
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <asm/unistd.h>
-#include "os.h"
-#include "proc_mm.h"
-#include "skas.h"
-#include "skas_ptrace.h"
-#include "sysdep/tls.h"
-
-extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
-
-static long write_ldt_entry(struct mm_id *mm_idp, int func,
-		     struct user_desc *desc, void **addr, int done)
-{
-	long res;
-
-	if (proc_mm) {
-		/*
-		 * This is a special handling for the case, that the mm to
-		 * modify isn't current->active_mm.
-		 * If this is called directly by modify_ldt,
-		 *     (current->active_mm->context.skas.u == mm_idp)
-		 * will be true. So no call to __switch_mm(mm_idp) is done.
-		 * If this is called in case of init_new_ldt or PTRACE_LDT,
-		 * mm_idp won't belong to current->active_mm, but child->mm.
-		 * So we need to switch child's mm into our userspace, then
-		 * later switch back.
-		 *
-		 * Note: I'm unsure: should interrupts be disabled here?
-		 */
-		if (!current->active_mm || current->active_mm == &init_mm ||
-		    mm_idp != &current->active_mm->context.id)
-			__switch_mm(mm_idp);
-	}
-
-	if (ptrace_ldt) {
-		struct ptrace_ldt ldt_op = (struct ptrace_ldt) {
-			.func = func,
-			.ptr = desc,
-			.bytecount = sizeof(*desc)};
-		u32 cpu;
-		int pid;
-
-		if (!proc_mm)
-			pid = mm_idp->u.pid;
-		else {
-			cpu = get_cpu();
-			pid = userspace_pid[cpu];
-		}
-
-		res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op);
-
-		if (proc_mm)
-			put_cpu();
-	}
-	else {
-		void *stub_addr;
-		res = syscall_stub_data(mm_idp, (unsigned long *)desc,
-					(sizeof(*desc) + sizeof(long) - 1) &
-					    ~(sizeof(long) - 1),
-					addr, &stub_addr);
-		if (!res) {
-			unsigned long args[] = { func,
-						 (unsigned long)stub_addr,
-						 sizeof(*desc),
-						 0, 0, 0 };
-			res = run_syscall_stub(mm_idp, __NR_modify_ldt, args,
-					       0, addr, done);
-		}
-	}
-
-	if (proc_mm) {
-		/*
-		 * This is the second part of special handling, that makes
-		 * PTRACE_LDT possible to implement.
-		 */
-		if (current->active_mm && current->active_mm != &init_mm &&
-		    mm_idp != &current->active_mm->context.id)
-			__switch_mm(&current->active_mm->context.id);
-	}
-
-	return res;
-}
-
-static long read_ldt_from_host(void __user * ptr, unsigned long bytecount)
-{
-	int res, n;
-	struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) {
-			.func = 0,
-			.bytecount = bytecount,
-			.ptr = kmalloc(bytecount, GFP_KERNEL)};
-	u32 cpu;
-
-	if (ptrace_ldt.ptr == NULL)
-		return -ENOMEM;
-
-	/*
-	 * This is called from sys_modify_ldt only, so userspace_pid gives
-	 * us the right number
-	 */
-
-	cpu = get_cpu();
-	res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt);
-	put_cpu();
-	if (res < 0)
-		goto out;
-
-	n = copy_to_user(ptr, ptrace_ldt.ptr, res);
-	if (n != 0)
-		res = -EFAULT;
-
-  out:
-	kfree(ptrace_ldt.ptr);
-
-	return res;
-}
-
-/*
- * In skas mode, we hold our own ldt data in UML.
- * Thus, the code implementing sys_modify_ldt_skas
- * is very similar to (and mostly stolen from) sys_modify_ldt
- * for arch/i386/kernel/ldt.c
- * The routines copied and modified in part are:
- * - read_ldt
- * - read_default_ldt
- * - write_ldt
- * - sys_modify_ldt_skas
- */
-
-static int read_ldt(void __user * ptr, unsigned long bytecount)
-{
-	int i, err = 0;
-	unsigned long size;
-	uml_ldt_t * ldt = &current->mm->context.ldt;
-
-	if (!ldt->entry_count)
-		goto out;
-	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
-		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
-	err = bytecount;
-
-	if (ptrace_ldt)
-		return read_ldt_from_host(ptr, bytecount);
-
-	mutex_lock(&ldt->lock);
-	if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
-		size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
-		if (size > bytecount)
-			size = bytecount;
-		if (copy_to_user(ptr, ldt->u.entries, size))
-			err = -EFAULT;
-		bytecount -= size;
-		ptr += size;
-	}
-	else {
-		for (i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount;
-		     i++) {
-			size = PAGE_SIZE;
-			if (size > bytecount)
-				size = bytecount;
-			if (copy_to_user(ptr, ldt->u.pages[i], size)) {
-				err = -EFAULT;
-				break;
-			}
-			bytecount -= size;
-			ptr += size;
-		}
-	}
-	mutex_unlock(&ldt->lock);
-
-	if (bytecount == 0 || err == -EFAULT)
-		goto out;
-
-	if (clear_user(ptr, bytecount))
-		err = -EFAULT;
-
-out:
-	return err;
-}
-
-static int read_default_ldt(void __user * ptr, unsigned long bytecount)
-{
-	int err;
-
-	if (bytecount > 5*LDT_ENTRY_SIZE)
-		bytecount = 5*LDT_ENTRY_SIZE;
-
-	err = bytecount;
-	/*
-	 * UML doesn't support lcall7 and lcall27.
-	 * So, we don't really have a default ldt, but emulate
-	 * an empty ldt of common host default ldt size.
-	 */
-	if (clear_user(ptr, bytecount))
-		err = -EFAULT;
-
-	return err;
-}
-
-static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
-{
-	uml_ldt_t * ldt = &current->mm->context.ldt;
-	struct mm_id * mm_idp = &current->mm->context.id;
-	int i, err;
-	struct user_desc ldt_info;
-	struct ldt_entry entry0, *ldt_p;
-	void *addr = NULL;
-
-	err = -EINVAL;
-	if (bytecount != sizeof(ldt_info))
-		goto out;
-	err = -EFAULT;
-	if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
-		goto out;
-
-	err = -EINVAL;
-	if (ldt_info.entry_number >= LDT_ENTRIES)
-		goto out;
-	if (ldt_info.contents == 3) {
-		if (func == 1)
-			goto out;
-		if (ldt_info.seg_not_present == 0)
-			goto out;
-	}
-
-	if (!ptrace_ldt)
-		mutex_lock(&ldt->lock);
-
-	err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
-	if (err)
-		goto out_unlock;
-	else if (ptrace_ldt) {
-		/* With PTRACE_LDT available, this is used as a flag only */
-		ldt->entry_count = 1;
-		goto out;
-	}
-
-	if (ldt_info.entry_number >= ldt->entry_count &&
-	    ldt_info.entry_number >= LDT_DIRECT_ENTRIES) {
-		for (i=ldt->entry_count/LDT_ENTRIES_PER_PAGE;
-		     i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number;
-		     i++) {
-			if (i == 0)
-				memcpy(&entry0, ldt->u.entries,
-				       sizeof(entry0));
-			ldt->u.pages[i] = (struct ldt_entry *)
-				__get_free_page(GFP_KERNEL|__GFP_ZERO);
-			if (!ldt->u.pages[i]) {
-				err = -ENOMEM;
-				/* Undo the change in host */
-				memset(&ldt_info, 0, sizeof(ldt_info));
-				write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1);
-				goto out_unlock;
-			}
-			if (i == 0) {
-				memcpy(ldt->u.pages[0], &entry0,
-				       sizeof(entry0));
-				memcpy(ldt->u.pages[0]+1, ldt->u.entries+1,
-				       sizeof(entry0)*(LDT_DIRECT_ENTRIES-1));
-			}
-			ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE;
-		}
-	}
-	if (ldt->entry_count <= ldt_info.entry_number)
-		ldt->entry_count = ldt_info.entry_number + 1;
-
-	if (ldt->entry_count <= LDT_DIRECT_ENTRIES)
-		ldt_p = ldt->u.entries + ldt_info.entry_number;
-	else
-		ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] +
-			ldt_info.entry_number%LDT_ENTRIES_PER_PAGE;
-
-	if (ldt_info.base_addr == 0 && ldt_info.limit == 0 &&
-	   (func == 1 || LDT_empty(&ldt_info))) {
-		ldt_p->a = 0;
-		ldt_p->b = 0;
-	}
-	else{
-		if (func == 1)
-			ldt_info.useable = 0;
-		ldt_p->a = LDT_entry_a(&ldt_info);
-		ldt_p->b = LDT_entry_b(&ldt_info);
-	}
-	err = 0;
-
-out_unlock:
-	mutex_unlock(&ldt->lock);
-out:
-	return err;
-}
-
-static long do_modify_ldt_skas(int func, void __user *ptr,
-			       unsigned long bytecount)
-{
-	int ret = -ENOSYS;
-
-	switch (func) {
-		case 0:
-			ret = read_ldt(ptr, bytecount);
-			break;
-		case 1:
-		case 0x11:
-			ret = write_ldt(ptr, bytecount, func);
-			break;
-		case 2:
-			ret = read_default_ldt(ptr, bytecount);
-			break;
-	}
-	return ret;
-}
-
-static DEFINE_SPINLOCK(host_ldt_lock);
-static short dummy_list[9] = {0, -1};
-static short * host_ldt_entries = NULL;
-
-static void ldt_get_host_info(void)
-{
-	long ret;
-	struct ldt_entry * ldt;
-	short *tmp;
-	int i, size, k, order;
-
-	spin_lock(&host_ldt_lock);
-
-	if (host_ldt_entries != NULL) {
-		spin_unlock(&host_ldt_lock);
-		return;
-	}
-	host_ldt_entries = dummy_list+1;
-
-	spin_unlock(&host_ldt_lock);
-
-	for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++)
-		;
-
-	ldt = (struct ldt_entry *)
-	      __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
-	if (ldt == NULL) {
-		printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer "
-		       "for host ldt\n");
-		return;
-	}
-
-	ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE);
-	if (ret < 0) {
-		printk(KERN_ERR "ldt_get_host_info: couldn't read host ldt\n");
-		goto out_free;
-	}
-	if (ret == 0) {
-		/* default_ldt is active, simply write an empty entry 0 */
-		host_ldt_entries = dummy_list;
-		goto out_free;
-	}
-
-	for (i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++) {
-		if (ldt[i].a != 0 || ldt[i].b != 0)
-			size++;
-	}
-
-	if (size < ARRAY_SIZE(dummy_list))
-		host_ldt_entries = dummy_list;
-	else {
-		size = (size + 1) * sizeof(dummy_list[0]);
-		tmp = kmalloc(size, GFP_KERNEL);
-		if (tmp == NULL) {
-			printk(KERN_ERR "ldt_get_host_info: couldn't allocate "
-			       "host ldt list\n");
-			goto out_free;
-		}
-		host_ldt_entries = tmp;
-	}
-
-	for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) {
-		if (ldt[i].a != 0 || ldt[i].b != 0)
-			host_ldt_entries[k++] = i;
-	}
-	host_ldt_entries[k] = -1;
-
-out_free:
-	free_pages((unsigned long)ldt, order);
-}
-
-long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
-{
-	struct user_desc desc;
-	short * num_p;
-	int i;
-	long page, err=0;
-	void *addr = NULL;
-	struct proc_mm_op copy;
-
-
-	if (!ptrace_ldt)
-		mutex_init(&new_mm->ldt.lock);
-
-	if (!from_mm) {
-		memset(&desc, 0, sizeof(desc));
-		/*
-		 * We have to initialize a clean ldt.
-		 */
-		if (proc_mm) {
-			/*
-			 * If the new mm was created using proc_mm, host's
-			 * default-ldt currently is assigned, which normally
-			 * contains the call-gates for lcall7 and lcall27.
-			 * To remove these gates, we simply write an empty
-			 * entry as number 0 to the host.
-			 */
-			err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, 1);
-		}
-		else{
-			/*
-			 * Now we try to retrieve info about the ldt, we
-			 * inherited from the host. All ldt-entries found
-			 * will be reset in the following loop
-			 */
-			ldt_get_host_info();
-			for (num_p=host_ldt_entries; *num_p != -1; num_p++) {
-				desc.entry_number = *num_p;
-				err = write_ldt_entry(&new_mm->id, 1, &desc,
-						      &addr, *(num_p + 1) == -1);
-				if (err)
-					break;
-			}
-		}
-		new_mm->ldt.entry_count = 0;
-
-		goto out;
-	}
-
-	if (proc_mm) {
-		/*
-		 * We have a valid from_mm, so we now have to copy the LDT of
-		 * from_mm to new_mm, because using proc_mm an new mm with
-		 * an empty/default LDT was created in new_mm()
-		 */
-		copy = ((struct proc_mm_op) { .op 	= MM_COPY_SEGMENTS,
-					      .u 	=
-					      { .copy_segments =
-							from_mm->id.u.mm_fd } } );
-		i = os_write_file(new_mm->id.u.mm_fd, &copy, sizeof(copy));
-		if (i != sizeof(copy))
-			printk(KERN_ERR "new_mm : /proc/mm copy_segments "
-			       "failed, err = %d\n", -i);
-	}
-
-	if (!ptrace_ldt) {
-		/*
-		 * Our local LDT is used to supply the data for
-		 * modify_ldt(READLDT), if PTRACE_LDT isn't available,
-		 * i.e., we have to use the stub for modify_ldt, which
-		 * can't handle the big read buffer of up to 64kB.
-		 */
-		mutex_lock(&from_mm->ldt.lock);
-		if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES)
-			memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries,
-			       sizeof(new_mm->ldt.u.entries));
-		else {
-			i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
-			while (i-->0) {
-				page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
-				if (!page) {
-					err = -ENOMEM;
-					break;
-				}
-				new_mm->ldt.u.pages[i] =
-					(struct ldt_entry *) page;
-				memcpy(new_mm->ldt.u.pages[i],
-				       from_mm->ldt.u.pages[i], PAGE_SIZE);
-			}
-		}
-		new_mm->ldt.entry_count = from_mm->ldt.entry_count;
-		mutex_unlock(&from_mm->ldt.lock);
-	}
-
-    out:
-	return err;
-}
-
-
-void free_ldt(struct mm_context *mm)
-{
-	int i;
-
-	if (!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES) {
-		i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
-		while (i-- > 0)
-			free_page((long) mm->ldt.u.pages[i]);
-	}
-	mm->ldt.entry_count = 0;
-}
-
-int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
-{
-	return do_modify_ldt_skas(func, ptr, bytecount);
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/Makefile linux-libre-3.2-gnu/arch/um/sys-i386/Makefile
--- linux-libre-3.1-gnu/arch/um/sys-i386/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,24 +0,0 @@
-#
-# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
-#
-
-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 atomic64_cx8_32.o mem.o
-
-obj-$(CONFIG_BINFMT_ELF) += elfcore.o
-
-subarch-obj-y = lib/string_32.o
-subarch-obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += lib/rwsem.o
-subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o
-subarch-obj-$(CONFIG_MODULES) += kernel/module.o
-
-USER_OBJS := bugs.o ptrace_user.o fault.o
-
-USER_OBJS += user-offsets.s
-extra-y += user-offsets.s
-
-UNPROFILE_OBJS := stub_segv.o
-CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
-
-include arch/um/scripts/Makefile.rules
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/mem.c linux-libre-3.2-gnu/arch/um/sys-i386/mem.c
--- linux-libre-3.1-gnu/arch/um/sys-i386/mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/mem.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
- *
- * This program is free software; you can 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 <asm/page.h>
-#include <asm/mman.h>
-
-static struct vm_area_struct gate_vma;
-
-static int __init gate_vma_init(void)
-{
-	if (!FIXADDR_USER_START)
-		return 0;
-
-	gate_vma.vm_mm = NULL;
-	gate_vma.vm_start = FIXADDR_USER_START;
-	gate_vma.vm_end = FIXADDR_USER_END;
-	gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
-	gate_vma.vm_page_prot = __P101;
-
-	/*
-	 * Make sure the vDSO gets into every core dump.
-	 * Dumping its contents makes post-mortem fully interpretable later
-	 * without matching up the same kernel and hardware config to see
-	 * what PC values meant.
-	 */
-	gate_vma.vm_flags |= VM_ALWAYSDUMP;
-
-	return 0;
-}
-__initcall(gate_vma_init);
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
-	return FIXADDR_USER_START ? &gate_vma : NULL;
-}
-
-int in_gate_area_no_mm(unsigned long addr)
-{
-	if (!FIXADDR_USER_START)
-		return 0;
-
-	if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END))
-		return 1;
-
-	return 0;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
-	struct vm_area_struct *vma = get_gate_vma(mm);
-
-	if (!vma)
-		return 0;
-
-	return (addr >= vma->vm_start) && (addr < vma->vm_end);
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/ptrace.c linux-libre-3.2-gnu/arch/um/sys-i386/ptrace.c
--- linux-libre-3.1-gnu/arch/um/sys-i386/ptrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/ptrace.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include "linux/mm.h"
-#include "linux/sched.h"
-#include "asm/uaccess.h"
-#include "skas.h"
-
-extern int arch_switch_tls(struct task_struct *to);
-
-void arch_switch_to(struct task_struct *to)
-{
-	int err = arch_switch_tls(to);
-	if (!err)
-		return;
-
-	if (err != -EINVAL)
-		printk(KERN_WARNING "arch_switch_tls failed, errno %d, "
-		       "not EINVAL\n", -err);
-	else
-		printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n");
-}
-
-int is_syscall(unsigned long addr)
-{
-	unsigned short instr;
-	int n;
-
-	n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
-	if (n) {
-		/* access_process_vm() grants access to vsyscall and stub,
-		 * while copy_from_user doesn't. Maybe access_process_vm is
-		 * slow, but that doesn't matter, since it will be called only
-		 * in case of singlestepping, if copy_from_user failed.
-		 */
-		n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
-		if (n != sizeof(instr)) {
-			printk(KERN_ERR "is_syscall : failed to read "
-			       "instruction from 0x%lx\n", addr);
-			return 1;
-		}
-	}
-	/* int 0x80 or sysenter */
-	return (instr == 0x80cd) || (instr == 0x340f);
-}
-
-/* determines which flags the user has access to. */
-/* 1 = access 0 = no access */
-#define FLAG_MASK 0x00044dd5
-
-int putreg(struct task_struct *child, int regno, unsigned long value)
-{
-	regno >>= 2;
-	switch (regno) {
-	case FS:
-		if (value && (value & 3) != 3)
-			return -EIO;
-		PT_REGS_FS(&child->thread.regs) = value;
-		return 0;
-	case GS:
-		if (value && (value & 3) != 3)
-			return -EIO;
-		PT_REGS_GS(&child->thread.regs) = value;
-		return 0;
-	case DS:
-	case ES:
-		if (value && (value & 3) != 3)
-			return -EIO;
-		value &= 0xffff;
-		break;
-	case SS:
-	case CS:
-		if ((value & 3) != 3)
-			return -EIO;
-		value &= 0xffff;
-		break;
-	case EFL:
-		value &= FLAG_MASK;
-		value |= PT_REGS_EFLAGS(&child->thread.regs);
-		break;
-	}
-	PT_REGS_SET(&child->thread.regs, regno, value);
-	return 0;
-}
-
-int poke_user(struct task_struct *child, long addr, long data)
-{
-	if ((addr & 3) || addr < 0)
-		return -EIO;
-
-	if (addr < MAX_REG_OFFSET)
-		return putreg(child, addr, data);
-	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
-		 (addr <= offsetof(struct user, u_debugreg[7]))) {
-		addr -= offsetof(struct user, u_debugreg[0]);
-		addr = addr >> 2;
-		if ((addr == 4) || (addr == 5))
-			return -EIO;
-		child->thread.arch.debugregs[addr] = data;
-		return 0;
-	}
-	return -EIO;
-}
-
-unsigned long getreg(struct task_struct *child, int regno)
-{
-	unsigned long retval = ~0UL;
-
-	regno >>= 2;
-	switch (regno) {
-	case FS:
-	case GS:
-	case DS:
-	case ES:
-	case SS:
-	case CS:
-		retval = 0xffff;
-		/* fall through */
-	default:
-		retval &= PT_REG(&child->thread.regs, regno);
-	}
-	return retval;
-}
-
-/* read the word at location addr in the USER area. */
-int peek_user(struct task_struct *child, long addr, long data)
-{
-	unsigned long tmp;
-
-	if ((addr & 3) || addr < 0)
-		return -EIO;
-
-	tmp = 0;  /* Default return condition */
-	if (addr < MAX_REG_OFFSET) {
-		tmp = getreg(child, addr);
-	}
-	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
-		 (addr <= offsetof(struct user, u_debugreg[7]))) {
-		addr -= offsetof(struct user, u_debugreg[0]);
-		addr = addr >> 2;
-		tmp = child->thread.arch.debugregs[addr];
-	}
-	return put_user(tmp, (unsigned long __user *) data);
-}
-
-static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
-	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
-	struct user_i387_struct fpregs;
-
-	err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
-	if (err)
-		return err;
-
-	n = copy_to_user(buf, &fpregs, sizeof(fpregs));
-	if(n > 0)
-		return -EFAULT;
-
-	return n;
-}
-
-static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
-	int n, cpu = ((struct thread_info *) child->stack)->cpu;
-	struct user_i387_struct fpregs;
-
-	n = copy_from_user(&fpregs, buf, sizeof(fpregs));
-	if (n > 0)
-		return -EFAULT;
-
-	return restore_fp_registers(userspace_pid[cpu],
-				    (unsigned long *) &fpregs);
-}
-
-static int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
-{
-	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
-	struct user_fxsr_struct fpregs;
-
-	err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
-	if (err)
-		return err;
-
-	n = copy_to_user(buf, &fpregs, sizeof(fpregs));
-	if(n > 0)
-		return -EFAULT;
-
-	return n;
-}
-
-static int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
-{
-	int n, cpu = ((struct thread_info *) child->stack)->cpu;
-	struct user_fxsr_struct fpregs;
-
-	n = copy_from_user(&fpregs, buf, sizeof(fpregs));
-	if (n > 0)
-		return -EFAULT;
-
-	return restore_fpx_registers(userspace_pid[cpu],
-				     (unsigned long *) &fpregs);
-}
-
-long subarch_ptrace(struct task_struct *child, long request,
-		    unsigned long addr, unsigned long data)
-{
-	int ret = -EIO;
-	void __user *datap = (void __user *) data;
-	switch (request) {
-	case PTRACE_GETFPREGS: /* Get the child FPU state. */
-		ret = get_fpregs(datap, child);
-		break;
-	case PTRACE_SETFPREGS: /* Set the child FPU state. */
-		ret = set_fpregs(datap, child);
-		break;
-	case PTRACE_GETFPXREGS: /* Get the child FPU state. */
-		ret = get_fpxregs(datap, child);
-		break;
-	case PTRACE_SETFPXREGS: /* Set the child FPU state. */
-		ret = set_fpxregs(datap, child);
-		break;
-	default:
-		ret = -EIO;
-	}
-	return ret;
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/ptrace_user.c linux-libre-3.2-gnu/arch/um/sys-i386/ptrace_user.c
--- linux-libre-3.1-gnu/arch/um/sys-i386/ptrace_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/ptrace_user.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <errno.h>
-#include <sys/ptrace.h>
-
-int ptrace_getregs(long pid, unsigned long *regs_out)
-{
-	if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
-		return -errno;
-	return 0;
-}
-
-int ptrace_setregs(long pid, unsigned long *regs)
-{
-	if (ptrace(PTRACE_SETREGS, pid, 0, regs) < 0)
-		return -errno;
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/setjmp.S linux-libre-3.2-gnu/arch/um/sys-i386/setjmp.S
--- linux-libre-3.1-gnu/arch/um/sys-i386/setjmp.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/setjmp.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,58 +0,0 @@
-#
-# arch/i386/setjmp.S
-#
-# setjmp/longjmp for the i386 architecture
-#
-
-#
-# The jmp_buf is assumed to contain the following, in order:
-#	%ebx
-#	%esp
-#	%ebp
-#	%esi
-#	%edi
-#	<return address>
-#
-
-	.text
-	.align 4
-	.globl setjmp
-	.type setjmp, @function
-setjmp:
-#ifdef _REGPARM
-	movl %eax,%edx
-#else
-	movl 4(%esp),%edx
-#endif
-	popl %ecx			# Return address, and adjust the stack
-	xorl %eax,%eax			# Return value
-	movl %ebx,(%edx)
-	movl %esp,4(%edx)		# Post-return %esp!
-	pushl %ecx			# Make the call/return stack happy
-	movl %ebp,8(%edx)
-	movl %esi,12(%edx)
-	movl %edi,16(%edx)
-	movl %ecx,20(%edx)		# Return address
-	ret
-
-	.size setjmp,.-setjmp
-
-	.text
-	.align 4
-	.globl longjmp
-	.type longjmp, @function
-longjmp:
-#ifdef _REGPARM
-	xchgl %eax,%edx
-#else
-	movl 4(%esp),%edx		# jmp_ptr address
-	movl 8(%esp),%eax		# Return value
-#endif
-	movl (%edx),%ebx
-	movl 4(%edx),%esp
-	movl 8(%edx),%ebp
-	movl 12(%edx),%esi
-	movl 16(%edx),%edi
-	jmp *20(%edx)
-
-	.size longjmp,.-longjmp
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/archsetjmp.h linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/archsetjmp.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/archsetjmp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/archsetjmp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * arch/um/include/sysdep-i386/archsetjmp.h
- */
-
-#ifndef _KLIBC_ARCHSETJMP_H
-#define _KLIBC_ARCHSETJMP_H
-
-struct __jmp_buf {
-	unsigned int __ebx;
-	unsigned int __esp;
-	unsigned int __ebp;
-	unsigned int __esi;
-	unsigned int __edi;
-	unsigned int __eip;
-};
-
-typedef struct __jmp_buf jmp_buf[1];
-
-#define JB_IP __eip
-#define JB_SP __esp
-
-#endif				/* _SETJMP_H */
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/barrier.h linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/barrier.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/barrier.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/barrier.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-#ifndef __SYSDEP_I386_BARRIER_H
-#define __SYSDEP_I386_BARRIER_H
-
-/* Copied from include/asm-i386 for use by userspace.  i386 has the option
- * of using mfence, but I'm just using this, which works everywhere, for now.
- */
-#define mb() asm volatile("lock; addl $0,0(%esp)")
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/checksum.h linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/checksum.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/checksum.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/checksum.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,201 +0,0 @@
-/* 
- * Licensed under the GPL
- */
-
-#ifndef __UM_SYSDEP_CHECKSUM_H
-#define __UM_SYSDEP_CHECKSUM_H
-
-#include "linux/in6.h"
-#include "linux/string.h"
-
-/*
- * 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);
-
-/*
- *	Note: when you get a NULL pointer exception here this means someone
- *	passed in an incorrect kernel address to one of these functions.
- *
- *	If you use these functions directly please don't forget the
- *	access_ok().
- */
-
-static __inline__
-__wsum csum_partial_copy_nocheck(const void *src, void *dst,
-				       int len, __wsum sum)
-{
-	memcpy(dst, src, len);
-	return csum_partial(dst, len, sum);
-}
-
-/*
- * the same as csum_partial, but copies from src while it
- * checksums, and handles user-space pointer exceptions correctly, when needed.
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-static __inline__
-__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
-					 int len, __wsum sum, int *err_ptr)
-{
-	if (copy_from_user(dst, src, len)) {
-		*err_ptr = -EFAULT;
-		return (__force __wsum)-1;
-	}
-
-	return csum_partial(dst, len, sum);
-}
-
-/*
- *	This is a version of ip_compute_csum() optimized for IP headers,
- *	which always checksum on 4 octet boundaries.
- *
- *	By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
- *	Arnt Gulbrandsen.
- */
-static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
-	unsigned int sum;
-
-	__asm__ __volatile__(
-	    "movl (%1), %0	;\n"
-	    "subl $4, %2	;\n"
-	    "jbe 2f		;\n"
-	    "addl 4(%1), %0	;\n"
-	    "adcl 8(%1), %0	;\n"
-	    "adcl 12(%1), %0	;\n"
-"1:	    adcl 16(%1), %0	;\n"
-	    "lea 4(%1), %1	;\n"
-	    "decl %2		;\n"
-	    "jne 1b		;\n"
-	    "adcl $0, %0	;\n"
-	    "movl %0, %2	;\n"
-	    "shrl $16, %0	;\n"
-	    "addw %w2, %w0	;\n"
-	    "adcl $0, %0	;\n"
-	    "notl %0		;\n"
-"2:				;\n"
-	/* Since the input registers which are loaded with iph and ipl
-	   are modified, we must also specify them as outputs, or gcc
-	   will assume they contain their original values. */
-	: "=r" (sum), "=r" (iph), "=r" (ihl)
-	: "1" (iph), "2" (ihl)
-	: "memory");
-	return (__force __sum16)sum;
-}
-
-/*
- *	Fold a partial checksum
- */
-
-static inline __sum16 csum_fold(__wsum sum)
-{
-	__asm__(
-		"addl %1, %0		;\n"
-		"adcl $0xffff, %0	;\n"
-		: "=r" (sum)
-		: "r" ((__force u32)sum << 16),
-		  "0" ((__force u32)sum & 0xffff0000)
-	);
-	return (__force __sum16)(~(__force u32)sum >> 16);
-}
-
-static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
-						   unsigned short len,
-						   unsigned short proto,
-						   __wsum sum)
-{
-    __asm__(
-	"addl %1, %0	;\n"
-	"adcl %2, %0	;\n"
-	"adcl %3, %0	;\n"
-	"adcl $0, %0	;\n"
-	: "=r" (sum)
-	: "g" (daddr), "g"(saddr), "g"((len + proto) << 8), "0"(sum));
-    return sum;
-}
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
-						   unsigned short len,
-						   unsigned short proto,
-						   __wsum sum)
-{
-	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-
-static inline __sum16 ip_compute_csum(const void *buff, int len)
-{
-    return csum_fold (csum_partial(buff, len, 0));
-}
-
-#define _HAVE_ARCH_IPV6_CSUM
-static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
-					  const struct in6_addr *daddr,
-					  __u32 len, unsigned short proto,
-					  __wsum sum)
-{
-	__asm__(
-		"addl 0(%1), %0		;\n"
-		"adcl 4(%1), %0		;\n"
-		"adcl 8(%1), %0		;\n"
-		"adcl 12(%1), %0	;\n"
-		"adcl 0(%2), %0		;\n"
-		"adcl 4(%2), %0		;\n"
-		"adcl 8(%2), %0		;\n"
-		"adcl 12(%2), %0	;\n"
-		"adcl %3, %0		;\n"
-		"adcl %4, %0		;\n"
-		"adcl $0, %0		;\n"
-		: "=&r" (sum)
-		: "r" (saddr), "r" (daddr),
-		  "r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
-
-	return csum_fold(sum);
-}
-
-/*
- *	Copy and checksum to user
- */
-#define HAVE_CSUM_COPY_USER
-static __inline__ __wsum csum_and_copy_to_user(const void *src,
-						     void __user *dst,
-						     int len, __wsum sum, int *err_ptr)
-{
-	if (access_ok(VERIFY_WRITE, dst, len)) {
-		if (copy_to_user(dst, src, len)) {
-			*err_ptr = -EFAULT;
-			return (__force __wsum)-1;
-		}
-
-		return csum_partial(src, len, sum);
-	}
-
-	if (len)
-		*err_ptr = -EFAULT;
-
-	return (__force __wsum)-1; /* invalid checksum */
-}
-
-#endif
-
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/faultinfo.h linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/faultinfo.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/faultinfo.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/faultinfo.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
- * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
- * Licensed under the GPL
- */
-
-#ifndef __FAULTINFO_I386_H
-#define __FAULTINFO_I386_H
-
-/* this structure contains the full arch-specific faultinfo
- * from the traps.
- * On i386, ptrace_faultinfo unfortunately doesn't provide
- * all the info, since trap_no is missing.
- * All common elements are defined at the same position in
- * both structures, thus making it easy to copy the
- * contents without knowledge about the structure elements.
- */
-struct faultinfo {
-        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
-        unsigned long cr2; /* in ptrace_faultinfo called addr */
-        int trap_no; /* missing in ptrace_faultinfo */
-};
-
-#define FAULT_WRITE(fi) ((fi).error_code & 2)
-#define FAULT_ADDRESS(fi) ((fi).cr2)
-
-#define PTRACE_FULL_FAULTINFO 0
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/host_ldt.h linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/host_ldt.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/host_ldt.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/host_ldt.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-#ifndef __ASM_HOST_LDT_I386_H
-#define __ASM_HOST_LDT_I386_H
-
-#include <asm/ldt.h>
-
-/*
- * macros stolen from include/asm-i386/desc.h
- */
-#define LDT_entry_a(info) \
-	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-
-#define LDT_entry_b(info) \
-	(((info)->base_addr & 0xff000000) | \
-	(((info)->base_addr & 0x00ff0000) >> 16) | \
-	((info)->limit & 0xf0000) | \
-	(((info)->read_exec_only ^ 1) << 9) | \
-	((info)->contents << 10) | \
-	(((info)->seg_not_present ^ 1) << 15) | \
-	((info)->seg_32bit << 22) | \
-	((info)->limit_in_pages << 23) | \
-	((info)->useable << 20) | \
-	0x7000)
-
-#define LDT_empty(info) (\
-	(info)->base_addr	== 0	&& \
-	(info)->limit		== 0	&& \
-	(info)->contents	== 0	&& \
-	(info)->read_exec_only	== 1	&& \
-	(info)->seg_32bit	== 0	&& \
-	(info)->limit_in_pages	== 0	&& \
-	(info)->seg_not_present	== 1	&& \
-	(info)->useable		== 0	)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/kernel-offsets.h linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/kernel-offsets.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/kernel-offsets.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/kernel-offsets.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/elf.h>
-#include <linux/crypto.h>
-#include <asm/mman.h>
-
-#define DEFINE(sym, val) \
-	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define STR(x) #x
-#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : )
-
-#define BLANK() asm volatile("\n->" : : )
-
-#define OFFSET(sym, str, mem) \
-	DEFINE(sym, offsetof(struct str, mem));
-
-void foo(void)
-{
-#include <common-offsets.h>
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/ptrace.h linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/ptrace.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/ptrace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/ptrace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_I386_PTRACE_H
-#define __SYSDEP_I386_PTRACE_H
-
-#include "user_constants.h"
-#include "sysdep/faultinfo.h"
-
-#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
-#define MAX_REG_OFFSET (UM_FRAME_SIZE)
-
-static inline void update_debugregs(int seq) {}
-
-/* syscall emulation path in ptrace */
-
-#ifndef PTRACE_SYSEMU
-#define PTRACE_SYSEMU 31
-#endif
-
-void set_using_sysemu(int value);
-int get_using_sysemu(void);
-extern int sysemu_supported;
-
-#include "skas_ptregs.h"
-
-#define REGS_IP(r) ((r)[HOST_IP])
-#define REGS_SP(r) ((r)[HOST_SP])
-#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
-#define REGS_EAX(r) ((r)[HOST_EAX])
-#define REGS_EBX(r) ((r)[HOST_EBX])
-#define REGS_ECX(r) ((r)[HOST_ECX])
-#define REGS_EDX(r) ((r)[HOST_EDX])
-#define REGS_ESI(r) ((r)[HOST_ESI])
-#define REGS_EDI(r) ((r)[HOST_EDI])
-#define REGS_EBP(r) ((r)[HOST_EBP])
-#define REGS_CS(r) ((r)[HOST_CS])
-#define REGS_SS(r) ((r)[HOST_SS])
-#define REGS_DS(r) ((r)[HOST_DS])
-#define REGS_ES(r) ((r)[HOST_ES])
-#define REGS_FS(r) ((r)[HOST_FS])
-#define REGS_GS(r) ((r)[HOST_GS])
-
-#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res)
-
-#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
-
-#ifndef PTRACE_SYSEMU_SINGLESTEP
-#define PTRACE_SYSEMU_SINGLESTEP 32
-#endif
-
-struct uml_pt_regs {
-	unsigned long gp[MAX_REG_NR];
-	unsigned long fp[HOST_FPX_SIZE];
-	struct faultinfo faultinfo;
-	long syscall;
-	int is_user;
-};
-
-#define EMPTY_UML_PT_REGS { }
-
-#define UPT_IP(r) REGS_IP((r)->gp)
-#define UPT_SP(r) REGS_SP((r)->gp)
-#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
-#define UPT_EAX(r) REGS_EAX((r)->gp)
-#define UPT_EBX(r) REGS_EBX((r)->gp)
-#define UPT_ECX(r) REGS_ECX((r)->gp)
-#define UPT_EDX(r) REGS_EDX((r)->gp)
-#define UPT_ESI(r) REGS_ESI((r)->gp)
-#define UPT_EDI(r) REGS_EDI((r)->gp)
-#define UPT_EBP(r) REGS_EBP((r)->gp)
-#define UPT_ORIG_EAX(r) ((r)->syscall)
-#define UPT_CS(r) REGS_CS((r)->gp)
-#define UPT_SS(r) REGS_SS((r)->gp)
-#define UPT_DS(r) REGS_DS((r)->gp)
-#define UPT_ES(r) REGS_ES((r)->gp)
-#define UPT_FS(r) REGS_FS((r)->gp)
-#define UPT_GS(r) REGS_GS((r)->gp)
-
-#define UPT_SYSCALL_ARG1(r) UPT_EBX(r)
-#define UPT_SYSCALL_ARG2(r) UPT_ECX(r)
-#define UPT_SYSCALL_ARG3(r) UPT_EDX(r)
-#define UPT_SYSCALL_ARG4(r) UPT_ESI(r)
-#define UPT_SYSCALL_ARG5(r) UPT_EDI(r)
-#define UPT_SYSCALL_ARG6(r) UPT_EBP(r)
-
-extern int user_context(unsigned long sp);
-
-#define UPT_IS_USER(r) ((r)->is_user)
-
-struct syscall_args {
-	unsigned long args[6];
-};
-
-#define SYSCALL_ARGS(r) ((struct syscall_args) \
-			 { .args = { UPT_SYSCALL_ARG1(r),	\
-				     UPT_SYSCALL_ARG2(r),	\
-				     UPT_SYSCALL_ARG3(r),	\
-				     UPT_SYSCALL_ARG4(r),	\
-				     UPT_SYSCALL_ARG5(r),	\
-				     UPT_SYSCALL_ARG6(r) } } )
-
-#define UPT_REG(regs, reg) \
-	({	unsigned long val; \
-		switch(reg){ \
-		case EIP: val = UPT_IP(regs); break; \
-		case UESP: val = UPT_SP(regs); break; \
-		case EAX: val = UPT_EAX(regs); break; \
-		case EBX: val = UPT_EBX(regs); break; \
-		case ECX: val = UPT_ECX(regs); break; \
-		case EDX: val = UPT_EDX(regs); break; \
-		case ESI: val = UPT_ESI(regs); break; \
-		case EDI: val = UPT_EDI(regs); break; \
-		case EBP: val = UPT_EBP(regs); break; \
-		case ORIG_EAX: val = UPT_ORIG_EAX(regs); break; \
-		case CS: val = UPT_CS(regs); break; \
-		case SS: val = UPT_SS(regs); break; \
-		case DS: val = UPT_DS(regs); break; \
-		case ES: val = UPT_ES(regs); break; \
-		case FS: val = UPT_FS(regs); break; \
-		case GS: val = UPT_GS(regs); break; \
-		case EFL: val = UPT_EFLAGS(regs); break; \
-		default :  \
-			panic("Bad register in UPT_REG : %d\n", reg);  \
-			val = -1; \
-		} \
-	        val; \
-	})
-
-#define UPT_SET(regs, reg, val) \
-	do { \
-		switch(reg){ \
-		case EIP: UPT_IP(regs) = val; break; \
-		case UESP: UPT_SP(regs) = val; break; \
-		case EAX: UPT_EAX(regs) = val; break; \
-		case EBX: UPT_EBX(regs) = val; break; \
-		case ECX: UPT_ECX(regs) = val; break; \
-		case EDX: UPT_EDX(regs) = val; break; \
-		case ESI: UPT_ESI(regs) = val; break; \
-		case EDI: UPT_EDI(regs) = val; break; \
-		case EBP: UPT_EBP(regs) = val; break; \
-		case ORIG_EAX: UPT_ORIG_EAX(regs) = val; break; \
-		case CS: UPT_CS(regs) = val; break; \
-		case SS: UPT_SS(regs) = val; break; \
-		case DS: UPT_DS(regs) = val; break; \
-		case ES: UPT_ES(regs) = val; break; \
-		case FS: UPT_FS(regs) = val; break; \
-		case GS: UPT_GS(regs) = val; break; \
-		case EFL: UPT_EFLAGS(regs) = val; break; \
-		default :  \
-			panic("Bad register in UPT_SET : %d\n", reg);  \
-			break; \
-		} \
-	} while (0)
-
-#define UPT_SET_SYSCALL_RETURN(r, res) \
-	REGS_SET_SYSCALL_RETURN((r)->regs, (res))
-
-#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
-
-#define UPT_ORIG_SYSCALL(r) UPT_EAX(r)
-#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r)
-#define UPT_SYSCALL_RET(r) UPT_EAX(r)
-
-#define UPT_FAULTINFO(r) (&(r)->faultinfo)
-
-extern void arch_init_registers(int pid);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/ptrace_user.h linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/ptrace_user.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/ptrace_user.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/ptrace_user.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_I386_PTRACE_USER_H__
-#define __SYSDEP_I386_PTRACE_USER_H__
-
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
-#include <asm/ptrace.h>
-#include "user_constants.h"
-
-#define PT_OFFSET(r) ((r) * sizeof(long))
-
-#define PT_SYSCALL_NR(regs) ((regs)[ORIG_EAX])
-#define PT_SYSCALL_NR_OFFSET PT_OFFSET(ORIG_EAX)
-
-#define PT_SYSCALL_ARG1_OFFSET PT_OFFSET(EBX)
-#define PT_SYSCALL_ARG2_OFFSET PT_OFFSET(ECX)
-#define PT_SYSCALL_ARG3_OFFSET PT_OFFSET(EDX)
-#define PT_SYSCALL_ARG4_OFFSET PT_OFFSET(ESI)
-#define PT_SYSCALL_ARG5_OFFSET PT_OFFSET(EDI)
-#define PT_SYSCALL_ARG6_OFFSET PT_OFFSET(EBP)
-
-#define PT_SYSCALL_RET_OFFSET PT_OFFSET(EAX)
-
-#define REGS_SYSCALL_NR EAX /* This is used before a system call */
-#define REGS_SYSCALL_ARG1 EBX
-#define REGS_SYSCALL_ARG2 ECX
-#define REGS_SYSCALL_ARG3 EDX
-#define REGS_SYSCALL_ARG4 ESI
-#define REGS_SYSCALL_ARG5 EDI
-#define REGS_SYSCALL_ARG6 EBP
-
-#define REGS_IP_INDEX EIP
-#define REGS_SP_INDEX UESP
-
-#define PT_IP_OFFSET PT_OFFSET(EIP)
-#define PT_IP(regs) ((regs)[EIP])
-#define PT_SP_OFFSET PT_OFFSET(UESP)
-#define PT_SP(regs) ((regs)[UESP])
-
-#define FP_SIZE ((HOST_FPX_SIZE > HOST_FP_SIZE) ? HOST_FPX_SIZE : HOST_FP_SIZE)
-
-#ifndef FRAME_SIZE
-#define FRAME_SIZE (17)
-#endif
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/sc.h linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/sc.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/sc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/sc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-#ifndef __SYSDEP_I386_SC_H
-#define __SYSDEP_I386_SC_H
-
-#include <user_constants.h>
-
-#define SC_OFFSET(sc, field) \
-	*((unsigned long *) &(((char *) (sc))[HOST_##field]))
-#define SC_FP_OFFSET(sc, field) \
-	*((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[HOST_##field]))
-#define SC_FP_OFFSET_PTR(sc, field, type) \
-	((type *) &(((char *) (SC_FPSTATE(sc)))[HOST_##field]))
-
-#define SC_IP(sc) SC_OFFSET(sc, SC_IP)
-#define SC_SP(sc) SC_OFFSET(sc, SC_SP)
-#define SC_FS(sc) SC_OFFSET(sc, SC_FS)
-#define SC_GS(sc) SC_OFFSET(sc, SC_GS)
-#define SC_DS(sc) SC_OFFSET(sc, SC_DS)
-#define SC_ES(sc) SC_OFFSET(sc, SC_ES)
-#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
-#define SC_CS(sc) SC_OFFSET(sc, SC_CS)
-#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS)
-#define SC_EAX(sc) SC_OFFSET(sc, SC_EAX)
-#define SC_EBX(sc) SC_OFFSET(sc, SC_EBX)
-#define SC_ECX(sc) SC_OFFSET(sc, SC_ECX)
-#define SC_EDX(sc) SC_OFFSET(sc, SC_EDX)
-#define SC_EDI(sc) SC_OFFSET(sc, SC_EDI)
-#define SC_ESI(sc) SC_OFFSET(sc, SC_ESI)
-#define SC_EBP(sc) SC_OFFSET(sc, SC_EBP)
-#define SC_TRAPNO(sc) SC_OFFSET(sc, SC_TRAPNO)
-#define SC_ERR(sc) SC_OFFSET(sc, SC_ERR)
-#define SC_CR2(sc) SC_OFFSET(sc, SC_CR2)
-#define SC_FPSTATE(sc) SC_OFFSET(sc, SC_FPSTATE)
-#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK)
-#define SC_FP_CW(sc) SC_FP_OFFSET(sc, SC_FP_CW)
-#define SC_FP_SW(sc) SC_FP_OFFSET(sc, SC_FP_SW)
-#define SC_FP_TAG(sc) SC_FP_OFFSET(sc, SC_FP_TAG)
-#define SC_FP_IPOFF(sc) SC_FP_OFFSET(sc, SC_FP_IPOFF)
-#define SC_FP_CSSEL(sc) SC_FP_OFFSET(sc, SC_FP_CSSEL)
-#define SC_FP_DATAOFF(sc) SC_FP_OFFSET(sc, SC_FP_DATAOFF)
-#define SC_FP_DATASEL(sc) SC_FP_OFFSET(sc, SC_FP_DATASEL)
-#define SC_FP_ST(sc) SC_FP_OFFSET_PTR(sc, SC_FP_ST, struct _fpstate)
-#define SC_FXSR_ENV(sc) SC_FP_OFFSET_PTR(sc, SC_FXSR_ENV, void)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/sigcontext.h linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/sigcontext.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/sigcontext.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/sigcontext.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYS_SIGCONTEXT_I386_H
-#define __SYS_SIGCONTEXT_I386_H
-
-#include "sysdep/sc.h"
-
-#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
-
-#define GET_FAULTINFO_FROM_SC(fi, sc) \
-	{ \
-		(fi).cr2 = SC_CR2(sc); \
-		(fi).error_code = SC_ERR(sc); \
-		(fi).trap_no = SC_TRAPNO(sc); \
-	}
-
-/* This is Page Fault */
-#define SEGV_IS_FIXABLE(fi)	((fi)->trap_no == 14)
-
-/* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */
-#define SEGV_MAYBE_FIXABLE(fi)	((fi)->trap_no == 0 && ptrace_faultinfo)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/skas_ptrace.h linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/skas_ptrace.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/skas_ptrace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/skas_ptrace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_I386_SKAS_PTRACE_H
-#define __SYSDEP_I386_SKAS_PTRACE_H
-
-struct ptrace_faultinfo {
-        int is_write;
-        unsigned long addr;
-};
-
-struct ptrace_ldt {
-        int func;
-        void *ptr;
-        unsigned long bytecount;
-};
-
-#define PTRACE_LDT 54
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/stub.h linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/stub.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/stub.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/stub.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_STUB_H
-#define __SYSDEP_STUB_H
-
-#include <sys/mman.h>
-#include <asm/ptrace.h>
-#include <asm/unistd.h>
-#include "as-layout.h"
-#include "stub-data.h"
-#include "kern_constants.h"
-
-extern void stub_segv_handler(int sig);
-extern void stub_clone_handler(void);
-
-#define STUB_SYSCALL_RET EAX
-#define STUB_MMAP_NR __NR_mmap2
-#define MMAP_OFFSET(o) ((o) >> UM_KERN_PAGE_SHIFT)
-
-static inline long stub_syscall0(long syscall)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall));
-
-	return ret;
-}
-
-static inline long stub_syscall1(long syscall, long arg1)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1));
-
-	return ret;
-}
-
-static inline long stub_syscall2(long syscall, long arg1, long arg2)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
-			"c" (arg2));
-
-	return ret;
-}
-
-static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
-			"c" (arg2), "d" (arg3));
-
-	return ret;
-}
-
-static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
-				 long arg4)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
-			"c" (arg2), "d" (arg3), "S" (arg4));
-
-	return ret;
-}
-
-static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
-				 long arg4, long arg5)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
-			"c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5));
-
-	return ret;
-}
-
-static inline void trap_myself(void)
-{
-	__asm("int3");
-}
-
-static inline void remap_stack(int fd, unsigned long offset)
-{
-	__asm__ volatile ("movl %%eax,%%ebp ; movl %0,%%eax ; int $0x80 ;"
-			  "movl %7, %%ebx ; movl %%eax, (%%ebx)"
-			  : : "g" (STUB_MMAP_NR), "b" (STUB_DATA),
-			    "c" (UM_KERN_PAGE_SIZE),
-			    "d" (PROT_READ | PROT_WRITE),
-			    "S" (MAP_FIXED | MAP_SHARED), "D" (fd),
-			    "a" (offset),
-			    "i" (&((struct stub_data *) STUB_DATA)->err)
-			  : "memory");
-}
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/syscalls.h linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/syscalls.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/syscalls.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/syscalls.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include "asm/unistd.h"
-#include "sysdep/ptrace.h"
-
-typedef long syscall_handler_t(struct pt_regs);
-
-/* Not declared on x86, incompatible declarations on x86_64, so these have
- * to go here rather than in sys_call_table.c
- */
-extern syscall_handler_t sys_rt_sigaction;
-
-extern syscall_handler_t *sys_call_table[];
-
-#define EXECUTE_SYSCALL(syscall, regs) \
-	((long (*)(struct syscall_args)) \
-	 (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/system.h linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/system.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/system.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,132 +0,0 @@
-#ifndef _ASM_X86_SYSTEM_H_
-#define _ASM_X86_SYSTEM_H_
-
-#include <asm/asm.h>
-#include <asm/segment.h>
-#include <asm/cpufeature.h>
-#include <asm/cmpxchg.h>
-#include <asm/nops.h>
-
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-
-/* entries in ARCH_DLINFO: */
-#ifdef CONFIG_IA32_EMULATION
-# define AT_VECTOR_SIZE_ARCH 2
-#else
-# define AT_VECTOR_SIZE_ARCH 1
-#endif
-
-extern unsigned long arch_align_stack(unsigned long sp);
-
-void default_idle(void);
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- */
-#ifdef CONFIG_X86_32
-/*
- * Some non-Intel clones support out of order store. wmb() ceases to be a
- * nop for these.
- */
-#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
-#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
-#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
-#else
-#define mb() 	asm volatile("mfence":::"memory")
-#define rmb()	asm volatile("lfence":::"memory")
-#define wmb()	asm volatile("sfence" ::: "memory")
-#endif
-
-/**
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier.  All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads.  This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies.  See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- *	CPU 0				CPU 1
- *
- *	b = 2;
- *	memory_barrier();
- *	p = &b;				q = p;
- *					read_barrier_depends();
- *					d = *q;
- * </programlisting>
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().  However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- *	CPU 0				CPU 1
- *
- *	a = 2;
- *	memory_barrier();
- *	b = 3;				y = b;
- *					read_barrier_depends();
- *					x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like this where there are no data dependencies.
- **/
-
-#define read_barrier_depends()	do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()	mb()
-#ifdef CONFIG_X86_PPRO_FENCE
-# define smp_rmb()	rmb()
-#else
-# define smp_rmb()	barrier()
-#endif
-#ifdef CONFIG_X86_OOSTORE
-# define smp_wmb() 	wmb()
-#else
-# define smp_wmb()	barrier()
-#endif
-#define smp_read_barrier_depends()	read_barrier_depends()
-#define set_mb(var, value) do { (void)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
-
-/*
- * Stop RDTSC speculation. This is needed when you need to use RDTSC
- * (or get_cycles or vread that possibly accesses the TSC) in a defined
- * code region.
- *
- * (Could use an alternative three way for this if there was one.)
- */
-static inline void rdtsc_barrier(void)
-{
-	alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
-	alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
-}
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/tls.h linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/tls.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/tls.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/tls.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-#ifndef _SYSDEP_TLS_H
-#define _SYSDEP_TLS_H
-
-# ifndef __KERNEL__
-
-/* Change name to avoid conflicts with the original one from <asm/ldt.h>, which
- * may be named user_desc (but in 2.4 and in header matching its API was named
- * modify_ldt_ldt_s). */
-
-typedef struct um_dup_user_desc {
-	unsigned int  entry_number;
-	unsigned int  base_addr;
-	unsigned int  limit;
-	unsigned int  seg_32bit:1;
-	unsigned int  contents:2;
-	unsigned int  read_exec_only:1;
-	unsigned int  limit_in_pages:1;
-	unsigned int  seg_not_present:1;
-	unsigned int  useable:1;
-} user_desc_t;
-
-# else /* __KERNEL__ */
-
-#  include <ldt.h>
-typedef struct user_desc user_desc_t;
-
-# endif /* __KERNEL__ */
-
-#define GDT_ENTRY_TLS_MIN_I386 6
-#define GDT_ENTRY_TLS_MIN_X86_64 12
-
-#endif /* _SYSDEP_TLS_H */
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/vm-flags.h linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/vm-flags.h
--- linux-libre-3.1-gnu/arch/um/sys-i386/shared/sysdep/vm-flags.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/shared/sysdep/vm-flags.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __VM_FLAGS_I386_H
-#define __VM_FLAGS_I386_H
-
-#define VM_DATA_DEFAULT_FLAGS \
-	(VM_READ | VM_WRITE | \
-	((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
-		 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/signal.c linux-libre-3.2-gnu/arch/um/sys-i386/signal.c
--- linux-libre-3.1-gnu/arch/um/sys-i386/signal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/signal.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,508 +0,0 @@
-/*
- * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <linux/ptrace.h>
-#include <asm/unistd.h>
-#include <asm/uaccess.h>
-#include <asm/ucontext.h>
-#include "frame_kern.h"
-#include "skas.h"
-
-void copy_sc(struct uml_pt_regs *regs, void *from)
-{
-	struct sigcontext *sc = from;
-
-	REGS_GS(regs->gp) = sc->gs;
-	REGS_FS(regs->gp) = sc->fs;
-	REGS_ES(regs->gp) = sc->es;
-	REGS_DS(regs->gp) = sc->ds;
-	REGS_EDI(regs->gp) = sc->di;
-	REGS_ESI(regs->gp) = sc->si;
-	REGS_EBP(regs->gp) = sc->bp;
-	REGS_SP(regs->gp) = sc->sp;
-	REGS_EBX(regs->gp) = sc->bx;
-	REGS_EDX(regs->gp) = sc->dx;
-	REGS_ECX(regs->gp) = sc->cx;
-	REGS_EAX(regs->gp) = sc->ax;
-	REGS_IP(regs->gp) = sc->ip;
-	REGS_CS(regs->gp) = sc->cs;
-	REGS_EFLAGS(regs->gp) = sc->flags;
-	REGS_SS(regs->gp) = sc->ss;
-}
-
-/*
- * FPU tag word conversions.
- */
-
-static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
-{
-	unsigned int tmp; /* to avoid 16 bit prefixes in the code */
-
-	/* Transform each pair of bits into 01 (valid) or 00 (empty) */
-	tmp = ~twd;
-	tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
-	/* and move the valid bits to the lower byte. */
-	tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
-	tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
-	tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
-	return tmp;
-}
-
-static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave)
-{
-	struct _fpxreg *st = NULL;
-	unsigned long twd = (unsigned long) fxsave->twd;
-	unsigned long tag;
-	unsigned long ret = 0xffff0000;
-	int i;
-
-#define FPREG_ADDR(f, n)	((char *)&(f)->st_space + (n) * 16)
-
-	for (i = 0; i < 8; i++) {
-		if (twd & 0x1) {
-			st = (struct _fpxreg *) FPREG_ADDR(fxsave, i);
-
-			switch (st->exponent & 0x7fff) {
-			case 0x7fff:
-				tag = 2;		/* Special */
-				break;
-			case 0x0000:
-				if ( !st->significand[0] &&
-				     !st->significand[1] &&
-				     !st->significand[2] &&
-				     !st->significand[3] ) {
-					tag = 1;	/* Zero */
-				} else {
-					tag = 2;	/* Special */
-				}
-				break;
-			default:
-				if (st->significand[3] & 0x8000) {
-					tag = 0;	/* Valid */
-				} else {
-					tag = 2;	/* Special */
-				}
-				break;
-			}
-		} else {
-			tag = 3;			/* Empty */
-		}
-		ret |= (tag << (2 * i));
-		twd = twd >> 1;
-	}
-	return ret;
-}
-
-static int convert_fxsr_to_user(struct _fpstate __user *buf,
-				struct user_fxsr_struct *fxsave)
-{
-	unsigned long env[7];
-	struct _fpreg __user *to;
-	struct _fpxreg *from;
-	int i;
-
-	env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul;
-	env[1] = (unsigned long)fxsave->swd | 0xffff0000ul;
-	env[2] = twd_fxsr_to_i387(fxsave);
-	env[3] = fxsave->fip;
-	env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
-	env[5] = fxsave->foo;
-	env[6] = fxsave->fos;
-
-	if (__copy_to_user(buf, env, 7 * sizeof(unsigned long)))
-		return 1;
-
-	to = &buf->_st[0];
-	from = (struct _fpxreg *) &fxsave->st_space[0];
-	for (i = 0; i < 8; i++, to++, from++) {
-		unsigned long __user *t = (unsigned long __user *)to;
-		unsigned long *f = (unsigned long *)from;
-
-		if (__put_user(*f, t) ||
-				__put_user(*(f + 1), t + 1) ||
-				__put_user(from->exponent, &to->exponent))
-			return 1;
-	}
-	return 0;
-}
-
-static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave,
-				  struct _fpstate __user *buf)
-{
-	unsigned long env[7];
-	struct _fpxreg *to;
-	struct _fpreg __user *from;
-	int i;
-
-	if (copy_from_user( env, buf, 7 * sizeof(long)))
-		return 1;
-
-	fxsave->cwd = (unsigned short)(env[0] & 0xffff);
-	fxsave->swd = (unsigned short)(env[1] & 0xffff);
-	fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
-	fxsave->fip = env[3];
-	fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16);
-	fxsave->fcs = (env[4] & 0xffff);
-	fxsave->foo = env[5];
-	fxsave->fos = env[6];
-
-	to = (struct _fpxreg *) &fxsave->st_space[0];
-	from = &buf->_st[0];
-	for (i = 0; i < 8; i++, to++, from++) {
-		unsigned long *t = (unsigned long *)to;
-		unsigned long __user *f = (unsigned long __user *)from;
-
-		if (__get_user(*t, f) ||
-		    __get_user(*(t + 1), f + 1) ||
-		    __get_user(to->exponent, &from->exponent))
-			return 1;
-	}
-	return 0;
-}
-
-extern int have_fpx_regs;
-
-static int copy_sc_from_user(struct pt_regs *regs,
-			     struct sigcontext __user *from)
-{
-	struct sigcontext sc;
-	int err, pid;
-
-	err = copy_from_user(&sc, from, sizeof(sc));
-	if (err)
-		return err;
-
-	pid = userspace_pid[current_thread_info()->cpu];
-	copy_sc(&regs->regs, &sc);
-	if (have_fpx_regs) {
-		struct user_fxsr_struct fpx;
-
-		err = copy_from_user(&fpx,
-			&((struct _fpstate __user *)sc.fpstate)->_fxsr_env[0],
-				     sizeof(struct user_fxsr_struct));
-		if (err)
-			return 1;
-
-		err = convert_fxsr_from_user(&fpx, sc.fpstate);
-		if (err)
-			return 1;
-
-		err = restore_fpx_registers(pid, (unsigned long *) &fpx);
-		if (err < 0) {
-			printk(KERN_ERR "copy_sc_from_user - "
-			       "restore_fpx_registers failed, errno = %d\n",
-			       -err);
-			return 1;
-		}
-	}
-	else {
-		struct user_i387_struct fp;
-
-		err = copy_from_user(&fp, sc.fpstate,
-				     sizeof(struct user_i387_struct));
-		if (err)
-			return 1;
-
-		err = restore_fp_registers(pid, (unsigned long *) &fp);
-		if (err < 0) {
-			printk(KERN_ERR "copy_sc_from_user - "
-			       "restore_fp_registers failed, errno = %d\n",
-			       -err);
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-static int copy_sc_to_user(struct sigcontext __user *to,
-			   struct _fpstate __user *to_fp, struct pt_regs *regs,
-			   unsigned long sp)
-{
-	struct sigcontext sc;
-	struct faultinfo * fi = &current->thread.arch.faultinfo;
-	int err, pid;
-
-	sc.gs = REGS_GS(regs->regs.gp);
-	sc.fs = REGS_FS(regs->regs.gp);
-	sc.es = REGS_ES(regs->regs.gp);
-	sc.ds = REGS_DS(regs->regs.gp);
-	sc.di = REGS_EDI(regs->regs.gp);
-	sc.si = REGS_ESI(regs->regs.gp);
-	sc.bp = REGS_EBP(regs->regs.gp);
-	sc.sp = sp;
-	sc.bx = REGS_EBX(regs->regs.gp);
-	sc.dx = REGS_EDX(regs->regs.gp);
-	sc.cx = REGS_ECX(regs->regs.gp);
-	sc.ax = REGS_EAX(regs->regs.gp);
-	sc.ip = REGS_IP(regs->regs.gp);
-	sc.cs = REGS_CS(regs->regs.gp);
-	sc.flags = REGS_EFLAGS(regs->regs.gp);
-	sc.sp_at_signal = regs->regs.gp[UESP];
-	sc.ss = regs->regs.gp[SS];
-	sc.cr2 = fi->cr2;
-	sc.err = fi->error_code;
-	sc.trapno = fi->trap_no;
-
-	to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
-	sc.fpstate = to_fp;
-
-	pid = userspace_pid[current_thread_info()->cpu];
-	if (have_fpx_regs) {
-		struct user_fxsr_struct fpx;
-
-		err = save_fpx_registers(pid, (unsigned long *) &fpx);
-		if (err < 0){
-			printk(KERN_ERR "copy_sc_to_user - save_fpx_registers "
-			       "failed, errno = %d\n", err);
-			return 1;
-		}
-
-		err = convert_fxsr_to_user(to_fp, &fpx);
-		if (err)
-			return 1;
-
-		err |= __put_user(fpx.swd, &to_fp->status);
-		err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic);
-		if (err)
-			return 1;
-
-		if (copy_to_user(&to_fp->_fxsr_env[0], &fpx,
-				 sizeof(struct user_fxsr_struct)))
-			return 1;
-	}
-	else {
-		struct user_i387_struct fp;
-
-		err = save_fp_registers(pid, (unsigned long *) &fp);
-		if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
-			return 1;
-	}
-
-	return copy_to_user(to, &sc, sizeof(sc));
-}
-
-static int copy_ucontext_to_user(struct ucontext __user *uc,
-				 struct _fpstate __user *fp, sigset_t *set,
-				 unsigned long sp)
-{
-	int err = 0;
-
-	err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
-	err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
-	err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
-	err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, sp);
-	err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
-	return err;
-}
-
-struct sigframe
-{
-	char __user *pretcode;
-	int sig;
-	struct sigcontext sc;
-	struct _fpstate fpstate;
-	unsigned long extramask[_NSIG_WORDS-1];
-	char retcode[8];
-};
-
-struct rt_sigframe
-{
-	char __user *pretcode;
-	int sig;
-	struct siginfo __user *pinfo;
-	void __user *puc;
-	struct siginfo info;
-	struct ucontext uc;
-	struct _fpstate fpstate;
-	char retcode[8];
-};
-
-int setup_signal_stack_sc(unsigned long stack_top, int sig,
-			  struct k_sigaction *ka, struct pt_regs *regs,
-			  sigset_t *mask)
-{
-	struct sigframe __user *frame;
-	void __user *restorer;
-	unsigned long save_sp = PT_REGS_SP(regs);
-	int err = 0;
-
-	/* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
-	stack_top = ((stack_top + 4) & -16UL) - 4;
-	frame = (struct sigframe __user *) stack_top - 1;
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		return 1;
-
-	restorer = frame->retcode;
-	if (ka->sa.sa_flags & SA_RESTORER)
-		restorer = ka->sa.sa_restorer;
-
-	/* Update SP now because the page fault handler refuses to extend
-	 * the stack if the faulting address is too far below the current
-	 * SP, which frame now certainly is.  If there's an error, the original
-	 * value is restored on the way out.
-	 * When writing the sigcontext to the stack, we have to write the
-	 * original value, so that's passed to copy_sc_to_user, which does
-	 * the right thing with it.
-	 */
-	PT_REGS_SP(regs) = (unsigned long) frame;
-
-	err |= __put_user(restorer, &frame->pretcode);
-	err |= __put_user(sig, &frame->sig);
-	err |= copy_sc_to_user(&frame->sc, NULL, regs, save_sp);
-	err |= __put_user(mask->sig[0], &frame->sc.oldmask);
-	if (_NSIG_WORDS > 1)
-		err |= __copy_to_user(&frame->extramask, &mask->sig[1],
-				      sizeof(frame->extramask));
-
-	/*
-	 * This is popl %eax ; movl $,%eax ; int $0x80
-	 *
-	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
-	 * reasons and because gdb uses it as a signature to notice
-	 * signal handler stack frames.
-	 */
-	err |= __put_user(0xb858, (short __user *)(frame->retcode+0));
-	err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2));
-	err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));
-
-	if (err)
-		goto err;
-
-	PT_REGS_SP(regs) = (unsigned long) frame;
-	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
-	PT_REGS_EAX(regs) = (unsigned long) sig;
-	PT_REGS_EDX(regs) = (unsigned long) 0;
-	PT_REGS_ECX(regs) = (unsigned long) 0;
-
-	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
-		ptrace_notify(SIGTRAP);
-	return 0;
-
-err:
-	PT_REGS_SP(regs) = save_sp;
-	return err;
-}
-
-int setup_signal_stack_si(unsigned long stack_top, int sig,
-			  struct k_sigaction *ka, struct pt_regs *regs,
-			  siginfo_t *info, sigset_t *mask)
-{
-	struct rt_sigframe __user *frame;
-	void __user *restorer;
-	unsigned long save_sp = PT_REGS_SP(regs);
-	int err = 0;
-
-	stack_top &= -8UL;
-	frame = (struct rt_sigframe __user *) stack_top - 1;
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		return 1;
-
-	restorer = frame->retcode;
-	if (ka->sa.sa_flags & SA_RESTORER)
-		restorer = ka->sa.sa_restorer;
-
-	/* See comment above about why this is here */
-	PT_REGS_SP(regs) = (unsigned long) frame;
-
-	err |= __put_user(restorer, &frame->pretcode);
-	err |= __put_user(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);
-	err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
-				     save_sp);
-
-	/*
-	 * This is movl $,%eax ; int $0x80
-	 *
-	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
-	 * reasons and because gdb uses it as a signature to notice
-	 * signal handler stack frames.
-	 */
-	err |= __put_user(0xb8, (char __user *)(frame->retcode+0));
-	err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1));
-	err |= __put_user(0x80cd, (short __user *)(frame->retcode+5));
-
-	if (err)
-		goto err;
-
-	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
-	PT_REGS_EAX(regs) = (unsigned long) sig;
-	PT_REGS_EDX(regs) = (unsigned long) &frame->info;
-	PT_REGS_ECX(regs) = (unsigned long) &frame->uc;
-
-	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
-		ptrace_notify(SIGTRAP);
-	return 0;
-
-err:
-	PT_REGS_SP(regs) = save_sp;
-	return err;
-}
-
-long sys_sigreturn(struct pt_regs regs)
-{
-	unsigned long sp = PT_REGS_SP(&current->thread.regs);
-	struct sigframe __user *frame = (struct sigframe __user *)(sp - 8);
-	sigset_t set;
-	struct sigcontext __user *sc = &frame->sc;
-	unsigned long __user *oldmask = &sc->oldmask;
-	unsigned long __user *extramask = frame->extramask;
-	int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
-
-	if (copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) ||
-	    copy_from_user(&set.sig[1], extramask, sig_size))
-		goto segfault;
-
-	sigdelsetmask(&set, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (copy_sc_from_user(&current->thread.regs, sc))
-		goto segfault;
-
-	/* Avoid ERESTART handling */
-	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
-	return PT_REGS_SYSCALL_RET(&current->thread.regs);
-
- segfault:
-	force_sig(SIGSEGV, current);
-	return 0;
-}
-
-long sys_rt_sigreturn(struct pt_regs regs)
-{
-	unsigned long sp = PT_REGS_SP(&current->thread.regs);
-	struct rt_sigframe __user *frame =
-		(struct rt_sigframe __user *) (sp - 4);
-	sigset_t set;
-	struct ucontext __user *uc = &frame->uc;
-	int sig_size = _NSIG_WORDS * sizeof(unsigned long);
-
-	if (copy_from_user(&set, &uc->uc_sigmask, sig_size))
-		goto segfault;
-
-	sigdelsetmask(&set, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
-		goto segfault;
-
-	/* Avoid ERESTART handling */
-	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
-	return PT_REGS_SYSCALL_RET(&current->thread.regs);
-
- segfault:
-	force_sig(SIGSEGV, current);
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/stub.S linux-libre-3.2-gnu/arch/um/sys-i386/stub.S
--- linux-libre-3.1-gnu/arch/um/sys-i386/stub.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/stub.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-#include "as-layout.h"
-
-	.globl syscall_stub
-.section .__syscall_stub, "ax"
-
-	.globl batch_syscall_stub
-batch_syscall_stub:
-	/* load pointer to first operation */
-	mov	$(STUB_DATA+8), %esp
-
-again:
-	/* load length of additional data */
-	mov	0x0(%esp), %eax
-
-	/* if(length == 0) : end of list */
-	/* write possible 0 to header */
-	mov	%eax, STUB_DATA+4
-	cmpl	$0, %eax
-	jz	done
-
-	/* save current pointer */
-	mov	%esp, STUB_DATA+4
-
-	/* skip additional data */
-	add	%eax, %esp
-
-	/* load syscall-# */
-	pop	%eax
-
-	/* load syscall params */
-	pop	%ebx
-	pop	%ecx
-	pop	%edx
-	pop	%esi
- 	pop	%edi
-	pop	%ebp
-
-	/* execute syscall */
-	int	$0x80
-
-	/* check return value */
-	pop	%ebx
-	cmp	%ebx, %eax
-	je	again
-
-done:
-	/* save return value */
-	mov	%eax, STUB_DATA
-
-	/* stop */
-	int3
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/stub_segv.c linux-libre-3.2-gnu/arch/um/sys-i386/stub_segv.c
--- linux-libre-3.1-gnu/arch/um/sys-i386/stub_segv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/stub_segv.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include "sysdep/stub.h"
-#include "sysdep/sigcontext.h"
-
-void __attribute__ ((__section__ (".__syscall_stub")))
-stub_segv_handler(int sig)
-{
-	struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
-
-	GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), sc);
-
-	trap_myself();
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/syscalls.c linux-libre-3.2-gnu/arch/um/sys-i386/syscalls.c
--- linux-libre-3.1-gnu/arch/um/sys-i386/syscalls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/syscalls.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,66 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include "linux/sched.h"
-#include "linux/shm.h"
-#include "linux/ipc.h"
-#include "linux/syscalls.h"
-#include "asm/mman.h"
-#include "asm/uaccess.h"
-#include "asm/unistd.h"
-
-/*
- * The prototype on i386 is:
- *
- *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
- *
- * and the "newtls" arg. on i386 is read by copy_thread directly from the
- * register saved on the stack.
- */
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
-	       int __user *parent_tid, void *newtls, int __user *child_tid)
-{
-	long ret;
-
-	if (!newsp)
-		newsp = UPT_SP(&current->thread.regs.regs);
-
-	current->thread.forking = 1;
-	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
-		      child_tid);
-	current->thread.forking = 0;
-	return ret;
-}
-
-long 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))
-			return -EFAULT;
-		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
-		__get_user(mask, &act->sa_mask);
-		siginitset(&new_ka.sa.sa_mask, mask);
-	}
-
-	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
-	if (!ret && oact) {
-		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
-		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
-			return -EFAULT;
-		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
-	}
-
-	return ret;
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/sys_call_table.S linux-libre-3.2-gnu/arch/um/sys-i386/sys_call_table.S
--- linux-libre-3.1-gnu/arch/um/sys-i386/sys_call_table.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/sys_call_table.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-#include <linux/linkage.h>
-/* Steal i386 syscall table for our purposes, but with some slight changes.*/
-
-#define sys_iopl sys_ni_syscall
-#define sys_ioperm sys_ni_syscall
-
-#define sys_vm86old sys_ni_syscall
-#define sys_vm86 sys_ni_syscall
-
-#define old_mmap sys_old_mmap
-
-#define ptregs_fork sys_fork
-#define ptregs_execve sys_execve
-#define ptregs_iopl sys_iopl
-#define ptregs_vm86old sys_vm86old
-#define ptregs_sigreturn sys_sigreturn
-#define ptregs_clone sys_clone
-#define ptregs_vm86 sys_vm86
-#define ptregs_rt_sigreturn sys_rt_sigreturn
-#define ptregs_sigaltstack sys_sigaltstack
-#define ptregs_vfork sys_vfork
-
-.section .rodata,"a"
-
-#include "../../x86/kernel/syscall_table_32.S"
-
-ENTRY(syscall_table_size)
-.long .-sys_call_table
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/sysrq.c linux-libre-3.2-gnu/arch/um/sys-i386/sysrq.c
--- linux-libre-3.1-gnu/arch/um/sys-i386/sysrq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/sysrq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include "linux/kernel.h"
-#include "linux/smp.h"
-#include "linux/sched.h"
-#include "linux/kallsyms.h"
-#include "asm/ptrace.h"
-#include "sysrq.h"
-
-/* This is declared by <linux/sched.h> */
-void show_regs(struct pt_regs *regs)
-{
-        printk("\n");
-        printk("EIP: %04lx:[<%08lx>] CPU: %d %s", 
-	       0xffff & PT_REGS_CS(regs), PT_REGS_IP(regs),
-	       smp_processor_id(), print_tainted());
-        if (PT_REGS_CS(regs) & 3)
-                printk(" ESP: %04lx:%08lx", 0xffff & PT_REGS_SS(regs),
-		       PT_REGS_SP(regs));
-        printk(" EFLAGS: %08lx\n    %s\n", PT_REGS_EFLAGS(regs),
-	       print_tainted());
-        printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
-                PT_REGS_EAX(regs), PT_REGS_EBX(regs), 
-	       PT_REGS_ECX(regs), 
-	       PT_REGS_EDX(regs));
-        printk("ESI: %08lx EDI: %08lx EBP: %08lx",
-	       PT_REGS_ESI(regs), PT_REGS_EDI(regs), 
-	       PT_REGS_EBP(regs));
-        printk(" DS: %04lx ES: %04lx\n",
-	       0xffff & PT_REGS_DS(regs), 
-	       0xffff & PT_REGS_ES(regs));
-
-        show_trace(NULL, (unsigned long *) &regs);
-}
-
-/* Copied from i386. */
-static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
-{
-	return	p > (void *)tinfo &&
-		p < (void *)tinfo + THREAD_SIZE - 3;
-}
-
-/* Adapted from i386 (we also print the address we read from). */
-static inline unsigned long print_context_stack(struct thread_info *tinfo,
-				unsigned long *stack, unsigned long ebp)
-{
-	unsigned long addr;
-
-#ifdef CONFIG_FRAME_POINTER
-	while (valid_stack_ptr(tinfo, (void *)ebp)) {
-		addr = *(unsigned long *)(ebp + 4);
-		printk("%08lx:  [<%08lx>]", ebp + 4, addr);
-		print_symbol(" %s", addr);
-		printk("\n");
-		ebp = *(unsigned long *)ebp;
-	}
-#else
-	while (valid_stack_ptr(tinfo, stack)) {
-		addr = *stack;
-		if (__kernel_text_address(addr)) {
-			printk("%08lx:  [<%08lx>]", (unsigned long) stack, addr);
-			print_symbol(" %s", addr);
-			printk("\n");
-		}
-		stack++;
-	}
-#endif
-	return ebp;
-}
-
-void show_trace(struct task_struct* task, unsigned long * stack)
-{
-	unsigned long ebp;
-	struct thread_info *context;
-
-	/* Turn this into BUG_ON if possible. */
-	if (!stack) {
-		stack = (unsigned long*) &stack;
-		printk("show_trace: got NULL stack, implicit assumption task == current");
-		WARN_ON(1);
-	}
-
-	if (!task)
-		task = current;
-
-	if (task != current) {
-		ebp = (unsigned long) KSTK_EBP(task);
-	} else {
-		asm ("movl %%ebp, %0" : "=r" (ebp) : );
-	}
-
-	context = (struct thread_info *)
-		((unsigned long)stack & (~(THREAD_SIZE - 1)));
-	print_context_stack(context, stack, ebp);
-
-	printk("\n");
-}
-
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/tls.c linux-libre-3.2-gnu/arch/um/sys-i386/tls.c
--- linux-libre-3.1-gnu/arch/um/sys-i386/tls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/tls.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,396 +0,0 @@
-/*
- * Copyright (C) 2005 Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
- * Licensed under the GPL
- */
-
-#include "linux/percpu.h"
-#include "linux/sched.h"
-#include "asm/uaccess.h"
-#include "os.h"
-#include "skas.h"
-#include "sysdep/tls.h"
-
-/*
- * If needed we can detect when it's uninitialized.
- *
- * These are initialized in an initcall and unchanged thereafter.
- */
-static int host_supports_tls = -1;
-int host_gdt_entry_tls_min;
-
-int do_set_thread_area(struct user_desc *info)
-{
-	int ret;
-	u32 cpu;
-
-	cpu = get_cpu();
-	ret = os_set_thread_area(info, userspace_pid[cpu]);
-	put_cpu();
-
-	if (ret)
-		printk(KERN_ERR "PTRACE_SET_THREAD_AREA failed, err = %d, "
-		       "index = %d\n", ret, info->entry_number);
-
-	return ret;
-}
-
-int do_get_thread_area(struct user_desc *info)
-{
-	int ret;
-	u32 cpu;
-
-	cpu = get_cpu();
-	ret = os_get_thread_area(info, userspace_pid[cpu]);
-	put_cpu();
-
-	if (ret)
-		printk(KERN_ERR "PTRACE_GET_THREAD_AREA failed, err = %d, "
-		       "index = %d\n", ret, info->entry_number);
-
-	return ret;
-}
-
-/*
- * sys_get_thread_area: get a yet unused TLS descriptor index.
- * XXX: Consider leaving one free slot for glibc usage at first place. This must
- * be done here (and by changing GDT_ENTRY_TLS_* macros) and nowhere else.
- *
- * Also, this must be tested when compiling in SKAS mode with dynamic linking
- * and running against NPTL.
- */
-static int get_free_idx(struct task_struct* task)
-{
-	struct thread_struct *t = &task->thread;
-	int idx;
-
-	if (!t->arch.tls_array)
-		return GDT_ENTRY_TLS_MIN;
-
-	for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
-		if (!t->arch.tls_array[idx].present)
-			return idx + GDT_ENTRY_TLS_MIN;
-	return -ESRCH;
-}
-
-static inline void clear_user_desc(struct user_desc* info)
-{
-	/* Postcondition: LDT_empty(info) returns true. */
-	memset(info, 0, sizeof(*info));
-
-	/*
-	 * Check the LDT_empty or the i386 sys_get_thread_area code - we obtain
-	 * indeed an empty user_desc.
-	 */
-	info->read_exec_only = 1;
-	info->seg_not_present = 1;
-}
-
-#define O_FORCE 1
-
-static int load_TLS(int flags, struct task_struct *to)
-{
-	int ret = 0;
-	int idx;
-
-	for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) {
-		struct uml_tls_struct* curr =
-			&to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN];
-
-		/*
-		 * Actually, now if it wasn't flushed it gets cleared and
-		 * flushed to the host, which will clear it.
-		 */
-		if (!curr->present) {
-			if (!curr->flushed) {
-				clear_user_desc(&curr->tls);
-				curr->tls.entry_number = idx;
-			} else {
-				WARN_ON(!LDT_empty(&curr->tls));
-				continue;
-			}
-		}
-
-		if (!(flags & O_FORCE) && curr->flushed)
-			continue;
-
-		ret = do_set_thread_area(&curr->tls);
-		if (ret)
-			goto out;
-
-		curr->flushed = 1;
-	}
-out:
-	return ret;
-}
-
-/*
- * Verify if we need to do a flush for the new process, i.e. if there are any
- * present desc's, only if they haven't been flushed.
- */
-static inline int needs_TLS_update(struct task_struct *task)
-{
-	int i;
-	int ret = 0;
-
-	for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
-		struct uml_tls_struct* curr =
-			&task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
-
-		/*
-		 * Can't test curr->present, we may need to clear a descriptor
-		 * which had a value.
-		 */
-		if (curr->flushed)
-			continue;
-		ret = 1;
-		break;
-	}
-	return ret;
-}
-
-/*
- * On a newly forked process, the TLS descriptors haven't yet been flushed. So
- * we mark them as such and the first switch_to will do the job.
- */
-void clear_flushed_tls(struct task_struct *task)
-{
-	int i;
-
-	for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
-		struct uml_tls_struct* curr =
-			&task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
-
-		/*
-		 * Still correct to do this, if it wasn't present on the host it
-		 * will remain as flushed as it was.
-		 */
-		if (!curr->present)
-			continue;
-
-		curr->flushed = 0;
-	}
-}
-
-/*
- * In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a
- * common host process. So this is needed in SKAS0 too.
- *
- * However, if each thread had a different host process (and this was discussed
- * for SMP support) this won't be needed.
- *
- * And this will not need be used when (and if) we'll add support to the host
- * SKAS patch.
- */
-
-int arch_switch_tls(struct task_struct *to)
-{
-	if (!host_supports_tls)
-		return 0;
-
-	/*
-	 * We have no need whatsoever to switch TLS for kernel threads; beyond
-	 * that, that would also result in us calling os_set_thread_area with
-	 * userspace_pid[cpu] == 0, which gives an error.
-	 */
-	if (likely(to->mm))
-		return load_TLS(O_FORCE, to);
-
-	return 0;
-}
-
-static int set_tls_entry(struct task_struct* task, struct user_desc *info,
-			 int idx, int flushed)
-{
-	struct thread_struct *t = &task->thread;
-
-	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
-		return -EINVAL;
-
-	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls = *info;
-	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present = 1;
-	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed = flushed;
-
-	return 0;
-}
-
-int arch_copy_tls(struct task_struct *new)
-{
-	struct user_desc info;
-	int idx, ret = -EFAULT;
-
-	if (copy_from_user(&info,
-			   (void __user *) UPT_ESI(&new->thread.regs.regs),
-			   sizeof(info)))
-		goto out;
-
-	ret = -EINVAL;
-	if (LDT_empty(&info))
-		goto out;
-
-	idx = info.entry_number;
-
-	ret = set_tls_entry(new, &info, idx, 0);
-out:
-	return ret;
-}
-
-/* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */
-static int get_tls_entry(struct task_struct *task, struct user_desc *info,
-			 int idx)
-{
-	struct thread_struct *t = &task->thread;
-
-	if (!t->arch.tls_array)
-		goto clear;
-
-	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
-		return -EINVAL;
-
-	if (!t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present)
-		goto clear;
-
-	*info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls;
-
-out:
-	/*
-	 * Temporary debugging check, to make sure that things have been
-	 * flushed. This could be triggered if load_TLS() failed.
-	 */
-	if (unlikely(task == current &&
-		     !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) {
-		printk(KERN_ERR "get_tls_entry: task with pid %d got here "
-				"without flushed TLS.", current->pid);
-	}
-
-	return 0;
-clear:
-	/*
-	 * When the TLS entry has not been set, the values read to user in the
-	 * tls_array are 0 (because it's cleared at boot, see
-	 * arch/i386/kernel/head.S:cpu_gdt_table). Emulate that.
-	 */
-	clear_user_desc(info);
-	info->entry_number = idx;
-	goto out;
-}
-
-int sys_set_thread_area(struct user_desc __user *user_desc)
-{
-	struct user_desc info;
-	int idx, ret;
-
-	if (!host_supports_tls)
-		return -ENOSYS;
-
-	if (copy_from_user(&info, user_desc, sizeof(info)))
-		return -EFAULT;
-
-	idx = info.entry_number;
-
-	if (idx == -1) {
-		idx = get_free_idx(current);
-		if (idx < 0)
-			return idx;
-		info.entry_number = idx;
-		/* Tell the user which slot we chose for him.*/
-		if (put_user(idx, &user_desc->entry_number))
-			return -EFAULT;
-	}
-
-	ret = do_set_thread_area(&info);
-	if (ret)
-		return ret;
-	return set_tls_entry(current, &info, idx, 1);
-}
-
-/*
- * Perform set_thread_area on behalf of the traced child.
- * Note: error handling is not done on the deferred load, and this differ from
- * i386. However the only possible error are caused by bugs.
- */
-int ptrace_set_thread_area(struct task_struct *child, int idx,
-			   struct user_desc __user *user_desc)
-{
-	struct user_desc info;
-
-	if (!host_supports_tls)
-		return -EIO;
-
-	if (copy_from_user(&info, user_desc, sizeof(info)))
-		return -EFAULT;
-
-	return set_tls_entry(child, &info, idx, 0);
-}
-
-int sys_get_thread_area(struct user_desc __user *user_desc)
-{
-	struct user_desc info;
-	int idx, ret;
-
-	if (!host_supports_tls)
-		return -ENOSYS;
-
-	if (get_user(idx, &user_desc->entry_number))
-		return -EFAULT;
-
-	ret = get_tls_entry(current, &info, idx);
-	if (ret < 0)
-		goto out;
-
-	if (copy_to_user(user_desc, &info, sizeof(info)))
-		ret = -EFAULT;
-
-out:
-	return ret;
-}
-
-/*
- * Perform get_thread_area on behalf of the traced child.
- */
-int ptrace_get_thread_area(struct task_struct *child, int idx,
-		struct user_desc __user *user_desc)
-{
-	struct user_desc info;
-	int ret;
-
-	if (!host_supports_tls)
-		return -EIO;
-
-	ret = get_tls_entry(child, &info, idx);
-	if (ret < 0)
-		goto out;
-
-	if (copy_to_user(user_desc, &info, sizeof(info)))
-		ret = -EFAULT;
-out:
-	return ret;
-}
-
-/*
- * This code is really i386-only, but it detects and logs x86_64 GDT indexes
- * if a 32-bit UML is running on a 64-bit host.
- */
-static int __init __setup_host_supports_tls(void)
-{
-	check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min);
-	if (host_supports_tls) {
-		printk(KERN_INFO "Host TLS support detected\n");
-		printk(KERN_INFO "Detected host type: ");
-		switch (host_gdt_entry_tls_min) {
-		case GDT_ENTRY_TLS_MIN_I386:
-			printk(KERN_CONT "i386");
-			break;
-		case GDT_ENTRY_TLS_MIN_X86_64:
-			printk(KERN_CONT "x86_64");
-			break;
-		}
-		printk(KERN_CONT " (GDT indexes %d to %d)\n",
-		       host_gdt_entry_tls_min,
-		       host_gdt_entry_tls_min + GDT_ENTRY_TLS_ENTRIES);
-	} else
-		printk(KERN_ERR "  Host TLS support NOT detected! "
-				"TLS support inside UML will not work\n");
-	return 0;
-}
-
-__initcall(__setup_host_supports_tls);
diff -druN linux-libre-3.1-gnu/arch/um/sys-i386/user-offsets.c linux-libre-3.2-gnu/arch/um/sys-i386/user-offsets.c
--- linux-libre-3.1-gnu/arch/um/sys-i386/user-offsets.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-i386/user-offsets.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-#include <stdio.h>
-#include <stddef.h>
-#include <signal.h>
-#include <sys/poll.h>
-#include <sys/user.h>
-#include <sys/mman.h>
-#include <asm/ptrace.h>
-
-#define DEFINE(sym, val) \
-	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define DEFINE_LONGS(sym, val) \
-	asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
-
-#define OFFSET(sym, str, mem) \
-	DEFINE(sym, offsetof(struct str, mem));
-
-void foo(void)
-{
-	OFFSET(HOST_SC_TRAPNO, sigcontext, trapno);
-	OFFSET(HOST_SC_ERR, sigcontext, err);
-	OFFSET(HOST_SC_CR2, sigcontext, cr2);
-
-	DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct));
-	DEFINE_LONGS(HOST_FPX_SIZE, sizeof(struct user_fpxregs_struct));
-
-	DEFINE(HOST_IP, EIP);
-	DEFINE(HOST_SP, UESP);
-	DEFINE(HOST_EFLAGS, EFL);
-	DEFINE(HOST_EAX, EAX);
-	DEFINE(HOST_EBX, EBX);
-	DEFINE(HOST_ECX, ECX);
-	DEFINE(HOST_EDX, EDX);
-	DEFINE(HOST_ESI, ESI);
-	DEFINE(HOST_EDI, EDI);
-	DEFINE(HOST_EBP, EBP);
-	DEFINE(HOST_CS, CS);
-	DEFINE(HOST_SS, SS);
-	DEFINE(HOST_DS, DS);
-	DEFINE(HOST_FS, FS);
-	DEFINE(HOST_ES, ES);
-	DEFINE(HOST_GS, GS);
-	DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
-
-	/* XXX Duplicated between i386 and x86_64 */
-	DEFINE(UM_POLLIN, POLLIN);
-	DEFINE(UM_POLLPRI, POLLPRI);
-	DEFINE(UM_POLLOUT, POLLOUT);
-
-	DEFINE(UM_PROT_READ, PROT_READ);
-	DEFINE(UM_PROT_WRITE, PROT_WRITE);
-	DEFINE(UM_PROT_EXEC, PROT_EXEC);
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/asm/archparam.h linux-libre-3.2-gnu/arch/um/sys-x86_64/asm/archparam.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/asm/archparam.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/asm/archparam.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_ARCHPARAM_X86_64_H
-#define __UM_ARCHPARAM_X86_64_H
-
-
-/* No user-accessible fixmap addresses, i.e. vsyscall */
-#define FIXADDR_USER_START	0
-#define FIXADDR_USER_END	0
-
-#endif
-
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/asm/elf.h linux-libre-3.2-gnu/arch/um/sys-x86_64/asm/elf.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/asm/elf.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/asm/elf.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,132 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- *
- * Licensed under the GPL
- */
-#ifndef __UM_ELF_X86_64_H
-#define __UM_ELF_X86_64_H
-
-#include <asm/user.h>
-#include "skas.h"
-
-/* x86-64 relocation types, taken from asm-x86_64/elf.h */
-#define R_X86_64_NONE		0	/* No reloc */
-#define R_X86_64_64		1	/* Direct 64 bit  */
-#define R_X86_64_PC32		2	/* PC relative 32 bit signed */
-#define R_X86_64_GOT32		3	/* 32 bit GOT entry */
-#define R_X86_64_PLT32		4	/* 32 bit PLT address */
-#define R_X86_64_COPY		5	/* Copy symbol at runtime */
-#define R_X86_64_GLOB_DAT	6	/* Create GOT entry */
-#define R_X86_64_JUMP_SLOT	7	/* Create PLT entry */
-#define R_X86_64_RELATIVE	8	/* Adjust by program base */
-#define R_X86_64_GOTPCREL	9	/* 32 bit signed pc relative
-					   offset to GOT */
-#define R_X86_64_32		10	/* Direct 32 bit zero extended */
-#define R_X86_64_32S		11	/* Direct 32 bit sign extended */
-#define R_X86_64_16		12	/* Direct 16 bit zero extended */
-#define R_X86_64_PC16		13	/* 16 bit sign extended pc relative */
-#define R_X86_64_8		14	/* Direct 8 bit sign extended  */
-#define R_X86_64_PC8		15	/* 8 bit sign extended pc relative */
-
-#define R_X86_64_NUM		16
-
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct user_i387_struct elf_fpregset_t;
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) \
-	((x)->e_machine == EM_X86_64)
-
-#define ELF_CLASS	ELFCLASS64
-#define ELF_DATA        ELFDATA2LSB
-#define ELF_ARCH        EM_X86_64
-
-#define ELF_PLAT_INIT(regs, load_addr)    do { \
-	PT_REGS_RBX(regs) = 0; \
-	PT_REGS_RCX(regs) = 0; \
-	PT_REGS_RDX(regs) = 0; \
-	PT_REGS_RSI(regs) = 0; \
-	PT_REGS_RDI(regs) = 0; \
-	PT_REGS_RBP(regs) = 0; \
-	PT_REGS_RAX(regs) = 0; \
-	PT_REGS_R8(regs) = 0; \
-	PT_REGS_R9(regs) = 0; \
-	PT_REGS_R10(regs) = 0; \
-	PT_REGS_R11(regs) = 0; \
-	PT_REGS_R12(regs) = 0; \
-	PT_REGS_R13(regs) = 0; \
-	PT_REGS_R14(regs) = 0; \
-	PT_REGS_R15(regs) = 0; \
-} while (0)
-
-#define ELF_CORE_COPY_REGS(pr_reg, _regs)		\
-	(pr_reg)[0] = (_regs)->regs.gp[0];			\
-	(pr_reg)[1] = (_regs)->regs.gp[1];			\
-	(pr_reg)[2] = (_regs)->regs.gp[2];			\
-	(pr_reg)[3] = (_regs)->regs.gp[3];			\
-	(pr_reg)[4] = (_regs)->regs.gp[4];			\
-	(pr_reg)[5] = (_regs)->regs.gp[5];			\
-	(pr_reg)[6] = (_regs)->regs.gp[6];			\
-	(pr_reg)[7] = (_regs)->regs.gp[7];			\
-	(pr_reg)[8] = (_regs)->regs.gp[8];			\
-	(pr_reg)[9] = (_regs)->regs.gp[9];			\
-	(pr_reg)[10] = (_regs)->regs.gp[10];			\
-	(pr_reg)[11] = (_regs)->regs.gp[11];			\
-	(pr_reg)[12] = (_regs)->regs.gp[12];			\
-	(pr_reg)[13] = (_regs)->regs.gp[13];			\
-	(pr_reg)[14] = (_regs)->regs.gp[14];			\
-	(pr_reg)[15] = (_regs)->regs.gp[15];			\
-	(pr_reg)[16] = (_regs)->regs.gp[16];			\
-	(pr_reg)[17] = (_regs)->regs.gp[17];			\
-	(pr_reg)[18] = (_regs)->regs.gp[18];			\
-	(pr_reg)[19] = (_regs)->regs.gp[19];			\
-	(pr_reg)[20] = (_regs)->regs.gp[20];			\
-	(pr_reg)[21] = current->thread.arch.fs;			\
-	(pr_reg)[22] = 0;					\
-	(pr_reg)[23] = 0;					\
-	(pr_reg)[24] = 0;					\
-	(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);
-
-#define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu)
-
-#ifdef TIF_IA32 /* XXX */
-#error XXX, indeed
-        clear_thread_flag(TIF_IA32);
-#endif
-
-#define ELF_EXEC_PAGESIZE 4096
-
-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
-
-extern long elf_aux_hwcap;
-#define ELF_HWCAP (elf_aux_hwcap)
-
-#define ELF_PLATFORM "x86_64"
-
-#define SET_PERSONALITY(ex) do ; while(0)
-
-#define __HAVE_ARCH_GATE_AREA 1
-#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
-struct linux_binprm;
-extern int arch_setup_additional_pages(struct linux_binprm *bprm,
-	int uses_interp);
-
-extern unsigned long um_vdso_addr;
-#define AT_SYSINFO_EHDR 33
-#define ARCH_DLINFO	NEW_AUX_ENT(AT_SYSINFO_EHDR, um_vdso_addr)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/asm/module.h linux-libre-3.2-gnu/arch/um/sys-x86_64/asm/module.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/asm/module.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/asm/module.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_MODULE_X86_64_H
-#define __UM_MODULE_X86_64_H
-
-/* UML is simple */
-struct mod_arch_specific
-{
-};
-
-#define Elf_Shdr Elf64_Shdr
-#define Elf_Sym Elf64_Sym
-#define Elf_Ehdr Elf64_Ehdr
-
-#endif
-
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/asm/processor.h linux-libre-3.2-gnu/arch/um/sys-x86_64/asm/processor.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/asm/processor.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/asm/processor.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_PROCESSOR_X86_64_H
-#define __UM_PROCESSOR_X86_64_H
-
-/* include faultinfo structure */
-#include "sysdep/faultinfo.h"
-
-struct arch_thread {
-        unsigned long debugregs[8];
-        int debugregs_seq;
-        unsigned long fs;
-        struct faultinfo faultinfo;
-};
-
-/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
-static inline void rep_nop(void)
-{
-	__asm__ __volatile__("rep;nop": : :"memory");
-}
-
-#define cpu_relax()   rep_nop()
-
-#define INIT_ARCH_THREAD { .debugregs  		= { [ 0 ... 7 ] = 0 }, \
-			   .debugregs_seq	= 0, \
-			   .fs			= 0, \
-			   .faultinfo		= { 0, 0, 0 } }
-
-static inline void arch_flush_thread(struct arch_thread *thread)
-{
-}
-
-static inline void arch_copy_thread(struct arch_thread *from,
-                                    struct arch_thread *to)
-{
-	to->fs = from->fs;
-}
-
-#include <asm/user.h>
-
-#define current_text_addr() \
-	({ void *pc; __asm__("movq $1f,%0\n1:":"=g" (pc)); pc; })
-
-#define ARCH_IS_STACKGROW(address) \
-        (address + 128 >= UPT_SP(&current->thread.regs.regs))
-
-#define KSTK_EIP(tsk) KSTK_REG(tsk, RIP)
-#define KSTK_ESP(tsk) KSTK_REG(tsk, RSP)
-
-#include "asm/processor-generic.h"
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/asm/ptrace.h linux-libre-3.2-gnu/arch/um/sys-x86_64/asm/ptrace.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/asm/ptrace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/asm/ptrace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,72 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_PTRACE_X86_64_H
-#define __UM_PTRACE_X86_64_H
-
-#include "linux/compiler.h"
-#include "asm/errno.h"
-
-#define __FRAME_OFFSETS /* Needed to get the R* macros */
-#include "asm/ptrace-generic.h"
-
-#define HOST_AUDIT_ARCH AUDIT_ARCH_X86_64
-
-#define PT_REGS_RBX(r) UPT_RBX(&(r)->regs)
-#define PT_REGS_RCX(r) UPT_RCX(&(r)->regs)
-#define PT_REGS_RDX(r) UPT_RDX(&(r)->regs)
-#define PT_REGS_RSI(r) UPT_RSI(&(r)->regs)
-#define PT_REGS_RDI(r) UPT_RDI(&(r)->regs)
-#define PT_REGS_RBP(r) UPT_RBP(&(r)->regs)
-#define PT_REGS_RAX(r) UPT_RAX(&(r)->regs)
-#define PT_REGS_R8(r) UPT_R8(&(r)->regs)
-#define PT_REGS_R9(r) UPT_R9(&(r)->regs)
-#define PT_REGS_R10(r) UPT_R10(&(r)->regs)
-#define PT_REGS_R11(r) UPT_R11(&(r)->regs)
-#define PT_REGS_R12(r) UPT_R12(&(r)->regs)
-#define PT_REGS_R13(r) UPT_R13(&(r)->regs)
-#define PT_REGS_R14(r) UPT_R14(&(r)->regs)
-#define PT_REGS_R15(r) UPT_R15(&(r)->regs)
-
-#define PT_REGS_FS(r) UPT_FS(&(r)->regs)
-#define PT_REGS_GS(r) UPT_GS(&(r)->regs)
-#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
-#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
-#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
-#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
-
-#define PT_REGS_ORIG_RAX(r) UPT_ORIG_RAX(&(r)->regs)
-#define PT_REGS_RIP(r) UPT_IP(&(r)->regs)
-#define PT_REGS_RSP(r) UPT_SP(&(r)->regs)
-
-#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
-
-/* XXX */
-#define user_mode(r) UPT_IS_USER(&(r)->regs)
-#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_RAX(r)
-#define PT_REGS_SYSCALL_RET(r) PT_REGS_RAX(r)
-
-#define PT_FIX_EXEC_STACK(sp) do ; while(0)
-
-#define profile_pc(regs) PT_REGS_IP(regs)
-
-struct user_desc;
-
-static inline int ptrace_get_thread_area(struct task_struct *child, int idx,
-                                         struct user_desc __user *user_desc)
-{
-        return -ENOSYS;
-}
-
-static inline int ptrace_set_thread_area(struct task_struct *child, int idx,
-                                         struct user_desc __user *user_desc)
-{
-        return -ENOSYS;
-}
-
-extern long arch_prctl(struct task_struct *task, int code,
-		       unsigned long __user *addr);
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/bug.c linux-libre-3.2-gnu/arch/um/sys-x86_64/bug.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/bug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/bug.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL V2
- */
-
-#include <linux/uaccess.h>
-
-/*
- * Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
- * that's not relevant in skas mode.
- */
-
-int is_valid_bugaddr(unsigned long eip)
-{
-	unsigned short ud2;
-
-	if (probe_kernel_address((unsigned short __user *)eip, ud2))
-		return 0;
-
-	return ud2 == 0x0b0f;
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/bugs.c linux-libre-3.2-gnu/arch/um/sys-x86_64/bugs.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/bugs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/bugs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include "sysdep/ptrace.h"
-
-void arch_check_bugs(void)
-{
-}
-
-void arch_examine_signal(int sig, struct uml_pt_regs *regs)
-{
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/delay.c linux-libre-3.2-gnu/arch/um/sys-x86_64/delay.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/delay.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/delay.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
- * Mostly copied from arch/x86/lib/delay.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/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <asm/param.h>
-
-void __delay(unsigned long loops)
-{
-	asm volatile(
-		"test %0,%0\n"
-		"jz 3f\n"
-		"jmp 1f\n"
-
-		".align 16\n"
-		"1: jmp 2f\n"
-
-		".align 16\n"
-		"2: dec %0\n"
-		" jnz 2b\n"
-		"3: dec %0\n"
-
-		: /* we don't need output */
-		: "a" (loops)
-	);
-}
-EXPORT_SYMBOL(__delay);
-
-inline void __const_udelay(unsigned long xloops)
-{
-	int d0;
-
-	xloops *= 4;
-	asm("mull %%edx"
-		: "=d" (xloops), "=&a" (d0)
-		: "1" (xloops), "0"
-		(loops_per_jiffy * (HZ/4)));
-
-	__delay(++xloops);
-}
-EXPORT_SYMBOL(__const_udelay);
-
-void __udelay(unsigned long usecs)
-{
-	__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
-}
-EXPORT_SYMBOL(__udelay);
-
-void __ndelay(unsigned long nsecs)
-{
-	__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
-}
-EXPORT_SYMBOL(__ndelay);
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/fault.c linux-libre-3.2-gnu/arch/um/sys-x86_64/fault.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/fault.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/fault.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include "sysdep/ptrace.h"
-
-/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
-struct exception_table_entry
-{
-	unsigned long insn;
-	unsigned long fixup;
-};
-
-const struct exception_table_entry *search_exception_tables(unsigned long add);
-
-int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
-{
-	const struct exception_table_entry *fixup;
-
-	fixup = search_exception_tables(address);
-	if (fixup != 0) {
-		UPT_IP(regs) = fixup->fixup;
-		return 1;
-	}
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/ksyms.c linux-libre-3.2-gnu/arch/um/sys-x86_64/ksyms.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/ksyms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/ksyms.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,11 +0,0 @@
-#include <linux/module.h>
-#include <asm/string.h>
-#include <asm/checksum.h>
-
-/*XXX: we need them because they would be exported by x86_64 */
-#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
-EXPORT_SYMBOL(memcpy);
-#else
-EXPORT_SYMBOL(__memcpy);
-#endif
-EXPORT_SYMBOL(csum_partial);
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/Makefile linux-libre-3.2-gnu/arch/um/sys-x86_64/Makefile
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-#
-# Copyright 2003 PathScale, Inc.
-#
-# Licensed under the GPL
-#
-
-obj-y = bug.o bugs.o delay.o fault.o ldt.o ptrace.o ptrace_user.o mem.o \
-	setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \
-	sysrq.o ksyms.o tls.o
-
-obj-y += vdso/
-
-subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o \
-		lib/rwsem.o
-subarch-obj-$(CONFIG_MODULES) += kernel/module.o
-
-ldt-y = ../sys-i386/ldt.o
-
-USER_OBJS := ptrace_user.o
-
-USER_OBJS += user-offsets.s
-extra-y += user-offsets.s
-
-UNPROFILE_OBJS := stub_segv.o
-CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
-
-include arch/um/scripts/Makefile.rules
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/mem.c linux-libre-3.2-gnu/arch/um/sys-x86_64/mem.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/mem.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-#include "linux/mm.h"
-#include "asm/page.h"
-#include "asm/mman.h"
-
-const char *arch_vma_name(struct vm_area_struct *vma)
-{
-	if (vma->vm_mm && vma->vm_start == um_vdso_addr)
-		return "[vdso]";
-
-	return NULL;
-}
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
-	return NULL;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
-	return 0;
-}
-
-int in_gate_area_no_mm(unsigned long addr)
-{
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/ptrace.c linux-libre-3.2-gnu/arch/um/sys-x86_64/ptrace.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/ptrace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/ptrace.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,198 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- *
- * Licensed under the GPL
- */
-
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#define __FRAME_OFFSETS
-#include <asm/ptrace.h>
-#include <asm/uaccess.h>
-
-/*
- * determines which flags the user has access to.
- * 1 = access 0 = no access
- */
-#define FLAG_MASK 0x44dd5UL
-
-int putreg(struct task_struct *child, int regno, unsigned long value)
-{
-	unsigned long tmp;
-
-#ifdef TIF_IA32
-	/*
-	 * Some code in the 64bit emulation may not be 64bit clean.
-	 * Don't take any chances.
-	 */
-	if (test_tsk_thread_flag(child, TIF_IA32))
-		value &= 0xffffffff;
-#endif
-	switch (regno) {
-	case FS:
-	case GS:
-	case DS:
-	case ES:
-	case SS:
-	case CS:
-		if (value && (value & 3) != 3)
-			return -EIO;
-		value &= 0xffff;
-		break;
-
-	case FS_BASE:
-	case GS_BASE:
-		if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
-			return -EIO;
-		break;
-
-	case EFLAGS:
-		value &= FLAG_MASK;
-		tmp = PT_REGS_EFLAGS(&child->thread.regs) & ~FLAG_MASK;
-		value |= tmp;
-		break;
-	}
-
-	PT_REGS_SET(&child->thread.regs, regno, value);
-	return 0;
-}
-
-int poke_user(struct task_struct *child, long addr, long data)
-{
-	if ((addr & 3) || addr < 0)
-		return -EIO;
-
-	if (addr < MAX_REG_OFFSET)
-		return putreg(child, addr, data);
-	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
-		(addr <= offsetof(struct user, u_debugreg[7]))) {
-		addr -= offsetof(struct user, u_debugreg[0]);
-		addr = addr >> 2;
-		if ((addr == 4) || (addr == 5))
-			return -EIO;
-		child->thread.arch.debugregs[addr] = data;
-		return 0;
-	}
-	return -EIO;
-}
-
-unsigned long getreg(struct task_struct *child, int regno)
-{
-	unsigned long retval = ~0UL;
-	switch (regno) {
-	case FS:
-	case GS:
-	case DS:
-	case ES:
-	case SS:
-	case CS:
-		retval = 0xffff;
-		/* fall through */
-	default:
-		retval &= PT_REG(&child->thread.regs, regno);
-#ifdef TIF_IA32
-		if (test_tsk_thread_flag(child, TIF_IA32))
-			retval &= 0xffffffff;
-#endif
-	}
-	return retval;
-}
-
-int peek_user(struct task_struct *child, long addr, long data)
-{
-	/* read the word at location addr in the USER area. */
-	unsigned long tmp;
-
-	if ((addr & 3) || addr < 0)
-		return -EIO;
-
-	tmp = 0;  /* Default return condition */
-	if (addr < MAX_REG_OFFSET)
-		tmp = getreg(child, addr);
-	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
-		(addr <= offsetof(struct user, u_debugreg[7]))) {
-		addr -= offsetof(struct user, u_debugreg[0]);
-		addr = addr >> 2;
-		tmp = child->thread.arch.debugregs[addr];
-	}
-	return put_user(tmp, (unsigned long *) data);
-}
-
-/* XXX Mostly copied from sys-i386 */
-int is_syscall(unsigned long addr)
-{
-	unsigned short instr;
-	int n;
-
-	n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
-	if (n) {
-		/*
-		 * access_process_vm() grants access to vsyscall and stub,
-		 * while copy_from_user doesn't. Maybe access_process_vm is
-		 * slow, but that doesn't matter, since it will be called only
-		 * in case of singlestepping, if copy_from_user failed.
-		 */
-		n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
-		if (n != sizeof(instr)) {
-			printk("is_syscall : failed to read instruction from "
-			       "0x%lx\n", addr);
-			return 1;
-		}
-	}
-	/* sysenter */
-	return instr == 0x050f;
-}
-
-static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
-	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
-	long fpregs[HOST_FP_SIZE];
-
-	BUG_ON(sizeof(*buf) != sizeof(fpregs));
-	err = save_fp_registers(userspace_pid[cpu], fpregs);
-	if (err)
-		return err;
-
-	n = copy_to_user(buf, fpregs, sizeof(fpregs));
-	if (n > 0)
-		return -EFAULT;
-
-	return n;
-}
-
-static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
-	int n, cpu = ((struct thread_info *) child->stack)->cpu;
-	long fpregs[HOST_FP_SIZE];
-
-	BUG_ON(sizeof(*buf) != sizeof(fpregs));
-	n = copy_from_user(fpregs, buf, sizeof(fpregs));
-	if (n > 0)
-		return -EFAULT;
-
-	return restore_fp_registers(userspace_pid[cpu], fpregs);
-}
-
-long subarch_ptrace(struct task_struct *child, long request,
-		    unsigned long addr, unsigned long data)
-{
-	int ret = -EIO;
-	void __user *datap = (void __user *) data;
-
-	switch (request) {
-	case PTRACE_GETFPREGS: /* Get the child FPU state. */
-		ret = get_fpregs(datap, child);
-		break;
-	case PTRACE_SETFPREGS: /* Set the child FPU state. */
-		ret = set_fpregs(datap, child);
-		break;
-	case PTRACE_ARCH_PRCTL:
-		/* XXX Calls ptrace on the host - needs some SMP thinking */
-		ret = arch_prctl(child, data, (void __user *) addr);
-		break;
-	}
-
-	return ret;
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/ptrace_user.c linux-libre-3.2-gnu/arch/um/sys-x86_64/ptrace_user.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/ptrace_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/ptrace_user.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include <errno.h>
-#include "ptrace_user.h"
-
-int ptrace_getregs(long pid, unsigned long *regs_out)
-{
-	if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
-		return -errno;
-	return(0);
-}
-
-int ptrace_setregs(long pid, unsigned long *regs_out)
-{
-	if (ptrace(PTRACE_SETREGS, pid, 0, regs_out) < 0)
-		return -errno;
-	return(0);
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/setjmp.S linux-libre-3.2-gnu/arch/um/sys-x86_64/setjmp.S
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/setjmp.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/setjmp.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,54 +0,0 @@
-#
-# arch/x86_64/setjmp.S
-#
-# setjmp/longjmp for the x86-64 architecture
-#
-
-#
-# The jmp_buf is assumed to contain the following, in order:
-#	%rbx
-#	%rsp (post-return)
-#	%rbp
-#	%r12
-#	%r13
-#	%r14
-#	%r15
-#	<return address>
-#
-
-	.text
-	.align 4
-	.globl setjmp
-	.type setjmp, @function
-setjmp:
-	pop  %rsi			# Return address, and adjust the stack
-	xorl %eax,%eax			# Return value
-	movq %rbx,(%rdi)
-	movq %rsp,8(%rdi)		# Post-return %rsp!
-	push %rsi			# Make the call/return stack happy
-	movq %rbp,16(%rdi)
-	movq %r12,24(%rdi)
-	movq %r13,32(%rdi)
-	movq %r14,40(%rdi)
-	movq %r15,48(%rdi)
-	movq %rsi,56(%rdi)		# Return address
-	ret
-
-	.size setjmp,.-setjmp
-
-	.text
-	.align 4
-	.globl longjmp
-	.type longjmp, @function
-longjmp:
-	movl %esi,%eax			# Return value (int)
-	movq (%rdi),%rbx
-	movq 8(%rdi),%rsp
-	movq 16(%rdi),%rbp
-	movq 24(%rdi),%r12
-	movq 32(%rdi),%r13
-	movq 40(%rdi),%r14
-	movq 48(%rdi),%r15
-	jmp *56(%rdi)
-
-	.size longjmp,.-longjmp
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/archsetjmp.h linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/archsetjmp.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/archsetjmp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/archsetjmp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,24 +0,0 @@
-/*
- * arch/um/include/sysdep-x86_64/archsetjmp.h
- */
-
-#ifndef _KLIBC_ARCHSETJMP_H
-#define _KLIBC_ARCHSETJMP_H
-
-struct __jmp_buf {
-	unsigned long __rbx;
-	unsigned long __rsp;
-	unsigned long __rbp;
-	unsigned long __r12;
-	unsigned long __r13;
-	unsigned long __r14;
-	unsigned long __r15;
-	unsigned long __rip;
-};
-
-typedef struct __jmp_buf jmp_buf[1];
-
-#define JB_IP __rip
-#define JB_SP __rsp
-
-#endif				/* _SETJMP_H */
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/barrier.h linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/barrier.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/barrier.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/barrier.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef __SYSDEP_X86_64_BARRIER_H
-#define __SYSDEP_X86_64_BARRIER_H
-
-/* Copied from include/asm-x86_64 for use by userspace. */
-#define mb() 	asm volatile("mfence":::"memory")
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/checksum.h linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/checksum.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/checksum.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/checksum.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,144 +0,0 @@
-/*
- * Licensed under the GPL
- */
-
-#ifndef __UM_SYSDEP_CHECKSUM_H
-#define __UM_SYSDEP_CHECKSUM_H
-
-#include "linux/string.h"
-#include "linux/in6.h"
-#include "asm/uaccess.h"
-
-extern __wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- *	Note: when you get a NULL pointer exception here this means someone
- *	passed in an incorrect kernel address to one of these functions.
- *
- *	If you use these functions directly please don't forget the
- *	access_ok().
- */
-
-static __inline__
-__wsum csum_partial_copy_nocheck(const void *src, void *dst,
-				       int len, __wsum sum)
-{
-	memcpy(dst, src, len);
-	return(csum_partial(dst, len, sum));
-}
-
-static __inline__
-__wsum csum_partial_copy_from_user(const void __user *src,
-                                         void *dst, int len, __wsum sum,
-                                         int *err_ptr)
-{
-        if (copy_from_user(dst, src, len)) {
-                *err_ptr = -EFAULT;
-                return (__force __wsum)-1;
-        }
-        return csum_partial(dst, len, sum);
-}
-
-/**
- * csum_fold - Fold and invert a 32bit checksum.
- * sum: 32bit unfolded sum
- *
- * Fold a 32bit running checksum to 16bit and invert it. This is usually
- * the last step before putting a checksum into a packet.
- * Make sure not to mix with 64bit checksums.
- */
-static inline __sum16 csum_fold(__wsum sum)
-{
-	__asm__(
-		"  addl %1,%0\n"
-		"  adcl $0xffff,%0"
-		: "=r" (sum)
-		: "r" ((__force u32)sum << 16),
-		  "0" ((__force u32)sum & 0xffff0000)
-	);
-	return (__force __sum16)(~(__force u32)sum >> 16);
-}
-
-/**
- * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.
- * @saddr: source address
- * @daddr: destination address
- * @len: length of packet
- * @proto: ip protocol of packet
- * @sum: initial sum to be added in (32bit unfolded)
- *
- * Returns the pseudo header checksum the input data. Result is
- * 32bit unfolded.
- */
-static inline __wsum
-csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
-		   unsigned short proto, __wsum sum)
-{
-	asm("  addl %1, %0\n"
-	    "  adcl %2, %0\n"
-	    "  adcl %3, %0\n"
-	    "  adcl $0, %0\n"
-		: "=r" (sum)
-	    : "g" (daddr), "g" (saddr), "g" ((len + proto) << 8), "0" (sum));
-	return sum;
-}
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
-					   unsigned short len,
-					   unsigned short proto,
-					   __wsum sum)
-{
-	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-/**
- * ip_fast_csum - Compute the IPv4 header checksum efficiently.
- * iph: ipv4 header
- * ihl: length of header / 4
- */
-static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
-	unsigned int sum;
-
-	asm(	"  movl (%1), %0\n"
-		"  subl $4, %2\n"
-		"  jbe 2f\n"
-		"  addl 4(%1), %0\n"
-		"  adcl 8(%1), %0\n"
-		"  adcl 12(%1), %0\n"
-		"1: adcl 16(%1), %0\n"
-		"  lea 4(%1), %1\n"
-		"  decl %2\n"
-		"  jne	1b\n"
-		"  adcl $0, %0\n"
-		"  movl %0, %2\n"
-		"  shrl $16, %0\n"
-		"  addw %w2, %w0\n"
-		"  adcl $0, %0\n"
-		"  notl %0\n"
-		"2:"
-	/* Since the input registers which are loaded with iph and ipl
-	   are modified, we must also specify them as outputs, or gcc
-	   will assume they contain their original values. */
-	: "=r" (sum), "=r" (iph), "=r" (ihl)
-	: "1" (iph), "2" (ihl)
-	: "memory");
-	return (__force __sum16)sum;
-}
-
-static inline unsigned add32_with_carry(unsigned a, unsigned b)
-{
-        asm("addl %2,%0\n\t"
-            "adcl $0,%0"
-            : "=r" (a)
-            : "0" (a), "r" (b));
-        return a;
-}
-
-extern __sum16 ip_compute_csum(const void *buff, int len);
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/faultinfo.h linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/faultinfo.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/faultinfo.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/faultinfo.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
- * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
- * Licensed under the GPL
- */
-
-#ifndef __FAULTINFO_X86_64_H
-#define __FAULTINFO_X86_64_H
-
-/* this structure contains the full arch-specific faultinfo
- * from the traps.
- * On i386, ptrace_faultinfo unfortunately doesn't provide
- * all the info, since trap_no is missing.
- * All common elements are defined at the same position in
- * both structures, thus making it easy to copy the
- * contents without knowledge about the structure elements.
- */
-struct faultinfo {
-        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
-        unsigned long cr2; /* in ptrace_faultinfo called addr */
-        int trap_no; /* missing in ptrace_faultinfo */
-};
-
-#define FAULT_WRITE(fi) ((fi).error_code & 2)
-#define FAULT_ADDRESS(fi) ((fi).cr2)
-
-#define PTRACE_FULL_FAULTINFO 1
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/host_ldt.h linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/host_ldt.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/host_ldt.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/host_ldt.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-#ifndef __ASM_HOST_LDT_X86_64_H
-#define __ASM_HOST_LDT_X86_64_H
-
-#include <asm/ldt.h>
-
-/*
- * macros stolen from include/asm-x86_64/desc.h
- */
-#define LDT_entry_a(info) \
-	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-
-/* Don't allow setting of the lm bit. It is useless anyways because
- * 64bit system calls require __USER_CS. */
-#define LDT_entry_b(info) \
-	(((info)->base_addr & 0xff000000) | \
-	(((info)->base_addr & 0x00ff0000) >> 16) | \
-	((info)->limit & 0xf0000) | \
-	(((info)->read_exec_only ^ 1) << 9) | \
-	((info)->contents << 10) | \
-	(((info)->seg_not_present ^ 1) << 15) | \
-	((info)->seg_32bit << 22) | \
-	((info)->limit_in_pages << 23) | \
-	((info)->useable << 20) | \
-	/* ((info)->lm << 21) | */ \
-	0x7000)
-
-#define LDT_empty(info) (\
-	(info)->base_addr	== 0	&& \
-	(info)->limit		== 0	&& \
-	(info)->contents	== 0	&& \
-	(info)->read_exec_only	== 1	&& \
-	(info)->seg_32bit	== 0	&& \
-	(info)->limit_in_pages	== 0	&& \
-	(info)->seg_not_present	== 1	&& \
-	(info)->useable		== 0	&& \
-	(info)->lm              == 0)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/elf.h>
-#include <linux/crypto.h>
-#include <asm/page.h>
-#include <asm/mman.h>
-
-#define DEFINE(sym, val) \
-	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define DEFINE_STR1(x) #x
-#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " DEFINE_STR1(val) " " #val: : )
-
-#define BLANK() asm volatile("\n->" : : )
-
-#define OFFSET(sym, str, mem) \
-	DEFINE(sym, offsetof(struct str, mem));
-
-void foo(void)
-{
-#include <common-offsets.h>
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/ptrace.h linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/ptrace.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/ptrace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/ptrace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,240 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- *
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_PTRACE_H
-#define __SYSDEP_X86_64_PTRACE_H
-
-#include "user_constants.h"
-#include "sysdep/faultinfo.h"
-
-#define MAX_REG_OFFSET (UM_FRAME_SIZE)
-#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
-
-#include "skas_ptregs.h"
-
-#define REGS_IP(r) ((r)[HOST_IP])
-#define REGS_SP(r) ((r)[HOST_SP])
-
-#define REGS_RBX(r) ((r)[HOST_RBX])
-#define REGS_RCX(r) ((r)[HOST_RCX])
-#define REGS_RDX(r) ((r)[HOST_RDX])
-#define REGS_RSI(r) ((r)[HOST_RSI])
-#define REGS_RDI(r) ((r)[HOST_RDI])
-#define REGS_RBP(r) ((r)[HOST_RBP])
-#define REGS_RAX(r) ((r)[HOST_RAX])
-#define REGS_R8(r) ((r)[HOST_R8])
-#define REGS_R9(r) ((r)[HOST_R9])
-#define REGS_R10(r) ((r)[HOST_R10])
-#define REGS_R11(r) ((r)[HOST_R11])
-#define REGS_R12(r) ((r)[HOST_R12])
-#define REGS_R13(r) ((r)[HOST_R13])
-#define REGS_R14(r) ((r)[HOST_R14])
-#define REGS_R15(r) ((r)[HOST_R15])
-#define REGS_CS(r) ((r)[HOST_CS])
-#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
-#define REGS_SS(r) ((r)[HOST_SS])
-
-#define HOST_FS_BASE 21
-#define HOST_GS_BASE 22
-#define HOST_DS 23
-#define HOST_ES 24
-#define HOST_FS 25
-#define HOST_GS 26
-
-/* Also defined in asm/ptrace-x86_64.h, but not in libc headers.  So, these
- * are already defined for kernel code, but not for userspace code.
- */
-#ifndef FS_BASE
-/* These aren't defined in ptrace.h, but exist in struct user_regs_struct,
- * which is what x86_64 ptrace actually uses.
- */
-#define FS_BASE (HOST_FS_BASE * sizeof(long))
-#define GS_BASE (HOST_GS_BASE * sizeof(long))
-#define DS (HOST_DS * sizeof(long))
-#define ES (HOST_ES * sizeof(long))
-#define FS (HOST_FS * sizeof(long))
-#define GS (HOST_GS * sizeof(long))
-#endif
-
-#define REGS_FS_BASE(r) ((r)[HOST_FS_BASE])
-#define REGS_GS_BASE(r) ((r)[HOST_GS_BASE])
-#define REGS_DS(r) ((r)[HOST_DS])
-#define REGS_ES(r) ((r)[HOST_ES])
-#define REGS_FS(r) ((r)[HOST_FS])
-#define REGS_GS(r) ((r)[HOST_GS])
-
-#define REGS_ORIG_RAX(r) ((r)[HOST_ORIG_RAX])
-
-#define REGS_SET_SYSCALL_RETURN(r, res) REGS_RAX(r) = (res)
-
-#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
-
-#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type)
-
-#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
-
-#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
-
-#define REGS_TRAP(r) ((r)->trap_type)
-
-#define REGS_ERR(r) ((r)->fault_type)
-
-struct uml_pt_regs {
-	unsigned long gp[MAX_REG_NR];
-	unsigned long fp[HOST_FP_SIZE];
-	struct faultinfo faultinfo;
-	long syscall;
-	int is_user;
-};
-
-#define EMPTY_UML_PT_REGS { }
-
-#define UPT_RBX(r) REGS_RBX((r)->gp)
-#define UPT_RCX(r) REGS_RCX((r)->gp)
-#define UPT_RDX(r) REGS_RDX((r)->gp)
-#define UPT_RSI(r) REGS_RSI((r)->gp)
-#define UPT_RDI(r) REGS_RDI((r)->gp)
-#define UPT_RBP(r) REGS_RBP((r)->gp)
-#define UPT_RAX(r) REGS_RAX((r)->gp)
-#define UPT_R8(r) REGS_R8((r)->gp)
-#define UPT_R9(r) REGS_R9((r)->gp)
-#define UPT_R10(r) REGS_R10((r)->gp)
-#define UPT_R11(r) REGS_R11((r)->gp)
-#define UPT_R12(r) REGS_R12((r)->gp)
-#define UPT_R13(r) REGS_R13((r)->gp)
-#define UPT_R14(r) REGS_R14((r)->gp)
-#define UPT_R15(r) REGS_R15((r)->gp)
-#define UPT_CS(r) REGS_CS((r)->gp)
-#define UPT_FS_BASE(r) REGS_FS_BASE((r)->gp)
-#define UPT_FS(r) REGS_FS((r)->gp)
-#define UPT_GS_BASE(r) REGS_GS_BASE((r)->gp)
-#define UPT_GS(r) REGS_GS((r)->gp)
-#define UPT_DS(r) REGS_DS((r)->gp)
-#define UPT_ES(r) REGS_ES((r)->gp)
-#define UPT_CS(r) REGS_CS((r)->gp)
-#define UPT_SS(r) REGS_SS((r)->gp)
-#define UPT_ORIG_RAX(r) REGS_ORIG_RAX((r)->gp)
-
-#define UPT_IP(r) REGS_IP((r)->gp)
-#define UPT_SP(r) REGS_SP((r)->gp)
-
-#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
-#define UPT_SYSCALL_NR(r) ((r)->syscall)
-#define UPT_SYSCALL_RET(r) UPT_RAX(r)
-
-extern int user_context(unsigned long sp);
-
-#define UPT_IS_USER(r) ((r)->is_user)
-
-#define UPT_SYSCALL_ARG1(r) UPT_RDI(r)
-#define UPT_SYSCALL_ARG2(r) UPT_RSI(r)
-#define UPT_SYSCALL_ARG3(r) UPT_RDX(r)
-#define UPT_SYSCALL_ARG4(r) UPT_R10(r)
-#define UPT_SYSCALL_ARG5(r) UPT_R8(r)
-#define UPT_SYSCALL_ARG6(r) UPT_R9(r)
-
-struct syscall_args {
-	unsigned long args[6];
-};
-
-#define SYSCALL_ARGS(r) ((struct syscall_args) \
-			 { .args = { UPT_SYSCALL_ARG1(r),	 \
-				     UPT_SYSCALL_ARG2(r),	 \
-				     UPT_SYSCALL_ARG3(r),	 \
-				     UPT_SYSCALL_ARG4(r),	 \
-				     UPT_SYSCALL_ARG5(r),	 \
-				     UPT_SYSCALL_ARG6(r) } } )
-
-#define UPT_REG(regs, reg) \
-	({      unsigned long val;		\
-		switch(reg){						\
-		case R8: val = UPT_R8(regs); break;			\
-		case R9: val = UPT_R9(regs); break;			\
-		case R10: val = UPT_R10(regs); break;			\
-		case R11: val = UPT_R11(regs); break;			\
-		case R12: val = UPT_R12(regs); break;			\
-		case R13: val = UPT_R13(regs); break;			\
-		case R14: val = UPT_R14(regs); break;			\
-		case R15: val = UPT_R15(regs); break;			\
-		case RIP: val = UPT_IP(regs); break;			\
-		case RSP: val = UPT_SP(regs); break;			\
-		case RAX: val = UPT_RAX(regs); break;			\
-		case RBX: val = UPT_RBX(regs); break;			\
-		case RCX: val = UPT_RCX(regs); break;			\
-		case RDX: val = UPT_RDX(regs); break;			\
-		case RSI: val = UPT_RSI(regs); break;			\
-		case RDI: val = UPT_RDI(regs); break;			\
-		case RBP: val = UPT_RBP(regs); break;			\
-		case ORIG_RAX: val = UPT_ORIG_RAX(regs); break;		\
-		case CS: val = UPT_CS(regs); break;			\
-		case SS: val = UPT_SS(regs); break;			\
-		case FS_BASE: val = UPT_FS_BASE(regs); break;		\
-		case GS_BASE: val = UPT_GS_BASE(regs); break;		\
-		case DS: val = UPT_DS(regs); break;			\
-		case ES: val = UPT_ES(regs); break;			\
-		case FS : val = UPT_FS (regs); break;			\
-		case GS: val = UPT_GS(regs); break;			\
-		case EFLAGS: val = UPT_EFLAGS(regs); break;		\
-		default :						\
-			panic("Bad register in UPT_REG : %d\n", reg);	\
-			val = -1;					\
-		}							\
-		val;							\
-	})
-
-
-#define UPT_SET(regs, reg, val) \
-	({      unsigned long __upt_val = val;	\
-		switch(reg){						\
-		case R8: UPT_R8(regs) = __upt_val; break;		\
-		case R9: UPT_R9(regs) = __upt_val; break;		\
-		case R10: UPT_R10(regs) = __upt_val; break;		\
-		case R11: UPT_R11(regs) = __upt_val; break;		\
-		case R12: UPT_R12(regs) = __upt_val; break;		\
-		case R13: UPT_R13(regs) = __upt_val; break;		\
-		case R14: UPT_R14(regs) = __upt_val; break;		\
-		case R15: UPT_R15(regs) = __upt_val; break;		\
-		case RIP: UPT_IP(regs) = __upt_val; break;		\
-		case RSP: UPT_SP(regs) = __upt_val; break;		\
-		case RAX: UPT_RAX(regs) = __upt_val; break;		\
-		case RBX: UPT_RBX(regs) = __upt_val; break;		\
-		case RCX: UPT_RCX(regs) = __upt_val; break;		\
-		case RDX: UPT_RDX(regs) = __upt_val; break;		\
-		case RSI: UPT_RSI(regs) = __upt_val; break;		\
-		case RDI: UPT_RDI(regs) = __upt_val; break;		\
-		case RBP: UPT_RBP(regs) = __upt_val; break;		\
-		case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break;	\
-		case CS: UPT_CS(regs) = __upt_val; break;		\
-		case SS: UPT_SS(regs) = __upt_val; break;		\
-		case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break;	\
-		case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break;	\
-		case DS: UPT_DS(regs) = __upt_val; break;		\
-		case ES: UPT_ES(regs) = __upt_val; break;		\
-		case FS: UPT_FS(regs) = __upt_val; break;		\
-		case GS: UPT_GS(regs) = __upt_val; break;		\
-		case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break;	\
-		default :						\
-			panic("Bad register in UPT_SET : %d\n", reg);	\
-			break;						\
-		}							\
-		__upt_val;						\
-	})
-
-#define UPT_SET_SYSCALL_RETURN(r, res) \
-	REGS_SET_SYSCALL_RETURN((r)->regs, (res))
-
-#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
-
-#define UPT_SEGV_IS_FIXABLE(r) REGS_SEGV_IS_FIXABLE(&r->skas)
-
-#define UPT_FAULTINFO(r) (&(r)->faultinfo)
-
-static inline void arch_init_registers(int pid)
-{
-}
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,77 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_PTRACE_USER_H__
-#define __SYSDEP_X86_64_PTRACE_USER_H__
-
-#define __FRAME_OFFSETS
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
-#include <asm/ptrace.h>
-#undef __FRAME_OFFSETS
-#include "user_constants.h"
-
-#define PT_INDEX(off) ((off) / sizeof(unsigned long))
-
-#define PT_SYSCALL_NR(regs) ((regs)[PT_INDEX(ORIG_RAX)])
-#define PT_SYSCALL_NR_OFFSET (ORIG_RAX)
-
-#define PT_SYSCALL_ARG1(regs) (((unsigned long *) (regs))[PT_INDEX(RDI)])
-#define PT_SYSCALL_ARG1_OFFSET (RDI)
-
-#define PT_SYSCALL_ARG2(regs) (((unsigned long *) (regs))[PT_INDEX(RSI)])
-#define PT_SYSCALL_ARG2_OFFSET (RSI)
-
-#define PT_SYSCALL_ARG3(regs) (((unsigned long *) (regs))[PT_INDEX(RDX)])
-#define PT_SYSCALL_ARG3_OFFSET (RDX)
-
-#define PT_SYSCALL_ARG4(regs) (((unsigned long *) (regs))[PT_INDEX(RCX)])
-#define PT_SYSCALL_ARG4_OFFSET (RCX)
-
-#define PT_SYSCALL_ARG5(regs) (((unsigned long *) (regs))[PT_INDEX(R8)])
-#define PT_SYSCALL_ARG5_OFFSET (R8)
-
-#define PT_SYSCALL_ARG6(regs) (((unsigned long *) (regs))[PT_INDEX(R9)])
-#define PT_SYSCALL_ARG6_OFFSET (R9)
-
-#define PT_SYSCALL_RET_OFFSET (RAX)
-
-#define PT_IP_OFFSET (RIP)
-#define PT_IP(regs) ((regs)[PT_INDEX(RIP)])
-
-#define PT_SP_OFFSET (RSP)
-#define PT_SP(regs) ((regs)[PT_INDEX(RSP)])
-
-#define PT_ORIG_RAX_OFFSET (ORIG_RAX)
-#define PT_ORIG_RAX(regs) ((regs)[PT_INDEX(ORIG_RAX)])
-
-/*
- * x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though
- * it's defined in the kernel's include/linux/ptrace.h. Additionally, use the
- * 2.4 name and value for 2.4 host compatibility.
- */
-#ifndef PTRACE_OLDSETOPTIONS
-#define PTRACE_OLDSETOPTIONS 21
-#endif
-
-/*
- * These are before the system call, so the system call number is RAX
- * rather than ORIG_RAX, and arg4 is R10 rather than RCX
- */
-#define REGS_SYSCALL_NR PT_INDEX(RAX)
-#define REGS_SYSCALL_ARG1 PT_INDEX(RDI)
-#define REGS_SYSCALL_ARG2 PT_INDEX(RSI)
-#define REGS_SYSCALL_ARG3 PT_INDEX(RDX)
-#define REGS_SYSCALL_ARG4 PT_INDEX(R10)
-#define REGS_SYSCALL_ARG5 PT_INDEX(R8)
-#define REGS_SYSCALL_ARG6 PT_INDEX(R9)
-
-#define REGS_IP_INDEX PT_INDEX(RIP)
-#define REGS_SP_INDEX PT_INDEX(RSP)
-
-#define FP_SIZE (HOST_FP_SIZE)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/sc.h linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/sc.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/sc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/sc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-#ifndef __SYSDEP_X86_64_SC_H
-#define __SYSDEP_X86_64_SC_H
-
-/* Copyright (C) 2003 - 2004 PathScale, Inc
- * Released under the GPL
- */
-
-#include <user_constants.h>
-
-#define SC_OFFSET(sc, field) \
-	 *((unsigned long *) &(((char *) (sc))[HOST_##field]))
-
-#define SC_RBX(sc) SC_OFFSET(sc, SC_RBX)
-#define SC_RCX(sc) SC_OFFSET(sc, SC_RCX)
-#define SC_RDX(sc) SC_OFFSET(sc, SC_RDX)
-#define SC_RSI(sc) SC_OFFSET(sc, SC_RSI)
-#define SC_RDI(sc) SC_OFFSET(sc, SC_RDI)
-#define SC_RBP(sc) SC_OFFSET(sc, SC_RBP)
-#define SC_RAX(sc) SC_OFFSET(sc, SC_RAX)
-#define SC_R8(sc) SC_OFFSET(sc, SC_R8)
-#define SC_R9(sc) SC_OFFSET(sc, SC_R9)
-#define SC_R10(sc) SC_OFFSET(sc, SC_R10)
-#define SC_R11(sc) SC_OFFSET(sc, SC_R11)
-#define SC_R12(sc) SC_OFFSET(sc, SC_R12)
-#define SC_R13(sc) SC_OFFSET(sc, SC_R13)
-#define SC_R14(sc) SC_OFFSET(sc, SC_R14)
-#define SC_R15(sc) SC_OFFSET(sc, SC_R15)
-#define SC_IP(sc) SC_OFFSET(sc, SC_IP)
-#define SC_SP(sc) SC_OFFSET(sc, SC_SP)
-#define SC_CR2(sc) SC_OFFSET(sc, SC_CR2)
-#define SC_ERR(sc) SC_OFFSET(sc, SC_ERR)
-#define SC_TRAPNO(sc) SC_OFFSET(sc, SC_TRAPNO)
-#define SC_CS(sc) SC_OFFSET(sc, SC_CS)
-#define SC_FS(sc) SC_OFFSET(sc, SC_FS)
-#define SC_GS(sc) SC_OFFSET(sc, SC_GS)
-#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS)
-#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK)
-#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
-#if 0
-#define SC_ORIG_RAX(sc) SC_OFFSET(sc, SC_ORIG_RAX)
-#define SC_DS(sc) SC_OFFSET(sc, SC_DS)
-#define SC_ES(sc) SC_OFFSET(sc, SC_ES)
-#endif
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/sigcontext.h linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/sigcontext.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/sigcontext.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/sigcontext.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_SIGCONTEXT_H
-#define __SYSDEP_X86_64_SIGCONTEXT_H
-
-#include <sysdep/sc.h>
-
-#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
-
-#define GET_FAULTINFO_FROM_SC(fi, sc) \
-	{ \
-		(fi).cr2 = SC_CR2(sc); \
-		(fi).error_code = SC_ERR(sc); \
-		(fi).trap_no = SC_TRAPNO(sc); \
-	}
-
-/* This is Page Fault */
-#define SEGV_IS_FIXABLE(fi)	((fi)->trap_no == 14)
-
-/* No broken SKAS API, which doesn't pass trap_no, here. */
-#define SEGV_MAYBE_FIXABLE(fi)	0
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_SKAS_PTRACE_H
-#define __SYSDEP_X86_64_SKAS_PTRACE_H
-
-struct ptrace_faultinfo {
-        int is_write;
-        unsigned long addr;
-};
-
-struct ptrace_ldt {
-        int func;
-        void *ptr;
-        unsigned long bytecount;
-};
-
-#define PTRACE_LDT 54
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/stub.h linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/stub.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/stub.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/stub.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_STUB_H
-#define __SYSDEP_STUB_H
-
-#include <sys/mman.h>
-#include <asm/unistd.h>
-#include <sysdep/ptrace_user.h>
-#include "as-layout.h"
-#include "stub-data.h"
-#include "kern_constants.h"
-
-extern void stub_segv_handler(int sig);
-extern void stub_clone_handler(void);
-
-#define STUB_SYSCALL_RET PT_INDEX(RAX)
-#define STUB_MMAP_NR __NR_mmap
-#define MMAP_OFFSET(o) (o)
-
-#define __syscall_clobber "r11","rcx","memory"
-#define __syscall "syscall"
-
-static inline long stub_syscall0(long syscall)
-{
-	long ret;
-
-	__asm__ volatile (__syscall
-		: "=a" (ret)
-		: "0" (syscall) : __syscall_clobber );
-
-	return ret;
-}
-
-static inline long stub_syscall2(long syscall, long arg1, long arg2)
-{
-	long ret;
-
-	__asm__ volatile (__syscall
-		: "=a" (ret)
-		: "0" (syscall), "D" (arg1), "S" (arg2) : __syscall_clobber );
-
-	return ret;
-}
-
-static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
-{
-	long ret;
-
-	__asm__ volatile (__syscall
-		: "=a" (ret)
-		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3)
-		: __syscall_clobber );
-
-	return ret;
-}
-
-static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
-				 long arg4)
-{
-	long ret;
-
-	__asm__ volatile ("movq %5,%%r10 ; " __syscall
-		: "=a" (ret)
-		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
-		  "g" (arg4)
-		: __syscall_clobber, "r10" );
-
-	return ret;
-}
-
-static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
-				 long arg4, long arg5)
-{
-	long ret;
-
-	__asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " __syscall
-		: "=a" (ret)
-		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
-		  "g" (arg4), "g" (arg5)
-		: __syscall_clobber, "r10", "r8" );
-
-	return ret;
-}
-
-static inline void trap_myself(void)
-{
-	__asm("int3");
-}
-
-static inline void remap_stack(long fd, unsigned long offset)
-{
-	__asm__ volatile ("movq %4,%%r10 ; movq %5,%%r8 ; "
-			  "movq %6, %%r9; " __syscall "; movq %7, %%rbx ; "
-			  "movq %%rax, (%%rbx)":
-			  : "a" (STUB_MMAP_NR), "D" (STUB_DATA),
-			    "S" (UM_KERN_PAGE_SIZE),
-			    "d" (PROT_READ | PROT_WRITE),
-                            "g" (MAP_FIXED | MAP_SHARED), "g" (fd),
-			    "g" (offset),
-			    "i" (&((struct stub_data *) STUB_DATA)->err)
-			  : __syscall_clobber, "r10", "r8", "r9" );
-}
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/syscalls.h linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/syscalls.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/syscalls.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/syscalls.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_SYSCALLS_H__
-#define __SYSDEP_X86_64_SYSCALLS_H__
-
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <kern_constants.h>
-
-typedef long syscall_handler_t(void);
-
-extern syscall_handler_t *sys_call_table[];
-
-#define EXECUTE_SYSCALL(syscall, regs) \
-	(((long (*)(long, long, long, long, long, long)) \
-	  (*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(&regs->regs), \
-		 		      UPT_SYSCALL_ARG2(&regs->regs), \
-				      UPT_SYSCALL_ARG3(&regs->regs), \
-				      UPT_SYSCALL_ARG4(&regs->regs), \
-				      UPT_SYSCALL_ARG5(&regs->regs), \
-				      UPT_SYSCALL_ARG6(&regs->regs)))
-
-extern long old_mmap(unsigned long addr, unsigned long len,
-		     unsigned long prot, unsigned long flags,
-		     unsigned long fd, unsigned long pgoff);
-extern syscall_handler_t sys_modify_ldt;
-extern syscall_handler_t sys_arch_prctl;
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/system.h linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/system.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/system.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,132 +0,0 @@
-#ifndef _ASM_X86_SYSTEM_H_
-#define _ASM_X86_SYSTEM_H_
-
-#include <asm/asm.h>
-#include <asm/segment.h>
-#include <asm/cpufeature.h>
-#include <asm/cmpxchg.h>
-#include <asm/nops.h>
-
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-
-/* entries in ARCH_DLINFO: */
-#ifdef CONFIG_IA32_EMULATION
-# define AT_VECTOR_SIZE_ARCH 2
-#else
-# define AT_VECTOR_SIZE_ARCH 1
-#endif
-
-extern unsigned long arch_align_stack(unsigned long sp);
-
-void default_idle(void);
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- */
-#ifdef CONFIG_X86_32
-/*
- * Some non-Intel clones support out of order store. wmb() ceases to be a
- * nop for these.
- */
-#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
-#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
-#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
-#else
-#define mb() 	asm volatile("mfence":::"memory")
-#define rmb()	asm volatile("lfence":::"memory")
-#define wmb()	asm volatile("sfence" ::: "memory")
-#endif
-
-/**
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier.  All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads.  This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies.  See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- *	CPU 0				CPU 1
- *
- *	b = 2;
- *	memory_barrier();
- *	p = &b;				q = p;
- *					read_barrier_depends();
- *					d = *q;
- * </programlisting>
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().  However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- *	CPU 0				CPU 1
- *
- *	a = 2;
- *	memory_barrier();
- *	b = 3;				y = b;
- *					read_barrier_depends();
- *					x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like this where there are no data dependencies.
- **/
-
-#define read_barrier_depends()	do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()	mb()
-#ifdef CONFIG_X86_PPRO_FENCE
-# define smp_rmb()	rmb()
-#else
-# define smp_rmb()	barrier()
-#endif
-#ifdef CONFIG_X86_OOSTORE
-# define smp_wmb() 	wmb()
-#else
-# define smp_wmb()	barrier()
-#endif
-#define smp_read_barrier_depends()	read_barrier_depends()
-#define set_mb(var, value) do { (void)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
-
-/*
- * Stop RDTSC speculation. This is needed when you need to use RDTSC
- * (or get_cycles or vread that possibly accesses the TSC) in a defined
- * code region.
- *
- * (Could use an alternative three way for this if there was one.)
- */
-static inline void rdtsc_barrier(void)
-{
-	alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
-	alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
-}
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/tls.h linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/tls.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/tls.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/tls.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-#ifndef _SYSDEP_TLS_H
-#define _SYSDEP_TLS_H
-
-# ifndef __KERNEL__
-
-/* Change name to avoid conflicts with the original one from <asm/ldt.h>, which
- * may be named user_desc (but in 2.4 and in header matching its API was named
- * modify_ldt_ldt_s). */
-
-typedef struct um_dup_user_desc {
-	unsigned int  entry_number;
-	unsigned int  base_addr;
-	unsigned int  limit;
-	unsigned int  seg_32bit:1;
-	unsigned int  contents:2;
-	unsigned int  read_exec_only:1;
-	unsigned int  limit_in_pages:1;
-	unsigned int  seg_not_present:1;
-	unsigned int  useable:1;
-	unsigned int  lm:1;
-} user_desc_t;
-
-# else /* __KERNEL__ */
-
-#  include <ldt.h>
-typedef struct user_desc user_desc_t;
-
-# endif /* __KERNEL__ */
-#endif /* _SYSDEP_TLS_H */
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/vm-flags.h linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/vm-flags.h
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/shared/sysdep/vm-flags.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/shared/sysdep/vm-flags.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Copyright 2003 PathScale, Inc.
- * Licensed under the GPL
- */
-
-#ifndef __VM_FLAGS_X86_64_H
-#define __VM_FLAGS_X86_64_H
-
-#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
-	VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-#define VM_STACK_DEFAULT_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \
-	VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/signal.c linux-libre-3.2-gnu/arch/um/sys-x86_64/signal.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/signal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/signal.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,290 +0,0 @@
-/*
- * Copyright (C) 2003 PathScale, Inc.
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <linux/personality.h>
-#include <linux/ptrace.h>
-#include <linux/kernel.h>
-#include <asm/unistd.h>
-#include <asm/uaccess.h>
-#include <asm/ucontext.h>
-#include "frame_kern.h"
-#include "skas.h"
-
-void copy_sc(struct uml_pt_regs *regs, void *from)
-{
-	struct sigcontext *sc = from;
-
-#define GETREG(regs, regno, sc, regname)				\
-	(regs)->gp[(regno) / sizeof(unsigned long)] = (sc)->regname
-
-	GETREG(regs, R8, sc, r8);
-	GETREG(regs, R9, sc, r9);
-	GETREG(regs, R10, sc, r10);
-	GETREG(regs, R11, sc, r11);
-	GETREG(regs, R12, sc, r12);
-	GETREG(regs, R13, sc, r13);
-	GETREG(regs, R14, sc, r14);
-	GETREG(regs, R15, sc, r15);
-	GETREG(regs, RDI, sc, di);
-	GETREG(regs, RSI, sc, si);
-	GETREG(regs, RBP, sc, bp);
-	GETREG(regs, RBX, sc, bx);
-	GETREG(regs, RDX, sc, dx);
-	GETREG(regs, RAX, sc, ax);
-	GETREG(regs, RCX, sc, cx);
-	GETREG(regs, RSP, sc, sp);
-	GETREG(regs, RIP, sc, ip);
-	GETREG(regs, EFLAGS, sc, flags);
-	GETREG(regs, CS, sc, cs);
-
-#undef GETREG
-}
-
-static int copy_sc_from_user(struct pt_regs *regs,
-			     struct sigcontext __user *from,
-			     struct _fpstate __user *fpp)
-{
-	struct user_i387_struct fp;
-	int err = 0;
-
-#define GETREG(regs, regno, sc, regname)				\
-	__get_user((regs)->regs.gp[(regno) / sizeof(unsigned long)],	\
-		   &(sc)->regname)
-
-	err |= GETREG(regs, R8, from, r8);
-	err |= GETREG(regs, R9, from, r9);
-	err |= GETREG(regs, R10, from, r10);
-	err |= GETREG(regs, R11, from, r11);
-	err |= GETREG(regs, R12, from, r12);
-	err |= GETREG(regs, R13, from, r13);
-	err |= GETREG(regs, R14, from, r14);
-	err |= GETREG(regs, R15, from, r15);
-	err |= GETREG(regs, RDI, from, di);
-	err |= GETREG(regs, RSI, from, si);
-	err |= GETREG(regs, RBP, from, bp);
-	err |= GETREG(regs, RBX, from, bx);
-	err |= GETREG(regs, RDX, from, dx);
-	err |= GETREG(regs, RAX, from, ax);
-	err |= GETREG(regs, RCX, from, cx);
-	err |= GETREG(regs, RSP, from, sp);
-	err |= GETREG(regs, RIP, from, ip);
-	err |= GETREG(regs, EFLAGS, from, flags);
-	err |= GETREG(regs, CS, from, cs);
-	if (err)
-		return 1;
-
-#undef GETREG
-
-	err = copy_from_user(&fp, fpp, sizeof(struct user_i387_struct));
-	if (err)
-		return 1;
-
-	err = restore_fp_registers(userspace_pid[current_thread_info()->cpu],
-				   (unsigned long *) &fp);
-	if (err < 0) {
-		printk(KERN_ERR "copy_sc_from_user - "
-		       "restore_fp_registers failed, errno = %d\n",
-		       -err);
-		return 1;
-	}
-
-	return 0;
-}
-
-static int copy_sc_to_user(struct sigcontext __user *to,
-			   struct _fpstate __user *to_fp, struct pt_regs *regs,
-			   unsigned long mask, unsigned long sp)
-{
-	struct faultinfo * fi = &current->thread.arch.faultinfo;
-	struct user_i387_struct fp;
-	int err = 0;
-
-	err |= __put_user(0, &to->gs);
-	err |= __put_user(0, &to->fs);
-
-#define PUTREG(regs, regno, sc, regname)				\
-	__put_user((regs)->regs.gp[(regno) / sizeof(unsigned long)],	\
-		   &(sc)->regname)
-
-	err |= PUTREG(regs, RDI, to, di);
-	err |= PUTREG(regs, RSI, to, si);
-	err |= PUTREG(regs, RBP, to, bp);
-	/*
-	 * Must use original RSP, which is passed in, rather than what's in
-	 * the pt_regs, because that's already been updated to point at the
-	 * signal frame.
-	 */
-	err |= __put_user(sp, &to->sp);
-	err |= PUTREG(regs, RBX, to, bx);
-	err |= PUTREG(regs, RDX, to, dx);
-	err |= PUTREG(regs, RCX, to, cx);
-	err |= PUTREG(regs, RAX, to, ax);
-	err |= PUTREG(regs, R8, to, r8);
-	err |= PUTREG(regs, R9, to, r9);
-	err |= PUTREG(regs, R10, to, r10);
-	err |= PUTREG(regs, R11, to, r11);
-	err |= PUTREG(regs, R12, to, r12);
-	err |= PUTREG(regs, R13, to, r13);
-	err |= PUTREG(regs, R14, to, r14);
-	err |= PUTREG(regs, R15, to, r15);
-	err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */
-
-	err |= __put_user(fi->cr2, &to->cr2);
-	err |= __put_user(fi->error_code, &to->err);
-	err |= __put_user(fi->trap_no, &to->trapno);
-
-	err |= PUTREG(regs, RIP, to, ip);
-	err |= PUTREG(regs, EFLAGS, to, flags);
-#undef PUTREG
-
-	err |= __put_user(mask, &to->oldmask);
-	if (err)
-		return 1;
-
-	err = save_fp_registers(userspace_pid[current_thread_info()->cpu],
-				(unsigned long *) &fp);
-	if (err < 0) {
-		printk(KERN_ERR "copy_sc_from_user - restore_fp_registers "
-		       "failed, errno = %d\n", -err);
-		return 1;
-	}
-
-	if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
-		return 1;
-
-	return err;
-}
-
-struct rt_sigframe
-{
-	char __user *pretcode;
-	struct ucontext uc;
-	struct siginfo info;
-	struct _fpstate fpstate;
-};
-
-int setup_signal_stack_si(unsigned long stack_top, int sig,
-			  struct k_sigaction *ka, struct pt_regs * regs,
-			  siginfo_t *info, sigset_t *set)
-{
-	struct rt_sigframe __user *frame;
-	unsigned long save_sp = PT_REGS_RSP(regs);
-	int err = 0;
-	struct task_struct *me = current;
-
-	frame = (struct rt_sigframe __user *)
-		round_down(stack_top - sizeof(struct rt_sigframe), 16);
-	/* Subtract 128 for a red zone and 8 for proper alignment */
-	frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);
-
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto out;
-
-	if (ka->sa.sa_flags & SA_SIGINFO) {
-		err |= copy_siginfo_to_user(&frame->info, info);
-		if (err)
-			goto out;
-	}
-
-	/*
-	 * Update SP now because the page fault handler refuses to extend
-	 * the stack if the faulting address is too far below the current
-	 * SP, which frame now certainly is.  If there's an error, the original
-	 * value is restored on the way out.
-	 * When writing the sigcontext to the stack, we have to write the
-	 * original value, so that's passed to copy_sc_to_user, which does
-	 * the right thing with it.
-	 */
-	PT_REGS_RSP(regs) = (unsigned long) frame;
-
-	/* Create the ucontext.  */
-	err |= __put_user(0, &frame->uc.uc_flags);
-	err |= __put_user(0, &frame->uc.uc_link);
-	err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-	err |= __put_user(sas_ss_flags(save_sp),
-			  &frame->uc.uc_stack.ss_flags);
-	err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
-	err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
-			       set->sig[0], save_sp);
-	err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate);
-	if (sizeof(*set) == 16) {
-		__put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
-		__put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
-	}
-	else
-		err |= __copy_to_user(&frame->uc.uc_sigmask, set,
-				      sizeof(*set));
-
-	/*
-	 * Set up to return from userspace.  If provided, use a stub
-	 * already in userspace.
-	 */
-	/* x86-64 should always use SA_RESTORER. */
-	if (ka->sa.sa_flags & SA_RESTORER)
-		err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
-	else
-		/* could use a vstub here */
-		goto restore_sp;
-
-	if (err)
-		goto restore_sp;
-
-	/* Set up registers for signal handler */
-	{
-		struct exec_domain *ed = current_thread_info()->exec_domain;
-		if (unlikely(ed && ed->signal_invmap && sig < 32))
-			sig = ed->signal_invmap[sig];
-	}
-
-	PT_REGS_RDI(regs) = sig;
-	/* In case the signal handler was declared without prototypes */
-	PT_REGS_RAX(regs) = 0;
-
-	/*
-	 * This also works for non SA_SIGINFO handlers because they expect the
-	 * next argument after the signal number on the stack.
-	 */
-	PT_REGS_RSI(regs) = (unsigned long) &frame->info;
-	PT_REGS_RDX(regs) = (unsigned long) &frame->uc;
-	PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler;
- out:
-	return err;
-
-restore_sp:
-	PT_REGS_RSP(regs) = save_sp;
-	return err;
-}
-
-long sys_rt_sigreturn(struct pt_regs *regs)
-{
-	unsigned long sp = PT_REGS_SP(&current->thread.regs);
-	struct rt_sigframe __user *frame =
-		(struct rt_sigframe __user *)(sp - 8);
-	struct ucontext __user *uc = &frame->uc;
-	sigset_t set;
-
-	if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
-		goto segfault;
-
-	sigdelsetmask(&set, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext,
-			      &frame->fpstate))
-		goto segfault;
-
-	/* Avoid ERESTART handling */
-	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
-	return PT_REGS_SYSCALL_RET(&current->thread.regs);
-
- segfault:
-	force_sig(SIGSEGV, current);
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/stub.S linux-libre-3.2-gnu/arch/um/sys-x86_64/stub.S
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/stub.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/stub.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,66 +0,0 @@
-#include "as-layout.h"
-
-	.globl syscall_stub
-.section .__syscall_stub, "ax"
-syscall_stub:
-	syscall
-	/* We don't have 64-bit constants, so this constructs the address
-	 * we need.
-	 */
-	movq	$(STUB_DATA >> 32), %rbx
-	salq	$32, %rbx
-	movq	$(STUB_DATA & 0xffffffff), %rcx
-	or	%rcx, %rbx
-	movq	%rax, (%rbx)
-	int3
-
-	.globl batch_syscall_stub
-batch_syscall_stub:
-	mov	$(STUB_DATA >> 32), %rbx
-	sal	$32, %rbx
-	mov	$(STUB_DATA & 0xffffffff), %rax
-	or	%rax, %rbx
-	/* load pointer to first operation */
-	mov	%rbx, %rsp
-	add	$0x10, %rsp
-again:
-	/* load length of additional data */
-	mov	0x0(%rsp), %rax
-
-	/* if(length == 0) : end of list */
-	/* write possible 0 to header */
-	mov	%rax, 8(%rbx)
-	cmp	$0, %rax
-	jz	done
-
-	/* save current pointer */
-	mov	%rsp, 8(%rbx)
-
-	/* skip additional data */
-	add	%rax, %rsp
-
-	/* load syscall-# */
-	pop	%rax
-
-	/* load syscall params */
-	pop	%rdi
-	pop	%rsi
-	pop	%rdx
-	pop	%r10
- 	pop	%r8
-	pop	%r9
-
-	/* execute syscall */
-	syscall
-
-	/* check return value */
-	pop	%rcx
-	cmp	%rcx, %rax
-	je	again
-
-done:
-	/* save return value */
-	mov	%rax, (%rbx)
-
-	/* stop */
-	int3
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/stub_segv.c linux-libre-3.2-gnu/arch/um/sys-x86_64/stub_segv.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/stub_segv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/stub_segv.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-#include "as-layout.h"
-#include "sysdep/stub.h"
-#include "sysdep/faultinfo.h"
-#include "sysdep/sigcontext.h"
-
-void __attribute__ ((__section__ (".__syscall_stub")))
-stub_segv_handler(int sig)
-{
-	struct ucontext *uc;
-
-	__asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :);
-	GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA),
-			      &uc->uc_mcontext);
-	trap_myself();
-}
-
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/syscalls.c linux-libre-3.2-gnu/arch/um/sys-x86_64/syscalls.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/syscalls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/syscalls.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include "linux/linkage.h"
-#include "linux/personality.h"
-#include "linux/utsname.h"
-#include "asm/prctl.h" /* XXX This should get the constants from libc */
-#include "asm/uaccess.h"
-#include "os.h"
-
-long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
-{
-	unsigned long *ptr = addr, tmp;
-	long ret;
-	int pid = task->mm->context.id.u.pid;
-
-	/*
-	 * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to
-	 * be safe), we need to call arch_prctl on the host because
-	 * setting %fs may result in something else happening (like a
-	 * GDT or thread.fs being set instead).  So, we let the host
-	 * fiddle the registers and thread struct and restore the
-	 * registers afterwards.
-	 *
-	 * So, the saved registers are stored to the process (this
-	 * needed because a stub may have been the last thing to run),
-	 * arch_prctl is run on the host, then the registers are read
-	 * back.
-	 */
-	switch (code) {
-	case ARCH_SET_FS:
-	case ARCH_SET_GS:
-		ret = restore_registers(pid, &current->thread.regs.regs);
-		if (ret)
-			return ret;
-		break;
-	case ARCH_GET_FS:
-	case ARCH_GET_GS:
-		/*
-		 * With these two, we read to a local pointer and
-		 * put_user it to the userspace pointer that we were
-		 * given.  If addr isn't valid (because it hasn't been
-		 * faulted in or is just bogus), we want put_user to
-		 * fault it in (or return -EFAULT) instead of having
-		 * the host return -EFAULT.
-		 */
-		ptr = &tmp;
-	}
-
-	ret = os_arch_prctl(pid, code, ptr);
-	if (ret)
-		return ret;
-
-	switch (code) {
-	case ARCH_SET_FS:
-		current->thread.arch.fs = (unsigned long) ptr;
-		ret = save_registers(pid, &current->thread.regs.regs);
-		break;
-	case ARCH_SET_GS:
-		ret = save_registers(pid, &current->thread.regs.regs);
-		break;
-	case ARCH_GET_FS:
-		ret = put_user(tmp, addr);
-		break;
-	case ARCH_GET_GS:
-		ret = put_user(tmp, addr);
-		break;
-	}
-
-	return ret;
-}
-
-long sys_arch_prctl(int code, unsigned long addr)
-{
-	return arch_prctl(current, code, (unsigned long __user *) addr);
-}
-
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
-	       void __user *parent_tid, void __user *child_tid)
-{
-	long ret;
-
-	if (!newsp)
-		newsp = UPT_SP(&current->thread.regs.regs);
-	current->thread.forking = 1;
-	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
-		      child_tid);
-	current->thread.forking = 0;
-	return ret;
-}
-
-void arch_switch_to(struct task_struct *to)
-{
-	if ((to->thread.arch.fs == 0) || (to->mm == NULL))
-		return;
-
-	arch_prctl(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/syscall_table.c linux-libre-3.2-gnu/arch/um/sys-x86_64/syscall_table.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/syscall_table.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/syscall_table.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-/*
- * System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
- * with some changes for UML.
- */
-
-#include <linux/linkage.h>
-#include <linux/sys.h>
-#include <linux/cache.h>
-#include <kern_constants.h>
-
-#define __NO_STUBS
-
-/*
- * Below you can see, in terms of #define's, the differences between the x86-64
- * and the UML syscall table.
- */
-
-/* Not going to be implemented by UML, since we have no hardware. */
-#define stub_iopl sys_ni_syscall
-#define sys_ioperm sys_ni_syscall
-
-/*
- * The UML TLS problem. Note that x86_64 does not implement this, so the below
- * is needed only for the ia32 compatibility.
- */
-
-/* On UML we call it this way ("old" means it's not mmap2) */
-#define sys_mmap old_mmap
-
-#define stub_clone sys_clone
-#define stub_fork sys_fork
-#define stub_vfork sys_vfork
-#define stub_execve sys_execve
-#define stub_rt_sigsuspend sys_rt_sigsuspend
-#define stub_sigaltstack sys_sigaltstack
-#define stub_rt_sigreturn sys_rt_sigreturn
-
-#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
-#undef _ASM_X86_UNISTD_64_H
-#include "../../x86/include/asm/unistd_64.h"
-
-#undef __SYSCALL
-#define __SYSCALL(nr, sym) [ nr ] = sym,
-#undef _ASM_X86_UNISTD_64_H
-
-typedef void (*sys_call_ptr_t)(void);
-
-extern void sys_ni_syscall(void);
-
-/*
- * We used to have a trick here which made sure that holes in the
- * x86_64 table were filled in with sys_ni_syscall, but a comment in
- * unistd_64.h says that holes aren't allowed, so the trick was
- * removed.
- * The trick looked like this
- *	[0 ... UM_NR_syscall_max] = &sys_ni_syscall
- * before including unistd_64.h - the later initializations overwrote
- * the sys_ni_syscall filler.
- */
-
-sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
-#include "../../x86/include/asm/unistd_64.h"
-};
-
-int syscall_table_size = sizeof(sys_call_table);
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/sysrq.c linux-libre-3.2-gnu/arch/um/sys-x86_64/sysrq.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/sysrq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/sysrq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/utsname.h>
-#include <asm/current.h>
-#include <asm/ptrace.h>
-#include "sysrq.h"
-
-void __show_regs(struct pt_regs *regs)
-{
-	printk("\n");
-	print_modules();
-	printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
-		current->comm, print_tainted(), init_utsname()->release);
-	printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff,
-	       PT_REGS_RIP(regs));
-	printk(KERN_INFO "RSP: %016lx  EFLAGS: %08lx\n", PT_REGS_RSP(regs),
-	       PT_REGS_EFLAGS(regs));
-	printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
-	       PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs));
-	printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
-	       PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs));
-	printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
-	       PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs));
-	printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
-	       PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs));
-	printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
-	       PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs));
-}
-
-void show_regs(struct pt_regs *regs)
-{
-	__show_regs(regs);
-	show_trace(current, (unsigned long *) &regs);
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/tls.c linux-libre-3.2-gnu/arch/um/sys-x86_64/tls.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/tls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/tls.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-#include "linux/sched.h"
-
-void clear_flushed_tls(struct task_struct *task)
-{
-}
-
-int arch_copy_tls(struct task_struct *t)
-{
-	/*
-	 * If CLONE_SETTLS is set, we need to save the thread id
-	 * (which is argument 5, child_tid, of clone) so it can be set
-	 * during context switches.
-	 */
-	t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)];
-
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/user-offsets.c linux-libre-3.2-gnu/arch/um/sys-x86_64/user-offsets.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/user-offsets.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/user-offsets.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-#include <stdio.h>
-#include <stddef.h>
-#include <signal.h>
-#include <sys/poll.h>
-#include <sys/mman.h>
-#include <sys/user.h>
-#define __FRAME_OFFSETS
-#include <asm/ptrace.h>
-#include <asm/types.h>
-
-#define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define DEFINE_LONGS(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
-
-#define OFFSET(sym, str, mem) \
-	DEFINE(sym, offsetof(struct str, mem));
-
-void foo(void)
-{
-	OFFSET(HOST_SC_CR2, sigcontext, cr2);
-	OFFSET(HOST_SC_ERR, sigcontext, err);
-	OFFSET(HOST_SC_TRAPNO, sigcontext, trapno);
-
-	DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long));
-	DEFINE_LONGS(HOST_RBX, RBX);
-	DEFINE_LONGS(HOST_RCX, RCX);
-	DEFINE_LONGS(HOST_RDI, RDI);
-	DEFINE_LONGS(HOST_RSI, RSI);
-	DEFINE_LONGS(HOST_RDX, RDX);
-	DEFINE_LONGS(HOST_RBP, RBP);
-	DEFINE_LONGS(HOST_RAX, RAX);
-	DEFINE_LONGS(HOST_R8, R8);
-	DEFINE_LONGS(HOST_R9, R9);
-	DEFINE_LONGS(HOST_R10, R10);
-	DEFINE_LONGS(HOST_R11, R11);
-	DEFINE_LONGS(HOST_R12, R12);
-	DEFINE_LONGS(HOST_R13, R13);
-	DEFINE_LONGS(HOST_R14, R14);
-	DEFINE_LONGS(HOST_R15, R15);
-	DEFINE_LONGS(HOST_ORIG_RAX, ORIG_RAX);
-	DEFINE_LONGS(HOST_CS, CS);
-	DEFINE_LONGS(HOST_SS, SS);
-	DEFINE_LONGS(HOST_EFLAGS, EFLAGS);
-#if 0
-	DEFINE_LONGS(HOST_FS, FS);
-	DEFINE_LONGS(HOST_GS, GS);
-	DEFINE_LONGS(HOST_DS, DS);
-	DEFINE_LONGS(HOST_ES, ES);
-#endif
-
-	DEFINE_LONGS(HOST_IP, RIP);
-	DEFINE_LONGS(HOST_SP, RSP);
-	DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
-
-	/* XXX Duplicated between i386 and x86_64 */
-	DEFINE(UM_POLLIN, POLLIN);
-	DEFINE(UM_POLLPRI, POLLPRI);
-	DEFINE(UM_POLLOUT, POLLOUT);
-
-	DEFINE(UM_PROT_READ, PROT_READ);
-	DEFINE(UM_PROT_WRITE, PROT_WRITE);
-	DEFINE(UM_PROT_EXEC, PROT_EXEC);
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/vdso/checkundef.sh linux-libre-3.2-gnu/arch/um/sys-x86_64/vdso/checkundef.sh
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/vdso/checkundef.sh	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/vdso/checkundef.sh	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#!/bin/sh
-nm="$1"
-file="$2"
-$nm "$file" | grep '^ *U' > /dev/null 2>&1
-if [ $? -eq 1 ]; then
-    exit 0
-else
-    echo "$file: undefined symbols found" >&2
-    exit 1
-fi
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/vdso/Makefile linux-libre-3.2-gnu/arch/um/sys-x86_64/vdso/Makefile
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/vdso/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/vdso/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,90 +0,0 @@
-#
-# Building vDSO images for x86.
-#
-
-VDSO64-y		:= y
-
-vdso-install-$(VDSO64-y)	+= vdso.so
-
-
-# files to link into the vdso
-vobjs-y := vdso-note.o um_vdso.o
-
-# files to link into kernel
-obj-$(VDSO64-y)			+= vdso.o vma.o
-
-vobjs := $(foreach F,$(vobjs-y),$(obj)/$F)
-
-$(obj)/vdso.o: $(obj)/vdso.so
-
-targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
-
-export CPPFLAGS_vdso.lds += -P -C
-
-VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
-       -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
-
-$(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
-
-$(obj)/vdso.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
-	$(call if_changed,vdso)
-
-$(obj)/%.so: OBJCOPYFLAGS := -S
-$(obj)/%.so: $(obj)/%.so.dbg FORCE
-	$(call if_changed,objcopy)
-
-#
-# Don't omit frame pointers for ease of userspace debugging, but do
-# optimize sibling calls.
-#
-CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \
-       $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \
-       -fno-omit-frame-pointer -foptimize-sibling-calls
-
-$(vobjs): KBUILD_CFLAGS += $(CFL)
-
-#
-# vDSO code runs in userspace and -pg doesn't help with profiling anyway.
-#
-CFLAGS_REMOVE_vdso-note.o = -pg
-CFLAGS_REMOVE_um_vdso.o = -pg
-
-targets += vdso-syms.lds
-obj-$(VDSO64-y)			+= vdso-syms.lds
-
-#
-# Match symbols in the DSO that look like VDSO*; produce a file of constants.
-#
-sed-vdsosym := -e 's/^00*/0/' \
-	-e 's/^\([0-9a-fA-F]*\) . \(VDSO[a-zA-Z0-9_]*\)$$/\2 = 0x\1;/p'
-quiet_cmd_vdsosym = VDSOSYM $@
-define cmd_vdsosym
-	$(NM) $< | LC_ALL=C sed -n $(sed-vdsosym) | LC_ALL=C sort > $@
-endef
-
-$(obj)/%-syms.lds: $(obj)/%.so.dbg FORCE
-	$(call if_changed,vdsosym)
-
-#
-# The DSO images are built using a special linker script.
-#
-quiet_cmd_vdso = VDSO    $@
-      cmd_vdso = $(CC) -nostdlib -o $@ \
-		       $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
-		       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
-		 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
-
-VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
-GCOV_PROFILE := n
-
-#
-# Install the unstripped copy of vdso*.so listed in $(vdso-install-y).
-#
-quiet_cmd_vdso_install = INSTALL $@
-      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
-$(vdso-install-y): %.so: $(obj)/%.so.dbg FORCE
-	@mkdir -p $(MODLIB)/vdso
-	$(call cmd,vdso_install)
-
-PHONY += vdso_install $(vdso-install-y)
-vdso_install: $(vdso-install-y)
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/vdso/um_vdso.c linux-libre-3.2-gnu/arch/um/sys-x86_64/vdso/um_vdso.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/vdso/um_vdso.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/vdso/um_vdso.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
- *
- * This program is free software; you can 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 vDSO turns all calls into a syscall so that UML can trap them.
- */
-
-
-/* Disable profiling for userspace code */
-#define DISABLE_BRANCH_PROFILING
-
-#include <linux/time.h>
-#include <linux/getcpu.h>
-#include <asm/unistd.h>
-
-int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
-{
-	long ret;
-
-	asm("syscall" : "=a" (ret) :
-		"0" (__NR_clock_gettime), "D" (clock), "S" (ts) : "memory");
-
-	return ret;
-}
-int clock_gettime(clockid_t, struct timespec *)
-	__attribute__((weak, alias("__vdso_clock_gettime")));
-
-int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
-{
-	long ret;
-
-	asm("syscall" : "=a" (ret) :
-		"0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory");
-
-	return ret;
-}
-int gettimeofday(struct timeval *, struct timezone *)
-	__attribute__((weak, alias("__vdso_gettimeofday")));
-
-time_t __vdso_time(time_t *t)
-{
-	long secs;
-
-	asm volatile("syscall"
-		: "=a" (secs)
-		: "0" (__NR_time), "D" (t) : "cc", "r11", "cx", "memory");
-
-	return secs;
-}
-int time(time_t *t) __attribute__((weak, alias("__vdso_time")));
-
-long
-__vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused)
-{
-	/*
-	 * UML does not support SMP, we can cheat here. :)
-	 */
-
-	if (cpu)
-		*cpu = 0;
-	if (node)
-		*node = 0;
-
-	return 0;
-}
-
-long getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
-	__attribute__((weak, alias("__vdso_getcpu")));
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/vdso/vdso-layout.lds.S linux-libre-3.2-gnu/arch/um/sys-x86_64/vdso/vdso-layout.lds.S
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/vdso/vdso-layout.lds.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/vdso/vdso-layout.lds.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,64 +0,0 @@
-/*
- * Linker script for vDSO.  This is an ELF shared object prelinked to
- * its virtual address, and with only one read-only segment.
- * This script controls its layout.
- */
-
-SECTIONS
-{
-	. = VDSO_PRELINK + SIZEOF_HEADERS;
-
-	.hash		: { *(.hash) }			:text
-	.gnu.hash	: { *(.gnu.hash) }
-	.dynsym		: { *(.dynsym) }
-	.dynstr		: { *(.dynstr) }
-	.gnu.version	: { *(.gnu.version) }
-	.gnu.version_d	: { *(.gnu.version_d) }
-	.gnu.version_r	: { *(.gnu.version_r) }
-
-	.note		: { *(.note.*) }		:text	:note
-
-	.eh_frame_hdr	: { *(.eh_frame_hdr) }		:text	:eh_frame_hdr
-	.eh_frame	: { KEEP (*(.eh_frame)) }	:text
-
-	.dynamic	: { *(.dynamic) }		:text	:dynamic
-
-	.rodata		: { *(.rodata*) }		:text
-	.data		: {
-	      *(.data*)
-	      *(.sdata*)
-	      *(.got.plt) *(.got)
-	      *(.gnu.linkonce.d.*)
-	      *(.bss*)
-	      *(.dynbss*)
-	      *(.gnu.linkonce.b.*)
-	}
-
-	.altinstructions	: { *(.altinstructions) }
-	.altinstr_replacement	: { *(.altinstr_replacement) }
-
-	/*
-	 * Align the actual code well away from the non-instruction data.
-	 * This is the best thing for the I-cache.
-	 */
-	. = ALIGN(0x100);
-
-	.text		: { *(.text*) }			:text	=0x90909090
-}
-
-/*
- * Very old versions of ld do not recognize this name token; use the constant.
- */
-#define PT_GNU_EH_FRAME	0x6474e550
-
-/*
- * We must supply the ELF program headers explicitly to get just one
- * PT_LOAD segment, and set the flags explicitly to make segments read-only.
- */
-PHDRS
-{
-	text		PT_LOAD		FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
-	dynamic		PT_DYNAMIC	FLAGS(4);		/* PF_R */
-	note		PT_NOTE		FLAGS(4);		/* PF_R */
-	eh_frame_hdr	PT_GNU_EH_FRAME;
-}
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/vdso/vdso.lds.S linux-libre-3.2-gnu/arch/um/sys-x86_64/vdso/vdso.lds.S
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/vdso/vdso.lds.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/vdso/vdso.lds.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-/*
- * Linker script for 64-bit vDSO.
- * We #include the file to define the layout details.
- * Here we only choose the prelinked virtual address.
- *
- * This file defines the version script giving the user-exported symbols in
- * the DSO.  We can define local symbols here called VDSO* to make their
- * values visible using the asm-x86/vdso.h macros from the kernel proper.
- */
-
-#define VDSO_PRELINK 0xffffffffff700000
-#include "vdso-layout.lds.S"
-
-/*
- * This controls what userland symbols we export from the vDSO.
- */
-VERSION {
-	LINUX_2.6 {
-	global:
-		clock_gettime;
-		__vdso_clock_gettime;
-		gettimeofday;
-		__vdso_gettimeofday;
-		getcpu;
-		__vdso_getcpu;
-		time;
-		__vdso_time;
-	local: *;
-	};
-}
-
-VDSO64_PRELINK = VDSO_PRELINK;
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/vdso/vdso-note.S linux-libre-3.2-gnu/arch/um/sys-x86_64/vdso/vdso-note.S
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/vdso/vdso-note.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/vdso/vdso-note.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-/*
- * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
- * Here we can supply some information useful to userland.
- */
-
-#include <linux/uts.h>
-#include <linux/version.h>
-#include <linux/elfnote.h>
-
-ELFNOTE_START(Linux, 0, "a")
-	.long LINUX_VERSION_CODE
-ELFNOTE_END
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/vdso/vdso.S linux-libre-3.2-gnu/arch/um/sys-x86_64/vdso/vdso.S
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/vdso/vdso.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/vdso/vdso.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#include <linux/init.h>
-
-__INITDATA
-
-	.globl vdso_start, vdso_end
-vdso_start:
-	.incbin "arch/um/sys-x86_64/vdso/vdso.so"
-vdso_end:
-
-__FINIT
diff -druN linux-libre-3.1-gnu/arch/um/sys-x86_64/vdso/vma.c linux-libre-3.2-gnu/arch/um/sys-x86_64/vdso/vma.c
--- linux-libre-3.1-gnu/arch/um/sys-x86_64/vdso/vma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/um/sys-x86_64/vdso/vma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
- *
- * This program is free software; you can 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/slab.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/page.h>
-#include <linux/init.h>
-
-unsigned int __read_mostly vdso_enabled = 1;
-unsigned long um_vdso_addr;
-
-extern unsigned long task_size;
-extern char vdso_start[], vdso_end[];
-
-static struct page **vdsop;
-
-static int __init init_vdso(void)
-{
-	struct page *um_vdso;
-
-	BUG_ON(vdso_end - vdso_start > PAGE_SIZE);
-
-	um_vdso_addr = task_size - PAGE_SIZE;
-
-	vdsop = kmalloc(GFP_KERNEL, sizeof(struct page *));
-	if (!vdsop)
-		goto oom;
-
-	um_vdso = alloc_page(GFP_KERNEL);
-	if (!um_vdso) {
-		kfree(vdsop);
-
-		goto oom;
-	}
-
-	copy_page(page_address(um_vdso), vdso_start);
-	*vdsop = um_vdso;
-
-	return 0;
-
-oom:
-	printk(KERN_ERR "Cannot allocate vdso\n");
-	vdso_enabled = 0;
-
-	return -ENOMEM;
-}
-subsys_initcall(init_vdso);
-
-int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
-{
-	int err;
-	struct mm_struct *mm = current->mm;
-
-	if (!vdso_enabled)
-		return 0;
-
-	down_write(&mm->mmap_sem);
-
-	err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE,
-		VM_READ|VM_EXEC|
-		VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
-		VM_ALWAYSDUMP,
-		vdsop);
-
-	up_write(&mm->mmap_sem);
-
-	return err;
-}
diff -druN linux-libre-3.1-gnu/arch/unicore32/boot/compressed/Makefile linux-libre-3.2-gnu/arch/unicore32/boot/compressed/Makefile
--- linux-libre-3.1-gnu/arch/unicore32/boot/compressed/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/unicore32/boot/compressed/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -10,8 +10,8 @@
 # Copyright (C) 2001~2010 GUAN Xue-tao
 #
 
-EXTRA_CFLAGS	:= -fpic -fno-builtin
-EXTRA_AFLAGS	:= -Wa,-march=all
+ccflags-y	:= -fpic -fno-builtin
+asflags-y	:= -Wa,-march=all
 
 OBJS		:= misc.o
 
diff -druN linux-libre-3.1-gnu/arch/unicore32/include/asm/bitops.h linux-libre-3.2-gnu/arch/unicore32/include/asm/bitops.h
--- linux-libre-3.1-gnu/arch/unicore32/include/asm/bitops.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/unicore32/include/asm/bitops.h	2012-01-04 18:55:44.000000000 -0500
@@ -13,12 +13,6 @@
 #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_
@@ -44,4 +38,10 @@
 
 #include <asm-generic/bitops.h>
 
+/* following definitions: to avoid using codes in lib/find_*.c */
+#define find_next_bit		find_next_bit
+#define find_next_zero_bit	find_next_zero_bit
+#define find_first_bit		find_first_bit
+#define find_first_zero_bit	find_first_zero_bit
+
 #endif /* __UNICORE_BITOPS_H__ */
diff -druN linux-libre-3.1-gnu/arch/unicore32/include/asm/io.h linux-libre-3.2-gnu/arch/unicore32/include/asm/io.h
--- linux-libre-3.1-gnu/arch/unicore32/include/asm/io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/unicore32/include/asm/io.h	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,7 @@
  * ioremap and friends.
  *
  * ioremap takes a PCI memory address, as specified in
- * Documentation/IO-mapping.txt.
+ * Documentation/io-mapping.txt.
  *
  */
 #define ioremap(cookie, size)		__uc32_ioremap(cookie, size)
diff -druN linux-libre-3.1-gnu/arch/unicore32/include/asm/processor.h linux-libre-3.2-gnu/arch/unicore32/include/asm/processor.h
--- linux-libre-3.1-gnu/arch/unicore32/include/asm/processor.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/unicore32/include/asm/processor.h	2012-01-04 18:55:44.000000000 -0500
@@ -53,7 +53,6 @@
 #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 */                        \
diff -druN linux-libre-3.1-gnu/arch/unicore32/Kconfig linux-libre-3.2-gnu/arch/unicore32/Kconfig
--- linux-libre-3.1-gnu/arch/unicore32/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/unicore32/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -237,13 +237,13 @@
 
 config I2C_BATTERY_BQ27200
 	tristate "I2C Battery BQ27200 Support"
-	select PUV3_I2C
+	select I2C_PUV3
 	select POWER_SUPPLY
 	select BATTERY_BQ27x00
 
 config I2C_EEPROM_AT24
 	tristate "I2C EEPROMs AT24 support"
-	select PUV3_I2C
+	select I2C_PUV3
 	select MISC_DEVICES
 	select EEPROM_AT24
 
diff -druN linux-libre-3.1-gnu/arch/unicore32/Kconfig.debug linux-libre-3.2-gnu/arch/unicore32/Kconfig.debug
--- linux-libre-3.1-gnu/arch/unicore32/Kconfig.debug	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/unicore32/Kconfig.debug	2012-01-04 18:55:44.000000000 -0500
@@ -44,18 +44,4 @@
 	  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-3.1-gnu/arch/unicore32/kernel/ksyms.c linux-libre-3.2-gnu/arch/unicore32/kernel/ksyms.c
--- linux-libre-3.1-gnu/arch/unicore32/kernel/ksyms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/unicore32/kernel/ksyms.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,8 +24,8 @@
 
 #include "ksyms.h"
 
-EXPORT_SYMBOL(__uc32_find_next_zero_bit);
-EXPORT_SYMBOL(__uc32_find_next_bit);
+EXPORT_SYMBOL(find_next_zero_bit);
+EXPORT_SYMBOL(find_next_bit);
 
 EXPORT_SYMBOL(__backtrace);
 
diff -druN linux-libre-3.1-gnu/arch/unicore32/lib/findbit.S linux-libre-3.2-gnu/arch/unicore32/lib/findbit.S
--- linux-libre-3.1-gnu/arch/unicore32/lib/findbit.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/unicore32/lib/findbit.S	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
  * Purpose  : Find a 'zero' bit
  * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
  */
-__uc32_find_first_zero_bit:
+ENTRY(find_first_zero_bit)
 		cxor.a	r1, #0
 		beq	3f
 		mov	r2, #0
@@ -29,13 +29,14 @@
 		bub	1b
 3:		mov	r0, r1			@ no free bits
 		mov	pc, lr
+ENDPROC(find_first_zero_bit)
 
 /*
  * Purpose  : Find next 'zero' bit
  * Prototype: int find_next_zero_bit
  *		(void *addr, unsigned int maxbit, int offset)
  */
-ENTRY(__uc32_find_next_zero_bit)
+ENTRY(find_next_zero_bit)
 		cxor.a	r1, #0
 		beq	3b
 		and.a	ip, r2, #7
@@ -47,14 +48,14 @@
 		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)
+ENDPROC(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:
+ENTRY(find_first_bit)
 		cxor.a	r1, #0
 		beq	3f
 		mov	r2, #0
@@ -66,13 +67,14 @@
 		bub	1b
 3:		mov	r0, r1			@ no free bits
 		mov	pc, lr
+ENDPROC(find_first_bit)
 
 /*
  * Purpose  : Find next 'one' bit
  * Prototype: int find_next_zero_bit
  *		(void *addr, unsigned int maxbit, int offset)
  */
-ENTRY(__uc32_find_next_bit)
+ENTRY(find_next_bit)
 		cxor.a	r1, #0
 		beq	3b
 		and.a	ip, r2, #7
@@ -83,7 +85,7 @@
 		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)
+ENDPROC(find_next_bit)
 
 /*
  * One or more bits in the LSB of r3 are assumed to be set.
diff -druN linux-libre-3.1-gnu/arch/unicore32/mm/init.c linux-libre-3.2-gnu/arch/unicore32/mm/init.c
--- linux-libre-3.1-gnu/arch/unicore32/mm/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/unicore32/mm/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/memblock.h>
 #include <linux/sort.h>
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 
 #include <asm/sections.h>
 #include <asm/setup.h>
diff -druN linux-libre-3.1-gnu/arch/x86/boot/header.S linux-libre-3.2-gnu/arch/x86/boot/header.S
--- linux-libre-3.1-gnu/arch/x86/boot/header.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/boot/header.S	2012-01-04 18:55:44.000000000 -0500
@@ -129,7 +129,7 @@
 
 type_of_loader:	.byte	0		# 0 means ancient bootloader, newer
 					# bootloaders know to change this.
-					# See Documentation/i386/boot.txt for
+					# See Documentation/x86/boot.txt for
 					# assigned ids
 
 # flags, unused bits must be zero (RFU) bit within loadflags
diff -druN linux-libre-3.1-gnu/arch/x86/configs/x86_64_defconfig linux-libre-3.2-gnu/arch/x86/configs/x86_64_defconfig
--- linux-libre-3.1-gnu/arch/x86/configs/x86_64_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/configs/x86_64_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -67,8 +67,8 @@
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
 CONFIG_X86_ACPI_CPUFREQ=y
 CONFIG_PCI_MMCONFIG=y
-CONFIG_DMAR=y
-# CONFIG_DMAR_DEFAULT_ON is not set
+CONFIG_INTEL_IOMMU=y
+# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCCARD=y
 CONFIG_YENTA=y
diff -druN linux-libre-3.1-gnu/arch/x86/crypto/aes_glue.c linux-libre-3.2-gnu/arch/x86/crypto/aes_glue.c
--- linux-libre-3.1-gnu/arch/x86/crypto/aes_glue.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/crypto/aes_glue.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,9 @@
  *
  */
 
+#include <linux/module.h>
 #include <crypto/aes.h>
+#include <asm/aes.h>
 
 asmlinkage void aes_enc_blk(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in);
 asmlinkage void aes_dec_blk(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in);
diff -druN linux-libre-3.1-gnu/arch/x86/crypto/aesni-intel_glue.c linux-libre-3.2-gnu/arch/x86/crypto/aesni-intel_glue.c
--- linux-libre-3.1-gnu/arch/x86/crypto/aesni-intel_glue.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/crypto/aesni-intel_glue.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/hardirq.h>
 #include <linux/types.h>
 #include <linux/crypto.h>
+#include <linux/module.h>
 #include <linux/err.h>
 #include <crypto/algapi.h>
 #include <crypto/aes.h>
diff -druN linux-libre-3.1-gnu/arch/x86/crypto/blowfish_glue.c linux-libre-3.2-gnu/arch/x86/crypto/blowfish_glue.c
--- linux-libre-3.1-gnu/arch/x86/crypto/blowfish_glue.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/crypto/blowfish_glue.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,492 @@
+/*
+ * Glue Code for assembler optimized version of Blowfish
+ *
+ * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
+ *   Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ * CTR part based on code (crypto/ctr.c) by:
+ *   (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.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 <crypto/blowfish.h>
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+
+/* regular block cipher functions */
+asmlinkage void __blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src,
+				   bool xor);
+asmlinkage void blowfish_dec_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src);
+
+/* 4-way parallel cipher functions */
+asmlinkage void __blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst,
+					const u8 *src, bool xor);
+asmlinkage void blowfish_dec_blk_4way(struct bf_ctx *ctx, u8 *dst,
+				      const u8 *src);
+
+static inline void blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src)
+{
+	__blowfish_enc_blk(ctx, dst, src, false);
+}
+
+static inline void blowfish_enc_blk_xor(struct bf_ctx *ctx, u8 *dst,
+					const u8 *src)
+{
+	__blowfish_enc_blk(ctx, dst, src, true);
+}
+
+static inline void blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst,
+					 const u8 *src)
+{
+	__blowfish_enc_blk_4way(ctx, dst, src, false);
+}
+
+static inline void blowfish_enc_blk_xor_4way(struct bf_ctx *ctx, u8 *dst,
+				      const u8 *src)
+{
+	__blowfish_enc_blk_4way(ctx, dst, src, true);
+}
+
+static void blowfish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	blowfish_enc_blk(crypto_tfm_ctx(tfm), dst, src);
+}
+
+static void blowfish_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	blowfish_dec_blk(crypto_tfm_ctx(tfm), dst, src);
+}
+
+static struct crypto_alg bf_alg = {
+	.cra_name		=	"blowfish",
+	.cra_driver_name	=	"blowfish-asm",
+	.cra_priority		=	200,
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	BF_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof(struct bf_ctx),
+	.cra_alignmask		=	3,
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(bf_alg.cra_list),
+	.cra_u			=	{
+		.cipher = {
+			.cia_min_keysize	=	BF_MIN_KEY_SIZE,
+			.cia_max_keysize	=	BF_MAX_KEY_SIZE,
+			.cia_setkey		=	blowfish_setkey,
+			.cia_encrypt		=	blowfish_encrypt,
+			.cia_decrypt		=	blowfish_decrypt,
+		}
+	}
+};
+
+static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
+		     void (*fn)(struct bf_ctx *, u8 *, const u8 *),
+		     void (*fn_4way)(struct bf_ctx *, u8 *, const u8 *))
+{
+	struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = BF_BLOCK_SIZE;
+	unsigned int nbytes;
+	int err;
+
+	err = blkcipher_walk_virt(desc, walk);
+
+	while ((nbytes = walk->nbytes)) {
+		u8 *wsrc = walk->src.virt.addr;
+		u8 *wdst = walk->dst.virt.addr;
+
+		/* Process four block batch */
+		if (nbytes >= bsize * 4) {
+			do {
+				fn_4way(ctx, wdst, wsrc);
+
+				wsrc += bsize * 4;
+				wdst += bsize * 4;
+				nbytes -= bsize * 4;
+			} while (nbytes >= bsize * 4);
+
+			if (nbytes < bsize)
+				goto done;
+		}
+
+		/* Handle leftovers */
+		do {
+			fn(ctx, wdst, wsrc);
+
+			wsrc += bsize;
+			wdst += bsize;
+			nbytes -= bsize;
+		} while (nbytes >= bsize);
+
+done:
+		err = blkcipher_walk_done(desc, walk, nbytes);
+	}
+
+	return err;
+}
+
+static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	return ecb_crypt(desc, &walk, blowfish_enc_blk, blowfish_enc_blk_4way);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	return ecb_crypt(desc, &walk, blowfish_dec_blk, blowfish_dec_blk_4way);
+}
+
+static struct crypto_alg blk_ecb_alg = {
+	.cra_name		= "ecb(blowfish)",
+	.cra_driver_name	= "ecb-blowfish-asm",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= BF_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct bf_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_ecb_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= BF_MIN_KEY_SIZE,
+			.max_keysize	= BF_MAX_KEY_SIZE,
+			.setkey		= blowfish_setkey,
+			.encrypt	= ecb_encrypt,
+			.decrypt	= ecb_decrypt,
+		},
+	},
+};
+
+static unsigned int __cbc_encrypt(struct blkcipher_desc *desc,
+				  struct blkcipher_walk *walk)
+{
+	struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = BF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u64 *src = (u64 *)walk->src.virt.addr;
+	u64 *dst = (u64 *)walk->dst.virt.addr;
+	u64 *iv = (u64 *)walk->iv;
+
+	do {
+		*dst = *src ^ *iv;
+		blowfish_enc_blk(ctx, (u8 *)dst, (u8 *)dst);
+		iv = dst;
+
+		src += 1;
+		dst += 1;
+		nbytes -= bsize;
+	} while (nbytes >= bsize);
+
+	*(u64 *)walk->iv = *iv;
+	return nbytes;
+}
+
+static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		nbytes = __cbc_encrypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
+				  struct blkcipher_walk *walk)
+{
+	struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = BF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u64 *src = (u64 *)walk->src.virt.addr;
+	u64 *dst = (u64 *)walk->dst.virt.addr;
+	u64 ivs[4 - 1];
+	u64 last_iv;
+
+	/* Start of the last block. */
+	src += nbytes / bsize - 1;
+	dst += nbytes / bsize - 1;
+
+	last_iv = *src;
+
+	/* Process four block batch */
+	if (nbytes >= bsize * 4) {
+		do {
+			nbytes -= bsize * 4 - bsize;
+			src -= 4 - 1;
+			dst -= 4 - 1;
+
+			ivs[0] = src[0];
+			ivs[1] = src[1];
+			ivs[2] = src[2];
+
+			blowfish_dec_blk_4way(ctx, (u8 *)dst, (u8 *)src);
+
+			dst[1] ^= ivs[0];
+			dst[2] ^= ivs[1];
+			dst[3] ^= ivs[2];
+
+			nbytes -= bsize;
+			if (nbytes < bsize)
+				goto done;
+
+			*dst ^= *(src - 1);
+			src -= 1;
+			dst -= 1;
+		} while (nbytes >= bsize * 4);
+
+		if (nbytes < bsize)
+			goto done;
+	}
+
+	/* Handle leftovers */
+	for (;;) {
+		blowfish_dec_blk(ctx, (u8 *)dst, (u8 *)src);
+
+		nbytes -= bsize;
+		if (nbytes < bsize)
+			break;
+
+		*dst ^= *(src - 1);
+		src -= 1;
+		dst -= 1;
+	}
+
+done:
+	*dst ^= *(u64 *)walk->iv;
+	*(u64 *)walk->iv = last_iv;
+
+	return nbytes;
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		nbytes = __cbc_decrypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static struct crypto_alg blk_cbc_alg = {
+	.cra_name		= "cbc(blowfish)",
+	.cra_driver_name	= "cbc-blowfish-asm",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= BF_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct bf_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_cbc_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= BF_MIN_KEY_SIZE,
+			.max_keysize	= BF_MAX_KEY_SIZE,
+			.ivsize		= BF_BLOCK_SIZE,
+			.setkey		= blowfish_setkey,
+			.encrypt	= cbc_encrypt,
+			.decrypt	= cbc_decrypt,
+		},
+	},
+};
+
+static void ctr_crypt_final(struct bf_ctx *ctx, struct blkcipher_walk *walk)
+{
+	u8 *ctrblk = walk->iv;
+	u8 keystream[BF_BLOCK_SIZE];
+	u8 *src = walk->src.virt.addr;
+	u8 *dst = walk->dst.virt.addr;
+	unsigned int nbytes = walk->nbytes;
+
+	blowfish_enc_blk(ctx, keystream, ctrblk);
+	crypto_xor(keystream, src, nbytes);
+	memcpy(dst, keystream, nbytes);
+
+	crypto_inc(ctrblk, BF_BLOCK_SIZE);
+}
+
+static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
+				struct blkcipher_walk *walk)
+{
+	struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = BF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u64 *src = (u64 *)walk->src.virt.addr;
+	u64 *dst = (u64 *)walk->dst.virt.addr;
+	u64 ctrblk = be64_to_cpu(*(__be64 *)walk->iv);
+	__be64 ctrblocks[4];
+
+	/* Process four block batch */
+	if (nbytes >= bsize * 4) {
+		do {
+			if (dst != src) {
+				dst[0] = src[0];
+				dst[1] = src[1];
+				dst[2] = src[2];
+				dst[3] = src[3];
+			}
+
+			/* create ctrblks for parallel encrypt */
+			ctrblocks[0] = cpu_to_be64(ctrblk++);
+			ctrblocks[1] = cpu_to_be64(ctrblk++);
+			ctrblocks[2] = cpu_to_be64(ctrblk++);
+			ctrblocks[3] = cpu_to_be64(ctrblk++);
+
+			blowfish_enc_blk_xor_4way(ctx, (u8 *)dst,
+						  (u8 *)ctrblocks);
+
+			src += 4;
+			dst += 4;
+		} while ((nbytes -= bsize * 4) >= bsize * 4);
+
+		if (nbytes < bsize)
+			goto done;
+	}
+
+	/* Handle leftovers */
+	do {
+		if (dst != src)
+			*dst = *src;
+
+		ctrblocks[0] = cpu_to_be64(ctrblk++);
+
+		blowfish_enc_blk_xor(ctx, (u8 *)dst, (u8 *)ctrblocks);
+
+		src += 1;
+		dst += 1;
+	} while ((nbytes -= bsize) >= bsize);
+
+done:
+	*(__be64 *)walk->iv = cpu_to_be64(ctrblk);
+	return nbytes;
+}
+
+static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		     struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt_block(desc, &walk, BF_BLOCK_SIZE);
+
+	while ((nbytes = walk.nbytes) >= BF_BLOCK_SIZE) {
+		nbytes = __ctr_crypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	if (walk.nbytes) {
+		ctr_crypt_final(crypto_blkcipher_ctx(desc->tfm), &walk);
+		err = blkcipher_walk_done(desc, &walk, 0);
+	}
+
+	return err;
+}
+
+static struct crypto_alg blk_ctr_alg = {
+	.cra_name		= "ctr(blowfish)",
+	.cra_driver_name	= "ctr-blowfish-asm",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= 1,
+	.cra_ctxsize		= sizeof(struct bf_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_ctr_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= BF_MIN_KEY_SIZE,
+			.max_keysize	= BF_MAX_KEY_SIZE,
+			.ivsize		= BF_BLOCK_SIZE,
+			.setkey		= blowfish_setkey,
+			.encrypt	= ctr_crypt,
+			.decrypt	= ctr_crypt,
+		},
+	},
+};
+
+static int __init init(void)
+{
+	int err;
+
+	err = crypto_register_alg(&bf_alg);
+	if (err)
+		goto bf_err;
+	err = crypto_register_alg(&blk_ecb_alg);
+	if (err)
+		goto ecb_err;
+	err = crypto_register_alg(&blk_cbc_alg);
+	if (err)
+		goto cbc_err;
+	err = crypto_register_alg(&blk_ctr_alg);
+	if (err)
+		goto ctr_err;
+
+	return 0;
+
+ctr_err:
+	crypto_unregister_alg(&blk_cbc_alg);
+cbc_err:
+	crypto_unregister_alg(&blk_ecb_alg);
+ecb_err:
+	crypto_unregister_alg(&bf_alg);
+bf_err:
+	return err;
+}
+
+static void __exit fini(void)
+{
+	crypto_unregister_alg(&blk_ctr_alg);
+	crypto_unregister_alg(&blk_cbc_alg);
+	crypto_unregister_alg(&blk_ecb_alg);
+	crypto_unregister_alg(&bf_alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Blowfish Cipher Algorithm, asm optimized");
+MODULE_ALIAS("blowfish");
+MODULE_ALIAS("blowfish-asm");
diff -druN linux-libre-3.1-gnu/arch/x86/crypto/blowfish-x86_64-asm_64.S linux-libre-3.2-gnu/arch/x86/crypto/blowfish-x86_64-asm_64.S
--- linux-libre-3.1-gnu/arch/x86/crypto/blowfish-x86_64-asm_64.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/crypto/blowfish-x86_64-asm_64.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,390 @@
+/*
+ * Blowfish Cipher Algorithm (x86_64)
+ *
+ * Copyright (C) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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
+ *
+ */
+
+.file "blowfish-x86_64-asm.S"
+.text
+
+/* structure of crypto context */
+#define p	0
+#define s0	((16 + 2) * 4)
+#define s1	((16 + 2 + (1 * 256)) * 4)
+#define s2	((16 + 2 + (2 * 256)) * 4)
+#define s3	((16 + 2 + (3 * 256)) * 4)
+
+/* register macros */
+#define CTX %rdi
+#define RIO %rsi
+
+#define RX0 %rax
+#define RX1 %rbx
+#define RX2 %rcx
+#define RX3 %rdx
+
+#define RX0d %eax
+#define RX1d %ebx
+#define RX2d %ecx
+#define RX3d %edx
+
+#define RX0bl %al
+#define RX1bl %bl
+#define RX2bl %cl
+#define RX3bl %dl
+
+#define RX0bh %ah
+#define RX1bh %bh
+#define RX2bh %ch
+#define RX3bh %dh
+
+#define RT0 %rbp
+#define RT1 %rsi
+#define RT2 %r8
+#define RT3 %r9
+
+#define RT0d %ebp
+#define RT1d %esi
+#define RT2d %r8d
+#define RT3d %r9d
+
+#define RKEY %r10
+
+/***********************************************************************
+ * 1-way blowfish
+ ***********************************************************************/
+#define F() \
+	rorq $16,		RX0; \
+	movzbl RX0bh,		RT0d; \
+	movzbl RX0bl,		RT1d; \
+	rolq $16,		RX0; \
+	movl s0(CTX,RT0,4),	RT0d; \
+	addl s1(CTX,RT1,4),	RT0d; \
+	movzbl RX0bh,		RT1d; \
+	movzbl RX0bl,		RT2d; \
+	rolq $32,		RX0; \
+	xorl s2(CTX,RT1,4),	RT0d; \
+	addl s3(CTX,RT2,4),	RT0d; \
+	xorq RT0,		RX0;
+
+#define add_roundkey_enc(n) \
+	xorq p+4*(n)(CTX), 	RX0;
+
+#define round_enc(n) \
+	add_roundkey_enc(n); \
+	\
+	F(); \
+	F();
+
+#define add_roundkey_dec(n) \
+	movq p+4*(n-1)(CTX),	RT0; \
+	rorq $32,		RT0; \
+	xorq RT0,		RX0;
+
+#define round_dec(n) \
+	add_roundkey_dec(n); \
+	\
+	F(); \
+	F(); \
+
+#define read_block() \
+	movq (RIO), 		RX0; \
+	rorq $32, 		RX0; \
+	bswapq 			RX0;
+
+#define write_block() \
+	bswapq 			RX0; \
+	movq RX0, 		(RIO);
+
+#define xor_block() \
+	bswapq 			RX0; \
+	xorq RX0, 		(RIO);
+
+.align 8
+.global __blowfish_enc_blk
+.type   __blowfish_enc_blk,@function;
+
+__blowfish_enc_blk:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 *	%rcx: bool, if true: xor output
+	 */
+	movq %rbp, %r11;
+
+	movq %rsi, %r10;
+	movq %rdx, RIO;
+
+	read_block();
+
+	round_enc(0);
+	round_enc(2);
+	round_enc(4);
+	round_enc(6);
+	round_enc(8);
+	round_enc(10);
+	round_enc(12);
+	round_enc(14);
+	add_roundkey_enc(16);
+
+	movq %r11, %rbp;
+
+	movq %r10, RIO;
+	test %cl, %cl;
+	jnz __enc_xor;
+
+	write_block();
+	ret;
+__enc_xor:
+	xor_block();
+	ret;
+
+.align 8
+.global blowfish_dec_blk
+.type   blowfish_dec_blk,@function;
+
+blowfish_dec_blk:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+	movq %rbp, %r11;
+
+	movq %rsi, %r10;
+	movq %rdx, RIO;
+
+	read_block();
+
+	round_dec(17);
+	round_dec(15);
+	round_dec(13);
+	round_dec(11);
+	round_dec(9);
+	round_dec(7);
+	round_dec(5);
+	round_dec(3);
+	add_roundkey_dec(1);
+
+	movq %r10, RIO;
+	write_block();
+
+	movq %r11, %rbp;
+
+	ret;
+
+/**********************************************************************
+  4-way blowfish, four blocks parallel
+ **********************************************************************/
+
+/* F() for 4-way. Slower when used alone/1-way, but faster when used
+ * parallel/4-way (tested on AMD Phenom II & Intel Xeon E7330).
+ */
+#define F4(x) \
+	movzbl x ## bh,		RT1d; \
+	movzbl x ## bl,		RT3d; \
+	rorq $16,		x; \
+	movzbl x ## bh,		RT0d; \
+	movzbl x ## bl,		RT2d; \
+	rorq $16,		x; \
+	movl s0(CTX,RT0,4),	RT0d; \
+	addl s1(CTX,RT2,4),	RT0d; \
+	xorl s2(CTX,RT1,4),	RT0d; \
+	addl s3(CTX,RT3,4),	RT0d; \
+	xorq RT0,		x;
+
+#define add_preloaded_roundkey4() \
+	xorq RKEY,		RX0; \
+	xorq RKEY,		RX1; \
+	xorq RKEY,		RX2; \
+	xorq RKEY,		RX3;
+
+#define preload_roundkey_enc(n) \
+	movq p+4*(n)(CTX),	RKEY;
+
+#define add_roundkey_enc4(n) \
+	add_preloaded_roundkey4(); \
+	preload_roundkey_enc(n + 2);
+
+#define round_enc4(n) \
+	add_roundkey_enc4(n); \
+	\
+	F4(RX0); \
+	F4(RX1); \
+	F4(RX2); \
+	F4(RX3); \
+	\
+	F4(RX0); \
+	F4(RX1); \
+	F4(RX2); \
+	F4(RX3);
+
+#define preload_roundkey_dec(n) \
+	movq p+4*((n)-1)(CTX),	RKEY; \
+	rorq $32,		RKEY;
+
+#define add_roundkey_dec4(n) \
+	add_preloaded_roundkey4(); \
+	preload_roundkey_dec(n - 2);
+
+#define round_dec4(n) \
+	add_roundkey_dec4(n); \
+	\
+	F4(RX0); \
+	F4(RX1); \
+	F4(RX2); \
+	F4(RX3); \
+	\
+	F4(RX0); \
+	F4(RX1); \
+	F4(RX2); \
+	F4(RX3);
+
+#define read_block4() \
+	movq (RIO),		RX0; \
+	rorq $32,		RX0; \
+	bswapq 			RX0; \
+	\
+	movq 8(RIO),		RX1; \
+	rorq $32,		RX1; \
+	bswapq 			RX1; \
+	\
+	movq 16(RIO),		RX2; \
+	rorq $32,		RX2; \
+	bswapq 			RX2; \
+	\
+	movq 24(RIO),		RX3; \
+	rorq $32,		RX3; \
+	bswapq 			RX3;
+
+#define write_block4() \
+	bswapq 			RX0; \
+	movq RX0,		(RIO); \
+	\
+	bswapq 			RX1; \
+	movq RX1,		8(RIO); \
+	\
+	bswapq 			RX2; \
+	movq RX2,		16(RIO); \
+	\
+	bswapq 			RX3; \
+	movq RX3,		24(RIO);
+
+#define xor_block4() \
+	bswapq 			RX0; \
+	xorq RX0,		(RIO); \
+	\
+	bswapq 			RX1; \
+	xorq RX1,		8(RIO); \
+	\
+	bswapq 			RX2; \
+	xorq RX2,		16(RIO); \
+	\
+	bswapq 			RX3; \
+	xorq RX3,		24(RIO);
+
+.align 8
+.global __blowfish_enc_blk_4way
+.type   __blowfish_enc_blk_4way,@function;
+
+__blowfish_enc_blk_4way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 *	%rcx: bool, if true: xor output
+	 */
+	pushq %rbp;
+	pushq %rbx;
+	pushq %rcx;
+
+	preload_roundkey_enc(0);
+
+	movq %rsi, %r11;
+	movq %rdx, RIO;
+
+	read_block4();
+
+	round_enc4(0);
+	round_enc4(2);
+	round_enc4(4);
+	round_enc4(6);
+	round_enc4(8);
+	round_enc4(10);
+	round_enc4(12);
+	round_enc4(14);
+	add_preloaded_roundkey4();
+
+	popq %rbp;
+	movq %r11, RIO;
+
+	test %bpl, %bpl;
+	jnz __enc_xor4;
+
+	write_block4();
+
+	popq %rbx;
+	popq %rbp;
+	ret;
+
+__enc_xor4:
+	xor_block4();
+
+	popq %rbx;
+	popq %rbp;
+	ret;
+
+.align 8
+.global blowfish_dec_blk_4way
+.type   blowfish_dec_blk_4way,@function;
+
+blowfish_dec_blk_4way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+	pushq %rbp;
+	pushq %rbx;
+	preload_roundkey_dec(17);
+
+	movq %rsi, %r11;
+	movq %rdx, RIO;
+
+	read_block4();
+
+	round_dec4(17);
+	round_dec4(15);
+	round_dec4(13);
+	round_dec4(11);
+	round_dec4(9);
+	round_dec4(7);
+	round_dec4(5);
+	round_dec4(3);
+	add_preloaded_roundkey4();
+
+	movq %r11, RIO;
+	write_block4();
+
+	popq %rbx;
+	popq %rbp;
+
+	ret;
+
diff -druN linux-libre-3.1-gnu/arch/x86/crypto/Makefile linux-libre-3.2-gnu/arch/x86/crypto/Makefile
--- linux-libre-3.1-gnu/arch/x86/crypto/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/crypto/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -7,21 +7,33 @@
 obj-$(CONFIG_CRYPTO_SALSA20_586) += salsa20-i586.o
 
 obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
+obj-$(CONFIG_CRYPTO_BLOWFISH_X86_64) += blowfish-x86_64.o
 obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
+obj-$(CONFIG_CRYPTO_TWOFISH_X86_64_3WAY) += twofish-x86_64-3way.o
 obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o
 obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o
 obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o
 
 obj-$(CONFIG_CRYPTO_CRC32C_INTEL) += crc32c-intel.o
+obj-$(CONFIG_CRYPTO_SHA1_SSSE3) += sha1-ssse3.o
 
 aes-i586-y := aes-i586-asm_32.o aes_glue.o
 twofish-i586-y := twofish-i586-asm_32.o twofish_glue.o
 salsa20-i586-y := salsa20-i586-asm_32.o salsa20_glue.o
 
 aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
+blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o
 twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o
+twofish-x86_64-3way-y := twofish-x86_64-asm_64-3way.o twofish_glue_3way.o
 salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o
 
 aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o
 
 ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
+
+# enable AVX support only when $(AS) can actually assemble the instructions
+ifeq ($(call as-instr,vpxor %xmm0$(comma)%xmm1$(comma)%xmm2,yes,no),yes)
+AFLAGS_sha1_ssse3_asm.o += -DSHA1_ENABLE_AVX_SUPPORT
+CFLAGS_sha1_ssse3_glue.o += -DSHA1_ENABLE_AVX_SUPPORT
+endif
+sha1-ssse3-y := sha1_ssse3_asm.o sha1_ssse3_glue.o
diff -druN linux-libre-3.1-gnu/arch/x86/crypto/sha1_ssse3_asm.S linux-libre-3.2-gnu/arch/x86/crypto/sha1_ssse3_asm.S
--- linux-libre-3.1-gnu/arch/x86/crypto/sha1_ssse3_asm.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/crypto/sha1_ssse3_asm.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,558 @@
+/*
+ * This is a SIMD SHA-1 implementation. It requires the Intel(R) Supplemental
+ * SSE3 instruction set extensions introduced in Intel Core Microarchitecture
+ * processors. CPUs supporting Intel(R) AVX extensions will get an additional
+ * boost.
+ *
+ * This work was inspired by the vectorized implementation of Dean Gaudet.
+ * Additional information on it can be found at:
+ *    http://www.arctic.org/~dean/crypto/sha1.html
+ *
+ * It was improved upon with more efficient vectorization of the message
+ * scheduling. This implementation has also been optimized for all current and
+ * several future generations of Intel CPUs.
+ *
+ * See this article for more information about the implementation details:
+ *   http://software.intel.com/en-us/articles/improving-the-performance-of-the-secure-hash-algorithm-1/
+ *
+ * Copyright (C) 2010, Intel Corp.
+ *   Authors: Maxim Locktyukhin <maxim.locktyukhin@intel.com>
+ *            Ronen Zohar <ronen.zohar@intel.com>
+ *
+ * Converted to AT&T syntax and adapted for inclusion in the Linux kernel:
+ *   Author: Mathias Krause <minipli@googlemail.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.
+ */
+
+#define CTX	%rdi	// arg1
+#define BUF	%rsi	// arg2
+#define CNT	%rdx	// arg3
+
+#define REG_A	%ecx
+#define REG_B	%esi
+#define REG_C	%edi
+#define REG_D	%ebp
+#define REG_E	%edx
+
+#define REG_T1	%eax
+#define REG_T2	%ebx
+
+#define K_BASE		%r8
+#define HASH_PTR	%r9
+#define BUFFER_PTR	%r10
+#define BUFFER_END	%r11
+
+#define W_TMP1	%xmm0
+#define W_TMP2	%xmm9
+
+#define W0	%xmm1
+#define W4	%xmm2
+#define W8	%xmm3
+#define W12	%xmm4
+#define W16	%xmm5
+#define W20	%xmm6
+#define W24	%xmm7
+#define W28	%xmm8
+
+#define XMM_SHUFB_BSWAP	%xmm10
+
+/* we keep window of 64 w[i]+K pre-calculated values in a circular buffer */
+#define WK(t)	(((t) & 15) * 4)(%rsp)
+#define W_PRECALC_AHEAD	16
+
+/*
+ * This macro implements the SHA-1 function's body for single 64-byte block
+ * param: function's name
+ */
+.macro SHA1_VECTOR_ASM  name
+	.global	\name
+	.type	\name, @function
+	.align 32
+\name:
+	push	%rbx
+	push	%rbp
+	push	%r12
+
+	mov	%rsp, %r12
+	sub	$64, %rsp		# allocate workspace
+	and	$~15, %rsp		# align stack
+
+	mov	CTX, HASH_PTR
+	mov	BUF, BUFFER_PTR
+
+	shl	$6, CNT			# multiply by 64
+	add	BUF, CNT
+	mov	CNT, BUFFER_END
+
+	lea	K_XMM_AR(%rip), K_BASE
+	xmm_mov	BSWAP_SHUFB_CTL(%rip), XMM_SHUFB_BSWAP
+
+	SHA1_PIPELINED_MAIN_BODY
+
+	# cleanup workspace
+	mov	$8, %ecx
+	mov	%rsp, %rdi
+	xor	%rax, %rax
+	rep stosq
+
+	mov	%r12, %rsp		# deallocate workspace
+
+	pop	%r12
+	pop	%rbp
+	pop	%rbx
+	ret
+
+	.size	\name, .-\name
+.endm
+
+/*
+ * This macro implements 80 rounds of SHA-1 for one 64-byte block
+ */
+.macro SHA1_PIPELINED_MAIN_BODY
+	INIT_REGALLOC
+
+	mov	  (HASH_PTR), A
+	mov	 4(HASH_PTR), B
+	mov	 8(HASH_PTR), C
+	mov	12(HASH_PTR), D
+	mov	16(HASH_PTR), E
+
+  .set i, 0
+  .rept W_PRECALC_AHEAD
+	W_PRECALC i
+    .set i, (i+1)
+  .endr
+
+.align 4
+1:
+	RR F1,A,B,C,D,E,0
+	RR F1,D,E,A,B,C,2
+	RR F1,B,C,D,E,A,4
+	RR F1,E,A,B,C,D,6
+	RR F1,C,D,E,A,B,8
+
+	RR F1,A,B,C,D,E,10
+	RR F1,D,E,A,B,C,12
+	RR F1,B,C,D,E,A,14
+	RR F1,E,A,B,C,D,16
+	RR F1,C,D,E,A,B,18
+
+	RR F2,A,B,C,D,E,20
+	RR F2,D,E,A,B,C,22
+	RR F2,B,C,D,E,A,24
+	RR F2,E,A,B,C,D,26
+	RR F2,C,D,E,A,B,28
+
+	RR F2,A,B,C,D,E,30
+	RR F2,D,E,A,B,C,32
+	RR F2,B,C,D,E,A,34
+	RR F2,E,A,B,C,D,36
+	RR F2,C,D,E,A,B,38
+
+	RR F3,A,B,C,D,E,40
+	RR F3,D,E,A,B,C,42
+	RR F3,B,C,D,E,A,44
+	RR F3,E,A,B,C,D,46
+	RR F3,C,D,E,A,B,48
+
+	RR F3,A,B,C,D,E,50
+	RR F3,D,E,A,B,C,52
+	RR F3,B,C,D,E,A,54
+	RR F3,E,A,B,C,D,56
+	RR F3,C,D,E,A,B,58
+
+	add	$64, BUFFER_PTR		# move to the next 64-byte block
+	cmp	BUFFER_END, BUFFER_PTR	# if the current is the last one use
+	cmovae	K_BASE, BUFFER_PTR	# dummy source to avoid buffer overrun
+
+	RR F4,A,B,C,D,E,60
+	RR F4,D,E,A,B,C,62
+	RR F4,B,C,D,E,A,64
+	RR F4,E,A,B,C,D,66
+	RR F4,C,D,E,A,B,68
+
+	RR F4,A,B,C,D,E,70
+	RR F4,D,E,A,B,C,72
+	RR F4,B,C,D,E,A,74
+	RR F4,E,A,B,C,D,76
+	RR F4,C,D,E,A,B,78
+
+	UPDATE_HASH   (HASH_PTR), A
+	UPDATE_HASH  4(HASH_PTR), B
+	UPDATE_HASH  8(HASH_PTR), C
+	UPDATE_HASH 12(HASH_PTR), D
+	UPDATE_HASH 16(HASH_PTR), E
+
+	RESTORE_RENAMED_REGS
+	cmp	K_BASE, BUFFER_PTR	# K_BASE means, we reached the end
+	jne	1b
+.endm
+
+.macro INIT_REGALLOC
+  .set A, REG_A
+  .set B, REG_B
+  .set C, REG_C
+  .set D, REG_D
+  .set E, REG_E
+  .set T1, REG_T1
+  .set T2, REG_T2
+.endm
+
+.macro RESTORE_RENAMED_REGS
+	# order is important (REG_C is where it should be)
+	mov	B, REG_B
+	mov	D, REG_D
+	mov	A, REG_A
+	mov	E, REG_E
+.endm
+
+.macro SWAP_REG_NAMES  a, b
+  .set _T, \a
+  .set \a, \b
+  .set \b, _T
+.endm
+
+.macro F1  b, c, d
+	mov	\c, T1
+	SWAP_REG_NAMES \c, T1
+	xor	\d, T1
+	and	\b, T1
+	xor	\d, T1
+.endm
+
+.macro F2  b, c, d
+	mov	\d, T1
+	SWAP_REG_NAMES \d, T1
+	xor	\c, T1
+	xor	\b, T1
+.endm
+
+.macro F3  b, c ,d
+	mov	\c, T1
+	SWAP_REG_NAMES \c, T1
+	mov	\b, T2
+	or	\b, T1
+	and	\c, T2
+	and	\d, T1
+	or	T2, T1
+.endm
+
+.macro F4  b, c, d
+	F2 \b, \c, \d
+.endm
+
+.macro UPDATE_HASH  hash, val
+	add	\hash, \val
+	mov	\val, \hash
+.endm
+
+/*
+ * RR does two rounds of SHA-1 back to back with W[] pre-calc
+ *   t1 = F(b, c, d);   e += w(i)
+ *   e += t1;           b <<= 30;   d  += w(i+1);
+ *   t1 = F(a, b, c);
+ *   d += t1;           a <<= 5;
+ *   e += a;
+ *   t1 = e;            a >>= 7;
+ *   t1 <<= 5;
+ *   d += t1;
+ */
+.macro RR  F, a, b, c, d, e, round
+	add	WK(\round), \e
+	\F   \b, \c, \d		# t1 = F(b, c, d);
+	W_PRECALC (\round + W_PRECALC_AHEAD)
+	rol	$30, \b
+	add	T1, \e
+	add	WK(\round + 1), \d
+
+	\F   \a, \b, \c
+	W_PRECALC (\round + W_PRECALC_AHEAD + 1)
+	rol	$5, \a
+	add	\a, \e
+	add	T1, \d
+	ror	$7, \a		# (a <<r 5) >>r 7) => a <<r 30)
+
+	mov	\e, T1
+	SWAP_REG_NAMES \e, T1
+
+	rol	$5, T1
+	add	T1, \d
+
+	# write:  \a, \b
+	# rotate: \a<=\d, \b<=\e, \c<=\a, \d<=\b, \e<=\c
+.endm
+
+.macro W_PRECALC  r
+  .set i, \r
+
+  .if (i < 20)
+    .set K_XMM, 0
+  .elseif (i < 40)
+    .set K_XMM, 16
+  .elseif (i < 60)
+    .set K_XMM, 32
+  .elseif (i < 80)
+    .set K_XMM, 48
+  .endif
+
+  .if ((i < 16) || ((i >= 80) && (i < (80 + W_PRECALC_AHEAD))))
+    .set i, ((\r) % 80)	    # pre-compute for the next iteration
+    .if (i == 0)
+	W_PRECALC_RESET
+    .endif
+	W_PRECALC_00_15
+  .elseif (i<32)
+	W_PRECALC_16_31
+  .elseif (i < 80)   // rounds 32-79
+	W_PRECALC_32_79
+  .endif
+.endm
+
+.macro W_PRECALC_RESET
+  .set W,          W0
+  .set W_minus_04, W4
+  .set W_minus_08, W8
+  .set W_minus_12, W12
+  .set W_minus_16, W16
+  .set W_minus_20, W20
+  .set W_minus_24, W24
+  .set W_minus_28, W28
+  .set W_minus_32, W
+.endm
+
+.macro W_PRECALC_ROTATE
+  .set W_minus_32, W_minus_28
+  .set W_minus_28, W_minus_24
+  .set W_minus_24, W_minus_20
+  .set W_minus_20, W_minus_16
+  .set W_minus_16, W_minus_12
+  .set W_minus_12, W_minus_08
+  .set W_minus_08, W_minus_04
+  .set W_minus_04, W
+  .set W,          W_minus_32
+.endm
+
+.macro W_PRECALC_SSSE3
+
+.macro W_PRECALC_00_15
+	W_PRECALC_00_15_SSSE3
+.endm
+.macro W_PRECALC_16_31
+	W_PRECALC_16_31_SSSE3
+.endm
+.macro W_PRECALC_32_79
+	W_PRECALC_32_79_SSSE3
+.endm
+
+/* message scheduling pre-compute for rounds 0-15 */
+.macro W_PRECALC_00_15_SSSE3
+  .if ((i & 3) == 0)
+	movdqu	(i*4)(BUFFER_PTR), W_TMP1
+  .elseif ((i & 3) == 1)
+	pshufb	XMM_SHUFB_BSWAP, W_TMP1
+	movdqa	W_TMP1, W
+  .elseif ((i & 3) == 2)
+	paddd	(K_BASE), W_TMP1
+  .elseif ((i & 3) == 3)
+	movdqa  W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+/* message scheduling pre-compute for rounds 16-31
+ *
+ * - calculating last 32 w[i] values in 8 XMM registers
+ * - pre-calculate K+w[i] values and store to mem, for later load by ALU add
+ *   instruction
+ *
+ * some "heavy-lifting" vectorization for rounds 16-31 due to w[i]->w[i-3]
+ * dependency, but improves for 32-79
+ */
+.macro W_PRECALC_16_31_SSSE3
+  # blended scheduling of vector and scalar instruction streams, one 4-wide
+  # vector iteration / 4 scalar rounds
+  .if ((i & 3) == 0)
+	movdqa	W_minus_12, W
+	palignr	$8, W_minus_16, W	# w[i-14]
+	movdqa	W_minus_04, W_TMP1
+	psrldq	$4, W_TMP1		# w[i-3]
+	pxor	W_minus_08, W
+  .elseif ((i & 3) == 1)
+	pxor	W_minus_16, W_TMP1
+	pxor	W_TMP1, W
+	movdqa	W, W_TMP2
+	movdqa	W, W_TMP1
+	pslldq	$12, W_TMP2
+  .elseif ((i & 3) == 2)
+	psrld	$31, W
+	pslld	$1, W_TMP1
+	por	W, W_TMP1
+	movdqa	W_TMP2, W
+	psrld	$30, W_TMP2
+	pslld	$2, W
+  .elseif ((i & 3) == 3)
+	pxor	W, W_TMP1
+	pxor	W_TMP2, W_TMP1
+	movdqa	W_TMP1, W
+	paddd	K_XMM(K_BASE), W_TMP1
+	movdqa	W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+/* message scheduling pre-compute for rounds 32-79
+ *
+ * in SHA-1 specification: w[i] = (w[i-3] ^ w[i-8]  ^ w[i-14] ^ w[i-16]) rol 1
+ * instead we do equal:    w[i] = (w[i-6] ^ w[i-16] ^ w[i-28] ^ w[i-32]) rol 2
+ * allows more efficient vectorization since w[i]=>w[i-3] dependency is broken
+ */
+.macro W_PRECALC_32_79_SSSE3
+  .if ((i & 3) == 0)
+	movdqa	W_minus_04, W_TMP1
+	pxor	W_minus_28, W		# W is W_minus_32 before xor
+	palignr	$8, W_minus_08, W_TMP1
+  .elseif ((i & 3) == 1)
+	pxor	W_minus_16, W
+	pxor	W_TMP1, W
+	movdqa	W, W_TMP1
+  .elseif ((i & 3) == 2)
+	psrld	$30, W
+	pslld	$2, W_TMP1
+	por	W, W_TMP1
+  .elseif ((i & 3) == 3)
+	movdqa	W_TMP1, W
+	paddd	K_XMM(K_BASE), W_TMP1
+	movdqa	W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+.endm		// W_PRECALC_SSSE3
+
+
+#define K1	0x5a827999
+#define K2	0x6ed9eba1
+#define K3	0x8f1bbcdc
+#define K4	0xca62c1d6
+
+.section .rodata
+.align 16
+
+K_XMM_AR:
+	.long K1, K1, K1, K1
+	.long K2, K2, K2, K2
+	.long K3, K3, K3, K3
+	.long K4, K4, K4, K4
+
+BSWAP_SHUFB_CTL:
+	.long 0x00010203
+	.long 0x04050607
+	.long 0x08090a0b
+	.long 0x0c0d0e0f
+
+
+.section .text
+
+W_PRECALC_SSSE3
+.macro xmm_mov a, b
+	movdqu	\a,\b
+.endm
+
+/* SSSE3 optimized implementation:
+ *  extern "C" void sha1_transform_ssse3(u32 *digest, const char *data, u32 *ws,
+ *                                       unsigned int rounds);
+ */
+SHA1_VECTOR_ASM     sha1_transform_ssse3
+
+#ifdef SHA1_ENABLE_AVX_SUPPORT
+
+.macro W_PRECALC_AVX
+
+.purgem W_PRECALC_00_15
+.macro  W_PRECALC_00_15
+    W_PRECALC_00_15_AVX
+.endm
+.purgem W_PRECALC_16_31
+.macro  W_PRECALC_16_31
+    W_PRECALC_16_31_AVX
+.endm
+.purgem W_PRECALC_32_79
+.macro  W_PRECALC_32_79
+    W_PRECALC_32_79_AVX
+.endm
+
+.macro W_PRECALC_00_15_AVX
+  .if ((i & 3) == 0)
+	vmovdqu	(i*4)(BUFFER_PTR), W_TMP1
+  .elseif ((i & 3) == 1)
+	vpshufb	XMM_SHUFB_BSWAP, W_TMP1, W
+  .elseif ((i & 3) == 2)
+	vpaddd	(K_BASE), W, W_TMP1
+  .elseif ((i & 3) == 3)
+	vmovdqa	W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+.macro W_PRECALC_16_31_AVX
+  .if ((i & 3) == 0)
+	vpalignr $8, W_minus_16, W_minus_12, W	# w[i-14]
+	vpsrldq	$4, W_minus_04, W_TMP1		# w[i-3]
+	vpxor	W_minus_08, W, W
+	vpxor	W_minus_16, W_TMP1, W_TMP1
+  .elseif ((i & 3) == 1)
+	vpxor	W_TMP1, W, W
+	vpslldq	$12, W, W_TMP2
+	vpslld	$1, W, W_TMP1
+  .elseif ((i & 3) == 2)
+	vpsrld	$31, W, W
+	vpor	W, W_TMP1, W_TMP1
+	vpslld	$2, W_TMP2, W
+	vpsrld	$30, W_TMP2, W_TMP2
+  .elseif ((i & 3) == 3)
+	vpxor	W, W_TMP1, W_TMP1
+	vpxor	W_TMP2, W_TMP1, W
+	vpaddd	K_XMM(K_BASE), W, W_TMP1
+	vmovdqu	W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+.macro W_PRECALC_32_79_AVX
+  .if ((i & 3) == 0)
+	vpalignr $8, W_minus_08, W_minus_04, W_TMP1
+	vpxor	W_minus_28, W, W		# W is W_minus_32 before xor
+  .elseif ((i & 3) == 1)
+	vpxor	W_minus_16, W_TMP1, W_TMP1
+	vpxor	W_TMP1, W, W
+  .elseif ((i & 3) == 2)
+	vpslld	$2, W, W_TMP1
+	vpsrld	$30, W, W
+	vpor	W, W_TMP1, W
+  .elseif ((i & 3) == 3)
+	vpaddd	K_XMM(K_BASE), W, W_TMP1
+	vmovdqu	W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+.endm    // W_PRECALC_AVX
+
+W_PRECALC_AVX
+.purgem xmm_mov
+.macro xmm_mov a, b
+	vmovdqu	\a,\b
+.endm
+
+
+/* AVX optimized implementation:
+ *  extern "C" void sha1_transform_avx(u32 *digest, const char *data, u32 *ws,
+ *                                     unsigned int rounds);
+ */
+SHA1_VECTOR_ASM     sha1_transform_avx
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/crypto/sha1_ssse3_glue.c linux-libre-3.2-gnu/arch/x86/crypto/sha1_ssse3_glue.c
--- linux-libre-3.1-gnu/arch/x86/crypto/sha1_ssse3_glue.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/crypto/sha1_ssse3_glue.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,240 @@
+/*
+ * Cryptographic API.
+ *
+ * Glue code for the SHA1 Secure Hash Algorithm assembler implementation using
+ * Supplemental SSE3 instructions.
+ *
+ * This file is based on sha1_generic.c
+ *
+ * Copyright (c) Alan Smithee.
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
+ * Copyright (c) Mathias Krause <minipli@googlemail.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.
+ *
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/sha.h>
+#include <asm/byteorder.h>
+#include <asm/i387.h>
+#include <asm/xcr.h>
+#include <asm/xsave.h>
+
+
+asmlinkage void sha1_transform_ssse3(u32 *digest, const char *data,
+				     unsigned int rounds);
+#ifdef SHA1_ENABLE_AVX_SUPPORT
+asmlinkage void sha1_transform_avx(u32 *digest, const char *data,
+				   unsigned int rounds);
+#endif
+
+static asmlinkage void (*sha1_transform_asm)(u32 *, const char *, unsigned int);
+
+
+static int sha1_ssse3_init(struct shash_desc *desc)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+
+	*sctx = (struct sha1_state){
+		.state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 },
+	};
+
+	return 0;
+}
+
+static int __sha1_ssse3_update(struct shash_desc *desc, const u8 *data,
+			       unsigned int len, unsigned int partial)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+	unsigned int done = 0;
+
+	sctx->count += len;
+
+	if (partial) {
+		done = SHA1_BLOCK_SIZE - partial;
+		memcpy(sctx->buffer + partial, data, done);
+		sha1_transform_asm(sctx->state, sctx->buffer, 1);
+	}
+
+	if (len - done >= SHA1_BLOCK_SIZE) {
+		const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE;
+
+		sha1_transform_asm(sctx->state, data + done, rounds);
+		done += rounds * SHA1_BLOCK_SIZE;
+	}
+
+	memcpy(sctx->buffer, data + done, len - done);
+
+	return 0;
+}
+
+static int sha1_ssse3_update(struct shash_desc *desc, const u8 *data,
+			     unsigned int len)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+	unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+	int res;
+
+	/* Handle the fast case right here */
+	if (partial + len < SHA1_BLOCK_SIZE) {
+		sctx->count += len;
+		memcpy(sctx->buffer + partial, data, len);
+
+		return 0;
+	}
+
+	if (!irq_fpu_usable()) {
+		res = crypto_sha1_update(desc, data, len);
+	} else {
+		kernel_fpu_begin();
+		res = __sha1_ssse3_update(desc, data, len, partial);
+		kernel_fpu_end();
+	}
+
+	return res;
+}
+
+
+/* Add padding and return the message digest. */
+static int sha1_ssse3_final(struct shash_desc *desc, u8 *out)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+	unsigned int i, index, padlen;
+	__be32 *dst = (__be32 *)out;
+	__be64 bits;
+	static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, };
+
+	bits = cpu_to_be64(sctx->count << 3);
+
+	/* Pad out to 56 mod 64 and append length */
+	index = sctx->count % SHA1_BLOCK_SIZE;
+	padlen = (index < 56) ? (56 - index) : ((SHA1_BLOCK_SIZE+56) - index);
+	if (!irq_fpu_usable()) {
+		crypto_sha1_update(desc, padding, padlen);
+		crypto_sha1_update(desc, (const u8 *)&bits, sizeof(bits));
+	} else {
+		kernel_fpu_begin();
+		/* We need to fill a whole block for __sha1_ssse3_update() */
+		if (padlen <= 56) {
+			sctx->count += padlen;
+			memcpy(sctx->buffer + index, padding, padlen);
+		} else {
+			__sha1_ssse3_update(desc, padding, padlen, index);
+		}
+		__sha1_ssse3_update(desc, (const u8 *)&bits, sizeof(bits), 56);
+		kernel_fpu_end();
+	}
+
+	/* Store state in digest */
+	for (i = 0; i < 5; i++)
+		dst[i] = cpu_to_be32(sctx->state[i]);
+
+	/* Wipe context */
+	memset(sctx, 0, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha1_ssse3_export(struct shash_desc *desc, void *out)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(out, sctx, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha1_ssse3_import(struct shash_desc *desc, const void *in)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(sctx, in, sizeof(*sctx));
+
+	return 0;
+}
+
+static struct shash_alg alg = {
+	.digestsize	=	SHA1_DIGEST_SIZE,
+	.init		=	sha1_ssse3_init,
+	.update		=	sha1_ssse3_update,
+	.final		=	sha1_ssse3_final,
+	.export		=	sha1_ssse3_export,
+	.import		=	sha1_ssse3_import,
+	.descsize	=	sizeof(struct sha1_state),
+	.statesize	=	sizeof(struct sha1_state),
+	.base		=	{
+		.cra_name	=	"sha1",
+		.cra_driver_name=	"sha1-ssse3",
+		.cra_priority	=	150,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA1_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
+};
+
+#ifdef SHA1_ENABLE_AVX_SUPPORT
+static bool __init avx_usable(void)
+{
+	u64 xcr0;
+
+	if (!cpu_has_avx || !cpu_has_osxsave)
+		return false;
+
+	xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
+	if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) {
+		pr_info("AVX detected but unusable.\n");
+
+		return false;
+	}
+
+	return true;
+}
+#endif
+
+static int __init sha1_ssse3_mod_init(void)
+{
+	/* test for SSSE3 first */
+	if (cpu_has_ssse3)
+		sha1_transform_asm = sha1_transform_ssse3;
+
+#ifdef SHA1_ENABLE_AVX_SUPPORT
+	/* allow AVX to override SSSE3, it's a little faster */
+	if (avx_usable())
+		sha1_transform_asm = sha1_transform_avx;
+#endif
+
+	if (sha1_transform_asm) {
+		pr_info("Using %s optimized SHA-1 implementation\n",
+		        sha1_transform_asm == sha1_transform_ssse3 ? "SSSE3"
+		                                                   : "AVX");
+		return crypto_register_shash(&alg);
+	}
+	pr_info("Neither AVX nor SSSE3 is available/usable.\n");
+
+	return -ENODEV;
+}
+
+static void __exit sha1_ssse3_mod_fini(void)
+{
+	crypto_unregister_shash(&alg);
+}
+
+module_init(sha1_ssse3_mod_init);
+module_exit(sha1_ssse3_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, Supplemental SSE3 accelerated");
+
+MODULE_ALIAS("sha1");
diff -druN linux-libre-3.1-gnu/arch/x86/crypto/twofish_glue_3way.c linux-libre-3.2-gnu/arch/x86/crypto/twofish_glue_3way.c
--- linux-libre-3.1-gnu/arch/x86/crypto/twofish_glue_3way.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/crypto/twofish_glue_3way.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,472 @@
+/*
+ * Glue Code for 3-way parallel assembler optimized version of Twofish
+ *
+ * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
+ *   Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ * CTR part based on code (crypto/ctr.c) by:
+ *   (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.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/crypto.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+#include <crypto/twofish.h>
+#include <crypto/b128ops.h>
+
+/* regular block cipher functions from twofish_x86_64 module */
+asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst,
+				const u8 *src);
+asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst,
+				const u8 *src);
+
+/* 3-way parallel cipher functions */
+asmlinkage void __twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
+				       const u8 *src, bool xor);
+asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst,
+				     const u8 *src);
+
+static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
+					const u8 *src)
+{
+	__twofish_enc_blk_3way(ctx, dst, src, false);
+}
+
+static inline void twofish_enc_blk_xor_3way(struct twofish_ctx *ctx, u8 *dst,
+					    const u8 *src)
+{
+	__twofish_enc_blk_3way(ctx, dst, src, true);
+}
+
+static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
+		     void (*fn)(struct twofish_ctx *, u8 *, const u8 *),
+		     void (*fn_3way)(struct twofish_ctx *, u8 *, const u8 *))
+{
+	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = TF_BLOCK_SIZE;
+	unsigned int nbytes;
+	int err;
+
+	err = blkcipher_walk_virt(desc, walk);
+
+	while ((nbytes = walk->nbytes)) {
+		u8 *wsrc = walk->src.virt.addr;
+		u8 *wdst = walk->dst.virt.addr;
+
+		/* Process three block batch */
+		if (nbytes >= bsize * 3) {
+			do {
+				fn_3way(ctx, wdst, wsrc);
+
+				wsrc += bsize * 3;
+				wdst += bsize * 3;
+				nbytes -= bsize * 3;
+			} while (nbytes >= bsize * 3);
+
+			if (nbytes < bsize)
+				goto done;
+		}
+
+		/* Handle leftovers */
+		do {
+			fn(ctx, wdst, wsrc);
+
+			wsrc += bsize;
+			wdst += bsize;
+			nbytes -= bsize;
+		} while (nbytes >= bsize);
+
+done:
+		err = blkcipher_walk_done(desc, walk, nbytes);
+	}
+
+	return err;
+}
+
+static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	return ecb_crypt(desc, &walk, twofish_enc_blk, twofish_enc_blk_3way);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	return ecb_crypt(desc, &walk, twofish_dec_blk, twofish_dec_blk_3way);
+}
+
+static struct crypto_alg blk_ecb_alg = {
+	.cra_name		= "ecb(twofish)",
+	.cra_driver_name	= "ecb-twofish-3way",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= TF_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct twofish_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_ecb_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= TF_MIN_KEY_SIZE,
+			.max_keysize	= TF_MAX_KEY_SIZE,
+			.setkey		= twofish_setkey,
+			.encrypt	= ecb_encrypt,
+			.decrypt	= ecb_decrypt,
+		},
+	},
+};
+
+static unsigned int __cbc_encrypt(struct blkcipher_desc *desc,
+				  struct blkcipher_walk *walk)
+{
+	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = TF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u128 *src = (u128 *)walk->src.virt.addr;
+	u128 *dst = (u128 *)walk->dst.virt.addr;
+	u128 *iv = (u128 *)walk->iv;
+
+	do {
+		u128_xor(dst, src, iv);
+		twofish_enc_blk(ctx, (u8 *)dst, (u8 *)dst);
+		iv = dst;
+
+		src += 1;
+		dst += 1;
+		nbytes -= bsize;
+	} while (nbytes >= bsize);
+
+	u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv);
+	return nbytes;
+}
+
+static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		nbytes = __cbc_encrypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
+				  struct blkcipher_walk *walk)
+{
+	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = TF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u128 *src = (u128 *)walk->src.virt.addr;
+	u128 *dst = (u128 *)walk->dst.virt.addr;
+	u128 ivs[3 - 1];
+	u128 last_iv;
+
+	/* Start of the last block. */
+	src += nbytes / bsize - 1;
+	dst += nbytes / bsize - 1;
+
+	last_iv = *src;
+
+	/* Process three block batch */
+	if (nbytes >= bsize * 3) {
+		do {
+			nbytes -= bsize * (3 - 1);
+			src -= 3 - 1;
+			dst -= 3 - 1;
+
+			ivs[0] = src[0];
+			ivs[1] = src[1];
+
+			twofish_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src);
+
+			u128_xor(dst + 1, dst + 1, ivs + 0);
+			u128_xor(dst + 2, dst + 2, ivs + 1);
+
+			nbytes -= bsize;
+			if (nbytes < bsize)
+				goto done;
+
+			u128_xor(dst, dst, src - 1);
+			src -= 1;
+			dst -= 1;
+		} while (nbytes >= bsize * 3);
+
+		if (nbytes < bsize)
+			goto done;
+	}
+
+	/* Handle leftovers */
+	for (;;) {
+		twofish_dec_blk(ctx, (u8 *)dst, (u8 *)src);
+
+		nbytes -= bsize;
+		if (nbytes < bsize)
+			break;
+
+		u128_xor(dst, dst, src - 1);
+		src -= 1;
+		dst -= 1;
+	}
+
+done:
+	u128_xor(dst, dst, (u128 *)walk->iv);
+	*(u128 *)walk->iv = last_iv;
+
+	return nbytes;
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		nbytes = __cbc_decrypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static struct crypto_alg blk_cbc_alg = {
+	.cra_name		= "cbc(twofish)",
+	.cra_driver_name	= "cbc-twofish-3way",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= TF_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct twofish_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_cbc_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= TF_MIN_KEY_SIZE,
+			.max_keysize	= TF_MAX_KEY_SIZE,
+			.ivsize		= TF_BLOCK_SIZE,
+			.setkey		= twofish_setkey,
+			.encrypt	= cbc_encrypt,
+			.decrypt	= cbc_decrypt,
+		},
+	},
+};
+
+static inline void u128_to_be128(be128 *dst, const u128 *src)
+{
+	dst->a = cpu_to_be64(src->a);
+	dst->b = cpu_to_be64(src->b);
+}
+
+static inline void be128_to_u128(u128 *dst, const be128 *src)
+{
+	dst->a = be64_to_cpu(src->a);
+	dst->b = be64_to_cpu(src->b);
+}
+
+static inline void u128_inc(u128 *i)
+{
+	i->b++;
+	if (!i->b)
+		i->a++;
+}
+
+static void ctr_crypt_final(struct blkcipher_desc *desc,
+			    struct blkcipher_walk *walk)
+{
+	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	u8 *ctrblk = walk->iv;
+	u8 keystream[TF_BLOCK_SIZE];
+	u8 *src = walk->src.virt.addr;
+	u8 *dst = walk->dst.virt.addr;
+	unsigned int nbytes = walk->nbytes;
+
+	twofish_enc_blk(ctx, keystream, ctrblk);
+	crypto_xor(keystream, src, nbytes);
+	memcpy(dst, keystream, nbytes);
+
+	crypto_inc(ctrblk, TF_BLOCK_SIZE);
+}
+
+static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
+				struct blkcipher_walk *walk)
+{
+	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = TF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u128 *src = (u128 *)walk->src.virt.addr;
+	u128 *dst = (u128 *)walk->dst.virt.addr;
+	u128 ctrblk;
+	be128 ctrblocks[3];
+
+	be128_to_u128(&ctrblk, (be128 *)walk->iv);
+
+	/* Process three block batch */
+	if (nbytes >= bsize * 3) {
+		do {
+			if (dst != src) {
+				dst[0] = src[0];
+				dst[1] = src[1];
+				dst[2] = src[2];
+			}
+
+			/* create ctrblks for parallel encrypt */
+			u128_to_be128(&ctrblocks[0], &ctrblk);
+			u128_inc(&ctrblk);
+			u128_to_be128(&ctrblocks[1], &ctrblk);
+			u128_inc(&ctrblk);
+			u128_to_be128(&ctrblocks[2], &ctrblk);
+			u128_inc(&ctrblk);
+
+			twofish_enc_blk_xor_3way(ctx, (u8 *)dst,
+						 (u8 *)ctrblocks);
+
+			src += 3;
+			dst += 3;
+			nbytes -= bsize * 3;
+		} while (nbytes >= bsize * 3);
+
+		if (nbytes < bsize)
+			goto done;
+	}
+
+	/* Handle leftovers */
+	do {
+		if (dst != src)
+			*dst = *src;
+
+		u128_to_be128(&ctrblocks[0], &ctrblk);
+		u128_inc(&ctrblk);
+
+		twofish_enc_blk(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks);
+		u128_xor(dst, dst, (u128 *)ctrblocks);
+
+		src += 1;
+		dst += 1;
+		nbytes -= bsize;
+	} while (nbytes >= bsize);
+
+done:
+	u128_to_be128((be128 *)walk->iv, &ctrblk);
+	return nbytes;
+}
+
+static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		     struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt_block(desc, &walk, TF_BLOCK_SIZE);
+
+	while ((nbytes = walk.nbytes) >= TF_BLOCK_SIZE) {
+		nbytes = __ctr_crypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	if (walk.nbytes) {
+		ctr_crypt_final(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, 0);
+	}
+
+	return err;
+}
+
+static struct crypto_alg blk_ctr_alg = {
+	.cra_name		= "ctr(twofish)",
+	.cra_driver_name	= "ctr-twofish-3way",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= 1,
+	.cra_ctxsize		= sizeof(struct twofish_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_ctr_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= TF_MIN_KEY_SIZE,
+			.max_keysize	= TF_MAX_KEY_SIZE,
+			.ivsize		= TF_BLOCK_SIZE,
+			.setkey		= twofish_setkey,
+			.encrypt	= ctr_crypt,
+			.decrypt	= ctr_crypt,
+		},
+	},
+};
+
+int __init init(void)
+{
+	int err;
+
+	err = crypto_register_alg(&blk_ecb_alg);
+	if (err)
+		goto ecb_err;
+	err = crypto_register_alg(&blk_cbc_alg);
+	if (err)
+		goto cbc_err;
+	err = crypto_register_alg(&blk_ctr_alg);
+	if (err)
+		goto ctr_err;
+
+	return 0;
+
+ctr_err:
+	crypto_unregister_alg(&blk_cbc_alg);
+cbc_err:
+	crypto_unregister_alg(&blk_ecb_alg);
+ecb_err:
+	return err;
+}
+
+void __exit fini(void)
+{
+	crypto_unregister_alg(&blk_ctr_alg);
+	crypto_unregister_alg(&blk_cbc_alg);
+	crypto_unregister_alg(&blk_ecb_alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Twofish Cipher Algorithm, 3-way parallel asm optimized");
+MODULE_ALIAS("twofish");
+MODULE_ALIAS("twofish-asm");
diff -druN linux-libre-3.1-gnu/arch/x86/crypto/twofish_glue.c linux-libre-3.2-gnu/arch/x86/crypto/twofish_glue.c
--- linux-libre-3.1-gnu/arch/x86/crypto/twofish_glue.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/crypto/twofish_glue.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,17 +44,21 @@
 #include <linux/module.h>
 #include <linux/types.h>
 
-asmlinkage void twofish_enc_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
-asmlinkage void twofish_dec_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
+asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst,
+				const u8 *src);
+EXPORT_SYMBOL_GPL(twofish_enc_blk);
+asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst,
+				const u8 *src);
+EXPORT_SYMBOL_GPL(twofish_dec_blk);
 
 static void twofish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	twofish_enc_blk(tfm, dst, src);
+	twofish_enc_blk(crypto_tfm_ctx(tfm), dst, src);
 }
 
 static void twofish_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	twofish_dec_blk(tfm, dst, src);
+	twofish_dec_blk(crypto_tfm_ctx(tfm), dst, src);
 }
 
 static struct crypto_alg alg = {
diff -druN linux-libre-3.1-gnu/arch/x86/crypto/twofish-i586-asm_32.S linux-libre-3.2-gnu/arch/x86/crypto/twofish-i586-asm_32.S
--- linux-libre-3.1-gnu/arch/x86/crypto/twofish-i586-asm_32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/crypto/twofish-i586-asm_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -26,7 +26,7 @@
 
 #define in_blk    12  /* input byte array address parameter*/
 #define out_blk   8  /* output byte array address parameter*/
-#define tfm       4  /* Twofish context structure */
+#define ctx       4  /* Twofish context structure */
 
 #define a_offset	0
 #define b_offset	4
@@ -229,8 +229,8 @@
 	push    %esi
 	push    %edi
 
-	mov	tfm + 16(%esp),	%ebp	/* abuse the base pointer: set new base bointer to the crypto tfm */
-	add	$crypto_tfm_ctx_offset, %ebp	/* ctx address */
+	mov	ctx + 16(%esp),	%ebp	/* abuse the base pointer: set new base
+					 * pointer to the ctx address */
 	mov     in_blk+16(%esp),%edi	/* input address in edi */
 
 	mov	(%edi),		%eax
@@ -285,8 +285,8 @@
 	push    %edi
 
 
-	mov	tfm + 16(%esp),	%ebp	/* abuse the base pointer: set new base bointer to the crypto tfm */
-	add	$crypto_tfm_ctx_offset, %ebp	/* ctx address */
+	mov	ctx + 16(%esp),	%ebp	/* abuse the base pointer: set new base
+					 * pointer to the ctx address */
 	mov     in_blk+16(%esp),%edi	/* input address in edi */
 
 	mov	(%edi),		%eax
diff -druN linux-libre-3.1-gnu/arch/x86/crypto/twofish-x86_64-asm_64-3way.S linux-libre-3.2-gnu/arch/x86/crypto/twofish-x86_64-asm_64-3way.S
--- linux-libre-3.1-gnu/arch/x86/crypto/twofish-x86_64-asm_64-3way.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/crypto/twofish-x86_64-asm_64-3way.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,316 @@
+/*
+ * Twofish Cipher 3-way parallel algorithm (x86_64)
+ *
+ * Copyright (C) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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
+ *
+ */
+
+.file "twofish-x86_64-asm-3way.S"
+.text
+
+/* structure of crypto context */
+#define s0	0
+#define s1	1024
+#define s2	2048
+#define s3	3072
+#define w	4096
+#define k	4128
+
+/**********************************************************************
+  3-way twofish
+ **********************************************************************/
+#define CTX %rdi
+#define RIO %rdx
+
+#define RAB0 %rax
+#define RAB1 %rbx
+#define RAB2 %rcx
+
+#define RAB0d %eax
+#define RAB1d %ebx
+#define RAB2d %ecx
+
+#define RAB0bh %ah
+#define RAB1bh %bh
+#define RAB2bh %ch
+
+#define RAB0bl %al
+#define RAB1bl %bl
+#define RAB2bl %cl
+
+#define RCD0 %r8
+#define RCD1 %r9
+#define RCD2 %r10
+
+#define RCD0d %r8d
+#define RCD1d %r9d
+#define RCD2d %r10d
+
+#define RX0 %rbp
+#define RX1 %r11
+#define RX2 %r12
+
+#define RX0d %ebp
+#define RX1d %r11d
+#define RX2d %r12d
+
+#define RY0 %r13
+#define RY1 %r14
+#define RY2 %r15
+
+#define RY0d %r13d
+#define RY1d %r14d
+#define RY2d %r15d
+
+#define RT0 %rdx
+#define RT1 %rsi
+
+#define RT0d %edx
+#define RT1d %esi
+
+#define do16bit_ror(rot, op1, op2, T0, T1, tmp1, tmp2, ab, dst) \
+	movzbl ab ## bl,		tmp2 ## d; \
+	movzbl ab ## bh,		tmp1 ## d; \
+	rorq $(rot),			ab; \
+	op1##l T0(CTX, tmp2, 4),	dst ## d; \
+	op2##l T1(CTX, tmp1, 4),	dst ## d;
+
+/*
+ * Combined G1 & G2 function. Reordered with help of rotates to have moves
+ * at begining.
+ */
+#define g1g2_3(ab, cd, Tx0, Tx1, Tx2, Tx3, Ty0, Ty1, Ty2, Ty3, x, y) \
+	/* G1,1 && G2,1 */ \
+	do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 0, ab ## 0, x ## 0); \
+	do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 0, ab ## 0, y ## 0); \
+	\
+	do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 1, ab ## 1, x ## 1); \
+	do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 1, ab ## 1, y ## 1); \
+	\
+	do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 2, ab ## 2, x ## 2); \
+	do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 2, ab ## 2, y ## 2); \
+	\
+	/* G1,2 && G2,2 */ \
+	do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 0, x ## 0); \
+	do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 0, y ## 0); \
+	xchgq cd ## 0, ab ## 0; \
+	\
+	do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 1, x ## 1); \
+	do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 1, y ## 1); \
+	xchgq cd ## 1, ab ## 1; \
+	\
+	do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 2, x ## 2); \
+	do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 2, y ## 2); \
+	xchgq cd ## 2, ab ## 2;
+
+#define enc_round_end(ab, x, y, n) \
+	addl y ## d,			x ## d; \
+	addl x ## d,			y ## d; \
+	addl k+4*(2*(n))(CTX),		x ## d; \
+	xorl ab ## d,			x ## d; \
+	addl k+4*(2*(n)+1)(CTX),	y ## d; \
+	shrq $32,			ab; \
+	roll $1,			ab ## d; \
+	xorl y ## d,			ab ## d; \
+	shlq $32,			ab; \
+	rorl $1,			x ## d; \
+	orq x,				ab;
+
+#define dec_round_end(ba, x, y, n) \
+	addl y ## d,			x ## d; \
+	addl x ## d,			y ## d; \
+	addl k+4*(2*(n))(CTX),		x ## d; \
+	addl k+4*(2*(n)+1)(CTX),	y ## d; \
+	xorl ba ## d,			y ## d; \
+	shrq $32,			ba; \
+	roll $1,			ba ## d; \
+	xorl x ## d,			ba ## d; \
+	shlq $32,			ba; \
+	rorl $1,			y ## d; \
+	orq y,				ba;
+
+#define encrypt_round3(ab, cd, n) \
+	g1g2_3(ab, cd, s0, s1, s2, s3, s0, s1, s2, s3, RX, RY); \
+	\
+	enc_round_end(ab ## 0, RX0, RY0, n); \
+	enc_round_end(ab ## 1, RX1, RY1, n); \
+	enc_round_end(ab ## 2, RX2, RY2, n);
+
+#define decrypt_round3(ba, dc, n) \
+	g1g2_3(ba, dc, s1, s2, s3, s0, s3, s0, s1, s2, RY, RX); \
+	\
+	dec_round_end(ba ## 0, RX0, RY0, n); \
+	dec_round_end(ba ## 1, RX1, RY1, n); \
+	dec_round_end(ba ## 2, RX2, RY2, n);
+
+#define encrypt_cycle3(ab, cd, n) \
+	encrypt_round3(ab, cd, n*2); \
+	encrypt_round3(ab, cd, (n*2)+1);
+
+#define decrypt_cycle3(ba, dc, n) \
+	decrypt_round3(ba, dc, (n*2)+1); \
+	decrypt_round3(ba, dc, (n*2));
+
+#define inpack3(in, n, xy, m) \
+	movq 4*(n)(in),			xy ## 0; \
+	xorq w+4*m(CTX),		xy ## 0; \
+	\
+	movq 4*(4+(n))(in),		xy ## 1; \
+	xorq w+4*m(CTX),		xy ## 1; \
+	\
+	movq 4*(8+(n))(in),		xy ## 2; \
+	xorq w+4*m(CTX),		xy ## 2;
+
+#define outunpack3(op, out, n, xy, m) \
+	xorq w+4*m(CTX),		xy ## 0; \
+	op ## q xy ## 0,		4*(n)(out); \
+	\
+	xorq w+4*m(CTX),		xy ## 1; \
+	op ## q xy ## 1,		4*(4+(n))(out); \
+	\
+	xorq w+4*m(CTX),		xy ## 2; \
+	op ## q xy ## 2,		4*(8+(n))(out);
+
+#define inpack_enc3() \
+	inpack3(RIO, 0, RAB, 0); \
+	inpack3(RIO, 2, RCD, 2);
+
+#define outunpack_enc3(op) \
+	outunpack3(op, RIO, 2, RAB, 6); \
+	outunpack3(op, RIO, 0, RCD, 4);
+
+#define inpack_dec3() \
+	inpack3(RIO, 0, RAB, 4); \
+	rorq $32,			RAB0; \
+	rorq $32,			RAB1; \
+	rorq $32,			RAB2; \
+	inpack3(RIO, 2, RCD, 6); \
+	rorq $32,			RCD0; \
+	rorq $32,			RCD1; \
+	rorq $32,			RCD2;
+
+#define outunpack_dec3() \
+	rorq $32,			RCD0; \
+	rorq $32,			RCD1; \
+	rorq $32,			RCD2; \
+	outunpack3(mov, RIO, 0, RCD, 0); \
+	rorq $32,			RAB0; \
+	rorq $32,			RAB1; \
+	rorq $32,			RAB2; \
+	outunpack3(mov, RIO, 2, RAB, 2);
+
+.align 8
+.global __twofish_enc_blk_3way
+.type   __twofish_enc_blk_3way,@function;
+
+__twofish_enc_blk_3way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src, RIO
+	 *	%rcx: bool, if true: xor output
+	 */
+	pushq %r15;
+	pushq %r14;
+	pushq %r13;
+	pushq %r12;
+	pushq %rbp;
+	pushq %rbx;
+
+	pushq %rcx; /* bool xor */
+	pushq %rsi; /* dst */
+
+	inpack_enc3();
+
+	encrypt_cycle3(RAB, RCD, 0);
+	encrypt_cycle3(RAB, RCD, 1);
+	encrypt_cycle3(RAB, RCD, 2);
+	encrypt_cycle3(RAB, RCD, 3);
+	encrypt_cycle3(RAB, RCD, 4);
+	encrypt_cycle3(RAB, RCD, 5);
+	encrypt_cycle3(RAB, RCD, 6);
+	encrypt_cycle3(RAB, RCD, 7);
+
+	popq RIO; /* dst */
+	popq %rbp; /* bool xor */
+
+	testb %bpl, %bpl;
+	jnz __enc_xor3;
+
+	outunpack_enc3(mov);
+
+	popq %rbx;
+	popq %rbp;
+	popq %r12;
+	popq %r13;
+	popq %r14;
+	popq %r15;
+	ret;
+
+__enc_xor3:
+	outunpack_enc3(xor);
+
+	popq %rbx;
+	popq %rbp;
+	popq %r12;
+	popq %r13;
+	popq %r14;
+	popq %r15;
+	ret;
+
+.global twofish_dec_blk_3way
+.type   twofish_dec_blk_3way,@function;
+
+twofish_dec_blk_3way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src, RIO
+	 */
+	pushq %r15;
+	pushq %r14;
+	pushq %r13;
+	pushq %r12;
+	pushq %rbp;
+	pushq %rbx;
+
+	pushq %rsi; /* dst */
+
+	inpack_dec3();
+
+	decrypt_cycle3(RAB, RCD, 7);
+	decrypt_cycle3(RAB, RCD, 6);
+	decrypt_cycle3(RAB, RCD, 5);
+	decrypt_cycle3(RAB, RCD, 4);
+	decrypt_cycle3(RAB, RCD, 3);
+	decrypt_cycle3(RAB, RCD, 2);
+	decrypt_cycle3(RAB, RCD, 1);
+	decrypt_cycle3(RAB, RCD, 0);
+
+	popq RIO; /* dst */
+
+	outunpack_dec3();
+
+	popq %rbx;
+	popq %rbp;
+	popq %r12;
+	popq %r13;
+	popq %r14;
+	popq %r15;
+	ret;
+
diff -druN linux-libre-3.1-gnu/arch/x86/crypto/twofish-x86_64-asm_64.S linux-libre-3.2-gnu/arch/x86/crypto/twofish-x86_64-asm_64.S
--- linux-libre-3.1-gnu/arch/x86/crypto/twofish-x86_64-asm_64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/crypto/twofish-x86_64-asm_64.S	2012-01-04 18:55:44.000000000 -0500
@@ -221,10 +221,9 @@
 twofish_enc_blk:
 	pushq    R1
 
-	/* %rdi contains the crypto tfm address */
+	/* %rdi contains the ctx address */
 	/* %rsi contains the output address */
 	/* %rdx contains the input address */
-	add	$crypto_tfm_ctx_offset, %rdi	/* set ctx address */
 	/* ctx address is moved to free one non-rex register
 	as target for the 8bit high operations */
 	mov	%rdi,		%r11
@@ -274,10 +273,9 @@
 twofish_dec_blk:
 	pushq    R1
 
-	/* %rdi contains the crypto tfm address */
+	/* %rdi contains the ctx address */
 	/* %rsi contains the output address */
 	/* %rdx contains the input address */
-	add	$crypto_tfm_ctx_offset, %rdi	/* set ctx address */
 	/* ctx address is moved to free one non-rex register
 	as target for the 8bit high operations */
 	mov	%rdi,		%r11
diff -druN linux-libre-3.1-gnu/arch/x86/ia32/ia32entry.S linux-libre-3.2-gnu/arch/x86/ia32/ia32entry.S
--- linux-libre-3.1-gnu/arch/x86/ia32/ia32entry.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/ia32/ia32entry.S	2012-01-04 18:55:44.000000000 -0500
@@ -850,4 +850,6 @@
 	.quad sys_syncfs
 	.quad compat_sys_sendmmsg	/* 345 */
 	.quad sys_setns
+	.quad compat_sys_process_vm_readv
+	.quad compat_sys_process_vm_writev
 ia32_syscall_end:
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/amd_nb.h linux-libre-3.2-gnu/arch/x86/include/asm/amd_nb.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/amd_nb.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/amd_nb.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,9 +19,15 @@
 extern int amd_get_subcaches(int);
 extern int amd_set_subcaches(int, int);
 
+struct amd_l3_cache {
+	unsigned indices;
+	u8	 subcaches[4];
+};
+
 struct amd_northbridge {
 	struct pci_dev *misc;
 	struct pci_dev *link;
+	struct amd_l3_cache l3_cache;
 };
 
 struct amd_northbridge_info {
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/apicdef.h linux-libre-3.2-gnu/arch/x86/include/asm/apicdef.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/apicdef.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/apicdef.h	2012-01-04 18:55:44.000000000 -0500
@@ -100,7 +100,9 @@
 #define		APIC_TIMER_BASE_CLKIN		0x0
 #define		APIC_TIMER_BASE_TMBASE		0x1
 #define		APIC_TIMER_BASE_DIV		0x2
+#define		APIC_LVT_TIMER_ONESHOT		(0 << 17)
 #define		APIC_LVT_TIMER_PERIODIC		(1 << 17)
+#define		APIC_LVT_TIMER_TSCDEADLINE	(2 << 17)
 #define		APIC_LVT_MASKED			(1 << 16)
 #define		APIC_LVT_LEVEL_TRIGGER		(1 << 15)
 #define		APIC_LVT_REMOTE_IRR		(1 << 14)
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/apic.h linux-libre-3.2-gnu/arch/x86/include/asm/apic.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/apic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/apic.h	2012-01-04 18:55:44.000000000 -0500
@@ -49,6 +49,7 @@
 extern int local_apic_timer_c2_ok;
 
 extern int disable_apic;
+extern unsigned int lapic_timer_frequency;
 
 #ifdef CONFIG_SMP
 extern void __inquire_remote_apic(int apicid);
@@ -495,7 +496,7 @@
 	return;
 }
 
-extern struct apic *generic_bigsmp_probe(void);
+extern void generic_bigsmp_probe(void);
 
 
 #ifdef CONFIG_X86_LOCAL_APIC
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/archrandom.h linux-libre-3.2-gnu/arch/x86/include/asm/archrandom.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/archrandom.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/include/asm/archrandom.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the Linux kernel.
+ *
+ * Copyright (c) 2011, Intel Corporation
+ * Authors: Fenghua Yu <fenghua.yu@intel.com>,
+ *          H. Peter Anvin <hpa@linux.intel.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef ASM_X86_ARCHRANDOM_H
+#define ASM_X86_ARCHRANDOM_H
+
+#include <asm/processor.h>
+#include <asm/cpufeature.h>
+#include <asm/alternative.h>
+#include <asm/nops.h>
+
+#define RDRAND_RETRY_LOOPS	10
+
+#define RDRAND_INT	".byte 0x0f,0xc7,0xf0"
+#ifdef CONFIG_X86_64
+# define RDRAND_LONG	".byte 0x48,0x0f,0xc7,0xf0"
+#else
+# define RDRAND_LONG	RDRAND_INT
+#endif
+
+#ifdef CONFIG_ARCH_RANDOM
+
+#define GET_RANDOM(name, type, rdrand, nop)			\
+static inline int name(type *v)					\
+{								\
+	int ok;							\
+	alternative_io("movl $0, %0\n\t"			\
+		       nop,					\
+		       "\n1: " rdrand "\n\t"			\
+		       "jc 2f\n\t"				\
+		       "decl %0\n\t"                            \
+		       "jnz 1b\n\t"                             \
+		       "2:",                                    \
+		       X86_FEATURE_RDRAND,                      \
+		       ASM_OUTPUT2("=r" (ok), "=a" (*v)),       \
+		       "0" (RDRAND_RETRY_LOOPS));		\
+	return ok;						\
+}
+
+#ifdef CONFIG_X86_64
+
+GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP5);
+GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP4);
+
+#else
+
+GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP3);
+GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP3);
+
+#endif /* CONFIG_X86_64 */
+
+#endif  /* CONFIG_ARCH_RANDOM */
+
+extern void x86_init_rdrand(struct cpuinfo_x86 *c);
+
+#endif /* ASM_X86_ARCHRANDOM_H */
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/atomic64_64.h linux-libre-3.2-gnu/arch/x86/include/asm/atomic64_64.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/atomic64_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/atomic64_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -170,11 +170,7 @@
  */
 static inline long atomic64_add_return(long i, atomic64_t *v)
 {
-	long __i = i;
-	asm volatile(LOCK_PREFIX "xaddq %0, %1;"
-		     : "+r" (i), "+m" (v->counter)
-		     : : "memory");
-	return i + __i;
+	return i + xadd(&v->counter, i);
 }
 
 static inline long atomic64_sub_return(long i, atomic64_t *v)
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/atomic.h linux-libre-3.2-gnu/arch/x86/include/asm/atomic.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/atomic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/atomic.h	2012-01-04 18:55:44.000000000 -0500
@@ -172,18 +172,14 @@
  */
 static inline int atomic_add_return(int i, atomic_t *v)
 {
-	int __i;
 #ifdef CONFIG_M386
+	int __i;
 	unsigned long flags;
 	if (unlikely(boot_cpu_data.x86 <= 3))
 		goto no_xadd;
 #endif
 	/* Modern 486+ processor */
-	__i = i;
-	asm volatile(LOCK_PREFIX "xaddl %0, %1"
-		     : "+r" (i), "+m" (v->counter)
-		     : : "memory");
-	return i + __i;
+	return i + xadd(&v->counter, i);
 
 #ifdef CONFIG_M386
 no_xadd: /* Legacy 386 processor */
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/cmpxchg_32.h linux-libre-3.2-gnu/arch/x86/include/asm/cmpxchg_32.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/cmpxchg_32.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/cmpxchg_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,61 +1,11 @@
 #ifndef _ASM_X86_CMPXCHG_32_H
 #define _ASM_X86_CMPXCHG_32_H
 
-#include <linux/bitops.h> /* for LOCK_PREFIX */
-
 /*
  * Note: if you use set64_bit(), __cmpxchg64(), or their variants, you
  *       you need to test for the feature in boot_cpu_data.
  */
 
-extern void __xchg_wrong_size(void);
-
-/*
- * Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
- * Since this is generally used to protect other memory information, we
- * use "asm volatile" and "memory" clobbers to prevent gcc from moving
- * information around.
- */
-#define __xchg(x, ptr, size)						\
-({									\
-	__typeof(*(ptr)) __x = (x);					\
-	switch (size) {							\
-	case 1:								\
-	{								\
-		volatile u8 *__ptr = (volatile u8 *)(ptr);		\
-		asm volatile("xchgb %0,%1"				\
-			     : "=q" (__x), "+m" (*__ptr)		\
-			     : "0" (__x)				\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 2:								\
-	{								\
-		volatile u16 *__ptr = (volatile u16 *)(ptr);		\
-		asm volatile("xchgw %0,%1"				\
-			     : "=r" (__x), "+m" (*__ptr)		\
-			     : "0" (__x)				\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 4:								\
-	{								\
-		volatile u32 *__ptr = (volatile u32 *)(ptr);		\
-		asm volatile("xchgl %0,%1"				\
-			     : "=r" (__x), "+m" (*__ptr)		\
-			     : "0" (__x)				\
-			     : "memory");				\
-		break;							\
-	}								\
-	default:							\
-		__xchg_wrong_size();					\
-	}								\
-	__x;								\
-})
-
-#define xchg(ptr, v)							\
-	__xchg((v), (ptr), sizeof(*ptr))
-
 /*
  * CMPXCHG8B only writes to the target if we had the previous
  * value in registers, otherwise it acts as a read and gives us the
@@ -84,72 +34,8 @@
 		     : "memory");
 }
 
-extern void __cmpxchg_wrong_size(void);
-
-/*
- * 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 __raw_cmpxchg(ptr, old, new, size, lock)			\
-({									\
-	__typeof__(*(ptr)) __ret;					\
-	__typeof__(*(ptr)) __old = (old);				\
-	__typeof__(*(ptr)) __new = (new);				\
-	switch (size) {							\
-	case 1:								\
-	{								\
-		volatile u8 *__ptr = (volatile u8 *)(ptr);		\
-		asm volatile(lock "cmpxchgb %2,%1"			\
-			     : "=a" (__ret), "+m" (*__ptr)		\
-			     : "q" (__new), "0" (__old)			\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 2:								\
-	{								\
-		volatile u16 *__ptr = (volatile u16 *)(ptr);		\
-		asm volatile(lock "cmpxchgw %2,%1"			\
-			     : "=a" (__ret), "+m" (*__ptr)		\
-			     : "r" (__new), "0" (__old)			\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 4:								\
-	{								\
-		volatile u32 *__ptr = (volatile u32 *)(ptr);		\
-		asm volatile(lock "cmpxchgl %2,%1"			\
-			     : "=a" (__ret), "+m" (*__ptr)		\
-			     : "r" (__new), "0" (__old)			\
-			     : "memory");				\
-		break;							\
-	}								\
-	default:							\
-		__cmpxchg_wrong_size();					\
-	}								\
-	__ret;								\
-})
-
-#define __cmpxchg(ptr, old, new, size)					\
-	__raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
-
-#define __sync_cmpxchg(ptr, old, new, size)				\
-	__raw_cmpxchg((ptr), (old), (new), (size), "lock; ")
-
-#define __cmpxchg_local(ptr, old, new, size)				\
-	__raw_cmpxchg((ptr), (old), (new), (size), "")
-
 #ifdef CONFIG_X86_CMPXCHG
 #define __HAVE_ARCH_CMPXCHG 1
-
-#define cmpxchg(ptr, old, new)						\
-	__cmpxchg((ptr), (old), (new), sizeof(*ptr))
-
-#define sync_cmpxchg(ptr, old, new)					\
-	__sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
-
-#define cmpxchg_local(ptr, old, new)					\
-	__cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
 #endif
 
 #ifdef CONFIG_X86_CMPXCHG64
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/cmpxchg_64.h linux-libre-3.2-gnu/arch/x86/include/asm/cmpxchg_64.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/cmpxchg_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/cmpxchg_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,144 +1,13 @@
 #ifndef _ASM_X86_CMPXCHG_64_H
 #define _ASM_X86_CMPXCHG_64_H
 
-#include <asm/alternative.h> /* Provides LOCK_PREFIX */
-
 static inline void set_64bit(volatile u64 *ptr, u64 val)
 {
 	*ptr = val;
 }
 
-extern void __xchg_wrong_size(void);
-extern void __cmpxchg_wrong_size(void);
-
-/*
- * Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
- * Since this is generally used to protect other memory information, we
- * use "asm volatile" and "memory" clobbers to prevent gcc from moving
- * information around.
- */
-#define __xchg(x, ptr, size)						\
-({									\
-	__typeof(*(ptr)) __x = (x);					\
-	switch (size) {							\
-	case 1:								\
-	{								\
-		volatile u8 *__ptr = (volatile u8 *)(ptr);		\
-		asm volatile("xchgb %0,%1"				\
-			     : "=q" (__x), "+m" (*__ptr)		\
-			     : "0" (__x)				\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 2:								\
-	{								\
-		volatile u16 *__ptr = (volatile u16 *)(ptr);		\
-		asm volatile("xchgw %0,%1"				\
-			     : "=r" (__x), "+m" (*__ptr)		\
-			     : "0" (__x)				\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 4:								\
-	{								\
-		volatile u32 *__ptr = (volatile u32 *)(ptr);		\
-		asm volatile("xchgl %0,%1"				\
-			     : "=r" (__x), "+m" (*__ptr)		\
-			     : "0" (__x)				\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 8:								\
-	{								\
-		volatile u64 *__ptr = (volatile u64 *)(ptr);		\
-		asm volatile("xchgq %0,%1"				\
-			     : "=r" (__x), "+m" (*__ptr)		\
-			     : "0" (__x)				\
-			     : "memory");				\
-		break;							\
-	}								\
-	default:							\
-		__xchg_wrong_size();					\
-	}								\
-	__x;								\
-})
-
-#define xchg(ptr, v)							\
-	__xchg((v), (ptr), sizeof(*ptr))
-
 #define __HAVE_ARCH_CMPXCHG 1
 
-/*
- * 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 __raw_cmpxchg(ptr, old, new, size, lock)			\
-({									\
-	__typeof__(*(ptr)) __ret;					\
-	__typeof__(*(ptr)) __old = (old);				\
-	__typeof__(*(ptr)) __new = (new);				\
-	switch (size) {							\
-	case 1:								\
-	{								\
-		volatile u8 *__ptr = (volatile u8 *)(ptr);		\
-		asm volatile(lock "cmpxchgb %2,%1"			\
-			     : "=a" (__ret), "+m" (*__ptr)		\
-			     : "q" (__new), "0" (__old)			\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 2:								\
-	{								\
-		volatile u16 *__ptr = (volatile u16 *)(ptr);		\
-		asm volatile(lock "cmpxchgw %2,%1"			\
-			     : "=a" (__ret), "+m" (*__ptr)		\
-			     : "r" (__new), "0" (__old)			\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 4:								\
-	{								\
-		volatile u32 *__ptr = (volatile u32 *)(ptr);		\
-		asm volatile(lock "cmpxchgl %2,%1"			\
-			     : "=a" (__ret), "+m" (*__ptr)		\
-			     : "r" (__new), "0" (__old)			\
-			     : "memory");				\
-		break;							\
-	}								\
-	case 8:								\
-	{								\
-		volatile u64 *__ptr = (volatile u64 *)(ptr);		\
-		asm volatile(lock "cmpxchgq %2,%1"			\
-			     : "=a" (__ret), "+m" (*__ptr)		\
-			     : "r" (__new), "0" (__old)			\
-			     : "memory");				\
-		break;							\
-	}								\
-	default:							\
-		__cmpxchg_wrong_size();					\
-	}								\
-	__ret;								\
-})
-
-#define __cmpxchg(ptr, old, new, size)					\
-	__raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
-
-#define __sync_cmpxchg(ptr, old, new, size)				\
-	__raw_cmpxchg((ptr), (old), (new), (size), "lock; ")
-
-#define __cmpxchg_local(ptr, old, new, size)				\
-	__raw_cmpxchg((ptr), (old), (new), (size), "")
-
-#define cmpxchg(ptr, old, new)						\
-	__cmpxchg((ptr), (old), (new), sizeof(*ptr))
-
-#define sync_cmpxchg(ptr, old, new)					\
-	__sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
-
-#define cmpxchg_local(ptr, old, new)					\
-	__cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
-
 #define cmpxchg64(ptr, o, n)						\
 ({									\
 	BUILD_BUG_ON(sizeof(*(ptr)) != 8);				\
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/cmpxchg.h linux-libre-3.2-gnu/arch/x86/include/asm/cmpxchg.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/cmpxchg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/cmpxchg.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,210 @@
+#ifndef ASM_X86_CMPXCHG_H
+#define ASM_X86_CMPXCHG_H
+
+#include <linux/compiler.h>
+#include <asm/alternative.h> /* Provides LOCK_PREFIX */
+
+/*
+ * Non-existant functions to indicate usage errors at link time
+ * (or compile-time if the compiler implements __compiletime_error().
+ */
+extern void __xchg_wrong_size(void)
+	__compiletime_error("Bad argument size for xchg");
+extern void __cmpxchg_wrong_size(void)
+	__compiletime_error("Bad argument size for cmpxchg");
+extern void __xadd_wrong_size(void)
+	__compiletime_error("Bad argument size for xadd");
+
+/*
+ * Constants for operation sizes. On 32-bit, the 64-bit size it set to
+ * -1 because sizeof will never return -1, thereby making those switch
+ * case statements guaranteeed dead code which the compiler will
+ * eliminate, and allowing the "missing symbol in the default case" to
+ * indicate a usage error.
+ */
+#define __X86_CASE_B	1
+#define __X86_CASE_W	2
+#define __X86_CASE_L	4
+#ifdef CONFIG_64BIT
+#define __X86_CASE_Q	8
+#else
+#define	__X86_CASE_Q	-1		/* sizeof will never return -1 */
+#endif
+
+/*
+ * Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
+ * Since this is generally used to protect other memory information, we
+ * use "asm volatile" and "memory" clobbers to prevent gcc from moving
+ * information around.
+ */
+#define __xchg(x, ptr, size)						\
+({									\
+	__typeof(*(ptr)) __x = (x);					\
+	switch (size) {							\
+	case __X86_CASE_B:						\
+	{								\
+		volatile u8 *__ptr = (volatile u8 *)(ptr);		\
+		asm volatile("xchgb %0,%1"				\
+			     : "=q" (__x), "+m" (*__ptr)		\
+			     : "0" (__x)				\
+			     : "memory");				\
+		break;							\
+	}								\
+	case __X86_CASE_W:						\
+	{								\
+		volatile u16 *__ptr = (volatile u16 *)(ptr);		\
+		asm volatile("xchgw %0,%1"				\
+			     : "=r" (__x), "+m" (*__ptr)		\
+			     : "0" (__x)				\
+			     : "memory");				\
+		break;							\
+	}								\
+	case __X86_CASE_L:						\
+	{								\
+		volatile u32 *__ptr = (volatile u32 *)(ptr);		\
+		asm volatile("xchgl %0,%1"				\
+			     : "=r" (__x), "+m" (*__ptr)		\
+			     : "0" (__x)				\
+			     : "memory");				\
+		break;							\
+	}								\
+	case __X86_CASE_Q:						\
+	{								\
+		volatile u64 *__ptr = (volatile u64 *)(ptr);		\
+		asm volatile("xchgq %0,%1"				\
+			     : "=r" (__x), "+m" (*__ptr)		\
+			     : "0" (__x)				\
+			     : "memory");				\
+		break;							\
+	}								\
+	default:							\
+		__xchg_wrong_size();					\
+	}								\
+	__x;								\
+})
+
+#define xchg(ptr, v)							\
+	__xchg((v), (ptr), sizeof(*ptr))
+
+/*
+ * 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 __raw_cmpxchg(ptr, old, new, size, lock)			\
+({									\
+	__typeof__(*(ptr)) __ret;					\
+	__typeof__(*(ptr)) __old = (old);				\
+	__typeof__(*(ptr)) __new = (new);				\
+	switch (size) {							\
+	case __X86_CASE_B:						\
+	{								\
+		volatile u8 *__ptr = (volatile u8 *)(ptr);		\
+		asm volatile(lock "cmpxchgb %2,%1"			\
+			     : "=a" (__ret), "+m" (*__ptr)		\
+			     : "q" (__new), "0" (__old)			\
+			     : "memory");				\
+		break;							\
+	}								\
+	case __X86_CASE_W:						\
+	{								\
+		volatile u16 *__ptr = (volatile u16 *)(ptr);		\
+		asm volatile(lock "cmpxchgw %2,%1"			\
+			     : "=a" (__ret), "+m" (*__ptr)		\
+			     : "r" (__new), "0" (__old)			\
+			     : "memory");				\
+		break;							\
+	}								\
+	case __X86_CASE_L:						\
+	{								\
+		volatile u32 *__ptr = (volatile u32 *)(ptr);		\
+		asm volatile(lock "cmpxchgl %2,%1"			\
+			     : "=a" (__ret), "+m" (*__ptr)		\
+			     : "r" (__new), "0" (__old)			\
+			     : "memory");				\
+		break;							\
+	}								\
+	case __X86_CASE_Q:						\
+	{								\
+		volatile u64 *__ptr = (volatile u64 *)(ptr);		\
+		asm volatile(lock "cmpxchgq %2,%1"			\
+			     : "=a" (__ret), "+m" (*__ptr)		\
+			     : "r" (__new), "0" (__old)			\
+			     : "memory");				\
+		break;							\
+	}								\
+	default:							\
+		__cmpxchg_wrong_size();					\
+	}								\
+	__ret;								\
+})
+
+#define __cmpxchg(ptr, old, new, size)					\
+	__raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
+
+#define __sync_cmpxchg(ptr, old, new, size)				\
+	__raw_cmpxchg((ptr), (old), (new), (size), "lock; ")
+
+#define __cmpxchg_local(ptr, old, new, size)				\
+	__raw_cmpxchg((ptr), (old), (new), (size), "")
+
 #ifdef CONFIG_X86_32
 # include "cmpxchg_32.h"
 #else
 # include "cmpxchg_64.h"
 #endif
+
+#ifdef __HAVE_ARCH_CMPXCHG
+#define cmpxchg(ptr, old, new)						\
+	__cmpxchg((ptr), (old), (new), sizeof(*ptr))
+
+#define sync_cmpxchg(ptr, old, new)					\
+	__sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
+
+#define cmpxchg_local(ptr, old, new)					\
+	__cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
+#endif
+
+#define __xadd(ptr, inc, lock)						\
+	({								\
+	        __typeof__ (*(ptr)) __ret = (inc);			\
+		switch (sizeof(*(ptr))) {				\
+		case __X86_CASE_B:					\
+			asm volatile (lock "xaddb %b0, %1\n"		\
+				      : "+r" (__ret), "+m" (*(ptr))	\
+				      : : "memory", "cc");		\
+			break;						\
+		case __X86_CASE_W:					\
+			asm volatile (lock "xaddw %w0, %1\n"		\
+				      : "+r" (__ret), "+m" (*(ptr))	\
+				      : : "memory", "cc");		\
+			break;						\
+		case __X86_CASE_L:					\
+			asm volatile (lock "xaddl %0, %1\n"		\
+				      : "+r" (__ret), "+m" (*(ptr))	\
+				      : : "memory", "cc");		\
+			break;						\
+		case __X86_CASE_Q:					\
+			asm volatile (lock "xaddq %q0, %1\n"		\
+				      : "+r" (__ret), "+m" (*(ptr))	\
+				      : : "memory", "cc");		\
+			break;						\
+		default:						\
+			__xadd_wrong_size();				\
+		}							\
+		__ret;							\
+	})
+
+/*
+ * xadd() adds "inc" to "*ptr" and atomically returns the previous
+ * value of "*ptr".
+ *
+ * xadd() is locked when multiple CPUs are online
+ * xadd_sync() is always locked
+ * xadd_local() is never locked
+ */
+#define xadd(ptr, inc)		__xadd((ptr), (inc), LOCK_PREFIX)
+#define xadd_sync(ptr, inc)	__xadd((ptr), (inc), "lock; ")
+#define xadd_local(ptr, inc)	__xadd((ptr), (inc), "")
+
+#endif	/* ASM_X86_CMPXCHG_H */
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/compat.h linux-libre-3.2-gnu/arch/x86/include/asm/compat.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/compat.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/compat.h	2012-01-04 18:55:44.000000000 -0500
@@ -108,7 +108,8 @@
 	compat_fsid_t	f_fsid;
 	int		f_namelen;	/* SunOS ignores this field. */
 	int		f_frsize;
-	int		f_spare[5];
+	int		f_flags;
+	int		f_spare[4];
 };
 
 #define COMPAT_RLIM_OLD_INFINITY	0x7fffffff
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/cpufeature.h linux-libre-3.2-gnu/arch/x86/include/asm/cpufeature.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/cpufeature.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/cpufeature.h	2012-01-04 18:55:44.000000000 -0500
@@ -114,12 +114,14 @@
 #define X86_FEATURE_CX16	(4*32+13) /* CMPXCHG16B */
 #define X86_FEATURE_XTPR	(4*32+14) /* Send Task Priority Messages */
 #define X86_FEATURE_PDCM	(4*32+15) /* Performance Capabilities */
+#define X86_FEATURE_PCID	(4*32+17) /* Process Context Identifiers */
 #define X86_FEATURE_DCA		(4*32+18) /* Direct Cache Access */
 #define X86_FEATURE_XMM4_1	(4*32+19) /* "sse4_1" SSE-4.1 */
 #define X86_FEATURE_XMM4_2	(4*32+20) /* "sse4_2" SSE-4.2 */
 #define X86_FEATURE_X2APIC	(4*32+21) /* x2APIC */
 #define X86_FEATURE_MOVBE	(4*32+22) /* MOVBE instruction */
 #define X86_FEATURE_POPCNT      (4*32+23) /* POPCNT instruction */
+#define X86_FEATURE_TSC_DEADLINE_TIMER	(4*32+24) /* Tsc deadline timer */
 #define X86_FEATURE_AES		(4*32+25) /* AES instructions */
 #define X86_FEATURE_XSAVE	(4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
 #define X86_FEATURE_OSXSAVE	(4*32+27) /* "" XSAVE enabled in the OS */
@@ -257,7 +259,9 @@
 #define cpu_has_xmm		boot_cpu_has(X86_FEATURE_XMM)
 #define cpu_has_xmm2		boot_cpu_has(X86_FEATURE_XMM2)
 #define cpu_has_xmm3		boot_cpu_has(X86_FEATURE_XMM3)
+#define cpu_has_ssse3		boot_cpu_has(X86_FEATURE_SSSE3)
 #define cpu_has_aes		boot_cpu_has(X86_FEATURE_AES)
+#define cpu_has_avx		boot_cpu_has(X86_FEATURE_AVX)
 #define cpu_has_ht		boot_cpu_has(X86_FEATURE_HT)
 #define cpu_has_mp		boot_cpu_has(X86_FEATURE_MP)
 #define cpu_has_nx		boot_cpu_has(X86_FEATURE_NX)
@@ -285,6 +289,7 @@
 #define cpu_has_xmm4_2		boot_cpu_has(X86_FEATURE_XMM4_2)
 #define cpu_has_x2apic		boot_cpu_has(X86_FEATURE_X2APIC)
 #define cpu_has_xsave		boot_cpu_has(X86_FEATURE_XSAVE)
+#define cpu_has_osxsave		boot_cpu_has(X86_FEATURE_OSXSAVE)
 #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)
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/device.h linux-libre-3.2-gnu/arch/x86/include/asm/device.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/device.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/device.h	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
 #ifdef CONFIG_X86_64
 struct dma_map_ops *dma_ops;
 #endif
-#if defined(CONFIG_DMAR) || defined(CONFIG_AMD_IOMMU)
+#if defined(CONFIG_INTEL_IOMMU) || defined(CONFIG_AMD_IOMMU)
 	void *iommu; /* hook for IOMMU specific extension */
 #endif
 };
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/dma-mapping.h linux-libre-3.2-gnu/arch/x86/include/asm/dma-mapping.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/dma-mapping.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/dma-mapping.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
 #define _ASM_X86_DMA_MAPPING_H
 
 /*
- * IOMMU interface. See Documentation/PCI/PCI-DMA-mapping.txt and
+ * IOMMU interface. See Documentation/DMA-API-HOWTO.txt and
  * Documentation/DMA-API.txt for documentation.
  */
 
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/dwarf2.h linux-libre-3.2-gnu/arch/x86/include/asm/dwarf2.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/dwarf2.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/dwarf2.h	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #define CFI_REMEMBER_STATE	.cfi_remember_state
 #define CFI_RESTORE_STATE	.cfi_restore_state
 #define CFI_UNDEFINED		.cfi_undefined
+#define CFI_ESCAPE		.cfi_escape
 
 #ifdef CONFIG_AS_CFI_SIGNAL_FRAME
 #define CFI_SIGNAL_FRAME	.cfi_signal_frame
@@ -68,6 +69,7 @@
 #define CFI_REMEMBER_STATE	cfi_ignore
 #define CFI_RESTORE_STATE	cfi_ignore
 #define CFI_UNDEFINED		cfi_ignore
+#define CFI_ESCAPE		cfi_ignore
 #define CFI_SIGNAL_FRAME	cfi_ignore
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/elf.h linux-libre-3.2-gnu/arch/x86/include/asm/elf.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/elf.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/elf.h	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@
 /*
  * ELF register definitions..
  */
+#include <linux/thread_info.h>
 
 #include <asm/ptrace.h>
 #include <asm/user.h>
@@ -320,4 +321,34 @@
 extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 #define arch_randomize_brk arch_randomize_brk
 
+/*
+ * True on X86_32 or when emulating IA32 on X86_64
+ */
+static inline int mmap_is_ia32(void)
+{
+#ifdef CONFIG_X86_32
+	return 1;
+#endif
+#ifdef CONFIG_IA32_EMULATION
+	if (test_thread_flag(TIF_IA32))
+		return 1;
+#endif
+	return 0;
+}
+
+/* The first two values are special, do not change. See align_addr() */
+enum align_flags {
+	ALIGN_VA_32	= BIT(0),
+	ALIGN_VA_64	= BIT(1),
+	ALIGN_VDSO	= BIT(2),
+	ALIGN_TOPDOWN	= BIT(3),
+};
+
+struct va_alignment {
+	int flags;
+	unsigned long mask;
+} ____cacheline_aligned;
+
+extern struct va_alignment va_align;
+extern unsigned long align_addr(unsigned long, struct file *, enum align_flags);
 #endif /* _ASM_X86_ELF_H */
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/hw_irq.h linux-libre-3.2-gnu/arch/x86/include/asm/hw_irq.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/hw_irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/hw_irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -119,7 +119,7 @@
 	cpumask_var_t		old_domain;
 	u8			vector;
 	u8			move_in_progress : 1;
-#ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_IRQ_REMAP
 	struct irq_2_iommu	irq_2_iommu;
 #endif
 };
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/hyperv.h linux-libre-3.2-gnu/arch/x86/include/asm/hyperv.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/hyperv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/hyperv.h	2012-01-04 18:55:44.000000000 -0500
@@ -189,5 +189,6 @@
 #define HV_STATUS_INVALID_HYPERCALL_CODE	2
 #define HV_STATUS_INVALID_HYPERCALL_INPUT	3
 #define HV_STATUS_INVALID_ALIGNMENT		4
+#define HV_STATUS_INSUFFICIENT_BUFFERS		19
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/intel_scu_ipc.h linux-libre-3.2-gnu/arch/x86/include/asm/intel_scu_ipc.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/intel_scu_ipc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/intel_scu_ipc.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,11 +1,17 @@
 #ifndef _ASM_X86_INTEL_SCU_IPC_H_
 #define  _ASM_X86_INTEL_SCU_IPC_H_
 
-#define IPCMSG_VRTC	0xFA	 /* Set vRTC device */
+#include <linux/notifier.h>
 
-/* Command id associated with message IPCMSG_VRTC */
-#define IPC_CMD_VRTC_SETTIME      1 /* Set time */
-#define IPC_CMD_VRTC_SETALARM     2 /* Set alarm */
+#define IPCMSG_WARM_RESET	0xF0
+#define IPCMSG_COLD_RESET	0xF1
+#define IPCMSG_SOFT_RESET	0xF2
+#define IPCMSG_COLD_BOOT	0xF3
+
+#define IPCMSG_VRTC		0xFA	 /* Set vRTC device */
+	/* Command id associated with message IPCMSG_VRTC */
+	#define IPC_CMD_VRTC_SETTIME      1 /* Set time */
+	#define IPC_CMD_VRTC_SETALARM     2 /* Set alarm */
 
 /* Read single register */
 int intel_scu_ipc_ioread8(u16 addr, u8 *data);
@@ -44,4 +50,24 @@
 /* Update FW version */
 int intel_scu_ipc_fw_update(u8 *buffer, u32 length);
 
+extern struct blocking_notifier_head intel_scu_notifier;
+
+static inline void intel_scu_notifier_add(struct notifier_block *nb)
+{
+	blocking_notifier_chain_register(&intel_scu_notifier, nb);
+}
+
+static inline void intel_scu_notifier_remove(struct notifier_block *nb)
+{
+	blocking_notifier_chain_unregister(&intel_scu_notifier, nb);
+}
+
+static inline int intel_scu_notifier_post(unsigned long v, void *p)
+{
+	return blocking_notifier_call_chain(&intel_scu_notifier, v, p);
+}
+
+#define		SCU_AVAILABLE		1
+#define		SCU_DOWN		2
+
 #endif
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/irq_remapping.h linux-libre-3.2-gnu/arch/x86/include/asm/irq_remapping.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/irq_remapping.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/irq_remapping.h	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,8 @@
 
 #define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8)
 
-#ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_IRQ_REMAP
+static void irq_remap_modify_chip_defaults(struct irq_chip *chip);
 static inline void prepare_irte(struct irte *irte, int vector,
 			        unsigned int dest)
 {
@@ -36,6 +37,9 @@
 {
 	return false;
 }
+static inline void irq_remap_modify_chip_defaults(struct irq_chip *chip)
+{
+}
 #endif
 
 #endif	/* _ASM_X86_IRQ_REMAPPING_H */
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/irq_vectors.h linux-libre-3.2-gnu/arch/x86/include/asm/irq_vectors.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/irq_vectors.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/irq_vectors.h	2012-01-04 18:55:44.000000000 -0500
@@ -160,19 +160,11 @@
 #define IO_APIC_VECTOR_LIMIT		( 32 * MAX_IO_APICS )
 
 #ifdef CONFIG_X86_IO_APIC
-# ifdef CONFIG_SPARSE_IRQ
-#  define CPU_VECTOR_LIMIT		(64 * NR_CPUS)
-#  define NR_IRQS					\
+# define CPU_VECTOR_LIMIT		(64 * NR_CPUS)
+# define NR_IRQS					\
 	(CPU_VECTOR_LIMIT > IO_APIC_VECTOR_LIMIT ?	\
 		(NR_VECTORS + CPU_VECTOR_LIMIT)  :	\
 		(NR_VECTORS + IO_APIC_VECTOR_LIMIT))
-# else
-#  define CPU_VECTOR_LIMIT		(32 * NR_CPUS)
-#  define NR_IRQS					\
-	(CPU_VECTOR_LIMIT < IO_APIC_VECTOR_LIMIT ?	\
-		(NR_VECTORS + CPU_VECTOR_LIMIT)  :	\
-		(NR_VECTORS + IO_APIC_VECTOR_LIMIT))
-# endif
 #else /* !CONFIG_X86_IO_APIC: */
 # define NR_IRQS			NR_IRQS_LEGACY
 #endif
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/kvm_emulate.h linux-libre-3.2-gnu/arch/x86/include/asm/kvm_emulate.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/kvm_emulate.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/kvm_emulate.h	2012-01-04 18:55:44.000000000 -0500
@@ -262,7 +262,7 @@
 	struct operand dst;
 	bool has_seg_override;
 	u8 seg_override;
-	unsigned int d;
+	u64 d;
 	int (*execute)(struct x86_emulate_ctxt *ctxt);
 	int (*check_perm)(struct x86_emulate_ctxt *ctxt);
 	/* modrm */
@@ -275,6 +275,8 @@
 	unsigned long _eip;
 	/* Fields above regs are cleared together. */
 	unsigned long regs[NR_VCPU_REGS];
+	struct operand memop;
+	struct operand *memopp;
 	struct fetch_cache fetch;
 	struct read_cache io_read;
 	struct read_cache mem_read;
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/kvm_host.h linux-libre-3.2-gnu/arch/x86/include/asm/kvm_host.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/kvm_host.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/kvm_host.h	2012-01-04 18:55:44.000000000 -0500
@@ -26,7 +26,8 @@
 #include <asm/mtrr.h>
 #include <asm/msr-index.h>
 
-#define KVM_MAX_VCPUS 64
+#define KVM_MAX_VCPUS 254
+#define KVM_SOFT_MAX_VCPUS 64
 #define KVM_MEMORY_SLOTS 32
 /* memory slots that does not exposed to userspace */
 #define KVM_PRIVATE_MEM_SLOTS 4
@@ -264,6 +265,7 @@
 	void (*new_cr3)(struct kvm_vcpu *vcpu);
 	void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long root);
 	unsigned long (*get_cr3)(struct kvm_vcpu *vcpu);
+	u64 (*get_pdptr)(struct kvm_vcpu *vcpu, int index);
 	int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err,
 			  bool prefault);
 	void (*inject_page_fault)(struct kvm_vcpu *vcpu,
@@ -411,8 +413,9 @@
 	u32  tsc_catchup_mult;
 	s8   tsc_catchup_shift;
 
-	bool nmi_pending;
-	bool nmi_injected;
+	atomic_t nmi_queued;  /* unprocessed asynchronous NMIs */
+	unsigned nmi_pending; /* NMI queued after currently running handler */
+	bool nmi_injected;    /* Trying to inject an NMI this entry */
 
 	struct mtrr_state_type mtrr_state;
 	u32 pat;
@@ -628,14 +631,13 @@
 	void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
 
 	u64 (*compute_tsc_offset)(struct kvm_vcpu *vcpu, u64 target_tsc);
+	u64 (*read_l1_tsc)(struct kvm_vcpu *vcpu);
 
 	void (*get_exit_info)(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2);
 
 	int (*check_intercept)(struct kvm_vcpu *vcpu,
 			       struct x86_instruction_info *info,
 			       enum x86_intercept_stage stage);
-
-	const struct trace_print_flags *exit_reasons_str;
 };
 
 struct kvm_arch_async_pf {
@@ -672,6 +674,8 @@
 
 extern bool tdp_enabled;
 
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu);
+
 /* control of guest tsc rate supported? */
 extern bool kvm_has_tsc_control;
 /* minimum supported tsc_khz for guests */
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/mach_traps.h linux-libre-3.2-gnu/arch/x86/include/asm/mach_traps.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/mach_traps.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/mach_traps.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
 #define NMI_REASON_CLEAR_IOCHK	0x08
 #define NMI_REASON_CLEAR_MASK	0x0f
 
-static inline unsigned char get_nmi_reason(void)
+static inline unsigned char default_get_nmi_reason(void)
 {
 	return inb(NMI_REASON_PORT);
 }
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/mce.h linux-libre-3.2-gnu/arch/x86/include/asm/mce.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/mce.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/mce.h	2012-01-04 18:55:44.000000000 -0500
@@ -201,7 +201,10 @@
 void mce_notify_process(void);
 
 DECLARE_PER_CPU(struct mce, injectm);
-extern struct file_operations mce_chrdev_ops;
+
+extern void register_mce_write_callback(ssize_t (*)(struct file *filp,
+				    const char __user *ubuf,
+				    size_t usize, loff_t *off));
 
 /*
  * Exception handler
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/mrst.h linux-libre-3.2-gnu/arch/x86/include/asm/mrst.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/mrst.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/mrst.h	2012-01-04 18:55:44.000000000 -0500
@@ -31,11 +31,20 @@
 };
 
 extern enum mrst_cpu_type __mrst_cpu_chip;
+
+#ifdef CONFIG_X86_INTEL_MID
+
 static inline enum mrst_cpu_type mrst_identify_cpu(void)
 {
 	return __mrst_cpu_chip;
 }
 
+#else /* !CONFIG_X86_INTEL_MID */
+
+#define mrst_identify_cpu()    (0)
+
+#endif /* !CONFIG_X86_INTEL_MID */
+
 enum mrst_timer_options {
 	MRST_TIMER_DEFAULT,
 	MRST_TIMER_APBT_ONLY,
@@ -44,6 +53,13 @@
 
 extern enum mrst_timer_options mrst_timer_options;
 
+/*
+ * Penwell uses spread spectrum clock, so the freq number is not exactly
+ * the same as reported by MSR based on SDM.
+ */
+#define PENWELL_FSB_FREQ_83SKU         83200
+#define PENWELL_FSB_FREQ_100SKU        99840
+
 #define SFI_MTMR_MAX_NUM 8
 #define SFI_MRTC_MAX	8
 
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/msr.h linux-libre-3.2-gnu/arch/x86/include/asm/msr.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/msr.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/msr.h	2012-01-04 18:55:44.000000000 -0500
@@ -169,7 +169,14 @@
 	return native_write_msr_safe(msr, low, high);
 }
 
-/* rdmsr with exception handling */
+/*
+ * rdmsr with exception handling.
+ *
+ * Please note that the exception handling works only after we've
+ * switched to the "smart" #GP handler in trap_init() which knows about
+ * exception tables - using this macro earlier than that causes machine
+ * hangs on boxes which do not implement the @msr in the first argument.
+ */
 #define rdmsr_safe(msr, p1, p2)					\
 ({								\
 	int __err;						\
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/msr-index.h linux-libre-3.2-gnu/arch/x86/include/asm/msr-index.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/msr-index.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/msr-index.h	2012-01-04 18:55:44.000000000 -0500
@@ -229,6 +229,8 @@
 #define MSR_IA32_APICBASE_ENABLE	(1<<11)
 #define MSR_IA32_APICBASE_BASE		(0xfffff<<12)
 
+#define MSR_IA32_TSCDEADLINE		0x000006e0
+
 #define MSR_IA32_UCODE_WRITE		0x00000079
 #define MSR_IA32_UCODE_REV		0x0000008b
 
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/nmi.h linux-libre-3.2-gnu/arch/x86/include/asm/nmi.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/nmi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/nmi.h	2012-01-04 18:55:44.000000000 -0500
@@ -22,27 +22,26 @@
 #define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace
 #endif
 
-/*
- * Define some priorities for the nmi notifier call chain.
- *
- * Create a local nmi bit that has a higher priority than
- * 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 separate
- * the priorities.  This can go a lot higher if needed be.
- */
+#define NMI_FLAG_FIRST	1
 
-#define NMI_LOCAL_SHIFT		16	/* randomly picked */
-#define NMI_LOCAL_BIT		(1ULL << NMI_LOCAL_SHIFT)
-#define NMI_HIGH_PRIOR		(1ULL << 8)
-#define NMI_NORMAL_PRIOR	(1ULL << 4)
-#define NMI_LOW_PRIOR		(1ULL << 0)
-#define NMI_LOCAL_HIGH_PRIOR	(NMI_LOCAL_BIT | NMI_HIGH_PRIOR)
-#define NMI_LOCAL_NORMAL_PRIOR	(NMI_LOCAL_BIT | NMI_NORMAL_PRIOR)
-#define NMI_LOCAL_LOW_PRIOR	(NMI_LOCAL_BIT | NMI_LOW_PRIOR)
+enum {
+	NMI_LOCAL=0,
+	NMI_UNKNOWN,
+	NMI_MAX
+};
+
+#define NMI_DONE	0
+#define NMI_HANDLED	1
+
+typedef int (*nmi_handler_t)(unsigned int, struct pt_regs *);
+
+int register_nmi_handler(unsigned int, nmi_handler_t, unsigned long,
+			 const char *);
+
+void unregister_nmi_handler(unsigned int, const char *);
 
 void stop_nmi(void);
 void restart_nmi(void);
+void local_touch_nmi(void);
 
 #endif /* _ASM_X86_NMI_H */
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/pci_x86.h linux-libre-3.2-gnu/arch/x86/include/asm/pci_x86.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/pci_x86.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/pci_x86.h	2012-01-04 18:55:44.000000000 -0500
@@ -99,10 +99,10 @@
 						int reg, int len, u32 val);
 };
 
-extern struct pci_raw_ops *raw_pci_ops;
-extern struct pci_raw_ops *raw_pci_ext_ops;
+extern const struct pci_raw_ops *raw_pci_ops;
+extern const struct pci_raw_ops *raw_pci_ext_ops;
 
-extern struct pci_raw_ops pci_direct_conf1;
+extern const struct pci_raw_ops pci_direct_conf1;
 extern bool port_cf9_safe;
 
 /* arch_initcall level */
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/perf_event.h linux-libre-3.2-gnu/arch/x86/include/asm/perf_event.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/perf_event.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/perf_event.h	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,9 @@
 #define ARCH_PERFMON_EVENTSEL_INV			(1ULL << 23)
 #define ARCH_PERFMON_EVENTSEL_CMASK			0xFF000000ULL
 
+#define AMD_PERFMON_EVENTSEL_GUESTONLY			(1ULL << 40)
+#define AMD_PERFMON_EVENTSEL_HOSTONLY			(1ULL << 41)
+
 #define AMD64_EVENTSEL_EVENT	\
 	(ARCH_PERFMON_EVENTSEL_EVENT | (0x0FULL << 32))
 #define INTEL_ARCH_EVENT_MASK	\
@@ -43,14 +46,17 @@
 #define AMD64_RAW_EVENT_MASK		\
 	(X86_RAW_EVENT_MASK          |  \
 	 AMD64_EVENTSEL_EVENT)
+#define AMD64_NUM_COUNTERS				4
+#define AMD64_NUM_COUNTERS_F15H				6
+#define AMD64_NUM_COUNTERS_MAX				AMD64_NUM_COUNTERS_F15H
 
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL		      0x3c
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL		0x3c
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK		(0x00 << 8)
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX			 0
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX		0
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \
 		(1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX))
 
-#define ARCH_PERFMON_BRANCH_MISSES_RETIRED			 6
+#define ARCH_PERFMON_BRANCH_MISSES_RETIRED		6
 
 /*
  * Intel "Architectural Performance Monitoring" CPUID
@@ -110,6 +116,35 @@
  */
 #define X86_PMC_IDX_FIXED_BTS				(X86_PMC_IDX_FIXED + 16)
 
+/*
+ * IBS cpuid feature detection
+ */
+
+#define IBS_CPUID_FEATURES		0x8000001b
+
+/*
+ * Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but
+ * bit 0 is used to indicate the existence of IBS.
+ */
+#define IBS_CAPS_AVAIL			(1U<<0)
+#define IBS_CAPS_FETCHSAM		(1U<<1)
+#define IBS_CAPS_OPSAM			(1U<<2)
+#define IBS_CAPS_RDWROPCNT		(1U<<3)
+#define IBS_CAPS_OPCNT			(1U<<4)
+#define IBS_CAPS_BRNTRGT		(1U<<5)
+#define IBS_CAPS_OPCNTEXT		(1U<<6)
+
+#define IBS_CAPS_DEFAULT		(IBS_CAPS_AVAIL		\
+					 | IBS_CAPS_FETCHSAM	\
+					 | IBS_CAPS_OPSAM)
+
+/*
+ * IBS APIC setup
+ */
+#define IBSCTL				0x1cc
+#define IBSCTL_LVT_OFFSET_VALID		(1ULL<<8)
+#define IBSCTL_LVT_OFFSET_MASK		0x0F
+
 /* IbsFetchCtl bits/masks */
 #define IBS_FETCH_RAND_EN	(1ULL<<57)
 #define IBS_FETCH_VAL		(1ULL<<49)
@@ -124,6 +159,8 @@
 #define IBS_OP_MAX_CNT		0x0000FFFFULL
 #define IBS_OP_MAX_CNT_EXT	0x007FFFFFULL	/* not a register bit mask */
 
+extern u32 get_ibs_caps(void);
+
 #ifdef CONFIG_PERF_EVENTS
 extern void perf_events_lapic_init(void);
 
@@ -159,7 +196,19 @@
 	);							\
 }
 
+struct perf_guest_switch_msr {
+	unsigned msr;
+	u64 host, guest;
+};
+
+extern struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr);
 #else
+static inline perf_guest_switch_msr *perf_guest_get_msrs(int *nr)
+{
+	*nr = 0;
+	return NULL;
+}
+
 static inline void perf_events_lapic_init(void)	{ }
 #endif
 
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/processor.h linux-libre-3.2-gnu/arch/x86/include/asm/processor.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/processor.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/processor.h	2012-01-04 18:55:44.000000000 -0500
@@ -111,6 +111,7 @@
 	/* Index into per_cpu list: */
 	u16			cpu_index;
 #endif
+	u32			microcode;
 } __attribute__((__aligned__(SMP_CACHE_BYTES)));
 
 #define X86_VENDOR_INTEL	0
@@ -179,7 +180,8 @@
 	      "=b" (*ebx),
 	      "=c" (*ecx),
 	      "=d" (*edx)
-	    : "0" (*eax), "2" (*ecx));
+	    : "0" (*eax), "2" (*ecx)
+	    : "memory");
 }
 
 static inline void load_cr3(pgd_t *pgdir)
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/reboot.h linux-libre-3.2-gnu/arch/x86/include/asm/reboot.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/reboot.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/reboot.h	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,7 @@
 #define MRR_BIOS	0
 #define MRR_APM		1
 
-typedef void (*nmi_shootdown_cb)(int, struct die_args*);
+typedef void (*nmi_shootdown_cb)(int, struct pt_regs*);
 void nmi_shootdown_cpus(nmi_shootdown_cb callback);
 
 #endif /* _ASM_X86_REBOOT_H */
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/rwsem.h linux-libre-3.2-gnu/arch/x86/include/asm/rwsem.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/rwsem.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/rwsem.h	2012-01-04 18:55:44.000000000 -0500
@@ -204,13 +204,7 @@
  */
 static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
 {
-	long tmp = delta;
-
-	asm volatile(LOCK_PREFIX "xadd %0,%1"
-		     : "+r" (tmp), "+m" (sem->count)
-		     : : "memory");
-
-	return tmp + delta;
+	return delta + xadd(&sem->count, delta);
 }
 
 #endif /* __KERNEL__ */
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/spinlock.h linux-libre-3.2-gnu/arch/x86/include/asm/spinlock.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/spinlock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/spinlock.h	2012-01-04 18:55:44.000000000 -0500
@@ -49,109 +49,49 @@
  * issues and should be optimal for the uncontended case. Note the tail must be
  * in the high part, because a wide xadd increment of the low part would carry
  * up and contaminate the high part.
- *
- * With fewer than 2^8 possible CPUs, we can use x86's partial registers to
- * save some instructions and make the code more elegant. There really isn't
- * much between them in performance though, especially as locks are out of line.
  */
-#if (NR_CPUS < 256)
-#define TICKET_SHIFT 8
-
 static __always_inline void __ticket_spin_lock(arch_spinlock_t *lock)
 {
-	short inc = 0x0100;
+	register struct __raw_tickets inc = { .tail = 1 };
 
-	asm volatile (
-		LOCK_PREFIX "xaddw %w0, %1\n"
-		"1:\t"
-		"cmpb %h0, %b0\n\t"
-		"je 2f\n\t"
-		"rep ; nop\n\t"
-		"movb %1, %b0\n\t"
-		/* don't need lfence here, because loads are in-order */
-		"jmp 1b\n"
-		"2:"
-		: "+Q" (inc), "+m" (lock->slock)
-		:
-		: "memory", "cc");
+	inc = xadd(&lock->tickets, inc);
+
+	for (;;) {
+		if (inc.head == inc.tail)
+			break;
+		cpu_relax();
+		inc.head = ACCESS_ONCE(lock->tickets.head);
+	}
+	barrier();		/* make sure nothing creeps before the lock is taken */
 }
 
 static __always_inline int __ticket_spin_trylock(arch_spinlock_t *lock)
 {
-	int tmp, new;
+	arch_spinlock_t old, new;
 
-	asm volatile("movzwl %2, %0\n\t"
-		     "cmpb %h0,%b0\n\t"
-		     "leal 0x100(%" REG_PTR_MODE "0), %1\n\t"
-		     "jne 1f\n\t"
-		     LOCK_PREFIX "cmpxchgw %w1,%2\n\t"
-		     "1:"
-		     "sete %b1\n\t"
-		     "movzbl %b1,%0\n\t"
-		     : "=&a" (tmp), "=&q" (new), "+m" (lock->slock)
-		     :
-		     : "memory", "cc");
+	old.tickets = ACCESS_ONCE(lock->tickets);
+	if (old.tickets.head != old.tickets.tail)
+		return 0;
 
-	return tmp;
+	new.head_tail = old.head_tail + (1 << TICKET_SHIFT);
+
+	/* cmpxchg is a full barrier, so nothing can move before it */
+	return cmpxchg(&lock->head_tail, old.head_tail, new.head_tail) == old.head_tail;
 }
 
+#if (NR_CPUS < 256)
 static __always_inline void __ticket_spin_unlock(arch_spinlock_t *lock)
 {
 	asm volatile(UNLOCK_LOCK_PREFIX "incb %0"
-		     : "+m" (lock->slock)
+		     : "+m" (lock->head_tail)
 		     :
 		     : "memory", "cc");
 }
 #else
-#define TICKET_SHIFT 16
-
-static __always_inline void __ticket_spin_lock(arch_spinlock_t *lock)
-{
-	int inc = 0x00010000;
-	int tmp;
-
-	asm volatile(LOCK_PREFIX "xaddl %0, %1\n"
-		     "movzwl %w0, %2\n\t"
-		     "shrl $16, %0\n\t"
-		     "1:\t"
-		     "cmpl %0, %2\n\t"
-		     "je 2f\n\t"
-		     "rep ; nop\n\t"
-		     "movzwl %1, %2\n\t"
-		     /* don't need lfence here, because loads are in-order */
-		     "jmp 1b\n"
-		     "2:"
-		     : "+r" (inc), "+m" (lock->slock), "=&r" (tmp)
-		     :
-		     : "memory", "cc");
-}
-
-static __always_inline int __ticket_spin_trylock(arch_spinlock_t *lock)
-{
-	int tmp;
-	int new;
-
-	asm volatile("movl %2,%0\n\t"
-		     "movl %0,%1\n\t"
-		     "roll $16, %0\n\t"
-		     "cmpl %0,%1\n\t"
-		     "leal 0x00010000(%" REG_PTR_MODE "0), %1\n\t"
-		     "jne 1f\n\t"
-		     LOCK_PREFIX "cmpxchgl %1,%2\n\t"
-		     "1:"
-		     "sete %b1\n\t"
-		     "movzbl %b1,%0\n\t"
-		     : "=&a" (tmp), "=&q" (new), "+m" (lock->slock)
-		     :
-		     : "memory", "cc");
-
-	return tmp;
-}
-
 static __always_inline void __ticket_spin_unlock(arch_spinlock_t *lock)
 {
 	asm volatile(UNLOCK_LOCK_PREFIX "incw %0"
-		     : "+m" (lock->slock)
+		     : "+m" (lock->head_tail)
 		     :
 		     : "memory", "cc");
 }
@@ -159,16 +99,16 @@
 
 static inline int __ticket_spin_is_locked(arch_spinlock_t *lock)
 {
-	int tmp = ACCESS_ONCE(lock->slock);
+	struct __raw_tickets tmp = ACCESS_ONCE(lock->tickets);
 
-	return !!(((tmp >> TICKET_SHIFT) ^ tmp) & ((1 << TICKET_SHIFT) - 1));
+	return !!(tmp.tail ^ tmp.head);
 }
 
 static inline int __ticket_spin_is_contended(arch_spinlock_t *lock)
 {
-	int tmp = ACCESS_ONCE(lock->slock);
+	struct __raw_tickets tmp = ACCESS_ONCE(lock->tickets);
 
-	return (((tmp >> TICKET_SHIFT) - tmp) & ((1 << TICKET_SHIFT) - 1)) > 1;
+	return ((tmp.tail - tmp.head) & TICKET_MASK) > 1;
 }
 
 #ifndef CONFIG_PARAVIRT_SPINLOCKS
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/spinlock_types.h linux-libre-3.2-gnu/arch/x86/include/asm/spinlock_types.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/spinlock_types.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/spinlock_types.h	2012-01-04 18:55:44.000000000 -0500
@@ -5,11 +5,29 @@
 # error "please don't include this file directly"
 #endif
 
+#include <linux/types.h>
+
+#if (CONFIG_NR_CPUS < 256)
+typedef u8  __ticket_t;
+typedef u16 __ticketpair_t;
+#else
+typedef u16 __ticket_t;
+typedef u32 __ticketpair_t;
+#endif
+
+#define TICKET_SHIFT	(sizeof(__ticket_t) * 8)
+#define TICKET_MASK	((__ticket_t)((1 << TICKET_SHIFT) - 1))
+
 typedef struct arch_spinlock {
-	unsigned int slock;
+	union {
+		__ticketpair_t head_tail;
+		struct __raw_tickets {
+			__ticket_t head, tail;
+		} tickets;
+	};
 } arch_spinlock_t;
 
-#define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 }
+#define __ARCH_SPIN_LOCK_UNLOCKED	{ { 0 } }
 
 #include <asm/rwlock.h>
 
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/system.h linux-libre-3.2-gnu/arch/x86/include/asm/system.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/system.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -401,6 +401,7 @@
 extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
 
 void default_idle(void);
+bool set_pm_idle_to_default(void);
 
 void stop_this_cpu(void *dummy);
 
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/timer.h linux-libre-3.2-gnu/arch/x86/include/asm/timer.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/timer.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/timer.h	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,22 @@
  *  (mathieu.desnoyers@polymtl.ca)
  *
  *			-johnstul@us.ibm.com "math is hard, lets go shopping!"
+ *
+ * In:
+ *
+ * ns = cycles * cyc2ns_scale / SC
+ *
+ * Although we may still have enough bits to store the value of ns,
+ * in some cases, we may not have enough bits to store cycles * cyc2ns_scale,
+ * leading to an incorrect result.
+ *
+ * To avoid this, we can decompose 'cycles' into quotient and remainder
+ * of division by SC.  Then,
+ *
+ * ns = (quot * SC + rem) * cyc2ns_scale / SC
+ *    = quot * cyc2ns_scale + (rem * cyc2ns_scale) / SC
+ *
+ *			- sqazi@google.com
  */
 
 DECLARE_PER_CPU(unsigned long, cyc2ns);
@@ -41,9 +57,14 @@
 
 static inline unsigned long long __cycles_2_ns(unsigned long long cyc)
 {
+	unsigned long long quot;
+	unsigned long long rem;
 	int cpu = smp_processor_id();
 	unsigned long long ns = per_cpu(cyc2ns_offset, cpu);
-	ns += cyc * per_cpu(cyc2ns, cpu) >> CYC2NS_SCALE_FACTOR;
+	quot = (cyc >> CYC2NS_SCALE_FACTOR);
+	rem = cyc & ((1ULL << CYC2NS_SCALE_FACTOR) - 1);
+	ns += quot * per_cpu(cyc2ns, cpu) +
+		((rem * per_cpu(cyc2ns, cpu)) >> CYC2NS_SCALE_FACTOR);
 	return ns;
 }
 
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/unistd_32.h linux-libre-3.2-gnu/arch/x86/include/asm/unistd_32.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/unistd_32.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/unistd_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -352,10 +352,12 @@
 #define __NR_syncfs             344
 #define __NR_sendmmsg		345
 #define __NR_setns		346
+#define __NR_process_vm_readv	347
+#define __NR_process_vm_writev	348
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 347
+#define NR_syscalls 349
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/unistd_64.h linux-libre-3.2-gnu/arch/x86/include/asm/unistd_64.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/unistd_64.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/unistd_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -624,7 +624,6 @@
 __SYSCALL(__NR_move_pages, sys_move_pages)
 #define __NR_utimensat				280
 __SYSCALL(__NR_utimensat, sys_utimensat)
-#define __IGNORE_getcpu		/* implemented as a vsyscall */
 #define __NR_epoll_pwait			281
 __SYSCALL(__NR_epoll_pwait, sys_epoll_pwait)
 #define __NR_signalfd				282
@@ -683,6 +682,10 @@
 __SYSCALL(__NR_setns, sys_setns)
 #define __NR_getcpu				309
 __SYSCALL(__NR_getcpu, sys_getcpu)
+#define __NR_process_vm_readv			310
+__SYSCALL(__NR_process_vm_readv, sys_process_vm_readv)
+#define __NR_process_vm_writev			311
+__SYSCALL(__NR_process_vm_writev, sys_process_vm_writev)
 
 #ifndef __NO_STUBS
 #define __ARCH_WANT_OLD_READDIR
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/uv/uv_bau.h linux-libre-3.2-gnu/arch/x86/include/asm/uv/uv_bau.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/uv/uv_bau.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/uv/uv_bau.h	2012-01-04 18:55:44.000000000 -0500
@@ -55,6 +55,7 @@
 #define UV_BAU_TUNABLES_DIR		"sgi_uv"
 #define UV_BAU_TUNABLES_FILE		"bau_tunables"
 #define WHITESPACE			" \t\n"
+#define uv_mmask			((1UL << uv_hub_info->m_val) - 1)
 #define uv_physnodeaddr(x)		((__pa((unsigned long)(x)) & uv_mmask))
 #define cpubit_isset(cpu, bau_local_cpumask) \
 	test_bit((cpu), (bau_local_cpumask).bits)
@@ -656,11 +657,7 @@
  */
 static inline int atom_asr(short i, struct atomic_short *v)
 {
-	short __i = i;
-	asm volatile(LOCK_PREFIX "xaddw %0, %1"
-			: "+r" (i), "+m" (v->counter)
-			: : "memory");
-	return i + __i;
+	return i + xadd(&v->counter, i);
 }
 
 /*
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/uv/uv_hub.h linux-libre-3.2-gnu/arch/x86/include/asm/uv/uv_hub.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/uv/uv_hub.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/uv/uv_hub.h	2012-01-04 18:55:44.000000000 -0500
@@ -46,6 +46,13 @@
  *	PNODE   - the low N bits of the GNODE. The PNODE is the most useful variant
  *		  of the nasid for socket usage.
  *
+ *	GPA	- (global physical address) a socket physical address converted
+ *		  so that it can be used by the GRU as a global address. Socket
+ *		  physical addresses 1) need additional NASID (node) bits added
+ *		  to the high end of the address, and 2) unaliased if the
+ *		  partition does not have a physical address 0. In addition, on
+ *		  UV2 rev 1, GPAs need the gnode left shifted to bits 39 or 40.
+ *
  *
  *  NumaLink Global Physical Address Format:
  *  +--------------------------------+---------------------+
@@ -141,6 +148,8 @@
 	unsigned int		gnode_extra;
 	unsigned char		hub_revision;
 	unsigned char		apic_pnode_shift;
+	unsigned char		m_shift;
+	unsigned char		n_lshift;
 	unsigned long		gnode_upper;
 	unsigned long		lowmem_remap_top;
 	unsigned long		lowmem_remap_base;
@@ -177,6 +186,16 @@
 	return uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE;
 }
 
+static inline int is_uv2_1_hub(void)
+{
+	return uv_hub_info->hub_revision == UV2_HUB_REVISION_BASE;
+}
+
+static inline int is_uv2_2_hub(void)
+{
+	return uv_hub_info->hub_revision == UV2_HUB_REVISION_BASE + 1;
+}
+
 union uvh_apicid {
     unsigned long       v;
     struct uvh_apicid_s {
@@ -276,7 +295,10 @@
 {
 	if (paddr < uv_hub_info->lowmem_remap_top)
 		paddr |= uv_hub_info->lowmem_remap_base;
-	return paddr | uv_hub_info->gnode_upper;
+	paddr |= uv_hub_info->gnode_upper;
+	paddr = ((paddr << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
+		((paddr >> uv_hub_info->m_val) << uv_hub_info->n_lshift);
+	return paddr;
 }
 
 
@@ -300,16 +322,19 @@
 	unsigned long remap_base = uv_hub_info->lowmem_remap_base;
 	unsigned long remap_top =  uv_hub_info->lowmem_remap_top;
 
+	gpa = ((gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
+		((gpa >> uv_hub_info->n_lshift) << uv_hub_info->m_val);
+	gpa = gpa & uv_hub_info->gpa_mask;
 	if (paddr >= remap_base && paddr < remap_base + remap_top)
 		paddr -= remap_base;
 	return paddr;
 }
 
 
-/* gnode -> pnode */
+/* gpa -> pnode */
 static inline unsigned long uv_gpa_to_gnode(unsigned long gpa)
 {
-	return gpa >> uv_hub_info->m_val;
+	return gpa >> uv_hub_info->n_lshift;
 }
 
 /* gpa -> pnode */
@@ -320,6 +345,12 @@
 	return uv_gpa_to_gnode(gpa) & n_mask;
 }
 
+/* gpa -> node offset*/
+static inline unsigned long uv_gpa_to_offset(unsigned long gpa)
+{
+	return (gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift;
+}
+
 /* pnode, offset --> socket virtual */
 static inline void *uv_pnode_offset_to_vaddr(int pnode, unsigned long offset)
 {
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/uv/uv_mmrs.h linux-libre-3.2-gnu/arch/x86/include/asm/uv/uv_mmrs.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/uv/uv_mmrs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/uv/uv_mmrs.h	2012-01-04 18:55:44.000000000 -0500
@@ -57,6 +57,7 @@
 
 #define UV1_HUB_PART_NUMBER	0x88a5
 #define UV2_HUB_PART_NUMBER	0x8eb8
+#define UV2_HUB_PART_NUMBER_X	0x1111
 
 /* Compat: if this #define is present, UV headers support UV2 */
 #define UV2_HUB_IS_SUPPORTED	1
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/vmx.h linux-libre-3.2-gnu/arch/x86/include/asm/vmx.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/vmx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/vmx.h	2012-01-04 18:55:44.000000000 -0500
@@ -350,6 +350,18 @@
 #define DEBUG_REG_ACCESS_REG(eq)        (((eq) >> 8) & 0xf) /* 11:8, general purpose reg. */
 
 
+/*
+ * Exit Qualifications for APIC-Access
+ */
+#define APIC_ACCESS_OFFSET              0xfff   /* 11:0, offset within the APIC page */
+#define APIC_ACCESS_TYPE                0xf000  /* 15:12, access type */
+#define TYPE_LINEAR_APIC_INST_READ      (0 << 12)
+#define TYPE_LINEAR_APIC_INST_WRITE     (1 << 12)
+#define TYPE_LINEAR_APIC_INST_FETCH     (2 << 12)
+#define TYPE_LINEAR_APIC_EVENT          (3 << 12)
+#define TYPE_PHYSICAL_APIC_EVENT        (10 << 12)
+#define TYPE_PHYSICAL_APIC_INST         (15 << 12)
+
 /* segment AR */
 #define SEGMENT_AR_L_MASK (1 << 13)
 
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/x86_init.h linux-libre-3.2-gnu/arch/x86/include/asm/x86_init.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/x86_init.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/x86_init.h	2012-01-04 18:55:44.000000000 -0500
@@ -152,6 +152,7 @@
 /**
  * struct x86_platform_ops - platform specific runtime functions
  * @calibrate_tsc:		calibrate TSC
+ * @wallclock_init:		init the wallclock device
  * @get_wallclock:		get time from HW clock like RTC etc.
  * @set_wallclock:		set time back to HW clock
  * @is_untracked_pat_range	exclude from PAT logic
@@ -160,11 +161,13 @@
  */
 struct x86_platform_ops {
 	unsigned long (*calibrate_tsc)(void);
+	void (*wallclock_init)(void);
 	unsigned long (*get_wallclock)(void);
 	int (*set_wallclock)(unsigned long nowtime);
 	void (*iommu_shutdown)(void);
 	bool (*is_untracked_pat_range)(u64 start, u64 end);
 	void (*nmi_init)(void);
+	unsigned char (*get_nmi_reason)(void);
 	int (*i8042_detect)(void);
 };
 
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/xen/grant_table.h linux-libre-3.2-gnu/arch/x86/include/asm/xen/grant_table.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/xen/grant_table.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/xen/grant_table.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#ifndef _ASM_X86_XEN_GRANT_TABLE_H
-#define _ASM_X86_XEN_GRANT_TABLE_H
-
-#define xen_alloc_vm_area(size)	alloc_vm_area(size)
-#define xen_free_vm_area(area)	free_vm_area(area)
-
-#endif /* _ASM_X86_XEN_GRANT_TABLE_H */
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/xen/hypercall.h linux-libre-3.2-gnu/arch/x86/include/asm/xen/hypercall.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/xen/hypercall.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/xen/hypercall.h	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,7 @@
 #include <xen/interface/xen.h>
 #include <xen/interface/sched.h>
 #include <xen/interface/physdev.h>
+#include <xen/interface/platform.h>
 
 /*
  * The hypercall asms have to meet several constraints:
@@ -301,6 +302,13 @@
 }
 
 static inline int
+HYPERVISOR_dom0_op(struct xen_platform_op *platform_op)
+{
+	platform_op->interface_version = XENPF_INTERFACE_VERSION;
+	return _hypercall1(int, dom0_op, platform_op);
+}
+
+static inline int
 HYPERVISOR_set_debugreg(int reg, unsigned long value)
 {
 	return _hypercall2(int, set_debugreg, reg, value);
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/xen/interface.h linux-libre-3.2-gnu/arch/x86/include/asm/xen/interface.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/xen/interface.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/xen/interface.h	2012-01-04 18:55:44.000000000 -0500
@@ -55,6 +55,7 @@
 DEFINE_GUEST_HANDLE(int);
 DEFINE_GUEST_HANDLE(long);
 DEFINE_GUEST_HANDLE(void);
+DEFINE_GUEST_HANDLE(uint64_t);
 #endif
 
 #ifndef HYPERVISOR_VIRT_START
diff -druN linux-libre-3.1-gnu/arch/x86/include/asm/xen/page.h linux-libre-3.2-gnu/arch/x86/include/asm/xen/page.h
--- linux-libre-3.1-gnu/arch/x86/include/asm/xen/page.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/include/asm/xen/page.h	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <asm/pgtable.h>
 
 #include <xen/interface/xen.h>
+#include <xen/grant_table.h>
 #include <xen/features.h>
 
 /* Xen machine address */
@@ -48,14 +49,11 @@
 					     unsigned long pfn_e);
 
 extern int m2p_add_override(unsigned long mfn, struct page *page,
-			    bool clear_pte);
+			    struct gnttab_map_grant_ref *kmap_op);
 extern int m2p_remove_override(struct page *page, bool clear_pte);
 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;
diff -druN linux-libre-3.1-gnu/arch/x86/Kconfig linux-libre-3.2-gnu/arch/x86/Kconfig
--- linux-libre-3.1-gnu/arch/x86/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -64,10 +64,12 @@
 	select HAVE_TEXT_POKE_SMP
 	select HAVE_GENERIC_HARDIRQS
 	select HAVE_SPARSE_IRQ
+	select SPARSE_IRQ
 	select GENERIC_FIND_FIRST_BIT
 	select GENERIC_IRQ_PROBE
 	select GENERIC_PENDING_IRQ if SMP
 	select GENERIC_IRQ_SHOW
+	select GENERIC_CLOCKEVENTS_MIN_ADJUST
 	select IRQ_FORCED_THREADING
 	select USE_GENERIC_SMP_HELPERS if SMP
 	select HAVE_BPF_JIT if (X86_64 && NET)
@@ -130,7 +132,7 @@
 	bool
 
 config NEED_DMA_MAP_STATE
-       def_bool (X86_64 || DMAR || DMA_API_DEBUG)
+       def_bool (X86_64 || INTEL_IOMMU || DMA_API_DEBUG)
 
 config NEED_SG_DMA_LENGTH
 	def_bool y
@@ -192,9 +194,6 @@
 config NEED_PER_CPU_PAGE_FIRST_CHUNK
 	def_bool y
 
-config HAVE_CPUMASK_OF_CPU_MAP
-	def_bool X86_64_SMP
-
 config ARCH_HIBERNATION_POSSIBLE
 	def_bool y
 
@@ -220,7 +219,7 @@
 
 config HAVE_INTEL_TXT
 	def_bool y
-	depends on EXPERIMENTAL && DMAR && ACPI
+	depends on EXPERIMENTAL && INTEL_IOMMU && ACPI
 
 config X86_32_SMP
 	def_bool y
@@ -279,7 +278,7 @@
 	  Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
 	  Management" code will be disabled if you say Y here.
 
-	  See also <file:Documentation/i386/IO-APIC.txt>,
+	  See also <file:Documentation/x86/i386/IO-APIC.txt>,
 	  <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
 	  <http://www.tldp.org/docs.html#howto>.
 
@@ -287,7 +286,7 @@
 
 config X86_X2APIC
 	bool "Support x2apic"
-	depends on X86_LOCAL_APIC && X86_64 && INTR_REMAP
+	depends on X86_LOCAL_APIC && X86_64 && IRQ_REMAP
 	---help---
 	  This enables x2apic support on CPUs that have this feature.
 
@@ -391,7 +390,7 @@
 	  This option compiles in support for the CE4100 SOC for settop
 	  boxes and media devices.
 
-config X86_INTEL_MID
+config X86_WANT_INTEL_MID
 	bool "Intel MID platform support"
 	depends on X86_32
 	depends on X86_EXTENDED_PLATFORM
@@ -400,7 +399,10 @@
 	  systems which do not have the PCI legacy interfaces (Moorestown,
 	  Medfield). If you are building for a PC class system say N here.
 
-if X86_INTEL_MID
+if X86_WANT_INTEL_MID
+
+config X86_INTEL_MID
+	bool
 
 config X86_MRST
        bool "Moorestown MID platform"
@@ -412,6 +414,7 @@
 	select SPI
 	select INTEL_SCU_IPC
 	select X86_PLATFORM_DEVICES
+	select X86_INTEL_MID
 	---help---
 	  Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin
 	  Internet Device(MID) platform. Moorestown consists of two chips:
@@ -1452,6 +1455,15 @@
 	def_bool y
 	depends on X86_PAT
 
+config ARCH_RANDOM
+	def_bool y
+	prompt "x86 architectural random number generator" if EXPERT
+	---help---
+	  Enable the x86 architectural RDRAND instruction
+	  (Intel Bull Mountain technology) to generate random numbers.
+	  If supported, this is a high bandwidth, cryptographically
+	  secure hardware random number generator.
+
 config EFI
 	bool "EFI runtime service support"
 	depends on ACPI
@@ -2064,6 +2076,20 @@
 	   - AC adapter status updates
 	   - Battery status updates
 
+config ALIX
+	bool "PCEngines ALIX System Support (LED setup)"
+	select GPIOLIB
+	---help---
+	  This option enables system support for the PCEngines ALIX.
+	  At present this just sets up LEDs for GPIO control on
+	  ALIX2/3/6 boards.  However, other system specific setup should
+	  get added here.
+
+	  Note: You must still enable the drivers for GPIO and LED support
+	  (GPIO_CS5535 & LEDS_GPIO) to actually use the LEDs
+
+	  Note: You have to set alix.force=1 for boards with Award BIOS.
+
 endif # X86_32
 
 config AMD_NB
diff -druN linux-libre-3.1-gnu/arch/x86/Kconfig.debug linux-libre-3.2-gnu/arch/x86/Kconfig.debug
--- linux-libre-3.1-gnu/arch/x86/Kconfig.debug	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/Kconfig.debug	2012-01-04 18:55:44.000000000 -0500
@@ -139,7 +139,7 @@
 	  code. When you use it make sure you have a big enough
 	  IOMMU/AGP aperture.  Most of the options enabled by this can
 	  be set more finegrained using the iommu= command line
-	  options. See Documentation/x86_64/boot-options.txt for more
+	  options. See Documentation/x86/x86_64/boot-options.txt for more
 	  details.
 
 config IOMMU_STRESS
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/alternative.c linux-libre-3.2-gnu/arch/x86/kernel/alternative.c
--- linux-libre-3.1-gnu/arch/x86/kernel/alternative.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/alternative.c	2012-01-04 18:55:44.000000000 -0500
@@ -738,5 +738,5 @@
 
 	atomic_set(&stop_machine_first, 1);
 	wrote_text = 0;
-	__stop_machine(stop_machine_text_poke, (void *)&tpp, NULL);
+	__stop_machine(stop_machine_text_poke, (void *)&tpp, cpu_online_mask);
 }
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/amd_gart_64.c linux-libre-3.2-gnu/arch/x86/kernel/amd_gart_64.c
--- linux-libre-3.1-gnu/arch/x86/kernel/amd_gart_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/amd_gart_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
  * This allows to use PCI devices that only support 32bit addresses on systems
  * with more than 4GB.
  *
- * See Documentation/PCI/PCI-DMA-mapping.txt for the interface specification.
+ * See Documentation/DMA-API-HOWTO.txt for the interface specification.
  *
  * Copyright 2002 Andi Kleen, SuSE Labs.
  * Subject to the GNU General Public License v2 only.
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/apic/apic.c linux-libre-3.2-gnu/arch/x86/kernel/apic/apic.c
--- linux-libre-3.1-gnu/arch/x86/kernel/apic/apic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/apic/apic.c	2012-01-04 18:55:44.000000000 -0500
@@ -186,7 +186,7 @@
 	.flags = IORESOURCE_MEM | IORESOURCE_BUSY,
 };
 
-static unsigned int calibration_result;
+unsigned int lapic_timer_frequency = 0;
 
 static void apic_pm_activate(void);
 
@@ -454,7 +454,7 @@
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 	case CLOCK_EVT_MODE_ONESHOT:
-		__setup_APIC_LVTT(calibration_result,
+		__setup_APIC_LVTT(lapic_timer_frequency,
 				  mode != CLOCK_EVT_MODE_PERIODIC, 1);
 		break;
 	case CLOCK_EVT_MODE_UNUSED:
@@ -638,6 +638,25 @@
 	long delta, deltatsc;
 	int pm_referenced = 0;
 
+	/**
+	 * check if lapic timer has already been calibrated by platform
+	 * specific routine, such as tsc calibration code. if so, we just fill
+	 * in the clockevent structure and return.
+	 */
+
+	if (lapic_timer_frequency) {
+		apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n",
+				lapic_timer_frequency);
+		lapic_clockevent.mult = div_sc(lapic_timer_frequency/APIC_DIVISOR,
+					TICK_NSEC, lapic_clockevent.shift);
+		lapic_clockevent.max_delta_ns =
+			clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
+		lapic_clockevent.min_delta_ns =
+			clockevent_delta2ns(0xF, &lapic_clockevent);
+		lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
+		return 0;
+	}
+
 	local_irq_disable();
 
 	/* Replace the global interrupt handler */
@@ -679,12 +698,12 @@
 	lapic_clockevent.min_delta_ns =
 		clockevent_delta2ns(0xF, &lapic_clockevent);
 
-	calibration_result = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
+	lapic_timer_frequency = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
 
 	apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta);
 	apic_printk(APIC_VERBOSE, "..... mult: %u\n", lapic_clockevent.mult);
 	apic_printk(APIC_VERBOSE, "..... calibration result: %u\n",
-		    calibration_result);
+		    lapic_timer_frequency);
 
 	if (cpu_has_tsc) {
 		apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
@@ -695,13 +714,13 @@
 
 	apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
 		    "%u.%04u MHz.\n",
-		    calibration_result / (1000000 / HZ),
-		    calibration_result % (1000000 / HZ));
+		    lapic_timer_frequency / (1000000 / HZ),
+		    lapic_timer_frequency % (1000000 / HZ));
 
 	/*
 	 * Do a sanity check on the APIC calibration result
 	 */
-	if (calibration_result < (1000000 / HZ)) {
+	if (lapic_timer_frequency < (1000000 / HZ)) {
 		local_irq_enable();
 		pr_warning("APIC frequency too slow, disabling apic timer\n");
 		return -1;
@@ -1437,27 +1456,21 @@
 
 int __init enable_IR(void)
 {
-#ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_IRQ_REMAP
 	if (!intr_remapping_supported()) {
 		pr_debug("intr-remapping not supported\n");
-		return 0;
+		return -1;
 	}
 
 	if (!x2apic_preenabled && skip_ioapic_setup) {
 		pr_info("Skipped enabling intr-remap because of skipping "
 			"io-apic setup\n");
-		return 0;
+		return -1;
 	}
 
-	if (enable_intr_remapping(x2apic_supported()))
-		return 0;
-
-	pr_info("Enabled Interrupt-remapping\n");
-
-	return 1;
-
+	return enable_intr_remapping();
 #endif
-	return 0;
+	return -1;
 }
 
 void __init enable_IR_x2apic(void)
@@ -1481,11 +1494,11 @@
 	mask_ioapic_entries();
 
 	if (dmar_table_init_ret)
-		ret = 0;
+		ret = -1;
 	else
 		ret = enable_IR();
 
-	if (!ret) {
+	if (ret < 0) {
 		/* IR is required if there is APIC ID > 255 even when running
 		 * under KVM
 		 */
@@ -1499,6 +1512,9 @@
 		x2apic_force_phys();
 	}
 
+	if (ret == IRQ_REMAP_XAPIC_MODE)
+		goto nox2apic;
+
 	x2apic_enabled = 1;
 
 	if (x2apic_supported() && !x2apic_mode) {
@@ -1508,19 +1524,21 @@
 	}
 
 nox2apic:
-	if (!ret) /* IR enabling failed */
+	if (ret < 0) /* IR enabling failed */
 		restore_ioapic_entries();
 	legacy_pic->restore_mask();
 	local_irq_restore(flags);
 
 out:
-	if (x2apic_enabled)
+	if (x2apic_enabled || !x2apic_supported())
 		return;
 
 	if (x2apic_preenabled)
 		panic("x2apic: enabled by BIOS but kernel init failed.");
-	else if (cpu_has_x2apic)
-		pr_info("Not enabling x2apic, Intr-remapping init failed.\n");
+	else if (ret == IRQ_REMAP_XAPIC_MODE)
+		pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n");
+	else if (ret < 0)
+		pr_info("x2apic not enabled, IRQ remapping init failed\n");
 }
 
 #ifdef CONFIG_X86_64
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/apic/bigsmp_32.c linux-libre-3.2-gnu/arch/x86/kernel/apic/bigsmp_32.c
--- linux-libre-3.1-gnu/arch/x86/kernel/apic/bigsmp_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/apic/bigsmp_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -255,12 +255,24 @@
 	.x86_32_early_logical_apicid	= bigsmp_early_logical_apicid,
 };
 
-struct apic * __init generic_bigsmp_probe(void)
+void __init generic_bigsmp_probe(void)
 {
-	if (probe_bigsmp())
-		return &apic_bigsmp;
+	unsigned int cpu;
 
-	return NULL;
+	if (!probe_bigsmp())
+		return;
+
+	apic = &apic_bigsmp;
+
+	for_each_possible_cpu(cpu) {
+		if (early_per_cpu(x86_cpu_to_logical_apicid,
+				  cpu) == BAD_APICID)
+			continue;
+		early_per_cpu(x86_cpu_to_logical_apicid, cpu) =
+			bigsmp_early_logical_apicid(cpu);
+	}
+
+	pr_info("Overriding APIC driver with %s\n", apic_bigsmp.name);
 }
 
 apic_driver(apic_bigsmp);
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/apic/hw_nmi.c linux-libre-3.2-gnu/arch/x86/kernel/apic/hw_nmi.c
--- linux-libre-3.1-gnu/arch/x86/kernel/apic/hw_nmi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/apic/hw_nmi.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,22 +60,10 @@
 }
 
 static int __kprobes
-arch_trigger_all_cpu_backtrace_handler(struct notifier_block *self,
-			 unsigned long cmd, void *__args)
+arch_trigger_all_cpu_backtrace_handler(unsigned int cmd, struct pt_regs *regs)
 {
-	struct die_args *args = __args;
-	struct pt_regs *regs;
 	int cpu;
 
-	switch (cmd) {
-	case DIE_NMI:
-		break;
-
-	default:
-		return NOTIFY_DONE;
-	}
-
-	regs = args->regs;
 	cpu = smp_processor_id();
 
 	if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) {
@@ -86,21 +74,16 @@
 		show_regs(regs);
 		arch_spin_unlock(&lock);
 		cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask));
-		return NOTIFY_STOP;
+		return NMI_HANDLED;
 	}
 
-	return NOTIFY_DONE;
+	return NMI_DONE;
 }
 
-static __read_mostly struct notifier_block backtrace_notifier = {
-	.notifier_call          = arch_trigger_all_cpu_backtrace_handler,
-	.next                   = NULL,
-	.priority               = NMI_LOCAL_LOW_PRIOR,
-};
-
 static int __init register_trigger_all_cpu_backtrace(void)
 {
-	register_die_notifier(&backtrace_notifier);
+	register_nmi_handler(NMI_LOCAL, arch_trigger_all_cpu_backtrace_handler,
+				0, "arch_bt");
 	return 0;
 }
 early_initcall(register_trigger_all_cpu_backtrace);
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/apic/io_apic.c linux-libre-3.2-gnu/arch/x86/kernel/apic/io_apic.c
--- linux-libre-3.1-gnu/arch/x86/kernel/apic/io_apic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/apic/io_apic.c	2012-01-04 18:55:44.000000000 -0500
@@ -92,21 +92,21 @@
 	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
 } ioapics[MAX_IO_APICS];
 
-#define mpc_ioapic_ver(id)		ioapics[id].mp_config.apicver
+#define mpc_ioapic_ver(ioapic_idx)	ioapics[ioapic_idx].mp_config.apicver
 
-int mpc_ioapic_id(int id)
+int mpc_ioapic_id(int ioapic_idx)
 {
-	return ioapics[id].mp_config.apicid;
+	return ioapics[ioapic_idx].mp_config.apicid;
 }
 
-unsigned int mpc_ioapic_addr(int id)
+unsigned int mpc_ioapic_addr(int ioapic_idx)
 {
-	return ioapics[id].mp_config.apicaddr;
+	return ioapics[ioapic_idx].mp_config.apicaddr;
 }
 
-struct mp_ioapic_gsi *mp_ioapic_gsi_routing(int id)
+struct mp_ioapic_gsi *mp_ioapic_gsi_routing(int ioapic_idx)
 {
-	return &ioapics[id].gsi_config;
+	return &ioapics[ioapic_idx].gsi_config;
 }
 
 int nr_ioapics;
@@ -186,21 +186,15 @@
 
 
 /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
-#ifdef CONFIG_SPARSE_IRQ
 static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY];
-#else
-static struct irq_cfg irq_cfgx[NR_IRQS];
-#endif
 
 int __init arch_early_irq_init(void)
 {
 	struct irq_cfg *cfg;
 	int count, node, i;
 
-	if (!legacy_pic->nr_legacy_irqs) {
-		nr_irqs_gsi = 0;
+	if (!legacy_pic->nr_legacy_irqs)
 		io_apic_irqs = ~0UL;
-	}
 
 	for (i = 0; i < nr_ioapics; i++) {
 		ioapics[i].saved_registers =
@@ -234,7 +228,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_SPARSE_IRQ
 static struct irq_cfg *irq_cfg(unsigned int irq)
 {
 	return irq_get_chip_data(irq);
@@ -269,22 +262,6 @@
 	kfree(cfg);
 }
 
-#else
-
-struct irq_cfg *irq_cfg(unsigned int irq)
-{
-	return irq < nr_irqs ? irq_cfgx + irq : NULL;
-}
-
-static struct irq_cfg *alloc_irq_cfg(unsigned int irq, int node)
-{
-	return irq_cfgx + irq;
-}
-
-static inline void free_irq_cfg(unsigned int at, struct irq_cfg *cfg) { }
-
-#endif
-
 static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node)
 {
 	int res = irq_alloc_desc_at(at, node);
@@ -394,13 +371,21 @@
 	struct IO_APIC_route_entry entry;
 };
 
+static struct IO_APIC_route_entry __ioapic_read_entry(int apic, int pin)
+{
+	union entry_union eu;
+
+	eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
+	eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
+	return eu.entry;
+}
+
 static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
 {
 	union entry_union eu;
 	unsigned long flags;
 	raw_spin_lock_irqsave(&ioapic_lock, flags);
-	eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
-	eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
+	eu.entry = __ioapic_read_entry(apic, pin);
 	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 	return eu.entry;
 }
@@ -529,18 +514,6 @@
 		__io_apic_modify_irq(entry, mask_and, mask_or, final);
 }
 
-static void __mask_and_edge_IO_APIC_irq(struct irq_pin_list *entry)
-{
-	__io_apic_modify_irq(entry, ~IO_APIC_REDIR_LEVEL_TRIGGER,
-			     IO_APIC_REDIR_MASKED, NULL);
-}
-
-static void __unmask_and_level_IO_APIC_irq(struct irq_pin_list *entry)
-{
-	__io_apic_modify_irq(entry, ~IO_APIC_REDIR_MASKED,
-			     IO_APIC_REDIR_LEVEL_TRIGGER, NULL);
-}
-
 static void io_apic_sync(struct irq_pin_list *entry)
 {
 	/*
@@ -585,6 +558,66 @@
 	unmask_ioapic(data->chip_data);
 }
 
+/*
+ * IO-APIC versions below 0x20 don't support EOI register.
+ * For the record, here is the information about various versions:
+ *     0Xh     82489DX
+ *     1Xh     I/OAPIC or I/O(x)APIC which are not PCI 2.2 Compliant
+ *     2Xh     I/O(x)APIC which is PCI 2.2 Compliant
+ *     30h-FFh Reserved
+ *
+ * Some of the Intel ICH Specs (ICH2 to ICH5) documents the io-apic
+ * version as 0x2. This is an error with documentation and these ICH chips
+ * use io-apic's of version 0x20.
+ *
+ * For IO-APIC's with EOI register, we use that to do an explicit EOI.
+ * Otherwise, we simulate the EOI message manually by changing the trigger
+ * mode to edge and then back to level, with RTE being masked during this.
+ */
+static void __eoi_ioapic_pin(int apic, int pin, int vector, struct irq_cfg *cfg)
+{
+	if (mpc_ioapic_ver(apic) >= 0x20) {
+		/*
+		 * Intr-remapping uses pin number as the virtual vector
+		 * in the RTE. Actual vector is programmed in
+		 * intr-remapping table entry. Hence for the io-apic
+		 * EOI we use the pin number.
+		 */
+		if (cfg && irq_remapped(cfg))
+			io_apic_eoi(apic, pin);
+		else
+			io_apic_eoi(apic, vector);
+	} else {
+		struct IO_APIC_route_entry entry, entry1;
+
+		entry = entry1 = __ioapic_read_entry(apic, pin);
+
+		/*
+		 * Mask the entry and change the trigger mode to edge.
+		 */
+		entry1.mask = 1;
+		entry1.trigger = IOAPIC_EDGE;
+
+		__ioapic_write_entry(apic, pin, entry1);
+
+		/*
+		 * Restore the previous level triggered entry.
+		 */
+		__ioapic_write_entry(apic, pin, entry);
+	}
+}
+
+static void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
+{
+	struct irq_pin_list *entry;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
+	for_each_irq_pin(entry, cfg->irq_2_pin)
+		__eoi_ioapic_pin(entry->apic, entry->pin, cfg->vector, cfg);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
 static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
 {
 	struct IO_APIC_route_entry entry;
@@ -593,10 +626,44 @@
 	entry = ioapic_read_entry(apic, pin);
 	if (entry.delivery_mode == dest_SMI)
 		return;
+
 	/*
-	 * Disable it in the IO-APIC irq-routing table:
+	 * Make sure the entry is masked and re-read the contents to check
+	 * if it is a level triggered pin and if the remote-IRR is set.
+	 */
+	if (!entry.mask) {
+		entry.mask = 1;
+		ioapic_write_entry(apic, pin, entry);
+		entry = ioapic_read_entry(apic, pin);
+	}
+
+	if (entry.irr) {
+		unsigned long flags;
+
+		/*
+		 * Make sure the trigger mode is set to level. Explicit EOI
+		 * doesn't clear the remote-IRR if the trigger mode is not
+		 * set to level.
+		 */
+		if (!entry.trigger) {
+			entry.trigger = IOAPIC_LEVEL;
+			ioapic_write_entry(apic, pin, entry);
+		}
+
+		raw_spin_lock_irqsave(&ioapic_lock, flags);
+		__eoi_ioapic_pin(apic, pin, entry.vector, NULL);
+		raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+	}
+
+	/*
+	 * Clear the rest of the bits in the IO-APIC RTE except for the mask
+	 * bit.
 	 */
 	ioapic_mask_entry(apic, pin);
+	entry = ioapic_read_entry(apic, pin);
+	if (entry.irr)
+		printk(KERN_ERR "Unable to reset IRR for apic: %d, pin :%d\n",
+		       mpc_ioapic_id(apic), pin);
 }
 
 static void clear_IO_APIC (void)
@@ -712,13 +779,13 @@
 /*
  * Find the IRQ entry number of a certain pin.
  */
-static int find_irq_entry(int apic, int pin, int type)
+static int find_irq_entry(int ioapic_idx, int pin, int type)
 {
 	int i;
 
 	for (i = 0; i < mp_irq_entries; i++)
 		if (mp_irqs[i].irqtype == type &&
-		    (mp_irqs[i].dstapic == mpc_ioapic_id(apic) ||
+		    (mp_irqs[i].dstapic == mpc_ioapic_id(ioapic_idx) ||
 		     mp_irqs[i].dstapic == MP_APIC_ALL) &&
 		    mp_irqs[i].dstirq == pin)
 			return i;
@@ -757,12 +824,13 @@
 		    (mp_irqs[i].srcbusirq == irq))
 			break;
 	}
+
 	if (i < mp_irq_entries) {
-		int apic;
-		for(apic = 0; apic < nr_ioapics; apic++) {
-			if (mpc_ioapic_id(apic) == mp_irqs[i].dstapic)
-				return apic;
-		}
+		int ioapic_idx;
+
+		for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+			if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic)
+				return ioapic_idx;
 	}
 
 	return -1;
@@ -977,7 +1045,7 @@
 int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
 				struct io_apic_irq_attr *irq_attr)
 {
-	int apic, i, best_guess = -1;
+	int ioapic_idx, i, best_guess = -1;
 
 	apic_printk(APIC_DEBUG,
 		    "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
@@ -990,8 +1058,8 @@
 	for (i = 0; i < mp_irq_entries; i++) {
 		int lbus = mp_irqs[i].srcbus;
 
-		for (apic = 0; apic < nr_ioapics; apic++)
-			if (mpc_ioapic_id(apic) == mp_irqs[i].dstapic ||
+		for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+			if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic ||
 			    mp_irqs[i].dstapic == MP_APIC_ALL)
 				break;
 
@@ -999,13 +1067,13 @@
 		    !mp_irqs[i].irqtype &&
 		    (bus == lbus) &&
 		    (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
-			int irq = pin_2_irq(i, apic, mp_irqs[i].dstirq);
+			int irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq);
 
-			if (!(apic || IO_APIC_IRQ(irq)))
+			if (!(ioapic_idx || IO_APIC_IRQ(irq)))
 				continue;
 
 			if (pin == (mp_irqs[i].srcbusirq & 3)) {
-				set_io_apic_irq_attr(irq_attr, apic,
+				set_io_apic_irq_attr(irq_attr, ioapic_idx,
 						     mp_irqs[i].dstirq,
 						     irq_trigger(i),
 						     irq_polarity(i));
@@ -1016,7 +1084,7 @@
 			 * best-guess fuzzy result for broken mptables.
 			 */
 			if (best_guess < 0) {
-				set_io_apic_irq_attr(irq_attr, apic,
+				set_io_apic_irq_attr(irq_attr, ioapic_idx,
 						     mp_irqs[i].dstirq,
 						     irq_trigger(i),
 						     irq_polarity(i));
@@ -1202,7 +1270,6 @@
 }
 
 static struct irq_chip ioapic_chip;
-static struct irq_chip ir_ioapic_chip;
 
 #ifdef CONFIG_X86_32
 static inline int IO_APIC_irq_trigger(int irq)
@@ -1246,7 +1313,7 @@
 
 	if (irq_remapped(cfg)) {
 		irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
-		chip = &ir_ioapic_chip;
+		irq_remap_modify_chip_defaults(chip);
 		fasteoi = trigger != 0;
 	}
 
@@ -1255,77 +1322,100 @@
 				      fasteoi ? "fasteoi" : "edge");
 }
 
-static int setup_ioapic_entry(int apic_id, int irq,
-			      struct IO_APIC_route_entry *entry,
-			      unsigned int destination, int trigger,
-			      int polarity, int vector, int pin)
-{
-	/*
-	 * add it to the IO-APIC irq-routing table:
-	 */
-	memset(entry,0,sizeof(*entry));
 
-	if (intr_remapping_enabled) {
-		struct intel_iommu *iommu = map_ioapic_to_ir(apic_id);
-		struct irte irte;
-		struct IR_IO_APIC_route_entry *ir_entry =
-			(struct IR_IO_APIC_route_entry *) entry;
-		int index;
+static int setup_ir_ioapic_entry(int irq,
+			      struct IR_IO_APIC_route_entry *entry,
+			      unsigned int destination, int vector,
+			      struct io_apic_irq_attr *attr)
+{
+	int index;
+	struct irte irte;
+	int ioapic_id = mpc_ioapic_id(attr->ioapic);
+	struct intel_iommu *iommu = map_ioapic_to_ir(ioapic_id);
 
-		if (!iommu)
-			panic("No mapping iommu for ioapic %d\n", apic_id);
+	if (!iommu) {
+		pr_warn("No mapping iommu for ioapic %d\n", ioapic_id);
+		return -ENODEV;
+	}
 
-		index = alloc_irte(iommu, irq, 1);
-		if (index < 0)
-			panic("Failed to allocate IRTE for ioapic %d\n", apic_id);
+	index = alloc_irte(iommu, irq, 1);
+	if (index < 0) {
+		pr_warn("Failed to allocate IRTE for ioapic %d\n", ioapic_id);
+		return -ENOMEM;
+	}
 
-		prepare_irte(&irte, vector, destination);
+	prepare_irte(&irte, vector, destination);
 
-		/* Set source-id of interrupt request */
-		set_ioapic_sid(&irte, apic_id);
+	/* Set source-id of interrupt request */
+	set_ioapic_sid(&irte, ioapic_id);
 
-		modify_irte(irq, &irte);
+	modify_irte(irq, &irte);
 
-		ir_entry->index2 = (index >> 15) & 0x1;
-		ir_entry->zero = 0;
-		ir_entry->format = 1;
-		ir_entry->index = (index & 0x7fff);
-		/*
-		 * IO-APIC RTE will be configured with virtual vector.
-		 * irq handler will do the explicit EOI to the io-apic.
-		 */
-		ir_entry->vector = pin;
+	apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: "
+		"Set IRTE entry (P:%d FPD:%d Dst_Mode:%d "
+		"Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X "
+		"Avail:%X Vector:%02X Dest:%08X "
+		"SID:%04X SQ:%X SVT:%X)\n",
+		attr->ioapic, irte.present, irte.fpd, irte.dst_mode,
+		irte.redir_hint, irte.trigger_mode, irte.dlvry_mode,
+		irte.avail, irte.vector, irte.dest_id,
+		irte.sid, irte.sq, irte.svt);
 
-		apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: "
-			"Set IRTE entry (P:%d FPD:%d Dst_Mode:%d "
-			"Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X "
-			"Avail:%X Vector:%02X Dest:%08X "
-			"SID:%04X SQ:%X SVT:%X)\n",
-			apic_id, irte.present, irte.fpd, irte.dst_mode,
-			irte.redir_hint, irte.trigger_mode, irte.dlvry_mode,
-			irte.avail, irte.vector, irte.dest_id,
-			irte.sid, irte.sq, irte.svt);
-	} else {
-		entry->delivery_mode = apic->irq_delivery_mode;
-		entry->dest_mode = apic->irq_dest_mode;
-		entry->dest = destination;
-		entry->vector = vector;
-	}
+	memset(entry, 0, sizeof(*entry));
 
-	entry->mask = 0;				/* enable IRQ */
-	entry->trigger = trigger;
-	entry->polarity = polarity;
+	entry->index2	= (index >> 15) & 0x1;
+	entry->zero	= 0;
+	entry->format	= 1;
+	entry->index	= (index & 0x7fff);
+	/*
+	 * IO-APIC RTE will be configured with virtual vector.
+	 * irq handler will do the explicit EOI to the io-apic.
+	 */
+	entry->vector	= attr->ioapic_pin;
+	entry->mask	= 0;			/* enable IRQ */
+	entry->trigger	= attr->trigger;
+	entry->polarity	= attr->polarity;
 
 	/* Mask level triggered irqs.
 	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
 	 */
-	if (trigger)
+	if (attr->trigger)
 		entry->mask = 1;
+
 	return 0;
 }
 
-static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq,
-			     struct irq_cfg *cfg, int trigger, int polarity)
+static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry,
+			       unsigned int destination, int vector,
+			       struct io_apic_irq_attr *attr)
+{
+	if (intr_remapping_enabled)
+		return setup_ir_ioapic_entry(irq,
+			 (struct IR_IO_APIC_route_entry *)entry,
+			 destination, vector, attr);
+
+	memset(entry, 0, sizeof(*entry));
+
+	entry->delivery_mode = apic->irq_delivery_mode;
+	entry->dest_mode     = apic->irq_dest_mode;
+	entry->dest	     = destination;
+	entry->vector	     = vector;
+	entry->mask	     = 0;			/* enable IRQ */
+	entry->trigger	     = attr->trigger;
+	entry->polarity	     = attr->polarity;
+
+	/*
+	 * Mask level triggered irqs.
+	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
+	 */
+	if (attr->trigger)
+		entry->mask = 1;
+
+	return 0;
+}
+
+static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg,
+				struct io_apic_irq_attr *attr)
 {
 	struct IO_APIC_route_entry entry;
 	unsigned int dest;
@@ -1348,49 +1438,48 @@
 	apic_printk(APIC_VERBOSE,KERN_DEBUG
 		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
 		    "IRQ %d Mode:%i Active:%i Dest:%d)\n",
-		    apic_id, mpc_ioapic_id(apic_id), pin, cfg->vector,
-		    irq, trigger, polarity, dest);
-
+		    attr->ioapic, mpc_ioapic_id(attr->ioapic), attr->ioapic_pin,
+		    cfg->vector, irq, attr->trigger, attr->polarity, dest);
 
-	if (setup_ioapic_entry(mpc_ioapic_id(apic_id), irq, &entry,
-			       dest, trigger, polarity, cfg->vector, pin)) {
-		printk("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
-		       mpc_ioapic_id(apic_id), pin);
+	if (setup_ioapic_entry(irq, &entry, dest, cfg->vector, attr)) {
+		pr_warn("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
+			mpc_ioapic_id(attr->ioapic), attr->ioapic_pin);
 		__clear_irq_vector(irq, cfg);
+
 		return;
 	}
 
-	ioapic_register_intr(irq, cfg, trigger);
+	ioapic_register_intr(irq, cfg, attr->trigger);
 	if (irq < legacy_pic->nr_legacy_irqs)
 		legacy_pic->mask(irq);
 
-	ioapic_write_entry(apic_id, pin, entry);
+	ioapic_write_entry(attr->ioapic, attr->ioapic_pin, entry);
 }
 
-static bool __init io_apic_pin_not_connected(int idx, int apic_id, int pin)
+static bool __init io_apic_pin_not_connected(int idx, int ioapic_idx, int pin)
 {
 	if (idx != -1)
 		return false;
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG " apic %d pin %d not connected\n",
-		    mpc_ioapic_id(apic_id), pin);
+		    mpc_ioapic_id(ioapic_idx), pin);
 	return true;
 }
 
-static void __init __io_apic_setup_irqs(unsigned int apic_id)
+static void __init __io_apic_setup_irqs(unsigned int ioapic_idx)
 {
 	int idx, node = cpu_to_node(0);
 	struct io_apic_irq_attr attr;
 	unsigned int pin, irq;
 
-	for (pin = 0; pin < ioapics[apic_id].nr_registers; pin++) {
-		idx = find_irq_entry(apic_id, pin, mp_INT);
-		if (io_apic_pin_not_connected(idx, apic_id, pin))
+	for (pin = 0; pin < ioapics[ioapic_idx].nr_registers; pin++) {
+		idx = find_irq_entry(ioapic_idx, pin, mp_INT);
+		if (io_apic_pin_not_connected(idx, ioapic_idx, pin))
 			continue;
 
-		irq = pin_2_irq(idx, apic_id, pin);
+		irq = pin_2_irq(idx, ioapic_idx, pin);
 
-		if ((apic_id > 0) && (irq > 16))
+		if ((ioapic_idx > 0) && (irq > 16))
 			continue;
 
 		/*
@@ -1398,10 +1487,10 @@
 		 * installed and if it returns 1:
 		 */
 		if (apic->multi_timer_check &&
-		    apic->multi_timer_check(apic_id, irq))
+		    apic->multi_timer_check(ioapic_idx, irq))
 			continue;
 
-		set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
+		set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
 				     irq_polarity(idx));
 
 		io_apic_setup_irq_pin(irq, node, &attr);
@@ -1410,12 +1499,12 @@
 
 static void __init setup_IO_APIC_irqs(void)
 {
-	unsigned int apic_id;
+	unsigned int ioapic_idx;
 
 	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);
+	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+		__io_apic_setup_irqs(ioapic_idx);
 }
 
 /*
@@ -1425,28 +1514,28 @@
  */
 void setup_IO_APIC_irq_extra(u32 gsi)
 {
-	int apic_id = 0, pin, idx, irq, node = cpu_to_node(0);
+	int ioapic_idx = 0, pin, idx, irq, node = cpu_to_node(0);
 	struct io_apic_irq_attr attr;
 
 	/*
 	 * Convert 'gsi' to 'ioapic.pin'.
 	 */
-	apic_id = mp_find_ioapic(gsi);
-	if (apic_id < 0)
+	ioapic_idx = mp_find_ioapic(gsi);
+	if (ioapic_idx < 0)
 		return;
 
-	pin = mp_find_ioapic_pin(apic_id, gsi);
-	idx = find_irq_entry(apic_id, pin, mp_INT);
+	pin = mp_find_ioapic_pin(ioapic_idx, gsi);
+	idx = find_irq_entry(ioapic_idx, pin, mp_INT);
 	if (idx == -1)
 		return;
 
-	irq = pin_2_irq(idx, apic_id, pin);
+	irq = pin_2_irq(idx, ioapic_idx, pin);
 
 	/* Only handle the non legacy irqs on secondary ioapics */
-	if (apic_id == 0 || irq < NR_IRQS_LEGACY)
+	if (ioapic_idx == 0 || irq < NR_IRQS_LEGACY)
 		return;
 
-	set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
+	set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
 			     irq_polarity(idx));
 
 	io_apic_setup_irq_pin_once(irq, node, &attr);
@@ -1455,8 +1544,8 @@
 /*
  * Set up the timer pin, possibly with the 8259A-master behind.
  */
-static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin,
-					int vector)
+static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx,
+					 unsigned int pin, int vector)
 {
 	struct IO_APIC_route_entry entry;
 
@@ -1487,45 +1576,29 @@
 	/*
 	 * Add it to the IO-APIC irq-routing table:
 	 */
-	ioapic_write_entry(apic_id, pin, entry);
+	ioapic_write_entry(ioapic_idx, pin, entry);
 }
 
-
-__apicdebuginit(void) print_IO_APIC(void)
+__apicdebuginit(void) print_IO_APIC(int ioapic_idx)
 {
-	int apic, i;
+	int i;
 	union IO_APIC_reg_00 reg_00;
 	union IO_APIC_reg_01 reg_01;
 	union IO_APIC_reg_02 reg_02;
 	union IO_APIC_reg_03 reg_03;
 	unsigned long flags;
-	struct irq_cfg *cfg;
-	unsigned int irq;
-
-	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
-	for (i = 0; i < nr_ioapics; i++)
-		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
-		       mpc_ioapic_id(i), ioapics[i].nr_registers);
-
-	/*
-	 * We are a bit conservative about what we expect.  We have to
-	 * know about every hardware change ASAP.
-	 */
-	printk(KERN_INFO "testing the IO APIC.......................\n");
-
-	for (apic = 0; apic < nr_ioapics; apic++) {
 
 	raw_spin_lock_irqsave(&ioapic_lock, flags);
-	reg_00.raw = io_apic_read(apic, 0);
-	reg_01.raw = io_apic_read(apic, 1);
+	reg_00.raw = io_apic_read(ioapic_idx, 0);
+	reg_01.raw = io_apic_read(ioapic_idx, 1);
 	if (reg_01.bits.version >= 0x10)
-		reg_02.raw = io_apic_read(apic, 2);
+		reg_02.raw = io_apic_read(ioapic_idx, 2);
 	if (reg_01.bits.version >= 0x20)
-		reg_03.raw = io_apic_read(apic, 3);
+		reg_03.raw = io_apic_read(ioapic_idx, 3);
 	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	printk("\n");
-	printk(KERN_DEBUG "IO APIC #%d......\n", mpc_ioapic_id(apic));
+	printk(KERN_DEBUG "IO APIC #%d......\n", mpc_ioapic_id(ioapic_idx));
 	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
 	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
 	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
@@ -1575,7 +1648,7 @@
 			struct IO_APIC_route_entry entry;
 			struct IR_IO_APIC_route_entry *ir_entry;
 
-			entry = ioapic_read_entry(apic, i);
+			entry = ioapic_read_entry(ioapic_idx, i);
 			ir_entry = (struct IR_IO_APIC_route_entry *) &entry;
 			printk(KERN_DEBUG " %02x %04X ",
 				i,
@@ -1596,7 +1669,7 @@
 		} else {
 			struct IO_APIC_route_entry entry;
 
-			entry = ioapic_read_entry(apic, i);
+			entry = ioapic_read_entry(ioapic_idx, i);
 			printk(KERN_DEBUG " %02x %02X  ",
 				i,
 				entry.dest
@@ -1614,12 +1687,38 @@
 			);
 		}
 	}
-	}
+}
+
+__apicdebuginit(void) print_IO_APICs(void)
+{
+	int ioapic_idx;
+	struct irq_cfg *cfg;
+	unsigned int irq;
+	struct irq_chip *chip;
+
+	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
+	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
+		       mpc_ioapic_id(ioapic_idx),
+		       ioapics[ioapic_idx].nr_registers);
+
+	/*
+	 * We are a bit conservative about what we expect.  We have to
+	 * know about every hardware change ASAP.
+	 */
+	printk(KERN_INFO "testing the IO APIC.......................\n");
+
+	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+		print_IO_APIC(ioapic_idx);
 
 	printk(KERN_DEBUG "IRQ to pin mappings:\n");
 	for_each_active_irq(irq) {
 		struct irq_pin_list *entry;
 
+		chip = irq_get_chip(irq);
+		if (chip != &ioapic_chip)
+			continue;
+
 		cfg = irq_get_chip_data(irq);
 		if (!cfg)
 			continue;
@@ -1633,8 +1732,6 @@
 	}
 
 	printk(KERN_INFO ".................................... done.\n");
-
-	return;
 }
 
 __apicdebuginit(void) print_APIC_field(int base)
@@ -1828,7 +1925,7 @@
 		return 0;
 
 	print_local_APICs(show_lapic);
-	print_IO_APIC();
+	print_IO_APICs();
 
 	return 0;
 }
@@ -1953,7 +2050,7 @@
 {
 	union IO_APIC_reg_00 reg_00;
 	physid_mask_t phys_id_present_map;
-	int apic_id;
+	int ioapic_idx;
 	int i;
 	unsigned char old_id;
 	unsigned long flags;
@@ -1967,21 +2064,20 @@
 	/*
 	 * Set the IOAPIC ID to the value stored in the MPC table.
 	 */
-	for (apic_id = 0; apic_id < nr_ioapics; apic_id++) {
-
+	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) {
 		/* Read the register 0 value */
 		raw_spin_lock_irqsave(&ioapic_lock, flags);
-		reg_00.raw = io_apic_read(apic_id, 0);
+		reg_00.raw = io_apic_read(ioapic_idx, 0);
 		raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
-		old_id = mpc_ioapic_id(apic_id);
+		old_id = mpc_ioapic_id(ioapic_idx);
 
-		if (mpc_ioapic_id(apic_id) >= get_physical_broadcast()) {
+		if (mpc_ioapic_id(ioapic_idx) >= get_physical_broadcast()) {
 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
-				apic_id, mpc_ioapic_id(apic_id));
+				ioapic_idx, mpc_ioapic_id(ioapic_idx));
 			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
 				reg_00.bits.ID);
-			ioapics[apic_id].mp_config.apicid = reg_00.bits.ID;
+			ioapics[ioapic_idx].mp_config.apicid = reg_00.bits.ID;
 		}
 
 		/*
@@ -1990,9 +2086,9 @@
 		 * 'stuck on smp_invalidate_needed IPI wait' messages.
 		 */
 		if (apic->check_apicid_used(&phys_id_present_map,
-					    mpc_ioapic_id(apic_id))) {
+					    mpc_ioapic_id(ioapic_idx))) {
 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
-				apic_id, mpc_ioapic_id(apic_id));
+				ioapic_idx, mpc_ioapic_id(ioapic_idx));
 			for (i = 0; i < get_physical_broadcast(); i++)
 				if (!physid_isset(i, phys_id_present_map))
 					break;
@@ -2001,14 +2097,14 @@
 			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
 				i);
 			physid_set(i, phys_id_present_map);
-			ioapics[apic_id].mp_config.apicid = i;
+			ioapics[ioapic_idx].mp_config.apicid = i;
 		} else {
 			physid_mask_t tmp;
-			apic->apicid_to_cpu_present(mpc_ioapic_id(apic_id),
+			apic->apicid_to_cpu_present(mpc_ioapic_id(ioapic_idx),
 						    &tmp);
 			apic_printk(APIC_VERBOSE, "Setting %d in the "
 					"phys_id_present_map\n",
-					mpc_ioapic_id(apic_id));
+					mpc_ioapic_id(ioapic_idx));
 			physids_or(phys_id_present_map, phys_id_present_map, tmp);
 		}
 
@@ -2016,35 +2112,35 @@
 		 * We need to adjust the IRQ routing table
 		 * if the ID changed.
 		 */
-		if (old_id != mpc_ioapic_id(apic_id))
+		if (old_id != mpc_ioapic_id(ioapic_idx))
 			for (i = 0; i < mp_irq_entries; i++)
 				if (mp_irqs[i].dstapic == old_id)
 					mp_irqs[i].dstapic
-						= mpc_ioapic_id(apic_id);
+						= mpc_ioapic_id(ioapic_idx);
 
 		/*
 		 * Update the ID register according to the right value
 		 * from the MPC table if they are different.
 		 */
-		if (mpc_ioapic_id(apic_id) == reg_00.bits.ID)
+		if (mpc_ioapic_id(ioapic_idx) == reg_00.bits.ID)
 			continue;
 
 		apic_printk(APIC_VERBOSE, KERN_INFO
 			"...changing IO-APIC physical APIC ID to %d ...",
-			mpc_ioapic_id(apic_id));
+			mpc_ioapic_id(ioapic_idx));
 
-		reg_00.bits.ID = mpc_ioapic_id(apic_id);
+		reg_00.bits.ID = mpc_ioapic_id(ioapic_idx);
 		raw_spin_lock_irqsave(&ioapic_lock, flags);
-		io_apic_write(apic_id, 0, reg_00.raw);
+		io_apic_write(ioapic_idx, 0, reg_00.raw);
 		raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
 		/*
 		 * Sanity check
 		 */
 		raw_spin_lock_irqsave(&ioapic_lock, flags);
-		reg_00.raw = io_apic_read(apic_id, 0);
+		reg_00.raw = io_apic_read(ioapic_idx, 0);
 		raw_spin_unlock_irqrestore(&ioapic_lock, flags);
-		if (reg_00.bits.ID != mpc_ioapic_id(apic_id))
+		if (reg_00.bits.ID != mpc_ioapic_id(ioapic_idx))
 			printk("could not set ID!\n");
 		else
 			apic_printk(APIC_VERBOSE, " ok.\n");
@@ -2255,7 +2351,7 @@
 	return ret;
 }
 
-#ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_IRQ_REMAP
 
 /*
  * Migrate the IO-APIC irq in the presence of intr-remapping.
@@ -2267,6 +2363,9 @@
  * updated vector information), by using a virtual vector (io-apic pin number).
  * Real vector that is used for interrupting cpu will be coming from
  * the interrupt-remapping table entry.
+ *
+ * As the migration is a simple atomic update of IRTE, the same mechanism
+ * is used to migrate MSI irq's in the presence of interrupt-remapping.
  */
 static int
 ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
@@ -2291,10 +2390,16 @@
 	irte.dest_id = IRTE_DEST(dest);
 
 	/*
-	 * Modified the IRTE and flushes the Interrupt entry cache.
+	 * Atomically updates the IRTE with the new destination, vector
+	 * and flushes the interrupt entry cache.
 	 */
 	modify_irte(irq, &irte);
 
+	/*
+	 * After this point, all the interrupts will start arriving
+	 * at the new destination. So, time to cleanup the previous
+	 * vector allocation.
+	 */
 	if (cfg->move_in_progress)
 		send_cleanup_vector(cfg);
 
@@ -2407,48 +2512,6 @@
 
 atomic_t irq_mis_count;
 
-/*
- * IO-APIC versions below 0x20 don't support EOI register.
- * For the record, here is the information about various versions:
- *     0Xh     82489DX
- *     1Xh     I/OAPIC or I/O(x)APIC which are not PCI 2.2 Compliant
- *     2Xh     I/O(x)APIC which is PCI 2.2 Compliant
- *     30h-FFh Reserved
- *
- * Some of the Intel ICH Specs (ICH2 to ICH5) documents the io-apic
- * version as 0x2. This is an error with documentation and these ICH chips
- * use io-apic's of version 0x20.
- *
- * For IO-APIC's with EOI register, we use that to do an explicit EOI.
- * Otherwise, we simulate the EOI message manually by changing the trigger
- * mode to edge and then back to level, with RTE being masked during this.
-*/
-static void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
-{
-	struct irq_pin_list *entry;
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&ioapic_lock, flags);
-	for_each_irq_pin(entry, cfg->irq_2_pin) {
-		if (mpc_ioapic_ver(entry->apic) >= 0x20) {
-			/*
-			 * Intr-remapping uses pin number as the virtual vector
-			 * in the RTE. Actual vector is programmed in
-			 * intr-remapping table entry. Hence for the io-apic
-			 * EOI we use the pin number.
-			 */
-			if (irq_remapped(cfg))
-				io_apic_eoi(entry->apic, entry->pin);
-			else
-				io_apic_eoi(entry->apic, cfg->vector);
-		} else {
-			__mask_and_edge_IO_APIC_irq(entry);
-			__unmask_and_level_IO_APIC_irq(entry);
-		}
-	}
-	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
 static void ack_apic_level(struct irq_data *data)
 {
 	struct irq_cfg *cfg = data->chip_data;
@@ -2552,7 +2615,7 @@
 	}
 }
 
-#ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_IRQ_REMAP
 static void ir_ack_apic_edge(struct irq_data *data)
 {
 	ack_APIC_irq();
@@ -2563,7 +2626,23 @@
 	ack_APIC_irq();
 	eoi_ioapic_irq(data->irq, data->chip_data);
 }
-#endif /* CONFIG_INTR_REMAP */
+
+static void ir_print_prefix(struct irq_data *data, struct seq_file *p)
+{
+	seq_printf(p, " IR-%s", data->chip->name);
+}
+
+static void irq_remap_modify_chip_defaults(struct irq_chip *chip)
+{
+	chip->irq_print_chip = ir_print_prefix;
+	chip->irq_ack = ir_ack_apic_edge;
+	chip->irq_eoi = ir_ack_apic_level;
+
+#ifdef CONFIG_SMP
+	chip->irq_set_affinity = ir_ioapic_set_affinity;
+#endif
+}
+#endif /* CONFIG_IRQ_REMAP */
 
 static struct irq_chip ioapic_chip __read_mostly = {
 	.name			= "IO-APIC",
@@ -2578,21 +2657,6 @@
 	.irq_retrigger		= ioapic_retrigger_irq,
 };
 
-static struct irq_chip ir_ioapic_chip __read_mostly = {
-	.name			= "IR-IO-APIC",
-	.irq_startup		= startup_ioapic_irq,
-	.irq_mask		= mask_ioapic_irq,
-	.irq_unmask		= unmask_ioapic_irq,
-#ifdef CONFIG_INTR_REMAP
-	.irq_ack		= ir_ack_apic_edge,
-	.irq_eoi		= ir_ack_apic_level,
-#ifdef CONFIG_SMP
-	.irq_set_affinity	= ir_ioapic_set_affinity,
-#endif
-#endif
-	.irq_retrigger		= ioapic_retrigger_irq,
-};
-
 static inline void init_IO_APIC_traps(void)
 {
 	struct irq_cfg *cfg;
@@ -2944,27 +3008,26 @@
 
 late_initcall(io_apic_bug_finalize);
 
-static void resume_ioapic_id(int ioapic_id)
+static void resume_ioapic_id(int ioapic_idx)
 {
 	unsigned long flags;
 	union IO_APIC_reg_00 reg_00;
 
-
 	raw_spin_lock_irqsave(&ioapic_lock, flags);
-	reg_00.raw = io_apic_read(ioapic_id, 0);
-	if (reg_00.bits.ID != mpc_ioapic_id(ioapic_id)) {
-		reg_00.bits.ID = mpc_ioapic_id(ioapic_id);
-		io_apic_write(ioapic_id, 0, reg_00.raw);
+	reg_00.raw = io_apic_read(ioapic_idx, 0);
+	if (reg_00.bits.ID != mpc_ioapic_id(ioapic_idx)) {
+		reg_00.bits.ID = mpc_ioapic_id(ioapic_idx);
+		io_apic_write(ioapic_idx, 0, reg_00.raw);
 	}
 	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
 static void ioapic_resume(void)
 {
-	int ioapic_id;
+	int ioapic_idx;
 
-	for (ioapic_id = nr_ioapics - 1; ioapic_id >= 0; ioapic_id--)
-		resume_ioapic_id(ioapic_id);
+	for (ioapic_idx = nr_ioapics - 1; ioapic_idx >= 0; ioapic_idx--)
+		resume_ioapic_id(ioapic_idx);
 
 	restore_ioapic_entries();
 }
@@ -3144,45 +3207,6 @@
 
 	return 0;
 }
-#ifdef CONFIG_INTR_REMAP
-/*
- * Migrate the MSI irq to another cpumask. This migration is
- * done in the process context using interrupt-remapping hardware.
- */
-static int
-ir_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
-		    bool force)
-{
-	struct irq_cfg *cfg = data->chip_data;
-	unsigned int dest, irq = data->irq;
-	struct irte irte;
-
-	if (get_irte(irq, &irte))
-		return -1;
-
-	if (__ioapic_set_affinity(data, mask, &dest))
-		return -1;
-
-	irte.vector = cfg->vector;
-	irte.dest_id = IRTE_DEST(dest);
-
-	/*
-	 * atomically update the IRTE with the new destination and vector.
-	 */
-	modify_irte(irq, &irte);
-
-	/*
-	 * After this point, all the interrupts will start arriving
-	 * at the new destination. So, time to cleanup the previous
-	 * vector allocation.
-	 */
-	if (cfg->move_in_progress)
-		send_cleanup_vector(cfg);
-
-	return 0;
-}
-
-#endif
 #endif /* CONFIG_SMP */
 
 /*
@@ -3200,19 +3224,6 @@
 	.irq_retrigger		= ioapic_retrigger_irq,
 };
 
-static struct irq_chip msi_ir_chip = {
-	.name			= "IR-PCI-MSI",
-	.irq_unmask		= unmask_msi_irq,
-	.irq_mask		= mask_msi_irq,
-#ifdef CONFIG_INTR_REMAP
-	.irq_ack		= ir_ack_apic_edge,
-#ifdef CONFIG_SMP
-	.irq_set_affinity	= ir_msi_set_affinity,
-#endif
-#endif
-	.irq_retrigger		= ioapic_retrigger_irq,
-};
-
 /*
  * Map the PCI dev to the corresponding remapping hardware unit
  * and allocate 'nvec' consecutive interrupt-remapping table entries
@@ -3255,7 +3266,7 @@
 
 	if (irq_remapped(irq_get_chip_data(irq))) {
 		irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
-		chip = &msi_ir_chip;
+		irq_remap_modify_chip_defaults(chip);
 	}
 
 	irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
@@ -3328,7 +3339,7 @@
 	destroy_irq(irq);
 }
 
-#if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP)
+#ifdef CONFIG_DMAR_TABLE
 #ifdef CONFIG_SMP
 static int
 dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
@@ -3409,19 +3420,6 @@
 
 #endif /* CONFIG_SMP */
 
-static struct irq_chip ir_hpet_msi_type = {
-	.name			= "IR-HPET_MSI",
-	.irq_unmask		= hpet_msi_unmask,
-	.irq_mask		= hpet_msi_mask,
-#ifdef CONFIG_INTR_REMAP
-	.irq_ack		= ir_ack_apic_edge,
-#ifdef CONFIG_SMP
-	.irq_set_affinity	= ir_msi_set_affinity,
-#endif
-#endif
-	.irq_retrigger		= ioapic_retrigger_irq,
-};
-
 static struct irq_chip hpet_msi_type = {
 	.name = "HPET_MSI",
 	.irq_unmask = hpet_msi_unmask,
@@ -3458,7 +3456,7 @@
 	hpet_msi_write(irq_get_handler_data(irq), &msg);
 	irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
 	if (irq_remapped(irq_get_chip_data(irq)))
-		chip = &ir_hpet_msi_type;
+		irq_remap_modify_chip_defaults(chip);
 
 	irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
 	return 0;
@@ -3566,26 +3564,25 @@
 		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);
+		setup_ioapic_irq(irq, cfg, attr);
 	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;
+	unsigned int ioapic_idx = attr->ioapic, pin = attr->ioapic_pin;
 	int ret;
 
 	/* Avoid redundant programming */
-	if (test_bit(pin, ioapics[id].pin_programmed)) {
+	if (test_bit(pin, ioapics[ioapic_idx].pin_programmed)) {
 		pr_debug("Pin %d-%d already programmed\n",
-			 mpc_ioapic_id(id), pin);
+			 mpc_ioapic_id(ioapic_idx), pin);
 		return 0;
 	}
 	ret = io_apic_setup_irq_pin(irq, node, attr);
 	if (!ret)
-		set_bit(pin, ioapics[id].pin_programmed);
+		set_bit(pin, ioapics[ioapic_idx].pin_programmed);
 	return ret;
 }
 
@@ -3621,7 +3618,6 @@
 	return nr_irqs_gsi;
 }
 
-#ifdef CONFIG_SPARSE_IRQ
 int __init arch_probe_nr_irqs(void)
 {
 	int nr;
@@ -3641,7 +3637,6 @@
 
 	return NR_IRQS_LEGACY;
 }
-#endif
 
 int io_apic_set_pci_routing(struct device *dev, int irq,
 			    struct io_apic_irq_attr *irq_attr)
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/apic/probe_32.c linux-libre-3.2-gnu/arch/x86/kernel/apic/probe_32.c
--- linux-libre-3.1-gnu/arch/x86/kernel/apic/probe_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/apic/probe_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -200,14 +200,8 @@
 	 * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
 	 */
 
-	if (!cmdline_apic && apic == &apic_default) {
-		struct apic *bigsmp = generic_bigsmp_probe();
-		if (bigsmp) {
-			apic = bigsmp;
-			printk(KERN_INFO "Overriding APIC driver with %s\n",
-			       apic->name);
-		}
-	}
+	if (!cmdline_apic && apic == &apic_default)
+		generic_bigsmp_probe();
 #endif
 
 	if (apic->setup_apic_routing)
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/apic/x2apic_uv_x.c linux-libre-3.2-gnu/arch/x86/kernel/apic/x2apic_uv_x.c
--- linux-libre-3.1-gnu/arch/x86/kernel/apic/x2apic_uv_x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/apic/x2apic_uv_x.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,6 +93,8 @@
 
 	if (node_id.s.part_number == UV2_HUB_PART_NUMBER)
 		uv_min_hub_revision_id += UV2_HUB_REVISION_BASE - 1;
+	if (node_id.s.part_number == UV2_HUB_PART_NUMBER_X)
+		uv_min_hub_revision_id += UV2_HUB_REVISION_BASE - 1;
 
 	uv_hub_info->hub_revision = uv_min_hub_revision_id;
 	pnode = (node_id.s.node_id >> 1) & ((1 << m_n_config.s.n_skt) - 1);
@@ -672,18 +674,11 @@
 /*
  * When NMI is received, print a stack trace.
  */
-int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data)
+int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
 {
 	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;
-
 	/*
 	 * Each blade has an MMR that indicates when an NMI has been sent
 	 * to cpus on the blade. If an NMI is detected, atomically
@@ -704,7 +699,7 @@
 	}
 
 	if (likely(__get_cpu_var(cpu_last_nmi_count) == uv_blade_info[bid].nmi_count))
-		return NOTIFY_DONE;
+		return NMI_DONE;
 
 	__get_cpu_var(cpu_last_nmi_count) = uv_blade_info[bid].nmi_count;
 
@@ -717,17 +712,12 @@
 	dump_stack();
 	spin_unlock(&uv_nmi_lock);
 
-	return NOTIFY_STOP;
+	return NMI_HANDLED;
 }
 
-static struct notifier_block uv_dump_stack_nmi_nb = {
-	.notifier_call	= uv_handle_nmi,
-	.priority = NMI_LOCAL_LOW_PRIOR - 1,
-};
-
 void uv_register_nmi_notifier(void)
 {
-	if (register_die_notifier(&uv_dump_stack_nmi_nb))
+	if (register_nmi_handler(NMI_UNKNOWN, uv_handle_nmi, 0, "uv"))
 		printk(KERN_WARNING "UV NMI handler failed to register\n");
 }
 
@@ -832,6 +822,10 @@
 		uv_cpu_hub_info(cpu)->apic_pnode_shift = uvh_apicid.s.pnode_shift;
 		uv_cpu_hub_info(cpu)->hub_revision = uv_hub_info->hub_revision;
 
+		uv_cpu_hub_info(cpu)->m_shift = 64 - m_val;
+		uv_cpu_hub_info(cpu)->n_lshift = is_uv2_1_hub() ?
+				(m_val == 40 ? 40 : 39) : m_val;
+
 		pnode = uv_apicid_to_pnode(apicid);
 		blade = boot_pnode_to_blade(pnode);
 		lcpu = uv_blade_info[blade].nr_possible_cpus;
@@ -862,8 +856,7 @@
 		if (uv_node_to_blade[nid] >= 0)
 			continue;
 		paddr = node_start_pfn(nid) << PAGE_SHIFT;
-		paddr = uv_soc_phys_ram_to_gpa(paddr);
-		pnode = (paddr >> m_val) & pnode_mask;
+		pnode = uv_gpa_to_pnode(uv_soc_phys_ram_to_gpa(paddr));
 		blade = boot_pnode_to_blade(pnode);
 		uv_node_to_blade[nid] = blade;
 	}
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/apm_32.c linux-libre-3.2-gnu/arch/x86/kernel/apm_32.c
--- linux-libre-3.1-gnu/arch/x86/kernel/apm_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/apm_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -249,8 +249,6 @@
 #define	APM_MINOR_DEV	134
 
 /*
- * See Documentation/Config.help for the configuration options.
- *
  * Various options can be changed at boot time as follows:
  * (We allow underscores for compatibility with the modules code)
  *	apm=on/off			enable/disable APM
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/amd.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/amd.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/amd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/amd.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,7 @@
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
+#include <linux/elf.h>
 #include <linux/mm.h>
 
 #include <linux/io.h>
@@ -410,6 +412,34 @@
 #endif
 }
 
+static void __cpuinit bsp_init_amd(struct cpuinfo_x86 *c)
+{
+	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
+
+		if (c->x86 > 0x10 ||
+		    (c->x86 == 0x10 && c->x86_model >= 0x2)) {
+			u64 val;
+
+			rdmsrl(MSR_K7_HWCR, val);
+			if (!(val & BIT(24)))
+				printk(KERN_WARNING FW_BUG "TSC doesn't count "
+					"with P0 frequency!\n");
+		}
+	}
+
+	if (c->x86 == 0x15) {
+		unsigned long upperbit;
+		u32 cpuid, assoc;
+
+		cpuid	 = cpuid_edx(0x80000005);
+		assoc	 = cpuid >> 16 & 0xff;
+		upperbit = ((cpuid >> 24) << 10) / assoc;
+
+		va_align.mask	  = (upperbit - 1) & PAGE_MASK;
+		va_align.flags    = ALIGN_VA_32 | ALIGN_VA_64;
+	}
+}
+
 static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
 {
 	early_init_amd_mc(c);
@@ -441,27 +471,12 @@
 			set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
 	}
 #endif
-
-	/* We need to do the following only once */
-	if (c != &boot_cpu_data)
-		return;
-
-	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
-
-		if (c->x86 > 0x10 ||
-		    (c->x86 == 0x10 && c->x86_model >= 0x2)) {
-			u64 val;
-
-			rdmsrl(MSR_K7_HWCR, val);
-			if (!(val & BIT(24)))
-				printk(KERN_WARNING FW_BUG "TSC doesn't count "
-					"with P0 frequency!\n");
-		}
-	}
 }
 
 static void __cpuinit init_amd(struct cpuinfo_x86 *c)
 {
+	u32 dummy;
+
 #ifdef CONFIG_SMP
 	unsigned long long value;
 
@@ -640,6 +655,8 @@
 			checking_wrmsrl(MSR_AMD64_MCx_MASK(4), mask);
 		}
 	}
+
+	rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
 }
 
 #ifdef CONFIG_X86_32
@@ -679,6 +696,7 @@
 	.c_size_cache	= amd_size_cache,
 #endif
 	.c_early_init   = early_init_amd,
+	.c_bsp_init	= bsp_init_amd,
 	.c_init		= init_amd,
 	.c_x86_vendor	= X86_VENDOR_AMD,
 };
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/common.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/common.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <asm/stackprotector.h>
 #include <asm/perf_event.h>
 #include <asm/mmu_context.h>
+#include <asm/archrandom.h>
 #include <asm/hypervisor.h>
 #include <asm/processor.h>
 #include <asm/sections.h>
@@ -681,6 +682,9 @@
 	filter_cpuid_features(c, false);
 
 	setup_smep(c);
+
+	if (this_cpu->c_bsp_init)
+		this_cpu->c_bsp_init(c);
 }
 
 void __init early_cpu_init(void)
@@ -857,6 +861,7 @@
 #endif
 
 	init_hypervisor(c);
+	x86_init_rdrand(c);
 
 	/*
 	 * Clear/Set all flags overriden by options, need do it
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/cpu.h linux-libre-3.2-gnu/arch/x86/kernel/cpu/cpu.h
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/cpu.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/cpu.h	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 	struct		cpu_model_info c_models[4];
 
 	void            (*c_early_init)(struct cpuinfo_x86 *);
+	void		(*c_bsp_init)(struct cpuinfo_x86 *);
 	void		(*c_init)(struct cpuinfo_x86 *);
 	void		(*c_identify)(struct cpuinfo_x86 *);
 	unsigned int	(*c_size_cache)(struct cpuinfo_x86 *, unsigned int);
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/intel.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/intel.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/intel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/intel.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,15 @@
 		(c->x86 == 0x6 && c->x86_model >= 0x0e))
 		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
 
+	if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64)) {
+		unsigned lower_word;
+
+		wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+		/* Required by the SDM */
+		sync_core();
+		rdmsr(MSR_IA32_UCODE_REV, lower_word, c->microcode);
+	}
+
 	/*
 	 * Atom erratum AAE44/AAF40/AAG38/AAH41:
 	 *
@@ -55,17 +64,10 @@
 	 * need the microcode to have already been loaded... so if it is
 	 * not, recommend a BIOS update and disable large pages.
 	 */
-	if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2) {
-		u32 ucode, junk;
-
-		wrmsr(MSR_IA32_UCODE_REV, 0, 0);
-		sync_core();
-		rdmsr(MSR_IA32_UCODE_REV, junk, ucode);
-
-		if (ucode < 0x20e) {
-			printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n");
-			clear_cpu_cap(c, X86_FEATURE_PSE);
-		}
+	if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2 &&
+	    c->microcode < 0x20e) {
+		printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n");
+		clear_cpu_cap(c, X86_FEATURE_PSE);
 	}
 
 #ifdef CONFIG_X86_64
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c	2012-01-04 18:55:44.000000000 -0500
@@ -151,28 +151,17 @@
 	u32 full;
 };
 
-struct amd_l3_cache {
-	struct	 amd_northbridge *nb;
-	unsigned indices;
-	u8	 subcaches[4];
-};
-
-struct _cpuid4_info {
+struct _cpuid4_info_regs {
 	union _cpuid4_leaf_eax eax;
 	union _cpuid4_leaf_ebx ebx;
 	union _cpuid4_leaf_ecx ecx;
 	unsigned long size;
-	struct amd_l3_cache *l3;
-	DECLARE_BITMAP(shared_cpu_map, NR_CPUS);
+	struct amd_northbridge *nb;
 };
 
-/* subset of above _cpuid4_info w/o shared_cpu_map */
-struct _cpuid4_info_regs {
-	union _cpuid4_leaf_eax eax;
-	union _cpuid4_leaf_ebx ebx;
-	union _cpuid4_leaf_ecx ecx;
-	unsigned long size;
-	struct amd_l3_cache *l3;
+struct _cpuid4_info {
+	struct _cpuid4_info_regs base;
+	DECLARE_BITMAP(shared_cpu_map, NR_CPUS);
 };
 
 unsigned short			num_cache_leaves;
@@ -314,16 +303,23 @@
 /*
  * L3 cache descriptors
  */
-static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
+static void __cpuinit amd_calc_l3_indices(struct amd_northbridge *nb)
 {
+	struct amd_l3_cache *l3 = &nb->l3_cache;
 	unsigned int sc0, sc1, sc2, sc3;
 	u32 val = 0;
 
-	pci_read_config_dword(l3->nb->misc, 0x1C4, &val);
+	pci_read_config_dword(nb->misc, 0x1C4, &val);
 
 	/* calculate subcache sizes */
 	l3->subcaches[0] = sc0 = !(val & BIT(0));
 	l3->subcaches[1] = sc1 = !(val & BIT(4));
+
+	if (boot_cpu_data.x86 == 0x15) {
+		l3->subcaches[0] = sc0 += !(val & BIT(1));
+		l3->subcaches[1] = sc1 += !(val & BIT(5));
+	}
+
 	l3->subcaches[2] = sc2 = !(val & BIT(8))  + !(val & BIT(9));
 	l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13));
 
@@ -333,33 +329,16 @@
 static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf,
 					int index)
 {
-	static struct amd_l3_cache *__cpuinitdata l3_caches;
 	int node;
 
 	/* only for L3, and not in virtualized environments */
-	if (index < 3 || amd_nb_num() == 0)
+	if (index < 3)
 		return;
 
-	/*
-	 * Strictly speaking, the amount in @size below is leaked since it is
-	 * never freed but this is done only on shutdown so it doesn't matter.
-	 */
-	if (!l3_caches) {
-		int size = amd_nb_num() * sizeof(struct amd_l3_cache);
-
-		l3_caches = kzalloc(size, GFP_ATOMIC);
-		if (!l3_caches)
-			return;
-	}
-
 	node = amd_get_nb_id(smp_processor_id());
-
-	if (!l3_caches[node].nb) {
-		l3_caches[node].nb = node_to_amd_nb(node);
-		amd_calc_l3_indices(&l3_caches[node]);
-	}
-
-	this_leaf->l3 = &l3_caches[node];
+	this_leaf->nb = node_to_amd_nb(node);
+	if (this_leaf->nb && !this_leaf->nb->l3_cache.indices)
+		amd_calc_l3_indices(this_leaf->nb);
 }
 
 /*
@@ -369,11 +348,11 @@
  *
  * @returns: the disabled index if used or negative value if slot free.
  */
-int amd_get_l3_disable_slot(struct amd_l3_cache *l3, unsigned slot)
+int amd_get_l3_disable_slot(struct amd_northbridge *nb, unsigned slot)
 {
 	unsigned int reg = 0;
 
-	pci_read_config_dword(l3->nb->misc, 0x1BC + slot * 4, &reg);
+	pci_read_config_dword(nb->misc, 0x1BC + slot * 4, &reg);
 
 	/* check whether this slot is activated already */
 	if (reg & (3UL << 30))
@@ -387,11 +366,10 @@
 {
 	int index;
 
-	if (!this_leaf->l3 ||
-	    !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
+	if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
 		return -EINVAL;
 
-	index = amd_get_l3_disable_slot(this_leaf->l3, slot);
+	index = amd_get_l3_disable_slot(this_leaf->base.nb, slot);
 	if (index >= 0)
 		return sprintf(buf, "%d\n", index);
 
@@ -408,7 +386,7 @@
 SHOW_CACHE_DISABLE(0)
 SHOW_CACHE_DISABLE(1)
 
-static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
+static void amd_l3_disable_index(struct amd_northbridge *nb, int cpu,
 				 unsigned slot, unsigned long idx)
 {
 	int i;
@@ -421,10 +399,10 @@
 	for (i = 0; i < 4; i++) {
 		u32 reg = idx | (i << 20);
 
-		if (!l3->subcaches[i])
+		if (!nb->l3_cache.subcaches[i])
 			continue;
 
-		pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg);
+		pci_write_config_dword(nb->misc, 0x1BC + slot * 4, reg);
 
 		/*
 		 * We need to WBINVD on a core on the node containing the L3
@@ -434,7 +412,7 @@
 		wbinvd_on_cpu(cpu);
 
 		reg |= BIT(31);
-		pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg);
+		pci_write_config_dword(nb->misc, 0x1BC + slot * 4, reg);
 	}
 }
 
@@ -448,24 +426,24 @@
  *
  * @return: 0 on success, error status on failure
  */
-int amd_set_l3_disable_slot(struct amd_l3_cache *l3, int cpu, unsigned slot,
+int amd_set_l3_disable_slot(struct amd_northbridge *nb, int cpu, unsigned slot,
 			    unsigned long index)
 {
 	int ret = 0;
 
 	/*  check if @slot is already used or the index is already disabled */
-	ret = amd_get_l3_disable_slot(l3, slot);
+	ret = amd_get_l3_disable_slot(nb, slot);
 	if (ret >= 0)
 		return -EINVAL;
 
-	if (index > l3->indices)
+	if (index > nb->l3_cache.indices)
 		return -EINVAL;
 
 	/* check whether the other slot has disabled the same index already */
-	if (index == amd_get_l3_disable_slot(l3, !slot))
+	if (index == amd_get_l3_disable_slot(nb, !slot))
 		return -EINVAL;
 
-	amd_l3_disable_index(l3, cpu, slot, index);
+	amd_l3_disable_index(nb, cpu, slot, index);
 
 	return 0;
 }
@@ -480,8 +458,7 @@
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	if (!this_leaf->l3 ||
-	    !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
+	if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
 		return -EINVAL;
 
 	cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
@@ -489,7 +466,7 @@
 	if (strict_strtoul(buf, 10, &val) < 0)
 		return -EINVAL;
 
-	err = amd_set_l3_disable_slot(this_leaf->l3, cpu, slot, val);
+	err = amd_set_l3_disable_slot(this_leaf->base.nb, cpu, slot, val);
 	if (err) {
 		if (err == -EEXIST)
 			printk(KERN_WARNING "L3 disable slot %d in use!\n",
@@ -518,7 +495,7 @@
 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))
+	if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
 		return -EINVAL;
 
 	return sprintf(buf, "%x\n", amd_get_subcaches(cpu));
@@ -533,7 +510,7 @@
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+	if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
 		return -EINVAL;
 
 	if (strict_strtoul(buf, 16, &val) < 0)
@@ -769,7 +746,7 @@
 		return;
 	}
 	this_leaf = CPUID4_INFO_IDX(cpu, index);
-	num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
+	num_threads_sharing = 1 + this_leaf->base.eax.split.num_threads_sharing;
 
 	if (num_threads_sharing == 1)
 		cpumask_set_cpu(cpu, to_cpumask(this_leaf->shared_cpu_map));
@@ -820,29 +797,19 @@
 	for (i = 0; i < num_cache_leaves; i++)
 		cache_remove_shared_cpu_map(cpu, i);
 
-	kfree(per_cpu(ici_cpuid4_info, cpu)->l3);
 	kfree(per_cpu(ici_cpuid4_info, cpu));
 	per_cpu(ici_cpuid4_info, cpu) = NULL;
 }
 
-static int
-__cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
-{
-	struct _cpuid4_info_regs *leaf_regs =
-		(struct _cpuid4_info_regs *)this_leaf;
-
-	return cpuid4_cache_lookup_regs(index, leaf_regs);
-}
-
 static void __cpuinit get_cpu_leaves(void *_retval)
 {
 	int j, *retval = _retval, cpu = smp_processor_id();
 
 	/* Do cpuid and store the results */
 	for (j = 0; j < num_cache_leaves; j++) {
-		struct _cpuid4_info *this_leaf;
-		this_leaf = CPUID4_INFO_IDX(cpu, j);
-		*retval = cpuid4_cache_lookup(j, this_leaf);
+		struct _cpuid4_info *this_leaf = CPUID4_INFO_IDX(cpu, j);
+
+		*retval = cpuid4_cache_lookup_regs(j, &this_leaf->base);
 		if (unlikely(*retval < 0)) {
 			int i;
 
@@ -900,16 +867,16 @@
 	return sprintf(buf, "%lu\n", (unsigned long)this_leaf->object + val); \
 }
 
-show_one_plus(level, eax.split.level, 0);
-show_one_plus(coherency_line_size, ebx.split.coherency_line_size, 1);
-show_one_plus(physical_line_partition, ebx.split.physical_line_partition, 1);
-show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1);
-show_one_plus(number_of_sets, ecx.split.number_of_sets, 1);
+show_one_plus(level, base.eax.split.level, 0);
+show_one_plus(coherency_line_size, base.ebx.split.coherency_line_size, 1);
+show_one_plus(physical_line_partition, base.ebx.split.physical_line_partition, 1);
+show_one_plus(ways_of_associativity, base.ebx.split.ways_of_associativity, 1);
+show_one_plus(number_of_sets, base.ecx.split.number_of_sets, 1);
 
 static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf,
 			 unsigned int cpu)
 {
-	return sprintf(buf, "%luK\n", this_leaf->size / 1024);
+	return sprintf(buf, "%luK\n", this_leaf->base.size / 1024);
 }
 
 static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf,
@@ -946,7 +913,7 @@
 static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf,
 			 unsigned int cpu)
 {
-	switch (this_leaf->eax.split.type) {
+	switch (this_leaf->base.eax.split.type) {
 	case CACHE_TYPE_DATA:
 		return sprintf(buf, "Data\n");
 	case CACHE_TYPE_INST:
@@ -1135,7 +1102,7 @@
 
 		ktype_cache.default_attrs = default_attrs;
 #ifdef CONFIG_AMD_NB
-		if (this_leaf->l3)
+		if (this_leaf->base.nb)
 			ktype_cache.default_attrs = amd_l3_attrs();
 #endif
 		retval = kobject_init_and_add(&(this_object->kobj),
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/Makefile linux-libre-3.2-gnu/arch/x86/kernel/cpu/Makefile
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 obj-y			:= intel_cacheinfo.o scattered.o topology.o
 obj-y			+= proc.o capflags.o powerflags.o common.o
 obj-y			+= vmware.o hypervisor.o sched.o mshyperv.o
+obj-y			+= rdrand.o
 
 obj-$(CONFIG_X86_32)	+= bugs.o
 obj-$(CONFIG_X86_64)	+= bugs_64.o
@@ -28,10 +29,15 @@
 
 obj-$(CONFIG_PERF_EVENTS)		+= perf_event.o
 
+ifdef CONFIG_PERF_EVENTS
+obj-$(CONFIG_CPU_SUP_AMD)		+= perf_event_amd.o
+obj-$(CONFIG_CPU_SUP_INTEL)		+= perf_event_p6.o perf_event_p4.o perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o
+endif
+
 obj-$(CONFIG_X86_MCE)			+= mcheck/
 obj-$(CONFIG_MTRR)			+= mtrr/
 
-obj-$(CONFIG_X86_LOCAL_APIC)		+= perfctr-watchdog.o
+obj-$(CONFIG_X86_LOCAL_APIC)		+= perfctr-watchdog.o perf_event_amd_ibs.o
 
 quiet_cmd_mkcapflags = MKCAP   $@
       cmd_mkcapflags = $(PERL) $(srctree)/$(src)/mkcapflags.pl $< $@
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/mcheck/mce-apei.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/mcheck/mce-apei.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/mcheck/mce-apei.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/mcheck/mce-apei.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/acpi.h>
 #include <linux/cper.h>
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/mcheck/mce.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/mcheck/mce.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/mcheck/mce.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/mcheck/mce.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,8 +36,8 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/debugfs.h>
-#include <linux/edac_mce.h>
 #include <linux/irq_work.h>
+#include <linux/export.h>
 
 #include <asm/processor.h>
 #include <asm/mce.h>
@@ -144,23 +144,20 @@
 void mce_log(struct mce *mce)
 {
 	unsigned next, entry;
+	int ret = 0;
 
 	/* Emit the trace record: */
 	trace_mce_record(mce);
 
+	ret = atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, mce);
+	if (ret == NOTIFY_STOP)
+		return;
+
 	mce->finished = 0;
 	wmb();
 	for (;;) {
 		entry = rcu_dereference_check_mce(mcelog.next);
 		for (;;) {
-			/*
-			 * If edac_mce is enabled, it will check the error type
-			 * and will process it, if it is a known error.
-			 * Otherwise, the error will be sent through mcelog
-			 * interface
-			 */
-			if (edac_mce_parse(mce))
-				return;
 
 			/*
 			 * When the buffer fills up discard new entries.
@@ -217,8 +214,13 @@
 		pr_cont("MISC %llx ", m->misc);
 
 	pr_cont("\n");
-	pr_emerg(HW_ERR "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n",
-		m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid);
+	/*
+	 * Note this output is parsed by external tools and old fields
+	 * should not be changed.
+	 */
+	pr_emerg(HW_ERR "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x microcode %x\n",
+		m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid,
+		cpu_data(m->extcpu).microcode);
 
 	/*
 	 * Print out human-readable details about the MCE error,
@@ -551,10 +553,8 @@
 		 * Don't get the IP here because it's unlikely to
 		 * have anything to do with the actual error location.
 		 */
-		if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce) {
+		if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce)
 			mce_log(&m);
-			atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, &m);
-		}
 
 		/*
 		 * Clear state for this bank.
@@ -908,9 +908,6 @@
 
 	percpu_inc(mce_exception_count);
 
-	if (notify_die(DIE_NMI, "machine check", regs, error_code,
-			   18, SIGKILL) == NOTIFY_STOP)
-		goto out;
 	if (!banks)
 		goto out;
 
@@ -1140,6 +1137,15 @@
 	add_timer_on(t, smp_processor_id());
 }
 
+/* Must not be called in IRQ context where del_timer_sync() can deadlock */
+static void mce_timer_delete_all(void)
+{
+	int cpu;
+
+	for_each_online_cpu(cpu)
+		del_timer_sync(&per_cpu(mce_timer, cpu));
+}
+
 static void mce_do_trigger(struct work_struct *work)
 {
 	call_usermodehelper(mce_helper, mce_helper_argv, NULL, UMH_NO_WAIT);
@@ -1628,16 +1634,35 @@
 	}
 }
 
-/* Modified in mce-inject.c, so not static or const */
-struct file_operations mce_chrdev_ops = {
+static ssize_t (*mce_write)(struct file *filp, const char __user *ubuf,
+			    size_t usize, loff_t *off);
+
+void register_mce_write_callback(ssize_t (*fn)(struct file *filp,
+			     const char __user *ubuf,
+			     size_t usize, loff_t *off))
+{
+	mce_write = fn;
+}
+EXPORT_SYMBOL_GPL(register_mce_write_callback);
+
+ssize_t mce_chrdev_write(struct file *filp, const char __user *ubuf,
+			 size_t usize, loff_t *off)
+{
+	if (mce_write)
+		return mce_write(filp, ubuf, usize, off);
+	else
+		return -EINVAL;
+}
+
+static const struct file_operations mce_chrdev_ops = {
 	.open			= mce_chrdev_open,
 	.release		= mce_chrdev_release,
 	.read			= mce_chrdev_read,
+	.write			= mce_chrdev_write,
 	.poll			= mce_chrdev_poll,
 	.unlocked_ioctl		= mce_chrdev_ioctl,
 	.llseek			= no_llseek,
 };
-EXPORT_SYMBOL_GPL(mce_chrdev_ops);
 
 static struct miscdevice mce_chrdev_device = {
 	MISC_MCELOG_MINOR,
@@ -1750,7 +1775,6 @@
 
 static void mce_cpu_restart(void *data)
 {
-	del_timer_sync(&__get_cpu_var(mce_timer));
 	if (!mce_available(__this_cpu_ptr(&cpu_info)))
 		return;
 	__mcheck_cpu_init_generic();
@@ -1760,16 +1784,15 @@
 /* Reinit MCEs after user configuration changes */
 static void mce_restart(void)
 {
+	mce_timer_delete_all();
 	on_each_cpu(mce_cpu_restart, NULL, 1);
 }
 
 /* Toggle features for corrected errors */
-static void mce_disable_ce(void *all)
+static void mce_disable_cmci(void *data)
 {
 	if (!mce_available(__this_cpu_ptr(&cpu_info)))
 		return;
-	if (all)
-		del_timer_sync(&__get_cpu_var(mce_timer));
 	cmci_clear();
 }
 
@@ -1852,7 +1875,8 @@
 	if (mce_ignore_ce ^ !!new) {
 		if (new) {
 			/* disable ce features */
-			on_each_cpu(mce_disable_ce, (void *)1, 1);
+			mce_timer_delete_all();
+			on_each_cpu(mce_disable_cmci, NULL, 1);
 			mce_ignore_ce = 1;
 		} else {
 			/* enable ce features */
@@ -1875,7 +1899,7 @@
 	if (mce_cmci_disabled ^ !!new) {
 		if (new) {
 			/* disable cmci */
-			on_each_cpu(mce_disable_ce, NULL, 1);
+			on_each_cpu(mce_disable_cmci, NULL, 1);
 			mce_cmci_disabled = 1;
 		} else {
 			/* enable cmci */
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/mcheck/mce-inject.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/mcheck/mce-inject.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/mcheck/mce-inject.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/mcheck/mce-inject.c	2012-01-04 18:55:44.000000000 -0500
@@ -78,27 +78,20 @@
 
 static cpumask_var_t mce_inject_cpumask;
 
-static int mce_raise_notify(struct notifier_block *self,
-			    unsigned long val, void *data)
+static int mce_raise_notify(unsigned int cmd, struct pt_regs *regs)
 {
-	struct die_args *args = (struct die_args *)data;
 	int cpu = smp_processor_id();
 	struct mce *m = &__get_cpu_var(injectm);
-	if (val != DIE_NMI || !cpumask_test_cpu(cpu, mce_inject_cpumask))
-		return NOTIFY_DONE;
+	if (!cpumask_test_cpu(cpu, mce_inject_cpumask))
+		return NMI_DONE;
 	cpumask_clear_cpu(cpu, mce_inject_cpumask);
 	if (m->inject_flags & MCJ_EXCEPTION)
-		raise_exception(m, args->regs);
+		raise_exception(m, regs);
 	else if (m->status)
 		raise_poll(m);
-	return NOTIFY_STOP;
+	return NMI_HANDLED;
 }
 
-static struct notifier_block mce_raise_nb = {
-	.notifier_call = mce_raise_notify,
-	.priority = NMI_LOCAL_NORMAL_PRIOR,
-};
-
 /* Inject mce on current CPU */
 static int raise_local(void)
 {
@@ -215,8 +208,9 @@
 	if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL))
 		return -ENOMEM;
 	printk(KERN_INFO "Machine check injector initialized\n");
-	mce_chrdev_ops.write = mce_write;
-	register_die_notifier(&mce_raise_nb);
+	register_mce_write_callback(mce_write);
+	register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0,
+				"mce_notify");
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,7 @@
  * cmci_discover_lock protects against parallel discovery attempts
  * which could race against each other.
  */
-static DEFINE_SPINLOCK(cmci_discover_lock);
+static DEFINE_RAW_SPINLOCK(cmci_discover_lock);
 
 #define CMCI_THRESHOLD 1
 
@@ -85,7 +85,7 @@
 	int hdr = 0;
 	int i;
 
-	spin_lock_irqsave(&cmci_discover_lock, flags);
+	raw_spin_lock_irqsave(&cmci_discover_lock, flags);
 	for (i = 0; i < banks; i++) {
 		u64 val;
 
@@ -116,7 +116,7 @@
 			WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks)));
 		}
 	}
-	spin_unlock_irqrestore(&cmci_discover_lock, flags);
+	raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
 	if (hdr)
 		printk(KERN_CONT "\n");
 }
@@ -150,7 +150,7 @@
 
 	if (!cmci_supported(&banks))
 		return;
-	spin_lock_irqsave(&cmci_discover_lock, flags);
+	raw_spin_lock_irqsave(&cmci_discover_lock, flags);
 	for (i = 0; i < banks; i++) {
 		if (!test_bit(i, __get_cpu_var(mce_banks_owned)))
 			continue;
@@ -160,7 +160,7 @@
 		wrmsrl(MSR_IA32_MCx_CTL2(i), val);
 		__clear_bit(i, __get_cpu_var(mce_banks_owned));
 	}
-	spin_unlock_irqrestore(&cmci_discover_lock, flags);
+	raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
 }
 
 /*
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/percpu.h>
+#include <linux/export.h>
 #include <linux/sysdev.h>
 #include <linux/types.h>
 #include <linux/init.h>
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/mshyperv.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/mshyperv.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/mshyperv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/mshyperv.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,8 @@
  */
 
 #include <linux/types.h>
+#include <linux/time.h>
+#include <linux/clocksource.h>
 #include <linux/module.h>
 #include <asm/processor.h>
 #include <asm/hypervisor.h>
@@ -36,6 +38,25 @@
 		!memcmp("Microsoft Hv", hyp_signature, 12);
 }
 
+static cycle_t read_hv_clock(struct clocksource *arg)
+{
+	cycle_t current_tick;
+	/*
+	 * Read the partition counter to get the current tick count. This count
+	 * is set to 0 when the partition is created and is incremented in
+	 * 100 nanosecond units.
+	 */
+	rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
+	return current_tick;
+}
+
+static struct clocksource hyperv_cs = {
+	.name		= "hyperv_clocksource",
+	.rating		= 400, /* use this when running on Hyperv*/
+	.read		= read_hv_clock,
+	.mask		= CLOCKSOURCE_MASK(64),
+};
+
 static void __init ms_hyperv_init_platform(void)
 {
 	/*
@@ -46,6 +67,8 @@
 
 	printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n",
 	       ms_hyperv.features, ms_hyperv.hints);
+
+	clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100);
 }
 
 const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/mtrr/generic.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/mtrr/generic.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/mtrr/generic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/mtrr/generic.c	2012-01-04 18:55:44.000000000 -0500
@@ -547,6 +547,7 @@
 
 		if (tmp != mask_lo) {
 			printk(KERN_WARNING "mtrr: your BIOS has configured an incorrect mask, fixing it.\n");
+			add_taint(TAINT_FIRMWARE_WORKAROUND);
 			mask_lo = tmp;
 		}
 	}
@@ -693,6 +694,7 @@
 
 	/* Disable MTRRs, and set the default type to uncached */
 	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo & ~0xcff, deftype_hi);
+	wbinvd();
 }
 
 static void post_set(void) __releases(set_atomicity_lock)
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event_amd.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event_amd.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event_amd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event_amd.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,10 @@
-#ifdef CONFIG_CPU_SUP_AMD
+#include <linux/perf_event.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <asm/apicdef.h>
+
+#include "perf_event.h"
 
 static __initconst const u64 amd_hw_cache_event_ids
 				[PERF_COUNT_HW_CACHE_MAX]
@@ -132,6 +138,19 @@
 	if (ret)
 		return ret;
 
+	if (event->attr.exclude_host && event->attr.exclude_guest)
+		/*
+		 * When HO == GO == 1 the hardware treats that as GO == HO == 0
+		 * and will count in both modes. We don't want to count in that
+		 * case so we emulate no-counting by setting US = OS = 0.
+		 */
+		event->hw.config &= ~(ARCH_PERFMON_EVENTSEL_USR |
+				      ARCH_PERFMON_EVENTSEL_OS);
+	else if (event->attr.exclude_host)
+		event->hw.config |= AMD_PERFMON_EVENTSEL_GUESTONLY;
+	else if (event->attr.exclude_guest)
+		event->hw.config |= AMD_PERFMON_EVENTSEL_HOSTONLY;
+
 	if (event->attr.type != PERF_TYPE_RAW)
 		return 0;
 
@@ -350,7 +369,7 @@
 			continue;
 
 		if (nb->nb_id == nb_id) {
-			kfree(cpuc->amd_nb);
+			cpuc->kfree_on_online = cpuc->amd_nb;
 			cpuc->amd_nb = nb;
 			break;
 		}
@@ -392,7 +411,7 @@
 	.perfctr		= MSR_K7_PERFCTR0,
 	.event_map		= amd_pmu_event_map,
 	.max_events		= ARRAY_SIZE(amd_perfmon_event_map),
-	.num_counters		= 4,
+	.num_counters		= AMD64_NUM_COUNTERS,
 	.cntval_bits		= 48,
 	.cntval_mask		= (1ULL << 48) - 1,
 	.apic			= 1,
@@ -556,7 +575,7 @@
 	.perfctr		= MSR_F15H_PERF_CTR,
 	.event_map		= amd_pmu_event_map,
 	.max_events		= ARRAY_SIZE(amd_perfmon_event_map),
-	.num_counters		= 6,
+	.num_counters		= AMD64_NUM_COUNTERS_F15H,
 	.cntval_bits		= 48,
 	.cntval_mask		= (1ULL << 48) - 1,
 	.apic			= 1,
@@ -573,7 +592,7 @@
 #endif
 };
 
-static __init int amd_pmu_init(void)
+__init int amd_pmu_init(void)
 {
 	/* Performance-monitoring supported from K7 and later: */
 	if (boot_cpu_data.x86 < 6)
@@ -602,12 +621,3 @@
 
 	return 0;
 }
-
-#else /* CONFIG_CPU_SUP_AMD */
-
-static int amd_pmu_init(void)
-{
-	return 0;
-}
-
-#endif
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event_amd_ibs.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event_amd_ibs.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event_amd_ibs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event_amd_ibs.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,301 @@
+/*
+ * Performance events - AMD IBS
+ *
+ *  Copyright (C) 2011 Advanced Micro Devices, Inc., Robert Richter
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/perf_event.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include <asm/apic.h>
+
+static u32 ibs_caps;
+
+#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD)
+
+static struct pmu perf_ibs;
+
+static int perf_ibs_init(struct perf_event *event)
+{
+	if (perf_ibs.type != event->attr.type)
+		return -ENOENT;
+	return 0;
+}
+
+static int perf_ibs_add(struct perf_event *event, int flags)
+{
+	return 0;
+}
+
+static void perf_ibs_del(struct perf_event *event, int flags)
+{
+}
+
+static struct pmu perf_ibs = {
+	.event_init= perf_ibs_init,
+	.add= perf_ibs_add,
+	.del= perf_ibs_del,
+};
+
+static __init int perf_event_ibs_init(void)
+{
+	if (!ibs_caps)
+		return -ENODEV;	/* ibs not supported by the cpu */
+
+	perf_pmu_register(&perf_ibs, "ibs", -1);
+	printk(KERN_INFO "perf: AMD IBS detected (0x%08x)\n", ibs_caps);
+
+	return 0;
+}
+
+#else /* defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD) */
+
+static __init int perf_event_ibs_init(void) { return 0; }
+
+#endif
+
+/* IBS - apic initialization, for perf and oprofile */
+
+static __init u32 __get_ibs_caps(void)
+{
+	u32 caps;
+	unsigned int max_level;
+
+	if (!boot_cpu_has(X86_FEATURE_IBS))
+		return 0;
+
+	/* check IBS cpuid feature flags */
+	max_level = cpuid_eax(0x80000000);
+	if (max_level < IBS_CPUID_FEATURES)
+		return IBS_CAPS_DEFAULT;
+
+	caps = cpuid_eax(IBS_CPUID_FEATURES);
+	if (!(caps & IBS_CAPS_AVAIL))
+		/* cpuid flags not valid */
+		return IBS_CAPS_DEFAULT;
+
+	return caps;
+}
+
+u32 get_ibs_caps(void)
+{
+	return ibs_caps;
+}
+
+EXPORT_SYMBOL(get_ibs_caps);
+
+static inline int get_eilvt(int offset)
+{
+	return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1);
+}
+
+static inline int put_eilvt(int offset)
+{
+	return !setup_APIC_eilvt(offset, 0, 0, 1);
+}
+
+/*
+ * Check and reserve APIC extended interrupt LVT offset for IBS if available.
+ */
+static inline int ibs_eilvt_valid(void)
+{
+	int offset;
+	u64 val;
+	int valid = 0;
+
+	preempt_disable();
+
+	rdmsrl(MSR_AMD64_IBSCTL, val);
+	offset = val & IBSCTL_LVT_OFFSET_MASK;
+
+	if (!(val & IBSCTL_LVT_OFFSET_VALID)) {
+		pr_err(FW_BUG "cpu %d, invalid IBS interrupt offset %d (MSR%08X=0x%016llx)\n",
+		       smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
+		goto out;
+	}
+
+	if (!get_eilvt(offset)) {
+		pr_err(FW_BUG "cpu %d, IBS interrupt offset %d not available (MSR%08X=0x%016llx)\n",
+		       smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
+		goto out;
+	}
+
+	valid = 1;
+out:
+	preempt_enable();
+
+	return valid;
+}
+
+static int setup_ibs_ctl(int ibs_eilvt_off)
+{
+	struct pci_dev *cpu_cfg;
+	int nodes;
+	u32 value = 0;
+
+	nodes = 0;
+	cpu_cfg = NULL;
+	do {
+		cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD,
+					 PCI_DEVICE_ID_AMD_10H_NB_MISC,
+					 cpu_cfg);
+		if (!cpu_cfg)
+			break;
+		++nodes;
+		pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
+				       | IBSCTL_LVT_OFFSET_VALID);
+		pci_read_config_dword(cpu_cfg, IBSCTL, &value);
+		if (value != (ibs_eilvt_off | IBSCTL_LVT_OFFSET_VALID)) {
+			pci_dev_put(cpu_cfg);
+			printk(KERN_DEBUG "Failed to setup IBS LVT offset, "
+			       "IBSCTL = 0x%08x\n", value);
+			return -EINVAL;
+		}
+	} while (1);
+
+	if (!nodes) {
+		printk(KERN_DEBUG "No CPU node configured for IBS\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/*
+ * This runs only on the current cpu. We try to find an LVT offset and
+ * setup the local APIC. For this we must disable preemption. On
+ * success we initialize all nodes with this offset. This updates then
+ * the offset in the IBS_CTL per-node msr. The per-core APIC setup of
+ * the IBS interrupt vector is handled by perf_ibs_cpu_notifier that
+ * is using the new offset.
+ */
+static int force_ibs_eilvt_setup(void)
+{
+	int offset;
+	int ret;
+
+	preempt_disable();
+	/* find the next free available EILVT entry, skip offset 0 */
+	for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) {
+		if (get_eilvt(offset))
+			break;
+	}
+	preempt_enable();
+
+	if (offset == APIC_EILVT_NR_MAX) {
+		printk(KERN_DEBUG "No EILVT entry available\n");
+		return -EBUSY;
+	}
+
+	ret = setup_ibs_ctl(offset);
+	if (ret)
+		goto out;
+
+	if (!ibs_eilvt_valid()) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	pr_info("IBS: LVT offset %d assigned\n", offset);
+
+	return 0;
+out:
+	preempt_disable();
+	put_eilvt(offset);
+	preempt_enable();
+	return ret;
+}
+
+static inline int get_ibs_lvt_offset(void)
+{
+	u64 val;
+
+	rdmsrl(MSR_AMD64_IBSCTL, val);
+	if (!(val & IBSCTL_LVT_OFFSET_VALID))
+		return -EINVAL;
+
+	return val & IBSCTL_LVT_OFFSET_MASK;
+}
+
+static void setup_APIC_ibs(void *dummy)
+{
+	int offset;
+
+	offset = get_ibs_lvt_offset();
+	if (offset < 0)
+		goto failed;
+
+	if (!setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 0))
+		return;
+failed:
+	pr_warn("perf: IBS APIC setup failed on cpu #%d\n",
+		smp_processor_id());
+}
+
+static void clear_APIC_ibs(void *dummy)
+{
+	int offset;
+
+	offset = get_ibs_lvt_offset();
+	if (offset >= 0)
+		setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
+}
+
+static int __cpuinit
+perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
+{
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		setup_APIC_ibs(NULL);
+		break;
+	case CPU_DYING:
+		clear_APIC_ibs(NULL);
+		break;
+	default:
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static __init int amd_ibs_init(void)
+{
+	u32 caps;
+	int ret = -EINVAL;
+
+	caps = __get_ibs_caps();
+	if (!caps)
+		return -ENODEV;	/* ibs not supported by the cpu */
+
+	/*
+	 * Force LVT offset assignment for family 10h: The offsets are
+	 * not assigned by the BIOS for this family, so the OS is
+	 * responsible for doing it. If the OS assignment fails, fall
+	 * back to BIOS settings and try to setup this.
+	 */
+	if (boot_cpu_data.x86 == 0x10)
+		force_ibs_eilvt_setup();
+
+	if (!ibs_eilvt_valid())
+		goto out;
+
+	get_online_cpus();
+	ibs_caps = caps;
+	/* make ibs_caps visible to other cpus: */
+	smp_mb();
+	perf_cpu_notifier(perf_ibs_cpu_notifier);
+	smp_call_function(setup_APIC_ibs, NULL, 1);
+	put_online_cpus();
+
+	ret = perf_event_ibs_init();
+out:
+	if (ret)
+		pr_err("Failed to setup IBS, %d\n", ret);
+	return ret;
+}
+
+/* Since we need the pci subsystem to init ibs we can't do this earlier: */
+device_initcall(amd_ibs_init);
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,8 @@
 #include <asm/smp.h>
 #include <asm/alternative.h>
 
+#include "perf_event.h"
+
 #if 0
 #undef wrmsrl
 #define wrmsrl(msr, val) 					\
@@ -43,283 +45,17 @@
 } while (0)
 #endif
 
-/*
- *          |   NHM/WSM    |      SNB     |
- * register -------------------------------
- *          |  HT  | no HT |  HT  | no HT |
- *-----------------------------------------
- * offcore  | core | core  | cpu  | core  |
- * lbr_sel  | core | core  | cpu  | core  |
- * ld_lat   | cpu  | core  | cpu  | core  |
- *-----------------------------------------
- *
- * Given that there is a small number of shared regs,
- * we can pre-allocate their slot in the per-cpu
- * per-core reg tables.
- */
-enum extra_reg_type {
-	EXTRA_REG_NONE  = -1,	/* not used */
-
-	EXTRA_REG_RSP_0 = 0,	/* offcore_response_0 */
-	EXTRA_REG_RSP_1 = 1,	/* offcore_response_1 */
-
-	EXTRA_REG_MAX		/* number of entries needed */
-};
-
-struct event_constraint {
-	union {
-		unsigned long	idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
-		u64		idxmsk64;
-	};
-	u64	code;
-	u64	cmask;
-	int	weight;
-};
-
-struct amd_nb {
-	int nb_id;  /* NorthBridge id */
-	int refcnt; /* reference count */
-	struct perf_event *owners[X86_PMC_IDX_MAX];
-	struct event_constraint event_constraints[X86_PMC_IDX_MAX];
-};
-
-struct intel_percore;
-
-#define MAX_LBR_ENTRIES		16
-
-struct cpu_hw_events {
-	/*
-	 * Generic x86 PMC bits
-	 */
-	struct perf_event	*events[X86_PMC_IDX_MAX]; /* in counter order */
-	unsigned long		active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
-	unsigned long		running[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
-	int			enabled;
-
-	int			n_events;
-	int			n_added;
-	int			n_txn;
-	int			assign[X86_PMC_IDX_MAX]; /* event to counter assignment */
-	u64			tags[X86_PMC_IDX_MAX];
-	struct perf_event	*event_list[X86_PMC_IDX_MAX]; /* in enabled order */
-
-	unsigned int		group_flag;
-
-	/*
-	 * Intel DebugStore bits
-	 */
-	struct debug_store	*ds;
-	u64			pebs_enabled;
-
-	/*
-	 * Intel LBR bits
-	 */
-	int				lbr_users;
-	void				*lbr_context;
-	struct perf_branch_stack	lbr_stack;
-	struct perf_branch_entry	lbr_entries[MAX_LBR_ENTRIES];
-
-	/*
-	 * manage shared (per-core, per-cpu) registers
-	 * used on Intel NHM/WSM/SNB
-	 */
-	struct intel_shared_regs	*shared_regs;
-
-	/*
-	 * AMD specific bits
-	 */
-	struct amd_nb		*amd_nb;
-};
-
-#define __EVENT_CONSTRAINT(c, n, m, w) {\
-	{ .idxmsk64 = (n) },		\
-	.code = (c),			\
-	.cmask = (m),			\
-	.weight = (w),			\
-}
-
-#define EVENT_CONSTRAINT(c, n, m)	\
-	__EVENT_CONSTRAINT(c, n, m, HWEIGHT(n))
-
-/*
- * Constraint on the Event code.
- */
-#define INTEL_EVENT_CONSTRAINT(c, n)	\
-	EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT)
-
-/*
- * Constraint on the Event code + UMask + fixed-mask
- *
- * filter mask to validate fixed counter events.
- * the following filters disqualify for fixed counters:
- *  - inv
- *  - edge
- *  - cnt-mask
- *  The other filters are supported by fixed counters.
- *  The any-thread option is supported starting with v3.
- */
-#define FIXED_EVENT_CONSTRAINT(c, n)	\
-	EVENT_CONSTRAINT(c, (1ULL << (32+n)), X86_RAW_EVENT_MASK)
-
-/*
- * Constraint on the Event code + UMask
- */
-#define INTEL_UEVENT_CONSTRAINT(c, n)	\
-	EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK)
-
-#define EVENT_CONSTRAINT_END		\
-	EVENT_CONSTRAINT(0, 0, 0)
-
-#define for_each_event_constraint(e, c)	\
-	for ((e) = (c); (e)->weight; (e)++)
-
-/*
- * Per register state.
- */
-struct er_account {
-	raw_spinlock_t		lock;	/* per-core: protect structure */
-	u64			config;	/* extra MSR config */
-	u64			reg;	/* extra MSR number */
-	atomic_t		ref;	/* reference count */
-};
-
-/*
- * Extra registers for specific events.
- *
- * Some events need large masks and require external MSRs.
- * Those extra MSRs end up being shared for all events on
- * a PMU and sometimes between PMU of sibling HT threads.
- * In either case, the kernel needs to handle conflicting
- * accesses to those extra, shared, regs. The data structure
- * to manage those registers is stored in cpu_hw_event.
- */
-struct extra_reg {
-	unsigned int		event;
-	unsigned int		msr;
-	u64			config_mask;
-	u64			valid_mask;
-	int			idx;  /* per_xxx->regs[] reg index */
-};
-
-#define EVENT_EXTRA_REG(e, ms, m, vm, i) {	\
-	.event = (e),		\
-	.msr = (ms),		\
-	.config_mask = (m),	\
-	.valid_mask = (vm),	\
-	.idx = EXTRA_REG_##i	\
-	}
-
-#define INTEL_EVENT_EXTRA_REG(event, msr, vm, idx)	\
-	EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm, idx)
-
-#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0, RSP_0)
-
-union perf_capabilities {
-	struct {
-		u64	lbr_format    : 6;
-		u64	pebs_trap     : 1;
-		u64	pebs_arch_reg : 1;
-		u64	pebs_format   : 4;
-		u64	smm_freeze    : 1;
-	};
-	u64	capabilities;
-};
-
-/*
- * struct x86_pmu - generic x86 pmu
- */
-struct x86_pmu {
-	/*
-	 * Generic x86 PMC bits
-	 */
-	const char	*name;
-	int		version;
-	int		(*handle_irq)(struct pt_regs *);
-	void		(*disable_all)(void);
-	void		(*enable_all)(int added);
-	void		(*enable)(struct perf_event *);
-	void		(*disable)(struct perf_event *);
-	int		(*hw_config)(struct perf_event *event);
-	int		(*schedule_events)(struct cpu_hw_events *cpuc, int n, int *assign);
-	unsigned	eventsel;
-	unsigned	perfctr;
-	u64		(*event_map)(int);
-	int		max_events;
-	int		num_counters;
-	int		num_counters_fixed;
-	int		cntval_bits;
-	u64		cntval_mask;
-	int		apic;
-	u64		max_period;
-	struct event_constraint *
-			(*get_event_constraints)(struct cpu_hw_events *cpuc,
-						 struct perf_event *event);
-
-	void		(*put_event_constraints)(struct cpu_hw_events *cpuc,
-						 struct perf_event *event);
-	struct event_constraint *event_constraints;
-	void		(*quirks)(void);
-	int		perfctr_second_write;
-
-	int		(*cpu_prepare)(int cpu);
-	void		(*cpu_starting)(int cpu);
-	void		(*cpu_dying)(int cpu);
-	void		(*cpu_dead)(int cpu);
-
-	/*
-	 * Intel Arch Perfmon v2+
-	 */
-	u64			intel_ctrl;
-	union perf_capabilities intel_cap;
-
-	/*
-	 * Intel DebugStore bits
-	 */
-	int		bts, pebs;
-	int		bts_active, pebs_active;
-	int		pebs_record_size;
-	void		(*drain_pebs)(struct pt_regs *regs);
-	struct event_constraint *pebs_constraints;
-
-	/*
-	 * Intel LBR
-	 */
-	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;
-	unsigned int er_flags;
-};
-
-#define ERF_NO_HT_SHARING	1
-#define ERF_HAS_RSP_1		2
-
-static struct x86_pmu x86_pmu __read_mostly;
+struct x86_pmu x86_pmu __read_mostly;
 
-static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
+DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
 	.enabled = 1,
 };
 
-static int x86_perf_event_set_period(struct perf_event *event);
-
-/*
- * Generalized hw caching related hw_event table, filled
- * in on a per model basis. A value of 0 means
- * 'not supported', -1 means 'hw_event makes no sense on
- * this CPU', any other value means the raw hw_event
- * ID.
- */
-
-#define C(x) PERF_COUNT_HW_CACHE_##x
-
-static u64 __read_mostly hw_cache_event_ids
+u64 __read_mostly hw_cache_event_ids
 				[PERF_COUNT_HW_CACHE_MAX]
 				[PERF_COUNT_HW_CACHE_OP_MAX]
 				[PERF_COUNT_HW_CACHE_RESULT_MAX];
-static u64 __read_mostly hw_cache_extra_regs
+u64 __read_mostly hw_cache_extra_regs
 				[PERF_COUNT_HW_CACHE_MAX]
 				[PERF_COUNT_HW_CACHE_OP_MAX]
 				[PERF_COUNT_HW_CACHE_RESULT_MAX];
@@ -329,8 +65,7 @@
  * Can only be executed on the CPU where the event is active.
  * Returns the delta events processed.
  */
-static u64
-x86_perf_event_update(struct perf_event *event)
+u64 x86_perf_event_update(struct perf_event *event)
 {
 	struct hw_perf_event *hwc = &event->hw;
 	int shift = 64 - x86_pmu.cntval_bits;
@@ -373,30 +108,6 @@
 	return new_raw_count;
 }
 
-static inline int x86_pmu_addr_offset(int index)
-{
-	int offset;
-
-	/* offset = X86_FEATURE_PERFCTR_CORE ? index << 1 : index */
-	alternative_io(ASM_NOP2,
-		       "shll $1, %%eax",
-		       X86_FEATURE_PERFCTR_CORE,
-		       "=a" (offset),
-		       "a"  (index));
-
-	return offset;
-}
-
-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.
  */
@@ -532,9 +243,6 @@
 	return false;
 }
 
-static void reserve_ds_buffers(void);
-static void release_ds_buffers(void);
-
 static void hw_perf_event_destroy(struct perf_event *event)
 {
 	if (atomic_dec_and_mutex_lock(&active_events, &pmc_reserve_mutex)) {
@@ -583,7 +291,7 @@
 	return x86_pmu_extra_regs(val, event);
 }
 
-static int x86_setup_perfctr(struct perf_event *event)
+int x86_setup_perfctr(struct perf_event *event)
 {
 	struct perf_event_attr *attr = &event->attr;
 	struct hw_perf_event *hwc = &event->hw;
@@ -604,12 +312,8 @@
 			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;
+		return x86_pmu_extra_regs(event->attr.config, event);
 
 	if (attr->type == PERF_TYPE_HW_CACHE)
 		return set_ext_hw_attr(hwc, event);
@@ -647,7 +351,7 @@
 	return 0;
 }
 
-static int x86_pmu_hw_config(struct perf_event *event)
+int x86_pmu_hw_config(struct perf_event *event)
 {
 	if (event->attr.precise_ip) {
 		int precise = 0;
@@ -723,7 +427,7 @@
 	return x86_pmu.hw_config(event);
 }
 
-static void x86_pmu_disable_all(void)
+void x86_pmu_disable_all(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	int idx;
@@ -758,15 +462,7 @@
 	x86_pmu.disable_all();
 }
 
-static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
-					  u64 enable_mask)
-{
-	if (hwc->extra_reg.reg)
-		wrmsrl(hwc->extra_reg.reg, hwc->extra_reg.config);
-	wrmsrl(hwc->config_base, hwc->config | enable_mask);
-}
-
-static void x86_pmu_enable_all(int added)
+void x86_pmu_enable_all(int added)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	int idx;
@@ -788,7 +484,7 @@
 	return event->pmu == &pmu;
 }
 
-static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
+int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
 {
 	struct event_constraint *c, *constraints[X86_PMC_IDX_MAX];
 	unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
@@ -888,7 +584,7 @@
 				x86_pmu.put_event_constraints(cpuc, cpuc->event_list[i]);
 		}
 	}
-	return num ? -ENOSPC : 0;
+	return num ? -EINVAL : 0;
 }
 
 /*
@@ -907,7 +603,7 @@
 
 	if (is_x86_event(leader)) {
 		if (n >= max_count)
-			return -ENOSPC;
+			return -EINVAL;
 		cpuc->event_list[n] = leader;
 		n++;
 	}
@@ -920,7 +616,7 @@
 			continue;
 
 		if (n >= max_count)
-			return -ENOSPC;
+			return -EINVAL;
 
 		cpuc->event_list[n] = event;
 		n++;
@@ -959,7 +655,6 @@
 }
 
 static void x86_pmu_start(struct perf_event *event, int flags);
-static void x86_pmu_stop(struct perf_event *event, int flags);
 
 static void x86_pmu_enable(struct pmu *pmu)
 {
@@ -1031,21 +726,13 @@
 	x86_pmu.enable_all(added);
 }
 
-static inline void x86_pmu_disable_event(struct perf_event *event)
-{
-	struct hw_perf_event *hwc = &event->hw;
-
-	wrmsrl(hwc->config_base, hwc->config);
-}
-
 static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left);
 
 /*
  * Set the next IRQ period, based on the hwc->period_left value.
  * To be called with the event disabled in hw:
  */
-static int
-x86_perf_event_set_period(struct perf_event *event)
+int x86_perf_event_set_period(struct perf_event *event)
 {
 	struct hw_perf_event *hwc = &event->hw;
 	s64 left = local64_read(&hwc->period_left);
@@ -1105,7 +792,7 @@
 	return ret;
 }
 
-static void x86_pmu_enable_event(struct perf_event *event)
+void x86_pmu_enable_event(struct perf_event *event)
 {
 	if (__this_cpu_read(cpu_hw_events.enabled))
 		__x86_pmu_enable_event(&event->hw,
@@ -1244,7 +931,7 @@
 	local_irq_restore(flags);
 }
 
-static void x86_pmu_stop(struct perf_event *event, int flags)
+void x86_pmu_stop(struct perf_event *event, int flags)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct hw_perf_event *hwc = &event->hw;
@@ -1297,7 +984,7 @@
 	perf_event_update_userpage(event);
 }
 
-static int x86_pmu_handle_irq(struct pt_regs *regs)
+int x86_pmu_handle_irq(struct pt_regs *regs)
 {
 	struct perf_sample_data data;
 	struct cpu_hw_events *cpuc;
@@ -1367,109 +1054,28 @@
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
 }
 
-struct pmu_nmi_state {
-	unsigned int	marked;
-	int		handled;
-};
-
-static DEFINE_PER_CPU(struct pmu_nmi_state, pmu_nmi);
-
 static int __kprobes
-perf_event_nmi_handler(struct notifier_block *self,
-			 unsigned long cmd, void *__args)
+perf_event_nmi_handler(unsigned int cmd, struct pt_regs *regs)
 {
-	struct die_args *args = __args;
-	unsigned int this_nmi;
-	int handled;
-
 	if (!atomic_read(&active_events))
-		return NOTIFY_DONE;
-
-	switch (cmd) {
-	case DIE_NMI:
-		break;
-	case DIE_NMIUNKNOWN:
-		this_nmi = percpu_read(irq_stat.__nmi_count);
-		if (this_nmi != __this_cpu_read(pmu_nmi.marked))
-			/* let the kernel handle the unknown nmi */
-			return NOTIFY_DONE;
-		/*
-		 * This one is a PMU back-to-back nmi. Two events
-		 * trigger 'simultaneously' raising two back-to-back
-		 * NMIs. If the first NMI handles both, the latter
-		 * will be empty and daze the CPU. So, we drop it to
-		 * avoid false-positive 'unknown nmi' messages.
-		 */
-		return NOTIFY_STOP;
-	default:
-		return NOTIFY_DONE;
-	}
-
-	handled = x86_pmu.handle_irq(args->regs);
-	if (!handled)
-		return NOTIFY_DONE;
-
-	this_nmi = percpu_read(irq_stat.__nmi_count);
-	if ((handled > 1) ||
-		/* the next nmi could be a back-to-back nmi */
-	    ((__this_cpu_read(pmu_nmi.marked) == this_nmi) &&
-	     (__this_cpu_read(pmu_nmi.handled) > 1))) {
-		/*
-		 * We could have two subsequent back-to-back nmis: The
-		 * first handles more than one counter, the 2nd
-		 * handles only one counter and the 3rd handles no
-		 * counter.
-		 *
-		 * This is the 2nd nmi because the previous was
-		 * handling more than one counter. We will mark the
-		 * next (3rd) and then drop it if unhandled.
-		 */
-		__this_cpu_write(pmu_nmi.marked, this_nmi + 1);
-		__this_cpu_write(pmu_nmi.handled, handled);
-	}
-
-	return NOTIFY_STOP;
-}
-
-static __read_mostly struct notifier_block perf_event_nmi_notifier = {
-	.notifier_call		= perf_event_nmi_handler,
-	.next			= NULL,
-	.priority		= NMI_LOCAL_LOW_PRIOR,
-};
-
-static struct event_constraint unconstrained;
-static struct event_constraint emptyconstraint;
-
-static struct event_constraint *
-x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
-{
-	struct event_constraint *c;
-
-	if (x86_pmu.event_constraints) {
-		for_each_event_constraint(c, x86_pmu.event_constraints) {
-			if ((event->hw.config & c->cmask) == c->code)
-				return c;
-		}
-	}
+		return NMI_DONE;
 
-	return &unconstrained;
+	return x86_pmu.handle_irq(regs);
 }
 
-#include "perf_event_amd.c"
-#include "perf_event_p6.c"
-#include "perf_event_p4.c"
-#include "perf_event_intel_lbr.c"
-#include "perf_event_intel_ds.c"
-#include "perf_event_intel.c"
+struct event_constraint emptyconstraint;
+struct event_constraint unconstrained;
 
 static int __cpuinit
 x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (long)hcpu;
+	struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
 	int ret = NOTIFY_OK;
 
 	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_UP_PREPARE:
+		cpuc->kfree_on_online = NULL;
 		if (x86_pmu.cpu_prepare)
 			ret = x86_pmu.cpu_prepare(cpu);
 		break;
@@ -1479,6 +1085,10 @@
 			x86_pmu.cpu_starting(cpu);
 		break;
 
+	case CPU_ONLINE:
+		kfree(cpuc->kfree_on_online);
+		break;
+
 	case CPU_DYING:
 		if (x86_pmu.cpu_dying)
 			x86_pmu.cpu_dying(cpu);
@@ -1557,7 +1167,7 @@
 		((1LL << x86_pmu.num_counters_fixed)-1) << X86_PMC_IDX_FIXED;
 
 	perf_events_lapic_init();
-	register_die_notifier(&perf_event_nmi_notifier);
+	register_nmi_handler(NMI_LOCAL, perf_event_nmi_handler, 0, "PMI");
 
 	unconstrained = (struct event_constraint)
 		__EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1,
@@ -1702,7 +1312,7 @@
 	c = x86_pmu.get_event_constraints(fake_cpuc, event);
 
 	if (!c || !c->weight)
-		ret = -ENOSPC;
+		ret = -EINVAL;
 
 	if (x86_pmu.put_event_constraints)
 		x86_pmu.put_event_constraints(fake_cpuc, event);
@@ -1727,7 +1337,7 @@
 {
 	struct perf_event *leader = event->group_leader;
 	struct cpu_hw_events *fake_cpuc;
-	int ret = -ENOSPC, n;
+	int ret = -EINVAL, n;
 
 	fake_cpuc = allocate_fake_cpuc();
 	if (IS_ERR(fake_cpuc))
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event.h linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event.h
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,505 @@
+/*
+ * Performance events x86 architecture header
+ *
+ *  Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
+ *  Copyright (C) 2009 Jaswinder Singh Rajput
+ *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
+ *  Copyright (C) 2009 Google, Inc., Stephane Eranian
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/perf_event.h>
+
+/*
+ *          |   NHM/WSM    |      SNB     |
+ * register -------------------------------
+ *          |  HT  | no HT |  HT  | no HT |
+ *-----------------------------------------
+ * offcore  | core | core  | cpu  | core  |
+ * lbr_sel  | core | core  | cpu  | core  |
+ * ld_lat   | cpu  | core  | cpu  | core  |
+ *-----------------------------------------
+ *
+ * Given that there is a small number of shared regs,
+ * we can pre-allocate their slot in the per-cpu
+ * per-core reg tables.
+ */
+enum extra_reg_type {
+	EXTRA_REG_NONE  = -1,	/* not used */
+
+	EXTRA_REG_RSP_0 = 0,	/* offcore_response_0 */
+	EXTRA_REG_RSP_1 = 1,	/* offcore_response_1 */
+
+	EXTRA_REG_MAX		/* number of entries needed */
+};
+
+struct event_constraint {
+	union {
+		unsigned long	idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+		u64		idxmsk64;
+	};
+	u64	code;
+	u64	cmask;
+	int	weight;
+};
+
+struct amd_nb {
+	int nb_id;  /* NorthBridge id */
+	int refcnt; /* reference count */
+	struct perf_event *owners[X86_PMC_IDX_MAX];
+	struct event_constraint event_constraints[X86_PMC_IDX_MAX];
+};
+
+/* The maximal number of PEBS events: */
+#define MAX_PEBS_EVENTS		4
+
+/*
+ * A debug store configuration.
+ *
+ * We only support architectures that use 64bit fields.
+ */
+struct debug_store {
+	u64	bts_buffer_base;
+	u64	bts_index;
+	u64	bts_absolute_maximum;
+	u64	bts_interrupt_threshold;
+	u64	pebs_buffer_base;
+	u64	pebs_index;
+	u64	pebs_absolute_maximum;
+	u64	pebs_interrupt_threshold;
+	u64	pebs_event_reset[MAX_PEBS_EVENTS];
+};
+
+/*
+ * Per register state.
+ */
+struct er_account {
+	raw_spinlock_t		lock;	/* per-core: protect structure */
+	u64                 config;	/* extra MSR config */
+	u64                 reg;	/* extra MSR number */
+	atomic_t            ref;	/* reference count */
+};
+
+/*
+ * Per core/cpu state
+ *
+ * Used to coordinate shared registers between HT threads or
+ * among events on a single PMU.
+ */
+struct intel_shared_regs {
+	struct er_account       regs[EXTRA_REG_MAX];
+	int                     refcnt;		/* per-core: #HT threads */
+	unsigned                core_id;	/* per-core: core id */
+};
+
+#define MAX_LBR_ENTRIES		16
+
+struct cpu_hw_events {
+	/*
+	 * Generic x86 PMC bits
+	 */
+	struct perf_event	*events[X86_PMC_IDX_MAX]; /* in counter order */
+	unsigned long		active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+	unsigned long		running[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+	int			enabled;
+
+	int			n_events;
+	int			n_added;
+	int			n_txn;
+	int			assign[X86_PMC_IDX_MAX]; /* event to counter assignment */
+	u64			tags[X86_PMC_IDX_MAX];
+	struct perf_event	*event_list[X86_PMC_IDX_MAX]; /* in enabled order */
+
+	unsigned int		group_flag;
+
+	/*
+	 * Intel DebugStore bits
+	 */
+	struct debug_store	*ds;
+	u64			pebs_enabled;
+
+	/*
+	 * Intel LBR bits
+	 */
+	int				lbr_users;
+	void				*lbr_context;
+	struct perf_branch_stack	lbr_stack;
+	struct perf_branch_entry	lbr_entries[MAX_LBR_ENTRIES];
+
+	/*
+	 * Intel host/guest exclude bits
+	 */
+	u64				intel_ctrl_guest_mask;
+	u64				intel_ctrl_host_mask;
+	struct perf_guest_switch_msr	guest_switch_msrs[X86_PMC_IDX_MAX];
+
+	/*
+	 * manage shared (per-core, per-cpu) registers
+	 * used on Intel NHM/WSM/SNB
+	 */
+	struct intel_shared_regs	*shared_regs;
+
+	/*
+	 * AMD specific bits
+	 */
+	struct amd_nb		*amd_nb;
+
+	void				*kfree_on_online;
+};
+
+#define __EVENT_CONSTRAINT(c, n, m, w) {\
+	{ .idxmsk64 = (n) },		\
+	.code = (c),			\
+	.cmask = (m),			\
+	.weight = (w),			\
+}
+
+#define EVENT_CONSTRAINT(c, n, m)	\
+	__EVENT_CONSTRAINT(c, n, m, HWEIGHT(n))
+
+/*
+ * Constraint on the Event code.
+ */
+#define INTEL_EVENT_CONSTRAINT(c, n)	\
+	EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT)
+
+/*
+ * Constraint on the Event code + UMask + fixed-mask
+ *
+ * filter mask to validate fixed counter events.
+ * the following filters disqualify for fixed counters:
+ *  - inv
+ *  - edge
+ *  - cnt-mask
+ *  The other filters are supported by fixed counters.
+ *  The any-thread option is supported starting with v3.
+ */
+#define FIXED_EVENT_CONSTRAINT(c, n)	\
+	EVENT_CONSTRAINT(c, (1ULL << (32+n)), X86_RAW_EVENT_MASK)
+
+/*
+ * Constraint on the Event code + UMask
+ */
+#define INTEL_UEVENT_CONSTRAINT(c, n)	\
+	EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK)
+
+#define EVENT_CONSTRAINT_END		\
+	EVENT_CONSTRAINT(0, 0, 0)
+
+#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.
+ * Those extra MSRs end up being shared for all events on
+ * a PMU and sometimes between PMU of sibling HT threads.
+ * In either case, the kernel needs to handle conflicting
+ * accesses to those extra, shared, regs. The data structure
+ * to manage those registers is stored in cpu_hw_event.
+ */
+struct extra_reg {
+	unsigned int		event;
+	unsigned int		msr;
+	u64			config_mask;
+	u64			valid_mask;
+	int			idx;  /* per_xxx->regs[] reg index */
+};
+
+#define EVENT_EXTRA_REG(e, ms, m, vm, i) {	\
+	.event = (e),		\
+	.msr = (ms),		\
+	.config_mask = (m),	\
+	.valid_mask = (vm),	\
+	.idx = EXTRA_REG_##i	\
+	}
+
+#define INTEL_EVENT_EXTRA_REG(event, msr, vm, idx)	\
+	EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm, idx)
+
+#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0, RSP_0)
+
+union perf_capabilities {
+	struct {
+		u64	lbr_format:6;
+		u64	pebs_trap:1;
+		u64	pebs_arch_reg:1;
+		u64	pebs_format:4;
+		u64	smm_freeze:1;
+	};
+	u64	capabilities;
+};
+
+/*
+ * struct x86_pmu - generic x86 pmu
+ */
+struct x86_pmu {
+	/*
+	 * Generic x86 PMC bits
+	 */
+	const char	*name;
+	int		version;
+	int		(*handle_irq)(struct pt_regs *);
+	void		(*disable_all)(void);
+	void		(*enable_all)(int added);
+	void		(*enable)(struct perf_event *);
+	void		(*disable)(struct perf_event *);
+	int		(*hw_config)(struct perf_event *event);
+	int		(*schedule_events)(struct cpu_hw_events *cpuc, int n, int *assign);
+	unsigned	eventsel;
+	unsigned	perfctr;
+	u64		(*event_map)(int);
+	int		max_events;
+	int		num_counters;
+	int		num_counters_fixed;
+	int		cntval_bits;
+	u64		cntval_mask;
+	int		apic;
+	u64		max_period;
+	struct event_constraint *
+			(*get_event_constraints)(struct cpu_hw_events *cpuc,
+						 struct perf_event *event);
+
+	void		(*put_event_constraints)(struct cpu_hw_events *cpuc,
+						 struct perf_event *event);
+	struct event_constraint *event_constraints;
+	void		(*quirks)(void);
+	int		perfctr_second_write;
+
+	int		(*cpu_prepare)(int cpu);
+	void		(*cpu_starting)(int cpu);
+	void		(*cpu_dying)(int cpu);
+	void		(*cpu_dead)(int cpu);
+
+	/*
+	 * Intel Arch Perfmon v2+
+	 */
+	u64			intel_ctrl;
+	union perf_capabilities intel_cap;
+
+	/*
+	 * Intel DebugStore bits
+	 */
+	int		bts, pebs;
+	int		bts_active, pebs_active;
+	int		pebs_record_size;
+	void		(*drain_pebs)(struct pt_regs *regs);
+	struct event_constraint *pebs_constraints;
+
+	/*
+	 * Intel LBR
+	 */
+	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;
+	unsigned int er_flags;
+
+	/*
+	 * Intel host/guest support (KVM)
+	 */
+	struct perf_guest_switch_msr *(*guest_get_msrs)(int *nr);
+};
+
+#define ERF_NO_HT_SHARING	1
+#define ERF_HAS_RSP_1		2
+
+extern struct x86_pmu x86_pmu __read_mostly;
+
+DECLARE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
+
+int x86_perf_event_set_period(struct perf_event *event);
+
+/*
+ * Generalized hw caching related hw_event table, filled
+ * in on a per model basis. A value of 0 means
+ * 'not supported', -1 means 'hw_event makes no sense on
+ * this CPU', any other value means the raw hw_event
+ * ID.
+ */
+
+#define C(x) PERF_COUNT_HW_CACHE_##x
+
+extern u64 __read_mostly hw_cache_event_ids
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX];
+extern u64 __read_mostly hw_cache_extra_regs
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX];
+
+u64 x86_perf_event_update(struct perf_event *event);
+
+static inline int x86_pmu_addr_offset(int index)
+{
+	int offset;
+
+	/* offset = X86_FEATURE_PERFCTR_CORE ? index << 1 : index */
+	alternative_io(ASM_NOP2,
+		       "shll $1, %%eax",
+		       X86_FEATURE_PERFCTR_CORE,
+		       "=a" (offset),
+		       "a"  (index));
+
+	return offset;
+}
+
+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);
+}
+
+int x86_setup_perfctr(struct perf_event *event);
+
+int x86_pmu_hw_config(struct perf_event *event);
+
+void x86_pmu_disable_all(void);
+
+static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
+					  u64 enable_mask)
+{
+	if (hwc->extra_reg.reg)
+		wrmsrl(hwc->extra_reg.reg, hwc->extra_reg.config);
+	wrmsrl(hwc->config_base, hwc->config | enable_mask);
+}
+
+void x86_pmu_enable_all(int added);
+
+int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign);
+
+void x86_pmu_stop(struct perf_event *event, int flags);
+
+static inline void x86_pmu_disable_event(struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	wrmsrl(hwc->config_base, hwc->config);
+}
+
+void x86_pmu_enable_event(struct perf_event *event);
+
+int x86_pmu_handle_irq(struct pt_regs *regs);
+
+extern struct event_constraint emptyconstraint;
+
+extern struct event_constraint unconstrained;
+
+#ifdef CONFIG_CPU_SUP_AMD
+
+int amd_pmu_init(void);
+
+#else /* CONFIG_CPU_SUP_AMD */
+
+static inline int amd_pmu_init(void)
+{
+	return 0;
+}
+
+#endif /* CONFIG_CPU_SUP_AMD */
+
+#ifdef CONFIG_CPU_SUP_INTEL
+
+int intel_pmu_save_and_restart(struct perf_event *event);
+
+struct event_constraint *
+x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event);
+
+struct intel_shared_regs *allocate_shared_regs(int cpu);
+
+int intel_pmu_init(void);
+
+void init_debug_store_on_cpu(int cpu);
+
+void fini_debug_store_on_cpu(int cpu);
+
+void release_ds_buffers(void);
+
+void reserve_ds_buffers(void);
+
+extern struct event_constraint bts_constraint;
+
+void intel_pmu_enable_bts(u64 config);
+
+void intel_pmu_disable_bts(void);
+
+int intel_pmu_drain_bts_buffer(void);
+
+extern struct event_constraint intel_core2_pebs_event_constraints[];
+
+extern struct event_constraint intel_atom_pebs_event_constraints[];
+
+extern struct event_constraint intel_nehalem_pebs_event_constraints[];
+
+extern struct event_constraint intel_westmere_pebs_event_constraints[];
+
+extern struct event_constraint intel_snb_pebs_event_constraints[];
+
+struct event_constraint *intel_pebs_constraints(struct perf_event *event);
+
+void intel_pmu_pebs_enable(struct perf_event *event);
+
+void intel_pmu_pebs_disable(struct perf_event *event);
+
+void intel_pmu_pebs_enable_all(void);
+
+void intel_pmu_pebs_disable_all(void);
+
+void intel_ds_init(void);
+
+void intel_pmu_lbr_reset(void);
+
+void intel_pmu_lbr_enable(struct perf_event *event);
+
+void intel_pmu_lbr_disable(struct perf_event *event);
+
+void intel_pmu_lbr_enable_all(void);
+
+void intel_pmu_lbr_disable_all(void);
+
+void intel_pmu_lbr_read(void);
+
+void intel_pmu_lbr_init_core(void);
+
+void intel_pmu_lbr_init_nhm(void);
+
+void intel_pmu_lbr_init_atom(void);
+
+int p4_pmu_init(void);
+
+int p6_pmu_init(void);
+
+#else /* CONFIG_CPU_SUP_INTEL */
+
+static inline void reserve_ds_buffers(void)
+{
+}
+
+static inline void release_ds_buffers(void)
+{
+}
+
+static inline int intel_pmu_init(void)
+{
+	return 0;
+}
+
+static inline struct intel_shared_regs *allocate_shared_regs(int cpu)
+{
+	return NULL;
+}
+
+#endif /* CONFIG_CPU_SUP_INTEL */
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event_intel.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event_intel.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event_intel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event_intel.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,16 +1,20 @@
-#ifdef CONFIG_CPU_SUP_INTEL
-
 /*
  * Per core/cpu state
  *
  * Used to coordinate shared registers between HT threads or
  * among events on a single PMU.
  */
-struct intel_shared_regs {
-	struct er_account       regs[EXTRA_REG_MAX];
-	int                     refcnt;		/* per-core: #HT threads */
-	unsigned                core_id;	/* per-core: core id */
-};
+
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+
+#include <asm/hardirq.h>
+#include <asm/apic.h>
+
+#include "perf_event.h"
 
 /*
  * Intel PerfMon, used on Core and later.
@@ -746,7 +750,8 @@
 
 	intel_pmu_pebs_enable_all();
 	intel_pmu_lbr_enable_all();
-	wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl);
+	wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL,
+			x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask);
 
 	if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) {
 		struct perf_event *event =
@@ -869,6 +874,7 @@
 static void intel_pmu_disable_event(struct perf_event *event)
 {
 	struct hw_perf_event *hwc = &event->hw;
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
 	if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) {
 		intel_pmu_disable_bts();
@@ -876,6 +882,9 @@
 		return;
 	}
 
+	cpuc->intel_ctrl_guest_mask &= ~(1ull << hwc->idx);
+	cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx);
+
 	if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
 		intel_pmu_disable_fixed(hwc);
 		return;
@@ -921,6 +930,7 @@
 static void intel_pmu_enable_event(struct perf_event *event)
 {
 	struct hw_perf_event *hwc = &event->hw;
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
 	if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) {
 		if (!__this_cpu_read(cpu_hw_events.enabled))
@@ -930,6 +940,11 @@
 		return;
 	}
 
+	if (event->attr.exclude_host)
+		cpuc->intel_ctrl_guest_mask |= (1ull << hwc->idx);
+	if (event->attr.exclude_guest)
+		cpuc->intel_ctrl_host_mask |= (1ull << hwc->idx);
+
 	if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
 		intel_pmu_enable_fixed(hwc);
 		return;
@@ -945,7 +960,7 @@
  * Save and restart an expired event. Called by NMI contexts,
  * so it has to be careful about preempting normal event ops:
  */
-static int intel_pmu_save_and_restart(struct perf_event *event)
+int intel_pmu_save_and_restart(struct perf_event *event)
 {
 	x86_perf_event_update(event);
 	return x86_perf_event_set_period(event);
@@ -1154,7 +1169,7 @@
 		 */
 		c = &unconstrained;
 	} else if (intel_try_alt_er(event, orig_idx)) {
-		raw_spin_unlock(&era->lock);
+		raw_spin_unlock_irqrestore(&era->lock, flags);
 		goto again;
 	}
 	raw_spin_unlock_irqrestore(&era->lock, flags);
@@ -1197,6 +1212,21 @@
 	return c;
 }
 
+struct event_constraint *
+x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
+{
+	struct event_constraint *c;
+
+	if (x86_pmu.event_constraints) {
+		for_each_event_constraint(c, x86_pmu.event_constraints) {
+			if ((event->hw.config & c->cmask) == c->code)
+				return c;
+		}
+	}
+
+	return &unconstrained;
+}
+
 static struct event_constraint *
 intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
 {
@@ -1284,12 +1314,84 @@
 	return 0;
 }
 
+struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr)
+{
+	if (x86_pmu.guest_get_msrs)
+		return x86_pmu.guest_get_msrs(nr);
+	*nr = 0;
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(perf_guest_get_msrs);
+
+static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	struct perf_guest_switch_msr *arr = cpuc->guest_switch_msrs;
+
+	arr[0].msr = MSR_CORE_PERF_GLOBAL_CTRL;
+	arr[0].host = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask;
+	arr[0].guest = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_host_mask;
+
+	*nr = 1;
+	return arr;
+}
+
+static struct perf_guest_switch_msr *core_guest_get_msrs(int *nr)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	struct perf_guest_switch_msr *arr = cpuc->guest_switch_msrs;
+	int idx;
+
+	for (idx = 0; idx < x86_pmu.num_counters; idx++)  {
+		struct perf_event *event = cpuc->events[idx];
+
+		arr[idx].msr = x86_pmu_config_addr(idx);
+		arr[idx].host = arr[idx].guest = 0;
+
+		if (!test_bit(idx, cpuc->active_mask))
+			continue;
+
+		arr[idx].host = arr[idx].guest =
+			event->hw.config | ARCH_PERFMON_EVENTSEL_ENABLE;
+
+		if (event->attr.exclude_host)
+			arr[idx].host &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+		else if (event->attr.exclude_guest)
+			arr[idx].guest &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+	}
+
+	*nr = x86_pmu.num_counters;
+	return arr;
+}
+
+static void core_pmu_enable_event(struct perf_event *event)
+{
+	if (!event->attr.exclude_host)
+		x86_pmu_enable_event(event);
+}
+
+static void core_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 hw_perf_event *hwc = &cpuc->events[idx]->hw;
+
+		if (!test_bit(idx, cpuc->active_mask) ||
+				cpuc->events[idx]->attr.exclude_host)
+			continue;
+
+		__x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE);
+	}
+}
+
 static __initconst const struct x86_pmu core_pmu = {
 	.name			= "core",
 	.handle_irq		= x86_pmu_handle_irq,
 	.disable_all		= x86_pmu_disable_all,
-	.enable_all		= x86_pmu_enable_all,
-	.enable			= x86_pmu_enable_event,
+	.enable_all		= core_pmu_enable_all,
+	.enable			= core_pmu_enable_event,
 	.disable		= x86_pmu_disable_event,
 	.hw_config		= x86_pmu_hw_config,
 	.schedule_events	= x86_schedule_events,
@@ -1307,9 +1409,10 @@
 	.get_event_constraints	= intel_get_event_constraints,
 	.put_event_constraints	= intel_put_event_constraints,
 	.event_constraints	= intel_core_event_constraints,
+	.guest_get_msrs		= core_guest_get_msrs,
 };
 
-static struct intel_shared_regs *allocate_shared_regs(int cpu)
+struct intel_shared_regs *allocate_shared_regs(int cpu)
 {
 	struct intel_shared_regs *regs;
 	int i;
@@ -1362,7 +1465,7 @@
 
 		pc = per_cpu(cpu_hw_events, i).shared_regs;
 		if (pc && pc->core_id == core_id) {
-			kfree(cpuc->shared_regs);
+			cpuc->kfree_on_online = cpuc->shared_regs;
 			cpuc->shared_regs = pc;
 			break;
 		}
@@ -1413,6 +1516,7 @@
 	.cpu_prepare		= intel_pmu_cpu_prepare,
 	.cpu_starting		= intel_pmu_cpu_starting,
 	.cpu_dying		= intel_pmu_cpu_dying,
+	.guest_get_msrs		= intel_guest_get_msrs,
 };
 
 static void intel_clovertown_quirks(void)
@@ -1441,7 +1545,14 @@
 	x86_pmu.pebs_constraints = NULL;
 }
 
-static __init int intel_pmu_init(void)
+static void intel_sandybridge_quirks(void)
+{
+	printk(KERN_WARNING "PEBS disabled due to CPU errata.\n");
+	x86_pmu.pebs = 0;
+	x86_pmu.pebs_constraints = NULL;
+}
+
+__init int intel_pmu_init(void)
 {
 	union cpuid10_edx edx;
 	union cpuid10_eax eax;
@@ -1590,6 +1701,7 @@
 		break;
 
 	case 42: /* SandyBridge */
+		x86_pmu.quirks = intel_sandybridge_quirks;
 	case 45: /* SandyBridge, "Romely-EP" */
 		memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
 		       sizeof(hw_cache_event_ids));
@@ -1597,7 +1709,7 @@
 		intel_pmu_lbr_init_nhm();
 
 		x86_pmu.event_constraints = intel_snb_event_constraints;
-		x86_pmu.pebs_constraints = intel_snb_pebs_events;
+		x86_pmu.pebs_constraints = intel_snb_pebs_event_constraints;
 		x86_pmu.extra_regs = intel_snb_extra_regs;
 		/* all extra regs are per-cpu when HT is on */
 		x86_pmu.er_flags |= ERF_HAS_RSP_1;
@@ -1628,16 +1740,3 @@
 	}
 	return 0;
 }
-
-#else /* CONFIG_CPU_SUP_INTEL */
-
-static int intel_pmu_init(void)
-{
-	return 0;
-}
-
-static struct intel_shared_regs *allocate_shared_regs(int cpu)
-{
-	return NULL;
-}
-#endif /* CONFIG_CPU_SUP_INTEL */
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event_intel_ds.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event_intel_ds.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event_intel_ds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event_intel_ds.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,10 @@
-#ifdef CONFIG_CPU_SUP_INTEL
+#include <linux/bitops.h>
+#include <linux/types.h>
+#include <linux/slab.h>
 
-/* The maximal number of PEBS events: */
-#define MAX_PEBS_EVENTS		4
+#include <asm/perf_event.h>
+
+#include "perf_event.h"
 
 /* The size of a BTS record in bytes: */
 #define BTS_RECORD_SIZE		24
@@ -37,24 +40,7 @@
 	u64 status, dla, dse, lat;
 };
 
-/*
- * A debug store configuration.
- *
- * We only support architectures that use 64bit fields.
- */
-struct debug_store {
-	u64	bts_buffer_base;
-	u64	bts_index;
-	u64	bts_absolute_maximum;
-	u64	bts_interrupt_threshold;
-	u64	pebs_buffer_base;
-	u64	pebs_index;
-	u64	pebs_absolute_maximum;
-	u64	pebs_interrupt_threshold;
-	u64	pebs_event_reset[MAX_PEBS_EVENTS];
-};
-
-static void init_debug_store_on_cpu(int cpu)
+void init_debug_store_on_cpu(int cpu)
 {
 	struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
 
@@ -66,7 +52,7 @@
 		     (u32)((u64)(unsigned long)ds >> 32));
 }
 
-static void fini_debug_store_on_cpu(int cpu)
+void fini_debug_store_on_cpu(int cpu)
 {
 	if (!per_cpu(cpu_hw_events, cpu).ds)
 		return;
@@ -175,7 +161,7 @@
 	kfree(ds);
 }
 
-static void release_ds_buffers(void)
+void release_ds_buffers(void)
 {
 	int cpu;
 
@@ -194,7 +180,7 @@
 	put_online_cpus();
 }
 
-static void reserve_ds_buffers(void)
+void reserve_ds_buffers(void)
 {
 	int bts_err = 0, pebs_err = 0;
 	int cpu;
@@ -260,10 +246,10 @@
  * BTS
  */
 
-static struct event_constraint bts_constraint =
+struct event_constraint bts_constraint =
 	EVENT_CONSTRAINT(0, 1ULL << X86_PMC_IDX_FIXED_BTS, 0);
 
-static void intel_pmu_enable_bts(u64 config)
+void intel_pmu_enable_bts(u64 config)
 {
 	unsigned long debugctlmsr;
 
@@ -282,7 +268,7 @@
 	update_debugctlmsr(debugctlmsr);
 }
 
-static void intel_pmu_disable_bts(void)
+void intel_pmu_disable_bts(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	unsigned long debugctlmsr;
@@ -299,7 +285,7 @@
 	update_debugctlmsr(debugctlmsr);
 }
 
-static int intel_pmu_drain_bts_buffer(void)
+int intel_pmu_drain_bts_buffer(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct debug_store *ds = cpuc->ds;
@@ -361,7 +347,7 @@
 /*
  * PEBS
  */
-static struct event_constraint intel_core2_pebs_event_constraints[] = {
+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 */
@@ -370,14 +356,14 @@
 	EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint intel_atom_pebs_event_constraints[] = {
+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_event_constraints[] = {
+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 */
@@ -392,7 +378,7 @@
 	EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint intel_westmere_pebs_event_constraints[] = {
+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 */
@@ -407,7 +393,7 @@
 	EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint intel_snb_pebs_events[] = {
+struct event_constraint intel_snb_pebs_event_constraints[] = {
 	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 */
@@ -428,8 +414,7 @@
 	EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint *
-intel_pebs_constraints(struct perf_event *event)
+struct event_constraint *intel_pebs_constraints(struct perf_event *event)
 {
 	struct event_constraint *c;
 
@@ -446,7 +431,7 @@
 	return &emptyconstraint;
 }
 
-static void intel_pmu_pebs_enable(struct perf_event *event)
+void intel_pmu_pebs_enable(struct perf_event *event)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct hw_perf_event *hwc = &event->hw;
@@ -460,7 +445,7 @@
 		intel_pmu_lbr_enable(event);
 }
 
-static void intel_pmu_pebs_disable(struct perf_event *event)
+void intel_pmu_pebs_disable(struct perf_event *event)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct hw_perf_event *hwc = &event->hw;
@@ -475,7 +460,7 @@
 		intel_pmu_lbr_disable(event);
 }
 
-static void intel_pmu_pebs_enable_all(void)
+void intel_pmu_pebs_enable_all(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -483,7 +468,7 @@
 		wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled);
 }
 
-static void intel_pmu_pebs_disable_all(void)
+void intel_pmu_pebs_disable_all(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -508,6 +493,7 @@
 	unsigned long from = cpuc->lbr_entries[0].from;
 	unsigned long old_to, to = cpuc->lbr_entries[0].to;
 	unsigned long ip = regs->ip;
+	int is_64bit = 0;
 
 	/*
 	 * We don't need to fixup if the PEBS assist is fault like
@@ -559,7 +545,10 @@
 		} else
 			kaddr = (void *)to;
 
-		kernel_insn_init(&insn, kaddr);
+#ifdef CONFIG_X86_64
+		is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32);
+#endif
+		insn_init(&insn, kaddr, is_64bit);
 		insn_get_length(&insn);
 		to += insn.length;
 	} while (to < ip);
@@ -576,8 +565,6 @@
 	return 0;
 }
 
-static int intel_pmu_save_and_restart(struct perf_event *event);
-
 static void __intel_pmu_pebs_event(struct perf_event *event,
 				   struct pt_regs *iregs, void *__pebs)
 {
@@ -716,7 +703,7 @@
  * BTS, PEBS probe and setup
  */
 
-static void intel_ds_init(void)
+void intel_ds_init(void)
 {
 	/*
 	 * No support for 32bit formats
@@ -749,15 +736,3 @@
 		}
 	}
 }
-
-#else /* CONFIG_CPU_SUP_INTEL */
-
-static void reserve_ds_buffers(void)
-{
-}
-
-static void release_ds_buffers(void)
-{
-}
-
-#endif /* CONFIG_CPU_SUP_INTEL */
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event_intel_lbr.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event_intel_lbr.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event_intel_lbr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event_intel_lbr.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,10 @@
-#ifdef CONFIG_CPU_SUP_INTEL
+#include <linux/perf_event.h>
+#include <linux/types.h>
+
+#include <asm/perf_event.h>
+#include <asm/msr.h>
+
+#include "perf_event.h"
 
 enum {
 	LBR_FORMAT_32		= 0x00,
@@ -48,7 +54,7 @@
 	}
 }
 
-static void intel_pmu_lbr_reset(void)
+void intel_pmu_lbr_reset(void)
 {
 	if (!x86_pmu.lbr_nr)
 		return;
@@ -59,7 +65,7 @@
 		intel_pmu_lbr_reset_64();
 }
 
-static void intel_pmu_lbr_enable(struct perf_event *event)
+void intel_pmu_lbr_enable(struct perf_event *event)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -81,7 +87,7 @@
 	cpuc->lbr_users++;
 }
 
-static void intel_pmu_lbr_disable(struct perf_event *event)
+void intel_pmu_lbr_disable(struct perf_event *event)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -95,7 +101,7 @@
 		__intel_pmu_lbr_disable();
 }
 
-static void intel_pmu_lbr_enable_all(void)
+void intel_pmu_lbr_enable_all(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -103,7 +109,7 @@
 		__intel_pmu_lbr_enable();
 }
 
-static void intel_pmu_lbr_disable_all(void)
+void intel_pmu_lbr_disable_all(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -178,7 +184,7 @@
 	cpuc->lbr_stack.nr = i;
 }
 
-static void intel_pmu_lbr_read(void)
+void intel_pmu_lbr_read(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -191,7 +197,7 @@
 		intel_pmu_lbr_read_64(cpuc);
 }
 
-static void intel_pmu_lbr_init_core(void)
+void intel_pmu_lbr_init_core(void)
 {
 	x86_pmu.lbr_nr     = 4;
 	x86_pmu.lbr_tos    = 0x01c9;
@@ -199,7 +205,7 @@
 	x86_pmu.lbr_to     = 0x60;
 }
 
-static void intel_pmu_lbr_init_nhm(void)
+void intel_pmu_lbr_init_nhm(void)
 {
 	x86_pmu.lbr_nr     = 16;
 	x86_pmu.lbr_tos    = 0x01c9;
@@ -207,12 +213,10 @@
 	x86_pmu.lbr_to     = 0x6c0;
 }
 
-static void intel_pmu_lbr_init_atom(void)
+void intel_pmu_lbr_init_atom(void)
 {
 	x86_pmu.lbr_nr	   = 8;
 	x86_pmu.lbr_tos    = 0x01c9;
 	x86_pmu.lbr_from   = 0x40;
 	x86_pmu.lbr_to     = 0x60;
 }
-
-#endif /* CONFIG_CPU_SUP_INTEL */
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event_p4.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event_p4.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event_p4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event_p4.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,9 +7,13 @@
  *  For licencing details see kernel-base/COPYING
  */
 
-#ifdef CONFIG_CPU_SUP_INTEL
+#include <linux/perf_event.h>
 
 #include <asm/perf_event_p4.h>
+#include <asm/hardirq.h>
+#include <asm/apic.h>
+
+#include "perf_event.h"
 
 #define P4_CNTR_LIMIT 3
 /*
@@ -1264,7 +1268,7 @@
 	}
 
 done:
-	return num ? -ENOSPC : 0;
+	return num ? -EINVAL : 0;
 }
 
 static __initconst const struct x86_pmu p4_pmu = {
@@ -1303,7 +1307,7 @@
 	.perfctr_second_write	= 1,
 };
 
-static __init int p4_pmu_init(void)
+__init int p4_pmu_init(void)
 {
 	unsigned int low, high;
 
@@ -1326,5 +1330,3 @@
 
 	return 0;
 }
-
-#endif /* CONFIG_CPU_SUP_INTEL */
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event_p6.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event_p6.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/perf_event_p6.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/perf_event_p6.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,7 @@
-#ifdef CONFIG_CPU_SUP_INTEL
+#include <linux/perf_event.h>
+#include <linux/types.h>
+
+#include "perf_event.h"
 
 /*
  * Not sure about some of these
@@ -114,7 +117,7 @@
 	.event_constraints	= p6_event_constraints,
 };
 
-static __init int p6_pmu_init(void)
+__init int p6_pmu_init(void)
 {
 	switch (boot_cpu_data.x86_model) {
 	case 1:
@@ -138,5 +141,3 @@
 
 	return 0;
 }
-
-#endif /* CONFIG_CPU_SUP_INTEL */
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/proc.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/proc.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/proc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/proc.c	2012-01-04 18:55:44.000000000 -0500
@@ -85,6 +85,8 @@
 		seq_printf(m, "stepping\t: %d\n", c->x86_mask);
 	else
 		seq_printf(m, "stepping\t: unknown\n");
+	if (c->microcode)
+		seq_printf(m, "microcode\t: 0x%x\n", c->microcode);
 
 	if (cpu_has(c, X86_FEATURE_TSC)) {
 		unsigned int freq = cpufreq_quick_get(cpu);
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/cpu/rdrand.c linux-libre-3.2-gnu/arch/x86/kernel/cpu/rdrand.c
--- linux-libre-3.1-gnu/arch/x86/kernel/cpu/rdrand.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/kernel/cpu/rdrand.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the Linux kernel.
+ *
+ * Copyright (c) 2011, Intel Corporation
+ * Authors: Fenghua Yu <fenghua.yu@intel.com>,
+ *          H. Peter Anvin <hpa@linux.intel.com>
+ *
+ * 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.
+ *
+ */
+
+#include <asm/processor.h>
+#include <asm/archrandom.h>
+#include <asm/sections.h>
+
+static int __init x86_rdrand_setup(char *s)
+{
+	setup_clear_cpu_cap(X86_FEATURE_RDRAND);
+	return 1;
+}
+__setup("nordrand", x86_rdrand_setup);
+
+/* We can't use arch_get_random_long() here since alternatives haven't run */
+static inline int rdrand_long(unsigned long *v)
+{
+	int ok;
+	asm volatile("1: " RDRAND_LONG "\n\t"
+		     "jc 2f\n\t"
+		     "decl %0\n\t"
+		     "jnz 1b\n\t"
+		     "2:"
+		     : "=r" (ok), "=a" (*v)
+		     : "0" (RDRAND_RETRY_LOOPS));
+	return ok;
+}
+
+/*
+ * Force a reseed cycle; we are architecturally guaranteed a reseed
+ * after no more than 512 128-bit chunks of random data.  This also
+ * acts as a test of the CPU capability.
+ */
+#define RESEED_LOOP ((512*128)/sizeof(unsigned long))
+
+void __cpuinit x86_init_rdrand(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_ARCH_RANDOM
+	unsigned long tmp;
+	int i, count, ok;
+
+	if (!cpu_has(c, X86_FEATURE_RDRAND))
+		return;		/* Nothing to do */
+
+	for (count = i = 0; i < RESEED_LOOP; i++) {
+		ok = rdrand_long(&tmp);
+		if (ok)
+			count++;
+	}
+
+	if (count != RESEED_LOOP)
+		clear_cpu_cap(c, X86_FEATURE_RDRAND);
+#endif
+}
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/crash.c linux-libre-3.2-gnu/arch/x86/kernel/crash.c
--- linux-libre-3.1-gnu/arch/x86/kernel/crash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/crash.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,15 +32,12 @@
 
 #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
 
-static void kdump_nmi_callback(int cpu, struct die_args *args)
+static void kdump_nmi_callback(int cpu, struct pt_regs *regs)
 {
-	struct pt_regs *regs;
 #ifdef CONFIG_X86_32
 	struct pt_regs fixed_regs;
 #endif
 
-	regs = args->regs;
-
 #ifdef CONFIG_X86_32
 	if (!user_mode_vm(regs)) {
 		crash_fixup_ss_esp(&fixed_regs, regs);
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/devicetree.c linux-libre-3.2-gnu/arch/x86/kernel/devicetree.c
--- linux-libre-3.1-gnu/arch/x86/kernel/devicetree.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/devicetree.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,7 @@
  * Architecture specific OF callbacks.
  */
 #include <linux/bootmem.h>
+#include <linux/export.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/list.h>
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/dumpstack_32.c linux-libre-3.2-gnu/arch/x86/kernel/dumpstack_32.c
--- linux-libre-3.1-gnu/arch/x86/kernel/dumpstack_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/dumpstack_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -116,16 +116,16 @@
 		for (i = 0; i < code_len; i++, ip++) {
 			if (ip < (u8 *)PAGE_OFFSET ||
 					probe_kernel_address(ip, c)) {
-				printk(" Bad EIP value.");
+				printk(KERN_CONT " Bad EIP value.");
 				break;
 			}
 			if (ip == (u8 *)regs->ip)
-				printk("<%02x> ", c);
+				printk(KERN_CONT "<%02x> ", c);
 			else
-				printk("%02x ", c);
+				printk(KERN_CONT "%02x ", c);
 		}
 	}
-	printk("\n");
+	printk(KERN_CONT "\n");
 }
 
 int is_valid_bugaddr(unsigned long ip)
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/dumpstack_64.c linux-libre-3.2-gnu/arch/x86/kernel/dumpstack_64.c
--- linux-libre-3.1-gnu/arch/x86/kernel/dumpstack_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/dumpstack_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -284,16 +284,16 @@
 		for (i = 0; i < code_len; i++, ip++) {
 			if (ip < (u8 *)PAGE_OFFSET ||
 					probe_kernel_address(ip, c)) {
-				printk(" Bad RIP value.");
+				printk(KERN_CONT " Bad RIP value.");
 				break;
 			}
 			if (ip == (u8 *)regs->ip)
-				printk("<%02x> ", c);
+				printk(KERN_CONT "<%02x> ", c);
 			else
-				printk("%02x ", c);
+				printk(KERN_CONT "%02x ", c);
 		}
 	}
-	printk("\n");
+	printk(KERN_CONT "\n");
 }
 
 int is_valid_bugaddr(unsigned long ip)
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/e820.c linux-libre-3.2-gnu/arch/x86/kernel/e820.c
--- linux-libre-3.1-gnu/arch/x86/kernel/e820.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/e820.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/crash_dump.h>
+#include <linux/export.h>
 #include <linux/bootmem.h>
 #include <linux/pfn.h>
 #include <linux/suspend.h>
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/entry_64.S linux-libre-3.2-gnu/arch/x86/kernel/entry_64.S
--- linux-libre-3.1-gnu/arch/x86/kernel/entry_64.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/entry_64.S	2012-01-04 18:55:44.000000000 -0500
@@ -331,10 +331,15 @@
 1:	incl PER_CPU_VAR(irq_count)
 	jne 2f
 	mov PER_CPU_VAR(irq_stack_ptr),%rsp
-	EMPTY_FRAME 0
+	CFI_DEF_CFA_REGISTER	rsi
 
 2:	/* Store previous stack value */
 	pushq %rsi
+	CFI_ESCAPE	0x0f /* DW_CFA_def_cfa_expression */, 6, \
+			0x77 /* DW_OP_breg7 */, 0, \
+			0x06 /* DW_OP_deref */, \
+			0x08 /* DW_OP_const1u */, SS+8-RBP, \
+			0x22 /* DW_OP_plus */
 	/* We entered an interrupt context - irqs are off: */
 	TRACE_IRQS_OFF
 	.endm
@@ -788,7 +793,6 @@
 	subq $ORIG_RAX-RBP, %rsp
 	CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP
 	SAVE_ARGS_IRQ
-	PARTIAL_FRAME 0
 	call \func
 	.endm
 
@@ -813,10 +817,10 @@
 
 	/* Restore saved previous stack */
 	popq %rsi
-	leaq 16(%rsi), %rsp
-
+	CFI_DEF_CFA_REGISTER	rsi
+	leaq ARGOFFSET-RBP(%rsi), %rsp
 	CFI_DEF_CFA_REGISTER	rsp
-	CFI_ADJUST_CFA_OFFSET	-16
+	CFI_ADJUST_CFA_OFFSET	RBP-ARGOFFSET
 
 exit_intr:
 	GET_THREAD_INFO(%rcx)
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/hpet.c linux-libre-3.2-gnu/arch/x86/kernel/hpet.c
--- linux-libre-3.1-gnu/arch/x86/kernel/hpet.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/hpet.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
+#include <linux/export.h>
 #include <linux/sysdev.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -1048,6 +1049,14 @@
 }
 EXPORT_SYMBOL_GPL(hpet_rtc_timer_init);
 
+static void hpet_disable_rtc_channel(void)
+{
+	unsigned long cfg;
+	cfg = hpet_readl(HPET_T1_CFG);
+	cfg &= ~HPET_TN_ENABLE;
+	hpet_writel(cfg, HPET_T1_CFG);
+}
+
 /*
  * The functions below are called from rtc driver.
  * Return 0 if HPET is not being used.
@@ -1059,6 +1068,9 @@
 		return 0;
 
 	hpet_rtc_flags &= ~bit_mask;
+	if (unlikely(!hpet_rtc_flags))
+		hpet_disable_rtc_channel();
+
 	return 1;
 }
 EXPORT_SYMBOL_GPL(hpet_mask_rtc_irq_bit);
@@ -1124,15 +1136,11 @@
 
 static void hpet_rtc_timer_reinit(void)
 {
-	unsigned int cfg, delta;
+	unsigned int delta;
 	int lost_ints = -1;
 
-	if (unlikely(!hpet_rtc_flags)) {
-		cfg = hpet_readl(HPET_T1_CFG);
-		cfg &= ~HPET_TN_ENABLE;
-		hpet_writel(cfg, HPET_T1_CFG);
-		return;
-	}
+	if (unlikely(!hpet_rtc_flags))
+		hpet_disable_rtc_channel();
 
 	if (!(hpet_rtc_flags & RTC_PIE) || hpet_pie_limit)
 		delta = hpet_default_delta;
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/irq_64.c linux-libre-3.2-gnu/arch/x86/kernel/irq_64.c
--- linux-libre-3.1-gnu/arch/x86/kernel/irq_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/irq_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,9 @@
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 	u64 curbase = (u64)task_stack_page(current);
 
+	if (user_mode_vm(regs))
+		return;
+
 	WARN_ONCE(regs->sp >= curbase &&
 		  regs->sp <= curbase + THREAD_SIZE &&
 		  regs->sp <  curbase + sizeof(struct thread_info) +
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/irq.c linux-libre-3.2-gnu/arch/x86/kernel/irq.c
--- linux-libre-3.1-gnu/arch/x86/kernel/irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/smp.h>
 #include <linux/ftrace.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 
 #include <asm/apic.h>
 #include <asm/io_apic.h>
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/jump_label.c linux-libre-3.2-gnu/arch/x86/kernel/jump_label.c
--- linux-libre-3.1-gnu/arch/x86/kernel/jump_label.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/jump_label.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,8 +24,9 @@
 	} __attribute__((packed));
 };
 
-void arch_jump_label_transform(struct jump_entry *entry,
-			       enum jump_label_type type)
+static void __jump_label_transform(struct jump_entry *entry,
+				   enum jump_label_type type,
+				   void *(*poker)(void *, const void *, size_t))
 {
 	union jump_code_union code;
 
@@ -35,17 +36,24 @@
 				(entry->code + JUMP_LABEL_NOP_SIZE);
 	} else
 		memcpy(&code, ideal_nops[NOP_ATOMIC5], JUMP_LABEL_NOP_SIZE);
+
+	(*poker)((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE);
+}
+
+void arch_jump_label_transform(struct jump_entry *entry,
+			       enum jump_label_type type)
+{
 	get_online_cpus();
 	mutex_lock(&text_mutex);
-	text_poke_smp((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE);
+	__jump_label_transform(entry, type, text_poke_smp);
 	mutex_unlock(&text_mutex);
 	put_online_cpus();
 }
 
-void arch_jump_label_text_poke_early(jump_label_t addr)
+void arch_jump_label_transform_static(struct jump_entry *entry,
+				      enum jump_label_type type)
 {
-	text_poke_early((void *)addr, ideal_nops[NOP_ATOMIC5],
-			JUMP_LABEL_NOP_SIZE);
+	__jump_label_transform(entry, type, text_poke_early);
 }
 
 #endif
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/kgdb.c linux-libre-3.2-gnu/arch/x86/kernel/kgdb.c
--- linux-libre-3.1-gnu/arch/x86/kernel/kgdb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/kgdb.c	2012-01-04 18:55:44.000000000 -0500
@@ -511,28 +511,37 @@
 
 static int was_in_debug_nmi[NR_CPUS];
 
-static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+static int kgdb_nmi_handler(unsigned int cmd, struct pt_regs *regs)
 {
-	struct pt_regs *regs = args->regs;
-
 	switch (cmd) {
-	case DIE_NMI:
+	case NMI_LOCAL:
 		if (atomic_read(&kgdb_active) != -1) {
 			/* KGDB CPU roundup */
 			kgdb_nmicallback(raw_smp_processor_id(), regs);
 			was_in_debug_nmi[raw_smp_processor_id()] = 1;
 			touch_nmi_watchdog();
-			return NOTIFY_STOP;
+			return NMI_HANDLED;
 		}
-		return NOTIFY_DONE;
+		break;
 
-	case DIE_NMIUNKNOWN:
+	case NMI_UNKNOWN:
 		if (was_in_debug_nmi[raw_smp_processor_id()]) {
 			was_in_debug_nmi[raw_smp_processor_id()] = 0;
-			return NOTIFY_STOP;
+			return NMI_HANDLED;
 		}
-		return NOTIFY_DONE;
+		break;
+	default:
+		/* do nothing */
+		break;
+	}
+	return NMI_DONE;
+}
 
+static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+{
+	struct pt_regs *regs = args->regs;
+
+	switch (cmd) {
 	case DIE_DEBUG:
 		if (atomic_read(&kgdb_cpu_doing_single_step) != -1) {
 			if (user_mode(regs))
@@ -590,11 +599,6 @@
 
 static struct notifier_block kgdb_notifier = {
 	.notifier_call	= kgdb_notify,
-
-	/*
-	 * Lowest-prio notifier priority, we want to be notified last:
-	 */
-	.priority	= NMI_LOCAL_LOW_PRIOR,
 };
 
 /**
@@ -605,7 +609,31 @@
  */
 int kgdb_arch_init(void)
 {
-	return register_die_notifier(&kgdb_notifier);
+	int retval;
+
+	retval = register_die_notifier(&kgdb_notifier);
+	if (retval)
+		goto out;
+
+	retval = register_nmi_handler(NMI_LOCAL, kgdb_nmi_handler,
+					0, "kgdb");
+	if (retval)
+		goto out1;
+
+	retval = register_nmi_handler(NMI_UNKNOWN, kgdb_nmi_handler,
+					0, "kgdb");
+
+	if (retval)
+		goto out2;
+
+	return retval;
+
+out2:
+	unregister_nmi_handler(NMI_LOCAL, "kgdb");
+out1:
+	unregister_die_notifier(&kgdb_notifier);
+out:
+	return retval;
 }
 
 static void kgdb_hw_overflow_handler(struct perf_event *event,
@@ -673,6 +701,8 @@
 			breakinfo[i].pev = NULL;
 		}
 	}
+	unregister_nmi_handler(NMI_UNKNOWN, "kgdb");
+	unregister_nmi_handler(NMI_LOCAL, "kgdb");
 	unregister_die_notifier(&kgdb_notifier);
 }
 
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/kprobes.c linux-libre-3.2-gnu/arch/x86/kernel/kprobes.c
--- linux-libre-3.1-gnu/arch/x86/kernel/kprobes.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/kprobes.c	2012-01-04 18:55:44.000000000 -0500
@@ -75,8 +75,11 @@
 	/*
 	 * Undefined/reserved opcodes, conditional jump, Opcode Extension
 	 * Groups, and some special opcodes can not boost.
+	 * This is non-const and volatile to keep gcc from statically
+	 * optimizing it out, as variable_test_bit makes gcc think only
+	 * *(unsigned long*) is used. 
 	 */
-static const u32 twobyte_is_boostable[256 / 32] = {
+static volatile u32 twobyte_is_boostable[256 / 32] = {
 	/*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f          */
 	/*      ----------------------------------------------          */
 	W(0x00, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0) | /* 00 */
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/kvmclock.c linux-libre-3.2-gnu/arch/x86/kernel/kvmclock.c
--- linux-libre-3.1-gnu/arch/x86/kernel/kvmclock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/kvmclock.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,9 +74,10 @@
 	struct pvclock_vcpu_time_info *src;
 	cycle_t ret;
 
-	src = &get_cpu_var(hv_clock);
+	preempt_disable_notrace();
+	src = &__get_cpu_var(hv_clock);
 	ret = pvclock_clocksource_read(src);
-	put_cpu_var(hv_clock);
+	preempt_enable_notrace();
 	return ret;
 }
 
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/Makefile linux-libre-3.2-gnu/arch/x86/kernel/Makefile
--- linux-libre-3.1-gnu/arch/x86/kernel/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,7 @@
 
 obj-y			:= process_$(BITS).o signal.o entry_$(BITS).o
 obj-y			+= traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
-obj-y			+= time.o ioport.o ldt.o dumpstack.o
+obj-y			+= time.o ioport.o ldt.o dumpstack.o nmi.o
 obj-y			+= setup.o x86_init.o i8259.o irqinit.o jump_label.o
 obj-$(CONFIG_IRQ_WORK)  += irq_work.o
 obj-y			+= probe_roms.o
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/microcode_amd.c linux-libre-3.2-gnu/arch/x86/kernel/microcode_amd.c
--- linux-libre-3.1-gnu/arch/x86/kernel/microcode_amd.c	2012-03-19 21:28:29.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/microcode_amd.c	2012-03-19 21:29:19.000000000 -0400
@@ -74,14 +74,13 @@
 static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
 {
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
-	u32 dummy;
 
 	if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
 		pr_warning("CPU%d: family %d not supported\n", cpu, c->x86);
 		return -1;
 	}
 
-	rdmsr(MSR_AMD64_PATCH_LEVEL, csig->rev, dummy);
+	csig->rev = c->microcode;
 	pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);
 
 	return 0;
@@ -130,6 +129,7 @@
 	int cpu_num = raw_smp_processor_id();
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
 	struct microcode_amd *mc_amd = uci->mc;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
 	/* We should bind the task to the CPU */
 	BUG_ON(cpu_num != cpu);
@@ -150,6 +150,7 @@
 
 	pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev);
 	uci->cpu_sig.rev = rev;
+	c->microcode = rev;
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/microcode_core.c linux-libre-3.2-gnu/arch/x86/kernel/microcode_core.c
--- linux-libre-3.1-gnu/arch/x86/kernel/microcode_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/microcode_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -256,7 +256,7 @@
 	return 0;
 }
 
-static void microcode_dev_exit(void)
+static void __exit microcode_dev_exit(void)
 {
 	misc_deregister(&microcode_dev);
 }
@@ -483,7 +483,13 @@
 		sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
 		pr_debug("CPU%d removed\n", cpu);
 		break;
-	case CPU_DEAD:
+
+	/*
+	 * When a CPU goes offline, don't free up or invalidate the copy of
+	 * the microcode in kernel memory, so that we can reuse it when the
+	 * CPU comes back online without unnecessarily requesting the userspace
+	 * for it again.
+	 */
 	case CPU_UP_CANCELED_FROZEN:
 		/* The CPU refused to come up during a system resume */
 		microcode_fini_cpu(cpu);
@@ -513,10 +519,8 @@
 
 	microcode_pdev = platform_device_register_simple("microcode", -1,
 							 NULL, 0);
-	if (IS_ERR(microcode_pdev)) {
-		microcode_dev_exit();
+	if (IS_ERR(microcode_pdev))
 		return PTR_ERR(microcode_pdev);
-	}
 
 	get_online_cpus();
 	mutex_lock(&microcode_mutex);
@@ -526,14 +530,12 @@
 	mutex_unlock(&microcode_mutex);
 	put_online_cpus();
 
-	if (error) {
-		platform_device_unregister(microcode_pdev);
-		return error;
-	}
+	if (error)
+		goto out_pdev;
 
 	error = microcode_dev_init();
 	if (error)
-		return error;
+		goto out_sysdev_driver;
 
 	register_syscore_ops(&mc_syscore_ops);
 	register_hotcpu_notifier(&mc_cpu_notifier);
@@ -542,6 +544,20 @@
 		" <tigran@aivazian.fsnet.co.uk>, Peter Oruba\n");
 
 	return 0;
+
+out_sysdev_driver:
+	get_online_cpus();
+	mutex_lock(&microcode_mutex);
+
+	sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver);
+
+	mutex_unlock(&microcode_mutex);
+	put_online_cpus();
+
+out_pdev:
+	platform_device_unregister(microcode_pdev);
+	return error;
+
 }
 module_init(microcode_init);
 
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/microcode_intel.c linux-libre-3.2-gnu/arch/x86/kernel/microcode_intel.c
--- linux-libre-3.1-gnu/arch/x86/kernel/microcode_intel.c	2012-03-19 21:28:33.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/microcode_intel.c	2012-03-19 21:29:26.000000000 -0400
@@ -161,12 +161,7 @@
 		csig->pf = 1 << ((val[1] >> 18) & 7);
 	}
 
-	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
-	/* see notes above for revision 1.07.  Apparent chip bug */
-	sync_core();
-	/* get the current revision from MSR 0x8B */
-	rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev);
-
+	csig->rev = c->microcode;
 	pr_info("CPU%d sig=0x%x, pf=0x%x, revision=0x%x\n",
 		cpu_num, csig->sig, csig->pf, csig->rev);
 
@@ -299,9 +294,9 @@
 	struct microcode_intel *mc_intel;
 	struct ucode_cpu_info *uci;
 	unsigned int val[2];
-	int cpu_num;
+	int cpu_num = raw_smp_processor_id();
+	struct cpuinfo_x86 *c = &cpu_data(cpu_num);
 
-	cpu_num = raw_smp_processor_id();
 	uci = ucode_cpu_info + cpu;
 	mc_intel = uci->mc;
 
@@ -317,7 +312,7 @@
 	      (unsigned long) mc_intel->bits >> 16 >> 16);
 	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
 
-	/* see notes above for revision 1.07.  Apparent chip bug */
+	/* As documented in the SDM: Do a CPUID 1 here */
 	sync_core();
 
 	/* get the current revision from MSR 0x8B */
@@ -335,6 +330,7 @@
 		(mc_intel->hdr.date >> 16) & 0xff);
 
 	uci->cpu_sig.rev = val[1];
+	c->microcode = val[1];
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/mpparse.c linux-libre-3.2-gnu/arch/x86/kernel/mpparse.c
--- linux-libre-3.1-gnu/arch/x86/kernel/mpparse.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/mpparse.c	2012-01-04 18:55:44.000000000 -0500
@@ -95,8 +95,8 @@
 	}
 #endif
 
+	set_bit(m->busid, mp_bus_not_pci);
 	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) {
-		set_bit(m->busid, mp_bus_not_pci);
 #if defined(CONFIG_EISA) || defined(CONFIG_MCA)
 		mp_bus_id_to_type[m->busid] = MP_BUS_ISA;
 #endif
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/nmi.c linux-libre-3.2-gnu/arch/x86/kernel/nmi.c
--- linux-libre-3.1-gnu/arch/x86/kernel/nmi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/kernel/nmi.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,435 @@
+/*
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
+ *  Copyright (C) 2011	Don Zickus Red Hat, Inc.
+ *
+ *  Pentium III FXSR, SSE support
+ *	Gareth Hughes <gareth@valinux.com>, May 2000
+ */
+
+/*
+ * Handle hardware traps and faults.
+ */
+#include <linux/spinlock.h>
+#include <linux/kprobes.h>
+#include <linux/kdebug.h>
+#include <linux/nmi.h>
+#include <linux/delay.h>
+#include <linux/hardirq.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+
+#include <linux/mca.h>
+
+#if defined(CONFIG_EDAC)
+#include <linux/edac.h>
+#endif
+
+#include <linux/atomic.h>
+#include <asm/traps.h>
+#include <asm/mach_traps.h>
+#include <asm/nmi.h>
+#include <asm/x86_init.h>
+
+#define NMI_MAX_NAMELEN	16
+struct nmiaction {
+	struct list_head list;
+	nmi_handler_t handler;
+	unsigned int flags;
+	char *name;
+};
+
+struct nmi_desc {
+	spinlock_t lock;
+	struct list_head head;
+};
+
+static struct nmi_desc nmi_desc[NMI_MAX] = 
+{
+	{
+		.lock = __SPIN_LOCK_UNLOCKED(&nmi_desc[0].lock),
+		.head = LIST_HEAD_INIT(nmi_desc[0].head),
+	},
+	{
+		.lock = __SPIN_LOCK_UNLOCKED(&nmi_desc[1].lock),
+		.head = LIST_HEAD_INIT(nmi_desc[1].head),
+	},
+
+};
+
+struct nmi_stats {
+	unsigned int normal;
+	unsigned int unknown;
+	unsigned int external;
+	unsigned int swallow;
+};
+
+static DEFINE_PER_CPU(struct nmi_stats, nmi_stats);
+
+static int ignore_nmis;
+
+int unknown_nmi_panic;
+/*
+ * Prevent NMI reason port (0x61) being accessed simultaneously, can
+ * only be used in NMI handler.
+ */
+static DEFINE_RAW_SPINLOCK(nmi_reason_lock);
+
+static int __init setup_unknown_nmi_panic(char *str)
+{
+	unknown_nmi_panic = 1;
+	return 1;
+}
+__setup("unknown_nmi_panic", setup_unknown_nmi_panic);
+
+#define nmi_to_desc(type) (&nmi_desc[type])
+
+static int notrace __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2b)
+{
+	struct nmi_desc *desc = nmi_to_desc(type);
+	struct nmiaction *a;
+	int handled=0;
+
+	rcu_read_lock();
+
+	/*
+	 * NMIs are edge-triggered, which means if you have enough
+	 * of them concurrently, you can lose some because only one
+	 * can be latched at any given time.  Walk the whole list
+	 * to handle those situations.
+	 */
+	list_for_each_entry_rcu(a, &desc->head, list)
+		handled += a->handler(type, regs);
+
+	rcu_read_unlock();
+
+	/* return total number of NMI events handled */
+	return handled;
+}
+
+static int __setup_nmi(unsigned int type, struct nmiaction *action)
+{
+	struct nmi_desc *desc = nmi_to_desc(type);
+	unsigned long flags;
+
+	spin_lock_irqsave(&desc->lock, flags);
+
+	/*
+	 * most handlers of type NMI_UNKNOWN never return because
+	 * they just assume the NMI is theirs.  Just a sanity check
+	 * to manage expectations
+	 */
+	WARN_ON_ONCE(type == NMI_UNKNOWN && !list_empty(&desc->head));
+
+	/*
+	 * some handlers need to be executed first otherwise a fake
+	 * event confuses some handlers (kdump uses this flag)
+	 */
+	if (action->flags & NMI_FLAG_FIRST)
+		list_add_rcu(&action->list, &desc->head);
+	else
+		list_add_tail_rcu(&action->list, &desc->head);
+	
+	spin_unlock_irqrestore(&desc->lock, flags);
+	return 0;
+}
+
+static struct nmiaction *__free_nmi(unsigned int type, const char *name)
+{
+	struct nmi_desc *desc = nmi_to_desc(type);
+	struct nmiaction *n;
+	unsigned long flags;
+
+	spin_lock_irqsave(&desc->lock, flags);
+
+	list_for_each_entry_rcu(n, &desc->head, list) {
+		/*
+		 * the name passed in to describe the nmi handler
+		 * is used as the lookup key
+		 */
+		if (!strcmp(n->name, name)) {
+			WARN(in_nmi(),
+				"Trying to free NMI (%s) from NMI context!\n", n->name);
+			list_del_rcu(&n->list);
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&desc->lock, flags);
+	synchronize_rcu();
+	return (n);
+}
+
+int register_nmi_handler(unsigned int type, nmi_handler_t handler,
+			unsigned long nmiflags, const char *devname)
+{
+	struct nmiaction *action;
+	int retval = -ENOMEM;
+
+	if (!handler)
+		return -EINVAL;
+
+	action = kzalloc(sizeof(struct nmiaction), GFP_KERNEL);
+	if (!action)
+		goto fail_action;
+
+	action->handler = handler;
+	action->flags = nmiflags;
+	action->name = kstrndup(devname, NMI_MAX_NAMELEN, GFP_KERNEL);
+	if (!action->name)
+		goto fail_action_name;
+
+	retval = __setup_nmi(type, action);
+
+	if (retval)
+		goto fail_setup_nmi;
+
+	return retval;
+
+fail_setup_nmi:
+	kfree(action->name);
+fail_action_name:
+	kfree(action);
+fail_action:	
+
+	return retval;
+}
+EXPORT_SYMBOL_GPL(register_nmi_handler);
+
+void unregister_nmi_handler(unsigned int type, const char *name)
+{
+	struct nmiaction *a;
+
+	a = __free_nmi(type, name);
+	if (a) {
+		kfree(a->name);
+		kfree(a);
+	}
+}
+
+EXPORT_SYMBOL_GPL(unregister_nmi_handler);
+
+static notrace __kprobes void
+pci_serr_error(unsigned char reason, struct pt_regs *regs)
+{
+	pr_emerg("NMI: PCI system error (SERR) for reason %02x on CPU %d.\n",
+		 reason, smp_processor_id());
+
+	/*
+	 * On some machines, PCI SERR line is used to report memory
+	 * errors. EDAC makes use of it.
+	 */
+#if defined(CONFIG_EDAC)
+	if (edac_handler_set()) {
+		edac_atomic_assert_error();
+		return;
+	}
+#endif
+
+	if (panic_on_unrecovered_nmi)
+		panic("NMI: Not continuing");
+
+	pr_emerg("Dazed and confused, but trying to continue\n");
+
+	/* Clear and disable the PCI SERR error line. */
+	reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_SERR;
+	outb(reason, NMI_REASON_PORT);
+}
+
+static notrace __kprobes void
+io_check_error(unsigned char reason, struct pt_regs *regs)
+{
+	unsigned long i;
+
+	pr_emerg(
+	"NMI: IOCK error (debug interrupt?) for reason %02x on CPU %d.\n",
+		 reason, smp_processor_id());
+	show_registers(regs);
+
+	if (panic_on_io_nmi)
+		panic("NMI IOCK error: Not continuing");
+
+	/* Re-enable the IOCK line, wait for a few seconds */
+	reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK;
+	outb(reason, NMI_REASON_PORT);
+
+	i = 20000;
+	while (--i) {
+		touch_nmi_watchdog();
+		udelay(100);
+	}
+
+	reason &= ~NMI_REASON_CLEAR_IOCHK;
+	outb(reason, NMI_REASON_PORT);
+}
+
+static notrace __kprobes void
+unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
+{
+	int handled;
+
+	/*
+	 * Use 'false' as back-to-back NMIs are dealt with one level up.
+	 * Of course this makes having multiple 'unknown' handlers useless
+	 * as only the first one is ever run (unless it can actually determine
+	 * if it caused the NMI)
+	 */
+	handled = nmi_handle(NMI_UNKNOWN, regs, false);
+	if (handled) {
+		__this_cpu_add(nmi_stats.unknown, handled);
+		return;
+	}
+
+	__this_cpu_add(nmi_stats.unknown, 1);
+
+#ifdef CONFIG_MCA
+	/*
+	 * Might actually be able to figure out what the guilty party
+	 * is:
+	 */
+	if (MCA_bus) {
+		mca_handle_nmi();
+		return;
+	}
+#endif
+	pr_emerg("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
+		 reason, smp_processor_id());
+
+	pr_emerg("Do you have a strange power saving mode enabled?\n");
+	if (unknown_nmi_panic || panic_on_unrecovered_nmi)
+		panic("NMI: Not continuing");
+
+	pr_emerg("Dazed and confused, but trying to continue\n");
+}
+
+static DEFINE_PER_CPU(bool, swallow_nmi);
+static DEFINE_PER_CPU(unsigned long, last_nmi_rip);
+
+static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
+{
+	unsigned char reason = 0;
+	int handled;
+	bool b2b = false;
+
+	/*
+	 * CPU-specific NMI must be processed before non-CPU-specific
+	 * NMI, otherwise we may lose it, because the CPU-specific
+	 * NMI can not be detected/processed on other CPUs.
+	 */
+
+	/*
+	 * Back-to-back NMIs are interesting because they can either
+	 * be two NMI or more than two NMIs (any thing over two is dropped
+	 * due to NMI being edge-triggered).  If this is the second half
+	 * of the back-to-back NMI, assume we dropped things and process
+	 * more handlers.  Otherwise reset the 'swallow' NMI behaviour
+	 */
+	if (regs->ip == __this_cpu_read(last_nmi_rip))
+		b2b = true;
+	else
+		__this_cpu_write(swallow_nmi, false);
+
+	__this_cpu_write(last_nmi_rip, regs->ip);
+
+	handled = nmi_handle(NMI_LOCAL, regs, b2b);
+	__this_cpu_add(nmi_stats.normal, handled);
+	if (handled) {
+		/*
+		 * There are cases when a NMI handler handles multiple
+		 * events in the current NMI.  One of these events may
+		 * be queued for in the next NMI.  Because the event is
+		 * already handled, the next NMI will result in an unknown
+		 * NMI.  Instead lets flag this for a potential NMI to
+		 * swallow.
+		 */
+		if (handled > 1)
+			__this_cpu_write(swallow_nmi, true);
+		return;
+	}
+
+	/* Non-CPU-specific NMI: NMI sources can be processed on any CPU */
+	raw_spin_lock(&nmi_reason_lock);
+	reason = x86_platform.get_nmi_reason();
+
+	if (reason & NMI_REASON_MASK) {
+		if (reason & NMI_REASON_SERR)
+			pci_serr_error(reason, regs);
+		else if (reason & NMI_REASON_IOCHK)
+			io_check_error(reason, regs);
+#ifdef CONFIG_X86_32
+		/*
+		 * Reassert NMI in case it became active
+		 * meanwhile as it's edge-triggered:
+		 */
+		reassert_nmi();
+#endif
+		__this_cpu_add(nmi_stats.external, 1);
+		raw_spin_unlock(&nmi_reason_lock);
+		return;
+	}
+	raw_spin_unlock(&nmi_reason_lock);
+
+	/*
+	 * Only one NMI can be latched at a time.  To handle
+	 * this we may process multiple nmi handlers at once to
+	 * cover the case where an NMI is dropped.  The downside
+	 * to this approach is we may process an NMI prematurely,
+	 * while its real NMI is sitting latched.  This will cause
+	 * an unknown NMI on the next run of the NMI processing.
+	 *
+	 * We tried to flag that condition above, by setting the
+	 * swallow_nmi flag when we process more than one event.
+	 * This condition is also only present on the second half
+	 * of a back-to-back NMI, so we flag that condition too.
+	 *
+	 * If both are true, we assume we already processed this
+	 * NMI previously and we swallow it.  Otherwise we reset
+	 * the logic.
+	 *
+	 * There are scenarios where we may accidentally swallow
+	 * a 'real' unknown NMI.  For example, while processing
+	 * a perf NMI another perf NMI comes in along with a
+	 * 'real' unknown NMI.  These two NMIs get combined into
+	 * one (as descibed above).  When the next NMI gets
+	 * processed, it will be flagged by perf as handled, but
+	 * noone will know that there was a 'real' unknown NMI sent
+	 * also.  As a result it gets swallowed.  Or if the first
+	 * perf NMI returns two events handled then the second
+	 * NMI will get eaten by the logic below, again losing a
+	 * 'real' unknown NMI.  But this is the best we can do
+	 * for now.
+	 */
+	if (b2b && __this_cpu_read(swallow_nmi))
+		__this_cpu_add(nmi_stats.swallow, 1);
+	else
+		unknown_nmi_error(reason, regs);
+}
+
+dotraplinkage notrace __kprobes void
+do_nmi(struct pt_regs *regs, long error_code)
+{
+	nmi_enter();
+
+	inc_irq_stat(__nmi_count);
+
+	if (!ignore_nmis)
+		default_do_nmi(regs);
+
+	nmi_exit();
+}
+
+void stop_nmi(void)
+{
+	ignore_nmis++;
+}
+
+void restart_nmi(void)
+{
+	ignore_nmis--;
+}
+
+/* reset the back-to-back NMI logic */
+void local_touch_nmi(void)
+{
+	__this_cpu_write(last_nmi_rip, 0);
+}
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/pci-dma.c linux-libre-3.2-gnu/arch/x86/kernel/pci-dma.c
--- linux-libre-3.1-gnu/arch/x86/kernel/pci-dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/pci-dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/dma-debug.h>
 #include <linux/dmar.h>
+#include <linux/export.h>
 #include <linux/bootmem.h>
 #include <linux/gfp.h>
 #include <linux/pci.h>
@@ -117,8 +118,8 @@
 }
 
 /*
- * See <Documentation/x86_64/boot-options.txt> for the iommu kernel parameter
- * documentation.
+ * See <Documentation/x86/x86_64/boot-options.txt> for the iommu kernel
+ * parameter documentation.
  */
 static __init int iommu_setup(char *p)
 {
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/probe_roms.c linux-libre-3.2-gnu/arch/x86/kernel/probe_roms.c
--- linux-libre-3.1-gnu/arch/x86/kernel/probe_roms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/probe_roms.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,9 +10,9 @@
 #include <linux/dmi.h>
 #include <linux/pfn.h>
 #include <linux/pci.h>
-#include <asm/pci-direct.h>
-
+#include <linux/export.h>
 
+#include <asm/pci-direct.h>
 #include <asm/e820.h>
 #include <asm/mmzone.h>
 #include <asm/setup.h>
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/process_32.c linux-libre-3.2-gnu/arch/x86/kernel/process_32.c
--- linux-libre-3.1-gnu/arch/x86/kernel/process_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/process_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -57,6 +57,7 @@
 #include <asm/idle.h>
 #include <asm/syscalls.h>
 #include <asm/debugreg.h>
+#include <asm/nmi.h>
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
@@ -107,6 +108,7 @@
 			if (cpu_is_offline(cpu))
 				play_dead();
 
+			local_touch_nmi();
 			local_irq_disable();
 			/* Don't trace irqs off for idle */
 			stop_critical_timings();
@@ -262,7 +264,7 @@
 
 
 /*
- *	switch_to(x,yn) should switch tasks from x to y.
+ *	switch_to(x,y) should switch tasks from x to y.
  *
  * We fsave/fwait so that an exception goes off at the right time
  * (as a call from the fsave or fwait in effect) rather than to
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/process_64.c linux-libre-3.2-gnu/arch/x86/kernel/process_64.c
--- linux-libre-3.1-gnu/arch/x86/kernel/process_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/process_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -51,6 +51,7 @@
 #include <asm/idle.h>
 #include <asm/syscalls.h>
 #include <asm/debugreg.h>
+#include <asm/nmi.h>
 
 asmlinkage extern void ret_from_fork(void);
 
@@ -133,6 +134,7 @@
 			 * from here on, until they go to idle.
 			 * Otherwise, idle callbacks can misfire.
 			 */
+			local_touch_nmi();
 			local_irq_disable();
 			enter_idle();
 			/* Don't trace irqs off for idle */
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/process.c linux-libre-3.2-gnu/arch/x86/kernel/process.c
--- linux-libre-3.1-gnu/arch/x86/kernel/process.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/process.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,7 +49,7 @@
 void free_thread_info(struct thread_info *ti)
 {
 	free_thread_xstate(ti->task);
-	free_pages((unsigned long)ti, get_order(THREAD_SIZE));
+	free_pages((unsigned long)ti, THREAD_ORDER);
 }
 
 void arch_task_cache_init(void)
@@ -403,6 +403,14 @@
 EXPORT_SYMBOL(default_idle);
 #endif
 
+bool set_pm_idle_to_default(void)
+{
+	bool ret = !!pm_idle;
+
+	pm_idle = default_idle;
+
+	return ret;
+}
 void stop_this_cpu(void *dummy)
 {
 	local_irq_disable();
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/quirks.c linux-libre-3.2-gnu/arch/x86/kernel/quirks.c
--- linux-libre-3.1-gnu/arch/x86/kernel/quirks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/quirks.c	2012-01-04 18:55:44.000000000 -0500
@@ -553,4 +553,17 @@
 			quirk_amd_nb_node);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_LINK,
 			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F0,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F1,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F2,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F4,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F5,
+			quirk_amd_nb_node);
+
 #endif
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/reboot.c linux-libre-3.2-gnu/arch/x86/kernel/reboot.c
--- linux-libre-3.1-gnu/arch/x86/kernel/reboot.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/reboot.c	2012-01-04 18:55:44.000000000 -0500
@@ -124,7 +124,7 @@
  */
 
 /*
- * Some machines require the "reboot=b"  commandline option,
+ * Some machines require the "reboot=b" or "reboot=k"  commandline options,
  * this quirk makes that automatic.
  */
 static int __init set_bios_reboot(const struct dmi_system_id *d)
@@ -136,6 +136,15 @@
 	return 0;
 }
 
+static int __init set_kbd_reboot(const struct dmi_system_id *d)
+{
+	if (reboot_type != BOOT_KBD) {
+		reboot_type = BOOT_KBD;
+		printk(KERN_INFO "%s series board detected. Selecting KBD-method for reboot.\n", d->ident);
+	}
+	return 0;
+}
+
 static struct dmi_system_id __initdata reboot_dmi_table[] = {
 	{	/* Handle problems with rebooting on Dell E520's */
 		.callback = set_bios_reboot,
@@ -295,7 +304,7 @@
 		},
 	},
 	{ /* Handle reboot issue on Acer Aspire one */
-		.callback = set_bios_reboot,
+		.callback = set_kbd_reboot,
 		.ident = "Acer Aspire One A110",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -443,6 +452,14 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6420"),
 		},
 	},
+	{	/* Handle problems with rebooting on the OptiPlex 990. */
+		.callback = set_pci_reboot,
+		.ident = "Dell OptiPlex 990",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"),
+		},
+	},
 	{ }
 };
 
@@ -464,7 +481,7 @@
 	}
 }
 
-static void vmxoff_nmi(int cpu, struct die_args *args)
+static void vmxoff_nmi(int cpu, struct pt_regs *regs)
 {
 	cpu_emergency_vmxoff();
 }
@@ -736,14 +753,10 @@
 
 static atomic_t waiting_for_crash_ipi;
 
-static int crash_nmi_callback(struct notifier_block *self,
-			unsigned long val, void *data)
+static int crash_nmi_callback(unsigned int val, struct pt_regs *regs)
 {
 	int cpu;
 
-	if (val != DIE_NMI)
-		return NOTIFY_OK;
-
 	cpu = raw_smp_processor_id();
 
 	/* Don't do anything if this handler is invoked on crashing cpu.
@@ -751,10 +764,10 @@
 	 * an NMI if system was initially booted with nmi_watchdog parameter.
 	 */
 	if (cpu == crashing_cpu)
-		return NOTIFY_STOP;
+		return NMI_HANDLED;
 	local_irq_disable();
 
-	shootdown_callback(cpu, (struct die_args *)data);
+	shootdown_callback(cpu, regs);
 
 	atomic_dec(&waiting_for_crash_ipi);
 	/* Assume hlt works */
@@ -762,7 +775,7 @@
 	for (;;)
 		cpu_relax();
 
-	return 1;
+	return NMI_HANDLED;
 }
 
 static void smp_send_nmi_allbutself(void)
@@ -770,12 +783,6 @@
 	apic->send_IPI_allbutself(NMI_VECTOR);
 }
 
-static struct notifier_block crash_nmi_nb = {
-	.notifier_call = crash_nmi_callback,
-	/* we want to be the first one called */
-	.priority = NMI_LOCAL_HIGH_PRIOR+1,
-};
-
 /* Halt all other CPUs, calling the specified function on each of them
  *
  * This function can be used to halt all other CPUs on crash
@@ -794,7 +801,8 @@
 
 	atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
 	/* Would it be better to replace the trap vector here? */
-	if (register_die_notifier(&crash_nmi_nb))
+	if (register_nmi_handler(NMI_LOCAL, crash_nmi_callback,
+				 NMI_FLAG_FIRST, "crash"))
 		return;		/* return what? */
 	/* Ensure the new callback function is set before sending
 	 * out the NMI
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/rtc.c linux-libre-3.2-gnu/arch/x86/kernel/rtc.c
--- linux-libre-3.1-gnu/arch/x86/kernel/rtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/rtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,12 +5,14 @@
 #include <linux/mc146818rtc.h>
 #include <linux/acpi.h>
 #include <linux/bcd.h>
+#include <linux/export.h>
 #include <linux/pnp.h>
 #include <linux/of.h>
 
 #include <asm/vsyscall.h>
 #include <asm/x86_init.h>
 #include <asm/time.h>
+#include <asm/mrst.h>
 
 #ifdef CONFIG_X86_32
 /*
@@ -241,6 +243,10 @@
 	if (of_have_populated_dt())
 		return 0;
 
+	/* Intel MID platforms don't have ioport rtc */
+	if (mrst_identify_cpu())
+		return -ENODEV;
+
 	platform_device_register(&rtc_device);
 	dev_info(&rtc_device.dev,
 		 "registered platform RTC device (no PNP device found)\n");
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/setup.c linux-libre-3.2-gnu/arch/x86/kernel/setup.c
--- linux-libre-3.1-gnu/arch/x86/kernel/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -1045,6 +1045,8 @@
 
 	x86_init.timers.wallclock_init();
 
+	x86_platform.wallclock_init();
+
 	mcheck_init();
 
 	arch_init_ideal_nops();
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/smp.c linux-libre-3.2-gnu/arch/x86/kernel/smp.c
--- linux-libre-3.1-gnu/arch/x86/kernel/smp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/smp.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
+#include <linux/export.h>
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
 #include <linux/cache.h>
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/syscall_table_32.S linux-libre-3.2-gnu/arch/x86/kernel/syscall_table_32.S
--- linux-libre-3.1-gnu/arch/x86/kernel/syscall_table_32.S	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/syscall_table_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -346,3 +346,5 @@
 	.long sys_syncfs
 	.long sys_sendmmsg		/* 345 */
 	.long sys_setns
+	.long sys_process_vm_readv
+	.long sys_process_vm_writev
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/sys_x86_64.c linux-libre-3.2-gnu/arch/x86/kernel/sys_x86_64.c
--- linux-libre-3.1-gnu/arch/x86/kernel/sys_x86_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/sys_x86_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,10 +14,73 @@
 #include <linux/personality.h>
 #include <linux/random.h>
 #include <linux/uaccess.h>
+#include <linux/elf.h>
 
 #include <asm/ia32.h>
 #include <asm/syscalls.h>
 
+/*
+ * Align a virtual address to avoid aliasing in the I$ on AMD F15h.
+ *
+ * @flags denotes the allocation direction - bottomup or topdown -
+ * or vDSO; see call sites below.
+ */
+unsigned long align_addr(unsigned long addr, struct file *filp,
+			 enum align_flags flags)
+{
+	unsigned long tmp_addr;
+
+	/* handle 32- and 64-bit case with a single conditional */
+	if (va_align.flags < 0 || !(va_align.flags & (2 - mmap_is_ia32())))
+		return addr;
+
+	if (!(current->flags & PF_RANDOMIZE))
+		return addr;
+
+	if (!((flags & ALIGN_VDSO) || filp))
+		return addr;
+
+	tmp_addr = addr;
+
+	/*
+	 * We need an address which is <= than the original
+	 * one only when in topdown direction.
+	 */
+	if (!(flags & ALIGN_TOPDOWN))
+		tmp_addr += va_align.mask;
+
+	tmp_addr &= ~va_align.mask;
+
+	return tmp_addr;
+}
+
+static int __init control_va_addr_alignment(char *str)
+{
+	/* guard against enabling this on other CPU families */
+	if (va_align.flags < 0)
+		return 1;
+
+	if (*str == 0)
+		return 1;
+
+	if (*str == '=')
+		str++;
+
+	if (!strcmp(str, "32"))
+		va_align.flags = ALIGN_VA_32;
+	else if (!strcmp(str, "64"))
+		va_align.flags = ALIGN_VA_64;
+	else if (!strcmp(str, "off"))
+		va_align.flags = 0;
+	else if (!strcmp(str, "on"))
+		va_align.flags = ALIGN_VA_32 | ALIGN_VA_64;
+	else
+		return 0;
+
+	return 1;
+}
+__setup("align_va_addr", control_va_addr_alignment);
+
 SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
 		unsigned long, prot, unsigned long, flags,
 		unsigned long, fd, unsigned long, off)
@@ -92,6 +155,9 @@
 	start_addr = addr;
 
 full_search:
+
+	addr = align_addr(addr, filp, 0);
+
 	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
 		/* At this point:  (!vma || addr < vma->vm_end). */
 		if (end - len < addr) {
@@ -117,6 +183,7 @@
 			mm->cached_hole_size = vma->vm_start - addr;
 
 		addr = vma->vm_end;
+		addr = align_addr(addr, filp, 0);
 	}
 }
 
@@ -161,10 +228,13 @@
 
 	/* make sure it can fit in the remaining address space */
 	if (addr > len) {
-		vma = find_vma(mm, addr-len);
-		if (!vma || addr <= vma->vm_start)
+		unsigned long tmp_addr = align_addr(addr - len, filp,
+						    ALIGN_TOPDOWN);
+
+		vma = find_vma(mm, tmp_addr);
+		if (!vma || tmp_addr + len <= vma->vm_start)
 			/* remember the address as a hint for next time */
-			return mm->free_area_cache = addr-len;
+			return mm->free_area_cache = tmp_addr;
 	}
 
 	if (mm->mmap_base < len)
@@ -173,6 +243,8 @@
 	addr = mm->mmap_base-len;
 
 	do {
+		addr = align_addr(addr, filp, ALIGN_TOPDOWN);
+
 		/*
 		 * Lookup failure means no vma is above this address,
 		 * else if new region fits below vma->vm_start,
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/tboot.c linux-libre-3.2-gnu/arch/x86/kernel/tboot.c
--- linux-libre-3.1-gnu/arch/x86/kernel/tboot.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/tboot.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/dma_remapping.h>
 #include <linux/init_task.h>
 #include <linux/spinlock.h>
+#include <linux/export.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/init.h>
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/time.c linux-libre-3.2-gnu/arch/x86/kernel/time.c
--- linux-libre-3.1-gnu/arch/x86/kernel/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/interrupt.h>
 #include <linux/i8253.h>
 #include <linux/time.h>
+#include <linux/export.h>
 #include <linux/mca.h>
 
 #include <asm/vsyscall.h>
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/topology.c linux-libre-3.2-gnu/arch/x86/kernel/topology.c
--- linux-libre-3.1-gnu/arch/x86/kernel/topology.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/topology.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
  * Send feedback to <colpatch@us.ibm.com>
  */
 #include <linux/nodemask.h>
+#include <linux/export.h>
 #include <linux/mmzone.h>
 #include <linux/init.h>
 #include <linux/smp.h>
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/traps.c linux-libre-3.2-gnu/arch/x86/kernel/traps.c
--- linux-libre-3.1-gnu/arch/x86/kernel/traps.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/traps.c	2012-01-04 18:55:44.000000000 -0500
@@ -81,15 +81,6 @@
 DECLARE_BITMAP(used_vectors, NR_VECTORS);
 EXPORT_SYMBOL_GPL(used_vectors);
 
-static int ignore_nmis;
-
-int unknown_nmi_panic;
-/*
- * Prevent NMI reason port (0x61) being accessed simultaneously, can
- * only be used in NMI handler.
- */
-static DEFINE_RAW_SPINLOCK(nmi_reason_lock);
-
 static inline void conditional_sti(struct pt_regs *regs)
 {
 	if (regs->flags & X86_EFLAGS_IF)
@@ -307,152 +298,6 @@
 	die("general protection fault", regs, error_code);
 }
 
-static int __init setup_unknown_nmi_panic(char *str)
-{
-	unknown_nmi_panic = 1;
-	return 1;
-}
-__setup("unknown_nmi_panic", setup_unknown_nmi_panic);
-
-static notrace __kprobes void
-pci_serr_error(unsigned char reason, struct pt_regs *regs)
-{
-	pr_emerg("NMI: PCI system error (SERR) for reason %02x on CPU %d.\n",
-		 reason, smp_processor_id());
-
-	/*
-	 * On some machines, PCI SERR line is used to report memory
-	 * errors. EDAC makes use of it.
-	 */
-#if defined(CONFIG_EDAC)
-	if (edac_handler_set()) {
-		edac_atomic_assert_error();
-		return;
-	}
-#endif
-
-	if (panic_on_unrecovered_nmi)
-		panic("NMI: Not continuing");
-
-	pr_emerg("Dazed and confused, but trying to continue\n");
-
-	/* Clear and disable the PCI SERR error line. */
-	reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_SERR;
-	outb(reason, NMI_REASON_PORT);
-}
-
-static notrace __kprobes void
-io_check_error(unsigned char reason, struct pt_regs *regs)
-{
-	unsigned long i;
-
-	pr_emerg(
-	"NMI: IOCK error (debug interrupt?) for reason %02x on CPU %d.\n",
-		 reason, smp_processor_id());
-	show_registers(regs);
-
-	if (panic_on_io_nmi)
-		panic("NMI IOCK error: Not continuing");
-
-	/* Re-enable the IOCK line, wait for a few seconds */
-	reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK;
-	outb(reason, NMI_REASON_PORT);
-
-	i = 20000;
-	while (--i) {
-		touch_nmi_watchdog();
-		udelay(100);
-	}
-
-	reason &= ~NMI_REASON_CLEAR_IOCHK;
-	outb(reason, NMI_REASON_PORT);
-}
-
-static notrace __kprobes void
-unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
-{
-	if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) ==
-			NOTIFY_STOP)
-		return;
-#ifdef CONFIG_MCA
-	/*
-	 * Might actually be able to figure out what the guilty party
-	 * is:
-	 */
-	if (MCA_bus) {
-		mca_handle_nmi();
-		return;
-	}
-#endif
-	pr_emerg("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
-		 reason, smp_processor_id());
-
-	pr_emerg("Do you have a strange power saving mode enabled?\n");
-	if (unknown_nmi_panic || panic_on_unrecovered_nmi)
-		panic("NMI: Not continuing");
-
-	pr_emerg("Dazed and confused, but trying to continue\n");
-}
-
-static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
-{
-	unsigned char reason = 0;
-
-	/*
-	 * CPU-specific NMI must be processed before non-CPU-specific
-	 * NMI, otherwise we may lose it, because the CPU-specific
-	 * NMI can not be detected/processed on other CPUs.
-	 */
-	if (notify_die(DIE_NMI, "nmi", regs, 0, 2, SIGINT) == NOTIFY_STOP)
-		return;
-
-	/* Non-CPU-specific NMI: NMI sources can be processed on any CPU */
-	raw_spin_lock(&nmi_reason_lock);
-	reason = get_nmi_reason();
-
-	if (reason & NMI_REASON_MASK) {
-		if (reason & NMI_REASON_SERR)
-			pci_serr_error(reason, regs);
-		else if (reason & NMI_REASON_IOCHK)
-			io_check_error(reason, regs);
-#ifdef CONFIG_X86_32
-		/*
-		 * Reassert NMI in case it became active
-		 * meanwhile as it's edge-triggered:
-		 */
-		reassert_nmi();
-#endif
-		raw_spin_unlock(&nmi_reason_lock);
-		return;
-	}
-	raw_spin_unlock(&nmi_reason_lock);
-
-	unknown_nmi_error(reason, regs);
-}
-
-dotraplinkage notrace __kprobes void
-do_nmi(struct pt_regs *regs, long error_code)
-{
-	nmi_enter();
-
-	inc_irq_stat(__nmi_count);
-
-	if (!ignore_nmis)
-		default_do_nmi(regs);
-
-	nmi_exit();
-}
-
-void stop_nmi(void)
-{
-	ignore_nmis++;
-}
-
-void restart_nmi(void)
-{
-	ignore_nmis--;
-}
-
 /* May run on IST stack. */
 dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)
 {
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/vsyscall_64.c linux-libre-3.2-gnu/arch/x86/kernel/vsyscall_64.c
--- linux-libre-3.1-gnu/arch/x86/kernel/vsyscall_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/vsyscall_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/seqlock.h>
 #include <linux/jiffies.h>
 #include <linux/sysctl.h>
+#include <linux/topology.h>
 #include <linux/clocksource.h>
 #include <linux/getcpu.h>
 #include <linux/cpu.h>
diff -druN linux-libre-3.1-gnu/arch/x86/kernel/x86_init.c linux-libre-3.2-gnu/arch/x86/kernel/x86_init.c
--- linux-libre-3.1-gnu/arch/x86/kernel/x86_init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kernel/x86_init.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,12 +21,14 @@
 #include <asm/pat.h>
 #include <asm/tsc.h>
 #include <asm/iommu.h>
+#include <asm/mach_traps.h>
 
 void __cpuinit x86_init_noop(void) { }
 void __init x86_init_uint_noop(unsigned int unused) { }
 void __init x86_init_pgd_noop(pgd_t *unused) { }
 int __init iommu_init_noop(void) { return 0; }
 void iommu_shutdown_noop(void) { }
+void wallclock_init_noop(void) { }
 
 /*
  * The platform setup functions are preset with the default functions
@@ -97,11 +99,13 @@
 
 struct x86_platform_ops x86_platform = {
 	.calibrate_tsc			= native_calibrate_tsc,
+	.wallclock_init			= wallclock_init_noop,
 	.get_wallclock			= mach_get_cmos_time,
 	.set_wallclock			= mach_set_rtc_mmss,
 	.iommu_shutdown			= iommu_shutdown_noop,
 	.is_untracked_pat_range		= is_ISA_range,
 	.nmi_init			= default_nmi_init,
+	.get_nmi_reason			= default_get_nmi_reason,
 	.i8042_detect			= default_i8042_detect
 };
 
diff -druN linux-libre-3.1-gnu/arch/x86/kvm/emulate.c linux-libre-3.2-gnu/arch/x86/kvm/emulate.c
--- linux-libre-3.1-gnu/arch/x86/kvm/emulate.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kvm/emulate.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,39 @@
 #include "tss.h"
 
 /*
+ * Operand types
+ */
+#define OpNone             0ull
+#define OpImplicit         1ull  /* No generic decode */
+#define OpReg              2ull  /* Register */
+#define OpMem              3ull  /* Memory */
+#define OpAcc              4ull  /* Accumulator: AL/AX/EAX/RAX */
+#define OpDI               5ull  /* ES:DI/EDI/RDI */
+#define OpMem64            6ull  /* Memory, 64-bit */
+#define OpImmUByte         7ull  /* Zero-extended 8-bit immediate */
+#define OpDX               8ull  /* DX register */
+#define OpCL               9ull  /* CL register (for shifts) */
+#define OpImmByte         10ull  /* 8-bit sign extended immediate */
+#define OpOne             11ull  /* Implied 1 */
+#define OpImm             12ull  /* Sign extended immediate */
+#define OpMem16           13ull  /* Memory operand (16-bit). */
+#define OpMem32           14ull  /* Memory operand (32-bit). */
+#define OpImmU            15ull  /* Immediate operand, zero extended */
+#define OpSI              16ull  /* SI/ESI/RSI */
+#define OpImmFAddr        17ull  /* Immediate far address */
+#define OpMemFAddr        18ull  /* Far address in memory */
+#define OpImmU16          19ull  /* Immediate operand, 16 bits, zero extended */
+#define OpES              20ull  /* ES */
+#define OpCS              21ull  /* CS */
+#define OpSS              22ull  /* SS */
+#define OpDS              23ull  /* DS */
+#define OpFS              24ull  /* FS */
+#define OpGS              25ull  /* GS */
+
+#define OpBits             5  /* Width of operand field */
+#define OpMask             ((1ull << OpBits) - 1)
+
+/*
  * Opcode effective-address decode tables.
  * Note that we only emulate instructions that have at least one memory
  * operand (excluding implicit stack references). We assume that stack
@@ -40,37 +73,35 @@
 /* Operand sizes: 8-bit operands or specified/overridden size. */
 #define ByteOp      (1<<0)	/* 8-bit operands. */
 /* Destination operand type. */
-#define ImplicitOps (1<<1)	/* Implicit in opcode. No generic decode. */
-#define DstReg      (2<<1)	/* Register operand. */
-#define DstMem      (3<<1)	/* Memory operand. */
-#define DstAcc      (4<<1)	/* Destination Accumulator */
-#define DstDI       (5<<1)	/* Destination is in ES:(E)DI */
-#define DstMem64    (6<<1)	/* 64bit memory operand */
-#define DstImmUByte (7<<1)	/* 8-bit unsigned immediate operand */
-#define DstDX       (8<<1)	/* Destination is in DX register */
-#define DstMask     (0xf<<1)
+#define DstShift    1
+#define ImplicitOps (OpImplicit << DstShift)
+#define DstReg      (OpReg << DstShift)
+#define DstMem      (OpMem << DstShift)
+#define DstAcc      (OpAcc << DstShift)
+#define DstDI       (OpDI << DstShift)
+#define DstMem64    (OpMem64 << DstShift)
+#define DstImmUByte (OpImmUByte << DstShift)
+#define DstDX       (OpDX << DstShift)
+#define DstMask     (OpMask << DstShift)
 /* Source operand type. */
-#define SrcNone     (0<<5)	/* No source operand. */
-#define SrcReg      (1<<5)	/* Register operand. */
-#define SrcMem      (2<<5)	/* Memory operand. */
-#define SrcMem16    (3<<5)	/* Memory operand (16-bit). */
-#define SrcMem32    (4<<5)	/* Memory operand (32-bit). */
-#define SrcImm      (5<<5)	/* Immediate operand. */
-#define SrcImmByte  (6<<5)	/* 8-bit sign-extended immediate operand. */
-#define SrcOne      (7<<5)	/* Implied '1' */
-#define SrcImmUByte (8<<5)      /* 8-bit unsigned immediate operand. */
-#define SrcImmU     (9<<5)      /* Immediate operand, unsigned */
-#define SrcSI       (0xa<<5)	/* Source is in the DS:RSI */
-#define SrcImmFAddr (0xb<<5)	/* Source is immediate far address */
-#define SrcMemFAddr (0xc<<5)	/* Source is far address in memory */
-#define SrcAcc      (0xd<<5)	/* Source Accumulator */
-#define SrcImmU16   (0xe<<5)    /* Immediate operand, unsigned, 16 bits */
-#define SrcDX       (0xf<<5)	/* Source is in DX register */
-#define SrcMask     (0xf<<5)
-/* Generic ModRM decode. */
-#define ModRM       (1<<9)
-/* Destination is only written; never read. */
-#define Mov         (1<<10)
+#define SrcShift    6
+#define SrcNone     (OpNone << SrcShift)
+#define SrcReg      (OpReg << SrcShift)
+#define SrcMem      (OpMem << SrcShift)
+#define SrcMem16    (OpMem16 << SrcShift)
+#define SrcMem32    (OpMem32 << SrcShift)
+#define SrcImm      (OpImm << SrcShift)
+#define SrcImmByte  (OpImmByte << SrcShift)
+#define SrcOne      (OpOne << SrcShift)
+#define SrcImmUByte (OpImmUByte << SrcShift)
+#define SrcImmU     (OpImmU << SrcShift)
+#define SrcSI       (OpSI << SrcShift)
+#define SrcImmFAddr (OpImmFAddr << SrcShift)
+#define SrcMemFAddr (OpMemFAddr << SrcShift)
+#define SrcAcc      (OpAcc << SrcShift)
+#define SrcImmU16   (OpImmU16 << SrcShift)
+#define SrcDX       (OpDX << SrcShift)
+#define SrcMask     (OpMask << SrcShift)
 #define BitOp       (1<<11)
 #define MemAbs      (1<<12)      /* Memory operand is absolute displacement */
 #define String      (1<<13)     /* String instruction (rep capable) */
@@ -81,6 +112,10 @@
 #define Prefix      (3<<15)     /* Instruction varies with 66/f2/f3 prefix */
 #define RMExt       (4<<15)     /* Opcode extension in ModRM r/m if mod == 3 */
 #define Sse         (1<<18)     /* SSE Vector instruction */
+/* Generic ModRM decode. */
+#define ModRM       (1<<19)
+/* Destination is only written; never read. */
+#define Mov         (1<<20)
 /* Misc flags */
 #define Prot        (1<<21) /* instruction generates #UD if not in prot-mode */
 #define VendorSpecific (1<<22) /* Vendor specific instruction */
@@ -91,12 +126,19 @@
 #define Priv        (1<<27) /* instruction generates #GP if current CPL != 0 */
 #define No64	    (1<<28)
 /* Source 2 operand type */
-#define Src2None    (0<<29)
-#define Src2CL      (1<<29)
-#define Src2ImmByte (2<<29)
-#define Src2One     (3<<29)
-#define Src2Imm     (4<<29)
-#define Src2Mask    (7<<29)
+#define Src2Shift   (29)
+#define Src2None    (OpNone << Src2Shift)
+#define Src2CL      (OpCL << Src2Shift)
+#define Src2ImmByte (OpImmByte << Src2Shift)
+#define Src2One     (OpOne << Src2Shift)
+#define Src2Imm     (OpImm << Src2Shift)
+#define Src2ES      (OpES << Src2Shift)
+#define Src2CS      (OpCS << Src2Shift)
+#define Src2SS      (OpSS << Src2Shift)
+#define Src2DS      (OpDS << Src2Shift)
+#define Src2FS      (OpFS << Src2Shift)
+#define Src2GS      (OpGS << Src2Shift)
+#define Src2Mask    (OpMask << Src2Shift)
 
 #define X2(x...) x, x
 #define X3(x...) X2(x), x
@@ -108,8 +150,8 @@
 #define X16(x...) X8(x), X8(x)
 
 struct opcode {
-	u32 flags;
-	u8 intercept;
+	u64 flags : 56;
+	u64 intercept : 8;
 	union {
 		int (*execute)(struct x86_emulate_ctxt *ctxt);
 		struct opcode *group;
@@ -205,105 +247,100 @@
 #define ON64(x)
 #endif
 
-#define ____emulate_2op(_op, _src, _dst, _eflags, _x, _y, _suffix, _dsttype) \
+#define ____emulate_2op(ctxt, _op, _x, _y, _suffix, _dsttype)	\
 	do {								\
 		__asm__ __volatile__ (					\
 			_PRE_EFLAGS("0", "4", "2")			\
 			_op _suffix " %"_x"3,%1; "			\
 			_POST_EFLAGS("0", "4", "2")			\
-			: "=m" (_eflags), "+q" (*(_dsttype*)&(_dst).val),\
+			: "=m" ((ctxt)->eflags),			\
+			  "+q" (*(_dsttype*)&(ctxt)->dst.val),		\
 			  "=&r" (_tmp)					\
-			: _y ((_src).val), "i" (EFLAGS_MASK));		\
+			: _y ((ctxt)->src.val), "i" (EFLAGS_MASK));	\
 	} while (0)
 
 
 /* Raw emulation: instruction has two explicit operands. */
-#define __emulate_2op_nobyte(_op,_src,_dst,_eflags,_wx,_wy,_lx,_ly,_qx,_qy) \
+#define __emulate_2op_nobyte(ctxt,_op,_wx,_wy,_lx,_ly,_qx,_qy)		\
 	do {								\
 		unsigned long _tmp;					\
 									\
-		switch ((_dst).bytes) {					\
+		switch ((ctxt)->dst.bytes) {				\
 		case 2:							\
-			____emulate_2op(_op,_src,_dst,_eflags,_wx,_wy,"w",u16);\
+			____emulate_2op(ctxt,_op,_wx,_wy,"w",u16);	\
 			break;						\
 		case 4:							\
-			____emulate_2op(_op,_src,_dst,_eflags,_lx,_ly,"l",u32);\
+			____emulate_2op(ctxt,_op,_lx,_ly,"l",u32);	\
 			break;						\
 		case 8:							\
-			ON64(____emulate_2op(_op,_src,_dst,_eflags,_qx,_qy,"q",u64)); \
+			ON64(____emulate_2op(ctxt,_op,_qx,_qy,"q",u64)); \
 			break;						\
 		}							\
 	} while (0)
 
-#define __emulate_2op(_op,_src,_dst,_eflags,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \
+#define __emulate_2op(ctxt,_op,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy)		     \
 	do {								     \
 		unsigned long _tmp;					     \
-		switch ((_dst).bytes) {				             \
+		switch ((ctxt)->dst.bytes) {				     \
 		case 1:							     \
-			____emulate_2op(_op,_src,_dst,_eflags,_bx,_by,"b",u8); \
+			____emulate_2op(ctxt,_op,_bx,_by,"b",u8);	     \
 			break;						     \
 		default:						     \
-			__emulate_2op_nobyte(_op, _src, _dst, _eflags,	     \
+			__emulate_2op_nobyte(ctxt, _op,			     \
 					     _wx, _wy, _lx, _ly, _qx, _qy);  \
 			break;						     \
 		}							     \
 	} while (0)
 
 /* Source operand is byte-sized and may be restricted to just %cl. */
-#define emulate_2op_SrcB(_op, _src, _dst, _eflags)                      \
-	__emulate_2op(_op, _src, _dst, _eflags,				\
-		      "b", "c", "b", "c", "b", "c", "b", "c")
+#define emulate_2op_SrcB(ctxt, _op)					\
+	__emulate_2op(ctxt, _op, "b", "c", "b", "c", "b", "c", "b", "c")
 
 /* Source operand is byte, word, long or quad sized. */
-#define emulate_2op_SrcV(_op, _src, _dst, _eflags)                      \
-	__emulate_2op(_op, _src, _dst, _eflags,				\
-		      "b", "q", "w", "r", _LO32, "r", "", "r")
+#define emulate_2op_SrcV(ctxt, _op)					\
+	__emulate_2op(ctxt, _op, "b", "q", "w", "r", _LO32, "r", "", "r")
 
 /* Source operand is word, long or quad sized. */
-#define emulate_2op_SrcV_nobyte(_op, _src, _dst, _eflags)               \
-	__emulate_2op_nobyte(_op, _src, _dst, _eflags,			\
-			     "w", "r", _LO32, "r", "", "r")
+#define emulate_2op_SrcV_nobyte(ctxt, _op)				\
+	__emulate_2op_nobyte(ctxt, _op, "w", "r", _LO32, "r", "", "r")
 
 /* Instruction has three operands and one operand is stored in ECX register */
-#define __emulate_2op_cl(_op, _cl, _src, _dst, _eflags, _suffix, _type)	\
+#define __emulate_2op_cl(ctxt, _op, _suffix, _type)		\
 	do {								\
 		unsigned long _tmp;					\
-		_type _clv  = (_cl).val;				\
-		_type _srcv = (_src).val;				\
-		_type _dstv = (_dst).val;				\
+		_type _clv  = (ctxt)->src2.val;				\
+		_type _srcv = (ctxt)->src.val;				\
+		_type _dstv = (ctxt)->dst.val;				\
 									\
 		__asm__ __volatile__ (					\
 			_PRE_EFLAGS("0", "5", "2")			\
 			_op _suffix " %4,%1 \n"				\
 			_POST_EFLAGS("0", "5", "2")			\
-			: "=m" (_eflags), "+r" (_dstv), "=&r" (_tmp)	\
+			: "=m" ((ctxt)->eflags), "+r" (_dstv), "=&r" (_tmp) \
 			: "c" (_clv) , "r" (_srcv), "i" (EFLAGS_MASK)	\
 			);						\
 									\
-		(_cl).val  = (unsigned long) _clv;			\
-		(_src).val = (unsigned long) _srcv;			\
-		(_dst).val = (unsigned long) _dstv;			\
+		(ctxt)->src2.val  = (unsigned long) _clv;		\
+		(ctxt)->src2.val = (unsigned long) _srcv;		\
+		(ctxt)->dst.val = (unsigned long) _dstv;		\
 	} while (0)
 
-#define emulate_2op_cl(_op, _cl, _src, _dst, _eflags)			\
+#define emulate_2op_cl(ctxt, _op)					\
 	do {								\
-		switch ((_dst).bytes) {					\
+		switch ((ctxt)->dst.bytes) {				\
 		case 2:							\
-			__emulate_2op_cl(_op, _cl, _src, _dst, _eflags,	\
-					 "w", unsigned short);         	\
+			__emulate_2op_cl(ctxt, _op, "w", u16);		\
 			break;						\
 		case 4:							\
-			__emulate_2op_cl(_op, _cl, _src, _dst, _eflags,	\
-					 "l", unsigned int);           	\
+			__emulate_2op_cl(ctxt, _op, "l", u32);		\
 			break;						\
 		case 8:							\
-			ON64(__emulate_2op_cl(_op, _cl, _src, _dst, _eflags, \
-					      "q", unsigned long));	\
+			ON64(__emulate_2op_cl(ctxt, _op, "q", ulong));	\
 			break;						\
 		}							\
 	} while (0)
 
-#define __emulate_1op(_op, _dst, _eflags, _suffix)			\
+#define __emulate_1op(ctxt, _op, _suffix)				\
 	do {								\
 		unsigned long _tmp;					\
 									\
@@ -311,39 +348,27 @@
 			_PRE_EFLAGS("0", "3", "2")			\
 			_op _suffix " %1; "				\
 			_POST_EFLAGS("0", "3", "2")			\
-			: "=m" (_eflags), "+m" ((_dst).val),		\
+			: "=m" ((ctxt)->eflags), "+m" ((ctxt)->dst.val), \
 			  "=&r" (_tmp)					\
 			: "i" (EFLAGS_MASK));				\
 	} while (0)
 
 /* Instruction has only one explicit operand (no source operand). */
-#define emulate_1op(_op, _dst, _eflags)                                    \
+#define emulate_1op(ctxt, _op)						\
 	do {								\
-		switch ((_dst).bytes) {				        \
-		case 1:	__emulate_1op(_op, _dst, _eflags, "b"); break;	\
-		case 2:	__emulate_1op(_op, _dst, _eflags, "w"); break;	\
-		case 4:	__emulate_1op(_op, _dst, _eflags, "l"); break;	\
-		case 8:	ON64(__emulate_1op(_op, _dst, _eflags, "q")); break; \
+		switch ((ctxt)->dst.bytes) {				\
+		case 1:	__emulate_1op(ctxt, _op, "b"); break;		\
+		case 2:	__emulate_1op(ctxt, _op, "w"); break;		\
+		case 4:	__emulate_1op(ctxt, _op, "l"); break;		\
+		case 8:	ON64(__emulate_1op(ctxt, _op, "q")); break;	\
 		}							\
 	} while (0)
 
-#define __emulate_1op_rax_rdx(_op, _src, _rax, _rdx, _eflags, _suffix)		\
-	do {								\
-		unsigned long _tmp;					\
-									\
-		__asm__ __volatile__ (					\
-			_PRE_EFLAGS("0", "4", "1")			\
-			_op _suffix " %5; "				\
-			_POST_EFLAGS("0", "4", "1")			\
-			: "=m" (_eflags), "=&r" (_tmp),			\
-			  "+a" (_rax), "+d" (_rdx)			\
-			: "i" (EFLAGS_MASK), "m" ((_src).val),		\
-			  "a" (_rax), "d" (_rdx));			\
-	} while (0)
-
-#define __emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, _eflags, _suffix, _ex) \
+#define __emulate_1op_rax_rdx(ctxt, _op, _suffix, _ex)			\
 	do {								\
 		unsigned long _tmp;					\
+		ulong *rax = &(ctxt)->regs[VCPU_REGS_RAX];		\
+		ulong *rdx = &(ctxt)->regs[VCPU_REGS_RDX];		\
 									\
 		__asm__ __volatile__ (					\
 			_PRE_EFLAGS("0", "5", "1")			\
@@ -356,53 +381,27 @@
 			"jmp 2b \n\t"					\
 			".popsection \n\t"				\
 			_ASM_EXTABLE(1b, 3b)				\
-			: "=m" (_eflags), "=&r" (_tmp),			\
-			  "+a" (_rax), "+d" (_rdx), "+qm"(_ex)		\
-			: "i" (EFLAGS_MASK), "m" ((_src).val),		\
-			  "a" (_rax), "d" (_rdx));			\
+			: "=m" ((ctxt)->eflags), "=&r" (_tmp),		\
+			  "+a" (*rax), "+d" (*rdx), "+qm"(_ex)		\
+			: "i" (EFLAGS_MASK), "m" ((ctxt)->src.val),	\
+			  "a" (*rax), "d" (*rdx));			\
 	} while (0)
 
 /* instruction has only one source operand, destination is implicit (e.g. mul, div, imul, idiv) */
-#define emulate_1op_rax_rdx(_op, _src, _rax, _rdx, _eflags)		\
-	do {								\
-		switch((_src).bytes) {					\
-		case 1:							\
-			__emulate_1op_rax_rdx(_op, _src, _rax, _rdx,	\
-					      _eflags, "b");		\
-			break;						\
-		case 2:							\
-			__emulate_1op_rax_rdx(_op, _src, _rax, _rdx,	\
-					      _eflags, "w");		\
-			break;						\
-		case 4:							\
-			__emulate_1op_rax_rdx(_op, _src, _rax, _rdx,	\
-					      _eflags, "l");		\
-			break;						\
-		case 8:							\
-			ON64(__emulate_1op_rax_rdx(_op, _src, _rax, _rdx, \
-						   _eflags, "q"));	\
-			break;						\
-		}							\
-	} while (0)
-
-#define emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, _eflags, _ex)	\
+#define emulate_1op_rax_rdx(ctxt, _op, _ex)	\
 	do {								\
-		switch((_src).bytes) {					\
+		switch((ctxt)->src.bytes) {				\
 		case 1:							\
-			__emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx,	\
-						 _eflags, "b", _ex);	\
+			__emulate_1op_rax_rdx(ctxt, _op, "b", _ex);	\
 			break;						\
 		case 2:							\
-			__emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
-						 _eflags, "w", _ex);	\
+			__emulate_1op_rax_rdx(ctxt, _op, "w", _ex);	\
 			break;						\
 		case 4:							\
-			__emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
-						 _eflags, "l", _ex);	\
+			__emulate_1op_rax_rdx(ctxt, _op, "l", _ex);	\
 			break;						\
 		case 8: ON64(						\
-			__emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
-						 _eflags, "q", _ex));	\
+			__emulate_1op_rax_rdx(ctxt, _op, "q", _ex));	\
 			break;						\
 		}							\
 	} while (0)
@@ -651,41 +650,50 @@
 	return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
 }
 
-static int do_insn_fetch_byte(struct x86_emulate_ctxt *ctxt,
-			      unsigned long eip, u8 *dest)
+/*
+ * Fetch the next byte of the instruction being emulated which is pointed to
+ * by ctxt->_eip, then increment ctxt->_eip.
+ *
+ * Also prefetch the remaining bytes of the instruction without crossing page
+ * boundary if they are not in fetch_cache yet.
+ */
+static int do_insn_fetch_byte(struct x86_emulate_ctxt *ctxt, u8 *dest)
 {
 	struct fetch_cache *fc = &ctxt->fetch;
 	int rc;
 	int size, cur_size;
 
-	if (eip == fc->end) {
+	if (ctxt->_eip == fc->end) {
 		unsigned long linear;
-		struct segmented_address addr = { .seg=VCPU_SREG_CS, .ea=eip};
+		struct segmented_address addr = { .seg = VCPU_SREG_CS,
+						  .ea  = ctxt->_eip };
 		cur_size = fc->end - fc->start;
-		size = min(15UL - cur_size, PAGE_SIZE - offset_in_page(eip));
+		size = min(15UL - cur_size,
+			   PAGE_SIZE - offset_in_page(ctxt->_eip));
 		rc = __linearize(ctxt, addr, size, false, true, &linear);
-		if (rc != X86EMUL_CONTINUE)
+		if (unlikely(rc != X86EMUL_CONTINUE))
 			return rc;
 		rc = ctxt->ops->fetch(ctxt, linear, fc->data + cur_size,
 				      size, &ctxt->exception);
-		if (rc != X86EMUL_CONTINUE)
+		if (unlikely(rc != X86EMUL_CONTINUE))
 			return rc;
 		fc->end += size;
 	}
-	*dest = fc->data[eip - fc->start];
+	*dest = fc->data[ctxt->_eip - fc->start];
+	ctxt->_eip++;
 	return X86EMUL_CONTINUE;
 }
 
 static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
-			 unsigned long eip, void *dest, unsigned size)
+			 void *dest, unsigned size)
 {
 	int rc;
 
 	/* x86 instructions are limited to 15 bytes. */
-	if (eip + size - ctxt->eip > 15)
+	if (unlikely(ctxt->_eip + size - ctxt->eip > 15))
 		return X86EMUL_UNHANDLEABLE;
 	while (size--) {
-		rc = do_insn_fetch_byte(ctxt, eip++, dest++);
+		rc = do_insn_fetch_byte(ctxt, dest++);
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
 	}
@@ -693,20 +701,18 @@
 }
 
 /* Fetch next part of the instruction being emulated. */
-#define insn_fetch(_type, _size, _eip)					\
+#define insn_fetch(_type, _ctxt)					\
 ({	unsigned long _x;						\
-	rc = do_insn_fetch(ctxt, (_eip), &_x, (_size));			\
+	rc = do_insn_fetch(_ctxt, &_x, sizeof(_type));			\
 	if (rc != X86EMUL_CONTINUE)					\
 		goto done;						\
-	(_eip) += (_size);						\
 	(_type)_x;							\
 })
 
-#define insn_fetch_arr(_arr, _size, _eip)				\
-({	rc = do_insn_fetch(ctxt, (_eip), _arr, (_size));		\
+#define insn_fetch_arr(_arr, _size, _ctxt)				\
+({	rc = do_insn_fetch(_ctxt, _arr, (_size));			\
 	if (rc != X86EMUL_CONTINUE)					\
 		goto done;						\
-	(_eip) += (_size);						\
 })
 
 /*
@@ -894,7 +900,7 @@
 		ctxt->modrm_rm = base_reg = (ctxt->rex_prefix & 1) << 3; /* REG.B */
 	}
 
-	ctxt->modrm = insn_fetch(u8, 1, ctxt->_eip);
+	ctxt->modrm = insn_fetch(u8, ctxt);
 	ctxt->modrm_mod |= (ctxt->modrm & 0xc0) >> 6;
 	ctxt->modrm_reg |= (ctxt->modrm & 0x38) >> 3;
 	ctxt->modrm_rm |= (ctxt->modrm & 0x07);
@@ -928,13 +934,13 @@
 		switch (ctxt->modrm_mod) {
 		case 0:
 			if (ctxt->modrm_rm == 6)
-				modrm_ea += insn_fetch(u16, 2, ctxt->_eip);
+				modrm_ea += insn_fetch(u16, ctxt);
 			break;
 		case 1:
-			modrm_ea += insn_fetch(s8, 1, ctxt->_eip);
+			modrm_ea += insn_fetch(s8, ctxt);
 			break;
 		case 2:
-			modrm_ea += insn_fetch(u16, 2, ctxt->_eip);
+			modrm_ea += insn_fetch(u16, ctxt);
 			break;
 		}
 		switch (ctxt->modrm_rm) {
@@ -971,13 +977,13 @@
 	} else {
 		/* 32/64-bit ModR/M decode. */
 		if ((ctxt->modrm_rm & 7) == 4) {
-			sib = insn_fetch(u8, 1, ctxt->_eip);
+			sib = insn_fetch(u8, ctxt);
 			index_reg |= (sib >> 3) & 7;
 			base_reg |= sib & 7;
 			scale = sib >> 6;
 
 			if ((base_reg & 7) == 5 && ctxt->modrm_mod == 0)
-				modrm_ea += insn_fetch(s32, 4, ctxt->_eip);
+				modrm_ea += insn_fetch(s32, ctxt);
 			else
 				modrm_ea += ctxt->regs[base_reg];
 			if (index_reg != 4)
@@ -990,13 +996,13 @@
 		switch (ctxt->modrm_mod) {
 		case 0:
 			if (ctxt->modrm_rm == 5)
-				modrm_ea += insn_fetch(s32, 4, ctxt->_eip);
+				modrm_ea += insn_fetch(s32, ctxt);
 			break;
 		case 1:
-			modrm_ea += insn_fetch(s8, 1, ctxt->_eip);
+			modrm_ea += insn_fetch(s8, ctxt);
 			break;
 		case 2:
-			modrm_ea += insn_fetch(s32, 4, ctxt->_eip);
+			modrm_ea += insn_fetch(s32, ctxt);
 			break;
 		}
 	}
@@ -1013,13 +1019,13 @@
 	op->type = OP_MEM;
 	switch (ctxt->ad_bytes) {
 	case 2:
-		op->addr.mem.ea = insn_fetch(u16, 2, ctxt->_eip);
+		op->addr.mem.ea = insn_fetch(u16, ctxt);
 		break;
 	case 4:
-		op->addr.mem.ea = insn_fetch(u32, 4, ctxt->_eip);
+		op->addr.mem.ea = insn_fetch(u32, ctxt);
 		break;
 	case 8:
-		op->addr.mem.ea = insn_fetch(u64, 8, ctxt->_eip);
+		op->addr.mem.ea = insn_fetch(u64, ctxt);
 		break;
 	}
 done:
@@ -1452,15 +1458,18 @@
 	return emulate_popf(ctxt, &ctxt->dst.val, ctxt->op_bytes);
 }
 
-static int emulate_push_sreg(struct x86_emulate_ctxt *ctxt, int seg)
+static int em_push_sreg(struct x86_emulate_ctxt *ctxt)
 {
+	int seg = ctxt->src2.val;
+
 	ctxt->src.val = get_segment_selector(ctxt, seg);
 
 	return em_push(ctxt);
 }
 
-static int emulate_pop_sreg(struct x86_emulate_ctxt *ctxt, int seg)
+static int em_pop_sreg(struct x86_emulate_ctxt *ctxt)
 {
+	int seg = ctxt->src2.val;
 	unsigned long selector;
 	int rc;
 
@@ -1674,64 +1683,74 @@
 {
 	switch (ctxt->modrm_reg) {
 	case 0:	/* rol */
-		emulate_2op_SrcB("rol", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcB(ctxt, "rol");
 		break;
 	case 1:	/* ror */
-		emulate_2op_SrcB("ror", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcB(ctxt, "ror");
 		break;
 	case 2:	/* rcl */
-		emulate_2op_SrcB("rcl", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcB(ctxt, "rcl");
 		break;
 	case 3:	/* rcr */
-		emulate_2op_SrcB("rcr", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcB(ctxt, "rcr");
 		break;
 	case 4:	/* sal/shl */
 	case 6:	/* sal/shl */
-		emulate_2op_SrcB("sal", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcB(ctxt, "sal");
 		break;
 	case 5:	/* shr */
-		emulate_2op_SrcB("shr", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcB(ctxt, "shr");
 		break;
 	case 7:	/* sar */
-		emulate_2op_SrcB("sar", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcB(ctxt, "sar");
 		break;
 	}
 	return X86EMUL_CONTINUE;
 }
 
-static int em_grp3(struct x86_emulate_ctxt *ctxt)
+static int em_not(struct x86_emulate_ctxt *ctxt)
+{
+	ctxt->dst.val = ~ctxt->dst.val;
+	return X86EMUL_CONTINUE;
+}
+
+static int em_neg(struct x86_emulate_ctxt *ctxt)
+{
+	emulate_1op(ctxt, "neg");
+	return X86EMUL_CONTINUE;
+}
+
+static int em_mul_ex(struct x86_emulate_ctxt *ctxt)
+{
+	u8 ex = 0;
+
+	emulate_1op_rax_rdx(ctxt, "mul", ex);
+	return X86EMUL_CONTINUE;
+}
+
+static int em_imul_ex(struct x86_emulate_ctxt *ctxt)
+{
+	u8 ex = 0;
+
+	emulate_1op_rax_rdx(ctxt, "imul", ex);
+	return X86EMUL_CONTINUE;
+}
+
+static int em_div_ex(struct x86_emulate_ctxt *ctxt)
 {
-	unsigned long *rax = &ctxt->regs[VCPU_REGS_RAX];
-	unsigned long *rdx = &ctxt->regs[VCPU_REGS_RDX];
 	u8 de = 0;
 
-	switch (ctxt->modrm_reg) {
-	case 0 ... 1:	/* test */
-		emulate_2op_SrcV("test", ctxt->src, ctxt->dst, ctxt->eflags);
-		break;
-	case 2:	/* not */
-		ctxt->dst.val = ~ctxt->dst.val;
-		break;
-	case 3:	/* neg */
-		emulate_1op("neg", ctxt->dst, ctxt->eflags);
-		break;
-	case 4: /* mul */
-		emulate_1op_rax_rdx("mul", ctxt->src, *rax, *rdx, ctxt->eflags);
-		break;
-	case 5: /* imul */
-		emulate_1op_rax_rdx("imul", ctxt->src, *rax, *rdx, ctxt->eflags);
-		break;
-	case 6: /* div */
-		emulate_1op_rax_rdx_ex("div", ctxt->src, *rax, *rdx,
-				       ctxt->eflags, de);
-		break;
-	case 7: /* idiv */
-		emulate_1op_rax_rdx_ex("idiv", ctxt->src, *rax, *rdx,
-				       ctxt->eflags, de);
-		break;
-	default:
-		return X86EMUL_UNHANDLEABLE;
-	}
+	emulate_1op_rax_rdx(ctxt, "div", de);
+	if (de)
+		return emulate_de(ctxt);
+	return X86EMUL_CONTINUE;
+}
+
+static int em_idiv_ex(struct x86_emulate_ctxt *ctxt)
+{
+	u8 de = 0;
+
+	emulate_1op_rax_rdx(ctxt, "idiv", de);
 	if (de)
 		return emulate_de(ctxt);
 	return X86EMUL_CONTINUE;
@@ -1743,10 +1762,10 @@
 
 	switch (ctxt->modrm_reg) {
 	case 0:	/* inc */
-		emulate_1op("inc", ctxt->dst, ctxt->eflags);
+		emulate_1op(ctxt, "inc");
 		break;
 	case 1:	/* dec */
-		emulate_1op("dec", ctxt->dst, ctxt->eflags);
+		emulate_1op(ctxt, "dec");
 		break;
 	case 2: /* call near abs */ {
 		long int old_eip;
@@ -1812,8 +1831,9 @@
 	return rc;
 }
 
-static int emulate_load_segment(struct x86_emulate_ctxt *ctxt, int seg)
+static int em_lseg(struct x86_emulate_ctxt *ctxt)
 {
+	int seg = ctxt->src2.val;
 	unsigned short sel;
 	int rc;
 
@@ -2452,7 +2472,7 @@
 	ctxt->src.type = OP_IMM;
 	ctxt->src.val = 0;
 	ctxt->src.bytes = 1;
-	emulate_2op_SrcV("or", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "or");
 	ctxt->eflags &= ~(X86_EFLAGS_AF | X86_EFLAGS_CF);
 	if (cf)
 		ctxt->eflags |= X86_EFLAGS_CF;
@@ -2502,49 +2522,49 @@
 
 static int em_add(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("add", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "add");
 	return X86EMUL_CONTINUE;
 }
 
 static int em_or(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("or", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "or");
 	return X86EMUL_CONTINUE;
 }
 
 static int em_adc(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("adc", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "adc");
 	return X86EMUL_CONTINUE;
 }
 
 static int em_sbb(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("sbb", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "sbb");
 	return X86EMUL_CONTINUE;
 }
 
 static int em_and(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("and", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "and");
 	return X86EMUL_CONTINUE;
 }
 
 static int em_sub(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("sub", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "sub");
 	return X86EMUL_CONTINUE;
 }
 
 static int em_xor(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("xor", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "xor");
 	return X86EMUL_CONTINUE;
 }
 
 static int em_cmp(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("cmp", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "cmp");
 	/* Disable writeback. */
 	ctxt->dst.type = OP_NONE;
 	return X86EMUL_CONTINUE;
@@ -2552,7 +2572,9 @@
 
 static int em_test(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV("test", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV(ctxt, "test");
+	/* Disable writeback. */
+	ctxt->dst.type = OP_NONE;
 	return X86EMUL_CONTINUE;
 }
 
@@ -2570,7 +2592,7 @@
 
 static int em_imul(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_2op_SrcV_nobyte("imul", ctxt->src, ctxt->dst, ctxt->eflags);
+	emulate_2op_SrcV_nobyte(ctxt, "imul");
 	return X86EMUL_CONTINUE;
 }
 
@@ -3025,9 +3047,14 @@
 };
 
 static struct opcode group3[] = {
-	D(DstMem | SrcImm | ModRM), D(DstMem | SrcImm | ModRM),
-	D(DstMem | SrcNone | ModRM | Lock), D(DstMem | SrcNone | ModRM | Lock),
-	X4(D(SrcMem | ModRM)),
+	I(DstMem | SrcImm | ModRM, em_test),
+	I(DstMem | SrcImm | ModRM, em_test),
+	I(DstMem | SrcNone | ModRM | Lock, em_not),
+	I(DstMem | SrcNone | ModRM | Lock, em_neg),
+	I(SrcMem | ModRM, em_mul_ex),
+	I(SrcMem | ModRM, em_imul_ex),
+	I(SrcMem | ModRM, em_div_ex),
+	I(SrcMem | ModRM, em_idiv_ex),
 };
 
 static struct opcode group4[] = {
@@ -3090,16 +3117,20 @@
 static struct opcode opcode_table[256] = {
 	/* 0x00 - 0x07 */
 	I6ALU(Lock, em_add),
-	D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64),
+	I(ImplicitOps | Stack | No64 | Src2ES, em_push_sreg),
+	I(ImplicitOps | Stack | No64 | Src2ES, em_pop_sreg),
 	/* 0x08 - 0x0F */
 	I6ALU(Lock, em_or),
-	D(ImplicitOps | Stack | No64), N,
+	I(ImplicitOps | Stack | No64 | Src2CS, em_push_sreg),
+	N,
 	/* 0x10 - 0x17 */
 	I6ALU(Lock, em_adc),
-	D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64),
+	I(ImplicitOps | Stack | No64 | Src2SS, em_push_sreg),
+	I(ImplicitOps | Stack | No64 | Src2SS, em_pop_sreg),
 	/* 0x18 - 0x1F */
 	I6ALU(Lock, em_sbb),
-	D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64),
+	I(ImplicitOps | Stack | No64 | Src2DS, em_push_sreg),
+	I(ImplicitOps | Stack | No64 | Src2DS, em_pop_sreg),
 	/* 0x20 - 0x27 */
 	I6ALU(Lock, em_and), N, N,
 	/* 0x28 - 0x2F */
@@ -3167,7 +3198,8 @@
 	D2bv(DstMem | SrcImmByte | ModRM),
 	I(ImplicitOps | Stack | SrcImmU16, em_ret_near_imm),
 	I(ImplicitOps | Stack, em_ret),
-	D(DstReg | SrcMemFAddr | ModRM | No64), D(DstReg | SrcMemFAddr | ModRM | No64),
+	I(DstReg | SrcMemFAddr | ModRM | No64 | Src2ES, em_lseg),
+	I(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS, em_lseg),
 	G(ByteOp, group11), G(0, group11),
 	/* 0xC8 - 0xCF */
 	N, N, N, I(ImplicitOps | Stack, em_ret_far),
@@ -3242,20 +3274,22 @@
 	/* 0x90 - 0x9F */
 	X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)),
 	/* 0xA0 - 0xA7 */
-	D(ImplicitOps | Stack), D(ImplicitOps | Stack),
+	I(Stack | Src2FS, em_push_sreg), I(Stack | Src2FS, em_pop_sreg),
 	DI(ImplicitOps, cpuid), D(DstMem | SrcReg | ModRM | BitOp),
 	D(DstMem | SrcReg | Src2ImmByte | ModRM),
 	D(DstMem | SrcReg | Src2CL | ModRM), N, N,
 	/* 0xA8 - 0xAF */
-	D(ImplicitOps | Stack), D(ImplicitOps | Stack),
+	I(Stack | Src2GS, em_push_sreg), I(Stack | Src2GS, em_pop_sreg),
 	DI(ImplicitOps, rsm), D(DstMem | SrcReg | ModRM | BitOp | Lock),
 	D(DstMem | SrcReg | Src2ImmByte | ModRM),
 	D(DstMem | SrcReg | Src2CL | ModRM),
 	D(ModRM), I(DstReg | SrcMem | ModRM, em_imul),
 	/* 0xB0 - 0xB7 */
 	D2bv(DstMem | SrcReg | ModRM | Lock),
-	D(DstReg | SrcMemFAddr | ModRM), D(DstMem | SrcReg | ModRM | BitOp | Lock),
-	D(DstReg | SrcMemFAddr | ModRM), D(DstReg | SrcMemFAddr | ModRM),
+	I(DstReg | SrcMemFAddr | ModRM | Src2SS, em_lseg),
+	D(DstMem | SrcReg | ModRM | BitOp | Lock),
+	I(DstReg | SrcMemFAddr | ModRM | Src2FS, em_lseg),
+	I(DstReg | SrcMemFAddr | ModRM | Src2GS, em_lseg),
 	D(ByteOp | DstReg | SrcMem | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
 	/* 0xB8 - 0xBF */
 	N, N,
@@ -3309,13 +3343,13 @@
 	/* NB. Immediates are sign-extended as necessary. */
 	switch (op->bytes) {
 	case 1:
-		op->val = insn_fetch(s8, 1, ctxt->_eip);
+		op->val = insn_fetch(s8, ctxt);
 		break;
 	case 2:
-		op->val = insn_fetch(s16, 2, ctxt->_eip);
+		op->val = insn_fetch(s16, ctxt);
 		break;
 	case 4:
-		op->val = insn_fetch(s32, 4, ctxt->_eip);
+		op->val = insn_fetch(s32, ctxt);
 		break;
 	}
 	if (!sign_extension) {
@@ -3335,6 +3369,125 @@
 	return rc;
 }
 
+static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
+			  unsigned d)
+{
+	int rc = X86EMUL_CONTINUE;
+
+	switch (d) {
+	case OpReg:
+		decode_register_operand(ctxt, op,
+			 op == &ctxt->dst &&
+			 ctxt->twobyte && (ctxt->b == 0xb6 || ctxt->b == 0xb7));
+		break;
+	case OpImmUByte:
+		rc = decode_imm(ctxt, op, 1, false);
+		break;
+	case OpMem:
+		ctxt->memop.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+	mem_common:
+		*op = ctxt->memop;
+		ctxt->memopp = op;
+		if ((ctxt->d & BitOp) && op == &ctxt->dst)
+			fetch_bit_operand(ctxt);
+		op->orig_val = op->val;
+		break;
+	case OpMem64:
+		ctxt->memop.bytes = 8;
+		goto mem_common;
+	case OpAcc:
+		op->type = OP_REG;
+		op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+		op->addr.reg = &ctxt->regs[VCPU_REGS_RAX];
+		fetch_register_operand(op);
+		op->orig_val = op->val;
+		break;
+	case OpDI:
+		op->type = OP_MEM;
+		op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+		op->addr.mem.ea =
+			register_address(ctxt, ctxt->regs[VCPU_REGS_RDI]);
+		op->addr.mem.seg = VCPU_SREG_ES;
+		op->val = 0;
+		break;
+	case OpDX:
+		op->type = OP_REG;
+		op->bytes = 2;
+		op->addr.reg = &ctxt->regs[VCPU_REGS_RDX];
+		fetch_register_operand(op);
+		break;
+	case OpCL:
+		op->bytes = 1;
+		op->val = ctxt->regs[VCPU_REGS_RCX] & 0xff;
+		break;
+	case OpImmByte:
+		rc = decode_imm(ctxt, op, 1, true);
+		break;
+	case OpOne:
+		op->bytes = 1;
+		op->val = 1;
+		break;
+	case OpImm:
+		rc = decode_imm(ctxt, op, imm_size(ctxt), true);
+		break;
+	case OpMem16:
+		ctxt->memop.bytes = 2;
+		goto mem_common;
+	case OpMem32:
+		ctxt->memop.bytes = 4;
+		goto mem_common;
+	case OpImmU16:
+		rc = decode_imm(ctxt, op, 2, false);
+		break;
+	case OpImmU:
+		rc = decode_imm(ctxt, op, imm_size(ctxt), false);
+		break;
+	case OpSI:
+		op->type = OP_MEM;
+		op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+		op->addr.mem.ea =
+			register_address(ctxt, ctxt->regs[VCPU_REGS_RSI]);
+		op->addr.mem.seg = seg_override(ctxt);
+		op->val = 0;
+		break;
+	case OpImmFAddr:
+		op->type = OP_IMM;
+		op->addr.mem.ea = ctxt->_eip;
+		op->bytes = ctxt->op_bytes + 2;
+		insn_fetch_arr(op->valptr, op->bytes, ctxt);
+		break;
+	case OpMemFAddr:
+		ctxt->memop.bytes = ctxt->op_bytes + 2;
+		goto mem_common;
+	case OpES:
+		op->val = VCPU_SREG_ES;
+		break;
+	case OpCS:
+		op->val = VCPU_SREG_CS;
+		break;
+	case OpSS:
+		op->val = VCPU_SREG_SS;
+		break;
+	case OpDS:
+		op->val = VCPU_SREG_DS;
+		break;
+	case OpFS:
+		op->val = VCPU_SREG_FS;
+		break;
+	case OpGS:
+		op->val = VCPU_SREG_GS;
+		break;
+	case OpImplicit:
+		/* Special instructions do their own operand decoding. */
+	default:
+		op->type = OP_NONE; /* Disable writeback. */
+		break;
+	}
+
+done:
+	return rc;
+}
+
 int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 {
 	int rc = X86EMUL_CONTINUE;
@@ -3342,8 +3495,9 @@
 	int def_op_bytes, def_ad_bytes, goffset, simd_prefix;
 	bool op_prefix = false;
 	struct opcode opcode;
-	struct operand memop = { .type = OP_NONE }, *memopp = NULL;
 
+	ctxt->memop.type = OP_NONE;
+	ctxt->memopp = NULL;
 	ctxt->_eip = ctxt->eip;
 	ctxt->fetch.start = ctxt->_eip;
 	ctxt->fetch.end = ctxt->fetch.start + insn_len;
@@ -3366,7 +3520,7 @@
 		break;
 #endif
 	default:
-		return -1;
+		return EMULATION_FAILED;
 	}
 
 	ctxt->op_bytes = def_op_bytes;
@@ -3374,7 +3528,7 @@
 
 	/* Legacy prefixes. */
 	for (;;) {
-		switch (ctxt->b = insn_fetch(u8, 1, ctxt->_eip)) {
+		switch (ctxt->b = insn_fetch(u8, ctxt)) {
 		case 0x66:	/* operand-size override */
 			op_prefix = true;
 			/* switch between 2/4 bytes */
@@ -3430,7 +3584,7 @@
 	/* Two-byte opcode? */
 	if (ctxt->b == 0x0f) {
 		ctxt->twobyte = 1;
-		ctxt->b = insn_fetch(u8, 1, ctxt->_eip);
+		ctxt->b = insn_fetch(u8, ctxt);
 		opcode = twobyte_table[ctxt->b];
 	}
 	ctxt->d = opcode.flags;
@@ -3438,13 +3592,13 @@
 	while (ctxt->d & GroupMask) {
 		switch (ctxt->d & GroupMask) {
 		case Group:
-			ctxt->modrm = insn_fetch(u8, 1, ctxt->_eip);
+			ctxt->modrm = insn_fetch(u8, ctxt);
 			--ctxt->_eip;
 			goffset = (ctxt->modrm >> 3) & 7;
 			opcode = opcode.u.group[goffset];
 			break;
 		case GroupDual:
-			ctxt->modrm = insn_fetch(u8, 1, ctxt->_eip);
+			ctxt->modrm = insn_fetch(u8, ctxt);
 			--ctxt->_eip;
 			goffset = (ctxt->modrm >> 3) & 7;
 			if ((ctxt->modrm >> 6) == 3)
@@ -3458,7 +3612,7 @@
 			break;
 		case Prefix:
 			if (ctxt->rep_prefix && op_prefix)
-				return X86EMUL_UNHANDLEABLE;
+				return EMULATION_FAILED;
 			simd_prefix = op_prefix ? 0x66 : ctxt->rep_prefix;
 			switch (simd_prefix) {
 			case 0x00: opcode = opcode.u.gprefix->pfx_no; break;
@@ -3468,10 +3622,10 @@
 			}
 			break;
 		default:
-			return X86EMUL_UNHANDLEABLE;
+			return EMULATION_FAILED;
 		}
 
-		ctxt->d &= ~GroupMask;
+		ctxt->d &= ~(u64)GroupMask;
 		ctxt->d |= opcode.flags;
 	}
 
@@ -3481,10 +3635,10 @@
 
 	/* Unrecognised? */
 	if (ctxt->d == 0 || (ctxt->d & Undefined))
-		return -1;
+		return EMULATION_FAILED;
 
 	if (!(ctxt->d & VendorSpecific) && ctxt->only_vendor_specific_insn)
-		return -1;
+		return EMULATION_FAILED;
 
 	if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack))
 		ctxt->op_bytes = 8;
@@ -3501,96 +3655,27 @@
 
 	/* ModRM and SIB bytes. */
 	if (ctxt->d & ModRM) {
-		rc = decode_modrm(ctxt, &memop);
+		rc = decode_modrm(ctxt, &ctxt->memop);
 		if (!ctxt->has_seg_override)
 			set_seg_override(ctxt, ctxt->modrm_seg);
 	} else if (ctxt->d & MemAbs)
-		rc = decode_abs(ctxt, &memop);
+		rc = decode_abs(ctxt, &ctxt->memop);
 	if (rc != X86EMUL_CONTINUE)
 		goto done;
 
 	if (!ctxt->has_seg_override)
 		set_seg_override(ctxt, VCPU_SREG_DS);
 
-	memop.addr.mem.seg = seg_override(ctxt);
+	ctxt->memop.addr.mem.seg = seg_override(ctxt);
 
-	if (memop.type == OP_MEM && ctxt->ad_bytes != 8)
-		memop.addr.mem.ea = (u32)memop.addr.mem.ea;
+	if (ctxt->memop.type == OP_MEM && ctxt->ad_bytes != 8)
+		ctxt->memop.addr.mem.ea = (u32)ctxt->memop.addr.mem.ea;
 
 	/*
 	 * Decode and fetch the source operand: register, memory
 	 * or immediate.
 	 */
-	switch (ctxt->d & SrcMask) {
-	case SrcNone:
-		break;
-	case SrcReg:
-		decode_register_operand(ctxt, &ctxt->src, 0);
-		break;
-	case SrcMem16:
-		memop.bytes = 2;
-		goto srcmem_common;
-	case SrcMem32:
-		memop.bytes = 4;
-		goto srcmem_common;
-	case SrcMem:
-		memop.bytes = (ctxt->d & ByteOp) ? 1 :
-							   ctxt->op_bytes;
-	srcmem_common:
-		ctxt->src = memop;
-		memopp = &ctxt->src;
-		break;
-	case SrcImmU16:
-		rc = decode_imm(ctxt, &ctxt->src, 2, false);
-		break;
-	case SrcImm:
-		rc = decode_imm(ctxt, &ctxt->src, imm_size(ctxt), true);
-		break;
-	case SrcImmU:
-		rc = decode_imm(ctxt, &ctxt->src, imm_size(ctxt), false);
-		break;
-	case SrcImmByte:
-		rc = decode_imm(ctxt, &ctxt->src, 1, true);
-		break;
-	case SrcImmUByte:
-		rc = decode_imm(ctxt, &ctxt->src, 1, false);
-		break;
-	case SrcAcc:
-		ctxt->src.type = OP_REG;
-		ctxt->src.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
-		ctxt->src.addr.reg = &ctxt->regs[VCPU_REGS_RAX];
-		fetch_register_operand(&ctxt->src);
-		break;
-	case SrcOne:
-		ctxt->src.bytes = 1;
-		ctxt->src.val = 1;
-		break;
-	case SrcSI:
-		ctxt->src.type = OP_MEM;
-		ctxt->src.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
-		ctxt->src.addr.mem.ea =
-			register_address(ctxt, ctxt->regs[VCPU_REGS_RSI]);
-		ctxt->src.addr.mem.seg = seg_override(ctxt);
-		ctxt->src.val = 0;
-		break;
-	case SrcImmFAddr:
-		ctxt->src.type = OP_IMM;
-		ctxt->src.addr.mem.ea = ctxt->_eip;
-		ctxt->src.bytes = ctxt->op_bytes + 2;
-		insn_fetch_arr(ctxt->src.valptr, ctxt->src.bytes, ctxt->_eip);
-		break;
-	case SrcMemFAddr:
-		memop.bytes = ctxt->op_bytes + 2;
-		goto srcmem_common;
-		break;
-	case SrcDX:
-		ctxt->src.type = OP_REG;
-		ctxt->src.bytes = 2;
-		ctxt->src.addr.reg = &ctxt->regs[VCPU_REGS_RDX];
-		fetch_register_operand(&ctxt->src);
-		break;
-	}
-
+	rc = decode_operand(ctxt, &ctxt->src, (ctxt->d >> SrcShift) & OpMask);
 	if (rc != X86EMUL_CONTINUE)
 		goto done;
 
@@ -3598,85 +3683,18 @@
 	 * Decode and fetch the second source operand: register, memory
 	 * or immediate.
 	 */
-	switch (ctxt->d & Src2Mask) {
-	case Src2None:
-		break;
-	case Src2CL:
-		ctxt->src2.bytes = 1;
-		ctxt->src2.val = ctxt->regs[VCPU_REGS_RCX] & 0xff;
-		break;
-	case Src2ImmByte:
-		rc = decode_imm(ctxt, &ctxt->src2, 1, true);
-		break;
-	case Src2One:
-		ctxt->src2.bytes = 1;
-		ctxt->src2.val = 1;
-		break;
-	case Src2Imm:
-		rc = decode_imm(ctxt, &ctxt->src2, imm_size(ctxt), true);
-		break;
-	}
-
+	rc = decode_operand(ctxt, &ctxt->src2, (ctxt->d >> Src2Shift) & OpMask);
 	if (rc != X86EMUL_CONTINUE)
 		goto done;
 
 	/* Decode and fetch the destination operand: register or memory. */
-	switch (ctxt->d & DstMask) {
-	case DstReg:
-		decode_register_operand(ctxt, &ctxt->dst,
-			 ctxt->twobyte && (ctxt->b == 0xb6 || ctxt->b == 0xb7));
-		break;
-	case DstImmUByte:
-		ctxt->dst.type = OP_IMM;
-		ctxt->dst.addr.mem.ea = ctxt->_eip;
-		ctxt->dst.bytes = 1;
-		ctxt->dst.val = insn_fetch(u8, 1, ctxt->_eip);
-		break;
-	case DstMem:
-	case DstMem64:
-		ctxt->dst = memop;
-		memopp = &ctxt->dst;
-		if ((ctxt->d & DstMask) == DstMem64)
-			ctxt->dst.bytes = 8;
-		else
-			ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
-		if (ctxt->d & BitOp)
-			fetch_bit_operand(ctxt);
-		ctxt->dst.orig_val = ctxt->dst.val;
-		break;
-	case DstAcc:
-		ctxt->dst.type = OP_REG;
-		ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
-		ctxt->dst.addr.reg = &ctxt->regs[VCPU_REGS_RAX];
-		fetch_register_operand(&ctxt->dst);
-		ctxt->dst.orig_val = ctxt->dst.val;
-		break;
-	case DstDI:
-		ctxt->dst.type = OP_MEM;
-		ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
-		ctxt->dst.addr.mem.ea =
-			register_address(ctxt, ctxt->regs[VCPU_REGS_RDI]);
-		ctxt->dst.addr.mem.seg = VCPU_SREG_ES;
-		ctxt->dst.val = 0;
-		break;
-	case DstDX:
-		ctxt->dst.type = OP_REG;
-		ctxt->dst.bytes = 2;
-		ctxt->dst.addr.reg = &ctxt->regs[VCPU_REGS_RDX];
-		fetch_register_operand(&ctxt->dst);
-		break;
-	case ImplicitOps:
-		/* Special instructions do their own operand decoding. */
-	default:
-		ctxt->dst.type = OP_NONE; /* Disable writeback. */
-		break;
-	}
+	rc = decode_operand(ctxt, &ctxt->dst, (ctxt->d >> DstShift) & OpMask);
 
 done:
-	if (memopp && memopp->type == OP_MEM && ctxt->rip_relative)
-		memopp->addr.mem.ea += ctxt->_eip;
+	if (ctxt->memopp && ctxt->memopp->type == OP_MEM && ctxt->rip_relative)
+		ctxt->memopp->addr.mem.ea += ctxt->_eip;
 
-	return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK;
+	return (rc != X86EMUL_CONTINUE) ? EMULATION_FAILED : EMULATION_OK;
 }
 
 static bool string_insn_completed(struct x86_emulate_ctxt *ctxt)
@@ -3825,32 +3843,11 @@
 		goto twobyte_insn;
 
 	switch (ctxt->b) {
-	case 0x06:		/* push es */
-		rc = emulate_push_sreg(ctxt, VCPU_SREG_ES);
-		break;
-	case 0x07:		/* pop es */
-		rc = emulate_pop_sreg(ctxt, VCPU_SREG_ES);
-		break;
-	case 0x0e:		/* push cs */
-		rc = emulate_push_sreg(ctxt, VCPU_SREG_CS);
-		break;
-	case 0x16:		/* push ss */
-		rc = emulate_push_sreg(ctxt, VCPU_SREG_SS);
-		break;
-	case 0x17:		/* pop ss */
-		rc = emulate_pop_sreg(ctxt, VCPU_SREG_SS);
-		break;
-	case 0x1e:		/* push ds */
-		rc = emulate_push_sreg(ctxt, VCPU_SREG_DS);
-		break;
-	case 0x1f:		/* pop ds */
-		rc = emulate_pop_sreg(ctxt, VCPU_SREG_DS);
-		break;
 	case 0x40 ... 0x47: /* inc r16/r32 */
-		emulate_1op("inc", ctxt->dst, ctxt->eflags);
+		emulate_1op(ctxt, "inc");
 		break;
 	case 0x48 ... 0x4f: /* dec r16/r32 */
-		emulate_1op("dec", ctxt->dst, ctxt->eflags);
+		emulate_1op(ctxt, "dec");
 		break;
 	case 0x63:		/* movsxd */
 		if (ctxt->mode != X86EMUL_MODE_PROT64)
@@ -3891,12 +3888,6 @@
 	case 0xc0 ... 0xc1:
 		rc = em_grp2(ctxt);
 		break;
-	case 0xc4:		/* les */
-		rc = emulate_load_segment(ctxt, VCPU_SREG_ES);
-		break;
-	case 0xc5:		/* lds */
-		rc = emulate_load_segment(ctxt, VCPU_SREG_DS);
-		break;
 	case 0xcc:		/* int3 */
 		rc = emulate_int(ctxt, 3);
 		break;
@@ -3953,9 +3944,6 @@
 		/* complement carry flag from eflags reg */
 		ctxt->eflags ^= EFLG_CF;
 		break;
-	case 0xf6 ... 0xf7:	/* Grp3 */
-		rc = em_grp3(ctxt);
-		break;
 	case 0xf8: /* clc */
 		ctxt->eflags &= ~EFLG_CF;
 		break;
@@ -4103,36 +4091,24 @@
 	case 0x90 ... 0x9f:     /* setcc r/m8 */
 		ctxt->dst.val = test_cc(ctxt->b, ctxt->eflags);
 		break;
-	case 0xa0:	  /* push fs */
-		rc = emulate_push_sreg(ctxt, VCPU_SREG_FS);
-		break;
-	case 0xa1:	 /* pop fs */
-		rc = emulate_pop_sreg(ctxt, VCPU_SREG_FS);
-		break;
 	case 0xa3:
 	      bt:		/* bt */
 		ctxt->dst.type = OP_NONE;
 		/* only subword offset */
 		ctxt->src.val &= (ctxt->dst.bytes << 3) - 1;
-		emulate_2op_SrcV_nobyte("bt", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcV_nobyte(ctxt, "bt");
 		break;
 	case 0xa4: /* shld imm8, r, r/m */
 	case 0xa5: /* shld cl, r, r/m */
-		emulate_2op_cl("shld", ctxt->src2, ctxt->src, ctxt->dst, ctxt->eflags);
-		break;
-	case 0xa8:	/* push gs */
-		rc = emulate_push_sreg(ctxt, VCPU_SREG_GS);
-		break;
-	case 0xa9:	/* pop gs */
-		rc = emulate_pop_sreg(ctxt, VCPU_SREG_GS);
+		emulate_2op_cl(ctxt, "shld");
 		break;
 	case 0xab:
 	      bts:		/* bts */
-		emulate_2op_SrcV_nobyte("bts", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcV_nobyte(ctxt, "bts");
 		break;
 	case 0xac: /* shrd imm8, r, r/m */
 	case 0xad: /* shrd cl, r, r/m */
-		emulate_2op_cl("shrd", ctxt->src2, ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_cl(ctxt, "shrd");
 		break;
 	case 0xae:              /* clflush */
 		break;
@@ -4143,7 +4119,7 @@
 		 */
 		ctxt->src.orig_val = ctxt->src.val;
 		ctxt->src.val = ctxt->regs[VCPU_REGS_RAX];
-		emulate_2op_SrcV("cmp", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcV(ctxt, "cmp");
 		if (ctxt->eflags & EFLG_ZF) {
 			/* Success: write back to memory. */
 			ctxt->dst.val = ctxt->src.orig_val;
@@ -4153,18 +4129,9 @@
 			ctxt->dst.addr.reg = (unsigned long *)&ctxt->regs[VCPU_REGS_RAX];
 		}
 		break;
-	case 0xb2:		/* lss */
-		rc = emulate_load_segment(ctxt, VCPU_SREG_SS);
-		break;
 	case 0xb3:
 	      btr:		/* btr */
-		emulate_2op_SrcV_nobyte("btr", ctxt->src, ctxt->dst, ctxt->eflags);
-		break;
-	case 0xb4:		/* lfs */
-		rc = emulate_load_segment(ctxt, VCPU_SREG_FS);
-		break;
-	case 0xb5:		/* lgs */
-		rc = emulate_load_segment(ctxt, VCPU_SREG_GS);
+		emulate_2op_SrcV_nobyte(ctxt, "btr");
 		break;
 	case 0xb6 ... 0xb7:	/* movzx */
 		ctxt->dst.bytes = ctxt->op_bytes;
@@ -4185,7 +4152,7 @@
 		break;
 	case 0xbb:
 	      btc:		/* btc */
-		emulate_2op_SrcV_nobyte("btc", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcV_nobyte(ctxt, "btc");
 		break;
 	case 0xbc: {		/* bsf */
 		u8 zf;
@@ -4217,7 +4184,7 @@
 							(s16) ctxt->src.val;
 		break;
 	case 0xc0 ... 0xc1:	/* xadd */
-		emulate_2op_SrcV("add", ctxt->src, ctxt->dst, ctxt->eflags);
+		emulate_2op_SrcV(ctxt, "add");
 		/* Write back the register source. */
 		ctxt->src.val = ctxt->dst.orig_val;
 		write_register_operand(&ctxt->src);
diff -druN linux-libre-3.1-gnu/arch/x86/kvm/i8254.c linux-libre-3.2-gnu/arch/x86/kvm/i8254.c
--- linux-libre-3.1-gnu/arch/x86/kvm/i8254.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kvm/i8254.c	2012-01-04 18:55:44.000000000 -0500
@@ -338,11 +338,15 @@
 		return HRTIMER_NORESTART;
 }
 
-static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period)
+static void create_pit_timer(struct kvm *kvm, u32 val, int is_period)
 {
+	struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
 	struct kvm_timer *pt = &ps->pit_timer;
 	s64 interval;
 
+	if (!irqchip_in_kernel(kvm))
+		return;
+
 	interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ);
 
 	pr_debug("create pit timer, interval is %llu nsec\n", interval);
@@ -394,13 +398,13 @@
         /* FIXME: enhance mode 4 precision */
 	case 4:
 		if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)) {
-			create_pit_timer(ps, val, 0);
+			create_pit_timer(kvm, val, 0);
 		}
 		break;
 	case 2:
 	case 3:
 		if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)){
-			create_pit_timer(ps, val, 1);
+			create_pit_timer(kvm, val, 1);
 		}
 		break;
 	default:
@@ -713,14 +717,16 @@
 	kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
 
 	kvm_iodevice_init(&pit->dev, &pit_dev_ops);
-	ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, &pit->dev);
+	ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, KVM_PIT_BASE_ADDRESS,
+				      KVM_PIT_MEM_LENGTH, &pit->dev);
 	if (ret < 0)
 		goto fail;
 
 	if (flags & KVM_PIT_SPEAKER_DUMMY) {
 		kvm_iodevice_init(&pit->speaker_dev, &speaker_dev_ops);
 		ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS,
-						&pit->speaker_dev);
+					      KVM_SPEAKER_BASE_ADDRESS, 4,
+					      &pit->speaker_dev);
 		if (ret < 0)
 			goto fail_unregister;
 	}
diff -druN linux-libre-3.1-gnu/arch/x86/kvm/i8259.c linux-libre-3.2-gnu/arch/x86/kvm/i8259.c
--- linux-libre-3.1-gnu/arch/x86/kvm/i8259.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kvm/i8259.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,9 @@
 #include <linux/kvm_host.h>
 #include "trace.h"
 
+#define pr_pic_unimpl(fmt, ...)	\
+	pr_err_ratelimited("kvm: pic: " fmt, ## __VA_ARGS__)
+
 static void pic_irq_request(struct kvm *kvm, int level);
 
 static void pic_lock(struct kvm_pic *s)
@@ -306,10 +309,10 @@
 			}
 			s->init_state = 1;
 			if (val & 0x02)
-				printk(KERN_ERR "single mode not supported");
+				pr_pic_unimpl("single mode not supported");
 			if (val & 0x08)
-				printk(KERN_ERR
-				       "level sensitive irq not supported");
+				pr_pic_unimpl(
+					"level sensitive irq not supported");
 		} else if (val & 0x08) {
 			if (val & 0x04)
 				s->poll = 1;
@@ -459,22 +462,15 @@
 	}
 }
 
-static inline struct kvm_pic *to_pic(struct kvm_io_device *dev)
-{
-	return container_of(dev, struct kvm_pic, dev);
-}
-
-static int picdev_write(struct kvm_io_device *this,
+static int picdev_write(struct kvm_pic *s,
 			 gpa_t addr, int len, const void *val)
 {
-	struct kvm_pic *s = to_pic(this);
 	unsigned char data = *(unsigned char *)val;
 	if (!picdev_in_range(addr))
 		return -EOPNOTSUPP;
 
 	if (len != 1) {
-		if (printk_ratelimit())
-			printk(KERN_ERR "PIC: non byte write\n");
+		pr_pic_unimpl("non byte write\n");
 		return 0;
 	}
 	pic_lock(s);
@@ -494,17 +490,15 @@
 	return 0;
 }
 
-static int picdev_read(struct kvm_io_device *this,
+static int picdev_read(struct kvm_pic *s,
 		       gpa_t addr, int len, void *val)
 {
-	struct kvm_pic *s = to_pic(this);
 	unsigned char data = 0;
 	if (!picdev_in_range(addr))
 		return -EOPNOTSUPP;
 
 	if (len != 1) {
-		if (printk_ratelimit())
-			printk(KERN_ERR "PIC: non byte read\n");
+		pr_pic_unimpl("non byte read\n");
 		return 0;
 	}
 	pic_lock(s);
@@ -525,6 +519,48 @@
 	return 0;
 }
 
+static int picdev_master_write(struct kvm_io_device *dev,
+			       gpa_t addr, int len, const void *val)
+{
+	return picdev_write(container_of(dev, struct kvm_pic, dev_master),
+			    addr, len, val);
+}
+
+static int picdev_master_read(struct kvm_io_device *dev,
+			      gpa_t addr, int len, void *val)
+{
+	return picdev_read(container_of(dev, struct kvm_pic, dev_master),
+			    addr, len, val);
+}
+
+static int picdev_slave_write(struct kvm_io_device *dev,
+			      gpa_t addr, int len, const void *val)
+{
+	return picdev_write(container_of(dev, struct kvm_pic, dev_slave),
+			    addr, len, val);
+}
+
+static int picdev_slave_read(struct kvm_io_device *dev,
+			     gpa_t addr, int len, void *val)
+{
+	return picdev_read(container_of(dev, struct kvm_pic, dev_slave),
+			    addr, len, val);
+}
+
+static int picdev_eclr_write(struct kvm_io_device *dev,
+			     gpa_t addr, int len, const void *val)
+{
+	return picdev_write(container_of(dev, struct kvm_pic, dev_eclr),
+			    addr, len, val);
+}
+
+static int picdev_eclr_read(struct kvm_io_device *dev,
+			    gpa_t addr, int len, void *val)
+{
+	return picdev_read(container_of(dev, struct kvm_pic, dev_eclr),
+			    addr, len, val);
+}
+
 /*
  * callback when PIC0 irq status changed
  */
@@ -537,9 +573,19 @@
 	s->output = level;
 }
 
-static const struct kvm_io_device_ops picdev_ops = {
-	.read     = picdev_read,
-	.write    = picdev_write,
+static const struct kvm_io_device_ops picdev_master_ops = {
+	.read     = picdev_master_read,
+	.write    = picdev_master_write,
+};
+
+static const struct kvm_io_device_ops picdev_slave_ops = {
+	.read     = picdev_slave_read,
+	.write    = picdev_slave_write,
+};
+
+static const struct kvm_io_device_ops picdev_eclr_ops = {
+	.read     = picdev_eclr_read,
+	.write    = picdev_eclr_write,
 };
 
 struct kvm_pic *kvm_create_pic(struct kvm *kvm)
@@ -560,16 +606,39 @@
 	/*
 	 * Initialize PIO device
 	 */
-	kvm_iodevice_init(&s->dev, &picdev_ops);
+	kvm_iodevice_init(&s->dev_master, &picdev_master_ops);
+	kvm_iodevice_init(&s->dev_slave, &picdev_slave_ops);
+	kvm_iodevice_init(&s->dev_eclr, &picdev_eclr_ops);
 	mutex_lock(&kvm->slots_lock);
-	ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, &s->dev);
+	ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, 0x20, 2,
+				      &s->dev_master);
+	if (ret < 0)
+		goto fail_unlock;
+
+	ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, 0xa0, 2, &s->dev_slave);
+	if (ret < 0)
+		goto fail_unreg_2;
+
+	ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, 0x4d0, 2, &s->dev_eclr);
+	if (ret < 0)
+		goto fail_unreg_1;
+
 	mutex_unlock(&kvm->slots_lock);
-	if (ret < 0) {
-		kfree(s);
-		return NULL;
-	}
 
 	return s;
+
+fail_unreg_1:
+	kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &s->dev_slave);
+
+fail_unreg_2:
+	kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &s->dev_master);
+
+fail_unlock:
+	mutex_unlock(&kvm->slots_lock);
+
+	kfree(s);
+
+	return NULL;
 }
 
 void kvm_destroy_pic(struct kvm *kvm)
@@ -577,7 +646,9 @@
 	struct kvm_pic *vpic = kvm->arch.vpic;
 
 	if (vpic) {
-		kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev);
+		kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev_master);
+		kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev_slave);
+		kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev_eclr);
 		kvm->arch.vpic = NULL;
 		kfree(vpic);
 	}
diff -druN linux-libre-3.1-gnu/arch/x86/kvm/irq.h linux-libre-3.2-gnu/arch/x86/kvm/irq.h
--- linux-libre-3.1-gnu/arch/x86/kvm/irq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kvm/irq.h	2012-01-04 18:55:44.000000000 -0500
@@ -66,7 +66,9 @@
 	struct kvm *kvm;
 	struct kvm_kpic_state pics[2]; /* 0 is master pic, 1 is slave pic */
 	int output;		/* intr from master PIC */
-	struct kvm_io_device dev;
+	struct kvm_io_device dev_master;
+	struct kvm_io_device dev_slave;
+	struct kvm_io_device dev_eclr;
 	void (*ack_notifier)(void *opaque, int irq);
 	unsigned long irq_states[16];
 };
diff -druN linux-libre-3.1-gnu/arch/x86/kvm/kvm_cache_regs.h linux-libre-3.2-gnu/arch/x86/kvm/kvm_cache_regs.h
--- linux-libre-3.1-gnu/arch/x86/kvm/kvm_cache_regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kvm/kvm_cache_regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -45,13 +45,6 @@
 	return vcpu->arch.walk_mmu->pdptrs[index];
 }
 
-static inline u64 kvm_pdptr_read_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, int index)
-{
-	load_pdptrs(vcpu, mmu, mmu->get_cr3(vcpu));
-
-	return mmu->pdptrs[index];
-}
-
 static inline ulong kvm_read_cr0_bits(struct kvm_vcpu *vcpu, ulong mask)
 {
 	ulong tmask = mask & KVM_POSSIBLE_CR0_GUEST_BITS;
diff -druN linux-libre-3.1-gnu/arch/x86/kvm/kvm_timer.h linux-libre-3.2-gnu/arch/x86/kvm/kvm_timer.h
--- linux-libre-3.1-gnu/arch/x86/kvm/kvm_timer.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kvm/kvm_timer.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,8 @@
 struct kvm_timer {
 	struct hrtimer timer;
 	s64 period; 				/* unit: ns */
+	u32 timer_mode_mask;
+	u64 tscdeadline;
 	atomic_t pending;			/* accumulated triggered timers */
 	bool reinject;
 	struct kvm_timer_ops *t_ops;
diff -druN linux-libre-3.1-gnu/arch/x86/kvm/lapic.c linux-libre-3.2-gnu/arch/x86/kvm/lapic.c
--- linux-libre-3.1-gnu/arch/x86/kvm/lapic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kvm/lapic.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,6 +68,9 @@
 #define VEC_POS(v) ((v) & (32 - 1))
 #define REG_POS(v) (((v) >> 5) << 4)
 
+static unsigned int min_timer_period_us = 500;
+module_param(min_timer_period_us, uint, S_IRUGO | S_IWUSR);
+
 static inline u32 apic_get_reg(struct kvm_lapic *apic, int reg_off)
 {
 	return *((u32 *) (apic->regs + reg_off));
@@ -135,9 +138,23 @@
 	return apic_get_reg(apic, lvt_type) & APIC_VECTOR_MASK;
 }
 
+static inline int apic_lvtt_oneshot(struct kvm_lapic *apic)
+{
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_ONESHOT);
+}
+
 static inline int apic_lvtt_period(struct kvm_lapic *apic)
 {
-	return apic_get_reg(apic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC;
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_PERIODIC);
+}
+
+static inline int apic_lvtt_tscdeadline(struct kvm_lapic *apic)
+{
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) ==
+			APIC_LVT_TIMER_TSCDEADLINE);
 }
 
 static inline int apic_lvt_nmi_mode(u32 lvt_val)
@@ -166,7 +183,7 @@
 }
 
 static unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
-	LVT_MASK | APIC_LVT_TIMER_PERIODIC,	/* LVTT */
+	LVT_MASK ,      /* part LVTT mask, timer mode mask added at runtime */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTTHMR */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTPC */
 	LINT_MASK, LINT_MASK,	/* LVT0-1 */
@@ -316,8 +333,8 @@
 			result = 1;
 		break;
 	default:
-		printk(KERN_WARNING "Bad DFR vcpu %d: %08x\n",
-		       apic->vcpu->vcpu_id, apic_get_reg(apic, APIC_DFR));
+		apic_debug("Bad DFR vcpu %d: %08x\n",
+			   apic->vcpu->vcpu_id, apic_get_reg(apic, APIC_DFR));
 		break;
 	}
 
@@ -354,8 +371,8 @@
 		result = (target != source);
 		break;
 	default:
-		printk(KERN_WARNING "Bad dest shorthand value %x\n",
-		       short_hand);
+		apic_debug("kvm: apic: Bad dest shorthand value %x\n",
+			   short_hand);
 		break;
 	}
 
@@ -401,11 +418,11 @@
 		break;
 
 	case APIC_DM_REMRD:
-		printk(KERN_DEBUG "Ignoring delivery mode 3\n");
+		apic_debug("Ignoring delivery mode 3\n");
 		break;
 
 	case APIC_DM_SMI:
-		printk(KERN_DEBUG "Ignoring guest SMI\n");
+		apic_debug("Ignoring guest SMI\n");
 		break;
 
 	case APIC_DM_NMI:
@@ -565,11 +582,13 @@
 			val = kvm_apic_id(apic) << 24;
 		break;
 	case APIC_ARBPRI:
-		printk(KERN_WARNING "Access APIC ARBPRI register "
-		       "which is for P6\n");
+		apic_debug("Access APIC ARBPRI register which is for P6\n");
 		break;
 
 	case APIC_TMCCT:	/* Timer CCR */
+		if (apic_lvtt_tscdeadline(apic))
+			return 0;
+
 		val = apic_get_tmcct(apic);
 		break;
 
@@ -664,29 +683,40 @@
 
 static void start_apic_timer(struct kvm_lapic *apic)
 {
-	ktime_t now = apic->lapic_timer.timer.base->get_time();
-
-	apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT) *
-		    APIC_BUS_CYCLE_NS * apic->divide_count;
+	ktime_t now;
 	atomic_set(&apic->lapic_timer.pending, 0);
 
-	if (!apic->lapic_timer.period)
-		return;
-	/*
-	 * Do not allow the guest to program periodic timers with small
-	 * interval, since the hrtimers are not throttled by the host
-	 * scheduler.
-	 */
-	if (apic_lvtt_period(apic)) {
-		if (apic->lapic_timer.period < NSEC_PER_MSEC/2)
-			apic->lapic_timer.period = NSEC_PER_MSEC/2;
-	}
+	if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic)) {
+		/* lapic timer in oneshot or peroidic mode */
+		now = apic->lapic_timer.timer.base->get_time();
+		apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT)
+			    * APIC_BUS_CYCLE_NS * apic->divide_count;
 
-	hrtimer_start(&apic->lapic_timer.timer,
-		      ktime_add_ns(now, apic->lapic_timer.period),
-		      HRTIMER_MODE_ABS);
+		if (!apic->lapic_timer.period)
+			return;
+		/*
+		 * Do not allow the guest to program periodic timers with small
+		 * interval, since the hrtimers are not throttled by the host
+		 * scheduler.
+		 */
+		if (apic_lvtt_period(apic)) {
+			s64 min_period = min_timer_period_us * 1000LL;
 
-	apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
+			if (apic->lapic_timer.period < min_period) {
+				pr_info_ratelimited(
+				    "kvm: vcpu %i: requested %lld ns "
+				    "lapic timer period limited to %lld ns\n",
+				    apic->vcpu->vcpu_id,
+				    apic->lapic_timer.period, min_period);
+				apic->lapic_timer.period = min_period;
+			}
+		}
+
+		hrtimer_start(&apic->lapic_timer.timer,
+			      ktime_add_ns(now, apic->lapic_timer.period),
+			      HRTIMER_MODE_ABS);
+
+		apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
 			   PRIx64 ", "
 			   "timer initial count 0x%x, period %lldns, "
 			   "expire @ 0x%016" PRIx64 ".\n", __func__,
@@ -695,6 +725,30 @@
 			   apic->lapic_timer.period,
 			   ktime_to_ns(ktime_add_ns(now,
 					apic->lapic_timer.period)));
+	} else if (apic_lvtt_tscdeadline(apic)) {
+		/* lapic timer in tsc deadline mode */
+		u64 guest_tsc, tscdeadline = apic->lapic_timer.tscdeadline;
+		u64 ns = 0;
+		struct kvm_vcpu *vcpu = apic->vcpu;
+		unsigned long this_tsc_khz = vcpu_tsc_khz(vcpu);
+		unsigned long flags;
+
+		if (unlikely(!tscdeadline || !this_tsc_khz))
+			return;
+
+		local_irq_save(flags);
+
+		now = apic->lapic_timer.timer.base->get_time();
+		guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
+		if (likely(tscdeadline > guest_tsc)) {
+			ns = (tscdeadline - guest_tsc) * 1000000ULL;
+			do_div(ns, this_tsc_khz);
+		}
+		hrtimer_start(&apic->lapic_timer.timer,
+			ktime_add_ns(now, ns), HRTIMER_MODE_ABS);
+
+		local_irq_restore(flags);
+	}
 }
 
 static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
@@ -782,7 +836,6 @@
 
 	case APIC_LVT0:
 		apic_manage_nmi_watchdog(apic, val);
-	case APIC_LVTT:
 	case APIC_LVTTHMR:
 	case APIC_LVTPC:
 	case APIC_LVT1:
@@ -796,7 +849,22 @@
 
 		break;
 
+	case APIC_LVTT:
+		if ((apic_get_reg(apic, APIC_LVTT) &
+		    apic->lapic_timer.timer_mode_mask) !=
+		   (val & apic->lapic_timer.timer_mode_mask))
+			hrtimer_cancel(&apic->lapic_timer.timer);
+
+		if (!apic_sw_enabled(apic))
+			val |= APIC_LVT_MASKED;
+		val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask);
+		apic_set_reg(apic, APIC_LVTT, val);
+		break;
+
 	case APIC_TMICT:
+		if (apic_lvtt_tscdeadline(apic))
+			break;
+
 		hrtimer_cancel(&apic->lapic_timer.timer);
 		apic_set_reg(apic, APIC_TMICT, val);
 		start_apic_timer(apic);
@@ -804,14 +872,14 @@
 
 	case APIC_TDCR:
 		if (val & 4)
-			printk(KERN_ERR "KVM_WRITE:TDCR %x\n", val);
+			apic_debug("KVM_WRITE:TDCR %x\n", val);
 		apic_set_reg(apic, APIC_TDCR, val);
 		update_divide_count(apic);
 		break;
 
 	case APIC_ESR:
 		if (apic_x2apic_mode(apic) && val != 0) {
-			printk(KERN_ERR "KVM_WRITE:ESR not zero %x\n", val);
+			apic_debug("KVM_WRITE:ESR not zero %x\n", val);
 			ret = 1;
 		}
 		break;
@@ -864,6 +932,15 @@
 	return 0;
 }
 
+void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (apic)
+		apic_reg_write(vcpu->arch.apic, APIC_EOI, 0);
+}
+EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi);
+
 void kvm_free_lapic(struct kvm_vcpu *vcpu)
 {
 	if (!vcpu->arch.apic)
@@ -883,6 +960,32 @@
  *----------------------------------------------------------------------
  */
 
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+	if (!apic)
+		return 0;
+
+	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+		return 0;
+
+	return apic->lapic_timer.tscdeadline;
+}
+
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+	if (!apic)
+		return;
+
+	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+		return;
+
+	hrtimer_cancel(&apic->lapic_timer.timer);
+	apic->lapic_timer.tscdeadline = data;
+	start_apic_timer(apic);
+}
+
 void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
diff -druN linux-libre-3.1-gnu/arch/x86/kvm/lapic.h linux-libre-3.2-gnu/arch/x86/kvm/lapic.h
--- linux-libre-3.1-gnu/arch/x86/kvm/lapic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kvm/lapic.h	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 void kvm_lapic_reset(struct kvm_vcpu *vcpu);
 u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu);
 void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8);
+void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu);
 void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value);
 u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);
 void kvm_apic_set_version(struct kvm_vcpu *vcpu);
@@ -41,6 +42,9 @@
 bool kvm_apic_present(struct kvm_vcpu *vcpu);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
 
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data);
+
 void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
 void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
 void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);
diff -druN linux-libre-3.1-gnu/arch/x86/kvm/mmu_audit.c linux-libre-3.2-gnu/arch/x86/kvm/mmu_audit.c
--- linux-libre-3.1-gnu/arch/x86/kvm/mmu_audit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kvm/mmu_audit.c	2012-01-04 18:55:44.000000000 -0500
@@ -121,16 +121,16 @@
 
 static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep)
 {
+	static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 10);
 	unsigned long *rmapp;
 	struct kvm_mmu_page *rev_sp;
 	gfn_t gfn;
 
-
 	rev_sp = page_header(__pa(sptep));
 	gfn = kvm_mmu_page_get_gfn(rev_sp, sptep - rev_sp->spt);
 
 	if (!gfn_to_memslot(kvm, gfn)) {
-		if (!printk_ratelimit())
+		if (!__ratelimit(&ratelimit_state))
 			return;
 		audit_printk(kvm, "no memslot for gfn %llx\n", gfn);
 		audit_printk(kvm, "index %ld of sp (gfn=%llx)\n",
@@ -141,7 +141,7 @@
 
 	rmapp = gfn_to_rmap(kvm, gfn, rev_sp->role.level);
 	if (!*rmapp) {
-		if (!printk_ratelimit())
+		if (!__ratelimit(&ratelimit_state))
 			return;
 		audit_printk(kvm, "no rmap for writable spte %llx\n",
 			     *sptep);
diff -druN linux-libre-3.1-gnu/arch/x86/kvm/mmu.c linux-libre-3.2-gnu/arch/x86/kvm/mmu.c
--- linux-libre-3.1-gnu/arch/x86/kvm/mmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kvm/mmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -2770,7 +2770,7 @@
 
 		ASSERT(!VALID_PAGE(root));
 		if (vcpu->arch.mmu.root_level == PT32E_ROOT_LEVEL) {
-			pdptr = kvm_pdptr_read_mmu(vcpu, &vcpu->arch.mmu, i);
+			pdptr = vcpu->arch.mmu.get_pdptr(vcpu, i);
 			if (!is_present_gpte(pdptr)) {
 				vcpu->arch.mmu.pae_root[i] = 0;
 				continue;
@@ -3318,6 +3318,7 @@
 	context->direct_map = true;
 	context->set_cr3 = kvm_x86_ops->set_tdp_cr3;
 	context->get_cr3 = get_cr3;
+	context->get_pdptr = kvm_pdptr_read;
 	context->inject_page_fault = kvm_inject_page_fault;
 	context->nx = is_nx(vcpu);
 
@@ -3376,6 +3377,7 @@
 
 	vcpu->arch.walk_mmu->set_cr3           = kvm_x86_ops->set_cr3;
 	vcpu->arch.walk_mmu->get_cr3           = get_cr3;
+	vcpu->arch.walk_mmu->get_pdptr         = kvm_pdptr_read;
 	vcpu->arch.walk_mmu->inject_page_fault = kvm_inject_page_fault;
 
 	return r;
@@ -3386,6 +3388,7 @@
 	struct kvm_mmu *g_context = &vcpu->arch.nested_mmu;
 
 	g_context->get_cr3           = get_cr3;
+	g_context->get_pdptr         = kvm_pdptr_read;
 	g_context->inject_page_fault = kvm_inject_page_fault;
 
 	/*
diff -druN linux-libre-3.1-gnu/arch/x86/kvm/paging_tmpl.h linux-libre-3.2-gnu/arch/x86/kvm/paging_tmpl.h
--- linux-libre-3.1-gnu/arch/x86/kvm/paging_tmpl.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kvm/paging_tmpl.h	2012-01-04 18:55:44.000000000 -0500
@@ -147,7 +147,7 @@
 	gfn_t table_gfn;
 	unsigned index, pt_access, uninitialized_var(pte_access);
 	gpa_t pte_gpa;
-	bool eperm;
+	bool eperm, last_gpte;
 	int offset;
 	const int write_fault = access & PFERR_WRITE_MASK;
 	const int user_fault  = access & PFERR_USER_MASK;
@@ -163,7 +163,7 @@
 
 #if PTTYPE == 64
 	if (walker->level == PT32E_ROOT_LEVEL) {
-		pte = kvm_pdptr_read_mmu(vcpu, mmu, (addr >> 30) & 3);
+		pte = mmu->get_pdptr(vcpu, (addr >> 30) & 3);
 		trace_kvm_mmu_paging_element(pte, walker->level);
 		if (!is_present_gpte(pte))
 			goto error;
@@ -221,6 +221,17 @@
 			eperm = true;
 #endif
 
+		last_gpte = FNAME(is_last_gpte)(walker, vcpu, mmu, pte);
+		if (last_gpte) {
+			pte_access = pt_access &
+				     FNAME(gpte_access)(vcpu, pte, true);
+			/* check if the kernel is fetching from user page */
+			if (unlikely(pte_access & PT_USER_MASK) &&
+			    kvm_read_cr4_bits(vcpu, X86_CR4_SMEP))
+				if (fetch_fault && !user_fault)
+					eperm = true;
+		}
+
 		if (!eperm && unlikely(!(pte & PT_ACCESSED_MASK))) {
 			int ret;
 			trace_kvm_mmu_set_accessed_bit(table_gfn, index,
@@ -238,18 +249,12 @@
 
 		walker->ptes[walker->level - 1] = pte;
 
-		if (FNAME(is_last_gpte)(walker, vcpu, mmu, pte)) {
+		if (last_gpte) {
 			int lvl = walker->level;
 			gpa_t real_gpa;
 			gfn_t gfn;
 			u32 ac;
 
-			/* check if the kernel is fetching from user page */
-			if (unlikely(pte_access & PT_USER_MASK) &&
-			    kvm_read_cr4_bits(vcpu, X86_CR4_SMEP))
-				if (fetch_fault && !user_fault)
-					eperm = true;
-
 			gfn = gpte_to_gfn_lvl(pte, lvl);
 			gfn += (addr & PT_LVL_OFFSET_MASK(lvl)) >> PAGE_SHIFT;
 
@@ -295,7 +300,6 @@
 		walker->ptes[walker->level - 1] = pte;
 	}
 
-	pte_access = pt_access & FNAME(gpte_access)(vcpu, pte, true);
 	walker->pt_access = pt_access;
 	walker->pte_access = pte_access;
 	pgprintk("%s: pte %llx pte_access %x pt_access %x\n",
diff -druN linux-libre-3.1-gnu/arch/x86/kvm/svm.c linux-libre-3.2-gnu/arch/x86/kvm/svm.c
--- linux-libre-3.1-gnu/arch/x86/kvm/svm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kvm/svm.c	2012-01-04 18:55:44.000000000 -0500
@@ -1084,7 +1084,6 @@
 	if (npt_enabled) {
 		/* Setup VMCB for Nested Paging */
 		control->nested_ctl = 1;
-		clr_intercept(svm, INTERCEPT_TASK_SWITCH);
 		clr_intercept(svm, INTERCEPT_INVLPG);
 		clr_exception_intercept(svm, PF_VECTOR);
 		clr_cr_intercept(svm, INTERCEPT_CR3_READ);
@@ -1844,6 +1843,20 @@
 	return svm->nested.nested_cr3;
 }
 
+static u64 nested_svm_get_tdp_pdptr(struct kvm_vcpu *vcpu, int index)
+{
+	struct vcpu_svm *svm = to_svm(vcpu);
+	u64 cr3 = svm->nested.nested_cr3;
+	u64 pdpte;
+	int ret;
+
+	ret = kvm_read_guest_page(vcpu->kvm, gpa_to_gfn(cr3), &pdpte,
+				  offset_in_page(cr3) + index * 8, 8);
+	if (ret)
+		return 0;
+	return pdpte;
+}
+
 static void nested_svm_set_tdp_cr3(struct kvm_vcpu *vcpu,
 				   unsigned long root)
 {
@@ -1875,6 +1888,7 @@
 
 	vcpu->arch.mmu.set_cr3           = nested_svm_set_tdp_cr3;
 	vcpu->arch.mmu.get_cr3           = nested_svm_get_tdp_cr3;
+	vcpu->arch.mmu.get_pdptr         = nested_svm_get_tdp_pdptr;
 	vcpu->arch.mmu.inject_page_fault = nested_svm_inject_npf_exit;
 	vcpu->arch.mmu.shadow_root_level = get_npt_level();
 	vcpu->arch.walk_mmu              = &vcpu->arch.nested_mmu;
@@ -2182,7 +2196,8 @@
 				       vmcb->control.exit_info_1,
 				       vmcb->control.exit_info_2,
 				       vmcb->control.exit_int_info,
-				       vmcb->control.exit_int_info_err);
+				       vmcb->control.exit_int_info_err,
+				       KVM_ISA_SVM);
 
 	nested_vmcb = nested_svm_map(svm, svm->nested.vmcb, &page);
 	if (!nested_vmcb)
@@ -2894,15 +2909,20 @@
 	return 0;
 }
 
+u64 svm_read_l1_tsc(struct kvm_vcpu *vcpu)
+{
+	struct vmcb *vmcb = get_host_vmcb(to_svm(vcpu));
+	return vmcb->control.tsc_offset +
+		svm_scale_tsc(vcpu, native_read_tsc());
+}
+
 static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
 	switch (ecx) {
 	case MSR_IA32_TSC: {
-		struct vmcb *vmcb = get_host_vmcb(svm);
-
-		*data = vmcb->control.tsc_offset +
+		*data = svm->vmcb->control.tsc_offset +
 			svm_scale_tsc(vcpu, native_read_tsc());
 
 		break;
@@ -3314,8 +3334,6 @@
 	struct kvm_run *kvm_run = vcpu->run;
 	u32 exit_code = svm->vmcb->control.exit_code;
 
-	trace_kvm_exit(exit_code, vcpu, KVM_ISA_SVM);
-
 	if (!is_cr_intercept(svm, INTERCEPT_CR0_WRITE))
 		vcpu->arch.cr0 = svm->vmcb->save.cr0;
 	if (npt_enabled)
@@ -3335,7 +3353,8 @@
 					svm->vmcb->control.exit_info_1,
 					svm->vmcb->control.exit_info_2,
 					svm->vmcb->control.exit_int_info,
-					svm->vmcb->control.exit_int_info_err);
+					svm->vmcb->control.exit_int_info_err,
+					KVM_ISA_SVM);
 
 		vmexit = nested_svm_exit_special(svm);
 
@@ -3768,6 +3787,8 @@
 	vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
 	vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
 
+	trace_kvm_exit(svm->vmcb->control.exit_code, vcpu, KVM_ISA_SVM);
+
 	if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
 		kvm_before_handle_nmi(&svm->vcpu);
 
@@ -3897,60 +3918,6 @@
 	}
 }
 
-static const struct trace_print_flags svm_exit_reasons_str[] = {
-	{ SVM_EXIT_READ_CR0,			"read_cr0" },
-	{ SVM_EXIT_READ_CR3,			"read_cr3" },
-	{ SVM_EXIT_READ_CR4,			"read_cr4" },
-	{ SVM_EXIT_READ_CR8,			"read_cr8" },
-	{ SVM_EXIT_WRITE_CR0,			"write_cr0" },
-	{ SVM_EXIT_WRITE_CR3,			"write_cr3" },
-	{ SVM_EXIT_WRITE_CR4,			"write_cr4" },
-	{ SVM_EXIT_WRITE_CR8,			"write_cr8" },
-	{ SVM_EXIT_READ_DR0,			"read_dr0" },
-	{ SVM_EXIT_READ_DR1,			"read_dr1" },
-	{ SVM_EXIT_READ_DR2,			"read_dr2" },
-	{ SVM_EXIT_READ_DR3,			"read_dr3" },
-	{ SVM_EXIT_WRITE_DR0,			"write_dr0" },
-	{ SVM_EXIT_WRITE_DR1,			"write_dr1" },
-	{ SVM_EXIT_WRITE_DR2,			"write_dr2" },
-	{ SVM_EXIT_WRITE_DR3,			"write_dr3" },
-	{ SVM_EXIT_WRITE_DR5,			"write_dr5" },
-	{ SVM_EXIT_WRITE_DR7,			"write_dr7" },
-	{ SVM_EXIT_EXCP_BASE + DB_VECTOR,	"DB excp" },
-	{ SVM_EXIT_EXCP_BASE + BP_VECTOR,	"BP excp" },
-	{ SVM_EXIT_EXCP_BASE + UD_VECTOR,	"UD excp" },
-	{ SVM_EXIT_EXCP_BASE + PF_VECTOR,	"PF excp" },
-	{ SVM_EXIT_EXCP_BASE + NM_VECTOR,	"NM excp" },
-	{ SVM_EXIT_EXCP_BASE + MC_VECTOR,	"MC excp" },
-	{ SVM_EXIT_INTR,			"interrupt" },
-	{ SVM_EXIT_NMI,				"nmi" },
-	{ SVM_EXIT_SMI,				"smi" },
-	{ SVM_EXIT_INIT,			"init" },
-	{ SVM_EXIT_VINTR,			"vintr" },
-	{ SVM_EXIT_CPUID,			"cpuid" },
-	{ SVM_EXIT_INVD,			"invd" },
-	{ SVM_EXIT_HLT,				"hlt" },
-	{ SVM_EXIT_INVLPG,			"invlpg" },
-	{ SVM_EXIT_INVLPGA,			"invlpga" },
-	{ SVM_EXIT_IOIO,			"io" },
-	{ SVM_EXIT_MSR,				"msr" },
-	{ SVM_EXIT_TASK_SWITCH,			"task_switch" },
-	{ SVM_EXIT_SHUTDOWN,			"shutdown" },
-	{ SVM_EXIT_VMRUN,			"vmrun" },
-	{ SVM_EXIT_VMMCALL,			"hypercall" },
-	{ SVM_EXIT_VMLOAD,			"vmload" },
-	{ SVM_EXIT_VMSAVE,			"vmsave" },
-	{ SVM_EXIT_STGI,			"stgi" },
-	{ SVM_EXIT_CLGI,			"clgi" },
-	{ SVM_EXIT_SKINIT,			"skinit" },
-	{ SVM_EXIT_WBINVD,			"wbinvd" },
-	{ SVM_EXIT_MONITOR,			"monitor" },
-	{ SVM_EXIT_MWAIT,			"mwait" },
-	{ SVM_EXIT_XSETBV,			"xsetbv" },
-	{ SVM_EXIT_NPF,				"npf" },
-	{ -1, NULL }
-};
-
 static int svm_get_lpage_level(void)
 {
 	return PT_PDPE_LEVEL;
@@ -4223,7 +4190,6 @@
 	.get_mt_mask = svm_get_mt_mask,
 
 	.get_exit_info = svm_get_exit_info,
-	.exit_reasons_str = svm_exit_reasons_str,
 
 	.get_lpage_level = svm_get_lpage_level,
 
@@ -4239,6 +4205,7 @@
 	.write_tsc_offset = svm_write_tsc_offset,
 	.adjust_tsc_offset = svm_adjust_tsc_offset,
 	.compute_tsc_offset = svm_compute_tsc_offset,
+	.read_l1_tsc = svm_read_l1_tsc,
 
 	.set_tdp_cr3 = set_tdp_cr3,
 
diff -druN linux-libre-3.1-gnu/arch/x86/kvm/trace.h linux-libre-3.2-gnu/arch/x86/kvm/trace.h
--- linux-libre-3.1-gnu/arch/x86/kvm/trace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kvm/trace.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,8 @@
 #define _TRACE_KVM_H
 
 #include <linux/tracepoint.h>
+#include <asm/vmx.h>
+#include <asm/svm.h>
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM kvm
@@ -181,6 +183,95 @@
 #define KVM_ISA_VMX   1
 #define KVM_ISA_SVM   2
 
+#define VMX_EXIT_REASONS \
+	{ EXIT_REASON_EXCEPTION_NMI,		"EXCEPTION_NMI" }, \
+	{ EXIT_REASON_EXTERNAL_INTERRUPT,	"EXTERNAL_INTERRUPT" }, \
+	{ EXIT_REASON_TRIPLE_FAULT,		"TRIPLE_FAULT" }, \
+	{ EXIT_REASON_PENDING_INTERRUPT,	"PENDING_INTERRUPT" }, \
+	{ EXIT_REASON_NMI_WINDOW,		"NMI_WINDOW" }, \
+	{ EXIT_REASON_TASK_SWITCH,		"TASK_SWITCH" }, \
+	{ EXIT_REASON_CPUID,			"CPUID" }, \
+	{ EXIT_REASON_HLT,			"HLT" }, \
+	{ EXIT_REASON_INVLPG,			"INVLPG" }, \
+	{ EXIT_REASON_RDPMC,			"RDPMC" }, \
+	{ EXIT_REASON_RDTSC,			"RDTSC" }, \
+	{ EXIT_REASON_VMCALL,			"VMCALL" }, \
+	{ EXIT_REASON_VMCLEAR,			"VMCLEAR" }, \
+	{ EXIT_REASON_VMLAUNCH,			"VMLAUNCH" }, \
+	{ EXIT_REASON_VMPTRLD,			"VMPTRLD" }, \
+	{ EXIT_REASON_VMPTRST,			"VMPTRST" }, \
+	{ EXIT_REASON_VMREAD,			"VMREAD" }, \
+	{ EXIT_REASON_VMRESUME,			"VMRESUME" }, \
+	{ EXIT_REASON_VMWRITE,			"VMWRITE" }, \
+	{ EXIT_REASON_VMOFF,			"VMOFF" }, \
+	{ EXIT_REASON_VMON,			"VMON" }, \
+	{ EXIT_REASON_CR_ACCESS,		"CR_ACCESS" }, \
+	{ EXIT_REASON_DR_ACCESS,		"DR_ACCESS" }, \
+	{ EXIT_REASON_IO_INSTRUCTION,		"IO_INSTRUCTION" }, \
+	{ EXIT_REASON_MSR_READ,			"MSR_READ" }, \
+	{ EXIT_REASON_MSR_WRITE,		"MSR_WRITE" }, \
+	{ EXIT_REASON_MWAIT_INSTRUCTION,	"MWAIT_INSTRUCTION" }, \
+	{ EXIT_REASON_MONITOR_INSTRUCTION,	"MONITOR_INSTRUCTION" }, \
+	{ EXIT_REASON_PAUSE_INSTRUCTION,	"PAUSE_INSTRUCTION" }, \
+	{ EXIT_REASON_MCE_DURING_VMENTRY,	"MCE_DURING_VMENTRY" }, \
+	{ EXIT_REASON_TPR_BELOW_THRESHOLD,	"TPR_BELOW_THRESHOLD" },	\
+	{ EXIT_REASON_APIC_ACCESS,		"APIC_ACCESS" }, \
+	{ EXIT_REASON_EPT_VIOLATION,		"EPT_VIOLATION" }, \
+	{ EXIT_REASON_EPT_MISCONFIG,		"EPT_MISCONFIG" }, \
+	{ EXIT_REASON_WBINVD,			"WBINVD" }
+
+#define SVM_EXIT_REASONS \
+	{ SVM_EXIT_READ_CR0,			"read_cr0" }, \
+	{ SVM_EXIT_READ_CR3,			"read_cr3" }, \
+	{ SVM_EXIT_READ_CR4,			"read_cr4" }, \
+	{ SVM_EXIT_READ_CR8,			"read_cr8" }, \
+	{ SVM_EXIT_WRITE_CR0,			"write_cr0" }, \
+	{ SVM_EXIT_WRITE_CR3,			"write_cr3" }, \
+	{ SVM_EXIT_WRITE_CR4,			"write_cr4" }, \
+	{ SVM_EXIT_WRITE_CR8,			"write_cr8" }, \
+	{ SVM_EXIT_READ_DR0,			"read_dr0" }, \
+	{ SVM_EXIT_READ_DR1,			"read_dr1" }, \
+	{ SVM_EXIT_READ_DR2,			"read_dr2" }, \
+	{ SVM_EXIT_READ_DR3,			"read_dr3" }, \
+	{ SVM_EXIT_WRITE_DR0,			"write_dr0" }, \
+	{ SVM_EXIT_WRITE_DR1,			"write_dr1" }, \
+	{ SVM_EXIT_WRITE_DR2,			"write_dr2" }, \
+	{ SVM_EXIT_WRITE_DR3,			"write_dr3" }, \
+	{ SVM_EXIT_WRITE_DR5,			"write_dr5" }, \
+	{ SVM_EXIT_WRITE_DR7,			"write_dr7" }, \
+	{ SVM_EXIT_EXCP_BASE + DB_VECTOR,	"DB excp" }, \
+	{ SVM_EXIT_EXCP_BASE + BP_VECTOR,	"BP excp" }, \
+	{ SVM_EXIT_EXCP_BASE + UD_VECTOR,	"UD excp" }, \
+	{ SVM_EXIT_EXCP_BASE + PF_VECTOR,	"PF excp" }, \
+	{ SVM_EXIT_EXCP_BASE + NM_VECTOR,	"NM excp" }, \
+	{ SVM_EXIT_EXCP_BASE + MC_VECTOR,	"MC excp" }, \
+	{ SVM_EXIT_INTR,			"interrupt" }, \
+	{ SVM_EXIT_NMI,				"nmi" }, \
+	{ SVM_EXIT_SMI,				"smi" }, \
+	{ SVM_EXIT_INIT,			"init" }, \
+	{ SVM_EXIT_VINTR,			"vintr" }, \
+	{ SVM_EXIT_CPUID,			"cpuid" }, \
+	{ SVM_EXIT_INVD,			"invd" }, \
+	{ SVM_EXIT_HLT,				"hlt" }, \
+	{ SVM_EXIT_INVLPG,			"invlpg" }, \
+	{ SVM_EXIT_INVLPGA,			"invlpga" }, \
+	{ SVM_EXIT_IOIO,			"io" }, \
+	{ SVM_EXIT_MSR,				"msr" }, \
+	{ SVM_EXIT_TASK_SWITCH,			"task_switch" }, \
+	{ SVM_EXIT_SHUTDOWN,			"shutdown" }, \
+	{ SVM_EXIT_VMRUN,			"vmrun" }, \
+	{ SVM_EXIT_VMMCALL,			"hypercall" }, \
+	{ SVM_EXIT_VMLOAD,			"vmload" }, \
+	{ SVM_EXIT_VMSAVE,			"vmsave" }, \
+	{ SVM_EXIT_STGI,			"stgi" }, \
+	{ SVM_EXIT_CLGI,			"clgi" }, \
+	{ SVM_EXIT_SKINIT,			"skinit" }, \
+	{ SVM_EXIT_WBINVD,			"wbinvd" }, \
+	{ SVM_EXIT_MONITOR,			"monitor" }, \
+	{ SVM_EXIT_MWAIT,			"mwait" }, \
+	{ SVM_EXIT_XSETBV,			"xsetbv" }, \
+	{ SVM_EXIT_NPF,				"npf" }
+
 /*
  * Tracepoint for kvm guest exit:
  */
@@ -205,8 +296,9 @@
 	),
 
 	TP_printk("reason %s rip 0x%lx info %llx %llx",
-		 ftrace_print_symbols_seq(p, __entry->exit_reason,
-					  kvm_x86_ops->exit_reasons_str),
+		 (__entry->isa == KVM_ISA_VMX) ?
+		 __print_symbolic(__entry->exit_reason, VMX_EXIT_REASONS) :
+		 __print_symbolic(__entry->exit_reason, SVM_EXIT_REASONS),
 		 __entry->guest_rip, __entry->info1, __entry->info2)
 );
 
@@ -486,9 +578,9 @@
 TRACE_EVENT(kvm_nested_vmexit,
 	    TP_PROTO(__u64 rip, __u32 exit_code,
 		     __u64 exit_info1, __u64 exit_info2,
-		     __u32 exit_int_info, __u32 exit_int_info_err),
+		     __u32 exit_int_info, __u32 exit_int_info_err, __u32 isa),
 	    TP_ARGS(rip, exit_code, exit_info1, exit_info2,
-		    exit_int_info, exit_int_info_err),
+		    exit_int_info, exit_int_info_err, isa),
 
 	TP_STRUCT__entry(
 		__field(	__u64,		rip			)
@@ -497,6 +589,7 @@
 		__field(	__u64,		exit_info2		)
 		__field(	__u32,		exit_int_info		)
 		__field(	__u32,		exit_int_info_err	)
+		__field(	__u32,		isa			)
 	),
 
 	TP_fast_assign(
@@ -506,12 +599,14 @@
 		__entry->exit_info2		= exit_info2;
 		__entry->exit_int_info		= exit_int_info;
 		__entry->exit_int_info_err	= exit_int_info_err;
+		__entry->isa			= isa;
 	),
 	TP_printk("rip: 0x%016llx reason: %s ext_inf1: 0x%016llx "
 		  "ext_inf2: 0x%016llx ext_int: 0x%08x ext_int_err: 0x%08x",
 		  __entry->rip,
-		  ftrace_print_symbols_seq(p, __entry->exit_code,
-					   kvm_x86_ops->exit_reasons_str),
+		 (__entry->isa == KVM_ISA_VMX) ?
+		 __print_symbolic(__entry->exit_code, VMX_EXIT_REASONS) :
+		 __print_symbolic(__entry->exit_code, SVM_EXIT_REASONS),
 		  __entry->exit_info1, __entry->exit_info2,
 		  __entry->exit_int_info, __entry->exit_int_info_err)
 );
@@ -522,9 +617,9 @@
 TRACE_EVENT(kvm_nested_vmexit_inject,
 	    TP_PROTO(__u32 exit_code,
 		     __u64 exit_info1, __u64 exit_info2,
-		     __u32 exit_int_info, __u32 exit_int_info_err),
+		     __u32 exit_int_info, __u32 exit_int_info_err, __u32 isa),
 	    TP_ARGS(exit_code, exit_info1, exit_info2,
-		    exit_int_info, exit_int_info_err),
+		    exit_int_info, exit_int_info_err, isa),
 
 	TP_STRUCT__entry(
 		__field(	__u32,		exit_code		)
@@ -532,6 +627,7 @@
 		__field(	__u64,		exit_info2		)
 		__field(	__u32,		exit_int_info		)
 		__field(	__u32,		exit_int_info_err	)
+		__field(	__u32,		isa			)
 	),
 
 	TP_fast_assign(
@@ -540,12 +636,14 @@
 		__entry->exit_info2		= exit_info2;
 		__entry->exit_int_info		= exit_int_info;
 		__entry->exit_int_info_err	= exit_int_info_err;
+		__entry->isa			= isa;
 	),
 
 	TP_printk("reason: %s ext_inf1: 0x%016llx "
 		  "ext_inf2: 0x%016llx ext_int: 0x%08x ext_int_err: 0x%08x",
-		  ftrace_print_symbols_seq(p, __entry->exit_code,
-					   kvm_x86_ops->exit_reasons_str),
+		 (__entry->isa == KVM_ISA_VMX) ?
+		 __print_symbolic(__entry->exit_code, VMX_EXIT_REASONS) :
+		 __print_symbolic(__entry->exit_code, SVM_EXIT_REASONS),
 		__entry->exit_info1, __entry->exit_info2,
 		__entry->exit_int_info, __entry->exit_int_info_err)
 );
diff -druN linux-libre-3.1-gnu/arch/x86/kvm/vmx.c linux-libre-3.2-gnu/arch/x86/kvm/vmx.c
--- linux-libre-3.1-gnu/arch/x86/kvm/vmx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kvm/vmx.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,7 @@
 #include <asm/mce.h>
 #include <asm/i387.h>
 #include <asm/xcr.h>
+#include <asm/perf_event.h>
 
 #include "trace.h"
 
@@ -71,6 +72,9 @@
 static int __read_mostly yield_on_hlt = 1;
 module_param(yield_on_hlt, bool, S_IRUGO);
 
+static int __read_mostly fasteoi = 1;
+module_param(fasteoi, bool, S_IRUGO);
+
 /*
  * If nested=1, nested virtualization is supported, i.e., guests may use
  * VMX and be a hypervisor for its own guests. If nested=0, guests may not
@@ -115,7 +119,7 @@
 static int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW;
 module_param(ple_window, int, S_IRUGO);
 
-#define NR_AUTOLOAD_MSRS 1
+#define NR_AUTOLOAD_MSRS 8
 #define VMCS02_POOL_SIZE 1
 
 struct vmcs {
@@ -619,6 +623,7 @@
 static unsigned long *vmx_msr_bitmap_longmode;
 
 static bool cpu_has_load_ia32_efer;
+static bool cpu_has_load_perf_global_ctrl;
 
 static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
 static DEFINE_SPINLOCK(vmx_vpid_lock);
@@ -1188,15 +1193,34 @@
 	vmcs_write32(EXCEPTION_BITMAP, eb);
 }
 
+static void clear_atomic_switch_msr_special(unsigned long entry,
+		unsigned long exit)
+{
+	vmcs_clear_bits(VM_ENTRY_CONTROLS, entry);
+	vmcs_clear_bits(VM_EXIT_CONTROLS, exit);
+}
+
 static void clear_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr)
 {
 	unsigned i;
 	struct msr_autoload *m = &vmx->msr_autoload;
 
-	if (msr == MSR_EFER && cpu_has_load_ia32_efer) {
-		vmcs_clear_bits(VM_ENTRY_CONTROLS, VM_ENTRY_LOAD_IA32_EFER);
-		vmcs_clear_bits(VM_EXIT_CONTROLS, VM_EXIT_LOAD_IA32_EFER);
-		return;
+	switch (msr) {
+	case MSR_EFER:
+		if (cpu_has_load_ia32_efer) {
+			clear_atomic_switch_msr_special(VM_ENTRY_LOAD_IA32_EFER,
+					VM_EXIT_LOAD_IA32_EFER);
+			return;
+		}
+		break;
+	case MSR_CORE_PERF_GLOBAL_CTRL:
+		if (cpu_has_load_perf_global_ctrl) {
+			clear_atomic_switch_msr_special(
+					VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL,
+					VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL);
+			return;
+		}
+		break;
 	}
 
 	for (i = 0; i < m->nr; ++i)
@@ -1212,25 +1236,55 @@
 	vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->nr);
 }
 
+static void add_atomic_switch_msr_special(unsigned long entry,
+		unsigned long exit, unsigned long guest_val_vmcs,
+		unsigned long host_val_vmcs, u64 guest_val, u64 host_val)
+{
+	vmcs_write64(guest_val_vmcs, guest_val);
+	vmcs_write64(host_val_vmcs, host_val);
+	vmcs_set_bits(VM_ENTRY_CONTROLS, entry);
+	vmcs_set_bits(VM_EXIT_CONTROLS, exit);
+}
+
 static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr,
 				  u64 guest_val, u64 host_val)
 {
 	unsigned i;
 	struct msr_autoload *m = &vmx->msr_autoload;
 
-	if (msr == MSR_EFER && cpu_has_load_ia32_efer) {
-		vmcs_write64(GUEST_IA32_EFER, guest_val);
-		vmcs_write64(HOST_IA32_EFER, host_val);
-		vmcs_set_bits(VM_ENTRY_CONTROLS, VM_ENTRY_LOAD_IA32_EFER);
-		vmcs_set_bits(VM_EXIT_CONTROLS, VM_EXIT_LOAD_IA32_EFER);
-		return;
+	switch (msr) {
+	case MSR_EFER:
+		if (cpu_has_load_ia32_efer) {
+			add_atomic_switch_msr_special(VM_ENTRY_LOAD_IA32_EFER,
+					VM_EXIT_LOAD_IA32_EFER,
+					GUEST_IA32_EFER,
+					HOST_IA32_EFER,
+					guest_val, host_val);
+			return;
+		}
+		break;
+	case MSR_CORE_PERF_GLOBAL_CTRL:
+		if (cpu_has_load_perf_global_ctrl) {
+			add_atomic_switch_msr_special(
+					VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL,
+					VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL,
+					GUEST_IA32_PERF_GLOBAL_CTRL,
+					HOST_IA32_PERF_GLOBAL_CTRL,
+					guest_val, host_val);
+			return;
+		}
+		break;
 	}
 
 	for (i = 0; i < m->nr; ++i)
 		if (m->guest[i].index == msr)
 			break;
 
-	if (i == m->nr) {
+	if (i == NR_AUTOLOAD_MSRS) {
+		printk_once(KERN_WARNING"Not enough mst switch entries. "
+				"Can't add msr %x\n", msr);
+		return;
+	} else if (i == m->nr) {
 		++m->nr;
 		vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->nr);
 		vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->nr);
@@ -1748,6 +1802,21 @@
 }
 
 /*
+ * Like guest_read_tsc, but always returns L1's notion of the timestamp
+ * counter, even if a nested guest (L2) is currently running.
+ */
+u64 vmx_read_l1_tsc(struct kvm_vcpu *vcpu)
+{
+	u64 host_tsc, tsc_offset;
+
+	rdtscll(host_tsc);
+	tsc_offset = is_guest_mode(vcpu) ?
+		to_vmx(vcpu)->nested.vmcs01_tsc_offset :
+		vmcs_read64(TSC_OFFSET);
+	return host_tsc + tsc_offset;
+}
+
+/*
  * Empty call-back. Needs to be implemented when VMX enables the SET_TSC_KHZ
  * ioctl. In this case the call-back should update internal vmx state to make
  * the changes effective.
@@ -1762,15 +1831,23 @@
  */
 static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
 {
-	vmcs_write64(TSC_OFFSET, offset);
-	if (is_guest_mode(vcpu))
+	if (is_guest_mode(vcpu)) {
 		/*
-		 * We're here if L1 chose not to trap the TSC MSR. Since
-		 * prepare_vmcs12() does not copy tsc_offset, we need to also
-		 * set the vmcs12 field here.
+		 * We're here if L1 chose not to trap WRMSR to TSC. According
+		 * to the spec, this should set L1's TSC; The offset that L1
+		 * set for L2 remains unchanged, and still needs to be added
+		 * to the newly set TSC to get L2's TSC.
 		 */
-		get_vmcs12(vcpu)->tsc_offset = offset -
-			to_vmx(vcpu)->nested.vmcs01_tsc_offset;
+		struct vmcs12 *vmcs12;
+		to_vmx(vcpu)->nested.vmcs01_tsc_offset = offset;
+		/* recalculate vmcs02.TSC_OFFSET: */
+		vmcs12 = get_vmcs12(vcpu);
+		vmcs_write64(TSC_OFFSET, offset +
+			(nested_cpu_has(vmcs12, CPU_BASED_USE_TSC_OFFSETING) ?
+			 vmcs12->tsc_offset : 0));
+	} else {
+		vmcs_write64(TSC_OFFSET, offset);
+	}
 }
 
 static void vmx_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment)
@@ -2429,6 +2506,42 @@
 		&& allow_1_setting(MSR_IA32_VMX_EXIT_CTLS,
 				   VM_EXIT_LOAD_IA32_EFER);
 
+	cpu_has_load_perf_global_ctrl =
+		allow_1_setting(MSR_IA32_VMX_ENTRY_CTLS,
+				VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL)
+		&& allow_1_setting(MSR_IA32_VMX_EXIT_CTLS,
+				   VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL);
+
+	/*
+	 * Some cpus support VM_ENTRY_(LOAD|SAVE)_IA32_PERF_GLOBAL_CTRL
+	 * but due to arrata below it can't be used. Workaround is to use
+	 * msr load mechanism to switch IA32_PERF_GLOBAL_CTRL.
+	 *
+	 * VM Exit May Incorrectly Clear IA32_PERF_GLOBAL_CTRL [34:32]
+	 *
+	 * AAK155             (model 26)
+	 * AAP115             (model 30)
+	 * AAT100             (model 37)
+	 * BC86,AAY89,BD102   (model 44)
+	 * BA97               (model 46)
+	 *
+	 */
+	if (cpu_has_load_perf_global_ctrl && boot_cpu_data.x86 == 0x6) {
+		switch (boot_cpu_data.x86_model) {
+		case 26:
+		case 30:
+		case 37:
+		case 44:
+		case 46:
+			cpu_has_load_perf_global_ctrl = false;
+			printk_once(KERN_WARNING"kvm: VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL "
+					"does not work properly. Using workaround\n");
+			break;
+		default:
+			break;
+		}
+	}
+
 	return 0;
 }
 
@@ -2736,8 +2849,8 @@
 
 	guest_tr_ar = vmcs_read32(GUEST_TR_AR_BYTES);
 	if ((guest_tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_64_TSS) {
-		printk(KERN_DEBUG "%s: tss fixup for long mode. \n",
-		       __func__);
+		pr_debug_ratelimited("%s: tss fixup for long mode. \n",
+				     __func__);
 		vmcs_write32(GUEST_TR_AR_BYTES,
 			     (guest_tr_ar & ~AR_TYPE_MASK)
 			     | AR_TYPE_BUSY_64_TSS);
@@ -4115,8 +4228,7 @@
 		error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
 	if (is_page_fault(intr_info)) {
 		/* EPT won't cause page fault directly */
-		if (enable_ept)
-			BUG();
+		BUG_ON(enable_ept);
 		cr2 = vmcs_readl(EXIT_QUALIFICATION);
 		trace_kvm_page_fault(cr2, error_code);
 
@@ -4518,6 +4630,24 @@
 
 static int handle_apic_access(struct kvm_vcpu *vcpu)
 {
+	if (likely(fasteoi)) {
+		unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+		int access_type, offset;
+
+		access_type = exit_qualification & APIC_ACCESS_TYPE;
+		offset = exit_qualification & APIC_ACCESS_OFFSET;
+		/*
+		 * Sane guest uses MOV to write EOI, with written value
+		 * not cared. So make a short-circuit here by avoiding
+		 * heavy instruction emulation.
+		 */
+		if ((access_type == TYPE_LINEAR_APIC_INST_WRITE) &&
+		    (offset == APIC_EOI)) {
+			kvm_lapic_set_eoi(vcpu);
+			skip_emulated_instruction(vcpu);
+			return 1;
+		}
+	}
 	return emulate_instruction(vcpu, 0) == EMULATE_DONE;
 }
 
@@ -5591,8 +5721,8 @@
 		return 0;
 
 	if (unlikely(vmx->fail)) {
-		printk(KERN_INFO "%s failed vm entry %x\n",
-		       __func__, vmcs_read32(VM_INSTRUCTION_ERROR));
+		pr_info_ratelimited("%s failed vm entry %x\n", __func__,
+				    vmcs_read32(VM_INSTRUCTION_ERROR));
 		return 1;
 	}
 
@@ -5696,8 +5826,6 @@
 	u32 exit_reason = vmx->exit_reason;
 	u32 vectoring_info = vmx->idt_vectoring_info;
 
-	trace_kvm_exit(exit_reason, vcpu, KVM_ISA_VMX);
-
 	/* If guest state is invalid, start emulating */
 	if (vmx->emulation_required && emulate_invalid_guest_state)
 		return handle_invalid_guest_state(vcpu);
@@ -5927,6 +6055,24 @@
 	vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0);
 }
 
+static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
+{
+	int i, nr_msrs;
+	struct perf_guest_switch_msr *msrs;
+
+	msrs = perf_guest_get_msrs(&nr_msrs);
+
+	if (!msrs)
+		return;
+
+	for (i = 0; i < nr_msrs; i++)
+		if (msrs[i].host == msrs[i].guest)
+			clear_atomic_switch_msr(vmx, msrs[i].msr);
+		else
+			add_atomic_switch_msr(vmx, msrs[i].msr, msrs[i].guest,
+					msrs[i].host);
+}
+
 #ifdef CONFIG_X86_64
 #define R "r"
 #define Q "q"
@@ -5976,6 +6122,8 @@
 	if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
 		vmx_set_interrupt_shadow(vcpu, 0);
 
+	atomic_switch_perf_msrs(vmx);
+
 	vmx->__launched = vmx->loaded_vmcs->launched;
 	asm(
 		/* Store host registers */
@@ -6101,6 +6249,7 @@
 	vmx->loaded_vmcs->launched = 1;
 
 	vmx->exit_reason = vmcs_read32(VM_EXIT_REASON);
+	trace_kvm_exit(vmx->exit_reason, vcpu, KVM_ISA_VMX);
 
 	vmx_complete_atomic_exit(vmx);
 	vmx_recover_nmi_blocking(vmx);
@@ -6241,49 +6390,6 @@
 	return ret;
 }
 
-#define _ER(x) { EXIT_REASON_##x, #x }
-
-static const struct trace_print_flags vmx_exit_reasons_str[] = {
-	_ER(EXCEPTION_NMI),
-	_ER(EXTERNAL_INTERRUPT),
-	_ER(TRIPLE_FAULT),
-	_ER(PENDING_INTERRUPT),
-	_ER(NMI_WINDOW),
-	_ER(TASK_SWITCH),
-	_ER(CPUID),
-	_ER(HLT),
-	_ER(INVLPG),
-	_ER(RDPMC),
-	_ER(RDTSC),
-	_ER(VMCALL),
-	_ER(VMCLEAR),
-	_ER(VMLAUNCH),
-	_ER(VMPTRLD),
-	_ER(VMPTRST),
-	_ER(VMREAD),
-	_ER(VMRESUME),
-	_ER(VMWRITE),
-	_ER(VMOFF),
-	_ER(VMON),
-	_ER(CR_ACCESS),
-	_ER(DR_ACCESS),
-	_ER(IO_INSTRUCTION),
-	_ER(MSR_READ),
-	_ER(MSR_WRITE),
-	_ER(MWAIT_INSTRUCTION),
-	_ER(MONITOR_INSTRUCTION),
-	_ER(PAUSE_INSTRUCTION),
-	_ER(MCE_DURING_VMENTRY),
-	_ER(TPR_BELOW_THRESHOLD),
-	_ER(APIC_ACCESS),
-	_ER(EPT_VIOLATION),
-	_ER(EPT_MISCONFIG),
-	_ER(WBINVD),
-	{ -1, NULL }
-};
-
-#undef _ER
-
 static int vmx_get_lpage_level(void)
 {
 	if (enable_ept && !cpu_has_vmx_ept_1g_page())
@@ -6514,8 +6620,11 @@
 
 	set_cr4_guest_host_mask(vmx);
 
-	vmcs_write64(TSC_OFFSET,
-		vmx->nested.vmcs01_tsc_offset + vmcs12->tsc_offset);
+	if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING)
+		vmcs_write64(TSC_OFFSET,
+			vmx->nested.vmcs01_tsc_offset + vmcs12->tsc_offset);
+	else
+		vmcs_write64(TSC_OFFSET, vmx->nested.vmcs01_tsc_offset);
 
 	if (enable_vpid) {
 		/*
@@ -6610,9 +6719,8 @@
 	if (vmcs12->vm_entry_msr_load_count > 0 ||
 	    vmcs12->vm_exit_msr_load_count > 0 ||
 	    vmcs12->vm_exit_msr_store_count > 0) {
-		if (printk_ratelimit())
-			printk(KERN_WARNING
-			  "%s: VMCS MSR_{LOAD,STORE} unsupported\n", __func__);
+		pr_warn_ratelimited("%s: VMCS MSR_{LOAD,STORE} unsupported\n",
+				    __func__);
 		nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
 		return 1;
 	}
@@ -6922,7 +7030,7 @@
 
 	load_vmcs12_host_state(vcpu, vmcs12);
 
-	/* Update TSC_OFFSET if vmx_adjust_tsc_offset() was used while L2 ran */
+	/* Update TSC_OFFSET if TSC was changed while L2 ran */
 	vmcs_write64(TSC_OFFSET, vmx->nested.vmcs01_tsc_offset);
 
 	/* This is needed for same reason as it was needed in prepare_vmcs02 */
@@ -7039,7 +7147,6 @@
 	.get_mt_mask = vmx_get_mt_mask,
 
 	.get_exit_info = vmx_get_exit_info,
-	.exit_reasons_str = vmx_exit_reasons_str,
 
 	.get_lpage_level = vmx_get_lpage_level,
 
@@ -7055,6 +7162,7 @@
 	.write_tsc_offset = vmx_write_tsc_offset,
 	.adjust_tsc_offset = vmx_adjust_tsc_offset,
 	.compute_tsc_offset = vmx_compute_tsc_offset,
+	.read_l1_tsc = vmx_read_l1_tsc,
 
 	.set_tdp_cr3 = vmx_set_cr3,
 
diff -druN linux-libre-3.1-gnu/arch/x86/kvm/x86.c linux-libre-3.2-gnu/arch/x86/kvm/x86.c
--- linux-libre-3.1-gnu/arch/x86/kvm/x86.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/kvm/x86.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,6 +44,7 @@
 #include <linux/perf_event.h>
 #include <linux/uaccess.h>
 #include <linux/hash.h>
+#include <linux/pci.h>
 #include <trace/events/kvm.h>
 
 #define CREATE_TRACE_POINTS
@@ -83,6 +84,7 @@
 static void update_cr8_intercept(struct kvm_vcpu *vcpu);
 static int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid,
 				    struct kvm_cpuid_entry2 __user *entries);
+static void process_nmi(struct kvm_vcpu *vcpu);
 
 struct kvm_x86_ops *kvm_x86_ops;
 EXPORT_SYMBOL_GPL(kvm_x86_ops);
@@ -359,8 +361,8 @@
 
 void kvm_inject_nmi(struct kvm_vcpu *vcpu)
 {
-	kvm_make_request(KVM_REQ_EVENT, vcpu);
-	vcpu->arch.nmi_pending = 1;
+	atomic_inc(&vcpu->arch.nmi_queued);
+	kvm_make_request(KVM_REQ_NMI, vcpu);
 }
 EXPORT_SYMBOL_GPL(kvm_inject_nmi);
 
@@ -599,6 +601,7 @@
 static void update_cpuid(struct kvm_vcpu *vcpu)
 {
 	struct kvm_cpuid_entry2 *best;
+	struct kvm_lapic *apic = vcpu->arch.apic;
 
 	best = kvm_find_cpuid_entry(vcpu, 1, 0);
 	if (!best)
@@ -610,6 +613,13 @@
 		if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE))
 			best->ecx |= bit(X86_FEATURE_OSXSAVE);
 	}
+
+	if (apic) {
+		if (best->ecx & bit(X86_FEATURE_TSC_DEADLINE_TIMER))
+			apic->lapic_timer.timer_mode_mask = 3 << 17;
+		else
+			apic->lapic_timer.timer_mode_mask = 1 << 17;
+	}
 }
 
 int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -825,6 +835,7 @@
 static unsigned num_msrs_to_save;
 
 static u32 emulated_msrs[] = {
+	MSR_IA32_TSCDEADLINE,
 	MSR_IA32_MISC_ENABLE,
 	MSR_IA32_MCG_STATUS,
 	MSR_IA32_MCG_CTL,
@@ -1000,7 +1011,7 @@
 	return ret;
 }
 
-static u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
 {
 	if (vcpu->arch.virtual_tsc_khz)
 		return vcpu->arch.virtual_tsc_khz;
@@ -1098,7 +1109,7 @@
 
 	/* Keep irq disabled to prevent changes to the clock */
 	local_irq_save(flags);
-	kvm_get_msr(v, MSR_IA32_TSC, &tsc_timestamp);
+	tsc_timestamp = kvm_x86_ops->read_l1_tsc(v);
 	kernel_ns = get_kernel_ns();
 	this_tsc_khz = vcpu_tsc_khz(v);
 	if (unlikely(this_tsc_khz == 0)) {
@@ -1564,6 +1575,9 @@
 		break;
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
 		return kvm_x2apic_msr_write(vcpu, msr, data);
+	case MSR_IA32_TSCDEADLINE:
+		kvm_set_lapic_tscdeadline_msr(vcpu, data);
+		break;
 	case MSR_IA32_MISC_ENABLE:
 		vcpu->arch.ia32_misc_enable_msr = data;
 		break;
@@ -1825,6 +1839,9 @@
 		return kvm_hv_vapic_msr_read(vcpu, APIC_ICR, pdata);
 	case HV_X64_MSR_TPR:
 		return kvm_hv_vapic_msr_read(vcpu, APIC_TASKPRI, pdata);
+	case HV_X64_MSR_APIC_ASSIST_PAGE:
+		data = vcpu->arch.hv_vapic;
+		break;
 	default:
 		pr_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr);
 		return 1;
@@ -1839,7 +1856,6 @@
 
 	switch (msr) {
 	case MSR_IA32_PLATFORM_ID:
-	case MSR_IA32_UCODE_REV:
 	case MSR_IA32_EBL_CR_POWERON:
 	case MSR_IA32_DEBUGCTLMSR:
 	case MSR_IA32_LASTBRANCHFROMIP:
@@ -1860,6 +1876,9 @@
 	case MSR_FAM10H_MMIO_CONF_BASE:
 		data = 0;
 		break;
+	case MSR_IA32_UCODE_REV:
+		data = 0x100000000ULL;
+		break;
 	case MSR_MTRRcap:
 		data = 0x500 | KVM_NR_VAR_MTRR;
 		break;
@@ -1888,6 +1907,9 @@
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
 		return kvm_x2apic_msr_read(vcpu, msr, pdata);
 		break;
+	case MSR_IA32_TSCDEADLINE:
+		data = kvm_get_lapic_tscdeadline_msr(vcpu);
+		break;
 	case MSR_IA32_MISC_ENABLE:
 		data = vcpu->arch.ia32_misc_enable_msr;
 		break;
@@ -2086,6 +2108,9 @@
 		r = !kvm_x86_ops->cpu_has_accelerated_tpr();
 		break;
 	case KVM_CAP_NR_VCPUS:
+		r = KVM_SOFT_MAX_VCPUS;
+		break;
+	case KVM_CAP_MAX_VCPUS:
 		r = KVM_MAX_VCPUS;
 		break;
 	case KVM_CAP_NR_MEMSLOTS:
@@ -2095,7 +2120,7 @@
 		r = 0;
 		break;
 	case KVM_CAP_IOMMU:
-		r = iommu_found();
+		r = iommu_present(&pci_bus_type);
 		break;
 	case KVM_CAP_MCE:
 		r = KVM_MAX_MCE_BANKS;
@@ -2106,6 +2131,9 @@
 	case KVM_CAP_TSC_CONTROL:
 		r = kvm_has_tsc_control;
 		break;
+	case KVM_CAP_TSC_DEADLINE_TIMER:
+		r = boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER);
+		break;
 	default:
 		r = 0;
 		break;
@@ -2210,7 +2238,7 @@
 		s64 tsc_delta;
 		u64 tsc;
 
-		kvm_get_msr(vcpu, MSR_IA32_TSC, &tsc);
+		tsc = kvm_x86_ops->read_l1_tsc(vcpu);
 		tsc_delta = !vcpu->arch.last_guest_tsc ? 0 :
 			     tsc - vcpu->arch.last_guest_tsc;
 
@@ -2234,7 +2262,7 @@
 {
 	kvm_x86_ops->vcpu_put(vcpu);
 	kvm_put_guest_fpu(vcpu);
-	kvm_get_msr(vcpu, MSR_IA32_TSC, &vcpu->arch.last_guest_tsc);
+	vcpu->arch.last_guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
 }
 
 static int is_efer_nx(void)
@@ -2819,6 +2847,7 @@
 static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu,
 					       struct kvm_vcpu_events *events)
 {
+	process_nmi(vcpu);
 	events->exception.injected =
 		vcpu->arch.exception.pending &&
 		!kvm_exception_is_soft(vcpu->arch.exception.nr);
@@ -2836,7 +2865,7 @@
 			KVM_X86_SHADOW_INT_MOV_SS | KVM_X86_SHADOW_INT_STI);
 
 	events->nmi.injected = vcpu->arch.nmi_injected;
-	events->nmi.pending = vcpu->arch.nmi_pending;
+	events->nmi.pending = vcpu->arch.nmi_pending != 0;
 	events->nmi.masked = kvm_x86_ops->get_nmi_mask(vcpu);
 	events->nmi.pad = 0;
 
@@ -2856,6 +2885,7 @@
 			      | KVM_VCPUEVENT_VALID_SHADOW))
 		return -EINVAL;
 
+	process_nmi(vcpu);
 	vcpu->arch.exception.pending = events->exception.injected;
 	vcpu->arch.exception.nr = events->exception.nr;
 	vcpu->arch.exception.has_error_code = events->exception.has_error_code;
@@ -3556,7 +3586,11 @@
 			if (r) {
 				mutex_lock(&kvm->slots_lock);
 				kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
-							  &vpic->dev);
+							  &vpic->dev_master);
+				kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
+							  &vpic->dev_slave);
+				kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
+							  &vpic->dev_eclr);
 				mutex_unlock(&kvm->slots_lock);
 				kfree(vpic);
 				goto create_irqchip_unlock;
@@ -4045,84 +4079,105 @@
 	return 0;
 }
 
-static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
-				  unsigned long addr,
-				  void *val,
-				  unsigned int bytes,
-				  struct x86_exception *exception)
+int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
+			const void *val, int bytes)
 {
-	struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
-	gpa_t gpa;
-	int handled, ret;
+	int ret;
+
+	ret = kvm_write_guest(vcpu->kvm, gpa, val, bytes);
+	if (ret < 0)
+		return 0;
+	kvm_mmu_pte_write(vcpu, gpa, val, bytes, 1);
+	return 1;
+}
+
+struct read_write_emulator_ops {
+	int (*read_write_prepare)(struct kvm_vcpu *vcpu, void *val,
+				  int bytes);
+	int (*read_write_emulate)(struct kvm_vcpu *vcpu, gpa_t gpa,
+				  void *val, int bytes);
+	int (*read_write_mmio)(struct kvm_vcpu *vcpu, gpa_t gpa,
+			       int bytes, void *val);
+	int (*read_write_exit_mmio)(struct kvm_vcpu *vcpu, gpa_t gpa,
+				    void *val, int bytes);
+	bool write;
+};
 
+static int read_prepare(struct kvm_vcpu *vcpu, void *val, int bytes)
+{
 	if (vcpu->mmio_read_completed) {
 		memcpy(val, vcpu->mmio_data, bytes);
 		trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes,
 			       vcpu->mmio_phys_addr, *(u64 *)val);
 		vcpu->mmio_read_completed = 0;
-		return X86EMUL_CONTINUE;
+		return 1;
 	}
 
-	ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, false);
-
-	if (ret < 0)
-		return X86EMUL_PROPAGATE_FAULT;
-
-	if (ret)
-		goto mmio;
-
-	if (kvm_read_guest_virt(ctxt, addr, val, bytes, exception)
-	    == X86EMUL_CONTINUE)
-		return X86EMUL_CONTINUE;
+	return 0;
+}
 
-mmio:
-	/*
-	 * Is this MMIO handled locally?
-	 */
-	handled = vcpu_mmio_read(vcpu, gpa, bytes, val);
+static int read_emulate(struct kvm_vcpu *vcpu, gpa_t gpa,
+			void *val, int bytes)
+{
+	return !kvm_read_guest(vcpu->kvm, gpa, val, bytes);
+}
 
-	if (handled == bytes)
-		return X86EMUL_CONTINUE;
+static int write_emulate(struct kvm_vcpu *vcpu, gpa_t gpa,
+			 void *val, int bytes)
+{
+	return emulator_write_phys(vcpu, gpa, val, bytes);
+}
 
-	gpa += handled;
-	bytes -= handled;
-	val += handled;
+static int write_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes, void *val)
+{
+	trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, *(u64 *)val);
+	return vcpu_mmio_write(vcpu, gpa, bytes, val);
+}
 
+static int read_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
+			  void *val, int bytes)
+{
 	trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0);
-
-	vcpu->mmio_needed = 1;
-	vcpu->run->exit_reason = KVM_EXIT_MMIO;
-	vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;
-	vcpu->mmio_size = bytes;
-	vcpu->run->mmio.len = min(vcpu->mmio_size, 8);
-	vcpu->run->mmio.is_write = vcpu->mmio_is_write = 0;
-	vcpu->mmio_index = 0;
-
 	return X86EMUL_IO_NEEDED;
 }
 
-int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
-			const void *val, int bytes)
+static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
+			   void *val, int bytes)
 {
-	int ret;
-
-	ret = kvm_write_guest(vcpu->kvm, gpa, val, bytes);
-	if (ret < 0)
-		return 0;
-	kvm_mmu_pte_write(vcpu, gpa, val, bytes, 1);
-	return 1;
+	memcpy(vcpu->mmio_data, val, bytes);
+	memcpy(vcpu->run->mmio.data, vcpu->mmio_data, 8);
+	return X86EMUL_CONTINUE;
 }
 
-static int emulator_write_emulated_onepage(unsigned long addr,
-					   const void *val,
-					   unsigned int bytes,
-					   struct x86_exception *exception,
-					   struct kvm_vcpu *vcpu)
+static struct read_write_emulator_ops read_emultor = {
+	.read_write_prepare = read_prepare,
+	.read_write_emulate = read_emulate,
+	.read_write_mmio = vcpu_mmio_read,
+	.read_write_exit_mmio = read_exit_mmio,
+};
+
+static struct read_write_emulator_ops write_emultor = {
+	.read_write_emulate = write_emulate,
+	.read_write_mmio = write_mmio,
+	.read_write_exit_mmio = write_exit_mmio,
+	.write = true,
+};
+
+static int emulator_read_write_onepage(unsigned long addr, void *val,
+				       unsigned int bytes,
+				       struct x86_exception *exception,
+				       struct kvm_vcpu *vcpu,
+				       struct read_write_emulator_ops *ops)
 {
 	gpa_t gpa;
 	int handled, ret;
+	bool write = ops->write;
 
-	ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, true);
+	if (ops->read_write_prepare &&
+		  ops->read_write_prepare(vcpu, val, bytes))
+		return X86EMUL_CONTINUE;
+
+	ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, write);
 
 	if (ret < 0)
 		return X86EMUL_PROPAGATE_FAULT;
@@ -4131,15 +4186,14 @@
 	if (ret)
 		goto mmio;
 
-	if (emulator_write_phys(vcpu, gpa, val, bytes))
+	if (ops->read_write_emulate(vcpu, gpa, val, bytes))
 		return X86EMUL_CONTINUE;
 
 mmio:
-	trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, *(u64 *)val);
 	/*
 	 * Is this MMIO handled locally?
 	 */
-	handled = vcpu_mmio_write(vcpu, gpa, bytes, val);
+	handled = ops->read_write_mmio(vcpu, gpa, bytes, val);
 	if (handled == bytes)
 		return X86EMUL_CONTINUE;
 
@@ -4148,23 +4202,20 @@
 	val += handled;
 
 	vcpu->mmio_needed = 1;
-	memcpy(vcpu->mmio_data, val, bytes);
 	vcpu->run->exit_reason = KVM_EXIT_MMIO;
 	vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;
 	vcpu->mmio_size = bytes;
 	vcpu->run->mmio.len = min(vcpu->mmio_size, 8);
-	vcpu->run->mmio.is_write = vcpu->mmio_is_write = 1;
-	memcpy(vcpu->run->mmio.data, vcpu->mmio_data, 8);
+	vcpu->run->mmio.is_write = vcpu->mmio_is_write = write;
 	vcpu->mmio_index = 0;
 
-	return X86EMUL_CONTINUE;
+	return ops->read_write_exit_mmio(vcpu, gpa, val, bytes);
 }
 
-int emulator_write_emulated(struct x86_emulate_ctxt *ctxt,
-			    unsigned long addr,
-			    const void *val,
-			    unsigned int bytes,
-			    struct x86_exception *exception)
+int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr,
+			void *val, unsigned int bytes,
+			struct x86_exception *exception,
+			struct read_write_emulator_ops *ops)
 {
 	struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
 
@@ -4173,16 +4224,38 @@
 		int rc, now;
 
 		now = -addr & ~PAGE_MASK;
-		rc = emulator_write_emulated_onepage(addr, val, now, exception,
-						     vcpu);
+		rc = emulator_read_write_onepage(addr, val, now, exception,
+						 vcpu, ops);
+
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
 		addr += now;
 		val += now;
 		bytes -= now;
 	}
-	return emulator_write_emulated_onepage(addr, val, bytes, exception,
-					       vcpu);
+
+	return emulator_read_write_onepage(addr, val, bytes, exception,
+					   vcpu, ops);
+}
+
+static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
+				  unsigned long addr,
+				  void *val,
+				  unsigned int bytes,
+				  struct x86_exception *exception)
+{
+	return emulator_read_write(ctxt, addr, val, bytes,
+				   exception, &read_emultor);
+}
+
+int emulator_write_emulated(struct x86_emulate_ctxt *ctxt,
+			    unsigned long addr,
+			    const void *val,
+			    unsigned int bytes,
+			    struct x86_exception *exception)
+{
+	return emulator_read_write(ctxt, addr, (void *)val, bytes,
+				   exception, &write_emultor);
 }
 
 #define CMPXCHG_TYPE(t, ptr, old, new) \
@@ -4712,7 +4785,7 @@
 	kvm_set_rflags(vcpu, ctxt->eflags);
 
 	if (irq == NMI_VECTOR)
-		vcpu->arch.nmi_pending = false;
+		vcpu->arch.nmi_pending = 0;
 	else
 		vcpu->arch.interrupt.pending = false;
 
@@ -4788,7 +4861,7 @@
 
 		trace_kvm_emulate_insn_start(vcpu);
 		++vcpu->stat.insn_emulation;
-		if (r)  {
+		if (r != EMULATION_OK)  {
 			if (emulation_type & EMULTYPE_TRAP_UD)
 				return EMULATE_FAIL;
 			if (reexecute_instruction(vcpu, cr2))
@@ -5521,7 +5594,7 @@
 	/* try to inject new event if pending */
 	if (vcpu->arch.nmi_pending) {
 		if (kvm_x86_ops->nmi_allowed(vcpu)) {
-			vcpu->arch.nmi_pending = false;
+			--vcpu->arch.nmi_pending;
 			vcpu->arch.nmi_injected = true;
 			kvm_x86_ops->set_nmi(vcpu);
 		}
@@ -5553,10 +5626,26 @@
 	}
 }
 
+static void process_nmi(struct kvm_vcpu *vcpu)
+{
+	unsigned limit = 2;
+
+	/*
+	 * x86 is limited to one NMI running, and one NMI pending after it.
+	 * If an NMI is already in progress, limit further NMIs to just one.
+	 * Otherwise, allow two (and we'll inject the first one immediately).
+	 */
+	if (kvm_x86_ops->get_nmi_mask(vcpu) || vcpu->arch.nmi_injected)
+		limit = 1;
+
+	vcpu->arch.nmi_pending += atomic_xchg(&vcpu->arch.nmi_queued, 0);
+	vcpu->arch.nmi_pending = min(vcpu->arch.nmi_pending, limit);
+	kvm_make_request(KVM_REQ_EVENT, vcpu);
+}
+
 static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 {
 	int r;
-	bool nmi_pending;
 	bool req_int_win = !irqchip_in_kernel(vcpu->kvm) &&
 		vcpu->run->request_interrupt_window;
 
@@ -5596,6 +5685,8 @@
 		}
 		if (kvm_check_request(KVM_REQ_STEAL_UPDATE, vcpu))
 			record_steal_time(vcpu);
+		if (kvm_check_request(KVM_REQ_NMI, vcpu))
+			process_nmi(vcpu);
 
 	}
 
@@ -5603,19 +5694,11 @@
 	if (unlikely(r))
 		goto out;
 
-	/*
-	 * An NMI can be injected between local nmi_pending read and
-	 * vcpu->arch.nmi_pending read inside inject_pending_event().
-	 * But in that case, KVM_REQ_EVENT will be set, which makes
-	 * the race described above benign.
-	 */
-	nmi_pending = ACCESS_ONCE(vcpu->arch.nmi_pending);
-
 	if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) {
 		inject_pending_event(vcpu);
 
 		/* enable NMI/IRQ window open exits if needed */
-		if (nmi_pending)
+		if (vcpu->arch.nmi_pending)
 			kvm_x86_ops->enable_nmi_window(vcpu);
 		else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
 			kvm_x86_ops->enable_irq_window(vcpu);
@@ -5678,7 +5761,7 @@
 	if (hw_breakpoint_active())
 		hw_breakpoint_restore();
 
-	kvm_get_msr(vcpu, MSR_IA32_TSC, &vcpu->arch.last_guest_tsc);
+	vcpu->arch.last_guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
 
 	vcpu->mode = OUTSIDE_GUEST_MODE;
 	smp_wmb();
@@ -6323,7 +6406,8 @@
 
 int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu)
 {
-	vcpu->arch.nmi_pending = false;
+	atomic_set(&vcpu->arch.nmi_queued, 0);
+	vcpu->arch.nmi_pending = 0;
 	vcpu->arch.nmi_injected = false;
 
 	vcpu->arch.switch_db_regs = 0;
@@ -6598,7 +6682,7 @@
 		!vcpu->arch.apf.halted)
 		|| !list_empty_careful(&vcpu->async_pf.done)
 		|| vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED
-		|| vcpu->arch.nmi_pending ||
+		|| atomic_read(&vcpu->arch.nmi_queued) ||
 		(kvm_arch_interrupt_allowed(vcpu) &&
 		 kvm_cpu_has_interrupt(vcpu));
 }
diff -druN linux-libre-3.1-gnu/arch/x86/lguest/boot.c linux-libre-3.2-gnu/arch/x86/lguest/boot.c
--- linux-libre-3.1-gnu/arch/x86/lguest/boot.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/lguest/boot.c	2012-01-04 18:55:44.000000000 -0500
@@ -56,6 +56,7 @@
 #include <linux/lguest_launcher.h>
 #include <linux/virtio_console.h>
 #include <linux/pm.h>
+#include <linux/export.h>
 #include <asm/apic.h>
 #include <asm/lguest.h>
 #include <asm/paravirt.h>
@@ -70,6 +71,7 @@
 #include <asm/i387.h>
 #include <asm/stackprotector.h>
 #include <asm/reboot.h>		/* for struct machine_ops */
+#include <asm/kvm_para.h>
 
 /*G:010
  * Welcome to the Guest!
@@ -455,6 +457,15 @@
 		*ax &= 0xFFFFF0FF;
 		*ax |= 0x00000500;
 		break;
+
+	/*
+	 * This is used to detect if we're running under KVM.  We might be,
+	 * but that's a Host matter, not us.  So say we're not.
+	 */
+	case KVM_CPUID_SIGNATURE:
+		*bx = *cx = *dx = 0;
+		break;
+
 	/*
 	 * 0x80000000 returns the highest Extended Function, so we futureproof
 	 * like we do above by limiting it to known fields.
diff -druN linux-libre-3.1-gnu/arch/x86/lib/insn.c linux-libre-3.2-gnu/arch/x86/lib/insn.c
--- linux-libre-3.1-gnu/arch/x86/lib/insn.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/lib/insn.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,14 +22,23 @@
 #include <asm/inat.h>
 #include <asm/insn.h>
 
-#define get_next(t, insn)	\
-	({t r; r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; })
+/* Verify next sizeof(t) bytes can be on the same instruction */
+#define validate_next(t, insn, n)	\
+	((insn)->next_byte + sizeof(t) + n - (insn)->kaddr <= MAX_INSN_SIZE)
 
-#define peek_next(t, insn)	\
-	({t r; r = *(t*)insn->next_byte; r; })
+#define __get_next(t, insn)	\
+	({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; })
+
+#define __peek_nbyte_next(t, insn, n)	\
+	({ t r = *(t*)((insn)->next_byte + n); r; })
+
+#define get_next(t, insn)	\
+	({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); })
 
 #define peek_nbyte_next(t, insn, n)	\
-	({t r; r = *(t*)((insn)->next_byte + n); r; })
+	({ if (unlikely(!validate_next(t, insn, n))) goto err_out; __peek_nbyte_next(t, insn, n); })
+
+#define peek_next(t, insn)	peek_nbyte_next(t, insn, 0)
 
 /**
  * insn_init() - initialize struct insn
@@ -158,6 +167,8 @@
 	insn->vex_prefix.got = 1;
 
 	prefixes->got = 1;
+
+err_out:
 	return;
 }
 
@@ -208,6 +219,9 @@
 		insn->attr = 0;	/* This instruction is bad */
 end:
 	opcode->got = 1;
+
+err_out:
+	return;
 }
 
 /**
@@ -241,6 +255,9 @@
 	if (insn->x86_64 && inat_is_force64(insn->attr))
 		insn->opnd_bytes = 8;
 	modrm->got = 1;
+
+err_out:
+	return;
 }
 
 
@@ -290,6 +307,9 @@
 		}
 	}
 	insn->sib.got = 1;
+
+err_out:
+	return;
 }
 
 
@@ -351,6 +371,9 @@
 	}
 out:
 	insn->displacement.got = 1;
+
+err_out:
+	return;
 }
 
 /* Decode moffset16/32/64 */
@@ -373,6 +396,9 @@
 		break;
 	}
 	insn->moffset1.got = insn->moffset2.got = 1;
+
+err_out:
+	return;
 }
 
 /* Decode imm v32(Iz) */
@@ -389,6 +415,9 @@
 		insn->immediate.nbytes = 4;
 		break;
 	}
+
+err_out:
+	return;
 }
 
 /* Decode imm v64(Iv/Ov) */
@@ -411,6 +440,9 @@
 		break;
 	}
 	insn->immediate1.got = insn->immediate2.got = 1;
+
+err_out:
+	return;
 }
 
 /* Decode ptr16:16/32(Ap) */
@@ -432,6 +464,9 @@
 	insn->immediate2.value = get_next(unsigned short, insn);
 	insn->immediate2.nbytes = 2;
 	insn->immediate1.got = insn->immediate2.got = 1;
+
+err_out:
+	return;
 }
 
 /**
@@ -496,6 +531,9 @@
 	}
 done:
 	insn->immediate.got = 1;
+
+err_out:
+	return;
 }
 
 /**
diff -druN linux-libre-3.1-gnu/arch/x86/Makefile.um linux-libre-3.2-gnu/arch/x86/Makefile.um
--- linux-libre-3.1-gnu/arch/x86/Makefile.um	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/Makefile.um	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,61 @@
+core-y += arch/x86/crypto/
+
+ifeq ($(CONFIG_X86_32),y)
+START := 0x8048000
+
+LDFLAGS			+= -m elf_i386
+ELF_ARCH		:= i386
+ELF_FORMAT 		:= elf32-i386
+CHECKFLAGS	+= -D__i386__
+
+ifeq ("$(origin SUBARCH)", "command line")
+ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)")
+KBUILD_CFLAGS		+= $(call cc-option,-m32)
+KBUILD_AFLAGS		+= $(call cc-option,-m32)
+LINK-y			+= $(call cc-option,-m32)
+
+export LDFLAGS
+endif
+endif
+
+# First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y.
+include $(srctree)/arch/x86/Makefile_32.cpu
+
+# prevent gcc from keeping the stack 16 byte aligned. Taken from i386.
+cflags-y += $(call cc-option,-mpreferred-stack-boundary=2)
+
+# Prevent sprintf in nfsd from being converted to strcpy and resulting in
+# an unresolved reference.
+cflags-y += -ffreestanding
+
+# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
+# a lot more stack due to the lack of sharing of stacklots.  Also, gcc
+# 4.3.0 needs -funit-at-a-time for extern inline functions.
+KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \
+			echo $(call cc-option,-fno-unit-at-a-time); \
+			else echo $(call cc-option,-funit-at-a-time); fi ;)
+
+KBUILD_CFLAGS += $(cflags-y)
+
+else
+
+START := 0x60000000
+
+KBUILD_CFLAGS += -fno-builtin -m64 
+
+CHECKFLAGS  += -m64 -D__x86_64__
+KBUILD_AFLAGS += -m64
+LDFLAGS += -m elf_x86_64
+KBUILD_CPPFLAGS += -m64
+
+ELF_ARCH := i386:x86-64
+ELF_FORMAT := elf64-x86-64
+
+# Not on all 64-bit distros /lib is a symlink to /lib64. PLD is an example.
+
+LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64
+LINK-y += -m64
+
+# Do unit-at-a-time unconditionally on x86_64, following the host
+KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time)
+endif
diff -druN linux-libre-3.1-gnu/arch/x86/mm/fault.c linux-libre-3.2-gnu/arch/x86/mm/fault.c
--- linux-libre-3.1-gnu/arch/x86/mm/fault.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/mm/fault.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
 #include <asm/traps.h>			/* dotraplinkage, ...		*/
 #include <asm/pgalloc.h>		/* pgd_*(), ...			*/
 #include <asm/kmemcheck.h>		/* kmemcheck_*(), ...		*/
-#include <asm/vsyscall.h>
+#include <asm/fixmap.h>			/* VSYSCALL_START		*/
 
 /*
  * Page fault error code bits:
@@ -420,12 +420,14 @@
 	return 0;
 }
 
+#ifdef CONFIG_CPU_SUP_AMD
 static const char errata93_warning[] =
 KERN_ERR 
 "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
 "******* Working around it, but it may cause SEGVs or burn power.\n"
 "******* Please consider a BIOS update.\n"
 "******* Disabling USB legacy in the BIOS may also help.\n";
+#endif
 
 /*
  * No vm86 mode in 64-bit mode:
@@ -505,7 +507,11 @@
  */
 static int is_errata93(struct pt_regs *regs, unsigned long address)
 {
-#ifdef CONFIG_X86_64
+#if defined(CONFIG_X86_64) && defined(CONFIG_CPU_SUP_AMD)
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD
+	    || boot_cpu_data.x86 != 0xf)
+		return 0;
+
 	if (address != regs->ip)
 		return 0;
 
diff -druN linux-libre-3.1-gnu/arch/x86/mm/gup.c linux-libre-3.2-gnu/arch/x86/mm/gup.c
--- linux-libre-3.1-gnu/arch/x86/mm/gup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/mm/gup.c	2012-01-04 18:55:44.000000000 -0500
@@ -108,16 +108,6 @@
 	SetPageReferenced(page);
 }
 
-static inline void get_huge_page_tail(struct page *page)
-{
-	/*
-	 * __split_huge_page_refcount() cannot run
-	 * from under us.
-	 */
-	VM_BUG_ON(atomic_read(&page->_count) < 0);
-	atomic_inc(&page->_count);
-}
-
 static noinline int gup_huge_pmd(pmd_t pmd, unsigned long addr,
 		unsigned long end, int write, struct page **pages, int *nr)
 {
@@ -211,6 +201,8 @@
 	do {
 		VM_BUG_ON(compound_head(page) != head);
 		pages[*nr] = page;
+		if (PageTail(page))
+			get_huge_page_tail(page);
 		(*nr)++;
 		page++;
 		refs++;
diff -druN linux-libre-3.1-gnu/arch/x86/mm/highmem_32.c linux-libre-3.2-gnu/arch/x86/mm/highmem_32.c
--- linux-libre-3.1-gnu/arch/x86/mm/highmem_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/mm/highmem_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,6 +45,7 @@
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 	BUG_ON(!pte_none(*(kmap_pte-idx)));
 	set_pte(kmap_pte-idx, mk_pte(page, prot));
+	arch_flush_lazy_mmu_mode();
 
 	return (void *)vaddr;
 }
@@ -88,6 +89,7 @@
 		 */
 		kpte_clear_flush(kmap_pte-idx, vaddr);
 		kmap_atomic_idx_pop();
+		arch_flush_lazy_mmu_mode();
 	}
 #ifdef CONFIG_DEBUG_HIGHMEM
 	else {
diff -druN linux-libre-3.1-gnu/arch/x86/mm/mmap.c linux-libre-3.2-gnu/arch/x86/mm/mmap.c
--- linux-libre-3.1-gnu/arch/x86/mm/mmap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/mm/mmap.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,10 @@
 #include <linux/sched.h>
 #include <asm/elf.h>
 
+struct __read_mostly va_alignment va_align = {
+	.flags = -1,
+};
+
 static unsigned int stack_maxrandom_size(void)
 {
 	unsigned int max = 0;
@@ -42,7 +46,6 @@
 	return max;
 }
 
-
 /*
  * Top of mmap area (just below the process stack).
  *
@@ -51,21 +54,6 @@
 #define MIN_GAP (128*1024*1024UL + stack_maxrandom_size())
 #define MAX_GAP (TASK_SIZE/6*5)
 
-/*
- * True on X86_32 or when emulating IA32 on X86_64
- */
-static int mmap_is_ia32(void)
-{
-#ifdef CONFIG_X86_32
-	return 1;
-#endif
-#ifdef CONFIG_IA32_EMULATION
-	if (test_thread_flag(TIF_IA32))
-		return 1;
-#endif
-	return 0;
-}
-
 static int mmap_is_legacy(void)
 {
 	if (current->personality & ADDR_COMPAT_LAYOUT)
diff -druN linux-libre-3.1-gnu/arch/x86/mm/mmio-mod.c linux-libre-3.2-gnu/arch/x86/mm/mmio-mod.c
--- linux-libre-3.1-gnu/arch/x86/mm/mmio-mod.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/mm/mmio-mod.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,6 @@
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
-#include <linux/version.h>
 #include <linux/kallsyms.h>
 #include <asm/pgtable.h>
 #include <linux/mmiotrace.h>
diff -druN linux-libre-3.1-gnu/arch/x86/net/bpf_jit_comp.c linux-libre-3.2-gnu/arch/x86/net/bpf_jit_comp.c
--- linux-libre-3.1-gnu/arch/x86/net/bpf_jit_comp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/net/bpf_jit_comp.c	2012-01-04 18:55:44.000000000 -0500
@@ -568,8 +568,8 @@
 					break;
 				}
 				if (filter[i].jt != 0) {
-					if (filter[i].jf)
-						t_offset += is_near(f_offset) ? 2 : 6;
+					if (filter[i].jf && f_offset)
+						t_offset += is_near(f_offset) ? 2 : 5;
 					EMIT_COND_JMP(t_op, t_offset);
 					if (filter[i].jf)
 						EMIT_JMP(f_offset);
diff -druN linux-libre-3.1-gnu/arch/x86/oprofile/init.c linux-libre-3.2-gnu/arch/x86/oprofile/init.c
--- linux-libre-3.1-gnu/arch/x86/oprofile/init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/oprofile/init.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 extern void op_nmi_exit(void);
 extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth);
 
+static int nmi_timer;
 
 int __init oprofile_arch_init(struct oprofile_operations *ops)
 {
@@ -31,8 +32,9 @@
 #ifdef CONFIG_X86_LOCAL_APIC
 	ret = op_nmi_init(ops);
 #endif
+	nmi_timer = (ret != 0);
 #ifdef CONFIG_X86_IO_APIC
-	if (ret < 0)
+	if (nmi_timer)
 		ret = op_nmi_timer_init(ops);
 #endif
 	ops->backtrace = x86_backtrace;
@@ -44,6 +46,7 @@
 void oprofile_arch_exit(void)
 {
 #ifdef CONFIG_X86_LOCAL_APIC
-	op_nmi_exit();
+	if (!nmi_timer)
+		op_nmi_exit();
 #endif
 }
diff -druN linux-libre-3.1-gnu/arch/x86/oprofile/nmi_int.c linux-libre-3.2-gnu/arch/x86/oprofile/nmi_int.c
--- linux-libre-3.1-gnu/arch/x86/oprofile/nmi_int.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/oprofile/nmi_int.c	2012-01-04 18:55:44.000000000 -0500
@@ -61,26 +61,15 @@
 }
 
 
-static int profile_exceptions_notify(struct notifier_block *self,
-				     unsigned long val, void *data)
+static int profile_exceptions_notify(unsigned int val, struct pt_regs *regs)
 {
-	struct die_args *args = (struct die_args *)data;
-	int ret = NOTIFY_DONE;
-
-	switch (val) {
-	case DIE_NMI:
-		if (ctr_running)
-			model->check_ctrs(args->regs, &__get_cpu_var(cpu_msrs));
-		else if (!nmi_enabled)
-			break;
-		else
-			model->stop(&__get_cpu_var(cpu_msrs));
-		ret = NOTIFY_STOP;
-		break;
-	default:
-		break;
-	}
-	return ret;
+	if (ctr_running)
+		model->check_ctrs(regs, &__get_cpu_var(cpu_msrs));
+	else if (!nmi_enabled)
+		return NMI_DONE;
+	else
+		model->stop(&__get_cpu_var(cpu_msrs));
+	return NMI_HANDLED;
 }
 
 static void nmi_cpu_save_registers(struct op_msrs *msrs)
@@ -355,20 +344,14 @@
 	int cpu = smp_processor_id();
 	struct op_msrs *msrs = &per_cpu(cpu_msrs, cpu);
 	nmi_cpu_save_registers(msrs);
-	spin_lock(&oprofilefs_lock);
+	raw_spin_lock(&oprofilefs_lock);
 	model->setup_ctrs(model, msrs);
 	nmi_cpu_setup_mux(cpu, msrs);
-	spin_unlock(&oprofilefs_lock);
+	raw_spin_unlock(&oprofilefs_lock);
 	per_cpu(saved_lvtpc, cpu) = apic_read(APIC_LVTPC);
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
 }
 
-static struct notifier_block profile_exceptions_nb = {
-	.notifier_call = profile_exceptions_notify,
-	.next = NULL,
-	.priority = NMI_LOCAL_LOW_PRIOR,
-};
-
 static void nmi_cpu_restore_registers(struct op_msrs *msrs)
 {
 	struct op_msr *counters = msrs->counters;
@@ -402,8 +385,6 @@
 	apic_write(APIC_LVTPC, per_cpu(saved_lvtpc, cpu));
 	apic_write(APIC_LVTERR, v);
 	nmi_cpu_restore_registers(msrs);
-	if (model->cpu_down)
-		model->cpu_down();
 }
 
 static void nmi_cpu_up(void *dummy)
@@ -508,7 +489,8 @@
 	ctr_running = 0;
 	/* make variables visible to the nmi handler: */
 	smp_mb();
-	err = register_die_notifier(&profile_exceptions_nb);
+	err = register_nmi_handler(NMI_LOCAL, profile_exceptions_notify,
+					0, "oprofile");
 	if (err)
 		goto fail;
 
@@ -538,7 +520,7 @@
 	put_online_cpus();
 	/* make variables visible to the nmi handler: */
 	smp_mb();
-	unregister_die_notifier(&profile_exceptions_nb);
+	unregister_nmi_handler(NMI_LOCAL, "oprofile");
 	msrs = &get_cpu_var(cpu_msrs);
 	model->shutdown(msrs);
 	free_msrs();
diff -druN linux-libre-3.1-gnu/arch/x86/oprofile/nmi_timer_int.c linux-libre-3.2-gnu/arch/x86/oprofile/nmi_timer_int.c
--- linux-libre-3.1-gnu/arch/x86/oprofile/nmi_timer_int.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/oprofile/nmi_timer_int.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,32 +18,16 @@
 #include <asm/apic.h>
 #include <asm/ptrace.h>
 
-static int profile_timer_exceptions_notify(struct notifier_block *self,
-					   unsigned long val, void *data)
+static int profile_timer_exceptions_notify(unsigned int val, struct pt_regs *regs)
 {
-	struct die_args *args = (struct die_args *)data;
-	int ret = NOTIFY_DONE;
-
-	switch (val) {
-	case DIE_NMI:
-		oprofile_add_sample(args->regs, 0);
-		ret = NOTIFY_STOP;
-		break;
-	default:
-		break;
-	}
-	return ret;
+	oprofile_add_sample(regs, 0);
+	return NMI_HANDLED;
 }
 
-static struct notifier_block profile_timer_exceptions_nb = {
-	.notifier_call = profile_timer_exceptions_notify,
-	.next = NULL,
-	.priority = NMI_LOW_PRIOR,
-};
-
 static int timer_start(void)
 {
-	if (register_die_notifier(&profile_timer_exceptions_nb))
+	if (register_nmi_handler(NMI_LOCAL, profile_timer_exceptions_notify,
+					0, "oprofile-timer"))
 		return 1;
 	return 0;
 }
@@ -51,7 +35,7 @@
 
 static void timer_stop(void)
 {
-	unregister_die_notifier(&profile_timer_exceptions_nb);
+	unregister_nmi_handler(NMI_LOCAL, "oprofile-timer");
 	synchronize_sched();  /* Allow already-started NMIs to complete. */
 }
 
diff -druN linux-libre-3.1-gnu/arch/x86/oprofile/op_model_amd.c linux-libre-3.2-gnu/arch/x86/oprofile/op_model_amd.c
--- linux-libre-3.1-gnu/arch/x86/oprofile/op_model_amd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/oprofile/op_model_amd.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,8 +29,6 @@
 #include "op_x86_model.h"
 #include "op_counter.h"
 
-#define NUM_COUNTERS		4
-#define NUM_COUNTERS_F15H	6
 #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
 #define NUM_VIRT_COUNTERS	32
 #else
@@ -70,62 +68,12 @@
 static struct ibs_state ibs_state;
 
 /*
- * IBS cpuid feature detection
- */
-
-#define IBS_CPUID_FEATURES		0x8000001b
-
-/*
- * Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but
- * bit 0 is used to indicate the existence of IBS.
- */
-#define IBS_CAPS_AVAIL			(1U<<0)
-#define IBS_CAPS_FETCHSAM		(1U<<1)
-#define IBS_CAPS_OPSAM			(1U<<2)
-#define IBS_CAPS_RDWROPCNT		(1U<<3)
-#define IBS_CAPS_OPCNT			(1U<<4)
-#define IBS_CAPS_BRNTRGT		(1U<<5)
-#define IBS_CAPS_OPCNTEXT		(1U<<6)
-
-#define IBS_CAPS_DEFAULT		(IBS_CAPS_AVAIL		\
-					 | IBS_CAPS_FETCHSAM	\
-					 | IBS_CAPS_OPSAM)
-
-/*
- * IBS APIC setup
- */
-#define IBSCTL				0x1cc
-#define IBSCTL_LVT_OFFSET_VALID		(1ULL<<8)
-#define IBSCTL_LVT_OFFSET_MASK		0x0F
-
-/*
  * IBS randomization macros
  */
 #define IBS_RANDOM_BITS			12
 #define IBS_RANDOM_MASK			((1ULL << IBS_RANDOM_BITS) - 1)
 #define IBS_RANDOM_MAXCNT_OFFSET	(1ULL << (IBS_RANDOM_BITS - 5))
 
-static u32 get_ibs_caps(void)
-{
-	u32 ibs_caps;
-	unsigned int max_level;
-
-	if (!boot_cpu_has(X86_FEATURE_IBS))
-		return 0;
-
-	/* check IBS cpuid feature flags */
-	max_level = cpuid_eax(0x80000000);
-	if (max_level < IBS_CPUID_FEATURES)
-		return IBS_CAPS_DEFAULT;
-
-	ibs_caps = cpuid_eax(IBS_CPUID_FEATURES);
-	if (!(ibs_caps & IBS_CAPS_AVAIL))
-		/* cpuid flags not valid */
-		return IBS_CAPS_DEFAULT;
-
-	return ibs_caps;
-}
-
 /*
  * 16-bit Linear Feedback Shift Register (LFSR)
  *
@@ -316,81 +264,6 @@
 		wrmsrl(MSR_AMD64_IBSOPCTL, 0);
 }
 
-static inline int get_eilvt(int offset)
-{
-	return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1);
-}
-
-static inline int put_eilvt(int offset)
-{
-	return !setup_APIC_eilvt(offset, 0, 0, 1);
-}
-
-static inline int ibs_eilvt_valid(void)
-{
-	int offset;
-	u64 val;
-	int valid = 0;
-
-	preempt_disable();
-
-	rdmsrl(MSR_AMD64_IBSCTL, val);
-	offset = val & IBSCTL_LVT_OFFSET_MASK;
-
-	if (!(val & IBSCTL_LVT_OFFSET_VALID)) {
-		pr_err(FW_BUG "cpu %d, invalid IBS interrupt offset %d (MSR%08X=0x%016llx)\n",
-		       smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
-		goto out;
-	}
-
-	if (!get_eilvt(offset)) {
-		pr_err(FW_BUG "cpu %d, IBS interrupt offset %d not available (MSR%08X=0x%016llx)\n",
-		       smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
-		goto out;
-	}
-
-	valid = 1;
-out:
-	preempt_enable();
-
-	return valid;
-}
-
-static inline int get_ibs_offset(void)
-{
-	u64 val;
-
-	rdmsrl(MSR_AMD64_IBSCTL, val);
-	if (!(val & IBSCTL_LVT_OFFSET_VALID))
-		return -EINVAL;
-
-	return val & IBSCTL_LVT_OFFSET_MASK;
-}
-
-static void setup_APIC_ibs(void)
-{
-	int offset;
-
-	offset = get_ibs_offset();
-	if (offset < 0)
-		goto failed;
-
-	if (!setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 0))
-		return;
-failed:
-	pr_warn("oprofile: IBS APIC setup failed on cpu #%d\n",
-		smp_processor_id());
-}
-
-static void clear_APIC_ibs(void)
-{
-	int offset;
-
-	offset = get_ibs_offset();
-	if (offset >= 0)
-		setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
-}
-
 #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
 
 static void op_mux_switch_ctrl(struct op_x86_model_spec const *model,
@@ -439,7 +312,7 @@
 			goto fail;
 		}
 		/* both registers must be reserved */
-		if (num_counters == NUM_COUNTERS_F15H) {
+		if (num_counters == AMD64_NUM_COUNTERS_F15H) {
 			msrs->counters[i].addr = MSR_F15H_PERF_CTR + (i << 1);
 			msrs->controls[i].addr = MSR_F15H_PERF_CTL + (i << 1);
 		} else {
@@ -504,15 +377,6 @@
 		val |= op_x86_get_ctrl(model, &counter_config[virt]);
 		wrmsrl(msrs->controls[i].addr, val);
 	}
-
-	if (ibs_caps)
-		setup_APIC_ibs();
-}
-
-static void op_amd_cpu_shutdown(void)
-{
-	if (ibs_caps)
-		clear_APIC_ibs();
 }
 
 static int op_amd_check_ctrs(struct pt_regs * const regs,
@@ -575,86 +439,6 @@
 	op_amd_stop_ibs();
 }
 
-static int setup_ibs_ctl(int ibs_eilvt_off)
-{
-	struct pci_dev *cpu_cfg;
-	int nodes;
-	u32 value = 0;
-
-	nodes = 0;
-	cpu_cfg = NULL;
-	do {
-		cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD,
-					 PCI_DEVICE_ID_AMD_10H_NB_MISC,
-					 cpu_cfg);
-		if (!cpu_cfg)
-			break;
-		++nodes;
-		pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
-				       | IBSCTL_LVT_OFFSET_VALID);
-		pci_read_config_dword(cpu_cfg, IBSCTL, &value);
-		if (value != (ibs_eilvt_off | IBSCTL_LVT_OFFSET_VALID)) {
-			pci_dev_put(cpu_cfg);
-			printk(KERN_DEBUG "Failed to setup IBS LVT offset, "
-			       "IBSCTL = 0x%08x\n", value);
-			return -EINVAL;
-		}
-	} while (1);
-
-	if (!nodes) {
-		printk(KERN_DEBUG "No CPU node configured for IBS\n");
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-/*
- * This runs only on the current cpu. We try to find an LVT offset and
- * setup the local APIC. For this we must disable preemption. On
- * success we initialize all nodes with this offset. This updates then
- * the offset in the IBS_CTL per-node msr. The per-core APIC setup of
- * the IBS interrupt vector is called from op_amd_setup_ctrs()/op_-
- * amd_cpu_shutdown() using the new offset.
- */
-static int force_ibs_eilvt_setup(void)
-{
-	int offset;
-	int ret;
-
-	preempt_disable();
-	/* find the next free available EILVT entry, skip offset 0 */
-	for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) {
-		if (get_eilvt(offset))
-			break;
-	}
-	preempt_enable();
-
-	if (offset == APIC_EILVT_NR_MAX) {
-		printk(KERN_DEBUG "No EILVT entry available\n");
-		return -EBUSY;
-	}
-
-	ret = setup_ibs_ctl(offset);
-	if (ret)
-		goto out;
-
-	if (!ibs_eilvt_valid()) {
-		ret = -EFAULT;
-		goto out;
-	}
-
-	pr_err(FW_BUG "using offset %d for IBS interrupts\n", offset);
-	pr_err(FW_BUG "workaround enabled for IBS LVT offset\n");
-
-	return 0;
-out:
-	preempt_disable();
-	put_eilvt(offset);
-	preempt_enable();
-	return ret;
-}
-
 /*
  * check and reserve APIC extended interrupt LVT offset for IBS if
  * available
@@ -667,17 +451,6 @@
 	if (!ibs_caps)
 		return;
 
-	if (ibs_eilvt_valid())
-		goto out;
-
-	if (!force_ibs_eilvt_setup())
-		goto out;
-
-	/* Failed to setup ibs */
-	ibs_caps = 0;
-	return;
-
-out:
 	printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps);
 }
 
@@ -741,9 +514,9 @@
 	ops->create_files = setup_ibs_files;
 
 	if (boot_cpu_data.x86 == 0x15) {
-		num_counters = NUM_COUNTERS_F15H;
+		num_counters = AMD64_NUM_COUNTERS_F15H;
 	} else {
-		num_counters = NUM_COUNTERS;
+		num_counters = AMD64_NUM_COUNTERS;
 	}
 
 	op_amd_spec.num_counters = num_counters;
@@ -760,7 +533,6 @@
 	.init			= op_amd_init,
 	.fill_in_addresses	= &op_amd_fill_in_addresses,
 	.setup_ctrs		= &op_amd_setup_ctrs,
-	.cpu_down		= &op_amd_cpu_shutdown,
 	.check_ctrs		= &op_amd_check_ctrs,
 	.start			= &op_amd_start,
 	.stop			= &op_amd_stop,
diff -druN linux-libre-3.1-gnu/arch/x86/oprofile/op_model_ppro.c linux-libre-3.2-gnu/arch/x86/oprofile/op_model_ppro.c
--- linux-libre-3.1-gnu/arch/x86/oprofile/op_model_ppro.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/oprofile/op_model_ppro.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,7 @@
 
 #define MSR_PPRO_EVENTSEL_RESERVED	((0xFFFFFFFFULL<<32)|(1ULL<<21))
 
-static u64 *reset_value;
+static u64 reset_value[OP_MAX_COUNTER];
 
 static void ppro_shutdown(struct op_msrs const * const msrs)
 {
@@ -40,10 +40,6 @@
 		release_perfctr_nmi(MSR_P6_PERFCTR0 + i);
 		release_evntsel_nmi(MSR_P6_EVNTSEL0 + i);
 	}
-	if (reset_value) {
-		kfree(reset_value);
-		reset_value = NULL;
-	}
 }
 
 static int ppro_fill_in_addresses(struct op_msrs * const msrs)
@@ -79,13 +75,6 @@
 	u64 val;
 	int i;
 
-	if (!reset_value) {
-		reset_value = kzalloc(sizeof(reset_value[0]) * num_counters,
-					GFP_ATOMIC);
-		if (!reset_value)
-			return;
-	}
-
 	if (cpu_has_arch_perfmon) {
 		union cpuid10_eax eax;
 		eax.full = cpuid_eax(0xa);
@@ -141,13 +130,6 @@
 	u64 val;
 	int i;
 
-	/*
-	 * This can happen if perf counters are in use when
-	 * we steal the die notifier NMI.
-	 */
-	if (unlikely(!reset_value))
-		goto out;
-
 	for (i = 0; i < num_counters; ++i) {
 		if (!reset_value[i])
 			continue;
@@ -158,7 +140,6 @@
 		wrmsrl(msrs->counters[i].addr, -reset_value[i]);
 	}
 
-out:
 	/* Only P6 based Pentium M need to re-unmask the apic vector but it
 	 * doesn't hurt other P6 variant */
 	apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
@@ -179,8 +160,6 @@
 	u64 val;
 	int i;
 
-	if (!reset_value)
-		return;
 	for (i = 0; i < num_counters; ++i) {
 		if (reset_value[i]) {
 			rdmsrl(msrs->controls[i].addr, val);
@@ -196,8 +175,6 @@
 	u64 val;
 	int i;
 
-	if (!reset_value)
-		return;
 	for (i = 0; i < num_counters; ++i) {
 		if (!reset_value[i])
 			continue;
@@ -242,7 +219,7 @@
 		eax.split.bit_width = 40;
 	}
 
-	num_counters = eax.split.num_counters;
+	num_counters = min((int)eax.split.num_counters, OP_MAX_COUNTER);
 
 	op_arch_perfmon_spec.num_counters = num_counters;
 	op_arch_perfmon_spec.num_controls = num_counters;
diff -druN linux-libre-3.1-gnu/arch/x86/oprofile/op_x86_model.h linux-libre-3.2-gnu/arch/x86/oprofile/op_x86_model.h
--- linux-libre-3.1-gnu/arch/x86/oprofile/op_x86_model.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/oprofile/op_x86_model.h	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,6 @@
 	int		(*fill_in_addresses)(struct op_msrs * const msrs);
 	void		(*setup_ctrs)(struct op_x86_model_spec const *model,
 				      struct op_msrs const * const msrs);
-	void		(*cpu_down)(void);
 	int		(*check_ctrs)(struct pt_regs * const regs,
 				      struct op_msrs const * const msrs);
 	void		(*start)(struct op_msrs const * const msrs);
diff -druN linux-libre-3.1-gnu/arch/x86/pci/ce4100.c linux-libre-3.2-gnu/arch/x86/pci/ce4100.c
--- linux-libre-3.1-gnu/arch/x86/pci/ce4100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/pci/ce4100.c	2012-01-04 18:55:44.000000000 -0500
@@ -304,7 +304,7 @@
 	return pci_direct_conf1.write(seg, bus, devfn, reg, len, value);
 }
 
-struct pci_raw_ops ce4100_pci_conf = {
+static const struct pci_raw_ops ce4100_pci_conf = {
 	.read =	ce4100_conf_read,
 	.write = ce4100_conf_write,
 };
diff -druN linux-libre-3.1-gnu/arch/x86/pci/common.c linux-libre-3.2-gnu/arch/x86/pci/common.c
--- linux-libre-3.1-gnu/arch/x86/pci/common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/pci/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,8 +33,8 @@
 int pcibios_last_bus = -1;
 unsigned long pirq_table_addr;
 struct pci_bus *pci_root_bus;
-struct pci_raw_ops *raw_pci_ops;
-struct pci_raw_ops *raw_pci_ext_ops;
+const struct pci_raw_ops *__read_mostly raw_pci_ops;
+const struct pci_raw_ops *__read_mostly raw_pci_ext_ops;
 
 int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
 						int reg, int len, u32 *val)
diff -druN linux-libre-3.1-gnu/arch/x86/pci/direct.c linux-libre-3.2-gnu/arch/x86/pci/direct.c
--- linux-libre-3.1-gnu/arch/x86/pci/direct.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/pci/direct.c	2012-01-04 18:55:44.000000000 -0500
@@ -79,7 +79,7 @@
 
 #undef PCI_CONF1_ADDRESS
 
-struct pci_raw_ops pci_direct_conf1 = {
+const struct pci_raw_ops pci_direct_conf1 = {
 	.read =		pci_conf1_read,
 	.write =	pci_conf1_write,
 };
@@ -175,7 +175,7 @@
 
 #undef PCI_CONF2_ADDRESS
 
-struct pci_raw_ops pci_direct_conf2 = {
+static const struct pci_raw_ops pci_direct_conf2 = {
 	.read =		pci_conf2_read,
 	.write =	pci_conf2_write,
 };
@@ -191,7 +191,7 @@
  * This should be close to trivial, but it isn't, because there are buggy
  * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
  */
-static int __init pci_sanity_check(struct pci_raw_ops *o)
+static int __init pci_sanity_check(const struct pci_raw_ops *o)
 {
 	u32 x = 0;
 	int year, devfn;
diff -druN linux-libre-3.1-gnu/arch/x86/pci/i386.c linux-libre-3.2-gnu/arch/x86/pci/i386.c
--- linux-libre-3.1-gnu/arch/x86/pci/i386.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/pci/i386.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
diff -druN linux-libre-3.1-gnu/arch/x86/pci/legacy.c linux-libre-3.2-gnu/arch/x86/pci/legacy.c
--- linux-libre-3.1-gnu/arch/x86/pci/legacy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/pci/legacy.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,7 @@
  * legacy.c - traditional, old school PCI bus probing
  */
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <asm/pci_x86.h>
 
diff -druN linux-libre-3.1-gnu/arch/x86/pci/mmconfig_32.c linux-libre-3.2-gnu/arch/x86/pci/mmconfig_32.c
--- linux-libre-3.1-gnu/arch/x86/pci/mmconfig_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/pci/mmconfig_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -117,7 +117,7 @@
 	return 0;
 }
 
-static struct pci_raw_ops pci_mmcfg = {
+static const struct pci_raw_ops pci_mmcfg = {
 	.read =		pci_mmcfg_read,
 	.write =	pci_mmcfg_write,
 };
diff -druN linux-libre-3.1-gnu/arch/x86/pci/mmconfig_64.c linux-libre-3.2-gnu/arch/x86/pci/mmconfig_64.c
--- linux-libre-3.1-gnu/arch/x86/pci/mmconfig_64.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/pci/mmconfig_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -81,7 +81,7 @@
 	return 0;
 }
 
-static struct pci_raw_ops pci_mmcfg = {
+static const struct pci_raw_ops pci_mmcfg = {
 	.read =		pci_mmcfg_read,
 	.write =	pci_mmcfg_write,
 };
diff -druN linux-libre-3.1-gnu/arch/x86/pci/numaq_32.c linux-libre-3.2-gnu/arch/x86/pci/numaq_32.c
--- linux-libre-3.1-gnu/arch/x86/pci/numaq_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/pci/numaq_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -110,7 +110,7 @@
 
 #undef PCI_CONF1_MQ_ADDRESS
 
-static struct pci_raw_ops pci_direct_conf1_mq = {
+static const struct pci_raw_ops pci_direct_conf1_mq = {
 	.read	= pci_conf1_mq_read,
 	.write	= pci_conf1_mq_write
 };
diff -druN linux-libre-3.1-gnu/arch/x86/pci/olpc.c linux-libre-3.2-gnu/arch/x86/pci/olpc.c
--- linux-libre-3.1-gnu/arch/x86/pci/olpc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/pci/olpc.c	2012-01-04 18:55:44.000000000 -0500
@@ -301,7 +301,7 @@
 	return 0;
 }
 
-static struct pci_raw_ops pci_olpc_conf = {
+static const struct pci_raw_ops pci_olpc_conf = {
 	.read =	pci_olpc_read,
 	.write = pci_olpc_write,
 };
diff -druN linux-libre-3.1-gnu/arch/x86/pci/pcbios.c linux-libre-3.2-gnu/arch/x86/pci/pcbios.c
--- linux-libre-3.1-gnu/arch/x86/pci/pcbios.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/pci/pcbios.c	2012-01-04 18:55:44.000000000 -0500
@@ -303,7 +303,7 @@
  * Function table for BIOS32 access
  */
 
-static struct pci_raw_ops pci_bios_access = {
+static const struct pci_raw_ops pci_bios_access = {
 	.read =		pci_bios_read,
 	.write =	pci_bios_write
 };
@@ -312,7 +312,7 @@
  * Try to find PCI BIOS.
  */
 
-static struct pci_raw_ops * __devinit pci_find_bios(void)
+static const struct pci_raw_ops * __devinit pci_find_bios(void)
 {
 	union bios32 *check;
 	unsigned char sum;
diff -druN linux-libre-3.1-gnu/arch/x86/pci/xen.c linux-libre-3.2-gnu/arch/x86/pci/xen.c
--- linux-libre-3.1-gnu/arch/x86/pci/xen.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/pci/xen.c	2012-01-04 18:55:44.000000000 -0500
@@ -175,8 +175,10 @@
 					       "pcifront-msi-x" :
 					       "pcifront-msi",
 						DOMID_SELF);
-		if (irq < 0)
+		if (irq < 0) {
+			ret = irq;
 			goto free;
+		}
 		i++;
 	}
 	kfree(v);
@@ -221,8 +223,10 @@
 		if (msg.data != XEN_PIRQ_MSI_DATA ||
 		    xen_irq_from_pirq(pirq) < 0) {
 			pirq = xen_allocate_pirq_msi(dev, msidesc);
-			if (pirq < 0)
+			if (pirq < 0) {
+				irq = -ENODEV;
 				goto error;
+			}
 			xen_msi_compose_msg(dev, pirq, &msg);
 			__write_msi_msg(msidesc, &msg);
 			dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq);
@@ -244,10 +248,12 @@
 error:
 	dev_err(&dev->dev,
 		"Xen PCI frontend has not registered MSI/MSI-X support!\n");
-	return -ENODEV;
+	return irq;
 }
 
 #ifdef CONFIG_XEN_DOM0
+static bool __read_mostly pci_seg_supported = true;
+
 static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
 	int ret = 0;
@@ -265,10 +271,11 @@
 
 		memset(&map_irq, 0, sizeof(map_irq));
 		map_irq.domid = domid;
-		map_irq.type = MAP_PIRQ_TYPE_MSI;
+		map_irq.type = MAP_PIRQ_TYPE_MSI_SEG;
 		map_irq.index = -1;
 		map_irq.pirq = -1;
-		map_irq.bus = dev->bus->number;
+		map_irq.bus = dev->bus->number |
+			      (pci_domain_nr(dev->bus) << 16);
 		map_irq.devfn = dev->devfn;
 
 		if (type == PCI_CAP_ID_MSIX) {
@@ -285,7 +292,20 @@
 			map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
 		}
 
-		ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
+		ret = -EINVAL;
+		if (pci_seg_supported)
+			ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq,
+						    &map_irq);
+		if (ret == -EINVAL && !pci_domain_nr(dev->bus)) {
+			map_irq.type = MAP_PIRQ_TYPE_MSI;
+			map_irq.index = -1;
+			map_irq.pirq = -1;
+			map_irq.bus = dev->bus->number;
+			ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq,
+						    &map_irq);
+			if (ret != -EINVAL)
+				pci_seg_supported = false;
+		}
 		if (ret) {
 			dev_warn(&dev->dev, "xen map irq failed %d for %d domain\n",
 				 ret, domid);
diff -druN linux-libre-3.1-gnu/arch/x86/platform/ce4100/ce4100.c linux-libre-3.2-gnu/arch/x86/platform/ce4100/ce4100.c
--- linux-libre-3.1-gnu/arch/x86/platform/ce4100/ce4100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/platform/ce4100/ce4100.c	2012-01-04 18:55:44.000000000 -0500
@@ -109,7 +109,7 @@
 }
 
 #else
-static inline void sdv_serial_fixup(void);
+static inline void sdv_serial_fixup(void) {};
 #endif
 
 static void __init sdv_arch_setup(void)
diff -druN linux-libre-3.1-gnu/arch/x86/platform/efi/efi_32.c linux-libre-3.2-gnu/arch/x86/platform/efi/efi_32.c
--- linux-libre-3.1-gnu/arch/x86/platform/efi/efi_32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/platform/efi/efi_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/efi.h>
 
 #include <asm/io.h>
+#include <asm/desc.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -38,43 +39,14 @@
  */
 
 static unsigned long efi_rt_eflags;
-static pgd_t efi_bak_pg_dir_pointer[2];
 
 void efi_call_phys_prelog(void)
 {
-	unsigned long cr4;
-	unsigned long temp;
 	struct desc_ptr gdt_descr;
 
 	local_irq_save(efi_rt_eflags);
 
-	/*
-	 * If I don't have PAE, I should just duplicate two entries in page
-	 * directory. If I have PAE, I just need to duplicate one entry in
-	 * page directory.
-	 */
-	cr4 = read_cr4_safe();
-
-	if (cr4 & X86_CR4_PAE) {
-		efi_bak_pg_dir_pointer[0].pgd =
-		    swapper_pg_dir[pgd_index(0)].pgd;
-		swapper_pg_dir[0].pgd =
-		    swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
-	} else {
-		efi_bak_pg_dir_pointer[0].pgd =
-		    swapper_pg_dir[pgd_index(0)].pgd;
-		efi_bak_pg_dir_pointer[1].pgd =
-		    swapper_pg_dir[pgd_index(0x400000)].pgd;
-		swapper_pg_dir[pgd_index(0)].pgd =
-		    swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
-		temp = PAGE_OFFSET + 0x400000;
-		swapper_pg_dir[pgd_index(0x400000)].pgd =
-		    swapper_pg_dir[pgd_index(temp)].pgd;
-	}
-
-	/*
-	 * After the lock is released, the original page table is restored.
-	 */
+	load_cr3(initial_page_table);
 	__flush_tlb_all();
 
 	gdt_descr.address = __pa(get_cpu_gdt_table(0));
@@ -84,28 +56,13 @@
 
 void efi_call_phys_epilog(void)
 {
-	unsigned long cr4;
 	struct desc_ptr gdt_descr;
 
 	gdt_descr.address = (unsigned long)get_cpu_gdt_table(0);
 	gdt_descr.size = GDT_SIZE - 1;
 	load_gdt(&gdt_descr);
 
-	cr4 = read_cr4_safe();
-
-	if (cr4 & X86_CR4_PAE) {
-		swapper_pg_dir[pgd_index(0)].pgd =
-		    efi_bak_pg_dir_pointer[0].pgd;
-	} else {
-		swapper_pg_dir[pgd_index(0)].pgd =
-		    efi_bak_pg_dir_pointer[0].pgd;
-		swapper_pg_dir[pgd_index(0x400000)].pgd =
-		    efi_bak_pg_dir_pointer[1].pgd;
-	}
-
-	/*
-	 * After the lock is released, the original page table is restored.
-	 */
+	load_cr3(swapper_pg_dir);
 	__flush_tlb_all();
 
 	local_irq_restore(efi_rt_eflags);
diff -druN linux-libre-3.1-gnu/arch/x86/platform/efi/efi.c linux-libre-3.2-gnu/arch/x86/platform/efi/efi.c
--- linux-libre-3.1-gnu/arch/x86/platform/efi/efi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/platform/efi/efi.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/efi.h>
+#include <linux/export.h>
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
 #include <linux/spinlock.h>
diff -druN linux-libre-3.1-gnu/arch/x86/platform/geode/alix.c linux-libre-3.2-gnu/arch/x86/platform/geode/alix.c
--- linux-libre-3.1-gnu/arch/x86/platform/geode/alix.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/platform/geode/alix.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,142 @@
+/*
+ * System Specific setup for PCEngines ALIX.
+ * At the moment this means setup of GPIO control of LEDs
+ * on Alix.2/3/6 boards.
+ *
+ *
+ * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
+ * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com>
+ *
+ * TODO: There are large similarities with leds-net5501.c
+ * by Alessandro Zummo <a.zummo@towertech.it>
+ * In the future leds-net5501.c should be migrated over to 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <asm/geode.h>
+
+static int force = 0;
+module_param(force, bool, 0444);
+/* FIXME: Award bios is not automatically detected as Alix platform */
+MODULE_PARM_DESC(force, "Force detection as ALIX.2/ALIX.3 platform");
+
+static struct gpio_led alix_leds[] = {
+	{
+		.name = "alix:1",
+		.gpio = 6,
+		.default_trigger = "default-on",
+		.active_low = 1,
+	},
+	{
+		.name = "alix:2",
+		.gpio = 25,
+		.default_trigger = "default-off",
+		.active_low = 1,
+	},
+	{
+		.name = "alix:3",
+		.gpio = 27,
+		.default_trigger = "default-off",
+		.active_low = 1,
+	},
+};
+
+static struct gpio_led_platform_data alix_leds_data = {
+	.num_leds = ARRAY_SIZE(alix_leds),
+	.leds = alix_leds,
+};
+
+static struct platform_device alix_leds_dev = {
+	.name = "leds-gpio",
+	.id = -1,
+	.dev.platform_data = &alix_leds_data,
+};
+
+static void __init register_alix(void)
+{
+	/* Setup LED control through leds-gpio driver */
+	platform_device_register(&alix_leds_dev);
+}
+
+static int __init alix_present(unsigned long bios_phys,
+				const char *alix_sig,
+				size_t alix_sig_len)
+{
+	const size_t bios_len = 0x00010000;
+	const char *bios_virt;
+	const char *scan_end;
+	const char *p;
+	char name[64];
+
+	if (force) {
+		printk(KERN_NOTICE "%s: forced to skip BIOS test, "
+		       "assume system is ALIX.2/ALIX.3\n",
+		       KBUILD_MODNAME);
+		return 1;
+	}
+
+	bios_virt = phys_to_virt(bios_phys);
+	scan_end = bios_virt + bios_len - (alix_sig_len + 2);
+	for (p = bios_virt; p < scan_end; p++) {
+		const char *tail;
+		char *a;
+
+		if (memcmp(p, alix_sig, alix_sig_len) != 0)
+			continue;
+
+		memcpy(name, p, sizeof(name));
+
+		/* remove the first \0 character from string */
+		a = strchr(name, '\0');
+		if (a)
+			*a = ' ';
+
+		/* cut the string at a newline */
+		a = strchr(name, '\r');
+		if (a)
+			*a = '\0';
+
+		tail = p + alix_sig_len;
+		if ((tail[0] == '2' || tail[0] == '3')) {
+			printk(KERN_INFO
+			       "%s: system is recognized as \"%s\"\n",
+			       KBUILD_MODNAME, name);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int __init alix_init(void)
+{
+	const char tinybios_sig[] = "PC Engines ALIX.";
+	const char coreboot_sig[] = "PC Engines\0ALIX.";
+
+	if (!is_geode())
+		return 0;
+
+	if (alix_present(0xf0000, tinybios_sig, sizeof(tinybios_sig) - 1) ||
+	    alix_present(0x500, coreboot_sig, sizeof(coreboot_sig) - 1))
+		register_alix();
+
+	return 0;
+}
+
+module_init(alix_init);
+
+MODULE_AUTHOR("Ed Wildgoose <kernel@wildgooses.com>");
+MODULE_DESCRIPTION("PCEngines ALIX System Setup");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/arch/x86/platform/geode/Makefile linux-libre-3.2-gnu/arch/x86/platform/geode/Makefile
--- linux-libre-3.1-gnu/arch/x86/platform/geode/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/platform/geode/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1 @@
+obj-$(CONFIG_ALIX)		+= alix.o
diff -druN linux-libre-3.1-gnu/arch/x86/platform/Makefile linux-libre-3.2-gnu/arch/x86/platform/Makefile
--- linux-libre-3.1-gnu/arch/x86/platform/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/platform/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 # Platform specific code goes here
 obj-y	+= ce4100/
 obj-y	+= efi/
+obj-y	+= geode/
 obj-y	+= iris/
 obj-y	+= mrst/
 obj-y	+= olpc/
diff -druN linux-libre-3.1-gnu/arch/x86/platform/mrst/mrst.c linux-libre-3.2-gnu/arch/x86/platform/mrst/mrst.c
--- linux-libre-3.1-gnu/arch/x86/platform/mrst/mrst.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/platform/mrst/mrst.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,8 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/scatterlist.h>
 #include <linux/sfi.h>
 #include <linux/intel_pmic_gpio.h>
 #include <linux/spi/spi.h>
@@ -24,6 +26,8 @@
 #include <linux/platform_device.h>
 #include <linux/irq.h>
 #include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/mfd/intel_msic.h>
 
 #include <asm/setup.h>
 #include <asm/mpspec_def.h>
@@ -72,6 +76,20 @@
 EXPORT_SYMBOL_GPL(sfi_mrtc_array);
 int sfi_mrtc_num;
 
+static void mrst_power_off(void)
+{
+	if (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT)
+		intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 1);
+}
+
+static void mrst_reboot(void)
+{
+	if (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT)
+		intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 0);
+	else
+		intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0);
+}
+
 /* parse all the mtimer info to a static mtimer array */
 static int __init sfi_parse_mtmr(struct sfi_table_header *table)
 {
@@ -183,11 +201,34 @@
 static unsigned long __init mrst_calibrate_tsc(void)
 {
 	unsigned long flags, fast_calibrate;
+	if (__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) {
+		u32 lo, hi, ratio, fsb;
 
-	local_irq_save(flags);
-	fast_calibrate = apbt_quick_calibrate();
-	local_irq_restore(flags);
-
+		rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+		pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
+		ratio = (hi >> 8) & 0x1f;
+		pr_debug("ratio is %d\n", ratio);
+		if (!ratio) {
+			pr_err("read a zero ratio, should be incorrect!\n");
+			pr_err("force tsc ratio to 16 ...\n");
+			ratio = 16;
+		}
+		rdmsr(MSR_FSB_FREQ, lo, hi);
+		if ((lo & 0x7) == 0x7)
+			fsb = PENWELL_FSB_FREQ_83SKU;
+		else
+			fsb = PENWELL_FSB_FREQ_100SKU;
+		fast_calibrate = ratio * fsb;
+		pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
+		lapic_timer_frequency = fsb * 1000 / HZ;
+		/* mark tsc clocksource as reliable */
+		set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
+	} else {
+		local_irq_save(flags);
+		fast_calibrate = apbt_quick_calibrate();
+		local_irq_restore(flags);
+	}
+	
 	if (fast_calibrate)
 		return fast_calibrate;
 
@@ -238,15 +279,15 @@
 	return 0;
 }
 
-/* Reboot and power off are handled by the SCU on a MID device */
-static void mrst_power_off(void)
-{
-	intel_scu_ipc_simple_command(0xf1, 1);
-}
-
-static void mrst_reboot(void)
+/*
+ * Moorestown does not have external NMI source nor port 0x61 to report
+ * NMI status. The possible NMI sources are from pmu as a result of NMI
+ * watchdog or lock debug. Reading io port 0x61 results in 0xff which
+ * misled NMI handler.
+ */
+static unsigned char mrst_get_nmi_reason(void)
 {
-	intel_scu_ipc_simple_command(0xf1, 0);
+	return 0;
 }
 
 /*
@@ -270,6 +311,8 @@
 	x86_platform.calibrate_tsc = mrst_calibrate_tsc;
 	x86_platform.i8042_detect = mrst_i8042_detect;
 	x86_init.timers.wallclock_init = mrst_rtc_init;
+	x86_platform.get_nmi_reason = mrst_get_nmi_reason;
+
 	x86_init.pci.init = pci_mrst_init;
 	x86_init.pci.fixup_irqs = x86_init_noop;
 
@@ -392,6 +435,7 @@
 	struct spi_board_info *spi_info = info;
 	int intr = get_gpio_by_name("max3111_int");
 
+	spi_info->mode = SPI_MODE_0;
 	if (intr == -1)
 		return NULL;
 	spi_info->irq = intr + MRST_IRQ_OFFSET;
@@ -443,6 +487,46 @@
 	return max7315;
 }
 
+static void *tca6416_platform_data(void *info)
+{
+	static struct pca953x_platform_data tca6416;
+	struct i2c_board_info *i2c_info = info;
+	int gpio_base, intr;
+	char base_pin_name[SFI_NAME_LEN + 1];
+	char intr_pin_name[SFI_NAME_LEN + 1];
+
+	strcpy(i2c_info->type, "tca6416");
+	strcpy(base_pin_name, "tca6416_base");
+	strcpy(intr_pin_name, "tca6416_int");
+
+	gpio_base = get_gpio_by_name(base_pin_name);
+	intr = get_gpio_by_name(intr_pin_name);
+
+	if (gpio_base == -1)
+		return NULL;
+	tca6416.gpio_base = gpio_base;
+	if (intr != -1) {
+		i2c_info->irq = intr + MRST_IRQ_OFFSET;
+		tca6416.irq_base = gpio_base + MRST_IRQ_OFFSET;
+	} else {
+		i2c_info->irq = -1;
+		tca6416.irq_base = -1;
+	}
+	return &tca6416;
+}
+
+static void *mpu3050_platform_data(void *info)
+{
+	struct i2c_board_info *i2c_info = info;
+	int intr = get_gpio_by_name("mpu3050_int");
+
+	if (intr == -1)
+		return NULL;
+
+	i2c_info->irq = intr + MRST_IRQ_OFFSET;
+	return NULL;
+}
+
 static void __init *emc1403_platform_data(void *info)
 {
 	static short intr2nd_pdata;
@@ -480,15 +564,148 @@
 	return NULL;
 }
 
+static struct resource msic_resources[] = {
+	{
+		.start	= INTEL_MSIC_IRQ_PHYS_BASE,
+		.end	= INTEL_MSIC_IRQ_PHYS_BASE + 64 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct intel_msic_platform_data msic_pdata;
+
+static struct platform_device msic_device = {
+	.name		= "intel_msic",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &msic_pdata,
+	},
+	.num_resources	= ARRAY_SIZE(msic_resources),
+	.resource	= msic_resources,
+};
+
+static inline bool mrst_has_msic(void)
+{
+	return mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL;
+}
+
+static int msic_scu_status_change(struct notifier_block *nb,
+				  unsigned long code, void *data)
+{
+	if (code == SCU_DOWN) {
+		platform_device_unregister(&msic_device);
+		return 0;
+	}
+
+	return platform_device_register(&msic_device);
+}
+
+static int __init msic_init(void)
+{
+	static struct notifier_block msic_scu_notifier = {
+		.notifier_call	= msic_scu_status_change,
+	};
+
+	/*
+	 * We need to be sure that the SCU IPC is ready before MSIC device
+	 * can be registered.
+	 */
+	if (mrst_has_msic())
+		intel_scu_notifier_add(&msic_scu_notifier);
+
+	return 0;
+}
+arch_initcall(msic_init);
+
+/*
+ * msic_generic_platform_data - sets generic platform data for the block
+ * @info: pointer to the SFI device table entry for this block
+ * @block: MSIC block
+ *
+ * Function sets IRQ number from the SFI table entry for given device to
+ * the MSIC platform data.
+ */
+static void *msic_generic_platform_data(void *info, enum intel_msic_block block)
+{
+	struct sfi_device_table_entry *entry = info;
+
+	BUG_ON(block < 0 || block >= INTEL_MSIC_BLOCK_LAST);
+	msic_pdata.irq[block] = entry->irq;
+
+	return no_platform_data(info);
+}
+
+static void *msic_battery_platform_data(void *info)
+{
+	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_BATTERY);
+}
+
+static void *msic_gpio_platform_data(void *info)
+{
+	static struct intel_msic_gpio_pdata pdata;
+	int gpio = get_gpio_by_name("msic_gpio_base");
+
+	if (gpio < 0)
+		return NULL;
+
+	pdata.gpio_base = gpio;
+	msic_pdata.gpio = &pdata;
+
+	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_GPIO);
+}
+
+static void *msic_audio_platform_data(void *info)
+{
+	struct platform_device *pdev;
+
+	pdev = platform_device_register_simple("sst-platform", -1, NULL, 0);
+	if (IS_ERR(pdev)) {
+		pr_err("failed to create audio platform device\n");
+		return NULL;
+	}
+
+	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_AUDIO);
+}
+
+static void *msic_power_btn_platform_data(void *info)
+{
+	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_POWER_BTN);
+}
+
+static void *msic_ocd_platform_data(void *info)
+{
+	static struct intel_msic_ocd_pdata pdata;
+	int gpio = get_gpio_by_name("ocd_gpio");
+
+	if (gpio < 0)
+		return NULL;
+
+	pdata.gpio = gpio;
+	msic_pdata.ocd = &pdata;
+
+	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD);
+}
+
 static const struct devs_id __initconst device_ids[] = {
+	{"bma023", SFI_DEV_TYPE_I2C, 1, &no_platform_data},
 	{"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data},
+	{"pmic_gpio", SFI_DEV_TYPE_IPC, 1, &pmic_gpio_platform_data},
 	{"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data},
 	{"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data},
 	{"i2c_max7315_2", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data},
+	{"tca6416", SFI_DEV_TYPE_I2C, 1, &tca6416_platform_data},
 	{"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data},
 	{"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data},
 	{"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data},
-	{"msic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data},
+	{"mpu3050", SFI_DEV_TYPE_I2C, 1, &mpu3050_platform_data},
+
+	/* MSIC subdevices */
+	{"msic_battery", SFI_DEV_TYPE_IPC, 1, &msic_battery_platform_data},
+	{"msic_gpio", SFI_DEV_TYPE_IPC, 1, &msic_gpio_platform_data},
+	{"msic_audio", SFI_DEV_TYPE_IPC, 1, &msic_audio_platform_data},
+	{"msic_power_btn", SFI_DEV_TYPE_IPC, 1, &msic_power_btn_platform_data},
+	{"msic_ocd", SFI_DEV_TYPE_IPC, 1, &msic_ocd_platform_data},
+
 	{},
 };
 
@@ -555,6 +772,9 @@
 	i2c_devs[i2c_next_dev++] = new_dev;
 }
 
+BLOCKING_NOTIFIER_HEAD(intel_scu_notifier);
+EXPORT_SYMBOL_GPL(intel_scu_notifier);
+
 /* Called by IPC driver */
 void intel_scu_devices_create(void)
 {
@@ -579,6 +799,7 @@
 		} else
 			i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1);
 	}
+	intel_scu_notifier_post(SCU_AVAILABLE, 0L);
 }
 EXPORT_SYMBOL_GPL(intel_scu_devices_create);
 
@@ -587,6 +808,8 @@
 {
 	int i;
 
+	intel_scu_notifier_post(SCU_DOWN, 0L);
+
 	for (i = 0; i < ipc_next_dev; i++)
 		platform_device_del(ipc_devs[i]);
 }
@@ -603,19 +826,37 @@
 	platform_device_add_resources(pdev, &res, 1);
 }
 
-static void __init sfi_handle_ipc_dev(struct platform_device *pdev)
+static void __init sfi_handle_ipc_dev(struct sfi_device_table_entry *entry)
 {
 	const struct devs_id *dev = device_ids;
+	struct platform_device *pdev;
 	void *pdata = NULL;
 
 	while (dev->name[0]) {
 		if (dev->type == SFI_DEV_TYPE_IPC &&
-			!strncmp(dev->name, pdev->name, SFI_NAME_LEN)) {
-			pdata = dev->get_platform_data(pdev);
+			!strncmp(dev->name, entry->name, SFI_NAME_LEN)) {
+			pdata = dev->get_platform_data(entry);
 			break;
 		}
 		dev++;
 	}
+
+	/*
+	 * On Medfield the platform device creation is handled by the MSIC
+	 * MFD driver so we don't need to do it here.
+	 */
+	if (mrst_has_msic())
+		return;
+
+	/* ID as IRQ is a hack that will go away */
+	pdev = platform_device_alloc(entry->name, entry->irq);
+	if (pdev == NULL) {
+		pr_err("out of memory for SFI platform device '%s'.\n",
+			entry->name);
+		return;
+	}
+	install_irq_resource(pdev, entry->irq);
+
 	pdev->dev.platform_data = pdata;
 	intel_scu_device_register(pdev);
 }
@@ -668,7 +909,6 @@
 	struct sfi_device_table_entry *pentry;
 	struct spi_board_info spi_info;
 	struct i2c_board_info i2c_info;
-	struct platform_device *pdev;
 	int num, i, bus;
 	int ioapic;
 	struct io_apic_irq_attr irq_attr;
@@ -696,17 +936,9 @@
 
 		switch (pentry->type) {
 		case SFI_DEV_TYPE_IPC:
-			/* ID as IRQ is a hack that will go away */
-			pdev = platform_device_alloc(pentry->name, irq);
-			if (pdev == NULL) {
-				pr_err("out of memory for SFI platform device '%s'.\n",
-							pentry->name);
-				continue;
-			}
-			install_irq_resource(pdev, irq);
 			pr_debug("info[%2d]: IPC bus, name = %16.16s, "
-				"irq = 0x%2x\n", i, pentry->name, irq);
-			sfi_handle_ipc_dev(pdev);
+				"irq = 0x%2x\n", i, pentry->name, pentry->irq);
+			sfi_handle_ipc_dev(pentry);
 			break;
 		case SFI_DEV_TYPE_SPI:
 			memset(&spi_info, 0, sizeof(spi_info));
diff -druN linux-libre-3.1-gnu/arch/x86/platform/mrst/pmu.c linux-libre-3.2-gnu/arch/x86/platform/mrst/pmu.c
--- linux-libre-3.1-gnu/arch/x86/platform/mrst/pmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/platform/mrst/pmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -70,7 +70,7 @@
 /* 24 */ { 0x4110, 0 },			/* Lincroft */
 };
 
-/* n.b. We ignore PCI-id 0x815 in LSS9 b/c MeeGo has no driver for it */
+/* n.b. We ignore PCI-id 0x815 in LSS9 b/c Linux has no driver for it */
 static u16 mrst_lss9_pci_ids[] = {0x080a, 0x0814, 0};
 static u16 mrst_lss10_pci_ids[] = {0x0800, 0x0801, 0x0802, 0x0803,
 					0x0804, 0x0805, 0x080f, 0};
diff -druN linux-libre-3.1-gnu/arch/x86/platform/mrst/vrtc.c linux-libre-3.2-gnu/arch/x86/platform/mrst/vrtc.c
--- linux-libre-3.1-gnu/arch/x86/platform/mrst/vrtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/platform/mrst/vrtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/sfi.h>
 #include <linux/platform_device.h>
@@ -75,8 +76,8 @@
 
 	spin_unlock_irqrestore(&rtc_lock, flags);
 
-	/* vRTC YEAR reg contains the offset to 1960 */
-	year += 1960;
+	/* vRTC YEAR reg contains the offset to 1972 */
+	year += 1972;
 
 	printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
 		"mon: %d year: %d\n", sec, min, hour, mday, mon, year);
diff -druN linux-libre-3.1-gnu/arch/x86/platform/olpc/olpc-xo1-pm.c linux-libre-3.2-gnu/arch/x86/platform/olpc/olpc-xo1-pm.c
--- linux-libre-3.1-gnu/arch/x86/platform/olpc/olpc-xo1-pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/platform/olpc/olpc-xo1-pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 
 #include <linux/cs5535.h>
 #include <linux/platform_device.h>
+#include <linux/export.h>
 #include <linux/pm.h>
 #include <linux/mfd/core.h>
 #include <linux/suspend.h>
diff -druN linux-libre-3.1-gnu/arch/x86/platform/uv/bios_uv.c linux-libre-3.2-gnu/arch/x86/platform/uv/bios_uv.c
--- linux-libre-3.1-gnu/arch/x86/platform/uv/bios_uv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/platform/uv/bios_uv.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/efi.h>
+#include <linux/export.h>
 #include <asm/efi.h>
 #include <linux/io.h>
 #include <asm/uv/bios.h>
diff -druN linux-libre-3.1-gnu/arch/x86/platform/uv/tlb_uv.c linux-libre-3.2-gnu/arch/x86/platform/uv/tlb_uv.c
--- linux-libre-3.1-gnu/arch/x86/platform/uv/tlb_uv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/platform/uv/tlb_uv.c	2012-01-04 18:55:44.000000000 -0500
@@ -115,9 +115,6 @@
 
 /* base pnode in this partition */
 static int uv_base_pnode __read_mostly;
-/* position of pnode (which is nasid>>1): */
-static int uv_nshift __read_mostly;
-static unsigned long uv_mmask __read_mostly;
 
 static DEFINE_PER_CPU(struct ptc_stats, ptcstats);
 static DEFINE_PER_CPU(struct bau_control, bau_control);
@@ -1435,7 +1432,7 @@
 {
 	int i;
 	int cpu;
-	unsigned long pa;
+	unsigned long gpa;
 	unsigned long m;
 	unsigned long n;
 	size_t dsize;
@@ -1451,9 +1448,9 @@
 	bau_desc = kmalloc_node(dsize, GFP_KERNEL, node);
 	BUG_ON(!bau_desc);
 
-	pa = uv_gpa(bau_desc); /* need the real nasid*/
-	n = pa >> uv_nshift;
-	m = pa & uv_mmask;
+	gpa = uv_gpa(bau_desc);
+	n = uv_gpa_to_gnode(gpa);
+	m = uv_gpa_to_offset(gpa);
 
 	/* the 14-bit pnode */
 	write_mmr_descriptor_base(pnode, (n << UV_DESC_PSHIFT | m));
@@ -1525,9 +1522,9 @@
 		bcp->queue_last		= pqp + (DEST_Q_SIZE - 1);
 	}
 	/*
-	 * need the pnode of where the memory was really allocated
+	 * need the gnode of where the memory was really allocated
 	 */
-	pn = uv_gpa(pqp) >> uv_nshift;
+	pn = uv_gpa_to_gnode(uv_gpa(pqp));
 	first = uv_physnodeaddr(pqp);
 	pn_first = ((unsigned long)pn << UV_PAYLOADQ_PNODE_SHIFT) | first;
 	last = uv_physnodeaddr(pqp + (DEST_Q_SIZE - 1));
@@ -1837,8 +1834,6 @@
 		zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cur_cpu));
 	}
 
-	uv_nshift = uv_hub_info->m_val;
-	uv_mmask = (1UL << uv_hub_info->m_val) - 1;
 	nuvhubs = uv_num_possible_blades();
 	spin_lock_init(&disable_lock);
 	congested_cycles = usec_2_cycles(congested_respns_us);
diff -druN linux-libre-3.1-gnu/arch/x86/power/cpu.c linux-libre-3.2-gnu/arch/x86/power/cpu.c
--- linux-libre-3.1-gnu/arch/x86/power/cpu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/power/cpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include <linux/suspend.h>
+#include <linux/export.h>
 #include <linux/smp.h>
 
 #include <asm/pgtable.h>
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/apic.h linux-libre-3.2-gnu/arch/x86/um/asm/apic.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/apic.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/apic.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,4 @@
+#ifndef __UM_APIC_H
+#define __UM_APIC_H
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/arch_hweight.h linux-libre-3.2-gnu/arch/x86/um/asm/arch_hweight.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/arch_hweight.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/arch_hweight.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,6 @@
+#ifndef _ASM_UM_HWEIGHT_H
+#define _ASM_UM_HWEIGHT_H
+
+#include <asm-generic/bitops/arch_hweight.h>
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/archparam.h linux-libre-3.2-gnu/arch/x86/um/asm/archparam.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/archparam.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/archparam.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,20 @@
+/* 
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright 2003 PathScale, Inc.
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_ARCHPARAM_H
+#define __UM_ARCHPARAM_H
+
+#ifdef CONFIG_X86_32
+
+#ifdef CONFIG_X86_PAE
+#define LAST_PKMAP 512
+#else
+#define LAST_PKMAP 1024
+#endif
+
+#endif
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/checksum_32.h linux-libre-3.2-gnu/arch/x86/um/asm/checksum_32.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/checksum_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/checksum_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,201 @@
+/*
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_SYSDEP_CHECKSUM_H
+#define __UM_SYSDEP_CHECKSUM_H
+
+#include "linux/in6.h"
+#include "linux/string.h"
+
+/*
+ * 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);
+
+/*
+ *	Note: when you get a NULL pointer exception here this means someone
+ *	passed in an incorrect kernel address to one of these functions.
+ *
+ *	If you use these functions directly please don't forget the
+ *	access_ok().
+ */
+
+static __inline__
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+				       int len, __wsum sum)
+{
+	memcpy(dst, src, len);
+	return csum_partial(dst, len, sum);
+}
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums, and handles user-space pointer exceptions correctly, when needed.
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+static __inline__
+__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+					 int len, __wsum sum, int *err_ptr)
+{
+	if (copy_from_user(dst, src, len)) {
+		*err_ptr = -EFAULT;
+		return (__force __wsum)-1;
+	}
+
+	return csum_partial(dst, len, sum);
+}
+
+/*
+ *	This is a version of ip_compute_csum() optimized for IP headers,
+ *	which always checksum on 4 octet boundaries.
+ *
+ *	By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
+ *	Arnt Gulbrandsen.
+ */
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+	unsigned int sum;
+
+	__asm__ __volatile__(
+	    "movl (%1), %0	;\n"
+	    "subl $4, %2	;\n"
+	    "jbe 2f		;\n"
+	    "addl 4(%1), %0	;\n"
+	    "adcl 8(%1), %0	;\n"
+	    "adcl 12(%1), %0	;\n"
+"1:	    adcl 16(%1), %0	;\n"
+	    "lea 4(%1), %1	;\n"
+	    "decl %2		;\n"
+	    "jne 1b		;\n"
+	    "adcl $0, %0	;\n"
+	    "movl %0, %2	;\n"
+	    "shrl $16, %0	;\n"
+	    "addw %w2, %w0	;\n"
+	    "adcl $0, %0	;\n"
+	    "notl %0		;\n"
+"2:				;\n"
+	/* Since the input registers which are loaded with iph and ipl
+	   are modified, we must also specify them as outputs, or gcc
+	   will assume they contain their original values. */
+	: "=r" (sum), "=r" (iph), "=r" (ihl)
+	: "1" (iph), "2" (ihl)
+	: "memory");
+	return (__force __sum16)sum;
+}
+
+/*
+ *	Fold a partial checksum
+ */
+
+static inline __sum16 csum_fold(__wsum sum)
+{
+	__asm__(
+		"addl %1, %0		;\n"
+		"adcl $0xffff, %0	;\n"
+		: "=r" (sum)
+		: "r" ((__force u32)sum << 16),
+		  "0" ((__force u32)sum & 0xffff0000)
+	);
+	return (__force __sum16)(~(__force u32)sum >> 16);
+}
+
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+						   unsigned short len,
+						   unsigned short proto,
+						   __wsum sum)
+{
+    __asm__(
+	"addl %1, %0	;\n"
+	"adcl %2, %0	;\n"
+	"adcl %3, %0	;\n"
+	"adcl $0, %0	;\n"
+	: "=r" (sum)
+	: "g" (daddr), "g"(saddr), "g"((len + proto) << 8), "0"(sum));
+    return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+						   unsigned short len,
+						   unsigned short proto,
+						   __wsum sum)
+{
+	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+static inline __sum16 ip_compute_csum(const void *buff, int len)
+{
+    return csum_fold (csum_partial(buff, len, 0));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+					  const struct in6_addr *daddr,
+					  __u32 len, unsigned short proto,
+					  __wsum sum)
+{
+	__asm__(
+		"addl 0(%1), %0		;\n"
+		"adcl 4(%1), %0		;\n"
+		"adcl 8(%1), %0		;\n"
+		"adcl 12(%1), %0	;\n"
+		"adcl 0(%2), %0		;\n"
+		"adcl 4(%2), %0		;\n"
+		"adcl 8(%2), %0		;\n"
+		"adcl 12(%2), %0	;\n"
+		"adcl %3, %0		;\n"
+		"adcl %4, %0		;\n"
+		"adcl $0, %0		;\n"
+		: "=&r" (sum)
+		: "r" (saddr), "r" (daddr),
+		  "r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
+
+	return csum_fold(sum);
+}
+
+/*
+ *	Copy and checksum to user
+ */
+#define HAVE_CSUM_COPY_USER
+static __inline__ __wsum csum_and_copy_to_user(const void *src,
+						     void __user *dst,
+						     int len, __wsum sum, int *err_ptr)
+{
+	if (access_ok(VERIFY_WRITE, dst, len)) {
+		if (copy_to_user(dst, src, len)) {
+			*err_ptr = -EFAULT;
+			return (__force __wsum)-1;
+		}
+
+		return csum_partial(src, len, sum);
+	}
+
+	if (len)
+		*err_ptr = -EFAULT;
+
+	return (__force __wsum)-1; /* invalid checksum */
+}
+
+#endif
+
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/checksum_64.h linux-libre-3.2-gnu/arch/x86/um/asm/checksum_64.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/checksum_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/checksum_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,144 @@
+/*
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_SYSDEP_CHECKSUM_H
+#define __UM_SYSDEP_CHECKSUM_H
+
+#include "linux/string.h"
+#include "linux/in6.h"
+#include "asm/uaccess.h"
+
+extern __wsum csum_partial(const void *buff, int len, __wsum sum);
+
+/*
+ *	Note: when you get a NULL pointer exception here this means someone
+ *	passed in an incorrect kernel address to one of these functions.
+ *
+ *	If you use these functions directly please don't forget the
+ *	access_ok().
+ */
+
+static __inline__
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+				       int len, __wsum sum)
+{
+	memcpy(dst, src, len);
+	return(csum_partial(dst, len, sum));
+}
+
+static __inline__
+__wsum csum_partial_copy_from_user(const void __user *src,
+                                         void *dst, int len, __wsum sum,
+                                         int *err_ptr)
+{
+        if (copy_from_user(dst, src, len)) {
+                *err_ptr = -EFAULT;
+                return (__force __wsum)-1;
+        }
+        return csum_partial(dst, len, sum);
+}
+
+/**
+ * csum_fold - Fold and invert a 32bit checksum.
+ * sum: 32bit unfolded sum
+ *
+ * Fold a 32bit running checksum to 16bit and invert it. This is usually
+ * the last step before putting a checksum into a packet.
+ * Make sure not to mix with 64bit checksums.
+ */
+static inline __sum16 csum_fold(__wsum sum)
+{
+	__asm__(
+		"  addl %1,%0\n"
+		"  adcl $0xffff,%0"
+		: "=r" (sum)
+		: "r" ((__force u32)sum << 16),
+		  "0" ((__force u32)sum & 0xffff0000)
+	);
+	return (__force __sum16)(~(__force u32)sum >> 16);
+}
+
+/**
+ * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.
+ * @saddr: source address
+ * @daddr: destination address
+ * @len: length of packet
+ * @proto: ip protocol of packet
+ * @sum: initial sum to be added in (32bit unfolded)
+ *
+ * Returns the pseudo header checksum the input data. Result is
+ * 32bit unfolded.
+ */
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+		   unsigned short proto, __wsum sum)
+{
+	asm("  addl %1, %0\n"
+	    "  adcl %2, %0\n"
+	    "  adcl %3, %0\n"
+	    "  adcl $0, %0\n"
+		: "=r" (sum)
+	    : "g" (daddr), "g" (saddr), "g" ((len + proto) << 8), "0" (sum));
+	return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+					   unsigned short len,
+					   unsigned short proto,
+					   __wsum sum)
+{
+	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/**
+ * ip_fast_csum - Compute the IPv4 header checksum efficiently.
+ * iph: ipv4 header
+ * ihl: length of header / 4
+ */
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+	unsigned int sum;
+
+	asm(	"  movl (%1), %0\n"
+		"  subl $4, %2\n"
+		"  jbe 2f\n"
+		"  addl 4(%1), %0\n"
+		"  adcl 8(%1), %0\n"
+		"  adcl 12(%1), %0\n"
+		"1: adcl 16(%1), %0\n"
+		"  lea 4(%1), %1\n"
+		"  decl %2\n"
+		"  jne	1b\n"
+		"  adcl $0, %0\n"
+		"  movl %0, %2\n"
+		"  shrl $16, %0\n"
+		"  addw %w2, %w0\n"
+		"  adcl $0, %0\n"
+		"  notl %0\n"
+		"2:"
+	/* Since the input registers which are loaded with iph and ipl
+	   are modified, we must also specify them as outputs, or gcc
+	   will assume they contain their original values. */
+	: "=r" (sum), "=r" (iph), "=r" (ihl)
+	: "1" (iph), "2" (ihl)
+	: "memory");
+	return (__force __sum16)sum;
+}
+
+static inline unsigned add32_with_carry(unsigned a, unsigned b)
+{
+        asm("addl %2,%0\n\t"
+            "adcl $0,%0"
+            : "=r" (a)
+            : "0" (a), "r" (b));
+        return a;
+}
+
+extern __sum16 ip_compute_csum(const void *buff, int len);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/checksum.h linux-libre-3.2-gnu/arch/x86/um/asm/checksum.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/checksum.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/checksum.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,10 @@
+#ifndef __UM_CHECKSUM_H
+#define __UM_CHECKSUM_H
+
+#ifdef CONFIG_X86_32
+# include "checksum_32.h"
+#else
+# include "checksum_64.h"
+#endif
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/desc.h linux-libre-3.2-gnu/arch/x86/um/asm/desc.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/desc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/desc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+#ifndef __UM_DESC_H
+#define __UM_DESC_H
+
+/* Taken from asm-i386/desc.h, it's the only thing we need. The rest wouldn't
+ * compile, and has never been used. */
+#define LDT_empty(info) (\
+	(info)->base_addr	== 0	&& \
+	(info)->limit		== 0	&& \
+	(info)->contents	== 0	&& \
+	(info)->read_exec_only	== 1	&& \
+	(info)->seg_32bit	== 0	&& \
+	(info)->limit_in_pages	== 0	&& \
+	(info)->seg_not_present	== 1	&& \
+	(info)->useable		== 0	)
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/elf.h linux-libre-3.2-gnu/arch/x86/um/asm/elf.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/elf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/elf.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+#ifndef __UM_ELF_X86_H
+#define __UM_ELF_X86_H
+
+#include <asm/user.h>
+#include "skas.h"
+
+#ifdef CONFIG_X86_32
+
+#define R_386_NONE	0
+#define R_386_32	1
+#define R_386_PC32	2
+#define R_386_GOT32	3
+#define R_386_PLT32	4
+#define R_386_COPY	5
+#define R_386_GLOB_DAT	6
+#define R_386_JMP_SLOT	7
+#define R_386_RELATIVE	8
+#define R_386_GOTOFF	9
+#define R_386_GOTPC	10
+#define R_386_NUM	11
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+	(((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
+
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA        ELFDATA2LSB
+#define ELF_ARCH        EM_386
+
+#define ELF_PLAT_INIT(regs, load_addr) do { \
+	PT_REGS_EBX(regs) = 0; \
+	PT_REGS_ECX(regs) = 0; \
+	PT_REGS_EDX(regs) = 0; \
+	PT_REGS_ESI(regs) = 0; \
+	PT_REGS_EDI(regs) = 0; \
+	PT_REGS_EBP(regs) = 0; \
+	PT_REGS_EAX(regs) = 0; \
+} while (0)
+
+/* Shamelessly stolen from include/asm-i386/elf.h */
+
+#define ELF_CORE_COPY_REGS(pr_reg, regs) do {	\
+	pr_reg[0] = PT_REGS_EBX(regs);		\
+	pr_reg[1] = PT_REGS_ECX(regs);		\
+	pr_reg[2] = PT_REGS_EDX(regs);		\
+	pr_reg[3] = PT_REGS_ESI(regs);		\
+	pr_reg[4] = PT_REGS_EDI(regs);		\
+	pr_reg[5] = PT_REGS_EBP(regs);		\
+	pr_reg[6] = PT_REGS_EAX(regs);		\
+	pr_reg[7] = PT_REGS_DS(regs);		\
+	pr_reg[8] = PT_REGS_ES(regs);		\
+	/* fake once used fs and gs selectors? */	\
+	pr_reg[9] = PT_REGS_DS(regs);		\
+	pr_reg[10] = PT_REGS_DS(regs);		\
+	pr_reg[11] = PT_REGS_SYSCALL_NR(regs);	\
+	pr_reg[12] = PT_REGS_IP(regs);		\
+	pr_reg[13] = PT_REGS_CS(regs);		\
+	pr_reg[14] = PT_REGS_EFLAGS(regs);	\
+	pr_reg[15] = PT_REGS_SP(regs);		\
+	pr_reg[16] = PT_REGS_SS(regs);		\
+} while (0);
+
+extern char * elf_aux_platform;
+#define ELF_PLATFORM (elf_aux_platform)
+
+extern unsigned long vsyscall_ehdr;
+extern unsigned long vsyscall_end;
+extern unsigned long __kernel_vsyscall;
+
+/*
+ * This is the range that is readable by user mode, and things
+ * acting like user mode such as get_user_pages.
+ */
+#define FIXADDR_USER_START      vsyscall_ehdr
+#define FIXADDR_USER_END        vsyscall_end
+
+
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them, start the x86-specific ones at 32.
+ */
+#define AT_SYSINFO		32
+#define AT_SYSINFO_EHDR		33
+
+#define ARCH_DLINFO						\
+do {								\
+	if ( vsyscall_ehdr ) {					\
+		NEW_AUX_ENT(AT_SYSINFO,	__kernel_vsyscall);	\
+		NEW_AUX_ENT(AT_SYSINFO_EHDR, vsyscall_ehdr);	\
+	}							\
+} while (0)
+
+#else
+
+/* x86-64 relocation types, taken from asm-x86_64/elf.h */
+#define R_X86_64_NONE		0	/* No reloc */
+#define R_X86_64_64		1	/* Direct 64 bit  */
+#define R_X86_64_PC32		2	/* PC relative 32 bit signed */
+#define R_X86_64_GOT32		3	/* 32 bit GOT entry */
+#define R_X86_64_PLT32		4	/* 32 bit PLT address */
+#define R_X86_64_COPY		5	/* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT	6	/* Create GOT entry */
+#define R_X86_64_JUMP_SLOT	7	/* Create PLT entry */
+#define R_X86_64_RELATIVE	8	/* Adjust by program base */
+#define R_X86_64_GOTPCREL	9	/* 32 bit signed pc relative
+					   offset to GOT */
+#define R_X86_64_32		10	/* Direct 32 bit zero extended */
+#define R_X86_64_32S		11	/* Direct 32 bit sign extended */
+#define R_X86_64_16		12	/* Direct 16 bit zero extended */
+#define R_X86_64_PC16		13	/* 16 bit sign extended pc relative */
+#define R_X86_64_8		14	/* Direct 8 bit sign extended  */
+#define R_X86_64_PC8		15	/* 8 bit sign extended pc relative */
+
+#define R_X86_64_NUM		16
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+	((x)->e_machine == EM_X86_64)
+
+#define ELF_CLASS	ELFCLASS64
+#define ELF_DATA        ELFDATA2LSB
+#define ELF_ARCH        EM_X86_64
+
+#define ELF_PLAT_INIT(regs, load_addr)    do { \
+	PT_REGS_RBX(regs) = 0; \
+	PT_REGS_RCX(regs) = 0; \
+	PT_REGS_RDX(regs) = 0; \
+	PT_REGS_RSI(regs) = 0; \
+	PT_REGS_RDI(regs) = 0; \
+	PT_REGS_RBP(regs) = 0; \
+	PT_REGS_RAX(regs) = 0; \
+	PT_REGS_R8(regs) = 0; \
+	PT_REGS_R9(regs) = 0; \
+	PT_REGS_R10(regs) = 0; \
+	PT_REGS_R11(regs) = 0; \
+	PT_REGS_R12(regs) = 0; \
+	PT_REGS_R13(regs) = 0; \
+	PT_REGS_R14(regs) = 0; \
+	PT_REGS_R15(regs) = 0; \
+} while (0)
+
+#define ELF_CORE_COPY_REGS(pr_reg, _regs)		\
+	(pr_reg)[0] = (_regs)->regs.gp[0];			\
+	(pr_reg)[1] = (_regs)->regs.gp[1];			\
+	(pr_reg)[2] = (_regs)->regs.gp[2];			\
+	(pr_reg)[3] = (_regs)->regs.gp[3];			\
+	(pr_reg)[4] = (_regs)->regs.gp[4];			\
+	(pr_reg)[5] = (_regs)->regs.gp[5];			\
+	(pr_reg)[6] = (_regs)->regs.gp[6];			\
+	(pr_reg)[7] = (_regs)->regs.gp[7];			\
+	(pr_reg)[8] = (_regs)->regs.gp[8];			\
+	(pr_reg)[9] = (_regs)->regs.gp[9];			\
+	(pr_reg)[10] = (_regs)->regs.gp[10];			\
+	(pr_reg)[11] = (_regs)->regs.gp[11];			\
+	(pr_reg)[12] = (_regs)->regs.gp[12];			\
+	(pr_reg)[13] = (_regs)->regs.gp[13];			\
+	(pr_reg)[14] = (_regs)->regs.gp[14];			\
+	(pr_reg)[15] = (_regs)->regs.gp[15];			\
+	(pr_reg)[16] = (_regs)->regs.gp[16];			\
+	(pr_reg)[17] = (_regs)->regs.gp[17];			\
+	(pr_reg)[18] = (_regs)->regs.gp[18];			\
+	(pr_reg)[19] = (_regs)->regs.gp[19];			\
+	(pr_reg)[20] = (_regs)->regs.gp[20];			\
+	(pr_reg)[21] = current->thread.arch.fs;			\
+	(pr_reg)[22] = 0;					\
+	(pr_reg)[23] = 0;					\
+	(pr_reg)[24] = 0;					\
+	(pr_reg)[25] = 0;					\
+	(pr_reg)[26] = 0;
+
+#define ELF_PLATFORM "x86_64"
+
+/* No user-accessible fixmap addresses, i.e. vsyscall */
+#define FIXADDR_USER_START      0
+#define FIXADDR_USER_END        0
+
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+	int uses_interp);
+
+extern unsigned long um_vdso_addr;
+#define AT_SYSINFO_EHDR 33
+#define ARCH_DLINFO	NEW_AUX_ENT(AT_SYSINFO_EHDR, um_vdso_addr)
+
+#endif
+
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct user_i387_struct elf_fpregset_t;
+
+#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);
+
+#define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu)
+
+#define ELF_EXEC_PAGESIZE 4096
+
+#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
+
+extern long elf_aux_hwcap;
+#define ELF_HWCAP (elf_aux_hwcap)
+
+#define SET_PERSONALITY(ex) do ; while(0)
+#define __HAVE_ARCH_GATE_AREA 1
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/irq_vectors.h linux-libre-3.2-gnu/arch/x86/um/asm/irq_vectors.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/irq_vectors.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/irq_vectors.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,10 @@
+/* 
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_IRQ_VECTORS_H
+#define __UM_IRQ_VECTORS_H
+
+#endif
+
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/mm_context.h linux-libre-3.2-gnu/arch/x86/um/asm/mm_context.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/mm_context.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/mm_context.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Licensed under the GPL
+ *
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ */
+
+#ifndef __ASM_LDT_H
+#define __ASM_LDT_H
+
+#include <linux/mutex.h>
+#include <asm/ldt.h>
+
+extern void ldt_host_info(void);
+
+#define LDT_PAGES_MAX \
+	((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
+#define LDT_ENTRIES_PER_PAGE \
+	(PAGE_SIZE/LDT_ENTRY_SIZE)
+#define LDT_DIRECT_ENTRIES \
+	((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE)
+
+struct ldt_entry {
+	__u32 a;
+	__u32 b;
+};
+
+typedef struct uml_ldt {
+	int entry_count;
+	struct mutex lock;
+	union {
+		struct ldt_entry * pages[LDT_PAGES_MAX];
+		struct ldt_entry entries[LDT_DIRECT_ENTRIES];
+	} u;
+} uml_ldt_t;
+
+#define LDT_entry_a(info) \
+	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
+
+#define LDT_entry_b(info) \
+	(((info)->base_addr & 0xff000000) | \
+	(((info)->base_addr & 0x00ff0000) >> 16) | \
+	((info)->limit & 0xf0000) | \
+	(((info)->read_exec_only ^ 1) << 9) | \
+	((info)->contents << 10) | \
+	(((info)->seg_not_present ^ 1) << 15) | \
+	((info)->seg_32bit << 22) | \
+	((info)->limit_in_pages << 23) | \
+	((info)->useable << 20) | \
+	0x7000)
+
+#define _LDT_empty(info) (\
+	(info)->base_addr	== 0	&& \
+	(info)->limit		== 0	&& \
+	(info)->contents	== 0	&& \
+	(info)->read_exec_only	== 1	&& \
+	(info)->seg_32bit	== 0	&& \
+	(info)->limit_in_pages	== 0	&& \
+	(info)->seg_not_present	== 1	&& \
+	(info)->useable		== 0	)
+
+#ifdef CONFIG_X86_64
+#define LDT_empty(info) (_LDT_empty(info) && ((info)->lm == 0))
+#else
+#define LDT_empty(info) (_LDT_empty(info))
+#endif
+
+struct uml_arch_mm_context {
+	uml_ldt_t ldt;
+};
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/module.h linux-libre-3.2-gnu/arch/x86/um/asm/module.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/module.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/module.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+#ifndef __UM_MODULE_H
+#define __UM_MODULE_H
+
+/* UML is simple */
+struct mod_arch_specific
+{
+};
+
+#ifdef CONFIG_X86_32
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+
+#else
+
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+#define Elf_Ehdr Elf64_Ehdr
+
+#endif
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/processor_32.h linux-libre-3.2-gnu/arch/x86/um/asm/processor_32.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/processor_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/processor_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PROCESSOR_I386_H
+#define __UM_PROCESSOR_I386_H
+
+#include <linux/string.h>
+#include <asm/segment.h>
+#include <asm/ldt.h>
+
+extern int host_has_cmov;
+
+struct uml_tls_struct {
+	struct user_desc tls;
+	unsigned flushed:1;
+	unsigned present:1;
+};
+
+struct arch_thread {
+	struct uml_tls_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
+	unsigned long debugregs[8];
+	int debugregs_seq;
+	struct faultinfo faultinfo;
+};
+
+#define INIT_ARCH_THREAD { \
+	.tls_array  		= { [ 0 ... GDT_ENTRY_TLS_ENTRIES - 1 ] = \
+				    { .present = 0, .flushed = 0 } }, \
+	.debugregs  		= { [ 0 ... 7 ] = 0 }, \
+	.debugregs_seq		= 0, \
+	.faultinfo		= { 0, 0, 0 } \
+}
+
+static inline void arch_flush_thread(struct arch_thread *thread)
+{
+	/* Clear any TLS still hanging */
+	memset(&thread->tls_array, 0, sizeof(thread->tls_array));
+}
+
+static inline void arch_copy_thread(struct arch_thread *from,
+                                    struct arch_thread *to)
+{
+        memcpy(&to->tls_array, &from->tls_array, sizeof(from->tls_array));
+}
+
+#include <asm/user.h>
+
+/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+static inline void rep_nop(void)
+{
+	__asm__ __volatile__("rep;nop": : :"memory");
+}
+
+#define cpu_relax()	rep_nop()
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter"). Stolen
+ * from asm-i386/processor.h
+ */
+#define current_text_addr() \
+	({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/processor_64.h linux-libre-3.2-gnu/arch/x86/um/asm/processor_64.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/processor_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/processor_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PROCESSOR_X86_64_H
+#define __UM_PROCESSOR_X86_64_H
+
+struct arch_thread {
+        unsigned long debugregs[8];
+        int debugregs_seq;
+        unsigned long fs;
+        struct faultinfo faultinfo;
+};
+
+/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+static inline void rep_nop(void)
+{
+	__asm__ __volatile__("rep;nop": : :"memory");
+}
+
+#define cpu_relax()   rep_nop()
+
+#define INIT_ARCH_THREAD { .debugregs  		= { [ 0 ... 7 ] = 0 }, \
+			   .debugregs_seq	= 0, \
+			   .fs			= 0, \
+			   .faultinfo		= { 0, 0, 0 } }
+
+static inline void arch_flush_thread(struct arch_thread *thread)
+{
+}
+
+static inline void arch_copy_thread(struct arch_thread *from,
+                                    struct arch_thread *to)
+{
+	to->fs = from->fs;
+}
+
+#include <asm/user.h>
+
+#define current_text_addr() \
+	({ void *pc; __asm__("movq $1f,%0\n1:":"=g" (pc)); pc; })
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/processor.h linux-libre-3.2-gnu/arch/x86/um/asm/processor.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/processor.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/processor.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+#ifndef __UM_PROCESSOR_H
+#define __UM_PROCESSOR_H
+
+/* include faultinfo structure */
+#include <sysdep/faultinfo.h>
+
+#ifdef CONFIG_X86_32
+# include "processor_32.h"
+#else
+# include "processor_64.h"
+#endif
+
+#define KSTK_EIP(tsk) KSTK_REG(tsk, HOST_IP)
+#define KSTK_ESP(tsk) KSTK_REG(tsk, HOST_SP)
+#define KSTK_EBP(tsk) KSTK_REG(tsk, HOST_BP)
+
+#define ARCH_IS_STACKGROW(address) \
+       (address + 65536 + 32 * sizeof(unsigned long) >= UPT_SP(&current->thread.regs.regs))
+
+#include <asm/processor-generic.h>
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/ptrace_32.h linux-libre-3.2-gnu/arch/x86/um/asm/ptrace_32.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/ptrace_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/ptrace_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,51 @@
+/* 
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PTRACE_I386_H
+#define __UM_PTRACE_I386_H
+
+#define HOST_AUDIT_ARCH AUDIT_ARCH_I386
+
+#include "linux/compiler.h"
+#include "asm/ptrace-generic.h"
+
+#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs)
+#define PT_REGS_EBX(r) UPT_EBX(&(r)->regs)
+#define PT_REGS_ECX(r) UPT_ECX(&(r)->regs)
+#define PT_REGS_EDX(r) UPT_EDX(&(r)->regs)
+#define PT_REGS_ESI(r) UPT_ESI(&(r)->regs)
+#define PT_REGS_EDI(r) UPT_EDI(&(r)->regs)
+#define PT_REGS_EBP(r) UPT_EBP(&(r)->regs)
+
+#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
+#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
+#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
+#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
+#define PT_REGS_FS(r) UPT_FS(&(r)->regs)
+#define PT_REGS_GS(r) UPT_GS(&(r)->regs)
+
+#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
+
+#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_EAX(r)
+#define PT_REGS_SYSCALL_RET(r) PT_REGS_EAX(r)
+#define PT_FIX_EXEC_STACK(sp) do ; while(0)
+
+#define profile_pc(regs) PT_REGS_IP(regs)
+
+#define user_mode(r) UPT_IS_USER(&(r)->regs)
+
+/*
+ * Forward declaration to avoid including sysdep/tls.h, which causes a
+ * circular include, and compilation failures.
+ */
+struct user_desc;
+
+extern int ptrace_get_thread_area(struct task_struct *child, int idx,
+                                  struct user_desc __user *user_desc);
+
+extern int ptrace_set_thread_area(struct task_struct *child, int idx,
+                                  struct user_desc __user *user_desc);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/ptrace_64.h linux-libre-3.2-gnu/arch/x86/um/asm/ptrace_64.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/ptrace_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/ptrace_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PTRACE_X86_64_H
+#define __UM_PTRACE_X86_64_H
+
+#include "linux/compiler.h"
+#include "asm/errno.h"
+
+#define __FRAME_OFFSETS /* Needed to get the R* macros */
+#include "asm/ptrace-generic.h"
+
+#define HOST_AUDIT_ARCH AUDIT_ARCH_X86_64
+
+#define PT_REGS_RBX(r) UPT_RBX(&(r)->regs)
+#define PT_REGS_RCX(r) UPT_RCX(&(r)->regs)
+#define PT_REGS_RDX(r) UPT_RDX(&(r)->regs)
+#define PT_REGS_RSI(r) UPT_RSI(&(r)->regs)
+#define PT_REGS_RDI(r) UPT_RDI(&(r)->regs)
+#define PT_REGS_RBP(r) UPT_RBP(&(r)->regs)
+#define PT_REGS_RAX(r) UPT_RAX(&(r)->regs)
+#define PT_REGS_R8(r) UPT_R8(&(r)->regs)
+#define PT_REGS_R9(r) UPT_R9(&(r)->regs)
+#define PT_REGS_R10(r) UPT_R10(&(r)->regs)
+#define PT_REGS_R11(r) UPT_R11(&(r)->regs)
+#define PT_REGS_R12(r) UPT_R12(&(r)->regs)
+#define PT_REGS_R13(r) UPT_R13(&(r)->regs)
+#define PT_REGS_R14(r) UPT_R14(&(r)->regs)
+#define PT_REGS_R15(r) UPT_R15(&(r)->regs)
+
+#define PT_REGS_FS(r) UPT_FS(&(r)->regs)
+#define PT_REGS_GS(r) UPT_GS(&(r)->regs)
+#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
+#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
+#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
+#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
+
+#define PT_REGS_ORIG_RAX(r) UPT_ORIG_RAX(&(r)->regs)
+#define PT_REGS_RIP(r) UPT_IP(&(r)->regs)
+#define PT_REGS_SP(r) UPT_SP(&(r)->regs)
+
+#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
+
+/* XXX */
+#define user_mode(r) UPT_IS_USER(&(r)->regs)
+#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_RAX(r)
+#define PT_REGS_SYSCALL_RET(r) PT_REGS_RAX(r)
+
+#define PT_FIX_EXEC_STACK(sp) do ; while(0)
+
+#define profile_pc(regs) PT_REGS_IP(regs)
+
+struct user_desc;
+
+static inline int ptrace_get_thread_area(struct task_struct *child, int idx,
+                                         struct user_desc __user *user_desc)
+{
+        return -ENOSYS;
+}
+
+static inline int ptrace_set_thread_area(struct task_struct *child, int idx,
+                                         struct user_desc __user *user_desc)
+{
+        return -ENOSYS;
+}
+
+extern long arch_prctl(struct task_struct *task, int code,
+		       unsigned long __user *addr);
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/ptrace.h linux-libre-3.2-gnu/arch/x86/um/asm/ptrace.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/ptrace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/ptrace.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+#ifdef CONFIG_X86_32
+# include "ptrace_32.h"
+#else
+# include "ptrace_64.h"
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/required-features.h linux-libre-3.2-gnu/arch/x86/um/asm/required-features.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/required-features.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/required-features.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,9 @@
+#ifndef __UM_REQUIRED_FEATURES_H
+#define __UM_REQUIRED_FEATURES_H
+
+/*
+ * Nothing to see, just need something for the i386 and x86_64 asm
+ * headers to include.
+ */
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/segment.h linux-libre-3.2-gnu/arch/x86/um/asm/segment.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/segment.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/segment.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,10 @@
+#ifndef __UM_SEGMENT_H
+#define __UM_SEGMENT_H
+
+extern int host_gdt_entry_tls_min;
+
+#define GDT_ENTRY_TLS_ENTRIES 3
+#define GDT_ENTRY_TLS_MIN host_gdt_entry_tls_min
+#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/system.h linux-libre-3.2-gnu/arch/x86/um/asm/system.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/system.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/system.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,135 @@
+#ifndef _ASM_X86_SYSTEM_H_
+#define _ASM_X86_SYSTEM_H_
+
+#include <asm/asm.h>
+#include <asm/segment.h>
+#include <asm/cpufeature.h>
+#include <asm/cmpxchg.h>
+#include <asm/nops.h>
+
+#include <linux/kernel.h>
+#include <linux/irqflags.h>
+
+/* entries in ARCH_DLINFO: */
+#ifdef CONFIG_IA32_EMULATION
+# define AT_VECTOR_SIZE_ARCH 2
+#else
+# define AT_VECTOR_SIZE_ARCH 1
+#endif
+
+extern unsigned long arch_align_stack(unsigned long sp);
+
+void default_idle(void);
+
+/*
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ */
+#ifdef CONFIG_X86_32
+/*
+ * Some non-Intel clones support out of order store. wmb() ceases to be a
+ * nop for these.
+ */
+#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
+#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
+#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
+#else
+#define mb() 	asm volatile("mfence":::"memory")
+#define rmb()	asm volatile("lfence":::"memory")
+#define wmb()	asm volatile("sfence" ::: "memory")
+#endif
+
+/**
+ * read_barrier_depends - Flush all pending reads that subsequents reads
+ * depend on.
+ *
+ * No data-dependent reads from memory-like regions are ever reordered
+ * over this barrier.  All reads preceding this primitive are guaranteed
+ * to access memory (but not necessarily other CPUs' caches) before any
+ * reads following this primitive that depend on the data return by
+ * any of the preceding reads.  This primitive is much lighter weight than
+ * rmb() on most CPUs, and is never heavier weight than is
+ * rmb().
+ *
+ * These ordering constraints are respected by both the local CPU
+ * and the compiler.
+ *
+ * Ordering is not guaranteed by anything other than these primitives,
+ * not even by data dependencies.  See the documentation for
+ * memory_barrier() for examples and URLs to more information.
+ *
+ * For example, the following code would force ordering (the initial
+ * value of "a" is zero, "b" is one, and "p" is "&a"):
+ *
+ * <programlisting>
+ *	CPU 0				CPU 1
+ *
+ *	b = 2;
+ *	memory_barrier();
+ *	p = &b;				q = p;
+ *					read_barrier_depends();
+ *					d = *q;
+ * </programlisting>
+ *
+ * because the read of "*q" depends on the read of "p" and these
+ * two reads are separated by a read_barrier_depends().  However,
+ * the following code, with the same initial values for "a" and "b":
+ *
+ * <programlisting>
+ *	CPU 0				CPU 1
+ *
+ *	a = 2;
+ *	memory_barrier();
+ *	b = 3;				y = b;
+ *					read_barrier_depends();
+ *					x = a;
+ * </programlisting>
+ *
+ * does not enforce ordering, since there is no data dependency between
+ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
+ * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
+ * in cases like this where there are no data dependencies.
+ **/
+
+#define read_barrier_depends()	do { } while (0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()	mb()
+#ifdef CONFIG_X86_PPRO_FENCE
+# define smp_rmb()	rmb()
+#else
+# define smp_rmb()	barrier()
+#endif
+#ifdef CONFIG_X86_OOSTORE
+# define smp_wmb() 	wmb()
+#else
+# define smp_wmb()	barrier()
+#endif
+#define smp_read_barrier_depends()	read_barrier_depends()
+#define set_mb(var, value) do { (void)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
+
+/*
+ * Stop RDTSC speculation. This is needed when you need to use RDTSC
+ * (or get_cycles or vread that possibly accesses the TSC) in a defined
+ * code region.
+ *
+ * (Could use an alternative three way for this if there was one.)
+ */
+static inline void rdtsc_barrier(void)
+{
+	alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
+	alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
+}
+
+extern void *_switch_to(void *prev, void *next, void *last);
+#define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/asm/vm-flags.h linux-libre-3.2-gnu/arch/x86/um/asm/vm-flags.h
--- linux-libre-3.1-gnu/arch/x86/um/asm/vm-flags.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/asm/vm-flags.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright 2003 PathScale, Inc.
+ * Licensed under the GPL
+ */
+
+#ifndef __VM_FLAGS_X86_H
+#define __VM_FLAGS_X86_H
+
+#ifdef CONFIG_X86_32
+
+#define VM_DATA_DEFAULT_FLAGS \
+	(VM_READ | VM_WRITE | \
+	((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
+		 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#else
+
+#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
+	VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+#define VM_STACK_DEFAULT_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \
+	VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#endif
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/bug.c linux-libre-3.2-gnu/arch/x86/um/bug.c
--- linux-libre-3.1-gnu/arch/x86/um/bug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/bug.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL V2
+ */
+
+#include <linux/uaccess.h>
+
+/*
+ * Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
+ * that's not relevant in skas mode.
+ */
+
+int is_valid_bugaddr(unsigned long eip)
+{
+	unsigned short ud2;
+
+	if (probe_kernel_address((unsigned short __user *)eip, ud2))
+		return 0;
+
+	return ud2 == 0x0b0f;
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/bugs_32.c linux-libre-3.2-gnu/arch/x86/um/bugs_32.c
--- linux-libre-3.1-gnu/arch/x86/um/bugs_32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/bugs_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include <signal.h>
+#include "kern_util.h"
+#include "longjmp.h"
+#include "sysdep/ptrace.h"
+#include <generated/asm-offsets.h>
+
+/* Set during early boot */
+static int host_has_cmov = 1;
+static jmp_buf cmov_test_return;
+
+#define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID]))
+
+static void cmov_sigill_test_handler(int sig)
+{
+	host_has_cmov = 0;
+	longjmp(cmov_test_return, 1);
+}
+
+void arch_check_bugs(void)
+{
+	struct sigaction old, new;
+
+	printk(UM_KERN_INFO "Checking for host processor cmov support...");
+	new.sa_handler = cmov_sigill_test_handler;
+
+	/* Make sure that SIGILL is enabled after the handler longjmps back */
+	new.sa_flags = SA_NODEFER;
+	sigemptyset(&new.sa_mask);
+	sigaction(SIGILL, &new, &old);
+
+	if (setjmp(cmov_test_return) == 0) {
+		unsigned long foo = 0;
+		__asm__ __volatile__("cmovz %0, %1" : "=r" (foo) : "0" (foo));
+		printk(UM_KERN_CONT "Yes\n");
+	} else
+		printk(UM_KERN_CONT "No\n");
+
+	sigaction(SIGILL, &old, &new);
+}
+
+void arch_examine_signal(int sig, struct uml_pt_regs *regs)
+{
+	unsigned char tmp[2];
+
+	/*
+	 * This is testing for a cmov (0x0f 0x4x) instruction causing a
+	 * SIGILL in init.
+	 */
+	if ((sig != SIGILL) || (TASK_PID(get_current()) != 1))
+		return;
+
+	if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) {
+		printk(UM_KERN_ERR "SIGILL in init, could not read "
+		       "instructions!\n");
+		return;
+	}
+
+	if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
+		return;
+
+	if (host_has_cmov == 0)
+		printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
+		       "processor doesn't implement.  Boot a filesystem "
+		       "compiled for older processors");
+	else if (host_has_cmov == 1)
+		printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
+		       "processor claims to implement");
+	else
+		printk(UM_KERN_ERR "Bad value for host_has_cmov (%d)",
+			host_has_cmov);
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/bugs_64.c linux-libre-3.2-gnu/arch/x86/um/bugs_64.c
--- linux-libre-3.1-gnu/arch/x86/um/bugs_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/bugs_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include "sysdep/ptrace.h"
+
+void arch_check_bugs(void)
+{
+}
+
+void arch_examine_signal(int sig, struct uml_pt_regs *regs)
+{
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/checksum_32.S linux-libre-3.2-gnu/arch/x86/um/checksum_32.S
--- linux-libre-3.1-gnu/arch/x86/um/checksum_32.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/checksum_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,458 @@
+/*
+ * 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>
+ *              Pentium Pro/II routines:
+ *              Alexander Kjeldaas <astor@guardian.no>
+ *              Finn Arne Gangstad <finnag@guardian.no>
+ *		Lots of code moved from tcp.c and ip.c; see those files
+ *		for more names.
+ *
+ * Changes:     Ingo Molnar, converted csum_partial_copy() to 2.1 exception
+ *			     handling.
+ *		Andi Kleen,  add zeroing on error
+ *                   converted to pure assembler
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/errno.h>
+				
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+/*	
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+ */
+		
+.text
+.align 4
+.globl csum_partial
+		
+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
+
+	  /*		
+	   * Experiments with Ethernet and SLIP connections show that buff
+	   * is aligned on either a 2-byte or 4-byte boundary.  We get at
+	   * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
+	   * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+	   * alignment for the unrolled loop.
+	   */		
+csum_partial:
+	pushl %esi
+	pushl %ebx
+	movl 20(%esp),%eax	# Function arg: unsigned int sum
+	movl 16(%esp),%ecx	# Function arg: int len
+	movl 12(%esp),%esi	# Function arg: unsigned char *buff
+	testl $2, %esi		# Check alignment.
+	jz 2f			# Jump if alignment is ok.
+	subl $2, %ecx		# Alignment uses up two bytes.
+	jae 1f			# Jump if we had at least two bytes.
+	addl $2, %ecx		# ecx was < 2.  Deal with it.
+	jmp 4f
+1:	movw (%esi), %bx
+	addl $2, %esi
+	addw %bx, %ax
+	adcl $0, %eax
+2:
+	movl %ecx, %edx
+	shrl $5, %ecx
+	jz 2f
+	testl %esi, %esi
+1:	movl (%esi), %ebx
+	adcl %ebx, %eax
+	movl 4(%esi), %ebx
+	adcl %ebx, %eax
+	movl 8(%esi), %ebx
+	adcl %ebx, %eax
+	movl 12(%esi), %ebx
+	adcl %ebx, %eax
+	movl 16(%esi), %ebx
+	adcl %ebx, %eax
+	movl 20(%esi), %ebx
+	adcl %ebx, %eax
+	movl 24(%esi), %ebx
+	adcl %ebx, %eax
+	movl 28(%esi), %ebx
+	adcl %ebx, %eax
+	lea 32(%esi), %esi
+	dec %ecx
+	jne 1b
+	adcl $0, %eax
+2:	movl %edx, %ecx
+	andl $0x1c, %edx
+	je 4f
+	shrl $2, %edx		# This clears CF
+3:	adcl (%esi), %eax
+	lea 4(%esi), %esi
+	dec %edx
+	jne 3b
+	adcl $0, %eax
+4:	andl $3, %ecx
+	jz 7f
+	cmpl $2, %ecx
+	jb 5f
+	movw (%esi),%cx
+	leal 2(%esi),%esi
+	je 6f
+	shll $16,%ecx
+5:	movb (%esi),%cl
+6:	addl %ecx,%eax
+	adcl $0, %eax 
+7:	
+	popl %ebx
+	popl %esi
+	ret
+
+#else
+
+/* Version for PentiumII/PPro */
+
+csum_partial:
+	pushl %esi
+	pushl %ebx
+	movl 20(%esp),%eax	# Function arg: unsigned int sum
+	movl 16(%esp),%ecx	# Function arg: int len
+	movl 12(%esp),%esi	# Function arg:	const unsigned char *buf
+
+	testl $2, %esi         
+	jnz 30f                 
+10:
+	movl %ecx, %edx
+	movl %ecx, %ebx
+	andl $0x7c, %ebx
+	shrl $7, %ecx
+	addl %ebx,%esi
+	shrl $2, %ebx  
+	negl %ebx
+	lea 45f(%ebx,%ebx,2), %ebx
+	testl %esi, %esi
+	jmp *%ebx
+
+	# Handle 2-byte-aligned regions
+20:	addw (%esi), %ax
+	lea 2(%esi), %esi
+	adcl $0, %eax
+	jmp 10b
+
+30:	subl $2, %ecx          
+	ja 20b                 
+	je 32f
+	movzbl (%esi),%ebx	# csumming 1 byte, 2-aligned
+	addl %ebx, %eax
+	adcl $0, %eax
+	jmp 80f
+32:
+	addw (%esi), %ax	# csumming 2 bytes, 2-aligned
+	adcl $0, %eax
+	jmp 80f
+
+40: 
+	addl -128(%esi), %eax
+	adcl -124(%esi), %eax
+	adcl -120(%esi), %eax
+	adcl -116(%esi), %eax   
+	adcl -112(%esi), %eax   
+	adcl -108(%esi), %eax
+	adcl -104(%esi), %eax
+	adcl -100(%esi), %eax
+	adcl -96(%esi), %eax
+	adcl -92(%esi), %eax
+	adcl -88(%esi), %eax
+	adcl -84(%esi), %eax
+	adcl -80(%esi), %eax
+	adcl -76(%esi), %eax
+	adcl -72(%esi), %eax
+	adcl -68(%esi), %eax
+	adcl -64(%esi), %eax     
+	adcl -60(%esi), %eax     
+	adcl -56(%esi), %eax     
+	adcl -52(%esi), %eax   
+	adcl -48(%esi), %eax   
+	adcl -44(%esi), %eax
+	adcl -40(%esi), %eax
+	adcl -36(%esi), %eax
+	adcl -32(%esi), %eax
+	adcl -28(%esi), %eax
+	adcl -24(%esi), %eax
+	adcl -20(%esi), %eax
+	adcl -16(%esi), %eax
+	adcl -12(%esi), %eax
+	adcl -8(%esi), %eax
+	adcl -4(%esi), %eax
+45:
+	lea 128(%esi), %esi
+	adcl $0, %eax
+	dec %ecx
+	jge 40b
+	movl %edx, %ecx
+50:	andl $3, %ecx
+	jz 80f
+
+	# Handle the last 1-3 bytes without jumping
+	notl %ecx		# 1->2, 2->1, 3->0, higher bits are masked
+	movl $0xffffff,%ebx	# by the shll and shrl instructions
+	shll $3,%ecx
+	shrl %cl,%ebx
+	andl -128(%esi),%ebx	# esi is 4-aligned so should be ok
+	addl %ebx,%eax
+	adcl $0,%eax
+80: 
+	popl %ebx
+	popl %esi
+	ret
+				
+#endif
+
+/*
+unsigned int csum_partial_copy_generic (const char *src, char *dst,
+				  int len, int sum, int *src_err_ptr, int *dst_err_ptr)
+ */ 
+
+/*
+ * Copy from ds while checksumming, otherwise like csum_partial
+ *
+ * The macros SRC and DST specify the type of access for the instruction.
+ * thus we can call a custom exception handler for all access types.
+ *
+ * FIXME: could someone double-check whether I haven't mixed up some SRC and
+ *	  DST definitions? It's damn hard to trigger all cases.  I hope I got
+ *	  them all but there's no guarantee.
+ */
+
+#define SRC(y...)			\
+	9999: y;			\
+	.section __ex_table, "a";	\
+	.long 9999b, 6001f	;	\
+	.previous
+
+#define DST(y...)			\
+	9999: y;			\
+	.section __ex_table, "a";	\
+	.long 9999b, 6002f	;	\
+	.previous
+
+.align 4
+
+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
+
+#define ARGBASE 16		
+#define FP		12
+
+csum_partial_copy_generic_i386:
+	subl  $4,%esp	
+	pushl %edi
+	pushl %esi
+	pushl %ebx
+	movl ARGBASE+16(%esp),%eax	# sum
+	movl ARGBASE+12(%esp),%ecx	# len
+	movl ARGBASE+4(%esp),%esi	# src
+	movl ARGBASE+8(%esp),%edi	# dst
+
+	testl $2, %edi			# Check alignment. 
+	jz 2f				# Jump if alignment is ok.
+	subl $2, %ecx			# Alignment uses up two bytes.
+	jae 1f				# Jump if we had at least two bytes.
+	addl $2, %ecx			# ecx was < 2.  Deal with it.
+	jmp 4f
+SRC(1:	movw (%esi), %bx	)
+	addl $2, %esi
+DST(	movw %bx, (%edi)	)
+	addl $2, %edi
+	addw %bx, %ax	
+	adcl $0, %eax
+2:
+	movl %ecx, FP(%esp)
+	shrl $5, %ecx
+	jz 2f
+	testl %esi, %esi
+SRC(1:	movl (%esi), %ebx	)
+SRC(	movl 4(%esi), %edx	)
+	adcl %ebx, %eax
+DST(	movl %ebx, (%edi)	)
+	adcl %edx, %eax
+DST(	movl %edx, 4(%edi)	)
+
+SRC(	movl 8(%esi), %ebx	)
+SRC(	movl 12(%esi), %edx	)
+	adcl %ebx, %eax
+DST(	movl %ebx, 8(%edi)	)
+	adcl %edx, %eax
+DST(	movl %edx, 12(%edi)	)
+
+SRC(	movl 16(%esi), %ebx 	)
+SRC(	movl 20(%esi), %edx	)
+	adcl %ebx, %eax
+DST(	movl %ebx, 16(%edi)	)
+	adcl %edx, %eax
+DST(	movl %edx, 20(%edi)	)
+
+SRC(	movl 24(%esi), %ebx	)
+SRC(	movl 28(%esi), %edx	)
+	adcl %ebx, %eax
+DST(	movl %ebx, 24(%edi)	)
+	adcl %edx, %eax
+DST(	movl %edx, 28(%edi)	)
+
+	lea 32(%esi), %esi
+	lea 32(%edi), %edi
+	dec %ecx
+	jne 1b
+	adcl $0, %eax
+2:	movl FP(%esp), %edx
+	movl %edx, %ecx
+	andl $0x1c, %edx
+	je 4f
+	shrl $2, %edx			# This clears CF
+SRC(3:	movl (%esi), %ebx	)
+	adcl %ebx, %eax
+DST(	movl %ebx, (%edi)	)
+	lea 4(%esi), %esi
+	lea 4(%edi), %edi
+	dec %edx
+	jne 3b
+	adcl $0, %eax
+4:	andl $3, %ecx
+	jz 7f
+	cmpl $2, %ecx
+	jb 5f
+SRC(	movw (%esi), %cx	)
+	leal 2(%esi), %esi
+DST(	movw %cx, (%edi)	)
+	leal 2(%edi), %edi
+	je 6f
+	shll $16,%ecx
+SRC(5:	movb (%esi), %cl	)
+DST(	movb %cl, (%edi)	)
+6:	addl %ecx, %eax
+	adcl $0, %eax
+7:
+5000:
+
+# Exception handler:
+.section .fixup, "ax"							
+
+6001:
+	movl ARGBASE+20(%esp), %ebx	# src_err_ptr
+	movl $-EFAULT, (%ebx)
+
+	# zero the complete destination - computing the rest
+	# is too much work 
+	movl ARGBASE+8(%esp), %edi	# dst
+	movl ARGBASE+12(%esp), %ecx	# len
+	xorl %eax,%eax
+	rep ; stosb
+
+	jmp 5000b
+
+6002:
+	movl ARGBASE+24(%esp), %ebx	# dst_err_ptr
+	movl $-EFAULT,(%ebx)
+	jmp 5000b
+
+.previous
+
+	popl %ebx
+	popl %esi
+	popl %edi
+	popl %ecx			# equivalent to addl $4,%esp
+	ret	
+
+#else
+
+/* Version for PentiumII/PPro */
+
+#define ROUND1(x) \
+	SRC(movl x(%esi), %ebx	)	;	\
+	addl %ebx, %eax			;	\
+	DST(movl %ebx, x(%edi)	)	; 
+
+#define ROUND(x) \
+	SRC(movl x(%esi), %ebx	)	;	\
+	adcl %ebx, %eax			;	\
+	DST(movl %ebx, x(%edi)	)	;
+
+#define ARGBASE 12
+		
+csum_partial_copy_generic_i386:
+	pushl %ebx
+	pushl %edi
+	pushl %esi
+	movl ARGBASE+4(%esp),%esi	#src
+	movl ARGBASE+8(%esp),%edi	#dst	
+	movl ARGBASE+12(%esp),%ecx	#len
+	movl ARGBASE+16(%esp),%eax	#sum
+#	movl %ecx, %edx  
+	movl %ecx, %ebx  
+	movl %esi, %edx
+	shrl $6, %ecx     
+	andl $0x3c, %ebx  
+	negl %ebx
+	subl %ebx, %esi  
+	subl %ebx, %edi  
+	lea  -1(%esi),%edx
+	andl $-32,%edx
+	lea 3f(%ebx,%ebx), %ebx
+	testl %esi, %esi 
+	jmp *%ebx
+1:	addl $64,%esi
+	addl $64,%edi 
+	SRC(movb -32(%edx),%bl)	; SRC(movb (%edx),%bl)
+	ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52)	
+	ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36)	
+	ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20)	
+	ROUND (-16) ROUND(-12) ROUND(-8)  ROUND(-4)	
+3:	adcl $0,%eax
+	addl $64, %edx
+	dec %ecx
+	jge 1b
+4:	movl ARGBASE+12(%esp),%edx	#len
+	andl $3, %edx
+	jz 7f
+	cmpl $2, %edx
+	jb 5f
+SRC(	movw (%esi), %dx         )
+	leal 2(%esi), %esi
+DST(	movw %dx, (%edi)         )
+	leal 2(%edi), %edi
+	je 6f
+	shll $16,%edx
+5:
+SRC(	movb (%esi), %dl         )
+DST(	movb %dl, (%edi)         )
+6:	addl %edx, %eax
+	adcl $0, %eax
+7:
+.section .fixup, "ax"
+6001:	movl	ARGBASE+20(%esp), %ebx	# src_err_ptr	
+	movl $-EFAULT, (%ebx)
+	# zero the complete destination (computing the rest is too much work)
+	movl ARGBASE+8(%esp),%edi	# dst
+	movl ARGBASE+12(%esp),%ecx	# len
+	xorl %eax,%eax
+	rep; stosb
+	jmp 7b
+6002:	movl ARGBASE+24(%esp), %ebx	# dst_err_ptr
+	movl $-EFAULT, (%ebx)
+	jmp  7b			
+.previous				
+
+	popl %esi
+	popl %edi
+	popl %ebx
+	ret
+				
+#undef ROUND
+#undef ROUND1		
+		
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/delay.c linux-libre-3.2-gnu/arch/x86/um/delay.c
--- linux-libre-3.1-gnu/arch/x86/um/delay.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/delay.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ * Mostly copied from arch/x86/lib/delay.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/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/param.h>
+
+void __delay(unsigned long loops)
+{
+	asm volatile(
+		"test %0,%0\n"
+		"jz 3f\n"
+		"jmp 1f\n"
+
+		".align 16\n"
+		"1: jmp 2f\n"
+
+		".align 16\n"
+		"2: dec %0\n"
+		" jnz 2b\n"
+		"3: dec %0\n"
+
+		: /* we don't need output */
+		: "a" (loops)
+	);
+}
+EXPORT_SYMBOL(__delay);
+
+inline void __const_udelay(unsigned long xloops)
+{
+	int d0;
+
+	xloops *= 4;
+	asm("mull %%edx"
+		: "=d" (xloops), "=&a" (d0)
+		: "1" (xloops), "0"
+		(loops_per_jiffy * (HZ/4)));
+
+	__delay(++xloops);
+}
+EXPORT_SYMBOL(__const_udelay);
+
+void __udelay(unsigned long usecs)
+{
+	__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
+}
+EXPORT_SYMBOL(__udelay);
+
+void __ndelay(unsigned long nsecs)
+{
+	__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
+}
+EXPORT_SYMBOL(__ndelay);
diff -druN linux-libre-3.1-gnu/arch/x86/um/elfcore.c linux-libre-3.2-gnu/arch/x86/um/elfcore.c
--- linux-libre-3.1-gnu/arch/x86/um/elfcore.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/elfcore.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,83 @@
+#include <linux/elf.h>
+#include <linux/coredump.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+#include <asm/elf.h>
+
+
+Elf32_Half elf_core_extra_phdrs(void)
+{
+	return vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0;
+}
+
+int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
+			       unsigned long limit)
+{
+	if ( vsyscall_ehdr ) {
+		const struct elfhdr *const ehdrp =
+			(struct elfhdr *) vsyscall_ehdr;
+		const struct elf_phdr *const phdrp =
+			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
+		int i;
+		Elf32_Off ofs = 0;
+
+		for (i = 0; i < ehdrp->e_phnum; ++i) {
+			struct elf_phdr phdr = phdrp[i];
+
+			if (phdr.p_type == PT_LOAD) {
+				ofs = phdr.p_offset = offset;
+				offset += phdr.p_filesz;
+			} else {
+				phdr.p_offset += ofs;
+			}
+			phdr.p_paddr = 0; /* match other core phdrs */
+			*size += sizeof(phdr);
+			if (*size > limit
+			    || !dump_write(file, &phdr, sizeof(phdr)))
+				return 0;
+		}
+	}
+	return 1;
+}
+
+int elf_core_write_extra_data(struct file *file, size_t *size,
+			      unsigned long limit)
+{
+	if ( vsyscall_ehdr ) {
+		const struct elfhdr *const ehdrp =
+			(struct elfhdr *) vsyscall_ehdr;
+		const struct elf_phdr *const phdrp =
+			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
+		int i;
+
+		for (i = 0; i < ehdrp->e_phnum; ++i) {
+			if (phdrp[i].p_type == PT_LOAD) {
+				void *addr = (void *) phdrp[i].p_vaddr;
+				size_t filesz = phdrp[i].p_filesz;
+
+				*size += filesz;
+				if (*size > limit
+				    || !dump_write(file, addr, filesz))
+					return 0;
+			}
+		}
+	}
+	return 1;
+}
+
+size_t elf_core_extra_data_size(void)
+{
+	if ( vsyscall_ehdr ) {
+		const struct elfhdr *const ehdrp =
+			(struct elfhdr *)vsyscall_ehdr;
+		const struct elf_phdr *const phdrp =
+			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
+		int i;
+
+		for (i = 0; i < ehdrp->e_phnum; ++i)
+			if (phdrp[i].p_type == PT_LOAD)
+				return (size_t) phdrp[i].p_filesz;
+	}
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/fault.c linux-libre-3.2-gnu/arch/x86/um/fault.c
--- linux-libre-3.1-gnu/arch/x86/um/fault.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/fault.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,28 @@
+/* 
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include "sysdep/ptrace.h"
+
+/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
+struct exception_table_entry
+{
+	unsigned long insn;
+	unsigned long fixup;
+};
+
+const struct exception_table_entry *search_exception_tables(unsigned long add);
+
+/* Compare this to arch/i386/mm/extable.c:fixup_exception() */
+int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
+{
+	const struct exception_table_entry *fixup;
+
+	fixup = search_exception_tables(address);
+	if (fixup != 0) {
+		UPT_IP(regs) = fixup->fixup;
+		return 1;
+	}
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/Kconfig linux-libre-3.2-gnu/arch/x86/um/Kconfig
--- linux-libre-3.1-gnu/arch/x86/um/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,67 @@
+mainmenu "User Mode Linux/$SUBARCH $KERNELVERSION Kernel Configuration"
+
+source "arch/um/Kconfig.common"
+
+menu "UML-specific options"
+
+menu "Host processor type and features"
+
+config CMPXCHG_LOCAL
+	bool
+	default n
+
+config CMPXCHG_DOUBLE
+	bool
+	default n
+
+source "arch/x86/Kconfig.cpu"
+
+endmenu
+
+config UML_X86
+	def_bool y
+	select GENERIC_FIND_FIRST_BIT
+
+config 64BIT
+	bool
+	default SUBARCH = "x86_64"
+
+config X86_32
+	def_bool !64BIT
+	select HAVE_AOUT
+
+config X86_64
+	def_bool 64BIT
+
+config RWSEM_XCHGADD_ALGORITHM
+	def_bool X86_XADD && 64BIT
+
+config RWSEM_GENERIC_SPINLOCK
+	def_bool !RWSEM_XCHGADD_ALGORITHM
+
+config 3_LEVEL_PGTABLES
+	bool "Three-level pagetables (EXPERIMENTAL)" if !64BIT
+	default 64BIT
+	depends on EXPERIMENTAL
+	help
+	Three-level pagetables will let UML have more than 4G of physical
+	memory.  All the memory that can't be mapped directly will be treated
+	as high memory.
+
+	However, this it experimental on 32-bit architectures, so if unsure say
+	N (on x86-64 it's automatically enabled, instead, as it's safe there).
+
+config ARCH_HAS_SC_SIGNALS
+	def_bool !64BIT
+
+config ARCH_REUSE_HOST_VSYSCALL_AREA
+	def_bool !64BIT
+
+config GENERIC_HWEIGHT
+	def_bool y
+
+source "arch/um/Kconfig.um"
+
+endmenu
+
+source "arch/um/Kconfig.rest"
diff -druN linux-libre-3.1-gnu/arch/x86/um/ksyms.c linux-libre-3.2-gnu/arch/x86/um/ksyms.c
--- linux-libre-3.1-gnu/arch/x86/um/ksyms.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/ksyms.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,13 @@
+#include <linux/module.h>
+#include <asm/string.h>
+#include <asm/checksum.h>
+
+#ifndef CONFIG_X86_32
+/*XXX: we need them because they would be exported by x86_64 */
+#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
+EXPORT_SYMBOL(memcpy);
+#else
+EXPORT_SYMBOL(__memcpy);
+#endif
+#endif
+EXPORT_SYMBOL(csum_partial);
diff -druN linux-libre-3.1-gnu/arch/x86/um/ldt.c linux-libre-3.2-gnu/arch/x86/um/ldt.c
--- linux-libre-3.1-gnu/arch/x86/um/ldt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/ldt.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,502 @@
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <asm/unistd.h>
+#include "os.h"
+#include "proc_mm.h"
+#include "skas.h"
+#include "skas_ptrace.h"
+#include "sysdep/tls.h"
+
+extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
+
+static long write_ldt_entry(struct mm_id *mm_idp, int func,
+		     struct user_desc *desc, void **addr, int done)
+{
+	long res;
+
+	if (proc_mm) {
+		/*
+		 * This is a special handling for the case, that the mm to
+		 * modify isn't current->active_mm.
+		 * If this is called directly by modify_ldt,
+		 *     (current->active_mm->context.skas.u == mm_idp)
+		 * will be true. So no call to __switch_mm(mm_idp) is done.
+		 * If this is called in case of init_new_ldt or PTRACE_LDT,
+		 * mm_idp won't belong to current->active_mm, but child->mm.
+		 * So we need to switch child's mm into our userspace, then
+		 * later switch back.
+		 *
+		 * Note: I'm unsure: should interrupts be disabled here?
+		 */
+		if (!current->active_mm || current->active_mm == &init_mm ||
+		    mm_idp != &current->active_mm->context.id)
+			__switch_mm(mm_idp);
+	}
+
+	if (ptrace_ldt) {
+		struct ptrace_ldt ldt_op = (struct ptrace_ldt) {
+			.func = func,
+			.ptr = desc,
+			.bytecount = sizeof(*desc)};
+		u32 cpu;
+		int pid;
+
+		if (!proc_mm)
+			pid = mm_idp->u.pid;
+		else {
+			cpu = get_cpu();
+			pid = userspace_pid[cpu];
+		}
+
+		res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op);
+
+		if (proc_mm)
+			put_cpu();
+	}
+	else {
+		void *stub_addr;
+		res = syscall_stub_data(mm_idp, (unsigned long *)desc,
+					(sizeof(*desc) + sizeof(long) - 1) &
+					    ~(sizeof(long) - 1),
+					addr, &stub_addr);
+		if (!res) {
+			unsigned long args[] = { func,
+						 (unsigned long)stub_addr,
+						 sizeof(*desc),
+						 0, 0, 0 };
+			res = run_syscall_stub(mm_idp, __NR_modify_ldt, args,
+					       0, addr, done);
+		}
+	}
+
+	if (proc_mm) {
+		/*
+		 * This is the second part of special handling, that makes
+		 * PTRACE_LDT possible to implement.
+		 */
+		if (current->active_mm && current->active_mm != &init_mm &&
+		    mm_idp != &current->active_mm->context.id)
+			__switch_mm(&current->active_mm->context.id);
+	}
+
+	return res;
+}
+
+static long read_ldt_from_host(void __user * ptr, unsigned long bytecount)
+{
+	int res, n;
+	struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) {
+			.func = 0,
+			.bytecount = bytecount,
+			.ptr = kmalloc(bytecount, GFP_KERNEL)};
+	u32 cpu;
+
+	if (ptrace_ldt.ptr == NULL)
+		return -ENOMEM;
+
+	/*
+	 * This is called from sys_modify_ldt only, so userspace_pid gives
+	 * us the right number
+	 */
+
+	cpu = get_cpu();
+	res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt);
+	put_cpu();
+	if (res < 0)
+		goto out;
+
+	n = copy_to_user(ptr, ptrace_ldt.ptr, res);
+	if (n != 0)
+		res = -EFAULT;
+
+  out:
+	kfree(ptrace_ldt.ptr);
+
+	return res;
+}
+
+/*
+ * In skas mode, we hold our own ldt data in UML.
+ * Thus, the code implementing sys_modify_ldt_skas
+ * is very similar to (and mostly stolen from) sys_modify_ldt
+ * for arch/i386/kernel/ldt.c
+ * The routines copied and modified in part are:
+ * - read_ldt
+ * - read_default_ldt
+ * - write_ldt
+ * - sys_modify_ldt_skas
+ */
+
+static int read_ldt(void __user * ptr, unsigned long bytecount)
+{
+	int i, err = 0;
+	unsigned long size;
+	uml_ldt_t *ldt = &current->mm->context.arch.ldt;
+
+	if (!ldt->entry_count)
+		goto out;
+	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
+		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
+	err = bytecount;
+
+	if (ptrace_ldt)
+		return read_ldt_from_host(ptr, bytecount);
+
+	mutex_lock(&ldt->lock);
+	if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
+		size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
+		if (size > bytecount)
+			size = bytecount;
+		if (copy_to_user(ptr, ldt->u.entries, size))
+			err = -EFAULT;
+		bytecount -= size;
+		ptr += size;
+	}
+	else {
+		for (i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount;
+		     i++) {
+			size = PAGE_SIZE;
+			if (size > bytecount)
+				size = bytecount;
+			if (copy_to_user(ptr, ldt->u.pages[i], size)) {
+				err = -EFAULT;
+				break;
+			}
+			bytecount -= size;
+			ptr += size;
+		}
+	}
+	mutex_unlock(&ldt->lock);
+
+	if (bytecount == 0 || err == -EFAULT)
+		goto out;
+
+	if (clear_user(ptr, bytecount))
+		err = -EFAULT;
+
+out:
+	return err;
+}
+
+static int read_default_ldt(void __user * ptr, unsigned long bytecount)
+{
+	int err;
+
+	if (bytecount > 5*LDT_ENTRY_SIZE)
+		bytecount = 5*LDT_ENTRY_SIZE;
+
+	err = bytecount;
+	/*
+	 * UML doesn't support lcall7 and lcall27.
+	 * So, we don't really have a default ldt, but emulate
+	 * an empty ldt of common host default ldt size.
+	 */
+	if (clear_user(ptr, bytecount))
+		err = -EFAULT;
+
+	return err;
+}
+
+static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
+{
+	uml_ldt_t *ldt = &current->mm->context.arch.ldt;
+	struct mm_id * mm_idp = &current->mm->context.id;
+	int i, err;
+	struct user_desc ldt_info;
+	struct ldt_entry entry0, *ldt_p;
+	void *addr = NULL;
+
+	err = -EINVAL;
+	if (bytecount != sizeof(ldt_info))
+		goto out;
+	err = -EFAULT;
+	if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
+		goto out;
+
+	err = -EINVAL;
+	if (ldt_info.entry_number >= LDT_ENTRIES)
+		goto out;
+	if (ldt_info.contents == 3) {
+		if (func == 1)
+			goto out;
+		if (ldt_info.seg_not_present == 0)
+			goto out;
+	}
+
+	if (!ptrace_ldt)
+		mutex_lock(&ldt->lock);
+
+	err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
+	if (err)
+		goto out_unlock;
+	else if (ptrace_ldt) {
+		/* With PTRACE_LDT available, this is used as a flag only */
+		ldt->entry_count = 1;
+		goto out;
+	}
+
+	if (ldt_info.entry_number >= ldt->entry_count &&
+	    ldt_info.entry_number >= LDT_DIRECT_ENTRIES) {
+		for (i=ldt->entry_count/LDT_ENTRIES_PER_PAGE;
+		     i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number;
+		     i++) {
+			if (i == 0)
+				memcpy(&entry0, ldt->u.entries,
+				       sizeof(entry0));
+			ldt->u.pages[i] = (struct ldt_entry *)
+				__get_free_page(GFP_KERNEL|__GFP_ZERO);
+			if (!ldt->u.pages[i]) {
+				err = -ENOMEM;
+				/* Undo the change in host */
+				memset(&ldt_info, 0, sizeof(ldt_info));
+				write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1);
+				goto out_unlock;
+			}
+			if (i == 0) {
+				memcpy(ldt->u.pages[0], &entry0,
+				       sizeof(entry0));
+				memcpy(ldt->u.pages[0]+1, ldt->u.entries+1,
+				       sizeof(entry0)*(LDT_DIRECT_ENTRIES-1));
+			}
+			ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE;
+		}
+	}
+	if (ldt->entry_count <= ldt_info.entry_number)
+		ldt->entry_count = ldt_info.entry_number + 1;
+
+	if (ldt->entry_count <= LDT_DIRECT_ENTRIES)
+		ldt_p = ldt->u.entries + ldt_info.entry_number;
+	else
+		ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] +
+			ldt_info.entry_number%LDT_ENTRIES_PER_PAGE;
+
+	if (ldt_info.base_addr == 0 && ldt_info.limit == 0 &&
+	   (func == 1 || LDT_empty(&ldt_info))) {
+		ldt_p->a = 0;
+		ldt_p->b = 0;
+	}
+	else{
+		if (func == 1)
+			ldt_info.useable = 0;
+		ldt_p->a = LDT_entry_a(&ldt_info);
+		ldt_p->b = LDT_entry_b(&ldt_info);
+	}
+	err = 0;
+
+out_unlock:
+	mutex_unlock(&ldt->lock);
+out:
+	return err;
+}
+
+static long do_modify_ldt_skas(int func, void __user *ptr,
+			       unsigned long bytecount)
+{
+	int ret = -ENOSYS;
+
+	switch (func) {
+		case 0:
+			ret = read_ldt(ptr, bytecount);
+			break;
+		case 1:
+		case 0x11:
+			ret = write_ldt(ptr, bytecount, func);
+			break;
+		case 2:
+			ret = read_default_ldt(ptr, bytecount);
+			break;
+	}
+	return ret;
+}
+
+static DEFINE_SPINLOCK(host_ldt_lock);
+static short dummy_list[9] = {0, -1};
+static short * host_ldt_entries = NULL;
+
+static void ldt_get_host_info(void)
+{
+	long ret;
+	struct ldt_entry * ldt;
+	short *tmp;
+	int i, size, k, order;
+
+	spin_lock(&host_ldt_lock);
+
+	if (host_ldt_entries != NULL) {
+		spin_unlock(&host_ldt_lock);
+		return;
+	}
+	host_ldt_entries = dummy_list+1;
+
+	spin_unlock(&host_ldt_lock);
+
+	for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++)
+		;
+
+	ldt = (struct ldt_entry *)
+	      __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
+	if (ldt == NULL) {
+		printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer "
+		       "for host ldt\n");
+		return;
+	}
+
+	ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE);
+	if (ret < 0) {
+		printk(KERN_ERR "ldt_get_host_info: couldn't read host ldt\n");
+		goto out_free;
+	}
+	if (ret == 0) {
+		/* default_ldt is active, simply write an empty entry 0 */
+		host_ldt_entries = dummy_list;
+		goto out_free;
+	}
+
+	for (i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++) {
+		if (ldt[i].a != 0 || ldt[i].b != 0)
+			size++;
+	}
+
+	if (size < ARRAY_SIZE(dummy_list))
+		host_ldt_entries = dummy_list;
+	else {
+		size = (size + 1) * sizeof(dummy_list[0]);
+		tmp = kmalloc(size, GFP_KERNEL);
+		if (tmp == NULL) {
+			printk(KERN_ERR "ldt_get_host_info: couldn't allocate "
+			       "host ldt list\n");
+			goto out_free;
+		}
+		host_ldt_entries = tmp;
+	}
+
+	for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) {
+		if (ldt[i].a != 0 || ldt[i].b != 0)
+			host_ldt_entries[k++] = i;
+	}
+	host_ldt_entries[k] = -1;
+
+out_free:
+	free_pages((unsigned long)ldt, order);
+}
+
+long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
+{
+	struct user_desc desc;
+	short * num_p;
+	int i;
+	long page, err=0;
+	void *addr = NULL;
+	struct proc_mm_op copy;
+
+
+	if (!ptrace_ldt)
+		mutex_init(&new_mm->arch.ldt.lock);
+
+	if (!from_mm) {
+		memset(&desc, 0, sizeof(desc));
+		/*
+		 * We have to initialize a clean ldt.
+		 */
+		if (proc_mm) {
+			/*
+			 * If the new mm was created using proc_mm, host's
+			 * default-ldt currently is assigned, which normally
+			 * contains the call-gates for lcall7 and lcall27.
+			 * To remove these gates, we simply write an empty
+			 * entry as number 0 to the host.
+			 */
+			err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, 1);
+		}
+		else{
+			/*
+			 * Now we try to retrieve info about the ldt, we
+			 * inherited from the host. All ldt-entries found
+			 * will be reset in the following loop
+			 */
+			ldt_get_host_info();
+			for (num_p=host_ldt_entries; *num_p != -1; num_p++) {
+				desc.entry_number = *num_p;
+				err = write_ldt_entry(&new_mm->id, 1, &desc,
+						      &addr, *(num_p + 1) == -1);
+				if (err)
+					break;
+			}
+		}
+		new_mm->arch.ldt.entry_count = 0;
+
+		goto out;
+	}
+
+	if (proc_mm) {
+		/*
+		 * We have a valid from_mm, so we now have to copy the LDT of
+		 * from_mm to new_mm, because using proc_mm an new mm with
+		 * an empty/default LDT was created in new_mm()
+		 */
+		copy = ((struct proc_mm_op) { .op 	= MM_COPY_SEGMENTS,
+					      .u 	=
+					      { .copy_segments =
+							from_mm->id.u.mm_fd } } );
+		i = os_write_file(new_mm->id.u.mm_fd, &copy, sizeof(copy));
+		if (i != sizeof(copy))
+			printk(KERN_ERR "new_mm : /proc/mm copy_segments "
+			       "failed, err = %d\n", -i);
+	}
+
+	if (!ptrace_ldt) {
+		/*
+		 * Our local LDT is used to supply the data for
+		 * modify_ldt(READLDT), if PTRACE_LDT isn't available,
+		 * i.e., we have to use the stub for modify_ldt, which
+		 * can't handle the big read buffer of up to 64kB.
+		 */
+		mutex_lock(&from_mm->arch.ldt.lock);
+		if (from_mm->arch.ldt.entry_count <= LDT_DIRECT_ENTRIES)
+			memcpy(new_mm->arch.ldt.u.entries, from_mm->arch.ldt.u.entries,
+			       sizeof(new_mm->arch.ldt.u.entries));
+		else {
+			i = from_mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
+			while (i-->0) {
+				page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
+				if (!page) {
+					err = -ENOMEM;
+					break;
+				}
+				new_mm->arch.ldt.u.pages[i] =
+					(struct ldt_entry *) page;
+				memcpy(new_mm->arch.ldt.u.pages[i],
+				       from_mm->arch.ldt.u.pages[i], PAGE_SIZE);
+			}
+		}
+		new_mm->arch.ldt.entry_count = from_mm->arch.ldt.entry_count;
+		mutex_unlock(&from_mm->arch.ldt.lock);
+	}
+
+    out:
+	return err;
+}
+
+
+void free_ldt(struct mm_context *mm)
+{
+	int i;
+
+	if (!ptrace_ldt && mm->arch.ldt.entry_count > LDT_DIRECT_ENTRIES) {
+		i = mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
+		while (i-- > 0)
+			free_page((long) mm->arch.ldt.u.pages[i]);
+	}
+	mm->arch.ldt.entry_count = 0;
+}
+
+int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
+{
+	return do_modify_ldt_skas(func, ptr, bytecount);
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/Makefile linux-libre-3.2-gnu/arch/x86/um/Makefile
--- linux-libre-3.1-gnu/arch/x86/um/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+#
+
+ifeq ($(CONFIG_X86_32),y)
+	BITS := 32
+else
+	BITS := 64
+endif
+
+obj-y = bug.o bugs_$(BITS).o delay.o fault.o ksyms.o ldt.o \
+	ptrace_$(BITS).o ptrace_user.o setjmp_$(BITS).o signal.o \
+	stub_$(BITS).o stub_segv.o syscalls_$(BITS).o \
+	sys_call_table_$(BITS).o sysrq_$(BITS).o tls_$(BITS).o \
+	mem_$(BITS).o subarch.o os-$(OS)/
+
+ifeq ($(CONFIG_X86_32),y)
+
+obj-y += checksum_32.o
+obj-$(CONFIG_BINFMT_ELF) += elfcore.o
+
+subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o
+subarch-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += ../lib/rwsem.o
+subarch-$(CONFIG_HIGHMEM) += ../mm/highmem_32.o
+
+else
+
+obj-y += vdso/
+
+subarch-y = ../lib/csum-partial_64.o ../lib/memcpy_64.o ../lib/thunk_64.o \
+		../lib/rwsem.o
+
+endif
+
+subarch-$(CONFIG_MODULES) += ../kernel/module.o
+
+USER_OBJS := bugs_$(BITS).o ptrace_user.o fault.o
+
+extra-y += user-offsets.s
+$(obj)/user-offsets.s: c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS)
+
+UNPROFILE_OBJS := stub_segv.o
+CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
+
+include arch/um/scripts/Makefile.rules
diff -druN linux-libre-3.1-gnu/arch/x86/um/mem_32.c linux-libre-3.2-gnu/arch/x86/um/mem_32.c
--- linux-libre-3.1-gnu/arch/x86/um/mem_32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/mem_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ *
+ * This program is free software; you can 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 <asm/page.h>
+#include <asm/mman.h>
+
+static struct vm_area_struct gate_vma;
+
+static int __init gate_vma_init(void)
+{
+	if (!FIXADDR_USER_START)
+		return 0;
+
+	gate_vma.vm_mm = NULL;
+	gate_vma.vm_start = FIXADDR_USER_START;
+	gate_vma.vm_end = FIXADDR_USER_END;
+	gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
+	gate_vma.vm_page_prot = __P101;
+
+	/*
+	 * Make sure the vDSO gets into every core dump.
+	 * Dumping its contents makes post-mortem fully interpretable later
+	 * without matching up the same kernel and hardware config to see
+	 * what PC values meant.
+	 */
+	gate_vma.vm_flags |= VM_ALWAYSDUMP;
+
+	return 0;
+}
+__initcall(gate_vma_init);
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+	return FIXADDR_USER_START ? &gate_vma : NULL;
+}
+
+int in_gate_area_no_mm(unsigned long addr)
+{
+	if (!FIXADDR_USER_START)
+		return 0;
+
+	if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END))
+		return 1;
+
+	return 0;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
+{
+	struct vm_area_struct *vma = get_gate_vma(mm);
+
+	if (!vma)
+		return 0;
+
+	return (addr >= vma->vm_start) && (addr < vma->vm_end);
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/mem_64.c linux-libre-3.2-gnu/arch/x86/um/mem_64.c
--- linux-libre-3.1-gnu/arch/x86/um/mem_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/mem_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+#include "linux/mm.h"
+#include "asm/page.h"
+#include "asm/mman.h"
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	if (vma->vm_mm && vma->vm_start == um_vdso_addr)
+		return "[vdso]";
+
+	return NULL;
+}
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+	return NULL;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
+{
+	return 0;
+}
+
+int in_gate_area_no_mm(unsigned long addr)
+{
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/os-Linux/Makefile linux-libre-3.2-gnu/arch/x86/um/os-Linux/Makefile
--- linux-libre-3.1-gnu/arch/x86/um/os-Linux/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/os-Linux/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,13 @@
+#
+# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+# Licensed under the GPL
+#
+
+obj-y = registers.o task_size.o mcontext.o
+
+obj-$(CONFIG_X86_32) += tls.o
+obj-$(CONFIG_64BIT) += prctl.o
+
+USER_OBJS := $(obj-y)
+
+include arch/um/scripts/Makefile.rules
diff -druN linux-libre-3.1-gnu/arch/x86/um/os-Linux/mcontext.c linux-libre-3.2-gnu/arch/x86/um/os-Linux/mcontext.c
--- linux-libre-3.1-gnu/arch/x86/um/os-Linux/mcontext.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/os-Linux/mcontext.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,31 @@
+#include <sys/ucontext.h>
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
+#include <sysdep/ptrace.h>
+
+void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc)
+{
+#ifdef __i386__
+#define COPY2(X,Y) regs->gp[X] = mc->gregs[REG_##Y]
+#define COPY(X) regs->gp[X] = mc->gregs[REG_##X]
+#define COPY_SEG(X) regs->gp[X] = mc->gregs[REG_##X] & 0xffff;
+#define COPY_SEG_CPL3(X) regs->gp[X] = (mc->gregs[REG_##X] & 0xffff) | 3;
+	COPY_SEG(GS); COPY_SEG(FS); COPY_SEG(ES); COPY_SEG(DS);
+	COPY(EDI); COPY(ESI); COPY(EBP);
+	COPY2(UESP, ESP); /* sic */
+	COPY(EBX); COPY(EDX); COPY(ECX); COPY(EAX);
+	COPY(EIP); COPY_SEG_CPL3(CS); COPY(EFL); COPY_SEG_CPL3(SS);
+#else
+#define COPY2(X,Y) regs->gp[X/sizeof(unsigned long)] = mc->gregs[REG_##Y]
+#define COPY(X) regs->gp[X/sizeof(unsigned long)] = mc->gregs[REG_##X]
+	COPY(R8); COPY(R9); COPY(R10); COPY(R11);
+	COPY(R12); COPY(R13); COPY(R14); COPY(R15);
+	COPY(RDI); COPY(RSI); COPY(RBP); COPY(RBX);
+	COPY(RDX); COPY(RAX); COPY(RCX); COPY(RSP);
+	COPY(RIP);
+	COPY2(EFLAGS, EFL);
+	COPY2(CS, CSGSFS);
+	regs->gp[CS / sizeof(unsigned long)] &= 0xffff;
+	regs->gp[CS / sizeof(unsigned long)] |= 3;
+#endif
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/os-Linux/prctl.c linux-libre-3.2-gnu/arch/x86/um/os-Linux/prctl.c
--- linux-libre-3.1-gnu/arch/x86/um/os-Linux/prctl.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/os-Linux/prctl.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2007 Jeff Dike (jdike@{addtoit.com,linux.intel.com})
+ * Licensed under the GPL
+ */
+
+#include <sys/ptrace.h>
+#include <linux/ptrace.h>
+
+int os_arch_prctl(int pid, int code, unsigned long *addr)
+{
+        return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) addr, code);
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/os-Linux/registers.c linux-libre-3.2-gnu/arch/x86/um/os-Linux/registers.c
--- linux-libre-3.1-gnu/arch/x86/um/os-Linux/registers.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/os-Linux/registers.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2004 PathScale, Inc
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include <errno.h>
+#include <sys/ptrace.h>
+#ifdef __i386__
+#include <sys/user.h>
+#endif
+#include "longjmp.h"
+#include "sysdep/ptrace_user.h"
+
+int save_fp_registers(int pid, unsigned long *fp_regs)
+{
+	if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
+		return -errno;
+	return 0;
+}
+
+int restore_fp_registers(int pid, unsigned long *fp_regs)
+{
+	if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
+		return -errno;
+	return 0;
+}
+
+#ifdef __i386__
+int have_fpx_regs = 1;
+int save_fpx_registers(int pid, unsigned long *fp_regs)
+{
+	if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
+		return -errno;
+	return 0;
+}
+
+int restore_fpx_registers(int pid, unsigned long *fp_regs)
+{
+	if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0)
+		return -errno;
+	return 0;
+}
+
+int get_fp_registers(int pid, unsigned long *regs)
+{
+	if (have_fpx_regs)
+		return save_fpx_registers(pid, regs);
+	else
+		return save_fp_registers(pid, regs);
+}
+
+int put_fp_registers(int pid, unsigned long *regs)
+{
+	if (have_fpx_regs)
+		return restore_fpx_registers(pid, regs);
+	else
+		return restore_fp_registers(pid, regs);
+}
+
+void arch_init_registers(int pid)
+{
+	struct user_fpxregs_struct fpx_regs;
+	int err;
+
+	err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs);
+	if (!err)
+		return;
+
+	if (errno != EIO)
+		panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
+		      errno);
+
+	have_fpx_regs = 0;
+}
+#else
+
+int get_fp_registers(int pid, unsigned long *regs)
+{
+	return save_fp_registers(pid, regs);
+}
+
+int put_fp_registers(int pid, unsigned long *regs)
+{
+	return restore_fp_registers(pid, regs);
+}
+
+#endif
+
+unsigned long get_thread_reg(int reg, jmp_buf *buf)
+{
+	switch (reg) {
+#ifdef __i386__
+	case HOST_IP:
+		return buf[0]->__eip;
+	case HOST_SP:
+		return buf[0]->__esp;
+	case HOST_BP:
+		return buf[0]->__ebp;
+#else
+	case HOST_IP:
+		return buf[0]->__rip;
+	case HOST_SP:
+		return buf[0]->__rsp;
+	case HOST_BP:
+		return buf[0]->__rbp;
+#endif
+	default:
+		printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
+		       reg);
+		return 0;
+	}
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/os-Linux/task_size.c linux-libre-3.2-gnu/arch/x86/um/os-Linux/task_size.c
--- linux-libre-3.1-gnu/arch/x86/um/os-Linux/task_size.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/os-Linux/task_size.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,150 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include "longjmp.h"
+
+#ifdef __i386__
+
+static jmp_buf buf;
+
+static void segfault(int sig)
+{
+	longjmp(buf, 1);
+}
+
+static int page_ok(unsigned long page)
+{
+	unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT);
+	unsigned long n = ~0UL;
+	void *mapped = NULL;
+	int ok = 0;
+
+	/*
+	 * First see if the page is readable.  If it is, it may still
+	 * be a VDSO, so we go on to see if it's writable.  If not
+	 * then try mapping memory there.  If that fails, then we're
+	 * still in the kernel area.  As a sanity check, we'll fail if
+	 * the mmap succeeds, but gives us an address different from
+	 * what we wanted.
+	 */
+	if (setjmp(buf) == 0)
+		n = *address;
+	else {
+		mapped = mmap(address, UM_KERN_PAGE_SIZE,
+			      PROT_READ | PROT_WRITE,
+			      MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+		if (mapped == MAP_FAILED)
+			return 0;
+		if (mapped != address)
+			goto out;
+	}
+
+	/*
+	 * Now, is it writeable?  If so, then we're in user address
+	 * space.  If not, then try mprotecting it and try the write
+	 * again.
+	 */
+	if (setjmp(buf) == 0) {
+		*address = n;
+		ok = 1;
+		goto out;
+	} else if (mprotect(address, UM_KERN_PAGE_SIZE,
+			    PROT_READ | PROT_WRITE) != 0)
+		goto out;
+
+	if (setjmp(buf) == 0) {
+		*address = n;
+		ok = 1;
+	}
+
+ out:
+	if (mapped != NULL)
+		munmap(mapped, UM_KERN_PAGE_SIZE);
+	return ok;
+}
+
+unsigned long os_get_top_address(void)
+{
+	struct sigaction sa, old;
+	unsigned long bottom = 0;
+	/*
+	 * A 32-bit UML on a 64-bit host gets confused about the VDSO at
+	 * 0xffffe000.  It is mapped, is readable, can be reprotected writeable
+	 * and written.  However, exec discovers later that it can't be
+	 * unmapped.  So, just set the highest address to be checked to just
+	 * below it.  This might waste some address space on 4G/4G 32-bit
+	 * hosts, but shouldn't hurt otherwise.
+	 */
+	unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT;
+	unsigned long test, original;
+
+	printf("Locating the bottom of the address space ... ");
+	fflush(stdout);
+
+	/*
+	 * We're going to be longjmping out of the signal handler, so
+	 * SA_DEFER needs to be set.
+	 */
+	sa.sa_handler = segfault;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = SA_NODEFER;
+	if (sigaction(SIGSEGV, &sa, &old)) {
+		perror("os_get_top_address");
+		exit(1);
+	}
+
+	/* Manually scan the address space, bottom-up, until we find
+	 * the first valid page (or run out of them).
+	 */
+	for (bottom = 0; bottom < top; bottom++) {
+		if (page_ok(bottom))
+			break;
+	}
+
+	/* If we've got this far, we ran out of pages. */
+	if (bottom == top) {
+		fprintf(stderr, "Unable to determine bottom of address "
+			"space.\n");
+		exit(1);
+	}
+
+	printf("0x%x\n", bottom << UM_KERN_PAGE_SHIFT);
+	printf("Locating the top of the address space ... ");
+	fflush(stdout);
+
+	original = bottom;
+
+	/* This could happen with a 4G/4G split */
+	if (page_ok(top))
+		goto out;
+
+	do {
+		test = bottom + (top - bottom) / 2;
+		if (page_ok(test))
+			bottom = test;
+		else
+			top = test;
+	} while (top - bottom > 1);
+
+out:
+	/* Restore the old SIGSEGV handling */
+	if (sigaction(SIGSEGV, &old, NULL)) {
+		perror("os_get_top_address");
+		exit(1);
+	}
+	top <<= UM_KERN_PAGE_SHIFT;
+	printf("0x%x\n", top);
+
+	return top;
+}
+
+#else
+
+unsigned long os_get_top_address(void)
+{
+	/* The old value of CONFIG_TOP_ADDR */
+	return 0x7fc0000000;
+}
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/os-Linux/tls.c linux-libre-3.2-gnu/arch/x86/um/os-Linux/tls.c
--- linux-libre-3.1-gnu/arch/x86/um/os-Linux/tls.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/os-Linux/tls.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,67 @@
+#include <errno.h>
+#include <linux/unistd.h>
+
+#include <sys/ptrace.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#include "sysdep/tls.h"
+
+#ifndef PTRACE_GET_THREAD_AREA
+#define PTRACE_GET_THREAD_AREA 25
+#endif
+
+#ifndef PTRACE_SET_THREAD_AREA
+#define PTRACE_SET_THREAD_AREA 26
+#endif
+
+/* Checks whether host supports TLS, and sets *tls_min according to the value
+ * valid on the host.
+ * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */
+void check_host_supports_tls(int *supports_tls, int *tls_min)
+{
+	/* Values for x86 and x86_64.*/
+	int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(val); i++) {
+		user_desc_t info;
+		info.entry_number = val[i];
+
+		if (syscall(__NR_get_thread_area, &info) == 0) {
+			*tls_min = val[i];
+			*supports_tls = 1;
+			return;
+		} else {
+			if (errno == EINVAL)
+				continue;
+			else if (errno == ENOSYS)
+				*supports_tls = 0;
+				return;
+		}
+	}
+
+	*supports_tls = 0;
+}
+
+int os_set_thread_area(user_desc_t *info, int pid)
+{
+	int ret;
+
+	ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number,
+		     (unsigned long) info);
+	if (ret < 0)
+		ret = -errno;
+	return ret;
+}
+
+int os_get_thread_area(user_desc_t *info, int pid)
+{
+	int ret;
+
+	ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number,
+		     (unsigned long) info);
+	if (ret < 0)
+		ret = -errno;
+	return ret;
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/ptrace_32.c linux-libre-3.2-gnu/arch/x86/um/ptrace_32.c
--- linux-libre-3.1-gnu/arch/x86/um/ptrace_32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/ptrace_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/mm.h"
+#include "linux/sched.h"
+#include "asm/uaccess.h"
+#include "skas.h"
+
+extern int arch_switch_tls(struct task_struct *to);
+
+void arch_switch_to(struct task_struct *to)
+{
+	int err = arch_switch_tls(to);
+	if (!err)
+		return;
+
+	if (err != -EINVAL)
+		printk(KERN_WARNING "arch_switch_tls failed, errno %d, "
+		       "not EINVAL\n", -err);
+	else
+		printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n");
+}
+
+int is_syscall(unsigned long addr)
+{
+	unsigned short instr;
+	int n;
+
+	n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
+	if (n) {
+		/* access_process_vm() grants access to vsyscall and stub,
+		 * while copy_from_user doesn't. Maybe access_process_vm is
+		 * slow, but that doesn't matter, since it will be called only
+		 * in case of singlestepping, if copy_from_user failed.
+		 */
+		n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
+		if (n != sizeof(instr)) {
+			printk(KERN_ERR "is_syscall : failed to read "
+			       "instruction from 0x%lx\n", addr);
+			return 1;
+		}
+	}
+	/* int 0x80 or sysenter */
+	return (instr == 0x80cd) || (instr == 0x340f);
+}
+
+/* determines which flags the user has access to. */
+/* 1 = access 0 = no access */
+#define FLAG_MASK 0x00044dd5
+
+static const int reg_offsets[] = {
+	[EBX] = HOST_BX,
+	[ECX] = HOST_CX,
+	[EDX] = HOST_DX,
+	[ESI] = HOST_SI,
+	[EDI] = HOST_DI,
+	[EBP] = HOST_BP,
+	[EAX] = HOST_AX,
+	[DS] = HOST_DS,
+	[ES] = HOST_ES,
+	[FS] = HOST_FS,
+	[GS] = HOST_GS,
+	[EIP] = HOST_IP,
+	[CS] = HOST_CS,
+	[EFL] = HOST_EFLAGS,
+	[UESP] = HOST_SP,
+	[SS] = HOST_SS,
+};
+
+int putreg(struct task_struct *child, int regno, unsigned long value)
+{
+	regno >>= 2;
+	switch (regno) {
+	case EBX:
+	case ECX:
+	case EDX:
+	case ESI:
+	case EDI:
+	case EBP:
+	case EAX:
+	case EIP:
+	case UESP:
+		break;
+	case FS:
+		if (value && (value & 3) != 3)
+			return -EIO;
+		break;
+	case GS:
+		if (value && (value & 3) != 3)
+			return -EIO;
+		break;
+	case DS:
+	case ES:
+		if (value && (value & 3) != 3)
+			return -EIO;
+		value &= 0xffff;
+		break;
+	case SS:
+	case CS:
+		if ((value & 3) != 3)
+			return -EIO;
+		value &= 0xffff;
+		break;
+	case EFL:
+		value &= FLAG_MASK;
+		child->thread.regs.regs.gp[HOST_EFLAGS] |= value;
+		return 0;
+	case ORIG_EAX:
+		child->thread.regs.regs.syscall = value;
+		return 0;
+	default :
+		panic("Bad register in putreg() : %d\n", regno);
+	}
+	child->thread.regs.regs.gp[reg_offsets[regno]] = value;
+	return 0;
+}
+
+int poke_user(struct task_struct *child, long addr, long data)
+{
+	if ((addr & 3) || addr < 0)
+		return -EIO;
+
+	if (addr < MAX_REG_OFFSET)
+		return putreg(child, addr, data);
+	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
+		 (addr <= offsetof(struct user, u_debugreg[7]))) {
+		addr -= offsetof(struct user, u_debugreg[0]);
+		addr = addr >> 2;
+		if ((addr == 4) || (addr == 5))
+			return -EIO;
+		child->thread.arch.debugregs[addr] = data;
+		return 0;
+	}
+	return -EIO;
+}
+
+unsigned long getreg(struct task_struct *child, int regno)
+{
+	unsigned long mask = ~0UL;
+
+	regno >>= 2;
+	switch (regno) {
+	case ORIG_EAX:
+		return child->thread.regs.regs.syscall;
+	case FS:
+	case GS:
+	case DS:
+	case ES:
+	case SS:
+	case CS:
+		mask = 0xffff;
+		break;
+	case EIP:
+	case UESP:
+	case EAX:
+	case EBX:
+	case ECX:
+	case EDX:
+	case ESI:
+	case EDI:
+	case EBP:
+	case EFL:
+		break;
+	default:
+		panic("Bad register in getreg() : %d\n", regno);
+	}
+	return mask & child->thread.regs.regs.gp[reg_offsets[regno]];
+}
+
+/* read the word at location addr in the USER area. */
+int peek_user(struct task_struct *child, long addr, long data)
+{
+	unsigned long tmp;
+
+	if ((addr & 3) || addr < 0)
+		return -EIO;
+
+	tmp = 0;  /* Default return condition */
+	if (addr < MAX_REG_OFFSET) {
+		tmp = getreg(child, addr);
+	}
+	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
+		 (addr <= offsetof(struct user, u_debugreg[7]))) {
+		addr -= offsetof(struct user, u_debugreg[0]);
+		addr = addr >> 2;
+		tmp = child->thread.arch.debugregs[addr];
+	}
+	return put_user(tmp, (unsigned long __user *) data);
+}
+
+static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
+{
+	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
+	struct user_i387_struct fpregs;
+
+	err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
+	if (err)
+		return err;
+
+	n = copy_to_user(buf, &fpregs, sizeof(fpregs));
+	if(n > 0)
+		return -EFAULT;
+
+	return n;
+}
+
+static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
+{
+	int n, cpu = ((struct thread_info *) child->stack)->cpu;
+	struct user_i387_struct fpregs;
+
+	n = copy_from_user(&fpregs, buf, sizeof(fpregs));
+	if (n > 0)
+		return -EFAULT;
+
+	return restore_fp_registers(userspace_pid[cpu],
+				    (unsigned long *) &fpregs);
+}
+
+static int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
+{
+	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
+	struct user_fxsr_struct fpregs;
+
+	err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
+	if (err)
+		return err;
+
+	n = copy_to_user(buf, &fpregs, sizeof(fpregs));
+	if(n > 0)
+		return -EFAULT;
+
+	return n;
+}
+
+static int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
+{
+	int n, cpu = ((struct thread_info *) child->stack)->cpu;
+	struct user_fxsr_struct fpregs;
+
+	n = copy_from_user(&fpregs, buf, sizeof(fpregs));
+	if (n > 0)
+		return -EFAULT;
+
+	return restore_fpx_registers(userspace_pid[cpu],
+				     (unsigned long *) &fpregs);
+}
+
+long subarch_ptrace(struct task_struct *child, long request,
+		    unsigned long addr, unsigned long data)
+{
+	int ret = -EIO;
+	void __user *datap = (void __user *) data;
+	switch (request) {
+	case PTRACE_GETFPREGS: /* Get the child FPU state. */
+		ret = get_fpregs(datap, child);
+		break;
+	case PTRACE_SETFPREGS: /* Set the child FPU state. */
+		ret = set_fpregs(datap, child);
+		break;
+	case PTRACE_GETFPXREGS: /* Get the child FPU state. */
+		ret = get_fpxregs(datap, child);
+		break;
+	case PTRACE_SETFPXREGS: /* Set the child FPU state. */
+		ret = set_fpxregs(datap, child);
+		break;
+	default:
+		ret = -EIO;
+	}
+	return ret;
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/ptrace_64.c linux-libre-3.2-gnu/arch/x86/um/ptrace_64.c
--- linux-libre-3.1-gnu/arch/x86/um/ptrace_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/ptrace_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ *
+ * Licensed under the GPL
+ */
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+/*
+ * determines which flags the user has access to.
+ * 1 = access 0 = no access
+ */
+#define FLAG_MASK 0x44dd5UL
+
+static const int reg_offsets[] =
+{
+	[R8 >> 3] = HOST_R8,
+	[R9 >> 3] = HOST_R9,
+	[R10 >> 3] = HOST_R10,
+	[R11 >> 3] = HOST_R11,
+	[R12 >> 3] = HOST_R12,
+	[R13 >> 3] = HOST_R13,
+	[R14 >> 3] = HOST_R14,
+	[R15 >> 3] = HOST_R15,
+	[RIP >> 3] = HOST_IP,
+	[RSP >> 3] = HOST_SP,
+	[RAX >> 3] = HOST_AX,
+	[RBX >> 3] = HOST_BX,
+	[RCX >> 3] = HOST_CX,
+	[RDX >> 3] = HOST_DX,
+	[RSI >> 3] = HOST_SI,
+	[RDI >> 3] = HOST_DI,
+	[RBP >> 3] = HOST_BP,
+	[CS >> 3] = HOST_CS,
+	[SS >> 3] = HOST_SS,
+	[FS_BASE >> 3] = HOST_FS_BASE,
+	[GS_BASE >> 3] = HOST_GS_BASE,
+	[DS >> 3] = HOST_DS,
+	[ES >> 3] = HOST_ES,
+	[FS >> 3] = HOST_FS,
+	[GS >> 3] = HOST_GS,
+	[EFLAGS >> 3] = HOST_EFLAGS,
+	[ORIG_RAX >> 3] = HOST_ORIG_AX,
+};
+
+int putreg(struct task_struct *child, int regno, unsigned long value)
+{
+#ifdef TIF_IA32
+	/*
+	 * Some code in the 64bit emulation may not be 64bit clean.
+	 * Don't take any chances.
+	 */
+	if (test_tsk_thread_flag(child, TIF_IA32))
+		value &= 0xffffffff;
+#endif
+	switch (regno) {
+	case R8:
+	case R9:
+	case R10:
+	case R11:
+	case R12:
+	case R13:
+	case R14:
+	case R15:
+	case RIP:
+	case RSP:
+	case RAX:
+	case RBX:
+	case RCX:
+	case RDX:
+	case RSI:
+	case RDI:
+	case RBP:
+	case ORIG_RAX:
+		break;
+
+	case FS:
+	case GS:
+	case DS:
+	case ES:
+	case SS:
+	case CS:
+		if (value && (value & 3) != 3)
+			return -EIO;
+		value &= 0xffff;
+		break;
+
+	case FS_BASE:
+	case GS_BASE:
+		if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
+			return -EIO;
+		break;
+
+	case EFLAGS:
+		value &= FLAG_MASK;
+		child->thread.regs.regs.gp[HOST_EFLAGS] |= value;
+		return 0;
+
+	default:
+		panic("Bad register in putreg(): %d\n", regno);
+	}
+
+	child->thread.regs.regs.gp[reg_offsets[regno >> 3]] = value;
+	return 0;
+}
+
+int poke_user(struct task_struct *child, long addr, long data)
+{
+	if ((addr & 3) || addr < 0)
+		return -EIO;
+
+	if (addr < MAX_REG_OFFSET)
+		return putreg(child, addr, data);
+	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
+		(addr <= offsetof(struct user, u_debugreg[7]))) {
+		addr -= offsetof(struct user, u_debugreg[0]);
+		addr = addr >> 2;
+		if ((addr == 4) || (addr == 5))
+			return -EIO;
+		child->thread.arch.debugregs[addr] = data;
+		return 0;
+	}
+	return -EIO;
+}
+
+unsigned long getreg(struct task_struct *child, int regno)
+{
+	unsigned long mask = ~0UL;
+#ifdef TIF_IA32
+	if (test_tsk_thread_flag(child, TIF_IA32))
+		mask = 0xffffffff;
+#endif
+	switch (regno) {
+	case R8:
+	case R9:
+	case R10:
+	case R11:
+	case R12:
+	case R13:
+	case R14:
+	case R15:
+	case RIP:
+	case RSP:
+	case RAX:
+	case RBX:
+	case RCX:
+	case RDX:
+	case RSI:
+	case RDI:
+	case RBP:
+	case ORIG_RAX:
+	case EFLAGS:
+	case FS_BASE:
+	case GS_BASE:
+		break;
+	case FS:
+	case GS:
+	case DS:
+	case ES:
+	case SS:
+	case CS:
+		mask = 0xffff;
+		break;
+	default:
+		panic("Bad register in getreg: %d\n", regno);
+	}
+	return mask & child->thread.regs.regs.gp[reg_offsets[regno >> 3]];
+}
+
+int peek_user(struct task_struct *child, long addr, long data)
+{
+	/* read the word at location addr in the USER area. */
+	unsigned long tmp;
+
+	if ((addr & 3) || addr < 0)
+		return -EIO;
+
+	tmp = 0;  /* Default return condition */
+	if (addr < MAX_REG_OFFSET)
+		tmp = getreg(child, addr);
+	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
+		(addr <= offsetof(struct user, u_debugreg[7]))) {
+		addr -= offsetof(struct user, u_debugreg[0]);
+		addr = addr >> 2;
+		tmp = child->thread.arch.debugregs[addr];
+	}
+	return put_user(tmp, (unsigned long *) data);
+}
+
+/* XXX Mostly copied from sys-i386 */
+int is_syscall(unsigned long addr)
+{
+	unsigned short instr;
+	int n;
+
+	n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
+	if (n) {
+		/*
+		 * access_process_vm() grants access to vsyscall and stub,
+		 * while copy_from_user doesn't. Maybe access_process_vm is
+		 * slow, but that doesn't matter, since it will be called only
+		 * in case of singlestepping, if copy_from_user failed.
+		 */
+		n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
+		if (n != sizeof(instr)) {
+			printk("is_syscall : failed to read instruction from "
+			       "0x%lx\n", addr);
+			return 1;
+		}
+	}
+	/* sysenter */
+	return instr == 0x050f;
+}
+
+static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
+{
+	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
+	long fpregs[HOST_FP_SIZE];
+
+	BUG_ON(sizeof(*buf) != sizeof(fpregs));
+	err = save_fp_registers(userspace_pid[cpu], fpregs);
+	if (err)
+		return err;
+
+	n = copy_to_user(buf, fpregs, sizeof(fpregs));
+	if (n > 0)
+		return -EFAULT;
+
+	return n;
+}
+
+static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
+{
+	int n, cpu = ((struct thread_info *) child->stack)->cpu;
+	long fpregs[HOST_FP_SIZE];
+
+	BUG_ON(sizeof(*buf) != sizeof(fpregs));
+	n = copy_from_user(fpregs, buf, sizeof(fpregs));
+	if (n > 0)
+		return -EFAULT;
+
+	return restore_fp_registers(userspace_pid[cpu], fpregs);
+}
+
+long subarch_ptrace(struct task_struct *child, long request,
+		    unsigned long addr, unsigned long data)
+{
+	int ret = -EIO;
+	void __user *datap = (void __user *) data;
+
+	switch (request) {
+	case PTRACE_GETFPREGS: /* Get the child FPU state. */
+		ret = get_fpregs(datap, child);
+		break;
+	case PTRACE_SETFPREGS: /* Set the child FPU state. */
+		ret = set_fpregs(datap, child);
+		break;
+	case PTRACE_ARCH_PRCTL:
+		/* XXX Calls ptrace on the host - needs some SMP thinking */
+		ret = arch_prctl(child, data, (void __user *) addr);
+		break;
+	}
+
+	return ret;
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/ptrace_user.c linux-libre-3.2-gnu/arch/x86/um/ptrace_user.c
--- linux-libre-3.1-gnu/arch/x86/um/ptrace_user.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/ptrace_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include <errno.h>
+#include "ptrace_user.h"
+
+int ptrace_getregs(long pid, unsigned long *regs_out)
+{
+	if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
+		return -errno;
+	return 0;
+}
+
+int ptrace_setregs(long pid, unsigned long *regs)
+{
+	if (ptrace(PTRACE_SETREGS, pid, 0, regs) < 0)
+		return -errno;
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/setjmp_32.S linux-libre-3.2-gnu/arch/x86/um/setjmp_32.S
--- linux-libre-3.1-gnu/arch/x86/um/setjmp_32.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/setjmp_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,58 @@
+#
+# arch/i386/setjmp.S
+#
+# setjmp/longjmp for the i386 architecture
+#
+
+#
+# The jmp_buf is assumed to contain the following, in order:
+#	%ebx
+#	%esp
+#	%ebp
+#	%esi
+#	%edi
+#	<return address>
+#
+
+	.text
+	.align 4
+	.globl setjmp
+	.type setjmp, @function
+setjmp:
+#ifdef _REGPARM
+	movl %eax,%edx
+#else
+	movl 4(%esp),%edx
+#endif
+	popl %ecx			# Return address, and adjust the stack
+	xorl %eax,%eax			# Return value
+	movl %ebx,(%edx)
+	movl %esp,4(%edx)		# Post-return %esp!
+	pushl %ecx			# Make the call/return stack happy
+	movl %ebp,8(%edx)
+	movl %esi,12(%edx)
+	movl %edi,16(%edx)
+	movl %ecx,20(%edx)		# Return address
+	ret
+
+	.size setjmp,.-setjmp
+
+	.text
+	.align 4
+	.globl longjmp
+	.type longjmp, @function
+longjmp:
+#ifdef _REGPARM
+	xchgl %eax,%edx
+#else
+	movl 4(%esp),%edx		# jmp_ptr address
+	movl 8(%esp),%eax		# Return value
+#endif
+	movl (%edx),%ebx
+	movl 4(%edx),%esp
+	movl 8(%edx),%ebp
+	movl 12(%edx),%esi
+	movl 16(%edx),%edi
+	jmp *20(%edx)
+
+	.size longjmp,.-longjmp
diff -druN linux-libre-3.1-gnu/arch/x86/um/setjmp_64.S linux-libre-3.2-gnu/arch/x86/um/setjmp_64.S
--- linux-libre-3.1-gnu/arch/x86/um/setjmp_64.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/setjmp_64.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,54 @@
+#
+# arch/x86_64/setjmp.S
+#
+# setjmp/longjmp for the x86-64 architecture
+#
+
+#
+# The jmp_buf is assumed to contain the following, in order:
+#	%rbx
+#	%rsp (post-return)
+#	%rbp
+#	%r12
+#	%r13
+#	%r14
+#	%r15
+#	<return address>
+#
+
+	.text
+	.align 4
+	.globl setjmp
+	.type setjmp, @function
+setjmp:
+	pop  %rsi			# Return address, and adjust the stack
+	xorl %eax,%eax			# Return value
+	movq %rbx,(%rdi)
+	movq %rsp,8(%rdi)		# Post-return %rsp!
+	push %rsi			# Make the call/return stack happy
+	movq %rbp,16(%rdi)
+	movq %r12,24(%rdi)
+	movq %r13,32(%rdi)
+	movq %r14,40(%rdi)
+	movq %r15,48(%rdi)
+	movq %rsi,56(%rdi)		# Return address
+	ret
+
+	.size setjmp,.-setjmp
+
+	.text
+	.align 4
+	.globl longjmp
+	.type longjmp, @function
+longjmp:
+	movl %esi,%eax			# Return value (int)
+	movq (%rdi),%rbx
+	movq 8(%rdi),%rsp
+	movq 16(%rdi),%rbp
+	movq 24(%rdi),%r12
+	movq 32(%rdi),%r13
+	movq 40(%rdi),%r14
+	movq 48(%rdi),%r15
+	jmp *56(%rdi)
+
+	.size longjmp,.-longjmp
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/archsetjmp_32.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/archsetjmp_32.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/archsetjmp_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/archsetjmp_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+/*
+ * arch/um/include/sysdep-i386/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+	unsigned int __ebx;
+	unsigned int __esp;
+	unsigned int __ebp;
+	unsigned int __esi;
+	unsigned int __edi;
+	unsigned int __eip;
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#define JB_IP __eip
+#define JB_SP __esp
+
+#endif				/* _SETJMP_H */
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/archsetjmp_64.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/archsetjmp_64.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/archsetjmp_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/archsetjmp_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,24 @@
+/*
+ * arch/um/include/sysdep-x86_64/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+	unsigned long __rbx;
+	unsigned long __rsp;
+	unsigned long __rbp;
+	unsigned long __r12;
+	unsigned long __r13;
+	unsigned long __r14;
+	unsigned long __r15;
+	unsigned long __rip;
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#define JB_IP __rip
+#define JB_SP __rsp
+
+#endif				/* _SETJMP_H */
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/archsetjmp.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/archsetjmp.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/archsetjmp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/archsetjmp.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+#ifdef __i386__
+#include "archsetjmp_32.h"
+#else
+#include "archsetjmp_64.h"
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/faultinfo_32.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/faultinfo_32.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/faultinfo_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/faultinfo_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ * Licensed under the GPL
+ */
+
+#ifndef __FAULTINFO_I386_H
+#define __FAULTINFO_I386_H
+
+/* this structure contains the full arch-specific faultinfo
+ * from the traps.
+ * On i386, ptrace_faultinfo unfortunately doesn't provide
+ * all the info, since trap_no is missing.
+ * All common elements are defined at the same position in
+ * both structures, thus making it easy to copy the
+ * contents without knowledge about the structure elements.
+ */
+struct faultinfo {
+        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
+        unsigned long cr2; /* in ptrace_faultinfo called addr */
+        int trap_no; /* missing in ptrace_faultinfo */
+};
+
+#define FAULT_WRITE(fi) ((fi).error_code & 2)
+#define FAULT_ADDRESS(fi) ((fi).cr2)
+
+/* This is Page Fault */
+#define SEGV_IS_FIXABLE(fi)	((fi)->trap_no == 14)
+
+/* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */
+#define SEGV_MAYBE_FIXABLE(fi)	((fi)->trap_no == 0 && ptrace_faultinfo)
+
+#define PTRACE_FULL_FAULTINFO 0
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/faultinfo_64.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/faultinfo_64.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/faultinfo_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/faultinfo_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ * Licensed under the GPL
+ */
+
+#ifndef __FAULTINFO_X86_64_H
+#define __FAULTINFO_X86_64_H
+
+/* this structure contains the full arch-specific faultinfo
+ * from the traps.
+ * On i386, ptrace_faultinfo unfortunately doesn't provide
+ * all the info, since trap_no is missing.
+ * All common elements are defined at the same position in
+ * both structures, thus making it easy to copy the
+ * contents without knowledge about the structure elements.
+ */
+struct faultinfo {
+        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
+        unsigned long cr2; /* in ptrace_faultinfo called addr */
+        int trap_no; /* missing in ptrace_faultinfo */
+};
+
+#define FAULT_WRITE(fi) ((fi).error_code & 2)
+#define FAULT_ADDRESS(fi) ((fi).cr2)
+
+/* This is Page Fault */
+#define SEGV_IS_FIXABLE(fi)	((fi)->trap_no == 14)
+
+/* No broken SKAS API, which doesn't pass trap_no, here. */
+#define SEGV_MAYBE_FIXABLE(fi)	0
+
+#define PTRACE_FULL_FAULTINFO 1
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/faultinfo.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/faultinfo.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/faultinfo.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/faultinfo.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+#ifdef __i386__
+#include "faultinfo_32.h"
+#else
+#include "faultinfo_64.h"
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/kernel-offsets.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/kernel-offsets.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/kernel-offsets.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/kernel-offsets.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,21 @@
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/elf.h>
+#include <linux/crypto.h>
+#include <asm/mman.h>
+
+#define DEFINE(sym, val) \
+	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define STR(x) #x
+#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : )
+
+#define BLANK() asm volatile("\n->" : : )
+
+#define OFFSET(sym, str, mem) \
+	DEFINE(sym, offsetof(struct str, mem));
+
+void foo(void)
+{
+#include <common-offsets.h>
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/mcontext.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/mcontext.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/mcontext.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/mcontext.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,31 @@
+/* 
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYS_SIGCONTEXT_X86_H
+#define __SYS_SIGCONTEXT_X86_H
+
+extern void get_regs_from_mc(struct uml_pt_regs *, mcontext_t *);
+
+#ifdef __i386__
+
+#define GET_FAULTINFO_FROM_MC(fi, mc) \
+	{ \
+		(fi).cr2 = (mc)->cr2; \
+		(fi).error_code = (mc)->gregs[REG_ERR]; \
+		(fi).trap_no = (mc)->gregs[REG_TRAPNO]; \
+	}
+
+#else
+
+#define GET_FAULTINFO_FROM_MC(fi, mc) \
+	{ \
+		(fi).cr2 = (mc)->gregs[REG_CR2]; \
+		(fi).error_code = (mc)->gregs[REG_ERR]; \
+		(fi).trap_no = (mc)->gregs[REG_TRAPNO]; \
+	}
+
+#endif
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/ptrace_32.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/ptrace_32.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/ptrace_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/ptrace_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_I386_PTRACE_H
+#define __SYSDEP_I386_PTRACE_H
+
+#include <generated/user_constants.h>
+#include "sysdep/faultinfo.h"
+
+#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
+#define MAX_REG_OFFSET (UM_FRAME_SIZE)
+
+static inline void update_debugregs(int seq) {}
+
+/* syscall emulation path in ptrace */
+
+#ifndef PTRACE_SYSEMU
+#define PTRACE_SYSEMU 31
+#endif
+
+void set_using_sysemu(int value);
+int get_using_sysemu(void);
+extern int sysemu_supported;
+
+#define REGS_IP(r) ((r)[HOST_IP])
+#define REGS_SP(r) ((r)[HOST_SP])
+#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
+#define REGS_EAX(r) ((r)[HOST_AX])
+#define REGS_EBX(r) ((r)[HOST_BX])
+#define REGS_ECX(r) ((r)[HOST_CX])
+#define REGS_EDX(r) ((r)[HOST_DX])
+#define REGS_ESI(r) ((r)[HOST_SI])
+#define REGS_EDI(r) ((r)[HOST_DI])
+#define REGS_EBP(r) ((r)[HOST_BP])
+#define REGS_CS(r) ((r)[HOST_CS])
+#define REGS_SS(r) ((r)[HOST_SS])
+#define REGS_DS(r) ((r)[HOST_DS])
+#define REGS_ES(r) ((r)[HOST_ES])
+#define REGS_FS(r) ((r)[HOST_FS])
+#define REGS_GS(r) ((r)[HOST_GS])
+
+#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res)
+
+#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
+#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
+
+#ifndef PTRACE_SYSEMU_SINGLESTEP
+#define PTRACE_SYSEMU_SINGLESTEP 32
+#endif
+
+struct uml_pt_regs {
+	unsigned long gp[MAX_REG_NR];
+	unsigned long fp[HOST_FPX_SIZE];
+	struct faultinfo faultinfo;
+	long syscall;
+	int is_user;
+};
+
+#define EMPTY_UML_PT_REGS { }
+
+#define UPT_IP(r) REGS_IP((r)->gp)
+#define UPT_SP(r) REGS_SP((r)->gp)
+#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
+#define UPT_EAX(r) REGS_EAX((r)->gp)
+#define UPT_EBX(r) REGS_EBX((r)->gp)
+#define UPT_ECX(r) REGS_ECX((r)->gp)
+#define UPT_EDX(r) REGS_EDX((r)->gp)
+#define UPT_ESI(r) REGS_ESI((r)->gp)
+#define UPT_EDI(r) REGS_EDI((r)->gp)
+#define UPT_EBP(r) REGS_EBP((r)->gp)
+#define UPT_ORIG_EAX(r) ((r)->syscall)
+#define UPT_CS(r) REGS_CS((r)->gp)
+#define UPT_SS(r) REGS_SS((r)->gp)
+#define UPT_DS(r) REGS_DS((r)->gp)
+#define UPT_ES(r) REGS_ES((r)->gp)
+#define UPT_FS(r) REGS_FS((r)->gp)
+#define UPT_GS(r) REGS_GS((r)->gp)
+
+#define UPT_SYSCALL_ARG1(r) UPT_EBX(r)
+#define UPT_SYSCALL_ARG2(r) UPT_ECX(r)
+#define UPT_SYSCALL_ARG3(r) UPT_EDX(r)
+#define UPT_SYSCALL_ARG4(r) UPT_ESI(r)
+#define UPT_SYSCALL_ARG5(r) UPT_EDI(r)
+#define UPT_SYSCALL_ARG6(r) UPT_EBP(r)
+
+extern int user_context(unsigned long sp);
+
+#define UPT_IS_USER(r) ((r)->is_user)
+
+struct syscall_args {
+	unsigned long args[6];
+};
+
+#define SYSCALL_ARGS(r) ((struct syscall_args) \
+			 { .args = { UPT_SYSCALL_ARG1(r),	\
+				     UPT_SYSCALL_ARG2(r),	\
+				     UPT_SYSCALL_ARG3(r),	\
+				     UPT_SYSCALL_ARG4(r),	\
+				     UPT_SYSCALL_ARG5(r),	\
+				     UPT_SYSCALL_ARG6(r) } } )
+
+#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
+
+#define UPT_ORIG_SYSCALL(r) UPT_EAX(r)
+#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r)
+#define UPT_SYSCALL_RET(r) UPT_EAX(r)
+
+#define UPT_FAULTINFO(r) (&(r)->faultinfo)
+
+extern void arch_init_registers(int pid);
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/ptrace_64.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/ptrace_64.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/ptrace_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/ptrace_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_X86_64_PTRACE_H
+#define __SYSDEP_X86_64_PTRACE_H
+
+#include <generated/user_constants.h>
+#include "sysdep/faultinfo.h"
+
+#define MAX_REG_OFFSET (UM_FRAME_SIZE)
+#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
+
+#define REGS_IP(r) ((r)[HOST_IP])
+#define REGS_SP(r) ((r)[HOST_SP])
+
+#define REGS_RBX(r) ((r)[HOST_BX])
+#define REGS_RCX(r) ((r)[HOST_CX])
+#define REGS_RDX(r) ((r)[HOST_DX])
+#define REGS_RSI(r) ((r)[HOST_SI])
+#define REGS_RDI(r) ((r)[HOST_DI])
+#define REGS_RBP(r) ((r)[HOST_BP])
+#define REGS_RAX(r) ((r)[HOST_AX])
+#define REGS_R8(r) ((r)[HOST_R8])
+#define REGS_R9(r) ((r)[HOST_R9])
+#define REGS_R10(r) ((r)[HOST_R10])
+#define REGS_R11(r) ((r)[HOST_R11])
+#define REGS_R12(r) ((r)[HOST_R12])
+#define REGS_R13(r) ((r)[HOST_R13])
+#define REGS_R14(r) ((r)[HOST_R14])
+#define REGS_R15(r) ((r)[HOST_R15])
+#define REGS_CS(r) ((r)[HOST_CS])
+#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
+#define REGS_SS(r) ((r)[HOST_SS])
+
+#define HOST_FS_BASE 21
+#define HOST_GS_BASE 22
+#define HOST_DS 23
+#define HOST_ES 24
+#define HOST_FS 25
+#define HOST_GS 26
+
+/* Also defined in asm/ptrace-x86_64.h, but not in libc headers.  So, these
+ * are already defined for kernel code, but not for userspace code.
+ */
+#ifndef FS_BASE
+/* These aren't defined in ptrace.h, but exist in struct user_regs_struct,
+ * which is what x86_64 ptrace actually uses.
+ */
+#define FS_BASE (HOST_FS_BASE * sizeof(long))
+#define GS_BASE (HOST_GS_BASE * sizeof(long))
+#define DS (HOST_DS * sizeof(long))
+#define ES (HOST_ES * sizeof(long))
+#define FS (HOST_FS * sizeof(long))
+#define GS (HOST_GS * sizeof(long))
+#endif
+
+#define REGS_FS_BASE(r) ((r)[HOST_FS_BASE])
+#define REGS_GS_BASE(r) ((r)[HOST_GS_BASE])
+#define REGS_DS(r) ((r)[HOST_DS])
+#define REGS_ES(r) ((r)[HOST_ES])
+#define REGS_FS(r) ((r)[HOST_FS])
+#define REGS_GS(r) ((r)[HOST_GS])
+
+#define REGS_ORIG_RAX(r) ((r)[HOST_ORIG_AX])
+
+#define REGS_SET_SYSCALL_RETURN(r, res) REGS_RAX(r) = (res)
+
+#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
+#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
+
+#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
+
+#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
+
+#define REGS_TRAP(r) ((r)->trap_type)
+
+#define REGS_ERR(r) ((r)->fault_type)
+
+struct uml_pt_regs {
+	unsigned long gp[MAX_REG_NR];
+	unsigned long fp[HOST_FP_SIZE];
+	struct faultinfo faultinfo;
+	long syscall;
+	int is_user;
+};
+
+#define EMPTY_UML_PT_REGS { }
+
+#define UPT_RBX(r) REGS_RBX((r)->gp)
+#define UPT_RCX(r) REGS_RCX((r)->gp)
+#define UPT_RDX(r) REGS_RDX((r)->gp)
+#define UPT_RSI(r) REGS_RSI((r)->gp)
+#define UPT_RDI(r) REGS_RDI((r)->gp)
+#define UPT_RBP(r) REGS_RBP((r)->gp)
+#define UPT_RAX(r) REGS_RAX((r)->gp)
+#define UPT_R8(r) REGS_R8((r)->gp)
+#define UPT_R9(r) REGS_R9((r)->gp)
+#define UPT_R10(r) REGS_R10((r)->gp)
+#define UPT_R11(r) REGS_R11((r)->gp)
+#define UPT_R12(r) REGS_R12((r)->gp)
+#define UPT_R13(r) REGS_R13((r)->gp)
+#define UPT_R14(r) REGS_R14((r)->gp)
+#define UPT_R15(r) REGS_R15((r)->gp)
+#define UPT_CS(r) REGS_CS((r)->gp)
+#define UPT_FS_BASE(r) REGS_FS_BASE((r)->gp)
+#define UPT_FS(r) REGS_FS((r)->gp)
+#define UPT_GS_BASE(r) REGS_GS_BASE((r)->gp)
+#define UPT_GS(r) REGS_GS((r)->gp)
+#define UPT_DS(r) REGS_DS((r)->gp)
+#define UPT_ES(r) REGS_ES((r)->gp)
+#define UPT_CS(r) REGS_CS((r)->gp)
+#define UPT_SS(r) REGS_SS((r)->gp)
+#define UPT_ORIG_RAX(r) REGS_ORIG_RAX((r)->gp)
+
+#define UPT_IP(r) REGS_IP((r)->gp)
+#define UPT_SP(r) REGS_SP((r)->gp)
+
+#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
+#define UPT_SYSCALL_NR(r) ((r)->syscall)
+#define UPT_SYSCALL_RET(r) UPT_RAX(r)
+
+extern int user_context(unsigned long sp);
+
+#define UPT_IS_USER(r) ((r)->is_user)
+
+#define UPT_SYSCALL_ARG1(r) UPT_RDI(r)
+#define UPT_SYSCALL_ARG2(r) UPT_RSI(r)
+#define UPT_SYSCALL_ARG3(r) UPT_RDX(r)
+#define UPT_SYSCALL_ARG4(r) UPT_R10(r)
+#define UPT_SYSCALL_ARG5(r) UPT_R8(r)
+#define UPT_SYSCALL_ARG6(r) UPT_R9(r)
+
+struct syscall_args {
+	unsigned long args[6];
+};
+
+#define SYSCALL_ARGS(r) ((struct syscall_args) \
+			 { .args = { UPT_SYSCALL_ARG1(r),	 \
+				     UPT_SYSCALL_ARG2(r),	 \
+				     UPT_SYSCALL_ARG3(r),	 \
+				     UPT_SYSCALL_ARG4(r),	 \
+				     UPT_SYSCALL_ARG5(r),	 \
+				     UPT_SYSCALL_ARG6(r) } } )
+
+#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
+
+#define UPT_FAULTINFO(r) (&(r)->faultinfo)
+
+static inline void arch_init_registers(int pid)
+{
+}
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/ptrace.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/ptrace.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/ptrace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/ptrace.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+#ifdef __i386__
+#include "ptrace_32.h"
+#else
+#include "ptrace_64.h"
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/ptrace_user.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/ptrace_user.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/ptrace_user.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/ptrace_user.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,27 @@
+#include <generated/user_constants.h>
+
+#define PT_OFFSET(r) ((r) * sizeof(long))
+
+#define PT_SYSCALL_NR(regs) ((regs)[HOST_ORIG_AX])
+#define PT_SYSCALL_NR_OFFSET PT_OFFSET(HOST_ORIG_AX)
+
+#define PT_SYSCALL_RET_OFFSET PT_OFFSET(HOST_AX)
+
+#define REGS_IP_INDEX HOST_IP
+#define REGS_SP_INDEX HOST_SP
+
+#ifdef __i386__
+#define FP_SIZE ((HOST_FPX_SIZE > HOST_FP_SIZE) ? HOST_FPX_SIZE : HOST_FP_SIZE)
+#else
+#define FP_SIZE HOST_FP_SIZE
+
+/*
+ * x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though
+ * it's defined in the kernel's include/linux/ptrace.h. Additionally, use the
+ * 2.4 name and value for 2.4 host compatibility.
+ */
+#ifndef PTRACE_OLDSETOPTIONS
+#define PTRACE_OLDSETOPTIONS 21
+#endif
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/skas_ptrace.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/skas_ptrace.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/skas_ptrace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/skas_ptrace.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_X86_SKAS_PTRACE_H
+#define __SYSDEP_X86_SKAS_PTRACE_H
+
+struct ptrace_faultinfo {
+        int is_write;
+        unsigned long addr;
+};
+
+struct ptrace_ldt {
+        int func;
+        void *ptr;
+        unsigned long bytecount;
+};
+
+#define PTRACE_LDT 54
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/stub_32.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/stub_32.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/stub_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/stub_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_STUB_H
+#define __SYSDEP_STUB_H
+
+#include <asm/ptrace.h>
+
+#define STUB_SYSCALL_RET EAX
+#define STUB_MMAP_NR __NR_mmap2
+#define MMAP_OFFSET(o) ((o) >> UM_KERN_PAGE_SHIFT)
+
+static inline long stub_syscall0(long syscall)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall));
+
+	return ret;
+}
+
+static inline long stub_syscall1(long syscall, long arg1)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1));
+
+	return ret;
+}
+
+static inline long stub_syscall2(long syscall, long arg1, long arg2)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+			"c" (arg2));
+
+	return ret;
+}
+
+static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+			"c" (arg2), "d" (arg3));
+
+	return ret;
+}
+
+static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
+				 long arg4)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+			"c" (arg2), "d" (arg3), "S" (arg4));
+
+	return ret;
+}
+
+static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
+				 long arg4, long arg5)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+			"c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5));
+
+	return ret;
+}
+
+static inline void trap_myself(void)
+{
+	__asm("int3");
+}
+
+static inline void remap_stack(int fd, unsigned long offset)
+{
+	__asm__ volatile ("movl %%eax,%%ebp ; movl %0,%%eax ; int $0x80 ;"
+			  "movl %7, %%ebx ; movl %%eax, (%%ebx)"
+			  : : "g" (STUB_MMAP_NR), "b" (STUB_DATA),
+			    "c" (UM_KERN_PAGE_SIZE),
+			    "d" (PROT_READ | PROT_WRITE),
+			    "S" (MAP_FIXED | MAP_SHARED), "D" (fd),
+			    "a" (offset),
+			    "i" (&((struct stub_data *) STUB_DATA)->err)
+			  : "memory");
+}
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/stub_64.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/stub_64.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/stub_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/stub_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_STUB_H
+#define __SYSDEP_STUB_H
+
+#include <sysdep/ptrace_user.h>
+
+#define STUB_SYSCALL_RET PT_INDEX(RAX)
+#define STUB_MMAP_NR __NR_mmap
+#define MMAP_OFFSET(o) (o)
+
+#define __syscall_clobber "r11","rcx","memory"
+#define __syscall "syscall"
+
+static inline long stub_syscall0(long syscall)
+{
+	long ret;
+
+	__asm__ volatile (__syscall
+		: "=a" (ret)
+		: "0" (syscall) : __syscall_clobber );
+
+	return ret;
+}
+
+static inline long stub_syscall2(long syscall, long arg1, long arg2)
+{
+	long ret;
+
+	__asm__ volatile (__syscall
+		: "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2) : __syscall_clobber );
+
+	return ret;
+}
+
+static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
+{
+	long ret;
+
+	__asm__ volatile (__syscall
+		: "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3)
+		: __syscall_clobber );
+
+	return ret;
+}
+
+static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
+				 long arg4)
+{
+	long ret;
+
+	__asm__ volatile ("movq %5,%%r10 ; " __syscall
+		: "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
+		  "g" (arg4)
+		: __syscall_clobber, "r10" );
+
+	return ret;
+}
+
+static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
+				 long arg4, long arg5)
+{
+	long ret;
+
+	__asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " __syscall
+		: "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
+		  "g" (arg4), "g" (arg5)
+		: __syscall_clobber, "r10", "r8" );
+
+	return ret;
+}
+
+static inline void trap_myself(void)
+{
+	__asm("int3");
+}
+
+static inline void remap_stack(long fd, unsigned long offset)
+{
+	__asm__ volatile ("movq %4,%%r10 ; movq %5,%%r8 ; "
+			  "movq %6, %%r9; " __syscall "; movq %7, %%rbx ; "
+			  "movq %%rax, (%%rbx)":
+			  : "a" (STUB_MMAP_NR), "D" (STUB_DATA),
+			    "S" (UM_KERN_PAGE_SIZE),
+			    "d" (PROT_READ | PROT_WRITE),
+                            "g" (MAP_FIXED | MAP_SHARED), "g" (fd),
+			    "g" (offset),
+			    "i" (&((struct stub_data *) STUB_DATA)->err)
+			  : __syscall_clobber, "r10", "r8", "r9" );
+}
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/stub.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/stub.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/stub.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/stub.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,14 @@
+#include <asm/unistd.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include "as-layout.h"
+#include "stub-data.h"
+
+#ifdef __i386__
+#include "stub_32.h"
+#else
+#include "stub_64.h"
+#endif
+
+extern void stub_segv_handler(int, siginfo_t *, void *);
+extern void stub_clone_handler(void);
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/syscalls_32.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/syscalls_32.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/syscalls_32.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/syscalls_32.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,20 @@
+/* 
+ * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include "asm/unistd.h"
+#include "sysdep/ptrace.h"
+
+typedef long syscall_handler_t(struct pt_regs);
+
+/* Not declared on x86, incompatible declarations on x86_64, so these have
+ * to go here rather than in sys_call_table.c
+ */
+extern syscall_handler_t sys_rt_sigaction;
+
+extern syscall_handler_t *sys_call_table[];
+
+#define EXECUTE_SYSCALL(syscall, regs) \
+	((long (*)(struct syscall_args)) \
+	 (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/syscalls_64.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/syscalls_64.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/syscalls_64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/syscalls_64.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_X86_64_SYSCALLS_H__
+#define __SYSDEP_X86_64_SYSCALLS_H__
+
+#include <linux/msg.h>
+#include <linux/shm.h>
+
+typedef long syscall_handler_t(void);
+
+extern syscall_handler_t *sys_call_table[];
+
+#define EXECUTE_SYSCALL(syscall, regs) \
+	(((long (*)(long, long, long, long, long, long)) \
+	  (*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(&regs->regs), \
+		 		      UPT_SYSCALL_ARG2(&regs->regs), \
+				      UPT_SYSCALL_ARG3(&regs->regs), \
+				      UPT_SYSCALL_ARG4(&regs->regs), \
+				      UPT_SYSCALL_ARG5(&regs->regs), \
+				      UPT_SYSCALL_ARG6(&regs->regs)))
+
+extern long old_mmap(unsigned long addr, unsigned long len,
+		     unsigned long prot, unsigned long flags,
+		     unsigned long fd, unsigned long pgoff);
+extern syscall_handler_t sys_modify_ldt;
+extern syscall_handler_t sys_arch_prctl;
+
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/syscalls.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/syscalls.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/syscalls.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/syscalls.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+#ifdef __i386__
+#include "syscalls_32.h"
+#else
+#include "syscalls_64.h"
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/tls.h linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/tls.h
--- linux-libre-3.1-gnu/arch/x86/um/shared/sysdep/tls.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/shared/sysdep/tls.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,39 @@
+#ifndef _SYSDEP_TLS_H
+#define _SYSDEP_TLS_H
+
+# ifndef __KERNEL__
+
+/* Change name to avoid conflicts with the original one from <asm/ldt.h>, which
+ * may be named user_desc (but in 2.4 and in header matching its API was named
+ * modify_ldt_ldt_s). */
+
+typedef struct um_dup_user_desc {
+	unsigned int  entry_number;
+	unsigned int  base_addr;
+	unsigned int  limit;
+	unsigned int  seg_32bit:1;
+	unsigned int  contents:2;
+	unsigned int  read_exec_only:1;
+	unsigned int  limit_in_pages:1;
+	unsigned int  seg_not_present:1;
+	unsigned int  useable:1;
+#ifdef __x86_64__
+	unsigned int  lm:1;
+#endif
+} user_desc_t;
+
+# else /* __KERNEL__ */
+
+typedef struct user_desc user_desc_t;
+
+# endif /* __KERNEL__ */
+
+extern int os_set_thread_area(user_desc_t *info, int pid);
+extern int os_get_thread_area(user_desc_t *info, int pid);
+
+#ifdef __i386__
+#define GDT_ENTRY_TLS_MIN_I386 6
+#define GDT_ENTRY_TLS_MIN_X86_64 12
+#endif
+
+#endif /* _SYSDEP_TLS_H */
diff -druN linux-libre-3.1-gnu/arch/x86/um/signal.c linux-libre-3.2-gnu/arch/x86/um/signal.c
--- linux-libre-3.1-gnu/arch/x86/um/signal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/signal.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,624 @@
+/*
+ * Copyright (C) 2003 PathScale, Inc.
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+
+#include <linux/personality.h>
+#include <linux/ptrace.h>
+#include <linux/kernel.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <asm/ucontext.h>
+#include "frame_kern.h"
+#include "skas.h"
+
+#ifdef CONFIG_X86_32
+
+/*
+ * FPU tag word conversions.
+ */
+
+static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
+{
+	unsigned int tmp; /* to avoid 16 bit prefixes in the code */
+
+	/* Transform each pair of bits into 01 (valid) or 00 (empty) */
+	tmp = ~twd;
+	tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
+	/* and move the valid bits to the lower byte. */
+	tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
+	tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
+	tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
+	return tmp;
+}
+
+static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave)
+{
+	struct _fpxreg *st = NULL;
+	unsigned long twd = (unsigned long) fxsave->twd;
+	unsigned long tag;
+	unsigned long ret = 0xffff0000;
+	int i;
+
+#define FPREG_ADDR(f, n)	((char *)&(f)->st_space + (n) * 16)
+
+	for (i = 0; i < 8; i++) {
+		if (twd & 0x1) {
+			st = (struct _fpxreg *) FPREG_ADDR(fxsave, i);
+
+			switch (st->exponent & 0x7fff) {
+			case 0x7fff:
+				tag = 2;		/* Special */
+				break;
+			case 0x0000:
+				if ( !st->significand[0] &&
+				     !st->significand[1] &&
+				     !st->significand[2] &&
+				     !st->significand[3] ) {
+					tag = 1;	/* Zero */
+				} else {
+					tag = 2;	/* Special */
+				}
+				break;
+			default:
+				if (st->significand[3] & 0x8000) {
+					tag = 0;	/* Valid */
+				} else {
+					tag = 2;	/* Special */
+				}
+				break;
+			}
+		} else {
+			tag = 3;			/* Empty */
+		}
+		ret |= (tag << (2 * i));
+		twd = twd >> 1;
+	}
+	return ret;
+}
+
+static int convert_fxsr_to_user(struct _fpstate __user *buf,
+				struct user_fxsr_struct *fxsave)
+{
+	unsigned long env[7];
+	struct _fpreg __user *to;
+	struct _fpxreg *from;
+	int i;
+
+	env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul;
+	env[1] = (unsigned long)fxsave->swd | 0xffff0000ul;
+	env[2] = twd_fxsr_to_i387(fxsave);
+	env[3] = fxsave->fip;
+	env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
+	env[5] = fxsave->foo;
+	env[6] = fxsave->fos;
+
+	if (__copy_to_user(buf, env, 7 * sizeof(unsigned long)))
+		return 1;
+
+	to = &buf->_st[0];
+	from = (struct _fpxreg *) &fxsave->st_space[0];
+	for (i = 0; i < 8; i++, to++, from++) {
+		unsigned long __user *t = (unsigned long __user *)to;
+		unsigned long *f = (unsigned long *)from;
+
+		if (__put_user(*f, t) ||
+				__put_user(*(f + 1), t + 1) ||
+				__put_user(from->exponent, &to->exponent))
+			return 1;
+	}
+	return 0;
+}
+
+static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave,
+				  struct _fpstate __user *buf)
+{
+	unsigned long env[7];
+	struct _fpxreg *to;
+	struct _fpreg __user *from;
+	int i;
+
+	if (copy_from_user( env, buf, 7 * sizeof(long)))
+		return 1;
+
+	fxsave->cwd = (unsigned short)(env[0] & 0xffff);
+	fxsave->swd = (unsigned short)(env[1] & 0xffff);
+	fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
+	fxsave->fip = env[3];
+	fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16);
+	fxsave->fcs = (env[4] & 0xffff);
+	fxsave->foo = env[5];
+	fxsave->fos = env[6];
+
+	to = (struct _fpxreg *) &fxsave->st_space[0];
+	from = &buf->_st[0];
+	for (i = 0; i < 8; i++, to++, from++) {
+		unsigned long *t = (unsigned long *)to;
+		unsigned long __user *f = (unsigned long __user *)from;
+
+		if (__get_user(*t, f) ||
+		    __get_user(*(t + 1), f + 1) ||
+		    __get_user(to->exponent, &from->exponent))
+			return 1;
+	}
+	return 0;
+}
+
+extern int have_fpx_regs;
+
+#endif
+
+static int copy_sc_from_user(struct pt_regs *regs,
+			     struct sigcontext __user *from)
+{
+	struct sigcontext sc;
+	int err, pid;
+
+	err = copy_from_user(&sc, from, sizeof(sc));
+	if (err)
+		return err;
+
+#define GETREG(regno, regname) regs->regs.gp[HOST_##regno] = sc.regname
+
+#ifdef CONFIG_X86_32
+	GETREG(GS, gs);
+	GETREG(FS, fs);
+	GETREG(ES, es);
+	GETREG(DS, ds);
+#endif
+	GETREG(DI, di);
+	GETREG(SI, si);
+	GETREG(BP, bp);
+	GETREG(SP, sp);
+	GETREG(BX, bx);
+	GETREG(DX, dx);
+	GETREG(CX, cx);
+	GETREG(AX, ax);
+	GETREG(IP, ip);
+
+#ifdef CONFIG_X86_64
+	GETREG(R8, r8);
+	GETREG(R9, r9);
+	GETREG(R10, r10);
+	GETREG(R11, r11);
+	GETREG(R12, r12);
+	GETREG(R13, r13);
+	GETREG(R14, r14);
+	GETREG(R15, r15);
+#endif
+
+	GETREG(CS, cs);
+	GETREG(EFLAGS, flags);
+#ifdef CONFIG_X86_32
+	GETREG(SS, ss);
+#endif
+
+#undef GETREG
+
+	pid = userspace_pid[current_thread_info()->cpu];
+#ifdef CONFIG_X86_32
+	if (have_fpx_regs) {
+		struct user_fxsr_struct fpx;
+
+		err = copy_from_user(&fpx,
+			&((struct _fpstate __user *)sc.fpstate)->_fxsr_env[0],
+				     sizeof(struct user_fxsr_struct));
+		if (err)
+			return 1;
+
+		err = convert_fxsr_from_user(&fpx, sc.fpstate);
+		if (err)
+			return 1;
+
+		err = restore_fpx_registers(pid, (unsigned long *) &fpx);
+		if (err < 0) {
+			printk(KERN_ERR "copy_sc_from_user - "
+			       "restore_fpx_registers failed, errno = %d\n",
+			       -err);
+			return 1;
+		}
+	} else
+#endif
+	{
+		struct user_i387_struct fp;
+
+		err = copy_from_user(&fp, sc.fpstate,
+				     sizeof(struct user_i387_struct));
+		if (err)
+			return 1;
+
+		err = restore_fp_registers(pid, (unsigned long *) &fp);
+		if (err < 0) {
+			printk(KERN_ERR "copy_sc_from_user - "
+			       "restore_fp_registers failed, errno = %d\n",
+			       -err);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int copy_sc_to_user(struct sigcontext __user *to,
+			   struct _fpstate __user *to_fp, struct pt_regs *regs,
+			   unsigned long mask)
+{
+	struct sigcontext sc;
+	struct faultinfo * fi = &current->thread.arch.faultinfo;
+	int err, pid;
+	memset(&sc, 0, sizeof(struct sigcontext));
+
+#define PUTREG(regno, regname) sc.regname = regs->regs.gp[HOST_##regno]
+
+#ifdef CONFIG_X86_32
+	PUTREG(GS, gs);
+	PUTREG(FS, fs);
+	PUTREG(ES, es);
+	PUTREG(DS, ds);
+#endif
+	PUTREG(DI, di);
+	PUTREG(SI, si);
+	PUTREG(BP, bp);
+	PUTREG(SP, sp);
+	PUTREG(BX, bx);
+	PUTREG(DX, dx);
+	PUTREG(CX, cx);
+	PUTREG(AX, ax);
+#ifdef CONFIG_X86_64
+	PUTREG(R8, r8);
+	PUTREG(R9, r9);
+	PUTREG(R10, r10);
+	PUTREG(R11, r11);
+	PUTREG(R12, r12);
+	PUTREG(R13, r13);
+	PUTREG(R14, r14);
+	PUTREG(R15, r15);
+#endif
+
+	sc.cr2 = fi->cr2;
+	sc.err = fi->error_code;
+	sc.trapno = fi->trap_no;
+	PUTREG(IP, ip);
+	PUTREG(CS, cs);
+	PUTREG(EFLAGS, flags);
+#ifdef CONFIG_X86_32
+	PUTREG(SP, sp_at_signal);
+	PUTREG(SS, ss);
+#endif
+#undef PUTREG
+	sc.oldmask = mask;
+	sc.fpstate = to_fp;
+
+	err = copy_to_user(to, &sc, sizeof(struct sigcontext));
+	if (err)
+		return 1;
+
+	pid = userspace_pid[current_thread_info()->cpu];
+
+#ifdef CONFIG_X86_32
+	if (have_fpx_regs) {
+		struct user_fxsr_struct fpx;
+
+		err = save_fpx_registers(pid, (unsigned long *) &fpx);
+		if (err < 0){
+			printk(KERN_ERR "copy_sc_to_user - save_fpx_registers "
+			       "failed, errno = %d\n", err);
+			return 1;
+		}
+
+		err = convert_fxsr_to_user(to_fp, &fpx);
+		if (err)
+			return 1;
+
+		err |= __put_user(fpx.swd, &to_fp->status);
+		err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic);
+		if (err)
+			return 1;
+
+		if (copy_to_user(&to_fp->_fxsr_env[0], &fpx,
+				 sizeof(struct user_fxsr_struct)))
+			return 1;
+	} else
+#endif
+	{
+		struct user_i387_struct fp;
+
+		err = save_fp_registers(pid, (unsigned long *) &fp);
+		if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
+			return 1;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_X86_32
+static int copy_ucontext_to_user(struct ucontext __user *uc,
+				 struct _fpstate __user *fp, sigset_t *set,
+				 unsigned long sp)
+{
+	int err = 0;
+
+	err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
+	err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
+	err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
+	err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, 0);
+	err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
+	return err;
+}
+
+struct sigframe
+{
+	char __user *pretcode;
+	int sig;
+	struct sigcontext sc;
+	struct _fpstate fpstate;
+	unsigned long extramask[_NSIG_WORDS-1];
+	char retcode[8];
+};
+
+struct rt_sigframe
+{
+	char __user *pretcode;
+	int sig;
+	struct siginfo __user *pinfo;
+	void __user *puc;
+	struct siginfo info;
+	struct ucontext uc;
+	struct _fpstate fpstate;
+	char retcode[8];
+};
+
+int setup_signal_stack_sc(unsigned long stack_top, int sig,
+			  struct k_sigaction *ka, struct pt_regs *regs,
+			  sigset_t *mask)
+{
+	struct sigframe __user *frame;
+	void __user *restorer;
+	int err = 0;
+
+	/* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
+	stack_top = ((stack_top + 4) & -16UL) - 4;
+	frame = (struct sigframe __user *) stack_top - 1;
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		return 1;
+
+	restorer = frame->retcode;
+	if (ka->sa.sa_flags & SA_RESTORER)
+		restorer = ka->sa.sa_restorer;
+
+	err |= __put_user(restorer, &frame->pretcode);
+	err |= __put_user(sig, &frame->sig);
+	err |= copy_sc_to_user(&frame->sc, &frame->fpstate, regs, mask->sig[0]);
+	if (_NSIG_WORDS > 1)
+		err |= __copy_to_user(&frame->extramask, &mask->sig[1],
+				      sizeof(frame->extramask));
+
+	/*
+	 * This is popl %eax ; movl $,%eax ; int $0x80
+	 *
+	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
+	 * reasons and because gdb uses it as a signature to notice
+	 * signal handler stack frames.
+	 */
+	err |= __put_user(0xb858, (short __user *)(frame->retcode+0));
+	err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2));
+	err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));
+
+	if (err)
+		return err;
+
+	PT_REGS_SP(regs) = (unsigned long) frame;
+	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
+	PT_REGS_EAX(regs) = (unsigned long) sig;
+	PT_REGS_EDX(regs) = (unsigned long) 0;
+	PT_REGS_ECX(regs) = (unsigned long) 0;
+
+	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
+		ptrace_notify(SIGTRAP);
+	return 0;
+}
+
+int setup_signal_stack_si(unsigned long stack_top, int sig,
+			  struct k_sigaction *ka, struct pt_regs *regs,
+			  siginfo_t *info, sigset_t *mask)
+{
+	struct rt_sigframe __user *frame;
+	void __user *restorer;
+	int err = 0;
+
+	stack_top &= -8UL;
+	frame = (struct rt_sigframe __user *) stack_top - 1;
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		return 1;
+
+	restorer = frame->retcode;
+	if (ka->sa.sa_flags & SA_RESTORER)
+		restorer = ka->sa.sa_restorer;
+
+	err |= __put_user(restorer, &frame->pretcode);
+	err |= __put_user(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);
+	err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
+					PT_REGS_SP(regs));
+
+	/*
+	 * This is movl $,%eax ; int $0x80
+	 *
+	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
+	 * reasons and because gdb uses it as a signature to notice
+	 * signal handler stack frames.
+	 */
+	err |= __put_user(0xb8, (char __user *)(frame->retcode+0));
+	err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1));
+	err |= __put_user(0x80cd, (short __user *)(frame->retcode+5));
+
+	if (err)
+		return err;
+
+	PT_REGS_SP(regs) = (unsigned long) frame;
+	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
+	PT_REGS_EAX(regs) = (unsigned long) sig;
+	PT_REGS_EDX(regs) = (unsigned long) &frame->info;
+	PT_REGS_ECX(regs) = (unsigned long) &frame->uc;
+
+	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
+		ptrace_notify(SIGTRAP);
+	return 0;
+}
+
+long sys_sigreturn(struct pt_regs *regs)
+{
+	unsigned long sp = PT_REGS_SP(&current->thread.regs);
+	struct sigframe __user *frame = (struct sigframe __user *)(sp - 8);
+	sigset_t set;
+	struct sigcontext __user *sc = &frame->sc;
+	unsigned long __user *oldmask = &sc->oldmask;
+	unsigned long __user *extramask = frame->extramask;
+	int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
+
+	if (copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) ||
+	    copy_from_user(&set.sig[1], extramask, sig_size))
+		goto segfault;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	set_current_blocked(&set);
+
+	if (copy_sc_from_user(&current->thread.regs, sc))
+		goto segfault;
+
+	/* Avoid ERESTART handling */
+	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
+	return PT_REGS_SYSCALL_RET(&current->thread.regs);
+
+ segfault:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+#else
+
+struct rt_sigframe
+{
+	char __user *pretcode;
+	struct ucontext uc;
+	struct siginfo info;
+	struct _fpstate fpstate;
+};
+
+int setup_signal_stack_si(unsigned long stack_top, int sig,
+			  struct k_sigaction *ka, struct pt_regs * regs,
+			  siginfo_t *info, sigset_t *set)
+{
+	struct rt_sigframe __user *frame;
+	int err = 0;
+	struct task_struct *me = current;
+
+	frame = (struct rt_sigframe __user *)
+		round_down(stack_top - sizeof(struct rt_sigframe), 16);
+	/* Subtract 128 for a red zone and 8 for proper alignment */
+	frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto out;
+
+	if (ka->sa.sa_flags & SA_SIGINFO) {
+		err |= copy_siginfo_to_user(&frame->info, info);
+		if (err)
+			goto out;
+	}
+
+	/* Create the ucontext.  */
+	err |= __put_user(0, &frame->uc.uc_flags);
+	err |= __put_user(0, &frame->uc.uc_link);
+	err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+	err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)),
+			  &frame->uc.uc_stack.ss_flags);
+	err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
+	err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
+			       set->sig[0]);
+	err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate);
+	if (sizeof(*set) == 16) {
+		__put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
+		__put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
+	}
+	else
+		err |= __copy_to_user(&frame->uc.uc_sigmask, set,
+				      sizeof(*set));
+
+	/*
+	 * Set up to return from userspace.  If provided, use a stub
+	 * already in userspace.
+	 */
+	/* x86-64 should always use SA_RESTORER. */
+	if (ka->sa.sa_flags & SA_RESTORER)
+		err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
+	else
+		/* could use a vstub here */
+		return err;
+
+	if (err)
+		return err;
+
+	/* Set up registers for signal handler */
+	{
+		struct exec_domain *ed = current_thread_info()->exec_domain;
+		if (unlikely(ed && ed->signal_invmap && sig < 32))
+			sig = ed->signal_invmap[sig];
+	}
+
+	PT_REGS_SP(regs) = (unsigned long) frame;
+	PT_REGS_RDI(regs) = sig;
+	/* In case the signal handler was declared without prototypes */
+	PT_REGS_RAX(regs) = 0;
+
+	/*
+	 * This also works for non SA_SIGINFO handlers because they expect the
+	 * next argument after the signal number on the stack.
+	 */
+	PT_REGS_RSI(regs) = (unsigned long) &frame->info;
+	PT_REGS_RDX(regs) = (unsigned long) &frame->uc;
+	PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler;
+ out:
+	return err;
+}
+#endif
+
+long sys_rt_sigreturn(struct pt_regs *regs)
+{
+	unsigned long sp = PT_REGS_SP(&current->thread.regs);
+	struct rt_sigframe __user *frame =
+		(struct rt_sigframe __user *)(sp - sizeof(long));
+	struct ucontext __user *uc = &frame->uc;
+	sigset_t set;
+
+	if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
+		goto segfault;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	set_current_blocked(&set);
+
+	if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
+		goto segfault;
+
+	/* Avoid ERESTART handling */
+	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
+	return PT_REGS_SYSCALL_RET(&current->thread.regs);
+
+ segfault:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+#ifdef CONFIG_X86_32
+long ptregs_sigreturn(void)
+{
+	return sys_sigreturn(NULL);
+}
+long ptregs_rt_sigreturn(void)
+{
+	return sys_rt_sigreturn(NULL);
+}
+#endif
diff -druN linux-libre-3.1-gnu/arch/x86/um/stub_32.S linux-libre-3.2-gnu/arch/x86/um/stub_32.S
--- linux-libre-3.1-gnu/arch/x86/um/stub_32.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/stub_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,51 @@
+#include "as-layout.h"
+
+	.globl syscall_stub
+.section .__syscall_stub, "ax"
+
+	.globl batch_syscall_stub
+batch_syscall_stub:
+	/* load pointer to first operation */
+	mov	$(STUB_DATA+8), %esp
+
+again:
+	/* load length of additional data */
+	mov	0x0(%esp), %eax
+
+	/* if(length == 0) : end of list */
+	/* write possible 0 to header */
+	mov	%eax, STUB_DATA+4
+	cmpl	$0, %eax
+	jz	done
+
+	/* save current pointer */
+	mov	%esp, STUB_DATA+4
+
+	/* skip additional data */
+	add	%eax, %esp
+
+	/* load syscall-# */
+	pop	%eax
+
+	/* load syscall params */
+	pop	%ebx
+	pop	%ecx
+	pop	%edx
+	pop	%esi
+ 	pop	%edi
+	pop	%ebp
+
+	/* execute syscall */
+	int	$0x80
+
+	/* check return value */
+	pop	%ebx
+	cmp	%ebx, %eax
+	je	again
+
+done:
+	/* save return value */
+	mov	%eax, STUB_DATA
+
+	/* stop */
+	int3
diff -druN linux-libre-3.1-gnu/arch/x86/um/stub_64.S linux-libre-3.2-gnu/arch/x86/um/stub_64.S
--- linux-libre-3.1-gnu/arch/x86/um/stub_64.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/stub_64.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,66 @@
+#include "as-layout.h"
+
+	.globl syscall_stub
+.section .__syscall_stub, "ax"
+syscall_stub:
+	syscall
+	/* We don't have 64-bit constants, so this constructs the address
+	 * we need.
+	 */
+	movq	$(STUB_DATA >> 32), %rbx
+	salq	$32, %rbx
+	movq	$(STUB_DATA & 0xffffffff), %rcx
+	or	%rcx, %rbx
+	movq	%rax, (%rbx)
+	int3
+
+	.globl batch_syscall_stub
+batch_syscall_stub:
+	mov	$(STUB_DATA >> 32), %rbx
+	sal	$32, %rbx
+	mov	$(STUB_DATA & 0xffffffff), %rax
+	or	%rax, %rbx
+	/* load pointer to first operation */
+	mov	%rbx, %rsp
+	add	$0x10, %rsp
+again:
+	/* load length of additional data */
+	mov	0x0(%rsp), %rax
+
+	/* if(length == 0) : end of list */
+	/* write possible 0 to header */
+	mov	%rax, 8(%rbx)
+	cmp	$0, %rax
+	jz	done
+
+	/* save current pointer */
+	mov	%rsp, 8(%rbx)
+
+	/* skip additional data */
+	add	%rax, %rsp
+
+	/* load syscall-# */
+	pop	%rax
+
+	/* load syscall params */
+	pop	%rdi
+	pop	%rsi
+	pop	%rdx
+	pop	%r10
+ 	pop	%r8
+	pop	%r9
+
+	/* execute syscall */
+	syscall
+
+	/* check return value */
+	pop	%rcx
+	cmp	%rcx, %rax
+	je	again
+
+done:
+	/* save return value */
+	mov	%rax, (%rbx)
+
+	/* stop */
+	int3
diff -druN linux-libre-3.1-gnu/arch/x86/um/stub_segv.c linux-libre-3.2-gnu/arch/x86/um/stub_segv.c
--- linux-libre-3.1-gnu/arch/x86/um/stub_segv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/stub_segv.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include "sysdep/stub.h"
+#include "sysdep/faultinfo.h"
+#include "sysdep/mcontext.h"
+
+void __attribute__ ((__section__ (".__syscall_stub")))
+stub_segv_handler(int sig, siginfo_t *info, void *p)
+{
+	struct ucontext *uc = p;
+
+	GET_FAULTINFO_FROM_MC(*((struct faultinfo *) STUB_DATA),
+			      &uc->uc_mcontext);
+	trap_myself();
+}
+
diff -druN linux-libre-3.1-gnu/arch/x86/um/syscalls_32.c linux-libre-3.2-gnu/arch/x86/um/syscalls_32.c
--- linux-libre-3.1-gnu/arch/x86/um/syscalls_32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/syscalls_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,66 @@
+/* 
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/sched.h"
+#include "linux/shm.h"
+#include "linux/ipc.h"
+#include "linux/syscalls.h"
+#include "asm/mman.h"
+#include "asm/uaccess.h"
+#include "asm/unistd.h"
+
+/*
+ * The prototype on i386 is:
+ *
+ *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
+ *
+ * and the "newtls" arg. on i386 is read by copy_thread directly from the
+ * register saved on the stack.
+ */
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+	       int __user *parent_tid, void *newtls, int __user *child_tid)
+{
+	long ret;
+
+	if (!newsp)
+		newsp = UPT_SP(&current->thread.regs.regs);
+
+	current->thread.forking = 1;
+	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
+		      child_tid);
+	current->thread.forking = 0;
+	return ret;
+}
+
+long 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))
+			return -EFAULT;
+		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		__get_user(mask, &act->sa_mask);
+		siginitset(&new_ka.sa.sa_mask, mask);
+	}
+
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
+		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+			return -EFAULT;
+		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+	}
+
+	return ret;
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/syscalls_64.c linux-libre-3.2-gnu/arch/x86/um/syscalls_64.c
--- linux-libre-3.1-gnu/arch/x86/um/syscalls_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/syscalls_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include "linux/linkage.h"
+#include "linux/personality.h"
+#include "linux/utsname.h"
+#include "asm/prctl.h" /* XXX This should get the constants from libc */
+#include "asm/uaccess.h"
+#include "os.h"
+
+long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
+{
+	unsigned long *ptr = addr, tmp;
+	long ret;
+	int pid = task->mm->context.id.u.pid;
+
+	/*
+	 * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to
+	 * be safe), we need to call arch_prctl on the host because
+	 * setting %fs may result in something else happening (like a
+	 * GDT or thread.fs being set instead).  So, we let the host
+	 * fiddle the registers and thread struct and restore the
+	 * registers afterwards.
+	 *
+	 * So, the saved registers are stored to the process (this
+	 * needed because a stub may have been the last thing to run),
+	 * arch_prctl is run on the host, then the registers are read
+	 * back.
+	 */
+	switch (code) {
+	case ARCH_SET_FS:
+	case ARCH_SET_GS:
+		ret = restore_registers(pid, &current->thread.regs.regs);
+		if (ret)
+			return ret;
+		break;
+	case ARCH_GET_FS:
+	case ARCH_GET_GS:
+		/*
+		 * With these two, we read to a local pointer and
+		 * put_user it to the userspace pointer that we were
+		 * given.  If addr isn't valid (because it hasn't been
+		 * faulted in or is just bogus), we want put_user to
+		 * fault it in (or return -EFAULT) instead of having
+		 * the host return -EFAULT.
+		 */
+		ptr = &tmp;
+	}
+
+	ret = os_arch_prctl(pid, code, ptr);
+	if (ret)
+		return ret;
+
+	switch (code) {
+	case ARCH_SET_FS:
+		current->thread.arch.fs = (unsigned long) ptr;
+		ret = save_registers(pid, &current->thread.regs.regs);
+		break;
+	case ARCH_SET_GS:
+		ret = save_registers(pid, &current->thread.regs.regs);
+		break;
+	case ARCH_GET_FS:
+		ret = put_user(tmp, addr);
+		break;
+	case ARCH_GET_GS:
+		ret = put_user(tmp, addr);
+		break;
+	}
+
+	return ret;
+}
+
+long sys_arch_prctl(int code, unsigned long addr)
+{
+	return arch_prctl(current, code, (unsigned long __user *) addr);
+}
+
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+	       void __user *parent_tid, void __user *child_tid)
+{
+	long ret;
+
+	if (!newsp)
+		newsp = UPT_SP(&current->thread.regs.regs);
+	current->thread.forking = 1;
+	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
+		      child_tid);
+	current->thread.forking = 0;
+	return ret;
+}
+
+void arch_switch_to(struct task_struct *to)
+{
+	if ((to->thread.arch.fs == 0) || (to->mm == NULL))
+		return;
+
+	arch_prctl(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/sys_call_table_32.S linux-libre-3.2-gnu/arch/x86/um/sys_call_table_32.S
--- linux-libre-3.1-gnu/arch/x86/um/sys_call_table_32.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/sys_call_table_32.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+#include <linux/linkage.h>
+/* Steal i386 syscall table for our purposes, but with some slight changes.*/
+
+#define sys_iopl sys_ni_syscall
+#define sys_ioperm sys_ni_syscall
+
+#define sys_vm86old sys_ni_syscall
+#define sys_vm86 sys_ni_syscall
+
+#define old_mmap sys_old_mmap
+
+#define ptregs_fork sys_fork
+#define ptregs_execve sys_execve
+#define ptregs_iopl sys_iopl
+#define ptregs_vm86old sys_vm86old
+#define ptregs_clone sys_clone
+#define ptregs_vm86 sys_vm86
+#define ptregs_sigaltstack sys_sigaltstack
+#define ptregs_vfork sys_vfork
+
+.section .rodata,"a"
+
+#include "../kernel/syscall_table_32.S"
+
+ENTRY(syscall_table_size)
+.long .-sys_call_table
diff -druN linux-libre-3.1-gnu/arch/x86/um/sys_call_table_64.c linux-libre-3.2-gnu/arch/x86/um/sys_call_table_64.c
--- linux-libre-3.1-gnu/arch/x86/um/sys_call_table_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/sys_call_table_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,64 @@
+/*
+ * System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
+ * with some changes for UML.
+ */
+
+#include <linux/linkage.h>
+#include <linux/sys.h>
+#include <linux/cache.h>
+
+#define __NO_STUBS
+
+/*
+ * Below you can see, in terms of #define's, the differences between the x86-64
+ * and the UML syscall table.
+ */
+
+/* Not going to be implemented by UML, since we have no hardware. */
+#define stub_iopl sys_ni_syscall
+#define sys_ioperm sys_ni_syscall
+
+/*
+ * The UML TLS problem. Note that x86_64 does not implement this, so the below
+ * is needed only for the ia32 compatibility.
+ */
+
+/* On UML we call it this way ("old" means it's not mmap2) */
+#define sys_mmap old_mmap
+
+#define stub_clone sys_clone
+#define stub_fork sys_fork
+#define stub_vfork sys_vfork
+#define stub_execve sys_execve
+#define stub_rt_sigsuspend sys_rt_sigsuspend
+#define stub_sigaltstack sys_sigaltstack
+#define stub_rt_sigreturn sys_rt_sigreturn
+
+#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
+#undef _ASM_X86_UNISTD_64_H
+#include "../../x86/include/asm/unistd_64.h"
+
+#undef __SYSCALL
+#define __SYSCALL(nr, sym) [ nr ] = sym,
+#undef _ASM_X86_UNISTD_64_H
+
+typedef void (*sys_call_ptr_t)(void);
+
+extern void sys_ni_syscall(void);
+
+/*
+ * We used to have a trick here which made sure that holes in the
+ * x86_64 table were filled in with sys_ni_syscall, but a comment in
+ * unistd_64.h says that holes aren't allowed, so the trick was
+ * removed.
+ * The trick looked like this
+ *	[0 ... UM_NR_syscall_max] = &sys_ni_syscall
+ * before including unistd_64.h - the later initializations overwrote
+ * the sys_ni_syscall filler.
+ */
+
+sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
+#include <asm/unistd_64.h>
+};
+
+int syscall_table_size = sizeof(sys_call_table);
diff -druN linux-libre-3.1-gnu/arch/x86/um/sysrq_32.c linux-libre-3.2-gnu/arch/x86/um/sysrq_32.c
--- linux-libre-3.1-gnu/arch/x86/um/sysrq_32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/sysrq_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/kernel.h"
+#include "linux/smp.h"
+#include "linux/sched.h"
+#include "linux/kallsyms.h"
+#include "asm/ptrace.h"
+#include "sysrq.h"
+
+/* This is declared by <linux/sched.h> */
+void show_regs(struct pt_regs *regs)
+{
+        printk("\n");
+        printk("EIP: %04lx:[<%08lx>] CPU: %d %s", 
+	       0xffff & PT_REGS_CS(regs), PT_REGS_IP(regs),
+	       smp_processor_id(), print_tainted());
+        if (PT_REGS_CS(regs) & 3)
+                printk(" ESP: %04lx:%08lx", 0xffff & PT_REGS_SS(regs),
+		       PT_REGS_SP(regs));
+        printk(" EFLAGS: %08lx\n    %s\n", PT_REGS_EFLAGS(regs),
+	       print_tainted());
+        printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
+                PT_REGS_EAX(regs), PT_REGS_EBX(regs), 
+	       PT_REGS_ECX(regs), 
+	       PT_REGS_EDX(regs));
+        printk("ESI: %08lx EDI: %08lx EBP: %08lx",
+	       PT_REGS_ESI(regs), PT_REGS_EDI(regs), 
+	       PT_REGS_EBP(regs));
+        printk(" DS: %04lx ES: %04lx\n",
+	       0xffff & PT_REGS_DS(regs), 
+	       0xffff & PT_REGS_ES(regs));
+
+        show_trace(NULL, (unsigned long *) &regs);
+}
+
+/* Copied from i386. */
+static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
+{
+	return	p > (void *)tinfo &&
+		p < (void *)tinfo + THREAD_SIZE - 3;
+}
+
+/* Adapted from i386 (we also print the address we read from). */
+static inline unsigned long print_context_stack(struct thread_info *tinfo,
+				unsigned long *stack, unsigned long ebp)
+{
+	unsigned long addr;
+
+#ifdef CONFIG_FRAME_POINTER
+	while (valid_stack_ptr(tinfo, (void *)ebp)) {
+		addr = *(unsigned long *)(ebp + 4);
+		printk("%08lx:  [<%08lx>]", ebp + 4, addr);
+		print_symbol(" %s", addr);
+		printk("\n");
+		ebp = *(unsigned long *)ebp;
+	}
+#else
+	while (valid_stack_ptr(tinfo, stack)) {
+		addr = *stack;
+		if (__kernel_text_address(addr)) {
+			printk("%08lx:  [<%08lx>]", (unsigned long) stack, addr);
+			print_symbol(" %s", addr);
+			printk("\n");
+		}
+		stack++;
+	}
+#endif
+	return ebp;
+}
+
+void show_trace(struct task_struct* task, unsigned long * stack)
+{
+	unsigned long ebp;
+	struct thread_info *context;
+
+	/* Turn this into BUG_ON if possible. */
+	if (!stack) {
+		stack = (unsigned long*) &stack;
+		printk("show_trace: got NULL stack, implicit assumption task == current");
+		WARN_ON(1);
+	}
+
+	if (!task)
+		task = current;
+
+	if (task != current) {
+		ebp = (unsigned long) KSTK_EBP(task);
+	} else {
+		asm ("movl %%ebp, %0" : "=r" (ebp) : );
+	}
+
+	context = (struct thread_info *)
+		((unsigned long)stack & (~(THREAD_SIZE - 1)));
+	print_context_stack(context, stack, ebp);
+
+	printk("\n");
+}
+
diff -druN linux-libre-3.1-gnu/arch/x86/um/sysrq_64.c linux-libre-3.2-gnu/arch/x86/um/sysrq_64.c
--- linux-libre-3.1-gnu/arch/x86/um/sysrq_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/sysrq_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/utsname.h>
+#include <asm/current.h>
+#include <asm/ptrace.h>
+#include "sysrq.h"
+
+void __show_regs(struct pt_regs *regs)
+{
+	printk("\n");
+	print_modules();
+	printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
+		current->comm, print_tainted(), init_utsname()->release);
+	printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff,
+	       PT_REGS_RIP(regs));
+	printk(KERN_INFO "RSP: %016lx  EFLAGS: %08lx\n", PT_REGS_SP(regs),
+	       PT_REGS_EFLAGS(regs));
+	printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
+	       PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs));
+	printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
+	       PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs));
+	printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
+	       PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs));
+	printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
+	       PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs));
+	printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
+	       PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs));
+}
+
+void show_regs(struct pt_regs *regs)
+{
+	__show_regs(regs);
+	show_trace(current, (unsigned long *) &regs);
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/tls_32.c linux-libre-3.2-gnu/arch/x86/um/tls_32.c
--- linux-libre-3.1-gnu/arch/x86/um/tls_32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/tls_32.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2005 Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
+ * Licensed under the GPL
+ */
+
+#include "linux/percpu.h"
+#include "linux/sched.h"
+#include "asm/uaccess.h"
+#include "os.h"
+#include "skas.h"
+#include "sysdep/tls.h"
+
+/*
+ * If needed we can detect when it's uninitialized.
+ *
+ * These are initialized in an initcall and unchanged thereafter.
+ */
+static int host_supports_tls = -1;
+int host_gdt_entry_tls_min;
+
+int do_set_thread_area(struct user_desc *info)
+{
+	int ret;
+	u32 cpu;
+
+	cpu = get_cpu();
+	ret = os_set_thread_area(info, userspace_pid[cpu]);
+	put_cpu();
+
+	if (ret)
+		printk(KERN_ERR "PTRACE_SET_THREAD_AREA failed, err = %d, "
+		       "index = %d\n", ret, info->entry_number);
+
+	return ret;
+}
+
+int do_get_thread_area(struct user_desc *info)
+{
+	int ret;
+	u32 cpu;
+
+	cpu = get_cpu();
+	ret = os_get_thread_area(info, userspace_pid[cpu]);
+	put_cpu();
+
+	if (ret)
+		printk(KERN_ERR "PTRACE_GET_THREAD_AREA failed, err = %d, "
+		       "index = %d\n", ret, info->entry_number);
+
+	return ret;
+}
+
+/*
+ * sys_get_thread_area: get a yet unused TLS descriptor index.
+ * XXX: Consider leaving one free slot for glibc usage at first place. This must
+ * be done here (and by changing GDT_ENTRY_TLS_* macros) and nowhere else.
+ *
+ * Also, this must be tested when compiling in SKAS mode with dynamic linking
+ * and running against NPTL.
+ */
+static int get_free_idx(struct task_struct* task)
+{
+	struct thread_struct *t = &task->thread;
+	int idx;
+
+	if (!t->arch.tls_array)
+		return GDT_ENTRY_TLS_MIN;
+
+	for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
+		if (!t->arch.tls_array[idx].present)
+			return idx + GDT_ENTRY_TLS_MIN;
+	return -ESRCH;
+}
+
+static inline void clear_user_desc(struct user_desc* info)
+{
+	/* Postcondition: LDT_empty(info) returns true. */
+	memset(info, 0, sizeof(*info));
+
+	/*
+	 * Check the LDT_empty or the i386 sys_get_thread_area code - we obtain
+	 * indeed an empty user_desc.
+	 */
+	info->read_exec_only = 1;
+	info->seg_not_present = 1;
+}
+
+#define O_FORCE 1
+
+static int load_TLS(int flags, struct task_struct *to)
+{
+	int ret = 0;
+	int idx;
+
+	for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) {
+		struct uml_tls_struct* curr =
+			&to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN];
+
+		/*
+		 * Actually, now if it wasn't flushed it gets cleared and
+		 * flushed to the host, which will clear it.
+		 */
+		if (!curr->present) {
+			if (!curr->flushed) {
+				clear_user_desc(&curr->tls);
+				curr->tls.entry_number = idx;
+			} else {
+				WARN_ON(!LDT_empty(&curr->tls));
+				continue;
+			}
+		}
+
+		if (!(flags & O_FORCE) && curr->flushed)
+			continue;
+
+		ret = do_set_thread_area(&curr->tls);
+		if (ret)
+			goto out;
+
+		curr->flushed = 1;
+	}
+out:
+	return ret;
+}
+
+/*
+ * Verify if we need to do a flush for the new process, i.e. if there are any
+ * present desc's, only if they haven't been flushed.
+ */
+static inline int needs_TLS_update(struct task_struct *task)
+{
+	int i;
+	int ret = 0;
+
+	for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
+		struct uml_tls_struct* curr =
+			&task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
+
+		/*
+		 * Can't test curr->present, we may need to clear a descriptor
+		 * which had a value.
+		 */
+		if (curr->flushed)
+			continue;
+		ret = 1;
+		break;
+	}
+	return ret;
+}
+
+/*
+ * On a newly forked process, the TLS descriptors haven't yet been flushed. So
+ * we mark them as such and the first switch_to will do the job.
+ */
+void clear_flushed_tls(struct task_struct *task)
+{
+	int i;
+
+	for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
+		struct uml_tls_struct* curr =
+			&task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
+
+		/*
+		 * Still correct to do this, if it wasn't present on the host it
+		 * will remain as flushed as it was.
+		 */
+		if (!curr->present)
+			continue;
+
+		curr->flushed = 0;
+	}
+}
+
+/*
+ * In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a
+ * common host process. So this is needed in SKAS0 too.
+ *
+ * However, if each thread had a different host process (and this was discussed
+ * for SMP support) this won't be needed.
+ *
+ * And this will not need be used when (and if) we'll add support to the host
+ * SKAS patch.
+ */
+
+int arch_switch_tls(struct task_struct *to)
+{
+	if (!host_supports_tls)
+		return 0;
+
+	/*
+	 * We have no need whatsoever to switch TLS for kernel threads; beyond
+	 * that, that would also result in us calling os_set_thread_area with
+	 * userspace_pid[cpu] == 0, which gives an error.
+	 */
+	if (likely(to->mm))
+		return load_TLS(O_FORCE, to);
+
+	return 0;
+}
+
+static int set_tls_entry(struct task_struct* task, struct user_desc *info,
+			 int idx, int flushed)
+{
+	struct thread_struct *t = &task->thread;
+
+	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+		return -EINVAL;
+
+	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls = *info;
+	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present = 1;
+	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed = flushed;
+
+	return 0;
+}
+
+int arch_copy_tls(struct task_struct *new)
+{
+	struct user_desc info;
+	int idx, ret = -EFAULT;
+
+	if (copy_from_user(&info,
+			   (void __user *) UPT_ESI(&new->thread.regs.regs),
+			   sizeof(info)))
+		goto out;
+
+	ret = -EINVAL;
+	if (LDT_empty(&info))
+		goto out;
+
+	idx = info.entry_number;
+
+	ret = set_tls_entry(new, &info, idx, 0);
+out:
+	return ret;
+}
+
+/* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */
+static int get_tls_entry(struct task_struct *task, struct user_desc *info,
+			 int idx)
+{
+	struct thread_struct *t = &task->thread;
+
+	if (!t->arch.tls_array)
+		goto clear;
+
+	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+		return -EINVAL;
+
+	if (!t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present)
+		goto clear;
+
+	*info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls;
+
+out:
+	/*
+	 * Temporary debugging check, to make sure that things have been
+	 * flushed. This could be triggered if load_TLS() failed.
+	 */
+	if (unlikely(task == current &&
+		     !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) {
+		printk(KERN_ERR "get_tls_entry: task with pid %d got here "
+				"without flushed TLS.", current->pid);
+	}
+
+	return 0;
+clear:
+	/*
+	 * When the TLS entry has not been set, the values read to user in the
+	 * tls_array are 0 (because it's cleared at boot, see
+	 * arch/i386/kernel/head.S:cpu_gdt_table). Emulate that.
+	 */
+	clear_user_desc(info);
+	info->entry_number = idx;
+	goto out;
+}
+
+int sys_set_thread_area(struct user_desc __user *user_desc)
+{
+	struct user_desc info;
+	int idx, ret;
+
+	if (!host_supports_tls)
+		return -ENOSYS;
+
+	if (copy_from_user(&info, user_desc, sizeof(info)))
+		return -EFAULT;
+
+	idx = info.entry_number;
+
+	if (idx == -1) {
+		idx = get_free_idx(current);
+		if (idx < 0)
+			return idx;
+		info.entry_number = idx;
+		/* Tell the user which slot we chose for him.*/
+		if (put_user(idx, &user_desc->entry_number))
+			return -EFAULT;
+	}
+
+	ret = do_set_thread_area(&info);
+	if (ret)
+		return ret;
+	return set_tls_entry(current, &info, idx, 1);
+}
+
+/*
+ * Perform set_thread_area on behalf of the traced child.
+ * Note: error handling is not done on the deferred load, and this differ from
+ * i386. However the only possible error are caused by bugs.
+ */
+int ptrace_set_thread_area(struct task_struct *child, int idx,
+			   struct user_desc __user *user_desc)
+{
+	struct user_desc info;
+
+	if (!host_supports_tls)
+		return -EIO;
+
+	if (copy_from_user(&info, user_desc, sizeof(info)))
+		return -EFAULT;
+
+	return set_tls_entry(child, &info, idx, 0);
+}
+
+int sys_get_thread_area(struct user_desc __user *user_desc)
+{
+	struct user_desc info;
+	int idx, ret;
+
+	if (!host_supports_tls)
+		return -ENOSYS;
+
+	if (get_user(idx, &user_desc->entry_number))
+		return -EFAULT;
+
+	ret = get_tls_entry(current, &info, idx);
+	if (ret < 0)
+		goto out;
+
+	if (copy_to_user(user_desc, &info, sizeof(info)))
+		ret = -EFAULT;
+
+out:
+	return ret;
+}
+
+/*
+ * Perform get_thread_area on behalf of the traced child.
+ */
+int ptrace_get_thread_area(struct task_struct *child, int idx,
+		struct user_desc __user *user_desc)
+{
+	struct user_desc info;
+	int ret;
+
+	if (!host_supports_tls)
+		return -EIO;
+
+	ret = get_tls_entry(child, &info, idx);
+	if (ret < 0)
+		goto out;
+
+	if (copy_to_user(user_desc, &info, sizeof(info)))
+		ret = -EFAULT;
+out:
+	return ret;
+}
+
+/*
+ * This code is really i386-only, but it detects and logs x86_64 GDT indexes
+ * if a 32-bit UML is running on a 64-bit host.
+ */
+static int __init __setup_host_supports_tls(void)
+{
+	check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min);
+	if (host_supports_tls) {
+		printk(KERN_INFO "Host TLS support detected\n");
+		printk(KERN_INFO "Detected host type: ");
+		switch (host_gdt_entry_tls_min) {
+		case GDT_ENTRY_TLS_MIN_I386:
+			printk(KERN_CONT "i386");
+			break;
+		case GDT_ENTRY_TLS_MIN_X86_64:
+			printk(KERN_CONT "x86_64");
+			break;
+		}
+		printk(KERN_CONT " (GDT indexes %d to %d)\n",
+		       host_gdt_entry_tls_min,
+		       host_gdt_entry_tls_min + GDT_ENTRY_TLS_ENTRIES);
+	} else
+		printk(KERN_ERR "  Host TLS support NOT detected! "
+				"TLS support inside UML will not work\n");
+	return 0;
+}
+
+__initcall(__setup_host_supports_tls);
diff -druN linux-libre-3.1-gnu/arch/x86/um/tls_64.c linux-libre-3.2-gnu/arch/x86/um/tls_64.c
--- linux-libre-3.1-gnu/arch/x86/um/tls_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/tls_64.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,17 @@
+#include "linux/sched.h"
+
+void clear_flushed_tls(struct task_struct *task)
+{
+}
+
+int arch_copy_tls(struct task_struct *t)
+{
+	/*
+	 * If CLONE_SETTLS is set, we need to save the thread id
+	 * (which is argument 5, child_tid, of clone) so it can be set
+	 * during context switches.
+	 */
+	t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)];
+
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/user-offsets.c linux-libre-3.2-gnu/arch/x86/um/user-offsets.c
--- linux-libre-3.1-gnu/arch/x86/um/user-offsets.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/user-offsets.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,80 @@
+#include <stdio.h>
+#include <stddef.h>
+#include <signal.h>
+#include <sys/poll.h>
+#include <sys/mman.h>
+#include <sys/user.h>
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
+#include <asm/types.h>
+
+#define DEFINE(sym, val) \
+	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define DEFINE_LONGS(sym, val) \
+	asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
+
+void foo(void)
+{
+#ifdef __i386__
+	DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct));
+	DEFINE_LONGS(HOST_FPX_SIZE, sizeof(struct user_fpxregs_struct));
+
+	DEFINE(HOST_IP, EIP);
+	DEFINE(HOST_SP, UESP);
+	DEFINE(HOST_EFLAGS, EFL);
+	DEFINE(HOST_AX, EAX);
+	DEFINE(HOST_BX, EBX);
+	DEFINE(HOST_CX, ECX);
+	DEFINE(HOST_DX, EDX);
+	DEFINE(HOST_SI, ESI);
+	DEFINE(HOST_DI, EDI);
+	DEFINE(HOST_BP, EBP);
+	DEFINE(HOST_CS, CS);
+	DEFINE(HOST_SS, SS);
+	DEFINE(HOST_DS, DS);
+	DEFINE(HOST_FS, FS);
+	DEFINE(HOST_ES, ES);
+	DEFINE(HOST_GS, GS);
+	DEFINE(HOST_ORIG_AX, ORIG_EAX);
+#else
+	DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long));
+	DEFINE_LONGS(HOST_BX, RBX);
+	DEFINE_LONGS(HOST_CX, RCX);
+	DEFINE_LONGS(HOST_DI, RDI);
+	DEFINE_LONGS(HOST_SI, RSI);
+	DEFINE_LONGS(HOST_DX, RDX);
+	DEFINE_LONGS(HOST_BP, RBP);
+	DEFINE_LONGS(HOST_AX, RAX);
+	DEFINE_LONGS(HOST_R8, R8);
+	DEFINE_LONGS(HOST_R9, R9);
+	DEFINE_LONGS(HOST_R10, R10);
+	DEFINE_LONGS(HOST_R11, R11);
+	DEFINE_LONGS(HOST_R12, R12);
+	DEFINE_LONGS(HOST_R13, R13);
+	DEFINE_LONGS(HOST_R14, R14);
+	DEFINE_LONGS(HOST_R15, R15);
+	DEFINE_LONGS(HOST_ORIG_AX, ORIG_RAX);
+	DEFINE_LONGS(HOST_CS, CS);
+	DEFINE_LONGS(HOST_SS, SS);
+	DEFINE_LONGS(HOST_EFLAGS, EFLAGS);
+#if 0
+	DEFINE_LONGS(HOST_FS, FS);
+	DEFINE_LONGS(HOST_GS, GS);
+	DEFINE_LONGS(HOST_DS, DS);
+	DEFINE_LONGS(HOST_ES, ES);
+#endif
+
+	DEFINE_LONGS(HOST_IP, RIP);
+	DEFINE_LONGS(HOST_SP, RSP);
+#endif
+
+	DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
+	DEFINE(UM_POLLIN, POLLIN);
+	DEFINE(UM_POLLPRI, POLLPRI);
+	DEFINE(UM_POLLOUT, POLLOUT);
+
+	DEFINE(UM_PROT_READ, PROT_READ);
+	DEFINE(UM_PROT_WRITE, PROT_WRITE);
+	DEFINE(UM_PROT_EXEC, PROT_EXEC);
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/vdso/checkundef.sh linux-libre-3.2-gnu/arch/x86/um/vdso/checkundef.sh
--- linux-libre-3.1-gnu/arch/x86/um/vdso/checkundef.sh	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/vdso/checkundef.sh	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,10 @@
+#!/bin/sh
+nm="$1"
+file="$2"
+$nm "$file" | grep '^ *U' > /dev/null 2>&1
+if [ $? -eq 1 ]; then
+    exit 0
+else
+    echo "$file: undefined symbols found" >&2
+    exit 1
+fi
diff -druN linux-libre-3.1-gnu/arch/x86/um/vdso/Makefile linux-libre-3.2-gnu/arch/x86/um/vdso/Makefile
--- linux-libre-3.1-gnu/arch/x86/um/vdso/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/vdso/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,90 @@
+#
+# Building vDSO images for x86.
+#
+
+VDSO64-y		:= y
+
+vdso-install-$(VDSO64-y)	+= vdso.so
+
+
+# files to link into the vdso
+vobjs-y := vdso-note.o um_vdso.o
+
+# files to link into kernel
+obj-$(VDSO64-y)			+= vdso.o vma.o
+
+vobjs := $(foreach F,$(vobjs-y),$(obj)/$F)
+
+$(obj)/vdso.o: $(obj)/vdso.so
+
+targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
+
+export CPPFLAGS_vdso.lds += -P -C
+
+VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
+       -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
+
+$(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
+
+$(obj)/vdso.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
+	$(call if_changed,vdso)
+
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
+	$(call if_changed,objcopy)
+
+#
+# Don't omit frame pointers for ease of userspace debugging, but do
+# optimize sibling calls.
+#
+CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \
+       $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \
+       -fno-omit-frame-pointer -foptimize-sibling-calls
+
+$(vobjs): KBUILD_CFLAGS += $(CFL)
+
+#
+# vDSO code runs in userspace and -pg doesn't help with profiling anyway.
+#
+CFLAGS_REMOVE_vdso-note.o = -pg -fprofile-arcs -ftest-coverage
+CFLAGS_REMOVE_um_vdso.o = -pg -fprofile-arcs -ftest-coverage
+
+targets += vdso-syms.lds
+obj-$(VDSO64-y)			+= vdso-syms.lds
+
+#
+# Match symbols in the DSO that look like VDSO*; produce a file of constants.
+#
+sed-vdsosym := -e 's/^00*/0/' \
+	-e 's/^\([0-9a-fA-F]*\) . \(VDSO[a-zA-Z0-9_]*\)$$/\2 = 0x\1;/p'
+quiet_cmd_vdsosym = VDSOSYM $@
+define cmd_vdsosym
+	$(NM) $< | LC_ALL=C sed -n $(sed-vdsosym) | LC_ALL=C sort > $@
+endef
+
+$(obj)/%-syms.lds: $(obj)/%.so.dbg FORCE
+	$(call if_changed,vdsosym)
+
+#
+# The DSO images are built using a special linker script.
+#
+quiet_cmd_vdso = VDSO    $@
+      cmd_vdso = $(CC) -nostdlib -o $@ \
+		       $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
+		       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
+		 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
+
+VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+GCOV_PROFILE := n
+
+#
+# Install the unstripped copy of vdso*.so listed in $(vdso-install-y).
+#
+quiet_cmd_vdso_install = INSTALL $@
+      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+$(vdso-install-y): %.so: $(obj)/%.so.dbg FORCE
+	@mkdir -p $(MODLIB)/vdso
+	$(call cmd,vdso_install)
+
+PHONY += vdso_install $(vdso-install-y)
+vdso_install: $(vdso-install-y)
diff -druN linux-libre-3.1-gnu/arch/x86/um/vdso/um_vdso.c linux-libre-3.2-gnu/arch/x86/um/vdso/um_vdso.c
--- linux-libre-3.1-gnu/arch/x86/um/vdso/um_vdso.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/vdso/um_vdso.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ *
+ * This program is free software; you can 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 vDSO turns all calls into a syscall so that UML can trap them.
+ */
+
+
+/* Disable profiling for userspace code */
+#define DISABLE_BRANCH_PROFILING
+
+#include <linux/time.h>
+#include <linux/getcpu.h>
+#include <asm/unistd.h>
+
+int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
+{
+	long ret;
+
+	asm("syscall" : "=a" (ret) :
+		"0" (__NR_clock_gettime), "D" (clock), "S" (ts) : "memory");
+
+	return ret;
+}
+int clock_gettime(clockid_t, struct timespec *)
+	__attribute__((weak, alias("__vdso_clock_gettime")));
+
+int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+	long ret;
+
+	asm("syscall" : "=a" (ret) :
+		"0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory");
+
+	return ret;
+}
+int gettimeofday(struct timeval *, struct timezone *)
+	__attribute__((weak, alias("__vdso_gettimeofday")));
+
+time_t __vdso_time(time_t *t)
+{
+	long secs;
+
+	asm volatile("syscall"
+		: "=a" (secs)
+		: "0" (__NR_time), "D" (t) : "cc", "r11", "cx", "memory");
+
+	return secs;
+}
+int time(time_t *t) __attribute__((weak, alias("__vdso_time")));
+
+long
+__vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused)
+{
+	/*
+	 * UML does not support SMP, we can cheat here. :)
+	 */
+
+	if (cpu)
+		*cpu = 0;
+	if (node)
+		*node = 0;
+
+	return 0;
+}
+
+long getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
+	__attribute__((weak, alias("__vdso_getcpu")));
diff -druN linux-libre-3.1-gnu/arch/x86/um/vdso/vdso-layout.lds.S linux-libre-3.2-gnu/arch/x86/um/vdso/vdso-layout.lds.S
--- linux-libre-3.1-gnu/arch/x86/um/vdso/vdso-layout.lds.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/vdso/vdso-layout.lds.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,64 @@
+/*
+ * Linker script for vDSO.  This is an ELF shared object prelinked to
+ * its virtual address, and with only one read-only segment.
+ * This script controls its layout.
+ */
+
+SECTIONS
+{
+	. = VDSO_PRELINK + SIZEOF_HEADERS;
+
+	.hash		: { *(.hash) }			:text
+	.gnu.hash	: { *(.gnu.hash) }
+	.dynsym		: { *(.dynsym) }
+	.dynstr		: { *(.dynstr) }
+	.gnu.version	: { *(.gnu.version) }
+	.gnu.version_d	: { *(.gnu.version_d) }
+	.gnu.version_r	: { *(.gnu.version_r) }
+
+	.note		: { *(.note.*) }		:text	:note
+
+	.eh_frame_hdr	: { *(.eh_frame_hdr) }		:text	:eh_frame_hdr
+	.eh_frame	: { KEEP (*(.eh_frame)) }	:text
+
+	.dynamic	: { *(.dynamic) }		:text	:dynamic
+
+	.rodata		: { *(.rodata*) }		:text
+	.data		: {
+	      *(.data*)
+	      *(.sdata*)
+	      *(.got.plt) *(.got)
+	      *(.gnu.linkonce.d.*)
+	      *(.bss*)
+	      *(.dynbss*)
+	      *(.gnu.linkonce.b.*)
+	}
+
+	.altinstructions	: { *(.altinstructions) }
+	.altinstr_replacement	: { *(.altinstr_replacement) }
+
+	/*
+	 * Align the actual code well away from the non-instruction data.
+	 * This is the best thing for the I-cache.
+	 */
+	. = ALIGN(0x100);
+
+	.text		: { *(.text*) }			:text	=0x90909090
+}
+
+/*
+ * Very old versions of ld do not recognize this name token; use the constant.
+ */
+#define PT_GNU_EH_FRAME	0x6474e550
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+	text		PT_LOAD		FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
+	dynamic		PT_DYNAMIC	FLAGS(4);		/* PF_R */
+	note		PT_NOTE		FLAGS(4);		/* PF_R */
+	eh_frame_hdr	PT_GNU_EH_FRAME;
+}
diff -druN linux-libre-3.1-gnu/arch/x86/um/vdso/vdso.lds.S linux-libre-3.2-gnu/arch/x86/um/vdso/vdso.lds.S
--- linux-libre-3.1-gnu/arch/x86/um/vdso/vdso.lds.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/vdso/vdso.lds.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,32 @@
+/*
+ * Linker script for 64-bit vDSO.
+ * We #include the file to define the layout details.
+ * Here we only choose the prelinked virtual address.
+ *
+ * This file defines the version script giving the user-exported symbols in
+ * the DSO.  We can define local symbols here called VDSO* to make their
+ * values visible using the asm-x86/vdso.h macros from the kernel proper.
+ */
+
+#define VDSO_PRELINK 0xffffffffff700000
+#include "vdso-layout.lds.S"
+
+/*
+ * This controls what userland symbols we export from the vDSO.
+ */
+VERSION {
+	LINUX_2.6 {
+	global:
+		clock_gettime;
+		__vdso_clock_gettime;
+		gettimeofday;
+		__vdso_gettimeofday;
+		getcpu;
+		__vdso_getcpu;
+		time;
+		__vdso_time;
+	local: *;
+	};
+}
+
+VDSO64_PRELINK = VDSO_PRELINK;
diff -druN linux-libre-3.1-gnu/arch/x86/um/vdso/vdso-note.S linux-libre-3.2-gnu/arch/x86/um/vdso/vdso-note.S
--- linux-libre-3.1-gnu/arch/x86/um/vdso/vdso-note.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/vdso/vdso-note.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,12 @@
+/*
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
+ * Here we can supply some information useful to userland.
+ */
+
+#include <linux/uts.h>
+#include <linux/version.h>
+#include <linux/elfnote.h>
+
+ELFNOTE_START(Linux, 0, "a")
+	.long LINUX_VERSION_CODE
+ELFNOTE_END
diff -druN linux-libre-3.1-gnu/arch/x86/um/vdso/vdso.S linux-libre-3.2-gnu/arch/x86/um/vdso/vdso.S
--- linux-libre-3.1-gnu/arch/x86/um/vdso/vdso.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/vdso/vdso.S	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,10 @@
+#include <linux/init.h>
+
+__INITDATA
+
+	.globl vdso_start, vdso_end
+vdso_start:
+	.incbin "arch/x86/um/vdso/vdso.so"
+vdso_end:
+
+__FINIT
diff -druN linux-libre-3.1-gnu/arch/x86/um/vdso/vma.c linux-libre-3.2-gnu/arch/x86/um/vdso/vma.c
--- linux-libre-3.1-gnu/arch/x86/um/vdso/vma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/arch/x86/um/vdso/vma.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ *
+ * This program is free software; you can 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/slab.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <linux/init.h>
+
+unsigned int __read_mostly vdso_enabled = 1;
+unsigned long um_vdso_addr;
+
+extern unsigned long task_size;
+extern char vdso_start[], vdso_end[];
+
+static struct page **vdsop;
+
+static int __init init_vdso(void)
+{
+	struct page *um_vdso;
+
+	BUG_ON(vdso_end - vdso_start > PAGE_SIZE);
+
+	um_vdso_addr = task_size - PAGE_SIZE;
+
+	vdsop = kmalloc(sizeof(struct page *), GFP_KERNEL);
+	if (!vdsop)
+		goto oom;
+
+	um_vdso = alloc_page(GFP_KERNEL);
+	if (!um_vdso) {
+		kfree(vdsop);
+
+		goto oom;
+	}
+
+	copy_page(page_address(um_vdso), vdso_start);
+	*vdsop = um_vdso;
+
+	return 0;
+
+oom:
+	printk(KERN_ERR "Cannot allocate vdso\n");
+	vdso_enabled = 0;
+
+	return -ENOMEM;
+}
+subsys_initcall(init_vdso);
+
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+	int err;
+	struct mm_struct *mm = current->mm;
+
+	if (!vdso_enabled)
+		return 0;
+
+	down_write(&mm->mmap_sem);
+
+	err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE,
+		VM_READ|VM_EXEC|
+		VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+		VM_ALWAYSDUMP,
+		vdsop);
+
+	up_write(&mm->mmap_sem);
+
+	return err;
+}
diff -druN linux-libre-3.1-gnu/arch/x86/vdso/vma.c linux-libre-3.2-gnu/arch/x86/vdso/vma.c
--- linux-libre-3.1-gnu/arch/x86/vdso/vma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/vdso/vma.c	2012-01-04 18:55:44.000000000 -0500
@@ -89,6 +89,15 @@
 	addr = start + (offset << PAGE_SHIFT);
 	if (addr >= end)
 		addr = end;
+
+	/*
+	 * page-align it here so that get_unmapped_area doesn't
+	 * align it wrongfully again to the next page. addr can come in 4K
+	 * unaligned here as a result of stack start randomization.
+	 */
+	addr = PAGE_ALIGN(addr);
+	addr = align_addr(addr, NULL, ALIGN_VDSO);
+
 	return addr;
 }
 
diff -druN linux-libre-3.1-gnu/arch/x86/video/fbdev.c linux-libre-3.2-gnu/arch/x86/video/fbdev.c
--- linux-libre-3.1-gnu/arch/x86/video/fbdev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/video/fbdev.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 #include <linux/fb.h>
 #include <linux/pci.h>
+#include <linux/module.h>
 
 int fb_is_primary_device(struct fb_info *info)
 {
diff -druN linux-libre-3.1-gnu/arch/x86/xen/enlighten.c linux-libre-3.2-gnu/arch/x86/xen/enlighten.c
--- linux-libre-3.1-gnu/arch/x86/xen/enlighten.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/xen/enlighten.c	2012-01-04 18:55:44.000000000 -0500
@@ -251,6 +251,7 @@
 			~((1 << X86_FEATURE_APIC) |  /* disable local APIC */
 			  (1 << X86_FEATURE_ACPI));  /* disable ACPI */
 	ax = 1;
+	cx = 0;
 	xen_cpuid(&ax, &bx, &cx, &dx);
 
 	xsave_mask =
@@ -1355,7 +1356,7 @@
 	int cpu = (long)hcpu;
 	switch (action) {
 	case CPU_UP_PREPARE:
-		per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
+		xen_vcpu_setup(cpu);
 		if (xen_have_vector_callback)
 			xen_init_lock_cpu(cpu);
 		break;
@@ -1385,7 +1386,6 @@
 	xen_hvm_smp_init();
 	register_cpu_notifier(&xen_hvm_cpu_notifier);
 	xen_unplug_emulated_devices();
-	have_vcpu_info_placement = 0;
 	x86_init.irqs.intr_init = xen_init_IRQ;
 	xen_hvm_init_time_ops();
 	xen_hvm_init_mmu_ops();
diff -druN linux-libre-3.1-gnu/arch/x86/xen/grant-table.c linux-libre-3.2-gnu/arch/x86/xen/grant-table.c
--- linux-libre-3.1-gnu/arch/x86/xen/grant-table.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/xen/grant-table.c	2012-01-04 18:55:44.000000000 -0500
@@ -71,7 +71,7 @@
 
 	if (shared == NULL) {
 		struct vm_struct *area =
-			xen_alloc_vm_area(PAGE_SIZE * max_nr_gframes);
+			alloc_vm_area(PAGE_SIZE * max_nr_gframes, NULL);
 		BUG_ON(area == NULL);
 		shared = area->addr;
 		*__shared = shared;
diff -druN linux-libre-3.1-gnu/arch/x86/xen/Kconfig linux-libre-3.2-gnu/arch/x86/xen/Kconfig
--- linux-libre-3.1-gnu/arch/x86/xen/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/xen/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -25,8 +25,7 @@
 
 config XEN_PVHVM
 	def_bool y
-	depends on XEN
-	depends on X86_LOCAL_APIC
+	depends on XEN && PCI && X86_LOCAL_APIC
 
 config XEN_MAX_DOMAIN_MEMORY
        int
@@ -49,11 +48,3 @@
 	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-3.1-gnu/arch/x86/xen/mmu.c linux-libre-3.2-gnu/arch/x86/xen/mmu.c
--- linux-libre-3.1-gnu/arch/x86/xen/mmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/xen/mmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -495,41 +495,6 @@
 }
 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
-
 static pgd_t xen_make_pgd(pgdval_t pgd)
 {
 	pgd = pte_pfn_to_mfn(pgd);
@@ -1992,9 +1957,6 @@
 
 static void __init 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;
@@ -2404,17 +2366,3 @@
 	return err;
 }
 EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);
-
-#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,
-};
-#endif /* CONFIG_XEN_DEBUG_FS */
diff -druN linux-libre-3.1-gnu/arch/x86/xen/p2m.c linux-libre-3.2-gnu/arch/x86/xen/p2m.c
--- linux-libre-3.1-gnu/arch/x86/xen/p2m.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/xen/p2m.c	2012-01-04 18:55:44.000000000 -0500
@@ -161,7 +161,9 @@
 #include <asm/xen/page.h>
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
+#include <xen/grant_table.h>
 
+#include "multicalls.h"
 #include "xen-ops.h"
 
 static void __init m2p_override_init(void);
@@ -676,7 +678,8 @@
 }
 
 /* Add an MFN override for a particular page */
-int m2p_add_override(unsigned long mfn, struct page *page, bool clear_pte)
+int m2p_add_override(unsigned long mfn, struct page *page,
+		struct gnttab_map_grant_ref *kmap_op)
 {
 	unsigned long flags;
 	unsigned long pfn;
@@ -692,16 +695,28 @@
 					"m2p_add_override: pfn %lx not mapped", pfn))
 			return -EINVAL;
 	}
-
-	page->private = mfn;
+	WARN_ON(PagePrivate(page));
+	SetPagePrivate(page);
+	set_page_private(page, mfn);
 	page->index = pfn_to_mfn(pfn);
 
 	if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn))))
 		return -ENOMEM;
 
-	if (clear_pte && !PageHighMem(page))
-		/* Just zap old mapping for now */
-		pte_clear(&init_mm, address, ptep);
+	if (kmap_op != NULL) {
+		if (!PageHighMem(page)) {
+			struct multicall_space mcs =
+				xen_mc_entry(sizeof(*kmap_op));
+
+			MULTI_grant_table_op(mcs.mc,
+					GNTTABOP_map_grant_ref, kmap_op, 1);
+
+			xen_mc_issue(PARAVIRT_LAZY_MMU);
+		}
+		/* let's use dev_bus_addr to record the old mfn instead */
+		kmap_op->dev_bus_addr = page->index;
+		page->index = (unsigned long) kmap_op;
+	}
 	spin_lock_irqsave(&m2p_override_lock, flags);
 	list_add(&page->lru,  &m2p_overrides[mfn_hash(mfn)]);
 	spin_unlock_irqrestore(&m2p_override_lock, flags);
@@ -735,13 +750,56 @@
 	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);
+	WARN_ON(!PagePrivate(page));
+	ClearPagePrivate(page);
 
-	if (clear_pte && !PageHighMem(page))
-		set_pte_at(&init_mm, address, ptep,
-				pfn_pte(pfn, PAGE_KERNEL));
-		/* No tlb flush necessary because the caller already
-		 * left the pte unmapped. */
+	if (clear_pte) {
+		struct gnttab_map_grant_ref *map_op =
+			(struct gnttab_map_grant_ref *) page->index;
+		set_phys_to_machine(pfn, map_op->dev_bus_addr);
+		if (!PageHighMem(page)) {
+			struct multicall_space mcs;
+			struct gnttab_unmap_grant_ref *unmap_op;
+
+			/*
+			 * It might be that we queued all the m2p grant table
+			 * hypercalls in a multicall, then m2p_remove_override
+			 * get called before the multicall has actually been
+			 * issued. In this case handle is going to -1 because
+			 * it hasn't been modified yet.
+			 */
+			if (map_op->handle == -1)
+				xen_mc_flush();
+			/*
+			 * Now if map_op->handle is negative it means that the
+			 * hypercall actually returned an error.
+			 */
+			if (map_op->handle == GNTST_general_error) {
+				printk(KERN_WARNING "m2p_remove_override: "
+						"pfn %lx mfn %lx, failed to modify kernel mappings",
+						pfn, mfn);
+				return -1;
+			}
+
+			mcs = xen_mc_entry(
+					sizeof(struct gnttab_unmap_grant_ref));
+			unmap_op = mcs.args;
+			unmap_op->host_addr = map_op->host_addr;
+			unmap_op->handle = map_op->handle;
+			unmap_op->dev_bus_addr = 0;
+
+			MULTI_grant_table_op(mcs.mc,
+					GNTTABOP_unmap_grant_ref, unmap_op, 1);
+
+			xen_mc_issue(PARAVIRT_LAZY_MMU);
+
+			set_pte_at(&init_mm, address, ptep,
+					pfn_pte(pfn, PAGE_KERNEL));
+			__flush_tlb_single(address);
+			map_op->host_addr = 0;
+		}
+	} else
+		set_phys_to_machine(pfn, page->index);
 
 	return 0;
 }
@@ -758,7 +816,7 @@
 	spin_lock_irqsave(&m2p_override_lock, flags);
 
 	list_for_each_entry(p, bucket, lru) {
-		if (p->private == mfn) {
+		if (page_private(p) == mfn) {
 			ret = p;
 			break;
 		}
@@ -782,17 +840,21 @@
 EXPORT_SYMBOL_GPL(m2p_find_override_pfn);
 
 #ifdef CONFIG_XEN_DEBUG_FS
-
-int p2m_dump_show(struct seq_file *m, void *v)
+#include <linux/debugfs.h>
+#include "debugfs.h"
+static 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"};
+						"entry", "abnormal", "error"};
 #define TYPE_IDENTITY 0
 #define TYPE_MISSING 1
 #define TYPE_PFN 2
 #define TYPE_UNKNOWN 3
+	static const char * const type_name[] = {
+				[TYPE_IDENTITY] = "identity",
+				[TYPE_MISSING] = "missing",
+				[TYPE_PFN] = "pfn",
+				[TYPE_UNKNOWN] = "abnormal"};
 	unsigned long pfn, prev_pfn_type = 0, prev_pfn_level = 0;
 	unsigned int uninitialized_var(prev_level);
 	unsigned int uninitialized_var(prev_type);
@@ -856,4 +918,32 @@
 #undef TYPE_PFN
 #undef TYPE_UNKNOWN
 }
-#endif
+
+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_p2m_debugfs(void)
+{
+	struct dentry *d_xen = xen_init_debugfs();
+
+	if (d_xen == NULL)
+		return -ENOMEM;
+
+	d_mmu_debug = debugfs_create_dir("mmu", d_xen);
+
+	debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops);
+	return 0;
+}
+fs_initcall(xen_p2m_debugfs);
+#endif /* CONFIG_XEN_DEBUG_FS */
diff -druN linux-libre-3.1-gnu/arch/x86/xen/setup.c linux-libre-3.2-gnu/arch/x86/xen/setup.c
--- linux-libre-3.1-gnu/arch/x86/xen/setup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/xen/setup.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,7 +37,10 @@
 extern void xen_syscall32_target(void);
 
 /* Amount of extra memory space we add to the e820 ranges */
-phys_addr_t xen_extra_mem_start, xen_extra_mem_size;
+struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata;
+
+/* Number of pages released from the initial allocation. */
+unsigned long xen_released_pages;
 
 /* 
  * The maximum amount of extra memory compared to the base size.  The
@@ -51,48 +54,47 @@
  */
 #define EXTRA_MEM_RATIO		(10)
 
-static void __init xen_add_extra_mem(unsigned long pages)
+static void __init xen_add_extra_mem(u64 start, u64 size)
 {
 	unsigned long pfn;
+	int i;
 
-	u64 size = (u64)pages * PAGE_SIZE;
-	u64 extra_start = xen_extra_mem_start + xen_extra_mem_size;
-
-	if (!pages)
-		return;
-
-	e820_add_region(extra_start, size, E820_RAM);
-	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
-
-	memblock_x86_reserve_range(extra_start, extra_start + size, "XEN EXTRA");
+	for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) {
+		/* Add new region. */
+		if (xen_extra_mem[i].size == 0) {
+			xen_extra_mem[i].start = start;
+			xen_extra_mem[i].size  = size;
+			break;
+		}
+		/* Append to existing region. */
+		if (xen_extra_mem[i].start + xen_extra_mem[i].size == start) {
+			xen_extra_mem[i].size += size;
+			break;
+		}
+	}
+	if (i == XEN_EXTRA_MEM_MAX_REGIONS)
+		printk(KERN_WARNING "Warning: not enough extra memory regions\n");
 
-	xen_extra_mem_size += size;
+	memblock_x86_reserve_range(start, start + size, "XEN EXTRA");
 
-	xen_max_p2m_pfn = PFN_DOWN(extra_start + size);
+	xen_max_p2m_pfn = PFN_DOWN(start + size);
 
-	for (pfn = PFN_DOWN(extra_start); pfn <= xen_max_p2m_pfn; pfn++)
+	for (pfn = PFN_DOWN(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,
-					      phys_addr_t end_addr)
+static unsigned long __init xen_release_chunk(unsigned long start,
+					      unsigned long end)
 {
 	struct xen_memory_reservation reservation = {
 		.address_bits = 0,
 		.extent_order = 0,
 		.domid        = DOMID_SELF
 	};
-	unsigned long start, end;
 	unsigned long len = 0;
 	unsigned long pfn;
 	int ret;
 
-	start = PFN_UP(start_addr);
-	end = PFN_DOWN(end_addr);
-
-	if (end <= start)
-		return 0;
-
 	for(pfn = start; pfn < end; pfn++) {
 		unsigned long mfn = pfn_to_mfn(pfn);
 
@@ -117,72 +119,52 @@
 	return len;
 }
 
-static unsigned long __init xen_return_unused_memory(unsigned long max_pfn,
-						     const struct e820map *e820)
+static unsigned long __init xen_set_identity_and_release(
+	const struct e820entry *list, size_t map_size, unsigned long nr_pages)
 {
-	phys_addr_t max_addr = PFN_PHYS(max_pfn);
-	phys_addr_t last_end = ISA_END_ADDRESS;
+	phys_addr_t start = 0;
 	unsigned long released = 0;
-	int i;
-
-	/* Free any unused memory above the low 1Mbyte. */
-	for (i = 0; i < e820->nr_map && last_end < max_addr; i++) {
-		phys_addr_t end = e820->map[i].addr;
-		end = min(max_addr, end);
-
-		if (last_end < end)
-			released += xen_release_chunk(last_end, end);
-		last_end = max(last_end, e820->map[i].addr + e820->map[i].size);
-	}
-
-	if (last_end < max_addr)
-		released += xen_release_chunk(last_end, max_addr);
-
-	printk(KERN_INFO "released %lu pages of unused memory\n", released);
-	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;
+	const struct e820entry *entry;
 	int i;
 
+	/*
+	 * Combine non-RAM regions and gaps until a RAM region (or the
+	 * end of the map) is reached, then set the 1:1 map and
+	 * release the pages (if available) in those non-RAM regions.
+	 *
+	 * The combined non-RAM regions are rounded to a whole number
+	 * of pages so any partial pages are accessible via the 1:1
+	 * mapping.  This is needed for some BIOSes that put (for
+	 * example) the DMI tables in a reserved region that begins on
+	 * a non-page boundary.
+	 */
 	for (i = 0, entry = list; i < map_size; i++, entry++) {
-		phys_addr_t start = entry->addr;
-		phys_addr_t end = start + entry->size;
+		phys_addr_t end = entry->addr + entry->size;
 
-		if (start < last)
-			start = last;
+		if (entry->type == E820_RAM || i == map_size - 1) {
+			unsigned long start_pfn = PFN_DOWN(start);
+			unsigned long end_pfn = PFN_UP(end);
 
-		if (end <= start)
-			continue;
+			if (entry->type == E820_RAM)
+				end_pfn = PFN_UP(entry->addr);
 
-		/* Skip over the 1MB region. */
-		if (last > end)
-			continue;
+			if (start_pfn < end_pfn) {
+				if (start_pfn < nr_pages)
+					released += xen_release_chunk(
+						start_pfn, min(end_pfn, nr_pages));
 
-		if ((entry->type == E820_RAM) || (entry->type == E820_UNUSABLE)) {
-			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_pfn, end_pfn);
+			}
+			start = end;
 		}
-		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;
+
+	printk(KERN_INFO "Released %lu pages of unused memory\n", released);
+	printk(KERN_INFO "Set %ld page(s) to 1-1 mapping\n", identity);
+
+	return released;
 }
 
 static unsigned long __init xen_get_max_pages(void)
@@ -191,27 +173,50 @@
 	domid_t domid = DOMID_SELF;
 	int ret;
 
-	ret = HYPERVISOR_memory_op(XENMEM_maximum_reservation, &domid);
-	if (ret > 0)
-		max_pages = ret;
+	/*
+	 * For the initial domain we use the maximum reservation as
+	 * the maximum page.
+	 *
+	 * For guest domains the current maximum reservation reflects
+	 * the current maximum rather than the static maximum. In this
+	 * case the e820 map provided to us will cover the static
+	 * maximum region.
+	 */
+	if (xen_initial_domain()) {
+		ret = HYPERVISOR_memory_op(XENMEM_maximum_reservation, &domid);
+		if (ret > 0)
+			max_pages = ret;
+	}
+
 	return min(max_pages, MAX_DOMAIN_PAGES);
 }
 
+static void xen_align_and_add_e820_region(u64 start, u64 size, int type)
+{
+	u64 end = start + size;
+
+	/* Align RAM regions to page boundaries. */
+	if (type == E820_RAM) {
+		start = PAGE_ALIGN(start);
+		end &= ~((u64)PAGE_SIZE - 1);
+	}
+
+	e820_add_region(start, end - start, type);
+}
+
 /**
  * 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;
 	int rc;
 	struct xen_memory_map memmap;
+	unsigned long max_pages;
 	unsigned long extra_pages = 0;
-	unsigned long extra_limit;
-	unsigned long identity_pages = 0;
 	int i;
 	int op;
 
@@ -237,58 +242,65 @@
 	}
 	BUG_ON(rc);
 
-	memcpy(map_raw, map, sizeof(map));
-	e820.nr_map = 0;
-	xen_extra_mem_start = mem_end;
-	for (i = 0; i < memmap.nr_entries; i++) {
-		unsigned long long end;
+	/* Make sure the Xen-supplied memory map is well-ordered. */
+	sanitize_e820_map(map, memmap.nr_entries, &memmap.nr_entries);
 
-		/* Guard against non-page aligned E820 entries. */
-		if (map[i].type == E820_RAM)
-			map[i].size -= (map[i].size + map[i].addr) % PAGE_SIZE;
+	max_pages = xen_get_max_pages();
+	if (max_pages > max_pfn)
+		extra_pages += max_pages - max_pfn;
 
-		end = map[i].addr + map[i].size;
-		if (map[i].type == E820_RAM && end > mem_end) {
-			/* RAM off the end - may be partially included */
-			u64 delta = min(map[i].size, end - mem_end);
+	/*
+	 * Set P2M for all non-RAM pages and E820 gaps to be identity
+	 * type PFNs.  Any RAM pages that would be made inaccesible by
+	 * this are first released.
+	 */
+	xen_released_pages = xen_set_identity_and_release(
+		map, memmap.nr_entries, max_pfn);
+	extra_pages += xen_released_pages;
 
-			map[i].size -= delta;
-			end -= delta;
+	/*
+	 * Clamp the amount of extra memory to a EXTRA_MEM_RATIO
+	 * factor the base size.  On non-highmem systems, the base
+	 * size is the full initial memory allocation; on highmem it
+	 * is limited to the max size of lowmem, so that it doesn't
+	 * get completely filled.
+	 *
+	 * In principle there could be a problem in lowmem systems if
+	 * the initial memory is also very large with respect to
+	 * lowmem, but we won't try to deal with that here.
+	 */
+	extra_pages = min(EXTRA_MEM_RATIO * min(max_pfn, PFN_DOWN(MAXMEM)),
+			  extra_pages);
 
-			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);
+	i = 0;
+	while (i < memmap.nr_entries) {
+		u64 addr = map[i].addr;
+		u64 size = map[i].size;
+		u32 type = map[i].type;
+
+		if (type == E820_RAM) {
+			if (addr < mem_end) {
+				size = min(size, mem_end - addr);
+			} else if (extra_pages) {
+				size = min(size, (u64)extra_pages * PAGE_SIZE);
+				extra_pages -= size / PAGE_SIZE;
+				xen_add_extra_mem(addr, size);
+			} else
+				type = E820_UNUSABLE;
 		}
 
-		if (map[i].size > 0 && end > xen_extra_mem_start)
-			xen_extra_mem_start = end;
+		xen_align_and_add_e820_region(addr, size, type);
 
-		/* Add region if any remains */
-		if (map[i].size > 0)
-			e820_add_region(map[i].addr, map[i].size, map[i].type);
+		map[i].addr += size;
+		map[i].size -= size;
+		if (map[i].size == 0)
+			i++;
 	}
-	/* Align the balloon area so that max_low_pfn does not get set
-	 * to be at the _end_ of the PCI gap at the far end (fee01000).
-	 * Note that xen_extra_mem_start gets set in the loop above to be
-	 * past the last E820 region. */
-	if (xen_initial_domain() && (xen_extra_mem_start < (1ULL<<32)))
-		xen_extra_mem_start = (1ULL<<32);
 
 	/*
 	 * In domU, the ISA region is normal, usable memory, but we
 	 * reserve ISA memory anyway because too many things poke
 	 * about in there.
-	 *
-	 * In Dom0, the host E820 information can leave gaps in the
-	 * ISA range, which would cause us to release those pages.  To
-	 * avoid this, we unconditionally reserve them here.
 	 */
 	e820_add_region(ISA_START_ADDRESS, ISA_END_ADDRESS - ISA_START_ADDRESS,
 			E820_RESERVED);
@@ -305,44 +317,6 @@
 
 	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 
-	extra_limit = xen_get_max_pages();
-	if (max_pfn + extra_pages > extra_limit) {
-		if (extra_limit > max_pfn)
-			extra_pages = extra_limit - max_pfn;
-		else
-			extra_pages = 0;
-	}
-
-	extra_pages += xen_return_unused_memory(xen_start_info->nr_pages, &e820);
-
-	/*
-	 * Clamp the amount of extra memory to a EXTRA_MEM_RATIO
-	 * factor the base size.  On non-highmem systems, the base
-	 * size is the full initial memory allocation; on highmem it
-	 * is limited to the max size of lowmem, so that it doesn't
-	 * get completely filled.
-	 *
-	 * In principle there could be a problem in lowmem systems if
-	 * the initial memory is also very large with respect to
-	 * lowmem, but we won't try to deal with that here.
-	 */
-	extra_limit = min(EXTRA_MEM_RATIO * min(max_pfn, PFN_DOWN(MAXMEM)),
-			  max_pfn + extra_pages);
-
-	if (extra_limit >= max_pfn)
-		extra_pages = extra_limit - max_pfn;
-	else
-		extra_pages = 0;
-
-	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";
 }
 
@@ -448,6 +422,6 @@
 #endif
 	disable_cpuidle();
 	boot_option_idle_override = IDLE_HALT;
-
+	WARN_ON(set_pm_idle_to_default());
 	fiddle_vdso();
 }
diff -druN linux-libre-3.1-gnu/arch/x86/xen/time.c linux-libre-3.2-gnu/arch/x86/xen/time.c
--- linux-libre-3.1-gnu/arch/x86/xen/time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/x86/xen/time.c	2012-01-04 18:55:44.000000000 -0500
@@ -201,8 +201,22 @@
 
 static int xen_set_wallclock(unsigned long now)
 {
+	struct xen_platform_op op;
+	int rc;
+
 	/* do nothing for domU */
-	return -1;
+	if (!xen_initial_domain())
+		return -1;
+
+	op.cmd = XENPF_settime;
+	op.u.settime.secs = now;
+	op.u.settime.nsecs = 0;
+	op.u.settime.system_time = xen_clocksource_read();
+
+	rc = HYPERVISOR_dom0_op(&op);
+	WARN(rc != 0, "XENPF_settime failed: now=%ld\n", now);
+
+	return rc;
 }
 
 static struct clocksource xen_clocksource __read_mostly = {
diff -druN linux-libre-3.1-gnu/arch/xtensa/configs/iss_defconfig linux-libre-3.2-gnu/arch/xtensa/configs/iss_defconfig
--- linux-libre-3.1-gnu/arch/xtensa/configs/iss_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/xtensa/configs/iss_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,6 @@
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_NO_IOPORT=y
 CONFIG_HZ=100
-CONFIG_GENERIC_TIME=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 CONFIG_CONSTRUCTORS=y
 
diff -druN linux-libre-3.1-gnu/arch/xtensa/configs/s6105_defconfig linux-libre-3.2-gnu/arch/xtensa/configs/s6105_defconfig
--- linux-libre-3.1-gnu/arch/xtensa/configs/s6105_defconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/xtensa/configs/s6105_defconfig	2012-01-04 18:55:44.000000000 -0500
@@ -15,7 +15,6 @@
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_NO_IOPORT=y
 CONFIG_HZ=100
-CONFIG_GENERIC_TIME=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
diff -druN linux-libre-3.1-gnu/arch/xtensa/platforms/iss/network.c linux-libre-3.2-gnu/arch/xtensa/platforms/iss/network.c
--- linux-libre-3.1-gnu/arch/xtensa/platforms/iss/network.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/arch/xtensa/platforms/iss/network.c	2012-01-04 18:55:44.000000000 -0500
@@ -633,7 +633,7 @@
 	.ndo_set_mac_address	= iss_net_set_mac,
 	//.ndo_do_ioctl		= iss_net_ioctl,
 	.ndo_tx_timeout		= iss_net_tx_timeout,
-	.ndo_set_multicast_list = iss_net_set_multicast_list,
+	.ndo_set_rx_mode	= iss_net_set_multicast_list,
 };
 
 static int iss_net_configure(int index, char *init)
diff -druN linux-libre-3.1-gnu/block/blk-cgroup.c linux-libre-3.2-gnu/block/blk-cgroup.c
--- linux-libre-3.1-gnu/block/blk-cgroup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/block/blk-cgroup.c	2012-01-04 18:55:44.000000000 -0500
@@ -768,25 +768,14 @@
 	return disk_total;
 }
 
-static int blkio_check_dev_num(dev_t dev)
-{
-	int part = 0;
-	struct gendisk *disk;
-
-	disk = get_gendisk(dev, &part);
-	if (!disk || part)
-		return -ENODEV;
-
-	return 0;
-}
-
 static int blkio_policy_parse_and_set(char *buf,
 	struct blkio_policy_node *newpn, enum blkio_policy_id plid, int fileid)
 {
+	struct gendisk *disk = NULL;
 	char *s[4], *p, *major_s = NULL, *minor_s = NULL;
-	int ret;
 	unsigned long major, minor;
-	int i = 0;
+	int i = 0, ret = -EINVAL;
+	int part;
 	dev_t dev;
 	u64 temp;
 
@@ -804,37 +793,36 @@
 	}
 
 	if (i != 2)
-		return -EINVAL;
+		goto out;
 
 	p = strsep(&s[0], ":");
 	if (p != NULL)
 		major_s = p;
 	else
-		return -EINVAL;
+		goto out;
 
 	minor_s = s[0];
 	if (!minor_s)
-		return -EINVAL;
+		goto out;
 
-	ret = strict_strtoul(major_s, 10, &major);
-	if (ret)
-		return -EINVAL;
+	if (strict_strtoul(major_s, 10, &major))
+		goto out;
 
-	ret = strict_strtoul(minor_s, 10, &minor);
-	if (ret)
-		return -EINVAL;
+	if (strict_strtoul(minor_s, 10, &minor))
+		goto out;
 
 	dev = MKDEV(major, minor);
 
-	ret = strict_strtoull(s[1], 10, &temp);
-	if (ret)
-		return -EINVAL;
+	if (strict_strtoull(s[1], 10, &temp))
+		goto out;
 
 	/* For rule removal, do not check for device presence. */
 	if (temp) {
-		ret = blkio_check_dev_num(dev);
-		if (ret)
-			return ret;
+		disk = get_gendisk(dev, &part);
+		if (!disk || part) {
+			ret = -ENODEV;
+			goto out;
+		}
 	}
 
 	newpn->dev = dev;
@@ -843,7 +831,7 @@
 	case BLKIO_POLICY_PROP:
 		if ((temp < BLKIO_WEIGHT_MIN && temp > 0) ||
 		     temp > BLKIO_WEIGHT_MAX)
-			return -EINVAL;
+			goto out;
 
 		newpn->plid = plid;
 		newpn->fileid = fileid;
@@ -860,7 +848,7 @@
 		case BLKIO_THROTL_read_iops_device:
 		case BLKIO_THROTL_write_iops_device:
 			if (temp > THROTL_IOPS_MAX)
-				return -EINVAL;
+				goto out;
 
 			newpn->plid = plid;
 			newpn->fileid = fileid;
@@ -871,68 +859,96 @@
 	default:
 		BUG();
 	}
-
-	return 0;
+	ret = 0;
+out:
+	put_disk(disk);
+	return ret;
 }
 
 unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg,
 			      dev_t dev)
 {
 	struct blkio_policy_node *pn;
+	unsigned long flags;
+	unsigned int weight;
+
+	spin_lock_irqsave(&blkcg->lock, flags);
 
 	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_PROP,
 				BLKIO_PROP_weight_device);
 	if (pn)
-		return pn->val.weight;
+		weight = pn->val.weight;
 	else
-		return blkcg->weight;
+		weight = blkcg->weight;
+
+	spin_unlock_irqrestore(&blkcg->lock, flags);
+
+	return weight;
 }
 EXPORT_SYMBOL_GPL(blkcg_get_weight);
 
 uint64_t blkcg_get_read_bps(struct blkio_cgroup *blkcg, dev_t dev)
 {
 	struct blkio_policy_node *pn;
+	unsigned long flags;
+	uint64_t bps = -1;
 
+	spin_lock_irqsave(&blkcg->lock, flags);
 	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
 				BLKIO_THROTL_read_bps_device);
 	if (pn)
-		return pn->val.bps;
-	else
-		return -1;
+		bps = pn->val.bps;
+	spin_unlock_irqrestore(&blkcg->lock, flags);
+
+	return bps;
 }
 
 uint64_t blkcg_get_write_bps(struct blkio_cgroup *blkcg, dev_t dev)
 {
 	struct blkio_policy_node *pn;
+	unsigned long flags;
+	uint64_t bps = -1;
+
+	spin_lock_irqsave(&blkcg->lock, flags);
 	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
 				BLKIO_THROTL_write_bps_device);
 	if (pn)
-		return pn->val.bps;
-	else
-		return -1;
+		bps = pn->val.bps;
+	spin_unlock_irqrestore(&blkcg->lock, flags);
+
+	return bps;
 }
 
 unsigned int blkcg_get_read_iops(struct blkio_cgroup *blkcg, dev_t dev)
 {
 	struct blkio_policy_node *pn;
+	unsigned long flags;
+	unsigned int iops = -1;
 
+	spin_lock_irqsave(&blkcg->lock, flags);
 	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
 				BLKIO_THROTL_read_iops_device);
 	if (pn)
-		return pn->val.iops;
-	else
-		return -1;
+		iops = pn->val.iops;
+	spin_unlock_irqrestore(&blkcg->lock, flags);
+
+	return iops;
 }
 
 unsigned int blkcg_get_write_iops(struct blkio_cgroup *blkcg, dev_t dev)
 {
 	struct blkio_policy_node *pn;
+	unsigned long flags;
+	unsigned int iops = -1;
+
+	spin_lock_irqsave(&blkcg->lock, flags);
 	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
 				BLKIO_THROTL_write_iops_device);
 	if (pn)
-		return pn->val.iops;
-	else
-		return -1;
+		iops = pn->val.iops;
+	spin_unlock_irqrestore(&blkcg->lock, flags);
+
+	return iops;
 }
 
 /* Checks whether user asked for deleting a policy rule */
@@ -1085,6 +1101,7 @@
 
 	if (blkio_delete_rule_command(newpn)) {
 		blkio_policy_delete_node(pn);
+		kfree(pn);
 		spin_unlock_irq(&blkcg->lock);
 		goto update_io_group;
 	}
diff -druN linux-libre-3.1-gnu/block/blk-cgroup.h linux-libre-3.2-gnu/block/blk-cgroup.h
--- linux-libre-3.1-gnu/block/blk-cgroup.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/block/blk-cgroup.h	2012-01-04 18:55:44.000000000 -0500
@@ -188,7 +188,7 @@
 	union {
 		unsigned int weight;
 		/*
-		 * Rate read/write in terms of byptes per second
+		 * Rate read/write in terms of bytes per second
 		 * Whether this rate represents read or write is determined
 		 * by file type "fileid".
 		 */
diff -druN linux-libre-3.1-gnu/block/blk-core.c linux-libre-3.2-gnu/block/blk-core.c
--- linux-libre-3.1-gnu/block/blk-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/block/blk-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/task_io_accounting_ops.h>
 #include <linux/fault-inject.h>
 #include <linux/list_sort.h>
+#include <linux/delay.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/block.h>
@@ -38,8 +39,6 @@
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete);
 
-static int __make_request(struct request_queue *q, struct bio *bio);
-
 /*
  * For the allocated request tables
  */
@@ -347,30 +346,87 @@
 }
 EXPORT_SYMBOL(blk_put_queue);
 
-/*
- * Note: If a driver supplied the queue lock, it is disconnected
- * by this function. The actual state of the lock doesn't matter
- * here as the request_queue isn't accessible after this point
- * (QUEUE_FLAG_DEAD is set) and no other requests will be queued.
+/**
+ * blk_drain_queue - drain requests from request_queue
+ * @q: queue to drain
+ * @drain_all: whether to drain all requests or only the ones w/ ELVPRIV
+ *
+ * Drain requests from @q.  If @drain_all is set, all requests are drained.
+ * If not, only ELVPRIV requests are drained.  The caller is responsible
+ * for ensuring that no new requests which need to be drained are queued.
+ */
+void blk_drain_queue(struct request_queue *q, bool drain_all)
+{
+	while (true) {
+		int nr_rqs;
+
+		spin_lock_irq(q->queue_lock);
+
+		elv_drain_elevator(q);
+		if (drain_all)
+			blk_throtl_drain(q);
+
+		/*
+		 * This function might be called on a queue which failed
+		 * driver init after queue creation.  Some drivers
+		 * (e.g. fd) get unhappy in such cases.  Kick queue iff
+		 * dispatch queue has something on it.
+		 */
+		if (!list_empty(&q->queue_head))
+			__blk_run_queue(q);
+
+		if (drain_all)
+			nr_rqs = q->rq.count[0] + q->rq.count[1];
+		else
+			nr_rqs = q->rq.elvpriv;
+
+		spin_unlock_irq(q->queue_lock);
+
+		if (!nr_rqs)
+			break;
+		msleep(10);
+	}
+}
+
+/**
+ * blk_cleanup_queue - shutdown a request queue
+ * @q: request queue to shutdown
+ *
+ * Mark @q DEAD, drain all pending requests, destroy and put it.  All
+ * future requests will be failed immediately with -ENODEV.
  */
 void blk_cleanup_queue(struct request_queue *q)
 {
-	/*
-	 * We know we have process context here, so we can be a little
-	 * cautious and ensure that pending block actions on this device
-	 * are done before moving on. Going into this function, we should
-	 * not have processes doing IO to this device.
-	 */
-	blk_sync_queue(q);
+	spinlock_t *lock = q->queue_lock;
 
-	del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer);
+	/* mark @q DEAD, no new request or merges will be allowed afterwards */
 	mutex_lock(&q->sysfs_lock);
 	queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q);
-	mutex_unlock(&q->sysfs_lock);
+
+	spin_lock_irq(lock);
+	queue_flag_set(QUEUE_FLAG_NOMERGES, q);
+	queue_flag_set(QUEUE_FLAG_NOXMERGES, q);
+	queue_flag_set(QUEUE_FLAG_DEAD, q);
 
 	if (q->queue_lock != &q->__queue_lock)
 		q->queue_lock = &q->__queue_lock;
 
+	spin_unlock_irq(lock);
+	mutex_unlock(&q->sysfs_lock);
+
+	/*
+	 * Drain all requests queued before DEAD marking.  The caller might
+	 * be trying to tear down @q before its elevator is initialized, in
+	 * which case we don't want to call into draining.
+	 */
+	if (q->elevator)
+		blk_drain_queue(q, true);
+
+	/* @q won't process any more request, flush async actions */
+	del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer);
+	blk_sync_queue(q);
+
+	/* @q is and will stay empty, shutdown and put */
 	blk_put_queue(q);
 }
 EXPORT_SYMBOL(blk_cleanup_queue);
@@ -418,6 +474,7 @@
 	q->backing_dev_info.state = 0;
 	q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY;
 	q->backing_dev_info.name = "block";
+	q->node = node_id;
 
 	err = bdi_init(&q->backing_dev_info);
 	if (err) {
@@ -502,7 +559,7 @@
 	if (!uninit_q)
 		return NULL;
 
-	q = blk_init_allocated_queue_node(uninit_q, rfn, lock, node_id);
+	q = blk_init_allocated_queue(uninit_q, rfn, lock);
 	if (!q)
 		blk_cleanup_queue(uninit_q);
 
@@ -514,18 +571,9 @@
 blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn,
 			 spinlock_t *lock)
 {
-	return blk_init_allocated_queue_node(q, rfn, lock, -1);
-}
-EXPORT_SYMBOL(blk_init_allocated_queue);
-
-struct request_queue *
-blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn,
-			      spinlock_t *lock, int node_id)
-{
 	if (!q)
 		return NULL;
 
-	q->node = node_id;
 	if (blk_init_free_list(q))
 		return NULL;
 
@@ -541,7 +589,7 @@
 	/*
 	 * This also sets hw/phys segments, boundary and size
 	 */
-	blk_queue_make_request(q, __make_request);
+	blk_queue_make_request(q, blk_queue_bio);
 
 	q->sg_reserved_size = INT_MAX;
 
@@ -555,7 +603,7 @@
 
 	return NULL;
 }
-EXPORT_SYMBOL(blk_init_allocated_queue_node);
+EXPORT_SYMBOL(blk_init_allocated_queue);
 
 int blk_get_queue(struct request_queue *q)
 {
@@ -576,7 +624,7 @@
 }
 
 static struct request *
-blk_alloc_request(struct request_queue *q, int flags, int priv, gfp_t gfp_mask)
+blk_alloc_request(struct request_queue *q, unsigned int flags, gfp_t gfp_mask)
 {
 	struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask);
 
@@ -587,12 +635,10 @@
 
 	rq->cmd_flags = flags | REQ_ALLOCED;
 
-	if (priv) {
-		if (unlikely(elv_set_request(q, rq, gfp_mask))) {
-			mempool_free(rq, q->rq.rq_pool);
-			return NULL;
-		}
-		rq->cmd_flags |= REQ_ELVPRIV;
+	if ((flags & REQ_ELVPRIV) &&
+	    unlikely(elv_set_request(q, rq, gfp_mask))) {
+		mempool_free(rq, q->rq.rq_pool);
+		return NULL;
 	}
 
 	return rq;
@@ -651,12 +697,13 @@
  * A request has just been released.  Account for it, update the full and
  * congestion status, wake up any waiters.   Called under q->queue_lock.
  */
-static void freed_request(struct request_queue *q, int sync, int priv)
+static void freed_request(struct request_queue *q, unsigned int flags)
 {
 	struct request_list *rl = &q->rq;
+	int sync = rw_is_sync(flags);
 
 	rl->count[sync]--;
-	if (priv)
+	if (flags & REQ_ELVPRIV)
 		rl->elvpriv--;
 
 	__freed_request(q, sync);
@@ -684,10 +731,19 @@
 	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*.
+/**
+ * get_request - get a free request
+ * @q: request_queue to allocate request from
+ * @rw_flags: RW and SYNC flags
+ * @bio: bio to allocate request for (can be %NULL)
+ * @gfp_mask: allocation mask
+ *
+ * Get a free request from @q.  This function may fail under memory
+ * pressure or if @q is dead.
+ *
+ * Must be callled with @q->queue_lock held and,
+ * Returns %NULL on failure, with @q->queue_lock held.
+ * Returns !%NULL on success, with @q->queue_lock *not held*.
  */
 static struct request *get_request(struct request_queue *q, int rw_flags,
 				   struct bio *bio, gfp_t gfp_mask)
@@ -696,7 +752,10 @@
 	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 = 0;
+	int may_queue;
+
+	if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
+		return NULL;
 
 	may_queue = elv_may_queue(q, rw_flags);
 	if (may_queue == ELV_MQUEUE_NO)
@@ -740,17 +799,17 @@
 	rl->count[is_sync]++;
 	rl->starved[is_sync] = 0;
 
-	if (blk_rq_should_init_elevator(bio)) {
-		priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
-		if (priv)
-			rl->elvpriv++;
+	if (blk_rq_should_init_elevator(bio) &&
+	    !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags)) {
+		rw_flags |= REQ_ELVPRIV;
+		rl->elvpriv++;
 	}
 
 	if (blk_queue_io_stat(q))
 		rw_flags |= REQ_IO_STAT;
 	spin_unlock_irq(q->queue_lock);
 
-	rq = blk_alloc_request(q, rw_flags, priv, gfp_mask);
+	rq = blk_alloc_request(q, rw_flags, gfp_mask);
 	if (unlikely(!rq)) {
 		/*
 		 * Allocation failed presumably due to memory. Undo anything
@@ -760,7 +819,7 @@
 		 * wait queue, but this is pretty rare.
 		 */
 		spin_lock_irq(q->queue_lock);
-		freed_request(q, is_sync, priv);
+		freed_request(q, rw_flags);
 
 		/*
 		 * in the very unlikely event that allocation failed and no
@@ -790,11 +849,18 @@
 	return rq;
 }
 
-/*
- * No available requests for this queue, wait for some requests to become
- * available.
+/**
+ * get_request_wait - get a free request with retry
+ * @q: request_queue to allocate request from
+ * @rw_flags: RW and SYNC flags
+ * @bio: bio to allocate request for (can be %NULL)
  *
- * Called with q->queue_lock held, and returns with it unlocked.
+ * Get a free request from @q.  This function keeps retrying under memory
+ * pressure and fails iff @q is dead.
+ *
+ * Must be callled with @q->queue_lock held and,
+ * Returns %NULL on failure, with @q->queue_lock held.
+ * Returns !%NULL on success, with @q->queue_lock *not held*.
  */
 static struct request *get_request_wait(struct request_queue *q, int rw_flags,
 					struct bio *bio)
@@ -808,6 +874,9 @@
 		struct io_context *ioc;
 		struct request_list *rl = &q->rq;
 
+		if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
+			return NULL;
+
 		prepare_to_wait_exclusive(&rl->wait[is_sync], &wait,
 				TASK_UNINTERRUPTIBLE);
 
@@ -838,19 +907,15 @@
 {
 	struct request *rq;
 
-	if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
-		return NULL;
-
 	BUG_ON(rw != READ && rw != WRITE);
 
 	spin_lock_irq(q->queue_lock);
-	if (gfp_mask & __GFP_WAIT) {
+	if (gfp_mask & __GFP_WAIT)
 		rq = get_request_wait(q, rw, NULL);
-	} else {
+	else
 		rq = get_request(q, rw, NULL, gfp_mask);
-		if (!rq)
-			spin_unlock_irq(q->queue_lock);
-	}
+	if (!rq)
+		spin_unlock_irq(q->queue_lock);
 	/* q->queue_lock is unlocked at this point */
 
 	return rq;
@@ -1052,14 +1117,13 @@
 	 * it didn't come out of our reserved rq pools
 	 */
 	if (req->cmd_flags & REQ_ALLOCED) {
-		int is_sync = rq_is_sync(req) != 0;
-		int priv = req->cmd_flags & REQ_ELVPRIV;
+		unsigned int flags = req->cmd_flags;
 
 		BUG_ON(!list_empty(&req->queuelist));
 		BUG_ON(!hlist_unhashed(&req->hash));
 
 		blk_free_request(q, req);
-		freed_request(q, is_sync, priv);
+		freed_request(q, flags);
 	}
 }
 EXPORT_SYMBOL_GPL(__blk_put_request);
@@ -1161,18 +1225,32 @@
 	return true;
 }
 
-/*
- * Attempts to merge with the plugged list in the current process. Returns
- * true if merge was successful, otherwise false.
+/**
+ * attempt_plug_merge - try to merge with %current's plugged list
+ * @q: request_queue new bio is being queued at
+ * @bio: new bio being queued
+ * @request_count: out parameter for number of traversed plugged requests
+ *
+ * Determine whether @bio being queued on @q can be merged with a request
+ * on %current's plugged list.  Returns %true if merge was successful,
+ * otherwise %false.
+ *
+ * This function is called without @q->queue_lock; however, elevator is
+ * accessed iff there already are requests on the plugged list which in
+ * turn guarantees validity of the elevator.
+ *
+ * Note that, on successful merge, elevator operation
+ * elevator_bio_merged_fn() will be called without queue lock.  Elevator
+ * must be ready for this.
  */
-static bool attempt_plug_merge(struct task_struct *tsk, struct request_queue *q,
-			       struct bio *bio, unsigned int *request_count)
+static bool attempt_plug_merge(struct request_queue *q, struct bio *bio,
+			       unsigned int *request_count)
 {
 	struct blk_plug *plug;
 	struct request *rq;
 	bool ret = false;
 
-	plug = tsk->plug;
+	plug = current->plug;
 	if (!plug)
 		goto out;
 	*request_count = 0;
@@ -1202,7 +1280,6 @@
 
 void init_request_from_bio(struct request *req, struct bio *bio)
 {
-	req->cpu = bio->bi_comp_cpu;
 	req->cmd_type = REQ_TYPE_FS;
 
 	req->cmd_flags |= bio->bi_rw & REQ_COMMON_MASK;
@@ -1215,7 +1292,7 @@
 	blk_rq_bio_prep(req->q, req, bio);
 }
 
-static int __make_request(struct request_queue *q, struct bio *bio)
+void blk_queue_bio(struct request_queue *q, struct bio *bio)
 {
 	const bool sync = !!(bio->bi_rw & REQ_SYNC);
 	struct blk_plug *plug;
@@ -1240,8 +1317,8 @@
 	 * Check if we can merge with the plugged list before grabbing
 	 * any locks.
 	 */
-	if (attempt_plug_merge(current, q, bio, &request_count))
-		goto out;
+	if (attempt_plug_merge(q, bio, &request_count))
+		return;
 
 	spin_lock_irq(q->queue_lock);
 
@@ -1275,6 +1352,10 @@
 	 * Returns with the queue unlocked.
 	 */
 	req = get_request_wait(q, rw_flags, bio);
+	if (unlikely(!req)) {
+		bio_endio(bio, -ENODEV);	/* @q is dead */
+		goto out_unlock;
+	}
 
 	/*
 	 * After dropping the lock and possibly sleeping here, our request
@@ -1284,8 +1365,7 @@
 	 */
 	init_request_from_bio(req, bio);
 
-	if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) ||
-	    bio_flagged(bio, BIO_CPU_AFFINE))
+	if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags))
 		req->cpu = raw_smp_processor_id();
 
 	plug = current->plug;
@@ -1298,15 +1378,19 @@
 		 */
 		if (list_empty(&plug->list))
 			trace_block_plug(q);
-		else if (!plug->should_sort) {
-			struct request *__rq;
+		else {
+			if (!plug->should_sort) {
+				struct request *__rq;
 
-			__rq = list_entry_rq(plug->list.prev);
-			if (__rq->q != q)
-				plug->should_sort = 1;
+				__rq = list_entry_rq(plug->list.prev);
+				if (__rq->q != q)
+					plug->should_sort = 1;
+			}
+			if (request_count >= BLK_MAX_REQUEST_COUNT) {
+				blk_flush_plug_list(plug, false);
+				trace_block_plug(q);
+			}
 		}
-		if (request_count >= BLK_MAX_REQUEST_COUNT)
-			blk_flush_plug_list(plug, false);
 		list_add_tail(&req->queuelist, &plug->list);
 		drive_stat_acct(req, 1);
 	} else {
@@ -1316,9 +1400,8 @@
 out_unlock:
 		spin_unlock_irq(q->queue_lock);
 	}
-out:
-	return 0;
 }
+EXPORT_SYMBOL_GPL(blk_queue_bio);	/* for device mapper only */
 
 /*
  * If bio->bi_dev is a partition, remap the location
@@ -1417,165 +1500,135 @@
 	return 0;
 }
 
-/**
- * generic_make_request - hand a buffer to its device driver for I/O
- * @bio:  The bio describing the location in memory and on the device.
- *
- * generic_make_request() is used to make I/O requests of block
- * devices. It is passed a &struct bio, which describes the I/O that needs
- * to be done.
- *
- * generic_make_request() does not return any status.  The
- * success/failure status of the request, along with notification of
- * completion, is delivered asynchronously through the bio->bi_end_io
- * function described (one day) else where.
- *
- * The caller of generic_make_request must make sure that bi_io_vec
- * are set to describe the memory buffer, and that bi_dev and bi_sector are
- * set to describe the device address, and the
- * bi_end_io and optionally bi_private are set to describe how
- * completion notification should be signaled.
- *
- * generic_make_request and the drivers it calls may use bi_next if this
- * bio happens to be merged with someone else, and may change bi_dev and
- * bi_sector for remaps as it sees fit.  So the values of these fields
- * should NOT be depended on after the call to generic_make_request.
- */
-static inline void __generic_make_request(struct bio *bio)
+static noinline_for_stack bool
+generic_make_request_checks(struct bio *bio)
 {
 	struct request_queue *q;
-	sector_t old_sector;
-	int ret, nr_sectors = bio_sectors(bio);
-	dev_t old_dev;
+	int nr_sectors = bio_sectors(bio);
 	int err = -EIO;
+	char b[BDEVNAME_SIZE];
+	struct hd_struct *part;
 
 	might_sleep();
 
 	if (bio_check_eod(bio, nr_sectors))
 		goto end_io;
 
-	/*
-	 * Resolve the mapping until finished. (drivers are
-	 * still free to implement/resolve their own stacking
-	 * by explicitly returning 0)
-	 *
-	 * NOTE: we don't repeat the blk_size check for each new device.
-	 * Stacking drivers are expected to know what they are doing.
-	 */
-	old_sector = -1;
-	old_dev = 0;
-	do {
-		char b[BDEVNAME_SIZE];
-		struct hd_struct *part;
-
-		q = bdev_get_queue(bio->bi_bdev);
-		if (unlikely(!q)) {
-			printk(KERN_ERR
-			       "generic_make_request: Trying to access "
-				"nonexistent block-device %s (%Lu)\n",
-				bdevname(bio->bi_bdev, b),
-				(long long) bio->bi_sector);
-			goto end_io;
-		}
-
-		if (unlikely(!(bio->bi_rw & REQ_DISCARD) &&
-			     nr_sectors > queue_max_hw_sectors(q))) {
-			printk(KERN_ERR "bio too big device %s (%u > %u)\n",
-			       bdevname(bio->bi_bdev, b),
-			       bio_sectors(bio),
-			       queue_max_hw_sectors(q));
-			goto end_io;
-		}
-
-		if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
-			goto end_io;
-
-		part = bio->bi_bdev->bd_part;
-		if (should_fail_request(part, bio->bi_size) ||
-		    should_fail_request(&part_to_disk(part)->part0,
-					bio->bi_size))
-			goto end_io;
-
-		/*
-		 * If this device has partitions, remap block n
-		 * of partition p to block n+start(p) of the disk.
-		 */
-		blk_partition_remap(bio);
+	q = bdev_get_queue(bio->bi_bdev);
+	if (unlikely(!q)) {
+		printk(KERN_ERR
+		       "generic_make_request: Trying to access "
+			"nonexistent block-device %s (%Lu)\n",
+			bdevname(bio->bi_bdev, b),
+			(long long) bio->bi_sector);
+		goto end_io;
+	}
 
-		if (bio_integrity_enabled(bio) && bio_integrity_prep(bio))
-			goto end_io;
+	if (unlikely(!(bio->bi_rw & REQ_DISCARD) &&
+		     nr_sectors > queue_max_hw_sectors(q))) {
+		printk(KERN_ERR "bio too big device %s (%u > %u)\n",
+		       bdevname(bio->bi_bdev, b),
+		       bio_sectors(bio),
+		       queue_max_hw_sectors(q));
+		goto end_io;
+	}
 
-		if (old_sector != -1)
-			trace_block_bio_remap(q, bio, old_dev, old_sector);
+	part = bio->bi_bdev->bd_part;
+	if (should_fail_request(part, bio->bi_size) ||
+	    should_fail_request(&part_to_disk(part)->part0,
+				bio->bi_size))
+		goto end_io;
 
-		old_sector = bio->bi_sector;
-		old_dev = bio->bi_bdev->bd_dev;
+	/*
+	 * If this device has partitions, remap block n
+	 * of partition p to block n+start(p) of the disk.
+	 */
+	blk_partition_remap(bio);
 
-		if (bio_check_eod(bio, nr_sectors))
-			goto end_io;
+	if (bio_integrity_enabled(bio) && bio_integrity_prep(bio))
+		goto end_io;
 
-		/*
-		 * Filter flush bio's early so that make_request based
-		 * drivers without flush support don't have to worry
-		 * about them.
-		 */
-		if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && !q->flush_flags) {
-			bio->bi_rw &= ~(REQ_FLUSH | REQ_FUA);
-			if (!nr_sectors) {
-				err = 0;
-				goto end_io;
-			}
-		}
+	if (bio_check_eod(bio, nr_sectors))
+		goto end_io;
 
-		if ((bio->bi_rw & REQ_DISCARD) &&
-		    (!blk_queue_discard(q) ||
-		     ((bio->bi_rw & REQ_SECURE) &&
-		      !blk_queue_secdiscard(q)))) {
-			err = -EOPNOTSUPP;
+	/*
+	 * Filter flush bio's early so that make_request based
+	 * drivers without flush support don't have to worry
+	 * about them.
+	 */
+	if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && !q->flush_flags) {
+		bio->bi_rw &= ~(REQ_FLUSH | REQ_FUA);
+		if (!nr_sectors) {
+			err = 0;
 			goto end_io;
 		}
+	}
 
-		if (blk_throtl_bio(q, &bio))
-			goto end_io;
-
-		/*
-		 * If bio = NULL, bio has been throttled and will be submitted
-		 * later.
-		 */
-		if (!bio)
-			break;
-
-		trace_block_bio_queue(q, bio);
+	if ((bio->bi_rw & REQ_DISCARD) &&
+	    (!blk_queue_discard(q) ||
+	     ((bio->bi_rw & REQ_SECURE) &&
+	      !blk_queue_secdiscard(q)))) {
+		err = -EOPNOTSUPP;
+		goto end_io;
+	}
 
-		ret = q->make_request_fn(q, bio);
-	} while (ret);
+	if (blk_throtl_bio(q, bio))
+		return false;	/* throttled, will be resubmitted later */
 
-	return;
+	trace_block_bio_queue(q, bio);
+	return true;
 
 end_io:
 	bio_endio(bio, err);
+	return false;
 }
 
-/*
- * We only want one ->make_request_fn to be active at a time,
- * else stack usage with stacked devices could be a problem.
- * So use current->bio_list to keep a list of requests
- * submited by a make_request_fn function.
- * current->bio_list is also used as a flag to say if
- * generic_make_request is currently active in this task or not.
- * If it is NULL, then no make_request is active.  If it is non-NULL,
- * then a make_request is active, and new requests should be added
- * at the tail
+/**
+ * generic_make_request - hand a buffer to its device driver for I/O
+ * @bio:  The bio describing the location in memory and on the device.
+ *
+ * generic_make_request() is used to make I/O requests of block
+ * devices. It is passed a &struct bio, which describes the I/O that needs
+ * to be done.
+ *
+ * generic_make_request() does not return any status.  The
+ * success/failure status of the request, along with notification of
+ * completion, is delivered asynchronously through the bio->bi_end_io
+ * function described (one day) else where.
+ *
+ * The caller of generic_make_request must make sure that bi_io_vec
+ * are set to describe the memory buffer, and that bi_dev and bi_sector are
+ * set to describe the device address, and the
+ * bi_end_io and optionally bi_private are set to describe how
+ * completion notification should be signaled.
+ *
+ * generic_make_request and the drivers it calls may use bi_next if this
+ * bio happens to be merged with someone else, and may resubmit the bio to
+ * a lower device by calling into generic_make_request recursively, which
+ * means the bio should NOT be touched after the call to ->make_request_fn.
  */
 void generic_make_request(struct bio *bio)
 {
 	struct bio_list bio_list_on_stack;
 
+	if (!generic_make_request_checks(bio))
+		return;
+
+	/*
+	 * We only want one ->make_request_fn to be active at a time, else
+	 * stack usage with stacked devices could be a problem.  So use
+	 * current->bio_list to keep a list of requests submited by a
+	 * make_request_fn function.  current->bio_list is also used as a
+	 * flag to say if generic_make_request is currently active in this
+	 * task or not.  If it is NULL, then no make_request is active.  If
+	 * it is non-NULL, then a make_request is active, and new requests
+	 * should be added at the tail
+	 */
 	if (current->bio_list) {
-		/* make_request is active */
 		bio_list_add(current->bio_list, bio);
 		return;
 	}
+
 	/* following loop may be a bit non-obvious, and so deserves some
 	 * explanation.
 	 * Before entering the loop, bio->bi_next is NULL (as all callers
@@ -1583,22 +1636,21 @@
 	 * We pretend that we have just taken it off a longer list, so
 	 * we assign bio_list to a pointer to the bio_list_on_stack,
 	 * thus initialising the bio_list of new bios to be
-	 * added.  __generic_make_request may indeed add some more bios
+	 * added.  ->make_request() may indeed add some more bios
 	 * through a recursive call to generic_make_request.  If it
 	 * did, we find a non-NULL value in bio_list and re-enter the loop
 	 * from the top.  In this case we really did just take the bio
 	 * of the top of the list (no pretending) and so remove it from
-	 * bio_list, and call into __generic_make_request again.
-	 *
-	 * The loop was structured like this to make only one call to
-	 * __generic_make_request (which is important as it is large and
-	 * inlined) and to keep the structure simple.
+	 * bio_list, and call into ->make_request() again.
 	 */
 	BUG_ON(bio->bi_next);
 	bio_list_init(&bio_list_on_stack);
 	current->bio_list = &bio_list_on_stack;
 	do {
-		__generic_make_request(bio);
+		struct request_queue *q = bdev_get_queue(bio->bi_bdev);
+
+		q->make_request_fn(q, bio);
+
 		bio = bio_list_pop(current->bio_list);
 	} while (bio);
 	current->bio_list = NULL; /* deactivate */
@@ -1725,6 +1777,8 @@
 		where = ELEVATOR_INSERT_FLUSH;
 
 	add_acct_request(q, rq, where);
+	if (where == ELEVATOR_INSERT_FLUSH)
+		__blk_run_queue(q);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 
 	return 0;
@@ -2628,6 +2682,20 @@
 
 #define PLUG_MAGIC	0x91827364
 
+/**
+ * blk_start_plug - initialize blk_plug and track it inside the task_struct
+ * @plug:	The &struct blk_plug that needs to be initialized
+ *
+ * Description:
+ *   Tracking blk_plug inside the task_struct will help with auto-flushing the
+ *   pending I/O should the task end up blocking between blk_start_plug() and
+ *   blk_finish_plug(). This is important from a performance perspective, but
+ *   also ensures that we don't deadlock. For instance, if the task is blocking
+ *   for a memory allocation, memory reclaim could end up wanting to free a
+ *   page belonging to that request that is currently residing in our private
+ *   plug. By flushing the pending I/O when the process goes to sleep, we avoid
+ *   this kind of deadlock.
+ */
 void blk_start_plug(struct blk_plug *plug)
 {
 	struct task_struct *tsk = current;
diff -druN linux-libre-3.1-gnu/block/blk-flush.c linux-libre-3.2-gnu/block/blk-flush.c
--- linux-libre-3.1-gnu/block/blk-flush.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/block/blk-flush.c	2012-01-04 18:55:44.000000000 -0500
@@ -320,7 +320,7 @@
 		return;
 	}
 
-	BUG_ON(!rq->bio || rq->bio != rq->biotail);
+	BUG_ON(rq->bio != rq->biotail); /*assumes zero or single bio rq */
 
 	/*
 	 * If there's data but flush is not necessary, the request can be
@@ -330,7 +330,6 @@
 	if ((policy & REQ_FSEQ_DATA) &&
 	    !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) {
 		list_add_tail(&rq->queuelist, &q->queue_head);
-		blk_run_queue_async(q);
 		return;
 	}
 
diff -druN linux-libre-3.1-gnu/block/blk.h linux-libre-3.2-gnu/block/blk.h
--- linux-libre-3.1-gnu/block/blk.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/block/blk.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 			struct bio *bio);
 int blk_rq_append_bio(struct request_queue *q, struct request *rq,
 		      struct bio *bio);
+void blk_drain_queue(struct request_queue *q, bool drain_all);
 void blk_dequeue_request(struct request *rq);
 void __blk_queue_free_tags(struct request_queue *q);
 bool __blk_end_bidi_request(struct request *rq, int error,
@@ -188,4 +189,21 @@
 	        (rq->cmd_flags & REQ_DISCARD));
 }
 
-#endif
+#ifdef CONFIG_BLK_DEV_THROTTLING
+extern bool blk_throtl_bio(struct request_queue *q, struct bio *bio);
+extern void blk_throtl_drain(struct request_queue *q);
+extern int blk_throtl_init(struct request_queue *q);
+extern void blk_throtl_exit(struct request_queue *q);
+extern void blk_throtl_release(struct request_queue *q);
+#else /* CONFIG_BLK_DEV_THROTTLING */
+static inline bool blk_throtl_bio(struct request_queue *q, struct bio *bio)
+{
+	return false;
+}
+static inline void blk_throtl_drain(struct request_queue *q) { }
+static inline int blk_throtl_init(struct request_queue *q) { return 0; }
+static inline void blk_throtl_exit(struct request_queue *q) { }
+static inline void blk_throtl_release(struct request_queue *q) { }
+#endif /* CONFIG_BLK_DEV_THROTTLING */
+
+#endif /* BLK_INTERNAL_H */
diff -druN linux-libre-3.1-gnu/block/blk-integrity.c linux-libre-3.2-gnu/block/blk-integrity.c
--- linux-libre-3.1-gnu/block/blk-integrity.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/block/blk-integrity.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/mempool.h>
 #include <linux/bio.h>
 #include <linux/scatterlist.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 
 #include "blk.h"
diff -druN linux-libre-3.1-gnu/block/blk-map.c linux-libre-3.2-gnu/block/blk-map.c
--- linux-libre-3.1-gnu/block/blk-map.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/block/blk-map.c	2012-01-04 18:55:44.000000000 -0500
@@ -204,10 +204,11 @@
 		if (!iov[i].iov_len)
 			return -EINVAL;
 
-		if (uaddr & queue_dma_alignment(q)) {
+		/*
+		 * Keep going so we check length of all segments
+		 */
+		if (uaddr & queue_dma_alignment(q))
 			unaligned = 1;
-			break;
-		}
 	}
 
 	if (unaligned || (q->dma_pad_mask & len) || map_data)
@@ -310,7 +311,7 @@
 	if (IS_ERR(bio))
 		return PTR_ERR(bio);
 
-	if (rq_data_dir(rq) == WRITE)
+	if (!reading)
 		bio->bi_rw |= REQ_WRITE;
 
 	if (do_copy)
diff -druN linux-libre-3.1-gnu/block/blk-sysfs.c linux-libre-3.2-gnu/block/blk-sysfs.c
--- linux-libre-3.1-gnu/block/blk-sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/block/blk-sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -457,11 +457,11 @@
 }
 
 /**
- * blk_cleanup_queue: - release a &struct request_queue when it is no longer needed
- * @kobj:    the kobj belonging of the request queue to be released
+ * blk_release_queue: - release a &struct request_queue when it is no longer needed
+ * @kobj:    the kobj belonging to the request queue to be released
  *
  * Description:
- *     blk_cleanup_queue is the pair to blk_init_queue() or
+ *     blk_release_queue is the pair to blk_init_queue() or
  *     blk_queue_make_request().  It should be called when a request queue is
  *     being released; typically when a block device is being de-registered.
  *     Currently, its primary task it to free all the &struct request
@@ -490,6 +490,7 @@
 	if (q->queue_tags)
 		__blk_queue_free_tags(q);
 
+	blk_throtl_release(q);
 	blk_trace_shutdown(q);
 
 	bdi_destroy(&q->backing_dev_info);
diff -druN linux-libre-3.1-gnu/block/blk-tag.c linux-libre-3.2-gnu/block/blk-tag.c
--- linux-libre-3.1-gnu/block/blk-tag.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/block/blk-tag.c	2012-01-04 18:55:44.000000000 -0500
@@ -282,16 +282,9 @@
 void blk_queue_end_tag(struct request_queue *q, struct request *rq)
 {
 	struct blk_queue_tag *bqt = q->queue_tags;
-	int tag = rq->tag;
-
-	BUG_ON(tag == -1);
+	unsigned tag = rq->tag; /* negative tags invalid */
 
-	if (unlikely(tag >= bqt->real_max_depth))
-		/*
-		 * This can happen after tag depth has been reduced.
-		 * FIXME: how about a warning or info message here?
-		 */
-		return;
+	BUG_ON(tag >= bqt->real_max_depth);
 
 	list_del_init(&rq->queuelist);
 	rq->cmd_flags &= ~REQ_QUEUED;
diff -druN linux-libre-3.1-gnu/block/blk-throttle.c linux-libre-3.2-gnu/block/blk-throttle.c
--- linux-libre-3.1-gnu/block/blk-throttle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/block/blk-throttle.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/bio.h>
 #include <linux/blktrace_api.h>
 #include "blk-cgroup.h"
+#include "blk.h"
 
 /* Max dispatch from a group in 1 round */
 static int throtl_grp_quantum = 8;
@@ -302,16 +303,16 @@
 	return tg;
 }
 
-/*
- * This function returns with queue lock unlocked in case of error, like
- * request queue is no more
- */
 static struct throtl_grp * throtl_get_tg(struct throtl_data *td)
 {
 	struct throtl_grp *tg = NULL, *__tg = NULL;
 	struct blkio_cgroup *blkcg;
 	struct request_queue *q = td->queue;
 
+	/* no throttling for dead queue */
+	if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
+		return NULL;
+
 	rcu_read_lock();
 	blkcg = task_blkio_cgroup(current);
 	tg = throtl_find_tg(td, blkcg);
@@ -323,32 +324,22 @@
 	/*
 	 * Need to allocate a group. Allocation of group also needs allocation
 	 * of per cpu stats which in-turn takes a mutex() and can block. Hence
-	 * we need to drop rcu lock and queue_lock before we call alloc
-	 *
-	 * Take the request queue reference to make sure queue does not
-	 * go away once we return from allocation.
+	 * we need to drop rcu lock and queue_lock before we call alloc.
 	 */
-	blk_get_queue(q);
 	rcu_read_unlock();
 	spin_unlock_irq(q->queue_lock);
 
 	tg = throtl_alloc_tg(td);
-	/*
-	 * We might have slept in group allocation. Make sure queue is not
-	 * dead
-	 */
-	if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) {
-		blk_put_queue(q);
-		if (tg)
-			kfree(tg);
-
-		return ERR_PTR(-ENODEV);
-	}
-	blk_put_queue(q);
 
 	/* Group allocated and queue is still alive. take the lock */
 	spin_lock_irq(q->queue_lock);
 
+	/* Make sure @q is still alive */
+	if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) {
+		kfree(tg);
+		return NULL;
+	}
+
 	/*
 	 * Initialize the new group. After sleeping, read the blkcg again.
 	 */
@@ -1014,11 +1005,6 @@
 	}
 }
 
-static void throtl_td_free(struct throtl_data *td)
-{
-	kfree(td);
-}
-
 /*
  * Blk cgroup controller notification saying that blkio_group object is being
  * delinked as associated cgroup object is going away. That also means that
@@ -1123,17 +1109,17 @@
 	.plid = BLKIO_POLICY_THROTL,
 };
 
-int blk_throtl_bio(struct request_queue *q, struct bio **biop)
+bool blk_throtl_bio(struct request_queue *q, struct bio *bio)
 {
 	struct throtl_data *td = q->td;
 	struct throtl_grp *tg;
-	struct bio *bio = *biop;
 	bool rw = bio_data_dir(bio), update_disptime = true;
 	struct blkio_cgroup *blkcg;
+	bool throttled = false;
 
 	if (bio->bi_rw & REQ_THROTTLED) {
 		bio->bi_rw &= ~REQ_THROTTLED;
-		return 0;
+		goto out;
 	}
 
 	/*
@@ -1152,7 +1138,7 @@
 			blkiocg_update_dispatch_stats(&tg->blkg, bio->bi_size,
 					rw, rw_is_sync(bio->bi_rw));
 			rcu_read_unlock();
-			return 0;
+			goto out;
 		}
 	}
 	rcu_read_unlock();
@@ -1161,18 +1147,10 @@
 	 * Either group has not been allocated yet or it is not an unlimited
 	 * IO group
 	 */
-
 	spin_lock_irq(q->queue_lock);
 	tg = throtl_get_tg(td);
-
-	if (IS_ERR(tg)) {
-		if (PTR_ERR(tg)	== -ENODEV) {
-			/*
-			 * Queue is gone. No queue lock held here.
-			 */
-			return -ENODEV;
-		}
-	}
+	if (unlikely(!tg))
+		goto out_unlock;
 
 	if (tg->nr_queued[rw]) {
 		/*
@@ -1200,7 +1178,7 @@
 		 * So keep on trimming slice even if bio is not queued.
 		 */
 		throtl_trim_slice(td, tg, rw);
-		goto out;
+		goto out_unlock;
 	}
 
 queue_bio:
@@ -1212,16 +1190,52 @@
 			tg->nr_queued[READ], tg->nr_queued[WRITE]);
 
 	throtl_add_bio_tg(q->td, tg, bio);
-	*biop = NULL;
+	throttled = true;
 
 	if (update_disptime) {
 		tg_update_disptime(td, tg);
 		throtl_schedule_next_dispatch(td);
 	}
 
+out_unlock:
+	spin_unlock_irq(q->queue_lock);
 out:
+	return throttled;
+}
+
+/**
+ * blk_throtl_drain - drain throttled bios
+ * @q: request_queue to drain throttled bios for
+ *
+ * Dispatch all currently throttled bios on @q through ->make_request_fn().
+ */
+void blk_throtl_drain(struct request_queue *q)
+	__releases(q->queue_lock) __acquires(q->queue_lock)
+{
+	struct throtl_data *td = q->td;
+	struct throtl_rb_root *st = &td->tg_service_tree;
+	struct throtl_grp *tg;
+	struct bio_list bl;
+	struct bio *bio;
+
+	WARN_ON_ONCE(!queue_is_locked(q));
+
+	bio_list_init(&bl);
+
+	while ((tg = throtl_rb_first(st))) {
+		throtl_dequeue_tg(td, tg);
+
+		while ((bio = bio_list_peek(&tg->bio_lists[READ])))
+			tg_dispatch_one_bio(td, tg, bio_data_dir(bio), &bl);
+		while ((bio = bio_list_peek(&tg->bio_lists[WRITE])))
+			tg_dispatch_one_bio(td, tg, bio_data_dir(bio), &bl);
+	}
 	spin_unlock_irq(q->queue_lock);
-	return 0;
+
+	while ((bio = bio_list_pop(&bl)))
+		generic_make_request(bio);
+
+	spin_lock_irq(q->queue_lock);
 }
 
 int blk_throtl_init(struct request_queue *q)
@@ -1296,7 +1310,11 @@
 	 * it.
 	 */
 	throtl_shutdown_wq(q);
-	throtl_td_free(td);
+}
+
+void blk_throtl_release(struct request_queue *q)
+{
+	kfree(q->td);
 }
 
 static int __init throtl_init(void)
diff -druN linux-libre-3.1-gnu/block/bsg-lib.c linux-libre-3.2-gnu/block/bsg-lib.c
--- linux-libre-3.1-gnu/block/bsg-lib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/block/bsg-lib.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/delay.h>
 #include <linux/scatterlist.h>
 #include <linux/bsg-lib.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <scsi/scsi_cmnd.h>
 
 /**
diff -druN linux-libre-3.1-gnu/block/cfq-iosched.c linux-libre-3.2-gnu/block/cfq-iosched.c
--- linux-libre-3.1-gnu/block/cfq-iosched.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/block/cfq-iosched.c	2012-01-04 18:55:44.000000000 -0500
@@ -1655,6 +1655,8 @@
 		    struct request *next)
 {
 	struct cfq_queue *cfqq = RQ_CFQQ(rq);
+	struct cfq_data *cfqd = q->elevator->elevator_data;
+
 	/*
 	 * reposition in fifo if next is older than rq
 	 */
@@ -1669,6 +1671,16 @@
 	cfq_remove_request(next);
 	cfq_blkiocg_update_io_merged_stats(&(RQ_CFQG(rq))->blkg,
 					rq_data_dir(next), rq_is_sync(next));
+
+	cfqq = RQ_CFQQ(next);
+	/*
+	 * all requests of this queue are merged to other queues, delete it
+	 * from the service tree. If it's the active_queue,
+	 * cfq_dispatch_requests() will choose to expire it or do idle
+	 */
+	if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY_ROOT(&cfqq->sort_list) &&
+	    cfqq != cfqd->active_queue)
+		cfq_del_cfqq_rr(cfqd, cfqq);
 }
 
 static int cfq_allow_merge(struct request_queue *q, struct request *rq,
@@ -3184,7 +3196,7 @@
 		}
 	}
 
-	if (ret)
+	if (ret && ret != -EEXIST)
 		printk(KERN_ERR "cfq: cic link failed!\n");
 
 	return ret;
@@ -3200,6 +3212,7 @@
 {
 	struct io_context *ioc = NULL;
 	struct cfq_io_context *cic;
+	int ret;
 
 	might_sleep_if(gfp_mask & __GFP_WAIT);
 
@@ -3207,6 +3220,7 @@
 	if (!ioc)
 		return NULL;
 
+retry:
 	cic = cfq_cic_lookup(cfqd, ioc);
 	if (cic)
 		goto out;
@@ -3215,7 +3229,12 @@
 	if (cic == NULL)
 		goto err;
 
-	if (cfq_cic_link(cfqd, ioc, cic, gfp_mask))
+	ret = cfq_cic_link(cfqd, ioc, cic, gfp_mask);
+	if (ret == -EEXIST) {
+		/* someone has linked cic to ioc already */
+		cfq_cic_free(cic);
+		goto retry;
+	} else if (ret)
 		goto err_free;
 
 out:
@@ -4036,6 +4055,11 @@
 
 	if (blkio_alloc_blkg_stats(&cfqg->blkg)) {
 		kfree(cfqg);
+
+		spin_lock(&cic_index_lock);
+		ida_remove(&cic_index_ida, cfqd->cic_index);
+		spin_unlock(&cic_index_lock);
+
 		kfree(cfqd);
 		return NULL;
 	}
diff -druN linux-libre-3.1-gnu/block/elevator.c linux-libre-3.2-gnu/block/elevator.c
--- linux-libre-3.1-gnu/block/elevator.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/block/elevator.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/compiler.h>
-#include <linux/delay.h>
 #include <linux/blktrace_api.h>
 #include <linux/hash.h>
 #include <linux/uaccess.h>
@@ -182,7 +181,7 @@
 	eq->elevator_data = data;
 }
 
-static char chosen_elevator[16];
+static char chosen_elevator[ELV_NAME_MAX];
 
 static int __init elevator_setup(char *str)
 {
@@ -606,43 +605,35 @@
 void elv_drain_elevator(struct request_queue *q)
 {
 	static int printed;
+
+	lockdep_assert_held(q->queue_lock);
+
 	while (q->elevator->ops->elevator_dispatch_fn(q, 1))
 		;
-	if (q->nr_sorted == 0)
-		return;
-	if (printed++ < 10) {
+	if (q->nr_sorted && printed++ < 10) {
 		printk(KERN_ERR "%s: forced dispatching is broken "
 		       "(nr_sorted=%u), please report this\n",
 		       q->elevator->elevator_type->elevator_name, q->nr_sorted);
 	}
 }
 
-/*
- * Call with queue lock held, interrupts disabled
- */
 void elv_quiesce_start(struct request_queue *q)
 {
 	if (!q->elevator)
 		return;
 
+	spin_lock_irq(q->queue_lock);
 	queue_flag_set(QUEUE_FLAG_ELVSWITCH, q);
+	spin_unlock_irq(q->queue_lock);
 
-	/*
-	 * make sure we don't have any requests in flight
-	 */
-	elv_drain_elevator(q);
-	while (q->rq.elvpriv) {
-		__blk_run_queue(q);
-		spin_unlock_irq(q->queue_lock);
-		msleep(10);
-		spin_lock_irq(q->queue_lock);
-		elv_drain_elevator(q);
-	}
+	blk_drain_queue(q, false);
 }
 
 void elv_quiesce_end(struct request_queue *q)
 {
+	spin_lock_irq(q->queue_lock);
 	queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
+	spin_unlock_irq(q->queue_lock);
 }
 
 void __elv_add_request(struct request_queue *q, struct request *rq, int where)
@@ -972,7 +963,6 @@
 	/*
 	 * Turn on BYPASS and drain all requests w/ elevator private data
 	 */
-	spin_lock_irq(q->queue_lock);
 	elv_quiesce_start(q);
 
 	/*
@@ -983,8 +973,8 @@
 	/*
 	 * attach and start new elevator
 	 */
+	spin_lock_irq(q->queue_lock);
 	elevator_attach(q, e, data);
-
 	spin_unlock_irq(q->queue_lock);
 
 	if (old_elevator->registered) {
@@ -999,9 +989,7 @@
 	 * finally exit old elevator and turn off BYPASS.
 	 */
 	elevator_exit(old_elevator);
-	spin_lock_irq(q->queue_lock);
 	elv_quiesce_end(q);
-	spin_unlock_irq(q->queue_lock);
 
 	blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name);
 
@@ -1015,10 +1003,7 @@
 	elevator_exit(e);
 	q->elevator = old_elevator;
 	elv_register_queue(q);
-
-	spin_lock_irq(q->queue_lock);
-	queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
-	spin_unlock_irq(q->queue_lock);
+	elv_quiesce_end(q);
 
 	return err;
 }
diff -druN linux-libre-3.1-gnu/block/genhd.c linux-libre-3.2-gnu/block/genhd.c
--- linux-libre-3.1-gnu/block/genhd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/block/genhd.c	2012-01-04 18:55:44.000000000 -0500
@@ -536,7 +536,7 @@
 	disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj);
 
 	/* No minors to use for partitions */
-	if (!disk_partitionable(disk))
+	if (!disk_part_scan_enabled(disk))
 		goto exit;
 
 	/* No such device (e.g., media were just removed) */
@@ -611,6 +611,12 @@
 	register_disk(disk);
 	blk_register_queue(disk);
 
+	/*
+	 * Take an extra ref on queue which will be put on disk_release()
+	 * so that it sticks around as long as @disk is there.
+	 */
+	WARN_ON_ONCE(blk_get_queue(disk->queue));
+
 	retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj,
 				   "bdi");
 	WARN_ON(retval);
@@ -841,7 +847,7 @@
 	char buf[BDEVNAME_SIZE];
 
 	/* Don't show non-partitionable removeable devices or empty devices */
-	if (!get_capacity(sgp) || (!disk_partitionable(sgp) &&
+	if (!get_capacity(sgp) || (!disk_max_parts(sgp) &&
 				   (sgp->flags & GENHD_FL_REMOVABLE)))
 		return 0;
 	if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)
@@ -1095,6 +1101,8 @@
 	disk_replace_part_tbl(disk, NULL);
 	free_part_stats(&disk->part0);
 	free_part_info(&disk->part0);
+	if (disk->queue)
+		blk_put_queue(disk->queue);
 	kfree(disk);
 }
 struct class block_class = {
diff -druN linux-libre-3.1-gnu/block/ioctl.c linux-libre-3.2-gnu/block/ioctl.c
--- linux-libre-3.1-gnu/block/ioctl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/block/ioctl.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 #include <linux/capability.h>
 #include <linux/blkdev.h>
+#include <linux/export.h>
 #include <linux/gfp.h>
 #include <linux/blkpg.h>
 #include <linux/hdreg.h>
@@ -101,7 +102,7 @@
 	struct gendisk *disk = bdev->bd_disk;
 	int res;
 
-	if (!disk_partitionable(disk) || bdev != bdev->bd_contains)
+	if (!disk_part_scan_enabled(disk) || bdev != bdev->bd_contains)
 		return -EINVAL;
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
diff -druN linux-libre-3.1-gnu/block/scsi_ioctl.c linux-libre-3.2-gnu/block/scsi_ioctl.c
--- linux-libre-3.1-gnu/block/scsi_ioctl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/block/scsi_ioctl.c	2012-01-04 18:55:44.000000000 -0500
@@ -565,7 +565,7 @@
 {
 	int err;
 
-	if (!q || blk_get_queue(q))
+	if (!q)
 		return -ENXIO;
 
 	switch (cmd) {
@@ -686,7 +686,6 @@
 			err = -ENOTTY;
 	}
 
-	blk_put_queue(q);
 	return err;
 }
 EXPORT_SYMBOL(scsi_cmd_ioctl);
diff -druN linux-libre-3.1-gnu/CREDITS linux-libre-3.2-gnu/CREDITS
--- linux-libre-3.1-gnu/CREDITS	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/CREDITS	2012-01-04 18:55:44.000000000 -0500
@@ -688,10 +688,13 @@
 
 N: Kees Cook
 E: kees@outflux.net
-W: http://outflux.net/
-P: 1024D/17063E6D 9FA3 C49C 23C9 D1BC 2E30  1975 1FFF 4BA9 1706 3E6D
-D: Minor updates to SCSI types, added /proc/pid/maps protection
+E: kees@ubuntu.com
+E: keescook@chromium.org
+W: http://outflux.net/blog/
+P: 4096R/DC6DC026 A5C3 F68F 229D D60F 723E  6E13 8972 F4DF DC6D C026
+D: Various security things, bug fixes, and documentation.
 S: (ask for current address)
+S: Portland, Oregon
 S: USA
 
 N: Robin Cornelius
diff -druN linux-libre-3.1-gnu/crypto/ablkcipher.c linux-libre-3.2-gnu/crypto/ablkcipher.c
--- linux-libre-3.1-gnu/crypto/ablkcipher.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/ablkcipher.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,8 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include <crypto/scatterwalk.h>
 
@@ -381,6 +383,35 @@
 	return 0;
 }
 
+#ifdef CONFIG_NET
+static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_blkcipher rblkcipher;
+
+	snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "ablkcipher");
+	snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+		 alg->cra_ablkcipher.geniv ?: "<default>");
+
+	rblkcipher.blocksize = alg->cra_blocksize;
+	rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
+	rblkcipher.max_keysize = alg->cra_ablkcipher.max_keysize;
+	rblkcipher.ivsize = alg->cra_ablkcipher.ivsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
+		sizeof(struct crypto_report_blkcipher), &rblkcipher);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
@@ -403,6 +434,7 @@
 #ifdef CONFIG_PROC_FS
 	.show = crypto_ablkcipher_show,
 #endif
+	.report = crypto_ablkcipher_report,
 };
 EXPORT_SYMBOL_GPL(crypto_ablkcipher_type);
 
@@ -432,6 +464,35 @@
 	return 0;
 }
 
+#ifdef CONFIG_NET
+static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_blkcipher rblkcipher;
+
+	snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "givcipher");
+	snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+		 alg->cra_ablkcipher.geniv ?: "<built-in>");
+
+	rblkcipher.blocksize = alg->cra_blocksize;
+	rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
+	rblkcipher.max_keysize = alg->cra_ablkcipher.max_keysize;
+	rblkcipher.ivsize = alg->cra_ablkcipher.ivsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
+		sizeof(struct crypto_report_blkcipher), &rblkcipher);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
@@ -454,6 +515,7 @@
 #ifdef CONFIG_PROC_FS
 	.show = crypto_givcipher_show,
 #endif
+	.report = crypto_givcipher_report,
 };
 EXPORT_SYMBOL_GPL(crypto_givcipher_type);
 
diff -druN linux-libre-3.1-gnu/crypto/aead.c linux-libre-3.2-gnu/crypto/aead.c
--- linux-libre-3.1-gnu/crypto/aead.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/aead.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,8 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include "internal.h"
 
@@ -109,6 +111,35 @@
 	return 0;
 }
 
+#ifdef CONFIG_NET
+static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_aead raead;
+	struct aead_alg *aead = &alg->cra_aead;
+
+	snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "aead");
+	snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+		 aead->geniv ?: "<built-in>");
+
+	raead.blocksize = alg->cra_blocksize;
+	raead.maxauthsize = aead->maxauthsize;
+	raead.ivsize = aead->ivsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_AEAD,
+		sizeof(struct crypto_report_aead), &raead);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
@@ -130,6 +161,7 @@
 #ifdef CONFIG_PROC_FS
 	.show = crypto_aead_show,
 #endif
+	.report = crypto_aead_report,
 };
 EXPORT_SYMBOL_GPL(crypto_aead_type);
 
@@ -165,6 +197,35 @@
 	return 0;
 }
 
+#ifdef CONFIG_NET
+static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_aead raead;
+	struct aead_alg *aead = &alg->cra_aead;
+
+	snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "nivaead");
+	snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", aead->geniv);
+
+	raead.blocksize = alg->cra_blocksize;
+	raead.maxauthsize = aead->maxauthsize;
+	raead.ivsize = aead->ivsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_AEAD,
+		sizeof(struct crypto_report_aead), &raead);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
+
 static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
@@ -186,6 +247,7 @@
 #ifdef CONFIG_PROC_FS
 	.show = crypto_nivaead_show,
 #endif
+	.report = crypto_nivaead_report,
 };
 EXPORT_SYMBOL_GPL(crypto_nivaead_type);
 
diff -druN linux-libre-3.1-gnu/crypto/ahash.c linux-libre-3.2-gnu/crypto/ahash.c
--- linux-libre-3.1-gnu/crypto/ahash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/ahash.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,8 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include "internal.h"
 
@@ -397,6 +399,31 @@
 	return sizeof(struct crypto_shash *);
 }
 
+#ifdef CONFIG_NET
+static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_hash rhash;
+
+	snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "ahash");
+
+	rhash.blocksize = alg->cra_blocksize;
+	rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_HASH,
+		sizeof(struct crypto_report_hash), &rhash);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
@@ -415,6 +442,7 @@
 #ifdef CONFIG_PROC_FS
 	.show = crypto_ahash_show,
 #endif
+	.report = crypto_ahash_report,
 	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
 	.maskset = CRYPTO_ALG_TYPE_AHASH_MASK,
 	.type = CRYPTO_ALG_TYPE_AHASH,
diff -druN linux-libre-3.1-gnu/crypto/algapi.c linux-libre-3.2-gnu/crypto/algapi.c
--- linux-libre-3.1-gnu/crypto/algapi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/algapi.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,8 +22,6 @@
 
 #include "internal.h"
 
-static void crypto_remove_final(struct list_head *list);
-
 static LIST_HEAD(crypto_template_list);
 
 void crypto_larval_error(const char *name, u32 type, u32 mask)
@@ -129,9 +127,8 @@
 	BUG_ON(!list_empty(&inst->alg.cra_users));
 }
 
-static void crypto_remove_spawns(struct crypto_alg *alg,
-				 struct list_head *list,
-				 struct crypto_alg *nalg)
+void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
+			  struct crypto_alg *nalg)
 {
 	u32 new_type = (nalg ?: alg)->cra_flags;
 	struct crypto_spawn *spawn, *n;
@@ -177,6 +174,7 @@
 			crypto_remove_spawn(spawn, list);
 	}
 }
+EXPORT_SYMBOL_GPL(crypto_remove_spawns);
 
 static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
 {
@@ -321,7 +319,7 @@
 }
 EXPORT_SYMBOL_GPL(crypto_alg_tested);
 
-static void crypto_remove_final(struct list_head *list)
+void crypto_remove_final(struct list_head *list)
 {
 	struct crypto_alg *alg;
 	struct crypto_alg *n;
@@ -331,6 +329,7 @@
 		crypto_alg_put(alg);
 	}
 }
+EXPORT_SYMBOL_GPL(crypto_remove_final);
 
 static void crypto_wait_for_test(struct crypto_larval *larval)
 {
@@ -493,6 +492,7 @@
 		goto err;
 
 	inst->alg.cra_module = tmpl->module;
+	inst->alg.cra_flags |= CRYPTO_ALG_INSTANCE;
 
 	down_write(&crypto_alg_sem);
 
diff -druN linux-libre-3.1-gnu/crypto/async_tx/async_memcpy.c linux-libre-3.2-gnu/crypto/async_tx/async_memcpy.c
--- linux-libre-3.1-gnu/crypto/async_tx/async_memcpy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/async_tx/async_memcpy.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/highmem.h>
+#include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/async_tx.h>
diff -druN linux-libre-3.1-gnu/crypto/async_tx/async_pq.c linux-libre-3.2-gnu/crypto/async_tx/async_pq.c
--- linux-libre-3.1-gnu/crypto/async_tx/async_pq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/async_tx/async_pq.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/raid/pq.h>
 #include <linux/async_tx.h>
diff -druN linux-libre-3.1-gnu/crypto/async_tx/async_raid6_recov.c linux-libre-3.2-gnu/crypto/async_tx/async_raid6_recov.c
--- linux-libre-3.1-gnu/crypto/async_tx/async_raid6_recov.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/async_tx/async_raid6_recov.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/raid/pq.h>
 #include <linux/async_tx.h>
diff -druN linux-libre-3.1-gnu/crypto/async_tx/async_tx.c linux-libre-3.2-gnu/crypto/async_tx/async_tx.c
--- linux-libre-3.1-gnu/crypto/async_tx/async_tx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/async_tx/async_tx.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
  *
  */
 #include <linux/rculist.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/async_tx.h>
 
diff -druN linux-libre-3.1-gnu/crypto/async_tx/async_xor.c linux-libre-3.2-gnu/crypto/async_tx/async_xor.c
--- linux-libre-3.1-gnu/crypto/async_tx/async_xor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/async_tx/async_xor.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/raid/xor.h>
diff -druN linux-libre-3.1-gnu/crypto/async_tx/raid6test.c linux-libre-3.2-gnu/crypto/async_tx/raid6test.c
--- linux-libre-3.1-gnu/crypto/async_tx/raid6test.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/async_tx/raid6test.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/gfp.h>
 #include <linux/mm.h>
 #include <linux/random.h>
+#include <linux/module.h>
 
 #undef pr
 #define pr(fmt, args...) pr_info("raid6test: " fmt, ##args)
diff -druN linux-libre-3.1-gnu/crypto/blkcipher.c linux-libre-3.2-gnu/crypto/blkcipher.c
--- linux-libre-3.1-gnu/crypto/blkcipher.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/blkcipher.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include "internal.h"
 
@@ -492,6 +494,35 @@
 		return crypto_init_blkcipher_ops_async(tfm);
 }
 
+#ifdef CONFIG_NET
+static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_blkcipher rblkcipher;
+
+	snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "blkcipher");
+	snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+		 alg->cra_blkcipher.geniv ?: "<default>");
+
+	rblkcipher.blocksize = alg->cra_blocksize;
+	rblkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
+	rblkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
+	rblkcipher.ivsize = alg->cra_blkcipher.ivsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
+		sizeof(struct crypto_report_blkcipher), &rblkcipher);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
@@ -511,6 +542,7 @@
 #ifdef CONFIG_PROC_FS
 	.show = crypto_blkcipher_show,
 #endif
+	.report = crypto_blkcipher_report,
 };
 EXPORT_SYMBOL_GPL(crypto_blkcipher_type);
 
diff -druN linux-libre-3.1-gnu/crypto/blowfish.c linux-libre-3.2-gnu/crypto/blowfish.c
--- linux-libre-3.1-gnu/crypto/blowfish.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/blowfish.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,482 +0,0 @@
-/*
- * Cryptographic API.
- *
- * Blowfish Cipher Algorithm, by Bruce Schneier.
- * http://www.counterpane.com/blowfish.html
- *
- * Adapted from Kerneli implementation.
- *
- * Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org>
- * Copyright (c) Kyle McMartin <kyle@debian.org>
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/module.h>
-#include <linux/mm.h>
-#include <asm/byteorder.h>
-#include <linux/crypto.h>
-#include <linux/types.h>
-
-#define BF_BLOCK_SIZE 8
-#define BF_MIN_KEY_SIZE 4
-#define BF_MAX_KEY_SIZE 56
-
-struct bf_ctx {
-	u32 p[18];
-	u32 s[1024];
-};
-
-static const u32 bf_pbox[16 + 2] = {
-	0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
-	0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
-	0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
-	0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
-	0x9216d5d9, 0x8979fb1b,
-};
-
-static const u32 bf_sbox[256 * 4] = {
-	0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
-	0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
-	0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
-	0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
-	0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
-	0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
-	0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
-	0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
-	0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
-	0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
-	0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
-	0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
-	0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
-	0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
-	0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
-	0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
-	0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
-	0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
-	0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
-	0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
-	0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
-	0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
-	0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
-	0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
-	0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
-	0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
-	0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
-	0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
-	0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
-	0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
-	0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
-	0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
-	0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
-	0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
-	0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
-	0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
-	0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
-	0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
-	0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
-	0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
-	0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
-	0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
-	0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
-	0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
-	0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
-	0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
-	0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
-	0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
-	0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
-	0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
-	0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
-	0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
-	0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
-	0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
-	0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
-	0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
-	0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
-	0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
-	0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
-	0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
-	0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
-	0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
-	0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
-	0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
-	0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
-	0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
-	0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
-	0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
-	0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
-	0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
-	0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
-	0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
-	0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
-	0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
-	0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
-	0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
-	0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
-	0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
-	0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
-	0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
-	0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
-	0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
-	0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
-	0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
-	0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
-	0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
-	0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
-	0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
-	0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
-	0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
-	0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
-	0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
-	0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
-	0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
-	0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
-	0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
-	0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
-	0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
-	0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
-	0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
-	0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
-	0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
-	0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
-	0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
-	0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
-	0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
-	0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
-	0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
-	0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
-	0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
-	0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
-	0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
-	0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
-	0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
-	0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
-	0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
-	0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
-	0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
-	0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
-	0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
-	0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
-	0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
-	0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
-	0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
-	0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
-	0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
-	0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
-	0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
-	0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
-	0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
-	0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
-	0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
-	0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
-	0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
-	0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
-	0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
-	0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
-	0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
-	0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
-	0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
-	0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
-	0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
-	0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
-	0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
-	0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
-	0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
-	0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
-	0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
-	0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
-	0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
-	0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
-	0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
-	0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
-	0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
-	0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
-	0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
-	0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
-	0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
-	0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
-	0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
-	0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
-	0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
-	0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
-	0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
-	0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
-	0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
-	0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
-	0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
-	0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
-	0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
-	0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
-	0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
-	0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
-	0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
-	0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
-	0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
-	0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
-	0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
-	0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
-	0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
-	0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
-	0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
-	0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
-	0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
-	0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
-	0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
-	0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
-	0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
-	0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
-	0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
-	0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
-	0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
-	0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
-	0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
-	0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
-	0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
-	0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
-	0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
-	0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
-	0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
-	0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
-	0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
-	0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
-	0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
-	0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
-	0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
-	0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
-	0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
-	0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
-	0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
-	0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
-	0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
-	0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
-	0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
-	0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
-	0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
-	0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
-	0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
-	0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
-	0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
-	0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
-	0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
-	0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
-	0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
-	0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
-	0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
-	0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
-	0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
-	0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
-	0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
-	0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
-	0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
-	0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
-	0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
-	0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
-	0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
-	0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
-	0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
-	0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
-	0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
-	0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
-	0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
-	0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
-	0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
-	0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
-	0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
-	0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
-	0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
-	0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
-	0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
-	0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
-	0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
-	0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
-	0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
-	0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
-	0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
-};
-
-/*
- * Round loop unrolling macros, S is a pointer to a S-Box array
- * organized in 4 unsigned longs at a row.
- */
-#define GET32_3(x) (((x) & 0xff))
-#define GET32_2(x) (((x) >> (8)) & (0xff))
-#define GET32_1(x) (((x) >> (16)) & (0xff))
-#define GET32_0(x) (((x) >> (24)) & (0xff))
-
-#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \
-          S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
-
-#define ROUND(a, b, n)  b ^= P[n]; a ^= bf_F (b)
-
-/*
- * The blowfish encipher, processes 64-bit blocks.
- * NOTE: This function MUSTN'T respect endianess
- */
-static void encrypt_block(struct bf_ctx *bctx, u32 *dst, u32 *src)
-{
-	const u32 *P = bctx->p;
-	const u32 *S = bctx->s;
-	u32 yl = src[0];
-	u32 yr = src[1];
-
-	ROUND(yr, yl, 0);
-	ROUND(yl, yr, 1);
-	ROUND(yr, yl, 2);
-	ROUND(yl, yr, 3);
-	ROUND(yr, yl, 4);
-	ROUND(yl, yr, 5);
-	ROUND(yr, yl, 6);
-	ROUND(yl, yr, 7);
-	ROUND(yr, yl, 8);
-	ROUND(yl, yr, 9);
-	ROUND(yr, yl, 10);
-	ROUND(yl, yr, 11);
-	ROUND(yr, yl, 12);
-	ROUND(yl, yr, 13);
-	ROUND(yr, yl, 14);
-	ROUND(yl, yr, 15);
-
-	yl ^= P[16];
-	yr ^= P[17];
-
-	dst[0] = yr;
-	dst[1] = yl;
-}
-
-static void bf_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
-{
-	const __be32 *in_blk = (const __be32 *)src;
-	__be32 *const out_blk = (__be32 *)dst;
-	u32 in32[2], out32[2];
-
-	in32[0] = be32_to_cpu(in_blk[0]);
-	in32[1] = be32_to_cpu(in_blk[1]);
-	encrypt_block(crypto_tfm_ctx(tfm), out32, in32);
-	out_blk[0] = cpu_to_be32(out32[0]);
-	out_blk[1] = cpu_to_be32(out32[1]);
-}
-
-static void bf_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
-{
-	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
-	const __be32 *in_blk = (const __be32 *)src;
-	__be32 *const out_blk = (__be32 *)dst;
-	const u32 *P = ctx->p;
-	const u32 *S = ctx->s;
-	u32 yl = be32_to_cpu(in_blk[0]);
-	u32 yr = be32_to_cpu(in_blk[1]);
-
-	ROUND(yr, yl, 17);
-	ROUND(yl, yr, 16);
-	ROUND(yr, yl, 15);
-	ROUND(yl, yr, 14);
-	ROUND(yr, yl, 13);
-	ROUND(yl, yr, 12);
-	ROUND(yr, yl, 11);
-	ROUND(yl, yr, 10);
-	ROUND(yr, yl, 9);
-	ROUND(yl, yr, 8);
-	ROUND(yr, yl, 7);
-	ROUND(yl, yr, 6);
-	ROUND(yr, yl, 5);
-	ROUND(yl, yr, 4);
-	ROUND(yr, yl, 3);
-	ROUND(yl, yr, 2);
-
-	yl ^= P[1];
-	yr ^= P[0];
-
-	out_blk[0] = cpu_to_be32(yr);
-	out_blk[1] = cpu_to_be32(yl);
-}
-
-/*
- * Calculates the blowfish S and P boxes for encryption and decryption.
- */
-static int bf_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
-{
-	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
-	u32 *P = ctx->p;
-	u32 *S = ctx->s;
-	short i, j, count;
-	u32 data[2], temp;
-
-	/* Copy the initialization s-boxes */
-	for (i = 0, count = 0; i < 256; i++)
-		for (j = 0; j < 4; j++, count++)
-			S[count] = bf_sbox[count];
-
-	/* Set the p-boxes */
-	for (i = 0; i < 16 + 2; i++)
-		P[i] = bf_pbox[i];
-
-	/* Actual subkey generation */
-	for (j = 0, i = 0; i < 16 + 2; i++) {
-		temp = (((u32)key[j] << 24) |
-			((u32)key[(j + 1) % keylen] << 16) |
-			((u32)key[(j + 2) % keylen] << 8) |
-			((u32)key[(j + 3) % keylen]));
-
-		P[i] = P[i] ^ temp;
-		j = (j + 4) % keylen;
-	}
-
-	data[0] = 0x00000000;
-	data[1] = 0x00000000;
-
-	for (i = 0; i < 16 + 2; i += 2) {
-		encrypt_block((struct bf_ctx *)ctx, data, data);
-
-		P[i] = data[0];
-		P[i + 1] = data[1];
-	}
-
-	for (i = 0; i < 4; i++) {
-		for (j = 0, count = i * 256; j < 256; j += 2, count += 2) {
-			encrypt_block((struct bf_ctx *)ctx, data, data);
-
-			S[count] = data[0];
-			S[count + 1] = data[1];
-		}
-	}
-
-	/* Bruce says not to bother with the weak key check. */
-	return 0;
-}
-
-static struct crypto_alg alg = {
-	.cra_name		=	"blowfish",
-	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
-	.cra_blocksize		=	BF_BLOCK_SIZE,
-	.cra_ctxsize		=	sizeof(struct bf_ctx),
-	.cra_alignmask		=	3,
-	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(alg.cra_list),
-	.cra_u			=	{ .cipher = {
-	.cia_min_keysize	=	BF_MIN_KEY_SIZE,
-	.cia_max_keysize	=	BF_MAX_KEY_SIZE,
-	.cia_setkey   		= 	bf_setkey,
-	.cia_encrypt 		=	bf_encrypt,
-	.cia_decrypt  		=	bf_decrypt } }
-};
-
-static int __init blowfish_mod_init(void)
-{
-	return crypto_register_alg(&alg);
-}
-
-static void __exit blowfish_mod_fini(void)
-{
-	crypto_unregister_alg(&alg);
-}
-
-module_init(blowfish_mod_init);
-module_exit(blowfish_mod_fini);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Blowfish Cipher Algorithm");
diff -druN linux-libre-3.1-gnu/crypto/blowfish_common.c linux-libre-3.2-gnu/crypto/blowfish_common.c
--- linux-libre-3.1-gnu/crypto/blowfish_common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/crypto/blowfish_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,402 @@
+/*
+ * Cryptographic API.
+ *
+ * Common Blowfish algorithm parts shared between the c and assembler
+ * implementations.
+ *
+ * Blowfish Cipher Algorithm, by Bruce Schneier.
+ * http://www.counterpane.com/blowfish.html
+ *
+ * Adapted from Kerneli implementation.
+ *
+ * Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org>
+ * Copyright (c) Kyle McMartin <kyle@debian.org>
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/module.h>
+#include <linux/mm.h>
+#include <asm/byteorder.h>
+#include <linux/crypto.h>
+#include <linux/types.h>
+#include <crypto/blowfish.h>
+
+static const u32 bf_pbox[16 + 2] = {
+	0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
+	0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
+	0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+	0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
+	0x9216d5d9, 0x8979fb1b,
+};
+
+static const u32 bf_sbox[256 * 4] = {
+	0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+	0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+	0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+	0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+	0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
+	0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+	0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
+	0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+	0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+	0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+	0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
+	0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+	0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
+	0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+	0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+	0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+	0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
+	0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+	0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
+	0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+	0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+	0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+	0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
+	0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+	0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
+	0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
+	0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+	0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+	0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
+	0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+	0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
+	0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+	0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+	0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+	0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
+	0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+	0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
+	0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
+	0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+	0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+	0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
+	0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+	0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
+	0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
+	0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+	0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+	0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
+	0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+	0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
+	0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+	0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+	0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+	0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
+	0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+	0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
+	0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+	0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+	0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+	0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
+	0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+	0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+	0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+	0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+	0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
+	0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
+	0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+	0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+	0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
+	0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
+	0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+	0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
+	0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
+	0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+	0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
+	0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
+	0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+	0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
+	0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+	0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+	0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
+	0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
+	0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+	0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
+	0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
+	0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+	0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
+	0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
+	0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+	0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
+	0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
+	0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+	0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
+	0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
+	0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+	0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
+	0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
+	0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+	0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
+	0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
+	0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+	0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
+	0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
+	0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+	0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
+	0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
+	0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+	0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
+	0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
+	0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+	0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
+	0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
+	0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+	0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
+	0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
+	0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+	0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
+	0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
+	0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+	0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
+	0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
+	0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+	0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
+	0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
+	0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+	0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
+	0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+	0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+	0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
+	0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
+	0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+	0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+	0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+	0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
+	0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+	0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
+	0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+	0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+	0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
+	0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
+	0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+	0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
+	0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+	0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+	0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
+	0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
+	0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+	0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
+	0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+	0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+	0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+	0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
+	0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+	0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
+	0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+	0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+	0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
+	0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
+	0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+	0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
+	0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+	0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+	0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
+	0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
+	0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+	0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
+	0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+	0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+	0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+	0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
+	0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+	0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
+	0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+	0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+	0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
+	0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
+	0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+	0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
+	0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
+	0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+	0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
+	0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
+	0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+	0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
+	0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+	0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+	0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+	0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
+	0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+	0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
+	0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+	0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+	0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
+	0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
+	0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+	0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+	0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+	0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
+	0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+	0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
+	0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
+	0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+	0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
+	0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
+	0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+	0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
+	0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
+	0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+	0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
+	0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
+	0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+	0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
+	0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
+	0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+	0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+	0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
+	0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+	0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
+	0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
+	0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+	0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
+	0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
+	0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+	0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
+	0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
+	0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+	0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
+	0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
+	0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+	0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
+	0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
+	0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+	0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
+	0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
+	0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+	0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
+	0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
+	0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+	0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+	0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
+	0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+	0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
+	0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
+	0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+	0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
+	0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
+	0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+	0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
+	0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
+	0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+	0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
+	0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
+	0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+	0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
+	0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+	0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+	0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
+};
+
+/*
+ * Round loop unrolling macros, S is a pointer to a S-Box array
+ * organized in 4 unsigned longs at a row.
+ */
+#define GET32_3(x) (((x) & 0xff))
+#define GET32_2(x) (((x) >> (8)) & (0xff))
+#define GET32_1(x) (((x) >> (16)) & (0xff))
+#define GET32_0(x) (((x) >> (24)) & (0xff))
+
+#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \
+		S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
+
+#define ROUND(a, b, n) ({ b ^= P[n]; a ^= bf_F(b); })
+
+/*
+ * The blowfish encipher, processes 64-bit blocks.
+ * NOTE: This function MUSTN'T respect endianess
+ */
+static void encrypt_block(struct bf_ctx *bctx, u32 *dst, u32 *src)
+{
+	const u32 *P = bctx->p;
+	const u32 *S = bctx->s;
+	u32 yl = src[0];
+	u32 yr = src[1];
+
+	ROUND(yr, yl, 0);
+	ROUND(yl, yr, 1);
+	ROUND(yr, yl, 2);
+	ROUND(yl, yr, 3);
+	ROUND(yr, yl, 4);
+	ROUND(yl, yr, 5);
+	ROUND(yr, yl, 6);
+	ROUND(yl, yr, 7);
+	ROUND(yr, yl, 8);
+	ROUND(yl, yr, 9);
+	ROUND(yr, yl, 10);
+	ROUND(yl, yr, 11);
+	ROUND(yr, yl, 12);
+	ROUND(yl, yr, 13);
+	ROUND(yr, yl, 14);
+	ROUND(yl, yr, 15);
+
+	yl ^= P[16];
+	yr ^= P[17];
+
+	dst[0] = yr;
+	dst[1] = yl;
+}
+
+/*
+ * Calculates the blowfish S and P boxes for encryption and decryption.
+ */
+int blowfish_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
+	u32 *P = ctx->p;
+	u32 *S = ctx->s;
+	short i, j, count;
+	u32 data[2], temp;
+
+	/* Copy the initialization s-boxes */
+	for (i = 0, count = 0; i < 256; i++)
+		for (j = 0; j < 4; j++, count++)
+			S[count] = bf_sbox[count];
+
+	/* Set the p-boxes */
+	for (i = 0; i < 16 + 2; i++)
+		P[i] = bf_pbox[i];
+
+	/* Actual subkey generation */
+	for (j = 0, i = 0; i < 16 + 2; i++) {
+		temp = (((u32)key[j] << 24) |
+			((u32)key[(j + 1) % keylen] << 16) |
+			((u32)key[(j + 2) % keylen] << 8) |
+			((u32)key[(j + 3) % keylen]));
+
+		P[i] = P[i] ^ temp;
+		j = (j + 4) % keylen;
+	}
+
+	data[0] = 0x00000000;
+	data[1] = 0x00000000;
+
+	for (i = 0; i < 16 + 2; i += 2) {
+		encrypt_block((struct bf_ctx *)ctx, data, data);
+
+		P[i] = data[0];
+		P[i + 1] = data[1];
+	}
+
+	for (i = 0; i < 4; i++) {
+		for (j = 0, count = i * 256; j < 256; j += 2, count += 2) {
+			encrypt_block((struct bf_ctx *)ctx, data, data);
+
+			S[count] = data[0];
+			S[count + 1] = data[1];
+		}
+	}
+
+	/* Bruce says not to bother with the weak key check. */
+	return 0;
+}
+EXPORT_SYMBOL_GPL(blowfish_setkey);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Blowfish Cipher common functions");
diff -druN linux-libre-3.1-gnu/crypto/blowfish_generic.c linux-libre-3.2-gnu/crypto/blowfish_generic.c
--- linux-libre-3.1-gnu/crypto/blowfish_generic.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/crypto/blowfish_generic.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,142 @@
+/*
+ * Cryptographic API.
+ *
+ * Blowfish Cipher Algorithm, by Bruce Schneier.
+ * http://www.counterpane.com/blowfish.html
+ *
+ * Adapted from Kerneli implementation.
+ *
+ * Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org>
+ * Copyright (c) Kyle McMartin <kyle@debian.org>
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/module.h>
+#include <linux/mm.h>
+#include <asm/byteorder.h>
+#include <linux/crypto.h>
+#include <linux/types.h>
+#include <crypto/blowfish.h>
+
+/*
+ * Round loop unrolling macros, S is a pointer to a S-Box array
+ * organized in 4 unsigned longs at a row.
+ */
+#define GET32_3(x) (((x) & 0xff))
+#define GET32_2(x) (((x) >> (8)) & (0xff))
+#define GET32_1(x) (((x) >> (16)) & (0xff))
+#define GET32_0(x) (((x) >> (24)) & (0xff))
+
+#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \
+		S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
+
+#define ROUND(a, b, n) ({ b ^= P[n]; a ^= bf_F(b); })
+
+static void bf_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
+	const __be32 *in_blk = (const __be32 *)src;
+	__be32 *const out_blk = (__be32 *)dst;
+	const u32 *P = ctx->p;
+	const u32 *S = ctx->s;
+	u32 yl = be32_to_cpu(in_blk[0]);
+	u32 yr = be32_to_cpu(in_blk[1]);
+
+	ROUND(yr, yl, 0);
+	ROUND(yl, yr, 1);
+	ROUND(yr, yl, 2);
+	ROUND(yl, yr, 3);
+	ROUND(yr, yl, 4);
+	ROUND(yl, yr, 5);
+	ROUND(yr, yl, 6);
+	ROUND(yl, yr, 7);
+	ROUND(yr, yl, 8);
+	ROUND(yl, yr, 9);
+	ROUND(yr, yl, 10);
+	ROUND(yl, yr, 11);
+	ROUND(yr, yl, 12);
+	ROUND(yl, yr, 13);
+	ROUND(yr, yl, 14);
+	ROUND(yl, yr, 15);
+
+	yl ^= P[16];
+	yr ^= P[17];
+
+	out_blk[0] = cpu_to_be32(yr);
+	out_blk[1] = cpu_to_be32(yl);
+}
+
+static void bf_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
+	const __be32 *in_blk = (const __be32 *)src;
+	__be32 *const out_blk = (__be32 *)dst;
+	const u32 *P = ctx->p;
+	const u32 *S = ctx->s;
+	u32 yl = be32_to_cpu(in_blk[0]);
+	u32 yr = be32_to_cpu(in_blk[1]);
+
+	ROUND(yr, yl, 17);
+	ROUND(yl, yr, 16);
+	ROUND(yr, yl, 15);
+	ROUND(yl, yr, 14);
+	ROUND(yr, yl, 13);
+	ROUND(yl, yr, 12);
+	ROUND(yr, yl, 11);
+	ROUND(yl, yr, 10);
+	ROUND(yr, yl, 9);
+	ROUND(yl, yr, 8);
+	ROUND(yr, yl, 7);
+	ROUND(yl, yr, 6);
+	ROUND(yr, yl, 5);
+	ROUND(yl, yr, 4);
+	ROUND(yr, yl, 3);
+	ROUND(yl, yr, 2);
+
+	yl ^= P[1];
+	yr ^= P[0];
+
+	out_blk[0] = cpu_to_be32(yr);
+	out_blk[1] = cpu_to_be32(yl);
+}
+
+static struct crypto_alg alg = {
+	.cra_name		=	"blowfish",
+	.cra_driver_name	=	"blowfish-generic",
+	.cra_priority		=	100,
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	BF_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof(struct bf_ctx),
+	.cra_alignmask		=	3,
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(alg.cra_list),
+	.cra_u			=	{ .cipher = {
+	.cia_min_keysize	=	BF_MIN_KEY_SIZE,
+	.cia_max_keysize	=	BF_MAX_KEY_SIZE,
+	.cia_setkey		=	blowfish_setkey,
+	.cia_encrypt		=	bf_encrypt,
+	.cia_decrypt		=	bf_decrypt } }
+};
+
+static int __init blowfish_mod_init(void)
+{
+	return crypto_register_alg(&alg);
+}
+
+static void __exit blowfish_mod_fini(void)
+{
+	crypto_unregister_alg(&alg);
+}
+
+module_init(blowfish_mod_init);
+module_exit(blowfish_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Blowfish Cipher Algorithm");
+MODULE_ALIAS("blowfish");
diff -druN linux-libre-3.1-gnu/crypto/cryptd.c linux-libre-3.2-gnu/crypto/cryptd.c
--- linux-libre-3.1-gnu/crypto/cryptd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/cryptd.c	2012-01-04 18:55:44.000000000 -0500
@@ -945,7 +945,7 @@
 	crypto_unregister_template(&cryptd_tmpl);
 }
 
-module_init(cryptd_init);
+subsys_initcall(cryptd_init);
 module_exit(cryptd_exit);
 
 MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/crypto/crypto_user.c linux-libre-3.2-gnu/crypto/crypto_user.c
--- linux-libre-3.1-gnu/crypto/crypto_user.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/crypto/crypto_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,435 @@
+/*
+ * Crypto user configuration API.
+ *
+ * Copyright (C) 2011 secunet Security Networks AG
+ * Copyright (C) 2011 Steffen Klassert <steffen.klassert@secunet.com>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
+#include <linux/security.h>
+#include <net/net_namespace.h>
+#include "internal.h"
+
+DEFINE_MUTEX(crypto_cfg_mutex);
+
+/* The crypto netlink socket */
+static struct sock *crypto_nlsk;
+
+struct crypto_dump_info {
+	struct sk_buff *in_skb;
+	struct sk_buff *out_skb;
+	u32 nlmsg_seq;
+	u16 nlmsg_flags;
+};
+
+static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact)
+{
+	struct crypto_alg *q, *alg = NULL;
+
+	down_read(&crypto_alg_sem);
+
+	list_for_each_entry(q, &crypto_alg_list, cra_list) {
+		int match = 0;
+
+		if ((q->cra_flags ^ p->cru_type) & p->cru_mask)
+			continue;
+
+		if (strlen(p->cru_driver_name))
+			match = !strcmp(q->cra_driver_name,
+					p->cru_driver_name);
+		else if (!exact)
+			match = !strcmp(q->cra_name, p->cru_name);
+
+		if (match) {
+			alg = q;
+			break;
+		}
+	}
+
+	up_read(&crypto_alg_sem);
+
+	return alg;
+}
+
+static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_cipher rcipher;
+
+	snprintf(rcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "cipher");
+
+	rcipher.blocksize = alg->cra_blocksize;
+	rcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
+	rcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_CIPHER,
+		sizeof(struct crypto_report_cipher), &rcipher);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_comp rcomp;
+
+	snprintf(rcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "compression");
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_COMPRESS,
+		sizeof(struct crypto_report_comp), &rcomp);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int crypto_report_one(struct crypto_alg *alg,
+			     struct crypto_user_alg *ualg, struct sk_buff *skb)
+{
+	memcpy(&ualg->cru_name, &alg->cra_name, sizeof(ualg->cru_name));
+	memcpy(&ualg->cru_driver_name, &alg->cra_driver_name,
+	       sizeof(ualg->cru_driver_name));
+	memcpy(&ualg->cru_module_name, module_name(alg->cra_module),
+	       CRYPTO_MAX_ALG_NAME);
+
+	ualg->cru_flags = alg->cra_flags;
+	ualg->cru_refcnt = atomic_read(&alg->cra_refcnt);
+
+	NLA_PUT_U32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority);
+
+	if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
+		struct crypto_report_larval rl;
+
+		snprintf(rl.type, CRYPTO_MAX_ALG_NAME, "%s", "larval");
+
+		NLA_PUT(skb, CRYPTOCFGA_REPORT_LARVAL,
+			sizeof(struct crypto_report_larval), &rl);
+
+		goto out;
+	}
+
+	if (alg->cra_type && alg->cra_type->report) {
+		if (alg->cra_type->report(skb, alg))
+			goto nla_put_failure;
+
+		goto out;
+	}
+
+	switch (alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL)) {
+	case CRYPTO_ALG_TYPE_CIPHER:
+		if (crypto_report_cipher(skb, alg))
+			goto nla_put_failure;
+
+		break;
+	case CRYPTO_ALG_TYPE_COMPRESS:
+		if (crypto_report_comp(skb, alg))
+			goto nla_put_failure;
+
+		break;
+	}
+
+out:
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int crypto_report_alg(struct crypto_alg *alg,
+			     struct crypto_dump_info *info)
+{
+	struct sk_buff *in_skb = info->in_skb;
+	struct sk_buff *skb = info->out_skb;
+	struct nlmsghdr *nlh;
+	struct crypto_user_alg *ualg;
+	int err = 0;
+
+	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, info->nlmsg_seq,
+			CRYPTO_MSG_GETALG, sizeof(*ualg), info->nlmsg_flags);
+	if (!nlh) {
+		err = -EMSGSIZE;
+		goto out;
+	}
+
+	ualg = nlmsg_data(nlh);
+
+	err = crypto_report_one(alg, ualg, skb);
+	if (err) {
+		nlmsg_cancel(skb, nlh);
+		goto out;
+	}
+
+	nlmsg_end(skb, nlh);
+
+out:
+	return err;
+}
+
+static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
+			 struct nlattr **attrs)
+{
+	struct crypto_user_alg *p = nlmsg_data(in_nlh);
+	struct crypto_alg *alg;
+	struct sk_buff *skb;
+	struct crypto_dump_info info;
+	int err;
+
+	if (!p->cru_driver_name)
+		return -EINVAL;
+
+	alg = crypto_alg_match(p, 1);
+	if (!alg)
+		return -ENOENT;
+
+	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
+
+	info.in_skb = in_skb;
+	info.out_skb = skb;
+	info.nlmsg_seq = in_nlh->nlmsg_seq;
+	info.nlmsg_flags = 0;
+
+	err = crypto_report_alg(alg, &info);
+	if (err)
+		return err;
+
+	return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).pid);
+}
+
+static int crypto_dump_report(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct crypto_alg *alg;
+	struct crypto_dump_info info;
+	int err;
+
+	if (cb->args[0])
+		goto out;
+
+	cb->args[0] = 1;
+
+	info.in_skb = cb->skb;
+	info.out_skb = skb;
+	info.nlmsg_seq = cb->nlh->nlmsg_seq;
+	info.nlmsg_flags = NLM_F_MULTI;
+
+	list_for_each_entry(alg, &crypto_alg_list, cra_list) {
+		err = crypto_report_alg(alg, &info);
+		if (err)
+			goto out_err;
+	}
+
+out:
+	return skb->len;
+out_err:
+	return err;
+}
+
+static int crypto_dump_report_done(struct netlink_callback *cb)
+{
+	return 0;
+}
+
+static int crypto_update_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
+			     struct nlattr **attrs)
+{
+	struct crypto_alg *alg;
+	struct crypto_user_alg *p = nlmsg_data(nlh);
+	struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL];
+	LIST_HEAD(list);
+
+	if (priority && !strlen(p->cru_driver_name))
+		return -EINVAL;
+
+	alg = crypto_alg_match(p, 1);
+	if (!alg)
+		return -ENOENT;
+
+	down_write(&crypto_alg_sem);
+
+	crypto_remove_spawns(alg, &list, NULL);
+
+	if (priority)
+		alg->cra_priority = nla_get_u32(priority);
+
+	up_write(&crypto_alg_sem);
+
+	crypto_remove_final(&list);
+
+	return 0;
+}
+
+static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
+			  struct nlattr **attrs)
+{
+	struct crypto_alg *alg;
+	struct crypto_user_alg *p = nlmsg_data(nlh);
+
+	alg = crypto_alg_match(p, 1);
+	if (!alg)
+		return -ENOENT;
+
+	/* We can not unregister core algorithms such as aes-generic.
+	 * We would loose the reference in the crypto_alg_list to this algorithm
+	 * if we try to unregister. Unregistering such an algorithm without
+	 * removing the module is not possible, so we restrict to crypto
+	 * instances that are build from templates. */
+	if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE))
+		return -EINVAL;
+
+	if (atomic_read(&alg->cra_refcnt) != 1)
+		return -EBUSY;
+
+	return crypto_unregister_alg(alg);
+}
+
+static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
+			  struct nlattr **attrs)
+{
+	int exact;
+	const char *name;
+	struct crypto_alg *alg;
+	struct crypto_user_alg *p = nlmsg_data(nlh);
+	struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL];
+
+	if (strlen(p->cru_driver_name))
+		exact = 1;
+
+	if (priority && !exact)
+		return -EINVAL;
+
+	alg = crypto_alg_match(p, exact);
+	if (alg)
+		return -EEXIST;
+
+	if (strlen(p->cru_driver_name))
+		name = p->cru_driver_name;
+	else
+		name = p->cru_name;
+
+	alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask);
+	if (IS_ERR(alg))
+		return PTR_ERR(alg);
+
+	down_write(&crypto_alg_sem);
+
+	if (priority)
+		alg->cra_priority = nla_get_u32(priority);
+
+	up_write(&crypto_alg_sem);
+
+	crypto_mod_put(alg);
+
+	return 0;
+}
+
+#define MSGSIZE(type) sizeof(struct type)
+
+static const int crypto_msg_min[CRYPTO_NR_MSGTYPES] = {
+	[CRYPTO_MSG_NEWALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+	[CRYPTO_MSG_DELALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+	[CRYPTO_MSG_UPDATEALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+	[CRYPTO_MSG_GETALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+};
+
+static const struct nla_policy crypto_policy[CRYPTOCFGA_MAX+1] = {
+	[CRYPTOCFGA_PRIORITY_VAL]   = { .type = NLA_U32},
+};
+
+#undef MSGSIZE
+
+static struct crypto_link {
+	int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
+	int (*dump)(struct sk_buff *, struct netlink_callback *);
+	int (*done)(struct netlink_callback *);
+} crypto_dispatch[CRYPTO_NR_MSGTYPES] = {
+	[CRYPTO_MSG_NEWALG	- CRYPTO_MSG_BASE] = { .doit = crypto_add_alg},
+	[CRYPTO_MSG_DELALG	- CRYPTO_MSG_BASE] = { .doit = crypto_del_alg},
+	[CRYPTO_MSG_UPDATEALG	- CRYPTO_MSG_BASE] = { .doit = crypto_update_alg},
+	[CRYPTO_MSG_GETALG	- CRYPTO_MSG_BASE] = { .doit = crypto_report,
+						       .dump = crypto_dump_report,
+						       .done = crypto_dump_report_done},
+};
+
+static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+{
+	struct nlattr *attrs[CRYPTOCFGA_MAX+1];
+	struct crypto_link *link;
+	int type, err;
+
+	type = nlh->nlmsg_type;
+	if (type > CRYPTO_MSG_MAX)
+		return -EINVAL;
+
+	type -= CRYPTO_MSG_BASE;
+	link = &crypto_dispatch[type];
+
+	if (security_netlink_recv(skb, CAP_NET_ADMIN))
+		return -EPERM;
+
+	if ((type == (CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE) &&
+	    (nlh->nlmsg_flags & NLM_F_DUMP))) {
+		if (link->dump == NULL)
+			return -EINVAL;
+
+		return netlink_dump_start(crypto_nlsk, skb, nlh,
+					  link->dump, link->done, 0);
+	}
+
+	err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
+			  crypto_policy);
+	if (err < 0)
+		return err;
+
+	if (link->doit == NULL)
+		return -EINVAL;
+
+	return link->doit(skb, nlh, attrs);
+}
+
+static void crypto_netlink_rcv(struct sk_buff *skb)
+{
+	mutex_lock(&crypto_cfg_mutex);
+	netlink_rcv_skb(skb, &crypto_user_rcv_msg);
+	mutex_unlock(&crypto_cfg_mutex);
+}
+
+static int __init crypto_user_init(void)
+{
+	crypto_nlsk = netlink_kernel_create(&init_net, NETLINK_CRYPTO,
+					    0, crypto_netlink_rcv,
+					    NULL, THIS_MODULE);
+	if (!crypto_nlsk)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void __exit crypto_user_exit(void)
+{
+	netlink_kernel_release(crypto_nlsk);
+}
+
+module_init(crypto_user_init);
+module_exit(crypto_user_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
+MODULE_DESCRIPTION("Crypto userspace configuration API");
diff -druN linux-libre-3.1-gnu/crypto/crypto_wq.c linux-libre-3.2-gnu/crypto/crypto_wq.c
--- linux-libre-3.1-gnu/crypto/crypto_wq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/crypto_wq.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
  */
 
 #include <linux/workqueue.h>
+#include <linux/module.h>
 #include <crypto/algapi.h>
 #include <crypto/crypto_wq.h>
 
diff -druN linux-libre-3.1-gnu/crypto/internal.h linux-libre-3.2-gnu/crypto/internal.h
--- linux-libre-3.1-gnu/crypto/internal.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/internal.h	2012-01-04 18:55:44.000000000 -0500
@@ -86,6 +86,9 @@
 void crypto_larval_error(const char *name, u32 type, u32 mask);
 void crypto_alg_tested(const char *name, int err);
 
+void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
+			  struct crypto_alg *nalg);
+void crypto_remove_final(struct list_head *list);
 void crypto_shoot_alg(struct crypto_alg *alg);
 struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
 				      u32 mask);
diff -druN linux-libre-3.1-gnu/crypto/Kconfig linux-libre-3.2-gnu/crypto/Kconfig
--- linux-libre-3.1-gnu/crypto/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -100,6 +100,14 @@
 	select CRYPTO_BLKCIPHER2
 	select CRYPTO_PCOMP2
 
+config CRYPTO_USER
+	tristate "Userspace cryptographic algorithm configuration"
+	depends on NET
+	select CRYPTO_MANAGER
+	help
+	  Userapace configuration for cryptographic instantiations such as
+	  cbc(aes).
+
 config CRYPTO_MANAGER_DISABLE_TESTS
 	bool "Disable run-time self tests"
 	default y
@@ -407,6 +415,16 @@
 	help
 	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
 
+config CRYPTO_SHA1_SSSE3
+	tristate "SHA1 digest algorithm (SSSE3/AVX)"
+	depends on X86 && 64BIT
+	select CRYPTO_SHA1
+	select CRYPTO_HASH
+	help
+	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented
+	  using Supplemental SSE3 (SSSE3) instructions or Advanced Vector
+	  Extensions (AVX), when available.
+
 config CRYPTO_SHA256
 	tristate "SHA224 and SHA256 digest algorithm"
 	select CRYPTO_HASH
@@ -590,6 +608,7 @@
 config CRYPTO_BLOWFISH
 	tristate "Blowfish cipher algorithm"
 	select CRYPTO_ALGAPI
+	select CRYPTO_BLOWFISH_COMMON
 	help
 	  Blowfish cipher algorithm, by Bruce Schneier.
 
@@ -600,6 +619,30 @@
 	  See also:
 	  <http://www.schneier.com/blowfish.html>
 
+config CRYPTO_BLOWFISH_COMMON
+	tristate
+	help
+	  Common parts of the Blowfish cipher algorithm shared by the
+	  generic c and the assembler implementations.
+
+	  See also:
+	  <http://www.schneier.com/blowfish.html>
+
+config CRYPTO_BLOWFISH_X86_64
+	tristate "Blowfish cipher algorithm (x86_64)"
+	depends on (X86 || UML_X86) && 64BIT
+	select CRYPTO_ALGAPI
+	select CRYPTO_BLOWFISH_COMMON
+	help
+	  Blowfish cipher algorithm (x86_64), by Bruce Schneier.
+
+	  This is a variable key length cipher which can use keys from 32
+	  bits to 448 bits in length.  It's fast, simple and specifically
+	  designed for use on "large microprocessors".
+
+	  See also:
+	  <http://www.schneier.com/blowfish.html>
+
 config CRYPTO_CAMELLIA
 	tristate "Camellia cipher algorithms"
 	depends on CRYPTO
@@ -792,6 +835,26 @@
 
 	  See also:
 	  <http://www.schneier.com/twofish.html>
+
+config CRYPTO_TWOFISH_X86_64_3WAY
+	tristate "Twofish cipher algorithm (x86_64, 3-way parallel)"
+	depends on (X86 || UML_X86) && 64BIT
+	select CRYPTO_ALGAPI
+	select CRYPTO_TWOFISH_COMMON
+	select CRYPTO_TWOFISH_X86_64
+	help
+	  Twofish cipher algorithm (x86_64, 3-way parallel).
+
+	  Twofish was submitted as an AES (Advanced Encryption Standard)
+	  candidate cipher by researchers at CounterPane Systems.  It is a
+	  16 round block cipher supporting key sizes of 128, 192, and 256
+	  bits.
+
+	  This module provides Twofish cipher algorithm that processes three
+	  blocks parallel, utilizing resources of out-of-order CPUs better.
+
+	  See also:
+	  <http://www.schneier.com/twofish.html>
 
 comment "Compression"
 
diff -druN linux-libre-3.1-gnu/crypto/Makefile linux-libre-3.2-gnu/crypto/Makefile
--- linux-libre-3.1-gnu/crypto/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 cryptomgr-y := algboss.o testmgr.o
 
 obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
+obj-$(CONFIG_CRYPTO_USER) += crypto_user.o
 obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
 obj-$(CONFIG_CRYPTO_VMAC) += vmac.o
 obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o
@@ -60,7 +61,8 @@
 obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o
 obj-$(CONFIG_CRYPTO_DES) += des_generic.o
 obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
-obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
+obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish_generic.o
+obj-$(CONFIG_CRYPTO_BLOWFISH_COMMON) += blowfish_common.o
 obj-$(CONFIG_CRYPTO_TWOFISH) += twofish_generic.o
 obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o
 obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o
diff -druN linux-libre-3.1-gnu/crypto/md4.c linux-libre-3.2-gnu/crypto/md4.c
--- linux-libre-3.1-gnu/crypto/md4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/md4.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <crypto/internal/hash.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/string.h>
 #include <linux/types.h>
 #include <asm/byteorder.h>
diff -druN linux-libre-3.1-gnu/crypto/pcompress.c linux-libre-3.2-gnu/crypto/pcompress.c
--- linux-libre-3.1-gnu/crypto/pcompress.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/pcompress.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
 #include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/string.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include <crypto/compress.h>
 #include <crypto/internal/compress.h>
@@ -46,6 +48,28 @@
 	return 0;
 }
 
+#ifdef CONFIG_NET
+static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_comp rpcomp;
+
+	snprintf(rpcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "pcomp");
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_COMPRESS,
+		sizeof(struct crypto_report_comp), &rpcomp);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg)
@@ -60,6 +84,7 @@
 #ifdef CONFIG_PROC_FS
 	.show		= crypto_pcomp_show,
 #endif
+	.report		= crypto_pcomp_report,
 	.maskclear	= ~CRYPTO_ALG_TYPE_MASK,
 	.maskset	= CRYPTO_ALG_TYPE_MASK,
 	.type		= CRYPTO_ALG_TYPE_PCOMPRESS,
diff -druN linux-libre-3.1-gnu/crypto/proc.c linux-libre-3.2-gnu/crypto/proc.c
--- linux-libre-3.1-gnu/crypto/proc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/proc.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/atomic.h>
 #include <linux/init.h>
 #include <linux/crypto.h>
+#include <linux/module.h>	/* for module_name() */
 #include <linux/rwsem.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
diff -druN linux-libre-3.1-gnu/crypto/rng.c linux-libre-3.2-gnu/crypto/rng.c
--- linux-libre-3.1-gnu/crypto/rng.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/rng.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,8 @@
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 static DEFINE_MUTEX(crypto_default_rng_lock);
 struct crypto_rng *crypto_default_rng;
@@ -58,6 +60,30 @@
 	return 0;
 }
 
+#ifdef CONFIG_NET
+static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_rng rrng;
+
+	snprintf(rrng.type, CRYPTO_MAX_ALG_NAME, "%s", "rng");
+
+	rrng.seedsize = alg->cra_rng.seedsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_RNG,
+		sizeof(struct crypto_report_rng), &rrng);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
@@ -78,6 +104,7 @@
 #ifdef CONFIG_PROC_FS
 	.show = crypto_rng_show,
 #endif
+	.report = crypto_rng_report,
 };
 EXPORT_SYMBOL_GPL(crypto_rng_type);
 
diff -druN linux-libre-3.1-gnu/crypto/sha1_generic.c linux-libre-3.2-gnu/crypto/sha1_generic.c
--- linux-libre-3.1-gnu/crypto/sha1_generic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/sha1_generic.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,7 +36,7 @@
 	return 0;
 }
 
-static int sha1_update(struct shash_desc *desc, const u8 *data,
+int crypto_sha1_update(struct shash_desc *desc, const u8 *data,
 			unsigned int len)
 {
 	struct sha1_state *sctx = shash_desc_ctx(desc);
@@ -71,6 +71,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(crypto_sha1_update);
 
 
 /* Add padding and return the message digest. */
@@ -87,10 +88,10 @@
 	/* Pad out to 56 mod 64 */
 	index = sctx->count & 0x3f;
 	padlen = (index < 56) ? (56 - index) : ((64+56) - index);
-	sha1_update(desc, padding, padlen);
+	crypto_sha1_update(desc, padding, padlen);
 
 	/* Append length */
-	sha1_update(desc, (const u8 *)&bits, sizeof(bits));
+	crypto_sha1_update(desc, (const u8 *)&bits, sizeof(bits));
 
 	/* Store state in digest */
 	for (i = 0; i < 5; i++)
@@ -121,7 +122,7 @@
 static struct shash_alg alg = {
 	.digestsize	=	SHA1_DIGEST_SIZE,
 	.init		=	sha1_init,
-	.update		=	sha1_update,
+	.update		=	crypto_sha1_update,
 	.final		=	sha1_final,
 	.export		=	sha1_export,
 	.import		=	sha1_import,
diff -druN linux-libre-3.1-gnu/crypto/shash.c linux-libre-3.2-gnu/crypto/shash.c
--- linux-libre-3.1-gnu/crypto/shash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/shash.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,8 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include "internal.h"
 
@@ -522,6 +524,31 @@
 	return alg->cra_ctxsize;
 }
 
+#ifdef CONFIG_NET
+static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_hash rhash;
+	struct shash_alg *salg = __crypto_shash_alg(alg);
+
+	snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "shash");
+	rhash.blocksize = alg->cra_blocksize;
+	rhash.digestsize = salg->digestsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_HASH,
+		sizeof(struct crypto_report_hash), &rhash);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
@@ -541,6 +568,7 @@
 #ifdef CONFIG_PROC_FS
 	.show = crypto_shash_show,
 #endif
+	.report = crypto_shash_report,
 	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
 	.maskset = CRYPTO_ALG_TYPE_MASK,
 	.type = CRYPTO_ALG_TYPE_SHASH,
diff -druN linux-libre-3.1-gnu/crypto/tcrypt.c linux-libre-3.2-gnu/crypto/tcrypt.c
--- linux-libre-3.1-gnu/crypto/tcrypt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/tcrypt.c	2012-01-04 18:55:44.000000000 -0500
@@ -782,11 +782,13 @@
 	case 7:
 		ret += tcrypt_test("ecb(blowfish)");
 		ret += tcrypt_test("cbc(blowfish)");
+		ret += tcrypt_test("ctr(blowfish)");
 		break;
 
 	case 8:
 		ret += tcrypt_test("ecb(twofish)");
 		ret += tcrypt_test("cbc(twofish)");
+		ret += tcrypt_test("ctr(twofish)");
 		break;
 
 	case 9:
@@ -1039,6 +1041,10 @@
 				speed_template_16_24_32);
 		test_cipher_speed("cbc(twofish)", DECRYPT, sec, NULL, 0,
 				speed_template_16_24_32);
+		test_cipher_speed("ctr(twofish)", ENCRYPT, sec, NULL, 0,
+				speed_template_16_24_32);
+		test_cipher_speed("ctr(twofish)", DECRYPT, sec, NULL, 0,
+				speed_template_16_24_32);
 		break;
 
 	case 203:
@@ -1050,6 +1056,10 @@
 				  speed_template_8_32);
 		test_cipher_speed("cbc(blowfish)", DECRYPT, sec, NULL, 0,
 				  speed_template_8_32);
+		test_cipher_speed("ctr(blowfish)", ENCRYPT, sec, NULL, 0,
+				  speed_template_8_32);
+		test_cipher_speed("ctr(blowfish)", DECRYPT, sec, NULL, 0,
+				  speed_template_8_32);
 		break;
 
 	case 204:
diff -druN linux-libre-3.1-gnu/crypto/testmgr.c linux-libre-3.2-gnu/crypto/testmgr.c
--- linux-libre-3.1-gnu/crypto/testmgr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/testmgr.c	2012-01-04 18:55:44.000000000 -0500
@@ -1756,6 +1756,36 @@
 			}
 		}
 	}, {
+		.alg = "ctr(blowfish)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = bf_ctr_enc_tv_template,
+					.count = BF_CTR_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = bf_ctr_dec_tv_template,
+					.count = BF_CTR_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
+		.alg = "ctr(twofish)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = tf_ctr_enc_tv_template,
+					.count = TF_CTR_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = tf_ctr_dec_tv_template,
+					.count = TF_CTR_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
 		.alg = "cts(cbc(aes))",
 		.test = alg_test_skcipher,
 		.suite = {
diff -druN linux-libre-3.1-gnu/crypto/testmgr.h linux-libre-3.2-gnu/crypto/testmgr.h
--- linux-libre-3.1-gnu/crypto/testmgr.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/testmgr.h	2012-01-04 18:55:44.000000000 -0500
@@ -2391,10 +2391,12 @@
 /*
  * Blowfish test vectors.
  */
-#define BF_ENC_TEST_VECTORS	6
-#define BF_DEC_TEST_VECTORS	6
-#define BF_CBC_ENC_TEST_VECTORS	1
-#define BF_CBC_DEC_TEST_VECTORS	1
+#define BF_ENC_TEST_VECTORS	7
+#define BF_DEC_TEST_VECTORS	7
+#define BF_CBC_ENC_TEST_VECTORS	2
+#define BF_CBC_DEC_TEST_VECTORS	2
+#define BF_CTR_ENC_TEST_VECTORS	2
+#define BF_CTR_DEC_TEST_VECTORS	2
 
 static struct cipher_testvec bf_enc_tv_template[] = {
 	{ /* DES test vectors from OpenSSL */
@@ -2448,6 +2450,24 @@
 		.ilen	= 8,
 		.result	= "\xc0\x45\x04\x01\x2e\x4e\x1f\x53",
 		.rlen	= 8,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.ilen	= 40,
+		.result	= "\x96\x87\x3D\x0C\x7B\xFB\xBD\x1F"
+			  "\xE3\xC1\x99\x6D\x39\xD4\xC2\x7D"
+			  "\xD7\x87\xA1\xF2\xDF\x51\x71\x26"
+			  "\xC2\xF4\x6D\xFF\xF6\xCD\x6B\x40"
+			  "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B",
+		.rlen	= 40,
 	},
 };
 
@@ -2503,6 +2523,24 @@
 		.ilen	= 8,
 		.result	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
 		.rlen	= 8,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.input	= "\x96\x87\x3D\x0C\x7B\xFB\xBD\x1F"
+			  "\xE3\xC1\x99\x6D\x39\xD4\xC2\x7D"
+			  "\xD7\x87\xA1\xF2\xDF\x51\x71\x26"
+			  "\xC2\xF4\x6D\xFF\xF6\xCD\x6B\x40"
+			  "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B",
+		.ilen	= 40,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.rlen	= 40,
 	},
 };
 
@@ -2522,6 +2560,25 @@
 			  "\x58\xde\xb9\xe7\x15\x46\x16\xd9"
 			  "\x59\xf1\x65\x2b\xd5\xff\x92\xcc",
 		.rlen	= 32,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.ilen	= 40,
+		.result	= "\xB4\xFE\xA5\xBB\x3D\x2C\x27\x06"
+			  "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
+			  "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
+			  "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
+			  "\x01\x9C\x93\x63\x51\x60\x82\xD2",
+		.rlen	= 40,
 	},
 };
 
@@ -2541,16 +2598,125 @@
 			  "\x68\x65\x20\x74\x69\x6d\x65\x20"
 			  "\x66\x6f\x72\x20\x00\x00\x00\x00",
 		.rlen	= 32,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\xB4\xFE\xA5\xBB\x3D\x2C\x27\x06"
+			  "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
+			  "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
+			  "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
+			  "\x01\x9C\x93\x63\x51\x60\x82\xD2",
+		.ilen	= 40,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.rlen	= 40,
+	},
+};
+
+static struct cipher_testvec bf_ctr_enc_tv_template[] = {
+	{ /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.ilen	= 40,
+		.result	= "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
+			  "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
+			  "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
+			  "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
+			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC",
+		.rlen	= 40,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B",
+		.ilen	= 43,
+		.result	= "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
+			  "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
+			  "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
+			  "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
+			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
+			  "\x3D\xA7\xE9",
+		.rlen	= 43,
+	},
+};
+
+static struct cipher_testvec bf_ctr_dec_tv_template[] = {
+	{ /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
+			  "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
+			  "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
+			  "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
+			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC",
+		.ilen	= 40,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.rlen	= 40,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
+			  "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
+			  "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
+			  "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
+			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
+			  "\x3D\xA7\xE9",
+		.ilen	= 43,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B",
+		.rlen	= 43,
 	},
 };
 
 /*
  * Twofish test vectors.
  */
-#define TF_ENC_TEST_VECTORS		3
-#define TF_DEC_TEST_VECTORS		3
-#define TF_CBC_ENC_TEST_VECTORS		4
-#define TF_CBC_DEC_TEST_VECTORS		4
+#define TF_ENC_TEST_VECTORS		4
+#define TF_DEC_TEST_VECTORS		4
+#define TF_CBC_ENC_TEST_VECTORS		5
+#define TF_CBC_DEC_TEST_VECTORS		5
+#define TF_CTR_ENC_TEST_VECTORS		2
+#define TF_CTR_DEC_TEST_VECTORS		2
 
 static struct cipher_testvec tf_enc_tv_template[] = {
 	{
@@ -2582,6 +2748,30 @@
 		.result	= "\x37\x52\x7b\xe0\x05\x23\x34\xb8"
 			  "\x9f\x0c\xfc\xca\xe8\x7c\xfa\x20",
 		.rlen	= 16,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x3F\x85\x62\x3F\x1C\xF9\xD6\x1C"
+			  "\xF9\xD6\xB3\x90\x6D\x4A\x90\x6D"
+			  "\x4A\x27\x04\xE1\x27\x04\xE1\xBE"
+			  "\x9B\x78\xBE\x9B\x78\x55\x32\x0F",
+		.klen	= 32,
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.ilen	= 64,
+		.result	= "\x88\xCB\x1E\xC2\xAF\x8A\x97\xFF"
+			  "\xF6\x90\x46\x9C\x4A\x0F\x08\xDC"
+			  "\xDE\xAB\xAD\xFA\xFC\xA8\xC2\x3D"
+			  "\xE0\xE4\x8B\x3F\xD5\xA3\xF7\x14"
+			  "\x34\x9E\xB6\x08\xB2\xDD\xA8\xF5"
+			  "\xDF\xFA\xC7\xE8\x09\x50\x76\x08"
+			  "\xA2\xB6\x6A\x59\xC0\x2B\x6D\x05"
+			  "\x89\xF6\x82\xF0\xD3\xDB\x06\x02",
+		.rlen	= 64,
 	},
 };
 
@@ -2615,6 +2805,30 @@
 		.ilen	= 16,
 		.result	= zeroed_string,
 		.rlen	= 16,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x3F\x85\x62\x3F\x1C\xF9\xD6\x1C"
+			  "\xF9\xD6\xB3\x90\x6D\x4A\x90\x6D"
+			  "\x4A\x27\x04\xE1\x27\x04\xE1\xBE"
+			  "\x9B\x78\xBE\x9B\x78\x55\x32\x0F",
+		.klen	= 32,
+		.input	= "\x88\xCB\x1E\xC2\xAF\x8A\x97\xFF"
+			  "\xF6\x90\x46\x9C\x4A\x0F\x08\xDC"
+			  "\xDE\xAB\xAD\xFA\xFC\xA8\xC2\x3D"
+			  "\xE0\xE4\x8B\x3F\xD5\xA3\xF7\x14"
+			  "\x34\x9E\xB6\x08\xB2\xDD\xA8\xF5"
+			  "\xDF\xFA\xC7\xE8\x09\x50\x76\x08"
+			  "\xA2\xB6\x6A\x59\xC0\x2B\x6D\x05"
+			  "\x89\xF6\x82\xF0\xD3\xDB\x06\x02",
+		.ilen	= 64,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.rlen	= 64,
 	},
 };
 
@@ -2661,6 +2875,32 @@
 			  "\x05\xef\x8c\x61\xa8\x11\x58\x26"
 			  "\x34\xba\x5c\xb7\x10\x6a\xa6\x41",
 		.rlen	= 48,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.ilen	= 64,
+		.result	= "\xC8\xFF\xF2\x53\xA6\x27\x09\xD1"
+			  "\x33\x38\xC2\xC0\x0C\x14\x7E\xB5"
+			  "\x26\x1B\x05\x0C\x05\x12\x3F\xC0"
+			  "\xF9\x1C\x02\x28\x40\x96\x6F\xD0"
+			  "\x3D\x32\xDF\xDA\x56\x00\x6E\xEE"
+			  "\x5B\x2A\x72\x9D\xC2\x4D\x19\xBC"
+			  "\x8C\x53\xFA\x87\x6F\xDD\x81\xA3"
+			  "\xB1\xD3\x44\x65\xDF\xE7\x63\x38",
+		.rlen	= 64,
 	},
 };
 
@@ -2707,6 +2947,148 @@
 		.ilen	= 48,
 		.result	= zeroed_string,
 		.rlen	= 48,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\xC8\xFF\xF2\x53\xA6\x27\x09\xD1"
+			  "\x33\x38\xC2\xC0\x0C\x14\x7E\xB5"
+			  "\x26\x1B\x05\x0C\x05\x12\x3F\xC0"
+			  "\xF9\x1C\x02\x28\x40\x96\x6F\xD0"
+			  "\x3D\x32\xDF\xDA\x56\x00\x6E\xEE"
+			  "\x5B\x2A\x72\x9D\xC2\x4D\x19\xBC"
+			  "\x8C\x53\xFA\x87\x6F\xDD\x81\xA3"
+			  "\xB1\xD3\x44\x65\xDF\xE7\x63\x38",
+		.ilen	= 64,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.rlen	= 64,
+	},
+};
+
+static struct cipher_testvec tf_ctr_enc_tv_template[] = {
+	{ /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.ilen	= 64,
+		.result	= "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
+			  "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
+			  "\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
+			  "\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
+			  "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
+			  "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
+			  "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
+			  "\x01\x41\x21\x12\x38\xAB\x52\x4F",
+		.rlen	= 64,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE",
+		.ilen	= 67,
+		.result	= "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
+			  "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
+			  "\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
+			  "\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
+			  "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
+			  "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
+			  "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
+			  "\x01\x41\x21\x12\x38\xAB\x52\x4F"
+			  "\xA8\x57\x20",
+		.rlen	= 67,
+	},
+};
+
+static struct cipher_testvec tf_ctr_dec_tv_template[] = {
+	{ /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
+			  "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
+			  "\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
+			  "\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
+			  "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
+			  "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
+			  "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
+			  "\x01\x41\x21\x12\x38\xAB\x52\x4F",
+		.ilen	= 64,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.rlen	= 64,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
+			  "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
+			  "\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
+			  "\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
+			  "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
+			  "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
+			  "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
+			  "\x01\x41\x21\x12\x38\xAB\x52\x4F"
+			  "\xA8\x57\x20",
+		.ilen	= 67,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE",
+		.rlen	= 67,
 	},
 };
 
diff -druN linux-libre-3.1-gnu/crypto/vmac.c linux-libre-3.2-gnu/crypto/vmac.c
--- linux-libre-3.1-gnu/crypto/vmac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/vmac.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/crypto.h>
+#include <linux/module.h>
 #include <linux/scatterlist.h>
 #include <asm/byteorder.h>
 #include <crypto/scatterwalk.h>
diff -druN linux-libre-3.1-gnu/crypto/wp512.c linux-libre-3.2-gnu/crypto/wp512.c
--- linux-libre-3.1-gnu/crypto/wp512.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/wp512.c	2012-01-04 18:55:44.000000000 -0500
@@ -762,11 +762,17 @@
 	0x86228644a411c286ULL,
 };
 
-static const u64 rc[WHIRLPOOL_ROUNDS + 1] = {
-	0x0000000000000000ULL, 0x1823c6e887b8014fULL, 0x36a6d2f5796f9152ULL,
-	0x60bc9b8ea30c7b35ULL, 0x1de0d7c22e4bfe57ULL, 0x157737e59ff04adaULL,
-	0x58c9290ab1a06b85ULL, 0xbd5d10f4cb3e0567ULL, 0xe427418ba77d95d8ULL,
-	0xfbee7c66dd17479eULL, 0xca2dbf07ad5a8333ULL,
+static const u64 rc[WHIRLPOOL_ROUNDS] = {
+	0x1823c6e887b8014fULL,
+	0x36a6d2f5796f9152ULL,
+	0x60bc9b8ea30c7b35ULL,
+	0x1de0d7c22e4bfe57ULL,
+	0x157737e59ff04adaULL,
+	0x58c9290ab1a06b85ULL,
+	0xbd5d10f4cb3e0567ULL,
+	0xe427418ba77d95d8ULL,
+	0xfbee7c66dd17479eULL,
+	0xca2dbf07ad5a8333ULL,
 };
 
 /**
@@ -793,7 +799,7 @@
 	state[6] = block[6] ^ (K[6] = wctx->hash[6]);
 	state[7] = block[7] ^ (K[7] = wctx->hash[7]);
 
-	for (r = 1; r <= WHIRLPOOL_ROUNDS; r++) {
+	for (r = 0; r < WHIRLPOOL_ROUNDS; r++) {
 
 		L[0] = C0[(int)(K[0] >> 56)       ] ^
 			   C1[(int)(K[7] >> 48) & 0xff] ^
diff -druN linux-libre-3.1-gnu/crypto/xcbc.c linux-libre-3.2-gnu/crypto/xcbc.c
--- linux-libre-3.1-gnu/crypto/xcbc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/crypto/xcbc.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <crypto/internal/hash.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 
 static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101,
 			   0x02020202, 0x02020202, 0x02020202, 0x02020202,
diff -druN linux-libre-3.1-gnu/Documentation/ABI/removed/o2cb linux-libre-3.2-gnu/Documentation/ABI/removed/o2cb
--- linux-libre-3.1-gnu/Documentation/ABI/removed/o2cb	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/ABI/removed/o2cb	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 What:		/sys/o2cb symlink
 Date:		May 2011
-KernelVersion:	2.6.40
+KernelVersion:	3.0
 Contact:	ocfs2-devel@oss.oracle.com
 Description:	This is a symlink: /sys/o2cb to /sys/fs/o2cb. The symlink is
 		removed when new versions of ocfs2-tools which know to look
diff -druN linux-libre-3.1-gnu/Documentation/ABI/removed/raw1394 linux-libre-3.2-gnu/Documentation/ABI/removed/raw1394
--- linux-libre-3.1-gnu/Documentation/ABI/removed/raw1394	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/ABI/removed/raw1394	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
 	/dev/raw1394 was a character device file that allowed low-level
 	access to FireWire buses.  Its major drawbacks were its inability
 	to implement sensible device security policies, and its low level
-	of abstraction that required userspace clients do duplicate much
+	of abstraction that required userspace clients to duplicate much
 	of the kernel's ieee1394 core functionality.
 	Replaced by /dev/fw*, i.e. the <linux/firewire-cdev.h> ABI of
 	firewire-core.
diff -druN linux-libre-3.1-gnu/Documentation/ABI/stable/sysfs-acpi-pmprofile linux-libre-3.2-gnu/Documentation/ABI/stable/sysfs-acpi-pmprofile
--- linux-libre-3.1-gnu/Documentation/ABI/stable/sysfs-acpi-pmprofile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/ABI/stable/sysfs-acpi-pmprofile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+What: 		/sys/firmware/acpi/pm_profile
+Date:		03-Nov-2011
+KernelVersion:	v3.2
+Contact:	linux-acpi@vger.kernel.org
+Description: 	The ACPI pm_profile sysfs interface exports the platform
+		power management (and performance) requirement expectations
+		as provided by BIOS. The integer value is directly passed as
+		retrieved from the FADT ACPI table.
+Values:         For possible values see ACPI specification:
+		5.2.9 Fixed ACPI Description Table (FADT)
+		Field: Preferred_PM_Profile
+
+		Currently these values are defined by spec:
+		0 Unspecified
+		1 Desktop
+		2 Mobile
+		3 Workstation
+		4 Enterprise Server
+		5 SOHO Server
+		6 Appliance PC
+		7 Performance Server
+		>7 Reserved
diff -druN linux-libre-3.1-gnu/Documentation/ABI/testing/debugfs-ideapad linux-libre-3.2-gnu/Documentation/ABI/testing/debugfs-ideapad
--- linux-libre-3.1-gnu/Documentation/ABI/testing/debugfs-ideapad	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/ABI/testing/debugfs-ideapad	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+What:		/sys/kernel/debug/ideapad/cfg
+Date:		Sep 2011
+KernelVersion:	3.2
+Contact:	Ike Panhc <ike.pan@canonical.com>
+Description:
+
+cfg shows the return value of _CFG method in VPC2004 device. It tells machine
+capability and what graphic component within the machine.
+
+
+What:		/sys/kernel/debug/ideapad/status
+Date:		Sep 2011
+KernelVersion:	3.2
+Contact:	Ike Panhc <ike.pan@canonical.com>
+Description:
+
+status shows infos we can read and tells its meaning and value.
+
+
diff -druN linux-libre-3.1-gnu/Documentation/ABI/testing/evm linux-libre-3.2-gnu/Documentation/ABI/testing/evm
--- linux-libre-3.1-gnu/Documentation/ABI/testing/evm	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/ABI/testing/evm	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+What:		security/evm
+Date:		March 2011
+Contact:	Mimi Zohar <zohar@us.ibm.com>
+Description:
+		EVM protects a file's security extended attributes(xattrs)
+		against integrity attacks. The initial method maintains an
+		HMAC-sha1 value across the extended attributes, storing the
+		value as the extended attribute 'security.evm'.
+
+		EVM depends on the Kernel Key Retention System to provide it
+		with a trusted/encrypted key for the HMAC-sha1 operation.
+		The key is loaded onto the root's keyring using keyctl.  Until
+		EVM receives notification that the key has been successfully
+		loaded onto the keyring (echo 1 > <securityfs>/evm), EVM
+		can not create or validate the 'security.evm' xattr, but
+		returns INTEGRITY_UNKNOWN.  Loading the key and signaling EVM
+		should be done as early as possible.  Normally this is done
+		in the initramfs, which has already been measured as part
+		of the trusted boot.  For more information on creating and
+		loading existing trusted/encrypted keys, refer to:
+		Documentation/keys-trusted-encrypted.txt.  (A sample dracut
+		patch, which loads the trusted/encrypted key and enables
+		EVM, is available from http://linux-ima.sourceforge.net/#EVM.)
diff -druN linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-bus-bcma linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-bus-bcma
--- linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-bus-bcma	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-bus-bcma	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 What:		/sys/bus/bcma/devices/.../manuf
 Date:		May 2011
-KernelVersion:	2.6.40
+KernelVersion:	3.0
 Contact:	RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
 Description:
 		Each BCMA core has it's manufacturer id. See
@@ -8,7 +8,7 @@
 
 What:		/sys/bus/bcma/devices/.../id
 Date:		May 2011
-KernelVersion:	2.6.40
+KernelVersion:	3.0
 Contact:	RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
 Description:
 		There are a few types of BCMA cores, they can be identified by
@@ -16,7 +16,7 @@
 
 What:		/sys/bus/bcma/devices/.../rev
 Date:		May 2011
-KernelVersion:	2.6.40
+KernelVersion:	3.0
 Contact:	RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
 Description:
 		BCMA cores of the same type can still slightly differ depending
@@ -24,7 +24,7 @@
 
 What:		/sys/bus/bcma/devices/.../class
 Date:		May 2011
-KernelVersion:	2.6.40
+KernelVersion:	3.0
 Contact:	RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
 Description:
 		Each BCMA core is identified by few fields, including class it
diff -druN linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss
--- linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss	2012-01-04 18:55:44.000000000 -0500
@@ -71,3 +71,10 @@
 		a dump device, as kdump requires resetting the device in order
 		to work reliably.
 
+Where:		/sys/bus/pci/devices/<dev>/ccissX/transport_mode
+Date:		July 2011
+Kernel Version:	3.0
+Contact:	iss_storagedev@hp.com
+Description:	Value of "simple" indicates that the controller has been placed
+		in "simple mode". Value of "performant" indicates that the
+		controller has been placed in "performant mode".
diff -druN linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd
--- linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-bus-pci-drivers-ehci_hcd	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,46 @@
+What:		/sys/bus/pci/drivers/ehci_hcd/.../companion
+		/sys/bus/usb/devices/usbN/../companion
+Date:		January 2007
+KernelVersion:	2.6.21
+Contact:	Alan Stern <stern@rowland.harvard.edu>
+Description:
+		PCI-based EHCI USB controllers (i.e., high-speed USB-2.0
+		controllers) are often implemented along with a set of
+		"companion" full/low-speed USB-1.1 controllers.  When a
+		high-speed device is plugged in, the connection is routed
+		to the EHCI controller; when a full- or low-speed device
+		is plugged in, the connection is routed to the companion
+		controller.
+
+		Sometimes you want to force a high-speed device to connect
+		at full speed, which can be accomplished by forcing the
+		connection to be routed to the companion controller.
+		That's what this file does.  Writing a port number to the
+		file causes connections on that port to be routed to the
+		companion controller, and writing the negative of a port
+		number returns the port to normal operation.
+
+		For example: To force the high-speed device attached to
+		port 4 on bus 2 to run at full speed:
+
+			echo 4 >/sys/bus/usb/devices/usb2/../companion
+
+		To return the port to high-speed operation:
+
+			echo -4 >/sys/bus/usb/devices/usb2/../companion
+
+		Reading the file gives the list of ports currently forced
+		to the companion controller.
+
+		Note: Some EHCI controllers do not have companions; they
+		may contain an internal "transaction translator" or they
+		may be attached directly to a "rate-matching hub".  This
+		mechanism will not work with such controllers.  Also, it
+		cannot be used to force a port on a high-speed hub to
+		connect at full speed.
+
+		Note: When this file was first added, it appeared in a
+		different sysfs directory.  The location given above is
+		correct for 2.6.35 (and probably several earlier kernel
+		versions as well).
+
diff -druN linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-bus-rbd linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-bus-rbd
--- linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-bus-rbd	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-bus-rbd	2012-01-04 18:55:44.000000000 -0500
@@ -57,13 +57,6 @@
 
 	 $ echo <snap-name> > /sys/bus/rbd/devices/<dev-id>/snap_create
 
-rollback_snap
-
-	Rolls back data to the specified snapshot. This goes over the entire
-	list of rados blocks and sends a rollback command to each.
-
-	 $ echo <snap-name> > /sys/bus/rbd/devices/<dev-id>/snap_rollback
-
 snap_*
 
 	A directory per each snapshot
diff -druN linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-bus-usb linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-bus-usb
--- linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-bus-usb	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-bus-usb	2012-01-04 18:55:44.000000000 -0500
@@ -142,3 +142,18 @@
 		such devices.
 Users:
 		usb_modeswitch
+
+What:		/sys/bus/usb/devices/.../power/usb2_hardware_lpm
+Date:		September 2011
+Contact:	Andiry Xu <andiry.xu@amd.com>
+Description:
+		If CONFIG_USB_SUSPEND is set and a USB 2.0 lpm-capable device
+		is plugged in to a xHCI host which support link PM, it will
+		perform a LPM test; if the test is passed and host supports
+		USB2 hardware LPM (xHCI 1.0 feature), USB2 hardware LPM will
+		be enabled for the device and the USB device directory will
+		contain a file named power/usb2_hardware_lpm.  The file holds
+		a string value (enable or disable) indicating whether or not
+		USB2 hardware LPM is enabled for the device. Developer can
+		write y/Y/1 or n/N/0 to the file to enable/disable the
+		feature.
diff -druN linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870
--- linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870	2012-01-04 18:55:44.000000000 -0500
@@ -4,8 +4,8 @@
 What:		/sys/class/backlight/<backlight>/l3_office_max
 What:		/sys/class/backlight/<backlight>/l4_indoor_max
 What:		/sys/class/backlight/<backlight>/l5_dark_max
-Date:		Mai 2011
-KernelVersion:	2.6.40
+Date:		May 2011
+KernelVersion:	3.0
 Contact:	device-drivers-devel@blackfin.uclinux.org
 Description:
 		Control the maximum brightness for <ambient light zone>
@@ -18,8 +18,8 @@
 What:		/sys/class/backlight/<backlight>/l3_office_dim
 What:		/sys/class/backlight/<backlight>/l4_indoor_dim
 What:		/sys/class/backlight/<backlight>/l5_dark_dim
-Date:		Mai 2011
-KernelVersion:	2.6.40
+Date:		May 2011
+KernelVersion:	3.0
 Contact:	device-drivers-devel@blackfin.uclinux.org
 Description:
 		Control the dim brightness for <ambient light zone>
@@ -29,8 +29,8 @@
 		this <ambient light zone>.
 
 What:		/sys/class/backlight/<backlight>/ambient_light_level
-Date:		Mai 2011
-KernelVersion:	2.6.40
+Date:		May 2011
+KernelVersion:	3.0
 Contact:	device-drivers-devel@blackfin.uclinux.org
 Description:
 		Get conversion value of the light sensor.
@@ -39,8 +39,8 @@
 		8000 (max ambient brightness)
 
 What:		/sys/class/backlight/<backlight>/ambient_light_zone
-Date:		Mai 2011
-KernelVersion:	2.6.40
+Date:		May 2011
+KernelVersion:	3.0
 Contact:	device-drivers-devel@blackfin.uclinux.org
 Description:
 		Get/Set current ambient light zone. Reading returns
diff -druN linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-class-devfreq linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-class-devfreq
--- linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-class-devfreq	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-class-devfreq	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,52 @@
+What:		/sys/class/devfreq/.../
+Date:		September 2011
+Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+		Provide a place in sysfs for the devfreq objects.
+		This allows accessing various devfreq specific variables.
+		The name of devfreq object denoted as ... is same as the
+		name of device using devfreq.
+
+What:		/sys/class/devfreq/.../governor
+Date:		September 2011
+Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+		The /sys/class/devfreq/.../governor shows the name of the
+		governor used by the corresponding devfreq object.
+
+What:		/sys/class/devfreq/.../cur_freq
+Date:		September 2011
+Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+		The /sys/class/devfreq/.../cur_freq shows the current
+		frequency of the corresponding devfreq object.
+
+What:		/sys/class/devfreq/.../central_polling
+Date:		September 2011
+Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+		The /sys/class/devfreq/.../central_polling shows whether
+		the devfreq ojbect is using devfreq-provided central
+		polling mechanism or not.
+
+What:		/sys/class/devfreq/.../polling_interval
+Date:		September 2011
+Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+		The /sys/class/devfreq/.../polling_interval shows and sets
+		the requested polling interval of the corresponding devfreq
+		object. The values are represented in ms. If the value is
+		less than 1 jiffy, it is considered to be 0, which means
+		no polling. This value is meaningless if the governor is
+		not polling; thus. If the governor is not using
+		devfreq-provided central polling
+		(/sys/class/devfreq/.../central_polling is 0), this value
+		may be useless.
+
+What:		/sys/class/devfreq/.../userspace/set_freq
+Date:		September 2011
+Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+		The /sys/class/devfreq/.../userspace/set_freq shows and
+		sets the requested frequency for the devfreq object if
+		userspace governor is in effect.
diff -druN linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-class-net-mesh linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-class-net-mesh
--- linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-class-net-mesh	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-class-net-mesh	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,14 @@
                 mesh will be fragmented or silently discarded if the
                 packet size exceeds the outgoing interface MTU.
 
+What:		/sys/class/net/<mesh_iface>/mesh/ap_isolation
+Date:		May 2011
+Contact:	Antonio Quartulli <ordex@autistici.org>
+Description:
+		Indicates whether the data traffic going from a
+		wireless client to another wireless client will be
+		silently dropped.
+
 What:           /sys/class/net/<mesh_iface>/mesh/gw_bandwidth
 Date:           October 2010
 Contact:        Marek Lindner <lindner_marek@yahoo.de>
diff -druN linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
--- linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,7 @@
+What:		/sys/module/hid_logitech/drivers/hid:logitech/<dev>/range.
+Date:		July 2011
+KernelVersion:	3.2
+Contact:	Michal Malý <madcatxster@gmail.com>
+Description:	Display minimum, maximum and current range of the steering
+		wheel. Writing a value within min and max boundaries sets the
+		range of the wheel.
diff -druN linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-driver-wacom linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-driver-wacom
--- linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-driver-wacom	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-driver-wacom	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,72 @@
+What:		/sys/class/hidraw/hidraw*/device/speed
+Date:		April 2010
+Kernel Version:	2.6.35
+Contact:	linux-bluetooth@vger.kernel.org
+Description:
+		The /sys/class/hidraw/hidraw*/device/speed file controls
+		reporting speed of Wacom bluetooth tablet. Reading from
+		this file returns 1 if tablet reports in high speed mode
+		or 0 otherwise. Writing to this file one of these values
+		switches reporting speed.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/led
+Date:		August 2011
+Contact:	linux-input@vger.kernel.org
+Description:
+		Attribute group for control of the status LEDs and the OLEDs.
+		This attribute group is only available for Intuos 4 M, L,
+		and XL (with LEDs and OLEDs) and Cintiq 21UX2 (LEDs only).
+		Therefore its presence implicitly signifies the presence of
+		said LEDs and OLEDs on the tablet device.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status0_luminance
+Date:		August 2011
+Contact:	linux-input@vger.kernel.org
+Description:
+		Writing to this file sets the status LED luminance (1..127)
+		when the stylus does not touch the tablet surface, and no
+		button is pressed on the stylus. This luminance level is
+		normally lower than the level when a button is pressed.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status1_luminance
+Date:		August 2011
+Contact:	linux-input@vger.kernel.org
+Description:
+		Writing to this file sets the status LED luminance (1..127)
+		when the stylus touches the tablet surface, or any button is
+		pressed on the stylus.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led0_select
+Date:		August 2011
+Contact:	linux-input@vger.kernel.org
+Description:
+		Writing to this file sets which one of the four (for Intuos 4)
+		or of the right four (for Cintiq 21UX2) status LEDs is active (0..3).
+		The other three LEDs on the same side are always inactive.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led1_select
+Date:		September 2011
+Contact:	linux-input@vger.kernel.org
+Description:
+		Writing to this file sets which one of the left four (for Cintiq 21UX2)
+		status LEDs is active (0..3). The other three LEDs on the left are always
+		inactive.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/buttons_luminance
+Date:		August 2011
+Contact:	linux-input@vger.kernel.org
+Description:
+		Writing to this file sets the overall luminance level (0..15)
+		of all eight button OLED displays.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/button<n>_rawimg
+Date:		August 2011
+Contact:	linux-input@vger.kernel.org
+Description:
+		When writing a 1024 byte raw image in Wacom Intuos 4
+		interleaving format to the file, the image shows up on Button N
+		of the device. The image is a 64x32 pixel 4-bit gray image. The
+		1024 byte binary is split up into 16x 64 byte chunks. Each 64
+		byte chunk encodes the image data for two consecutive lines on
+		the display. The low nibble of each byte contains the first
+		line, and the high nibble contains the second line.
diff -druN linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-platform-ideapad-laptop linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-platform-ideapad-laptop
--- linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-platform-ideapad-laptop	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-platform-ideapad-laptop	2012-01-04 18:55:44.000000000 -0500
@@ -5,19 +5,4 @@
 Description:
 		Control the power of camera module. 1 means on, 0 means off.
 
-What:		/sys/devices/platform/ideapad/cfg
-Date:		Jun 2011
-KernelVersion:	3.1
-Contact:	"Ike Panhc <ike.pan@canonical.com>"
-Description:
-		Ideapad capability bits.
-		Bit 8-10: 1 - Intel graphic only
-		          2 - ATI graphic only
-		          3 - Nvidia graphic only
-		          4 - Intel and ATI graphic
-		          5 - Intel and Nvidia graphic
-		Bit 16: Bluetooth exist (1 for exist)
-		Bit 17: 3G exist (1 for exist)
-		Bit 18: Wifi exist (1 for exist)
-		Bit 19: Camera exist (1 for exist)
 
diff -druN linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-wacom linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-wacom
--- linux-libre-3.1-gnu/Documentation/ABI/testing/sysfs-wacom	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/ABI/testing/sysfs-wacom	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-What:		/sys/class/hidraw/hidraw*/device/speed
-Date:		April 2010
-Kernel Version:	2.6.35
-Contact:	linux-bluetooth@vger.kernel.org
-Description:
-		The /sys/class/hidraw/hidraw*/device/speed file controls
-		reporting speed of wacom bluetooth tablet. Reading from
-		this file returns 1 if tablet reports in high speed mode
-		or 0 otherwise. Writing to this file one of these values
-		switches reporting speed.
diff -druN linux-libre-3.1-gnu/Documentation/blackfin/bfin-gpio-notes.txt linux-libre-3.2-gnu/Documentation/blackfin/bfin-gpio-notes.txt
--- linux-libre-3.1-gnu/Documentation/blackfin/bfin-gpio-notes.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/blackfin/bfin-gpio-notes.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * File:         Documentation/blackfin/bfin-gpio-note.txt
+ * File:         Documentation/blackfin/bfin-gpio-notes.txt
  * Based on:
  * Author:
  *
diff -druN linux-libre-3.1-gnu/Documentation/block/biodoc.txt linux-libre-3.2-gnu/Documentation/block/biodoc.txt
--- linux-libre-3.1-gnu/Documentation/block/biodoc.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/block/biodoc.txt	2012-01-04 18:55:44.000000000 -0500
@@ -186,7 +186,7 @@
 do not have a corresponding kernel virtual address space mapping) and
 low-memory pages.
 
-Note: Please refer to Documentation/PCI/PCI-DMA-mapping.txt for a discussion
+Note: Please refer to Documentation/DMA-API-HOWTO.txt for a discussion
 on PCI high mem DMA aspects and mapping of scatter gather lists, and support
 for 64 bit PCI.
 
diff -druN linux-libre-3.1-gnu/Documentation/block/switching-sched.txt linux-libre-3.2-gnu/Documentation/block/switching-sched.txt
--- linux-libre-3.1-gnu/Documentation/block/switching-sched.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/block/switching-sched.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 To choose IO schedulers at boot time, use the argument 'elevator=deadline'.
-'noop', 'as' and 'cfq' (the default) are also available. IO schedulers are
-assigned globally at boot time only presently.
+'noop' and 'cfq' (the default) are also available. IO schedulers are assigned
+globally at boot time only presently.
 
 Each io queue has a set of io scheduler tunables associated with it. These
 tunables control how the io scheduler works. You can find these entries
diff -druN linux-libre-3.1-gnu/Documentation/blockdev/cciss.txt linux-libre-3.2-gnu/Documentation/blockdev/cciss.txt
--- linux-libre-3.1-gnu/Documentation/blockdev/cciss.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/blockdev/cciss.txt	2012-01-04 18:55:44.000000000 -0500
@@ -78,6 +78,16 @@
 /dev/cciss/c1d1p2		Controller 1, disk 1, partition 2
 /dev/cciss/c1d1p3		Controller 1, disk 1, partition 3
 
+CCISS simple mode support
+-------------------------
+
+The "cciss_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.
+
 SCSI tape drive and medium changer support
 ------------------------------------------
 
@@ -88,14 +98,12 @@
 "SCSI support" in your kernel configuration to be able to use SCSI
 tape drives with your Smart Array 5xxx controller.
 
-Additionally, note that the driver will not engage the SCSI core at init 
-time.  The driver must be directed to dynamically engage the SCSI core via 
-the /proc filesystem entry which the "block" side of the driver creates as 
-/proc/driver/cciss/cciss* at runtime.  This is because at driver init time, 
-the SCSI core may not yet be initialized (because the driver is a block 
-driver) and attempting to register it with the SCSI core in such a case 
-would cause a hang.  This is best done via an initialization script 
-(typically in /etc/init.d, but could vary depending on distribution). 
+Additionally, note that the driver will engage the SCSI core at init
+time if any tape drives or medium changers are detected.  The driver may
+also be directed to dynamically engage the SCSI core via the /proc filesystem
+entry which the "block" side of the driver creates as
+/proc/driver/cciss/cciss* at runtime.  This is best done via a script.
+
 For example:
 
 	for x in /proc/driver/cciss/cciss[0-9]*
diff -druN linux-libre-3.1-gnu/Documentation/bus-virt-phys-mapping.txt linux-libre-3.2-gnu/Documentation/bus-virt-phys-mapping.txt
--- linux-libre-3.1-gnu/Documentation/bus-virt-phys-mapping.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/bus-virt-phys-mapping.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 [ NOTE: The virt_to_bus() and bus_to_virt() functions have been
 	superseded by the functionality provided by the PCI DMA interface
-	(see Documentation/PCI/PCI-DMA-mapping.txt).  They continue
+	(see Documentation/DMA-API-HOWTO.txt).  They continue
 	to be documented below for historical purposes, but new code
 	must not use them. --davidm 00/12/12 ]
 
diff -druN linux-libre-3.1-gnu/Documentation/cdrom/packet-writing.txt linux-libre-3.2-gnu/Documentation/cdrom/packet-writing.txt
--- linux-libre-3.1-gnu/Documentation/cdrom/packet-writing.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/cdrom/packet-writing.txt	2012-01-04 18:55:44.000000000 -0500
@@ -109,7 +109,7 @@
 
 For a description of the sysfs interface look into the file:
 
-  Documentation/ABI/testing/sysfs-block-pktcdvd
+  Documentation/ABI/testing/sysfs-class-pktcdvd
 
 
 Using the pktcdvd debugfs interface
diff -druN linux-libre-3.1-gnu/Documentation/cgroups/cgroups.txt linux-libre-3.2-gnu/Documentation/cgroups/cgroups.txt
--- linux-libre-3.1-gnu/Documentation/cgroups/cgroups.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/cgroups/cgroups.txt	2012-01-04 18:55:44.000000000 -0500
@@ -454,8 +454,8 @@
 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.
+Note: Due to some restrictions enforced by some cgroup subsystems, moving
+a process to another cgroup can fail.
 
 2.3 Mounting hierarchies by name
 --------------------------------
diff -druN linux-libre-3.1-gnu/Documentation/cgroups/freezer-subsystem.txt linux-libre-3.2-gnu/Documentation/cgroups/freezer-subsystem.txt
--- linux-libre-3.1-gnu/Documentation/cgroups/freezer-subsystem.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/cgroups/freezer-subsystem.txt	2012-01-04 18:55:44.000000000 -0500
@@ -33,9 +33,9 @@
 
 	From a second, unrelated bash shell:
 	$ kill -SIGSTOP 16690
-	$ kill -SIGCONT 16990
+	$ kill -SIGCONT 16690
 
-	<at this point 16990 exits and causes 16644 to exit too>
+	<at this point 16690 exits and causes 16644 to exit too>
 
 This happens because bash can observe both signals and choose how it
 responds to them.
diff -druN linux-libre-3.1-gnu/Documentation/cgroups/memory.txt linux-libre-3.2-gnu/Documentation/cgroups/memory.txt
--- linux-libre-3.1-gnu/Documentation/cgroups/memory.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/cgroups/memory.txt	2012-01-04 18:55:44.000000000 -0500
@@ -418,7 +418,6 @@
 
 # The following additional stats are dependent on CONFIG_DEBUG_VM.
 
-inactive_ratio		- VM internal parameter. (see mm/page_alloc.c)
 recent_rotated_anon	- VM internal parameter. (see mm/vmscan.c)
 recent_rotated_file	- VM internal parameter. (see mm/vmscan.c)
 recent_scanned_anon	- VM internal parameter. (see mm/vmscan.c)
diff -druN linux-libre-3.1-gnu/Documentation/CodingStyle linux-libre-3.2-gnu/Documentation/CodingStyle
--- linux-libre-3.1-gnu/Documentation/CodingStyle	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/CodingStyle	2012-01-04 18:55:44.000000000 -0500
@@ -166,8 +166,8 @@
 else
 	do_that();
 
-This does not apply if one branch of a conditional statement is a single
-statement. Use braces in both branches.
+This does not apply if only one branch of a conditional statement is a single
+statement; in the latter case use braces in both branches:
 
 if (condition) {
 	do_this();
diff -druN linux-libre-3.1-gnu/Documentation/cpu-freq/governors.txt linux-libre-3.2-gnu/Documentation/cpu-freq/governors.txt
--- linux-libre-3.1-gnu/Documentation/cpu-freq/governors.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/cpu-freq/governors.txt	2012-01-04 18:55:44.000000000 -0500
@@ -132,7 +132,7 @@
 transition_latency * 100
 Or by kernel restrictions:
 If CONFIG_NO_HZ is set, the limit is 10ms fixed.
-If CONFIG_NO_HZ is not set or no_hz=off boot parameter is used, the
+If CONFIG_NO_HZ is not set or nohz=off boot parameter is used, the
 limits depend on the CONFIG_HZ option:
 HZ=1000: min=20000us  (20ms)
 HZ=250:  min=80000us  (80ms)
diff -druN linux-libre-3.1-gnu/Documentation/development-process/4.Coding linux-libre-3.2-gnu/Documentation/development-process/4.Coding
--- linux-libre-3.1-gnu/Documentation/development-process/4.Coding	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/development-process/4.Coding	2012-01-04 18:55:44.000000000 -0500
@@ -278,7 +278,7 @@
 fail; these failures can be restricted to a specific range of code.
 Running with fault injection enabled allows the programmer to see how the
 code responds when things go badly.  See
-Documentation/fault-injection/fault-injection.text for more information on
+Documentation/fault-injection/fault-injection.txt for more information on
 how to use this facility.
 
 Other kinds of errors can be found with the "sparse" static analysis tool.
diff -druN linux-libre-3.1-gnu/Documentation/device-mapper/dm-log.txt linux-libre-3.2-gnu/Documentation/device-mapper/dm-log.txt
--- linux-libre-3.1-gnu/Documentation/device-mapper/dm-log.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/device-mapper/dm-log.txt	2012-01-04 18:55:44.000000000 -0500
@@ -48,7 +48,7 @@
 communication.
 
 There are currently two userspace log implementations that leverage this
-framework - "clustered_disk" and "clustered_core".  These implementations
+framework - "clustered-disk" and "clustered-core".  These implementations
 provide a cluster-coherent log for shared-storage.  Device-mapper mirroring
 can be used in a shared-storage environment when the cluster log implementations
 are employed.
diff -druN linux-libre-3.1-gnu/Documentation/device-mapper/persistent-data.txt linux-libre-3.2-gnu/Documentation/device-mapper/persistent-data.txt
--- linux-libre-3.1-gnu/Documentation/device-mapper/persistent-data.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/device-mapper/persistent-data.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,84 @@
+Introduction
+============
+
+The more-sophisticated device-mapper targets require complex metadata
+that is managed in kernel.  In late 2010 we were seeing that various
+different targets were rolling their own data strutures, for example:
+
+- Mikulas Patocka's multisnap implementation
+- Heinz Mauelshagen's thin provisioning target
+- Another btree-based caching target posted to dm-devel
+- Another multi-snapshot target based on a design of Daniel Phillips
+
+Maintaining these data structures takes a lot of work, so if possible
+we'd like to reduce the number.
+
+The persistent-data library is an attempt to provide a re-usable
+framework for people who want to store metadata in device-mapper
+targets.  It's currently used by the thin-provisioning target and an
+upcoming hierarchical storage target.
+
+Overview
+========
+
+The main documentation is in the header files which can all be found
+under drivers/md/persistent-data.
+
+The block manager
+-----------------
+
+dm-block-manager.[hc]
+
+This provides access to the data on disk in fixed sized-blocks.  There
+is a read/write locking interface to prevent concurrent accesses, and
+keep data that is being used in the cache.
+
+Clients of persistent-data are unlikely to use this directly.
+
+The transaction manager
+-----------------------
+
+dm-transaction-manager.[hc]
+
+This restricts access to blocks and enforces copy-on-write semantics.
+The only way you can get hold of a writable block through the
+transaction manager is by shadowing an existing block (ie. doing
+copy-on-write) or allocating a fresh one.  Shadowing is elided within
+the same transaction so performance is reasonable.  The commit method
+ensures that all data is flushed before it writes the superblock.
+On power failure your metadata will be as it was when last committed.
+
+The Space Maps
+--------------
+
+dm-space-map.h
+dm-space-map-metadata.[hc]
+dm-space-map-disk.[hc]
+
+On-disk data structures that keep track of reference counts of blocks.
+Also acts as the allocator of new blocks.  Currently two
+implementations: a simpler one for managing blocks on a different
+device (eg. thinly-provisioned data blocks); and one for managing
+the metadata space.  The latter is complicated by the need to store
+its own data within the space it's managing.
+
+The data structures
+-------------------
+
+dm-btree.[hc]
+dm-btree-remove.c
+dm-btree-spine.c
+dm-btree-internal.h
+
+Currently there is only one data structure, a hierarchical btree.
+There are plans to add more.  For example, something with an
+array-like interface would see a lot of use.
+
+The btree is 'hierarchical' in that you can define it to be composed
+of nested btrees, and take multiple keys.  For example, the
+thin-provisioning target uses a btree with two levels of nesting.
+The first maps a device id to a mapping tree, and that in turn maps a
+virtual block to a physical block.
+
+Values stored in the btrees can have arbitrary size.  Keys are always
+64bits, although nesting allows you to use multiple keys.
diff -druN linux-libre-3.1-gnu/Documentation/device-mapper/thin-provisioning.txt linux-libre-3.2-gnu/Documentation/device-mapper/thin-provisioning.txt
--- linux-libre-3.1-gnu/Documentation/device-mapper/thin-provisioning.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/device-mapper/thin-provisioning.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,285 @@
+Introduction
+============
+
+This document descibes a collection of device-mapper targets that
+between them implement thin-provisioning and snapshots.
+
+The main highlight of this implementation, compared to the previous
+implementation of snapshots, is that it allows many virtual devices to
+be stored on the same data volume.  This simplifies administration and
+allows the sharing of data between volumes, thus reducing disk usage.
+
+Another significant feature is support for an arbitrary depth of
+recursive snapshots (snapshots of snapshots of snapshots ...).  The
+previous implementation of snapshots did this by chaining together
+lookup tables, and so performance was O(depth).  This new
+implementation uses a single data structure to avoid this degradation
+with depth.  Fragmentation may still be an issue, however, in some
+scenarios.
+
+Metadata is stored on a separate device from data, giving the
+administrator some freedom, for example to:
+
+- Improve metadata resilience by storing metadata on a mirrored volume
+  but data on a non-mirrored one.
+
+- Improve performance by storing the metadata on SSD.
+
+Status
+======
+
+These targets are very much still in the EXPERIMENTAL state.  Please
+do not yet rely on them in production.  But do experiment and offer us
+feedback.  Different use cases will have different performance
+characteristics, for example due to fragmentation of the data volume.
+
+If you find this software is not performing as expected please mail
+dm-devel@redhat.com with details and we'll try our best to improve
+things for you.
+
+Userspace tools for checking and repairing the metadata are under
+development.
+
+Cookbook
+========
+
+This section describes some quick recipes for using thin provisioning.
+They use the dmsetup program to control the device-mapper driver
+directly.  End users will be advised to use a higher-level volume
+manager such as LVM2 once support has been added.
+
+Pool device
+-----------
+
+The pool device ties together the metadata volume and the data volume.
+It maps I/O linearly to the data volume and updates the metadata via
+two mechanisms:
+
+- Function calls from the thin targets
+
+- Device-mapper 'messages' from userspace which control the creation of new
+  virtual devices amongst other things.
+
+Setting up a fresh pool device
+------------------------------
+
+Setting up a pool device requires a valid metadata device, and a
+data device.  If you do not have an existing metadata device you can
+make one by zeroing the first 4k to indicate empty metadata.
+
+    dd if=/dev/zero of=$metadata_dev bs=4096 count=1
+
+The amount of metadata you need will vary according to how many blocks
+are shared between thin devices (i.e. through snapshots).  If you have
+less sharing than average you'll need a larger-than-average metadata device.
+
+As a guide, we suggest you calculate the number of bytes to use in the
+metadata device as 48 * $data_dev_size / $data_block_size but round it up
+to 2MB if the answer is smaller.  The largest size supported is 16GB.
+
+If you're creating large numbers of snapshots which are recording large
+amounts of change, you may need find you need to increase this.
+
+Reloading a pool table
+----------------------
+
+You may reload a pool's table, indeed this is how the pool is resized
+if it runs out of space.  (N.B. While specifying a different metadata
+device when reloading is not forbidden at the moment, things will go
+wrong if it does not route I/O to exactly the same on-disk location as
+previously.)
+
+Using an existing pool device
+-----------------------------
+
+    dmsetup create pool \
+	--table "0 20971520 thin-pool $metadata_dev $data_dev \
+		 $data_block_size $low_water_mark"
+
+$data_block_size gives the smallest unit of disk space that can be
+allocated at a time expressed in units of 512-byte sectors.  People
+primarily interested in thin provisioning may want to use a value such
+as 1024 (512KB).  People doing lots of snapshotting may want a smaller value
+such as 128 (64KB).  If you are not zeroing newly-allocated data,
+a larger $data_block_size in the region of 256000 (128MB) is suggested.
+$data_block_size must be the same for the lifetime of the
+metadata device.
+
+$low_water_mark is expressed in blocks of size $data_block_size.  If
+free space on the data device drops below this level then a dm event
+will be triggered which a userspace daemon should catch allowing it to
+extend the pool device.  Only one such event will be sent.
+Resuming a device with a new table itself triggers an event so the
+userspace daemon can use this to detect a situation where a new table
+already exceeds the threshold.
+
+Thin provisioning
+-----------------
+
+i) Creating a new thinly-provisioned volume.
+
+  To create a new thinly- provisioned volume you must send a message to an
+  active pool device, /dev/mapper/pool in this example.
+
+    dmsetup message /dev/mapper/pool 0 "create_thin 0"
+
+  Here '0' is an identifier for the volume, a 24-bit number.  It's up
+  to the caller to allocate and manage these identifiers.  If the
+  identifier is already in use, the message will fail with -EEXIST.
+
+ii) Using a thinly-provisioned volume.
+
+  Thinly-provisioned volumes are activated using the 'thin' target:
+
+    dmsetup create thin --table "0 2097152 thin /dev/mapper/pool 0"
+
+  The last parameter is the identifier for the thinp device.
+
+Internal snapshots
+------------------
+
+i) Creating an internal snapshot.
+
+  Snapshots are created with another message to the pool.
+
+  N.B.  If the origin device that you wish to snapshot is active, you
+  must suspend it before creating the snapshot to avoid corruption.
+  This is NOT enforced at the moment, so please be careful!
+
+    dmsetup suspend /dev/mapper/thin
+    dmsetup message /dev/mapper/pool 0 "create_snap 1 0"
+    dmsetup resume /dev/mapper/thin
+
+  Here '1' is the identifier for the volume, a 24-bit number.  '0' is the
+  identifier for the origin device.
+
+ii) Using an internal snapshot.
+
+  Once created, the user doesn't have to worry about any connection
+  between the origin and the snapshot.  Indeed the snapshot is no
+  different from any other thinly-provisioned device and can be
+  snapshotted itself via the same method.  It's perfectly legal to
+  have only one of them active, and there's no ordering requirement on
+  activating or removing them both.  (This differs from conventional
+  device-mapper snapshots.)
+
+  Activate it exactly the same way as any other thinly-provisioned volume:
+
+    dmsetup create snap --table "0 2097152 thin /dev/mapper/pool 1"
+
+Deactivation
+------------
+
+All devices using a pool must be deactivated before the pool itself
+can be.
+
+    dmsetup remove thin
+    dmsetup remove snap
+    dmsetup remove pool
+
+Reference
+=========
+
+'thin-pool' target
+------------------
+
+i) Constructor
+
+    thin-pool <metadata dev> <data dev> <data block size (sectors)> \
+	      <low water mark (blocks)> [<number of feature args> [<arg>]*]
+
+    Optional feature arguments:
+    - 'skip_block_zeroing': skips the zeroing of newly-provisioned blocks.
+
+    Data block size must be between 64KB (128 sectors) and 1GB
+    (2097152 sectors) inclusive.
+
+
+ii) Status
+
+    <transaction id> <used metadata blocks>/<total metadata blocks>
+    <used data blocks>/<total data blocks> <held metadata root>
+
+
+    transaction id:
+	A 64-bit number used by userspace to help synchronise with metadata
+	from volume managers.
+
+    used data blocks / total data blocks
+	If the number of free blocks drops below the pool's low water mark a
+	dm event will be sent to userspace.  This event is edge-triggered and
+	it will occur only once after each resume so volume manager writers
+	should register for the event and then check the target's status.
+
+    held metadata root:
+	The location, in sectors, of the metadata root that has been
+	'held' for userspace read access.  '-' indicates there is no
+	held root.  This feature is not yet implemented so '-' is
+	always returned.
+
+iii) Messages
+
+    create_thin <dev id>
+
+	Create a new thinly-provisioned device.
+	<dev id> is an arbitrary unique 24-bit identifier chosen by
+	the caller.
+
+    create_snap <dev id> <origin id>
+
+	Create a new snapshot of another thinly-provisioned device.
+	<dev id> is an arbitrary unique 24-bit identifier chosen by
+	the caller.
+	<origin id> is the identifier of the thinly-provisioned device
+	of which the new device will be a snapshot.
+
+    delete <dev id>
+
+	Deletes a thin device.  Irreversible.
+
+    trim <dev id> <new size in sectors>
+
+	Delete mappings from the end of a thin device.  Irreversible.
+	You might want to use this if you're reducing the size of
+	your thinly-provisioned device.  In many cases, due to the
+	sharing of blocks between devices, it is not possible to
+	determine in advance how much space 'trim' will release.  (In
+	future a userspace tool might be able to perform this
+	calculation.)
+
+    set_transaction_id <current id> <new id>
+
+	Userland volume managers, such as LVM, need a way to
+	synchronise their external metadata with the internal metadata of the
+	pool target.  The thin-pool target offers to store an
+	arbitrary 64-bit transaction id and return it on the target's
+	status line.  To avoid races you must provide what you think
+	the current transaction id is when you change it with this
+	compare-and-swap message.
+
+'thin' target
+-------------
+
+i) Constructor
+
+    thin <pool dev> <dev id>
+
+    pool dev:
+	the thin-pool device, e.g. /dev/mapper/my_pool or 253:0
+
+    dev id:
+	the internal device identifier of the device to be
+	activated.
+
+The pool doesn't store any size against the thin devices.  If you
+load a thin target that is smaller than you've been using previously,
+then you'll have no access to blocks mapped beyond the end.  If you
+load a target that is bigger than before, then extra blocks will be
+provisioned as and when needed.
+
+If you wish to reduce the size of your thin device and potentially
+regain some space then send the 'trim' message to the pool.
+
+ii) Status
+
+     <nr mapped sectors> <highest mapped sector>
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/calxeda.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/calxeda.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/calxeda.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/calxeda.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,8 @@
+Calxeda Highbank Platforms Device Tree Bindings
+-----------------------------------------------
+
+Boards with Calxeda Cortex-A9 based Highbank SOC shall have the following
+properties.
+
+Required root node properties:
+    - compatible = "calxeda,highbank";
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/fsl.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/fsl.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/fsl.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/fsl.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+Freescale i.MX Platforms Device Tree Bindings
+-----------------------------------------------
+
+i.MX51 Babbage Board
+Required root node properties:
+    - compatible = "fsl,imx51-babbage", "fsl,imx51";
+
+i.MX53 Automotive Reference Design Board
+Required root node properties:
+    - compatible = "fsl,imx53-ard", "fsl,imx53";
+
+i.MX53 Evaluation Kit
+Required root node properties:
+    - compatible = "fsl,imx53-evk", "fsl,imx53";
+
+i.MX53 Quick Start Board
+Required root node properties:
+    - compatible = "fsl,imx53-qsb", "fsl,imx53";
+
+i.MX53 Smart Mobile Reference Design Board
+Required root node properties:
+    - compatible = "fsl,imx53-smd", "fsl,imx53";
+
+i.MX6 Quad SABRE Automotive Board
+Required root node properties:
+    - compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/gic.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/gic.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/gic.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/gic.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,55 @@
+* ARM Generic Interrupt Controller
+
+ARM SMP cores are often associated with a GIC, providing per processor
+interrupts (PPI), shared processor interrupts (SPI) and software
+generated interrupts (SGI).
+
+Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
+Secondary GICs are cascaded into the upward interrupt controller and do not
+have PPIs or SGIs.
+
+Main node required properties:
+
+- compatible : should be one of:
+	"arm,cortex-a9-gic"
+	"arm,arm11mp-gic"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source.  The type shall be a <u32> and the value shall be 3.
+
+  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
+  interrupts.
+
+  The 2nd cell contains the interrupt number for the interrupt type.
+  SPI interrupts are in the range [0-987].  PPI interrupts are in the
+  range [0-15].
+
+  The 3rd cell is the flags, encoded as follows:
+	bits[3:0] trigger type and level flags.
+		1 = low-to-high edge triggered
+		2 = high-to-low edge triggered
+		4 = active high level-sensitive
+		8 = active low level-sensitive
+	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
+	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
+	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
+
+- reg : Specifies base physical address(s) and size of the GIC registers. The
+  first region is the GIC distributor register base and size. The 2nd region is
+  the GIC cpu interface register base and size.
+
+Optional
+- interrupts	: Interrupt source of the parent interrupt controller. Only
+  present on secondary GICs.
+
+Example:
+
+	intc: interrupt-controller@fff11000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <1>;
+		interrupt-controller;
+		reg = <0xfff11000 0x1000>,
+		      <0xfff10100 0x100>;
+	};
+
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/l2cc.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/l2cc.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/l2cc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/l2cc.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,44 @@
+* ARM L2 Cache Controller
+
+ARM cores often have a separate level 2 cache controller. There are various
+implementations of the L2 cache controller with compatible programming models.
+The ARM L2 cache representation in the device tree should be done as follows:
+
+Required properties:
+
+- compatible : should be one of:
+	"arm,pl310-cache"
+	"arm,l220-cache"
+	"arm,l210-cache"
+- cache-unified : Specifies the cache is a unified cache.
+- cache-level : Should be set to 2 for a level 2 cache.
+- reg : Physical base address and size of cache controller's memory mapped
+  registers.
+
+Optional properties:
+
+- arm,data-latency : Cycles of latency for Data RAM accesses. Specifies 3 cells of
+  read, write and setup latencies. Minimum valid values are 1. Controllers
+  without setup latency control should use a value of 0.
+- arm,tag-latency : Cycles of latency for Tag RAM accesses. Specifies 3 cells of
+  read, write and setup latencies. Controllers without setup latency control
+  should use 0. Controllers without separate read and write Tag RAM latency
+  values should only use the first cell.
+- arm,dirty-latency : Cycles of latency for Dirty RAMs. This is a single cell.
+- arm,filter-ranges : <start length> Starting address and length of window to
+  filter. Addresses in the filter window are directed to the M1 port. Other
+  addresses will go to the M0 port.
+- interrupts : 1 combined interrupt.
+
+Example:
+
+L2: cache-controller {
+        compatible = "arm,pl310-cache";
+        reg = <0xfff12000 0x1000>;
+        arm,data-latency = <1 1 1>;
+        arm,tag-latency = <2 2 2>;
+        arm,filter-latency = <0x80000000 0x8000000>;
+        cache-unified;
+        cache-level = <2>;
+	interrupts = <45>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/omap/dsp.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/omap/dsp.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/omap/dsp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/omap/dsp.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,14 @@
+* TI - DSP (Digital Signal Processor)
+
+TI DSP included in OMAP SoC
+
+Required properties:
+- compatible : Should be "ti,omap3-c64" for OMAP3 & 4
+- ti,hwmods: "dsp"
+
+Examples:
+
+dsp {
+    compatible = "ti,omap3-c64";
+    ti,hwmods = "dsp";
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/omap/iva.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/omap/iva.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/omap/iva.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/omap/iva.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+* TI - IVA (Imaging and Video Accelerator) subsystem
+
+The IVA contain various audio, video or imaging HW accelerator
+depending of the version.
+
+Required properties:
+- compatible : Should be:
+  - "ti,ivahd" for OMAP4
+  - "ti,iva2.2" for OMAP3
+  - "ti,iva2.1" for OMAP2430
+  - "ti,iva1" for OMAP2420
+- ti,hwmods: "iva"
+
+Examples:
+
+iva {
+    compatible = "ti,ivahd", "ti,iva";
+    ti,hwmods = "iva";
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/omap/l3-noc.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/omap/l3-noc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/omap/l3-noc.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+* TI - L3 Network On Chip (NoC)
+
+This version is an implementation of the generic NoC IP
+provided by Arteris.
+
+Required properties:
+- compatible : Should be "ti,omap3-l3-smx" for OMAP3 family
+               Should be "ti,omap4-l3-noc" for OMAP4 family
+- ti,hwmods: "l3_main_1", ... One hwmod for each noc domain.
+
+Examples:
+
+ocp {
+	compatible = "ti,omap4-l3-noc", "simple-bus";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+	ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3";
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/omap/mpu.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/omap/mpu.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/omap/mpu.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/omap/mpu.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,27 @@
+* TI - MPU (Main Processor Unit) subsystem
+
+The MPU subsystem contain one or several ARM cores
+depending of the version.
+The MPU contain CPUs, GIC, L2 cache and a local PRCM.
+
+Required properties:
+- compatible : Should be "ti,omap3-mpu" for OMAP3
+               Should be "ti,omap4-mpu" for OMAP4
+- ti,hwmods: "mpu"
+
+Examples:
+
+- For an OMAP4 SMP system:
+
+mpu {
+    compatible = "ti,omap4-mpu";
+    ti,hwmods = "mpu";
+};
+
+
+- For an OMAP3 monocore system:
+
+mpu {
+    compatible = "ti,omap3-mpu";
+    ti,hwmods = "mpu";
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,43 @@
+* Texas Instruments OMAP
+
+OMAP is currently using a static file per SoC family to describe the
+IPs present in the SoC.
+On top of that an omap_device is created to extend the platform_device
+capabilities and to allow binding with one or several hwmods.
+The hwmods will contain all the information to build the device:
+adresse range, irq lines, dma lines, interconnect, PRCM register,
+clock domain, input clocks.
+For the moment just point to the existing hwmod, the next step will be
+to move data from hwmod to device-tree representation.
+
+
+Required properties:
+- compatible: Every devices present in OMAP SoC should be in the
+  form: "ti,XXX"
+- ti,hwmods: list of hwmod names (ascii strings), that comes from the OMAP
+  HW documentation, attached to a device. Must contain at least
+  one hwmod.
+
+Optional properties:
+- ti,no_idle_on_suspend: When present, it prevents the PM to idle the module
+  during suspend.
+
+
+Example:
+
+spinlock@1 {
+    compatible = "ti,omap4-spinlock";
+    ti,hwmods = "spinlock";
+};
+
+
+Boards:
+
+- OMAP3 BeagleBoard : Low cost community board
+  compatible = "ti,omap3-beagle", "ti,omap3"
+
+- OMAP4 SDP : Software Developement Board
+  compatible = "ti,omap4-sdp", "ti,omap4430"
+
+- OMAP4 PandaBoard : Low cost community board
+  compatible = "ti,omap4-panda", "ti,omap4430"
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/picoxcell.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/picoxcell.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/picoxcell.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/picoxcell.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,24 @@
+Picochip picoXcell device tree bindings.
+========================================
+
+Required root node properties:
+    - compatible:
+	- "picochip,pc7302-pc3x3" : PC7302 development board with PC3X3 device.
+	- "picochip,pc7302-pc3x2" : PC7302 development board with PC3X2 device.
+	- "picochip,pc3x3" : picoXcell PC3X3 device based board.
+	- "picochip,pc3x2" : picoXcell PC3X2 device based board.
+
+Timers required properties:
+    - compatible = "picochip,pc3x2-timer"
+    - interrupts : The single IRQ line for the timer.
+    - clock-freq : The frequency in HZ of the timer.
+    - reg : The register bank for the timer.
+
+Note: two timers are required - one for the scheduler clock and one for the
+event tick/NOHZ.
+
+VIC required properties:
+    - compatible = "arm,pl192-vic".
+    - interrupt-controller.
+    - reg : The register bank for the device.
+    - #interrupt-cells : Must be 1.
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/primecell.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/primecell.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/arm/primecell.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/arm/primecell.txt	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,9 @@
 
 Required properties:
 
-- compatible : should be a specific value for peripheral and "arm,primecell"
+- compatible : should be a specific name for the peripheral and
+               "arm,primecell".  The specific name will match the ARM
+               engineering name for the logic block in the form: "arm,pl???"
 
 Optional properties:
 
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/ata/calxeda-sata.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/ata/calxeda-sata.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/ata/calxeda-sata.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/ata/calxeda-sata.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,17 @@
+* Calxeda SATA Controller
+
+SATA nodes are defined to describe on-chip Serial ATA controllers.
+Each SATA controller should have its own node.
+
+Required properties:
+- compatible        : compatible list, contains "calxeda,hb-ahci"
+- interrupts        : <interrupt mapping for SATA IRQ>
+- reg               : <registers mapping>
+
+Example:
+        sata@ffe08000 {
+		compatible = "calxeda,hb-ahci";
+                reg = <0xffe08000 0x1000>;
+                interrupts = <115>;
+        };
+
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/crypto/picochip-spacc.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/crypto/picochip-spacc.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/crypto/picochip-spacc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/crypto/picochip-spacc.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,23 @@
+Picochip picoXcell SPAcc (Security Protocol Accelerator) bindings
+
+Picochip picoXcell devices contain crypto offload engines that may be used for
+IPSEC and femtocell layer 2 ciphering.
+
+Required properties:
+  - compatible : "picochip,spacc-ipsec" for the IPSEC offload engine
+    "picochip,spacc-l2" for the femtocell layer 2 ciphering engine.
+  - reg : Offset and length of the register set for this device
+  - interrupt-parent : The interrupt controller that controls the SPAcc
+    interrupt.
+  - interrupts : The interrupt line from the SPAcc.
+  - ref-clock : The input clock that drives the SPAcc.
+
+Example SPAcc node:
+
+spacc@10000 {
+	compatible = "picochip,spacc-ipsec";
+	reg = <0x100000 0x10000>;
+	interrupt-parent = <&vic0>;
+	interrupts = <24>;
+	ref-clock = <&ipsec_clk>, "ref";
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/gpio/led.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/gpio/led.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/gpio/led.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/gpio/led.txt	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
 
 LED sub-node properties:
 - gpios :  Should specify the LED's GPIO, see "Specifying GPIO information
-  for devices" in Documentation/powerpc/booting-without-of.txt.  Active
+  for devices" in Documentation/devicetree/booting-without-of.txt.  Active
   low LEDs should be indicated using flags in the GPIO specifier.
 - label :  (optional) The label for this LED.  If omitted, the label is
   taken from the node name (excluding the unit address).
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/gpio/pl061-gpio.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/gpio/pl061-gpio.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/gpio/pl061-gpio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/gpio/pl061-gpio.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,10 @@
+ARM PL061 GPIO controller
+
+Required properties:
+- compatible : "arm,pl061", "arm,primecell"
+- #gpio-cells : Should be two. The first cell is the pin number and the
+  second cell is used to specify optional parameters:
+  - bit 0 specifies polarity (0 for normal, 1 for inverted)
+- gpio-controller : Marks the device node as a GPIO controller.
+- interrupts : Interrupt mapping for GPIO IRQ.
+
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+* Freescale Inter IC (I2C) and High Speed Inter IC (HS-I2C) for i.MX
+
+Required properties:
+- compatible : Should be "fsl,<chip>-i2c"
+- reg : Should contain I2C/HS-I2C registers location and length
+- interrupts : Should contain I2C/HS-I2C interrupt
+
+Optional properties:
+- clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz.
+  The absence of the propoerty indicates the default frequency 100 kHz.
+
+Examples:
+
+i2c@83fc4000 { /* I2C2 on i.MX51 */
+	compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+	reg = <0x83fc4000 0x4000>;
+	interrupts = <63>;
+};
+
+i2c@70038000 { /* HS-I2C on i.MX51 */
+	compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+	reg = <0x70038000 0x4000>;
+	interrupts = <64>;
+	clock-frequency = <400000>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/i2c/samsung-i2c.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/i2c/samsung-i2c.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/i2c/samsung-i2c.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/i2c/samsung-i2c.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,39 @@
+* Samsung's I2C controller
+
+The Samsung's I2C controller is used to interface with I2C devices.
+
+Required properties:
+  - compatible: value should be either of the following.
+      (a) "samsung, s3c2410-i2c", for i2c compatible with s3c2410 i2c.
+      (b) "samsung, s3c2440-i2c", for i2c compatible with s3c2440 i2c.
+  - reg: physical base address of the controller and length of memory mapped
+    region.
+  - interrupts: interrupt number to the cpu.
+  - samsung,i2c-sda-delay: Delay (in ns) applied to data line (SDA) edges.
+  - gpios: The order of the gpios should be the following: <SDA, SCL>.
+    The gpio specifier depends on the gpio controller.
+
+Optional properties:
+  - samsung,i2c-slave-addr: Slave address in multi-master enviroment. If not
+    specified, default value is 0.
+  - samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not
+    specified, the default value in Hz is 100000.
+
+Example:
+
+	i2c@13870000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x13870000 0x100>;
+		interrupts = <345>;
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <100000>;
+		gpios = <&gpd1 2 0 /* SDA */
+			 &gpd1 3 0 /* SCL */>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		wm8994@1a {
+			compatible = "wlf,wm8994";
+			reg = <0x1a>;
+		};
+	};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,27 @@
+* NVIDIA Tegra Secure Digital Host Controller
+
+This controller on Tegra family SoCs provides an interface for MMC, SD,
+and SDIO types of memory cards.
+
+Required properties:
+- compatible : Should be "nvidia,<chip>-sdhci"
+- reg : Should contain SD/MMC registers location and length
+- interrupts : Should contain SD/MMC interrupt
+
+Optional properties:
+- cd-gpios : Specify GPIOs for card detection
+- wp-gpios : Specify GPIOs for write protection
+- power-gpios : Specify GPIOs for power control
+- support-8bit : Boolean, indicates if 8-bit mode should be used.
+
+Example:
+
+sdhci@c8000200 {
+	compatible = "nvidia,tegra20-sdhci";
+	reg = <0xc8000200 0x200>;
+	interrupts = <47>;
+	cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+	wp-gpios = <&gpio 57 0>; /* gpio PH1 */
+	power-gpios = <&gpio 155 0>; /* gpio PT3 */
+	support-8bit;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/mtd/atmel-dataflash.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/mtd/atmel-dataflash.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/mtd/atmel-dataflash.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/mtd/atmel-dataflash.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,14 @@
+* Atmel Data Flash
+
+Required properties:
+- compatible : "atmel,<model>", "atmel,<series>", "atmel,dataflash".
+
+Example:
+
+flash@1 {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+	spi-max-frequency = <25000000>;
+	reg = <1>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1,61 +1,24 @@
-CAN Device Tree Bindings
-------------------------
-2011 Freescale Semiconductor, Inc.
-
-fsl,flexcan-v1.0 nodes
------------------------
-In addition to the required compatible-, reg- and interrupt-properties, you can
-also specify which clock source shall be used for the controller.
+Flexcan CAN contoller on Freescale's ARM and PowerPC system-on-a-chip (SOC).
 
-CPI Clock- Can Protocol Interface Clock
-	This CLK_SRC bit of CTRL(control register) selects the clock source to
-	the CAN Protocol Interface(CPI) to be either the peripheral clock
-	(driven by the PLL) or the crystal oscillator clock. The selected clock
-	is the one fed to the prescaler to generate the Serial Clock (Sclock).
-	The PRESDIV field of CTRL(control register) controls a prescaler that
-	generates the Serial Clock (Sclock), whose period defines the
-	time quantum used to compose the CAN waveform.
+Required properties:
 
-Can Engine Clock Source
-	There are two sources for CAN clock
-	- Platform Clock  It represents the bus clock
-	- Oscillator Clock
+- compatible : Should be "fsl,<processor>-flexcan"
 
-	Peripheral Clock (PLL)
-	--------------
-		     |
-		    ---------		      -------------
-		    |       |CPI Clock	      | Prescaler |       Sclock
-		    |       |---------------->| (1.. 256) |------------>
-		    ---------		      -------------
-                     |  |
-	--------------  ---------------------CLK_SRC
-	Oscillator Clock
+  An implementation should also claim any of the following compatibles
+  that it is fully backwards compatible with:
 
-- fsl,flexcan-clock-source : CAN Engine Clock Source.This property selects
-			     the peripheral clock. PLL clock is fed to the
-			     prescaler to generate the Serial Clock (Sclock).
-			     Valid values are "oscillator" and "platform"
-			     "oscillator": CAN engine clock source is oscillator clock.
-			     "platform" The CAN engine clock source is the bus clock
-		             (platform clock).
+  - fsl,p1010-flexcan
 
-- fsl,flexcan-clock-divider : for the reference and system clock, an additional
-			      clock divider can be specified.
-- clock-frequency: frequency required to calculate the bitrate for FlexCAN.
+- reg : Offset and length of the register set for this device
+- interrupts : Interrupt tuple for this device
+- clock-frequency : The oscillator frequency driving the flexcan device
 
-Note:
-	- v1.0 of flexcan-v1.0 represent the IP block version for P1010 SOC.
-	- P1010 does not have oscillator as the Clock Source.So the default
-	  Clock Source is platform clock.
-Examples:
+Example:
 
-	can0@1c000 {
-		compatible = "fsl,flexcan-v1.0";
+	can@1c000 {
+		compatible = "fsl,p1010-flexcan";
 		reg = <0x1c000 0x1000>;
 		interrupts = <48 0x2>;
 		interrupt-parent = <&mpic>;
-		fsl,flexcan-clock-source = "platform";
-		fsl,flexcan-clock-divider = <2>;
-		clock-frequency = <fixed by u-boot>;
+		clock-frequency = <200000000>; // filled in by bootloader
 	};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/net/smsc911x.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/net/smsc911x.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/net/smsc911x.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/net/smsc911x.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,38 @@
+* Smart Mixed-Signal Connectivity (SMSC) LAN911x/912x Controller
+
+Required properties:
+- compatible : Should be "smsc,lan<model>", "smsc,lan9115"
+- reg : Address and length of the io space for SMSC LAN
+- interrupts : Should contain SMSC LAN interrupt line
+- interrupt-parent : Should be the phandle for the interrupt controller
+  that services interrupts for this device
+- phy-mode : String, operation mode of the PHY interface.
+  Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii",
+  "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii".
+
+Optional properties:
+- reg-shift : Specify the quantity to shift the register offsets by
+- reg-io-width : Specify the size (in bytes) of the IO accesses that
+  should be performed on the device.  Valid value for SMSC LAN is
+  2 or 4.  If it's omitted or invalid, the size would be 2.
+- smsc,irq-active-high : Indicates the IRQ polarity is active-high
+- smsc,irq-push-pull : Indicates the IRQ type is push-pull
+- smsc,force-internal-phy : Forces SMSC LAN controller to use
+  internal PHY
+- smsc,force-external-phy : Forces SMSC LAN controller to use
+  external PHY
+- smsc,save-mac-address : Indicates that mac address needs to be saved
+  before resetting the controller
+- local-mac-address : 6 bytes, mac address
+
+Examples:
+
+lan9220@f4000000 {
+	compatible = "smsc,lan9220", "smsc,lan9115";
+	reg = <0xf4000000 0x2000000>;
+	phy-mode = "mii";
+	interrupt-parent = <&gpio1>;
+	interrupts = <31>;
+	reg-io-width = <4>;
+	smsc,irq-push-pull;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+NVIDIA Tegra 2 pinmux controller
+
+Required properties:
+- compatible : "nvidia,tegra20-pinmux"
+
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/powerpc/fsl/board.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/powerpc/fsl/board.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/powerpc/fsl/board.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/powerpc/fsl/board.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,8 @@
+Freescale Reference Board Bindings
+
+This document describes device tree bindings for various devices that
+exist on some Freescale reference boards.
+
 * Board Control and Status (BCSR)
 
 Required properties:
@@ -12,25 +17,26 @@
 		reg = <f8000000 8000>;
 	};
 
-* Freescale on board FPGA
+* Freescale on-board FPGA
 
 This is the memory-mapped registers for on board FPGA.
 
 Required properities:
-- compatible : should be "fsl,fpga-pixis".
-- reg : should contain the address and the length of the FPPGA register
-  set.
+- compatible: should be a board-specific string followed by a string
+  indicating the type of FPGA.  Example:
+	"fsl,<board>-fpga", "fsl,fpga-pixis"
+- reg: should contain the address and the length of the FPGA register set.
 - interrupt-parent: should specify phandle for the interrupt controller.
-- interrupts : should specify event (wakeup) IRQ.
+- interrupts: should specify event (wakeup) IRQ.
 
-Example (MPC8610HPCD):
+Example (P1022DS):
 
-	board-control@e8000000 {
-		compatible = "fsl,fpga-pixis";
-		reg = <0xe8000000 32>;
-		interrupt-parent = <&mpic>;
-		interrupts = <8 8>;
-	};
+	 board-control@3,0 {
+		 compatible = "fsl,p1022ds-fpga", "fsl,fpga-ngpixis";
+		 reg = <3 0 0x30>;
+		 interrupt-parent = <&mpic>;
+		 interrupts = <8 8 0 0>;
+	 };
 
 * Freescale BCSR GPIO banks
 
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/powerpc/fsl/dcsr.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/powerpc/fsl/dcsr.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/powerpc/fsl/dcsr.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/powerpc/fsl/dcsr.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,395 @@
+===================================================================
+Debug Control and Status Register (DCSR) Binding
+Copyright 2011 Freescale Semiconductor Inc.
+
+NOTE: The bindings described in this document are preliminary and subject
+to change.  Some of the compatible strings that contain only generic names
+may turn out to be inappropriate, or need additional properties to describe
+the integration of the block with the rest of the chip.
+
+=====================================================================
+Debug Control and Status Register Memory Map
+
+Description
+
+This node defines the base address and range for the
+defined DCSR Memory Map. Child nodes will describe the individual
+debug blocks defined within this memory space.
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include "fsl,dcsr" and "simple-bus".
+	The DCSR space exists in the memory-mapped bus.
+
+	- #address-cells
+	Usage: required
+	Value type: <u32>
+	Definition: A standard property.  Defines the number of cells
+	or representing physical addresses in child nodes.
+
+	- #size-cells
+	Usage: required
+	Value type: <u32>
+	Definition: A standard property.  Defines the number of cells
+	or representing the size of physical addresses in
+	child nodes.
+
+	- ranges
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property. Specifies the physical address
+	range of the DCSR space.
+
+EXAMPLE
+	dcsr: dcsr@f00000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,dcsr", "simple-bus";
+		ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+	};
+
+=====================================================================
+Event Processing Unit
+
+This node represents the region of DCSR space allocated to the EPU
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include "fsl,dcsr-epu"
+
+	- interrupts
+	Usage: required
+	Value type: <prop_encoded-array>
+	Definition:  Specifies the interrupts generated by the EPU.
+	The value of the interrupts property consists of three
+	interrupt specifiers. The format of the specifier is defined
+	by the binding document describing the node's interrupt parent.
+
+	The EPU counters can be configured to assert the performance
+	monitor interrupt signal based on either counter overflow or value
+	match. Which counter asserted the interrupt is captured in an EPU
+	Counter Interrupt Status Register (EPCPUISR).
+
+	The EPU unit can also be configured to assert either or both of
+	two interrupt signals based on debug event sources within the SoC.
+	The interrupt signals are epu_xt_int0 and epu_xt_int1.
+	Which event source asserted the interrupt is captured in an EPU
+	Interrupt Status Register (EPISR0,EPISR1).
+
+	Interrupt numbers are lised in order (perfmon, event0, event1).
+
+	- interrupt-parent
+	Usage: required
+	Value type: <phandle>
+	Definition: A single <phandle> value that points
+	to the interrupt parent to which the child domain
+	is being mapped. Value must be "&mpic"
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+
+EXAMPLE
+	dcsr-epu@0 {
+		compatible = "fsl,dcsr-epu";
+		interrupts = <52 2 0 0
+			      84 2 0 0
+			      85 2 0 0>;
+		interrupt-parent = <&mpic>;
+		reg = <0x0 0x1000>;
+	};
+
+=======================================================================
+Nexus Port Controller
+
+This node represents the region of DCSR space allocated to the NPC
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include "fsl,dcsr-npc"
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+	The Nexus Port controller occupies two regions in the DCSR space
+	with distinct functionality.
+
+	The first register range describes the Nexus Port Controller
+	control and status registers.
+
+	The second register range describes the Nexus Port Controller
+	internal trace buffer. The NPC trace buffer is a small memory buffer
+	which stages the nexus trace data for transmission via the Aurora port
+	or to a DDR based trace buffer. In some configurations the NPC trace
+	buffer can be the only trace buffer used.
+
+
+EXAMPLE
+		dcsr-npc {
+			compatible = "fsl,dcsr-npc";
+			reg = <0x1000 0x1000 0x1000000 0x8000>;
+		};
+
+=======================================================================
+Nexus Concentrator
+
+This node represents the region of DCSR space allocated to the NXC
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include "fsl,dcsr-nxc"
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+
+EXAMPLE
+		dcsr-nxc@2000 {
+			compatible = "fsl,dcsr-nxc";
+			reg = <0x2000 0x1000>;
+		};
+=======================================================================
+CoreNet Debug Controller
+
+This node represents the region of DCSR space allocated to
+the CoreNet Debug controller.
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include "fsl,dcsr-corenet"
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+	The CoreNet Debug controller occupies two regions in the DCSR space
+	with distinct functionality.
+
+	The first register range describes the CoreNet Debug Controller
+	functionalty to perform transaction and transaction attribute matches.
+
+	The second register range describes the CoreNet Debug Controller
+	functionalty to trigger event notifications and debug traces.
+
+EXAMPLE
+		dcsr-corenet {
+			compatible = "fsl,dcsr-corenet";
+			reg = <0x8000 0x1000 0xB0000 0x1000>;
+		};
+
+=======================================================================
+Data Path Debug controller
+
+This node represents the region of DCSR space allocated to
+the DPAA Debug Controller. This controller controls debug configuration
+for the QMAN and FMAN blocks.
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include both an identifier specific to the SoC
+	or Debug IP of the form "fsl,<soc>-dcsr-dpaa" in addition to the
+	generic compatible string "fsl,dcsr-dpaa".
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+
+EXAMPLE
+		dcsr-dpaa@9000 {
+			compatible = "fsl,p4080-dcsr-dpaa", "fsl,dcsr-dpaa";
+			reg = <0x9000 0x1000>;
+		};
+
+=======================================================================
+OCeaN Debug controller
+
+This node represents the region of DCSR space allocated to
+the OCN Debug Controller.
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include both an identifier specific to the SoC
+	or Debug IP of the form "fsl,<soc>-dcsr-ocn" in addition to the
+	generic compatible string "fsl,dcsr-ocn".
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+
+EXAMPLE
+		dcsr-ocn@11000 {
+			compatible = "fsl,p4080-dcsr-ocn", "fsl,dcsr-ocn";
+			reg = <0x11000 0x1000>;
+		};
+
+=======================================================================
+DDR Controller Debug controller
+
+This node represents the region of DCSR space allocated to
+the OCN Debug Controller.
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include "fsl,dcsr-ddr"
+
+	- dev-handle
+	Usage: required
+	Definition: A phandle to associate this debug node with its
+	component controller.
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+
+EXAMPLE
+		dcsr-ddr@12000 {
+			compatible = "fsl,dcsr-ddr";
+			dev-handle = <&ddr1>;
+			reg = <0x12000 0x1000>;
+		};
+
+=======================================================================
+Nexus Aurora Link Controller
+
+This node represents the region of DCSR space allocated to
+the NAL Controller.
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include both an identifier specific to the SoC
+	or Debug IP of the form "fsl,<soc>-dcsr-nal" in addition to the
+	generic compatible string "fsl,dcsr-nal".
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+
+EXAMPLE
+		dcsr-nal@18000 {
+			compatible = "fsl,p4080-dcsr-nal", "fsl,dcsr-nal";
+			reg = <0x18000 0x1000>;
+		};
+
+
+=======================================================================
+Run Control and Power Management
+
+This node represents the region of DCSR space allocated to
+the RCPM Debug Controller. This functionlity is limited to the
+control the debug operations of the SoC and cores.
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include both an identifier specific to the SoC
+	or Debug IP of the form "fsl,<soc>-dcsr-rcpm" in addition to the
+	generic compatible string "fsl,dcsr-rcpm".
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+
+EXAMPLE
+		dcsr-rcpm@22000 {
+			compatible = "fsl,p4080-dcsr-rcpm", "fsl,dcsr-rcpm";
+			reg = <0x22000 0x1000>;
+		};
+
+=======================================================================
+Core Service Bridge Proxy
+
+This node represents the region of DCSR space allocated to
+the Core Service Bridge Proxies.
+There is one Core Service Bridge Proxy device for each CPU in the system.
+This functionlity provides access to the debug operations of the CPU.
+
+PROPERTIES
+
+	- compatible
+	Usage: required
+	Value type: <string>
+	Definition: Must include both an identifier specific to the cpu
+	of the form "fsl,dcsr-<cpu>-sb-proxy" in addition to the
+	generic compatible string "fsl,dcsr-cpu-sb-proxy".
+
+	- cpu-handle
+	Usage: required
+	Definition: A phandle to associate this debug node with its cpu.
+
+	- reg
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: A standard property.  Specifies the physical address
+	offset and length of the DCSR space registers of the device
+	configuration block.
+
+EXAMPLE
+		dcsr-cpu-sb-proxy@40000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy",
+				     "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu0>;
+			reg = <0x40000 0x1000>;
+		};
+		dcsr-cpu-sb-proxy@41000 {
+			compatible = "fsl,dcsr-e500mc-sb-proxy",
+				     "fsl,dcsr-cpu-sb-proxy";
+			cpu-handle = <&cpu1>;
+			reg = <0x41000 0x1000>;
+		};
+
+=======================================================================
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,16 @@
   are routed to IPIC, and for 85xx/86xx cpu the interrupts are routed
   to MPIC.
 
+Optional properties:
+- msi-address-64: 64-bit PCI address of the MSIIR register. The MSIIR register
+  is used for MSI messaging.  The address of MSIIR in PCI address space is
+  the MSI message address.
+
+  This property may be used in virtualized environments where the hypervisor
+  has created an alternate mapping for the MSIR block.  See below for an
+  explanation.
+
+
 Example:
 	msi@41600 {
 		compatible = "fsl,mpc8610-msi", "fsl,mpic-msi";
@@ -41,3 +51,35 @@
 			0xe7 0>;
 		interrupt-parent = <&mpic>;
 	};
+
+The Freescale hypervisor and msi-address-64
+-------------------------------------------
+Normally, PCI devices have access to all of CCSR via an ATMU mapping.  The
+Freescale MSI driver calculates the address of MSIIR (in the MSI register
+block) and sets that address as the MSI message address.
+
+In a virtualized environment, the hypervisor may need to create an IOMMU
+mapping for MSIIR.  The Freescale ePAPR hypervisor has this requirement
+because of hardware limitations of the Peripheral Access Management Unit
+(PAMU), which is currently the only IOMMU that the hypervisor supports.
+The ATMU is programmed with the guest physical address, and the PAMU
+intercepts transactions and reroutes them to the true physical address.
+
+In the PAMU, each PCI controller is given only one primary window.  The
+PAMU restricts DMA operations so that they can only occur within a window.
+Because PCI devices must be able to DMA to memory, the primary window must
+be used to cover all of the guest's memory space.
+
+PAMU primary windows can be divided into 256 subwindows, and each
+subwindow can have its own address mapping ("guest physical" to "true
+physical").  However, each subwindow has to have the same alignment, which
+means they cannot be located at just any address.  Because of these
+restrictions, it is usually impossible to create a 4KB subwindow that
+covers MSIIR where it's normally located.
+
+Therefore, the hypervisor has to create a subwindow inside the same
+primary window used for memory, but mapped to the MSIR block (where MSIIR
+lives).  The first subwindow after the end of guest memory is used for
+this.  The address specified in the msi-address-64 property is the PCI
+address of MSIIR.  The hypervisor configures the PAMU to map that address to
+the true physical address of MSIIR.
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/serial/rs485.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/serial/rs485.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/serial/rs485.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/serial/rs485.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,31 @@
+* RS485 serial communications
+
+The RTS signal is capable of automatically controlling line direction for
+the built-in half-duplex mode.
+The properties described hereafter shall be given to a half-duplex capable
+UART node.
+
+Required properties:
+- rs485-rts-delay: prop-encoded-array <a b> where:
+  * a is the delay beteween rts signal and beginning of data sent in milliseconds.
+      it corresponds to the delay before sending data.
+  * b is the delay between end of data sent and rts signal in milliseconds
+      it corresponds to the delay after sending data and actual release of the line.
+
+Optional properties:
+- linux,rs485-enabled-at-boot-time: empty property telling to enable the rs485
+  feature at boot time. It can be disabled later with proper ioctl.
+- rs485-rx-during-tx: empty property that enables the receiving of data even
+  whilst sending data.
+
+RS485 example for Atmel USART:
+	usart0: serial@fff8c000 {
+		compatible = "atmel,at91sam9260-usart";
+		reg = <0xfff8c000 0x4000>;
+		interrupts = <7>;
+		atmel,use-dma-rx;
+		atmel,use-dma-tx;
+		linux,rs485-enabled-at-boot-time;
+		rs485-rts-delay = <0 200>;		// in milliseconds
+	};
+
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,11 @@
+* Freescale SGTL5000 Stereo Codec
+
+Required properties:
+- compatible : "fsl,sgtl5000".
+
+Example:
+
+codec: sgtl5000@0a {
+	compatible = "fsl,sgtl5000";
+	reg = <0x0a>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8510.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8510.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8510.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8510.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8510 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8510"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8510@1a {
+	compatible = "wlf,wm8510";
+	reg = <0x1a>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8523.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8523.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8523.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8523.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+WM8523 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+  - compatible : "wlf,wm8523"
+
+  - reg : the I2C address of the device.
+
+Example:
+
+codec: wm8523@1a {
+	compatible = "wlf,wm8523";
+	reg = <0x1a>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8580.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8580.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8580.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8580.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+WM8580 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+  - compatible : "wlf,wm8580"
+
+  - reg : the I2C address of the device.
+
+Example:
+
+codec: wm8580@1a {
+	compatible = "wlf,wm8580";
+	reg = <0x1a>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8711.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8711.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8711.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8711.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8711 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8711"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8711@1a {
+	compatible = "wlf,wm8711";
+	reg = <0x1a>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8728.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8728.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8728.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8728.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8728 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8728"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8728@1a {
+	compatible = "wlf,wm8728";
+	reg = <0x1a>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8731.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8731.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8731.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8731.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8731 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8731"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8731@1a {
+	compatible = "wlf,wm8731";
+	reg = <0x1a>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8737.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8737.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8737.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8737.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8737 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8737"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8737@1a {
+	compatible = "wlf,wm8737";
+	reg = <0x1a>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8741.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8741.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8741.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8741.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8741 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8741"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8741@1a {
+	compatible = "wlf,wm8741";
+	reg = <0x1a>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8750.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8750.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8750.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8750.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8750 and WM8987 audio CODECs
+
+These devices support both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8750" or "wlf,wm8987"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8750@1a {
+	compatible = "wlf,wm8750";
+	reg = <0x1a>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8753.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8753.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8753.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8753.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8753 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8753"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8737@1a {
+	compatible = "wlf,wm8753";
+	reg = <0x1a>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8770.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8770.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8770.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8770.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+WM8770 audio CODEC
+
+This device supports SPI.
+
+Required properties:
+
+  - compatible : "wlf,wm8770"
+
+  - reg : the chip select number.
+
+Example:
+
+codec: wm8770@1 {
+	compatible = "wlf,wm8770";
+	reg = <1>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8776.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8776.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8776.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8776.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8776 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8776"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8776@1a {
+	compatible = "wlf,wm8776";
+	reg = <0x1a>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8804.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8804.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/sound/wm8804.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/sound/wm8804.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,18 @@
+WM8804 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8804"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8804@1a {
+	compatible = "wlf,wm8804";
+	reg = <0x1a>;
+};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/spi/spi_pl022.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/spi/spi_pl022.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/spi/spi_pl022.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/spi/spi_pl022.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,12 @@
+ARM PL022 SPI controller
+
+Required properties:
+- compatible : "arm,pl022", "arm,primecell"
+- reg : Offset and length of the register set for the device
+- interrupts : Should contain SPI controller interrupt
+
+Optional properties:
+- cs-gpios : should specify GPIOs used for chipselects.
+  The gpios will be referred to as reg = <index> in the SPI child nodes.
+  If unspecified, a single SPI device without a chip select can be used.
+
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,27 @@
+* Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART)
+
+Required properties:
+- compatible: Should be "atmel,<chip>-usart"
+  The compatible <chip> indicated will be the first SoC to support an
+  additional mode or an USART new feature.
+- reg: Should contain registers location and length
+- interrupts: Should contain interrupt
+
+Optional properties:
+- atmel,use-dma-rx: use of PDC or DMA for receiving data
+- atmel,use-dma-tx: use of PDC or DMA for transmitting data
+
+<chip> compatible description:
+- at91rm9200:  legacy USART support
+- at91sam9260: generic USART implementation for SAM9 SoCs
+
+Example:
+
+	usart0: serial@fff8c000 {
+		compatible = "atmel,at91sam9260-usart";
+		reg = <0xfff8c000 0x4000>;
+		interrupts = <7>;
+		atmel,use-dma-rx;
+		atmel,use-dma-tx;
+	};
+
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/tty/serial/msm_serial.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/tty/serial/msm_serial.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/tty/serial/msm_serial.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,27 @@
+* Qualcomm MSM UART
+
+Required properties:
+- compatible :
+	- "qcom,msm-uart", and one of "qcom,msm-hsuart" or
+	  "qcom,msm-lsuart".
+- reg : offset and length of the register set for the device
+	for the hsuart operating in compatible mode, there should be a
+	second pair describing the gsbi registers.
+- interrupts : should contain the uart interrupt.
+
+There are two different UART blocks used in MSM devices,
+"qcom,msm-hsuart" and "qcom,msm-lsuart".  The msm-serial driver is
+able to handle both of these, and matches against the "qcom,msm-uart"
+as the compatibility.
+
+The registers for the "qcom,msm-hsuart" device need to specify both
+register blocks, even for the common driver.
+
+Example:
+
+	uart@19c400000 {
+		compatible = "qcom,msm-hsuart", "qcom,msm-uart";
+		reg = <0x19c40000 0x1000>,
+		      <0x19c00000 0x1000>;
+		interrupts = <195>;
+	};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+* Synopsys DesignWare ABP UART
+
+Required properties:
+- compatible : "snps,dw-apb-uart"
+- reg : offset and length of the register set for the device.
+- interrupts : should contain uart interrupt.
+- clock-frequency : the input clock frequency for the UART.
+
+Optional properties:
+- reg-shift : quantity to shift the register offsets by.  If this property is
+  not present then the register offsets are not shifted.
+- reg-io-width : the size (in bytes) of the IO accesses that should be
+  performed on the device.  If this property is not present then single byte
+  accesses are used.
+
+Example:
+
+	uart@80230000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x80230000 0x100>;
+		clock-frequency = <3686400>;
+		interrupts = <10>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+	};
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/vendor-prefixes.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/vendor-prefixes.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/vendor-prefixes.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/vendor-prefixes.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,41 @@
+Device tree binding vendor prefix registry.  Keep list in alphabetical order.
+
+This isn't an exhaustive list, but you should add new prefixes to it before
+using them to avoid name-space collisions.
+
+adi	Analog Devices, Inc.
+amcc	Applied Micro Circuits Corporation (APM, formally AMCC)
+apm	Applied Micro Circuits Corporation (APM)
+arm	ARM Ltd.
+atmel	Atmel Corporation
+chrp	Common Hardware Reference Platform
+dallas	Maxim Integrated Products (formerly Dallas Semiconductor)
+denx	Denx Software Engineering
+epson	Seiko Epson Corp.
+est	ESTeem Wireless Modems
+fsl	Freescale Semiconductor
+GEFanuc	GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+gef	GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+hp	Hewlett Packard
+ibm	International Business Machines (IBM)
+idt	Integrated Device Technologies, Inc.
+intercontrol	Inter Control Group
+linux	Linux-specific binding
+marvell	Marvell Technology Group Ltd.
+maxim	Maxim Integrated Products
+mosaixtech	Mosaix Technologies, Inc.
+national	National Semiconductor
+nintendo	Nintendo
+nvidia	NVIDIA
+nxp	NXP Semiconductors
+powervr	Imagination Technologies
+qcom	Qualcomm, Inc.
+ramtron	Ramtron International
+samsung	Samsung Semiconductor
+schindler	Schindler
+sil	Silicon Image
+simtek
+sirf	SiRF Technology, Inc.
+stericsson	ST-Ericsson
+ti	Texas Instruments
+xlnx	Xilinx
diff -druN linux-libre-3.1-gnu/Documentation/devicetree/bindings/virtio/mmio.txt linux-libre-3.2-gnu/Documentation/devicetree/bindings/virtio/mmio.txt
--- linux-libre-3.1-gnu/Documentation/devicetree/bindings/virtio/mmio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/devicetree/bindings/virtio/mmio.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,17 @@
+* virtio memory mapped device
+
+See http://ozlabs.org/~rusty/virtio-spec/ for more details.
+
+Required properties:
+
+- compatible:	"virtio,mmio" compatibility string
+- reg:		control registers base address and size including configuration space
+- interrupts:	interrupt generated by the device
+
+Example:
+
+	virtio_block@3000 {
+		compatible = "virtio,mmio";
+		reg = <0x3000 0x100>;
+		interrupts = <41>;
+	}
diff -druN linux-libre-3.1-gnu/Documentation/DMA-API.txt linux-libre-3.2-gnu/Documentation/DMA-API.txt
--- linux-libre-3.1-gnu/Documentation/DMA-API.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/DMA-API.txt	2012-01-04 18:55:44.000000000 -0500
@@ -50,6 +50,13 @@
 implementation may choose to ignore flags that affect the location of
 the returned memory, like GFP_DMA).
 
+void *
+dma_zalloc_coherent(struct device *dev, size_t size,
+			     dma_addr_t *dma_handle, gfp_t flag)
+
+Wraps dma_alloc_coherent() and also zeroes the returned memory if the
+allocation attempt succeeded.
+
 void
 dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
 			   dma_addr_t dma_handle)
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/80211.tmpl linux-libre-3.2-gnu/Documentation/DocBook/80211.tmpl
--- linux-libre-3.1-gnu/Documentation/DocBook/80211.tmpl	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/DocBook/80211.tmpl	2012-01-04 18:55:44.000000000 -0500
@@ -433,8 +433,18 @@
           Insert notes about VLAN interfaces with hw crypto here or
           in the hw crypto chapter.
         </para>
+      <section id="ps-client">
+        <title>support for powersaving clients</title>
+!Pinclude/net/mac80211.h AP support for powersaving clients
+      </section>
 !Finclude/net/mac80211.h ieee80211_get_buffered_bc
 !Finclude/net/mac80211.h ieee80211_beacon_get
+!Finclude/net/mac80211.h ieee80211_sta_eosp_irqsafe
+!Finclude/net/mac80211.h ieee80211_frame_release_type
+!Finclude/net/mac80211.h ieee80211_sta_ps_transition
+!Finclude/net/mac80211.h ieee80211_sta_ps_transition_ni
+!Finclude/net/mac80211.h ieee80211_sta_set_buffered
+!Finclude/net/mac80211.h ieee80211_sta_block_awake
       </chapter>
 
       <chapter id="multi-iface">
@@ -460,7 +470,6 @@
 !Finclude/net/mac80211.h sta_notify_cmd
 !Finclude/net/mac80211.h ieee80211_find_sta
 !Finclude/net/mac80211.h ieee80211_find_sta_by_ifaddr
-!Finclude/net/mac80211.h ieee80211_sta_block_awake
       </chapter>
 
       <chapter id="hardware-scan-offload">
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/drm.tmpl linux-libre-3.2-gnu/Documentation/DocBook/drm.tmpl
--- linux-libre-3.1-gnu/Documentation/DocBook/drm.tmpl	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/DocBook/drm.tmpl	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,7 @@
       The Linux DRM layer contains code intended to support the needs
       of complex graphics devices, usually containing programmable
       pipelines well suited to 3D graphics acceleration.  Graphics
-      drivers in the kernel can make use of DRM functions to make
+      drivers in the kernel may make use of DRM functions to make
       tasks like memory management, interrupt handling and DMA easier,
       and provide a uniform interface to applications.
     </para>
@@ -57,10 +57,10 @@
       existing drivers.
     </para>
     <para>
-      First, we'll go over some typical driver initialization
+      First, we go over some typical driver initialization
       requirements, like setting up command buffers, creating an
       initial output configuration, and initializing core services.
-      Subsequent sections will cover core internals in more detail,
+      Subsequent sections cover core internals in more detail,
       providing implementation notes and examples.
     </para>
     <para>
@@ -74,7 +74,7 @@
     </para>
     <para>
       The core of every DRM driver is struct drm_driver.  Drivers
-      will typically statically initialize a drm_driver structure,
+      typically statically initialize a drm_driver structure,
       then pass it to drm_init() at load time.
     </para>
 
@@ -88,8 +88,8 @@
     </para>
     <programlisting>
       static struct drm_driver driver = {
-	/* don't use mtrr's here, the Xserver or user space app should
-	 * deal with them for intel hardware.
+	/* Don't use MTRRs here; the Xserver or userspace app should
+	 * deal with them for Intel hardware.
 	 */
 	.driver_features =
 	    DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
@@ -154,8 +154,8 @@
     </programlisting>
     <para>
       In the example above, taken from the i915 DRM driver, the driver
-      sets several flags indicating what core features it supports.
-      We'll go over the individual callbacks in later sections.  Since
+      sets several flags indicating what core features it supports;
+      we go over the individual callbacks in later sections.  Since
       flags indicate which features your driver supports to the DRM
       core, you need to set most of them prior to calling drm_init().  Some,
       like DRIVER_MODESET can be set later based on user supplied parameters,
@@ -203,8 +203,8 @@
 	<term>DRIVER_HAVE_IRQ</term><term>DRIVER_IRQ_SHARED</term>
 	<listitem>
 	  <para>
-	    DRIVER_HAVE_IRQ indicates whether the driver has a IRQ
-	    handler, DRIVER_IRQ_SHARED indicates whether the device &amp;
+	    DRIVER_HAVE_IRQ indicates whether the driver has an IRQ
+	    handler.  DRIVER_IRQ_SHARED indicates whether the device &amp;
 	    handler support shared IRQs (note that this is required of
 	    PCI drivers).
 	  </para>
@@ -214,8 +214,8 @@
 	<term>DRIVER_DMA_QUEUE</term>
 	<listitem>
 	  <para>
-	    If the driver queues DMA requests and completes them
-	    asynchronously, this flag should be set.  Deprecated.
+	    Should be set if the driver queues DMA requests and completes them
+	    asynchronously.  Deprecated.
 	  </para>
 	</listitem>
       </varlistentry>
@@ -238,7 +238,7 @@
     </variablelist>
     <para>
       In this specific case, the driver requires AGP and supports
-      IRQs.  DMA, as we'll see, is handled by device specific ioctls
+      IRQs.  DMA, as discussed later, is handled by device-specific ioctls
       in this case.  It also supports the kernel mode setting APIs, though
       unlike in the actual i915 driver source, this example unconditionally
       exports KMS capability.
@@ -269,36 +269,34 @@
       initial output configuration.
     </para>
     <para>
-      Note that the tasks performed at driver load time must not
-      conflict with DRM client requirements.  For instance, if user
+      If compatibility is a concern (e.g. with drivers converted over
+      to the new interfaces from the old ones), care must be taken to
+      prevent device initialization and control that is incompatible with
+      currently active userspace drivers.  For instance, if user
       level mode setting drivers are in use, it would be problematic
       to perform output discovery &amp; configuration at load time.
-      Likewise, if pre-memory management aware user level drivers are
+      Likewise, if user-level drivers unaware of memory management are
       in use, memory management and command buffer setup may need to
-      be omitted.  These requirements are driver specific, and care
+      be omitted.  These requirements are driver-specific, and care
       needs to be taken to keep both old and new applications and
       libraries working.  The i915 driver supports the "modeset"
       module parameter to control whether advanced features are
-      enabled at load time or in legacy fashion.  If compatibility is
-      a concern (e.g. with drivers converted over to the new interfaces
-      from the old ones), care must be taken to prevent incompatible
-      device initialization and control with the currently active
-      userspace drivers.
+      enabled at load time or in legacy fashion.
     </para>
 
     <sect2>
       <title>Driver private &amp; performance counters</title>
       <para>
 	The driver private hangs off the main drm_device structure and
-	can be used for tracking various device specific bits of
+	can be used for tracking various device-specific bits of
 	information, like register offsets, command buffer status,
 	register state for suspend/resume, etc.  At load time, a
-	driver can simply allocate one and set drm_device.dev_priv
-	appropriately; at unload the driver can free it and set
-	drm_device.dev_priv to NULL.
+	driver may simply allocate one and set drm_device.dev_priv
+	appropriately; it should be freed and drm_device.dev_priv set
+	to NULL when the driver is unloaded.
       </para>
       <para>
-	The DRM supports several counters which can be used for rough
+	The DRM supports several counters which may be used for rough
 	performance characterization.  Note that the DRM stat counter
 	system is not often used by applications, and supporting
 	additional counters is completely optional.
@@ -307,15 +305,15 @@
 	These interfaces are deprecated and should not be used.  If performance
 	monitoring is desired, the developer should investigate and
 	potentially enhance the kernel perf and tracing infrastructure to export
-	GPU related performance information to performance monitoring
-	tools and applications.
+	GPU related performance information for consumption by performance
+	monitoring tools and applications.
       </para>
     </sect2>
 
     <sect2>
       <title>Configuring the device</title>
       <para>
-	Obviously, device configuration will be device specific.
+	Obviously, device configuration is device-specific.
 	However, there are several common operations: finding a
 	device's PCI resources, mapping them, and potentially setting
 	up an IRQ handler.
@@ -323,10 +321,10 @@
       <para>
 	Finding &amp; mapping resources is fairly straightforward.  The
 	DRM wrapper functions, drm_get_resource_start() and
-	drm_get_resource_len() can be used to find BARs on the given
+	drm_get_resource_len(), may be used to find BARs on the given
 	drm_device struct.  Once those values have been retrieved, the
 	driver load function can call drm_addmap() to create a new
-	mapping for the BAR in question.  Note you'll probably want a
+	mapping for the BAR in question.  Note that you probably want a
 	drm_local_map_t in your driver private structure to track any
 	mappings you create.
 <!-- !Fdrivers/gpu/drm/drm_bufs.c drm_get_resource_* -->
@@ -335,20 +333,20 @@
       <para>
 	if compatibility with other operating systems isn't a concern
 	(DRM drivers can run under various BSD variants and OpenSolaris),
-	native Linux calls can be used for the above, e.g. pci_resource_*
+	native Linux calls may be used for the above, e.g. pci_resource_*
 	and iomap*/iounmap.  See the Linux device driver book for more
 	info.
       </para>
       <para>
-	Once you have a register map, you can use the DRM_READn() and
+	Once you have a register map, you may use the DRM_READn() and
 	DRM_WRITEn() macros to access the registers on your device, or
-	use driver specific versions to offset into your MMIO space
-	relative to a driver specific base pointer (see I915_READ for
-	example).
+	use driver-specific versions to offset into your MMIO space
+	relative to a driver-specific base pointer (see I915_READ for
+	an example).
       </para>
       <para>
 	If your device supports interrupt generation, you may want to
-	setup an interrupt handler at driver load time as well.  This
+	set up an interrupt handler when the driver is loaded.  This
 	is done using the drm_irq_install() function.  If your device
 	supports vertical blank interrupts, it should call
 	drm_vblank_init() to initialize the core vblank handling code before
@@ -357,7 +355,7 @@
       </para>
 <!--!Fdrivers/char/drm/drm_irq.c drm_irq_install-->
       <para>
-	Once your interrupt handler is registered (it'll use your
+	Once your interrupt handler is registered (it uses your
 	drm_driver.irq_handler as the actual interrupt handling
 	function), you can safely enable interrupts on your device,
 	assuming any other state your interrupt handler uses is also
@@ -371,10 +369,10 @@
 	using the pci_map_rom() call, a convenience function that
 	takes care of mapping the actual ROM, whether it has been
 	shadowed into memory (typically at address 0xc0000) or exists
-	on the PCI device in the ROM BAR.  Note that once you've
-	mapped the ROM and extracted any necessary information, be
-	sure to unmap it; on many devices the ROM address decoder is
-	shared with other BARs, so leaving it mapped can cause
+	on the PCI device in the ROM BAR.  Note that after the ROM
+	has been mapped and any necessary information has been extracted,
+	it should be unmapped; on many devices, the ROM address decoder is
+	shared with other BARs, so leaving it mapped could cause
 	undesired behavior like hangs or memory corruption.
 <!--!Fdrivers/pci/rom.c pci_map_rom-->
       </para>
@@ -389,9 +387,9 @@
 	should support a memory manager.
       </para>
       <para>
-	If your driver supports memory management (it should!), you'll
+	If your driver supports memory management (it should!), you
 	need to set that up at load time as well.  How you initialize
-	it depends on which memory manager you're using, TTM or GEM.
+	it depends on which memory manager you're using: TTM or GEM.
       </para>
       <sect3>
 	<title>TTM initialization</title>
@@ -401,7 +399,7 @@
 	  and devices with dedicated video RAM (VRAM), i.e. most discrete
 	  graphics devices.  If your device has dedicated RAM, supporting
 	  TTM is desirable.  TTM also integrates tightly with your
-	  driver specific buffer execution function.  See the radeon
+	  driver-specific buffer execution function.  See the radeon
 	  driver for examples.
 	</para>
 	<para>
@@ -429,21 +427,21 @@
 	  created by the memory manager at runtime.  Your global TTM should
 	  have a type of TTM_GLOBAL_TTM_MEM.  The size field for the global
 	  object should be sizeof(struct ttm_mem_global), and the init and
-	  release hooks should point at your driver specific init and
-	  release routines, which will probably eventually call
-	  ttm_mem_global_init and ttm_mem_global_release respectively.
+	  release hooks should point at your driver-specific init and
+	  release routines, which probably eventually call
+	  ttm_mem_global_init and ttm_mem_global_release, respectively.
 	</para>
 	<para>
 	  Once your global TTM accounting structure is set up and initialized
-	  (done by calling ttm_global_item_ref on the global object you
-	  just created), you'll need to create a buffer object TTM to
+	  by calling ttm_global_item_ref() on it,
+	  you need to create a buffer object TTM to
 	  provide a pool for buffer object allocation by clients and the
 	  kernel itself.  The type of this object should be TTM_GLOBAL_TTM_BO,
 	  and its size should be sizeof(struct ttm_bo_global).  Again,
-	  driver specific init and release functions can be provided,
-	  likely eventually calling ttm_bo_global_init and
-	  ttm_bo_global_release, respectively.  Also like the previous
-	  object, ttm_global_item_ref is used to create an initial reference
+	  driver-specific init and release functions may be provided,
+	  likely eventually calling ttm_bo_global_init() and
+	  ttm_bo_global_release(), respectively.  Also, like the previous
+	  object, ttm_global_item_ref() is used to create an initial reference
 	  count for the TTM, which will call your initialization function.
 	</para>
       </sect3>
@@ -453,27 +451,26 @@
 	  GEM is an alternative to TTM, designed specifically for UMA
 	  devices.  It has simpler initialization and execution requirements
 	  than TTM, but has no VRAM management capability.  Core GEM
-	  initialization is comprised of a basic drm_mm_init call to create
+	  is initialized by calling drm_mm_init() to create
 	  a GTT DRM MM object, which provides an address space pool for
-	  object allocation.  In a KMS configuration, the driver will
-	  need to allocate and initialize a command ring buffer following
-	  basic GEM initialization.  Most UMA devices have a so-called
+	  object allocation.  In a KMS configuration, the driver
+	  needs to allocate and initialize a command ring buffer following
+	  core GEM initialization.  A UMA device usually has what is called a
 	  "stolen" memory region, which provides space for the initial
 	  framebuffer and large, contiguous memory regions required by the
-	  device.  This space is not typically managed by GEM, and must
+	  device.  This space is not typically managed by GEM, and it must
 	  be initialized separately into its own DRM MM object.
 	</para>
 	<para>
-	  Initialization will be driver specific, and will depend on
-	  the architecture of the device.  In the case of Intel
+	  Initialization is driver-specific. In the case of Intel
 	  integrated graphics chips like 965GM, GEM initialization can
 	  be done by calling the internal GEM init function,
 	  i915_gem_do_init().  Since the 965GM is a UMA device
-	  (i.e. it doesn't have dedicated VRAM), GEM will manage
+	  (i.e. it doesn't have dedicated VRAM), GEM manages
 	  making regular RAM available for GPU operations.  Memory set
 	  aside by the BIOS (called "stolen" memory by the i915
-	  driver) will be managed by the DRM memrange allocator; the
-	  rest of the aperture will be managed by GEM.
+	  driver) is managed by the DRM memrange allocator; the
+	  rest of the aperture is managed by GEM.
 	  <programlisting>
 	    /* Basic memrange allocator for stolen space (aka vram) */
 	    drm_memrange_init(&amp;dev_priv->vram, 0, prealloc_size);
@@ -483,7 +480,7 @@
 <!--!Edrivers/char/drm/drm_memrange.c-->
 	</para>
 	<para>
-	  Once the memory manager has been set up, we can allocate the
+	  Once the memory manager has been set up, we may allocate the
 	  command buffer.  In the i915 case, this is also done with a
 	  GEM function, i915_gem_init_ringbuffer().
 	</para>
@@ -493,16 +490,25 @@
     <sect2>
       <title>Output configuration</title>
       <para>
-	The final initialization task is output configuration.  This involves
-	finding and initializing the CRTCs, encoders and connectors
-	for your device, creating an initial configuration and
-	registering a framebuffer console driver.
+	The final initialization task is output configuration.  This involves:
+	<itemizedlist>
+	  <listitem>
+	    Finding and initializing the CRTCs, encoders, and connectors
+	    for the device.
+	  </listitem>
+	  <listitem>
+	    Creating an initial configuration.
+	  </listitem>
+	  <listitem>
+	    Registering a framebuffer console driver.
+	  </listitem>
+	</itemizedlist>
       </para>
       <sect3>
 	<title>Output discovery and initialization</title>
 	<para>
-	  Several core functions exist to create CRTCs, encoders and
-	  connectors, namely drm_crtc_init(), drm_connector_init() and
+	  Several core functions exist to create CRTCs, encoders, and
+	  connectors, namely: drm_crtc_init(), drm_connector_init(), and
 	  drm_encoder_init(), along with several "helper" functions to
 	  perform common tasks.
 	</para>
@@ -555,10 +561,10 @@
 	</programlisting>
 	<para>
 	  In the example above (again, taken from the i915 driver), a
-	  CRT connector and encoder combination is created.  A device
-	  specific i2c bus is also created, for fetching EDID data and
+	  CRT connector and encoder combination is created.  A device-specific
+	  i2c bus is also created for fetching EDID data and
 	  performing monitor detection.  Once the process is complete,
-	  the new connector is registered with sysfs, to make its
+	  the new connector is registered with sysfs to make its
 	  properties available to applications.
 	</para>
 	<sect4>
@@ -567,12 +573,12 @@
 	    Since many PC-class graphics devices have similar display output
 	    designs, the DRM provides a set of helper functions to make
 	    output management easier.  The core helper routines handle
-	    encoder re-routing and disabling of unused functions following
-	    mode set.  Using the helpers is optional, but recommended for
+	    encoder re-routing and the disabling of unused functions following
+	    mode setting.  Using the helpers is optional, but recommended for
 	    devices with PC-style architectures (i.e. a set of display planes
 	    for feeding pixels to encoders which are in turn routed to
 	    connectors).  Devices with more complex requirements needing
-	    finer grained management can opt to use the core callbacks
+	    finer grained management may opt to use the core callbacks
 	    directly.
 	  </para>
 	  <para>
@@ -580,17 +586,25 @@
 	  </para>
 	</sect4>
 	<para>
-	  For each encoder, CRTC and connector, several functions must
-	  be provided, depending on the object type.  Encoder objects
-	  need to provide a DPMS (basically on/off) function, mode fixup
-	  (for converting requested modes into native hardware timings),
-	  and prepare, set and commit functions for use by the core DRM
-	  helper functions.  Connector helpers need to provide mode fetch and
-	  validity functions as well as an encoder matching function for
-	  returning an ideal encoder for a given connector.  The core
-	  connector functions include a DPMS callback, (deprecated)
-	  save/restore routines, detection, mode probing, property handling,
-	  and cleanup functions.
+	  Each encoder object needs to provide:
+	  <itemizedlist>
+	    <listitem>
+	      A DPMS (basically on/off) function.
+	    </listitem>
+	    <listitem>
+	      A mode-fixup function (for converting requested modes into
+	      native hardware timings).
+	    </listitem>
+	    <listitem>
+	      Functions (prepare, set, and commit) for use by the core DRM
+	      helper functions.
+	    </listitem>
+	  </itemizedlist>
+	  Connector helpers need to provide functions (mode-fetch, validity,
+	  and encoder-matching) for returning an ideal encoder for a given
+	  connector.  The core connector functions include a DPMS callback,
+	  save/restore routines (deprecated), detection, mode probing,
+	  property handling, and cleanup functions.
 	</para>
 <!--!Edrivers/char/drm/drm_crtc.h-->
 <!--!Edrivers/char/drm/drm_crtc.c-->
@@ -605,23 +619,34 @@
     <title>VBlank event handling</title>
     <para>
       The DRM core exposes two vertical blank related ioctls:
-      DRM_IOCTL_WAIT_VBLANK and DRM_IOCTL_MODESET_CTL.
+      <variablelist>
+        <varlistentry>
+          <term>DRM_IOCTL_WAIT_VBLANK</term>
+          <listitem>
+            <para>
+              This takes a struct drm_wait_vblank structure as its argument,
+              and it is used to block or request a signal when a specified
+              vblank event occurs.
+            </para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term>DRM_IOCTL_MODESET_CTL</term>
+          <listitem>
+            <para>
+              This should be called by application level drivers before and
+              after mode setting, since on many devices the vertical blank
+              counter is reset at that time.  Internally, the DRM snapshots
+              the last vblank count when the ioctl is called with the
+              _DRM_PRE_MODESET command, so that the counter won't go backwards
+              (which is dealt with when _DRM_POST_MODESET is used).
+            </para>
+          </listitem>
+        </varlistentry>
+      </variablelist>
 <!--!Edrivers/char/drm/drm_irq.c-->
     </para>
     <para>
-      DRM_IOCTL_WAIT_VBLANK takes a struct drm_wait_vblank structure
-      as its argument, and is used to block or request a signal when a
-      specified vblank event occurs.
-    </para>
-    <para>
-      DRM_IOCTL_MODESET_CTL should be called by application level
-      drivers before and after mode setting, since on many devices the
-      vertical blank counter will be reset at that time.  Internally,
-      the DRM snapshots the last vblank count when the ioctl is called
-      with the _DRM_PRE_MODESET command so that the counter won't go
-      backwards (which is dealt with when _DRM_POST_MODESET is used).
-    </para>
-    <para>
       To support the functions above, the DRM core provides several
       helper functions for tracking vertical blank counters, and
       requires drivers to provide several callbacks:
@@ -632,24 +657,24 @@
       register.  The enable and disable vblank callbacks should enable
       and disable vertical blank interrupts, respectively.  In the
       absence of DRM clients waiting on vblank events, the core DRM
-      code will use the disable_vblank() function to disable
-      interrupts, which saves power.  They'll be re-enabled again when
+      code uses the disable_vblank() function to disable
+      interrupts, which saves power.  They are re-enabled again when
       a client calls the vblank wait ioctl above.
     </para>
     <para>
-      Devices that don't provide a count register can simply use an
+      A device that doesn't provide a count register may simply use an
       internal atomic counter incremented on every vertical blank
-      interrupt, and can make their enable and disable vblank
-      functions into no-ops.
+      interrupt (and then treat the enable_vblank() and disable_vblank()
+      callbacks as no-ops).
     </para>
   </sect1>
 
   <sect1>
     <title>Memory management</title>
     <para>
-      The memory manager lies at the heart of many DRM operations, and
-      is also required to support advanced client features like OpenGL
-      pbuffers.  The DRM currently contains two memory managers, TTM
+      The memory manager lies at the heart of many DRM operations; it
+      is required to support advanced client features like OpenGL
+      pbuffers.  The DRM currently contains two memory managers: TTM
       and GEM.
     </para>
 
@@ -679,41 +704,46 @@
       <para>
 	GEM-enabled drivers must provide gem_init_object() and
 	gem_free_object() callbacks to support the core memory
-	allocation routines.  They should also provide several driver
-	specific ioctls to support command execution, pinning, buffer
+	allocation routines.  They should also provide several driver-specific
+	ioctls to support command execution, pinning, buffer
 	read &amp; write, mapping, and domain ownership transfers.
       </para>
       <para>
-	On a fundamental level, GEM involves several operations: memory
-	allocation and freeing, command execution, and aperture management
-	at command execution time.  Buffer object allocation is relatively
+	On a fundamental level, GEM involves several operations:
+	<itemizedlist>
+	  <listitem>Memory allocation and freeing</listitem>
+	  <listitem>Command execution</listitem>
+	  <listitem>Aperture management at command execution time</listitem>
+	</itemizedlist>
+	Buffer object allocation is relatively
 	straightforward and largely provided by Linux's shmem layer, which
 	provides memory to back each object.  When mapped into the GTT
 	or used in a command buffer, the backing pages for an object are
 	flushed to memory and marked write combined so as to be coherent
-	with the GPU.  Likewise, when the GPU finishes rendering to an object,
-	if the CPU accesses it, it must be made coherent with the CPU's view
+	with the GPU.  Likewise, if the CPU accesses an object after the GPU
+	has finished rendering to the object, then the object must be made
+	coherent with the CPU's view
 	of memory, usually involving GPU cache flushing of various kinds.
-	This core CPU&lt;-&gt;GPU coherency management is provided by the GEM
-	set domain function, which evaluates an object's current domain and
+	This core CPU&lt;-&gt;GPU coherency management is provided by a
+	device-specific ioctl, which evaluates an object's current domain and
 	performs any necessary flushing or synchronization to put the object
 	into the desired coherency domain (note that the object may be busy,
-	i.e. an active render target; in that case the set domain function
-	will block the client and wait for rendering to complete before
+	i.e. an active render target; in that case, setting the domain
+	blocks the client and waits for rendering to complete before
 	performing any necessary flushing operations).
       </para>
       <para>
 	Perhaps the most important GEM function is providing a command
 	execution interface to clients.  Client programs construct command
-	buffers containing references to previously allocated memory objects
-	and submit them to GEM.  At that point, GEM will take care to bind
+	buffers containing references to previously allocated memory objects,
+	and then submit them to GEM.  At that point, GEM takes care to bind
 	all the objects into the GTT, execute the buffer, and provide
 	necessary synchronization between clients accessing the same buffers.
 	This often involves evicting some objects from the GTT and re-binding
 	others (a fairly expensive operation), and providing relocation
 	support which hides fixed GTT offsets from clients.  Clients must
 	take care not to submit command buffers that reference more objects
-	than can fit in the GTT or GEM will reject them and no rendering
+	than can fit in the GTT; otherwise, GEM will reject them and no rendering
 	will occur.  Similarly, if several objects in the buffer require
 	fence registers to be allocated for correct rendering (e.g. 2D blits
 	on pre-965 chips), care must be taken not to require more fence
@@ -729,7 +759,7 @@
     <title>Output management</title>
     <para>
       At the core of the DRM output management code is a set of
-      structures representing CRTCs, encoders and connectors.
+      structures representing CRTCs, encoders, and connectors.
     </para>
     <para>
       A CRTC is an abstraction representing a part of the chip that
@@ -765,21 +795,19 @@
   <sect1>
     <title>Framebuffer management</title>
     <para>
-      In order to set a mode on a given CRTC, encoder and connector
-      configuration, clients need to provide a framebuffer object which
-      will provide a source of pixels for the CRTC to deliver to the encoder(s)
-      and ultimately the connector(s) in the configuration.  A framebuffer
-      is fundamentally a driver specific memory object, made into an opaque
-      handle by the DRM addfb function.  Once an fb has been created this
-      way it can be passed to the KMS mode setting routines for use in
-      a configuration.
+      Clients need to provide a framebuffer object which provides a source
+      of pixels for a CRTC to deliver to the encoder(s) and ultimately the
+      connector(s). A framebuffer is fundamentally a driver-specific memory
+      object, made into an opaque handle by the DRM's addfb() function.
+      Once a framebuffer has been created this way, it may be passed to the
+      KMS mode setting routines for use in a completed configuration.
     </para>
   </sect1>
 
   <sect1>
     <title>Command submission &amp; fencing</title>
     <para>
-      This should cover a few device specific command submission
+      This should cover a few device-specific command submission
       implementations.
     </para>
   </sect1>
@@ -789,7 +817,7 @@
     <para>
       The DRM core provides some suspend/resume code, but drivers
       wanting full suspend/resume support should provide save() and
-      restore() functions.  These will be called at suspend,
+      restore() functions.  These are called at suspend,
       hibernate, or resume time, and should perform any state save or
       restore required by your device across suspend or hibernate
       states.
@@ -812,8 +840,8 @@
     <para>
       The DRM core exports several interfaces to applications,
       generally intended to be used through corresponding libdrm
-      wrapper functions.  In addition, drivers export device specific
-      interfaces for use by userspace drivers &amp; device aware
+      wrapper functions.  In addition, drivers export device-specific
+      interfaces for use by userspace drivers &amp; device-aware
       applications through ioctls and sysfs files.
     </para>
     <para>
@@ -822,8 +850,8 @@
       management, memory management, and output management.
     </para>
     <para>
-      Cover generic ioctls and sysfs layout here.  Only need high
-      level info, since man pages will cover the rest.
+      Cover generic ioctls and sysfs layout here.  We only need high-level
+      info, since man pages should cover the rest.
     </para>
   </chapter>
 
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/media/dvb/dvbproperty.xml linux-libre-3.2-gnu/Documentation/DocBook/media/dvb/dvbproperty.xml
--- linux-libre-3.1-gnu/Documentation/DocBook/media/dvb/dvbproperty.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/DocBook/media/dvb/dvbproperty.xml	2012-01-04 18:55:44.000000000 -0500
@@ -352,6 +352,7 @@
 	SYS_CMMB,
 	SYS_DAB,
 	SYS_DVBT2,
+	SYS_TURBO,
 } fe_delivery_system_t;
 </programlisting>
 		</section>
@@ -809,6 +810,8 @@
 			<listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
 			<listitem><para><link linkend="DTV-SYMBOL-RATE"><constant>DTV_SYMBOL_RATE</constant></link></para></listitem>
 			<listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
+			<listitem><para><link linkend="DTV-VOLTAGE"><constant>DTV_VOLTAGE</constant></link></para></listitem>
+			<listitem><para><link linkend="DTV-TONE"><constant>DTV_TONE</constant></link></para></listitem>
 		</itemizedlist>
 		<para>Future implementations might add those two missing parameters:</para>
 		<itemizedlist mark='opencircle'>
@@ -818,25 +821,18 @@
 	</section>
 	<section id="dvbs2-params">
 		<title>DVB-S2 delivery system</title>
-		<para>The following parameters are valid for DVB-S2:</para>
+		<para>In addition to all parameters valid for DVB-S, DVB-S2 supports the following parameters:</para>
 		<itemizedlist mark='opencircle'>
-			<listitem><para><link linkend="DTV-API-VERSION"><constant>DTV_API_VERSION</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-DELIVERY-SYSTEM"><constant>DTV_DELIVERY_SYSTEM</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-SYMBOL-RATE"><constant>DTV_SYMBOL_RATE</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-VOLTAGE"><constant>DTV_VOLTAGE</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-TONE"><constant>DTV_TONE</constant></link></para></listitem>
+			<listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
 			<listitem><para><link linkend="DTV-PILOT"><constant>DTV_PILOT</constant></link></para></listitem>
 			<listitem><para><link linkend="DTV-ROLLOFF"><constant>DTV_ROLLOFF</constant></link></para></listitem>
 		</itemizedlist>
-		<para>Future implementations might add those two missing parameters:</para>
+	</section>
+	<section id="turbo-params">
+		<title>Turbo code delivery system</title>
+		<para>In addition to all parameters valid for DVB-S, turbo code supports the following parameters:</para>
 		<itemizedlist mark='opencircle'>
-			<listitem><para><link linkend="DTV-DISEQC-MASTER"><constant>DTV_DISEQC_MASTER</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-DISEQC-SLAVE-REPLY"><constant>DTV_DISEQC_SLAVE_REPLY</constant></link></para></listitem>
+			<listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="isdbs-params">
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/media/dvb/intro.xml linux-libre-3.2-gnu/Documentation/DocBook/media/dvb/intro.xml
--- linux-libre-3.1-gnu/Documentation/DocBook/media/dvb/intro.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/DocBook/media/dvb/intro.xml	2012-01-04 18:55:44.000000000 -0500
@@ -205,7 +205,7 @@
 additional include file <emphasis
 role="tt">linux/dvb/version.h</emphasis> exists, which defines the
 constant <emphasis role="tt">DVB_API_VERSION</emphasis>. This document
-describes <emphasis role="tt">DVB_API_VERSION&#x00A0;3</emphasis>.
+describes <emphasis role="tt">DVB_API_VERSION 5.4</emphasis>.
 </para>
 
 </section>
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/compat.xml linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/compat.xml
--- linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/compat.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/compat.xml	2012-01-04 18:55:44.000000000 -0500
@@ -2370,6 +2370,14 @@
         </listitem>
       </orderedlist>
     </section>
+    <section>
+      <title>V4L2 in Linux 3.2</title>
+      <orderedlist>
+        <listitem>
+	  <para>V4L2_CTRL_FLAG_VOLATILE was added to signal volatile controls to userspace.</para>
+        </listitem>
+      </orderedlist>
+    </section>
 
     <section id="other">
       <title>Relation of V4L2 to other Linux multimedia APIs</title>
@@ -2478,6 +2486,9 @@
         <listitem>
 	  <para>Flash API. <xref linkend="flash-controls" /></para>
         </listitem>
+        <listitem>
+	  <para>&VIDIOC-CREATE-BUFS; and &VIDIOC-PREPARE-BUF; ioctls.</para>
+        </listitem>
       </itemizedlist>
     </section>
 
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/controls.xml linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/controls.xml
--- linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/controls.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/controls.xml	2012-01-04 18:55:44.000000000 -0500
@@ -232,8 +232,9 @@
 	    <entry>Enables a power line frequency filter to avoid
 flicker. Possible values for <constant>enum v4l2_power_line_frequency</constant> are:
 <constant>V4L2_CID_POWER_LINE_FREQUENCY_DISABLED</constant> (0),
-<constant>V4L2_CID_POWER_LINE_FREQUENCY_50HZ</constant> (1) and
-<constant>V4L2_CID_POWER_LINE_FREQUENCY_60HZ</constant> (2).</entry>
+<constant>V4L2_CID_POWER_LINE_FREQUENCY_50HZ</constant> (1),
+<constant>V4L2_CID_POWER_LINE_FREQUENCY_60HZ</constant> (2) and
+<constant>V4L2_CID_POWER_LINE_FREQUENCY_AUTO</constant> (3).</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_CID_HUE_AUTO</constant></entry>
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/dev-subdev.xml linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/dev-subdev.xml
--- linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/dev-subdev.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/dev-subdev.xml	2012-01-04 18:55:44.000000000 -0500
@@ -266,7 +266,7 @@
 
       <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
+      <constant>V4L2_SUBDEV_FORMAT_ACTIVE</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
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/io.xml linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/io.xml
--- linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/io.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/io.xml	2012-01-04 18:55:44.000000000 -0500
@@ -927,6 +927,33 @@
 Applications set or clear this flag before calling the
 <constant>VIDIOC_QBUF</constant> ioctl.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_FLAG_PREPARED</constant></entry>
+	    <entry>0x0400</entry>
+	    <entry>The buffer has been prepared for I/O and can be queued by the
+application. Drivers set or clear this flag when the
+<link linkend="vidioc-querybuf">VIDIOC_QUERYBUF</link>, <link
+	  linkend="vidioc-qbuf">VIDIOC_PREPARE_BUF</link>, <link
+	  linkend="vidioc-qbuf">VIDIOC_QBUF</link> or <link
+	  linkend="vidioc-qbuf">VIDIOC_DQBUF</link> ioctl is called.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant></entry>
+	    <entry>0x0400</entry>
+	    <entry>Caches do not have to be invalidated for this buffer.
+Typically applications shall use this flag if the data captured in the buffer
+is not going to be touched by the CPU, instead the buffer will, probably, be
+passed on to a DMA-capable hardware unit for further processing or output.
+</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant></entry>
+	    <entry>0x0800</entry>
+	    <entry>Caches do not have to be cleaned for this buffer.
+Typically applications shall use this flag for output buffers if the data
+in this buffer has not been created by the CPU but by some DMA-capable unit,
+in which case caches have not been used.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/v4l2.xml linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/v4l2.xml
--- linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/v4l2.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/v4l2.xml	2012-01-04 18:55:44.000000000 -0500
@@ -128,6 +128,13 @@
 applications. -->
 
       <revision>
+	<revnumber>3.2</revnumber>
+	<date>2011-08-26</date>
+	<authorinitials>hv</authorinitials>
+	<revremark>Added V4L2_CTRL_FLAG_VOLATILE.</revremark>
+      </revision>
+
+      <revision>
 	<revnumber>3.1</revnumber>
 	<date>2011-06-27</date>
 	<authorinitials>mcc, po, hv</authorinitials>
@@ -410,7 +417,7 @@
 </partinfo>
 
 <title>Video for Linux Two API Specification</title>
- <subtitle>Revision 3.1</subtitle>
+ <subtitle>Revision 3.2</subtitle>
 
   <chapter id="common">
     &sub-common;
@@ -462,6 +469,7 @@
     &sub-close;
     &sub-ioctl;
     <!-- All ioctls go here. -->
+    &sub-create-bufs;
     &sub-cropcap;
     &sub-dbg-g-chip-ident;
     &sub-dbg-g-register;
@@ -504,6 +512,7 @@
     &sub-queryctrl;
     &sub-query-dv-preset;
     &sub-querystd;
+    &sub-prepare-buf;
     &sub-reqbufs;
     &sub-s-hw-freq-seek;
     &sub-streamon;
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
--- linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,139 @@
+<refentry id="vidioc-create-bufs">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_CREATE_BUFS</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_CREATE_BUFS</refname>
+    <refpurpose>Create buffers for Memory Mapped or User Pointer I/O</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_create_buffers *<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_CREATE_BUFS</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>This ioctl is used to create buffers for <link linkend="mmap">memory
+mapped</link> or <link linkend="userp">user pointer</link>
+I/O. It can be used as an alternative or in addition to the
+<constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter control over buffers
+is required. This ioctl can be called multiple times to create buffers of
+different sizes.</para>
+
+    <para>To allocate device buffers applications initialize relevant fields of
+the <structname>v4l2_create_buffers</structname> structure. They set the
+<structfield>type</structfield> field in the
+<structname>v4l2_format</structname> structure, embedded in this
+structure, to the respective stream or buffer type.
+<structfield>count</structfield> must be set to the number of required buffers.
+<structfield>memory</structfield> specifies the required I/O method. The
+<structfield>format</structfield> field shall typically be filled in using
+either the <constant>VIDIOC_TRY_FMT</constant> or
+<constant>VIDIOC_G_FMT</constant> ioctl(). Additionally, applications can adjust
+<structfield>sizeimage</structfield> fields to fit their specific needs. The
+<structfield>reserved</structfield> array must be zeroed.</para>
+
+    <para>When the ioctl is called with a pointer to this structure the driver
+will attempt to allocate up to the requested number of buffers and store the
+actual number allocated and the starting index in the
+<structfield>count</structfield> and the <structfield>index</structfield> fields
+respectively. On return <structfield>count</structfield> can be smaller than
+the number requested. The driver may also increase buffer sizes if required,
+however, it will not update <structfield>sizeimage</structfield> field values.
+The user has to use <constant>VIDIOC_QUERYBUF</constant> to retrieve that
+information.</para>
+
+    <table pgwide="1" frame="none" id="v4l2-create-buffers">
+      <title>struct <structname>v4l2_create_buffers</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>index</structfield></entry>
+	    <entry>The starting buffer index, returned by the driver.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>count</structfield></entry>
+	    <entry>The number of buffers requested or granted.</entry>
+	  </row>
+	  <row>
+	    <entry>&v4l2-memory;</entry>
+	    <entry><structfield>memory</structfield></entry>
+	    <entry>Applications set this field to
+<constant>V4L2_MEMORY_MMAP</constant> or
+<constant>V4L2_MEMORY_USERPTR</constant>.</entry>
+	  </row>
+	  <row>
+	    <entry>&v4l2-format;</entry>
+	    <entry><structfield>format</structfield></entry>
+	    <entry>Filled in by the application, preserved by the driver.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[8]</entry>
+	    <entry>A place holder for future extensions.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>ENOMEM</errorcode></term>
+	<listitem>
+	  <para>No memory to allocate buffers for <link linkend="mmap">memory
+mapped</link> I/O.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The buffer type (<structfield>type</structfield> field) or the
+requested I/O method (<structfield>memory</structfield>) is not
+supported.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/vidioc-dqevent.xml linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/vidioc-dqevent.xml
--- linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/vidioc-dqevent.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/vidioc-dqevent.xml	2012-01-04 18:55:44.000000000 -0500
@@ -88,6 +88,12 @@
 	  </row>
 	  <row>
 	    <entry></entry>
+	    <entry>&v4l2-event-frame-sync;</entry>
+            <entry><structfield>frame</structfield></entry>
+	    <entry>Event data for event V4L2_EVENT_FRAME_SYNC.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
 	    <entry>__u8</entry>
             <entry><structfield>data</structfield>[64]</entry>
 	    <entry>Event data. Defined by the event type. The union
@@ -135,6 +141,129 @@
       </tgroup>
     </table>
 
+    <table frame="none" pgwide="1" id="v4l2-event-vsync">
+      <title>struct <structname>v4l2_event_vsync</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u8</entry>
+	    <entry><structfield>field</structfield></entry>
+	    <entry>The upcoming field. See &v4l2-field;.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table frame="none" pgwide="1" id="v4l2-event-ctrl">
+      <title>struct <structname>v4l2_event_ctrl</structname></title>
+      <tgroup cols="4">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>changes</structfield></entry>
+	    <entry></entry>
+	    <entry>A bitmask that tells what has changed. See <xref linkend="changes-flags" />.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>type</structfield></entry>
+	    <entry></entry>
+	    <entry>The type of the control. See &v4l2-ctrl-type;.</entry>
+	  </row>
+	  <row>
+	    <entry>union (anonymous)</entry>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry></entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>__s32</entry>
+	    <entry><structfield>value</structfield></entry>
+	    <entry>The 32-bit value of the control for 32-bit control types.
+		This is 0 for string controls since the value of a string
+		cannot be passed using &VIDIOC-DQEVENT;.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>__s64</entry>
+	    <entry><structfield>value64</structfield></entry>
+	    <entry>The 64-bit value of the control for 64-bit control types.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>flags</structfield></entry>
+	    <entry></entry>
+	    <entry>The control flags. See <xref linkend="control-flags" />.</entry>
+	  </row>
+	  <row>
+	    <entry>__s32</entry>
+	    <entry><structfield>minimum</structfield></entry>
+	    <entry></entry>
+	    <entry>The minimum value of the control. See &v4l2-queryctrl;.</entry>
+	  </row>
+	  <row>
+	    <entry>__s32</entry>
+	    <entry><structfield>maximum</structfield></entry>
+	    <entry></entry>
+	    <entry>The maximum value of the control. See &v4l2-queryctrl;.</entry>
+	  </row>
+	  <row>
+	    <entry>__s32</entry>
+	    <entry><structfield>step</structfield></entry>
+	    <entry></entry>
+	    <entry>The step value of the control. See &v4l2-queryctrl;.</entry>
+	  </row>
+	  <row>
+	    <entry>__s32</entry>
+	    <entry><structfield>default_value</structfield></entry>
+	    <entry></entry>
+	    <entry>The default value value of the control. See &v4l2-queryctrl;.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table frame="none" pgwide="1" id="v4l2-event-frame-sync">
+      <title>struct <structname>v4l2_event_frame_sync</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>frame_sequence</structfield></entry>
+	    <entry>
+	      The sequence number of the frame being received.
+	    </entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table pgwide="1" frame="none" id="changes-flags">
+      <title>Changes</title>
+      <tgroup cols="3">
+	&cs-def;
+	<tbody valign="top">
+	  <row>
+	    <entry><constant>V4L2_EVENT_CTRL_CH_VALUE</constant></entry>
+	    <entry>0x0001</entry>
+	    <entry>This control event was triggered because the value of the control
+		changed. Special case: if a button control is pressed, then this
+		event is sent as well, even though there is not explicit value
+		associated with a button control.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_EVENT_CTRL_CH_FLAGS</constant></entry>
+	    <entry>0x0002</entry>
+	    <entry>This control event was triggered because the control flags
+		changed.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
   </refsect1>
   <refsect1>
     &return-value;
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
--- linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,88 @@
+<refentry id="vidioc-prepare-buf">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_PREPARE_BUF</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_PREPARE_BUF</refname>
+    <refpurpose>Prepare a buffer for I/O</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_buffer *<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_PREPARE_BUF</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>Applications can optionally call the
+<constant>VIDIOC_PREPARE_BUF</constant> ioctl to pass ownership of the buffer
+to the driver before actually enqueuing it, using the
+<constant>VIDIOC_QBUF</constant> ioctl, and to prepare it for future I/O.
+Such preparations may include cache invalidation or cleaning. Performing them
+in advance saves time during the actual I/O. In case such cache operations are
+not required, the application can use one of
+<constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant> and
+<constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant> flags to skip the respective
+step.</para>
+
+    <para>The <structname>v4l2_buffer</structname> structure is
+specified in <xref linkend="buffer" />.</para>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EBUSY</errorcode></term>
+	<listitem>
+	  <para>File I/O is in progress.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The buffer <structfield>type</structfield> is not
+supported, or the <structfield>index</structfield> is out of bounds,
+or no buffers have been allocated yet, or the
+<structfield>userptr</structfield> or
+<structfield>length</structfield> are invalid.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
--- linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml	2012-01-04 18:55:44.000000000 -0500
@@ -406,6 +406,15 @@
 writing a value will cause the device to carry out a given action
 (&eg; motor control) but no meaningful value can be returned.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_CTRL_FLAG_VOLATILE</constant></entry>
+	    <entry>0x0080</entry>
+	    <entry>This control is volatile, which means that the value of the control
+changes continuously. A typical example would be the current gain value if the device
+is in auto-gain mode. In such a case the hardware calculates the gain value based on
+the lighting conditions which can change over time. Note that setting a new value for
+a volatile control will have no effect. The new value will just be ignored.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
--- linux-libre-3.1-gnu/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml	2012-01-04 18:55:44.000000000 -0500
@@ -139,6 +139,22 @@
 	    </entry>
 	  </row>
 	  <row>
+	    <entry><constant>V4L2_EVENT_FRAME_SYNC</constant></entry>
+	    <entry>4</entry>
+	    <entry>
+	      <para>Triggered immediately when the reception of a
+	      frame has begun. This event has a
+	      &v4l2-event-frame-sync; associated with it.</para>
+
+	      <para>If the hardware needs to be stopped in the case of a
+	      buffer underrun it might not be able to generate this event.
+	      In such cases the <structfield>frame_sequence</structfield>
+	      field in &v4l2-event-frame-sync; will not be incremented. This
+	      causes two consecutive frame sequence numbers to have n times
+	      frame interval in between them.</para>
+	    </entry>
+	  </row>
+	  <row>
 	    <entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry>
 	    <entry>0x08000000</entry>
 	    <entry>Base event number for driver-private events.</entry>
@@ -183,113 +199,6 @@
       </tgroup>
     </table>
 
-    <table frame="none" pgwide="1" id="v4l2-event-vsync">
-      <title>struct <structname>v4l2_event_vsync</structname></title>
-      <tgroup cols="3">
-	&cs-str;
-	<tbody valign="top">
-	  <row>
-	    <entry>__u8</entry>
-	    <entry><structfield>field</structfield></entry>
-	    <entry>The upcoming field. See &v4l2-field;.</entry>
-	  </row>
-	</tbody>
-      </tgroup>
-    </table>
-
-    <table frame="none" pgwide="1" id="v4l2-event-ctrl">
-      <title>struct <structname>v4l2_event_ctrl</structname></title>
-      <tgroup cols="4">
-	&cs-str;
-	<tbody valign="top">
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>changes</structfield></entry>
-	    <entry></entry>
-	    <entry>A bitmask that tells what has changed. See <xref linkend="changes-flags" />.</entry>
-	  </row>
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>type</structfield></entry>
-	    <entry></entry>
-	    <entry>The type of the control. See &v4l2-ctrl-type;.</entry>
-	  </row>
-	  <row>
-	    <entry>union (anonymous)</entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	  </row>
-	  <row>
-	    <entry></entry>
-	    <entry>__s32</entry>
-	    <entry><structfield>value</structfield></entry>
-	    <entry>The 32-bit value of the control for 32-bit control types.
-		This is 0 for string controls since the value of a string
-		cannot be passed using &VIDIOC-DQEVENT;.</entry>
-	  </row>
-	  <row>
-	    <entry></entry>
-	    <entry>__s64</entry>
-	    <entry><structfield>value64</structfield></entry>
-	    <entry>The 64-bit value of the control for 64-bit control types.</entry>
-	  </row>
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>flags</structfield></entry>
-	    <entry></entry>
-	    <entry>The control flags. See <xref linkend="control-flags" />.</entry>
-	  </row>
-	  <row>
-	    <entry>__s32</entry>
-	    <entry><structfield>minimum</structfield></entry>
-	    <entry></entry>
-	    <entry>The minimum value of the control. See &v4l2-queryctrl;.</entry>
-	  </row>
-	  <row>
-	    <entry>__s32</entry>
-	    <entry><structfield>maximum</structfield></entry>
-	    <entry></entry>
-	    <entry>The maximum value of the control. See &v4l2-queryctrl;.</entry>
-	  </row>
-	  <row>
-	    <entry>__s32</entry>
-	    <entry><structfield>step</structfield></entry>
-	    <entry></entry>
-	    <entry>The step value of the control. See &v4l2-queryctrl;.</entry>
-	  </row>
-	  <row>
-	    <entry>__s32</entry>
-	    <entry><structfield>default_value</structfield></entry>
-	    <entry></entry>
-	    <entry>The default value value of the control. See &v4l2-queryctrl;.</entry>
-	  </row>
-	</tbody>
-      </tgroup>
-    </table>
-
-    <table pgwide="1" frame="none" id="changes-flags">
-      <title>Changes</title>
-      <tgroup cols="3">
-	&cs-def;
-	<tbody valign="top">
-	  <row>
-	    <entry><constant>V4L2_EVENT_CTRL_CH_VALUE</constant></entry>
-	    <entry>0x0001</entry>
-	    <entry>This control event was triggered because the value of the control
-		changed. Special case: if a button control is pressed, then this
-		event is sent as well, even though there is not explicit value
-		associated with a button control.</entry>
-	  </row>
-	  <row>
-	    <entry><constant>V4L2_EVENT_CTRL_CH_FLAGS</constant></entry>
-	    <entry>0x0002</entry>
-	    <entry>This control event was triggered because the control flags
-		changed.</entry>
-	  </row>
-	</tbody>
-      </tgroup>
-    </table>
   </refsect1>
   <refsect1>
     &return-value;
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/mtdnand.tmpl linux-libre-3.2-gnu/Documentation/DocBook/mtdnand.tmpl
--- linux-libre-3.1-gnu/Documentation/DocBook/mtdnand.tmpl	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/DocBook/mtdnand.tmpl	2012-01-04 18:55:44.000000000 -0500
@@ -572,7 +572,7 @@
 			</para>
 			<para>
 				The simplest way to activate the FLASH based bad block table support 
-				is to set the option NAND_USE_FLASH_BBT in the option field of
+				is to set the option NAND_BBT_USE_FLASH in the bbt_option field of
 				the nand chip structure before calling nand_scan(). For AG-AND
 				chips is this done by default.
 				This activates the default FLASH based bad block table functionality 
@@ -773,20 +773,6 @@
 				done according to the default builtin scheme.
 			</para>
 		</sect2>
-		<sect2 id="User_space_placement_selection">
-			<title>User space placement selection</title>
-		<para>
-			All non ecc functions like mtd->read and mtd->write use an internal 
-			structure, which can be set by an ioctl. This structure is preset 
-			to the autoplacement default.
-	     		<programlisting>
-	ioctl (fd, MEMSETOOBSEL, oobsel);
-	     		</programlisting>
-			oobsel is a pointer to a user supplied structure of type
-			nand_oobconfig. The contents of this structure must match the 
-			criteria of the filesystem, which will be used. See an example in utils/nandwrite.c.
-		</para>
-		</sect2>
 	</sect1>	
 	<sect1 id="Spare_area_autoplacement_default">
 		<title>Spare area autoplacement default schemes</title>
@@ -1158,9 +1144,6 @@
 		These constants are defined in nand.h. They are ored together to describe
 		the functionality.
      		<programlisting>
-/* Use a flash based bad block table. This option is parsed by the
- * default bad block table function (nand_default_bbt). */
-#define NAND_USE_FLASH_BBT	0x00010000
 /* The hw ecc generator provides a syndrome instead a ecc value on read 
  * This can only work if we have the ecc bytes directly behind the 
  * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/uio-howto.tmpl linux-libre-3.2-gnu/Documentation/DocBook/uio-howto.tmpl
--- linux-libre-3.1-gnu/Documentation/DocBook/uio-howto.tmpl	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/DocBook/uio-howto.tmpl	2012-01-04 18:55:44.000000000 -0500
@@ -521,6 +521,11 @@
 
 <itemizedlist>
 <listitem><para>
+<varname>const char *name</varname>: Optional. Set this to help identify
+the memory region, it will show up in the corresponding sysfs node.
+</para></listitem>
+
+<listitem><para>
 <varname>int memtype</varname>: Required if the mapping is used. Set this to
 <varname>UIO_MEM_PHYS</varname> if you you have physical memory on your
 card to be mapped. Use <varname>UIO_MEM_LOGICAL</varname> for logical
@@ -529,7 +534,7 @@
 </para></listitem>
 
 <listitem><para>
-<varname>unsigned long addr</varname>: Required if the mapping is used.
+<varname>phys_addr_t addr</varname>: Required if the mapping is used.
 Fill in the address of your memory block. This address is the one that
 appears in sysfs.
 </para></listitem>
@@ -553,7 +558,7 @@
 </itemizedlist>
 
 <para>
-Please do not touch the <varname>kobj</varname> element of
+Please do not touch the <varname>map</varname> element of
 <varname>struct uio_mem</varname>! It is used by the UIO framework
 to set up sysfs files for this mapping. Simply leave it alone.
 </para>
diff -druN linux-libre-3.1-gnu/Documentation/DocBook/writing-an-alsa-driver.tmpl linux-libre-3.2-gnu/Documentation/DocBook/writing-an-alsa-driver.tmpl
--- linux-libre-3.1-gnu/Documentation/DocBook/writing-an-alsa-driver.tmpl	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/DocBook/writing-an-alsa-driver.tmpl	2012-01-04 18:55:44.000000000 -0500
@@ -4288,7 +4288,7 @@
 <![CDATA[
   struct snd_rawmidi *rmidi;
   snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags,
-                      irq, irq_flags, &rmidi);
+                      irq, &rmidi);
 ]]>
           </programlisting>
         </informalexample>
@@ -4343,6 +4343,13 @@
 	by itself to start processing the output stream in the irq handler.
 	</para>
 
+	<para>
+	If the MPU-401 interface shares its interrupt with the other logical
+	devices on the card, set <constant>MPU401_INFO_IRQ_HOOK</constant>
+	(see <link linkend="midi-interface-interrupt-handler"><citetitle>
+	below</citetitle></link>).
+	</para>
+
       <para>
         Usually, the port address corresponds to the command port and
         port + 1 corresponds to the data port. If not, you may change
@@ -4375,14 +4382,12 @@
       </para>
 
       <para>
-        The 6th argument specifies the irq number for UART. If the irq
-      is already allocated, pass 0 to the 7th argument
-      (<parameter>irq_flags</parameter>). Otherwise, pass the flags
-      for irq allocation 
-      (<constant>SA_XXX</constant> bits) to it, and the irq will be
-      reserved by the mpu401-uart layer. If the card doesn't generate
-      UART interrupts, pass -1 as the irq number. Then a timer
-      interrupt will be invoked for polling. 
+	The 6th argument specifies the ISA irq number that will be
+	allocated.  If no interrupt is to be allocated (because your
+	code is already allocating a shared interrupt, or because the
+	device does not use interrupts), pass -1 instead.
+	For a MPU-401 device without an interrupt, a polling timer
+	will be used instead.
       </para>
     </section>
 
@@ -4390,12 +4395,13 @@
       <title>Interrupt Handler</title>
       <para>
         When the interrupt is allocated in
-      <function>snd_mpu401_uart_new()</function>, the private
-      interrupt handler is used, hence you don't have anything else to do
-      than creating the mpu401 stuff. Otherwise, you have to call
-      <function>snd_mpu401_uart_interrupt()</function> explicitly when
-      a UART interrupt is invoked and checked in your own interrupt
-      handler.  
+      <function>snd_mpu401_uart_new()</function>, an exclusive ISA
+      interrupt handler is automatically used, hence you don't have
+      anything else to do than creating the mpu401 stuff.  Otherwise, you
+      have to set <constant>MPU401_INFO_IRQ_HOOK</constant>, and call
+      <function>snd_mpu401_uart_interrupt()</function> explicitly from your
+      own interrupt handler when it has determined that a UART interrupt
+      has occurred.
       </para>
 
       <para>
diff -druN linux-libre-3.1-gnu/Documentation/driver-model/binding.txt linux-libre-3.2-gnu/Documentation/driver-model/binding.txt
--- linux-libre-3.1-gnu/Documentation/driver-model/binding.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/driver-model/binding.txt	2012-01-04 18:55:44.000000000 -0500
@@ -48,10 +48,6 @@
 and actually register it with the class, which happens with the
 class's register_dev callback.
 
-NOTE: The device class structures and core routines to manipulate them
-are not in the mainline kernel, so the discussion is still a bit
-speculative. 
-
 
 Driver
 ~~~~~~
diff -druN linux-libre-3.1-gnu/Documentation/driver-model/device.txt linux-libre-3.2-gnu/Documentation/driver-model/device.txt
--- linux-libre-3.1-gnu/Documentation/driver-model/device.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/driver-model/device.txt	2012-01-04 18:55:44.000000000 -0500
@@ -45,33 +45,52 @@
 			 const char *buf, size_t count);
 };
 
-Attributes of devices can be exported via drivers using a simple
-procfs-like interface. 
+Attributes of devices can be exported by a device driver through sysfs.
 
 Please see Documentation/filesystems/sysfs.txt for more information
 on how sysfs works.
 
+As explained in Documentation/kobject.txt, device attributes must be be
+created before the KOBJ_ADD uevent is generated. The only way to realize
+that is by defining an attribute group.
+
 Attributes are declared using a macro called DEVICE_ATTR:
 
 #define DEVICE_ATTR(name,mode,show,store)
 
 Example:
 
-DEVICE_ATTR(power,0644,show_power,store_power);
+static DEVICE_ATTR(type, 0444, show_type, NULL);
+static DEVICE_ATTR(power, 0644, show_power, store_power);
 
-This declares a structure of type struct device_attribute named
-'dev_attr_power'. This can then be added and removed to the device's
-directory using:
+This declares two structures of type struct device_attribute with respective
+names 'dev_attr_type' and 'dev_attr_power'. These two attributes can be
+organized as follows into a group:
 
-int device_create_file(struct device *device, struct device_attribute * entry);
-void device_remove_file(struct device * dev, struct device_attribute * attr);
+static struct attribute *dev_attrs[] = {
+	&dev_attr_type.attr,
+	&dev_attr_power.attr,
+	NULL,
+};
 
-Example:
+static struct attribute_group dev_attr_group = {
+	.attrs = dev_attrs,
+};
 
-device_create_file(dev,&dev_attr_power);
-device_remove_file(dev,&dev_attr_power);
+static const struct attribute_group *dev_attr_groups[] = {
+	&dev_attr_group,
+	NULL,
+};
 
-The file name will be 'power' with a mode of 0644 (-rw-r--r--).
+This array of groups can then be associated with a device by setting the
+group pointer in struct device before device_register() is invoked:
+
+      dev->groups = dev_attr_groups;
+      device_register(dev);
+
+The device_register() function will use the 'groups' pointer to create the
+device attributes and the device_unregister() function will use this pointer
+to remove the device attributes.
 
 Word of warning:  While the kernel allows device_create_file() and
 device_remove_file() to be called on a device at any time, userspace has
@@ -84,24 +103,4 @@
 This is important for device driver that need to publish additional
 attributes for a device at driver probe time.  If the device driver simply
 calls device_create_file() on the device structure passed to it, then
-userspace will never be notified of the new attributes.  Instead, it should
-probably use class_create() and class->dev_attrs to set up a list of
-desired attributes in the modules_init function, and then in the .probe()
-hook, and then use device_create() to create a new device as a child
-of the probed device.  The new device will generate a new uevent and
-properly advertise the new attributes to userspace.
-
-For example, if a driver wanted to add the following attributes:
-struct device_attribute mydriver_attribs[] = {
-	__ATTR(port_count, 0444, port_count_show),
-	__ATTR(serial_number, 0444, serial_number_show),
-	NULL
-};
-
-Then in the module init function is would do:
-	mydriver_class = class_create(THIS_MODULE, "my_attrs");
-	mydriver_class.dev_attr = mydriver_attribs;
-
-And assuming 'dev' is the struct device passed into the probe hook, the driver
-probe function would do something like:
-	device_create(&mydriver_class, dev, chrdev, &private_data, "my_name");
+userspace will never be notified of the new attributes.
diff -druN linux-libre-3.1-gnu/Documentation/fault-injection/fault-injection.txt linux-libre-3.2-gnu/Documentation/fault-injection/fault-injection.txt
--- linux-libre-3.1-gnu/Documentation/fault-injection/fault-injection.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/fault-injection/fault-injection.txt	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,11 @@
   /sys/block/<device>/make-it-fail or
   /sys/block/<device>/<partition>/make-it-fail. (generic_make_request())
 
+o fail_mmc_request
+
+  injects MMC data errors on devices permitted by setting
+  debugfs entries under /sys/kernel/debug/mmc0/fail_mmc_request
+
 Configure fault-injection capabilities behavior
 -----------------------------------------------
 
@@ -115,7 +120,8 @@
 
 	failslab=
 	fail_page_alloc=
-	fail_make_request=<interval>,<probability>,<space>,<times>
+	fail_make_request=
+	mmc_core.fail_request=<interval>,<probability>,<space>,<times>
 
 How to add new fault injection capability
 -----------------------------------------
diff -druN linux-libre-3.1-gnu/Documentation/fb/udlfb.txt linux-libre-3.2-gnu/Documentation/fb/udlfb.txt
--- linux-libre-3.1-gnu/Documentation/fb/udlfb.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/fb/udlfb.txt	2012-01-04 18:55:44.000000000 -0500
@@ -87,23 +87,38 @@
 options, however.
 
 From the command line, pass options to modprobe
-modprobe udlfb defio=1 console=1
+modprobe udlfb fb_defio=0 console=1 shadow=1
 
-Or for permanent option, create file like /etc/modprobe.d/options with text
-options udlfb defio=1 console=1
+Or modify options on the fly at /sys/module/udlfb/parameters directory via
+sudo nano fb_defio
+change the parameter in place, and save the file.
 
-Accepted options:
+Unplug/replug USB device to apply with new settings
+
+Or for permanent option, create file like /etc/modprobe.d/udlfb.conf with text
+options udlfb fb_defio=0 console=1 shadow=1
+
+Accepted boolean options:
 
 fb_defio	Make use of the fb_defio (CONFIG_FB_DEFERRED_IO) kernel
 		module to track changed areas of the framebuffer by page faults.
-        	Standard fbdev applications that use mmap but that do not
-		report damage, may be able to work with this enabled.
-		Disabled by default because of overhead and other issues.
+		Standard fbdev applications that use mmap but that do not
+		report damage, should be able to work with this enabled.
+		Disable when running with X server that supports reporting
+		changed regions via ioctl, as this method is simpler,
+		more stable, and higher performance.
+		default: fb_defio=1
 
-console		Allow fbcon to attach to udlfb provided framebuffers. This
-		is disabled by default because fbcon will aggressively consume
-		the first framebuffer it finds, which isn't usually what the
-		user wants in the case of USB displays.
+console	Allow fbcon to attach to udlfb provided framebuffers.
+		Can be disabled if fbcon and other clients
+		(e.g. X with --shared-vt) are in conflict.
+		default: console=1
+
+shadow		Allocate a 2nd framebuffer to shadow what's currently across
+		the USB bus in device memory. If any pixels are unchanged,
+		do not transmit. Spends host memory to save USB transfers.
+		Enabled by default. Only disable on very low memory systems.
+		default: shadow=1
 
 Sysfs Attributes
 ================
diff -druN linux-libre-3.1-gnu/Documentation/feature-removal-schedule.txt linux-libre-3.2-gnu/Documentation/feature-removal-schedule.txt
--- linux-libre-3.1-gnu/Documentation/feature-removal-schedule.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/feature-removal-schedule.txt	2012-01-04 18:55:44.000000000 -0500
@@ -133,41 +133,6 @@
 
 ---------------------------
 
-What:	sys_sysctl
-When:	September 2010
-Option: CONFIG_SYSCTL_SYSCALL
-Why:	The same information is available in a more convenient from
-	/proc/sys, and none of the sysctl variables appear to be
-	important performance wise.
-
-	Binary sysctls are a long standing source of subtle kernel
-	bugs and security issues.
-
-	When I looked several months ago all I could find after
-	searching several distributions were 5 user space programs and
-	glibc (which falls back to /proc/sys) using this syscall.
-
-	The man page for sysctl(2) documents it as unusable for user
-	space programs.
-
-	sysctl(2) is not generally ABI compatible to a 32bit user
-	space application on a 64bit and a 32bit kernel.
-
-	For the last several months the policy has been no new binary
-	sysctls and no one has put forward an argument to use them.
-
-	Binary sysctls issues seem to keep happening appearing so
-	properly deprecating them (with a warning to user space) and a
-	2 year grace warning period will mean eventually we can kill
-	them and end the pain.
-
-	In the mean time individual binary sysctls can be dealt with
-	in a piecewise fashion.
-
-Who:	Eric Biederman <ebiederm@xmission.com>
-
----------------------------
-
 What:	/proc/<pid>/oom_adj
 When:	August 2012
 Why:	/proc/<pid>/oom_adj allows userspace to influence the oom killer's
@@ -495,29 +460,6 @@
 
 ----------------------------
 
-What:	Support for UVCIOC_CTRL_ADD in the uvcvideo driver
-When:	3.2
-Why:	The information passed to the driver by this ioctl is now queried
-	dynamically from the device.
-Who:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-
-----------------------------
-
-What:	Support for UVCIOC_CTRL_MAP_OLD in the uvcvideo driver
-When:	3.2
-Why:	Used only by applications compiled against older driver versions.
-	Superseded by UVCIOC_CTRL_MAP which supports V4L2 menu controls.
-Who:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-
-----------------------------
-
-What:	Support for UVCIOC_CTRL_GET and UVCIOC_CTRL_SET in the uvcvideo driver
-When:	3.2
-Why:	Superseded by the UVCIOC_CTRL_QUERY ioctl.
-Who:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-
-----------------------------
-
 What:	Support for driver specific ioctls in the pwc driver (everything
 	defined in media/pwc-ioctl.h)
 When:	3.3
@@ -594,9 +536,18 @@
 Who:    Lee, Chun-Yi <jlee@novell.com>
 
 ----------------------------
+
 What:	The XFS nodelaylog mount option
 When:	3.3
 Why:	The delaylog mode that has been the default since 2.6.39 has proven
 	stable, and the old code is in the way of additional improvements in
 	the log code.
 Who:	Christoph Hellwig <hch@lst.de>
+
+----------------------------
+
+What:	iwlagn alias support
+When:	3.5
+Why:	The iwlagn module has been renamed iwlwifi.  The alias will be around
+	for backward compatibility for several cycles and then dropped.
+Who:	Don Fry <donald.h.fry@intel.com>
diff -druN linux-libre-3.1-gnu/Documentation/filesystems/9p.txt linux-libre-3.2-gnu/Documentation/filesystems/9p.txt
--- linux-libre-3.1-gnu/Documentation/filesystems/9p.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/filesystems/9p.txt	2012-01-04 18:55:44.000000000 -0500
@@ -92,7 +92,7 @@
 
   wfdno=n	the file descriptor for writing with trans=fd
 
-  maxdata=n	the number of bytes to use for 9p packet payload (msize)
+  msize=n	the number of bytes to use for 9p packet payload
 
   port=n	port to connect to on the remote server
 
diff -druN linux-libre-3.1-gnu/Documentation/filesystems/btrfs.txt linux-libre-3.2-gnu/Documentation/filesystems/btrfs.txt
--- linux-libre-3.1-gnu/Documentation/filesystems/btrfs.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/filesystems/btrfs.txt	2012-01-04 18:55:44.000000000 -0500
@@ -63,8 +63,8 @@
 Userspace tools for creating and manipulating Btrfs file systems are
 available from the git repository at the following location:
 
- http://git.kernel.org/?p=linux/kernel/git/mason/btrfs-progs-unstable.git
- git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-progs-unstable.git
+ http://git.kernel.org/?p=linux/kernel/git/mason/btrfs-progs.git
+ git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-progs.git
 
 These include the following tools:
 
diff -druN linux-libre-3.1-gnu/Documentation/filesystems/caching/object.txt linux-libre-3.2-gnu/Documentation/filesystems/caching/object.txt
--- linux-libre-3.1-gnu/Documentation/filesystems/caching/object.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/filesystems/caching/object.txt	2012-01-04 18:55:44.000000000 -0500
@@ -127,9 +127,9 @@
 PROVISION OF CPU TIME
 ---------------------
 
-The work to be done by the various states is given CPU time by the threads of
-the slow work facility (see Documentation/slow-work.txt).  This is used in
-preference to the workqueue facility because:
+The work to be done by the various states was given CPU time by the threads of
+the slow work facility.  This was used in preference to the workqueue facility
+because:
 
  (1) Threads may be completely occupied for very long periods of time by a
      particular work item.  These state actions may be doing sequences of
diff -druN linux-libre-3.1-gnu/Documentation/filesystems/ext3.txt linux-libre-3.2-gnu/Documentation/filesystems/ext3.txt
--- linux-libre-3.1-gnu/Documentation/filesystems/ext3.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/filesystems/ext3.txt	2012-01-04 18:55:44.000000000 -0500
@@ -73,14 +73,6 @@
 			also be used to enable or disable barriers, for
 			consistency with other ext3 mount options.
 
-orlov		(*)	This enables the new Orlov block allocator. It is
-			enabled by default.
-
-oldalloc		This disables the Orlov block allocator and enables
-			the old block allocator.  Orlov should have better
-			performance - we'd like to get some feedback if it's
-			the contrary for you.
-
 user_xattr		Enables Extended User Attributes.  Additionally, you
 			need to have extended attribute support enabled in the
 			kernel configuration (CONFIG_EXT3_FS_XATTR).  See the
diff -druN linux-libre-3.1-gnu/Documentation/filesystems/ext4.txt linux-libre-3.2-gnu/Documentation/filesystems/ext4.txt
--- linux-libre-3.1-gnu/Documentation/filesystems/ext4.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/filesystems/ext4.txt	2012-01-04 18:55:44.000000000 -0500
@@ -160,7 +160,9 @@
                      	lead to any number of problems.
 
 data=journal		All data are committed into the journal prior to being
-			written into the main file system.
+			written into the main file system.  Enabling
+			this mode will disable delayed allocation and
+			O_DIRECT support.
 
 data=ordered	(*)	All data are forced directly out to the main file
 			system prior to its metadata being committed to the
@@ -201,30 +203,19 @@
 			table readahead algorithm will pre-read into
 			the buffer cache.  The default value is 32 blocks.
 
-orlov		(*)	This enables the new Orlov block allocator. It is
-			enabled by default.
-
-oldalloc		This disables the Orlov block allocator and enables
-			the old block allocator.  Orlov should have better
-			performance - we'd like to get some feedback if it's
-			the contrary for you.
-
-user_xattr		Enables Extended User Attributes.  Additionally, you
-			need to have extended attribute support enabled in the
-			kernel configuration (CONFIG_EXT4_FS_XATTR).  See the
-			attr(5) manual page and http://acl.bestbits.at/ to
-			learn more about extended attributes.
-
-nouser_xattr		Disables Extended User Attributes.
-
-acl			Enables POSIX Access Control Lists support.
-			Additionally, you need to have ACL support enabled in
-			the kernel configuration (CONFIG_EXT4_FS_POSIX_ACL).
-			See the acl(5) manual page and http://acl.bestbits.at/
-			for more information.
+nouser_xattr		Disables Extended User Attributes. If you have extended
+			attribute support enabled in the kernel configuration
+			(CONFIG_EXT4_FS_XATTR), extended attribute support
+			is enabled by default on mount. See the attr(5) manual
+			page and http://acl.bestbits.at/ for more information
+			about extended attributes.
 
 noacl			This option disables POSIX Access Control List
-			support.
+			support. If ACL support is enabled in the kernel
+			configuration (CONFIG_EXT4_FS_POSIX_ACL), ACL is
+			enabled by default on mount. See the acl(5) manual
+			page and http://acl.bestbits.at/ for more information
+			about acl.
 
 bsddf		(*)	Make 'df' act like BSD.
 minixdf			Make 'df' act like Minix.
@@ -419,8 +410,8 @@
 In the event of a crash, the journal can be replayed, bringing both data and
 metadata into a consistent state.  This mode is the slowest except when data
 needs to be read from and written to disk at the same time where it
-outperforms all others modes.  Currently ext4 does not have delayed
-allocation support if this data journalling mode is selected.
+outperforms all others modes.  Enabling this mode will disable delayed
+allocation and O_DIRECT support.
 
 /proc entries
 =============
diff -druN linux-libre-3.1-gnu/Documentation/filesystems/hfs.txt linux-libre-3.2-gnu/Documentation/filesystems/hfs.txt
--- linux-libre-3.1-gnu/Documentation/filesystems/hfs.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/filesystems/hfs.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,4 @@
+Note: This filesystem doesn't have a maintainer.
 
 Macintosh HFS Filesystem for Linux
 ==================================
@@ -76,8 +77,6 @@
 Credits
 =======
 
-The HFS drivers was written by Paul H. Hargrovea (hargrove@sccm.Stanford.EDU)
-and is now maintained by Roman Zippel (roman@ardistech.com) at Ardis
-Technologies.
-Roman rewrote large parts of the code and brought in btree routines derived
-from Brad Boyer's hfsplus driver (also maintained by Roman now).
+The HFS drivers was written by Paul H. Hargrovea (hargrove@sccm.Stanford.EDU).
+Roman Zippel (roman@ardistech.com) rewrote large parts of the code and brought
+in btree routines derived from Brad Boyer's hfsplus driver.
diff -druN linux-libre-3.1-gnu/Documentation/filesystems/inotify.txt linux-libre-3.2-gnu/Documentation/filesystems/inotify.txt
--- linux-libre-3.1-gnu/Documentation/filesystems/inotify.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/filesystems/inotify.txt	2012-01-04 18:55:44.000000000 -0500
@@ -194,7 +194,8 @@
 Each watch is associated with an inotify_watch structure.  Watches are chained
 off of each associated inotify_handle and each associated inode.
 
-See fs/inotify.c and fs/inotify_user.c for the locking and lifetime rules.
+See fs/notify/inotify/inotify_fsnotify.c and fs/notify/inotify/inotify_user.c
+for the locking and lifetime rules.
 
 
 (vi) Rationale
diff -druN linux-libre-3.1-gnu/Documentation/filesystems/Locking linux-libre-3.2-gnu/Documentation/filesystems/Locking
--- linux-libre-3.1-gnu/Documentation/filesystems/Locking	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/filesystems/Locking	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 d_compare:	yes		no		no		maybe
 d_delete:	no		yes		no		no
 d_release:	no		no		yes		no
+d_prune:        no              yes             no              no
 d_iput:		no		no		yes		no
 d_dname:	no		no		no		no
 d_automount:	no		no		yes		no
diff -druN linux-libre-3.1-gnu/Documentation/filesystems/locks.txt linux-libre-3.2-gnu/Documentation/filesystems/locks.txt
--- linux-libre-3.1-gnu/Documentation/filesystems/locks.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/filesystems/locks.txt	2012-01-04 18:55:44.000000000 -0500
@@ -53,11 +53,12 @@
 1.3 Mandatory Locking As A Mount Option
 ---------------------------------------
 
-Mandatory locking, as described in 'Documentation/filesystems/mandatory.txt'
-was prior to this release a general configuration option that was valid for
-all mounted filesystems.  This had a number of inherent dangers, not the
-least of which was the ability to freeze an NFS server by asking it to read
-a file for which a mandatory lock existed.
+Mandatory locking, as described in
+'Documentation/filesystems/mandatory-locking.txt' was prior to this release a
+general configuration option that was valid for all mounted filesystems.  This
+had a number of inherent dangers, not the least of which was the ability to
+freeze an NFS server by asking it to read a file for which a mandatory lock
+existed.
 
 From this release of the kernel, mandatory locking can be turned on and off
 on a per-filesystem basis, using the mount options 'mand' and 'nomand'.
diff -druN linux-libre-3.1-gnu/Documentation/filesystems/nfs/idmapper.txt linux-libre-3.2-gnu/Documentation/filesystems/nfs/idmapper.txt
--- linux-libre-3.1-gnu/Documentation/filesystems/nfs/idmapper.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/filesystems/nfs/idmapper.txt	2012-01-04 18:55:44.000000000 -0500
@@ -47,7 +47,7 @@
 this case, /some/other/program will handle all uid lookups and
 /usr/sbin/nfs.idmap will handle gid, user, and group lookups.
 
-See <file:Documentation/security/keys-request-keys.txt> for more information
+See <file:Documentation/security/keys-request-key.txt> for more information
 about the request-key function.
 
 
diff -druN linux-libre-3.1-gnu/Documentation/filesystems/pohmelfs/design_notes.txt linux-libre-3.2-gnu/Documentation/filesystems/pohmelfs/design_notes.txt
--- linux-libre-3.1-gnu/Documentation/filesystems/pohmelfs/design_notes.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/filesystems/pohmelfs/design_notes.txt	2012-01-04 18:55:44.000000000 -0500
@@ -58,8 +58,9 @@
 POHMELFS clients operate with a working set of servers and are capable of balancing read-only
 operations (like lookups or directory listings) between them according to IO priorities.
 Administrators can add or remove servers from the set at run-time via special commands (described
-in Documentation/pohmelfs/info.txt file). Writes are replicated to all servers, which are connected
-with write permission turned on. IO priority and permissions can be changed in run-time.
+in Documentation/filesystems/pohmelfs/info.txt file). Writes are replicated to all servers, which
+are connected with write permission turned on. IO priority and permissions can be changed in
+run-time.
 
 POHMELFS is capable of full data channel encryption and/or strong crypto hashing.
 One can select any kernel supported cipher, encryption mode, hash type and operation mode
diff -druN linux-libre-3.1-gnu/Documentation/filesystems/proc.txt linux-libre-3.2-gnu/Documentation/filesystems/proc.txt
--- linux-libre-3.1-gnu/Documentation/filesystems/proc.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/filesystems/proc.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1263,7 +1263,7 @@
 This chapter  is  heavily  based  on the documentation included in the pre 2.2
 kernels, and became part of it in version 2.2.1 of the Linux kernel.
 
-Please see: Documentation/sysctls/ directory for descriptions of these
+Please see: Documentation/sysctl/ directory for descriptions of these
 entries.
 
 ------------------------------------------------------------------------------
diff -druN linux-libre-3.1-gnu/Documentation/filesystems/sysfs.txt linux-libre-3.2-gnu/Documentation/filesystems/sysfs.txt
--- linux-libre-3.1-gnu/Documentation/filesystems/sysfs.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/filesystems/sysfs.txt	2012-01-04 18:55:44.000000000 -0500
@@ -4,7 +4,7 @@
 Patrick Mochel	<mochel@osdl.org>
 Mike Murphy <mamurph@cs.clemson.edu>
 
-Revised:    15 July 2010
+Revised:    16 August 2011
 Original:   10 January 2003
 
 
@@ -370,3 +370,11 @@
 void driver_remove_file(struct device_driver *, const struct driver_attribute *);
 
 
+Documentation
+~~~~~~~~~~~~~
+
+The sysfs directory structure and the attributes in each directory define an
+ABI between the kernel and user space. As for any ABI, it is important that
+this ABI is stable and properly documented. All new sysfs attributes must be
+documented in Documentation/ABI. See also Documentation/ABI/README for more
+information.
diff -druN linux-libre-3.1-gnu/Documentation/filesystems/vfs.txt linux-libre-3.2-gnu/Documentation/filesystems/vfs.txt
--- linux-libre-3.1-gnu/Documentation/filesystems/vfs.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/filesystems/vfs.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1053,9 +1053,6 @@
 	and the dentry is returned. The caller must use dput()
 	to free the dentry when it finishes using it.
 
-For further information on dentry locking, please refer to the document
-Documentation/filesystems/dentry-locking.txt.
-
 Mount Options
 =============
 
diff -druN linux-libre-3.1-gnu/Documentation/frv/booting.txt linux-libre-3.2-gnu/Documentation/frv/booting.txt
--- linux-libre-3.1-gnu/Documentation/frv/booting.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/frv/booting.txt	2012-01-04 18:55:44.000000000 -0500
@@ -180,9 +180,3 @@
 
       This tells the kernel what program to run initially. By default this is
       /sbin/init, but /sbin/sash or /bin/sh are common alternatives.
-
-  (*) vdc=...
-
-      This option configures the MB93493 companion chip visual display
-      driver. Please see Documentation/frv/mb93493/vdc.txt for more
-      information.
diff -druN linux-libre-3.1-gnu/Documentation/hwmon/ad7314 linux-libre-3.2-gnu/Documentation/hwmon/ad7314
--- linux-libre-3.1-gnu/Documentation/hwmon/ad7314	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/hwmon/ad7314	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+Kernel driver ad7314
+====================
+
+Supported chips:
+   * Analog Devices AD7314
+     Prefix: 'ad7314'
+     Datasheet: Publicly available at Analog Devices website.
+   * Analog Devices ADT7301
+     Prefix: 'adt7301'
+     Datasheet: Publicly available at Analog Devices website.
+   * Analog Devices ADT7302
+     Prefix: 'adt7302'
+     Datasheet: Publicly available at Analog Devices website.
+
+Description
+-----------
+
+Driver supports the above parts.  The ad7314 has a 10 bit
+sensor with 1lsb = 0.25 degrees centigrade. The adt7301 and
+adt7302 have 14 bit sensors with 1lsb = 0.03125 degrees centigrade.
+
+Notes
+-----
+
+Currently power down mode is not supported.
diff -druN linux-libre-3.1-gnu/Documentation/hwmon/adm1275 linux-libre-3.2-gnu/Documentation/hwmon/adm1275
--- linux-libre-3.1-gnu/Documentation/hwmon/adm1275	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/hwmon/adm1275	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,10 @@
     Prefix: 'adm1275'
     Addresses scanned: -
     Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1275.pdf
+  * Analog Devices ADM1276
+    Prefix: 'adm1276'
+    Addresses scanned: -
+    Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1276.pdf
 
 Author: Guenter Roeck <guenter.roeck@ericsson.com>
 
@@ -13,13 +17,13 @@
 Description
 -----------
 
-This driver supports hardware montoring for Analog Devices ADM1275 Hot-Swap
-Controller and Digital Power Monitor.
+This driver supports hardware montoring for Analog Devices ADM1275 and ADM1276
+Hot-Swap Controller and Digital Power Monitor.
 
-The ADM1275 is a hot-swap controller that allows a circuit board to be removed
-from or inserted into a live backplane. It also features current and voltage
-readback via an integrated 12-bit analog-to-digital converter (ADC), accessed
-using a PMBus. interface.
+ADM1275 and ADM1276 are hot-swap controllers that allow a circuit board to be
+removed from or inserted into a live backplane. They also feature current and
+voltage readback via an integrated 12-bit analog-to-digital converter (ADC),
+accessed using a PMBus interface.
 
 The driver is a client driver to the core PMBus driver. Please see
 Documentation/hwmon/pmbus for details on PMBus client drivers.
@@ -48,17 +52,25 @@
 
 in1_label		"vin1" or "vout1" depending on chip variant and
 			configuration.
-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_min_alarm		Voltage low alarm. From VOLTAGE_UV_WARNING status.
-in1_max_alarm		Voltage high alarm. From VOLTAGE_OV_WARNING status.
+in1_input		Measured voltage.
+in1_min			Minumum Voltage.
+in1_max			Maximum voltage.
+in1_min_alarm		Voltage low alarm.
+in1_max_alarm		Voltage high alarm.
 in1_highest		Historical maximum voltage.
 in1_reset_history	Write any value to reset history.
 
 curr1_label		"iout1"
-curr1_input		Measured current. From READ_IOUT register.
-curr1_max		Maximum current. From IOUT_OC_WARN_LIMIT register.
-curr1_max_alarm		Current high alarm. From IOUT_OC_WARN_LIMIT register.
+curr1_input		Measured current.
+curr1_max		Maximum current.
+curr1_max_alarm		Current high alarm.
+curr1_lcrit		Critical minimum current. Depending on the chip
+			configuration, either curr1_lcrit or curr1_crit is
+			supported, but not both.
+curr1_lcrit_alarm	Critical current low alarm.
+curr1_crit		Critical maximum current. Depending on the chip
+			configuration, either curr1_lcrit or curr1_crit is
+			supported, but not both.
+curr1_crit_alarm	Critical current high alarm.
 curr1_highest		Historical maximum current.
 curr1_reset_history	Write any value to reset history.
diff -druN linux-libre-3.1-gnu/Documentation/hwmon/exynos4_tmu linux-libre-3.2-gnu/Documentation/hwmon/exynos4_tmu
--- linux-libre-3.1-gnu/Documentation/hwmon/exynos4_tmu	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/hwmon/exynos4_tmu	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,81 @@
+Kernel driver exynos4_tmu
+=================
+
+Supported chips:
+* ARM SAMSUNG EXYNOS4 series of SoC
+  Prefix: 'exynos4-tmu'
+  Datasheet: Not publicly available
+
+Authors: Donggeun Kim <dg77.kim@samsung.com>
+
+Description
+-----------
+
+This driver allows to read temperature inside SAMSUNG EXYNOS4 series of SoC.
+
+The chip only exposes the measured 8-bit temperature code value
+through a register.
+Temperature can be taken from the temperature code.
+There are three equations converting from temperature to temperature code.
+
+The three equations are:
+  1. Two point trimming
+	Tc = (T - 25) * (TI2 - TI1) / (85 - 25) + TI1
+
+  2. One point trimming
+	Tc = T + TI1 - 25
+
+  3. No trimming
+	Tc = T + 50
+
+  Tc: Temperature code, T: Temperature,
+  TI1: Trimming info for 25 degree Celsius (stored at TRIMINFO register)
+       Temperature code measured at 25 degree Celsius which is unchanged
+  TI2: Trimming info for 85 degree Celsius (stored at TRIMINFO register)
+       Temperature code measured at 85 degree Celsius which is unchanged
+
+TMU(Thermal Management Unit) in EXYNOS4 generates interrupt
+when temperature exceeds pre-defined levels.
+The maximum number of configurable threshold is four.
+The threshold levels are defined as follows:
+  Level_0: current temperature > trigger_level_0 + threshold
+  Level_1: current temperature > trigger_level_1 + threshold
+  Level_2: current temperature > trigger_level_2 + threshold
+  Level_3: current temperature > trigger_level_3 + threshold
+
+  The threshold and each trigger_level are set
+  through the corresponding registers.
+
+When an interrupt occurs, this driver notify user space of
+one of four threshold levels for the interrupt
+through kobject_uevent_env and sysfs_notify functions.
+Although an interrupt condition for level_0 can be set,
+it is not notified to user space through sysfs_notify function.
+
+Sysfs Interface
+---------------
+name		name of the temperature sensor
+		RO
+
+temp1_input	temperature
+		RO
+
+temp1_max	temperature for level_1 interrupt
+		RO
+
+temp1_crit	temperature for level_2 interrupt
+		RO
+
+temp1_emergency	temperature for level_3 interrupt
+		RO
+
+temp1_max_alarm	alarm for level_1 interrupt
+		RO
+
+temp1_crit_alarm
+		alarm for level_2 interrupt
+		RO
+
+temp1_emergency_alarm
+		alarm for level_3 interrupt
+		RO
diff -druN linux-libre-3.1-gnu/Documentation/hwmon/lm75 linux-libre-3.2-gnu/Documentation/hwmon/lm75
--- linux-libre-3.1-gnu/Documentation/hwmon/lm75	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/hwmon/lm75	2012-01-04 18:55:44.000000000 -0500
@@ -12,26 +12,46 @@
     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
-    Datasheet: Publicly available at the Dallas Semiconductor website
-               http://www.maxim-ic.com/
-  * Dallas Semiconductor DS1775
-    Prefix: 'lm75'
-    Addresses scanned: I2C 0x48 - 0x4f
+  * Dallas Semiconductor DS75, DS1775
+    Prefixes: 'ds75', 'ds1775'
+    Addresses scanned: none
     Datasheet: Publicly available at the Dallas Semiconductor website
                http://www.maxim-ic.com/
   * Maxim MAX6625, MAX6626
-    Prefix: 'lm75'
-    Addresses scanned: I2C 0x48 - 0x4b
+    Prefixes: 'max6625', 'max6626'
+    Addresses scanned: none
     Datasheet: Publicly available at the Maxim website
                http://www.maxim-ic.com/
   * Microchip (TelCom) TCN75
     Prefix: 'lm75'
-    Addresses scanned: I2C 0x48 - 0x4f
+    Addresses scanned: none
+    Datasheet: Publicly available at the Microchip website
+               http://www.microchip.com/
+  * Microchip MCP9800, MCP9801, MCP9802, MCP9803
+    Prefix: 'mcp980x'
+    Addresses scanned: none
     Datasheet: Publicly available at the Microchip website
                http://www.microchip.com/
+  * Analog Devices ADT75
+    Prefix: 'adt75'
+    Addresses scanned: none
+    Datasheet: Publicly available at the Analog Devices website
+               http://www.analog.com/adt75
+  * ST Microelectronics STDS75
+    Prefix: 'stds75'
+    Addresses scanned: none
+    Datasheet: Publicly available at the ST website
+               http://www.st.com/internet/analog/product/121769.jsp
+  * Texas Instruments TMP100, TMP101, TMP105, TMP75, TMP175, TMP275
+    Prefixes: 'tmp100', 'tmp101', 'tmp105', 'tmp175', 'tmp75', 'tmp275'
+    Addresses scanned: none
+    Datasheet: Publicly available at the Texas Instruments website
+               http://www.ti.com/product/tmp100
+               http://www.ti.com/product/tmp101
+               http://www.ti.com/product/tmp105
+               http://www.ti.com/product/tmp75
+               http://www.ti.com/product/tmp175
+               http://www.ti.com/product/tmp275
 
 Author: Frodo Looijaard <frodol@dds.nl>
 
@@ -50,21 +70,16 @@
 The LM75 only updates its values each 1.5 seconds; reading it more often
 will do no harm, but will return 'old' values.
 
-The LM75 is usually used in combination with LM78-like chips, to measure
-the temperature of the processor(s).
-
-The DS75, DS1775, MAX6625, and MAX6626 are supported as well.
-They are not distinguished from an LM75. While most of these chips
-have three additional bits of accuracy (12 vs. 9 for the LM75),
-the additional bits are not supported. Not only that, but these chips will
-not be detected if not in 9-bit precision mode (use the force parameter if
-needed).
-
-The TCN75 is supported as well, and is not distinguished from an LM75.
+The original LM75 was typically used in combination with LM78-like chips
+on PC motherboards, to measure the temperature of the processor(s). Clones
+are now used in various embedded designs.
 
 The LM75 is essentially an industry standard; there may be other
 LM75 clones not listed here, with or without various enhancements,
-that are supported.
+that are supported. The clones are not detected by the driver, unless
+they reproduce the exact register tricks of the original LM75, and must
+therefore be instantiated explicitly. The specific enhancements (such as
+higher resolution) are not currently supported by the driver.
 
 The LM77 is not supported, contrary to what we pretended for a long time.
 Both chips are simply not compatible, value encoding differs.
diff -druN linux-libre-3.1-gnu/Documentation/hwmon/ltc2978 linux-libre-3.2-gnu/Documentation/hwmon/ltc2978
--- linux-libre-3.1-gnu/Documentation/hwmon/ltc2978	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/hwmon/ltc2978	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,103 @@
+Kernel driver ltc2978
+=====================
+
+Supported chips:
+  * Linear Technology LTC2978
+    Prefix: 'ltc2978'
+    Addresses scanned: -
+    Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf
+  * Linear Technology LTC3880
+    Prefix: 'ltc3880'
+    Addresses scanned: -
+    Datasheet: http://cds.linear.com/docs/Datasheet/3880f.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+The LTC2978 is an octal power supply monitor, supervisor, sequencer and
+margin controller. The LTC3880 is a dual, PolyPhase DC/DC synchronous
+step-down switching regulator controller.
+
+
+Usage Notes
+-----------
+
+This driver does not probe for PMBus devices. You will have to instantiate
+devices explicitly.
+
+Example: the following commands will load the driver for an LTC2978 at address
+0x60 on I2C bus #1:
+
+# modprobe ltc2978
+# echo ltc2978 0x60 > /sys/bus/i2c/devices/i2c-1/new_device
+
+
+Sysfs attributes
+----------------
+
+in1_label		"vin"
+in1_input		Measured input voltage.
+in1_min			Minimum input voltage.
+in1_max			Maximum input voltage.
+in1_lcrit		Critical minimum input voltage.
+in1_crit		Critical maximum input voltage.
+in1_min_alarm		Input voltage low alarm.
+in1_max_alarm		Input voltage high alarm.
+in1_lcrit_alarm		Input voltage critical low alarm.
+in1_crit_alarm		Input voltage critical high alarm.
+in1_lowest		Lowest input voltage. LTC2978 only.
+in1_highest		Highest input voltage.
+in1_reset_history	Reset history. Writing into this attribute will reset
+			history for all attributes.
+
+in[2-9]_label		"vout[1-8]". Channels 3 to 9 on LTC2978 only.
+in[2-9]_input		Measured output voltage.
+in[2-9]_min		Minimum output voltage.
+in[2-9]_max		Maximum output voltage.
+in[2-9]_lcrit		Critical minimum output voltage.
+in[2-9]_crit		Critical maximum output voltage.
+in[2-9]_min_alarm	Output voltage low alarm.
+in[2-9]_max_alarm	Output voltage high alarm.
+in[2-9]_lcrit_alarm	Output voltage critical low alarm.
+in[2-9]_crit_alarm	Output voltage critical high alarm.
+in[2-9]_lowest		Lowest output voltage. LTC2978 only.
+in[2-9]_highest		Lowest output voltage.
+in[2-9]_reset_history	Reset history. Writing into this attribute will reset
+			history for all attributes.
+
+temp[1-3]_input		Measured temperature.
+			On LTC2978, only one temperature measurement is
+			supported and reflects the internal temperature.
+			On LTC3880, temp1 and temp2 report external
+			temperatures, and temp3 reports the internal
+			temperature.
+temp[1-3]_min		Mimimum temperature.
+temp[1-3]_max		Maximum temperature.
+temp[1-3]_lcrit		Critical low temperature.
+temp[1-3]_crit		Critical high temperature.
+temp[1-3]_min_alarm	Chip temperature low alarm.
+temp[1-3]_max_alarm	Chip temperature high alarm.
+temp[1-3]_lcrit_alarm	Chip temperature critical low alarm.
+temp[1-3]_crit_alarm	Chip temperature critical high alarm.
+temp[1-3]_lowest	Lowest measured temperature. LTC2978 only.
+temp[1-3]_highest	Highest measured temperature.
+temp[1-3]_reset_history	Reset history. Writing into this attribute will reset
+			history for all attributes.
+
+power[1-2]_label	"pout[1-2]". LTC3880 only.
+power[1-2]_input	Measured power.
+
+curr1_label		"iin". LTC3880 only.
+curr1_input		Measured input current.
+curr1_max		Maximum input current.
+curr1_max_alarm		Input current high alarm.
+
+curr[2-3]_label		"iout[1-2]". LTC3880 only.
+curr[2-3]_input		Measured input current.
+curr[2-3]_max		Maximum input current.
+curr[2-3]_crit		Critical input current.
+curr[2-3]_max_alarm	Input current high alarm.
+curr[2-3]_crit_alarm	Input current critical high alarm.
diff -druN linux-libre-3.1-gnu/Documentation/hwmon/pmbus linux-libre-3.2-gnu/Documentation/hwmon/pmbus
--- linux-libre-3.1-gnu/Documentation/hwmon/pmbus	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/hwmon/pmbus	2012-01-04 18:55:44.000000000 -0500
@@ -8,11 +8,6 @@
     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
   * ON Semiconductor ADP4000, NCP4200, NCP4208
     Prefixes: 'adp4000', 'ncp4200', 'ncp4208'
     Addresses scanned: -
@@ -20,6 +15,14 @@
 	http://www.onsemi.com/pub_link/Collateral/ADP4000-D.PDF
 	http://www.onsemi.com/pub_link/Collateral/NCP4200-D.PDF
 	http://www.onsemi.com/pub_link/Collateral/JUNE%202009-%20REV.%200.PDF
+  * Lineage Power
+    Prefixes: 'pdt003', 'pdt006', 'pdt012', 'udt020'
+    Addresses scanned: -
+    Datasheets:
+	http://www.lineagepower.com/oem/pdf/PDT003A0X.pdf
+	http://www.lineagepower.com/oem/pdf/PDT006A0X.pdf
+	http://www.lineagepower.com/oem/pdf/PDT012A0X.pdf
+	http://www.lineagepower.com/oem/pdf/UDT020A0X.pdf
   * Generic PMBus devices
     Prefix: 'pmbus'
     Addresses scanned: -
diff -druN linux-libre-3.1-gnu/Documentation/hwmon/pmbus-core linux-libre-3.2-gnu/Documentation/hwmon/pmbus-core
--- linux-libre-3.1-gnu/Documentation/hwmon/pmbus-core	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/hwmon/pmbus-core	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,283 @@
+PMBus core driver and internal API
+==================================
+
+Introduction
+============
+
+[from pmbus.org] The Power Management Bus (PMBus) is an open standard
+power-management protocol with a fully defined command language that facilitates
+communication with power converters and other devices in a power system. The
+protocol is implemented over the industry-standard SMBus serial interface and
+enables programming, control, and real-time monitoring of compliant power
+conversion products. This flexible and highly versatile standard allows for
+communication between devices based on both analog and digital technologies, and
+provides true interoperability which will reduce design complexity and shorten
+time to market for power system designers. Pioneered by leading power supply and
+semiconductor companies, this open power system standard is maintained and
+promoted by the PMBus Implementers Forum (PMBus-IF), comprising 30+ adopters
+with the objective to provide support to, and facilitate adoption among, users.
+
+Unfortunately, while PMBus commands are standardized, there are no mandatory
+commands, and manufacturers can add as many non-standard commands as they like.
+Also, different PMBUs devices act differently if non-supported commands are
+executed. Some devices return an error, some devices return 0xff or 0xffff and
+set a status error flag, and some devices may simply hang up.
+
+Despite all those difficulties, a generic PMBus device driver is still useful
+and supported since kernel version 2.6.39. However, it was necessary to support
+device specific extensions in addition to the core PMBus driver, since it is
+simply unknown what new device specific functionality PMBus device developers
+come up with next.
+
+To make device specific extensions as scalable as possible, and to avoid having
+to modify the core PMBus driver repeatedly for new devices, the PMBus driver was
+split into core, generic, and device specific code. The core code (in
+pmbus_core.c) provides generic functionality. The generic code (in pmbus.c)
+provides support for generic PMBus devices. Device specific code is responsible
+for device specific initialization and, if needed, maps device specific
+functionality into generic functionality. This is to some degree comparable
+to PCI code, where generic code is augmented as needed with quirks for all kinds
+of devices.
+
+PMBus device capabilities auto-detection
+========================================
+
+For generic PMBus devices, code in pmbus.c attempts to auto-detect all supported
+PMBus commands. Auto-detection is somewhat limited, since there are simply too
+many variables to consider. For example, it is almost impossible to autodetect
+which PMBus commands are paged and which commands are replicated across all
+pages (see the PMBus specification for details on multi-page PMBus devices).
+
+For this reason, it often makes sense to provide a device specific driver if not
+all commands can be auto-detected. The data structures in this driver can be
+used to inform the core driver about functionality supported by individual
+chips.
+
+Some commands are always auto-detected. This applies to all limit commands
+(lcrit, min, max, and crit attributes) as well as associated alarm attributes.
+Limits and alarm attributes are auto-detected because there are simply too many
+possible combinations to provide a manual configuration interface.
+
+PMBus internal API
+==================
+
+The API between core and device specific PMBus code is defined in
+drivers/hwmon/pmbus/pmbus.h. In addition to the internal API, pmbus.h defines
+standard PMBus commands and virtual PMBus commands.
+
+Standard PMBus commands
+-----------------------
+
+Standard PMBus commands (commands values 0x00 to 0xff) are defined in the PMBUs
+specification.
+
+Virtual PMBus commands
+----------------------
+
+Virtual PMBus commands are provided to enable support for non-standard
+functionality which has been implemented by several chip vendors and is thus
+desirable to support.
+
+Virtual PMBus commands start with command value 0x100 and can thus easily be
+distinguished from standard PMBus commands (which can not have values larger
+than 0xff). Support for virtual PMBus commands is device specific and thus has
+to be implemented in device specific code.
+
+Virtual commands are named PMBUS_VIRT_xxx and start with PMBUS_VIRT_BASE. All
+virtual commands are word sized.
+
+There are currently two types of virtual commands.
+
+- READ commands are read-only; writes are either ignored or return an error.
+- RESET commands are read/write. Reading reset registers returns zero
+  (used for detection), writing any value causes the associated history to be
+  reset.
+
+Virtual commands have to be handled in device specific driver code. Chip driver
+code returns non-negative values if a virtual command is supported, or a
+negative error code if not. The chip driver may return -ENODATA or any other
+Linux error code in this case, though an error code other than -ENODATA is
+handled more efficiently and thus preferred. Either case, the calling PMBus
+core code will abort if the chip driver returns an error code when reading
+or writing virtual registers (in other words, the PMBus core code will never
+send a virtual command to a chip).
+
+PMBus driver information
+------------------------
+
+PMBus driver information, defined in struct pmbus_driver_info, is the main means
+for device specific drivers to pass information to the core PMBus driver.
+Specifically, it provides the following information.
+
+- For devices supporting its data in Direct Data Format, it provides coefficients
+  for converting register values into normalized data. This data is usually
+  provided by chip manufacturers in device datasheets.
+- Supported chip functionality can be provided to the core driver. This may be
+  necessary for chips which react badly if non-supported commands are executed,
+  and/or to speed up device detection and initialization.
+- Several function entry points are provided to support overriding and/or
+  augmenting generic command execution. This functionality can be used to map
+  non-standard PMBus commands to standard commands, or to augment standard
+  command return values with device specific information.
+
+  API functions
+  -------------
+
+  Functions provided by chip driver
+  ---------------------------------
+
+  All functions return the command return value (read) or zero (write) if
+  successful. A return value of -ENODATA indicates that there is no manufacturer
+  specific command, but that a standard PMBus command may exist. Any other
+  negative return value indicates that the commands does not exist for this
+  chip, and that no attempt should be made to read or write the standard
+  command.
+
+  As mentioned above, an exception to this rule applies to virtual commands,
+  which  _must_ be handled in driver specific code. See "Virtual PMBus Commands"
+  above for more details.
+
+  Command execution in the core PMBus driver code is as follows.
+
+	if (chip_access_function) {
+		status = chip_access_function();
+		if (status != -ENODATA)
+			return status;
+	}
+	if (command >= PMBUS_VIRT_BASE)	/* For word commands/registers only */
+		return -EINVAL;
+	return generic_access();
+
+  Chip drivers may provide pointers to the following functions in struct
+  pmbus_driver_info. All functions are optional.
+
+  int (*read_byte_data)(struct i2c_client *client, int page, int reg);
+
+  Read byte from page <page>, register <reg>.
+  <page> may be -1, which means "current page".
+
+  int (*read_word_data)(struct i2c_client *client, int page, int reg);
+
+  Read word from page <page>, register <reg>.
+
+  int (*write_word_data)(struct i2c_client *client, int page, int reg,
+		         u16 word);
+
+  Write word to page <page>, register <reg>.
+
+  int (*write_byte)(struct i2c_client *client, int page, u8 value);
+
+  Write byte to page <page>, register <reg>.
+  <page> may be -1, which means "current page".
+
+  int (*identify)(struct i2c_client *client, struct pmbus_driver_info *info);
+
+  Determine supported PMBus functionality. This function is only necessary
+  if a chip driver supports multiple chips, and the chip functionality is not
+  pre-determined. It is currently only used by the generic pmbus driver
+  (pmbus.c).
+
+  Functions exported by core driver
+  ---------------------------------
+
+  Chip drivers are expected to use the following functions to read or write
+  PMBus registers. Chip drivers may also use direct I2C commands. If direct I2C
+  commands are used, the chip driver code must not directly modify the current
+  page, since the selected page is cached in the core driver and the core driver
+  will assume that it is selected. Using pmbus_set_page() to select a new page
+  is mandatory.
+
+  int pmbus_set_page(struct i2c_client *client, u8 page);
+
+  Set PMBus page register to <page> for subsequent commands.
+
+  int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
+
+  Read word data from <page>, <reg>. Similar to i2c_smbus_read_word_data(), but
+  selects page first.
+
+  int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg,
+			    u16 word);
+
+  Write word data to <page>, <reg>. Similar to i2c_smbus_write_word_data(), but
+  selects page first.
+
+  int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
+
+  Read byte data from <page>, <reg>. Similar to i2c_smbus_read_byte_data(), but
+  selects page first. <page> may be -1, which means "current page".
+
+  int pmbus_write_byte(struct i2c_client *client, int page, u8 value);
+
+  Write byte data to <page>, <reg>. Similar to i2c_smbus_write_byte(), but
+  selects page first. <page> may be -1, which means "current page".
+
+  void pmbus_clear_faults(struct i2c_client *client);
+
+  Execute PMBus "Clear Fault" command on all chip pages.
+  This function calls the device specific write_byte function if defined.
+  Therefore, it must _not_ be called from that function.
+
+  bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
+
+  Check if byte register exists. Return true if the register exists, false
+  otherwise.
+  This function calls the device specific write_byte function if defined to
+  obtain the chip status. Therefore, it must _not_ be called from that function.
+
+  bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
+
+  Check if word register exists. Return true if the register exists, false
+  otherwise.
+  This function calls the device specific write_byte function if defined to
+  obtain the chip status. Therefore, it must _not_ be called from that function.
+
+  int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
+                     struct pmbus_driver_info *info);
+
+  Execute probe function. Similar to standard probe function for other drivers,
+  with the pointer to struct pmbus_driver_info as additional argument. Calls
+  identify function if supported. Must only be called from device probe
+  function.
+
+  void pmbus_do_remove(struct i2c_client *client);
+
+  Execute driver remove function. Similar to standard driver remove function.
+
+  const struct pmbus_driver_info
+	*pmbus_get_driver_info(struct i2c_client *client);
+
+  Return pointer to struct pmbus_driver_info as passed to pmbus_do_probe().
+
+
+PMBus driver platform data
+==========================
+
+PMBus platform data is defined in include/linux/i2c/pmbus.h. Platform data
+currently only provides a flag field with a single bit used.
+
+#define PMBUS_SKIP_STATUS_CHECK (1 << 0)
+
+struct pmbus_platform_data {
+        u32 flags;              /* Device specific flags */
+};
+
+
+Flags
+-----
+
+PMBUS_SKIP_STATUS_CHECK
+
+During register detection, skip checking the status register for
+communication or command errors.
+
+Some PMBus chips respond with valid data when trying to read an unsupported
+register. For such chips, checking the status register is mandatory when
+trying to determine if a chip register exists or not.
+Other PMBus chips don't support the STATUS_CML register, or report
+communication errors for no explicable reason. For such chips, checking the
+status register must be disabled.
+
+Some i2c controllers do not support single-byte commands (write commands with
+no data, i2c_smbus_write_byte()). With such controllers, clearing the status
+register is impossible, and the PMBUS_SKIP_STATUS_CHECK flag must be set.
diff -druN linux-libre-3.1-gnu/Documentation/hwmon/w83627ehf linux-libre-3.2-gnu/Documentation/hwmon/w83627ehf
--- linux-libre-3.1-gnu/Documentation/hwmon/w83627ehf	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/hwmon/w83627ehf	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,10 @@
     Prefix: 'w83627dhg'
     Addresses scanned: ISA address retrieved from Super I/O registers
     Datasheet: not available
+  * Winbond W83627UHG
+    Prefix: 'w83627uhg'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: available from www.nuvoton.com
   * Winbond W83667HG
     Prefix: 'w83667hg'
     Addresses scanned: ISA address retrieved from Super I/O registers
@@ -42,14 +46,13 @@
 -----------
 
 This driver implements support for the Winbond W83627EHF, W83627EHG,
-W83627DHG, W83627DHG-P, W83667HG, W83667HG-B, W83667HG-I (NCT6775F),
-and NCT6776F super I/O chips. We will refer to them collectively as
-Winbond chips.
+W83627DHG, W83627DHG-P, W83627UHG, 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 (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),
+The chips implement 2 to 4 temperature sensors (9 for NCT6775F and NCT6776F),
+2 to 5 fan rotation speed sensors, 8 to 10 analog voltage sensors, one VID
+(except for 627UHG), 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
@@ -86,17 +89,16 @@
 
 temp1 -> pwm1
 temp2 -> pwm2
-temp3 -> pwm3
+temp3 -> pwm3 (not on 627UHG)
 prog  -> pwm4 (not on 667HG and 667HG-B; the programmable setting is not
 	       supported by the driver)
 
 /sys files
 ----------
 
-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",
-       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".
+name - this is a standard hwmon device entry, it contains the name of
+       the device (see the prefix in the list of supported devices at
+       the top of this file)
 
 pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range:
 	   0 (stop) to 255 (full)
diff -druN linux-libre-3.1-gnu/Documentation/hwmon/zl6100 linux-libre-3.2-gnu/Documentation/hwmon/zl6100
--- linux-libre-3.1-gnu/Documentation/hwmon/zl6100	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/hwmon/zl6100	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,125 @@
+Kernel driver zl6100
+====================
+
+Supported chips:
+  * Intersil / Zilker Labs ZL2004
+    Prefix: 'zl2004'
+    Addresses scanned: -
+    Datasheet: http://www.intersil.com/data/fn/fn6847.pdf
+  * Intersil / Zilker Labs ZL2006
+    Prefix: 'zl2006'
+    Addresses scanned: -
+    Datasheet: http://www.intersil.com/data/fn/fn6850.pdf
+  * Intersil / Zilker Labs ZL2008
+    Prefix: 'zl2008'
+    Addresses scanned: -
+    Datasheet: http://www.intersil.com/data/fn/fn6859.pdf
+  * Intersil / Zilker Labs ZL2105
+    Prefix: 'zl2105'
+    Addresses scanned: -
+    Datasheet: http://www.intersil.com/data/fn/fn6851.pdf
+  * Intersil / Zilker Labs ZL2106
+    Prefix: 'zl2106'
+    Addresses scanned: -
+    Datasheet: http://www.intersil.com/data/fn/fn6852.pdf
+  * Intersil / Zilker Labs ZL6100
+    Prefix: 'zl6100'
+    Addresses scanned: -
+    Datasheet: http://www.intersil.com/data/fn/fn6876.pdf
+  * Intersil / Zilker Labs ZL6105
+    Prefix: 'zl6105'
+    Addresses scanned: -
+    Datasheet: http://www.intersil.com/data/fn/fn6906.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports hardware montoring for Intersil / Zilker Labs ZL6100 and
+compatible digital DC-DC controllers.
+
+The driver is a client driver to the core PMBus driver. Please see
+Documentation/hwmon/pmbus and Documentation.hwmon/pmbus-core 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.
+
+WARNING: Do not access chip registers using the i2cdump command, and do not use
+any of the i2ctools commands on a command register used to save and restore
+configuration data (0x11, 0x12, 0x15, 0x16, and 0xf4). The chips supported by
+this driver interpret any access to those command registers (including read
+commands) as request to execute the command in question. Unless write accesses
+to those registers are protected, this may result in power loss, board resets,
+and/or Flash corruption. Worst case, your board may turn into a brick.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Module parameters
+-----------------
+
+delay
+-----
+
+Some Intersil/Zilker Labs DC-DC controllers require a minimum interval between
+I2C bus accesses. According to Intersil, the minimum interval is 2 ms, though
+1 ms appears to be sufficient and has not caused any problems in testing.
+The problem is known to affect ZL6100, ZL2105, and ZL2008. It is known not to
+affect ZL2004 and ZL6105. The driver automatically sets the interval to 1 ms
+except for ZL2004 and ZL6105. To enable manual override, the driver provides a
+writeable module parameter, 'delay', which can be used to set the interval to
+a value between 0 and 65,535 microseconds.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported. Limits are read-write; all other
+attributes are read-only.
+
+in1_label		"vin"
+in1_input		Measured input voltage.
+in1_min			Minimum input voltage.
+in1_max			Maximum input voltage.
+in1_lcrit		Critical minumum input voltage.
+in1_crit		Critical maximum input voltage.
+in1_min_alarm		Input voltage low alarm.
+in1_max_alarm		Input voltage high alarm.
+in1_lcrit_alarm		Input voltage critical low alarm.
+in1_crit_alarm		Input voltage critical high alarm.
+
+in2_label		"vout1"
+in2_input		Measured output voltage.
+in2_lcrit		Critical minumum output Voltage.
+in2_crit		Critical maximum output voltage.
+in2_lcrit_alarm		Critical output voltage critical low alarm.
+in2_crit_alarm		Critical output voltage critical high alarm.
+
+curr1_label		"iout1"
+curr1_input		Measured output current.
+curr1_lcrit		Critical minimum output current.
+curr1_crit		Critical maximum output current.
+curr1_lcrit_alarm	Output current critical low alarm.
+curr1_crit_alarm	Output current critical high alarm.
+
+temp[12]_input		Measured temperature.
+temp[12]_min		Minimum temperature.
+temp[12]_max		Maximum temperature.
+temp[12]_lcrit		Critical low temperature.
+temp[12]_crit		Critical high temperature.
+temp[12]_min_alarm	Chip temperature low alarm.
+temp[12]_max_alarm	Chip temperature high alarm.
+temp[12]_lcrit_alarm	Chip temperature critical low alarm.
+temp[12]_crit_alarm	Chip temperature critical high alarm.
diff -druN linux-libre-3.1-gnu/Documentation/hwspinlock.txt linux-libre-3.2-gnu/Documentation/hwspinlock.txt
--- linux-libre-3.1-gnu/Documentation/hwspinlock.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/hwspinlock.txt	2012-01-04 18:55:44.000000000 -0500
@@ -39,23 +39,20 @@
      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.
+     Should be called from a process context (might sleep).
 
   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.
+     Should be called from a process context (might sleep).
 
   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.
+     Should be called from a process context (might sleep).
 
   int hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int timeout);
    - lock a previously-assigned hwspinlock with a timeout limit (specified in
@@ -230,45 +227,62 @@
 
 4. API for implementors
 
-  int hwspin_lock_register(struct hwspinlock *hwlock);
+  int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
+		const struct hwspinlock_ops *ops, int base_id, int num_locks);
    - 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.
+     order to register a new hwspinlock device (which is usually a bank of
+     numerous locks). Should be called from a process context (this function
+     might sleep).
+     Returns 0 on success, or appropriate error code on failure.
 
-  struct hwspinlock *hwspin_lock_unregister(unsigned int id);
+  int hwspin_lock_unregister(struct hwspinlock_device *bank);
    - 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.
+     to unregister an hwspinlock device (which is usually a bank of numerous
+     locks).
+     Should be called from a process context (this function might sleep).
      Returns the address of hwspinlock on success, or NULL on error (e.g.
      if the hwspinlock is sill in use).
 
-5. struct hwspinlock
+5. Important structs
 
-This struct represents an hwspinlock instance. It is registered by the
-underlying hwspinlock implementation using the hwspin_lock_register() API.
+struct hwspinlock_device is a device which usually contains a bank
+of hardware locks. 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_device - a device which usually spans numerous hwspinlocks
+ * @dev: underlying device, will be used to invoke runtime PM api
+ * @ops: platform-specific hwspinlock handlers
+ * @base_id: id index of the first lock in this device
+ * @num_locks: number of locks in this device
+ * @lock: dynamically allocated array of 'struct hwspinlock'
  */
-struct hwspinlock {
+struct hwspinlock_device {
 	struct device *dev;
 	const struct hwspinlock_ops *ops;
-	int id;
+	int base_id;
+	int num_locks;
+	struct hwspinlock lock[0];
+};
+
+struct hwspinlock_device contains an array of hwspinlock structs, each
+of which represents a single hardware lock:
+
+/**
+ * struct hwspinlock - this struct represents a single hwspinlock instance
+ * @bank: the hwspinlock_device structure which owns this lock
+ * @lock: initialized and used by hwspinlock core
+ * @priv: private data, owned by the underlying platform-specific hwspinlock drv
+ */
+struct hwspinlock {
+	struct hwspinlock_device *bank;
 	spinlock_t lock;
-	struct module *owner;
+	void *priv;
 };
 
-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.
+When registering a bank of locks, the hwspinlock driver only needs to
+set the priv members of the locks. The rest of the members are set and
+initialized by the hwspinlock core itself.
 
 6. Implementation callbacks
 
diff -druN linux-libre-3.1-gnu/Documentation/i2c/smbus-protocol linux-libre-3.2-gnu/Documentation/i2c/smbus-protocol
--- linux-libre-3.1-gnu/Documentation/i2c/smbus-protocol	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/i2c/smbus-protocol	2012-01-04 18:55:44.000000000 -0500
@@ -88,6 +88,10 @@
 
 S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
 
+Note the convenience function i2c_smbus_read_word_swapped is
+available for reads where the two data bytes are the other way
+around (not SMBus compliant, but very popular.)
+
 
 SMBus Write Byte:  i2c_smbus_write_byte_data()
 ==============================================
@@ -108,6 +112,10 @@
 
 S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P
 
+Note the convenience function i2c_smbus_write_word_swapped is
+available for writes where the two data bytes are the other way
+around (not SMBus compliant, but very popular.)
+
 
 SMBus Process Call:  i2c_smbus_process_call()
 =============================================
diff -druN linux-libre-3.1-gnu/Documentation/i2c/ten-bit-addresses linux-libre-3.2-gnu/Documentation/i2c/ten-bit-addresses
--- linux-libre-3.1-gnu/Documentation/i2c/ten-bit-addresses	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/i2c/ten-bit-addresses	2012-01-04 18:55:44.000000000 -0500
@@ -1,22 +1,24 @@
 The I2C protocol knows about two kinds of device addresses: normal 7 bit
 addresses, and an extended set of 10 bit addresses. The sets of addresses
 do not intersect: the 7 bit address 0x10 is not the same as the 10 bit
-address 0x10 (though a single device could respond to both of them). You
-select a 10 bit address by adding an extra byte after the address
-byte:
-  S Addr7 Rd/Wr ....
-becomes
-  S 11110 Addr10 Rd/Wr
-S is the start bit, Rd/Wr the read/write bit, and if you count the number
-of bits, you will see the there are 8 after the S bit for 7 bit addresses,
-and 16 after the S bit for 10 bit addresses.
+address 0x10 (though a single device could respond to both of them).
 
-WARNING! The current 10 bit address support is EXPERIMENTAL. There are
-several places in the code that will cause SEVERE PROBLEMS with 10 bit
-addresses, even though there is some basic handling and hooks. Also,
-almost no supported adapter handles the 10 bit addresses correctly.
+I2C messages to and from 10-bit address devices have a different format.
+See the I2C specification for the details.
 
-As soon as a real 10 bit address device is spotted 'in the wild', we
-can and will add proper support. Right now, 10 bit address devices
-are defined by the I2C protocol, but we have never seen a single device
-which supports them.
+The current 10 bit address support is minimal. It should work, however
+you can expect some problems along the way:
+* Not all bus drivers support 10-bit addresses. Some don't because the
+  hardware doesn't support them (SMBus doesn't require 10-bit address
+  support for example), some don't because nobody bothered adding the
+  code (or it's there but not working properly.) Software implementation
+  (i2c-algo-bit) is known to work.
+* Some optional features do not support 10-bit addresses. This is the
+  case of automatic detection and instantiation of devices by their,
+  drivers, for example.
+* Many user-space packages (for example i2c-tools) lack support for
+  10-bit addresses.
+
+Note that 10-bit address devices are still pretty rare, so the limitations
+listed above could stay for a long time, maybe even forever if nobody
+needs them to be fixed.
diff -druN linux-libre-3.1-gnu/Documentation/input/elantech.txt linux-libre-3.2-gnu/Documentation/input/elantech.txt
--- linux-libre-3.1-gnu/Documentation/input/elantech.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/input/elantech.txt	2012-01-04 18:55:44.000000000 -0500
@@ -16,15 +16,28 @@
 
  1. Introduction
  2. Extra knobs
- 3. Hardware version 1
-    3.1 Registers
-    3.2 Native relative mode 4 byte packet format
-    3.3 Native absolute mode 4 byte packet format
- 4. Hardware version 2
+ 3. Differentiating hardware versions
+ 4. Hardware version 1
     4.1 Registers
-    4.2 Native absolute mode 6 byte packet format
-        4.2.1 One finger touch
-        4.2.2 Two finger touch
+    4.2 Native relative mode 4 byte packet format
+    4.3 Native absolute mode 4 byte packet format
+ 5. Hardware version 2
+    5.1 Registers
+    5.2 Native absolute mode 6 byte packet format
+        5.2.1 Parity checking and packet re-synchronization
+        5.2.2 One/Three finger touch
+        5.2.3 Two finger touch
+ 6. Hardware version 3
+    6.1 Registers
+    6.2 Native absolute mode 6 byte packet format
+        6.2.1 One/Three finger touch
+        6.2.2 Two finger touch
+ 7. Hardware version 4
+    7.1 Registers
+    7.2 Native absolute mode 6 byte packet format
+        7.2.1 Status packet
+        7.2.2 Head packet
+        7.2.3 Motion packet
 
 
 
@@ -375,7 +388,7 @@
 
 In case an error is detected, all the packets are shifted by one (and packet[0] is discarded).
 
-5.2.1 One/Three finger touch
+5.2.2 One/Three finger touch
       ~~~~~~~~~~~~~~~~
 
 byte 0:
@@ -384,19 +397,19 @@
 	 n1  n0  w3  w2   .   .   R   L
 
          L, R = 1 when Left, Right mouse button pressed
-         n1..n0 = numbers of fingers on touchpad
+         n1..n0 = number of fingers on touchpad
 
 byte 1:
 
    bit   7   6   5   4   3   2   1   0
-	 p7  p6  p5  p4  .  x10 x9  x8
+	 p7  p6  p5  p4 x11 x10 x9  x8
 
 byte 2:
 
    bit   7   6   5   4   3   2   1   0
 	 x7  x6  x5  x4  x3  x2  x1  x0
 
-         x10..x0 = absolute x value (horizontal)
+         x11..x0 = absolute x value (horizontal)
 
 byte 3:
 
@@ -420,7 +433,7 @@
 byte 4:
 
    bit   7   6   5   4   3   2   1   0
-        p3  p1  p2  p0   .   .  y9  y8
+        p3  p1  p2  p0  y11 y10 y9  y8
 
 	 p7..p0 = pressure (not EF113)
 
@@ -429,10 +442,10 @@
    bit   7   6   5   4   3   2   1   0
         y7  y6  y5  y4  y3  y2  y1  y0
 
-         y9..y0 = absolute y value (vertical)
+         y11..y0 = absolute y value (vertical)
 
 
-4.2.2 Two finger touch
+5.2.3 Two finger touch
       ~~~~~~~~~~~~~~~~
 
 Note that the two pairs of coordinates are not exactly the coordinates of the
@@ -446,7 +459,7 @@
         n1  n0  ay8 ax8  .   .   R   L
 
          L, R = 1 when Left, Right mouse button pressed
-         n1..n0 = numbers of fingers on touchpad
+         n1..n0 = number of fingers on touchpad
 
 byte 1:
 
@@ -480,3 +493,253 @@
         by7 by8 by5 by4 by3 by2 by1 by0
 
          by8..by0 = upper-right finger absolute y value
+
+/////////////////////////////////////////////////////////////////////////////
+
+6. Hardware version 3
+   ==================
+
+6.1 Registers
+    ~~~~~~~~~
+* reg_10
+
+   bit   7   6   5   4   3   2   1   0
+         0   0   0   0   0   0   0   A
+
+         A: 1 = enable absolute tracking
+
+6.2 Native absolute mode 6 byte packet format
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+1 and 3 finger touch shares the same 6-byte packet format, except that
+3 finger touch only reports the position of the center of all three fingers.
+
+Firmware would send 12 bytes of data for 2 finger touch.
+
+Note on debounce:
+In case the box has unstable power supply or other electricity issues, or
+when number of finger changes, F/W would send "debounce packet" to inform
+driver that the hardware is in debounce status.
+The debouce packet has the following signature:
+    byte 0: 0xc4
+    byte 1: 0xff
+    byte 2: 0xff
+    byte 3: 0x02
+    byte 4: 0xff
+    byte 5: 0xff
+When we encounter this kind of packet, we just ignore it.
+
+6.2.1 One/Three finger touch
+      ~~~~~~~~~~~~~~~~~~~~~~
+
+byte 0:
+
+   bit   7   6   5   4   3   2   1   0
+        n1  n0  w3  w2   0   1   R   L
+
+        L, R = 1 when Left, Right mouse button pressed
+        n1..n0 = number of fingers on touchpad
+
+byte 1:
+
+   bit   7   6   5   4   3   2   1   0
+        p7  p6  p5  p4 x11 x10  x9  x8
+
+byte 2:
+
+   bit   7   6   5   4   3   2   1   0
+        x7  x6  x5  x4  x3  x2  x1  x0
+
+        x11..x0 = absolute x value (horizontal)
+
+byte 3:
+
+   bit   7   6   5   4   3   2   1   0
+         0   0  w1  w0   0   0   1   0
+
+         w3..w0 = width of the finger touch
+
+byte 4:
+
+   bit   7   6   5   4   3   2   1   0
+        p3  p1  p2  p0  y11 y10 y9  y8
+
+        p7..p0 = pressure
+
+byte 5:
+
+   bit   7   6   5   4   3   2   1   0
+        y7  y6  y5  y4  y3  y2  y1  y0
+
+        y11..y0 = absolute y value (vertical)
+
+6.2.2 Two finger touch
+      ~~~~~~~~~~~~~~~~
+
+The packet format is exactly the same for two finger touch, except the hardware
+sends two 6 byte packets. The first packet contains data for the first finger,
+the second packet has data for the second finger. So for two finger touch a
+total of 12 bytes are sent.
+
+/////////////////////////////////////////////////////////////////////////////
+
+7. Hardware version 4
+   ==================
+
+7.1 Registers
+    ~~~~~~~~~
+* reg_07
+
+   bit   7   6   5   4   3   2   1   0
+         0   0   0   0   0   0   0   A
+
+         A: 1 = enable absolute tracking
+
+7.2 Native absolute mode 6 byte packet format
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers.
+Unfortunately, due to PS/2's limited bandwidth, its packet format is rather
+complex.
+
+Whenever the numbers or identities of the fingers changes, the hardware sends a
+status packet to indicate how many and which fingers is on touchpad, followed by
+head packets or motion packets. A head packet contains data of finger id, finger
+position (absolute x, y values), width, and pressure. A motion packet contains
+two fingers' position delta.
+
+For example, when status packet tells there are 2 fingers on touchpad, then we
+can expect two following head packets. If the finger status doesn't change,
+the following packets would be motion packets, only sending delta of finger
+position, until we receive a status packet.
+
+One exception is one finger touch. when a status packet tells us there is only
+one finger, the hardware would just send head packets afterwards.
+
+7.2.1 Status packet
+      ~~~~~~~~~~~~~
+
+byte 0:
+
+   bit   7   6   5   4   3   2   1   0
+         .   .   .   .   0   1   R   L
+
+         L, R = 1 when Left, Right mouse button pressed
+
+byte 1:
+
+   bit   7   6   5   4   3   2   1   0
+         .   .   . ft4 ft3 ft2 ft1 ft0
+
+         ft4 ft3 ft2 ft1 ft0 ftn = 1 when finger n is on touchpad
+
+byte 2: not used
+
+byte 3:
+
+   bit   7   6   5   4   3   2   1   0
+         .   .   .   1   0   0   0   0
+
+         constant bits
+
+byte 4:
+
+   bit   7   6   5   4   3   2   1   0
+         p   .   .   .   .   .   .   .
+
+         p = 1 for palm
+
+byte 5: not used
+
+7.2.2 Head packet
+      ~~~~~~~~~~~
+
+byte 0:
+
+   bit   7   6   5   4   3   2   1   0
+        w3  w2  w1  w0   0   1   R   L
+
+        L, R = 1 when Left, Right mouse button pressed
+        w3..w0 = finger width (spans how many trace lines)
+
+byte 1:
+
+   bit   7   6   5   4   3   2   1   0
+        p7  p6  p5  p4 x11 x10  x9  x8
+
+byte 2:
+
+   bit   7   6   5   4   3   2   1   0
+        x7  x6  x5  x4  x3  x2  x1  x0
+
+        x11..x0 = absolute x value (horizontal)
+
+byte 3:
+
+   bit   7   6   5   4   3   2   1   0
+       id2 id1 id0   1   0   0   0   1
+
+       id2..id0 = finger id
+
+byte 4:
+
+   bit   7   6   5   4   3   2   1   0
+        p3  p1  p2  p0  y11 y10 y9  y8
+
+        p7..p0 = pressure
+
+byte 5:
+
+   bit   7   6   5   4   3   2   1   0
+        y7  y6  y5  y4  y3  y2  y1  y0
+
+        y11..y0 = absolute y value (vertical)
+
+7.2.3 Motion packet
+      ~~~~~~~~~~~~~
+
+byte 0:
+
+   bit   7   6   5   4   3   2   1   0
+       id2 id1 id0   w   0   1   R   L
+
+       L, R = 1 when Left, Right mouse button pressed
+       id2..id0 = finger id
+       w = 1 when delta overflows (> 127 or < -128), in this case
+       firmware sends us (delta x / 5) and (delta y  / 5)
+
+byte 1:
+
+   bit   7   6   5   4   3   2   1   0
+        x7  x6  x5  x4  x3  x2  x1  x0
+
+        x7..x0 = delta x (two's complement)
+
+byte 2:
+
+   bit   7   6   5   4   3   2   1   0
+        y7  y6  y5  y4  y3  y2  y1  y0
+
+        y7..y0 = delta y (two's complement)
+
+byte 3:
+
+   bit   7   6   5   4   3   2   1   0
+       id2 id1 id0   1   0   0   1   0
+
+       id2..id0 = finger id
+
+byte 4:
+
+   bit   7   6   5   4   3   2   1   0
+        x7  x6  x5  x4  x3  x2  x1  x0
+
+        x7..x0 = delta x (two's complement)
+
+byte 5:
+
+   bit   7   6   5   4   3   2   1   0
+        y7  y6  y5  y4  y3  y2  y1  y0
+
+        y7..y0 = delta y (two's complement)
+
+        byte 0 ~ 2 for one finger
+        byte 3 ~ 5 for another
diff -druN linux-libre-3.1-gnu/Documentation/input/input.txt linux-libre-3.2-gnu/Documentation/input/input.txt
--- linux-libre-3.1-gnu/Documentation/input/input.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/input/input.txt	2012-01-04 18:55:44.000000000 -0500
@@ -111,7 +111,7 @@
 
  The monitor and speaker controls should be easy to add to the hid/input
 interface, but for the UPSs and LCDs it doesn't make much sense. For this,
-the hiddev interface was designed. See Documentation/usb/hiddev.txt
+the hiddev interface was designed. See Documentation/hid/hiddev.txt
 for more information about it.
 
   The usage of the usbhid module is very simple, it takes no parameters,
diff -druN linux-libre-3.1-gnu/Documentation/input/multi-touch-protocol.txt linux-libre-3.2-gnu/Documentation/input/multi-touch-protocol.txt
--- linux-libre-3.1-gnu/Documentation/input/multi-touch-protocol.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/input/multi-touch-protocol.txt	2012-01-04 18:55:44.000000000 -0500
@@ -65,6 +65,20 @@
 end.  Upon receiving an MT event, one simply updates the appropriate
 attribute of the current slot.
 
+Some devices identify and/or track more contacts than they can report to the
+driver.  A driver for such a device should associate one type B slot with each
+contact that is reported by the hardware.  Whenever the identity of the
+contact associated with a slot changes, the driver should invalidate that
+slot by changing its ABS_MT_TRACKING_ID.  If the hardware signals that it is
+tracking more contacts than it is currently reporting, the driver should use
+a BTN_TOOL_*TAP event to inform userspace of the total number of contacts
+being tracked by the hardware at that moment.  The driver should do this by
+explicitly sending the corresponding BTN_TOOL_*TAP event and setting
+use_count to false when calling input_mt_report_pointer_emulation().
+The driver should only advertise as many slots as the hardware can report.
+Userspace can detect that a driver can report more total contacts than slots
+by noting that the largest supported BTN_TOOL_*TAP event is larger than the
+total number of type B slots reported in the absinfo for the ABS_MT_SLOT axis.
 
 Protocol Example A
 ------------------
diff -druN linux-libre-3.1-gnu/Documentation/kernel-docs.txt linux-libre-3.2-gnu/Documentation/kernel-docs.txt
--- linux-libre-3.1-gnu/Documentation/kernel-docs.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/kernel-docs.txt	2012-01-04 18:55:44.000000000 -0500
@@ -300,7 +300,7 @@
        
      * Title: "The Kernel Hacking HOWTO"
        Author: Various Talented People, and Rusty.
-       Location: in kernel tree, Documentation/DocBook/kernel-hacking/
+       Location: in kernel tree, Documentation/DocBook/kernel-hacking.tmpl
        (must be built as "make {htmldocs | psdocs | pdfdocs})
        Keywords: HOWTO, kernel contexts, deadlock, locking, modules,
        symbols, return conventions.
@@ -351,7 +351,7 @@
        
      * Title: "Linux Kernel Locking HOWTO"
        Author: Various Talented People, and Rusty.
-       Location: in kernel tree, Documentation/DocBook/kernel-locking/
+       Location: in kernel tree, Documentation/DocBook/kernel-locking.tmpl
        (must be built as "make {htmldocs | psdocs | pdfdocs})
        Keywords: locks, locking, spinlock, semaphore, atomic, race
        condition, bottom halves, tasklets, softirqs.
diff -druN linux-libre-3.1-gnu/Documentation/kernel-parameters.txt linux-libre-3.2-gnu/Documentation/kernel-parameters.txt
--- linux-libre-3.1-gnu/Documentation/kernel-parameters.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/kernel-parameters.txt	2012-01-04 18:55:44.000000000 -0500
@@ -49,6 +49,7 @@
 	EDD	BIOS Enhanced Disk Drive Services (EDD) is enabled
 	EFI	EFI Partitioning (GPT) is enabled
 	EIDE	EIDE/ATAPI support is enabled.
+	EVM	Extended Verification Module
 	FB	The frame buffer device is enabled.
 	FTRACE	Function tracing enabled.
 	GCOV	GCOV profiling is enabled.
@@ -163,7 +164,7 @@
 			rsdt -- prefer RSDT over (default) XSDT
 			copy_dsdt -- copy DSDT to memory
 
-			See also Documentation/power/pm.txt, pci=noacpi
+			See also Documentation/power/runtime_pm.txt, pci=noacpi
 
 	acpi_rsdp=	[ACPI,EFI,KEXEC]
 			Pass the RSDP address to the kernel, mostly used
@@ -306,7 +307,20 @@
 			behaviour to be specified.  Bit 0 enables warnings,
 			bit 1 enables fixups, and bit 2 sends a segfault.
 
-	amd_iommu=	[HW,X86-84]
+	align_va_addr=	[X86-64]
+			Align virtual addresses by clearing slice [14:12] when
+			allocating a VMA at process creation time. This option
+			gives you up to 3% performance improvement on AMD F15h
+			machines (where it is enabled by default) for a
+			CPU-intensive style benchmark, and it can vary highly in
+			a microbenchmark depending on workload and compiler.
+
+			32: only for 32-bit processes
+			64: only for 64-bit processes
+			on: enable for both 32- and 64-bit processes
+			off: disable for both 32- and 64-bit processes
+
+	amd_iommu=	[HW,X86-64]
 			Pass parameters to the AMD IOMMU driver in the system.
 			Possible values are:
 			fullflush - enable flushing of IO/TLB entries when
@@ -319,7 +333,7 @@
 	amijoy.map=	[HW,JOY] Amiga joystick support
 			Map of devices attached to JOY0DAT and JOY1DAT
 			Format: <a>,<b>
-			See also Documentation/kernel/input/joystick.txt
+			See also Documentation/input/joystick.txt
 
 	analog.map=	[HW,JOY] Analog joystick and gamepad support
 			Specifies type or capabilities of an analog joystick
@@ -408,7 +422,7 @@
 	bttv.radio=	Most important insmod options are available as
 			kernel args too.
 	bttv.pll=	See Documentation/video4linux/bttv/Insmod-options
-	bttv.tuner=	and Documentation/video4linux/bttv/CARDLIST
+	bttv.tuner=
 
 	bulk_remove=off	[PPC]  This parameter disables the use of the pSeries
 			firmware feature for flushing multiple hpte entries
@@ -724,13 +738,13 @@
 
 	elevator=	[IOSCHED]
 			Format: {"cfq" | "deadline" | "noop"}
-			See Documentation/block/as-iosched.txt and
+			See Documentation/block/cfq-iosched.txt and
 			Documentation/block/deadline-iosched.txt for details.
 
-	elfcorehdr=	[IA-64,PPC,SH,X86]
+	elfcorehdr=[size[KMG]@]offset[KMG] [IA64,PPC,SH,X86,S390]
 			Specifies physical address of start of kernel core
-			image elf header. Generally kexec loader will
-			pass this option to capture kernel.
+			image elf header and optionally the size. Generally
+			kexec loader will pass this option to capture kernel.
 			See Documentation/kdump/kdump.txt for details.
 
 	enable_mtrr_cleanup [X86]
@@ -760,12 +774,17 @@
 			This option is obsoleted by the "netdev=" option, which
 			has equivalent usage. See its documentation for details.
 
+	evm=		[EVM]
+			Format: { "fix" }
+			Permit 'security.evm' to be updated regardless of
+			current integrity status.
+
 	failslab=
 	fail_page_alloc=
 	fail_make_request=[KNL]
 			General fault injection mechanism.
 			Format: <interval>,<probability>,<space>,<times>
-			See also /Documentation/fault-injection/.
+			See also Documentation/fault-injection/.
 
 	floppy=		[HW]
 			See Documentation/blockdev/floppy.txt.
@@ -954,6 +973,9 @@
 	ignore_loglevel	[KNL]
 			Ignore loglevel setting - this will print /all/
 			kernel messages to the console. Useful for debugging.
+			We also add it as printk module parameter, so users
+			could change it dynamically, usually by
+			/sys/module/printk/parameters/ignore_loglevel.
 
 	ihash_entries=	[KNL]
 			Set number of hash buckets for inode cache.
@@ -1014,10 +1036,11 @@
 			has the capability. With this option, super page will
 			not be supported.
 	intremap=	[X86-64, Intel-IOMMU]
-			Format: { on (default) | off | nosid }
 			on	enable Interrupt Remapping (default)
 			off	disable Interrupt Remapping
 			nosid	disable Source ID checking
+			no_x2apic_optout
+				BIOS x2APIC opt-out request will be ignored
 
 	inttest=	[IA-64]
 
@@ -1181,6 +1204,10 @@
 			[KVM,Intel] Disable FlexPriority feature (TPR shadow).
 			Default is 1 (enabled)
 
+	kvm-intel.nested=
+			[KVM,Intel] Enable VMX nesting (nVMX).
+			Default is 0 (disabled)
+
 	kvm-intel.unrestricted_guest=
 			[KVM,Intel] Disable unrestricted guest feature
 			(virtualized real and unpaged mode) on capable
@@ -1642,6 +1669,11 @@
 			debugging driver suspend/resume hooks).  This may
 			not work reliably with all consoles, but is known
 			to work with serial and VGA consoles.
+			To facilitate more flexible debugging, we also add
+			console_suspend, a printk module parameter to control
+			it. Users could use console_suspend (usually
+			/sys/module/printk/parameters/console_suspend) to
+			turn on/off it dynamically.
 
 	noaliencache	[MM, NUMA, SLAB] Disables the allocation of alien
 			caches in the slab allocator.  Saves per-node memory,
@@ -1777,6 +1809,11 @@
 
 	noresidual	[PPC] Don't use residual data on PReP machines.
 
+	nordrand	[X86] Disable the direct use of the RDRAND
+			instruction even if it is supported by the
+			processor.  RDRAND is still available to user
+			space applications.
+
 	noresume	[SWSUSP] Disables resume and restores original swap
 			space.
 
@@ -2240,6 +2277,13 @@
 			in <PAGE_SIZE> units (needed only for swap files).
 			See  Documentation/power/swsusp-and-swap-files.txt
 
+	resumedelay=	[HIBERNATION] Delay (in seconds) to pause before attempting to
+			read the resume files
+
+	resumewait	[HIBERNATION] Wait (indefinitely) for resume device to show up.
+			Useful for devices that are detected asynchronously
+			(e.g. USB and MMC devices).
+
 	hibernate=	[HIBERNATION]
 		noresume	Don't check if there's a hibernation image
 				present during boot.
@@ -2375,7 +2419,7 @@
 			Format: <integer>
 
 	sonypi.*=	[HW] Sony Programmable I/O Control Device driver
-			See Documentation/sonypi.txt
+			See Documentation/laptops/sonypi.txt
 
 	specialix=	[HW,SERIAL] Specialix multi-serial port adapter
 			See Documentation/serial/specialix.txt.
diff -druN linux-libre-3.1-gnu/Documentation/laptops/thinkpad-acpi.txt linux-libre-3.2-gnu/Documentation/laptops/thinkpad-acpi.txt
--- linux-libre-3.1-gnu/Documentation/laptops/thinkpad-acpi.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/laptops/thinkpad-acpi.txt	2012-01-04 18:55:44.000000000 -0500
@@ -411,9 +411,9 @@
 
 0x1004	0x03	FN+F4		Sleep button (ACPI sleep button
 				semantics, i.e. sleep-to-RAM).
-				It is always generate some kind
+				It always generates some kind
 				of event, either the hot key
-				event or a ACPI sleep button
+				event or an ACPI sleep button
 				event. The firmware may
 				refuse to generate further FN+F4
 				key presses until a S3 or S4 ACPI
@@ -736,7 +736,7 @@
 sysfs notes:
 
 The ThinkLight sysfs interface is documented by the LED class
-documentation, in Documentation/leds-class.txt.  The ThinkLight LED name
+documentation, in Documentation/leds/leds-class.txt.  The ThinkLight LED name
 is "tpacpi::thinklight".
 
 Due to limitations in the sysfs LED class, if the status of the ThinkLight
@@ -833,7 +833,7 @@
 sysfs notes:
 
 The ThinkPad LED sysfs interface is described in detail by the LED class
-documentation, in Documentation/leds-class.txt.
+documentation, in Documentation/leds/leds-class.txt.
 
 The LEDs are named (in LED ID order, from 0 to 12):
 "tpacpi::power", "tpacpi:orange:batt", "tpacpi:green:batt",
diff -druN linux-libre-3.1-gnu/Documentation/leds/leds-class.txt linux-libre-3.2-gnu/Documentation/leds/leds-class.txt
--- linux-libre-3.1-gnu/Documentation/leds/leds-class.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/leds/leds-class.txt	2012-01-04 18:55:44.000000000 -0500
@@ -61,8 +61,8 @@
 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.
+however, it is better to 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
diff -druN linux-libre-3.1-gnu/Documentation/media-framework.txt linux-libre-3.2-gnu/Documentation/media-framework.txt
--- linux-libre-3.1-gnu/Documentation/media-framework.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/media-framework.txt	2012-01-04 18:55:44.000000000 -0500
@@ -9,8 +9,8 @@
 ------------
 
 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.
+Documentation/DocBook/media/v4l/media-controller.xml. This document will focus
+on the kernel-side implementation of the media framework.
 
 
 Abstract media device model
diff -druN linux-libre-3.1-gnu/Documentation/memory-barriers.txt linux-libre-3.2-gnu/Documentation/memory-barriers.txt
--- linux-libre-3.1-gnu/Documentation/memory-barriers.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/memory-barriers.txt	2012-01-04 18:55:44.000000000 -0500
@@ -438,7 +438,7 @@
 	[*] For information on bus mastering DMA and coherency please read:
 
 	    Documentation/PCI/pci.txt
-	    Documentation/PCI/PCI-DMA-mapping.txt
+	    Documentation/DMA-API-HOWTO.txt
 	    Documentation/DMA-API.txt
 
 
diff -druN linux-libre-3.1-gnu/Documentation/networking/batman-adv.txt linux-libre-3.2-gnu/Documentation/networking/batman-adv.txt
--- linux-libre-3.1-gnu/Documentation/networking/batman-adv.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/networking/batman-adv.txt	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-[state: 17-04-2011]
+[state: 21-08-2011]
 
 BATMAN-ADV
 ----------
@@ -68,9 +68,9 @@
 folder:
 
 #  ls  /sys/class/net/bat0/mesh/
-#  aggregated_ogms  gw_bandwidth  hop_penalty
-#  bonding          gw_mode       orig_interval
-#  fragmentation    gw_sel_class  vis_mode
+# aggregated_ogms   fragmentation gw_sel_class   vis_mode
+# ap_isolation      gw_bandwidth  hop_penalty
+# bonding           gw_mode       orig_interval
 
 
 There is a special folder for debugging information:
diff -druN linux-libre-3.1-gnu/Documentation/networking/ip-sysctl.txt linux-libre-3.2-gnu/Documentation/networking/ip-sysctl.txt
--- linux-libre-3.1-gnu/Documentation/networking/ip-sysctl.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/networking/ip-sysctl.txt	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,7 @@
 	default FALSE
 
 min_pmtu - INTEGER
-	default 562 - minimum discovered Path MTU
+	default 552 - minimum discovered Path MTU
 
 route/max_size - INTEGER
 	Maximum number of routes allowed in the kernel.  Increase
@@ -282,11 +282,11 @@
 	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.
-	Default value is 1024 for systems with more than 128Mb of memory,
-	and 128 for low memory machines. If server suffers of overload,
-	try to increase this number.
+	Maximal number of remembered connection requests, which have not
+	received an acknowledgment from connecting client.
+	The minimal value is 128 for low memory machines, and it will
+	increase in proportion to the memory of machine.
+	If server suffers from overload, try increasing this number.
 
 tcp_max_tw_buckets - INTEGER
 	Maximal number of timewait sockets held by system simultaneously.
@@ -1045,6 +1045,11 @@
 accept_ra - INTEGER
 	Accept Router Advertisements; autoconfigure using them.
 
+	It also determines whether or not to transmit Router
+	Solicitations. If and only if the functional setting is to
+	accept Router Advertisements, Router Solicitations will be
+	transmitted.
+
 	Possible values are:
 		0 Do not accept Router Advertisements.
 		1 Accept Router Advertisements if forwarding is disabled.
@@ -1115,14 +1120,14 @@
 	Possible values are:
 		0 Forwarding disabled
 		1 Forwarding enabled
-		2 Forwarding enabled (Hybrid Mode)
 
 	FALSE (0):
 
 	By default, Host behaviour is assumed.  This means:
 
 	1. IsRouter flag is not set in Neighbour Advertisements.
-	2. Router Solicitations are being sent when necessary.
+	2. If accept_ra is TRUE (default), transmit Router
+	   Solicitations.
 	3. If accept_ra is TRUE (default), accept Router
 	   Advertisements (and do autoconfiguration).
 	4. If accept_redirects is TRUE (default), accept Redirects.
@@ -1133,16 +1138,10 @@
 	This means exactly the reverse from the above:
 
 	1. IsRouter flag is set in Neighbour Advertisements.
-	2. Router Solicitations are not sent.
+	2. Router Solicitations are not sent unless accept_ra is 2.
 	3. Router Advertisements are ignored unless accept_ra is 2.
 	4. Redirects are ignored.
 
-	TRUE (2):
-
-	Hybrid mode. Same behaviour as TRUE, except for:
-
-	2. Router Solicitations are being sent when necessary.
-
 	Default: 0 (disabled) if global forwarding is disabled (default),
 		 otherwise 1 (enabled).
 
diff -druN linux-libre-3.1-gnu/Documentation/networking/ipvs-sysctl.txt linux-libre-3.2-gnu/Documentation/networking/ipvs-sysctl.txt
--- linux-libre-3.1-gnu/Documentation/networking/ipvs-sysctl.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/networking/ipvs-sysctl.txt	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,23 @@
         enabled and the variable is automatically set to 2, otherwise
         the strategy is disabled and the variable is  set  to 1.
 
+conntrack - BOOLEAN
+	0 - disabled (default)
+	not 0 - enabled
+
+	If set, maintain connection tracking entries for
+	connections handled by IPVS.
+
+	This should be enabled if connections handled by IPVS are to be
+	also handled by stateful firewall rules. That is, iptables rules
+	that make use of connection tracking.  It is a performance
+	optimisation to disable this setting otherwise.
+
+	Connections handled by the IPVS FTP application module
+	will have connection tracking entries regardless of this setting.
+
+	Only available when IPVS is compiled with CONFIG_IP_VS_NFCT enabled.
+
 cache_bypass - BOOLEAN
         0 - disabled (default)
         not 0 - enabled
@@ -39,7 +56,7 @@
 	11         - IPVS packet handling (ip_vs_in/ip_vs_out)
 	12 or more - packet traversal
 
-	Only available when IPVS is compiled with the CONFIG_IPVS_DEBUG
+	Only available when IPVS is compiled with CONFIG_IP_VS_DEBUG enabled.
 
 	Higher debugging levels include the messages for lower debugging
 	levels, so setting debug level 2, includes level 0, 1 and 2
@@ -123,13 +140,11 @@
 secure_tcp - INTEGER
         0  - disabled (default)
 
-        The secure_tcp defense is to use a more complicated state
-        transition table and some possible short timeouts of each
-        state. In the VS/NAT, it delays the entering the ESTABLISHED
-        until the real server starts to send data and ACK packet
-        (after 3-way handshake).
+	The secure_tcp defense is to use a more complicated TCP state
+	transition table. For VS/NAT, it also delays entering the
+	TCP ESTABLISHED state until the three way handshake is completed.
 
-        The value definition is the same as that of drop_entry or
+        The value definition is the same as that of drop_entry and
         drop_packet.
 
 sync_threshold - INTEGER
@@ -141,3 +156,36 @@
         synchronized, every time the number of its incoming packets
         modulus 50 equals the threshold. The range of the threshold is
         from 0 to 49.
+
+snat_reroute - BOOLEAN
+	0 - disabled
+	not 0 - enabled (default)
+
+	If enabled, recalculate the route of SNATed packets from
+	realservers so that they are routed as if they originate from the
+	director. Otherwise they are routed as if they are forwarded by the
+	director.
+
+	If policy routing is in effect then it is possible that the route
+	of a packet originating from a director is routed differently to a
+	packet being forwarded by the director.
+
+	If policy routing is not in effect then the recalculated route will
+	always be the same as the original route so it is an optimisation
+	to disable snat_reroute and avoid the recalculation.
+
+sync_version - INTEGER
+	default 1
+
+	The version of the synchronisation protocol used when sending
+	synchronisation messages.
+
+	0 selects the original synchronisation protocol (version 0). This
+	should be used when sending synchronisation messages to a legacy
+	system that only understands the original synchronisation protocol.
+
+	1 selects the current synchronisation protocol (version 1). This
+	should be used where possible.
+
+	Kernels with this sync_version entry are able to receive messages
+	of both version 1 and version 2 of the synchronisation protocol.
diff -druN linux-libre-3.1-gnu/Documentation/networking/LICENSE.qlcnic linux-libre-3.2-gnu/Documentation/networking/LICENSE.qlcnic
--- linux-libre-3.1-gnu/Documentation/networking/LICENSE.qlcnic	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/networking/LICENSE.qlcnic	2012-01-04 18:55:44.000000000 -0500
@@ -1,61 +1,22 @@
-Copyright (c) 2009-2010 QLogic Corporation
+Copyright (c) 2009-2011 QLogic Corporation
 QLogic Linux qlcnic NIC Driver
 
-This program includes a device driver for Linux 2.6 that may be
-distributed with QLogic hardware specific firmware binary file.
 You may modify and redistribute the device driver code under the
 GNU General Public License (a copy of which is attached hereto as
 Exhibit A) published by the Free Software Foundation (version 2).
 
-You may redistribute the hardware specific firmware binary file
-under the following terms:
-
-       1. Redistribution of source code (only if applicable),
-          must retain the above copyright notice, this list of
-          conditions and the following disclaimer.
-
-       2. Redistribution 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 QLogic Corporation may not be used to
-          endorse or promote products derived from this software
-          without specific prior written permission
-
-REGARDLESS OF WHAT LICENSING MECHANISM IS USED OR APPLICABLE,
-THIS PROGRAM IS PROVIDED BY QLOGIC CORPORATION "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.
-
-USER ACKNOWLEDGES AND AGREES THAT USE OF THIS PROGRAM WILL NOT
-CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, ESTOPPEL, OR
-OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT,
-TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN
-ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN
-COMBINATION WITH THIS PROGRAM.
-
 
 EXHIBIT A
 
-                   GNU GENERAL PUBLIC LICENSE
-                      Version 2, June 1991
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
 
  Copyright (C) 1989, 1991 Free Software Foundation, Inc.
  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
-                           Preamble
+			    Preamble
 
   The licenses for most software are designed to take away your
 freedom to share and change it.  By contrast, the GNU General Public
@@ -105,7 +66,7 @@
   The precise terms and conditions for copying, distribution and
 modification follow.
 
-                   GNU GENERAL PUBLIC LICENSE
+		    GNU GENERAL PUBLIC LICENSE
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
   0. This License applies to any program or other work which contains
@@ -304,7 +265,7 @@
 of preserving the free status of all derivatives of our free software and
 of promoting the sharing and reuse of software generally.
 
-                           NO WARRANTY
+			    NO WARRANTY
 
   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
diff -druN linux-libre-3.1-gnu/Documentation/networking/mac80211-injection.txt linux-libre-3.2-gnu/Documentation/networking/mac80211-injection.txt
--- linux-libre-3.1-gnu/Documentation/networking/mac80211-injection.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/networking/mac80211-injection.txt	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,10 @@
    IEEE80211_RADIOTAP_F_FRAG: frame will be fragmented if longer than the
 			      current fragmentation threshold.
 
+ * IEEE80211_RADIOTAP_TX_FLAGS
+
+   IEEE80211_RADIOTAP_F_TX_NOACK: frame should be sent without waiting for
+				  an ACK even if it is a unicast frame
 
 The injection code can also skip all other currently defined radiotap fields
 facilitating replay of captured radiotap headers directly.
diff -druN linux-libre-3.1-gnu/Documentation/networking/netdevices.txt linux-libre-3.2-gnu/Documentation/networking/netdevices.txt
--- linux-libre-3.1-gnu/Documentation/networking/netdevices.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/networking/netdevices.txt	2012-01-04 18:55:44.000000000 -0500
@@ -73,7 +73,7 @@
 	has to lock by itself when needed. It is recommended to use a try lock
 	for this and return NETDEV_TX_LOCKED when the spin lock fails.
 	The locking there should also properly protect against 
-	set_multicast_list. Note that the use of NETIF_F_LLTX is deprecated.
+	set_rx_mode. Note that the use of NETIF_F_LLTX is deprecated.
 	Don't use it for new drivers.
 
 	Context: Process with BHs disabled or BH (timer),
@@ -92,7 +92,7 @@
 	Context: BHs disabled
 	Notes: netif_queue_stopped() is guaranteed true
 
-dev->set_multicast_list:
+dev->set_rx_mode:
 	Synchronization: netif_tx_lock spinlock.
 	Context: BHs disabled
 
diff -druN linux-libre-3.1-gnu/Documentation/networking/scaling.txt linux-libre-3.2-gnu/Documentation/networking/scaling.txt
--- linux-libre-3.1-gnu/Documentation/networking/scaling.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/networking/scaling.txt	2012-01-04 18:55:44.000000000 -0500
@@ -73,7 +73,7 @@
 an IRQ may be handled on any CPU. Because a non-negligible part of packet
 processing takes place in receive interrupt handling, it is advantageous
 to spread receive interrupts between CPUs. To manually adjust the IRQ
-affinity of each interrupt see Documentation/IRQ-affinity. Some systems
+affinity of each interrupt see Documentation/IRQ-affinity.txt. Some systems
 will be running irqbalance, a daemon that dynamically optimizes IRQ
 assignments and as a result may override any manual settings.
 
diff -druN linux-libre-3.1-gnu/Documentation/networking/stmmac.txt linux-libre-3.2-gnu/Documentation/networking/stmmac.txt
--- linux-libre-3.1-gnu/Documentation/networking/stmmac.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/networking/stmmac.txt	2012-01-04 18:55:44.000000000 -0500
@@ -76,7 +76,16 @@
 
 4.5) DMA descriptors
 Driver handles both normal and enhanced descriptors. The latter has been only
-tested on DWC Ether MAC 10/100/1000 Universal version 3.41a.
+tested on DWC Ether MAC 10/100/1000 Universal version 3.41a and later.
+
+STMMAC supports DMA descriptor to operate both in dual buffer (RING)
+and linked-list(CHAINED) mode. In RING each descriptor points to two
+data buffer pointers whereas in CHAINED mode they point to only one data
+buffer pointer. RING mode is the default.
+
+In CHAINED mode each descriptor will have pointer to next descriptor in
+the list, hence creating the explicit chaining in the descriptor itself,
+whereas such explicit chaining is not possible in RING mode.
 
 4.6) Ethtool support
 Ethtool is supported. Driver statistics and internal errors can be taken using:
@@ -235,7 +244,38 @@
  o enh_desc.c: functions for handling enhanced descriptors
  o norm_desc.c: functions for handling normal descriptors
 
-5) TODO:
+5) Debug Information
+
+The driver exports many information i.e. internal statistics,
+debug information, MAC and DMA registers etc.
+
+These can be read in several ways depending on the
+type of the information actually needed.
+
+For example a user can be use the ethtool support
+to get statistics: e.g. using: ethtool -S ethX
+(that shows the Management counters (MMC) if supported)
+or sees the MAC/DMA registers: e.g. using: ethtool -d ethX
+
+Compiling the Kernel with CONFIG_DEBUG_FS and enabling the
+STMMAC_DEBUG_FS option the driver will export the following
+debugfs entries:
+
+/sys/kernel/debug/stmmaceth/descriptors_status
+  To show the DMA TX/RX descriptor rings
+
+Developer can also use the "debug" module parameter to get
+further debug information.
+
+In the end, there are other macros (that cannot be enabled
+via menuconfig) to turn-on the RX/TX DMA debugging,
+specific MAC core debug printk etc. Others to enable the
+debug in the TX and RX processes.
+All these are only useful during the developing stage
+and should never enabled inside the code for general usage.
+In fact, these can generate an huge amount of debug messages.
+
+6) TODO:
  o XGMAC is not supported.
  o Review the timer optimisation code to use an embedded device that will be
   available in new chip generations.
diff -druN linux-libre-3.1-gnu/Documentation/oops-tracing.txt linux-libre-3.2-gnu/Documentation/oops-tracing.txt
--- linux-libre-3.1-gnu/Documentation/oops-tracing.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/oops-tracing.txt	2012-01-04 18:55:44.000000000 -0500
@@ -263,6 +263,8 @@
  12: 'I' if the kernel is working around a severe bug in the platform
      firmware (BIOS or similar).
 
+ 13: 'O' if an externally-built ("out-of-tree") module has been loaded.
+
 The primary reason for the 'Tainted: ' string is to tell kernel
 debuggers if this is a clean kernel or if anything unusual has
 occurred.  Tainting is permanent: even if an offending module is
diff -druN linux-libre-3.1-gnu/Documentation/PCI/pci.txt linux-libre-3.2-gnu/Documentation/PCI/pci.txt
--- linux-libre-3.1-gnu/Documentation/PCI/pci.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/PCI/pci.txt	2012-01-04 18:55:44.000000000 -0500
@@ -314,7 +314,7 @@
 as the PCI "bus address" might have been remapped to a "host physical"
 address by the arch/chip-set specific kernel support.
 
-See Documentation/IO-mapping.txt for how to access device registers
+See Documentation/io-mapping.txt for how to access device registers
 or device memory.
 
 The device driver needs to call pci_request_region() to verify
diff -druN linux-libre-3.1-gnu/Documentation/pinctrl.txt linux-libre-3.2-gnu/Documentation/pinctrl.txt
--- linux-libre-3.1-gnu/Documentation/pinctrl.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/pinctrl.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,950 @@
+PINCTRL (PIN CONTROL) subsystem
+This document outlines the pin control subsystem in Linux
+
+This subsystem deals with:
+
+- Enumerating and naming controllable pins
+
+- Multiplexing of pins, pads, fingers (etc) see below for details
+
+The intention is to also deal with:
+
+- Software-controlled biasing and driving mode specific pins, such as
+  pull-up/down, open drain etc, load capacitance configuration when controlled
+  by software, etc.
+
+
+Top-level interface
+===================
+
+Definition of PIN CONTROLLER:
+
+- A pin controller is a piece of hardware, usually a set of registers, that
+  can control PINs. It may be able to multiplex, bias, set load capacitance,
+  set drive strength etc for individual pins or groups of pins.
+
+Definition of PIN:
+
+- PINS are equal to pads, fingers, balls or whatever packaging input or
+  output line you want to control and these are denoted by unsigned integers
+  in the range 0..maxpin. This numberspace is local to each PIN CONTROLLER, so
+  there may be several such number spaces in a system. This pin space may
+  be sparse - i.e. there may be gaps in the space with numbers where no
+  pin exists.
+
+When a PIN CONTROLLER is instatiated, it will register a descriptor to the
+pin control framework, and this descriptor contains an array of pin descriptors
+describing the pins handled by this specific pin controller.
+
+Here is an example of a PGA (Pin Grid Array) chip seen from underneath:
+
+        A   B   C   D   E   F   G   H
+
+   8    o   o   o   o   o   o   o   o
+
+   7    o   o   o   o   o   o   o   o
+
+   6    o   o   o   o   o   o   o   o
+
+   5    o   o   o   o   o   o   o   o
+
+   4    o   o   o   o   o   o   o   o
+
+   3    o   o   o   o   o   o   o   o
+
+   2    o   o   o   o   o   o   o   o
+
+   1    o   o   o   o   o   o   o   o
+
+To register a pin controller and name all the pins on this package we can do
+this in our driver:
+
+#include <linux/pinctrl/pinctrl.h>
+
+const struct pinctrl_pin_desc __refdata foo_pins[] = {
+      PINCTRL_PIN(0, "A1"),
+      PINCTRL_PIN(1, "A2"),
+      PINCTRL_PIN(2, "A3"),
+      ...
+      PINCTRL_PIN(61, "H6"),
+      PINCTRL_PIN(62, "H7"),
+      PINCTRL_PIN(63, "H8"),
+};
+
+static struct pinctrl_desc foo_desc = {
+	.name = "foo",
+	.pins = foo_pins,
+	.npins = ARRAY_SIZE(foo_pins),
+	.maxpin = 63,
+	.owner = THIS_MODULE,
+};
+
+int __init foo_probe(void)
+{
+	struct pinctrl_dev *pctl;
+
+	pctl = pinctrl_register(&foo_desc, <PARENT>, NULL);
+	if (IS_ERR(pctl))
+		pr_err("could not register foo pin driver\n");
+}
+
+Pins usually have fancier names than this. You can find these in the dataheet
+for your chip. Notice that the core pinctrl.h file provides a fancy macro
+called PINCTRL_PIN() to create the struct entries. As you can see I enumerated
+the pins from 0 in the upper left corner to 63 in the lower right corner,
+this enumeration was arbitrarily chosen, in practice you need to think
+through your numbering system so that it matches the layout of registers
+and such things in your driver, or the code may become complicated. You must
+also consider matching of offsets to the GPIO ranges that may be handled by
+the pin controller.
+
+For a padring with 467 pads, as opposed to actual pins, I used an enumeration
+like this, walking around the edge of the chip, which seems to be industry
+standard too (all these pads had names, too):
+
+
+     0 ..... 104
+   466        105
+     .        .
+     .        .
+   358        224
+    357 .... 225
+
+
+Pin groups
+==========
+
+Many controllers need to deal with groups of pins, so the pin controller
+subsystem has a mechanism for enumerating groups of pins and retrieving the
+actual enumerated pins that are part of a certain group.
+
+For example, say that we have a group of pins dealing with an SPI interface
+on { 0, 8, 16, 24 }, and a group of pins dealing with an I2C interface on pins
+on { 24, 25 }.
+
+These two groups are presented to the pin control subsystem by implementing
+some generic pinctrl_ops like this:
+
+#include <linux/pinctrl/pinctrl.h>
+
+struct foo_group {
+	const char *name;
+	const unsigned int *pins;
+	const unsigned num_pins;
+};
+
+static unsigned int spi0_pins[] = { 0, 8, 16, 24 };
+static unsigned int i2c0_pins[] = { 24, 25 };
+
+static const struct foo_group foo_groups[] = {
+	{
+		.name = "spi0_grp",
+		.pins = spi0_pins,
+		.num_pins = ARRAY_SIZE(spi0_pins),
+	},
+	{
+		.name = "i2c0_grp",
+		.pins = i2c0_pins,
+		.num_pins = ARRAY_SIZE(i2c0_pins),
+	},
+};
+
+
+static int foo_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
+{
+	if (selector >= ARRAY_SIZE(foo_groups))
+		return -EINVAL;
+	return 0;
+}
+
+static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
+				       unsigned selector)
+{
+	return foo_groups[selector].name;
+}
+
+static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+			       unsigned ** const pins,
+			       unsigned * const num_pins)
+{
+	*pins = (unsigned *) foo_groups[selector].pins;
+	*num_pins = foo_groups[selector].num_pins;
+	return 0;
+}
+
+static struct pinctrl_ops foo_pctrl_ops = {
+	.list_groups = foo_list_groups,
+	.get_group_name = foo_get_group_name,
+	.get_group_pins = foo_get_group_pins,
+};
+
+
+static struct pinctrl_desc foo_desc = {
+       ...
+       .pctlops = &foo_pctrl_ops,
+};
+
+The pin control subsystem will call the .list_groups() function repeatedly
+beginning on 0 until it returns non-zero to determine legal selectors, then
+it will call the other functions to retrieve the name and pins of the group.
+Maintaining the data structure of the groups is up to the driver, this is
+just a simple example - in practice you may need more entries in your group
+structure, for example specific register ranges associated with each group
+and so on.
+
+
+Interaction with the GPIO subsystem
+===================================
+
+The GPIO drivers may want to perform operations of various types on the same
+physical pins that are also registered as pin controller pins.
+
+Since the pin controller subsystem have its pinspace local to the pin
+controller we need a mapping so that the pin control subsystem can figure out
+which pin controller handles control of a certain GPIO pin. Since a single
+pin controller may be muxing several GPIO ranges (typically SoCs that have
+one set of pins but internally several GPIO silicon blocks, each modeled as
+a struct gpio_chip) any number of GPIO ranges can be added to a pin controller
+instance like this:
+
+struct gpio_chip chip_a;
+struct gpio_chip chip_b;
+
+static struct pinctrl_gpio_range gpio_range_a = {
+	.name = "chip a",
+	.id = 0,
+	.base = 32,
+	.npins = 16,
+	.gc = &chip_a;
+};
+
+static struct pinctrl_gpio_range gpio_range_a = {
+	.name = "chip b",
+	.id = 0,
+	.base = 48,
+	.npins = 8,
+	.gc = &chip_b;
+};
+
+
+{
+	struct pinctrl_dev *pctl;
+	...
+	pinctrl_add_gpio_range(pctl, &gpio_range_a);
+	pinctrl_add_gpio_range(pctl, &gpio_range_b);
+}
+
+So this complex system has one pin controller handling two different
+GPIO chips. Chip a has 16 pins and chip b has 8 pins. They are mapped in
+the global GPIO pin space at:
+
+chip a: [32 .. 47]
+chip b: [48 .. 55]
+
+When GPIO-specific functions in the pin control subsystem are called, these
+ranges will be used to look up the apropriate pin controller by inspecting
+and matching the pin to the pin ranges across all controllers. When a
+pin controller handling the matching range is found, GPIO-specific functions
+will be called on that specific pin controller.
+
+For all functionalities dealing with pin biasing, pin muxing etc, the pin
+controller subsystem will subtract the range's .base offset from the passed
+in gpio pin number, and pass that on to the pin control driver, so the driver
+will get an offset into its handled number range. Further it is also passed
+the range ID value, so that the pin controller knows which range it should
+deal with.
+
+For example: if a user issues pinctrl_gpio_set_foo(50), the pin control
+subsystem will find that the second range on this pin controller matches,
+subtract the base 48 and call the
+pinctrl_driver_gpio_set_foo(pinctrl, range, 2) where the latter function has
+this signature:
+
+int pinctrl_driver_gpio_set_foo(struct pinctrl_dev *pctldev,
+    struct pinctrl_gpio_range *rangeid,
+    unsigned offset);
+
+Now the driver knows that we want to do some GPIO-specific operation on the
+second GPIO range handled by "chip b", at offset 2 in that specific range.
+
+(If the GPIO subsystem is ever refactored to use a local per-GPIO controller
+pin space, this mapping will need to be augmented accordingly.)
+
+
+PINMUX interfaces
+=================
+
+These calls use the pinmux_* naming prefix.  No other calls should use that
+prefix.
+
+
+What is pinmuxing?
+==================
+
+PINMUX, also known as padmux, ballmux, alternate functions or mission modes
+is a way for chip vendors producing some kind of electrical packages to use
+a certain physical pin (ball, pad, finger, etc) for multiple mutually exclusive
+functions, depending on the application. By "application" in this context
+we usually mean a way of soldering or wiring the package into an electronic
+system, even though the framework makes it possible to also change the function
+at runtime.
+
+Here is an example of a PGA (Pin Grid Array) chip seen from underneath:
+
+        A   B   C   D   E   F   G   H
+      +---+
+   8  | o | o   o   o   o   o   o   o
+      |   |
+   7  | o | o   o   o   o   o   o   o
+      |   |
+   6  | o | o   o   o   o   o   o   o
+      +---+---+
+   5  | o | o | o   o   o   o   o   o
+      +---+---+               +---+
+   4    o   o   o   o   o   o | o | o
+                              |   |
+   3    o   o   o   o   o   o | o | o
+                              |   |
+   2    o   o   o   o   o   o | o | o
+      +-------+-------+-------+---+---+
+   1  | o   o | o   o | o   o | o | o |
+      +-------+-------+-------+---+---+
+
+This is not tetris. The game to think of is chess. Not all PGA/BGA packages
+are chessboard-like, big ones have "holes" in some arrangement according to
+different design patterns, but we're using this as a simple example. Of the
+pins you see some will be taken by things like a few VCC and GND to feed power
+to the chip, and quite a few will be taken by large ports like an external
+memory interface. The remaining pins will often be subject to pin multiplexing.
+
+The example 8x8 PGA package above will have pin numbers 0 thru 63 assigned to
+its physical pins. It will name the pins { A1, A2, A3 ... H6, H7, H8 } using
+pinctrl_register_pins() and a suitable data set as shown earlier.
+
+In this 8x8 BGA package the pins { A8, A7, A6, A5 } can be used as an SPI port
+(these are four pins: CLK, RXD, TXD, FRM). In that case, pin B5 can be used as
+some general-purpose GPIO pin. However, in another setting, pins { A5, B5 } can
+be used as an I2C port (these are just two pins: SCL, SDA). Needless to say,
+we cannot use the SPI port and I2C port at the same time. However in the inside
+of the package the silicon performing the SPI logic can alternatively be routed
+out on pins { G4, G3, G2, G1 }.
+
+On the botton row at { A1, B1, C1, D1, E1, F1, G1, H1 } we have something
+special - it's an external MMC bus that can be 2, 4 or 8 bits wide, and it will
+consume 2, 4 or 8 pins respectively, so either { A1, B1 } are taken or
+{ A1, B1, C1, D1 } or all of them. If we use all 8 bits, we cannot use the SPI
+port on pins { G4, G3, G2, G1 } of course.
+
+This way the silicon blocks present inside the chip can be multiplexed "muxed"
+out on different pin ranges. Often contemporary SoC (systems on chip) will
+contain several I2C, SPI, SDIO/MMC, etc silicon blocks that can be routed to
+different pins by pinmux settings.
+
+Since general-purpose I/O pins (GPIO) are typically always in shortage, it is
+common to be able to use almost any pin as a GPIO pin if it is not currently
+in use by some other I/O port.
+
+
+Pinmux conventions
+==================
+
+The purpose of the pinmux functionality in the pin controller subsystem is to
+abstract and provide pinmux settings to the devices you choose to instantiate
+in your machine configuration. It is inspired by the clk, GPIO and regulator
+subsystems, so devices will request their mux setting, but it's also possible
+to request a single pin for e.g. GPIO.
+
+Definitions:
+
+- FUNCTIONS can be switched in and out by a driver residing with the pin
+  control subsystem in the drivers/pinctrl/* directory of the kernel. The
+  pin control driver knows the possible functions. In the example above you can
+  identify three pinmux functions, one for spi, one for i2c and one for mmc.
+
+- FUNCTIONS are assumed to be enumerable from zero in a one-dimensional array.
+  In this case the array could be something like: { spi0, i2c0, mmc0 }
+  for the three available functions.
+
+- FUNCTIONS have PIN GROUPS as defined on the generic level - so a certain
+  function is *always* associated with a certain set of pin groups, could
+  be just a single one, but could also be many. In the example above the
+  function i2c is associated with the pins { A5, B5 }, enumerated as
+  { 24, 25 } in the controller pin space.
+
+  The Function spi is associated with pin groups { A8, A7, A6, A5 }
+  and { G4, G3, G2, G1 }, which are enumerated as { 0, 8, 16, 24 } and
+  { 38, 46, 54, 62 } respectively.
+
+  Group names must be unique per pin controller, no two groups on the same
+  controller may have the same name.
+
+- The combination of a FUNCTION and a PIN GROUP determine a certain function
+  for a certain set of pins. The knowledge of the functions and pin groups
+  and their machine-specific particulars are kept inside the pinmux driver,
+  from the outside only the enumerators are known, and the driver core can:
+
+  - Request the name of a function with a certain selector (>= 0)
+  - A list of groups associated with a certain function
+  - Request that a certain group in that list to be activated for a certain
+    function
+
+  As already described above, pin groups are in turn self-descriptive, so
+  the core will retrieve the actual pin range in a certain group from the
+  driver.
+
+- FUNCTIONS and GROUPS on a certain PIN CONTROLLER are MAPPED to a certain
+  device by the board file, device tree or similar machine setup configuration
+  mechanism, similar to how regulators are connected to devices, usually by
+  name. Defining a pin controller, function and group thus uniquely identify
+  the set of pins to be used by a certain device. (If only one possible group
+  of pins is available for the function, no group name need to be supplied -
+  the core will simply select the first and only group available.)
+
+  In the example case we can define that this particular machine shall
+  use device spi0 with pinmux function fspi0 group gspi0 and i2c0 on function
+  fi2c0 group gi2c0, on the primary pin controller, we get mappings
+  like these:
+
+  {
+    {"map-spi0", spi0, pinctrl0, fspi0, gspi0},
+    {"map-i2c0", i2c0, pinctrl0, fi2c0, gi2c0}
+  }
+
+  Every map must be assigned a symbolic name, pin controller and function.
+  The group is not compulsory - if it is omitted the first group presented by
+  the driver as applicable for the function will be selected, which is
+  useful for simple cases.
+
+  The device name is present in map entries tied to specific devices. Maps
+  without device names are referred to as SYSTEM pinmuxes, such as can be taken
+  by the machine implementation on boot and not tied to any specific device.
+
+  It is possible to map several groups to the same combination of device,
+  pin controller and function. This is for cases where a certain function on
+  a certain pin controller may use different sets of pins in different
+  configurations.
+
+- PINS for a certain FUNCTION using a certain PIN GROUP on a certain
+  PIN CONTROLLER are provided on a first-come first-serve basis, so if some
+  other device mux setting or GPIO pin request has already taken your physical
+  pin, you will be denied the use of it. To get (activate) a new setting, the
+  old one has to be put (deactivated) first.
+
+Sometimes the documentation and hardware registers will be oriented around
+pads (or "fingers") rather than pins - these are the soldering surfaces on the
+silicon inside the package, and may or may not match the actual number of
+pins/balls underneath the capsule. Pick some enumeration that makes sense to
+you. Define enumerators only for the pins you can control if that makes sense.
+
+Assumptions:
+
+We assume that the number possible function maps to pin groups is limited by
+the hardware. I.e. we assume that there is no system where any function can be
+mapped to any pin, like in a phone exchange. So the available pins groups for
+a certain function will be limited to a few choices (say up to eight or so),
+not hundreds or any amount of choices. This is the characteristic we have found
+by inspecting available pinmux hardware, and a necessary assumption since we
+expect pinmux drivers to present *all* possible function vs pin group mappings
+to the subsystem.
+
+
+Pinmux drivers
+==============
+
+The pinmux core takes care of preventing conflicts on pins and calling
+the pin controller driver to execute different settings.
+
+It is the responsibility of the pinmux driver to impose further restrictions
+(say for example infer electronic limitations due to load etc) to determine
+whether or not the requested function can actually be allowed, and in case it
+is possible to perform the requested mux setting, poke the hardware so that
+this happens.
+
+Pinmux drivers are required to supply a few callback functions, some are
+optional. Usually the enable() and disable() functions are implemented,
+writing values into some certain registers to activate a certain mux setting
+for a certain pin.
+
+A simple driver for the above example will work by setting bits 0, 1, 2, 3 or 4
+into some register named MUX to select a certain function with a certain
+group of pins would work something like this:
+
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+struct foo_group {
+	const char *name;
+	const unsigned int *pins;
+	const unsigned num_pins;
+};
+
+static const unsigned spi0_0_pins[] = { 0, 8, 16, 24 };
+static const unsigned spi0_1_pins[] = { 38, 46, 54, 62 };
+static const unsigned i2c0_pins[] = { 24, 25 };
+static const unsigned mmc0_1_pins[] = { 56, 57 };
+static const unsigned mmc0_2_pins[] = { 58, 59 };
+static const unsigned mmc0_3_pins[] = { 60, 61, 62, 63 };
+
+static const struct foo_group foo_groups[] = {
+	{
+		.name = "spi0_0_grp",
+		.pins = spi0_0_pins,
+		.num_pins = ARRAY_SIZE(spi0_0_pins),
+	},
+	{
+		.name = "spi0_1_grp",
+		.pins = spi0_1_pins,
+		.num_pins = ARRAY_SIZE(spi0_1_pins),
+	},
+	{
+		.name = "i2c0_grp",
+		.pins = i2c0_pins,
+		.num_pins = ARRAY_SIZE(i2c0_pins),
+	},
+	{
+		.name = "mmc0_1_grp",
+		.pins = mmc0_1_pins,
+		.num_pins = ARRAY_SIZE(mmc0_1_pins),
+	},
+	{
+		.name = "mmc0_2_grp",
+		.pins = mmc0_2_pins,
+		.num_pins = ARRAY_SIZE(mmc0_2_pins),
+	},
+	{
+		.name = "mmc0_3_grp",
+		.pins = mmc0_3_pins,
+		.num_pins = ARRAY_SIZE(mmc0_3_pins),
+	},
+};
+
+
+static int foo_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
+{
+	if (selector >= ARRAY_SIZE(foo_groups))
+		return -EINVAL;
+	return 0;
+}
+
+static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
+				       unsigned selector)
+{
+	return foo_groups[selector].name;
+}
+
+static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+			       unsigned ** const pins,
+			       unsigned * const num_pins)
+{
+	*pins = (unsigned *) foo_groups[selector].pins;
+	*num_pins = foo_groups[selector].num_pins;
+	return 0;
+}
+
+static struct pinctrl_ops foo_pctrl_ops = {
+	.list_groups = foo_list_groups,
+	.get_group_name = foo_get_group_name,
+	.get_group_pins = foo_get_group_pins,
+};
+
+struct foo_pmx_func {
+	const char *name;
+	const char * const *groups;
+	const unsigned num_groups;
+};
+
+static const char * const spi0_groups[] = { "spi0_1_grp" };
+static const char * const i2c0_groups[] = { "i2c0_grp" };
+static const char * const mmc0_groups[] = { "mmc0_1_grp", "mmc0_2_grp",
+					"mmc0_3_grp" };
+
+static const struct foo_pmx_func foo_functions[] = {
+	{
+		.name = "spi0",
+		.groups = spi0_groups,
+		.num_groups = ARRAY_SIZE(spi0_groups),
+	},
+	{
+		.name = "i2c0",
+		.groups = i2c0_groups,
+		.num_groups = ARRAY_SIZE(i2c0_groups),
+	},
+	{
+		.name = "mmc0",
+		.groups = mmc0_groups,
+		.num_groups = ARRAY_SIZE(mmc0_groups),
+	},
+};
+
+int foo_list_funcs(struct pinctrl_dev *pctldev, unsigned selector)
+{
+	if (selector >= ARRAY_SIZE(foo_functions))
+		return -EINVAL;
+	return 0;
+}
+
+const char *foo_get_fname(struct pinctrl_dev *pctldev, unsigned selector)
+{
+	return myfuncs[selector].name;
+}
+
+static int foo_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+			  const char * const **groups,
+			  unsigned * const num_groups)
+{
+	*groups = foo_functions[selector].groups;
+	*num_groups = foo_functions[selector].num_groups;
+	return 0;
+}
+
+int foo_enable(struct pinctrl_dev *pctldev, unsigned selector,
+		unsigned group)
+{
+	u8 regbit = (1 << group);
+
+	writeb((readb(MUX)|regbit), MUX)
+	return 0;
+}
+
+int foo_disable(struct pinctrl_dev *pctldev, unsigned selector,
+		unsigned group)
+{
+	u8 regbit = (1 << group);
+
+	writeb((readb(MUX) & ~(regbit)), MUX)
+	return 0;
+}
+
+struct pinmux_ops foo_pmxops = {
+	.list_functions = foo_list_funcs,
+	.get_function_name = foo_get_fname,
+	.get_function_groups = foo_get_groups,
+	.enable = foo_enable,
+	.disable = foo_disable,
+};
+
+/* Pinmux operations are handled by some pin controller */
+static struct pinctrl_desc foo_desc = {
+	...
+	.pctlops = &foo_pctrl_ops,
+	.pmxops = &foo_pmxops,
+};
+
+In the example activating muxing 0 and 1 at the same time setting bits
+0 and 1, uses one pin in common so they would collide.
+
+The beauty of the pinmux subsystem is that since it keeps track of all
+pins and who is using them, it will already have denied an impossible
+request like that, so the driver does not need to worry about such
+things - when it gets a selector passed in, the pinmux subsystem makes
+sure no other device or GPIO assignment is already using the selected
+pins. Thus bits 0 and 1 in the control register will never be set at the
+same time.
+
+All the above functions are mandatory to implement for a pinmux driver.
+
+
+Pinmux interaction with the GPIO subsystem
+==========================================
+
+The function list could become long, especially if you can convert every
+individual pin into a GPIO pin independent of any other pins, and then try
+the approach to define every pin as a function.
+
+In this case, the function array would become 64 entries for each GPIO
+setting and then the device functions.
+
+For this reason there is an additional function a pinmux driver can implement
+to enable only GPIO on an individual pin: .gpio_request_enable(). The same
+.free() function as for other functions is assumed to be usable also for
+GPIO pins.
+
+This function will pass in the affected GPIO range identified by the pin
+controller core, so you know which GPIO pins are being affected by the request
+operation.
+
+Alternatively it is fully allowed to use named functions for each GPIO
+pin, the pinmux_request_gpio() will attempt to obtain the function "gpioN"
+where "N" is the global GPIO pin number if no special GPIO-handler is
+registered.
+
+
+Pinmux board/machine configuration
+==================================
+
+Boards and machines define how a certain complete running system is put
+together, including how GPIOs and devices are muxed, how regulators are
+constrained and how the clock tree looks. Of course pinmux settings are also
+part of this.
+
+A pinmux config for a machine looks pretty much like a simple regulator
+configuration, so for the example array above we want to enable i2c and
+spi on the second function mapping:
+
+#include <linux/pinctrl/machine.h>
+
+static struct pinmux_map pmx_mapping[] = {
+	{
+		.ctrl_dev_name = "pinctrl.0",
+		.function = "spi0",
+		.dev_name = "foo-spi.0",
+	},
+	{
+		.ctrl_dev_name = "pinctrl.0",
+		.function = "i2c0",
+		.dev_name = "foo-i2c.0",
+	},
+	{
+		.ctrl_dev_name = "pinctrl.0",
+		.function = "mmc0",
+		.dev_name = "foo-mmc.0",
+	},
+};
+
+The dev_name here matches to the unique device name that can be used to look
+up the device struct (just like with clockdev or regulators). The function name
+must match a function provided by the pinmux driver handling this pin range.
+
+As you can see we may have several pin controllers on the system and thus
+we need to specify which one of them that contain the functions we wish
+to map. The map can also use struct device * directly, so there is no
+inherent need to use strings to specify .dev_name or .ctrl_dev_name, these
+are for the situation where you do not have a handle to the struct device *,
+for example if they are not yet instantiated or cumbersome to obtain.
+
+You register this pinmux mapping to the pinmux subsystem by simply:
+
+       ret = pinmux_register_mappings(&pmx_mapping, ARRAY_SIZE(pmx_mapping));
+
+Since the above construct is pretty common there is a helper macro to make
+it even more compact which assumes you want to use pinctrl.0 and position
+0 for mapping, for example:
+
+static struct pinmux_map pmx_mapping[] = {
+       PINMUX_MAP_PRIMARY("I2CMAP", "i2c0", "foo-i2c.0"),
+};
+
+
+Complex mappings
+================
+
+As it is possible to map a function to different groups of pins an optional
+.group can be specified like this:
+
+...
+{
+	.name = "spi0-pos-A",
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "spi0",
+	.group = "spi0_0_grp",
+	.dev_name = "foo-spi.0",
+},
+{
+	.name = "spi0-pos-B",
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "spi0",
+	.group = "spi0_1_grp",
+	.dev_name = "foo-spi.0",
+},
+...
+
+This example mapping is used to switch between two positions for spi0 at
+runtime, as described further below under the heading "Runtime pinmuxing".
+
+Further it is possible to match several groups of pins to the same function
+for a single device, say for example in the mmc0 example above, where you can
+additively expand the mmc0 bus from 2 to 4 to 8 pins. If we want to use all
+three groups for a total of 2+2+4 = 8 pins (for an 8-bit MMC bus as is the
+case), we define a mapping like this:
+
+...
+{
+	.name "2bit"
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "mmc0",
+	.group = "mmc0_0_grp",
+	.dev_name = "foo-mmc.0",
+},
+{
+	.name "4bit"
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "mmc0",
+	.group = "mmc0_0_grp",
+	.dev_name = "foo-mmc.0",
+},
+{
+	.name "4bit"
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "mmc0",
+	.group = "mmc0_1_grp",
+	.dev_name = "foo-mmc.0",
+},
+{
+	.name "8bit"
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "mmc0",
+	.group = "mmc0_0_grp",
+	.dev_name = "foo-mmc.0",
+},
+{
+	.name "8bit"
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "mmc0",
+	.group = "mmc0_1_grp",
+	.dev_name = "foo-mmc.0",
+},
+{
+	.name "8bit"
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "mmc0",
+	.group = "mmc0_2_grp",
+	.dev_name = "foo-mmc.0",
+},
+...
+
+The result of grabbing this mapping from the device with something like
+this (see next paragraph):
+
+	pmx = pinmux_get(&device, "8bit");
+
+Will be that you activate all the three bottom records in the mapping at
+once. Since they share the same name, pin controller device, funcion and
+device, and since we allow multiple groups to match to a single device, they
+all get selected, and they all get enabled and disable simultaneously by the
+pinmux core.
+
+
+Pinmux requests from drivers
+============================
+
+Generally it is discouraged to let individual drivers get and enable pinmuxes.
+So if possible, handle the pinmuxes in platform code or some other place where
+you have access to all the affected struct device * pointers. In some cases
+where a driver needs to switch between different mux mappings at runtime
+this is not possible.
+
+A driver may request a certain mux to be activated, usually just the default
+mux like this:
+
+#include <linux/pinctrl/pinmux.h>
+
+struct foo_state {
+       struct pinmux *pmx;
+       ...
+};
+
+foo_probe()
+{
+	/* Allocate a state holder named "state" etc */
+	struct pinmux pmx;
+
+	pmx = pinmux_get(&device, NULL);
+	if IS_ERR(pmx)
+		return PTR_ERR(pmx);
+	pinmux_enable(pmx);
+
+	state->pmx = pmx;
+}
+
+foo_remove()
+{
+	pinmux_disable(state->pmx);
+	pinmux_put(state->pmx);
+}
+
+If you want to grab a specific mux mapping and not just the first one found for
+this device you can specify a specific mapping name, for example in the above
+example the second i2c0 setting: pinmux_get(&device, "spi0-pos-B");
+
+This get/enable/disable/put sequence can just as well be handled by bus drivers
+if you don't want each and every driver to handle it and you know the
+arrangement on your bus.
+
+The semantics of the get/enable respective disable/put is as follows:
+
+- pinmux_get() is called in process context to reserve the pins affected with
+  a certain mapping and set up the pinmux core and the driver. It will allocate
+  a struct from the kernel memory to hold the pinmux state.
+
+- pinmux_enable()/pinmux_disable() is quick and can be called from fastpath
+  (irq context) when you quickly want to set up/tear down the hardware muxing
+  when running a device driver. Usually it will just poke some values into a
+  register.
+
+- pinmux_disable() is called in process context to tear down the pin requests
+  and release the state holder struct for the mux setting.
+
+Usually the pinmux core handled the get/put pair and call out to the device
+drivers bookkeeping operations, like checking available functions and the
+associated pins, whereas the enable/disable pass on to the pin controller
+driver which takes care of activating and/or deactivating the mux setting by
+quickly poking some registers.
+
+The pins are allocated for your device when you issue the pinmux_get() call,
+after this you should be able to see this in the debugfs listing of all pins.
+
+
+System pinmux hogging
+=====================
+
+A system pinmux map entry, i.e. a pinmux setting that does not have a device
+associated with it, can be hogged by the core when the pin controller is
+registered. This means that the core will attempt to call pinmux_get() and
+pinmux_enable() on it immediately after the pin control device has been
+registered.
+
+This is enabled by simply setting the .hog_on_boot field in the map to true,
+like this:
+
+{
+	.name "POWERMAP"
+	.ctrl_dev_name = "pinctrl.0",
+	.function = "power_func",
+	.hog_on_boot = true,
+},
+
+Since it may be common to request the core to hog a few always-applicable
+mux settings on the primary pin controller, there is a convenience macro for
+this:
+
+PINMUX_MAP_PRIMARY_SYS_HOG("POWERMAP", "power_func")
+
+This gives the exact same result as the above construction.
+
+
+Runtime pinmuxing
+=================
+
+It is possible to mux a certain function in and out at runtime, say to move
+an SPI port from one set of pins to another set of pins. Say for example for
+spi0 in the example above, we expose two different groups of pins for the same
+function, but with different named in the mapping as described under
+"Advanced mapping" above. So we have two mappings named "spi0-pos-A" and
+"spi0-pos-B".
+
+This snippet first muxes the function in the pins defined by group A, enables
+it, disables and releases it, and muxes it in on the pins defined by group B:
+
+foo_switch()
+{
+	struct pinmux pmx;
+
+	/* Enable on position A */
+	pmx = pinmux_get(&device, "spi0-pos-A");
+	if IS_ERR(pmx)
+		return PTR_ERR(pmx);
+	pinmux_enable(pmx);
+
+	/* This releases the pins again */
+	pinmux_disable(pmx);
+	pinmux_put(pmx);
+
+	/* Enable on position B */
+	pmx = pinmux_get(&device, "spi0-pos-B");
+	if IS_ERR(pmx)
+		return PTR_ERR(pmx);
+	pinmux_enable(pmx);
+	...
+}
+
+The above has to be done from process context.
diff -druN linux-libre-3.1-gnu/Documentation/power/00-INDEX linux-libre-3.2-gnu/Documentation/power/00-INDEX
--- linux-libre-3.1-gnu/Documentation/power/00-INDEX	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/power/00-INDEX	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,8 @@
 	- How to get suspend to ram working (and debug it when it isn't)
 states.txt
 	- System power management states
+suspend-and-cpuhotplug.txt
+	- Explains the interaction between Suspend-to-RAM (S3) and CPU hotplug
 swsusp-and-swap-files.txt
 	- Using swap files with software suspend (to disk)
 swsusp-dmcrypt.txt
diff -druN linux-libre-3.1-gnu/Documentation/power/basic-pm-debugging.txt linux-libre-3.2-gnu/Documentation/power/basic-pm-debugging.txt
--- linux-libre-3.1-gnu/Documentation/power/basic-pm-debugging.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/power/basic-pm-debugging.txt	2012-01-04 18:55:44.000000000 -0500
@@ -173,7 +173,7 @@
 information about the reasons of the suspend (resume) failure.  Alternatively,
 it may be possible to use a FireWire port for debugging with firescope
 (ftp://ftp.firstfloor.org/pub/ak/firescope/).  On x86 it is also possible to
-use the PM_TRACE mechanism documented in Documentation/s2ram.txt .
+use the PM_TRACE mechanism documented in Documentation/power/s2ram.txt .
 
 2. Testing suspend to RAM (STR)
 
@@ -201,3 +201,27 @@
 analogous to the one described in section 1.  If you find some failing drivers,
 you will have to unload them every time before an STR transition (ie. before
 you run s2ram), and please report the problems with them.
+
+There is a debugfs entry which shows the suspend to RAM statistics. Here is an
+example of its output.
+	# mount -t debugfs none /sys/kernel/debug
+	# cat /sys/kernel/debug/suspend_stats
+	success: 20
+	fail: 5
+	failed_freeze: 0
+	failed_prepare: 0
+	failed_suspend: 5
+	failed_suspend_noirq: 0
+	failed_resume: 0
+	failed_resume_noirq: 0
+	failures:
+	  last_failed_dev:	alarm
+				adc
+	  last_failed_errno:	-16
+				-16
+	  last_failed_step:	suspend
+				suspend
+Field success means the success number of suspend to RAM, and field fail means
+the failure number. Others are the failure number of different steps of suspend
+to RAM. suspend_stats just lists the last 2 failed devices, error number and
+failed step of suspend.
diff -druN linux-libre-3.1-gnu/Documentation/power/devices.txt linux-libre-3.2-gnu/Documentation/power/devices.txt
--- linux-libre-3.1-gnu/Documentation/power/devices.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/power/devices.txt	2012-01-04 18:55:44.000000000 -0500
@@ -123,9 +123,10 @@
 Subsystem-Level Methods
 -----------------------
 The core methods to suspend and resume devices reside in struct dev_pm_ops
-pointed to by the pm member of struct bus_type, struct device_type and
-struct class.  They are mostly of interest to the people writing infrastructure
-for buses, like PCI or USB, or device type and device class drivers.
+pointed to by the ops member of struct dev_pm_domain, or by the pm member of
+struct bus_type, struct device_type and struct class.  They are mostly of
+interest to the people writing infrastructure for platforms and buses, like PCI
+or USB, or device type and device class drivers.
 
 Bus drivers implement these methods as appropriate for the hardware and the
 drivers using it; PCI works differently from USB, and so on.  Not many people
@@ -139,39 +140,57 @@
 
 /sys/devices/.../power/wakeup files
 -----------------------------------
-All devices in the driver model have two flags to control handling of wakeup
-events (hardware signals that can force the device and/or system out of a low
-power state).  These flags are initialized by bus or device driver code using
+All device objects in the driver model contain fields that control the handling
+of system wakeup events (hardware signals that can force the system out of a
+sleep state).  These fields are initialized by bus or device driver code using
 device_set_wakeup_capable() and device_set_wakeup_enable(), defined in
 include/linux/pm_wakeup.h.
 
-The "can_wakeup" flag just records whether the device (and its driver) can
+The "power.can_wakeup" flag just records whether the device (and its driver) can
 physically support wakeup events.  The device_set_wakeup_capable() routine
-affects this flag.  The "should_wakeup" flag controls whether the device should
-try to use its wakeup mechanism.  device_set_wakeup_enable() affects this flag;
-for the most part drivers should not change its value.  The initial value of
-should_wakeup is supposed to be false for the majority of devices; the major
-exceptions are power buttons, keyboards, and Ethernet adapters whose WoL
-(wake-on-LAN) feature has been set up with ethtool.
+affects this flag.  The "power.wakeup" field is a pointer to an object of type
+struct wakeup_source used for controlling whether or not the device should use
+its system wakeup mechanism and for notifying the PM core of system wakeup
+events signaled by the device.  This object 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().
 
 Whether or not a device is capable of issuing wakeup events is a hardware
 matter, and the kernel is responsible for keeping track of it.  By contrast,
 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.  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.
+"power/wakeup" file.  User space can write the strings "enabled" or "disabled"
+to it to indicate whether or not, respectively, the device is supposed to signal
+system wakeup.  This file is only present if the "power.wakeup" object exists
+for the given device and is created (or removed) along with that object, 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.
+The "power/wakeup" file is supposed to contain the "disabled" string initially
+for the majority of devices; the major exceptions are power buttons, keyboards,
+and Ethernet adapters whose WoL (wake-on-LAN) feature has been set up with
+ethtool.  It should also default to "enabled" for devices that don't generate
+wakeup requests on their own but merely forward wakeup requests from one bus to
+another (like PCI Express ports).
+
+The device_may_wakeup() routine returns true only if the "power.wakeup" object
+exists and the corresponding "power/wakeup" file contains the string "enabled".
 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.
+Device drivers, however, are not supposed to call device_set_wakeup_enable()
+directly in any case.
 
+It ought to be noted that system wakeup is conceptually different from "remote
+wakeup" used by runtime power management, although it may be supported by the
+same physical mechanism.  Remote wakeup is a feature allowing devices in
+low-power states to trigger specific interrupts to signal conditions in which
+they should be put into the full-power state.  Those interrupts may or may not
+be used to signal system wakeup events, depending on the hardware design.  On
+some systems it is impossible to trigger them from system sleep states.  In any
+case, remote wakeup should always be enabled for runtime power management for
+all devices and drivers that support it.
 
 /sys/devices/.../power/control files
 ------------------------------------
@@ -247,20 +266,31 @@
 support all these callbacks and not all drivers use all the callbacks.  The
 various phases always run after tasks have been frozen and before they are
 unfrozen.  Furthermore, the *_noirq phases run at a time when IRQ handlers have
-been disabled (except for those marked with the IRQ_WAKEUP flag).
+been disabled (except for those marked with the IRQF_NO_SUSPEND flag).
 
-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).
+All phases use PM domain, bus, type, or class callbacks (that is, methods
+defined in dev->pm_domain->ops, dev->bus->pm, dev->type->pm, or dev->class->pm).
+These callbacks are regarded by the PM core as mutually exclusive.  Moreover,
+PM domain callbacks always take precedence over bus, type and class callbacks,
+while type callbacks take precedence over bus and class callbacks, and class
+callbacks take precedence over bus callbacks.  To be precise, the following
+rules are used to determine which callback to execute in the given phase:
+
+    1.	If dev->pm_domain is present, the PM core will attempt to execute the
+	callback included in dev->pm_domain->ops.  If that callback is not
+	present, no action will be carried out for the given device.
+
+    2.	Otherwise, if both dev->type and dev->type->pm are present, the callback
+	included in dev->type->pm will be executed.
+
+    3.	Otherwise, if both dev->class and dev->class->pm are present, the
+	callback included in dev->class->pm will be executed.
+
+    4.	Otherwise, if both dev->bus and dev->bus->pm are present, the callback
+	included in dev->bus->pm will be executed.
+
+This allows PM domains and device types to override callbacks provided by bus
+types or device 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.
@@ -279,15 +309,10 @@
 	time.)  Unlike the other suspend-related phases, during the prepare
 	phase the device tree is traversed top-down.
 
-	In addition to that, if device drivers need to allocate additional
-	memory to be able to hadle device suspend correctly, that should be
-	done in the prepare phase.
-
 	After the prepare callback method returns, no new children may be
 	registered below the device.  The method may also prepare the device or
-	driver in some way for the upcoming system power transition (for
-	example, by allocating additional memory required for this purpose), but
-	it should not put the device into a low-power state.
+	driver in some way for the upcoming system power transition, but it
+	should not put the device into a low-power state.
 
     2.	The suspend methods should quiesce the device to stop it from performing
 	I/O.  They also may save the device registers and put it into the
diff -druN linux-libre-3.1-gnu/Documentation/power/freezing-of-tasks.txt linux-libre-3.2-gnu/Documentation/power/freezing-of-tasks.txt
--- linux-libre-3.1-gnu/Documentation/power/freezing-of-tasks.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/power/freezing-of-tasks.txt	2012-01-04 18:55:44.000000000 -0500
@@ -22,12 +22,12 @@
 either wakes them up, if they are kernel threads, or sends fake signals to them,
 if they are user space processes.  A task that has TIF_FREEZE set, should react
 to it by calling the function called refrigerator() (defined in
-kernel/power/process.c), which sets the task's PF_FROZEN flag, changes its state
+kernel/freezer.c), which sets the task's PF_FROZEN flag, changes its state
 to TASK_UNINTERRUPTIBLE and makes it loop until PF_FROZEN is cleared for it.
 Then, we say that the task is 'frozen' and therefore the set of functions
 handling this mechanism is referred to as 'the freezer' (these functions are
-defined in kernel/power/process.c and include/linux/freezer.h).  User space
-processes are generally frozen before kernel threads.
+defined in kernel/power/process.c, kernel/freezer.c & include/linux/freezer.h).
+User space processes are generally frozen before kernel threads.
 
 It is not recommended to call refrigerator() directly.  Instead, it is
 recommended to use the try_to_freeze() function (defined in
@@ -95,7 +95,7 @@
 additional memory and we prevent them from doing that by freezing them earlier.
 [Of course, this also means that device drivers should not allocate substantial
 amounts of memory from their .suspend() callbacks before hibernation, but this
-is e separate issue.]
+is a separate issue.]
 
 3. The third reason is to prevent user space processes and some kernel threads
 from interfering with the suspending and resuming of devices.  A user space
diff -druN linux-libre-3.1-gnu/Documentation/power/pm_qos_interface.txt linux-libre-3.2-gnu/Documentation/power/pm_qos_interface.txt
--- linux-libre-3.1-gnu/Documentation/power/pm_qos_interface.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/power/pm_qos_interface.txt	2012-01-04 18:55:44.000000000 -0500
@@ -4,14 +4,19 @@
 performance expectations by drivers, subsystems and user space applications on
 one of the parameters.
 
-Currently we have {cpu_dma_latency, network_latency, network_throughput} as the
-initial set of pm_qos parameters.
+Two different PM QoS frameworks are available:
+1. PM QoS classes for cpu_dma_latency, network_latency, network_throughput.
+2. the per-device PM QoS framework provides the API to manage the per-device latency
+constraints.
 
 Each parameters have defined units:
  * latency: usec
  * timeout: usec
  * throughput: kbs (kilo bit / sec)
 
+
+1. PM QoS framework
+
 The infrastructure exposes multiple misc device nodes one per implemented
 parameter.  The set of parameters implement is defined by pm_qos_power_init()
 and pm_qos_params.h.  This is done because having the available parameters
@@ -23,14 +28,18 @@
 changes to the request list or elements of the list.  Typically the
 aggregated target value is simply the max or min of the request values held
 in the parameter list elements.
+Note: the aggregated target value is implemented as an atomic variable so that
+reading the aggregated value does not require any locking mechanism.
+
 
 From kernel mode the use of this interface is simple:
 
-handle = pm_qos_add_request(param_class, target_value):
-Will insert an element into the list for that identified PM_QOS class with the
+void pm_qos_add_request(handle, param_class, target_value):
+Will insert an element into the list for that identified PM QoS class with the
 target value.  Upon change to this list the new target is recomputed and any
 registered notifiers are called only if the target value is now different.
-Clients of pm_qos need to save the returned handle.
+Clients of pm_qos need to save the returned handle for future use in other
+pm_qos API functions.
 
 void pm_qos_update_request(handle, new_target_value):
 Will update the list element pointed to by the handle with the new target value
@@ -42,6 +51,20 @@
 call the notification tree if the target was changed as a result of removing
 the request.
 
+int pm_qos_request(param_class):
+Returns the aggregated value for a given PM QoS class.
+
+int pm_qos_request_active(handle):
+Returns if the request is still active, i.e. it has not been removed from a
+PM QoS class constraints list.
+
+int pm_qos_add_notifier(param_class, notifier):
+Adds a notification callback function to the PM QoS class. The callback is
+called when the aggregated value for the PM QoS class is changed.
+
+int pm_qos_remove_notifier(int param_class, notifier):
+Removes the notification callback function for the PM QoS class.
+
 
 From user mode:
 Only processes can register a pm_qos request.  To provide for automatic
@@ -63,4 +86,63 @@
 node.
 
 
+2. PM QoS per-device latency framework
+
+For each device a list of performance requests is maintained along with
+an aggregated target value.  The aggregated target value is updated with
+changes to the request list or elements of the list.  Typically the
+aggregated target value is simply the max or min of the request values held
+in the parameter list elements.
+Note: the aggregated target value is implemented as an atomic variable so that
+reading the aggregated value does not require any locking mechanism.
+
+
+From kernel mode the use of this interface is the following:
+
+int dev_pm_qos_add_request(device, handle, value):
+Will insert an element into the list for that identified device with the
+target value.  Upon change to this list the new target is recomputed and any
+registered notifiers are called only if the target value is now different.
+Clients of dev_pm_qos need to save the handle for future use in other
+dev_pm_qos API functions.
+
+int dev_pm_qos_update_request(handle, new_value):
+Will update the list element pointed to by the handle with the new target value
+and recompute the new aggregated target, calling the notification trees if the
+target is changed.
+
+int dev_pm_qos_remove_request(handle):
+Will remove the element.  After removal it will update the aggregate target and
+call the notification trees if the target was changed as a result of removing
+the request.
+
+s32 dev_pm_qos_read_value(device):
+Returns the aggregated value for a given device's constraints list.
+
+
+Notification mechanisms:
+The per-device PM QoS framework has 2 different and distinct notification trees:
+a per-device notification tree and a global notification tree.
+
+int dev_pm_qos_add_notifier(device, notifier):
+Adds a notification callback function for the device.
+The callback is called when the aggregated value of the device constraints list
+is changed.
+
+int dev_pm_qos_remove_notifier(device, notifier):
+Removes the notification callback function for the device.
+
+int dev_pm_qos_add_global_notifier(notifier):
+Adds a notification callback function in the global notification tree of the
+framework.
+The callback is called when the aggregated value for any device is changed.
+
+int dev_pm_qos_remove_global_notifier(notifier):
+Removes the notification callback function from the global notification tree
+of the framework.
+
+
+From user mode:
+No API for user space access to the per-device latency constraints is provided
+yet - still under discussion.
 
diff -druN linux-libre-3.1-gnu/Documentation/power/regulator/machine.txt linux-libre-3.2-gnu/Documentation/power/regulator/machine.txt
--- linux-libre-3.1-gnu/Documentation/power/regulator/machine.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/power/regulator/machine.txt	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
 each regulator.
 
 struct regulator_consumer_supply {
-	struct device *dev;	/* consumer */
+	const char *dev_name;	/* consumer dev_name() */
 	const char *supply;	/* consumer supply - e.g. "vcc" */
 };
 
@@ -24,13 +24,13 @@
 
 static struct regulator_consumer_supply regulator1_consumers[] = {
 {
-	.dev	= &platform_consumerB_device.dev,
-	.supply	= "Vcc",
+	.dev_name	= "dev_name(consumer B)",
+	.supply		= "Vcc",
 },};
 
 static struct regulator_consumer_supply regulator2_consumers[] = {
 {
-	.dev	= &platform_consumerA_device.dev,
+	.dev	= "dev_name(consumer A"),
 	.supply	= "Vcc",
 },};
 
@@ -43,6 +43,7 @@
 
 static struct regulator_init_data regulator1_data = {
 	.constraints = {
+		.name = "Regulator-1",
 		.min_uV = 3300000,
 		.max_uV = 3300000,
 		.valid_modes_mask = REGULATOR_MODE_NORMAL,
@@ -51,13 +52,19 @@
 	.consumer_supplies = regulator1_consumers,
 };
 
+The name field should be set to something that is usefully descriptive
+for the board for configuration of supplies for other regulators and
+for use in logging and other diagnostic output.  Normally the name
+used for the supply rail in the schematic is a good choice.  If no
+name is provided then the subsystem will choose one.
+
 Regulator-1 supplies power to Regulator-2. This relationship must be registered
 with the core so that Regulator-1 is also enabled when Consumer A enables its
 supply (Regulator-2). The supply regulator is set by the supply_regulator
-field below:-
+field below and co:-
 
 static struct regulator_init_data regulator2_data = {
-	.supply_regulator = "regulator_name",
+	.supply_regulator = "Regulator-1",
 	.constraints = {
 		.min_uV = 1800000,
 		.max_uV = 2000000,
diff -druN linux-libre-3.1-gnu/Documentation/power/runtime_pm.txt linux-libre-3.2-gnu/Documentation/power/runtime_pm.txt
--- linux-libre-3.1-gnu/Documentation/power/runtime_pm.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/power/runtime_pm.txt	2012-01-04 18:55:44.000000000 -0500
@@ -43,21 +43,34 @@
 	...
 };
 
-The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks are
-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.
+The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks
+are executed by the PM core for the device's subsystem that may be either of
+the following:
+
+  1. PM domain of the device, if the device's PM domain object, dev->pm_domain,
+     is present.
+
+  2. Device type of the device, if both dev->type and dev->type->pm are present.
+
+  3. Device class of the device, if both dev->class and dev->class->pm are
+     present.
+
+  4. Bus type of the device, if both dev->bus and dev->bus->pm are present.
+
+The PM core always checks which callback to use in the order given above, so the
+priority order of callbacks from high to low is: PM domain, device type, class
+and bus type.  Moreover, the high-priority one will always take precedence over
+a low-priority one.  The PM domain, 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
-to tell the PM core that a device's ->runtime_suspend() and ->runtime_resume()
-callbacks should be invoked in atomic context with interrupts disabled.
-This implies that these callback routines must not block or sleep, but it also
-means that the synchronous helper functions listed at the end of Section 4 can
-be used within an interrupt handler or in an atomic context.
+to tell the PM core that their ->runtime_suspend(), ->runtime_resume() and
+->runtime_idle() callbacks may be invoked in atomic context with interrupts
+disabled for a given device.  This implies that the callback routines in
+question must not block or sleep, but it also means that the synchronous helper
+functions listed at the end of Section 4 may be used for that device within an
+interrupt handler or generally in an atomic context.
 
 The subsystem-level suspend callback is _entirely_ _responsible_ for handling
 the suspend of the device as appropriate, which may, but need not include
@@ -477,12 +490,14 @@
 If pm_runtime_irq_safe() has been called for a device then the following helper
 functions may also be used in interrupt context:
 
+pm_runtime_idle()
 pm_runtime_suspend()
 pm_runtime_autosuspend()
 pm_runtime_resume()
 pm_runtime_get_sync()
 pm_runtime_put_sync()
 pm_runtime_put_sync_suspend()
+pm_runtime_put_sync_autosuspend()
 
 5. Runtime PM Initialization, Device Probing and Removal
 
@@ -782,6 +797,16 @@
 Similarly, if the power.use_autosuspend field isn't set then the autosuspend
 helper functions will behave just like the non-autosuspend counterparts.
 
+Under some circumstances a driver or subsystem may want to prevent a device
+from autosuspending immediately, even though the usage counter is zero and the
+autosuspend delay time has expired.  If the ->runtime_suspend() callback
+returns -EAGAIN or -EBUSY, and if the next autosuspend delay expiration time is
+in the future (as it normally would be if the callback invoked
+pm_runtime_mark_last_busy()), the PM core will automatically reschedule the
+autosuspend.  The ->runtime_suspend() callback can't do this rescheduling
+itself because no suspend requests of any kind are accepted while the device is
+suspending (i.e., while the callback is running).
+
 The implementation is well suited for asynchronous use in interrupt contexts.
 However such use inevitably involves races, because the PM core can't
 synchronize ->runtime_suspend() callbacks with the arrival of I/O requests.
diff -druN linux-libre-3.1-gnu/Documentation/power/suspend-and-cpuhotplug.txt linux-libre-3.2-gnu/Documentation/power/suspend-and-cpuhotplug.txt
--- linux-libre-3.1-gnu/Documentation/power/suspend-and-cpuhotplug.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/power/suspend-and-cpuhotplug.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,275 @@
+Interaction of Suspend code (S3) with the CPU hotplug infrastructure
+
+     (C) 2011 Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
+
+
+I. How does the regular CPU hotplug code differ from how the Suspend-to-RAM
+   infrastructure uses it internally? And where do they share common code?
+
+Well, a picture is worth a thousand words... So ASCII art follows :-)
+
+[This depicts the current design in the kernel, and focusses only on the
+interactions involving the freezer and CPU hotplug and also tries to explain
+the locking involved. It outlines the notifications involved as well.
+But please note that here, only the call paths are illustrated, with the aim
+of describing where they take different paths and where they share code.
+What happens when regular CPU hotplug and Suspend-to-RAM race with each other
+is not depicted here.]
+
+On a high level, the suspend-resume cycle goes like this:
+
+|Freeze| -> |Disable nonboot| -> |Do suspend| -> |Enable nonboot| -> |Thaw |
+|tasks |    |     cpus      |    |          |    |     cpus     |    |tasks|
+
+
+More details follow:
+
+                                Suspend call path
+                                -----------------
+
+                                  Write 'mem' to
+                                /sys/power/state
+                                    syfs file
+                                        |
+                                        v
+                               Acquire pm_mutex lock
+                                        |
+                                        v
+                             Send PM_SUSPEND_PREPARE
+                                   notifications
+                                        |
+                                        v
+                                   Freeze tasks
+                                        |
+                                        |
+                                        v
+                              disable_nonboot_cpus()
+                                   /* start */
+                                        |
+                                        v
+                            Acquire cpu_add_remove_lock
+                                        |
+                                        v
+                             Iterate over CURRENTLY
+                                   online CPUs
+                                        |
+                                        |
+                                        |                ----------
+                                        v                          | L
+             ======>               _cpu_down()                     |
+            |              [This takes cpuhotplug.lock             |
+  Common    |               before taking down the CPU             |
+   code     |               and releases it when done]             | O
+            |            While it is at it, notifications          |
+            |            are sent when notable events occur,       |
+             ======>     by running all registered callbacks.      |
+                                        |                          | O
+                                        |                          |
+                                        |                          |
+                                        v                          |
+                            Note down these cpus in                | P
+                                frozen_cpus mask         ----------
+                                        |
+                                        v
+                           Disable regular cpu hotplug
+                        by setting cpu_hotplug_disabled=1
+                                        |
+                                        v
+                            Release cpu_add_remove_lock
+                                        |
+                                        v
+                       /* disable_nonboot_cpus() complete */
+                                        |
+                                        v
+                                   Do suspend
+
+
+
+Resuming back is likewise, with the counterparts being (in the order of
+execution during resume):
+* enable_nonboot_cpus() which involves:
+   |  Acquire cpu_add_remove_lock
+   |  Reset cpu_hotplug_disabled to 0, thereby enabling regular cpu hotplug
+   |  Call _cpu_up() [for all those cpus in the frozen_cpus mask, in a loop]
+   |  Release cpu_add_remove_lock
+   v
+
+* thaw tasks
+* send PM_POST_SUSPEND notifications
+* Release pm_mutex lock.
+
+
+It is to be noted here that the pm_mutex lock is acquired at the very
+beginning, when we are just starting out to suspend, and then released only
+after the entire cycle is complete (i.e., suspend + resume).
+
+
+
+                          Regular CPU hotplug call path
+                          -----------------------------
+
+                                Write 0 (or 1) to
+                       /sys/devices/system/cpu/cpu*/online
+                                    sysfs file
+                                        |
+                                        |
+                                        v
+                                    cpu_down()
+                                        |
+                                        v
+                           Acquire cpu_add_remove_lock
+                                        |
+                                        v
+                          If cpu_hotplug_disabled is 1
+                                return gracefully
+                                        |
+                                        |
+                                        v
+             ======>                _cpu_down()
+            |              [This takes cpuhotplug.lock
+  Common    |               before taking down the CPU
+   code     |               and releases it when done]
+            |            While it is at it, notifications
+            |           are sent when notable events occur,
+             ======>    by running all registered callbacks.
+                                        |
+                                        |
+                                        v
+                          Release cpu_add_remove_lock
+                               [That's it!, for
+                              regular CPU hotplug]
+
+
+
+So, as can be seen from the two diagrams (the parts marked as "Common code"),
+regular CPU hotplug and the suspend code path converge at the _cpu_down() and
+_cpu_up() functions. They differ in the arguments passed to these functions,
+in that during regular CPU hotplug, 0 is passed for the 'tasks_frozen'
+argument. But during suspend, since the tasks are already frozen by the time
+the non-boot CPUs are offlined or onlined, the _cpu_*() functions are called
+with the 'tasks_frozen' argument set to 1.
+[See below for some known issues regarding this.]
+
+
+Important files and functions/entry points:
+------------------------------------------
+
+kernel/power/process.c : freeze_processes(), thaw_processes()
+kernel/power/suspend.c : suspend_prepare(), suspend_enter(), suspend_finish()
+kernel/cpu.c: cpu_[up|down](), _cpu_[up|down](), [disable|enable]_nonboot_cpus()
+
+
+
+II. What are the issues involved in CPU hotplug?
+    -------------------------------------------
+
+There are some interesting situations involving CPU hotplug and microcode
+update on the CPUs, as discussed below:
+
+[Please bear in mind that the kernel requests the microcode images from
+userspace, using the request_firmware() function defined in
+drivers/base/firmware_class.c]
+
+
+a. When all the CPUs are identical:
+
+   This is the most common situation and it is quite straightforward: we want
+   to apply the same microcode revision to each of the CPUs.
+   To give an example of x86, the collect_cpu_info() function defined in
+   arch/x86/kernel/microcode_core.c helps in discovering the type of the CPU
+   and thereby in applying the correct microcode revision to it.
+   But note that the kernel does not maintain a common microcode image for the
+   all CPUs, in order to handle case 'b' described below.
+
+
+b. When some of the CPUs are different than the rest:
+
+   In this case since we probably need to apply different microcode revisions
+   to different CPUs, the kernel maintains a copy of the correct microcode
+   image for each CPU (after appropriate CPU type/model discovery using
+   functions such as collect_cpu_info()).
+
+
+c. When a CPU is physically hot-unplugged and a new (and possibly different
+   type of) CPU is hot-plugged into the system:
+
+   In the current design of the kernel, whenever a CPU is taken offline during
+   a regular CPU hotplug operation, upon receiving the CPU_DEAD notification
+   (which is sent by the CPU hotplug code), the microcode update driver's
+   callback for that event reacts by freeing the kernel's copy of the
+   microcode image for that CPU.
+
+   Hence, when a new CPU is brought online, since the kernel finds that it
+   doesn't have the microcode image, it does the CPU type/model discovery
+   afresh and then requests the userspace for the appropriate microcode image
+   for that CPU, which is subsequently applied.
+
+   For example, in x86, the mc_cpu_callback() function (which is the microcode
+   update driver's callback registered for CPU hotplug events) calls
+   microcode_update_cpu() which would call microcode_init_cpu() in this case,
+   instead of microcode_resume_cpu() when it finds that the kernel doesn't
+   have a valid microcode image. This ensures that the CPU type/model
+   discovery is performed and the right microcode is applied to the CPU after
+   getting it from userspace.
+
+
+d. Handling microcode update during suspend/hibernate:
+
+   Strictly speaking, during a CPU hotplug operation which does not involve
+   physically removing or inserting CPUs, the CPUs are not actually powered
+   off during a CPU offline. They are just put to the lowest C-states possible.
+   Hence, in such a case, it is not really necessary to re-apply microcode
+   when the CPUs are brought back online, since they wouldn't have lost the
+   image during the CPU offline operation.
+
+   This is the usual scenario encountered during a resume after a suspend.
+   However, in the case of hibernation, since all the CPUs are completely
+   powered off, during restore it becomes necessary to apply the microcode
+   images to all the CPUs.
+
+   [Note that we don't expect someone to physically pull out nodes and insert
+   nodes with a different type of CPUs in-between a suspend-resume or a
+   hibernate/restore cycle.]
+
+   In the current design of the kernel however, during a CPU offline operation
+   as part of the suspend/hibernate cycle (the CPU_DEAD_FROZEN notification),
+   the existing copy of microcode image in the kernel is not freed up.
+   And during the CPU online operations (during resume/restore), since the
+   kernel finds that it already has copies of the microcode images for all the
+   CPUs, it just applies them to the CPUs, avoiding any re-discovery of CPU
+   type/model and the need for validating whether the microcode revisions are
+   right for the CPUs or not (due to the above assumption that physical CPU
+   hotplug will not be done in-between suspend/resume or hibernate/restore
+   cycles).
+
+
+III. Are there any known problems when regular CPU hotplug and suspend race
+     with each other?
+
+Yes, they are listed below:
+
+1. When invoking regular CPU hotplug, the 'tasks_frozen' argument passed to
+   the _cpu_down() and _cpu_up() functions is *always* 0.
+   This might not reflect the true current state of the system, since the
+   tasks could have been frozen by an out-of-band event such as a suspend
+   operation in progress. Hence, it will lead to wrong notifications being
+   sent during the cpu online/offline events (eg, CPU_ONLINE notification
+   instead of CPU_ONLINE_FROZEN) which in turn will lead to execution of
+   inappropriate code by the callbacks registered for such CPU hotplug events.
+
+2. If a regular CPU hotplug stress test happens to race with the freezer due
+   to a suspend operation in progress at the same time, then we could hit the
+   situation described below:
+
+    * A regular cpu online operation continues its journey from userspace
+      into the kernel, since the freezing has not yet begun.
+    * Then freezer gets to work and freezes userspace.
+    * If cpu online has not yet completed the microcode update stuff by now,
+      it will now start waiting on the frozen userspace in the
+      TASK_UNINTERRUPTIBLE state, in order to get the microcode image.
+    * Now the freezer continues and tries to freeze the remaining tasks. But
+      due to this wait mentioned above, the freezer won't be able to freeze
+      the cpu online hotplug task and hence freezing of tasks fails.
+
+   As a result of this task freezing failure, the suspend operation gets
+   aborted.
diff -druN linux-libre-3.1-gnu/Documentation/power/userland-swsusp.txt linux-libre-3.2-gnu/Documentation/power/userland-swsusp.txt
--- linux-libre-3.1-gnu/Documentation/power/userland-swsusp.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/power/userland-swsusp.txt	2012-01-04 18:55:44.000000000 -0500
@@ -77,7 +77,8 @@
 	resume_swap_area, as defined in kernel/power/suspend_ioctls.h,
 	containing the resume device specification and the offset); for swap
 	partitions the offset is always 0, but it is different from zero for
-	swap files (see Documentation/swsusp-and-swap-files.txt for details).
+	swap files (see Documentation/power/swsusp-and-swap-files.txt for
+	details).
 
 SNAPSHOT_PLATFORM_SUPPORT - enable/disable the hibernation platform support,
 	depending on the argument value (enable, if the argument is nonzero)
diff -druN linux-libre-3.1-gnu/Documentation/rapidio/rapidio.txt linux-libre-3.2-gnu/Documentation/rapidio/rapidio.txt
--- linux-libre-3.1-gnu/Documentation/rapidio/rapidio.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/rapidio/rapidio.txt	2012-01-04 18:55:44.000000000 -0500
@@ -144,7 +144,7 @@
 
 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
+in the system, it sets the Discovered bit in the Port General Control CSR
 to indicate that enumeration is completed and agents are allowed to execute
 passive discovery of the network.
 
diff -druN linux-libre-3.1-gnu/Documentation/rapidio/tsi721.txt linux-libre-3.2-gnu/Documentation/rapidio/tsi721.txt
--- linux-libre-3.1-gnu/Documentation/rapidio/tsi721.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/rapidio/tsi721.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,49 @@
+RapidIO subsystem mport driver for IDT Tsi721 PCI Express-to-SRIO bridge.
+=========================================================================
+
+I. Overview
+
+This driver implements all currently defined RapidIO mport callback functions.
+It supports maintenance read and write operations, inbound and outbound RapidIO
+doorbells, inbound maintenance port-writes and RapidIO messaging.
+
+To generate SRIO maintenance transactions this driver uses one of Tsi721 DMA
+channels. This mechanism provides access to larger range of hop counts and
+destination IDs without need for changes in outbound window translation.
+
+RapidIO messaging support uses dedicated messaging channels for each mailbox.
+For inbound messages this driver uses destination ID matching to forward messages
+into the corresponding message queue. Messaging callbacks are implemented to be
+fully compatible with RIONET driver (Ethernet over RapidIO messaging services).
+
+II. Known problems
+
+  None.
+
+III. To do
+
+ Add DMA data transfers (non-messaging).
+ Add inbound region (SRIO-to-PCIe) mapping.
+
+IV. Version History
+
+  1.0.0 - Initial driver release.
+
+V.  License
+-----------------------------------------------
+
+  Copyright(c) 2011 Integrated Device Technology, Inc. All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the Free
+  Software Foundation; either version 2 of the License, or (at your option)
+  any later version.
+
+  This program is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
diff -druN linux-libre-3.1-gnu/Documentation/RCU/lockdep-splat.txt linux-libre-3.2-gnu/Documentation/RCU/lockdep-splat.txt
--- linux-libre-3.1-gnu/Documentation/RCU/lockdep-splat.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/RCU/lockdep-splat.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,110 @@
+Lockdep-RCU was added to the Linux kernel in early 2010
+(http://lwn.net/Articles/371986/).  This facility checks for some common
+misuses of the RCU API, most notably using one of the rcu_dereference()
+family to access an RCU-protected pointer without the proper protection.
+When such misuse is detected, an lockdep-RCU splat is emitted.
+
+The usual cause of a lockdep-RCU slat is someone accessing an
+RCU-protected data structure without either (1) being in the right kind of
+RCU read-side critical section or (2) holding the right update-side lock.
+This problem can therefore be serious: it might result in random memory
+overwriting or worse.  There can of course be false positives, this
+being the real world and all that.
+
+So let's look at an example RCU lockdep splat from 3.0-rc5, one that
+has long since been fixed:
+
+===============================
+[ INFO: suspicious RCU usage. ]
+-------------------------------
+block/cfq-iosched.c:2776 suspicious rcu_dereference_protected() usage!
+
+other info that might help us debug this:
+
+
+rcu_scheduler_active = 1, debug_locks = 0
+3 locks held by scsi_scan_6/1552:
+ #0:  (&shost->scan_mutex){+.+.+.}, at: [<ffffffff8145efca>]
+scsi_scan_host_selected+0x5a/0x150
+ #1:  (&eq->sysfs_lock){+.+...}, at: [<ffffffff812a5032>]
+elevator_exit+0x22/0x60
+ #2:  (&(&q->__queue_lock)->rlock){-.-...}, at: [<ffffffff812b6233>]
+cfq_exit_queue+0x43/0x190
+
+stack backtrace:
+Pid: 1552, comm: scsi_scan_6 Not tainted 3.0.0-rc5 #17
+Call Trace:
+ [<ffffffff810abb9b>] lockdep_rcu_dereference+0xbb/0xc0
+ [<ffffffff812b6139>] __cfq_exit_single_io_context+0xe9/0x120
+ [<ffffffff812b626c>] cfq_exit_queue+0x7c/0x190
+ [<ffffffff812a5046>] elevator_exit+0x36/0x60
+ [<ffffffff812a802a>] blk_cleanup_queue+0x4a/0x60
+ [<ffffffff8145cc09>] scsi_free_queue+0x9/0x10
+ [<ffffffff81460944>] __scsi_remove_device+0x84/0xd0
+ [<ffffffff8145dca3>] scsi_probe_and_add_lun+0x353/0xb10
+ [<ffffffff817da069>] ? error_exit+0x29/0xb0
+ [<ffffffff817d98ed>] ? _raw_spin_unlock_irqrestore+0x3d/0x80
+ [<ffffffff8145e722>] __scsi_scan_target+0x112/0x680
+ [<ffffffff812c690d>] ? trace_hardirqs_off_thunk+0x3a/0x3c
+ [<ffffffff817da069>] ? error_exit+0x29/0xb0
+ [<ffffffff812bcc60>] ? kobject_del+0x40/0x40
+ [<ffffffff8145ed16>] scsi_scan_channel+0x86/0xb0
+ [<ffffffff8145f0b0>] scsi_scan_host_selected+0x140/0x150
+ [<ffffffff8145f149>] do_scsi_scan_host+0x89/0x90
+ [<ffffffff8145f170>] do_scan_async+0x20/0x160
+ [<ffffffff8145f150>] ? do_scsi_scan_host+0x90/0x90
+ [<ffffffff810975b6>] kthread+0xa6/0xb0
+ [<ffffffff817db154>] kernel_thread_helper+0x4/0x10
+ [<ffffffff81066430>] ? finish_task_switch+0x80/0x110
+ [<ffffffff817d9c04>] ? retint_restore_args+0xe/0xe
+ [<ffffffff81097510>] ? __init_kthread_worker+0x70/0x70
+ [<ffffffff817db150>] ? gs_change+0xb/0xb
+
+Line 2776 of block/cfq-iosched.c in v3.0-rc5 is as follows:
+
+	if (rcu_dereference(ioc->ioc_data) == cic) {
+
+This form says that it must be in a plain vanilla RCU read-side critical
+section, but the "other info" list above shows that this is not the
+case.  Instead, we hold three locks, one of which might be RCU related.
+And maybe that lock really does protect this reference.  If so, the fix
+is to inform RCU, perhaps by changing __cfq_exit_single_io_context() to
+take the struct request_queue "q" from cfq_exit_queue() as an argument,
+which would permit us to invoke rcu_dereference_protected as follows:
+
+	if (rcu_dereference_protected(ioc->ioc_data,
+				      lockdep_is_held(&q->queue_lock)) == cic) {
+
+With this change, there would be no lockdep-RCU splat emitted if this
+code was invoked either from within an RCU read-side critical section
+or with the ->queue_lock held.  In particular, this would have suppressed
+the above lockdep-RCU splat because ->queue_lock is held (see #2 in the
+list above).
+
+On the other hand, perhaps we really do need an RCU read-side critical
+section.  In this case, the critical section must span the use of the
+return value from rcu_dereference(), or at least until there is some
+reference count incremented or some such.  One way to handle this is to
+add rcu_read_lock() and rcu_read_unlock() as follows:
+
+	rcu_read_lock();
+	if (rcu_dereference(ioc->ioc_data) == cic) {
+		spin_lock(&ioc->lock);
+		rcu_assign_pointer(ioc->ioc_data, NULL);
+		spin_unlock(&ioc->lock);
+	}
+	rcu_read_unlock();
+
+With this change, the rcu_dereference() is always within an RCU
+read-side critical section, which again would have suppressed the
+above lockdep-RCU splat.
+
+But in this particular case, we don't actually deference the pointer
+returned from rcu_dereference().  Instead, that pointer is just compared
+to the cic pointer, which means that the rcu_dereference() can be replaced
+by rcu_access_pointer() as follows:
+
+	if (rcu_access_pointer(ioc->ioc_data) == cic) {
+
+Because it is legal to invoke rcu_access_pointer() without protection,
+this change would also suppress the above lockdep-RCU splat.
diff -druN linux-libre-3.1-gnu/Documentation/RCU/lockdep.txt linux-libre-3.2-gnu/Documentation/RCU/lockdep.txt
--- linux-libre-3.1-gnu/Documentation/RCU/lockdep.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/RCU/lockdep.txt	2012-01-04 18:55:44.000000000 -0500
@@ -32,9 +32,27 @@
 	srcu_dereference(p, sp):
 		Check for SRCU read-side critical section.
 	rcu_dereference_check(p, c):
-		Use explicit check expression "c".  This is useful in
-		code that is invoked by both readers and updaters.
-	rcu_dereference_raw(p)
+		Use explicit check expression "c" along with
+		rcu_read_lock_held().  This is useful in code that is
+		invoked by both RCU readers and updaters.
+	rcu_dereference_bh_check(p, c):
+		Use explicit check expression "c" along with
+		rcu_read_lock_bh_held().  This is useful in code that
+		is invoked by both RCU-bh readers and updaters.
+	rcu_dereference_sched_check(p, c):
+		Use explicit check expression "c" along with
+		rcu_read_lock_sched_held().  This is useful in code that
+		is invoked by both RCU-sched readers and updaters.
+	srcu_dereference_check(p, c):
+		Use explicit check expression "c" along with
+		srcu_read_lock_held()().  This is useful in code that
+		is invoked by both SRCU readers and updaters.
+	rcu_dereference_index_check(p, c):
+		Use explicit check expression "c", but the caller
+		must supply one of the rcu_read_lock_held() functions.
+		This is useful in code that uses RCU-protected arrays
+		that is invoked by both RCU readers and updaters.
+	rcu_dereference_raw(p):
 		Don't check.  (Use sparingly, if at all.)
 	rcu_dereference_protected(p, c):
 		Use explicit check expression "c", and omit all barriers
@@ -48,13 +66,11 @@
 		value of the pointer itself, for example, against NULL.
 
 The rcu_dereference_check() check expression can be any boolean
-expression, but would normally include one of the rcu_read_lock_held()
-family of functions and a lockdep expression.  However, any boolean
-expression can be used.  For a moderately ornate example, consider
-the following:
+expression, but would normally include a lockdep expression.  However,
+any boolean expression can be used.  For a moderately ornate example,
+consider the following:
 
 	file = rcu_dereference_check(fdt->fd[fd],
-				     rcu_read_lock_held() ||
 				     lockdep_is_held(&files->file_lock) ||
 				     atomic_read(&files->count) == 1);
 
@@ -62,7 +78,7 @@
 and, if CONFIG_PROVE_RCU is configured, verifies that this expression
 is used in:
 
-1.	An RCU read-side critical section, or
+1.	An RCU read-side critical section (implicit), or
 2.	with files->file_lock held, or
 3.	on an unshared files_struct.
 
diff -druN linux-libre-3.1-gnu/Documentation/RCU/NMI-RCU.txt linux-libre-3.2-gnu/Documentation/RCU/NMI-RCU.txt
--- linux-libre-3.1-gnu/Documentation/RCU/NMI-RCU.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/RCU/NMI-RCU.txt	2012-01-04 18:55:44.000000000 -0500
@@ -95,7 +95,7 @@
 to free up the handler's data as soon as synchronize_sched() returns.
 
 Important note: for this to work, the architecture in question must
-invoke irq_enter() and irq_exit() on NMI entry and exit, respectively.
+invoke nmi_enter() and nmi_exit() on NMI entry and exit, respectively.
 
 
 Answer to Quick Quiz
diff -druN linux-libre-3.1-gnu/Documentation/RCU/torture.txt linux-libre-3.2-gnu/Documentation/RCU/torture.txt
--- linux-libre-3.1-gnu/Documentation/RCU/torture.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/RCU/torture.txt	2012-01-04 18:55:44.000000000 -0500
@@ -42,7 +42,7 @@
 fqs_stutter	Wait time (in seconds) between consecutive bursts
 		of calls to force_quiescent_state().
 
-irqreaders	Says to invoke RCU readers from irq level.  This is currently
+irqreader	Says to invoke RCU readers from irq level.  This is currently
 		done via timers.  Defaults to "1" for variants of RCU that
 		permit this.  (Or, more accurately, variants of RCU that do
 		-not- permit this know to ignore this variable.)
@@ -79,19 +79,68 @@
 		Specifying "stutter=0" causes the test to run continuously
 		without pausing, which is the old default behavior.
 
+test_boost	Whether or not to test the ability of RCU to do priority
+		boosting.  Defaults to "test_boost=1", which performs
+		RCU priority-inversion testing only if the selected
+		RCU implementation supports priority boosting.  Specifying
+		"test_boost=0" never performs RCU priority-inversion
+		testing.  Specifying "test_boost=2" performs RCU
+		priority-inversion testing even if the selected RCU
+		implementation does not support RCU priority boosting,
+		which can be used to test rcutorture's ability to
+		carry out RCU priority-inversion testing.
+
+test_boost_interval
+		The number of seconds in an RCU priority-inversion test
+		cycle.	Defaults to "test_boost_interval=7".  It is
+		usually wise for this value to be relatively prime to
+		the value selected for "stutter".
+
+test_boost_duration
+		The number of seconds to do RCU priority-inversion testing
+		within any given "test_boost_interval".  Defaults to
+		"test_boost_duration=4".
+
 test_no_idle_hz	Whether or not to test the ability of RCU to operate in
 		a kernel that disables the scheduling-clock interrupt to
 		idle CPUs.  Boolean parameter, "1" to test, "0" otherwise.
 		Defaults to omitting this test.
 
-torture_type	The type of RCU to test: "rcu" for the rcu_read_lock() API,
-		"rcu_sync" for rcu_read_lock() with synchronous reclamation,
-		"rcu_bh" for the rcu_read_lock_bh() API, "rcu_bh_sync" for
-		rcu_read_lock_bh() with synchronous reclamation, "srcu" for
-		the "srcu_read_lock()" API, "sched" for the use of
-		preempt_disable() together with synchronize_sched(),
-		and "sched_expedited" for the use of preempt_disable()
-		with synchronize_sched_expedited().
+torture_type	The type of RCU to test, with string values as follows:
+
+		"rcu":  rcu_read_lock(), rcu_read_unlock() and call_rcu().
+
+		"rcu_sync":  rcu_read_lock(), rcu_read_unlock(), and
+			synchronize_rcu().
+
+		"rcu_expedited": rcu_read_lock(), rcu_read_unlock(), and
+			synchronize_rcu_expedited().
+
+		"rcu_bh": rcu_read_lock_bh(), rcu_read_unlock_bh(), and
+			call_rcu_bh().
+
+		"rcu_bh_sync": rcu_read_lock_bh(), rcu_read_unlock_bh(),
+			and synchronize_rcu_bh().
+
+		"rcu_bh_expedited": rcu_read_lock_bh(), rcu_read_unlock_bh(),
+			and synchronize_rcu_bh_expedited().
+
+		"srcu": srcu_read_lock(), srcu_read_unlock() and
+			synchronize_srcu().
+
+		"srcu_expedited": srcu_read_lock(), srcu_read_unlock() and
+			synchronize_srcu_expedited().
+
+		"sched": preempt_disable(), preempt_enable(), and
+			call_rcu_sched().
+
+		"sched_sync": preempt_disable(), preempt_enable(), and
+			synchronize_sched().
+
+		"sched_expedited": preempt_disable(), preempt_enable(), and
+			synchronize_sched_expedited().
+
+		Defaults to "rcu".
 
 verbose		Enable debug printk()s.  Default is disabled.
 
@@ -100,12 +149,12 @@
 
 The statistics output is as follows:
 
-	rcu-torture: --- Start of test: nreaders=16 stat_interval=0 verbose=0
-	rcu-torture: rtc: 0000000000000000 ver: 1916 tfle: 0 rta: 1916 rtaf: 0 rtf: 1915
-	rcu-torture: Reader Pipe:  1466408 9747 0 0 0 0 0 0 0 0 0
-	rcu-torture: Reader Batch:  1464477 11678 0 0 0 0 0 0 0 0
-	rcu-torture: Free-Block Circulation:  1915 1915 1915 1915 1915 1915 1915 1915 1915 1915 0
-	rcu-torture: --- End of test
+	rcu-torture:--- Start of test: nreaders=16 nfakewriters=4 stat_interval=30 verbose=0 test_no_idle_hz=1 shuffle_interval=3 stutter=5 irqreader=1 fqs_duration=0 fqs_holdoff=0 fqs_stutter=3 test_boost=1/0 test_boost_interval=7 test_boost_duration=4
+	rcu-torture: rtc:           (null) ver: 155441 tfle: 0 rta: 155441 rtaf: 8884 rtf: 155440 rtmbe: 0 rtbke: 0 rtbre: 0 rtbf: 0 rtb: 0 nt: 3055767
+	rcu-torture: Reader Pipe:  727860534 34213 0 0 0 0 0 0 0 0 0
+	rcu-torture: Reader Batch:  727877838 17003 0 0 0 0 0 0 0 0 0
+	rcu-torture: Free-Block Circulation:  155440 155440 155440 155440 155440 155440 155440 155440 155440 155440 0
+	rcu-torture:--- End of test: SUCCESS: nreaders=16 nfakewriters=4 stat_interval=30 verbose=0 test_no_idle_hz=1 shuffle_interval=3 stutter=5 irqreader=1 fqs_duration=0 fqs_holdoff=0 fqs_stutter=3 test_boost=1/0 test_boost_interval=7 test_boost_duration=4
 
 The command "dmesg | grep torture:" will extract this information on
 most systems.  On more esoteric configurations, it may be necessary to
@@ -113,26 +162,55 @@
 the RCU torture test.  The printk()s use KERN_ALERT, so they should
 be evident.  ;-)
 
+The first and last lines show the rcutorture module parameters, and the
+last line shows either "SUCCESS" or "FAILURE", based on rcutorture's
+automatic determination as to whether RCU operated correctly.
+
 The entries are as follows:
 
 o	"rtc": The hexadecimal address of the structure currently visible
 	to readers.
 
-o	"ver": The number of times since boot that the rcutw writer task
+o	"ver": The number of times since boot that the RCU writer task
 	has changed the structure visible to readers.
 
 o	"tfle": If non-zero, indicates that the "torture freelist"
-	containing structure to be placed into the "rtc" area is empty.
+	containing structures to be placed into the "rtc" area is empty.
 	This condition is important, since it can fool you into thinking
 	that RCU is working when it is not.  :-/
 
 o	"rta": Number of structures allocated from the torture freelist.
 
 o	"rtaf": Number of allocations from the torture freelist that have
-	failed due to the list being empty.
+	failed due to the list being empty.  It is not unusual for this
+	to be non-zero, but it is bad for it to be a large fraction of
+	the value indicated by "rta".
 
 o	"rtf": Number of frees into the torture freelist.
 
+o	"rtmbe": A non-zero value indicates that rcutorture believes that
+	rcu_assign_pointer() and rcu_dereference() are not working
+	correctly.  This value should be zero.
+
+o	"rtbke": rcutorture was unable to create the real-time kthreads
+	used to force RCU priority inversion.  This value should be zero.
+
+o	"rtbre": Although rcutorture successfully created the kthreads
+	used to force RCU priority inversion, it was unable to set them
+	to the real-time priority level of 1.  This value should be zero.
+
+o	"rtbf": The number of times that RCU priority boosting failed
+	to resolve RCU priority inversion.
+
+o	"rtb": The number of times that rcutorture attempted to force
+	an RCU priority inversion condition.  If you are testing RCU
+	priority boosting via the "test_boost" module parameter, this
+	value should be non-zero.
+
+o	"nt": The number of times rcutorture ran RCU read-side code from
+	within a timer handler.  This value should be non-zero only
+	if you specified the "irqreader" module parameter.
+
 o	"Reader Pipe": Histogram of "ages" of structures seen by readers.
 	If any entries past the first two are non-zero, RCU is broken.
 	And rcutorture prints the error flag string "!!!" to make sure
@@ -162,26 +240,15 @@
 	somehow gets incremented farther than it should.
 
 Different implementations of RCU can provide implementation-specific
-additional information.  For example, SRCU provides the following:
+additional information.  For example, SRCU provides the following
+additional line:
 
-	srcu-torture: rtc: f8cf46a8 ver: 355 tfle: 0 rta: 356 rtaf: 0 rtf: 346 rtmbe: 0
-	srcu-torture: Reader Pipe:  559738 939 0 0 0 0 0 0 0 0 0
-	srcu-torture: Reader Batch:  560434 243 0 0 0 0 0 0 0 0
-	srcu-torture: Free-Block Circulation:  355 354 353 352 351 350 349 348 347 346 0
 	srcu-torture: per-CPU(idx=1): 0(0,1) 1(0,1) 2(0,0) 3(0,1)
 
-The first four lines are similar to those for RCU.  The last line shows
-the per-CPU counter state.  The numbers in parentheses are the values
-of the "old" and "current" counters for the corresponding CPU.  The
-"idx" value maps the "old" and "current" values to the underlying array,
-and is useful for debugging.
-
-Similarly, sched_expedited RCU provides the following:
-
-	sched_expedited-torture: rtc: d0000000016c1880 ver: 1090796 tfle: 0 rta: 1090796 rtaf: 0 rtf: 1090787 rtmbe: 0 nt: 27713319
-	sched_expedited-torture: Reader Pipe:  12660320201 95875 0 0 0 0 0 0 0 0 0
-	sched_expedited-torture: Reader Batch:  12660424885 0 0 0 0 0 0 0 0 0 0
-	sched_expedited-torture: Free-Block Circulation:  1090795 1090795 1090794 1090793 1090792 1090791 1090790 1090789 1090788 1090787 0
+This line shows the per-CPU counter state.  The numbers in parentheses are
+the values of the "old" and "current" counters for the corresponding CPU.
+The "idx" value maps the "old" and "current" values to the underlying
+array, and is useful for debugging.
 
 
 USAGE
diff -druN linux-libre-3.1-gnu/Documentation/RCU/trace.txt linux-libre-3.2-gnu/Documentation/RCU/trace.txt
--- linux-libre-3.1-gnu/Documentation/RCU/trace.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/RCU/trace.txt	2012-01-04 18:55:44.000000000 -0500
@@ -33,23 +33,23 @@
 The output of "cat rcu/rcudata" looks as follows:
 
 rcu_sched:
-  0 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=545/1/0 df=50 of=0 ri=0 ql=163 qs=NRW. kt=0/W/0 ktl=ebc3 b=10 ci=153737 co=0 ca=0
-  1 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=967/1/0 df=58 of=0 ri=0 ql=634 qs=NRW. kt=0/W/1 ktl=58c b=10 ci=191037 co=0 ca=0
-  2 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=1081/1/0 df=175 of=0 ri=0 ql=74 qs=N.W. kt=0/W/2 ktl=da94 b=10 ci=75991 co=0 ca=0
-  3 c=20942 g=20943 pq=1 pqc=20942 qp=1 dt=1846/0/0 df=404 of=0 ri=0 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=72261 co=0 ca=0
-  4 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=369/1/0 df=83 of=0 ri=0 ql=48 qs=N.W. kt=0/W/4 ktl=e0e7 b=10 ci=128365 co=0 ca=0
-  5 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=381/1/0 df=64 of=0 ri=0 ql=169 qs=NRW. kt=0/W/5 ktl=fb2f b=10 ci=164360 co=0 ca=0
-  6 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=1037/1/0 df=183 of=0 ri=0 ql=62 qs=N.W. kt=0/W/6 ktl=d2ad b=10 ci=65663 co=0 ca=0
-  7 c=20897 g=20897 pq=1 pqc=20896 qp=0 dt=1572/0/0 df=382 of=0 ri=0 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=75006 co=0 ca=0
+  0 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=545/1/0 df=50 of=0 ri=0 ql=163 qs=NRW. kt=0/W/0 ktl=ebc3 b=10 ci=153737 co=0 ca=0
+  1 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=967/1/0 df=58 of=0 ri=0 ql=634 qs=NRW. kt=0/W/1 ktl=58c b=10 ci=191037 co=0 ca=0
+  2 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=1081/1/0 df=175 of=0 ri=0 ql=74 qs=N.W. kt=0/W/2 ktl=da94 b=10 ci=75991 co=0 ca=0
+  3 c=20942 g=20943 pq=1 pgp=20942 qp=1 dt=1846/0/0 df=404 of=0 ri=0 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=72261 co=0 ca=0
+  4 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=369/1/0 df=83 of=0 ri=0 ql=48 qs=N.W. kt=0/W/4 ktl=e0e7 b=10 ci=128365 co=0 ca=0
+  5 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=381/1/0 df=64 of=0 ri=0 ql=169 qs=NRW. kt=0/W/5 ktl=fb2f b=10 ci=164360 co=0 ca=0
+  6 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=1037/1/0 df=183 of=0 ri=0 ql=62 qs=N.W. kt=0/W/6 ktl=d2ad b=10 ci=65663 co=0 ca=0
+  7 c=20897 g=20897 pq=1 pgp=20896 qp=0 dt=1572/0/0 df=382 of=0 ri=0 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=75006 co=0 ca=0
 rcu_bh:
-  0 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=545/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/0 ktl=ebc3 b=10 ci=0 co=0 ca=0
-  1 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=967/1/0 df=3 of=0 ri=1 ql=0 qs=.... kt=0/W/1 ktl=58c b=10 ci=151 co=0 ca=0
-  2 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1081/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/2 ktl=da94 b=10 ci=0 co=0 ca=0
-  3 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1846/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=0 co=0 ca=0
-  4 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=369/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/4 ktl=e0e7 b=10 ci=0 co=0 ca=0
-  5 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=381/1/0 df=4 of=0 ri=1 ql=0 qs=.... kt=0/W/5 ktl=fb2f b=10 ci=0 co=0 ca=0
-  6 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1037/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/6 ktl=d2ad b=10 ci=0 co=0 ca=0
-  7 c=1474 g=1474 pq=1 pqc=1473 qp=0 dt=1572/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=0 co=0 ca=0
+  0 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=545/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/0 ktl=ebc3 b=10 ci=0 co=0 ca=0
+  1 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=967/1/0 df=3 of=0 ri=1 ql=0 qs=.... kt=0/W/1 ktl=58c b=10 ci=151 co=0 ca=0
+  2 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=1081/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/2 ktl=da94 b=10 ci=0 co=0 ca=0
+  3 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=1846/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=0 co=0 ca=0
+  4 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=369/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/4 ktl=e0e7 b=10 ci=0 co=0 ca=0
+  5 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=381/1/0 df=4 of=0 ri=1 ql=0 qs=.... kt=0/W/5 ktl=fb2f b=10 ci=0 co=0 ca=0
+  6 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=1037/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/6 ktl=d2ad b=10 ci=0 co=0 ca=0
+  7 c=1474 g=1474 pq=1 pgp=1473 qp=0 dt=1572/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=0 co=0 ca=0
 
 The first section lists the rcu_data structures for rcu_sched, the second
 for rcu_bh.  Note that CONFIG_TREE_PREEMPT_RCU kernels will have an
@@ -84,7 +84,7 @@
 	CPU has not yet reported that fact, (2) some other CPU has not
 	yet reported for this grace period, or (3) both.
 
-o	"pqc" indicates which grace period the last-observed quiescent
+o	"pgp" indicates which grace period the last-observed quiescent
 	state for this CPU corresponds to.  This is important for handling
 	the race between CPU 0 reporting an extended dynticks-idle
 	quiescent state for CPU 1 and CPU 1 suddenly waking up and
@@ -184,10 +184,14 @@
 	The number after the final slash is the CPU that the kthread
 	is actually running on.
 
+	This field is displayed only for CONFIG_RCU_BOOST kernels.
+
 o	"ktl" is the low-order 16 bits (in hexadecimal) of the count of
 	the number of times that this CPU's per-CPU kthread has gone
 	through its loop servicing invoke_rcu_cpu_kthread() requests.
 
+	This field is displayed only for CONFIG_RCU_BOOST kernels.
+
 o	"b" is the batch limit for this CPU.  If more than this number
 	of RCU callbacks is ready to invoke, then the remainder will
 	be deferred.
diff -druN linux-libre-3.1-gnu/Documentation/rfkill.txt linux-libre-3.2-gnu/Documentation/rfkill.txt
--- linux-libre-3.1-gnu/Documentation/rfkill.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/rfkill.txt	2012-01-04 18:55:44.000000000 -0500
@@ -117,5 +117,4 @@
 "type" sysfs files explained above.
 
 
-For further details consult Documentation/ABI/stable/dev-rfkill and
-Documentation/ABI/stable/sysfs-class-rfkill.
+For further details consult Documentation/ABI/stable/sysfs-class-rfkill.
diff -druN linux-libre-3.1-gnu/Documentation/scheduler/sched-bwc.txt linux-libre-3.2-gnu/Documentation/scheduler/sched-bwc.txt
--- linux-libre-3.1-gnu/Documentation/scheduler/sched-bwc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/scheduler/sched-bwc.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,122 @@
+CFS Bandwidth Control
+=====================
+
+[ This document only discusses CPU bandwidth control for SCHED_NORMAL.
+  The SCHED_RT case is covered in Documentation/scheduler/sched-rt-group.txt ]
+
+CFS bandwidth control is a CONFIG_FAIR_GROUP_SCHED extension which allows the
+specification of the maximum CPU bandwidth available to a group or hierarchy.
+
+The bandwidth allowed for a group is specified using a quota and period. Within
+each given "period" (microseconds), a group is allowed to consume only up to
+"quota" microseconds of CPU time.  When the CPU bandwidth consumption of a
+group exceeds this limit (for that period), the tasks belonging to its
+hierarchy will be throttled and are not allowed to run again until the next
+period.
+
+A group's unused runtime is globally tracked, being refreshed with quota units
+above at each period boundary.  As threads consume this bandwidth it is
+transferred to cpu-local "silos" on a demand basis.  The amount transferred
+within each of these updates is tunable and described as the "slice".
+
+Management
+----------
+Quota and period are managed within the cpu subsystem via cgroupfs.
+
+cpu.cfs_quota_us: the total available run-time within a period (in microseconds)
+cpu.cfs_period_us: the length of a period (in microseconds)
+cpu.stat: exports throttling statistics [explained further below]
+
+The default values are:
+	cpu.cfs_period_us=100ms
+	cpu.cfs_quota=-1
+
+A value of -1 for cpu.cfs_quota_us indicates that the group does not have any
+bandwidth restriction in place, such a group is described as an unconstrained
+bandwidth group.  This represents the traditional work-conserving behavior for
+CFS.
+
+Writing any (valid) positive value(s) will enact the specified bandwidth limit.
+The minimum quota allowed for the quota or period is 1ms.  There is also an
+upper bound on the period length of 1s.  Additional restrictions exist when
+bandwidth limits are used in a hierarchical fashion, these are explained in
+more detail below.
+
+Writing any negative value to cpu.cfs_quota_us will remove the bandwidth limit
+and return the group to an unconstrained state once more.
+
+Any updates to a group's bandwidth specification will result in it becoming
+unthrottled if it is in a constrained state.
+
+System wide settings
+--------------------
+For efficiency run-time is transferred between the global pool and CPU local
+"silos" in a batch fashion.  This greatly reduces global accounting pressure
+on large systems.  The amount transferred each time such an update is required
+is described as the "slice".
+
+This is tunable via procfs:
+	/proc/sys/kernel/sched_cfs_bandwidth_slice_us (default=5ms)
+
+Larger slice values will reduce transfer overheads, while smaller values allow
+for more fine-grained consumption.
+
+Statistics
+----------
+A group's bandwidth statistics are exported via 3 fields in cpu.stat.
+
+cpu.stat:
+- nr_periods: Number of enforcement intervals that have elapsed.
+- nr_throttled: Number of times the group has been throttled/limited.
+- throttled_time: The total time duration (in nanoseconds) for which entities
+  of the group have been throttled.
+
+This interface is read-only.
+
+Hierarchical considerations
+---------------------------
+The interface enforces that an individual entity's bandwidth is always
+attainable, that is: max(c_i) <= C. However, over-subscription in the
+aggregate case is explicitly allowed to enable work-conserving semantics
+within a hierarchy.
+  e.g. \Sum (c_i) may exceed C
+[ Where C is the parent's bandwidth, and c_i its children ]
+
+
+There are two ways in which a group may become throttled:
+	a. it fully consumes its own quota within a period
+	b. a parent's quota is fully consumed within its period
+
+In case b) above, even though the child may have runtime remaining it will not
+be allowed to until the parent's runtime is refreshed.
+
+Examples
+--------
+1. Limit a group to 1 CPU worth of runtime.
+
+	If period is 250ms and quota is also 250ms, the group will get
+	1 CPU worth of runtime every 250ms.
+
+	# echo 250000 > cpu.cfs_quota_us /* quota = 250ms */
+	# echo 250000 > cpu.cfs_period_us /* period = 250ms */
+
+2. Limit a group to 2 CPUs worth of runtime on a multi-CPU machine.
+
+	With 500ms period and 1000ms quota, the group can get 2 CPUs worth of
+	runtime every 500ms.
+
+	# echo 1000000 > cpu.cfs_quota_us /* quota = 1000ms */
+	# echo 500000 > cpu.cfs_period_us /* period = 500ms */
+
+	The larger period here allows for increased burst capacity.
+
+3. Limit a group to 20% of 1 CPU.
+
+	With 50ms period, 10ms quota will be equivalent to 20% of 1 CPU.
+
+	# echo 10000 > cpu.cfs_quota_us /* quota = 10ms */
+	# echo 50000 > cpu.cfs_period_us /* period = 50ms */
+
+	By using a small period here we are ensuring a consistent latency
+	response at the expense of burst capacity.
+
diff -druN linux-libre-3.1-gnu/Documentation/scsi/00-INDEX linux-libre-3.2-gnu/Documentation/scsi/00-INDEX
--- linux-libre-3.1-gnu/Documentation/scsi/00-INDEX	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/scsi/00-INDEX	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,8 @@
 	- Licence of the Flashpoint driver
 LICENSE.qla2xxx
 	- License for QLogic Linux Fibre Channel HBA Driver firmware.
+LICENSE.qla4xxx
+	- License for QLogic Linux iSCSI HBA Driver.
 Mylex.txt
 	- info on driver for Mylex adapters
 NinjaSCSI.txt
diff -druN linux-libre-3.1-gnu/Documentation/scsi/aic7xxx_old.txt linux-libre-3.2-gnu/Documentation/scsi/aic7xxx_old.txt
--- linux-libre-3.1-gnu/Documentation/scsi/aic7xxx_old.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/scsi/aic7xxx_old.txt	2012-01-04 18:55:44.000000000 -0500
@@ -444,7 +444,7 @@
   Kernel Compile options
   ------------------------------
     The various kernel compile time options for this driver are now fairly
-    well documented in the file Documentation/Configure.help.  In order to
+    well documented in the file drivers/scsi/Kconfig.  In order to
     see this documentation, you need to use one of the advanced configuration
     programs (menuconfig and xconfig).  If you are using the "make menuconfig"
     method of configuring your kernel, then you would simply highlight the
diff -druN linux-libre-3.1-gnu/Documentation/scsi/bnx2fc.txt linux-libre-3.2-gnu/Documentation/scsi/bnx2fc.txt
--- linux-libre-3.1-gnu/Documentation/scsi/bnx2fc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/scsi/bnx2fc.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,75 @@
+Operating FCoE using bnx2fc
+===========================
+Broadcom FCoE offload through bnx2fc is full stateful hardware offload that
+cooperates with all interfaces provided by the Linux ecosystem for FC/FCoE and
+SCSI controllers.  As such, FCoE functionality, once enabled is largely
+transparent. Devices discovered on the SAN will be registered and unregistered
+automatically with the upper storage layers.
+
+Despite the fact that the Broadcom's FCoE offload is fully offloaded, it does
+depend on the state of the network interfaces to operate. As such, the network
+interface (e.g. eth0) associated with the FCoE offload initiator must be 'up'.
+It is recommended that the network interfaces be configured to be brought up
+automatically at boot time.
+
+Furthermore, the Broadcom FCoE offload solution creates VLAN interfaces to
+support the VLANs that have been discovered for FCoE operation (e.g.
+eth0.1001-fcoe).  Do not delete or disable these interfaces or FCoE operation
+will be disrupted.
+
+Driver Usage Model:
+===================
+
+1. Ensure that fcoe-utils package is installed.
+
+2. Configure the interfaces on which bnx2fc driver has to operate on.
+Here are the steps to configure:
+	a. cd /etc/fcoe
+	b. copy cfg-ethx to cfg-eth5 if FCoE has to be enabled on eth5.
+	c. Repeat this for all the interfaces where FCoE has to be enabled.
+	d. Edit all the cfg-eth files to set "no" for DCB_REQUIRED** field, and
+	   "yes" for AUTO_VLAN.
+	e. Other configuration parameters should be left as default
+
+3. Ensure that "bnx2fc" is in SUPPORTED_DRIVERS list in /etc/fcoe/config.
+
+4. Start fcoe service. (service fcoe start). If Broadcom devices are present in
+the system, bnx2fc driver would automatically claim the interfaces, starts vlan
+discovery and log into the targets.
+
+5. "Symbolic Name" in 'fcoeadm -i' output would display if bnx2fc has claimed
+the interface.
+Eg:
+[root@bh2 ~]# fcoeadm -i
+    Description:      NetXtreme II BCM57712 10 Gigabit Ethernet
+    Revision:         01
+    Manufacturer:     Broadcom Corporation
+    Serial Number:    0010186FD558
+    Driver:           bnx2x 1.70.00-0
+    Number of Ports:  2
+
+        Symbolic Name:     bnx2fc v1.0.5 over eth5.4
+        OS Device Name:    host11
+        Node Name:         0x10000010186FD559
+        Port Name:         0x20000010186FD559
+        FabricName:        0x2001000DECB3B681
+        Speed:             10 Gbit
+        Supported Speed:   10 Gbit
+        MaxFrameSize:      2048
+        FC-ID (Port ID):   0x0F0377
+        State:             Online
+
+6. Verify the vlan discovery is performed by running ifconfig and notice
+<INTERFACE>.<VLAN>-fcoe interfaces are automatically created.
+
+Refer to fcoeadm manpage for more information on fcoeadm operations to
+create/destroy interfaces or to display lun/target information.
+
+NOTE:
+====
+** Broadcom FCoE capable devices implement a DCBX/LLDP client on-chip. Only one
+LLDP client is allowed per interface. For proper operation all host software
+based DCBX/LLDP clients (e.g. lldpad) must be disabled. To disable lldpad on a
+given interface, run the following command:
+
+lldptool set-lldp -i <interface_name> adminStatus=disabled
diff -druN linux-libre-3.1-gnu/Documentation/scsi/ChangeLog.megaraid_sas linux-libre-3.2-gnu/Documentation/scsi/ChangeLog.megaraid_sas
--- linux-libre-3.1-gnu/Documentation/scsi/ChangeLog.megaraid_sas	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/scsi/ChangeLog.megaraid_sas	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,18 @@
+Release Date    : Wed. Oct 5, 2011 17:00:00 PST 2010 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Adam Radford
+Current Version : 00.00.06.12-rc1
+Old Version     : 00.00.05.40-rc1
+    1. Continue booting immediately if FW in FAULT at driver load time.
+    2. Increase default cmds per lun to 256.
+    3. Fix mismatch in megasas_reset_fusion() mutex lock-unlock.
+    4. Remove some un-necessary code.
+    5. Clear state change interrupts for Fusion/Invader.
+    6. Clear FUSION_IN_RESET before enabling interrupts.
+    7. Add support for MegaRAID 9360/9380 12GB/s controllers.
+    8. Add multiple MSI-X vector/multiple reply queue support.
+    9. Add driver workaround for PERC5/1068 kdump kernel panic.
+-------------------------------------------------------------------------------
 Release Date    : Tue. Jul 26, 2011 17:00:00 PST 2010 -
 			(emaild-id:megaraidlinux@lsi.com)
 			Adam Radford
diff -druN linux-libre-3.1-gnu/Documentation/scsi/LICENSE.qla4xxx linux-libre-3.2-gnu/Documentation/scsi/LICENSE.qla4xxx
--- linux-libre-3.1-gnu/Documentation/scsi/LICENSE.qla4xxx	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/scsi/LICENSE.qla4xxx	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,310 @@
+Copyright (c) 2003-2011 QLogic Corporation
+QLogic Linux iSCSI HBA Driver
+
+This program includes a device driver for Linux 3.x.
+You may modify and redistribute the device driver code under the
+GNU General Public License (a copy of which is attached hereto as
+Exhibit A) published by the Free Software Foundation (version 2).
+
+REGARDLESS OF WHAT LICENSING MECHANISM IS USED OR APPLICABLE,
+THIS PROGRAM IS PROVIDED BY QLOGIC CORPORATION "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.
+
+USER ACKNOWLEDGES AND AGREES THAT USE OF THIS PROGRAM WILL NOT
+CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, ESTOPPEL, OR
+OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT,
+TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN
+ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN
+COMBINATION WITH THIS PROGRAM.
+
+
+EXHIBIT A
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
diff -druN linux-libre-3.1-gnu/Documentation/scsi/scsi_mid_low_api.txt linux-libre-3.2-gnu/Documentation/scsi/scsi_mid_low_api.txt
--- linux-libre-3.1-gnu/Documentation/scsi/scsi_mid_low_api.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/scsi/scsi_mid_low_api.txt	2012-01-04 18:55:44.000000000 -0500
@@ -55,11 +55,6 @@
 about the USB mass storage driver see the 
 /usr/src/linux/drivers/usb/storage directory.
 
-The Linux kernel source Documentation/DocBook/scsidrivers.tmpl file
-refers to this file. With the appropriate DocBook tool-set, this permits
-users to generate html, ps and pdf renderings of information within this
-file (e.g. the interface functions).
-
 Driver structure
 ================
 Traditionally an LLD for the SCSI subsystem has been at least two files in
diff -druN linux-libre-3.1-gnu/Documentation/security/keys-trusted-encrypted.txt linux-libre-3.2-gnu/Documentation/security/keys-trusted-encrypted.txt
--- linux-libre-3.1-gnu/Documentation/security/keys-trusted-encrypted.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/security/keys-trusted-encrypted.txt	2012-01-04 18:55:44.000000000 -0500
@@ -156,4 +156,5 @@
 Other uses for trusted and encrypted keys, such as for disk and file encryption
 are anticipated.  In particular the new format 'ecryptfs' has been defined in
 in order to use encrypted keys to mount an eCryptfs filesystem.  More details
-about the usage can be found in the file 'Documentation/keys-ecryptfs.txt'.
+about the usage can be found in the file
+'Documentation/security/keys-ecryptfs.txt'.
diff -druN linux-libre-3.1-gnu/Documentation/serial/computone.txt linux-libre-3.2-gnu/Documentation/serial/computone.txt
--- linux-libre-3.1-gnu/Documentation/serial/computone.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/serial/computone.txt	2012-01-04 18:55:44.000000000 -0500
@@ -20,8 +20,6 @@
 Date: 11/01/2001
 Historical Author: Andrew Manison <amanison@america.net>
 Primary Author: Doug McNash
-Support: support@computone.com
-Fixes and Updates: Mike Warfield <mhw@wittsend.com>
 
 This file assumes that you are using the Computone drivers which are
 integrated into the kernel sources.  For updating the drivers or installing
diff -druN linux-libre-3.1-gnu/Documentation/serial/serial-rs485.txt linux-libre-3.2-gnu/Documentation/serial/serial-rs485.txt
--- linux-libre-3.1-gnu/Documentation/serial/serial-rs485.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/serial/serial-rs485.txt	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,10 @@
    RS485 communications. This data structure is used to set and configure RS485
    parameters in the platform data and in ioctls.
 
+   The device tree can also provide RS485 boot time parameters (see [2]
+   for bindings). The driver is in charge of filling this data structure from
+   the values given by the device tree.
+
    Any driver for devices capable of working both as RS232 and RS485 should
    provide at least the following ioctls:
 
@@ -93,17 +97,28 @@
 
 	struct serial_rs485 rs485conf;
 
-	/* Set RS485 mode: */
+	/* Enable RS485 mode: */
 	rs485conf.flags |= SER_RS485_ENABLED;
 
+	/* Set logical level for RTS pin equal to 1 when sending: */
+	rs485conf.flags |= SER_RS485_RTS_ON_SEND;
+	/* or, set logical level for RTS pin equal to 0 when sending: */
+	rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
+
+	/* Set logical level for RTS pin equal to 1 after sending: */
+	rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
+	/* or, set logical level for RTS pin equal to 0 after sending: */
+	rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
+
 	/* Set rts delay before send, if needed: */
-	rs485conf.flags |= SER_RS485_RTS_BEFORE_SEND;
 	rs485conf.delay_rts_before_send = ...;
 
 	/* Set rts delay after send, if needed: */
-	rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
 	rs485conf.delay_rts_after_send = ...;
 
+	/* Set this flag if you want to receive data even whilst sending data */
+	rs485conf.flags |= SER_RS485_RX_DURING_TX;
+
 	if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
 		/* Error handling. See errno. */
 	}
@@ -118,3 +133,4 @@
 5. REFERENCES
 
  [1]	include/linux/serial.h
+ [2]	Documentation/devicetree/bindings/serial/rs485.txt
diff -druN linux-libre-3.1-gnu/Documentation/sound/alsa/ALSA-Configuration.txt linux-libre-3.2-gnu/Documentation/sound/alsa/ALSA-Configuration.txt
--- linux-libre-3.1-gnu/Documentation/sound/alsa/ALSA-Configuration.txt	2012-03-19 22:13:52.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/sound/alsa/ALSA-Configuration.txt	2012-03-19 22:17:26.000000000 -0400
@@ -886,6 +886,12 @@
 		disable)
     power_save_controller - Reset HD-audio controller in power-saving mode
 		(default = on)
+    align_buffer_size - Force rounding of buffer/period sizes to multiples
+    		      of 128 bytes. This is more efficient in terms of memory
+		      access but isn't required by the HDA spec and prevents
+		      users from specifying exact period/buffer sizes.
+		      (default = on)
+    snoop	- Enable/disable snooping (default = on)
 
     This module supports multiple cards and autoprobe.
     
diff -druN linux-libre-3.1-gnu/Documentation/sound/alsa/HD-Audio-Controls.txt linux-libre-3.2-gnu/Documentation/sound/alsa/HD-Audio-Controls.txt
--- linux-libre-3.1-gnu/Documentation/sound/alsa/HD-Audio-Controls.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/sound/alsa/HD-Audio-Controls.txt	2012-01-04 18:55:44.000000000 -0500
@@ -98,3 +98,19 @@
 
 * Auto-Mute Mode
   See Reatek codecs.
+
+
+Analog codecs
+--------------
+
+* Channel Mode
+  This is an enum control to change the surround-channel setup,
+  appears only when the surround channels are available.
+  It gives the number of channels to be used, "2ch", "4ch" and "6ch".
+  According to the configuration, this also controls the
+  jack-retasking of multi-I/O jacks.
+
+* Independent HP
+  When this enum control is enabled, the headphone output is routed
+  from an individual stream (the third PCM such as hw:0,2) instead of
+  the primary stream.
diff -druN linux-libre-3.1-gnu/Documentation/sound/alsa/HD-Audio-Models.txt linux-libre-3.2-gnu/Documentation/sound/alsa/HD-Audio-Models.txt
--- linux-libre-3.1-gnu/Documentation/sound/alsa/HD-Audio-Models.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/sound/alsa/HD-Audio-Models.txt	2012-01-04 18:55:44.000000000 -0500
@@ -29,9 +29,6 @@
 
 ALC260
 ======
-  hp		HP machines
-  hp-3013	HP machines (3013-variant)
-  hp-dc7600	HP DC7600
   fujitsu	Fujitsu S7020
   acer		Acer TravelMate
   will		Will laptops (PB V7900)
@@ -46,15 +43,10 @@
 ALC262
 ======
   fujitsu	Fujitsu Laptop
-  hp-bpc	HP xw4400/6400/8400/9400 laptops
-  hp-bpc-d7000	HP BPC D7000
-  hp-tc-t5735	HP Thin Client T5735
-  hp-rp5700	HP RP5700
   benq		Benq ED8
   benq-t31	Benq T31
   hippo		Hippo (ATI) with jack detection, Sony UX-90s
   hippo_1	Hippo (Benq) with jack detection
-  sony-assamd	Sony ASSAMD
   toshiba-s06	Toshiba S06
   toshiba-rx1	Toshiba RX1
   tyan		Tyan Thunder n6650W (S2915-E)
@@ -66,43 +58,15 @@
 
 ALC267/268
 ==========
-  quanta-il1	Quanta IL1 mini-notebook
-  3stack	3-stack model
-  toshiba	Toshiba A205
-  acer		Acer laptops
-  acer-dmic	Acer laptops with digital-mic
-  acer-aspire	Acer Aspire One
-  dell		Dell OEM laptops (Vostro 1200)
-  zepto		Zepto laptops
-  test		for testing/debugging purpose, almost all controls can
-		adjusted.  Appearing only when compiled with
-		$CONFIG_SND_DEBUG=y
-  auto		auto-config reading BIOS (default)
+  N/A
 
 ALC269
 ======
-  basic		Basic preset
-  quanta	Quanta FL1
   laptop-amic	Laptops with analog-mic input
   laptop-dmic	Laptops with digital-mic input
-  fujitsu	FSC Amilo
-  lifebook	Fujitsu Lifebook S6420
-  auto		auto-config reading BIOS (default)
 
 ALC662/663/272
 ==============
-  3stack-dig	3-stack (2-channel) with SPDIF
-  3stack-6ch	 3-stack (6-channel)
-  3stack-6ch-dig 3-stack (6-channel) with SPDIF
-  5stack-dig	 5-stack with SPDIF
-  lenovo-101e	 Lenovo laptop
-  eeepc-p701	ASUS Eeepc P701
-  eeepc-ep20	ASUS Eeepc EP20
-  ecs		ECS/Foxconn mobo
-  m51va		ASUS M51VA
-  g71v		ASUS G71V
-  h13		ASUS H13
-  g50v		ASUS G50V
   asus-mode1	ASUS
   asus-mode2	ASUS
   asus-mode3	ASUS
@@ -111,15 +75,10 @@
   asus-mode6	ASUS
   asus-mode7	ASUS
   asus-mode8	ASUS
-  dell		Dell with ALC272
-  dell-zm1	Dell ZM1 with ALC272
-  samsung-nc10	Samsung NC10 mini notebook
-  auto		auto-config reading BIOS (default)
 
 ALC680
 ======
-  base		Base model (ASUS NX90)
-  auto		auto-config reading BIOS (default)
+  N/A
 
 ALC882/883/885/888/889
 ======================
@@ -175,28 +134,11 @@
 
 ALC861/660
 ==========
-  3stack	3-jack
-  3stack-dig	3-jack with SPDIF I/O
-  6stack-dig	6-jack with SPDIF I/O
-  3stack-660	3-jack (for ALC660)
-  uniwill-m31	Uniwill M31 laptop
-  toshiba	Toshiba laptop support
-  asus		Asus laptop support
-  asus-laptop	ASUS F2/F3 laptops
-  auto		auto-config reading BIOS (default)
+  N/A
 
 ALC861VD/660VD
 ==============
-  3stack	3-jack
-  3stack-dig	3-jack with SPDIF OUT
-  6stack-dig	6-jack with SPDIF OUT
-  3stack-660	3-jack (for ALC660VD)
-  3stack-660-digout 3-jack with SPDIF OUT (for ALC660VD)
-  lenovo	Lenovo 3000 C200
-  dallas	Dallas laptops
-  hp		HP TX1000
-  asus-v1s	ASUS V1Sn
-  auto		auto-config reading BIOS (default)
+  N/A
 
 CMI9880
 =======
@@ -289,7 +231,6 @@
   hp-dv6736	HP dv6736
   hp-f700	HP Compaq Presario F700
   ideapad	Lenovo IdeaPad laptop
-  lenovo-x200	Lenovo X200 laptop
   toshiba	Toshiba Satellite M300
 
 Conexant 5066
@@ -408,6 +349,7 @@
   ref		Reference board
   mic-ref	Reference board with power management for ports
   dell-s14	Dell laptop
+  dell-vostro-3500	Dell Vostro 3500 laptop
   hp		HP laptops with (inverted) mute-LED
   hp-dv7-4000	HP dv-7 4000
   auto		BIOS setup (default)
diff -druN linux-libre-3.1-gnu/Documentation/sound/alsa/HD-Audio.txt linux-libre-3.2-gnu/Documentation/sound/alsa/HD-Audio.txt
--- linux-libre-3.1-gnu/Documentation/sound/alsa/HD-Audio.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/sound/alsa/HD-Audio.txt	2012-01-04 18:55:44.000000000 -0500
@@ -447,7 +447,10 @@
 three numbers indicating the codec vendor-id (0x12345678 in the
 example), the codec subsystem-id (0xabcd1234) and the address (2) of
 the codec.  The rest patch entries are applied to this specified codec
-until another codec entry is given.
+until another codec entry is given.  Passing 0 or a negative number to
+the first or the second value will make the check of the corresponding
+field be skipped.  It'll be useful for really broken devices that don't
+initialize SSID properly.
 
 The `[model]` line allows to change the model name of the each codec.
 In the example above, it will be changed to model=auto.
@@ -491,7 +494,7 @@
 The hd-audio driver reads the file via request_firmware().  Thus,
 a patch file has to be located on the appropriate firmware path,
 typically, /lib/firmware.  For example, when you pass the option
-`patch=hda-init.fw`, the file /lib/firmware/hda-init-fw must be
+`patch=hda-init.fw`, the file /lib/firmware/hda-init.fw must be
 present.
 
 The patch module option is specific to each card instance, and you
@@ -524,11 +527,59 @@
 check the current value.  If it's non-zero, the feature is turned on.
 
 
+Tracepoints
+~~~~~~~~~~~
+The hd-audio driver gives a few basic tracepoints.
+`hda:hda_send_cmd` traces each CORB write while `hda:hda_get_response`
+traces the response from RIRB (only when read from the codec driver).
+`hda:hda_bus_reset` traces the bus-reset due to fatal error, etc,
+`hda:hda_unsol_event` traces the unsolicited events, and
+`hda:hda_power_down` and `hda:hda_power_up` trace the power down/up
+via power-saving behavior.
+
+Enabling all tracepoints can be done like
+------------------------------------------------------------------------
+  # echo 1 > /sys/kernel/debug/tracing/events/hda/enable
+------------------------------------------------------------------------
+then after some commands, you can traces from
+/sys/kernel/debug/tracing/trace file.  For example, when you want to
+trace what codec command is sent, enable the tracepoint like:
+------------------------------------------------------------------------
+  # cat /sys/kernel/debug/tracing/trace
+  # tracer: nop
+  #
+  #       TASK-PID    CPU#    TIMESTAMP  FUNCTION
+  #          | |       |          |         |
+         <...>-7807  [002] 105147.774889: hda_send_cmd: [0:0] val=e3a019
+         <...>-7807  [002] 105147.774893: hda_send_cmd: [0:0] val=e39019
+         <...>-7807  [002] 105147.999542: hda_send_cmd: [0:0] val=e3a01a
+         <...>-7807  [002] 105147.999543: hda_send_cmd: [0:0] val=e3901a
+         <...>-26764 [001] 349222.837143: hda_send_cmd: [0:0] val=e3a019
+         <...>-26764 [001] 349222.837148: hda_send_cmd: [0:0] val=e39019
+         <...>-26764 [001] 349223.058539: hda_send_cmd: [0:0] val=e3a01a
+         <...>-26764 [001] 349223.058541: hda_send_cmd: [0:0] val=e3901a
+------------------------------------------------------------------------
+Here `[0:0]` indicates the card number and the codec address, and
+`val` shows the value sent to the codec, respectively.  The value is
+a packed value, and you can decode it via hda-decode-verb program
+included in hda-emu package below.  For example, the value e3a019 is
+to set the left output-amp value to 25.
+------------------------------------------------------------------------
+  % hda-decode-verb 0xe3a019
+  raw value = 0x00e3a019
+  cid = 0, nid = 0x0e, verb = 0x3a0, parm = 0x19
+  raw value: verb = 0x3a0, parm = 0x19
+  verbname = set_amp_gain_mute
+  amp raw val = 0xa019
+  output, left, idx=0, mute=0, val=25
+------------------------------------------------------------------------
+
+
 Development Tree
 ~~~~~~~~~~~~~~~~
 The latest development codes for HD-audio are found on sound git tree:
 
-- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
+- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
 
 The master branch or for-next branches can be used as the main
 development branches in general while the HD-audio specific patches
@@ -543,7 +594,7 @@
 install(-modules).  See INSTALL in the package.  The snapshot tarballs
 are found at:
 
-- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/snapshot/
+- ftp://ftp.suse.com/pub/people/tiwai/snapshot/
 
 
 Sending a Bug Report
@@ -645,7 +696,7 @@
 
 The hda-verb program is found in the ftp directory:
 
-- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/misc/
+- ftp://ftp.suse.com/pub/people/tiwai/misc/
 
 Also a git repository is available:
 
@@ -713,7 +764,7 @@
 
 The package is found in:
 
-- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/misc/
+- ftp://ftp.suse.com/pub/people/tiwai/misc/
 
 A git repository is available:
 
diff -druN linux-libre-3.1-gnu/Documentation/sound/alsa/soc/machine.txt linux-libre-3.2-gnu/Documentation/sound/alsa/soc/machine.txt
--- linux-libre-3.1-gnu/Documentation/sound/alsa/soc/machine.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/sound/alsa/soc/machine.txt	2012-01-04 18:55:44.000000000 -0500
@@ -50,8 +50,7 @@
 The machine DAI configuration glues all the codec and CPU DAIs together. It can
 also be used to set up the DAI system clock and for any machine related DAI
 initialisation e.g. the machine audio map can be connected to the codec audio
-map, unconnected codec pins can be set as such. Please see corgi.c, spitz.c
-for examples.
+map, unconnected codec pins can be set as such.
 
 struct snd_soc_dai_link is used to set up each DAI in your machine. e.g.
 
@@ -83,8 +82,7 @@
 The machine driver can optionally extend the codec power map and to become an
 audio power map of the audio subsystem. This allows for automatic power up/down
 of speaker/HP amplifiers, etc. Codec pins can be connected to the machines jack
-sockets in the machine init function. See soc/pxa/spitz.c and dapm.txt for
-details.
+sockets in the machine init function.
 
 
 Machine Controls
diff -druN linux-libre-3.1-gnu/Documentation/sound/oss/PAS16 linux-libre-3.2-gnu/Documentation/sound/oss/PAS16
--- linux-libre-3.1-gnu/Documentation/sound/oss/PAS16	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/sound/oss/PAS16	2012-01-04 18:55:44.000000000 -0500
@@ -60,8 +60,7 @@
 
 The new stuff for 2.3.99 and later
 ============================================================================
-The following configuration options from Documentation/Configure.help
-are relevant to configuring the PAS16:
+The following configuration options are relevant to configuring the PAS16:
 
 Sound card support
 CONFIG_SOUND
diff -druN linux-libre-3.1-gnu/Documentation/spi/pxa2xx linux-libre-3.2-gnu/Documentation/spi/pxa2xx
--- linux-libre-3.1-gnu/Documentation/spi/pxa2xx	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/spi/pxa2xx	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
 ===================================================
 This a mini howto on the pxa2xx_spi driver.  The driver turns a PXA2xx
 synchronous serial port into a SPI master controller
-(see Documentation/spi/spi_summary). The driver has the following features
+(see Documentation/spi/spi-summary). The driver has the following features
 
 - Support for any PXA2xx SSP
 - SSP PIO and SSP DMA data transfers.
@@ -85,7 +85,7 @@
 -----------------------
 Typically each SPI slave (chip) is defined in the arch/.../mach-*/board-*.c
 using the "spi_board_info" structure found in "linux/spi/spi.h". See
-"Documentation/spi/spi_summary" for additional information.
+"Documentation/spi/spi-summary" for additional information.
 
 Each slave device attached to the PXA must provide slave specific configuration
 information via the structure "pxa2xx_spi_chip" found in
diff -druN linux-libre-3.1-gnu/Documentation/stable_kernel_rules.txt linux-libre-3.2-gnu/Documentation/stable_kernel_rules.txt
--- linux-libre-3.1-gnu/Documentation/stable_kernel_rules.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/stable_kernel_rules.txt	2012-01-04 18:55:44.000000000 -0500
@@ -24,10 +24,10 @@
 Procedure for submitting patches to the -stable tree:
 
  - Send the patch, after verifying that it follows the above rules, to
-   stable@kernel.org.  You must note the upstream commit ID in the changelog
-   of your submission.
+   stable@vger.kernel.org.  You must note the upstream commit ID in the
+   changelog of your submission.
  - To have the patch automatically included in the stable tree, add the tag
-     Cc: stable@kernel.org
+     Cc: stable@vger.kernel.org
    in the sign-off area. Once the patch is merged it will be applied to
    the stable tree without anything else needing to be done by the author
    or subsystem maintainer.
@@ -35,10 +35,10 @@
    cherry-picked than this can be specified in the following format in
    the sign-off area:
 
-     Cc: <stable@kernel.org> # .32.x: a1f84a3: sched: Check for idle
-     Cc: <stable@kernel.org> # .32.x: 1b9508f: sched: Rate-limit newidle
-     Cc: <stable@kernel.org> # .32.x: fd21073: sched: Fix affinity logic
-     Cc: <stable@kernel.org> # .32.x
+     Cc: <stable@vger.kernel.org> # .32.x: a1f84a3: sched: Check for idle
+     Cc: <stable@vger.kernel.org> # .32.x: 1b9508f: sched: Rate-limit newidle
+     Cc: <stable@vger.kernel.org> # .32.x: fd21073: sched: Fix affinity logic
+     Cc: <stable@vger.kernel.org> # .32.x
     Signed-off-by: Ingo Molnar <mingo@elte.hu>
 
    The tag sequence has the meaning of:
diff -druN linux-libre-3.1-gnu/Documentation/sysctl/kernel.txt linux-libre-3.2-gnu/Documentation/sysctl/kernel.txt
--- linux-libre-3.1-gnu/Documentation/sysctl/kernel.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/sysctl/kernel.txt	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 - bootloader_type	     [ X86 only ]
 - bootloader_version	     [ X86 only ]
 - callhome		     [ S390 only ]
+- cap_last_cap
 - core_pattern
 - core_pipe_limit
 - core_uses_pid
@@ -155,6 +156,13 @@
 
 ==============================================================
 
+cap_last_cap
+
+Highest valid capability of the running kernel.  Exports
+CAP_LAST_CAP from the kernel.
+
+==============================================================
+
 core_pattern:
 
 core_pattern is used to specify a core dumpfile pattern name.
diff -druN linux-libre-3.1-gnu/Documentation/timers/highres.txt linux-libre-3.2-gnu/Documentation/timers/highres.txt
--- linux-libre-3.1-gnu/Documentation/timers/highres.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/timers/highres.txt	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@
 ---------------------------
 
 The hrtimer base infrastructure was merged into the 2.6.16 kernel. Details of
-the base implementation are covered in Documentation/hrtimers/hrtimer.txt. See
+the base implementation are covered in Documentation/timers/hrtimers.txt. See
 also figure #2 (OLS slides p. 15)
 
 The main differences to the timer wheel, which holds the armed timer_list type
diff -druN linux-libre-3.1-gnu/Documentation/trace/postprocess/trace-vmscan-postprocess.pl linux-libre-3.2-gnu/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
--- linux-libre-3.1-gnu/Documentation/trace/postprocess/trace-vmscan-postprocess.pl	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/trace/postprocess/trace-vmscan-postprocess.pl	2012-01-04 18:55:44.000000000 -0500
@@ -379,10 +379,10 @@
 
 			# To closer match vmstat scanning statistics, only count isolate_both
 			# and isolate_inactive as scanning. isolate_active is rotation
-			# isolate_inactive == 0
-			# isolate_active   == 1
-			# isolate_both     == 2
-			if ($isolate_mode != 1) {
+			# isolate_inactive == 1
+			# isolate_active   == 2
+			# isolate_both     == 3
+			if ($isolate_mode != 2) {
 				$perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned;
 			}
 			$perprocesspid{$process_pid}->{HIGH_NR_CONTIG_DIRTY} += $nr_contig_dirty;
diff -druN linux-libre-3.1-gnu/Documentation/usb/dma.txt linux-libre-3.2-gnu/Documentation/usb/dma.txt
--- linux-libre-3.1-gnu/Documentation/usb/dma.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/usb/dma.txt	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
 
 The big picture is that USB drivers can continue to ignore most DMA issues,
 though they still must provide DMA-ready buffers (see
-Documentation/PCI/PCI-DMA-mapping.txt).  That's how they've worked through
+Documentation/DMA-API-HOWTO.txt).  That's how they've worked through
 the 2.4 (and earlier) kernels.
 
 OR:  they can now be DMA-aware.
@@ -57,7 +57,7 @@
   force a consistent memory access ordering by using memory barriers.  It's
   not using a streaming DMA mapping, so it's good for small transfers on
   systems where the I/O would otherwise thrash an IOMMU mapping.  (See
-  Documentation/PCI/PCI-DMA-mapping.txt for definitions of "coherent" and
+  Documentation/DMA-API-HOWTO.txt for definitions of "coherent" and
   "streaming" DMA mappings.)
 
   Asking for 1/Nth of a page (as well as asking for N pages) is reasonably
@@ -88,7 +88,7 @@
 Existing buffers aren't usable for DMA without first being mapped into the
 DMA address space of the device.  However, most buffers passed to your
 driver can safely be used with such DMA mapping.  (See the first section
-of Documentation/PCI/PCI-DMA-mapping.txt, titled "What memory is DMA-able?")
+of Documentation/DMA-API-HOWTO.txt, titled "What memory is DMA-able?")
 
 - When you're using scatterlists, you can map everything at once.  On some
   systems, this kicks in an IOMMU and turns the scatterlists into single
diff -druN linux-libre-3.1-gnu/Documentation/usb/dwc3.txt linux-libre-3.2-gnu/Documentation/usb/dwc3.txt
--- linux-libre-3.1-gnu/Documentation/usb/dwc3.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/usb/dwc3.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,45 @@
+
+ TODO
+~~~~~~
+Please pick something while reading :)
+
+- Convert interrupt handler to per-ep-thread-irq
+
+  As it turns out some DWC3-commands ~1ms to complete. Currently we spin
+  until the command completes which is bad.
+
+  Implementation idea:
+  - dwc core implements a demultiplexing irq chip for interrupts per
+    endpoint. The interrupt numbers are allocated during probe and belong
+    to the device. If MSI provides per-endpoint interrupt this dummy
+    interrupt chip can be replaced with "real" interrupts.
+  - interrupts are requested / allocated on usb_ep_enable() and removed on
+    usb_ep_disable(). Worst case are 32 interrupts, the lower limit is two
+    for ep0/1.
+  - dwc3_send_gadget_ep_cmd() will sleep in wait_for_completion_timeout()
+    until the command completes.
+  - the interrupt handler is split into the following pieces:
+    - primary handler of the device
+      goes through every event and calls generic_handle_irq() for event
+      it. On return from generic_handle_irq() in acknowledges the event
+      counter so interrupt goes away (eventually).
+
+    - threaded handler of the device
+      none
+
+    - primary handler of the EP-interrupt
+      reads the event and tries to process it. Everything that requries
+      sleeping is handed over to the Thread. The event is saved in an
+      per-endpoint data-structure.
+      We probably have to pay attention not to process events once we
+      handed something to thread so we don't process event X prio Y
+      where X > Y.
+
+    - threaded handler of the EP-interrupt
+      handles the remaining EP work which might sleep such as waiting
+      for command completion.
+
+  Latency:
+   There should be no increase in latency since the interrupt-thread has a
+   high priority and will be run before an average task in user land
+   (except the user changed priorities).
diff -druN linux-libre-3.1-gnu/Documentation/usb/linux-cdc-acm.inf linux-libre-3.2-gnu/Documentation/usb/linux-cdc-acm.inf
--- linux-libre-3.1-gnu/Documentation/usb/linux-cdc-acm.inf	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/usb/linux-cdc-acm.inf	2012-01-04 18:55:44.000000000 -0500
@@ -90,10 +90,10 @@
 [SourceDisksFiles]
 [SourceDisksNames]
 [DeviceList]
-%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02
+%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02, USB\VID_1D6B&PID_0106&MI_00
 
 [DeviceList.NTamd64]
-%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02
+%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02, USB\VID_1D6B&PID_0106&MI_00
 
 
 ;------------------------------------------------------------------------------
diff -druN linux-libre-3.1-gnu/Documentation/usb/power-management.txt linux-libre-3.2-gnu/Documentation/usb/power-management.txt
--- linux-libre-3.1-gnu/Documentation/usb/power-management.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/usb/power-management.txt	2012-01-04 18:55:44.000000000 -0500
@@ -439,10 +439,10 @@
 device.
 
 External suspend calls should never be allowed to fail in this way,
-only autosuspend calls.  The driver can tell them apart by checking
-the PM_EVENT_AUTO bit in the message.event argument to the suspend
-method; this bit will be set for internal PM events (autosuspend) and
-clear for external PM events.
+only autosuspend calls.  The driver can tell them apart by applying
+the PMSG_IS_AUTO() macro to the message argument to the suspend
+method; it will return True for internal PM events (autosuspend) and
+False for external PM events.
 
 
 	Mutual exclusion
@@ -487,3 +487,29 @@
 resume as soon as the system suspend is complete.  Or the remote
 wakeup may fail and get lost.  Which outcome occurs depends on timing
 and on the hardware and firmware design.
+
+
+	xHCI hardware link PM
+	---------------------
+
+xHCI host controller provides hardware link power management to usb2.0
+(xHCI 1.0 feature) and usb3.0 devices which support link PM. By
+enabling hardware LPM, the host can automatically put the device into
+lower power state(L1 for usb2.0 devices, or U1/U2 for usb3.0 devices),
+which state device can enter and resume very quickly.
+
+The user interface for controlling USB2 hardware LPM is located in the
+power/ subdirectory of each USB device's sysfs directory, that is, in
+/sys/bus/usb/devices/.../power/ where "..." is the device's ID. The
+relevant attribute files is usb2_hardware_lpm.
+
+	power/usb2_hardware_lpm
+
+		When a USB2 device which support LPM is plugged to a
+		xHCI host root hub which support software LPM, the
+		host will run a software LPM test for it; if the device
+		enters L1 state and resume successfully and the host
+		supports USB2 hardware LPM, this file will show up and
+		driver will enable hardware LPM	for the device. You
+		can write y/Y/1 or n/N/0 to the file to	enable/disable
+		USB2 hardware LPM manually. This is for	test purpose mainly.
diff -druN linux-libre-3.1-gnu/Documentation/video4linux/CARDLIST.tm6000 linux-libre-3.2-gnu/Documentation/video4linux/CARDLIST.tm6000
--- linux-libre-3.1-gnu/Documentation/video4linux/CARDLIST.tm6000	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/video4linux/CARDLIST.tm6000	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,16 @@
+  1 -> Generic tm5600 board                   (tm5600)          [6000:0001]
+  2 -> Generic tm6000 board                   (tm6000)          [6000:0001]
+  3 -> Generic tm6010 board                   (tm6010)          [6000:0002]
+  4 -> 10Moons UT821                          (tm5600)          [6000:0001]
+  5 -> 10Moons UT330                          (tm5600)
+  6 -> ADSTech Dual TV                        (tm6000)          [06e1:f332]
+  7 -> FreeCom and similar                    (tm6000)          [14aa:0620]
+  8 -> ADSTech Mini Dual TV                   (tm6000)          [06e1:b339]
+  9 -> Hauppauge WinTV HVR-900H/USB2 Stick    (tm6010)          [2040:6600,2040:6601,2040:6610,2040:6611]
+ 10 -> Beholder Wander                        (tm6010)          [6000:dec0]
+ 11 -> Beholder Voyager                       (tm6010)          [6000:dec1]
+ 12 -> TerraTec Cinergy Hybrid XE/Cinergy Hybrid Stick (tm6010) [0ccd:0086,0ccd:00a5]
+ 13 -> TwinHan TU501                          (tm6010)          [13d3:3240,13d3:3241,13d3:3243,13d3:3264]
+ 14 -> Beholder Wander Lite                   (tm6010)          [6000:dec2]
+ 15 -> Beholder Voyager Lite                  (tm6010)          [6000:dec3]
+
diff -druN linux-libre-3.1-gnu/Documentation/video4linux/gspca.txt linux-libre-3.2-gnu/Documentation/video4linux/gspca.txt
--- linux-libre-3.1-gnu/Documentation/video4linux/gspca.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/video4linux/gspca.txt	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 ----
 spca501		0000:0000	MystFromOri Unknown Camera
 spca508		0130:0130	Clone Digital Webcam 11043
+zc3xx		03f0:1b07	HP Premium Starter Cam
 m5602		0402:5602	ALi Video Camera Controller
 spca501		040a:0002	Kodak DVC-325
 spca500		040a:0300	Kodak EZ200
@@ -190,6 +191,7 @@
 ov519		05a9:0530	OmniVision
 ov519		05a9:2800	OmniVision SuperCAM
 ov519		05a9:4519	Webcam Classic
+ov534_9		05a9:8065	OmniVision test kit ov538+ov9712
 ov519		05a9:8519	OmniVision
 ov519		05a9:a511	D-Link USB Digital Video Camera
 ov519		05a9:a518	D-Link DSB-C310 Webcam
@@ -199,6 +201,8 @@
 gl860		05e3:f191	Genesys Logic PC Camera
 spca561		060b:a001	Maxell Compact Pc PM3
 zc3xx		0698:2003	CTX M730V built in
+topro		06a2:0003	TP6800 PC Camera, CmoX CX0342 webcam
+topro		06a2:6810	Creative Qmax
 nw80x		06a5:0000	Typhoon Webcam 100 USB
 nw80x		06a5:d001	Divio based webcams
 nw80x		06a5:d800	Divio Chicony TwinkleCam, Trust SpaceCam
diff -druN linux-libre-3.1-gnu/Documentation/video4linux/omap3isp.txt linux-libre-3.2-gnu/Documentation/video4linux/omap3isp.txt
--- linux-libre-3.1-gnu/Documentation/video4linux/omap3isp.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/video4linux/omap3isp.txt	2012-01-04 18:55:44.000000000 -0500
@@ -70,10 +70,11 @@
 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.
+The CCDC subdev produces V4L2_EVENT_FRAME_SYNC type event on HS_VS
+interrupt which is used to signal frame start. Earlier version of this
+driver used V4L2_EVENT_OMAP3ISP_HS_VS for this purpose. 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
diff -druN linux-libre-3.1-gnu/Documentation/video4linux/v4l2-controls.txt linux-libre-3.2-gnu/Documentation/video4linux/v4l2-controls.txt
--- linux-libre-3.1-gnu/Documentation/video4linux/v4l2-controls.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/video4linux/v4l2-controls.txt	2012-01-04 18:55:44.000000000 -0500
@@ -285,11 +285,11 @@
 Note that you use the 'new value' union as well in g_volatile_ctrl. In general
 controls that need to implement g_volatile_ctrl are read-only controls.
 
-To mark a control as volatile you have to set the is_volatile flag:
+To mark a control as volatile you have to set V4L2_CTRL_FLAG_VOLATILE:
 
 	ctrl = v4l2_ctrl_new_std(&sd->ctrl_handler, ...);
 	if (ctrl)
-		ctrl->is_volatile = 1;
+		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
 
 For try/s_ctrl the new values (i.e. as passed by the user) are filled in and
 you can modify them in try_ctrl or set them in s_ctrl. The 'cur' union
@@ -367,8 +367,7 @@
 The last argument is the priv pointer which can be set to driver-specific
 private data.
 
-The v4l2_ctrl_config struct also has fields to set the is_private and is_volatile
-flags.
+The v4l2_ctrl_config struct also has a field to set the is_private flag.
 
 If the name field is not set, then the framework will assume this is a standard
 control and will fill in the name, type and flags fields accordingly.
@@ -496,18 +495,20 @@
 
 A common type of control cluster is one that handles 'auto-foo/foo'-type
 controls. Typical examples are autogain/gain, autoexposure/exposure,
-autowhitebalance/red balance/blue balance. In all cases you have one controls
+autowhitebalance/red balance/blue balance. In all cases you have one control
 that determines whether another control is handled automatically by the hardware,
 or whether it is under manual control from the user.
 
 If the cluster is in automatic mode, then the manual controls should be
-marked inactive. When the volatile controls are read the g_volatile_ctrl
-operation should return the value that the hardware's automatic mode set up
-automatically.
+marked inactive and volatile. When the volatile controls are read the
+g_volatile_ctrl operation should return the value that the hardware's automatic
+mode set up automatically.
 
 If the cluster is put in manual mode, then the manual controls should become
-active again and the is_volatile flag should be ignored (so g_volatile_ctrl is
-no longer called while in manual mode).
+active again and the volatile flag is cleared (so g_volatile_ctrl is no longer
+called while in manual mode). In addition just before switching to manual mode
+the current values as determined by the auto mode are copied as the new manual
+values.
 
 Finally the V4L2_CTRL_FLAG_UPDATE should be set for the auto control since
 changing that control affects the control flags of the manual controls.
@@ -520,7 +521,11 @@
 
 The first two arguments are identical to v4l2_ctrl_cluster. The third argument
 tells the framework which value switches the cluster into manual mode. The
-last argument will optionally set the is_volatile flag for the non-auto controls.
+last argument will optionally set V4L2_CTRL_FLAG_VOLATILE for the non-auto controls.
+If it is false, then the manual controls are never volatile. You would typically
+use that if the hardware does not give you the option to read back to values as
+determined by the auto mode (e.g. if autogain is on, the hardware doesn't allow
+you to obtain the current gain value).
 
 The first control of the cluster is assumed to be the 'auto' control.
 
@@ -681,16 +686,6 @@
 count if nothing was done yet. If it is less than count then only the controls
 up to error_idx-1 were successfully applied.
 
-3) When attempting to read a button control the framework will return -EACCES
-instead of -EINVAL as stated in the spec. It seems to make more sense since
-button controls are write-only controls.
-
-4) Attempting to write to a read-only control will return -EACCES instead of
--EINVAL as the spec says.
-
-5) The spec does not mention what should happen when you try to set/get a
-control class controls. The framework will return -EACCES.
-
 
 Proposals for Extensions
 ========================
@@ -703,9 +698,3 @@
 2) It is possible to mark in the controls array which controls have been
 successfully written and which failed by for example adding a bit to the
 control ID. Not sure if it is worth the effort, though.
-
-3) Trying to set volatile inactive controls should result in -EACCESS.
-
-4) Add a new flag to mark volatile controls. Any application that wants
-to store the state of the controls can then skip volatile inactive controls.
-Currently it is not possible to detect such controls.
diff -druN linux-libre-3.1-gnu/Documentation/virtual/kvm/api.txt linux-libre-3.2-gnu/Documentation/virtual/kvm/api.txt
--- linux-libre-3.1-gnu/Documentation/virtual/kvm/api.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/virtual/kvm/api.txt	2012-01-04 18:55:44.000000000 -0500
@@ -175,10 +175,30 @@
 Returns: vcpu fd on success, -1 on error
 
 This API adds a vcpu to a virtual machine.  The vcpu id is a small integer
-in the range [0, max_vcpus).  You can use KVM_CAP_NR_VCPUS of the
-KVM_CHECK_EXTENSION ioctl() to determine the value for max_vcpus at run-time.
+in the range [0, max_vcpus).
+
+The recommended max_vcpus value can be retrieved using the KVM_CAP_NR_VCPUS of
+the KVM_CHECK_EXTENSION ioctl() at run-time.
+The maximum possible value for max_vcpus can be retrieved using the
+KVM_CAP_MAX_VCPUS of the KVM_CHECK_EXTENSION ioctl() at run-time.
+
 If the KVM_CAP_NR_VCPUS does not exist, you should assume that max_vcpus is 4
 cpus max.
+If the KVM_CAP_MAX_VCPUS does not exist, you should assume that max_vcpus is
+same as the value returned from KVM_CAP_NR_VCPUS.
+
+On powerpc using book3s_hv mode, the vcpus are mapped onto virtual
+threads in one or more virtual CPU cores.  (This is because the
+hardware requires all the hardware threads in a CPU core to be in the
+same partition.)  The KVM_CAP_PPC_SMT capability indicates the number
+of vcpus per virtual core (vcore).  The vcore id is obtained by
+dividing the vcpu id by the number of vcpus per vcore.  The vcpus in a
+given vcore will always be in the same physical core as each other
+(though that might be a different physical core from time to time).
+Userspace can control the threading (SMT) mode of the guest by its
+allocation of vcpu ids.  For example, if userspace wants
+single-threaded guest vcpus, it should make all vcpu ids be a multiple
+of the number of vcpus per vcore.
 
 On powerpc using book3s_hv mode, the vcpus are mapped onto virtual
 threads in one or more virtual CPU cores.  (This is because the
@@ -1080,6 +1100,15 @@
    eax, ebx, ecx, edx: the values returned by the cpuid instruction for
          this function/index combination
 
+The TSC deadline timer feature (CPUID leaf 1, ecx[24]) is always returned
+as false, since the feature depends on KVM_CREATE_IRQCHIP for local APIC
+support.  Instead it is reported via
+
+  ioctl(KVM_CHECK_EXTENSION, KVM_CAP_TSC_DEADLINE_TIMER)
+
+if that returns true and you use KVM_CREATE_IRQCHIP, or if you emulate the
+feature in userspace, then you can enable the feature for KVM_SET_CPUID2.
+
 4.47 KVM_PPC_GET_PVINFO
 
 Capability: KVM_CAP_PPC_GET_PVINFO
@@ -1131,6 +1160,13 @@
 /* Depends on KVM_CAP_IOMMU */
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU	(1 << 0)
 
+The KVM_DEV_ASSIGN_ENABLE_IOMMU flag is a mandatory option to ensure
+isolation of the device.  Usages not specifying this flag are deprecated.
+
+Only PCI header type 0 devices with PCI BAR resources are supported by
+device assignment.  The user requesting this ioctl must have read/write
+access to the PCI sysfs resource files associated with the device.
+
 4.49 KVM_DEASSIGN_PCI_DEVICE
 
 Capability: KVM_CAP_DEVICE_DEASSIGNMENT
@@ -1633,3 +1669,50 @@
 		char padding[256];
 	};
 };
+
+6. Capabilities that can be enabled
+
+There are certain capabilities that change the behavior of the virtual CPU when
+enabled. To enable them, please see section 4.37. Below you can find a list of
+capabilities and what their effect on the vCPU is when enabling them.
+
+The following information is provided along with the description:
+
+  Architectures: which instruction set architectures provide this ioctl.
+      x86 includes both i386 and x86_64.
+
+  Parameters: what parameters are accepted by the capability.
+
+  Returns: the return value.  General error numbers (EBADF, ENOMEM, EINVAL)
+      are not detailed, but errors with specific meanings are.
+
+6.1 KVM_CAP_PPC_OSI
+
+Architectures: ppc
+Parameters: none
+Returns: 0 on success; -1 on error
+
+This capability enables interception of OSI hypercalls that otherwise would
+be treated as normal system calls to be injected into the guest. OSI hypercalls
+were invented by Mac-on-Linux to have a standardized communication mechanism
+between the guest and the host.
+
+When this capability is enabled, KVM_EXIT_OSI can occur.
+
+6.2 KVM_CAP_PPC_PAPR
+
+Architectures: ppc
+Parameters: none
+Returns: 0 on success; -1 on error
+
+This capability enables interception of PAPR hypercalls. PAPR hypercalls are
+done using the hypercall instruction "sc 1".
+
+It also sets the guest privilege level to "supervisor" mode. Usually the guest
+runs in "hypervisor" privilege mode with a few missing features.
+
+In addition to the above, it changes the semantics of SDR1. In this mode, the
+HTAB address part of SDR1 contains an HVA instead of a GPA, as PAPR keeps the
+HTAB invisible to the guest.
+
+When this capability is enabled, KVM_EXIT_PAPR_HCALL can occur.
diff -druN linux-libre-3.1-gnu/Documentation/virtual/lguest/lguest.c linux-libre-3.2-gnu/Documentation/virtual/lguest/lguest.c
--- linux-libre-3.1-gnu/Documentation/virtual/lguest/lguest.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/virtual/lguest/lguest.c	2012-01-04 18:55:44.000000000 -0500
@@ -436,7 +436,7 @@
 
 	/*
 	 * Go back to the start of the file and read the header.  It should be
-	 * a Linux boot header (see Documentation/x86/i386/boot.txt)
+	 * a Linux boot header (see Documentation/x86/boot.txt)
 	 */
 	lseek(fd, 0, SEEK_SET);
 	read(fd, &boot, sizeof(boot));
diff -druN linux-libre-3.1-gnu/Documentation/virtual/uml/UserModeLinux-HOWTO.txt linux-libre-3.2-gnu/Documentation/virtual/uml/UserModeLinux-HOWTO.txt
--- linux-libre-3.1-gnu/Documentation/virtual/uml/UserModeLinux-HOWTO.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/virtual/uml/UserModeLinux-HOWTO.txt	2012-01-04 18:55:44.000000000 -0500
@@ -134,13 +134,13 @@
 
   ______________________________________________________________________
 
-  11..  IInnttrroodduuccttiioonn
+  1.  Introduction
 
   Welcome to User Mode Linux.  It's going to be fun.
 
 
 
-  11..11..  HHooww iiss UUsseerr MMooddee LLiinnuuxx DDiiffffeerreenntt??
+  1.1.  How is User Mode Linux Different?
 
   Normally, the Linux Kernel talks straight to your hardware (video
   card, keyboard, hard drives, etc), and any programs which run ask the
@@ -181,7 +181,7 @@
 
 
 
-  11..22..  WWhhyy WWoouulldd II WWaanntt UUsseerr MMooddee LLiinnuuxx??
+  1.2.  Why Would I Want User Mode Linux?
 
 
   1. If User Mode Linux crashes, your host kernel is still fine.
@@ -206,12 +206,12 @@
 
 
 
-  22..  CCoommppiilliinngg tthhee kkeerrnneell aanndd mmoodduulleess
+  2.  Compiling the kernel and modules
 
 
 
 
-  22..11..  CCoommppiilliinngg tthhee kkeerrnneell
+  2.1.  Compiling the kernel
 
 
   Compiling the user mode kernel is just like compiling any other
@@ -322,7 +322,7 @@
   bug fixes and enhancements that have gone into subsequent releases.
 
 
-  22..22..  CCoommppiilliinngg aanndd iinnssttaalllliinngg kkeerrnneell mmoodduulleess
+  2.2.  Compiling and installing kernel modules
 
   UML modules are built in the same way as the native kernel (with the
   exception of the 'ARCH=um' that you always need for UML):
@@ -386,19 +386,19 @@
 
 
 
-  22..33..  CCoommppiilliinngg aanndd iinnssttaalllliinngg uummll__uuttiilliittiieess
+  2.3.  Compiling and installing uml_utilities
 
   Many features of the UML kernel require a user-space helper program,
   so a uml_utilities package is distributed separately from the kernel
   patch which provides these helpers. Included within this is:
 
-  +o  port-helper - Used by consoles which connect to xterms or ports
+  o  port-helper - Used by consoles which connect to xterms or ports
 
-  +o  tunctl - Configuration tool to create and delete tap devices
+  o  tunctl - Configuration tool to create and delete tap devices
 
-  +o  uml_net - Setuid binary for automatic tap device configuration
+  o  uml_net - Setuid binary for automatic tap device configuration
 
-  +o  uml_switch - User-space virtual switch required for daemon
+  o  uml_switch - User-space virtual switch required for daemon
      transport
 
      The uml_utilities tree is compiled with:
@@ -423,11 +423,11 @@
 
 
 
-  33..  RRuunnnniinngg UUMMLL aanndd llooggggiinngg iinn
+  3.  Running UML and logging in
 
 
 
-  33..11..  RRuunnnniinngg UUMMLL
+  3.1.  Running UML
 
   It runs on 2.2.15 or later, and all 2.4 kernels.
 
@@ -454,7 +454,7 @@
 
 
 
-  33..22..  LLooggggiinngg iinn
+  3.2.  Logging in
 
 
 
@@ -468,7 +468,7 @@
 
   There are a couple of other ways to log in:
 
-  +o  On a virtual console
+  o  On a virtual console
 
 
 
@@ -480,7 +480,7 @@
 
 
 
-  +o  Over the serial line
+  o  Over the serial line
 
 
      In the boot output, find a line that looks like:
@@ -503,7 +503,7 @@
 
 
 
-  +o  Over the net
+  o  Over the net
 
 
      If the network is running, then you can telnet to the virtual
@@ -514,13 +514,13 @@
   down and the process will exit.
 
 
-  33..33..  EExxaammpplleess
+  3.3.  Examples
 
   Here are some examples of UML in action:
 
-  +o  A login session <http://user-mode-linux.sourceforge.net/login.html>
+  o  A login session <http://user-mode-linux.sourceforge.net/login.html>
 
-  +o  A virtual network <http://user-mode-linux.sourceforge.net/net.html>
+  o  A virtual network <http://user-mode-linux.sourceforge.net/net.html>
 
 
 
@@ -528,12 +528,12 @@
 
 
 
-  44..  UUMMLL oonn 22GG//22GG hhoossttss
+  4.  UML on 2G/2G hosts
 
 
 
 
-  44..11..  IInnttrroodduuccttiioonn
+  4.1.  Introduction
 
 
   Most Linux machines are configured so that the kernel occupies the
@@ -546,7 +546,7 @@
 
 
 
-  44..22..  TThhee pprroobblleemm
+  4.2.  The problem
 
 
   The prebuilt UML binaries on this site will not run on 2G/2G hosts
@@ -558,7 +558,7 @@
 
 
 
-  44..33..  TThhee ssoolluuttiioonn
+  4.3.  The solution
 
 
   The fix for this is to rebuild UML from source after enabling
@@ -576,7 +576,7 @@
 
 
 
-  55..  SSeettttiinngg uupp sseerriiaall lliinneess aanndd ccoonnssoolleess
+  5.  Setting up serial lines and consoles
 
 
   It is possible to attach UML serial lines and consoles to many types
@@ -586,12 +586,12 @@
   You can attach them to host ptys, ttys, file descriptors, and ports.
   This allows you to do things like
 
-  +o  have a UML console appear on an unused host console,
+  o  have a UML console appear on an unused host console,
 
-  +o  hook two virtual machines together by having one attach to a pty
+  o  hook two virtual machines together by having one attach to a pty
      and having the other attach to the corresponding tty
 
-  +o  make a virtual machine accessible from the net by attaching a
+  o  make a virtual machine accessible from the net by attaching a
      console to a port on the host.
 
 
@@ -599,7 +599,7 @@
 
 
 
-  55..11..  SSppeecciiffyyiinngg tthhee ddeevviiccee
+  5.1.  Specifying the device
 
   Devices are specified with "con" or "ssl" (console or serial line,
   respectively), optionally with a device number if you are talking
@@ -626,13 +626,13 @@
 
 
 
-  55..22..  SSppeecciiffyyiinngg tthhee cchhaannnneell
+  5.2.  Specifying the channel
 
   There are a number of different types of channels to attach a UML
   device to, each with a different way of specifying exactly what to
   attach to.
 
-  +o  pseudo-terminals - device=pty pts terminals - device=pts
+  o  pseudo-terminals - device=pty pts terminals - device=pts
 
 
      This will cause UML to allocate a free host pseudo-terminal for the
@@ -640,20 +640,20 @@
      log.  You access it by attaching a terminal program to the
      corresponding tty:
 
-  +o  screen /dev/pts/n
+  o  screen /dev/pts/n
 
-  +o  screen /dev/ttyxx
+  o  screen /dev/ttyxx
 
-  +o  minicom -o -p /dev/ttyxx - minicom seems not able to handle pts
+  o  minicom -o -p /dev/ttyxx - minicom seems not able to handle pts
      devices
 
-  +o  kermit - start it up, 'open' the device, then 'connect'
+  o  kermit - start it up, 'open' the device, then 'connect'
 
 
 
 
 
-  +o  terminals - device=tty:tty device file
+  o  terminals - device=tty:tty device file
 
 
      This will make UML attach the device to the specified tty (i.e
@@ -672,7 +672,7 @@
 
 
 
-  +o  xterms - device=xterm
+  o  xterms - device=xterm
 
 
      UML will run an xterm and the device will be attached to it.
@@ -681,7 +681,7 @@
 
 
 
-  +o  Port - device=port:port number
+  o  Port - device=port:port number
 
 
      This will attach the UML devices to the specified host port.
@@ -725,7 +725,7 @@
 
 
 
-  +o  already-existing file descriptors - device=file descriptor
+  o  already-existing file descriptors - device=file descriptor
 
 
      If you set up a file descriptor on the UML command line, you can
@@ -743,7 +743,7 @@
 
 
 
-  +o  Nothing - device=null
+  o  Nothing - device=null
 
 
      This allows the device to be opened, in contrast to 'none', but
@@ -754,7 +754,7 @@
 
 
 
-  +o  None - device=none
+  o  None - device=none
 
 
      This causes the device to disappear.
@@ -770,7 +770,7 @@
 
 
 
-  will cause serial line 3 to accept input on the host's /dev/tty3 and
+  will cause serial line 3 to accept input on the host's /dev/tty2 and
   display output on an xterm.  That's a silly example - the most common
   use of this syntax is to reattach the main console to stdin and stdout
   as shown above.
@@ -785,7 +785,7 @@
 
 
 
-  55..33..  EExxaammpplleess
+  5.3.  Examples
 
   There are a number of interesting things you can do with this
   capability.
@@ -838,7 +838,7 @@
   prompt of the other virtual machine.
 
 
-  66..  SSeettttiinngg uupp tthhee nneettwwoorrkk
+  6.  Setting up the network
 
 
 
@@ -858,19 +858,19 @@
   There are currently five transport types available for a UML virtual
   machine to exchange packets with other hosts:
 
-  +o  ethertap
+  o  ethertap
 
-  +o  TUN/TAP
+  o  TUN/TAP
 
-  +o  Multicast
+  o  Multicast
 
-  +o  a switch daemon
+  o  a switch daemon
 
-  +o  slip
+  o  slip
 
-  +o  slirp
+  o  slirp
 
-  +o  pcap
+  o  pcap
 
      The TUN/TAP, ethertap, slip, and slirp transports allow a UML
      instance to exchange packets with the host.  They may be directed
@@ -893,28 +893,28 @@
   With so many host transports, which one should you use?  Here's when
   you should use each one:
 
-  +o  ethertap - if you want access to the host networking and it is
+  o  ethertap - if you want access to the host networking and it is
      running 2.2
 
-  +o  TUN/TAP - if you want access to the host networking and it is
+  o  TUN/TAP - if you want access to the host networking and it is
      running 2.4.  Also, the TUN/TAP transport is able to use a
      preconfigured device, allowing it to avoid using the setuid uml_net
      helper, which is a security advantage.
 
-  +o  Multicast - if you want a purely virtual network and you don't want
+  o  Multicast - if you want a purely virtual network and you don't want
      to set up anything but the UML
 
-  +o  a switch daemon - if you want a purely virtual network and you
+  o  a switch daemon - if you want a purely virtual network and you
      don't mind running the daemon in order to get somewhat better
      performance
 
-  +o  slip - there is no particular reason to run the slip backend unless
+  o  slip - there is no particular reason to run the slip backend unless
      ethertap and TUN/TAP are just not available for some reason
 
-  +o  slirp - if you don't have root access on the host to setup
+  o  slirp - if you don't have root access on the host to setup
      networking, or if you don't want to allocate an IP to your UML
 
-  +o  pcap - not much use for actual network connectivity, but great for
+  o  pcap - not much use for actual network connectivity, but great for
      monitoring traffic on the host
 
      Ethertap is available on 2.4 and works fine.  TUN/TAP is preferred
@@ -926,7 +926,7 @@
      exploit the helper's root privileges.
 
 
-  66..11..  GGeenneerraall sseettuupp
+  6.1.  General setup
 
   First, you must have the virtual network enabled in your UML.  If are
   running a prebuilt kernel from this site, everything is already
@@ -995,7 +995,7 @@
 
 
 
-  66..22..  UUsseerrssppaaccee ddaaeemmoonnss
+  6.2.  Userspace daemons
 
   You will likely need the setuid helper, or the switch daemon, or both.
   They are both installed with the RPM and deb, so if you've installed
@@ -1011,7 +1011,7 @@
 
 
 
-  66..33..  SSppeecciiffyyiinngg eetthheerrnneett aaddddrreesssseess
+  6.3.  Specifying ethernet addresses
 
   Below, you will see that the TUN/TAP, ethertap, and daemon interfaces
   allow you to specify hardware addresses for the virtual ethernet
@@ -1023,11 +1023,11 @@
   sufficient to guarantee a unique hardware address for the device.  A
   couple of exceptions are:
 
-  +o  Another set of virtual ethernet devices are on the same network and
+  o  Another set of virtual ethernet devices are on the same network and
      they are assigned hardware addresses using a different scheme which
      may conflict with the UML IP address-based scheme
 
-  +o  You aren't going to use the device for IP networking, so you don't
+  o  You aren't going to use the device for IP networking, so you don't
      assign the device an IP address
 
      If you let the driver provide the hardware address, you should make
@@ -1049,7 +1049,7 @@
 
 
 
-  66..44..  UUMMLL iinntteerrffaaccee sseettuupp
+  6.4.  UML interface setup
 
   Once the network devices have been described on the command line, you
   should boot UML and log in.
@@ -1131,7 +1131,7 @@
 
 
 
-  66..55..  MMuullttiiccaasstt
+  6.5.  Multicast
 
   The simplest way to set up a virtual network between multiple UMLs is
   to use the mcast transport.  This was written by Harald Welte and is
@@ -1194,7 +1194,7 @@
 
 
 
-  66..66..  TTUUNN//TTAAPP wwiitthh tthhee uummll__nneett hheellppeerr
+  6.6.  TUN/TAP with the uml_net helper
 
   TUN/TAP is the preferred mechanism on 2.4 to exchange packets with the
   host.  The TUN/TAP backend has been in UML since 2.4.9-3um.
@@ -1247,10 +1247,10 @@
   There are a couple potential problems with running the TUN/TAP
   transport on a 2.4 host kernel
 
-  +o  TUN/TAP seems not to work on 2.4.3 and earlier.  Upgrade the host
+  o  TUN/TAP seems not to work on 2.4.3 and earlier.  Upgrade the host
      kernel or use the ethertap transport.
 
-  +o  With an upgraded kernel, TUN/TAP may fail with
+  o  With an upgraded kernel, TUN/TAP may fail with
 
 
        File descriptor in bad state
@@ -1269,7 +1269,7 @@
 
 
 
-  66..77..  TTUUNN//TTAAPP wwiitthh aa pprreeccoonnffiigguurreedd ttaapp ddeevviiccee
+  6.7.  TUN/TAP with a preconfigured tap device
 
   If you prefer not to have UML use uml_net (which is somewhat
   insecure), with UML 2.4.17-11, you can set up a TUN/TAP device
@@ -1277,7 +1277,7 @@
   there is no need for root assistance.  Setting up the device is done
   as follows:
 
-  +o  Create the device with tunctl (available from the UML utilities
+  o  Create the device with tunctl (available from the UML utilities
      tarball)
 
 
@@ -1291,7 +1291,7 @@
   where uid is the user id or username that UML will be run as.  This
   will tell you what device was created.
 
-  +o  Configure the device IP (change IP addresses and device name to
+  o  Configure the device IP (change IP addresses and device name to
      suit)
 
 
@@ -1303,7 +1303,7 @@
 
 
 
-  +o  Set up routing and arping if desired - this is my recipe, there are
+  o  Set up routing and arping if desired - this is my recipe, there are
      other ways of doing the same thing
 
 
@@ -1338,7 +1338,7 @@
   utility which reads the information from a config file and sets up
   devices at boot time.
 
-  +o  Rather than using up two IPs and ARPing for one of them, you can
+  o  Rather than using up two IPs and ARPing for one of them, you can
      also provide direct access to your LAN by the UML by using a
      bridge.
 
@@ -1417,7 +1417,7 @@
   Note that 'br0' should be setup using ifconfig with the existing IP
   address of eth0, as eth0 no longer has its own IP.
 
-  +o
+  o
 
 
      Also, the /dev/net/tun device must be writable by the user running
@@ -1438,11 +1438,11 @@
   devices and chgrp /dev/net/tun to that group with mode 664 or 660.
 
 
-  +o  Once the device is set up, run UML with 'eth0=tuntap,device name'
+  o  Once the device is set up, run UML with 'eth0=tuntap,device name'
      (i.e. 'eth0=tuntap,tap0') on the command line (or do it with the
      mconsole config command).
 
-  +o  Bring the eth device up in UML and you're in business.
+  o  Bring the eth device up in UML and you're in business.
 
      If you don't want that tap device any more, you can make it non-
      persistent with
@@ -1465,7 +1465,7 @@
 
 
 
-  66..88..  EEtthheerrttaapp
+  6.8.  Ethertap
 
   Ethertap is the general mechanism on 2.2 for userspace processes to
   exchange packets with the kernel.
@@ -1561,9 +1561,9 @@
 
 
 
-  66..99..  TThhee sswwiittcchh ddaaeemmoonn
+  6.9.  The switch daemon
 
-  NNoottee: This is the daemon formerly known as uml_router, but which was
+  Note: This is the daemon formerly known as uml_router, but which was
   renamed so the network weenies of the world would stop growling at me.
 
 
@@ -1649,7 +1649,7 @@
 
 
 
-  66..1100..  SSlliipp
+  6.10.  Slip
 
   Slip is another, less general, mechanism for a process to communicate
   with the host networking.  In contrast to the ethertap interface,
@@ -1681,7 +1681,7 @@
 
 
 
-  66..1111..  SSlliirrpp
+  6.11.  Slirp
 
   slirp uses an external program, usually /usr/bin/slirp, to provide IP
   only networking connectivity through the host. This is similar to IP
@@ -1737,7 +1737,7 @@
 
 
 
-  66..1122..  ppccaapp
+  6.12.  pcap
 
   The pcap transport is attached to a UML ethernet device on the command
   line or with uml_mconsole with the following syntax:
@@ -1777,7 +1777,7 @@
 
 
 
-  66..1133..  SSeettttiinngg uupp tthhee hhoosstt yyoouurrsseellff
+  6.13.  Setting up the host yourself
 
   If you don't specify an address for the host side of the ethertap or
   slip device, UML won't do any setup on the host.  So this is what is
@@ -1785,7 +1785,7 @@
   192.168.0.251 and a UML-side IP of 192.168.0.250 - adjust to suit your
   own network):
 
-  +o  The device needs to be configured with its IP address.  Tap devices
+  o  The device needs to be configured with its IP address.  Tap devices
      are also configured with an mtu of 1484.  Slip devices are
      configured with a point-to-point address pointing at the UML ip
      address.
@@ -1805,7 +1805,7 @@
 
 
 
-  +o  If a tap device is being set up, a route is set to the UML IP.
+  o  If a tap device is being set up, a route is set to the UML IP.
 
 
        UML# route add -host 192.168.0.250 gw 192.168.0.251
@@ -1814,7 +1814,7 @@
 
 
 
-  +o  To allow other hosts on your network to see the virtual machine,
+  o  To allow other hosts on your network to see the virtual machine,
      proxy arp is set up for it.
 
 
@@ -1824,7 +1824,7 @@
 
 
 
-  +o  Finally, the host is set up to route packets.
+  o  Finally, the host is set up to route packets.
 
 
        host#  echo 1 > /proc/sys/net/ipv4/ip_forward
@@ -1838,12 +1838,12 @@
 
 
 
-  77..  SShhaarriinngg FFiilleessyysstteemmss bbeettwweeeenn VViirrttuuaall MMaacchhiinneess
+  7.  Sharing Filesystems between Virtual Machines
 
 
 
 
-  77..11..  AA wwaarrnniinngg
+  7.1.  A warning
 
   Don't attempt to share filesystems simply by booting two UMLs from the
   same file.  That's the same thing as booting two physical machines
@@ -1851,7 +1851,7 @@
 
 
 
-  77..22..  UUssiinngg llaayyeerreedd bblloocckk ddeevviicceess
+  7.2.  Using layered block devices
 
   The way to share a filesystem between two virtual machines is to use
   the copy-on-write (COW) layering capability of the ubd block driver.
@@ -1896,7 +1896,7 @@
 
 
 
-  77..33..  NNoottee!!
+  7.3.  Note!
 
   When checking the size of the COW file in order to see the gobs of
   space that you're saving, make sure you use 'ls -ls' to see the actual
@@ -1926,7 +1926,7 @@
 
 
 
-  77..44..  AAnnootthheerr wwaarrnniinngg
+  7.4.  Another warning
 
   Once a filesystem is being used as a readonly backing file for a COW
   file, do not boot directly from it or modify it in any way.  Doing so
@@ -1952,7 +1952,7 @@
 
 
 
-  77..55..  uummll__mmoooo :: MMeerrggiinngg aa CCOOWW ffiillee wwiitthh iittss bbaacckkiinngg ffiillee
+  7.5.  uml_moo : Merging a COW file with its backing file
 
   Depending on how you use UML and COW devices, it may be advisable to
   merge the changes in the COW file into the backing file every once in
@@ -2001,7 +2001,7 @@
 
 
 
-  88..  CCrreeaattiinngg ffiilleessyysstteemmss
+  8.  Creating filesystems
 
 
   You may want to create and mount new UML filesystems, either because
@@ -2015,7 +2015,7 @@
   should be easy to translate to the filesystem of your choice.
 
 
-  88..11..  CCrreeaattee tthhee ffiilleessyysstteemm ffiillee
+  8.1.  Create the filesystem file
 
   dd is your friend.  All you need to do is tell dd to create an empty
   file of the appropriate size.  I usually make it sparse to save time
@@ -2032,7 +2032,7 @@
 
 
 
-  88..22..  AAssssiiggnn tthhee ffiillee ttoo aa UUMMLL ddeevviiccee
+  8.2.  Assign the file to a UML device
 
   Add an argument like the following to the UML command line:
 
@@ -2045,7 +2045,7 @@
 
 
 
-  88..33..  CCrreeaattiinngg aanndd mmoouunnttiinngg tthhee ffiilleessyysstteemm
+  8.3.  Creating and mounting the filesystem
 
   Make sure that the filesystem is available, either by being built into
   the kernel, or available as a module, then boot up UML and log in.  If
@@ -2096,7 +2096,7 @@
 
 
 
-  99..  HHoosstt ffiillee aacccceessss
+  9.  Host file access
 
 
   If you want to access files on the host machine from inside UML, you
@@ -2112,7 +2112,7 @@
   files contained in it just as you would on the host.
 
 
-  99..11..  UUssiinngg hhoossttffss
+  9.1.  Using hostfs
 
   To begin with, make sure that hostfs is available inside the virtual
   machine with
@@ -2151,7 +2151,7 @@
 
 
 
-  99..22..  hhoossttffss aass tthhee rroooott ffiilleessyysstteemm
+  9.2.  hostfs as the root filesystem
 
   It's possible to boot from a directory hierarchy on the host using
   hostfs rather than using the standard filesystem in a file.
@@ -2194,20 +2194,20 @@
   UML should then boot as it does normally.
 
 
-  99..33..  BBuuiillddiinngg hhoossttffss
+  9.3.  Building hostfs
 
   If you need to build hostfs because it's not in your kernel, you have
   two choices:
 
 
 
-  +o  Compiling hostfs into the kernel:
+  o  Compiling hostfs into the kernel:
 
 
      Reconfigure the kernel and set the 'Host filesystem' option under
 
 
-  +o  Compiling hostfs as a module:
+  o  Compiling hostfs as a module:
 
 
      Reconfigure the kernel and set the 'Host filesystem' option under
@@ -2228,7 +2228,7 @@
 
 
 
-  1100..  TThhee MMaannaaggeemmeenntt CCoonnssoollee
+  10.  The Management Console
 
 
 
@@ -2240,15 +2240,15 @@
 
   There are a number of things you can do with the mconsole interface:
 
-  +o  get the kernel version
+  o  get the kernel version
 
-  +o  add and remove devices
+  o  add and remove devices
 
-  +o  halt or reboot the machine
+  o  halt or reboot the machine
 
-  +o  Send SysRq commands
+  o  Send SysRq commands
 
-  +o  Pause and resume the UML
+  o  Pause and resume the UML
 
 
   You need the mconsole client (uml_mconsole) which is present in CVS
@@ -2300,28 +2300,28 @@
 
   You'll get a prompt, at which you can run one of these commands:
 
-  +o  version
+  o  version
 
-  +o  halt
+  o  halt
 
-  +o  reboot
+  o  reboot
 
-  +o  config
+  o  config
 
-  +o  remove
+  o  remove
 
-  +o  sysrq
+  o  sysrq
 
-  +o  help
+  o  help
 
-  +o  cad
+  o  cad
 
-  +o  stop
+  o  stop
 
-  +o  go
+  o  go
 
 
-  1100..11..  vveerrssiioonn
+  10.1.  version
 
   This takes no arguments.  It prints the UML version.
 
@@ -2342,7 +2342,7 @@
 
 
 
-  1100..22..  hhaalltt aanndd rreebboooott
+  10.2.  halt and reboot
 
   These take no arguments.  They shut the machine down immediately, with
   no syncing of disks and no clean shutdown of userspace.  So, they are
@@ -2357,7 +2357,7 @@
 
 
 
-  1100..33..  ccoonnffiigg
+  10.3.  config
 
   "config" adds a new device to the virtual machine.  Currently the ubd
   and network drivers support this.  It takes one argument, which is the
@@ -2378,7 +2378,7 @@
 
 
 
-  1100..44..  rreemmoovvee
+  10.4.  remove
 
   "remove" deletes a device from the system.  Its argument is just the
   name of the device to be removed. The device must be idle in whatever
@@ -2397,7 +2397,7 @@
 
 
 
-  1100..55..  ssyyssrrqq
+  10.5.  sysrq
 
   This takes one argument, which is a single letter.  It calls the
   generic kernel's SysRq driver, which does whatever is called for by
@@ -2407,14 +2407,14 @@
 
 
 
-  1100..66..  hheellpp
+  10.6.  help
 
   "help" returns a string listing the valid commands and what each one
   does.
 
 
 
-  1100..77..  ccaadd
+  10.7.  cad
 
   This invokes the Ctl-Alt-Del action on init.  What exactly this ends
   up doing is up to /etc/inittab.  Normally, it reboots the machine.
@@ -2432,7 +2432,7 @@
 
 
 
-  1100..88..  ssttoopp
+  10.8.  stop
 
   This puts the UML in a loop reading mconsole requests until a 'go'
   mconsole command is received. This is very useful for making backups
@@ -2448,7 +2448,7 @@
 
 
 
-  1100..99..  ggoo
+  10.9.  go
 
   This resumes a UML after being paused by a 'stop' command. Note that
   when the UML has resumed, TCP connections may have timed out and if
@@ -2462,10 +2462,10 @@
 
 
 
-  1111..  KKeerrnneell ddeebbuuggggiinngg
+  11.  Kernel debugging
 
 
-  NNoottee:: The interface that makes debugging, as described here, possible
+  Note: The interface that makes debugging, as described here, possible
   is present in 2.4.0-test6 kernels and later.
 
 
@@ -2485,7 +2485,7 @@
 
 
 
-  1111..11..  SSttaarrttiinngg tthhee kkeerrnneell uunnddeerr ggddbb
+  11.1.  Starting the kernel under gdb
 
   You can have the kernel running under the control of gdb from the
   beginning by putting 'debug' on the command line.  You will get an
@@ -2498,7 +2498,7 @@
   There is a transcript of a debugging session  here <debug-
   session.html> , with breakpoints being set in the scheduler and in an
   interrupt handler.
-  1111..22..  EExxaammiinniinngg sslleeeeppiinngg pprroocceesssseess
+  11.2.  Examining sleeping processes
 
   Not every bug is evident in the currently running process.  Sometimes,
   processes hang in the kernel when they shouldn't because they've
@@ -2516,7 +2516,7 @@
 
   Now what you do is this:
 
-  +o  detach from the current thread
+  o  detach from the current thread
 
 
        (UML gdb)  det
@@ -2525,7 +2525,7 @@
 
 
 
-  +o  attach to the thread you are interested in
+  o  attach to the thread you are interested in
 
 
        (UML gdb)  att <host pid>
@@ -2534,7 +2534,7 @@
 
 
 
-  +o  look at its stack and anything else of interest
+  o  look at its stack and anything else of interest
 
 
        (UML gdb)  bt
@@ -2545,7 +2545,7 @@
   Note that you can't do anything at this point that requires that a
   process execute, e.g. calling a function
 
-  +o  when you're done looking at that process, reattach to the current
+  o  when you're done looking at that process, reattach to the current
      thread and continue it
 
 
@@ -2569,12 +2569,12 @@
 
 
 
-  1111..33..  RRuunnnniinngg dddddd oonn UUMMLL
+  11.3.  Running ddd on UML
 
   ddd works on UML, but requires a special kludge.  The process goes
   like this:
 
-  +o  Start ddd
+  o  Start ddd
 
 
        host% ddd linux
@@ -2583,14 +2583,14 @@
 
 
 
-  +o  With ps, get the pid of the gdb that ddd started.  You can ask the
+  o  With ps, get the pid of the gdb that ddd started.  You can ask the
      gdb to tell you, but for some reason that confuses things and
      causes a hang.
 
-  +o  run UML with 'debug=parent gdb-pid=<pid>' added to the command line
+  o  run UML with 'debug=parent gdb-pid=<pid>' added to the command line
      - it will just sit there after you hit return
 
-  +o  type 'att 1' to the ddd gdb and you will see something like
+  o  type 'att 1' to the ddd gdb and you will see something like
 
 
        0xa013dc51 in __kill ()
@@ -2602,12 +2602,12 @@
 
 
 
-  +o  At this point, type 'c', UML will boot up, and you can use ddd just
+  o  At this point, type 'c', UML will boot up, and you can use ddd just
      as you do on any other process.
 
 
 
-  1111..44..  DDeebbuuggggiinngg mmoodduulleess
+  11.4.  Debugging modules
 
   gdb has support for debugging code which is dynamically loaded into
   the process.  This support is what is needed to debug kernel modules
@@ -2823,7 +2823,7 @@
 
 
 
-  1111..55..  AAttttaacchhiinngg ggddbb ttoo tthhee kkeerrnneell
+  11.5.  Attaching gdb to the kernel
 
   If you don't have the kernel running under gdb, you can attach gdb to
   it later by sending the tracing thread a SIGUSR1.  The first line of
@@ -2857,7 +2857,7 @@
 
 
 
-  1111..66..  UUssiinngg aalltteerrnnaattee ddeebbuuggggeerrss
+  11.6.  Using alternate debuggers
 
   UML has support for attaching to an already running debugger rather
   than starting gdb itself.  This is present in CVS as of 17 Apr 2001.
@@ -2886,7 +2886,7 @@
   An example of an alternate debugger is strace.  You can strace the
   actual kernel as follows:
 
-  +o  Run the following in a shell
+  o  Run the following in a shell
 
 
        host%
@@ -2894,10 +2894,10 @@
 
 
 
-  +o  Run UML with 'debug' and 'gdb-pid=<pid>' with the pid printed out
+  o  Run UML with 'debug' and 'gdb-pid=<pid>' with the pid printed out
      by the previous command
 
-  +o  Hit return in the shell, and UML will start running, and strace
+  o  Hit return in the shell, and UML will start running, and strace
      output will start accumulating in the output file.
 
      Note that this is different from running
@@ -2917,9 +2917,9 @@
 
 
 
-  1122..  KKeerrnneell ddeebbuuggggiinngg eexxaammpplleess
+  12.  Kernel debugging examples
 
-  1122..11..  TThhee ccaassee ooff tthhee hhuunngg ffsscckk
+  12.1.  The case of the hung fsck
 
   When booting up the kernel, fsck failed, and dropped me into a shell
   to fix things up.  I ran fsck -y, which hung:
@@ -3154,9 +3154,9 @@
 
   The interesting things here are :
 
-  +o  There are two segfaults on this stack (frames 9 and 14)
+  o  There are two segfaults on this stack (frames 9 and 14)
 
-  +o  The first faulting address (frame 11) is 0x50000800
+  o  The first faulting address (frame 11) is 0x50000800
 
   (gdb) p (void *)1342179328
   $16 = (void *) 0x50000800
@@ -3399,7 +3399,7 @@
   on will be somewhat clearer.
 
 
-  1122..22..  EEppiissooddee 22:: TThhee ccaassee ooff tthhee hhuunngg ffsscckk
+  12.2.  Episode 2: The case of the hung fsck
 
   After setting a trap in the SEGV handler for accesses to the signal
   thread's stack, I reran the kernel.
@@ -3788,12 +3788,12 @@
 
 
 
-  1133..  WWhhaatt ttoo ddoo wwhheenn UUMMLL ddooeessnn''tt wwoorrkk
+  13.  What to do when UML doesn't work
 
 
 
 
-  1133..11..  SSttrraannggee ccoommppiillaattiioonn eerrrroorrss wwhheenn yyoouu bbuuiilldd ffrroomm ssoouurrccee
+  13.1.  Strange compilation errors when you build from source
 
   As of test11, it is necessary to have "ARCH=um" in the environment or
   on the make command line for all steps in building UML, including
@@ -3824,8 +3824,8 @@
 
 
 
-  1133..33..  AA vvaarriieettyy ooff ppaanniiccss aanndd hhaannggss wwiitthh //ttmmpp oonn aa rreeiisseerrffss  ffiilleessyyss--
-  tteemm
+  13.3.  A variety of panics and hangs with /tmp on a reiserfs  filesys-
+  tem
 
   I saw this on reiserfs 3.5.21 and it seems to be fixed in 3.5.27.
   Panics preceded by
@@ -3842,8 +3842,8 @@
 
 
 
-  1133..44..  TThhee ccoommppiillee ffaaiillss wwiitthh eerrrroorrss aabboouutt ccoonnfflliiccttiinngg ttyyppeess ffoorr
-  ''ooppeenn'',, ''dduupp'',, aanndd ''wwaaiittppiidd''
+  13.4.  The compile fails with errors about conflicting types for
+  'open', 'dup', and 'waitpid'
 
   This happens when you build in /usr/src/linux.  The UML build makes
   the include/asm link point to include/asm-um.  /usr/include/asm points
@@ -3854,14 +3854,14 @@
 
 
 
-  1133..55..  UUMMLL ddooeessnn''tt wwoorrkk wwhheenn //ttmmpp iiss aann NNFFSS ffiilleessyysstteemm
+  13.5.  UML doesn't work when /tmp is an NFS filesystem
 
   This seems to be a similar situation with the ReiserFS problem above.
   Some versions of NFS seems not to handle mmap correctly, which UML
   depends on.  The workaround is have /tmp be a non-NFS directory.
 
 
-  1133..66..  UUMMLL hhaannggss oonn bboooott wwhheenn ccoommppiilleedd wwiitthh ggpprrooff ssuuppppoorrtt
+  13.6.  UML hangs on boot when compiled with gprof support
 
   If you build UML with gprof support and, early in the boot, it does
   this
@@ -3878,7 +3878,7 @@
 
 
 
-  1133..77..  ssyyssllooggdd ddiieess wwiitthh aa SSIIGGTTEERRMM oonn ssttaarrttuupp
+  13.7.  syslogd dies with a SIGTERM on startup
 
   The exact boot error depends on the distribution that you're booting,
   but Debian produces this:
@@ -3897,17 +3897,17 @@
 
 
 
-  1133..88..  TTUUNN//TTAAPP nneettwwoorrkkiinngg ddooeessnn''tt wwoorrkk oonn aa 22..44 hhoosstt
+  13.8.  TUN/TAP networking doesn't work on a 2.4 host
 
   There are a couple of problems which were
   <http://www.geocrawler.com/lists/3/SourceForge/597/0/> name="pointed
   out">  by Tim Robinson <timro at trkr dot net>
 
-  +o  It doesn't work on hosts running 2.4.7 (or thereabouts) or earlier.
+  o  It doesn't work on hosts running 2.4.7 (or thereabouts) or earlier.
      The fix is to upgrade to something more recent and then read the
      next item.
 
-  +o  If you see
+  o  If you see
 
 
        File descriptor in bad state
@@ -3921,8 +3921,8 @@
 
 
 
-  1133..99..  YYoouu ccaann nneettwwoorrkk ttoo tthhee hhoosstt bbuutt nnoott ttoo ootthheerr mmaacchhiinneess oonn tthhee
-  nneett
+  13.9.  You can network to the host but not to other machines on the
+  net
 
   If you can connect to the host, and the host can connect to UML, but
   you cannot connect to any other machines, then you may need to enable
@@ -3972,7 +3972,7 @@
 
 
 
-  1133..1100..  II hhaavvee nnoo rroooott aanndd II wwaanntt ttoo ssccrreeaamm
+  13.10.  I have no root and I want to scream
 
   Thanks to Birgit Wahlich for telling me about this strange one.  It
   turns out that there's a limit of six environment variables on the
@@ -3987,7 +3987,7 @@
 
 
 
-  1133..1111..  UUMMLL bbuuiilldd ccoonnfflliicctt bbeettwweeeenn ppttrraaccee..hh aanndd uuccoonntteexxtt..hh
+  13.11.  UML build conflict between ptrace.h and ucontext.h
 
   On some older systems, /usr/include/asm/ptrace.h and
   /usr/include/sys/ucontext.h define the same names.  So, when they're
@@ -4007,7 +4007,7 @@
 
 
 
-  1133..1122..  TThhee UUMMLL BBooggooMMiippss iiss eexxaaccttllyy hhaallff tthhee hhoosstt''ss BBooggooMMiippss
+  13.12.  The UML BogoMips is exactly half the host's BogoMips
 
   On i386 kernels, there are two ways of running the loop that is used
   to calculate the BogoMips rating, using the TSC if it's there or using
@@ -4019,7 +4019,7 @@
 
 
 
-  1133..1133..  WWhheenn yyoouu rruunn UUMMLL,, iitt iimmmmeeddiiaatteellyy sseeggffaauullttss
+  13.13.  When you run UML, it immediately segfaults
 
   If the host is configured with the 2G/2G address space split, that's
   why.  See ``UML on 2G/2G hosts''  for the details on getting UML to
@@ -4027,7 +4027,7 @@
 
 
 
-  1133..1144..  xxtteerrmmss aappppeeaarr,, tthheenn iimmmmeeddiiaatteellyy ddiissaappppeeaarr
+  13.14.  xterms appear, then immediately disappear
 
   If you're running an up to date kernel with an old release of
   uml_utilities, the port-helper program will not work properly, so
@@ -4039,7 +4039,7 @@
 
 
 
-  1133..1155..  AAnnyy ootthheerr ppaanniicc,, hhaanngg,, oorr ssttrraannggee bbeehhaavviioorr
+  13.15.  Any other panic, hang, or strange behavior
 
   If you're seeing truly strange behavior, such as hangs or panics that
   happen in random places, or you try running the debugger to see what's
@@ -4059,7 +4059,7 @@
 
   If you want to be super-helpful, read ``Diagnosing Problems'' and
   follow the instructions contained therein.
-  1144..  DDiiaaggnnoossiinngg PPrroobblleemmss
+  14.  Diagnosing Problems
 
 
   If you get UML to crash, hang, or otherwise misbehave, you should
@@ -4078,7 +4078,7 @@
   ``Kernel debugging''  UML first.
 
 
-  1144..11..  CCaassee 11 :: NNoorrmmaall kkeerrnneell ppaanniiccss
+  14.1.  Case 1 : Normal kernel panics
 
   The most common case is for a normal thread to panic.  To debug this,
   you will need to run it under the debugger (add 'debug' to the command
@@ -4128,7 +4128,7 @@
   to get that information from the faulting ip.
 
 
-  1144..22..  CCaassee 22 :: TTrraacciinngg tthhrreeaadd ppaanniiccss
+  14.2.  Case 2 : Tracing thread panics
 
   The less common and more painful case is when the tracing thread
   panics.  In this case, the kernel debugger will be useless because it
@@ -4161,7 +4161,7 @@
   backtrace in and wait for our crack debugging team to fix the problem.
 
 
-  1144..33..  CCaassee 33 :: TTrraacciinngg tthhrreeaadd ppaanniiccss ccaauusseedd bbyy ootthheerr tthhrreeaaddss
+  14.3.  Case 3 : Tracing thread panics caused by other threads
 
   However, there are cases where the misbehavior of another thread
   caused the problem.  The most common panic of this type is:
@@ -4227,7 +4227,7 @@
 
 
 
-  1144..44..  CCaassee 44 :: HHaannggss
+  14.4.  Case 4 : Hangs
 
   Hangs seem to be fairly rare, but they sometimes happen.  When a hang
   happens, we need a backtrace from the offending process.  Run the
@@ -4257,7 +4257,7 @@
 
 
 
-  1155..  TThhaannkkss
+  15.  Thanks
 
 
   A number of people have helped this project in various ways, and this
@@ -4274,20 +4274,20 @@
   bookkeeping lapses and I forget about contributions.
 
 
-  1155..11..  CCooddee aanndd DDooccuummeennttaattiioonn
+  15.1.  Code and Documentation
 
   Rusty Russell <rusty at linuxcare.com.au>  -
 
-  +o  wrote the  HOWTO <http://user-mode-
+  o  wrote the  HOWTO <http://user-mode-
      linux.sourceforge.net/UserModeLinux-HOWTO.html>
 
-  +o  prodded me into making this project official and putting it on
+  o  prodded me into making this project official and putting it on
      SourceForge
 
-  +o  came up with the way cool UML logo <http://user-mode-
+  o  came up with the way cool UML logo <http://user-mode-
      linux.sourceforge.net/uml-small.png>
 
-  +o  redid the config process
+  o  redid the config process
 
 
   Peter Moulder <reiter at netspace.net.au>  - Fixed my config and build
@@ -4296,18 +4296,18 @@
 
   Bill Stearns <wstearns at pobox.com>  -
 
-  +o  HOWTO updates
+  o  HOWTO updates
 
-  +o  lots of bug reports
+  o  lots of bug reports
 
-  +o  lots of testing
+  o  lots of testing
 
-  +o  dedicated a box (uml.ists.dartmouth.edu) to support UML development
+  o  dedicated a box (uml.ists.dartmouth.edu) to support UML development
 
-  +o  wrote the mkrootfs script, which allows bootable filesystems of
+  o  wrote the mkrootfs script, which allows bootable filesystems of
      RPM-based distributions to be cranked out
 
-  +o  cranked out a large number of filesystems with said script
+  o  cranked out a large number of filesystems with said script
 
 
   Jim Leu <jleu at mindspring.com>  - Wrote the virtual ethernet driver
@@ -4375,176 +4375,176 @@
 
   David Coulson <http://davidcoulson.net>  -
 
-  +o  Set up the usermodelinux.org <http://usermodelinux.org>  site,
+  o  Set up the usermodelinux.org <http://usermodelinux.org>  site,
      which is a great way of keeping the UML user community on top of
      UML goings-on.
 
-  +o  Site documentation and updates
+  o  Site documentation and updates
 
-  +o  Nifty little UML management daemon  UMLd
+  o  Nifty little UML management daemon  UMLd
      <http://uml.openconsultancy.com/umld/>
 
-  +o  Lots of testing and bug reports
+  o  Lots of testing and bug reports
 
 
 
 
-  1155..22..  FFlluusshhiinngg oouutt bbuuggss
+  15.2.  Flushing out bugs
 
 
 
-  +o  Yuri Pudgorodsky
+  o  Yuri Pudgorodsky
 
-  +o  Gerald Britton
+  o  Gerald Britton
 
-  +o  Ian Wehrman
+  o  Ian Wehrman
 
-  +o  Gord Lamb
+  o  Gord Lamb
 
-  +o  Eugene Koontz
+  o  Eugene Koontz
 
-  +o  John H. Hartman
+  o  John H. Hartman
 
-  +o  Anders Karlsson
+  o  Anders Karlsson
 
-  +o  Daniel Phillips
+  o  Daniel Phillips
 
-  +o  John Fremlin
+  o  John Fremlin
 
-  +o  Rainer Burgstaller
+  o  Rainer Burgstaller
 
-  +o  James Stevenson
+  o  James Stevenson
 
-  +o  Matt Clay
+  o  Matt Clay
 
-  +o  Cliff Jefferies
+  o  Cliff Jefferies
 
-  +o  Geoff Hoff
+  o  Geoff Hoff
 
-  +o  Lennert Buytenhek
+  o  Lennert Buytenhek
 
-  +o  Al Viro
+  o  Al Viro
 
-  +o  Frank Klingenhoefer
+  o  Frank Klingenhoefer
 
-  +o  Livio Baldini Soares
+  o  Livio Baldini Soares
 
-  +o  Jon Burgess
+  o  Jon Burgess
 
-  +o  Petru Paler
+  o  Petru Paler
 
-  +o  Paul
+  o  Paul
 
-  +o  Chris Reahard
+  o  Chris Reahard
 
-  +o  Sverker Nilsson
+  o  Sverker Nilsson
 
-  +o  Gong Su
+  o  Gong Su
 
-  +o  johan verrept
+  o  johan verrept
 
-  +o  Bjorn Eriksson
+  o  Bjorn Eriksson
 
-  +o  Lorenzo Allegrucci
+  o  Lorenzo Allegrucci
 
-  +o  Muli Ben-Yehuda
+  o  Muli Ben-Yehuda
 
-  +o  David Mansfield
+  o  David Mansfield
 
-  +o  Howard Goff
+  o  Howard Goff
 
-  +o  Mike Anderson
+  o  Mike Anderson
 
-  +o  John Byrne
+  o  John Byrne
 
-  +o  Sapan J. Batia
+  o  Sapan J. Batia
 
-  +o  Iris Huang
+  o  Iris Huang
 
-  +o  Jan Hudec
+  o  Jan Hudec
 
-  +o  Voluspa
+  o  Voluspa
 
 
 
 
-  1155..33..  BBuugglleettss aanndd cclleeaann--uuppss
+  15.3.  Buglets and clean-ups
 
 
 
-  +o  Dave Zarzycki
+  o  Dave Zarzycki
 
-  +o  Adam Lazur
+  o  Adam Lazur
 
-  +o  Boria Feigin
+  o  Boria Feigin
 
-  +o  Brian J. Murrell
+  o  Brian J. Murrell
 
-  +o  JS
+  o  JS
 
-  +o  Roman Zippel
+  o  Roman Zippel
 
-  +o  Wil Cooley
+  o  Wil Cooley
 
-  +o  Ayelet Shemesh
+  o  Ayelet Shemesh
 
-  +o  Will Dyson
+  o  Will Dyson
 
-  +o  Sverker Nilsson
+  o  Sverker Nilsson
 
-  +o  dvorak
+  o  dvorak
 
-  +o  v.naga srinivas
+  o  v.naga srinivas
 
-  +o  Shlomi Fish
+  o  Shlomi Fish
 
-  +o  Roger Binns
+  o  Roger Binns
 
-  +o  johan verrept
+  o  johan verrept
 
-  +o  MrChuoi
+  o  MrChuoi
 
-  +o  Peter Cleve
+  o  Peter Cleve
 
-  +o  Vincent Guffens
+  o  Vincent Guffens
 
-  +o  Nathan Scott
+  o  Nathan Scott
 
-  +o  Patrick Caulfield
+  o  Patrick Caulfield
 
-  +o  jbearce
+  o  jbearce
 
-  +o  Catalin Marinas
+  o  Catalin Marinas
 
-  +o  Shane Spencer
+  o  Shane Spencer
 
-  +o  Zou Min
+  o  Zou Min
 
 
-  +o  Ryan Boder
+  o  Ryan Boder
 
-  +o  Lorenzo Colitti
+  o  Lorenzo Colitti
 
-  +o  Gwendal Grignou
+  o  Gwendal Grignou
 
-  +o  Andre' Breiler
+  o  Andre' Breiler
 
-  +o  Tsutomu Yasuda
+  o  Tsutomu Yasuda
 
 
 
-  1155..44..  CCaassee SSttuuddiieess
+  15.4.  Case Studies
 
 
-  +o  Jon Wright
+  o  Jon Wright
 
-  +o  William McEwan
+  o  William McEwan
 
-  +o  Michael Richardson
+  o  Michael Richardson
 
 
 
-  1155..55..  OOtthheerr ccoonnttrriibbuuttiioonnss
+  15.5.  Other contributions
 
 
   Bill Carr <Bill.Carr at compaq.com>  made the Red Hat mkrootfs script
diff -druN linux-libre-3.1-gnu/Documentation/vm/00-INDEX linux-libre-3.2-gnu/Documentation/vm/00-INDEX
--- linux-libre-3.1-gnu/Documentation/vm/00-INDEX	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/vm/00-INDEX	2012-01-04 18:55:44.000000000 -0500
@@ -30,8 +30,6 @@
 	- description of page migration in NUMA systems.
 pagemap.txt
 	- pagemap, from the userspace perspective
-slabinfo.c
-	- source code for a tool to get reports about slabs.
 slub.txt
 	- a short users guide for SLUB.
 unevictable-lru.txt
diff -druN linux-libre-3.1-gnu/Documentation/vm/numa linux-libre-3.2-gnu/Documentation/vm/numa
--- linux-libre-3.1-gnu/Documentation/vm/numa	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/vm/numa	2012-01-04 18:55:44.000000000 -0500
@@ -109,11 +109,11 @@
 such as taskset(1) and numactl(1), and program interfaces such as
 sched_setaffinity(2).  Further, one can modify the kernel's default local
 allocation behavior using Linux NUMA memory policy.
-[see Documentation/vm/numa_memory_policy.]
+[see Documentation/vm/numa_memory_policy.txt.]
 
 System administrators can restrict the CPUs and nodes' memories that a non-
 privileged user can specify in the scheduling or NUMA commands and functions
-using control groups and CPUsets.  [see Documentation/cgroups/CPUsets.txt]
+using control groups and CPUsets.  [see Documentation/cgroups/cpusets.txt]
 
 On architectures that do not hide memoryless nodes, Linux will include only
 zones [nodes] with memory in the zonelists.  This means that for a memoryless
diff -druN linux-libre-3.1-gnu/Documentation/vm/slub.txt linux-libre-3.2-gnu/Documentation/vm/slub.txt
--- linux-libre-3.1-gnu/Documentation/vm/slub.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/vm/slub.txt	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
 slabs that have data in them. See "slabinfo -h" for more options when
 running the command. slabinfo can be compiled with
 
-gcc -o slabinfo Documentation/vm/slabinfo.c
+gcc -o slabinfo tools/slub/slabinfo.c
 
 Some of the modes of operation of slabinfo require that slub debugging
 be enabled on the command line. F.e. no tracking information will be
diff -druN linux-libre-3.1-gnu/Documentation/watchdog/convert_drivers_to_kernel_api.txt linux-libre-3.2-gnu/Documentation/watchdog/convert_drivers_to_kernel_api.txt
--- linux-libre-3.1-gnu/Documentation/watchdog/convert_drivers_to_kernel_api.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/Documentation/watchdog/convert_drivers_to_kernel_api.txt	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,195 @@
+Converting old watchdog drivers to the watchdog framework
+by Wolfram Sang <w.sang@pengutronix.de>
+=========================================================
+
+Before the watchdog framework came into the kernel, every driver had to
+implement the API on its own. Now, as the framework factored out the common
+components, those drivers can be lightened making it a user of the framework.
+This document shall guide you for this task. The necessary steps are described
+as well as things to look out for.
+
+
+Remove the file_operations struct
+---------------------------------
+
+Old drivers define their own file_operations for actions like open(), write(),
+etc... These are now handled by the framework and just call the driver when
+needed. So, in general, the 'file_operations' struct and assorted functions can
+go. Only very few driver-specific details have to be moved to other functions.
+Here is a overview of the functions and probably needed actions:
+
+- open: Everything dealing with resource management (file-open checks, magic
+  close preparations) can simply go. Device specific stuff needs to go to the
+  driver specific start-function. Note that for some drivers, the start-function
+  also serves as the ping-function. If that is the case and you need start/stop
+  to be balanced (clocks!), you are better off refactoring a separate start-function.
+
+- close: Same hints as for open apply.
+
+- write: Can simply go, all defined behaviour is taken care of by the framework,
+  i.e. ping on write and magic char ('V') handling.
+
+- ioctl: While the driver is allowed to have extensions to the IOCTL interface,
+  the most common ones are handled by the framework, supported by some assistance
+  from the driver:
+
+	WDIOC_GETSUPPORT:
+		Returns the mandatory watchdog_info struct from the driver
+
+	WDIOC_GETSTATUS:
+		Needs the status-callback defined, otherwise returns 0
+
+	WDIOC_GETBOOTSTATUS:
+		Needs the bootstatus member properly set. Make sure it is 0 if you
+		don't have further support!
+
+	WDIOC_SETOPTIONS:
+		No preparations needed
+
+	WDIOC_KEEPALIVE:
+		If wanted, options in watchdog_info need to have WDIOF_KEEPALIVEPING
+		set
+
+	WDIOC_SETTIMEOUT:
+		Options in watchdog_info need to have WDIOF_SETTIMEOUT set
+		and a set_timeout-callback has to be defined. The core will also
+		do limit-checking, if min_timeout and max_timeout in the watchdog
+		device are set. All is optional.
+
+	WDIOC_GETTIMEOUT:
+		No preparations needed
+
+  Other IOCTLs can be served using the ioctl-callback. Note that this is mainly
+  intended for porting old drivers; new drivers should not invent private IOCTLs.
+  Private IOCTLs are processed first. When the callback returns with
+  -ENOIOCTLCMD, the IOCTLs of the framework will be tried, too. Any other error
+  is directly given to the user.
+
+Example conversion:
+
+-static const struct file_operations s3c2410wdt_fops = {
+-       .owner          = THIS_MODULE,
+-       .llseek         = no_llseek,
+-       .write          = s3c2410wdt_write,
+-       .unlocked_ioctl = s3c2410wdt_ioctl,
+-       .open           = s3c2410wdt_open,
+-       .release        = s3c2410wdt_release,
+-};
+
+Check the functions for device-specific stuff and keep it for later
+refactoring. The rest can go.
+
+
+Remove the miscdevice
+---------------------
+
+Since the file_operations are gone now, you can also remove the 'struct
+miscdevice'. The framework will create it on watchdog_dev_register() called by
+watchdog_register_device().
+
+-static struct miscdevice s3c2410wdt_miscdev = {
+-       .minor          = WATCHDOG_MINOR,
+-       .name           = "watchdog",
+-       .fops           = &s3c2410wdt_fops,
+-};
+
+
+Remove obsolete includes and defines
+------------------------------------
+
+Because of the simplifications, a few defines are probably unused now. Remove
+them. Includes can be removed, too. For example:
+
+- #include <linux/fs.h>
+- #include <linux/miscdevice.h> (if MODULE_ALIAS_MISCDEV is not used)
+- #include <linux/uaccess.h> (if no custom IOCTLs are used)
+
+
+Add the watchdog operations
+---------------------------
+
+All possible callbacks are defined in 'struct watchdog_ops'. You can find it
+explained in 'watchdog-kernel-api.txt' in this directory. start(), stop() and
+owner must be set, the rest are optional. You will easily find corresponding
+functions in the old driver. Note that you will now get a pointer to the
+watchdog_device as a parameter to these functions, so you probably have to
+change the function header. Other changes are most likely not needed, because
+here simply happens the direct hardware access. If you have device-specific
+code left from the above steps, it should be refactored into these callbacks.
+
+Here is a simple example:
+
++static struct watchdog_ops s3c2410wdt_ops = {
++       .owner = THIS_MODULE,
++       .start = s3c2410wdt_start,
++       .stop = s3c2410wdt_stop,
++       .ping = s3c2410wdt_keepalive,
++       .set_timeout = s3c2410wdt_set_heartbeat,
++};
+
+A typical function-header change looks like:
+
+-static void s3c2410wdt_keepalive(void)
++static int s3c2410wdt_keepalive(struct watchdog_device *wdd)
+ {
+...
++
++       return 0;
+ }
+
+...
+
+-       s3c2410wdt_keepalive();
++       s3c2410wdt_keepalive(&s3c2410_wdd);
+
+
+Add the watchdog device
+-----------------------
+
+Now we need to create a 'struct watchdog_device' and populate it with the
+necessary information for the framework. The struct is also explained in detail
+in 'watchdog-kernel-api.txt' in this directory. We pass it the mandatory
+watchdog_info struct and the newly created watchdog_ops. Often, old drivers
+have their own record-keeping for things like bootstatus and timeout using
+static variables. Those have to be converted to use the members in
+watchdog_device. Note that the timeout values are unsigned int. Some drivers
+use signed int, so this has to be converted, too.
+
+Here is a simple example for a watchdog device:
+
++static struct watchdog_device s3c2410_wdd = {
++       .info = &s3c2410_wdt_ident,
++       .ops = &s3c2410wdt_ops,
++};
+
+
+Register the watchdog device
+----------------------------
+
+Replace misc_register(&miscdev) with watchdog_register_device(&watchdog_dev).
+Make sure the return value gets checked and the error message, if present,
+still fits. Also convert the unregister case.
+
+-       ret = misc_register(&s3c2410wdt_miscdev);
++       ret = watchdog_register_device(&s3c2410_wdd);
+
+...
+
+-       misc_deregister(&s3c2410wdt_miscdev);
++       watchdog_unregister_device(&s3c2410_wdd);
+
+
+Update the Kconfig-entry
+------------------------
+
+The entry for the driver now needs to select WATCHDOG_CORE:
+
++       select WATCHDOG_CORE
+
+
+Create a patch and send it to upstream
+--------------------------------------
+
+Make sure you understood Documentation/SubmittingPatches and send your patch to
+linux-watchdog@vger.kernel.org. We are looking forward to it :)
+
diff -druN linux-libre-3.1-gnu/Documentation/x86/entry_64.txt linux-libre-3.2-gnu/Documentation/x86/entry_64.txt
--- linux-libre-3.1-gnu/Documentation/x86/entry_64.txt	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/x86/entry_64.txt	2012-01-04 18:55:44.000000000 -0500
@@ -27,9 +27,6 @@
    magically-generated functions that make their way to do_IRQ with
    the interrupt number as a parameter.
 
- - emulate_vsyscall: int 0xcc, a special non-ABI entry used by
-   vsyscall emulation.
-
  - APIC interrupts: Various special-purpose interrupts for things
    like TLB shootdown.
 
diff -druN linux-libre-3.1-gnu/Documentation/zh_CN/SubmitChecklist linux-libre-3.2-gnu/Documentation/zh_CN/SubmitChecklist
--- linux-libre-3.1-gnu/Documentation/zh_CN/SubmitChecklist	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/Documentation/zh_CN/SubmitChecklist	1969-12-31 19:00:00.000000000 -0500
@@ -1,109 +0,0 @@
-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_ATOMIC_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-3.1-gnu/drivers/acpi/acpica/evxface.c linux-libre-3.2-gnu/drivers/acpi/acpica/evxface.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/evxface.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/evxface.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/evxfevnt.c linux-libre-3.2-gnu/drivers/acpi/acpica/evxfevnt.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/evxfevnt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/evxfevnt.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "actables.h"
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/evxfgpe.c linux-libre-3.2-gnu/drivers/acpi/acpica/evxfgpe.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/evxfgpe.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/evxfgpe.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acevents.h"
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/evxfregn.c linux-libre-3.2-gnu/drivers/acpi/acpica/evxfregn.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/evxfregn.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/evxfregn.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/hwregs.c linux-libre-3.2-gnu/drivers/acpi/acpica/hwregs.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/hwregs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/hwregs.c	2012-01-04 18:55:44.000000000 -0500
@@ -269,16 +269,17 @@
 
 	status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
 					ACPI_BITMASK_ALL_FIXED_STATUS);
-	if (ACPI_FAILURE(status)) {
-		goto unlock_and_exit;
-	}
+
+	acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
+
+	if (ACPI_FAILURE(status))
+		goto exit;
 
 	/* Clear the GPE Bits in all GPE registers in all GPE blocks */
 
 	status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
 
-      unlock_and_exit:
-	acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
+exit:
 	return_ACPI_STATUS(status);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/hwsleep.c linux-libre-3.2-gnu/drivers/acpi/acpica/hwsleep.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/hwsleep.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/hwsleep.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,6 +46,7 @@
 #include "accommon.h"
 #include "actables.h"
 #include <linux/tboot.h>
+#include <linux/module.h>
 
 #define _COMPONENT          ACPI_HARDWARE
 ACPI_MODULE_NAME("hwsleep")
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/hwtimer.c linux-libre-3.2-gnu/drivers/acpi/acpica/hwtimer.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/hwtimer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/hwtimer.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/hwxface.c linux-libre-3.2-gnu/drivers/acpi/acpica/hwxface.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/hwxface.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/hwxface.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/nsxfeval.c linux-libre-3.2-gnu/drivers/acpi/acpica/nsxfeval.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/nsxfeval.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/nsxfeval.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/nsxfname.c linux-libre-3.2-gnu/drivers/acpi/acpica/nsxfname.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/nsxfname.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/nsxfname.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/nsxfobj.c linux-libre-3.2-gnu/drivers/acpi/acpica/nsxfobj.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/nsxfobj.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/nsxfobj.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/rsxface.c linux-libre-3.2-gnu/drivers/acpi/acpica/rsxface.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/rsxface.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/rsxface.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acresrc.h"
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/tbxface.c linux-libre-3.2-gnu/drivers/acpi/acpica/tbxface.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/tbxface.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/tbxface.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/utdebug.c linux-libre-3.2-gnu/drivers/acpi/acpica/utdebug.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/utdebug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/utdebug.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/utdecode.c linux-libre-3.2-gnu/drivers/acpi/acpica/utdecode.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/utdecode.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/utdecode.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/utglobal.c linux-libre-3.2-gnu/drivers/acpi/acpica/utglobal.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/utglobal.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/utglobal.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@
 
 #define DEFINE_ACPI_GLOBALS
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/utxface.c linux-libre-3.2-gnu/drivers/acpi/acpica/utxface.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/utxface.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/utxface.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acevents.h"
diff -druN linux-libre-3.1-gnu/drivers/acpi/acpica/utxferror.c linux-libre-3.2-gnu/drivers/acpi/acpica/utxferror.c
--- linux-libre-3.1-gnu/drivers/acpi/acpica/utxferror.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/acpica/utxferror.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+#include <linux/export.h>
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
diff -druN linux-libre-3.1-gnu/drivers/acpi/apei/erst.c linux-libre-3.2-gnu/drivers/acpi/apei/erst.c
--- linux-libre-3.1-gnu/drivers/acpi/apei/erst.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/apei/erst.c	2012-01-04 18:55:44.000000000 -0500
@@ -932,8 +932,9 @@
 static int erst_open_pstore(struct pstore_info *psi);
 static int erst_close_pstore(struct pstore_info *psi);
 static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
-			   struct timespec *time, struct pstore_info *psi);
-static u64 erst_writer(enum pstore_type_id type, unsigned int part,
+			   struct timespec *time, char **buf,
+			   struct pstore_info *psi);
+static int erst_writer(enum pstore_type_id type, u64 *id, unsigned int part,
 		       size_t size, struct pstore_info *psi);
 static int erst_clearer(enum pstore_type_id type, u64 id,
 			struct pstore_info *psi);
@@ -986,17 +987,23 @@
 }
 
 static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
-			   struct timespec *time, struct pstore_info *psi)
+			   struct timespec *time, char **buf,
+			   struct pstore_info *psi)
 {
 	int rc;
 	ssize_t len = 0;
 	u64 record_id;
-	struct cper_pstore_record *rcd = (struct cper_pstore_record *)
-					(erst_info.buf - sizeof(*rcd));
+	struct cper_pstore_record *rcd;
+	size_t rcd_len = sizeof(*rcd) + erst_info.bufsize;
 
 	if (erst_disable)
 		return -ENODEV;
 
+	rcd = kmalloc(rcd_len, GFP_KERNEL);
+	if (!rcd) {
+		rc = -ENOMEM;
+		goto out;
+	}
 skip:
 	rc = erst_get_record_id_next(&reader_pos, &record_id);
 	if (rc)
@@ -1004,22 +1011,27 @@
 
 	/* no more record */
 	if (record_id == APEI_ERST_INVALID_RECORD_ID) {
-		rc = -1;
+		rc = -EINVAL;
 		goto out;
 	}
 
-	len = erst_read(record_id, &rcd->hdr, sizeof(*rcd) +
-			erst_info.bufsize);
+	len = erst_read(record_id, &rcd->hdr, rcd_len);
 	/* The record may be cleared by others, try read next record */
 	if (len == -ENOENT)
 		goto skip;
-	else if (len < 0) {
-		rc = -1;
+	else if (len < sizeof(*rcd)) {
+		rc = -EIO;
 		goto out;
 	}
 	if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0)
 		goto skip;
 
+	*buf = kmalloc(len, GFP_KERNEL);
+	if (*buf == NULL) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	memcpy(*buf, rcd->data, len - sizeof(*rcd));
 	*id = record_id;
 	if (uuid_le_cmp(rcd->sec_hdr.section_type,
 			CPER_SECTION_TYPE_DMESG) == 0)
@@ -1037,14 +1049,16 @@
 	time->tv_nsec = 0;
 
 out:
+	kfree(rcd);
 	return (rc < 0) ? rc : (len - sizeof(*rcd));
 }
 
-static u64 erst_writer(enum pstore_type_id type, unsigned int part,
+static int erst_writer(enum pstore_type_id type, u64 *id, unsigned int part,
 		       size_t size, struct pstore_info *psi)
 {
 	struct cper_pstore_record *rcd = (struct cper_pstore_record *)
 					(erst_info.buf - sizeof(*rcd));
+	int ret;
 
 	memset(rcd, 0, sizeof(*rcd));
 	memcpy(rcd->hdr.signature, CPER_SIG_RECORD, CPER_SIG_SIZE);
@@ -1079,9 +1093,10 @@
 	}
 	rcd->sec_hdr.section_severity = CPER_SEV_FATAL;
 
-	erst_write(&rcd->hdr);
+	ret = erst_write(&rcd->hdr);
+	*id = rcd->hdr.record_id;
 
-	return rcd->hdr.record_id;
+	return ret;
 }
 
 static int erst_clearer(enum pstore_type_id type, u64 id,
@@ -1165,7 +1180,7 @@
 		goto err_release_erange;
 
 	buf = kmalloc(erst_erange.size, GFP_KERNEL);
-	mutex_init(&erst_info.buf_mutex);
+	spin_lock_init(&erst_info.buf_lock);
 	if (buf) {
 		erst_info.buf = buf + sizeof(struct cper_pstore_record);
 		erst_info.bufsize = erst_erange.size -
diff -druN linux-libre-3.1-gnu/drivers/acpi/apei/ghes.c linux-libre-3.2-gnu/drivers/acpi/apei/ghes.c
--- linux-libre-3.1-gnu/drivers/acpi/apei/ghes.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/apei/ghes.c	2012-01-04 18:55:44.000000000 -0500
@@ -50,6 +50,7 @@
 #include <acpi/hed.h>
 #include <asm/mce.h>
 #include <asm/tlbflush.h>
+#include <asm/nmi.h>
 
 #include "apei-internal.h"
 
@@ -749,15 +750,11 @@
 	}
 }
 
-static int ghes_notify_nmi(struct notifier_block *this,
-				  unsigned long cmd, void *data)
+static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs)
 {
 	struct ghes *ghes, *ghes_global = NULL;
 	int sev, sev_global = -1;
-	int ret = NOTIFY_DONE;
-
-	if (cmd != DIE_NMI)
-		return ret;
+	int ret = NMI_DONE;
 
 	raw_spin_lock(&ghes_nmi_lock);
 	list_for_each_entry_rcu(ghes, &ghes_nmi, list) {
@@ -770,10 +767,10 @@
 			sev_global = sev;
 			ghes_global = ghes;
 		}
-		ret = NOTIFY_STOP;
+		ret = NMI_HANDLED;
 	}
 
-	if (ret == NOTIFY_DONE)
+	if (ret == NMI_DONE)
 		goto out;
 
 	if (sev_global >= GHES_SEV_PANIC) {
@@ -825,10 +822,6 @@
 	.notifier_call = ghes_notify_sci,
 };
 
-static struct notifier_block ghes_notifier_nmi = {
-	.notifier_call = ghes_notify_nmi,
-};
-
 static unsigned long ghes_esource_prealloc_size(
 	const struct acpi_hest_generic *generic)
 {
@@ -918,7 +911,8 @@
 		ghes_estatus_pool_expand(len);
 		mutex_lock(&ghes_list_mutex);
 		if (list_empty(&ghes_nmi))
-			register_die_notifier(&ghes_notifier_nmi);
+			register_nmi_handler(NMI_LOCAL, ghes_notify_nmi, 0,
+						"ghes");
 		list_add_rcu(&ghes->list, &ghes_nmi);
 		mutex_unlock(&ghes_list_mutex);
 		break;
@@ -964,7 +958,7 @@
 		mutex_lock(&ghes_list_mutex);
 		list_del_rcu(&ghes->list);
 		if (list_empty(&ghes_nmi))
-			unregister_die_notifier(&ghes_notifier_nmi);
+			unregister_nmi_handler(NMI_LOCAL, "ghes");
 		mutex_unlock(&ghes_list_mutex);
 		/*
 		 * To synchronize with NMI handler, ghes can only be
diff -druN linux-libre-3.1-gnu/drivers/acpi/apei/Kconfig linux-libre-3.2-gnu/drivers/acpi/apei/Kconfig
--- linux-libre-3.1-gnu/drivers/acpi/apei/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/apei/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,6 @@
 	depends on ACPI_APEI && X86
 	select ACPI_HED
 	select IRQ_WORK
-	select LLIST
 	select GENERIC_ALLOCATOR
 	help
 	  Generic Hardware Error Source provides a way to report
diff -druN linux-libre-3.1-gnu/drivers/acpi/atomicio.c linux-libre-3.2-gnu/drivers/acpi/atomicio.c
--- linux-libre-3.1-gnu/drivers/acpi/atomicio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/atomicio.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <linux/io.h>
@@ -76,7 +76,7 @@
 {
 	struct acpi_iomap *map;
 
-	map = __acpi_find_iomap(paddr, size);
+	map = __acpi_find_iomap(paddr, size/8);
 	if (map)
 		return map->vaddr + (paddr - map->paddr);
 	else
diff -druN linux-libre-3.1-gnu/drivers/acpi/blacklist.c linux-libre-3.2-gnu/drivers/acpi/blacklist.c
--- linux-libre-3.1-gnu/drivers/acpi/blacklist.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/blacklist.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <acpi/acpi_bus.h>
diff -druN linux-libre-3.1-gnu/drivers/acpi/bus.c linux-libre-3.2-gnu/drivers/acpi/bus.c
--- linux-libre-3.1-gnu/drivers/acpi/bus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/bus.c	2012-01-04 18:55:44.000000000 -0500
@@ -911,10 +911,7 @@
 	}
 #endif
 
-	status =
-	    acpi_enable_subsystem(~
-				  (ACPI_NO_HARDWARE_INIT |
-				   ACPI_NO_ACPI_ENABLE));
+	status = acpi_enable_subsystem(~ACPI_NO_ACPI_ENABLE);
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_ERR PREFIX "Unable to enable ACPI\n");
 		goto error0;
@@ -935,8 +932,7 @@
 
 	acpi_os_initialize1();
 
-	status =
-	    acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE);
+	status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE);
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_ERR PREFIX
 		       "Unable to start the ACPI Interpreter\n");
diff -druN linux-libre-3.1-gnu/drivers/acpi/debugfs.c linux-libre-3.2-gnu/drivers/acpi/debugfs.c
--- linux-libre-3.1-gnu/drivers/acpi/debugfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/debugfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,7 @@
  * debugfs.c - ACPI debugfs interface to userspace.
  */
 
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/debugfs.h>
 #include <acpi/acpi_drivers.h>
diff -druN linux-libre-3.1-gnu/drivers/acpi/ec_sys.c linux-libre-3.2-gnu/drivers/acpi/ec_sys.c
--- linux-libre-3.1-gnu/drivers/acpi/ec_sys.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/ec_sys.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/acpi.h>
 #include <linux/debugfs.h>
+#include <linux/module.h>
 #include "internal.h"
 
 MODULE_AUTHOR("Thomas Renninger <trenn@suse.de>");
diff -druN linux-libre-3.1-gnu/drivers/acpi/event.c linux-libre-3.2-gnu/drivers/acpi/event.c
--- linux-libre-3.1-gnu/drivers/acpi/event.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/event.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/spinlock.h>
+#include <linux/export.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <linux/poll.h>
diff -druN linux-libre-3.1-gnu/drivers/acpi/glue.c linux-libre-3.2-gnu/drivers/acpi/glue.c
--- linux-libre-3.1-gnu/drivers/acpi/glue.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/glue.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
  *
  * This file is released under the GPLv2.
  */
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/device.h>
diff -druN linux-libre-3.1-gnu/drivers/acpi/osl.c linux-libre-3.2-gnu/drivers/acpi/osl.c
--- linux-libre-3.1-gnu/drivers/acpi/osl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/osl.c	2012-01-04 18:55:44.000000000 -0500
@@ -80,7 +80,8 @@
 static void *acpi_irq_context;
 static struct workqueue_struct *kacpid_wq;
 static struct workqueue_struct *kacpi_notify_wq;
-static struct workqueue_struct *kacpi_hotplug_wq;
+struct workqueue_struct *kacpi_hotplug_wq;
+EXPORT_SYMBOL(kacpi_hotplug_wq);
 
 struct acpi_res_list {
 	resource_size_t start;
diff -druN linux-libre-3.1-gnu/drivers/acpi/proc.c linux-libre-3.2-gnu/drivers/acpi/proc.c
--- linux-libre-3.1-gnu/drivers/acpi/proc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/proc.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/export.h>
 #include <linux/suspend.h>
 #include <linux/bcd.h>
 #include <asm/uaccess.h>
diff -druN linux-libre-3.1-gnu/drivers/acpi/processor_core.c linux-libre-3.2-gnu/drivers/acpi/processor_core.c
--- linux-libre-3.1-gnu/drivers/acpi/processor_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/processor_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
  *	Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
  *	- Added _PDC for platforms with Intel CPUs
  */
+#include <linux/export.h>
 #include <linux/dmi.h>
 #include <linux/slab.h>
 
diff -druN linux-libre-3.1-gnu/drivers/acpi/processor_driver.c linux-libre-3.2-gnu/drivers/acpi/processor_driver.c
--- linux-libre-3.1-gnu/drivers/acpi/processor_driver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/processor_driver.c	2012-01-04 18:55:44.000000000 -0500
@@ -426,7 +426,7 @@
 
 	if (action == CPU_ONLINE && pr) {
 		acpi_processor_ppc_has_changed(pr, 0);
-		acpi_processor_cst_has_changed(pr);
+		acpi_processor_hotplug(pr);
 		acpi_processor_reevaluate_tstate(pr, action);
 		acpi_processor_tstate_has_changed(pr);
 	}
@@ -503,8 +503,7 @@
 	acpi_processor_get_throttling_info(pr);
 	acpi_processor_get_limit_info(pr);
 
-
-	if (cpuidle_get_driver() == &acpi_idle_driver)
+	if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
 		acpi_processor_power_init(pr, device);
 
 	pr->cdev = thermal_cooling_device_register("Processor", device,
@@ -800,17 +799,9 @@
 
 	memset(&errata, 0, sizeof(errata));
 
-	if (!cpuidle_register_driver(&acpi_idle_driver)) {
-		printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
-			acpi_idle_driver.name);
-	} else {
-		printk(KERN_DEBUG "ACPI: acpi_idle yielding to %s\n",
-			cpuidle_get_driver()->name);
-	}
-
 	result = acpi_bus_register_driver(&acpi_processor_driver);
 	if (result < 0)
-		goto out_cpuidle;
+		return result;
 
 	acpi_processor_install_hotplug_notify();
 
@@ -821,11 +812,6 @@
 	acpi_processor_throttling_init();
 
 	return 0;
-
-out_cpuidle:
-	cpuidle_unregister_driver(&acpi_idle_driver);
-
-	return result;
 }
 
 static void __exit acpi_processor_exit(void)
diff -druN linux-libre-3.1-gnu/drivers/acpi/processor_idle.c linux-libre-3.2-gnu/drivers/acpi/processor_idle.c
--- linux-libre-3.1-gnu/drivers/acpi/processor_idle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/processor_idle.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,7 +37,7 @@
 #include <linux/dmi.h>
 #include <linux/moduleparam.h>
 #include <linux/sched.h>	/* need_resched() */
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
 #include <linux/clockchips.h>
 #include <linux/cpuidle.h>
 #include <linux/irqflags.h>
@@ -224,7 +224,6 @@
 /*
  * Suspend / resume control
  */
-static int acpi_idle_suspend;
 static u32 saved_bm_rld;
 
 static void acpi_idle_bm_rld_save(void)
@@ -243,21 +242,13 @@
 
 int acpi_processor_suspend(struct acpi_device * device, pm_message_t state)
 {
-	if (acpi_idle_suspend == 1)
-		return 0;
-
 	acpi_idle_bm_rld_save();
-	acpi_idle_suspend = 1;
 	return 0;
 }
 
 int acpi_processor_resume(struct acpi_device * device)
 {
-	if (acpi_idle_suspend == 0)
-		return 0;
-
 	acpi_idle_bm_rld_restore();
-	acpi_idle_suspend = 0;
 	return 0;
 }
 
@@ -741,66 +732,65 @@
 /**
  * acpi_idle_enter_c1 - enters an ACPI C1 state-type
  * @dev: the target CPU
- * @state: the state data
+ * @drv: cpuidle driver containing cpuidle state info
+ * @index: index of target state
  *
  * This is equivalent to the HALT instruction.
  */
 static int acpi_idle_enter_c1(struct cpuidle_device *dev,
-			      struct cpuidle_state *state)
+		struct cpuidle_driver *drv, int index)
 {
 	ktime_t  kt1, kt2;
 	s64 idle_time;
 	struct acpi_processor *pr;
-	struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+	struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+	struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
 
 	pr = __this_cpu_read(processors);
+	dev->last_residency = 0;
 
 	if (unlikely(!pr))
-		return 0;
+		return -EINVAL;
 
 	local_irq_disable();
 
-	/* Do not access any ACPI IO ports in suspend path */
-	if (acpi_idle_suspend) {
-		local_irq_enable();
-		cpu_relax();
-		return 0;
-	}
-
 	lapic_timer_state_broadcast(pr, cx, 1);
 	kt1 = ktime_get_real();
 	acpi_idle_do_entry(cx);
 	kt2 = ktime_get_real();
 	idle_time =  ktime_to_us(ktime_sub(kt2, kt1));
 
+	/* Update device last_residency*/
+	dev->last_residency = (int)idle_time;
+
 	local_irq_enable();
 	cx->usage++;
 	lapic_timer_state_broadcast(pr, cx, 0);
 
-	return idle_time;
+	return index;
 }
 
 /**
  * acpi_idle_enter_simple - enters an ACPI state without BM handling
  * @dev: the target CPU
- * @state: the state data
+ * @drv: cpuidle driver with cpuidle state information
+ * @index: the index of suggested state
  */
 static int acpi_idle_enter_simple(struct cpuidle_device *dev,
-				  struct cpuidle_state *state)
+		struct cpuidle_driver *drv, int index)
 {
 	struct acpi_processor *pr;
-	struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+	struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+	struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
 	ktime_t  kt1, kt2;
 	s64 idle_time_ns;
 	s64 idle_time;
 
 	pr = __this_cpu_read(processors);
+	dev->last_residency = 0;
 
 	if (unlikely(!pr))
-		return 0;
-
-	if (acpi_idle_suspend)
-		return(acpi_idle_enter_c1(dev, state));
+		return -EINVAL;
 
 	local_irq_disable();
 
@@ -815,7 +805,7 @@
 		if (unlikely(need_resched())) {
 			current_thread_info()->status |= TS_POLLING;
 			local_irq_enable();
-			return 0;
+			return -EINVAL;
 		}
 	}
 
@@ -837,6 +827,9 @@
 	idle_time = idle_time_ns;
 	do_div(idle_time, NSEC_PER_USEC);
 
+	/* Update device last_residency*/
+	dev->last_residency = (int)idle_time;
+
 	/* Tell the scheduler how much we idled: */
 	sched_clock_idle_wakeup_event(idle_time_ns);
 
@@ -848,46 +841,46 @@
 
 	lapic_timer_state_broadcast(pr, cx, 0);
 	cx->time += idle_time;
-	return idle_time;
+	return index;
 }
 
 static int c3_cpu_count;
-static DEFINE_SPINLOCK(c3_lock);
+static DEFINE_RAW_SPINLOCK(c3_lock);
 
 /**
  * acpi_idle_enter_bm - enters C3 with proper BM handling
  * @dev: the target CPU
- * @state: the state data
+ * @drv: cpuidle driver containing state data
+ * @index: the index of suggested state
  *
  * If BM is detected, the deepest non-C3 idle state is entered instead.
  */
 static int acpi_idle_enter_bm(struct cpuidle_device *dev,
-			      struct cpuidle_state *state)
+		struct cpuidle_driver *drv, int index)
 {
 	struct acpi_processor *pr;
-	struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
+	struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+	struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
 	ktime_t  kt1, kt2;
 	s64 idle_time_ns;
 	s64 idle_time;
 
 
 	pr = __this_cpu_read(processors);
+	dev->last_residency = 0;
 
 	if (unlikely(!pr))
-		return 0;
-
-	if (acpi_idle_suspend)
-		return(acpi_idle_enter_c1(dev, state));
+		return -EINVAL;
 
 	if (!cx->bm_sts_skip && acpi_idle_bm_check()) {
-		if (dev->safe_state) {
-			dev->last_state = dev->safe_state;
-			return dev->safe_state->enter(dev, dev->safe_state);
+		if (drv->safe_state_index >= 0) {
+			return drv->states[drv->safe_state_index].enter(dev,
+						drv, drv->safe_state_index);
 		} else {
 			local_irq_disable();
 			acpi_safe_halt();
 			local_irq_enable();
-			return 0;
+			return -EINVAL;
 		}
 	}
 
@@ -904,7 +897,7 @@
 		if (unlikely(need_resched())) {
 			current_thread_info()->status |= TS_POLLING;
 			local_irq_enable();
-			return 0;
+			return -EINVAL;
 		}
 	}
 
@@ -930,12 +923,12 @@
 	 * without doing anything.
 	 */
 	if (pr->flags.bm_check && pr->flags.bm_control) {
-		spin_lock(&c3_lock);
+		raw_spin_lock(&c3_lock);
 		c3_cpu_count++;
 		/* Disable bus master arbitration when all CPUs are in C3 */
 		if (c3_cpu_count == num_online_cpus())
 			acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1);
-		spin_unlock(&c3_lock);
+		raw_spin_unlock(&c3_lock);
 	} else if (!pr->flags.bm_check) {
 		ACPI_FLUSH_CPU_CACHE();
 	}
@@ -944,16 +937,19 @@
 
 	/* Re-enable bus master arbitration */
 	if (pr->flags.bm_check && pr->flags.bm_control) {
-		spin_lock(&c3_lock);
+		raw_spin_lock(&c3_lock);
 		acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0);
 		c3_cpu_count--;
-		spin_unlock(&c3_lock);
+		raw_spin_unlock(&c3_lock);
 	}
 	kt2 = ktime_get_real();
 	idle_time_ns = ktime_to_ns(ktime_sub(kt2, kt1));
 	idle_time = idle_time_ns;
 	do_div(idle_time, NSEC_PER_USEC);
 
+	/* Update device last_residency*/
+	dev->last_residency = (int)idle_time;
+
 	/* Tell the scheduler how much we idled: */
 	sched_clock_idle_wakeup_event(idle_time_ns);
 
@@ -965,7 +961,7 @@
 
 	lapic_timer_state_broadcast(pr, cx, 0);
 	cx->time += idle_time;
-	return idle_time;
+	return index;
 }
 
 struct cpuidle_driver acpi_idle_driver = {
@@ -974,14 +970,16 @@
 };
 
 /**
- * acpi_processor_setup_cpuidle - prepares and configures CPUIDLE
+ * acpi_processor_setup_cpuidle_cx - prepares and configures CPUIDLE
+ * device i.e. per-cpu data
+ *
  * @pr: the ACPI processor
  */
-static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
+static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr)
 {
 	int i, count = CPUIDLE_DRIVER_STATE_START;
 	struct acpi_processor_cx *cx;
-	struct cpuidle_state *state;
+	struct cpuidle_state_usage *state_usage;
 	struct cpuidle_device *dev = &pr->power.dev;
 
 	if (!pr->flags.power_setup_done)
@@ -992,9 +990,62 @@
 	}
 
 	dev->cpu = pr->id;
+
+	if (max_cstate == 0)
+		max_cstate = 1;
+
+	for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
+		cx = &pr->power.states[i];
+		state_usage = &dev->states_usage[count];
+
+		if (!cx->valid)
+			continue;
+
+#ifdef CONFIG_HOTPLUG_CPU
+		if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
+		    !pr->flags.has_cst &&
+		    !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
+			continue;
+#endif
+
+		cpuidle_set_statedata(state_usage, cx);
+
+		count++;
+		if (count == CPUIDLE_STATE_MAX)
+			break;
+	}
+
+	dev->state_count = count;
+
+	if (!count)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * acpi_processor_setup_cpuidle states- prepares and configures cpuidle
+ * global state data i.e. idle routines
+ *
+ * @pr: the ACPI processor
+ */
+static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
+{
+	int i, count = CPUIDLE_DRIVER_STATE_START;
+	struct acpi_processor_cx *cx;
+	struct cpuidle_state *state;
+	struct cpuidle_driver *drv = &acpi_idle_driver;
+
+	if (!pr->flags.power_setup_done)
+		return -EINVAL;
+
+	if (pr->flags.power == 0)
+		return -EINVAL;
+
+	drv->safe_state_index = -1;
 	for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
-		dev->states[i].name[0] = '\0';
-		dev->states[i].desc[0] = '\0';
+		drv->states[i].name[0] = '\0';
+		drv->states[i].desc[0] = '\0';
 	}
 
 	if (max_cstate == 0)
@@ -1002,7 +1053,6 @@
 
 	for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
 		cx = &pr->power.states[i];
-		state = &dev->states[count];
 
 		if (!cx->valid)
 			continue;
@@ -1013,8 +1063,8 @@
 		    !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
 			continue;
 #endif
-		cpuidle_set_statedata(state, cx);
 
+		state = &drv->states[count];
 		snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
 		strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
 		state->exit_latency = cx->latency;
@@ -1027,13 +1077,13 @@
 				state->flags |= CPUIDLE_FLAG_TIME_VALID;
 
 			state->enter = acpi_idle_enter_c1;
-			dev->safe_state = state;
+			drv->safe_state_index = count;
 			break;
 
 			case ACPI_STATE_C2:
 			state->flags |= CPUIDLE_FLAG_TIME_VALID;
 			state->enter = acpi_idle_enter_simple;
-			dev->safe_state = state;
+			drv->safe_state_index = count;
 			break;
 
 			case ACPI_STATE_C3:
@@ -1049,7 +1099,7 @@
 			break;
 	}
 
-	dev->state_count = count;
+	drv->state_count = count;
 
 	if (!count)
 		return -EINVAL;
@@ -1057,7 +1107,7 @@
 	return 0;
 }
 
-int acpi_processor_cst_has_changed(struct acpi_processor *pr)
+int acpi_processor_hotplug(struct acpi_processor *pr)
 {
 	int ret = 0;
 
@@ -1078,7 +1128,7 @@
 	cpuidle_disable_device(&pr->power.dev);
 	acpi_processor_get_power_info(pr);
 	if (pr->flags.power) {
-		acpi_processor_setup_cpuidle(pr);
+		acpi_processor_setup_cpuidle_cx(pr);
 		ret = cpuidle_enable_device(&pr->power.dev);
 	}
 	cpuidle_resume_and_unlock();
@@ -1086,10 +1136,72 @@
 	return ret;
 }
 
+int acpi_processor_cst_has_changed(struct acpi_processor *pr)
+{
+	int cpu;
+	struct acpi_processor *_pr;
+
+	if (disabled_by_idle_boot_param())
+		return 0;
+
+	if (!pr)
+		return -EINVAL;
+
+	if (nocst)
+		return -ENODEV;
+
+	if (!pr->flags.power_setup_done)
+		return -ENODEV;
+
+	/*
+	 * FIXME:  Design the ACPI notification to make it once per
+	 * system instead of once per-cpu.  This condition is a hack
+	 * to make the code that updates C-States be called once.
+	 */
+
+	if (smp_processor_id() == 0 &&
+			cpuidle_get_driver() == &acpi_idle_driver) {
+
+		cpuidle_pause_and_lock();
+		/* Protect against cpu-hotplug */
+		get_online_cpus();
+
+		/* Disable all cpuidle devices */
+		for_each_online_cpu(cpu) {
+			_pr = per_cpu(processors, cpu);
+			if (!_pr || !_pr->flags.power_setup_done)
+				continue;
+			cpuidle_disable_device(&_pr->power.dev);
+		}
+
+		/* Populate Updated C-state information */
+		acpi_processor_setup_cpuidle_states(pr);
+
+		/* Enable all cpuidle devices */
+		for_each_online_cpu(cpu) {
+			_pr = per_cpu(processors, cpu);
+			if (!_pr || !_pr->flags.power_setup_done)
+				continue;
+			acpi_processor_get_power_info(_pr);
+			if (_pr->flags.power) {
+				acpi_processor_setup_cpuidle_cx(_pr);
+				cpuidle_enable_device(&_pr->power.dev);
+			}
+		}
+		put_online_cpus();
+		cpuidle_resume_and_unlock();
+	}
+
+	return 0;
+}
+
+static int acpi_processor_registered;
+
 int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
 			      struct acpi_device *device)
 {
 	acpi_status status = 0;
+	int retval;
 	static int first_run;
 
 	if (disabled_by_idle_boot_param())
@@ -1126,9 +1238,26 @@
 	 * platforms that only support C1.
 	 */
 	if (pr->flags.power) {
-		acpi_processor_setup_cpuidle(pr);
-		if (cpuidle_register_device(&pr->power.dev))
-			return -EIO;
+		/* Register acpi_idle_driver if not already registered */
+		if (!acpi_processor_registered) {
+			acpi_processor_setup_cpuidle_states(pr);
+			retval = cpuidle_register_driver(&acpi_idle_driver);
+			if (retval)
+				return retval;
+			printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
+					acpi_idle_driver.name);
+		}
+		/* Register per-cpu cpuidle_device. Cpuidle driver
+		 * must already be registered before registering device
+		 */
+		acpi_processor_setup_cpuidle_cx(pr);
+		retval = cpuidle_register_device(&pr->power.dev);
+		if (retval) {
+			if (acpi_processor_registered == 0)
+				cpuidle_unregister_driver(&acpi_idle_driver);
+			return retval;
+		}
+		acpi_processor_registered++;
 	}
 	return 0;
 }
@@ -1139,8 +1268,13 @@
 	if (disabled_by_idle_boot_param())
 		return 0;
 
-	cpuidle_unregister_device(&pr->power.dev);
-	pr->flags.power_setup_done = 0;
+	if (pr->flags.power) {
+		cpuidle_unregister_device(&pr->power.dev);
+		acpi_processor_registered--;
+		if (acpi_processor_registered == 0)
+			cpuidle_unregister_driver(&acpi_idle_driver);
+	}
 
+	pr->flags.power_setup_done = 0;
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/acpi/sbshc.c linux-libre-3.2-gnu/drivers/acpi/sbshc.c
--- linux-libre-3.1-gnu/drivers/acpi/sbshc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/sbshc.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/wait.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include "sbshc.h"
 
diff -druN linux-libre-3.1-gnu/drivers/acpi/scan.c linux-libre-3.2-gnu/drivers/acpi/scan.c
--- linux-libre-3.1-gnu/drivers/acpi/scan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/scan.c	2012-01-04 18:55:44.000000000 -0500
@@ -1062,13 +1062,12 @@
 	if (!id)
 		return;
 
-	id->id = kmalloc(strlen(dev_id) + 1, GFP_KERNEL);
+	id->id = kstrdup(dev_id, GFP_KERNEL);
 	if (!id->id) {
 		kfree(id);
 		return;
 	}
 
-	strcpy(id->id, dev_id);
 	list_add_tail(&id->list, &device->pnp.ids);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/acpi/sleep.c linux-libre-3.2-gnu/drivers/acpi/sleep.c
--- linux-libre-3.1-gnu/drivers/acpi/sleep.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/sleep.c	2012-01-04 18:55:44.000000000 -0500
@@ -390,6 +390,22 @@
 	},
 	{
 	.callback = init_nvs_nosave,
+	.ident = "Sony Vaio VGN-FW21E",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"),
+		},
+	},
+	{
+	.callback = init_nvs_nosave,
+	.ident = "Sony Vaio VPCEB17FX",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"),
+		},
+	},
+	{
+	.callback = init_nvs_nosave,
 	.ident = "Sony Vaio VGN-SR11M",
 	.matches = {
 		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
@@ -444,6 +460,22 @@
 		DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"),
 		},
 	},
+	{
+	.callback = init_nvs_nosave,
+	.ident = "Sony Vaio VGN-SR26GN_P",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR26GN_P"),
+		},
+	},
+	{
+	.callback = init_nvs_nosave,
+	.ident = "Sony Vaio VGN-FW520F",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"),
+		},
+	},
 	{},
 };
 #endif /* CONFIG_SUSPEND */
diff -druN linux-libre-3.1-gnu/drivers/acpi/sysfs.c linux-libre-3.2-gnu/drivers/acpi/sysfs.c
--- linux-libre-3.1-gnu/drivers/acpi/sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -706,11 +706,23 @@
 	return;
 }
 
+static ssize_t
+acpi_show_profile(struct device *dev, struct device_attribute *attr,
+		  char *buf)
+{
+	return sprintf(buf, "%d\n", acpi_gbl_FADT.preferred_profile);
+}
+
+static const struct device_attribute pm_profile_attr =
+	__ATTR(pm_profile, S_IRUGO, acpi_show_profile, NULL);
+
 int __init acpi_sysfs_init(void)
 {
 	int result;
 
 	result = acpi_tables_sysfs_init();
-
+	if (result)
+		return result;
+	result = sysfs_create_file(acpi_kobj, &pm_profile_attr.attr);
 	return result;
 }
diff -druN linux-libre-3.1-gnu/drivers/acpi/video_detect.c linux-libre-3.2-gnu/drivers/acpi/video_detect.c
--- linux-libre-3.1-gnu/drivers/acpi/video_detect.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/acpi/video_detect.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
  *
  */
 
+#include <linux/export.h>
 #include <linux/acpi.h>
 #include <linux/dmi.h>
 #include <linux/pci.h>
diff -druN linux-libre-3.1-gnu/drivers/amba/bus.c linux-libre-3.2-gnu/drivers/amba/bus.c
--- linux-libre-3.1-gnu/drivers/amba/bus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/amba/bus.c	2012-01-04 18:55:44.000000000 -0500
@@ -365,6 +365,40 @@
 
 #endif /* !CONFIG_HIBERNATE_CALLBACKS */
 
+#ifdef CONFIG_PM_RUNTIME
+/*
+ * Hooks to provide runtime PM of the pclk (bus clock).  It is safe to
+ * enable/disable the bus clock at runtime PM suspend/resume as this
+ * does not result in loss of context.  However, disabling vcore power
+ * would do, so we leave that to the driver.
+ */
+static int amba_pm_runtime_suspend(struct device *dev)
+{
+	struct amba_device *pcdev = to_amba_device(dev);
+	int ret = pm_generic_runtime_suspend(dev);
+
+	if (ret == 0 && dev->driver)
+		clk_disable(pcdev->pclk);
+
+	return ret;
+}
+
+static int amba_pm_runtime_resume(struct device *dev)
+{
+	struct amba_device *pcdev = to_amba_device(dev);
+	int ret;
+
+	if (dev->driver) {
+		ret = clk_enable(pcdev->pclk);
+		/* Failure is probably fatal to the system, but... */
+		if (ret)
+			return ret;
+	}
+
+	return pm_generic_runtime_resume(dev);
+}
+#endif
+
 #ifdef CONFIG_PM
 
 static const struct dev_pm_ops amba_pm = {
@@ -383,8 +417,8 @@
 	.poweroff_noirq	= amba_pm_poweroff_noirq,
 	.restore_noirq	= amba_pm_restore_noirq,
 	SET_RUNTIME_PM_OPS(
-		pm_generic_runtime_suspend,
-		pm_generic_runtime_resume,
+		amba_pm_runtime_suspend,
+		amba_pm_runtime_resume,
 		pm_generic_runtime_idle
 	)
 };
@@ -426,9 +460,17 @@
 	if (IS_ERR(pclk))
 		return PTR_ERR(pclk);
 
+	ret = clk_prepare(pclk);
+	if (ret) {
+		clk_put(pclk);
+		return ret;
+	}
+
 	ret = clk_enable(pclk);
-	if (ret)
+	if (ret) {
+		clk_unprepare(pclk);
 		clk_put(pclk);
+	}
 
 	return ret;
 }
@@ -438,6 +480,7 @@
 	struct clk *pclk = pcdev->pclk;
 
 	clk_disable(pclk);
+	clk_unprepare(pclk);
 	clk_put(pclk);
 }
 
@@ -494,10 +537,18 @@
 		if (ret)
 			break;
 
+		pm_runtime_get_noresume(dev);
+		pm_runtime_set_active(dev);
+		pm_runtime_enable(dev);
+
 		ret = pcdrv->probe(pcdev, id);
 		if (ret == 0)
 			break;
 
+		pm_runtime_disable(dev);
+		pm_runtime_set_suspended(dev);
+		pm_runtime_put_noidle(dev);
+
 		amba_put_disable_pclk(pcdev);
 		amba_put_disable_vcore(pcdev);
 	} while (0);
@@ -509,7 +560,16 @@
 {
 	struct amba_device *pcdev = to_amba_device(dev);
 	struct amba_driver *drv = to_amba_driver(dev->driver);
-	int ret = drv->remove(pcdev);
+	int ret;
+
+	pm_runtime_get_sync(dev);
+	ret = drv->remove(pcdev);
+	pm_runtime_put_noidle(dev);
+
+	/* Undo the runtime PM settings in amba_probe() */
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
 
 	amba_put_disable_pclk(pcdev);
 	amba_put_disable_vcore(pcdev);
diff -druN linux-libre-3.1-gnu/drivers/ata/ahci.c linux-libre-3.2-gnu/drivers/ata/ahci.c
--- linux-libre-3.1-gnu/drivers/ata/ahci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/ahci.c	2012-01-04 18:55:44.000000000 -0500
@@ -390,6 +390,9 @@
 	/* Promise */
 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
 
+	/* Asmedia */
+	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },	/* ASM1061 */
+
 	/* Generic, PCI class code for AHCI */
 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
diff -druN linux-libre-3.1-gnu/drivers/ata/ahci_platform.c linux-libre-3.2-gnu/drivers/ata/ahci_platform.c
--- linux-libre-3.1-gnu/drivers/ata/ahci_platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/ahci_platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,41 @@
 #include <linux/ahci_platform.h>
 #include "ahci.h"
 
+enum ahci_type {
+	AHCI,		/* standard platform ahci */
+	IMX53_AHCI,	/* ahci on i.mx53 */
+};
+
+static struct platform_device_id ahci_devtype[] = {
+	{
+		.name = "ahci",
+		.driver_data = AHCI,
+	}, {
+		.name = "imx53-ahci",
+		.driver_data = IMX53_AHCI,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, ahci_devtype);
+
+
+static const struct ata_port_info ahci_port_info[] = {
+	/* by features */
+	[AHCI] = {
+		.flags		= AHCI_FLAG_COMMON,
+		.pio_mask	= ATA_PIO4,
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &ahci_ops,
+	},
+	[IMX53_AHCI] = {
+		.flags		= AHCI_FLAG_COMMON,
+		.pio_mask	= ATA_PIO4,
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &ahci_pmp_retry_srst_ops,
+	},
+};
+
 static struct scsi_host_template ahci_platform_sht = {
 	AHCI_SHT("ahci_platform"),
 };
@@ -30,13 +65,9 @@
 static int __init ahci_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct ahci_platform_data *pdata = dev->platform_data;
-	struct ata_port_info pi = {
-		.flags		= AHCI_FLAG_COMMON,
-		.pio_mask	= ATA_PIO4,
-		.udma_mask	= ATA_UDMA6,
-		.port_ops	= &ahci_ops,
-	};
+	struct ahci_platform_data *pdata = dev_get_platdata(dev);
+	const struct platform_device_id *id = platform_get_device_id(pdev);
+	struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0];
 	const struct ata_port_info *ppi[] = { &pi, NULL };
 	struct ahci_host_priv *hpriv;
 	struct ata_host *host;
@@ -160,7 +191,7 @@
 static int __devexit ahci_remove(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct ahci_platform_data *pdata = dev->platform_data;
+	struct ahci_platform_data *pdata = dev_get_platdata(dev);
 	struct ata_host *host = dev_get_drvdata(dev);
 
 	ata_host_detach(host);
@@ -171,12 +202,20 @@
 	return 0;
 }
 
+static const struct of_device_id ahci_of_match[] = {
+	{ .compatible = "calxeda,hb-ahci", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ahci_of_match);
+
 static struct platform_driver ahci_driver = {
 	.remove = __devexit_p(ahci_remove),
 	.driver = {
 		.name = "ahci",
 		.owner = THIS_MODULE,
+		.of_match_table = ahci_of_match,
 	},
+	.id_table	= ahci_devtype,
 };
 
 static int __init ahci_init(void)
diff -druN linux-libre-3.1-gnu/drivers/ata/ata_piix.c linux-libre-3.2-gnu/drivers/ata/ata_piix.c
--- linux-libre-3.1-gnu/drivers/ata/ata_piix.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/ata_piix.c	2012-01-04 18:55:44.000000000 -0500
@@ -113,6 +113,8 @@
 	PIIX_PATA_FLAGS		= ATA_FLAG_SLAVE_POSS,
 	PIIX_SATA_FLAGS		= ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
 
+	PIIX_FLAG_PIO16		= (1 << 30), /*support 16bit PIO only*/
+
 	PIIX_80C_PRI		= (1 << 5) | (1 << 4),
 	PIIX_80C_SEC		= (1 << 7) | (1 << 6),
 
@@ -147,6 +149,7 @@
 	ich8m_apple_sata,	/* locks up on second port enable */
 	tolapai_sata,
 	piix_pata_vmw,			/* PIIX4 for VMware, spurious DMA_ERR */
+	ich8_sata_snb,
 };
 
 struct piix_map_db {
@@ -177,6 +180,7 @@
 static int piix_sidpr_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
 			      unsigned hints);
 static bool piix_irq_check(struct ata_port *ap);
+static int piix_port_start(struct ata_port *ap);
 #ifdef CONFIG_PM
 static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
 static int piix_pci_device_resume(struct pci_dev *pdev);
@@ -298,21 +302,21 @@
 	/* SATA Controller IDE (PCH) */
 	{ 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
 	/* SATA Controller IDE (CPT) */
-	{ 0x8086, 0x1c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+	{ 0x8086, 0x1c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
 	/* SATA Controller IDE (CPT) */
-	{ 0x8086, 0x1c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+	{ 0x8086, 0x1c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
 	/* SATA Controller IDE (CPT) */
 	{ 0x8086, 0x1c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
 	/* SATA Controller IDE (CPT) */
 	{ 0x8086, 0x1c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
 	/* SATA Controller IDE (PBG) */
-	{ 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+	{ 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
 	/* 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 },
+	{ 0x8086, 0x1e00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
 	/* SATA Controller IDE (Panther Point) */
-	{ 0x8086, 0x1e01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+	{ 0x8086, 0x1e01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
 	/* SATA Controller IDE (Panther Point) */
 	{ 0x8086, 0x1e08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
 	/* SATA Controller IDE (Panther Point) */
@@ -338,6 +342,7 @@
 static struct ata_port_operations piix_sata_ops = {
 	.inherits		= &ata_bmdma32_port_ops,
 	.sff_irq_check		= piix_irq_check,
+	.port_start		= piix_port_start,
 };
 
 static struct ata_port_operations piix_pata_ops = {
@@ -478,6 +483,7 @@
 	[ich8_2port_sata]	= &ich8_2port_map_db,
 	[ich8m_apple_sata]	= &ich8m_apple_map_db,
 	[tolapai_sata]		= &tolapai_map_db,
+	[ich8_sata_snb]		= &ich8_map_db,
 };
 
 static struct ata_port_info piix_port_info[] = {
@@ -606,6 +612,19 @@
 		.port_ops	= &piix_vmw_ops,
 	},
 
+	/*
+	 * some Sandybridge chipsets have broken 32 mode up to now,
+	 * see https://bugzilla.kernel.org/show_bug.cgi?id=40592
+	 */
+	[ich8_sata_snb] =
+	{
+		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR | PIIX_FLAG_PIO16,
+		.pio_mask	= ATA_PIO4,
+		.mwdma_mask	= ATA_MWDMA2,
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &piix_sata_ops,
+	},
+
 };
 
 static struct pci_bits piix_enable_bits[] = {
@@ -649,6 +668,14 @@
 	{ 0, }
 };
 
+static int piix_port_start(struct ata_port *ap)
+{
+	if (!(ap->flags & PIIX_FLAG_PIO16))
+		ap->pflags |= ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE;
+
+	return ata_bmdma_port_start(ap);
+}
+
 /**
  *	ich_pata_cable_detect - Probe host controller cable detect info
  *	@ap: Port for which cable detect info is desired
@@ -704,22 +731,11 @@
 
 static DEFINE_SPINLOCK(piix_lock);
 
-/**
- *	piix_set_piomode - Initialize host controller PATA PIO timings
- *	@ap: Port whose timings we are configuring
- *	@adev: um
- *
- *	Set PIO mode for device, in host controller PCI config space.
- *
- *	LOCKING:
- *	None (inherited from caller).
- */
-
-static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+static void piix_set_timings(struct ata_port *ap, struct ata_device *adev,
+			     u8 pio)
 {
 	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
 	unsigned long flags;
-	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
 	unsigned int is_slave	= (adev->devno != 0);
 	unsigned int master_port= ap->port_no ? 0x42 : 0x40;
 	unsigned int slave_port	= 0x44;
@@ -744,10 +760,16 @@
 		control |= 1;	/* TIME1 enable */
 	if (ata_pio_need_iordy(adev))
 		control |= 2;	/* IE enable */
-
 	/* Intel specifies that the PPE functionality is for disk only */
 	if (adev->class == ATA_DEV_ATA)
 		control |= 4;	/* PPE enable */
+	/*
+	 * If the drive MWDMA is faster than it can do PIO then
+	 * we must force PIO into PIO0
+	 */
+	if (adev->pio_mode < XFER_PIO_0 + pio)
+		/* Enable DMA timing only */
+		control |= 8;	/* PIO cycles in PIO0 */
 
 	spin_lock_irqsave(&piix_lock, flags);
 
@@ -759,8 +781,6 @@
 	if (is_slave) {
 		/* clear TIME1|IE1|PPE1|DTE1 */
 		master_data &= 0xff0f;
-		/* Enable SITRE (separate slave timing register) */
-		master_data |= 0x4000;
 		/* enable PPE1, IE1 and TIME1 as needed */
 		master_data |= (control << 4);
 		pci_read_config_byte(dev, slave_port, &slave_data);
@@ -778,6 +798,9 @@
 			(timings[pio][0] << 12) |
 			(timings[pio][1] << 8);
 	}
+
+	/* Enable SITRE (separate slave timing register) */
+	master_data |= 0x4000;
 	pci_write_config_word(dev, master_port, master_data);
 	if (is_slave)
 		pci_write_config_byte(dev, slave_port, slave_data);
@@ -795,6 +818,22 @@
 }
 
 /**
+ *	piix_set_piomode - Initialize host controller PATA PIO timings
+ *	@ap: Port whose timings we are configuring
+ *	@adev: Drive in question
+ *
+ *	Set PIO mode for device, in host controller PCI config space.
+ *
+ *	LOCKING:
+ *	None (inherited from caller).
+ */
+
+static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+	piix_set_timings(ap, adev, adev->pio_mode - XFER_PIO_0);
+}
+
+/**
  *	do_pata_set_dmamode - Initialize host controller PATA PIO timings
  *	@ap: Port whose timings we are configuring
  *	@adev: Drive in question
@@ -810,31 +849,20 @@
 {
 	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
 	unsigned long flags;
-	u8 master_port		= ap->port_no ? 0x42 : 0x40;
-	u16 master_data;
 	u8 speed		= adev->dma_mode;
 	int devid		= adev->devno + 2 * ap->port_no;
 	u8 udma_enable		= 0;
 
-	static const	 /* ISP  RTC */
-	u8 timings[][2]	= { { 0, 0 },
-			    { 0, 0 },
-			    { 1, 0 },
-			    { 2, 1 },
-			    { 2, 3 }, };
-
-	spin_lock_irqsave(&piix_lock, flags);
-
-	pci_read_config_word(dev, master_port, &master_data);
-	if (ap->udma_mask)
-		pci_read_config_byte(dev, 0x48, &udma_enable);
-
 	if (speed >= XFER_UDMA_0) {
-		unsigned int udma = adev->dma_mode - XFER_UDMA_0;
+		unsigned int udma = speed - XFER_UDMA_0;
 		u16 udma_timing;
 		u16 ideconf;
 		int u_clock, u_speed;
 
+		spin_lock_irqsave(&piix_lock, flags);
+
+		pci_read_config_byte(dev, 0x48, &udma_enable);
+
 		/*
 		 * UDMA is handled by a combination of clock switching and
 		 * selection of dividers
@@ -867,56 +895,21 @@
 			   performance (WR_PingPong_En) */
 			pci_write_config_word(dev, 0x54, ideconf);
 		}
+
+		pci_write_config_byte(dev, 0x48, udma_enable);
+
+		spin_unlock_irqrestore(&piix_lock, flags);
 	} else {
-		/*
-		 * MWDMA is driven by the PIO timings. We must also enable
-		 * IORDY unconditionally along with TIME1. PPE has already
-		 * been set when the PIO timing was set.
-		 */
-		unsigned int mwdma	= adev->dma_mode - XFER_MW_DMA_0;
-		unsigned int control;
-		u8 slave_data;
+		/* MWDMA is driven by the PIO timings. */
+		unsigned int mwdma = speed - XFER_MW_DMA_0;
 		const unsigned int needed_pio[3] = {
 			XFER_PIO_0, XFER_PIO_3, XFER_PIO_4
 		};
 		int pio = needed_pio[mwdma] - XFER_PIO_0;
 
-		control = 3;	/* IORDY|TIME1 */
-
-		/* If the drive MWDMA is faster than it can do PIO then
-		   we must force PIO into PIO0 */
-
-		if (adev->pio_mode < needed_pio[mwdma])
-			/* Enable DMA timing only */
-			control |= 8;	/* PIO cycles in PIO0 */
-
-		if (adev->devno) {	/* Slave */
-			master_data &= 0xFF4F;  /* Mask out IORDY|TIME1|DMAONLY */
-			master_data |= control << 4;
-			pci_read_config_byte(dev, 0x44, &slave_data);
-			slave_data &= (ap->port_no ? 0x0f : 0xf0);
-			/* Load the matching timing */
-			slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
-			pci_write_config_byte(dev, 0x44, slave_data);
-		} else { 	/* Master */
-			master_data &= 0xCCF4;	/* Mask out IORDY|TIME1|DMAONLY
-						   and master timing bits */
-			master_data |= control;
-			master_data |=
-				(timings[pio][0] << 12) |
-				(timings[pio][1] << 8);
-		}
-
-		if (ap->udma_mask)
-			udma_enable &= ~(1 << devid);
-
-		pci_write_config_word(dev, master_port, master_data);
+		/* XFER_PIO_0 is never used currently */
+		piix_set_timings(ap, adev, pio);
 	}
-	/* Don't scribble on 0x48 if the controller does not support UDMA */
-	if (ap->udma_mask)
-		pci_write_config_byte(dev, 0x48, udma_enable);
-
-	spin_unlock_irqrestore(&piix_lock, flags);
 }
 
 /**
diff -druN linux-libre-3.1-gnu/drivers/ata/Kconfig linux-libre-3.2-gnu/drivers/ata/Kconfig
--- linux-libre-3.1-gnu/drivers/ata/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -820,7 +820,7 @@
 
 config PATA_OF_PLATFORM
 	tristate "OpenFirmware platform device PATA support"
-	depends on PATA_PLATFORM && PPC_OF
+	depends on PATA_PLATFORM && OF && OF_IRQ
 	help
 	  This option enables support for generic directly connected ATA
 	  devices commonly found on embedded systems with OpenFirmware
@@ -831,6 +831,7 @@
 config PATA_QDI
 	tristate "QDI VLB PATA support"
 	depends on ISA
+	select PATA_LEGACY
 	help
 	  Support for QDI 6500 and 6580 PATA controllers on VESA local bus.
 
diff -druN linux-libre-3.1-gnu/drivers/ata/libata-core.c linux-libre-3.2-gnu/drivers/ata/libata-core.c
--- linux-libre-3.1-gnu/drivers/ata/libata-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/libata-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -2938,7 +2938,7 @@
 	if (id[ATA_ID_FIELD_VALID] & 2) {	/* EIDE drive */
 		memset(&p, 0, sizeof(p));
 
-		if (speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) {
+		if (speed >= XFER_PIO_0 && speed < XFER_SW_DMA_0) {
 			if (speed <= XFER_PIO_2)
 				p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO];
 			else if ((speed <= XFER_PIO_4) ||
@@ -6713,6 +6713,7 @@
 EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
 EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);
 EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
+EXPORT_SYMBOL_GPL(__ata_change_queue_depth);
 EXPORT_SYMBOL_GPL(sata_scr_valid);
 EXPORT_SYMBOL_GPL(sata_scr_read);
 EXPORT_SYMBOL_GPL(sata_scr_write);
diff -druN linux-libre-3.1-gnu/drivers/ata/libata-eh.c linux-libre-3.2-gnu/drivers/ata/libata-eh.c
--- linux-libre-3.1-gnu/drivers/ata/libata-eh.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/libata-eh.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 
 #include <linux/kernel.h>
 #include <linux/blkdev.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
@@ -2532,8 +2533,7 @@
 	return reset(link, classes, deadline);
 }
 
-static int ata_eh_followup_srst_needed(struct ata_link *link,
-				       int rc, const unsigned int *classes)
+static int ata_eh_followup_srst_needed(struct ata_link *link, int rc)
 {
 	if ((link->flags & ATA_LFLAG_NO_SRST) || ata_link_offline(link))
 		return 0;
@@ -2726,7 +2726,7 @@
 
 		/* perform follow-up SRST if necessary */
 		if (reset == hardreset &&
-		    ata_eh_followup_srst_needed(link, rc, classes)) {
+		    ata_eh_followup_srst_needed(link, rc)) {
 			reset = softreset;
 
 			if (!reset) {
@@ -2883,7 +2883,7 @@
 	    sata_scr_read(link, SCR_STATUS, &sstatus))
 		rc = -ERESTART;
 
-	if (rc == -ERESTART || try >= max_tries) {
+	if (try >= max_tries) {
 		/*
 		 * Thaw host port even if reset failed, so that the port
 		 * can be retried on the next phy event.  This risks
@@ -2909,6 +2909,16 @@
 		ata_eh_acquire(ap);
 	}
 
+	/*
+	 * While disks spinup behind PMP, some controllers fail sending SRST.
+	 * They need to be reset - as well as the PMP - before retrying.
+	 */
+	if (rc == -ERESTART) {
+		if (ata_is_host_link(link))
+			ata_eh_thaw_port(ap);
+		goto out;
+	}
+
 	if (try == max_tries - 1) {
 		sata_down_spd_limit(link, 0);
 		if (slave)
diff -druN linux-libre-3.1-gnu/drivers/ata/libata-pmp.c linux-libre-3.2-gnu/drivers/ata/libata-pmp.c
--- linux-libre-3.1-gnu/drivers/ata/libata-pmp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/libata-pmp.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/libata.h>
 #include <linux/slab.h>
 #include "libata.h"
@@ -388,12 +389,9 @@
 			/* link reports offline after LPM */
 			link->flags |= ATA_LFLAG_NO_LPM;
 
-			/* Class code report is unreliable and SRST
-			 * times out under certain configurations.
-			 */
+			/* Class code report is unreliable. */
 			if (link->pmp < 5)
-				link->flags |= ATA_LFLAG_NO_SRST |
-					       ATA_LFLAG_ASSUME_ATA;
+				link->flags |= ATA_LFLAG_ASSUME_ATA;
 
 			/* port 5 is for SEMB device and it doesn't like SRST */
 			if (link->pmp == 5)
diff -druN linux-libre-3.1-gnu/drivers/ata/libata-scsi.c linux-libre-3.2-gnu/drivers/ata/libata-scsi.c
--- linux-libre-3.1-gnu/drivers/ata/libata-scsi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/libata-scsi.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/kernel.h>
 #include <linux/blkdev.h>
 #include <linux/spinlock.h>
+#include <linux/export.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
@@ -1215,25 +1216,19 @@
 }
 
 /**
- *	ata_scsi_change_queue_depth - SCSI callback for queue depth config
+ *	__ata_change_queue_depth - helper for ata_scsi_change_queue_depth
+ *	@ap: ATA port to which the device change the queue depth
  *	@sdev: SCSI device to configure queue depth for
  *	@queue_depth: new queue depth
  *	@reason: calling context
  *
- *	This is libata standard hostt->change_queue_depth callback.
- *	SCSI will call into this callback when user tries to set queue
- *	depth via sysfs.
- *
- *	LOCKING:
- *	SCSI layer (we don't care)
+ *	libsas and libata have different approaches for associating a sdev to
+ *	its ata_port.
  *
- *	RETURNS:
- *	Newly configured queue depth.
  */
-int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth,
-				int reason)
+int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
+			     int queue_depth, int reason)
 {
-	struct ata_port *ap = ata_shost_to_port(sdev->host);
 	struct ata_device *dev;
 	unsigned long flags;
 
@@ -1269,6 +1264,30 @@
 }
 
 /**
+ *	ata_scsi_change_queue_depth - SCSI callback for queue depth config
+ *	@sdev: SCSI device to configure queue depth for
+ *	@queue_depth: new queue depth
+ *	@reason: calling context
+ *
+ *	This is libata standard hostt->change_queue_depth callback.
+ *	SCSI will call into this callback when user tries to set queue
+ *	depth via sysfs.
+ *
+ *	LOCKING:
+ *	SCSI layer (we don't care)
+ *
+ *	RETURNS:
+ *	Newly configured queue depth.
+ */
+int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth,
+				int reason)
+{
+	struct ata_port *ap = ata_shost_to_port(sdev->host);
+
+	return __ata_change_queue_depth(ap, sdev, queue_depth, reason);
+}
+
+/**
  *	ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
  *	@qc: Storage for translated ATA taskfile
  *
diff -druN linux-libre-3.1-gnu/drivers/ata/libata-sff.c linux-libre-3.2-gnu/drivers/ata/libata-sff.c
--- linux-libre-3.1-gnu/drivers/ata/libata-sff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/libata-sff.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <linux/kernel.h>
 #include <linux/gfp.h>
 #include <linux/pci.h>
+#include <linux/module.h>
 #include <linux/libata.h>
 #include <linux/highmem.h>
 
@@ -569,7 +570,7 @@
 
 	/* Transfer trailing byte, if any. */
 	if (unlikely(buflen & 0x01)) {
-		unsigned char pad[2];
+		unsigned char pad[2] = { };
 
 		/* Point buf to the tail of buffer */
 		buf += buflen - 1;
@@ -628,7 +629,7 @@
 
 	/* Transfer trailing bytes, if any */
 	if (unlikely(slop)) {
-		unsigned char pad[4];
+		unsigned char pad[4] = { };
 
 		/* Point buf to the tail of buffer */
 		buf += buflen - slop;
@@ -678,7 +679,7 @@
 	unsigned int consumed;
 
 	local_irq_save(flags);
-	consumed = ata_sff_data_xfer(dev, buf, buflen, rw);
+	consumed = ata_sff_data_xfer32(dev, buf, buflen, rw);
 	local_irq_restore(flags);
 
 	return consumed;
@@ -2507,31 +2508,10 @@
 	return NULL;
 }
 
-/**
- *	ata_pci_sff_init_one - Initialize/register PIO-only PCI IDE controller
- *	@pdev: Controller to be initialized
- *	@ppi: array of port_info, must be enough for two ports
- *	@sht: scsi_host_template to use when registering the host
- *	@host_priv: host private_data
- *	@hflag: host flags
- *
- *	This is a helper function which can be called from a driver's
- *	xxx_init_one() probe function if the hardware uses traditional
- *	IDE taskfile registers and is PIO only.
- *
- *	ASSUMPTION:
- *	Nobody makes a single channel controller that appears solely as
- *	the secondary legacy port on PCI.
- *
- *	LOCKING:
- *	Inherited from PCI layer (may sleep).
- *
- *	RETURNS:
- *	Zero on success, negative on errno-based value on error.
- */
-int ata_pci_sff_init_one(struct pci_dev *pdev,
-		 const struct ata_port_info * const *ppi,
-		 struct scsi_host_template *sht, void *host_priv, int hflag)
+static int ata_pci_init_one(struct pci_dev *pdev,
+		const struct ata_port_info * const *ppi,
+		struct scsi_host_template *sht, void *host_priv,
+		int hflags, bool bmdma)
 {
 	struct device *dev = &pdev->dev;
 	const struct ata_port_info *pi;
@@ -2553,14 +2533,26 @@
 	if (rc)
 		goto out;
 
-	/* prepare and activate SFF host */
-	rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+#ifdef CONFIG_ATA_BMDMA
+	if (bmdma)
+		/* prepare and activate BMDMA host */
+		rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
+	else
+#endif
+		/* prepare and activate SFF host */
+		rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
 	if (rc)
 		goto out;
 	host->private_data = host_priv;
-	host->flags |= hflag;
+	host->flags |= hflags;
 
-	rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
+#ifdef CONFIG_ATA_BMDMA
+	if (bmdma) {
+		pci_set_master(pdev);
+		rc = ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);
+	} else
+#endif
+		rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
 out:
 	if (rc == 0)
 		devres_remove_group(&pdev->dev, NULL);
@@ -2569,6 +2561,35 @@
 
 	return rc;
 }
+
+/**
+ *	ata_pci_sff_init_one - Initialize/register PIO-only PCI IDE controller
+ *	@pdev: Controller to be initialized
+ *	@ppi: array of port_info, must be enough for two ports
+ *	@sht: scsi_host_template to use when registering the host
+ *	@host_priv: host private_data
+ *	@hflag: host flags
+ *
+ *	This is a helper function which can be called from a driver's
+ *	xxx_init_one() probe function if the hardware uses traditional
+ *	IDE taskfile registers and is PIO only.
+ *
+ *	ASSUMPTION:
+ *	Nobody makes a single channel controller that appears solely as
+ *	the secondary legacy port on PCI.
+ *
+ *	LOCKING:
+ *	Inherited from PCI layer (may sleep).
+ *
+ *	RETURNS:
+ *	Zero on success, negative on errno-based value on error.
+ */
+int ata_pci_sff_init_one(struct pci_dev *pdev,
+		 const struct ata_port_info * const *ppi,
+		 struct scsi_host_template *sht, void *host_priv, int hflag)
+{
+	return ata_pci_init_one(pdev, ppi, sht, host_priv, hflag, 0);
+}
 EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
 
 #endif /* CONFIG_PCI */
@@ -3286,42 +3307,7 @@
 			   struct scsi_host_template *sht, void *host_priv,
 			   int hflags)
 {
-	struct device *dev = &pdev->dev;
-	const struct ata_port_info *pi;
-	struct ata_host *host = NULL;
-	int rc;
-
-	DPRINTK("ENTER\n");
-
-	pi = ata_sff_find_valid_pi(ppi);
-	if (!pi) {
-		dev_err(&pdev->dev, "no valid port_info specified\n");
-		return -EINVAL;
-	}
-
-	if (!devres_open_group(dev, NULL, GFP_KERNEL))
-		return -ENOMEM;
-
-	rc = pcim_enable_device(pdev);
-	if (rc)
-		goto out;
-
-	/* prepare and activate BMDMA host */
-	rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
-	if (rc)
-		goto out;
-	host->private_data = host_priv;
-	host->flags |= hflags;
-
-	pci_set_master(pdev);
-	rc = ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);
- out:
-	if (rc == 0)
-		devres_remove_group(&pdev->dev, NULL);
-	else
-		devres_release_group(&pdev->dev, NULL);
-
-	return rc;
+	return ata_pci_init_one(pdev, ppi, sht, host_priv, hflags, 1);
 }
 EXPORT_SYMBOL_GPL(ata_pci_bmdma_init_one);
 
diff -druN linux-libre-3.1-gnu/drivers/ata/Makefile linux-libre-3.2-gnu/drivers/ata/Makefile
--- linux-libre-3.1-gnu/drivers/ata/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -88,7 +88,6 @@
 obj-$(CONFIG_PATA_PALMLD)	+= pata_palmld.o
 obj-$(CONFIG_PATA_PLATFORM)	+= pata_platform.o
 obj-$(CONFIG_PATA_OF_PLATFORM)	+= pata_of_platform.o
-obj-$(CONFIG_PATA_QDI)		+= pata_qdi.o
 obj-$(CONFIG_PATA_RB532)	+= pata_rb532_cf.o
 obj-$(CONFIG_PATA_RZ1000)	+= pata_rz1000.o
 obj-$(CONFIG_PATA_SAMSUNG_CF)	+= pata_samsung_cf.o
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_ali.c linux-libre-3.2-gnu/drivers/ata/pata_ali.c
--- linux-libre-3.1-gnu/drivers/ata/pata_ali.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_ali.c	2012-01-04 18:55:44.000000000 -0500
@@ -56,7 +56,7 @@
 		},
 	},
 	{
-		.ident = "Toshiba Satelite S1800-814",
+		.ident = "Toshiba Satellite S1800-814",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "S1800-814"),
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_arasan_cf.c linux-libre-3.2-gnu/drivers/ata/pata_arasan_cf.c
--- linux-libre-3.1-gnu/drivers/ata/pata_arasan_cf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_arasan_cf.c	2012-01-04 18:55:44.000000000 -0500
@@ -922,8 +922,7 @@
 #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 ata_host *host = dev_get_drvdata(dev);
 	struct arasan_cf_dev *acdev = host->ports[0]->private_data;
 
 	if (acdev->dma_chan) {
@@ -937,8 +936,7 @@
 
 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 ata_host *host = dev_get_drvdata(dev);
 	struct arasan_cf_dev *acdev = host->ports[0]->private_data;
 
 	cf_init(acdev);
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_artop.c linux-libre-3.2-gnu/drivers/ata/pata_artop.c
--- linux-libre-3.1-gnu/drivers/ata/pata_artop.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_artop.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
  *    pata_artop.c - ARTOP ATA controller driver
  *
  *	(C) 2006 Red Hat
- *	(C) 2007 Bartlomiej Zolnierkiewicz
+ *	(C) 2007,2011 Bartlomiej Zolnierkiewicz
  *
  *    Based in part on drivers/ide/pci/aec62xx.c
  *	Copyright (C) 1999-2002	Andre Hedrick <andre@linux-ide.org>
@@ -28,7 +28,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME	"pata_artop"
-#define DRV_VERSION	"0.4.5"
+#define DRV_VERSION	"0.4.6"
 
 /*
  *	The ARTOP has 33 Mhz and "over clocked" timing tables. Until we
@@ -39,31 +39,15 @@
 
 static int clock = 0;
 
-static int artop6210_pre_reset(struct ata_link *link, unsigned long deadline)
-{
-	struct ata_port *ap = link->ap;
-	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-	const struct pci_bits artop_enable_bits[] = {
-		{ 0x4AU, 1U, 0x02UL, 0x02UL },	/* port 0 */
-		{ 0x4AU, 1U, 0x04UL, 0x04UL },	/* port 1 */
-	};
-
-	if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
-		return -ENOENT;
-
-	return ata_sff_prereset(link, deadline);
-}
-
 /**
- *	artop6260_pre_reset	-	check for 40/80 pin
+ *	artop62x0_pre_reset	-	probe begin
  *	@link: link
  *	@deadline: deadline jiffies for the operation
  *
- *	The ARTOP hardware reports the cable detect bits in register 0x49.
  *	Nothing complicated needed here.
  */
 
-static int artop6260_pre_reset(struct ata_link *link, unsigned long deadline)
+static int artop62x0_pre_reset(struct ata_link *link, unsigned long deadline)
 {
 	static const struct pci_bits artop_enable_bits[] = {
 		{ 0x4AU, 1U, 0x02UL, 0x02UL },	/* port 0 */
@@ -73,7 +57,7 @@
 	struct ata_port *ap = link->ap;
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
-	/* Odd numbered device ids are the units with enable bits (the -R cards) */
+	/* Odd numbered device ids are the units with enable bits. */
 	if ((pdev->device & 1) &&
 	    !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
 		return -ENOENT;
@@ -317,7 +301,7 @@
 	.cable_detect		= ata_cable_40wire,
 	.set_piomode		= artop6210_set_piomode,
 	.set_dmamode		= artop6210_set_dmamode,
-	.prereset		= artop6210_pre_reset,
+	.prereset		= artop62x0_pre_reset,
 	.qc_defer		= artop6210_qc_defer,
 };
 
@@ -326,9 +310,36 @@
 	.cable_detect		= artop6260_cable_detect,
 	.set_piomode		= artop6260_set_piomode,
 	.set_dmamode		= artop6260_set_dmamode,
-	.prereset		= artop6260_pre_reset,
+	.prereset		= artop62x0_pre_reset,
 };
 
+static void atp8xx_fixup(struct pci_dev *pdev)
+{
+	if (pdev->device == 0x0005)
+		/* BIOS may have left us in UDMA, clear it before libata probe */
+		pci_write_config_byte(pdev, 0x54, 0);
+	else if (pdev->device == 0x0008 || pdev->device == 0x0009) {
+		u8 reg;
+
+		/* Mac systems come up with some registers not set as we
+		   will need them */
+
+		/* Clear reset & test bits */
+		pci_read_config_byte(pdev, 0x49, &reg);
+		pci_write_config_byte(pdev, 0x49, reg & ~0x30);
+
+		/* PCI latency must be > 0x80 for burst mode, tweak it
+		 * if required.
+		 */
+		pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &reg);
+		if (reg <= 0x80)
+			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90);
+
+		/* Enable IRQ output and burst mode */
+		pci_read_config_byte(pdev, 0x4a, &reg);
+		pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80);
+	}
+}
 
 /**
  *	artop_init_one - Register ARTOP ATA PCI device with kernel services
@@ -383,42 +394,22 @@
 	if (rc)
 		return rc;
 
-	if (id->driver_data == 0) {	/* 6210 variant */
+	if (id->driver_data == 0)	/* 6210 variant */
 		ppi[0] = &info_6210;
-		/* BIOS may have left us in UDMA, clear it before libata probe */
-		pci_write_config_byte(pdev, 0x54, 0);
-	}
 	else if (id->driver_data == 1)	/* 6260 */
 		ppi[0] = &info_626x;
 	else if (id->driver_data == 2)	{ /* 6280 or 6280 + fast */
 		unsigned long io = pci_resource_start(pdev, 4);
-		u8 reg;
 
 		ppi[0] = &info_628x;
 		if (inb(io) & 0x10)
 			ppi[0] = &info_628x_fast;
-		/* Mac systems come up with some registers not set as we
-		   will need them */
-
-		/* Clear reset & test bits */
-		pci_read_config_byte(pdev, 0x49, &reg);
-		pci_write_config_byte(pdev, 0x49, reg & ~ 0x30);
-
-		/* PCI latency must be > 0x80 for burst mode, tweak it
-		 * if required.
-		 */
-		pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &reg);
-		if (reg <= 0x80)
-			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90);
-
-		/* Enable IRQ output and burst mode */
-		pci_read_config_byte(pdev, 0x4a, &reg);
-		pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80);
-
 	}
 
 	BUG_ON(ppi[0] == NULL);
 
+	atp8xx_fixup(pdev);
+
 	return ata_pci_bmdma_init_one(pdev, ppi, &artop_sht, NULL, 0);
 }
 
@@ -432,11 +423,32 @@
 	{ }	/* terminate list */
 };
 
+#ifdef CONFIG_PM
+static int atp8xx_reinit_one(struct pci_dev *pdev)
+{
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	int rc;
+
+	rc = ata_pci_device_do_resume(pdev);
+	if (rc)
+		return rc;
+
+	atp8xx_fixup(pdev);
+
+	ata_host_resume(host);
+	return 0;
+}
+#endif
+
 static struct pci_driver artop_pci_driver = {
 	.name			= DRV_NAME,
 	.id_table		= artop_pci_tbl,
 	.probe			= artop_init_one,
 	.remove			= ata_pci_remove_one,
+#ifdef CONFIG_PM
+	.suspend		= ata_pci_device_suspend,
+	.resume			= atp8xx_reinit_one,
+#endif
 };
 
 static int __init artop_init(void)
@@ -452,9 +464,8 @@
 module_init(artop_init);
 module_exit(artop_exit);
 
-MODULE_AUTHOR("Alan Cox");
+MODULE_AUTHOR("Alan Cox, Bartlomiej Zolnierkiewicz");
 MODULE_DESCRIPTION("SCSI low-level driver for ARTOP PATA");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, artop_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
-
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_at91.c linux-libre-3.2-gnu/drivers/ata/pata_at91.c
--- linux-libre-3.1-gnu/drivers/ata/pata_at91.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_at91.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@
 
 #include <mach/at91sam9_smc.h>
 #include <mach/board.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
 
 #define DRV_NAME		"pata_at91"
 #define DRV_VERSION		"0.3"
@@ -414,10 +414,13 @@
 
 	host->private_data = info;
 
-	return ata_host_activate(host, irq ? gpio_to_irq(irq) : 0,
+	ret = ata_host_activate(host, irq ? gpio_to_irq(irq) : 0,
 			irq ? ata_sff_interrupt : NULL,
 			irq_flags, &pata_at91_sht);
 
+	if (!ret)
+		return 0;
+
 err_put:
 	clk_put(info->mck);
 	return ret;
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_atiixp.c linux-libre-3.2-gnu/drivers/ata/pata_atiixp.c
--- linux-libre-3.1-gnu/drivers/ata/pata_atiixp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_atiixp.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,6 +49,31 @@
 static DEFINE_SPINLOCK(atiixp_lock);
 
 /**
+ *	atiixp_prereset	-	perform reset handling
+ *	@link: ATA link
+ *	@deadline: deadline jiffies for the operation
+ *
+ *	Reset sequence checking enable bits to see which ports are
+ *	active.
+ */
+
+static int atiixp_prereset(struct ata_link *link, unsigned long deadline)
+{
+	static const struct pci_bits atiixp_enable_bits[] = {
+		{ 0x48, 1, 0x01, 0x00 },
+		{ 0x48, 1, 0x08, 0x00 }
+	};
+
+	struct ata_port *ap = link->ap;
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
+	if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no]))
+		return -ENOENT;
+
+	return ata_sff_prereset(link, deadline);
+}
+
+/**
  *	atiixp_set_pio_timing	-	set initial PIO mode data
  *	@ap: ATA interface
  *	@adev: ATA device
@@ -221,6 +246,7 @@
 	.bmdma_start 	= atiixp_bmdma_start,
 	.bmdma_stop	= atiixp_bmdma_stop,
 
+	.prereset	= atiixp_prereset,
 	.cable_detect	= atiixp_cable_detect,
 	.set_piomode	= atiixp_set_piomode,
 	.set_dmamode	= atiixp_set_dmamode,
@@ -235,16 +261,7 @@
 		.udma_mask = ATA_UDMA5,
 		.port_ops = &atiixp_port_ops
 	};
-	static const struct pci_bits atiixp_enable_bits[] = {
-		{ 0x48, 1, 0x01, 0x00 },
-		{ 0x48, 1, 0x08, 0x00 }
-	};
 	const struct ata_port_info *ppi[] = { &info, &info };
-	int i;
-
-	for (i = 0; i < 2; i++)
-		if (!pci_test_config_bits(pdev, &atiixp_enable_bits[i]))
-			ppi[i] = &ata_dummy_port_info;
 
 	return ata_pci_bmdma_init_one(pdev, ppi, &atiixp_sht, NULL,
 				      ATA_HOST_PARALLEL_SCAN);
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_cmd64x.c linux-libre-3.2-gnu/drivers/ata/pata_cmd64x.c
--- linux-libre-3.1-gnu/drivers/ata/pata_cmd64x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_cmd64x.c	2012-01-04 18:55:44.000000000 -0500
@@ -82,7 +82,7 @@
 }
 
 /**
- *	cmd64x_set_piomode	-	set PIO and MWDMA timing
+ *	cmd64x_set_timing	-	set PIO and MWDMA timing
  *	@ap: ATA interface
  *	@adev: ATA device
  *	@mode: mode
@@ -288,6 +288,22 @@
 	.cable_detect	= cmd648_cable_detect,
 };
 
+static void cmd64x_fixup(struct pci_dev *pdev)
+{
+	u8 mrdmode;
+
+	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
+	pci_read_config_byte(pdev, MRDMODE, &mrdmode);
+	mrdmode &= ~0x30;	/* IRQ set up */
+	mrdmode |= 0x02;	/* Memory read line enable */
+	pci_write_config_byte(pdev, MRDMODE, mrdmode);
+
+	/* PPC specific fixup copied from old driver */
+#ifdef CONFIG_PPC
+	pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
+#endif
+}
+
 static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	static const struct ata_port_info cmd_info[6] = {
@@ -336,7 +352,7 @@
 		&cmd_info[id->driver_data],
 		NULL
 	};
-	u8 mrdmode, reg;
+	u8 reg;
 	int rc;
 	struct pci_dev *bridge = pdev->bus->self;
 	/* mobility split bridges don't report enabled ports correctly */
@@ -368,11 +384,7 @@
 			cntrl_ch0_ok = 0;
 	}
 
-	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
-	pci_read_config_byte(pdev, MRDMODE, &mrdmode);
-	mrdmode &= ~ 0x30;	/* IRQ set up */
-	mrdmode |= 0x02;	/* Memory read line enable */
-	pci_write_config_byte(pdev, MRDMODE, mrdmode);
+	cmd64x_fixup(pdev);
 
 	/* check for enabled ports */
 	pci_read_config_byte(pdev, CNTRL, &reg);
@@ -388,13 +400,6 @@
 		ppi[1] = &ata_dummy_port_info;
 	}
 
-	/* Force PIO 0 here.. */
-
-	/* PPC specific fixup copied from old driver */
-#ifdef CONFIG_PPC
-	pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
-#endif
-
 	return ata_pci_bmdma_init_one(pdev, ppi, &cmd64x_sht, NULL, 0);
 }
 
@@ -402,21 +407,14 @@
 static int cmd64x_reinit_one(struct pci_dev *pdev)
 {
 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	u8 mrdmode;
 	int rc;
 
 	rc = ata_pci_device_do_resume(pdev);
 	if (rc)
 		return rc;
 
-	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
-	pci_read_config_byte(pdev, MRDMODE, &mrdmode);
-	mrdmode &= ~ 0x30;	/* IRQ set up */
-	mrdmode |= 0x02;	/* Memory read line enable */
-	pci_write_config_byte(pdev, MRDMODE, mrdmode);
-#ifdef CONFIG_PPC
-	pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
-#endif
+	cmd64x_fixup(pdev);
+
 	ata_host_resume(host);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_cs5535.c linux-libre-3.2-gnu/drivers/ata/pata_cs5535.c
--- linux-libre-3.1-gnu/drivers/ata/pata_cs5535.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_cs5535.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,7 +38,7 @@
 #include <linux/libata.h>
 #include <asm/msr.h>
 
-#define DRV_NAME	"cs5535"
+#define DRV_NAME	"pata_cs5535"
 #define DRV_VERSION	"0.2.12"
 
 /*
@@ -67,8 +67,6 @@
 
 #define CS5535_CABLE_DETECT    0x48
 
-#define CS5535_BAD_PIO(timings) ( (timings&~0x80000000UL)==0x00009172 )
-
 /**
  *	cs5535_cable_detect	-	detect cable type
  *	@ap: Port to detect on
@@ -188,16 +186,6 @@
 	};
 	const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
 
-	u32 timings, dummy;
-
-	/* Check the BIOS set the initial timing clock. If not set the
-	   timings for PIO0 */
-	rdmsr(ATAC_CH0D0_PIO, timings, dummy);
-	if (CS5535_BAD_PIO(timings))
-		wrmsr(ATAC_CH0D0_PIO, 0xF7F4F7F4UL, 0);
-	rdmsr(ATAC_CH0D1_PIO, timings, dummy);
-	if (CS5535_BAD_PIO(timings))
-		wrmsr(ATAC_CH0D1_PIO, 0xF7F4F7F4UL, 0);
 	return ata_pci_bmdma_init_one(dev, ppi, &cs5535_sht, NULL, 0);
 }
 
@@ -230,7 +218,7 @@
 }
 
 MODULE_AUTHOR("Alan Cox, Jens Altmann, Wolfgan Zuleger, Alexander Kiausch");
-MODULE_DESCRIPTION("low-level driver for the NS/AMD 5530");
+MODULE_DESCRIPTION("low-level driver for the NS/AMD 5535");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, cs5535);
 MODULE_VERSION(DRV_VERSION);
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_efar.c linux-libre-3.2-gnu/drivers/ata/pata_efar.c
--- linux-libre-3.1-gnu/drivers/ata/pata_efar.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_efar.c	2012-01-04 18:55:44.000000000 -0500
@@ -73,7 +73,7 @@
 /**
  *	efar_set_piomode - Initialize host controller PATA PIO timings
  *	@ap: Port whose timings we are configuring
- *	@adev: um
+ *	@adev: Device to program
  *
  *	Set PIO mode for device, in host controller PCI config space.
  *
@@ -85,9 +85,9 @@
 {
 	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
 	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
-	unsigned int idetm_port= ap->port_no ? 0x42 : 0x40;
+	unsigned int master_port = ap->port_no ? 0x42 : 0x40;
 	unsigned long flags;
-	u16 idetm_data;
+	u16 master_data;
 	u8 udma_enable;
 	int control = 0;
 
@@ -113,20 +113,20 @@
 
 	spin_lock_irqsave(&efar_lock, flags);
 
-	pci_read_config_word(dev, idetm_port, &idetm_data);
+	pci_read_config_word(dev, master_port, &master_data);
 
 	/* Set PPE, IE, and TIME as appropriate */
 	if (adev->devno == 0) {
-		idetm_data &= 0xCCF0;
-		idetm_data |= control;
-		idetm_data |= (timings[pio][0] << 12) |
+		master_data &= 0xCCF0;
+		master_data |= control;
+		master_data |= (timings[pio][0] << 12) |
 			(timings[pio][1] << 8);
 	} else {
 		int shift = 4 * ap->port_no;
 		u8 slave_data;
 
-		idetm_data &= 0xFF0F;
-		idetm_data |= (control << 4);
+		master_data &= 0xFF0F;
+		master_data |= (control << 4);
 
 		/* Slave timing in separate register */
 		pci_read_config_byte(dev, 0x44, &slave_data);
@@ -135,8 +135,8 @@
 		pci_write_config_byte(dev, 0x44, slave_data);
 	}
 
-	idetm_data |= 0x4000;	/* Ensure SITRE is set */
-	pci_write_config_word(dev, idetm_port, idetm_data);
+	master_data |= 0x4000;	/* Ensure SITRE is set */
+	pci_write_config_word(dev, master_port, master_data);
 
 	pci_read_config_byte(dev, 0x48, &udma_enable);
 	udma_enable &= ~(1 << (2 * ap->port_no + adev->devno));
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_hpt366.c linux-libre-3.2-gnu/drivers/ata/pata_hpt366.c
--- linux-libre-3.1-gnu/drivers/ata/pata_hpt366.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_hpt366.c	2012-01-04 18:55:44.000000000 -0500
@@ -111,6 +111,28 @@
 	{	0,		0x01208585	}
 };
 
+/**
+ *	hpt36x_find_mode	-	find the hpt36x timing
+ *	@ap: ATA port
+ *	@speed: transfer mode
+ *
+ *	Return the 32bit register programming information for this channel
+ *	that matches the speed provided.
+ */
+
+static u32 hpt36x_find_mode(struct ata_port *ap, int speed)
+{
+	struct hpt_clock *clocks = ap->host->private_data;
+
+	while (clocks->xfer_mode) {
+		if (clocks->xfer_mode == speed)
+			return clocks->timing;
+		clocks++;
+	}
+	BUG();
+	return 0xffffffffU;	/* silence compiler warning */
+}
+
 static const char * const bad_ata33[] = {
 	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3",
 	"Maxtor 90845U3", "Maxtor 90650U2",
@@ -210,10 +232,9 @@
 static void hpt366_set_mode(struct ata_port *ap, struct ata_device *adev,
 			    u8 mode)
 {
-	struct hpt_clock *clocks = ap->host->private_data;
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	u32 addr = 0x40 + 4 * adev->devno;
-	u32 mask, reg;
+	u32 mask, reg, t;
 
 	/* determine timing mask and find matching clock entry */
 	if (mode < XFER_MW_DMA_0)
@@ -223,13 +244,7 @@
 	else
 		mask = 0x30070000;
 
-	while (clocks->xfer_mode) {
-		if (clocks->xfer_mode == mode)
-			break;
-		clocks++;
-	}
-	if (!clocks->xfer_mode)
-		BUG();
+	t = hpt36x_find_mode(ap, mode);
 
 	/*
 	 * Combine new mode bits with old config bits and disable
@@ -237,7 +252,7 @@
 	 * problems handling I/O errors later.
 	 */
 	pci_read_config_dword(pdev, addr, &reg);
-	reg = ((reg & ~mask) | (clocks->timing & mask)) & ~0xc0000000;
+	reg = ((reg & ~mask) | (t & mask)) & ~0xc0000000;
 	pci_write_config_dword(pdev, addr, reg);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_it8213.c linux-libre-3.2-gnu/drivers/ata/pata_it8213.c
--- linux-libre-3.1-gnu/drivers/ata/pata_it8213.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_it8213.c	2012-01-04 18:55:44.000000000 -0500
@@ -76,8 +76,8 @@
 {
 	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
 	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
-	unsigned int idetm_port= ap->port_no ? 0x42 : 0x40;
-	u16 idetm_data;
+	unsigned int master_port = ap->port_no ? 0x42 : 0x40;
+	u16 master_data;
 	int control = 0;
 
 	/*
@@ -100,19 +100,19 @@
 	if (adev->class != ATA_DEV_ATA)
 		control |= 4;	/* PPE */
 
-	pci_read_config_word(dev, idetm_port, &idetm_data);
+	pci_read_config_word(dev, master_port, &master_data);
 
 	/* Set PPE, IE, and TIME as appropriate */
 	if (adev->devno == 0) {
-		idetm_data &= 0xCCF0;
-		idetm_data |= control;
-		idetm_data |= (timings[pio][0] << 12) |
+		master_data &= 0xCCF0;
+		master_data |= control;
+		master_data |= (timings[pio][0] << 12) |
 			(timings[pio][1] << 8);
 	} else {
 		u8 slave_data;
 
-		idetm_data &= 0xFF0F;
-		idetm_data |= (control << 4);
+		master_data &= 0xFF0F;
+		master_data |= (control << 4);
 
 		/* Slave timing in separate register */
 		pci_read_config_byte(dev, 0x44, &slave_data);
@@ -121,8 +121,8 @@
 		pci_write_config_byte(dev, 0x44, slave_data);
 	}
 
-	idetm_data |= 0x4000;	/* Ensure SITRE is set */
-	pci_write_config_word(dev, idetm_port, idetm_data);
+	master_data |= 0x4000;	/* Ensure SITRE is set */
+	pci_write_config_word(dev, master_port, master_data);
 }
 
 /**
@@ -163,7 +163,7 @@
 
 		/* Clocks follow the PIIX style */
 		u_speed = min(2 - (udma & 1), udma);
-		if (udma == 5)
+		if (udma > 4)
 			u_clock = 0x1000;	/* 100Mhz */
 		else if (udma > 2)
 			u_clock = 1;		/* 66Mhz */
@@ -262,7 +262,7 @@
 		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA12_ONLY,
-		.udma_mask 	= ATA_UDMA4, /* FIXME: want UDMA 100? */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &it8213_ops,
 	};
 	/* Current IT8213 stuff is single port */
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_legacy.c linux-libre-3.2-gnu/drivers/ata/pata_legacy.c
--- linux-libre-3.1-gnu/drivers/ata/pata_legacy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_legacy.c	2012-01-04 18:55:44.000000000 -0500
@@ -79,15 +79,6 @@
 module_param(all, int, 0444);
 MODULE_PARM_DESC(all, "Grab all legacy port devices, even if PCI(0=off, 1=on)");
 
-struct legacy_data {
-	unsigned long timing;
-	u8 clock[2];
-	u8 last;
-	int fast;
-	struct platform_device *platform_dev;
-
-};
-
 enum controller {
 	BIOS = 0,
 	SNOOP = 1,
@@ -104,6 +95,14 @@
 	UNKNOWN = -1
 };
 
+struct legacy_data {
+	unsigned long timing;
+	u8 clock[2];
+	u8 last;
+	int fast;
+	enum controller type;
+	struct platform_device *platform_dev;
+};
 
 struct legacy_probe {
 	unsigned char *name;
@@ -137,11 +136,17 @@
 static int ht6560b;		/* HT 6560A on primary 1, second 2, both 3 */
 static int opti82c611a;		/* Opti82c611A on primary 1, sec 2, both 3 */
 static int opti82c46x;		/* Opti 82c465MV present(pri/sec autodetect) */
-static int qdi;			/* Set to probe QDI controllers */
 static int autospeed;		/* Chip present which snoops speed changes */
 static int pio_mask = ATA_PIO4;	/* PIO range for autospeed devices */
 static int iordy_mask = 0xFFFFFFFF;	/* Use iordy if available */
 
+/* Set to probe QDI controllers */
+#ifdef CONFIG_PATA_QDI_MODULE
+static int qdi = 1;
+#else
+static int qdi;
+#endif
+
 #ifdef CONFIG_PATA_WINBOND_VLB_MODULE
 static int winbond = 1;		/* Set to probe Winbond controllers,
 					give I/O port if non standard */
@@ -631,40 +636,20 @@
 	.qc_issue	= opti82c46x_qc_issue,
 };
 
-static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
-	struct ata_timing t;
-	struct legacy_data *ld_qdi = ap->host->private_data;
-	int active, recovery;
-	u8 timing;
-
-	/* Get the timing data in cycles */
-	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
-
-	if (ld_qdi->fast) {
-		active = 8 - clamp_val(t.active, 1, 8);
-		recovery = 18 - clamp_val(t.recover, 3, 18);
-	} else {
-		active = 9 - clamp_val(t.active, 2, 9);
-		recovery = 15 - clamp_val(t.recover, 0, 15);
-	}
-	timing = (recovery << 4) | active | 0x08;
-
-	ld_qdi->clock[adev->devno] = timing;
-
-	outb(timing, ld_qdi->timing);
-}
-
 /**
- *	qdi6580dp_set_piomode		-	PIO setup for dual channel
+ *	qdi65x0_set_piomode		-	PIO setup for QDI65x0
  *	@ap: Port
  *	@adev: Device
  *
+ *	In single channel mode the 6580 has one clock per device and we can
+ *	avoid the requirement to clock switch. We also have to load the timing
+ *	into the right clock according to whether we are master or slave.
+ *
  *	In dual channel mode the 6580 has one clock per channel and we have
  *	to software clockswitch in qc_issue.
  */
 
-static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
+static void qdi65x0_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
 	struct ata_timing t;
 	struct legacy_data *ld_qdi = ap->host->private_data;
@@ -682,47 +667,15 @@
 		recovery = 15 - clamp_val(t.recover, 0, 15);
 	}
 	timing = (recovery << 4) | active | 0x08;
-
 	ld_qdi->clock[adev->devno] = timing;
 
-	outb(timing, ld_qdi->timing + 2 * ap->port_no);
-	/* Clear the FIFO */
-	if (adev->class != ATA_DEV_ATA)
-		outb(0x5F, (ld_qdi->timing & 0xFFF0) + 3);
-}
-
-/**
- *	qdi6580_set_piomode		-	PIO setup for single channel
- *	@ap: Port
- *	@adev: Device
- *
- *	In single channel mode the 6580 has one clock per device and we can
- *	avoid the requirement to clock switch. We also have to load the timing
- *	into the right clock according to whether we are master or slave.
- */
-
-static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
-	struct ata_timing t;
-	struct legacy_data *ld_qdi = ap->host->private_data;
-	int active, recovery;
-	u8 timing;
-
-	/* Get the timing data in cycles */
-	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
+	if (ld_qdi->type == QDI6580)
+		outb(timing, ld_qdi->timing + 2 * adev->devno);
+	else
+		outb(timing, ld_qdi->timing + 2 * ap->port_no);
 
-	if (ld_qdi->fast) {
-		active = 8 - clamp_val(t.active, 1, 8);
-		recovery = 18 - clamp_val(t.recover, 3, 18);
-	} else {
-		active = 9 - clamp_val(t.active, 2, 9);
-		recovery = 15 - clamp_val(t.recover, 0, 15);
-	}
-	timing = (recovery << 4) | active | 0x08;
-	ld_qdi->clock[adev->devno] = timing;
-	outb(timing, ld_qdi->timing + 2 * adev->devno);
 	/* Clear the FIFO */
-	if (adev->class != ATA_DEV_ATA)
+	if (ld_qdi->type != QDI6500 && adev->class != ATA_DEV_ATA)
 		outb(0x5F, (ld_qdi->timing & 0xFFF0) + 3);
 }
 
@@ -789,20 +742,20 @@
 
 static struct ata_port_operations qdi6500_port_ops = {
 	.inherits	= &legacy_base_port_ops,
-	.set_piomode	= qdi6500_set_piomode,
+	.set_piomode	= qdi65x0_set_piomode,
 	.qc_issue	= qdi_qc_issue,
 	.sff_data_xfer	= vlb32_data_xfer,
 };
 
 static struct ata_port_operations qdi6580_port_ops = {
 	.inherits	= &legacy_base_port_ops,
-	.set_piomode	= qdi6580_set_piomode,
+	.set_piomode	= qdi65x0_set_piomode,
 	.sff_data_xfer	= vlb32_data_xfer,
 };
 
 static struct ata_port_operations qdi6580dp_port_ops = {
 	.inherits	= &legacy_base_port_ops,
-	.set_piomode	= qdi6580dp_set_piomode,
+	.set_piomode	= qdi65x0_set_piomode,
 	.qc_issue	= qdi_qc_issue,
 	.sff_data_xfer	= vlb32_data_xfer,
 };
@@ -879,29 +832,29 @@
 };
 
 static struct legacy_controller controllers[] = {
-	{"BIOS",	&legacy_port_ops, 	0x1F,
+	{"BIOS",	&legacy_port_ops, 	ATA_PIO4,
 			ATA_FLAG_NO_IORDY,	0,			NULL },
-	{"Snooping", 	&simple_port_ops, 	0x1F,
+	{"Snooping", 	&simple_port_ops, 	ATA_PIO4,
 			0,			0,			NULL },
-	{"PDC20230",	&pdc20230_port_ops,	0x7,
+	{"PDC20230",	&pdc20230_port_ops,	ATA_PIO2,
 			ATA_FLAG_NO_IORDY,
 			ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE,	NULL },
-	{"HT6560A",	&ht6560a_port_ops,	0x07,
+	{"HT6560A",	&ht6560a_port_ops,	ATA_PIO2,
 			ATA_FLAG_NO_IORDY,	0,			NULL },
-	{"HT6560B",	&ht6560b_port_ops,	0x1F,
+	{"HT6560B",	&ht6560b_port_ops,	ATA_PIO4,
 			ATA_FLAG_NO_IORDY,	0,			NULL },
-	{"OPTI82C611A",	&opti82c611a_port_ops,	0x0F,
+	{"OPTI82C611A",	&opti82c611a_port_ops,	ATA_PIO3,
 			0,			0,			NULL },
-	{"OPTI82C46X",	&opti82c46x_port_ops,	0x0F,
+	{"OPTI82C46X",	&opti82c46x_port_ops,	ATA_PIO3,
 			0,			0,			NULL },
-	{"QDI6500",	&qdi6500_port_ops,	0x07,
+	{"QDI6500",	&qdi6500_port_ops,	ATA_PIO2,
 			ATA_FLAG_NO_IORDY,
 			ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE,    qdi_port },
-	{"QDI6580",	&qdi6580_port_ops,	0x1F,
+	{"QDI6580",	&qdi6580_port_ops,	ATA_PIO4,
 			0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port },
-	{"QDI6580DP",	&qdi6580dp_port_ops,	0x1F,
+	{"QDI6580DP",	&qdi6580dp_port_ops,	ATA_PIO4,
 			0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port },
-	{"W83759A",	&winbond_port_ops,	0x1F,
+	{"W83759A",	&winbond_port_ops,	ATA_PIO4,
 			0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE,
 								winbond_port }
 };
@@ -1022,6 +975,7 @@
 	ctrl_addr = devm_ioport_map(&pdev->dev, io + 0x0206, 1);
 	if (!io_addr || !ctrl_addr)
 		goto fail;
+	ld->type = probe->type;
 	if (controller->setup)
 		if (controller->setup(pdev, probe, ld) < 0)
 			goto fail;
@@ -1306,6 +1260,7 @@
 MODULE_DESCRIPTION("low-level driver for legacy ATA");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
+MODULE_ALIAS("pata_qdi");
 MODULE_ALIAS("pata_winbond");
 
 module_param(probe_all, int, 0);
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_mpc52xx.c linux-libre-3.2-gnu/drivers/ata/pata_mpc52xx.c
--- linux-libre-3.1-gnu/drivers/ata/pata_mpc52xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_mpc52xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -780,7 +780,7 @@
 	}
 
 	task_irq = bcom_get_task_irq(dmatsk);
-	ret = request_irq(task_irq, &mpc52xx_ata_task_irq, IRQF_DISABLED,
+	ret = request_irq(task_irq, &mpc52xx_ata_task_irq, 0,
 				"ATA task", priv);
 	if (ret) {
 		dev_err(&op->dev, "error requesting DMA IRQ\n");
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_of_platform.c linux-libre-3.2-gnu/drivers/ata/pata_of_platform.c
--- linux-libre-3.1-gnu/drivers/ata/pata_of_platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_of_platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,8 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/ata_platform.h>
 
@@ -50,18 +52,18 @@
 	}
 
 	ret = of_irq_to_resource(dn, 0, &irq_res);
-	if (ret == NO_IRQ)
+	if (!ret)
 		irq_res.start = irq_res.end = 0;
 	else
 		irq_res.flags = 0;
 
 	prop = of_get_property(dn, "reg-shift", NULL);
 	if (prop)
-		reg_shift = *prop;
+		reg_shift = be32_to_cpup(prop);
 
 	prop = of_get_property(dn, "pio-mode", NULL);
 	if (prop) {
-		pio_mode = *prop;
+		pio_mode = be32_to_cpup(prop);
 		if (pio_mode > 6) {
 			dev_err(&ofdev->dev, "invalid pio-mode\n");
 			return -EINVAL;
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_pdc2027x.c linux-libre-3.2-gnu/drivers/ata/pata_pdc2027x.c
--- linux-libre-3.1-gnu/drivers/ata/pata_pdc2027x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_pdc2027x.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,6 +63,7 @@
 };
 
 static int pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+static int pdc2027x_reinit_one(struct pci_dev *pdev);
 static int pdc2027x_prereset(struct ata_link *link, unsigned long deadline);
 static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);
 static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);
@@ -126,6 +127,10 @@
 	.id_table		= pdc2027x_pci_tbl,
 	.probe			= pdc2027x_init_one,
 	.remove			= ata_pci_remove_one,
+#ifdef CONFIG_PM
+	.suspend		= ata_pci_device_suspend,
+	.resume			= pdc2027x_reinit_one,
+#endif
 };
 
 static struct scsi_host_template pdc2027x_sht = {
@@ -754,6 +759,31 @@
 				 IRQF_SHARED, &pdc2027x_sht);
 }
 
+#ifdef CONFIG_PM
+static int pdc2027x_reinit_one(struct pci_dev *pdev)
+{
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	unsigned int board_idx;
+	int rc;
+
+	rc = ata_pci_device_do_resume(pdev);
+	if (rc)
+		return rc;
+
+	if (pdev->device == PCI_DEVICE_ID_PROMISE_20268 ||
+	    pdev->device == PCI_DEVICE_ID_PROMISE_20270)
+		board_idx = PDC_UDMA_100;
+	else
+		board_idx = PDC_UDMA_133;
+
+	if (pdc_hardware_init(host, board_idx))
+		return -EIO;
+
+	ata_host_resume(host);
+	return 0;
+}
+#endif
+
 /**
  * pdc2027x_init - Called after this module is loaded into the kernel.
  */
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_qdi.c linux-libre-3.2-gnu/drivers/ata/pata_qdi.c
--- linux-libre-3.1-gnu/drivers/ata/pata_qdi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_qdi.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,366 +0,0 @@
-/*
- *    pata_qdi.c - QDI VLB ATA controllers
- *	(C) 2006 Red Hat
- *
- * This driver mostly exists as a proof of concept for non PCI devices under
- * libata. While the QDI6580 was 'neat' in 1993 it is no longer terribly
- * useful.
- *
- * Tuning code written from the documentation at
- * http://www.ryston.cz/petr/vlb/qd6500.html
- * http://www.ryston.cz/petr/vlb/qd6580.html
- *
- * Probe code based on drivers/ide/legacy/qd65xx.c
- * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
- * Samuel Thibault <samuel.thibault@ens-lyon.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-#include <linux/platform_device.h>
-
-#define DRV_NAME "pata_qdi"
-#define DRV_VERSION "0.3.1"
-
-#define NR_HOST 4	/* Two 6580s */
-
-struct qdi_data {
-	unsigned long timing;
-	u8 clock[2];
-	u8 last;
-	int fast;
-	struct platform_device *platform_dev;
-
-};
-
-static struct ata_host *qdi_host[NR_HOST];
-static struct qdi_data qdi_data[NR_HOST];
-static int nr_qdi_host;
-
-#ifdef MODULE
-static int probe_qdi = 1;
-#else
-static int probe_qdi;
-#endif
-
-static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
-	struct ata_timing t;
-	struct qdi_data *qdi = ap->host->private_data;
-	int active, recovery;
-	u8 timing;
-
-	/* Get the timing data in cycles */
-	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
-
-	if (qdi->fast) {
-		active = 8 - clamp_val(t.active, 1, 8);
-		recovery = 18 - clamp_val(t.recover, 3, 18);
-	} else {
-		active = 9 - clamp_val(t.active, 2, 9);
-		recovery = 15 - clamp_val(t.recover, 0, 15);
-	}
-	timing = (recovery << 4) | active | 0x08;
-
-	qdi->clock[adev->devno] = timing;
-
-	outb(timing, qdi->timing);
-}
-
-static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
-{
-	struct ata_timing t;
-	struct qdi_data *qdi = ap->host->private_data;
-	int active, recovery;
-	u8 timing;
-
-	/* Get the timing data in cycles */
-	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
-
-	if (qdi->fast) {
-		active = 8 - clamp_val(t.active, 1, 8);
-		recovery = 18 - clamp_val(t.recover, 3, 18);
-	} else {
-		active = 9 - clamp_val(t.active, 2, 9);
-		recovery = 15 - clamp_val(t.recover, 0, 15);
-	}
-	timing = (recovery << 4) | active | 0x08;
-
-	qdi->clock[adev->devno] = timing;
-
-	outb(timing, qdi->timing);
-
-	/* Clear the FIFO */
-	if (adev->class != ATA_DEV_ATA)
-		outb(0x5F, (qdi->timing & 0xFFF0) + 3);
-}
-
-/**
- *	qdi_qc_issue		-	command issue
- *	@qc: command pending
- *
- *	Called when the libata layer is about to issue a command. We wrap
- *	this interface so that we can load the correct ATA timings.
- */
-
-static unsigned int qdi_qc_issue(struct ata_queued_cmd *qc)
-{
-	struct ata_port *ap = qc->ap;
-	struct ata_device *adev = qc->dev;
-	struct qdi_data *qdi = ap->host->private_data;
-
-	if (qdi->clock[adev->devno] != qdi->last) {
-		if (adev->pio_mode) {
-			qdi->last = qdi->clock[adev->devno];
-			outb(qdi->clock[adev->devno], qdi->timing);
-		}
-	}
-	return ata_sff_qc_issue(qc);
-}
-
-static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf,
-				  unsigned int buflen, int rw)
-{
-	if (ata_id_has_dword_io(dev->id)) {
-		struct ata_port *ap = dev->link->ap;
-		int slop = buflen & 3;
-
-		if (rw == READ)
-			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
-		else
-			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
-
-		if (unlikely(slop)) {
-			__le32 pad;
-			if (rw == READ) {
-				pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
-				memcpy(buf + buflen - slop, &pad, slop);
-			} else {
-				memcpy(&pad, buf + buflen - slop, slop);
-				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
-			}
-			buflen += 4 - slop;
-		}
-	} else
-		buflen = ata_sff_data_xfer(dev, buf, buflen, rw);
-
-	return buflen;
-}
-
-static struct scsi_host_template qdi_sht = {
-	ATA_PIO_SHT(DRV_NAME),
-};
-
-static struct ata_port_operations qdi6500_port_ops = {
-	.inherits	= &ata_sff_port_ops,
-	.qc_issue	= qdi_qc_issue,
-	.sff_data_xfer	= qdi_data_xfer,
-	.cable_detect	= ata_cable_40wire,
-	.set_piomode	= qdi6500_set_piomode,
-};
-
-static struct ata_port_operations qdi6580_port_ops = {
-	.inherits	= &qdi6500_port_ops,
-	.set_piomode	= qdi6580_set_piomode,
-};
-
-/**
- *	qdi_init_one		-	attach a qdi interface
- *	@type: Type to display
- *	@io: I/O port start
- *	@irq: interrupt line
- *	@fast: True if on a > 33Mhz VLB
- *
- *	Register an ISA bus IDE interface. Such interfaces are PIO and we
- *	assume do not support IRQ sharing.
- */
-
-static __init int qdi_init_one(unsigned long port, int type, unsigned long io, int irq, int fast)
-{
-	unsigned long ctl = io + 0x206;
-	struct platform_device *pdev;
-	struct ata_host *host;
-	struct ata_port *ap;
-	void __iomem *io_addr, *ctl_addr;
-	int ret;
-
-	/*
-	 *	Fill in a probe structure first of all
-	 */
-
-	pdev = platform_device_register_simple(DRV_NAME, nr_qdi_host, NULL, 0);
-	if (IS_ERR(pdev))
-		return PTR_ERR(pdev);
-
-	ret = -ENOMEM;
-	io_addr = devm_ioport_map(&pdev->dev, io, 8);
-	ctl_addr = devm_ioport_map(&pdev->dev, ctl, 1);
-	if (!io_addr || !ctl_addr)
-		goto fail;
-
-	ret = -ENOMEM;
-	host = ata_host_alloc(&pdev->dev, 1);
-	if (!host)
-		goto fail;
-	ap = host->ports[0];
-
-	if (type == 6580) {
-		ap->ops = &qdi6580_port_ops;
-		ap->pio_mask = ATA_PIO4;
-		ap->flags |= ATA_FLAG_SLAVE_POSS;
-	} else {
-		ap->ops = &qdi6500_port_ops;
-		ap->pio_mask = ATA_PIO2; /* Actually PIO3 !IORDY is possible */
-		ap->flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY;
-	}
-
-	ap->ioaddr.cmd_addr = io_addr;
-	ap->ioaddr.altstatus_addr = ctl_addr;
-	ap->ioaddr.ctl_addr = ctl_addr;
-	ata_sff_std_ports(&ap->ioaddr);
-
-	ata_port_desc(ap, "cmd %lx ctl %lx", io, ctl);
-
-	/*
-	 *	Hook in a private data structure per channel
-	 */
-	ap->private_data = &qdi_data[nr_qdi_host];
-
-	qdi_data[nr_qdi_host].timing = port;
-	qdi_data[nr_qdi_host].fast = fast;
-	qdi_data[nr_qdi_host].platform_dev = pdev;
-
-	printk(KERN_INFO DRV_NAME": qd%d at 0x%lx.\n", type, io);
-
-	/* activate */
-	ret = ata_host_activate(host, irq, ata_sff_interrupt, 0, &qdi_sht);
-	if (ret)
-		goto fail;
-
-	qdi_host[nr_qdi_host++] = dev_get_drvdata(&pdev->dev);
-	return 0;
-
- fail:
-	platform_device_unregister(pdev);
-	return ret;
-}
-
-/**
- *	qdi_init		-	attach qdi interfaces
- *
- *	Attach qdi IDE interfaces by scanning the ports it may occupy.
- */
-
-static __init int qdi_init(void)
-{
-	unsigned long flags;
-	static const unsigned long qd_port[2] = { 0x30, 0xB0 };
-	static const unsigned long ide_port[2] = { 0x170, 0x1F0 };
-	static const int ide_irq[2] = { 14, 15 };
-
-	int ct = 0;
-	int i;
-
-	if (probe_qdi == 0)
-		return -ENODEV;
-
-	/*
- 	 *	Check each possible QD65xx base address
-	 */
-
-	for (i = 0; i < 2; i++) {
-		unsigned long port = qd_port[i];
-		u8 r, res;
-
-
-		if (request_region(port, 2, "pata_qdi")) {
-			/* Check for a card */
-			local_irq_save(flags);
-			r = inb_p(port);
-			outb_p(0x19, port);
-			res = inb_p(port);
-			outb_p(r, port);
-			local_irq_restore(flags);
-
-			/* Fail */
-			if (res == 0x19)
-			{
-				release_region(port, 2);
-				continue;
-			}
-
-			/* Passes the presence test */
-			r = inb_p(port + 1);	/* Check port agrees with port set */
-			if ((r & 2) >> 1 != i) {
-				release_region(port, 2);
-				continue;
-			}
-
-			/* Check card type */
-			if ((r & 0xF0) == 0xC0) {
-				/* QD6500: single channel */
-				if (r & 8) {
-					/* Disabled ? */
-					release_region(port, 2);
-					continue;
-				}
-				if (qdi_init_one(port, 6500, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04) == 0)
-					ct++;
-			}
-			if (((r & 0xF0) == 0xA0) || (r & 0xF0) == 0x50) {
-				/* QD6580: dual channel */
-				if (!request_region(port + 2 , 2, "pata_qdi"))
-				{
-					release_region(port, 2);
-					continue;
-				}
-				res = inb(port + 3);
-				if (res & 1) {
-					/* Single channel mode */
-					if (qdi_init_one(port, 6580, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04) == 0)
-						ct++;
-				} else {
-					/* Dual channel mode */
-					if (qdi_init_one(port, 6580, 0x1F0, 14, r & 0x04) == 0)
-						ct++;
-					if (qdi_init_one(port + 2, 6580, 0x170, 15, r & 0x04) == 0)
-						ct++;
-				}
-			}
-		}
-	}
-	if (ct != 0)
-		return 0;
-	return -ENODEV;
-}
-
-static __exit void qdi_exit(void)
-{
-	int i;
-
-	for (i = 0; i < nr_qdi_host; i++) {
-		ata_host_detach(qdi_host[i]);
-		/* Free the control resource. The 6580 dual channel has the resources
-		 * claimed as a pair of 2 byte resources so we need no special cases...
-		 */
-		release_region(qdi_data[i].timing, 2);
-		platform_device_unregister(qdi_data[i].platform_dev);
-	}
-}
-
-MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("low-level driver for qdi ATA");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-
-module_init(qdi_init);
-module_exit(qdi_exit);
-
-module_param(probe_qdi, int, 0);
-
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_rdc.c linux-libre-3.2-gnu/drivers/ata/pata_rdc.c
--- linux-libre-3.1-gnu/drivers/ata/pata_rdc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_rdc.c	2012-01-04 18:55:44.000000000 -0500
@@ -86,6 +86,8 @@
 	return ata_sff_prereset(link, deadline);
 }
 
+static DEFINE_SPINLOCK(rdc_lock);
+
 /**
  *	rdc_set_piomode - Initialize host controller PATA PIO timings
  *	@ap: Port whose timings we are configuring
@@ -101,6 +103,7 @@
 {
 	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
 	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
+	unsigned long flags;
 	unsigned int is_slave	= (adev->devno != 0);
 	unsigned int master_port= ap->port_no ? 0x42 : 0x40;
 	unsigned int slave_port	= 0x44;
@@ -124,6 +127,8 @@
 	if (adev->class == ATA_DEV_ATA)
 		control |= 4;	/* PPE enable */
 
+	spin_lock_irqsave(&rdc_lock, flags);
+
 	/* PIO configuration clears DTE unconditionally.  It will be
 	 * programmed in set_dmamode which is guaranteed to be called
 	 * after set_piomode if any DMA mode is available.
@@ -161,6 +166,8 @@
 	pci_read_config_byte(dev, 0x48, &udma_enable);
 	udma_enable &= ~(1 << (2 * ap->port_no + adev->devno));
 	pci_write_config_byte(dev, 0x48, udma_enable);
+
+	spin_unlock_irqrestore(&rdc_lock, flags);
 }
 
 /**
@@ -177,6 +184,7 @@
 static void rdc_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 {
 	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
+	unsigned long flags;
 	u8 master_port		= ap->port_no ? 0x42 : 0x40;
 	u16 master_data;
 	u8 speed		= adev->dma_mode;
@@ -190,6 +198,8 @@
 			    { 2, 1 },
 			    { 2, 3 }, };
 
+	spin_lock_irqsave(&rdc_lock, flags);
+
 	pci_read_config_word(dev, master_port, &master_data);
 	pci_read_config_byte(dev, 0x48, &udma_enable);
 
@@ -271,6 +281,8 @@
 		pci_write_config_word(dev, master_port, master_data);
 	}
 	pci_write_config_byte(dev, 0x48, udma_enable);
+
+	spin_unlock_irqrestore(&rdc_lock, flags);
 }
 
 static struct ata_port_operations rdc_pata_ops = {
@@ -375,6 +387,10 @@
 	.id_table		= rdc_pci_tbl,
 	.probe			= rdc_init_one,
 	.remove			= rdc_remove_one,
+#ifdef CONFIG_PM
+	.suspend		= ata_pci_device_suspend,
+	.resume			= ata_pci_device_resume,
+#endif
 };
 
 
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_sc1200.c linux-libre-3.2-gnu/drivers/ata/pata_sc1200.c
--- linux-libre-3.1-gnu/drivers/ata/pata_sc1200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_sc1200.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,7 +38,7 @@
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 
-#define DRV_NAME	"sc1200"
+#define DRV_NAME	"pata_sc1200"
 #define DRV_VERSION	"0.2.6"
 
 #define SC1200_REV_A	0x00
@@ -86,10 +86,14 @@
 static void sc1200_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
 	static const u32 pio_timings[4][5] = {
-		{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010},	// format0  33Mhz
-		{0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010},	// format1, 33Mhz
-		{0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021},	// format1, 48Mhz
-		{0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131}	// format1, 66Mhz
+		/* format0, 33Mhz */
+		{ 0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010 },
+		/* format1, 33Mhz */
+		{ 0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010 },
+		/* format1, 48Mhz */
+		{ 0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021 },
+		/* format1, 66Mhz */
+		{ 0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131 }
 	};
 
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_scc.c linux-libre-3.2-gnu/drivers/ata/pata_scc.c
--- linux-libre-3.1-gnu/drivers/ata/pata_scc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_scc.c	2012-01-04 18:55:44.000000000 -0500
@@ -826,18 +826,6 @@
 }
 
 /**
- *	scc_pata_prereset - prepare for reset
- *	@ap: ATA port to be reset
- *	@deadline: deadline jiffies for the operation
- */
-
-static int scc_pata_prereset(struct ata_link *link, unsigned long deadline)
-{
-	link->ap->cbl = ATA_CBL_PATA80;
-	return ata_sff_prereset(link, deadline);
-}
-
-/**
  *	scc_postreset - standard postreset callback
  *	@ap: the target ata_port
  *	@classes: classes of attached devices
@@ -946,7 +934,7 @@
 	.bmdma_status		= scc_bmdma_status,
 	.sff_data_xfer		= scc_data_xfer,
 
-	.prereset		= scc_pata_prereset,
+	.cable_detect		= ata_cable_80wire,
 	.softreset		= scc_softreset,
 	.postreset		= scc_postreset,
 
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_serverworks.c linux-libre-3.2-gnu/drivers/ata/pata_serverworks.c
--- linux-libre-3.1-gnu/drivers/ata/pata_serverworks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_serverworks.c	2012-01-04 18:55:44.000000000 -0500
@@ -58,31 +58,15 @@
 };
 
 /**
- *	dell_cable	-	Dell serverworks cable detection
+ *	oem_cable	-	Dell/Sun serverworks cable detection
  *	@ap: ATA port to do cable detect
  *
- *	Dell hide the 40/80 pin select for their interfaces in the top two
- *	bits of the subsystem ID.
- */
-
-static int dell_cable(struct ata_port *ap) {
-	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-
-	if (pdev->subsystem_device & (1 << (ap->port_no + 14)))
-		return ATA_CBL_PATA80;
-	return ATA_CBL_PATA40;
-}
-
-/**
- *	sun_cable	-	Sun Cobalt 'Alpine' cable detection
- *	@ap: ATA port to do cable select
- *
- *	Cobalt CSB5 IDE hides the 40/80pin in the top two bits of the
- *	subsystem ID the same as dell. We could use one function but we may
- *	need to extend the Dell one in future
+ *	Dell PowerEdge and Sun Cobalt 'Alpine' hide the 40/80 pin select
+ *	for their interfaces in the top two bits of the subsystem ID.
  */
 
-static int sun_cable(struct ata_port *ap) {
+static int oem_cable(struct ata_port *ap)
+{
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
 	if (pdev->subsystem_device & (1 << (ap->port_no + 14)))
@@ -90,49 +74,21 @@
 	return ATA_CBL_PATA40;
 }
 
-/**
- *	osb4_cable	-	OSB4 cable detect
- *	@ap: ATA port to check
- *
- *	The OSB4 isn't UDMA66 capable so this is easy
- */
-
-static int osb4_cable(struct ata_port *ap) {
-	return ATA_CBL_PATA40;
-}
-
-/**
- *	csb_cable	-	CSB5/6 cable detect
- *	@ap: ATA port to check
- *
- *	Serverworks default arrangement is to use the drive side detection
- *	only.
- */
-
-static int csb_cable(struct ata_port *ap) {
-	return ATA_CBL_PATA_UNK;
-}
-
 struct sv_cable_table {
 	int device;
 	int subvendor;
 	int (*cable_detect)(struct ata_port *ap);
 };
 
-/*
- *	Note that we don't copy the old serverworks code because the old
- *	code contains obvious mistakes
- */
-
 static struct sv_cable_table cable_detect[] = {
-	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_DELL, dell_cable },
-	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_VENDOR_ID_DELL, dell_cable },
-	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_SUN,  sun_cable },
-	{ PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, osb4_cable },
-	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, csb_cable },
-	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, csb_cable },
-	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, csb_cable },
-	{ PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, csb_cable },
+	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE,   PCI_VENDOR_ID_DELL, oem_cable },
+	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE,   PCI_VENDOR_ID_DELL, oem_cable },
+	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE,   PCI_VENDOR_ID_SUN,  oem_cable },
+	{ PCI_DEVICE_ID_SERVERWORKS_OSB4IDE,   PCI_ANY_ID, ata_cable_40wire  },
+	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE,   PCI_ANY_ID, ata_cable_unknown },
+	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE,   PCI_ANY_ID, ata_cable_unknown },
+	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2,  PCI_ANY_ID, ata_cable_unknown },
+	{ PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, ata_cable_unknown },
 	{ }
 };
 
@@ -393,6 +349,31 @@
 	pci_write_config_byte(pdev, 0x5A, btr);
 }
 
+static int serverworks_fixup(struct pci_dev *pdev)
+{
+	int rc = 0;
+
+	/* Force master latency timer to 64 PCI clocks */
+	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
+
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE:
+		rc = serverworks_fixup_osb4(pdev);
+		break;
+	case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
+		ata_pci_bmdma_clear_simplex(pdev);
+		/* fall through */
+	case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
+	case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
+		rc = serverworks_fixup_csb(pdev);
+		break;
+	case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE:
+		serverworks_fixup_ht1000(pdev);
+		break;
+	}
+
+	return rc;
+}
 
 static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
@@ -430,13 +411,12 @@
 	if (rc)
 		return rc;
 
-	/* Force master latency timer to 64 PCI clocks */
-	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
+	rc = serverworks_fixup(pdev);
 
 	/* OSB4 : South Bridge and IDE */
 	if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
 		/* Select non UDMA capable OSB4 if we can't do fixups */
-		if ( serverworks_fixup_osb4(pdev) < 0)
+		if (rc < 0)
 			ppi[0] = &info[1];
 	}
 	/* setup CSB5/CSB6 : South Bridge and IDE option RAID */
@@ -446,19 +426,13 @@
 
 		 /* If the returned btr is the newer revision then
 		    select the right info block */
-		 if (serverworks_fixup_csb(pdev) == 3)
+		 if (rc == 3)
 		 	ppi[0] = &info[3];
 
 		/* Is this the 3rd channel CSB6 IDE ? */
 		if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)
 			ppi[1] = &ata_dummy_port_info;
 	}
-	/* setup HT1000E */
-	else if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
-		serverworks_fixup_ht1000(pdev);
-
-	if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
-		ata_pci_bmdma_clear_simplex(pdev);
 
 	return ata_pci_bmdma_init_one(pdev, ppi, &serverworks_sht, NULL, 0);
 }
@@ -473,24 +447,7 @@
 	if (rc)
 		return rc;
 
-	/* Force master latency timer to 64 PCI clocks */
-	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
-
-	switch (pdev->device) {
-		case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE:
-			serverworks_fixup_osb4(pdev);
-			break;
-		case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
-			ata_pci_bmdma_clear_simplex(pdev);
-			/* fall through */
-		case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
-		case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
-			serverworks_fixup_csb(pdev);
-			break;
-		case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE:
-			serverworks_fixup_ht1000(pdev);
-			break;
-	}
+	(void)serverworks_fixup(pdev);
 
 	ata_host_resume(host);
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_sil680.c linux-libre-3.2-gnu/drivers/ata/pata_sil680.c
--- linux-libre-3.1-gnu/drivers/ata/pata_sil680.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_sil680.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,11 +38,12 @@
 
 /**
  *	sil680_selreg		-	return register base
- *	@hwif: interface
+ *	@ap: ATA interface
  *	@r: config offset
  *
- *	Turn a config register offset into the right address in either
- *	PCI space or MMIO space to access the control register in question
+ *	Turn a config register offset into the right address in PCI space
+ *	to access the control register in question.
+ *
  *	Thankfully this is a configuration operation so isn't performance
  *	criticial.
  */
@@ -56,12 +57,12 @@
 
 /**
  *	sil680_seldev		-	return register base
- *	@hwif: interface
+ *	@ap: ATA interface
  *	@r: config offset
  *
- *	Turn a config register offset into the right address in either
- *	PCI space or MMIO space to access the control register in question
- *	including accounting for the unit shift.
+ *	Turn a config register offset into the right address in PCI space
+ *	to access the control register in question including accounting for
+ *	the unit shift.
  */
 
 static unsigned long sil680_seldev(struct ata_port *ap, struct ata_device *adev, int r)
@@ -81,7 +82,8 @@
  *	space for us.
  */
 
-static int sil680_cable_detect(struct ata_port *ap) {
+static int sil680_cable_detect(struct ata_port *ap)
+{
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	unsigned long addr = sil680_selreg(ap, 0);
 	u8 ata66;
@@ -93,7 +95,7 @@
 }
 
 /**
- *	sil680_set_piomode	-	set initial PIO mode data
+ *	sil680_set_piomode	-	set PIO mode data
  *	@ap: ATA interface
  *	@adev: ATA device
  *
@@ -104,8 +106,12 @@
 
 static void sil680_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
-	static u16 speed_p[5] = { 0x328A, 0x2283, 0x1104, 0x10C3, 0x10C1 };
-	static u16 speed_t[5] = { 0x328A, 0x2283, 0x1281, 0x10C3, 0x10C1 };
+	static const u16 speed_p[5] = {
+		0x328A, 0x2283, 0x1104, 0x10C3, 0x10C1
+	};
+	static const u16 speed_t[5] = {
+		0x328A, 0x2283, 0x1281, 0x10C3, 0x10C1
+	};
 
 	unsigned long tfaddr = sil680_selreg(ap, 0x02);
 	unsigned long addr = sil680_seldev(ap, adev, 0x04);
@@ -140,22 +146,23 @@
 }
 
 /**
- *	sil680_set_dmamode	-	set initial DMA mode data
+ *	sil680_set_dmamode	-	set DMA mode data
  *	@ap: ATA interface
  *	@adev: ATA device
  *
- *	Program the MWDMA/UDMA modes for the sil680 k
- *	chipset. The MWDMA mode values are pulled from a lookup table
+ *	Program the MWDMA/UDMA modes for the sil680 chipset.
+ *
+ *	The MWDMA mode values are pulled from a lookup table
  *	while the chipset uses mode number for UDMA.
  */
 
 static void sil680_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 {
-	static u8 ultra_table[2][7] = {
+	static const u8 ultra_table[2][7] = {
 		{ 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01, 0xFF },	/* 100MHz */
 		{ 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 },	/* 133Mhz */
 	};
-	static u16 dma_table[3] = { 0x2208, 0x10C2, 0x10C1 };
+	static const u16 dma_table[3] = { 0x2208, 0x10C2, 0x10C1 };
 
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	unsigned long ma = sil680_seldev(ap, adev, 0x08);
@@ -175,7 +182,7 @@
 	mode &= ~(0x03 << port_shift);
 
 	/* Extract scsc */
-	scsc = (scsc & 0x30) ? 1: 0;
+	scsc = (scsc & 0x30) ? 1 : 0;
 
 	if (adev->dma_mode >= XFER_UDMA_0) {
 		multi = 0x10C1;
@@ -248,7 +255,7 @@
 {
 	u8 tmpbyte	= 0;
 
-        /* FIXME: double check */
+	/* FIXME: double check */
 	pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE,
 			      pdev->revision ? 1 : 255);
 
@@ -266,22 +273,22 @@
 		*try_mmio = (tmpbyte & 1) || pci_resource_start(pdev, 5);
 #endif
 
-	switch(tmpbyte & 0x30) {
-		case 0x00:
-			/* 133 clock attempt to force it on */
-			pci_write_config_byte(pdev, 0x8A, tmpbyte|0x10);
-			break;
-		case 0x30:
-			/* if clocking is disabled */
-			/* 133 clock attempt to force it on */
-			pci_write_config_byte(pdev, 0x8A, tmpbyte & ~0x20);
-			break;
-		case 0x10:
-			/* 133 already */
-			break;
-		case 0x20:
-			/* BIOS set PCI x2 clocking */
-			break;
+	switch (tmpbyte & 0x30) {
+	case 0x00:
+		/* 133 clock attempt to force it on */
+		pci_write_config_byte(pdev, 0x8A, tmpbyte|0x10);
+		break;
+	case 0x30:
+		/* if clocking is disabled */
+		/* 133 clock attempt to force it on */
+		pci_write_config_byte(pdev, 0x8A, tmpbyte & ~0x20);
+		break;
+	case 0x10:
+		/* 133 already */
+		break;
+	case 0x20:
+		/* BIOS set PCI x2 clocking */
+		break;
 	}
 
 	pci_read_config_byte(pdev,   0x8A, &tmpbyte);
@@ -299,12 +306,19 @@
 	pci_write_config_dword(pdev, 0xB8, 0x43924392);
 	pci_write_config_dword(pdev, 0xBC, 0x40094009);
 
-	switch(tmpbyte & 0x30) {
-		case 0x00: printk(KERN_INFO "sil680: 100MHz clock.\n");break;
-		case 0x10: printk(KERN_INFO "sil680: 133MHz clock.\n");break;
-		case 0x20: printk(KERN_INFO "sil680: Using PCI clock.\n");break;
-		/* This last case is _NOT_ ok */
-		case 0x30: printk(KERN_ERR "sil680: Clock disabled ?\n");
+	switch (tmpbyte & 0x30) {
+	case 0x00:
+		printk(KERN_INFO "sil680: 100MHz clock.\n");
+		break;
+	case 0x10:
+		printk(KERN_INFO "sil680: 133MHz clock.\n");
+		break;
+	case 0x20:
+		printk(KERN_INFO "sil680: Using PCI clock.\n");
+		break;
+	/* This last case is _NOT_ ok */
+	case 0x30:
+		printk(KERN_ERR "sil680: Clock disabled ?\n");
 	}
 	return tmpbyte & 0x30;
 }
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_sis.c linux-libre-3.2-gnu/drivers/ata/pata_sis.c
--- linux-libre-3.1-gnu/drivers/ata/pata_sis.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_sis.c	2012-01-04 18:55:44.000000000 -0500
@@ -55,7 +55,7 @@
 	/* devid, subvendor, subdev */
 	{ 0x5513, 0x1043, 0x1107 },	/* ASUS A6K */
 	{ 0x5513, 0x1734, 0x105F },	/* FSC Amilo A1630 */
-	{ 0x5513, 0x1071, 0x8640 },     /* EasyNote K5305 */
+	{ 0x5513, 0x1071, 0x8640 },	/* EasyNote K5305 */
 	/* end marker */
 	{ 0, }
 };
@@ -76,7 +76,7 @@
 }
 
 /**
- *	sis_old_port_base		-	return PCI configuration base for dev
+ *	sis_old_port_base - return PCI configuration base for dev
  *	@adev: device
  *
  *	Returns the base of the PCI configuration registers for this port
@@ -85,11 +85,34 @@
 
 static int sis_old_port_base(struct ata_device *adev)
 {
-	return  0x40 + (4 * adev->link->ap->port_no) +  (2 * adev->devno);
+	return 0x40 + (4 * adev->link->ap->port_no) + (2 * adev->devno);
 }
 
 /**
- *	sis_133_cable_detect	-	check for 40/80 pin
+ *	sis_port_base - return PCI configuration base for dev
+ *	@adev: device
+ *
+ *	Returns the base of the PCI configuration registers for this port
+ *	number.
+ */
+
+static int sis_port_base(struct ata_device *adev)
+{
+	struct ata_port *ap = adev->link->ap;
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+	int port = 0x40;
+	u32 reg54;
+
+	/* If bit 30 is set then the registers are mapped at 0x70 not 0x40 */
+	pci_read_config_dword(pdev, 0x54, &reg54);
+	if (reg54 & 0x40000000)
+		port = 0x70;
+
+	return port + (8 * ap->port_no) + (4 * adev->devno);
+}
+
+/**
+ *	sis_133_cable_detect - check for 40/80 pin
  *	@ap: Port
  *	@deadline: deadline jiffies for the operation
  *
@@ -110,7 +133,7 @@
 }
 
 /**
- *	sis_66_cable_detect	-	check for 40/80 pin
+ *	sis_66_cable_detect - check for 40/80 pin
  *	@ap: Port
  *
  *	Perform cable detection on the UDMA66, UDMA100 and early UDMA133
@@ -132,7 +155,7 @@
 
 
 /**
- *	sis_pre_reset		-	probe begin
+ *	sis_pre_reset - probe begin
  *	@link: ATA link
  *	@deadline: deadline jiffies for the operation
  *
@@ -160,7 +183,7 @@
 
 
 /**
- *	sis_set_fifo	-	Set RWP fifo bits for this device
+ *	sis_set_fifo - Set RWP fifo bits for this device
  *	@ap: Port
  *	@adev: Device
  *
@@ -203,13 +226,13 @@
 
 static void sis_old_set_piomode (struct ata_port *ap, struct ata_device *adev)
 {
-	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	int port = sis_old_port_base(adev);
 	u8 t1, t2;
 	int speed = adev->pio_mode - XFER_PIO_0;
 
-	const u8 active[]   = { 0x00, 0x07, 0x04, 0x03, 0x01 };
-	const u8 recovery[] = { 0x00, 0x06, 0x04, 0x03, 0x03 };
+	static const u8 active[]   = { 0x00, 0x07, 0x04, 0x03, 0x01 };
+	static const u8 recovery[] = { 0x00, 0x06, 0x04, 0x03, 0x03 };
 
 	sis_set_fifo(ap, adev);
 
@@ -240,11 +263,11 @@
 
 static void sis_100_set_piomode (struct ata_port *ap, struct ata_device *adev)
 {
-	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	int port = sis_old_port_base(adev);
 	int speed = adev->pio_mode - XFER_PIO_0;
 
-	const u8 actrec[] = { 0x00, 0x67, 0x44, 0x33, 0x31 };
+	static const u8 actrec[] = { 0x00, 0x67, 0x44, 0x33, 0x31 };
 
 	sis_set_fifo(ap, adev);
 
@@ -265,20 +288,19 @@
 
 static void sis_133_set_piomode (struct ata_port *ap, struct ata_device *adev)
 {
-	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
-	int port = 0x40;
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+	int port;
 	u32 t1;
-	u32 reg54;
 	int speed = adev->pio_mode - XFER_PIO_0;
 
-	const u32 timing133[] = {
+	static const u32 timing133[] = {
 		0x28269000,	/* Recovery << 24 | Act << 16 | Ini << 12 */
 		0x0C266000,
 		0x04263000,
 		0x0C0A3000,
 		0x05093000
 	};
-	const u32 timing100[] = {
+	static const u32 timing100[] = {
 		0x1E1C6000,	/* Recovery << 24 | Act << 16 | Ini << 12 */
 		0x091C4000,
 		0x031C2000,
@@ -288,12 +310,7 @@
 
 	sis_set_fifo(ap, adev);
 
-	/* If bit 14 is set then the registers are mapped at 0x70 not 0x40 */
-	pci_read_config_dword(pdev, 0x54, &reg54);
-	if (reg54 & 0x40000000)
-		port = 0x70;
-	port += 8 * ap->port_no +  4 * adev->devno;
-
+	port = sis_port_base(adev);
 	pci_read_config_dword(pdev, port, &t1);
 	t1 &= 0xC0C00FFF;	/* Mask out timing */
 
@@ -319,13 +336,13 @@
 
 static void sis_old_set_dmamode (struct ata_port *ap, struct ata_device *adev)
 {
-	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	int speed = adev->dma_mode - XFER_MW_DMA_0;
 	int drive_pci = sis_old_port_base(adev);
 	u16 timing;
 
-	const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 };
-	const u16 udma_bits[]  = { 0xE000, 0xC000, 0xA000 };
+	static const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 };
+	static const u16 udma_bits[]  = { 0xE000, 0xC000, 0xA000 };
 
 	pci_read_config_word(pdev, drive_pci, &timing);
 
@@ -358,14 +375,14 @@
 
 static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev)
 {
-	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	int speed = adev->dma_mode - XFER_MW_DMA_0;
 	int drive_pci = sis_old_port_base(adev);
 	u16 timing;
 
 	/* MWDMA 0-2 and UDMA 0-5 */
-	const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 };
-	const u16 udma_bits[]  = { 0xF000, 0xD000, 0xB000, 0xA000, 0x9000, 0x8000 };
+	static const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 };
+	static const u16 udma_bits[]  = { 0xF000, 0xD000, 0xB000, 0xA000, 0x9000, 0x8000 };
 
 	pci_read_config_word(pdev, drive_pci, &timing);
 
@@ -397,12 +414,12 @@
 
 static void sis_100_set_dmamode (struct ata_port *ap, struct ata_device *adev)
 {
-	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	int speed = adev->dma_mode - XFER_MW_DMA_0;
 	int drive_pci = sis_old_port_base(adev);
 	u8 timing;
 
-	const u8 udma_bits[]  = { 0x8B, 0x87, 0x85, 0x83, 0x82, 0x81};
+	static const u8 udma_bits[]  = { 0x8B, 0x87, 0x85, 0x83, 0x82, 0x81};
 
 	pci_read_config_byte(pdev, drive_pci + 1, &timing);
 
@@ -431,7 +448,7 @@
 
 static void sis_133_early_set_dmamode (struct ata_port *ap, struct ata_device *adev)
 {
-	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	int speed = adev->dma_mode - XFER_MW_DMA_0;
 	int drive_pci = sis_old_port_base(adev);
 	u8 timing;
@@ -464,32 +481,34 @@
 
 static void sis_133_set_dmamode (struct ata_port *ap, struct ata_device *adev)
 {
-	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
-	int speed = adev->dma_mode - XFER_MW_DMA_0;
-	int port = 0x40;
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+	int port;
 	u32 t1;
-	u32 reg54;
-
-	/* bits 4- cycle time 8 - cvs time */
-	static const u32 timing_u100[] = { 0x6B0, 0x470, 0x350, 0x140, 0x120, 0x110, 0x000 };
-	static const u32 timing_u133[] = { 0x9F0, 0x6A0, 0x470, 0x250, 0x230, 0x220, 0x210 };
-
-	/* If bit 14 is set then the registers are mapped at 0x70 not 0x40 */
-	pci_read_config_dword(pdev, 0x54, &reg54);
-	if (reg54 & 0x40000000)
-		port = 0x70;
-	port += (8 * ap->port_no) +  (4 * adev->devno);
 
+	port = sis_port_base(adev);
 	pci_read_config_dword(pdev, port, &t1);
 
 	if (adev->dma_mode < XFER_UDMA_0) {
+		/* Recovery << 24 | Act << 16 | Ini << 12, like PIO modes */
+		static const u32 timing_u100[] = { 0x19154000, 0x06072000, 0x04062000 };
+		static const u32 timing_u133[] = { 0x221C6000, 0x0C0A3000, 0x05093000 };
+		int speed = adev->dma_mode - XFER_MW_DMA_0;
+
+		t1 &= 0xC0C00FFF;
+		/* disable UDMA */
 		t1 &= ~0x00000004;
-		/* FIXME: need data sheet to add MWDMA here. Also lacking on
-		   ide/pci driver */
+		if (t1 & 0x08)
+			t1 |= timing_u133[speed];
+		else
+			t1 |= timing_u100[speed];
 	} else {
-		speed = adev->dma_mode - XFER_UDMA_0;
-		/* if & 8 no UDMA133 - need info for ... */
+		/* bits 4- cycle time 8 - cvs time */
+		static const u32 timing_u100[] = { 0x6B0, 0x470, 0x350, 0x140, 0x120, 0x110, 0x000 };
+		static const u32 timing_u133[] = { 0x9F0, 0x6A0, 0x470, 0x250, 0x230, 0x220, 0x210 };
+		int speed = adev->dma_mode - XFER_UDMA_0;
+
 		t1 &= ~0x00000FF0;
+		/* enable UDMA */
 		t1 |= 0x00000004;
 		if (t1 & 0x08)
 			t1 |= timing_u133[speed];
@@ -499,6 +518,27 @@
 	pci_write_config_dword(pdev, port, t1);
 }
 
+/**
+ *	sis_133_mode_filter - mode selection filter
+ *	@adev: ATA device
+ *
+ *	Block UDMA6 on devices that do not support it.
+ */
+
+static unsigned long sis_133_mode_filter(struct ata_device *adev, unsigned long mask)
+{
+	struct ata_port *ap = adev->link->ap;
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+	int port = sis_port_base(adev);
+	u32 t1;
+
+	pci_read_config_dword(pdev, port, &t1);
+	/* if ATA133 is disabled, mask it out */
+	if (!(t1 & 0x08))
+		mask &= ~(0xC0 << ATA_SHIFT_UDMA);
+	return mask;
+}
+
 static struct scsi_host_template sis_sht = {
 	ATA_BMDMA_SHT(DRV_NAME),
 };
@@ -520,6 +560,7 @@
 	.set_piomode		= sis_133_set_piomode,
 	.set_dmamode		= sis_133_set_dmamode,
 	.cable_detect		= sis_133_cable_detect,
+	.mode_filter		= sis_133_mode_filter,
 };
 
 static struct ata_port_operations sis_133_early_ops = {
@@ -588,7 +629,7 @@
 static const struct ata_port_info sis_info133 = {
 	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= ATA_PIO4,
-	/* No MWDMA */
+	.mwdma_mask	= ATA_MWDMA2,
 	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &sis_133_ops,
 };
@@ -669,7 +710,7 @@
  *	@pdev: PCI device to register
  *	@ent: Entry in sis_pci_tbl matching with @pdev
  *
- *	Called from kernel PCI layer.  We probe for combined mode (sigh),
+ *	Called from kernel PCI layer. We probe for combined mode (sigh),
  *	and then hand over control to libata, for it to do the rest.
  *
  *	LOCKING:
@@ -769,17 +810,20 @@
 
 		switch(trueid) {
 		case 0x5518:	/* SIS 962/963 */
+			dev_info(&pdev->dev,
+				 "SiS 962/963 MuTIOL IDE UDMA133 controller\n");
 			chipset = &sis133;
 			if ((idemisc & 0x40000000) == 0) {
 				pci_write_config_dword(pdev, 0x54, idemisc | 0x40000000);
-				printk(KERN_INFO "SIS5513: Switching to 5513 register mapping\n");
+				dev_info(&pdev->dev,
+					 "Switching to 5513 register mapping\n");
 			}
 			break;
 		case 0x0180:	/* SIS 965/965L */
-			chipset =  &sis133;
+			chipset = &sis133;
 			break;
 		case 0x1180:	/* SIS 966/966L */
-			chipset =  &sis133;
+			chipset = &sis133;
 			break;
 		}
 	}
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_sl82c105.c linux-libre-3.2-gnu/drivers/ata/pata_sl82c105.c
--- linux-libre-3.1-gnu/drivers/ata/pata_sl82c105.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_sl82c105.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 /*
  * pata_sl82c105.c 	- SL82C105 PATA for new ATA layer
  *			  (C) 2005 Red Hat Inc
+ *			  (C) 2011 Bartlomiej Zolnierkiewicz
  *
  * Based in part on linux/drivers/ide/pci/sl82c105.c
  * 		SL82C105/Winbond 553 IDE driver
@@ -289,6 +290,14 @@
 	return bridge->revision;
 }
 
+static void sl82c105_fixup(struct pci_dev *pdev)
+{
+	u32 val;
+
+	pci_read_config_dword(pdev, 0x40, &val);
+	val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
+	pci_write_config_dword(pdev, 0x40, val);
+}
 
 static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
@@ -306,7 +315,6 @@
 	/* for now use only the first port */
 	const struct ata_port_info *ppi[] = { &info_early,
 					       NULL };
-	u32 val;
 	int rev;
 	int rc;
 
@@ -325,13 +333,28 @@
 	else
 		ppi[0] = &info_dma;
 
-	pci_read_config_dword(dev, 0x40, &val);
-	val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
-	pci_write_config_dword(dev, 0x40, val);
+	sl82c105_fixup(dev);
 
 	return ata_pci_bmdma_init_one(dev, ppi, &sl82c105_sht, NULL, 0);
 }
 
+#ifdef CONFIG_PM
+static int sl82c105_reinit_one(struct pci_dev *pdev)
+{
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	int rc;
+
+	rc = ata_pci_device_do_resume(pdev);
+	if (rc)
+		return rc;
+
+	sl82c105_fixup(pdev);
+
+	ata_host_resume(host);
+	return 0;
+}
+#endif
+
 static const struct pci_device_id sl82c105[] = {
 	{ PCI_VDEVICE(WINBOND, PCI_DEVICE_ID_WINBOND_82C105), },
 
@@ -342,7 +365,11 @@
 	.name 		= DRV_NAME,
 	.id_table	= sl82c105,
 	.probe 		= sl82c105_init_one,
-	.remove		= ata_pci_remove_one
+	.remove		= ata_pci_remove_one,
+#ifdef CONFIG_PM
+	.suspend	= ata_pci_device_suspend,
+	.resume		= sl82c105_reinit_one,
+#endif
 };
 
 static int __init sl82c105_init(void)
diff -druN linux-libre-3.1-gnu/drivers/ata/pata_via.c linux-libre-3.2-gnu/drivers/ata/pata_via.c
--- linux-libre-3.1-gnu/drivers/ata/pata_via.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/pata_via.c	2012-01-04 18:55:44.000000000 -0500
@@ -509,6 +509,27 @@
 	}
 }
 
+static void via_fixup(struct pci_dev *pdev, const struct via_isa_bridge *config)
+{
+	u32 timing;
+
+	/* Initialise the FIFO for the enabled channels. */
+	via_config_fifo(pdev, config->flags);
+
+	if (config->udma_mask == ATA_UDMA4) {
+		/* The 66 MHz devices require we enable the clock */
+		pci_read_config_dword(pdev, 0x50, &timing);
+		timing |= 0x80008;
+		pci_write_config_dword(pdev, 0x50, timing);
+	}
+	if (config->flags & VIA_BAD_CLK66) {
+		/* Disable the 66MHz clock on problem devices */
+		pci_read_config_dword(pdev, 0x50, &timing);
+		timing &= ~0x80008;
+		pci_write_config_dword(pdev, 0x50, timing);
+	}
+}
+
 /**
  *	via_init_one		-	discovery callback
  *	@pdev: PCI device
@@ -570,7 +591,6 @@
 	struct pci_dev *isa;
 	const struct via_isa_bridge *config;
 	u8 enable;
-	u32 timing;
 	unsigned long flags = id->driver_data;
 	int rc;
 
@@ -609,9 +629,6 @@
 			return -ENODEV;
 	}
 
-	/* Initialise the FIFO for the enabled channels. */
-	via_config_fifo(pdev, config->flags);
-
 	/* Clock set up */
 	switch (config->udma_mask) {
 	case 0x00:
@@ -637,12 +654,7 @@
 		return -ENODEV;
  	}
 
-	if (config->flags & VIA_BAD_CLK66) {
-		/* Disable the 66MHz clock on problem devices */
-		pci_read_config_dword(pdev, 0x50, &timing);
-		timing &= ~0x80008;
-		pci_write_config_dword(pdev, 0x50, timing);
-	}
+	via_fixup(pdev, config);
 
 	/* We have established the device type, now fire it up */
 	return ata_pci_bmdma_init_one(pdev, ppi, &via_sht, (void *)config, 0);
@@ -661,29 +673,14 @@
 
 static int via_reinit_one(struct pci_dev *pdev)
 {
-	u32 timing;
 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	const struct via_isa_bridge *config = host->private_data;
 	int rc;
 
 	rc = ata_pci_device_do_resume(pdev);
 	if (rc)
 		return rc;
 
-	via_config_fifo(pdev, config->flags);
-
-	if (config->udma_mask == ATA_UDMA4) {
-		/* The 66 MHz devices require we enable the clock */
-		pci_read_config_dword(pdev, 0x50, &timing);
-		timing |= 0x80008;
-		pci_write_config_dword(pdev, 0x50, timing);
-	}
-	if (config->flags & VIA_BAD_CLK66) {
-		/* Disable the 66MHz clock on problem devices */
-		pci_read_config_dword(pdev, 0x50, &timing);
-		timing &= ~0x80008;
-		pci_write_config_dword(pdev, 0x50, timing);
-	}
+	via_fixup(pdev, host->private_data);
 
 	ata_host_resume(host);
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/ata/sata_mv.c linux-libre-3.2-gnu/drivers/ata/sata_mv.c
--- linux-libre-3.1-gnu/drivers/ata/sata_mv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/sata_mv.c	2012-01-04 18:55:44.000000000 -0500
@@ -4087,8 +4087,11 @@
 	dev_info(&pdev->dev, "slots %u ports %d\n",
 		 (unsigned)MV_MAX_Q_DEPTH, host->n_ports);
 
-	return ata_host_activate(host, platform_get_irq(pdev, 0), mv_interrupt,
-				 IRQF_SHARED, &mv6_sht);
+	rc = ata_host_activate(host, platform_get_irq(pdev, 0), mv_interrupt,
+			       IRQF_SHARED, &mv6_sht);
+	if (!rc)
+		return 0;
+
 err:
 #if defined(CONFIG_HAVE_CLK)
 	if (!IS_ERR(hpriv->clk)) {
@@ -4110,8 +4113,7 @@
  */
 static int __devexit mv_platform_remove(struct platform_device *pdev)
 {
-	struct device *dev = &pdev->dev;
-	struct ata_host *host = dev_get_drvdata(dev);
+	struct ata_host *host = platform_get_drvdata(pdev);
 #if defined(CONFIG_HAVE_CLK)
 	struct mv_host_priv *hpriv = host->private_data;
 #endif
@@ -4129,7 +4131,7 @@
 #ifdef CONFIG_PM
 static int mv_platform_suspend(struct platform_device *pdev, pm_message_t state)
 {
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct ata_host *host = platform_get_drvdata(pdev);
 	if (host)
 		return ata_host_suspend(host, state);
 	else
@@ -4138,7 +4140,7 @@
 
 static int mv_platform_resume(struct platform_device *pdev)
 {
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct ata_host *host = platform_get_drvdata(pdev);
 	int ret;
 
 	if (host) {
@@ -4353,7 +4355,7 @@
 #ifdef CONFIG_PM
 static int mv_pci_device_resume(struct pci_dev *pdev)
 {
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct ata_host *host = pci_get_drvdata(pdev);
 	int rc;
 
 	rc = ata_pci_device_do_resume(pdev);
diff -druN linux-libre-3.1-gnu/drivers/ata/sata_sil24.c linux-libre-3.2-gnu/drivers/ata/sata_sil24.c
--- linux-libre-3.1-gnu/drivers/ata/sata_sil24.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/sata_sil24.c	2012-01-04 18:55:44.000000000 -0500
@@ -268,7 +268,7 @@
 	struct sil24_atapi_block atapi;
 };
 
-static struct sil24_cerr_info {
+static const struct sil24_cerr_info {
 	unsigned int err_mask, action;
 	const char *desc;
 } sil24_cerr_db[] = {
@@ -1019,7 +1019,7 @@
 
 	/* deal with command error */
 	if (irq_stat & PORT_IRQ_ERROR) {
-		struct sil24_cerr_info *ci = NULL;
+		const struct sil24_cerr_info *ci = NULL;
 		unsigned int err_mask = 0, action = 0;
 		u32 context, cerr;
 		int pmp;
diff -druN linux-libre-3.1-gnu/drivers/ata/sata_sis.c linux-libre-3.2-gnu/drivers/ata/sata_sis.c
--- linux-libre-3.1-gnu/drivers/ata/sata_sis.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ata/sata_sis.c	2012-01-04 18:55:44.000000000 -0500
@@ -104,7 +104,7 @@
 };
 
 MODULE_AUTHOR("Uwe Koziolek");
-MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller");
+MODULE_DESCRIPTION("low-level driver for Silicon Integrated Systems SATA controller");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, sis_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
diff -druN linux-libre-3.1-gnu/drivers/atm/eni.c linux-libre-3.2-gnu/drivers/atm/eni.c
--- linux-libre-3.1-gnu/drivers/atm/eni.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/atm/eni.c	2012-01-04 18:55:44.000000000 -0500
@@ -1134,8 +1134,9 @@
 				    skb_headlen(skb));
 			else
 				put_dma(tx->index,eni_dev->dma,&j,(unsigned long)
-				    skb_shinfo(skb)->frags[i].page + skb_shinfo(skb)->frags[i].page_offset,
-				    skb_shinfo(skb)->frags[i].size);
+				    skb_frag_page(&skb_shinfo(skb)->frags[i]) +
+					skb_shinfo(skb)->frags[i].page_offset,
+				    skb_frag_size(&skb_shinfo(skb)->frags[i]));
 	}
 	if (skb->len & 3)
 		put_dma(tx->index,eni_dev->dma,&j,zeroes,4-(skb->len & 3));
diff -druN linux-libre-3.1-gnu/drivers/atm/idt77252.c linux-libre-3.2-gnu/drivers/atm/idt77252.c
--- linux-libre-3.1-gnu/drivers/atm/idt77252.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/atm/idt77252.c	2012-01-04 18:55:44.000000000 -0500
@@ -3416,27 +3416,28 @@
 
 	size = sizeof(struct vc_map *) * card->tct_size;
 	IPRINTK("%s: allocate %d byte for VC map.\n", card->name, size);
-	if (NULL == (card->vcs = vmalloc(size))) {
+	card->vcs = vzalloc(size);
+	if (!card->vcs) {
 		printk("%s: memory allocation failure.\n", card->name);
 		deinit_card(card);
 		return -1;
 	}
-	memset(card->vcs, 0, size);
 
 	size = sizeof(struct vc_map *) * card->scd_size;
 	IPRINTK("%s: allocate %d byte for SCD to VC mapping.\n",
 	        card->name, size);
-	if (NULL == (card->scd2vc = vmalloc(size))) {
+	card->scd2vc = vzalloc(size);
+	if (!card->scd2vc) {
 		printk("%s: memory allocation failure.\n", card->name);
 		deinit_card(card);
 		return -1;
 	}
-	memset(card->scd2vc, 0, size);
 
 	size = sizeof(struct tst_info) * (card->tst_size - 2);
 	IPRINTK("%s: allocate %d byte for TST to VC mapping.\n",
 		card->name, size);
-	if (NULL == (card->soft_tst = vmalloc(size))) {
+	card->soft_tst = vmalloc(size);
+	if (!card->soft_tst) {
 		printk("%s: memory allocation failure.\n", card->name);
 		deinit_card(card);
 		return -1;
diff -druN linux-libre-3.1-gnu/drivers/atm/iphase.c linux-libre-3.2-gnu/drivers/atm/iphase.c
--- linux-libre-3.1-gnu/drivers/atm/iphase.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/atm/iphase.c	2012-01-04 18:55:44.000000000 -0500
@@ -818,127 +818,152 @@
 
 }
 
-static void IaFrontEndIntr(IADEV *iadev) {
-  volatile IA_SUNI *suni;
-  volatile ia_mb25_t *mb25;
-  volatile suni_pm7345_t *suni_pm7345;
+static u32 ia_phy_read32(struct iadev_priv *ia, unsigned int reg)
+{
+	return readl(ia->phy + (reg >> 2));
+}
 
-  if(iadev->phy_type & FE_25MBIT_PHY) {
-     mb25 = (ia_mb25_t*)iadev->phy;
-     iadev->carrier_detect =  Boolean(mb25->mb25_intr_status & MB25_IS_GSB);
-  } else if (iadev->phy_type & FE_DS3_PHY) {
-     suni_pm7345 = (suni_pm7345_t *)iadev->phy;
-     /* clear FRMR interrupts */
-     (void) suni_pm7345->suni_ds3_frm_intr_stat; 
-     iadev->carrier_detect =  
-           Boolean(!(suni_pm7345->suni_ds3_frm_stat & SUNI_DS3_LOSV));
-  } else if (iadev->phy_type & FE_E3_PHY ) {
-     suni_pm7345 = (suni_pm7345_t *)iadev->phy;
-     (void) suni_pm7345->suni_e3_frm_maint_intr_ind;
-     iadev->carrier_detect =
-           Boolean(!(suni_pm7345->suni_e3_frm_fram_intr_ind_stat&SUNI_E3_LOS));
-  }
-  else { 
-     suni = (IA_SUNI *)iadev->phy;
-     (void) suni->suni_rsop_status;
-     iadev->carrier_detect = Boolean(!(suni->suni_rsop_status & SUNI_LOSV));
-  }
-  if (iadev->carrier_detect)
-    printk("IA: SUNI carrier detected\n");
-  else
-    printk("IA: SUNI carrier lost signal\n"); 
-  return;
+static void ia_phy_write32(struct iadev_priv *ia, unsigned int reg, u32 val)
+{
+	writel(val, ia->phy + (reg >> 2));
 }
 
-static void ia_mb25_init (IADEV *iadev)
+static void ia_frontend_intr(struct iadev_priv *iadev)
+{
+	u32 status;
+
+	if (iadev->phy_type & FE_25MBIT_PHY) {
+		status = ia_phy_read32(iadev, MB25_INTR_STATUS);
+		iadev->carrier_detect = (status & MB25_IS_GSB) ? 1 : 0;
+	} else if (iadev->phy_type & FE_DS3_PHY) {
+		ia_phy_read32(iadev, SUNI_DS3_FRM_INTR_STAT);
+		status = ia_phy_read32(iadev, SUNI_DS3_FRM_STAT);
+		iadev->carrier_detect = (status & SUNI_DS3_LOSV) ? 0 : 1;
+	} else if (iadev->phy_type & FE_E3_PHY) {
+		ia_phy_read32(iadev, SUNI_E3_FRM_MAINT_INTR_IND);
+		status = ia_phy_read32(iadev, SUNI_E3_FRM_FRAM_INTR_IND_STAT);
+		iadev->carrier_detect = (status & SUNI_E3_LOS) ? 0 : 1;
+	} else {
+		status = ia_phy_read32(iadev, SUNI_RSOP_STATUS);
+		iadev->carrier_detect = (status & SUNI_LOSV) ? 0 : 1;
+	}
+
+	printk(KERN_INFO "IA: SUNI carrier %s\n",
+		iadev->carrier_detect ? "detected" : "lost signal");
+}
+
+static void ia_mb25_init(struct iadev_priv *iadev)
 {
-   volatile ia_mb25_t  *mb25 = (ia_mb25_t*)iadev->phy;
 #if 0
    mb25->mb25_master_ctrl = MB25_MC_DRIC | MB25_MC_DREC | MB25_MC_ENABLED;
 #endif
-   mb25->mb25_master_ctrl = MB25_MC_DRIC | MB25_MC_DREC;
-   mb25->mb25_diag_control = 0;
-   /*
-    * Initialize carrier detect state
-    */
-   iadev->carrier_detect =  Boolean(mb25->mb25_intr_status & MB25_IS_GSB);
-   return;
-}                   
+	ia_phy_write32(iadev, MB25_MASTER_CTRL, MB25_MC_DRIC | MB25_MC_DREC);
+	ia_phy_write32(iadev, MB25_DIAG_CONTROL, 0);
 
-static void ia_suni_pm7345_init (IADEV *iadev)
+	iadev->carrier_detect =
+		(ia_phy_read32(iadev, MB25_INTR_STATUS) & MB25_IS_GSB) ? 1 : 0;
+}
+
+struct ia_reg {
+	u16 reg;
+	u16 val;
+};
+
+static void ia_phy_write(struct iadev_priv *iadev,
+			 const struct ia_reg *regs, int len)
 {
-   volatile suni_pm7345_t *suni_pm7345 = (suni_pm7345_t *)iadev->phy;
-   if (iadev->phy_type & FE_DS3_PHY)
-   {
-      iadev->carrier_detect = 
-          Boolean(!(suni_pm7345->suni_ds3_frm_stat & SUNI_DS3_LOSV)); 
-      suni_pm7345->suni_ds3_frm_intr_enbl = 0x17;
-      suni_pm7345->suni_ds3_frm_cfg = 1;
-      suni_pm7345->suni_ds3_tran_cfg = 1;
-      suni_pm7345->suni_config = 0;
-      suni_pm7345->suni_splr_cfg = 0;
-      suni_pm7345->suni_splt_cfg = 0;
-   }
-   else 
-   {
-      iadev->carrier_detect = 
-          Boolean(!(suni_pm7345->suni_e3_frm_fram_intr_ind_stat & SUNI_E3_LOS));
-      suni_pm7345->suni_e3_frm_fram_options = 0x4;
-      suni_pm7345->suni_e3_frm_maint_options = 0x20;
-      suni_pm7345->suni_e3_frm_fram_intr_enbl = 0x1d;
-      suni_pm7345->suni_e3_frm_maint_intr_enbl = 0x30;
-      suni_pm7345->suni_e3_tran_stat_diag_options = 0x0;
-      suni_pm7345->suni_e3_tran_fram_options = 0x1;
-      suni_pm7345->suni_config = SUNI_PM7345_E3ENBL;
-      suni_pm7345->suni_splr_cfg = 0x41;
-      suni_pm7345->suni_splt_cfg = 0x41;
-   } 
-   /*
-    * Enable RSOP loss of signal interrupt.
-    */
-   suni_pm7345->suni_intr_enbl = 0x28;
- 
-   /*
-    * Clear error counters
-    */
-   suni_pm7345->suni_id_reset = 0;
+	while (len--) {
+		ia_phy_write32(iadev, regs->reg, regs->val);
+		regs++;
+	}
+}
 
-   /*
-    * Clear "PMCTST" in master test register.
-    */
-   suni_pm7345->suni_master_test = 0;
+static void ia_suni_pm7345_init_ds3(struct iadev_priv *iadev)
+{
+	static const struct ia_reg suni_ds3_init [] = {
+		{ SUNI_DS3_FRM_INTR_ENBL,	0x17 },
+		{ SUNI_DS3_FRM_CFG,		0x01 },
+		{ SUNI_DS3_TRAN_CFG,		0x01 },
+		{ SUNI_CONFIG,			0 },
+		{ SUNI_SPLR_CFG,		0 },
+		{ SUNI_SPLT_CFG,		0 }
+	};
+	u32 status;
 
-   suni_pm7345->suni_rxcp_ctrl = 0x2c;
-   suni_pm7345->suni_rxcp_fctrl = 0x81;
- 
-   suni_pm7345->suni_rxcp_idle_pat_h1 =
-   	suni_pm7345->suni_rxcp_idle_pat_h2 =
-   	suni_pm7345->suni_rxcp_idle_pat_h3 = 0;
-   suni_pm7345->suni_rxcp_idle_pat_h4 = 1;
- 
-   suni_pm7345->suni_rxcp_idle_mask_h1 = 0xff;
-   suni_pm7345->suni_rxcp_idle_mask_h2 = 0xff;
-   suni_pm7345->suni_rxcp_idle_mask_h3 = 0xff;
-   suni_pm7345->suni_rxcp_idle_mask_h4 = 0xfe;
- 
-   suni_pm7345->suni_rxcp_cell_pat_h1 =
-   	suni_pm7345->suni_rxcp_cell_pat_h2 =
-   	suni_pm7345->suni_rxcp_cell_pat_h3 = 0;
-   suni_pm7345->suni_rxcp_cell_pat_h4 = 1;
- 
-   suni_pm7345->suni_rxcp_cell_mask_h1 =
-   	suni_pm7345->suni_rxcp_cell_mask_h2 =
-   	suni_pm7345->suni_rxcp_cell_mask_h3 =
-   	suni_pm7345->suni_rxcp_cell_mask_h4 = 0xff;
- 
-   suni_pm7345->suni_txcp_ctrl = 0xa4;
-   suni_pm7345->suni_txcp_intr_en_sts = 0x10;
-   suni_pm7345->suni_txcp_idle_pat_h5 = 0x55;
- 
-   suni_pm7345->suni_config &= ~(SUNI_PM7345_LLB |
-                                 SUNI_PM7345_CLB |
-                                 SUNI_PM7345_DLB |
-                                  SUNI_PM7345_PLB);
+	status = ia_phy_read32(iadev, SUNI_DS3_FRM_STAT);
+	iadev->carrier_detect = (status & SUNI_DS3_LOSV) ? 0 : 1;
+
+	ia_phy_write(iadev, suni_ds3_init, ARRAY_SIZE(suni_ds3_init));
+}
+
+static void ia_suni_pm7345_init_e3(struct iadev_priv *iadev)
+{
+	static const struct ia_reg suni_e3_init [] = {
+		{ SUNI_E3_FRM_FRAM_OPTIONS,		0x04 },
+		{ SUNI_E3_FRM_MAINT_OPTIONS,		0x20 },
+		{ SUNI_E3_FRM_FRAM_INTR_ENBL,		0x1d },
+		{ SUNI_E3_FRM_MAINT_INTR_ENBL,		0x30 },
+		{ SUNI_E3_TRAN_STAT_DIAG_OPTIONS,	0 },
+		{ SUNI_E3_TRAN_FRAM_OPTIONS,		0x01 },
+		{ SUNI_CONFIG,				SUNI_PM7345_E3ENBL },
+		{ SUNI_SPLR_CFG,			0x41 },
+		{ SUNI_SPLT_CFG,			0x41 }
+	};
+	u32 status;
+
+	status = ia_phy_read32(iadev, SUNI_E3_FRM_FRAM_INTR_IND_STAT);
+	iadev->carrier_detect = (status & SUNI_E3_LOS) ? 0 : 1;
+	ia_phy_write(iadev, suni_e3_init, ARRAY_SIZE(suni_e3_init));
+}
+
+static void ia_suni_pm7345_init(struct iadev_priv *iadev)
+{
+	static const struct ia_reg suni_init [] = {
+		/* Enable RSOP loss of signal interrupt. */
+		{ SUNI_INTR_ENBL,		0x28 },
+		/* Clear error counters. */
+		{ SUNI_ID_RESET,		0 },
+		/* Clear "PMCTST" in master test register. */
+		{ SUNI_MASTER_TEST,		0 },
+
+		{ SUNI_RXCP_CTRL,		0x2c },
+		{ SUNI_RXCP_FCTRL,		0x81 },
+
+		{ SUNI_RXCP_IDLE_PAT_H1,	0 },
+		{ SUNI_RXCP_IDLE_PAT_H2,	0 },
+		{ SUNI_RXCP_IDLE_PAT_H3,	0 },
+		{ SUNI_RXCP_IDLE_PAT_H4,	0x01 },
+
+		{ SUNI_RXCP_IDLE_MASK_H1,	0xff },
+		{ SUNI_RXCP_IDLE_MASK_H2,	0xff },
+		{ SUNI_RXCP_IDLE_MASK_H3,	0xff },
+		{ SUNI_RXCP_IDLE_MASK_H4,	0xfe },
+
+		{ SUNI_RXCP_CELL_PAT_H1,	0 },
+		{ SUNI_RXCP_CELL_PAT_H2,	0 },
+		{ SUNI_RXCP_CELL_PAT_H3,	0 },
+		{ SUNI_RXCP_CELL_PAT_H4,	0x01 },
+
+		{ SUNI_RXCP_CELL_MASK_H1,	0xff },
+		{ SUNI_RXCP_CELL_MASK_H2,	0xff },
+		{ SUNI_RXCP_CELL_MASK_H3,	0xff },
+		{ SUNI_RXCP_CELL_MASK_H4,	0xff },
+
+		{ SUNI_TXCP_CTRL,		0xa4 },
+		{ SUNI_TXCP_INTR_EN_STS,	0x10 },
+		{ SUNI_TXCP_IDLE_PAT_H5,	0x55 }
+	};
+
+	if (iadev->phy_type & FE_DS3_PHY)
+		ia_suni_pm7345_init_ds3(iadev);
+	else
+		ia_suni_pm7345_init_e3(iadev);
+
+	ia_phy_write(iadev, suni_init, ARRAY_SIZE(suni_init));
+
+	ia_phy_write32(iadev, SUNI_CONFIG, ia_phy_read32(iadev, SUNI_CONFIG) &
+		~(SUNI_PM7345_LLB | SUNI_PM7345_CLB |
+		  SUNI_PM7345_DLB | SUNI_PM7345_PLB));
 #ifdef __SNMP__
    suni_pm7345->suni_rxcp_intr_en_sts |= SUNI_OOCDE;
 #endif /* __SNMP__ */
@@ -1425,10 +1450,10 @@
 	       iadev->dma + IPHASE5575_RX_LIST_ADDR);  
 	IF_INIT(printk("Tx Dle list addr: 0x%p value: 0x%0x\n",
                       iadev->dma+IPHASE5575_TX_LIST_ADDR,
-                      *(u32*)(iadev->dma+IPHASE5575_TX_LIST_ADDR));  
+                      readl(iadev->dma + IPHASE5575_TX_LIST_ADDR));
 	printk("Rx Dle list addr: 0x%p value: 0x%0x\n",
                       iadev->dma+IPHASE5575_RX_LIST_ADDR,
-                      *(u32*)(iadev->dma+IPHASE5575_RX_LIST_ADDR));)  
+                      readl(iadev->dma + IPHASE5575_RX_LIST_ADDR));)
   
 	writew(0xffff, iadev->reass_reg+REASS_MASK_REG);  
 	writew(0, iadev->reass_reg+MODE_REG);  
@@ -2208,7 +2233,7 @@
 	if (status & STAT_DLERINT)  
 	{  
 	   /* Clear this bit by writing a 1 to it. */  
-	   *(u_int *)(iadev->reg+IPHASE5575_BUS_STATUS_REG) = STAT_DLERINT;
+	   writel(STAT_DLERINT, iadev->reg + IPHASE5575_BUS_STATUS_REG);
 	   rx_dle_intr(dev);  
 	}  
 	if (status & STAT_SEGINT)  
@@ -2219,13 +2244,13 @@
 	}  
 	if (status & STAT_DLETINT)  
 	{  
-	   *(u_int *)(iadev->reg+IPHASE5575_BUS_STATUS_REG) = STAT_DLETINT;  
+	   writel(STAT_DLETINT, iadev->reg + IPHASE5575_BUS_STATUS_REG);
 	   tx_dle_intr(dev);  
 	}  
 	if (status & (STAT_FEINT | STAT_ERRINT | STAT_MARKINT))  
 	{  
            if (status & STAT_FEINT) 
-               IaFrontEndIntr(iadev);
+               ia_frontend_intr(iadev);
 	}  
    }
    return IRQ_RETVAL(handled);
@@ -2556,7 +2581,7 @@
 				goto err_free_rx;
 		}
 		/* Get iadev->carrier_detect status */
-		IaFrontEndIntr(iadev);
+		ia_frontend_intr(iadev);
 	}
 	return 0;
 
@@ -2827,7 +2852,7 @@
 
          case 0xb:
 	    if (!capable(CAP_NET_ADMIN)) return -EPERM;
-            IaFrontEndIntr(iadev);
+            ia_frontend_intr(iadev);
             break;
          case 0xa:
 	    if (!capable(CAP_NET_ADMIN)) return -EPERM;
diff -druN linux-libre-3.1-gnu/drivers/atm/iphase.h linux-libre-3.2-gnu/drivers/atm/iphase.h
--- linux-libre-3.1-gnu/drivers/atm/iphase.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/atm/iphase.h	2012-01-04 18:55:44.000000000 -0500
@@ -889,79 +889,71 @@
 } IARTN_Q;
 
 #define SUNI_LOSV   	0x04
-typedef struct {
-        u32   suni_master_reset;      /* SUNI Master Reset and Identity     */
-        u32   suni_master_config;     /* SUNI Master Configuration          */
-        u32   suni_master_intr_stat;  /* SUNI Master Interrupt Status       */
-        u32   suni_reserved1;         /* Reserved                           */
-        u32   suni_master_clk_monitor;/* SUNI Master Clock Monitor          */
-        u32   suni_master_control;    /* SUNI Master Clock Monitor          */
-        u32   suni_reserved2[10];     /* Reserved                           */
-
-        u32   suni_rsop_control;      /* RSOP Control/Interrupt Enable      */
-        u32   suni_rsop_status;       /* RSOP Status/Interrupt States       */
-        u32   suni_rsop_section_bip8l;/* RSOP Section BIP-8 LSB             */
-        u32   suni_rsop_section_bip8m;/* RSOP Section BIP-8 MSB             */
-
-        u32   suni_tsop_control;      /* TSOP Control                       */
-        u32   suni_tsop_diag;         /* TSOP Disgnostics                   */
-        u32   suni_tsop_reserved[2];  /* TSOP Reserved                      */
-
-        u32   suni_rlop_cs;           /* RLOP Control/Status                */
-        u32   suni_rlop_intr;         /* RLOP Interrupt Enable/Status       */
-        u32   suni_rlop_line_bip24l;  /* RLOP Line BIP-24 LSB               */
-        u32   suni_rlop_line_bip24;   /* RLOP Line BIP-24                   */
-        u32   suni_rlop_line_bip24m;  /* RLOP Line BIP-24 MSB               */
-        u32   suni_rlop_line_febel;   /* RLOP Line FEBE LSB                 */
-        u32   suni_rlop_line_febe;    /* RLOP Line FEBE                     */
-        u32   suni_rlop_line_febem;   /* RLOP Line FEBE MSB                 */
-
-        u32   suni_tlop_control;      /* TLOP Control                       */
-        u32   suni_tlop_disg;         /* TLOP Disgnostics                   */
-        u32   suni_tlop_reserved[14]; /* TLOP Reserved                      */
-
-        u32   suni_rpop_cs;           /* RPOP Status/Control                */
-        u32   suni_rpop_intr;         /* RPOP Interrupt/Status              */
-        u32   suni_rpop_reserved;     /* RPOP Reserved                      */
-        u32   suni_rpop_intr_ena;     /* RPOP Interrupt Enable              */
-        u32   suni_rpop_reserved1[3]; /* RPOP Reserved                      */
-        u32   suni_rpop_path_sig;     /* RPOP Path Signal Label             */
-        u32   suni_rpop_bip8l;        /* RPOP Path BIP-8 LSB                */
-        u32   suni_rpop_bip8m;        /* RPOP Path BIP-8 MSB                */
-        u32   suni_rpop_febel;        /* RPOP Path FEBE LSB                 */
-        u32   suni_rpop_febem;        /* RPOP Path FEBE MSB                 */
-        u32   suni_rpop_reserved2[4]; /* RPOP Reserved                      */
-
-        u32   suni_tpop_cntrl_daig;   /* TPOP Control/Disgnostics           */
-        u32   suni_tpop_pointer_ctrl; /* TPOP Pointer Control               */
-        u32   suni_tpop_sourcer_ctrl; /* TPOP Source Control                */
-        u32   suni_tpop_reserved1[2]; /* TPOP Reserved                      */
-        u32   suni_tpop_arb_prtl;     /* TPOP Arbitrary Pointer LSB         */
-        u32   suni_tpop_arb_prtm;     /* TPOP Arbitrary Pointer MSB         */
-        u32   suni_tpop_reserved2;    /* TPOP Reserved                      */
-        u32   suni_tpop_path_sig;     /* TPOP Path Signal Lable             */
-        u32   suni_tpop_path_status;  /* TPOP Path Status                   */
-        u32   suni_tpop_reserved3[6]; /* TPOP Reserved                      */              
-
-        u32   suni_racp_cs;           /* RACP Control/Status                */
-        u32   suni_racp_intr;         /* RACP Interrupt Enable/Status       */
-        u32   suni_racp_hdr_pattern;  /* RACP Match Header Pattern          */
-        u32   suni_racp_hdr_mask;     /* RACP Match Header Mask             */
-        u32   suni_racp_corr_hcs;     /* RACP Correctable HCS Error Count   */
-        u32   suni_racp_uncorr_hcs;   /* RACP Uncorrectable HCS Error Count */
-        u32   suni_racp_reserved[10]; /* RACP Reserved                      */
-
-        u32   suni_tacp_control;      /* TACP Control                       */
-        u32   suni_tacp_idle_hdr_pat; /* TACP Idle Cell Header Pattern      */
-        u32   suni_tacp_idle_pay_pay; /* TACP Idle Cell Payld Octet Pattern */
-        u32   suni_tacp_reserved[5];  /* TACP Reserved                      */
-
-        u32   suni_reserved3[24];     /* Reserved                           */
+enum ia_suni {
+	SUNI_MASTER_RESET	= 0x000, /* SUNI Master Reset and Identity   */
+	SUNI_MASTER_CONFIG	= 0x004, /* SUNI Master Configuration        */
+	SUNI_MASTER_INTR_STAT	= 0x008, /* SUNI Master Interrupt Status     */
+	SUNI_RESERVED1		= 0x00c, /* Reserved                         */
+	SUNI_MASTER_CLK_MONITOR	= 0x010, /* SUNI Master Clock Monitor        */
+	SUNI_MASTER_CONTROL	= 0x014, /* SUNI Master Clock Monitor        */
+					 /* Reserved (10)                    */
+	SUNI_RSOP_CONTROL	= 0x040, /* RSOP Control/Interrupt Enable    */
+	SUNI_RSOP_STATUS	= 0x044, /* RSOP Status/Interrupt States     */
+	SUNI_RSOP_SECTION_BIP8L	= 0x048, /* RSOP Section BIP-8 LSB           */
+	SUNI_RSOP_SECTION_BIP8M	= 0x04c, /* RSOP Section BIP-8 MSB           */
 
-        u32   suni_master_test;       /* SUNI Master Test                   */
-        u32   suni_reserved_test;     /* SUNI Reserved for Test             */
-} IA_SUNI;
+	SUNI_TSOP_CONTROL	= 0x050, /* TSOP Control                     */
+	SUNI_TSOP_DIAG		= 0x054, /* TSOP Disgnostics                 */
+					 /* Reserved (2)                     */
+	SUNI_RLOP_CS		= 0x060, /* RLOP Control/Status              */
+	SUNI_RLOP_INTR		= 0x064, /* RLOP Interrupt Enable/Status     */
+	SUNI_RLOP_LINE_BIP24L	= 0x068, /* RLOP Line BIP-24 LSB             */
+	SUNI_RLOP_LINE_BIP24	= 0x06c, /* RLOP Line BIP-24                 */
+	SUNI_RLOP_LINE_BIP24M	= 0x070, /* RLOP Line BIP-24 MSB             */
+	SUNI_RLOP_LINE_FEBEL	= 0x074, /* RLOP Line FEBE LSB               */
+	SUNI_RLOP_LINE_FEBE	= 0x078, /* RLOP Line FEBE                   */
+	SUNI_RLOP_LINE_FEBEM	= 0x07c, /* RLOP Line FEBE MSB               */
 
+	SUNI_TLOP_CONTROL	= 0x080, /* TLOP Control                     */
+	SUNI_TLOP_DISG		= 0x084, /* TLOP Disgnostics                 */
+					 /* Reserved (14)                    */
+	SUNI_RPOP_CS		= 0x0c0, /* RPOP Status/Control              */
+	SUNI_RPOP_INTR		= 0x0c4, /* RPOP Interrupt/Status            */
+	SUNI_RPOP_RESERVED	= 0x0c8, /* RPOP Reserved                    */
+	SUNI_RPOP_INTR_ENA	= 0x0cc, /* RPOP Interrupt Enable            */
+					 /* Reserved (3)                     */
+	SUNI_RPOP_PATH_SIG	= 0x0dc, /* RPOP Path Signal Label           */
+	SUNI_RPOP_BIP8L		= 0x0e0, /* RPOP Path BIP-8 LSB              */
+	SUNI_RPOP_BIP8M		= 0x0e4, /* RPOP Path BIP-8 MSB              */
+	SUNI_RPOP_FEBEL		= 0x0e8, /* RPOP Path FEBE LSB               */
+	SUNI_RPOP_FEBEM		= 0x0ec, /* RPOP Path FEBE MSB               */
+					 /* Reserved (4)                     */
+	SUNI_TPOP_CNTRL_DAIG	= 0x100, /* TPOP Control/Disgnostics         */
+	SUNI_TPOP_POINTER_CTRL	= 0x104, /* TPOP Pointer Control             */
+	SUNI_TPOP_SOURCER_CTRL	= 0x108, /* TPOP Source Control              */
+					 /* Reserved (2)                     */
+	SUNI_TPOP_ARB_PRTL	= 0x114, /* TPOP Arbitrary Pointer LSB       */
+	SUNI_TPOP_ARB_PRTM	= 0x118, /* TPOP Arbitrary Pointer MSB       */
+	SUNI_TPOP_RESERVED2	= 0x11c, /* TPOP Reserved                    */
+	SUNI_TPOP_PATH_SIG	= 0x120, /* TPOP Path Signal Lable           */
+	SUNI_TPOP_PATH_STATUS	= 0x124, /* TPOP Path Status                 */
+					 /* Reserved (6)                     */
+	SUNI_RACP_CS		= 0x140, /* RACP Control/Status              */
+	SUNI_RACP_INTR		= 0x144, /* RACP Interrupt Enable/Status     */
+	SUNI_RACP_HDR_PATTERN	= 0x148, /* RACP Match Header Pattern        */
+	SUNI_RACP_HDR_MASK	= 0x14c, /* RACP Match Header Mask           */
+	SUNI_RACP_CORR_HCS	= 0x150, /* RACP Correctable HCS Error Count */
+	SUNI_RACP_UNCORR_HCS	= 0x154, /* RACP Uncorrectable HCS Err Count */
+					 /* Reserved (10)                    */
+	SUNI_TACP_CONTROL	= 0x180, /* TACP Control                     */
+	SUNI_TACP_IDLE_HDR_PAT	= 0x184, /* TACP Idle Cell Header Pattern    */
+	SUNI_TACP_IDLE_PAY_PAY	= 0x188, /* TACP Idle Cell Payld Octet Patrn */
+					 /* Reserved (5)                     */
+					 /* Reserved (24)                    */
+	/* FIXME: unused but name conflicts.
+	 * SUNI_MASTER_TEST	= 0x200,    SUNI Master Test                 */
+	SUNI_RESERVED_TEST	= 0x204  /* SUNI Reserved for Test           */
+};
 
 typedef struct _SUNI_STATS_
 {
@@ -993,13 +985,11 @@
    u32 racp_uchcs_count;            // uncorrectable HCS error count
 } IA_SUNI_STATS; 
 
-typedef struct iadev_t {  
+typedef struct iadev_priv {
 	/*-----base pointers into (i)chipSAR+ address space */   
-	u32 __iomem *phy;		/* base pointer into phy(SUNI) */  
-	u32 __iomem *dma;		/* base pointer into DMA control   
-						registers */  
-	u32 __iomem *reg;		/* base pointer to SAR registers  
-					   - Bus Interface Control Regs */  
+	u32 __iomem *phy;	/* Base pointer into phy (SUNI). */
+	u32 __iomem *dma;	/* Base pointer into DMA control registers. */
+	u32 __iomem *reg;	/* Base pointer to SAR registers. */
 	u32 __iomem *seg_reg;		/* base pointer to segmentation engine  
 						internal registers */  
 	u32 __iomem *reass_reg;		/* base pointer to reassemble engine  
@@ -1071,14 +1061,14 @@
 #define INPH_IA_VCC(v) ((struct ia_vcc *) (v)->dev_data)  
 
 /******************* IDT77105 25MB/s PHY DEFINE *****************************/
-typedef struct {
-	u_int	mb25_master_ctrl;	/* Master control		     */
-	u_int	mb25_intr_status;	/* Interrupt status		     */
-	u_int	mb25_diag_control;	/* Diagnostic control		     */
-	u_int	mb25_led_hec;		/* LED driver and HEC status/control */
-	u_int	mb25_low_byte_counter;	/* Low byte counter		     */
-	u_int	mb25_high_byte_counter;	/* High byte counter		     */
-} ia_mb25_t;
+enum ia_mb25 {
+	MB25_MASTER_CTRL	= 0x00, /* Master control		     */
+	MB25_INTR_STATUS	= 0x04,	/* Interrupt status		     */
+	MB25_DIAG_CONTROL	= 0x08,	/* Diagnostic control		     */
+	MB25_LED_HEC		= 0x0c,	/* LED driver and HEC status/control */
+	MB25_LOW_BYTE_COUNTER	= 0x10,
+	MB25_HIGH_BYTE_COUNTER	= 0x14
+};
 
 /*
  * Master Control
@@ -1127,122 +1117,121 @@
 #define FE_E3_PHY       0x0090          /* E3 */
 		     
 /*********************** SUNI_PM7345 PHY DEFINE HERE *********************/
-typedef struct _suni_pm7345_t
-{
-    u_int suni_config;     /* SUNI Configuration */
-    u_int suni_intr_enbl;  /* SUNI Interrupt Enable */
-    u_int suni_intr_stat;  /* SUNI Interrupt Status */
-    u_int suni_control;    /* SUNI Control */
-    u_int suni_id_reset;   /* SUNI Reset and Identity */
-    u_int suni_data_link_ctrl;
-    u_int suni_rboc_conf_intr_enbl;
-    u_int suni_rboc_stat;
-    u_int suni_ds3_frm_cfg;
-    u_int suni_ds3_frm_intr_enbl;
-    u_int suni_ds3_frm_intr_stat;
-    u_int suni_ds3_frm_stat;
-    u_int suni_rfdl_cfg;
-    u_int suni_rfdl_enbl_stat;
-    u_int suni_rfdl_stat;
-    u_int suni_rfdl_data;
-    u_int suni_pmon_chng;
-    u_int suni_pmon_intr_enbl_stat;
-    u_int suni_reserved1[0x13-0x11];
-    u_int suni_pmon_lcv_evt_cnt_lsb;
-    u_int suni_pmon_lcv_evt_cnt_msb;
-    u_int suni_pmon_fbe_evt_cnt_lsb;
-    u_int suni_pmon_fbe_evt_cnt_msb;
-    u_int suni_pmon_sez_det_cnt_lsb;
-    u_int suni_pmon_sez_det_cnt_msb;
-    u_int suni_pmon_pe_evt_cnt_lsb;
-    u_int suni_pmon_pe_evt_cnt_msb;
-    u_int suni_pmon_ppe_evt_cnt_lsb;
-    u_int suni_pmon_ppe_evt_cnt_msb;
-    u_int suni_pmon_febe_evt_cnt_lsb;
-    u_int suni_pmon_febe_evt_cnt_msb;
-    u_int suni_ds3_tran_cfg;
-    u_int suni_ds3_tran_diag;
-    u_int suni_reserved2[0x23-0x21];
-    u_int suni_xfdl_cfg;
-    u_int suni_xfdl_intr_st;
-    u_int suni_xfdl_xmit_data;
-    u_int suni_xboc_code;
-    u_int suni_splr_cfg;
-    u_int suni_splr_intr_en;
-    u_int suni_splr_intr_st;
-    u_int suni_splr_status;
-    u_int suni_splt_cfg;
-    u_int suni_splt_cntl;
-    u_int suni_splt_diag_g1;
-    u_int suni_splt_f1;
-    u_int suni_cppm_loc_meters;
-    u_int suni_cppm_chng_of_cppm_perf_meter;
-    u_int suni_cppm_b1_err_cnt_lsb;
-    u_int suni_cppm_b1_err_cnt_msb;
-    u_int suni_cppm_framing_err_cnt_lsb;
-    u_int suni_cppm_framing_err_cnt_msb;
-    u_int suni_cppm_febe_cnt_lsb;
-    u_int suni_cppm_febe_cnt_msb;
-    u_int suni_cppm_hcs_err_cnt_lsb;
-    u_int suni_cppm_hcs_err_cnt_msb;
-    u_int suni_cppm_idle_un_cell_cnt_lsb;
-    u_int suni_cppm_idle_un_cell_cnt_msb;
-    u_int suni_cppm_rcv_cell_cnt_lsb;
-    u_int suni_cppm_rcv_cell_cnt_msb;
-    u_int suni_cppm_xmit_cell_cnt_lsb;
-    u_int suni_cppm_xmit_cell_cnt_msb;
-    u_int suni_rxcp_ctrl;
-    u_int suni_rxcp_fctrl;
-    u_int suni_rxcp_intr_en_sts;
-    u_int suni_rxcp_idle_pat_h1;
-    u_int suni_rxcp_idle_pat_h2;
-    u_int suni_rxcp_idle_pat_h3;
-    u_int suni_rxcp_idle_pat_h4;
-    u_int suni_rxcp_idle_mask_h1;
-    u_int suni_rxcp_idle_mask_h2;
-    u_int suni_rxcp_idle_mask_h3;
-    u_int suni_rxcp_idle_mask_h4;
-    u_int suni_rxcp_cell_pat_h1;
-    u_int suni_rxcp_cell_pat_h2;
-    u_int suni_rxcp_cell_pat_h3;
-    u_int suni_rxcp_cell_pat_h4;
-    u_int suni_rxcp_cell_mask_h1;
-    u_int suni_rxcp_cell_mask_h2;
-    u_int suni_rxcp_cell_mask_h3;
-    u_int suni_rxcp_cell_mask_h4;
-    u_int suni_rxcp_hcs_cs;
-    u_int suni_rxcp_lcd_cnt_threshold;
-    u_int suni_reserved3[0x57-0x54];
-    u_int suni_txcp_ctrl;
-    u_int suni_txcp_intr_en_sts;
-    u_int suni_txcp_idle_pat_h1;
-    u_int suni_txcp_idle_pat_h2;
-    u_int suni_txcp_idle_pat_h3;
-    u_int suni_txcp_idle_pat_h4;
-    u_int suni_txcp_idle_pat_h5;
-    u_int suni_txcp_idle_payload;
-    u_int suni_e3_frm_fram_options;
-    u_int suni_e3_frm_maint_options;
-    u_int suni_e3_frm_fram_intr_enbl;
-    u_int suni_e3_frm_fram_intr_ind_stat;
-    u_int suni_e3_frm_maint_intr_enbl;
-    u_int suni_e3_frm_maint_intr_ind;
-    u_int suni_e3_frm_maint_stat;
-    u_int suni_reserved4;
-    u_int suni_e3_tran_fram_options;
-    u_int suni_e3_tran_stat_diag_options;
-    u_int suni_e3_tran_bip_8_err_mask;
-    u_int suni_e3_tran_maint_adapt_options;
-    u_int suni_ttb_ctrl;
-    u_int suni_ttb_trail_trace_id_stat;
-    u_int suni_ttb_ind_addr;
-    u_int suni_ttb_ind_data;
-    u_int suni_ttb_exp_payload_type;
-    u_int suni_ttb_payload_type_ctrl_stat;
-    u_int suni_pad5[0x7f-0x71];
-    u_int suni_master_test;
-    u_int suni_pad6[0xff-0x80];
-}suni_pm7345_t;
+enum suni_pm7345 {
+	SUNI_CONFIG			= 0x000, /* SUNI Configuration */
+	SUNI_INTR_ENBL			= 0x004, /* SUNI Interrupt Enable */
+	SUNI_INTR_STAT			= 0x008, /* SUNI Interrupt Status */
+	SUNI_CONTROL			= 0x00c, /* SUNI Control */
+	SUNI_ID_RESET			= 0x010, /* SUNI Reset and Identity */
+	SUNI_DATA_LINK_CTRL		= 0x014,
+	SUNI_RBOC_CONF_INTR_ENBL	= 0x018,
+	SUNI_RBOC_STAT			= 0x01c,
+	SUNI_DS3_FRM_CFG		= 0x020,
+	SUNI_DS3_FRM_INTR_ENBL		= 0x024,
+	SUNI_DS3_FRM_INTR_STAT		= 0x028,
+	SUNI_DS3_FRM_STAT		= 0x02c,
+	SUNI_RFDL_CFG			= 0x030,
+	SUNI_RFDL_ENBL_STAT		= 0x034,
+	SUNI_RFDL_STAT			= 0x038,
+	SUNI_RFDL_DATA			= 0x03c,
+	SUNI_PMON_CHNG			= 0x040,
+	SUNI_PMON_INTR_ENBL_STAT	= 0x044,
+	/* SUNI_RESERVED1 (0x13 - 0x11) */
+	SUNI_PMON_LCV_EVT_CNT_LSB	= 0x050,
+	SUNI_PMON_LCV_EVT_CNT_MSB	= 0x054,
+	SUNI_PMON_FBE_EVT_CNT_LSB	= 0x058,
+	SUNI_PMON_FBE_EVT_CNT_MSB	= 0x05c,
+	SUNI_PMON_SEZ_DET_CNT_LSB	= 0x060,
+	SUNI_PMON_SEZ_DET_CNT_MSB	= 0x064,
+	SUNI_PMON_PE_EVT_CNT_LSB	= 0x068,
+	SUNI_PMON_PE_EVT_CNT_MSB	= 0x06c,
+	SUNI_PMON_PPE_EVT_CNT_LSB	= 0x070,
+	SUNI_PMON_PPE_EVT_CNT_MSB	= 0x074,
+	SUNI_PMON_FEBE_EVT_CNT_LSB	= 0x078,
+	SUNI_PMON_FEBE_EVT_CNT_MSB	= 0x07c,
+	SUNI_DS3_TRAN_CFG		= 0x080,
+	SUNI_DS3_TRAN_DIAG		= 0x084,
+	/* SUNI_RESERVED2 (0x23 - 0x21) */
+	SUNI_XFDL_CFG			= 0x090,
+	SUNI_XFDL_INTR_ST		= 0x094,
+	SUNI_XFDL_XMIT_DATA		= 0x098,
+	SUNI_XBOC_CODE			= 0x09c,
+	SUNI_SPLR_CFG			= 0x0a0,
+	SUNI_SPLR_INTR_EN		= 0x0a4,
+	SUNI_SPLR_INTR_ST		= 0x0a8,
+	SUNI_SPLR_STATUS		= 0x0ac,
+	SUNI_SPLT_CFG			= 0x0b0,
+	SUNI_SPLT_CNTL			= 0x0b4,
+	SUNI_SPLT_DIAG_G1		= 0x0b8,
+	SUNI_SPLT_F1			= 0x0bc,
+	SUNI_CPPM_LOC_METERS		= 0x0c0,
+	SUNI_CPPM_CHG_OF_CPPM_PERF_METR	= 0x0c4,
+	SUNI_CPPM_B1_ERR_CNT_LSB	= 0x0c8,
+	SUNI_CPPM_B1_ERR_CNT_MSB	= 0x0cc,
+	SUNI_CPPM_FRAMING_ERR_CNT_LSB	= 0x0d0,
+	SUNI_CPPM_FRAMING_ERR_CNT_MSB	= 0x0d4,
+	SUNI_CPPM_FEBE_CNT_LSB		= 0x0d8,
+	SUNI_CPPM_FEBE_CNT_MSB		= 0x0dc,
+	SUNI_CPPM_HCS_ERR_CNT_LSB	= 0x0e0,
+	SUNI_CPPM_HCS_ERR_CNT_MSB	= 0x0e4,
+	SUNI_CPPM_IDLE_UN_CELL_CNT_LSB	= 0x0e8,
+	SUNI_CPPM_IDLE_UN_CELL_CNT_MSB	= 0x0ec,
+	SUNI_CPPM_RCV_CELL_CNT_LSB	= 0x0f0,
+	SUNI_CPPM_RCV_CELL_CNT_MSB	= 0x0f4,
+	SUNI_CPPM_XMIT_CELL_CNT_LSB	= 0x0f8,
+	SUNI_CPPM_XMIT_CELL_CNT_MSB	= 0x0fc,
+	SUNI_RXCP_CTRL			= 0x100,
+	SUNI_RXCP_FCTRL			= 0x104,
+	SUNI_RXCP_INTR_EN_STS		= 0x108,
+	SUNI_RXCP_IDLE_PAT_H1		= 0x10c,
+	SUNI_RXCP_IDLE_PAT_H2		= 0x110,
+	SUNI_RXCP_IDLE_PAT_H3		= 0x114,
+	SUNI_RXCP_IDLE_PAT_H4		= 0x118,
+	SUNI_RXCP_IDLE_MASK_H1		= 0x11c,
+	SUNI_RXCP_IDLE_MASK_H2		= 0x120,
+	SUNI_RXCP_IDLE_MASK_H3		= 0x124,
+	SUNI_RXCP_IDLE_MASK_H4		= 0x128,
+	SUNI_RXCP_CELL_PAT_H1		= 0x12c,
+	SUNI_RXCP_CELL_PAT_H2		= 0x130,
+	SUNI_RXCP_CELL_PAT_H3		= 0x134,
+	SUNI_RXCP_CELL_PAT_H4		= 0x138,
+	SUNI_RXCP_CELL_MASK_H1		= 0x13c,
+	SUNI_RXCP_CELL_MASK_H2		= 0x140,
+	SUNI_RXCP_CELL_MASK_H3		= 0x144,
+	SUNI_RXCP_CELL_MASK_H4		= 0x148,
+	SUNI_RXCP_HCS_CS		= 0x14c,
+	SUNI_RXCP_LCD_CNT_THRESHOLD	= 0x150,
+	/* SUNI_RESERVED3 (0x57 - 0x54) */
+	SUNI_TXCP_CTRL			= 0x160,
+	SUNI_TXCP_INTR_EN_STS		= 0x164,
+	SUNI_TXCP_IDLE_PAT_H1		= 0x168,
+	SUNI_TXCP_IDLE_PAT_H2		= 0x16c,
+	SUNI_TXCP_IDLE_PAT_H3		= 0x170,
+	SUNI_TXCP_IDLE_PAT_H4		= 0x174,
+	SUNI_TXCP_IDLE_PAT_H5		= 0x178,
+	SUNI_TXCP_IDLE_PAYLOAD		= 0x17c,
+	SUNI_E3_FRM_FRAM_OPTIONS	= 0x180,
+	SUNI_E3_FRM_MAINT_OPTIONS	= 0x184,
+	SUNI_E3_FRM_FRAM_INTR_ENBL	= 0x188,
+	SUNI_E3_FRM_FRAM_INTR_IND_STAT	= 0x18c,
+	SUNI_E3_FRM_MAINT_INTR_ENBL	= 0x190,
+	SUNI_E3_FRM_MAINT_INTR_IND	= 0x194,
+	SUNI_E3_FRM_MAINT_STAT		= 0x198,
+	SUNI_RESERVED4			= 0x19c,
+	SUNI_E3_TRAN_FRAM_OPTIONS	= 0x1a0,
+	SUNI_E3_TRAN_STAT_DIAG_OPTIONS	= 0x1a4,
+	SUNI_E3_TRAN_BIP_8_ERR_MASK	= 0x1a8,
+	SUNI_E3_TRAN_MAINT_ADAPT_OPTS	= 0x1ac,
+	SUNI_TTB_CTRL			= 0x1b0,
+	SUNI_TTB_TRAIL_TRACE_ID_STAT	= 0x1b4,
+	SUNI_TTB_IND_ADDR		= 0x1b8,
+	SUNI_TTB_IND_DATA		= 0x1bc,
+	SUNI_TTB_EXP_PAYLOAD_TYPE	= 0x1c0,
+	SUNI_TTB_PAYLOAD_TYPE_CTRL_STAT	= 0x1c4,
+	/* SUNI_PAD5 (0x7f - 0x71) */
+	SUNI_MASTER_TEST		= 0x200,
+	/* SUNI_PAD6 (0xff - 0x80) */
+};
 
 #define SUNI_PM7345_T suni_pm7345_t
 #define SUNI_PM7345     0x20            /* Suni chip type */
diff -druN linux-libre-3.1-gnu/drivers/atm/lanai.c linux-libre-3.2-gnu/drivers/atm/lanai.c
--- linux-libre-3.1-gnu/drivers/atm/lanai.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/atm/lanai.c	2012-01-04 18:55:44.000000000 -0500
@@ -1457,10 +1457,9 @@
 	return (lanai->vccs == NULL) ? -ENOMEM : 0;
 #else
 	int bytes = (lanai->num_vci) * sizeof(struct lanai_vcc *);
-	lanai->vccs = (struct lanai_vcc **) vmalloc(bytes);
+	lanai->vccs = vzalloc(bytes);
 	if (unlikely(lanai->vccs == NULL))
 		return -ENOMEM;
-	memset(lanai->vccs, 0, bytes);
 	return 0;
 #endif
 }
diff -druN linux-libre-3.1-gnu/drivers/base/base.h linux-libre-3.2-gnu/drivers/base/base.h
--- linux-libre-3.1-gnu/drivers/base/base.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/base.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,4 @@
+#include <linux/notifier.h>
 
 /**
  * struct subsys_private - structure to hold the private to the driver core portions of the bus_type/class structure.
diff -druN linux-libre-3.1-gnu/drivers/base/class.c linux-libre-3.2-gnu/drivers/base/class.c
--- linux-libre-3.1-gnu/drivers/base/class.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/class.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,18 @@
 	return ret;
 }
 
+static const void *class_attr_namespace(struct kobject *kobj,
+					const struct attribute *attr)
+{
+	struct class_attribute *class_attr = to_class_attr(attr);
+	struct subsys_private *cp = to_subsys_private(kobj);
+	const void *ns = NULL;
+
+	if (class_attr->namespace)
+		ns = class_attr->namespace(cp->class, class_attr);
+	return ns;
+}
+
 static void class_release(struct kobject *kobj)
 {
 	struct subsys_private *cp = to_subsys_private(kobj);
@@ -72,8 +84,9 @@
 }
 
 static const struct sysfs_ops class_sysfs_ops = {
-	.show	= class_attr_show,
-	.store	= class_attr_store,
+	.show	   = class_attr_show,
+	.store	   = class_attr_store,
+	.namespace = class_attr_namespace,
 };
 
 static struct kobj_type class_ktype = {
diff -druN linux-libre-3.1-gnu/drivers/base/core.c linux-libre-3.2-gnu/drivers/base/core.c
--- linux-libre-3.1-gnu/drivers/base/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/kallsyms.h>
 #include <linux/mutex.h>
 #include <linux/async.h>
+#include <linux/pm_runtime.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -1743,6 +1744,10 @@
 		list_del_init(&dev->kobj.entry);
 		spin_unlock(&devices_kset->list_lock);
 
+		/* Don't allow any more runtime suspends */
+		pm_runtime_get_noresume(dev);
+		pm_runtime_barrier(dev);
+
 		if (dev->bus && dev->bus->shutdown) {
 			dev_dbg(dev, "shutdown\n");
 			dev->bus->shutdown(dev);
@@ -1764,8 +1769,8 @@
 
 #ifdef CONFIG_PRINTK
 
-static int __dev_printk(const char *level, const struct device *dev,
-			struct va_format *vaf)
+int __dev_printk(const char *level, const struct device *dev,
+		 struct va_format *vaf)
 {
 	if (!dev)
 		return printk("%s(NULL device *): %pV", level, vaf);
@@ -1773,6 +1778,7 @@
 	return printk("%s%s %s: %pV",
 		      level, dev_driver_string(dev), dev_name(dev), vaf);
 }
+EXPORT_SYMBOL(__dev_printk);
 
 int dev_printk(const char *level, const struct device *dev,
 	       const char *fmt, ...)
diff -druN linux-libre-3.1-gnu/drivers/base/dd.c linux-libre-3.2-gnu/drivers/base/dd.c
--- linux-libre-3.1-gnu/drivers/base/dd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/dd.c	2012-01-04 18:55:44.000000000 -0500
@@ -147,6 +147,9 @@
 		printk(KERN_WARNING
 		       "%s: probe of %s failed with error %d\n",
 		       drv->name, dev_name(dev), ret);
+	} else {
+		pr_debug("%s: probe of %s rejects match %d\n",
+		       drv->name, dev_name(dev), ret);
 	}
 	/*
 	 * Ignore errors returned by ->probe so that the next driver can try
diff -druN linux-libre-3.1-gnu/drivers/base/dma-coherent.c linux-libre-3.2-gnu/drivers/base/dma-coherent.c
--- linux-libre-3.1-gnu/drivers/base/dma-coherent.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/dma-coherent.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@
  */
 #include <linux/slab.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/dma-mapping.h>
 
 struct dma_coherent_mem {
diff -druN linux-libre-3.1-gnu/drivers/base/dma-mapping.c linux-libre-3.2-gnu/drivers/base/dma-mapping.c
--- linux-libre-3.1-gnu/drivers/base/dma-mapping.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/dma-mapping.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 #include <linux/gfp.h>
 
 /*
diff -druN linux-libre-3.1-gnu/drivers/base/hypervisor.c linux-libre-3.2-gnu/drivers/base/hypervisor.c
--- linux-libre-3.1-gnu/drivers/base/hypervisor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/hypervisor.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 
 #include <linux/kobject.h>
 #include <linux/device.h>
+#include <linux/export.h>
 #include "base.h"
 
 struct kobject *hypervisor_kobj;
diff -druN linux-libre-3.1-gnu/drivers/base/memory.c linux-libre-3.2-gnu/drivers/base/memory.c
--- linux-libre-3.1-gnu/drivers/base/memory.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/memory.c	2012-01-04 18:55:44.000000000 -0500
@@ -224,13 +224,48 @@
 }
 
 /*
+ * The probe routines leave the pages reserved, just as the bootmem code does.
+ * Make sure they're still that way.
+ */
+static bool pages_correctly_reserved(unsigned long start_pfn,
+					unsigned long nr_pages)
+{
+	int i, j;
+	struct page *page;
+	unsigned long pfn = start_pfn;
+
+	/*
+	 * memmap between sections is not contiguous except with
+	 * SPARSEMEM_VMEMMAP. We lookup the page once per section
+	 * and assume memmap is contiguous within each section
+	 */
+	for (i = 0; i < sections_per_block; i++, pfn += PAGES_PER_SECTION) {
+		if (WARN_ON_ONCE(!pfn_valid(pfn)))
+			return false;
+		page = pfn_to_page(pfn);
+
+		for (j = 0; j < PAGES_PER_SECTION; j++) {
+			if (PageReserved(page + j))
+				continue;
+
+			printk(KERN_WARNING "section number %ld page number %d "
+				"not reserved, was it already online?\n",
+				pfn_to_section_nr(pfn), j);
+
+			return false;
+		}
+	}
+
+	return true;
+}
+
+/*
  * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is
  * OK to have direct references to sparsemem variables in here.
  */
 static int
 memory_block_action(unsigned long phys_index, unsigned long action)
 {
-	int i;
 	unsigned long start_pfn, start_paddr;
 	unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
 	struct page *first_page;
@@ -238,26 +273,13 @@
 
 	first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT);
 
-	/*
-	 * The probe routines leave the pages reserved, just
-	 * as the bootmem code does.  Make sure they're still
-	 * that way.
-	 */
-	if (action == MEM_ONLINE) {
-		for (i = 0; i < nr_pages; i++) {
-			if (PageReserved(first_page+i))
-				continue;
-
-			printk(KERN_WARNING "section number %ld page number %d "
-				"not reserved, was it already online?\n",
-				phys_index, i);
-			return -EBUSY;
-		}
-	}
-
 	switch (action) {
 		case MEM_ONLINE:
 			start_pfn = page_to_pfn(first_page);
+
+			if (!pages_correctly_reserved(start_pfn, nr_pages))
+				return -EBUSY;
+
 			ret = online_pages(start_pfn, nr_pages);
 			break;
 		case MEM_OFFLINE:
@@ -380,9 +402,13 @@
 	u64 phys_addr;
 	int nid;
 	int i, ret;
+	unsigned long pages_per_block = PAGES_PER_SECTION * sections_per_block;
 
 	phys_addr = simple_strtoull(buf, NULL, 0);
 
+	if (phys_addr & ((pages_per_block << PAGE_SHIFT) - 1))
+		return -EINVAL;
+
 	for (i = 0; i < sections_per_block; i++) {
 		nid = memory_add_physaddr_to_nid(phys_addr);
 		ret = add_memory(nid, phys_addr,
diff -druN linux-libre-3.1-gnu/drivers/base/node.c linux-libre-3.2-gnu/drivers/base/node.c
--- linux-libre-3.1-gnu/drivers/base/node.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/node.c	2012-01-04 18:55:44.000000000 -0500
@@ -127,12 +127,13 @@
 		       nid, K(node_page_state(nid, NR_WRITEBACK)),
 		       nid, K(node_page_state(nid, NR_FILE_PAGES)),
 		       nid, K(node_page_state(nid, NR_FILE_MAPPED)),
-		       nid, K(node_page_state(nid, NR_ANON_PAGES)
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+		       nid, K(node_page_state(nid, NR_ANON_PAGES)
 			+ node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) *
-			HPAGE_PMD_NR
+			HPAGE_PMD_NR),
+#else
+		       nid, K(node_page_state(nid, NR_ANON_PAGES)),
 #endif
-		       ),
 		       nid, K(node_page_state(nid, NR_SHMEM)),
 		       nid, node_page_state(nid, NR_KERNEL_STACK) *
 				THREAD_SIZE / 1024,
@@ -143,13 +144,14 @@
 		       nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE) +
 				node_page_state(nid, NR_SLAB_UNRECLAIMABLE)),
 		       nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE)),
-		       nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE))
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+		       nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE))
 			, nid,
 			K(node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) *
-			HPAGE_PMD_NR)
+			HPAGE_PMD_NR));
+#else
+		       nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE)));
 #endif
-		       );
 	n += hugetlb_report_node_meminfo(nid, buf + n);
 	return n;
 }
diff -druN linux-libre-3.1-gnu/drivers/base/platform.c linux-libre-3.2-gnu/drivers/base/platform.c
--- linux-libre-3.1-gnu/drivers/base/platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -375,52 +375,64 @@
 EXPORT_SYMBOL_GPL(platform_device_unregister);
 
 /**
- * platform_device_register_resndata - add a platform-level device with
+ * platform_device_register_full - add a platform-level device with
  * resources and platform-specific data
  *
- * @parent: parent device for the device we're adding
- * @name: base name of the device we're adding
- * @id: instance id
- * @res: set of resources that needs to be allocated for the device
- * @num: number of resources
- * @data: platform specific data for this platform device
- * @size: size of platform specific data
+ * @pdevinfo: data used to create device
  *
  * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
  */
-struct platform_device *platform_device_register_resndata(
-		struct device *parent,
-		const char *name, int id,
-		const struct resource *res, unsigned int num,
-		const void *data, size_t size)
+struct platform_device *platform_device_register_full(
+		struct platform_device_info *pdevinfo)
 {
 	int ret = -ENOMEM;
 	struct platform_device *pdev;
 
-	pdev = platform_device_alloc(name, id);
+	pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id);
 	if (!pdev)
-		goto err;
+		goto err_alloc;
 
-	pdev->dev.parent = parent;
+	pdev->dev.parent = pdevinfo->parent;
 
-	ret = platform_device_add_resources(pdev, res, num);
+	if (pdevinfo->dma_mask) {
+		/*
+		 * This memory isn't freed when the device is put,
+		 * I don't have a nice idea for that though.  Conceptually
+		 * dma_mask in struct device should not be a pointer.
+		 * See http://thread.gmane.org/gmane.linux.kernel.pci/9081
+		 */
+		pdev->dev.dma_mask =
+			kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
+		if (!pdev->dev.dma_mask)
+			goto err;
+
+		*pdev->dev.dma_mask = pdevinfo->dma_mask;
+		pdev->dev.coherent_dma_mask = pdevinfo->dma_mask;
+	}
+
+	ret = platform_device_add_resources(pdev,
+			pdevinfo->res, pdevinfo->num_res);
 	if (ret)
 		goto err;
 
-	ret = platform_device_add_data(pdev, data, size);
+	ret = platform_device_add_data(pdev,
+			pdevinfo->data, pdevinfo->size_data);
 	if (ret)
 		goto err;
 
 	ret = platform_device_add(pdev);
 	if (ret) {
 err:
+		kfree(pdev->dev.dma_mask);
+
+err_alloc:
 		platform_device_put(pdev);
 		return ERR_PTR(ret);
 	}
 
 	return pdev;
 }
-EXPORT_SYMBOL_GPL(platform_device_register_resndata);
+EXPORT_SYMBOL_GPL(platform_device_register_full);
 
 static int platform_drv_probe(struct device *_dev)
 {
@@ -614,7 +626,7 @@
 		return rc;
 
 	add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX,
-		(pdev->id_entry) ? pdev->id_entry->name : pdev->name);
+			pdev->name);
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/base/power/clock_ops.c linux-libre-3.2-gnu/drivers/base/power/clock_ops.c
--- linux-libre-3.1-gnu/drivers/base/power/clock_ops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/power/clock_ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,18 +10,13 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/pm.h>
-#include <linux/pm_runtime.h>
+#include <linux/pm_clock.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 
 #ifdef CONFIG_PM
 
-struct pm_clk_data {
-	struct list_head clock_list;
-	spinlock_t lock;
-};
-
 enum pce_status {
 	PCE_STATUS_NONE = 0,
 	PCE_STATUS_ACQUIRED,
@@ -36,11 +31,6 @@
 	enum pce_status status;
 };
 
-static struct pm_clk_data *__to_pcd(struct device *dev)
-{
-	return dev ? dev->power.subsys_data : NULL;
-}
-
 /**
  * pm_clk_acquire - Acquire a device clock.
  * @dev: Device whose clock is to be acquired.
@@ -67,10 +57,10 @@
  */
 int pm_clk_add(struct device *dev, const char *con_id)
 {
-	struct pm_clk_data *pcd = __to_pcd(dev);
+	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
 
-	if (!pcd)
+	if (!psd)
 		return -EINVAL;
 
 	ce = kzalloc(sizeof(*ce), GFP_KERNEL);
@@ -91,9 +81,9 @@
 
 	pm_clk_acquire(dev, ce);
 
-	spin_lock_irq(&pcd->lock);
-	list_add_tail(&ce->node, &pcd->clock_list);
-	spin_unlock_irq(&pcd->lock);
+	spin_lock_irq(&psd->lock);
+	list_add_tail(&ce->node, &psd->clock_list);
+	spin_unlock_irq(&psd->lock);
 	return 0;
 }
 
@@ -114,9 +104,7 @@
 			clk_put(ce->clk);
 	}
 
-	if (ce->con_id)
-		kfree(ce->con_id);
-
+	kfree(ce->con_id);
 	kfree(ce);
 }
 
@@ -130,15 +118,15 @@
  */
 void pm_clk_remove(struct device *dev, const char *con_id)
 {
-	struct pm_clk_data *pcd = __to_pcd(dev);
+	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
 
-	if (!pcd)
+	if (!psd)
 		return;
 
-	spin_lock_irq(&pcd->lock);
+	spin_lock_irq(&psd->lock);
 
-	list_for_each_entry(ce, &pcd->clock_list, node) {
+	list_for_each_entry(ce, &psd->clock_list, node) {
 		if (!con_id && !ce->con_id)
 			goto remove;
 		else if (!con_id || !ce->con_id)
@@ -147,12 +135,12 @@
 			goto remove;
 	}
 
-	spin_unlock_irq(&pcd->lock);
+	spin_unlock_irq(&psd->lock);
 	return;
 
  remove:
 	list_del(&ce->node);
-	spin_unlock_irq(&pcd->lock);
+	spin_unlock_irq(&psd->lock);
 
 	__pm_clk_remove(ce);
 }
@@ -161,23 +149,27 @@
  * pm_clk_init - Initialize a device's list of power management clocks.
  * @dev: Device to initialize the list of PM clocks for.
  *
- * Allocate a struct pm_clk_data object, initialize its lock member and
- * make the @dev's power.subsys_data field point to it.
+ * Initialize the lock and clock_list members of the device's pm_subsys_data
+ * object.
  */
-int pm_clk_init(struct device *dev)
+void pm_clk_init(struct device *dev)
 {
-	struct pm_clk_data *pcd;
-
-	pcd = kzalloc(sizeof(*pcd), GFP_KERNEL);
-	if (!pcd) {
-		dev_err(dev, "Not enough memory for PM clock data.\n");
-		return -ENOMEM;
-	}
+	struct pm_subsys_data *psd = dev_to_psd(dev);
+	if (psd)
+		INIT_LIST_HEAD(&psd->clock_list);
+}
 
-	INIT_LIST_HEAD(&pcd->clock_list);
-	spin_lock_init(&pcd->lock);
-	dev->power.subsys_data = pcd;
-	return 0;
+/**
+ * pm_clk_create - Create and initialize a device's list of PM clocks.
+ * @dev: Device to create and initialize the list of PM clocks for.
+ *
+ * Allocate a struct pm_subsys_data object, initialize its lock and clock_list
+ * members and make the @dev's power.subsys_data field point to it.
+ */
+int pm_clk_create(struct device *dev)
+{
+	int ret = dev_pm_get_subsys_data(dev);
+	return ret < 0 ? ret : 0;
 }
 
 /**
@@ -185,29 +177,28 @@
  * @dev: Device to destroy the list of PM clocks for.
  *
  * Clear the @dev's power.subsys_data field, remove the list of clock entries
- * from the struct pm_clk_data object pointed to by it before and free
+ * from the struct pm_subsys_data object pointed to by it before and free
  * that object.
  */
 void pm_clk_destroy(struct device *dev)
 {
-	struct pm_clk_data *pcd = __to_pcd(dev);
+	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce, *c;
 	struct list_head list;
 
-	if (!pcd)
+	if (!psd)
 		return;
 
-	dev->power.subsys_data = NULL;
 	INIT_LIST_HEAD(&list);
 
-	spin_lock_irq(&pcd->lock);
+	spin_lock_irq(&psd->lock);
 
-	list_for_each_entry_safe_reverse(ce, c, &pcd->clock_list, node)
+	list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node)
 		list_move(&ce->node, &list);
 
-	spin_unlock_irq(&pcd->lock);
+	spin_unlock_irq(&psd->lock);
 
-	kfree(pcd);
+	dev_pm_put_subsys_data(dev);
 
 	list_for_each_entry_safe_reverse(ce, c, &list, node) {
 		list_del(&ce->node);
@@ -225,25 +216,26 @@
  */
 int pm_clk_suspend(struct device *dev)
 {
-	struct pm_clk_data *pcd = __to_pcd(dev);
+	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
 	unsigned long flags;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
-	if (!pcd)
+	if (!psd)
 		return 0;
 
-	spin_lock_irqsave(&pcd->lock, flags);
+	spin_lock_irqsave(&psd->lock, flags);
 
-	list_for_each_entry_reverse(ce, &pcd->clock_list, node) {
+	list_for_each_entry_reverse(ce, &psd->clock_list, node) {
 		if (ce->status < PCE_STATUS_ERROR) {
-			clk_disable(ce->clk);
+			if (ce->status == PCE_STATUS_ENABLED)
+				clk_disable(ce->clk);
 			ce->status = PCE_STATUS_ACQUIRED;
 		}
 	}
 
-	spin_unlock_irqrestore(&pcd->lock, flags);
+	spin_unlock_irqrestore(&psd->lock, flags);
 
 	return 0;
 }
@@ -254,25 +246,25 @@
  */
 int pm_clk_resume(struct device *dev)
 {
-	struct pm_clk_data *pcd = __to_pcd(dev);
+	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
 	unsigned long flags;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
-	if (!pcd)
+	if (!psd)
 		return 0;
 
-	spin_lock_irqsave(&pcd->lock, flags);
+	spin_lock_irqsave(&psd->lock, flags);
 
-	list_for_each_entry(ce, &pcd->clock_list, node) {
+	list_for_each_entry(ce, &psd->clock_list, node) {
 		if (ce->status < PCE_STATUS_ERROR) {
 			clk_enable(ce->clk);
 			ce->status = PCE_STATUS_ENABLED;
 		}
 	}
 
-	spin_unlock_irqrestore(&pcd->lock, flags);
+	spin_unlock_irqrestore(&psd->lock, flags);
 
 	return 0;
 }
@@ -310,7 +302,7 @@
 		if (dev->pm_domain)
 			break;
 
-		error = pm_clk_init(dev);
+		error = pm_clk_create(dev);
 		if (error)
 			break;
 
@@ -345,22 +337,22 @@
  */
 int pm_clk_suspend(struct device *dev)
 {
-	struct pm_clk_data *pcd = __to_pcd(dev);
+	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
 	unsigned long flags;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
 	/* If there is no driver, the clocks are already disabled. */
-	if (!pcd || !dev->driver)
+	if (!psd || !dev->driver)
 		return 0;
 
-	spin_lock_irqsave(&pcd->lock, flags);
+	spin_lock_irqsave(&psd->lock, flags);
 
-	list_for_each_entry_reverse(ce, &pcd->clock_list, node)
+	list_for_each_entry_reverse(ce, &psd->clock_list, node)
 		clk_disable(ce->clk);
 
-	spin_unlock_irqrestore(&pcd->lock, flags);
+	spin_unlock_irqrestore(&psd->lock, flags);
 
 	return 0;
 }
@@ -371,22 +363,22 @@
  */
 int pm_clk_resume(struct device *dev)
 {
-	struct pm_clk_data *pcd = __to_pcd(dev);
+	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
 	unsigned long flags;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
 	/* If there is no driver, the clocks should remain disabled. */
-	if (!pcd || !dev->driver)
+	if (!psd || !dev->driver)
 		return 0;
 
-	spin_lock_irqsave(&pcd->lock, flags);
+	spin_lock_irqsave(&psd->lock, flags);
 
-	list_for_each_entry(ce, &pcd->clock_list, node)
+	list_for_each_entry(ce, &psd->clock_list, node)
 		clk_enable(ce->clk);
 
-	spin_unlock_irqrestore(&pcd->lock, flags);
+	spin_unlock_irqrestore(&psd->lock, flags);
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/base/power/common.c linux-libre-3.2-gnu/drivers/base/power/common.c
--- linux-libre-3.1-gnu/drivers/base/power/common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/base/power/common.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,86 @@
+/*
+ * drivers/base/power/common.c - Common device power management code.
+ *
+ * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/pm_clock.h>
+
+/**
+ * dev_pm_get_subsys_data - Create or refcount power.subsys_data for device.
+ * @dev: Device to handle.
+ *
+ * If power.subsys_data is NULL, point it to a new object, otherwise increment
+ * its reference counter.  Return 1 if a new object has been created, otherwise
+ * return 0 or error code.
+ */
+int dev_pm_get_subsys_data(struct device *dev)
+{
+	struct pm_subsys_data *psd;
+	int ret = 0;
+
+	psd = kzalloc(sizeof(*psd), GFP_KERNEL);
+	if (!psd)
+		return -ENOMEM;
+
+	spin_lock_irq(&dev->power.lock);
+
+	if (dev->power.subsys_data) {
+		dev->power.subsys_data->refcount++;
+	} else {
+		spin_lock_init(&psd->lock);
+		psd->refcount = 1;
+		dev->power.subsys_data = psd;
+		pm_clk_init(dev);
+		psd = NULL;
+		ret = 1;
+	}
+
+	spin_unlock_irq(&dev->power.lock);
+
+	/* kfree() verifies that its argument is nonzero. */
+	kfree(psd);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_get_subsys_data);
+
+/**
+ * dev_pm_put_subsys_data - Drop reference to power.subsys_data.
+ * @dev: Device to handle.
+ *
+ * If the reference counter of power.subsys_data is zero after dropping the
+ * reference, power.subsys_data is removed.  Return 1 if that happens or 0
+ * otherwise.
+ */
+int dev_pm_put_subsys_data(struct device *dev)
+{
+	struct pm_subsys_data *psd;
+	int ret = 0;
+
+	spin_lock_irq(&dev->power.lock);
+
+	psd = dev_to_psd(dev);
+	if (!psd) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (--psd->refcount == 0) {
+		dev->power.subsys_data = NULL;
+		kfree(psd);
+		ret = 1;
+	}
+
+ out:
+	spin_unlock_irq(&dev->power.lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_put_subsys_data);
diff -druN linux-libre-3.1-gnu/drivers/base/power/domain.c linux-libre-3.2-gnu/drivers/base/power/domain.c
--- linux-libre-3.1-gnu/drivers/base/power/domain.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/power/domain.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,10 +29,20 @@
 	return pd_to_genpd(dev->pm_domain);
 }
 
-static void genpd_sd_counter_dec(struct generic_pm_domain *genpd)
+static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd)
 {
-	if (!WARN_ON(genpd->sd_count == 0))
-			genpd->sd_count--;
+	bool ret = false;
+
+	if (!WARN_ON(atomic_read(&genpd->sd_count) == 0))
+		ret = !!atomic_dec_and_test(&genpd->sd_count);
+
+	return ret;
+}
+
+static void genpd_sd_counter_inc(struct generic_pm_domain *genpd)
+{
+	atomic_inc(&genpd->sd_count);
+	smp_mb__after_atomic_inc();
 }
 
 static void genpd_acquire_lock(struct generic_pm_domain *genpd)
@@ -71,60 +81,97 @@
 }
 
 /**
- * pm_genpd_poweron - Restore power to a given PM domain and its parents.
+ * __pm_genpd_poweron - Restore power to a given PM domain and its masters.
  * @genpd: PM domain to power up.
  *
- * Restore power to @genpd and all of its parents so that it is possible to
+ * Restore power to @genpd and all of its masters so that it is possible to
  * resume a device belonging to it.
  */
-int pm_genpd_poweron(struct generic_pm_domain *genpd)
+int __pm_genpd_poweron(struct generic_pm_domain *genpd)
+	__releases(&genpd->lock) __acquires(&genpd->lock)
 {
-	struct generic_pm_domain *parent = genpd->parent;
+	struct gpd_link *link;
+	DEFINE_WAIT(wait);
 	int ret = 0;
 
- start:
-	if (parent) {
-		genpd_acquire_lock(parent);
-		mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
-	} else {
+	/* If the domain's master is being waited for, we have to wait too. */
+	for (;;) {
+		prepare_to_wait(&genpd->status_wait_queue, &wait,
+				TASK_UNINTERRUPTIBLE);
+		if (genpd->status != GPD_STATE_WAIT_MASTER)
+			break;
+		mutex_unlock(&genpd->lock);
+
+		schedule();
+
 		mutex_lock(&genpd->lock);
 	}
+	finish_wait(&genpd->status_wait_queue, &wait);
 
 	if (genpd->status == GPD_STATE_ACTIVE
 	    || (genpd->prepared_count > 0 && genpd->suspend_power_off))
-		goto out;
+		return 0;
 
 	if (genpd->status != GPD_STATE_POWER_OFF) {
 		genpd_set_active(genpd);
-		goto out;
+		return 0;
 	}
 
-	if (parent && parent->status != GPD_STATE_ACTIVE) {
+	/*
+	 * The list is guaranteed not to change while the loop below is being
+	 * executed, unless one of the masters' .power_on() callbacks fiddles
+	 * with it.
+	 */
+	list_for_each_entry(link, &genpd->slave_links, slave_node) {
+		genpd_sd_counter_inc(link->master);
+		genpd->status = GPD_STATE_WAIT_MASTER;
+
 		mutex_unlock(&genpd->lock);
-		genpd_release_lock(parent);
 
-		ret = pm_genpd_poweron(parent);
-		if (ret)
-			return ret;
+		ret = pm_genpd_poweron(link->master);
 
-		goto start;
+		mutex_lock(&genpd->lock);
+
+		/*
+		 * The "wait for parent" status is guaranteed not to change
+		 * while the master is powering on.
+		 */
+		genpd->status = GPD_STATE_POWER_OFF;
+		wake_up_all(&genpd->status_wait_queue);
+		if (ret) {
+			genpd_sd_counter_dec(link->master);
+			goto err;
+		}
 	}
 
 	if (genpd->power_on) {
 		ret = genpd->power_on(genpd);
 		if (ret)
-			goto out;
+			goto err;
 	}
 
 	genpd_set_active(genpd);
-	if (parent)
-		parent->sd_count++;
 
- out:
-	mutex_unlock(&genpd->lock);
-	if (parent)
-		genpd_release_lock(parent);
+	return 0;
+
+ err:
+	list_for_each_entry_continue_reverse(link, &genpd->slave_links, slave_node)
+		genpd_sd_counter_dec(link->master);
+
+	return ret;
+}
 
+/**
+ * pm_genpd_poweron - Restore power to a given PM domain and its masters.
+ * @genpd: PM domain to power up.
+ */
+int pm_genpd_poweron(struct generic_pm_domain *genpd)
+{
+	int ret;
+
+	mutex_lock(&genpd->lock);
+	ret = __pm_genpd_poweron(genpd);
+	mutex_unlock(&genpd->lock);
 	return ret;
 }
 
@@ -134,18 +181,19 @@
 
 /**
  * __pm_genpd_save_device - Save the pre-suspend state of a device.
- * @dle: Device list entry of the device to save the state of.
+ * @pdd: Domain data of the device to save the state of.
  * @genpd: PM domain the device belongs to.
  */
-static int __pm_genpd_save_device(struct dev_list_entry *dle,
+static int __pm_genpd_save_device(struct pm_domain_data *pdd,
 				  struct generic_pm_domain *genpd)
 	__releases(&genpd->lock) __acquires(&genpd->lock)
 {
-	struct device *dev = dle->dev;
+	struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
+	struct device *dev = pdd->dev;
 	struct device_driver *drv = dev->driver;
 	int ret = 0;
 
-	if (dle->need_restore)
+	if (gpd_data->need_restore)
 		return 0;
 
 	mutex_unlock(&genpd->lock);
@@ -163,24 +211,25 @@
 	mutex_lock(&genpd->lock);
 
 	if (!ret)
-		dle->need_restore = true;
+		gpd_data->need_restore = true;
 
 	return ret;
 }
 
 /**
  * __pm_genpd_restore_device - Restore the pre-suspend state of a device.
- * @dle: Device list entry of the device to restore the state of.
+ * @pdd: Domain data of the device to restore the state of.
  * @genpd: PM domain the device belongs to.
  */
-static void __pm_genpd_restore_device(struct dev_list_entry *dle,
+static void __pm_genpd_restore_device(struct pm_domain_data *pdd,
 				      struct generic_pm_domain *genpd)
 	__releases(&genpd->lock) __acquires(&genpd->lock)
 {
-	struct device *dev = dle->dev;
+	struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
+	struct device *dev = pdd->dev;
 	struct device_driver *drv = dev->driver;
 
-	if (!dle->need_restore)
+	if (!gpd_data->need_restore)
 		return;
 
 	mutex_unlock(&genpd->lock);
@@ -197,7 +246,7 @@
 
 	mutex_lock(&genpd->lock);
 
-	dle->need_restore = false;
+	gpd_data->need_restore = false;
 }
 
 /**
@@ -211,7 +260,8 @@
  */
 static bool genpd_abort_poweroff(struct generic_pm_domain *genpd)
 {
-	return genpd->status == GPD_STATE_ACTIVE || genpd->resume_count > 0;
+	return genpd->status == GPD_STATE_WAIT_MASTER
+		|| genpd->status == GPD_STATE_ACTIVE || genpd->resume_count > 0;
 }
 
 /**
@@ -238,8 +288,8 @@
 static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
 	__releases(&genpd->lock) __acquires(&genpd->lock)
 {
-	struct generic_pm_domain *parent;
-	struct dev_list_entry *dle;
+	struct pm_domain_data *pdd;
+	struct gpd_link *link;
 	unsigned int not_suspended;
 	int ret = 0;
 
@@ -247,19 +297,22 @@
 	/*
 	 * Do not try to power off the domain in the following situations:
 	 * (1) The domain is already in the "power off" state.
-	 * (2) System suspend is in progress.
+	 * (2) The domain is waiting for its master to power up.
 	 * (3) One of the domain's devices is being resumed right now.
+	 * (4) System suspend is in progress.
 	 */
-	if (genpd->status == GPD_STATE_POWER_OFF || genpd->prepared_count > 0
-	    || genpd->resume_count > 0)
+	if (genpd->status == GPD_STATE_POWER_OFF
+	    || genpd->status == GPD_STATE_WAIT_MASTER
+	    || genpd->resume_count > 0 || genpd->prepared_count > 0)
 		return 0;
 
-	if (genpd->sd_count > 0)
+	if (atomic_read(&genpd->sd_count) > 0)
 		return -EBUSY;
 
 	not_suspended = 0;
-	list_for_each_entry(dle, &genpd->dev_list, node)
-		if (dle->dev->driver && !pm_runtime_suspended(dle->dev))
+	list_for_each_entry(pdd, &genpd->dev_list, list_node)
+		if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev)
+		    || pdd->dev->power.irq_safe))
 			not_suspended++;
 
 	if (not_suspended > genpd->in_progress)
@@ -282,54 +335,50 @@
 	genpd->status = GPD_STATE_BUSY;
 	genpd->poweroff_task = current;
 
-	list_for_each_entry_reverse(dle, &genpd->dev_list, node) {
-		ret = __pm_genpd_save_device(dle, genpd);
+	list_for_each_entry_reverse(pdd, &genpd->dev_list, list_node) {
+		ret = atomic_read(&genpd->sd_count) == 0 ?
+			__pm_genpd_save_device(pdd, genpd) : -EBUSY;
+
+		if (genpd_abort_poweroff(genpd))
+			goto out;
+
 		if (ret) {
 			genpd_set_active(genpd);
 			goto out;
 		}
 
-		if (genpd_abort_poweroff(genpd))
-			goto out;
-
 		if (genpd->status == GPD_STATE_REPEAT) {
 			genpd->poweroff_task = NULL;
 			goto start;
 		}
 	}
 
-	parent = genpd->parent;
-	if (parent) {
-		mutex_unlock(&genpd->lock);
-
-		genpd_acquire_lock(parent);
-		mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
-
-		if (genpd_abort_poweroff(genpd)) {
-			genpd_release_lock(parent);
+	if (genpd->power_off) {
+		if (atomic_read(&genpd->sd_count) > 0) {
+			ret = -EBUSY;
 			goto out;
 		}
-	}
 
-	if (genpd->power_off) {
+		/*
+		 * If sd_count > 0 at this point, one of the subdomains hasn't
+		 * managed to call pm_genpd_poweron() for the master yet after
+		 * incrementing it.  In that case pm_genpd_poweron() will wait
+		 * for us to drop the lock, so we can call .power_off() and let
+		 * the pm_genpd_poweron() restore power for us (this shouldn't
+		 * happen very often).
+		 */
 		ret = genpd->power_off(genpd);
 		if (ret == -EBUSY) {
 			genpd_set_active(genpd);
-			if (parent)
-				genpd_release_lock(parent);
-
 			goto out;
 		}
 	}
 
 	genpd->status = GPD_STATE_POWER_OFF;
 
-	if (parent) {
-		genpd_sd_counter_dec(parent);
-		if (parent->sd_count == 0)
-			genpd_queue_power_off_work(parent);
-
-		genpd_release_lock(parent);
+	list_for_each_entry(link, &genpd->slave_links, slave_node) {
+		genpd_sd_counter_dec(link->master);
+		genpd_queue_power_off_work(link->master);
 	}
 
  out:
@@ -371,12 +420,21 @@
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
+	might_sleep_if(!genpd->dev_irq_safe);
+
 	if (genpd->stop_device) {
 		int ret = genpd->stop_device(dev);
 		if (ret)
 			return ret;
 	}
 
+	/*
+	 * If power.irq_safe is set, this routine will be run with interrupts
+	 * off, so it can't use mutexes.
+	 */
+	if (dev->power.irq_safe)
+		return 0;
+
 	mutex_lock(&genpd->lock);
 	genpd->in_progress++;
 	pm_genpd_poweroff(genpd);
@@ -387,24 +445,6 @@
 }
 
 /**
- * __pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain.
- * @dev: Device to resume.
- * @genpd: PM domain the device belongs to.
- */
-static void __pm_genpd_runtime_resume(struct device *dev,
-				      struct generic_pm_domain *genpd)
-{
-	struct dev_list_entry *dle;
-
-	list_for_each_entry(dle, &genpd->dev_list, node) {
-		if (dle->dev == dev) {
-			__pm_genpd_restore_device(dle, genpd);
-			break;
-		}
-	}
-}
-
-/**
  * pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain.
  * @dev: Device to resume.
  *
@@ -424,11 +464,18 @@
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
-	ret = pm_genpd_poweron(genpd);
-	if (ret)
-		return ret;
+	might_sleep_if(!genpd->dev_irq_safe);
+
+	/* If power.irq_safe, the PM domain is never powered off. */
+	if (dev->power.irq_safe)
+		goto out;
 
 	mutex_lock(&genpd->lock);
+	ret = __pm_genpd_poweron(genpd);
+	if (ret) {
+		mutex_unlock(&genpd->lock);
+		return ret;
+	}
 	genpd->status = GPD_STATE_BUSY;
 	genpd->resume_count++;
 	for (;;) {
@@ -448,12 +495,13 @@
 		mutex_lock(&genpd->lock);
 	}
 	finish_wait(&genpd->status_wait_queue, &wait);
-	__pm_genpd_runtime_resume(dev, genpd);
+	__pm_genpd_restore_device(dev->power.subsys_data->domain_data, genpd);
 	genpd->resume_count--;
 	genpd_set_active(genpd);
 	wake_up_all(&genpd->status_wait_queue);
 	mutex_unlock(&genpd->lock);
 
+ out:
 	if (genpd->start_device)
 		genpd->start_device(dev);
 
@@ -478,8 +526,6 @@
 #else
 
 static inline void genpd_power_off_work_fn(struct work_struct *work) {}
-static inline void __pm_genpd_runtime_resume(struct device *dev,
-					     struct generic_pm_domain *genpd) {}
 
 #define pm_genpd_runtime_suspend	NULL
 #define pm_genpd_runtime_resume		NULL
@@ -489,11 +535,11 @@
 #ifdef CONFIG_PM_SLEEP
 
 /**
- * pm_genpd_sync_poweroff - Synchronously power off a PM domain and its parents.
+ * pm_genpd_sync_poweroff - Synchronously power off a PM domain and its masters.
  * @genpd: PM domain to power off, if possible.
  *
  * Check if the given PM domain can be powered off (during system suspend or
- * hibernation) and do that if so.  Also, in that case propagate to its parent.
+ * hibernation) and do that if so.  Also, in that case propagate to its masters.
  *
  * This function is only called in "noirq" stages of system power transitions,
  * so it need not acquire locks (all of the "noirq" callbacks are executed
@@ -501,21 +547,23 @@
  */
 static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
 {
-	struct generic_pm_domain *parent = genpd->parent;
+	struct gpd_link *link;
 
 	if (genpd->status == GPD_STATE_POWER_OFF)
 		return;
 
-	if (genpd->suspended_count != genpd->device_count || genpd->sd_count > 0)
+	if (genpd->suspended_count != genpd->device_count
+	    || atomic_read(&genpd->sd_count) > 0)
 		return;
 
 	if (genpd->power_off)
 		genpd->power_off(genpd);
 
 	genpd->status = GPD_STATE_POWER_OFF;
-	if (parent) {
-		genpd_sd_counter_dec(parent);
-		pm_genpd_sync_poweroff(parent);
+
+	list_for_each_entry(link, &genpd->slave_links, slave_node) {
+		genpd_sd_counter_dec(link->master);
+		pm_genpd_sync_poweroff(link->master);
 	}
 }
 
@@ -666,7 +714,7 @@
 	if (ret)
 		return ret;
 
-	if (device_may_wakeup(dev)
+	if (dev->power.wakeup_path
 	    && genpd->active_wakeup && genpd->active_wakeup(dev))
 		return 0;
 
@@ -890,7 +938,7 @@
 	if (ret)
 		return ret;
 
-	if (device_may_wakeup(dev)
+	if (dev->power.wakeup_path
 	    && genpd->active_wakeup && genpd->active_wakeup(dev))
 		return 0;
 
@@ -1034,7 +1082,8 @@
  */
 int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev)
 {
-	struct dev_list_entry *dle;
+	struct generic_pm_domain_data *gpd_data;
+	struct pm_domain_data *pdd;
 	int ret = 0;
 
 	dev_dbg(dev, "%s()\n", __func__);
@@ -1054,26 +1103,26 @@
 		goto out;
 	}
 
-	list_for_each_entry(dle, &genpd->dev_list, node)
-		if (dle->dev == dev) {
+	list_for_each_entry(pdd, &genpd->dev_list, list_node)
+		if (pdd->dev == dev) {
 			ret = -EINVAL;
 			goto out;
 		}
 
-	dle = kzalloc(sizeof(*dle), GFP_KERNEL);
-	if (!dle) {
+	gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL);
+	if (!gpd_data) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	dle->dev = dev;
-	dle->need_restore = false;
-	list_add_tail(&dle->node, &genpd->dev_list);
 	genpd->device_count++;
 
-	spin_lock_irq(&dev->power.lock);
 	dev->pm_domain = &genpd->domain;
-	spin_unlock_irq(&dev->power.lock);
+	dev_pm_get_subsys_data(dev);
+	dev->power.subsys_data->domain_data = &gpd_data->base;
+	gpd_data->base.dev = dev;
+	gpd_data->need_restore = false;
+	list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
 
  out:
 	genpd_release_lock(genpd);
@@ -1089,7 +1138,7 @@
 int pm_genpd_remove_device(struct generic_pm_domain *genpd,
 			   struct device *dev)
 {
-	struct dev_list_entry *dle;
+	struct pm_domain_data *pdd;
 	int ret = -EINVAL;
 
 	dev_dbg(dev, "%s()\n", __func__);
@@ -1104,17 +1153,17 @@
 		goto out;
 	}
 
-	list_for_each_entry(dle, &genpd->dev_list, node) {
-		if (dle->dev != dev)
+	list_for_each_entry(pdd, &genpd->dev_list, list_node) {
+		if (pdd->dev != dev)
 			continue;
 
-		spin_lock_irq(&dev->power.lock);
+		list_del_init(&pdd->list_node);
+		pdd->dev = NULL;
+		dev_pm_put_subsys_data(dev);
 		dev->pm_domain = NULL;
-		spin_unlock_irq(&dev->power.lock);
+		kfree(to_gpd_data(pdd));
 
 		genpd->device_count--;
-		list_del(&dle->node);
-		kfree(dle);
 
 		ret = 0;
 		break;
@@ -1129,48 +1178,55 @@
 /**
  * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
  * @genpd: Master PM domain to add the subdomain to.
- * @new_subdomain: Subdomain to be added.
+ * @subdomain: Subdomain to be added.
  */
 int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
-			   struct generic_pm_domain *new_subdomain)
+			   struct generic_pm_domain *subdomain)
 {
-	struct generic_pm_domain *subdomain;
+	struct gpd_link *link;
 	int ret = 0;
 
-	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(new_subdomain))
+	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
 		return -EINVAL;
 
  start:
 	genpd_acquire_lock(genpd);
-	mutex_lock_nested(&new_subdomain->lock, SINGLE_DEPTH_NESTING);
+	mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
 
-	if (new_subdomain->status != GPD_STATE_POWER_OFF
-	    && new_subdomain->status != GPD_STATE_ACTIVE) {
-		mutex_unlock(&new_subdomain->lock);
+	if (subdomain->status != GPD_STATE_POWER_OFF
+	    && subdomain->status != GPD_STATE_ACTIVE) {
+		mutex_unlock(&subdomain->lock);
 		genpd_release_lock(genpd);
 		goto start;
 	}
 
 	if (genpd->status == GPD_STATE_POWER_OFF
-	    &&  new_subdomain->status != GPD_STATE_POWER_OFF) {
+	    &&  subdomain->status != GPD_STATE_POWER_OFF) {
 		ret = -EINVAL;
 		goto out;
 	}
 
-	list_for_each_entry(subdomain, &genpd->sd_list, sd_node) {
-		if (subdomain == new_subdomain) {
+	list_for_each_entry(link, &genpd->slave_links, slave_node) {
+		if (link->slave == subdomain && link->master == genpd) {
 			ret = -EINVAL;
 			goto out;
 		}
 	}
 
-	list_add_tail(&new_subdomain->sd_node, &genpd->sd_list);
-	new_subdomain->parent = genpd;
+	link = kzalloc(sizeof(*link), GFP_KERNEL);
+	if (!link) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	link->master = genpd;
+	list_add_tail(&link->master_node, &genpd->master_links);
+	link->slave = subdomain;
+	list_add_tail(&link->slave_node, &subdomain->slave_links);
 	if (subdomain->status != GPD_STATE_POWER_OFF)
-		genpd->sd_count++;
+		genpd_sd_counter_inc(genpd);
 
  out:
-	mutex_unlock(&new_subdomain->lock);
+	mutex_unlock(&subdomain->lock);
 	genpd_release_lock(genpd);
 
 	return ret;
@@ -1179,22 +1235,22 @@
 /**
  * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
  * @genpd: Master PM domain to remove the subdomain from.
- * @target: Subdomain to be removed.
+ * @subdomain: Subdomain to be removed.
  */
 int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
-			      struct generic_pm_domain *target)
+			      struct generic_pm_domain *subdomain)
 {
-	struct generic_pm_domain *subdomain;
+	struct gpd_link *link;
 	int ret = -EINVAL;
 
-	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(target))
+	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
 		return -EINVAL;
 
  start:
 	genpd_acquire_lock(genpd);
 
-	list_for_each_entry(subdomain, &genpd->sd_list, sd_node) {
-		if (subdomain != target)
+	list_for_each_entry(link, &genpd->master_links, master_node) {
+		if (link->slave != subdomain)
 			continue;
 
 		mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
@@ -1206,8 +1262,9 @@
 			goto start;
 		}
 
-		list_del(&subdomain->sd_node);
-		subdomain->parent = NULL;
+		list_del(&link->master_node);
+		list_del(&link->slave_node);
+		kfree(link);
 		if (subdomain->status != GPD_STATE_POWER_OFF)
 			genpd_sd_counter_dec(genpd);
 
@@ -1234,15 +1291,14 @@
 	if (IS_ERR_OR_NULL(genpd))
 		return;
 
-	INIT_LIST_HEAD(&genpd->sd_node);
-	genpd->parent = NULL;
+	INIT_LIST_HEAD(&genpd->master_links);
+	INIT_LIST_HEAD(&genpd->slave_links);
 	INIT_LIST_HEAD(&genpd->dev_list);
-	INIT_LIST_HEAD(&genpd->sd_list);
 	mutex_init(&genpd->lock);
 	genpd->gov = gov;
 	INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
 	genpd->in_progress = 0;
-	genpd->sd_count = 0;
+	atomic_set(&genpd->sd_count, 0);
 	genpd->status = is_off ? GPD_STATE_POWER_OFF : GPD_STATE_ACTIVE;
 	init_waitqueue_head(&genpd->status_wait_queue);
 	genpd->poweroff_task = NULL;
diff -druN linux-libre-3.1-gnu/drivers/base/power/generic_ops.c linux-libre-3.2-gnu/drivers/base/power/generic_ops.c
--- linux-libre-3.1-gnu/drivers/base/power/generic_ops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/power/generic_ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
+#include <linux/export.h>
 
 #ifdef CONFIG_PM_RUNTIME
 /**
diff -druN linux-libre-3.1-gnu/drivers/base/power/main.c linux-libre-3.2-gnu/drivers/base/power/main.c
--- linux-libre-3.1-gnu/drivers/base/power/main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/power/main.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 
 #include <linux/device.h>
 #include <linux/kallsyms.h>
+#include <linux/export.h>
 #include <linux/mutex.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
@@ -46,6 +47,7 @@
 LIST_HEAD(dpm_suspended_list);
 LIST_HEAD(dpm_noirq_list);
 
+struct suspend_stats suspend_stats;
 static DEFINE_MUTEX(dpm_list_mtx);
 static pm_message_t pm_transition;
 
@@ -65,6 +67,7 @@
 	spin_lock_init(&dev->power.lock);
 	pm_runtime_init(dev);
 	INIT_LIST_HEAD(&dev->power.entry);
+	dev->power.power_state = PMSG_INVALID;
 }
 
 /**
@@ -96,6 +99,7 @@
 		dev_warn(dev, "parent %s should not be sleeping\n",
 			dev_name(dev->parent));
 	list_add_tail(&dev->power.entry, &dpm_list);
+	dev_pm_qos_constraints_init(dev);
 	mutex_unlock(&dpm_list_mtx);
 }
 
@@ -109,6 +113,7 @@
 		 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
 	complete_all(&dev->power.completion);
 	mutex_lock(&dpm_list_mtx);
+	dev_pm_qos_constraints_destroy(dev);
 	list_del_init(&dev->power.entry);
 	mutex_unlock(&dpm_list_mtx);
 	device_wakeup_disable(dev);
@@ -464,8 +469,12 @@
 		mutex_unlock(&dpm_list_mtx);
 
 		error = device_resume_noirq(dev, state);
-		if (error)
+		if (error) {
+			suspend_stats.failed_resume_noirq++;
+			dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
+			dpm_save_failed_dev(dev_name(dev));
 			pm_dev_err(dev, state, " early", error);
+		}
 
 		mutex_lock(&dpm_list_mtx);
 		put_device(dev);
@@ -626,8 +635,12 @@
 			mutex_unlock(&dpm_list_mtx);
 
 			error = device_resume(dev, state, false);
-			if (error)
+			if (error) {
+				suspend_stats.failed_resume++;
+				dpm_save_failed_step(SUSPEND_RESUME);
+				dpm_save_failed_dev(dev_name(dev));
 				pm_dev_err(dev, state, "", error);
+			}
 
 			mutex_lock(&dpm_list_mtx);
 		}
@@ -802,6 +815,9 @@
 		mutex_lock(&dpm_list_mtx);
 		if (error) {
 			pm_dev_err(dev, state, " late", error);
+			suspend_stats.failed_suspend_noirq++;
+			dpm_save_failed_step(SUSPEND_SUSPEND_NOIRQ);
+			dpm_save_failed_dev(dev_name(dev));
 			put_device(dev);
 			break;
 		}
@@ -902,7 +918,12 @@
 	}
 
  End:
-	dev->power.is_suspended = !error;
+	if (!error) {
+		dev->power.is_suspended = true;
+		if (dev->power.wakeup_path
+		    && dev->parent && !dev->parent->power.ignore_children)
+			dev->parent->power.wakeup_path = true;
+	}
 
 	device_unlock(dev);
 	complete_all(&dev->power.completion);
@@ -923,8 +944,10 @@
 	int error;
 
 	error = __device_suspend(dev, pm_transition, true);
-	if (error)
+	if (error) {
+		dpm_save_failed_dev(dev_name(dev));
 		pm_dev_err(dev, pm_transition, " async", error);
+	}
 
 	put_device(dev);
 }
@@ -967,6 +990,7 @@
 		mutex_lock(&dpm_list_mtx);
 		if (error) {
 			pm_dev_err(dev, state, "", error);
+			dpm_save_failed_dev(dev_name(dev));
 			put_device(dev);
 			break;
 		}
@@ -980,7 +1004,10 @@
 	async_synchronize_full();
 	if (!error)
 		error = async_error;
-	if (!error)
+	if (error) {
+		suspend_stats.failed_suspend++;
+		dpm_save_failed_step(SUSPEND_SUSPEND);
+	} else
 		dpm_show_time(starttime, state, NULL);
 	return error;
 }
@@ -999,6 +1026,8 @@
 
 	device_lock(dev);
 
+	dev->power.wakeup_path = device_may_wakeup(dev);
+
 	if (dev->pm_domain) {
 		pm_dev_dbg(dev, state, "preparing power domain ");
 		if (dev->pm_domain->ops.prepare)
@@ -1088,7 +1117,10 @@
 	int error;
 
 	error = dpm_prepare(state);
-	if (!error)
+	if (error) {
+		suspend_stats.failed_prepare++;
+		dpm_save_failed_step(SUSPEND_PREPARE);
+	} else
 		error = dpm_suspend(state);
 	return error;
 }
diff -druN linux-libre-3.1-gnu/drivers/base/power/Makefile linux-libre-3.2-gnu/drivers/base/power/Makefile
--- linux-libre-3.1-gnu/drivers/base/power/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/power/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-obj-$(CONFIG_PM)	+= sysfs.o generic_ops.o
+obj-$(CONFIG_PM)	+= sysfs.o generic_ops.o common.o qos.o
 obj-$(CONFIG_PM_SLEEP)	+= main.o wakeup.o
 obj-$(CONFIG_PM_RUNTIME)	+= runtime.o
 obj-$(CONFIG_PM_TRACE_RTC)	+= trace.o
@@ -6,4 +6,4 @@
 obj-$(CONFIG_PM_GENERIC_DOMAINS)	+=  domain.o
 obj-$(CONFIG_HAVE_CLK)	+= clock_ops.o
 
-ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
\ No newline at end of file
+ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
diff -druN linux-libre-3.1-gnu/drivers/base/power/opp.c linux-libre-3.2-gnu/drivers/base/power/opp.c
--- linux-libre-3.1-gnu/drivers/base/power/opp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/power/opp.c	2012-01-04 18:55:44.000000000 -0500
@@ -73,6 +73,7 @@
  *		RCU usage: nodes are not modified in the list of device_opp,
  *		however addition is possible and is secured by dev_opp_list_lock
  * @dev:	device pointer
+ * @head:	notifier head to notify the OPP availability changes.
  * @opp_list:	list of opps
  *
  * This is an internal data structure maintaining the link to opps attached to
@@ -83,6 +84,7 @@
 	struct list_head node;
 
 	struct device *dev;
+	struct srcu_notifier_head head;
 	struct list_head opp_list;
 };
 
@@ -404,6 +406,7 @@
 		}
 
 		dev_opp->dev = dev;
+		srcu_init_notifier_head(&dev_opp->head);
 		INIT_LIST_HEAD(&dev_opp->opp_list);
 
 		/* Secure the device list modification */
@@ -428,6 +431,11 @@
 	list_add_rcu(&new_opp->node, head);
 	mutex_unlock(&dev_opp_list_lock);
 
+	/*
+	 * Notify the changes in the availability of the operable
+	 * frequency/voltage list.
+	 */
+	srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ADD, new_opp);
 	return 0;
 }
 
@@ -504,6 +512,14 @@
 	mutex_unlock(&dev_opp_list_lock);
 	synchronize_rcu();
 
+	/* Notify the change of the OPP availability */
+	if (availability_req)
+		srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ENABLE,
+					 new_opp);
+	else
+		srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_DISABLE,
+					 new_opp);
+
 	/* clean up old opp */
 	new_opp = opp;
 	goto out;
@@ -643,3 +659,17 @@
 	*table = NULL;
 }
 #endif		/* CONFIG_CPU_FREQ */
+
+/**
+ * opp_get_notifier() - find notifier_head of the device with opp
+ * @dev:	device pointer used to lookup device OPPs.
+ */
+struct srcu_notifier_head *opp_get_notifier(struct device *dev)
+{
+	struct device_opp *dev_opp = find_device_opp(dev);
+
+	if (IS_ERR(dev_opp))
+		return ERR_CAST(dev_opp); /* matching type */
+
+	return &dev_opp->head;
+}
diff -druN linux-libre-3.1-gnu/drivers/base/power/power.h linux-libre-3.2-gnu/drivers/base/power/power.h
--- linux-libre-3.1-gnu/drivers/base/power/power.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/power/power.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,5 @@
+#include <linux/pm_qos.h>
+
 #ifdef CONFIG_PM_RUNTIME
 
 extern void pm_runtime_init(struct device *dev);
@@ -35,15 +37,21 @@
 static inline void device_pm_init(struct device *dev)
 {
 	spin_lock_init(&dev->power.lock);
+	dev->power.power_state = PMSG_INVALID;
 	pm_runtime_init(dev);
 }
 
+static inline void device_pm_add(struct device *dev)
+{
+	dev_pm_qos_constraints_init(dev);
+}
+
 static inline void device_pm_remove(struct device *dev)
 {
+	dev_pm_qos_constraints_destroy(dev);
 	pm_runtime_remove(dev);
 }
 
-static inline void device_pm_add(struct device *dev) {}
 static inline void device_pm_move_before(struct device *deva,
 					 struct device *devb) {}
 static inline void device_pm_move_after(struct device *deva,
diff -druN linux-libre-3.1-gnu/drivers/base/power/qos.c linux-libre-3.2-gnu/drivers/base/power/qos.c
--- linux-libre-3.1-gnu/drivers/base/power/qos.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/base/power/qos.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,414 @@
+/*
+ * Devices PM QoS constraints management
+ *
+ * Copyright (C) 2011 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ *
+ * This module exposes the interface to kernel space for specifying
+ * per-device PM QoS dependencies. It provides infrastructure for registration
+ * of:
+ *
+ * Dependents on a QoS value : register requests
+ * Watchers of QoS value : get notified when target QoS value changes
+ *
+ * This QoS design is best effort based. Dependents register their QoS needs.
+ * Watchers register to keep track of the current QoS needs of the system.
+ * Watchers can register different types of notification callbacks:
+ *  . a per-device notification callback using the dev_pm_qos_*_notifier API.
+ *    The notification chain data is stored in the per-device constraint
+ *    data struct.
+ *  . a system-wide notification callback using the dev_pm_qos_*_global_notifier
+ *    API. The notification chain data is stored in a static variable.
+ *
+ * Note about the per-device constraint data struct allocation:
+ * . The per-device constraints data struct ptr is tored into the device
+ *    dev_pm_info.
+ * . To minimize the data usage by the per-device constraints, the data struct
+ *   is only allocated at the first call to dev_pm_qos_add_request.
+ * . The data is later free'd when the device is removed from the system.
+ *  . A global mutex protects the constraints users from the data being
+ *     allocated and free'd.
+ */
+
+#include <linux/pm_qos.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/export.h>
+
+
+static DEFINE_MUTEX(dev_pm_qos_mtx);
+
+static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
+
+/**
+ * dev_pm_qos_read_value - Get PM QoS constraint for a given device.
+ * @dev: Device to get the PM QoS constraint value for.
+ */
+s32 dev_pm_qos_read_value(struct device *dev)
+{
+	struct pm_qos_constraints *c;
+	unsigned long flags;
+	s32 ret = 0;
+
+	spin_lock_irqsave(&dev->power.lock, flags);
+
+	c = dev->power.constraints;
+	if (c)
+		ret = pm_qos_read_value(c);
+
+	spin_unlock_irqrestore(&dev->power.lock, flags);
+
+	return ret;
+}
+
+/*
+ * apply_constraint
+ * @req: constraint request to apply
+ * @action: action to perform add/update/remove, of type enum pm_qos_req_action
+ * @value: defines the qos request
+ *
+ * Internal function to update the constraints list using the PM QoS core
+ * code and if needed call the per-device and the global notification
+ * callbacks
+ */
+static int apply_constraint(struct dev_pm_qos_request *req,
+			    enum pm_qos_req_action action, int value)
+{
+	int ret, curr_value;
+
+	ret = pm_qos_update_target(req->dev->power.constraints,
+				   &req->node, action, value);
+
+	if (ret) {
+		/* Call the global callbacks if needed */
+		curr_value = pm_qos_read_value(req->dev->power.constraints);
+		blocking_notifier_call_chain(&dev_pm_notifiers,
+					     (unsigned long)curr_value,
+					     req);
+	}
+
+	return ret;
+}
+
+/*
+ * dev_pm_qos_constraints_allocate
+ * @dev: device to allocate data for
+ *
+ * Called at the first call to add_request, for constraint data allocation
+ * Must be called with the dev_pm_qos_mtx mutex held
+ */
+static int dev_pm_qos_constraints_allocate(struct device *dev)
+{
+	struct pm_qos_constraints *c;
+	struct blocking_notifier_head *n;
+
+	c = kzalloc(sizeof(*c), GFP_KERNEL);
+	if (!c)
+		return -ENOMEM;
+
+	n = kzalloc(sizeof(*n), GFP_KERNEL);
+	if (!n) {
+		kfree(c);
+		return -ENOMEM;
+	}
+	BLOCKING_INIT_NOTIFIER_HEAD(n);
+
+	plist_head_init(&c->list);
+	c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
+	c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
+	c->type = PM_QOS_MIN;
+	c->notifiers = n;
+
+	spin_lock_irq(&dev->power.lock);
+	dev->power.constraints = c;
+	spin_unlock_irq(&dev->power.lock);
+
+	return 0;
+}
+
+/**
+ * dev_pm_qos_constraints_init - Initalize device's PM QoS constraints pointer.
+ * @dev: target device
+ *
+ * Called from the device PM subsystem during device insertion under
+ * device_pm_lock().
+ */
+void dev_pm_qos_constraints_init(struct device *dev)
+{
+	mutex_lock(&dev_pm_qos_mtx);
+	dev->power.constraints = NULL;
+	dev->power.power_state = PMSG_ON;
+	mutex_unlock(&dev_pm_qos_mtx);
+}
+
+/**
+ * dev_pm_qos_constraints_destroy
+ * @dev: target device
+ *
+ * Called from the device PM subsystem on device removal under device_pm_lock().
+ */
+void dev_pm_qos_constraints_destroy(struct device *dev)
+{
+	struct dev_pm_qos_request *req, *tmp;
+	struct pm_qos_constraints *c;
+
+	mutex_lock(&dev_pm_qos_mtx);
+
+	dev->power.power_state = PMSG_INVALID;
+	c = dev->power.constraints;
+	if (!c)
+		goto out;
+
+	/* Flush the constraints list for the device */
+	plist_for_each_entry_safe(req, tmp, &c->list, node) {
+		/*
+		 * Update constraints list and call the notification
+		 * callbacks if needed
+		 */
+		apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
+		memset(req, 0, sizeof(*req));
+	}
+
+	spin_lock_irq(&dev->power.lock);
+	dev->power.constraints = NULL;
+	spin_unlock_irq(&dev->power.lock);
+
+	kfree(c->notifiers);
+	kfree(c);
+
+ out:
+	mutex_unlock(&dev_pm_qos_mtx);
+}
+
+/**
+ * dev_pm_qos_add_request - inserts new qos request into the list
+ * @dev: target device for the constraint
+ * @req: pointer to a preallocated handle
+ * @value: defines the qos request
+ *
+ * This function inserts a new entry in the device constraints list of
+ * requested qos performance characteristics. It recomputes the aggregate
+ * QoS expectations of parameters and initializes the dev_pm_qos_request
+ * handle.  Caller needs to save this handle for later use in updates and
+ * removal.
+ *
+ * Returns 1 if the aggregated constraint value has changed,
+ * 0 if the aggregated constraint value has not changed,
+ * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory
+ * to allocate for data structures, -ENODEV if the device has just been removed
+ * from the system.
+ */
+int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
+			   s32 value)
+{
+	int ret = 0;
+
+	if (!dev || !req) /*guard against callers passing in null */
+		return -EINVAL;
+
+	if (WARN(dev_pm_qos_request_active(req),
+		 "%s() called for already added request\n", __func__))
+		return -EINVAL;
+
+	req->dev = dev;
+
+	mutex_lock(&dev_pm_qos_mtx);
+
+	if (!dev->power.constraints) {
+		if (dev->power.power_state.event == PM_EVENT_INVALID) {
+			/* The device has been removed from the system. */
+			req->dev = NULL;
+			ret = -ENODEV;
+			goto out;
+		} else {
+			/*
+			 * Allocate the constraints data on the first call to
+			 * add_request, i.e. only if the data is not already
+			 * allocated and if the device has not been removed.
+			 */
+			ret = dev_pm_qos_constraints_allocate(dev);
+		}
+	}
+
+	if (!ret)
+		ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
+
+ out:
+	mutex_unlock(&dev_pm_qos_mtx);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
+
+/**
+ * dev_pm_qos_update_request - modifies an existing qos request
+ * @req : handle to list element holding a dev_pm_qos request to use
+ * @new_value: defines the qos request
+ *
+ * Updates an existing dev PM qos request along with updating the
+ * target value.
+ *
+ * Attempts are made to make this code callable on hot code paths.
+ *
+ * Returns 1 if the aggregated constraint value has changed,
+ * 0 if the aggregated constraint value has not changed,
+ * -EINVAL in case of wrong parameters, -ENODEV if the device has been
+ * removed from the system
+ */
+int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
+			      s32 new_value)
+{
+	int ret = 0;
+
+	if (!req) /*guard against callers passing in null */
+		return -EINVAL;
+
+	if (WARN(!dev_pm_qos_request_active(req),
+		 "%s() called for unknown object\n", __func__))
+		return -EINVAL;
+
+	mutex_lock(&dev_pm_qos_mtx);
+
+	if (req->dev->power.constraints) {
+		if (new_value != req->node.prio)
+			ret = apply_constraint(req, PM_QOS_UPDATE_REQ,
+					       new_value);
+	} else {
+		/* Return if the device has been removed */
+		ret = -ENODEV;
+	}
+
+	mutex_unlock(&dev_pm_qos_mtx);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
+
+/**
+ * dev_pm_qos_remove_request - modifies an existing qos request
+ * @req: handle to request list element
+ *
+ * Will remove pm qos request from the list of constraints and
+ * recompute the current target value. Call this on slow code paths.
+ *
+ * Returns 1 if the aggregated constraint value has changed,
+ * 0 if the aggregated constraint value has not changed,
+ * -EINVAL in case of wrong parameters, -ENODEV if the device has been
+ * removed from the system
+ */
+int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
+{
+	int ret = 0;
+
+	if (!req) /*guard against callers passing in null */
+		return -EINVAL;
+
+	if (WARN(!dev_pm_qos_request_active(req),
+		 "%s() called for unknown object\n", __func__))
+		return -EINVAL;
+
+	mutex_lock(&dev_pm_qos_mtx);
+
+	if (req->dev->power.constraints) {
+		ret = apply_constraint(req, PM_QOS_REMOVE_REQ,
+				       PM_QOS_DEFAULT_VALUE);
+		memset(req, 0, sizeof(*req));
+	} else {
+		/* Return if the device has been removed */
+		ret = -ENODEV;
+	}
+
+	mutex_unlock(&dev_pm_qos_mtx);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request);
+
+/**
+ * dev_pm_qos_add_notifier - sets notification entry for changes to target value
+ * of per-device PM QoS constraints
+ *
+ * @dev: target device for the constraint
+ * @notifier: notifier block managed by caller.
+ *
+ * Will register the notifier into a notification chain that gets called
+ * upon changes to the target value for the device.
+ */
+int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
+{
+	int retval = 0;
+
+	mutex_lock(&dev_pm_qos_mtx);
+
+	/* Silently return if the constraints object is not present. */
+	if (dev->power.constraints)
+		retval = blocking_notifier_chain_register(
+				dev->power.constraints->notifiers,
+				notifier);
+
+	mutex_unlock(&dev_pm_qos_mtx);
+	return retval;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier);
+
+/**
+ * dev_pm_qos_remove_notifier - deletes notification for changes to target value
+ * of per-device PM QoS constraints
+ *
+ * @dev: target device for the constraint
+ * @notifier: notifier block to be removed.
+ *
+ * Will remove the notifier from the notification chain that gets called
+ * upon changes to the target value.
+ */
+int dev_pm_qos_remove_notifier(struct device *dev,
+			       struct notifier_block *notifier)
+{
+	int retval = 0;
+
+	mutex_lock(&dev_pm_qos_mtx);
+
+	/* Silently return if the constraints object is not present. */
+	if (dev->power.constraints)
+		retval = blocking_notifier_chain_unregister(
+				dev->power.constraints->notifiers,
+				notifier);
+
+	mutex_unlock(&dev_pm_qos_mtx);
+	return retval;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_remove_notifier);
+
+/**
+ * dev_pm_qos_add_global_notifier - sets notification entry for changes to
+ * target value of the PM QoS constraints for any device
+ *
+ * @notifier: notifier block managed by caller.
+ *
+ * Will register the notifier into a notification chain that gets called
+ * upon changes to the target value for any device.
+ */
+int dev_pm_qos_add_global_notifier(struct notifier_block *notifier)
+{
+	return blocking_notifier_chain_register(&dev_pm_notifiers, notifier);
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_add_global_notifier);
+
+/**
+ * dev_pm_qos_remove_global_notifier - deletes notification for changes to
+ * target value of PM QoS constraints for any device
+ *
+ * @notifier: notifier block to be removed.
+ *
+ * Will remove the notifier from the notification chain that gets called
+ * upon changes to the target value for any device.
+ */
+int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier)
+{
+	return blocking_notifier_chain_unregister(&dev_pm_notifiers, notifier);
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_remove_global_notifier);
diff -druN linux-libre-3.1-gnu/drivers/base/power/runtime.c linux-libre-3.2-gnu/drivers/base/power/runtime.c
--- linux-libre-3.1-gnu/drivers/base/power/runtime.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/power/runtime.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,9 @@
  */
 
 #include <linux/sched.h>
+#include <linux/export.h>
 #include <linux/pm_runtime.h>
+#include <trace/events/rpm.h>
 #include "power.h"
 
 static int rpm_resume(struct device *dev, int rpmflags);
@@ -28,13 +30,10 @@
 void update_pm_runtime_accounting(struct device *dev)
 {
 	unsigned long now = jiffies;
-	int delta;
+	unsigned long delta;
 
 	delta = now - dev->power.accounting_timestamp;
 
-	if (delta < 0)
-		delta = 0;
-
 	dev->power.accounting_timestamp = now;
 
 	if (dev->power.disable_depth > 0)
@@ -155,6 +154,31 @@
 }
 
 /**
+ * __rpm_callback - Run a given runtime PM callback for a given device.
+ * @cb: Runtime PM callback to run.
+ * @dev: Device to run the callback for.
+ */
+static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
+	__releases(&dev->power.lock) __acquires(&dev->power.lock)
+{
+	int retval;
+
+	if (dev->power.irq_safe)
+		spin_unlock(&dev->power.lock);
+	else
+		spin_unlock_irq(&dev->power.lock);
+
+	retval = cb(dev);
+
+	if (dev->power.irq_safe)
+		spin_lock(&dev->power.lock);
+	else
+		spin_lock_irq(&dev->power.lock);
+
+	return retval;
+}
+
+/**
  * rpm_idle - Notify device bus type if the device can be suspended.
  * @dev: Device to notify the bus type about.
  * @rpmflags: Flag bits.
@@ -171,6 +195,7 @@
 	int (*callback)(struct device *);
 	int retval;
 
+	trace_rpm_idle(dev, rpmflags);
 	retval = rpm_check_suspend_allowed(dev);
 	if (retval < 0)
 		;	/* Conditions are wrong. */
@@ -225,24 +250,14 @@
 	else
 		callback = NULL;
 
-	if (callback) {
-		if (dev->power.irq_safe)
-			spin_unlock(&dev->power.lock);
-		else
-			spin_unlock_irq(&dev->power.lock);
-
-		callback(dev);
-
-		if (dev->power.irq_safe)
-			spin_lock(&dev->power.lock);
-		else
-			spin_lock_irq(&dev->power.lock);
-	}
+	if (callback)
+		__rpm_callback(callback, dev);
 
 	dev->power.idle_notification = false;
 	wake_up_all(&dev->power.wait_queue);
 
  out:
+	trace_rpm_return_int(dev, _THIS_IP_, retval);
 	return retval;
 }
 
@@ -252,22 +267,14 @@
  * @dev: Device to run the callback for.
  */
 static int rpm_callback(int (*cb)(struct device *), struct device *dev)
-	__releases(&dev->power.lock) __acquires(&dev->power.lock)
 {
 	int retval;
 
 	if (!cb)
 		return -ENOSYS;
 
-	if (dev->power.irq_safe) {
-		retval = cb(dev);
-	} else {
-		spin_unlock_irq(&dev->power.lock);
-
-		retval = cb(dev);
+	retval = __rpm_callback(cb, dev);
 
-		spin_lock_irq(&dev->power.lock);
-	}
 	dev->power.runtime_error = retval;
 	return retval != -EACCES ? retval : -EIO;
 }
@@ -277,14 +284,19 @@
  * @dev: Device to suspend.
  * @rpmflags: Flag bits.
  *
- * Check if the device's runtime PM status allows it to be suspended.  If
- * another suspend has been started earlier, either return immediately or wait
- * for it to finish, depending on the RPM_NOWAIT and RPM_ASYNC flags.  Cancel a
- * pending idle notification.  If the RPM_ASYNC flag is set then queue a
- * suspend request; otherwise run the ->runtime_suspend() callback directly.
- * If a deferred resume was requested while the callback was running then carry
- * it out; otherwise send an idle notification for the device (if the suspend
- * failed) or for its parent (if the suspend succeeded).
+ * Check if the device's runtime PM status allows it to be suspended.
+ * Cancel a pending idle notification, autosuspend or suspend. If
+ * another suspend has been started earlier, either return immediately
+ * or wait for it to finish, depending on the RPM_NOWAIT and RPM_ASYNC
+ * flags. If the RPM_ASYNC flag is set then queue a suspend request;
+ * otherwise run the ->runtime_suspend() callback directly. When
+ * ->runtime_suspend succeeded, if a deferred resume was requested while
+ * the callback was running then carry it out, otherwise send an idle
+ * notification for its parent (if the suspend succeeded and both
+ * ignore_children of parent->power and irq_safe of dev->power are not set).
+ * If ->runtime_suspend failed with -EAGAIN or -EBUSY, and if the RPM_AUTO
+ * flag is set and the next autosuspend-delay expiration time is in the
+ * future, schedule another autosuspend attempt.
  *
  * This function must be called under dev->power.lock with interrupts disabled.
  */
@@ -295,7 +307,7 @@
 	struct device *parent = NULL;
 	int retval;
 
-	dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
+	trace_rpm_suspend(dev, rpmflags);
 
  repeat:
 	retval = rpm_check_suspend_allowed(dev);
@@ -347,6 +359,15 @@
 			goto out;
 		}
 
+		if (dev->power.irq_safe) {
+			spin_unlock(&dev->power.lock);
+
+			cpu_relax();
+
+			spin_lock(&dev->power.lock);
+			goto repeat;
+		}
+
 		/* Wait for the other suspend running in parallel with us. */
 		for (;;) {
 			prepare_to_wait(&dev->power.wait_queue, &wait,
@@ -396,19 +417,31 @@
 	if (retval) {
 		__update_runtime_status(dev, RPM_ACTIVE);
 		dev->power.deferred_resume = false;
-		if (retval == -EAGAIN || retval == -EBUSY)
+		if (retval == -EAGAIN || retval == -EBUSY) {
 			dev->power.runtime_error = 0;
-		else
+
+			/*
+			 * If the callback routine failed an autosuspend, and
+			 * if the last_busy time has been updated so that there
+			 * is a new autosuspend expiration time, automatically
+			 * reschedule another autosuspend.
+			 */
+			if ((rpmflags & RPM_AUTO) &&
+			    pm_runtime_autosuspend_expiration(dev) != 0)
+				goto repeat;
+		} else {
 			pm_runtime_cancel_pending(dev);
-	} else {
+		}
+		wake_up_all(&dev->power.wait_queue);
+		goto out;
+	}
  no_callback:
-		__update_runtime_status(dev, RPM_SUSPENDED);
-		pm_runtime_deactivate_timer(dev);
+	__update_runtime_status(dev, RPM_SUSPENDED);
+	pm_runtime_deactivate_timer(dev);
 
-		if (dev->parent) {
-			parent = dev->parent;
-			atomic_add_unless(&parent->power.child_count, -1, 0);
-		}
+	if (dev->parent) {
+		parent = dev->parent;
+		atomic_add_unless(&parent->power.child_count, -1, 0);
 	}
 	wake_up_all(&dev->power.wait_queue);
 
@@ -430,7 +463,7 @@
 	}
 
  out:
-	dev_dbg(dev, "%s returns %d\n", __func__, retval);
+	trace_rpm_return_int(dev, _THIS_IP_, retval);
 
 	return retval;
 }
@@ -459,7 +492,7 @@
 	struct device *parent = NULL;
 	int retval = 0;
 
-	dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
+	trace_rpm_resume(dev, rpmflags);
 
  repeat:
 	if (dev->power.runtime_error)
@@ -496,6 +529,15 @@
 			goto out;
 		}
 
+		if (dev->power.irq_safe) {
+			spin_unlock(&dev->power.lock);
+
+			cpu_relax();
+
+			spin_lock(&dev->power.lock);
+			goto repeat;
+		}
+
 		/* Wait for the operation carried out in parallel with us. */
 		for (;;) {
 			prepare_to_wait(&dev->power.wait_queue, &wait,
@@ -615,7 +657,7 @@
 		spin_lock_irq(&dev->power.lock);
 	}
 
-	dev_dbg(dev, "%s returns %d\n", __func__, retval);
+	trace_rpm_return_int(dev, _THIS_IP_, retval);
 
 	return retval;
 }
@@ -732,13 +774,16 @@
  * return immediately if it is larger than zero.  Then carry out an idle
  * notification, either synchronous or asynchronous.
  *
- * This routine may be called in atomic context if the RPM_ASYNC flag is set.
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set,
+ * or if pm_runtime_irq_safe() has been called.
  */
 int __pm_runtime_idle(struct device *dev, int rpmflags)
 {
 	unsigned long flags;
 	int retval;
 
+	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
 	if (rpmflags & RPM_GET_PUT) {
 		if (!atomic_dec_and_test(&dev->power.usage_count))
 			return 0;
@@ -761,13 +806,16 @@
  * return immediately if it is larger than zero.  Then carry out a suspend,
  * either synchronous or asynchronous.
  *
- * This routine may be called in atomic context if the RPM_ASYNC flag is set.
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set,
+ * or if pm_runtime_irq_safe() has been called.
  */
 int __pm_runtime_suspend(struct device *dev, int rpmflags)
 {
 	unsigned long flags;
 	int retval;
 
+	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
 	if (rpmflags & RPM_GET_PUT) {
 		if (!atomic_dec_and_test(&dev->power.usage_count))
 			return 0;
@@ -789,13 +837,16 @@
  * If the RPM_GET_PUT flag is set, increment the device's usage count.  Then
  * carry out a resume, either synchronous or asynchronous.
  *
- * This routine may be called in atomic context if the RPM_ASYNC flag is set.
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set,
+ * or if pm_runtime_irq_safe() has been called.
  */
 int __pm_runtime_resume(struct device *dev, int rpmflags)
 {
 	unsigned long flags;
 	int retval;
 
+	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
 	if (rpmflags & RPM_GET_PUT)
 		atomic_inc(&dev->power.usage_count);
 
diff -druN linux-libre-3.1-gnu/drivers/base/power/sysfs.c linux-libre-3.2-gnu/drivers/base/power/sysfs.c
--- linux-libre-3.1-gnu/drivers/base/power/sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/power/sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@
 
 #include <linux/device.h>
 #include <linux/string.h>
+#include <linux/export.h>
 #include <linux/pm_runtime.h>
 #include <linux/atomic.h>
 #include <linux/jiffies.h>
diff -druN linux-libre-3.1-gnu/drivers/base/power/trace.c linux-libre-3.2-gnu/drivers/base/power/trace.c
--- linux-libre-3.1-gnu/drivers/base/power/trace.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/power/trace.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 
 #include <linux/resume-trace.h>
+#include <linux/export.h>
 #include <linux/rtc.h>
 
 #include <asm/rtc.h>
diff -druN linux-libre-3.1-gnu/drivers/base/power/wakeup.c linux-libre-3.2-gnu/drivers/base/power/wakeup.c
--- linux-libre-3.1-gnu/drivers/base/power/wakeup.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/power/wakeup.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/capability.h>
+#include <linux/export.h>
 #include <linux/suspend.h>
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
@@ -276,7 +277,9 @@
  *
  * By default, most devices should leave wakeup disabled.  The exceptions are
  * devices that everyone expects to be wakeup sources: keyboards, power buttons,
- * possibly network interfaces, etc.
+ * possibly network interfaces, etc.  Also, devices that don't generate their
+ * own wakeup requests but merely forward requests from one bus to another
+ * (like PCI bridges) should have wakeup enabled by default.
  */
 int device_init_wakeup(struct device *dev, bool enable)
 {
diff -druN linux-libre-3.1-gnu/drivers/base/regmap/internal.h linux-libre-3.2-gnu/drivers/base/regmap/internal.h
--- linux-libre-3.1-gnu/drivers/base/regmap/internal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/base/regmap/internal.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,128 @@
+/*
+ * Register map access API internal header
+ *
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _REGMAP_INTERNAL_H
+#define _REGMAP_INTERNAL_H
+
+#include <linux/regmap.h>
+#include <linux/fs.h>
+
+struct regmap;
+struct regcache_ops;
+
+struct regmap_format {
+	size_t buf_size;
+	size_t reg_bytes;
+	size_t val_bytes;
+	void (*format_write)(struct regmap *map,
+			     unsigned int reg, unsigned int val);
+	void (*format_reg)(void *buf, unsigned int reg);
+	void (*format_val)(void *buf, unsigned int val);
+	unsigned int (*parse_val)(void *buf);
+};
+
+struct regmap {
+	struct mutex lock;
+
+	struct device *dev; /* Device we do I/O on */
+	void *work_buf;     /* Scratch buffer used to format I/O */
+	struct regmap_format format;  /* Buffer format */
+	const struct regmap_bus *bus;
+
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs;
+#endif
+
+	unsigned int max_register;
+	bool (*writeable_reg)(struct device *dev, unsigned int reg);
+	bool (*readable_reg)(struct device *dev, unsigned int reg);
+	bool (*volatile_reg)(struct device *dev, unsigned int reg);
+	bool (*precious_reg)(struct device *dev, unsigned int reg);
+
+	u8 read_flag_mask;
+	u8 write_flag_mask;
+
+	/* regcache specific members */
+	const struct regcache_ops *cache_ops;
+	enum regcache_type cache_type;
+
+	/* number of bytes in reg_defaults_raw */
+	unsigned int cache_size_raw;
+	/* number of bytes per word in reg_defaults_raw */
+	unsigned int cache_word_size;
+	/* number of entries in reg_defaults */
+	unsigned int num_reg_defaults;
+	/* number of entries in reg_defaults_raw */
+	unsigned int num_reg_defaults_raw;
+
+	/* if set, only the cache is modified not the HW */
+	unsigned int cache_only:1;
+	/* if set, only the HW is modified not the cache */
+	unsigned int cache_bypass:1;
+	/* if set, remember to free reg_defaults_raw */
+	unsigned int cache_free:1;
+
+	struct reg_default *reg_defaults;
+	const void *reg_defaults_raw;
+	void *cache;
+};
+
+struct regcache_ops {
+	const char *name;
+	enum regcache_type type;
+	int (*init)(struct regmap *map);
+	int (*exit)(struct regmap *map);
+	int (*read)(struct regmap *map, unsigned int reg, unsigned int *value);
+	int (*write)(struct regmap *map, unsigned int reg, unsigned int value);
+	int (*sync)(struct regmap *map);
+};
+
+bool regmap_writeable(struct regmap *map, unsigned int reg);
+bool regmap_readable(struct regmap *map, unsigned int reg);
+bool regmap_volatile(struct regmap *map, unsigned int reg);
+bool regmap_precious(struct regmap *map, unsigned int reg);
+
+int _regmap_write(struct regmap *map, unsigned int reg,
+		  unsigned int val);
+
+#ifdef CONFIG_DEBUG_FS
+extern void regmap_debugfs_initcall(void);
+extern void regmap_debugfs_init(struct regmap *map);
+extern void regmap_debugfs_exit(struct regmap *map);
+#else
+static inline void regmap_debugfs_initcall(void) { }
+static inline void regmap_debugfs_init(struct regmap *map) { }
+static inline void regmap_debugfs_exit(struct regmap *map) { }
+#endif
+
+/* regcache core declarations */
+int regcache_init(struct regmap *map);
+void regcache_exit(struct regmap *map);
+int regcache_read(struct regmap *map,
+		       unsigned int reg, unsigned int *value);
+int regcache_write(struct regmap *map,
+			unsigned int reg, unsigned int value);
+int regcache_sync(struct regmap *map);
+
+unsigned int regcache_get_val(const void *base, unsigned int idx,
+			      unsigned int word_size);
+bool regcache_set_val(void *base, unsigned int idx,
+		      unsigned int val, unsigned int word_size);
+int regcache_lookup_reg(struct regmap *map, unsigned int reg);
+int regcache_insert_reg(struct regmap *map, unsigned int reg,
+			unsigned int val);
+
+extern struct regcache_ops regcache_indexed_ops;
+extern struct regcache_ops regcache_rbtree_ops;
+extern struct regcache_ops regcache_lzo_ops;
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/base/regmap/Kconfig linux-libre-3.2-gnu/drivers/base/regmap/Kconfig
--- linux-libre-3.1-gnu/drivers/base/regmap/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/regmap/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,8 @@
 
 config REGMAP
 	default y if (REGMAP_I2C || REGMAP_SPI)
+	select LZO_COMPRESS
+	select LZO_DECOMPRESS
 	bool
 
 config REGMAP_I2C
diff -druN linux-libre-3.1-gnu/drivers/base/regmap/Makefile linux-libre-3.2-gnu/drivers/base/regmap/Makefile
--- linux-libre-3.1-gnu/drivers/base/regmap/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/regmap/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,4 @@
-obj-$(CONFIG_REGMAP) += regmap.o
+obj-$(CONFIG_REGMAP) += regmap.o regcache.o regcache-indexed.o regcache-rbtree.o regcache-lzo.o
+obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
 obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
 obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
diff -druN linux-libre-3.1-gnu/drivers/base/regmap/regcache.c linux-libre-3.2-gnu/drivers/base/regmap/regcache.c
--- linux-libre-3.1-gnu/drivers/base/regmap/regcache.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/base/regmap/regcache.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,402 @@
+/*
+ * Register cache access API
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <trace/events/regmap.h>
+#include <linux/bsearch.h>
+#include <linux/sort.h>
+
+#include "internal.h"
+
+static const struct regcache_ops *cache_types[] = {
+	&regcache_indexed_ops,
+	&regcache_rbtree_ops,
+	&regcache_lzo_ops,
+};
+
+static int regcache_hw_init(struct regmap *map)
+{
+	int i, j;
+	int ret;
+	int count;
+	unsigned int val;
+	void *tmp_buf;
+
+	if (!map->num_reg_defaults_raw)
+		return -EINVAL;
+
+	if (!map->reg_defaults_raw) {
+		dev_warn(map->dev, "No cache defaults, reading back from HW\n");
+		tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL);
+		if (!tmp_buf)
+			return -EINVAL;
+		ret = regmap_bulk_read(map, 0, tmp_buf,
+				       map->num_reg_defaults_raw);
+		if (ret < 0) {
+			kfree(tmp_buf);
+			return ret;
+		}
+		map->reg_defaults_raw = tmp_buf;
+		map->cache_free = 1;
+	}
+
+	/* calculate the size of reg_defaults */
+	for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) {
+		val = regcache_get_val(map->reg_defaults_raw,
+				       i, map->cache_word_size);
+		if (!val)
+			continue;
+		count++;
+	}
+
+	map->reg_defaults = kmalloc(count * sizeof(struct reg_default),
+				      GFP_KERNEL);
+	if (!map->reg_defaults)
+		return -ENOMEM;
+
+	/* fill the reg_defaults */
+	map->num_reg_defaults = count;
+	for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
+		val = regcache_get_val(map->reg_defaults_raw,
+				       i, map->cache_word_size);
+		if (!val)
+			continue;
+		map->reg_defaults[j].reg = i;
+		map->reg_defaults[j].def = val;
+		j++;
+	}
+
+	return 0;
+}
+
+int regcache_init(struct regmap *map)
+{
+	int ret;
+	int i;
+	void *tmp_buf;
+
+	if (map->cache_type == REGCACHE_NONE) {
+		map->cache_bypass = true;
+		return 0;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(cache_types); i++)
+		if (cache_types[i]->type == map->cache_type)
+			break;
+
+	if (i == ARRAY_SIZE(cache_types)) {
+		dev_err(map->dev, "Could not match compress type: %d\n",
+			map->cache_type);
+		return -EINVAL;
+	}
+
+	map->cache = NULL;
+	map->cache_ops = cache_types[i];
+
+	if (!map->cache_ops->read ||
+	    !map->cache_ops->write ||
+	    !map->cache_ops->name)
+		return -EINVAL;
+
+	/* We still need to ensure that the reg_defaults
+	 * won't vanish from under us.  We'll need to make
+	 * a copy of it.
+	 */
+	if (map->reg_defaults) {
+		if (!map->num_reg_defaults)
+			return -EINVAL;
+		tmp_buf = kmemdup(map->reg_defaults, map->num_reg_defaults *
+				  sizeof(struct reg_default), GFP_KERNEL);
+		if (!tmp_buf)
+			return -ENOMEM;
+		map->reg_defaults = tmp_buf;
+	} else if (map->num_reg_defaults_raw) {
+		/* Some devices such as PMICs don't have cache defaults,
+		 * we cope with this by reading back the HW registers and
+		 * crafting the cache defaults by hand.
+		 */
+		ret = regcache_hw_init(map);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (!map->max_register)
+		map->max_register = map->num_reg_defaults_raw;
+
+	if (map->cache_ops->init) {
+		dev_dbg(map->dev, "Initializing %s cache\n",
+			map->cache_ops->name);
+		return map->cache_ops->init(map);
+	}
+	return 0;
+}
+
+void regcache_exit(struct regmap *map)
+{
+	if (map->cache_type == REGCACHE_NONE)
+		return;
+
+	BUG_ON(!map->cache_ops);
+
+	kfree(map->reg_defaults);
+	if (map->cache_free)
+		kfree(map->reg_defaults_raw);
+
+	if (map->cache_ops->exit) {
+		dev_dbg(map->dev, "Destroying %s cache\n",
+			map->cache_ops->name);
+		map->cache_ops->exit(map);
+	}
+}
+
+/**
+ * regcache_read: Fetch the value of a given register from the cache.
+ *
+ * @map: map to configure.
+ * @reg: The register index.
+ * @value: The value to be returned.
+ *
+ * Return a negative value on failure, 0 on success.
+ */
+int regcache_read(struct regmap *map,
+		  unsigned int reg, unsigned int *value)
+{
+	if (map->cache_type == REGCACHE_NONE)
+		return -ENOSYS;
+
+	BUG_ON(!map->cache_ops);
+
+	if (!regmap_readable(map, reg))
+		return -EIO;
+
+	if (!regmap_volatile(map, reg))
+		return map->cache_ops->read(map, reg, value);
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regcache_read);
+
+/**
+ * regcache_write: Set the value of a given register in the cache.
+ *
+ * @map: map to configure.
+ * @reg: The register index.
+ * @value: The new register value.
+ *
+ * Return a negative value on failure, 0 on success.
+ */
+int regcache_write(struct regmap *map,
+		   unsigned int reg, unsigned int value)
+{
+	if (map->cache_type == REGCACHE_NONE)
+		return 0;
+
+	BUG_ON(!map->cache_ops);
+
+	if (!regmap_writeable(map, reg))
+		return -EIO;
+
+	if (!regmap_volatile(map, reg))
+		return map->cache_ops->write(map, reg, value);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(regcache_write);
+
+/**
+ * regcache_sync: Sync the register cache with the hardware.
+ *
+ * @map: map to configure.
+ *
+ * Any registers that should not be synced should be marked as
+ * volatile.  In general drivers can choose not to use the provided
+ * syncing functionality if they so require.
+ *
+ * Return a negative value on failure, 0 on success.
+ */
+int regcache_sync(struct regmap *map)
+{
+	int ret = 0;
+	unsigned int val;
+	unsigned int i;
+	const char *name;
+	unsigned int bypass;
+
+	BUG_ON(!map->cache_ops);
+
+	mutex_lock(&map->lock);
+	/* Remember the initial bypass state */
+	bypass = map->cache_bypass;
+	dev_dbg(map->dev, "Syncing %s cache\n",
+		map->cache_ops->name);
+	name = map->cache_ops->name;
+	trace_regcache_sync(map->dev, name, "start");
+	if (map->cache_ops->sync) {
+		ret = map->cache_ops->sync(map);
+	} else {
+		for (i = 0; i < map->num_reg_defaults; i++) {
+			ret = regcache_read(map, i, &val);
+			if (ret < 0)
+				goto out;
+			map->cache_bypass = 1;
+			ret = _regmap_write(map, i, val);
+			map->cache_bypass = 0;
+			if (ret < 0)
+				goto out;
+			dev_dbg(map->dev, "Synced register %#x, value %#x\n",
+				map->reg_defaults[i].reg,
+				map->reg_defaults[i].def);
+		}
+
+	}
+out:
+	trace_regcache_sync(map->dev, name, "stop");
+	/* Restore the bypass state */
+	map->cache_bypass = bypass;
+	mutex_unlock(&map->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regcache_sync);
+
+/**
+ * regcache_cache_only: Put a register map into cache only mode
+ *
+ * @map: map to configure
+ * @cache_only: flag if changes should be written to the hardware
+ *
+ * When a register map is marked as cache only writes to the register
+ * map API will only update the register cache, they will not cause
+ * any hardware changes.  This is useful for allowing portions of
+ * drivers to act as though the device were functioning as normal when
+ * it is disabled for power saving reasons.
+ */
+void regcache_cache_only(struct regmap *map, bool enable)
+{
+	mutex_lock(&map->lock);
+	WARN_ON(map->cache_bypass && enable);
+	map->cache_only = enable;
+	mutex_unlock(&map->lock);
+}
+EXPORT_SYMBOL_GPL(regcache_cache_only);
+
+/**
+ * regcache_cache_bypass: Put a register map into cache bypass mode
+ *
+ * @map: map to configure
+ * @cache_bypass: flag if changes should not be written to the hardware
+ *
+ * When a register map is marked with the cache bypass option, writes
+ * to the register map API will only update the hardware and not the
+ * the cache directly.  This is useful when syncing the cache back to
+ * the hardware.
+ */
+void regcache_cache_bypass(struct regmap *map, bool enable)
+{
+	mutex_lock(&map->lock);
+	WARN_ON(map->cache_only && enable);
+	map->cache_bypass = enable;
+	mutex_unlock(&map->lock);
+}
+EXPORT_SYMBOL_GPL(regcache_cache_bypass);
+
+bool regcache_set_val(void *base, unsigned int idx,
+		      unsigned int val, unsigned int word_size)
+{
+	switch (word_size) {
+	case 1: {
+		u8 *cache = base;
+		if (cache[idx] == val)
+			return true;
+		cache[idx] = val;
+		break;
+	}
+	case 2: {
+		u16 *cache = base;
+		if (cache[idx] == val)
+			return true;
+		cache[idx] = val;
+		break;
+	}
+	default:
+		BUG();
+	}
+	/* unreachable */
+	return false;
+}
+
+unsigned int regcache_get_val(const void *base, unsigned int idx,
+			      unsigned int word_size)
+{
+	if (!base)
+		return -EINVAL;
+
+	switch (word_size) {
+	case 1: {
+		const u8 *cache = base;
+		return cache[idx];
+	}
+	case 2: {
+		const u16 *cache = base;
+		return cache[idx];
+	}
+	default:
+		BUG();
+	}
+	/* unreachable */
+	return -1;
+}
+
+static int regcache_default_cmp(const void *a, const void *b)
+{
+	const struct reg_default *_a = a;
+	const struct reg_default *_b = b;
+
+	return _a->reg - _b->reg;
+}
+
+int regcache_lookup_reg(struct regmap *map, unsigned int reg)
+{
+	struct reg_default key;
+	struct reg_default *r;
+
+	key.reg = reg;
+	key.def = 0;
+
+	r = bsearch(&key, map->reg_defaults, map->num_reg_defaults,
+		    sizeof(struct reg_default), regcache_default_cmp);
+
+	if (r)
+		return r - map->reg_defaults;
+	else
+		return -ENOENT;
+}
+
+int regcache_insert_reg(struct regmap *map, unsigned int reg,
+			unsigned int val)
+{
+	void *tmp;
+
+	tmp = krealloc(map->reg_defaults,
+		       (map->num_reg_defaults + 1) * sizeof(struct reg_default),
+		       GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+	map->reg_defaults = tmp;
+	map->num_reg_defaults++;
+	map->reg_defaults[map->num_reg_defaults - 1].reg = reg;
+	map->reg_defaults[map->num_reg_defaults - 1].def = val;
+	sort(map->reg_defaults, map->num_reg_defaults,
+	     sizeof(struct reg_default), regcache_default_cmp, NULL);
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/drivers/base/regmap/regcache-indexed.c linux-libre-3.2-gnu/drivers/base/regmap/regcache-indexed.c
--- linux-libre-3.1-gnu/drivers/base/regmap/regcache-indexed.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/base/regmap/regcache-indexed.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,64 @@
+/*
+ * Register cache access API - indexed caching support
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+
+#include "internal.h"
+
+static int regcache_indexed_read(struct regmap *map, unsigned int reg,
+				 unsigned int *value)
+{
+	int ret;
+
+	ret = regcache_lookup_reg(map, reg);
+	if (ret >= 0)
+		*value = map->reg_defaults[ret].def;
+
+	return ret;
+}
+
+static int regcache_indexed_write(struct regmap *map, unsigned int reg,
+				  unsigned int value)
+{
+	int ret;
+
+	ret = regcache_lookup_reg(map, reg);
+	if (ret < 0)
+		return regcache_insert_reg(map, reg, value);
+	map->reg_defaults[ret].def = value;
+	return 0;
+}
+
+static int regcache_indexed_sync(struct regmap *map)
+{
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < map->num_reg_defaults; i++) {
+		ret = _regmap_write(map, map->reg_defaults[i].reg,
+				    map->reg_defaults[i].def);
+		if (ret < 0)
+			return ret;
+		dev_dbg(map->dev, "Synced register %#x, value %#x\n",
+			map->reg_defaults[i].reg,
+			map->reg_defaults[i].def);
+	}
+	return 0;
+}
+
+struct regcache_ops regcache_indexed_ops = {
+	.type = REGCACHE_INDEXED,
+	.name = "indexed",
+	.read = regcache_indexed_read,
+	.write = regcache_indexed_write,
+	.sync = regcache_indexed_sync
+};
diff -druN linux-libre-3.1-gnu/drivers/base/regmap/regcache-lzo.c linux-libre-3.2-gnu/drivers/base/regmap/regcache-lzo.c
--- linux-libre-3.1-gnu/drivers/base/regmap/regcache-lzo.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/base/regmap/regcache-lzo.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,361 @@
+/*
+ * Register cache access API - LZO caching support
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+#include <linux/lzo.h>
+
+#include "internal.h"
+
+struct regcache_lzo_ctx {
+	void *wmem;
+	void *dst;
+	const void *src;
+	size_t src_len;
+	size_t dst_len;
+	size_t decompressed_size;
+	unsigned long *sync_bmp;
+	int sync_bmp_nbits;
+};
+
+#define LZO_BLOCK_NUM 8
+static int regcache_lzo_block_count(void)
+{
+	return LZO_BLOCK_NUM;
+}
+
+static int regcache_lzo_prepare(struct regcache_lzo_ctx *lzo_ctx)
+{
+	lzo_ctx->wmem = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+	if (!lzo_ctx->wmem)
+		return -ENOMEM;
+	return 0;
+}
+
+static int regcache_lzo_compress(struct regcache_lzo_ctx *lzo_ctx)
+{
+	size_t compress_size;
+	int ret;
+
+	ret = lzo1x_1_compress(lzo_ctx->src, lzo_ctx->src_len,
+			       lzo_ctx->dst, &compress_size, lzo_ctx->wmem);
+	if (ret != LZO_E_OK || compress_size > lzo_ctx->dst_len)
+		return -EINVAL;
+	lzo_ctx->dst_len = compress_size;
+	return 0;
+}
+
+static int regcache_lzo_decompress(struct regcache_lzo_ctx *lzo_ctx)
+{
+	size_t dst_len;
+	int ret;
+
+	dst_len = lzo_ctx->dst_len;
+	ret = lzo1x_decompress_safe(lzo_ctx->src, lzo_ctx->src_len,
+				    lzo_ctx->dst, &dst_len);
+	if (ret != LZO_E_OK || dst_len != lzo_ctx->dst_len)
+		return -EINVAL;
+	return 0;
+}
+
+static int regcache_lzo_compress_cache_block(struct regmap *map,
+		struct regcache_lzo_ctx *lzo_ctx)
+{
+	int ret;
+
+	lzo_ctx->dst_len = lzo1x_worst_compress(PAGE_SIZE);
+	lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
+	if (!lzo_ctx->dst) {
+		lzo_ctx->dst_len = 0;
+		return -ENOMEM;
+	}
+
+	ret = regcache_lzo_compress(lzo_ctx);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static int regcache_lzo_decompress_cache_block(struct regmap *map,
+		struct regcache_lzo_ctx *lzo_ctx)
+{
+	int ret;
+
+	lzo_ctx->dst_len = lzo_ctx->decompressed_size;
+	lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
+	if (!lzo_ctx->dst) {
+		lzo_ctx->dst_len = 0;
+		return -ENOMEM;
+	}
+
+	ret = regcache_lzo_decompress(lzo_ctx);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static inline int regcache_lzo_get_blkindex(struct regmap *map,
+					    unsigned int reg)
+{
+	return (reg * map->cache_word_size) /
+		DIV_ROUND_UP(map->cache_size_raw, regcache_lzo_block_count());
+}
+
+static inline int regcache_lzo_get_blkpos(struct regmap *map,
+					  unsigned int reg)
+{
+	return reg % (DIV_ROUND_UP(map->cache_size_raw, regcache_lzo_block_count()) /
+		      map->cache_word_size);
+}
+
+static inline int regcache_lzo_get_blksize(struct regmap *map)
+{
+	return DIV_ROUND_UP(map->cache_size_raw, regcache_lzo_block_count());
+}
+
+static int regcache_lzo_init(struct regmap *map)
+{
+	struct regcache_lzo_ctx **lzo_blocks;
+	size_t bmp_size;
+	int ret, i, blksize, blkcount;
+	const char *p, *end;
+	unsigned long *sync_bmp;
+
+	ret = 0;
+
+	blkcount = regcache_lzo_block_count();
+	map->cache = kzalloc(blkcount * sizeof *lzo_blocks,
+			     GFP_KERNEL);
+	if (!map->cache)
+		return -ENOMEM;
+	lzo_blocks = map->cache;
+
+	/*
+	 * allocate a bitmap to be used when syncing the cache with
+	 * the hardware.  Each time a register is modified, the corresponding
+	 * bit is set in the bitmap, so we know that we have to sync
+	 * that register.
+	 */
+	bmp_size = map->num_reg_defaults_raw;
+	sync_bmp = kmalloc(BITS_TO_LONGS(bmp_size) * sizeof(long),
+			   GFP_KERNEL);
+	if (!sync_bmp) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	bitmap_zero(sync_bmp, bmp_size);
+
+	/* allocate the lzo blocks and initialize them */
+	for (i = 0; i < blkcount; i++) {
+		lzo_blocks[i] = kzalloc(sizeof **lzo_blocks,
+					GFP_KERNEL);
+		if (!lzo_blocks[i]) {
+			kfree(sync_bmp);
+			ret = -ENOMEM;
+			goto err;
+		}
+		lzo_blocks[i]->sync_bmp = sync_bmp;
+		lzo_blocks[i]->sync_bmp_nbits = bmp_size;
+		/* alloc the working space for the compressed block */
+		ret = regcache_lzo_prepare(lzo_blocks[i]);
+		if (ret < 0)
+			goto err;
+	}
+
+	blksize = regcache_lzo_get_blksize(map);
+	p = map->reg_defaults_raw;
+	end = map->reg_defaults_raw + map->cache_size_raw;
+	/* compress the register map and fill the lzo blocks */
+	for (i = 0; i < blkcount; i++, p += blksize) {
+		lzo_blocks[i]->src = p;
+		if (p + blksize > end)
+			lzo_blocks[i]->src_len = end - p;
+		else
+			lzo_blocks[i]->src_len = blksize;
+		ret = regcache_lzo_compress_cache_block(map,
+						       lzo_blocks[i]);
+		if (ret < 0)
+			goto err;
+		lzo_blocks[i]->decompressed_size =
+			lzo_blocks[i]->src_len;
+	}
+
+	return 0;
+err:
+	regcache_exit(map);
+	return ret;
+}
+
+static int regcache_lzo_exit(struct regmap *map)
+{
+	struct regcache_lzo_ctx **lzo_blocks;
+	int i, blkcount;
+
+	lzo_blocks = map->cache;
+	if (!lzo_blocks)
+		return 0;
+
+	blkcount = regcache_lzo_block_count();
+	/*
+	 * the pointer to the bitmap used for syncing the cache
+	 * is shared amongst all lzo_blocks.  Ensure it is freed
+	 * only once.
+	 */
+	if (lzo_blocks[0])
+		kfree(lzo_blocks[0]->sync_bmp);
+	for (i = 0; i < blkcount; i++) {
+		if (lzo_blocks[i]) {
+			kfree(lzo_blocks[i]->wmem);
+			kfree(lzo_blocks[i]->dst);
+		}
+		/* each lzo_block is a pointer returned by kmalloc or NULL */
+		kfree(lzo_blocks[i]);
+	}
+	kfree(lzo_blocks);
+	map->cache = NULL;
+	return 0;
+}
+
+static int regcache_lzo_read(struct regmap *map,
+			     unsigned int reg, unsigned int *value)
+{
+	struct regcache_lzo_ctx *lzo_block, **lzo_blocks;
+	int ret, blkindex, blkpos;
+	size_t blksize, tmp_dst_len;
+	void *tmp_dst;
+
+	/* index of the compressed lzo block */
+	blkindex = regcache_lzo_get_blkindex(map, reg);
+	/* register index within the decompressed block */
+	blkpos = regcache_lzo_get_blkpos(map, reg);
+	/* size of the compressed block */
+	blksize = regcache_lzo_get_blksize(map);
+	lzo_blocks = map->cache;
+	lzo_block = lzo_blocks[blkindex];
+
+	/* save the pointer and length of the compressed block */
+	tmp_dst = lzo_block->dst;
+	tmp_dst_len = lzo_block->dst_len;
+
+	/* prepare the source to be the compressed block */
+	lzo_block->src = lzo_block->dst;
+	lzo_block->src_len = lzo_block->dst_len;
+
+	/* decompress the block */
+	ret = regcache_lzo_decompress_cache_block(map, lzo_block);
+	if (ret >= 0)
+		/* fetch the value from the cache */
+		*value = regcache_get_val(lzo_block->dst, blkpos,
+					  map->cache_word_size);
+
+	kfree(lzo_block->dst);
+	/* restore the pointer and length of the compressed block */
+	lzo_block->dst = tmp_dst;
+	lzo_block->dst_len = tmp_dst_len;
+
+	return ret;
+}
+
+static int regcache_lzo_write(struct regmap *map,
+			      unsigned int reg, unsigned int value)
+{
+	struct regcache_lzo_ctx *lzo_block, **lzo_blocks;
+	int ret, blkindex, blkpos;
+	size_t blksize, tmp_dst_len;
+	void *tmp_dst;
+
+	/* index of the compressed lzo block */
+	blkindex = regcache_lzo_get_blkindex(map, reg);
+	/* register index within the decompressed block */
+	blkpos = regcache_lzo_get_blkpos(map, reg);
+	/* size of the compressed block */
+	blksize = regcache_lzo_get_blksize(map);
+	lzo_blocks = map->cache;
+	lzo_block = lzo_blocks[blkindex];
+
+	/* save the pointer and length of the compressed block */
+	tmp_dst = lzo_block->dst;
+	tmp_dst_len = lzo_block->dst_len;
+
+	/* prepare the source to be the compressed block */
+	lzo_block->src = lzo_block->dst;
+	lzo_block->src_len = lzo_block->dst_len;
+
+	/* decompress the block */
+	ret = regcache_lzo_decompress_cache_block(map, lzo_block);
+	if (ret < 0) {
+		kfree(lzo_block->dst);
+		goto out;
+	}
+
+	/* write the new value to the cache */
+	if (regcache_set_val(lzo_block->dst, blkpos, value,
+			     map->cache_word_size)) {
+		kfree(lzo_block->dst);
+		goto out;
+	}
+
+	/* prepare the source to be the decompressed block */
+	lzo_block->src = lzo_block->dst;
+	lzo_block->src_len = lzo_block->dst_len;
+
+	/* compress the block */
+	ret = regcache_lzo_compress_cache_block(map, lzo_block);
+	if (ret < 0) {
+		kfree(lzo_block->dst);
+		kfree(lzo_block->src);
+		goto out;
+	}
+
+	/* set the bit so we know we have to sync this register */
+	set_bit(reg, lzo_block->sync_bmp);
+	kfree(tmp_dst);
+	kfree(lzo_block->src);
+	return 0;
+out:
+	lzo_block->dst = tmp_dst;
+	lzo_block->dst_len = tmp_dst_len;
+	return ret;
+}
+
+static int regcache_lzo_sync(struct regmap *map)
+{
+	struct regcache_lzo_ctx **lzo_blocks;
+	unsigned int val;
+	int i;
+	int ret;
+
+	lzo_blocks = map->cache;
+	for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) {
+		ret = regcache_read(map, i, &val);
+		if (ret)
+			return ret;
+		map->cache_bypass = 1;
+		ret = _regmap_write(map, i, val);
+		map->cache_bypass = 0;
+		if (ret)
+			return ret;
+		dev_dbg(map->dev, "Synced register %#x, value %#x\n",
+			i, val);
+	}
+
+	return 0;
+}
+
+struct regcache_ops regcache_lzo_ops = {
+	.type = REGCACHE_LZO,
+	.name = "lzo",
+	.init = regcache_lzo_init,
+	.exit = regcache_lzo_exit,
+	.read = regcache_lzo_read,
+	.write = regcache_lzo_write,
+	.sync = regcache_lzo_sync
+};
diff -druN linux-libre-3.1-gnu/drivers/base/regmap/regcache-rbtree.c linux-libre-3.2-gnu/drivers/base/regmap/regcache-rbtree.c
--- linux-libre-3.1-gnu/drivers/base/regmap/regcache-rbtree.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/base/regmap/regcache-rbtree.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,345 @@
+/*
+ * Register cache access API - rbtree caching support
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+#include <linux/rbtree.h>
+
+#include "internal.h"
+
+static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
+				 unsigned int value);
+
+struct regcache_rbtree_node {
+	/* the actual rbtree node holding this block */
+	struct rb_node node;
+	/* base register handled by this block */
+	unsigned int base_reg;
+	/* block of adjacent registers */
+	void *block;
+	/* number of registers available in the block */
+	unsigned int blklen;
+} __attribute__ ((packed));
+
+struct regcache_rbtree_ctx {
+	struct rb_root root;
+	struct regcache_rbtree_node *cached_rbnode;
+};
+
+static inline void regcache_rbtree_get_base_top_reg(
+	struct regcache_rbtree_node *rbnode,
+	unsigned int *base, unsigned int *top)
+{
+	*base = rbnode->base_reg;
+	*top = rbnode->base_reg + rbnode->blklen - 1;
+}
+
+static unsigned int regcache_rbtree_get_register(
+	struct regcache_rbtree_node *rbnode, unsigned int idx,
+	unsigned int word_size)
+{
+	return regcache_get_val(rbnode->block, idx, word_size);
+}
+
+static void regcache_rbtree_set_register(struct regcache_rbtree_node *rbnode,
+					 unsigned int idx, unsigned int val,
+					 unsigned int word_size)
+{
+	regcache_set_val(rbnode->block, idx, val, word_size);
+}
+
+static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map,
+	unsigned int reg)
+{
+	struct regcache_rbtree_ctx *rbtree_ctx = map->cache;
+	struct rb_node *node;
+	struct regcache_rbtree_node *rbnode;
+	unsigned int base_reg, top_reg;
+
+	rbnode = rbtree_ctx->cached_rbnode;
+	if (rbnode) {
+		regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
+		if (reg >= base_reg && reg <= top_reg)
+			return rbnode;
+	}
+
+	node = rbtree_ctx->root.rb_node;
+	while (node) {
+		rbnode = container_of(node, struct regcache_rbtree_node, node);
+		regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
+		if (reg >= base_reg && reg <= top_reg) {
+			rbtree_ctx->cached_rbnode = rbnode;
+			return rbnode;
+		} else if (reg > top_reg) {
+			node = node->rb_right;
+		} else if (reg < base_reg) {
+			node = node->rb_left;
+		}
+	}
+
+	return NULL;
+}
+
+static int regcache_rbtree_insert(struct rb_root *root,
+				  struct regcache_rbtree_node *rbnode)
+{
+	struct rb_node **new, *parent;
+	struct regcache_rbtree_node *rbnode_tmp;
+	unsigned int base_reg_tmp, top_reg_tmp;
+	unsigned int base_reg;
+
+	parent = NULL;
+	new = &root->rb_node;
+	while (*new) {
+		rbnode_tmp = container_of(*new, struct regcache_rbtree_node,
+					  node);
+		/* base and top registers of the current rbnode */
+		regcache_rbtree_get_base_top_reg(rbnode_tmp, &base_reg_tmp,
+						 &top_reg_tmp);
+		/* base register of the rbnode to be added */
+		base_reg = rbnode->base_reg;
+		parent = *new;
+		/* if this register has already been inserted, just return */
+		if (base_reg >= base_reg_tmp &&
+		    base_reg <= top_reg_tmp)
+			return 0;
+		else if (base_reg > top_reg_tmp)
+			new = &((*new)->rb_right);
+		else if (base_reg < base_reg_tmp)
+			new = &((*new)->rb_left);
+	}
+
+	/* insert the node into the rbtree */
+	rb_link_node(&rbnode->node, parent, new);
+	rb_insert_color(&rbnode->node, root);
+
+	return 1;
+}
+
+static int regcache_rbtree_init(struct regmap *map)
+{
+	struct regcache_rbtree_ctx *rbtree_ctx;
+	int i;
+	int ret;
+
+	map->cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL);
+	if (!map->cache)
+		return -ENOMEM;
+
+	rbtree_ctx = map->cache;
+	rbtree_ctx->root = RB_ROOT;
+	rbtree_ctx->cached_rbnode = NULL;
+
+	for (i = 0; i < map->num_reg_defaults; i++) {
+		ret = regcache_rbtree_write(map,
+					    map->reg_defaults[i].reg,
+					    map->reg_defaults[i].def);
+		if (ret)
+			goto err;
+	}
+
+	return 0;
+
+err:
+	regcache_exit(map);
+	return ret;
+}
+
+static int regcache_rbtree_exit(struct regmap *map)
+{
+	struct rb_node *next;
+	struct regcache_rbtree_ctx *rbtree_ctx;
+	struct regcache_rbtree_node *rbtree_node;
+
+	/* if we've already been called then just return */
+	rbtree_ctx = map->cache;
+	if (!rbtree_ctx)
+		return 0;
+
+	/* free up the rbtree */
+	next = rb_first(&rbtree_ctx->root);
+	while (next) {
+		rbtree_node = rb_entry(next, struct regcache_rbtree_node, node);
+		next = rb_next(&rbtree_node->node);
+		rb_erase(&rbtree_node->node, &rbtree_ctx->root);
+		kfree(rbtree_node->block);
+		kfree(rbtree_node);
+	}
+
+	/* release the resources */
+	kfree(map->cache);
+	map->cache = NULL;
+
+	return 0;
+}
+
+static int regcache_rbtree_read(struct regmap *map,
+				unsigned int reg, unsigned int *value)
+{
+	struct regcache_rbtree_node *rbnode;
+	unsigned int reg_tmp;
+
+	rbnode = regcache_rbtree_lookup(map, reg);
+	if (rbnode) {
+		reg_tmp = reg - rbnode->base_reg;
+		*value = regcache_rbtree_get_register(rbnode, reg_tmp,
+						      map->cache_word_size);
+	} else {
+		return -ENOENT;
+	}
+
+	return 0;
+}
+
+
+static int regcache_rbtree_insert_to_block(struct regcache_rbtree_node *rbnode,
+					   unsigned int pos, unsigned int reg,
+					   unsigned int value, unsigned int word_size)
+{
+	u8 *blk;
+
+	blk = krealloc(rbnode->block,
+		       (rbnode->blklen + 1) * word_size, GFP_KERNEL);
+	if (!blk)
+		return -ENOMEM;
+
+	/* insert the register value in the correct place in the rbnode block */
+	memmove(blk + (pos + 1) * word_size,
+		blk + pos * word_size,
+		(rbnode->blklen - pos) * word_size);
+
+	/* update the rbnode block, its size and the base register */
+	rbnode->block = blk;
+	rbnode->blklen++;
+	if (!pos)
+		rbnode->base_reg = reg;
+
+	regcache_rbtree_set_register(rbnode, pos, value, word_size);
+	return 0;
+}
+
+static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
+				 unsigned int value)
+{
+	struct regcache_rbtree_ctx *rbtree_ctx;
+	struct regcache_rbtree_node *rbnode, *rbnode_tmp;
+	struct rb_node *node;
+	unsigned int val;
+	unsigned int reg_tmp;
+	unsigned int pos;
+	int i;
+	int ret;
+
+	rbtree_ctx = map->cache;
+	/* if we can't locate it in the cached rbnode we'll have
+	 * to traverse the rbtree looking for it.
+	 */
+	rbnode = regcache_rbtree_lookup(map, reg);
+	if (rbnode) {
+		reg_tmp = reg - rbnode->base_reg;
+		val = regcache_rbtree_get_register(rbnode, reg_tmp,
+						   map->cache_word_size);
+		if (val == value)
+			return 0;
+		regcache_rbtree_set_register(rbnode, reg_tmp, value,
+					     map->cache_word_size);
+	} else {
+		/* look for an adjacent register to the one we are about to add */
+		for (node = rb_first(&rbtree_ctx->root); node;
+		     node = rb_next(node)) {
+			rbnode_tmp = rb_entry(node, struct regcache_rbtree_node, node);
+			for (i = 0; i < rbnode_tmp->blklen; i++) {
+				reg_tmp = rbnode_tmp->base_reg + i;
+				if (abs(reg_tmp - reg) != 1)
+					continue;
+				/* decide where in the block to place our register */
+				if (reg_tmp + 1 == reg)
+					pos = i + 1;
+				else
+					pos = i;
+				ret = regcache_rbtree_insert_to_block(rbnode_tmp, pos,
+								      reg, value,
+								      map->cache_word_size);
+				if (ret)
+					return ret;
+				rbtree_ctx->cached_rbnode = rbnode_tmp;
+				return 0;
+			}
+		}
+		/* we did not manage to find a place to insert it in an existing
+		 * block so create a new rbnode with a single register in its block.
+		 * This block will get populated further if any other adjacent
+		 * registers get modified in the future.
+		 */
+		rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL);
+		if (!rbnode)
+			return -ENOMEM;
+		rbnode->blklen = 1;
+		rbnode->base_reg = reg;
+		rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size,
+					GFP_KERNEL);
+		if (!rbnode->block) {
+			kfree(rbnode);
+			return -ENOMEM;
+		}
+		regcache_rbtree_set_register(rbnode, 0, value, map->cache_word_size);
+		regcache_rbtree_insert(&rbtree_ctx->root, rbnode);
+		rbtree_ctx->cached_rbnode = rbnode;
+	}
+
+	return 0;
+}
+
+static int regcache_rbtree_sync(struct regmap *map)
+{
+	struct regcache_rbtree_ctx *rbtree_ctx;
+	struct rb_node *node;
+	struct regcache_rbtree_node *rbnode;
+	unsigned int regtmp;
+	unsigned int val;
+	int ret;
+	int i;
+
+	rbtree_ctx = map->cache;
+	for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
+		rbnode = rb_entry(node, struct regcache_rbtree_node, node);
+		for (i = 0; i < rbnode->blklen; i++) {
+			regtmp = rbnode->base_reg + i;
+			val = regcache_rbtree_get_register(rbnode, i,
+							   map->cache_word_size);
+
+			/* Is this the hardware default?  If so skip. */
+			ret = regcache_lookup_reg(map, i);
+			if (ret > 0 && val == map->reg_defaults[ret].def)
+				continue;
+
+			map->cache_bypass = 1;
+			ret = _regmap_write(map, regtmp, val);
+			map->cache_bypass = 0;
+			if (ret)
+				return ret;
+			dev_dbg(map->dev, "Synced register %#x, value %#x\n",
+				regtmp, val);
+		}
+	}
+
+	return 0;
+}
+
+struct regcache_ops regcache_rbtree_ops = {
+	.type = REGCACHE_RBTREE,
+	.name = "rbtree",
+	.init = regcache_rbtree_init,
+	.exit = regcache_rbtree_exit,
+	.read = regcache_rbtree_read,
+	.write = regcache_rbtree_write,
+	.sync = regcache_rbtree_sync
+};
diff -druN linux-libre-3.1-gnu/drivers/base/regmap/regmap.c linux-libre-3.2-gnu/drivers/base/regmap/regmap.c
--- linux-libre-3.1-gnu/drivers/base/regmap/regmap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/regmap/regmap.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,29 +15,54 @@
 #include <linux/mutex.h>
 #include <linux/err.h>
 
-#include <linux/regmap.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/regmap.h>
 
-struct regmap;
+#include "internal.h"
 
-struct regmap_format {
-	size_t buf_size;
-	size_t reg_bytes;
-	size_t val_bytes;
-	void (*format_write)(struct regmap *map,
-			     unsigned int reg, unsigned int val);
-	void (*format_reg)(void *buf, unsigned int reg);
-	void (*format_val)(void *buf, unsigned int val);
-	unsigned int (*parse_val)(void *buf);
-};
+bool regmap_writeable(struct regmap *map, unsigned int reg)
+{
+	if (map->max_register && reg > map->max_register)
+		return false;
 
-struct regmap {
-	struct mutex lock;
+	if (map->writeable_reg)
+		return map->writeable_reg(map->dev, reg);
 
-	struct device *dev; /* Device we do I/O on */
-	void *work_buf;     /* Scratch buffer used to format I/O */
-	struct regmap_format format;  /* Buffer format */
-	const struct regmap_bus *bus;
-};
+	return true;
+}
+
+bool regmap_readable(struct regmap *map, unsigned int reg)
+{
+	if (map->max_register && reg > map->max_register)
+		return false;
+
+	if (map->readable_reg)
+		return map->readable_reg(map->dev, reg);
+
+	return true;
+}
+
+bool regmap_volatile(struct regmap *map, unsigned int reg)
+{
+	if (map->max_register && reg > map->max_register)
+		return false;
+
+	if (map->volatile_reg)
+		return map->volatile_reg(map->dev, reg);
+
+	return true;
+}
+
+bool regmap_precious(struct regmap *map, unsigned int reg)
+{
+	if (map->max_register && reg > map->max_register)
+		return false;
+
+	if (map->precious_reg)
+		return map->precious_reg(map->dev, reg);
+
+	return false;
+}
 
 static void regmap_format_4_12_write(struct regmap *map,
 				     unsigned int reg, unsigned int val)
@@ -116,6 +141,25 @@
 	map->format.val_bytes = config->val_bits / 8;
 	map->dev = dev;
 	map->bus = bus;
+	map->max_register = config->max_register;
+	map->writeable_reg = config->writeable_reg;
+	map->readable_reg = config->readable_reg;
+	map->volatile_reg = config->volatile_reg;
+	map->precious_reg = config->precious_reg;
+	map->cache_type = config->cache_type;
+	map->reg_defaults = config->reg_defaults;
+	map->num_reg_defaults = config->num_reg_defaults;
+	map->num_reg_defaults_raw = config->num_reg_defaults_raw;
+	map->reg_defaults_raw = config->reg_defaults_raw;
+	map->cache_size_raw = (config->val_bits / 8) * config->num_reg_defaults_raw;
+	map->cache_word_size = config->val_bits / 8;
+
+	if (config->read_flag_mask || config->write_flag_mask) {
+		map->read_flag_mask = config->read_flag_mask;
+		map->write_flag_mask = config->write_flag_mask;
+	} else {
+		map->read_flag_mask = bus->read_flag_mask;
+	}
 
 	switch (config->reg_bits) {
 	case 4:
@@ -171,6 +215,12 @@
 		goto err_map;
 	}
 
+	ret = regcache_init(map);
+	if (ret < 0)
+		goto err_map;
+
+	regmap_debugfs_init(map);
+
 	return map;
 
 err_map:
@@ -185,6 +235,8 @@
  */
 void regmap_exit(struct regmap *map)
 {
+	regcache_exit(map);
+	regmap_debugfs_exit(map);
 	kfree(map->work_buf);
 	kfree(map);
 }
@@ -193,19 +245,38 @@
 static int _regmap_raw_write(struct regmap *map, unsigned int reg,
 			     const void *val, size_t val_len)
 {
+	u8 *u8 = map->work_buf;
 	void *buf;
 	int ret = -ENOTSUPP;
 	size_t len;
+	int i;
+
+	/* Check for unwritable registers before we start */
+	if (map->writeable_reg)
+		for (i = 0; i < val_len / map->format.val_bytes; i++)
+			if (!map->writeable_reg(map->dev, reg + i))
+				return -EINVAL;
 
 	map->format.format_reg(map->work_buf, reg);
 
-	/* Try to do a gather write if we can */
-	if (map->bus->gather_write)
+	u8[0] |= map->write_flag_mask;
+
+	trace_regmap_hw_write_start(map->dev, reg,
+				    val_len / map->format.val_bytes);
+
+	/* If we're doing a single register write we can probably just
+	 * send the work_buf directly, otherwise try to do a gather
+	 * write.
+	 */
+	if (val == map->work_buf + map->format.reg_bytes)
+		ret = map->bus->write(map->dev, map->work_buf,
+				      map->format.reg_bytes + val_len);
+	else if (map->bus->gather_write)
 		ret = map->bus->gather_write(map->dev, map->work_buf,
 					     map->format.reg_bytes,
 					     val, val_len);
 
-	/* Otherwise fall back on linearising by hand. */
+	/* If that didn't work fall back on linearising by hand. */
 	if (ret == -ENOTSUPP) {
 		len = map->format.reg_bytes + val_len;
 		buf = kmalloc(len, GFP_KERNEL);
@@ -219,19 +290,39 @@
 		kfree(buf);
 	}
 
+	trace_regmap_hw_write_done(map->dev, reg,
+				   val_len / map->format.val_bytes);
+
 	return ret;
 }
 
-static int _regmap_write(struct regmap *map, unsigned int reg,
-			 unsigned int val)
+int _regmap_write(struct regmap *map, unsigned int reg,
+		  unsigned int val)
 {
+	int ret;
 	BUG_ON(!map->format.format_write && !map->format.format_val);
 
+	if (!map->cache_bypass) {
+		ret = regcache_write(map, reg, val);
+		if (ret != 0)
+			return ret;
+		if (map->cache_only)
+			return 0;
+	}
+
+	trace_regmap_reg_write(map->dev, reg, val);
+
 	if (map->format.format_write) {
 		map->format.format_write(map, reg, val);
 
-		return map->bus->write(map->dev, map->work_buf,
-				       map->format.buf_size);
+		trace_regmap_hw_write_start(map->dev, reg, 1);
+
+		ret = map->bus->write(map->dev, map->work_buf,
+				      map->format.buf_size);
+
+		trace_regmap_hw_write_done(map->dev, reg, 1);
+
+		return ret;
 	} else {
 		map->format.format_val(map->work_buf + map->format.reg_bytes,
 				       val);
@@ -286,6 +377,8 @@
 {
 	int ret;
 
+	WARN_ON(map->cache_type != REGCACHE_NONE);
+
 	mutex_lock(&map->lock);
 
 	ret = _regmap_raw_write(map, reg, val, val_len);
@@ -305,20 +398,23 @@
 	map->format.format_reg(map->work_buf, reg);
 
 	/*
-	 * Some buses flag reads by setting the high bits in the
+	 * Some buses or devices flag reads by setting the high bits in the
 	 * register addresss; since it's always the high bits for all
 	 * current formats we can do this here rather than in
 	 * formatting.  This may break if we get interesting formats.
 	 */
-	if (map->bus->read_flag_mask)
-		u8[0] |= map->bus->read_flag_mask;
+	u8[0] |= map->read_flag_mask;
+
+	trace_regmap_hw_read_start(map->dev, reg,
+				   val_len / map->format.val_bytes);
 
 	ret = map->bus->read(map->dev, map->work_buf, map->format.reg_bytes,
 			     val, val_len);
-	if (ret != 0)
-		return ret;
 
-	return 0;
+	trace_regmap_hw_read_done(map->dev, reg,
+				  val_len / map->format.val_bytes);
+
+	return ret;
 }
 
 static int _regmap_read(struct regmap *map, unsigned int reg,
@@ -329,9 +425,20 @@
 	if (!map->format.parse_val)
 		return -EINVAL;
 
+	if (!map->cache_bypass) {
+		ret = regcache_read(map, reg, val);
+		if (ret == 0)
+			return 0;
+	}
+
+	if (map->cache_only)
+		return -EBUSY;
+
 	ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes);
-	if (ret == 0)
+	if (ret == 0) {
 		*val = map->format.parse_val(map->work_buf);
+		trace_regmap_reg_read(map->dev, reg, *val);
+	}
 
 	return ret;
 }
@@ -375,6 +482,14 @@
 		    size_t val_len)
 {
 	int ret;
+	int i;
+	bool vol = true;
+
+	for (i = 0; i < val_len / map->format.val_bytes; i++)
+		if (!regmap_volatile(map, reg + i))
+			vol = false;
+
+	WARN_ON(!vol && map->cache_type != REGCACHE_NONE);
 
 	mutex_lock(&map->lock);
 
@@ -402,16 +517,30 @@
 {
 	int ret, i;
 	size_t val_bytes = map->format.val_bytes;
+	bool vol = true;
 
 	if (!map->format.parse_val)
 		return -EINVAL;
 
-	ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
-	if (ret != 0)
-		return ret;
+	/* Is this a block of volatile registers? */
+	for (i = 0; i < val_count; i++)
+		if (!regmap_volatile(map, reg + i))
+			vol = false;
 
-	for (i = 0; i < val_count * val_bytes; i += val_bytes)
-		map->format.parse_val(val + i);
+	if (vol || map->cache_type == REGCACHE_NONE) {
+		ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
+		if (ret != 0)
+			return ret;
+
+		for (i = 0; i < val_count * val_bytes; i += val_bytes)
+			map->format.parse_val(val + i);
+	} else {
+		for (i = 0; i < val_count; i++) {
+			ret = regmap_read(map, reg + i, val + (i * val_bytes));
+			if (ret != 0)
+				return ret;
+		}
+	}
 
 	return 0;
 }
@@ -450,3 +579,11 @@
 	return ret;
 }
 EXPORT_SYMBOL_GPL(regmap_update_bits);
+
+static int __init regmap_initcall(void)
+{
+	regmap_debugfs_initcall();
+
+	return 0;
+}
+postcore_initcall(regmap_initcall);
diff -druN linux-libre-3.1-gnu/drivers/base/regmap/regmap-debugfs.c linux-libre-3.2-gnu/drivers/base/regmap/regmap-debugfs.c
--- linux-libre-3.1-gnu/drivers/base/regmap/regmap-debugfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/base/regmap/regmap-debugfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,209 @@
+/*
+ * Register map access API - debugfs
+ *
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+
+#include "internal.h"
+
+static struct dentry *regmap_debugfs_root;
+
+/* Calculate the length of a fixed format  */
+static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size)
+{
+	snprintf(buf, buf_size, "%x", max_val);
+	return strlen(buf);
+}
+
+static int regmap_open_file(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	int reg_len, val_len, tot_len;
+	size_t buf_pos = 0;
+	loff_t p = 0;
+	ssize_t ret;
+	int i;
+	struct regmap *map = file->private_data;
+	char *buf;
+	unsigned int val;
+
+	if (*ppos < 0 || !count)
+		return -EINVAL;
+
+	buf = kmalloc(count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	/* Calculate the length of a fixed format  */
+	reg_len = regmap_calc_reg_len(map->max_register, buf, count);
+	val_len = 2 * map->format.val_bytes;
+	tot_len = reg_len + val_len + 3;      /* : \n */
+
+	for (i = 0; i < map->max_register + 1; i++) {
+		if (!regmap_readable(map, i))
+			continue;
+
+		if (regmap_precious(map, i))
+			continue;
+
+		/* If we're in the region the user is trying to read */
+		if (p >= *ppos) {
+			/* ...but not beyond it */
+			if (buf_pos >= count - 1 - tot_len)
+				break;
+
+			/* Format the register */
+			snprintf(buf + buf_pos, count - buf_pos, "%.*x: ",
+				 reg_len, i);
+			buf_pos += reg_len + 2;
+
+			/* Format the value, write all X if we can't read */
+			ret = regmap_read(map, i, &val);
+			if (ret == 0)
+				snprintf(buf + buf_pos, count - buf_pos,
+					 "%.*x", val_len, val);
+			else
+				memset(buf + buf_pos, 'X', val_len);
+			buf_pos += 2 * map->format.val_bytes;
+
+			buf[buf_pos++] = '\n';
+		}
+		p += tot_len;
+	}
+
+	ret = buf_pos;
+
+	if (copy_to_user(user_buf, buf, buf_pos)) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	*ppos += buf_pos;
+
+out:
+	kfree(buf);
+	return ret;
+}
+
+static const struct file_operations regmap_map_fops = {
+	.open = regmap_open_file,
+	.read = regmap_map_read_file,
+	.llseek = default_llseek,
+};
+
+static ssize_t regmap_access_read_file(struct file *file,
+				       char __user *user_buf, size_t count,
+				       loff_t *ppos)
+{
+	int reg_len, tot_len;
+	size_t buf_pos = 0;
+	loff_t p = 0;
+	ssize_t ret;
+	int i;
+	struct regmap *map = file->private_data;
+	char *buf;
+
+	if (*ppos < 0 || !count)
+		return -EINVAL;
+
+	buf = kmalloc(count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	/* Calculate the length of a fixed format  */
+	reg_len = regmap_calc_reg_len(map->max_register, buf, count);
+	tot_len = reg_len + 10; /* ': R W V P\n' */
+
+	for (i = 0; i < map->max_register + 1; i++) {
+		/* Ignore registers which are neither readable nor writable */
+		if (!regmap_readable(map, i) && !regmap_writeable(map, i))
+			continue;
+
+		/* If we're in the region the user is trying to read */
+		if (p >= *ppos) {
+			/* ...but not beyond it */
+			if (buf_pos >= count - 1 - tot_len)
+				break;
+
+			/* Format the register */
+			snprintf(buf + buf_pos, count - buf_pos,
+				 "%.*x: %c %c %c %c\n",
+				 reg_len, i,
+				 regmap_readable(map, i) ? 'y' : 'n',
+				 regmap_writeable(map, i) ? 'y' : 'n',
+				 regmap_volatile(map, i) ? 'y' : 'n',
+				 regmap_precious(map, i) ? 'y' : 'n');
+
+			buf_pos += tot_len;
+		}
+		p += tot_len;
+	}
+
+	ret = buf_pos;
+
+	if (copy_to_user(user_buf, buf, buf_pos)) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	*ppos += buf_pos;
+
+out:
+	kfree(buf);
+	return ret;
+}
+
+static const struct file_operations regmap_access_fops = {
+	.open = regmap_open_file,
+	.read = regmap_access_read_file,
+	.llseek = default_llseek,
+};
+
+void regmap_debugfs_init(struct regmap *map)
+{
+	map->debugfs = debugfs_create_dir(dev_name(map->dev),
+					  regmap_debugfs_root);
+	if (!map->debugfs) {
+		dev_warn(map->dev, "Failed to create debugfs directory\n");
+		return;
+	}
+
+	if (map->max_register) {
+		debugfs_create_file("registers", 0400, map->debugfs,
+				    map, &regmap_map_fops);
+		debugfs_create_file("access", 0400, map->debugfs,
+				    map, &regmap_access_fops);
+	}
+}
+
+void regmap_debugfs_exit(struct regmap *map)
+{
+	debugfs_remove_recursive(map->debugfs);
+}
+
+void regmap_debugfs_initcall(void)
+{
+	regmap_debugfs_root = debugfs_create_dir("regmap", NULL);
+	if (!regmap_debugfs_root) {
+		pr_warn("regmap: Failed to create debugfs root\n");
+		return;
+	}
+}
diff -druN linux-libre-3.1-gnu/drivers/base/regmap/regmap-i2c.c linux-libre-3.2-gnu/drivers/base/regmap/regmap-i2c.c
--- linux-libre-3.1-gnu/drivers/base/regmap/regmap-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/regmap/regmap-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -90,11 +90,9 @@
 }
 
 static struct regmap_bus regmap_i2c = {
-	.type = &i2c_bus_type,
 	.write = regmap_i2c_write,
 	.gather_write = regmap_i2c_gather_write,
 	.read = regmap_i2c_read,
-	.owner = THIS_MODULE,
 };
 
 /**
diff -druN linux-libre-3.1-gnu/drivers/base/regmap/regmap-spi.c linux-libre-3.2-gnu/drivers/base/regmap/regmap-spi.c
--- linux-libre-3.1-gnu/drivers/base/regmap/regmap-spi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/regmap/regmap-spi.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,11 +48,9 @@
 }
 
 static struct regmap_bus regmap_spi = {
-	.type = &spi_bus_type,
 	.write = regmap_spi_write,
 	.gather_write = regmap_spi_gather_write,
 	.read = regmap_spi_read,
-	.owner = THIS_MODULE,
 	.read_flag_mask = 0x80,
 };
 
diff -druN linux-libre-3.1-gnu/drivers/base/transport_class.c linux-libre-3.2-gnu/drivers/base/transport_class.c
--- linux-libre-3.1-gnu/drivers/base/transport_class.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/base/transport_class.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
  * transport class is framed entirely in terms of generic devices to
  * allow it to be used by any physical HBA in the system.
  */
+#include <linux/export.h>
 #include <linux/attribute_container.h>
 #include <linux/transport_class.h>
 
diff -druN linux-libre-3.1-gnu/drivers/bcma/bcma_private.h linux-libre-3.2-gnu/drivers/bcma/bcma_private.h
--- linux-libre-3.1-gnu/drivers/bcma/bcma_private.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bcma/bcma_private.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,13 +15,29 @@
 /* main.c */
 int bcma_bus_register(struct bcma_bus *bus);
 void bcma_bus_unregister(struct bcma_bus *bus);
+int __init bcma_bus_early_register(struct bcma_bus *bus,
+				   struct bcma_device *core_cc,
+				   struct bcma_device *core_mips);
 
 /* scan.c */
 int bcma_bus_scan(struct bcma_bus *bus);
+int __init bcma_bus_scan_early(struct bcma_bus *bus,
+			       struct bcma_device_id *match,
+			       struct bcma_device *core);
+void bcma_init_bus(struct bcma_bus *bus);
 
 /* sprom.c */
 int bcma_sprom_get(struct bcma_bus *bus);
 
+/* driver_chipcommon.c */
+#ifdef CONFIG_BCMA_DRIVER_MIPS
+void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
+#endif /* CONFIG_BCMA_DRIVER_MIPS */
+
+/* driver_chipcommon_pmu.c */
+u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc);
+u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
+
 #ifdef CONFIG_BCMA_HOST_PCI
 /* host_pci.c */
 extern int __init bcma_host_pci_init(void);
diff -druN linux-libre-3.1-gnu/drivers/bcma/core.c linux-libre-3.2-gnu/drivers/bcma/core.c
--- linux-libre-3.1-gnu/drivers/bcma/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bcma/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
  */
 
 #include "bcma_private.h"
+#include <linux/export.h>
 #include <linux/bcma/bcma.h>
 
 bool bcma_core_is_enabled(struct bcma_device *core)
@@ -110,6 +111,8 @@
 u32 bcma_core_dma_translation(struct bcma_device *core)
 {
 	switch (core->bus->hosttype) {
+	case BCMA_HOSTTYPE_SOC:
+		return 0;
 	case BCMA_HOSTTYPE_PCI:
 		if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64)
 			return BCMA_DMA_TRANSLATION_DMA64_CMT;
diff -druN linux-libre-3.1-gnu/drivers/bcma/driver_chipcommon.c linux-libre-3.2-gnu/drivers/bcma/driver_chipcommon.c
--- linux-libre-3.1-gnu/drivers/bcma/driver_chipcommon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bcma/driver_chipcommon.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include "bcma_private.h"
+#include <linux/export.h>
 #include <linux/bcma/bcma.h>
 
 static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
@@ -26,6 +27,9 @@
 	u32 leddc_on = 10;
 	u32 leddc_off = 90;
 
+	if (cc->setup_done)
+		return;
+
 	if (cc->core->id.rev >= 11)
 		cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
 	cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
@@ -52,6 +56,8 @@
 			((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
 			 (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
 	}
+
+	cc->setup_done = true;
 }
 
 /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
@@ -101,3 +107,51 @@
 {
 	return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
 }
+
+#ifdef CONFIG_BCMA_DRIVER_MIPS
+void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
+{
+	unsigned int irq;
+	u32 baud_base;
+	u32 i;
+	unsigned int ccrev = cc->core->id.rev;
+	struct bcma_serial_port *ports = cc->serial_ports;
+
+	if (ccrev >= 11 && ccrev != 15) {
+		/* Fixed ALP clock */
+		baud_base = bcma_pmu_alp_clock(cc);
+		if (ccrev >= 21) {
+			/* Turn off UART clock before switching clocksource. */
+			bcma_cc_write32(cc, BCMA_CC_CORECTL,
+				       bcma_cc_read32(cc, BCMA_CC_CORECTL)
+				       & ~BCMA_CC_CORECTL_UARTCLKEN);
+		}
+		/* Set the override bit so we don't divide it */
+		bcma_cc_write32(cc, BCMA_CC_CORECTL,
+			       bcma_cc_read32(cc, BCMA_CC_CORECTL)
+			       | BCMA_CC_CORECTL_UARTCLK0);
+		if (ccrev >= 21) {
+			/* Re-enable the UART clock. */
+			bcma_cc_write32(cc, BCMA_CC_CORECTL,
+				       bcma_cc_read32(cc, BCMA_CC_CORECTL)
+				       | BCMA_CC_CORECTL_UARTCLKEN);
+		}
+	} else {
+		pr_err("serial not supported on this device ccrev: 0x%x\n",
+		       ccrev);
+		return;
+	}
+
+	irq = bcma_core_mips_irq(cc->core);
+
+	/* Determine the registers of the UARTs */
+	cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
+	for (i = 0; i < cc->nr_serial_ports; i++) {
+		ports[i].regs = cc->core->io_addr + BCMA_CC_UART0_DATA +
+				(i * 256);
+		ports[i].irq = irq;
+		ports[i].baud_base = baud_base;
+		ports[i].reg_shift = 0;
+	}
+}
+#endif /* CONFIG_BCMA_DRIVER_MIPS */
diff -druN linux-libre-3.1-gnu/drivers/bcma/driver_chipcommon_pmu.c linux-libre-3.2-gnu/drivers/bcma/driver_chipcommon_pmu.c
--- linux-libre-3.1-gnu/drivers/bcma/driver_chipcommon_pmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bcma/driver_chipcommon_pmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,22 +9,50 @@
  */
 
 #include "bcma_private.h"
+#include <linux/export.h>
 #include <linux/bcma/bcma.h>
 
-static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
-					u32 offset, u32 mask, u32 set)
+static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
 {
-	u32 value;
+	bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
+	bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
+	return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
+}
 
-	bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
+void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value)
+{
+	bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
+	bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
+	bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value);
+}
+EXPORT_SYMBOL_GPL(bcma_chipco_pll_write);
+
+void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
+			     u32 set)
+{
+	bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
+	bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
+	bcma_cc_maskset32(cc, BCMA_CC_PLLCTL_DATA, mask, set);
+}
+EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset);
+
+void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
+				 u32 offset, u32 mask, u32 set)
+{
 	bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset);
 	bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
-	value = bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA);
-	value &= mask;
-	value |= set;
-	bcma_cc_write32(cc, BCMA_CC_CHIPCTL_DATA, value);
-	bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA);
+	bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL_DATA, mask, set);
 }
+EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset);
+
+void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
+				u32 set)
+{
+	bcma_cc_write32(cc, BCMA_CC_REGCTL_ADDR, offset);
+	bcma_cc_read32(cc, BCMA_CC_REGCTL_ADDR);
+	bcma_cc_maskset32(cc, BCMA_CC_REGCTL_DATA, mask, set);
+}
+EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset);
 
 static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
 {
@@ -83,6 +111,24 @@
 	}
 }
 
+/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */
+void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable)
+{
+	struct bcma_bus *bus = cc->core->bus;
+	u32 val;
+
+	val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL);
+	if (enable) {
+		val |= BCMA_CHIPCTL_4331_EXTPA_EN;
+		if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11)
+			val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
+	} else {
+		val &= ~BCMA_CHIPCTL_4331_EXTPA_EN;
+		val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
+	}
+	bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val);
+}
+
 void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
 {
 	struct bcma_bus *bus = cc->core->bus;
@@ -92,7 +138,7 @@
 		bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7);
 		break;
 	case 0x4331:
-		pr_err("Enabling Ext PA lines not implemented\n");
+		/* BCM4331 workaround is SPROM-related, we put it in sprom.c */
 		break;
 	case 43224:
 		if (bus->chipinfo.rev == 0) {
@@ -136,3 +182,129 @@
 	bcma_pmu_swreg_init(cc);
 	bcma_pmu_workarounds(cc);
 }
+
+u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc)
+{
+	struct bcma_bus *bus = cc->core->bus;
+
+	switch (bus->chipinfo.id) {
+	case 0x4716:
+	case 0x4748:
+	case 47162:
+	case 0x4313:
+	case 0x5357:
+	case 0x4749:
+	case 53572:
+		/* always 20Mhz */
+		return 20000 * 1000;
+	case 0x5356:
+	case 0x5300:
+		/* always 25Mhz */
+		return 25000 * 1000;
+	default:
+		pr_warn("No ALP clock specified for %04X device, "
+			"pmu rev. %d, using default %d Hz\n",
+			bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
+	}
+	return BCMA_CC_PMU_ALP_CLOCK;
+}
+
+/* Find the output of the "m" pll divider given pll controls that start with
+ * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
+ */
+static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
+{
+	u32 tmp, div, ndiv, p1, p2, fc;
+	struct bcma_bus *bus = cc->core->bus;
+
+	BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0));
+
+	BUG_ON(!m || m > 4);
+
+	if (bus->chipinfo.id == 0x5357 || bus->chipinfo.id == 0x4749) {
+		/* Detect failure in clock setting */
+		tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
+		if (tmp & 0x40000)
+			return 133 * 1000000;
+	}
+
+	tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF);
+	p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT;
+	p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT;
+
+	tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF);
+	div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) &
+		BCMA_CC_PPL_MDIV_MASK;
+
+	tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF);
+	ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT;
+
+	/* Do calculation in Mhz */
+	fc = bcma_pmu_alp_clock(cc) / 1000000;
+	fc = (p1 * ndiv * fc) / p2;
+
+	/* Return clock in Hertz */
+	return (fc / div) * 1000000;
+}
+
+/* query bus clock frequency for PMU-enabled chipcommon */
+u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
+{
+	struct bcma_bus *bus = cc->core->bus;
+
+	switch (bus->chipinfo.id) {
+	case 0x4716:
+	case 0x4748:
+	case 47162:
+		return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
+				      BCMA_CC_PMU5_MAINPLL_SSB);
+	case 0x5356:
+		return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
+				      BCMA_CC_PMU5_MAINPLL_SSB);
+	case 0x5357:
+	case 0x4749:
+		return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
+				      BCMA_CC_PMU5_MAINPLL_SSB);
+	case 0x5300:
+		return bcma_pmu_clock(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
+				      BCMA_CC_PMU5_MAINPLL_SSB);
+	case 53572:
+		return 75000000;
+	default:
+		pr_warn("No backplane clock specified for %04X device, "
+			"pmu rev. %d, using default %d Hz\n",
+			bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
+	}
+	return BCMA_CC_PMU_HT_CLOCK;
+}
+
+/* query cpu clock frequency for PMU-enabled chipcommon */
+u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc)
+{
+	struct bcma_bus *bus = cc->core->bus;
+
+	if (bus->chipinfo.id == 53572)
+		return 300000000;
+
+	if (cc->pmu.rev >= 5) {
+		u32 pll;
+		switch (bus->chipinfo.id) {
+		case 0x5356:
+			pll = BCMA_CC_PMU5356_MAINPLL_PLL0;
+			break;
+		case 0x5357:
+		case 0x4749:
+			pll = BCMA_CC_PMU5357_MAINPLL_PLL0;
+			break;
+		default:
+			pll = BCMA_CC_PMU4716_MAINPLL_PLL0;
+			break;
+		}
+
+		/* TODO: if (bus->chipinfo.id == 0x5300)
+		  return si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU); */
+		return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
+	}
+
+	return bcma_pmu_get_clockcontrol(cc);
+}
diff -druN linux-libre-3.1-gnu/drivers/bcma/driver_mips.c linux-libre-3.2-gnu/drivers/bcma/driver_mips.c
--- linux-libre-3.1-gnu/drivers/bcma/driver_mips.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/bcma/driver_mips.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,256 @@
+/*
+ * Broadcom specific AMBA
+ * Broadcom MIPS32 74K core driver
+ *
+ * Copyright 2009, Broadcom Corporation
+ * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com>
+ * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+
+#include <linux/bcma/bcma.h>
+
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/time.h>
+
+/* The 47162a0 hangs when reading MIPS DMP registers registers */
+static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
+{
+	return dev->bus->chipinfo.id == 47162 && dev->bus->chipinfo.rev == 0 &&
+	       dev->id.id == BCMA_CORE_MIPS_74K;
+}
+
+/* The 5357b0 hangs when reading USB20H DMP registers */
+static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
+{
+	return (dev->bus->chipinfo.id == 0x5357 ||
+		dev->bus->chipinfo.id == 0x4749) &&
+	       dev->bus->chipinfo.pkg == 11 &&
+	       dev->id.id == BCMA_CORE_USB20_HOST;
+}
+
+static inline u32 mips_read32(struct bcma_drv_mips *mcore,
+			      u16 offset)
+{
+	return bcma_read32(mcore->core, offset);
+}
+
+static inline void mips_write32(struct bcma_drv_mips *mcore,
+				u16 offset,
+				u32 value)
+{
+	bcma_write32(mcore->core, offset, value);
+}
+
+static const u32 ipsflag_irq_mask[] = {
+	0,
+	BCMA_MIPS_IPSFLAG_IRQ1,
+	BCMA_MIPS_IPSFLAG_IRQ2,
+	BCMA_MIPS_IPSFLAG_IRQ3,
+	BCMA_MIPS_IPSFLAG_IRQ4,
+};
+
+static const u32 ipsflag_irq_shift[] = {
+	0,
+	BCMA_MIPS_IPSFLAG_IRQ1_SHIFT,
+	BCMA_MIPS_IPSFLAG_IRQ2_SHIFT,
+	BCMA_MIPS_IPSFLAG_IRQ3_SHIFT,
+	BCMA_MIPS_IPSFLAG_IRQ4_SHIFT,
+};
+
+static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
+{
+	u32 flag;
+
+	if (bcma_core_mips_bcm47162a0_quirk(dev))
+		return dev->core_index;
+	if (bcma_core_mips_bcm5357b0_quirk(dev))
+		return dev->core_index;
+	flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
+
+	return flag & 0x1F;
+}
+
+/* Get the MIPS IRQ assignment for a specified device.
+ * If unassigned, 0 is returned.
+ */
+unsigned int bcma_core_mips_irq(struct bcma_device *dev)
+{
+	struct bcma_device *mdev = dev->bus->drv_mips.core;
+	u32 irqflag;
+	unsigned int irq;
+
+	irqflag = bcma_core_mips_irqflag(dev);
+
+	for (irq = 1; irq <= 4; irq++)
+		if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
+		    (1 << irqflag))
+			return irq;
+
+	return 0;
+}
+EXPORT_SYMBOL(bcma_core_mips_irq);
+
+static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
+{
+	unsigned int oldirq = bcma_core_mips_irq(dev);
+	struct bcma_bus *bus = dev->bus;
+	struct bcma_device *mdev = bus->drv_mips.core;
+	u32 irqflag;
+
+	irqflag = bcma_core_mips_irqflag(dev);
+	BUG_ON(oldirq == 6);
+
+	dev->irq = irq + 2;
+
+	/* clear the old irq */
+	if (oldirq == 0)
+		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
+			    bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
+			    ~(1 << irqflag));
+	else
+		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0);
+
+	/* assign the new one */
+	if (irq == 0) {
+		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
+			    bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
+			    (1 << irqflag));
+	} else {
+		u32 oldirqflag = bcma_read32(mdev,
+					     BCMA_MIPS_MIPS74K_INTMASK(irq));
+		if (oldirqflag) {
+			struct bcma_device *core;
+
+			/* backplane irq line is in use, find out who uses
+			 * it and set user to irq 0
+			 */
+			list_for_each_entry_reverse(core, &bus->cores, list) {
+				if ((1 << bcma_core_mips_irqflag(core)) ==
+				    oldirqflag) {
+					bcma_core_mips_set_irq(core, 0);
+					break;
+				}
+			}
+		}
+		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq),
+			     1 << irqflag);
+	}
+
+	pr_info("set_irq: core 0x%04x, irq %d => %d\n",
+		dev->id.id, oldirq + 2, irq + 2);
+}
+
+static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
+{
+	int i;
+	static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
+	printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
+	for (i = 0; i <= 6; i++)
+		printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
+	printk("\n");
+}
+
+static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
+{
+	struct bcma_device *core;
+
+	list_for_each_entry_reverse(core, &bus->cores, list) {
+		bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
+	}
+}
+
+u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
+{
+	struct bcma_bus *bus = mcore->core->bus;
+
+	if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
+		return bcma_pmu_get_clockcpu(&bus->drv_cc);
+
+	pr_err("No PMU available, need this to get the cpu clock\n");
+	return 0;
+}
+EXPORT_SYMBOL(bcma_cpu_clock);
+
+static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
+{
+	struct bcma_bus *bus = mcore->core->bus;
+
+	switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
+	case BCMA_CC_FLASHT_STSER:
+	case BCMA_CC_FLASHT_ATSER:
+		pr_err("Serial flash not supported.\n");
+		break;
+	case BCMA_CC_FLASHT_PARA:
+		pr_info("found parallel flash.\n");
+		bus->drv_cc.pflash.window = 0x1c000000;
+		bus->drv_cc.pflash.window_size = 0x02000000;
+
+		if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) &
+		     BCMA_CC_FLASH_CFG_DS) == 0)
+			bus->drv_cc.pflash.buswidth = 1;
+		else
+			bus->drv_cc.pflash.buswidth = 2;
+		break;
+	default:
+		pr_err("flash not supported.\n");
+	}
+}
+
+void bcma_core_mips_init(struct bcma_drv_mips *mcore)
+{
+	struct bcma_bus *bus;
+	struct bcma_device *core;
+	bus = mcore->core->bus;
+
+	pr_info("Initializing MIPS core...\n");
+
+	if (!mcore->setup_done)
+		mcore->assigned_irqs = 1;
+
+	/* Assign IRQs to all cores on the bus */
+	list_for_each_entry_reverse(core, &bus->cores, list) {
+		int mips_irq;
+		if (core->irq)
+			continue;
+
+		mips_irq = bcma_core_mips_irq(core);
+		if (mips_irq > 4)
+			core->irq = 0;
+		else
+			core->irq = mips_irq + 2;
+		if (core->irq > 5)
+			continue;
+		switch (core->id.id) {
+		case BCMA_CORE_PCI:
+		case BCMA_CORE_PCIE:
+		case BCMA_CORE_ETHERNET:
+		case BCMA_CORE_ETHERNET_GBIT:
+		case BCMA_CORE_MAC_GBIT:
+		case BCMA_CORE_80211:
+		case BCMA_CORE_USB20_HOST:
+			/* These devices get their own IRQ line if available,
+			 * the rest goes on IRQ0
+			 */
+			if (mcore->assigned_irqs <= 4)
+				bcma_core_mips_set_irq(core,
+						       mcore->assigned_irqs++);
+			break;
+		}
+	}
+	pr_info("IRQ reconfiguration done\n");
+	bcma_core_mips_dump_irq(bus);
+
+	if (mcore->setup_done)
+		return;
+
+	bcma_chipco_serial_init(&bus->drv_cc);
+	bcma_core_mips_flash_detect(mcore);
+	mcore->setup_done = true;
+}
diff -druN linux-libre-3.1-gnu/drivers/bcma/driver_pci.c linux-libre-3.2-gnu/drivers/bcma/driver_pci.c
--- linux-libre-3.1-gnu/drivers/bcma/driver_pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bcma/driver_pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include "bcma_private.h"
+#include <linux/export.h>
 #include <linux/bcma/bcma.h>
 
 /**************************************************
@@ -173,7 +174,7 @@
 		return false;
 
 #ifdef CONFIG_SSB_DRIVER_PCICORE
-	if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI)
+	if (bus->sprom.boardflags_lo & SSB_BFL_NOPCI)
 		return false;
 #endif /* CONFIG_SSB_DRIVER_PCICORE */
 
@@ -189,6 +190,9 @@
 
 void bcma_core_pci_init(struct bcma_drv_pci *pc)
 {
+	if (pc->setup_done)
+		return;
+
 	if (bcma_core_pci_is_in_hostmode(pc)) {
 #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
 		bcma_core_pci_hostmode_init(pc);
@@ -198,6 +202,8 @@
 	} else {
 		bcma_core_pci_clientmode_init(pc);
 	}
+
+	pc->setup_done = true;
 }
 
 int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
@@ -205,7 +211,14 @@
 {
 	struct pci_dev *pdev = pc->core->bus->host_pci;
 	u32 coremask, tmp;
-	int err;
+	int err = 0;
+
+	if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
+		/* This bcma device is not on a PCI host-bus. So the IRQs are
+		 * not routed through the PCI core.
+		 * So we must not enable routing through the PCI core. */
+		goto out;
+	}
 
 	err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
 	if (err)
diff -druN linux-libre-3.1-gnu/drivers/bcma/host_pci.c linux-libre-3.2-gnu/drivers/bcma/host_pci.c
--- linux-libre-3.1-gnu/drivers/bcma/host_pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bcma/host_pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/slab.h>
 #include <linux/bcma/bcma.h>
 #include <linux/pci.h>
+#include <linux/module.h>
 
 static void bcma_host_pci_switch_core(struct bcma_device *core)
 {
diff -druN linux-libre-3.1-gnu/drivers/bcma/host_soc.c linux-libre-3.2-gnu/drivers/bcma/host_soc.c
--- linux-libre-3.1-gnu/drivers/bcma/host_soc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/bcma/host_soc.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,183 @@
+/*
+ * Broadcom specific AMBA
+ * System on Chip (SoC) Host
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+#include "scan.h"
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_soc.h>
+
+static u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset)
+{
+	return readb(core->io_addr + offset);
+}
+
+static u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset)
+{
+	return readw(core->io_addr + offset);
+}
+
+static u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset)
+{
+	return readl(core->io_addr + offset);
+}
+
+static void bcma_host_soc_write8(struct bcma_device *core, u16 offset,
+				 u8 value)
+{
+	writeb(value, core->io_addr + offset);
+}
+
+static void bcma_host_soc_write16(struct bcma_device *core, u16 offset,
+				 u16 value)
+{
+	writew(value, core->io_addr + offset);
+}
+
+static void bcma_host_soc_write32(struct bcma_device *core, u16 offset,
+				 u32 value)
+{
+	writel(value, core->io_addr + offset);
+}
+
+#ifdef CONFIG_BCMA_BLOCKIO
+static void bcma_host_soc_block_read(struct bcma_device *core, void *buffer,
+				     size_t count, u16 offset, u8 reg_width)
+{
+	void __iomem *addr = core->io_addr + offset;
+
+	switch (reg_width) {
+	case sizeof(u8): {
+		u8 *buf = buffer;
+
+		while (count) {
+			*buf = __raw_readb(addr);
+			buf++;
+			count--;
+		}
+		break;
+	}
+	case sizeof(u16): {
+		__le16 *buf = buffer;
+
+		WARN_ON(count & 1);
+		while (count) {
+			*buf = (__force __le16)__raw_readw(addr);
+			buf++;
+			count -= 2;
+		}
+		break;
+	}
+	case sizeof(u32): {
+		__le32 *buf = buffer;
+
+		WARN_ON(count & 3);
+		while (count) {
+			*buf = (__force __le32)__raw_readl(addr);
+			buf++;
+			count -= 4;
+		}
+		break;
+	}
+	default:
+		WARN_ON(1);
+	}
+}
+
+static void bcma_host_soc_block_write(struct bcma_device *core,
+				      const void *buffer,
+				      size_t count, u16 offset, u8 reg_width)
+{
+	void __iomem *addr = core->io_addr + offset;
+
+	switch (reg_width) {
+	case sizeof(u8): {
+		const u8 *buf = buffer;
+
+		while (count) {
+			__raw_writeb(*buf, addr);
+			buf++;
+			count--;
+		}
+		break;
+	}
+	case sizeof(u16): {
+		const __le16 *buf = buffer;
+
+		WARN_ON(count & 1);
+		while (count) {
+			__raw_writew((__force u16)(*buf), addr);
+			buf++;
+			count -= 2;
+		}
+		break;
+	}
+	case sizeof(u32): {
+		const __le32 *buf = buffer;
+
+		WARN_ON(count & 3);
+		while (count) {
+			__raw_writel((__force u32)(*buf), addr);
+			buf++;
+			count -= 4;
+		}
+		break;
+	}
+	default:
+		WARN_ON(1);
+	}
+}
+#endif /* CONFIG_BCMA_BLOCKIO */
+
+static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset)
+{
+	return readl(core->io_wrap + offset);
+}
+
+static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
+				  u32 value)
+{
+	writel(value, core->io_wrap + offset);
+}
+
+const struct bcma_host_ops bcma_host_soc_ops = {
+	.read8		= bcma_host_soc_read8,
+	.read16		= bcma_host_soc_read16,
+	.read32		= bcma_host_soc_read32,
+	.write8		= bcma_host_soc_write8,
+	.write16	= bcma_host_soc_write16,
+	.write32	= bcma_host_soc_write32,
+#ifdef CONFIG_BCMA_BLOCKIO
+	.block_read	= bcma_host_soc_block_read,
+	.block_write	= bcma_host_soc_block_write,
+#endif
+	.aread32	= bcma_host_soc_aread32,
+	.awrite32	= bcma_host_soc_awrite32,
+};
+
+int __init bcma_host_soc_register(struct bcma_soc *soc)
+{
+	struct bcma_bus *bus = &soc->bus;
+	int err;
+
+	/* iomap only first core. We have to read some register on this core
+	 * to scan the bus.
+	 */
+	bus->mmio = ioremap_nocache(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
+	if (!bus->mmio)
+		return -ENOMEM;
+
+	/* Host specific */
+	bus->hosttype = BCMA_HOSTTYPE_SOC;
+	bus->ops = &bcma_host_soc_ops;
+
+	/* Register */
+	err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips);
+	if (err)
+		iounmap(bus->mmio);
+
+	return err;
+}
diff -druN linux-libre-3.1-gnu/drivers/bcma/Kconfig linux-libre-3.2-gnu/drivers/bcma/Kconfig
--- linux-libre-3.1-gnu/drivers/bcma/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bcma/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,19 @@
 	help
 	  PCI core hostmode operation (external PCI bus).
 
+config BCMA_HOST_SOC
+	bool
+	depends on BCMA_DRIVER_MIPS
+
+config BCMA_DRIVER_MIPS
+	bool "BCMA Broadcom MIPS core driver"
+	depends on BCMA && MIPS
+	help
+	  Driver for the Broadcom MIPS core attached to Broadcom specific
+	  Advanced Microcontroller Bus.
+
+	  If unsure, say N
+
 config BCMA_DEBUG
 	bool "BCMA debugging"
 	depends on BCMA
diff -druN linux-libre-3.1-gnu/drivers/bcma/main.c linux-libre-3.2-gnu/drivers/bcma/main.c
--- linux-libre-3.1-gnu/drivers/bcma/main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bcma/main.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
  */
 
 #include "bcma_private.h"
+#include <linux/module.h>
 #include <linux/bcma/bcma.h>
 #include <linux/slab.h>
 
@@ -68,6 +69,10 @@
 static void bcma_release_core_dev(struct device *dev)
 {
 	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
+	if (core->io_addr)
+		iounmap(core->io_addr);
+	if (core->io_wrap)
+		iounmap(core->io_wrap);
 	kfree(core);
 }
 
@@ -82,6 +87,7 @@
 		case BCMA_CORE_CHIPCOMMON:
 		case BCMA_CORE_PCI:
 		case BCMA_CORE_PCIE:
+		case BCMA_CORE_MIPS_74K:
 			continue;
 		}
 
@@ -95,7 +101,10 @@
 			core->dma_dev = &bus->host_pci->dev;
 			core->irq = bus->host_pci->irq;
 			break;
-		case BCMA_HOSTTYPE_NONE:
+		case BCMA_HOSTTYPE_SOC:
+			core->dev.dma_mask = &core->dev.coherent_dma_mask;
+			core->dma_dev = &core->dev;
+			break;
 		case BCMA_HOSTTYPE_SDIO:
 			break;
 		}
@@ -142,6 +151,13 @@
 		bcma_core_chipcommon_init(&bus->drv_cc);
 	}
 
+	/* Init MIPS core */
+	core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
+	if (core) {
+		bus->drv_mips.core = core;
+		bcma_core_mips_init(&bus->drv_mips);
+	}
+
 	/* Init PCIE core */
 	core = bcma_find_core(bus, BCMA_CORE_PCIE);
 	if (core) {
@@ -171,6 +187,59 @@
 	bcma_unregister_cores(bus);
 }
 
+int __init bcma_bus_early_register(struct bcma_bus *bus,
+				   struct bcma_device *core_cc,
+				   struct bcma_device *core_mips)
+{
+	int err;
+	struct bcma_device *core;
+	struct bcma_device_id match;
+
+	bcma_init_bus(bus);
+
+	match.manuf = BCMA_MANUF_BCM;
+	match.id = BCMA_CORE_CHIPCOMMON;
+	match.class = BCMA_CL_SIM;
+	match.rev = BCMA_ANY_REV;
+
+	/* Scan for chip common core */
+	err = bcma_bus_scan_early(bus, &match, core_cc);
+	if (err) {
+		pr_err("Failed to scan for common core: %d\n", err);
+		return -1;
+	}
+
+	match.manuf = BCMA_MANUF_MIPS;
+	match.id = BCMA_CORE_MIPS_74K;
+	match.class = BCMA_CL_SIM;
+	match.rev = BCMA_ANY_REV;
+
+	/* Scan for mips core */
+	err = bcma_bus_scan_early(bus, &match, core_mips);
+	if (err) {
+		pr_err("Failed to scan for mips core: %d\n", err);
+		return -1;
+	}
+
+	/* Init CC core */
+	core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
+	if (core) {
+		bus->drv_cc.core = core;
+		bcma_core_chipcommon_init(&bus->drv_cc);
+	}
+
+	/* Init MIPS core */
+	core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
+	if (core) {
+		bus->drv_mips.core = core;
+		bcma_core_mips_init(&bus->drv_mips);
+	}
+
+	pr_info("Early bus registered\n");
+
+	return 0;
+}
+
 int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
 {
 	drv->drv.name = drv->name;
diff -druN linux-libre-3.1-gnu/drivers/bcma/Makefile linux-libre-3.2-gnu/drivers/bcma/Makefile
--- linux-libre-3.1-gnu/drivers/bcma/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bcma/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,9 @@
 bcma-y					+= driver_chipcommon.o driver_chipcommon_pmu.o
 bcma-y					+= driver_pci.o
 bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE)	+= driver_pci_host.o
+bcma-$(CONFIG_BCMA_DRIVER_MIPS)		+= driver_mips.o
 bcma-$(CONFIG_BCMA_HOST_PCI)		+= host_pci.o
+bcma-$(CONFIG_BCMA_HOST_SOC)		+= host_soc.o
 obj-$(CONFIG_BCMA)			+= bcma.o
 
 ccflags-$(CONFIG_BCMA_DEBUG)		:= -DDEBUG
diff -druN linux-libre-3.1-gnu/drivers/bcma/scan.c linux-libre-3.2-gnu/drivers/bcma/scan.c
--- linux-libre-3.1-gnu/drivers/bcma/scan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bcma/scan.c	2012-01-04 18:55:44.000000000 -0500
@@ -200,18 +200,162 @@
 	return addrl;
 }
 
-int bcma_bus_scan(struct bcma_bus *bus)
+static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus,
+						   u16 index)
 {
-	u32 erombase;
-	u32 __iomem *eromptr, *eromend;
+	struct bcma_device *core;
+
+	list_for_each_entry(core, &bus->cores, list) {
+		if (core->core_index == index)
+			return core;
+	}
+	return NULL;
+}
 
+static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
+			      struct bcma_device_id *match, int core_num,
+			      struct bcma_device *core)
+{
+	s32 tmp;
+	u8 i, j;
 	s32 cia, cib;
 	u8 ports[2], wrappers[2];
 
+	/* get CIs */
+	cia = bcma_erom_get_ci(bus, eromptr);
+	if (cia < 0) {
+		bcma_erom_push_ent(eromptr);
+		if (bcma_erom_is_end(bus, eromptr))
+			return -ESPIPE;
+		return -EILSEQ;
+	}
+	cib = bcma_erom_get_ci(bus, eromptr);
+	if (cib < 0)
+		return -EILSEQ;
+
+	/* parse CIs */
+	core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
+	core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
+	core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
+	ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
+	ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
+	wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
+	wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
+	core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
+
+	if (((core->id.manuf == BCMA_MANUF_ARM) &&
+	     (core->id.id == 0xFFF)) ||
+	    (ports[1] == 0)) {
+		bcma_erom_skip_component(bus, eromptr);
+		return -ENXIO;
+	}
+
+	/* check if component is a core at all */
+	if (wrappers[0] + wrappers[1] == 0) {
+		/* we could save addrl of the router
+		if (cid == BCMA_CORE_OOB_ROUTER)
+		 */
+		bcma_erom_skip_component(bus, eromptr);
+		return -ENXIO;
+	}
+
+	if (bcma_erom_is_bridge(bus, eromptr)) {
+		bcma_erom_skip_component(bus, eromptr);
+		return -ENXIO;
+	}
+
+	if (bcma_find_core_by_index(bus, core_num)) {
+		bcma_erom_skip_component(bus, eromptr);
+		return -ENODEV;
+	}
+
+	if (match && ((match->manuf != BCMA_ANY_MANUF &&
+	      match->manuf != core->id.manuf) ||
+	     (match->id != BCMA_ANY_ID && match->id != core->id.id) ||
+	     (match->rev != BCMA_ANY_REV && match->rev != core->id.rev) ||
+	     (match->class != BCMA_ANY_CLASS && match->class != core->id.class)
+	    )) {
+		bcma_erom_skip_component(bus, eromptr);
+		return -ENODEV;
+	}
+
+	/* get & parse master ports */
+	for (i = 0; i < ports[0]; i++) {
+		s32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);
+		if (mst_port_d < 0)
+			return -EILSEQ;
+	}
+
+	/* get & parse slave ports */
+	for (i = 0; i < ports[1]; i++) {
+		for (j = 0; ; j++) {
+			tmp = bcma_erom_get_addr_desc(bus, eromptr,
+				SCAN_ADDR_TYPE_SLAVE, i);
+			if (tmp < 0) {
+				/* no more entries for port _i_ */
+				/* pr_debug("erom: slave port %d "
+				 * "has %d descriptors\n", i, j); */
+				break;
+			} else {
+				if (i == 0 && j == 0)
+					core->addr = tmp;
+			}
+		}
+	}
+
+	/* get & parse master wrappers */
+	for (i = 0; i < wrappers[0]; i++) {
+		for (j = 0; ; j++) {
+			tmp = bcma_erom_get_addr_desc(bus, eromptr,
+				SCAN_ADDR_TYPE_MWRAP, i);
+			if (tmp < 0) {
+				/* no more entries for port _i_ */
+				/* pr_debug("erom: master wrapper %d "
+				 * "has %d descriptors\n", i, j); */
+				break;
+			} else {
+				if (i == 0 && j == 0)
+					core->wrap = tmp;
+			}
+		}
+	}
+
+	/* get & parse slave wrappers */
+	for (i = 0; i < wrappers[1]; i++) {
+		u8 hack = (ports[1] == 1) ? 0 : 1;
+		for (j = 0; ; j++) {
+			tmp = bcma_erom_get_addr_desc(bus, eromptr,
+				SCAN_ADDR_TYPE_SWRAP, i + hack);
+			if (tmp < 0) {
+				/* no more entries for port _i_ */
+				/* pr_debug("erom: master wrapper %d "
+				 * has %d descriptors\n", i, j); */
+				break;
+			} else {
+				if (wrappers[0] == 0 && !i && !j)
+					core->wrap = tmp;
+			}
+		}
+	}
+	if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
+		core->io_addr = ioremap_nocache(core->addr, BCMA_CORE_SIZE);
+		if (!core->io_addr)
+			return -ENOMEM;
+		core->io_wrap = ioremap_nocache(core->wrap, BCMA_CORE_SIZE);
+		if (!core->io_wrap) {
+			iounmap(core->io_addr);
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+void bcma_init_bus(struct bcma_bus *bus)
+{
 	s32 tmp;
-	u8 i, j;
 
-	int err;
+	if (bus->init_done)
+		return;
 
 	INIT_LIST_HEAD(&bus->cores);
 	bus->nr_cores = 0;
@@ -222,9 +366,27 @@
 	bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
 	bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
 	bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
+	bus->init_done = true;
+}
+
+int bcma_bus_scan(struct bcma_bus *bus)
+{
+	u32 erombase;
+	u32 __iomem *eromptr, *eromend;
+
+	int err, core_num = 0;
+
+	bcma_init_bus(bus);
 
 	erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
-	eromptr = bus->mmio;
+	if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
+		eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
+		if (!eromptr)
+			return -ENOMEM;
+	} else {
+		eromptr = bus->mmio;
+	}
+
 	eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
 
 	bcma_scan_switch_core(bus, erombase);
@@ -236,125 +398,89 @@
 		INIT_LIST_HEAD(&core->list);
 		core->bus = bus;
 
-		/* get CIs */
-		cia = bcma_erom_get_ci(bus, &eromptr);
-		if (cia < 0) {
-			bcma_erom_push_ent(&eromptr);
-			if (bcma_erom_is_end(bus, &eromptr))
-				break;
-			err= -EILSEQ;
-			goto out;
-		}
-		cib = bcma_erom_get_ci(bus, &eromptr);
-		if (cib < 0) {
-			err= -EILSEQ;
-			goto out;
-		}
+		err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core);
+		if (err == -ENODEV) {
+			core_num++;
+			continue;
+		} else if (err == -ENXIO)
+			continue;
+		else if (err == -ESPIPE)
+			break;
+		else if (err < 0)
+			return err;
 
-		/* parse CIs */
-		core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
-		core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
-		core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
-		ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
-		ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
-		wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
-		wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
-		core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
+		core->core_index = core_num++;
+		bus->nr_cores++;
 
-		if (((core->id.manuf == BCMA_MANUF_ARM) &&
-		     (core->id.id == 0xFFF)) ||
-		    (ports[1] == 0)) {
-			bcma_erom_skip_component(bus, &eromptr);
-			continue;
-		}
+		pr_info("Core %d found: %s "
+			"(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
+			core->core_index, bcma_device_name(&core->id),
+			core->id.manuf, core->id.id, core->id.rev,
+			core->id.class);
 
-		/* check if component is a core at all */
-		if (wrappers[0] + wrappers[1] == 0) {
-			/* we could save addrl of the router
-			if (cid == BCMA_CORE_OOB_ROUTER)
-			 */
-			bcma_erom_skip_component(bus, &eromptr);
-			continue;
-		}
+		list_add(&core->list, &bus->cores);
+	}
 
-		if (bcma_erom_is_bridge(bus, &eromptr)) {
-			bcma_erom_skip_component(bus, &eromptr);
-			continue;
-		}
+	if (bus->hosttype == BCMA_HOSTTYPE_SOC)
+		iounmap(eromptr);
 
-		/* get & parse master ports */
-		for (i = 0; i < ports[0]; i++) {
-			u32 mst_port_d = bcma_erom_get_mst_port(bus, &eromptr);
-			if (mst_port_d < 0) {
-				err= -EILSEQ;
-				goto out;
-			}
-		}
+	return 0;
+}
 
-		/* get & parse slave ports */
-		for (i = 0; i < ports[1]; i++) {
-			for (j = 0; ; j++) {
-				tmp = bcma_erom_get_addr_desc(bus, &eromptr,
-					SCAN_ADDR_TYPE_SLAVE, i);
-				if (tmp < 0) {
-					/* no more entries for port _i_ */
-					/* pr_debug("erom: slave port %d "
-					 * "has %d descriptors\n", i, j); */
-					break;
-				} else {
-					if (i == 0 && j == 0)
-						core->addr = tmp;
-				}
-			}
-		}
+int __init bcma_bus_scan_early(struct bcma_bus *bus,
+			       struct bcma_device_id *match,
+			       struct bcma_device *core)
+{
+	u32 erombase;
+	u32 __iomem *eromptr, *eromend;
 
-		/* get & parse master wrappers */
-		for (i = 0; i < wrappers[0]; i++) {
-			for (j = 0; ; j++) {
-				tmp = bcma_erom_get_addr_desc(bus, &eromptr,
-					SCAN_ADDR_TYPE_MWRAP, i);
-				if (tmp < 0) {
-					/* no more entries for port _i_ */
-					/* pr_debug("erom: master wrapper %d "
-					 * "has %d descriptors\n", i, j); */
-					break;
-				} else {
-					if (i == 0 && j == 0)
-						core->wrap = tmp;
-				}
-			}
-		}
+	int err = -ENODEV;
+	int core_num = 0;
 
-		/* get & parse slave wrappers */
-		for (i = 0; i < wrappers[1]; i++) {
-			u8 hack = (ports[1] == 1) ? 0 : 1;
-			for (j = 0; ; j++) {
-				tmp = bcma_erom_get_addr_desc(bus, &eromptr,
-					SCAN_ADDR_TYPE_SWRAP, i + hack);
-				if (tmp < 0) {
-					/* no more entries for port _i_ */
-					/* pr_debug("erom: master wrapper %d "
-					 * has %d descriptors\n", i, j); */
-					break;
-				} else {
-					if (wrappers[0] == 0 && !i && !j)
-						core->wrap = tmp;
-				}
-			}
-		}
+	erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
+	if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
+		eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
+		if (!eromptr)
+			return -ENOMEM;
+	} else {
+		eromptr = bus->mmio;
+	}
+
+	eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
+
+	bcma_scan_switch_core(bus, erombase);
+
+	while (eromptr < eromend) {
+		memset(core, 0, sizeof(*core));
+		INIT_LIST_HEAD(&core->list);
+		core->bus = bus;
 
+		err = bcma_get_next_core(bus, &eromptr, match, core_num, core);
+		if (err == -ENODEV) {
+			core_num++;
+			continue;
+		} else if (err == -ENXIO)
+			continue;
+		else if (err == -ESPIPE)
+			break;
+		else if (err < 0)
+			return err;
+
+		core->core_index = core_num++;
+		bus->nr_cores++;
 		pr_info("Core %d found: %s "
 			"(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
-			bus->nr_cores, bcma_device_name(&core->id),
+			core->core_index, bcma_device_name(&core->id),
 			core->id.manuf, core->id.id, core->id.rev,
 			core->id.class);
 
-		core->core_index = bus->nr_cores++;
 		list_add(&core->list, &bus->cores);
-		continue;
-out:
-		return err;
+		err = 0;
+		break;
 	}
 
-	return 0;
+	if (bus->hosttype == BCMA_HOSTTYPE_SOC)
+		iounmap(eromptr);
+
+	return err;
 }
diff -druN linux-libre-3.1-gnu/drivers/bcma/sprom.c linux-libre-3.2-gnu/drivers/bcma/sprom.c
--- linux-libre-3.1-gnu/drivers/bcma/sprom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bcma/sprom.c	2012-01-04 18:55:44.000000000 -0500
@@ -133,6 +133,15 @@
 		v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
 		*(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
 	}
+
+	bus->sprom.board_rev = sprom[SPOFF(SSB_SPROM8_BOARDREV)];
+
+	bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)];
+	bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)];
+	bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)];
+	bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)];
+
+	bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)];
 }
 
 int bcma_sprom_get(struct bcma_bus *bus)
@@ -152,6 +161,9 @@
 	if (!sprom)
 		return -ENOMEM;
 
+	if (bus->chipinfo.id == 0x4331)
+		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
+
 	/* Most cards have SPROM moved by additional offset 0x30 (48 dwords).
 	 * According to brcm80211 this applies to cards with PCIe rev >= 6
 	 * TODO: understand this condition and use it */
@@ -159,6 +171,9 @@
 		BCMA_CC_SPROM_PCIE6;
 	bcma_sprom_read(bus, offset, sprom);
 
+	if (bus->chipinfo.id == 0x4331)
+		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
+
 	err = bcma_sprom_valid(sprom);
 	if (err)
 		goto out;
diff -druN linux-libre-3.1-gnu/drivers/block/aoe/aoeblk.c linux-libre-3.2-gnu/drivers/block/aoe/aoeblk.c
--- linux-libre-3.1-gnu/drivers/block/aoe/aoeblk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/aoe/aoeblk.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/genhd.h>
 #include <linux/netdevice.h>
 #include <linux/mutex.h>
+#include <linux/export.h>
 #include "aoe.h"
 
 static DEFINE_MUTEX(aoeblk_mutex);
@@ -159,7 +160,7 @@
 	return 0;
 }
 
-static int
+static void
 aoeblk_make_request(struct request_queue *q, struct bio *bio)
 {
 	struct sk_buff_head queue;
@@ -172,25 +173,25 @@
 	if (bio == NULL) {
 		printk(KERN_ERR "aoe: bio is NULL\n");
 		BUG();
-		return 0;
+		return;
 	}
 	d = bio->bi_bdev->bd_disk->private_data;
 	if (d == NULL) {
 		printk(KERN_ERR "aoe: bd_disk->private_data is NULL\n");
 		BUG();
 		bio_endio(bio, -ENXIO);
-		return 0;
+		return;
 	} else if (bio->bi_io_vec == NULL) {
 		printk(KERN_ERR "aoe: bi_io_vec is NULL\n");
 		BUG();
 		bio_endio(bio, -ENXIO);
-		return 0;
+		return;
 	}
 	buf = mempool_alloc(d->bufpool, GFP_NOIO);
 	if (buf == NULL) {
 		printk(KERN_INFO "aoe: buf allocation failure\n");
 		bio_endio(bio, -ENOMEM);
-		return 0;
+		return;
 	}
 	memset(buf, 0, sizeof(*buf));
 	INIT_LIST_HEAD(&buf->bufs);
@@ -211,7 +212,7 @@
 		spin_unlock_irqrestore(&d->lock, flags);
 		mempool_free(buf, d->bufpool);
 		bio_endio(bio, -ENXIO);
-		return 0;
+		return;
 	}
 
 	list_add_tail(&buf->bufs, &d->bufq);
@@ -222,8 +223,6 @@
 
 	spin_unlock_irqrestore(&d->lock, flags);
 	aoenet_xmit(&queue);
-
-	return 0;
 }
 
 static int
diff -druN linux-libre-3.1-gnu/drivers/block/aoe/aoechr.c linux-libre-3.2-gnu/drivers/block/aoe/aoechr.c
--- linux-libre-3.1-gnu/drivers/block/aoe/aoechr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/aoe/aoechr.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/skbuff.h>
+#include <linux/export.h>
 #include "aoe.h"
 
 enum {
diff -druN linux-libre-3.1-gnu/drivers/block/brd.c linux-libre-3.2-gnu/drivers/block/brd.c
--- linux-libre-3.1-gnu/drivers/block/brd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/brd.c	2012-01-04 18:55:44.000000000 -0500
@@ -323,7 +323,7 @@
 	return err;
 }
 
-static int brd_make_request(struct request_queue *q, struct bio *bio)
+static void brd_make_request(struct request_queue *q, struct bio *bio)
 {
 	struct block_device *bdev = bio->bi_bdev;
 	struct brd_device *brd = bdev->bd_disk->private_data;
@@ -359,8 +359,6 @@
 
 out:
 	bio_endio(bio, err);
-
-	return 0;
 }
 
 #ifdef CONFIG_BLK_DEV_XIP
diff -druN linux-libre-3.1-gnu/drivers/block/cciss.c linux-libre-3.2-gnu/drivers/block/cciss.c
--- linux-libre-3.1-gnu/drivers/block/cciss.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/cciss.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/pci-aspm.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -68,6 +69,10 @@
 module_param(cciss_tape_cmds, int, 0644);
 MODULE_PARM_DESC(cciss_tape_cmds,
 	"number of commands to allocate for tape devices (default: 6)");
+static int cciss_simple_mode;
+module_param(cciss_simple_mode, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(cciss_simple_mode,
+	"Use 'simple mode' rather than 'performant mode'");
 
 static DEFINE_MUTEX(cciss_mutex);
 static struct proc_dir_entry *proc_cciss;
@@ -176,6 +181,7 @@
 			unsigned int block_size, InquiryData_struct *inq_buff,
 				   drive_info_struct *drv);
 static void __devinit cciss_interrupt_mode(ctlr_info_t *);
+static int __devinit cciss_enter_simple_mode(struct ctlr_info *h);
 static void start_io(ctlr_info_t *h);
 static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size,
 			__u8 page_code, unsigned char scsi3addr[],
@@ -388,7 +394,7 @@
 		h->product_name,
 		(unsigned long)h->board_id,
 		h->firm_ver[0], h->firm_ver[1], h->firm_ver[2],
-		h->firm_ver[3], (unsigned int)h->intr[PERF_MODE_INT],
+		h->firm_ver[3], (unsigned int)h->intr[h->intr_mode],
 		h->num_luns,
 		h->Qdepth, h->commands_outstanding,
 		h->maxQsinceinit, h->max_outstanding, h->maxSG);
@@ -636,6 +642,18 @@
 }
 static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan);
 
+static ssize_t host_show_transport_mode(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct ctlr_info *h = to_hba(dev);
+
+	return snprintf(buf, 20, "%s\n",
+		h->transMethod & CFGTBL_Trans_Performant ?
+			"performant" : "simple");
+}
+static DEVICE_ATTR(transport_mode, S_IRUGO, host_show_transport_mode, NULL);
+
 static ssize_t dev_show_unique_id(struct device *dev,
 				 struct device_attribute *attr,
 				 char *buf)
@@ -808,6 +826,7 @@
 static struct attribute *cciss_host_attrs[] = {
 	&dev_attr_rescan.attr,
 	&dev_attr_resettable.attr,
+	&dev_attr_transport_mode.attr,
 	NULL
 };
 
@@ -2582,6 +2601,8 @@
 			c->Request.Timeout = 0;
 			c->Request.CDB[0] = BMIC_WRITE;
 			c->Request.CDB[6] = BMIC_CACHE_FLUSH;
+			c->Request.CDB[7] = (size >> 8) & 0xFF;
+			c->Request.CDB[8] = size & 0xFF;
 			break;
 		case TEST_UNIT_READY:
 			c->Request.CDBLen = 6;
@@ -3984,6 +4005,9 @@
 {
 	__u32 trans_support;
 
+	if (cciss_simple_mode)
+		return;
+
 	dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n");
 	/* Attempt to put controller into performant mode if supported */
 	/* Does board support performant mode? */
@@ -4081,7 +4105,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;
 	return;
 }
 
@@ -4298,6 +4322,10 @@
 		dev_warn(&h->pdev->dev, "controller appears to be disabled\n");
 		return -ENODEV;
 	}
+
+	pci_disable_link_state(h->pdev, PCIE_LINK_STATE_L0S |
+				PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
+
 	err = pci_enable_device(h->pdev);
 	if (err) {
 		dev_warn(&h->pdev->dev, "Unable to Enable PCI device\n");
@@ -4341,6 +4369,9 @@
 	}
 	cciss_enable_scsi_prefetch(h);
 	cciss_p600_dma_prefetch_quirk(h);
+	err = cciss_enter_simple_mode(h);
+	if (err)
+		goto err_out_free_res;
 	cciss_put_controller_into_performant_mode(h);
 	return 0;
 
@@ -4533,6 +4564,13 @@
 		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
 		pmcsr |= PCI_D0;
 		pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
+
+		/*
+		 * The P600 requires a small delay when changing states.
+		 * Otherwise we may think the board did not reset and we bail.
+		 * This for kdump only and is particular to the P600.
+		 */
+		msleep(500);
 	}
 	return 0;
 }
@@ -4843,20 +4881,20 @@
 	irqreturn_t (*intxhandler)(int, void *))
 {
 	if (h->msix_vector || h->msi_vector) {
-		if (!request_irq(h->intr[PERF_MODE_INT], msixhandler,
-				IRQF_DISABLED, h->devname, h))
+		if (!request_irq(h->intr[h->intr_mode], msixhandler,
+				0, h->devname, h))
 			return 0;
 		dev_err(&h->pdev->dev, "Unable to get msi irq %d"
-			" for %s\n", h->intr[PERF_MODE_INT],
+			" for %s\n", h->intr[h->intr_mode],
 			h->devname);
 		return -1;
 	}
 
-	if (!request_irq(h->intr[PERF_MODE_INT], intxhandler,
-			IRQF_DISABLED, h->devname, h))
+	if (!request_irq(h->intr[h->intr_mode], intxhandler,
+			IRQF_SHARED, h->devname, h))
 		return 0;
 	dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n",
-		h->intr[PERF_MODE_INT], h->devname);
+		h->intr[h->intr_mode], h->devname);
 	return -1;
 }
 
@@ -4887,7 +4925,7 @@
 {
 	int ctlr = h->ctlr;
 
-	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);
@@ -4953,6 +4991,7 @@
 	h = hba[i];
 	h->pdev = pdev;
 	h->busy_initializing = 1;
+	h->intr_mode = cciss_simple_mode ? SIMPLE_MODE_INT : PERF_MODE_INT;
 	INIT_LIST_HEAD(&h->cmpQ);
 	INIT_LIST_HEAD(&h->reqQ);
 	mutex_init(&h->busy_shutting_down);
@@ -5009,7 +5048,7 @@
 
 	dev_info(&h->pdev->dev, "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n",
 	       h->devname, pdev->device, pci_name(pdev),
-	       h->intr[PERF_MODE_INT], dac ? "" : " not");
+	       h->intr[h->intr_mode], dac ? "" : " not");
 
 	if (cciss_allocate_cmd_pool(h))
 		goto clean4;
@@ -5056,7 +5095,7 @@
 		spin_lock_irqsave(&h->lock, flags);
 		h->access.set_intr_mask(h, CCISS_INTR_OFF);
 		spin_unlock_irqrestore(&h->lock, flags);
-		free_irq(h->intr[PERF_MODE_INT], h);
+		free_irq(h->intr[h->intr_mode], h);
 		rc = cciss_request_irq(h, cciss_msix_discard_completions,
 					cciss_intx_discard_completions);
 		if (rc) {
@@ -5126,6 +5165,7 @@
 	h->cciss_max_sectors = 8192;
 
 	rebuild_lun_table(h, 1, 0);
+	cciss_engage_scsi(h);
 	h->busy_initializing = 0;
 	return 1;
 
@@ -5133,7 +5173,7 @@
 	cciss_free_cmd_pool(h);
 	cciss_free_scatterlists(h);
 	cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds);
-	free_irq(h->intr[PERF_MODE_INT], h);
+	free_irq(h->intr[h->intr_mode], h);
 clean2:
 	unregister_blkdev(h->major, h->devname);
 clean1:
@@ -5172,9 +5212,31 @@
 	if (return_code != IO_OK)
 		dev_warn(&h->pdev->dev, "Error flushing cache\n");
 	h->access.set_intr_mask(h, CCISS_INTR_OFF);
-	free_irq(h->intr[PERF_MODE_INT], h);
+	free_irq(h->intr[h->intr_mode], h);
 }
 
+static int __devinit cciss_enter_simple_mode(struct ctlr_info *h)
+{
+	u32 trans_support;
+
+	trans_support = readl(&(h->cfgtable->TransportSupport));
+	if (!(trans_support & SIMPLE_MODE))
+		return -ENOTSUPP;
+
+	h->max_commands = readl(&(h->cfgtable->CmdsOutMax));
+	writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest));
+	writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
+	cciss_wait_for_mode_change_ack(h);
+	print_cfg_table(h);
+	if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) {
+		dev_warn(&h->pdev->dev, "unable to get board into simple mode\n");
+		return -ENODEV;
+	}
+	h->transMethod = CFGTBL_Trans_Simple;
+	return 0;
+}
+
+
 static void __devexit cciss_remove_one(struct pci_dev *pdev)
 {
 	ctlr_info_t *h;
diff -druN linux-libre-3.1-gnu/drivers/block/cciss.h linux-libre-3.2-gnu/drivers/block/cciss.h
--- linux-libre-3.1-gnu/drivers/block/cciss.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/cciss.h	2012-01-04 18:55:44.000000000 -0500
@@ -92,6 +92,7 @@
 	unsigned int intr[4];
 	unsigned int msix_vector;
 	unsigned int msi_vector;
+	int	intr_mode;
 	int 	cciss_max_sectors;
 	BYTE	cciss_read;
 	BYTE	cciss_write;
diff -druN linux-libre-3.1-gnu/drivers/block/cciss_scsi.c linux-libre-3.2-gnu/drivers/block/cciss_scsi.c
--- linux-libre-3.1-gnu/drivers/block/cciss_scsi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/cciss_scsi.c	2012-01-04 18:55:44.000000000 -0500
@@ -1720,5 +1720,6 @@
 /* If no tape support, then these become defined out of existence */
 
 #define cciss_scsi_setup(cntl_num)
+#define cciss_engage_scsi(h)
 
 #endif /* CONFIG_CISS_SCSI_TAPE */
diff -druN linux-libre-3.1-gnu/drivers/block/cpqarray.c linux-libre-3.2-gnu/drivers/block/cpqarray.c
--- linux-libre-3.1-gnu/drivers/block/cpqarray.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/cpqarray.c	2012-01-04 18:55:44.000000000 -0500
@@ -620,6 +620,7 @@
 	}
 	vendor_id = pdev->vendor;
 	device_id = pdev->device;
+	revision  = pdev->revision;
 	irq = pdev->irq;
 
 	for(i=0; i<6; i++)
@@ -632,7 +633,6 @@
 	}
 
 	pci_read_config_word(pdev, PCI_COMMAND, &command);
-	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
 	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size);
 	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_timer);
 
diff -druN linux-libre-3.1-gnu/drivers/block/drbd/drbd_bitmap.c linux-libre-3.2-gnu/drivers/block/drbd/drbd_bitmap.c
--- linux-libre-3.1-gnu/drivers/block/drbd/drbd_bitmap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/drbd/drbd_bitmap.c	2012-01-04 18:55:44.000000000 -0500
@@ -378,15 +378,14 @@
 	 * thread.  As we have no disk yet, we are not in the IO path,
 	 * not even the IO path of the peer. */
 	bytes = sizeof(struct page *)*want;
-	new_pages = kmalloc(bytes, GFP_KERNEL);
+	new_pages = kzalloc(bytes, GFP_KERNEL);
 	if (!new_pages) {
-		new_pages = vmalloc(bytes);
+		new_pages = vzalloc(bytes);
 		if (!new_pages)
 			return NULL;
 		vmalloced = 1;
 	}
 
-	memset(new_pages, 0, bytes);
 	if (want >= have) {
 		for (i = 0; i < have; i++)
 			new_pages[i] = old_pages[i];
diff -druN linux-libre-3.1-gnu/drivers/block/drbd/drbd_int.h linux-libre-3.2-gnu/drivers/block/drbd/drbd_int.h
--- linux-libre-3.1-gnu/drivers/block/drbd/drbd_int.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/drbd/drbd_int.h	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,6 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
-#include <linux/version.h>
 #include <linux/list.h>
 #include <linux/sched.h>
 #include <linux/bitops.h>
@@ -928,7 +927,7 @@
 #define NL_INT64(pn,pr,member) __u64 member;
 #define NL_BIT(pn,pr,member)   unsigned member:1;
 #define NL_STRING(pn,pr,member,len) unsigned char member[len]; int member ## _len;
-#include "linux/drbd_nl.h"
+#include <linux/drbd_nl.h>
 
 struct drbd_backing_dev {
 	struct block_device *backing_bdev;
@@ -1507,7 +1506,7 @@
 extern int proc_details;
 
 /* drbd_req */
-extern int drbd_make_request(struct request_queue *q, struct bio *bio);
+extern void 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);
diff -druN linux-libre-3.1-gnu/drivers/block/drbd/drbd_nl.c linux-libre-3.2-gnu/drivers/block/drbd/drbd_nl.c
--- linux-libre-3.1-gnu/drivers/block/drbd/drbd_nl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/drbd/drbd_nl.c	2012-01-04 18:55:44.000000000 -0500
@@ -94,7 +94,7 @@
 		 arg->member ## _len = dlen; \
 		 memcpy(arg->member, tags, min_t(size_t, dlen, len)); \
 		 break;
-#include "linux/drbd_nl.h"
+#include <linux/drbd_nl.h>
 
 /* Generate the struct to tag_list functions */
 #define NL_PACKET(name, number, fields) \
@@ -129,7 +129,7 @@
 	put_unaligned(arg->member ## _len, tags++);	\
 	memcpy(tags, arg->member, arg->member ## _len); \
 	tags = (unsigned short *)((char *)tags + arg->member ## _len);
-#include "linux/drbd_nl.h"
+#include <linux/drbd_nl.h>
 
 void drbd_bcast_ev_helper(struct drbd_conf *mdev, char *helper_name);
 void drbd_nl_send_reply(struct cn_msg *, int);
diff -druN linux-libre-3.1-gnu/drivers/block/drbd/drbd_req.c linux-libre-3.2-gnu/drivers/block/drbd/drbd_req.c
--- linux-libre-3.1-gnu/drivers/block/drbd/drbd_req.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/drbd/drbd_req.c	2012-01-04 18:55:44.000000000 -0500
@@ -1073,7 +1073,7 @@
 	return 0;
 }
 
-int drbd_make_request(struct request_queue *q, struct bio *bio)
+void 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;
@@ -1081,7 +1081,7 @@
 
 	if (drbd_fail_request_early(mdev, bio_data_dir(bio) & WRITE)) {
 		bio_endio(bio, -EPERM);
-		return 0;
+		return;
 	}
 
 	start_time = jiffies;
@@ -1100,7 +1100,8 @@
 
 	if (likely(s_enr == e_enr)) {
 		inc_ap_bio(mdev, 1);
-		return drbd_make_request_common(mdev, bio, start_time);
+		drbd_make_request_common(mdev, bio, start_time);
+		return;
 	}
 
 	/* can this bio be split generically?
@@ -1148,7 +1149,6 @@
 
 		bio_pair_release(bp);
 	}
-	return 0;
 }
 
 /* This is called by bio_add_page().  With this function we reduce
diff -druN linux-libre-3.1-gnu/drivers/block/loop.c linux-libre-3.2-gnu/drivers/block/loop.c
--- linux-libre-3.1-gnu/drivers/block/loop.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/loop.c	2012-01-04 18:55:44.000000000 -0500
@@ -76,6 +76,8 @@
 #include <linux/splice.h>
 #include <linux/sysfs.h>
 #include <linux/miscdevice.h>
+#include <linux/falloc.h>
+
 #include <asm/uaccess.h>
 
 static DEFINE_IDR(loop_index_idr);
@@ -159,17 +161,19 @@
 	&xor_funcs
 };
 
-static loff_t get_loop_size(struct loop_device *lo, struct file *file)
+static loff_t get_size(loff_t offset, loff_t sizelimit, struct file *file)
 {
-	loff_t size, offset, loopsize;
+	loff_t size, loopsize;
 
 	/* Compute loopsize in bytes */
 	size = i_size_read(file->f_mapping->host);
-	offset = lo->lo_offset;
 	loopsize = size - offset;
-	if (lo->lo_sizelimit > 0 && lo->lo_sizelimit < loopsize)
-		loopsize = lo->lo_sizelimit;
+	/* offset is beyond i_size, wierd but possible */
+	if (loopsize < 0)
+		return 0;
 
+	if (sizelimit > 0 && sizelimit < loopsize)
+		loopsize = sizelimit;
 	/*
 	 * Unfortunately, if we want to do I/O on the device,
 	 * the number of 512-byte sectors has to fit into a sector_t.
@@ -177,17 +181,25 @@
 	return loopsize >> 9;
 }
 
+static loff_t get_loop_size(struct loop_device *lo, struct file *file)
+{
+	return get_size(lo->lo_offset, lo->lo_sizelimit, file);
+}
+
 static int
-figure_loop_size(struct loop_device *lo)
+figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit)
 {
-	loff_t size = get_loop_size(lo, lo->lo_backing_file);
+	loff_t size = get_size(offset, sizelimit, lo->lo_backing_file);
 	sector_t x = (sector_t)size;
 
 	if (unlikely((loff_t)x != size))
 		return -EFBIG;
-
+	if (lo->lo_offset != offset)
+		lo->lo_offset = offset;
+	if (lo->lo_sizelimit != sizelimit)
+		lo->lo_sizelimit = sizelimit;
 	set_capacity(lo->lo_disk, x);
-	return 0;					
+	return 0;
 }
 
 static inline int
@@ -203,74 +215,6 @@
 }
 
 /**
- * do_lo_send_aops - helper for writing data to a loop device
- *
- * This is the fast version for backing filesystems which implement the address
- * space operations write_begin and write_end.
- */
-static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
-		loff_t pos, struct page *unused)
-{
-	struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */
-	struct address_space *mapping = file->f_mapping;
-	pgoff_t index;
-	unsigned offset, bv_offs;
-	int len, ret;
-
-	mutex_lock(&mapping->host->i_mutex);
-	index = pos >> PAGE_CACHE_SHIFT;
-	offset = pos & ((pgoff_t)PAGE_CACHE_SIZE - 1);
-	bv_offs = bvec->bv_offset;
-	len = bvec->bv_len;
-	while (len > 0) {
-		sector_t IV;
-		unsigned size, copied;
-		int transfer_result;
-		struct page *page;
-		void *fsdata;
-
-		IV = ((sector_t)index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9);
-		size = PAGE_CACHE_SIZE - offset;
-		if (size > len)
-			size = len;
-
-		ret = pagecache_write_begin(file, mapping, pos, size, 0,
-							&page, &fsdata);
-		if (ret)
-			goto fail;
-
-		file_update_time(file);
-
-		transfer_result = lo_do_transfer(lo, WRITE, page, offset,
-				bvec->bv_page, bv_offs, size, IV);
-		copied = size;
-		if (unlikely(transfer_result))
-			copied = 0;
-
-		ret = pagecache_write_end(file, mapping, pos, size, copied,
-							page, fsdata);
-		if (ret < 0 || ret != copied)
-			goto fail;
-
-		if (unlikely(transfer_result))
-			goto fail;
-
-		bv_offs += copied;
-		len -= copied;
-		offset = 0;
-		index++;
-		pos += copied;
-	}
-	ret = 0;
-out:
-	mutex_unlock(&mapping->host->i_mutex);
-	return ret;
-fail:
-	ret = -1;
-	goto out;
-}
-
-/**
  * __do_lo_send_write - helper for writing data to a loop device
  *
  * This helper just factors out common code between do_lo_send_direct_write()
@@ -297,10 +241,8 @@
 /**
  * do_lo_send_direct_write - helper for writing data to a loop device
  *
- * This is the fast, non-transforming version for backing filesystems which do
- * not implement the address space operations write_begin and write_end.
- * It uses the write file operation which should be present on all writeable
- * filesystems.
+ * This is the fast, non-transforming version that does not need double
+ * buffering.
  */
 static int do_lo_send_direct_write(struct loop_device *lo,
 		struct bio_vec *bvec, loff_t pos, struct page *page)
@@ -316,15 +258,9 @@
 /**
  * do_lo_send_write - helper for writing data to a loop device
  *
- * This is the slow, transforming version for filesystems which do not
- * implement the address space operations write_begin and write_end.  It
- * uses the write file operation which should be present on all writeable
- * filesystems.
- *
- * Using fops->write is slower than using aops->{prepare,commit}_write in the
- * transforming case because we need to double buffer the data as we cannot do
- * the transformations in place as we do not have direct access to the
- * destination pages of the backing file.
+ * This is the slow, transforming version that needs to double buffer the
+ * data as it cannot do the transformations in place without having direct
+ * access to the destination pages of the backing file.
  */
 static int do_lo_send_write(struct loop_device *lo, struct bio_vec *bvec,
 		loff_t pos, struct page *page)
@@ -350,17 +286,16 @@
 	struct page *page = NULL;
 	int i, ret = 0;
 
-	do_lo_send = do_lo_send_aops;
-	if (!(lo->lo_flags & LO_FLAGS_USE_AOPS)) {
+	if (lo->transfer != transfer_none) {
+		page = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
+		if (unlikely(!page))
+			goto fail;
+		kmap(page);
+		do_lo_send = do_lo_send_write;
+	} else {
 		do_lo_send = do_lo_send_direct_write;
-		if (lo->transfer != transfer_none) {
-			page = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
-			if (unlikely(!page))
-				goto fail;
-			kmap(page);
-			do_lo_send = do_lo_send_write;
-		}
 	}
+
 	bio_for_each_segment(bvec, bio, i) {
 		ret = do_lo_send(lo, bvec, pos, page);
 		if (ret < 0)
@@ -447,7 +382,8 @@
 
 	if (retval < 0)
 		return retval;
-
+	if (retval != bvec->bv_len)
+		return -EIO;
 	return 0;
 }
 
@@ -484,6 +420,29 @@
 			}
 		}
 
+		/*
+		 * We use punch hole to reclaim the free space used by the
+		 * image a.k.a. discard. However we do not support discard if
+		 * encryption is enabled, because it may give an attacker
+		 * useful information.
+		 */
+		if (bio->bi_rw & REQ_DISCARD) {
+			struct file *file = lo->lo_backing_file;
+			int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
+
+			if ((!file->f_op->fallocate) ||
+			    lo->lo_encrypt_key_size) {
+				ret = -EOPNOTSUPP;
+				goto out;
+			}
+			ret = file->f_op->fallocate(file, mode, pos,
+						    bio->bi_size);
+			if (unlikely(ret && ret != -EINVAL &&
+				     ret != -EOPNOTSUPP))
+				ret = -EIO;
+			goto out;
+		}
+
 		ret = lo_send(lo, bio, pos);
 
 		if ((bio->bi_rw & REQ_FUA) && !ret) {
@@ -514,7 +473,7 @@
 	return bio_list_pop(&lo->lo_bio_list);
 }
 
-static int loop_make_request(struct request_queue *q, struct bio *old_bio)
+static void loop_make_request(struct request_queue *q, struct bio *old_bio)
 {
 	struct loop_device *lo = q->queuedata;
 	int rw = bio_rw(old_bio);
@@ -532,12 +491,11 @@
 	loop_add_bio(lo, old_bio);
 	wake_up(&lo->lo_event);
 	spin_unlock_irq(&lo->lo_lock);
-	return 0;
+	return;
 
 out:
 	spin_unlock_irq(&lo->lo_lock);
 	bio_io_error(old_bio);
-	return 0;
 }
 
 struct switch_request {
@@ -700,7 +658,7 @@
 		goto out_putf;
 
 	fput(old_file);
-	if (max_part > 0)
+	if (lo->lo_flags & LO_FLAGS_PARTSCAN)
 		ioctl_by_bdev(bdev, BLKRRPART, 0);
 	return 0;
 
@@ -777,16 +735,25 @@
 	return sprintf(buf, "%s\n", autoclear ? "1" : "0");
 }
 
+static ssize_t loop_attr_partscan_show(struct loop_device *lo, char *buf)
+{
+	int partscan = (lo->lo_flags & LO_FLAGS_PARTSCAN);
+
+	return sprintf(buf, "%s\n", partscan ? "1" : "0");
+}
+
 LOOP_ATTR_RO(backing_file);
 LOOP_ATTR_RO(offset);
 LOOP_ATTR_RO(sizelimit);
 LOOP_ATTR_RO(autoclear);
+LOOP_ATTR_RO(partscan);
 
 static struct attribute *loop_attrs[] = {
 	&loop_attr_backing_file.attr,
 	&loop_attr_offset.attr,
 	&loop_attr_sizelimit.attr,
 	&loop_attr_autoclear.attr,
+	&loop_attr_partscan.attr,
 	NULL,
 };
 
@@ -807,6 +774,35 @@
 			   &loop_attribute_group);
 }
 
+static void loop_config_discard(struct loop_device *lo)
+{
+	struct file *file = lo->lo_backing_file;
+	struct inode *inode = file->f_mapping->host;
+	struct request_queue *q = lo->lo_queue;
+
+	/*
+	 * We use punch hole to reclaim the free space used by the
+	 * image a.k.a. discard. However we do support discard if
+	 * encryption is enabled, because it may give an attacker
+	 * useful information.
+	 */
+	if ((!file->f_op->fallocate) ||
+	    lo->lo_encrypt_key_size) {
+		q->limits.discard_granularity = 0;
+		q->limits.discard_alignment = 0;
+		q->limits.max_discard_sectors = 0;
+		q->limits.discard_zeroes_data = 0;
+		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
+		return;
+	}
+
+	q->limits.discard_granularity = inode->i_sb->s_blocksize;
+	q->limits.discard_alignment = 0;
+	q->limits.max_discard_sectors = UINT_MAX >> 9;
+	q->limits.discard_zeroes_data = 1;
+	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
+}
+
 static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 		       struct block_device *bdev, unsigned int arg)
 {
@@ -849,35 +845,23 @@
 	mapping = file->f_mapping;
 	inode = mapping->host;
 
-	if (!(file->f_mode & FMODE_WRITE))
-		lo_flags |= LO_FLAGS_READ_ONLY;
-
 	error = -EINVAL;
-	if (S_ISREG(inode->i_mode) || S_ISBLK(inode->i_mode)) {
-		const struct address_space_operations *aops = mapping->a_ops;
-
-		if (aops->write_begin)
-			lo_flags |= LO_FLAGS_USE_AOPS;
-		if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
-			lo_flags |= LO_FLAGS_READ_ONLY;
+	if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))
+		goto out_putf;
 
-		lo_blocksize = S_ISBLK(inode->i_mode) ?
-			inode->i_bdev->bd_block_size : PAGE_SIZE;
+	if (!(file->f_mode & FMODE_WRITE) || !(mode & FMODE_WRITE) ||
+	    !file->f_op->write)
+		lo_flags |= LO_FLAGS_READ_ONLY;
 
-		error = 0;
-	} else {
-		goto out_putf;
-	}
+	lo_blocksize = S_ISBLK(inode->i_mode) ?
+		inode->i_bdev->bd_block_size : PAGE_SIZE;
 
+	error = -EFBIG;
 	size = get_loop_size(lo, file);
-
-	if ((loff_t)(sector_t)size != size) {
-		error = -EFBIG;
+	if ((loff_t)(sector_t)size != size)
 		goto out_putf;
-	}
 
-	if (!(mode & FMODE_WRITE))
-		lo_flags |= LO_FLAGS_READ_ONLY;
+	error = 0;
 
 	set_device_ro(bdev, (lo_flags & LO_FLAGS_READ_ONLY) != 0);
 
@@ -919,7 +903,9 @@
 	}
 	lo->lo_state = Lo_bound;
 	wake_up_process(lo->lo_thread);
-	if (max_part > 0)
+	if (part_shift)
+		lo->lo_flags |= LO_FLAGS_PARTSCAN;
+	if (lo->lo_flags & LO_FLAGS_PARTSCAN)
 		ioctl_by_bdev(bdev, BLKRRPART, 0);
 	return 0;
 
@@ -980,10 +966,11 @@
 	return err;
 }
 
-static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
+static int loop_clr_fd(struct loop_device *lo)
 {
 	struct file *filp = lo->lo_backing_file;
 	gfp_t gfp = lo->old_gfp_mask;
+	struct block_device *bdev = lo->lo_device;
 
 	if (lo->lo_state != Lo_bound)
 		return -ENXIO;
@@ -1012,7 +999,6 @@
 	lo->lo_offset = 0;
 	lo->lo_sizelimit = 0;
 	lo->lo_encrypt_key_size = 0;
-	lo->lo_flags = 0;
 	lo->lo_thread = NULL;
 	memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
 	memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
@@ -1030,8 +1016,11 @@
 	lo->lo_state = Lo_unbound;
 	/* This is safe: open() is still holding a reference. */
 	module_put(THIS_MODULE);
-	if (max_part > 0 && bdev)
+	if (lo->lo_flags & LO_FLAGS_PARTSCAN && bdev)
 		ioctl_by_bdev(bdev, BLKRRPART, 0);
+	lo->lo_flags = 0;
+	if (!part_shift)
+		lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
 	mutex_unlock(&lo->lo_ctl_mutex);
 	/*
 	 * Need not hold lo_ctl_mutex to fput backing file.
@@ -1080,11 +1069,10 @@
 
 	if (lo->lo_offset != info->lo_offset ||
 	    lo->lo_sizelimit != info->lo_sizelimit) {
-		lo->lo_offset = info->lo_offset;
-		lo->lo_sizelimit = info->lo_sizelimit;
-		if (figure_loop_size(lo))
+		if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit))
 			return -EFBIG;
 	}
+	loop_config_discard(lo);
 
 	memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE);
 	memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE);
@@ -1100,6 +1088,13 @@
 	     (info->lo_flags & LO_FLAGS_AUTOCLEAR))
 		lo->lo_flags ^= LO_FLAGS_AUTOCLEAR;
 
+	if ((info->lo_flags & LO_FLAGS_PARTSCAN) &&
+	     !(lo->lo_flags & LO_FLAGS_PARTSCAN)) {
+		lo->lo_flags |= LO_FLAGS_PARTSCAN;
+		lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN;
+		ioctl_by_bdev(lo->lo_device, BLKRRPART, 0);
+	}
+
 	lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
 	lo->lo_init[0] = info->lo_init[0];
 	lo->lo_init[1] = info->lo_init[1];
@@ -1260,7 +1255,7 @@
 	err = -ENXIO;
 	if (unlikely(lo->lo_state != Lo_bound))
 		goto out;
-	err = figure_loop_size(lo);
+	err = figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit);
 	if (unlikely(err))
 		goto out;
 	sec = get_capacity(lo->lo_disk);
@@ -1293,18 +1288,24 @@
 		break;
 	case LOOP_CLR_FD:
 		/* loop_clr_fd would have unlocked lo_ctl_mutex on success */
-		err = loop_clr_fd(lo, bdev);
+		err = loop_clr_fd(lo);
 		if (!err)
 			goto out_unlocked;
 		break;
 	case LOOP_SET_STATUS:
-		err = loop_set_status_old(lo, (struct loop_info __user *) arg);
+		err = -EPERM;
+		if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN))
+			err = loop_set_status_old(lo,
+					(struct loop_info __user *)arg);
 		break;
 	case LOOP_GET_STATUS:
 		err = loop_get_status_old(lo, (struct loop_info __user *) arg);
 		break;
 	case LOOP_SET_STATUS64:
-		err = loop_set_status64(lo, (struct loop_info64 __user *) arg);
+		err = -EPERM;
+		if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN))
+			err = loop_set_status64(lo,
+					(struct loop_info64 __user *) arg);
 		break;
 	case LOOP_GET_STATUS64:
 		err = loop_get_status64(lo, (struct loop_info64 __user *) arg);
@@ -1513,7 +1514,7 @@
 		 * In autoclear mode, stop the loop thread
 		 * and remove configuration after last close.
 		 */
-		err = loop_clr_fd(lo, NULL);
+		err = loop_clr_fd(lo);
 		if (!err)
 			goto out_unlocked;
 	} else {
@@ -1635,6 +1636,27 @@
 	if (!disk)
 		goto out_free_queue;
 
+	/*
+	 * Disable partition scanning by default. The in-kernel partition
+	 * scanning can be requested individually per-device during its
+	 * setup. Userspace can always add and remove partitions from all
+	 * devices. The needed partition minors are allocated from the
+	 * extended minor space, the main loop device numbers will continue
+	 * to match the loop minors, regardless of the number of partitions
+	 * used.
+	 *
+	 * If max_part is given, partition scanning is globally enabled for
+	 * all loop devices. The minors for the main loop devices will be
+	 * multiples of max_part.
+	 *
+	 * Note: Global-for-all-devices, set-only-at-init, read-only module
+	 * parameteters like 'max_loop' and 'max_part' make things needlessly
+	 * complicated, are too static, inflexible and may surprise
+	 * userspace tools. Parameters like this in general should be avoided.
+	 */
+	if (!part_shift)
+		disk->flags |= GENHD_FL_NO_PART_SCAN;
+	disk->flags |= GENHD_FL_EXT_DEVT;
 	mutex_init(&lo->lo_ctl_mutex);
 	lo->lo_number		= i;
 	lo->lo_thread		= NULL;
diff -druN linux-libre-3.1-gnu/drivers/block/nbd.c linux-libre-3.2-gnu/drivers/block/nbd.c
--- linux-libre-3.1-gnu/drivers/block/nbd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/nbd.c	2012-01-04 18:55:44.000000000 -0500
@@ -127,8 +127,7 @@
 	if (lock)
 		mutex_lock(&lo->tx_lock);
 	if (lo->sock) {
-		printk(KERN_WARNING "%s: shutting down socket\n",
-			lo->disk->disk_name);
+		dev_warn(disk_to_dev(lo->disk), "shutting down socket\n");
 		kernel_sock_shutdown(lo->sock, SHUT_RDWR);
 		lo->sock = NULL;
 	}
@@ -158,8 +157,9 @@
 	sigset_t blocked, oldset;
 
 	if (unlikely(!sock)) {
-		printk(KERN_ERR "%s: Attempted %s on closed socket in sock_xmit\n",
-		       lo->disk->disk_name, (send ? "send" : "recv"));
+		dev_err(disk_to_dev(lo->disk),
+			"Attempted %s on closed socket in sock_xmit\n",
+			(send ? "send" : "recv"));
 		return -EINVAL;
 	}
 
@@ -250,8 +250,8 @@
 	result = sock_xmit(lo, 1, &request, sizeof(request),
 			(nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0);
 	if (result <= 0) {
-		printk(KERN_ERR "%s: Send control failed (result %d)\n",
-				lo->disk->disk_name, result);
+		dev_err(disk_to_dev(lo->disk),
+			"Send control failed (result %d)\n", result);
 		goto error_out;
 	}
 
@@ -270,8 +270,9 @@
 					lo->disk->disk_name, req, bvec->bv_len);
 			result = sock_send_bvec(lo, bvec, flags);
 			if (result <= 0) {
-				printk(KERN_ERR "%s: Send data failed (result %d)\n",
-						lo->disk->disk_name, result);
+				dev_err(disk_to_dev(lo->disk),
+					"Send data failed (result %d)\n",
+					result);
 				goto error_out;
 			}
 		}
@@ -328,14 +329,13 @@
 	reply.magic = 0;
 	result = sock_xmit(lo, 0, &reply, sizeof(reply), MSG_WAITALL);
 	if (result <= 0) {
-		printk(KERN_ERR "%s: Receive control failed (result %d)\n",
-				lo->disk->disk_name, result);
+		dev_err(disk_to_dev(lo->disk),
+			"Receive control failed (result %d)\n", result);
 		goto harderror;
 	}
 
 	if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
-		printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
-				lo->disk->disk_name,
+		dev_err(disk_to_dev(lo->disk), "Wrong magic (0x%lx)\n",
 				(unsigned long)ntohl(reply.magic));
 		result = -EPROTO;
 		goto harderror;
@@ -347,15 +347,15 @@
 		if (result != -ENOENT)
 			goto harderror;
 
-		printk(KERN_ERR "%s: Unexpected reply (%p)\n",
-				lo->disk->disk_name, reply.handle);
+		dev_err(disk_to_dev(lo->disk), "Unexpected reply (%p)\n",
+			reply.handle);
 		result = -EBADR;
 		goto harderror;
 	}
 
 	if (ntohl(reply.error)) {
-		printk(KERN_ERR "%s: Other side returned error (%d)\n",
-				lo->disk->disk_name, ntohl(reply.error));
+		dev_err(disk_to_dev(lo->disk), "Other side returned error (%d)\n",
+			ntohl(reply.error));
 		req->errors++;
 		return req;
 	}
@@ -369,8 +369,8 @@
 		rq_for_each_segment(bvec, req, iter) {
 			result = sock_recv_bvec(lo, bvec);
 			if (result <= 0) {
-				printk(KERN_ERR "%s: Receive data failed (result %d)\n",
-						lo->disk->disk_name, result);
+				dev_err(disk_to_dev(lo->disk), "Receive data failed (result %d)\n",
+					result);
 				req->errors++;
 				return req;
 			}
@@ -405,10 +405,10 @@
 
 	BUG_ON(lo->magic != LO_MAGIC);
 
-	lo->pid = current->pid;
-	ret = sysfs_create_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
+	lo->pid = task_pid_nr(current);
+	ret = device_create_file(disk_to_dev(lo->disk), &pid_attr);
 	if (ret) {
-		printk(KERN_ERR "nbd: sysfs_create_file failed!");
+		dev_err(disk_to_dev(lo->disk), "device_create_file failed!\n");
 		lo->pid = 0;
 		return ret;
 	}
@@ -416,7 +416,7 @@
 	while ((req = nbd_read_stat(lo)) != NULL)
 		nbd_end_request(req);
 
-	sysfs_remove_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
+	device_remove_file(disk_to_dev(lo->disk), &pid_attr);
 	lo->pid = 0;
 	return 0;
 }
@@ -457,8 +457,8 @@
 	if (rq_data_dir(req) == WRITE) {
 		nbd_cmd(req) = NBD_CMD_WRITE;
 		if (lo->flags & NBD_READ_ONLY) {
-			printk(KERN_ERR "%s: Write on read-only\n",
-					lo->disk->disk_name);
+			dev_err(disk_to_dev(lo->disk),
+				"Write on read-only\n");
 			goto error_out;
 		}
 	}
@@ -468,16 +468,15 @@
 	mutex_lock(&lo->tx_lock);
 	if (unlikely(!lo->sock)) {
 		mutex_unlock(&lo->tx_lock);
-		printk(KERN_ERR "%s: Attempted send on closed socket\n",
-		       lo->disk->disk_name);
+		dev_err(disk_to_dev(lo->disk),
+			"Attempted send on closed socket\n");
 		goto error_out;
 	}
 
 	lo->active_req = req;
 
 	if (nbd_send_req(lo, req) != 0) {
-		printk(KERN_ERR "%s: Request send failed\n",
-				lo->disk->disk_name);
+		dev_err(disk_to_dev(lo->disk), "Request send failed\n");
 		req->errors++;
 		nbd_end_request(req);
 	} else {
@@ -549,8 +548,8 @@
 		BUG_ON(lo->magic != LO_MAGIC);
 
 		if (unlikely(!lo->sock)) {
-			printk(KERN_ERR "%s: Attempted send on closed socket\n",
-				lo->disk->disk_name);
+			dev_err(disk_to_dev(lo->disk),
+				"Attempted send on closed socket\n");
 			req->errors++;
 			nbd_end_request(req);
 			spin_lock_irq(q->queue_lock);
@@ -576,7 +575,7 @@
 	case NBD_DISCONNECT: {
 		struct request sreq;
 
-	        printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
+		dev_info(disk_to_dev(lo->disk), "NBD_DISCONNECT\n");
 
 		blk_rq_init(NULL, &sreq);
 		sreq.cmd_type = REQ_TYPE_SPECIAL;
@@ -674,7 +673,7 @@
 		file = lo->file;
 		lo->file = NULL;
 		nbd_clear_que(lo);
-		printk(KERN_WARNING "%s: queue cleared\n", lo->disk->disk_name);
+		dev_warn(disk_to_dev(lo->disk), "queue cleared\n");
 		if (file)
 			fput(file);
 		lo->bytesize = 0;
@@ -694,8 +693,8 @@
 		return 0;
 
 	case NBD_PRINT_DEBUG:
-		printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",
-			bdev->bd_disk->disk_name,
+		dev_info(disk_to_dev(lo->disk),
+			"next = %p, prev = %p, head = %p\n",
 			lo->queue_head.next, lo->queue_head.prev,
 			&lo->queue_head);
 		return 0;
@@ -745,7 +744,7 @@
 	BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
 
 	if (max_part < 0) {
-		printk(KERN_CRIT "nbd: max_part must be >= 0\n");
+		printk(KERN_ERR "nbd: max_part must be >= 0\n");
 		return -EINVAL;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/block/paride/pg.c linux-libre-3.2-gnu/drivers/block/paride/pg.c
--- linux-libre-3.1-gnu/drivers/block/paride/pg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/paride/pg.c	2012-01-04 18:55:44.000000000 -0500
@@ -630,6 +630,7 @@
 		if (dev->status & 0x10)
 			return -ETIME;
 
+	memset(&hdr, 0, sizeof(hdr));
 	hdr.magic = PG_MAGIC;
 	hdr.dlen = dev->dlen;
 	copy = 0;
diff -druN linux-libre-3.1-gnu/drivers/block/pktcdvd.c linux-libre-3.2-gnu/drivers/block/pktcdvd.c
--- linux-libre-3.1-gnu/drivers/block/pktcdvd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/pktcdvd.c	2012-01-04 18:55:44.000000000 -0500
@@ -2444,7 +2444,7 @@
 	pkt_bio_finished(pd);
 }
 
-static int pkt_make_request(struct request_queue *q, struct bio *bio)
+static void pkt_make_request(struct request_queue *q, struct bio *bio)
 {
 	struct pktcdvd_device *pd;
 	char b[BDEVNAME_SIZE];
@@ -2473,7 +2473,7 @@
 		cloned_bio->bi_end_io = pkt_end_io_read_cloned;
 		pd->stats.secs_r += bio->bi_size >> 9;
 		pkt_queue_bio(pd, cloned_bio);
-		return 0;
+		return;
 	}
 
 	if (!test_bit(PACKET_WRITABLE, &pd->flags)) {
@@ -2509,7 +2509,7 @@
 			pkt_make_request(q, &bp->bio1);
 			pkt_make_request(q, &bp->bio2);
 			bio_pair_release(bp);
-			return 0;
+			return;
 		}
 	}
 
@@ -2533,7 +2533,7 @@
 				}
 				spin_unlock(&pkt->lock);
 				spin_unlock(&pd->cdrw.active_list_lock);
-				return 0;
+				return;
 			} else {
 				blocked_bio = 1;
 			}
@@ -2584,10 +2584,9 @@
 		 */
 		wake_up(&pd->wqueue);
 	}
-	return 0;
+	return;
 end_io:
 	bio_io_error(bio);
-	return 0;
 }
 
 
diff -druN linux-libre-3.1-gnu/drivers/block/ps3disk.c linux-libre-3.2-gnu/drivers/block/ps3disk.c
--- linux-libre-3.1-gnu/drivers/block/ps3disk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/ps3disk.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/ata.h>
 #include <linux/blkdev.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include <asm/lv1call.h>
 #include <asm/ps3stor.h>
diff -druN linux-libre-3.1-gnu/drivers/block/ps3vram.c linux-libre-3.2-gnu/drivers/block/ps3vram.c
--- linux-libre-3.1-gnu/drivers/block/ps3vram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/ps3vram.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 
 #include <linux/blkdev.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
@@ -596,7 +597,7 @@
 	return next;
 }
 
-static int ps3vram_make_request(struct request_queue *q, struct bio *bio)
+static void ps3vram_make_request(struct request_queue *q, struct bio *bio)
 {
 	struct ps3_system_bus_device *dev = q->queuedata;
 	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
@@ -610,13 +611,11 @@
 	spin_unlock_irq(&priv->lock);
 
 	if (busy)
-		return 0;
+		return;
 
 	do {
 		bio = ps3vram_do_bio(dev, bio);
 	} while (bio);
-
-	return 0;
 }
 
 static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev)
diff -druN linux-libre-3.1-gnu/drivers/block/rbd.c linux-libre-3.2-gnu/drivers/block/rbd.c
--- linux-libre-3.1-gnu/drivers/block/rbd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/rbd.c	2012-01-04 18:55:44.000000000 -0500
@@ -183,16 +183,12 @@
 
 static int __rbd_init_snaps_header(struct rbd_device *rbd_dev);
 static void rbd_dev_release(struct device *dev);
-static ssize_t rbd_snap_rollback(struct device *dev,
-				 struct device_attribute *attr,
-				 const char *buf,
-				 size_t size);
 static ssize_t rbd_snap_add(struct device *dev,
 			    struct device_attribute *attr,
 			    const char *buf,
 			    size_t count);
 static void __rbd_remove_snap_dev(struct rbd_device *rbd_dev,
-				  struct rbd_snap *snap);;
+				  struct rbd_snap *snap);
 
 
 static struct rbd_device *dev_to_rbd(struct device *dev)
@@ -260,7 +256,7 @@
 	kref_init(&rbdc->kref);
 	INIT_LIST_HEAD(&rbdc->node);
 
-	rbdc->client = ceph_create_client(opt, rbdc);
+	rbdc->client = ceph_create_client(opt, rbdc, 0, 0);
 	if (IS_ERR(rbdc->client))
 		goto out_rbdc;
 	opt = NULL; /* Now rbdc->client is responsible for opt */
@@ -461,6 +457,10 @@
 	u32 snap_count = le32_to_cpu(ondisk->snap_count);
 	int ret = -ENOMEM;
 
+	if (memcmp(ondisk, RBD_HEADER_TEXT, sizeof(RBD_HEADER_TEXT))) {
+		return -ENXIO;
+	}
+
 	init_rwsem(&header->snap_rwsem);
 	header->snap_names_len = le64_to_cpu(ondisk->snap_names_len);
 	header->snapc = kmalloc(sizeof(struct ceph_snap_context) +
@@ -1356,32 +1356,6 @@
 }
 
 /*
- * Request sync osd rollback
- */
-static int rbd_req_sync_rollback_obj(struct rbd_device *dev,
-				     u64 snapid,
-				     const char *obj)
-{
-	struct ceph_osd_req_op *ops;
-	int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_ROLLBACK, 0);
-	if (ret < 0)
-		return ret;
-
-	ops[0].snap.snapid = snapid;
-
-	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);
-
-	rbd_destroy_ops(ops);
-
-	return ret;
-}
-
-/*
  * Request sync osd read
  */
 static int rbd_req_sync_exec(struct rbd_device *dev,
@@ -1610,8 +1584,13 @@
 			goto out_dh;
 
 		rc = rbd_header_from_disk(header, dh, snap_count, GFP_KERNEL);
-		if (rc < 0)
+		if (rc < 0) {
+			if (rc == -ENXIO) {
+				pr_warning("unrecognized header format"
+					   " for image %s", rbd_dev->obj);
+			}
 			goto out_dh;
+		}
 
 		if (snap_count != header->total_snaps) {
 			snap_count = header->total_snaps;
@@ -1882,7 +1861,6 @@
 static DEVICE_ATTR(refresh, S_IWUSR, NULL, rbd_image_refresh);
 static DEVICE_ATTR(current_snap, S_IRUGO, rbd_snap_show, NULL);
 static DEVICE_ATTR(create_snap, S_IWUSR, NULL, rbd_snap_add);
-static DEVICE_ATTR(rollback_snap, S_IWUSR, NULL, rbd_snap_rollback);
 
 static struct attribute *rbd_attrs[] = {
 	&dev_attr_size.attr,
@@ -1893,7 +1871,6 @@
 	&dev_attr_current_snap.attr,
 	&dev_attr_refresh.attr,
 	&dev_attr_create_snap.attr,
-	&dev_attr_rollback_snap.attr,
 	NULL
 };
 
@@ -2424,64 +2401,6 @@
 	return ret;
 }
 
-static ssize_t rbd_snap_rollback(struct device *dev,
-				 struct device_attribute *attr,
-				 const char *buf,
-				 size_t count)
-{
-	struct rbd_device *rbd_dev = dev_to_rbd(dev);
-	int ret;
-	u64 snapid;
-	u64 cur_ofs;
-	char *seg_name = NULL;
-	char *snap_name = kmalloc(count + 1, GFP_KERNEL);
-	ret = -ENOMEM;
-	if (!snap_name)
-		return ret;
-
-	/* parse snaps add command */
-	snprintf(snap_name, count, "%s", buf);
-	seg_name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO);
-	if (!seg_name)
-		goto done;
-
-	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
-
-	ret = snap_by_name(&rbd_dev->header, snap_name, &snapid, NULL);
-	if (ret < 0)
-		goto done_unlock;
-
-	dout("snapid=%lld\n", snapid);
-
-	cur_ofs = 0;
-	while (cur_ofs < rbd_dev->header.image_size) {
-		cur_ofs += rbd_get_segment(&rbd_dev->header,
-					   rbd_dev->obj,
-					   cur_ofs, (u64)-1,
-					   seg_name, NULL);
-		dout("seg_name=%s\n", seg_name);
-
-		ret = rbd_req_sync_rollback_obj(rbd_dev, snapid, seg_name);
-		if (ret < 0)
-			pr_warning("could not roll back obj %s err=%d\n",
-				   seg_name, ret);
-	}
-
-	ret = __rbd_update_snaps(rbd_dev);
-	if (ret < 0)
-		goto done_unlock;
-
-	ret = count;
-
-done_unlock:
-	mutex_unlock(&ctl_mutex);
-done:
-	kfree(seg_name);
-	kfree(snap_name);
-
-	return ret;
-}
-
 static struct bus_attribute rbd_bus_attrs[] = {
 	__ATTR(add, S_IWUSR, NULL, rbd_add),
 	__ATTR(remove, S_IWUSR, NULL, rbd_remove),
diff -druN linux-libre-3.1-gnu/drivers/block/swim3.c linux-libre-3.2-gnu/drivers/block/swim3.c
--- linux-libre-3.1-gnu/drivers/block/swim3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/swim3.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  * handle GCR disks
  */
 
+#undef DEBUG
+
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -36,13 +38,11 @@
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 
-static DEFINE_MUTEX(swim3_mutex);
-static struct request_queue *swim3_queue;
-static struct gendisk *disks[2];
-static struct request *fd_req;
-
 #define MAX_FLOPPIES	2
 
+static DEFINE_MUTEX(swim3_mutex);
+static struct gendisk *disks[MAX_FLOPPIES];
+
 enum swim_state {
 	idle,
 	locating,
@@ -177,7 +177,6 @@
 
 struct floppy_state {
 	enum swim_state	state;
-	spinlock_t lock;
 	struct swim3 __iomem *swim3;	/* hardware registers */
 	struct dbdma_regs __iomem *dma;	/* DMA controller registers */
 	int	swim3_intr;	/* interrupt number for SWIM3 */
@@ -204,8 +203,20 @@
 	int	wanted;
 	struct macio_dev *mdev;
 	char	dbdma_cmd_space[5 * sizeof(struct dbdma_cmd)];
+	int	index;
+	struct request *cur_req;
 };
 
+#define swim3_err(fmt, arg...)	dev_err(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg)
+#define swim3_warn(fmt, arg...)	dev_warn(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg)
+#define swim3_info(fmt, arg...)	dev_info(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg)
+
+#ifdef DEBUG
+#define swim3_dbg(fmt, arg...)	dev_dbg(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg)
+#else
+#define swim3_dbg(fmt, arg...)	do { } while(0)
+#endif
+
 static struct floppy_state floppy_states[MAX_FLOPPIES];
 static int floppy_count = 0;
 static DEFINE_SPINLOCK(swim3_lock);
@@ -224,17 +235,8 @@
 	0, 0, 0, 0, 0, 0
 };
 
-static void swim3_select(struct floppy_state *fs, int sel);
-static void swim3_action(struct floppy_state *fs, int action);
-static int swim3_readbit(struct floppy_state *fs, int bit);
-static void do_fd_request(struct request_queue * q);
-static void start_request(struct floppy_state *fs);
-static void set_timeout(struct floppy_state *fs, int nticks,
-			void (*proc)(unsigned long));
-static void scan_track(struct floppy_state *fs);
 static void seek_track(struct floppy_state *fs, int n);
 static void init_dma(struct dbdma_cmd *cp, int cmd, void *buf, int count);
-static void setup_transfer(struct floppy_state *fs);
 static void act(struct floppy_state *fs);
 static void scan_timeout(unsigned long data);
 static void seek_timeout(unsigned long data);
@@ -254,18 +256,21 @@
 					unsigned int clearing);
 static int floppy_revalidate(struct gendisk *disk);
 
-static bool swim3_end_request(int err, unsigned int nr_bytes)
+static bool swim3_end_request(struct floppy_state *fs, int err, unsigned int nr_bytes)
 {
-	if (__blk_end_request(fd_req, err, nr_bytes))
-		return true;
+	struct request *req = fs->cur_req;
+	int rc;
 
-	fd_req = NULL;
-	return false;
-}
+	swim3_dbg("  end request, err=%d nr_bytes=%d, cur_req=%p\n",
+		  err, nr_bytes, req);
 
-static bool swim3_end_request_cur(int err)
-{
-	return swim3_end_request(err, blk_rq_cur_bytes(fd_req));
+	if (err)
+		nr_bytes = blk_rq_cur_bytes(req);
+	rc = __blk_end_request(req, err, nr_bytes);
+	if (rc)
+		return true;
+	fs->cur_req = NULL;
+	return false;
 }
 
 static void swim3_select(struct floppy_state *fs, int sel)
@@ -303,50 +308,53 @@
 	return (stat & DATA) == 0;
 }
 
-static void do_fd_request(struct request_queue * q)
-{
-	int i;
-
-	for(i=0; i<floppy_count; i++) {
-		struct floppy_state *fs = &floppy_states[i];
-		if (fs->mdev->media_bay &&
-		    check_media_bay(fs->mdev->media_bay) != MB_FD)
-			continue;
-		start_request(fs);
-	}
-}
-
 static void start_request(struct floppy_state *fs)
 {
 	struct request *req;
 	unsigned long x;
 
+	swim3_dbg("start request, initial state=%d\n", fs->state);
+
 	if (fs->state == idle && fs->wanted) {
 		fs->state = available;
 		wake_up(&fs->wait);
 		return;
 	}
 	while (fs->state == idle) {
-		if (!fd_req) {
-			fd_req = blk_fetch_request(swim3_queue);
-			if (!fd_req)
+		swim3_dbg("start request, idle loop, cur_req=%p\n", fs->cur_req);
+		if (!fs->cur_req) {
+			fs->cur_req = blk_fetch_request(disks[fs->index]->queue);
+			swim3_dbg("  fetched request %p\n", fs->cur_req);
+			if (!fs->cur_req)
 				break;
 		}
-		req = fd_req;
-#if 0
-		printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%u buf=%p\n",
-		       req->rq_disk->disk_name, req->cmd,
-		       (long)blk_rq_pos(req), blk_rq_sectors(req), req->buffer);
-		printk("           errors=%d current_nr_sectors=%u\n",
-		       req->errors, blk_rq_cur_sectors(req));
+		req = fs->cur_req;
+
+		if (fs->mdev->media_bay &&
+		    check_media_bay(fs->mdev->media_bay) != MB_FD) {
+			swim3_dbg("%s", "  media bay absent, dropping req\n");
+			swim3_end_request(fs, -ENODEV, 0);
+			continue;
+		}
+
+#if 0 /* This is really too verbose */
+		swim3_dbg("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%u buf=%p\n",
+			  req->rq_disk->disk_name, req->cmd,
+			  (long)blk_rq_pos(req), blk_rq_sectors(req),
+			  req->buffer);
+		swim3_dbg("           errors=%d current_nr_sectors=%u\n",
+			  req->errors, blk_rq_cur_sectors(req));
 #endif
 
 		if (blk_rq_pos(req) >= fs->total_secs) {
-			swim3_end_request_cur(-EIO);
+			swim3_dbg("  pos out of bounds (%ld, max is %ld)\n",
+				  (long)blk_rq_pos(req), (long)fs->total_secs);
+			swim3_end_request(fs, -EIO, 0);
 			continue;
 		}
 		if (fs->ejected) {
-			swim3_end_request_cur(-EIO);
+			swim3_dbg("%s", "  disk ejected\n");
+			swim3_end_request(fs, -EIO, 0);
 			continue;
 		}
 
@@ -354,7 +362,8 @@
 			if (fs->write_prot < 0)
 				fs->write_prot = swim3_readbit(fs, WRITE_PROT);
 			if (fs->write_prot) {
-				swim3_end_request_cur(-EIO);
+				swim3_dbg("%s", "  try to write, disk write protected\n");
+				swim3_end_request(fs, -EIO, 0);
 				continue;
 			}
 		}
@@ -369,7 +378,6 @@
 		x = ((long)blk_rq_pos(req)) % fs->secpercyl;
 		fs->head = x / fs->secpertrack;
 		fs->req_sector = x % fs->secpertrack + 1;
-		fd_req = req;
 		fs->state = do_transfer;
 		fs->retries = 0;
 
@@ -377,12 +385,14 @@
 	}
 }
 
+static void do_fd_request(struct request_queue * q)
+{
+	start_request(q->queuedata);
+}
+
 static void set_timeout(struct floppy_state *fs, int nticks,
 			void (*proc)(unsigned long))
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&fs->lock, flags);
 	if (fs->timeout_pending)
 		del_timer(&fs->timeout);
 	fs->timeout.expires = jiffies + nticks;
@@ -390,7 +400,6 @@
 	fs->timeout.data = (unsigned long) fs;
 	add_timer(&fs->timeout);
 	fs->timeout_pending = 1;
-	spin_unlock_irqrestore(&fs->lock, flags);
 }
 
 static inline void scan_track(struct floppy_state *fs)
@@ -442,40 +451,45 @@
 	struct swim3 __iomem *sw = fs->swim3;
 	struct dbdma_cmd *cp = fs->dma_cmd;
 	struct dbdma_regs __iomem *dr = fs->dma;
+	struct request *req = fs->cur_req;
 
-	if (blk_rq_cur_sectors(fd_req) <= 0) {
-		printk(KERN_ERR "swim3: transfer 0 sectors?\n");
+	if (blk_rq_cur_sectors(req) <= 0) {
+		swim3_warn("%s", "Transfer 0 sectors ?\n");
 		return;
 	}
-	if (rq_data_dir(fd_req) == WRITE)
+	if (rq_data_dir(req) == WRITE)
 		n = 1;
 	else {
 		n = fs->secpertrack - fs->req_sector + 1;
-		if (n > blk_rq_cur_sectors(fd_req))
-			n = blk_rq_cur_sectors(fd_req);
+		if (n > blk_rq_cur_sectors(req))
+			n = blk_rq_cur_sectors(req);
 	}
+
+	swim3_dbg("  setup xfer at sect %d (of %d) head %d for %d\n",
+		  fs->req_sector, fs->secpertrack, fs->head, n);
+
 	fs->scount = n;
 	swim3_select(fs, fs->head? READ_DATA_1: READ_DATA_0);
 	out_8(&sw->sector, fs->req_sector);
 	out_8(&sw->nsect, n);
 	out_8(&sw->gap3, 0);
 	out_le32(&dr->cmdptr, virt_to_bus(cp));
-	if (rq_data_dir(fd_req) == WRITE) {
+	if (rq_data_dir(req) == WRITE) {
 		/* Set up 3 dma commands: write preamble, data, postamble */
 		init_dma(cp, OUTPUT_MORE, write_preamble, sizeof(write_preamble));
 		++cp;
-		init_dma(cp, OUTPUT_MORE, fd_req->buffer, 512);
+		init_dma(cp, OUTPUT_MORE, req->buffer, 512);
 		++cp;
 		init_dma(cp, OUTPUT_LAST, write_postamble, sizeof(write_postamble));
 	} else {
-		init_dma(cp, INPUT_LAST, fd_req->buffer, n * 512);
+		init_dma(cp, INPUT_LAST, req->buffer, n * 512);
 	}
 	++cp;
 	out_le16(&cp->command, DBDMA_STOP);
 	out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS);
 	in_8(&sw->error);
 	out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS);
-	if (rq_data_dir(fd_req) == WRITE)
+	if (rq_data_dir(req) == WRITE)
 		out_8(&sw->control_bis, WRITE_SECTORS);
 	in_8(&sw->intr);
 	out_le32(&dr->control, (RUN << 16) | RUN);
@@ -488,12 +502,16 @@
 static void act(struct floppy_state *fs)
 {
 	for (;;) {
+		swim3_dbg("  act loop, state=%d, req_cyl=%d, cur_cyl=%d\n",
+			  fs->state, fs->req_cyl, fs->cur_cyl);
+
 		switch (fs->state) {
 		case idle:
 			return;		/* XXX shouldn't get here */
 
 		case locating:
 			if (swim3_readbit(fs, TRACK_ZERO)) {
+				swim3_dbg("%s", "    locate track 0\n");
 				fs->cur_cyl = 0;
 				if (fs->req_cyl == 0)
 					fs->state = do_transfer;
@@ -511,7 +529,7 @@
 				break;
 			}
 			if (fs->req_cyl == fs->cur_cyl) {
-				printk("whoops, seeking 0\n");
+				swim3_warn("%s", "Whoops, seeking 0\n");
 				fs->state = do_transfer;
 				break;
 			}
@@ -527,7 +545,9 @@
 		case do_transfer:
 			if (fs->cur_cyl != fs->req_cyl) {
 				if (fs->retries > 5) {
-					swim3_end_request_cur(-EIO);
+					swim3_err("Wrong cylinder in transfer, want: %d got %d\n",
+						  fs->req_cyl, fs->cur_cyl);
+					swim3_end_request(fs, -EIO, 0);
 					fs->state = idle;
 					return;
 				}
@@ -542,7 +562,7 @@
 			return;
 
 		default:
-			printk(KERN_ERR"swim3: unknown state %d\n", fs->state);
+			swim3_err("Unknown state %d\n", fs->state);
 			return;
 		}
 	}
@@ -552,59 +572,75 @@
 {
 	struct floppy_state *fs = (struct floppy_state *) data;
 	struct swim3 __iomem *sw = fs->swim3;
+	unsigned long flags;
+
+	swim3_dbg("* scan timeout, state=%d\n", fs->state);
 
+	spin_lock_irqsave(&swim3_lock, flags);
 	fs->timeout_pending = 0;
 	out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS);
 	out_8(&sw->select, RELAX);
 	out_8(&sw->intr_enable, 0);
 	fs->cur_cyl = -1;
 	if (fs->retries > 5) {
-		swim3_end_request_cur(-EIO);
+		swim3_end_request(fs, -EIO, 0);
 		fs->state = idle;
 		start_request(fs);
 	} else {
 		fs->state = jogging;
 		act(fs);
 	}
+	spin_unlock_irqrestore(&swim3_lock, flags);
 }
 
 static void seek_timeout(unsigned long data)
 {
 	struct floppy_state *fs = (struct floppy_state *) data;
 	struct swim3 __iomem *sw = fs->swim3;
+	unsigned long flags;
 
+	swim3_dbg("* seek timeout, state=%d\n", fs->state);
+
+	spin_lock_irqsave(&swim3_lock, flags);
 	fs->timeout_pending = 0;
 	out_8(&sw->control_bic, DO_SEEK);
 	out_8(&sw->select, RELAX);
 	out_8(&sw->intr_enable, 0);
-	printk(KERN_ERR "swim3: seek timeout\n");
-	swim3_end_request_cur(-EIO);
+	swim3_err("%s", "Seek timeout\n");
+	swim3_end_request(fs, -EIO, 0);
 	fs->state = idle;
 	start_request(fs);
+	spin_unlock_irqrestore(&swim3_lock, flags);
 }
 
 static void settle_timeout(unsigned long data)
 {
 	struct floppy_state *fs = (struct floppy_state *) data;
 	struct swim3 __iomem *sw = fs->swim3;
+	unsigned long flags;
+
+	swim3_dbg("* settle timeout, state=%d\n", fs->state);
 
+	spin_lock_irqsave(&swim3_lock, flags);
 	fs->timeout_pending = 0;
 	if (swim3_readbit(fs, SEEK_COMPLETE)) {
 		out_8(&sw->select, RELAX);
 		fs->state = locating;
 		act(fs);
-		return;
+		goto unlock;
 	}
 	out_8(&sw->select, RELAX);
 	if (fs->settle_time < 2*HZ) {
 		++fs->settle_time;
 		set_timeout(fs, 1, settle_timeout);
-		return;
+		goto unlock;
 	}
-	printk(KERN_ERR "swim3: seek settle timeout\n");
-	swim3_end_request_cur(-EIO);
+	swim3_err("%s", "Seek settle timeout\n");
+	swim3_end_request(fs, -EIO, 0);
 	fs->state = idle;
 	start_request(fs);
+ unlock:
+	spin_unlock_irqrestore(&swim3_lock, flags);
 }
 
 static void xfer_timeout(unsigned long data)
@@ -612,8 +648,12 @@
 	struct floppy_state *fs = (struct floppy_state *) data;
 	struct swim3 __iomem *sw = fs->swim3;
 	struct dbdma_regs __iomem *dr = fs->dma;
+	unsigned long flags;
 	int n;
 
+	swim3_dbg("* xfer timeout, state=%d\n", fs->state);
+
+	spin_lock_irqsave(&swim3_lock, flags);
 	fs->timeout_pending = 0;
 	out_le32(&dr->control, RUN << 16);
 	/* We must wait a bit for dbdma to stop */
@@ -622,12 +662,13 @@
 	out_8(&sw->intr_enable, 0);
 	out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION);
 	out_8(&sw->select, RELAX);
-	printk(KERN_ERR "swim3: timeout %sing sector %ld\n",
-	       (rq_data_dir(fd_req)==WRITE? "writ": "read"),
-	       (long)blk_rq_pos(fd_req));
-	swim3_end_request_cur(-EIO);
+	swim3_err("Timeout %sing sector %ld\n",
+	       (rq_data_dir(fs->cur_req)==WRITE? "writ": "read"),
+	       (long)blk_rq_pos(fs->cur_req));
+	swim3_end_request(fs, -EIO, 0);
 	fs->state = idle;
 	start_request(fs);
+	spin_unlock_irqrestore(&swim3_lock, flags);
 }
 
 static irqreturn_t swim3_interrupt(int irq, void *dev_id)
@@ -638,12 +679,17 @@
 	int stat, resid;
 	struct dbdma_regs __iomem *dr;
 	struct dbdma_cmd *cp;
+	unsigned long flags;
+	struct request *req = fs->cur_req;
 
+	swim3_dbg("* interrupt, state=%d\n", fs->state);
+
+	spin_lock_irqsave(&swim3_lock, flags);
 	intr = in_8(&sw->intr);
 	err = (intr & ERROR_INTR)? in_8(&sw->error): 0;
 	if ((intr & ERROR_INTR) && fs->state != do_transfer)
-		printk(KERN_ERR "swim3_interrupt, state=%d, dir=%x, intr=%x, err=%x\n",
-		       fs->state, rq_data_dir(fd_req), intr, err);
+		swim3_err("Non-transfer error interrupt: state=%d, dir=%x, intr=%x, err=%x\n",
+			  fs->state, rq_data_dir(req), intr, err);
 	switch (fs->state) {
 	case locating:
 		if (intr & SEEN_SECTOR) {
@@ -653,10 +699,10 @@
 			del_timer(&fs->timeout);
 			fs->timeout_pending = 0;
 			if (sw->ctrack == 0xff) {
-				printk(KERN_ERR "swim3: seen sector but cyl=ff?\n");
+				swim3_err("%s", "Seen sector but cyl=ff?\n");
 				fs->cur_cyl = -1;
 				if (fs->retries > 5) {
-					swim3_end_request_cur(-EIO);
+					swim3_end_request(fs, -EIO, 0);
 					fs->state = idle;
 					start_request(fs);
 				} else {
@@ -668,8 +714,8 @@
 			fs->cur_cyl = sw->ctrack;
 			fs->cur_sector = sw->csect;
 			if (fs->expect_cyl != -1 && fs->expect_cyl != fs->cur_cyl)
-				printk(KERN_ERR "swim3: expected cyl %d, got %d\n",
-				       fs->expect_cyl, fs->cur_cyl);
+				swim3_err("Expected cyl %d, got %d\n",
+					  fs->expect_cyl, fs->cur_cyl);
 			fs->state = do_transfer;
 			act(fs);
 		}
@@ -704,7 +750,7 @@
 		fs->timeout_pending = 0;
 		dr = fs->dma;
 		cp = fs->dma_cmd;
-		if (rq_data_dir(fd_req) == WRITE)
+		if (rq_data_dir(req) == WRITE)
 			++cp;
 		/*
 		 * Check that the main data transfer has finished.
@@ -729,31 +775,32 @@
 		if (intr & ERROR_INTR) {
 			n = fs->scount - 1 - resid / 512;
 			if (n > 0) {
-				blk_update_request(fd_req, 0, n << 9);
+				blk_update_request(req, 0, n << 9);
 				fs->req_sector += n;
 			}
 			if (fs->retries < 5) {
 				++fs->retries;
 				act(fs);
 			} else {
-				printk("swim3: error %sing block %ld (err=%x)\n",
-				       rq_data_dir(fd_req) == WRITE? "writ": "read",
-				       (long)blk_rq_pos(fd_req), err);
-				swim3_end_request_cur(-EIO);
+				swim3_err("Error %sing block %ld (err=%x)\n",
+				       rq_data_dir(req) == WRITE? "writ": "read",
+				       (long)blk_rq_pos(req), err);
+				swim3_end_request(fs, -EIO, 0);
 				fs->state = idle;
 			}
 		} else {
 			if ((stat & ACTIVE) == 0 || resid != 0) {
 				/* musta been an error */
-				printk(KERN_ERR "swim3: fd dma: stat=%x resid=%d\n", stat, resid);
-				printk(KERN_ERR "  state=%d, dir=%x, intr=%x, err=%x\n",
-				       fs->state, rq_data_dir(fd_req), intr, err);
-				swim3_end_request_cur(-EIO);
+				swim3_err("fd dma error: stat=%x resid=%d\n", stat, resid);
+				swim3_err("  state=%d, dir=%x, intr=%x, err=%x\n",
+					  fs->state, rq_data_dir(req), intr, err);
+				swim3_end_request(fs, -EIO, 0);
 				fs->state = idle;
 				start_request(fs);
 				break;
 			}
-			if (swim3_end_request(0, fs->scount << 9)) {
+			fs->retries = 0;
+			if (swim3_end_request(fs, 0, fs->scount << 9)) {
 				fs->req_sector += fs->scount;
 				if (fs->req_sector > fs->secpertrack) {
 					fs->req_sector -= fs->secpertrack;
@@ -770,8 +817,9 @@
 			start_request(fs);
 		break;
 	default:
-		printk(KERN_ERR "swim3: don't know what to do in state %d\n", fs->state);
+		swim3_err("Don't know what to do in state %d\n", fs->state);
 	}
+	spin_unlock_irqrestore(&swim3_lock, flags);
 	return IRQ_HANDLED;
 }
 
@@ -781,26 +829,31 @@
 }
 */
 
+/* Called under the mutex to grab exclusive access to a drive */
 static int grab_drive(struct floppy_state *fs, enum swim_state state,
 		      int interruptible)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&fs->lock, flags);
-	if (fs->state != idle) {
+	swim3_dbg("%s", "-> grab drive\n");
+
+	spin_lock_irqsave(&swim3_lock, flags);
+	if (fs->state != idle && fs->state != available) {
 		++fs->wanted;
 		while (fs->state != available) {
+			spin_unlock_irqrestore(&swim3_lock, flags);
 			if (interruptible && signal_pending(current)) {
 				--fs->wanted;
-				spin_unlock_irqrestore(&fs->lock, flags);
 				return -EINTR;
 			}
 			interruptible_sleep_on(&fs->wait);
+			spin_lock_irqsave(&swim3_lock, flags);
 		}
 		--fs->wanted;
 	}
 	fs->state = state;
-	spin_unlock_irqrestore(&fs->lock, flags);
+	spin_unlock_irqrestore(&swim3_lock, flags);
+
 	return 0;
 }
 
@@ -808,10 +861,12 @@
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&fs->lock, flags);
+	swim3_dbg("%s", "-> release drive\n");
+
+	spin_lock_irqsave(&swim3_lock, flags);
 	fs->state = idle;
 	start_request(fs);
-	spin_unlock_irqrestore(&fs->lock, flags);
+	spin_unlock_irqrestore(&swim3_lock, flags);
 }
 
 static int fd_eject(struct floppy_state *fs)
@@ -966,6 +1021,7 @@
 {
 	struct floppy_state *fs = disk->private_data;
 	struct swim3 __iomem *sw = fs->swim3;
+
 	mutex_lock(&swim3_mutex);
 	if (fs->ref_count > 0 && --fs->ref_count == 0) {
 		swim3_action(fs, MOTOR_OFF);
@@ -1031,30 +1087,48 @@
 	.revalidate_disk= floppy_revalidate,
 };
 
+static void swim3_mb_event(struct macio_dev* mdev, int mb_state)
+{
+	struct floppy_state *fs = macio_get_drvdata(mdev);
+	struct swim3 __iomem *sw = fs->swim3;
+
+	if (!fs)
+		return;
+	if (mb_state != MB_FD)
+		return;
+
+	/* Clear state */
+	out_8(&sw->intr_enable, 0);
+	in_8(&sw->intr);
+	in_8(&sw->error);
+}
+
 static int swim3_add_device(struct macio_dev *mdev, int index)
 {
 	struct device_node *swim = mdev->ofdev.dev.of_node;
 	struct floppy_state *fs = &floppy_states[index];
 	int rc = -EBUSY;
 
+	/* Do this first for message macros */
+	memset(fs, 0, sizeof(*fs));
+	fs->mdev = mdev;
+	fs->index = index;
+
 	/* Check & Request resources */
 	if (macio_resource_count(mdev) < 2) {
-		printk(KERN_WARNING "ifd%d: no address for %s\n",
-		       index, swim->full_name);
+		swim3_err("%s", "No address in device-tree\n");
 		return -ENXIO;
 	}
-	if (macio_irq_count(mdev) < 2) {
-		printk(KERN_WARNING "fd%d: no intrs for device %s\n",
-			index, swim->full_name);
+	if (macio_irq_count(mdev) < 1) {
+		swim3_err("%s", "No interrupt in device-tree\n");
+		return -ENXIO;
 	}
 	if (macio_request_resource(mdev, 0, "swim3 (mmio)")) {
-		printk(KERN_ERR "fd%d: can't request mmio resource for %s\n",
-		       index, swim->full_name);
+		swim3_err("%s", "Can't request mmio resource\n");
 		return -EBUSY;
 	}
 	if (macio_request_resource(mdev, 1, "swim3 (dma)")) {
-		printk(KERN_ERR "fd%d: can't request dma resource for %s\n",
-		       index, swim->full_name);
+		swim3_err("%s", "Can't request dma resource\n");
 		macio_release_resource(mdev, 0);
 		return -EBUSY;
 	}
@@ -1063,22 +1137,18 @@
 	if (mdev->media_bay == NULL)
 		pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 1);
 	
-	memset(fs, 0, sizeof(*fs));
-	spin_lock_init(&fs->lock);
 	fs->state = idle;
 	fs->swim3 = (struct swim3 __iomem *)
 		ioremap(macio_resource_start(mdev, 0), 0x200);
 	if (fs->swim3 == NULL) {
-		printk("fd%d: couldn't map registers for %s\n",
-		       index, swim->full_name);
+		swim3_err("%s", "Couldn't map mmio registers\n");
 		rc = -ENOMEM;
 		goto out_release;
 	}
 	fs->dma = (struct dbdma_regs __iomem *)
 		ioremap(macio_resource_start(mdev, 1), 0x200);
 	if (fs->dma == NULL) {
-		printk("fd%d: couldn't map DMA for %s\n",
-		       index, swim->full_name);
+		swim3_err("%s", "Couldn't map dma registers\n");
 		iounmap(fs->swim3);
 		rc = -ENOMEM;
 		goto out_release;
@@ -1090,31 +1160,25 @@
 	fs->secpercyl = 36;
 	fs->secpertrack = 18;
 	fs->total_secs = 2880;
-	fs->mdev = mdev;
 	init_waitqueue_head(&fs->wait);
 
 	fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space);
 	memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd));
 	st_le16(&fs->dma_cmd[1].command, DBDMA_STOP);
 
+	if (mdev->media_bay == NULL || check_media_bay(mdev->media_bay) == MB_FD)
+		swim3_mb_event(mdev, MB_FD);
+
 	if (request_irq(fs->swim3_intr, swim3_interrupt, 0, "SWIM3", fs)) {
-		printk(KERN_ERR "fd%d: couldn't request irq %d for %s\n",
-		       index, fs->swim3_intr, swim->full_name);
+		swim3_err("%s", "Couldn't request interrupt\n");
 		pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 0);
 		goto out_unmap;
 		return -EBUSY;
 	}
-/*
-	if (request_irq(fs->dma_intr, fd_dma_interrupt, 0, "SWIM3-dma", fs)) {
-		printk(KERN_ERR "Couldn't get irq %d for SWIM3 DMA",
-		       fs->dma_intr);
-		return -EBUSY;
-	}
-*/
 
 	init_timer(&fs->timeout);
 
-	printk(KERN_INFO "fd%d: SWIM3 floppy controller %s\n", floppy_count,
+	swim3_info("SWIM3 floppy controller %s\n",
 		mdev->media_bay ? "in media bay" : "");
 
 	return 0;
@@ -1132,41 +1196,42 @@
 
 static int __devinit swim3_attach(struct macio_dev *mdev, const struct of_device_id *match)
 {
-	int i, rc;
 	struct gendisk *disk;
+	int index, rc;
+
+	index = floppy_count++;
+	if (index >= MAX_FLOPPIES)
+		return -ENXIO;
 
 	/* Add the drive */
-	rc = swim3_add_device(mdev, floppy_count);
+	rc = swim3_add_device(mdev, index);
 	if (rc)
 		return rc;
+	/* Now register that disk. Same comment about failure handling */
+	disk = disks[index] = alloc_disk(1);
+	if (disk == NULL)
+		return -ENOMEM;
+	disk->queue = blk_init_queue(do_fd_request, &swim3_lock);
+	if (disk->queue == NULL) {
+		put_disk(disk);
+		return -ENOMEM;
+	}
+	disk->queue->queuedata = &floppy_states[index];
 
-	/* Now create the queue if not there yet */
-	if (swim3_queue == NULL) {
+	if (index == 0) {
 		/* If we failed, there isn't much we can do as the driver is still
 		 * too dumb to remove the device, just bail out
 		 */
 		if (register_blkdev(FLOPPY_MAJOR, "fd"))
 			return 0;
-		swim3_queue = blk_init_queue(do_fd_request, &swim3_lock);
-		if (swim3_queue == NULL) {
-			unregister_blkdev(FLOPPY_MAJOR, "fd");
-			return 0;
-		}
 	}
 
-	/* Now register that disk. Same comment about failure handling */
-	i = floppy_count++;
-	disk = disks[i] = alloc_disk(1);
-	if (disk == NULL)
-		return 0;
-
 	disk->major = FLOPPY_MAJOR;
-	disk->first_minor = i;
+	disk->first_minor = index;
 	disk->fops = &floppy_fops;
-	disk->private_data = &floppy_states[i];
-	disk->queue = swim3_queue;
+	disk->private_data = &floppy_states[index];
 	disk->flags |= GENHD_FL_REMOVABLE;
-	sprintf(disk->disk_name, "fd%d", i);
+	sprintf(disk->disk_name, "fd%d", index);
 	set_capacity(disk, 2880);
 	add_disk(disk);
 
@@ -1194,6 +1259,9 @@
 		.of_match_table	= swim3_match,
 	},
 	.probe		= swim3_attach,
+#ifdef CONFIG_PMAC_MEDIABAY
+	.mediabay_event	= swim3_mb_event,
+#endif
 #if 0
 	.suspend	= swim3_suspend,
 	.resume		= swim3_resume,
diff -druN linux-libre-3.1-gnu/drivers/block/umem.c linux-libre-3.2-gnu/drivers/block/umem.c
--- linux-libre-3.1-gnu/drivers/block/umem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/umem.c	2012-01-04 18:55:44.000000000 -0500
@@ -513,7 +513,7 @@
 	}
 }
 
-static int mm_make_request(struct request_queue *q, struct bio *bio)
+static void mm_make_request(struct request_queue *q, struct bio *bio)
 {
 	struct cardinfo *card = q->queuedata;
 	pr_debug("mm_make_request %llu %u\n",
@@ -525,7 +525,7 @@
 	card->biotail = &bio->bi_next;
 	spin_unlock_irq(&card->lock);
 
-	return 0;
+	return;
 }
 
 static irqreturn_t mm_interrupt(int irq, void *__card)
diff -druN linux-libre-3.1-gnu/drivers/block/virtio_blk.c linux-libre-3.2-gnu/drivers/block/virtio_blk.c
--- linux-libre-3.1-gnu/drivers/block/virtio_blk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/virtio_blk.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,15 +3,19 @@
 #include <linux/slab.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/module.h>
 #include <linux/virtio.h>
 #include <linux/virtio_blk.h>
 #include <linux/scatterlist.h>
 #include <linux/string_helpers.h>
 #include <scsi/scsi_cmnd.h>
+#include <linux/idr.h>
 
 #define PART_BITS 4
 
-static int major, index;
+static int major;
+static DEFINE_IDA(vd_index_ida);
+
 struct workqueue_struct *virtblk_wq;
 
 struct virtio_blk
@@ -35,6 +39,9 @@
 	/* What host tells us, plus 2 for header & tailer. */
 	unsigned int sg_elems;
 
+	/* Ida index - used to track minor number allocations. */
+	int index;
+
 	/* Scatterlist: can be too big for stack. */
 	struct scatterlist sg[/*sg_elems*/];
 };
@@ -276,6 +283,11 @@
 	return index << PART_BITS;
 }
 
+static int minor_to_index(int minor)
+{
+	return minor >> PART_BITS;
+}
+
 static ssize_t virtblk_serial_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
@@ -341,14 +353,17 @@
 {
 	struct virtio_blk *vblk;
 	struct request_queue *q;
-	int err;
+	int err, index;
 	u64 cap;
 	u32 v, blk_size, sg_elems, opt_io_size;
 	u16 min_io_size;
 	u8 physical_block_exp, alignment_offset;
 
-	if (index_to_minor(index) >= 1 << MINORBITS)
-		return -ENOSPC;
+	err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS),
+			     GFP_KERNEL);
+	if (err < 0)
+		goto out;
+	index = err;
 
 	/* We need to know how many segments before we allocate. */
 	err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX,
@@ -365,7 +380,7 @@
 				    sizeof(vblk->sg[0]) * sg_elems, GFP_KERNEL);
 	if (!vblk) {
 		err = -ENOMEM;
-		goto out;
+		goto out_free_index;
 	}
 
 	INIT_LIST_HEAD(&vblk->reqs);
@@ -421,7 +436,7 @@
 	vblk->disk->private_data = vblk;
 	vblk->disk->fops = &virtblk_fops;
 	vblk->disk->driverfs_dev = &vdev->dev;
-	index++;
+	vblk->index = index;
 
 	/* configure queue flush support */
 	if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH))
@@ -516,6 +531,8 @@
 	vdev->config->del_vqs(vdev);
 out_free_vblk:
 	kfree(vblk);
+out_free_index:
+	ida_simple_remove(&vd_index_ida, index);
 out:
 	return err;
 }
@@ -523,6 +540,7 @@
 static void __devexit virtblk_remove(struct virtio_device *vdev)
 {
 	struct virtio_blk *vblk = vdev->priv;
+	int index = vblk->index;
 
 	flush_work(&vblk->config_work);
 
@@ -538,6 +556,7 @@
 	mempool_destroy(vblk->pool);
 	vdev->config->del_vqs(vdev);
 	kfree(vblk);
+	ida_simple_remove(&vd_index_ida, index);
 }
 
 static const struct virtio_device_id id_table[] = {
diff -druN linux-libre-3.1-gnu/drivers/block/xen-blkback/blkback.c linux-libre-3.2-gnu/drivers/block/xen-blkback/blkback.c
--- linux-libre-3.1-gnu/drivers/block/xen-blkback/blkback.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/xen-blkback/blkback.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,9 @@
 #include <linux/list.h>
 #include <linux/delay.h>
 #include <linux/freezer.h>
+#include <linux/loop.h>
+#include <linux/falloc.h>
+#include <linux/fs.h>
 
 #include <xen/events.h>
 #include <xen/page.h>
@@ -258,13 +261,16 @@
 
 static void print_stats(struct xen_blkif *blkif)
 {
-	pr_info("xen-blkback (%s): oo %3d  |  rd %4d  |  wr %4d  |  f %4d\n",
+	pr_info("xen-blkback (%s): oo %3d  |  rd %4d  |  wr %4d  |  f %4d"
+		 "  |  ds %4d\n",
 		 current->comm, blkif->st_oo_req,
-		 blkif->st_rd_req, blkif->st_wr_req, blkif->st_f_req);
+		 blkif->st_rd_req, blkif->st_wr_req,
+		 blkif->st_f_req, blkif->st_ds_req);
 	blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000);
 	blkif->st_rd_req = 0;
 	blkif->st_wr_req = 0;
 	blkif->st_oo_req = 0;
+	blkif->st_ds_req = 0;
 }
 
 int xen_blkif_schedule(void *arg)
@@ -396,7 +402,7 @@
 			continue;
 
 		ret = m2p_add_override(PFN_DOWN(map[i].dev_bus_addr),
-			blkbk->pending_page(pending_req, i), false);
+			blkbk->pending_page(pending_req, i), NULL);
 		if (ret) {
 			pr_alert(DRV_PFX "Failed to install M2P override for %lx (ret: %d)\n",
 				 (unsigned long)map[i].dev_bus_addr, ret);
@@ -410,6 +416,59 @@
 	return ret;
 }
 
+static void xen_blk_discard(struct xen_blkif *blkif, struct blkif_request *req)
+{
+	int err = 0;
+	int status = BLKIF_RSP_OKAY;
+	struct block_device *bdev = blkif->vbd.bdev;
+
+	if (blkif->blk_backend_type == BLKIF_BACKEND_PHY)
+		/* just forward the discard request */
+		err = blkdev_issue_discard(bdev,
+				req->u.discard.sector_number,
+				req->u.discard.nr_sectors,
+				GFP_KERNEL, 0);
+	else if (blkif->blk_backend_type == BLKIF_BACKEND_FILE) {
+		/* punch a hole in the backing file */
+		struct loop_device *lo = bdev->bd_disk->private_data;
+		struct file *file = lo->lo_backing_file;
+
+		if (file->f_op->fallocate)
+			err = file->f_op->fallocate(file,
+				FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
+				req->u.discard.sector_number << 9,
+				req->u.discard.nr_sectors << 9);
+		else
+			err = -EOPNOTSUPP;
+	} else
+		err = -EOPNOTSUPP;
+
+	if (err == -EOPNOTSUPP) {
+		pr_debug(DRV_PFX "discard op failed, not supported\n");
+		status = BLKIF_RSP_EOPNOTSUPP;
+	} else if (err)
+		status = BLKIF_RSP_ERROR;
+
+	make_response(blkif, req->id, req->operation, status);
+}
+
+static void xen_blk_drain_io(struct xen_blkif *blkif)
+{
+	atomic_set(&blkif->drain, 1);
+	do {
+		/* The initial value is one, and one refcnt taken at the
+		 * start of the xen_blkif_schedule thread. */
+		if (atomic_read(&blkif->refcnt) <= 2)
+			break;
+		wait_for_completion_interruptible_timeout(
+				&blkif->drain_complete, HZ);
+
+		if (!atomic_read(&blkif->drain))
+			break;
+	} while (!kthread_should_stop());
+	atomic_set(&blkif->drain, 0);
+}
+
 /*
  * Completion callback on the bio's. Called as bh->b_end_io()
  */
@@ -422,6 +481,11 @@
 		pr_debug(DRV_PFX "flush diskcache op failed, not supported\n");
 		xen_blkbk_flush_diskcache(XBT_NIL, pending_req->blkif->be, 0);
 		pending_req->status = BLKIF_RSP_EOPNOTSUPP;
+	} else if ((pending_req->operation == BLKIF_OP_WRITE_BARRIER) &&
+		    (error == -EOPNOTSUPP)) {
+		pr_debug(DRV_PFX "write barrier op failed, not supported\n");
+		xen_blkbk_barrier(XBT_NIL, pending_req->blkif->be, 0);
+		pending_req->status = BLKIF_RSP_EOPNOTSUPP;
 	} else if (error) {
 		pr_debug(DRV_PFX "Buffer not up-to-date at end of operation,"
 			 " error=%d\n", error);
@@ -438,6 +502,10 @@
 		make_response(pending_req->blkif, pending_req->id,
 			      pending_req->operation, pending_req->status);
 		xen_blkif_put(pending_req->blkif);
+		if (atomic_read(&pending_req->blkif->refcnt) <= 2) {
+			if (atomic_read(&pending_req->blkif->drain))
+				complete(&pending_req->blkif->drain_complete);
+		}
 		free_req(pending_req);
 	}
 }
@@ -532,7 +600,6 @@
 
 	return more_to_do;
 }
-
 /*
  * Transmutation of the 'struct blkif_request' to a proper 'struct bio'
  * and call the 'submit_bio' to pass it to the underlying storage.
@@ -549,6 +616,7 @@
 	int i, nbio = 0;
 	int operation;
 	struct blk_plug plug;
+	bool drain = false;
 
 	switch (req->operation) {
 	case BLKIF_OP_READ:
@@ -559,11 +627,16 @@
 		blkif->st_wr_req++;
 		operation = WRITE_ODIRECT;
 		break;
+	case BLKIF_OP_WRITE_BARRIER:
+		drain = true;
 	case BLKIF_OP_FLUSH_DISKCACHE:
 		blkif->st_f_req++;
 		operation = WRITE_FLUSH;
 		break;
-	case BLKIF_OP_WRITE_BARRIER:
+	case BLKIF_OP_DISCARD:
+		blkif->st_ds_req++;
+		operation = REQ_DISCARD;
+		break;
 	default:
 		operation = 0; /* make gcc happy */
 		goto fail_response;
@@ -572,7 +645,8 @@
 
 	/* Check that the number of segments is sane. */
 	nseg = req->nr_segments;
-	if (unlikely(nseg == 0 && operation != WRITE_FLUSH) ||
+	if (unlikely(nseg == 0 && operation != WRITE_FLUSH &&
+				operation != REQ_DISCARD) ||
 	    unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
 		pr_debug(DRV_PFX "Bad number of segments in request (%d)\n",
 			 nseg);
@@ -621,16 +695,25 @@
 		}
 	}
 
+	/* Wait on all outstanding I/O's and once that has been completed
+	 * issue the WRITE_FLUSH.
+	 */
+	if (drain)
+		xen_blk_drain_io(pending_req->blkif);
+
 	/*
 	 * If we have failed at this point, we need to undo the M2P override,
 	 * set gnttab_set_unmap_op on all of the grant references and perform
 	 * the hypercall to unmap the grants - that is all done in
 	 * xen_blkbk_unmap.
 	 */
-	if (xen_blkbk_map(req, pending_req, seg))
+	if (operation != REQ_DISCARD && xen_blkbk_map(req, pending_req, seg))
 		goto fail_flush;
 
-	/* This corresponding xen_blkif_put is done in __end_block_io_op */
+	/*
+	 * This corresponding xen_blkif_put is done in __end_block_io_op, or
+	 * below (in "!bio") if we are handling a BLKIF_OP_DISCARD.
+	 */
 	xen_blkif_get(blkif);
 
 	for (i = 0; i < nseg; i++) {
@@ -654,18 +737,25 @@
 		preq.sector_number += seg[i].nsec;
 	}
 
-	/* This will be hit if the operation was a flush. */
+	/* This will be hit if the operation was a flush or discard. */
 	if (!bio) {
-		BUG_ON(operation != WRITE_FLUSH);
+		BUG_ON(operation != WRITE_FLUSH && operation != REQ_DISCARD);
 
-		bio = bio_alloc(GFP_KERNEL, 0);
-		if (unlikely(bio == NULL))
-			goto fail_put_bio;
+		if (operation == WRITE_FLUSH) {
+			bio = bio_alloc(GFP_KERNEL, 0);
+			if (unlikely(bio == NULL))
+				goto fail_put_bio;
 
-		biolist[nbio++] = bio;
-		bio->bi_bdev    = preq.bdev;
-		bio->bi_private = pending_req;
-		bio->bi_end_io  = end_block_io_op;
+			biolist[nbio++] = bio;
+			bio->bi_bdev    = preq.bdev;
+			bio->bi_private = pending_req;
+			bio->bi_end_io  = end_block_io_op;
+		} else if (operation == REQ_DISCARD) {
+			xen_blk_discard(blkif, req);
+			xen_blkif_put(blkif);
+			free_req(pending_req);
+			return 0;
+		}
 	}
 
 	/*
@@ -685,7 +775,7 @@
 
 	if (operation == READ)
 		blkif->st_rd_sect += preq.nr_sects;
-	else if (operation == WRITE || operation == WRITE_FLUSH)
+	else if (operation & WRITE)
 		blkif->st_wr_sect += preq.nr_sects;
 
 	return 0;
@@ -765,9 +855,9 @@
 
 	mmap_pages = xen_blkif_reqs * BLKIF_MAX_SEGMENTS_PER_REQUEST;
 
-	blkbk->pending_reqs          = kmalloc(sizeof(blkbk->pending_reqs[0]) *
+	blkbk->pending_reqs          = kzalloc(sizeof(blkbk->pending_reqs[0]) *
 					xen_blkif_reqs, GFP_KERNEL);
-	blkbk->pending_grant_handles = kzalloc(sizeof(blkbk->pending_grant_handles[0]) *
+	blkbk->pending_grant_handles = kmalloc(sizeof(blkbk->pending_grant_handles[0]) *
 					mmap_pages, GFP_KERNEL);
 	blkbk->pending_pages         = kzalloc(sizeof(blkbk->pending_pages[0]) *
 					mmap_pages, GFP_KERNEL);
@@ -790,8 +880,6 @@
 	if (rc)
 		goto failed_init;
 
-	memset(blkbk->pending_reqs, 0, sizeof(blkbk->pending_reqs));
-
 	INIT_LIST_HEAD(&blkbk->pending_free);
 	spin_lock_init(&blkbk->pending_free_lock);
 	init_waitqueue_head(&blkbk->pending_free_wq);
diff -druN linux-libre-3.1-gnu/drivers/block/xen-blkback/common.h linux-libre-3.2-gnu/drivers/block/xen-blkback/common.h
--- linux-libre-3.1-gnu/drivers/block/xen-blkback/common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/xen-blkback/common.h	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,6 @@
 #ifndef __XEN_BLKIF__BACKEND__COMMON_H__
 #define __XEN_BLKIF__BACKEND__COMMON_H__
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
@@ -63,13 +62,26 @@
 
 /* i386 protocol version */
 #pragma pack(push, 4)
+
+struct blkif_x86_32_request_rw {
+	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+};
+
+struct blkif_x86_32_request_discard {
+	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+	uint64_t nr_sectors;
+};
+
 struct blkif_x86_32_request {
 	uint8_t        operation;    /* BLKIF_OP_???                         */
 	uint8_t        nr_segments;  /* number of segments                   */
 	blkif_vdev_t   handle;       /* only for read/write requests         */
 	uint64_t       id;           /* private guest value, echoed in resp  */
-	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
-	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+	union {
+		struct blkif_x86_32_request_rw rw;
+		struct blkif_x86_32_request_discard discard;
+	} u;
 };
 struct blkif_x86_32_response {
 	uint64_t        id;              /* copied from request */
@@ -79,13 +91,26 @@
 #pragma pack(pop)
 
 /* x86_64 protocol version */
+
+struct blkif_x86_64_request_rw {
+	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+};
+
+struct blkif_x86_64_request_discard {
+	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+	uint64_t nr_sectors;
+};
+
 struct blkif_x86_64_request {
 	uint8_t        operation;    /* BLKIF_OP_???                         */
 	uint8_t        nr_segments;  /* number of segments                   */
 	blkif_vdev_t   handle;       /* only for read/write requests         */
 	uint64_t       __attribute__((__aligned__(8))) id;
-	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
-	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+	union {
+		struct blkif_x86_64_request_rw rw;
+		struct blkif_x86_64_request_discard discard;
+	} u;
 };
 struct blkif_x86_64_response {
 	uint64_t       __attribute__((__aligned__(8))) id;
@@ -113,6 +138,11 @@
 	BLKIF_PROTOCOL_X86_64 = 3,
 };
 
+enum blkif_backend_type {
+	BLKIF_BACKEND_PHY  = 1,
+	BLKIF_BACKEND_FILE = 2,
+};
+
 struct xen_vbd {
 	/* What the domain refers to this vbd as. */
 	blkif_vdev_t		handle;
@@ -138,8 +168,9 @@
 	unsigned int		irq;
 	/* Comms information. */
 	enum blkif_protocol	blk_protocol;
+	enum blkif_backend_type blk_backend_type;
 	union blkif_back_rings	blk_rings;
-	struct vm_struct	*blk_ring_area;
+	void			*blk_ring;
 	/* The VBD attached to this interface. */
 	struct xen_vbd		vbd;
 	/* Back pointer to the backend_info. */
@@ -149,6 +180,9 @@
 	atomic_t		refcnt;
 
 	wait_queue_head_t	wq;
+	/* for barrier (drain) requests */
+	struct completion	drain_complete;
+	atomic_t		drain;
 	/* One thread per one blkif. */
 	struct task_struct	*xenblkd;
 	unsigned int		waiting_reqs;
@@ -159,13 +193,11 @@
 	int			st_wr_req;
 	int			st_oo_req;
 	int			st_f_req;
+	int			st_ds_req;
 	int			st_rd_sect;
 	int			st_wr_sect;
 
 	wait_queue_head_t	waiting_to_free;
-
-	grant_handle_t		shmem_handle;
-	grant_ref_t		shmem_ref;
 };
 
 
@@ -182,7 +214,7 @@
 
 struct phys_req {
 	unsigned short		dev;
-	unsigned short		nr_sects;
+	blkif_sector_t		nr_sects;
 	struct block_device	*bdev;
 	blkif_sector_t		sector_number;
 };
@@ -196,6 +228,8 @@
 int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt,
 			      struct backend_info *be, int state);
 
+int xen_blkbk_barrier(struct xenbus_transaction xbt,
+		      struct backend_info *be, int state);
 struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be);
 
 static inline void blkif_get_x86_32_req(struct blkif_request *dst,
@@ -206,12 +240,25 @@
 	dst->nr_segments = src->nr_segments;
 	dst->handle = src->handle;
 	dst->id = src->id;
-	dst->u.rw.sector_number = src->sector_number;
-	barrier();
-	if (n > dst->nr_segments)
-		n = dst->nr_segments;
-	for (i = 0; i < n; i++)
-		dst->u.rw.seg[i] = src->seg[i];
+	switch (src->operation) {
+	case BLKIF_OP_READ:
+	case BLKIF_OP_WRITE:
+	case BLKIF_OP_WRITE_BARRIER:
+	case BLKIF_OP_FLUSH_DISKCACHE:
+		dst->u.rw.sector_number = src->u.rw.sector_number;
+		barrier();
+		if (n > dst->nr_segments)
+			n = dst->nr_segments;
+		for (i = 0; i < n; i++)
+			dst->u.rw.seg[i] = src->u.rw.seg[i];
+		break;
+	case BLKIF_OP_DISCARD:
+		dst->u.discard.sector_number = src->u.discard.sector_number;
+		dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
+		break;
+	default:
+		break;
+	}
 }
 
 static inline void blkif_get_x86_64_req(struct blkif_request *dst,
@@ -222,12 +269,25 @@
 	dst->nr_segments = src->nr_segments;
 	dst->handle = src->handle;
 	dst->id = src->id;
-	dst->u.rw.sector_number = src->sector_number;
-	barrier();
-	if (n > dst->nr_segments)
-		n = dst->nr_segments;
-	for (i = 0; i < n; i++)
-		dst->u.rw.seg[i] = src->seg[i];
+	switch (src->operation) {
+	case BLKIF_OP_READ:
+	case BLKIF_OP_WRITE:
+	case BLKIF_OP_WRITE_BARRIER:
+	case BLKIF_OP_FLUSH_DISKCACHE:
+		dst->u.rw.sector_number = src->u.rw.sector_number;
+		barrier();
+		if (n > dst->nr_segments)
+			n = dst->nr_segments;
+		for (i = 0; i < n; i++)
+			dst->u.rw.seg[i] = src->u.rw.seg[i];
+		break;
+	case BLKIF_OP_DISCARD:
+		dst->u.discard.sector_number = src->u.discard.sector_number;
+		dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
+		break;
+	default:
+		break;
+	}
 }
 
 #endif /* __XEN_BLKIF__BACKEND__COMMON_H__ */
diff -druN linux-libre-3.1-gnu/drivers/block/xen-blkback/xenbus.c linux-libre-3.2-gnu/drivers/block/xen-blkback/xenbus.c
--- linux-libre-3.1-gnu/drivers/block/xen-blkback/xenbus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/xen-blkback/xenbus.c	2012-01-04 18:55:44.000000000 -0500
@@ -114,44 +114,14 @@
 	spin_lock_init(&blkif->blk_ring_lock);
 	atomic_set(&blkif->refcnt, 1);
 	init_waitqueue_head(&blkif->wq);
+	init_completion(&blkif->drain_complete);
+	atomic_set(&blkif->drain, 0);
 	blkif->st_print = jiffies;
 	init_waitqueue_head(&blkif->waiting_to_free);
 
 	return blkif;
 }
 
-static int map_frontend_page(struct xen_blkif *blkif, unsigned long shared_page)
-{
-	struct gnttab_map_grant_ref op;
-
-	gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr,
-			  GNTMAP_host_map, shared_page, blkif->domid);
-
-	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
-		BUG();
-
-	if (op.status) {
-		DPRINTK("Grant table operation failure !\n");
-		return op.status;
-	}
-
-	blkif->shmem_ref = shared_page;
-	blkif->shmem_handle = op.handle;
-
-	return 0;
-}
-
-static void unmap_frontend_page(struct xen_blkif *blkif)
-{
-	struct gnttab_unmap_grant_ref op;
-
-	gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr,
-			    GNTMAP_host_map, blkif->shmem_handle);
-
-	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
-		BUG();
-}
-
 static int xen_blkif_map(struct xen_blkif *blkif, unsigned long shared_page,
 			 unsigned int evtchn)
 {
@@ -161,35 +131,29 @@
 	if (blkif->irq)
 		return 0;
 
-	blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE);
-	if (!blkif->blk_ring_area)
-		return -ENOMEM;
-
-	err = map_frontend_page(blkif, shared_page);
-	if (err) {
-		free_vm_area(blkif->blk_ring_area);
+	err = xenbus_map_ring_valloc(blkif->be->dev, shared_page, &blkif->blk_ring);
+	if (err < 0)
 		return err;
-	}
 
 	switch (blkif->blk_protocol) {
 	case BLKIF_PROTOCOL_NATIVE:
 	{
 		struct blkif_sring *sring;
-		sring = (struct blkif_sring *)blkif->blk_ring_area->addr;
+		sring = (struct blkif_sring *)blkif->blk_ring;
 		BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE);
 		break;
 	}
 	case BLKIF_PROTOCOL_X86_32:
 	{
 		struct blkif_x86_32_sring *sring_x86_32;
-		sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring_area->addr;
+		sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring;
 		BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE);
 		break;
 	}
 	case BLKIF_PROTOCOL_X86_64:
 	{
 		struct blkif_x86_64_sring *sring_x86_64;
-		sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring_area->addr;
+		sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring;
 		BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE);
 		break;
 	}
@@ -201,8 +165,7 @@
 						    xen_blkif_be_int, 0,
 						    "blkif-backend", blkif);
 	if (err < 0) {
-		unmap_frontend_page(blkif);
-		free_vm_area(blkif->blk_ring_area);
+		xenbus_unmap_ring_vfree(blkif->be->dev, blkif->blk_ring);
 		blkif->blk_rings.common.sring = NULL;
 		return err;
 	}
@@ -228,8 +191,7 @@
 	}
 
 	if (blkif->blk_rings.common.sring) {
-		unmap_frontend_page(blkif);
-		free_vm_area(blkif->blk_ring_area);
+		xenbus_unmap_ring_vfree(blkif->be->dev, blkif->blk_ring);
 		blkif->blk_rings.common.sring = NULL;
 	}
 }
@@ -272,6 +234,7 @@
 VBD_SHOW(rd_req,  "%d\n", be->blkif->st_rd_req);
 VBD_SHOW(wr_req,  "%d\n", be->blkif->st_wr_req);
 VBD_SHOW(f_req,  "%d\n", be->blkif->st_f_req);
+VBD_SHOW(ds_req,  "%d\n", be->blkif->st_ds_req);
 VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect);
 VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect);
 
@@ -280,6 +243,7 @@
 	&dev_attr_rd_req.attr,
 	&dev_attr_wr_req.attr,
 	&dev_attr_f_req.attr,
+	&dev_attr_ds_req.attr,
 	&dev_attr_rd_sect.attr,
 	&dev_attr_wr_sect.attr,
 	NULL
@@ -419,6 +383,73 @@
 	return err;
 }
 
+int xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info *be)
+{
+	struct xenbus_device *dev = be->dev;
+	struct xen_blkif *blkif = be->blkif;
+	char *type;
+	int err;
+	int state = 0;
+
+	type = xenbus_read(XBT_NIL, dev->nodename, "type", NULL);
+	if (!IS_ERR(type)) {
+		if (strncmp(type, "file", 4) == 0) {
+			state = 1;
+			blkif->blk_backend_type = BLKIF_BACKEND_FILE;
+		}
+		if (strncmp(type, "phy", 3) == 0) {
+			struct block_device *bdev = be->blkif->vbd.bdev;
+			struct request_queue *q = bdev_get_queue(bdev);
+			if (blk_queue_discard(q)) {
+				err = xenbus_printf(xbt, dev->nodename,
+					"discard-granularity", "%u",
+					q->limits.discard_granularity);
+				if (err) {
+					xenbus_dev_fatal(dev, err,
+						"writing discard-granularity");
+					goto kfree;
+				}
+				err = xenbus_printf(xbt, dev->nodename,
+					"discard-alignment", "%u",
+					q->limits.discard_alignment);
+				if (err) {
+					xenbus_dev_fatal(dev, err,
+						"writing discard-alignment");
+					goto kfree;
+				}
+				state = 1;
+				blkif->blk_backend_type = BLKIF_BACKEND_PHY;
+			}
+		}
+	} else {
+		err = PTR_ERR(type);
+		xenbus_dev_fatal(dev, err, "reading type");
+		goto out;
+	}
+
+	err = xenbus_printf(xbt, dev->nodename, "feature-discard",
+			    "%d", state);
+	if (err)
+		xenbus_dev_fatal(dev, err, "writing feature-discard");
+kfree:
+	kfree(type);
+out:
+	return err;
+}
+int xen_blkbk_barrier(struct xenbus_transaction xbt,
+		      struct backend_info *be, int state)
+{
+	struct xenbus_device *dev = be->dev;
+	int err;
+
+	err = xenbus_printf(xbt, dev->nodename, "feature-barrier",
+			    "%d", state);
+	if (err)
+		xenbus_dev_fatal(dev, err, "writing feature-barrier");
+
+	return err;
+}
+
 /*
  * Entry point to this code when a new device is created.  Allocate the basic
  * structures, and watch the store waiting for the hotplug scripts to tell us
@@ -650,6 +681,11 @@
 	if (err)
 		goto abort;
 
+	err = xen_blkbk_discard(xbt, be);
+
+	/* If we can't advertise it is OK. */
+	err = xen_blkbk_barrier(xbt, be, be->blkif->vbd.flush_support);
+
 	err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu",
 			    (unsigned long long)vbd_sz(&be->blkif->vbd));
 	if (err) {
diff -druN linux-libre-3.1-gnu/drivers/block/xen-blkfront.c linux-libre-3.2-gnu/drivers/block/xen-blkfront.c
--- linux-libre-3.1-gnu/drivers/block/xen-blkfront.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/block/xen-blkfront.c	2012-01-04 18:55:44.000000000 -0500
@@ -98,6 +98,9 @@
 	unsigned long shadow_free;
 	unsigned int feature_flush;
 	unsigned int flush_op;
+	unsigned int feature_discard;
+	unsigned int discard_granularity;
+	unsigned int discard_alignment;
 	int is_ready;
 };
 
@@ -302,29 +305,36 @@
 		ring_req->operation = info->flush_op;
 	}
 
-	ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
-	BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
+	if (unlikely(req->cmd_flags & REQ_DISCARD)) {
+		/* id, sector_number and handle are set above. */
+		ring_req->operation = BLKIF_OP_DISCARD;
+		ring_req->nr_segments = 0;
+		ring_req->u.discard.nr_sectors = blk_rq_sectors(req);
+	} else {
+		ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
+		BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
 
-	for_each_sg(info->sg, sg, ring_req->nr_segments, i) {
-		buffer_mfn = pfn_to_mfn(page_to_pfn(sg_page(sg)));
-		fsect = sg->offset >> 9;
-		lsect = fsect + (sg->length >> 9) - 1;
-		/* install a grant reference. */
-		ref = gnttab_claim_grant_reference(&gref_head);
-		BUG_ON(ref == -ENOSPC);
+		for_each_sg(info->sg, sg, ring_req->nr_segments, i) {
+			buffer_mfn = pfn_to_mfn(page_to_pfn(sg_page(sg)));
+			fsect = sg->offset >> 9;
+			lsect = fsect + (sg->length >> 9) - 1;
+			/* install a grant reference. */
+			ref = gnttab_claim_grant_reference(&gref_head);
+			BUG_ON(ref == -ENOSPC);
 
-		gnttab_grant_foreign_access_ref(
-				ref,
-				info->xbdev->otherend_id,
-				buffer_mfn,
-				rq_data_dir(req) );
+			gnttab_grant_foreign_access_ref(
+					ref,
+					info->xbdev->otherend_id,
+					buffer_mfn,
+					rq_data_dir(req));
 
-		info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn);
-		ring_req->u.rw.seg[i] =
-				(struct blkif_request_segment) {
-					.gref       = ref,
-					.first_sect = fsect,
-					.last_sect  = lsect };
+			info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn);
+			ring_req->u.rw.seg[i] =
+					(struct blkif_request_segment) {
+						.gref       = ref,
+						.first_sect = fsect,
+						.last_sect  = lsect };
+		}
 	}
 
 	info->ring.req_prod_pvt++;
@@ -370,7 +380,9 @@
 
 		blk_start_request(req);
 
-		if (req->cmd_type != REQ_TYPE_FS) {
+		if ((req->cmd_type != REQ_TYPE_FS) ||
+		    ((req->cmd_flags & (REQ_FLUSH | REQ_FUA)) &&
+		    !info->flush_op)) {
 			__blk_end_request_all(req, -EIO);
 			continue;
 		}
@@ -399,6 +411,7 @@
 static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
 {
 	struct request_queue *rq;
+	struct blkfront_info *info = gd->private_data;
 
 	rq = blk_init_queue(do_blkif_request, &blkif_io_lock);
 	if (rq == NULL)
@@ -406,6 +419,13 @@
 
 	queue_flag_set_unlocked(QUEUE_FLAG_VIRT, rq);
 
+	if (info->feature_discard) {
+		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, rq);
+		blk_queue_max_discard_sectors(rq, get_capacity(gd));
+		rq->limits.discard_granularity = info->discard_granularity;
+		rq->limits.discard_alignment = info->discard_alignment;
+	}
+
 	/* Hard sector size and max sectors impersonate the equiv. hardware. */
 	blk_queue_logical_block_size(rq, sector_size);
 	blk_queue_max_hw_sectors(rq, 512);
@@ -722,6 +742,17 @@
 
 		error = (bret->status == BLKIF_RSP_OKAY) ? 0 : -EIO;
 		switch (bret->operation) {
+		case BLKIF_OP_DISCARD:
+			if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
+				struct request_queue *rq = info->rq;
+				printk(KERN_WARNING "blkfront: %s: discard op failed\n",
+					   info->gd->disk_name);
+				error = -EOPNOTSUPP;
+				info->feature_discard = 0;
+				queue_flag_clear(QUEUE_FLAG_DISCARD, rq);
+			}
+			__blk_end_request_all(req, error);
+			break;
 		case BLKIF_OP_FLUSH_DISKCACHE:
 		case BLKIF_OP_WRITE_BARRIER:
 			if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
@@ -1098,6 +1129,33 @@
 	bdput(bdev);
 }
 
+static void blkfront_setup_discard(struct blkfront_info *info)
+{
+	int err;
+	char *type;
+	unsigned int discard_granularity;
+	unsigned int discard_alignment;
+
+	type = xenbus_read(XBT_NIL, info->xbdev->otherend, "type", NULL);
+	if (IS_ERR(type))
+		return;
+
+	if (strncmp(type, "phy", 3) == 0) {
+		err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+			"discard-granularity", "%u", &discard_granularity,
+			"discard-alignment", "%u", &discard_alignment,
+			NULL);
+		if (!err) {
+			info->feature_discard = 1;
+			info->discard_granularity = discard_granularity;
+			info->discard_alignment = discard_alignment;
+		}
+	} else if (strncmp(type, "file", 4) == 0)
+		info->feature_discard = 1;
+
+	kfree(type);
+}
+
 /*
  * Invoked when the backend is finally 'ready' (and has told produced
  * the details about the physical device - #sectors, size, etc).
@@ -1108,7 +1166,7 @@
 	unsigned long sector_size;
 	unsigned int binfo;
 	int err;
-	int barrier, flush;
+	int barrier, flush, discard;
 
 	switch (info->connected) {
 	case BLKIF_STATE_CONNECTED:
@@ -1178,7 +1236,14 @@
 		info->feature_flush = REQ_FLUSH;
 		info->flush_op = BLKIF_OP_FLUSH_DISKCACHE;
 	}
-		
+
+	err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+			    "feature-discard", "%d", &discard,
+			    NULL);
+
+	if (!err && discard)
+		blkfront_setup_discard(info);
+
 	err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size);
 	if (err) {
 		xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s",
@@ -1385,6 +1450,8 @@
 
 static int __init xlblk_init(void)
 {
+	int ret;
+
 	if (!xen_domain())
 		return -ENODEV;
 
@@ -1394,7 +1461,13 @@
 		return -ENODEV;
 	}
 
-	return xenbus_register_frontend(&blkfront);
+	ret = xenbus_register_frontend(&blkfront);
+	if (ret) {
+		unregister_blkdev(XENVBD_MAJOR, DEV_NAME);
+		return ret;
+	}
+
+	return 0;
 }
 module_init(xlblk_init);
 
diff -druN linux-libre-3.1-gnu/drivers/bluetooth/ath3k.c linux-libre-3.2-gnu/drivers/bluetooth/ath3k.c
--- linux-libre-3.1-gnu/drivers/bluetooth/ath3k.c	2012-03-19 21:59:41.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bluetooth/ath3k.c	2012-03-19 22:03:35.000000000 -0400
@@ -105,7 +105,7 @@
 
 	pipe = usb_sndctrlpipe(udev, 0);
 
-	send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
+	send_buf = kmalloc(BULK_SIZE, GFP_KERNEL);
 	if (!send_buf) {
 		BT_ERR("Can't allocate memory chunk for firmware");
 		return -ENOMEM;
@@ -176,7 +176,7 @@
 
 	count = firmware->size;
 
-	send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
+	send_buf = kmalloc(BULK_SIZE, GFP_KERNEL);
 	if (!send_buf) {
 		BT_ERR("Can't allocate memory chunk for firmware");
 		return -ENOMEM;
diff -druN linux-libre-3.1-gnu/drivers/bluetooth/bcm203x.c linux-libre-3.2-gnu/drivers/bluetooth/bcm203x.c
--- linux-libre-3.1-gnu/drivers/bluetooth/bcm203x.c	2012-03-19 21:59:48.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bluetooth/bcm203x.c	2012-03-19 22:03:42.000000000 -0400
@@ -24,6 +24,7 @@
 
 #include <linux/module.h>
 
+#include <linux/atomic.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -65,6 +66,7 @@
 	unsigned long		state;
 
 	struct work_struct	work;
+	atomic_t		shutdown;
 
 	struct urb		*urb;
 	unsigned char		*buffer;
@@ -97,6 +99,7 @@
 
 		data->state = BCM203X_SELECT_MEMORY;
 
+		/* use workqueue to have a small delay */
 		schedule_work(&data->work);
 		break;
 
@@ -155,7 +158,10 @@
 	struct bcm203x_data *data =
 		container_of(work, struct bcm203x_data, work);
 
-	if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0)
+	if (atomic_read(&data->shutdown))
+		return;
+
+	if (usb_submit_urb(data->urb, GFP_KERNEL) < 0)
 		BT_ERR("Can't submit URB");
 }
 
@@ -243,6 +249,7 @@
 
 	usb_set_intfdata(intf, data);
 
+	/* use workqueue to have a small delay */
 	schedule_work(&data->work);
 
 	return 0;
@@ -254,6 +261,9 @@
 
 	BT_DBG("intf %p", intf);
 
+	atomic_inc(&data->shutdown);
+	cancel_work_sync(&data->work);
+
 	usb_kill_urb(data->urb);
 
 	usb_set_intfdata(intf, NULL);
diff -druN linux-libre-3.1-gnu/drivers/bluetooth/bfusb.c linux-libre-3.2-gnu/drivers/bluetooth/bfusb.c
--- linux-libre-3.1-gnu/drivers/bluetooth/bfusb.c	2012-03-19 21:59:55.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bluetooth/bfusb.c	2012-03-19 22:03:49.000000000 -0400
@@ -568,22 +568,23 @@
 
 	BT_INFO("BlueFRITZ! USB loading firmware");
 
+	buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_KERNEL);
+	if (!buf) {
+		BT_ERR("Can't allocate memory chunk for firmware");
+		return -ENOMEM;
+	}
+
 	pipe = usb_sndctrlpipe(data->udev, 0);
 
 	if (usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
 				0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) {
 		BT_ERR("Can't change to loading configuration");
+		kfree(buf);
 		return -EBUSY;
 	}
 
 	data->udev->toggle[0] = data->udev->toggle[1] = 0;
 
-	buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_ATOMIC);
-	if (!buf) {
-		BT_ERR("Can't allocate memory chunk for firmware");
-		return -ENOMEM;
-	}
-
 	pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
 
 	while (count) {
diff -druN linux-libre-3.1-gnu/drivers/bluetooth/btmrvl_main.c linux-libre-3.2-gnu/drivers/bluetooth/btmrvl_main.c
--- linux-libre-3.1-gnu/drivers/bluetooth/btmrvl_main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bluetooth/btmrvl_main.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * this warranty disclaimer.
  **/
 
+#include <linux/module.h>
+
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
diff -druN linux-libre-3.1-gnu/drivers/bluetooth/btmrvl_sdio.c linux-libre-3.2-gnu/drivers/bluetooth/btmrvl_sdio.c
--- linux-libre-3.1-gnu/drivers/bluetooth/btmrvl_sdio.c	2012-03-19 22:00:22.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bluetooth/btmrvl_sdio.c	2012-03-19 22:04:07.000000000 -0400
@@ -23,6 +23,7 @@
 
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/sdio_func.h>
+#include <linux/module.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
@@ -64,7 +65,7 @@
 	.io_port_1 = 0x01,
 	.io_port_2 = 0x02,
 };
-static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = {
+static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
 	.cfg = 0x00,
 	.host_int_mask = 0x02,
 	.host_intstatus = 0x03,
@@ -81,7 +82,7 @@
 	.io_port_2 = 0x7a,
 };
 
-static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
+static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
 	.helper		= "/*(DEBLOBBED)*/",
 	.reg		= &btmrvl_reg_8688,
 	.sd_blksz_fw_dl	= 64,
@@ -90,17 +91,27 @@
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
 	.helper		= NULL,
 	.firmware	= "/*(DEBLOBBED)*/",
-	.reg		= &btmrvl_reg_8787,
+	.reg		= &btmrvl_reg_87xx,
+	.sd_blksz_fw_dl	= 256,
+};
+
+static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
+	.helper		= NULL,
+	.firmware	= "/*(DEBLOBBED)*/",
+	.reg		= &btmrvl_reg_87xx,
 	.sd_blksz_fw_dl	= 256,
 };
 
 static const struct sdio_device_id btmrvl_sdio_ids[] = {
 	/* Marvell SD8688 Bluetooth device */
 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
-			.driver_data = (unsigned long) &btmrvl_sdio_sd6888 },
+			.driver_data = (unsigned long) &btmrvl_sdio_sd8688 },
 	/* Marvell SD8787 Bluetooth device */
 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
 			.driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
+	/* Marvell SD8797 Bluetooth device */
+	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
+			.driver_data = (unsigned long) &btmrvl_sdio_sd8797 },
 
 	{ }	/* Terminating entry */
 };
diff -druN linux-libre-3.1-gnu/drivers/bluetooth/btusb.c linux-libre-3.2-gnu/drivers/bluetooth/btusb.c
--- linux-libre-3.1-gnu/drivers/bluetooth/btusb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bluetooth/btusb.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,6 +60,9 @@
 	/* Generic Bluetooth USB device */
 	{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
 
+	/* Broadcom SoftSailing reporting vendor specific */
+	{ USB_DEVICE(0x05ac, 0x21e1) },
+
 	/* Apple MacBookPro 7,1 */
 	{ USB_DEVICE(0x05ac, 0x8213) },
 
@@ -97,6 +100,9 @@
 	/* Canyon CN-BTU1 with HID interfaces */
 	{ USB_DEVICE(0x0c10, 0x0000) },
 
+	/* Broadcom BCM20702A0 */
+	{ USB_DEVICE(0x413c, 0x8197) },
+
 	{ }	/* Terminating entry */
 };
 
@@ -708,8 +714,7 @@
 		break;
 
 	case HCI_ACLDATA_PKT:
-		if (!data->bulk_tx_ep || (hdev->conn_hash.acl_num < 1 &&
-						hdev->conn_hash.le_num < 1))
+		if (!data->bulk_tx_ep)
 			return -ENODEV;
 
 		urb = usb_alloc_urb(0, GFP_ATOMIC);
@@ -772,9 +777,8 @@
 		usb_mark_last_busy(data->udev);
 	}
 
-	usb_free_urb(urb);
-
 done:
+	usb_free_urb(urb);
 	return err;
 }
 
@@ -1116,7 +1120,7 @@
 		return 0;
 
 	spin_lock_irq(&data->txlock);
-	if (!((message.event & PM_EVENT_AUTO) && data->tx_in_flight)) {
+	if (!(PMSG_IS_AUTO(message) && data->tx_in_flight)) {
 		set_bit(BTUSB_SUSPENDING, &data->flags);
 		spin_unlock_irq(&data->txlock);
 	} else {
diff -druN linux-libre-3.1-gnu/drivers/bluetooth/btwilink.c linux-libre-3.2-gnu/drivers/bluetooth/btwilink.c
--- linux-libre-3.1-gnu/drivers/bluetooth/btwilink.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bluetooth/btwilink.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <net/bluetooth/hci.h>
 
 #include <linux/ti_wilink_st.h>
+#include <linux/module.h>
 
 /* Bluetooth Driver Version */
 #define VERSION               "1.0"
diff -druN linux-libre-3.1-gnu/drivers/bluetooth/Kconfig linux-libre-3.2-gnu/drivers/bluetooth/Kconfig
--- linux-libre-3.1-gnu/drivers/bluetooth/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/bluetooth/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -188,7 +188,7 @@
 	  The core driver to support Marvell Bluetooth devices.
 
 	  This driver is required if you want to support
-	  Marvell Bluetooth devices, such as 8688/8787.
+	  Marvell Bluetooth devices, such as 8688/8787/8797.
 
 	  Say Y here to compile Marvell Bluetooth driver
 	  into the kernel or say M to compile it as module.
@@ -201,8 +201,8 @@
 	  The driver for Marvell Bluetooth chipsets with SDIO interface.
 
 	  This driver is required if you want to use Marvell Bluetooth
-	  devices with SDIO interface. Currently SD8688/SD8787 chipsets are
-	  supported.
+	  devices with SDIO interface. Currently SD8688/SD8787/SD8797
+	  chipsets are supported.
 
 	  Say Y here to compile support for Marvell BT-over-SDIO driver
 	  into the kernel or say M to compile it as module.
diff -druN linux-libre-3.1-gnu/drivers/char/agp/backend.c linux-libre-3.2-gnu/drivers/char/agp/backend.c
--- linux-libre-3.1-gnu/drivers/char/agp/backend.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/agp/backend.c	2012-01-04 18:55:44.000000000 -0500
@@ -171,7 +171,7 @@
 	}
 	got_gatt = 1;
 
-	bridge->key_list = vmalloc(PAGE_SIZE * 4);
+	bridge->key_list = vzalloc(PAGE_SIZE * 4);
 	if (bridge->key_list == NULL) {
 		dev_err(&bridge->dev->dev,
 			"can't allocate memory for key lists\n");
@@ -181,7 +181,6 @@
 	got_keylist = 1;
 
 	/* FIXME vmalloc'd memory not guaranteed contiguous */
-	memset(bridge->key_list, 0, PAGE_SIZE * 4);
 
 	if (bridge->driver->configure()) {
 		dev_err(&bridge->dev->dev, "error configuring host chipset\n");
diff -druN linux-libre-3.1-gnu/drivers/char/agp/hp-agp.c linux-libre-3.2-gnu/drivers/char/agp/hp-agp.c
--- linux-libre-3.1-gnu/drivers/char/agp/hp-agp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/agp/hp-agp.c	2012-01-04 18:55:44.000000000 -0500
@@ -336,7 +336,8 @@
 	off_t j, io_pg_start;
 	int io_pg_count;
 
-	if (type != 0 || mem->type != 0) {
+	if (type != mem->type ||
+		agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) {
 		return -EINVAL;
 	}
 
@@ -380,7 +381,8 @@
 	struct _hp_private *hp = &hp_private;
 	int i, io_pg_start, io_pg_count;
 
-	if (type != 0 || mem->type != 0) {
+	if (type != mem->type ||
+		agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) {
 		return -EINVAL;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/char/agp/intel-gtt.c linux-libre-3.2-gnu/drivers/char/agp/intel-gtt.c
--- linux-libre-3.1-gnu/drivers/char/agp/intel-gtt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/agp/intel-gtt.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,10 +30,10 @@
 /*
  * If we have Intel graphics, we're not going to have anything other than
  * an Intel IOMMU. So make the correct use of the PCI DMA API contingent
- * on the Intel IOMMU support (CONFIG_DMAR).
+ * on the Intel IOMMU support (CONFIG_INTEL_IOMMU).
  * Only newer chipsets need to bother with this, of course.
  */
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_INTEL_IOMMU
 #define USE_PCI_DMA_API 1
 #else
 #define USE_PCI_DMA_API 0
@@ -923,6 +923,9 @@
 {
 	int ret = -EINVAL;
 
+	if (intel_private.base.do_idle_maps)
+		return -ENODEV;
+
 	if (intel_private.clear_fake_agp) {
 		int start = intel_private.base.stolen_size / PAGE_SIZE;
 		int end = intel_private.base.gtt_mappable_entries;
@@ -985,6 +988,9 @@
 	if (mem->page_count == 0)
 		return 0;
 
+	if (intel_private.base.do_idle_maps)
+		return -ENODEV;
+
 	intel_gtt_clear_range(pg_start, mem->page_count);
 
 	if (intel_private.base.needs_dmar) {
@@ -1177,6 +1183,26 @@
 {
 }
 
+/* Certain Gen5 chipsets require require idling the GPU before
+ * unmapping anything from the GTT when VT-d is enabled.
+ */
+static inline int needs_idle_maps(void)
+{
+#ifdef CONFIG_INTEL_IOMMU
+	const unsigned short gpu_devid = intel_private.pcidev->device;
+	extern int intel_iommu_gfx_mapped;
+
+	/* Query intel_iommu to see if we need the workaround. Presumably that
+	 * was loaded first.
+	 */
+	if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB ||
+	     gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) &&
+	     intel_iommu_gfx_mapped)
+		return 1;
+#endif
+	return 0;
+}
+
 static int i9xx_setup(void)
 {
 	u32 reg_addr;
@@ -1211,6 +1237,9 @@
 		intel_private.gtt_bus_addr = reg_addr + gtt_offset;
 	}
 
+	if (needs_idle_maps())
+		intel_private.base.do_idle_maps = 1;
+
 	intel_i9xx_setup_flush();
 
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/char/apm-emulation.c linux-libre-3.2-gnu/drivers/char/apm-emulation.c
--- linux-libre-3.1-gnu/drivers/char/apm-emulation.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/apm-emulation.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,10 +40,7 @@
 #define APM_MINOR_DEV	134
 
 /*
- * See Documentation/Config.help for the configuration options.
- *
- * Various options can be changed at boot time as follows:
- * (We allow underscores for compatibility with the modules code)
+ * One option can be changed at boot time as follows:
  *	apm=on/off			enable/disable APM
  */
 
@@ -300,17 +297,13 @@
 			/*
 			 * Wait for the suspend/resume to complete.  If there
 			 * are pending acknowledges, we wait here for them.
+			 * wait_event_freezable() is interruptible and pending
+			 * signal can cause busy looping.  We aren't doing
+			 * anything critical, chill a bit on each iteration.
 			 */
-			freezer_do_not_count();
-
-			wait_event(apm_suspend_waitqueue,
-				   as->suspend_state == SUSPEND_DONE);
-
-			/*
-			 * Since we are waiting until the suspend is done, the
-			 * try_to_freeze() in freezer_count() will not trigger
-			 */
-			freezer_count();
+			while (wait_event_freezable(apm_suspend_waitqueue,
+					as->suspend_state == SUSPEND_DONE))
+				msleep(10);
 			break;
 		case SUSPEND_ACKTO:
 			as->suspend_result = -ETIMEDOUT;
diff -druN linux-libre-3.1-gnu/drivers/char/hw_random/atmel-rng.c linux-libre-3.2-gnu/drivers/char/hw_random/atmel-rng.c
--- linux-libre-3.1-gnu/drivers/char/hw_random/atmel-rng.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/char/hw_random/atmel-rng.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2011 Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/hw_random.h>
+#include <linux/platform_device.h>
+
+#define TRNG_CR		0x00
+#define TRNG_ISR	0x1c
+#define TRNG_ODATA	0x50
+
+#define TRNG_KEY	0x524e4700 /* RNG */
+
+struct atmel_trng {
+	struct clk *clk;
+	void __iomem *base;
+	struct hwrng rng;
+};
+
+static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max,
+			   bool wait)
+{
+	struct atmel_trng *trng = container_of(rng, struct atmel_trng, rng);
+	u32 *data = buf;
+
+	/* data ready? */
+	if (readl(trng->base + TRNG_ODATA) & 1) {
+		*data = readl(trng->base + TRNG_ODATA);
+		return 4;
+	} else
+		return 0;
+}
+
+static int atmel_trng_probe(struct platform_device *pdev)
+{
+	struct atmel_trng *trng;
+	struct resource *res;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL);
+	if (!trng)
+		return -ENOMEM;
+
+	if (!devm_request_mem_region(&pdev->dev, res->start,
+				     resource_size(res), pdev->name))
+		return -EBUSY;
+
+	trng->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!trng->base)
+		return -EBUSY;
+
+	trng->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(trng->clk))
+		return PTR_ERR(trng->clk);
+
+	ret = clk_enable(trng->clk);
+	if (ret)
+		goto err_enable;
+
+	writel(TRNG_KEY | 1, trng->base + TRNG_CR);
+	trng->rng.name = pdev->name;
+	trng->rng.read = atmel_trng_read;
+
+	ret = hwrng_register(&trng->rng);
+	if (ret)
+		goto err_register;
+
+	platform_set_drvdata(pdev, trng);
+
+	return 0;
+
+err_register:
+	clk_disable(trng->clk);
+err_enable:
+	clk_put(trng->clk);
+
+	return ret;
+}
+
+static int __devexit atmel_trng_remove(struct platform_device *pdev)
+{
+	struct atmel_trng *trng = platform_get_drvdata(pdev);
+
+	hwrng_unregister(&trng->rng);
+
+	writel(TRNG_KEY, trng->base + TRNG_CR);
+	clk_disable(trng->clk);
+	clk_put(trng->clk);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int atmel_trng_suspend(struct device *dev)
+{
+	struct atmel_trng *trng = dev_get_drvdata(dev);
+
+	clk_disable(trng->clk);
+
+	return 0;
+}
+
+static int atmel_trng_resume(struct device *dev)
+{
+	struct atmel_trng *trng = dev_get_drvdata(dev);
+
+	return clk_enable(trng->clk);
+}
+
+static const struct dev_pm_ops atmel_trng_pm_ops = {
+	.suspend	= atmel_trng_suspend,
+	.resume		= atmel_trng_resume,
+};
+#endif /* CONFIG_PM */
+
+static struct platform_driver atmel_trng_driver = {
+	.probe		= atmel_trng_probe,
+	.remove		= __devexit_p(atmel_trng_remove),
+	.driver		= {
+		.name	= "atmel-trng",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &atmel_trng_pm_ops,
+#endif /* CONFIG_PM */
+	},
+};
+
+static int __init atmel_trng_init(void)
+{
+	return platform_driver_register(&atmel_trng_driver);
+}
+module_init(atmel_trng_init);
+
+static void __exit atmel_trng_exit(void)
+{
+	platform_driver_unregister(&atmel_trng_driver);
+}
+module_exit(atmel_trng_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
+MODULE_DESCRIPTION("Atmel true random number generator driver");
diff -druN linux-libre-3.1-gnu/drivers/char/hw_random/Kconfig linux-libre-3.2-gnu/drivers/char/hw_random/Kconfig
--- linux-libre-3.1-gnu/drivers/char/hw_random/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/hw_random/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -60,6 +60,19 @@
 
 	  If unsure, say Y.
 
+config HW_RANDOM_ATMEL
+	tristate "Atmel Random Number Generator support"
+	depends on HW_RANDOM && ARCH_AT91SAM9G45
+	default HW_RANDOM
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator hardware found on Atmel AT91 devices.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called atmel-rng.
+
+	  If unsure, say Y.
+
 config HW_RANDOM_GEODE
 	tristate "AMD Geode HW Random Number Generator support"
 	depends on HW_RANDOM && X86_32 && PCI
@@ -222,3 +235,18 @@
 	 module will be called ppc4xx-rng.
 
 	 If unsure, say N.
+
+config UML_RANDOM
+	depends on UML
+	tristate "Hardware random number generator"
+	help
+	  This option enables UML's "hardware" random number generator.  It
+	  attaches itself to the host's /dev/random, supplying as much entropy
+	  as the host has, rather than the small amount the UML gets from its
+	  own drivers.  It registers itself as a standard hardware random number
+	  generator, major 10, minor 183, and the canonical device name is
+	  /dev/hwrng.
+	  The way to make use of this is to install the rng-tools package
+	  (check your distro, or download from
+	  http://sourceforge.net/projects/gkernel/).  rngd periodically reads
+	  /dev/hwrng and injects the entropy into /dev/random.
diff -druN linux-libre-3.1-gnu/drivers/char/hw_random/Makefile linux-libre-3.2-gnu/drivers/char/hw_random/Makefile
--- linux-libre-3.1-gnu/drivers/char/hw_random/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/hw_random/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
 obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o
 obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
 obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
+obj-$(CONFIG_HW_RANDOM_ATMEL) += atmel-rng.o
 obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
 obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o
 n2-rng-y := n2-drv.o n2-asm.o
diff -druN linux-libre-3.1-gnu/drivers/char/hw_random/virtio-rng.c linux-libre-3.2-gnu/drivers/char/hw_random/virtio-rng.c
--- linux-libre-3.1-gnu/drivers/char/hw_random/virtio-rng.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/hw_random/virtio-rng.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/spinlock.h>
 #include <linux/virtio.h>
 #include <linux/virtio_rng.h>
+#include <linux/module.h>
 
 static struct virtqueue *vq;
 static unsigned int data_avail;
diff -druN linux-libre-3.1-gnu/drivers/char/ipmi/ipmi_watchdog.c linux-libre-3.2-gnu/drivers/char/ipmi/ipmi_watchdog.c
--- linux-libre-3.1-gnu/drivers/char/ipmi/ipmi_watchdog.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/ipmi/ipmi_watchdog.c	2012-01-04 18:55:44.000000000 -0500
@@ -65,6 +65,7 @@
  * mechanism for it at that time.
  */
 #include <asm/kdebug.h>
+#include <asm/nmi.h>
 #define HAVE_DIE_NMI
 #endif
 
@@ -138,6 +139,8 @@
 #define IPMI_WDOG_SET_TIMER		0x24
 #define IPMI_WDOG_GET_TIMER		0x25
 
+#define IPMI_WDOG_TIMER_NOT_INIT_RESP	0x80
+
 /* These are here until the real ones get into the watchdog.h interface. */
 #ifndef WDIOC_GETTIMEOUT
 #define	WDIOC_GETTIMEOUT        _IOW(WATCHDOG_IOCTL_BASE, 20, int)
@@ -595,6 +598,7 @@
 	struct kernel_ipmi_msg            msg;
 	int                               rv;
 	struct ipmi_system_interface_addr addr;
+	int				  timeout_retries = 0;
 
 	if (ipmi_ignore_heartbeat)
 		return 0;
@@ -615,6 +619,7 @@
 
 	mutex_lock(&heartbeat_lock);
 
+restart:
 	atomic_set(&heartbeat_tofree, 2);
 
 	/*
@@ -652,7 +657,33 @@
 	/* Wait for the heartbeat to be sent. */
 	wait_for_completion(&heartbeat_wait);
 
-	if (heartbeat_recv_msg.msg.data[0] != 0) {
+	if (heartbeat_recv_msg.msg.data[0] == IPMI_WDOG_TIMER_NOT_INIT_RESP)  {
+		timeout_retries++;
+		if (timeout_retries > 3) {
+			printk(KERN_ERR PFX ": Unable to restore the IPMI"
+			       " watchdog's settings, giving up.\n");
+			rv = -EIO;
+			goto out_unlock;
+		}
+
+		/*
+		 * The timer was not initialized, that means the BMC was
+		 * probably reset and lost the watchdog information.  Attempt
+		 * to restore the timer's info.  Note that we still hold
+		 * the heartbeat lock, to keep a heartbeat from happening
+		 * in this process, so must say no heartbeat to avoid a
+		 * deadlock on this mutex.
+		 */
+		rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
+		if (rv) {
+			printk(KERN_ERR PFX ": Unable to send the command to"
+			       " set the watchdog's settings, giving up.\n");
+			goto out_unlock;
+		}
+
+		/* We might need a new heartbeat, so do it now */
+		goto restart;
+	} else if (heartbeat_recv_msg.msg.data[0] != 0) {
 		/*
 		 * Got an error in the heartbeat response.  It was already
 		 * reported in ipmi_wdog_msg_handler, but we should return
@@ -661,6 +692,7 @@
 		rv = -EINVAL;
 	}
 
+out_unlock:
 	mutex_unlock(&heartbeat_lock);
 
 	return rv;
@@ -921,11 +953,15 @@
 static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
 				  void                 *handler_data)
 {
-	if (msg->msg.data[0] != 0) {
+	if (msg->msg.cmd == IPMI_WDOG_RESET_TIMER &&
+			msg->msg.data[0] == IPMI_WDOG_TIMER_NOT_INIT_RESP)
+		printk(KERN_INFO PFX "response: The IPMI controller appears"
+		       " to have been reset, will attempt to reinitialize"
+		       " the watchdog timer\n");
+	else if (msg->msg.data[0] != 0)
 		printk(KERN_ERR PFX "response: Error %x on cmd %x\n",
 		       msg->msg.data[0],
 		       msg->msg.cmd);
-	}
 
 	ipmi_free_recv_msg(msg);
 }
@@ -1077,17 +1113,8 @@
 
 #ifdef HAVE_DIE_NMI
 static int
-ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
+ipmi_nmi(unsigned int val, struct pt_regs *regs)
 {
-	struct die_args *args = data;
-
-	if (val != DIE_NMIUNKNOWN)
-		return NOTIFY_OK;
-
-	/* Hack, if it's a memory or I/O error, ignore it. */
-	if (args->err & 0xc0)
-		return NOTIFY_OK;
-
 	/*
 	 * If we get here, it's an NMI that's not a memory or I/O
 	 * error.  We can't truly tell if it's from IPMI or not
@@ -1097,15 +1124,15 @@
 
 	if (testing_nmi) {
 		testing_nmi = 2;
-		return NOTIFY_STOP;
+		return NMI_HANDLED;
 	}
 
 	/* If we are not expecting a timeout, ignore it. */
 	if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
-		return NOTIFY_OK;
+		return NMI_DONE;
 
 	if (preaction_val != WDOG_PRETIMEOUT_NMI)
-		return NOTIFY_OK;
+		return NMI_DONE;
 
 	/*
 	 * If no one else handled the NMI, we assume it was the IPMI
@@ -1120,12 +1147,8 @@
 			panic(PFX "pre-timeout");
 	}
 
-	return NOTIFY_STOP;
+	return NMI_HANDLED;
 }
-
-static struct notifier_block ipmi_nmi_handler = {
-	.notifier_call = ipmi_nmi
-};
 #endif
 
 static int wdog_reboot_handler(struct notifier_block *this,
@@ -1290,7 +1313,8 @@
 		}
 	}
 	if (do_nmi && !nmi_handler_registered) {
-		rv = register_die_notifier(&ipmi_nmi_handler);
+		rv = register_nmi_handler(NMI_UNKNOWN, ipmi_nmi, 0,
+						"ipmi");
 		if (rv) {
 			printk(KERN_WARNING PFX
 			       "Can't register nmi handler\n");
@@ -1298,7 +1322,7 @@
 		} else
 			nmi_handler_registered = 1;
 	} else if (!do_nmi && nmi_handler_registered) {
-		unregister_die_notifier(&ipmi_nmi_handler);
+		unregister_nmi_handler(NMI_UNKNOWN, "ipmi");
 		nmi_handler_registered = 0;
 	}
 #endif
@@ -1336,7 +1360,7 @@
 	if (rv) {
 #ifdef HAVE_DIE_NMI
 		if (nmi_handler_registered)
-			unregister_die_notifier(&ipmi_nmi_handler);
+			unregister_nmi_handler(NMI_UNKNOWN, "ipmi");
 #endif
 		atomic_notifier_chain_unregister(&panic_notifier_list,
 						 &wdog_panic_notifier);
@@ -1357,7 +1381,7 @@
 
 #ifdef HAVE_DIE_NMI
 	if (nmi_handler_registered)
-		unregister_die_notifier(&ipmi_nmi_handler);
+		unregister_nmi_handler(NMI_UNKNOWN, "ipmi");
 #endif
 
 	atomic_notifier_chain_unregister(&panic_notifier_list,
diff -druN linux-libre-3.1-gnu/drivers/char/Kconfig linux-libre-3.2-gnu/drivers/char/Kconfig
--- linux-libre-3.1-gnu/drivers/char/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -298,7 +298,7 @@
 config RTC
 	tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)"
 	depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV \
-			&& !ARM && !SUPERH && !S390 && !AVR32 && !BLACKFIN
+			&& !ARM && !SUPERH && !S390 && !AVR32 && !BLACKFIN && !UML
 	---help---
 	  If you say Y here and create a character special file /dev/rtc with
 	  major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -346,7 +346,7 @@
 
 config GEN_RTC
 	tristate "Generic /dev/rtc emulation"
-	depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32 && !BLACKFIN
+	depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32 && !BLACKFIN && !UML
 	---help---
 	  If you say Y here and create a character special file /dev/rtc with
 	  major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -490,7 +490,7 @@
 
 config PC8736x_GPIO
 	tristate "NatSemi PC8736x GPIO Support"
-	depends on X86_32
+	depends on X86_32 && !UML
 	default SCx200_GPIO	# mostly N
 	select NSC_GPIO		# needed for support routines
 	help
diff -druN linux-libre-3.1-gnu/drivers/char/mem.c linux-libre-3.2-gnu/drivers/char/mem.c
--- linux-libre-3.1-gnu/drivers/char/mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/mem.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/bootmem.h>
 #include <linux/splice.h>
 #include <linux/pfn.h>
+#include <linux/export.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
diff -druN linux-libre-3.1-gnu/drivers/char/ps3flash.c linux-libre-3.2-gnu/drivers/char/ps3flash.c
--- linux-libre-3.1-gnu/drivers/char/ps3flash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/ps3flash.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+#include <linux/module.h>
 
 #include <asm/lv1call.h>
 #include <asm/ps3stor.h>
diff -druN linux-libre-3.1-gnu/drivers/char/ramoops.c linux-libre-3.2-gnu/drivers/char/ramoops.c
--- linux-libre-3.1-gnu/drivers/char/ramoops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/ramoops.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/kmsg_dump.h>
 #include <linux/time.h>
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
diff -druN linux-libre-3.1-gnu/drivers/char/random.c linux-libre-3.2-gnu/drivers/char/random.c
--- linux-libre-3.1-gnu/drivers/char/random.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/random.c	2012-01-04 18:55:44.000000000 -0500
@@ -932,7 +932,21 @@
  */
 void get_random_bytes(void *buf, int nbytes)
 {
-	extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
+	char *p = buf;
+
+	while (nbytes) {
+		unsigned long v;
+		int chunk = min(nbytes, (int)sizeof(unsigned long));
+		
+		if (!arch_get_random_long(&v))
+			break;
+		
+		memcpy(p, &v, chunk);
+		p += chunk;
+		nbytes -= chunk;
+	}
+
+	extract_entropy(&nonblocking_pool, p, nbytes, 0, 0);
 }
 EXPORT_SYMBOL(get_random_bytes);
 
@@ -1318,9 +1332,14 @@
 DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
 unsigned int get_random_int(void)
 {
-	__u32 *hash = get_cpu_var(get_random_int_hash);
+	__u32 *hash;
 	unsigned int ret;
 
+	if (arch_get_random_int(&ret))
+		return ret;
+
+	hash = get_cpu_var(get_random_int_hash);
+
 	hash[0] += current->pid + jiffies + get_cycles();
 	md5_transform(hash, random_int_secret);
 	ret = hash[0];
diff -druN linux-libre-3.1-gnu/drivers/char/raw.c linux-libre-3.2-gnu/drivers/char/raw.c
--- linux-libre-3.1-gnu/drivers/char/raw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/raw.c	2012-01-04 18:55:44.000000000 -0500
@@ -324,13 +324,12 @@
 		max_raw_minors = MAX_RAW_MINORS;
 	}
 
-	raw_devices = vmalloc(sizeof(struct raw_device_data) * max_raw_minors);
+	raw_devices = vzalloc(sizeof(struct raw_device_data) * max_raw_minors);
 	if (!raw_devices) {
 		printk(KERN_ERR "Not enough memory for raw device structures\n");
 		ret = -ENOMEM;
 		goto error;
 	}
-	memset(raw_devices, 0, sizeof(struct raw_device_data) * max_raw_minors);
 
 	ret = register_chrdev_region(dev, max_raw_minors, "raw");
 	if (ret)
diff -druN linux-libre-3.1-gnu/drivers/char/rtc.c linux-libre-3.2-gnu/drivers/char/rtc.c
--- linux-libre-3.1-gnu/drivers/char/rtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/rtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -80,6 +80,7 @@
 #include <linux/bcd.h>
 #include <linux/delay.h>
 #include <linux/uaccess.h>
+#include <linux/ratelimit.h>
 
 #include <asm/current.h>
 #include <asm/system.h>
@@ -1195,10 +1196,8 @@
 
 	spin_unlock_irq(&rtc_lock);
 
-	if (printk_ratelimit()) {
-		printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
-			freq);
-	}
+	printk_ratelimited(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
+			   freq);
 
 	/* Now we have new data */
 	wake_up_interruptible(&rtc_wait);
diff -druN linux-libre-3.1-gnu/drivers/char/scc.h linux-libre-3.2-gnu/drivers/char/scc.h
--- linux-libre-3.1-gnu/drivers/char/scc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/scc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,613 +0,0 @@
-/*
- * atari_SCC.h: Definitions for the Am8530 Serial Communications Controller
- *
- * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- *
- */
-
-
-#ifndef _SCC_H
-#define _SCC_H
-
-#include <linux/delay.h>
-
-/* Special configuration ioctls for the Atari SCC5380 Serial
- * Communications Controller
- */
-
-/* ioctl command codes */
-
-#define TIOCGATSCC	0x54c0	/* get SCC configuration */
-#define TIOCSATSCC	0x54c1	/* set SCC configuration */
-#define TIOCDATSCC	0x54c2	/* reset configuration to defaults */
-
-/* Clock sources */
-
-#define CLK_RTxC	0
-#define CLK_TRxC	1
-#define CLK_PCLK	2
-
-/* baud_bases for the common clocks in the Atari. These are the real
- * frequencies divided by 16.
- */
-   
-#define SCC_BAUD_BASE_TIMC	19200	/* 0.3072 MHz from TT-MFP, Timer C */
-#define SCC_BAUD_BASE_BCLK	153600	/* 2.4576 MHz */
-#define SCC_BAUD_BASE_PCLK4	229500	/* 3.6720 MHz */
-#define SCC_BAUD_BASE_PCLK	503374	/* 8.0539763 MHz */
-#define SCC_BAUD_BASE_NONE	0	/* for not connected or unused
-					 * clock sources */
-
-/* The SCC clock configuration structure */
-
-struct scc_clock_config {
-	unsigned	RTxC_base;	/* base_baud of RTxC */
-	unsigned	TRxC_base;	/* base_baud of TRxC */
-	unsigned	PCLK_base;	/* base_baud of PCLK, both channels! */
-	struct {
-		unsigned clksrc;	/* CLK_RTxC, CLK_TRxC or CLK_PCLK */
-		unsigned divisor;	/* divisor for base baud, valid values:
-					 * see below */
-	} baud_table[17];		/* For 50, 75, 110, 135, 150, 200, 300,
-					 * 600, 1200, 1800, 2400, 4800, 9600,
-					 * 19200, 38400, 57600 and 115200 bps.
-					 * The last two could be replaced by
-					 * other rates > 38400 if they're not
-					 * possible.
-					 */
-};
-
-/* The following divisors are valid:
- *
- *   - CLK_RTxC: 1 or even (1, 2 and 4 are the direct modes, > 4 use
- *               the BRG)
- *
- *   - CLK_TRxC: 1, 2 or 4 (no BRG, only direct modes possible)
- *
- *   - CLK_PCLK: >= 4 and even (no direct modes, only BRG)
- *
- */
-
-struct scc_port {
-	struct gs_port		gs;
-	volatile unsigned char	*ctrlp;
-	volatile unsigned char	*datap;
-	int			x_char;		/* xon/xoff character */
-	int			c_dcd;
-	int			channel;
-	struct scc_port		*port_a;	/* Reference to port A and B */
-	struct scc_port		*port_b;	/*   structs for reg access  */
-};
-
-#define SCC_MAGIC	0x52696368
-
-/***********************************************************************/
-/*                                                                     */
-/*                             Register Names                          */
-/*                                                                     */
-/***********************************************************************/
-
-/* The SCC documentation gives no explicit names to the registers,
- * they're just called WR0..15 and RR0..15. To make the source code
- * better readable and make the transparent write reg read access (see
- * below) possible, I christen them here with self-invented names.
- * Note that (real) read registers are assigned numbers 16..31. WR7'
- * has number 33.
- */
-
-#define	COMMAND_REG		0	/* wo */
-#define	INT_AND_DMA_REG		1	/* wo */
-#define	INT_VECTOR_REG		2	/* rw, common to both channels */
-#define	RX_CTRL_REG		3	/* rw */
-#define	AUX1_CTRL_REG		4	/* rw */
-#define	TX_CTRL_REG		5	/* rw */
-#define	SYNC_ADR_REG		6	/* wo */
-#define	SYNC_CHAR_REG		7	/* wo */
-#define	SDLC_OPTION_REG		33	/* wo */
-#define	TX_DATA_REG		8	/* wo */
-#define	MASTER_INT_CTRL		9	/* wo, common to both channels */
-#define	AUX2_CTRL_REG		10	/* rw */
-#define	CLK_CTRL_REG		11	/* wo */
-#define	TIMER_LOW_REG		12	/* rw */
-#define	TIMER_HIGH_REG		13	/* rw */
-#define	DPLL_CTRL_REG		14	/* wo */
-#define	INT_CTRL_REG		15	/* rw */
-
-#define	STATUS_REG		16	/* ro */
-#define	SPCOND_STATUS_REG	17	/* wo */
-/* RR2 is WR2 for Channel A, Channel B gives vector + current status: */
-#define	CURR_VECTOR_REG		18	/* Ch. B only, Ch. A for rw */
-#define	INT_PENDING_REG		19	/* Channel A only! */
-/* RR4 is WR4, if b6(MR7') == 1 */
-/* RR5 is WR5, if b6(MR7') == 1 */
-#define	FS_FIFO_LOW_REG		22	/* ro */
-#define	FS_FIFO_HIGH_REG	23	/* ro */
-#define	RX_DATA_REG		24	/* ro */
-/* RR9 is WR3, if b6(MR7') == 1 */
-#define	DPLL_STATUS_REG		26	/* ro */
-/* RR11 is WR10, if b6(MR7') == 1 */
-/* RR12 is WR12 */
-/* RR13 is WR13 */
-/* RR14 not present */
-/* RR15 is WR15 */
-
-
-/***********************************************************************/
-/*                                                                     */
-/*                             Register Values                         */
-/*                                                                     */
-/***********************************************************************/
-
-
-/* WR0: COMMAND_REG "CR" */
-
-#define	CR_RX_CRC_RESET		0x40
-#define	CR_TX_CRC_RESET		0x80
-#define	CR_TX_UNDERRUN_RESET	0xc0
-
-#define	CR_EXTSTAT_RESET	0x10
-#define	CR_SEND_ABORT		0x18
-#define	CR_ENAB_INT_NEXT_RX	0x20
-#define	CR_TX_PENDING_RESET	0x28
-#define	CR_ERROR_RESET		0x30
-#define	CR_HIGHEST_IUS_RESET	0x38
-
-
-/* WR1: INT_AND_DMA_REG "IDR" */
-
-#define	IDR_EXTSTAT_INT_ENAB	0x01
-#define	IDR_TX_INT_ENAB		0x02
-#define	IDR_PARERR_AS_SPCOND	0x04
-
-#define	IDR_RX_INT_DISAB	0x00
-#define	IDR_RX_INT_FIRST	0x08
-#define	IDR_RX_INT_ALL		0x10
-#define	IDR_RX_INT_SPCOND	0x18
-#define	IDR_RX_INT_MASK		0x18
-
-#define	IDR_WAITREQ_RX		0x20
-#define	IDR_WAITREQ_IS_REQ	0x40
-#define	IDR_WAITREQ_ENAB	0x80
-
-
-/* WR3: RX_CTRL_REG "RCR" */
-
-#define	RCR_RX_ENAB		0x01
-#define	RCR_DISCARD_SYNC_CHARS	0x02
-#define	RCR_ADDR_SEARCH		0x04
-#define	RCR_CRC_ENAB		0x08
-#define	RCR_SEARCH_MODE		0x10
-#define	RCR_AUTO_ENAB_MODE	0x20
-
-#define	RCR_CHSIZE_MASK		0xc0
-#define	RCR_CHSIZE_5		0x00
-#define	RCR_CHSIZE_6		0x40
-#define	RCR_CHSIZE_7		0x80
-#define	RCR_CHSIZE_8		0xc0
-
-
-/* WR4: AUX1_CTRL_REG "A1CR" */
-
-#define	A1CR_PARITY_MASK	0x03
-#define	A1CR_PARITY_NONE	0x00
-#define	A1CR_PARITY_ODD		0x01
-#define	A1CR_PARITY_EVEN	0x03
-
-#define	A1CR_MODE_MASK		0x0c
-#define	A1CR_MODE_SYNCR		0x00
-#define	A1CR_MODE_ASYNC_1	0x04
-#define	A1CR_MODE_ASYNC_15	0x08
-#define	A1CR_MODE_ASYNC_2	0x0c
-
-#define	A1CR_SYNCR_MODE_MASK	0x30
-#define	A1CR_SYNCR_MONOSYNC	0x00
-#define	A1CR_SYNCR_BISYNC	0x10
-#define	A1CR_SYNCR_SDLC		0x20
-#define	A1CR_SYNCR_EXTCSYNC	0x30
-
-#define	A1CR_CLKMODE_MASK	0xc0
-#define	A1CR_CLKMODE_x1		0x00
-#define	A1CR_CLKMODE_x16	0x40
-#define	A1CR_CLKMODE_x32	0x80
-#define	A1CR_CLKMODE_x64	0xc0
-
-
-/* WR5: TX_CTRL_REG "TCR" */
-
-#define	TCR_TX_CRC_ENAB		0x01
-#define	TCR_RTS			0x02
-#define	TCR_USE_CRC_CCITT	0x00
-#define	TCR_USE_CRC_16		0x04
-#define	TCR_TX_ENAB		0x08
-#define	TCR_SEND_BREAK		0x10
-
-#define	TCR_CHSIZE_MASK		0x60
-#define	TCR_CHSIZE_5		0x00
-#define	TCR_CHSIZE_6		0x20
-#define	TCR_CHSIZE_7		0x40
-#define	TCR_CHSIZE_8		0x60
-
-#define	TCR_DTR			0x80
-
-
-/* WR7': SLDC_OPTION_REG "SOR" */
-
-#define	SOR_AUTO_TX_ENAB	0x01
-#define	SOR_AUTO_EOM_RESET	0x02
-#define	SOR_AUTO_RTS_MODE	0x04
-#define	SOR_NRZI_DISAB_HIGH	0x08
-#define	SOR_ALT_DTRREQ_TIMING	0x10
-#define	SOR_READ_CRC_CHARS	0x20
-#define	SOR_EXTENDED_REG_ACCESS	0x40
-
-
-/* WR9: MASTER_INT_CTRL "MIC" */
-
-#define	MIC_VEC_INCL_STAT	0x01
-#define	MIC_NO_VECTOR		0x02
-#define	MIC_DISAB_LOWER_CHAIN	0x04
-#define	MIC_MASTER_INT_ENAB	0x08
-#define	MIC_STATUS_HIGH		0x10
-#define	MIC_IGN_INTACK		0x20
-
-#define	MIC_NO_RESET		0x00
-#define	MIC_CH_A_RESET		0x40
-#define	MIC_CH_B_RESET		0x80
-#define	MIC_HARD_RESET		0xc0
-
-
-/* WR10: AUX2_CTRL_REG "A2CR" */
-
-#define	A2CR_SYNC_6		0x01
-#define	A2CR_LOOP_MODE		0x02
-#define	A2CR_ABORT_ON_UNDERRUN	0x04
-#define	A2CR_MARK_IDLE		0x08
-#define	A2CR_GO_ACTIVE_ON_POLL	0x10
-
-#define	A2CR_CODING_MASK	0x60
-#define	A2CR_CODING_NRZ		0x00
-#define	A2CR_CODING_NRZI	0x20
-#define	A2CR_CODING_FM1		0x40
-#define	A2CR_CODING_FM0		0x60
-
-#define	A2CR_PRESET_CRC_1	0x80
-
-
-/* WR11: CLK_CTRL_REG "CCR" */
-
-#define	CCR_TRxCOUT_MASK	0x03
-#define	CCR_TRxCOUT_XTAL	0x00
-#define	CCR_TRxCOUT_TXCLK	0x01
-#define	CCR_TRxCOUT_BRG		0x02
-#define	CCR_TRxCOUT_DPLL	0x03
-
-#define	CCR_TRxC_OUTPUT		0x04
-
-#define	CCR_TXCLK_MASK		0x18
-#define	CCR_TXCLK_RTxC		0x00
-#define	CCR_TXCLK_TRxC		0x08
-#define	CCR_TXCLK_BRG		0x10
-#define	CCR_TXCLK_DPLL		0x18
-
-#define	CCR_RXCLK_MASK		0x60
-#define	CCR_RXCLK_RTxC		0x00
-#define	CCR_RXCLK_TRxC		0x20
-#define	CCR_RXCLK_BRG		0x40
-#define	CCR_RXCLK_DPLL		0x60
-
-#define	CCR_RTxC_XTAL		0x80
-
-
-/* WR14: DPLL_CTRL_REG "DCR" */
-
-#define	DCR_BRG_ENAB		0x01
-#define	DCR_BRG_USE_PCLK	0x02
-#define	DCR_DTRREQ_IS_REQ	0x04
-#define	DCR_AUTO_ECHO		0x08
-#define	DCR_LOCAL_LOOPBACK	0x10
-
-#define	DCR_DPLL_EDGE_SEARCH	0x20
-#define	DCR_DPLL_ERR_RESET	0x40
-#define	DCR_DPLL_DISAB		0x60
-#define	DCR_DPLL_CLK_BRG	0x80
-#define	DCR_DPLL_CLK_RTxC	0xa0
-#define	DCR_DPLL_FM		0xc0
-#define	DCR_DPLL_NRZI		0xe0
-
-
-/* WR15: INT_CTRL_REG "ICR" */
-
-#define	ICR_OPTIONREG_SELECT	0x01
-#define	ICR_ENAB_BRG_ZERO_INT	0x02
-#define	ICR_USE_FS_FIFO		0x04
-#define	ICR_ENAB_DCD_INT	0x08
-#define	ICR_ENAB_SYNC_INT	0x10
-#define	ICR_ENAB_CTS_INT	0x20
-#define	ICR_ENAB_UNDERRUN_INT	0x40
-#define	ICR_ENAB_BREAK_INT	0x80
-
-
-/* RR0: STATUS_REG "SR" */
-
-#define	SR_CHAR_AVAIL		0x01
-#define	SR_BRG_ZERO		0x02
-#define	SR_TX_BUF_EMPTY		0x04
-#define	SR_DCD			0x08
-#define	SR_SYNC_ABORT		0x10
-#define	SR_CTS			0x20
-#define	SR_TX_UNDERRUN		0x40
-#define	SR_BREAK		0x80
-
-
-/* RR1: SPCOND_STATUS_REG "SCSR" */
-
-#define	SCSR_ALL_SENT		0x01
-#define	SCSR_RESIDUAL_MASK	0x0e
-#define	SCSR_PARITY_ERR		0x10
-#define	SCSR_RX_OVERRUN		0x20
-#define	SCSR_CRC_FRAME_ERR	0x40
-#define	SCSR_END_OF_FRAME	0x80
-
-
-/* RR3: INT_PENDING_REG "IPR" */
-
-#define	IPR_B_EXTSTAT		0x01
-#define	IPR_B_TX		0x02
-#define	IPR_B_RX		0x04
-#define	IPR_A_EXTSTAT		0x08
-#define	IPR_A_TX		0x10
-#define	IPR_A_RX		0x20
-
-
-/* RR7: FS_FIFO_HIGH_REG "FFHR" */
-
-#define	FFHR_CNT_MASK		0x3f
-#define	FFHR_IS_FROM_FIFO	0x40
-#define	FFHR_FIFO_OVERRUN	0x80
-
-
-/* RR10: DPLL_STATUS_REG "DSR" */
-
-#define	DSR_ON_LOOP		0x02
-#define	DSR_ON_LOOP_SENDING	0x10
-#define	DSR_TWO_CLK_MISSING	0x40
-#define	DSR_ONE_CLK_MISSING	0x80
-
-/***********************************************************************/
-/*                                                                     */
-/*                             Register Access                         */
-/*                                                                     */
-/***********************************************************************/
-
-
-/* The SCC needs 3.5 PCLK cycles recovery time between to register
- * accesses. PCLK runs with 8 MHz on an Atari, so this delay is 3.5 *
- * 125 ns = 437.5 ns. This is too short for udelay().
- * 10/16/95: A tstb st_mfp.par_dt_reg takes 600ns (sure?) and thus should be
- * quite right
- */
-
-#define scc_reg_delay() \
-    do {			\
-	if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)	\
-		__asm__ __volatile__ ( " nop; nop");			\
-	else if (MACH_IS_ATARI)						\
-		__asm__ __volatile__ ( "tstb %0" : : "g" (*_scc_del) : "cc" );\
-    } while (0)
-
-static unsigned char scc_shadow[2][16];
-
-/* The following functions should relax the somehow complicated
- * register access of the SCC. _SCCwrite() stores all written values
- * (except for WR0 and WR8) in shadow registers for later recall. This
- * removes the burden of remembering written values as needed. The
- * extra work of storing the value doesn't count, since a delay is
- * needed after a SCC access anyway. Additionally, _SCCwrite() manages
- * writes to WR0 and WR8 differently, because these can be accessed
- * directly with less overhead. Another special case are WR7 and WR7'.
- * _SCCwrite automatically checks what of this registers is selected
- * and changes b0 of WR15 if needed.
- * 
- * _SCCread() for standard read registers is straightforward, except
- * for RR2 (split into two "virtual" registers: one for the value
- * written to WR2 (from the shadow) and one for the vector including
- * status from RR2, Ch. B) and RR3. The latter must be read from
- * Channel A, because it reads as all zeros on Ch. B. RR0 and RR8 can
- * be accessed directly as before.
- * 
- * The two inline function contain complicated switch statements. But
- * I rely on regno and final_delay being constants, so gcc can reduce
- * the whole stuff to just some assembler statements.
- * 
- * _SCCwrite and _SCCread aren't intended to be used directly under
- * normal circumstances. The macros SCCread[_ND] and SCCwrite[_ND] are
- * for that purpose. They assume that a local variable 'port' is
- * declared and pointing to the port's scc_struct entry. The
- * variants with "_NB" appended should be used if no other SCC
- * accesses follow immediately (within 0.5 usecs). They just skip the
- * final delay nops.
- * 
- * Please note that accesses to SCC registers should only take place
- * when interrupts are turned off (at least if SCC interrupts are
- * enabled). Otherwise, an interrupt could interfere with the
- * two-stage accessing process.
- *
- */
-
-
-static __inline__ void _SCCwrite(
-	struct scc_port *port,
-	unsigned char *shadow,
-	volatile unsigned char *_scc_del,
-	int regno,
-	unsigned char val, int final_delay )
-{
-	switch( regno ) {
-
-	  case COMMAND_REG:
-		/* WR0 can be written directly without pointing */
-		*port->ctrlp = val;
-		break;
-
-	  case SYNC_CHAR_REG:
-		/* For WR7, first set b0 of WR15 to 0, if needed */
-		if (shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT) {
-			*port->ctrlp = 15;
-			shadow[INT_CTRL_REG] &= ~ICR_OPTIONREG_SELECT;
-			scc_reg_delay();
-			*port->ctrlp = shadow[INT_CTRL_REG];
-			scc_reg_delay();
-		}
-		goto normal_case;
-		
-	  case SDLC_OPTION_REG:
-		/* For WR7', first set b0 of WR15 to 1, if needed */
-		if (!(shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT)) {
-			*port->ctrlp = 15;
-			shadow[INT_CTRL_REG] |= ICR_OPTIONREG_SELECT;
-			scc_reg_delay();
-			*port->ctrlp = shadow[INT_CTRL_REG];
-			scc_reg_delay();
-		}
-		*port->ctrlp = 7;
-		shadow[8] = val;	/* WR7' shadowed at WR8 */
-		scc_reg_delay();
-		*port->ctrlp = val;
-		break;
-
-	  case TX_DATA_REG:		/* WR8 */
-		/* TX_DATA_REG can be accessed directly on some h/w */
-		if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)
-		{
-			*port->ctrlp = regno;
-			scc_reg_delay();
-			*port->ctrlp = val;
-		}
-		else
-			*port->datap = val;
-		break;
-
-	  case MASTER_INT_CTRL:
-		*port->ctrlp = regno;
-		val &= 0x3f;	/* bits 6..7 are the reset commands */
-		scc_shadow[0][regno] = val;
-		scc_reg_delay();
-		*port->ctrlp = val;
-		break;
-
-	  case DPLL_CTRL_REG:
-		*port->ctrlp = regno;
-		val &= 0x1f;			/* bits 5..7 are the DPLL commands */
-		shadow[regno] = val;
-		scc_reg_delay();
-		*port->ctrlp = val;
-		break;
-
-	  case 1 ... 6:	
-	  case 10 ... 13:
-	  case 15:
-	  normal_case:
-		*port->ctrlp = regno;
-		shadow[regno] = val;
-		scc_reg_delay();
-		*port->ctrlp = val;
-		break;
-		
-	  default:
-		printk( "Bad SCC write access to WR%d\n", regno );
-		break;
-		
-	}
-
-	if (final_delay)
-		scc_reg_delay();
-}
-
-
-static __inline__ unsigned char _SCCread(
-	struct scc_port *port,
-	unsigned char *shadow,
-	volatile unsigned char *_scc_del,
-	int regno, int final_delay )
-{
-	unsigned char rv;
-
-	switch( regno ) {
-
-		/* --- real read registers --- */
-	  case STATUS_REG:
-		rv = *port->ctrlp;
-		break;
-
-	  case INT_PENDING_REG:
-		/* RR3: read only from Channel A! */
-		port = port->port_a;
-		goto normal_case;
-
-	  case RX_DATA_REG:
-		/* RR8 can be accessed directly on some h/w */
-		if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)
-		{
-			*port->ctrlp = 8;
-			scc_reg_delay();
-			rv = *port->ctrlp;
-		}
-		else
-			rv = *port->datap;
-		break;
-
-	  case CURR_VECTOR_REG:
-		/* RR2 (vector including status) from Ch. B */
-		port = port->port_b;
-		goto normal_case;
-		
-		/* --- reading write registers: access the shadow --- */
-	  case 1 ... 7:
-	  case 10 ... 15:
-		return shadow[regno]; /* no final delay! */
-
-		/* WR7' is special, because it is shadowed at the place of WR8 */
-	  case SDLC_OPTION_REG:
-		return shadow[8]; /* no final delay! */
-
-		/* WR9 is special too, because it is common for both channels */
-	  case MASTER_INT_CTRL:
-		return scc_shadow[0][9]; /* no final delay! */
-
-	  default:
-		printk( "Bad SCC read access to %cR%d\n", (regno & 16) ? 'R' : 'W',
-				regno & ~16 );
-		break;
-		
-	  case SPCOND_STATUS_REG:
-	  case FS_FIFO_LOW_REG:
-	  case FS_FIFO_HIGH_REG:
-	  case DPLL_STATUS_REG:
-	  normal_case:
-		*port->ctrlp = regno & 0x0f;
-		scc_reg_delay();
-		rv = *port->ctrlp;
-		break;
-		
-	}
-
-	if (final_delay)
-		scc_reg_delay();
-	return rv;
-}
-
-#define SCC_ACCESS_INIT(port)						\
-	unsigned char *_scc_shadow = &scc_shadow[port->channel][0]
-
-#define	SCCwrite(reg,val)	_SCCwrite(port,_scc_shadow,scc_del,(reg),(val),1)
-#define	SCCwrite_NB(reg,val)	_SCCwrite(port,_scc_shadow,scc_del,(reg),(val),0)
-#define	SCCread(reg)		_SCCread(port,_scc_shadow,scc_del,(reg),1)
-#define	SCCread_NB(reg)		_SCCread(port,_scc_shadow,scc_del,(reg),0)
-
-#define SCCmod(reg,and,or)	SCCwrite((reg),(SCCread(reg)&(and))|(or))
-
-#endif /* _SCC_H */
diff -druN linux-libre-3.1-gnu/drivers/char/tpm/tpm.c linux-libre-3.2-gnu/drivers/char/tpm/tpm.c
--- linux-libre-3.1-gnu/drivers/char/tpm/tpm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/tpm/tpm.c	2012-01-04 18:55:44.000000000 -0500
@@ -966,6 +966,9 @@
 {
 	struct tpm_chip *chip = dev_get_drvdata(dev);
 
+	if (chip->vendor.duration[TPM_LONG] == 0)
+		return 0;
+
 	return sprintf(buf, "%d %d %d [%s]\n",
 		       jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]),
 		       jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]),
diff -druN linux-libre-3.1-gnu/drivers/char/ttyprintk.c linux-libre-3.2-gnu/drivers/char/ttyprintk.c
--- linux-libre-3.1-gnu/drivers/char/ttyprintk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/ttyprintk.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/device.h>
 #include <linux/serial.h>
 #include <linux/tty.h>
+#include <linux/export.h>
 
 struct ttyprintk_port {
 	struct tty_port port;
@@ -170,7 +171,7 @@
 	.ioctl = tpk_ioctl,
 };
 
-struct tty_port_operations null_ops = { };
+static struct tty_port_operations null_ops = { };
 
 static struct tty_driver *ttyprintk_driver;
 
diff -druN linux-libre-3.1-gnu/drivers/char/virtio_console.c linux-libre-3.2-gnu/drivers/char/virtio_console.c
--- linux-libre-3.1-gnu/drivers/char/virtio_console.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/char/virtio_console.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,8 +19,10 @@
  */
 #include <linux/cdev.h>
 #include <linux/debugfs.h>
+#include <linux/completion.h>
 #include <linux/device.h>
 #include <linux/err.h>
+#include <linux/freezer.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/list.h>
@@ -32,6 +34,7 @@
 #include <linux/virtio_console.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
+#include <linux/module.h>
 #include "../tty/hvc/hvc_console.h"
 
 /*
@@ -73,6 +76,7 @@
 static struct ports_driver_data pdrvdata;
 
 DEFINE_SPINLOCK(pdrvdata_lock);
+DECLARE_COMPLETION(early_console_added);
 
 /* This struct holds information that's relevant only for console ports */
 struct console {
@@ -151,6 +155,10 @@
 	int chr_major;
 };
 
+struct port_stats {
+	unsigned long bytes_sent, bytes_received, bytes_discarded;
+};
+
 /* This struct holds the per-port data */
 struct port {
 	/* Next port in the list, head is in the ports_device */
@@ -179,6 +187,13 @@
 	struct dentry *debugfs_file;
 
 	/*
+	 * Keep count of the bytes sent, received and discarded for
+	 * this port for accounting and debugging purposes.  These
+	 * counts are not reset across port open / close events.
+	 */
+	struct port_stats stats;
+
+	/*
 	 * The entries in this struct will be valid if this port is
 	 * hooked up to an hvc console
 	 */
@@ -347,17 +362,19 @@
 }
 
 /* Callers should take appropriate locks */
-static void *get_inbuf(struct port *port)
+static struct port_buffer *get_inbuf(struct port *port)
 {
 	struct port_buffer *buf;
-	struct virtqueue *vq;
 	unsigned int len;
 
-	vq = port->in_vq;
-	buf = virtqueue_get_buf(vq, &len);
+	if (port->inbuf)
+		return port->inbuf;
+
+	buf = virtqueue_get_buf(port->in_vq, &len);
 	if (buf) {
 		buf->len = len;
 		buf->offset = 0;
+		port->stats.bytes_received += len;
 	}
 	return buf;
 }
@@ -384,32 +401,27 @@
 static void discard_port_data(struct port *port)
 {
 	struct port_buffer *buf;
-	struct virtqueue *vq;
-	unsigned int len;
-	int ret;
+	unsigned int err;
 
 	if (!port->portdev) {
 		/* Device has been unplugged.  vqs are already gone. */
 		return;
 	}
-	vq = port->in_vq;
-	if (port->inbuf)
-		buf = port->inbuf;
-	else
-		buf = virtqueue_get_buf(vq, &len);
+	buf = get_inbuf(port);
 
-	ret = 0;
+	err = 0;
 	while (buf) {
-		if (add_inbuf(vq, buf) < 0) {
-			ret++;
+		port->stats.bytes_discarded += buf->len - buf->offset;
+		if (add_inbuf(port->in_vq, buf) < 0) {
+			err++;
 			free_buf(buf);
 		}
-		buf = virtqueue_get_buf(vq, &len);
+		port->inbuf = NULL;
+		buf = get_inbuf(port);
 	}
-	port->inbuf = NULL;
-	if (ret)
+	if (err)
 		dev_warn(port->dev, "Errors adding %d buffers back to vq\n",
-			 ret);
+			 err);
 }
 
 static bool port_has_data(struct port *port)
@@ -417,18 +429,12 @@
 	unsigned long flags;
 	bool ret;
 
+	ret = false;
 	spin_lock_irqsave(&port->inbuf_lock, flags);
-	if (port->inbuf) {
-		ret = true;
-		goto out;
-	}
 	port->inbuf = get_inbuf(port);
-	if (port->inbuf) {
+	if (port->inbuf)
 		ret = true;
-		goto out;
-	}
-	ret = false;
-out:
+
 	spin_unlock_irqrestore(&port->inbuf_lock, flags);
 	return ret;
 }
@@ -529,6 +535,8 @@
 		cpu_relax();
 done:
 	spin_unlock_irqrestore(&port->outvq_lock, flags);
+
+	port->stats.bytes_sent += in_count;
 	/*
 	 * We're expected to return the amount of data we wrote -- all
 	 * of it
@@ -633,8 +641,8 @@
 		if (filp->f_flags & O_NONBLOCK)
 			return -EAGAIN;
 
-		ret = wait_event_interruptible(port->waitqueue,
-					       !will_read_block(port));
+		ret = wait_event_freezable(port->waitqueue,
+					   !will_read_block(port));
 		if (ret < 0)
 			return ret;
 	}
@@ -677,8 +685,8 @@
 		if (nonblock)
 			return -EAGAIN;
 
-		ret = wait_event_interruptible(port->waitqueue,
-					       !will_write_block(port));
+		ret = wait_event_freezable(port->waitqueue,
+					   !will_write_block(port));
 		if (ret < 0)
 			return ret;
 	}
@@ -1059,6 +1067,14 @@
 	out_offset += snprintf(buf + out_offset, out_count - out_offset,
 			       "outvq_full: %d\n", port->outvq_full);
 	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "bytes_sent: %lu\n", port->stats.bytes_sent);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "bytes_received: %lu\n",
+			       port->stats.bytes_received);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "bytes_discarded: %lu\n",
+			       port->stats.bytes_discarded);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
 			       "is_console: %s\n",
 			       is_console_port(port) ? "yes" : "no");
 	out_offset += snprintf(buf + out_offset, out_count - out_offset,
@@ -1143,6 +1159,7 @@
 	port->cons.ws.ws_row = port->cons.ws.ws_col = 0;
 
 	port->host_connected = port->guest_connected = false;
+	port->stats = (struct port_stats) { 0 };
 
 	port->outvq_full = false;
 
@@ -1352,6 +1369,7 @@
 			break;
 
 		init_port_console(port);
+		complete(&early_console_added);
 		/*
 		 * Could remove the port here in case init fails - but
 		 * have to notify the host first.
@@ -1394,6 +1412,13 @@
 		break;
 	case VIRTIO_CONSOLE_PORT_NAME:
 		/*
+		 * If we woke up after hibernation, we can get this
+		 * again.  Skip it in that case.
+		 */
+		if (port->name)
+			break;
+
+		/*
 		 * Skip the size of the header and the cpkt to get the size
 		 * of the name that was sent
 		 */
@@ -1481,8 +1506,7 @@
 		return;
 
 	spin_lock_irqsave(&port->inbuf_lock, flags);
-	if (!port->inbuf)
-		port->inbuf = get_inbuf(port);
+	port->inbuf = get_inbuf(port);
 
 	/*
 	 * Don't queue up data when port is closed.  This condition
@@ -1563,7 +1587,7 @@
 	portdev->out_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *),
 				   GFP_KERNEL);
 	if (!vqs || !io_callbacks || !io_names || !portdev->in_vqs ||
-			!portdev->out_vqs) {
+	    !portdev->out_vqs) {
 		err = -ENOMEM;
 		goto free;
 	}
@@ -1648,6 +1672,10 @@
 	struct ports_device *portdev;
 	int err;
 	bool multiport;
+	bool early = early_put_chars != NULL;
+
+	/* Ensure to read early_put_chars now */
+	barrier();
 
 	portdev = kmalloc(sizeof(*portdev), GFP_KERNEL);
 	if (!portdev) {
@@ -1675,13 +1703,11 @@
 
 	multiport = false;
 	portdev->config.max_nr_ports = 1;
-	if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) {
+	if (virtio_config_val(vdev, VIRTIO_CONSOLE_F_MULTIPORT,
+			      offsetof(struct virtio_console_config,
+				       max_nr_ports),
+			      &portdev->config.max_nr_ports) == 0)
 		multiport = true;
-		vdev->config->get(vdev, offsetof(struct virtio_console_config,
-						 max_nr_ports),
-				  &portdev->config.max_nr_ports,
-				  sizeof(portdev->config.max_nr_ports));
-	}
 
 	err = init_vqs(portdev);
 	if (err < 0) {
@@ -1719,6 +1745,19 @@
 
 	__send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID,
 			   VIRTIO_CONSOLE_DEVICE_READY, 1);
+
+	/*
+	 * If there was an early virtio console, assume that there are no
+	 * other consoles. We need to wait until the hvc_alloc matches the
+	 * hvc_instantiate, otherwise tty_open will complain, resulting in
+	 * a "Warning: unable to open an initial console" boot failure.
+	 * Without multiport this is done in add_port above. With multiport
+	 * this might take some host<->guest communication - thus we have to
+	 * wait.
+	 */
+	if (multiport && early)
+		wait_for_completion(&early_console_added);
+
 	return 0;
 
 free_vqs:
diff -druN linux-libre-3.1-gnu/drivers/clocksource/clksrc-dbx500-prcmu.c linux-libre-3.2-gnu/drivers/clocksource/clksrc-dbx500-prcmu.c
--- linux-libre-3.1-gnu/drivers/clocksource/clksrc-dbx500-prcmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/clocksource/clksrc-dbx500-prcmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson
+ * Author: Sundar Iyer for ST-Ericsson
+ * sched_clock implementation is based on:
+ * plat-nomadik/timer.c Linus Walleij <linus.walleij@stericsson.com>
+ *
+ * DBx500-PRCMU Timer
+ * The PRCMU has 5 timers which are available in a always-on
+ * power domain.  We use the Timer 4 for our always-on clock
+ * source on DB8500 and Timer 3 on DB5500.
+ */
+#include <linux/clockchips.h>
+#include <linux/clksrc-dbx500-prcmu.h>
+
+#include <asm/sched_clock.h>
+
+#include <mach/setup.h>
+#include <mach/hardware.h>
+
+#define RATE_32K		32768
+
+#define TIMER_MODE_CONTINOUS	0x1
+#define TIMER_DOWNCOUNT_VAL	0xffffffff
+
+#define PRCMU_TIMER_REF		0
+#define PRCMU_TIMER_DOWNCOUNT	0x4
+#define PRCMU_TIMER_MODE	0x8
+
+#define SCHED_CLOCK_MIN_WRAP 131072 /* 2^32 / 32768 */
+
+static void __iomem *clksrc_dbx500_timer_base;
+
+static cycle_t clksrc_dbx500_prcmu_read(struct clocksource *cs)
+{
+	u32 count, count2;
+
+	do {
+		count = readl(clksrc_dbx500_timer_base +
+			      PRCMU_TIMER_DOWNCOUNT);
+		count2 = readl(clksrc_dbx500_timer_base +
+			       PRCMU_TIMER_DOWNCOUNT);
+	} while (count2 != count);
+
+	/* Negate because the timer is a decrementing counter */
+	return ~count;
+}
+
+static struct clocksource clocksource_dbx500_prcmu = {
+	.name		= "dbx500-prcmu-timer",
+	.rating		= 300,
+	.read		= clksrc_dbx500_prcmu_read,
+	.shift		= 10,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+#ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK
+static DEFINE_CLOCK_DATA(cd);
+
+unsigned long long notrace sched_clock(void)
+{
+	u32 cyc;
+
+	if (unlikely(!clksrc_dbx500_timer_base))
+		return 0;
+
+	cyc = clksrc_dbx500_prcmu_read(&clocksource_dbx500_prcmu);
+
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace clksrc_dbx500_prcmu_update_sched_clock(void)
+{
+	u32 cyc = clksrc_dbx500_prcmu_read(&clocksource_dbx500_prcmu);
+	update_sched_clock(&cd, cyc, (u32)~0);
+}
+#endif
+
+void __init clksrc_dbx500_prcmu_init(void __iomem *base)
+{
+	clksrc_dbx500_timer_base = base;
+
+	/*
+	 * The A9 sub system expects the timer to be configured as
+	 * a continous looping timer.
+	 * The PRCMU should configure it but if it for some reason
+	 * don't we do it here.
+	 */
+	if (readl(clksrc_dbx500_timer_base + PRCMU_TIMER_MODE) !=
+	    TIMER_MODE_CONTINOUS) {
+		writel(TIMER_MODE_CONTINOUS,
+		       clksrc_dbx500_timer_base + PRCMU_TIMER_MODE);
+		writel(TIMER_DOWNCOUNT_VAL,
+		       clksrc_dbx500_timer_base + PRCMU_TIMER_REF);
+	}
+#ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK
+	init_sched_clock(&cd, clksrc_dbx500_prcmu_update_sched_clock,
+			 32, RATE_32K);
+#endif
+	clocksource_calc_mult_shift(&clocksource_dbx500_prcmu,
+				    RATE_32K, SCHED_CLOCK_MIN_WRAP);
+	clocksource_register(&clocksource_dbx500_prcmu);
+}
diff -druN linux-libre-3.1-gnu/drivers/clocksource/dw_apb_timer.c linux-libre-3.2-gnu/drivers/clocksource/dw_apb_timer.c
--- linux-libre-3.1-gnu/drivers/clocksource/dw_apb_timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/clocksource/dw_apb_timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -348,7 +348,7 @@
  * dw_apb_clocksource_register() as the next step.
  */
 struct dw_apb_clocksource *
-dw_apb_clocksource_init(unsigned rating, char *name, void __iomem *base,
+dw_apb_clocksource_init(unsigned rating, const char *name, void __iomem *base,
 			unsigned long freq)
 {
 	struct dw_apb_clocksource *dw_cs = kzalloc(sizeof(*dw_cs), GFP_KERNEL);
diff -druN linux-libre-3.1-gnu/drivers/clocksource/Kconfig linux-libre-3.2-gnu/drivers/clocksource/Kconfig
--- linux-libre-3.1-gnu/drivers/clocksource/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/clocksource/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -15,3 +15,18 @@
 
 config DW_APB_TIMER
 	bool
+
+config CLKSRC_DBX500_PRCMU
+	bool "Clocksource PRCMU Timer"
+	depends on UX500_SOC_DB5500 || UX500_SOC_DB8500
+	default y
+	help
+	  Use the always on PRCMU Timer as clocksource
+
+config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
+	bool "Clocksource PRCMU Timer sched_clock"
+	depends on (CLKSRC_DBX500_PRCMU && !NOMADIK_MTU_SCHED_CLOCK)
+	select HAVE_SCHED_CLOCK
+	default y
+	help
+	  Use the always on PRCMU Timer as sched_clock
diff -druN linux-libre-3.1-gnu/drivers/clocksource/Makefile linux-libre-3.2-gnu/drivers/clocksource/Makefile
--- linux-libre-3.1-gnu/drivers/clocksource/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/clocksource/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -9,3 +9,4 @@
 obj-$(CONFIG_CLKBLD_I8253)	+= i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)	+= mmio.o
 obj-$(CONFIG_DW_APB_TIMER)	+= dw_apb_timer.o
+obj-$(CONFIG_CLKSRC_DBX500_PRCMU)	+= clksrc-dbx500-prcmu.o
\ No newline at end of file
diff -druN linux-libre-3.1-gnu/drivers/clocksource/sh_cmt.c linux-libre-3.2-gnu/drivers/clocksource/sh_cmt.c
--- linux-libre-3.1-gnu/drivers/clocksource/sh_cmt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/clocksource/sh_cmt.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/clockchips.h>
 #include <linux/sh_timer.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 struct sh_cmt_priv {
 	void __iomem *mapbase;
diff -druN linux-libre-3.1-gnu/drivers/clocksource/sh_mtu2.c linux-libre-3.2-gnu/drivers/clocksource/sh_mtu2.c
--- linux-libre-3.1-gnu/drivers/clocksource/sh_mtu2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/clocksource/sh_mtu2.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/clockchips.h>
 #include <linux/sh_timer.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 struct sh_mtu2_priv {
 	void __iomem *mapbase;
diff -druN linux-libre-3.1-gnu/drivers/clocksource/sh_tmu.c linux-libre-3.2-gnu/drivers/clocksource/sh_tmu.c
--- linux-libre-3.1-gnu/drivers/clocksource/sh_tmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/clocksource/sh_tmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/clockchips.h>
 #include <linux/sh_timer.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 struct sh_tmu_priv {
 	void __iomem *mapbase;
diff -druN linux-libre-3.1-gnu/drivers/connector/cn_proc.c linux-libre-3.2-gnu/drivers/connector/cn_proc.c
--- linux-libre-3.1-gnu/drivers/connector/cn_proc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/connector/cn_proc.c	2012-01-04 18:55:44.000000000 -0500
@@ -205,6 +205,32 @@
 	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
 }
 
+void proc_comm_connector(struct task_struct *task)
+{
+	struct cn_msg *msg;
+	struct proc_event *ev;
+	struct timespec ts;
+	__u8 buffer[CN_PROC_MSG_SIZE];
+
+	if (atomic_read(&proc_event_num_listeners) < 1)
+		return;
+
+	msg = (struct cn_msg *)buffer;
+	ev = (struct proc_event *)msg->data;
+	get_seq(&msg->seq, &ev->cpu);
+	ktime_get_ts(&ts); /* get high res monotonic timestamp */
+	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+	ev->what = PROC_EVENT_COMM;
+	ev->event_data.comm.process_pid  = task->pid;
+	ev->event_data.comm.process_tgid = task->tgid;
+	get_task_comm(ev->event_data.comm.comm, task);
+
+	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
+	msg->ack = 0; /* not used */
+	msg->len = sizeof(*ev);
+	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+}
+
 void proc_exit_connector(struct task_struct *task)
 {
 	struct cn_msg *msg;
diff -druN linux-libre-3.1-gnu/drivers/cpufreq/cpufreq_conservative.c linux-libre-3.2-gnu/drivers/cpufreq/cpufreq_conservative.c
--- linux-libre-3.1-gnu/drivers/cpufreq/cpufreq_conservative.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/cpufreq/cpufreq_conservative.c	2012-01-04 18:55:44.000000000 -0500
@@ -120,10 +120,12 @@
 
 static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
 {
-	u64 idle_time = get_cpu_idle_time_us(cpu, wall);
+	u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
 
 	if (idle_time == -1ULL)
 		return get_cpu_idle_time_jiffy(cpu, wall);
+	else
+		idle_time += get_cpu_iowait_time_us(cpu, wall);
 
 	return idle_time;
 }
diff -druN linux-libre-3.1-gnu/drivers/cpufreq/cpufreq_ondemand.c linux-libre-3.2-gnu/drivers/cpufreq/cpufreq_ondemand.c
--- linux-libre-3.1-gnu/drivers/cpufreq/cpufreq_ondemand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/cpufreq/cpufreq_ondemand.c	2012-01-04 18:55:44.000000000 -0500
@@ -144,10 +144,12 @@
 
 static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
 {
-	u64 idle_time = get_cpu_idle_time_us(cpu, wall);
+	u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
 
 	if (idle_time == -1ULL)
 		return get_cpu_idle_time_jiffy(cpu, wall);
+	else
+		idle_time += get_cpu_iowait_time_us(cpu, wall);
 
 	return idle_time;
 }
@@ -725,7 +727,7 @@
 		dbs_tuners_ins.down_differential =
 					MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
 		/*
-		 * In no_hz/micro accounting case we set the minimum frequency
+		 * In nohz/micro accounting case we set the minimum frequency
 		 * not depending on HZ, but fixed (very low). The deferred
 		 * timer might skip some samples if idle/sleeping as needed.
 		*/
diff -druN linux-libre-3.1-gnu/drivers/cpufreq/cpufreq_stats.c linux-libre-3.2-gnu/drivers/cpufreq/cpufreq_stats.c
--- linux-libre-3.1-gnu/drivers/cpufreq/cpufreq_stats.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/cpufreq/cpufreq_stats.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/cpu.h>
 #include <linux/sysfs.h>
 #include <linux/cpufreq.h>
+#include <linux/module.h>
 #include <linux/jiffies.h>
 #include <linux/percpu.h>
 #include <linux/kobject.h>
diff -druN linux-libre-3.1-gnu/drivers/cpufreq/db8500-cpufreq.c linux-libre-3.2-gnu/drivers/cpufreq/db8500-cpufreq.c
--- linux-libre-3.1-gnu/drivers/cpufreq/db8500-cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/cpufreq/db8500-cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,30 +12,35 @@
 #include <linux/cpufreq.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/mfd/db8500-prcmu.h>
+#include <linux/mfd/dbx500-prcmu.h>
 #include <mach/id.h>
 
 static struct cpufreq_frequency_table freq_table[] = {
 	[0] = {
 		.index = 0,
-		.frequency = 300000,
+		.frequency = 200000,
 	},
 	[1] = {
 		.index = 1,
-		.frequency = 600000,
+		.frequency = 300000,
 	},
 	[2] = {
-		/* Used for MAX_OPP, if available */
 		.index = 2,
-		.frequency = CPUFREQ_TABLE_END,
+		.frequency = 600000,
 	},
 	[3] = {
+		/* Used for MAX_OPP, if available */
 		.index = 3,
 		.frequency = CPUFREQ_TABLE_END,
 	},
+	[4] = {
+		.index = 4,
+		.frequency = CPUFREQ_TABLE_END,
+	},
 };
 
 static enum arm_opp idx2opp[] = {
+	ARM_EXTCLK,
 	ARM_50_OPP,
 	ARM_100_OPP,
 	ARM_MAX_OPP
@@ -72,13 +77,13 @@
 
 	freqs.old = policy->cur;
 	freqs.new = freq_table[idx].frequency;
-	freqs.cpu = policy->cpu;
 
 	if (freqs.old == freqs.new)
 		return 0;
 
 	/* pre-change notification */
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	for_each_cpu(freqs.cpu, policy->cpus)
+		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
 	/* request the PRCM unit for opp change */
 	if (prcmu_set_arm_opp(idx2opp[idx])) {
@@ -87,7 +92,8 @@
 	}
 
 	/* post change notification */
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	for_each_cpu(freqs.cpu, policy->cpus)
+		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
@@ -103,17 +109,19 @@
 
 static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
 {
-	int res;
-	int i;
+	int i, res;
 
 	BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table));
 
-	if (cpu_is_u8500v2() && !prcmu_is_u8400()) {
-		freq_table[0].frequency = 400000;
-		freq_table[1].frequency = 800000;
+	if (!prcmu_is_u8400()) {
+		freq_table[1].frequency = 400000;
+		freq_table[2].frequency = 800000;
 		if (prcmu_has_arm_maxopp())
-			freq_table[2].frequency = 1000000;
+			freq_table[3].frequency = 1000000;
 	}
+	pr_info("db8500-cpufreq : Available frequencies:\n");
+	for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
+		pr_info("  %d Mhz\n", freq_table[i].frequency/1000);
 
 	/* get policy fields based on the table */
 	res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
@@ -127,10 +135,6 @@
 	policy->min = policy->cpuinfo.min_freq;
 	policy->max = policy->cpuinfo.max_freq;
 	policy->cur = db8500_cpufreq_getspeed(policy->cpu);
-
-	for (i = 0; freq_table[i].frequency != policy->cur; i++)
-		;
-
 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 
 	/*
diff -druN linux-libre-3.1-gnu/drivers/cpufreq/e_powersaver.c linux-libre-3.2-gnu/drivers/cpufreq/e_powersaver.c
--- linux-libre-3.1-gnu/drivers/cpufreq/e_powersaver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/cpufreq/e_powersaver.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,11 @@
 #include <asm/msr.h>
 #include <asm/tsc.h>
 
+#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+#include <linux/acpi.h>
+#include <acpi/processor.h>
+#endif
+
 #define EPS_BRAND_C7M	0
 #define EPS_BRAND_C7	1
 #define EPS_BRAND_EDEN	2
@@ -27,11 +32,59 @@
 
 struct eps_cpu_data {
 	u32 fsb;
+#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+	u32 bios_limit;
+#endif
 	struct cpufreq_frequency_table freq_table[];
 };
 
 static struct eps_cpu_data *eps_cpu[NR_CPUS];
 
+/* Module parameters */
+static int freq_failsafe_off;
+static int voltage_failsafe_off;
+static int set_max_voltage;
+
+#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+static int ignore_acpi_limit;
+
+static struct acpi_processor_performance *eps_acpi_cpu_perf;
+
+/* Minimum necessary to get acpi_processor_get_bios_limit() working */
+static int eps_acpi_init(void)
+{
+	eps_acpi_cpu_perf = kzalloc(sizeof(struct acpi_processor_performance),
+				      GFP_KERNEL);
+	if (!eps_acpi_cpu_perf)
+		return -ENOMEM;
+
+	if (!zalloc_cpumask_var(&eps_acpi_cpu_perf->shared_cpu_map,
+								GFP_KERNEL)) {
+		kfree(eps_acpi_cpu_perf);
+		eps_acpi_cpu_perf = NULL;
+		return -ENOMEM;
+	}
+
+	if (acpi_processor_register_performance(eps_acpi_cpu_perf, 0)) {
+		free_cpumask_var(eps_acpi_cpu_perf->shared_cpu_map);
+		kfree(eps_acpi_cpu_perf);
+		eps_acpi_cpu_perf = NULL;
+		return -EIO;
+	}
+	return 0;
+}
+
+static int eps_acpi_exit(struct cpufreq_policy *policy)
+{
+	if (eps_acpi_cpu_perf) {
+		acpi_processor_unregister_performance(eps_acpi_cpu_perf, 0);
+		free_cpumask_var(eps_acpi_cpu_perf->shared_cpu_map);
+		kfree(eps_acpi_cpu_perf);
+		eps_acpi_cpu_perf = NULL;
+	}
+	return 0;
+}
+#endif
 
 static unsigned int eps_get(unsigned int cpu)
 {
@@ -164,6 +217,9 @@
 	int k, step, voltage;
 	int ret;
 	int states;
+#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+	unsigned int limit;
+#endif
 
 	if (policy->cpu != 0)
 		return -ENODEV;
@@ -244,11 +300,62 @@
 		return -EINVAL;
 	if (current_voltage > 0x1f || max_voltage > 0x1f)
 		return -EINVAL;
-	if (max_voltage < min_voltage)
+	if (max_voltage < min_voltage
+	    || current_voltage < min_voltage
+	    || current_voltage > max_voltage)
 		return -EINVAL;
 
+	/* Check for systems using underclocked CPU */
+	if (!freq_failsafe_off && max_multiplier != current_multiplier) {
+		printk(KERN_INFO "eps: Your processor is running at different "
+			"frequency then its maximum. Aborting.\n");
+		printk(KERN_INFO "eps: You can use freq_failsafe_off option "
+			"to disable this check.\n");
+		return -EINVAL;
+	}
+	if (!voltage_failsafe_off && max_voltage != current_voltage) {
+		printk(KERN_INFO "eps: Your processor is running at different "
+			"voltage then its maximum. Aborting.\n");
+		printk(KERN_INFO "eps: You can use voltage_failsafe_off "
+			"option to disable this check.\n");
+		return -EINVAL;
+	}
+
 	/* Calc FSB speed */
 	fsb = cpu_khz / current_multiplier;
+
+#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+	/* Check for ACPI processor speed limit */
+	if (!ignore_acpi_limit && !eps_acpi_init()) {
+		if (!acpi_processor_get_bios_limit(policy->cpu, &limit)) {
+			printk(KERN_INFO "eps: ACPI limit %u.%uGHz\n",
+				limit/1000000,
+				(limit%1000000)/10000);
+			eps_acpi_exit(policy);
+			/* Check if max_multiplier is in BIOS limits */
+			if (limit && max_multiplier * fsb > limit) {
+				printk(KERN_INFO "eps: Aborting.\n");
+				return -EINVAL;
+			}
+		}
+	}
+#endif
+
+	/* Allow user to set lower maximum voltage then that reported
+	 * by processor */
+	if (brand == EPS_BRAND_C7M && set_max_voltage) {
+		u32 v;
+
+		/* Change mV to something hardware can use */
+		v = (set_max_voltage - 700) / 16;
+		/* Check if voltage is within limits */
+		if (v >= min_voltage && v <= max_voltage) {
+			printk(KERN_INFO "eps: Setting %dmV as maximum.\n",
+				v * 16 + 700);
+			max_voltage = v;
+		}
+	}
+
 	/* Calc number of p-states supported */
 	if (brand == EPS_BRAND_C7M)
 		states = max_multiplier - min_multiplier + 1;
@@ -265,6 +372,9 @@
 
 	/* Copy basic values */
 	centaur->fsb = fsb;
+#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+	centaur->bios_limit = limit;
+#endif
 
 	/* Fill frequency and MSR value table */
 	f_table = &centaur->freq_table[0];
@@ -303,17 +413,7 @@
 static int eps_cpu_exit(struct cpufreq_policy *policy)
 {
 	unsigned int cpu = policy->cpu;
-	struct eps_cpu_data *centaur;
-	u32 lo, hi;
-
-	if (eps_cpu[cpu] == NULL)
-		return -ENODEV;
-	centaur = eps_cpu[cpu];
 
-	/* Get max frequency */
-	rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
-	/* Set max frequency */
-	eps_set_state(centaur, cpu, hi & 0xffff);
 	/* Bye */
 	cpufreq_frequency_table_put_attr(policy->cpu);
 	kfree(eps_cpu[cpu]);
@@ -359,6 +459,19 @@
 	cpufreq_unregister_driver(&eps_driver);
 }
 
+/* Allow user to overclock his machine or to change frequency to higher after
+ * unloading module */
+module_param(freq_failsafe_off, int, 0644);
+MODULE_PARM_DESC(freq_failsafe_off, "Disable current vs max frequency check");
+module_param(voltage_failsafe_off, int, 0644);
+MODULE_PARM_DESC(voltage_failsafe_off, "Disable current vs max voltage check");
+#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+module_param(ignore_acpi_limit, int, 0644);
+MODULE_PARM_DESC(ignore_acpi_limit, "Don't check ACPI's processor speed limit");
+#endif
+module_param(set_max_voltage, int, 0644);
+MODULE_PARM_DESC(set_max_voltage, "Set maximum CPU voltage (mV) C7-M only");
+
 MODULE_AUTHOR("Rafal Bilski <rafalbilski@interia.pl>");
 MODULE_DESCRIPTION("Enhanced PowerSaver driver for VIA C7 CPU's.");
 MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/cpufreq/exynos4210-cpufreq.c linux-libre-3.2-gnu/drivers/cpufreq/exynos4210-cpufreq.c
--- linux-libre-3.1-gnu/drivers/cpufreq/exynos4210-cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/cpufreq/exynos4210-cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,8 @@
 #include <linux/slab.h>
 #include <linux/regulator/consumer.h>
 #include <linux/cpufreq.h>
+#include <linux/notifier.h>
+#include <linux/suspend.h>
 
 #include <mach/map.h>
 #include <mach/regs-clock.h>
@@ -36,6 +38,10 @@
 static struct cpufreq_freqs freqs;
 static unsigned int memtype;
 
+static unsigned int locking_frequency;
+static bool frequency_locked;
+static DEFINE_MUTEX(cpufreq_lock);
+
 enum exynos4_memory_type {
 	DDR2 = 4,
 	LPDDR2,
@@ -405,22 +411,32 @@
 {
 	unsigned int index, old_index;
 	unsigned int arm_volt, int_volt;
+	int err = -EINVAL;
 
 	freqs.old = exynos4_getspeed(policy->cpu);
 
+	mutex_lock(&cpufreq_lock);
+
+	if (frequency_locked && target_freq != locking_frequency) {
+		err = -EAGAIN;
+		goto out;
+	}
+
 	if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
 					   freqs.old, relation, &old_index))
-		return -EINVAL;
+		goto out;
 
 	if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
 					   target_freq, relation, &index))
-		return -EINVAL;
+		goto out;
+
+	err = 0;
 
 	freqs.new = exynos4_freq_table[index].frequency;
 	freqs.cpu = policy->cpu;
 
 	if (freqs.new == freqs.old)
-		return 0;
+		goto out;
 
 	/* get the voltage value */
 	arm_volt = exynos4_volt_table[index].arm_volt;
@@ -447,10 +463,16 @@
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
-	return 0;
+out:
+	mutex_unlock(&cpufreq_lock);
+	return err;
 }
 
 #ifdef CONFIG_PM
+/*
+ * These suspend/resume are used as syscore_ops, it is already too
+ * late to set regulator voltages at this stage.
+ */
 static int exynos4_cpufreq_suspend(struct cpufreq_policy *policy)
 {
 	return 0;
@@ -462,8 +484,82 @@
 }
 #endif
 
+/**
+ * exynos4_cpufreq_pm_notifier - block CPUFREQ's activities in suspend-resume
+ *			context
+ * @notifier
+ * @pm_event
+ * @v
+ *
+ * While frequency_locked == true, target() ignores every frequency but
+ * locking_frequency. The locking_frequency value is the initial frequency,
+ * which is set by the bootloader. In order to eliminate possible
+ * inconsistency in clock values, we save and restore frequencies during
+ * suspend and resume and block CPUFREQ activities. Note that the standard
+ * suspend/resume cannot be used as they are too deep (syscore_ops) for
+ * regulator actions.
+ */
+static int exynos4_cpufreq_pm_notifier(struct notifier_block *notifier,
+				       unsigned long pm_event, void *v)
+{
+	struct cpufreq_policy *policy = cpufreq_cpu_get(0); /* boot CPU */
+	static unsigned int saved_frequency;
+	unsigned int temp;
+
+	mutex_lock(&cpufreq_lock);
+	switch (pm_event) {
+	case PM_SUSPEND_PREPARE:
+		if (frequency_locked)
+			goto out;
+		frequency_locked = true;
+
+		if (locking_frequency) {
+			saved_frequency = exynos4_getspeed(0);
+
+			mutex_unlock(&cpufreq_lock);
+			exynos4_target(policy, locking_frequency,
+				       CPUFREQ_RELATION_H);
+			mutex_lock(&cpufreq_lock);
+		}
+
+		break;
+	case PM_POST_SUSPEND:
+
+		if (saved_frequency) {
+			/*
+			 * While frequency_locked, only locking_frequency
+			 * is valid for target(). In order to use
+			 * saved_frequency while keeping frequency_locked,
+			 * we temporarly overwrite locking_frequency.
+			 */
+			temp = locking_frequency;
+			locking_frequency = saved_frequency;
+
+			mutex_unlock(&cpufreq_lock);
+			exynos4_target(policy, locking_frequency,
+				       CPUFREQ_RELATION_H);
+			mutex_lock(&cpufreq_lock);
+
+			locking_frequency = temp;
+		}
+
+		frequency_locked = false;
+		break;
+	}
+out:
+	mutex_unlock(&cpufreq_lock);
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block exynos4_cpufreq_nb = {
+	.notifier_call = exynos4_cpufreq_pm_notifier,
+};
+
 static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
+	int ret;
+
 	policy->cur = policy->min = policy->max = exynos4_getspeed(policy->cpu);
 
 	cpufreq_frequency_table_get_attr(exynos4_freq_table, policy->cpu);
@@ -479,16 +575,35 @@
 	 */
 	cpumask_setall(policy->cpus);
 
-	return cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table);
+	ret = cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table);
+	if (ret)
+		return ret;
+
+	cpufreq_frequency_table_get_attr(exynos4_freq_table, policy->cpu);
+
+	return 0;
+}
+
+static int exynos4_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+	cpufreq_frequency_table_put_attr(policy->cpu);
+	return 0;
 }
 
+static struct freq_attr *exynos4_cpufreq_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
+
 static struct cpufreq_driver exynos4_driver = {
 	.flags		= CPUFREQ_STICKY,
 	.verify		= exynos4_verify_speed,
 	.target		= exynos4_target,
 	.get		= exynos4_getspeed,
 	.init		= exynos4_cpufreq_cpu_init,
+	.exit		= exynos4_cpufreq_cpu_exit,
 	.name		= "exynos4_cpufreq",
+	.attr		= exynos4_cpufreq_attr,
 #ifdef CONFIG_PM
 	.suspend	= exynos4_cpufreq_suspend,
 	.resume		= exynos4_cpufreq_resume,
@@ -501,6 +616,8 @@
 	if (IS_ERR(cpu_clk))
 		return PTR_ERR(cpu_clk);
 
+	locking_frequency = exynos4_getspeed(0);
+
 	moutcore = clk_get(NULL, "moutcore");
 	if (IS_ERR(moutcore))
 		goto out;
@@ -540,6 +657,8 @@
 		printk(KERN_DEBUG "%s: memtype= 0x%x\n", __func__, memtype);
 	}
 
+	register_pm_notifier(&exynos4_cpufreq_nb);
+
 	return cpufreq_register_driver(&exynos4_driver);
 
 out:
diff -druN linux-libre-3.1-gnu/drivers/cpufreq/s3c64xx-cpufreq.c linux-libre-3.2-gnu/drivers/cpufreq/s3c64xx-cpufreq.c
--- linux-libre-3.1-gnu/drivers/cpufreq/s3c64xx-cpufreq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/cpufreq/s3c64xx-cpufreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/regulator/consumer.h>
+#include <linux/module.h>
 
 static struct clk *armclk;
 static struct regulator *vddarm;
diff -druN linux-libre-3.1-gnu/drivers/cpuidle/cpuidle.c linux-libre-3.2-gnu/drivers/cpuidle/cpuidle.c
--- linux-libre-3.1-gnu/drivers/cpuidle/cpuidle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/cpuidle/cpuidle.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,11 +12,12 @@
 #include <linux/mutex.h>
 #include <linux/sched.h>
 #include <linux/notifier.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
 #include <linux/cpu.h>
 #include <linux/cpuidle.h>
 #include <linux/ktime.h>
 #include <linux/hrtimer.h>
+#include <linux/module.h>
 #include <trace/events/power.h>
 
 #include "cpuidle.h"
@@ -61,8 +62,9 @@
 int cpuidle_idle_call(void)
 {
 	struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
+	struct cpuidle_driver *drv = cpuidle_get_driver();
 	struct cpuidle_state *target_state;
-	int next_state;
+	int next_state, entered_state;
 
 	if (off)
 		return -ENODEV;
@@ -83,45 +85,36 @@
 	hrtimer_peek_ahead_timers();
 #endif
 
-	/*
-	 * Call the device's prepare function before calling the
-	 * governor's select function.  ->prepare gives the device's
-	 * cpuidle driver a chance to update any dynamic information
-	 * of its cpuidle states for the current idle period, e.g.
-	 * state availability, latencies, residencies, etc.
-	 */
-	if (dev->prepare)
-		dev->prepare(dev);
-
 	/* ask the governor for the next state */
-	next_state = cpuidle_curr_governor->select(dev);
+	next_state = cpuidle_curr_governor->select(drv, dev);
 	if (need_resched()) {
 		local_irq_enable();
 		return 0;
 	}
 
-	target_state = &dev->states[next_state];
-
-	/* enter the state and update stats */
-	dev->last_state = target_state;
+	target_state = &drv->states[next_state];
 
 	trace_power_start(POWER_CSTATE, next_state, dev->cpu);
 	trace_cpu_idle(next_state, dev->cpu);
 
-	dev->last_residency = target_state->enter(dev, target_state);
+	entered_state = target_state->enter(dev, drv, next_state);
 
 	trace_power_end(dev->cpu);
 	trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu);
 
-	if (dev->last_state)
-		target_state = dev->last_state;
-
-	target_state->time += (unsigned long long)dev->last_residency;
-	target_state->usage++;
+	if (entered_state >= 0) {
+		/* Update cpuidle counters */
+		/* This can be moved to within driver enter routine
+		 * but that results in multiple copies of same code.
+		 */
+		dev->states_usage[entered_state].time +=
+				(unsigned long long)dev->last_residency;
+		dev->states_usage[entered_state].usage++;
+	}
 
 	/* give the governor an opportunity to reflect on the outcome */
 	if (cpuidle_curr_governor->reflect)
-		cpuidle_curr_governor->reflect(dev);
+		cpuidle_curr_governor->reflect(dev, entered_state);
 
 	return 0;
 }
@@ -172,11 +165,11 @@
 EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
 
 #ifdef CONFIG_ARCH_HAS_CPU_RELAX
-static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st)
+static int poll_idle(struct cpuidle_device *dev,
+		struct cpuidle_driver *drv, int index)
 {
 	ktime_t	t1, t2;
 	s64 diff;
-	int ret;
 
 	t1 = ktime_get();
 	local_irq_enable();
@@ -188,15 +181,14 @@
 	if (diff > INT_MAX)
 		diff = INT_MAX;
 
-	ret = (int) diff;
-	return ret;
+	dev->last_residency = (int) diff;
+
+	return index;
 }
 
-static void poll_idle_init(struct cpuidle_device *dev)
+static void poll_idle_init(struct cpuidle_driver *drv)
 {
-	struct cpuidle_state *state = &dev->states[0];
-
-	cpuidle_set_statedata(state, NULL);
+	struct cpuidle_state *state = &drv->states[0];
 
 	snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
 	snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
@@ -207,7 +199,7 @@
 	state->enter = poll_idle;
 }
 #else
-static void poll_idle_init(struct cpuidle_device *dev) {}
+static void poll_idle_init(struct cpuidle_driver *drv) {}
 #endif /* CONFIG_ARCH_HAS_CPU_RELAX */
 
 /**
@@ -234,21 +226,20 @@
 			return ret;
 	}
 
-	poll_idle_init(dev);
+	poll_idle_init(cpuidle_get_driver());
 
 	if ((ret = cpuidle_add_state_sysfs(dev)))
 		return ret;
 
 	if (cpuidle_curr_governor->enable &&
-	    (ret = cpuidle_curr_governor->enable(dev)))
+	    (ret = cpuidle_curr_governor->enable(cpuidle_get_driver(), dev)))
 		goto fail_sysfs;
 
 	for (i = 0; i < dev->state_count; i++) {
-		dev->states[i].usage = 0;
-		dev->states[i].time = 0;
+		dev->states_usage[i].usage = 0;
+		dev->states_usage[i].time = 0;
 	}
 	dev->last_residency = 0;
-	dev->last_state = NULL;
 
 	smp_wmb();
 
@@ -282,7 +273,7 @@
 	dev->enabled = 0;
 
 	if (cpuidle_curr_governor->disable)
-		cpuidle_curr_governor->disable(dev);
+		cpuidle_curr_governor->disable(cpuidle_get_driver(), dev);
 
 	cpuidle_remove_state_sysfs(dev);
 	enabled_devices--;
@@ -310,26 +301,6 @@
 
 	init_completion(&dev->kobj_unregister);
 
-	/*
-	 * cpuidle driver should set the dev->power_specified bit
-	 * before registering the device if the driver provides
-	 * power_usage numbers.
-	 *
-	 * For those devices whose ->power_specified is not set,
-	 * we fill in power_usage with decreasing values as the
-	 * cpuidle code has an implicit assumption that state Cn
-	 * uses less power than C(n-1).
-	 *
-	 * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
-	 * an power value of -1.  So we use -2, -3, etc, for other
-	 * c-states.
-	 */
-	if (!dev->power_specified) {
-		int i;
-		for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++)
-			dev->states[i].power_usage = -1 - i;
-	}
-
 	per_cpu(cpuidle_devices, dev->cpu) = dev;
 	list_add(&dev->device_list, &cpuidle_detected_devices);
 	if ((ret = cpuidle_add_sysfs(sys_dev))) {
diff -druN linux-libre-3.1-gnu/drivers/cpuidle/driver.c linux-libre-3.2-gnu/drivers/cpuidle/driver.c
--- linux-libre-3.1-gnu/drivers/cpuidle/driver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/cpuidle/driver.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,30 @@
 static struct cpuidle_driver *cpuidle_curr_driver;
 DEFINE_SPINLOCK(cpuidle_driver_lock);
 
+static void __cpuidle_register_driver(struct cpuidle_driver *drv)
+{
+	int i;
+	/*
+	 * cpuidle driver should set the drv->power_specified bit
+	 * before registering if the driver provides
+	 * power_usage numbers.
+	 *
+	 * If power_specified is not set,
+	 * we fill in power_usage with decreasing values as the
+	 * cpuidle code has an implicit assumption that state Cn
+	 * uses less power than C(n-1).
+	 *
+	 * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
+	 * an power value of -1.  So we use -2, -3, etc, for other
+	 * c-states.
+	 */
+	if (!drv->power_specified) {
+		for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++)
+			drv->states[i].power_usage = -1 - i;
+	}
+}
+
+
 /**
  * cpuidle_register_driver - registers a driver
  * @drv: the driver
@@ -34,6 +58,7 @@
 		spin_unlock(&cpuidle_driver_lock);
 		return -EBUSY;
 	}
+	__cpuidle_register_driver(drv);
 	cpuidle_curr_driver = drv;
 	spin_unlock(&cpuidle_driver_lock);
 
diff -druN linux-libre-3.1-gnu/drivers/cpuidle/governors/ladder.c linux-libre-3.2-gnu/drivers/cpuidle/governors/ladder.c
--- linux-libre-3.1-gnu/drivers/cpuidle/governors/ladder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/cpuidle/governors/ladder.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,8 +14,8 @@
 
 #include <linux/kernel.h>
 #include <linux/cpuidle.h>
-#include <linux/pm_qos_params.h>
-#include <linux/moduleparam.h>
+#include <linux/pm_qos.h>
+#include <linux/module.h>
 #include <linux/jiffies.h>
 
 #include <asm/io.h>
@@ -60,9 +60,11 @@
 
 /**
  * ladder_select_state - selects the next state to enter
+ * @drv: cpuidle driver
  * @dev: the CPU
  */
-static int ladder_select_state(struct cpuidle_device *dev)
+static int ladder_select_state(struct cpuidle_driver *drv,
+				struct cpuidle_device *dev)
 {
 	struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
 	struct ladder_device_state *last_state;
@@ -77,15 +79,17 @@
 
 	last_state = &ldev->states[last_idx];
 
-	if (dev->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID)
-		last_residency = cpuidle_get_last_residency(dev) - dev->states[last_idx].exit_latency;
+	if (drv->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID) {
+		last_residency = cpuidle_get_last_residency(dev) - \
+					 drv->states[last_idx].exit_latency;
+	}
 	else
 		last_residency = last_state->threshold.promotion_time + 1;
 
 	/* consider promotion */
-	if (last_idx < dev->state_count - 1 &&
+	if (last_idx < drv->state_count - 1 &&
 	    last_residency > last_state->threshold.promotion_time &&
-	    dev->states[last_idx + 1].exit_latency <= latency_req) {
+	    drv->states[last_idx + 1].exit_latency <= latency_req) {
 		last_state->stats.promotion_count++;
 		last_state->stats.demotion_count = 0;
 		if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) {
@@ -96,11 +100,11 @@
 
 	/* consider demotion */
 	if (last_idx > CPUIDLE_DRIVER_STATE_START &&
-	    dev->states[last_idx].exit_latency > latency_req) {
+	    drv->states[last_idx].exit_latency > latency_req) {
 		int i;
 
 		for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) {
-			if (dev->states[i].exit_latency <= latency_req)
+			if (drv->states[i].exit_latency <= latency_req)
 				break;
 		}
 		ladder_do_selection(ldev, last_idx, i);
@@ -123,9 +127,11 @@
 
 /**
  * ladder_enable_device - setup for the governor
+ * @drv: cpuidle driver
  * @dev: the CPU
  */
-static int ladder_enable_device(struct cpuidle_device *dev)
+static int ladder_enable_device(struct cpuidle_driver *drv,
+				struct cpuidle_device *dev)
 {
 	int i;
 	struct ladder_device *ldev = &per_cpu(ladder_devices, dev->cpu);
@@ -134,8 +140,8 @@
 
 	ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START;
 
-	for (i = 0; i < dev->state_count; i++) {
-		state = &dev->states[i];
+	for (i = 0; i < drv->state_count; i++) {
+		state = &drv->states[i];
 		lstate = &ldev->states[i];
 
 		lstate->stats.promotion_count = 0;
@@ -144,7 +150,7 @@
 		lstate->threshold.promotion_count = PROMOTION_COUNT;
 		lstate->threshold.demotion_count = DEMOTION_COUNT;
 
-		if (i < dev->state_count - 1)
+		if (i < drv->state_count - 1)
 			lstate->threshold.promotion_time = state->exit_latency;
 		if (i > 0)
 			lstate->threshold.demotion_time = state->exit_latency;
@@ -153,11 +159,24 @@
 	return 0;
 }
 
+/**
+ * ladder_reflect - update the correct last_state_idx
+ * @dev: the CPU
+ * @index: the index of actual state entered
+ */
+static void ladder_reflect(struct cpuidle_device *dev, int index)
+{
+	struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
+	if (index > 0)
+		ldev->last_state_idx = index;
+}
+
 static struct cpuidle_governor ladder_governor = {
 	.name =		"ladder",
 	.rating =	10,
 	.enable =	ladder_enable_device,
 	.select =	ladder_select_state,
+	.reflect =	ladder_reflect,
 	.owner =	THIS_MODULE,
 };
 
diff -druN linux-libre-3.1-gnu/drivers/cpuidle/governors/menu.c linux-libre-3.2-gnu/drivers/cpuidle/governors/menu.c
--- linux-libre-3.1-gnu/drivers/cpuidle/governors/menu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/cpuidle/governors/menu.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,13 +12,14 @@
 
 #include <linux/kernel.h>
 #include <linux/cpuidle.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
 #include <linux/time.h>
 #include <linux/ktime.h>
 #include <linux/hrtimer.h>
 #include <linux/tick.h>
 #include <linux/sched.h>
 #include <linux/math64.h>
+#include <linux/module.h>
 
 #define BUCKETS 12
 #define INTERVALS 8
@@ -182,7 +183,7 @@
 
 static DEFINE_PER_CPU(struct menu_device, menu_devices);
 
-static void menu_update(struct cpuidle_device *dev);
+static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev);
 
 /* This implements DIV_ROUND_CLOSEST but avoids 64 bit division */
 static u64 div_round64(u64 dividend, u32 divisor)
@@ -228,9 +229,10 @@
 
 /**
  * menu_select - selects the next idle state to enter
+ * @drv: cpuidle driver containing state data
  * @dev: the CPU
  */
-static int menu_select(struct cpuidle_device *dev)
+static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 {
 	struct menu_device *data = &__get_cpu_var(menu_devices);
 	int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
@@ -240,7 +242,7 @@
 	struct timespec t;
 
 	if (data->needs_update) {
-		menu_update(dev);
+		menu_update(drv, dev);
 		data->needs_update = 0;
 	}
 
@@ -285,11 +287,9 @@
 	 * Find the idle state with the lowest power while satisfying
 	 * our constraints.
 	 */
-	for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) {
-		struct cpuidle_state *s = &dev->states[i];
+	for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
+		struct cpuidle_state *s = &drv->states[i];
 
-		if (s->flags & CPUIDLE_FLAG_IGNORE)
-			continue;
 		if (s->target_residency > data->predicted_us)
 			continue;
 		if (s->exit_latency > latency_req)
@@ -310,26 +310,30 @@
 /**
  * menu_reflect - records that data structures need update
  * @dev: the CPU
+ * @index: the index of actual entered state
  *
  * NOTE: it's important to be fast here because this operation will add to
  *       the overall exit latency.
  */
-static void menu_reflect(struct cpuidle_device *dev)
+static void menu_reflect(struct cpuidle_device *dev, int index)
 {
 	struct menu_device *data = &__get_cpu_var(menu_devices);
-	data->needs_update = 1;
+	data->last_state_idx = index;
+	if (index >= 0)
+		data->needs_update = 1;
 }
 
 /**
  * menu_update - attempts to guess what happened after entry
+ * @drv: cpuidle driver containing state data
  * @dev: the CPU
  */
-static void menu_update(struct cpuidle_device *dev)
+static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 {
 	struct menu_device *data = &__get_cpu_var(menu_devices);
 	int last_idx = data->last_state_idx;
 	unsigned int last_idle_us = cpuidle_get_last_residency(dev);
-	struct cpuidle_state *target = &dev->states[last_idx];
+	struct cpuidle_state *target = &drv->states[last_idx];
 	unsigned int measured_us;
 	u64 new_factor;
 
@@ -383,9 +387,11 @@
 
 /**
  * menu_enable_device - scans a CPU's states and does setup
+ * @drv: cpuidle driver
  * @dev: the CPU
  */
-static int menu_enable_device(struct cpuidle_device *dev)
+static int menu_enable_device(struct cpuidle_driver *drv,
+				struct cpuidle_device *dev)
 {
 	struct menu_device *data = &per_cpu(menu_devices, dev->cpu);
 
diff -druN linux-libre-3.1-gnu/drivers/cpuidle/sysfs.c linux-libre-3.2-gnu/drivers/cpuidle/sysfs.c
--- linux-libre-3.1-gnu/drivers/cpuidle/sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/cpuidle/sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -216,7 +216,8 @@
 
 struct cpuidle_state_attr {
 	struct attribute attr;
-	ssize_t (*show)(struct cpuidle_state *, char *);
+	ssize_t (*show)(struct cpuidle_state *, \
+					struct cpuidle_state_usage *, char *);
 	ssize_t (*store)(struct cpuidle_state *, const char *, size_t);
 };
 
@@ -224,19 +225,22 @@
 static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0444, show, NULL)
 
 #define define_show_state_function(_name) \
-static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
+static ssize_t show_state_##_name(struct cpuidle_state *state, \
+			 struct cpuidle_state_usage *state_usage, char *buf) \
 { \
 	return sprintf(buf, "%u\n", state->_name);\
 }
 
 #define define_show_state_ull_function(_name) \
-static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
+static ssize_t show_state_##_name(struct cpuidle_state *state, \
+			struct cpuidle_state_usage *state_usage, char *buf) \
 { \
-	return sprintf(buf, "%llu\n", state->_name);\
+	return sprintf(buf, "%llu\n", state_usage->_name);\
 }
 
 #define define_show_state_str_function(_name) \
-static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
+static ssize_t show_state_##_name(struct cpuidle_state *state, \
+			struct cpuidle_state_usage *state_usage, char *buf) \
 { \
 	if (state->_name[0] == '\0')\
 		return sprintf(buf, "<null>\n");\
@@ -269,16 +273,18 @@
 
 #define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
 #define kobj_to_state(k) (kobj_to_state_obj(k)->state)
+#define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
 #define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
 static ssize_t cpuidle_state_show(struct kobject * kobj,
 	struct attribute * attr ,char * buf)
 {
 	int ret = -EIO;
 	struct cpuidle_state *state = kobj_to_state(kobj);
+	struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj);
 	struct cpuidle_state_attr * cattr = attr_to_stateattr(attr);
 
 	if (cattr->show)
-		ret = cattr->show(state, buf);
+		ret = cattr->show(state, state_usage, buf);
 
 	return ret;
 }
@@ -316,13 +322,15 @@
 {
 	int i, ret = -ENOMEM;
 	struct cpuidle_state_kobj *kobj;
+	struct cpuidle_driver *drv = cpuidle_get_driver();
 
 	/* state statistics */
 	for (i = 0; i < device->state_count; i++) {
 		kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
 		if (!kobj)
 			goto error_state;
-		kobj->state = &device->states[i];
+		kobj->state = &drv->states[i];
+		kobj->state_usage = &device->states_usage[i];
 		init_completion(&kobj->kobj_unregister);
 
 		ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, &device->kobj,
diff -druN linux-libre-3.1-gnu/drivers/crypto/hifn_795x.c linux-libre-3.2-gnu/drivers/crypto/hifn_795x.c
--- linux-libre-3.1-gnu/drivers/crypto/hifn_795x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/crypto/hifn_795x.c	2012-01-04 18:55:44.000000000 -0500
@@ -2744,10 +2744,8 @@
 	unsigned int freq;
 	int err;
 
-	if (sizeof(dma_addr_t) > 4) {
-		printk(KERN_INFO "HIFN supports only 32-bit addresses.\n");
-		return -EINVAL;
-	}
+	/* HIFN supports only 32-bit addresses */
+	BUILD_BUG_ON(sizeof(dma_addr_t) != 4);
 
 	if (strncmp(hifn_pll_ref, "ext", 3) &&
 	    strncmp(hifn_pll_ref, "pci", 3)) {
diff -druN linux-libre-3.1-gnu/drivers/crypto/Kconfig linux-libre-3.2-gnu/drivers/crypto/Kconfig
--- linux-libre-3.1-gnu/drivers/crypto/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/crypto/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -200,6 +200,7 @@
 	select CRYPTO_BLKCIPHER
 	select HW_RANDOM if CRYPTO_DEV_HIFN_795X_RNG
 	depends on PCI
+	depends on !ARCH_DMA_ADDR_T_64BIT
 	help
 	  This option allows you to have support for HIFN 795x crypto adapters.
 
@@ -266,7 +267,7 @@
 
 config CRYPTO_DEV_PICOXCELL
 	tristate "Support for picoXcell IPSEC and Layer2 crypto engines"
-	depends on ARCH_PICOXCELL
+	depends on ARCH_PICOXCELL && HAVE_CLK
 	select CRYPTO_AES
 	select CRYPTO_AUTHENC
 	select CRYPTO_ALGAPI
diff -druN linux-libre-3.1-gnu/drivers/crypto/mv_cesa.c linux-libre-3.2-gnu/drivers/crypto/mv_cesa.c
--- linux-libre-3.1-gnu/drivers/crypto/mv_cesa.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/crypto/mv_cesa.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <crypto/internal/hash.h>
 #include <crypto/sha.h>
 
@@ -342,11 +343,13 @@
 		else
 			op.config |= CFG_MID_FRAG;
 
-		writel(req_ctx->state[0], cpg->reg + DIGEST_INITIAL_VAL_A);
-		writel(req_ctx->state[1], cpg->reg + DIGEST_INITIAL_VAL_B);
-		writel(req_ctx->state[2], cpg->reg + DIGEST_INITIAL_VAL_C);
-		writel(req_ctx->state[3], cpg->reg + DIGEST_INITIAL_VAL_D);
-		writel(req_ctx->state[4], cpg->reg + DIGEST_INITIAL_VAL_E);
+		if (first_block) {
+			writel(req_ctx->state[0], cpg->reg + DIGEST_INITIAL_VAL_A);
+			writel(req_ctx->state[1], cpg->reg + DIGEST_INITIAL_VAL_B);
+			writel(req_ctx->state[2], cpg->reg + DIGEST_INITIAL_VAL_C);
+			writel(req_ctx->state[3], cpg->reg + DIGEST_INITIAL_VAL_D);
+			writel(req_ctx->state[4], cpg->reg + DIGEST_INITIAL_VAL_E);
+		}
 	}
 
 	memcpy(cpg->sram + SRAM_CONFIG, &op, sizeof(struct sec_accel_config));
diff -druN linux-libre-3.1-gnu/drivers/crypto/n2_core.c linux-libre-3.2-gnu/drivers/crypto/n2_core.c
--- linux-libre-3.1-gnu/drivers/crypto/n2_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/crypto/n2_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -1006,9 +1006,9 @@
 
 	spin_unlock_irqrestore(&qp->lock, flags);
 
+out:
 	put_cpu();
 
-out:
 	n2_chunk_complete(req, NULL);
 	return err;
 }
@@ -1096,9 +1096,9 @@
 
 	spin_unlock_irqrestore(&qp->lock, flags);
 
+out:
 	put_cpu();
 
-out:
 	n2_chunk_complete(req, err ? NULL : final_iv_addr);
 	return err;
 }
diff -druN linux-libre-3.1-gnu/drivers/crypto/padlock-aes.c linux-libre-3.2-gnu/drivers/crypto/padlock-aes.c
--- linux-libre-3.1-gnu/drivers/crypto/padlock-aes.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/crypto/padlock-aes.c	2012-01-04 18:55:44.000000000 -0500
@@ -508,10 +508,8 @@
 	int ret;
 	struct cpuinfo_x86 *c = &cpu_data(0);
 
-	if (!cpu_has_xcrypt) {
-		printk(KERN_NOTICE PFX "VIA PadLock not detected.\n");
+	if (!cpu_has_xcrypt)
 		return -ENODEV;
-	}
 
 	if (!cpu_has_xcrypt_enabled) {
 		printk(KERN_NOTICE PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n");
diff -druN linux-libre-3.1-gnu/drivers/crypto/picoxcell_crypto.c linux-libre-3.2-gnu/drivers/crypto/picoxcell_crypto.c
--- linux-libre-3.1-gnu/drivers/crypto/picoxcell_crypto.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/crypto/picoxcell_crypto.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 #include <linux/io.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/rtnetlink.h>
@@ -1241,8 +1242,8 @@
 	spin_unlock_irqrestore(&engine->hw_lock, flags);
 
 	list_for_each_entry_safe(req, tmp, &completed, list) {
-		req->complete(req);
 		list_del(&req->list);
+		req->complete(req);
 	}
 }
 
@@ -1657,10 +1658,33 @@
 	},
 };
 
-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)
+#ifdef CONFIG_OF
+static const struct of_device_id spacc_of_id_table[] = {
+	{ .compatible = "picochip,spacc-ipsec" },
+	{ .compatible = "picochip,spacc-l2" },
+	{}
+};
+#else /* CONFIG_OF */
+#define spacc_of_id_table NULL
+#endif /* CONFIG_OF */
+
+static bool spacc_is_compatible(struct platform_device *pdev,
+				const char *spacc_type)
+{
+	const struct platform_device_id *platid = platform_get_device_id(pdev);
+
+	if (platid && !strcmp(platid->name, spacc_type))
+		return true;
+
+#ifdef CONFIG_OF
+	if (of_device_is_compatible(pdev->dev.of_node, spacc_type))
+		return true;
+#endif /* CONFIG_OF */
+
+	return false;
+}
+
+static int __devinit spacc_probe(struct platform_device *pdev)
 {
 	int i, err, ret = -EINVAL;
 	struct resource *mem, *irq;
@@ -1669,13 +1693,25 @@
 	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);
+	if (spacc_is_compatible(pdev, "picochip,spacc-ipsec")) {
+		engine->max_ctxs	= SPACC_CRYPTO_IPSEC_MAX_CTXS;
+		engine->cipher_pg_sz	= SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ;
+		engine->hash_pg_sz	= SPACC_CRYPTO_IPSEC_HASH_PG_SZ;
+		engine->fifo_sz		= SPACC_CRYPTO_IPSEC_FIFO_SZ;
+		engine->algs		= ipsec_engine_algs;
+		engine->num_algs	= ARRAY_SIZE(ipsec_engine_algs);
+	} else if (spacc_is_compatible(pdev, "picochip,spacc-l2")) {
+		engine->max_ctxs	= SPACC_CRYPTO_L2_MAX_CTXS;
+		engine->cipher_pg_sz	= SPACC_CRYPTO_L2_CIPHER_PG_SZ;
+		engine->hash_pg_sz	= SPACC_CRYPTO_L2_HASH_PG_SZ;
+		engine->fifo_sz		= SPACC_CRYPTO_L2_FIFO_SZ;
+		engine->algs		= l2_engine_algs;
+		engine->num_algs	= ARRAY_SIZE(l2_engine_algs);
+	} else {
+		return -EINVAL;
+	}
+
+	engine->name = dev_name(&pdev->dev);
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -1711,7 +1747,7 @@
 
 	spin_lock_init(&engine->hw_lock);
 
-	engine->clk = clk_get(&pdev->dev, NULL);
+	engine->clk = clk_get(&pdev->dev, "ref");
 	if (IS_ERR(engine->clk)) {
 		dev_info(&pdev->dev, "clk unavailable\n");
 		device_remove_file(&pdev->dev, &dev_attr_stat_irq_thresh);
@@ -1800,72 +1836,33 @@
 	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 const struct platform_device_id spacc_id_table[] = {
+	{ "picochip,spacc-ipsec", },
+	{ "picochip,spacc-l2", },
 };
 
-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,
+static struct platform_driver spacc_driver = {
+	.probe		= spacc_probe,
 	.remove		= __devexit_p(spacc_remove),
 	.driver		= {
-		.name	= "picoxcell-l2",
+		.name	= "picochip,spacc",
 #ifdef CONFIG_PM
 		.pm	= &spacc_pm_ops,
 #endif /* CONFIG_PM */
+		.of_match_table	= spacc_of_id_table,
 	},
+	.id_table	= spacc_id_table,
 };
 
 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;
+	return platform_driver_register(&spacc_driver);
 }
 module_init(spacc_init);
 
 static void __exit spacc_exit(void)
 {
-	platform_driver_unregister(&ipsec_driver);
-	platform_driver_unregister(&l2_driver);
+	platform_driver_unregister(&spacc_driver);
 }
 module_exit(spacc_exit);
 
diff -druN linux-libre-3.1-gnu/drivers/crypto/talitos.c linux-libre-3.2-gnu/drivers/crypto/talitos.c
--- linux-libre-3.1-gnu/drivers/crypto/talitos.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/crypto/talitos.c	2012-01-04 18:55:44.000000000 -0500
@@ -416,7 +416,7 @@
 /*
  * locate current (offending) descriptor
  */
-static struct talitos_desc *current_desc(struct device *dev, int ch)
+static u32 current_desc_hdr(struct device *dev, int ch)
 {
 	struct talitos_private *priv = dev_get_drvdata(dev);
 	int tail = priv->chan[ch].tail;
@@ -428,23 +428,25 @@
 		tail = (tail + 1) & (priv->fifo_len - 1);
 		if (tail == priv->chan[ch].tail) {
 			dev_err(dev, "couldn't locate current descriptor\n");
-			return NULL;
+			return 0;
 		}
 	}
 
-	return priv->chan[ch].fifo[tail].desc;
+	return priv->chan[ch].fifo[tail].desc->hdr;
 }
 
 /*
  * user diagnostics; report root cause of error based on execution unit status
  */
-static void report_eu_error(struct device *dev, int ch,
-			    struct talitos_desc *desc)
+static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
 {
 	struct talitos_private *priv = dev_get_drvdata(dev);
 	int i;
 
-	switch (desc->hdr & DESC_HDR_SEL0_MASK) {
+	if (!desc_hdr)
+		desc_hdr = in_be32(priv->reg + TALITOS_DESCBUF(ch));
+
+	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
 	case DESC_HDR_SEL0_AFEU:
 		dev_err(dev, "AFEUISR 0x%08x_%08x\n",
 			in_be32(priv->reg + TALITOS_AFEUISR),
@@ -488,7 +490,7 @@
 		break;
 	}
 
-	switch (desc->hdr & DESC_HDR_SEL1_MASK) {
+	switch (desc_hdr & DESC_HDR_SEL1_MASK) {
 	case DESC_HDR_SEL1_MDEUA:
 	case DESC_HDR_SEL1_MDEUB:
 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
@@ -550,7 +552,7 @@
 		if (v_lo & TALITOS_CCPSR_LO_IEU)
 			dev_err(dev, "invalid execution unit error\n");
 		if (v_lo & TALITOS_CCPSR_LO_EU)
-			report_eu_error(dev, ch, current_desc(dev, ch));
+			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
 		if (v_lo & TALITOS_CCPSR_LO_GB)
 			dev_err(dev, "gather boundary error\n");
 		if (v_lo & TALITOS_CCPSR_LO_GRL)
diff -druN linux-libre-3.1-gnu/drivers/dca/dca-core.c linux-libre-3.2-gnu/drivers/dca/dca-core.c
--- linux-libre-3.1-gnu/drivers/dca/dca-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dca/dca-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/device.h>
 #include <linux/dca.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define DCA_VERSION "1.12.1"
 
@@ -35,7 +36,7 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Intel Corporation");
 
-static DEFINE_SPINLOCK(dca_lock);
+static DEFINE_RAW_SPINLOCK(dca_lock);
 
 static LIST_HEAD(dca_domains);
 
@@ -101,10 +102,10 @@
 
 	INIT_LIST_HEAD(&unregistered_providers);
 
-	spin_lock_irqsave(&dca_lock, flags);
+	raw_spin_lock_irqsave(&dca_lock, flags);
 
 	if (list_empty(&dca_domains)) {
-		spin_unlock_irqrestore(&dca_lock, flags);
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
 		return;
 	}
 
@@ -116,7 +117,7 @@
 
 	dca_free_domain(domain);
 
-	spin_unlock_irqrestore(&dca_lock, flags);
+	raw_spin_unlock_irqrestore(&dca_lock, flags);
 
 	list_for_each_entry_safe(dca, _dca, &unregistered_providers, node) {
 		dca_sysfs_remove_provider(dca);
@@ -144,13 +145,8 @@
 	domain = dca_find_domain(rc);
 
 	if (!domain) {
-		if (dca_provider_ioat_ver_3_0(dev) && !list_empty(&dca_domains)) {
+		if (dca_provider_ioat_ver_3_0(dev) && !list_empty(&dca_domains))
 			dca_providers_blocked = 1;
-		} else {
-			domain = dca_allocate_domain(rc);
-			if (domain)
-				list_add(&domain->node, &dca_domains);
-		}
 	}
 
 	return domain;
@@ -198,19 +194,19 @@
 	if (!dev)
 		return -EFAULT;
 
-	spin_lock_irqsave(&dca_lock, flags);
+	raw_spin_lock_irqsave(&dca_lock, flags);
 
 	/* check if the requester has not been added already */
 	dca = dca_find_provider_by_dev(dev);
 	if (dca) {
-		spin_unlock_irqrestore(&dca_lock, flags);
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
 		return -EEXIST;
 	}
 
 	pci_rc = dca_pci_rc_from_dev(dev);
 	domain = dca_find_domain(pci_rc);
 	if (!domain) {
-		spin_unlock_irqrestore(&dca_lock, flags);
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
 		return -ENODEV;
 	}
 
@@ -220,17 +216,17 @@
 			break;
 	}
 
-	spin_unlock_irqrestore(&dca_lock, flags);
+	raw_spin_unlock_irqrestore(&dca_lock, flags);
 
 	if (slot < 0)
 		return slot;
 
 	err = dca_sysfs_add_req(dca, dev, slot);
 	if (err) {
-		spin_lock_irqsave(&dca_lock, flags);
+		raw_spin_lock_irqsave(&dca_lock, flags);
 		if (dca == dca_find_provider_by_dev(dev))
 			dca->ops->remove_requester(dca, dev);
-		spin_unlock_irqrestore(&dca_lock, flags);
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
 		return err;
 	}
 
@@ -251,14 +247,14 @@
 	if (!dev)
 		return -EFAULT;
 
-	spin_lock_irqsave(&dca_lock, flags);
+	raw_spin_lock_irqsave(&dca_lock, flags);
 	dca = dca_find_provider_by_dev(dev);
 	if (!dca) {
-		spin_unlock_irqrestore(&dca_lock, flags);
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
 		return -ENODEV;
 	}
 	slot = dca->ops->remove_requester(dca, dev);
-	spin_unlock_irqrestore(&dca_lock, flags);
+	raw_spin_unlock_irqrestore(&dca_lock, flags);
 
 	if (slot < 0)
 		return slot;
@@ -280,16 +276,16 @@
 	u8 tag;
 	unsigned long flags;
 
-	spin_lock_irqsave(&dca_lock, flags);
+	raw_spin_lock_irqsave(&dca_lock, flags);
 
 	dca = dca_find_provider_by_dev(dev);
 	if (!dca) {
-		spin_unlock_irqrestore(&dca_lock, flags);
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
 		return -ENODEV;
 	}
 	tag = dca->ops->get_tag(dca, dev, cpu);
 
-	spin_unlock_irqrestore(&dca_lock, flags);
+	raw_spin_unlock_irqrestore(&dca_lock, flags);
 	return tag;
 }
 
@@ -360,36 +356,51 @@
 {
 	int err;
 	unsigned long flags;
-	struct dca_domain *domain;
+	struct dca_domain *domain, *newdomain = NULL;
 
-	spin_lock_irqsave(&dca_lock, flags);
+	raw_spin_lock_irqsave(&dca_lock, flags);
 	if (dca_providers_blocked) {
-		spin_unlock_irqrestore(&dca_lock, flags);
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
 		return -ENODEV;
 	}
-	spin_unlock_irqrestore(&dca_lock, flags);
+	raw_spin_unlock_irqrestore(&dca_lock, flags);
 
 	err = dca_sysfs_add_provider(dca, dev);
 	if (err)
 		return err;
 
-	spin_lock_irqsave(&dca_lock, flags);
+	raw_spin_lock_irqsave(&dca_lock, flags);
 	domain = dca_get_domain(dev);
 	if (!domain) {
+		struct pci_bus *rc;
+
 		if (dca_providers_blocked) {
-			spin_unlock_irqrestore(&dca_lock, flags);
+			raw_spin_unlock_irqrestore(&dca_lock, flags);
 			dca_sysfs_remove_provider(dca);
 			unregister_dca_providers();
-		} else {
-			spin_unlock_irqrestore(&dca_lock, flags);
+			return -ENODEV;
+		}
+
+		raw_spin_unlock_irqrestore(&dca_lock, flags);
+		rc = dca_pci_rc_from_dev(dev);
+		newdomain = dca_allocate_domain(rc);
+		if (!newdomain)
+			return -ENODEV;
+		raw_spin_lock_irqsave(&dca_lock, flags);
+		/* Recheck, we might have raced after dropping the lock */
+		domain = dca_get_domain(dev);
+		if (!domain) {
+			domain = newdomain;
+			newdomain = NULL;
+			list_add(&domain->node, &dca_domains);
 		}
-		return -ENODEV;
 	}
 	list_add(&dca->node, &domain->dca_providers);
-	spin_unlock_irqrestore(&dca_lock, flags);
+	raw_spin_unlock_irqrestore(&dca_lock, flags);
 
 	blocking_notifier_call_chain(&dca_provider_chain,
 				     DCA_PROVIDER_ADD, NULL);
+	kfree(newdomain);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(register_dca_provider);
@@ -407,7 +418,7 @@
 	blocking_notifier_call_chain(&dca_provider_chain,
 				     DCA_PROVIDER_REMOVE, NULL);
 
-	spin_lock_irqsave(&dca_lock, flags);
+	raw_spin_lock_irqsave(&dca_lock, flags);
 
 	list_del(&dca->node);
 
@@ -416,7 +427,7 @@
 	if (list_empty(&domain->dca_providers))
 		dca_free_domain(domain);
 
-	spin_unlock_irqrestore(&dca_lock, flags);
+	raw_spin_unlock_irqrestore(&dca_lock, flags);
 
 	dca_sysfs_remove_provider(dca);
 }
diff -druN linux-libre-3.1-gnu/drivers/dca/dca-sysfs.c linux-libre-3.2-gnu/drivers/dca/dca-sysfs.c
--- linux-libre-3.1-gnu/drivers/dca/dca-sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dca/dca-sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/err.h>
 #include <linux/dca.h>
 #include <linux/gfp.h>
+#include <linux/export.h>
 
 static struct class *dca_class;
 static struct idr dca_idr;
diff -druN linux-libre-3.1-gnu/drivers/devfreq/devfreq.c linux-libre-3.2-gnu/drivers/devfreq/devfreq.c
--- linux-libre-3.1-gnu/drivers/devfreq/devfreq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/devfreq/devfreq.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,607 @@
+/*
+ * devfreq: Generic Dynamic Voltage and Frequency Scaling (DVFS) Framework
+ *	    for Non-CPU Devices.
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ *	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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/opp.h>
+#include <linux/devfreq.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/printk.h>
+#include <linux/hrtimer.h>
+#include "governor.h"
+
+struct class *devfreq_class;
+
+/*
+ * devfreq_work periodically monitors every registered device.
+ * The minimum polling interval is one jiffy. The polling interval is
+ * determined by the minimum polling period among all polling devfreq
+ * devices. The resolution of polling interval is one jiffy.
+ */
+static bool polling;
+static struct workqueue_struct *devfreq_wq;
+static struct delayed_work devfreq_work;
+
+/* wait removing if this is to be removed */
+static struct devfreq *wait_remove_device;
+
+/* The list of all device-devfreq */
+static LIST_HEAD(devfreq_list);
+static DEFINE_MUTEX(devfreq_list_lock);
+
+/**
+ * find_device_devfreq() - find devfreq struct using device pointer
+ * @dev:	device pointer used to lookup device devfreq.
+ *
+ * Search the list of device devfreqs and return the matched device's
+ * devfreq info. devfreq_list_lock should be held by the caller.
+ */
+static struct devfreq *find_device_devfreq(struct device *dev)
+{
+	struct devfreq *tmp_devfreq;
+
+	if (unlikely(IS_ERR_OR_NULL(dev))) {
+		pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+	WARN(!mutex_is_locked(&devfreq_list_lock),
+	     "devfreq_list_lock must be locked.");
+
+	list_for_each_entry(tmp_devfreq, &devfreq_list, node) {
+		if (tmp_devfreq->dev.parent == dev)
+			return tmp_devfreq;
+	}
+
+	return ERR_PTR(-ENODEV);
+}
+
+/**
+ * update_devfreq() - Reevaluate the device and configure frequency.
+ * @devfreq:	the devfreq instance.
+ *
+ * Note: Lock devfreq->lock before calling update_devfreq
+ *	 This function is exported for governors.
+ */
+int update_devfreq(struct devfreq *devfreq)
+{
+	unsigned long freq;
+	int err = 0;
+
+	if (!mutex_is_locked(&devfreq->lock)) {
+		WARN(true, "devfreq->lock must be locked by the caller.\n");
+		return -EINVAL;
+	}
+
+	/* Reevaluate the proper frequency */
+	err = devfreq->governor->get_target_freq(devfreq, &freq);
+	if (err)
+		return err;
+
+	err = devfreq->profile->target(devfreq->dev.parent, &freq);
+	if (err)
+		return err;
+
+	devfreq->previous_freq = freq;
+	return err;
+}
+
+/**
+ * devfreq_notifier_call() - Notify that the device frequency requirements
+ *			   has been changed out of devfreq framework.
+ * @nb		the notifier_block (supposed to be devfreq->nb)
+ * @type	not used
+ * @devp	not used
+ *
+ * Called by a notifier that uses devfreq->nb.
+ */
+static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
+				 void *devp)
+{
+	struct devfreq *devfreq = container_of(nb, struct devfreq, nb);
+	int ret;
+
+	mutex_lock(&devfreq->lock);
+	ret = update_devfreq(devfreq);
+	mutex_unlock(&devfreq->lock);
+
+	return ret;
+}
+
+/**
+ * _remove_devfreq() - Remove devfreq from the device.
+ * @devfreq:	the devfreq struct
+ * @skip:	skip calling device_unregister().
+ *
+ * Note that the caller should lock devfreq->lock before calling
+ * this. _remove_devfreq() will unlock it and free devfreq
+ * internally. devfreq_list_lock should be locked by the caller
+ * as well (not relased at return)
+ *
+ * Lock usage:
+ * devfreq->lock: locked before call.
+ *		  unlocked at return (and freed)
+ * devfreq_list_lock: locked before call.
+ *		      kept locked at return.
+ *		      if devfreq is centrally polled.
+ *
+ * Freed memory:
+ * devfreq
+ */
+static void _remove_devfreq(struct devfreq *devfreq, bool skip)
+{
+	if (!mutex_is_locked(&devfreq->lock)) {
+		WARN(true, "devfreq->lock must be locked by the caller.\n");
+		return;
+	}
+	if (!devfreq->governor->no_central_polling &&
+	    !mutex_is_locked(&devfreq_list_lock)) {
+		WARN(true, "devfreq_list_lock must be locked by the caller.\n");
+		return;
+	}
+
+	if (devfreq->being_removed)
+		return;
+
+	devfreq->being_removed = true;
+
+	if (devfreq->profile->exit)
+		devfreq->profile->exit(devfreq->dev.parent);
+
+	if (devfreq->governor->exit)
+		devfreq->governor->exit(devfreq);
+
+	if (!skip && get_device(&devfreq->dev)) {
+		device_unregister(&devfreq->dev);
+		put_device(&devfreq->dev);
+	}
+
+	if (!devfreq->governor->no_central_polling)
+		list_del(&devfreq->node);
+
+	mutex_unlock(&devfreq->lock);
+	mutex_destroy(&devfreq->lock);
+
+	kfree(devfreq);
+}
+
+/**
+ * devfreq_dev_release() - Callback for struct device to release the device.
+ * @dev:	the devfreq device
+ *
+ * This calls _remove_devfreq() if _remove_devfreq() is not called.
+ * Note that devfreq_dev_release() could be called by _remove_devfreq() as
+ * well as by others unregistering the device.
+ */
+static void devfreq_dev_release(struct device *dev)
+{
+	struct devfreq *devfreq = to_devfreq(dev);
+	bool central_polling = !devfreq->governor->no_central_polling;
+
+	/*
+	 * If devfreq_dev_release() was called by device_unregister() of
+	 * _remove_devfreq(), we cannot mutex_lock(&devfreq->lock) and
+	 * being_removed is already set. This also partially checks the case
+	 * where devfreq_dev_release() is called from a thread other than
+	 * the one called _remove_devfreq(); however, this case is
+	 * dealt completely with another following being_removed check.
+	 *
+	 * Because being_removed is never being
+	 * unset, we do not need to worry about race conditions on
+	 * being_removed.
+	 */
+	if (devfreq->being_removed)
+		return;
+
+	if (central_polling)
+		mutex_lock(&devfreq_list_lock);
+
+	mutex_lock(&devfreq->lock);
+
+	/*
+	 * Check being_removed flag again for the case where
+	 * devfreq_dev_release() was called in a thread other than the one
+	 * possibly called _remove_devfreq().
+	 */
+	if (devfreq->being_removed) {
+		mutex_unlock(&devfreq->lock);
+		goto out;
+	}
+
+	/* devfreq->lock is unlocked and removed in _removed_devfreq() */
+	_remove_devfreq(devfreq, true);
+
+out:
+	if (central_polling)
+		mutex_unlock(&devfreq_list_lock);
+}
+
+/**
+ * devfreq_monitor() - Periodically poll devfreq objects.
+ * @work: the work struct used to run devfreq_monitor periodically.
+ *
+ */
+static void devfreq_monitor(struct work_struct *work)
+{
+	static unsigned long last_polled_at;
+	struct devfreq *devfreq, *tmp;
+	int error;
+	unsigned long jiffies_passed;
+	unsigned long next_jiffies = ULONG_MAX, now = jiffies;
+	struct device *dev;
+
+	/* Initially last_polled_at = 0, polling every device at bootup */
+	jiffies_passed = now - last_polled_at;
+	last_polled_at = now;
+	if (jiffies_passed == 0)
+		jiffies_passed = 1;
+
+	mutex_lock(&devfreq_list_lock);
+	list_for_each_entry_safe(devfreq, tmp, &devfreq_list, node) {
+		mutex_lock(&devfreq->lock);
+		dev = devfreq->dev.parent;
+
+		/* Do not remove tmp for a while */
+		wait_remove_device = tmp;
+
+		if (devfreq->governor->no_central_polling ||
+		    devfreq->next_polling == 0) {
+			mutex_unlock(&devfreq->lock);
+			continue;
+		}
+		mutex_unlock(&devfreq_list_lock);
+
+		/*
+		 * Reduce more next_polling if devfreq_wq took an extra
+		 * delay. (i.e., CPU has been idled.)
+		 */
+		if (devfreq->next_polling <= jiffies_passed) {
+			error = update_devfreq(devfreq);
+
+			/* Remove a devfreq with an error. */
+			if (error && error != -EAGAIN) {
+
+				dev_err(dev, "Due to update_devfreq error(%d), devfreq(%s) is removed from the device\n",
+					error, devfreq->governor->name);
+
+				/*
+				 * Unlock devfreq before locking the list
+				 * in order to avoid deadlock with
+				 * find_device_devfreq or others
+				 */
+				mutex_unlock(&devfreq->lock);
+				mutex_lock(&devfreq_list_lock);
+				/* Check if devfreq is already removed */
+				if (IS_ERR(find_device_devfreq(dev)))
+					continue;
+				mutex_lock(&devfreq->lock);
+				/* This unlocks devfreq->lock and free it */
+				_remove_devfreq(devfreq, false);
+				continue;
+			}
+			devfreq->next_polling = devfreq->polling_jiffies;
+		} else {
+			devfreq->next_polling -= jiffies_passed;
+		}
+
+		if (devfreq->next_polling)
+			next_jiffies = (next_jiffies > devfreq->next_polling) ?
+					devfreq->next_polling : next_jiffies;
+
+		mutex_unlock(&devfreq->lock);
+		mutex_lock(&devfreq_list_lock);
+	}
+	wait_remove_device = NULL;
+	mutex_unlock(&devfreq_list_lock);
+
+	if (next_jiffies > 0 && next_jiffies < ULONG_MAX) {
+		polling = true;
+		queue_delayed_work(devfreq_wq, &devfreq_work, next_jiffies);
+	} else {
+		polling = false;
+	}
+}
+
+/**
+ * devfreq_add_device() - Add devfreq feature to the device
+ * @dev:	the device to add devfreq feature.
+ * @profile:	device-specific profile to run devfreq.
+ * @governor:	the policy to choose frequency.
+ * @data:	private data for the governor. The devfreq framework does not
+ *		touch this value.
+ */
+struct devfreq *devfreq_add_device(struct device *dev,
+				   struct devfreq_dev_profile *profile,
+				   const struct devfreq_governor *governor,
+				   void *data)
+{
+	struct devfreq *devfreq;
+	int err = 0;
+
+	if (!dev || !profile || !governor) {
+		dev_err(dev, "%s: Invalid parameters.\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+
+	if (!governor->no_central_polling) {
+		mutex_lock(&devfreq_list_lock);
+		devfreq = find_device_devfreq(dev);
+		mutex_unlock(&devfreq_list_lock);
+		if (!IS_ERR(devfreq)) {
+			dev_err(dev, "%s: Unable to create devfreq for the device. It already has one.\n", __func__);
+			err = -EINVAL;
+			goto out;
+		}
+	}
+
+	devfreq = kzalloc(sizeof(struct devfreq), GFP_KERNEL);
+	if (!devfreq) {
+		dev_err(dev, "%s: Unable to create devfreq for the device\n",
+			__func__);
+		err = -ENOMEM;
+		goto out;
+	}
+
+	mutex_init(&devfreq->lock);
+	mutex_lock(&devfreq->lock);
+	devfreq->dev.parent = dev;
+	devfreq->dev.class = devfreq_class;
+	devfreq->dev.release = devfreq_dev_release;
+	devfreq->profile = profile;
+	devfreq->governor = governor;
+	devfreq->previous_freq = profile->initial_freq;
+	devfreq->data = data;
+	devfreq->next_polling = devfreq->polling_jiffies
+			      = msecs_to_jiffies(devfreq->profile->polling_ms);
+	devfreq->nb.notifier_call = devfreq_notifier_call;
+
+	dev_set_name(&devfreq->dev, dev_name(dev));
+	err = device_register(&devfreq->dev);
+	if (err) {
+		put_device(&devfreq->dev);
+		goto err_dev;
+	}
+
+	if (governor->init)
+		err = governor->init(devfreq);
+	if (err)
+		goto err_init;
+
+	mutex_unlock(&devfreq->lock);
+
+	if (governor->no_central_polling)
+		goto out;
+
+	mutex_lock(&devfreq_list_lock);
+
+	list_add(&devfreq->node, &devfreq_list);
+
+	if (devfreq_wq && devfreq->next_polling && !polling) {
+		polling = true;
+		queue_delayed_work(devfreq_wq, &devfreq_work,
+				   devfreq->next_polling);
+	}
+	mutex_unlock(&devfreq_list_lock);
+	goto out;
+err_init:
+	device_unregister(&devfreq->dev);
+err_dev:
+	mutex_unlock(&devfreq->lock);
+	kfree(devfreq);
+out:
+	if (err)
+		return ERR_PTR(err);
+	else
+		return devfreq;
+}
+
+/**
+ * devfreq_remove_device() - Remove devfreq feature from a device.
+ * @devfreq	the devfreq instance to be removed
+ */
+int devfreq_remove_device(struct devfreq *devfreq)
+{
+	bool central_polling;
+
+	if (!devfreq)
+		return -EINVAL;
+
+	central_polling = !devfreq->governor->no_central_polling;
+
+	if (central_polling) {
+		mutex_lock(&devfreq_list_lock);
+		while (wait_remove_device == devfreq) {
+			mutex_unlock(&devfreq_list_lock);
+			schedule();
+			mutex_lock(&devfreq_list_lock);
+		}
+	}
+
+	mutex_lock(&devfreq->lock);
+	_remove_devfreq(devfreq, false); /* it unlocks devfreq->lock */
+
+	if (central_polling)
+		mutex_unlock(&devfreq_list_lock);
+
+	return 0;
+}
+
+static ssize_t show_governor(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name);
+}
+
+static ssize_t show_freq(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lu\n", to_devfreq(dev)->previous_freq);
+}
+
+static ssize_t show_polling_interval(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", to_devfreq(dev)->profile->polling_ms);
+}
+
+static ssize_t store_polling_interval(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct devfreq *df = to_devfreq(dev);
+	unsigned int value;
+	int ret;
+
+	ret = sscanf(buf, "%u", &value);
+	if (ret != 1)
+		goto out;
+
+	mutex_lock(&df->lock);
+	df->profile->polling_ms = value;
+	df->next_polling = df->polling_jiffies
+			 = msecs_to_jiffies(value);
+	mutex_unlock(&df->lock);
+
+	ret = count;
+
+	if (df->governor->no_central_polling)
+		goto out;
+
+	mutex_lock(&devfreq_list_lock);
+	if (df->next_polling > 0 && !polling) {
+		polling = true;
+		queue_delayed_work(devfreq_wq, &devfreq_work,
+				   df->next_polling);
+	}
+	mutex_unlock(&devfreq_list_lock);
+out:
+	return ret;
+}
+
+static ssize_t show_central_polling(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n",
+		       !to_devfreq(dev)->governor->no_central_polling);
+}
+
+static struct device_attribute devfreq_attrs[] = {
+	__ATTR(governor, S_IRUGO, show_governor, NULL),
+	__ATTR(cur_freq, S_IRUGO, show_freq, NULL),
+	__ATTR(central_polling, S_IRUGO, show_central_polling, NULL),
+	__ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval,
+	       store_polling_interval),
+	{ },
+};
+
+/**
+ * devfreq_start_polling() - Initialize data structure for devfreq framework and
+ *			   start polling registered devfreq devices.
+ */
+static int __init devfreq_start_polling(void)
+{
+	mutex_lock(&devfreq_list_lock);
+	polling = false;
+	devfreq_wq = create_freezable_workqueue("devfreq_wq");
+	INIT_DELAYED_WORK_DEFERRABLE(&devfreq_work, devfreq_monitor);
+	mutex_unlock(&devfreq_list_lock);
+
+	devfreq_monitor(&devfreq_work.work);
+	return 0;
+}
+late_initcall(devfreq_start_polling);
+
+static int __init devfreq_init(void)
+{
+	devfreq_class = class_create(THIS_MODULE, "devfreq");
+	if (IS_ERR(devfreq_class)) {
+		pr_err("%s: couldn't create class\n", __FILE__);
+		return PTR_ERR(devfreq_class);
+	}
+	devfreq_class->dev_attrs = devfreq_attrs;
+	return 0;
+}
+subsys_initcall(devfreq_init);
+
+static void __exit devfreq_exit(void)
+{
+	class_destroy(devfreq_class);
+}
+module_exit(devfreq_exit);
+
+/*
+ * The followings are helper functions for devfreq user device drivers with
+ * OPP framework.
+ */
+
+/**
+ * devfreq_recommended_opp() - Helper function to get proper OPP for the
+ *			     freq value given to target callback.
+ * @dev		The devfreq user device. (parent of devfreq)
+ * @freq	The frequency given to target function
+ *
+ */
+struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq)
+{
+	struct opp *opp = opp_find_freq_ceil(dev, freq);
+
+	if (opp == ERR_PTR(-ENODEV))
+		opp = opp_find_freq_floor(dev, freq);
+	return opp;
+}
+
+/**
+ * devfreq_register_opp_notifier() - Helper function to get devfreq notified
+ *				   for any changes in the OPP availability
+ *				   changes
+ * @dev		The devfreq user device. (parent of devfreq)
+ * @devfreq	The devfreq object.
+ */
+int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq)
+{
+	struct srcu_notifier_head *nh = opp_get_notifier(dev);
+
+	if (IS_ERR(nh))
+		return PTR_ERR(nh);
+	return srcu_notifier_chain_register(nh, &devfreq->nb);
+}
+
+/**
+ * devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq
+ *				     notified for any changes in the OPP
+ *				     availability changes anymore.
+ * @dev		The devfreq user device. (parent of devfreq)
+ * @devfreq	The devfreq object.
+ *
+ * At exit() callback of devfreq_dev_profile, this must be included if
+ * devfreq_recommended_opp is used.
+ */
+int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq)
+{
+	struct srcu_notifier_head *nh = opp_get_notifier(dev);
+
+	if (IS_ERR(nh))
+		return PTR_ERR(nh);
+	return srcu_notifier_chain_unregister(nh, &devfreq->nb);
+}
+
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_DESCRIPTION("devfreq class support");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/devfreq/governor.h linux-libre-3.2-gnu/drivers/devfreq/governor.h
--- linux-libre-3.1-gnu/drivers/devfreq/governor.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/devfreq/governor.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,24 @@
+/*
+ * governor.h - internal header for devfreq governors.
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ *	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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This header is for devfreq governors in drivers/devfreq/
+ */
+
+#ifndef _GOVERNOR_H
+#define _GOVERNOR_H
+
+#include <linux/devfreq.h>
+
+#define to_devfreq(DEV)	container_of((DEV), struct devfreq, dev)
+
+/* Caution: devfreq->lock must be locked before calling update_devfreq */
+extern int update_devfreq(struct devfreq *devfreq);
+
+#endif /* _GOVERNOR_H */
diff -druN linux-libre-3.1-gnu/drivers/devfreq/governor_performance.c linux-libre-3.2-gnu/drivers/devfreq/governor_performance.c
--- linux-libre-3.1-gnu/drivers/devfreq/governor_performance.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/devfreq/governor_performance.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ *  linux/drivers/devfreq/governor_performance.c
+ *
+ *  Copyright (C) 2011 Samsung Electronics
+ *	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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/devfreq.h>
+
+static int devfreq_performance_func(struct devfreq *df,
+				    unsigned long *freq)
+{
+	/*
+	 * target callback should be able to get floor value as
+	 * said in devfreq.h
+	 */
+	*freq = UINT_MAX;
+	return 0;
+}
+
+const struct devfreq_governor devfreq_performance = {
+	.name = "performance",
+	.get_target_freq = devfreq_performance_func,
+	.no_central_polling = true,
+};
diff -druN linux-libre-3.1-gnu/drivers/devfreq/governor_powersave.c linux-libre-3.2-gnu/drivers/devfreq/governor_powersave.c
--- linux-libre-3.1-gnu/drivers/devfreq/governor_powersave.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/devfreq/governor_powersave.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+/*
+ *  linux/drivers/devfreq/governor_powersave.c
+ *
+ *  Copyright (C) 2011 Samsung Electronics
+ *	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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/devfreq.h>
+
+static int devfreq_powersave_func(struct devfreq *df,
+				  unsigned long *freq)
+{
+	/*
+	 * target callback should be able to get ceiling value as
+	 * said in devfreq.h
+	 */
+	*freq = 0;
+	return 0;
+}
+
+const struct devfreq_governor devfreq_powersave = {
+	.name = "powersave",
+	.get_target_freq = devfreq_powersave_func,
+	.no_central_polling = true,
+};
diff -druN linux-libre-3.1-gnu/drivers/devfreq/governor_simpleondemand.c linux-libre-3.2-gnu/drivers/devfreq/governor_simpleondemand.c
--- linux-libre-3.1-gnu/drivers/devfreq/governor_simpleondemand.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/devfreq/governor_simpleondemand.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,88 @@
+/*
+ *  linux/drivers/devfreq/governor_simpleondemand.c
+ *
+ *  Copyright (C) 2011 Samsung Electronics
+ *	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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/errno.h>
+#include <linux/devfreq.h>
+#include <linux/math64.h>
+
+/* Default constants for DevFreq-Simple-Ondemand (DFSO) */
+#define DFSO_UPTHRESHOLD	(90)
+#define DFSO_DOWNDIFFERENCTIAL	(5)
+static int devfreq_simple_ondemand_func(struct devfreq *df,
+					unsigned long *freq)
+{
+	struct devfreq_dev_status stat;
+	int err = df->profile->get_dev_status(df->dev.parent, &stat);
+	unsigned long long a, b;
+	unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD;
+	unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL;
+	struct devfreq_simple_ondemand_data *data = df->data;
+
+	if (err)
+		return err;
+
+	if (data) {
+		if (data->upthreshold)
+			dfso_upthreshold = data->upthreshold;
+		if (data->downdifferential)
+			dfso_downdifferential = data->downdifferential;
+	}
+	if (dfso_upthreshold > 100 ||
+	    dfso_upthreshold < dfso_downdifferential)
+		return -EINVAL;
+
+	/* Assume MAX if it is going to be divided by zero */
+	if (stat.total_time == 0) {
+		*freq = UINT_MAX;
+		return 0;
+	}
+
+	/* Prevent overflow */
+	if (stat.busy_time >= (1 << 24) || stat.total_time >= (1 << 24)) {
+		stat.busy_time >>= 7;
+		stat.total_time >>= 7;
+	}
+
+	/* Set MAX if it's busy enough */
+	if (stat.busy_time * 100 >
+	    stat.total_time * dfso_upthreshold) {
+		*freq = UINT_MAX;
+		return 0;
+	}
+
+	/* Set MAX if we do not know the initial frequency */
+	if (stat.current_frequency == 0) {
+		*freq = UINT_MAX;
+		return 0;
+	}
+
+	/* Keep the current frequency */
+	if (stat.busy_time * 100 >
+	    stat.total_time * (dfso_upthreshold - dfso_downdifferential)) {
+		*freq = stat.current_frequency;
+		return 0;
+	}
+
+	/* Set the desired frequency based on the load */
+	a = stat.busy_time;
+	a *= stat.current_frequency;
+	b = div_u64(a, stat.total_time);
+	b *= 100;
+	b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2));
+	*freq = (unsigned long) b;
+
+	return 0;
+}
+
+const struct devfreq_governor devfreq_simple_ondemand = {
+	.name = "simple_ondemand",
+	.get_target_freq = devfreq_simple_ondemand_func,
+};
diff -druN linux-libre-3.1-gnu/drivers/devfreq/governor_userspace.c linux-libre-3.2-gnu/drivers/devfreq/governor_userspace.c
--- linux-libre-3.1-gnu/drivers/devfreq/governor_userspace.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/devfreq/governor_userspace.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,116 @@
+/*
+ *  linux/drivers/devfreq/governor_simpleondemand.c
+ *
+ *  Copyright (C) 2011 Samsung Electronics
+ *	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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/devfreq.h>
+#include <linux/pm.h>
+#include <linux/mutex.h>
+#include "governor.h"
+
+struct userspace_data {
+	unsigned long user_frequency;
+	bool valid;
+};
+
+static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq)
+{
+	struct userspace_data *data = df->data;
+
+	if (!data->valid)
+		*freq = df->previous_freq; /* No user freq specified yet */
+	else
+		*freq = data->user_frequency;
+	return 0;
+}
+
+static ssize_t store_freq(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	struct devfreq *devfreq = to_devfreq(dev);
+	struct userspace_data *data;
+	unsigned long wanted;
+	int err = 0;
+
+
+	mutex_lock(&devfreq->lock);
+	data = devfreq->data;
+
+	sscanf(buf, "%lu", &wanted);
+	data->user_frequency = wanted;
+	data->valid = true;
+	err = update_devfreq(devfreq);
+	if (err == 0)
+		err = count;
+	mutex_unlock(&devfreq->lock);
+	return err;
+}
+
+static ssize_t show_freq(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct devfreq *devfreq = to_devfreq(dev);
+	struct userspace_data *data;
+	int err = 0;
+
+	mutex_lock(&devfreq->lock);
+	data = devfreq->data;
+
+	if (data->valid)
+		err = sprintf(buf, "%lu\n", data->user_frequency);
+	else
+		err = sprintf(buf, "undefined\n");
+	mutex_unlock(&devfreq->lock);
+	return err;
+}
+
+static DEVICE_ATTR(set_freq, 0644, show_freq, store_freq);
+static struct attribute *dev_entries[] = {
+	&dev_attr_set_freq.attr,
+	NULL,
+};
+static struct attribute_group dev_attr_group = {
+	.name	= "userspace",
+	.attrs	= dev_entries,
+};
+
+static int userspace_init(struct devfreq *devfreq)
+{
+	int err = 0;
+	struct userspace_data *data = kzalloc(sizeof(struct userspace_data),
+					      GFP_KERNEL);
+
+	if (!data) {
+		err = -ENOMEM;
+		goto out;
+	}
+	data->valid = false;
+	devfreq->data = data;
+
+	err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group);
+out:
+	return err;
+}
+
+static void userspace_exit(struct devfreq *devfreq)
+{
+	sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group);
+	kfree(devfreq->data);
+	devfreq->data = NULL;
+}
+
+const struct devfreq_governor devfreq_userspace = {
+	.name = "userspace",
+	.get_target_freq = devfreq_userspace_func,
+	.init = userspace_init,
+	.exit = userspace_exit,
+	.no_central_polling = true,
+};
diff -druN linux-libre-3.1-gnu/drivers/devfreq/Kconfig linux-libre-3.2-gnu/drivers/devfreq/Kconfig
--- linux-libre-3.1-gnu/drivers/devfreq/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/devfreq/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,68 @@
+menuconfig PM_DEVFREQ
+	bool "Generic Dynamic Voltage and Frequency Scaling (DVFS) support"
+	help
+	  A device may have a list of frequencies and voltages available.
+	  devfreq, a generic DVFS framework can be registered for a device
+	  in order to let the governor provided to devfreq choose an
+	  operating frequency based on the device driver's policy.
+
+	  Each device may have its own governor and policy. Devfreq can
+	  reevaluate the device state periodically and/or based on the
+	  notification to "nb", a notifier block, of devfreq.
+
+	  Like some CPUs with CPUfreq, a device may have multiple clocks.
+	  However, because the clock frequencies of a single device are
+	  determined by the single device's state, an instance of devfreq
+	  is attached to a single device and returns a "representative"
+	  clock frequency of the device, which is also attached
+	  to a device by 1-to-1. The device registering devfreq takes the
+	  responsiblity to "interpret" the representative frequency and
+	  to set its every clock accordingly with the "target" callback
+	  given to devfreq.
+
+	  When OPP is used with the devfreq device, it is recommended to
+	  register devfreq's nb to the OPP's notifier head.  If OPP is
+	  used with the devfreq device, you may use OPP helper
+	  functions defined in devfreq.h.
+
+if PM_DEVFREQ
+
+comment "DEVFREQ Governors"
+
+config DEVFREQ_GOV_SIMPLE_ONDEMAND
+	bool "Simple Ondemand"
+	help
+	  Chooses frequency based on the recent load on the device. Works
+	  similar as ONDEMAND governor of CPUFREQ does. A device with
+	  Simple-Ondemand should be able to provide busy/total counter
+	  values that imply the usage rate. A device may provide tuned
+	  values to the governor with data field at devfreq_add_device().
+
+config DEVFREQ_GOV_PERFORMANCE
+	bool "Performance"
+	help
+	  Sets the frequency at the maximum available frequency.
+	  This governor always returns UINT_MAX as frequency so that
+	  the DEVFREQ framework returns the highest frequency available
+	  at any time.
+
+config DEVFREQ_GOV_POWERSAVE
+	bool "Powersave"
+	help
+	  Sets the frequency at the minimum available frequency.
+	  This governor always returns 0 as frequency so that
+	  the DEVFREQ framework returns the lowest frequency available
+	  at any time.
+
+config DEVFREQ_GOV_USERSPACE
+	bool "Userspace"
+	help
+	  Sets the frequency at the user specified one.
+	  This governor returns the user configured frequency if there
+	  has been an input to /sys/devices/.../power/devfreq_set_freq.
+	  Otherwise, the governor does not change the frequnecy
+	  given at the initialization.
+
+comment "DEVFREQ Drivers"
+
+endif # PM_DEVFREQ
diff -druN linux-libre-3.1-gnu/drivers/devfreq/Makefile linux-libre-3.2-gnu/drivers/devfreq/Makefile
--- linux-libre-3.1-gnu/drivers/devfreq/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/devfreq/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+obj-$(CONFIG_PM_DEVFREQ)	+= devfreq.o
+obj-$(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)	+= governor_simpleondemand.o
+obj-$(CONFIG_DEVFREQ_GOV_PERFORMANCE)	+= governor_performance.o
+obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE)	+= governor_powersave.o
+obj-$(CONFIG_DEVFREQ_GOV_USERSPACE)	+= governor_userspace.o
diff -druN linux-libre-3.1-gnu/drivers/dma/amba-pl08x.c linux-libre-3.2-gnu/drivers/dma/amba-pl08x.c
--- linux-libre-3.1-gnu/drivers/dma/amba-pl08x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/amba-pl08x.c	2012-01-04 18:55:44.000000000 -0500
@@ -66,32 +66,29 @@
  *    after the final transfer signalled by LBREQ or LSREQ.  The DMAC
  *    will then move to the next LLI entry.
  *
- * Only the former works sanely with scatter lists, so we only implement
- * the DMAC flow control method.  However, peripherals which use the LBREQ
- * and LSREQ signals (eg, MMCI) are unable to use this mode, which through
- * these hardware restrictions prevents them from using scatter DMA.
- *
  * Global TODO:
  * - Break out common code from arch/arm/mach-s3c64xx and share
  */
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
-#include <linux/dmaengine.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl08x.h>
 #include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
 #include <linux/seq_file.h>
-
+#include <linux/slab.h>
 #include <asm/hardware/pl080.h>
 
 #define DRIVER_NAME	"pl08xdmac"
 
+static struct amba_driver pl08x_amba_driver;
+
 /**
  * struct vendor_data - vendor-specific config parameters for PL08x derivatives
  * @channels: the number of channels available in this variant
@@ -126,7 +123,8 @@
  * @phy_chans: array of data for the physical channels
  * @pool: a pool for the LLI descriptors
  * @pool_ctr: counter of LLIs in the pool
- * @lli_buses: bitmask to or in to LLI pointer selecting AHB port for LLI fetches
+ * @lli_buses: bitmask to or in to LLI pointer selecting AHB port for LLI
+ * fetches
  * @mem_buses: set to indicate memory transfers on AHB2.
  * @lock: a spinlock for this struct
  */
@@ -149,14 +147,6 @@
  * PL08X specific defines
  */
 
-/*
- * Memory boundaries: the manual for PL08x says that the controller
- * cannot read past a 1KiB boundary, so these defines are used to
- * create transfer LLIs that do not cross such boundaries.
- */
-#define PL08X_BOUNDARY_SHIFT		(10)	/* 1KB 0x400 */
-#define PL08X_BOUNDARY_SIZE		(1 << PL08X_BOUNDARY_SHIFT)
-
 /* Size (bytes) of each LLI buffer allocated for one transfer */
 # define PL08X_LLI_TSFR_SIZE	0x2000
 
@@ -272,7 +262,6 @@
 	writel(val, ch->base + PL080_CH_CONFIG);
 }
 
-
 /*
  * pl08x_terminate_phy_chan() stops the channel, clears the FIFO and
  * clears any pending interrupt status.  This should not be used for
@@ -363,7 +352,9 @@
 	if (!list_empty(&plchan->pend_list)) {
 		struct pl08x_txd *txdi;
 		list_for_each_entry(txdi, &plchan->pend_list, node) {
-			bytes += txdi->len;
+			struct pl08x_sg *dsg;
+			list_for_each_entry(dsg, &txd->dsg_list, node)
+				bytes += dsg->len;
 		}
 	}
 
@@ -407,6 +398,7 @@
 		return NULL;
 	}
 
+	pm_runtime_get_sync(&pl08x->adev->dev);
 	return ch;
 }
 
@@ -420,6 +412,8 @@
 	/* Stop the channel and clear its interrupts */
 	pl08x_terminate_phy_chan(pl08x, ch);
 
+	pm_runtime_put(&pl08x->adev->dev);
+
 	/* Mark it as free */
 	ch->serving = NULL;
 	spin_unlock_irqrestore(&ch->lock, flags);
@@ -499,36 +493,30 @@
 };
 
 /*
- * Autoselect a master bus to use for the transfer this prefers the
- * destination bus if both available if fixed address on one bus the
- * other will be chosen
+ * Autoselect a master bus to use for the transfer. Slave will be the chosen as
+ * victim in case src & dest are not similarly aligned. i.e. If after aligning
+ * masters address with width requirements of transfer (by sending few byte by
+ * byte data), slave is still not aligned, then its width will be reduced to
+ * BYTE.
+ * - prefers the destination bus if both available
+ * - prefers bus with fixed address (i.e. peripheral)
  */
 static void pl08x_choose_master_bus(struct pl08x_lli_build_data *bd,
 	struct pl08x_bus_data **mbus, struct pl08x_bus_data **sbus, u32 cctl)
 {
 	if (!(cctl & PL080_CONTROL_DST_INCR)) {
-		*mbus = &bd->srcbus;
-		*sbus = &bd->dstbus;
-	} else if (!(cctl & PL080_CONTROL_SRC_INCR)) {
 		*mbus = &bd->dstbus;
 		*sbus = &bd->srcbus;
+	} else if (!(cctl & PL080_CONTROL_SRC_INCR)) {
+		*mbus = &bd->srcbus;
+		*sbus = &bd->dstbus;
 	} else {
-		if (bd->dstbus.buswidth == 4) {
-			*mbus = &bd->dstbus;
-			*sbus = &bd->srcbus;
-		} else if (bd->srcbus.buswidth == 4) {
-			*mbus = &bd->srcbus;
-			*sbus = &bd->dstbus;
-		} else if (bd->dstbus.buswidth == 2) {
+		if (bd->dstbus.buswidth >= bd->srcbus.buswidth) {
 			*mbus = &bd->dstbus;
 			*sbus = &bd->srcbus;
-		} else if (bd->srcbus.buswidth == 2) {
+		} else {
 			*mbus = &bd->srcbus;
 			*sbus = &bd->dstbus;
-		} else {
-			/* bd->srcbus.buswidth == 1 */
-			*mbus = &bd->dstbus;
-			*sbus = &bd->srcbus;
 		}
 	}
 }
@@ -547,7 +535,8 @@
 	llis_va[num_llis].cctl = cctl;
 	llis_va[num_llis].src = bd->srcbus.addr;
 	llis_va[num_llis].dst = bd->dstbus.addr;
-	llis_va[num_llis].lli = llis_bus + (num_llis + 1) * sizeof(struct pl08x_lli);
+	llis_va[num_llis].lli = llis_bus + (num_llis + 1) *
+		sizeof(struct pl08x_lli);
 	llis_va[num_llis].lli |= bd->lli_bus;
 
 	if (cctl & PL080_CONTROL_SRC_INCR)
@@ -560,16 +549,12 @@
 	bd->remainder -= len;
 }
 
-/*
- * Return number of bytes to fill to boundary, or len.
- * This calculation works for any value of addr.
- */
-static inline size_t pl08x_pre_boundary(u32 addr, size_t len)
+static inline void prep_byte_width_lli(struct pl08x_lli_build_data *bd,
+		u32 *cctl, u32 len, int num_llis, size_t *total_bytes)
 {
-	size_t boundary_len = PL08X_BOUNDARY_SIZE -
-			(addr & (PL08X_BOUNDARY_SIZE - 1));
-
-	return min(boundary_len, len);
+	*cctl = pl08x_cctl_bits(*cctl, 1, 1, len);
+	pl08x_fill_lli_for_desc(bd, num_llis, len, *cctl);
+	(*total_bytes) += len;
 }
 
 /*
@@ -583,13 +568,12 @@
 	struct pl08x_bus_data *mbus, *sbus;
 	struct pl08x_lli_build_data bd;
 	int num_llis = 0;
-	u32 cctl;
-	size_t max_bytes_per_lli;
-	size_t total_bytes = 0;
+	u32 cctl, early_bytes = 0;
+	size_t max_bytes_per_lli, total_bytes;
 	struct pl08x_lli *llis_va;
+	struct pl08x_sg *dsg;
 
-	txd->llis_va = dma_pool_alloc(pl08x->pool, GFP_NOWAIT,
-				      &txd->llis_bus);
+	txd->llis_va = dma_pool_alloc(pl08x->pool, GFP_NOWAIT, &txd->llis_bus);
 	if (!txd->llis_va) {
 		dev_err(&pl08x->adev->dev, "%s no memory for llis\n", __func__);
 		return 0;
@@ -597,13 +581,9 @@
 
 	pl08x->pool_ctr++;
 
-	/* Get the default CCTL */
-	cctl = txd->cctl;
-
 	bd.txd = txd;
-	bd.srcbus.addr = txd->src_addr;
-	bd.dstbus.addr = txd->dst_addr;
 	bd.lli_bus = (pl08x->lli_buses & PL08X_AHB2) ? PL080_LLI_LM_AHB2 : 0;
+	cctl = txd->cctl;
 
 	/* Find maximum width of the source bus */
 	bd.srcbus.maxwidth =
@@ -615,215 +595,179 @@
 		pl08x_get_bytes_for_cctl((cctl & PL080_CONTROL_DWIDTH_MASK) >>
 				       PL080_CONTROL_DWIDTH_SHIFT);
 
-	/* Set up the bus widths to the maximum */
-	bd.srcbus.buswidth = bd.srcbus.maxwidth;
-	bd.dstbus.buswidth = bd.dstbus.maxwidth;
-
-	/*
-	 * Bytes transferred == tsize * MIN(buswidths), not max(buswidths)
-	 */
-	max_bytes_per_lli = min(bd.srcbus.buswidth, bd.dstbus.buswidth) *
-		PL080_CONTROL_TRANSFER_SIZE_MASK;
-
-	/* We need to count this down to zero */
-	bd.remainder = txd->len;
+	list_for_each_entry(dsg, &txd->dsg_list, node) {
+		total_bytes = 0;
+		cctl = txd->cctl;
 
-	/*
-	 * Choose bus to align to
-	 * - prefers destination bus if both available
-	 * - if fixed address on one bus chooses other
-	 */
-	pl08x_choose_master_bus(&bd, &mbus, &sbus, cctl);
+		bd.srcbus.addr = dsg->src_addr;
+		bd.dstbus.addr = dsg->dst_addr;
+		bd.remainder = dsg->len;
+		bd.srcbus.buswidth = bd.srcbus.maxwidth;
+		bd.dstbus.buswidth = bd.dstbus.maxwidth;
 
-	dev_vdbg(&pl08x->adev->dev, "src=0x%08x%s/%u dst=0x%08x%s/%u len=%zu llimax=%zu\n",
-		 bd.srcbus.addr, cctl & PL080_CONTROL_SRC_INCR ? "+" : "",
-		 bd.srcbus.buswidth,
-		 bd.dstbus.addr, cctl & PL080_CONTROL_DST_INCR ? "+" : "",
-		 bd.dstbus.buswidth,
-		 bd.remainder, max_bytes_per_lli);
-	dev_vdbg(&pl08x->adev->dev, "mbus=%s sbus=%s\n",
-		 mbus == &bd.srcbus ? "src" : "dst",
-		 sbus == &bd.srcbus ? "src" : "dst");
+		pl08x_choose_master_bus(&bd, &mbus, &sbus, cctl);
 
-	if (txd->len < mbus->buswidth) {
-		/* Less than a bus width available - send as single bytes */
-		while (bd.remainder) {
-			dev_vdbg(&pl08x->adev->dev,
-				 "%s single byte LLIs for a transfer of "
-				 "less than a bus width (remain 0x%08x)\n",
-				 __func__, bd.remainder);
-			cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-			pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
-			total_bytes++;
-		}
-	} else {
-		/* Make one byte LLIs until master bus is aligned */
-		while ((mbus->addr) % (mbus->buswidth)) {
-			dev_vdbg(&pl08x->adev->dev,
-				"%s adjustment lli for less than bus width "
-				 "(remain 0x%08x)\n",
-				 __func__, bd.remainder);
-			cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-			pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
-			total_bytes++;
-		}
+		dev_vdbg(&pl08x->adev->dev, "src=0x%08x%s/%u dst=0x%08x%s/%u len=%zu\n",
+			bd.srcbus.addr, cctl & PL080_CONTROL_SRC_INCR ? "+" : "",
+			bd.srcbus.buswidth,
+			bd.dstbus.addr, cctl & PL080_CONTROL_DST_INCR ? "+" : "",
+			bd.dstbus.buswidth,
+			bd.remainder);
+		dev_vdbg(&pl08x->adev->dev, "mbus=%s sbus=%s\n",
+			mbus == &bd.srcbus ? "src" : "dst",
+			sbus == &bd.srcbus ? "src" : "dst");
 
 		/*
-		 * Master now aligned
-		 * - if slave is not then we must set its width down
+		 * Zero length is only allowed if all these requirements are
+		 * met:
+		 * - flow controller is peripheral.
+		 * - src.addr is aligned to src.width
+		 * - dst.addr is aligned to dst.width
+		 *
+		 * sg_len == 1 should be true, as there can be two cases here:
+		 *
+		 * - Memory addresses are contiguous and are not scattered.
+		 *   Here, Only one sg will be passed by user driver, with
+		 *   memory address and zero length. We pass this to controller
+		 *   and after the transfer it will receive the last burst
+		 *   request from peripheral and so transfer finishes.
+		 *
+		 * - Memory addresses are scattered and are not contiguous.
+		 *   Here, Obviously as DMA controller doesn't know when a lli's
+		 *   transfer gets over, it can't load next lli. So in this
+		 *   case, there has to be an assumption that only one lli is
+		 *   supported. Thus, we can't have scattered addresses.
 		 */
-		if (sbus->addr % sbus->buswidth) {
-			dev_dbg(&pl08x->adev->dev,
-				"%s set down bus width to one byte\n",
-				 __func__);
+		if (!bd.remainder) {
+			u32 fc = (txd->ccfg & PL080_CONFIG_FLOW_CONTROL_MASK) >>
+				PL080_CONFIG_FLOW_CONTROL_SHIFT;
+			if (!((fc >= PL080_FLOW_SRC2DST_DST) &&
+					(fc <= PL080_FLOW_SRC2DST_SRC))) {
+				dev_err(&pl08x->adev->dev, "%s sg len can't be zero",
+					__func__);
+				return 0;
+			}
 
-			sbus->buswidth = 1;
+			if ((bd.srcbus.addr % bd.srcbus.buswidth) ||
+					(bd.srcbus.addr % bd.srcbus.buswidth)) {
+				dev_err(&pl08x->adev->dev,
+					"%s src & dst address must be aligned to src"
+					" & dst width if peripheral is flow controller",
+					__func__);
+				return 0;
+			}
+
+			cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
+					bd.dstbus.buswidth, 0);
+			pl08x_fill_lli_for_desc(&bd, num_llis++, 0, cctl);
+			break;
 		}
 
 		/*
-		 * Make largest possible LLIs until less than one bus
-		 * width left
+		 * Send byte by byte for following cases
+		 * - Less than a bus width available
+		 * - until master bus is aligned
 		 */
-		while (bd.remainder > (mbus->buswidth - 1)) {
-			size_t lli_len, target_len, tsize, odd_bytes;
+		if (bd.remainder < mbus->buswidth)
+			early_bytes = bd.remainder;
+		else if ((mbus->addr) % (mbus->buswidth)) {
+			early_bytes = mbus->buswidth - (mbus->addr) %
+				(mbus->buswidth);
+			if ((bd.remainder - early_bytes) < mbus->buswidth)
+				early_bytes = bd.remainder;
+		}
 
-			/*
-			 * If enough left try to send max possible,
-			 * otherwise try to send the remainder
-			 */
-			target_len = min(bd.remainder, max_bytes_per_lli);
+		if (early_bytes) {
+			dev_vdbg(&pl08x->adev->dev,
+				"%s byte width LLIs (remain 0x%08x)\n",
+				__func__, bd.remainder);
+			prep_byte_width_lli(&bd, &cctl, early_bytes, num_llis++,
+				&total_bytes);
+		}
 
+		if (bd.remainder) {
 			/*
-			 * Set bus lengths for incrementing buses to the
-			 * number of bytes which fill to next memory boundary,
-			 * limiting on the target length calculated above.
+			 * Master now aligned
+			 * - if slave is not then we must set its width down
 			 */
-			if (cctl & PL080_CONTROL_SRC_INCR)
-				bd.srcbus.fill_bytes =
-					pl08x_pre_boundary(bd.srcbus.addr,
-						target_len);
-			else
-				bd.srcbus.fill_bytes = target_len;
-
-			if (cctl & PL080_CONTROL_DST_INCR)
-				bd.dstbus.fill_bytes =
-					pl08x_pre_boundary(bd.dstbus.addr,
-						target_len);
-			else
-				bd.dstbus.fill_bytes = target_len;
+			if (sbus->addr % sbus->buswidth) {
+				dev_dbg(&pl08x->adev->dev,
+					"%s set down bus width to one byte\n",
+					__func__);
 
-			/* Find the nearest */
-			lli_len	= min(bd.srcbus.fill_bytes,
-				      bd.dstbus.fill_bytes);
+				sbus->buswidth = 1;
+			}
 
-			BUG_ON(lli_len > bd.remainder);
+			/*
+			 * Bytes transferred = tsize * src width, not
+			 * MIN(buswidths)
+			 */
+			max_bytes_per_lli = bd.srcbus.buswidth *
+				PL080_CONTROL_TRANSFER_SIZE_MASK;
+			dev_vdbg(&pl08x->adev->dev,
+				"%s max bytes per lli = %zu\n",
+				__func__, max_bytes_per_lli);
 
-			if (lli_len <= 0) {
-				dev_err(&pl08x->adev->dev,
-					"%s lli_len is %zu, <= 0\n",
-						__func__, lli_len);
-				return 0;
-			}
+			/*
+			 * Make largest possible LLIs until less than one bus
+			 * width left
+			 */
+			while (bd.remainder > (mbus->buswidth - 1)) {
+				size_t lli_len, tsize, width;
 
-			if (lli_len == target_len) {
-				/*
-				 * Can send what we wanted.
-				 * Maintain alignment
-				 */
-				lli_len	= (lli_len/mbus->buswidth) *
-							mbus->buswidth;
-				odd_bytes = 0;
-			} else {
 				/*
-				 * So now we know how many bytes to transfer
-				 * to get to the nearest boundary.  The next
-				 * LLI will past the boundary.  However, we
-				 * may be working to a boundary on the slave
-				 * bus.  We need to ensure the master stays
-				 * aligned, and that we are working in
-				 * multiples of the bus widths.
+				 * If enough left try to send max possible,
+				 * otherwise try to send the remainder
 				 */
-				odd_bytes = lli_len % mbus->buswidth;
-				lli_len -= odd_bytes;
-
-			}
+				lli_len = min(bd.remainder, max_bytes_per_lli);
 
-			if (lli_len) {
 				/*
-				 * Check against minimum bus alignment:
-				 * Calculate actual transfer size in relation
-				 * to bus width an get a maximum remainder of
-				 * the smallest bus width - 1
+				 * Check against maximum bus alignment:
+				 * Calculate actual transfer size in relation to
+				 * bus width an get a maximum remainder of the
+				 * highest bus width - 1
 				 */
-				/* FIXME: use round_down()? */
-				tsize = lli_len / min(mbus->buswidth,
-						      sbus->buswidth);
-				lli_len	= tsize * min(mbus->buswidth,
-						      sbus->buswidth);
-
-				if (target_len != lli_len) {
-					dev_vdbg(&pl08x->adev->dev,
-					"%s can't send what we want. Desired 0x%08zx, lli of 0x%08zx bytes in txd of 0x%08zx\n",
-					__func__, target_len, lli_len, txd->len);
-				}
-
-				cctl = pl08x_cctl_bits(cctl,
-						       bd.srcbus.buswidth,
-						       bd.dstbus.buswidth,
-						       tsize);
+				width = max(mbus->buswidth, sbus->buswidth);
+				lli_len = (lli_len / width) * width;
+				tsize = lli_len / bd.srcbus.buswidth;
 
 				dev_vdbg(&pl08x->adev->dev,
-					"%s fill lli with single lli chunk of size 0x%08zx (remainder 0x%08zx)\n",
+					"%s fill lli with single lli chunk of "
+					"size 0x%08zx (remainder 0x%08zx)\n",
 					__func__, lli_len, bd.remainder);
+
+				cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
+					bd.dstbus.buswidth, tsize);
 				pl08x_fill_lli_for_desc(&bd, num_llis++,
-					lli_len, cctl);
+						lli_len, cctl);
 				total_bytes += lli_len;
 			}
 
-
-			if (odd_bytes) {
-				/*
-				 * Creep past the boundary, maintaining
-				 * master alignment
-				 */
-				int j;
-				for (j = 0; (j < mbus->buswidth)
-						&& (bd.remainder); j++) {
-					cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-					dev_vdbg(&pl08x->adev->dev,
-						"%s align with boundary, single byte (remain 0x%08zx)\n",
-						__func__, bd.remainder);
-					pl08x_fill_lli_for_desc(&bd,
-						num_llis++, 1, cctl);
-					total_bytes++;
-				}
+			/*
+			 * Send any odd bytes
+			 */
+			if (bd.remainder) {
+				dev_vdbg(&pl08x->adev->dev,
+					"%s align with boundary, send odd bytes (remain %zu)\n",
+					__func__, bd.remainder);
+				prep_byte_width_lli(&bd, &cctl, bd.remainder,
+						num_llis++, &total_bytes);
 			}
 		}
 
-		/*
-		 * Send any odd bytes
-		 */
-		while (bd.remainder) {
-			cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-			dev_vdbg(&pl08x->adev->dev,
-				"%s align with boundary, single odd byte (remain %zu)\n",
-				__func__, bd.remainder);
-			pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
-			total_bytes++;
+		if (total_bytes != dsg->len) {
+			dev_err(&pl08x->adev->dev,
+				"%s size of encoded lli:s don't match total txd, transferred 0x%08zx from size 0x%08zx\n",
+				__func__, total_bytes, dsg->len);
+			return 0;
 		}
-	}
-	if (total_bytes != txd->len) {
-		dev_err(&pl08x->adev->dev,
-			"%s size of encoded lli:s don't match total txd, transferred 0x%08zx from size 0x%08zx\n",
-			__func__, total_bytes, txd->len);
-		return 0;
-	}
 
-	if (num_llis >= MAX_NUM_TSFR_LLIS) {
-		dev_err(&pl08x->adev->dev,
-			"%s need to increase MAX_NUM_TSFR_LLIS from 0x%08x\n",
-			__func__, (u32) MAX_NUM_TSFR_LLIS);
-		return 0;
+		if (num_llis >= MAX_NUM_TSFR_LLIS) {
+			dev_err(&pl08x->adev->dev,
+				"%s need to increase MAX_NUM_TSFR_LLIS from 0x%08x\n",
+				__func__, (u32) MAX_NUM_TSFR_LLIS);
+			return 0;
+		}
 	}
 
 	llis_va = txd->llis_va;
@@ -856,11 +800,19 @@
 static void pl08x_free_txd(struct pl08x_driver_data *pl08x,
 			   struct pl08x_txd *txd)
 {
+	struct pl08x_sg *dsg, *_dsg;
+
 	/* Free the LLI */
-	dma_pool_free(pl08x->pool, txd->llis_va, txd->llis_bus);
+	if (txd->llis_va)
+		dma_pool_free(pl08x->pool, txd->llis_va, txd->llis_bus);
 
 	pl08x->pool_ctr--;
 
+	list_for_each_entry_safe(dsg, _dsg, &txd->dsg_list, node) {
+		list_del(&dsg->node);
+		kfree(dsg);
+	}
+
 	kfree(txd);
 }
 
@@ -917,9 +869,7 @@
 	 * need, but for slaves the physical signals may be muxed!
 	 * Can the platform allow us to use this channel?
 	 */
-	if (plchan->slave &&
-	    ch->signal < 0 &&
-	    pl08x->pd->get_signal) {
+	if (plchan->slave && pl08x->pd->get_signal) {
 		ret = pl08x->pd->get_signal(plchan);
 		if (ret < 0) {
 			dev_dbg(&pl08x->adev->dev,
@@ -1008,10 +958,8 @@
  * If slaves are relying on interrupts to signal completion this function
  * must not be called with interrupts disabled.
  */
-static enum dma_status
-pl08x_dma_tx_status(struct dma_chan *chan,
-		    dma_cookie_t cookie,
-		    struct dma_tx_state *txstate)
+static enum dma_status pl08x_dma_tx_status(struct dma_chan *chan,
+		dma_cookie_t cookie, struct dma_tx_state *txstate)
 {
 	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
 	dma_cookie_t last_used;
@@ -1253,7 +1201,9 @@
 
 	num_llis = pl08x_fill_llis_for_desc(pl08x, txd);
 	if (!num_llis) {
-		kfree(txd);
+		spin_lock_irqsave(&plchan->lock, flags);
+		pl08x_free_txd(pl08x, txd);
+		spin_unlock_irqrestore(&plchan->lock, flags);
 		return -EINVAL;
 	}
 
@@ -1301,13 +1251,14 @@
 static struct pl08x_txd *pl08x_get_txd(struct pl08x_dma_chan *plchan,
 	unsigned long flags)
 {
-	struct pl08x_txd *txd = kzalloc(sizeof(struct pl08x_txd), GFP_NOWAIT);
+	struct pl08x_txd *txd = kzalloc(sizeof(*txd), GFP_NOWAIT);
 
 	if (txd) {
 		dma_async_tx_descriptor_init(&txd->tx, &plchan->chan);
 		txd->tx.flags = flags;
 		txd->tx.tx_submit = pl08x_tx_submit;
 		INIT_LIST_HEAD(&txd->node);
+		INIT_LIST_HEAD(&txd->dsg_list);
 
 		/* Always enable error and terminal interrupts */
 		txd->ccfg = PL080_CONFIG_ERR_IRQ_MASK |
@@ -1326,6 +1277,7 @@
 	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
 	struct pl08x_driver_data *pl08x = plchan->host;
 	struct pl08x_txd *txd;
+	struct pl08x_sg *dsg;
 	int ret;
 
 	txd = pl08x_get_txd(plchan, flags);
@@ -1335,10 +1287,19 @@
 		return NULL;
 	}
 
+	dsg = kzalloc(sizeof(struct pl08x_sg), GFP_NOWAIT);
+	if (!dsg) {
+		pl08x_free_txd(pl08x, txd);
+		dev_err(&pl08x->adev->dev, "%s no memory for pl080 sg\n",
+				__func__);
+		return NULL;
+	}
+	list_add_tail(&dsg->node, &txd->dsg_list);
+
 	txd->direction = DMA_NONE;
-	txd->src_addr = src;
-	txd->dst_addr = dest;
-	txd->len = len;
+	dsg->src_addr = src;
+	dsg->dst_addr = dest;
+	dsg->len = len;
 
 	/* Set platform data for m2m */
 	txd->ccfg |= PL080_FLOW_MEM2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT;
@@ -1367,19 +1328,13 @@
 	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
 	struct pl08x_driver_data *pl08x = plchan->host;
 	struct pl08x_txd *txd;
-	int ret;
-
-	/*
-	 * Current implementation ASSUMES only one sg
-	 */
-	if (sg_len != 1) {
-		dev_err(&pl08x->adev->dev, "%s prepared too long sglist\n",
-			__func__);
-		BUG();
-	}
+	struct pl08x_sg *dsg;
+	struct scatterlist *sg;
+	dma_addr_t slave_addr;
+	int ret, tmp;
 
 	dev_dbg(&pl08x->adev->dev, "%s prepare transaction of %d bytes from %s\n",
-		__func__, sgl->length, plchan->name);
+			__func__, sgl->length, plchan->name);
 
 	txd = pl08x_get_txd(plchan, flags);
 	if (!txd) {
@@ -1398,24 +1353,49 @@
 	 * channel target address dynamically at runtime.
 	 */
 	txd->direction = direction;
-	txd->len = sgl->length;
 
 	if (direction == DMA_TO_DEVICE) {
-		txd->ccfg |= PL080_FLOW_MEM2PER << PL080_CONFIG_FLOW_CONTROL_SHIFT;
 		txd->cctl = plchan->dst_cctl;
-		txd->src_addr = sgl->dma_address;
-		txd->dst_addr = plchan->dst_addr;
+		slave_addr = plchan->dst_addr;
 	} else if (direction == DMA_FROM_DEVICE) {
-		txd->ccfg |= PL080_FLOW_PER2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT;
 		txd->cctl = plchan->src_cctl;
-		txd->src_addr = plchan->src_addr;
-		txd->dst_addr = sgl->dma_address;
+		slave_addr = plchan->src_addr;
 	} else {
+		pl08x_free_txd(pl08x, txd);
 		dev_err(&pl08x->adev->dev,
 			"%s direction unsupported\n", __func__);
 		return NULL;
 	}
 
+	if (plchan->cd->device_fc)
+		tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER_PER :
+			PL080_FLOW_PER2MEM_PER;
+	else
+		tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER :
+			PL080_FLOW_PER2MEM;
+
+	txd->ccfg |= tmp << PL080_CONFIG_FLOW_CONTROL_SHIFT;
+
+	for_each_sg(sgl, sg, sg_len, tmp) {
+		dsg = kzalloc(sizeof(struct pl08x_sg), GFP_NOWAIT);
+		if (!dsg) {
+			pl08x_free_txd(pl08x, txd);
+			dev_err(&pl08x->adev->dev, "%s no mem for pl080 sg\n",
+					__func__);
+			return NULL;
+		}
+		list_add_tail(&dsg->node, &txd->dsg_list);
+
+		dsg->len = sg_dma_len(sg);
+		if (direction == DMA_TO_DEVICE) {
+			dsg->src_addr = sg_phys(sg);
+			dsg->dst_addr = slave_addr;
+		} else {
+			dsg->src_addr = slave_addr;
+			dsg->dst_addr = sg_phys(sg);
+		}
+	}
+
 	ret = pl08x_prep_channel_resources(plchan, txd);
 	if (ret)
 		return NULL;
@@ -1489,9 +1469,15 @@
 
 bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
 {
-	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
+	struct pl08x_dma_chan *plchan;
 	char *name = chan_id;
 
+	/* Reject channels for devices not bound to this driver */
+	if (chan->device->dev->driver != &pl08x_amba_driver.drv)
+		return false;
+
+	plchan = to_pl08x_chan(chan);
+
 	/* Check that the channel is not taken! */
 	if (!strcmp(plchan->name, name))
 		return true;
@@ -1507,34 +1493,34 @@
  */
 static void pl08x_ensure_on(struct pl08x_driver_data *pl08x)
 {
-	u32 val;
-
-	val = readl(pl08x->base + PL080_CONFIG);
-	val &= ~(PL080_CONFIG_M2_BE | PL080_CONFIG_M1_BE | PL080_CONFIG_ENABLE);
-	/* We implicitly clear bit 1 and that means little-endian mode */
-	val |= PL080_CONFIG_ENABLE;
-	writel(val, pl08x->base + PL080_CONFIG);
+	writel(PL080_CONFIG_ENABLE, pl08x->base + PL080_CONFIG);
 }
 
 static void pl08x_unmap_buffers(struct pl08x_txd *txd)
 {
 	struct device *dev = txd->tx.chan->device->dev;
+	struct pl08x_sg *dsg;
 
 	if (!(txd->tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
 		if (txd->tx.flags & DMA_COMPL_SRC_UNMAP_SINGLE)
-			dma_unmap_single(dev, txd->src_addr, txd->len,
-				DMA_TO_DEVICE);
-		else
-			dma_unmap_page(dev, txd->src_addr, txd->len,
-				DMA_TO_DEVICE);
+			list_for_each_entry(dsg, &txd->dsg_list, node)
+				dma_unmap_single(dev, dsg->src_addr, dsg->len,
+						DMA_TO_DEVICE);
+		else {
+			list_for_each_entry(dsg, &txd->dsg_list, node)
+				dma_unmap_page(dev, dsg->src_addr, dsg->len,
+						DMA_TO_DEVICE);
+		}
 	}
 	if (!(txd->tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
 		if (txd->tx.flags & DMA_COMPL_DEST_UNMAP_SINGLE)
-			dma_unmap_single(dev, txd->dst_addr, txd->len,
-				DMA_FROM_DEVICE);
+			list_for_each_entry(dsg, &txd->dsg_list, node)
+				dma_unmap_single(dev, dsg->dst_addr, dsg->len,
+						DMA_FROM_DEVICE);
 		else
-			dma_unmap_page(dev, txd->dst_addr, txd->len,
-				DMA_FROM_DEVICE);
+			list_for_each_entry(dsg, &txd->dsg_list, node)
+				dma_unmap_page(dev, dsg->dst_addr, dsg->len,
+						DMA_FROM_DEVICE);
 	}
 }
 
@@ -1589,8 +1575,8 @@
 		 */
 		list_for_each_entry(waiting, &pl08x->memcpy.channels,
 				    chan.device_node) {
-		  if (waiting->state == PL08X_CHAN_WAITING &&
-			    waiting->waiting != NULL) {
+			if (waiting->state == PL08X_CHAN_WAITING &&
+				waiting->waiting != NULL) {
 				int ret;
 
 				/* This should REALLY not fail now */
@@ -1630,38 +1616,40 @@
 static irqreturn_t pl08x_irq(int irq, void *dev)
 {
 	struct pl08x_driver_data *pl08x = dev;
-	u32 mask = 0;
-	u32 val;
-	int i;
+	u32 mask = 0, err, tc, i;
 
-	val = readl(pl08x->base + PL080_ERR_STATUS);
-	if (val) {
-		/* An error interrupt (on one or more channels) */
-		dev_err(&pl08x->adev->dev,
-			"%s error interrupt, register value 0x%08x\n",
-				__func__, val);
-		/*
-		 * Simply clear ALL PL08X error interrupts,
-		 * regardless of channel and cause
-		 * FIXME: should be 0x00000003 on PL081 really.
-		 */
-		writel(0x000000FF, pl08x->base + PL080_ERR_CLEAR);
+	/* check & clear - ERR & TC interrupts */
+	err = readl(pl08x->base + PL080_ERR_STATUS);
+	if (err) {
+		dev_err(&pl08x->adev->dev, "%s error interrupt, register value 0x%08x\n",
+			__func__, err);
+		writel(err, pl08x->base + PL080_ERR_CLEAR);
 	}
-	val = readl(pl08x->base + PL080_INT_STATUS);
+	tc = readl(pl08x->base + PL080_INT_STATUS);
+	if (tc)
+		writel(tc, pl08x->base + PL080_TC_CLEAR);
+
+	if (!err && !tc)
+		return IRQ_NONE;
+
 	for (i = 0; i < pl08x->vd->channels; i++) {
-		if ((1 << i) & val) {
+		if (((1 << i) & err) || ((1 << i) & tc)) {
 			/* Locate physical channel */
 			struct pl08x_phy_chan *phychan = &pl08x->phy_chans[i];
 			struct pl08x_dma_chan *plchan = phychan->serving;
 
+			if (!plchan) {
+				dev_err(&pl08x->adev->dev,
+					"%s Error TC interrupt on unused channel: 0x%08x\n",
+					__func__, i);
+				continue;
+			}
+
 			/* Schedule tasklet on this channel */
 			tasklet_schedule(&plchan->tasklet);
-
 			mask |= (1 << i);
 		}
 	}
-	/* Clear only the terminal interrupts on channels we processed */
-	writel(mask, pl08x->base + PL080_TC_CLEAR);
 
 	return mask ? IRQ_HANDLED : IRQ_NONE;
 }
@@ -1685,9 +1673,7 @@
  * Make a local wrapper to hold required data
  */
 static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
-					   struct dma_device *dmadev,
-					   unsigned int channels,
-					   bool slave)
+		struct dma_device *dmadev, unsigned int channels, bool slave)
 {
 	struct pl08x_dma_chan *chan;
 	int i;
@@ -1700,7 +1686,7 @@
 	 * to cope with that situation.
 	 */
 	for (i = 0; i < channels; i++) {
-		chan = kzalloc(sizeof(struct pl08x_dma_chan), GFP_KERNEL);
+		chan = kzalloc(sizeof(*chan), GFP_KERNEL);
 		if (!chan) {
 			dev_err(&pl08x->adev->dev,
 				"%s no memory for channel\n", __func__);
@@ -1728,7 +1714,7 @@
 			kfree(chan);
 			continue;
 		}
-		dev_info(&pl08x->adev->dev,
+		dev_dbg(&pl08x->adev->dev,
 			 "initialize virtual channel \"%s\"\n",
 			 chan->name);
 
@@ -1837,9 +1823,9 @@
 static void init_pl08x_debugfs(struct pl08x_driver_data *pl08x)
 {
 	/* Expose a simple debugfs interface to view all clocks */
-	(void) debugfs_create_file(dev_name(&pl08x->adev->dev), S_IFREG | S_IRUGO,
-				   NULL, pl08x,
-				   &pl08x_debugfs_operations);
+	(void) debugfs_create_file(dev_name(&pl08x->adev->dev),
+			S_IFREG | S_IRUGO, NULL, pl08x,
+			&pl08x_debugfs_operations);
 }
 
 #else
@@ -1860,12 +1846,15 @@
 		return ret;
 
 	/* Create the driver state holder */
-	pl08x = kzalloc(sizeof(struct pl08x_driver_data), GFP_KERNEL);
+	pl08x = kzalloc(sizeof(*pl08x), GFP_KERNEL);
 	if (!pl08x) {
 		ret = -ENOMEM;
 		goto out_no_pl08x;
 	}
 
+	pm_runtime_set_active(&adev->dev);
+	pm_runtime_enable(&adev->dev);
+
 	/* Initialize memcpy engine */
 	dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask);
 	pl08x->memcpy.dev = &adev->dev;
@@ -1939,7 +1928,7 @@
 	}
 
 	/* Initialize physical channels */
-	pl08x->phy_chans = kmalloc((vd->channels * sizeof(struct pl08x_phy_chan)),
+	pl08x->phy_chans = kmalloc((vd->channels * sizeof(*pl08x->phy_chans)),
 			GFP_KERNEL);
 	if (!pl08x->phy_chans) {
 		dev_err(&adev->dev, "%s failed to allocate "
@@ -1956,9 +1945,8 @@
 		spin_lock_init(&ch->lock);
 		ch->serving = NULL;
 		ch->signal = -1;
-		dev_info(&adev->dev,
-			 "physical channel %d is %s\n", i,
-			 pl08x_phy_channel_busy(ch) ? "BUSY" : "FREE");
+		dev_dbg(&adev->dev, "physical channel %d is %s\n",
+			i, pl08x_phy_channel_busy(ch) ? "BUSY" : "FREE");
 	}
 
 	/* Register as many memcpy channels as there are physical channels */
@@ -1974,8 +1962,7 @@
 
 	/* Register slave channels */
 	ret = pl08x_dma_init_virtual_channels(pl08x, &pl08x->slave,
-					      pl08x->pd->num_slave_channels,
-					      true);
+			pl08x->pd->num_slave_channels, true);
 	if (ret <= 0) {
 		dev_warn(&pl08x->adev->dev,
 			"%s failed to enumerate slave channels - %d\n",
@@ -2005,6 +1992,8 @@
 	dev_info(&pl08x->adev->dev, "DMA: PL%03x rev%u at 0x%08llx irq %d\n",
 		 amba_part(adev), amba_rev(adev),
 		 (unsigned long long)adev->res.start, adev->irq[0]);
+
+	pm_runtime_put(&adev->dev);
 	return 0;
 
 out_no_slave_reg:
@@ -2023,6 +2012,9 @@
 	dma_pool_destroy(pl08x->pool);
 out_no_lli_pool:
 out_no_platdata:
+	pm_runtime_put(&adev->dev);
+	pm_runtime_disable(&adev->dev);
+
 	kfree(pl08x);
 out_no_pl08x:
 	amba_release_regions(adev);
diff -druN linux-libre-3.1-gnu/drivers/dma/at_hdmac.c linux-libre-3.2-gnu/drivers/dma/at_hdmac.c
--- linux-libre-3.1-gnu/drivers/dma/at_hdmac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/at_hdmac.c	2012-01-04 18:55:44.000000000 -0500
@@ -107,10 +107,11 @@
 {
 	struct at_desc *desc, *_desc;
 	struct at_desc *ret = NULL;
+	unsigned long flags;
 	unsigned int i = 0;
 	LIST_HEAD(tmp_list);
 
-	spin_lock_bh(&atchan->lock);
+	spin_lock_irqsave(&atchan->lock, flags);
 	list_for_each_entry_safe(desc, _desc, &atchan->free_list, desc_node) {
 		i++;
 		if (async_tx_test_ack(&desc->txd)) {
@@ -121,7 +122,7 @@
 		dev_dbg(chan2dev(&atchan->chan_common),
 				"desc %p not ACKed\n", desc);
 	}
-	spin_unlock_bh(&atchan->lock);
+	spin_unlock_irqrestore(&atchan->lock, flags);
 	dev_vdbg(chan2dev(&atchan->chan_common),
 		"scanned %u descriptors on freelist\n", i);
 
@@ -129,9 +130,9 @@
 	if (!ret) {
 		ret = atc_alloc_descriptor(&atchan->chan_common, GFP_ATOMIC);
 		if (ret) {
-			spin_lock_bh(&atchan->lock);
+			spin_lock_irqsave(&atchan->lock, flags);
 			atchan->descs_allocated++;
-			spin_unlock_bh(&atchan->lock);
+			spin_unlock_irqrestore(&atchan->lock, flags);
 		} else {
 			dev_err(chan2dev(&atchan->chan_common),
 					"not enough descriptors available\n");
@@ -150,8 +151,9 @@
 {
 	if (desc) {
 		struct at_desc *child;
+		unsigned long flags;
 
-		spin_lock_bh(&atchan->lock);
+		spin_lock_irqsave(&atchan->lock, flags);
 		list_for_each_entry(child, &desc->tx_list, desc_node)
 			dev_vdbg(chan2dev(&atchan->chan_common),
 					"moving child desc %p to freelist\n",
@@ -160,7 +162,7 @@
 		dev_vdbg(chan2dev(&atchan->chan_common),
 			 "moving desc %p to freelist\n", desc);
 		list_add(&desc->desc_node, &atchan->free_list);
-		spin_unlock_bh(&atchan->lock);
+		spin_unlock_irqrestore(&atchan->lock, flags);
 	}
 }
 
@@ -299,7 +301,7 @@
 
 	/* for cyclic transfers,
 	 * no need to replay callback function while stopping */
-	if (!test_bit(ATC_IS_CYCLIC, &atchan->status)) {
+	if (!atc_chan_is_cyclic(atchan)) {
 		dma_async_tx_callback	callback = txd->callback;
 		void			*param = txd->callback_param;
 
@@ -471,16 +473,17 @@
 static void atc_tasklet(unsigned long data)
 {
 	struct at_dma_chan *atchan = (struct at_dma_chan *)data;
+	unsigned long flags;
 
-	spin_lock(&atchan->lock);
+	spin_lock_irqsave(&atchan->lock, flags);
 	if (test_and_clear_bit(ATC_IS_ERROR, &atchan->status))
 		atc_handle_error(atchan);
-	else if (test_bit(ATC_IS_CYCLIC, &atchan->status))
+	else if (atc_chan_is_cyclic(atchan))
 		atc_handle_cyclic(atchan);
 	else
 		atc_advance_work(atchan);
 
-	spin_unlock(&atchan->lock);
+	spin_unlock_irqrestore(&atchan->lock, flags);
 }
 
 static irqreturn_t at_dma_interrupt(int irq, void *dev_id)
@@ -539,8 +542,9 @@
 	struct at_desc		*desc = txd_to_at_desc(tx);
 	struct at_dma_chan	*atchan = to_at_dma_chan(tx->chan);
 	dma_cookie_t		cookie;
+	unsigned long		flags;
 
-	spin_lock_bh(&atchan->lock);
+	spin_lock_irqsave(&atchan->lock, flags);
 	cookie = atc_assign_cookie(atchan, desc);
 
 	if (list_empty(&atchan->active_list)) {
@@ -554,7 +558,7 @@
 		list_add_tail(&desc->desc_node, &atchan->queue);
 	}
 
-	spin_unlock_bh(&atchan->lock);
+	spin_unlock_irqrestore(&atchan->lock, flags);
 
 	return cookie;
 }
@@ -927,28 +931,29 @@
 	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
 	struct at_dma		*atdma = to_at_dma(chan->device);
 	int			chan_id = atchan->chan_common.chan_id;
+	unsigned long		flags;
 
 	LIST_HEAD(list);
 
 	dev_vdbg(chan2dev(chan), "atc_control (%d)\n", cmd);
 
 	if (cmd == DMA_PAUSE) {
-		spin_lock_bh(&atchan->lock);
+		spin_lock_irqsave(&atchan->lock, flags);
 
 		dma_writel(atdma, CHER, AT_DMA_SUSP(chan_id));
 		set_bit(ATC_IS_PAUSED, &atchan->status);
 
-		spin_unlock_bh(&atchan->lock);
+		spin_unlock_irqrestore(&atchan->lock, flags);
 	} else if (cmd == DMA_RESUME) {
-		if (!test_bit(ATC_IS_PAUSED, &atchan->status))
+		if (!atc_chan_is_paused(atchan))
 			return 0;
 
-		spin_lock_bh(&atchan->lock);
+		spin_lock_irqsave(&atchan->lock, flags);
 
 		dma_writel(atdma, CHDR, AT_DMA_RES(chan_id));
 		clear_bit(ATC_IS_PAUSED, &atchan->status);
 
-		spin_unlock_bh(&atchan->lock);
+		spin_unlock_irqrestore(&atchan->lock, flags);
 	} else if (cmd == DMA_TERMINATE_ALL) {
 		struct at_desc	*desc, *_desc;
 		/*
@@ -957,7 +962,7 @@
 		 * channel. We still have to poll the channel enable bit due
 		 * to AHB/HSB limitations.
 		 */
-		spin_lock_bh(&atchan->lock);
+		spin_lock_irqsave(&atchan->lock, flags);
 
 		/* disabling channel: must also remove suspend state */
 		dma_writel(atdma, CHDR, AT_DMA_RES(chan_id) | atchan->mask);
@@ -978,7 +983,7 @@
 		/* if channel dedicated to cyclic operations, free it */
 		clear_bit(ATC_IS_CYCLIC, &atchan->status);
 
-		spin_unlock_bh(&atchan->lock);
+		spin_unlock_irqrestore(&atchan->lock, flags);
 	} else {
 		return -ENXIO;
 	}
@@ -1004,9 +1009,10 @@
 	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
 	dma_cookie_t		last_used;
 	dma_cookie_t		last_complete;
+	unsigned long		flags;
 	enum dma_status		ret;
 
-	spin_lock_bh(&atchan->lock);
+	spin_lock_irqsave(&atchan->lock, flags);
 
 	last_complete = atchan->completed_cookie;
 	last_used = chan->cookie;
@@ -1021,7 +1027,7 @@
 		ret = dma_async_is_complete(cookie, last_complete, last_used);
 	}
 
-	spin_unlock_bh(&atchan->lock);
+	spin_unlock_irqrestore(&atchan->lock, flags);
 
 	if (ret != DMA_SUCCESS)
 		dma_set_tx_state(txstate, last_complete, last_used,
@@ -1029,7 +1035,7 @@
 	else
 		dma_set_tx_state(txstate, last_complete, last_used, 0);
 
-	if (test_bit(ATC_IS_PAUSED, &atchan->status))
+	if (atc_chan_is_paused(atchan))
 		ret = DMA_PAUSED;
 
 	dev_vdbg(chan2dev(chan), "tx_status %d: cookie = %d (d%d, u%d)\n",
@@ -1046,18 +1052,19 @@
 static void atc_issue_pending(struct dma_chan *chan)
 {
 	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
+	unsigned long		flags;
 
 	dev_vdbg(chan2dev(chan), "issue_pending\n");
 
 	/* Not needed for cyclic transfers */
-	if (test_bit(ATC_IS_CYCLIC, &atchan->status))
+	if (atc_chan_is_cyclic(atchan))
 		return;
 
-	spin_lock_bh(&atchan->lock);
+	spin_lock_irqsave(&atchan->lock, flags);
 	if (!atc_chan_is_enabled(atchan)) {
 		atc_advance_work(atchan);
 	}
-	spin_unlock_bh(&atchan->lock);
+	spin_unlock_irqrestore(&atchan->lock, flags);
 }
 
 /**
@@ -1073,6 +1080,7 @@
 	struct at_dma		*atdma = to_at_dma(chan->device);
 	struct at_desc		*desc;
 	struct at_dma_slave	*atslave;
+	unsigned long		flags;
 	int			i;
 	u32			cfg;
 	LIST_HEAD(tmp_list);
@@ -1116,11 +1124,11 @@
 		list_add_tail(&desc->desc_node, &tmp_list);
 	}
 
-	spin_lock_bh(&atchan->lock);
+	spin_lock_irqsave(&atchan->lock, flags);
 	atchan->descs_allocated = i;
 	list_splice(&tmp_list, &atchan->free_list);
 	atchan->completed_cookie = chan->cookie = 1;
-	spin_unlock_bh(&atchan->lock);
+	spin_unlock_irqrestore(&atchan->lock, flags);
 
 	/* channel parameters */
 	channel_writel(atchan, CFG, cfg);
@@ -1260,12 +1268,11 @@
 
 	/* initialize channels related values */
 	INIT_LIST_HEAD(&atdma->dma_common.channels);
-	for (i = 0; i < pdata->nr_channels; i++, atdma->dma_common.chancnt++) {
+	for (i = 0; i < pdata->nr_channels; i++) {
 		struct at_dma_chan	*atchan = &atdma->chan[i];
 
 		atchan->chan_common.device = &atdma->dma_common;
 		atchan->chan_common.cookie = atchan->completed_cookie = 1;
-		atchan->chan_common.chan_id = i;
 		list_add_tail(&atchan->chan_common.device_node,
 				&atdma->dma_common.channels);
 
@@ -1293,22 +1300,20 @@
 	if (dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask))
 		atdma->dma_common.device_prep_dma_memcpy = atc_prep_dma_memcpy;
 
-	if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask))
+	if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)) {
 		atdma->dma_common.device_prep_slave_sg = atc_prep_slave_sg;
-
-	if (dma_has_cap(DMA_CYCLIC, atdma->dma_common.cap_mask))
+		/* controller can do slave DMA: can trigger cyclic transfers */
+		dma_cap_set(DMA_CYCLIC, atdma->dma_common.cap_mask);
 		atdma->dma_common.device_prep_dma_cyclic = atc_prep_dma_cyclic;
-
-	if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask) ||
-	    dma_has_cap(DMA_CYCLIC, atdma->dma_common.cap_mask))
 		atdma->dma_common.device_control = atc_control;
+	}
 
 	dma_writel(atdma, EN, AT_DMA_ENABLE);
 
 	dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n",
 	  dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "",
 	  dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)  ? "slave " : "",
-	  atdma->dma_common.chancnt);
+	  pdata->nr_channels);
 
 	dma_async_device_register(&atdma->dma_common);
 
@@ -1377,27 +1382,112 @@
 	clk_disable(atdma->clk);
 }
 
+static int at_dma_prepare(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct at_dma *atdma = platform_get_drvdata(pdev);
+	struct dma_chan *chan, *_chan;
+
+	list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+			device_node) {
+		struct at_dma_chan *atchan = to_at_dma_chan(chan);
+		/* wait for transaction completion (except in cyclic case) */
+		if (atc_chan_is_enabled(atchan) && !atc_chan_is_cyclic(atchan))
+			return -EAGAIN;
+	}
+	return 0;
+}
+
+static void atc_suspend_cyclic(struct at_dma_chan *atchan)
+{
+	struct dma_chan	*chan = &atchan->chan_common;
+
+	/* Channel should be paused by user
+	 * do it anyway even if it is not done already */
+	if (!atc_chan_is_paused(atchan)) {
+		dev_warn(chan2dev(chan),
+		"cyclic channel not paused, should be done by channel user\n");
+		atc_control(chan, DMA_PAUSE, 0);
+	}
+
+	/* now preserve additional data for cyclic operations */
+	/* next descriptor address in the cyclic list */
+	atchan->save_dscr = channel_readl(atchan, DSCR);
+
+	vdbg_dump_regs(atchan);
+}
+
 static int at_dma_suspend_noirq(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct at_dma *atdma = platform_get_drvdata(pdev);
+	struct dma_chan *chan, *_chan;
 
-	at_dma_off(platform_get_drvdata(pdev));
+	/* preserve data */
+	list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+			device_node) {
+		struct at_dma_chan *atchan = to_at_dma_chan(chan);
+
+		if (atc_chan_is_cyclic(atchan))
+			atc_suspend_cyclic(atchan);
+		atchan->save_cfg = channel_readl(atchan, CFG);
+	}
+	atdma->save_imr = dma_readl(atdma, EBCIMR);
+
+	/* disable DMA controller */
+	at_dma_off(atdma);
 	clk_disable(atdma->clk);
 	return 0;
 }
 
+static void atc_resume_cyclic(struct at_dma_chan *atchan)
+{
+	struct at_dma	*atdma = to_at_dma(atchan->chan_common.device);
+
+	/* restore channel status for cyclic descriptors list:
+	 * next descriptor in the cyclic list at the time of suspend */
+	channel_writel(atchan, SADDR, 0);
+	channel_writel(atchan, DADDR, 0);
+	channel_writel(atchan, CTRLA, 0);
+	channel_writel(atchan, CTRLB, 0);
+	channel_writel(atchan, DSCR, atchan->save_dscr);
+	dma_writel(atdma, CHER, atchan->mask);
+
+	/* channel pause status should be removed by channel user
+	 * We cannot take the initiative to do it here */
+
+	vdbg_dump_regs(atchan);
+}
+
 static int at_dma_resume_noirq(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct at_dma *atdma = platform_get_drvdata(pdev);
+	struct dma_chan *chan, *_chan;
 
+	/* bring back DMA controller */
 	clk_enable(atdma->clk);
 	dma_writel(atdma, EN, AT_DMA_ENABLE);
+
+	/* clear any pending interrupt */
+	while (dma_readl(atdma, EBCISR))
+		cpu_relax();
+
+	/* restore saved data */
+	dma_writel(atdma, EBCIER, atdma->save_imr);
+	list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+			device_node) {
+		struct at_dma_chan *atchan = to_at_dma_chan(chan);
+
+		channel_writel(atchan, CFG, atchan->save_cfg);
+		if (atc_chan_is_cyclic(atchan))
+			atc_resume_cyclic(atchan);
+	}
 	return 0;
 }
 
 static const struct dev_pm_ops at_dma_dev_pm_ops = {
+	.prepare = at_dma_prepare,
 	.suspend_noirq = at_dma_suspend_noirq,
 	.resume_noirq = at_dma_resume_noirq,
 };
diff -druN linux-libre-3.1-gnu/drivers/dma/at_hdmac_regs.h linux-libre-3.2-gnu/drivers/dma/at_hdmac_regs.h
--- linux-libre-3.1-gnu/drivers/dma/at_hdmac_regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/at_hdmac_regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -204,6 +204,9 @@
  * @status: transmit status information from irq/prep* functions
  *                to tasklet (use atomic operations)
  * @tasklet: bottom half to finish transaction work
+ * @save_cfg: configuration register that is saved on suspend/resume cycle
+ * @save_dscr: for cyclic operations, preserve next descriptor address in
+ *             the cyclic list on suspend/resume cycle
  * @lock: serializes enqueue/dequeue operations to descriptors lists
  * @completed_cookie: identifier for the most recently completed operation
  * @active_list: list of descriptors dmaengine is being running on
@@ -218,6 +221,8 @@
 	u8			mask;
 	unsigned long		status;
 	struct tasklet_struct	tasklet;
+	u32			save_cfg;
+	u32			save_dscr;
 
 	spinlock_t		lock;
 
@@ -248,6 +253,7 @@
  * @chan_common: common dmaengine dma_device object members
  * @ch_regs: memory mapped register base
  * @clk: dma controller clock
+ * @save_imr: interrupt mask register that is saved on suspend/resume cycle
  * @all_chan_mask: all channels availlable in a mask
  * @dma_desc_pool: base of DMA descriptor region (DMA address)
  * @chan: channels table to store at_dma_chan structures
@@ -256,6 +262,7 @@
 	struct dma_device	dma_common;
 	void __iomem		*regs;
 	struct clk		*clk;
+	u32			save_imr;
 
 	u8			all_chan_mask;
 
@@ -355,6 +362,23 @@
 	return !!(dma_readl(atdma, CHSR) & atchan->mask);
 }
 
+/**
+ * atc_chan_is_paused - test channel pause/resume status
+ * @atchan: channel we want to test status
+ */
+static inline int atc_chan_is_paused(struct at_dma_chan *atchan)
+{
+	return test_bit(ATC_IS_PAUSED, &atchan->status);
+}
+
+/**
+ * atc_chan_is_cyclic - test if given channel has cyclic property set
+ * @atchan: channel we want to test status
+ */
+static inline int atc_chan_is_cyclic(struct at_dma_chan *atchan)
+{
+	return test_bit(ATC_IS_CYCLIC, &atchan->status);
+}
 
 /**
  * set_desc_eol - set end-of-link to descriptor so it will end transfer
diff -druN linux-libre-3.1-gnu/drivers/dma/dmatest.c linux-libre-3.2-gnu/drivers/dma/dmatest.c
--- linux-libre-3.1-gnu/drivers/dma/dmatest.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/dmatest.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
+#include <linux/freezer.h>
 #include <linux/init.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
@@ -251,6 +252,7 @@
 	int			i;
 
 	thread_name = current->comm;
+	set_freezable_with_signal();
 
 	ret = -ENOMEM;
 
@@ -305,7 +307,8 @@
 		dma_addr_t dma_srcs[src_cnt];
 		dma_addr_t dma_dsts[dst_cnt];
 		struct completion cmp;
-		unsigned long tmo = msecs_to_jiffies(timeout);
+		unsigned long start, tmo, end = 0 /* compiler... */;
+		bool reload = true;
 		u8 align = 0;
 
 		total_tests++;
@@ -404,7 +407,17 @@
 		}
 		dma_async_issue_pending(chan);
 
-		tmo = wait_for_completion_timeout(&cmp, tmo);
+		do {
+			start = jiffies;
+			if (reload)
+				end = start + msecs_to_jiffies(timeout);
+			else if (end <= start)
+				end = start + 1;
+			tmo = wait_for_completion_interruptible_timeout(&cmp,
+								end - start);
+			reload = try_to_freeze();
+		} while (tmo == -ERESTARTSYS);
+
 		status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
 
 		if (tmo == 0) {
@@ -477,6 +490,8 @@
 	pr_notice("%s: terminating after %u tests, %u failures (status %d)\n",
 			thread_name, total_tests, failed_tests, ret);
 
+	/* terminate all transfers on specified channels */
+	chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
 	if (iterations > 0)
 		while (!kthread_should_stop()) {
 			DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit);
@@ -499,6 +514,10 @@
 		list_del(&thread->node);
 		kfree(thread);
 	}
+
+	/* terminate all transfers on specified channels */
+	dtc->chan->device->device_control(dtc->chan, DMA_TERMINATE_ALL, 0);
+
 	kfree(dtc);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/dma/dw_dmac.c linux-libre-3.2-gnu/drivers/dma/dw_dmac.c
--- linux-libre-3.1-gnu/drivers/dma/dw_dmac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/dw_dmac.c	2012-01-04 18:55:44.000000000 -0500
@@ -1407,12 +1407,11 @@
 	dw->all_chan_mask = (1 << pdata->nr_channels) - 1;
 
 	INIT_LIST_HEAD(&dw->dma.channels);
-	for (i = 0; i < pdata->nr_channels; i++, dw->dma.chancnt++) {
+	for (i = 0; i < pdata->nr_channels; i++) {
 		struct dw_dma_chan	*dwc = &dw->chan[i];
 
 		dwc->chan.device = &dw->dma;
 		dwc->chan.cookie = dwc->completed = 1;
-		dwc->chan.chan_id = i;
 		if (pdata->chan_allocation_order == CHAN_ALLOCATION_ASCENDING)
 			list_add_tail(&dwc->chan.device_node,
 					&dw->dma.channels);
@@ -1468,7 +1467,7 @@
 	dma_writel(dw, CFG, DW_CFG_DMA_EN);
 
 	printk(KERN_INFO "%s: DesignWare DMA Controller, %d channels\n",
-			dev_name(&pdev->dev), dw->dma.chancnt);
+			dev_name(&pdev->dev), pdata->nr_channels);
 
 	dma_async_device_register(&dw->dma);
 
diff -druN linux-libre-3.1-gnu/drivers/dma/ep93xx_dma.c linux-libre-3.2-gnu/drivers/dma/ep93xx_dma.c
--- linux-libre-3.1-gnu/drivers/dma/ep93xx_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/ep93xx_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/dmaengine.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
diff -druN linux-libre-3.1-gnu/drivers/dma/imx-dma.c linux-libre-3.2-gnu/drivers/dma/imx-dma.c
--- linux-libre-3.1-gnu/drivers/dma/imx-dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/imx-dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
@@ -23,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/dmaengine.h>
+#include <linux/module.h>
 
 #include <asm/irq.h>
 #include <mach/dma-v1.h>
diff -druN linux-libre-3.1-gnu/drivers/dma/imx-sdma.c linux-libre-3.2-gnu/drivers/dma/imx-sdma.c
--- linux-libre-3.1-gnu/drivers/dma/imx-sdma.c	2012-03-19 21:30:50.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/imx-sdma.c	2012-03-19 21:32:25.000000000 -0400
@@ -18,6 +18,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
@@ -34,6 +35,7 @@
 #include <linux/dmaengine.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/module.h>
 
 #include <asm/irq.h>
 #include <mach/sdma.h>
@@ -318,6 +320,7 @@
 	dma_addr_t			context_phys;
 	struct dma_device		dma_device;
 	struct clk			*clk;
+	struct mutex			channel_0_lock;
 	struct sdma_script_start_addrs	*script_addrs;
 };
 
@@ -415,11 +418,15 @@
 	dma_addr_t buf_phys;
 	int ret;
 
+	mutex_lock(&sdma->channel_0_lock);
+
 	buf_virt = dma_alloc_coherent(NULL,
 			size,
 			&buf_phys, GFP_KERNEL);
-	if (!buf_virt)
-		return -ENOMEM;
+	if (!buf_virt) {
+		ret = -ENOMEM;
+		goto err_out;
+	}
 
 	bd0->mode.command = C0_SETPM;
 	bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
@@ -433,6 +440,9 @@
 
 	dma_free_coherent(NULL, size, buf_virt, buf_phys);
 
+err_out:
+	mutex_unlock(&sdma->channel_0_lock);
+
 	return ret;
 }
 
@@ -656,6 +666,8 @@
 	dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", sdmac->event_mask0);
 	dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", sdmac->event_mask1);
 
+	mutex_lock(&sdma->channel_0_lock);
+
 	memset(context, 0, sizeof(*context));
 	context->channel_state.pc = load_address;
 
@@ -676,6 +688,8 @@
 
 	ret = sdma_run_channel(&sdma->channel[0]);
 
+	mutex_unlock(&sdma->channel_0_lock);
+
 	return ret;
 }
 
@@ -1131,18 +1145,17 @@
 			saddr_arr[i] = addr_arr[i];
 }
 
-static int __init sdma_get_firmware(struct sdma_engine *sdma,
-		const char *fw_name)
+static void sdma_load_firmware(const struct firmware *fw, void *context)
 {
-	const struct firmware *fw;
+	struct sdma_engine *sdma = context;
 	const struct sdma_firmware_header *header;
-	int ret;
 	const struct sdma_script_start_addrs *addr;
 	unsigned short *ram_code;
 
-	ret = reject_firmware(&fw, fw_name, sdma->dev);
-	if (ret)
-		return ret;
+	if (!fw) {
+		dev_err(sdma->dev, "firmware not found\n");
+		return;
+	}
 
 	if (fw->size < sizeof(*header))
 		goto err_firmware;
@@ -1172,6 +1185,16 @@
 
 err_firmware:
 	release_firmware(fw);
+}
+
+static int __init sdma_get_firmware(struct sdma_engine *sdma,
+		const char *fw_name)
+{
+	int ret;
+
+	ret = reject_firmware_nowait(THIS_MODULE,
+			FW_ACTION_HOTPLUG, fw_name, sdma->dev,
+			GFP_KERNEL, sdma, sdma_load_firmware);
 
 	return ret;
 }
@@ -1269,11 +1292,14 @@
 	struct sdma_platform_data *pdata = pdev->dev.platform_data;
 	int i;
 	struct sdma_engine *sdma;
+	s32 *saddr_arr;
 
 	sdma = kzalloc(sizeof(*sdma), GFP_KERNEL);
 	if (!sdma)
 		return -ENOMEM;
 
+	mutex_init(&sdma->channel_0_lock);
+
 	sdma->dev = &pdev->dev;
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1310,6 +1336,11 @@
 		goto err_alloc;
 	}
 
+	/* initially no scripts available */
+	saddr_arr = (s32 *)sdma->script_addrs;
+	for (i = 0; i < SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; i++)
+		saddr_arr[i] = -EINVAL;
+
 	if (of_id)
 		pdev->id_entry = of_id->data;
 	sdma->devtype = pdev->id_entry->driver_data;
diff -druN linux-libre-3.1-gnu/drivers/dma/intel_mid_dma.c linux-libre-3.2-gnu/drivers/dma/intel_mid_dma.c
--- linux-libre-3.1-gnu/drivers/dma/intel_mid_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/intel_mid_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/interrupt.h>
 #include <linux/pm_runtime.h>
 #include <linux/intel_mid_dma.h>
+#include <linux/module.h>
 
 #define MAX_CHAN	4 /*max ch across controllers*/
 #include "intel_mid_dma_regs.h"
@@ -115,16 +116,15 @@
 
 /**
  * dmac1_mask_periphral_intr -	mask the periphral interrupt
- * @midc: dma channel for which masking is required
+ * @mid: dma device for which masking is required
  *
  * Masks the DMA periphral interrupt
  * this is valid for DMAC1 family controllers only
  * This controller should have periphral mask registers already mapped
  */
-static void dmac1_mask_periphral_intr(struct intel_mid_dma_chan *midc)
+static void dmac1_mask_periphral_intr(struct middma_device *mid)
 {
 	u32 pimr;
-	struct middma_device *mid = to_middma_device(midc->chan.device);
 
 	if (mid->pimr_mask) {
 		pimr = readl(mid->mask_reg + LNW_PERIPHRAL_MASK);
@@ -184,7 +184,6 @@
 static void disable_dma_interrupt(struct intel_mid_dma_chan *midc)
 {
 	/*Check LPE PISR, make sure fwd is disabled*/
-	dmac1_mask_periphral_intr(midc);
 	iowrite32(MASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_BLOCK);
 	iowrite32(MASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_TFR);
 	iowrite32(MASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_ERR);
@@ -1114,7 +1113,6 @@
 
 		midch->chan.device = &dma->common;
 		midch->chan.cookie =  1;
-		midch->chan.chan_id = i;
 		midch->ch_id = dma->chan_base + i;
 		pr_debug("MDMA:Init CH %d, ID %d\n", i, midch->ch_id);
 
@@ -1150,7 +1148,6 @@
 	dma_cap_set(DMA_SLAVE, dma->common.cap_mask);
 	dma_cap_set(DMA_PRIVATE, dma->common.cap_mask);
 	dma->common.dev = &pdev->dev;
-	dma->common.chancnt = dma->max_chan;
 
 	dma->common.device_alloc_chan_resources =
 					intel_mid_dma_alloc_chan_resources;
@@ -1350,6 +1347,7 @@
 		if (device->ch[i].in_use)
 			return -EAGAIN;
 	}
+	dmac1_mask_periphral_intr(device);
 	device->state = SUSPENDED;
 	pci_save_state(pci);
 	pci_disable_device(pci);
diff -druN linux-libre-3.1-gnu/drivers/dma/ipu/ipu_idmac.c linux-libre-3.2-gnu/drivers/dma/ipu/ipu_idmac.c
--- linux-libre-3.1-gnu/drivers/dma/ipu/ipu_idmac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/ipu/ipu_idmac.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/string.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/module.h>
 
 #include <mach/ipu.h>
 
@@ -1307,6 +1308,7 @@
 	    ipu_submit_buffer(ichan, descnew, sgnew, ichan->active_buffer) < 0) {
 		callback = descnew->txd.callback;
 		callback_param = descnew->txd.callback_param;
+		list_del_init(&descnew->list);
 		spin_unlock(&ichan->lock);
 		if (callback)
 			callback(callback_param);
@@ -1428,39 +1430,58 @@
 {
 	struct idmac_channel *ichan = to_idmac_chan(chan);
 	struct idmac *idmac = to_idmac(chan->device);
+	struct ipu *ipu = to_ipu(idmac);
+	struct list_head *list, *tmp;
 	unsigned long flags;
 	int i;
 
-	/* Only supports DMA_TERMINATE_ALL */
-	if (cmd != DMA_TERMINATE_ALL)
-		return -ENXIO;
+	switch (cmd) {
+	case DMA_PAUSE:
+		spin_lock_irqsave(&ipu->lock, flags);
+		ipu_ic_disable_task(ipu, chan->chan_id);
 
-	ipu_disable_channel(idmac, ichan,
-			    ichan->status >= IPU_CHANNEL_ENABLED);
+		/* Return all descriptors into "prepared" state */
+		list_for_each_safe(list, tmp, &ichan->queue)
+			list_del_init(list);
 
-	tasklet_disable(&to_ipu(idmac)->tasklet);
+		ichan->sg[0] = NULL;
+		ichan->sg[1] = NULL;
 
-	/* ichan->queue is modified in ISR, have to spinlock */
-	spin_lock_irqsave(&ichan->lock, flags);
-	list_splice_init(&ichan->queue, &ichan->free_list);
+		spin_unlock_irqrestore(&ipu->lock, flags);
 
-	if (ichan->desc)
-		for (i = 0; i < ichan->n_tx_desc; i++) {
-			struct idmac_tx_desc *desc = ichan->desc + i;
-			if (list_empty(&desc->list))
-				/* Descriptor was prepared, but not submitted */
-				list_add(&desc->list, &ichan->free_list);
+		ichan->status = IPU_CHANNEL_INITIALIZED;
+		break;
+	case DMA_TERMINATE_ALL:
+		ipu_disable_channel(idmac, ichan,
+				    ichan->status >= IPU_CHANNEL_ENABLED);
 
-			async_tx_clear_ack(&desc->txd);
-		}
+		tasklet_disable(&ipu->tasklet);
 
-	ichan->sg[0] = NULL;
-	ichan->sg[1] = NULL;
-	spin_unlock_irqrestore(&ichan->lock, flags);
+		/* ichan->queue is modified in ISR, have to spinlock */
+		spin_lock_irqsave(&ichan->lock, flags);
+		list_splice_init(&ichan->queue, &ichan->free_list);
 
-	tasklet_enable(&to_ipu(idmac)->tasklet);
+		if (ichan->desc)
+			for (i = 0; i < ichan->n_tx_desc; i++) {
+				struct idmac_tx_desc *desc = ichan->desc + i;
+				if (list_empty(&desc->list))
+					/* Descriptor was prepared, but not submitted */
+					list_add(&desc->list, &ichan->free_list);
 
-	ichan->status = IPU_CHANNEL_INITIALIZED;
+				async_tx_clear_ack(&desc->txd);
+			}
+
+		ichan->sg[0] = NULL;
+		ichan->sg[1] = NULL;
+		spin_unlock_irqrestore(&ichan->lock, flags);
+
+		tasklet_enable(&ipu->tasklet);
+
+		ichan->status = IPU_CHANNEL_INITIALIZED;
+		break;
+	default:
+		return -ENOSYS;
+	}
 
 	return 0;
 }
@@ -1663,7 +1684,6 @@
 		struct idmac_channel *ichan = ipu->channel + i;
 
 		idmac_control(&ichan->dma_chan, DMA_TERMINATE_ALL, 0);
-		idmac_prep_slave_sg(&ichan->dma_chan, NULL, 0, DMA_NONE, 0);
 	}
 
 	dma_async_device_unregister(&idmac->dma);
diff -druN linux-libre-3.1-gnu/drivers/dma/ipu/ipu_irq.c linux-libre-3.2-gnu/drivers/dma/ipu/ipu_irq.c
--- linux-libre-3.1-gnu/drivers/dma/ipu/ipu_irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/ipu/ipu_irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -81,7 +81,7 @@
 /* Protects allocations from the above array of maps */
 static DEFINE_MUTEX(map_lock);
 /* Protects register accesses and individual mappings */
-static DEFINE_SPINLOCK(bank_lock);
+static DEFINE_RAW_SPINLOCK(bank_lock);
 
 static struct ipu_irq_map *src2map(unsigned int src)
 {
@@ -101,11 +101,11 @@
 	uint32_t reg;
 	unsigned long lock_flags;
 
-	spin_lock_irqsave(&bank_lock, lock_flags);
+	raw_spin_lock_irqsave(&bank_lock, lock_flags);
 
 	bank = map->bank;
 	if (!bank) {
-		spin_unlock_irqrestore(&bank_lock, lock_flags);
+		raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 		pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
 		return;
 	}
@@ -114,7 +114,7 @@
 	reg |= (1UL << (map->source & 31));
 	ipu_write_reg(bank->ipu, reg, bank->control);
 
-	spin_unlock_irqrestore(&bank_lock, lock_flags);
+	raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 }
 
 static void ipu_irq_mask(struct irq_data *d)
@@ -124,11 +124,11 @@
 	uint32_t reg;
 	unsigned long lock_flags;
 
-	spin_lock_irqsave(&bank_lock, lock_flags);
+	raw_spin_lock_irqsave(&bank_lock, lock_flags);
 
 	bank = map->bank;
 	if (!bank) {
-		spin_unlock_irqrestore(&bank_lock, lock_flags);
+		raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 		pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
 		return;
 	}
@@ -137,7 +137,7 @@
 	reg &= ~(1UL << (map->source & 31));
 	ipu_write_reg(bank->ipu, reg, bank->control);
 
-	spin_unlock_irqrestore(&bank_lock, lock_flags);
+	raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 }
 
 static void ipu_irq_ack(struct irq_data *d)
@@ -146,17 +146,17 @@
 	struct ipu_irq_bank *bank;
 	unsigned long lock_flags;
 
-	spin_lock_irqsave(&bank_lock, lock_flags);
+	raw_spin_lock_irqsave(&bank_lock, lock_flags);
 
 	bank = map->bank;
 	if (!bank) {
-		spin_unlock_irqrestore(&bank_lock, lock_flags);
+		raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 		pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
 		return;
 	}
 
 	ipu_write_reg(bank->ipu, 1UL << (map->source & 31), bank->status);
-	spin_unlock_irqrestore(&bank_lock, lock_flags);
+	raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 }
 
 /**
@@ -172,11 +172,11 @@
 	unsigned long lock_flags;
 	bool ret;
 
-	spin_lock_irqsave(&bank_lock, lock_flags);
+	raw_spin_lock_irqsave(&bank_lock, lock_flags);
 	bank = map->bank;
 	ret = bank && ipu_read_reg(bank->ipu, bank->status) &
 		(1UL << (map->source & 31));
-	spin_unlock_irqrestore(&bank_lock, lock_flags);
+	raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 
 	return ret;
 }
@@ -213,10 +213,10 @@
 		if (irq_map[i].source < 0) {
 			unsigned long lock_flags;
 
-			spin_lock_irqsave(&bank_lock, lock_flags);
+			raw_spin_lock_irqsave(&bank_lock, lock_flags);
 			irq_map[i].source = source;
 			irq_map[i].bank = irq_bank + source / 32;
-			spin_unlock_irqrestore(&bank_lock, lock_flags);
+			raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 
 			ret = irq_map[i].irq;
 			pr_debug("IPU: mapped source %u to IRQ %u\n",
@@ -252,10 +252,10 @@
 			pr_debug("IPU: unmapped source %u from IRQ %u\n",
 				 source, irq_map[i].irq);
 
-			spin_lock_irqsave(&bank_lock, lock_flags);
+			raw_spin_lock_irqsave(&bank_lock, lock_flags);
 			irq_map[i].source = -EINVAL;
 			irq_map[i].bank = NULL;
-			spin_unlock_irqrestore(&bank_lock, lock_flags);
+			raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 
 			ret = 0;
 			break;
@@ -276,7 +276,7 @@
 	for (i = IPU_IRQ_NR_FN_BANKS; i < IPU_IRQ_NR_BANKS; i++) {
 		struct ipu_irq_bank *bank = irq_bank + i;
 
-		spin_lock(&bank_lock);
+		raw_spin_lock(&bank_lock);
 		status = ipu_read_reg(ipu, bank->status);
 		/*
 		 * Don't think we have to clear all interrupts here, they will
@@ -284,18 +284,18 @@
 		 * might want to clear unhandled interrupts after the loop...
 		 */
 		status &= ipu_read_reg(ipu, bank->control);
-		spin_unlock(&bank_lock);
+		raw_spin_unlock(&bank_lock);
 		while ((line = ffs(status))) {
 			struct ipu_irq_map *map;
 
 			line--;
 			status &= ~(1UL << line);
 
-			spin_lock(&bank_lock);
+			raw_spin_lock(&bank_lock);
 			map = src2map(32 * i + line);
 			if (map)
 				irq = map->irq;
-			spin_unlock(&bank_lock);
+			raw_spin_unlock(&bank_lock);
 
 			if (!map) {
 				pr_err("IPU: Interrupt on unmapped source %u bank %d\n",
@@ -317,22 +317,22 @@
 	for (i = 0; i < IPU_IRQ_NR_FN_BANKS; i++) {
 		struct ipu_irq_bank *bank = irq_bank + i;
 
-		spin_lock(&bank_lock);
+		raw_spin_lock(&bank_lock);
 		status = ipu_read_reg(ipu, bank->status);
 		/* Not clearing all interrupts, see above */
 		status &= ipu_read_reg(ipu, bank->control);
-		spin_unlock(&bank_lock);
+		raw_spin_unlock(&bank_lock);
 		while ((line = ffs(status))) {
 			struct ipu_irq_map *map;
 
 			line--;
 			status &= ~(1UL << line);
 
-			spin_lock(&bank_lock);
+			raw_spin_lock(&bank_lock);
 			map = src2map(32 * i + line);
 			if (map)
 				irq = map->irq;
-			spin_unlock(&bank_lock);
+			raw_spin_unlock(&bank_lock);
 
 			if (!map) {
 				pr_err("IPU: Interrupt on unmapped source %u bank %d\n",
diff -druN linux-libre-3.1-gnu/drivers/dma/Kconfig linux-libre-3.2-gnu/drivers/dma/Kconfig
--- linux-libre-3.1-gnu/drivers/dma/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -124,7 +124,7 @@
 
 config MX3_IPU
 	bool "MX3x Image Processing Unit support"
-	depends on ARCH_MX3
+	depends on SOC_IMX31 ||Â SOC_IMX35
 	select DMA_ENGINE
 	default y
 	help
@@ -193,7 +193,8 @@
 config PL330_DMA
 	tristate "DMA API Driver for PL330"
 	select DMA_ENGINE
-	depends on PL330
+	depends on ARM_AMBA
+	select PL330
 	help
 	  Select if your platform has one or more PL330 DMACs.
 	  You need to provide platform specific settings via
@@ -215,7 +216,7 @@
 
 config IMX_SDMA
 	tristate "i.MX SDMA support"
-	depends on ARCH_MX25 || ARCH_MX3 || ARCH_MX5
+	depends on ARCH_MX25 || SOC_IMX31 ||Â SOC_IMX35 || ARCH_MX5
 	select DMA_ENGINE
 	help
 	  Support the i.MX SDMA engine. This engine is integrated into
diff -druN linux-libre-3.1-gnu/drivers/dma/mpc512x_dma.c linux-libre-3.2-gnu/drivers/dma/mpc512x_dma.c
--- linux-libre-3.1-gnu/drivers/dma/mpc512x_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/mpc512x_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -741,7 +741,6 @@
 		mchan = &mdma->channels[i];
 
 		mchan->chan.device = dma;
-		mchan->chan.chan_id = i;
 		mchan->chan.cookie = 1;
 		mchan->completed_cookie = mchan->chan.cookie;
 
diff -druN linux-libre-3.1-gnu/drivers/dma/mxs-dma.c linux-libre-3.2-gnu/drivers/dma/mxs-dma.c
--- linux-libre-3.1-gnu/drivers/dma/mxs-dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/mxs-dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -130,6 +130,23 @@
 	struct mxs_dma_chan		mxs_chans[MXS_DMA_CHANNELS];
 };
 
+static inline void mxs_dma_clkgate(struct mxs_dma_chan *mxs_chan, int enable)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+	int set_clr = enable ? MXS_CLR_ADDR : MXS_SET_ADDR;
+
+	/* 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 + set_clr);
+		else
+			writel(1 << chan_id,
+				mxs_dma->base + HW_APBHX_CTRL0 + set_clr);
+	}
+}
+
 static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan)
 {
 	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
@@ -148,38 +165,21 @@
 	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
 	int chan_id = mxs_chan->chan.chan_id;
 
+	/* clkgate needs to be enabled before writing other registers */
+	mxs_dma_clkgate(mxs_chan, 1);
+
 	/* 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_dma_clkgate(mxs_chan, 0);
 
 	mxs_chan->status = DMA_SUCCESS;
 }
@@ -338,7 +338,10 @@
 	if (ret)
 		goto err_clk;
 
+	/* clkgate needs to be enabled for reset to finish */
+	mxs_dma_clkgate(mxs_chan, 1);
 	mxs_dma_reset_chan(mxs_chan);
+	mxs_dma_clkgate(mxs_chan, 0);
 
 	dma_async_tx_descriptor_init(&mxs_chan->desc, chan);
 	mxs_chan->desc.tx_submit = mxs_dma_tx_submit;
diff -druN linux-libre-3.1-gnu/drivers/dma/pch_dma.c linux-libre-3.2-gnu/drivers/dma/pch_dma.c
--- linux-libre-3.1-gnu/drivers/dma/pch_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/pch_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,7 +60,7 @@
 #define DMA_DESC_FOLLOW_WITHOUT_IRQ	0x2
 #define DMA_DESC_FOLLOW_WITH_IRQ	0x3
 
-#define MAX_CHAN_NR			8
+#define MAX_CHAN_NR			12
 
 #define DMA_MASK_CTL0_MODE	0x33333333
 #define DMA_MASK_CTL2_MODE	0x00003333
@@ -872,8 +872,7 @@
 	int i;
 
 	nr_channels = id->driver_data;
-	pd = kzalloc(sizeof(struct pch_dma)+
-		sizeof(struct pch_dma_chan) * nr_channels, GFP_KERNEL);
+	pd = kzalloc(sizeof(*pd), GFP_KERNEL);
 	if (!pd)
 		return -ENOMEM;
 
@@ -926,7 +925,6 @@
 	}
 
 	pd->dma.dev = &pdev->dev;
-	pd->dma.chancnt = nr_channels;
 
 	INIT_LIST_HEAD(&pd->dma.channels);
 
@@ -935,7 +933,6 @@
 
 		pd_chan->chan.device = &pd->dma;
 		pd_chan->chan.cookie = 1;
-		pd_chan->chan.chan_id = i;
 
 		pd_chan->membase = &regs->desc[i];
 
diff -druN linux-libre-3.1-gnu/drivers/dma/pl330.c linux-libre-3.2-gnu/drivers/dma/pl330.c
--- linux-libre-3.1-gnu/drivers/dma/pl330.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/pl330.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,8 @@
 #include <linux/interrupt.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl330.h>
+#include <linux/pm_runtime.h>
+#include <linux/scatterlist.h>
 
 #define NR_DEFAULT_DESC	16
 
@@ -68,6 +70,14 @@
 	 * NULL if the channel is available to be acquired.
 	 */
 	void *pl330_chid;
+
+	/* For D-to-M and M-to-D channels */
+	int burst_sz; /* the peripheral fifo width */
+	int burst_len; /* the number of burst */
+	dma_addr_t fifo_addr;
+
+	/* for cyclic capability */
+	bool cyclic;
 };
 
 struct dma_pl330_dmac {
@@ -83,6 +93,8 @@
 
 	/* Peripheral channels connected to this DMAC */
 	struct dma_pl330_chan *peripherals; /* keep at end */
+
+	struct clk *clk;
 };
 
 struct dma_pl330_desc {
@@ -152,6 +164,31 @@
 	spin_unlock_irqrestore(&pdmac->pool_lock, flags);
 }
 
+static inline void handle_cyclic_desc_list(struct list_head *list)
+{
+	struct dma_pl330_desc *desc;
+	struct dma_pl330_chan *pch;
+	unsigned long flags;
+
+	if (list_empty(list))
+		return;
+
+	list_for_each_entry(desc, list, node) {
+		dma_async_tx_callback callback;
+
+		/* Change status to reload it */
+		desc->status = PREP;
+		pch = desc->pchan;
+		callback = desc->txd.callback;
+		if (callback)
+			callback(desc->txd.callback_param);
+	}
+
+	spin_lock_irqsave(&pch->lock, flags);
+	list_splice_tail_init(list, &pch->work_list);
+	spin_unlock_irqrestore(&pch->lock, flags);
+}
+
 static inline void fill_queue(struct dma_pl330_chan *pch)
 {
 	struct dma_pl330_desc *desc;
@@ -205,7 +242,10 @@
 
 	spin_unlock_irqrestore(&pch->lock, flags);
 
-	free_desc_list(&list);
+	if (pch->cyclic)
+		handle_cyclic_desc_list(&list);
+	else
+		free_desc_list(&list);
 }
 
 static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
@@ -236,6 +276,7 @@
 	spin_lock_irqsave(&pch->lock, flags);
 
 	pch->completed = chan->cookie = 1;
+	pch->cyclic = false;
 
 	pch->pl330_chid = pl330_request_channel(&pdmac->pif);
 	if (!pch->pl330_chid) {
@@ -253,25 +294,52 @@
 static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg)
 {
 	struct dma_pl330_chan *pch = to_pchan(chan);
-	struct dma_pl330_desc *desc;
+	struct dma_pl330_desc *desc, *_dt;
 	unsigned long flags;
+	struct dma_pl330_dmac *pdmac = pch->dmac;
+	struct dma_slave_config *slave_config;
+	LIST_HEAD(list);
 
-	/* Only supports DMA_TERMINATE_ALL */
-	if (cmd != DMA_TERMINATE_ALL)
-		return -ENXIO;
-
-	spin_lock_irqsave(&pch->lock, flags);
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		spin_lock_irqsave(&pch->lock, flags);
 
-	/* FLUSH the PL330 Channel thread */
-	pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
+		/* FLUSH the PL330 Channel thread */
+		pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
 
-	/* Mark all desc done */
-	list_for_each_entry(desc, &pch->work_list, node)
-		desc->status = DONE;
+		/* Mark all desc done */
+		list_for_each_entry_safe(desc, _dt, &pch->work_list , node) {
+			desc->status = DONE;
+			pch->completed = desc->txd.cookie;
+			list_move_tail(&desc->node, &list);
+		}
 
-	spin_unlock_irqrestore(&pch->lock, flags);
+		list_splice_tail_init(&list, &pdmac->desc_pool);
+		spin_unlock_irqrestore(&pch->lock, flags);
+		break;
+	case DMA_SLAVE_CONFIG:
+		slave_config = (struct dma_slave_config *)arg;
 
-	pl330_tasklet((unsigned long) pch);
+		if (slave_config->direction == DMA_TO_DEVICE) {
+			if (slave_config->dst_addr)
+				pch->fifo_addr = slave_config->dst_addr;
+			if (slave_config->dst_addr_width)
+				pch->burst_sz = __ffs(slave_config->dst_addr_width);
+			if (slave_config->dst_maxburst)
+				pch->burst_len = slave_config->dst_maxburst;
+		} else if (slave_config->direction == DMA_FROM_DEVICE) {
+			if (slave_config->src_addr)
+				pch->fifo_addr = slave_config->src_addr;
+			if (slave_config->src_addr_width)
+				pch->burst_sz = __ffs(slave_config->src_addr_width);
+			if (slave_config->src_maxburst)
+				pch->burst_len = slave_config->src_maxburst;
+		}
+		break;
+	default:
+		dev_err(pch->dmac->pif.dev, "Not supported command.\n");
+		return -ENXIO;
+	}
 
 	return 0;
 }
@@ -288,6 +356,9 @@
 	pl330_release_channel(pch->pl330_chid);
 	pch->pl330_chid = NULL;
 
+	if (pch->cyclic)
+		list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
+
 	spin_unlock_irqrestore(&pch->lock, flags);
 }
 
@@ -453,7 +524,7 @@
 
 	if (peri) {
 		desc->req.rqtype = peri->rqtype;
-		desc->req.peri = peri->peri_id;
+		desc->req.peri = pch->chan.chan_id;
 	} else {
 		desc->req.rqtype = MEMTOMEM;
 		desc->req.peri = 0;
@@ -524,6 +595,51 @@
 	return burst_len;
 }
 
+static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
+		struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
+		size_t period_len, enum dma_data_direction direction)
+{
+	struct dma_pl330_desc *desc;
+	struct dma_pl330_chan *pch = to_pchan(chan);
+	dma_addr_t dst;
+	dma_addr_t src;
+
+	desc = pl330_get_desc(pch);
+	if (!desc) {
+		dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
+			__func__, __LINE__);
+		return NULL;
+	}
+
+	switch (direction) {
+	case DMA_TO_DEVICE:
+		desc->rqcfg.src_inc = 1;
+		desc->rqcfg.dst_inc = 0;
+		src = dma_addr;
+		dst = pch->fifo_addr;
+		break;
+	case DMA_FROM_DEVICE:
+		desc->rqcfg.src_inc = 0;
+		desc->rqcfg.dst_inc = 1;
+		src = pch->fifo_addr;
+		dst = dma_addr;
+		break;
+	default:
+		dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n",
+		__func__, __LINE__);
+		return NULL;
+	}
+
+	desc->rqcfg.brst_size = pch->burst_sz;
+	desc->rqcfg.brst_len = 1;
+
+	pch->cyclic = true;
+
+	fill_px(&desc->px, dst, src, period_len);
+
+	return &desc->txd;
+}
+
 static struct dma_async_tx_descriptor *
 pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
 		dma_addr_t src, size_t len, unsigned long flags)
@@ -579,7 +695,7 @@
 	struct dma_pl330_peri *peri = chan->private;
 	struct scatterlist *sg;
 	unsigned long flags;
-	int i, burst_size;
+	int i;
 	dma_addr_t addr;
 
 	if (unlikely(!pch || !sgl || !sg_len || !peri))
@@ -595,8 +711,7 @@
 		return NULL;
 	}
 
-	addr = peri->fifo_addr;
-	burst_size = peri->burst_sz;
+	addr = pch->fifo_addr;
 
 	first = NULL;
 
@@ -644,7 +759,7 @@
 				sg_dma_address(sg), addr, sg_dma_len(sg));
 		}
 
-		desc->rqcfg.brst_size = burst_size;
+		desc->rqcfg.brst_size = pch->burst_sz;
 		desc->rqcfg.brst_len = 1;
 	}
 
@@ -696,6 +811,30 @@
 		goto probe_err1;
 	}
 
+	pdmac->clk = clk_get(&adev->dev, "dma");
+	if (IS_ERR(pdmac->clk)) {
+		dev_err(&adev->dev, "Cannot get operation clock.\n");
+		ret = -EINVAL;
+		goto probe_err1;
+	}
+
+	amba_set_drvdata(adev, pdmac);
+
+#ifdef CONFIG_PM_RUNTIME
+	/* to use the runtime PM helper functions */
+	pm_runtime_enable(&adev->dev);
+
+	/* enable the power domain */
+	if (pm_runtime_get_sync(&adev->dev)) {
+		dev_err(&adev->dev, "failed to get runtime pm\n");
+		ret = -ENODEV;
+		goto probe_err1;
+	}
+#else
+	/* enable dma clk */
+	clk_enable(pdmac->clk);
+#endif
+
 	irq = adev->irq[0];
 	ret = request_irq(irq, pl330_irq_handler, 0,
 			dev_name(&adev->dev), pi);
@@ -732,6 +871,7 @@
 			case MEMTODEV:
 			case DEVTOMEM:
 				dma_cap_set(DMA_SLAVE, pd->cap_mask);
+				dma_cap_set(DMA_CYCLIC, pd->cap_mask);
 				break;
 			default:
 				dev_err(&adev->dev, "DEVTODEV Not Supported\n");
@@ -747,11 +887,9 @@
 		spin_lock_init(&pch->lock);
 		pch->pl330_chid = NULL;
 		pch->chan.device = pd;
-		pch->chan.chan_id = i;
 		pch->dmac = pdmac;
 
 		/* Add the channel to the DMAC list */
-		pd->chancnt++;
 		list_add_tail(&pch->chan.device_node, &pd->channels);
 	}
 
@@ -760,6 +898,7 @@
 	pd->device_alloc_chan_resources = pl330_alloc_chan_resources;
 	pd->device_free_chan_resources = pl330_free_chan_resources;
 	pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy;
+	pd->device_prep_dma_cyclic = pl330_prep_dma_cyclic;
 	pd->device_tx_status = pl330_tx_status;
 	pd->device_prep_slave_sg = pl330_prep_slave_sg;
 	pd->device_control = pl330_control;
@@ -771,8 +910,6 @@
 		goto probe_err4;
 	}
 
-	amba_set_drvdata(adev, pdmac);
-
 	dev_info(&adev->dev,
 		"Loaded driver for PL330 DMAC-%d\n", adev->periphid);
 	dev_info(&adev->dev,
@@ -833,6 +970,13 @@
 	res = &adev->res;
 	release_mem_region(res->start, resource_size(res));
 
+#ifdef CONFIG_PM_RUNTIME
+	pm_runtime_put(&adev->dev);
+	pm_runtime_disable(&adev->dev);
+#else
+	clk_disable(pdmac->clk);
+#endif
+
 	kfree(pdmac);
 
 	return 0;
@@ -846,10 +990,49 @@
 	{ 0, 0 },
 };
 
+#ifdef CONFIG_PM_RUNTIME
+static int pl330_runtime_suspend(struct device *dev)
+{
+	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
+
+	if (!pdmac) {
+		dev_err(dev, "failed to get dmac\n");
+		return -ENODEV;
+	}
+
+	clk_disable(pdmac->clk);
+
+	return 0;
+}
+
+static int pl330_runtime_resume(struct device *dev)
+{
+	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
+
+	if (!pdmac) {
+		dev_err(dev, "failed to get dmac\n");
+		return -ENODEV;
+	}
+
+	clk_enable(pdmac->clk);
+
+	return 0;
+}
+#else
+#define pl330_runtime_suspend	NULL
+#define pl330_runtime_resume	NULL
+#endif /* CONFIG_PM_RUNTIME */
+
+static const struct dev_pm_ops pl330_pm_ops = {
+	.runtime_suspend = pl330_runtime_suspend,
+	.runtime_resume = pl330_runtime_resume,
+};
+
 static struct amba_driver pl330_driver = {
 	.drv = {
 		.owner = THIS_MODULE,
 		.name = "dma-pl330",
+		.pm = &pl330_pm_ops,
 	},
 	.id_table = pl330_ids,
 	.probe = pl330_probe,
diff -druN linux-libre-3.1-gnu/drivers/dma/shdma.c linux-libre-3.2-gnu/drivers/dma/shdma.c
--- linux-libre-3.1-gnu/drivers/dma/shdma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/shdma.c	2012-01-04 18:55:44.000000000 -0500
@@ -259,14 +259,23 @@
 	return 0;
 }
 
+static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan);
+
 static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)
 {
 	struct sh_desc *desc = tx_to_sh_desc(tx), *chunk, *last = desc, *c;
 	struct sh_dmae_chan *sh_chan = to_sh_chan(tx->chan);
+	struct sh_dmae_slave *param = tx->chan->private;
 	dma_async_tx_callback callback = tx->callback;
 	dma_cookie_t cookie;
+	bool power_up;
 
-	spin_lock_bh(&sh_chan->desc_lock);
+	spin_lock_irq(&sh_chan->desc_lock);
+
+	if (list_empty(&sh_chan->ld_queue))
+		power_up = true;
+	else
+		power_up = false;
 
 	cookie = sh_chan->common.cookie;
 	cookie++;
@@ -302,7 +311,38 @@
 		tx->cookie, &last->async_tx, sh_chan->id,
 		desc->hw.sar, desc->hw.tcr, desc->hw.dar);
 
-	spin_unlock_bh(&sh_chan->desc_lock);
+	if (power_up) {
+		sh_chan->pm_state = DMAE_PM_BUSY;
+
+		pm_runtime_get(sh_chan->dev);
+
+		spin_unlock_irq(&sh_chan->desc_lock);
+
+		pm_runtime_barrier(sh_chan->dev);
+
+		spin_lock_irq(&sh_chan->desc_lock);
+
+		/* Have we been reset, while waiting? */
+		if (sh_chan->pm_state != DMAE_PM_ESTABLISHED) {
+			dev_dbg(sh_chan->dev, "Bring up channel %d\n",
+				sh_chan->id);
+			if (param) {
+				const struct sh_dmae_slave_config *cfg =
+					param->config;
+
+				dmae_set_dmars(sh_chan, cfg->mid_rid);
+				dmae_set_chcr(sh_chan, cfg->chcr);
+			} else {
+				dmae_init(sh_chan);
+			}
+
+			if (sh_chan->pm_state == DMAE_PM_PENDING)
+				sh_chan_xfer_ld_queue(sh_chan);
+			sh_chan->pm_state = DMAE_PM_ESTABLISHED;
+		}
+	}
+
+	spin_unlock_irq(&sh_chan->desc_lock);
 
 	return cookie;
 }
@@ -346,8 +386,6 @@
 	struct sh_dmae_slave *param = chan->private;
 	int ret;
 
-	pm_runtime_get_sync(sh_chan->dev);
-
 	/*
 	 * This relies on the guarantee from dmaengine that alloc_chan_resources
 	 * never runs concurrently with itself or free_chan_resources.
@@ -367,31 +405,20 @@
 		}
 
 		param->config = cfg;
-
-		dmae_set_dmars(sh_chan, cfg->mid_rid);
-		dmae_set_chcr(sh_chan, cfg->chcr);
-	} else {
-		dmae_init(sh_chan);
 	}
 
-	spin_lock_bh(&sh_chan->desc_lock);
 	while (sh_chan->descs_allocated < NR_DESCS_PER_CHANNEL) {
-		spin_unlock_bh(&sh_chan->desc_lock);
 		desc = kzalloc(sizeof(struct sh_desc), GFP_KERNEL);
-		if (!desc) {
-			spin_lock_bh(&sh_chan->desc_lock);
+		if (!desc)
 			break;
-		}
 		dma_async_tx_descriptor_init(&desc->async_tx,
 					&sh_chan->common);
 		desc->async_tx.tx_submit = sh_dmae_tx_submit;
 		desc->mark = DESC_IDLE;
 
-		spin_lock_bh(&sh_chan->desc_lock);
 		list_add(&desc->node, &sh_chan->ld_free);
 		sh_chan->descs_allocated++;
 	}
-	spin_unlock_bh(&sh_chan->desc_lock);
 
 	if (!sh_chan->descs_allocated) {
 		ret = -ENOMEM;
@@ -405,7 +432,7 @@
 		clear_bit(param->slave_id, sh_dmae_slave_used);
 etestused:
 efindslave:
-	pm_runtime_put(sh_chan->dev);
+	chan->private = NULL;
 	return ret;
 }
 
@@ -417,7 +444,6 @@
 	struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
 	struct sh_desc *desc, *_desc;
 	LIST_HEAD(list);
-	int descs = sh_chan->descs_allocated;
 
 	/* Protect against ISR */
 	spin_lock_irq(&sh_chan->desc_lock);
@@ -437,15 +463,12 @@
 		chan->private = NULL;
 	}
 
-	spin_lock_bh(&sh_chan->desc_lock);
+	spin_lock_irq(&sh_chan->desc_lock);
 
 	list_splice_init(&sh_chan->ld_free, &list);
 	sh_chan->descs_allocated = 0;
 
-	spin_unlock_bh(&sh_chan->desc_lock);
-
-	if (descs > 0)
-		pm_runtime_put(sh_chan->dev);
+	spin_unlock_irq(&sh_chan->desc_lock);
 
 	list_for_each_entry_safe(desc, _desc, &list, node)
 		kfree(desc);
@@ -534,6 +557,7 @@
 	struct sh_desc *first = NULL, *new = NULL /* compiler... */;
 	LIST_HEAD(tx_list);
 	int chunks = 0;
+	unsigned long irq_flags;
 	int i;
 
 	if (!sg_len)
@@ -544,7 +568,7 @@
 			(SH_DMA_TCR_MAX + 1);
 
 	/* Have to lock the whole loop to protect against concurrent release */
-	spin_lock_bh(&sh_chan->desc_lock);
+	spin_lock_irqsave(&sh_chan->desc_lock, irq_flags);
 
 	/*
 	 * Chaining:
@@ -590,7 +614,7 @@
 	/* Put them back on the free list, so, they don't get lost */
 	list_splice_tail(&tx_list, &sh_chan->ld_free);
 
-	spin_unlock_bh(&sh_chan->desc_lock);
+	spin_unlock_irqrestore(&sh_chan->desc_lock, irq_flags);
 
 	return &first->async_tx;
 
@@ -599,7 +623,7 @@
 		new->mark = DESC_IDLE;
 	list_splice(&tx_list, &sh_chan->ld_free);
 
-	spin_unlock_bh(&sh_chan->desc_lock);
+	spin_unlock_irqrestore(&sh_chan->desc_lock, irq_flags);
 
 	return NULL;
 }
@@ -661,6 +685,7 @@
 			   unsigned long arg)
 {
 	struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
+	unsigned long flags;
 
 	/* Only supports DMA_TERMINATE_ALL */
 	if (cmd != DMA_TERMINATE_ALL)
@@ -669,7 +694,7 @@
 	if (!chan)
 		return -EINVAL;
 
-	spin_lock_bh(&sh_chan->desc_lock);
+	spin_lock_irqsave(&sh_chan->desc_lock, flags);
 	dmae_halt(sh_chan);
 
 	if (!list_empty(&sh_chan->ld_queue)) {
@@ -678,9 +703,8 @@
 						  struct sh_desc, node);
 		desc->partial = (desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) <<
 			sh_chan->xmit_shift;
-
 	}
-	spin_unlock_bh(&sh_chan->desc_lock);
+	spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
 
 	sh_dmae_chan_ld_cleanup(sh_chan, true);
 
@@ -695,8 +719,9 @@
 	dma_cookie_t cookie = 0;
 	dma_async_tx_callback callback = NULL;
 	void *param = NULL;
+	unsigned long flags;
 
-	spin_lock_bh(&sh_chan->desc_lock);
+	spin_lock_irqsave(&sh_chan->desc_lock, flags);
 	list_for_each_entry_safe(desc, _desc, &sh_chan->ld_queue, node) {
 		struct dma_async_tx_descriptor *tx = &desc->async_tx;
 
@@ -762,7 +787,13 @@
 		     async_tx_test_ack(&desc->async_tx)) || all) {
 			/* Remove from ld_queue list */
 			desc->mark = DESC_IDLE;
+
 			list_move(&desc->node, &sh_chan->ld_free);
+
+			if (list_empty(&sh_chan->ld_queue)) {
+				dev_dbg(sh_chan->dev, "Bring down channel %d\n", sh_chan->id);
+				pm_runtime_put(sh_chan->dev);
+			}
 		}
 	}
 
@@ -773,7 +804,7 @@
 		 */
 		sh_chan->completed_cookie = sh_chan->common.cookie;
 
-	spin_unlock_bh(&sh_chan->desc_lock);
+	spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
 
 	if (callback)
 		callback(param);
@@ -792,14 +823,14 @@
 		;
 }
 
+/* Called under spin_lock_irq(&sh_chan->desc_lock) */
 static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
 {
 	struct sh_desc *desc;
 
-	spin_lock_bh(&sh_chan->desc_lock);
 	/* DMA work check */
 	if (dmae_is_busy(sh_chan))
-		goto sh_chan_xfer_ld_queue_end;
+		return;
 
 	/* Find the first not transferred descriptor */
 	list_for_each_entry(desc, &sh_chan->ld_queue, node)
@@ -812,15 +843,18 @@
 			dmae_start(sh_chan);
 			break;
 		}
-
-sh_chan_xfer_ld_queue_end:
-	spin_unlock_bh(&sh_chan->desc_lock);
 }
 
 static void sh_dmae_memcpy_issue_pending(struct dma_chan *chan)
 {
 	struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
-	sh_chan_xfer_ld_queue(sh_chan);
+
+	spin_lock_irq(&sh_chan->desc_lock);
+	if (sh_chan->pm_state == DMAE_PM_ESTABLISHED)
+		sh_chan_xfer_ld_queue(sh_chan);
+	else
+		sh_chan->pm_state = DMAE_PM_PENDING;
+	spin_unlock_irq(&sh_chan->desc_lock);
 }
 
 static enum dma_status sh_dmae_tx_status(struct dma_chan *chan,
@@ -831,6 +865,7 @@
 	dma_cookie_t last_used;
 	dma_cookie_t last_complete;
 	enum dma_status status;
+	unsigned long flags;
 
 	sh_dmae_chan_ld_cleanup(sh_chan, false);
 
@@ -841,7 +876,7 @@
 	BUG_ON(last_complete < 0);
 	dma_set_tx_state(txstate, last_complete, last_used, 0);
 
-	spin_lock_bh(&sh_chan->desc_lock);
+	spin_lock_irqsave(&sh_chan->desc_lock, flags);
 
 	status = dma_async_is_complete(cookie, last_complete, last_used);
 
@@ -859,7 +894,7 @@
 			}
 	}
 
-	spin_unlock_bh(&sh_chan->desc_lock);
+	spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
 
 	return status;
 }
@@ -912,6 +947,12 @@
 
 		list_splice_init(&sh_chan->ld_queue, &dl);
 
+		if (!list_empty(&dl)) {
+			dev_dbg(sh_chan->dev, "Bring down channel %d\n", sh_chan->id);
+			pm_runtime_put(sh_chan->dev);
+		}
+		sh_chan->pm_state = DMAE_PM_ESTABLISHED;
+
 		spin_unlock(&sh_chan->desc_lock);
 
 		/* Complete all  */
@@ -952,7 +993,7 @@
 	u32 sar_buf = sh_dmae_readl(sh_chan, SAR);
 	u32 dar_buf = sh_dmae_readl(sh_chan, DAR);
 
-	spin_lock(&sh_chan->desc_lock);
+	spin_lock_irq(&sh_chan->desc_lock);
 	list_for_each_entry(desc, &sh_chan->ld_queue, node) {
 		if (desc->mark == DESC_SUBMITTED &&
 		    ((desc->direction == DMA_FROM_DEVICE &&
@@ -965,10 +1006,10 @@
 			break;
 		}
 	}
-	spin_unlock(&sh_chan->desc_lock);
-
 	/* Next desc */
 	sh_chan_xfer_ld_queue(sh_chan);
+	spin_unlock_irq(&sh_chan->desc_lock);
+
 	sh_dmae_chan_ld_cleanup(sh_chan, false);
 }
 
@@ -1036,7 +1077,9 @@
 		return -ENOMEM;
 	}
 
-	/* copy struct dma_device */
+	new_sh_chan->pm_state = DMAE_PM_ESTABLISHED;
+
+	/* reference struct dma_device */
 	new_sh_chan->common.device = &shdev->common;
 
 	new_sh_chan->dev = shdev->common.dev;
diff -druN linux-libre-3.1-gnu/drivers/dma/shdma.h linux-libre-3.2-gnu/drivers/dma/shdma.h
--- linux-libre-3.1-gnu/drivers/dma/shdma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/shdma.h	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,12 @@
 
 struct device;
 
+enum dmae_pm_state {
+	DMAE_PM_ESTABLISHED,
+	DMAE_PM_BUSY,
+	DMAE_PM_PENDING,
+};
+
 struct sh_dmae_chan {
 	dma_cookie_t completed_cookie;	/* The maximum cookie completed */
 	spinlock_t desc_lock;		/* Descriptor operation lock */
@@ -38,6 +44,7 @@
 	u32 __iomem *base;
 	char dev_id[16];		/* unique name per DMAC of channel */
 	int pm_error;
+	enum dmae_pm_state pm_state;
 };
 
 struct sh_dmae_device {
diff -druN linux-libre-3.1-gnu/drivers/dma/ste_dma40.c linux-libre-3.2-gnu/drivers/dma/ste_dma40.c
--- linux-libre-3.1-gnu/drivers/dma/ste_dma40.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/ste_dma40.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/dmaengine.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
diff -druN linux-libre-3.1-gnu/drivers/dma/timb_dma.c linux-libre-3.2-gnu/drivers/dma/timb_dma.c
--- linux-libre-3.1-gnu/drivers/dma/timb_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/dma/timb_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -753,7 +753,7 @@
 
 	INIT_LIST_HEAD(&td->dma.channels);
 
-	for (i = 0; i < pdata->nr_channels; i++, td->dma.chancnt++) {
+	for (i = 0; i < pdata->nr_channels; i++) {
 		struct timb_dma_chan *td_chan = &td->channels[i];
 		struct timb_dma_platform_data_channel *pchan =
 			pdata->channels + i;
@@ -762,12 +762,11 @@
 		if ((i % 2) == pchan->rx) {
 			dev_err(&pdev->dev, "Wrong channel configuration\n");
 			err = -EINVAL;
-			goto err_tasklet_kill;
+			goto err_free_irq;
 		}
 
 		td_chan->chan.device = &td->dma;
 		td_chan->chan.cookie = 1;
-		td_chan->chan.chan_id = i;
 		spin_lock_init(&td_chan->lock);
 		INIT_LIST_HEAD(&td_chan->active_list);
 		INIT_LIST_HEAD(&td_chan->queue);
diff -druN linux-libre-3.1-gnu/drivers/edac/amd64_edac.c linux-libre-3.2-gnu/drivers/edac/amd64_edac.c
--- linux-libre-3.1-gnu/drivers/edac/amd64_edac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/edac/amd64_edac.c	2012-01-04 18:55:44.000000000 -0500
@@ -114,10 +114,22 @@
 	return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func);
 }
 
+/*
+ * Select DCT to which PCI cfg accesses are routed
+ */
+static void f15h_select_dct(struct amd64_pvt *pvt, u8 dct)
+{
+	u32 reg = 0;
+
+	amd64_read_pci_cfg(pvt->F1, DCT_CFG_SEL, &reg);
+	reg &= 0xfffffffe;
+	reg |= dct;
+	amd64_write_pci_cfg(pvt->F1, DCT_CFG_SEL, reg);
+}
+
 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) {
@@ -125,10 +137,7 @@
 		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);
+	f15h_select_dct(pvt, dct);
 
 	return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func);
 }
@@ -198,6 +207,10 @@
 	if (boot_cpu_data.x86 == 0xf)
 		min_scrubrate = 0x0;
 
+	/* F15h Erratum #505 */
+	if (boot_cpu_data.x86 == 0x15)
+		f15h_select_dct(pvt, 0);
+
 	return __amd64_set_scrub_rate(pvt->F3, bw, min_scrubrate);
 }
 
@@ -207,6 +220,10 @@
 	u32 scrubval = 0;
 	int i, retval = -EINVAL;
 
+	/* F15h Erratum #505 */
+	if (boot_cpu_data.x86 == 0x15)
+		f15h_select_dct(pvt, 0);
+
 	amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval);
 
 	scrubval = scrubval & 0x001F;
@@ -751,10 +768,10 @@
  * 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)
+static unsigned long amd64_determine_edac_cap(struct amd64_pvt *pvt)
 {
 	u8 bit;
-	enum dev_type edac_cap = EDAC_FLAG_NONE;
+	unsigned long edac_cap = EDAC_FLAG_NONE;
 
 	bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= K8_REV_F)
 		? 19
@@ -1953,11 +1970,9 @@
 		amd64_handle_ue(mci, m);
 }
 
-void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg)
+void amd64_decode_bus_error(int node_id, struct mce *m)
 {
-	struct mem_ctl_info *mci = mcis[node_id];
-
-	__amd64_decode_bus_error(mci, m);
+	__amd64_decode_bus_error(mcis[node_id], m);
 }
 
 /*
diff -druN linux-libre-3.1-gnu/drivers/edac/cpc925_edac.c linux-libre-3.2-gnu/drivers/edac/cpc925_edac.c
--- linux-libre-3.1-gnu/drivers/edac/cpc925_edac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/edac/cpc925_edac.c	2012-01-04 18:55:44.000000000 -0500
@@ -90,6 +90,7 @@
 	ECC_MASK_ENABLE = (APIMASK_ECC_UE_H | APIMASK_ECC_CE_H |
 			   APIMASK_ECC_UE_L | APIMASK_ECC_CE_L),
 };
+#define APIMASK_ADI(n)		CPC925_BIT(((n)+1))
 
 /************************************************************
  *	Processor Interface Exception Register (APIEXCP)
@@ -581,16 +582,73 @@
 }
 
 /******************** CPU err device********************************/
+static u32 cpc925_cpu_mask_disabled(void)
+{
+	struct device_node *cpus;
+	struct device_node *cpunode = NULL;
+	static u32 mask = 0;
+
+	/* use cached value if available */
+	if (mask != 0)
+		return mask;
+
+	mask = APIMASK_ADI0 | APIMASK_ADI1;
+
+	cpus = of_find_node_by_path("/cpus");
+	if (cpus == NULL) {
+		cpc925_printk(KERN_DEBUG, "No /cpus node !\n");
+		return 0;
+	}
+
+	while ((cpunode = of_get_next_child(cpus, cpunode)) != NULL) {
+		const u32 *reg = of_get_property(cpunode, "reg", NULL);
+
+		if (strcmp(cpunode->type, "cpu")) {
+			cpc925_printk(KERN_ERR, "Not a cpu node in /cpus: %s\n", cpunode->name);
+			continue;
+		}
+
+		if (reg == NULL || *reg > 2) {
+			cpc925_printk(KERN_ERR, "Bad reg value at %s\n", cpunode->full_name);
+			continue;
+		}
+
+		mask &= ~APIMASK_ADI(*reg);
+	}
+
+	if (mask != (APIMASK_ADI0 | APIMASK_ADI1)) {
+		/* We assume that each CPU sits on it's own PI and that
+		 * for present CPUs the reg property equals to the PI
+		 * interface id */
+		cpc925_printk(KERN_WARNING,
+				"Assuming PI id is equal to CPU MPIC id!\n");
+	}
+
+	of_node_put(cpunode);
+	of_node_put(cpus);
+
+	return mask;
+}
+
 /* Enable CPU Errors detection */
 static void cpc925_cpu_init(struct cpc925_dev_info *dev_info)
 {
 	u32 apimask;
+	u32 cpumask;
 
 	apimask = __raw_readl(dev_info->vbase + REG_APIMASK_OFFSET);
-	if ((apimask & CPU_MASK_ENABLE) == 0) {
-		apimask |= CPU_MASK_ENABLE;
-		__raw_writel(apimask, dev_info->vbase + REG_APIMASK_OFFSET);
+
+	cpumask = cpc925_cpu_mask_disabled();
+	if (apimask & cpumask) {
+		cpc925_printk(KERN_WARNING, "CPU(s) not present, "
+				"but enabled in APIMASK, disabling\n");
+		apimask &= ~cpumask;
 	}
+
+	if ((apimask & CPU_MASK_ENABLE) == 0)
+		apimask |= CPU_MASK_ENABLE;
+
+	__raw_writel(apimask, dev_info->vbase + REG_APIMASK_OFFSET);
 }
 
 /* Disable CPU Errors detection */
@@ -622,6 +680,9 @@
 	if ((apiexcp & CPU_EXCP_DETECTED) == 0)
 		return;
 
+	if ((apiexcp & ~cpc925_cpu_mask_disabled()) == 0)
+		return;
+
 	apimask = __raw_readl(dev_info->vbase + REG_APIMASK_OFFSET);
 	cpc925_printk(KERN_INFO, "Processor Interface Fault\n"
 				 "Processor Interface register dump:\n");
diff -druN linux-libre-3.1-gnu/drivers/edac/edac_core.h linux-libre-3.2-gnu/drivers/edac/edac_core.h
--- linux-libre-3.1-gnu/drivers/edac/edac_core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/edac/edac_core.h	2012-01-04 18:55:44.000000000 -0500
@@ -34,11 +34,10 @@
 #include <linux/platform_device.h>
 #include <linux/sysdev.h>
 #include <linux/workqueue.h>
+#include <linux/edac.h>
 
-#define EDAC_MC_LABEL_LEN	31
 #define EDAC_DEVICE_NAME_LEN	31
 #define EDAC_ATTRIB_VALUE_LEN	15
-#define MC_PROC_NAME_MAX_LEN	7
 
 #if PAGE_SHIFT < 20
 #define PAGES_TO_MiB(pages)	((pages) >> (20 - PAGE_SHIFT))
@@ -101,353 +100,6 @@
 
 #define edac_dev_name(dev) (dev)->dev_name
 
-/* memory devices */
-enum dev_type {
-	DEV_UNKNOWN = 0,
-	DEV_X1,
-	DEV_X2,
-	DEV_X4,
-	DEV_X8,
-	DEV_X16,
-	DEV_X32,		/* Do these parts exist? */
-	DEV_X64			/* Do these parts exist? */
-};
-
-#define DEV_FLAG_UNKNOWN	BIT(DEV_UNKNOWN)
-#define DEV_FLAG_X1		BIT(DEV_X1)
-#define DEV_FLAG_X2		BIT(DEV_X2)
-#define DEV_FLAG_X4		BIT(DEV_X4)
-#define DEV_FLAG_X8		BIT(DEV_X8)
-#define DEV_FLAG_X16		BIT(DEV_X16)
-#define DEV_FLAG_X32		BIT(DEV_X32)
-#define DEV_FLAG_X64		BIT(DEV_X64)
-
-/* memory types */
-enum mem_type {
-	MEM_EMPTY = 0,		/* Empty csrow */
-	MEM_RESERVED,		/* Reserved csrow type */
-	MEM_UNKNOWN,		/* Unknown csrow type */
-	MEM_FPM,		/* Fast page mode */
-	MEM_EDO,		/* Extended data out */
-	MEM_BEDO,		/* Burst Extended data out */
-	MEM_SDR,		/* Single data rate SDRAM */
-	MEM_RDR,		/* Registered single data rate SDRAM */
-	MEM_DDR,		/* Double data rate SDRAM */
-	MEM_RDDR,		/* Registered Double data rate SDRAM */
-	MEM_RMBS,		/* Rambus DRAM */
-	MEM_DDR2,		/* DDR2 RAM */
-	MEM_FB_DDR2,		/* fully buffered DDR2 */
-	MEM_RDDR2,		/* Registered DDR2 RAM */
-	MEM_XDR,		/* Rambus XDR */
-	MEM_DDR3,		/* DDR3 RAM */
-	MEM_RDDR3,		/* Registered DDR3 RAM */
-};
-
-#define MEM_FLAG_EMPTY		BIT(MEM_EMPTY)
-#define MEM_FLAG_RESERVED	BIT(MEM_RESERVED)
-#define MEM_FLAG_UNKNOWN	BIT(MEM_UNKNOWN)
-#define MEM_FLAG_FPM		BIT(MEM_FPM)
-#define MEM_FLAG_EDO		BIT(MEM_EDO)
-#define MEM_FLAG_BEDO		BIT(MEM_BEDO)
-#define MEM_FLAG_SDR		BIT(MEM_SDR)
-#define MEM_FLAG_RDR		BIT(MEM_RDR)
-#define MEM_FLAG_DDR		BIT(MEM_DDR)
-#define MEM_FLAG_RDDR		BIT(MEM_RDDR)
-#define MEM_FLAG_RMBS		BIT(MEM_RMBS)
-#define MEM_FLAG_DDR2           BIT(MEM_DDR2)
-#define MEM_FLAG_FB_DDR2        BIT(MEM_FB_DDR2)
-#define MEM_FLAG_RDDR2          BIT(MEM_RDDR2)
-#define MEM_FLAG_XDR            BIT(MEM_XDR)
-#define MEM_FLAG_DDR3		 BIT(MEM_DDR3)
-#define MEM_FLAG_RDDR3		 BIT(MEM_RDDR3)
-
-/* chipset Error Detection and Correction capabilities and mode */
-enum edac_type {
-	EDAC_UNKNOWN = 0,	/* Unknown if ECC is available */
-	EDAC_NONE,		/* Doesn't support ECC */
-	EDAC_RESERVED,		/* Reserved ECC type */
-	EDAC_PARITY,		/* Detects parity errors */
-	EDAC_EC,		/* Error Checking - no correction */
-	EDAC_SECDED,		/* Single bit error correction, Double detection */
-	EDAC_S2ECD2ED,		/* Chipkill x2 devices - do these exist? */
-	EDAC_S4ECD4ED,		/* Chipkill x4 devices */
-	EDAC_S8ECD8ED,		/* Chipkill x8 devices */
-	EDAC_S16ECD16ED,	/* Chipkill x16 devices */
-};
-
-#define EDAC_FLAG_UNKNOWN	BIT(EDAC_UNKNOWN)
-#define EDAC_FLAG_NONE		BIT(EDAC_NONE)
-#define EDAC_FLAG_PARITY	BIT(EDAC_PARITY)
-#define EDAC_FLAG_EC		BIT(EDAC_EC)
-#define EDAC_FLAG_SECDED	BIT(EDAC_SECDED)
-#define EDAC_FLAG_S2ECD2ED	BIT(EDAC_S2ECD2ED)
-#define EDAC_FLAG_S4ECD4ED	BIT(EDAC_S4ECD4ED)
-#define EDAC_FLAG_S8ECD8ED	BIT(EDAC_S8ECD8ED)
-#define EDAC_FLAG_S16ECD16ED	BIT(EDAC_S16ECD16ED)
-
-/* scrubbing capabilities */
-enum scrub_type {
-	SCRUB_UNKNOWN = 0,	/* Unknown if scrubber is available */
-	SCRUB_NONE,		/* No scrubber */
-	SCRUB_SW_PROG,		/* SW progressive (sequential) scrubbing */
-	SCRUB_SW_SRC,		/* Software scrub only errors */
-	SCRUB_SW_PROG_SRC,	/* Progressive software scrub from an error */
-	SCRUB_SW_TUNABLE,	/* Software scrub frequency is tunable */
-	SCRUB_HW_PROG,		/* HW progressive (sequential) scrubbing */
-	SCRUB_HW_SRC,		/* Hardware scrub only errors */
-	SCRUB_HW_PROG_SRC,	/* Progressive hardware scrub from an error */
-	SCRUB_HW_TUNABLE	/* Hardware scrub frequency is tunable */
-};
-
-#define SCRUB_FLAG_SW_PROG	BIT(SCRUB_SW_PROG)
-#define SCRUB_FLAG_SW_SRC	BIT(SCRUB_SW_SRC)
-#define SCRUB_FLAG_SW_PROG_SRC	BIT(SCRUB_SW_PROG_SRC)
-#define SCRUB_FLAG_SW_TUN	BIT(SCRUB_SW_SCRUB_TUNABLE)
-#define SCRUB_FLAG_HW_PROG	BIT(SCRUB_HW_PROG)
-#define SCRUB_FLAG_HW_SRC	BIT(SCRUB_HW_SRC)
-#define SCRUB_FLAG_HW_PROG_SRC	BIT(SCRUB_HW_PROG_SRC)
-#define SCRUB_FLAG_HW_TUN	BIT(SCRUB_HW_TUNABLE)
-
-/* FIXME - should have notify capabilities: NMI, LOG, PROC, etc */
-
-/* EDAC internal operation states */
-#define	OP_ALLOC		0x100
-#define OP_RUNNING_POLL		0x201
-#define OP_RUNNING_INTERRUPT	0x202
-#define OP_RUNNING_POLL_INTR	0x203
-#define OP_OFFLINE		0x300
-
-/*
- * There are several things to be aware of that aren't at all obvious:
- *
- *
- * SOCKETS, SOCKET SETS, BANKS, ROWS, CHIP-SELECT ROWS, CHANNELS, etc..
- *
- * These are some of the many terms that are thrown about that don't always
- * mean what people think they mean (Inconceivable!).  In the interest of
- * creating a common ground for discussion, terms and their definitions
- * will be established.
- *
- * Memory devices:	The individual chip on a memory stick.  These devices
- *			commonly output 4 and 8 bits each.  Grouping several
- *			of these in parallel provides 64 bits which is common
- *			for a memory stick.
- *
- * 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.
- *
- * Socket:		A physical connector on the motherboard that accepts
- *			a single memory stick.
- *
- * Channel:		Set of memory devices on a memory stick that must be
- *			grouped in parallel with one or more additional
- *			channels from other memory sticks.  This parallel
- *			grouping of the output from multiple channels are
- *			necessary for the smallest granularity of memory access.
- *			Some memory controllers are capable of single channel -
- *			which means that memory sticks can be loaded
- *			individually.  Other memory controllers are only
- *			capable of dual channel - which means that memory
- *			sticks must be loaded as pairs (see "socket set").
- *
- * Chip-select row:	All of the memory devices that are selected together.
- *			for a single, minimum grain of memory access.
- *			This selects all of the parallel memory devices across
- *			all of the parallel channels.  Common chip-select rows
- *			for single channel are 64 bits, for dual channel 128
- *			bits.
- *
- * Single-Ranked stick:	A Single-ranked stick has 1 chip-select row of memory.
- *			Motherboards commonly drive two chip-select pins to
- *			a memory stick. A single-ranked stick, will occupy
- *			only one of those rows. The other will be unused.
- *
- * Double-Ranked stick:	A double-ranked stick has two chip-select rows which
- *			access different sets of memory devices.  The two
- *			rows cannot be accessed concurrently.
- *
- * Double-sided stick:	DEPRECATED TERM, see Double-Ranked stick.
- *			A double-sided stick has two chip-select rows which
- *			access different sets of memory devices.  The two
- *			rows cannot be accessed concurrently.  "Double-sided"
- *			is irrespective of the memory devices being mounted
- *			on both sides of the memory stick.
- *
- * Socket set:		All of the memory sticks that are required for
- *			a single memory access or all of the memory sticks
- *			spanned by a chip-select row.  A single socket set
- *			has two chip-select rows and if double-sided sticks
- *			are used these will occupy those chip-select rows.
- *
- * Bank:		This term is avoided because it is unclear when
- *			needing to distinguish between chip-select rows and
- *			socket sets.
- *
- * Controller pages:
- *
- * Physical pages:
- *
- * Virtual pages:
- *
- *
- * STRUCTURE ORGANIZATION AND CHOICES
- *
- *
- *
- * PS - I enjoyed writing all that about as much as you enjoyed reading it.
- */
-
-struct channel_info {
-	int chan_idx;		/* channel index */
-	u32 ce_count;		/* Correctable Errors for this CHANNEL */
-	char label[EDAC_MC_LABEL_LEN + 1];	/* DIMM label on motherboard */
-	struct csrow_info *csrow;	/* the parent */
-};
-
-struct csrow_info {
-	unsigned long first_page;	/* first page number in dimm */
-	unsigned long last_page;	/* last page number in dimm */
-	unsigned long page_mask;	/* used for interleaving -
-					 * 0UL for non intlv
-					 */
-	u32 nr_pages;		/* number of pages in csrow */
-	u32 grain;		/* granularity of reported error in bytes */
-	int csrow_idx;		/* the chip-select row */
-	enum dev_type dtype;	/* memory device type */
-	u32 ue_count;		/* Uncorrectable Errors for this csrow */
-	u32 ce_count;		/* Correctable Errors for this csrow */
-	enum mem_type mtype;	/* memory csrow type */
-	enum edac_type edac_mode;	/* EDAC mode for this csrow */
-	struct mem_ctl_info *mci;	/* the parent */
-
-	struct kobject kobj;	/* sysfs kobject for this csrow */
-
-	/* channel information for this csrow */
-	u32 nr_channels;
-	struct channel_info *channels;
-};
-
-struct mcidev_sysfs_group {
-	const char *name;				/* group name */
-	const struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */
-};
-
-struct mcidev_sysfs_group_kobj {
-	struct list_head list;		/* list for all instances within a mc */
-
-	struct kobject kobj;		/* kobj for the group */
-
-	const struct mcidev_sysfs_group *grp;	/* group description table */
-	struct mem_ctl_info *mci;	/* the parent */
-};
-
-/* mcidev_sysfs_attribute structure
- *	used for driver sysfs attributes and in mem_ctl_info
- * 	sysfs top level entries
- */
-struct mcidev_sysfs_attribute {
-	/* It should use either attr or grp */
-	struct attribute attr;
-	const struct mcidev_sysfs_group *grp;	/* Points to a group of attributes */
-
-	/* Ops for show/store values at the attribute - not used on group */
-        ssize_t (*show)(struct mem_ctl_info *,char *);
-        ssize_t (*store)(struct mem_ctl_info *, const char *,size_t);
-};
-
-/* MEMORY controller information structure
- */
-struct mem_ctl_info {
-	struct list_head link;	/* for global list of mem_ctl_info structs */
-
-	struct module *owner;	/* Module owner of this control struct */
-
-	unsigned long mtype_cap;	/* memory types supported by mc */
-	unsigned long edac_ctl_cap;	/* Mem controller EDAC capabilities */
-	unsigned long edac_cap;	/* configuration capabilities - this is
-				 * closely related to edac_ctl_cap.  The
-				 * difference is that the controller may be
-				 * capable of s4ecd4ed which would be listed
-				 * in edac_ctl_cap, but if channels aren't
-				 * capable of s4ecd4ed then the edac_cap would
-				 * not have that capability.
-				 */
-	unsigned long scrub_cap;	/* chipset scrub capabilities */
-	enum scrub_type scrub_mode;	/* current scrub mode */
-
-	/* Translates sdram memory scrub rate given in bytes/sec to the
-	   internal representation and configures whatever else needs
-	   to be configured.
-	 */
-	int (*set_sdram_scrub_rate) (struct mem_ctl_info * mci, u32 bw);
-
-	/* Get the current sdram memory scrub rate from the internal
-	   representation and converts it to the closest matching
-	   bandwidth in bytes/sec.
-	 */
-	int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci);
-
-
-	/* pointer to edac checking routine */
-	void (*edac_check) (struct mem_ctl_info * mci);
-
-	/*
-	 * Remaps memory pages: controller pages to physical pages.
-	 * For most MC's, this will be NULL.
-	 */
-	/* FIXME - why not send the phys page to begin with? */
-	unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci,
-					   unsigned long page);
-	int mc_idx;
-	int nr_csrows;
-	struct csrow_info *csrows;
-	/*
-	 * FIXME - what about controllers on other busses? - IDs must be
-	 * unique.  dev pointer should be sufficiently unique, but
-	 * BUS:SLOT.FUNC numbers may not be unique.
-	 */
-	struct device *dev;
-	const char *mod_name;
-	const char *mod_ver;
-	const char *ctl_name;
-	const char *dev_name;
-	char proc_name[MC_PROC_NAME_MAX_LEN + 1];
-	void *pvt_info;
-	u32 ue_noinfo_count;	/* Uncorrectable Errors w/o info */
-	u32 ce_noinfo_count;	/* Correctable Errors w/o info */
-	u32 ue_count;		/* Total Uncorrectable Errors for this MC */
-	u32 ce_count;		/* Total Correctable Errors for this MC */
-	unsigned long start_time;	/* mci load start time (in jiffies) */
-
-	struct completion complete;
-
-	/* edac sysfs device control */
-	struct kobject edac_mci_kobj;
-
-	/* list for all grp instances within a mc */
-	struct list_head grp_kobj_list;
-
-	/* Additional top controller level attributes, but specified
-	 * by the low level driver.
-	 *
-	 * Set by the low level driver to provide attributes at the
-	 * controller level, same level as 'ue_count' and 'ce_count' above.
-	 * An array of structures, NULL terminated
-	 *
-	 * If attributes are desired, then set to array of attributes
-	 * If no attributes are desired, leave NULL
-	 */
-	const struct mcidev_sysfs_attribute *mc_driver_sysfs_attributes;
-
-	/* work struct for this MC */
-	struct delayed_work work;
-
-	/* the internal state of this controller instance */
-	int op_state;
-};
-
 /*
  * The following are the structures to provide for a generic
  * or abstract 'edac_device'. This set of structures and the
diff -druN linux-libre-3.1-gnu/drivers/edac/edac_mce.c linux-libre-3.2-gnu/drivers/edac/edac_mce.c
--- linux-libre-3.1-gnu/drivers/edac/edac_mce.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/edac/edac_mce.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-/* Provides edac interface to mcelog events
- *
- * This file may be distributed under the terms of the
- * GNU General Public License version 2.
- *
- * Copyright (c) 2009 by:
- *	 Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- * Red Hat Inc. http://www.redhat.com
- */
-
-#include <linux/module.h>
-#include <linux/edac_mce.h>
-#include <asm/mce.h>
-
-int edac_mce_enabled;
-EXPORT_SYMBOL_GPL(edac_mce_enabled);
-
-
-/*
- * Extension interface
- */
-
-static LIST_HEAD(edac_mce_list);
-static DEFINE_MUTEX(edac_mce_lock);
-
-int edac_mce_register(struct edac_mce *edac_mce)
-{
-	mutex_lock(&edac_mce_lock);
-	list_add_tail(&edac_mce->list, &edac_mce_list);
-	mutex_unlock(&edac_mce_lock);
-	return 0;
-}
-EXPORT_SYMBOL(edac_mce_register);
-
-void edac_mce_unregister(struct edac_mce *edac_mce)
-{
-	mutex_lock(&edac_mce_lock);
-	list_del(&edac_mce->list);
-	mutex_unlock(&edac_mce_lock);
-}
-EXPORT_SYMBOL(edac_mce_unregister);
-
-int edac_mce_parse(struct mce *mce)
-{
-	struct edac_mce *edac_mce;
-
-	list_for_each_entry(edac_mce, &edac_mce_list, list) {
-		if (edac_mce->check_error(edac_mce->priv, mce))
-			return 1;
-	}
-
-	/* Nobody queued the error */
-	return 0;
-}
-EXPORT_SYMBOL_GPL(edac_mce_parse);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("EDAC Driver for mcelog captured errors");
diff -druN linux-libre-3.1-gnu/drivers/edac/i7300_edac.c linux-libre-3.2-gnu/drivers/edac/i7300_edac.c
--- linux-libre-3.1-gnu/drivers/edac/i7300_edac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/edac/i7300_edac.c	2012-01-04 18:55:44.000000000 -0500
@@ -372,7 +372,7 @@
 static void i7300_process_error_global(struct mem_ctl_info *mci)
 {
 	struct i7300_pvt *pvt;
-	u32 errnum, value;
+	u32 errnum, error_reg;
 	unsigned long errors;
 	const char *specific;
 	bool is_fatal;
@@ -381,9 +381,9 @@
 
 	/* read in the 1st FATAL error register */
 	pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
-			      FERR_GLOBAL_HI, &value);
-	if (unlikely(value)) {
-		errors = value;
+			      FERR_GLOBAL_HI, &error_reg);
+	if (unlikely(error_reg)) {
+		errors = error_reg;
 		errnum = find_first_bit(&errors,
 					ARRAY_SIZE(ferr_global_hi_name));
 		specific = GET_ERR_FROM_TABLE(ferr_global_hi_name, errnum);
@@ -391,15 +391,15 @@
 
 		/* Clear the error bit */
 		pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
-				       FERR_GLOBAL_HI, value);
+				       FERR_GLOBAL_HI, error_reg);
 
 		goto error_global;
 	}
 
 	pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
-			      FERR_GLOBAL_LO, &value);
-	if (unlikely(value)) {
-		errors = value;
+			      FERR_GLOBAL_LO, &error_reg);
+	if (unlikely(error_reg)) {
+		errors = error_reg;
 		errnum = find_first_bit(&errors,
 					ARRAY_SIZE(ferr_global_lo_name));
 		specific = GET_ERR_FROM_TABLE(ferr_global_lo_name, errnum);
@@ -407,7 +407,7 @@
 
 		/* Clear the error bit */
 		pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
-				       FERR_GLOBAL_LO, value);
+				       FERR_GLOBAL_LO, error_reg);
 
 		goto error_global;
 	}
@@ -427,7 +427,7 @@
 static void i7300_process_fbd_error(struct mem_ctl_info *mci)
 {
 	struct i7300_pvt *pvt;
-	u32 errnum, value;
+	u32 errnum, value, error_reg;
 	u16 val16;
 	unsigned branch, channel, bank, rank, cas, ras;
 	u32 syndrome;
@@ -440,14 +440,14 @@
 
 	/* read in the 1st FATAL error register */
 	pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
-			      FERR_FAT_FBD, &value);
-	if (unlikely(value & FERR_FAT_FBD_ERR_MASK)) {
-		errors = value & FERR_FAT_FBD_ERR_MASK ;
+			      FERR_FAT_FBD, &error_reg);
+	if (unlikely(error_reg & FERR_FAT_FBD_ERR_MASK)) {
+		errors = error_reg & FERR_FAT_FBD_ERR_MASK ;
 		errnum = find_first_bit(&errors,
 					ARRAY_SIZE(ferr_fat_fbd_name));
 		specific = GET_ERR_FROM_TABLE(ferr_fat_fbd_name, errnum);
+		branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0;
 
-		branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0;
 		pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map,
 				     NRECMEMA, &val16);
 		bank = NRECMEMA_BANK(val16);
@@ -455,11 +455,14 @@
 
 		pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
 				NRECMEMB, &value);
-
 		is_wr = NRECMEMB_IS_WR(value);
 		cas = NRECMEMB_CAS(value);
 		ras = NRECMEMB_RAS(value);
 
+		/* Clean the error register */
+		pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
+				FERR_FAT_FBD, error_reg);
+
 		snprintf(pvt->tmp_prt_buffer, PAGE_SIZE,
 			"FATAL (Branch=%d DRAM-Bank=%d %s "
 			"RAS=%d CAS=%d Err=0x%lx (%s))",
@@ -476,21 +479,17 @@
 
 	/* read in the 1st NON-FATAL error register */
 	pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
-			      FERR_NF_FBD, &value);
-	if (unlikely(value & FERR_NF_FBD_ERR_MASK)) {
-		errors = value & FERR_NF_FBD_ERR_MASK;
+			      FERR_NF_FBD, &error_reg);
+	if (unlikely(error_reg & FERR_NF_FBD_ERR_MASK)) {
+		errors = error_reg & FERR_NF_FBD_ERR_MASK;
 		errnum = find_first_bit(&errors,
 					ARRAY_SIZE(ferr_nf_fbd_name));
 		specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum);
-
-		/* Clear the error bit */
-		pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
-				       FERR_GLOBAL_LO, value);
+		branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0;
 
 		pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
 			REDMEMA, &syndrome);
 
-		branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0;
 		pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map,
 				     RECMEMA, &val16);
 		bank = RECMEMA_BANK(val16);
@@ -498,18 +497,20 @@
 
 		pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
 				RECMEMB, &value);
-
 		is_wr = RECMEMB_IS_WR(value);
 		cas = RECMEMB_CAS(value);
 		ras = RECMEMB_RAS(value);
 
 		pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
 				     REDMEMB, &value);
-
 		channel = (branch << 1);
 		if (IS_SECOND_CH(value))
 			channel++;
 
+		/* Clear the error bit */
+		pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
+				FERR_NF_FBD, error_reg);
+
 		/* Form out message */
 		snprintf(pvt->tmp_prt_buffer, PAGE_SIZE,
 			"Corrected error (Branch=%d, Channel %d), "
diff -druN linux-libre-3.1-gnu/drivers/edac/i7core_edac.c linux-libre-3.2-gnu/drivers/edac/i7core_edac.c
--- linux-libre-3.1-gnu/drivers/edac/i7core_edac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/edac/i7core_edac.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,11 +31,13 @@
 #include <linux/pci_ids.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/dmi.h>
 #include <linux/edac.h>
 #include <linux/mmzone.h>
-#include <linux/edac_mce.h>
 #include <linux/smp.h>
+#include <asm/mce.h>
 #include <asm/processor.h>
+#include <asm/div64.h>
 
 #include "edac_core.h"
 
@@ -78,6 +80,8 @@
 	/* OFFSETS for Device 0 Function 0 */
 
 #define MC_CFG_CONTROL	0x90
+  #define MC_CFG_UNLOCK		0x02
+  #define MC_CFG_LOCK		0x00
 
 	/* OFFSETS for Device 3 Function 0 */
 
@@ -98,6 +102,15 @@
   #define DIMM0_COR_ERR(r)			((r) & 0x7fff)
 
 /* OFFSETS for Device 3 Function 2, as inicated on Xeon 5500 datasheet */
+#define MC_SSRCONTROL		0x48
+  #define SSR_MODE_DISABLE	0x00
+  #define SSR_MODE_ENABLE	0x01
+  #define SSR_MODE_MASK		0x03
+
+#define MC_SCRUB_CONTROL	0x4c
+  #define STARTSCRUB		(1 << 24)
+  #define SCRUBINTERVAL_MASK    0xffffff
+
 #define MC_COR_ECC_CNT_0	0x80
 #define MC_COR_ECC_CNT_1	0x84
 #define MC_COR_ECC_CNT_2	0x88
@@ -253,10 +266,7 @@
 	unsigned long	rdimm_ce_count[NUM_CHANS][MAX_DIMMS];
 	int		rdimm_last_ce_count[NUM_CHANS][MAX_DIMMS];
 
-	unsigned int	is_registered;
-
-	/* mcelog glue */
-	struct edac_mce		edac_mce;
+	bool		is_registered, enable_scrub;
 
 	/* Fifo double buffers */
 	struct mce		mce_entry[MCE_LOG_LEN];
@@ -268,6 +278,9 @@
 	/* Count indicator to show errors not got */
 	unsigned		mce_overrun;
 
+	/* DCLK Frequency used for computing scrub rate */
+	int			dclk_freq;
+
 	/* Struct to control EDAC polling */
 	struct edac_pci_ctl_info *i7core_pci;
 };
@@ -281,8 +294,7 @@
 		/* Memory controller */
 	{ PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR)     },
 	{ PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD)  },
-
-		/* Exists only for RDIMM */
+			/* Exists only for RDIMM */
 	{ PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS), .optional = 1  },
 	{ PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) },
 
@@ -303,6 +315,16 @@
 	{ PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR) },
 	{ PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK) },
 	{ PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC)   },
+
+		/* Generic Non-core registers */
+	/*
+	 * This is the PCI device on i7core and on Xeon 35xx (8086:2c41)
+	 * On Xeon 55xx, however, it has a different id (8086:2c40). So,
+	 * the probing code needs to test for the other address in case of
+	 * failure of this one
+	 */
+	{ PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NONCORE)  },
+
 };
 
 static const struct pci_id_descr pci_dev_descr_lynnfield[] = {
@@ -319,6 +341,12 @@
 	{ PCI_DESCR( 5, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR) },
 	{ PCI_DESCR( 5, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK) },
 	{ PCI_DESCR( 5, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC)   },
+
+	/*
+	 * This is the PCI device has an alternate address on some
+	 * processors like Core i7 860
+	 */
+	{ PCI_DESCR( 0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE)     },
 };
 
 static const struct pci_id_descr pci_dev_descr_i7core_westmere[] = {
@@ -346,6 +374,10 @@
 	{ PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_ADDR_REV2) },
 	{ PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_RANK_REV2) },
 	{ PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_TC_REV2)   },
+
+		/* Generic Non-core registers */
+	{ PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2)  },
+
 };
 
 #define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
@@ -714,6 +746,10 @@
 
 			csr->edac_mode = mode;
 			csr->mtype = mtype;
+			snprintf(csr->channels[0].label,
+					sizeof(csr->channels[0].label),
+					"CPU#%uChannel#%u_DIMM#%u",
+					pvt->i7core_dev->socket, i, j);
 
 			csrow++;
 		}
@@ -731,7 +767,7 @@
 			debugf1("\t\t%#x\t%#x\t%#x\n",
 				(value[j] >> 27) & 0x1,
 				(value[j] >> 24) & 0x7,
-				(value[j] && ((1 << 24) - 1)));
+				(value[j] & ((1 << 24) - 1)));
 	}
 
 	return 0;
@@ -1324,6 +1360,20 @@
 	pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
 			      dev_descr->dev_id, *prev);
 
+	/*
+	 * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs
+	 * is at addr 8086:2c40, instead of 8086:2c41. So, we need
+	 * to probe for the alternate address in case of failure
+	 */
+	if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev)
+		pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+				      PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev);
+
+	if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev)
+		pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+				      PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT,
+				      *prev);
+
 	if (!pdev) {
 		if (*prev) {
 			*prev = pdev;
@@ -1444,8 +1494,10 @@
 	struct i7core_pvt *pvt = mci->pvt_info;
 	struct pci_dev *pdev;
 	int i, func, slot;
+	char *family;
 
-	pvt->is_registered = 0;
+	pvt->is_registered = false;
+	pvt->enable_scrub  = false;
 	for (i = 0; i < i7core_dev->n_devs; i++) {
 		pdev = i7core_dev->pdev[i];
 		if (!pdev)
@@ -1461,9 +1513,37 @@
 			if (unlikely(func > MAX_CHAN_FUNC))
 				goto error;
 			pvt->pci_ch[slot - 4][func] = pdev;
-		} else if (!slot && !func)
+		} else if (!slot && !func) {
 			pvt->pci_noncore = pdev;
-		else
+
+			/* Detect the processor family */
+			switch (pdev->device) {
+			case PCI_DEVICE_ID_INTEL_I7_NONCORE:
+				family = "Xeon 35xx/ i7core";
+				pvt->enable_scrub = false;
+				break;
+			case PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT:
+				family = "i7-800/i5-700";
+				pvt->enable_scrub = false;
+				break;
+			case PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE:
+				family = "Xeon 34xx";
+				pvt->enable_scrub = false;
+				break;
+			case PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT:
+				family = "Xeon 55xx";
+				pvt->enable_scrub = true;
+				break;
+			case PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2:
+				family = "Xeon 56xx / i7-900";
+				pvt->enable_scrub = true;
+				break;
+			default:
+				family = "unknown";
+				pvt->enable_scrub = false;
+			}
+			debugf0("Detected a processor type %s\n", family);
+		} else
 			goto error;
 
 		debugf0("Associated fn %d.%d, dev = %p, socket %d\n",
@@ -1472,7 +1552,7 @@
 
 		if (PCI_SLOT(pdev->devfn) == 3 &&
 			PCI_FUNC(pdev->devfn) == 2)
-			pvt->is_registered = 1;
+			pvt->is_registered = true;
 	}
 
 	return 0;
@@ -1826,33 +1906,43 @@
  * WARNING: As this routine should be called at NMI time, extra care should
  * be taken to avoid deadlocks, and to be as fast as possible.
  */
-static int i7core_mce_check_error(void *priv, struct mce *mce)
+static int i7core_mce_check_error(struct notifier_block *nb, unsigned long val,
+				  void *data)
 {
-	struct mem_ctl_info *mci = priv;
-	struct i7core_pvt *pvt = mci->pvt_info;
+	struct mce *mce = (struct mce *)data;
+	struct i7core_dev *i7_dev;
+	struct mem_ctl_info *mci;
+	struct i7core_pvt *pvt;
+
+	i7_dev = get_i7core_dev(mce->socketid);
+	if (!i7_dev)
+		return NOTIFY_BAD;
+
+	mci = i7_dev->mci;
+	pvt = mci->pvt_info;
 
 	/*
 	 * Just let mcelog handle it if the error is
 	 * outside the memory controller
 	 */
 	if (((mce->status & 0xffff) >> 7) != 1)
-		return 0;
+		return NOTIFY_DONE;
 
 	/* Bank 8 registers are the only ones that we know how to handle */
 	if (mce->bank != 8)
-		return 0;
+		return NOTIFY_DONE;
 
 #ifdef CONFIG_SMP
 	/* Only handle if it is the right mc controller */
-	if (cpu_data(mce->cpu).phys_proc_id != pvt->i7core_dev->socket)
-		return 0;
+	if (mce->socketid != pvt->i7core_dev->socket)
+		return NOTIFY_DONE;
 #endif
 
 	smp_rmb();
 	if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
 		smp_wmb();
 		pvt->mce_overrun++;
-		return 0;
+		return NOTIFY_DONE;
 	}
 
 	/* Copy memory error at the ringbuffer */
@@ -1865,7 +1955,240 @@
 		i7core_check_error(mci);
 
 	/* Advise mcelog that the errors were handled */
-	return 1;
+	return NOTIFY_STOP;
+}
+
+static struct notifier_block i7_mce_dec = {
+	.notifier_call	= i7core_mce_check_error,
+};
+
+struct memdev_dmi_entry {
+	u8 type;
+	u8 length;
+	u16 handle;
+	u16 phys_mem_array_handle;
+	u16 mem_err_info_handle;
+	u16 total_width;
+	u16 data_width;
+	u16 size;
+	u8 form;
+	u8 device_set;
+	u8 device_locator;
+	u8 bank_locator;
+	u8 memory_type;
+	u16 type_detail;
+	u16 speed;
+	u8 manufacturer;
+	u8 serial_number;
+	u8 asset_tag;
+	u8 part_number;
+	u8 attributes;
+	u32 extended_size;
+	u16 conf_mem_clk_speed;
+} __attribute__((__packed__));
+
+
+/*
+ * Decode the DRAM Clock Frequency, be paranoid, make sure that all
+ * memory devices show the same speed, and if they don't then consider
+ * all speeds to be invalid.
+ */
+static void decode_dclk(const struct dmi_header *dh, void *_dclk_freq)
+{
+	int *dclk_freq = _dclk_freq;
+	u16 dmi_mem_clk_speed;
+
+	if (*dclk_freq == -1)
+		return;
+
+	if (dh->type == DMI_ENTRY_MEM_DEVICE) {
+		struct memdev_dmi_entry *memdev_dmi_entry =
+			(struct memdev_dmi_entry *)dh;
+		unsigned long conf_mem_clk_speed_offset =
+			(unsigned long)&memdev_dmi_entry->conf_mem_clk_speed -
+			(unsigned long)&memdev_dmi_entry->type;
+		unsigned long speed_offset =
+			(unsigned long)&memdev_dmi_entry->speed -
+			(unsigned long)&memdev_dmi_entry->type;
+
+		/* Check that a DIMM is present */
+		if (memdev_dmi_entry->size == 0)
+			return;
+
+		/*
+		 * Pick the configured speed if it's available, otherwise
+		 * pick the DIMM speed, or we don't have a speed.
+		 */
+		if (memdev_dmi_entry->length > conf_mem_clk_speed_offset) {
+			dmi_mem_clk_speed =
+				memdev_dmi_entry->conf_mem_clk_speed;
+		} else if (memdev_dmi_entry->length > speed_offset) {
+			dmi_mem_clk_speed = memdev_dmi_entry->speed;
+		} else {
+			*dclk_freq = -1;
+			return;
+		}
+
+		if (*dclk_freq == 0) {
+			/* First pass, speed was 0 */
+			if (dmi_mem_clk_speed > 0) {
+				/* Set speed if a valid speed is read */
+				*dclk_freq = dmi_mem_clk_speed;
+			} else {
+				/* Otherwise we don't have a valid speed */
+				*dclk_freq = -1;
+			}
+		} else if (*dclk_freq > 0 &&
+			   *dclk_freq != dmi_mem_clk_speed) {
+			/*
+			 * If we have a speed, check that all DIMMS are the same
+			 * speed, otherwise set the speed as invalid.
+			 */
+			*dclk_freq = -1;
+		}
+	}
+}
+
+/*
+ * The default DCLK frequency is used as a fallback if we
+ * fail to find anything reliable in the DMI. The value
+ * is taken straight from the datasheet.
+ */
+#define DEFAULT_DCLK_FREQ 800
+
+static int get_dclk_freq(void)
+{
+	int dclk_freq = 0;
+
+	dmi_walk(decode_dclk, (void *)&dclk_freq);
+
+	if (dclk_freq < 1)
+		return DEFAULT_DCLK_FREQ;
+
+	return dclk_freq;
+}
+
+/*
+ * set_sdram_scrub_rate		This routine sets byte/sec bandwidth scrub rate
+ *				to hardware according to SCRUBINTERVAL formula
+ *				found in datasheet.
+ */
+static int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 new_bw)
+{
+	struct i7core_pvt *pvt = mci->pvt_info;
+	struct pci_dev *pdev;
+	u32 dw_scrub;
+	u32 dw_ssr;
+
+	/* Get data from the MC register, function 2 */
+	pdev = pvt->pci_mcr[2];
+	if (!pdev)
+		return -ENODEV;
+
+	pci_read_config_dword(pdev, MC_SCRUB_CONTROL, &dw_scrub);
+
+	if (new_bw == 0) {
+		/* Prepare to disable petrol scrub */
+		dw_scrub &= ~STARTSCRUB;
+		/* Stop the patrol scrub engine */
+		write_and_test(pdev, MC_SCRUB_CONTROL,
+			       dw_scrub & ~SCRUBINTERVAL_MASK);
+
+		/* Get current status of scrub rate and set bit to disable */
+		pci_read_config_dword(pdev, MC_SSRCONTROL, &dw_ssr);
+		dw_ssr &= ~SSR_MODE_MASK;
+		dw_ssr |= SSR_MODE_DISABLE;
+	} else {
+		const int cache_line_size = 64;
+		const u32 freq_dclk_mhz = pvt->dclk_freq;
+		unsigned long long scrub_interval;
+		/*
+		 * Translate the desired scrub rate to a register value and
+		 * program the corresponding register value.
+		 */
+		scrub_interval = (unsigned long long)freq_dclk_mhz *
+			cache_line_size * 1000000;
+		do_div(scrub_interval, new_bw);
+
+		if (!scrub_interval || scrub_interval > SCRUBINTERVAL_MASK)
+			return -EINVAL;
+
+		dw_scrub = SCRUBINTERVAL_MASK & scrub_interval;
+
+		/* Start the patrol scrub engine */
+		pci_write_config_dword(pdev, MC_SCRUB_CONTROL,
+				       STARTSCRUB | dw_scrub);
+
+		/* Get current status of scrub rate and set bit to enable */
+		pci_read_config_dword(pdev, MC_SSRCONTROL, &dw_ssr);
+		dw_ssr &= ~SSR_MODE_MASK;
+		dw_ssr |= SSR_MODE_ENABLE;
+	}
+	/* Disable or enable scrubbing */
+	pci_write_config_dword(pdev, MC_SSRCONTROL, dw_ssr);
+
+	return new_bw;
+}
+
+/*
+ * get_sdram_scrub_rate		This routine convert current scrub rate value
+ *				into byte/sec bandwidth accourding to
+ *				SCRUBINTERVAL formula found in datasheet.
+ */
+static int get_sdram_scrub_rate(struct mem_ctl_info *mci)
+{
+	struct i7core_pvt *pvt = mci->pvt_info;
+	struct pci_dev *pdev;
+	const u32 cache_line_size = 64;
+	const u32 freq_dclk_mhz = pvt->dclk_freq;
+	unsigned long long scrub_rate;
+	u32 scrubval;
+
+	/* Get data from the MC register, function 2 */
+	pdev = pvt->pci_mcr[2];
+	if (!pdev)
+		return -ENODEV;
+
+	/* Get current scrub control data */
+	pci_read_config_dword(pdev, MC_SCRUB_CONTROL, &scrubval);
+
+	/* Mask highest 8-bits to 0 */
+	scrubval &=  SCRUBINTERVAL_MASK;
+	if (!scrubval)
+		return 0;
+
+	/* Calculate scrub rate value into byte/sec bandwidth */
+	scrub_rate =  (unsigned long long)freq_dclk_mhz *
+		1000000 * cache_line_size;
+	do_div(scrub_rate, scrubval);
+	return (int)scrub_rate;
+}
+
+static void enable_sdram_scrub_setting(struct mem_ctl_info *mci)
+{
+	struct i7core_pvt *pvt = mci->pvt_info;
+	u32 pci_lock;
+
+	/* Unlock writes to pci registers */
+	pci_read_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, &pci_lock);
+	pci_lock &= ~0x3;
+	pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL,
+			       pci_lock | MC_CFG_UNLOCK);
+
+	mci->set_sdram_scrub_rate = set_sdram_scrub_rate;
+	mci->get_sdram_scrub_rate = get_sdram_scrub_rate;
+}
+
+static void disable_sdram_scrub_setting(struct mem_ctl_info *mci)
+{
+	struct i7core_pvt *pvt = mci->pvt_info;
+	u32 pci_lock;
+
+	/* Lock writes to pci registers */
+	pci_read_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, &pci_lock);
+	pci_lock &= ~0x3;
+	pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL,
+			       pci_lock | MC_CFG_LOCK);
 }
 
 static void i7core_pci_ctl_create(struct i7core_pvt *pvt)
@@ -1874,7 +2197,8 @@
 						&pvt->i7core_dev->pdev[0]->dev,
 						EDAC_MOD_STR);
 	if (unlikely(!pvt->i7core_pci))
-		pr_warn("Unable to setup PCI error report via EDAC\n");
+		i7core_printk(KERN_WARNING,
+			      "Unable to setup PCI error report via EDAC\n");
 }
 
 static void i7core_pci_ctl_release(struct i7core_pvt *pvt)
@@ -1906,8 +2230,11 @@
 	debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
 		__func__, mci, &i7core_dev->pdev[0]->dev);
 
-	/* Disable MCE NMI handler */
-	edac_mce_unregister(&pvt->edac_mce);
+	/* Disable scrubrate setting */
+	if (pvt->enable_scrub)
+		disable_sdram_scrub_setting(mci);
+
+	atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &i7_mce_dec);
 
 	/* Disable EDAC polling */
 	i7core_pci_ctl_release(pvt);
@@ -1979,6 +2306,10 @@
 	/* Set the function pointer to an actual operation function */
 	mci->edac_check = i7core_check_error;
 
+	/* Enable scrubrate setting */
+	if (pvt->enable_scrub)
+		enable_sdram_scrub_setting(mci);
+
 	/* add this new MC control structure to EDAC's list of MCs */
 	if (unlikely(edac_mc_add_mc(mci))) {
 		debugf0("MC: " __FILE__
@@ -2002,21 +2333,13 @@
 	/* allocating generic PCI control info */
 	i7core_pci_ctl_create(pvt);
 
-	/* Registers on edac_mce in order to receive memory errors */
-	pvt->edac_mce.priv = mci;
-	pvt->edac_mce.check_error = i7core_mce_check_error;
-	rc = edac_mce_register(&pvt->edac_mce);
-	if (unlikely(rc < 0)) {
-		debugf0("MC: " __FILE__
-			": %s(): failed edac_mce_register()\n", __func__);
-		goto fail1;
-	}
+	/* DCLK for scrub rate setting */
+	pvt->dclk_freq = get_dclk_freq();
+
+	atomic_notifier_chain_register(&x86_mce_decoder_chain, &i7_mce_dec);
 
 	return 0;
 
-fail1:
-	i7core_pci_ctl_release(pvt);
-	edac_mc_del_mc(mci->dev);
 fail0:
 	kfree(mci->ctl_name);
 	edac_mc_free(mci);
@@ -2035,7 +2358,7 @@
 static int __devinit i7core_probe(struct pci_dev *pdev,
 				  const struct pci_device_id *id)
 {
-	int rc;
+	int rc, count = 0;
 	struct i7core_dev *i7core_dev;
 
 	/* get the pci devices we want to reserve for our use */
@@ -2055,12 +2378,28 @@
 		goto fail0;
 
 	list_for_each_entry(i7core_dev, &i7core_edac_list, list) {
+		count++;
 		rc = i7core_register_mci(i7core_dev);
 		if (unlikely(rc < 0))
 			goto fail1;
 	}
 
-	i7core_printk(KERN_INFO, "Driver loaded.\n");
+	/*
+	 * Nehalem-EX uses a different memory controller. However, as the
+	 * memory controller is not visible on some Nehalem/Nehalem-EP, we
+	 * need to indirectly probe via a X58 PCI device. The same devices
+	 * are found on (some) Nehalem-EX. So, on those machines, the
+	 * probe routine needs to return -ENODEV, as the actual Memory
+	 * Controller registers won't be detected.
+	 */
+	if (!count) {
+		rc = -ENODEV;
+		goto fail1;
+	}
+
+	i7core_printk(KERN_INFO,
+		      "Driver loaded, %d memory controller(s) found.\n",
+		      count);
 
 	mutex_unlock(&i7core_edac_lock);
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/edac/Kconfig linux-libre-3.2-gnu/drivers/edac/Kconfig
--- linux-libre-3.1-gnu/drivers/edac/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/edac/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -41,7 +41,7 @@
 
 config EDAC_DECODE_MCE
 	tristate "Decode MCEs in human-readable form (only on AMD for now)"
-	depends on CPU_SUP_AMD && X86_MCE
+	depends on CPU_SUP_AMD && X86_MCE_AMD
 	default y
 	---help---
 	  Enable this option if you want to decode Machine Check Exceptions
@@ -71,9 +71,6 @@
 	  occurred so that a particular failing memory module can be
 	  replaced.  If unsure, select 'Y'.
 
-config EDAC_MCE
-	bool
-
 config EDAC_AMD64
 	tristate "AMD64 (Opteron, Athlon64) K8, F10h"
 	depends on EDAC_MM_EDAC && AMD_NB && X86_64 && EDAC_DECODE_MCE
@@ -173,8 +170,7 @@
 
 config EDAC_I7CORE
 	tristate "Intel i7 Core (Nehalem) processors"
-	depends on EDAC_MM_EDAC && PCI && X86
-	select EDAC_MCE
+	depends on EDAC_MM_EDAC && PCI && X86 && X86_MCE_INTEL
 	help
 	  Support for error detection and correction the Intel
 	  i7 Core (Nehalem) Integrated Memory Controller that exists on
@@ -216,6 +212,14 @@
 	  Support for error detection and correction the Intel
 	  Clarksboro MCH (Intel 7300 chipset).
 
+config EDAC_SBRIDGE
+	tristate "Intel Sandy-Bridge Integrated MC"
+	depends on EDAC_MM_EDAC && PCI && X86_64 && X86_MCE_INTEL
+	depends on EXPERIMENTAL
+	help
+	  Support for error detection and correction the Intel
+	  Sandy Bridge Integrated Memory Controller.
+
 config EDAC_MPC85XX
 	tristate "Freescale MPC83xx / MPC85xx"
 	depends on EDAC_MM_EDAC && FSL_SOC && (PPC_83xx || PPC_85xx)
diff -druN linux-libre-3.1-gnu/drivers/edac/Makefile linux-libre-3.2-gnu/drivers/edac/Makefile
--- linux-libre-3.1-gnu/drivers/edac/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/edac/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,6 @@
 
 obj-$(CONFIG_EDAC)			:= edac_stub.o
 obj-$(CONFIG_EDAC_MM_EDAC)		+= edac_core.o
-obj-$(CONFIG_EDAC_MCE)			+= edac_mce.o
 
 edac_core-y	:= edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
 edac_core-y	+= edac_module.o edac_device_sysfs.o
@@ -29,6 +28,7 @@
 obj-$(CONFIG_EDAC_I5400)		+= i5400_edac.o
 obj-$(CONFIG_EDAC_I7300)		+= i7300_edac.o
 obj-$(CONFIG_EDAC_I7CORE)		+= i7core_edac.o
+obj-$(CONFIG_EDAC_SBRIDGE)		+= sb_edac.o
 obj-$(CONFIG_EDAC_E7XXX)		+= e7xxx_edac.o
 obj-$(CONFIG_EDAC_E752X)		+= e752x_edac.o
 obj-$(CONFIG_EDAC_I82443BXGX)		+= i82443bxgx_edac.o
diff -druN linux-libre-3.1-gnu/drivers/edac/mce_amd.c linux-libre-3.2-gnu/drivers/edac/mce_amd.c
--- linux-libre-3.1-gnu/drivers/edac/mce_amd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/edac/mce_amd.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,7 @@
 static u8 nb_err_cpumask = 0xf;
 
 static bool report_gart_errors;
-static void (*nb_bus_decoder)(int node_id, struct mce *m, u32 nbcfg);
+static void (*nb_bus_decoder)(int node_id, struct mce *m);
 
 void amd_report_gart_errors(bool v)
 {
@@ -17,13 +17,13 @@
 }
 EXPORT_SYMBOL_GPL(amd_report_gart_errors);
 
-void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32))
+void amd_register_ecc_decoder(void (*f)(int, struct mce *))
 {
 	nb_bus_decoder = f;
 }
 EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
 
-void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32))
+void amd_unregister_ecc_decoder(void (*f)(int, struct mce *))
 {
 	if (nb_bus_decoder) {
 		WARN_ON(nb_bus_decoder != f);
@@ -592,31 +592,14 @@
 	return false;
 }
 
-void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
+void amd_decode_nb_mce(struct mce *m)
 {
 	struct cpuinfo_x86 *c = &boot_cpu_data;
-	u16 ec   = EC(m->status);
-	u8 xec   = XEC(m->status, 0x1f);
-	u32 nbsh = (u32)(m->status >> 32);
-	int core = -1;
-
-	pr_emerg(HW_ERR "Northbridge Error (node %d", node_id);
-
-	/* F10h, revD can disable ErrCpu[3:0] through ErrCpuVal */
-	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;
-
-		if (assoc_cpus > 0)
-			core = fls(assoc_cpus) - 1;
-	}
+	int node_id = amd_get_nb_id(m->extcpu);
+	u16 ec = EC(m->status);
+	u8 xec = XEC(m->status, 0x1f);
 
-	if (core >= 0)
-		pr_cont(", core %d): ", core);
-	else
-		pr_cont("): ");
+	pr_emerg(HW_ERR "Northbridge Error (node %d): ", node_id);
 
 	switch (xec) {
 	case 0x2:
@@ -648,7 +631,7 @@
 
 	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);
+			nb_bus_decoder(node_id, m);
 
 	return;
 
@@ -764,13 +747,13 @@
 {
 	struct mce *m = (struct mce *)data;
 	struct cpuinfo_x86 *c = &boot_cpu_data;
-	int node, ecc;
+	int ecc;
 
 	if (amd_filter_mce(m))
 		return NOTIFY_STOP;
 
-	pr_emerg(HW_ERR "MC%d_STATUS[%s|%s|%s|%s|%s",
-		m->bank,
+	pr_emerg(HW_ERR "CPU:%d\tMC%d_STATUS[%s|%s|%s|%s|%s",
+		m->extcpu, m->bank,
 		((m->status & MCI_STATUS_OVER)	? "Over"  : "-"),
 		((m->status & MCI_STATUS_UC)	? "UE"	  : "CE"),
 		((m->status & MCI_STATUS_MISCV)	? "MiscV" : "-"),
@@ -789,6 +772,8 @@
 
 	pr_cont("]: 0x%016llx\n", m->status);
 
+	if (m->status & MCI_STATUS_ADDRV)
+		pr_emerg(HW_ERR "\tMC%d_ADDR: 0x%016llx\n", m->bank, m->addr);
 
 	switch (m->bank) {
 	case 0:
@@ -811,8 +796,7 @@
 		break;
 
 	case 4:
-		node = amd_get_nb_id(m->extcpu);
-		amd_decode_nb_mce(node, m, 0);
+		amd_decode_nb_mce(m);
 		break;
 
 	case 5:
diff -druN linux-libre-3.1-gnu/drivers/edac/mce_amd.h linux-libre-3.2-gnu/drivers/edac/mce_amd.h
--- linux-libre-3.1-gnu/drivers/edac/mce_amd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/edac/mce_amd.h	2012-01-04 18:55:44.000000000 -0500
@@ -86,9 +86,9 @@
 };
 
 void amd_report_gart_errors(bool);
-void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32));
-void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32));
-void amd_decode_nb_mce(int, struct mce *, u32);
+void amd_register_ecc_decoder(void (*f)(int, struct mce *));
+void amd_unregister_ecc_decoder(void (*f)(int, struct mce *));
+void amd_decode_nb_mce(struct mce *);
 int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data);
 
 #endif /* _EDAC_MCE_AMD_H */
diff -druN linux-libre-3.1-gnu/drivers/edac/mce_amd_inj.c linux-libre-3.2-gnu/drivers/edac/mce_amd_inj.c
--- linux-libre-3.1-gnu/drivers/edac/mce_amd_inj.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/edac/mce_amd_inj.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/kobject.h>
 #include <linux/sysdev.h>
 #include <linux/edac.h>
+#include <linux/module.h>
 #include <asm/mce.h>
 
 #include "mce_amd.h"
diff -druN linux-libre-3.1-gnu/drivers/edac/mpc85xx_edac.c linux-libre-3.2-gnu/drivers/edac/mpc85xx_edac.c
--- linux-libre-3.1-gnu/drivers/edac/mpc85xx_edac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/edac/mpc85xx_edac.c	2012-01-04 18:55:44.000000000 -0500
@@ -1128,7 +1128,7 @@
 	{ .compatible = "fsl,p1020-memory-controller", },
 	{ .compatible = "fsl,p1021-memory-controller", },
 	{ .compatible = "fsl,p2020-memory-controller", },
-	{ .compatible = "fsl,p4080-memory-controller", },
+	{ .compatible = "fsl,qoriq-memory-controller", },
 	{},
 };
 MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match);
diff -druN linux-libre-3.1-gnu/drivers/edac/ppc4xx_edac.c linux-libre-3.2-gnu/drivers/edac/ppc4xx_edac.c
--- linux-libre-3.1-gnu/drivers/edac/ppc4xx_edac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/edac/ppc4xx_edac.c	2012-01-04 18:55:44.000000000 -0500
@@ -205,7 +205,7 @@
 	.remove			= ppc4xx_edac_remove,
 	.driver = {
 		.owner = THIS_MODULE,
-		.name = PPC4XX_EDAC_MODULE_NAME
+		.name = PPC4XX_EDAC_MODULE_NAME,
 		.of_match_table = ppc4xx_edac_match,
 	},
 };
diff -druN linux-libre-3.1-gnu/drivers/edac/sb_edac.c linux-libre-3.2-gnu/drivers/edac/sb_edac.c
--- linux-libre-3.1-gnu/drivers/edac/sb_edac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/edac/sb_edac.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1893 @@
+/* Intel Sandy Bridge -EN/-EP/-EX Memory Controller kernel module
+ *
+ * This driver supports the memory controllers found on the Intel
+ * processor family Sandy Bridge.
+ *
+ * This file may be distributed under the terms of the
+ * GNU General Public License version 2 only.
+ *
+ * Copyright (c) 2011 by:
+ *	 Mauro Carvalho Chehab <mchehab@redhat.com>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/edac.h>
+#include <linux/mmzone.h>
+#include <linux/smp.h>
+#include <linux/bitmap.h>
+#include <asm/processor.h>
+#include <asm/mce.h>
+
+#include "edac_core.h"
+
+/* Static vars */
+static LIST_HEAD(sbridge_edac_list);
+static DEFINE_MUTEX(sbridge_edac_lock);
+static int probed;
+
+/*
+ * Alter this version for the module when modifications are made
+ */
+#define SBRIDGE_REVISION    " Ver: 1.0.0 "
+#define EDAC_MOD_STR      "sbridge_edac"
+
+/*
+ * Debug macros
+ */
+#define sbridge_printk(level, fmt, arg...)			\
+	edac_printk(level, "sbridge", fmt, ##arg)
+
+#define sbridge_mc_printk(mci, level, fmt, arg...)		\
+	edac_mc_chipset_printk(mci, level, "sbridge", fmt, ##arg)
+
+/*
+ * Get a bit field at register value <v>, from bit <lo> to bit <hi>
+ */
+#define GET_BITFIELD(v, lo, hi)	\
+	(((v) & ((1ULL << ((hi) - (lo) + 1)) - 1) << (lo)) >> (lo))
+
+/*
+ * sbridge Memory Controller Registers
+ */
+
+/*
+ * FIXME: For now, let's order by device function, as it makes
+ * easier for driver's development proccess. This table should be
+ * moved to pci_id.h when submitted upstream
+ */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0	0x3cf4	/* 12.6 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1	0x3cf6	/* 12.7 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_BR		0x3cf5	/* 13.6 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0	0x3ca0	/* 14.0 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA	0x3ca8	/* 15.0 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS	0x3c71	/* 15.1 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0	0x3caa	/* 15.2 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1	0x3cab	/* 15.3 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2	0x3cac	/* 15.4 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3	0x3cad	/* 15.5 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO	0x3cb8	/* 17.0 */
+
+	/*
+	 * Currently, unused, but will be needed in the future
+	 * implementations, as they hold the error counters
+	 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR0	0x3c72	/* 16.2 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR1	0x3c73	/* 16.3 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR2	0x3c76	/* 16.6 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR3	0x3c77	/* 16.7 */
+
+/* Devices 12 Function 6, Offsets 0x80 to 0xcc */
+static const u32 dram_rule[] = {
+	0x80, 0x88, 0x90, 0x98, 0xa0,
+	0xa8, 0xb0, 0xb8, 0xc0, 0xc8,
+};
+#define MAX_SAD		ARRAY_SIZE(dram_rule)
+
+#define SAD_LIMIT(reg)		((GET_BITFIELD(reg, 6, 25) << 26) | 0x3ffffff)
+#define DRAM_ATTR(reg)		GET_BITFIELD(reg, 2,  3)
+#define INTERLEAVE_MODE(reg)	GET_BITFIELD(reg, 1,  1)
+#define DRAM_RULE_ENABLE(reg)	GET_BITFIELD(reg, 0,  0)
+
+static char *get_dram_attr(u32 reg)
+{
+	switch(DRAM_ATTR(reg)) {
+		case 0:
+			return "DRAM";
+		case 1:
+			return "MMCFG";
+		case 2:
+			return "NXM";
+		default:
+			return "unknown";
+	}
+}
+
+static const u32 interleave_list[] = {
+	0x84, 0x8c, 0x94, 0x9c, 0xa4,
+	0xac, 0xb4, 0xbc, 0xc4, 0xcc,
+};
+#define MAX_INTERLEAVE	ARRAY_SIZE(interleave_list)
+
+#define SAD_PKG0(reg)		GET_BITFIELD(reg, 0, 2)
+#define SAD_PKG1(reg)		GET_BITFIELD(reg, 3, 5)
+#define SAD_PKG2(reg)		GET_BITFIELD(reg, 8, 10)
+#define SAD_PKG3(reg)		GET_BITFIELD(reg, 11, 13)
+#define SAD_PKG4(reg)		GET_BITFIELD(reg, 16, 18)
+#define SAD_PKG5(reg)		GET_BITFIELD(reg, 19, 21)
+#define SAD_PKG6(reg)		GET_BITFIELD(reg, 24, 26)
+#define SAD_PKG7(reg)		GET_BITFIELD(reg, 27, 29)
+
+static inline int sad_pkg(u32 reg, int interleave)
+{
+	switch (interleave) {
+	case 0:
+		return SAD_PKG0(reg);
+	case 1:
+		return SAD_PKG1(reg);
+	case 2:
+		return SAD_PKG2(reg);
+	case 3:
+		return SAD_PKG3(reg);
+	case 4:
+		return SAD_PKG4(reg);
+	case 5:
+		return SAD_PKG5(reg);
+	case 6:
+		return SAD_PKG6(reg);
+	case 7:
+		return SAD_PKG7(reg);
+	default:
+		return -EINVAL;
+	}
+}
+
+/* Devices 12 Function 7 */
+
+#define TOLM		0x80
+#define	TOHM		0x84
+
+#define GET_TOLM(reg)		((GET_BITFIELD(reg, 0,  3) << 28) | 0x3ffffff)
+#define GET_TOHM(reg)		((GET_BITFIELD(reg, 0, 20) << 25) | 0x3ffffff)
+
+/* Device 13 Function 6 */
+
+#define SAD_TARGET	0xf0
+
+#define SOURCE_ID(reg)		GET_BITFIELD(reg, 9, 11)
+
+#define SAD_CONTROL	0xf4
+
+#define NODE_ID(reg)		GET_BITFIELD(reg, 0, 2)
+
+/* Device 14 function 0 */
+
+static const u32 tad_dram_rule[] = {
+	0x40, 0x44, 0x48, 0x4c,
+	0x50, 0x54, 0x58, 0x5c,
+	0x60, 0x64, 0x68, 0x6c,
+};
+#define MAX_TAD	ARRAY_SIZE(tad_dram_rule)
+
+#define TAD_LIMIT(reg)		((GET_BITFIELD(reg, 12, 31) << 26) | 0x3ffffff)
+#define TAD_SOCK(reg)		GET_BITFIELD(reg, 10, 11)
+#define TAD_CH(reg)		GET_BITFIELD(reg,  8,  9)
+#define TAD_TGT3(reg)		GET_BITFIELD(reg,  6,  7)
+#define TAD_TGT2(reg)		GET_BITFIELD(reg,  4,  5)
+#define TAD_TGT1(reg)		GET_BITFIELD(reg,  2,  3)
+#define TAD_TGT0(reg)		GET_BITFIELD(reg,  0,  1)
+
+/* Device 15, function 0 */
+
+#define MCMTR			0x7c
+
+#define IS_ECC_ENABLED(mcmtr)		GET_BITFIELD(mcmtr, 2, 2)
+#define IS_LOCKSTEP_ENABLED(mcmtr)	GET_BITFIELD(mcmtr, 1, 1)
+#define IS_CLOSE_PG(mcmtr)		GET_BITFIELD(mcmtr, 0, 0)
+
+/* Device 15, function 1 */
+
+#define RASENABLES		0xac
+#define IS_MIRROR_ENABLED(reg)		GET_BITFIELD(reg, 0, 0)
+
+/* Device 15, functions 2-5 */
+
+static const int mtr_regs[] = {
+	0x80, 0x84, 0x88,
+};
+
+#define RANK_DISABLE(mtr)		GET_BITFIELD(mtr, 16, 19)
+#define IS_DIMM_PRESENT(mtr)		GET_BITFIELD(mtr, 14, 14)
+#define RANK_CNT_BITS(mtr)		GET_BITFIELD(mtr, 12, 13)
+#define RANK_WIDTH_BITS(mtr)		GET_BITFIELD(mtr, 2, 4)
+#define COL_WIDTH_BITS(mtr)		GET_BITFIELD(mtr, 0, 1)
+
+static const u32 tad_ch_nilv_offset[] = {
+	0x90, 0x94, 0x98, 0x9c,
+	0xa0, 0xa4, 0xa8, 0xac,
+	0xb0, 0xb4, 0xb8, 0xbc,
+};
+#define CHN_IDX_OFFSET(reg)		GET_BITFIELD(reg, 28, 29)
+#define TAD_OFFSET(reg)			(GET_BITFIELD(reg,  6, 25) << 26)
+
+static const u32 rir_way_limit[] = {
+	0x108, 0x10c, 0x110, 0x114, 0x118,
+};
+#define MAX_RIR_RANGES ARRAY_SIZE(rir_way_limit)
+
+#define IS_RIR_VALID(reg)	GET_BITFIELD(reg, 31, 31)
+#define RIR_WAY(reg)		GET_BITFIELD(reg, 28, 29)
+#define RIR_LIMIT(reg)		((GET_BITFIELD(reg,  1, 10) << 29)| 0x1fffffff)
+
+#define MAX_RIR_WAY	8
+
+static const u32 rir_offset[MAX_RIR_RANGES][MAX_RIR_WAY] = {
+	{ 0x120, 0x124, 0x128, 0x12c, 0x130, 0x134, 0x138, 0x13c },
+	{ 0x140, 0x144, 0x148, 0x14c, 0x150, 0x154, 0x158, 0x15c },
+	{ 0x160, 0x164, 0x168, 0x16c, 0x170, 0x174, 0x178, 0x17c },
+	{ 0x180, 0x184, 0x188, 0x18c, 0x190, 0x194, 0x198, 0x19c },
+	{ 0x1a0, 0x1a4, 0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc },
+};
+
+#define RIR_RNK_TGT(reg)		GET_BITFIELD(reg, 16, 19)
+#define RIR_OFFSET(reg)		GET_BITFIELD(reg,  2, 14)
+
+/* Device 16, functions 2-7 */
+
+/*
+ * FIXME: Implement the error count reads directly
+ */
+
+static const u32 correrrcnt[] = {
+	0x104, 0x108, 0x10c, 0x110,
+};
+
+#define RANK_ODD_OV(reg)		GET_BITFIELD(reg, 31, 31)
+#define RANK_ODD_ERR_CNT(reg)		GET_BITFIELD(reg, 16, 30)
+#define RANK_EVEN_OV(reg)		GET_BITFIELD(reg, 15, 15)
+#define RANK_EVEN_ERR_CNT(reg)		GET_BITFIELD(reg,  0, 14)
+
+static const u32 correrrthrsld[] = {
+	0x11c, 0x120, 0x124, 0x128,
+};
+
+#define RANK_ODD_ERR_THRSLD(reg)	GET_BITFIELD(reg, 16, 30)
+#define RANK_EVEN_ERR_THRSLD(reg)	GET_BITFIELD(reg,  0, 14)
+
+
+/* Device 17, function 0 */
+
+#define RANK_CFG_A		0x0328
+
+#define IS_RDIMM_ENABLED(reg)		GET_BITFIELD(reg, 11, 11)
+
+/*
+ * sbridge structs
+ */
+
+#define NUM_CHANNELS	4
+#define MAX_DIMMS	3		/* Max DIMMS per channel */
+
+struct sbridge_info {
+	u32	mcmtr;
+};
+
+struct sbridge_channel {
+	u32		ranks;
+	u32		dimms;
+};
+
+struct pci_id_descr {
+	int			dev;
+	int			func;
+	int 			dev_id;
+	int			optional;
+};
+
+struct pci_id_table {
+	const struct pci_id_descr	*descr;
+	int				n_devs;
+};
+
+struct sbridge_dev {
+	struct list_head	list;
+	u8			bus, mc;
+	u8			node_id, source_id;
+	struct pci_dev		**pdev;
+	int			n_devs;
+	struct mem_ctl_info	*mci;
+};
+
+struct sbridge_pvt {
+	struct pci_dev		*pci_ta, *pci_ddrio, *pci_ras;
+	struct pci_dev		*pci_sad0, *pci_sad1, *pci_ha0;
+	struct pci_dev		*pci_br;
+	struct pci_dev		*pci_tad[NUM_CHANNELS];
+
+	struct sbridge_dev	*sbridge_dev;
+
+	struct sbridge_info	info;
+	struct sbridge_channel	channel[NUM_CHANNELS];
+
+	int 			csrow_map[NUM_CHANNELS][MAX_DIMMS];
+
+	/* Memory type detection */
+	bool			is_mirrored, is_lockstep, is_close_pg;
+
+	/* Fifo double buffers */
+	struct mce		mce_entry[MCE_LOG_LEN];
+	struct mce		mce_outentry[MCE_LOG_LEN];
+
+	/* Fifo in/out counters */
+	unsigned		mce_in, mce_out;
+
+	/* Count indicator to show errors not got */
+	unsigned		mce_overrun;
+
+	/* Memory description */
+	u64			tolm, tohm;
+};
+
+#define PCI_DESCR(device, function, device_id)	\
+	.dev = (device),			\
+	.func = (function),			\
+	.dev_id = (device_id)
+
+static const struct pci_id_descr pci_dev_descr_sbridge[] = {
+		/* Processor Home Agent */
+	{ PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0)		},
+
+		/* Memory controller */
+	{ PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)		},
+	{ PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS)		},
+	{ PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0)	},
+	{ PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1)	},
+	{ PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2)	},
+	{ PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3)	},
+	{ PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO)	},
+
+		/* System Address Decoder */
+	{ PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0)		},
+	{ PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1)		},
+
+		/* Broadcast Registers */
+	{ PCI_DESCR(13, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_BR)		},
+};
+
+#define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
+static const struct pci_id_table pci_dev_descr_sbridge_table[] = {
+	PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge),
+	{0,}			/* 0 terminated list. */
+};
+
+/*
+ *	pci_device_id	table for which devices we are looking for
+ */
+static const struct pci_device_id sbridge_pci_tbl[] __devinitdata = {
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)},
+	{0,}			/* 0 terminated list. */
+};
+
+
+/****************************************************************************
+			Anciliary status routines
+ ****************************************************************************/
+
+static inline int numrank(u32 mtr)
+{
+	int ranks = (1 << RANK_CNT_BITS(mtr));
+
+	if (ranks > 4) {
+		debugf0("Invalid number of ranks: %d (max = 4) raw value = %x (%04x)",
+			ranks, (unsigned int)RANK_CNT_BITS(mtr), mtr);
+		return -EINVAL;
+	}
+
+	return ranks;
+}
+
+static inline int numrow(u32 mtr)
+{
+	int rows = (RANK_WIDTH_BITS(mtr) + 12);
+
+	if (rows < 13 || rows > 18) {
+		debugf0("Invalid number of rows: %d (should be between 14 and 17) raw value = %x (%04x)",
+			rows, (unsigned int)RANK_WIDTH_BITS(mtr), mtr);
+		return -EINVAL;
+	}
+
+	return 1 << rows;
+}
+
+static inline int numcol(u32 mtr)
+{
+	int cols = (COL_WIDTH_BITS(mtr) + 10);
+
+	if (cols > 12) {
+		debugf0("Invalid number of cols: %d (max = 4) raw value = %x (%04x)",
+			cols, (unsigned int)COL_WIDTH_BITS(mtr), mtr);
+		return -EINVAL;
+	}
+
+	return 1 << cols;
+}
+
+static struct sbridge_dev *get_sbridge_dev(u8 bus)
+{
+	struct sbridge_dev *sbridge_dev;
+
+	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
+		if (sbridge_dev->bus == bus)
+			return sbridge_dev;
+	}
+
+	return NULL;
+}
+
+static struct sbridge_dev *alloc_sbridge_dev(u8 bus,
+					   const struct pci_id_table *table)
+{
+	struct sbridge_dev *sbridge_dev;
+
+	sbridge_dev = kzalloc(sizeof(*sbridge_dev), GFP_KERNEL);
+	if (!sbridge_dev)
+		return NULL;
+
+	sbridge_dev->pdev = kzalloc(sizeof(*sbridge_dev->pdev) * table->n_devs,
+				   GFP_KERNEL);
+	if (!sbridge_dev->pdev) {
+		kfree(sbridge_dev);
+		return NULL;
+	}
+
+	sbridge_dev->bus = bus;
+	sbridge_dev->n_devs = table->n_devs;
+	list_add_tail(&sbridge_dev->list, &sbridge_edac_list);
+
+	return sbridge_dev;
+}
+
+static void free_sbridge_dev(struct sbridge_dev *sbridge_dev)
+{
+	list_del(&sbridge_dev->list);
+	kfree(sbridge_dev->pdev);
+	kfree(sbridge_dev);
+}
+
+/****************************************************************************
+			Memory check routines
+ ****************************************************************************/
+static struct pci_dev *get_pdev_slot_func(u8 bus, unsigned slot,
+					  unsigned func)
+{
+	struct sbridge_dev *sbridge_dev = get_sbridge_dev(bus);
+	int i;
+
+	if (!sbridge_dev)
+		return NULL;
+
+	for (i = 0; i < sbridge_dev->n_devs; i++) {
+		if (!sbridge_dev->pdev[i])
+			continue;
+
+		if (PCI_SLOT(sbridge_dev->pdev[i]->devfn) == slot &&
+		    PCI_FUNC(sbridge_dev->pdev[i]->devfn) == func) {
+			debugf1("Associated %02x.%02x.%d with %p\n",
+				bus, slot, func, sbridge_dev->pdev[i]);
+			return sbridge_dev->pdev[i];
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * sbridge_get_active_channels() - gets the number of channels and csrows
+ * bus:		Device bus
+ * @channels:	Number of channels that will be returned
+ * @csrows:	Number of csrows found
+ *
+ * Since EDAC core needs to know in advance the number of available channels
+ * and csrows, in order to allocate memory for csrows/channels, it is needed
+ * to run two similar steps. At the first step, implemented on this function,
+ * it checks the number of csrows/channels present at one socket, identified
+ * by the associated PCI bus.
+ * this is used in order to properly allocate the size of mci components.
+ * Note: one csrow is one dimm.
+ */
+static int sbridge_get_active_channels(const u8 bus, unsigned *channels,
+				      unsigned *csrows)
+{
+	struct pci_dev *pdev = NULL;
+	int i, j;
+	u32 mcmtr;
+
+	*channels = 0;
+	*csrows = 0;
+
+	pdev = get_pdev_slot_func(bus, 15, 0);
+	if (!pdev) {
+		sbridge_printk(KERN_ERR, "Couldn't find PCI device "
+					"%2x.%02d.%d!!!\n",
+					bus, 15, 0);
+		return -ENODEV;
+	}
+
+	pci_read_config_dword(pdev, MCMTR, &mcmtr);
+	if (!IS_ECC_ENABLED(mcmtr)) {
+		sbridge_printk(KERN_ERR, "ECC is disabled. Aborting\n");
+		return -ENODEV;
+	}
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		u32 mtr;
+
+		/* Device 15 functions 2 - 5  */
+		pdev = get_pdev_slot_func(bus, 15, 2 + i);
+		if (!pdev) {
+			sbridge_printk(KERN_ERR, "Couldn't find PCI device "
+						 "%2x.%02d.%d!!!\n",
+						 bus, 15, 2 + i);
+			return -ENODEV;
+		}
+		(*channels)++;
+
+		for (j = 0; j < ARRAY_SIZE(mtr_regs); j++) {
+			pci_read_config_dword(pdev, mtr_regs[j], &mtr);
+			debugf1("Bus#%02x channel #%d  MTR%d = %x\n", bus, i, j, mtr);
+			if (IS_DIMM_PRESENT(mtr))
+				(*csrows)++;
+		}
+	}
+
+	debugf0("Number of active channels: %d, number of active dimms: %d\n",
+		*channels, *csrows);
+
+	return 0;
+}
+
+static int get_dimm_config(const struct mem_ctl_info *mci)
+{
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	struct csrow_info *csr;
+	int i, j, banks, ranks, rows, cols, size, npages;
+	int csrow = 0;
+	unsigned long last_page = 0;
+	u32 reg;
+	enum edac_type mode;
+	enum mem_type mtype;
+
+	pci_read_config_dword(pvt->pci_br, SAD_TARGET, &reg);
+	pvt->sbridge_dev->source_id = SOURCE_ID(reg);
+
+	pci_read_config_dword(pvt->pci_br, SAD_CONTROL, &reg);
+	pvt->sbridge_dev->node_id = NODE_ID(reg);
+	debugf0("mc#%d: Node ID: %d, source ID: %d\n",
+		pvt->sbridge_dev->mc,
+		pvt->sbridge_dev->node_id,
+		pvt->sbridge_dev->source_id);
+
+	pci_read_config_dword(pvt->pci_ras, RASENABLES, &reg);
+	if (IS_MIRROR_ENABLED(reg)) {
+		debugf0("Memory mirror is enabled\n");
+		pvt->is_mirrored = true;
+	} else {
+		debugf0("Memory mirror is disabled\n");
+		pvt->is_mirrored = false;
+	}
+
+	pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr);
+	if (IS_LOCKSTEP_ENABLED(pvt->info.mcmtr)) {
+		debugf0("Lockstep is enabled\n");
+		mode = EDAC_S8ECD8ED;
+		pvt->is_lockstep = true;
+	} else {
+		debugf0("Lockstep is disabled\n");
+		mode = EDAC_S4ECD4ED;
+		pvt->is_lockstep = false;
+	}
+	if (IS_CLOSE_PG(pvt->info.mcmtr)) {
+		debugf0("address map is on closed page mode\n");
+		pvt->is_close_pg = true;
+	} else {
+		debugf0("address map is on open page mode\n");
+		pvt->is_close_pg = false;
+	}
+
+	pci_read_config_dword(pvt->pci_ta, RANK_CFG_A, &reg);
+	if (IS_RDIMM_ENABLED(reg)) {
+		/* FIXME: Can also be LRDIMM */
+		debugf0("Memory is registered\n");
+		mtype = MEM_RDDR3;
+	} else {
+		debugf0("Memory is unregistered\n");
+		mtype = MEM_DDR3;
+	}
+
+	/* On all supported DDR3 DIMM types, there are 8 banks available */
+	banks = 8;
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		u32 mtr;
+
+		for (j = 0; j < ARRAY_SIZE(mtr_regs); j++) {
+			pci_read_config_dword(pvt->pci_tad[i],
+					      mtr_regs[j], &mtr);
+			debugf4("Channel #%d  MTR%d = %x\n", i, j, mtr);
+			if (IS_DIMM_PRESENT(mtr)) {
+				pvt->channel[i].dimms++;
+
+				ranks = numrank(mtr);
+				rows = numrow(mtr);
+				cols = numcol(mtr);
+
+				/* DDR3 has 8 I/O banks */
+				size = (rows * cols * banks * ranks) >> (20 - 3);
+				npages = MiB_TO_PAGES(size);
+
+				debugf0("mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
+					pvt->sbridge_dev->mc, i, j,
+					size, npages,
+					banks, ranks, rows, cols);
+				csr = &mci->csrows[csrow];
+
+				csr->first_page = last_page;
+				csr->last_page = last_page + npages - 1;
+				csr->page_mask = 0UL;	/* Unused */
+				csr->nr_pages = npages;
+				csr->grain = 32;
+				csr->csrow_idx = csrow;
+				csr->dtype = (banks == 8) ? DEV_X8 : DEV_X4;
+				csr->ce_count = 0;
+				csr->ue_count = 0;
+				csr->mtype = mtype;
+				csr->edac_mode = mode;
+				csr->nr_channels = 1;
+				csr->channels[0].chan_idx = i;
+				csr->channels[0].ce_count = 0;
+				pvt->csrow_map[i][j] = csrow;
+				snprintf(csr->channels[0].label,
+					 sizeof(csr->channels[0].label),
+					 "CPU_SrcID#%u_Channel#%u_DIMM#%u",
+					 pvt->sbridge_dev->source_id, i, j);
+				last_page += npages;
+				csrow++;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static void get_memory_layout(const struct mem_ctl_info *mci)
+{
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	int i, j, k, n_sads, n_tads, sad_interl;
+	u32 reg;
+	u64 limit, prv = 0;
+	u64 tmp_mb;
+	u32 rir_way;
+
+	/*
+	 * Step 1) Get TOLM/TOHM ranges
+	 */
+
+	/* Address range is 32:28 */
+	pci_read_config_dword(pvt->pci_sad1, TOLM,
+			      &reg);
+	pvt->tolm = GET_TOLM(reg);
+	tmp_mb = (1 + pvt->tolm) >> 20;
+
+	debugf0("TOLM: %Lu.%03Lu GB (0x%016Lx)\n",
+		tmp_mb / 1000, tmp_mb % 1000, (u64)pvt->tolm);
+
+	/* Address range is already 45:25 */
+	pci_read_config_dword(pvt->pci_sad1, TOHM,
+			      &reg);
+	pvt->tohm = GET_TOHM(reg);
+	tmp_mb = (1 + pvt->tohm) >> 20;
+
+	debugf0("TOHM: %Lu.%03Lu GB (0x%016Lx)",
+		tmp_mb / 1000, tmp_mb % 1000, (u64)pvt->tohm);
+
+	/*
+	 * Step 2) Get SAD range and SAD Interleave list
+	 * TAD registers contain the interleave wayness. However, it
+	 * seems simpler to just discover it indirectly, with the
+	 * algorithm bellow.
+	 */
+	prv = 0;
+	for (n_sads = 0; n_sads < MAX_SAD; n_sads++) {
+		/* SAD_LIMIT Address range is 45:26 */
+		pci_read_config_dword(pvt->pci_sad0, dram_rule[n_sads],
+				      &reg);
+		limit = SAD_LIMIT(reg);
+
+		if (!DRAM_RULE_ENABLE(reg))
+			continue;
+
+		if (limit <= prv)
+			break;
+
+		tmp_mb = (limit + 1) >> 20;
+		debugf0("SAD#%d %s up to %Lu.%03Lu GB (0x%016Lx) %s reg=0x%08x\n",
+			n_sads,
+			get_dram_attr(reg),
+			tmp_mb / 1000, tmp_mb % 1000,
+			((u64)tmp_mb) << 20L,
+			INTERLEAVE_MODE(reg) ? "Interleave: 8:6" : "Interleave: [8:6]XOR[18:16]",
+			reg);
+		prv = limit;
+
+		pci_read_config_dword(pvt->pci_sad0, interleave_list[n_sads],
+				      &reg);
+		sad_interl = sad_pkg(reg, 0);
+		for (j = 0; j < 8; j++) {
+			if (j > 0 && sad_interl == sad_pkg(reg, j))
+				break;
+
+			debugf0("SAD#%d, interleave #%d: %d\n",
+			n_sads, j, sad_pkg(reg, j));
+		}
+	}
+
+	/*
+	 * Step 3) Get TAD range
+	 */
+	prv = 0;
+	for (n_tads = 0; n_tads < MAX_TAD; n_tads++) {
+		pci_read_config_dword(pvt->pci_ha0, tad_dram_rule[n_tads],
+				      &reg);
+		limit = TAD_LIMIT(reg);
+		if (limit <= prv)
+			break;
+		tmp_mb = (limit + 1) >> 20;
+
+		debugf0("TAD#%d: up to %Lu.%03Lu GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n",
+			n_tads, tmp_mb / 1000, tmp_mb % 1000,
+			((u64)tmp_mb) << 20L,
+			(u32)TAD_SOCK(reg),
+			(u32)TAD_CH(reg),
+			(u32)TAD_TGT0(reg),
+			(u32)TAD_TGT1(reg),
+			(u32)TAD_TGT2(reg),
+			(u32)TAD_TGT3(reg),
+			reg);
+		prv = tmp_mb;
+	}
+
+	/*
+	 * Step 4) Get TAD offsets, per each channel
+	 */
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		if (!pvt->channel[i].dimms)
+			continue;
+		for (j = 0; j < n_tads; j++) {
+			pci_read_config_dword(pvt->pci_tad[i],
+					      tad_ch_nilv_offset[j],
+					      &reg);
+			tmp_mb = TAD_OFFSET(reg) >> 20;
+			debugf0("TAD CH#%d, offset #%d: %Lu.%03Lu GB (0x%016Lx), reg=0x%08x\n",
+				i, j,
+				tmp_mb / 1000, tmp_mb % 1000,
+				((u64)tmp_mb) << 20L,
+				reg);
+		}
+	}
+
+	/*
+	 * Step 6) Get RIR Wayness/Limit, per each channel
+	 */
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		if (!pvt->channel[i].dimms)
+			continue;
+		for (j = 0; j < MAX_RIR_RANGES; j++) {
+			pci_read_config_dword(pvt->pci_tad[i],
+					      rir_way_limit[j],
+					      &reg);
+
+			if (!IS_RIR_VALID(reg))
+				continue;
+
+			tmp_mb = RIR_LIMIT(reg) >> 20;
+			rir_way = 1 << RIR_WAY(reg);
+			debugf0("CH#%d RIR#%d, limit: %Lu.%03Lu GB (0x%016Lx), way: %d, reg=0x%08x\n",
+				i, j,
+				tmp_mb / 1000, tmp_mb % 1000,
+				((u64)tmp_mb) << 20L,
+				rir_way,
+				reg);
+
+			for (k = 0; k < rir_way; k++) {
+				pci_read_config_dword(pvt->pci_tad[i],
+						      rir_offset[j][k],
+						      &reg);
+				tmp_mb = RIR_OFFSET(reg) << 6;
+
+				debugf0("CH#%d RIR#%d INTL#%d, offset %Lu.%03Lu GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
+					i, j, k,
+					tmp_mb / 1000, tmp_mb % 1000,
+					((u64)tmp_mb) << 20L,
+					(u32)RIR_RNK_TGT(reg),
+					reg);
+			}
+		}
+	}
+}
+
+struct mem_ctl_info *get_mci_for_node_id(u8 node_id)
+{
+	struct sbridge_dev *sbridge_dev;
+
+	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
+		if (sbridge_dev->node_id == node_id)
+			return sbridge_dev->mci;
+	}
+	return NULL;
+}
+
+static int get_memory_error_data(struct mem_ctl_info *mci,
+				 u64 addr,
+				 u8 *socket,
+				 long *channel_mask,
+				 u8 *rank,
+				 char *area_type)
+{
+	struct mem_ctl_info	*new_mci;
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	char			msg[256];
+	int 			n_rir, n_sads, n_tads, sad_way, sck_xch;
+	int			sad_interl, idx, base_ch;
+	int			interleave_mode;
+	unsigned		sad_interleave[MAX_INTERLEAVE];
+	u32			reg;
+	u8			ch_way,sck_way;
+	u32			tad_offset;
+	u32			rir_way;
+	u64			ch_addr, offset, limit, prv = 0;
+
+
+	/*
+	 * Step 0) Check if the address is at special memory ranges
+	 * The check bellow is probably enough to fill all cases where
+	 * the error is not inside a memory, except for the legacy
+	 * range (e. g. VGA addresses). It is unlikely, however, that the
+	 * memory controller would generate an error on that range.
+	 */
+	if ((addr > (u64) pvt->tolm) && (addr < (1L << 32))) {
+		sprintf(msg, "Error at TOLM area, on addr 0x%08Lx", addr);
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	if (addr >= (u64)pvt->tohm) {
+		sprintf(msg, "Error at MMIOH area, on addr 0x%016Lx", addr);
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+
+	/*
+	 * Step 1) Get socket
+	 */
+	for (n_sads = 0; n_sads < MAX_SAD; n_sads++) {
+		pci_read_config_dword(pvt->pci_sad0, dram_rule[n_sads],
+				      &reg);
+
+		if (!DRAM_RULE_ENABLE(reg))
+			continue;
+
+		limit = SAD_LIMIT(reg);
+		if (limit <= prv) {
+			sprintf(msg, "Can't discover the memory socket");
+			edac_mc_handle_ce_no_info(mci, msg);
+			return -EINVAL;
+		}
+		if  (addr <= limit)
+			break;
+		prv = limit;
+	}
+	if (n_sads == MAX_SAD) {
+		sprintf(msg, "Can't discover the memory socket");
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	area_type = get_dram_attr(reg);
+	interleave_mode = INTERLEAVE_MODE(reg);
+
+	pci_read_config_dword(pvt->pci_sad0, interleave_list[n_sads],
+			      &reg);
+	sad_interl = sad_pkg(reg, 0);
+	for (sad_way = 0; sad_way < 8; sad_way++) {
+		if (sad_way > 0 && sad_interl == sad_pkg(reg, sad_way))
+			break;
+		sad_interleave[sad_way] = sad_pkg(reg, sad_way);
+		debugf0("SAD interleave #%d: %d\n",
+			sad_way, sad_interleave[sad_way]);
+	}
+	debugf0("mc#%d: Error detected on SAD#%d: address 0x%016Lx < 0x%016Lx, Interleave [%d:6]%s\n",
+		pvt->sbridge_dev->mc,
+		n_sads,
+		addr,
+		limit,
+		sad_way + 7,
+		INTERLEAVE_MODE(reg) ? "" : "XOR[18:16]");
+	if (interleave_mode)
+		idx = ((addr >> 6) ^ (addr >> 16)) & 7;
+	else
+		idx = (addr >> 6) & 7;
+	switch (sad_way) {
+	case 1:
+		idx = 0;
+		break;
+	case 2:
+		idx = idx & 1;
+		break;
+	case 4:
+		idx = idx & 3;
+		break;
+	case 8:
+		break;
+	default:
+		sprintf(msg, "Can't discover socket interleave");
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	*socket = sad_interleave[idx];
+	debugf0("SAD interleave index: %d (wayness %d) = CPU socket %d\n",
+		idx, sad_way, *socket);
+
+	/*
+	 * Move to the proper node structure, in order to access the
+	 * right PCI registers
+	 */
+	new_mci = get_mci_for_node_id(*socket);
+	if (!new_mci) {
+		sprintf(msg, "Struct for socket #%u wasn't initialized",
+			*socket);
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	mci = new_mci;
+	pvt = mci->pvt_info;
+
+	/*
+	 * Step 2) Get memory channel
+	 */
+	prv = 0;
+	for (n_tads = 0; n_tads < MAX_TAD; n_tads++) {
+		pci_read_config_dword(pvt->pci_ha0, tad_dram_rule[n_tads],
+				      &reg);
+		limit = TAD_LIMIT(reg);
+		if (limit <= prv) {
+			sprintf(msg, "Can't discover the memory channel");
+			edac_mc_handle_ce_no_info(mci, msg);
+			return -EINVAL;
+		}
+		if  (addr <= limit)
+			break;
+		prv = limit;
+	}
+	ch_way = TAD_CH(reg) + 1;
+	sck_way = TAD_SOCK(reg) + 1;
+	/*
+	 * FIXME: Is it right to always use channel 0 for offsets?
+	 */
+	pci_read_config_dword(pvt->pci_tad[0],
+				tad_ch_nilv_offset[n_tads],
+				&tad_offset);
+
+	if (ch_way == 3)
+		idx = addr >> 6;
+	else
+		idx = addr >> (6 + sck_way);
+	idx = idx % ch_way;
+
+	/*
+	 * FIXME: Shouldn't we use CHN_IDX_OFFSET() here, when ch_way == 3 ???
+	 */
+	switch (idx) {
+	case 0:
+		base_ch = TAD_TGT0(reg);
+		break;
+	case 1:
+		base_ch = TAD_TGT1(reg);
+		break;
+	case 2:
+		base_ch = TAD_TGT2(reg);
+		break;
+	case 3:
+		base_ch = TAD_TGT3(reg);
+		break;
+	default:
+		sprintf(msg, "Can't discover the TAD target");
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	*channel_mask = 1 << base_ch;
+
+	if (pvt->is_mirrored) {
+		*channel_mask |= 1 << ((base_ch + 2) % 4);
+		switch(ch_way) {
+		case 2:
+		case 4:
+			sck_xch = 1 << sck_way * (ch_way >> 1);
+			break;
+		default:
+			sprintf(msg, "Invalid mirror set. Can't decode addr");
+			edac_mc_handle_ce_no_info(mci, msg);
+			return -EINVAL;
+		}
+	} else
+		sck_xch = (1 << sck_way) * ch_way;
+
+	if (pvt->is_lockstep)
+		*channel_mask |= 1 << ((base_ch + 1) % 4);
+
+	offset = TAD_OFFSET(tad_offset);
+
+	debugf0("TAD#%d: address 0x%016Lx < 0x%016Lx, socket interleave %d, channel interleave %d (offset 0x%08Lx), index %d, base ch: %d, ch mask: 0x%02lx\n",
+		n_tads,
+		addr,
+		limit,
+		(u32)TAD_SOCK(reg),
+		ch_way,
+		offset,
+		idx,
+		base_ch,
+		*channel_mask);
+
+	/* Calculate channel address */
+	/* Remove the TAD offset */
+
+	if (offset > addr) {
+		sprintf(msg, "Can't calculate ch addr: TAD offset 0x%08Lx is too high for addr 0x%08Lx!",
+			offset, addr);
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	addr -= offset;
+	/* Store the low bits [0:6] of the addr */
+	ch_addr = addr & 0x7f;
+	/* Remove socket wayness and remove 6 bits */
+	addr >>= 6;
+	addr /= sck_xch;
+#if 0
+	/* Divide by channel way */
+	addr = addr / ch_way;
+#endif
+	/* Recover the last 6 bits */
+	ch_addr |= addr << 6;
+
+	/*
+	 * Step 3) Decode rank
+	 */
+	for (n_rir = 0; n_rir < MAX_RIR_RANGES; n_rir++) {
+		pci_read_config_dword(pvt->pci_tad[base_ch],
+				      rir_way_limit[n_rir],
+				      &reg);
+
+		if (!IS_RIR_VALID(reg))
+			continue;
+
+		limit = RIR_LIMIT(reg);
+
+		debugf0("RIR#%d, limit: %Lu.%03Lu GB (0x%016Lx), way: %d\n",
+			n_rir,
+			(limit >> 20) / 1000, (limit >> 20) % 1000,
+			limit,
+			1 << RIR_WAY(reg));
+		if  (ch_addr <= limit)
+			break;
+	}
+	if (n_rir == MAX_RIR_RANGES) {
+		sprintf(msg, "Can't discover the memory rank for ch addr 0x%08Lx",
+			ch_addr);
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	rir_way = RIR_WAY(reg);
+	if (pvt->is_close_pg)
+		idx = (ch_addr >> 6);
+	else
+		idx = (ch_addr >> 13);	/* FIXME: Datasheet says to shift by 15 */
+	idx %= 1 << rir_way;
+
+	pci_read_config_dword(pvt->pci_tad[base_ch],
+			      rir_offset[n_rir][idx],
+			      &reg);
+	*rank = RIR_RNK_TGT(reg);
+
+	debugf0("RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n",
+		n_rir,
+		ch_addr,
+		limit,
+		rir_way,
+		idx);
+
+	return 0;
+}
+
+/****************************************************************************
+	Device initialization routines: put/get, init/exit
+ ****************************************************************************/
+
+/*
+ *	sbridge_put_all_devices	'put' all the devices that we have
+ *				reserved via 'get'
+ */
+static void sbridge_put_devices(struct sbridge_dev *sbridge_dev)
+{
+	int i;
+
+	debugf0(__FILE__ ": %s()\n", __func__);
+	for (i = 0; i < sbridge_dev->n_devs; i++) {
+		struct pci_dev *pdev = sbridge_dev->pdev[i];
+		if (!pdev)
+			continue;
+		debugf0("Removing dev %02x:%02x.%d\n",
+			pdev->bus->number,
+			PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+		pci_dev_put(pdev);
+	}
+}
+
+static void sbridge_put_all_devices(void)
+{
+	struct sbridge_dev *sbridge_dev, *tmp;
+
+	list_for_each_entry_safe(sbridge_dev, tmp, &sbridge_edac_list, list) {
+		sbridge_put_devices(sbridge_dev);
+		free_sbridge_dev(sbridge_dev);
+	}
+}
+
+/*
+ *	sbridge_get_all_devices	Find and perform 'get' operation on the MCH's
+ *			device/functions we want to reference for this driver
+ *
+ *			Need to 'get' device 16 func 1 and func 2
+ */
+static int sbridge_get_onedevice(struct pci_dev **prev,
+				 u8 *num_mc,
+				 const struct pci_id_table *table,
+				 const unsigned devno)
+{
+	struct sbridge_dev *sbridge_dev;
+	const struct pci_id_descr *dev_descr = &table->descr[devno];
+
+	struct pci_dev *pdev = NULL;
+	u8 bus = 0;
+
+	sbridge_printk(KERN_INFO,
+		"Seeking for: dev %02x.%d PCI ID %04x:%04x\n",
+		dev_descr->dev, dev_descr->func,
+		PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+
+	pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+			      dev_descr->dev_id, *prev);
+
+	if (!pdev) {
+		if (*prev) {
+			*prev = pdev;
+			return 0;
+		}
+
+		if (dev_descr->optional)
+			return 0;
+
+		if (devno == 0)
+			return -ENODEV;
+
+		sbridge_printk(KERN_INFO,
+			"Device not found: dev %02x.%d PCI ID %04x:%04x\n",
+			dev_descr->dev, dev_descr->func,
+			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+
+		/* End of list, leave */
+		return -ENODEV;
+	}
+	bus = pdev->bus->number;
+
+	sbridge_dev = get_sbridge_dev(bus);
+	if (!sbridge_dev) {
+		sbridge_dev = alloc_sbridge_dev(bus, table);
+		if (!sbridge_dev) {
+			pci_dev_put(pdev);
+			return -ENOMEM;
+		}
+		(*num_mc)++;
+	}
+
+	if (sbridge_dev->pdev[devno]) {
+		sbridge_printk(KERN_ERR,
+			"Duplicated device for "
+			"dev %02x:%d.%d PCI ID %04x:%04x\n",
+			bus, dev_descr->dev, dev_descr->func,
+			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+		pci_dev_put(pdev);
+		return -ENODEV;
+	}
+
+	sbridge_dev->pdev[devno] = pdev;
+
+	/* Sanity check */
+	if (unlikely(PCI_SLOT(pdev->devfn) != dev_descr->dev ||
+			PCI_FUNC(pdev->devfn) != dev_descr->func)) {
+		sbridge_printk(KERN_ERR,
+			"Device PCI ID %04x:%04x "
+			"has dev %02x:%d.%d instead of dev %02x:%02x.%d\n",
+			PCI_VENDOR_ID_INTEL, dev_descr->dev_id,
+			bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+			bus, dev_descr->dev, dev_descr->func);
+		return -ENODEV;
+	}
+
+	/* Be sure that the device is enabled */
+	if (unlikely(pci_enable_device(pdev) < 0)) {
+		sbridge_printk(KERN_ERR,
+			"Couldn't enable "
+			"dev %02x:%d.%d PCI ID %04x:%04x\n",
+			bus, dev_descr->dev, dev_descr->func,
+			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+		return -ENODEV;
+	}
+
+	debugf0("Detected dev %02x:%d.%d PCI ID %04x:%04x\n",
+		bus, dev_descr->dev,
+		dev_descr->func,
+		PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+
+	/*
+	 * As stated on drivers/pci/search.c, the reference count for
+	 * @from is always decremented if it is not %NULL. So, as we need
+	 * to get all devices up to null, we need to do a get for the device
+	 */
+	pci_dev_get(pdev);
+
+	*prev = pdev;
+
+	return 0;
+}
+
+static int sbridge_get_all_devices(u8 *num_mc)
+{
+	int i, rc;
+	struct pci_dev *pdev = NULL;
+	const struct pci_id_table *table = pci_dev_descr_sbridge_table;
+
+	while (table && table->descr) {
+		for (i = 0; i < table->n_devs; i++) {
+			pdev = NULL;
+			do {
+				rc = sbridge_get_onedevice(&pdev, num_mc,
+							   table, i);
+				if (rc < 0) {
+					if (i == 0) {
+						i = table->n_devs;
+						break;
+					}
+					sbridge_put_all_devices();
+					return -ENODEV;
+				}
+			} while (pdev);
+		}
+		table++;
+	}
+
+	return 0;
+}
+
+static int mci_bind_devs(struct mem_ctl_info *mci,
+			 struct sbridge_dev *sbridge_dev)
+{
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	struct pci_dev *pdev;
+	int i, func, slot;
+
+	for (i = 0; i < sbridge_dev->n_devs; i++) {
+		pdev = sbridge_dev->pdev[i];
+		if (!pdev)
+			continue;
+		slot = PCI_SLOT(pdev->devfn);
+		func = PCI_FUNC(pdev->devfn);
+		switch (slot) {
+		case 12:
+			switch (func) {
+			case 6:
+				pvt->pci_sad0 = pdev;
+				break;
+			case 7:
+				pvt->pci_sad1 = pdev;
+				break;
+			default:
+				goto error;
+			}
+			break;
+		case 13:
+			switch (func) {
+			case 6:
+				pvt->pci_br = pdev;
+				break;
+			default:
+				goto error;
+			}
+			break;
+		case 14:
+			switch (func) {
+			case 0:
+				pvt->pci_ha0 = pdev;
+				break;
+			default:
+				goto error;
+			}
+			break;
+		case 15:
+			switch (func) {
+			case 0:
+				pvt->pci_ta = pdev;
+				break;
+			case 1:
+				pvt->pci_ras = pdev;
+				break;
+			case 2:
+			case 3:
+			case 4:
+			case 5:
+				pvt->pci_tad[func - 2] = pdev;
+				break;
+			default:
+				goto error;
+			}
+			break;
+		case 17:
+			switch (func) {
+			case 0:
+				pvt->pci_ddrio = pdev;
+				break;
+			default:
+				goto error;
+			}
+			break;
+		default:
+			goto error;
+		}
+
+		debugf0("Associated PCI %02x.%02d.%d with dev = %p\n",
+			sbridge_dev->bus,
+			PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+			pdev);
+	}
+
+	/* Check if everything were registered */
+	if (!pvt->pci_sad0 || !pvt->pci_sad1 || !pvt->pci_ha0 ||
+	    !pvt-> pci_tad || !pvt->pci_ras  || !pvt->pci_ta ||
+	    !pvt->pci_ddrio)
+		goto enodev;
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		if (!pvt->pci_tad[i])
+			goto enodev;
+	}
+	return 0;
+
+enodev:
+	sbridge_printk(KERN_ERR, "Some needed devices are missing\n");
+	return -ENODEV;
+
+error:
+	sbridge_printk(KERN_ERR, "Device %d, function %d "
+		      "is out of the expected range\n",
+		      slot, func);
+	return -EINVAL;
+}
+
+/****************************************************************************
+			Error check routines
+ ****************************************************************************/
+
+/*
+ * While Sandy Bridge has error count registers, SMI BIOS read values from
+ * and resets the counters. So, they are not reliable for the OS to read
+ * from them. So, we have no option but to just trust on whatever MCE is
+ * telling us about the errors.
+ */
+static void sbridge_mce_output_error(struct mem_ctl_info *mci,
+				    const struct mce *m)
+{
+	struct mem_ctl_info *new_mci;
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	char *type, *optype, *msg, *recoverable_msg;
+	bool ripv = GET_BITFIELD(m->mcgstatus, 0, 0);
+	bool overflow = GET_BITFIELD(m->status, 62, 62);
+	bool uncorrected_error = GET_BITFIELD(m->status, 61, 61);
+	bool recoverable = GET_BITFIELD(m->status, 56, 56);
+	u32 core_err_cnt = GET_BITFIELD(m->status, 38, 52);
+	u32 mscod = GET_BITFIELD(m->status, 16, 31);
+	u32 errcode = GET_BITFIELD(m->status, 0, 15);
+	u32 channel = GET_BITFIELD(m->status, 0, 3);
+	u32 optypenum = GET_BITFIELD(m->status, 4, 6);
+	long channel_mask, first_channel;
+	u8  rank, socket;
+	int csrow, rc, dimm;
+	char *area_type = "Unknown";
+
+	if (ripv)
+		type = "NON_FATAL";
+	else
+		type = "FATAL";
+
+	/*
+	 * According with Table 15-9 of the Intel Archictecture spec vol 3A,
+	 * memory errors should fit in this mask:
+	 *	000f 0000 1mmm cccc (binary)
+	 * where:
+	 *	f = Correction Report Filtering Bit. If 1, subsequent errors
+	 *	    won't be shown
+	 *	mmm = error type
+	 *	cccc = channel
+	 * If the mask doesn't match, report an error to the parsing logic
+	 */
+	if (! ((errcode & 0xef80) == 0x80)) {
+		optype = "Can't parse: it is not a mem";
+	} else {
+		switch (optypenum) {
+		case 0:
+			optype = "generic undef request";
+			break;
+		case 1:
+			optype = "memory read";
+			break;
+		case 2:
+			optype = "memory write";
+			break;
+		case 3:
+			optype = "addr/cmd";
+			break;
+		case 4:
+			optype = "memory scrubbing";
+			break;
+		default:
+			optype = "reserved";
+			break;
+		}
+	}
+
+	rc = get_memory_error_data(mci, m->addr, &socket,
+				   &channel_mask, &rank, area_type);
+	if (rc < 0)
+		return;
+	new_mci = get_mci_for_node_id(socket);
+	if (!new_mci) {
+		edac_mc_handle_ce_no_info(mci, "Error: socket got corrupted!");
+		return;
+	}
+	mci = new_mci;
+	pvt = mci->pvt_info;
+
+	first_channel = find_first_bit(&channel_mask, NUM_CHANNELS);
+
+	if (rank < 4)
+		dimm = 0;
+	else if (rank < 8)
+		dimm = 1;
+	else
+		dimm = 2;
+
+	csrow = pvt->csrow_map[first_channel][dimm];
+
+	if (uncorrected_error && recoverable)
+		recoverable_msg = " recoverable";
+	else
+		recoverable_msg = "";
+
+	/*
+	 * FIXME: What should we do with "channel" information on mcelog?
+	 * Probably, we can just discard it, as the channel information
+	 * comes from the get_memory_error_data() address decoding
+	 */
+	msg = kasprintf(GFP_ATOMIC,
+			"%d %s error(s): %s on %s area %s%s: cpu=%d Err=%04x:%04x (ch=%d), "
+			"addr = 0x%08llx => socket=%d, Channel=%ld(mask=%ld), rank=%d\n",
+			core_err_cnt,
+			area_type,
+			optype,
+			type,
+			recoverable_msg,
+			overflow ? "OVERFLOW" : "",
+			m->cpu,
+			mscod, errcode,
+			channel,		/* 1111b means not specified */
+			(long long) m->addr,
+			socket,
+			first_channel,		/* This is the real channel on SB */
+			channel_mask,
+			rank);
+
+	debugf0("%s", msg);
+
+	/* Call the helper to output message */
+	if (uncorrected_error)
+		edac_mc_handle_fbd_ue(mci, csrow, 0, 0, msg);
+	else
+		edac_mc_handle_fbd_ce(mci, csrow, 0, msg);
+
+	kfree(msg);
+}
+
+/*
+ *	sbridge_check_error	Retrieve and process errors reported by the
+ *				hardware. Called by the Core module.
+ */
+static void sbridge_check_error(struct mem_ctl_info *mci)
+{
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	int i;
+	unsigned count = 0;
+	struct mce *m;
+
+	/*
+	 * 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.
+	 */
+	smp_rmb();
+	count = (pvt->mce_out + MCE_LOG_LEN - pvt->mce_in)
+		% MCE_LOG_LEN;
+	if (!count)
+		return;
+
+	m = pvt->mce_outentry;
+	if (pvt->mce_in + count > MCE_LOG_LEN) {
+		unsigned l = MCE_LOG_LEN - pvt->mce_in;
+
+		memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * l);
+		smp_wmb();
+		pvt->mce_in = 0;
+		count -= l;
+		m += l;
+	}
+	memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * count);
+	smp_wmb();
+	pvt->mce_in += count;
+
+	smp_rmb();
+	if (pvt->mce_overrun) {
+		sbridge_printk(KERN_ERR, "Lost %d memory errors\n",
+			      pvt->mce_overrun);
+		smp_wmb();
+		pvt->mce_overrun = 0;
+	}
+
+	/*
+	 * MCE second step: parse errors and display
+	 */
+	for (i = 0; i < count; i++)
+		sbridge_mce_output_error(mci, &pvt->mce_outentry[i]);
+}
+
+/*
+ * sbridge_mce_check_error	Replicates mcelog routine to get errors
+ *				This routine simply queues mcelog errors, and
+ *				return. The error itself should be handled later
+ *				by sbridge_check_error.
+ * WARNING: As this routine should be called at NMI time, extra care should
+ * be taken to avoid deadlocks, and to be as fast as possible.
+ */
+static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
+				   void *data)
+{
+	struct mce *mce = (struct mce *)data;
+	struct mem_ctl_info *mci;
+	struct sbridge_pvt *pvt;
+
+	mci = get_mci_for_node_id(mce->socketid);
+	if (!mci)
+		return NOTIFY_BAD;
+	pvt = mci->pvt_info;
+
+	/*
+	 * Just let mcelog handle it if the error is
+	 * outside the memory controller. A memory error
+	 * is indicated by bit 7 = 1 and bits = 8-11,13-15 = 0.
+	 * bit 12 has an special meaning.
+	 */
+	if ((mce->status & 0xefff) >> 7 != 1)
+		return NOTIFY_DONE;
+
+	printk("sbridge: HANDLING MCE MEMORY ERROR\n");
+
+	printk("CPU %d: Machine Check Exception: %Lx Bank %d: %016Lx\n",
+	       mce->extcpu, mce->mcgstatus, mce->bank, mce->status);
+	printk("TSC %llx ", mce->tsc);
+	printk("ADDR %llx ", mce->addr);
+	printk("MISC %llx ", mce->misc);
+
+	printk("PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n",
+		mce->cpuvendor, mce->cpuid, mce->time,
+		mce->socketid, mce->apicid);
+
+#ifdef CONFIG_SMP
+	/* Only handle if it is the right mc controller */
+	if (cpu_data(mce->cpu).phys_proc_id != pvt->sbridge_dev->mc)
+		return NOTIFY_DONE;
+#endif
+
+	smp_rmb();
+	if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
+		smp_wmb();
+		pvt->mce_overrun++;
+		return NOTIFY_DONE;
+	}
+
+	/* Copy memory error at the ringbuffer */
+	memcpy(&pvt->mce_entry[pvt->mce_out], mce, sizeof(*mce));
+	smp_wmb();
+	pvt->mce_out = (pvt->mce_out + 1) % MCE_LOG_LEN;
+
+	/* Handle fatal errors immediately */
+	if (mce->mcgstatus & 1)
+		sbridge_check_error(mci);
+
+	/* Advice mcelog that the error were handled */
+	return NOTIFY_STOP;
+}
+
+static struct notifier_block sbridge_mce_dec = {
+	.notifier_call      = sbridge_mce_check_error,
+};
+
+/****************************************************************************
+			EDAC register/unregister logic
+ ****************************************************************************/
+
+static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev)
+{
+	struct mem_ctl_info *mci = sbridge_dev->mci;
+	struct sbridge_pvt *pvt;
+
+	if (unlikely(!mci || !mci->pvt_info)) {
+		debugf0("MC: " __FILE__ ": %s(): dev = %p\n",
+			__func__, &sbridge_dev->pdev[0]->dev);
+
+		sbridge_printk(KERN_ERR, "Couldn't find mci handler\n");
+		return;
+	}
+
+	pvt = mci->pvt_info;
+
+	debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
+		__func__, mci, &sbridge_dev->pdev[0]->dev);
+
+	atomic_notifier_chain_unregister(&x86_mce_decoder_chain,
+					 &sbridge_mce_dec);
+
+	/* Remove MC sysfs nodes */
+	edac_mc_del_mc(mci->dev);
+
+	debugf1("%s: free mci struct\n", mci->ctl_name);
+	kfree(mci->ctl_name);
+	edac_mc_free(mci);
+	sbridge_dev->mci = NULL;
+}
+
+static int sbridge_register_mci(struct sbridge_dev *sbridge_dev)
+{
+	struct mem_ctl_info *mci;
+	struct sbridge_pvt *pvt;
+	int rc, channels, csrows;
+
+	/* Check the number of active and not disabled channels */
+	rc = sbridge_get_active_channels(sbridge_dev->bus, &channels, &csrows);
+	if (unlikely(rc < 0))
+		return rc;
+
+	/* allocate a new MC control structure */
+	mci = edac_mc_alloc(sizeof(*pvt), csrows, channels, sbridge_dev->mc);
+	if (unlikely(!mci))
+		return -ENOMEM;
+
+	debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
+		__func__, mci, &sbridge_dev->pdev[0]->dev);
+
+	pvt = mci->pvt_info;
+	memset(pvt, 0, sizeof(*pvt));
+
+	/* Associate sbridge_dev and mci for future usage */
+	pvt->sbridge_dev = sbridge_dev;
+	sbridge_dev->mci = mci;
+
+	mci->mtype_cap = MEM_FLAG_DDR3;
+	mci->edac_ctl_cap = EDAC_FLAG_NONE;
+	mci->edac_cap = EDAC_FLAG_NONE;
+	mci->mod_name = "sbridge_edac.c";
+	mci->mod_ver = SBRIDGE_REVISION;
+	mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx);
+	mci->dev_name = pci_name(sbridge_dev->pdev[0]);
+	mci->ctl_page_to_phys = NULL;
+
+	/* Set the function pointer to an actual operation function */
+	mci->edac_check = sbridge_check_error;
+
+	/* Store pci devices at mci for faster access */
+	rc = mci_bind_devs(mci, sbridge_dev);
+	if (unlikely(rc < 0))
+		goto fail0;
+
+	/* Get dimm basic config and the memory layout */
+	get_dimm_config(mci);
+	get_memory_layout(mci);
+
+	/* record ptr to the generic device */
+	mci->dev = &sbridge_dev->pdev[0]->dev;
+
+	/* add this new MC control structure to EDAC's list of MCs */
+	if (unlikely(edac_mc_add_mc(mci))) {
+		debugf0("MC: " __FILE__
+			": %s(): failed edac_mc_add_mc()\n", __func__);
+		rc = -EINVAL;
+		goto fail0;
+	}
+
+	atomic_notifier_chain_register(&x86_mce_decoder_chain,
+				       &sbridge_mce_dec);
+	return 0;
+
+fail0:
+	kfree(mci->ctl_name);
+	edac_mc_free(mci);
+	sbridge_dev->mci = NULL;
+	return rc;
+}
+
+/*
+ *	sbridge_probe	Probe for ONE instance of device to see if it is
+ *			present.
+ *	return:
+ *		0 for FOUND a device
+ *		< 0 for error code
+ */
+
+static int __devinit sbridge_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *id)
+{
+	int rc;
+	u8 mc, num_mc = 0;
+	struct sbridge_dev *sbridge_dev;
+
+	/* get the pci devices we want to reserve for our use */
+	mutex_lock(&sbridge_edac_lock);
+
+	/*
+	 * All memory controllers are allocated at the first pass.
+	 */
+	if (unlikely(probed >= 1)) {
+		mutex_unlock(&sbridge_edac_lock);
+		return -ENODEV;
+	}
+	probed++;
+
+	rc = sbridge_get_all_devices(&num_mc);
+	if (unlikely(rc < 0))
+		goto fail0;
+	mc = 0;
+
+	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
+		debugf0("Registering MC#%d (%d of %d)\n", mc, mc + 1, num_mc);
+		sbridge_dev->mc = mc++;
+		rc = sbridge_register_mci(sbridge_dev);
+		if (unlikely(rc < 0))
+			goto fail1;
+	}
+
+	sbridge_printk(KERN_INFO, "Driver loaded.\n");
+
+	mutex_unlock(&sbridge_edac_lock);
+	return 0;
+
+fail1:
+	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list)
+		sbridge_unregister_mci(sbridge_dev);
+
+	sbridge_put_all_devices();
+fail0:
+	mutex_unlock(&sbridge_edac_lock);
+	return rc;
+}
+
+/*
+ *	sbridge_remove	destructor for one instance of device
+ *
+ */
+static void __devexit sbridge_remove(struct pci_dev *pdev)
+{
+	struct sbridge_dev *sbridge_dev;
+
+	debugf0(__FILE__ ": %s()\n", __func__);
+
+	/*
+	 * we have a trouble here: pdev value for removal will be wrong, since
+	 * it will point to the X58 register used to detect that the machine
+	 * is a Nehalem or upper design. However, due to the way several PCI
+	 * devices are grouped together to provide MC functionality, we need
+	 * to use a different method for releasing the devices
+	 */
+
+	mutex_lock(&sbridge_edac_lock);
+
+	if (unlikely(!probed)) {
+		mutex_unlock(&sbridge_edac_lock);
+		return;
+	}
+
+	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list)
+		sbridge_unregister_mci(sbridge_dev);
+
+	/* Release PCI resources */
+	sbridge_put_all_devices();
+
+	probed--;
+
+	mutex_unlock(&sbridge_edac_lock);
+}
+
+MODULE_DEVICE_TABLE(pci, sbridge_pci_tbl);
+
+/*
+ *	sbridge_driver	pci_driver structure for this module
+ *
+ */
+static struct pci_driver sbridge_driver = {
+	.name     = "sbridge_edac",
+	.probe    = sbridge_probe,
+	.remove   = __devexit_p(sbridge_remove),
+	.id_table = sbridge_pci_tbl,
+};
+
+/*
+ *	sbridge_init		Module entry function
+ *			Try to initialize this module for its devices
+ */
+static int __init sbridge_init(void)
+{
+	int pci_rc;
+
+	debugf2("MC: " __FILE__ ": %s()\n", __func__);
+
+	/* Ensure that the OPSTATE is set correctly for POLL or NMI */
+	opstate_init();
+
+	pci_rc = pci_register_driver(&sbridge_driver);
+
+	if (pci_rc >= 0)
+		return 0;
+
+	sbridge_printk(KERN_ERR, "Failed to register device with error %d.\n",
+		      pci_rc);
+
+	return pci_rc;
+}
+
+/*
+ *	sbridge_exit()	Module exit function
+ *			Unregister the driver
+ */
+static void __exit sbridge_exit(void)
+{
+	debugf2("MC: " __FILE__ ": %s()\n", __func__);
+	pci_unregister_driver(&sbridge_driver);
+}
+
+module_init(sbridge_init);
+module_exit(sbridge_exit);
+
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("MC Driver for Intel Sandy Bridge memory controllers - "
+		   SBRIDGE_REVISION);
diff -druN linux-libre-3.1-gnu/drivers/firewire/core-iso.c linux-libre-3.2-gnu/drivers/firewire/core-iso.c
--- linux-libre-3.1-gnu/drivers/firewire/core-iso.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/firewire/core-iso.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 
 #include <asm/byteorder.h>
 
diff -druN linux-libre-3.1-gnu/drivers/firewire/core-transaction.c linux-libre-3.2-gnu/drivers/firewire/core-transaction.c
--- linux-libre-3.1-gnu/drivers/firewire/core-transaction.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/firewire/core-transaction.c	2012-01-04 18:55:44.000000000 -0500
@@ -1046,8 +1046,8 @@
 
 	cycles = card->split_timeout_hi * 8000 + (card->split_timeout_lo >> 19);
 
-	cycles = max(cycles, 800u); /* minimum as per the spec */
-	cycles = min(cycles, 3u * 8000u); /* maximum OHCI timeout */
+	/* minimum per IEEE 1394, maximum which doesn't overflow OHCI */
+	cycles = clamp(cycles, 800u, 3u * 8000u);
 
 	card->split_timeout_cycles = cycles;
 	card->split_timeout_jiffies = DIV_ROUND_UP(cycles * HZ, 8000);
diff -druN linux-libre-3.1-gnu/drivers/firewire/net.c linux-libre-3.2-gnu/drivers/firewire/net.c
--- linux-libre-3.1-gnu/drivers/firewire/net.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/firewire/net.c	2012-01-04 18:55:44.000000000 -0500
@@ -502,11 +502,7 @@
 static unsigned fwnet_max_payload(unsigned max_rec, unsigned speed)
 {
 	max_rec = min(max_rec, speed + 8);
-	max_rec = min(max_rec, 0xbU); /* <= 4096 */
-	if (max_rec < 8) {
-		fw_notify("max_rec %x out of range\n", max_rec);
-		max_rec = 8;
-	}
+	max_rec = clamp(max_rec, 8U, 11U); /* 512...4096 */
 
 	return (1 << (max_rec + 1)) - RFC2374_FRAG_HDR_SIZE;
 }
@@ -1125,17 +1121,12 @@
 	unsigned u;
 
 	if (dev->local_fifo == FWNET_NO_FIFO_ADDR) {
-		/* outside OHCI posted write area? */
-		static const struct fw_address_region region = {
-			.start = 0xffff00000000ULL,
-			.end   = CSR_REGISTER_BASE,
-		};
-
 		dev->handler.length = 4096;
 		dev->handler.address_callback = fwnet_receive_packet;
 		dev->handler.callback_data = dev;
 
-		retval = fw_core_add_address_handler(&dev->handler, &region);
+		retval = fw_core_add_address_handler(&dev->handler,
+					&fw_high_memory_region);
 		if (retval < 0)
 			goto failed_initial;
 
diff -druN linux-libre-3.1-gnu/drivers/firewire/ohci.c linux-libre-3.2-gnu/drivers/firewire/ohci.c
--- linux-libre-3.1-gnu/drivers/firewire/ohci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/firewire/ohci.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
 #include <linux/string.h>
 #include <linux/time.h>
 #include <linux/vmalloc.h>
+#include <linux/workqueue.h>
 
 #include <asm/byteorder.h>
 #include <asm/page.h>
@@ -125,6 +126,7 @@
 	struct fw_ohci *ohci;
 	u32 regs;
 	int total_allocation;
+	u32 current_bus;
 	bool running;
 	bool flushing;
 
@@ -226,7 +228,7 @@
 
 	__le32    *self_id_cpu;
 	dma_addr_t self_id_bus;
-	struct tasklet_struct bus_reset_tasklet;
+	struct work_struct bus_reset_work;
 
 	u32 self_id_buffer[512];
 };
@@ -263,6 +265,8 @@
 #define PCI_DEVICE_ID_AGERE_FW643	0x5901
 #define PCI_DEVICE_ID_JMICRON_JMB38X_FW	0x2380
 #define PCI_DEVICE_ID_TI_TSB12LV22	0x8009
+#define PCI_DEVICE_ID_TI_TSB12LV26	0x8020
+#define PCI_DEVICE_ID_TI_TSB82AA2	0x8025
 #define PCI_VENDOR_ID_PINNACLE_SYSTEMS	0x11bd
 
 #define QUIRK_CYCLE_TIMER		1
@@ -270,6 +274,7 @@
 #define QUIRK_BE_HEADERS		4
 #define QUIRK_NO_1394A			8
 #define QUIRK_NO_MSI			16
+#define QUIRK_TI_SLLZ059		32
 
 /* In case of multiple matches in ohci_quirks[], only the first one is used. */
 static const struct {
@@ -299,6 +304,12 @@
 	{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
 		QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
 
+	{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV26, PCI_ANY_ID,
+		QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059},
+
+	{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB82AA2, PCI_ANY_ID,
+		QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059},
+
 	{PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID,
 		QUIRK_RESET_PACKET},
 
@@ -315,6 +326,7 @@
 	", AR/selfID endianess = "	__stringify(QUIRK_BE_HEADERS)
 	", no 1394a enhancements = "	__stringify(QUIRK_NO_1394A)
 	", disable MSI = "		__stringify(QUIRK_NO_MSI)
+	", TI SLLZ059 erratum = "	__stringify(QUIRK_TI_SLLZ059)
 	")");
 
 #define OHCI_PARAM_DEBUG_AT_AR		1
@@ -859,7 +871,7 @@
 	 *
 	 * Alas some chips sometimes emit bus reset packets with a
 	 * wrong generation.  We set the correct generation for these
-	 * at a slightly incorrect time (in bus_reset_tasklet).
+	 * at a slightly incorrect time (in bus_reset_work).
 	 */
 	if (evt == OHCI1394_evt_bus_reset) {
 		if (!(ohci->quirks & QUIRK_RESET_PACKET))
@@ -1046,6 +1058,7 @@
 		address = le32_to_cpu(last->branch_address);
 		z = address & 0xf;
 		address &= ~0xf;
+		ctx->current_bus = address;
 
 		/* If the branch address points to a buffer outside of the
 		 * current buffer, advance to the next buffer. */
@@ -1713,9 +1726,94 @@
 	return ohci->bus_time | cycle_time_seconds;
 }
 
-static void bus_reset_tasklet(unsigned long data)
+static int get_status_for_port(struct fw_ohci *ohci, int port_index)
 {
-	struct fw_ohci *ohci = (struct fw_ohci *)data;
+	int reg;
+
+	mutex_lock(&ohci->phy_reg_mutex);
+	reg = write_phy_reg(ohci, 7, port_index);
+	if (reg >= 0)
+		reg = read_phy_reg(ohci, 8);
+	mutex_unlock(&ohci->phy_reg_mutex);
+	if (reg < 0)
+		return reg;
+
+	switch (reg & 0x0f) {
+	case 0x06:
+		return 2;	/* is child node (connected to parent node) */
+	case 0x0e:
+		return 3;	/* is parent node (connected to child node) */
+	}
+	return 1;		/* not connected */
+}
+
+static int get_self_id_pos(struct fw_ohci *ohci, u32 self_id,
+	int self_id_count)
+{
+	int i;
+	u32 entry;
+
+	for (i = 0; i < self_id_count; i++) {
+		entry = ohci->self_id_buffer[i];
+		if ((self_id & 0xff000000) == (entry & 0xff000000))
+			return -1;
+		if ((self_id & 0xff000000) < (entry & 0xff000000))
+			return i;
+	}
+	return i;
+}
+
+/*
+ * TI TSB82AA2B and TSB12LV26 do not receive the selfID of a locally
+ * attached TSB41BA3D phy; see http://www.ti.com/litv/pdf/sllz059.
+ * Construct the selfID from phy register contents.
+ * FIXME:  How to determine the selfID.i flag?
+ */
+static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count)
+{
+	int reg, i, pos, status;
+	/* link active 1, speed 3, bridge 0, contender 1, more packets 0 */
+	u32 self_id = 0x8040c800;
+
+	reg = reg_read(ohci, OHCI1394_NodeID);
+	if (!(reg & OHCI1394_NodeID_idValid)) {
+		fw_notify("node ID not valid, new bus reset in progress\n");
+		return -EBUSY;
+	}
+	self_id |= ((reg & 0x3f) << 24); /* phy ID */
+
+	reg = ohci_read_phy_reg(&ohci->card, 4);
+	if (reg < 0)
+		return reg;
+	self_id |= ((reg & 0x07) << 8); /* power class */
+
+	reg = ohci_read_phy_reg(&ohci->card, 1);
+	if (reg < 0)
+		return reg;
+	self_id |= ((reg & 0x3f) << 16); /* gap count */
+
+	for (i = 0; i < 3; i++) {
+		status = get_status_for_port(ohci, i);
+		if (status < 0)
+			return status;
+		self_id |= ((status & 0x3) << (6 - (i * 2)));
+	}
+
+	pos = get_self_id_pos(ohci, self_id, self_id_count);
+	if (pos >= 0) {
+		memmove(&(ohci->self_id_buffer[pos+1]),
+			&(ohci->self_id_buffer[pos]),
+			(self_id_count - pos) * sizeof(*ohci->self_id_buffer));
+		ohci->self_id_buffer[pos] = self_id;
+		self_id_count++;
+	}
+	return self_id_count;
+}
+
+static void bus_reset_work(struct work_struct *work)
+{
+	struct fw_ohci *ohci =
+		container_of(work, struct fw_ohci, bus_reset_work);
 	int self_id_count, i, j, reg;
 	int generation, new_generation;
 	unsigned long flags;
@@ -1753,21 +1851,50 @@
 	 * bit extra to get the actual number of self IDs.
 	 */
 	self_id_count = (reg >> 3) & 0xff;
-	if (self_id_count == 0 || self_id_count > 252) {
+
+	if (self_id_count > 252) {
 		fw_notify("inconsistent self IDs\n");
 		return;
 	}
+
 	generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
 	rmb();
 
 	for (i = 1, j = 0; j < self_id_count; i += 2, j++) {
 		if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1]) {
-			fw_notify("inconsistent self IDs\n");
-			return;
+			/*
+			 * If the invalid data looks like a cycle start packet,
+			 * it's likely to be the result of the cycle master
+			 * having a wrong gap count.  In this case, the self IDs
+			 * so far are valid and should be processed so that the
+			 * bus manager can then correct the gap count.
+			 */
+			if (cond_le32_to_cpu(ohci->self_id_cpu[i])
+							== 0xffff008f) {
+				fw_notify("ignoring spurious self IDs\n");
+				self_id_count = j;
+				break;
+			} else {
+				fw_notify("inconsistent self IDs\n");
+				return;
+			}
 		}
 		ohci->self_id_buffer[j] =
 				cond_le32_to_cpu(ohci->self_id_cpu[i]);
 	}
+
+	if (ohci->quirks & QUIRK_TI_SLLZ059) {
+		self_id_count = find_and_insert_self_id(ohci, self_id_count);
+		if (self_id_count < 0) {
+			fw_notify("could not construct local self ID\n");
+			return;
+		}
+	}
+
+	if (self_id_count == 0) {
+		fw_notify("inconsistent self IDs\n");
+		return;
+	}
 	rmb();
 
 	/*
@@ -1887,7 +2014,7 @@
 	log_irqs(event);
 
 	if (event & OHCI1394_selfIDComplete)
-		tasklet_schedule(&ohci->bus_reset_tasklet);
+		queue_work(fw_workqueue, &ohci->bus_reset_work);
 
 	if (event & OHCI1394_RQPkt)
 		tasklet_schedule(&ohci->ar_request_ctx.tasklet);
@@ -1934,7 +2061,8 @@
 		reg_read(ohci, OHCI1394_PostedWriteAddressLo);
 		reg_write(ohci, OHCI1394_IntEventClear,
 			  OHCI1394_postedWriteErr);
-		fw_error("PCI posted write error\n");
+		if (printk_ratelimit())
+			fw_error("PCI posted write error\n");
 	}
 
 	if (unlikely(event & OHCI1394_cycleTooLong)) {
@@ -2048,6 +2176,28 @@
 	return 0;
 }
 
+static int probe_tsb41ba3d(struct fw_ohci *ohci)
+{
+	/* TI vendor ID = 0x080028, TSB41BA3D product ID = 0x833005 (sic) */
+	static const u8 id[] = { 0x08, 0x00, 0x28, 0x83, 0x30, 0x05, };
+	int reg, i;
+
+	reg = read_phy_reg(ohci, 2);
+	if (reg < 0)
+		return reg;
+	if ((reg & PHY_EXTENDED_REGISTERS) != PHY_EXTENDED_REGISTERS)
+		return 0;
+
+	for (i = ARRAY_SIZE(id) - 1; i >= 0; i--) {
+		reg = read_paged_phy_reg(ohci, 1, i + 10);
+		if (reg < 0)
+			return reg;
+		if (reg != id[i])
+			return 0;
+	}
+	return 1;
+}
+
 static int ohci_enable(struct fw_card *card,
 		       const __be32 *config_rom, size_t length)
 {
@@ -2085,6 +2235,16 @@
 		return -EIO;
 	}
 
+	if (ohci->quirks & QUIRK_TI_SLLZ059) {
+		ret = probe_tsb41ba3d(ohci);
+		if (ret < 0)
+			return ret;
+		if (ret)
+			fw_notify("local TSB41BA3D phy\n");
+		else
+			ohci->quirks &= ~QUIRK_TI_SLLZ059;
+	}
+
 	reg_write(ohci, OHCI1394_HCControlClear,
 		  OHCI1394_HCControl_noByteSwapData);
 
@@ -2260,7 +2420,7 @@
 	 * then set up the real values for the two registers.
 	 *
 	 * We use ohci->lock to avoid racing with the code that sets
-	 * ohci->next_config_rom to NULL (see bus_reset_tasklet).
+	 * ohci->next_config_rom to NULL (see bus_reset_work).
 	 */
 
 	next_config_rom =
@@ -2539,6 +2699,7 @@
 	struct iso_context *ctx =
 		container_of(context, struct iso_context, context);
 	struct descriptor *pd;
+	u32 buffer_dma;
 	__le32 *ir_header;
 	void *p;
 
@@ -2549,6 +2710,16 @@
 		/* Descriptor(s) not done yet, stop iteration */
 		return 0;
 
+	while (!(d->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))) {
+		d++;
+		buffer_dma = le32_to_cpu(d->data_address);
+		dma_sync_single_range_for_cpu(context->ohci->card.device,
+					      buffer_dma & PAGE_MASK,
+					      buffer_dma & ~PAGE_MASK,
+					      le16_to_cpu(d->req_count),
+					      DMA_FROM_DEVICE);
+	}
+
 	p = last + 1;
 	copy_iso_headers(ctx, p);
 
@@ -2571,11 +2742,19 @@
 {
 	struct iso_context *ctx =
 		container_of(context, struct iso_context, context);
+	u32 buffer_dma;
 
 	if (!last->transfer_status)
 		/* Descriptor(s) not done yet, stop iteration */
 		return 0;
 
+	buffer_dma = le32_to_cpu(last->data_address);
+	dma_sync_single_range_for_cpu(context->ohci->card.device,
+				      buffer_dma & PAGE_MASK,
+				      buffer_dma & ~PAGE_MASK,
+				      le16_to_cpu(last->req_count),
+				      DMA_FROM_DEVICE);
+
 	if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS)
 		ctx->base.callback.mc(&ctx->base,
 				      le32_to_cpu(last->data_address) +
@@ -2586,6 +2765,43 @@
 	return 1;
 }
 
+static inline void sync_it_packet_for_cpu(struct context *context,
+					  struct descriptor *pd)
+{
+	__le16 control;
+	u32 buffer_dma;
+
+	/* only packets beginning with OUTPUT_MORE* have data buffers */
+	if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))
+		return;
+
+	/* skip over the OUTPUT_MORE_IMMEDIATE descriptor */
+	pd += 2;
+
+	/*
+	 * If the packet has a header, the first OUTPUT_MORE/LAST descriptor's
+	 * data buffer is in the context program's coherent page and must not
+	 * be synced.
+	 */
+	if ((le32_to_cpu(pd->data_address) & PAGE_MASK) ==
+	    (context->current_bus          & PAGE_MASK)) {
+		if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))
+			return;
+		pd++;
+	}
+
+	do {
+		buffer_dma = le32_to_cpu(pd->data_address);
+		dma_sync_single_range_for_cpu(context->ohci->card.device,
+					      buffer_dma & PAGE_MASK,
+					      buffer_dma & ~PAGE_MASK,
+					      le16_to_cpu(pd->req_count),
+					      DMA_TO_DEVICE);
+		control = pd->control;
+		pd++;
+	} while (!(control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS)));
+}
+
 static int handle_it_packet(struct context *context,
 			    struct descriptor *d,
 			    struct descriptor *last)
@@ -2602,6 +2818,8 @@
 		/* Descriptor(s) not done yet, stop iteration */
 		return 0;
 
+	sync_it_packet_for_cpu(context, d);
+
 	i = ctx->header_length;
 	if (i + 4 < PAGE_SIZE) {
 		/* Present this value as big-endian to match the receive code */
@@ -2971,6 +3189,10 @@
 		page_bus = page_private(buffer->pages[page]);
 		pd[i].data_address = cpu_to_le32(page_bus + offset);
 
+		dma_sync_single_range_for_device(ctx->context.ohci->card.device,
+						 page_bus, offset, length,
+						 DMA_TO_DEVICE);
+
 		payload_index += length;
 	}
 
@@ -2995,6 +3217,7 @@
 				       struct fw_iso_buffer *buffer,
 				       unsigned long payload)
 {
+	struct device *device = ctx->context.ohci->card.device;
 	struct descriptor *d, *pd;
 	dma_addr_t d_bus, page_bus;
 	u32 z, header_z, rest;
@@ -3049,6 +3272,10 @@
 			page_bus = page_private(buffer->pages[page]);
 			pd->data_address = cpu_to_le32(page_bus + offset);
 
+			dma_sync_single_range_for_device(device, page_bus,
+							 offset, length,
+							 DMA_FROM_DEVICE);
+
 			offset = (offset + length) & ~PAGE_MASK;
 			rest -= length;
 			if (offset == 0)
@@ -3108,6 +3335,10 @@
 		page_bus = page_private(buffer->pages[page]);
 		d->data_address = cpu_to_le32(page_bus + offset);
 
+		dma_sync_single_range_for_device(ctx->context.ohci->card.device,
+						 page_bus, offset, length,
+						 DMA_FROM_DEVICE);
+
 		rest -= length;
 		offset = 0;
 		page++;
@@ -3239,8 +3470,7 @@
 	spin_lock_init(&ohci->lock);
 	mutex_init(&ohci->phy_reg_mutex);
 
-	tasklet_init(&ohci->bus_reset_tasklet,
-		     bus_reset_tasklet, (unsigned long)ohci);
+	INIT_WORK(&ohci->bus_reset_work, bus_reset_work);
 
 	err = pci_request_region(dev, 0, ohci_driver_name);
 	if (err) {
@@ -3382,6 +3612,7 @@
 	ohci = pci_get_drvdata(dev);
 	reg_write(ohci, OHCI1394_IntMaskClear, ~0);
 	flush_writes(ohci);
+	cancel_work_sync(&ohci->bus_reset_work);
 	fw_core_remove_card(&ohci->card);
 
 	/*
diff -druN linux-libre-3.1-gnu/drivers/firewire/sbp2.c linux-libre-3.2-gnu/drivers/firewire/sbp2.c
--- linux-libre-3.1-gnu/drivers/firewire/sbp2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/firewire/sbp2.c	2012-01-04 18:55:44.000000000 -0500
@@ -154,12 +154,16 @@
 	bool blocked;
 };
 
+static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
+{
+	queue_delayed_work(fw_workqueue, &lu->work, delay);
+}
+
 /*
  * We create one struct sbp2_target per IEEE 1212 Unit Directory
  * and one struct Scsi_Host per sbp2_target.
  */
 struct sbp2_target {
-	struct kref kref;
 	struct fw_unit *unit;
 	const char *bus_id;
 	struct list_head lu_list;
@@ -772,71 +776,6 @@
 	return scsilun_to_int(&eight_bytes_lun);
 }
 
-static void sbp2_release_target(struct kref *kref)
-{
-	struct sbp2_target *tgt = container_of(kref, struct sbp2_target, kref);
-	struct sbp2_logical_unit *lu, *next;
-	struct Scsi_Host *shost =
-		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
-	struct scsi_device *sdev;
-	struct fw_device *device = target_device(tgt);
-
-	/* prevent deadlocks */
-	sbp2_unblock(tgt);
-
-	list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
-		sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun));
-		if (sdev) {
-			scsi_remove_device(sdev);
-			scsi_device_put(sdev);
-		}
-		if (lu->login_id != INVALID_LOGIN_ID) {
-			int generation, node_id;
-			/*
-			 * tgt->node_id may be obsolete here if we failed
-			 * during initial login or after a bus reset where
-			 * the topology changed.
-			 */
-			generation = device->generation;
-			smp_rmb(); /* node_id vs. generation */
-			node_id    = device->node_id;
-			sbp2_send_management_orb(lu, node_id, generation,
-						 SBP2_LOGOUT_REQUEST,
-						 lu->login_id, NULL);
-		}
-		fw_core_remove_address_handler(&lu->address_handler);
-		list_del(&lu->link);
-		kfree(lu);
-	}
-	scsi_remove_host(shost);
-	fw_notify("released %s, target %d:0:0\n", tgt->bus_id, shost->host_no);
-
-	fw_unit_put(tgt->unit);
-	scsi_host_put(shost);
-	fw_device_put(device);
-}
-
-static void sbp2_target_get(struct sbp2_target *tgt)
-{
-	kref_get(&tgt->kref);
-}
-
-static void sbp2_target_put(struct sbp2_target *tgt)
-{
-	kref_put(&tgt->kref, sbp2_release_target);
-}
-
-/*
- * Always get the target's kref when scheduling work on one its units.
- * Each workqueue job is responsible to call sbp2_target_put() upon return.
- */
-static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
-{
-	sbp2_target_get(lu->tgt);
-	if (!queue_delayed_work(fw_workqueue, &lu->work, delay))
-		sbp2_target_put(lu->tgt);
-}
-
 /*
  * Write retransmit retry values into the BUSY_TIMEOUT register.
  * - The single-phase retry protocol is supported by all SBP-2 devices, but the
@@ -877,7 +816,7 @@
 	int generation, node_id, local_node_id;
 
 	if (fw_device_is_shutdown(device))
-		goto out;
+		return;
 
 	generation    = device->generation;
 	smp_rmb();    /* node IDs must not be older than generation */
@@ -899,7 +838,7 @@
 			/* Let any waiting I/O fail from now on. */
 			sbp2_unblock(lu->tgt);
 		}
-		goto out;
+		return;
 	}
 
 	tgt->node_id	  = node_id;
@@ -925,7 +864,8 @@
 	if (lu->has_sdev) {
 		sbp2_cancel_orbs(lu);
 		sbp2_conditionally_unblock(lu);
-		goto out;
+
+		return;
 	}
 
 	if (lu->tgt->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY)
@@ -957,7 +897,8 @@
 	lu->has_sdev = true;
 	scsi_device_put(sdev);
 	sbp2_allow_block(lu);
-	goto out;
+
+	return;
 
  out_logout_login:
 	smp_rmb(); /* generation may have changed */
@@ -971,8 +912,57 @@
 	 * lu->work already.  Reset the work from reconnect to login.
 	 */
 	PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
- out:
-	sbp2_target_put(tgt);
+}
+
+static void sbp2_reconnect(struct work_struct *work)
+{
+	struct sbp2_logical_unit *lu =
+		container_of(work, struct sbp2_logical_unit, work.work);
+	struct sbp2_target *tgt = lu->tgt;
+	struct fw_device *device = target_device(tgt);
+	int generation, node_id, local_node_id;
+
+	if (fw_device_is_shutdown(device))
+		return;
+
+	generation    = device->generation;
+	smp_rmb();    /* node IDs must not be older than generation */
+	node_id       = device->node_id;
+	local_node_id = device->card->node_id;
+
+	if (sbp2_send_management_orb(lu, node_id, generation,
+				     SBP2_RECONNECT_REQUEST,
+				     lu->login_id, NULL) < 0) {
+		/*
+		 * If reconnect was impossible even though we are in the
+		 * current generation, fall back and try to log in again.
+		 *
+		 * We could check for "Function rejected" status, but
+		 * looking at the bus generation as simpler and more general.
+		 */
+		smp_rmb(); /* get current card generation */
+		if (generation == device->card->generation ||
+		    lu->retries++ >= 5) {
+			fw_error("%s: failed to reconnect\n", tgt->bus_id);
+			lu->retries = 0;
+			PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
+		}
+		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
+
+		return;
+	}
+
+	tgt->node_id      = node_id;
+	tgt->address_high = local_node_id << 16;
+	smp_wmb();	  /* node IDs must not be older than generation */
+	lu->generation	  = generation;
+
+	fw_notify("%s: reconnected to LUN %04x (%d retries)\n",
+		  tgt->bus_id, lu->lun, lu->retries);
+
+	sbp2_agent_reset(lu);
+	sbp2_cancel_orbs(lu);
+	sbp2_conditionally_unblock(lu);
 }
 
 static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
@@ -1120,6 +1110,7 @@
 }
 
 static struct scsi_host_template scsi_driver_template;
+static int sbp2_remove(struct device *dev);
 
 static int sbp2_probe(struct device *dev)
 {
@@ -1141,7 +1132,6 @@
 	tgt = (struct sbp2_target *)shost->hostdata;
 	dev_set_drvdata(&unit->device, tgt);
 	tgt->unit = unit;
-	kref_init(&tgt->kref);
 	INIT_LIST_HEAD(&tgt->lu_list);
 	tgt->bus_id = dev_name(&unit->device);
 	tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
@@ -1154,9 +1144,6 @@
 	if (scsi_add_host(shost, &unit->device) < 0)
 		goto fail_shost_put;
 
-	fw_device_get(device);
-	fw_unit_get(unit);
-
 	/* implicit directory ID */
 	tgt->directory_id = ((unit->directory - device->config_rom) * 4
 			     + CSR_CONFIG_ROM) & 0xffffff;
@@ -1166,7 +1153,7 @@
 
 	if (sbp2_scan_unit_dir(tgt, unit->directory, &model,
 			       &firmware_revision) < 0)
-		goto fail_tgt_put;
+		goto fail_remove;
 
 	sbp2_clamp_management_orb_timeout(tgt);
 	sbp2_init_workarounds(tgt, model, firmware_revision);
@@ -1177,16 +1164,17 @@
 	 * specifies the max payload size as 2 ^ (max_payload + 2), so
 	 * if we set this to max_speed + 7, we get the right value.
 	 */
-	tgt->max_payload = min(device->max_speed + 7, 10U);
-	tgt->max_payload = min(tgt->max_payload, device->card->max_receive - 1);
+	tgt->max_payload = min3(device->max_speed + 7, 10U,
+				device->card->max_receive - 1);
 
 	/* Do the login in a workqueue so we can easily reschedule retries. */
 	list_for_each_entry(lu, &tgt->lu_list, link)
 		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
+
 	return 0;
 
- fail_tgt_put:
-	sbp2_target_put(tgt);
+ fail_remove:
+	sbp2_remove(dev);
 	return -ENOMEM;
 
  fail_shost_put:
@@ -1194,71 +1182,6 @@
 	return -ENOMEM;
 }
 
-static int sbp2_remove(struct device *dev)
-{
-	struct fw_unit *unit = fw_unit(dev);
-	struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
-	struct sbp2_logical_unit *lu;
-
-	list_for_each_entry(lu, &tgt->lu_list, link)
-		cancel_delayed_work_sync(&lu->work);
-
-	sbp2_target_put(tgt);
-	return 0;
-}
-
-static void sbp2_reconnect(struct work_struct *work)
-{
-	struct sbp2_logical_unit *lu =
-		container_of(work, struct sbp2_logical_unit, work.work);
-	struct sbp2_target *tgt = lu->tgt;
-	struct fw_device *device = target_device(tgt);
-	int generation, node_id, local_node_id;
-
-	if (fw_device_is_shutdown(device))
-		goto out;
-
-	generation    = device->generation;
-	smp_rmb();    /* node IDs must not be older than generation */
-	node_id       = device->node_id;
-	local_node_id = device->card->node_id;
-
-	if (sbp2_send_management_orb(lu, node_id, generation,
-				     SBP2_RECONNECT_REQUEST,
-				     lu->login_id, NULL) < 0) {
-		/*
-		 * If reconnect was impossible even though we are in the
-		 * current generation, fall back and try to log in again.
-		 *
-		 * We could check for "Function rejected" status, but
-		 * looking at the bus generation as simpler and more general.
-		 */
-		smp_rmb(); /* get current card generation */
-		if (generation == device->card->generation ||
-		    lu->retries++ >= 5) {
-			fw_error("%s: failed to reconnect\n", tgt->bus_id);
-			lu->retries = 0;
-			PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
-		}
-		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
-		goto out;
-	}
-
-	tgt->node_id      = node_id;
-	tgt->address_high = local_node_id << 16;
-	smp_wmb();	  /* node IDs must not be older than generation */
-	lu->generation	  = generation;
-
-	fw_notify("%s: reconnected to LUN %04x (%d retries)\n",
-		  tgt->bus_id, lu->lun, lu->retries);
-
-	sbp2_agent_reset(lu);
-	sbp2_cancel_orbs(lu);
-	sbp2_conditionally_unblock(lu);
- out:
-	sbp2_target_put(tgt);
-}
-
 static void sbp2_update(struct fw_unit *unit)
 {
 	struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
@@ -1277,6 +1200,51 @@
 	}
 }
 
+static int sbp2_remove(struct device *dev)
+{
+	struct fw_unit *unit = fw_unit(dev);
+	struct fw_device *device = fw_parent_device(unit);
+	struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
+	struct sbp2_logical_unit *lu, *next;
+	struct Scsi_Host *shost =
+		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
+	struct scsi_device *sdev;
+
+	/* prevent deadlocks */
+	sbp2_unblock(tgt);
+
+	list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
+		cancel_delayed_work_sync(&lu->work);
+		sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun));
+		if (sdev) {
+			scsi_remove_device(sdev);
+			scsi_device_put(sdev);
+		}
+		if (lu->login_id != INVALID_LOGIN_ID) {
+			int generation, node_id;
+			/*
+			 * tgt->node_id may be obsolete here if we failed
+			 * during initial login or after a bus reset where
+			 * the topology changed.
+			 */
+			generation = device->generation;
+			smp_rmb(); /* node_id vs. generation */
+			node_id    = device->node_id;
+			sbp2_send_management_orb(lu, node_id, generation,
+						 SBP2_LOGOUT_REQUEST,
+						 lu->login_id, NULL);
+		}
+		fw_core_remove_address_handler(&lu->address_handler);
+		list_del(&lu->link);
+		kfree(lu);
+	}
+	scsi_remove_host(shost);
+	fw_notify("released %s, target %d:0:0\n", tgt->bus_id, shost->host_no);
+
+	scsi_host_put(shost);
+	return 0;
+}
+
 #define SBP2_UNIT_SPEC_ID_ENTRY	0x0000609e
 #define SBP2_SW_VERSION_ENTRY	0x00010483
 
diff -druN linux-libre-3.1-gnu/drivers/firmware/dmi_scan.c linux-libre-3.2-gnu/drivers/firmware/dmi_scan.c
--- linux-libre-3.1-gnu/drivers/firmware/dmi_scan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/firmware/dmi_scan.c	2012-01-04 18:55:44.000000000 -0500
@@ -585,14 +585,12 @@
 }
 
 /**
- *	dmi_name_in_vendors - Check if string is anywhere in the DMI vendor information.
+ *	dmi_name_in_vendors - Check if string is in the DMI system or board vendor name
  *	@str: 	Case sensitive Name
  */
 int dmi_name_in_vendors(const char *str)
 {
-	static int fields[] = { DMI_BIOS_VENDOR, DMI_BIOS_VERSION, DMI_SYS_VENDOR,
-				DMI_PRODUCT_NAME, DMI_PRODUCT_VERSION, DMI_BOARD_VENDOR,
-				DMI_BOARD_NAME, DMI_BOARD_VERSION, DMI_NONE };
+	static int fields[] = { DMI_SYS_VENDOR, DMI_BOARD_VENDOR, DMI_NONE };
 	int i;
 	for (i = 0; fields[i] != DMI_NONE; i++) {
 		int f = fields[i];
diff -druN linux-libre-3.1-gnu/drivers/firmware/edd.c linux-libre-3.2-gnu/drivers/firmware/edd.c
--- linux-libre-3.1-gnu/drivers/firmware/edd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/firmware/edd.c	2012-01-04 18:55:44.000000000 -0500
@@ -151,7 +151,8 @@
 		p += scnprintf(p, left, "\tbase_address: %x\n",
 			     info->params.interface_path.isa.base_address);
 	} else if (!strncmp(info->params.host_bus_type, "PCIX", 4) ||
-		   !strncmp(info->params.host_bus_type, "PCI", 3)) {
+		   !strncmp(info->params.host_bus_type, "PCI", 3) ||
+		   !strncmp(info->params.host_bus_type, "XPRS", 4)) {
 		p += scnprintf(p, left,
 			     "\t%02x:%02x.%d  channel: %u\n",
 			     info->params.interface_path.pci.bus,
@@ -159,7 +160,6 @@
 			     info->params.interface_path.pci.function,
 			     info->params.interface_path.pci.channel);
 	} else if (!strncmp(info->params.host_bus_type, "IBND", 4) ||
-		   !strncmp(info->params.host_bus_type, "XPRS", 4) ||
 		   !strncmp(info->params.host_bus_type, "HTPT", 4)) {
 		p += scnprintf(p, left,
 			     "\tTBD: %llx\n",
@@ -668,7 +668,7 @@
 {
 	struct edd_info *info = edd_dev_get_info(edev);
 
-	if (edd_dev_is_type(edev, "PCI")) {
+	if (edd_dev_is_type(edev, "PCI") || edd_dev_is_type(edev, "XPRS")) {
 		return pci_get_bus_and_slot(info->params.interface_path.pci.bus,
 				     PCI_DEVFN(info->params.interface_path.pci.slot,
 					       info->params.interface_path.pci.
diff -druN linux-libre-3.1-gnu/drivers/firmware/efivars.c linux-libre-3.2-gnu/drivers/firmware/efivars.c
--- linux-libre-3.1-gnu/drivers/firmware/efivars.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/firmware/efivars.c	2012-01-04 18:55:44.000000000 -0500
@@ -457,7 +457,8 @@
 }
 
 static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
-			       struct timespec *timespec, struct pstore_info *psi)
+			       struct timespec *timespec,
+			       char **buf, struct pstore_info *psi)
 {
 	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
 	struct efivars *efivars = psi->data;
@@ -478,7 +479,11 @@
 				timespec->tv_nsec = 0;
 				get_var_data_locked(efivars, &efivars->walk_entry->var);
 				size = efivars->walk_entry->var.DataSize;
-				memcpy(psi->buf, efivars->walk_entry->var.Data, size);
+				*buf = kmalloc(size, GFP_KERNEL);
+				if (*buf == NULL)
+					return -ENOMEM;
+				memcpy(*buf, efivars->walk_entry->var.Data,
+				       size);
 				efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
 					           struct efivar_entry, list);
 				return size;
@@ -490,8 +495,8 @@
 	return 0;
 }
 
-static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
-			    size_t size, struct pstore_info *psi)
+static int efi_pstore_write(enum pstore_type_id type, u64 *id,
+		unsigned int part, size_t size, struct pstore_info *psi)
 {
 	char name[DUMP_NAME_LEN];
 	char stub_name[DUMP_NAME_LEN];
@@ -499,7 +504,7 @@
 	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
 	struct efivars *efivars = psi->data;
 	struct efivar_entry *entry, *found = NULL;
-	int i;
+	int i, ret = 0;
 
 	sprintf(stub_name, "dump-type%u-%u-", type, part);
 	sprintf(name, "%s%lu", stub_name, get_seconds());
@@ -548,18 +553,19 @@
 		efivar_unregister(found);
 
 	if (size)
-		efivar_create_sysfs_entry(efivars,
+		ret = efivar_create_sysfs_entry(efivars,
 					  utf16_strsize(efi_name,
 							DUMP_NAME_LEN * 2),
 					  efi_name, &vendor);
 
-	return part;
+	*id = part;
+	return ret;
 };
 
 static int efi_pstore_erase(enum pstore_type_id type, u64 id,
 			    struct pstore_info *psi)
 {
-	efi_pstore_write(type, id, 0, psi);
+	efi_pstore_write(type, &id, (unsigned int)id, 0, psi);
 
 	return 0;
 }
@@ -575,13 +581,14 @@
 }
 
 static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
-			       struct timespec *time, struct pstore_info *psi)
+			       struct timespec *timespec,
+			       char **buf, struct pstore_info *psi)
 {
 	return -1;
 }
 
-static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
-			    size_t size, struct pstore_info *psi)
+static int efi_pstore_write(enum pstore_type_id type, u64 *id,
+		unsigned int part, size_t size, struct pstore_info *psi)
 {
 	return 0;
 }
@@ -978,7 +985,7 @@
 	if (efivars->efi_pstore_info.buf) {
 		efivars->efi_pstore_info.bufsize = 1024;
 		efivars->efi_pstore_info.data = efivars;
-		mutex_init(&efivars->efi_pstore_info.buf_mutex);
+		spin_lock_init(&efivars->efi_pstore_info.buf_lock);
 		pstore_register(&efivars->efi_pstore_info);
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/firmware/google/gsmi.c linux-libre-3.2-gnu/drivers/firmware/google/gsmi.c
--- linux-libre-3.1-gnu/drivers/firmware/google/gsmi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/firmware/google/gsmi.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/kdebug.h>
 #include <linux/reboot.h>
 #include <linux/efi.h>
+#include <linux/module.h>
 
 #define GSMI_SHUTDOWN_CLEAN	0	/* Clean Shutdown */
 /* TODO(mikew@google.com): Tie in HARDLOCKUP_DETECTOR with NMIWDT */
diff -druN linux-libre-3.1-gnu/drivers/firmware/iscsi_ibft.c linux-libre-3.2-gnu/drivers/firmware/iscsi_ibft.c
--- linux-libre-3.1-gnu/drivers/firmware/iscsi_ibft.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/firmware/iscsi_ibft.c	2012-01-04 18:55:44.000000000 -0500
@@ -746,6 +746,37 @@
 	ibft_cleanup();
 }
 
+#ifdef CONFIG_ACPI
+static const struct {
+	char *sign;
+} ibft_signs[] = {
+	/*
+	 * One spec says "IBFT", the other says "iBFT". We have to check
+	 * for both.
+	 */
+	{ ACPI_SIG_IBFT },
+	{ "iBFT" },
+};
+
+static void __init acpi_find_ibft_region(void)
+{
+	int i;
+	struct acpi_table_header *table = NULL;
+
+	if (acpi_disabled)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(ibft_signs) && !ibft_addr; i++) {
+		acpi_get_table(ibft_signs[i].sign, 0, &table);
+		ibft_addr = (struct acpi_table_ibft *)table;
+	}
+}
+#else
+static void __init acpi_find_ibft_region(void)
+{
+}
+#endif
+
 /*
  * ibft_init() - creates sysfs tree entries for the iBFT data.
  */
@@ -753,9 +784,16 @@
 {
 	int rc = 0;
 
+	/*
+	   As on UEFI systems the setup_arch()/find_ibft_region()
+	   is called before ACPI tables are parsed and it only does
+	   legacy finding.
+	*/
+	if (!ibft_addr)
+		acpi_find_ibft_region();
+
 	if (ibft_addr) {
-		printk(KERN_INFO "iBFT detected at 0x%llx.\n",
-		       (u64)isa_virt_to_bus(ibft_addr));
+		pr_info("iBFT detected.\n");
 
 		rc = ibft_check_device();
 		if (rc)
diff -druN linux-libre-3.1-gnu/drivers/firmware/iscsi_ibft_find.c linux-libre-3.2-gnu/drivers/firmware/iscsi_ibft_find.c
--- linux-libre-3.1-gnu/drivers/firmware/iscsi_ibft_find.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/firmware/iscsi_ibft_find.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,13 +45,6 @@
 static const struct {
 	char *sign;
 } ibft_signs[] = {
-#ifdef CONFIG_ACPI
-	/*
-	 * One spec says "IBFT", the other says "iBFT". We have to check
-	 * for both.
-	 */
-	{ ACPI_SIG_IBFT },
-#endif
 	{ "iBFT" },
 	{ "BIFT" },	/* Broadcom iSCSI Offload */
 };
@@ -62,14 +55,6 @@
 #define VGA_MEM 0xA0000 /* VGA buffer */
 #define VGA_SIZE 0x20000 /* 128kB */
 
-#ifdef CONFIG_ACPI
-static int __init acpi_find_ibft(struct acpi_table_header *header)
-{
-	ibft_addr = (struct acpi_table_ibft *)header;
-	return 0;
-}
-#endif /* CONFIG_ACPI */
-
 static int __init find_ibft_in_mem(void)
 {
 	unsigned long pos;
@@ -94,6 +79,7 @@
 				 * the table cannot be valid. */
 				if (pos + len <= (IBFT_END-1)) {
 					ibft_addr = (struct acpi_table_ibft *)virt;
+					pr_info("iBFT found at 0x%lx.\n", pos);
 					goto done;
 				}
 			}
@@ -108,20 +94,12 @@
  */
 unsigned long __init find_ibft_region(unsigned long *sizep)
 {
-#ifdef CONFIG_ACPI
-	int i;
-#endif
 	ibft_addr = NULL;
 
-#ifdef CONFIG_ACPI
-	for (i = 0; i < ARRAY_SIZE(ibft_signs) && !ibft_addr; i++)
-		acpi_table_parse(ibft_signs[i].sign, acpi_find_ibft);
-#endif /* CONFIG_ACPI */
-
 	/* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will
 	 * only use ACPI for this */
 
-	if (!ibft_addr && !efi_enabled)
+	if (!efi_enabled)
 		find_ibft_in_mem();
 
 	if (ibft_addr) {
diff -druN linux-libre-3.1-gnu/drivers/firmware/sigma.c linux-libre-3.2-gnu/drivers/firmware/sigma.c
--- linux-libre-3.1-gnu/drivers/firmware/sigma.c	2012-03-19 22:12:36.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/firmware/sigma.c	2012-03-19 22:16:14.000000000 -0400
@@ -14,13 +14,34 @@
 #include <linux/module.h>
 #include <linux/sigma.h>
 
-/* Return: 0==OK, <0==error, =1 ==no more actions */
+static size_t sigma_action_size(struct sigma_action *sa)
+{
+	size_t payload = 0;
+
+	switch (sa->instr) {
+	case SIGMA_ACTION_WRITEXBYTES:
+	case SIGMA_ACTION_WRITESINGLE:
+	case SIGMA_ACTION_WRITESAFELOAD:
+		payload = sigma_action_len(sa);
+		break;
+	default:
+		break;
+	}
+
+	payload = ALIGN(payload, 2);
+
+	return payload + sizeof(struct sigma_action);
+}
+
+/*
+ * Returns a negative error value in case of an error, 0 if processing of
+ * the firmware should be stopped after this action, 1 otherwise.
+ */
 static int
-process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw)
+process_sigma_action(struct i2c_client *client, struct sigma_action *sa)
 {
-	struct sigma_action *sa = (void *)(ssfw->fw->data + ssfw->pos);
 	size_t len = sigma_action_len(sa);
-	int ret = 0;
+	int ret;
 
 	pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,
 		sa->instr, sa->addr, len);
@@ -29,44 +50,50 @@
 	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;
-
+		return 0;
 	default:
 		return -EINVAL;
 	}
 
-	/* when arrive here ret=0 or sent data */
-	ssfw->pos += sigma_action_size(sa, len);
-	return ssfw->pos == ssfw->fw->size;
+	return 1;
 }
 
 static int
 process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw)
 {
-	pr_debug("%s: processing %p\n", __func__, ssfw);
+	struct sigma_action *sa;
+	size_t size;
+	int ret;
+
+	while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) {
+		sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos);
+
+		size = sigma_action_size(sa);
+		ssfw->pos += size;
+		if (ssfw->pos > ssfw->fw->size || size == 0)
+			break;
+
+		ret = process_sigma_action(client, sa);
 
-	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)
+
+		if (ret <= 0)
 			return ret;
 	}
+
+	if (ssfw->pos != ssfw->fw->size)
+		return -EINVAL;
+
+	return 0;
 }
 
 int process_sigma_firmware(struct i2c_client *client, const char *name)
@@ -89,16 +116,24 @@
 
 	/* then verify the header */
 	ret = -EINVAL;
-	if (fw->size < sizeof(*ssfw_head))
+
+	/*
+	 * Reject too small or unreasonable large files. The upper limit has been
+	 * chosen a bit arbitrarily, but it should be enough for all practical
+	 * purposes and having the limit makes it easier to avoid integer
+	 * overflows later in the loading process.
+	 */
+	if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000)
 		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);
+	crc = crc32(0, fw->data + sizeof(*ssfw_head),
+			fw->size - sizeof(*ssfw_head));
 	pr_debug("%s: crc=%x\n", __func__, crc);
-	if (crc != ssfw_head->crc)
+	if (crc != le32_to_cpu(ssfw_head->crc))
 		goto done;
 
 	ssfw.pos = sizeof(*ssfw_head);
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-74x164.c linux-libre-3.2-gnu/drivers/gpio/gpio-74x164.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-74x164.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-74x164.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/spi/74x164.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 struct gen_74x164_chip {
 	struct spi_device	*spi;
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-da9052.c linux-libre-3.2-gnu/drivers/gpio/gpio-da9052.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-da9052.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-da9052.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,7 +22,6 @@
 #include <linux/mfd/da9052/da9052.h>
 #include <linux/mfd/da9052/reg.h>
 #include <linux/mfd/da9052/pdata.h>
-#include <linux/mfd/da9052/gpio.h>
 
 #define DA9052_INPUT				1
 #define DA9052_OUTPUT_OPENDRAIN		2
@@ -43,6 +42,9 @@
 #define DA9052_GPIO_MASK_UPPER_NIBBLE		0xF0
 #define DA9052_GPIO_MASK_LOWER_NIBBLE		0x0F
 #define DA9052_GPIO_NIBBLE_SHIFT		4
+#define DA9052_IRQ_GPI0			16
+#define DA9052_GPIO_ODD_SHIFT			7
+#define DA9052_GPIO_EVEN_SHIFT			3
 
 struct da9052_gpio {
 	struct da9052 *da9052;
@@ -104,33 +106,26 @@
 static void da9052_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
 {
 	struct da9052_gpio *gpio = to_da9052_gpio(gc);
-	unsigned char register_value = 0;
 	int ret;
 
 	if (da9052_gpio_port_odd(offset)) {
-		if (value) {
-			register_value = DA9052_GPIO_ODD_PORT_MODE;
 			ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
 						DA9052_GPIO_0_1_REG,
 						DA9052_GPIO_ODD_PORT_MODE,
-						register_value);
+						value << DA9052_GPIO_ODD_SHIFT);
 			if (ret != 0)
 				dev_err(gpio->da9052->dev,
 					"Failed to updated gpio odd reg,%d",
 					ret);
-		}
 	} else {
-		if (value) {
-			register_value = DA9052_GPIO_EVEN_PORT_MODE;
 			ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
 						DA9052_GPIO_0_1_REG,
 						DA9052_GPIO_EVEN_PORT_MODE,
-						register_value);
+						value << DA9052_GPIO_EVEN_SHIFT);
 			if (ret != 0)
 				dev_err(gpio->da9052->dev,
 					"Failed to updated gpio even reg,%d",
 					ret);
-		}
 	}
 }
 
@@ -201,9 +196,9 @@
 	.direction_input = da9052_gpio_direction_input,
 	.direction_output = da9052_gpio_direction_output,
 	.to_irq = da9052_gpio_to_irq,
-	.can_sleep = 1;
-	.ngpio = 16;
-	.base = -1;
+	.can_sleep = 1,
+	.ngpio = 16,
+	.base = -1,
 };
 
 static int __devinit da9052_gpio_probe(struct platform_device *pdev)
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-davinci.c linux-libre-3.2-gnu/drivers/gpio/gpio-davinci.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-davinci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-davinci.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,455 @@
+/*
+ * TI DaVinci GPIO Support
+ *
+ * Copyright (c) 2006-2007 David Brownell
+ * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.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/gpio.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <asm/mach/irq.h>
+
+struct davinci_gpio_regs {
+	u32	dir;
+	u32	out_data;
+	u32	set_data;
+	u32	clr_data;
+	u32	in_data;
+	u32	set_rising;
+	u32	clr_rising;
+	u32	set_falling;
+	u32	clr_falling;
+	u32	intstat;
+};
+
+#define chip2controller(chip)	\
+	container_of(chip, struct davinci_gpio_controller, chip)
+
+static struct davinci_gpio_controller chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)];
+static void __iomem *gpio_base;
+
+static struct davinci_gpio_regs __iomem __init *gpio2regs(unsigned gpio)
+{
+	void __iomem *ptr;
+
+	if (gpio < 32 * 1)
+		ptr = gpio_base + 0x10;
+	else if (gpio < 32 * 2)
+		ptr = gpio_base + 0x38;
+	else if (gpio < 32 * 3)
+		ptr = gpio_base + 0x60;
+	else if (gpio < 32 * 4)
+		ptr = gpio_base + 0x88;
+	else if (gpio < 32 * 5)
+		ptr = gpio_base + 0xb0;
+	else
+		ptr = NULL;
+	return ptr;
+}
+
+static inline struct davinci_gpio_regs __iomem *irq2regs(int irq)
+{
+	struct davinci_gpio_regs __iomem *g;
+
+	g = (__force struct davinci_gpio_regs __iomem *)irq_get_chip_data(irq);
+
+	return g;
+}
+
+static int __init davinci_gpio_irq_setup(void);
+
+/*--------------------------------------------------------------------------*/
+
+/* board setup code *MUST* setup pinmux and enable the GPIO clock. */
+static inline int __davinci_direction(struct gpio_chip *chip,
+			unsigned offset, bool out, int value)
+{
+	struct davinci_gpio_controller *d = chip2controller(chip);
+	struct davinci_gpio_regs __iomem *g = d->regs;
+	unsigned long flags;
+	u32 temp;
+	u32 mask = 1 << offset;
+
+	spin_lock_irqsave(&d->lock, flags);
+	temp = __raw_readl(&g->dir);
+	if (out) {
+		temp &= ~mask;
+		__raw_writel(mask, value ? &g->set_data : &g->clr_data);
+	} else {
+		temp |= mask;
+	}
+	__raw_writel(temp, &g->dir);
+	spin_unlock_irqrestore(&d->lock, flags);
+
+	return 0;
+}
+
+static int davinci_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+	return __davinci_direction(chip, offset, false, 0);
+}
+
+static int
+davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value)
+{
+	return __davinci_direction(chip, offset, true, value);
+}
+
+/*
+ * Read the pin's value (works even if it's set up as output);
+ * returns zero/nonzero.
+ *
+ * Note that changes are synched to the GPIO clock, so reading values back
+ * right after you've set them may give old values.
+ */
+static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct davinci_gpio_controller *d = chip2controller(chip);
+	struct davinci_gpio_regs __iomem *g = d->regs;
+
+	return (1 << offset) & __raw_readl(&g->in_data);
+}
+
+/*
+ * Assuming the pin is muxed as a gpio output, set its output value.
+ */
+static void
+davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct davinci_gpio_controller *d = chip2controller(chip);
+	struct davinci_gpio_regs __iomem *g = d->regs;
+
+	__raw_writel((1 << offset), value ? &g->set_data : &g->clr_data);
+}
+
+static int __init davinci_gpio_setup(void)
+{
+	int i, base;
+	unsigned ngpio;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+	struct davinci_gpio_regs *regs;
+
+	if (soc_info->gpio_type != GPIO_TYPE_DAVINCI)
+		return 0;
+
+	/*
+	 * The gpio banks conceptually expose a segmented bitmap,
+	 * and "ngpio" is one more than the largest zero-based
+	 * bit index that's valid.
+	 */
+	ngpio = soc_info->gpio_num;
+	if (ngpio == 0) {
+		pr_err("GPIO setup:  how many GPIOs?\n");
+		return -EINVAL;
+	}
+
+	if (WARN_ON(DAVINCI_N_GPIO < ngpio))
+		ngpio = DAVINCI_N_GPIO;
+
+	gpio_base = ioremap(soc_info->gpio_base, SZ_4K);
+	if (WARN_ON(!gpio_base))
+		return -ENOMEM;
+
+	for (i = 0, base = 0; base < ngpio; i++, base += 32) {
+		chips[i].chip.label = "DaVinci";
+
+		chips[i].chip.direction_input = davinci_direction_in;
+		chips[i].chip.get = davinci_gpio_get;
+		chips[i].chip.direction_output = davinci_direction_out;
+		chips[i].chip.set = davinci_gpio_set;
+
+		chips[i].chip.base = base;
+		chips[i].chip.ngpio = ngpio - base;
+		if (chips[i].chip.ngpio > 32)
+			chips[i].chip.ngpio = 32;
+
+		spin_lock_init(&chips[i].lock);
+
+		regs = gpio2regs(base);
+		chips[i].regs = regs;
+		chips[i].set_data = &regs->set_data;
+		chips[i].clr_data = &regs->clr_data;
+		chips[i].in_data = &regs->in_data;
+
+		gpiochip_add(&chips[i].chip);
+	}
+
+	soc_info->gpio_ctlrs = chips;
+	soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32);
+
+	davinci_gpio_irq_setup();
+	return 0;
+}
+pure_initcall(davinci_gpio_setup);
+
+/*--------------------------------------------------------------------------*/
+/*
+ * We expect irqs will normally be set up as input pins, but they can also be
+ * used as output pins ... which is convenient for testing.
+ *
+ * NOTE:  The first few GPIOs also have direct INTC hookups in addition
+ * to their GPIOBNK0 irq, with a bit less overhead.
+ *
+ * All those INTC hookups (direct, plus several IRQ banks) can also
+ * serve as EDMA event triggers.
+ */
+
+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_handler_data(d);
+
+	__raw_writel(mask, &g->clr_falling);
+	__raw_writel(mask, &g->clr_rising);
+}
+
+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_handler_data(d);
+	unsigned status = irqd_get_trigger_type(d);
+
+	status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
+	if (!status)
+		status = IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
+
+	if (status & IRQ_TYPE_EDGE_FALLING)
+		__raw_writel(mask, &g->set_falling);
+	if (status & IRQ_TYPE_EDGE_RISING)
+		__raw_writel(mask, &g->set_rising);
+}
+
+static int gpio_irq_type(struct irq_data *d, unsigned trigger)
+{
+	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+		return -EINVAL;
+
+	return 0;
+}
+
+static struct irq_chip gpio_irqchip = {
+	.name		= "GPIO",
+	.irq_enable	= gpio_irq_enable,
+	.irq_disable	= gpio_irq_disable,
+	.irq_set_type	= gpio_irq_type,
+	.flags		= IRQCHIP_SET_TYPE_MASKED,
+};
+
+static void
+gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+	struct davinci_gpio_regs __iomem *g;
+	u32 mask = 0xffff;
+	struct davinci_gpio_controller *d;
+
+	d = (struct davinci_gpio_controller *)irq_desc_get_handler_data(desc);
+	g = (struct davinci_gpio_regs __iomem *)d->regs;
+
+	/* we only care about one bank */
+	if (irq & 1)
+		mask <<= 16;
+
+	/* temporarily mask (level sensitive) parent IRQ */
+	desc->irq_data.chip->irq_mask(&desc->irq_data);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
+	while (1) {
+		u32		status;
+		int		n;
+		int		res;
+
+		/* ack any irqs */
+		status = __raw_readl(&g->intstat) & mask;
+		if (!status)
+			break;
+		__raw_writel(status, &g->intstat);
+
+		/* now demux them to the right lowlevel handler */
+		n = d->irq_base;
+		if (irq & 1) {
+			n += 16;
+			status >>= 16;
+		}
+
+		while (status) {
+			res = ffs(status);
+			n += res;
+			generic_handle_irq(n - 1);
+			status >>= res;
+		}
+	}
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
+	/* now it may re-trigger */
+}
+
+static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset)
+{
+	struct davinci_gpio_controller *d = chip2controller(chip);
+
+	if (d->irq_base >= 0)
+		return d->irq_base + offset;
+	else
+		return -ENODEV;
+}
+
+static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)
+{
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+
+	/* NOTE:  we assume for now that only irqs in the first gpio_chip
+	 * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs).
+	 */
+	if (offset < soc_info->gpio_unbanked)
+		return soc_info->gpio_irq + offset;
+	else
+		return -ENODEV;
+}
+
+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_handler_data(d);
+
+	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+		return -EINVAL;
+
+	__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;
+}
+
+/*
+ * NOTE:  for suspend/resume, probably best to make a platform_device with
+ * suspend_late/resume_resume calls hooking into results of the set_wake()
+ * calls ... so if no gpios are wakeup events the clock can be disabled,
+ * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0
+ * (dm6446) can be set appropriately for GPIOV33 pins.
+ */
+
+static int __init davinci_gpio_irq_setup(void)
+{
+	unsigned	gpio, irq, bank;
+	struct clk	*clk;
+	u32		binten = 0;
+	unsigned	ngpio, bank_irq;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+	struct davinci_gpio_regs	__iomem *g;
+
+	ngpio = soc_info->gpio_num;
+
+	bank_irq = soc_info->gpio_irq;
+	if (bank_irq == 0) {
+		printk(KERN_ERR "Don't know first GPIO bank IRQ.\n");
+		return -EINVAL;
+	}
+
+	clk = clk_get(NULL, "gpio");
+	if (IS_ERR(clk)) {
+		printk(KERN_ERR "Error %ld getting gpio clock?\n",
+		       PTR_ERR(clk));
+		return PTR_ERR(clk);
+	}
+	clk_enable(clk);
+
+	/* Arrange gpio_to_irq() support, handling either direct IRQs or
+	 * banked IRQs.  Having GPIOs in the first GPIO bank use direct
+	 * IRQs, while the others use banked IRQs, would need some setup
+	 * tweaks to recognize hardware which can do that.
+	 */
+	for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) {
+		chips[bank].chip.to_irq = gpio_to_irq_banked;
+		chips[bank].irq_base = soc_info->gpio_unbanked
+			? -EINVAL
+			: (soc_info->intc_irq_num + gpio);
+	}
+
+	/*
+	 * AINTC can handle direct/unbanked IRQs for GPIOs, with the GPIO
+	 * controller only handling trigger modes.  We currently assume no
+	 * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs.
+	 */
+	if (soc_info->gpio_unbanked) {
+		static struct irq_chip gpio_irqchip_unbanked;
+
+		/* pass "bank 0" GPIO IRQs to AINTC */
+		chips[0].chip.to_irq = gpio_to_irq_unbanked;
+		binten = BIT(0);
+
+		/* AINTC handles mask/unmask; GPIO handles triggering */
+		irq = bank_irq;
+		gpio_irqchip_unbanked = *irq_get_chip(irq);
+		gpio_irqchip_unbanked.name = "GPIO-AINTC";
+		gpio_irqchip_unbanked.irq_set_type = gpio_irq_type_unbanked;
+
+		/* default trigger: both edges */
+		g = gpio2regs(0);
+		__raw_writel(~0, &g->set_falling);
+		__raw_writel(~0, &g->set_rising);
+
+		/* set the direct IRQs up to use that irqchip */
+		for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) {
+			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;
+	}
+
+	/*
+	 * Or, AINTC can handle IRQs for banks of 16 GPIO IRQs, which we
+	 * then chain through our own handler.
+	 */
+	for (gpio = 0, irq = gpio_to_irq(0), bank = 0;
+			gpio < ngpio;
+			bank++, bank_irq++) {
+		unsigned		i;
+
+		/* disabled by default, enabled only as needed */
+		g = gpio2regs(gpio);
+		__raw_writel(~0, &g->clr_falling);
+		__raw_writel(~0, &g->clr_rising);
+
+		/* set up all irqs in this bank */
+		irq_set_chained_handler(bank_irq, gpio_irq_handler);
+
+		/*
+		 * Each chip handles 32 gpios, and each irq bank consists of 16
+		 * gpio irqs. Pass the irq bank's corresponding controller to
+		 * the chained irq handler.
+		 */
+		irq_set_handler_data(bank_irq, &chips[gpio / 32]);
+
+		for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) {
+			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);
+		}
+
+		binten |= BIT(bank);
+	}
+
+done:
+	/* BINTEN -- per-bank interrupt enable. genirq would also let these
+	 * bits be set/cleared dynamically.
+	 */
+	__raw_writel(binten, gpio_base + 0x08);
+
+	printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
+
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-ep93xx.c linux-libre-3.2-gnu/drivers/gpio/gpio-ep93xx.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-ep93xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-ep93xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
@@ -23,6 +24,9 @@
 #include <linux/basic_mmio_gpio.h>
 
 #include <mach/hardware.h>
+#include <mach/gpio-ep93xx.h>
+
+#define irq_to_gpio(irq)	((irq) - gpio_to_irq(0))
 
 struct ep93xx_gpio {
 	void __iomem		*mmio_base;
@@ -307,6 +311,21 @@
 	return 0;
 }
 
+/*
+ * Map GPIO A0..A7  (0..7)  to irq 64..71,
+ *          B0..B7  (7..15) to irq 72..79, and
+ *          F0..F7 (16..24) to irq 80..87.
+ */
+static int ep93xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+
+	if (gpio > EP93XX_GPIO_LINE_MAX_IRQ)
+		return -EINVAL;
+
+	return 64 + gpio;
+}
+
 static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev,
 	void __iomem *mmio_base, struct ep93xx_gpio_bank *bank)
 {
@@ -321,8 +340,10 @@
 	bgc->gc.label = bank->label;
 	bgc->gc.base = bank->base;
 
-	if (bank->has_debounce)
+	if (bank->has_debounce) {
 		bgc->gc.set_debounce = ep93xx_gpio_set_debounce;
+		bgc->gc.to_irq = ep93xx_gpio_to_irq;
+	}
 
 	return gpiochip_add(&bgc->gc);
 }
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-exynos4.c linux-libre-3.2-gnu/drivers/gpio/gpio-exynos4.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-exynos4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-exynos4.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,385 +0,0 @@
-/*
- * EXYNOS4 - GPIOlib support
- *
- * 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/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>
-
-int s3c_gpio_setpull_exynos4(struct s3c_gpio_chip *chip,
-				unsigned int off, s3c_gpio_pull_t pull)
-{
-	if (pull == S3C_GPIO_PULL_UP)
-		pull = 3;
-
-	return s3c_gpio_setpull_updown(chip, off, pull);
-}
-
-s3c_gpio_pull_t s3c_gpio_getpull_exynos4(struct s3c_gpio_chip *chip,
-						unsigned int off)
-{
-	s3c_gpio_pull_t pull;
-
-	pull = s3c_gpio_getpull_updown(chip, off);
-	if (pull == 3)
-		pull = S3C_GPIO_PULL_UP;
-
-	return pull;
-}
-
-static struct s3c_gpio_cfg gpio_cfg = {
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_exynos4,
-	.get_pull	= s3c_gpio_getpull_exynos4,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_noint = {
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_exynos4,
-	.get_pull	= s3c_gpio_getpull_exynos4,
-};
-
-/*
- * 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-3.1-gnu/drivers/gpio/gpio-ks8695.c linux-libre-3.2-gnu/drivers/gpio/gpio-ks8695.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-ks8695.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-ks8695.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,319 @@
+/*
+ * arch/arm/mach-ks8695/gpio.c
+ *
+ * Copyright (C) 2006 Andrew Victor
+ * Updated to GPIOLIB, Copyright 2008 Simtec Electronics
+ *                     Daniel Silverstone <dsilvers@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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/gpio.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/mach/irq.h>
+
+#include <mach/regs-gpio.h>
+#include <mach/gpio-ks8695.h>
+
+/*
+ * Configure a GPIO line for either GPIO function, or its internal
+ * function (Interrupt, Timer, etc).
+ */
+static void ks8695_gpio_mode(unsigned int pin, short gpio)
+{
+	unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
+	unsigned long x, flags;
+
+	if (pin > KS8695_GPIO_5)	/* only GPIO 0..5 have internal functions */
+		return;
+
+	local_irq_save(flags);
+
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
+	if (gpio)			/* GPIO: set bit to 0 */
+		x &= ~enable[pin];
+	else				/* Internal function: set bit to 1 */
+		x |= enable[pin];
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC);
+
+	local_irq_restore(flags);
+}
+
+
+static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 };
+
+/*
+ * Configure GPIO pin as external interrupt source.
+ */
+int ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
+{
+	unsigned long x, flags;
+
+	if (pin > KS8695_GPIO_3)	/* only GPIO 0..3 can generate IRQ */
+		return -EINVAL;
+
+	local_irq_save(flags);
+
+	/* set pin as input */
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+	x &= ~IOPM(pin);
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+	local_irq_restore(flags);
+
+	/* Set IRQ triggering type */
+	irq_set_irq_type(gpio_irq[pin], type);
+
+	/* enable interrupt mode */
+	ks8695_gpio_mode(pin, 0);
+
+	return 0;
+}
+EXPORT_SYMBOL(ks8695_gpio_interrupt);
+
+
+
+/* .... Generic GPIO interface .............................................. */
+
+/*
+ * Configure the GPIO line as an input.
+ */
+static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin)
+{
+	unsigned long x, flags;
+
+	if (pin > KS8695_GPIO_15)
+		return -EINVAL;
+
+	/* set pin to GPIO mode */
+	ks8695_gpio_mode(pin, 1);
+
+	local_irq_save(flags);
+
+	/* set pin as input */
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+	x &= ~IOPM(pin);
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+
+/*
+ * Configure the GPIO line as an output, with default state.
+ */
+static int ks8695_gpio_direction_output(struct gpio_chip *gc,
+					unsigned int pin, int state)
+{
+	unsigned long x, flags;
+
+	if (pin > KS8695_GPIO_15)
+		return -EINVAL;
+
+	/* set pin to GPIO mode */
+	ks8695_gpio_mode(pin, 1);
+
+	local_irq_save(flags);
+
+	/* set line state */
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+	if (state)
+		x |= IOPD(pin);
+	else
+		x &= ~IOPD(pin);
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
+
+	/* set pin as output */
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+	x |= IOPM(pin);
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+
+/*
+ * Set the state of an output GPIO line.
+ */
+static void ks8695_gpio_set_value(struct gpio_chip *gc,
+				  unsigned int pin, int state)
+{
+	unsigned long x, flags;
+
+	if (pin > KS8695_GPIO_15)
+		return;
+
+	local_irq_save(flags);
+
+	/* set output line state */
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+	if (state)
+		x |= IOPD(pin);
+	else
+		x &= ~IOPD(pin);
+	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
+
+	local_irq_restore(flags);
+}
+
+
+/*
+ * Read the state of a GPIO line.
+ */
+static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin)
+{
+	unsigned long x;
+
+	if (pin > KS8695_GPIO_15)
+		return -EINVAL;
+
+	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+	return (x & IOPD(pin)) != 0;
+}
+
+
+/*
+ * Map GPIO line to IRQ number.
+ */
+static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin)
+{
+	if (pin > KS8695_GPIO_3)	/* only GPIO 0..3 can generate IRQ */
+		return -EINVAL;
+
+	return gpio_irq[pin];
+}
+
+/*
+ * Map IRQ number to GPIO line.
+ */
+int irq_to_gpio(unsigned int irq)
+{
+	if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3))
+		return -EINVAL;
+
+	return (irq - KS8695_IRQ_EXTERN0);
+}
+EXPORT_SYMBOL(irq_to_gpio);
+
+/* GPIOLIB interface */
+
+static struct gpio_chip ks8695_gpio_chip = {
+	.label			= "KS8695",
+	.direction_input	= ks8695_gpio_direction_input,
+	.direction_output	= ks8695_gpio_direction_output,
+	.get			= ks8695_gpio_get_value,
+	.set			= ks8695_gpio_set_value,
+	.to_irq			= ks8695_gpio_to_irq,
+	.base			= 0,
+	.ngpio			= 16,
+	.can_sleep		= 0,
+};
+
+/* Register the GPIOs */
+void ks8695_register_gpios(void)
+{
+	if (gpiochip_add(&ks8695_gpio_chip))
+		printk(KERN_ERR "Unable to register core GPIOs\n");
+}
+
+/* .... Debug interface ..................................................... */
+
+#ifdef CONFIG_DEBUG_FS
+
+static int ks8695_gpio_show(struct seq_file *s, void *unused)
+{
+	unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
+	unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM };
+	unsigned long mode, ctrl, data;
+	int i;
+
+	mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+	ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
+	data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+
+	seq_printf(s, "Pin\tI/O\tFunction\tState\n\n");
+
+	for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) {
+		seq_printf(s, "%i:\t", i);
+
+		seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input");
+
+		if (i <= KS8695_GPIO_3) {
+			if (ctrl & enable[i]) {
+				seq_printf(s, "EXT%i ", i);
+
+				switch ((ctrl & intmask[i]) >> (4 * i)) {
+					case IOPC_TM_LOW:
+						seq_printf(s, "(Low)");		break;
+					case IOPC_TM_HIGH:
+						seq_printf(s, "(High)");	break;
+					case IOPC_TM_RISING:
+						seq_printf(s, "(Rising)");	break;
+					case IOPC_TM_FALLING:
+						seq_printf(s, "(Falling)");	break;
+					case IOPC_TM_EDGE:
+						seq_printf(s, "(Edges)");	break;
+				}
+			}
+			else
+				seq_printf(s, "GPIO\t");
+		}
+		else if (i <= KS8695_GPIO_5) {
+			if (ctrl & enable[i])
+				seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4);
+			else
+				seq_printf(s, "GPIO\t");
+		}
+		else
+			seq_printf(s, "GPIO\t");
+
+		seq_printf(s, "\t");
+
+		seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0);
+	}
+	return 0;
+}
+
+static int ks8695_gpio_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ks8695_gpio_show, NULL);
+}
+
+static const struct file_operations ks8695_gpio_operations = {
+	.open		= ks8695_gpio_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init ks8695_gpio_debugfs_init(void)
+{
+	/* /sys/kernel/debug/ks8695_gpio */
+	(void) debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, &ks8695_gpio_operations);
+	return 0;
+}
+postcore_initcall(ks8695_gpio_debugfs_init);
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-langwell.c linux-libre-3.2-gnu/drivers/gpio/gpio-langwell.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-langwell.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-langwell.c	2012-01-04 18:55:44.000000000 -0500
@@ -59,6 +59,7 @@
 	GRER,		/* rising edge detect */
 	GFER,		/* falling edge detect */
 	GEDR,		/* edge detect result */
+	GAFR,		/* alt function */
 };
 
 struct lnw_gpio {
@@ -81,6 +82,31 @@
 	return ptr;
 }
 
+static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset,
+				   enum GPIO_REG reg_type)
+{
+	struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+	unsigned nreg = chip->ngpio / 32;
+	u8 reg = offset / 16;
+	void __iomem *ptr;
+
+	ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4);
+	return ptr;
+}
+
+static int lnw_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	void __iomem *gafr = gpio_reg_2bit(chip, offset, GAFR);
+	u32 value = readl(gafr);
+	int shift = (offset % 16) << 1, af = (value >> shift) & 3;
+
+	if (af) {
+		value &= ~(3 << shift);
+		writel(value, gafr);
+	}
+	return 0;
+}
+
 static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
 	void __iomem *gplr = gpio_reg(chip, offset, GPLR);
@@ -321,6 +347,7 @@
 	lnw->reg_base = base;
 	lnw->irq_base = irq_base;
 	lnw->chip.label = dev_name(&pdev->dev);
+	lnw->chip.request = lnw_gpio_request;
 	lnw->chip.direction_input = lnw_gpio_direction_input;
 	lnw->chip.direction_output = lnw_gpio_direction_output;
 	lnw->chip.get = lnw_gpio_get;
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-lpc32xx.c linux-libre-3.2-gnu/drivers/gpio/gpio-lpc32xx.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-lpc32xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-lpc32xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,446 @@
+/*
+ * arch/arm/mach-lpc32xx/gpiolib.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/io.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <mach/gpio-lpc32xx.h>
+
+#define LPC32XX_GPIO_P3_INP_STATE		_GPREG(0x000)
+#define LPC32XX_GPIO_P3_OUTP_SET		_GPREG(0x004)
+#define LPC32XX_GPIO_P3_OUTP_CLR		_GPREG(0x008)
+#define LPC32XX_GPIO_P3_OUTP_STATE		_GPREG(0x00C)
+#define LPC32XX_GPIO_P2_DIR_SET			_GPREG(0x010)
+#define LPC32XX_GPIO_P2_DIR_CLR			_GPREG(0x014)
+#define LPC32XX_GPIO_P2_DIR_STATE		_GPREG(0x018)
+#define LPC32XX_GPIO_P2_INP_STATE		_GPREG(0x01C)
+#define LPC32XX_GPIO_P2_OUTP_SET		_GPREG(0x020)
+#define LPC32XX_GPIO_P2_OUTP_CLR		_GPREG(0x024)
+#define LPC32XX_GPIO_P2_MUX_SET			_GPREG(0x028)
+#define LPC32XX_GPIO_P2_MUX_CLR			_GPREG(0x02C)
+#define LPC32XX_GPIO_P2_MUX_STATE		_GPREG(0x030)
+#define LPC32XX_GPIO_P0_INP_STATE		_GPREG(0x040)
+#define LPC32XX_GPIO_P0_OUTP_SET		_GPREG(0x044)
+#define LPC32XX_GPIO_P0_OUTP_CLR		_GPREG(0x048)
+#define LPC32XX_GPIO_P0_OUTP_STATE		_GPREG(0x04C)
+#define LPC32XX_GPIO_P0_DIR_SET			_GPREG(0x050)
+#define LPC32XX_GPIO_P0_DIR_CLR			_GPREG(0x054)
+#define LPC32XX_GPIO_P0_DIR_STATE		_GPREG(0x058)
+#define LPC32XX_GPIO_P1_INP_STATE		_GPREG(0x060)
+#define LPC32XX_GPIO_P1_OUTP_SET		_GPREG(0x064)
+#define LPC32XX_GPIO_P1_OUTP_CLR		_GPREG(0x068)
+#define LPC32XX_GPIO_P1_OUTP_STATE		_GPREG(0x06C)
+#define LPC32XX_GPIO_P1_DIR_SET			_GPREG(0x070)
+#define LPC32XX_GPIO_P1_DIR_CLR			_GPREG(0x074)
+#define LPC32XX_GPIO_P1_DIR_STATE		_GPREG(0x078)
+
+#define GPIO012_PIN_TO_BIT(x)			(1 << (x))
+#define GPIO3_PIN_TO_BIT(x)			(1 << ((x) + 25))
+#define GPO3_PIN_TO_BIT(x)			(1 << (x))
+#define GPIO012_PIN_IN_SEL(x, y)		(((x) >> (y)) & 1)
+#define GPIO3_PIN_IN_SHIFT(x)			((x) == 5 ? 24 : 10 + (x))
+#define GPIO3_PIN_IN_SEL(x, y)			((x) >> GPIO3_PIN_IN_SHIFT(y))
+#define GPIO3_PIN5_IN_SEL(x)			(((x) >> 24) & 1)
+#define GPI3_PIN_IN_SEL(x, y)			(((x) >> (y)) & 1)
+
+struct gpio_regs {
+	void __iomem *inp_state;
+	void __iomem *outp_set;
+	void __iomem *outp_clr;
+	void __iomem *dir_set;
+	void __iomem *dir_clr;
+};
+
+/*
+ * GPIO names
+ */
+static const char *gpio_p0_names[LPC32XX_GPIO_P0_MAX] = {
+	"p0.0", "p0.1", "p0.2", "p0.3",
+	"p0.4", "p0.5", "p0.6", "p0.7"
+};
+
+static const char *gpio_p1_names[LPC32XX_GPIO_P1_MAX] = {
+	"p1.0", "p1.1", "p1.2", "p1.3",
+	"p1.4", "p1.5", "p1.6", "p1.7",
+	"p1.8", "p1.9", "p1.10", "p1.11",
+	"p1.12", "p1.13", "p1.14", "p1.15",
+	"p1.16", "p1.17", "p1.18", "p1.19",
+	"p1.20", "p1.21", "p1.22", "p1.23",
+};
+
+static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {
+	"p2.0", "p2.1", "p2.2", "p2.3",
+	"p2.4", "p2.5", "p2.6", "p2.7",
+	"p2.8", "p2.9", "p2.10", "p2.11",
+	"p2.12"
+};
+
+static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {
+	"gpi000", "gpio01", "gpio02", "gpio03",
+	"gpio04", "gpio05"
+};
+
+static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = {
+	"gpi00", "gpi01", "gpi02", "gpi03",
+	"gpi04", "gpi05", "gpi06", "gpi07",
+	"gpi08", "gpi09",  NULL,    NULL,
+	 NULL,    NULL,    NULL,   "gpi15",
+	"gpi16", "gpi17", "gpi18", "gpi19",
+	"gpi20", "gpi21", "gpi22", "gpi23",
+	"gpi24", "gpi25", "gpi26", "gpi27"
+};
+
+static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = {
+	"gpo00", "gpo01", "gpo02", "gpo03",
+	"gpo04", "gpo05", "gpo06", "gpo07",
+	"gpo08", "gpo09", "gpo10", "gpo11",
+	"gpo12", "gpo13", "gpo14", "gpo15",
+	"gpo16", "gpo17", "gpo18", "gpo19",
+	"gpo20", "gpo21", "gpo22", "gpo23"
+};
+
+static struct gpio_regs gpio_grp_regs_p0 = {
+	.inp_state	= LPC32XX_GPIO_P0_INP_STATE,
+	.outp_set	= LPC32XX_GPIO_P0_OUTP_SET,
+	.outp_clr	= LPC32XX_GPIO_P0_OUTP_CLR,
+	.dir_set	= LPC32XX_GPIO_P0_DIR_SET,
+	.dir_clr	= LPC32XX_GPIO_P0_DIR_CLR,
+};
+
+static struct gpio_regs gpio_grp_regs_p1 = {
+	.inp_state	= LPC32XX_GPIO_P1_INP_STATE,
+	.outp_set	= LPC32XX_GPIO_P1_OUTP_SET,
+	.outp_clr	= LPC32XX_GPIO_P1_OUTP_CLR,
+	.dir_set	= LPC32XX_GPIO_P1_DIR_SET,
+	.dir_clr	= LPC32XX_GPIO_P1_DIR_CLR,
+};
+
+static struct gpio_regs gpio_grp_regs_p2 = {
+	.inp_state	= LPC32XX_GPIO_P2_INP_STATE,
+	.outp_set	= LPC32XX_GPIO_P2_OUTP_SET,
+	.outp_clr	= LPC32XX_GPIO_P2_OUTP_CLR,
+	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
+	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
+};
+
+static struct gpio_regs gpio_grp_regs_p3 = {
+	.inp_state	= LPC32XX_GPIO_P3_INP_STATE,
+	.outp_set	= LPC32XX_GPIO_P3_OUTP_SET,
+	.outp_clr	= LPC32XX_GPIO_P3_OUTP_CLR,
+	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
+	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
+};
+
+struct lpc32xx_gpio_chip {
+	struct gpio_chip	chip;
+	struct gpio_regs	*gpio_grp;
+};
+
+static inline struct lpc32xx_gpio_chip *to_lpc32xx_gpio(
+	struct gpio_chip *gpc)
+{
+	return container_of(gpc, struct lpc32xx_gpio_chip, chip);
+}
+
+static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int input)
+{
+	if (input)
+		__raw_writel(GPIO012_PIN_TO_BIT(pin),
+			group->gpio_grp->dir_clr);
+	else
+		__raw_writel(GPIO012_PIN_TO_BIT(pin),
+			group->gpio_grp->dir_set);
+}
+
+static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int input)
+{
+	u32 u = GPIO3_PIN_TO_BIT(pin);
+
+	if (input)
+		__raw_writel(u, group->gpio_grp->dir_clr);
+	else
+		__raw_writel(u, group->gpio_grp->dir_set);
+}
+
+static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int high)
+{
+	if (high)
+		__raw_writel(GPIO012_PIN_TO_BIT(pin),
+			group->gpio_grp->outp_set);
+	else
+		__raw_writel(GPIO012_PIN_TO_BIT(pin),
+			group->gpio_grp->outp_clr);
+}
+
+static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int high)
+{
+	u32 u = GPIO3_PIN_TO_BIT(pin);
+
+	if (high)
+		__raw_writel(u, group->gpio_grp->outp_set);
+	else
+		__raw_writel(u, group->gpio_grp->outp_clr);
+}
+
+static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int high)
+{
+	if (high)
+		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);
+	else
+		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);
+}
+
+static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group,
+	unsigned pin)
+{
+	return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state),
+		pin);
+}
+
+static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin)
+{
+	int state = __raw_readl(group->gpio_grp->inp_state);
+
+	/*
+	 * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped
+	 * to bits 10..14, while GPIOP3-5 is mapped to bit 24.
+	 */
+	return GPIO3_PIN_IN_SEL(state, pin);
+}
+
+static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin)
+{
+	return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin);
+}
+
+/*
+ * GENERIC_GPIO primitives.
+ */
+static int lpc32xx_gpio_dir_input_p012(struct gpio_chip *chip,
+	unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_dir_p012(group, pin, 1);
+
+	return 0;
+}
+
+static int lpc32xx_gpio_dir_input_p3(struct gpio_chip *chip,
+	unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_dir_p3(group, pin, 1);
+
+	return 0;
+}
+
+static int lpc32xx_gpio_dir_in_always(struct gpio_chip *chip,
+	unsigned pin)
+{
+	return 0;
+}
+
+static int lpc32xx_gpio_get_value_p012(struct gpio_chip *chip, unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	return __get_gpio_state_p012(group, pin);
+}
+
+static int lpc32xx_gpio_get_value_p3(struct gpio_chip *chip, unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	return __get_gpio_state_p3(group, pin);
+}
+
+static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	return __get_gpi_state_p3(group, pin);
+}
+
+static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_dir_p012(group, pin, 0);
+
+	return 0;
+}
+
+static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_dir_p3(group, pin, 0);
+
+	return 0;
+}
+
+static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	return 0;
+}
+
+static void lpc32xx_gpio_set_value_p012(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_level_p012(group, pin, value);
+}
+
+static void lpc32xx_gpio_set_value_p3(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_level_p3(group, pin, value);
+}
+
+static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpo_level_p3(group, pin, value);
+}
+
+static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
+{
+	if (pin < chip->ngpio)
+		return 0;
+
+	return -EINVAL;
+}
+
+static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
+	{
+		.chip = {
+			.label			= "gpio_p0",
+			.direction_input	= lpc32xx_gpio_dir_input_p012,
+			.get			= lpc32xx_gpio_get_value_p012,
+			.direction_output	= lpc32xx_gpio_dir_output_p012,
+			.set			= lpc32xx_gpio_set_value_p012,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPIO_P0_GRP,
+			.ngpio			= LPC32XX_GPIO_P0_MAX,
+			.names			= gpio_p0_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p0,
+	},
+	{
+		.chip = {
+			.label			= "gpio_p1",
+			.direction_input	= lpc32xx_gpio_dir_input_p012,
+			.get			= lpc32xx_gpio_get_value_p012,
+			.direction_output	= lpc32xx_gpio_dir_output_p012,
+			.set			= lpc32xx_gpio_set_value_p012,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPIO_P1_GRP,
+			.ngpio			= LPC32XX_GPIO_P1_MAX,
+			.names			= gpio_p1_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p1,
+	},
+	{
+		.chip = {
+			.label			= "gpio_p2",
+			.direction_input	= lpc32xx_gpio_dir_input_p012,
+			.get			= lpc32xx_gpio_get_value_p012,
+			.direction_output	= lpc32xx_gpio_dir_output_p012,
+			.set			= lpc32xx_gpio_set_value_p012,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPIO_P2_GRP,
+			.ngpio			= LPC32XX_GPIO_P2_MAX,
+			.names			= gpio_p2_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p2,
+	},
+	{
+		.chip = {
+			.label			= "gpio_p3",
+			.direction_input	= lpc32xx_gpio_dir_input_p3,
+			.get			= lpc32xx_gpio_get_value_p3,
+			.direction_output	= lpc32xx_gpio_dir_output_p3,
+			.set			= lpc32xx_gpio_set_value_p3,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPIO_P3_GRP,
+			.ngpio			= LPC32XX_GPIO_P3_MAX,
+			.names			= gpio_p3_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p3,
+	},
+	{
+		.chip = {
+			.label			= "gpi_p3",
+			.direction_input	= lpc32xx_gpio_dir_in_always,
+			.get			= lpc32xx_gpi_get_value,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPI_P3_GRP,
+			.ngpio			= LPC32XX_GPI_P3_MAX,
+			.names			= gpi_p3_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p3,
+	},
+	{
+		.chip = {
+			.label			= "gpo_p3",
+			.direction_output	= lpc32xx_gpio_dir_out_always,
+			.set			= lpc32xx_gpo_set_value,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPO_P3_GRP,
+			.ngpio			= LPC32XX_GPO_P3_MAX,
+			.names			= gpo_p3_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p3,
+	},
+};
+
+void __init lpc32xx_gpio_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++)
+		gpiochip_add(&lpc32xx_gpiochip[i].chip);
+}
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-mc33880.c linux-libre-3.2-gnu/drivers/gpio/gpio-mc33880.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-mc33880.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-mc33880.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/spi/mc33880.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define DRIVER_NAME "mc33880"
 
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-mcp23s08.c linux-libre-3.2-gnu/drivers/gpio/gpio-mcp23s08.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-mcp23s08.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-mcp23s08.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,7 @@
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/mutex.h>
+#include <linux/module.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-ml-ioh.c linux-libre-3.2-gnu/drivers/gpio/gpio-ml-ioh.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-ml-ioh.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-ml-ioh.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,10 +14,22 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  */
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#define IOH_EDGE_FALLING	0
+#define IOH_EDGE_RISING		BIT(0)
+#define IOH_LEVEL_L		BIT(1)
+#define IOH_LEVEL_H		(BIT(0) | BIT(1))
+#define IOH_EDGE_BOTH		BIT(2)
+#define IOH_IM_MASK		(BIT(0) | BIT(1) | BIT(2))
+
+#define IOH_IRQ_BASE		0
 
 #define PCI_VENDOR_ID_ROHM             0x10DB
 
@@ -46,12 +58,22 @@
 
 /**
  * struct ioh_gpio_reg_data - The register store data.
+ * @ien_reg	To store contents of interrupt enable register.
+ * @imask_reg:	To store contents of interrupt mask regist
  * @po_reg:	To store contents of PO register.
  * @pm_reg:	To store contents of PM register.
+ * @im0_reg:	To store contents of interrupt mode regist0
+ * @im1_reg:	To store contents of interrupt mode regist1
+ * @use_sel_reg: To store contents of GPIO_USE_SEL0~3
  */
 struct ioh_gpio_reg_data {
+	u32 ien_reg;
+	u32 imask_reg;
 	u32 po_reg;
 	u32 pm_reg;
+	u32 im0_reg;
+	u32 im1_reg;
+	u32 use_sel_reg;
 };
 
 /**
@@ -62,7 +84,11 @@
  * @gpio:			Data for GPIO infrastructure.
  * @ioh_gpio_reg:		Memory mapped Register data is saved here
  *				when suspend.
+ * @gpio_use_sel:		Save GPIO_USE_SEL1~4 register for PM
  * @ch:				Indicate GPIO channel
+ * @irq_base:		Save base of IRQ number for interrupt
+ * @spinlock:		Used for register access protection in
+ *				interrupt context ioh_irq_type and PM;
  */
 struct ioh_gpio {
 	void __iomem *base;
@@ -70,8 +96,11 @@
 	struct device *dev;
 	struct gpio_chip gpio;
 	struct ioh_gpio_reg_data ioh_gpio_reg;
+	u32 gpio_use_sel;
 	struct mutex lock;
 	int ch;
+	int irq_base;
+	spinlock_t spinlock;
 };
 
 static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12};
@@ -145,8 +174,25 @@
  */
 static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
 {
-	chip->ioh_gpio_reg.po_reg = ioread32(&chip->reg->regs[chip->ch].po);
-	chip->ioh_gpio_reg.pm_reg = ioread32(&chip->reg->regs[chip->ch].pm);
+	int i;
+
+	for (i = 0; i < 8; i ++, chip++) {
+		chip->ioh_gpio_reg.po_reg =
+					ioread32(&chip->reg->regs[chip->ch].po);
+		chip->ioh_gpio_reg.pm_reg =
+					ioread32(&chip->reg->regs[chip->ch].pm);
+		chip->ioh_gpio_reg.ien_reg =
+				       ioread32(&chip->reg->regs[chip->ch].ien);
+		chip->ioh_gpio_reg.imask_reg =
+				     ioread32(&chip->reg->regs[chip->ch].imask);
+		chip->ioh_gpio_reg.im0_reg =
+				      ioread32(&chip->reg->regs[chip->ch].im_0);
+		chip->ioh_gpio_reg.im1_reg =
+				      ioread32(&chip->reg->regs[chip->ch].im_1);
+		if (i < 4)
+			chip->ioh_gpio_reg.use_sel_reg =
+					   ioread32(&chip->reg->ioh_sel_reg[i]);
+	}
 }
 
 /*
@@ -154,13 +200,34 @@
  */
 static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
 {
-	/* to store contents of PO register */
-	iowrite32(chip->ioh_gpio_reg.po_reg, &chip->reg->regs[chip->ch].po);
-	/* to store contents of PM register */
-	iowrite32(chip->ioh_gpio_reg.pm_reg, &chip->reg->regs[chip->ch].pm);
+	int i;
+
+	for (i = 0; i < 8; i ++, chip++) {
+		iowrite32(chip->ioh_gpio_reg.po_reg,
+			  &chip->reg->regs[chip->ch].po);
+		iowrite32(chip->ioh_gpio_reg.pm_reg,
+			  &chip->reg->regs[chip->ch].pm);
+		iowrite32(chip->ioh_gpio_reg.ien_reg,
+			  &chip->reg->regs[chip->ch].ien);
+		iowrite32(chip->ioh_gpio_reg.imask_reg,
+			  &chip->reg->regs[chip->ch].imask);
+		iowrite32(chip->ioh_gpio_reg.im0_reg,
+			  &chip->reg->regs[chip->ch].im_0);
+		iowrite32(chip->ioh_gpio_reg.im1_reg,
+			  &chip->reg->regs[chip->ch].im_1);
+		if (i < 4)
+			iowrite32(chip->ioh_gpio_reg.use_sel_reg,
+				  &chip->reg->ioh_sel_reg[i]);
+	}
 }
 #endif
 
+static int ioh_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
+{
+	struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
+	return chip->irq_base + offset;
+}
+
 static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
 {
 	struct gpio_chip *gpio = &chip->gpio;
@@ -175,16 +242,178 @@
 	gpio->base = -1;
 	gpio->ngpio = num_port;
 	gpio->can_sleep = 0;
+	gpio->to_irq = ioh_gpio_to_irq;
+}
+
+static int ioh_irq_type(struct irq_data *d, unsigned int type)
+{
+	u32 im;
+	u32 *im_reg;
+	u32 ien;
+	u32 im_pos;
+	int ch;
+	unsigned long flags;
+	u32 val;
+	int irq = d->irq;
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct ioh_gpio *chip = gc->private;
+
+	ch = irq - chip->irq_base;
+	if (irq <= chip->irq_base + 7) {
+		im_reg = &chip->reg->regs[chip->ch].im_0;
+		im_pos = ch;
+	} else {
+		im_reg = &chip->reg->regs[chip->ch].im_1;
+		im_pos = ch - 8;
+	}
+	dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d type=%d\n",
+		__func__, irq, type, ch, im_pos, type);
+
+	spin_lock_irqsave(&chip->spinlock, flags);
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		val = IOH_EDGE_RISING;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		val = IOH_EDGE_FALLING;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		val = IOH_EDGE_BOTH;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		val = IOH_LEVEL_H;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		val = IOH_LEVEL_L;
+		break;
+	case IRQ_TYPE_PROBE:
+		goto end;
+	default:
+		dev_warn(chip->dev, "%s: unknown type(%dd)",
+			__func__, type);
+		goto end;
+	}
+
+	/* Set interrupt mode */
+	im = ioread32(im_reg) & ~(IOH_IM_MASK << (im_pos * 4));
+	iowrite32(im | (val << (im_pos * 4)), im_reg);
+
+	/* iclr */
+	iowrite32(BIT(ch), &chip->reg->regs[chip->ch].iclr);
+
+	/* IMASKCLR */
+	iowrite32(BIT(ch), &chip->reg->regs[chip->ch].imaskclr);
+
+	/* Enable interrupt */
+	ien = ioread32(&chip->reg->regs[chip->ch].ien);
+	iowrite32(ien | BIT(ch), &chip->reg->regs[chip->ch].ien);
+end:
+	spin_unlock_irqrestore(&chip->spinlock, flags);
+
+	return 0;
+}
+
+static void ioh_irq_unmask(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct ioh_gpio *chip = gc->private;
+
+	iowrite32(1 << (d->irq - chip->irq_base),
+		  &chip->reg->regs[chip->ch].imaskclr);
+}
+
+static void ioh_irq_mask(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct ioh_gpio *chip = gc->private;
+
+	iowrite32(1 << (d->irq - chip->irq_base),
+		  &chip->reg->regs[chip->ch].imask);
+}
+
+static void ioh_irq_disable(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct ioh_gpio *chip = gc->private;
+	unsigned long flags;
+	u32 ien;
+
+	spin_lock_irqsave(&chip->spinlock, flags);
+	ien = ioread32(&chip->reg->regs[chip->ch].ien);
+	ien &= ~(1 << (d->irq - chip->irq_base));
+	iowrite32(ien, &chip->reg->regs[chip->ch].ien);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
+}
+
+static void ioh_irq_enable(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct ioh_gpio *chip = gc->private;
+	unsigned long flags;
+	u32 ien;
+
+	spin_lock_irqsave(&chip->spinlock, flags);
+	ien = ioread32(&chip->reg->regs[chip->ch].ien);
+	ien |= 1 << (d->irq - chip->irq_base);
+	iowrite32(ien, &chip->reg->regs[chip->ch].ien);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
+}
+
+static irqreturn_t ioh_gpio_handler(int irq, void *dev_id)
+{
+	struct ioh_gpio *chip = dev_id;
+	u32 reg_val;
+	int i, j;
+	int ret = IRQ_NONE;
+
+	for (i = 0; i < 8; i++, chip++) {
+		reg_val = ioread32(&chip->reg->regs[i].istatus);
+		for (j = 0; j < num_ports[i]; j++) {
+			if (reg_val & BIT(j)) {
+				dev_dbg(chip->dev,
+					"%s:[%d]:irq=%d status=0x%x\n",
+					__func__, j, irq, reg_val);
+				iowrite32(BIT(j),
+					  &chip->reg->regs[chip->ch].iclr);
+				generic_handle_irq(chip->irq_base + j);
+				ret = IRQ_HANDLED;
+			}
+		}
+	}
+	return ret;
+}
+
+static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
+				unsigned int irq_start, unsigned int num)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+
+	gc = irq_alloc_generic_chip("ioh_gpio", 1, irq_start, chip->base,
+				    handle_simple_irq);
+	gc->private = chip;
+	ct = gc->chip_types;
+
+	ct->chip.irq_mask = ioh_irq_mask;
+	ct->chip.irq_unmask = ioh_irq_unmask;
+	ct->chip.irq_set_type = ioh_irq_type;
+	ct->chip.irq_disable = ioh_irq_disable;
+	ct->chip.irq_enable = ioh_irq_enable;
+
+	irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
+			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 }
 
 static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
 				    const struct pci_device_id *id)
 {
 	int ret;
-	int i;
+	int i, j;
 	struct ioh_gpio *chip;
 	void __iomem *base;
 	void __iomem *chip_save;
+	int irq_base;
 
 	ret = pci_enable_device(pdev);
 	if (ret) {
@@ -228,10 +457,41 @@
 	}
 
 	chip = chip_save;
+	for (j = 0; j < 8; j++, chip++) {
+		irq_base = irq_alloc_descs(-1, IOH_IRQ_BASE, num_ports[j],
+					   NUMA_NO_NODE);
+		if (irq_base < 0) {
+			dev_warn(&pdev->dev,
+				"ml_ioh_gpio: Failed to get IRQ base num\n");
+			chip->irq_base = -1;
+			goto err_irq_alloc_descs;
+		}
+		chip->irq_base = irq_base;
+		ioh_gpio_alloc_generic_chip(chip, irq_base, num_ports[j]);
+	}
+
+	chip = chip_save;
+	ret = request_irq(pdev->irq, ioh_gpio_handler,
+			     IRQF_SHARED, KBUILD_MODNAME, chip);
+	if (ret != 0) {
+		dev_err(&pdev->dev,
+			"%s request_irq failed\n", __func__);
+		goto err_request_irq;
+	}
+
 	pci_set_drvdata(pdev, chip);
 
 	return 0;
 
+err_request_irq:
+	chip = chip_save;
+err_irq_alloc_descs:
+	while (--j >= 0) {
+		chip--;
+		irq_free_descs(chip->irq_base, num_ports[j]);
+	}
+
+	chip = chip_save;
 err_gpiochip_add:
 	while (--i >= 0) {
 		chip--;
@@ -264,7 +524,11 @@
 	void __iomem *chip_save;
 
 	chip_save = chip;
+
+	free_irq(pdev->irq, chip);
+
 	for (i = 0; i < 8; i++, chip++) {
+		irq_free_descs(chip->irq_base, num_ports[i]);
 		err = gpiochip_remove(&chip->gpio);
 		if (err)
 			dev_err(&pdev->dev, "Failed gpiochip_remove\n");
@@ -282,9 +546,11 @@
 {
 	s32 ret;
 	struct ioh_gpio *chip = pci_get_drvdata(pdev);
+	unsigned long flags;
 
+	spin_lock_irqsave(&chip->spinlock, flags);
 	ioh_gpio_save_reg_conf(chip);
-	ioh_gpio_restore_reg_conf(chip);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 
 	ret = pci_save_state(pdev);
 	if (ret) {
@@ -304,6 +570,7 @@
 {
 	s32 ret;
 	struct ioh_gpio *chip = pci_get_drvdata(pdev);
+	unsigned long flags;
 
 	ret = pci_enable_wake(pdev, PCI_D0, 0);
 
@@ -315,9 +582,11 @@
 	}
 	pci_restore_state(pdev);
 
+	spin_lock_irqsave(&chip->spinlock, flags);
 	iowrite32(0x01, &chip->reg->srst);
 	iowrite32(0x00, &chip->reg->srst);
 	ioh_gpio_restore_reg_conf(chip);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-mpc5200.c linux-libre-3.2-gnu/drivers/gpio/gpio-mpc5200.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-mpc5200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-mpc5200.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/of_gpio.h>
 #include <linux/io.h>
 #include <linux/of_platform.h>
+#include <linux/module.h>
 
 #include <asm/gpio.h>
 #include <asm/mpc52xx.h>
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-mpc8xxx.c linux-libre-3.2-gnu/drivers/gpio/gpio-mpc8xxx.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-mpc8xxx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-mpc8xxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,406 @@
+/*
+ * GPIOs on MPC512x/8349/8572/8610 and compatible
+ *
+ * Copyright (C) 2008 Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+
+#define MPC8XXX_GPIO_PINS	32
+
+#define GPIO_DIR		0x00
+#define GPIO_ODR		0x04
+#define GPIO_DAT		0x08
+#define GPIO_IER		0x0c
+#define GPIO_IMR		0x10
+#define GPIO_ICR		0x14
+#define GPIO_ICR2		0x18
+
+struct mpc8xxx_gpio_chip {
+	struct of_mm_gpio_chip mm_gc;
+	spinlock_t lock;
+
+	/*
+	 * shadowed data register to be able to clear/set output pins in
+	 * open drain mode safely
+	 */
+	u32 data;
+	struct irq_host *irq;
+	void *of_dev_id_data;
+};
+
+static inline u32 mpc8xxx_gpio2mask(unsigned int gpio)
+{
+	return 1u << (MPC8XXX_GPIO_PINS - 1 - gpio);
+}
+
+static inline struct mpc8xxx_gpio_chip *
+to_mpc8xxx_gpio_chip(struct of_mm_gpio_chip *mm)
+{
+	return container_of(mm, struct mpc8xxx_gpio_chip, mm_gc);
+}
+
+static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm)
+{
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+
+	mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT);
+}
+
+/* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs
+ * defined as output cannot be determined by reading GPDAT register,
+ * so we use shadow data register instead. The status of input pins
+ * is determined by reading GPDAT register.
+ */
+static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+	u32 val;
+	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+
+	val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR);
+
+	return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio);
+}
+
+static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+
+	return in_be32(mm->regs + GPIO_DAT) & mpc8xxx_gpio2mask(gpio);
+}
+
+static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+	unsigned long flags;
+
+	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+
+	if (val)
+		mpc8xxx_gc->data |= mpc8xxx_gpio2mask(gpio);
+	else
+		mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask(gpio);
+
+	out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data);
+
+	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+}
+
+static int mpc8xxx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+	unsigned long flags;
+
+	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+
+	clrbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio));
+
+	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+
+	return 0;
+}
+
+static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+	unsigned long flags;
+
+	mpc8xxx_gpio_set(gc, gpio, val);
+
+	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+
+	setbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio));
+
+	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+
+	return 0;
+}
+
+static int mpc5121_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	/* GPIO 28..31 are input only on MPC5121 */
+	if (gpio >= 28)
+		return -EINVAL;
+
+	return mpc8xxx_gpio_dir_out(gc, gpio, val);
+}
+
+static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+
+	if (mpc8xxx_gc->irq && offset < MPC8XXX_GPIO_PINS)
+		return irq_create_mapping(mpc8xxx_gc->irq, offset);
+	else
+		return -ENXIO;
+}
+
+static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc)
+{
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
+	unsigned int mask;
+
+	mask = in_be32(mm->regs + GPIO_IER) & in_be32(mm->regs + GPIO_IMR);
+	if (mask)
+		generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq,
+						     32 - ffs(mask)));
+	chip->irq_eoi(&desc->irq_data);
+}
+
+static void mpc8xxx_irq_unmask(struct irq_data *d)
+{
+	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(irqd_to_hwirq(d)));
+
+	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+}
+
+static void mpc8xxx_irq_mask(struct irq_data *d)
+{
+	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(irqd_to_hwirq(d)));
+
+	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+}
+
+static void mpc8xxx_irq_ack(struct irq_data *d)
+{
+	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(irqd_to_hwirq(d)));
+}
+
+static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+	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;
+
+	switch (flow_type) {
+	case IRQ_TYPE_EDGE_FALLING:
+		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+		setbits32(mm->regs + GPIO_ICR,
+			  mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
+		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(irqd_to_hwirq(d)));
+		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+	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 = irqd_to_hwirq(d);
+	void __iomem *reg;
+	unsigned int shift;
+	unsigned long flags;
+
+	if (gpio < 16) {
+		reg = mm->regs + GPIO_ICR;
+		shift = (15 - gpio) * 2;
+	} else {
+		reg = mm->regs + GPIO_ICR2;
+		shift = (15 - (gpio % 16)) * 2;
+	}
+
+	switch (flow_type) {
+	case IRQ_TYPE_EDGE_FALLING:
+	case IRQ_TYPE_LEVEL_LOW:
+		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+		clrsetbits_be32(reg, 3 << shift, 2 << shift);
+		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+		break;
+
+	case IRQ_TYPE_EDGE_RISING:
+	case IRQ_TYPE_LEVEL_HIGH:
+		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+		clrsetbits_be32(reg, 3 << shift, 1 << shift);
+		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+		break;
+
+	case IRQ_TYPE_EDGE_BOTH:
+		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+		clrbits32(reg, 3 << shift);
+		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct irq_chip mpc8xxx_irq_chip = {
+	.name		= "mpc8xxx-gpio",
+	.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,
+				irq_hw_number_t hw)
+{
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data;
+
+	if (mpc8xxx_gc->of_dev_id_data)
+		mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data;
+
+	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;
+}
+
+static int mpc8xxx_gpio_irq_xlate(struct irq_host *h, struct device_node *ct,
+				  const u32 *intspec, unsigned int intsize,
+				  irq_hw_number_t *out_hwirq,
+				  unsigned int *out_flags)
+
+{
+	/* interrupt sense values coming from the device tree equal either
+	 * EDGE_FALLING or EDGE_BOTH
+	 */
+	*out_hwirq = intspec[0];
+	*out_flags = intspec[1];
+
+	return 0;
+}
+
+static struct irq_host_ops mpc8xxx_gpio_irq_ops = {
+	.map	= mpc8xxx_gpio_irq_map,
+	.xlate	= mpc8xxx_gpio_irq_xlate,
+};
+
+static struct of_device_id mpc8xxx_gpio_ids[] __initdata = {
+	{ .compatible = "fsl,mpc8349-gpio", },
+	{ .compatible = "fsl,mpc8572-gpio", },
+	{ .compatible = "fsl,mpc8610-gpio", },
+	{ .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, },
+	{ .compatible = "fsl,pq3-gpio",     },
+	{ .compatible = "fsl,qoriq-gpio",   },
+	{}
+};
+
+static void __init mpc8xxx_add_controller(struct device_node *np)
+{
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc;
+	struct of_mm_gpio_chip *mm_gc;
+	struct gpio_chip *gc;
+	const struct of_device_id *id;
+	unsigned hwirq;
+	int ret;
+
+	mpc8xxx_gc = kzalloc(sizeof(*mpc8xxx_gc), GFP_KERNEL);
+	if (!mpc8xxx_gc) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	spin_lock_init(&mpc8xxx_gc->lock);
+
+	mm_gc = &mpc8xxx_gc->mm_gc;
+	gc = &mm_gc->gc;
+
+	mm_gc->save_regs = mpc8xxx_gpio_save_regs;
+	gc->ngpio = MPC8XXX_GPIO_PINS;
+	gc->direction_input = mpc8xxx_gpio_dir_in;
+	gc->direction_output = of_device_is_compatible(np, "fsl,mpc5121-gpio") ?
+		mpc5121_gpio_dir_out : mpc8xxx_gpio_dir_out;
+	gc->get = of_device_is_compatible(np, "fsl,mpc8572-gpio") ?
+		mpc8572_gpio_get : mpc8xxx_gpio_get;
+	gc->set = mpc8xxx_gpio_set;
+	gc->to_irq = mpc8xxx_gpio_to_irq;
+
+	ret = of_mm_gpiochip_add(np, mm_gc);
+	if (ret)
+		goto err;
+
+	hwirq = irq_of_parse_and_map(np, 0);
+	if (hwirq == NO_IRQ)
+		goto skip_irq;
+
+	mpc8xxx_gc->irq =
+		irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, MPC8XXX_GPIO_PINS,
+			       &mpc8xxx_gpio_irq_ops, MPC8XXX_GPIO_PINS);
+	if (!mpc8xxx_gc->irq)
+		goto skip_irq;
+
+	id = of_match_node(mpc8xxx_gpio_ids, np);
+	if (id)
+		mpc8xxx_gc->of_dev_id_data = id->data;
+
+	mpc8xxx_gc->irq->host_data = mpc8xxx_gc;
+
+	/* ack and mask all irqs */
+	out_be32(mm_gc->regs + GPIO_IER, 0xffffffff);
+	out_be32(mm_gc->regs + GPIO_IMR, 0);
+
+	irq_set_handler_data(hwirq, mpc8xxx_gc);
+	irq_set_chained_handler(hwirq, mpc8xxx_gpio_irq_cascade);
+
+skip_irq:
+	return;
+
+err:
+	pr_err("%s: registration failed with status %d\n",
+	       np->full_name, ret);
+	kfree(mpc8xxx_gc);
+
+	return;
+}
+
+static int __init mpc8xxx_add_gpiochips(void)
+{
+	struct device_node *np;
+
+	for_each_matching_node(np, mpc8xxx_gpio_ids)
+		mpc8xxx_add_controller(np);
+
+	return 0;
+}
+arch_initcall(mpc8xxx_add_gpiochips);
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-mxc.c linux-libre-3.2-gnu/drivers/gpio/gpio-mxc.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-mxc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-mxc.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,11 @@
 #include <linux/basic_mmio_gpio.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/module.h>
 #include <asm-generic/bug.h>
+#include <asm/mach/irq.h>
+
+#define irq_to_gpio(irq)	((irq) - MXC_GPIO_IRQ_START)
 
 enum mxc_gpio_hwtype {
 	IMX1_GPIO,	/* runs on i.mx1 */
@@ -232,10 +236,15 @@
 {
 	u32 irq_stat;
 	struct mxc_gpio_port *port = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_get_chip(irq);
+
+	chained_irq_enter(chip, desc);
 
 	irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR);
 
 	mxc_gpio_irq_handler(port, irq_stat);
+
+	chained_irq_exit(chip, desc);
 }
 
 /* MX2 has one interrupt *for all* gpio ports */
@@ -337,6 +346,15 @@
 	mxc_gpio_hwtype = hwtype;
 }
 
+static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+	struct bgpio_chip *bgc = to_bgpio_chip(gc);
+	struct mxc_gpio_port *port =
+		container_of(bgc, struct mxc_gpio_port, bgc);
+
+	return port->virtual_irq_start + offset;
+}
+
 static int __devinit mxc_gpio_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -403,6 +421,7 @@
 	if (err)
 		goto out_iounmap;
 
+	port->bgc.gc.to_irq = mxc_gpio_to_irq;
 	port->bgc.gc.base = pdev->id * 32;
 	port->bgc.dir = port->bgc.read_reg(port->bgc.reg_dir);
 	port->bgc.data = port->bgc.read_reg(port->bgc.reg_set);
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-mxs.c linux-libre-3.2-gnu/drivers/gpio/gpio-mxs.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-mxs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-mxs.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/basic_mmio_gpio.h>
+#include <linux/module.h>
 #include <mach/mxs.h>
 
 #define MXS_SET		0x4
@@ -49,6 +50,8 @@
 #define GPIO_INT_LEV_MASK	(1 << 0)
 #define GPIO_INT_POL_MASK	(1 << 1)
 
+#define irq_to_gpio(irq)	((irq) - MXS_GPIO_IRQ_START)
+
 struct mxs_gpio_port {
 	void __iomem *base;
 	int id;
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-nomadik.c linux-libre-3.2-gnu/drivers/gpio/gpio-nomadik.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-nomadik.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-nomadik.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,8 +27,9 @@
 #include <asm/mach/irq.h>
 
 #include <plat/pincfg.h>
+#include <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
 
 /*
  * The GPIO module in the Nomadik family of Systems-on-Chip is an
@@ -58,7 +59,6 @@
 	u32 rwimsc;
 	u32 fwimsc;
 	u32 slpm;
-	u32 enabled;
 	u32 pull_up;
 };
 
@@ -276,6 +276,8 @@
 		if (!chip)
 			break;
 
+		clk_enable(chip->clk);
+
 		slpm[i] = readl(chip->addr + NMK_GPIO_SLPC);
 		writel(temp, chip->addr + NMK_GPIO_SLPC);
 	}
@@ -292,6 +294,8 @@
 			break;
 
 		writel(slpm[i], chip->addr + NMK_GPIO_SLPC);
+
+		clk_disable(chip->clk);
 	}
 }
 
@@ -336,10 +340,12 @@
 			break;
 		}
 
+		clk_enable(nmk_chip->clk);
 		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);
+		clk_disable(nmk_chip->clk);
 	}
 
 	if (glitch)
@@ -424,6 +430,7 @@
 	if (!nmk_chip)
 		return -EINVAL;
 
+	clk_enable(nmk_chip->clk);
 	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
 	spin_lock(&nmk_chip->lock);
 
@@ -431,6 +438,7 @@
 
 	spin_unlock(&nmk_chip->lock);
 	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+	clk_disable(nmk_chip->clk);
 
 	return 0;
 }
@@ -457,9 +465,11 @@
 	if (!nmk_chip)
 		return -EINVAL;
 
+	clk_enable(nmk_chip->clk);
 	spin_lock_irqsave(&nmk_chip->lock, flags);
 	__nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull);
 	spin_unlock_irqrestore(&nmk_chip->lock, flags);
+	clk_disable(nmk_chip->clk);
 
 	return 0;
 }
@@ -483,9 +493,11 @@
 	if (!nmk_chip)
 		return -EINVAL;
 
+	clk_enable(nmk_chip->clk);
 	spin_lock_irqsave(&nmk_chip->lock, flags);
 	__nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode);
 	spin_unlock_irqrestore(&nmk_chip->lock, flags);
+	clk_disable(nmk_chip->clk);
 
 	return 0;
 }
@@ -502,9 +514,13 @@
 
 	bit = 1 << (gpio - nmk_chip->chip.base);
 
+	clk_enable(nmk_chip->clk);
+
 	afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit;
 	bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit;
 
+	clk_disable(nmk_chip->clk);
+
 	return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
 }
 EXPORT_SYMBOL(nmk_gpio_get_mode);
@@ -525,7 +541,10 @@
 	nmk_chip = irq_data_get_irq_chip_data(d);
 	if (!nmk_chip)
 		return;
+
+	clk_enable(nmk_chip->clk);
 	writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC);
+	clk_disable(nmk_chip->clk);
 }
 
 enum nmk_gpio_irq_type {
@@ -586,11 +605,7 @@
 	if (!nmk_chip)
 		return -EINVAL;
 
-	if (enable)
-		nmk_chip->enabled |= bitmask;
-	else
-		nmk_chip->enabled &= ~bitmask;
-
+	clk_enable(nmk_chip->clk);
 	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
 	spin_lock(&nmk_chip->lock);
 
@@ -601,6 +616,7 @@
 
 	spin_unlock(&nmk_chip->lock);
 	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+	clk_disable(nmk_chip->clk);
 
 	return 0;
 }
@@ -628,10 +644,11 @@
 		return -EINVAL;
 	bitmask = nmk_gpio_get_bitmask(gpio);
 
+	clk_enable(nmk_chip->clk);
 	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
 	spin_lock(&nmk_chip->lock);
 
-	if (!(nmk_chip->enabled & bitmask))
+	if (irqd_irq_disabled(d))
 		__nmk_gpio_set_wake(nmk_chip, gpio, on);
 
 	if (on)
@@ -641,13 +658,15 @@
 
 	spin_unlock(&nmk_chip->lock);
 	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+	clk_disable(nmk_chip->clk);
 
 	return 0;
 }
 
 static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
-	bool enabled, wake = irqd_is_wakeup_set(d);
+	bool enabled = !irqd_irq_disabled(d);
+	bool wake = irqd_is_wakeup_set(d);
 	int gpio;
 	struct nmk_gpio_chip *nmk_chip;
 	unsigned long flags;
@@ -664,8 +683,7 @@
 	if (type & IRQ_TYPE_LEVEL_LOW)
 		return -EINVAL;
 
-	enabled = nmk_chip->enabled & bitmask;
-
+	clk_enable(nmk_chip->clk);
 	spin_lock_irqsave(&nmk_chip->lock, flags);
 
 	if (enabled)
@@ -689,10 +707,28 @@
 		__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true);
 
 	spin_unlock_irqrestore(&nmk_chip->lock, flags);
+	clk_disable(nmk_chip->clk);
 
 	return 0;
 }
 
+static unsigned int nmk_gpio_irq_startup(struct irq_data *d)
+{
+	struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
+
+	clk_enable(nmk_chip->clk);
+	nmk_gpio_irq_unmask(d);
+	return 0;
+}
+
+static void nmk_gpio_irq_shutdown(struct irq_data *d)
+{
+	struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
+
+	nmk_gpio_irq_mask(d);
+	clk_disable(nmk_chip->clk);
+}
+
 static struct irq_chip nmk_gpio_irq_chip = {
 	.name		= "Nomadik-GPIO",
 	.irq_ack	= nmk_gpio_irq_ack,
@@ -700,6 +736,8 @@
 	.irq_unmask	= nmk_gpio_irq_unmask,
 	.irq_set_type	= nmk_gpio_irq_set_type,
 	.irq_set_wake	= nmk_gpio_irq_set_wake,
+	.irq_startup	= nmk_gpio_irq_startup,
+	.irq_shutdown	= nmk_gpio_irq_shutdown,
 };
 
 static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
@@ -726,7 +764,11 @@
 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);
+	u32 status;
+
+	clk_enable(nmk_chip->clk);
+	status = readl(nmk_chip->addr + NMK_GPIO_IS);
+	clk_disable(nmk_chip->clk);
 
 	__nmk_gpio_irq_handler(irq, desc, status);
 }
@@ -772,7 +814,12 @@
 	struct nmk_gpio_chip *nmk_chip =
 		container_of(chip, struct nmk_gpio_chip, chip);
 
+	clk_enable(nmk_chip->clk);
+
 	writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
+
+	clk_disable(nmk_chip->clk);
+
 	return 0;
 }
 
@@ -781,8 +828,15 @@
 	struct nmk_gpio_chip *nmk_chip =
 		container_of(chip, struct nmk_gpio_chip, chip);
 	u32 bit = 1 << offset;
+	int value;
 
-	return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
+	clk_enable(nmk_chip->clk);
+
+	value = (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
+
+	clk_disable(nmk_chip->clk);
+
+	return value;
 }
 
 static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
@@ -791,7 +845,11 @@
 	struct nmk_gpio_chip *nmk_chip =
 		container_of(chip, struct nmk_gpio_chip, chip);
 
+	clk_enable(nmk_chip->clk);
+
 	__nmk_gpio_set_output(nmk_chip, offset, val);
+
+	clk_disable(nmk_chip->clk);
 }
 
 static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
@@ -800,8 +858,12 @@
 	struct nmk_gpio_chip *nmk_chip =
 		container_of(chip, struct nmk_gpio_chip, chip);
 
+	clk_enable(nmk_chip->clk);
+
 	__nmk_gpio_make_output(nmk_chip, offset, val);
 
+	clk_disable(nmk_chip->clk);
+
 	return 0;
 }
 
@@ -832,6 +894,8 @@
 		[NMK_GPIO_ALT_C]	= "altC",
 	};
 
+	clk_enable(nmk_chip->clk);
+
 	for (i = 0; i < chip->ngpio; i++, gpio++) {
 		const char *label = gpiochip_is_requested(chip, i);
 		bool pull;
@@ -876,6 +940,8 @@
 
 		seq_printf(s, "\n");
 	}
+
+	clk_disable(nmk_chip->clk);
 }
 
 #else
@@ -893,6 +959,34 @@
 	.can_sleep		= 0,
 };
 
+void nmk_gpio_clocks_enable(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+		if (!chip)
+			continue;
+
+		clk_enable(chip->clk);
+	}
+}
+
+void nmk_gpio_clocks_disable(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+		if (!chip)
+			continue;
+
+		clk_disable(chip->clk);
+	}
+}
+
 /*
  * 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,
@@ -912,6 +1006,8 @@
 		if (!chip)
 			break;
 
+		clk_enable(chip->clk);
+
 		chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC);
 		chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC);
 
@@ -926,6 +1022,8 @@
 			/* 0 -> wakeup enable */
 			writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC);
 		}
+
+		clk_disable(chip->clk);
 	}
 }
 
@@ -939,11 +1037,15 @@
 		if (!chip)
 			break;
 
+		clk_enable(chip->clk);
+
 		writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC);
 		writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC);
 
 		if (chip->sleepmode)
 			writel(chip->slpm, chip->addr + NMK_GPIO_SLPC);
+
+		clk_disable(chip->clk);
 	}
 }
 
@@ -1010,8 +1112,6 @@
 		goto out_release;
 	}
 
-	clk_enable(clk);
-
 	nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL);
 	if (!nmk_chip) {
 		ret = -ENOMEM;
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-omap.c linux-libre-3.2-gnu/drivers/gpio/gpio-omap.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-omap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-omap.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,7 +25,7 @@
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <mach/irqs.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
 #include <asm/mach/irq.h>
 
 struct gpio_bank {
@@ -148,13 +148,17 @@
 	return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0;
 }
 
-#define MOD_REG_BIT(reg, bit_mask, set)	\
-do {	\
-	int l = __raw_readl(base + reg); \
-	if (set) l |= bit_mask; \
-	else l &= ~bit_mask; \
-	__raw_writel(l, base + reg); \
-} while(0)
+static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
+{
+	int l = __raw_readl(base + reg);
+
+	if (set) 
+		l |= mask;
+	else
+		l &= ~mask;
+
+	__raw_writel(l, base + reg);
+}
 
 /**
  * _set_gpio_debounce - low level gpio debounce time
@@ -210,28 +214,28 @@
 	u32 gpio_bit = 1 << gpio;
 
 	if (cpu_is_omap44xx()) {
-		MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT0, gpio_bit,
-			trigger & IRQ_TYPE_LEVEL_LOW);
-		MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT1, gpio_bit,
-			trigger & IRQ_TYPE_LEVEL_HIGH);
-		MOD_REG_BIT(OMAP4_GPIO_RISINGDETECT, gpio_bit,
-			trigger & IRQ_TYPE_EDGE_RISING);
-		MOD_REG_BIT(OMAP4_GPIO_FALLINGDETECT, gpio_bit,
-			trigger & IRQ_TYPE_EDGE_FALLING);
+		_gpio_rmw(base, OMAP4_GPIO_LEVELDETECT0, gpio_bit,
+			  trigger & IRQ_TYPE_LEVEL_LOW);
+		_gpio_rmw(base, OMAP4_GPIO_LEVELDETECT1, gpio_bit,
+			  trigger & IRQ_TYPE_LEVEL_HIGH);
+		_gpio_rmw(base, OMAP4_GPIO_RISINGDETECT, gpio_bit,
+			  trigger & IRQ_TYPE_EDGE_RISING);
+		_gpio_rmw(base, OMAP4_GPIO_FALLINGDETECT, gpio_bit,
+			  trigger & IRQ_TYPE_EDGE_FALLING);
 	} else {
-		MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
-			trigger & IRQ_TYPE_LEVEL_LOW);
-		MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
-			trigger & IRQ_TYPE_LEVEL_HIGH);
-		MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
-			trigger & IRQ_TYPE_EDGE_RISING);
-		MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
-			trigger & IRQ_TYPE_EDGE_FALLING);
+		_gpio_rmw(base, OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
+			  trigger & IRQ_TYPE_LEVEL_LOW);
+		_gpio_rmw(base, OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
+			  trigger & IRQ_TYPE_LEVEL_HIGH);
+		_gpio_rmw(base, OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
+			  trigger & IRQ_TYPE_EDGE_RISING);
+		_gpio_rmw(base, OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
+			  trigger & IRQ_TYPE_EDGE_FALLING);
 	}
 	if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
 		if (cpu_is_omap44xx()) {
-			MOD_REG_BIT(OMAP4_GPIO_IRQWAKEN0, gpio_bit,
-				trigger != 0);
+			_gpio_rmw(base, OMAP4_GPIO_IRQWAKEN0, gpio_bit,
+				  trigger != 0);
 		} else {
 			/*
 			 * GPIO wakeup request can only be generated on edge
@@ -1086,6 +1090,11 @@
 
 	gc = irq_alloc_generic_chip("MPUIO", 1, irq_start, bank->base,
 				    handle_simple_irq);
+	if (!gc) {
+		dev_err(bank->dev, "Memory alloc failed for gc\n");
+		return;
+	}
+
 	ct = gc->chip_types;
 
 	/* NOTE: No ack required, reading IRQ status clears it. */
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-pca953x.c linux-libre-3.2-gnu/drivers/gpio/gpio-pca953x.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-pca953x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-pca953x.c	2012-01-04 18:55:44.000000000 -0500
@@ -546,7 +546,7 @@
  * Translate OpenFirmware node properties into platform_data
  * WARNING: This is DEPRECATED and will be removed eventually!
  */
-void
+static void
 pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
 {
 	struct device_node *node;
@@ -574,7 +574,7 @@
 		*invert = *val;
 }
 #else
-void
+static void
 pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
 {
 	*gpio_base = -1;
@@ -596,9 +596,6 @@
 
 	/* set platform specific polarity inversion */
 	ret = pca953x_write_reg(chip, PCA953X_INVERT, invert);
-	if (ret)
-		goto out;
-	return 0;
 out:
 	return ret;
 }
@@ -640,7 +637,7 @@
 	struct pca953x_platform_data *pdata;
 	struct pca953x_chip *chip;
 	int irq_base=0, invert=0;
-	int ret = 0;
+	int ret;
 
 	chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
 	if (chip == NULL)
@@ -673,10 +670,10 @@
 	pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
 
 	if (chip->chip_type == PCA953X_TYPE)
-		device_pca953x_init(chip, invert);
-	else if (chip->chip_type == PCA957X_TYPE)
-		device_pca957x_init(chip, invert);
+		ret = device_pca953x_init(chip, invert);
 	else
+		ret = device_pca957x_init(chip, invert);
+	if (ret)
 		goto out_failed;
 
 	ret = pca953x_irq_setup(chip, id, irq_base);
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-pcf857x.c linux-libre-3.2-gnu/drivers/gpio/gpio-pcf857x.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-pcf857x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-pcf857x.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pcf857x.h>
+#include <linux/module.h>
 
 
 static const struct i2c_device_id pcf857x_id[] = {
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-pch.c linux-libre-3.2-gnu/drivers/gpio/gpio-pch.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-pch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-pch.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,12 +14,21 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  */
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 
-#define PCH_GPIO_ALL_PINS	0xfff /* Mask for GPIO pins 0 to 11 */
-#define GPIO_NUM_PINS	12	/* Specifies number of GPIO PINS GPIO0-GPIO11 */
+#define PCH_EDGE_FALLING	0
+#define PCH_EDGE_RISING		BIT(0)
+#define PCH_LEVEL_L		BIT(1)
+#define PCH_LEVEL_H		(BIT(0) | BIT(1))
+#define PCH_EDGE_BOTH		BIT(2)
+#define PCH_IM_MASK		(BIT(0) | BIT(1) | BIT(2))
+
+#define PCH_IRQ_BASE		24
 
 struct pch_regs {
 	u32	ien;
@@ -33,18 +42,43 @@
 	u32	pm;
 	u32	im0;
 	u32	im1;
-	u32	reserved[4];
+	u32	reserved[3];
+	u32	gpio_use_sel;
 	u32	reset;
 };
 
+enum pch_type_t {
+	INTEL_EG20T_PCH,
+	OKISEMI_ML7223m_IOH, /* OKISEMI ML7223 IOH PCIe Bus-m */
+	OKISEMI_ML7223n_IOH  /* OKISEMI ML7223 IOH PCIe Bus-n */
+};
+
+/* Specifies number of GPIO PINS */
+static int gpio_pins[] = {
+	[INTEL_EG20T_PCH] = 12,
+	[OKISEMI_ML7223m_IOH] = 8,
+	[OKISEMI_ML7223n_IOH] = 8,
+};
+
 /**
  * struct pch_gpio_reg_data - The register store data.
+ * @ien_reg:	To store contents of IEN register.
+ * @imask_reg:	To store contents of IMASK register.
  * @po_reg:	To store contents of PO register.
  * @pm_reg:	To store contents of PM register.
+ * @im0_reg:	To store contents of IM0 register.
+ * @im1_reg:	To store contents of IM1 register.
+ * @gpio_use_sel_reg : To store contents of GPIO_USE_SEL register.
+ *		       (Only ML7223 Bus-n)
  */
 struct pch_gpio_reg_data {
+	u32 ien_reg;
+	u32 imask_reg;
 	u32 po_reg;
 	u32 pm_reg;
+	u32 im0_reg;
+	u32 im1_reg;
+	u32 gpio_use_sel_reg;
 };
 
 /**
@@ -55,6 +89,12 @@
  * @gpio:			Data for GPIO infrastructure.
  * @pch_gpio_reg:		Memory mapped Register data is saved here
  *				when suspend.
+ * @lock:			Used for register access protection
+ * @irq_base:		Save base of IRQ number for interrupt
+ * @ioh:		IOH ID
+ * @spinlock:		Used for register access protection in
+ *				interrupt context pch_irq_mask,
+ *				pch_irq_unmask and pch_irq_type;
  */
 struct pch_gpio {
 	void __iomem *base;
@@ -63,6 +103,9 @@
 	struct gpio_chip gpio;
 	struct pch_gpio_reg_data pch_gpio_reg;
 	struct mutex lock;
+	int irq_base;
+	enum pch_type_t ioh;
+	spinlock_t spinlock;
 };
 
 static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
@@ -96,7 +139,7 @@
 	u32 reg_val;
 
 	mutex_lock(&chip->lock);
-	pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS;
+	pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
 	pm |= (1 << nr);
 	iowrite32(pm, &chip->reg->pm);
 
@@ -118,7 +161,7 @@
 	u32 pm;
 
 	mutex_lock(&chip->lock);
-	pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS; /*bits 0-11*/
+	pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
 	pm &= ~(1 << nr);
 	iowrite32(pm, &chip->reg->pm);
 	mutex_unlock(&chip->lock);
@@ -131,8 +174,16 @@
  */
 static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
 {
+	chip->pch_gpio_reg.ien_reg = ioread32(&chip->reg->ien);
+	chip->pch_gpio_reg.imask_reg = ioread32(&chip->reg->imask);
 	chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
 	chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
+	chip->pch_gpio_reg.im0_reg = ioread32(&chip->reg->im0);
+	if (chip->ioh == INTEL_EG20T_PCH)
+		chip->pch_gpio_reg.im1_reg = ioread32(&chip->reg->im1);
+	if (chip->ioh == OKISEMI_ML7223n_IOH)
+		chip->pch_gpio_reg.gpio_use_sel_reg =\
+					    ioread32(&chip->reg->gpio_use_sel);
 }
 
 /*
@@ -140,10 +191,24 @@
  */
 static void pch_gpio_restore_reg_conf(struct pch_gpio *chip)
 {
+	iowrite32(chip->pch_gpio_reg.ien_reg, &chip->reg->ien);
+	iowrite32(chip->pch_gpio_reg.imask_reg, &chip->reg->imask);
 	/* to store contents of PO register */
 	iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
 	/* to store contents of PM register */
 	iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm);
+	iowrite32(chip->pch_gpio_reg.im0_reg, &chip->reg->im0);
+	if (chip->ioh == INTEL_EG20T_PCH)
+		iowrite32(chip->pch_gpio_reg.im1_reg, &chip->reg->im1);
+	if (chip->ioh == OKISEMI_ML7223n_IOH)
+		iowrite32(chip->pch_gpio_reg.gpio_use_sel_reg,
+			  &chip->reg->gpio_use_sel);
+}
+
+static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
+{
+	struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
+	return chip->irq_base + offset;
 }
 
 static void pch_gpio_setup(struct pch_gpio *chip)
@@ -158,8 +223,132 @@
 	gpio->set = pch_gpio_set;
 	gpio->dbg_show = NULL;
 	gpio->base = -1;
-	gpio->ngpio = GPIO_NUM_PINS;
+	gpio->ngpio = gpio_pins[chip->ioh];
 	gpio->can_sleep = 0;
+	gpio->to_irq = pch_gpio_to_irq;
+}
+
+static int pch_irq_type(struct irq_data *d, unsigned int type)
+{
+	u32 im;
+	u32 *im_reg;
+	u32 ien;
+	u32 im_pos;
+	int ch;
+	unsigned long flags;
+	u32 val;
+	int irq = d->irq;
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct pch_gpio *chip = gc->private;
+
+	ch = irq - chip->irq_base;
+	if (irq <= chip->irq_base + 7) {
+		im_reg = &chip->reg->im0;
+		im_pos = ch;
+	} else {
+		im_reg = &chip->reg->im1;
+		im_pos = ch - 8;
+	}
+	dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d\n",
+		__func__, irq, type, ch, im_pos);
+
+	spin_lock_irqsave(&chip->spinlock, flags);
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		val = PCH_EDGE_RISING;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		val = PCH_EDGE_FALLING;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		val = PCH_EDGE_BOTH;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		val = PCH_LEVEL_H;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		val = PCH_LEVEL_L;
+		break;
+	case IRQ_TYPE_PROBE:
+		goto end;
+	default:
+		dev_warn(chip->dev, "%s: unknown type(%dd)",
+			__func__, type);
+		goto end;
+	}
+
+	/* Set interrupt mode */
+	im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4));
+	iowrite32(im | (val << (im_pos * 4)), im_reg);
+
+	/* iclr */
+	iowrite32(BIT(ch), &chip->reg->iclr);
+
+	/* IMASKCLR */
+	iowrite32(BIT(ch), &chip->reg->imaskclr);
+
+	/* Enable interrupt */
+	ien = ioread32(&chip->reg->ien);
+	iowrite32(ien | BIT(ch), &chip->reg->ien);
+end:
+	spin_unlock_irqrestore(&chip->spinlock, flags);
+
+	return 0;
+}
+
+static void pch_irq_unmask(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct pch_gpio *chip = gc->private;
+
+	iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imaskclr);
+}
+
+static void pch_irq_mask(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct pch_gpio *chip = gc->private;
+
+	iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imask);
+}
+
+static irqreturn_t pch_gpio_handler(int irq, void *dev_id)
+{
+	struct pch_gpio *chip = dev_id;
+	u32 reg_val = ioread32(&chip->reg->istatus);
+	int i;
+	int ret = IRQ_NONE;
+
+	for (i = 0; i < gpio_pins[chip->ioh]; i++) {
+		if (reg_val & BIT(i)) {
+			dev_dbg(chip->dev, "%s:[%d]:irq=%d  status=0x%x\n",
+				__func__, i, irq, reg_val);
+			iowrite32(BIT(i), &chip->reg->iclr);
+			generic_handle_irq(chip->irq_base + i);
+			ret = IRQ_HANDLED;
+		}
+	}
+	return ret;
+}
+
+static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
+				unsigned int irq_start, unsigned int num)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+
+	gc = irq_alloc_generic_chip("pch_gpio", 1, irq_start, chip->base,
+				    handle_simple_irq);
+	gc->private = chip;
+	ct = gc->chip_types;
+
+	ct->chip.irq_mask = pch_irq_mask;
+	ct->chip.irq_unmask = pch_irq_unmask;
+	ct->chip.irq_set_type = pch_irq_type;
+
+	irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
+			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 }
 
 static int __devinit pch_gpio_probe(struct pci_dev *pdev,
@@ -167,6 +356,7 @@
 {
 	s32 ret;
 	struct pch_gpio *chip;
+	int irq_base;
 
 	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
@@ -192,6 +382,13 @@
 		goto err_iomap;
 	}
 
+	if (pdev->device == 0x8803)
+		chip->ioh = INTEL_EG20T_PCH;
+	else if (pdev->device == 0x8014)
+		chip->ioh = OKISEMI_ML7223m_IOH;
+	else if (pdev->device == 0x8043)
+		chip->ioh = OKISEMI_ML7223n_IOH;
+
 	chip->reg = chip->base;
 	pci_set_drvdata(pdev, chip);
 	mutex_init(&chip->lock);
@@ -202,8 +399,36 @@
 		goto err_gpiochip_add;
 	}
 
+	irq_base = irq_alloc_descs(-1, 0, gpio_pins[chip->ioh], NUMA_NO_NODE);
+	if (irq_base < 0) {
+		dev_warn(&pdev->dev, "PCH gpio: Failed to get IRQ base num\n");
+		chip->irq_base = -1;
+		goto end;
+	}
+	chip->irq_base = irq_base;
+
+	ret = request_irq(pdev->irq, pch_gpio_handler,
+			     IRQF_SHARED, KBUILD_MODNAME, chip);
+	if (ret != 0) {
+		dev_err(&pdev->dev,
+			"%s request_irq failed\n", __func__);
+		goto err_request_irq;
+	}
+
+	pch_gpio_alloc_generic_chip(chip, irq_base, gpio_pins[chip->ioh]);
+
+	/* Initialize interrupt ien register */
+	iowrite32(0, &chip->reg->ien);
+end:
 	return 0;
 
+err_request_irq:
+	irq_free_descs(irq_base, gpio_pins[chip->ioh]);
+
+	ret = gpiochip_remove(&chip->gpio);
+	if (ret)
+		dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
+
 err_gpiochip_add:
 	pci_iounmap(pdev, chip->base);
 
@@ -224,6 +449,12 @@
 	int err;
 	struct pch_gpio *chip = pci_get_drvdata(pdev);
 
+	if (chip->irq_base != -1) {
+		free_irq(pdev->irq, chip);
+
+		irq_free_descs(chip->irq_base, gpio_pins[chip->ioh]);
+	}
+
 	err = gpiochip_remove(&chip->gpio);
 	if (err)
 		dev_err(&pdev->dev, "Failed gpiochip_remove\n");
@@ -239,9 +470,11 @@
 {
 	s32 ret;
 	struct pch_gpio *chip = pci_get_drvdata(pdev);
+	unsigned long flags;
 
+	spin_lock_irqsave(&chip->spinlock, flags);
 	pch_gpio_save_reg_conf(chip);
-	pch_gpio_restore_reg_conf(chip);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 
 	ret = pci_save_state(pdev);
 	if (ret) {
@@ -261,6 +494,7 @@
 {
 	s32 ret;
 	struct pch_gpio *chip = pci_get_drvdata(pdev);
+	unsigned long flags;
 
 	ret = pci_enable_wake(pdev, PCI_D0, 0);
 
@@ -272,9 +506,11 @@
 	}
 	pci_restore_state(pdev);
 
+	spin_lock_irqsave(&chip->spinlock, flags);
 	iowrite32(0x01, &chip->reg->reset);
 	iowrite32(0x00, &chip->reg->reset);
 	pch_gpio_restore_reg_conf(chip);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 
 	return 0;
 }
@@ -287,6 +523,7 @@
 static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) },
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-pl061.c linux-libre-3.2-gnu/drivers/gpio/gpio-pl061.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-pl061.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-pl061.c	2012-01-04 18:55:44.000000000 -0500
@@ -118,7 +118,7 @@
 {
 	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
 
-	if (chip->irq_base == (unsigned) -1)
+	if (chip->irq_base == NO_IRQ)
 		return -EINVAL;
 
 	return chip->irq_base + offset;
@@ -238,14 +238,22 @@
 	int ret, irq, i;
 	static DECLARE_BITMAP(init_irq, NR_IRQS);
 
-	pdata = dev->dev.platform_data;
-	if (pdata == NULL)
-		return -ENODEV;
-
 	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
+	pdata = dev->dev.platform_data;
+	if (pdata) {
+		chip->gc.base = pdata->gpio_base;
+		chip->irq_base = pdata->irq_base;
+	} else if (dev->dev.of_node) {
+		chip->gc.base = -1;
+		chip->irq_base = NO_IRQ;
+	} else {
+		ret = -ENODEV;
+		goto free_mem;
+	}
+
 	if (!request_mem_region(dev->res.start,
 				resource_size(&dev->res), "pl061")) {
 		ret = -EBUSY;
@@ -267,14 +275,11 @@
 	chip->gc.get = pl061_get_value;
 	chip->gc.set = pl061_set_value;
 	chip->gc.to_irq = pl061_to_irq;
-	chip->gc.base = pdata->gpio_base;
 	chip->gc.ngpio = PL061_GPIO_NR;
 	chip->gc.label = dev_name(&dev->dev);
 	chip->gc.dev = &dev->dev;
 	chip->gc.owner = THIS_MODULE;
 
-	chip->irq_base = pdata->irq_base;
-
 	ret = gpiochip_add(&chip->gc);
 	if (ret)
 		goto iounmap;
@@ -283,7 +288,7 @@
 	 * irq_chip support
 	 */
 
-	if (chip->irq_base == (unsigned) -1)
+	if (chip->irq_base == NO_IRQ)
 		return 0;
 
 	writeb(0, chip->base + GPIOIE); /* disable irqs */
@@ -307,11 +312,13 @@
 	list_add(&chip->list, chip_list);
 
 	for (i = 0; i < PL061_GPIO_NR; i++) {
-		if (pdata->directions & (1 << i))
-			pl061_direction_output(&chip->gc, i,
-					pdata->values & (1 << i));
-		else
-			pl061_direction_input(&chip->gc, i);
+		if (pdata) {
+			if (pdata->directions & (1 << i))
+				pl061_direction_output(&chip->gc, i,
+						pdata->values & (1 << i));
+			else
+				pl061_direction_input(&chip->gc, i);
+		}
 
 		irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip,
 					 handle_simple_irq);
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-plat-samsung.c linux-libre-3.2-gnu/drivers/gpio/gpio-plat-samsung.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-plat-samsung.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-plat-samsung.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,205 +0,0 @@
-/*
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * SAMSUNG - 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 <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-#ifndef DEBUG_GPIO
-#define gpio_dbg(x...) do { } while (0)
-#else
-#define gpio_dbg(x...) printk(KERN_DEBUG x)
-#endif
-
-/* The samsung_gpiolib_4bit routines are to control the gpio banks where
- * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
- * following example:
- *
- * base + 0x00: Control register, 4 bits per gpio
- *		gpio n: 4 bits starting at (4*n)
- *		0000 = input, 0001 = output, others mean special-function
- * base + 0x04: Data register, 1 bit per gpio
- *		bit n: data bit n
- *
- * Note, since the data register is one bit per gpio and is at base + 0x4
- * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
- * the output.
-*/
-
-static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
-				      unsigned int offset)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long con;
-
-	con = __raw_readl(base + GPIOCON_OFF);
-	con &= ~(0xf << con_4bit_shift(offset));
-	__raw_writel(con, base + GPIOCON_OFF);
-
-	gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
-
-	return 0;
-}
-
-static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
-				       unsigned int offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long con;
-	unsigned long dat;
-
-	con = __raw_readl(base + GPIOCON_OFF);
-	con &= ~(0xf << con_4bit_shift(offset));
-	con |= 0x1 << con_4bit_shift(offset);
-
-	dat = __raw_readl(base + GPIODAT_OFF);
-
-	if (value)
-		dat |= 1 << offset;
-	else
-		dat &= ~(1 << offset);
-
-	__raw_writel(dat, base + GPIODAT_OFF);
-	__raw_writel(con, base + GPIOCON_OFF);
-	__raw_writel(dat, base + GPIODAT_OFF);
-
-	gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
-
-	return 0;
-}
-
-/* The next set of routines are for the case where the GPIO configuration
- * registers are 4 bits per GPIO but there is more than one register (the
- * bank has more than 8 GPIOs.
- *
- * This case is the similar to the 4 bit case, but the registers are as
- * follows:
- *
- * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
- *		gpio n: 4 bits starting at (4*n)
- *		0000 = input, 0001 = output, others mean special-function
- * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
- *		gpio n: 4 bits starting at (4*n)
- *		0000 = input, 0001 = output, others mean special-function
- * base + 0x08: Data register, 1 bit per gpio
- *		bit n: data bit n
- *
- * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
- * store the 'base + 0x4' address so that these routines see the data
- * register at ourchip->base + 0x04.
- */
-
-static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
-				       unsigned int offset)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	void __iomem *regcon = base;
-	unsigned long con;
-
-	if (offset > 7)
-		offset -= 8;
-	else
-		regcon -= 4;
-
-	con = __raw_readl(regcon);
-	con &= ~(0xf << con_4bit_shift(offset));
-	__raw_writel(con, regcon);
-
-	gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
-
-	return 0;
-}
-
-static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
-					unsigned int offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	void __iomem *regcon = base;
-	unsigned long con;
-	unsigned long dat;
-	unsigned con_offset = offset;
-
-	if (con_offset > 7)
-		con_offset -= 8;
-	else
-		regcon -= 4;
-
-	con = __raw_readl(regcon);
-	con &= ~(0xf << con_4bit_shift(con_offset));
-	con |= 0x1 << con_4bit_shift(con_offset);
-
-	dat = __raw_readl(base + GPIODAT_OFF);
-
-	if (value)
-		dat |= 1 << offset;
-	else
-		dat &= ~(1 << offset);
-
-	__raw_writel(dat, base + GPIODAT_OFF);
-	__raw_writel(con, regcon);
-	__raw_writel(dat, base + GPIODAT_OFF);
-
-	gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
-
-	return 0;
-}
-
-void __init samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
-{
-	chip->chip.direction_input = samsung_gpiolib_4bit_input;
-	chip->chip.direction_output = samsung_gpiolib_4bit_output;
-	chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
-}
-
-void __init samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
-{
-	chip->chip.direction_input = samsung_gpiolib_4bit2_input;
-	chip->chip.direction_output = samsung_gpiolib_4bit2_output;
-	chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
-}
-
-void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
-					   int nr_chips)
-{
-	for (; nr_chips > 0; nr_chips--, chip++) {
-		samsung_gpiolib_add_4bit(chip);
-		s3c_gpiolib_add(chip);
-	}
-}
-
-void __init samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
-					    int nr_chips)
-{
-	for (; nr_chips > 0; nr_chips--, chip++) {
-		samsung_gpiolib_add_4bit2(chip);
-		s3c_gpiolib_add(chip);
-	}
-}
-
-void __init samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
-					   int nr_chips)
-{
-	for (; nr_chips > 0; nr_chips--, chip++)
-		s3c_gpiolib_add(chip);
-}
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-pxa.c linux-libre-3.2-gnu/drivers/gpio/gpio-pxa.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-pxa.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-pxa.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,338 @@
+/*
+ *  linux/arch/arm/plat-pxa/gpio.c
+ *
+ *  Generic PXA GPIO handling
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/syscore_ops.h>
+#include <linux/slab.h>
+
+#include <mach/gpio-pxa.h>
+
+int pxa_last_gpio;
+
+struct pxa_gpio_chip {
+	struct gpio_chip chip;
+	void __iomem	*regbase;
+	char label[10];
+
+	unsigned long	irq_mask;
+	unsigned long	irq_edge_rise;
+	unsigned long	irq_edge_fall;
+
+#ifdef CONFIG_PM
+	unsigned long	saved_gplr;
+	unsigned long	saved_gpdr;
+	unsigned long	saved_grer;
+	unsigned long	saved_gfer;
+#endif
+};
+
+static DEFINE_SPINLOCK(gpio_lock);
+static struct pxa_gpio_chip *pxa_gpio_chips;
+
+#define for_each_gpio_chip(i, c)			\
+	for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++)
+
+static inline void __iomem *gpio_chip_base(struct gpio_chip *c)
+{
+	return container_of(c, struct pxa_gpio_chip, chip)->regbase;
+}
+
+static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio)
+{
+	return &pxa_gpio_chips[gpio_to_bank(gpio)];
+}
+
+static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	void __iomem *base = gpio_chip_base(chip);
+	uint32_t value, mask = 1 << offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	value = __raw_readl(base + GPDR_OFFSET);
+	if (__gpio_is_inverted(chip->base + offset))
+		value |= mask;
+	else
+		value &= ~mask;
+	__raw_writel(value, base + GPDR_OFFSET);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+	return 0;
+}
+
+static int pxa_gpio_direction_output(struct gpio_chip *chip,
+				     unsigned offset, int value)
+{
+	void __iomem *base = gpio_chip_base(chip);
+	uint32_t tmp, mask = 1 << offset;
+	unsigned long flags;
+
+	__raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	tmp = __raw_readl(base + GPDR_OFFSET);
+	if (__gpio_is_inverted(chip->base + offset))
+		tmp &= ~mask;
+	else
+		tmp |= mask;
+	__raw_writel(tmp, base + GPDR_OFFSET);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+	return 0;
+}
+
+static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset);
+}
+
+static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	__raw_writel(1 << offset, gpio_chip_base(chip) +
+				(value ? GPSR_OFFSET : GPCR_OFFSET));
+}
+
+static int __init pxa_init_gpio_chip(int gpio_end)
+{
+	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
+	struct pxa_gpio_chip *chips;
+
+	chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL);
+	if (chips == NULL) {
+		pr_err("%s: failed to allocate GPIO chips\n", __func__);
+		return -ENOMEM;
+	}
+
+	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
+		struct gpio_chip *c = &chips[i].chip;
+
+		sprintf(chips[i].label, "gpio-%d", i);
+		chips[i].regbase = GPIO_BANK(i);
+
+		c->base  = gpio;
+		c->label = chips[i].label;
+
+		c->direction_input  = pxa_gpio_direction_input;
+		c->direction_output = pxa_gpio_direction_output;
+		c->get = pxa_gpio_get;
+		c->set = pxa_gpio_set;
+
+		/* number of GPIOs on last bank may be less than 32 */
+		c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32;
+		gpiochip_add(c);
+	}
+	pxa_gpio_chips = chips;
+	return 0;
+}
+
+/* Update only those GRERx and GFERx edge detection register bits if those
+ * bits are set in c->irq_mask
+ */
+static inline void update_edge_detect(struct pxa_gpio_chip *c)
+{
+	uint32_t grer, gfer;
+
+	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask;
+	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask;
+	grer |= c->irq_edge_rise & c->irq_mask;
+	gfer |= c->irq_edge_fall & c->irq_mask;
+	__raw_writel(grer, c->regbase + GRER_OFFSET);
+	__raw_writel(gfer, c->regbase + GFER_OFFSET);
+}
+
+static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
+{
+	struct pxa_gpio_chip *c;
+	int gpio = irq_to_gpio(d->irq);
+	unsigned long gpdr, mask = GPIO_bit(gpio);
+
+	c = gpio_to_pxachip(gpio);
+
+	if (type == IRQ_TYPE_PROBE) {
+		/* Don't mess with enabled GPIOs using preconfigured edges or
+		 * GPIOs set to alternate function or to output during probe
+		 */
+		if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio))
+			return 0;
+
+		if (__gpio_is_occupied(gpio))
+			return 0;
+
+		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+	}
+
+	gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
+
+	if (__gpio_is_inverted(gpio))
+		__raw_writel(gpdr | mask,  c->regbase + GPDR_OFFSET);
+	else
+		__raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		c->irq_edge_rise |= mask;
+	else
+		c->irq_edge_rise &= ~mask;
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		c->irq_edge_fall |= mask;
+	else
+		c->irq_edge_fall &= ~mask;
+
+	update_edge_detect(c);
+
+	pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, d->irq, gpio,
+		((type & IRQ_TYPE_EDGE_RISING)  ? " rising"  : ""),
+		((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : ""));
+	return 0;
+}
+
+static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct pxa_gpio_chip *c;
+	int loop, gpio, gpio_base, n;
+	unsigned long gedr;
+
+	do {
+		loop = 0;
+		for_each_gpio_chip(gpio, c) {
+			gpio_base = c->chip.base;
+
+			gedr = __raw_readl(c->regbase + GEDR_OFFSET);
+			gedr = gedr & c->irq_mask;
+			__raw_writel(gedr, c->regbase + GEDR_OFFSET);
+
+			n = find_first_bit(&gedr, BITS_PER_LONG);
+			while (n < BITS_PER_LONG) {
+				loop = 1;
+
+				generic_handle_irq(gpio_to_irq(gpio_base + n));
+				n = find_next_bit(&gedr, BITS_PER_LONG, n + 1);
+			}
+		}
+	} while (loop);
+}
+
+static void pxa_ack_muxed_gpio(struct irq_data *d)
+{
+	int gpio = irq_to_gpio(d->irq);
+	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+
+	__raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET);
+}
+
+static void pxa_mask_muxed_gpio(struct irq_data *d)
+{
+	int gpio = irq_to_gpio(d->irq);
+	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+	uint32_t grer, gfer;
+
+	c->irq_mask &= ~GPIO_bit(gpio);
+
+	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio);
+	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio);
+	__raw_writel(grer, c->regbase + GRER_OFFSET);
+	__raw_writel(gfer, c->regbase + GFER_OFFSET);
+}
+
+static void pxa_unmask_muxed_gpio(struct irq_data *d)
+{
+	int gpio = irq_to_gpio(d->irq);
+	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+
+	c->irq_mask |= GPIO_bit(gpio);
+	update_edge_detect(c);
+}
+
+static struct irq_chip pxa_muxed_gpio_chip = {
+	.name		= "GPIO",
+	.irq_ack	= pxa_ack_muxed_gpio,
+	.irq_mask	= pxa_mask_muxed_gpio,
+	.irq_unmask	= pxa_unmask_muxed_gpio,
+	.irq_set_type	= pxa_gpio_irq_type,
+};
+
+void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn)
+{
+	struct pxa_gpio_chip *c;
+	int gpio, irq;
+
+	pxa_last_gpio = end;
+
+	/* Initialize GPIO chips */
+	pxa_init_gpio_chip(end);
+
+	/* clear all GPIO edge detects */
+	for_each_gpio_chip(gpio, c) {
+		__raw_writel(0, c->regbase + GFER_OFFSET);
+		__raw_writel(0, c->regbase + GRER_OFFSET);
+		__raw_writel(~0,c->regbase + GEDR_OFFSET);
+	}
+
+	for (irq  = gpio_to_irq(start); irq <= gpio_to_irq(end); 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 */
+	irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler);
+	pxa_muxed_gpio_chip.irq_set_wake = fn;
+}
+
+#ifdef CONFIG_PM
+static int pxa_gpio_suspend(void)
+{
+	struct pxa_gpio_chip *c;
+	int gpio;
+
+	for_each_gpio_chip(gpio, c) {
+		c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET);
+		c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
+		c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET);
+		c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET);
+
+		/* Clear GPIO transition detect bits */
+		__raw_writel(0xffffffff, c->regbase + GEDR_OFFSET);
+	}
+	return 0;
+}
+
+static void pxa_gpio_resume(void)
+{
+	struct pxa_gpio_chip *c;
+	int gpio;
+
+	for_each_gpio_chip(gpio, c) {
+		/* restore level with set/clear */
+		__raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET);
+		__raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET);
+
+		__raw_writel(c->saved_grer, c->regbase + GRER_OFFSET);
+		__raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET);
+		__raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET);
+	}
+}
+#else
+#define pxa_gpio_suspend	NULL
+#define pxa_gpio_resume		NULL
+#endif
+
+struct syscore_ops pxa_gpio_syscore_ops = {
+	.suspend	= pxa_gpio_suspend,
+	.resume		= pxa_gpio_resume,
+};
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-s5pc100.c linux-libre-3.2-gnu/drivers/gpio/gpio-s5pc100.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-s5pc100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-s5pc100.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,354 +0,0 @@
-/*
- * S5PC100 - GPIOlib support
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- *  Copyright 2009 Samsung Electronics Co
- *  Kyungmin Park <kyungmin.park@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/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-/* S5PC100 GPIO bank summary:
- *
- * Bank	GPIOs	Style	INT Type
- * A0	8	4Bit	GPIO_INT0
- * A1	5	4Bit	GPIO_INT1
- * B	8	4Bit	GPIO_INT2
- * C	5	4Bit	GPIO_INT3
- * D	7	4Bit	GPIO_INT4
- * E0	8	4Bit	GPIO_INT5
- * E1	6	4Bit	GPIO_INT6
- * F0	8	4Bit	GPIO_INT7
- * F1	8	4Bit	GPIO_INT8
- * F2	8	4Bit	GPIO_INT9
- * F3	4	4Bit	GPIO_INT10
- * G0	8	4Bit	GPIO_INT11
- * G1	3	4Bit	GPIO_INT12
- * G2	7	4Bit	GPIO_INT13
- * G3	7	4Bit	GPIO_INT14
- * H0	8	4Bit	WKUP_INT
- * H1	8	4Bit	WKUP_INT
- * H2	8	4Bit	WKUP_INT
- * H3	8	4Bit	WKUP_INT
- * I	8	4Bit	GPIO_INT15
- * J0	8	4Bit	GPIO_INT16
- * J1	5	4Bit	GPIO_INT17
- * J2	8	4Bit	GPIO_INT18
- * J3	8	4Bit	GPIO_INT19
- * J4	4	4Bit	GPIO_INT20
- * K0	8	4Bit	None
- * K1	6	4Bit	None
- * K2	8	4Bit	None
- * K3	8	4Bit	None
- * L0	8	4Bit	None
- * L1	8	4Bit	None
- * L2	8	4Bit	None
- * L3	8	4Bit	None
- */
-
-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_eint = {
-	.cfg_eint	= 0xf,
-	.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,
-};
-
-/*
- * GPIO bank's base address given the index of the bank in the
- * list of all gpio banks.
- */
-#define S5PC100_BANK_BASE(bank_nr)	(S5P_VA_GPIO + ((bank_nr) * 0x20))
-
-/*
- * Following are the gpio banks in S5PC100.
- *
- * 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 s5pc100_gpio_chips[] = {
-	{
-		.chip	= {
-			.base	= S5PC100_GPA0(0),
-			.ngpio	= S5PC100_GPIO_A0_NR,
-			.label	= "GPA0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPA1(0),
-			.ngpio	= S5PC100_GPIO_A1_NR,
-			.label	= "GPA1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPB(0),
-			.ngpio	= S5PC100_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPC(0),
-			.ngpio	= S5PC100_GPIO_C_NR,
-			.label	= "GPC",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPD(0),
-			.ngpio	= S5PC100_GPIO_D_NR,
-			.label	= "GPD",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPE0(0),
-			.ngpio	= S5PC100_GPIO_E0_NR,
-			.label	= "GPE0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPE1(0),
-			.ngpio	= S5PC100_GPIO_E1_NR,
-			.label	= "GPE1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPF0(0),
-			.ngpio	= S5PC100_GPIO_F0_NR,
-			.label	= "GPF0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPF1(0),
-			.ngpio	= S5PC100_GPIO_F1_NR,
-			.label	= "GPF1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPF2(0),
-			.ngpio	= S5PC100_GPIO_F2_NR,
-			.label	= "GPF2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPF3(0),
-			.ngpio	= S5PC100_GPIO_F3_NR,
-			.label	= "GPF3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPG0(0),
-			.ngpio	= S5PC100_GPIO_G0_NR,
-			.label	= "GPG0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPG1(0),
-			.ngpio	= S5PC100_GPIO_G1_NR,
-			.label	= "GPG1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPG2(0),
-			.ngpio	= S5PC100_GPIO_G2_NR,
-			.label	= "GPG2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPG3(0),
-			.ngpio	= S5PC100_GPIO_G3_NR,
-			.label	= "GPG3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPI(0),
-			.ngpio	= S5PC100_GPIO_I_NR,
-			.label	= "GPI",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPJ0(0),
-			.ngpio	= S5PC100_GPIO_J0_NR,
-			.label	= "GPJ0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPJ1(0),
-			.ngpio	= S5PC100_GPIO_J1_NR,
-			.label	= "GPJ1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPJ2(0),
-			.ngpio	= S5PC100_GPIO_J2_NR,
-			.label	= "GPJ2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPJ3(0),
-			.ngpio	= S5PC100_GPIO_J3_NR,
-			.label	= "GPJ3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PC100_GPJ4(0),
-			.ngpio	= S5PC100_GPIO_J4_NR,
-			.label	= "GPJ4",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPK0(0),
-			.ngpio	= S5PC100_GPIO_K0_NR,
-			.label	= "GPK0",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPK1(0),
-			.ngpio	= S5PC100_GPIO_K1_NR,
-			.label	= "GPK1",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPK2(0),
-			.ngpio	= S5PC100_GPIO_K2_NR,
-			.label	= "GPK2",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPK3(0),
-			.ngpio	= S5PC100_GPIO_K3_NR,
-			.label	= "GPK3",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPL0(0),
-			.ngpio	= S5PC100_GPIO_L0_NR,
-			.label	= "GPL0",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPL1(0),
-			.ngpio	= S5PC100_GPIO_L1_NR,
-			.label	= "GPL1",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPL2(0),
-			.ngpio	= S5PC100_GPIO_L2_NR,
-			.label	= "GPL2",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPL3(0),
-			.ngpio	= S5PC100_GPIO_L3_NR,
-			.label	= "GPL3",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPL4(0),
-			.ngpio	= S5PC100_GPIO_L4_NR,
-			.label	= "GPL4",
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC00),
-		.config	= &gpio_cfg_eint,
-		.irq_base = IRQ_EINT(0),
-		.chip	= {
-			.base	= S5PC100_GPH0(0),
-			.ngpio	= S5PC100_GPIO_H0_NR,
-			.label	= "GPH0",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC20),
-		.config	= &gpio_cfg_eint,
-		.irq_base = IRQ_EINT(8),
-		.chip	= {
-			.base	= S5PC100_GPH1(0),
-			.ngpio	= S5PC100_GPIO_H1_NR,
-			.label	= "GPH1",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC40),
-		.config	= &gpio_cfg_eint,
-		.irq_base = IRQ_EINT(16),
-		.chip	= {
-			.base	= S5PC100_GPH2(0),
-			.ngpio	= S5PC100_GPIO_H2_NR,
-			.label	= "GPH2",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC60),
-		.config	= &gpio_cfg_eint,
-		.irq_base = IRQ_EINT(24),
-		.chip	= {
-			.base	= S5PC100_GPH3(0),
-			.ngpio	= S5PC100_GPIO_H3_NR,
-			.label	= "GPH3",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	},
-};
-
-static __init int s5pc100_gpiolib_init(void)
-{
-	struct s3c_gpio_chip *chip = s5pc100_gpio_chips;
-	int nr_chips = ARRAY_SIZE(s5pc100_gpio_chips);
-	int gpioint_group = 0;
-	int i;
-
-	for (i = 0; i < nr_chips; i++, chip++) {
-		if (chip->config == NULL) {
-			chip->config = &gpio_cfg;
-			chip->group = gpioint_group++;
-		}
-		if (chip->base == NULL)
-			chip->base = S5PC100_BANK_BASE(i);
-	}
-
-	samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, nr_chips);
-	s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
-
-	return 0;
-}
-core_initcall(s5pc100_gpiolib_init);
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-s5pv210.c linux-libre-3.2-gnu/drivers/gpio/gpio-s5pv210.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-s5pv210.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-s5pv210.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,287 +0,0 @@
-/*
- * S5PV210 - GPIOlib support
- *
- * 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/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-#include <mach/map.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,
-};
-
-/* GPIO bank's base address given the index of the bank in the
- * list of all gpio banks.
- */
-#define S5PV210_BANK_BASE(bank_nr)	(S5P_VA_GPIO + ((bank_nr) * 0x20))
-
-/*
- * Following are the gpio banks in v210.
- *
- * 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 s5pv210_gpio_4bit[] = {
-	{
-		.chip	= {
-			.base	= S5PV210_GPA0(0),
-			.ngpio	= S5PV210_GPIO_A0_NR,
-			.label	= "GPA0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPA1(0),
-			.ngpio	= S5PV210_GPIO_A1_NR,
-			.label	= "GPA1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPB(0),
-			.ngpio	= S5PV210_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPC0(0),
-			.ngpio	= S5PV210_GPIO_C0_NR,
-			.label	= "GPC0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPC1(0),
-			.ngpio	= S5PV210_GPIO_C1_NR,
-			.label	= "GPC1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPD0(0),
-			.ngpio	= S5PV210_GPIO_D0_NR,
-			.label	= "GPD0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPD1(0),
-			.ngpio	= S5PV210_GPIO_D1_NR,
-			.label	= "GPD1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPE0(0),
-			.ngpio	= S5PV210_GPIO_E0_NR,
-			.label	= "GPE0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPE1(0),
-			.ngpio	= S5PV210_GPIO_E1_NR,
-			.label	= "GPE1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPF0(0),
-			.ngpio	= S5PV210_GPIO_F0_NR,
-			.label	= "GPF0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPF1(0),
-			.ngpio	= S5PV210_GPIO_F1_NR,
-			.label	= "GPF1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPF2(0),
-			.ngpio	= S5PV210_GPIO_F2_NR,
-			.label	= "GPF2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPF3(0),
-			.ngpio	= S5PV210_GPIO_F3_NR,
-			.label	= "GPF3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPG0(0),
-			.ngpio	= S5PV210_GPIO_G0_NR,
-			.label	= "GPG0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPG1(0),
-			.ngpio	= S5PV210_GPIO_G1_NR,
-			.label	= "GPG1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPG2(0),
-			.ngpio	= S5PV210_GPIO_G2_NR,
-			.label	= "GPG2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPG3(0),
-			.ngpio	= S5PV210_GPIO_G3_NR,
-			.label	= "GPG3",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PV210_GPI(0),
-			.ngpio	= S5PV210_GPIO_I_NR,
-			.label	= "GPI",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPJ0(0),
-			.ngpio	= S5PV210_GPIO_J0_NR,
-			.label	= "GPJ0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPJ1(0),
-			.ngpio	= S5PV210_GPIO_J1_NR,
-			.label	= "GPJ1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPJ2(0),
-			.ngpio	= S5PV210_GPIO_J2_NR,
-			.label	= "GPJ2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPJ3(0),
-			.ngpio	= S5PV210_GPIO_J3_NR,
-			.label	= "GPJ3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV210_GPJ4(0),
-			.ngpio	= S5PV210_GPIO_J4_NR,
-			.label	= "GPJ4",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PV210_MP01(0),
-			.ngpio	= S5PV210_GPIO_MP01_NR,
-			.label	= "MP01",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PV210_MP02(0),
-			.ngpio	= S5PV210_GPIO_MP02_NR,
-			.label	= "MP02",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PV210_MP03(0),
-			.ngpio	= S5PV210_GPIO_MP03_NR,
-			.label	= "MP03",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PV210_MP04(0),
-			.ngpio	= S5PV210_GPIO_MP04_NR,
-			.label	= "MP04",
-		},
-	}, {
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PV210_MP05(0),
-			.ngpio	= S5PV210_GPIO_MP05_NR,
-			.label	= "MP05",
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC00),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(0),
-		.chip	= {
-			.base	= S5PV210_GPH0(0),
-			.ngpio	= S5PV210_GPIO_H0_NR,
-			.label	= "GPH0",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC20),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(8),
-		.chip	= {
-			.base	= S5PV210_GPH1(0),
-			.ngpio	= S5PV210_GPIO_H1_NR,
-			.label	= "GPH1",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC40),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(16),
-		.chip	= {
-			.base	= S5PV210_GPH2(0),
-			.ngpio	= S5PV210_GPIO_H2_NR,
-			.label	= "GPH2",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO + 0xC60),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(24),
-		.chip	= {
-			.base	= S5PV210_GPH3(0),
-			.ngpio	= S5PV210_GPIO_H3_NR,
-			.label	= "GPH3",
-			.to_irq = samsung_gpiolib_to_irq,
-		},
-	},
-};
-
-static __init int s5pv210_gpiolib_init(void)
-{
-	struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
-	int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
-	int gpioint_group = 0;
-	int i = 0;
-
-	for (i = 0; i < nr_chips; i++, chip++) {
-		if (chip->config == NULL) {
-			chip->config = &gpio_cfg;
-			chip->group = gpioint_group++;
-		}
-		if (chip->base == NULL)
-			chip->base = S5PV210_BANK_BASE(i);
-	}
-
-	samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
-	s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
-
-	return 0;
-}
-core_initcall(s5pv210_gpiolib_init);
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-sa1100.c linux-libre-3.2-gnu/drivers/gpio/gpio-sa1100.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-sa1100.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-sa1100.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,63 @@
+/*
+ * linux/arch/arm/mach-sa1100/gpio.c
+ *
+ * Generic SA-1100 GPIO handling
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <mach/hardware.h>
+
+static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	return GPLR & GPIO_GPIO(offset);
+}
+
+static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	if (value)
+		GPSR = GPIO_GPIO(offset);
+	else
+		GPCR = GPIO_GPIO(offset);
+}
+
+static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	GPDR &= ~GPIO_GPIO(offset);
+	local_irq_restore(flags);
+	return 0;
+}
+
+static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int value)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	sa1100_gpio_set(chip, offset, value);
+	GPDR |= GPIO_GPIO(offset);
+	local_irq_restore(flags);
+	return 0;
+}
+
+static struct gpio_chip sa1100_gpio_chip = {
+	.label			= "gpio",
+	.direction_input	= sa1100_direction_input,
+	.direction_output	= sa1100_direction_output,
+	.set			= sa1100_gpio_set,
+	.get			= sa1100_gpio_get,
+	.base			= 0,
+	.ngpio			= GPIO_MAX + 1,
+};
+
+void __init sa1100_init_gpio(void)
+{
+	gpiochip_add(&sa1100_gpio_chip);
+}
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-samsung.c linux-libre-3.2-gnu/drivers/gpio/gpio-samsung.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-samsung.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-samsung.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2712 @@
+/*
+ * Copyright (c) 2009-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/
+ *
+ * SAMSUNG - 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 <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+#include <linux/ioport.h>
+
+#include <asm/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-gpio.h>
+
+#include <plat/cpu.h>
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+#include <plat/gpio-fns.h>
+#include <plat/pm.h>
+
+#ifndef DEBUG_GPIO
+#define gpio_dbg(x...) do { } while (0)
+#else
+#define gpio_dbg(x...) printk(KERN_DEBUG x)
+#endif
+
+int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
+				unsigned int off, samsung_gpio_pull_t pull)
+{
+	void __iomem *reg = chip->base + 0x08;
+	int shift = off * 2;
+	u32 pup;
+
+	pup = __raw_readl(reg);
+	pup &= ~(3 << shift);
+	pup |= pull << shift;
+	__raw_writel(pup, reg);
+
+	return 0;
+}
+
+samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
+						unsigned int off)
+{
+	void __iomem *reg = chip->base + 0x08;
+	int shift = off * 2;
+	u32 pup = __raw_readl(reg);
+
+	pup >>= shift;
+	pup &= 0x3;
+
+	return (__force samsung_gpio_pull_t)pup;
+}
+
+int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
+			 unsigned int off, samsung_gpio_pull_t pull)
+{
+	switch (pull) {
+	case S3C_GPIO_PULL_NONE:
+		pull = 0x01;
+		break;
+	case S3C_GPIO_PULL_UP:
+		pull = 0x00;
+		break;
+	case S3C_GPIO_PULL_DOWN:
+		pull = 0x02;
+		break;
+	}
+	return samsung_gpio_setpull_updown(chip, off, pull);
+}
+
+samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
+					 unsigned int off)
+{
+	samsung_gpio_pull_t pull;
+
+	pull = samsung_gpio_getpull_updown(chip, off);
+
+	switch (pull) {
+	case 0x00:
+		pull = S3C_GPIO_PULL_UP;
+		break;
+	case 0x01:
+	case 0x03:
+		pull = S3C_GPIO_PULL_NONE;
+		break;
+	case 0x02:
+		pull = S3C_GPIO_PULL_DOWN;
+		break;
+	}
+
+	return pull;
+}
+
+static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip,
+				  unsigned int off, samsung_gpio_pull_t pull,
+				  samsung_gpio_pull_t updown)
+{
+	void __iomem *reg = chip->base + 0x08;
+	u32 pup = __raw_readl(reg);
+
+	if (pull == updown)
+		pup &= ~(1 << off);
+	else if (pull == S3C_GPIO_PULL_NONE)
+		pup |= (1 << off);
+	else
+		return -EINVAL;
+
+	__raw_writel(pup, reg);
+	return 0;
+}
+
+static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip,
+						  unsigned int off,
+						  samsung_gpio_pull_t updown)
+{
+	void __iomem *reg = chip->base + 0x08;
+	u32 pup = __raw_readl(reg);
+
+	pup &= (1 << off);
+	return pup ? S3C_GPIO_PULL_NONE : updown;
+}
+
+samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
+					     unsigned int off)
+{
+	return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
+}
+
+int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
+			     unsigned int off, samsung_gpio_pull_t pull)
+{
+	return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
+}
+
+samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
+					       unsigned int off)
+{
+	return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
+}
+
+int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
+			       unsigned int off, samsung_gpio_pull_t pull)
+{
+	return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
+}
+
+static int exynos4_gpio_setpull(struct samsung_gpio_chip *chip,
+				unsigned int off, samsung_gpio_pull_t pull)
+{
+	if (pull == S3C_GPIO_PULL_UP)
+		pull = 3;
+
+	return samsung_gpio_setpull_updown(chip, off, pull);
+}
+
+static samsung_gpio_pull_t exynos4_gpio_getpull(struct samsung_gpio_chip *chip,
+						unsigned int off)
+{
+	samsung_gpio_pull_t pull;
+
+	pull = samsung_gpio_getpull_updown(chip, off);
+
+	if (pull == 3)
+		pull = S3C_GPIO_PULL_UP;
+
+	return pull;
+}
+
+/*
+ * samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register
+ * has two bits of configuration per gpio, which have the following
+ * functions:
+ *	00 = input
+ *	01 = output
+ *	1x = special function
+ */
+
+static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
+				    unsigned int off, unsigned int cfg)
+{
+	void __iomem *reg = chip->base;
+	unsigned int shift = off * 2;
+	u32 con;
+
+	if (samsung_gpio_is_cfg_special(cfg)) {
+		cfg &= 0xf;
+		if (cfg > 3)
+			return -EINVAL;
+
+		cfg <<= shift;
+	}
+
+	con = __raw_readl(reg);
+	con &= ~(0x3 << shift);
+	con |= cfg;
+	__raw_writel(con, reg);
+
+	return 0;
+}
+
+/*
+ * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ *
+ * The reverse of samsung_gpio_setcfg_2bit(). Will return a value whicg
+ * could be directly passed back to samsung_gpio_setcfg_2bit(), from the
+ * S3C_GPIO_SPECIAL() macro.
+ */
+
+static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
+					     unsigned int off)
+{
+	u32 con;
+
+	con = __raw_readl(chip->base);
+	con >>= off * 2;
+	con &= 3;
+
+	/* this conversion works for IN and OUT as well as special mode */
+	return S3C_GPIO_SPECIAL(con);
+}
+
+/*
+ * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register has 4 bits
+ * of control per GPIO, generally in the form of:
+ *	0000 = Input
+ *	0001 = Output
+ *	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
+ * each case.
+ */
+
+static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
+				    unsigned int off, unsigned int cfg)
+{
+	void __iomem *reg = chip->base;
+	unsigned int shift = (off & 7) * 4;
+	u32 con;
+
+	if (off < 8 && chip->chip.ngpio > 8)
+		reg -= 4;
+
+	if (samsung_gpio_is_cfg_special(cfg)) {
+		cfg &= 0xf;
+		cfg <<= shift;
+	}
+
+	con = __raw_readl(reg);
+	con &= ~(0xf << shift);
+	con |= cfg;
+	__raw_writel(con, reg);
+
+	return 0;
+}
+
+/*
+ * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ *
+ * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration
+ * register setting into a value the software can use, such as could be passed
+ * to samsung_gpio_setcfg_4bit().
+ *
+ * @sa samsung_gpio_getcfg_2bit
+ */
+
+static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
+					 unsigned int off)
+{
+	void __iomem *reg = chip->base;
+	unsigned int shift = (off & 7) * 4;
+	u32 con;
+
+	if (off < 8 && chip->chip.ngpio > 8)
+		reg -= 4;
+
+	con = __raw_readl(reg);
+	con >>= shift;
+	con &= 0xf;
+
+	/* this conversion works for IN and OUT as well as special mode */
+	return S3C_GPIO_SPECIAL(con);
+}
+
+#ifdef CONFIG_PLAT_S3C24XX
+/*
+ * s3c24xx_gpio_setcfg_abank - S3C24XX style GPIO configuration (Bank A)
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register
+ * has one bit of configuration for the gpio, where setting the bit
+ * means the pin is in special function mode and unset means output.
+ */
+
+static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip,
+				     unsigned int off, unsigned int cfg)
+{
+	void __iomem *reg = chip->base;
+	unsigned int shift = off;
+	u32 con;
+
+	if (samsung_gpio_is_cfg_special(cfg)) {
+		cfg &= 0xf;
+
+		/* Map output to 0, and SFN2 to 1 */
+		cfg -= 1;
+		if (cfg > 1)
+			return -EINVAL;
+
+		cfg <<= shift;
+	}
+
+	con = __raw_readl(reg);
+	con &= ~(0x1 << shift);
+	con |= cfg;
+	__raw_writel(con, reg);
+
+	return 0;
+}
+
+/*
+ * s3c24xx_gpio_getcfg_abank - S3C24XX style GPIO configuration read (Bank A)
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ *
+ * The reverse of s3c24xx_gpio_setcfg_abank() turning an GPIO into a usable
+ * GPIO configuration value.
+ *
+ * @sa samsung_gpio_getcfg_2bit
+ * @sa samsung_gpio_getcfg_4bit
+ */
+
+static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
+					  unsigned int off)
+{
+	u32 con;
+
+	con = __raw_readl(chip->base);
+	con >>= off;
+	con &= 1;
+	con++;
+
+	return S3C_GPIO_SFN(con);
+}
+#endif
+
+#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
+static int s5p64x0_gpio_setcfg_rbank(struct samsung_gpio_chip *chip,
+				     unsigned int off, unsigned int cfg)
+{
+	void __iomem *reg = chip->base;
+	unsigned int shift;
+	u32 con;
+
+	switch (off) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+		shift = (off & 7) * 4;
+		reg -= 4;
+		break;
+	case 6:
+		shift = ((off + 1) & 7) * 4;
+		reg -= 4;
+	default:
+		shift = ((off + 1) & 7) * 4;
+		break;
+	}
+
+	if (samsung_gpio_is_cfg_special(cfg)) {
+		cfg &= 0xf;
+		cfg <<= shift;
+	}
+
+	con = __raw_readl(reg);
+	con &= ~(0xf << shift);
+	con |= cfg;
+	__raw_writel(con, reg);
+
+	return 0;
+}
+#endif
+
+static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
+					   int nr_chips)
+{
+	for (; nr_chips > 0; nr_chips--, chipcfg++) {
+		if (!chipcfg->set_config)
+			chipcfg->set_config = samsung_gpio_setcfg_4bit;
+		if (!chipcfg->get_config)
+			chipcfg->get_config = samsung_gpio_getcfg_4bit;
+		if (!chipcfg->set_pull)
+			chipcfg->set_pull = samsung_gpio_setpull_updown;
+		if (!chipcfg->get_pull)
+			chipcfg->get_pull = samsung_gpio_getpull_updown;
+	}
+}
+
+struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
+	.set_config	= samsung_gpio_setcfg_2bit,
+	.get_config	= samsung_gpio_getcfg_2bit,
+};
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
+	.set_config	= s3c24xx_gpio_setcfg_abank,
+	.get_config	= s3c24xx_gpio_getcfg_abank,
+};
+#endif
+
+static struct samsung_gpio_cfg exynos4_gpio_cfg = {
+	.set_pull	= exynos4_gpio_setpull,
+	.get_pull	= exynos4_gpio_getpull,
+	.set_config	= samsung_gpio_setcfg_4bit,
+	.get_config	= samsung_gpio_getcfg_4bit,
+};
+
+#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
+static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
+	.cfg_eint	= 0x3,
+	.set_config	= s5p64x0_gpio_setcfg_rbank,
+	.get_config	= samsung_gpio_getcfg_4bit,
+	.set_pull	= samsung_gpio_setpull_updown,
+	.get_pull	= samsung_gpio_getpull_updown,
+};
+#endif
+
+static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
+	{
+		.cfg_eint	= 0x0,
+	}, {
+		.cfg_eint	= 0x3,
+	}, {
+		.cfg_eint	= 0x7,
+	}, {
+		.cfg_eint	= 0xF,
+	}, {
+		.cfg_eint	= 0x0,
+		.set_config	= samsung_gpio_setcfg_2bit,
+		.get_config	= samsung_gpio_getcfg_2bit,
+	}, {
+		.cfg_eint	= 0x2,
+		.set_config	= samsung_gpio_setcfg_2bit,
+		.get_config	= samsung_gpio_getcfg_2bit,
+	}, {
+		.cfg_eint	= 0x3,
+		.set_config	= samsung_gpio_setcfg_2bit,
+		.get_config	= samsung_gpio_getcfg_2bit,
+	}, {
+		.set_config	= samsung_gpio_setcfg_2bit,
+		.get_config	= samsung_gpio_getcfg_2bit,
+	}, {
+		.set_pull	= exynos4_gpio_setpull,
+		.get_pull	= exynos4_gpio_getpull,
+	}, {
+		.cfg_eint	= 0x3,
+		.set_pull	= exynos4_gpio_setpull,
+		.get_pull	= exynos4_gpio_getpull,
+	}
+};
+
+/*
+ * Default routines for controlling GPIO, based on the original S3C24XX
+ * GPIO functions which deal with the case where each gpio bank of the
+ * chip is as following:
+ *
+ * base + 0x00: Control register, 2 bits per gpio
+ *	        gpio n: 2 bits starting at (2*n)
+ *		00 = input, 01 = output, others mean special-function
+ * base + 0x04: Data register, 1 bit per gpio
+ *		bit n: data bit n
+*/
+
+static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long flags;
+	unsigned long con;
+
+	samsung_gpio_lock(ourchip, flags);
+
+	con = __raw_readl(base + 0x00);
+	con &= ~(3 << (offset * 2));
+
+	__raw_writel(con, base + 0x00);
+
+	samsung_gpio_unlock(ourchip, flags);
+	return 0;
+}
+
+static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
+				       unsigned offset, int value)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long flags;
+	unsigned long dat;
+	unsigned long con;
+
+	samsung_gpio_lock(ourchip, flags);
+
+	dat = __raw_readl(base + 0x04);
+	dat &= ~(1 << offset);
+	if (value)
+		dat |= 1 << offset;
+	__raw_writel(dat, base + 0x04);
+
+	con = __raw_readl(base + 0x00);
+	con &= ~(3 << (offset * 2));
+	con |= 1 << (offset * 2);
+
+	__raw_writel(con, base + 0x00);
+	__raw_writel(dat, base + 0x04);
+
+	samsung_gpio_unlock(ourchip, flags);
+	return 0;
+}
+
+/*
+ * The samsung_gpiolib_4bit routines are to control the gpio banks where
+ * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
+ * following example:
+ *
+ * base + 0x00: Control register, 4 bits per gpio
+ *		gpio n: 4 bits starting at (4*n)
+ *		0000 = input, 0001 = output, others mean special-function
+ * base + 0x04: Data register, 1 bit per gpio
+ *		bit n: data bit n
+ *
+ * Note, since the data register is one bit per gpio and is at base + 0x4
+ * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
+ * state of the output.
+ */
+
+static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
+				      unsigned int offset)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long con;
+
+	con = __raw_readl(base + GPIOCON_OFF);
+	con &= ~(0xf << con_4bit_shift(offset));
+	__raw_writel(con, base + GPIOCON_OFF);
+
+	gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
+
+	return 0;
+}
+
+static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
+				       unsigned int offset, int value)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long con;
+	unsigned long dat;
+
+	con = __raw_readl(base + GPIOCON_OFF);
+	con &= ~(0xf << con_4bit_shift(offset));
+	con |= 0x1 << con_4bit_shift(offset);
+
+	dat = __raw_readl(base + GPIODAT_OFF);
+
+	if (value)
+		dat |= 1 << offset;
+	else
+		dat &= ~(1 << offset);
+
+	__raw_writel(dat, base + GPIODAT_OFF);
+	__raw_writel(con, base + GPIOCON_OFF);
+	__raw_writel(dat, base + GPIODAT_OFF);
+
+	gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+
+	return 0;
+}
+
+/*
+ * The next set of routines are for the case where the GPIO configuration
+ * registers are 4 bits per GPIO but there is more than one register (the
+ * bank has more than 8 GPIOs.
+ *
+ * This case is the similar to the 4 bit case, but the registers are as
+ * follows:
+ *
+ * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
+ *		gpio n: 4 bits starting at (4*n)
+ *		0000 = input, 0001 = output, others mean special-function
+ * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
+ *		gpio n: 4 bits starting at (4*n)
+ *		0000 = input, 0001 = output, others mean special-function
+ * base + 0x08: Data register, 1 bit per gpio
+ *		bit n: data bit n
+ *
+ * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
+ * routines we store the 'base + 0x4' address so that these routines see
+ * the data register at ourchip->base + 0x04.
+ */
+
+static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
+				       unsigned int offset)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	void __iomem *regcon = base;
+	unsigned long con;
+
+	if (offset > 7)
+		offset -= 8;
+	else
+		regcon -= 4;
+
+	con = __raw_readl(regcon);
+	con &= ~(0xf << con_4bit_shift(offset));
+	__raw_writel(con, regcon);
+
+	gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
+
+	return 0;
+}
+
+static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
+					unsigned int offset, int value)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	void __iomem *regcon = base;
+	unsigned long con;
+	unsigned long dat;
+	unsigned con_offset = offset;
+
+	if (con_offset > 7)
+		con_offset -= 8;
+	else
+		regcon -= 4;
+
+	con = __raw_readl(regcon);
+	con &= ~(0xf << con_4bit_shift(con_offset));
+	con |= 0x1 << con_4bit_shift(con_offset);
+
+	dat = __raw_readl(base + GPIODAT_OFF);
+
+	if (value)
+		dat |= 1 << offset;
+	else
+		dat &= ~(1 << offset);
+
+	__raw_writel(dat, base + GPIODAT_OFF);
+	__raw_writel(con, regcon);
+	__raw_writel(dat, base + GPIODAT_OFF);
+
+	gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+
+	return 0;
+}
+
+#ifdef CONFIG_PLAT_S3C24XX
+/* The next set of routines are for the case of s3c24xx bank a */
+
+static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
+{
+	return -EINVAL;
+}
+
+static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long flags;
+	unsigned long dat;
+	unsigned long con;
+
+	local_irq_save(flags);
+
+	con = __raw_readl(base + 0x00);
+	dat = __raw_readl(base + 0x04);
+
+	dat &= ~(1 << offset);
+	if (value)
+		dat |= 1 << offset;
+
+	__raw_writel(dat, base + 0x04);
+
+	con &= ~(1 << offset);
+
+	__raw_writel(con, base + 0x00);
+	__raw_writel(dat, base + 0x04);
+
+	local_irq_restore(flags);
+	return 0;
+}
+#endif
+
+/* The next set of routines are for the case of s5p64x0 bank r */
+
+static int s5p64x0_gpiolib_rbank_input(struct gpio_chip *chip,
+				       unsigned int offset)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	void __iomem *regcon = base;
+	unsigned long con;
+	unsigned long flags;
+
+	switch (offset) {
+	case 6:
+		offset += 1;
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+		regcon -= 4;
+		break;
+	default:
+		offset -= 7;
+		break;
+	}
+
+	samsung_gpio_lock(ourchip, flags);
+
+	con = __raw_readl(regcon);
+	con &= ~(0xf << con_4bit_shift(offset));
+	__raw_writel(con, regcon);
+
+	samsung_gpio_unlock(ourchip, flags);
+
+	return 0;
+}
+
+static int s5p64x0_gpiolib_rbank_output(struct gpio_chip *chip,
+					unsigned int offset, int value)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	void __iomem *regcon = base;
+	unsigned long con;
+	unsigned long dat;
+	unsigned long flags;
+	unsigned con_offset  = offset;
+
+	switch (con_offset) {
+	case 6:
+		con_offset += 1;
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+		regcon -= 4;
+		break;
+	default:
+		con_offset -= 7;
+		break;
+	}
+
+	samsung_gpio_lock(ourchip, flags);
+
+	con = __raw_readl(regcon);
+	con &= ~(0xf << con_4bit_shift(con_offset));
+	con |= 0x1 << con_4bit_shift(con_offset);
+
+	dat = __raw_readl(base + GPIODAT_OFF);
+	if (value)
+		dat |= 1 << offset;
+	else
+		dat &= ~(1 << offset);
+
+	__raw_writel(con, regcon);
+	__raw_writel(dat, base + GPIODAT_OFF);
+
+	samsung_gpio_unlock(ourchip, flags);
+
+	return 0;
+}
+
+static void samsung_gpiolib_set(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long flags;
+	unsigned long dat;
+
+	samsung_gpio_lock(ourchip, flags);
+
+	dat = __raw_readl(base + 0x04);
+	dat &= ~(1 << offset);
+	if (value)
+		dat |= 1 << offset;
+	__raw_writel(dat, base + 0x04);
+
+	samsung_gpio_unlock(ourchip, flags);
+}
+
+static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+	unsigned long val;
+
+	val = __raw_readl(ourchip->base + 0x04);
+	val >>= offset;
+	val &= 1;
+
+	return val;
+}
+
+/*
+ * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
+ * for use with the configuration calls, and other parts of the s3c gpiolib
+ * support code.
+ *
+ * Not all s3c support code will need this, as some configurations of cpu
+ * may only support one or two different configuration options and have an
+ * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
+ * the machine support file should provide its own samsung_gpiolib_getchip()
+ * and any other necessary functions.
+ */
+
+#ifdef CONFIG_S3C_GPIO_TRACK
+struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
+
+static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
+{
+	unsigned int gpn;
+	int i;
+
+	gpn = chip->chip.base;
+	for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
+		BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
+		s3c_gpios[gpn] = chip;
+	}
+}
+#endif /* CONFIG_S3C_GPIO_TRACK */
+
+/*
+ * samsung_gpiolib_add() - add the Samsung gpio_chip.
+ * @chip: The chip to register
+ *
+ * This is a wrapper to gpiochip_add() that takes our specific gpio chip
+ * information and makes the necessary alterations for the platform and
+ * notes the information for use with the configuration systems and any
+ * other parts of the system.
+ */
+
+static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
+{
+	struct gpio_chip *gc = &chip->chip;
+	int ret;
+
+	BUG_ON(!chip->base);
+	BUG_ON(!gc->label);
+	BUG_ON(!gc->ngpio);
+
+	spin_lock_init(&chip->lock);
+
+	if (!gc->direction_input)
+		gc->direction_input = samsung_gpiolib_2bit_input;
+	if (!gc->direction_output)
+		gc->direction_output = samsung_gpiolib_2bit_output;
+	if (!gc->set)
+		gc->set = samsung_gpiolib_set;
+	if (!gc->get)
+		gc->get = samsung_gpiolib_get;
+
+#ifdef CONFIG_PM
+	if (chip->pm != NULL) {
+		if (!chip->pm->save || !chip->pm->resume)
+			printk(KERN_ERR "gpio: %s has missing PM functions\n",
+			       gc->label);
+	} else
+		printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
+#endif
+
+	/* gpiochip_add() prints own failure message on error. */
+	ret = gpiochip_add(gc);
+	if (ret >= 0)
+		s3c_gpiolib_track(chip);
+}
+
+static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
+					     int nr_chips, void __iomem *base)
+{
+	int i;
+	struct gpio_chip *gc = &chip->chip;
+
+	for (i = 0 ; i < nr_chips; i++, chip++) {
+		/* skip banks not present on SoC */
+		if (chip->chip.base >= S3C_GPIO_END)
+			continue;
+
+		if (!chip->config)
+			chip->config = &s3c24xx_gpiocfg_default;
+		if (!chip->pm)
+			chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
+		if ((base != NULL) && (chip->base == NULL))
+			chip->base = base + ((i) * 0x10);
+
+		if (!gc->direction_input)
+			gc->direction_input = samsung_gpiolib_2bit_input;
+		if (!gc->direction_output)
+			gc->direction_output = samsung_gpiolib_2bit_output;
+
+		samsung_gpiolib_add(chip);
+	}
+}
+
+static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
+						  int nr_chips, void __iomem *base,
+						  unsigned int offset)
+{
+	int i;
+
+	for (i = 0 ; i < nr_chips; i++, chip++) {
+		chip->chip.direction_input = samsung_gpiolib_2bit_input;
+		chip->chip.direction_output = samsung_gpiolib_2bit_output;
+
+		if (!chip->config)
+			chip->config = &samsung_gpio_cfgs[7];
+		if (!chip->pm)
+			chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
+		if ((base != NULL) && (chip->base == NULL))
+			chip->base = base + ((i) * offset);
+
+		samsung_gpiolib_add(chip);
+	}
+}
+
+/*
+ * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
+ * @chip: The gpio chip that is being configured.
+ * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
+ *
+ * This helper deal with the GPIO cases where the control register has 4 bits
+ * of control per GPIO, generally in the form of:
+ * 0000 = Input
+ * 0001 = Output
+ * 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
+ * (samsung_gpiolib_add_4bit2_chips)for each case.
+ */
+
+static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
+						  int nr_chips, void __iomem *base)
+{
+	int i;
+
+	for (i = 0 ; i < nr_chips; i++, chip++) {
+		chip->chip.direction_input = samsung_gpiolib_4bit_input;
+		chip->chip.direction_output = samsung_gpiolib_4bit_output;
+
+		if (!chip->config)
+			chip->config = &samsung_gpio_cfgs[2];
+		if (!chip->pm)
+			chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
+		if ((base != NULL) && (chip->base == NULL))
+			chip->base = base + ((i) * 0x20);
+
+		samsung_gpiolib_add(chip);
+	}
+}
+
+static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
+						   int nr_chips)
+{
+	for (; nr_chips > 0; nr_chips--, chip++) {
+		chip->chip.direction_input = samsung_gpiolib_4bit2_input;
+		chip->chip.direction_output = samsung_gpiolib_4bit2_output;
+
+		if (!chip->config)
+			chip->config = &samsung_gpio_cfgs[2];
+		if (!chip->pm)
+			chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
+
+		samsung_gpiolib_add(chip);
+	}
+}
+
+static void __init s5p64x0_gpiolib_add_rbank(struct samsung_gpio_chip *chip,
+					     int nr_chips)
+{
+	for (; nr_chips > 0; nr_chips--, chip++) {
+		chip->chip.direction_input = s5p64x0_gpiolib_rbank_input;
+		chip->chip.direction_output = s5p64x0_gpiolib_rbank_output;
+
+		if (!chip->pm)
+			chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
+
+		samsung_gpiolib_add(chip);
+	}
+}
+
+int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+	struct samsung_gpio_chip *samsung_chip = container_of(chip, struct samsung_gpio_chip, chip);
+
+	return samsung_chip->irq_base + offset;
+}
+
+#ifdef CONFIG_PLAT_S3C24XX
+static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset < 4)
+		return IRQ_EINT0 + offset;
+
+	if (offset < 8)
+		return IRQ_EINT4 + offset - 4;
+
+	return -EINVAL;
+}
+#endif
+
+#ifdef CONFIG_PLAT_S3C64XX
+static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
+{
+	return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
+}
+
+static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
+{
+	return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
+}
+#endif
+
+struct samsung_gpio_chip s3c24xx_gpios[] = {
+#ifdef CONFIG_PLAT_S3C24XX
+	{
+		.config	= &s3c24xx_gpiocfg_banka,
+		.chip	= {
+			.base			= S3C2410_GPA(0),
+			.owner			= THIS_MODULE,
+			.label			= "GPIOA",
+			.ngpio			= 24,
+			.direction_input	= s3c24xx_gpiolib_banka_input,
+			.direction_output	= s3c24xx_gpiolib_banka_output,
+		},
+	}, {
+		.chip	= {
+			.base	= S3C2410_GPB(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOB",
+			.ngpio	= 16,
+		},
+	}, {
+		.chip	= {
+			.base	= S3C2410_GPC(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOC",
+			.ngpio	= 16,
+		},
+	}, {
+		.chip	= {
+			.base	= S3C2410_GPD(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOD",
+			.ngpio	= 16,
+		},
+	}, {
+		.chip	= {
+			.base	= S3C2410_GPE(0),
+			.label	= "GPIOE",
+			.owner	= THIS_MODULE,
+			.ngpio	= 16,
+		},
+	}, {
+		.chip	= {
+			.base	= S3C2410_GPF(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOF",
+			.ngpio	= 8,
+			.to_irq	= s3c24xx_gpiolib_fbank_to_irq,
+		},
+	}, {
+		.irq_base = IRQ_EINT8,
+		.chip	= {
+			.base	= S3C2410_GPG(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOG",
+			.ngpio	= 16,
+			.to_irq	= samsung_gpiolib_to_irq,
+		},
+	}, {
+		.chip	= {
+			.base	= S3C2410_GPH(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOH",
+			.ngpio	= 11,
+		},
+	},
+		/* GPIOS for the S3C2443 and later devices. */
+	{
+		.base	= S3C2440_GPJCON,
+		.chip	= {
+			.base	= S3C2410_GPJ(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOJ",
+			.ngpio	= 16,
+		},
+	}, {
+		.base	= S3C2443_GPKCON,
+		.chip	= {
+			.base	= S3C2410_GPK(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOK",
+			.ngpio	= 16,
+		},
+	}, {
+		.base	= S3C2443_GPLCON,
+		.chip	= {
+			.base	= S3C2410_GPL(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOL",
+			.ngpio	= 15,
+		},
+	}, {
+		.base	= S3C2443_GPMCON,
+		.chip	= {
+			.base	= S3C2410_GPM(0),
+			.owner	= THIS_MODULE,
+			.label	= "GPIOM",
+			.ngpio	= 2,
+		},
+	},
+#endif
+};
+
+/*
+ * GPIO bank summary:
+ *
+ * Bank	GPIOs	Style	SlpCon	ExtInt Group
+ * A	8	4Bit	Yes	1
+ * B	7	4Bit	Yes	1
+ * C	8	4Bit	Yes	2
+ * D	5	4Bit	Yes	3
+ * E	5	4Bit	Yes	None
+ * F	16	2Bit	Yes	4 [1]
+ * G	7	4Bit	Yes	5
+ * H	10	4Bit[2]	Yes	6
+ * I	16	2Bit	Yes	None
+ * J	12	2Bit	Yes	None
+ * K	16	4Bit[2]	No	None
+ * L	15	4Bit[2] No	None
+ * M	6	4Bit	No	IRQ_EINT
+ * N	16	2Bit	No	IRQ_EINT
+ * O	16	2Bit	Yes	7
+ * P	15	2Bit	Yes	8
+ * Q	9	2Bit	Yes	9
+ *
+ * [1] BANKF pins 14,15 do not form part of the external interrupt sources
+ * [2] BANK has two control registers, GPxCON0 and GPxCON1
+ */
+
+static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
+#ifdef CONFIG_PLAT_S3C64XX
+	{
+		.chip	= {
+			.base	= S3C64XX_GPA(0),
+			.ngpio	= S3C64XX_GPIO_A_NR,
+			.label	= "GPA",
+		},
+	}, {
+		.chip	= {
+			.base	= S3C64XX_GPB(0),
+			.ngpio	= S3C64XX_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.chip	= {
+			.base	= S3C64XX_GPC(0),
+			.ngpio	= S3C64XX_GPIO_C_NR,
+			.label	= "GPC",
+		},
+	}, {
+		.chip	= {
+			.base	= S3C64XX_GPD(0),
+			.ngpio	= S3C64XX_GPIO_D_NR,
+			.label	= "GPD",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[0],
+		.chip	= {
+			.base	= S3C64XX_GPE(0),
+			.ngpio	= S3C64XX_GPIO_E_NR,
+			.label	= "GPE",
+		},
+	}, {
+		.base	= S3C64XX_GPG_BASE,
+		.chip	= {
+			.base	= S3C64XX_GPG(0),
+			.ngpio	= S3C64XX_GPIO_G_NR,
+			.label	= "GPG",
+		},
+	}, {
+		.base	= S3C64XX_GPM_BASE,
+		.config	= &samsung_gpio_cfgs[1],
+		.chip	= {
+			.base	= S3C64XX_GPM(0),
+			.ngpio	= S3C64XX_GPIO_M_NR,
+			.label	= "GPM",
+			.to_irq = s3c64xx_gpiolib_mbank_to_irq,
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
+#ifdef CONFIG_PLAT_S3C64XX
+	{
+		.base	= S3C64XX_GPH_BASE + 0x4,
+		.chip	= {
+			.base	= S3C64XX_GPH(0),
+			.ngpio	= S3C64XX_GPIO_H_NR,
+			.label	= "GPH",
+		},
+	}, {
+		.base	= S3C64XX_GPK_BASE + 0x4,
+		.config	= &samsung_gpio_cfgs[0],
+		.chip	= {
+			.base	= S3C64XX_GPK(0),
+			.ngpio	= S3C64XX_GPIO_K_NR,
+			.label	= "GPK",
+		},
+	}, {
+		.base	= S3C64XX_GPL_BASE + 0x4,
+		.config	= &samsung_gpio_cfgs[1],
+		.chip	= {
+			.base	= S3C64XX_GPL(0),
+			.ngpio	= S3C64XX_GPIO_L_NR,
+			.label	= "GPL",
+			.to_irq = s3c64xx_gpiolib_lbank_to_irq,
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
+#ifdef CONFIG_PLAT_S3C64XX
+	{
+		.base	= S3C64XX_GPF_BASE,
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S3C64XX_GPF(0),
+			.ngpio	= S3C64XX_GPIO_F_NR,
+			.label	= "GPF",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[7],
+		.chip	= {
+			.base	= S3C64XX_GPI(0),
+			.ngpio	= S3C64XX_GPIO_I_NR,
+			.label	= "GPI",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[7],
+		.chip	= {
+			.base	= S3C64XX_GPJ(0),
+			.ngpio	= S3C64XX_GPIO_J_NR,
+			.label	= "GPJ",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S3C64XX_GPO(0),
+			.ngpio	= S3C64XX_GPIO_O_NR,
+			.label	= "GPO",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S3C64XX_GPP(0),
+			.ngpio	= S3C64XX_GPIO_P_NR,
+			.label	= "GPP",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S3C64XX_GPQ(0),
+			.ngpio	= S3C64XX_GPIO_Q_NR,
+			.label	= "GPQ",
+		},
+	}, {
+		.base	= S3C64XX_GPN_BASE,
+		.irq_base = IRQ_EINT(0),
+		.config	= &samsung_gpio_cfgs[5],
+		.chip	= {
+			.base	= S3C64XX_GPN(0),
+			.ngpio	= S3C64XX_GPIO_N_NR,
+			.label	= "GPN",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	},
+#endif
+};
+
+/*
+ * S5P6440 GPIO bank summary:
+ *
+ * Bank	GPIOs	Style	SlpCon	ExtInt Group
+ * A	6	4Bit	Yes	1
+ * B	7	4Bit	Yes	1
+ * C	8	4Bit	Yes	2
+ * F	2	2Bit	Yes	4 [1]
+ * G	7	4Bit	Yes	5
+ * H	10	4Bit[2]	Yes	6
+ * I	16	2Bit	Yes	None
+ * J	12	2Bit	Yes	None
+ * N	16	2Bit	No	IRQ_EINT
+ * P	8	2Bit	Yes	8
+ * R	15	4Bit[2]	Yes	8
+ */
+
+static struct samsung_gpio_chip s5p6440_gpios_4bit[] = {
+#ifdef CONFIG_CPU_S5P6440
+	{
+		.chip	= {
+			.base	= S5P6440_GPA(0),
+			.ngpio	= S5P6440_GPIO_A_NR,
+			.label	= "GPA",
+		},
+	}, {
+		.chip	= {
+			.base	= S5P6440_GPB(0),
+			.ngpio	= S5P6440_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.chip	= {
+			.base	= S5P6440_GPC(0),
+			.ngpio	= S5P6440_GPIO_C_NR,
+			.label	= "GPC",
+		},
+	}, {
+		.base	= S5P64X0_GPG_BASE,
+		.chip	= {
+			.base	= S5P6440_GPG(0),
+			.ngpio	= S5P6440_GPIO_G_NR,
+			.label	= "GPG",
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip s5p6440_gpios_4bit2[] = {
+#ifdef CONFIG_CPU_S5P6440
+	{
+		.base	= S5P64X0_GPH_BASE + 0x4,
+		.chip	= {
+			.base	= S5P6440_GPH(0),
+			.ngpio	= S5P6440_GPIO_H_NR,
+			.label	= "GPH",
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip s5p6440_gpios_rbank[] = {
+#ifdef CONFIG_CPU_S5P6440
+	{
+		.base	= S5P64X0_GPR_BASE + 0x4,
+		.config	= &s5p64x0_gpio_cfg_rbank,
+		.chip	= {
+			.base	= S5P6440_GPR(0),
+			.ngpio	= S5P6440_GPIO_R_NR,
+			.label	= "GPR",
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip s5p6440_gpios_2bit[] = {
+#ifdef CONFIG_CPU_S5P6440
+	{
+		.base	= S5P64X0_GPF_BASE,
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S5P6440_GPF(0),
+			.ngpio	= S5P6440_GPIO_F_NR,
+			.label	= "GPF",
+		},
+	}, {
+		.base	= S5P64X0_GPI_BASE,
+		.config	= &samsung_gpio_cfgs[4],
+		.chip	= {
+			.base	= S5P6440_GPI(0),
+			.ngpio	= S5P6440_GPIO_I_NR,
+			.label	= "GPI",
+		},
+	}, {
+		.base	= S5P64X0_GPJ_BASE,
+		.config	= &samsung_gpio_cfgs[4],
+		.chip	= {
+			.base	= S5P6440_GPJ(0),
+			.ngpio	= S5P6440_GPIO_J_NR,
+			.label	= "GPJ",
+		},
+	}, {
+		.base	= S5P64X0_GPN_BASE,
+		.config	= &samsung_gpio_cfgs[5],
+		.chip	= {
+			.base	= S5P6440_GPN(0),
+			.ngpio	= S5P6440_GPIO_N_NR,
+			.label	= "GPN",
+		},
+	}, {
+		.base	= S5P64X0_GPP_BASE,
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S5P6440_GPP(0),
+			.ngpio	= S5P6440_GPIO_P_NR,
+			.label	= "GPP",
+		},
+	},
+#endif
+};
+
+/*
+ * S5P6450 GPIO bank summary:
+ *
+ * Bank	GPIOs	Style	SlpCon	ExtInt Group
+ * A	6	4Bit	Yes	1
+ * B	7	4Bit	Yes	1
+ * C	8	4Bit	Yes	2
+ * D	8	4Bit	Yes	None
+ * F	2	2Bit	Yes	None
+ * G	14	4Bit[2]	Yes	5
+ * H	10	4Bit[2]	Yes	6
+ * I	16	2Bit	Yes	None
+ * J	12	2Bit	Yes	None
+ * K	5	4Bit	Yes	None
+ * N	16	2Bit	No	IRQ_EINT
+ * P	11	2Bit	Yes	8
+ * Q	14	2Bit	Yes	None
+ * R	15	4Bit[2]	Yes	None
+ * S	8	2Bit	Yes	None
+ *
+ * [1] BANKF pins 14,15 do not form part of the external interrupt sources
+ * [2] BANK has two control registers, GPxCON0 and GPxCON1
+ */
+
+static struct samsung_gpio_chip s5p6450_gpios_4bit[] = {
+#ifdef CONFIG_CPU_S5P6450
+	{
+		.chip	= {
+			.base	= S5P6450_GPA(0),
+			.ngpio	= S5P6450_GPIO_A_NR,
+			.label	= "GPA",
+		},
+	}, {
+		.chip	= {
+			.base	= S5P6450_GPB(0),
+			.ngpio	= S5P6450_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.chip	= {
+			.base	= S5P6450_GPC(0),
+			.ngpio	= S5P6450_GPIO_C_NR,
+			.label	= "GPC",
+		},
+	}, {
+		.chip	= {
+			.base	= S5P6450_GPD(0),
+			.ngpio	= S5P6450_GPIO_D_NR,
+			.label	= "GPD",
+		},
+	}, {
+		.base	= S5P6450_GPK_BASE,
+		.chip	= {
+			.base	= S5P6450_GPK(0),
+			.ngpio	= S5P6450_GPIO_K_NR,
+			.label	= "GPK",
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip s5p6450_gpios_4bit2[] = {
+#ifdef CONFIG_CPU_S5P6450
+	{
+		.base	= S5P64X0_GPG_BASE + 0x4,
+		.chip	= {
+			.base	= S5P6450_GPG(0),
+			.ngpio	= S5P6450_GPIO_G_NR,
+			.label	= "GPG",
+		},
+	}, {
+		.base	= S5P64X0_GPH_BASE + 0x4,
+		.chip	= {
+			.base	= S5P6450_GPH(0),
+			.ngpio	= S5P6450_GPIO_H_NR,
+			.label	= "GPH",
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip s5p6450_gpios_rbank[] = {
+#ifdef CONFIG_CPU_S5P6450
+	{
+		.base	= S5P64X0_GPR_BASE + 0x4,
+		.config	= &s5p64x0_gpio_cfg_rbank,
+		.chip	= {
+			.base	= S5P6450_GPR(0),
+			.ngpio	= S5P6450_GPIO_R_NR,
+			.label	= "GPR",
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip s5p6450_gpios_2bit[] = {
+#ifdef CONFIG_CPU_S5P6450
+	{
+		.base	= S5P64X0_GPF_BASE,
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S5P6450_GPF(0),
+			.ngpio	= S5P6450_GPIO_F_NR,
+			.label	= "GPF",
+		},
+	}, {
+		.base	= S5P64X0_GPI_BASE,
+		.config	= &samsung_gpio_cfgs[4],
+		.chip	= {
+			.base	= S5P6450_GPI(0),
+			.ngpio	= S5P6450_GPIO_I_NR,
+			.label	= "GPI",
+		},
+	}, {
+		.base	= S5P64X0_GPJ_BASE,
+		.config	= &samsung_gpio_cfgs[4],
+		.chip	= {
+			.base	= S5P6450_GPJ(0),
+			.ngpio	= S5P6450_GPIO_J_NR,
+			.label	= "GPJ",
+		},
+	}, {
+		.base	= S5P64X0_GPN_BASE,
+		.config	= &samsung_gpio_cfgs[5],
+		.chip	= {
+			.base	= S5P6450_GPN(0),
+			.ngpio	= S5P6450_GPIO_N_NR,
+			.label	= "GPN",
+		},
+	}, {
+		.base	= S5P64X0_GPP_BASE,
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S5P6450_GPP(0),
+			.ngpio	= S5P6450_GPIO_P_NR,
+			.label	= "GPP",
+		},
+	}, {
+		.base	= S5P6450_GPQ_BASE,
+		.config	= &samsung_gpio_cfgs[5],
+		.chip	= {
+			.base	= S5P6450_GPQ(0),
+			.ngpio	= S5P6450_GPIO_Q_NR,
+			.label	= "GPQ",
+		},
+	}, {
+		.base	= S5P6450_GPS_BASE,
+		.config	= &samsung_gpio_cfgs[6],
+		.chip	= {
+			.base	= S5P6450_GPS(0),
+			.ngpio	= S5P6450_GPIO_S_NR,
+			.label	= "GPS",
+		},
+	},
+#endif
+};
+
+/*
+ * S5PC100 GPIO bank summary:
+ *
+ * Bank	GPIOs	Style	INT Type
+ * A0	8	4Bit	GPIO_INT0
+ * A1	5	4Bit	GPIO_INT1
+ * B	8	4Bit	GPIO_INT2
+ * C	5	4Bit	GPIO_INT3
+ * D	7	4Bit	GPIO_INT4
+ * E0	8	4Bit	GPIO_INT5
+ * E1	6	4Bit	GPIO_INT6
+ * F0	8	4Bit	GPIO_INT7
+ * F1	8	4Bit	GPIO_INT8
+ * F2	8	4Bit	GPIO_INT9
+ * F3	4	4Bit	GPIO_INT10
+ * G0	8	4Bit	GPIO_INT11
+ * G1	3	4Bit	GPIO_INT12
+ * G2	7	4Bit	GPIO_INT13
+ * G3	7	4Bit	GPIO_INT14
+ * H0	8	4Bit	WKUP_INT
+ * H1	8	4Bit	WKUP_INT
+ * H2	8	4Bit	WKUP_INT
+ * H3	8	4Bit	WKUP_INT
+ * I	8	4Bit	GPIO_INT15
+ * J0	8	4Bit	GPIO_INT16
+ * J1	5	4Bit	GPIO_INT17
+ * J2	8	4Bit	GPIO_INT18
+ * J3	8	4Bit	GPIO_INT19
+ * J4	4	4Bit	GPIO_INT20
+ * K0	8	4Bit	None
+ * K1	6	4Bit	None
+ * K2	8	4Bit	None
+ * K3	8	4Bit	None
+ * L0	8	4Bit	None
+ * L1	8	4Bit	None
+ * L2	8	4Bit	None
+ * L3	8	4Bit	None
+ */
+
+static struct samsung_gpio_chip s5pc100_gpios_4bit[] = {
+#ifdef CONFIG_CPU_S5PC100
+	{
+		.chip	= {
+			.base	= S5PC100_GPA0(0),
+			.ngpio	= S5PC100_GPIO_A0_NR,
+			.label	= "GPA0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPA1(0),
+			.ngpio	= S5PC100_GPIO_A1_NR,
+			.label	= "GPA1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPB(0),
+			.ngpio	= S5PC100_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPC(0),
+			.ngpio	= S5PC100_GPIO_C_NR,
+			.label	= "GPC",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPD(0),
+			.ngpio	= S5PC100_GPIO_D_NR,
+			.label	= "GPD",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPE0(0),
+			.ngpio	= S5PC100_GPIO_E0_NR,
+			.label	= "GPE0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPE1(0),
+			.ngpio	= S5PC100_GPIO_E1_NR,
+			.label	= "GPE1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPF0(0),
+			.ngpio	= S5PC100_GPIO_F0_NR,
+			.label	= "GPF0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPF1(0),
+			.ngpio	= S5PC100_GPIO_F1_NR,
+			.label	= "GPF1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPF2(0),
+			.ngpio	= S5PC100_GPIO_F2_NR,
+			.label	= "GPF2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPF3(0),
+			.ngpio	= S5PC100_GPIO_F3_NR,
+			.label	= "GPF3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPG0(0),
+			.ngpio	= S5PC100_GPIO_G0_NR,
+			.label	= "GPG0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPG1(0),
+			.ngpio	= S5PC100_GPIO_G1_NR,
+			.label	= "GPG1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPG2(0),
+			.ngpio	= S5PC100_GPIO_G2_NR,
+			.label	= "GPG2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPG3(0),
+			.ngpio	= S5PC100_GPIO_G3_NR,
+			.label	= "GPG3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPI(0),
+			.ngpio	= S5PC100_GPIO_I_NR,
+			.label	= "GPI",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPJ0(0),
+			.ngpio	= S5PC100_GPIO_J0_NR,
+			.label	= "GPJ0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPJ1(0),
+			.ngpio	= S5PC100_GPIO_J1_NR,
+			.label	= "GPJ1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPJ2(0),
+			.ngpio	= S5PC100_GPIO_J2_NR,
+			.label	= "GPJ2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPJ3(0),
+			.ngpio	= S5PC100_GPIO_J3_NR,
+			.label	= "GPJ3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPJ4(0),
+			.ngpio	= S5PC100_GPIO_J4_NR,
+			.label	= "GPJ4",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPK0(0),
+			.ngpio	= S5PC100_GPIO_K0_NR,
+			.label	= "GPK0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPK1(0),
+			.ngpio	= S5PC100_GPIO_K1_NR,
+			.label	= "GPK1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPK2(0),
+			.ngpio	= S5PC100_GPIO_K2_NR,
+			.label	= "GPK2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPK3(0),
+			.ngpio	= S5PC100_GPIO_K3_NR,
+			.label	= "GPK3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPL0(0),
+			.ngpio	= S5PC100_GPIO_L0_NR,
+			.label	= "GPL0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPL1(0),
+			.ngpio	= S5PC100_GPIO_L1_NR,
+			.label	= "GPL1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPL2(0),
+			.ngpio	= S5PC100_GPIO_L2_NR,
+			.label	= "GPL2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPL3(0),
+			.ngpio	= S5PC100_GPIO_L3_NR,
+			.label	= "GPL3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PC100_GPL4(0),
+			.ngpio	= S5PC100_GPIO_L4_NR,
+			.label	= "GPL4",
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC00),
+		.irq_base = IRQ_EINT(0),
+		.chip	= {
+			.base	= S5PC100_GPH0(0),
+			.ngpio	= S5PC100_GPIO_H0_NR,
+			.label	= "GPH0",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC20),
+		.irq_base = IRQ_EINT(8),
+		.chip	= {
+			.base	= S5PC100_GPH1(0),
+			.ngpio	= S5PC100_GPIO_H1_NR,
+			.label	= "GPH1",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC40),
+		.irq_base = IRQ_EINT(16),
+		.chip	= {
+			.base	= S5PC100_GPH2(0),
+			.ngpio	= S5PC100_GPIO_H2_NR,
+			.label	= "GPH2",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC60),
+		.irq_base = IRQ_EINT(24),
+		.chip	= {
+			.base	= S5PC100_GPH3(0),
+			.ngpio	= S5PC100_GPIO_H3_NR,
+			.label	= "GPH3",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	},
+#endif
+};
+
+/*
+ * Followings are the gpio banks in S5PV210/S5PC110
+ *
+ * The 'config' member when left to NULL, is initialized to the default
+ * structure samsung_gpio_cfgs[3] in the init function below.
+ *
+ * The 'base' member is also initialized in the init function below.
+ * Note: The initialization of 'base' member of samsung_gpio_chip structure
+ * uses the above macro and depends on the banks being listed in order here.
+ */
+
+static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
+#ifdef CONFIG_CPU_S5PV210
+	{
+		.chip	= {
+			.base	= S5PV210_GPA0(0),
+			.ngpio	= S5PV210_GPIO_A0_NR,
+			.label	= "GPA0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPA1(0),
+			.ngpio	= S5PV210_GPIO_A1_NR,
+			.label	= "GPA1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPB(0),
+			.ngpio	= S5PV210_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPC0(0),
+			.ngpio	= S5PV210_GPIO_C0_NR,
+			.label	= "GPC0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPC1(0),
+			.ngpio	= S5PV210_GPIO_C1_NR,
+			.label	= "GPC1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPD0(0),
+			.ngpio	= S5PV210_GPIO_D0_NR,
+			.label	= "GPD0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPD1(0),
+			.ngpio	= S5PV210_GPIO_D1_NR,
+			.label	= "GPD1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPE0(0),
+			.ngpio	= S5PV210_GPIO_E0_NR,
+			.label	= "GPE0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPE1(0),
+			.ngpio	= S5PV210_GPIO_E1_NR,
+			.label	= "GPE1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPF0(0),
+			.ngpio	= S5PV210_GPIO_F0_NR,
+			.label	= "GPF0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPF1(0),
+			.ngpio	= S5PV210_GPIO_F1_NR,
+			.label	= "GPF1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPF2(0),
+			.ngpio	= S5PV210_GPIO_F2_NR,
+			.label	= "GPF2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPF3(0),
+			.ngpio	= S5PV210_GPIO_F3_NR,
+			.label	= "GPF3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPG0(0),
+			.ngpio	= S5PV210_GPIO_G0_NR,
+			.label	= "GPG0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPG1(0),
+			.ngpio	= S5PV210_GPIO_G1_NR,
+			.label	= "GPG1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPG2(0),
+			.ngpio	= S5PV210_GPIO_G2_NR,
+			.label	= "GPG2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPG3(0),
+			.ngpio	= S5PV210_GPIO_G3_NR,
+			.label	= "GPG3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPI(0),
+			.ngpio	= S5PV210_GPIO_I_NR,
+			.label	= "GPI",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPJ0(0),
+			.ngpio	= S5PV210_GPIO_J0_NR,
+			.label	= "GPJ0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPJ1(0),
+			.ngpio	= S5PV210_GPIO_J1_NR,
+			.label	= "GPJ1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPJ2(0),
+			.ngpio	= S5PV210_GPIO_J2_NR,
+			.label	= "GPJ2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPJ3(0),
+			.ngpio	= S5PV210_GPIO_J3_NR,
+			.label	= "GPJ3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPJ4(0),
+			.ngpio	= S5PV210_GPIO_J4_NR,
+			.label	= "GPJ4",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_MP01(0),
+			.ngpio	= S5PV210_GPIO_MP01_NR,
+			.label	= "MP01",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_MP02(0),
+			.ngpio	= S5PV210_GPIO_MP02_NR,
+			.label	= "MP02",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_MP03(0),
+			.ngpio	= S5PV210_GPIO_MP03_NR,
+			.label	= "MP03",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_MP04(0),
+			.ngpio	= S5PV210_GPIO_MP04_NR,
+			.label	= "MP04",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_MP05(0),
+			.ngpio	= S5PV210_GPIO_MP05_NR,
+			.label	= "MP05",
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC00),
+		.irq_base = IRQ_EINT(0),
+		.chip	= {
+			.base	= S5PV210_GPH0(0),
+			.ngpio	= S5PV210_GPIO_H0_NR,
+			.label	= "GPH0",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC20),
+		.irq_base = IRQ_EINT(8),
+		.chip	= {
+			.base	= S5PV210_GPH1(0),
+			.ngpio	= S5PV210_GPIO_H1_NR,
+			.label	= "GPH1",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC40),
+		.irq_base = IRQ_EINT(16),
+		.chip	= {
+			.base	= S5PV210_GPH2(0),
+			.ngpio	= S5PV210_GPIO_H2_NR,
+			.label	= "GPH2",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC60),
+		.irq_base = IRQ_EINT(24),
+		.chip	= {
+			.base	= S5PV210_GPH3(0),
+			.ngpio	= S5PV210_GPIO_H3_NR,
+			.label	= "GPH3",
+			.to_irq = samsung_gpiolib_to_irq,
+		},
+	},
+#endif
+};
+
+/*
+ * Followings are the gpio banks in EXYNOS4210
+ *
+ * The 'config' member when left to NULL, is initialized to the default
+ * structure samsung_gpio_cfgs[3] in the init function below.
+ *
+ * The 'base' member is also initialized in the init function below.
+ * Note: The initialization of 'base' member of samsung_gpio_chip structure
+ * uses the above macro and depends on the banks being listed in order here.
+ */
+
+static struct samsung_gpio_chip exynos4_gpios_1[] = {
+#ifdef CONFIG_ARCH_EXYNOS4
+	{
+		.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",
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip exynos4_gpios_2[] = {
+#ifdef CONFIG_ARCH_EXYNOS4
+	{
+		.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	= &samsung_gpio_cfgs[8],
+		.chip	= {
+			.base	= EXYNOS4_GPY0(0),
+			.ngpio	= EXYNOS4_GPIO_Y0_NR,
+			.label	= "GPY0",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[8],
+		.chip	= {
+			.base	= EXYNOS4_GPY1(0),
+			.ngpio	= EXYNOS4_GPIO_Y1_NR,
+			.label	= "GPY1",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[8],
+		.chip	= {
+			.base	= EXYNOS4_GPY2(0),
+			.ngpio	= EXYNOS4_GPIO_Y2_NR,
+			.label	= "GPY2",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[8],
+		.chip	= {
+			.base	= EXYNOS4_GPY3(0),
+			.ngpio	= EXYNOS4_GPIO_Y3_NR,
+			.label	= "GPY3",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[8],
+		.chip	= {
+			.base	= EXYNOS4_GPY4(0),
+			.ngpio	= EXYNOS4_GPIO_Y4_NR,
+			.label	= "GPY4",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[8],
+		.chip	= {
+			.base	= EXYNOS4_GPY5(0),
+			.ngpio	= EXYNOS4_GPIO_Y5_NR,
+			.label	= "GPY5",
+		},
+	}, {
+		.config	= &samsung_gpio_cfgs[8],
+		.chip	= {
+			.base	= EXYNOS4_GPY6(0),
+			.ngpio	= EXYNOS4_GPIO_Y6_NR,
+			.label	= "GPY6",
+		},
+	}, {
+		.base	= (S5P_VA_GPIO2 + 0xC00),
+		.config	= &samsung_gpio_cfgs[9],
+		.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	= &samsung_gpio_cfgs[9],
+		.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	= &samsung_gpio_cfgs[9],
+		.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	= &samsung_gpio_cfgs[9],
+		.irq_base = IRQ_EINT(24),
+		.chip	= {
+			.base	= EXYNOS4_GPX3(0),
+			.ngpio	= EXYNOS4_GPIO_X3_NR,
+			.label	= "GPX3",
+			.to_irq	= samsung_gpiolib_to_irq,
+		},
+	},
+#endif
+};
+
+static struct samsung_gpio_chip exynos4_gpios_3[] = {
+#ifdef CONFIG_ARCH_EXYNOS4
+	{
+		.chip	= {
+			.base	= EXYNOS4_GPZ(0),
+			.ngpio	= EXYNOS4_GPIO_Z_NR,
+			.label	= "GPZ",
+		},
+	},
+#endif
+};
+
+/* TODO: cleanup soc_is_* */
+static __init int samsung_gpiolib_init(void)
+{
+	struct samsung_gpio_chip *chip;
+	int i, nr_chips;
+	int group = 0;
+
+	samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
+
+	if (soc_is_s3c24xx()) {
+		s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
+				ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
+	} else if (soc_is_s3c64xx()) {
+		samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
+				ARRAY_SIZE(s3c64xx_gpios_2bit),
+				S3C64XX_VA_GPIO + 0xE0, 0x20);
+		samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
+				ARRAY_SIZE(s3c64xx_gpios_4bit),
+				S3C64XX_VA_GPIO);
+		samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
+				ARRAY_SIZE(s3c64xx_gpios_4bit2));
+	} else if (soc_is_s5p6440()) {
+		samsung_gpiolib_add_2bit_chips(s5p6440_gpios_2bit,
+				ARRAY_SIZE(s5p6440_gpios_2bit), NULL, 0x0);
+		samsung_gpiolib_add_4bit_chips(s5p6440_gpios_4bit,
+				ARRAY_SIZE(s5p6440_gpios_4bit), S5P_VA_GPIO);
+		samsung_gpiolib_add_4bit2_chips(s5p6440_gpios_4bit2,
+				ARRAY_SIZE(s5p6440_gpios_4bit2));
+		s5p64x0_gpiolib_add_rbank(s5p6440_gpios_rbank,
+				ARRAY_SIZE(s5p6440_gpios_rbank));
+	} else if (soc_is_s5p6450()) {
+		samsung_gpiolib_add_2bit_chips(s5p6450_gpios_2bit,
+				ARRAY_SIZE(s5p6450_gpios_2bit), NULL, 0x0);
+		samsung_gpiolib_add_4bit_chips(s5p6450_gpios_4bit,
+				ARRAY_SIZE(s5p6450_gpios_4bit), S5P_VA_GPIO);
+		samsung_gpiolib_add_4bit2_chips(s5p6450_gpios_4bit2,
+				ARRAY_SIZE(s5p6450_gpios_4bit2));
+		s5p64x0_gpiolib_add_rbank(s5p6450_gpios_rbank,
+				ARRAY_SIZE(s5p6450_gpios_rbank));
+	} else if (soc_is_s5pc100()) {
+		group = 0;
+		chip = s5pc100_gpios_4bit;
+		nr_chips = ARRAY_SIZE(s5pc100_gpios_4bit);
+
+		for (i = 0; i < nr_chips; i++, chip++) {
+			if (!chip->config) {
+				chip->config = &samsung_gpio_cfgs[3];
+				chip->group = group++;
+			}
+		}
+		samsung_gpiolib_add_4bit_chips(s5pc100_gpios_4bit, nr_chips, S5P_VA_GPIO);
+#if defined(CONFIG_CPU_S5PC100) && defined(CONFIG_S5P_GPIO_INT)
+		s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
+#endif
+	} else if (soc_is_s5pv210()) {
+		group = 0;
+		chip = s5pv210_gpios_4bit;
+		nr_chips = ARRAY_SIZE(s5pv210_gpios_4bit);
+
+		for (i = 0; i < nr_chips; i++, chip++) {
+			if (!chip->config) {
+				chip->config = &samsung_gpio_cfgs[3];
+				chip->group = group++;
+			}
+		}
+		samsung_gpiolib_add_4bit_chips(s5pv210_gpios_4bit, nr_chips, S5P_VA_GPIO);
+#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
+		s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
+#endif
+	} else if (soc_is_exynos4210()) {
+		group = 0;
+
+		/* gpio part1 */
+		chip = exynos4_gpios_1;
+		nr_chips = ARRAY_SIZE(exynos4_gpios_1);
+
+		for (i = 0; i < nr_chips; i++, chip++) {
+			if (!chip->config) {
+				chip->config = &exynos4_gpio_cfg;
+				chip->group = group++;
+			}
+		}
+		samsung_gpiolib_add_4bit_chips(exynos4_gpios_1, nr_chips, S5P_VA_GPIO1);
+
+		/* gpio part2 */
+		chip = exynos4_gpios_2;
+		nr_chips = ARRAY_SIZE(exynos4_gpios_2);
+
+		for (i = 0; i < nr_chips; i++, chip++) {
+			if (!chip->config) {
+				chip->config = &exynos4_gpio_cfg;
+				chip->group = group++;
+			}
+		}
+		samsung_gpiolib_add_4bit_chips(exynos4_gpios_2, nr_chips, S5P_VA_GPIO2);
+
+		/* gpio part3 */
+		chip = exynos4_gpios_3;
+		nr_chips = ARRAY_SIZE(exynos4_gpios_3);
+
+		for (i = 0; i < nr_chips; i++, chip++) {
+			if (!chip->config) {
+				chip->config = &exynos4_gpio_cfg;
+				chip->group = group++;
+			}
+		}
+		samsung_gpiolib_add_4bit_chips(exynos4_gpios_3, nr_chips, S5P_VA_GPIO3);
+
+#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_S5P_GPIO_INT)
+		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);
+#endif
+	} else {
+		WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+core_initcall(samsung_gpiolib_init);
+
+int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
+{
+	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+	unsigned long flags;
+	int offset;
+	int ret;
+
+	if (!chip)
+		return -EINVAL;
+
+	offset = pin - chip->chip.base;
+
+	samsung_gpio_lock(chip, flags);
+	ret = samsung_gpio_do_setcfg(chip, offset, config);
+	samsung_gpio_unlock(chip, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(s3c_gpio_cfgpin);
+
+int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
+			  unsigned int cfg)
+{
+	int ret;
+
+	for (; nr > 0; nr--, start++) {
+		ret = s3c_gpio_cfgpin(start, cfg);
+		if (ret != 0)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
+
+int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
+			  unsigned int cfg, samsung_gpio_pull_t pull)
+{
+	int ret;
+
+	for (; nr > 0; nr--, start++) {
+		s3c_gpio_setpull(start, pull);
+		ret = s3c_gpio_cfgpin(start, cfg);
+		if (ret != 0)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
+
+unsigned s3c_gpio_getcfg(unsigned int pin)
+{
+	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+	unsigned long flags;
+	unsigned ret = 0;
+	int offset;
+
+	if (chip) {
+		offset = pin - chip->chip.base;
+
+		samsung_gpio_lock(chip, flags);
+		ret = samsung_gpio_do_getcfg(chip, offset);
+		samsung_gpio_unlock(chip, flags);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(s3c_gpio_getcfg);
+
+int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
+{
+	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+	unsigned long flags;
+	int offset, ret;
+
+	if (!chip)
+		return -EINVAL;
+
+	offset = pin - chip->chip.base;
+
+	samsung_gpio_lock(chip, flags);
+	ret = samsung_gpio_do_setpull(chip, offset, pull);
+	samsung_gpio_unlock(chip, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(s3c_gpio_setpull);
+
+samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
+{
+	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+	unsigned long flags;
+	int offset;
+	u32 pup = 0;
+
+	if (chip) {
+		offset = pin - chip->chip.base;
+
+		samsung_gpio_lock(chip, flags);
+		pup = samsung_gpio_do_getpull(chip, offset);
+		samsung_gpio_unlock(chip, flags);
+	}
+
+	return (__force samsung_gpio_pull_t)pup;
+}
+EXPORT_SYMBOL(s3c_gpio_getpull);
+
+/* gpiolib wrappers until these are totally eliminated */
+
+void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
+{
+	int ret;
+
+	WARN_ON(to);	/* should be none of these left */
+
+	if (!to) {
+		/* if pull is enabled, try first with up, and if that
+		 * fails, try using down */
+
+		ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
+		if (ret)
+			s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
+	} else {
+		s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
+	}
+}
+EXPORT_SYMBOL(s3c2410_gpio_pullup);
+
+void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
+{
+	/* do this via gpiolib until all users removed */
+
+	gpio_request(pin, "temporary");
+	gpio_set_value(pin, to);
+	gpio_free(pin);
+}
+EXPORT_SYMBOL(s3c2410_gpio_setpin);
+
+unsigned int s3c2410_gpio_getpin(unsigned int pin)
+{
+	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+	unsigned long offs = pin - chip->chip.base;
+
+	return __raw_readl(chip->base + 0x04) & (1 << offs);
+}
+EXPORT_SYMBOL(s3c2410_gpio_getpin);
+
+#ifdef CONFIG_S5P_GPIO_DRVSTR
+s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
+{
+	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+	unsigned int off;
+	void __iomem *reg;
+	int shift;
+	u32 drvstr;
+
+	if (!chip)
+		return -EINVAL;
+
+	off = pin - chip->chip.base;
+	shift = off * 2;
+	reg = chip->base + 0x0C;
+
+	drvstr = __raw_readl(reg);
+	drvstr = drvstr >> shift;
+	drvstr &= 0x3;
+
+	return (__force s5p_gpio_drvstr_t)drvstr;
+}
+EXPORT_SYMBOL(s5p_gpio_get_drvstr);
+
+int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
+{
+	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+	unsigned int off;
+	void __iomem *reg;
+	int shift;
+	u32 tmp;
+
+	if (!chip)
+		return -EINVAL;
+
+	off = pin - chip->chip.base;
+	shift = off * 2;
+	reg = chip->base + 0x0C;
+
+	tmp = __raw_readl(reg);
+	tmp &= ~(0x3 << shift);
+	tmp |= drvstr << shift;
+
+	__raw_writel(tmp, reg);
+
+	return 0;
+}
+EXPORT_SYMBOL(s5p_gpio_set_drvstr);
+#endif	/* CONFIG_S5P_GPIO_DRVSTR */
+
+#ifdef CONFIG_PLAT_S3C24XX
+unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
+{
+	unsigned long flags;
+	unsigned long misccr;
+
+	local_irq_save(flags);
+	misccr = __raw_readl(S3C24XX_MISCCR);
+	misccr &= ~clear;
+	misccr ^= change;
+	__raw_writel(misccr, S3C24XX_MISCCR);
+	local_irq_restore(flags);
+
+	return misccr;
+}
+EXPORT_SYMBOL(s3c2410_modify_misccr);
+#endif
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-tegra.c linux-libre-3.2-gnu/drivers/gpio/gpio-tegra.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-tegra.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-tegra.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,13 +20,15 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
 
 #include <asm/mach/irq.h>
 
+#include <mach/gpio-tegra.h>
 #include <mach/iomap.h>
 #include <mach/suspend.h>
 
@@ -34,9 +36,7 @@
 #define GPIO_PORT(x)		(((x) >> 3) & 0x3)
 #define GPIO_BIT(x)		((x) & 0x7)
 
-#define GPIO_REG(x)		(IO_TO_VIRT(TEGRA_GPIO_BASE) +	\
-				 GPIO_BANK(x) * 0x80 +		\
-				 GPIO_PORT(x) * 4)
+#define GPIO_REG(x)		(GPIO_BANK(x) * 0x80 + GPIO_PORT(x) * 4)
 
 #define GPIO_CNF(x)		(GPIO_REG(x) + 0x00)
 #define GPIO_OE(x)		(GPIO_REG(x) + 0x10)
@@ -75,15 +75,18 @@
 };
 
 
-static struct tegra_gpio_bank tegra_gpio_banks[] = {
-	{.bank = 0, .irq = INT_GPIO1},
-	{.bank = 1, .irq = INT_GPIO2},
-	{.bank = 2, .irq = INT_GPIO3},
-	{.bank = 3, .irq = INT_GPIO4},
-	{.bank = 4, .irq = INT_GPIO5},
-	{.bank = 5, .irq = INT_GPIO6},
-	{.bank = 6, .irq = INT_GPIO7},
-};
+static void __iomem *regs;
+static struct tegra_gpio_bank tegra_gpio_banks[7];
+
+static inline void tegra_gpio_writel(u32 val, u32 reg)
+{
+	__raw_writel(val, regs + reg);
+}
+
+static inline u32 tegra_gpio_readl(u32 reg)
+{
+	return __raw_readl(regs + reg);
+}
 
 static int tegra_gpio_compose(int bank, int port, int bit)
 {
@@ -97,7 +100,7 @@
 	val = 0x100 << GPIO_BIT(gpio);
 	if (value)
 		val |= 1 << GPIO_BIT(gpio);
-	__raw_writel(val, reg);
+	tegra_gpio_writel(val, reg);
 }
 
 void tegra_gpio_enable(int gpio)
@@ -117,7 +120,7 @@
 
 static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
-	return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
+	return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
 }
 
 static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -134,7 +137,10 @@
 	return 0;
 }
 
-
+static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	return TEGRA_GPIO_TO_IRQ(offset);
+}
 
 static struct gpio_chip tegra_gpio_chip = {
 	.label			= "tegra-gpio",
@@ -142,6 +148,7 @@
 	.get			= tegra_gpio_get,
 	.direction_output	= tegra_gpio_direction_output,
 	.set			= tegra_gpio_set,
+	.to_irq			= tegra_gpio_to_irq,
 	.base			= 0,
 	.ngpio			= TEGRA_NR_GPIOS,
 };
@@ -150,7 +157,7 @@
 {
 	int gpio = d->irq - INT_GPIO_BASE;
 
-	__raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
+	tegra_gpio_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
 }
 
 static void tegra_gpio_irq_mask(struct irq_data *d)
@@ -203,10 +210,10 @@
 
 	spin_lock_irqsave(&bank->lvl_lock[port], flags);
 
-	val = __raw_readl(GPIO_INT_LVL(gpio));
+	val = tegra_gpio_readl(GPIO_INT_LVL(gpio));
 	val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio));
 	val |= lvl_type << GPIO_BIT(gpio);
-	__raw_writel(val, GPIO_INT_LVL(gpio));
+	tegra_gpio_writel(val, GPIO_INT_LVL(gpio));
 
 	spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
 
@@ -232,12 +239,12 @@
 
 	for (port = 0; port < 4; port++) {
 		int gpio = tegra_gpio_compose(bank->bank, port, 0);
-		unsigned long sta = __raw_readl(GPIO_INT_STA(gpio)) &
-			__raw_readl(GPIO_INT_ENB(gpio));
-		u32 lvl = __raw_readl(GPIO_INT_LVL(gpio));
+		unsigned long sta = tegra_gpio_readl(GPIO_INT_STA(gpio)) &
+			tegra_gpio_readl(GPIO_INT_ENB(gpio));
+		u32 lvl = tegra_gpio_readl(GPIO_INT_LVL(gpio));
 
 		for_each_set_bit(pin, &sta, 8) {
-			__raw_writel(1 << pin, GPIO_INT_CLR(gpio));
+			tegra_gpio_writel(1 << pin, GPIO_INT_CLR(gpio));
 
 			/* if gpio is edge triggered, clear condition
 			 * before executing the hander so that we don't
@@ -271,11 +278,11 @@
 
 		for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
 			unsigned int gpio = (b<<5) | (p<<3);
-			__raw_writel(bank->cnf[p], GPIO_CNF(gpio));
-			__raw_writel(bank->out[p], GPIO_OUT(gpio));
-			__raw_writel(bank->oe[p], GPIO_OE(gpio));
-			__raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
-			__raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
+			tegra_gpio_writel(bank->cnf[p], GPIO_CNF(gpio));
+			tegra_gpio_writel(bank->out[p], GPIO_OUT(gpio));
+			tegra_gpio_writel(bank->oe[p], GPIO_OE(gpio));
+			tegra_gpio_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
+			tegra_gpio_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
 		}
 	}
 
@@ -294,11 +301,11 @@
 
 		for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
 			unsigned int gpio = (b<<5) | (p<<3);
-			bank->cnf[p] = __raw_readl(GPIO_CNF(gpio));
-			bank->out[p] = __raw_readl(GPIO_OUT(gpio));
-			bank->oe[p] = __raw_readl(GPIO_OE(gpio));
-			bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio));
-			bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio));
+			bank->cnf[p] = tegra_gpio_readl(GPIO_CNF(gpio));
+			bank->out[p] = tegra_gpio_readl(GPIO_OUT(gpio));
+			bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio));
+			bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio));
+			bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio));
 		}
 	}
 	local_irq_restore(flags);
@@ -328,38 +335,69 @@
  */
 static struct lock_class_key gpio_lock_class;
 
-static int __init tegra_gpio_init(void)
+static int __devinit tegra_gpio_probe(struct platform_device *pdev)
 {
+	struct resource *res;
 	struct tegra_gpio_bank *bank;
+	int gpio;
 	int i;
 	int j;
 
+	for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
+		res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+		if (!res) {
+			dev_err(&pdev->dev, "Missing IRQ resource\n");
+			return -ENODEV;
+		}
+
+		bank = &tegra_gpio_banks[i];
+		bank->bank = i;
+		bank->irq = res->start;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "Missing MEM resource\n");
+		return -ENODEV;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev, res->start,
+				     resource_size(res),
+				     dev_name(&pdev->dev))) {
+		dev_err(&pdev->dev, "Couldn't request MEM resource\n");
+		return -ENODEV;
+	}
+
+	regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!regs) {
+		dev_err(&pdev->dev, "Couldn't ioremap regs\n");
+		return -ENODEV;
+	}
+
 	for (i = 0; i < 7; i++) {
 		for (j = 0; j < 4; j++) {
 			int gpio = tegra_gpio_compose(i, j, 0);
-			__raw_writel(0x00, GPIO_INT_ENB(gpio));
+			tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio));
 		}
 	}
 
 #ifdef CONFIG_OF_GPIO
-	/*
-	 * This isn't ideal, but it gets things hooked up until this
-	 * driver is converted into a platform_device
-	 */
-	tegra_gpio_chip.of_node = of_find_compatible_node(NULL, NULL,
-						"nvidia,tegra20-gpio");
-#endif /* CONFIG_OF_GPIO */
+	tegra_gpio_chip.of_node = pdev->dev.of_node;
+#endif
 
 	gpiochip_add(&tegra_gpio_chip);
 
-	for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
-		bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))];
+	for (gpio = 0; gpio < TEGRA_NR_GPIOS; gpio++) {
+		int irq = TEGRA_GPIO_TO_IRQ(gpio);
+		/* No validity check; all Tegra GPIOs are valid IRQs */
 
-		irq_set_lockdep_class(i, &gpio_lock_class);
-		irq_set_chip_data(i, bank);
-		irq_set_chip_and_handler(i, &tegra_gpio_irq_chip,
+		bank = &tegra_gpio_banks[GPIO_BANK(gpio)];
+
+		irq_set_lockdep_class(irq, &gpio_lock_class);
+		irq_set_chip_data(irq, bank);
+		irq_set_chip_and_handler(irq, &tegra_gpio_irq_chip,
 					 handle_simple_irq);
-		set_irq_flags(i, IRQF_VALID);
+		set_irq_flags(irq, IRQF_VALID);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
@@ -375,6 +413,24 @@
 	return 0;
 }
 
+static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
+	{ .compatible = "nvidia,tegra20-gpio", },
+	{ },
+};
+
+static struct platform_driver tegra_gpio_driver = {
+	.driver		= {
+		.name	= "tegra-gpio",
+		.owner	= THIS_MODULE,
+		.of_match_table = tegra_gpio_of_match,
+	},
+	.probe		= tegra_gpio_probe,
+};
+
+static int __init tegra_gpio_init(void)
+{
+	return platform_driver_register(&tegra_gpio_driver);
+}
 postcore_initcall(tegra_gpio_init);
 
 void __init tegra_gpio_config(struct tegra_gpio_table *table, int num)
@@ -407,13 +463,13 @@
 			seq_printf(s,
 				"%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
 				i, j,
-				__raw_readl(GPIO_CNF(gpio)),
-				__raw_readl(GPIO_OE(gpio)),
-				__raw_readl(GPIO_OUT(gpio)),
-				__raw_readl(GPIO_IN(gpio)),
-				__raw_readl(GPIO_INT_STA(gpio)),
-				__raw_readl(GPIO_INT_ENB(gpio)),
-				__raw_readl(GPIO_INT_LVL(gpio)));
+				tegra_gpio_readl(GPIO_CNF(gpio)),
+				tegra_gpio_readl(GPIO_OE(gpio)),
+				tegra_gpio_readl(GPIO_OUT(gpio)),
+				tegra_gpio_readl(GPIO_IN(gpio)),
+				tegra_gpio_readl(GPIO_INT_STA(gpio)),
+				tegra_gpio_readl(GPIO_INT_ENB(gpio)),
+				tegra_gpio_readl(GPIO_INT_LVL(gpio)));
 		}
 	}
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-tnetv107x.c linux-libre-3.2-gnu/drivers/gpio/gpio-tnetv107x.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-tnetv107x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-tnetv107x.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,205 @@
+/*
+ * Texas Instruments TNETV107X GPIO Controller
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+
+#include <mach/common.h>
+#include <mach/tnetv107x.h>
+
+struct tnetv107x_gpio_regs {
+	u32	idver;
+	u32	data_in[3];
+	u32	data_out[3];
+	u32	direction[3];
+	u32	enable[3];
+};
+
+#define gpio_reg_index(gpio)	((gpio) >> 5)
+#define gpio_reg_bit(gpio)	BIT((gpio) & 0x1f)
+
+#define gpio_reg_rmw(reg, mask, val)	\
+	__raw_writel((__raw_readl(reg) & ~(mask)) | (val), (reg))
+
+#define gpio_reg_set_bit(reg, gpio)	\
+	gpio_reg_rmw((reg) + gpio_reg_index(gpio), 0, gpio_reg_bit(gpio))
+
+#define gpio_reg_clear_bit(reg, gpio)	\
+	gpio_reg_rmw((reg) + gpio_reg_index(gpio), gpio_reg_bit(gpio), 0)
+
+#define gpio_reg_get_bit(reg, gpio)	\
+	(__raw_readl((reg) + gpio_reg_index(gpio)) & gpio_reg_bit(gpio))
+
+#define chip2controller(chip)		\
+	container_of(chip, struct davinci_gpio_controller, chip)
+
+#define TNETV107X_GPIO_CTLRS	DIV_ROUND_UP(TNETV107X_N_GPIO, 32)
+
+static struct davinci_gpio_controller chips[TNETV107X_GPIO_CTLRS];
+
+static int tnetv107x_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct davinci_gpio_controller *ctlr = chip2controller(chip);
+	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
+	unsigned gpio = chip->base + offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	gpio_reg_set_bit(regs->enable, gpio);
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+
+	return 0;
+}
+
+static void tnetv107x_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	struct davinci_gpio_controller *ctlr = chip2controller(chip);
+	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
+	unsigned gpio = chip->base + offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	gpio_reg_clear_bit(regs->enable, gpio);
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+}
+
+static int tnetv107x_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
+{
+	struct davinci_gpio_controller *ctlr = chip2controller(chip);
+	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
+	unsigned gpio = chip->base + offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	gpio_reg_set_bit(regs->direction, gpio);
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+
+	return 0;
+}
+
+static int tnetv107x_gpio_dir_out(struct gpio_chip *chip,
+		unsigned offset, int value)
+{
+	struct davinci_gpio_controller *ctlr = chip2controller(chip);
+	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
+	unsigned gpio = chip->base + offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	if (value)
+		gpio_reg_set_bit(regs->data_out, gpio);
+	else
+		gpio_reg_clear_bit(regs->data_out, gpio);
+
+	gpio_reg_clear_bit(regs->direction, gpio);
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+
+	return 0;
+}
+
+static int tnetv107x_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct davinci_gpio_controller *ctlr = chip2controller(chip);
+	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
+	unsigned gpio = chip->base + offset;
+	int ret;
+
+	ret = gpio_reg_get_bit(regs->data_in, gpio);
+
+	return ret ? 1 : 0;
+}
+
+static void tnetv107x_gpio_set(struct gpio_chip *chip,
+		unsigned offset, int value)
+{
+	struct davinci_gpio_controller *ctlr = chip2controller(chip);
+	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
+	unsigned gpio = chip->base + offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	if (value)
+		gpio_reg_set_bit(regs->data_out, gpio);
+	else
+		gpio_reg_clear_bit(regs->data_out, gpio);
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+}
+
+static int __init tnetv107x_gpio_setup(void)
+{
+	int i, base;
+	unsigned ngpio;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+	struct tnetv107x_gpio_regs *regs;
+	struct davinci_gpio_controller *ctlr;
+
+	if (soc_info->gpio_type != GPIO_TYPE_TNETV107X)
+		return 0;
+
+	ngpio = soc_info->gpio_num;
+	if (ngpio == 0) {
+		pr_err("GPIO setup:  how many GPIOs?\n");
+		return -EINVAL;
+	}
+
+	if (WARN_ON(TNETV107X_N_GPIO < ngpio))
+		ngpio = TNETV107X_N_GPIO;
+
+	regs = ioremap(soc_info->gpio_base, SZ_4K);
+	if (WARN_ON(!regs))
+		return -EINVAL;
+
+	for (i = 0, base = 0; base < ngpio; i++, base += 32) {
+		ctlr = &chips[i];
+
+		ctlr->chip.label	= "tnetv107x";
+		ctlr->chip.can_sleep	= 0;
+		ctlr->chip.base		= base;
+		ctlr->chip.ngpio	= ngpio - base;
+		if (ctlr->chip.ngpio > 32)
+			ctlr->chip.ngpio = 32;
+
+		ctlr->chip.request		= tnetv107x_gpio_request;
+		ctlr->chip.free			= tnetv107x_gpio_free;
+		ctlr->chip.direction_input	= tnetv107x_gpio_dir_in;
+		ctlr->chip.get			= tnetv107x_gpio_get;
+		ctlr->chip.direction_output	= tnetv107x_gpio_dir_out;
+		ctlr->chip.set			= tnetv107x_gpio_set;
+
+		spin_lock_init(&ctlr->lock);
+
+		ctlr->regs	= regs;
+		ctlr->set_data	= &regs->data_out[i];
+		ctlr->clr_data	= &regs->data_out[i];
+		ctlr->in_data	= &regs->data_in[i];
+
+		gpiochip_add(&ctlr->chip);
+	}
+
+	soc_info->gpio_ctlrs = chips;
+	soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32);
+	return 0;
+}
+pure_initcall(tnetv107x_gpio_setup);
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-u300.c linux-libre-3.2-gnu/drivers/gpio/gpio-u300.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-u300.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-u300.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,18 +1,17 @@
 /*
  * U300 GPIO module.
  *
- * Copyright (C) 2007-2009 ST-Ericsson AB
+ * Copyright (C) 2007-2011 ST-Ericsson AB
  * License terms: GNU General Public License (GPL) version 2
  * This can driver either of the two basic GPIO cores
  * available in the U300 platforms:
  * COH 901 335   - Used in DB3150 (U300 1.0) and DB3200 (U330 1.0)
  * COH 901 571/3 - Used in DB3210 (U365 2.0) and DB3350 (U335 1.0)
- * Notice that you also have inline macros in <asm-arch/gpio.h>
- * Author: Linus Walleij <linus.walleij@stericsson.com>
+ * Author: Linus Walleij <linus.walleij@linaro.org>
  * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
- *
  */
 #include <linux/module.h>
+#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -21,677 +20,898 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <mach/gpio-u300.h>
 
-/* Reference to GPIO block clock */
-static struct clk *clk;
+/*
+ * Bias modes for U300 GPIOs
+ *
+ * GPIO_U300_CONFIG_BIAS_UNKNOWN: this bias mode is not known to us
+ * GPIO_U300_CONFIG_BIAS_FLOAT: no specific bias, the GPIO will float or state
+ *	is not controlled by software
+ * GPIO_U300_CONFIG_BIAS_PULL_UP: the GPIO will be pulled up (usually with high
+ *	impedance to VDD)
+ */
+#define GPIO_U300_CONFIG_BIAS_UNKNOWN	0x1000
+#define GPIO_U300_CONFIG_BIAS_FLOAT	0x1001
+#define GPIO_U300_CONFIG_BIAS_PULL_UP	0x1002
 
-/* Memory resource */
-static struct resource *memres;
-static void __iomem *virtbase;
-static struct device *gpiodev;
+/*
+ * Drive modes for U300 GPIOs (output)
+ *
+ * GPIO_U300_CONFIG_DRIVE_PUSH_PULL: the GPIO will be driven actively high and
+ *	low, this is the most typical case and is typically achieved with two
+ *	active transistors on the output
+ * GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN: the GPIO will be driven with open drain
+ *	(open collector) which means it is usually wired with other output
+ *	ports which are then pulled up with an external resistor
+ * GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE: the GPIO will be driven with open drain
+ *	(open emitter) which is the same as open drain mutatis mutandis but
+ *	pulled to ground
+ */
+#define GPIO_U300_CONFIG_DRIVE_PUSH_PULL	0x2000
+#define GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN	0x2001
+#define GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE	0x2002
+
+/*
+ * Register definitions for COH 901 335 variant
+ */
+#define U300_335_PORT_STRIDE				(0x1C)
+/* Port X Pin Data Register 32bit, this is both input and output (R/W) */
+#define U300_335_PXPDIR					(0x00)
+#define U300_335_PXPDOR					(0x00)
+/* Port X Pin Config Register 32bit (R/W) */
+#define U300_335_PXPCR					(0x04)
+/* This register layout is the same in both blocks */
+#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK		(0x0000FFFFUL)
+#define U300_GPIO_PXPCR_PIN_MODE_MASK			(0x00000003UL)
+#define U300_GPIO_PXPCR_PIN_MODE_SHIFT			(0x00000002UL)
+#define U300_GPIO_PXPCR_PIN_MODE_INPUT			(0x00000000UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL	(0x00000001UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN	(0x00000002UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE	(0x00000003UL)
+/* Port X Interrupt Event Register 32bit (R/W) */
+#define U300_335_PXIEV					(0x08)
+/* Port X Interrupt Enable Register 32bit (R/W) */
+#define U300_335_PXIEN					(0x0C)
+/* Port X Interrupt Force Register 32bit (R/W) */
+#define U300_335_PXIFR					(0x10)
+/* Port X Interrupt Config Register 32bit (R/W) */
+#define U300_335_PXICR					(0x14)
+/* This register layout is the same in both blocks */
+#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK		(0x000000FFUL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_MASK			(0x00000001UL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE		(0x00000000UL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE		(0x00000001UL)
+/* Port X Pull-up Enable Register 32bit (R/W) */
+#define U300_335_PXPER					(0x18)
+/* This register layout is the same in both blocks */
+#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK	(0x000000FFUL)
+#define U300_GPIO_PXPER_PULL_UP_DISABLE			(0x00000001UL)
+/* Control Register 32bit (R/W) */
+#define U300_335_CR					(0x54)
+#define U300_335_CR_BLOCK_CLOCK_ENABLE			(0x00000001UL)
+
+/*
+ * Register definitions for COH 901 571 / 3 variant
+ */
+#define U300_571_PORT_STRIDE				(0x30)
+/*
+ * Control Register 32bit (R/W)
+ * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores
+ * gives the number of GPIO pins.
+ * bit 8-2  (mask 0x000001FC) contains the core version ID.
+ */
+#define U300_571_CR					(0x00)
+#define U300_571_CR_SYNC_SEL_ENABLE			(0x00000002UL)
+#define U300_571_CR_BLOCK_CLKRQ_ENABLE			(0x00000001UL)
+/*
+ * These registers have the same layout and function as the corresponding
+ * COH 901 335 registers, just at different offset.
+ */
+#define U300_571_PXPDIR					(0x04)
+#define U300_571_PXPDOR					(0x08)
+#define U300_571_PXPCR					(0x0C)
+#define U300_571_PXPER					(0x10)
+#define U300_571_PXIEV					(0x14)
+#define U300_571_PXIEN					(0x18)
+#define U300_571_PXIFR					(0x1C)
+#define U300_571_PXICR					(0x20)
+
+/* 8 bits per port, no version has more than 7 ports */
+#define U300_GPIO_PINS_PER_PORT 8
+#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * 7)
+
+struct u300_gpio {
+	struct gpio_chip chip;
+	struct list_head port_list;
+	struct clk *clk;
+	struct resource *memres;
+	void __iomem *base;
+	struct device *dev;
+	int irq_base;
+	u32 stride;
+	/* Register offsets */
+	u32 pcr;
+	u32 dor;
+	u32 dir;
+	u32 per;
+	u32 icr;
+	u32 ien;
+	u32 iev;
+};
 
 struct u300_gpio_port {
-	const char *name;
+	struct list_head node;
+	struct u300_gpio *gpio;
+	char name[8];
 	int irq;
 	int number;
+	u8 toggle_edge_mode;
 };
 
+/*
+ * Macro to expand to read a specific register found in the "gpio"
+ * struct. It requires the struct u300_gpio *gpio variable to exist in
+ * its context. It calculates the port offset from the given pin
+ * offset, muliplies by the port stride and adds the register offset
+ * so it provides a pointer to the desired register.
+ */
+#define U300_PIN_REG(pin, reg) \
+	(gpio->base + (pin >> 3) * gpio->stride + gpio->reg)
 
-static struct u300_gpio_port gpio_ports[] = {
-	{
-		.name = "gpio0",
-		.number = 0,
-	},
-	{
-		.name = "gpio1",
-		.number = 1,
-	},
-	{
-		.name = "gpio2",
-		.number = 2,
-	},
-#ifdef U300_COH901571_3
-	{
-		.name = "gpio3",
-		.number = 3,
-	},
-	{
-		.name = "gpio4",
-		.number = 4,
-	},
-#ifdef CONFIG_MACH_U300_BS335
-	{
-		.name = "gpio5",
-		.number = 5,
-	},
-	{
-		.name = "gpio6",
-		.number = 6,
-	},
-#endif
-#endif
+/*
+ * Provides a bitmask for a specific gpio pin inside an 8-bit GPIO
+ * register.
+ */
+#define U300_PIN_BIT(pin) \
+	(1 << (pin & 0x07))
 
+struct u300_gpio_confdata {
+	u16 bias_mode;
+	bool output;
+	int outval;
 };
 
+/* BS335 has seven ports of 8 bits each = GPIO pins 0..55 */
+#define BS335_GPIO_NUM_PORTS 7
+/* BS365 has five ports of 8 bits each = GPIO pins 0..39 */
+#define BS365_GPIO_NUM_PORTS 5
 
-#ifdef U300_COH901571_3
+#define U300_FLOATING_INPUT { \
+	.bias_mode = GPIO_U300_CONFIG_BIAS_FLOAT, \
+	.output = false, \
+}
 
-/* Default input value */
-#define DEFAULT_OUTPUT_LOW   0
-#define DEFAULT_OUTPUT_HIGH  1
+#define U300_PULL_UP_INPUT { \
+	.bias_mode = GPIO_U300_CONFIG_BIAS_PULL_UP, \
+	.output = false, \
+}
 
-/* GPIO Pull-Up status */
-#define DISABLE_PULL_UP  0
-#define ENABLE_PULL_UP  1
+#define U300_OUTPUT_LOW { \
+	.output = true, \
+	.outval = 0, \
+}
 
-#define GPIO_NOT_USED 0
-#define GPIO_IN       1
-#define GPIO_OUT      2
+#define U300_OUTPUT_HIGH { \
+	.output = true, \
+	.outval = 1, \
+}
 
-struct u300_gpio_configuration_data {
-	unsigned char pin_usage;
-	unsigned char default_output_value;
-	unsigned char pull_up;
-};
 
 /* Initial configuration */
-const struct u300_gpio_configuration_data
-u300_gpio_config[U300_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
-#ifdef CONFIG_MACH_U300_BS335
+static const struct __initdata u300_gpio_confdata
+bs335_gpio_config[BS335_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
 	/* Port 0, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_HIGH,  DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+		U300_FLOATING_INPUT,
+		U300_OUTPUT_HIGH,
+		U300_FLOATING_INPUT,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
 	},
 	/* Port 1, pins 0-7 */
 	{
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_HIGH,  DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_PULL_UP_INPUT,
+		U300_FLOATING_INPUT,
+		U300_OUTPUT_HIGH,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
 	},
 	/* Port 2, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_OUTPUT_LOW,
+		U300_PULL_UP_INPUT,
+		U300_OUTPUT_LOW,
+		U300_PULL_UP_INPUT,
 	},
 	/* Port 3, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+		U300_PULL_UP_INPUT,
+		U300_OUTPUT_LOW,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
 	},
 	/* Port 4, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
 	},
 	/* Port 5, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
 	},
 	/* Port 6, pind 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
 	}
-#endif
+};
 
-#ifdef CONFIG_MACH_U300_BS365
+static const struct __initdata u300_gpio_confdata
+bs365_gpio_config[BS365_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
 	/* Port 0, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+		U300_FLOATING_INPUT,
+		U300_OUTPUT_LOW,
+		U300_FLOATING_INPUT,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_PULL_UP_INPUT,
+		U300_FLOATING_INPUT,
 	},
 	/* Port 1, pins 0-7 */
 	{
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_HIGH,  DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+		U300_OUTPUT_LOW,
+		U300_FLOATING_INPUT,
+		U300_OUTPUT_LOW,
+		U300_FLOATING_INPUT,
+		U300_FLOATING_INPUT,
+		U300_OUTPUT_HIGH,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
 	},
 	/* Port 2, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
+		U300_FLOATING_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
 	},
 	/* Port 3, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
 	},
 	/* Port 4, pins 0-7 */
 	{
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
+		U300_PULL_UP_INPUT,
 		/* These 4 pins doesn't exist on DB3210 */
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-		{GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
+		U300_OUTPUT_LOW,
 	}
-#endif
-};
-#endif
-
-
-/* No users == we can power down GPIO */
-static int gpio_users;
-
-struct gpio_struct {
-	int (*callback)(void *);
-	void *data;
-	int users;
 };
 
-static struct gpio_struct gpio_pin[U300_GPIO_MAX];
-
-/*
- * Let drivers register callback in order to get notified when there is
- * an interrupt on the gpio pin
+/**
+ * to_u300_gpio() - get the pointer to u300_gpio
+ * @chip: the gpio chip member of the structure u300_gpio
  */
-int gpio_register_callback(unsigned gpio, int (*func)(void *arg), void *data)
+static inline struct u300_gpio *to_u300_gpio(struct gpio_chip *chip)
 {
-	if (gpio_pin[gpio].callback)
-		dev_warn(gpiodev, "%s: WARNING: callback already "
-			 "registered for gpio pin#%d\n", __func__, gpio);
-	gpio_pin[gpio].callback = func;
-	gpio_pin[gpio].data = data;
-
-	return 0;
+	return container_of(chip, struct u300_gpio, chip);
 }
-EXPORT_SYMBOL(gpio_register_callback);
 
-int gpio_unregister_callback(unsigned gpio)
+static int u300_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
-	if (!gpio_pin[gpio].callback)
-		dev_warn(gpiodev, "%s: WARNING: callback already "
-			 "unregistered for gpio pin#%d\n", __func__, gpio);
-	gpio_pin[gpio].callback = NULL;
-	gpio_pin[gpio].data = NULL;
+	struct u300_gpio *gpio = to_u300_gpio(chip);
 
-	return 0;
+	return readl(U300_PIN_REG(offset, dir)) & U300_PIN_BIT(offset);
 }
-EXPORT_SYMBOL(gpio_unregister_callback);
 
-/* Non-zero means valid */
-int gpio_is_valid(int number)
+static void u300_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
-	if (number >= 0 &&
-	    number < (U300_GPIO_NUM_PORTS * U300_GPIO_PINS_PER_PORT))
-		return 1;
-	return 0;
-}
-EXPORT_SYMBOL(gpio_is_valid);
+	struct u300_gpio *gpio = to_u300_gpio(chip);
+	unsigned long flags;
+	u32 val;
 
-int gpio_request(unsigned gpio, const char *label)
-{
-	if (gpio_pin[gpio].users)
-		return -EINVAL;
-	else
-		gpio_pin[gpio].users++;
+	local_irq_save(flags);
 
-	gpio_users++;
+	val = readl(U300_PIN_REG(offset, dor));
+	if (value)
+		writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, dor));
+	else
+		writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, dor));
 
-	return 0;
+	local_irq_restore(flags);
 }
-EXPORT_SYMBOL(gpio_request);
 
-void gpio_free(unsigned gpio)
+static int u300_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 {
-	gpio_users--;
-	gpio_pin[gpio].users--;
-	if (unlikely(gpio_pin[gpio].users < 0)) {
-		dev_warn(gpiodev, "warning: gpio#%d release mismatch\n",
-			 gpio);
-		gpio_pin[gpio].users = 0;
-	}
-
-	return;
-}
-EXPORT_SYMBOL(gpio_free);
+	struct u300_gpio *gpio = to_u300_gpio(chip);
+	unsigned long flags;
+	u32 val;
 
-/* This returns zero or nonzero */
-int gpio_get_value(unsigned gpio)
-{
-	return readl(virtbase + U300_GPIO_PXPDIR +
-	  PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING) & (1 << (gpio & 0x07));
+	local_irq_save(flags);
+	val = readl(U300_PIN_REG(offset, pcr));
+	/* Mask out this pin, note 2 bits per setting */
+	val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((offset & 0x07) << 1));
+	writel(val, U300_PIN_REG(offset, pcr));
+	local_irq_restore(flags);
+	return 0;
 }
-EXPORT_SYMBOL(gpio_get_value);
 
-/*
- * We hope that the compiler will optimize away the unused branch
- * in case "value" is a constant
- */
-void gpio_set_value(unsigned gpio, int value)
+static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+				      int value)
 {
-	u32 val;
+	struct u300_gpio *gpio = to_u300_gpio(chip);
 	unsigned long flags;
+	u32 oldmode;
+	u32 val;
 
 	local_irq_save(flags);
-	if (value) {
-		/* set */
-		val = readl(virtbase + U300_GPIO_PXPDOR +
-		  PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING)
-		  & (1 << (gpio & 0x07));
-		writel(val | (1 << (gpio & 0x07)), virtbase +
-		  U300_GPIO_PXPDOR +
-		  PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
-	} else {
-		/* clear */
-		val = readl(virtbase + U300_GPIO_PXPDOR +
-		  PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING)
-		  & (1 << (gpio & 0x07));
-		writel(val & ~(1 << (gpio & 0x07)), virtbase +
-		  U300_GPIO_PXPDOR +
-		  PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
+	val = readl(U300_PIN_REG(offset, pcr));
+	/*
+	 * Drive mode must be set by the special mode set function, set
+	 * push/pull mode by default if no mode has been selected.
+	 */
+	oldmode = val & (U300_GPIO_PXPCR_PIN_MODE_MASK <<
+			 ((offset & 0x07) << 1));
+	/* mode = 0 means input, else some mode is already set */
+	if (oldmode == 0) {
+		val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK <<
+			 ((offset & 0x07) << 1));
+		val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
+			<< ((offset & 0x07) << 1));
+		writel(val, U300_PIN_REG(offset, pcr));
 	}
+	u300_gpio_set(chip, offset, value);
 	local_irq_restore(flags);
+	return 0;
 }
-EXPORT_SYMBOL(gpio_set_value);
 
-int gpio_direction_input(unsigned gpio)
+static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct u300_gpio *gpio = to_u300_gpio(chip);
+	int retirq = gpio->irq_base + offset;
+
+	dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d\n", offset,
+		retirq);
+	return retirq;
+}
+
+static int u300_gpio_config(struct gpio_chip *chip, unsigned offset,
+		     u16 param, unsigned long *data)
 {
+	struct u300_gpio *gpio = to_u300_gpio(chip);
 	unsigned long flags;
 	u32 val;
 
-	if (gpio > U300_GPIO_MAX)
-		return -EINVAL;
-
 	local_irq_save(flags);
-	val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
-	/* Mask out this pin*/
-	val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1));
-	/* This is not needed since it sets the bits to zero.*/
-	/* val |= (U300_GPIO_PXPCR_PIN_MODE_INPUT << (gpio*2)); */
-	writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
+	switch (param) {
+	case GPIO_U300_CONFIG_BIAS_UNKNOWN:
+	case GPIO_U300_CONFIG_BIAS_FLOAT:
+		val = readl(U300_PIN_REG(offset, per));
+		writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, per));
+		break;
+	case GPIO_U300_CONFIG_BIAS_PULL_UP:
+		val = readl(U300_PIN_REG(offset, per));
+		writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, per));
+		break;
+	case GPIO_U300_CONFIG_DRIVE_PUSH_PULL:
+		val = readl(U300_PIN_REG(offset, pcr));
+		val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK
+			 << ((offset & 0x07) << 1));
+		val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
+			<< ((offset & 0x07) << 1));
+		writel(val, U300_PIN_REG(offset, pcr));
+		break;
+	case GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN:
+		val = readl(U300_PIN_REG(offset, pcr));
+		val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK
+			 << ((offset & 0x07) << 1));
+		val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN
+			<< ((offset & 0x07) << 1));
+		writel(val, U300_PIN_REG(offset, pcr));
+		break;
+	case GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE:
+		val = readl(U300_PIN_REG(offset, pcr));
+		val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK
+			 << ((offset & 0x07) << 1));
+		val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE
+			<< ((offset & 0x07) << 1));
+		writel(val, U300_PIN_REG(offset, pcr));
+		break;
+	default:
+		local_irq_restore(flags);
+		dev_err(gpio->dev, "illegal configuration requested\n");
+		return -EINVAL;
+	}
 	local_irq_restore(flags);
 	return 0;
 }
-EXPORT_SYMBOL(gpio_direction_input);
 
-int gpio_direction_output(unsigned gpio, int value)
+static struct gpio_chip u300_gpio_chip = {
+	.label			= "u300-gpio-chip",
+	.owner			= THIS_MODULE,
+	.get			= u300_gpio_get,
+	.set			= u300_gpio_set,
+	.direction_input	= u300_gpio_direction_input,
+	.direction_output	= u300_gpio_direction_output,
+	.to_irq			= u300_gpio_to_irq,
+};
+
+static void u300_toggle_trigger(struct u300_gpio *gpio, unsigned offset)
 {
-	unsigned long flags;
 	u32 val;
 
-	if (gpio > U300_GPIO_MAX)
-		return -EINVAL;
-
-	local_irq_save(flags);
-	val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
-	/* Mask out this pin */
-	val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1));
-	/*
-	 * FIXME: configure for push/pull, open drain or open source per pin
-	 * in setup. The current driver will only support push/pull.
-	 */
-	val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
-			<< ((gpio & 0x07) << 1));
-	writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
-	gpio_set_value(gpio, value);
-	local_irq_restore(flags);
-	return 0;
+	val = readl(U300_PIN_REG(offset, icr));
+	/* Set mode depending on state */
+	if (u300_gpio_get(&gpio->chip, offset)) {
+		/* High now, let's trigger on falling edge next then */
+		writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, icr));
+		dev_dbg(gpio->dev, "next IRQ on falling edge on pin %d\n",
+			offset);
+	} else {
+		/* Low now, let's trigger on rising edge next then */
+		writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, icr));
+		dev_dbg(gpio->dev, "next IRQ on rising edge on pin %d\n",
+			offset);
+	}
 }
-EXPORT_SYMBOL(gpio_direction_output);
 
-/*
- * Enable an IRQ, edge is rising edge (!= 0) or falling edge (==0).
- */
-void enable_irq_on_gpio_pin(unsigned gpio, int edge)
+static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger)
 {
+	struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
+	struct u300_gpio *gpio = port->gpio;
+	int offset = d->irq - gpio->irq_base;
 	u32 val;
-	unsigned long flags;
-	local_irq_save(flags);
 
-	val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
-	val |= (1 << (gpio & 0x07));
-	writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
-	val = readl(virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
-	if (edge)
-		val |= (1 << (gpio & 0x07));
-	else
-		val &= ~(1 << (gpio & 0x07));
-	writel(val, virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
-	local_irq_restore(flags);
+	if ((trigger & IRQF_TRIGGER_RISING) &&
+	    (trigger & IRQF_TRIGGER_FALLING)) {
+		/*
+		 * The GPIO block can only trigger on falling OR rising edges,
+		 * not both. So we need to toggle the mode whenever the pin
+		 * goes from one state to the other with a special state flag
+		 */
+		dev_dbg(gpio->dev,
+			"trigger on both rising and falling edge on pin %d\n",
+			offset);
+		port->toggle_edge_mode |= U300_PIN_BIT(offset);
+		u300_toggle_trigger(gpio, offset);
+	} else if (trigger & IRQF_TRIGGER_RISING) {
+		dev_dbg(gpio->dev, "trigger on rising edge on pin %d\n",
+			offset);
+		val = readl(U300_PIN_REG(offset, icr));
+		writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, icr));
+		port->toggle_edge_mode &= ~U300_PIN_BIT(offset);
+	} else if (trigger & IRQF_TRIGGER_FALLING) {
+		dev_dbg(gpio->dev, "trigger on falling edge on pin %d\n",
+			offset);
+		val = readl(U300_PIN_REG(offset, icr));
+		writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, icr));
+		port->toggle_edge_mode &= ~U300_PIN_BIT(offset);
+	}
+
+	return 0;
 }
-EXPORT_SYMBOL(enable_irq_on_gpio_pin);
 
-void disable_irq_on_gpio_pin(unsigned gpio)
+static void u300_gpio_irq_enable(struct irq_data *d)
 {
+	struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
+	struct u300_gpio *gpio = port->gpio;
+	int offset = d->irq - gpio->irq_base;
 	u32 val;
 	unsigned long flags;
 
 	local_irq_save(flags);
-	val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
-	val &= ~(1 << (gpio & 0x07));
-	writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
-				U300_GPIO_PORTX_SPACING);
+	val = readl(U300_PIN_REG(offset, ien));
+	writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien));
 	local_irq_restore(flags);
 }
-EXPORT_SYMBOL(disable_irq_on_gpio_pin);
 
-/* Enable (value == 0) or disable (value == 1) internal pullup */
-void gpio_pullup(unsigned gpio, int value)
+static void u300_gpio_irq_disable(struct irq_data *d)
 {
+	struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
+	struct u300_gpio *gpio = port->gpio;
+	int offset = d->irq - gpio->irq_base;
 	u32 val;
 	unsigned long flags;
 
 	local_irq_save(flags);
-	if (value) {
-		val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) *
-					U300_GPIO_PORTX_SPACING);
-		writel(val | (1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER +
-				PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
-	} else {
-		val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) *
-					U300_GPIO_PORTX_SPACING);
-		writel(val & ~(1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER +
-				PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
-	}
+	val = readl(U300_PIN_REG(offset, ien));
+	writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, ien));
 	local_irq_restore(flags);
 }
-EXPORT_SYMBOL(gpio_pullup);
 
-static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
+static struct irq_chip u300_gpio_irqchip = {
+	.name			= "u300-gpio-irqchip",
+	.irq_enable		= u300_gpio_irq_enable,
+	.irq_disable		= u300_gpio_irq_disable,
+	.irq_set_type		= u300_gpio_irq_type,
+
+};
+
+static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
-	struct u300_gpio_port *port = dev_id;
-	u32 val;
-	int pin;
+	struct u300_gpio_port *port = irq_get_handler_data(irq);
+	struct u300_gpio *gpio = port->gpio;
+	int pinoffset = port->number << 3; /* get the right stride */
+	unsigned long val;
 
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 	/* Read event register */
-	val = readl(virtbase + U300_GPIO_PXIEV + port->number *
-				U300_GPIO_PORTX_SPACING);
-	/* Mask with enable register */
-	val &= readl(virtbase + U300_GPIO_PXIEV + port->number *
-				U300_GPIO_PORTX_SPACING);
+	val = readl(U300_PIN_REG(pinoffset, iev));
 	/* Mask relevant bits */
-	val &= U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK;
+	val &= 0xFFU; /* 8 bits per port */
 	/* ACK IRQ (clear event) */
-	writel(val, virtbase + U300_GPIO_PXIEV + port->number *
-				U300_GPIO_PORTX_SPACING);
-	/* Print message */
-	while (val != 0) {
-		unsigned gpio;
+	writel(val, U300_PIN_REG(pinoffset, iev));
 
-		pin = __ffs(val);
-		/* mask off this pin */
-		val &= ~(1 << pin);
-		gpio = (port->number << 3) + pin;
+	/* Call IRQ handler */
+	if (val != 0) {
+		int irqoffset;
 
-		if (gpio_pin[gpio].callback)
-			(void)gpio_pin[gpio].callback(gpio_pin[gpio].data);
-		else
-			dev_dbg(gpiodev, "stray GPIO IRQ on line %d\n",
-			       gpio);
+		for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) {
+			int pin_irq = gpio->irq_base + (port->number << 3)
+				+ irqoffset;
+			int offset = pinoffset + irqoffset;
+
+			dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n",
+				pin_irq, offset);
+			generic_handle_irq(pin_irq);
+			/*
+			 * Triggering IRQ on both rising and falling edge
+			 * needs mockery
+			 */
+			if (port->toggle_edge_mode & U300_PIN_BIT(offset))
+				u300_toggle_trigger(gpio, offset);
+		}
 	}
-	return IRQ_HANDLED;
+
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
-static void gpio_set_initial_values(void)
+static void __init u300_gpio_init_pin(struct u300_gpio *gpio,
+				      int offset,
+				      const struct u300_gpio_confdata *conf)
 {
-#ifdef U300_COH901571_3
-	int i, j;
-	unsigned long flags;
-	u32 val;
+	/* Set mode: input or output */
+	if (conf->output) {
+		u300_gpio_direction_output(&gpio->chip, offset, conf->outval);
 
-	/* Write default values to all pins */
-	for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
-		val = 0;
-		for (j = 0; j < 8; j++)
-			val |= (u32) (u300_gpio_config[i][j].default_output_value != DEFAULT_OUTPUT_LOW) << j;
-		local_irq_save(flags);
-		writel(val, virtbase + U300_GPIO_PXPDOR + i * U300_GPIO_PORTX_SPACING);
-		local_irq_restore(flags);
+		/* Deactivate bias mode for output */
+		u300_gpio_config(&gpio->chip, offset,
+				 GPIO_U300_CONFIG_BIAS_FLOAT,
+				 NULL);
+
+		/* Set drive mode for output */
+		u300_gpio_config(&gpio->chip, offset,
+				 GPIO_U300_CONFIG_DRIVE_PUSH_PULL, NULL);
+
+		dev_dbg(gpio->dev, "set up pin %d as output, value: %d\n",
+			offset, conf->outval);
+	} else {
+		u300_gpio_direction_input(&gpio->chip, offset);
+
+		/* Always set output low on input pins */
+		u300_gpio_set(&gpio->chip, offset, 0);
+
+		/* Set bias mode for input */
+		u300_gpio_config(&gpio->chip, offset, conf->bias_mode, NULL);
+
+		dev_dbg(gpio->dev, "set up pin %d as input, bias: %04x\n",
+			offset, conf->bias_mode);
 	}
+}
 
-	/*
-	 * Put all pins that are set to either 'GPIO_OUT' or 'GPIO_NOT_USED'
-	 * to output and 'GPIO_IN' to input for each port. And initialize
-	 * default value on outputs.
-	 */
-	for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
-		for (j = 0; j < U300_GPIO_PINS_PER_PORT; j++) {
-			local_irq_save(flags);
-			val = readl(virtbase + U300_GPIO_PXPCR +
-					 i * U300_GPIO_PORTX_SPACING);
-			/* Mask out this pin */
-			val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << (j << 1));
+static void __init u300_gpio_init_coh901571(struct u300_gpio *gpio,
+				     struct u300_gpio_platform *plat)
+{
+	int i, j;
 
-			if (u300_gpio_config[i][j].pin_usage != GPIO_IN)
-				val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL << (j << 1));
-			writel(val, virtbase + U300_GPIO_PXPCR +
-					 i * U300_GPIO_PORTX_SPACING);
-			local_irq_restore(flags);
+	/* Write default config and values to all pins */
+	for (i = 0; i < plat->ports; i++) {
+		for (j = 0; j < 8; j++) {
+			const struct u300_gpio_confdata *conf;
+			int offset = (i*8) + j;
+
+			if (plat->variant == U300_GPIO_COH901571_3_BS335)
+				conf = &bs335_gpio_config[i][j];
+			else if (plat->variant == U300_GPIO_COH901571_3_BS365)
+				conf = &bs365_gpio_config[i][j];
+			else
+				break;
+
+			u300_gpio_init_pin(gpio, offset, conf);
 		}
 	}
+}
 
-	/* Enable or disable the internal pull-ups in the GPIO ASIC block */
-	for (i = 0; i < U300_GPIO_MAX; i++) {
-		val = 0;
-		for (j = 0; j < 8; j++)
-			val |= (u32)((u300_gpio_config[i][j].pull_up == DISABLE_PULL_UP) << j);
-		local_irq_save(flags);
-		writel(val, virtbase + U300_GPIO_PXPER + i * U300_GPIO_PORTX_SPACING);
-		local_irq_restore(flags);
+static inline void u300_gpio_free_ports(struct u300_gpio *gpio)
+{
+	struct u300_gpio_port *port;
+	struct list_head *p, *n;
+
+	list_for_each_safe(p, n, &gpio->port_list) {
+		port = list_entry(p, struct u300_gpio_port, node);
+		list_del(&port->node);
+		free_irq(port->irq, port);
+		kfree(port);
 	}
-#endif
 }
 
-static int __init gpio_probe(struct platform_device *pdev)
+static int __init u300_gpio_probe(struct platform_device *pdev)
 {
-	u32 val;
+	struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev);
+	struct u300_gpio *gpio;
 	int err = 0;
+	int portno;
+	u32 val;
+	u32 ifr;
 	int i;
-	int num_irqs;
 
-	gpiodev = &pdev->dev;
-	memset(gpio_pin, 0, sizeof(gpio_pin));
+	gpio = kzalloc(sizeof(struct u300_gpio), GFP_KERNEL);
+	if (gpio == NULL) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	gpio->chip = u300_gpio_chip;
+	gpio->chip.ngpio = plat->ports * U300_GPIO_PINS_PER_PORT;
+	gpio->irq_base = plat->gpio_irq_base;
+	gpio->chip.dev = &pdev->dev;
+	gpio->chip.base = plat->gpio_base;
+	gpio->dev = &pdev->dev;
 
 	/* Get GPIO clock */
-	clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(clk)) {
-		err = PTR_ERR(clk);
-		dev_err(gpiodev, "could not get GPIO clock\n");
+	gpio->clk = clk_get(gpio->dev, NULL);
+	if (IS_ERR(gpio->clk)) {
+		err = PTR_ERR(gpio->clk);
+		dev_err(gpio->dev, "could not get GPIO clock\n");
 		goto err_no_clk;
 	}
-	err = clk_enable(clk);
+	err = clk_enable(gpio->clk);
 	if (err) {
-		dev_err(gpiodev, "could not enable GPIO clock\n");
+		dev_err(gpio->dev, "could not enable GPIO clock\n");
 		goto err_no_clk_enable;
 	}
 
-	memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!memres)
+	gpio->memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!gpio->memres) {
+		dev_err(gpio->dev, "could not get GPIO memory resource\n");
+		err = -ENODEV;
 		goto err_no_resource;
+	}
 
-	if (!request_mem_region(memres->start, resource_size(memres),
+	if (!request_mem_region(gpio->memres->start,
+				resource_size(gpio->memres),
 				"GPIO Controller")) {
 		err = -ENODEV;
 		goto err_no_ioregion;
 	}
 
-	virtbase = ioremap(memres->start, resource_size(memres));
-	if (!virtbase) {
+	gpio->base = ioremap(gpio->memres->start, resource_size(gpio->memres));
+	if (!gpio->base) {
 		err = -ENOMEM;
 		goto err_no_ioremap;
 	}
-	dev_info(gpiodev, "remapped 0x%08x to %p\n",
-		 memres->start, virtbase);
 
-#ifdef U300_COH901335
-	dev_info(gpiodev, "initializing GPIO Controller COH 901 335\n");
-	/* Turn on the GPIO block */
-	writel(U300_GPIO_CR_BLOCK_CLOCK_ENABLE, virtbase + U300_GPIO_CR);
-#endif
+	if (plat->variant == U300_GPIO_COH901335) {
+		dev_info(gpio->dev,
+			 "initializing GPIO Controller COH 901 335\n");
+		gpio->stride = U300_335_PORT_STRIDE;
+		gpio->pcr = U300_335_PXPCR;
+		gpio->dor = U300_335_PXPDOR;
+		gpio->dir = U300_335_PXPDIR;
+		gpio->per = U300_335_PXPER;
+		gpio->icr = U300_335_PXICR;
+		gpio->ien = U300_335_PXIEN;
+		gpio->iev = U300_335_PXIEV;
+		ifr = U300_335_PXIFR;
 
-#ifdef U300_COH901571_3
-	dev_info(gpiodev, "initializing GPIO Controller COH 901 571/3\n");
-	val = readl(virtbase + U300_GPIO_CR);
-	dev_info(gpiodev, "COH901571/3 block version: %d, " \
-	       "number of cores: %d\n",
-	       ((val & 0x0000FE00) >> 9),
-	       ((val & 0x000001FC) >> 2));
-	writel(U300_GPIO_CR_BLOCK_CLKRQ_ENABLE, virtbase + U300_GPIO_CR);
-#endif
+		/* Turn on the GPIO block */
+		writel(U300_335_CR_BLOCK_CLOCK_ENABLE,
+		       gpio->base + U300_335_CR);
+	} else if (plat->variant == U300_GPIO_COH901571_3_BS335 ||
+		   plat->variant == U300_GPIO_COH901571_3_BS365) {
+		dev_info(gpio->dev,
+			 "initializing GPIO Controller COH 901 571/3\n");
+		gpio->stride = U300_571_PORT_STRIDE;
+		gpio->pcr = U300_571_PXPCR;
+		gpio->dor = U300_571_PXPDOR;
+		gpio->dir = U300_571_PXPDIR;
+		gpio->per = U300_571_PXPER;
+		gpio->icr = U300_571_PXICR;
+		gpio->ien = U300_571_PXIEN;
+		gpio->iev = U300_571_PXIEV;
+		ifr = U300_571_PXIFR;
 
-	gpio_set_initial_values();
+		val = readl(gpio->base + U300_571_CR);
+		dev_info(gpio->dev, "COH901571/3 block version: %d, " \
+			 "number of cores: %d totalling %d pins\n",
+			 ((val & 0x000001FC) >> 2),
+			 ((val & 0x0000FE00) >> 9),
+			 ((val & 0x0000FE00) >> 9) * 8);
+		writel(U300_571_CR_BLOCK_CLKRQ_ENABLE,
+		       gpio->base + U300_571_CR);
+		u300_gpio_init_coh901571(gpio, plat);
+	} else {
+		dev_err(gpio->dev, "unknown block variant\n");
+		err = -ENODEV;
+		goto err_unknown_variant;
+	}
 
-	for (num_irqs = 0 ; num_irqs < U300_GPIO_NUM_PORTS; num_irqs++) {
+	/* Add each port with its IRQ separately */
+	INIT_LIST_HEAD(&gpio->port_list);
+	for (portno = 0 ; portno < plat->ports; portno++) {
+		struct u300_gpio_port *port =
+			kmalloc(sizeof(struct u300_gpio_port), GFP_KERNEL);
 
-		gpio_ports[num_irqs].irq =
-			platform_get_irq_byname(pdev,
-						gpio_ports[num_irqs].name);
+		if (!port) {
+			dev_err(gpio->dev, "out of memory\n");
+			err = -ENOMEM;
+			goto err_no_port;
+		}
 
-		err = request_irq(gpio_ports[num_irqs].irq,
-				  gpio_irq_handler, IRQF_DISABLED,
-				  gpio_ports[num_irqs].name,
-				  &gpio_ports[num_irqs]);
-		if (err) {
-			dev_err(gpiodev, "cannot allocate IRQ for %s!\n",
-				gpio_ports[num_irqs].name);
-			goto err_no_irq;
+		snprintf(port->name, 8, "gpio%d", portno);
+		port->number = portno;
+		port->gpio = gpio;
+
+		port->irq = platform_get_irq_byname(pdev,
+						    port->name);
+
+		dev_dbg(gpio->dev, "register IRQ %d for %s\n", port->irq,
+			port->name);
+
+		irq_set_chained_handler(port->irq, u300_gpio_irq_handler);
+		irq_set_handler_data(port->irq, port);
+
+		/* For each GPIO pin set the unique IRQ handler */
+		for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) {
+			int irqno = gpio->irq_base + (portno << 3) + i;
+
+			dev_dbg(gpio->dev, "handler for IRQ %d on %s\n",
+				irqno, port->name);
+			irq_set_chip_and_handler(irqno, &u300_gpio_irqchip,
+						 handle_simple_irq);
+			set_irq_flags(irqno, IRQF_VALID);
+			irq_set_chip_data(irqno, port);
 		}
-		/* Turns off PortX_irq_force */
-		writel(0x0, virtbase + U300_GPIO_PXIFR +
-				 num_irqs * U300_GPIO_PORTX_SPACING);
+
+		/* Turns off irq force (test register) for this port */
+		writel(0x0, gpio->base + portno * gpio->stride + ifr);
+
+		list_add_tail(&port->node, &gpio->port_list);
+	}
+	dev_dbg(gpio->dev, "initialized %d GPIO ports\n", portno);
+
+	err = gpiochip_add(&gpio->chip);
+	if (err) {
+		dev_err(gpio->dev, "unable to add gpiochip: %d\n", err);
+		goto err_no_chip;
 	}
 
+	platform_set_drvdata(pdev, gpio);
+
 	return 0;
 
- err_no_irq:
-	for (i = 0; i < num_irqs; i++)
-		free_irq(gpio_ports[i].irq, &gpio_ports[i]);
-	iounmap(virtbase);
- err_no_ioremap:
-	release_mem_region(memres->start, resource_size(memres));
- err_no_ioregion:
- err_no_resource:
-	clk_disable(clk);
- err_no_clk_enable:
-	clk_put(clk);
- err_no_clk:
-	dev_info(gpiodev, "module ERROR:%d\n", err);
+err_no_chip:
+err_no_port:
+	u300_gpio_free_ports(gpio);
+err_unknown_variant:
+	iounmap(gpio->base);
+err_no_ioremap:
+	release_mem_region(gpio->memres->start, resource_size(gpio->memres));
+err_no_ioregion:
+err_no_resource:
+	clk_disable(gpio->clk);
+err_no_clk_enable:
+	clk_put(gpio->clk);
+err_no_clk:
+	kfree(gpio);
+	dev_info(&pdev->dev, "module ERROR:%d\n", err);
 	return err;
 }
 
-static int __exit gpio_remove(struct platform_device *pdev)
+static int __exit u300_gpio_remove(struct platform_device *pdev)
 {
-	int i;
+	struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev);
+	struct u300_gpio *gpio = platform_get_drvdata(pdev);
+	int err;
 
 	/* Turn off the GPIO block */
-	writel(0x00000000U, virtbase + U300_GPIO_CR);
-	for (i = 0 ; i < U300_GPIO_NUM_PORTS; i++)
-		free_irq(gpio_ports[i].irq, &gpio_ports[i]);
-	iounmap(virtbase);
-	release_mem_region(memres->start, resource_size(memres));
-	clk_disable(clk);
-	clk_put(clk);
+	if (plat->variant == U300_GPIO_COH901335)
+		writel(0x00000000U, gpio->base + U300_335_CR);
+	if (plat->variant == U300_GPIO_COH901571_3_BS335 ||
+	    plat->variant == U300_GPIO_COH901571_3_BS365)
+		writel(0x00000000U, gpio->base + U300_571_CR);
+
+	err = gpiochip_remove(&gpio->chip);
+	if (err < 0) {
+		dev_err(gpio->dev, "unable to remove gpiochip: %d\n", err);
+		return err;
+	}
+	u300_gpio_free_ports(gpio);
+	iounmap(gpio->base);
+	release_mem_region(gpio->memres->start,
+			   resource_size(gpio->memres));
+	clk_disable(gpio->clk);
+	clk_put(gpio->clk);
+	platform_set_drvdata(pdev, NULL);
+	kfree(gpio);
 	return 0;
 }
 
-static struct platform_driver gpio_driver = {
+static struct platform_driver u300_gpio_driver = {
 	.driver		= {
 		.name	= "u300-gpio",
 	},
-	.remove		= __exit_p(gpio_remove),
+	.remove		= __exit_p(u300_gpio_remove),
 };
 
 
 static int __init u300_gpio_init(void)
 {
-	return platform_driver_probe(&gpio_driver, gpio_probe);
+	return platform_driver_probe(&u300_gpio_driver, u300_gpio_probe);
 }
 
 static void __exit u300_gpio_exit(void)
 {
-	platform_driver_unregister(&gpio_driver);
+	platform_driver_unregister(&u300_gpio_driver);
 }
 
 arch_initcall(u300_gpio_init);
 module_exit(u300_gpio_exit);
 
 MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
-
-#ifdef U300_COH901571_3
-MODULE_DESCRIPTION("ST-Ericsson AB COH 901 571/3 GPIO driver");
-#endif
-
-#ifdef U300_COH901335
-MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335 GPIO driver");
-#endif
-
+MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335/COH 901 571/3 GPIO driver");
 MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/gpio/gpio-xilinx.c linux-libre-3.2-gnu/drivers/gpio/gpio-xilinx.c
--- linux-libre-3.1-gnu/drivers/gpio/gpio-xilinx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/gpio-xilinx.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 
 #include <linux/init.h>
 #include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
diff -druN linux-libre-3.1-gnu/drivers/gpio/Kconfig linux-libre-3.2-gnu/drivers/gpio/Kconfig
--- linux-libre-3.1-gnu/drivers/gpio/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -95,14 +95,18 @@
 	depends on ARCH_EP93XX
 	select GPIO_GENERIC
 
-config GPIO_EXYNOS4
-	def_bool y
-	depends on CPU_EXYNOS4210
-
 config GPIO_MPC5200
 	def_bool y
 	depends on PPC_MPC52xx
 
+config GPIO_MPC8XXX
+	bool "MPC512x/MPC8xxx GPIO support"
+	depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \
+		   FSL_SOC_BOOKE || PPC_86xx
+	help
+	  Say Y here if you're going to use hardware that connects to the
+	  MPC512x/831x/834x/837x/8572/8610 GPIOs.
+
 config GPIO_MSM_V1
 	tristate "Qualcomm MSM GPIO v1"
 	depends on GPIOLIB && ARCH_MSM
@@ -131,18 +135,6 @@
 	select GPIO_GENERIC
 	select GENERIC_IRQ_CHIP
 
-config GPIO_PLAT_SAMSUNG
-	def_bool y
-	depends on SAMSUNG_GPIOLIB_4BIT
-
-config GPIO_S5PC100
-	def_bool y
-	depends on CPU_S5PC100
-
-config GPIO_S5PV210
-	def_bool y
-	depends on CPU_S5PV210
-
 config GPIO_PL061
 	bool "PrimeCell PL061 GPIO support"
 	depends on ARM_AMBA
@@ -178,9 +170,18 @@
 	  The Intel Tunnel Creek processor has 5 GPIOs powered by the
 	  core power rail and 9 from suspend power supply.
 
+config GPIO_U300
+	bool "ST-Ericsson U300 COH 901 335/571 GPIO"
+	depends on GPIOLIB && ARCH_U300
+	help
+	  Say yes here to support GPIO interface on ST-Ericsson U300.
+	  The names of the two IP block variants supported are
+	  COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
+	  ports of 8 GPIO pins each.
+
 config GPIO_VX855
 	tristate "VIA VX855/VX875 GPIO"
-	depends on MFD_SUPPORT && PCI
+	depends on PCI
 	select MFD_CORE
 	select MFD_VX855
 	help
@@ -388,6 +389,7 @@
 config GPIO_PCH
 	tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO"
 	depends on PCI && X86
+	select GENERIC_IRQ_CHIP
 	help
 	  This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
 	  which is an IOH(Input/Output Hub) for x86 embedded processor.
@@ -402,6 +404,7 @@
 config GPIO_ML_IOH
 	tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
 	depends on PCI
+	select GENERIC_IRQ_CHIP
 	help
 	  ML7213 is companion chip for Intel Atom E6xx series.
 	  This driver can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/Output
@@ -417,7 +420,6 @@
 config GPIO_RDC321X
 	tristate "RDC R-321x GPIO support"
 	depends on PCI
-	select MFD_SUPPORT
 	select MFD_CORE
 	select MFD_RDC321X
 	help
diff -druN linux-libre-3.1-gnu/drivers/gpio/Makefile linux-libre-3.2-gnu/drivers/gpio/Makefile
--- linux-libre-3.1-gnu/drivers/gpio/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpio/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -14,11 +14,13 @@
 obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o
 obj-$(CONFIG_GPIO_CS5535)	+= gpio-cs5535.o
 obj-$(CONFIG_GPIO_DA9052)	+= gpio-da9052.o
+obj-$(CONFIG_ARCH_DAVINCI)	+= gpio-davinci.o
 obj-$(CONFIG_GPIO_EP93XX)	+= gpio-ep93xx.o
-obj-$(CONFIG_GPIO_EXYNOS4)	+= gpio-exynos4.o
 obj-$(CONFIG_GPIO_IT8761E)	+= gpio-it8761e.o
 obj-$(CONFIG_GPIO_JANZ_TTL)	+= gpio-janz-ttl.o
+obj-$(CONFIG_ARCH_KS8695)	+= gpio-ks8695.o
 obj-$(CONFIG_GPIO_LANGWELL)	+= gpio-langwell.o
+obj-$(CONFIG_ARCH_LPC32XX)	+= gpio-lpc32xx.o
 obj-$(CONFIG_GPIO_MAX730X)	+= gpio-max730x.o
 obj-$(CONFIG_GPIO_MAX7300)	+= gpio-max7300.o
 obj-$(CONFIG_GPIO_MAX7301)	+= gpio-max7301.o
@@ -27,6 +29,7 @@
 obj-$(CONFIG_GPIO_MCP23S08)	+= gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)	+= gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MPC5200)	+= gpio-mpc5200.o
+obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MSM_V1)	+= gpio-msm-v1.o
 obj-$(CONFIG_GPIO_MSM_V2)	+= gpio-msm-v2.o
 obj-$(CONFIG_GPIO_MXC)		+= gpio-mxc.o
@@ -37,18 +40,17 @@
 obj-$(CONFIG_GPIO_PCF857X)	+= gpio-pcf857x.o
 obj-$(CONFIG_GPIO_PCH)		+= gpio-pch.o
 obj-$(CONFIG_GPIO_PL061)	+= gpio-pl061.o
+obj-$(CONFIG_PLAT_PXA)		+= gpio-pxa.o
 obj-$(CONFIG_GPIO_RDC321X)	+= gpio-rdc321x.o
-
-obj-$(CONFIG_GPIO_PLAT_SAMSUNG)	+= gpio-plat-samsung.o
-obj-$(CONFIG_GPIO_S5PC100)	+= gpio-s5pc100.o
-obj-$(CONFIG_GPIO_S5PV210)	+= gpio-s5pv210.o
-
+obj-$(CONFIG_PLAT_SAMSUNG)	+= gpio-samsung.o
+obj-$(CONFIG_ARCH_SA1100)	+= gpio-sa1100.o
 obj-$(CONFIG_GPIO_SCH)		+= gpio-sch.o
 obj-$(CONFIG_GPIO_STMPE)	+= gpio-stmpe.o
 obj-$(CONFIG_GPIO_SX150X)	+= gpio-sx150x.o
 obj-$(CONFIG_GPIO_TC3589X)	+= gpio-tc3589x.o
 obj-$(CONFIG_ARCH_TEGRA)	+= gpio-tegra.o
 obj-$(CONFIG_GPIO_TIMBERDALE)	+= gpio-timberdale.o
+obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o
 obj-$(CONFIG_GPIO_TPS65910)	+= gpio-tps65910.o
 obj-$(CONFIG_GPIO_TPS65912)	+= gpio-tps65912.o
 obj-$(CONFIG_GPIO_TWL4030)	+= gpio-twl4030.o
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/ati_pcigart.c linux-libre-3.2-gnu/drivers/gpu/drm/ati_pcigart.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/ati_pcigart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/ati_pcigart.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/export.h>
 #include "drmP.h"
 
 # define ATI_PCIGART_PAGE_SIZE		4096	/**< PCI GART page size */
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_buffer.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_buffer.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_buffer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_buffer.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
  * Pauli Nieminen <suokkos-at-gmail-dot-com>
  */
 
+#include <linux/export.h>
 #include "drm_buffer.h"
 
 /**
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_bufs.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_bufs.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_bufs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_bufs.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 #include <linux/log2.h>
+#include <linux/export.h>
 #include <asm/shmparam.h>
 #include "drmP.h"
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_cache.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_cache.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_cache.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_cache.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
  * Authors: Thomas HellstrÃ¶m <thomas-at-tungstengraphics-dot-com>
  */
 
+#include <linux/export.h>
 #include "drmP.h"
 
 #if defined(CONFIG_X86)
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_crtc.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_crtc.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_crtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_crtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
  */
 #include <linux/list.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "drm.h"
 #include "drmP.h"
 #include "drm_crtc.h"
@@ -162,6 +163,7 @@
 	{ DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
 	{ DRM_MODE_CONNECTOR_TV, "TV", 0 },
 	{ DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
+	{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0},
 };
 
 static struct drm_prop_enum_list drm_encoder_enum_list[] =
@@ -170,6 +172,7 @@
 	{ DRM_MODE_ENCODER_TMDS, "TMDS" },
 	{ DRM_MODE_ENCODER_LVDS, "LVDS" },
 	{ DRM_MODE_ENCODER_TVDAC, "TV" },
+	{ DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
 };
 
 char *drm_get_encoder_name(struct drm_encoder *encoder)
@@ -463,8 +466,10 @@
 	list_add_tail(&connector->head, &dev->mode_config.connector_list);
 	dev->mode_config.num_connector++;
 
-	drm_connector_attach_property(connector,
-				      dev->mode_config.edid_property, 0);
+	if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
+		drm_connector_attach_property(connector,
+					      dev->mode_config.edid_property,
+					      0);
 
 	drm_connector_attach_property(connector,
 				      dev->mode_config.dpms_property, 0);
@@ -1868,6 +1873,10 @@
 	}
 
 	if (num_clips && clips_ptr) {
+		if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
+			ret = -EINVAL;
+			goto out_err1;
+		}
 		clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
 		if (!clips) {
 			ret = -ENOMEM;
@@ -2113,8 +2122,10 @@
 	property->num_values = num_values;
 	INIT_LIST_HEAD(&property->enum_blob_list);
 
-	if (name)
+	if (name) {
 		strncpy(property->name, name, DRM_PROP_NAME_LEN);
+		property->name[DRM_PROP_NAME_LEN-1] = '\0';
+	}
 
 	list_add_tail(&property->head, &dev->mode_config.property_list);
 	return property;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_crtc_helper.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_crtc_helper.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_crtc_helper.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_crtc_helper.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,9 @@
  *      Jesse Barnes <jesse.barnes@intel.com>
  */
 
+#include <linux/export.h>
+#include <linux/moduleparam.h>
+
 #include "drmP.h"
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
@@ -372,11 +375,13 @@
 		encoder_funcs = encoder->helper_private;
 		if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
 						      adjusted_mode))) {
+			DRM_DEBUG_KMS("Encoder fixup failed\n");
 			goto done;
 		}
 	}
 
 	if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
+		DRM_DEBUG_KMS("CRTC fixup failed\n");
 		goto done;
 	}
 	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
@@ -451,6 +456,30 @@
 EXPORT_SYMBOL(drm_crtc_helper_set_mode);
 
 
+static int
+drm_crtc_helper_disable(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+
+	/* Decouple all encoders and their attached connectors from this crtc */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (encoder->crtc != crtc)
+			continue;
+
+		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+			if (connector->encoder != encoder)
+				continue;
+
+			connector->encoder = NULL;
+		}
+	}
+
+	drm_helper_disable_unused_functions(dev);
+	return 0;
+}
+
 /**
  * drm_crtc_helper_set_config - set a new config from userspace
  * @crtc: CRTC to setup
@@ -479,6 +508,7 @@
 	struct drm_connector *save_connectors, *connector;
 	int count = 0, ro, fail = 0;
 	struct drm_crtc_helper_funcs *crtc_funcs;
+	struct drm_mode_set save_set;
 	int ret = 0;
 	int i;
 
@@ -504,8 +534,7 @@
 				(int)set->num_connectors, set->x, set->y);
 	} else {
 		DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
-		set->mode = NULL;
-		set->num_connectors = 0;
+		return drm_crtc_helper_disable(set->crtc);
 	}
 
 	dev = set->crtc->dev;
@@ -551,6 +580,12 @@
 		save_connectors[count++] = *connector;
 	}
 
+	save_set.crtc = set->crtc;
+	save_set.mode = &set->crtc->mode;
+	save_set.x = set->crtc->x;
+	save_set.y = set->crtc->y;
+	save_set.fb = set->crtc->fb;
+
 	/* We should be able to check here if the fb has the same properties
 	 * and then just flip_or_move it */
 	if (set->crtc->fb != set->fb) {
@@ -716,6 +751,12 @@
 		*connector = save_connectors[count++];
 	}
 
+	/* Try to restore the config */
+	if (mode_changed &&
+	    !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
+				      save_set.y, save_set.fb))
+		DRM_ERROR("failed to restore config after modeset failure\n");
+
 	kfree(save_connectors);
 	kfree(save_encoders);
 	kfree(save_crtcs);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_debugfs.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_debugfs.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_debugfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_debugfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "drmP.h"
 
 #if defined(CONFIG_DEBUG_FS)
@@ -107,11 +108,8 @@
 		ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO,
 					  root, tmp, &drm_debugfs_fops);
 		if (!ent) {
-			char name[64];
-			strncpy(name, root->d_name.name,
-						min(root->d_name.len, 64U));
 			DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s/%s\n",
-				  name, files[i].name);
+				  root->d_name.name, files[i].name);
 			kfree(tmp);
 			ret = -1;
 			goto fail;
@@ -120,7 +118,10 @@
 		tmp->minor = minor;
 		tmp->dent = ent;
 		tmp->info_ent = &files[i];
-		list_add(&(tmp->list), &(minor->debugfs_nodes.list));
+
+		mutex_lock(&minor->debugfs_lock);
+		list_add(&tmp->list, &minor->debugfs_list);
+		mutex_unlock(&minor->debugfs_lock);
 	}
 	return 0;
 
@@ -148,7 +149,8 @@
 	char name[64];
 	int ret;
 
-	INIT_LIST_HEAD(&minor->debugfs_nodes.list);
+	INIT_LIST_HEAD(&minor->debugfs_list);
+	mutex_init(&minor->debugfs_lock);
 	sprintf(name, "%d", minor_id);
 	minor->debugfs_root = debugfs_create_dir(name, root);
 	if (!minor->debugfs_root) {
@@ -194,8 +196,9 @@
 	struct drm_info_node *tmp;
 	int i;
 
+	mutex_lock(&minor->debugfs_lock);
 	for (i = 0; i < count; i++) {
-		list_for_each_safe(pos, q, &minor->debugfs_nodes.list) {
+		list_for_each_safe(pos, q, &minor->debugfs_list) {
 			tmp = list_entry(pos, struct drm_info_node, list);
 			if (tmp->info_ent == &files[i]) {
 				debugfs_remove(tmp->dent);
@@ -204,6 +207,7 @@
 			}
 		}
 	}
+	mutex_unlock(&minor->debugfs_lock);
 	return 0;
 }
 EXPORT_SYMBOL(drm_debugfs_remove_files);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_dma.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_dma.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/export.h>
 #include "drmP.h"
 
 /**
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_drv.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_drv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,6 +48,7 @@
 
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "drmP.h"
 #include "drm_core.h"
 
@@ -124,7 +125,7 @@
 	DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 
-	DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
+	DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
 
 	DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
 
@@ -438,6 +439,8 @@
 					goto err_i1;
 				}
 			}
+			if (asize > usize)
+				memset(kdata + usize, 0, asize - usize);
 		}
 
 		if (cmd & IOC_IN) {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_edid.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_edid.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_edid.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_edid.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/export.h>
 #include "drmP.h"
 #include "drm_edid.h"
 #include "drm_edid_modes.h"
@@ -1319,6 +1320,7 @@
 #define HDMI_IDENTIFIER 0x000C03
 #define AUDIO_BLOCK	0x01
 #define VENDOR_BLOCK    0x03
+#define SPEAKER_BLOCK	0x04
 #define EDID_BASIC_AUDIO	(1 << 6)
 
 /**
@@ -1347,6 +1349,176 @@
 }
 EXPORT_SYMBOL(drm_find_cea_extension);
 
+static void
+parse_hdmi_vsdb(struct drm_connector *connector, uint8_t *db)
+{
+	connector->eld[5] |= (db[6] >> 7) << 1;  /* Supports_AI */
+
+	connector->dvi_dual = db[6] & 1;
+	connector->max_tmds_clock = db[7] * 5;
+
+	connector->latency_present[0] = db[8] >> 7;
+	connector->latency_present[1] = (db[8] >> 6) & 1;
+	connector->video_latency[0] = db[9];
+	connector->audio_latency[0] = db[10];
+	connector->video_latency[1] = db[11];
+	connector->audio_latency[1] = db[12];
+
+	DRM_LOG_KMS("HDMI: DVI dual %d, "
+		    "max TMDS clock %d, "
+		    "latency present %d %d, "
+		    "video latency %d %d, "
+		    "audio latency %d %d\n",
+		    connector->dvi_dual,
+		    connector->max_tmds_clock,
+	      (int) connector->latency_present[0],
+	      (int) connector->latency_present[1],
+		    connector->video_latency[0],
+		    connector->video_latency[1],
+		    connector->audio_latency[0],
+		    connector->audio_latency[1]);
+}
+
+static void
+monitor_name(struct detailed_timing *t, void *data)
+{
+	if (t->data.other_data.type == EDID_DETAIL_MONITOR_NAME)
+		*(u8 **)data = t->data.other_data.data.str.str;
+}
+
+/**
+ * drm_edid_to_eld - build ELD from EDID
+ * @connector: connector corresponding to the HDMI/DP sink
+ * @edid: EDID to parse
+ *
+ * Fill the ELD (EDID-Like Data) buffer for passing to the audio driver.
+ * Some ELD fields are left to the graphics driver caller:
+ * - Conn_Type
+ * - HDCP
+ * - Port_ID
+ */
+void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
+{
+	uint8_t *eld = connector->eld;
+	u8 *cea;
+	u8 *name;
+	u8 *db;
+	int sad_count = 0;
+	int mnl;
+	int dbl;
+
+	memset(eld, 0, sizeof(connector->eld));
+
+	cea = drm_find_cea_extension(edid);
+	if (!cea) {
+		DRM_DEBUG_KMS("ELD: no CEA Extension found\n");
+		return;
+	}
+
+	name = NULL;
+	drm_for_each_detailed_block((u8 *)edid, monitor_name, &name);
+	for (mnl = 0; name && mnl < 13; mnl++) {
+		if (name[mnl] == 0x0a)
+			break;
+		eld[20 + mnl] = name[mnl];
+	}
+	eld[4] = (cea[1] << 5) | mnl;
+	DRM_DEBUG_KMS("ELD monitor %s\n", eld + 20);
+
+	eld[0] = 2 << 3;		/* ELD version: 2 */
+
+	eld[16] = edid->mfg_id[0];
+	eld[17] = edid->mfg_id[1];
+	eld[18] = edid->prod_code[0];
+	eld[19] = edid->prod_code[1];
+
+	for (db = cea + 4; db < cea + cea[2]; db += dbl + 1) {
+		dbl = db[0] & 0x1f;
+
+		switch ((db[0] & 0xe0) >> 5) {
+		case AUDIO_BLOCK:	/* Audio Data Block, contains SADs */
+			sad_count = dbl / 3;
+			memcpy(eld + 20 + mnl, &db[1], dbl);
+			break;
+		case SPEAKER_BLOCK:	/* Speaker Allocation Data Block */
+			eld[7] = db[1];
+			break;
+		case VENDOR_BLOCK:
+			/* HDMI Vendor-Specific Data Block */
+			if (db[1] == 0x03 && db[2] == 0x0c && db[3] == 0)
+				parse_hdmi_vsdb(connector, db);
+			break;
+		default:
+			break;
+		}
+	}
+	eld[5] |= sad_count << 4;
+	eld[2] = (20 + mnl + sad_count * 3 + 3) / 4;
+
+	DRM_DEBUG_KMS("ELD size %d, SAD count %d\n", (int)eld[2], sad_count);
+}
+EXPORT_SYMBOL(drm_edid_to_eld);
+
+/**
+ * drm_av_sync_delay - HDMI/DP sink audio-video sync delay in millisecond
+ * @connector: connector associated with the HDMI/DP sink
+ * @mode: the display mode
+ */
+int drm_av_sync_delay(struct drm_connector *connector,
+		      struct drm_display_mode *mode)
+{
+	int i = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
+	int a, v;
+
+	if (!connector->latency_present[0])
+		return 0;
+	if (!connector->latency_present[1])
+		i = 0;
+
+	a = connector->audio_latency[i];
+	v = connector->video_latency[i];
+
+	/*
+	 * HDMI/DP sink doesn't support audio or video?
+	 */
+	if (a == 255 || v == 255)
+		return 0;
+
+	/*
+	 * Convert raw EDID values to millisecond.
+	 * Treat unknown latency as 0ms.
+	 */
+	if (a)
+		a = min(2 * (a - 1), 500);
+	if (v)
+		v = min(2 * (v - 1), 500);
+
+	return max(v - a, 0);
+}
+EXPORT_SYMBOL(drm_av_sync_delay);
+
+/**
+ * drm_select_eld - select one ELD from multiple HDMI/DP sinks
+ * @encoder: the encoder just changed display mode
+ * @mode: the adjusted display mode
+ *
+ * It's possible for one encoder to be associated with multiple HDMI/DP sinks.
+ * The policy is now hard coded to simply use the first HDMI/DP sink's ELD.
+ */
+struct drm_connector *drm_select_eld(struct drm_encoder *encoder,
+				     struct drm_display_mode *mode)
+{
+	struct drm_connector *connector;
+	struct drm_device *dev = encoder->dev;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		if (connector->encoder == encoder && connector->eld[0])
+			return connector;
+
+	return NULL;
+}
+EXPORT_SYMBOL(drm_select_eld);
+
 /**
  * drm_detect_hdmi_monitor - detect whether monitor is hdmi.
  * @edid: monitor EDID information
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_encoder_slave.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_encoder_slave.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_encoder_slave.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_encoder_slave.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
  *
  */
 
+#include <linux/module.h>
+
 #include "drm_encoder_slave.h"
 
 /**
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_fb_helper.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_fb_helper.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_fb_helper.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_fb_helper.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/sysrq.h>
 #include <linux/slab.h>
 #include <linux/fb.h>
+#include <linux/module.h>
 #include "drmP.h"
 #include "drm_crtc.h"
 #include "drm_fb_helper.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_fops.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_fops.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_fops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_fops.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include "drmP.h"
 #include <linux/poll.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 /* from BKL pushdown: note that nothing else serializes idr_find() */
 DEFINE_MUTEX(drm_global_mutex);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_gem.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_gem.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_gem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_gem.c	2012-01-04 18:55:44.000000000 -0500
@@ -285,6 +285,94 @@
 }
 EXPORT_SYMBOL(drm_gem_handle_create);
 
+
+/**
+ * drm_gem_free_mmap_offset - release a fake mmap offset for an object
+ * @obj: obj in question
+ *
+ * This routine frees fake offsets allocated by drm_gem_create_mmap_offset().
+ */
+void
+drm_gem_free_mmap_offset(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_gem_mm *mm = dev->mm_private;
+	struct drm_map_list *list = &obj->map_list;
+
+	drm_ht_remove_item(&mm->offset_hash, &list->hash);
+	drm_mm_put_block(list->file_offset_node);
+	kfree(list->map);
+	list->map = NULL;
+}
+EXPORT_SYMBOL(drm_gem_free_mmap_offset);
+
+/**
+ * drm_gem_create_mmap_offset - create a fake mmap offset for an object
+ * @obj: obj in question
+ *
+ * GEM memory mapping works by handing back to userspace a fake mmap offset
+ * it can use in a subsequent mmap(2) call.  The DRM core code then looks
+ * up the object based on the offset and sets up the various memory mapping
+ * structures.
+ *
+ * This routine allocates and attaches a fake offset for @obj.
+ */
+int
+drm_gem_create_mmap_offset(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_gem_mm *mm = dev->mm_private;
+	struct drm_map_list *list;
+	struct drm_local_map *map;
+	int ret = 0;
+
+	/* Set the object up for mmap'ing */
+	list = &obj->map_list;
+	list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
+	if (!list->map)
+		return -ENOMEM;
+
+	map = list->map;
+	map->type = _DRM_GEM;
+	map->size = obj->size;
+	map->handle = obj;
+
+	/* Get a DRM GEM mmap offset allocated... */
+	list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
+			obj->size / PAGE_SIZE, 0, 0);
+
+	if (!list->file_offset_node) {
+		DRM_ERROR("failed to allocate offset for bo %d\n", obj->name);
+		ret = -ENOSPC;
+		goto out_free_list;
+	}
+
+	list->file_offset_node = drm_mm_get_block(list->file_offset_node,
+			obj->size / PAGE_SIZE, 0);
+	if (!list->file_offset_node) {
+		ret = -ENOMEM;
+		goto out_free_list;
+	}
+
+	list->hash.key = list->file_offset_node->start;
+	ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
+	if (ret) {
+		DRM_ERROR("failed to add to map hash\n");
+		goto out_free_mm;
+	}
+
+	return 0;
+
+out_free_mm:
+	drm_mm_put_block(list->file_offset_node);
+out_free_list:
+	kfree(list->map);
+	list->map = NULL;
+
+	return ret;
+}
+EXPORT_SYMBOL(drm_gem_create_mmap_offset);
+
 /** Returns a reference to the object named by the handle. */
 struct drm_gem_object *
 drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_hashtab.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_hashtab.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_hashtab.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_hashtab.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 #include "drm_hashtab.h"
 #include <linux/hash.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 
 int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
 {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_ioc32.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_ioc32.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_ioc32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_ioc32.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
  */
 #include <linux/compat.h>
 #include <linux/ratelimit.h>
+#include <linux/export.h>
 
 #include "drmP.h"
 #include "drm_core.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_irq.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_irq.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,7 @@
 #include <linux/slab.h>
 
 #include <linux/vgaarb.h>
+#include <linux/export.h>
 
 /* Access macro for slots in vblank timestamp ringbuffer. */
 #define vblanktimestamp(dev, crtc, count) ( \
@@ -109,10 +110,7 @@
 	/* Prevent vblank irq processing while disabling vblank irqs,
 	 * so no updates of timestamps or count can happen after we've
 	 * disabled. Needed to prevent races in case of delayed irq's.
-	 * Disable preemption, so vblank_time_lock is held as short as
-	 * possible, even under a kernel with PREEMPT_RT patches.
 	 */
-	preempt_disable();
 	spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
 
 	dev->driver->disable_vblank(dev, crtc);
@@ -163,7 +161,6 @@
 	clear_vblank_timestamps(dev, crtc);
 
 	spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
-	preempt_enable();
 }
 
 static void vblank_disable_fn(unsigned long arg)
@@ -406,13 +403,16 @@
 	/*
 	 * Wake up any waiters so they don't hang.
 	 */
-	spin_lock_irqsave(&dev->vbl_lock, irqflags);
-	for (i = 0; i < dev->num_crtcs; i++) {
-		DRM_WAKEUP(&dev->vbl_queue[i]);
-		dev->vblank_enabled[i] = 0;
-		dev->last_vblank[i] = dev->driver->get_vblank_counter(dev, i);
+	if (dev->num_crtcs) {
+		spin_lock_irqsave(&dev->vbl_lock, irqflags);
+		for (i = 0; i < dev->num_crtcs; i++) {
+			DRM_WAKEUP(&dev->vbl_queue[i]);
+			dev->vblank_enabled[i] = 0;
+			dev->last_vblank[i] =
+				dev->driver->get_vblank_counter(dev, i);
+		}
+		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 	}
-	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 
 	if (!irq_enabled)
 		return -EINVAL;
@@ -885,10 +885,6 @@
 	spin_lock_irqsave(&dev->vbl_lock, irqflags);
 	/* Going from 0->1 means we have to enable interrupts again */
 	if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) {
-		/* Disable preemption while holding vblank_time_lock. Do
-		 * it explicitely to guard against PREEMPT_RT kernel.
-		 */
-		preempt_disable();
 		spin_lock_irqsave(&dev->vblank_time_lock, irqflags2);
 		if (!dev->vblank_enabled[crtc]) {
 			/* Enable vblank irqs under vblank_time_lock protection.
@@ -908,7 +904,6 @@
 			}
 		}
 		spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2);
-		preempt_enable();
 	} else {
 		if (!dev->vblank_enabled[crtc]) {
 			atomic_dec(&dev->vblank_refcount[crtc]);
@@ -1124,6 +1119,7 @@
 		trace_drm_vblank_event_delivered(current->pid, pipe,
 						 vblwait->request.sequence);
 	} else {
+		/* drm_handle_vblank_events will call drm_vblank_put */
 		list_add_tail(&e->base.link, &dev->vblank_event_list);
 		vblwait->reply.sequence = vblwait->request.sequence;
 	}
@@ -1204,8 +1200,12 @@
 		goto done;
 	}
 
-	if (flags & _DRM_VBLANK_EVENT)
+	if (flags & _DRM_VBLANK_EVENT) {
+		/* must hold on to the vblank ref until the event fires
+		 * drm_vblank_put will be called asynchronously
+		 */
 		return drm_queue_vblank_event(dev, crtc, vblwait, file_priv);
+	}
 
 	if ((flags & _DRM_VBLANK_NEXTONMISS) &&
 	    (seq - vblwait->request.sequence) <= (1<<23)) {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_memory.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_memory.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_memory.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_memory.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
  */
 
 #include <linux/highmem.h>
+#include <linux/export.h>
 #include "drmP.h"
 
 /**
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_mm.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_mm.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_mm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_mm.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,6 +45,7 @@
 #include "drm_mm.h"
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/export.h>
 
 #define MM_UNUSED_TARGET 4
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_modes.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_modes.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_modes.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_modes.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 
 #include <linux/list.h>
 #include <linux/list_sort.h>
+#include <linux/export.h>
 #include "drmP.h"
 #include "drm.h"
 #include "drm_crtc.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_pci.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_pci.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 #include "drmP.h"
 
 /**********************************************************************/
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_platform.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_platform.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/export.h>
 #include "drmP.h"
 
 /**
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_proc.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_proc.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_proc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_proc.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,7 @@
 
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "drmP.h"
 
 /***************************************************
@@ -95,7 +96,6 @@
 	struct drm_device *dev = minor->dev;
 	struct proc_dir_entry *ent;
 	struct drm_info_node *tmp;
-	char name[64];
 	int i, ret;
 
 	for (i = 0; i < count; i++) {
@@ -118,7 +118,7 @@
 				       &drm_proc_fops, tmp);
 		if (!ent) {
 			DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
-				  name, files[i].name);
+				  root->name, files[i].name);
 			list_del(&tmp->list);
 			kfree(tmp);
 			ret = -1;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_sman.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_sman.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_sman.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_sman.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
  * Thomas HellstrÃ¶m <thomas-at-tungstengraphics-dot-com>
  */
 
+#include <linux/export.h>
 #include "drm_sman.h"
 
 struct drm_owner_item {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_sysfs.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_sysfs.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/kdev_t.h>
 #include <linux/gfp.h>
 #include <linux/err.h>
+#include <linux/export.h>
 
 #include "drm_sysfs.h"
 #include "drm_core.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_usb.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_usb.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_usb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_usb.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 #include "drmP.h"
 #include <linux/usb.h>
+#include <linux/export.h>
 
 #ifdef CONFIG_USB
 int drm_get_usb_dev(struct usb_interface *interface,
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/drm_vm.c linux-libre-3.2-gnu/drivers/gpu/drm/drm_vm.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/drm_vm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/drm_vm.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
  */
 
 #include "drmP.h"
+#include <linux/export.h>
 #if defined(__ia64__)
 #include <linux/efi.h>
 #include <linux/slab.h>
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_buf.c linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_buf.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_buf.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_buf.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,112 @@
+/* exynos_drm_buf.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Author: Inki Dae <inki.dae@samsung.com>
+ *
+ * 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.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_gem.h"
+#include "exynos_drm_buf.h"
+
+static int lowlevel_buffer_allocate(struct drm_device *dev,
+		struct exynos_drm_gem_buf *buffer)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	buffer->kvaddr = dma_alloc_writecombine(dev->dev, buffer->size,
+			&buffer->dma_addr, GFP_KERNEL);
+	if (!buffer->kvaddr) {
+		DRM_ERROR("failed to allocate buffer.\n");
+		return -ENOMEM;
+	}
+
+	DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
+			(unsigned long)buffer->kvaddr,
+			(unsigned long)buffer->dma_addr,
+			buffer->size);
+
+	return 0;
+}
+
+static void lowlevel_buffer_deallocate(struct drm_device *dev,
+		struct exynos_drm_gem_buf *buffer)
+{
+	DRM_DEBUG_KMS("%s.\n", __FILE__);
+
+	if (buffer->dma_addr && buffer->size)
+		dma_free_writecombine(dev->dev, buffer->size, buffer->kvaddr,
+				(dma_addr_t)buffer->dma_addr);
+	else
+		DRM_DEBUG_KMS("buffer data are invalid.\n");
+}
+
+struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
+		unsigned int size)
+{
+	struct exynos_drm_gem_buf *buffer;
+
+	DRM_DEBUG_KMS("%s.\n", __FILE__);
+	DRM_DEBUG_KMS("desired size = 0x%x\n", size);
+
+	buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
+	if (!buffer) {
+		DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	buffer->size = size;
+
+	/*
+	 * allocate memory region with size and set the memory information
+	 * to vaddr and dma_addr of a buffer object.
+	 */
+	if (lowlevel_buffer_allocate(dev, buffer) < 0) {
+		kfree(buffer);
+		buffer = NULL;
+		return ERR_PTR(-ENOMEM);
+	}
+
+	return buffer;
+}
+
+void exynos_drm_buf_destroy(struct drm_device *dev,
+		struct exynos_drm_gem_buf *buffer)
+{
+	DRM_DEBUG_KMS("%s.\n", __FILE__);
+
+	if (!buffer) {
+		DRM_DEBUG_KMS("buffer is null.\n");
+		return;
+	}
+
+	lowlevel_buffer_deallocate(dev, buffer);
+
+	kfree(buffer);
+	buffer = NULL;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM Buffer Management Module");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_buf.h linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_buf.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_buf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_buf.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,40 @@
+/* exynos_drm_buf.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Author: Inki Dae <inki.dae@samsung.com>
+ *
+ * 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.
+ */
+
+#ifndef _EXYNOS_DRM_BUF_H_
+#define _EXYNOS_DRM_BUF_H_
+
+/* allocate physical memory. */
+struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
+		unsigned int size);
+
+/* get memory information of a drm framebuffer. */
+struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb);
+
+/* remove allocated physical memory. */
+void exynos_drm_buf_destroy(struct drm_device *dev,
+		struct exynos_drm_gem_buf *buffer);
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_connector.c linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_connector.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_connector.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_connector.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * 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.
+ */
+
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_encoder.h"
+
+#define MAX_EDID 256
+#define to_exynos_connector(x)	container_of(x, struct exynos_drm_connector,\
+				drm_connector)
+
+struct exynos_drm_connector {
+	struct drm_connector	drm_connector;
+	uint32_t		encoder_id;
+	struct exynos_drm_manager *manager;
+};
+
+/* convert exynos_video_timings to drm_display_mode */
+static inline void
+convert_to_display_mode(struct drm_display_mode *mode,
+			struct fb_videomode *timing)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	mode->clock = timing->pixclock / 1000;
+	mode->vrefresh = timing->refresh;
+
+	mode->hdisplay = timing->xres;
+	mode->hsync_start = mode->hdisplay + timing->left_margin;
+	mode->hsync_end = mode->hsync_start + timing->hsync_len;
+	mode->htotal = mode->hsync_end + timing->right_margin;
+
+	mode->vdisplay = timing->yres;
+	mode->vsync_start = mode->vdisplay + timing->upper_margin;
+	mode->vsync_end = mode->vsync_start + timing->vsync_len;
+	mode->vtotal = mode->vsync_end + timing->lower_margin;
+
+	if (timing->vmode & FB_VMODE_INTERLACED)
+		mode->flags |= DRM_MODE_FLAG_INTERLACE;
+
+	if (timing->vmode & FB_VMODE_DOUBLE)
+		mode->flags |= DRM_MODE_FLAG_DBLSCAN;
+}
+
+/* convert drm_display_mode to exynos_video_timings */
+static inline void
+convert_to_video_timing(struct fb_videomode *timing,
+			struct drm_display_mode *mode)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	memset(timing, 0, sizeof(*timing));
+
+	timing->pixclock = mode->clock * 1000;
+	timing->refresh = drm_mode_vrefresh(mode);
+
+	timing->xres = mode->hdisplay;
+	timing->left_margin = mode->hsync_start - mode->hdisplay;
+	timing->hsync_len = mode->hsync_end - mode->hsync_start;
+	timing->right_margin = mode->htotal - mode->hsync_end;
+
+	timing->yres = mode->vdisplay;
+	timing->upper_margin = mode->vsync_start - mode->vdisplay;
+	timing->vsync_len = mode->vsync_end - mode->vsync_start;
+	timing->lower_margin = mode->vtotal - mode->vsync_end;
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		timing->vmode = FB_VMODE_INTERLACED;
+	else
+		timing->vmode = FB_VMODE_NONINTERLACED;
+
+	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		timing->vmode |= FB_VMODE_DOUBLE;
+}
+
+static int exynos_drm_connector_get_modes(struct drm_connector *connector)
+{
+	struct exynos_drm_connector *exynos_connector =
+					to_exynos_connector(connector);
+	struct exynos_drm_manager *manager = exynos_connector->manager;
+	struct exynos_drm_display_ops *display_ops = manager->display_ops;
+	unsigned int count;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (!display_ops) {
+		DRM_DEBUG_KMS("display_ops is null.\n");
+		return 0;
+	}
+
+	/*
+	 * if get_edid() exists then get_edid() callback of hdmi side
+	 * is called to get edid data through i2c interface else
+	 * get timing from the FIMD driver(display controller).
+	 *
+	 * P.S. in case of lcd panel, count is always 1 if success
+	 * because lcd panel has only one mode.
+	 */
+	if (display_ops->get_edid) {
+		int ret;
+		void *edid;
+
+		edid = kzalloc(MAX_EDID, GFP_KERNEL);
+		if (!edid) {
+			DRM_ERROR("failed to allocate edid\n");
+			return 0;
+		}
+
+		ret = display_ops->get_edid(manager->dev, connector,
+						edid, MAX_EDID);
+		if (ret < 0) {
+			DRM_ERROR("failed to get edid data.\n");
+			kfree(edid);
+			edid = NULL;
+			return 0;
+		}
+
+		drm_mode_connector_update_edid_property(connector, edid);
+		count = drm_add_edid_modes(connector, edid);
+
+		kfree(connector->display_info.raw_edid);
+		connector->display_info.raw_edid = edid;
+	} else {
+		struct drm_display_mode *mode = drm_mode_create(connector->dev);
+		struct fb_videomode *timing;
+
+		if (display_ops->get_timing)
+			timing = display_ops->get_timing(manager->dev);
+		else {
+			drm_mode_destroy(connector->dev, mode);
+			return 0;
+		}
+
+		convert_to_display_mode(mode, timing);
+
+		mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+		drm_mode_set_name(mode);
+		drm_mode_probed_add(connector, mode);
+
+		count = 1;
+	}
+
+	return count;
+}
+
+static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
+					    struct drm_display_mode *mode)
+{
+	struct exynos_drm_connector *exynos_connector =
+					to_exynos_connector(connector);
+	struct exynos_drm_manager *manager = exynos_connector->manager;
+	struct exynos_drm_display_ops *display_ops = manager->display_ops;
+	struct fb_videomode timing;
+	int ret = MODE_BAD;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	convert_to_video_timing(&timing, mode);
+
+	if (display_ops && display_ops->check_timing)
+		if (!display_ops->check_timing(manager->dev, (void *)&timing))
+			ret = MODE_OK;
+
+	return ret;
+}
+
+struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct exynos_drm_connector *exynos_connector =
+					to_exynos_connector(connector);
+	struct drm_mode_object *obj;
+	struct drm_encoder *encoder;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	obj = drm_mode_object_find(dev, exynos_connector->encoder_id,
+				   DRM_MODE_OBJECT_ENCODER);
+	if (!obj) {
+		DRM_DEBUG_KMS("Unknown ENCODER ID %d\n",
+				exynos_connector->encoder_id);
+		return NULL;
+	}
+
+	encoder = obj_to_encoder(obj);
+
+	return encoder;
+}
+
+static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
+	.get_modes	= exynos_drm_connector_get_modes,
+	.mode_valid	= exynos_drm_connector_mode_valid,
+	.best_encoder	= exynos_drm_best_encoder,
+};
+
+/* get detection status of display device. */
+static enum drm_connector_status
+exynos_drm_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct exynos_drm_connector *exynos_connector =
+					to_exynos_connector(connector);
+	struct exynos_drm_manager *manager = exynos_connector->manager;
+	struct exynos_drm_display_ops *display_ops =
+					manager->display_ops;
+	enum drm_connector_status status = connector_status_disconnected;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (display_ops && display_ops->is_connected) {
+		if (display_ops->is_connected(manager->dev))
+			status = connector_status_connected;
+		else
+			status = connector_status_disconnected;
+	}
+
+	return status;
+}
+
+static void exynos_drm_connector_destroy(struct drm_connector *connector)
+{
+	struct exynos_drm_connector *exynos_connector =
+		to_exynos_connector(connector);
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+	kfree(exynos_connector);
+}
+
+static struct drm_connector_funcs exynos_connector_funcs = {
+	.dpms		= drm_helper_connector_dpms,
+	.fill_modes	= drm_helper_probe_single_connector_modes,
+	.detect		= exynos_drm_connector_detect,
+	.destroy	= exynos_drm_connector_destroy,
+};
+
+struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
+						   struct drm_encoder *encoder)
+{
+	struct exynos_drm_connector *exynos_connector;
+	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+	struct drm_connector *connector;
+	int type;
+	int err;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_connector = kzalloc(sizeof(*exynos_connector), GFP_KERNEL);
+	if (!exynos_connector) {
+		DRM_ERROR("failed to allocate connector\n");
+		return NULL;
+	}
+
+	connector = &exynos_connector->drm_connector;
+
+	switch (manager->display_ops->type) {
+	case EXYNOS_DISPLAY_TYPE_HDMI:
+		type = DRM_MODE_CONNECTOR_HDMIA;
+		connector->interlace_allowed = true;
+		connector->polled = DRM_CONNECTOR_POLL_HPD;
+		break;
+	default:
+		type = DRM_MODE_CONNECTOR_Unknown;
+		break;
+	}
+
+	drm_connector_init(dev, connector, &exynos_connector_funcs, type);
+	drm_connector_helper_add(connector, &exynos_connector_helper_funcs);
+
+	err = drm_sysfs_connector_add(connector);
+	if (err)
+		goto err_connector;
+
+	exynos_connector->encoder_id = encoder->base.id;
+	exynos_connector->manager = manager;
+	connector->encoder = encoder;
+
+	err = drm_mode_connector_attach_encoder(connector, encoder);
+	if (err) {
+		DRM_ERROR("failed to attach a connector to a encoder\n");
+		goto err_sysfs;
+	}
+
+	DRM_DEBUG_KMS("connector has been created\n");
+
+	return connector;
+
+err_sysfs:
+	drm_sysfs_connector_remove(connector);
+err_connector:
+	drm_connector_cleanup(connector);
+	kfree(exynos_connector);
+	return NULL;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM Connector Driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_connector.h linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_connector.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_connector.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_connector.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * 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.
+ */
+
+#ifndef _EXYNOS_DRM_CONNECTOR_H_
+#define _EXYNOS_DRM_CONNECTOR_H_
+
+struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
+						   struct drm_encoder *encoder);
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_core.c linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_core.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,272 @@
+/* exynos_drm_core.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Author:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * 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.
+ */
+
+#include "drmP.h"
+#include "exynos_drm_drv.h"
+#include "exynos_drm_encoder.h"
+#include "exynos_drm_connector.h"
+#include "exynos_drm_fbdev.h"
+
+static DEFINE_MUTEX(exynos_drm_mutex);
+static LIST_HEAD(exynos_drm_subdrv_list);
+static struct drm_device *drm_dev;
+
+static int exynos_drm_subdrv_probe(struct drm_device *dev,
+					struct exynos_drm_subdrv *subdrv)
+{
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	if (subdrv->probe) {
+		int ret;
+
+		/*
+		 * this probe callback would be called by sub driver
+		 * after setting of all resources to this sub driver,
+		 * such as clock, irq and register map are done or by load()
+		 * of exynos drm driver.
+		 *
+		 * P.S. note that this driver is considered for modularization.
+		 */
+		ret = subdrv->probe(dev, subdrv->manager.dev);
+		if (ret)
+			return ret;
+	}
+
+	/* create and initialize a encoder for this sub driver. */
+	encoder = exynos_drm_encoder_create(dev, &subdrv->manager,
+			(1 << MAX_CRTC) - 1);
+	if (!encoder) {
+		DRM_ERROR("failed to create encoder\n");
+		return -EFAULT;
+	}
+
+	/*
+	 * create and initialize a connector for this sub driver and
+	 * attach the encoder created above to the connector.
+	 */
+	connector = exynos_drm_connector_create(dev, encoder);
+	if (!connector) {
+		DRM_ERROR("failed to create connector\n");
+		encoder->funcs->destroy(encoder);
+		return -EFAULT;
+	}
+
+	subdrv->encoder = encoder;
+	subdrv->connector = connector;
+
+	return 0;
+}
+
+static void exynos_drm_subdrv_remove(struct drm_device *dev,
+				      struct exynos_drm_subdrv *subdrv)
+{
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	if (subdrv->remove)
+		subdrv->remove(dev);
+
+	if (subdrv->encoder) {
+		struct drm_encoder *encoder = subdrv->encoder;
+		encoder->funcs->destroy(encoder);
+		subdrv->encoder = NULL;
+	}
+
+	if (subdrv->connector) {
+		struct drm_connector *connector = subdrv->connector;
+		connector->funcs->destroy(connector);
+		subdrv->connector = NULL;
+	}
+}
+
+int exynos_drm_device_register(struct drm_device *dev)
+{
+	struct exynos_drm_subdrv *subdrv, *n;
+	int err;
+
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	if (!dev)
+		return -EINVAL;
+
+	if (drm_dev) {
+		DRM_ERROR("Already drm device were registered\n");
+		return -EBUSY;
+	}
+
+	mutex_lock(&exynos_drm_mutex);
+	list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) {
+		err = exynos_drm_subdrv_probe(dev, subdrv);
+		if (err) {
+			DRM_DEBUG("exynos drm subdrv probe failed.\n");
+			list_del(&subdrv->list);
+		}
+	}
+
+	drm_dev = dev;
+	mutex_unlock(&exynos_drm_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_device_register);
+
+int exynos_drm_device_unregister(struct drm_device *dev)
+{
+	struct exynos_drm_subdrv *subdrv;
+
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	if (!dev || dev != drm_dev) {
+		WARN(1, "Unexpected drm device unregister!\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&exynos_drm_mutex);
+	list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list)
+		exynos_drm_subdrv_remove(dev, subdrv);
+
+	drm_dev = NULL;
+	mutex_unlock(&exynos_drm_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_device_unregister);
+
+static int exynos_drm_mode_group_reinit(struct drm_device *dev)
+{
+	struct drm_mode_group *group = &dev->primary->mode_group;
+	uint32_t *id_list = group->id_list;
+	int ret;
+
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	ret = drm_mode_group_init_legacy_group(dev, group);
+	if (ret < 0)
+		return ret;
+
+	kfree(id_list);
+	return 0;
+}
+
+int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
+{
+	int err;
+
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	if (!subdrv)
+		return -EINVAL;
+
+	mutex_lock(&exynos_drm_mutex);
+	if (drm_dev) {
+		err = exynos_drm_subdrv_probe(drm_dev, subdrv);
+		if (err) {
+			DRM_ERROR("failed to probe exynos drm subdrv\n");
+			mutex_unlock(&exynos_drm_mutex);
+			return err;
+		}
+
+		/*
+		 * if any specific driver such as fimd or hdmi driver called
+		 * exynos_drm_subdrv_register() later than drm_load(),
+		 * the fb helper should be re-initialized and re-configured.
+		 */
+		err = exynos_drm_fbdev_reinit(drm_dev);
+		if (err) {
+			DRM_ERROR("failed to reinitialize exynos drm fbdev\n");
+			exynos_drm_subdrv_remove(drm_dev, subdrv);
+			mutex_unlock(&exynos_drm_mutex);
+			return err;
+		}
+
+		err = exynos_drm_mode_group_reinit(drm_dev);
+		if (err) {
+			DRM_ERROR("failed to reinitialize mode group\n");
+			exynos_drm_fbdev_fini(drm_dev);
+			exynos_drm_subdrv_remove(drm_dev, subdrv);
+			mutex_unlock(&exynos_drm_mutex);
+			return err;
+		}
+	}
+
+	subdrv->drm_dev = drm_dev;
+
+	list_add_tail(&subdrv->list, &exynos_drm_subdrv_list);
+	mutex_unlock(&exynos_drm_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register);
+
+int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
+{
+	int ret = -EFAULT;
+
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	if (!subdrv) {
+		DRM_DEBUG("Unexpected exynos drm subdrv unregister!\n");
+		return ret;
+	}
+
+	mutex_lock(&exynos_drm_mutex);
+	if (drm_dev) {
+		exynos_drm_subdrv_remove(drm_dev, subdrv);
+		list_del(&subdrv->list);
+
+		/*
+		 * fb helper should be updated once a sub driver is released
+		 * to re-configure crtc and connector and also to re-setup
+		 * drm framebuffer.
+		 */
+		ret = exynos_drm_fbdev_reinit(drm_dev);
+		if (ret < 0) {
+			DRM_ERROR("failed fb helper reinit.\n");
+			goto fail;
+		}
+
+		ret = exynos_drm_mode_group_reinit(drm_dev);
+		if (ret < 0) {
+			DRM_ERROR("failed drm mode group reinit.\n");
+			goto fail;
+		}
+	}
+
+fail:
+	mutex_unlock(&exynos_drm_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(exynos_drm_subdrv_unregister);
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM Core Driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.c linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,383 @@
+/* exynos_drm_crtc.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * 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.
+ */
+
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+
+#include "exynos_drm_crtc.h"
+#include "exynos_drm_drv.h"
+#include "exynos_drm_fb.h"
+#include "exynos_drm_encoder.h"
+#include "exynos_drm_gem.h"
+#include "exynos_drm_buf.h"
+
+#define to_exynos_crtc(x)	container_of(x, struct exynos_drm_crtc,\
+				drm_crtc)
+
+/*
+ * Exynos specific crtc structure.
+ *
+ * @drm_crtc: crtc object.
+ * @overlay: contain information common to display controller and hdmi and
+ *	contents of this overlay object would be copied to sub driver size.
+ * @pipe: a crtc index created at load() with a new crtc object creation
+ *	and the crtc object would be set to private->crtc array
+ *	to get a crtc object corresponding to this pipe from private->crtc
+ *	array when irq interrupt occured. the reason of using this pipe is that
+ *	drm framework doesn't support multiple irq yet.
+ *	we can refer to the crtc to current hardware interrupt occured through
+ *	this pipe value.
+ */
+struct exynos_drm_crtc {
+	struct drm_crtc			drm_crtc;
+	struct exynos_drm_overlay	overlay;
+	unsigned int			pipe;
+};
+
+static void exynos_drm_crtc_apply(struct drm_crtc *crtc)
+{
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+	struct exynos_drm_overlay *overlay = &exynos_crtc->overlay;
+
+	exynos_drm_fn_encoder(crtc, overlay,
+			exynos_drm_encoder_crtc_mode_set);
+	exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
+			exynos_drm_encoder_crtc_commit);
+}
+
+int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
+			      struct drm_framebuffer *fb,
+			      struct drm_display_mode *mode,
+			      struct exynos_drm_crtc_pos *pos)
+{
+	struct exynos_drm_gem_buf *buffer;
+	unsigned int actual_w;
+	unsigned int actual_h;
+
+	buffer = exynos_drm_fb_get_buf(fb);
+	if (!buffer) {
+		DRM_LOG_KMS("buffer is null.\n");
+		return -EFAULT;
+	}
+
+	overlay->dma_addr = buffer->dma_addr;
+	overlay->vaddr = buffer->kvaddr;
+
+	DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
+			(unsigned long)overlay->vaddr,
+			(unsigned long)overlay->dma_addr);
+
+	actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w);
+	actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h);
+
+	/* set drm framebuffer data. */
+	overlay->fb_x = pos->fb_x;
+	overlay->fb_y = pos->fb_y;
+	overlay->fb_width = fb->width;
+	overlay->fb_height = fb->height;
+	overlay->bpp = fb->bits_per_pixel;
+	overlay->pitch = fb->pitch;
+
+	/* set overlay range to be displayed. */
+	overlay->crtc_x = pos->crtc_x;
+	overlay->crtc_y = pos->crtc_y;
+	overlay->crtc_width = actual_w;
+	overlay->crtc_height = actual_h;
+
+	/* set drm mode data. */
+	overlay->mode_width = mode->hdisplay;
+	overlay->mode_height = mode->vdisplay;
+	overlay->refresh = mode->vrefresh;
+	overlay->scan_flag = mode->flags;
+
+	DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)",
+			overlay->crtc_x, overlay->crtc_y,
+			overlay->crtc_width, overlay->crtc_height);
+
+	return 0;
+}
+
+static int exynos_drm_crtc_update(struct drm_crtc *crtc)
+{
+	struct exynos_drm_crtc *exynos_crtc;
+	struct exynos_drm_overlay *overlay;
+	struct exynos_drm_crtc_pos pos;
+	struct drm_display_mode *mode = &crtc->mode;
+	struct drm_framebuffer *fb = crtc->fb;
+
+	if (!mode || !fb)
+		return -EINVAL;
+
+	exynos_crtc = to_exynos_crtc(crtc);
+	overlay = &exynos_crtc->overlay;
+
+	memset(&pos, 0, sizeof(struct exynos_drm_crtc_pos));
+
+	/* it means the offset of framebuffer to be displayed. */
+	pos.fb_x = crtc->x;
+	pos.fb_y = crtc->y;
+
+	/* OSD position to be displayed. */
+	pos.crtc_x = 0;
+	pos.crtc_y = 0;
+	pos.crtc_w = fb->width - crtc->x;
+	pos.crtc_h = fb->height - crtc->y;
+
+	return exynos_drm_overlay_update(overlay, crtc->fb, mode, &pos);
+}
+
+static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
+	DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
+				exynos_drm_encoder_crtc_commit);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		/* TODO */
+		exynos_drm_fn_encoder(crtc, NULL,
+				exynos_drm_encoder_crtc_disable);
+		break;
+	default:
+		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
+		break;
+	}
+}
+
+static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* drm framework doesn't check NULL. */
+}
+
+static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
+{
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
+			exynos_drm_encoder_crtc_commit);
+}
+
+static bool
+exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
+			    struct drm_display_mode *mode,
+			    struct drm_display_mode *adjusted_mode)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* drm framework doesn't check NULL */
+	return true;
+}
+
+static int
+exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
+			  struct drm_display_mode *adjusted_mode, int x, int y,
+			  struct drm_framebuffer *old_fb)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	mode = adjusted_mode;
+
+	return exynos_drm_crtc_update(crtc);
+}
+
+static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+					  struct drm_framebuffer *old_fb)
+{
+	int ret;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	ret = exynos_drm_crtc_update(crtc);
+	if (ret)
+		return ret;
+
+	exynos_drm_crtc_apply(crtc);
+
+	return ret;
+}
+
+static void exynos_drm_crtc_load_lut(struct drm_crtc *crtc)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+	/* drm framework doesn't check NULL */
+}
+
+static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
+	.dpms		= exynos_drm_crtc_dpms,
+	.prepare	= exynos_drm_crtc_prepare,
+	.commit		= exynos_drm_crtc_commit,
+	.mode_fixup	= exynos_drm_crtc_mode_fixup,
+	.mode_set	= exynos_drm_crtc_mode_set,
+	.mode_set_base	= exynos_drm_crtc_mode_set_base,
+	.load_lut	= exynos_drm_crtc_load_lut,
+};
+
+static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
+				      struct drm_framebuffer *fb,
+				      struct drm_pending_vblank_event *event)
+{
+	struct drm_device *dev = crtc->dev;
+	struct exynos_drm_private *dev_priv = dev->dev_private;
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+	struct drm_framebuffer *old_fb = crtc->fb;
+	int ret = -EINVAL;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	mutex_lock(&dev->struct_mutex);
+
+	if (event) {
+		/*
+		 * the pipe from user always is 0 so we can set pipe number
+		 * of current owner to event.
+		 */
+		event->pipe = exynos_crtc->pipe;
+
+		list_add_tail(&event->base.link,
+				&dev_priv->pageflip_event_list);
+
+		ret = drm_vblank_get(dev, exynos_crtc->pipe);
+		if (ret) {
+			DRM_DEBUG("failed to acquire vblank counter\n");
+			list_del(&event->base.link);
+
+			goto out;
+		}
+
+		crtc->fb = fb;
+		ret = exynos_drm_crtc_update(crtc);
+		if (ret) {
+			crtc->fb = old_fb;
+			drm_vblank_put(dev, exynos_crtc->pipe);
+			list_del(&event->base.link);
+
+			goto out;
+		}
+
+		/*
+		 * the values related to a buffer of the drm framebuffer
+		 * to be applied should be set at here. because these values
+		 * first, are set to shadow registers and then to
+		 * real registers at vsync front porch period.
+		 */
+		exynos_drm_crtc_apply(crtc);
+	}
+out:
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
+static void exynos_drm_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+	struct exynos_drm_private *private = crtc->dev->dev_private;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	private->crtc[exynos_crtc->pipe] = NULL;
+
+	drm_crtc_cleanup(crtc);
+	kfree(exynos_crtc);
+}
+
+static struct drm_crtc_funcs exynos_crtc_funcs = {
+	.set_config	= drm_crtc_helper_set_config,
+	.page_flip	= exynos_drm_crtc_page_flip,
+	.destroy	= exynos_drm_crtc_destroy,
+};
+
+struct exynos_drm_overlay *get_exynos_drm_overlay(struct drm_device *dev,
+		struct drm_crtc *crtc)
+{
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
+	return &exynos_crtc->overlay;
+}
+
+int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
+{
+	struct exynos_drm_crtc *exynos_crtc;
+	struct exynos_drm_private *private = dev->dev_private;
+	struct drm_crtc *crtc;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
+	if (!exynos_crtc) {
+		DRM_ERROR("failed to allocate exynos crtc\n");
+		return -ENOMEM;
+	}
+
+	exynos_crtc->pipe = nr;
+	crtc = &exynos_crtc->drm_crtc;
+
+	private->crtc[nr] = crtc;
+
+	drm_crtc_init(dev, crtc, &exynos_crtc_funcs);
+	drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs);
+
+	return 0;
+}
+
+int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
+{
+	struct exynos_drm_private *private = dev->dev_private;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_drm_fn_encoder(private->crtc[crtc], &crtc,
+			exynos_drm_enable_vblank);
+
+	return 0;
+}
+
+void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
+{
+	struct exynos_drm_private *private = dev->dev_private;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_drm_fn_encoder(private->crtc[crtc], &crtc,
+			exynos_drm_disable_vblank);
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM CRTC Driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.h linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,63 @@
+/* exynos_drm_crtc.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * 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.
+ */
+
+#ifndef _EXYNOS_DRM_CRTC_H_
+#define _EXYNOS_DRM_CRTC_H_
+
+struct exynos_drm_overlay *get_exynos_drm_overlay(struct drm_device *dev,
+		struct drm_crtc *crtc);
+int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr);
+int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc);
+void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
+
+/*
+ * Exynos specific crtc postion structure.
+ *
+ * @fb_x: offset x on a framebuffer to be displyed
+ *	- the unit is screen coordinates.
+ * @fb_y: offset y on a framebuffer to be displayed
+ *	- the unit is screen coordinates.
+ * @crtc_x: offset x on hardware screen.
+ * @crtc_y: offset y on hardware screen.
+ * @crtc_w: width of hardware screen.
+ * @crtc_h: height of hardware screen.
+ */
+struct exynos_drm_crtc_pos {
+	unsigned int fb_x;
+	unsigned int fb_y;
+	unsigned int crtc_x;
+	unsigned int crtc_y;
+	unsigned int crtc_w;
+	unsigned int crtc_h;
+};
+
+int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
+			      struct drm_framebuffer *fb,
+			      struct drm_display_mode *mode,
+			      struct exynos_drm_crtc_pos *pos);
+#endif
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.c linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * 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.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc_helper.h"
+
+#include <drm/exynos_drm.h>
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_crtc.h"
+#include "exynos_drm_fbdev.h"
+#include "exynos_drm_fb.h"
+#include "exynos_drm_gem.h"
+
+#define DRIVER_NAME	"exynos-drm"
+#define DRIVER_DESC	"Samsung SoC DRM"
+#define DRIVER_DATE	"20110530"
+#define DRIVER_MAJOR	1
+#define DRIVER_MINOR	0
+
+static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
+{
+	struct exynos_drm_private *private;
+	int ret;
+	int nr;
+
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
+	if (!private) {
+		DRM_ERROR("failed to allocate private\n");
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&private->pageflip_event_list);
+	dev->dev_private = (void *)private;
+
+	drm_mode_config_init(dev);
+
+	/* init kms poll for handling hpd */
+	drm_kms_helper_poll_init(dev);
+
+	exynos_drm_mode_config_init(dev);
+
+	/*
+	 * EXYNOS4 is enough to have two CRTCs and each crtc would be used
+	 * without dependency of hardware.
+	 */
+	for (nr = 0; nr < MAX_CRTC; nr++) {
+		ret = exynos_drm_crtc_create(dev, nr);
+		if (ret)
+			goto err_crtc;
+	}
+
+	ret = drm_vblank_init(dev, MAX_CRTC);
+	if (ret)
+		goto err_crtc;
+
+	/*
+	 * probe sub drivers such as display controller and hdmi driver,
+	 * that were registered at probe() of platform driver
+	 * to the sub driver and create encoder and connector for them.
+	 */
+	ret = exynos_drm_device_register(dev);
+	if (ret)
+		goto err_vblank;
+
+	/*
+	 * create and configure fb helper and also exynos specific
+	 * fbdev object.
+	 */
+	ret = exynos_drm_fbdev_init(dev);
+	if (ret) {
+		DRM_ERROR("failed to initialize drm fbdev\n");
+		goto err_drm_device;
+	}
+
+	return 0;
+
+err_drm_device:
+	exynos_drm_device_unregister(dev);
+err_vblank:
+	drm_vblank_cleanup(dev);
+err_crtc:
+	drm_mode_config_cleanup(dev);
+	kfree(private);
+
+	return ret;
+}
+
+static int exynos_drm_unload(struct drm_device *dev)
+{
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	exynos_drm_fbdev_fini(dev);
+	exynos_drm_device_unregister(dev);
+	drm_vblank_cleanup(dev);
+	drm_kms_helper_poll_fini(dev);
+	drm_mode_config_cleanup(dev);
+	kfree(dev->dev_private);
+
+	dev->dev_private = NULL;
+
+	return 0;
+}
+
+static void exynos_drm_preclose(struct drm_device *dev,
+					struct drm_file *file_priv)
+{
+	struct exynos_drm_private *dev_priv = dev->dev_private;
+
+	/*
+	 * drm framework frees all events at release time,
+	 * so private event list should be cleared.
+	 */
+	if (!list_empty(&dev_priv->pageflip_event_list))
+		INIT_LIST_HEAD(&dev_priv->pageflip_event_list);
+}
+
+static void exynos_drm_lastclose(struct drm_device *dev)
+{
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	exynos_drm_fbdev_restore_mode(dev);
+}
+
+static struct vm_operations_struct exynos_drm_gem_vm_ops = {
+	.fault = exynos_drm_gem_fault,
+	.open = drm_gem_vm_open,
+	.close = drm_gem_vm_close,
+};
+
+static struct drm_ioctl_desc exynos_ioctls[] = {
+	DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl,
+			DRM_UNLOCKED | DRM_AUTH),
+	DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP_OFFSET,
+			exynos_drm_gem_map_offset_ioctl, DRM_UNLOCKED |
+			DRM_AUTH),
+	DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP,
+			exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH),
+};
+
+static struct drm_driver exynos_drm_driver = {
+	.driver_features	= DRIVER_HAVE_IRQ | DRIVER_BUS_PLATFORM |
+				  DRIVER_MODESET | DRIVER_GEM,
+	.load			= exynos_drm_load,
+	.unload			= exynos_drm_unload,
+	.preclose		= exynos_drm_preclose,
+	.lastclose		= exynos_drm_lastclose,
+	.get_vblank_counter	= drm_vblank_count,
+	.enable_vblank		= exynos_drm_crtc_enable_vblank,
+	.disable_vblank		= exynos_drm_crtc_disable_vblank,
+	.gem_init_object	= exynos_drm_gem_init_object,
+	.gem_free_object	= exynos_drm_gem_free_object,
+	.gem_vm_ops		= &exynos_drm_gem_vm_ops,
+	.dumb_create		= exynos_drm_gem_dumb_create,
+	.dumb_map_offset	= exynos_drm_gem_dumb_map_offset,
+	.dumb_destroy		= exynos_drm_gem_dumb_destroy,
+	.ioctls			= exynos_ioctls,
+	.fops = {
+		.owner		= THIS_MODULE,
+		.open		= drm_open,
+		.mmap		= exynos_drm_gem_mmap,
+		.poll		= drm_poll,
+		.read		= drm_read,
+		.unlocked_ioctl	= drm_ioctl,
+		.release	= drm_release,
+	},
+	.name	= DRIVER_NAME,
+	.desc	= DRIVER_DESC,
+	.date	= DRIVER_DATE,
+	.major	= DRIVER_MAJOR,
+	.minor	= DRIVER_MINOR,
+};
+
+static int exynos_drm_platform_probe(struct platform_device *pdev)
+{
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls);
+
+	return drm_platform_init(&exynos_drm_driver, pdev);
+}
+
+static int exynos_drm_platform_remove(struct platform_device *pdev)
+{
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	drm_platform_exit(&exynos_drm_driver, pdev);
+
+	return 0;
+}
+
+static struct platform_driver exynos_drm_platform_driver = {
+	.probe		= exynos_drm_platform_probe,
+	.remove		= __devexit_p(exynos_drm_platform_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= DRIVER_NAME,
+	},
+};
+
+static int __init exynos_drm_init(void)
+{
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	return platform_driver_register(&exynos_drm_platform_driver);
+}
+
+static void __exit exynos_drm_exit(void)
+{
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	platform_driver_unregister(&exynos_drm_platform_driver);
+}
+
+module_init(exynos_drm_init);
+module_exit(exynos_drm_exit);
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM Driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.h linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,257 @@
+/* exynos_drm_drv.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * 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.
+ */
+
+#ifndef _EXYNOS_DRM_DRV_H_
+#define _EXYNOS_DRM_DRV_H_
+
+#include <linux/module.h>
+#include "drm.h"
+
+#define MAX_CRTC	2
+
+struct drm_device;
+struct exynos_drm_overlay;
+struct drm_connector;
+
+/* this enumerates display type. */
+enum exynos_drm_output_type {
+	EXYNOS_DISPLAY_TYPE_NONE,
+	/* RGB or CPU Interface. */
+	EXYNOS_DISPLAY_TYPE_LCD,
+	/* HDMI Interface. */
+	EXYNOS_DISPLAY_TYPE_HDMI,
+};
+
+/*
+ * Exynos drm overlay ops structure.
+ *
+ * @mode_set: copy drm overlay info to hw specific overlay info.
+ * @commit: apply hardware specific overlay data to registers.
+ * @disable: disable hardware specific overlay.
+ */
+struct exynos_drm_overlay_ops {
+	void (*mode_set)(struct device *subdrv_dev,
+			 struct exynos_drm_overlay *overlay);
+	void (*commit)(struct device *subdrv_dev);
+	void (*disable)(struct device *subdrv_dev);
+};
+
+/*
+ * Exynos drm common overlay structure.
+ *
+ * @fb_x: offset x on a framebuffer to be displayed.
+ *	- the unit is screen coordinates.
+ * @fb_y: offset y on a framebuffer to be displayed.
+ *	- the unit is screen coordinates.
+ * @fb_width: width of a framebuffer.
+ * @fb_height: height of a framebuffer.
+ * @crtc_x: offset x on hardware screen.
+ * @crtc_y: offset y on hardware screen.
+ * @crtc_width: window width to be displayed (hardware screen).
+ * @crtc_height: window height to be displayed (hardware screen).
+ * @mode_width: width of screen mode.
+ * @mode_height: height of screen mode.
+ * @refresh: refresh rate.
+ * @scan_flag: interlace or progressive way.
+ *	(it could be DRM_MODE_FLAG_*)
+ * @bpp: pixel size.(in bit)
+ * @dma_addr: bus(accessed by dma) address to the memory region allocated
+ *	for a overlay.
+ * @vaddr: virtual memory addresss to this overlay.
+ * @default_win: a window to be enabled.
+ * @color_key: color key on or off.
+ * @index_color: if using color key feature then this value would be used
+ *			as index color.
+ * @local_path: in case of lcd type, local path mode on or off.
+ * @transparency: transparency on or off.
+ * @activated: activated or not.
+ *
+ * this structure is common to exynos SoC and its contents would be copied
+ * to hardware specific overlay info.
+ */
+struct exynos_drm_overlay {
+	unsigned int fb_x;
+	unsigned int fb_y;
+	unsigned int fb_width;
+	unsigned int fb_height;
+	unsigned int crtc_x;
+	unsigned int crtc_y;
+	unsigned int crtc_width;
+	unsigned int crtc_height;
+	unsigned int mode_width;
+	unsigned int mode_height;
+	unsigned int refresh;
+	unsigned int scan_flag;
+	unsigned int bpp;
+	unsigned int pitch;
+	dma_addr_t dma_addr;
+	void __iomem *vaddr;
+
+	bool default_win;
+	bool color_key;
+	unsigned int index_color;
+	bool local_path;
+	bool transparency;
+	bool activated;
+};
+
+/*
+ * Exynos DRM Display Structure.
+ *	- this structure is common to analog tv, digital tv and lcd panel.
+ *
+ * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
+ * @is_connected: check for that display is connected or not.
+ * @get_edid: get edid modes from display driver.
+ * @get_timing: get timing object from display driver.
+ * @check_timing: check if timing is valid or not.
+ * @power_on: display device on or off.
+ */
+struct exynos_drm_display_ops {
+	enum exynos_drm_output_type type;
+	bool (*is_connected)(struct device *dev);
+	int (*get_edid)(struct device *dev, struct drm_connector *connector,
+				u8 *edid, int len);
+	void *(*get_timing)(struct device *dev);
+	int (*check_timing)(struct device *dev, void *timing);
+	int (*power_on)(struct device *dev, int mode);
+};
+
+/*
+ * Exynos drm manager ops
+ *
+ * @mode_set: convert drm_display_mode to hw specific display mode and
+ *	      would be called by encoder->mode_set().
+ * @commit: set current hw specific display mode to hw.
+ * @disable: disable hardware specific display mode.
+ * @enable_vblank: specific driver callback for enabling vblank interrupt.
+ * @disable_vblank: specific driver callback for disabling vblank interrupt.
+ */
+struct exynos_drm_manager_ops {
+	void (*mode_set)(struct device *subdrv_dev, void *mode);
+	void (*commit)(struct device *subdrv_dev);
+	void (*disable)(struct device *subdrv_dev);
+	int (*enable_vblank)(struct device *subdrv_dev);
+	void (*disable_vblank)(struct device *subdrv_dev);
+};
+
+/*
+ * Exynos drm common manager structure.
+ *
+ * @dev: pointer to device object for subdrv device driver.
+ *	sub drivers such as display controller or hdmi driver,
+ *	have their own device object.
+ * @ops: pointer to callbacks for exynos drm specific framebuffer.
+ *	these callbacks should be set by specific drivers such fimd
+ *	or hdmi driver and are used to control hardware global registers.
+ * @overlay_ops: pointer to callbacks for exynos drm specific framebuffer.
+ *	these callbacks should be set by specific drivers such fimd
+ *	or hdmi driver and are used to control hardware overlay reigsters.
+ * @display: pointer to callbacks for exynos drm specific framebuffer.
+ *	these callbacks should be set by specific drivers such fimd
+ *	or hdmi driver and are used to control display devices such as
+ *	analog tv, digital tv and lcd panel and also get timing data for them.
+ */
+struct exynos_drm_manager {
+	struct device *dev;
+	int pipe;
+	struct exynos_drm_manager_ops *ops;
+	struct exynos_drm_overlay_ops *overlay_ops;
+	struct exynos_drm_display_ops *display_ops;
+};
+
+/*
+ * Exynos drm private structure.
+ */
+struct exynos_drm_private {
+	struct drm_fb_helper *fb_helper;
+
+	/* list head for new event to be added. */
+	struct list_head pageflip_event_list;
+
+	/*
+	 * created crtc object would be contained at this array and
+	 * this array is used to be aware of which crtc did it request vblank.
+	 */
+	struct drm_crtc *crtc[MAX_CRTC];
+};
+
+/*
+ * Exynos drm sub driver structure.
+ *
+ * @list: sub driver has its own list object to register to exynos drm driver.
+ * @drm_dev: pointer to drm_device and this pointer would be set
+ *	when sub driver calls exynos_drm_subdrv_register().
+ * @probe: this callback would be called by exynos drm driver after
+ *	subdrv is registered to it.
+ * @remove: this callback is used to release resources created
+ *	by probe callback.
+ * @manager: subdrv has its own manager to control a hardware appropriately
+ *	and we can access a hardware drawing on this manager.
+ * @encoder: encoder object owned by this sub driver.
+ * @connector: connector object owned by this sub driver.
+ */
+struct exynos_drm_subdrv {
+	struct list_head list;
+	struct drm_device *drm_dev;
+
+	int (*probe)(struct drm_device *drm_dev, struct device *dev);
+	void (*remove)(struct drm_device *dev);
+
+	struct exynos_drm_manager manager;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+};
+
+/*
+ * this function calls a probe callback registered to sub driver list and
+ * create its own encoder and connector and then set drm_device object
+ * to global one.
+ */
+int exynos_drm_device_register(struct drm_device *dev);
+/*
+ * this function calls a remove callback registered to sub driver list and
+ * destroy its own encoder and connetor.
+ */
+int exynos_drm_device_unregister(struct drm_device *dev);
+
+/*
+ * this function would be called by sub drivers such as display controller
+ * or hdmi driver to register this sub driver object to exynos drm driver
+ * and when a sub driver is registered to exynos drm driver a probe callback
+ * of the sub driver is called and creates its own encoder and connector
+ * and then fb helper and drm mode group would be re-initialized.
+ */
+int exynos_drm_subdrv_register(struct exynos_drm_subdrv *drm_subdrv);
+
+/*
+ * this function removes subdrv list from exynos drm driver and fb helper
+ * and drm mode group would be re-initialized.
+ */
+int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *drm_subdrv);
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_encoder.c linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_encoder.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_encoder.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_encoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,332 @@
+/* exynos_drm_encoder.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * 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.
+ */
+
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_crtc.h"
+#include "exynos_drm_encoder.h"
+
+#define to_exynos_encoder(x)	container_of(x, struct exynos_drm_encoder,\
+				drm_encoder)
+
+/*
+ * exynos specific encoder structure.
+ *
+ * @drm_encoder: encoder object.
+ * @manager: specific encoder has its own manager to control a hardware
+ *	appropriately and we can access a hardware drawing on this manager.
+ */
+struct exynos_drm_encoder {
+	struct drm_encoder		drm_encoder;
+	struct exynos_drm_manager	*manager;
+};
+
+static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_connector *connector;
+	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+	struct exynos_drm_manager_ops *manager_ops = manager->ops;
+
+	DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode);
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		if (manager_ops && manager_ops->commit)
+			manager_ops->commit(manager->dev);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		/* TODO */
+		if (manager_ops && manager_ops->disable)
+			manager_ops->disable(manager->dev);
+		break;
+	default:
+		DRM_ERROR("unspecified mode %d\n", mode);
+		break;
+	}
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (connector->encoder == encoder) {
+			struct exynos_drm_display_ops *display_ops =
+							manager->display_ops;
+
+			DRM_DEBUG_KMS("connector[%d] dpms[%d]\n",
+					connector->base.id, mode);
+			if (display_ops && display_ops->power_on)
+				display_ops->power_on(manager->dev, mode);
+		}
+	}
+}
+
+static bool
+exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
+			       struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* drm framework doesn't check NULL. */
+
+	return true;
+}
+
+static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
+					 struct drm_display_mode *mode,
+					 struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_connector *connector;
+	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+	struct exynos_drm_manager_ops *manager_ops = manager->ops;
+	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+	struct exynos_drm_overlay *overlay = get_exynos_drm_overlay(dev,
+						encoder->crtc);
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	mode = adjusted_mode;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (connector->encoder == encoder) {
+			if (manager_ops && manager_ops->mode_set)
+				manager_ops->mode_set(manager->dev, mode);
+
+			if (overlay_ops && overlay_ops->mode_set)
+				overlay_ops->mode_set(manager->dev, overlay);
+		}
+	}
+}
+
+static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* drm framework doesn't check NULL. */
+}
+
+static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
+{
+	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+	struct exynos_drm_manager_ops *manager_ops = manager->ops;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (manager_ops && manager_ops->commit)
+		manager_ops->commit(manager->dev);
+}
+
+static struct drm_crtc *
+exynos_drm_encoder_get_crtc(struct drm_encoder *encoder)
+{
+	return encoder->crtc;
+}
+
+static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = {
+	.dpms		= exynos_drm_encoder_dpms,
+	.mode_fixup	= exynos_drm_encoder_mode_fixup,
+	.mode_set	= exynos_drm_encoder_mode_set,
+	.prepare	= exynos_drm_encoder_prepare,
+	.commit		= exynos_drm_encoder_commit,
+	.get_crtc	= exynos_drm_encoder_get_crtc,
+};
+
+static void exynos_drm_encoder_destroy(struct drm_encoder *encoder)
+{
+	struct exynos_drm_encoder *exynos_encoder =
+		to_exynos_encoder(encoder);
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_encoder->manager->pipe = -1;
+
+	drm_encoder_cleanup(encoder);
+	encoder->dev->mode_config.num_encoder--;
+	kfree(exynos_encoder);
+}
+
+static struct drm_encoder_funcs exynos_encoder_funcs = {
+	.destroy = exynos_drm_encoder_destroy,
+};
+
+struct drm_encoder *
+exynos_drm_encoder_create(struct drm_device *dev,
+			   struct exynos_drm_manager *manager,
+			   unsigned int possible_crtcs)
+{
+	struct drm_encoder *encoder;
+	struct exynos_drm_encoder *exynos_encoder;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (!manager || !possible_crtcs)
+		return NULL;
+
+	if (!manager->dev)
+		return NULL;
+
+	exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL);
+	if (!exynos_encoder) {
+		DRM_ERROR("failed to allocate encoder\n");
+		return NULL;
+	}
+
+	exynos_encoder->manager = manager;
+	encoder = &exynos_encoder->drm_encoder;
+	encoder->possible_crtcs = possible_crtcs;
+
+	DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
+
+	drm_encoder_init(dev, encoder, &exynos_encoder_funcs,
+			DRM_MODE_ENCODER_TMDS);
+
+	drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs);
+
+	DRM_DEBUG_KMS("encoder has been created\n");
+
+	return encoder;
+}
+
+struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder)
+{
+	return to_exynos_encoder(encoder)->manager;
+}
+
+void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
+			    void (*fn)(struct drm_encoder *, void *))
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_encoder *encoder;
+	struct exynos_drm_private *private = dev->dev_private;
+	struct exynos_drm_manager *manager;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		/*
+		 * if crtc is detached from encoder, check pipe,
+		 * otherwise check crtc attached to encoder
+		 */
+		if (!encoder->crtc) {
+			manager = to_exynos_encoder(encoder)->manager;
+			if (manager->pipe < 0 ||
+					private->crtc[manager->pipe] != crtc)
+				continue;
+		} else {
+			if (encoder->crtc != crtc)
+				continue;
+		}
+
+		fn(encoder, data);
+	}
+}
+
+void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data)
+{
+	struct exynos_drm_manager *manager =
+		to_exynos_encoder(encoder)->manager;
+	struct exynos_drm_manager_ops *manager_ops = manager->ops;
+	int crtc = *(int *)data;
+
+	if (manager->pipe == -1)
+		manager->pipe = crtc;
+
+	if (manager_ops->enable_vblank)
+		manager_ops->enable_vblank(manager->dev);
+}
+
+void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data)
+{
+	struct exynos_drm_manager *manager =
+		to_exynos_encoder(encoder)->manager;
+	struct exynos_drm_manager_ops *manager_ops = manager->ops;
+	int crtc = *(int *)data;
+
+	if (manager->pipe == -1)
+		manager->pipe = crtc;
+
+	if (manager_ops->disable_vblank)
+		manager_ops->disable_vblank(manager->dev);
+}
+
+void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data)
+{
+	struct exynos_drm_manager *manager =
+		to_exynos_encoder(encoder)->manager;
+	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+	int crtc = *(int *)data;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/*
+	 * when crtc is detached from encoder, this pipe is used
+	 * to select manager operation
+	 */
+	manager->pipe = crtc;
+
+	if (overlay_ops && overlay_ops->commit)
+		overlay_ops->commit(manager->dev);
+}
+
+void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data)
+{
+	struct exynos_drm_manager *manager =
+		to_exynos_encoder(encoder)->manager;
+	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+	struct exynos_drm_overlay *overlay = data;
+
+	if (overlay_ops && overlay_ops->mode_set)
+		overlay_ops->mode_set(manager->dev, overlay);
+}
+
+void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data)
+{
+	struct exynos_drm_manager *manager =
+		to_exynos_encoder(encoder)->manager;
+	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+
+	DRM_DEBUG_KMS("\n");
+
+	if (overlay_ops && overlay_ops->disable)
+		overlay_ops->disable(manager->dev);
+
+	/*
+	 * crtc is already detached from encoder and last
+	 * function for detaching is properly done, so
+	 * clear pipe from manager to prevent repeated call
+	 */
+	if (!encoder->crtc)
+		manager->pipe = -1;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM Encoder Driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_encoder.h linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_encoder.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_encoder.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_encoder.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * 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.
+ */
+
+#ifndef _EXYNOS_DRM_ENCODER_H_
+#define _EXYNOS_DRM_ENCODER_H_
+
+struct exynos_drm_manager;
+
+struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev,
+					       struct exynos_drm_manager *mgr,
+					       unsigned int possible_crtcs);
+struct exynos_drm_manager *
+exynos_drm_get_manager(struct drm_encoder *encoder);
+void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
+			    void (*fn)(struct drm_encoder *, void *));
+void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data);
+void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data);
+void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data);
+void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data);
+void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data);
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_fb.c linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_fb.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_fb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_fb.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,277 @@
+/* exynos_drm_fb.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * 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.
+ */
+
+#include "drmP.h"
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+#include "drm_fb_helper.h"
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_fb.h"
+#include "exynos_drm_buf.h"
+#include "exynos_drm_gem.h"
+
+#define to_exynos_fb(x)	container_of(x, struct exynos_drm_fb, fb)
+
+/*
+ * exynos specific framebuffer structure.
+ *
+ * @fb: drm framebuffer obejct.
+ * @exynos_gem_obj: exynos specific gem object containing a gem object.
+ * @buffer: pointer to exynos_drm_gem_buffer object.
+ *	- contain the memory information to memory region allocated
+ *	at default framebuffer creation.
+ */
+struct exynos_drm_fb {
+	struct drm_framebuffer		fb;
+	struct exynos_drm_gem_obj	*exynos_gem_obj;
+	struct exynos_drm_gem_buf	*buffer;
+};
+
+static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
+{
+	struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	drm_framebuffer_cleanup(fb);
+
+	/*
+	 * default framebuffer has no gem object so
+	 * a buffer of the default framebuffer should be released at here.
+	 */
+	if (!exynos_fb->exynos_gem_obj && exynos_fb->buffer)
+		exynos_drm_buf_destroy(fb->dev, exynos_fb->buffer);
+
+	kfree(exynos_fb);
+	exynos_fb = NULL;
+}
+
+static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
+					struct drm_file *file_priv,
+					unsigned int *handle)
+{
+	struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	return drm_gem_handle_create(file_priv,
+			&exynos_fb->exynos_gem_obj->base, handle);
+}
+
+static int exynos_drm_fb_dirty(struct drm_framebuffer *fb,
+				struct drm_file *file_priv, unsigned flags,
+				unsigned color, struct drm_clip_rect *clips,
+				unsigned num_clips)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* TODO */
+
+	return 0;
+}
+
+static struct drm_framebuffer_funcs exynos_drm_fb_funcs = {
+	.destroy	= exynos_drm_fb_destroy,
+	.create_handle	= exynos_drm_fb_create_handle,
+	.dirty		= exynos_drm_fb_dirty,
+};
+
+static struct drm_framebuffer *
+exynos_drm_fb_init(struct drm_file *file_priv, struct drm_device *dev,
+		    struct drm_mode_fb_cmd *mode_cmd)
+{
+	struct exynos_drm_fb *exynos_fb;
+	struct drm_framebuffer *fb;
+	struct exynos_drm_gem_obj *exynos_gem_obj = NULL;
+	struct drm_gem_object *obj;
+	unsigned int size;
+	int ret;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	mode_cmd->pitch = max(mode_cmd->pitch,
+			mode_cmd->width * (mode_cmd->bpp >> 3));
+
+	DRM_LOG_KMS("drm fb create(%dx%d)\n",
+			mode_cmd->width, mode_cmd->height);
+
+	exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
+	if (!exynos_fb) {
+		DRM_ERROR("failed to allocate exynos drm framebuffer.\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	fb = &exynos_fb->fb;
+	ret = drm_framebuffer_init(dev, fb, &exynos_drm_fb_funcs);
+	if (ret) {
+		DRM_ERROR("failed to initialize framebuffer.\n");
+		goto err_init;
+	}
+
+	DRM_LOG_KMS("create: fb id: %d\n", fb->base.id);
+
+	size = mode_cmd->pitch * mode_cmd->height;
+
+	/*
+	 * mode_cmd->handle could be NULL at booting time or
+	 * with user request. if NULL, a new buffer or a gem object
+	 * would be allocated.
+	 */
+	if (!mode_cmd->handle) {
+		if (!file_priv) {
+			struct exynos_drm_gem_buf *buffer;
+
+			/*
+			 * in case that file_priv is NULL, it allocates
+			 * only buffer and this buffer would be used
+			 * for default framebuffer.
+			 */
+			buffer = exynos_drm_buf_create(dev, size);
+			if (IS_ERR(buffer)) {
+				ret = PTR_ERR(buffer);
+				goto err_buffer;
+			}
+
+			exynos_fb->buffer = buffer;
+
+			DRM_LOG_KMS("default: dma_addr = 0x%lx, size = 0x%x\n",
+					(unsigned long)buffer->dma_addr, size);
+
+			goto out;
+		} else {
+			exynos_gem_obj = exynos_drm_gem_create(dev, file_priv,
+							&mode_cmd->handle,
+							size);
+			if (IS_ERR(exynos_gem_obj)) {
+				ret = PTR_ERR(exynos_gem_obj);
+				goto err_buffer;
+			}
+		}
+	} else {
+		obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle);
+		if (!obj) {
+			DRM_ERROR("failed to lookup gem object.\n");
+			goto err_buffer;
+		}
+
+		exynos_gem_obj = to_exynos_gem_obj(obj);
+
+		drm_gem_object_unreference_unlocked(obj);
+	}
+
+	/*
+	 * if got a exynos_gem_obj from either a handle or
+	 * a new creation then exynos_fb->exynos_gem_obj is NULL
+	 * so that default framebuffer has no its own gem object,
+	 * only its own buffer object.
+	 */
+	exynos_fb->buffer = exynos_gem_obj->buffer;
+
+	DRM_LOG_KMS("dma_addr = 0x%lx, size = 0x%x, gem object = 0x%x\n",
+			(unsigned long)exynos_fb->buffer->dma_addr, size,
+			(unsigned int)&exynos_gem_obj->base);
+
+out:
+	exynos_fb->exynos_gem_obj = exynos_gem_obj;
+
+	drm_helper_mode_fill_fb_struct(fb, mode_cmd);
+
+	return fb;
+
+err_buffer:
+	drm_framebuffer_cleanup(fb);
+
+err_init:
+	kfree(exynos_fb);
+
+	return ERR_PTR(ret);
+}
+
+struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev,
+					      struct drm_file *file_priv,
+					      struct drm_mode_fb_cmd *mode_cmd)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	return exynos_drm_fb_init(file_priv, dev, mode_cmd);
+}
+
+struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb)
+{
+	struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
+	struct exynos_drm_gem_buf *buffer;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	buffer = exynos_fb->buffer;
+	if (!buffer)
+		return NULL;
+
+	DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
+			(unsigned long)buffer->kvaddr,
+			(unsigned long)buffer->dma_addr);
+
+	return buffer;
+}
+
+static void exynos_drm_output_poll_changed(struct drm_device *dev)
+{
+	struct exynos_drm_private *private = dev->dev_private;
+	struct drm_fb_helper *fb_helper = private->fb_helper;
+
+	if (fb_helper)
+		drm_fb_helper_hotplug_event(fb_helper);
+}
+
+static struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
+	.fb_create = exynos_drm_fb_create,
+	.output_poll_changed = exynos_drm_output_poll_changed,
+};
+
+void exynos_drm_mode_config_init(struct drm_device *dev)
+{
+	dev->mode_config.min_width = 0;
+	dev->mode_config.min_height = 0;
+
+	/*
+	 * set max width and height as default value(4096x4096).
+	 * this value would be used to check framebuffer size limitation
+	 * at drm_mode_addfb().
+	 */
+	dev->mode_config.max_width = 4096;
+	dev->mode_config.max_height = 4096;
+
+	dev->mode_config.funcs = &exynos_drm_mode_config_funcs;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM FB Driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,468 @@
+/* exynos_drm_fbdev.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * 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.
+ */
+
+#include "drmP.h"
+#include "drm_crtc.h"
+#include "drm_fb_helper.h"
+#include "drm_crtc_helper.h"
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_fb.h"
+#include "exynos_drm_gem.h"
+#include "exynos_drm_buf.h"
+
+#define MAX_CONNECTOR		4
+#define PREFERRED_BPP		32
+
+#define to_exynos_fbdev(x)	container_of(x, struct exynos_drm_fbdev,\
+				drm_fb_helper)
+
+struct exynos_drm_fbdev {
+	struct drm_fb_helper	drm_fb_helper;
+	struct drm_framebuffer	*fb;
+};
+
+static int exynos_drm_fbdev_set_par(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+
+	switch (var->bits_per_pixel) {
+	case 32:
+	case 24:
+	case 18:
+	case 16:
+	case 12:
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		break;
+	case 1:
+		info->fix.visual = FB_VISUAL_MONO01;
+		break;
+	default:
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	}
+
+	info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
+
+	return drm_fb_helper_set_par(info);
+}
+
+
+static struct fb_ops exynos_drm_fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_check_var	= drm_fb_helper_check_var,
+	.fb_set_par	= exynos_drm_fbdev_set_par,
+	.fb_blank	= drm_fb_helper_blank,
+	.fb_pan_display	= drm_fb_helper_pan_display,
+	.fb_setcmap	= drm_fb_helper_setcmap,
+};
+
+static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
+				     struct drm_framebuffer *fb)
+{
+	struct fb_info *fbi = helper->fbdev;
+	struct drm_device *dev = helper->dev;
+	struct exynos_drm_fbdev *exynos_fb = to_exynos_fbdev(helper);
+	struct exynos_drm_gem_buf *buffer;
+	unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3);
+	unsigned long offset;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_fb->fb = fb;
+
+	drm_fb_helper_fill_fix(fbi, fb->pitch, fb->depth);
+	drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
+
+	buffer = exynos_drm_fb_get_buf(fb);
+	if (!buffer) {
+		DRM_LOG_KMS("buffer is null.\n");
+		return -EFAULT;
+	}
+
+	offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3);
+	offset += fbi->var.yoffset * fb->pitch;
+
+	dev->mode_config.fb_base = (resource_size_t)buffer->dma_addr;
+	fbi->screen_base = buffer->kvaddr + offset;
+	fbi->fix.smem_start = (unsigned long)(buffer->dma_addr + offset);
+	fbi->screen_size = size;
+	fbi->fix.smem_len = size;
+
+	return 0;
+}
+
+static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
+				    struct drm_fb_helper_surface_size *sizes)
+{
+	struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);
+	struct drm_device *dev = helper->dev;
+	struct fb_info *fbi;
+	struct drm_mode_fb_cmd mode_cmd = { 0 };
+	struct platform_device *pdev = dev->platformdev;
+	int ret;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n",
+			sizes->surface_width, sizes->surface_height,
+			sizes->surface_bpp);
+
+	mode_cmd.width = sizes->surface_width;
+	mode_cmd.height = sizes->surface_height;
+	mode_cmd.bpp = sizes->surface_bpp;
+	mode_cmd.depth = sizes->surface_depth;
+
+	mutex_lock(&dev->struct_mutex);
+
+	fbi = framebuffer_alloc(0, &pdev->dev);
+	if (!fbi) {
+		DRM_ERROR("failed to allocate fb info.\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	exynos_fbdev->fb = exynos_drm_fb_create(dev, NULL, &mode_cmd);
+	if (IS_ERR_OR_NULL(exynos_fbdev->fb)) {
+		DRM_ERROR("failed to create drm framebuffer.\n");
+		ret = PTR_ERR(exynos_fbdev->fb);
+		goto out;
+	}
+
+	helper->fb = exynos_fbdev->fb;
+	helper->fbdev = fbi;
+
+	fbi->par = helper;
+	fbi->flags = FBINFO_FLAG_DEFAULT;
+	fbi->fbops = &exynos_drm_fb_ops;
+
+	ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
+	if (ret) {
+		DRM_ERROR("failed to allocate cmap.\n");
+		goto out;
+	}
+
+	ret = exynos_drm_fbdev_update(helper, helper->fb);
+	if (ret < 0)
+		fb_dealloc_cmap(&fbi->cmap);
+
+/*
+ * if failed, all resources allocated above would be released by
+ * drm_mode_config_cleanup() when drm_load() had been called prior
+ * to any specific driver such as fimd or hdmi driver.
+ */
+out:
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
+static bool
+exynos_drm_fbdev_is_samefb(struct drm_framebuffer *fb,
+			    struct drm_fb_helper_surface_size *sizes)
+{
+	if (fb->width != sizes->surface_width)
+		return false;
+	if (fb->height != sizes->surface_height)
+		return false;
+	if (fb->bits_per_pixel != sizes->surface_bpp)
+		return false;
+	if (fb->depth != sizes->surface_depth)
+		return false;
+
+	return true;
+}
+
+static int exynos_drm_fbdev_recreate(struct drm_fb_helper *helper,
+				      struct drm_fb_helper_surface_size *sizes)
+{
+	struct drm_device *dev = helper->dev;
+	struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);
+	struct drm_framebuffer *fb = exynos_fbdev->fb;
+	struct drm_mode_fb_cmd mode_cmd = { 0 };
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (helper->fb != fb) {
+		DRM_ERROR("drm framebuffer is different\n");
+		return -EINVAL;
+	}
+
+	if (exynos_drm_fbdev_is_samefb(fb, sizes))
+		return 0;
+
+	mode_cmd.width = sizes->surface_width;
+	mode_cmd.height = sizes->surface_height;
+	mode_cmd.bpp = sizes->surface_bpp;
+	mode_cmd.depth = sizes->surface_depth;
+
+	if (fb->funcs->destroy)
+		fb->funcs->destroy(fb);
+
+	exynos_fbdev->fb = exynos_drm_fb_create(dev, NULL, &mode_cmd);
+	if (IS_ERR(exynos_fbdev->fb)) {
+		DRM_ERROR("failed to allocate fb.\n");
+		return PTR_ERR(exynos_fbdev->fb);
+	}
+
+	helper->fb = exynos_fbdev->fb;
+	return exynos_drm_fbdev_update(helper, helper->fb);
+}
+
+static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper,
+				   struct drm_fb_helper_surface_size *sizes)
+{
+	int ret = 0;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (!helper->fb) {
+		ret = exynos_drm_fbdev_create(helper, sizes);
+		if (ret < 0) {
+			DRM_ERROR("failed to create fbdev.\n");
+			return ret;
+		}
+
+		/*
+		 * fb_helper expects a value more than 1 if succeed
+		 * because register_framebuffer() should be called.
+		 */
+		ret = 1;
+	} else {
+		ret = exynos_drm_fbdev_recreate(helper, sizes);
+		if (ret < 0) {
+			DRM_ERROR("failed to reconfigure fbdev\n");
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = {
+	.fb_probe =	exynos_drm_fbdev_probe,
+};
+
+int exynos_drm_fbdev_init(struct drm_device *dev)
+{
+	struct exynos_drm_fbdev *fbdev;
+	struct exynos_drm_private *private = dev->dev_private;
+	struct drm_fb_helper *helper;
+	unsigned int num_crtc;
+	int ret;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector)
+		return 0;
+
+	fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+	if (!fbdev) {
+		DRM_ERROR("failed to allocate drm fbdev.\n");
+		return -ENOMEM;
+	}
+
+	private->fb_helper = helper = &fbdev->drm_fb_helper;
+	helper->funcs = &exynos_drm_fb_helper_funcs;
+
+	num_crtc = dev->mode_config.num_crtc;
+
+	ret = drm_fb_helper_init(dev, helper, num_crtc, MAX_CONNECTOR);
+	if (ret < 0) {
+		DRM_ERROR("failed to initialize drm fb helper.\n");
+		goto err_init;
+	}
+
+	ret = drm_fb_helper_single_add_all_connectors(helper);
+	if (ret < 0) {
+		DRM_ERROR("failed to register drm_fb_helper_connector.\n");
+		goto err_setup;
+
+	}
+
+	ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP);
+	if (ret < 0) {
+		DRM_ERROR("failed to set up hw configuration.\n");
+		goto err_setup;
+	}
+
+	return 0;
+
+err_setup:
+	drm_fb_helper_fini(helper);
+
+err_init:
+	private->fb_helper = NULL;
+	kfree(fbdev);
+
+	return ret;
+}
+
+static void exynos_drm_fbdev_destroy(struct drm_device *dev,
+				      struct drm_fb_helper *fb_helper)
+{
+	struct drm_framebuffer *fb;
+
+	/* release drm framebuffer and real buffer */
+	if (fb_helper->fb && fb_helper->fb->funcs) {
+		fb = fb_helper->fb;
+		if (fb && fb->funcs->destroy)
+			fb->funcs->destroy(fb);
+	}
+
+	/* release linux framebuffer */
+	if (fb_helper->fbdev) {
+		struct fb_info *info;
+		int ret;
+
+		info = fb_helper->fbdev;
+		ret = unregister_framebuffer(info);
+		if (ret < 0)
+			DRM_DEBUG_KMS("failed unregister_framebuffer()\n");
+
+		if (info->cmap.len)
+			fb_dealloc_cmap(&info->cmap);
+
+		framebuffer_release(info);
+	}
+
+	drm_fb_helper_fini(fb_helper);
+}
+
+void exynos_drm_fbdev_fini(struct drm_device *dev)
+{
+	struct exynos_drm_private *private = dev->dev_private;
+	struct exynos_drm_fbdev *fbdev;
+
+	if (!private || !private->fb_helper)
+		return;
+
+	fbdev = to_exynos_fbdev(private->fb_helper);
+
+	exynos_drm_fbdev_destroy(dev, private->fb_helper);
+	kfree(fbdev);
+	private->fb_helper = NULL;
+}
+
+void exynos_drm_fbdev_restore_mode(struct drm_device *dev)
+{
+	struct exynos_drm_private *private = dev->dev_private;
+
+	if (!private || !private->fb_helper)
+		return;
+
+	drm_fb_helper_restore_fbdev_mode(private->fb_helper);
+}
+
+int exynos_drm_fbdev_reinit(struct drm_device *dev)
+{
+	struct exynos_drm_private *private = dev->dev_private;
+	struct drm_fb_helper *fb_helper;
+	int ret;
+
+	if (!private)
+		return -EINVAL;
+
+	/*
+	 * if all sub drivers were unloaded then num_connector is 0
+	 * so at this time, the framebuffers also should be destroyed.
+	 */
+	if (!dev->mode_config.num_connector) {
+		exynos_drm_fbdev_fini(dev);
+		return 0;
+	}
+
+	fb_helper = private->fb_helper;
+
+	if (fb_helper) {
+		struct list_head temp_list;
+
+		INIT_LIST_HEAD(&temp_list);
+
+		/*
+		 * fb_helper is reintialized but kernel fb is reused
+		 * so kernel_fb_list need to be backuped and restored
+		 */
+		if (!list_empty(&fb_helper->kernel_fb_list))
+			list_replace_init(&fb_helper->kernel_fb_list,
+					&temp_list);
+
+		drm_fb_helper_fini(fb_helper);
+
+		ret = drm_fb_helper_init(dev, fb_helper,
+				dev->mode_config.num_crtc, MAX_CONNECTOR);
+		if (ret < 0) {
+			DRM_ERROR("failed to initialize drm fb helper\n");
+			return ret;
+		}
+
+		if (!list_empty(&temp_list))
+			list_replace(&temp_list, &fb_helper->kernel_fb_list);
+
+		ret = drm_fb_helper_single_add_all_connectors(fb_helper);
+		if (ret < 0) {
+			DRM_ERROR("failed to add fb helper to connectors\n");
+			goto err;
+		}
+
+		ret = drm_fb_helper_initial_config(fb_helper, PREFERRED_BPP);
+		if (ret < 0) {
+			DRM_ERROR("failed to set up hw configuration.\n");
+			goto err;
+		}
+	} else {
+		/*
+		 * if drm_load() failed whem drm load() was called prior
+		 * to specific drivers, fb_helper must be NULL and so
+		 * this fuction should be called again to re-initialize and
+		 * re-configure the fb helper. it means that this function
+		 * has been called by the specific drivers.
+		 */
+		ret = exynos_drm_fbdev_init(dev);
+	}
+
+	return ret;
+
+err:
+	/*
+	 * if drm_load() failed when drm load() was called prior
+	 * to specific drivers, the fb_helper must be NULL and so check it.
+	 */
+	if (fb_helper)
+		drm_fb_helper_fini(fb_helper);
+
+	return ret;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM FBDEV Driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.h linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * 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.
+ */
+
+#ifndef _EXYNOS_DRM_FBDEV_H_
+#define _EXYNOS_DRM_FBDEV_H_
+
+int exynos_drm_fbdev_init(struct drm_device *dev);
+int exynos_drm_fbdev_reinit(struct drm_device *dev);
+void exynos_drm_fbdev_fini(struct drm_device *dev);
+void exynos_drm_fbdev_restore_mode(struct drm_device *dev);
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_fb.h linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_fb.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_fb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_fb.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * 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.
+ */
+
+#ifndef _EXYNOS_DRM_FB_H_
+#define _EXYNOS_DRM_FB_H
+
+struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev,
+					      struct drm_file *filp,
+					      struct drm_mode_fb_cmd *mode_cmd);
+
+void exynos_drm_mode_config_init(struct drm_device *dev);
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_fimd.c linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_fimd.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_fimd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_fimd.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,846 @@
+/* exynos_drm_fimd.c
+ *
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * Authors:
+ *	Joonyoung Shim <jy0922.shim@samsung.com>
+ *	Inki Dae <inki.dae@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 "drmP.h"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <drm/exynos_drm.h>
+#include <plat/regs-fb-v4.h>
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_fbdev.h"
+#include "exynos_drm_crtc.h"
+
+/*
+ * FIMD is stand for Fully Interactive Mobile Display and
+ * as a display controller, it transfers contents drawn on memory
+ * to a LCD Panel through Display Interfaces such as RGB or
+ * CPU Interface.
+ */
+
+/* position control register for hardware window 0, 2 ~ 4.*/
+#define VIDOSD_A(win)		(VIDOSD_BASE + 0x00 + (win) * 16)
+#define VIDOSD_B(win)		(VIDOSD_BASE + 0x04 + (win) * 16)
+/* size control register for hardware window 0. */
+#define VIDOSD_C_SIZE_W0	(VIDOSD_BASE + 0x08)
+/* alpha control register for hardware window 1 ~ 4. */
+#define VIDOSD_C(win)		(VIDOSD_BASE + 0x18 + (win) * 16)
+/* size control register for hardware window 1 ~ 4. */
+#define VIDOSD_D(win)		(VIDOSD_BASE + 0x0C + (win) * 16)
+
+#define VIDWx_BUF_START(win, buf)	(VIDW_BUF_START(buf) + (win) * 8)
+#define VIDWx_BUF_END(win, buf)		(VIDW_BUF_END(buf) + (win) * 8)
+#define VIDWx_BUF_SIZE(win, buf)	(VIDW_BUF_SIZE(buf) + (win) * 4)
+
+/* color key control register for hardware window 1 ~ 4. */
+#define WKEYCON0_BASE(x)		((WKEYCON0 + 0x140) + (x * 8))
+/* color key value register for hardware window 1 ~ 4. */
+#define WKEYCON1_BASE(x)		((WKEYCON1 + 0x140) + (x * 8))
+
+/* FIMD has totally five hardware windows. */
+#define WINDOWS_NR	5
+
+#define get_fimd_context(dev)	platform_get_drvdata(to_platform_device(dev))
+
+struct fimd_win_data {
+	unsigned int		offset_x;
+	unsigned int		offset_y;
+	unsigned int		ovl_width;
+	unsigned int		ovl_height;
+	unsigned int		fb_width;
+	unsigned int		fb_height;
+	unsigned int		bpp;
+	dma_addr_t		dma_addr;
+	void __iomem		*vaddr;
+	unsigned int		buf_offsize;
+	unsigned int		line_size;	/* bytes */
+};
+
+struct fimd_context {
+	struct exynos_drm_subdrv	subdrv;
+	int				irq;
+	struct drm_crtc			*crtc;
+	struct clk			*bus_clk;
+	struct clk			*lcd_clk;
+	struct resource			*regs_res;
+	void __iomem			*regs;
+	struct fimd_win_data		win_data[WINDOWS_NR];
+	unsigned int			clkdiv;
+	unsigned int			default_win;
+	unsigned long			irq_flags;
+	u32				vidcon0;
+	u32				vidcon1;
+
+	struct fb_videomode		*timing;
+};
+
+static bool fimd_display_is_connected(struct device *dev)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* TODO. */
+
+	return true;
+}
+
+static void *fimd_get_timing(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	return ctx->timing;
+}
+
+static int fimd_check_timing(struct device *dev, void *timing)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* TODO. */
+
+	return 0;
+}
+
+static int fimd_display_power_on(struct device *dev, int mode)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* TODO. */
+
+	return 0;
+}
+
+static struct exynos_drm_display_ops fimd_display_ops = {
+	.type = EXYNOS_DISPLAY_TYPE_LCD,
+	.is_connected = fimd_display_is_connected,
+	.get_timing = fimd_get_timing,
+	.check_timing = fimd_check_timing,
+	.power_on = fimd_display_power_on,
+};
+
+static void fimd_commit(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	struct fb_videomode *timing = ctx->timing;
+	u32 val;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* setup polarity values from machine code. */
+	writel(ctx->vidcon1, ctx->regs + VIDCON1);
+
+	/* setup vertical timing values. */
+	val = VIDTCON0_VBPD(timing->upper_margin - 1) |
+	       VIDTCON0_VFPD(timing->lower_margin - 1) |
+	       VIDTCON0_VSPW(timing->vsync_len - 1);
+	writel(val, ctx->regs + VIDTCON0);
+
+	/* setup horizontal timing values.  */
+	val = VIDTCON1_HBPD(timing->left_margin - 1) |
+	       VIDTCON1_HFPD(timing->right_margin - 1) |
+	       VIDTCON1_HSPW(timing->hsync_len - 1);
+	writel(val, ctx->regs + VIDTCON1);
+
+	/* setup horizontal and vertical display size. */
+	val = VIDTCON2_LINEVAL(timing->yres - 1) |
+	       VIDTCON2_HOZVAL(timing->xres - 1);
+	writel(val, ctx->regs + VIDTCON2);
+
+	/* setup clock source, clock divider, enable dma. */
+	val = ctx->vidcon0;
+	val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
+
+	if (ctx->clkdiv > 1)
+		val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR;
+	else
+		val &= ~VIDCON0_CLKDIR;	/* 1:1 clock */
+
+	/*
+	 * fields of register with prefix '_F' would be updated
+	 * at vsync(same as dma start)
+	 */
+	val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
+	writel(val, ctx->regs + VIDCON0);
+}
+
+static void fimd_disable(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
+	struct drm_device *drm_dev = subdrv->drm_dev;
+	struct exynos_drm_manager *manager = &subdrv->manager;
+	u32 val;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* fimd dma off */
+	val = readl(ctx->regs + VIDCON0);
+	val &= ~(VIDCON0_ENVID | VIDCON0_ENVID_F);
+	writel(val, ctx->regs + VIDCON0);
+
+	/*
+	 * if vblank is enabled status with dma off then
+	 * it disables vsync interrupt.
+	 */
+	if (drm_dev->vblank_enabled[manager->pipe] &&
+		atomic_read(&drm_dev->vblank_refcount[manager->pipe])) {
+		drm_vblank_put(drm_dev, manager->pipe);
+
+		/*
+		 * if vblank_disable_allowed is 0 then disable
+		 * vsync interrupt right now else the vsync interrupt
+		 * would be disabled by drm timer once a current process
+		 * gives up ownershop of vblank event.
+		 */
+		if (!drm_dev->vblank_disable_allowed)
+			drm_vblank_off(drm_dev, manager->pipe);
+	}
+}
+
+static int fimd_enable_vblank(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	u32 val;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (!test_and_set_bit(0, &ctx->irq_flags)) {
+		val = readl(ctx->regs + VIDINTCON0);
+
+		val |= VIDINTCON0_INT_ENABLE;
+		val |= VIDINTCON0_INT_FRAME;
+
+		val &= ~VIDINTCON0_FRAMESEL0_MASK;
+		val |= VIDINTCON0_FRAMESEL0_VSYNC;
+		val &= ~VIDINTCON0_FRAMESEL1_MASK;
+		val |= VIDINTCON0_FRAMESEL1_NONE;
+
+		writel(val, ctx->regs + VIDINTCON0);
+	}
+
+	return 0;
+}
+
+static void fimd_disable_vblank(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	u32 val;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (test_and_clear_bit(0, &ctx->irq_flags)) {
+		val = readl(ctx->regs + VIDINTCON0);
+
+		val &= ~VIDINTCON0_INT_FRAME;
+		val &= ~VIDINTCON0_INT_ENABLE;
+
+		writel(val, ctx->regs + VIDINTCON0);
+	}
+}
+
+static struct exynos_drm_manager_ops fimd_manager_ops = {
+	.commit = fimd_commit,
+	.disable = fimd_disable,
+	.enable_vblank = fimd_enable_vblank,
+	.disable_vblank = fimd_disable_vblank,
+};
+
+static void fimd_win_mode_set(struct device *dev,
+			      struct exynos_drm_overlay *overlay)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	struct fimd_win_data *win_data;
+	unsigned long offset;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (!overlay) {
+		dev_err(dev, "overlay is NULL\n");
+		return;
+	}
+
+	offset = overlay->fb_x * (overlay->bpp >> 3);
+	offset += overlay->fb_y * overlay->pitch;
+
+	DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
+
+	win_data = &ctx->win_data[ctx->default_win];
+
+	win_data->offset_x = overlay->crtc_x;
+	win_data->offset_y = overlay->crtc_y;
+	win_data->ovl_width = overlay->crtc_width;
+	win_data->ovl_height = overlay->crtc_height;
+	win_data->fb_width = overlay->fb_width;
+	win_data->fb_height = overlay->fb_height;
+	win_data->dma_addr = overlay->dma_addr + offset;
+	win_data->vaddr = overlay->vaddr + offset;
+	win_data->bpp = overlay->bpp;
+	win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
+				(overlay->bpp >> 3);
+	win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
+
+	DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
+			win_data->offset_x, win_data->offset_y);
+	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
+			win_data->ovl_width, win_data->ovl_height);
+	DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n",
+			(unsigned long)win_data->dma_addr,
+			(unsigned long)win_data->vaddr);
+	DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
+			overlay->fb_width, overlay->crtc_width);
+}
+
+static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	struct fimd_win_data *win_data = &ctx->win_data[win];
+	unsigned long val;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	val = WINCONx_ENWIN;
+
+	switch (win_data->bpp) {
+	case 1:
+		val |= WINCON0_BPPMODE_1BPP;
+		val |= WINCONx_BITSWP;
+		val |= WINCONx_BURSTLEN_4WORD;
+		break;
+	case 2:
+		val |= WINCON0_BPPMODE_2BPP;
+		val |= WINCONx_BITSWP;
+		val |= WINCONx_BURSTLEN_8WORD;
+		break;
+	case 4:
+		val |= WINCON0_BPPMODE_4BPP;
+		val |= WINCONx_BITSWP;
+		val |= WINCONx_BURSTLEN_8WORD;
+		break;
+	case 8:
+		val |= WINCON0_BPPMODE_8BPP_PALETTE;
+		val |= WINCONx_BURSTLEN_8WORD;
+		val |= WINCONx_BYTSWP;
+		break;
+	case 16:
+		val |= WINCON0_BPPMODE_16BPP_565;
+		val |= WINCONx_HAWSWP;
+		val |= WINCONx_BURSTLEN_16WORD;
+		break;
+	case 24:
+		val |= WINCON0_BPPMODE_24BPP_888;
+		val |= WINCONx_WSWP;
+		val |= WINCONx_BURSTLEN_16WORD;
+		break;
+	case 32:
+		val |= WINCON1_BPPMODE_28BPP_A4888
+			| WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
+		val |= WINCONx_WSWP;
+		val |= WINCONx_BURSTLEN_16WORD;
+		break;
+	default:
+		DRM_DEBUG_KMS("invalid pixel size so using unpacked 24bpp.\n");
+
+		val |= WINCON0_BPPMODE_24BPP_888;
+		val |= WINCONx_WSWP;
+		val |= WINCONx_BURSTLEN_16WORD;
+		break;
+	}
+
+	DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
+
+	writel(val, ctx->regs + WINCON(win));
+}
+
+static void fimd_win_set_colkey(struct device *dev, unsigned int win)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	unsigned int keycon0 = 0, keycon1 = 0;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
+			WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
+
+	keycon1 = WxKEYCON1_COLVAL(0xffffffff);
+
+	writel(keycon0, ctx->regs + WKEYCON0_BASE(win));
+	writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
+}
+
+static void fimd_win_commit(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	struct fimd_win_data *win_data;
+	int win = ctx->default_win;
+	unsigned long val, alpha, size;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (win < 0 || win > WINDOWS_NR)
+		return;
+
+	win_data = &ctx->win_data[win];
+
+	/*
+	 * SHADOWCON register is used for enabling timing.
+	 *
+	 * for example, once only width value of a register is set,
+	 * if the dma is started then fimd hardware could malfunction so
+	 * with protect window setting, the register fields with prefix '_F'
+	 * wouldn't be updated at vsync also but updated once unprotect window
+	 * is set.
+	 */
+
+	/* protect windows */
+	val = readl(ctx->regs + SHADOWCON);
+	val |= SHADOWCON_WINx_PROTECT(win);
+	writel(val, ctx->regs + SHADOWCON);
+
+	/* buffer start address */
+	val = (unsigned long)win_data->dma_addr;
+	writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
+
+	/* buffer end address */
+	size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3);
+	val = (unsigned long)(win_data->dma_addr + size);
+	writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
+
+	DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
+			(unsigned long)win_data->dma_addr, val, size);
+	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
+			win_data->ovl_width, win_data->ovl_height);
+
+	/* buffer size */
+	val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) |
+		VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size);
+	writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
+
+	/* OSD position */
+	val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) |
+		VIDOSDxA_TOPLEFT_Y(win_data->offset_y);
+	writel(val, ctx->regs + VIDOSD_A(win));
+
+	val = VIDOSDxB_BOTRIGHT_X(win_data->offset_x +
+					win_data->ovl_width - 1) |
+		VIDOSDxB_BOTRIGHT_Y(win_data->offset_y +
+					win_data->ovl_height - 1);
+	writel(val, ctx->regs + VIDOSD_B(win));
+
+	DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
+			win_data->offset_x, win_data->offset_y,
+			win_data->offset_x + win_data->ovl_width - 1,
+			win_data->offset_y + win_data->ovl_height - 1);
+
+	/* hardware window 0 doesn't support alpha channel. */
+	if (win != 0) {
+		/* OSD alpha */
+		alpha = VIDISD14C_ALPHA1_R(0xf) |
+			VIDISD14C_ALPHA1_G(0xf) |
+			VIDISD14C_ALPHA1_B(0xf);
+
+		writel(alpha, ctx->regs + VIDOSD_C(win));
+	}
+
+	/* OSD size */
+	if (win != 3 && win != 4) {
+		u32 offset = VIDOSD_D(win);
+		if (win == 0)
+			offset = VIDOSD_C_SIZE_W0;
+		val = win_data->ovl_width * win_data->ovl_height;
+		writel(val, ctx->regs + offset);
+
+		DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
+	}
+
+	fimd_win_set_pixfmt(dev, win);
+
+	/* hardware window 0 doesn't support color key. */
+	if (win != 0)
+		fimd_win_set_colkey(dev, win);
+
+	/* Enable DMA channel and unprotect windows */
+	val = readl(ctx->regs + SHADOWCON);
+	val |= SHADOWCON_CHx_ENABLE(win);
+	val &= ~SHADOWCON_WINx_PROTECT(win);
+	writel(val, ctx->regs + SHADOWCON);
+}
+
+static void fimd_win_disable(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	int win = ctx->default_win;
+	u32 val;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (win < 0 || win > WINDOWS_NR)
+		return;
+
+	/* protect windows */
+	val = readl(ctx->regs + SHADOWCON);
+	val |= SHADOWCON_WINx_PROTECT(win);
+	writel(val, ctx->regs + SHADOWCON);
+
+	/* wincon */
+	val = readl(ctx->regs + WINCON(win));
+	val &= ~WINCONx_ENWIN;
+	writel(val, ctx->regs + WINCON(win));
+
+	/* unprotect windows */
+	val = readl(ctx->regs + SHADOWCON);
+	val &= ~SHADOWCON_CHx_ENABLE(win);
+	val &= ~SHADOWCON_WINx_PROTECT(win);
+	writel(val, ctx->regs + SHADOWCON);
+}
+
+static struct exynos_drm_overlay_ops fimd_overlay_ops = {
+	.mode_set = fimd_win_mode_set,
+	.commit = fimd_win_commit,
+	.disable = fimd_win_disable,
+};
+
+static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc)
+{
+	struct exynos_drm_private *dev_priv = drm_dev->dev_private;
+	struct drm_pending_vblank_event *e, *t;
+	struct timeval now;
+	unsigned long flags;
+	bool is_checked = false;
+
+	spin_lock_irqsave(&drm_dev->event_lock, flags);
+
+	list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
+			base.link) {
+		/* if event's pipe isn't same as crtc then ignore it. */
+		if (crtc != e->pipe)
+			continue;
+
+		is_checked = true;
+
+		do_gettimeofday(&now);
+		e->event.sequence = 0;
+		e->event.tv_sec = now.tv_sec;
+		e->event.tv_usec = now.tv_usec;
+
+		list_move_tail(&e->base.link, &e->base.file_priv->event_list);
+		wake_up_interruptible(&e->base.file_priv->event_wait);
+	}
+
+	if (is_checked)
+		drm_vblank_put(drm_dev, crtc);
+
+	spin_unlock_irqrestore(&drm_dev->event_lock, flags);
+}
+
+static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
+{
+	struct fimd_context *ctx = (struct fimd_context *)dev_id;
+	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
+	struct drm_device *drm_dev = subdrv->drm_dev;
+	struct exynos_drm_manager *manager = &subdrv->manager;
+	u32 val;
+
+	val = readl(ctx->regs + VIDINTCON1);
+
+	if (val & VIDINTCON1_INT_FRAME)
+		/* VSYNC interrupt */
+		writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
+
+	/*
+	 * in case that vblank_disable_allowed is 1, it could induce
+	 * the problem that manager->pipe could be -1 because with
+	 * disable callback, vsync interrupt isn't disabled and at this moment,
+	 * vsync interrupt could occur. the vsync interrupt would be disabled
+	 * by timer handler later.
+	 */
+	if (manager->pipe == -1)
+		return IRQ_HANDLED;
+
+	drm_handle_vblank(drm_dev, manager->pipe);
+	fimd_finish_pageflip(drm_dev, manager->pipe);
+
+	return IRQ_HANDLED;
+}
+
+static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/*
+	 * enable drm irq mode.
+	 * - with irq_enabled = 1, we can use the vblank feature.
+	 *
+	 * P.S. note that we wouldn't use drm irq handler but
+	 *	just specific driver own one instead because
+	 *	drm framework supports only one irq handler.
+	 */
+	drm_dev->irq_enabled = 1;
+
+	return 0;
+}
+
+static void fimd_subdrv_remove(struct drm_device *drm_dev)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* TODO. */
+}
+
+static int fimd_calc_clkdiv(struct fimd_context *ctx,
+			    struct fb_videomode *timing)
+{
+	unsigned long clk = clk_get_rate(ctx->lcd_clk);
+	u32 retrace;
+	u32 clkdiv;
+	u32 best_framerate = 0;
+	u32 framerate;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	retrace = timing->left_margin + timing->hsync_len +
+				timing->right_margin + timing->xres;
+	retrace *= timing->upper_margin + timing->vsync_len +
+				timing->lower_margin + timing->yres;
+
+	/* default framerate is 60Hz */
+	if (!timing->refresh)
+		timing->refresh = 60;
+
+	clk /= retrace;
+
+	for (clkdiv = 1; clkdiv < 0x100; clkdiv++) {
+		int tmp;
+
+		/* get best framerate */
+		framerate = clk / clkdiv;
+		tmp = timing->refresh - framerate;
+		if (tmp < 0) {
+			best_framerate = framerate;
+			continue;
+		} else {
+			if (!best_framerate)
+				best_framerate = framerate;
+			else if (tmp < (best_framerate - framerate))
+				best_framerate = framerate;
+			break;
+		}
+	}
+
+	return clkdiv;
+}
+
+static void fimd_clear_win(struct fimd_context *ctx, int win)
+{
+	u32 val;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	writel(0, ctx->regs + WINCON(win));
+	writel(0, ctx->regs + VIDOSD_A(win));
+	writel(0, ctx->regs + VIDOSD_B(win));
+	writel(0, ctx->regs + VIDOSD_C(win));
+
+	if (win == 1 || win == 2)
+		writel(0, ctx->regs + VIDOSD_D(win));
+
+	val = readl(ctx->regs + SHADOWCON);
+	val &= ~SHADOWCON_WINx_PROTECT(win);
+	writel(val, ctx->regs + SHADOWCON);
+}
+
+static int __devinit fimd_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct fimd_context *ctx;
+	struct exynos_drm_subdrv *subdrv;
+	struct exynos_drm_fimd_pdata *pdata;
+	struct fb_videomode *timing;
+	struct resource *res;
+	int win;
+	int ret = -EINVAL;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(dev, "no platform data specified\n");
+		return -EINVAL;
+	}
+
+	timing = &pdata->timing;
+	if (!timing) {
+		dev_err(dev, "timing is null.\n");
+		return -EINVAL;
+	}
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->bus_clk = clk_get(dev, "fimd");
+	if (IS_ERR(ctx->bus_clk)) {
+		dev_err(dev, "failed to get bus clock\n");
+		ret = PTR_ERR(ctx->bus_clk);
+		goto err_clk_get;
+	}
+
+	clk_enable(ctx->bus_clk);
+
+	ctx->lcd_clk = clk_get(dev, "sclk_fimd");
+	if (IS_ERR(ctx->lcd_clk)) {
+		dev_err(dev, "failed to get lcd clock\n");
+		ret = PTR_ERR(ctx->lcd_clk);
+		goto err_bus_clk;
+	}
+
+	clk_enable(ctx->lcd_clk);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "failed to find registers\n");
+		ret = -ENOENT;
+		goto err_clk;
+	}
+
+	ctx->regs_res = request_mem_region(res->start, resource_size(res),
+					   dev_name(dev));
+	if (!ctx->regs_res) {
+		dev_err(dev, "failed to claim register region\n");
+		ret = -ENOENT;
+		goto err_clk;
+	}
+
+	ctx->regs = ioremap(res->start, resource_size(res));
+	if (!ctx->regs) {
+		dev_err(dev, "failed to map registers\n");
+		ret = -ENXIO;
+		goto err_req_region_io;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(dev, "irq request failed.\n");
+		goto err_req_region_irq;
+	}
+
+	ctx->irq = res->start;
+
+	for (win = 0; win < WINDOWS_NR; win++)
+		fimd_clear_win(ctx, win);
+
+	ret = request_irq(ctx->irq, fimd_irq_handler, 0, "drm_fimd", ctx);
+	if (ret < 0) {
+		dev_err(dev, "irq request failed.\n");
+		goto err_req_irq;
+	}
+
+	ctx->clkdiv = fimd_calc_clkdiv(ctx, timing);
+	ctx->vidcon0 = pdata->vidcon0;
+	ctx->vidcon1 = pdata->vidcon1;
+	ctx->default_win = pdata->default_win;
+	ctx->timing = timing;
+
+	timing->pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv;
+
+	DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n",
+			timing->pixclock, ctx->clkdiv);
+
+	subdrv = &ctx->subdrv;
+
+	subdrv->probe = fimd_subdrv_probe;
+	subdrv->remove = fimd_subdrv_remove;
+	subdrv->manager.pipe = -1;
+	subdrv->manager.ops = &fimd_manager_ops;
+	subdrv->manager.overlay_ops = &fimd_overlay_ops;
+	subdrv->manager.display_ops = &fimd_display_ops;
+	subdrv->manager.dev = dev;
+
+	platform_set_drvdata(pdev, ctx);
+	exynos_drm_subdrv_register(subdrv);
+
+	return 0;
+
+err_req_irq:
+err_req_region_irq:
+	iounmap(ctx->regs);
+
+err_req_region_io:
+	release_resource(ctx->regs_res);
+	kfree(ctx->regs_res);
+
+err_clk:
+	clk_disable(ctx->lcd_clk);
+	clk_put(ctx->lcd_clk);
+
+err_bus_clk:
+	clk_disable(ctx->bus_clk);
+	clk_put(ctx->bus_clk);
+
+err_clk_get:
+	kfree(ctx);
+	return ret;
+}
+
+static int __devexit fimd_remove(struct platform_device *pdev)
+{
+	struct fimd_context *ctx = platform_get_drvdata(pdev);
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_drm_subdrv_unregister(&ctx->subdrv);
+
+	clk_disable(ctx->lcd_clk);
+	clk_disable(ctx->bus_clk);
+	clk_put(ctx->lcd_clk);
+	clk_put(ctx->bus_clk);
+
+	iounmap(ctx->regs);
+	release_resource(ctx->regs_res);
+	kfree(ctx->regs_res);
+	free_irq(ctx->irq, ctx);
+
+	kfree(ctx);
+
+	return 0;
+}
+
+static struct platform_driver fimd_driver = {
+	.probe		= fimd_probe,
+	.remove		= __devexit_p(fimd_remove),
+	.driver		= {
+		.name	= "exynos4-fb",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init fimd_init(void)
+{
+	return platform_driver_register(&fimd_driver);
+}
+
+static void __exit fimd_exit(void)
+{
+	platform_driver_unregister(&fimd_driver);
+}
+
+module_init(fimd_init);
+module_exit(fimd_exit);
+
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_DESCRIPTION("Samsung DRM FIMD Driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.c linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,430 @@
+/* exynos_drm_gem.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Author: Inki Dae <inki.dae@samsung.com>
+ *
+ * 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.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+
+#include <drm/exynos_drm.h>
+
+#include "exynos_drm_drv.h"
+#include "exynos_drm_gem.h"
+#include "exynos_drm_buf.h"
+
+static unsigned int convert_to_vm_err_msg(int msg)
+{
+	unsigned int out_msg;
+
+	switch (msg) {
+	case 0:
+	case -ERESTARTSYS:
+	case -EINTR:
+		out_msg = VM_FAULT_NOPAGE;
+		break;
+
+	case -ENOMEM:
+		out_msg = VM_FAULT_OOM;
+		break;
+
+	default:
+		out_msg = VM_FAULT_SIGBUS;
+		break;
+	}
+
+	return out_msg;
+}
+
+static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT;
+}
+
+static struct exynos_drm_gem_obj
+		*exynos_drm_gem_init(struct drm_device *drm_dev,
+			struct drm_file *file_priv, unsigned int *handle,
+			unsigned int size)
+{
+	struct exynos_drm_gem_obj *exynos_gem_obj;
+	struct drm_gem_object *obj;
+	int ret;
+
+	exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL);
+	if (!exynos_gem_obj) {
+		DRM_ERROR("failed to allocate exynos gem object.\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	obj = &exynos_gem_obj->base;
+
+	ret = drm_gem_object_init(drm_dev, obj, size);
+	if (ret < 0) {
+		DRM_ERROR("failed to initialize gem object.\n");
+		ret = -EINVAL;
+		goto err_object_init;
+	}
+
+	DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
+
+	ret = drm_gem_create_mmap_offset(obj);
+	if (ret < 0) {
+		DRM_ERROR("failed to allocate mmap offset.\n");
+		goto err_create_mmap_offset;
+	}
+
+	/*
+	 * allocate a id of idr table where the obj is registered
+	 * and handle has the id what user can see.
+	 */
+	ret = drm_gem_handle_create(file_priv, obj, handle);
+	if (ret)
+		goto err_handle_create;
+
+	DRM_DEBUG_KMS("gem handle = 0x%x\n", *handle);
+
+	/* drop reference from allocate - handle holds it now. */
+	drm_gem_object_unreference_unlocked(obj);
+
+	return exynos_gem_obj;
+
+err_handle_create:
+	drm_gem_free_mmap_offset(obj);
+
+err_create_mmap_offset:
+	drm_gem_object_release(obj);
+
+err_object_init:
+	kfree(exynos_gem_obj);
+
+	return ERR_PTR(ret);
+}
+
+struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
+				struct drm_file *file_priv,
+				unsigned int *handle, unsigned long size)
+{
+
+	struct exynos_drm_gem_obj *exynos_gem_obj = NULL;
+	struct exynos_drm_gem_buf *buffer;
+
+	size = roundup(size, PAGE_SIZE);
+
+	DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size);
+
+	buffer = exynos_drm_buf_create(dev, size);
+	if (IS_ERR(buffer)) {
+		return ERR_CAST(buffer);
+	}
+
+	exynos_gem_obj = exynos_drm_gem_init(dev, file_priv, handle, size);
+	if (IS_ERR(exynos_gem_obj)) {
+		exynos_drm_buf_destroy(dev, buffer);
+		return exynos_gem_obj;
+	}
+
+	exynos_gem_obj->buffer = buffer;
+
+	return exynos_gem_obj;
+}
+
+int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
+					struct drm_file *file_priv)
+{
+	struct drm_exynos_gem_create *args = data;
+	struct exynos_drm_gem_obj *exynos_gem_obj = NULL;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	exynos_gem_obj = exynos_drm_gem_create(dev, file_priv,
+						&args->handle, args->size);
+	if (IS_ERR(exynos_gem_obj))
+		return PTR_ERR(exynos_gem_obj);
+
+	return 0;
+}
+
+int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *file_priv)
+{
+	struct drm_exynos_gem_map_off *args = data;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	DRM_DEBUG_KMS("handle = 0x%x, offset = 0x%lx\n",
+			args->handle, (unsigned long)args->offset);
+
+	if (!(dev->driver->driver_features & DRIVER_GEM)) {
+		DRM_ERROR("does not support GEM.\n");
+		return -ENODEV;
+	}
+
+	return exynos_drm_gem_dumb_map_offset(file_priv, dev, args->handle,
+			&args->offset);
+}
+
+static int exynos_drm_gem_mmap_buffer(struct file *filp,
+		struct vm_area_struct *vma)
+{
+	struct drm_gem_object *obj = filp->private_data;
+	struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
+	struct exynos_drm_gem_buf *buffer;
+	unsigned long pfn, vm_size;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	vma->vm_flags |= (VM_IO | VM_RESERVED);
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	vma->vm_file = filp;
+
+	vm_size = vma->vm_end - vma->vm_start;
+	/*
+	 * a buffer contains information to physically continuous memory
+	 * allocated by user request or at framebuffer creation.
+	 */
+	buffer = exynos_gem_obj->buffer;
+
+	/* check if user-requested size is valid. */
+	if (vm_size > buffer->size)
+		return -EINVAL;
+
+	/*
+	 * get page frame number to physical memory to be mapped
+	 * to user space.
+	 */
+	pfn = ((unsigned long)exynos_gem_obj->buffer->dma_addr) >> PAGE_SHIFT;
+
+	DRM_DEBUG_KMS("pfn = 0x%lx\n", pfn);
+
+	if (remap_pfn_range(vma, vma->vm_start, pfn, vm_size,
+				vma->vm_page_prot)) {
+		DRM_ERROR("failed to remap pfn range.\n");
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+static const struct file_operations exynos_drm_gem_fops = {
+	.mmap = exynos_drm_gem_mmap_buffer,
+};
+
+int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *file_priv)
+{
+	struct drm_exynos_gem_mmap *args = data;
+	struct drm_gem_object *obj;
+	unsigned int addr;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (!(dev->driver->driver_features & DRIVER_GEM)) {
+		DRM_ERROR("does not support GEM.\n");
+		return -ENODEV;
+	}
+
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	if (!obj) {
+		DRM_ERROR("failed to lookup gem object.\n");
+		return -EINVAL;
+	}
+
+	obj->filp->f_op = &exynos_drm_gem_fops;
+	obj->filp->private_data = obj;
+
+	down_write(&current->mm->mmap_sem);
+	addr = do_mmap(obj->filp, 0, args->size,
+			PROT_READ | PROT_WRITE, MAP_SHARED, 0);
+	up_write(&current->mm->mmap_sem);
+
+	drm_gem_object_unreference_unlocked(obj);
+
+	if (IS_ERR((void *)addr))
+		return PTR_ERR((void *)addr);
+
+	args->mapped = addr;
+
+	DRM_DEBUG_KMS("mapped = 0x%lx\n", (unsigned long)args->mapped);
+
+	return 0;
+}
+
+int exynos_drm_gem_init_object(struct drm_gem_object *obj)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	return 0;
+}
+
+void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj)
+{
+	struct exynos_drm_gem_obj *exynos_gem_obj;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	DRM_DEBUG_KMS("handle count = %d\n",
+			atomic_read(&gem_obj->handle_count));
+
+	if (gem_obj->map_list.map)
+		drm_gem_free_mmap_offset(gem_obj);
+
+	/* release file pointer to gem object. */
+	drm_gem_object_release(gem_obj);
+
+	exynos_gem_obj = to_exynos_gem_obj(gem_obj);
+
+	exynos_drm_buf_destroy(gem_obj->dev, exynos_gem_obj->buffer);
+
+	kfree(exynos_gem_obj);
+}
+
+int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
+		struct drm_device *dev, struct drm_mode_create_dumb *args)
+{
+	struct exynos_drm_gem_obj *exynos_gem_obj;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/*
+	 * alocate memory to be used for framebuffer.
+	 * - this callback would be called by user application
+	 *	with DRM_IOCTL_MODE_CREATE_DUMB command.
+	 */
+
+	args->pitch = args->width * args->bpp >> 3;
+	args->size = args->pitch * args->height;
+
+	exynos_gem_obj = exynos_drm_gem_create(dev, file_priv, &args->handle,
+							args->size);
+	if (IS_ERR(exynos_gem_obj))
+		return PTR_ERR(exynos_gem_obj);
+
+	return 0;
+}
+
+int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
+		struct drm_device *dev, uint32_t handle, uint64_t *offset)
+{
+	struct exynos_drm_gem_obj *exynos_gem_obj;
+	struct drm_gem_object *obj;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	mutex_lock(&dev->struct_mutex);
+
+	/*
+	 * get offset of memory allocated for drm framebuffer.
+	 * - this callback would be called by user application
+	 *	with DRM_IOCTL_MODE_MAP_DUMB command.
+	 */
+
+	obj = drm_gem_object_lookup(dev, file_priv, handle);
+	if (!obj) {
+		DRM_ERROR("failed to lookup gem object.\n");
+		mutex_unlock(&dev->struct_mutex);
+		return -EINVAL;
+	}
+
+	exynos_gem_obj = to_exynos_gem_obj(obj);
+
+	*offset = get_gem_mmap_offset(&exynos_gem_obj->base);
+
+	drm_gem_object_unreference(obj);
+
+	DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+}
+
+int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct drm_gem_object *obj = vma->vm_private_data;
+	struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
+	struct drm_device *dev = obj->dev;
+	unsigned long pfn;
+	pgoff_t page_offset;
+	int ret;
+
+	page_offset = ((unsigned long)vmf->virtual_address -
+			vma->vm_start) >> PAGE_SHIFT;
+
+	mutex_lock(&dev->struct_mutex);
+
+	pfn = (((unsigned long)exynos_gem_obj->buffer->dma_addr) >>
+			PAGE_SHIFT) + page_offset;
+
+	ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return convert_to_vm_err_msg(ret);
+}
+
+int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	int ret;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/* set vm_area_struct. */
+	ret = drm_gem_mmap(filp, vma);
+	if (ret < 0) {
+		DRM_ERROR("failed to mmap.\n");
+		return ret;
+	}
+
+	vma->vm_flags &= ~VM_PFNMAP;
+	vma->vm_flags |= VM_MIXEDMAP;
+
+	return ret;
+}
+
+
+int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
+		struct drm_device *dev, unsigned int handle)
+{
+	int ret;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/*
+	 * obj->refcount and obj->handle_count are decreased and
+	 * if both them are 0 then exynos_drm_gem_free_object()
+	 * would be called by callback to release resources.
+	 */
+	ret = drm_gem_handle_delete(file_priv, handle);
+	if (ret < 0) {
+		DRM_ERROR("failed to delete drm_gem_handle.\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DRM GEM Module");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.h linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,123 @@
+/* exynos_drm_gem.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authoer: Inki Dae <inki.dae@samsung.com>
+ *
+ * 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.
+ */
+
+#ifndef _EXYNOS_DRM_GEM_H_
+#define _EXYNOS_DRM_GEM_H_
+
+#define to_exynos_gem_obj(x)	container_of(x,\
+			struct exynos_drm_gem_obj, base)
+
+/*
+ * exynos drm gem buffer structure.
+ *
+ * @kvaddr: kernel virtual address to allocated memory region.
+ * @dma_addr: bus address(accessed by dma) to allocated memory region.
+ *	- this address could be physical address without IOMMU and
+ *	device address with IOMMU.
+ * @size: size of allocated memory region.
+ */
+struct exynos_drm_gem_buf {
+	void __iomem		*kvaddr;
+	dma_addr_t		dma_addr;
+	unsigned long		size;
+};
+
+/*
+ * exynos drm buffer structure.
+ *
+ * @base: a gem object.
+ *	- a new handle to this gem object would be created
+ *	by drm_gem_handle_create().
+ * @buffer: a pointer to exynos_drm_gem_buffer object.
+ *	- contain the information to memory region allocated
+ *	by user request or at framebuffer creation.
+ *	continuous memory region allocated by user request
+ *	or at framebuffer creation.
+ *
+ * P.S. this object would be transfered to user as kms_bo.handle so
+ *	user can access the buffer through kms_bo.handle.
+ */
+struct exynos_drm_gem_obj {
+	struct drm_gem_object base;
+	struct exynos_drm_gem_buf *buffer;
+};
+
+/* create a new buffer and get a new gem handle. */
+struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
+		struct drm_file *file_priv,
+		unsigned int *handle, unsigned long size);
+
+/*
+ * request gem object creation and buffer allocation as the size
+ * that it is calculated with framebuffer information such as width,
+ * height and bpp.
+ */
+int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *file_priv);
+
+/* get buffer offset to map to user space. */
+int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *file_priv);
+
+/* unmap a buffer from user space. */
+int exynos_drm_gem_munmap_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *file_priv);
+
+/* initialize gem object. */
+int exynos_drm_gem_init_object(struct drm_gem_object *obj);
+
+/* free gem object. */
+void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj);
+
+/* create memory region for drm framebuffer. */
+int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
+		struct drm_device *dev, struct drm_mode_create_dumb *args);
+
+/* map memory region for drm framebuffer to user space. */
+int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
+		struct drm_device *dev, uint32_t handle, uint64_t *offset);
+
+/* page fault handler and mmap fault address(virtual) to physical memory. */
+int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
+
+/*
+ * mmap the physically continuous memory that a gem object contains
+ * to user space.
+ */
+int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *file_priv);
+
+/* set vm_flags and we can change the vm attribute to other one at here. */
+int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
+
+/*
+ * destroy memory region allocated.
+ *	- a gem handle and physical memory region pointed by a gem object
+ *	would be released by drm_gem_handle_delete().
+ */
+int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
+		struct drm_device *dev, unsigned int handle);
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/Kconfig linux-libre-3.2-gnu/drivers/gpu/drm/exynos/Kconfig
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,20 @@
+config DRM_EXYNOS
+	tristate "DRM Support for Samsung SoC EXYNOS Series"
+	depends on DRM && PLAT_SAMSUNG
+	default	n
+	select DRM_KMS_HELPER
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
+	help
+	  Choose this option if you have a Samsung SoC EXYNOS chipset.
+	  If M is selected the module will be called exynosdrm.
+
+config DRM_EXYNOS_FIMD
+	tristate "Exynos DRM FIMD"
+	depends on DRM_EXYNOS
+	default n
+	help
+	  Choose this option if you want to use Exynos FIMD for DRM.
+	  If M is selected, the module will be called exynos_drm_fimd
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/exynos/Makefile linux-libre-3.2-gnu/drivers/gpu/drm/exynos/Makefile
--- linux-libre-3.1-gnu/drivers/gpu/drm/exynos/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/exynos/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,11 @@
+#
+# 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 -Idrivers/gpu/drm/exynos
+exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \
+		exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \
+		exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o
+
+obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o
+obj-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i2c/ch7006_drv.c linux-libre-3.2-gnu/drivers/gpu/drm/i2c/ch7006_drv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i2c/ch7006_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i2c/ch7006_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
  *
  */
 
+#include <linux/module.h>
+
 #include "ch7006_priv.h"
 
 /* DRM encoder functions */
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i2c/sil164_drv.c linux-libre-3.2-gnu/drivers/gpu/drm/i2c/sil164_drv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i2c/sil164_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i2c/sil164_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
  *
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "drm_crtc_helper.h"
 #include "drm_encoder_slave.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i810/i810_drv.c linux-libre-3.2-gnu/drivers/gpu/drm/i810/i810_drv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i810/i810_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i810/i810_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,8 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "drm.h"
 #include "i810_drm.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/dvo_ch7017.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/dvo_ch7017.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/dvo_ch7017.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/dvo_ch7017.c	2012-01-04 18:55:44.000000000 -0500
@@ -227,7 +227,7 @@
 	default:
 		DRM_DEBUG_KMS("ch701x not detected, got %d: from %s "
 			      "slave %d.\n",
-			      val, adapter->name,dvo->slave_addr);
+			      val, adapter->name, dvo->slave_addr);
 		goto fail;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/dvo_ch7xxx.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/dvo_ch7xxx.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/dvo_ch7xxx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/dvo_ch7xxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -111,7 +111,7 @@
 /** Reads an 8 bit register */
 static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 {
-	struct ch7xxx_priv *ch7xxx= dvo->dev_priv;
+	struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
 	struct i2c_adapter *adapter = dvo->i2c_bus;
 	u8 out_buf[2];
 	u8 in_buf[2];
@@ -303,7 +303,7 @@
 
 	for (i = 0; i < CH7xxx_NUM_REGS; i++) {
 		uint8_t val;
-		if ((i % 8) == 0 )
+		if ((i % 8) == 0)
 			DRM_LOG_KMS("\n %02X: ", i);
 		ch7xxx_readb(dvo, i, &val);
 		DRM_LOG_KMS("%02X ", val);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/dvo_ivch.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/dvo_ivch.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/dvo_ivch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/dvo_ivch.c	2012-01-04 18:55:44.000000000 -0500
@@ -344,8 +344,8 @@
 			   (adjusted_mode->hdisplay - 1)) >> 2;
 		y_ratio = (((mode->vdisplay - 1) << 16) /
 			   (adjusted_mode->vdisplay - 1)) >> 2;
-		ivch_write (dvo, VR42, x_ratio);
-		ivch_write (dvo, VR41, y_ratio);
+		ivch_write(dvo, VR42, x_ratio);
+		ivch_write(dvo, VR41, y_ratio);
 	} else {
 		vr01 &= ~VR01_PANEL_FIT_ENABLE;
 		vr40 &= ~VR40_CLOCK_GATING_ENABLE;
@@ -410,7 +410,7 @@
 	}
 }
 
-struct intel_dvo_dev_ops ivch_ops= {
+struct intel_dvo_dev_ops ivch_ops = {
 	.init = ivch_init,
 	.dpms = ivch_dpms,
 	.mode_valid = ivch_mode_valid,
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/dvo_sil164.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/dvo_sil164.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/dvo_sil164.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/dvo_sil164.c	2012-01-04 18:55:44.000000000 -0500
@@ -104,7 +104,7 @@
 
 static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
 {
-	struct sil164_priv *sil= dvo->dev_priv;
+	struct sil164_priv *sil = dvo->dev_priv;
 	struct i2c_adapter *adapter = dvo->i2c_bus;
 	uint8_t out_buf[2];
 	struct i2c_msg msg = {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/dvo_tfp410.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/dvo_tfp410.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/dvo_tfp410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/dvo_tfp410.c	2012-01-04 18:55:44.000000000 -0500
@@ -56,7 +56,7 @@
 #define TFP410_CTL_2_MDI	(1<<0)
 
 #define TFP410_CTL_3		0x0A
-#define TFP410_CTL_3_DK_MASK 	(0x7<<5)
+#define TFP410_CTL_3_DK_MASK	(0x7<<5)
 #define TFP410_CTL_3_DK		(1<<5)
 #define TFP410_CTL_3_DKEN	(1<<4)
 #define TFP410_CTL_3_CTL_MASK	(0x7<<1)
@@ -225,12 +225,12 @@
 			    struct drm_display_mode *mode,
 			    struct drm_display_mode *adjusted_mode)
 {
-    /* As long as the basics are set up, since we don't have clock dependencies
-     * in the mode setup, we can just leave the registers alone and everything
-     * will work fine.
-     */
-    /* don't do much */
-    return;
+	/* As long as the basics are set up, since we don't have clock dependencies
+	* in the mode setup, we can just leave the registers alone and everything
+	* will work fine.
+	*/
+	/* don't do much */
+	return;
 }
 
 /* set the tfp410 power state */
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_debugfs.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_debugfs.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_debugfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_debugfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "drmP.h"
 #include "drm.h"
 #include "intel_drv.h"
@@ -61,6 +62,7 @@
 	const struct intel_device_info *info = INTEL_INFO(dev);
 
 	seq_printf(m, "gen: %d\n", info->gen);
+	seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev));
 #define B(x) seq_printf(m, #x ": %s\n", yesno(info->x))
 	B(is_mobile);
 	B(is_i85x);
@@ -98,12 +100,12 @@
 
 static const char *get_tiling_flag(struct drm_i915_gem_object *obj)
 {
-    switch (obj->tiling_mode) {
-    default:
-    case I915_TILING_NONE: return " ";
-    case I915_TILING_X: return "X";
-    case I915_TILING_Y: return "Y";
-    }
+	switch (obj->tiling_mode) {
+	default:
+	case I915_TILING_NONE: return " ";
+	case I915_TILING_X: return "X";
+	case I915_TILING_Y: return "Y";
+	}
 }
 
 static const char *cache_level_str(int type)
@@ -217,7 +219,7 @@
 			++mappable_count; \
 		} \
 	} \
-} while(0)
+} while (0)
 
 static int i915_gem_object_info(struct seq_file *m, void* data)
 {
@@ -635,11 +637,16 @@
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *ring;
+	int ret;
 
 	ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
 	if (ring->size == 0)
 		return 0;
 
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
 	seq_printf(m, "Ring %s:\n", ring->name);
 	seq_printf(m, "  Head :    %08x\n", I915_READ_HEAD(ring) & HEAD_ADDR);
 	seq_printf(m, "  Tail :    %08x\n", I915_READ_TAIL(ring) & TAIL_ADDR);
@@ -653,6 +660,8 @@
 	seq_printf(m, "  Control : %08x\n", I915_READ_CTL(ring));
 	seq_printf(m, "  Start :   %08x\n", I915_READ_START(ring));
 
+	mutex_unlock(&dev->struct_mutex);
+
 	return 0;
 }
 
@@ -841,7 +850,16 @@
 	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;
-	u16 crstanddelay = I915_READ16(CRSTANDVID);
+	u16 crstanddelay;
+	int ret;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	crstanddelay = I915_READ16(CRSTANDVID);
+
+	mutex_unlock(&dev->struct_mutex);
 
 	seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
 
@@ -939,7 +957,11 @@
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	u32 delayfreq;
-	int i;
+	int ret, i;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
 
 	for (i = 0; i < 16; i++) {
 		delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
@@ -947,6 +969,8 @@
 			   (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
 	}
 
+	mutex_unlock(&dev->struct_mutex);
+
 	return 0;
 }
 
@@ -961,13 +985,19 @@
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	u32 inttoext;
-	int i;
+	int ret, i;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
 
 	for (i = 1; i <= 32; i++) {
 		inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
 		seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
 	}
 
+	mutex_unlock(&dev->struct_mutex);
+
 	return 0;
 }
 
@@ -976,9 +1006,19 @@
 	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;
-	u32 rgvmodectl = I915_READ(MEMMODECTL);
-	u32 rstdbyctl = I915_READ(RSTDBYCTL);
-	u16 crstandvid = I915_READ16(CRSTANDVID);
+	u32 rgvmodectl, rstdbyctl;
+	u16 crstandvid;
+	int ret;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	rgvmodectl = I915_READ(MEMMODECTL);
+	rstdbyctl = I915_READ(RSTDBYCTL);
+	crstandvid = I915_READ16(CRSTANDVID);
+
+	mutex_unlock(&dev->struct_mutex);
 
 	seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
 		   "yes" : "no");
@@ -1166,9 +1206,16 @@
 	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;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
 
 	seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
 
+	mutex_unlock(&dev->struct_mutex);
+
 	return 0;
 }
 
@@ -1293,12 +1340,12 @@
 	char buf[80];
 	int len;
 
-	len = snprintf(buf, sizeof (buf),
+	len = snprintf(buf, sizeof(buf),
 		       "wedged :  %d\n",
 		       atomic_read(&dev_priv->mm.wedged));
 
-	if (len > sizeof (buf))
-		len = sizeof (buf);
+	if (len > sizeof(buf))
+		len = sizeof(buf);
 
 	return simple_read_from_buffer(ubuf, max, ppos, buf, len);
 }
@@ -1314,7 +1361,7 @@
 	int val = 1;
 
 	if (cnt > 0) {
-		if (cnt > sizeof (buf) - 1)
+		if (cnt > sizeof(buf) - 1)
 			return -EINVAL;
 
 		if (copy_from_user(buf, ubuf, cnt))
@@ -1357,11 +1404,11 @@
 	char buf[80];
 	int len;
 
-	len = snprintf(buf, sizeof (buf),
+	len = snprintf(buf, sizeof(buf),
 		       "max freq: %d\n", dev_priv->max_delay * 50);
 
-	if (len > sizeof (buf))
-		len = sizeof (buf);
+	if (len > sizeof(buf))
+		len = sizeof(buf);
 
 	return simple_read_from_buffer(ubuf, max, ppos, buf, len);
 }
@@ -1378,7 +1425,7 @@
 	int val = 1;
 
 	if (cnt > 0) {
-		if (cnt > sizeof (buf) - 1)
+		if (cnt > sizeof(buf) - 1)
 			return -EINVAL;
 
 		if (copy_from_user(buf, ubuf, cnt))
@@ -1432,12 +1479,12 @@
 	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
 	mutex_unlock(&dev_priv->dev->struct_mutex);
 
-	len = snprintf(buf, sizeof (buf),
+	len = snprintf(buf, sizeof(buf),
 		       "%d\n", (snpcr & GEN6_MBC_SNPCR_MASK) >>
 		       GEN6_MBC_SNPCR_SHIFT);
 
-	if (len > sizeof (buf))
-		len = sizeof (buf);
+	if (len > sizeof(buf))
+		len = sizeof(buf);
 
 	return simple_read_from_buffer(ubuf, max, ppos, buf, len);
 }
@@ -1455,7 +1502,7 @@
 	int val = 1;
 
 	if (cnt > 0) {
-		if (cnt > sizeof (buf) - 1)
+		if (cnt > sizeof(buf) - 1)
 			return -EINVAL;
 
 		if (copy_from_user(buf, ubuf, cnt))
@@ -1505,7 +1552,10 @@
 	node->minor = minor;
 	node->dent = ent;
 	node->info_ent = (void *) key;
-	list_add(&node->list, &minor->debugfs_nodes.list);
+
+	mutex_lock(&minor->debugfs_lock);
+	list_add(&node->list, &minor->debugfs_list);
+	mutex_unlock(&minor->debugfs_lock);
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_dma.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_dma.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
 #include <linux/pnp.h>
 #include <linux/vga_switcheroo.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <acpi/video.h>
 
 static void i915_write_hws_pga(struct drm_device *dev)
@@ -884,7 +885,7 @@
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
+	dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
 	if (!dev_priv->bridge_dev) {
 		DRM_ERROR("bridge device not found\n");
 		return -1;
@@ -1453,6 +1454,14 @@
 
 	diff1 = now - dev_priv->last_time1;
 
+	/* Prevent division-by-zero if we are asking too fast.
+	 * Also, we don't get interesting results if we are polling
+	 * faster than once in 10ms, so just return the saved value
+	 * in such cases.
+	 */
+	if (diff1 <= 10)
+		return dev_priv->chipset_power;
+
 	count1 = I915_READ(DMIEC);
 	count2 = I915_READ(DDREC);
 	count3 = I915_READ(CSIEC);
@@ -1483,6 +1492,8 @@
 	dev_priv->last_count1 = total_count;
 	dev_priv->last_time1 = now;
 
+	dev_priv->chipset_power = ret;
+
 	return ret;
 }
 
@@ -1730,10 +1741,10 @@
  */
 unsigned long i915_read_mch_val(void)
 {
-  	struct drm_i915_private *dev_priv;
+	struct drm_i915_private *dev_priv;
 	unsigned long chipset_val, graphics_val, ret = 0;
 
-  	spin_lock(&mchdev_lock);
+	spin_lock(&mchdev_lock);
 	if (!i915_mch_dev)
 		goto out_unlock;
 	dev_priv = i915_mch_dev;
@@ -1744,9 +1755,9 @@
 	ret = chipset_val + graphics_val;
 
 out_unlock:
-  	spin_unlock(&mchdev_lock);
+	spin_unlock(&mchdev_lock);
 
-  	return ret;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(i915_read_mch_val);
 
@@ -1757,10 +1768,10 @@
  */
 bool i915_gpu_raise(void)
 {
-  	struct drm_i915_private *dev_priv;
+	struct drm_i915_private *dev_priv;
 	bool ret = true;
 
-  	spin_lock(&mchdev_lock);
+	spin_lock(&mchdev_lock);
 	if (!i915_mch_dev) {
 		ret = false;
 		goto out_unlock;
@@ -1771,9 +1782,9 @@
 		dev_priv->max_delay--;
 
 out_unlock:
-  	spin_unlock(&mchdev_lock);
+	spin_unlock(&mchdev_lock);
 
-  	return ret;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(i915_gpu_raise);
 
@@ -1785,10 +1796,10 @@
  */
 bool i915_gpu_lower(void)
 {
-  	struct drm_i915_private *dev_priv;
+	struct drm_i915_private *dev_priv;
 	bool ret = true;
 
-  	spin_lock(&mchdev_lock);
+	spin_lock(&mchdev_lock);
 	if (!i915_mch_dev) {
 		ret = false;
 		goto out_unlock;
@@ -1799,9 +1810,9 @@
 		dev_priv->max_delay++;
 
 out_unlock:
-  	spin_unlock(&mchdev_lock);
+	spin_unlock(&mchdev_lock);
 
-  	return ret;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(i915_gpu_lower);
 
@@ -1812,10 +1823,10 @@
  */
 bool i915_gpu_busy(void)
 {
-  	struct drm_i915_private *dev_priv;
+	struct drm_i915_private *dev_priv;
 	bool ret = false;
 
-  	spin_lock(&mchdev_lock);
+	spin_lock(&mchdev_lock);
 	if (!i915_mch_dev)
 		goto out_unlock;
 	dev_priv = i915_mch_dev;
@@ -1823,9 +1834,9 @@
 	ret = dev_priv->busy;
 
 out_unlock:
-  	spin_unlock(&mchdev_lock);
+	spin_unlock(&mchdev_lock);
 
-  	return ret;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(i915_gpu_busy);
 
@@ -1837,10 +1848,10 @@
  */
 bool i915_gpu_turbo_disable(void)
 {
-  	struct drm_i915_private *dev_priv;
+	struct drm_i915_private *dev_priv;
 	bool ret = true;
 
-  	spin_lock(&mchdev_lock);
+	spin_lock(&mchdev_lock);
 	if (!i915_mch_dev) {
 		ret = false;
 		goto out_unlock;
@@ -1853,9 +1864,9 @@
 		ret = false;
 
 out_unlock:
-  	spin_unlock(&mchdev_lock);
+	spin_unlock(&mchdev_lock);
 
-  	return ret;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
 
@@ -1948,7 +1959,7 @@
 
 	agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
 
-        dev_priv->mm.gtt_mapping =
+	dev_priv->mm.gtt_mapping =
 		io_mapping_create_wc(dev->agp->base, agp_size);
 	if (dev_priv->mm.gtt_mapping == NULL) {
 		ret = -EIO;
@@ -2035,7 +2046,9 @@
 	spin_lock_init(&dev_priv->error_lock);
 	spin_lock_init(&dev_priv->rps_lock);
 
-	if (IS_MOBILE(dev) || !IS_GEN2(dev))
+	if (IS_IVYBRIDGE(dev))
+		dev_priv->num_pipe = 3;
+	else if (IS_MOBILE(dev) || !IS_GEN2(dev))
 		dev_priv->num_pipe = 2;
 	else
 		dev_priv->num_pipe = 1;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_drv.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_drv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include "intel_drv.h"
 
 #include <linux/console.h>
+#include <linux/module.h>
 #include "drm_crtc_helper.h"
 
 static int i915_modeset __read_mostly = -1;
@@ -57,17 +58,17 @@
 MODULE_PARM_DESC(powersave,
 		"Enable powersavings, fbc, downclocking, etc. (default: true)");
 
-unsigned int i915_semaphores __read_mostly = 0;
+int i915_semaphores __read_mostly = -1;
 module_param_named(semaphores, i915_semaphores, int, 0600);
 MODULE_PARM_DESC(semaphores,
-		"Use semaphores for inter-ring sync (default: false)");
+		"Use semaphores for inter-ring sync (default: -1 (use per-chip defaults))");
 
-unsigned int i915_enable_rc6 __read_mostly = 0;
+int i915_enable_rc6 __read_mostly = -1;
 module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);
 MODULE_PARM_DESC(i915_enable_rc6,
-		"Enable power-saving render C-state 6 (default: true)");
+		"Enable power-saving render C-state 6 (default: -1 (use per-chip default)");
 
-unsigned int i915_enable_fbc __read_mostly = -1;
+int i915_enable_fbc __read_mostly = -1;
 module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600);
 MODULE_PARM_DESC(i915_enable_fbc,
 		"Enable frame buffer compression for power savings "
@@ -79,11 +80,11 @@
 		"Use panel (LVDS/eDP) downclocking for power savings "
 		"(default: false)");
 
-unsigned int i915_panel_use_ssc __read_mostly = 1;
+int i915_panel_use_ssc __read_mostly = -1;
 module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
 MODULE_PARM_DESC(lvds_use_ssc,
 		"Use Spread Spectrum Clock with panels [LVDS/eDP] "
-		"(default: true)");
+		"(default: auto from VBT)");
 
 int i915_vbt_sdvo_panel_type __read_mostly = -1;
 module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600);
@@ -106,7 +107,7 @@
 extern int intel_agp_enabled;
 
 #define INTEL_VGA_DEVICE(id, info) {		\
-	.class = PCI_CLASS_DISPLAY_VGA << 8,	\
+	.class = PCI_BASE_CLASS_DISPLAY << 16,	\
 	.class_mask = 0xff0000,			\
 	.vendor = 0x8086,			\
 	.device = id,				\
@@ -294,7 +295,7 @@
 #define INTEL_PCH_CPT_DEVICE_ID_TYPE	0x1c00
 #define INTEL_PCH_PPT_DEVICE_ID_TYPE	0x1e00
 
-void intel_detect_pch (struct drm_device *dev)
+void intel_detect_pch(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct pci_dev *pch;
@@ -327,7 +328,7 @@
 	}
 }
 
-static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
+void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
 {
 	int count;
 
@@ -343,6 +344,22 @@
 		udelay(10);
 }
 
+void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
+{
+	int count;
+
+	count = 0;
+	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1))
+		udelay(10);
+
+	I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 1);
+	POSTING_READ(FORCEWAKE_MT);
+
+	count = 0;
+	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1) == 0)
+		udelay(10);
+}
+
 /*
  * Generally this is called implicitly by the register read function. However,
  * if some sequence requires the GT to not power down then this function should
@@ -355,15 +372,21 @@
 
 	/* Forcewake is atomic in case we get in here without the lock */
 	if (atomic_add_return(1, &dev_priv->forcewake_count) == 1)
-		__gen6_gt_force_wake_get(dev_priv);
+		dev_priv->display.force_wake_get(dev_priv);
 }
 
-static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
+void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
 {
 	I915_WRITE_NOTRACE(FORCEWAKE, 0);
 	POSTING_READ(FORCEWAKE);
 }
 
+void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
+{
+	I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 0);
+	POSTING_READ(FORCEWAKE_MT);
+}
+
 /*
  * see gen6_gt_force_wake_get()
  */
@@ -372,12 +395,12 @@
 	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
 
 	if (atomic_dec_and_test(&dev_priv->forcewake_count))
-		__gen6_gt_force_wake_put(dev_priv);
+		dev_priv->display.force_wake_put(dev_priv);
 }
 
 void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
 {
-	if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES ) {
+	if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
 		int loop = 500;
 		u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
 		while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
@@ -471,6 +494,9 @@
 		error = i915_gem_init_ringbuffer(dev);
 		mutex_unlock(&dev->struct_mutex);
 
+		if (HAS_PCH_SPLIT(dev))
+			ironlake_init_pch_refclk(dev);
+
 		drm_mode_config_reset(dev);
 		drm_irq_install(dev);
 
@@ -770,12 +796,12 @@
 }
 
 static const struct dev_pm_ops i915_pm_ops = {
-     .suspend = i915_pm_suspend,
-     .resume = i915_pm_resume,
-     .freeze = i915_pm_freeze,
-     .thaw = i915_pm_thaw,
-     .poweroff = i915_pm_poweroff,
-     .restore = i915_pm_resume,
+	.suspend = i915_pm_suspend,
+	.resume = i915_pm_resume,
+	.freeze = i915_pm_freeze,
+	.thaw = i915_pm_thaw,
+	.poweroff = i915_pm_poweroff,
+	.restore = i915_pm_resume,
 };
 
 static struct vm_operations_struct i915_gem_vm_ops = {
@@ -785,8 +811,8 @@
 };
 
 static struct drm_driver driver = {
-	/* don't use mtrr's here, the Xserver or user space app should
-	 * deal with them for intel hardware.
+	/* Don't use MTRRs here; the Xserver or userspace app should
+	 * deal with them for Intel hardware.
 	 */
 	.driver_features =
 	    DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
@@ -895,3 +921,44 @@
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL and additional rights");
+
+/* We give fast paths for the really cool registers */
+#define NEEDS_FORCE_WAKE(dev_priv, reg) \
+	(((dev_priv)->info->gen >= 6) && \
+	 ((reg) < 0x40000) &&		 \
+	 ((reg) != FORCEWAKE) &&	 \
+	 ((reg) != ECOBUS))
+
+#define __i915_read(x, y) \
+u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
+	u##x val = 0; \
+	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
+		gen6_gt_force_wake_get(dev_priv); \
+		val = read##y(dev_priv->regs + reg); \
+		gen6_gt_force_wake_put(dev_priv); \
+	} else { \
+		val = read##y(dev_priv->regs + reg); \
+	} \
+	trace_i915_reg_rw(false, reg, val, sizeof(val)); \
+	return val; \
+}
+
+__i915_read(8, b)
+__i915_read(16, w)
+__i915_read(32, l)
+__i915_read(64, q)
+#undef __i915_read
+
+#define __i915_write(x, y) \
+void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
+	trace_i915_reg_rw(true, reg, val, sizeof(val)); \
+	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
+		__gen6_gt_wait_for_fifo(dev_priv); \
+	} \
+	write##y(val, dev_priv->regs + reg); \
+}
+__i915_write(8, b)
+__i915_write(16, w)
+__i915_write(32, l)
+__i915_write(64, q)
+#undef __i915_write
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_drv.h linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_drv.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_drv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_drv.h	2012-01-04 18:55:44.000000000 -0500
@@ -107,6 +107,7 @@
 struct opregion_acpi;
 struct opregion_swsci;
 struct opregion_asle;
+struct drm_i915_private;
 
 struct intel_opregion {
 	struct opregion_header *header;
@@ -126,6 +127,9 @@
 	struct _drm_i915_sarea *sarea_priv;
 };
 #define I915_FENCE_REG_NONE -1
+#define I915_MAX_NUM_FENCES 16
+/* 16 fences + sign bit for FENCE_REG_NONE */
+#define I915_MAX_NUM_FENCE_BITS 5
 
 struct drm_i915_fence_reg {
 	struct list_head lru_list;
@@ -139,7 +143,6 @@
 	u8 slave_addr;
 	u8 dvo_wiring;
 	u8 i2c_pin;
-	u8 i2c_speed;
 	u8 ddc_pin;
 };
 
@@ -169,7 +172,7 @@
 	u32 instdone1;
 	u32 seqno;
 	u64 bbaddr;
-	u64 fence[16];
+	u64 fence[I915_MAX_NUM_FENCES];
 	struct timeval time;
 	struct drm_i915_error_object {
 		int page_count;
@@ -183,7 +186,7 @@
 		u32 gtt_offset;
 		u32 read_domains;
 		u32 write_domain;
-		s32 fence_reg:5;
+		s32 fence_reg:I915_MAX_NUM_FENCE_BITS;
 		s32 pinned:2;
 		u32 tiling:2;
 		u32 dirty:1;
@@ -209,6 +212,8 @@
 			     struct drm_display_mode *adjusted_mode,
 			     int x, int y,
 			     struct drm_framebuffer *old_fb);
+	void (*write_eld)(struct drm_connector *connector,
+			  struct drm_crtc *crtc);
 	void (*fdi_link_train)(struct drm_crtc *crtc);
 	void (*init_clock_gating)(struct drm_device *dev);
 	void (*init_pch_clock_gating)(struct drm_device *dev);
@@ -217,6 +222,8 @@
 			  struct drm_i915_gem_object *obj);
 	int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 			    int x, int y);
+	void (*force_wake_get)(struct drm_i915_private *dev_priv);
+	void (*force_wake_put)(struct drm_i915_private *dev_priv);
 	/* clock updates for mode set */
 	/* cursor updates */
 	/* render clock increase/decrease */
@@ -226,26 +233,26 @@
 
 struct intel_device_info {
 	u8 gen;
-	u8 is_mobile : 1;
-	u8 is_i85x : 1;
-	u8 is_i915g : 1;
-	u8 is_i945gm : 1;
-	u8 is_g33 : 1;
-	u8 need_gfx_hws : 1;
-	u8 is_g4x : 1;
-	u8 is_pineview : 1;
-	u8 is_broadwater : 1;
-	u8 is_crestline : 1;
-	u8 is_ivybridge : 1;
-	u8 has_fbc : 1;
-	u8 has_pipe_cxsr : 1;
-	u8 has_hotplug : 1;
-	u8 cursor_needs_physical : 1;
-	u8 has_overlay : 1;
-	u8 overlay_needs_physical : 1;
-	u8 supports_tv : 1;
-	u8 has_bsd_ring : 1;
-	u8 has_blt_ring : 1;
+	u8 is_mobile:1;
+	u8 is_i85x:1;
+	u8 is_i915g:1;
+	u8 is_i945gm:1;
+	u8 is_g33:1;
+	u8 need_gfx_hws:1;
+	u8 is_g4x:1;
+	u8 is_pineview:1;
+	u8 is_broadwater:1;
+	u8 is_crestline:1;
+	u8 is_ivybridge:1;
+	u8 has_fbc:1;
+	u8 has_pipe_cxsr:1;
+	u8 has_hotplug:1;
+	u8 cursor_needs_physical:1;
+	u8 has_overlay:1;
+	u8 overlay_needs_physical:1;
+	u8 supports_tv:1;
+	u8 has_bsd_ring:1;
+	u8 has_blt_ring:1;
 };
 
 enum no_fbc_reason {
@@ -347,7 +354,6 @@
 	/* LVDS info */
 	int backlight_level;  /* restore backlight to this value */
 	bool backlight_enabled;
-	struct drm_display_mode *panel_fixed_mode;
 	struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
 	struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
 
@@ -357,6 +363,7 @@
 	unsigned int lvds_vbt:1;
 	unsigned int int_crt_support:1;
 	unsigned int lvds_use_ssc:1;
+	unsigned int display_clock_mode:1;
 	int lvds_ssc_freq;
 	struct {
 		int rate;
@@ -374,7 +381,7 @@
 	struct notifier_block lid_notifier;
 
 	int crt_ddc_pin;
-	struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
+	struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */
 	int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
 	int num_fence_regs; /* 8 on pre-965, 16 otherwise */
 
@@ -505,7 +512,7 @@
 	u8 saveAR[21];
 	u8 saveDACMASK;
 	u8 saveCR[37];
-	uint64_t saveFENCE[16];
+	uint64_t saveFENCE[I915_MAX_NUM_FENCES];
 	u32 saveCURACNTR;
 	u32 saveCURAPOS;
 	u32 saveCURABASE;
@@ -672,10 +679,9 @@
 	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];
+	struct drm_crtc *plane_to_crtc_mapping[3];
+	struct drm_crtc *pipe_to_crtc_mapping[3];
 	wait_queue_head_t pending_flip_queue;
 	bool flip_pending_is_done;
 
@@ -707,6 +713,7 @@
 
 	u64 last_count1;
 	unsigned long last_time1;
+	unsigned long chipset_power;
 	u64 last_count2;
 	struct timespec last_time2;
 	unsigned long gfx_power;
@@ -759,39 +766,37 @@
 	 * (has pending rendering), and is not set if it's on inactive (ready
 	 * to be unbound).
 	 */
-	unsigned int active : 1;
+	unsigned int active:1;
 
 	/**
 	 * This is set if the object has been written to since last bound
 	 * to the GTT
 	 */
-	unsigned int dirty : 1;
+	unsigned int dirty:1;
 
 	/**
 	 * This is set if the object has been written to since the last
 	 * GPU flush.
 	 */
-	unsigned int pending_gpu_write : 1;
+	unsigned int pending_gpu_write:1;
 
 	/**
 	 * Fence register bits (if any) for this object.  Will be set
 	 * as needed when mapped into the GTT.
 	 * Protected by dev->struct_mutex.
-	 *
-	 * Size: 4 bits for 16 fences + sign (for FENCE_REG_NONE)
 	 */
-	signed int fence_reg : 5;
+	signed int fence_reg:I915_MAX_NUM_FENCE_BITS;
 
 	/**
 	 * Advice: are the backing pages purgeable?
 	 */
-	unsigned int madv : 2;
+	unsigned int madv:2;
 
 	/**
 	 * Current tiling mode for the object.
 	 */
-	unsigned int tiling_mode : 2;
-	unsigned int tiling_changed : 1;
+	unsigned int tiling_mode:2;
+	unsigned int tiling_changed:1;
 
 	/** How many users have pinned this object in GTT space. The following
 	 * users can each hold at most one reference: pwrite/pread, pin_ioctl
@@ -802,22 +807,22 @@
 	 *
 	 * In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3
 	 * bits with absolutely no headroom. So use 4 bits. */
-	unsigned int pin_count : 4;
+	unsigned int pin_count:4;
 #define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf
 
 	/**
 	 * Is the object at the current location in the gtt mappable and
 	 * fenceable? Used to avoid costly recalculations.
 	 */
-	unsigned int map_and_fenceable : 1;
+	unsigned int map_and_fenceable:1;
 
 	/**
 	 * Whether the current gtt mapping needs to be mappable (and isn't just
 	 * mappable by accident). Track pin and fault separate for a more
 	 * accurate mappable working set.
 	 */
-	unsigned int fault_mappable : 1;
-	unsigned int pin_mappable : 1;
+	unsigned int fault_mappable:1;
+	unsigned int pin_mappable:1;
 
 	/*
 	 * Is the GPU currently using a fence to access this buffer,
@@ -997,12 +1002,12 @@
 extern unsigned int i915_fbpercrtc __always_unused;
 extern int i915_panel_ignore_lid __read_mostly;
 extern unsigned int i915_powersave __read_mostly;
-extern unsigned int i915_semaphores __read_mostly;
+extern int i915_semaphores __read_mostly;
 extern unsigned int i915_lvds_downclock __read_mostly;
-extern unsigned int i915_panel_use_ssc __read_mostly;
+extern int i915_panel_use_ssc __read_mostly;
 extern int i915_vbt_sdvo_panel_type __read_mostly;
-extern unsigned int i915_enable_rc6 __read_mostly;
-extern unsigned int i915_enable_fbc __read_mostly;
+extern int i915_enable_rc6 __read_mostly;
+extern int i915_enable_fbc __read_mostly;
 extern bool i915_enable_hangcheck __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
@@ -1056,7 +1061,7 @@
 void
 i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
 
-void intel_enable_asle (struct drm_device *dev);
+void intel_enable_asle(struct drm_device *dev);
 
 #ifdef CONFIG_DEBUG_FS
 extern void i915_destroy_error_state(struct drm_device *dev);
@@ -1146,7 +1151,7 @@
 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);			  
+			  uint32_t handle);
 /**
  * Returns true if seq1 is later than seq2.
  */
@@ -1301,10 +1306,16 @@
 extern bool intel_fbc_enabled(struct drm_device *dev);
 extern void intel_disable_fbc(struct drm_device *dev);
 extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
+extern void ironlake_init_pch_refclk(struct drm_device *dev);
 extern void ironlake_enable_rc6(struct drm_device *dev);
 extern void gen6_set_rps(struct drm_device *dev, u8 val);
-extern void intel_detect_pch (struct drm_device *dev);
-extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
+extern void intel_detect_pch(struct drm_device *dev);
+extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
+
+extern void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv);
+extern void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv);
+extern void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);
+extern void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv);
 
 /* overlay */
 #ifdef CONFIG_DEBUG_FS
@@ -1350,22 +1361,12 @@
 /* We give fast paths for the really cool registers */
 #define NEEDS_FORCE_WAKE(dev_priv, reg) \
 	(((dev_priv)->info->gen >= 6) && \
-	((reg) < 0x40000) && \
-	((reg) != FORCEWAKE))
+	 ((reg) < 0x40000) &&		 \
+	 ((reg) != FORCEWAKE) &&	 \
+	 ((reg) != ECOBUS))
 
 #define __i915_read(x, y) \
-static inline u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
-	u##x val = 0; \
-	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
-		gen6_gt_force_wake_get(dev_priv); \
-		val = read##y(dev_priv->regs + reg); \
-		gen6_gt_force_wake_put(dev_priv); \
-	} else { \
-		val = read##y(dev_priv->regs + reg); \
-	} \
-	trace_i915_reg_rw(false, reg, val, sizeof(val)); \
-	return val; \
-}
+	u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);
 
 __i915_read(8, b)
 __i915_read(16, w)
@@ -1374,13 +1375,8 @@
 #undef __i915_read
 
 #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(true, reg, val, sizeof(val)); \
-	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
-		__gen6_gt_wait_for_fifo(dev_priv); \
-	} \
-	write##y(val, dev_priv->regs + reg); \
-}
+	void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val);
+
 __i915_write(8, b)
 __i915_write(16, w)
 __i915_write(32, l)
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_gem.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_gem.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_gem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_gem.c	2012-01-04 18:55:44.000000000 -0500
@@ -179,7 +179,7 @@
 	mutex_unlock(&dev->struct_mutex);
 
 	args->aper_size = dev_priv->mm.gtt_total;
-	args->aper_available_size = args->aper_size -pinned;
+	args->aper_available_size = args->aper_size - pinned;
 
 	return 0;
 }
@@ -195,6 +195,8 @@
 	u32 handle;
 
 	size = roundup(size, PAGE_SIZE);
+	if (size == 0)
+		return -EINVAL;
 
 	/* Allocate the new object */
 	obj = i915_gem_alloc_object(dev, size);
@@ -800,11 +802,11 @@
 		if (IS_ERR(page))
 			return PTR_ERR(page);
 
-		vaddr = kmap_atomic(page, KM_USER0);
+		vaddr = kmap_atomic(page);
 		ret = __copy_from_user_inatomic(vaddr + page_offset,
 						user_data,
 						page_length);
-		kunmap_atomic(vaddr, KM_USER0);
+		kunmap_atomic(vaddr);
 
 		set_page_dirty(page);
 		mark_page_accessed(page);
@@ -1265,74 +1267,6 @@
 }
 
 /**
- * i915_gem_create_mmap_offset - create a fake mmap offset for an object
- * @obj: obj in question
- *
- * GEM memory mapping works by handing back to userspace a fake mmap offset
- * it can use in a subsequent mmap(2) call.  The DRM core code then looks
- * up the object based on the offset and sets up the various memory mapping
- * structures.
- *
- * This routine allocates and attaches a fake offset for @obj.
- */
-static int
-i915_gem_create_mmap_offset(struct drm_i915_gem_object *obj)
-{
-	struct drm_device *dev = obj->base.dev;
-	struct drm_gem_mm *mm = dev->mm_private;
-	struct drm_map_list *list;
-	struct drm_local_map *map;
-	int ret = 0;
-
-	/* Set the object up for mmap'ing */
-	list = &obj->base.map_list;
-	list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
-	if (!list->map)
-		return -ENOMEM;
-
-	map = list->map;
-	map->type = _DRM_GEM;
-	map->size = obj->base.size;
-	map->handle = obj;
-
-	/* Get a DRM GEM mmap offset allocated... */
-	list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
-						    obj->base.size / PAGE_SIZE,
-						    0, 0);
-	if (!list->file_offset_node) {
-		DRM_ERROR("failed to allocate offset for bo %d\n",
-			  obj->base.name);
-		ret = -ENOSPC;
-		goto out_free_list;
-	}
-
-	list->file_offset_node = drm_mm_get_block(list->file_offset_node,
-						  obj->base.size / PAGE_SIZE,
-						  0);
-	if (!list->file_offset_node) {
-		ret = -ENOMEM;
-		goto out_free_list;
-	}
-
-	list->hash.key = list->file_offset_node->start;
-	ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
-	if (ret) {
-		DRM_ERROR("failed to add to map hash\n");
-		goto out_free_mm;
-	}
-
-	return 0;
-
-out_free_mm:
-	drm_mm_put_block(list->file_offset_node);
-out_free_list:
-	kfree(list->map);
-	list->map = NULL;
-
-	return ret;
-}
-
-/**
  * i915_gem_release_mmap - remove physical page mappings
  * @obj: obj in question
  *
@@ -1360,19 +1294,6 @@
 	obj->fault_mappable = false;
 }
 
-static void
-i915_gem_free_mmap_offset(struct drm_i915_gem_object *obj)
-{
-	struct drm_device *dev = obj->base.dev;
-	struct drm_gem_mm *mm = dev->mm_private;
-	struct drm_map_list *list = &obj->base.map_list;
-
-	drm_ht_remove_item(&mm->offset_hash, &list->hash);
-	drm_mm_put_block(list->file_offset_node);
-	kfree(list->map);
-	list->map = NULL;
-}
-
 static uint32_t
 i915_gem_get_gtt_size(struct drm_device *dev, uint32_t size, int tiling_mode)
 {
@@ -1475,7 +1396,7 @@
 
 	if (obj->base.size > dev_priv->mm.gtt_mappable_end) {
 		ret = -E2BIG;
-		goto unlock;
+		goto out;
 	}
 
 	if (obj->madv != I915_MADV_WILLNEED) {
@@ -1485,7 +1406,7 @@
 	}
 
 	if (!obj->base.map_list.map) {
-		ret = i915_gem_create_mmap_offset(obj);
+		ret = drm_gem_create_mmap_offset(&obj->base);
 		if (ret)
 			goto out;
 	}
@@ -1557,7 +1478,7 @@
 		obj->pages[i] = page;
 	}
 
-	if (obj->tiling_mode != I915_TILING_NONE)
+	if (i915_gem_object_needs_bit17_swizzle(obj))
 		i915_gem_object_do_bit_17_swizzle(obj);
 
 	return 0;
@@ -1579,7 +1500,7 @@
 
 	BUG_ON(obj->madv == __I915_MADV_PURGED);
 
-	if (obj->tiling_mode != I915_TILING_NONE)
+	if (i915_gem_object_needs_bit17_swizzle(obj))
 		i915_gem_object_save_bit_17_swizzle(obj);
 
 	if (obj->madv == I915_MADV_DONTNEED)
@@ -1824,7 +1745,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int i;
 
-	for (i = 0; i < 16; i++) {
+	for (i = 0; i < dev_priv->num_fence_regs; i++) {
 		struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
 		struct drm_i915_gem_object *obj = reg->obj;
 
@@ -1856,7 +1777,7 @@
 	 * lost bo to the inactive list.
 	 */
 	while (!list_empty(&dev_priv->mm.flushing_list)) {
-		obj= list_first_entry(&dev_priv->mm.flushing_list,
+		obj = list_first_entry(&dev_priv->mm.flushing_list,
 				      struct drm_i915_gem_object,
 				      mm_list);
 
@@ -1922,7 +1843,7 @@
 	while (!list_empty(&ring->active_list)) {
 		struct drm_i915_gem_object *obj;
 
-		obj= list_first_entry(&ring->active_list,
+		obj = list_first_entry(&ring->active_list,
 				      struct drm_i915_gem_object,
 				      ring_list);
 
@@ -2272,14 +2193,8 @@
 i915_gpu_idle(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	bool lists_empty;
 	int ret, i;
 
-	lists_empty = (list_empty(&dev_priv->mm.flushing_list) &&
-		       list_empty(&dev_priv->mm.active_list));
-	if (lists_empty)
-		return 0;
-
 	/* Flush everything onto the inactive list. */
 	for (i = 0; i < I915_NUM_RINGS; i++) {
 		ret = i915_ring_idle(&dev_priv->ring[i]);
@@ -2882,7 +2797,7 @@
 
 	fenceable =
 		obj->gtt_space->size == fence_size &&
-		(obj->gtt_space->start & (fence_alignment -1)) == 0;
+		(obj->gtt_space->start & (fence_alignment - 1)) == 0;
 
 	mappable =
 		obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end;
@@ -3597,9 +3512,11 @@
 			 * so emit a request to do so.
 			 */
 			request = kzalloc(sizeof(*request), GFP_KERNEL);
-			if (request)
-				ret = i915_add_request(obj->ring, NULL,request);
-			else
+			if (request) {
+				ret = i915_add_request(obj->ring, NULL, request);
+				if (ret)
+					kfree(request);
+			} else
 				ret = -ENOMEM;
 		}
 
@@ -3623,7 +3540,7 @@
 i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv)
 {
-    return i915_gem_ring_throttle(dev, file_priv);
+	return i915_gem_ring_throttle(dev, file_priv);
 }
 
 int
@@ -3698,7 +3615,7 @@
 	obj->base.write_domain = I915_GEM_DOMAIN_CPU;
 	obj->base.read_domains = I915_GEM_DOMAIN_CPU;
 
-	if (IS_GEN6(dev)) {
+	if (IS_GEN6(dev) || IS_GEN7(dev)) {
 		/* On Gen6, we can have the GPU use the LLC (the CPU
 		 * cache) for about a 10% performance improvement
 		 * compared to uncached.  Graphics requests other than
@@ -3752,7 +3669,7 @@
 	trace_i915_gem_object_destroy(obj);
 
 	if (obj->base.map_list.map)
-		i915_gem_free_mmap_offset(obj);
+		drm_gem_free_mmap_offset(&obj->base);
 
 	drm_gem_object_release(&obj->base);
 	i915_gem_info_remove_obj(dev_priv, obj->base.size);
@@ -3962,7 +3879,7 @@
 	INIT_LIST_HEAD(&dev_priv->mm.gtt_list);
 	for (i = 0; i < I915_NUM_RINGS; i++)
 		init_ring_lists(&dev_priv->ring[i]);
-	for (i = 0; i < 16; i++)
+	for (i = 0; i < I915_MAX_NUM_FENCES; i++)
 		INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
 	INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
 			  i915_gem_retire_work_handler);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_gem_debug.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_gem_debug.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_gem_debug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_gem_debug.c	2012-01-04 18:55:44.000000000 -0500
@@ -72,7 +72,7 @@
 			break;
 		} else if (!obj->active ||
 			   (obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0 ||
-			   list_empty(&obj->gpu_write_list)){
+			   list_empty(&obj->gpu_write_list)) {
 			DRM_ERROR("invalid flushing %p (a %d w %x gwl %d)\n",
 				  obj,
 				  obj->active,
@@ -157,7 +157,7 @@
 	for (page = 0; page < obj->size / PAGE_SIZE; page++) {
 		int i;
 
-		backing_map = kmap_atomic(obj->pages[page], KM_USER0);
+		backing_map = kmap_atomic(obj->pages[page]);
 
 		if (backing_map == NULL) {
 			DRM_ERROR("failed to map backing page\n");
@@ -181,13 +181,13 @@
 				}
 			}
 		}
-		kunmap_atomic(backing_map, KM_USER0);
+		kunmap_atomic(backing_map);
 		backing_map = NULL;
 	}
 
  out:
 	if (backing_map != NULL)
-		kunmap_atomic(backing_map, KM_USER0);
+		kunmap_atomic(backing_map);
 	iounmap(gtt_mapping);
 
 	/* give syslog time to catch up */
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_gem_evict.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_gem_evict.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_gem_evict.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_gem_evict.c	2012-01-04 18:55:44.000000000 -0500
@@ -122,7 +122,7 @@
 			goto found;
 	}
 	list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
-		if (! obj->base.write_domain || obj->pin_count)
+		if (!obj->base.write_domain || obj->pin_count)
 			continue;
 
 		if (mark_free(obj, &unwind_list))
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 #include "i915_drv.h"
 #include "i915_trace.h"
 #include "intel_drv.h"
+#include <linux/dma_remapping.h>
 
 struct change_domains {
 	uint32_t invalidate_domains;
@@ -746,6 +747,22 @@
 	return 0;
 }
 
+static bool
+intel_enable_semaphores(struct drm_device *dev)
+{
+	if (INTEL_INFO(dev)->gen < 6)
+		return 0;
+
+	if (i915_semaphores >= 0)
+		return i915_semaphores;
+
+	/* Disable semaphores on SNB */
+	if (INTEL_INFO(dev)->gen == 6)
+		return 0;
+
+	return 1;
+}
+
 static int
 i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj,
 			       struct intel_ring_buffer *to)
@@ -758,7 +775,7 @@
 		return 0;
 
 	/* XXX gpu semaphores are implicated in various hard hangs on SNB */
-	if (INTEL_INFO(obj->base.dev)->gen < 6 || !i915_semaphores)
+	if (!intel_enable_semaphores(obj->base.dev))
 		return i915_gem_object_wait_rendering(obj);
 
 	idx = intel_ring_sync_index(from, to);
@@ -784,7 +801,8 @@
 	}
 
 	from->sync_seqno[idx] = seqno;
-	return intel_ring_sync(to, from, seqno - 1);
+
+	return to->sync_to(to, from, seqno - 1);
 }
 
 static int
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_gem_gtt.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_gem_gtt.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_gem_gtt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_gem_gtt.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,6 +49,28 @@
 	}
 }
 
+static bool do_idling(struct drm_i915_private *dev_priv)
+{
+	bool ret = dev_priv->mm.interruptible;
+
+	if (unlikely(dev_priv->mm.gtt->do_idle_maps)) {
+		dev_priv->mm.interruptible = false;
+		if (i915_gpu_idle(dev_priv->dev)) {
+			DRM_ERROR("Couldn't idle GPU\n");
+			/* Wait a bit, in hopes it avoids the hang */
+			udelay(10);
+		}
+	}
+
+	return ret;
+}
+
+static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible)
+{
+	if (unlikely(dev_priv->mm.gtt->do_idle_maps))
+		dev_priv->mm.interruptible = interruptible;
+}
+
 void i915_gem_restore_gtt_mappings(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -117,6 +139,12 @@
 
 void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
 {
+	struct drm_device *dev = obj->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	bool interruptible;
+
+	interruptible = do_idling(dev_priv);
+
 	intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT,
 			      obj->base.size >> PAGE_SHIFT);
 
@@ -124,4 +152,6 @@
 		intel_gtt_unmap_memory(obj->sg_list, obj->num_sg);
 		obj->sg_list = NULL;
 	}
+
+	undo_idling(dev_priv, interruptible);
 }
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c	2012-01-04 18:55:44.000000000 -0500
@@ -92,7 +92,10 @@
 	uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
 	uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
 
-	if (INTEL_INFO(dev)->gen >= 5) {
+	if (INTEL_INFO(dev)->gen >= 6) {
+		swizzle_x = I915_BIT_6_SWIZZLE_NONE;
+		swizzle_y = I915_BIT_6_SWIZZLE_NONE;
+	} else if (IS_GEN5(dev)) {
 		/* On Ironlake whatever DRAM config, GPU always do
 		 * same swizzling setup.
 		 */
@@ -440,14 +443,9 @@
 void
 i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->base.dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	int page_count = obj->base.size >> PAGE_SHIFT;
 	int i;
 
-	if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
-		return;
-
 	if (obj->bit_17 == NULL)
 		return;
 
@@ -464,14 +462,9 @@
 void
 i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->base.dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	int page_count = obj->base.size >> PAGE_SHIFT;
 	int i;
 
-	if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
-		return;
-
 	if (obj->bit_17 == NULL) {
 		obj->bit_17 = kmalloc(BITS_TO_LONGS(page_count) *
 					   sizeof(long), GFP_KERNEL);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_irq.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_irq.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -383,6 +383,7 @@
 	pm_iir = dev_priv->pm_iir;
 	dev_priv->pm_iir = 0;
 	pm_imr = I915_READ(GEN6_PMIMR);
+	I915_WRITE(GEN6_PMIMR, 0);
 	spin_unlock_irq(&dev_priv->rps_lock);
 
 	if (!pm_iir)
@@ -420,7 +421,6 @@
 	 * an *extremely* unlikely race with gen6_rps_enable() that is prevented
 	 * by holding struct_mutex for the duration of the write.
 	 */
-	I915_WRITE(GEN6_PMIMR, pm_imr & ~pm_iir);
 	mutex_unlock(&dev_priv->dev->struct_mutex);
 }
 
@@ -536,8 +536,9 @@
 		unsigned long flags;
 		spin_lock_irqsave(&dev_priv->rps_lock, flags);
 		WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
-		I915_WRITE(GEN6_PMIMR, pm_iir);
 		dev_priv->pm_iir |= pm_iir;
+		I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
+		POSTING_READ(GEN6_PMIMR);
 		spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
 		queue_work(dev_priv->wq, &dev_priv->rps_work);
 	}
@@ -649,8 +650,9 @@
 		unsigned long flags;
 		spin_lock_irqsave(&dev_priv->rps_lock, flags);
 		WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
-		I915_WRITE(GEN6_PMIMR, pm_iir);
 		dev_priv->pm_iir |= pm_iir;
+		I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
+		POSTING_READ(GEN6_PMIMR);
 		spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
 		queue_work(dev_priv->wq, &dev_priv->rps_work);
 	}
@@ -711,7 +713,7 @@
 
 	page_count = src->base.size / PAGE_SIZE;
 
-	dst = kmalloc(sizeof(*dst) + page_count * sizeof (u32 *), GFP_ATOMIC);
+	dst = kmalloc(sizeof(*dst) + page_count * sizeof(u32 *), GFP_ATOMIC);
 	if (dst == NULL)
 		return NULL;
 
@@ -822,6 +824,7 @@
 
 	/* Fences */
 	switch (INTEL_INFO(dev)->gen) {
+	case 7:
 	case 6:
 		for (i = 0; i < 16; i++)
 			error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
@@ -1493,7 +1496,7 @@
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	ironlake_enable_display_irq(dev_priv, (pipe == 0) ?
-				    DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
+				    DE_PIPEA_VBLANK : DE_PIPEB_VBLANK);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
 	return 0;
@@ -1541,7 +1544,7 @@
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	ironlake_disable_display_irq(dev_priv, (pipe == 0) ?
-				     DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
+				     DE_PIPEA_VBLANK : DE_PIPEB_VBLANK);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
@@ -1777,6 +1780,26 @@
 	POSTING_READ(SDEIER);
 }
 
+/*
+ * Enable digital hotplug on the PCH, and configure the DP short pulse
+ * duration to 2ms (which is the minimum in the Display Port spec)
+ *
+ * This register is the same on all known PCH chips.
+ */
+
+static void ironlake_enable_pch_hotplug(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u32	hotplug;
+
+	hotplug = I915_READ(PCH_PORT_HOTPLUG);
+	hotplug &= ~(PORTD_PULSE_DURATION_MASK|PORTC_PULSE_DURATION_MASK|PORTB_PULSE_DURATION_MASK);
+	hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms;
+	hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms;
+	hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms;
+	I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
+}
+
 static int ironlake_irq_postinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1839,6 +1862,8 @@
 	I915_WRITE(SDEIER, hotplug_mask);
 	POSTING_READ(SDEIER);
 
+	ironlake_enable_pch_hotplug(dev);
+
 	if (IS_IRONLAKE_M(dev)) {
 		/* Clear & enable PCU event interrupts */
 		I915_WRITE(DEIIR, DE_PCU_EVENT);
@@ -1896,6 +1921,8 @@
 	I915_WRITE(SDEIER, hotplug_mask);
 	POSTING_READ(SDEIER);
 
+	ironlake_enable_pch_hotplug(dev);
+
 	return 0;
 }
 
@@ -2020,6 +2047,10 @@
 	I915_WRITE(GTIMR, 0xffffffff);
 	I915_WRITE(GTIER, 0x0);
 	I915_WRITE(GTIIR, I915_READ(GTIIR));
+
+	I915_WRITE(SDEIMR, 0xffffffff);
+	I915_WRITE(SDEIER, 0x0);
+	I915_WRITE(SDEIIR, I915_READ(SDEIIR));
 }
 
 static void i915_driver_irq_uninstall(struct drm_device * dev)
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_mem.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_mem.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_mem.c	2012-01-04 18:55:44.000000000 -0500
@@ -202,7 +202,7 @@
 	blocks->next = blocks->prev = *heap;
 
 	memset(*heap, 0, sizeof(**heap));
-	(*heap)->file_priv = (struct drm_file *) - 1;
+	(*heap)->file_priv = (struct drm_file *) -1;
 	(*heap)->next = (*heap)->prev = blocks;
 	return 0;
 }
@@ -359,19 +359,19 @@
 	return init_heap(heap, initheap->start, initheap->size);
 }
 
-int i915_mem_destroy_heap( struct drm_device *dev, void *data,
-			   struct drm_file *file_priv )
+int i915_mem_destroy_heap(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_mem_destroy_heap_t *destroyheap = data;
 	struct mem_block **heap;
 
-	if ( !dev_priv ) {
-		DRM_ERROR( "called with no initialization\n" );
+	if (!dev_priv) {
+		DRM_ERROR("called with no initialization\n");
 		return -EINVAL;
 	}
 
-	heap = get_heap( dev_priv, destroyheap->region );
+	heap = get_heap(dev_priv, destroyheap->region);
 	if (!heap) {
 		DRM_ERROR("get_heap failed");
 		return -EFAULT;
@@ -382,6 +382,6 @@
 		return -EFAULT;
 	}
 
-	i915_mem_takedown( heap );
+	i915_mem_takedown(heap);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_reg.h linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_reg.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_reg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -156,7 +156,7 @@
 #define MI_SUSPEND_FLUSH	MI_INSTR(0x0b, 0)
 #define   MI_SUSPEND_FLUSH_EN	(1<<0)
 #define MI_REPORT_HEAD		MI_INSTR(0x07, 0)
-#define MI_OVERLAY_FLIP		MI_INSTR(0x11,0)
+#define MI_OVERLAY_FLIP		MI_INSTR(0x11, 0)
 #define   MI_OVERLAY_CONTINUE	(0x0<<21)
 #define   MI_OVERLAY_ON		(0x1<<21)
 #define   MI_OVERLAY_OFF	(0x2<<21)
@@ -194,6 +194,13 @@
 #define  MI_SEMAPHORE_UPDATE	    (1<<21)
 #define  MI_SEMAPHORE_COMPARE	    (1<<20)
 #define  MI_SEMAPHORE_REGISTER	    (1<<18)
+#define  MI_SEMAPHORE_SYNC_RV	    (2<<16)
+#define  MI_SEMAPHORE_SYNC_RB	    (0<<16)
+#define  MI_SEMAPHORE_SYNC_VR	    (0<<16)
+#define  MI_SEMAPHORE_SYNC_VB	    (2<<16)
+#define  MI_SEMAPHORE_SYNC_BR	    (2<<16)
+#define  MI_SEMAPHORE_SYNC_BV	    (0<<16)
+#define  MI_SEMAPHORE_SYNC_INVALID  (1<<0)
 /*
  * 3D instructions used by the kernel
  */
@@ -235,16 +242,22 @@
 #define   ASYNC_FLIP                (1<<22)
 #define   DISPLAY_PLANE_A           (0<<20)
 #define   DISPLAY_PLANE_B           (1<<20)
-#define GFX_OP_PIPE_CONTROL	((0x3<<29)|(0x3<<27)|(0x2<<24)|2)
-#define   PIPE_CONTROL_QW_WRITE	(1<<14)
-#define   PIPE_CONTROL_DEPTH_STALL (1<<13)
-#define   PIPE_CONTROL_WC_FLUSH	(1<<12)
-#define   PIPE_CONTROL_IS_FLUSH	(1<<11) /* MBZ on Ironlake */
-#define   PIPE_CONTROL_TC_FLUSH (1<<10) /* GM45+ only */
-#define   PIPE_CONTROL_ISP_DIS	(1<<9)
-#define   PIPE_CONTROL_NOTIFY	(1<<8)
+#define GFX_OP_PIPE_CONTROL(len)	((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2))
+#define   PIPE_CONTROL_CS_STALL				(1<<20)
+#define   PIPE_CONTROL_QW_WRITE				(1<<14)
+#define   PIPE_CONTROL_DEPTH_STALL			(1<<13)
+#define   PIPE_CONTROL_WRITE_FLUSH			(1<<12)
+#define   PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH	(1<<12) /* gen6+ */
+#define   PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE	(1<<11) /* MBZ on Ironlake */
+#define   PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE		(1<<10) /* GM45+ only */
+#define   PIPE_CONTROL_INDIRECT_STATE_DISABLE		(1<<9)
+#define   PIPE_CONTROL_NOTIFY				(1<<8)
+#define   PIPE_CONTROL_VF_CACHE_INVALIDATE		(1<<4)
+#define   PIPE_CONTROL_CONST_CACHE_INVALIDATE		(1<<3)
+#define   PIPE_CONTROL_STATE_CACHE_INVALIDATE		(1<<2)
+#define   PIPE_CONTROL_STALL_AT_SCOREBOARD		(1<<1)
+#define   PIPE_CONTROL_DEPTH_CACHE_FLUSH		(1<<0)
 #define   PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
-#define   PIPE_CONTROL_STALL_EN	(1<<1) /* in addr word, Ironlake+ only */
 
 
 /*
@@ -296,6 +309,12 @@
 #define RING_CTL(base)		((base)+0x3c)
 #define RING_SYNC_0(base)	((base)+0x40)
 #define RING_SYNC_1(base)	((base)+0x44)
+#define GEN6_RVSYNC (RING_SYNC_0(RENDER_RING_BASE))
+#define GEN6_RBSYNC (RING_SYNC_1(RENDER_RING_BASE))
+#define GEN6_VRSYNC (RING_SYNC_1(GEN6_BSD_RING_BASE))
+#define GEN6_VBSYNC (RING_SYNC_0(GEN6_BSD_RING_BASE))
+#define GEN6_BRSYNC (RING_SYNC_0(BLT_RING_BASE))
+#define GEN6_BVSYNC (RING_SYNC_1(BLT_RING_BASE))
 #define RING_MAX_IDLE(base)	((base)+0x54)
 #define RING_HWS_PGA(base)	((base)+0x80)
 #define RING_HWS_PGA_GEN6(base)	((base)+0x2080)
@@ -470,7 +489,7 @@
 
 /* Enables non-sequential data reads through arbiter
  */
-#define   MI_ARB_DUAL_DATA_PHASE_DISABLE       	(1 << 9)
+#define   MI_ARB_DUAL_DATA_PHASE_DISABLE	(1 << 9)
 
 /* Disable FSB snooping of cacheable write cycles from binner/render
  * command stream
@@ -626,7 +645,7 @@
 
 #define ILK_DISPLAY_CHICKEN1	0x42000
 #define   ILK_FBCQ_DIS		(1<<22)
-#define   ILK_PABSTRETCH_DIS 	(1<<21)
+#define	  ILK_PABSTRETCH_DIS	(1<<21)
 
 
 /*
@@ -1534,12 +1553,21 @@
  */
 #define   PP_READY		(1 << 30)
 #define   PP_SEQUENCE_NONE	(0 << 28)
-#define   PP_SEQUENCE_ON	(1 << 28)
-#define   PP_SEQUENCE_OFF	(2 << 28)
-#define   PP_SEQUENCE_MASK	0x30000000
+#define   PP_SEQUENCE_POWER_UP	(1 << 28)
+#define   PP_SEQUENCE_POWER_DOWN (2 << 28)
+#define   PP_SEQUENCE_MASK	(3 << 28)
+#define   PP_SEQUENCE_SHIFT	28
 #define   PP_CYCLE_DELAY_ACTIVE	(1 << 27)
-#define   PP_SEQUENCE_STATE_ON_IDLE (1 << 3)
 #define   PP_SEQUENCE_STATE_MASK 0x0000000f
+#define   PP_SEQUENCE_STATE_OFF_IDLE	(0x0 << 0)
+#define   PP_SEQUENCE_STATE_OFF_S0_1	(0x1 << 0)
+#define   PP_SEQUENCE_STATE_OFF_S0_2	(0x2 << 0)
+#define   PP_SEQUENCE_STATE_OFF_S0_3	(0x3 << 0)
+#define   PP_SEQUENCE_STATE_ON_IDLE	(0x8 << 0)
+#define   PP_SEQUENCE_STATE_ON_S1_0	(0x9 << 0)
+#define   PP_SEQUENCE_STATE_ON_S1_2	(0xa << 0)
+#define   PP_SEQUENCE_STATE_ON_S1_3	(0xb << 0)
+#define   PP_SEQUENCE_STATE_RESET	(0xf << 0)
 #define PP_CONTROL	0x61204
 #define   POWER_TARGET_ON	(1 << 0)
 #define PP_ON_DELAYS	0x61208
@@ -2358,7 +2386,7 @@
 
 #define DSPFW1			0x70034
 #define   DSPFW_SR_SHIFT	23
-#define   DSPFW_SR_MASK 	(0x1ff<<23)
+#define   DSPFW_SR_MASK		(0x1ff<<23)
 #define   DSPFW_CURSORB_SHIFT	16
 #define   DSPFW_CURSORB_MASK	(0x3f<<16)
 #define   DSPFW_PLANEB_SHIFT	8
@@ -2416,6 +2444,7 @@
 #define  WM0_PIPE_CURSOR_MASK	(0x1f)
 
 #define WM0_PIPEB_ILK		0x45104
+#define WM0_PIPEC_IVB		0x45200
 #define WM1_LP_ILK		0x45108
 #define  WM1_LP_SR_EN		(1<<31)
 #define  WM1_LP_LATENCY_SHIFT	24
@@ -2554,10 +2583,18 @@
 #define _CURBBASE		0x700c4
 #define _CURBPOS			0x700c8
 
+#define _CURBCNTR_IVB		0x71080
+#define _CURBBASE_IVB		0x71084
+#define _CURBPOS_IVB		0x71088
+
 #define CURCNTR(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR)
 #define CURBASE(pipe) _PIPE(pipe, _CURABASE, _CURBBASE)
 #define CURPOS(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS)
 
+#define CURCNTR_IVB(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR_IVB)
+#define CURBASE_IVB(pipe) _PIPE(pipe, _CURABASE, _CURBBASE_IVB)
+#define CURPOS_IVB(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS_IVB)
+
 /* Display A control */
 #define _DSPACNTR                0x70180
 #define   DISPLAY_PLANE_ENABLE			(1<<31)
@@ -2903,12 +2940,13 @@
 #define SDEIER  0xc400c
 
 /* digital port hotplug */
-#define PCH_PORT_HOTPLUG        0xc4030
+#define PCH_PORT_HOTPLUG        0xc4030		/* SHOTPLUG_CTL */
 #define PORTD_HOTPLUG_ENABLE            (1 << 20)
 #define PORTD_PULSE_DURATION_2ms        (0)
 #define PORTD_PULSE_DURATION_4_5ms      (1 << 18)
 #define PORTD_PULSE_DURATION_6ms        (2 << 18)
 #define PORTD_PULSE_DURATION_100ms      (3 << 18)
+#define PORTD_PULSE_DURATION_MASK	(3 << 18)
 #define PORTD_HOTPLUG_NO_DETECT         (0)
 #define PORTD_HOTPLUG_SHORT_DETECT      (1 << 16)
 #define PORTD_HOTPLUG_LONG_DETECT       (1 << 17)
@@ -2917,6 +2955,7 @@
 #define PORTC_PULSE_DURATION_4_5ms      (1 << 10)
 #define PORTC_PULSE_DURATION_6ms        (2 << 10)
 #define PORTC_PULSE_DURATION_100ms      (3 << 10)
+#define PORTC_PULSE_DURATION_MASK	(3 << 10)
 #define PORTC_HOTPLUG_NO_DETECT         (0)
 #define PORTC_HOTPLUG_SHORT_DETECT      (1 << 8)
 #define PORTC_HOTPLUG_LONG_DETECT       (1 << 9)
@@ -2925,6 +2964,7 @@
 #define PORTB_PULSE_DURATION_4_5ms      (1 << 2)
 #define PORTB_PULSE_DURATION_6ms        (2 << 2)
 #define PORTB_PULSE_DURATION_100ms      (3 << 2)
+#define PORTB_PULSE_DURATION_MASK	(3 << 2)
 #define PORTB_HOTPLUG_NO_DETECT         (0)
 #define PORTB_HOTPLUG_SHORT_DETECT      (1 << 0)
 #define PORTB_HOTPLUG_LONG_DETECT       (1 << 1)
@@ -2945,15 +2985,15 @@
 
 #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(pipe) (pipe == 0 ?  _PCH_DPLL_A : _PCH_DPLL_B)
 
 #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_FP0(pipe) (pipe == 0 ? _PCH_FPA0 : _PCH_FPB0)
+#define PCH_FP1(pipe) (pipe == 0 ? _PCH_FPA1 : _PCH_FPB1)
 
 #define PCH_DPLL_TEST           0xc606c
 
@@ -3167,6 +3207,7 @@
 #define  FDI_LINK_TRAIN_NONE_IVB            (3<<8)
 
 /* both Tx and Rx */
+#define  FDI_COMPOSITE_SYNC		(1<<11)
 #define  FDI_LINK_TRAIN_AUTO		(1<<10)
 #define  FDI_SCRAMBLING_ENABLE          (0<<7)
 #define  FDI_SCRAMBLING_DISABLE         (1<<7)
@@ -3262,10 +3303,10 @@
 /* or SDVOB */
 #define HDMIB   0xe1140
 #define  PORT_ENABLE    (1 << 31)
-#define  TRANSCODER_A   (0)
-#define  TRANSCODER_B   (1 << 30)
-#define  TRANSCODER(pipe)	((pipe) << 30)
-#define  TRANSCODER_MASK   (1 << 30)
+#define  TRANSCODER(pipe)       ((pipe) << 30)
+#define  TRANSCODER_CPT(pipe)   ((pipe) << 29)
+#define  TRANSCODER_MASK        (1 << 30)
+#define  TRANSCODER_MASK_CPT    (3 << 29)
 #define  COLOR_FORMAT_8bpc      (0)
 #define  COLOR_FORMAT_12bpc     (3 << 26)
 #define  SDVOB_HOTPLUG_ENABLE   (1 << 23)
@@ -3308,15 +3349,35 @@
 #define PCH_PP_STATUS		0xc7200
 #define PCH_PP_CONTROL		0xc7204
 #define  PANEL_UNLOCK_REGS	(0xabcd << 16)
+#define  PANEL_UNLOCK_MASK	(0xffff << 16)
 #define  EDP_FORCE_VDD		(1 << 3)
 #define  EDP_BLC_ENABLE		(1 << 2)
 #define  PANEL_POWER_RESET	(1 << 1)
 #define  PANEL_POWER_OFF	(0 << 0)
 #define  PANEL_POWER_ON		(1 << 0)
 #define PCH_PP_ON_DELAYS	0xc7208
+#define  PANEL_PORT_SELECT_MASK	(3 << 30)
+#define  PANEL_PORT_SELECT_LVDS	(0 << 30)
+#define  PANEL_PORT_SELECT_DPA	(1 << 30)
 #define  EDP_PANEL		(1 << 30)
+#define  PANEL_PORT_SELECT_DPC	(2 << 30)
+#define  PANEL_PORT_SELECT_DPD	(3 << 30)
+#define  PANEL_POWER_UP_DELAY_MASK	(0x1fff0000)
+#define  PANEL_POWER_UP_DELAY_SHIFT	16
+#define  PANEL_LIGHT_ON_DELAY_MASK	(0x1fff)
+#define  PANEL_LIGHT_ON_DELAY_SHIFT	0
+
 #define PCH_PP_OFF_DELAYS	0xc720c
+#define  PANEL_POWER_DOWN_DELAY_MASK	(0x1fff0000)
+#define  PANEL_POWER_DOWN_DELAY_SHIFT	16
+#define  PANEL_LIGHT_OFF_DELAY_MASK	(0x1fff)
+#define  PANEL_LIGHT_OFF_DELAY_SHIFT	0
+
 #define PCH_PP_DIVISOR		0xc7210
+#define  PP_REFERENCE_DIVIDER_MASK	(0xffffff00)
+#define  PP_REFERENCE_DIVIDER_SHIFT	8
+#define  PANEL_POWER_CYCLE_DELAY_MASK	(0x1f)
+#define  PANEL_POWER_CYCLE_DELAY_SHIFT	0
 
 #define PCH_DP_B		0xe4100
 #define PCH_DPB_AUX_CH_CTL	0xe4110
@@ -3386,12 +3447,38 @@
 #define  EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B	(0x38<<22)
 #define  EDP_LINK_TRAIN_VOL_EMP_MASK_SNB	(0x3f<<22)
 
+/* IVB */
+#define EDP_LINK_TRAIN_400MV_0DB_IVB		(0x24 <<22)
+#define EDP_LINK_TRAIN_400MV_3_5DB_IVB		(0x2a <<22)
+#define EDP_LINK_TRAIN_400MV_6DB_IVB		(0x2f <<22)
+#define EDP_LINK_TRAIN_600MV_0DB_IVB		(0x30 <<22)
+#define EDP_LINK_TRAIN_600MV_3_5DB_IVB		(0x36 <<22)
+#define EDP_LINK_TRAIN_800MV_0DB_IVB		(0x38 <<22)
+#define EDP_LINK_TRAIN_800MV_3_5DB_IVB		(0x33 <<22)
+
+/* legacy values */
+#define EDP_LINK_TRAIN_500MV_0DB_IVB		(0x00 <<22)
+#define EDP_LINK_TRAIN_1000MV_0DB_IVB		(0x20 <<22)
+#define EDP_LINK_TRAIN_500MV_3_5DB_IVB		(0x02 <<22)
+#define EDP_LINK_TRAIN_1000MV_3_5DB_IVB		(0x22 <<22)
+#define EDP_LINK_TRAIN_1000MV_6DB_IVB		(0x23 <<22)
+
+#define  EDP_LINK_TRAIN_VOL_EMP_MASK_IVB	(0x3f<<22)
+
 #define  FORCEWAKE				0xA18C
 #define  FORCEWAKE_ACK				0x130090
+#define  FORCEWAKE_MT				0xa188 /* multi-threaded */
+#define  FORCEWAKE_MT_ACK			0x130040
+#define  ECOBUS					0xa180
+#define    FORCEWAKE_MT_ENABLE			(1<<5)
 
 #define  GT_FIFO_FREE_ENTRIES			0x120008
 #define    GT_FIFO_NUM_RESERVED_ENTRIES		20
 
+#define GEN6_UCGCTL2				0x9404
+# define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE		(1 << 12)
+# define GEN6_RCCUNIT_CLOCK_GATE_DISABLE		(1 << 11)
+
 #define GEN6_RPNSWREQ				0xA008
 #define   GEN6_TURBO_DISABLE			(1<<31)
 #define   GEN6_FREQUENCY(x)			((x)<<25)
@@ -3470,4 +3557,29 @@
 #define GEN6_PCODE_DATA				0x138128
 #define   GEN6_PCODE_FREQ_IA_RATIO_SHIFT	8
 
+#define G4X_AUD_VID_DID			0x62020
+#define INTEL_AUDIO_DEVCL		0x808629FB
+#define INTEL_AUDIO_DEVBLC		0x80862801
+#define INTEL_AUDIO_DEVCTG		0x80862802
+
+#define G4X_AUD_CNTL_ST			0x620B4
+#define G4X_ELDV_DEVCL_DEVBLC		(1 << 13)
+#define G4X_ELDV_DEVCTG			(1 << 14)
+#define G4X_ELD_ADDR			(0xf << 5)
+#define G4X_ELD_ACK			(1 << 4)
+#define G4X_HDMIW_HDMIEDID		0x6210C
+
+#define GEN5_HDMIW_HDMIEDID_A		0xE2050
+#define GEN5_AUD_CNTL_ST_A		0xE20B4
+#define GEN5_ELD_BUFFER_SIZE		(0x1f << 10)
+#define GEN5_ELD_ADDRESS		(0x1f << 5)
+#define GEN5_ELD_ACK			(1 << 4)
+#define GEN5_AUD_CNTL_ST2		0xE20C0
+#define GEN5_ELD_VALIDB			(1 << 0)
+#define GEN5_CP_READYB			(1 << 1)
+
+#define GEN7_HDMIW_HDMIEDID_A		0xE5050
+#define GEN7_AUD_CNTRL_ST_A		0xE50B4
+#define GEN7_AUD_CNTRL_ST2		0xE50C0
+
 #endif /* _I915_REG_H_ */
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_suspend.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_suspend.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_suspend.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_suspend.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,7 +60,7 @@
 	else
 		array = dev_priv->save_palette_b;
 
-	for(i = 0; i < 256; i++)
+	for (i = 0; i < 256; i++)
 		array[i] = I915_READ(reg + (i << 2));
 }
 
@@ -82,7 +82,7 @@
 	else
 		array = dev_priv->save_palette_b;
 
-	for(i = 0; i < 256; i++)
+	for (i = 0; i < 256; i++)
 		I915_WRITE(reg + (i << 2), array[i]);
 }
 
@@ -370,6 +370,7 @@
 
 	/* Fences */
 	switch (INTEL_INFO(dev)->gen) {
+	case 7:
 	case 6:
 		for (i = 0; i < 16; i++)
 			dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
@@ -404,6 +405,7 @@
 
 	/* Fences */
 	switch (INTEL_INFO(dev)->gen) {
+	case 7:
 	case 6:
 		for (i = 0; i < 16; i++)
 			I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]);
@@ -887,10 +889,10 @@
 	mutex_lock(&dev->struct_mutex);
 
 	/* Cache mode state */
-	I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
+	I915_WRITE(CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
 
 	/* Memory arbitration state */
-	I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
+	I915_WRITE(MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
 
 	for (i = 0; i < 16; i++) {
 		I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_trace.h linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_trace.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/i915_trace.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/i915_trace.h	2012-01-04 18:55:44.000000000 -0500
@@ -385,29 +385,29 @@
 );
 
 TRACE_EVENT(i915_reg_rw,
-           TP_PROTO(bool write, u32 reg, u64 val, int len),
+	TP_PROTO(bool write, u32 reg, u64 val, int len),
 
-           TP_ARGS(write, reg, val, len),
+	TP_ARGS(write, reg, val, len),
 
-           TP_STRUCT__entry(
-                   __field(u64, val)
-                   __field(u32, reg)
-                   __field(u16, write)
-                   __field(u16, len)
-                   ),
+	TP_STRUCT__entry(
+		__field(u64, val)
+		__field(u32, reg)
+		__field(u16, write)
+		__field(u16, len)
+		),
 
-           TP_fast_assign(
-                   __entry->val = (u64)val;
-                   __entry->reg = reg;
-                   __entry->write = write;
-                   __entry->len = len;
-                   ),
+	TP_fast_assign(
+		__entry->val = (u64)val;
+		__entry->reg = reg;
+		__entry->write = write;
+		__entry->len = 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))
+	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-3.1-gnu/drivers/gpu/drm/i915/intel_acpi.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_acpi.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_acpi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_acpi.c	2012-01-04 18:55:44.000000000 -0500
@@ -64,7 +64,7 @@
 
 	case ACPI_TYPE_BUFFER:
 		if (obj->buffer.length == 4) {
-			result =(obj->buffer.pointer[0] |
+			result = (obj->buffer.pointer[0] |
 				(obj->buffer.pointer[1] <<  8) |
 				(obj->buffer.pointer[2] << 16) |
 				(obj->buffer.pointer[3] << 24));
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_bios.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_bios.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_bios.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_bios.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2006 Intel Corporation
+ * Copyright Â© 2006 Intel Corporation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -309,6 +309,13 @@
 		dev_priv->lvds_use_ssc = general->enable_ssc;
 		dev_priv->lvds_ssc_freq =
 			intel_bios_ssc_frequency(dev, general->ssc_freq);
+		dev_priv->display_clock_mode = general->display_clock_mode;
+		DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d\n",
+			      dev_priv->int_tv_support,
+			      dev_priv->int_crt_support,
+			      dev_priv->lvds_use_ssc,
+			      dev_priv->lvds_ssc_freq,
+			      dev_priv->display_clock_mode);
 	}
 }
 
@@ -381,7 +388,7 @@
 		if (p_child->dvo_port != DEVICE_PORT_DVOB &&
 			p_child->dvo_port != DEVICE_PORT_DVOC) {
 			/* skip the incorrect SDVO port */
-			DRM_DEBUG_KMS("Incorrect SDVO port. Skip it \n");
+			DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n");
 			continue;
 		}
 		DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"
@@ -396,15 +403,13 @@
 			p_mapping->dvo_wiring = p_child->dvo_wiring;
 			p_mapping->ddc_pin = p_child->ddc_pin;
 			p_mapping->i2c_pin = p_child->i2c_pin;
-			p_mapping->i2c_speed = p_child->i2c_speed;
 			p_mapping->initialized = 1;
-			DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d, i2c_speed=%d\n",
+			DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",
 				      p_mapping->dvo_port,
 				      p_mapping->slave_addr,
 				      p_mapping->dvo_wiring,
 				      p_mapping->ddc_pin,
-				      p_mapping->i2c_pin,
-				      p_mapping->i2c_speed);
+				      p_mapping->i2c_pin);
 		} else {
 			DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
 					 "two SDVO device.\n");
@@ -564,7 +569,7 @@
 		count++;
 	}
 	if (!count) {
-		DRM_DEBUG_KMS("no child dev is parsed from VBT \n");
+		DRM_DEBUG_KMS("no child dev is parsed from VBT\n");
 		return;
 	}
 	dev_priv->child_dev = kzalloc(sizeof(*p_child) * count, GFP_KERNEL);
@@ -610,7 +615,7 @@
 	/* 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);
+	DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);
 
 	/* eDP data */
 	dev_priv->edp.bpp = 18;
@@ -639,7 +644,7 @@
 	if (dev_priv->opregion.vbt) {
 		struct vbt_header *vbt = dev_priv->opregion.vbt;
 		if (memcmp(vbt->signature, "$VBT", 4) == 0) {
-			DRM_DEBUG_DRIVER("Using VBT from OpRegion: %20s\n",
+			DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",
 					 vbt->signature);
 			bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);
 		} else
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_bios.h linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_bios.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_bios.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_bios.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2006 Intel Corporation
+ * Copyright Â© 2006 Intel Corporation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -120,7 +120,9 @@
 	u8 ssc_freq:1;
 	u8 enable_lfp_on_override:1;
 	u8 disable_ssc_ddt:1;
-	u8 rsvd8:3; /* finish byte */
+	u8 rsvd7:1;
+	u8 display_clock_mode:1;
+	u8 rsvd8:1; /* finish byte */
 
         /* bits 3 */
 	u8 disable_smooth_vision:1;
@@ -133,7 +135,10 @@
         /* bits 5 */
 	u8 int_crt_support:1;
 	u8 int_tv_support:1;
-	u8 rsvd11:6; /* finish byte */
+	u8 int_efp_support:1;
+	u8 dp_ssc_enb:1;	/* PCH attached eDP supports SSC */
+	u8 dp_ssc_freq:1;	/* SSC freq for PCH attached eDP */
+	u8 rsvd11:3; /* finish byte */
 } __attribute__((packed));
 
 /* pre-915 */
@@ -197,8 +202,7 @@
 struct child_device_config {
 	u16 handle;
 	u16 device_type;
-	u8  i2c_speed;
-	u8  rsvd[9];
+	u8  device_id[10]; /* ascii string */
 	u16 addin_offset;
 	u8  dvo_port; /* See Device_PORT_* above */
 	u8  i2c_pin;
@@ -240,7 +244,7 @@
 	 * And the device num is related with the size of general definition
 	 * block. It is obtained by using the following formula:
 	 * number = (block_size - sizeof(bdb_general_definitions))/
-	 * 		sizeof(child_device_config);
+	 *	     sizeof(child_device_config);
 	 */
 	struct child_device_config devices[0];
 } __attribute__((packed));
@@ -446,11 +450,11 @@
 #define EDP_VSWING_1_2V		3
 
 struct edp_power_seq {
-	u16 t3;
-	u16 t7;
+	u16 t1_t3;
+	u16 t8;
 	u16 t9;
 	u16 t10;
-	u16 t12;
+	u16 t11_t12;
 } __attribute__ ((packed));
 
 struct edp_link_params {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_crt.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_crt.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_crt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_crt.c	2012-01-04 18:55:44.000000000 -0500
@@ -69,7 +69,7 @@
 	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
 	temp &= ~ADPA_DAC_ENABLE;
 
-	switch(mode) {
+	switch (mode) {
 	case DRM_MODE_DPMS_ON:
 		temp |= ADPA_DAC_ENABLE;
 		break;
@@ -152,17 +152,13 @@
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
 		adpa |= ADPA_VSYNC_ACTIVE_HIGH;
 
-	if (intel_crtc->pipe == 0) {
-		if (HAS_PCH_CPT(dev))
-			adpa |= PORT_TRANS_A_SEL_CPT;
-		else
-			adpa |= ADPA_PIPE_A_SELECT;
-	} else {
-		if (HAS_PCH_CPT(dev))
-			adpa |= PORT_TRANS_B_SEL_CPT;
-		else
-			adpa |= ADPA_PIPE_B_SELECT;
-	}
+	/* For CPT allow 3 pipe config, for others just use A or B */
+	if (HAS_PCH_CPT(dev))
+		adpa |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
+	else if (intel_crtc->pipe == 0)
+		adpa |= ADPA_PIPE_A_SELECT;
+	else
+		adpa |= ADPA_PIPE_B_SELECT;
 
 	if (!HAS_PCH_SPLIT(dev))
 		I915_WRITE(BCLRPAT(intel_crtc->pipe), 0);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_display.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_display.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_display.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_display.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,50 +31,51 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/vgaarb.h>
+#include <drm/drm_edid.h>
 #include "drmP.h"
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
 #include "i915_trace.h"
 #include "drm_dp_helper.h"
-
 #include "drm_crtc_helper.h"
+#include <linux/dma_remapping.h>
 
 #define HAS_eDP (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
 
-bool intel_pipe_has_type (struct drm_crtc *crtc, int type);
+bool intel_pipe_has_type(struct drm_crtc *crtc, int type);
 static void intel_update_watermarks(struct drm_device *dev);
 static void intel_increase_pllclock(struct drm_crtc *crtc);
 static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on);
 
 typedef struct {
-    /* given values */
-    int n;
-    int m1, m2;
-    int p1, p2;
-    /* derived values */
-    int	dot;
-    int	vco;
-    int	m;
-    int	p;
+	/* given values */
+	int n;
+	int m1, m2;
+	int p1, p2;
+	/* derived values */
+	int	dot;
+	int	vco;
+	int	m;
+	int	p;
 } intel_clock_t;
 
 typedef struct {
-    int	min, max;
+	int	min, max;
 } intel_range_t;
 
 typedef struct {
-    int	dot_limit;
-    int	p2_slow, p2_fast;
+	int	dot_limit;
+	int	p2_slow, p2_fast;
 } intel_p2_t;
 
 #define INTEL_P2_NUM		      2
 typedef struct intel_limit intel_limit_t;
 struct intel_limit {
-    intel_range_t   dot, vco, n, m, m1, m2, p, p1;
-    intel_p2_t	    p2;
-    bool (* find_pll)(const intel_limit_t *, struct drm_crtc *,
-		      int, int, intel_clock_t *);
+	intel_range_t   dot, vco, n, m, m1, m2, p, p1;
+	intel_p2_t	    p2;
+	bool (* find_pll)(const intel_limit_t *, struct drm_crtc *,
+			int, int, intel_clock_t *);
 };
 
 /* FDI */
@@ -105,56 +106,56 @@
 }
 
 static const intel_limit_t intel_limits_i8xx_dvo = {
-        .dot = { .min = 25000, .max = 350000 },
-        .vco = { .min = 930000, .max = 1400000 },
-        .n = { .min = 3, .max = 16 },
-        .m = { .min = 96, .max = 140 },
-        .m1 = { .min = 18, .max = 26 },
-        .m2 = { .min = 6, .max = 16 },
-        .p = { .min = 4, .max = 128 },
-        .p1 = { .min = 2, .max = 33 },
+	.dot = { .min = 25000, .max = 350000 },
+	.vco = { .min = 930000, .max = 1400000 },
+	.n = { .min = 3, .max = 16 },
+	.m = { .min = 96, .max = 140 },
+	.m1 = { .min = 18, .max = 26 },
+	.m2 = { .min = 6, .max = 16 },
+	.p = { .min = 4, .max = 128 },
+	.p1 = { .min = 2, .max = 33 },
 	.p2 = { .dot_limit = 165000,
 		.p2_slow = 4, .p2_fast = 2 },
 	.find_pll = intel_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_i8xx_lvds = {
-        .dot = { .min = 25000, .max = 350000 },
-        .vco = { .min = 930000, .max = 1400000 },
-        .n = { .min = 3, .max = 16 },
-        .m = { .min = 96, .max = 140 },
-        .m1 = { .min = 18, .max = 26 },
-        .m2 = { .min = 6, .max = 16 },
-        .p = { .min = 4, .max = 128 },
-        .p1 = { .min = 1, .max = 6 },
+	.dot = { .min = 25000, .max = 350000 },
+	.vco = { .min = 930000, .max = 1400000 },
+	.n = { .min = 3, .max = 16 },
+	.m = { .min = 96, .max = 140 },
+	.m1 = { .min = 18, .max = 26 },
+	.m2 = { .min = 6, .max = 16 },
+	.p = { .min = 4, .max = 128 },
+	.p1 = { .min = 1, .max = 6 },
 	.p2 = { .dot_limit = 165000,
 		.p2_slow = 14, .p2_fast = 7 },
 	.find_pll = intel_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_i9xx_sdvo = {
-        .dot = { .min = 20000, .max = 400000 },
-        .vco = { .min = 1400000, .max = 2800000 },
-        .n = { .min = 1, .max = 6 },
-        .m = { .min = 70, .max = 120 },
-        .m1 = { .min = 10, .max = 22 },
-        .m2 = { .min = 5, .max = 9 },
-        .p = { .min = 5, .max = 80 },
-        .p1 = { .min = 1, .max = 8 },
+	.dot = { .min = 20000, .max = 400000 },
+	.vco = { .min = 1400000, .max = 2800000 },
+	.n = { .min = 1, .max = 6 },
+	.m = { .min = 70, .max = 120 },
+	.m1 = { .min = 10, .max = 22 },
+	.m2 = { .min = 5, .max = 9 },
+	.p = { .min = 5, .max = 80 },
+	.p1 = { .min = 1, .max = 8 },
 	.p2 = { .dot_limit = 200000,
 		.p2_slow = 10, .p2_fast = 5 },
 	.find_pll = intel_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_i9xx_lvds = {
-        .dot = { .min = 20000, .max = 400000 },
-        .vco = { .min = 1400000, .max = 2800000 },
-        .n = { .min = 1, .max = 6 },
-        .m = { .min = 70, .max = 120 },
-        .m1 = { .min = 10, .max = 22 },
-        .m2 = { .min = 5, .max = 9 },
-        .p = { .min = 7, .max = 98 },
-        .p1 = { .min = 1, .max = 8 },
+	.dot = { .min = 20000, .max = 400000 },
+	.vco = { .min = 1400000, .max = 2800000 },
+	.n = { .min = 1, .max = 6 },
+	.m = { .min = 70, .max = 120 },
+	.m1 = { .min = 10, .max = 22 },
+	.m2 = { .min = 5, .max = 9 },
+	.p = { .min = 7, .max = 98 },
+	.p1 = { .min = 1, .max = 8 },
 	.p2 = { .dot_limit = 112000,
 		.p2_slow = 14, .p2_fast = 7 },
 	.find_pll = intel_find_best_PLL,
@@ -222,44 +223,44 @@
 };
 
 static const intel_limit_t intel_limits_g4x_display_port = {
-        .dot = { .min = 161670, .max = 227000 },
-        .vco = { .min = 1750000, .max = 3500000},
-        .n = { .min = 1, .max = 2 },
-        .m = { .min = 97, .max = 108 },
-        .m1 = { .min = 0x10, .max = 0x12 },
-        .m2 = { .min = 0x05, .max = 0x06 },
-        .p = { .min = 10, .max = 20 },
-        .p1 = { .min = 1, .max = 2},
-        .p2 = { .dot_limit = 0,
+	.dot = { .min = 161670, .max = 227000 },
+	.vco = { .min = 1750000, .max = 3500000},
+	.n = { .min = 1, .max = 2 },
+	.m = { .min = 97, .max = 108 },
+	.m1 = { .min = 0x10, .max = 0x12 },
+	.m2 = { .min = 0x05, .max = 0x06 },
+	.p = { .min = 10, .max = 20 },
+	.p1 = { .min = 1, .max = 2},
+	.p2 = { .dot_limit = 0,
 		.p2_slow = 10, .p2_fast = 10 },
-        .find_pll = intel_find_pll_g4x_dp,
+	.find_pll = intel_find_pll_g4x_dp,
 };
 
 static const intel_limit_t intel_limits_pineview_sdvo = {
-        .dot = { .min = 20000, .max = 400000},
-        .vco = { .min = 1700000, .max = 3500000 },
+	.dot = { .min = 20000, .max = 400000},
+	.vco = { .min = 1700000, .max = 3500000 },
 	/* Pineview's Ncounter is a ring counter */
-        .n = { .min = 3, .max = 6 },
-        .m = { .min = 2, .max = 256 },
+	.n = { .min = 3, .max = 6 },
+	.m = { .min = 2, .max = 256 },
 	/* Pineview only has one combined m divider, which we treat as m2. */
-        .m1 = { .min = 0, .max = 0 },
-        .m2 = { .min = 0, .max = 254 },
-        .p = { .min = 5, .max = 80 },
-        .p1 = { .min = 1, .max = 8 },
+	.m1 = { .min = 0, .max = 0 },
+	.m2 = { .min = 0, .max = 254 },
+	.p = { .min = 5, .max = 80 },
+	.p1 = { .min = 1, .max = 8 },
 	.p2 = { .dot_limit = 200000,
 		.p2_slow = 10, .p2_fast = 5 },
 	.find_pll = intel_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_pineview_lvds = {
-        .dot = { .min = 20000, .max = 400000 },
-        .vco = { .min = 1700000, .max = 3500000 },
-        .n = { .min = 3, .max = 6 },
-        .m = { .min = 2, .max = 256 },
-        .m1 = { .min = 0, .max = 0 },
-        .m2 = { .min = 0, .max = 254 },
-        .p = { .min = 7, .max = 112 },
-        .p1 = { .min = 1, .max = 8 },
+	.dot = { .min = 20000, .max = 400000 },
+	.vco = { .min = 1700000, .max = 3500000 },
+	.n = { .min = 3, .max = 6 },
+	.m = { .min = 2, .max = 256 },
+	.m1 = { .min = 0, .max = 0 },
+	.m2 = { .min = 0, .max = 254 },
+	.p = { .min = 7, .max = 112 },
+	.p1 = { .min = 1, .max = 8 },
 	.p2 = { .dot_limit = 112000,
 		.p2_slow = 14, .p2_fast = 14 },
 	.find_pll = intel_find_best_PLL,
@@ -321,7 +322,7 @@
 	.m1 = { .min = 12, .max = 22 },
 	.m2 = { .min = 5, .max = 9 },
 	.p = { .min = 28, .max = 112 },
-	.p1 = { .min = 2,.max = 8 },
+	.p1 = { .min = 2, .max = 8 },
 	.p2 = { .dot_limit = 225000,
 		.p2_slow = 14, .p2_fast = 14 },
 	.find_pll = intel_g4x_find_best_PLL,
@@ -335,24 +336,24 @@
 	.m1 = { .min = 12, .max = 22 },
 	.m2 = { .min = 5, .max = 9 },
 	.p = { .min = 14, .max = 42 },
-	.p1 = { .min = 2,.max = 6 },
+	.p1 = { .min = 2, .max = 6 },
 	.p2 = { .dot_limit = 225000,
 		.p2_slow = 7, .p2_fast = 7 },
 	.find_pll = intel_g4x_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_ironlake_display_port = {
-        .dot = { .min = 25000, .max = 350000 },
-        .vco = { .min = 1760000, .max = 3510000},
-        .n = { .min = 1, .max = 2 },
-        .m = { .min = 81, .max = 90 },
-        .m1 = { .min = 12, .max = 22 },
-        .m2 = { .min = 5, .max = 9 },
-        .p = { .min = 10, .max = 20 },
-        .p1 = { .min = 1, .max = 2},
-        .p2 = { .dot_limit = 0,
+	.dot = { .min = 25000, .max = 350000 },
+	.vco = { .min = 1760000, .max = 3510000},
+	.n = { .min = 1, .max = 2 },
+	.m = { .min = 81, .max = 90 },
+	.m1 = { .min = 12, .max = 22 },
+	.m2 = { .min = 5, .max = 9 },
+	.p = { .min = 10, .max = 20 },
+	.p1 = { .min = 1, .max = 2},
+	.p2 = { .dot_limit = 0,
 		.p2_slow = 10, .p2_fast = 10 },
-        .find_pll = intel_find_pll_ironlake_dp,
+	.find_pll = intel_find_pll_ironlake_dp,
 };
 
 static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
@@ -404,7 +405,7 @@
 		limit = &intel_limits_g4x_hdmi;
 	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) {
 		limit = &intel_limits_g4x_sdvo;
-	} else if (intel_pipe_has_type (crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
 		limit = &intel_limits_g4x_display_port;
 	} else /* The option is for other outputs */
 		limit = &intel_limits_i9xx_sdvo;
@@ -488,26 +489,26 @@
 			       const intel_clock_t *clock)
 {
 	if (clock->p1  < limit->p1.min  || limit->p1.max  < clock->p1)
-		INTELPllInvalid ("p1 out of range\n");
+		INTELPllInvalid("p1 out of range\n");
 	if (clock->p   < limit->p.min   || limit->p.max   < clock->p)
-		INTELPllInvalid ("p out of range\n");
+		INTELPllInvalid("p out of range\n");
 	if (clock->m2  < limit->m2.min  || limit->m2.max  < clock->m2)
-		INTELPllInvalid ("m2 out of range\n");
+		INTELPllInvalid("m2 out of range\n");
 	if (clock->m1  < limit->m1.min  || limit->m1.max  < clock->m1)
-		INTELPllInvalid ("m1 out of range\n");
+		INTELPllInvalid("m1 out of range\n");
 	if (clock->m1 <= clock->m2 && !IS_PINEVIEW(dev))
-		INTELPllInvalid ("m1 <= m2\n");
+		INTELPllInvalid("m1 <= m2\n");
 	if (clock->m   < limit->m.min   || limit->m.max   < clock->m)
-		INTELPllInvalid ("m out of range\n");
+		INTELPllInvalid("m out of range\n");
 	if (clock->n   < limit->n.min   || limit->n.max   < clock->n)
-		INTELPllInvalid ("n out of range\n");
+		INTELPllInvalid("n out of range\n");
 	if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
-		INTELPllInvalid ("vco out of range\n");
+		INTELPllInvalid("vco out of range\n");
 	/* XXX: We may need to be checking "Dot clock" depending on the multiplier,
 	 * connector, etc., rather than just a single range.
 	 */
 	if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
-		INTELPllInvalid ("dot out of range\n");
+		INTELPllInvalid("dot out of range\n");
 
 	return true;
 }
@@ -542,7 +543,7 @@
 			clock.p2 = limit->p2.p2_fast;
 	}
 
-	memset (best_clock, 0, sizeof (*best_clock));
+	memset(best_clock, 0, sizeof(*best_clock));
 
 	for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
 	     clock.m1++) {
@@ -802,6 +803,19 @@
 	u32 val;
 	bool cur_state;
 
+	if (HAS_PCH_CPT(dev_priv->dev)) {
+		u32 pch_dpll;
+
+		pch_dpll = I915_READ(PCH_DPLL_SEL);
+
+		/* Make sure the selected PLL is enabled to the transcoder */
+		WARN(!((pch_dpll >> (4 * pipe)) & 8),
+		     "transcoder %d PLL not enabled\n", pipe);
+
+		/* Convert the transcoder pipe number to a pll pipe number */
+		pipe = (pch_dpll >> (4 * pipe)) & 1;
+	}
+
 	reg = PCH_DPLL(pipe);
 	val = I915_READ(reg);
 	cur_state = !!(val & DPLL_VCO_ENABLE);
@@ -1171,6 +1185,9 @@
 	int reg;
 	u32 val;
 
+	if (pipe > 1)
+		return;
+
 	/* PCH only available on ILK+ */
 	BUG_ON(dev_priv->info->gen < 5);
 
@@ -1191,6 +1208,9 @@
 	int reg;
 	u32 val;
 
+	if (pipe > 1)
+		return;
+
 	/* PCH only available on ILK+ */
 	BUG_ON(dev_priv->info->gen < 5);
 
@@ -1256,7 +1276,7 @@
 	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");
+		DRM_ERROR("failed to disable transcoder %d\n", pipe);
 }
 
 /**
@@ -2085,6 +2105,7 @@
 	switch (plane) {
 	case 0:
 	case 1:
+	case 2:
 		break;
 	default:
 		DRM_ERROR("Can't update plane %d in SAREA\n", plane);
@@ -2184,6 +2205,10 @@
 	case 0:
 	case 1:
 		break;
+	case 2:
+		if (IS_IVYBRIDGE(dev))
+			break;
+		/* fall through otherwise */
 	default:
 		DRM_ERROR("no plane for crtc\n");
 		return -EINVAL;
@@ -2440,7 +2465,7 @@
 
 }
 
-static const int 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,
@@ -2496,7 +2521,7 @@
 	if (HAS_PCH_CPT(dev))
 		cpt_phase_pointer_enable(dev, pipe);
 
-	for (i = 0; i < 4; i++ ) {
+	for (i = 0; i < 4; i++) {
 		reg = FDI_TX_CTL(pipe);
 		temp = I915_READ(reg);
 		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
@@ -2545,7 +2570,7 @@
 	POSTING_READ(reg);
 	udelay(150);
 
-	for (i = 0; i < 4; i++ ) {
+	for (i = 0; i < 4; i++) {
 		reg = FDI_TX_CTL(pipe);
 		temp = I915_READ(reg);
 		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
@@ -2600,6 +2625,7 @@
 	temp |= FDI_LINK_TRAIN_PATTERN_1_IVB;
 	temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
 	temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
+	temp |= FDI_COMPOSITE_SYNC;
 	I915_WRITE(reg, temp | FDI_TX_ENABLE);
 
 	reg = FDI_RX_CTL(pipe);
@@ -2607,6 +2633,7 @@
 	temp &= ~FDI_LINK_TRAIN_AUTO;
 	temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
 	temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
+	temp |= FDI_COMPOSITE_SYNC;
 	I915_WRITE(reg, temp | FDI_RX_ENABLE);
 
 	POSTING_READ(reg);
@@ -2615,7 +2642,7 @@
 	if (HAS_PCH_CPT(dev))
 		cpt_phase_pointer_enable(dev, pipe);
 
-	for (i = 0; i < 4; i++ ) {
+	for (i = 0; i < 4; i++) {
 		reg = FDI_TX_CTL(pipe);
 		temp = I915_READ(reg);
 		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
@@ -2657,7 +2684,7 @@
 	POSTING_READ(reg);
 	udelay(150);
 
-	for (i = 0; i < 4; i++ ) {
+	for (i = 0; i < 4; i++) {
 		reg = FDI_TX_CTL(pipe);
 		temp = I915_READ(reg);
 		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
@@ -2866,7 +2893,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
-	u32 reg, temp;
+	u32 reg, temp, transc_sel;
 
 	/* For PCH output, training FDI link */
 	dev_priv->display.fdi_link_train(crtc);
@@ -2874,12 +2901,21 @@
 	intel_enable_pch_pll(dev_priv, pipe);
 
 	if (HAS_PCH_CPT(dev)) {
+		transc_sel = intel_crtc->use_pll_a ? TRANSC_DPLLA_SEL :
+			TRANSC_DPLLB_SEL;
+
 		/* Be sure PCH DPLL SEL is set */
 		temp = I915_READ(PCH_DPLL_SEL);
-		if (pipe == 0 && (temp & TRANSA_DPLL_ENABLE) == 0)
+		if (pipe == 0) {
+			temp &= ~(TRANSA_DPLLB_SEL);
 			temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL);
-		else if (pipe == 1 && (temp & TRANSB_DPLL_ENABLE) == 0)
+		} else if (pipe == 1) {
+			temp &= ~(TRANSB_DPLLB_SEL);
 			temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
+		} else if (pipe == 2) {
+			temp &= ~(TRANSC_DPLLB_SEL);
+			temp |= (TRANSC_DPLL_ENABLE | transc_sel);
+		}
 		I915_WRITE(PCH_DPLL_SEL, temp);
 	}
 
@@ -2897,7 +2933,8 @@
 
 	/* For PCH DP, enable TRANS_DP_CTL */
 	if (HAS_PCH_CPT(dev) &&
-	    intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+	    (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+	     intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
 		u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) >> 5;
 		reg = TRANS_DP_CTL(pipe);
 		temp = I915_READ(reg);
@@ -2935,6 +2972,24 @@
 	intel_enable_transcoder(dev_priv, pipe);
 }
 
+void intel_cpt_verify_modeset(struct drm_device *dev, int pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int dslreg = PIPEDSL(pipe), tc2reg = TRANS_CHICKEN2(pipe);
+	u32 temp;
+
+	temp = I915_READ(dslreg);
+	udelay(500);
+	if (wait_for(I915_READ(dslreg) != temp, 5)) {
+		/* Without this, mode sets may fail silently on FDI */
+		I915_WRITE(tc2reg, TRANS_AUTOTRAIN_GEN_STALL_DIS);
+		udelay(250);
+		I915_WRITE(tc2reg, 0);
+		if (wait_for(I915_READ(dslreg) != temp, 5))
+			DRM_ERROR("mode set failed: pipe %d stuck\n", pipe);
+	}
+}
+
 static void ironlake_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -3045,13 +3100,13 @@
 		temp = I915_READ(PCH_DPLL_SEL);
 		switch (pipe) {
 		case 0:
-			temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL);
+			temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL);
 			break;
 		case 1:
 			temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
 			break;
 		case 2:
-			/* FIXME: manage transcoder PLLs? */
+			/* C shares PLL A or B */
 			temp &= ~(TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL);
 			break;
 		default:
@@ -3061,7 +3116,8 @@
 	}
 
 	/* disable PCH DPLL */
-	intel_disable_pch_pll(dev_priv, pipe);
+	if (!intel_crtc->no_pll)
+		intel_disable_pch_pll(dev_priv, pipe);
 
 	/* Switch from PCDclk to Rawclk */
 	reg = FDI_RX_CTL(pipe);
@@ -3293,18 +3349,25 @@
 	ironlake_crtc_enable(crtc);
 }
 
-void intel_encoder_prepare (struct drm_encoder *encoder)
+void intel_encoder_prepare(struct drm_encoder *encoder)
 {
 	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
 	/* lvds has its own version of prepare see intel_lvds_prepare */
 	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
 }
 
-void intel_encoder_commit (struct drm_encoder *encoder)
+void intel_encoder_commit(struct drm_encoder *encoder)
 {
 	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
+	struct drm_device *dev = encoder->dev;
+	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+	struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
+
 	/* lvds has its own version of commit see intel_lvds_commit */
 	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+
+	if (HAS_PCH_CPT(dev))
+		intel_cpt_verify_modeset(dev, intel_crtc->pipe);
 }
 
 void intel_encoder_destroy(struct drm_encoder *encoder)
@@ -4478,6 +4541,20 @@
 		enabled |= 2;
 	}
 
+	/* IVB has 3 pipes */
+	if (IS_IVYBRIDGE(dev) &&
+	    g4x_compute_wm0(dev, 2,
+			    &sandybridge_display_wm_info, latency,
+			    &sandybridge_cursor_wm_info, latency,
+			    &plane_wm, &cursor_wm)) {
+		I915_WRITE(WM0_PIPEC_IVB,
+			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+		DRM_DEBUG_KMS("FIFO watermarks For pipe C -"
+			      " plane %d, cursor: %d\n",
+			      plane_wm, cursor_wm);
+		enabled |= 3;
+	}
+
 	/*
 	 * Calculate and update the self-refresh watermark only when one
 	 * display plane is used.
@@ -4584,13 +4661,16 @@
 
 static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
 {
-	return dev_priv->lvds_use_ssc && i915_panel_use_ssc
+	if (i915_panel_use_ssc >= 0)
+		return i915_panel_use_ssc != 0;
+	return dev_priv->lvds_use_ssc
 		&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
 }
 
 /**
  * intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send
  * @crtc: CRTC structure
+ * @mode: requested mode
  *
  * A pipe may be connected to one or more outputs.  Based on the depth of the
  * attached framebuffer, choose a good color depth to use on the pipe.
@@ -4602,13 +4682,15 @@
  *    HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc
  *    Displays may support a restricted set as well, check EDID and clamp as
  *      appropriate.
+ *    DP may want to dither down to 6bpc to fit larger modes
  *
  * RETURNS:
  * Dithering requirement (i.e. false if display bpc and pipe bpc match,
  * true if they don't match).
  */
 static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
-					 unsigned int *pipe_bpp)
+					 unsigned int *pipe_bpp,
+					 struct drm_display_mode *mode)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4633,7 +4715,7 @@
 				lvds_bpc = 6;
 
 			if (lvds_bpc < display_bpc) {
-				DRM_DEBUG_DRIVER("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
+				DRM_DEBUG_KMS("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
 				display_bpc = lvds_bpc;
 			}
 			continue;
@@ -4644,7 +4726,7 @@
 			unsigned int edp_bpc = dev_priv->edp.bpp / 3;
 
 			if (edp_bpc < display_bpc) {
-				DRM_DEBUG_DRIVER("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
+				DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
 				display_bpc = edp_bpc;
 			}
 			continue;
@@ -4659,7 +4741,7 @@
 			/* Don't use an invalid EDID bpc value */
 			if (connector->display_info.bpc &&
 			    connector->display_info.bpc < display_bpc) {
-				DRM_DEBUG_DRIVER("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
+				DRM_DEBUG_KMS("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
 				display_bpc = connector->display_info.bpc;
 			}
 		}
@@ -4670,15 +4752,20 @@
 		 */
 		if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
 			if (display_bpc > 8 && display_bpc < 12) {
-				DRM_DEBUG_DRIVER("forcing bpc to 12 for HDMI\n");
+				DRM_DEBUG_KMS("forcing bpc to 12 for HDMI\n");
 				display_bpc = 12;
 			} else {
-				DRM_DEBUG_DRIVER("forcing bpc to 8 for HDMI\n");
+				DRM_DEBUG_KMS("forcing bpc to 8 for HDMI\n");
 				display_bpc = 8;
 			}
 		}
 	}
 
+	if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
+		DRM_DEBUG_KMS("Dithering DP to 6bpc\n");
+		display_bpc = 6;
+	}
+
 	/*
 	 * We could just drive the pipe at the highest bpc all the time and
 	 * enable dithering as needed, but that costs bandwidth.  So choose
@@ -4711,8 +4798,8 @@
 
 	display_bpc = min(display_bpc, bpc);
 
-	DRM_DEBUG_DRIVER("setting pipe bpc to %d (max display bpc %d)\n",
-			 bpc, display_bpc);
+	DRM_DEBUG_KMS("setting pipe bpc to %d (max display bpc %d)\n",
+		      bpc, display_bpc);
 
 	*pipe_bpp = display_bpc * 3;
 
@@ -4940,6 +5027,16 @@
 			pipeconf &= ~PIPECONF_DOUBLE_WIDE;
 	}
 
+	/* default to 8bpc */
+	pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN);
+	if (is_dp) {
+		if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
+			pipeconf |= PIPECONF_BPP_6 |
+				    PIPECONF_DITHER_EN |
+				    PIPECONF_DITHER_TYPE_SP;
+		}
+	}
+
 	dpll |= DPLL_VCO_ENABLE;
 
 	DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
@@ -5107,36 +5204,52 @@
 	return ret;
 }
 
-static void ironlake_update_pch_refclk(struct drm_device *dev)
+/*
+ * Initialize reference clocks when the driver loads
+ */
+void ironlake_init_pch_refclk(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_mode_config *mode_config = &dev->mode_config;
-	struct drm_crtc *crtc;
 	struct intel_encoder *encoder;
-	struct intel_encoder *has_edp_encoder = NULL;
 	u32 temp;
 	bool has_lvds = false;
+	bool has_cpu_edp = false;
+	bool has_pch_edp = false;
+	bool has_panel = false;
+	bool has_ck505 = false;
+	bool can_ssc = false;
 
 	/* We need to take the global config into account */
-	list_for_each_entry(crtc, &mode_config->crtc_list, head) {
-		if (!crtc->enabled)
-			continue;
-
-		list_for_each_entry(encoder, &mode_config->encoder_list,
-				    base.head) {
-			if (encoder->base.crtc != crtc)
-				continue;
-
-			switch (encoder->type) {
-			case INTEL_OUTPUT_LVDS:
-				has_lvds = true;
-			case INTEL_OUTPUT_EDP:
-				has_edp_encoder = encoder;
-				break;
-			}
+	list_for_each_entry(encoder, &mode_config->encoder_list,
+			    base.head) {
+		switch (encoder->type) {
+		case INTEL_OUTPUT_LVDS:
+			has_panel = true;
+			has_lvds = true;
+			break;
+		case INTEL_OUTPUT_EDP:
+			has_panel = true;
+			if (intel_encoder_is_pch_edp(&encoder->base))
+				has_pch_edp = true;
+			else
+				has_cpu_edp = true;
+			break;
 		}
 	}
 
+	if (HAS_PCH_IBX(dev)) {
+		has_ck505 = dev_priv->display_clock_mode;
+		can_ssc = has_ck505;
+	} else {
+		has_ck505 = false;
+		can_ssc = true;
+	}
+
+	DRM_DEBUG_KMS("has_panel %d has_lvds %d has_pch_edp %d has_cpu_edp %d has_ck505 %d\n",
+		      has_panel, has_lvds, has_pch_edp, has_cpu_edp,
+		      has_ck505);
+
 	/* Ironlake: try to setup display ref clock before DPLL
 	 * enabling. This is only under driver's control after
 	 * PCH B stepping, previous chipset stepping should be
@@ -5145,43 +5258,102 @@
 	temp = I915_READ(PCH_DREF_CONTROL);
 	/* Always enable nonspread source */
 	temp &= ~DREF_NONSPREAD_SOURCE_MASK;
-	temp |= DREF_NONSPREAD_SOURCE_ENABLE;
-	temp &= ~DREF_SSC_SOURCE_MASK;
-	temp |= DREF_SSC_SOURCE_ENABLE;
-	I915_WRITE(PCH_DREF_CONTROL, temp);
 
-	POSTING_READ(PCH_DREF_CONTROL);
-	udelay(200);
+	if (has_ck505)
+		temp |= DREF_NONSPREAD_CK505_ENABLE;
+	else
+		temp |= DREF_NONSPREAD_SOURCE_ENABLE;
 
-	if (has_edp_encoder) {
-		if (intel_panel_use_ssc(dev_priv)) {
-			temp |= DREF_SSC1_ENABLE;
-			I915_WRITE(PCH_DREF_CONTROL, temp);
+	if (has_panel) {
+		temp &= ~DREF_SSC_SOURCE_MASK;
+		temp |= DREF_SSC_SOURCE_ENABLE;
 
-			POSTING_READ(PCH_DREF_CONTROL);
-			udelay(200);
+		/* SSC must be turned on before enabling the CPU output  */
+		if (intel_panel_use_ssc(dev_priv) && can_ssc) {
+			DRM_DEBUG_KMS("Using SSC on panel\n");
+			temp |= DREF_SSC1_ENABLE;
 		}
+
+		/* Get SSC going before enabling the outputs */
+		I915_WRITE(PCH_DREF_CONTROL, temp);
+		POSTING_READ(PCH_DREF_CONTROL);
+		udelay(200);
+
 		temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
 
 		/* Enable CPU source on CPU attached eDP */
-		if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-			if (intel_panel_use_ssc(dev_priv))
+		if (has_cpu_edp) {
+			if (intel_panel_use_ssc(dev_priv) && can_ssc) {
+				DRM_DEBUG_KMS("Using SSC on eDP\n");
 				temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
+			}
 			else
 				temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
-		} else {
-			/* Enable SSC on PCH eDP if needed */
-			if (intel_panel_use_ssc(dev_priv)) {
-				DRM_ERROR("enabling SSC on PCH\n");
-				temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
-			}
-		}
+		} else
+			temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
+
+		I915_WRITE(PCH_DREF_CONTROL, temp);
+		POSTING_READ(PCH_DREF_CONTROL);
+		udelay(200);
+	} else {
+		DRM_DEBUG_KMS("Disabling SSC entirely\n");
+
+		temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
+
+		/* Turn off CPU output */
+		temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
+
+		I915_WRITE(PCH_DREF_CONTROL, temp);
+		POSTING_READ(PCH_DREF_CONTROL);
+		udelay(200);
+
+		/* Turn off the SSC source */
+		temp &= ~DREF_SSC_SOURCE_MASK;
+		temp |= DREF_SSC_SOURCE_DISABLE;
+
+		/* Turn off SSC1 */
+		temp &= ~ DREF_SSC1_ENABLE;
+
 		I915_WRITE(PCH_DREF_CONTROL, temp);
 		POSTING_READ(PCH_DREF_CONTROL);
 		udelay(200);
 	}
 }
 
+static int ironlake_get_refclk(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *encoder;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct intel_encoder *edp_encoder = NULL;
+	int num_connectors = 0;
+	bool is_lvds = false;
+
+	list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
+		if (encoder->base.crtc != crtc)
+			continue;
+
+		switch (encoder->type) {
+		case INTEL_OUTPUT_LVDS:
+			is_lvds = true;
+			break;
+		case INTEL_OUTPUT_EDP:
+			edp_encoder = encoder;
+			break;
+		}
+		num_connectors++;
+	}
+
+	if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
+		DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
+			      dev_priv->lvds_ssc_freq);
+		return dev_priv->lvds_ssc_freq * 1000;
+	}
+
+	return 120000;
+}
+
 static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 				  struct drm_display_mode *mode,
 				  struct drm_display_mode *adjusted_mode,
@@ -5241,16 +5413,7 @@
 		num_connectors++;
 	}
 
-	if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
-		refclk = dev_priv->lvds_ssc_freq * 1000;
-		DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
-			      refclk / 1000);
-	} else {
-		refclk = 96000;
-		if (!has_edp_encoder ||
-		    intel_encoder_is_pch_edp(&has_edp_encoder->base))
-			refclk = 120000; /* 120Mhz refclk */
-	}
+	refclk = ironlake_get_refclk(crtc);
 
 	/*
 	 * Returns a set of divisors for the desired target clock with the given
@@ -5335,7 +5498,7 @@
 	/* determine panel color depth */
 	temp = I915_READ(PIPECONF(pipe));
 	temp &= ~PIPE_BPC_MASK;
-	dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp);
+	dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode);
 	switch (pipe_bpp) {
 	case 18:
 		temp |= PIPE_6BPC;
@@ -5377,8 +5540,6 @@
 	ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
 			     &m_n);
 
-	ironlake_update_pch_refclk(dev);
-
 	fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
 	if (has_reduced_clock)
 		fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
@@ -5450,39 +5611,32 @@
 	/* Set up the display plane register */
 	dspcntr = DISPPLANE_GAMMA_ENABLE;
 
-	DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+	DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
 	drm_mode_debug_printmodeline(mode);
 
 	/* PCH eDP needs FDI, but CPU eDP does not */
-	if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-		I915_WRITE(PCH_FP0(pipe), fp);
-		I915_WRITE(PCH_DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
-
-		POSTING_READ(PCH_DPLL(pipe));
-		udelay(150);
-	}
+	if (!intel_crtc->no_pll) {
+		if (!has_edp_encoder ||
+		    intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+			I915_WRITE(PCH_FP0(pipe), fp);
+			I915_WRITE(PCH_DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
 
-	/* enable transcoder DPLL */
-	if (HAS_PCH_CPT(dev)) {
-		temp = I915_READ(PCH_DPLL_SEL);
-		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();
+			POSTING_READ(PCH_DPLL(pipe));
+			udelay(150);
+		}
+	} else {
+		if (dpll == (I915_READ(PCH_DPLL(0)) & 0x7fffffff) &&
+		    fp == I915_READ(PCH_FP0(0))) {
+			intel_crtc->use_pll_a = true;
+			DRM_DEBUG_KMS("using pipe a dpll\n");
+		} else if (dpll == (I915_READ(PCH_DPLL(1)) & 0x7fffffff) &&
+			   fp == I915_READ(PCH_FP0(1))) {
+			intel_crtc->use_pll_a = false;
+			DRM_DEBUG_KMS("using pipe b dpll\n");
+		} else {
+			DRM_DEBUG_KMS("no matching PLL configuration for pipe 2\n");
+			return -EINVAL;
 		}
-		I915_WRITE(PCH_DPLL_SEL, temp);
-
-		POSTING_READ(PCH_DPLL_SEL);
-		udelay(150);
 	}
 
 	/* The LVDS pin pair needs to be on before the DPLLs are enabled.
@@ -5492,17 +5646,13 @@
 	if (is_lvds) {
 		temp = I915_READ(PCH_LVDS);
 		temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
-		if (pipe == 1) {
-			if (HAS_PCH_CPT(dev))
-				temp |= PORT_TRANS_B_SEL_CPT;
-			else
-				temp |= LVDS_PIPEB_SELECT;
-		} else {
-			if (HAS_PCH_CPT(dev))
-				temp &= ~PORT_TRANS_SEL_MASK;
-			else
-				temp &= ~LVDS_PIPEB_SELECT;
-		}
+		if (HAS_PCH_CPT(dev))
+			temp |= PORT_TRANS_SEL_CPT(pipe);
+		else if (pipe == 1)
+			temp |= LVDS_PIPEB_SELECT;
+		else
+			temp &= ~LVDS_PIPEB_SELECT;
+
 		/* set the corresponsding LVDS_BORDER bit */
 		temp |= dev_priv->lvds_border_bits;
 		/* Set the B0-B3 data pairs corresponding to whether we're going to
@@ -5540,7 +5690,7 @@
 	pipeconf &= ~PIPECONF_DITHER_TYPE_MASK;
 	if ((is_lvds && dev_priv->lvds_dither) || dither) {
 		pipeconf |= PIPECONF_DITHER_EN;
-		pipeconf |= PIPECONF_DITHER_TYPE_ST1;
+		pipeconf |= PIPECONF_DITHER_TYPE_SP;
 	}
 	if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
 		intel_dp_set_m_n(crtc, mode, adjusted_mode);
@@ -5552,8 +5702,9 @@
 		I915_WRITE(TRANSDPLINK_N1(pipe), 0);
 	}
 
-	if (!has_edp_encoder ||
-	    intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+	if (!intel_crtc->no_pll &&
+	    (!has_edp_encoder ||
+	     intel_encoder_is_pch_edp(&has_edp_encoder->base))) {
 		I915_WRITE(PCH_DPLL(pipe), dpll);
 
 		/* Wait for the clocks to stabilize. */
@@ -5569,18 +5720,20 @@
 	}
 
 	intel_crtc->lowfreq_avail = false;
-	if (is_lvds && has_reduced_clock && i915_powersave) {
-		I915_WRITE(PCH_FP1(pipe), fp2);
-		intel_crtc->lowfreq_avail = true;
-		if (HAS_PIPE_CXSR(dev)) {
-			DRM_DEBUG_KMS("enabling CxSR downclocking\n");
-			pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
-		}
-	} else {
-		I915_WRITE(PCH_FP1(pipe), fp);
-		if (HAS_PIPE_CXSR(dev)) {
-			DRM_DEBUG_KMS("disabling CxSR downclocking\n");
-			pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
+	if (!intel_crtc->no_pll) {
+		if (is_lvds && has_reduced_clock && i915_powersave) {
+			I915_WRITE(PCH_FP1(pipe), fp2);
+			intel_crtc->lowfreq_avail = true;
+			if (HAS_PIPE_CXSR(dev)) {
+				DRM_DEBUG_KMS("enabling CxSR downclocking\n");
+				pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
+			}
+		} else {
+			I915_WRITE(PCH_FP1(pipe), fp);
+			if (HAS_PIPE_CXSR(dev)) {
+				DRM_DEBUG_KMS("disabling CxSR downclocking\n");
+				pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
+			}
 		}
 	}
 
@@ -5677,6 +5830,131 @@
 	return ret;
 }
 
+static void g4x_write_eld(struct drm_connector *connector,
+			  struct drm_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = connector->dev->dev_private;
+	uint8_t *eld = connector->eld;
+	uint32_t eldv;
+	uint32_t len;
+	uint32_t i;
+
+	i = I915_READ(G4X_AUD_VID_DID);
+
+	if (i == INTEL_AUDIO_DEVBLC || i == INTEL_AUDIO_DEVCL)
+		eldv = G4X_ELDV_DEVCL_DEVBLC;
+	else
+		eldv = G4X_ELDV_DEVCTG;
+
+	i = I915_READ(G4X_AUD_CNTL_ST);
+	i &= ~(eldv | G4X_ELD_ADDR);
+	len = (i >> 9) & 0x1f;		/* ELD buffer size */
+	I915_WRITE(G4X_AUD_CNTL_ST, i);
+
+	if (!eld[0])
+		return;
+
+	len = min_t(uint8_t, eld[2], len);
+	DRM_DEBUG_DRIVER("ELD size %d\n", len);
+	for (i = 0; i < len; i++)
+		I915_WRITE(G4X_HDMIW_HDMIEDID, *((uint32_t *)eld + i));
+
+	i = I915_READ(G4X_AUD_CNTL_ST);
+	i |= eldv;
+	I915_WRITE(G4X_AUD_CNTL_ST, i);
+}
+
+static void ironlake_write_eld(struct drm_connector *connector,
+				     struct drm_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = connector->dev->dev_private;
+	uint8_t *eld = connector->eld;
+	uint32_t eldv;
+	uint32_t i;
+	int len;
+	int hdmiw_hdmiedid;
+	int aud_cntl_st;
+	int aud_cntrl_st2;
+
+	if (IS_IVYBRIDGE(connector->dev)) {
+		hdmiw_hdmiedid = GEN7_HDMIW_HDMIEDID_A;
+		aud_cntl_st = GEN7_AUD_CNTRL_ST_A;
+		aud_cntrl_st2 = GEN7_AUD_CNTRL_ST2;
+	} else {
+		hdmiw_hdmiedid = GEN5_HDMIW_HDMIEDID_A;
+		aud_cntl_st = GEN5_AUD_CNTL_ST_A;
+		aud_cntrl_st2 = GEN5_AUD_CNTL_ST2;
+	}
+
+	i = to_intel_crtc(crtc)->pipe;
+	hdmiw_hdmiedid += i * 0x100;
+	aud_cntl_st += i * 0x100;
+
+	DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(i));
+
+	i = I915_READ(aud_cntl_st);
+	i = (i >> 29) & 0x3;		/* DIP_Port_Select, 0x1 = PortB */
+	if (!i) {
+		DRM_DEBUG_DRIVER("Audio directed to unknown port\n");
+		/* operate blindly on all ports */
+		eldv = GEN5_ELD_VALIDB;
+		eldv |= GEN5_ELD_VALIDB << 4;
+		eldv |= GEN5_ELD_VALIDB << 8;
+	} else {
+		DRM_DEBUG_DRIVER("ELD on port %c\n", 'A' + i);
+		eldv = GEN5_ELD_VALIDB << ((i - 1) * 4);
+	}
+
+	i = I915_READ(aud_cntrl_st2);
+	i &= ~eldv;
+	I915_WRITE(aud_cntrl_st2, i);
+
+	if (!eld[0])
+		return;
+
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+		DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
+		eld[5] |= (1 << 2);	/* Conn_Type, 0x1 = DisplayPort */
+	}
+
+	i = I915_READ(aud_cntl_st);
+	i &= ~GEN5_ELD_ADDRESS;
+	I915_WRITE(aud_cntl_st, i);
+
+	len = min_t(uint8_t, eld[2], 21);	/* 84 bytes of hw ELD buffer */
+	DRM_DEBUG_DRIVER("ELD size %d\n", len);
+	for (i = 0; i < len; i++)
+		I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i));
+
+	i = I915_READ(aud_cntrl_st2);
+	i |= eldv;
+	I915_WRITE(aud_cntrl_st2, i);
+}
+
+void intel_write_eld(struct drm_encoder *encoder,
+		     struct drm_display_mode *mode)
+{
+	struct drm_crtc *crtc = encoder->crtc;
+	struct drm_connector *connector;
+	struct drm_device *dev = encoder->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	connector = drm_select_eld(encoder, mode);
+	if (!connector)
+		return;
+
+	DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
+			 connector->base.id,
+			 drm_get_connector_name(connector),
+			 connector->encoder->base.id,
+			 drm_get_encoder_name(connector->encoder));
+
+	connector->eld[6] = drm_av_sync_delay(connector, mode) / 2;
+
+	if (dev_priv->display.write_eld)
+		dev_priv->display.write_eld(connector, crtc);
+}
+
 /** Loads the palette/gamma unit for the CRTC with the prepared values */
 void intel_crtc_load_lut(struct drm_crtc *crtc)
 {
@@ -5758,6 +6036,31 @@
 	I915_WRITE(CURBASE(pipe), base);
 }
 
+static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
+{
+	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;
+	bool visible = base != 0;
+
+	if (intel_crtc->cursor_visible != visible) {
+		uint32_t cntl = I915_READ(CURCNTR_IVB(pipe));
+		if (base) {
+			cntl &= ~CURSOR_MODE;
+			cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+		} else {
+			cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
+			cntl |= CURSOR_MODE_DISABLE;
+		}
+		I915_WRITE(CURCNTR_IVB(pipe), cntl);
+
+		intel_crtc->cursor_visible = visible;
+	}
+	/* and commit changes on next vblank */
+	I915_WRITE(CURBASE_IVB(pipe), base);
+}
+
 /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
 static void intel_crtc_update_cursor(struct drm_crtc *crtc,
 				     bool on)
@@ -5805,11 +6108,16 @@
 	if (!visible && !intel_crtc->cursor_visible)
 		return;
 
-	I915_WRITE(CURPOS(pipe), pos);
-	if (IS_845G(dev) || IS_I865G(dev))
-		i845_update_cursor(crtc, base);
-	else
-		i9xx_update_cursor(crtc, base);
+	if (IS_IVYBRIDGE(dev)) {
+		I915_WRITE(CURPOS_IVB(pipe), pos);
+		ivb_update_cursor(crtc, base);
+	} else {
+		I915_WRITE(CURPOS(pipe), pos);
+		if (IS_845G(dev) || IS_I865G(dev))
+			i845_update_cursor(crtc, base);
+		else
+			i9xx_update_cursor(crtc, base);
+	}
 
 	if (visible)
 		intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj);
@@ -6899,11 +7207,16 @@
 	work->old_fb_obj = intel_fb->obj;
 	INIT_WORK(&work->work, intel_unpin_work_fn);
 
+	ret = drm_vblank_get(dev, intel_crtc->pipe);
+	if (ret)
+		goto free_work;
+
 	/* We borrow the event spin lock for protecting unpin_work */
 	spin_lock_irqsave(&dev->event_lock, flags);
 	if (intel_crtc->unpin_work) {
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 		kfree(work);
+		drm_vblank_put(dev, intel_crtc->pipe);
 
 		DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
 		return -EBUSY;
@@ -6922,10 +7235,6 @@
 
 	crtc->fb = fb;
 
-	ret = drm_vblank_get(dev, intel_crtc->pipe);
-	if (ret)
-		goto cleanup_objs;
-
 	work->pending_flip_obj = obj;
 
 	work->enable_stall_check = true;
@@ -6948,7 +7257,6 @@
 
 cleanup_pending:
 	atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
-cleanup_objs:
 	drm_gem_object_unreference(&work->old_fb_obj->base);
 	drm_gem_object_unreference(&obj->base);
 	mutex_unlock(&dev->struct_mutex);
@@ -6957,6 +7265,8 @@
 	intel_crtc->unpin_work = NULL;
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 
+	drm_vblank_put(dev, intel_crtc->pipe);
+free_work:
 	kfree(work);
 
 	return ret;
@@ -7071,6 +7381,8 @@
 	intel_crtc->bpp = 24; /* default for pre-Ironlake */
 
 	if (HAS_PCH_SPLIT(dev)) {
+		if (pipe == 2 && IS_IVYBRIDGE(dev))
+			intel_crtc->no_pll = true;
 		intel_helper_funcs.prepare = ironlake_crtc_prepare;
 		intel_helper_funcs.commit = ironlake_crtc_commit;
 	} else {
@@ -7250,6 +7562,9 @@
 
 	/* disable all the possible outputs/crtcs before entering KMS mode */
 	drm_helper_disable_unused_functions(dev);
+
+	if (HAS_PCH_SPLIT(dev))
+		ironlake_init_pch_refclk(dev);
 }
 
 static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
@@ -7494,6 +7809,10 @@
 	I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
 	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
 	I915_WRITE(GEN6_PMIER, 0);
+	/* Complete PM interrupt masking here doesn't race with the rps work
+	 * item again unmasking PM interrupts because that is using a different
+	 * register (PMIMR) to mask PM interrupts. The only risk is in leaving
+	 * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
 
 	spin_lock_irq(&dev_priv->rps_lock);
 	dev_priv->pm_iir = 0;
@@ -7588,6 +7907,31 @@
 	dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);
 }
 
+static bool intel_enable_rc6(struct drm_device *dev)
+{
+	/*
+	 * Respect the kernel parameter if it is set
+	 */
+	if (i915_enable_rc6 >= 0)
+		return i915_enable_rc6;
+
+	/*
+	 * Disable RC6 on Ironlake
+	 */
+	if (INTEL_INFO(dev)->gen == 5)
+		return 0;
+
+	/*
+	 * Disable rc6 on Sandybridge
+	 */
+	if (INTEL_INFO(dev)->gen == 6) {
+		DRM_DEBUG_DRIVER("Sandybridge: RC6 disabled\n");
+		return 0;
+	}
+	DRM_DEBUG_DRIVER("RC6 enabled\n");
+	return 1;
+}
+
 void gen6_enable_rps(struct drm_i915_private *dev_priv)
 {
 	u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
@@ -7624,7 +7968,7 @@
 	I915_WRITE(GEN6_RC6p_THRESHOLD, 100000);
 	I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */
 
-	if (i915_enable_rc6)
+	if (intel_enable_rc6(dev_priv->dev))
 		rc6_mask = GEN6_RC_CTL_RC6p_ENABLE |
 			GEN6_RC_CTL_RC6_ENABLE;
 
@@ -7850,6 +8194,20 @@
 	I915_WRITE(WM2_LP_ILK, 0);
 	I915_WRITE(WM1_LP_ILK, 0);
 
+	/* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock
+	 * gating disable must be set.  Failure to set it results in
+	 * flickering pixels due to Z write ordering failures after
+	 * some amount of runtime in the Mesa "fire" demo, and Unigine
+	 * Sanctuary and Tropics, and apparently anything else with
+	 * alpha test or pixel discard.
+	 *
+	 * According to the spec, bit 11 (RCCUNIT) must also be set,
+	 * but we didn't debug actual testcases to find it out.
+	 */
+	I915_WRITE(GEN6_UCGCTL2,
+		   GEN6_RCPBUNIT_CLOCK_GATE_DISABLE |
+		   GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
+
 	/*
 	 * According to the spec the following bits should be
 	 * set in order to enable memory self-refresh and fbc:
@@ -8059,7 +8417,7 @@
 	/* rc6 disabled by default due to repeated reports of hanging during
 	 * boot and resume.
 	 */
-	if (!i915_enable_rc6)
+	if (!intel_enable_rc6(dev))
 		return;
 
 	mutex_lock(&dev->struct_mutex);
@@ -8154,7 +8512,7 @@
 	}
 
 	/* Returns the core display clock speed */
-	if (IS_I945G(dev) || (IS_G33(dev) && ! IS_PINEVIEW_M(dev)))
+	if (IS_I945G(dev) || (IS_G33(dev) && !IS_PINEVIEW_M(dev)))
 		dev_priv->display.get_display_clock_speed =
 			i945_get_display_clock_speed;
 	else if (IS_I915G(dev))
@@ -8178,6 +8536,28 @@
 
 	/* For FIFO watermark updates */
 	if (HAS_PCH_SPLIT(dev)) {
+		dev_priv->display.force_wake_get = __gen6_gt_force_wake_get;
+		dev_priv->display.force_wake_put = __gen6_gt_force_wake_put;
+
+		/* IVB configs may use multi-threaded forcewake */
+		if (IS_IVYBRIDGE(dev)) {
+			u32	ecobus;
+
+			mutex_lock(&dev->struct_mutex);
+			__gen6_gt_force_wake_mt_get(dev_priv);
+			ecobus = I915_READ(ECOBUS);
+			__gen6_gt_force_wake_mt_put(dev_priv);
+			mutex_unlock(&dev->struct_mutex);
+
+			if (ecobus & FORCEWAKE_MT_ENABLE) {
+				DRM_DEBUG_KMS("Using MT version of forcewake\n");
+				dev_priv->display.force_wake_get =
+					__gen6_gt_force_wake_mt_get;
+				dev_priv->display.force_wake_put =
+					__gen6_gt_force_wake_mt_put;
+			}
+		}
+
 		if (HAS_PCH_IBX(dev))
 			dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating;
 		else if (HAS_PCH_CPT(dev))
@@ -8193,6 +8573,7 @@
 			}
 			dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
 			dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
+			dev_priv->display.write_eld = ironlake_write_eld;
 		} else if (IS_GEN6(dev)) {
 			if (SNB_READ_WM0_LATENCY()) {
 				dev_priv->display.update_wm = sandybridge_update_wm;
@@ -8203,6 +8584,7 @@
 			}
 			dev_priv->display.fdi_link_train = gen6_fdi_link_train;
 			dev_priv->display.init_clock_gating = gen6_init_clock_gating;
+			dev_priv->display.write_eld = ironlake_write_eld;
 		} else if (IS_IVYBRIDGE(dev)) {
 			/* FIXME: detect B0+ stepping and use auto training */
 			dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
@@ -8214,7 +8596,7 @@
 				dev_priv->display.update_wm = NULL;
 			}
 			dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
-
+			dev_priv->display.write_eld = ironlake_write_eld;
 		} else
 			dev_priv->display.update_wm = NULL;
 	} else if (IS_PINEVIEW(dev)) {
@@ -8225,7 +8607,7 @@
 			DRM_INFO("failed to find known CxSR latency "
 				 "(found ddr%s fsb freq %d, mem freq %d), "
 				 "disabling CxSR\n",
-				 (dev_priv->is_ddr3 == 1) ? "3": "2",
+				 (dev_priv->is_ddr3 == 1) ? "3" : "2",
 				 dev_priv->fsb_freq, dev_priv->mem_freq);
 			/* Disable CxSR and never update its watermark again */
 			pineview_disable_cxsr(dev);
@@ -8234,6 +8616,7 @@
 			dev_priv->display.update_wm = pineview_update_wm;
 		dev_priv->display.init_clock_gating = gen3_init_clock_gating;
 	} else if (IS_G4X(dev)) {
+		dev_priv->display.write_eld = g4x_write_eld;
 		dev_priv->display.update_wm = g4x_update_wm;
 		dev_priv->display.init_clock_gating = g4x_init_clock_gating;
 	} else if (IS_GEN4(dev)) {
@@ -8294,7 +8677,7 @@
  * resume, or other times.  This quirk makes sure that's the case for
  * affected systems.
  */
-static void quirk_pipea_force (struct drm_device *dev)
+static void quirk_pipea_force(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -8322,7 +8705,7 @@
 	/* HP Compaq 2730p needs pipe A force quirk (LP: #291555) */
 	{ 0x2a42, 0x103c, 0x30eb, quirk_pipea_force },
 	/* HP Mini needs pipe A force quirk (LP: #322104) */
-	{ 0x27ae,0x103c, 0x361a, quirk_pipea_force },
+	{ 0x27ae, 0x103c, 0x361a, quirk_pipea_force },
 
 	/* Thinkpad R31 needs pipe A force quirk */
 	{ 0x3577, 0x1014, 0x0505, quirk_pipea_force },
@@ -8488,6 +8871,7 @@
 	 * enqueue unpin/hotplug work. */
 	drm_irq_uninstall(dev);
 	cancel_work_sync(&dev_priv->hotplug_work);
+	cancel_work_sync(&dev_priv->rps_work);
 
 	/* flush any delayed tasks or pending work */
 	flush_scheduled_work();
@@ -8573,7 +8957,7 @@
 struct intel_display_error_state *
 intel_display_capture_error_state(struct drm_device *dev)
 {
-        drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_display_error_state *error;
 	int i;
 
@@ -8589,7 +8973,7 @@
 		error->plane[i].control = I915_READ(DSPCNTR(i));
 		error->plane[i].stride = I915_READ(DSPSTRIDE(i));
 		error->plane[i].size = I915_READ(DSPSIZE(i));
-		error->plane[i].pos= I915_READ(DSPPOS(i));
+		error->plane[i].pos = I915_READ(DSPPOS(i));
 		error->plane[i].addr = I915_READ(DSPADDR(i));
 		if (INTEL_INFO(dev)->gen >= 4) {
 			error->plane[i].surface = I915_READ(DSPSURF(i));
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_dp.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_dp.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_dp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_dp.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 
 #include <linux/i2c.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "drmP.h"
 #include "drm.h"
 #include "drm_crtc.h"
@@ -36,7 +37,7 @@
 #include "i915_drv.h"
 #include "drm_dp_helper.h"
 
-
+#define DP_RECEIVER_CAP_SIZE	0xf
 #define DP_LINK_STATUS_SIZE	6
 #define DP_LINK_CHECK_TIMEOUT	(10 * 1000)
 
@@ -53,12 +54,19 @@
 	int dpms_mode;
 	uint8_t link_bw;
 	uint8_t lane_count;
-	uint8_t dpcd[8];
+	uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
 	struct i2c_adapter adapter;
 	struct i2c_algo_dp_aux_data algo;
 	bool is_pch_edp;
 	uint8_t	train_set[4];
-	uint8_t link_status[DP_LINK_STATUS_SIZE];
+	int panel_power_up_delay;
+	int panel_power_down_delay;
+	int panel_power_cycle_delay;
+	int backlight_on_delay;
+	int backlight_off_delay;
+	struct drm_display_mode *panel_fixed_mode;  /* for eDP */
+	struct delayed_work panel_vdd_work;
+	bool want_panel_vdd;
 };
 
 /**
@@ -86,6 +94,17 @@
 	return intel_dp->is_pch_edp;
 }
 
+/**
+ * is_cpu_edp - is the port on the CPU and attached to an eDP panel?
+ * @intel_dp: DP struct
+ *
+ * Returns true if the given DP struct corresponds to a CPU eDP port.
+ */
+static bool is_cpu_edp(struct intel_dp *intel_dp)
+{
+	return is_edp(intel_dp) && !is_pch_edp(intel_dp);
+}
+
 static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
 {
 	return container_of(encoder, struct intel_dp, base.base);
@@ -121,7 +140,7 @@
 static void intel_dp_link_down(struct intel_dp *intel_dp);
 
 void
-intel_edp_link_config (struct intel_encoder *intel_encoder,
+intel_edp_link_config(struct intel_encoder *intel_encoder,
 		       int *lane_num, int *link_bw)
 {
 	struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
@@ -136,16 +155,12 @@
 static int
 intel_dp_max_lane_count(struct intel_dp *intel_dp)
 {
-	int max_lane_count = 4;
-
-	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) {
-		max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f;
-		switch (max_lane_count) {
-		case 1: case 2: case 4:
-			break;
-		default:
-			max_lane_count = 4;
-		}
+	int max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f;
+	switch (max_lane_count) {
+	case 1: case 2: case 4:
+		break;
+	default:
+		max_lane_count = 4;
 	}
 	return max_lane_count;
 }
@@ -175,18 +190,36 @@
 		return 162000;
 }
 
-/* I think this is a fiction */
+/*
+ * The units on the numbers in the next two are... bizarre.  Examples will
+ * make it clearer; this one parallels an example in the eDP spec.
+ *
+ * intel_dp_max_data_rate for one lane of 2.7GHz evaluates as:
+ *
+ *     270000 * 1 * 8 / 10 == 216000
+ *
+ * The actual data capacity of that configuration is 2.16Gbit/s, so the
+ * units are decakilobits.  ->clock in a drm_display_mode is in kilohertz -
+ * or equivalently, kilopixels per second - so for 1680x1050R it'd be
+ * 119000.  At 18bpp that's 2142000 kilobits per second.
+ *
+ * Thus the strange-looking division by 10 in intel_dp_link_required, to
+ * get the result in decakilobits instead of kilobits.
+ */
+
 static int
-intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pixel_clock)
+intel_dp_link_required(struct intel_dp *intel_dp, int pixel_clock, int check_bpp)
 {
 	struct drm_crtc *crtc = intel_dp->base.base.crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int bpp = 24;
 
-	if (intel_crtc)
+	if (check_bpp)
+		bpp = check_bpp;
+	else if (intel_crtc)
 		bpp = intel_crtc->bpp;
 
-	return (pixel_clock * bpp + 7) / 8;
+	return (pixel_clock * bpp + 9) / 10;
 }
 
 static int
@@ -200,25 +233,29 @@
 		    struct drm_display_mode *mode)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
-	struct drm_device *dev = connector->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp));
 	int max_lanes = intel_dp_max_lane_count(intel_dp);
+	int max_rate, mode_rate;
 
-	if (is_edp(intel_dp) && dev_priv->panel_fixed_mode) {
-		if (mode->hdisplay > dev_priv->panel_fixed_mode->hdisplay)
+	if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
+		if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay)
 			return MODE_PANEL;
 
-		if (mode->vdisplay > dev_priv->panel_fixed_mode->vdisplay)
+		if (mode->vdisplay > intel_dp->panel_fixed_mode->vdisplay)
 			return MODE_PANEL;
 	}
 
-	/* 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)
-	     > intel_dp_max_data_rate(max_link_clock, max_lanes)))
-		return MODE_CLOCK_HIGH;
+	mode_rate = intel_dp_link_required(intel_dp, mode->clock, 0);
+	max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
+
+	if (mode_rate > max_rate) {
+			mode_rate = intel_dp_link_required(intel_dp,
+							   mode->clock, 18);
+			if (mode_rate > max_rate)
+				return MODE_CLOCK_HIGH;
+			else
+				mode->private_flags |= INTEL_MODE_DP_FORCE_6BPC;
+	}
 
 	if (mode->clock < 10000)
 		return MODE_CLOCK_LOW;
@@ -279,6 +316,38 @@
 	}
 }
 
+static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	return (I915_READ(PCH_PP_STATUS) & PP_ON) != 0;
+}
+
+static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	return (I915_READ(PCH_PP_CONTROL) & EDP_FORCE_VDD) != 0;
+}
+
+static void
+intel_dp_check_edp(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (!is_edp(intel_dp))
+		return;
+	if (!ironlake_edp_have_panel_power(intel_dp) && !ironlake_edp_have_panel_vdd(intel_dp)) {
+		WARN(1, "eDP powered off while attempting aux channel communication.\n");
+		DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n",
+			      I915_READ(PCH_PP_STATUS),
+			      I915_READ(PCH_PP_CONTROL));
+	}
+}
+
 static int
 intel_dp_aux_ch(struct intel_dp *intel_dp,
 		uint8_t *send, int send_bytes,
@@ -295,6 +364,7 @@
 	uint32_t aux_clock_divider;
 	int try, precharge;
 
+	intel_dp_check_edp(intel_dp);
 	/* The clock divider is based off the hrawclk,
 	 * and would like to run at 2MHz. So, take the
 	 * hrawclk value and divide by 2 and use that
@@ -302,9 +372,9 @@
 	 * Note that PCH attached eDP panels should use a 125MHz input
 	 * clock divider.
 	 */
-	if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) {
-		if (IS_GEN6(dev))
-			aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */
+	if (is_cpu_edp(intel_dp)) {
+		if (IS_GEN6(dev) || IS_GEN7(dev))
+			aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */
 		else
 			aux_clock_divider = 225; /* eDP input clock at 450Mhz */
 	} else if (HAS_PCH_SPLIT(dev))
@@ -337,7 +407,7 @@
 		for (i = 0; i < send_bytes; i += 4)
 			I915_WRITE(ch_data + i,
 				   pack_aux(send + i, send_bytes - i));
-	
+
 		/* Send the command and wait for it to complete */
 		I915_WRITE(ch_ctl,
 			   DP_AUX_CH_CTL_SEND_BUSY |
@@ -354,7 +424,7 @@
 				break;
 			udelay(100);
 		}
-	
+
 		/* Clear done status and any errors */
 		I915_WRITE(ch_ctl,
 			   status |
@@ -390,7 +460,7 @@
 		      DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
 	if (recv_bytes > recv_size)
 		recv_bytes = recv_size;
-	
+
 	for (i = 0; i < recv_bytes; i += 4)
 		unpack_aux(I915_READ(ch_data + i),
 			   recv + i, recv_bytes - i);
@@ -408,6 +478,7 @@
 	int msg_bytes;
 	uint8_t	ack;
 
+	intel_dp_check_edp(intel_dp);
 	if (send_bytes > 16)
 		return -1;
 	msg[0] = AUX_NATIVE_WRITE << 4;
@@ -450,6 +521,7 @@
 	uint8_t ack;
 	int ret;
 
+	intel_dp_check_edp(intel_dp);
 	msg[0] = AUX_NATIVE_READ << 4;
 	msg[1] = address >> 8;
 	msg[2] = address & 0xff;
@@ -493,6 +565,7 @@
 	int reply_bytes;
 	int ret;
 
+	intel_dp_check_edp(intel_dp);
 	/* Set up the command byte */
 	if (mode & MODE_I2C_READ)
 		msg[0] = AUX_I2C_READ << 4;
@@ -573,24 +646,32 @@
 	return -EREMOTEIO;
 }
 
+static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
+static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
+
 static int
 intel_dp_i2c_init(struct intel_dp *intel_dp,
 		  struct intel_connector *intel_connector, const char *name)
 {
+	int	ret;
+
 	DRM_DEBUG_KMS("i2c_init %s\n", name);
 	intel_dp->algo.running = false;
 	intel_dp->algo.address = 0;
 	intel_dp->algo.aux_ch = intel_dp_i2c_aux_ch;
 
-	memset(&intel_dp->adapter, '\0', sizeof (intel_dp->adapter));
+	memset(&intel_dp->adapter, '\0', sizeof(intel_dp->adapter));
 	intel_dp->adapter.owner = THIS_MODULE;
 	intel_dp->adapter.class = I2C_CLASS_DDC;
-	strncpy (intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1);
+	strncpy(intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1);
 	intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0';
 	intel_dp->adapter.algo_data = &intel_dp->algo;
 	intel_dp->adapter.dev.parent = &intel_connector->base.kdev;
 
-	return i2c_dp_aux_add_bus(&intel_dp->adapter);
+	ironlake_edp_panel_vdd_on(intel_dp);
+	ret = i2c_dp_aux_add_bus(&intel_dp->adapter);
+	ironlake_edp_panel_vdd_off(intel_dp, false);
+	return ret;
 }
 
 static bool
@@ -598,29 +679,29 @@
 		    struct drm_display_mode *adjusted_mode)
 {
 	struct drm_device *dev = encoder->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 	int lane_count, clock;
 	int max_lane_count = intel_dp_max_lane_count(intel_dp);
 	int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
+	int bpp = mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 0;
 	static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
 
-	if (is_edp(intel_dp) && dev_priv->panel_fixed_mode) {
-		intel_fixed_panel_mode(dev_priv->panel_fixed_mode, adjusted_mode);
+	if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
+		intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode);
 		intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN,
 					mode, adjusted_mode);
 		/*
 		 * the mode->clock is used to calculate the Data&Link M/N
 		 * of the pipe. For the eDP the fixed clock should be used.
 		 */
-		mode->clock = dev_priv->panel_fixed_mode->clock;
+		mode->clock = intel_dp->panel_fixed_mode->clock;
 	}
 
 	for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
 		for (clock = 0; clock <= max_clock; clock++) {
 			int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
 
-			if (intel_dp_link_required(encoder->dev, intel_dp, mode->clock)
+			if (intel_dp_link_required(intel_dp, mode->clock, bpp)
 					<= link_avail) {
 				intel_dp->link_bw = bws[clock];
 				intel_dp->lane_count = lane_count;
@@ -634,19 +715,6 @@
 		}
 	}
 
-	if (is_edp(intel_dp)) {
-		/* okay we failed just pick the highest */
-		intel_dp->lane_count = max_lane_count;
-		intel_dp->link_bw = bws[max_clock];
-		adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw);
-		DRM_DEBUG_KMS("Force picking display port link bw %02x lane "
-			      "count %d clock %d\n",
-			      intel_dp->link_bw, intel_dp->lane_count,
-			      adjusted_mode->clock);
-
-		return true;
-	}
-
 	return false;
 }
 
@@ -706,12 +774,11 @@
 			continue;
 
 		intel_dp = enc_to_intel_dp(encoder);
-		if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT) {
+		if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT ||
+		    intel_dp->base.type == INTEL_OUTPUT_EDP)
+		{
 			lane_count = intel_dp->lane_count;
 			break;
-		} else if (is_edp(intel_dp)) {
-			lane_count = dev_priv->edp.lanes;
-			break;
 		}
 	}
 
@@ -740,27 +807,53 @@
 	}
 }
 
+static void ironlake_edp_pll_on(struct drm_encoder *encoder);
+static void ironlake_edp_pll_off(struct drm_encoder *encoder);
+
 static void
 intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		  struct drm_display_mode *adjusted_mode)
 {
 	struct drm_device *dev = encoder->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 	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 |= intel_dp->color_range;
+	/* Turn on the eDP PLL if needed */
+	if (is_edp(intel_dp)) {
+		if (!is_pch_edp(intel_dp))
+			ironlake_edp_pll_on(encoder);
+		else
+			ironlake_edp_pll_off(encoder);
+	}
 
-	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
-		intel_dp->DP |= DP_SYNC_HS_HIGH;
-	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
-		intel_dp->DP |= DP_SYNC_VS_HIGH;
+	/*
+	 * There are four kinds of DP registers:
+	 *
+	 * 	IBX PCH
+	 * 	SNB CPU
+	 *	IVB CPU
+	 * 	CPT PCH
+	 *
+	 * IBX PCH and CPU are the same for almost everything,
+	 * except that the CPU DP PLL is configured in this
+	 * register
+	 *
+	 * CPT PCH is quite different, having many bits moved
+	 * to the TRANS_DP_CTL register instead. That
+	 * configuration happens (oddly) in ironlake_pch_enable
+	 */
 
-	if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
-		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
-	else
-		intel_dp->DP |= DP_LINK_TRAIN_OFF;
+	/* Preserve the BIOS-computed detected bit. This is
+	 * supposed to be read-only.
+	 */
+	intel_dp->DP = I915_READ(intel_dp->output_reg) & DP_DETECTED;
+	intel_dp->DP |=  DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
+
+	/* Handle DP bits in common between all three register formats */
+
+	intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
 
 	switch (intel_dp->lane_count) {
 	case 1:
@@ -773,135 +866,297 @@
 		intel_dp->DP |= DP_PORT_WIDTH_4;
 		break;
 	}
-	if (intel_dp->has_audio)
+	if (intel_dp->has_audio) {
+		DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
+				 pipe_name(intel_crtc->pipe));
 		intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
-
+		intel_write_eld(encoder, adjusted_mode);
+	}
 	memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
 	intel_dp->link_configuration[0] = intel_dp->link_bw;
 	intel_dp->link_configuration[1] = intel_dp->lane_count;
 	intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B;
-
 	/*
 	 * Check for DPCD version > 1.1 and enhanced framing support
 	 */
 	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
 	    (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {
 		intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
-		intel_dp->DP |= DP_ENHANCED_FRAMING;
 	}
 
-	/* CPT DP's pipe select is decided in TRANS_DP_CTL */
-	if (intel_crtc->pipe == 1 && !HAS_PCH_CPT(dev))
-		intel_dp->DP |= DP_PIPEB_SELECT;
+	/* Split out the IBX/CPU vs CPT settings */
+
+	if (is_cpu_edp(intel_dp) && IS_GEN7(dev)) {
+		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+			intel_dp->DP |= DP_SYNC_HS_HIGH;
+		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+			intel_dp->DP |= DP_SYNC_VS_HIGH;
+		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
+
+		if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN)
+			intel_dp->DP |= DP_ENHANCED_FRAMING;
+
+		intel_dp->DP |= intel_crtc->pipe << 29;
 
-	if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) {
 		/* don't miss out required setting for eDP */
 		intel_dp->DP |= DP_PLL_ENABLE;
 		if (adjusted_mode->clock < 200000)
 			intel_dp->DP |= DP_PLL_FREQ_160MHZ;
 		else
 			intel_dp->DP |= DP_PLL_FREQ_270MHZ;
+	} else if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) {
+		intel_dp->DP |= intel_dp->color_range;
+
+		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+			intel_dp->DP |= DP_SYNC_HS_HIGH;
+		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+			intel_dp->DP |= DP_SYNC_VS_HIGH;
+		intel_dp->DP |= DP_LINK_TRAIN_OFF;
+
+		if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN)
+			intel_dp->DP |= DP_ENHANCED_FRAMING;
+
+		if (intel_crtc->pipe == 1)
+			intel_dp->DP |= DP_PIPEB_SELECT;
+
+		if (is_cpu_edp(intel_dp)) {
+			/* don't miss out required setting for eDP */
+			intel_dp->DP |= DP_PLL_ENABLE;
+			if (adjusted_mode->clock < 200000)
+				intel_dp->DP |= DP_PLL_FREQ_160MHZ;
+			else
+				intel_dp->DP |= DP_PLL_FREQ_270MHZ;
+		}
+	} else {
+		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
 	}
 }
 
+#define IDLE_ON_MASK		(PP_ON | 0 	  | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
+#define IDLE_ON_VALUE   	(PP_ON | 0 	  | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_ON_IDLE)
+
+#define IDLE_OFF_MASK		(PP_ON | 0        | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
+#define IDLE_OFF_VALUE		(0     | 0        | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
+
+#define IDLE_CYCLE_MASK		(PP_ON | 0        | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK)
+#define IDLE_CYCLE_VALUE	(0     | 0        | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
+
+static void ironlake_wait_panel_status(struct intel_dp *intel_dp,
+				       u32 mask,
+				       u32 value)
+{
+	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	DRM_DEBUG_KMS("mask %08x value %08x status %08x control %08x\n",
+		      mask, value,
+		      I915_READ(PCH_PP_STATUS),
+		      I915_READ(PCH_PP_CONTROL));
+
+	if (_wait_for((I915_READ(PCH_PP_STATUS) & mask) == value, 5000, 10)) {
+		DRM_ERROR("Panel status timeout: status %08x control %08x\n",
+			  I915_READ(PCH_PP_STATUS),
+			  I915_READ(PCH_PP_CONTROL));
+	}
+}
+
+static void ironlake_wait_panel_on(struct intel_dp *intel_dp)
+{
+	DRM_DEBUG_KMS("Wait for panel power on\n");
+	ironlake_wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE);
+}
+
+static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
+{
+	DRM_DEBUG_KMS("Wait for panel power off time\n");
+	ironlake_wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
+}
+
+static void ironlake_wait_panel_power_cycle(struct intel_dp *intel_dp)
+{
+	DRM_DEBUG_KMS("Wait for panel power cycle\n");
+	ironlake_wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
+}
+
+
+/* Read the current pp_control value, unlocking the register if it
+ * is locked
+ */
+
+static  u32 ironlake_get_pp_control(struct drm_i915_private *dev_priv)
+{
+	u32	control = I915_READ(PCH_PP_CONTROL);
+
+	control &= ~PANEL_UNLOCK_MASK;
+	control |= PANEL_UNLOCK_REGS;
+	return control;
+}
+
 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);
+	if (!is_edp(intel_dp))
+		return;
+	DRM_DEBUG_KMS("Turn eDP VDD on\n");
 
-	pp = I915_READ(PCH_PP_CONTROL);
+	WARN(intel_dp->want_panel_vdd,
+	     "eDP VDD already requested on\n");
+
+	intel_dp->want_panel_vdd = true;
+
+	if (ironlake_edp_have_panel_vdd(intel_dp)) {
+		DRM_DEBUG_KMS("eDP VDD already on\n");
+		return;
+	}
+
+	if (!ironlake_edp_have_panel_power(intel_dp))
+		ironlake_wait_panel_power_cycle(intel_dp);
+
+	pp = ironlake_get_pp_control(dev_priv);
 	pp |= EDP_FORCE_VDD;
 	I915_WRITE(PCH_PP_CONTROL, pp);
 	POSTING_READ(PCH_PP_CONTROL);
+	DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n",
+		      I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL));
+
+	/*
+	 * If the panel wasn't on, delay before accessing aux channel
+	 */
+	if (!ironlake_edp_have_panel_power(intel_dp)) {
+		DRM_DEBUG_KMS("eDP was not running\n");
+		msleep(intel_dp->panel_power_up_delay);
+	}
 }
 
-static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp)
+static void ironlake_panel_vdd_off_sync(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);
+	if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) {
+		pp = ironlake_get_pp_control(dev_priv);
+		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);
+		/* Make sure sequencer is idle before allowing subsequent activity */
+		DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n",
+			      I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL));
+
+		msleep(intel_dp->panel_power_down_delay);
+	}
 }
 
-/* Returns true if the panel was already on when called */
-static bool ironlake_edp_panel_on (struct intel_dp *intel_dp)
+static void ironlake_panel_vdd_work(struct work_struct *__work)
+{
+	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
+						 struct intel_dp, panel_vdd_work);
+	struct drm_device *dev = intel_dp->base.base.dev;
+
+	mutex_lock(&dev->mode_config.mutex);
+	ironlake_panel_vdd_off_sync(intel_dp);
+	mutex_unlock(&dev->mode_config.mutex);
+}
+
+static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
+{
+	if (!is_edp(intel_dp))
+		return;
+
+	DRM_DEBUG_KMS("Turn eDP VDD off %d\n", intel_dp->want_panel_vdd);
+	WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on");
+
+	intel_dp->want_panel_vdd = false;
+
+	if (sync) {
+		ironlake_panel_vdd_off_sync(intel_dp);
+	} else {
+		/*
+		 * Queue the timer to fire a long
+		 * time from now (relative to the power down delay)
+		 * to keep the panel power up across a sequence of operations
+		 */
+		schedule_delayed_work(&intel_dp->panel_vdd_work,
+				      msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
+	}
+}
+
+static void ironlake_edp_panel_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, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE;
+	u32 pp;
 
-	if (I915_READ(PCH_PP_STATUS) & PP_ON)
-		return true;
+	if (!is_edp(intel_dp))
+		return;
 
-	pp = I915_READ(PCH_PP_CONTROL);
+	DRM_DEBUG_KMS("Turn eDP power on\n");
 
-	/* ILK workaround: disable reset around power sequence */
-	pp &= ~PANEL_POWER_RESET;
-	I915_WRITE(PCH_PP_CONTROL, pp);
-	POSTING_READ(PCH_PP_CONTROL);
+	if (ironlake_edp_have_panel_power(intel_dp)) {
+		DRM_DEBUG_KMS("eDP power already on\n");
+		return;
+	}
 
-	pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON;
-	I915_WRITE(PCH_PP_CONTROL, pp);
-	POSTING_READ(PCH_PP_CONTROL);
+	ironlake_wait_panel_power_cycle(intel_dp);
 
-	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",
-			  I915_READ(PCH_PP_STATUS));
+	pp = ironlake_get_pp_control(dev_priv);
+	if (IS_GEN5(dev)) {
+		/* ILK workaround: disable reset around power sequence */
+		pp &= ~PANEL_POWER_RESET;
+		I915_WRITE(PCH_PP_CONTROL, pp);
+		POSTING_READ(PCH_PP_CONTROL);
+	}
+
+	pp |= POWER_TARGET_ON;
+	if (!IS_GEN5(dev))
+		pp |= PANEL_POWER_RESET;
 
-	pp |= PANEL_POWER_RESET; /* restore panel reset bit */
 	I915_WRITE(PCH_PP_CONTROL, pp);
 	POSTING_READ(PCH_PP_CONTROL);
 
-	return false;
+	ironlake_wait_panel_on(intel_dp);
+
+	if (IS_GEN5(dev)) {
+		pp |= PANEL_POWER_RESET; /* restore panel reset bit */
+		I915_WRITE(PCH_PP_CONTROL, pp);
+		POSTING_READ(PCH_PP_CONTROL);
+	}
 }
 
-static void ironlake_edp_panel_off (struct drm_device *dev)
+static void ironlake_edp_panel_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, idle_off_mask = PP_ON | PP_SEQUENCE_MASK |
-		PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK;
-
-	pp = I915_READ(PCH_PP_CONTROL);
+	u32 pp;
 
-	/* ILK workaround: disable reset around power sequence */
-	pp &= ~PANEL_POWER_RESET;
-	I915_WRITE(PCH_PP_CONTROL, pp);
-	POSTING_READ(PCH_PP_CONTROL);
+	if (!is_edp(intel_dp))
+		return;
 
-	pp &= ~POWER_TARGET_ON;
-	I915_WRITE(PCH_PP_CONTROL, pp);
-	POSTING_READ(PCH_PP_CONTROL);
+	DRM_DEBUG_KMS("Turn eDP power off\n");
 
-	if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000))
-		DRM_ERROR("panel off wait timed out: 0x%08x\n",
-			  I915_READ(PCH_PP_STATUS));
+	WARN(intel_dp->want_panel_vdd, "Cannot turn power off while VDD is on\n");
 
-	pp |= PANEL_POWER_RESET; /* restore panel reset bit */
+	pp = ironlake_get_pp_control(dev_priv);
+	pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
 	I915_WRITE(PCH_PP_CONTROL, pp);
 	POSTING_READ(PCH_PP_CONTROL);
+
+	ironlake_wait_panel_off(intel_dp);
 }
 
-static void ironlake_edp_backlight_on (struct drm_device *dev)
+static void ironlake_edp_backlight_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 (!is_edp(intel_dp))
+		return;
+
 	DRM_DEBUG_KMS("\n");
 	/*
 	 * If we enable the backlight right away following a panel power
@@ -909,21 +1164,28 @@
 	 * link.  So delay a bit to make sure the image is solid before
 	 * allowing it to appear.
 	 */
-	msleep(300);
-	pp = I915_READ(PCH_PP_CONTROL);
+	msleep(intel_dp->backlight_on_delay);
+	pp = ironlake_get_pp_control(dev_priv);
 	pp |= EDP_BLC_ENABLE;
 	I915_WRITE(PCH_PP_CONTROL, pp);
+	POSTING_READ(PCH_PP_CONTROL);
 }
 
-static void ironlake_edp_backlight_off (struct drm_device *dev)
+static void ironlake_edp_backlight_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;
 
+	if (!is_edp(intel_dp))
+		return;
+
 	DRM_DEBUG_KMS("\n");
-	pp = I915_READ(PCH_PP_CONTROL);
+	pp = ironlake_get_pp_control(dev_priv);
 	pp &= ~EDP_BLC_ENABLE;
 	I915_WRITE(PCH_PP_CONTROL, pp);
+	POSTING_READ(PCH_PP_CONTROL);
+	msleep(intel_dp->backlight_off_delay);
 }
 
 static void ironlake_edp_pll_on(struct drm_encoder *encoder)
@@ -986,43 +1248,39 @@
 static void intel_dp_prepare(struct drm_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-	struct drm_device *dev = encoder->dev;
+
+	ironlake_edp_backlight_off(intel_dp);
+	ironlake_edp_panel_off(intel_dp);
 
 	/* Wake up the sink first */
+	ironlake_edp_panel_vdd_on(intel_dp);
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
-
-	if (is_edp(intel_dp)) {
-		ironlake_edp_backlight_off(dev);
-		ironlake_edp_panel_off(dev);
-		if (!is_pch_edp(intel_dp))
-			ironlake_edp_pll_on(encoder);
-		else
-			ironlake_edp_pll_off(encoder);
-	}
 	intel_dp_link_down(intel_dp);
+	ironlake_edp_panel_vdd_off(intel_dp, false);
+
+	/* Make sure the panel is off before trying to
+	 * change the mode
+	 */
 }
 
 static void intel_dp_commit(struct drm_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 	struct drm_device *dev = encoder->dev;
+	struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
 
-	if (is_edp(intel_dp))
-		ironlake_edp_panel_vdd_on(intel_dp);
-
+	ironlake_edp_panel_vdd_on(intel_dp);
+	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
 	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);
-	}
-
+	ironlake_edp_panel_on(intel_dp);
+	ironlake_edp_panel_vdd_off(intel_dp, true);
 	intel_dp_complete_link_train(intel_dp);
-
-	if (is_edp(intel_dp))
-		ironlake_edp_backlight_on(dev);
+	ironlake_edp_backlight_on(intel_dp);
 
 	intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
+
+	if (HAS_PCH_CPT(dev))
+		intel_cpt_verify_modeset(dev, intel_crtc->pipe);
 }
 
 static void
@@ -1034,28 +1292,30 @@
 	uint32_t dp_reg = I915_READ(intel_dp->output_reg);
 
 	if (mode != DRM_MODE_DPMS_ON) {
-		if (is_edp(intel_dp))
-			ironlake_edp_backlight_off(dev);
+		ironlake_edp_backlight_off(intel_dp);
+		ironlake_edp_panel_off(intel_dp);
+
+		ironlake_edp_panel_vdd_on(intel_dp);
 		intel_dp_sink_dpms(intel_dp, mode);
 		intel_dp_link_down(intel_dp);
-		if (is_edp(intel_dp))
-			ironlake_edp_panel_off(dev);
-		if (is_edp(intel_dp) && !is_pch_edp(intel_dp))
+		ironlake_edp_panel_vdd_off(intel_dp, false);
+
+		if (is_cpu_edp(intel_dp))
 			ironlake_edp_pll_off(encoder);
 	} else {
-		if (is_edp(intel_dp))
-			ironlake_edp_panel_vdd_on(intel_dp);
+		if (is_cpu_edp(intel_dp))
+			ironlake_edp_pll_on(encoder);
+
+		ironlake_edp_panel_vdd_on(intel_dp);
 		intel_dp_sink_dpms(intel_dp, mode);
 		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);
-			}
+			ironlake_edp_panel_on(intel_dp);
+			ironlake_edp_panel_vdd_off(intel_dp, true);
 			intel_dp_complete_link_train(intel_dp);
-		}
-		if (is_edp(intel_dp))
-			ironlake_edp_backlight_on(dev);
+		} else
+			ironlake_edp_panel_vdd_off(intel_dp, false);
+		ironlake_edp_backlight_on(intel_dp);
 	}
 	intel_dp->dpms_mode = mode;
 }
@@ -1090,11 +1350,11 @@
  * link status information
  */
 static bool
-intel_dp_get_link_status(struct intel_dp *intel_dp)
+intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
 	return intel_dp_aux_native_read_retry(intel_dp,
 					      DP_LANE0_1_STATUS,
-					      intel_dp->link_status,
+					      link_status,
 					      DP_LINK_STATUS_SIZE);
 }
 
@@ -1106,27 +1366,25 @@
 }
 
 static uint8_t
-intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE],
+intel_get_adjust_request_voltage(uint8_t adjust_request[2],
 				 int lane)
 {
-	int	    i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
 	int	    s = ((lane & 1) ?
 			 DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
 			 DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
-	uint8_t l = intel_dp_link_status(link_status, i);
+	uint8_t l = adjust_request[lane>>1];
 
 	return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
 }
 
 static uint8_t
-intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE],
+intel_get_adjust_request_pre_emphasis(uint8_t adjust_request[2],
 				      int lane)
 {
-	int	    i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
 	int	    s = ((lane & 1) ?
 			 DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
 			 DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
-	uint8_t l = intel_dp_link_status(link_status, i);
+	uint8_t l = adjust_request[lane>>1];
 
 	return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
 }
@@ -1148,34 +1406,63 @@
  * These are source-specific values; current Intel hardware supports
  * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
  */
-#define I830_DP_VOLTAGE_MAX	    DP_TRAIN_VOLTAGE_SWING_800
 
 static uint8_t
-intel_dp_pre_emphasis_max(uint8_t voltage_swing)
+intel_dp_voltage_max(struct intel_dp *intel_dp)
 {
-	switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
-	case DP_TRAIN_VOLTAGE_SWING_400:
-		return DP_TRAIN_PRE_EMPHASIS_6;
-	case DP_TRAIN_VOLTAGE_SWING_600:
-		return DP_TRAIN_PRE_EMPHASIS_6;
-	case DP_TRAIN_VOLTAGE_SWING_800:
-		return DP_TRAIN_PRE_EMPHASIS_3_5;
-	case DP_TRAIN_VOLTAGE_SWING_1200:
-	default:
-		return DP_TRAIN_PRE_EMPHASIS_0;
+	struct drm_device *dev = intel_dp->base.base.dev;
+
+	if (IS_GEN7(dev) && is_cpu_edp(intel_dp))
+		return DP_TRAIN_VOLTAGE_SWING_800;
+	else if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
+		return DP_TRAIN_VOLTAGE_SWING_1200;
+	else
+		return DP_TRAIN_VOLTAGE_SWING_800;
+}
+
+static uint8_t
+intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
+{
+	struct drm_device *dev = intel_dp->base.base.dev;
+
+	if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
+		case DP_TRAIN_VOLTAGE_SWING_400:
+			return DP_TRAIN_PRE_EMPHASIS_6;
+		case DP_TRAIN_VOLTAGE_SWING_600:
+		case DP_TRAIN_VOLTAGE_SWING_800:
+			return DP_TRAIN_PRE_EMPHASIS_3_5;
+		default:
+			return DP_TRAIN_PRE_EMPHASIS_0;
+		}
+	} else {
+		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
+		case DP_TRAIN_VOLTAGE_SWING_400:
+			return DP_TRAIN_PRE_EMPHASIS_6;
+		case DP_TRAIN_VOLTAGE_SWING_600:
+			return DP_TRAIN_PRE_EMPHASIS_6;
+		case DP_TRAIN_VOLTAGE_SWING_800:
+			return DP_TRAIN_PRE_EMPHASIS_3_5;
+		case DP_TRAIN_VOLTAGE_SWING_1200:
+		default:
+			return DP_TRAIN_PRE_EMPHASIS_0;
+		}
 	}
 }
 
 static void
-intel_get_adjust_train(struct intel_dp *intel_dp)
+intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
 	uint8_t v = 0;
 	uint8_t p = 0;
 	int lane;
+	uint8_t	*adjust_request = link_status + (DP_ADJUST_REQUEST_LANE0_1 - DP_LANE0_1_STATUS);
+	uint8_t voltage_max;
+	uint8_t preemph_max;
 
 	for (lane = 0; lane < intel_dp->lane_count; lane++) {
-		uint8_t this_v = intel_get_adjust_request_voltage(intel_dp->link_status, lane);
-		uint8_t this_p = intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane);
+		uint8_t this_v = intel_get_adjust_request_voltage(adjust_request, lane);
+		uint8_t this_p = intel_get_adjust_request_pre_emphasis(adjust_request, lane);
 
 		if (this_v > v)
 			v = this_v;
@@ -1183,18 +1470,20 @@
 			p = this_p;
 	}
 
-	if (v >= I830_DP_VOLTAGE_MAX)
-		v = I830_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED;
+	voltage_max = intel_dp_voltage_max(intel_dp);
+	if (v >= voltage_max)
+		v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
 
-	if (p >= intel_dp_pre_emphasis_max(v))
-		p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+	preemph_max = intel_dp_pre_emphasis_max(intel_dp, v);
+	if (p >= preemph_max)
+		p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
 
 	for (lane = 0; lane < 4; lane++)
 		intel_dp->train_set[lane] = v | p;
 }
 
 static uint32_t
-intel_dp_signal_levels(uint8_t train_set, int lane_count)
+intel_dp_signal_levels(uint8_t train_set)
 {
 	uint32_t	signal_levels = 0;
 
@@ -1259,13 +1548,43 @@
 	}
 }
 
+/* Gen7's DP voltage swing and pre-emphasis control */
+static uint32_t
+intel_gen7_edp_signal_levels(uint8_t train_set)
+{
+	int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
+					 DP_TRAIN_PRE_EMPHASIS_MASK);
+	switch (signal_levels) {
+	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0:
+		return EDP_LINK_TRAIN_400MV_0DB_IVB;
+	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5:
+		return EDP_LINK_TRAIN_400MV_3_5DB_IVB;
+	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
+		return EDP_LINK_TRAIN_400MV_6DB_IVB;
+
+	case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0:
+		return EDP_LINK_TRAIN_600MV_0DB_IVB;
+	case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
+		return EDP_LINK_TRAIN_600MV_3_5DB_IVB;
+
+	case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
+		return EDP_LINK_TRAIN_800MV_0DB_IVB;
+	case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5:
+		return EDP_LINK_TRAIN_800MV_3_5DB_IVB;
+
+	default:
+		DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:"
+			      "0x%x\n", signal_levels);
+		return EDP_LINK_TRAIN_500MV_0DB_IVB;
+	}
+}
+
 static uint8_t
 intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
 		      int lane)
 {
-	int i = DP_LANE0_1_STATUS + (lane >> 1);
 	int s = (lane & 1) * 4;
-	uint8_t l = intel_dp_link_status(link_status, i);
+	uint8_t l = link_status[lane>>1];
 
 	return (l >> s) & 0xf;
 }
@@ -1290,18 +1609,18 @@
 			 DP_LANE_CHANNEL_EQ_DONE|\
 			 DP_LANE_SYMBOL_LOCKED)
 static bool
-intel_channel_eq_ok(struct intel_dp *intel_dp)
+intel_channel_eq_ok(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
 	uint8_t lane_align;
 	uint8_t lane_status;
 	int lane;
 
-	lane_align = intel_dp_link_status(intel_dp->link_status,
+	lane_align = intel_dp_link_status(link_status,
 					  DP_LANE_ALIGN_STATUS_UPDATED);
 	if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
 		return false;
 	for (lane = 0; lane < intel_dp->lane_count; lane++) {
-		lane_status = intel_get_lane_status(intel_dp->link_status, lane);
+		lane_status = intel_get_lane_status(link_status, lane);
 		if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
 			return false;
 	}
@@ -1326,8 +1645,9 @@
 
 	ret = intel_dp_aux_native_write(intel_dp,
 					DP_TRAINING_LANE0_SET,
-					intel_dp->train_set, 4);
-	if (ret != 4)
+					intel_dp->train_set,
+					intel_dp->lane_count);
+	if (ret != intel_dp->lane_count)
 		return false;
 
 	return true;
@@ -1343,7 +1663,7 @@
 	int i;
 	uint8_t voltage;
 	bool clock_recovery = false;
-	int tries;
+	int voltage_tries, loop_tries;
 	u32 reg;
 	uint32_t DP = intel_dp->DP;
 
@@ -1364,26 +1684,35 @@
 				  DP_LINK_CONFIGURATION_SIZE);
 
 	DP |= DP_PORT_EN;
-	if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
+
+	if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
 		DP &= ~DP_LINK_TRAIN_MASK_CPT;
 	else
 		DP &= ~DP_LINK_TRAIN_MASK;
 	memset(intel_dp->train_set, 0, 4);
 	voltage = 0xff;
-	tries = 0;
+	voltage_tries = 0;
+	loop_tries = 0;
 	clock_recovery = false;
 	for (;;) {
 		/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
+		uint8_t	    link_status[DP_LINK_STATUS_SIZE];
 		uint32_t    signal_levels;
-		if (IS_GEN6(dev) && is_edp(intel_dp)) {
+
+
+		if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+			signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]);
+			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels;
+		} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
 			signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
 			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
 		} else {
-			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count);
+			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]);
+			DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n", signal_levels);
 			DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
 		}
 
-		if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
+		if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
 			reg = DP | DP_LINK_TRAIN_PAT_1_CPT;
 		else
 			reg = DP | DP_LINK_TRAIN_PAT_1;
@@ -1395,10 +1724,13 @@
 		/* Set training pattern 1 */
 
 		udelay(100);
-		if (!intel_dp_get_link_status(intel_dp))
+		if (!intel_dp_get_link_status(intel_dp, link_status)) {
+			DRM_ERROR("failed to get link status\n");
 			break;
+		}
 
-		if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
+		if (intel_clock_recovery_ok(link_status, intel_dp->lane_count)) {
+			DRM_DEBUG_KMS("clock recovery OK\n");
 			clock_recovery = true;
 			break;
 		}
@@ -1407,20 +1739,30 @@
 		for (i = 0; i < intel_dp->lane_count; i++)
 			if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
 				break;
-		if (i == intel_dp->lane_count)
-			break;
+		if (i == intel_dp->lane_count) {
+			++loop_tries;
+			if (loop_tries == 5) {
+				DRM_DEBUG_KMS("too many full retries, give up\n");
+				break;
+			}
+			memset(intel_dp->train_set, 0, 4);
+			voltage_tries = 0;
+			continue;
+		}
 
 		/* Check to see if we've tried the same voltage 5 times */
 		if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
-			++tries;
-			if (tries == 5)
+			++voltage_tries;
+			if (voltage_tries == 5) {
+				DRM_DEBUG_KMS("too many voltage retries, give up\n");
 				break;
+			}
 		} else
-			tries = 0;
+			voltage_tries = 0;
 		voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
 
 		/* Compute new intel_dp->train_set as requested by target */
-		intel_get_adjust_train(intel_dp);
+		intel_get_adjust_train(intel_dp, link_status);
 	}
 
 	intel_dp->DP = DP;
@@ -1443,6 +1785,7 @@
 	for (;;) {
 		/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
 		uint32_t    signal_levels;
+		uint8_t	    link_status[DP_LINK_STATUS_SIZE];
 
 		if (cr_tries > 5) {
 			DRM_ERROR("failed to train DP, aborting\n");
@@ -1450,15 +1793,18 @@
 			break;
 		}
 
-		if (IS_GEN6(dev) && is_edp(intel_dp)) {
+		if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+			signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]);
+			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels;
+		} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
 			signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
 			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
 		} else {
-			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count);
+			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]);
 			DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
 		}
 
-		if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
+		if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
 			reg = DP | DP_LINK_TRAIN_PAT_2_CPT;
 		else
 			reg = DP | DP_LINK_TRAIN_PAT_2;
@@ -1470,17 +1816,17 @@
 			break;
 
 		udelay(400);
-		if (!intel_dp_get_link_status(intel_dp))
+		if (!intel_dp_get_link_status(intel_dp, link_status))
 			break;
 
 		/* Make sure clock is still ok */
-		if (!intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
+		if (!intel_clock_recovery_ok(link_status, intel_dp->lane_count)) {
 			intel_dp_start_link_train(intel_dp);
 			cr_tries++;
 			continue;
 		}
 
-		if (intel_channel_eq_ok(intel_dp)) {
+		if (intel_channel_eq_ok(intel_dp, link_status)) {
 			channel_eq = true;
 			break;
 		}
@@ -1495,11 +1841,11 @@
 		}
 
 		/* Compute new intel_dp->train_set as requested by target */
-		intel_get_adjust_train(intel_dp);
+		intel_get_adjust_train(intel_dp, link_status);
 		++tries;
 	}
 
-	if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
+	if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
 		reg = DP | DP_LINK_TRAIN_OFF_CPT;
 	else
 		reg = DP | DP_LINK_TRAIN_OFF;
@@ -1529,7 +1875,7 @@
 		udelay(100);
 	}
 
-	if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) {
+	if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) {
 		DP &= ~DP_LINK_TRAIN_MASK_CPT;
 		I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
 	} else {
@@ -1540,8 +1886,12 @@
 
 	msleep(17);
 
-	if (is_edp(intel_dp))
-		DP |= DP_LINK_TRAIN_OFF;
+	if (is_edp(intel_dp)) {
+		if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
+			DP |= DP_LINK_TRAIN_OFF_CPT;
+		else
+			DP |= DP_LINK_TRAIN_OFF;
+	}
 
 	if (!HAS_PCH_CPT(dev) &&
 	    I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
@@ -1578,13 +1928,14 @@
 
 	I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
 	POSTING_READ(intel_dp->output_reg);
+	msleep(intel_dp->panel_power_down_delay);
 }
 
 static bool
 intel_dp_get_dpcd(struct intel_dp *intel_dp)
 {
 	if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd,
-					   sizeof (intel_dp->dpcd)) &&
+					   sizeof(intel_dp->dpcd)) &&
 	    (intel_dp->dpcd[DP_DPCD_REV] != 0)) {
 		return true;
 	}
@@ -1592,6 +1943,27 @@
 	return false;
 }
 
+static bool
+intel_dp_get_sink_irq(struct intel_dp *intel_dp, u8 *sink_irq_vector)
+{
+	int ret;
+
+	ret = intel_dp_aux_native_read_retry(intel_dp,
+					     DP_DEVICE_SERVICE_IRQ_VECTOR,
+					     sink_irq_vector, 1);
+	if (!ret)
+		return false;
+
+	return true;
+}
+
+static void
+intel_dp_handle_test_request(struct intel_dp *intel_dp)
+{
+	/* NAK by default */
+	intel_dp_aux_native_write_1(intel_dp, DP_TEST_RESPONSE, DP_TEST_ACK);
+}
+
 /*
  * According to DP spec
  * 5.1.2:
@@ -1604,6 +1976,9 @@
 static void
 intel_dp_check_link_status(struct intel_dp *intel_dp)
 {
+	u8 sink_irq_vector;
+	u8 link_status[DP_LINK_STATUS_SIZE];
+
 	if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON)
 		return;
 
@@ -1611,7 +1986,7 @@
 		return;
 
 	/* Try to read receiver status if the link appears to be up */
-	if (!intel_dp_get_link_status(intel_dp)) {
+	if (!intel_dp_get_link_status(intel_dp, link_status)) {
 		intel_dp_link_down(intel_dp);
 		return;
 	}
@@ -1622,7 +1997,21 @@
 		return;
 	}
 
-	if (!intel_channel_eq_ok(intel_dp)) {
+	/* Try to read the source of the interrupt */
+	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
+	    intel_dp_get_sink_irq(intel_dp, &sink_irq_vector)) {
+		/* Clear interrupt source */
+		intel_dp_aux_native_write_1(intel_dp,
+					    DP_DEVICE_SERVICE_IRQ_VECTOR,
+					    sink_irq_vector);
+
+		if (sink_irq_vector & DP_AUTOMATED_TEST_REQUEST)
+			intel_dp_handle_test_request(intel_dp);
+		if (sink_irq_vector & (DP_CP_IRQ | DP_SINK_SPECIFIC_IRQ))
+			DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
+	}
+
+	if (!intel_channel_eq_ok(intel_dp, link_status)) {
 		DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
 			      drm_get_encoder_name(&intel_dp->base.base));
 		intel_dp_start_link_train(intel_dp);
@@ -1683,6 +2072,31 @@
 	return intel_dp_detect_dpcd(intel_dp);
 }
 
+static struct edid *
+intel_dp_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
+{
+	struct intel_dp *intel_dp = intel_attached_dp(connector);
+	struct edid	*edid;
+
+	ironlake_edp_panel_vdd_on(intel_dp);
+	edid = drm_get_edid(connector, adapter);
+	ironlake_edp_panel_vdd_off(intel_dp, false);
+	return edid;
+}
+
+static int
+intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter *adapter)
+{
+	struct intel_dp *intel_dp = intel_attached_dp(connector);
+	int	ret;
+
+	ironlake_edp_panel_vdd_on(intel_dp);
+	ret = intel_ddc_get_modes(connector, adapter);
+	ironlake_edp_panel_vdd_off(intel_dp, false);
+	return ret;
+}
+
+
 /**
  * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
  *
@@ -1715,7 +2129,7 @@
 	if (intel_dp->force_audio) {
 		intel_dp->has_audio = intel_dp->force_audio > 0;
 	} else {
-		edid = drm_get_edid(connector, &intel_dp->adapter);
+		edid = intel_dp_get_edid(connector, &intel_dp->adapter);
 		if (edid) {
 			intel_dp->has_audio = drm_detect_monitor_audio(edid);
 			connector->display_info.raw_edid = NULL;
@@ -1736,28 +2150,36 @@
 	/* We should parse the EDID data and find out if it has an audio sink
 	 */
 
-	ret = intel_ddc_get_modes(connector, &intel_dp->adapter);
+	ret = intel_dp_get_edid_modes(connector, &intel_dp->adapter);
 	if (ret) {
-		if (is_edp(intel_dp) && !dev_priv->panel_fixed_mode) {
+		if (is_edp(intel_dp) && !intel_dp->panel_fixed_mode) {
 			struct drm_display_mode *newmode;
 			list_for_each_entry(newmode, &connector->probed_modes,
 					    head) {
-				if (newmode->type & DRM_MODE_TYPE_PREFERRED) {
-					dev_priv->panel_fixed_mode =
+				if ((newmode->type & DRM_MODE_TYPE_PREFERRED)) {
+					intel_dp->panel_fixed_mode =
 						drm_mode_duplicate(dev, newmode);
 					break;
 				}
 			}
 		}
-
 		return ret;
 	}
 
 	/* if eDP has no EDID, try to use fixed panel mode from VBT */
 	if (is_edp(intel_dp)) {
-		if (dev_priv->panel_fixed_mode != NULL) {
+		/* initialize panel mode from VBT if available for eDP */
+		if (intel_dp->panel_fixed_mode == NULL && dev_priv->lfp_lvds_vbt_mode != NULL) {
+			intel_dp->panel_fixed_mode =
+				drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
+			if (intel_dp->panel_fixed_mode) {
+				intel_dp->panel_fixed_mode->type |=
+					DRM_MODE_TYPE_PREFERRED;
+			}
+		}
+		if (intel_dp->panel_fixed_mode) {
 			struct drm_display_mode *mode;
-			mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
+			mode = drm_mode_duplicate(dev, intel_dp->panel_fixed_mode);
 			drm_mode_probed_add(connector, mode);
 			return 1;
 		}
@@ -1772,7 +2194,7 @@
 	struct edid *edid;
 	bool has_audio = false;
 
-	edid = drm_get_edid(connector, &intel_dp->adapter);
+	edid = intel_dp_get_edid(connector, &intel_dp->adapter);
 	if (edid) {
 		has_audio = drm_detect_monitor_audio(edid);
 
@@ -1839,7 +2261,7 @@
 }
 
 static void
-intel_dp_destroy (struct drm_connector *connector)
+intel_dp_destroy(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
 
@@ -1857,6 +2279,10 @@
 
 	i2c_del_adapter(&intel_dp->adapter);
 	drm_encoder_cleanup(encoder);
+	if (is_edp(intel_dp)) {
+		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+		ironlake_panel_vdd_off_sync(intel_dp);
+	}
 	kfree(intel_dp);
 }
 
@@ -1896,7 +2322,7 @@
 
 /* Return which DP Port should be selected for Transcoder DP control */
 int
-intel_trans_dp_port_sel (struct drm_crtc *crtc)
+intel_trans_dp_port_sel(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_mode_config *mode_config = &dev->mode_config;
@@ -1909,7 +2335,8 @@
 			continue;
 
 		intel_dp = enc_to_intel_dp(encoder);
-		if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT)
+		if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT ||
+		    intel_dp->base.type == INTEL_OUTPUT_EDP)
 			return intel_dp->output_reg;
 	}
 
@@ -1993,10 +2420,13 @@
 	else if (output_reg == DP_D || output_reg == PCH_DP_D)
 		intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
 
-	if (is_edp(intel_dp))
+	if (is_edp(intel_dp)) {
 		intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
+		INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
+				  ironlake_panel_vdd_work);
+	}
 
-	intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
+	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 	connector->interlace_allowed = true;
 	connector->doublescan_allowed = 0;
 
@@ -2032,25 +2462,59 @@
 			break;
 	}
 
-	intel_dp_i2c_init(intel_dp, intel_connector, name);
-
 	/* Cache some DPCD data in the eDP case */
 	if (is_edp(intel_dp)) {
 		bool ret;
-		u32 pp_on, pp_div;
+		struct edp_power_seq	cur, vbt;
+		u32 pp_on, pp_off, pp_div;
 
 		pp_on = I915_READ(PCH_PP_ON_DELAYS);
+		pp_off = I915_READ(PCH_PP_OFF_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 */
+		/* Pull timing values out of registers */
+		cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
+			PANEL_POWER_UP_DELAY_SHIFT;
+
+		cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >>
+			PANEL_LIGHT_ON_DELAY_SHIFT;
+
+		cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >>
+			PANEL_LIGHT_OFF_DELAY_SHIFT;
+
+		cur.t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >>
+			PANEL_POWER_DOWN_DELAY_SHIFT;
+
+		cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >>
+			       PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000;
+
+		DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
+			      cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12);
+
+		vbt = dev_priv->edp.pps;
+
+		DRM_DEBUG_KMS("vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
+			      vbt.t1_t3, vbt.t8, vbt.t9, vbt.t10, vbt.t11_t12);
+
+#define get_delay(field)	((max(cur.field, vbt.field) + 9) / 10)
+
+		intel_dp->panel_power_up_delay = get_delay(t1_t3);
+		intel_dp->backlight_on_delay = get_delay(t8);
+		intel_dp->backlight_off_delay = get_delay(t9);
+		intel_dp->panel_power_down_delay = get_delay(t10);
+		intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
+
+		DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
+			      intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
+			      intel_dp->panel_power_cycle_delay);
+
+		DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
+			      intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
 
 		ironlake_edp_panel_vdd_on(intel_dp);
 		ret = intel_dp_get_dpcd(intel_dp);
-		ironlake_edp_panel_vdd_off(intel_dp);
+		ironlake_edp_panel_vdd_off(intel_dp, false);
+
 		if (ret) {
 			if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
 				dev_priv->no_aux_handshake =
@@ -2065,18 +2529,11 @@
 		}
 	}
 
+	intel_dp_i2c_init(intel_dp, intel_connector, name);
+
 	intel_encoder->hot_plug = intel_dp_hot_plug;
 
 	if (is_edp(intel_dp)) {
-		/* initialize panel mode from VBT if available for eDP */
-		if (dev_priv->lfp_lvds_vbt_mode) {
-			dev_priv->panel_fixed_mode =
-				drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
-			if (dev_priv->panel_fixed_mode) {
-				dev_priv->panel_fixed_mode->type |=
-					DRM_MODE_TYPE_PREFERRED;
-			}
-		}
 		dev_priv->int_edp_connector = connector;
 		intel_panel_setup_backlight(dev);
 	}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_drv.h linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_drv.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_drv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_drv.h	2012-01-04 18:55:44.000000000 -0500
@@ -34,7 +34,7 @@
 #define _wait_for(COND, MS, W) ({ \
 	unsigned long timeout__ = jiffies + msecs_to_jiffies(MS);	\
 	int ret__ = 0;							\
-	while (! (COND)) {						\
+	while (!(COND)) {						\
 		if (time_after(jiffies, timeout__)) {			\
 			ret__ = -ETIMEDOUT;				\
 			break;						\
@@ -49,10 +49,10 @@
 
 #define MSLEEP(x) do { \
 	if (in_dbg_master()) \
-	       	mdelay(x); \
+		mdelay(x); \
 	else \
 		msleep(x); \
-} while(0)
+} while (0)
 
 #define KHz(x) (1000*x)
 #define MHz(x) KHz(1000*x)
@@ -110,6 +110,7 @@
 /* drm_display_mode->private_flags */
 #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0)
 #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT)
+#define INTEL_MODE_DP_FORCE_6BPC (0x10)
 
 static inline void
 intel_mode_set_pixel_multiplier(struct drm_display_mode *mode,
@@ -171,6 +172,9 @@
 	int16_t cursor_width, cursor_height;
 	bool cursor_visible;
 	unsigned int bpp;
+
+	bool no_pll; /* tertiary pipe for IVB */
+	bool use_pll_a;
 };
 
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
@@ -184,7 +188,7 @@
 #define DIP_VERSION_AVI 0x2
 #define DIP_LEN_AVI     13
 
-#define DIP_TYPE_SPD	0x3
+#define DIP_TYPE_SPD	0x83
 #define DIP_VERSION_SPD	0x1
 #define DIP_LEN_SPD	25
 #define DIP_SPD_UNKNOWN	0
@@ -284,7 +288,7 @@
 intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 		 struct drm_display_mode *adjusted_mode);
 extern bool intel_dpd_is_edp(struct drm_device *dev);
-extern void intel_edp_link_config (struct intel_encoder *, int *, int *);
+extern void intel_edp_link_config(struct intel_encoder *, int *, int *);
 extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
 
 /* intel_panel.c */
@@ -304,8 +308,8 @@
 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);
-extern void intel_encoder_commit (struct drm_encoder *encoder);
+extern void intel_encoder_prepare(struct drm_encoder *encoder);
+extern void intel_encoder_commit(struct drm_encoder *encoder);
 extern void intel_encoder_destroy(struct drm_encoder *encoder);
 
 static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector)
@@ -377,4 +381,8 @@
 extern void intel_fb_restore_mode(struct drm_device *dev);
 
 extern void intel_init_clock_gating(struct drm_device *dev);
+extern void intel_write_eld(struct drm_encoder *encoder,
+			    struct drm_display_mode *mode);
+extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe);
+
 #endif /* __INTEL_DRV_H__ */
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_hdmi.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_hdmi.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_hdmi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_hdmi.c	2012-01-04 18:55:44.000000000 -0500
@@ -69,8 +69,7 @@
 	frame->checksum = 0;
 	frame->ecc = 0;
 
-	/* Header isn't part of the checksum */
-	for (i = 5; i < frame->len; i++)
+	for (i = 0; i < frame->len + DIP_HEADER_SIZE; i++)
 		sum += data[i];
 
 	frame->checksum = 0x100 - sum;
@@ -104,7 +103,7 @@
 		flags |= VIDEO_DIP_ENABLE_AVI | VIDEO_DIP_FREQ_VSYNC;
 		break;
 	case DIP_TYPE_SPD:
-		flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_2VSYNC;
+		flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_VSYNC;
 		break;
 	default:
 		DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
@@ -165,9 +164,9 @@
 
 	flags = intel_infoframe_index(frame);
 
-	val &= ~VIDEO_DIP_SELECT_MASK;
+	val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
 
-	I915_WRITE(reg, val | flags);
+	I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
 
 	for (i = 0; i < len; i += 4) {
 		I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
@@ -245,16 +244,17 @@
 		sdvox |= HDMI_MODE_SELECT;
 
 	if (intel_hdmi->has_audio) {
+		DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n",
+				 pipe_name(intel_crtc->pipe));
 		sdvox |= SDVO_AUDIO_ENABLE;
 		sdvox |= SDVO_NULL_PACKETS_DURING_VSYNC;
+		intel_write_eld(encoder, adjusted_mode);
 	}
 
-	if (intel_crtc->pipe == 1) {
-		if (HAS_PCH_CPT(dev))
-			sdvox |= PORT_TRANS_B_SEL_CPT;
-		else
-			sdvox |= SDVO_PIPE_B_SELECT;
-	}
+	if (HAS_PCH_CPT(dev))
+		sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
+	else if (intel_crtc->pipe == 1)
+		sdvox |= SDVO_PIPE_B_SELECT;
 
 	I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
 	POSTING_READ(intel_hdmi->sdvox_reg);
@@ -486,6 +486,7 @@
 	struct intel_encoder *intel_encoder;
 	struct intel_connector *intel_connector;
 	struct intel_hdmi *intel_hdmi;
+	int i;
 
 	intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL);
 	if (!intel_hdmi)
@@ -511,7 +512,7 @@
 	connector->polled = DRM_CONNECTOR_POLL_HPD;
 	connector->interlace_allowed = 0;
 	connector->doublescan_allowed = 0;
-	intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
+	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
 	/* Set up the DDC bus. */
 	if (sdvox_reg == SDVOB) {
@@ -538,10 +539,14 @@
 
 	intel_hdmi->sdvox_reg = sdvox_reg;
 
-	if (!HAS_PCH_SPLIT(dev))
+	if (!HAS_PCH_SPLIT(dev)) {
 		intel_hdmi->write_infoframe = i9xx_write_infoframe;
-	else
+		I915_WRITE(VIDEO_DIP_CTL, 0);
+	} else {
 		intel_hdmi->write_infoframe = ironlake_write_infoframe;
+		for_each_pipe(i)
+			I915_WRITE(TVIDEO_DIP_CTL(i), 0);
+	}
 
 	drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_i2c.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_i2c.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
  */
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
+#include <linux/export.h>
 #include "drmP.h"
 #include "drm.h"
 #include "intel_drv.h"
@@ -422,13 +423,7 @@
 {
 	struct intel_gmbus *bus = to_intel_gmbus(adapter);
 
-	/* speed:
-	 * 0x0 = 100 KHz
-	 * 0x1 = 50 KHz
-	 * 0x2 = 400 KHz
-	 * 0x3 = 1000 Khz
-	 */
-	bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | (speed << 8);
+	bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | speed;
 }
 
 void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_lvds.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_lvds.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_lvds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_lvds.c	2012-01-04 18:55:44.000000000 -0500
@@ -715,6 +715,14 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"),
 		},
 	},
+	{
+		.callback = intel_no_lvds_dmi_callback,
+		.ident = "Asus AT5NM10T-I",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"),
+		},
+	},
 
 	{ }	/* terminating entry */
 };
@@ -888,9 +896,11 @@
 	intel_encoder->type = INTEL_OUTPUT_LVDS;
 
 	intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
-	intel_encoder->crtc_mask = (1 << 1);
-	if (INTEL_INFO(dev)->gen >= 5)
-		intel_encoder->crtc_mask |= (1 << 0);
+	if (HAS_PCH_SPLIT(dev))
+		intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
+	else
+		intel_encoder->crtc_mask = (1 << 1);
+
 	drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
 	drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
 	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_modes.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_modes.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_modes.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_modes.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/fb.h>
+#include <drm/drm_edid.h>
 #include "drmP.h"
 #include "intel_drv.h"
 #include "i915_drv.h"
@@ -74,6 +75,7 @@
 	if (edid) {
 		drm_mode_connector_update_edid_property(connector, edid);
 		ret = drm_add_edid_modes(connector, edid);
+		drm_edid_to_eld(connector, edid);
 		connector->display_info.raw_edid = NULL;
 		kfree(edid);
 	}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_opregion.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_opregion.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_opregion.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_opregion.c	2012-01-04 18:55:44.000000000 -0500
@@ -51,61 +51,61 @@
 #define MBOX_ASLE      (1<<2)
 
 struct opregion_header {
-       u8 signature[16];
-       u32 size;
-       u32 opregion_ver;
-       u8 bios_ver[32];
-       u8 vbios_ver[16];
-       u8 driver_ver[16];
-       u32 mboxes;
-       u8 reserved[164];
+	u8 signature[16];
+	u32 size;
+	u32 opregion_ver;
+	u8 bios_ver[32];
+	u8 vbios_ver[16];
+	u8 driver_ver[16];
+	u32 mboxes;
+	u8 reserved[164];
 } __attribute__((packed));
 
 /* OpRegion mailbox #1: public ACPI methods */
 struct opregion_acpi {
-       u32 drdy;       /* driver readiness */
-       u32 csts;       /* notification status */
-       u32 cevt;       /* current event */
-       u8 rsvd1[20];
-       u32 didl[8];    /* supported display devices ID list */
-       u32 cpdl[8];    /* currently presented display list */
-       u32 cadl[8];    /* currently active display list */
-       u32 nadl[8];    /* next active devices list */
-       u32 aslp;       /* ASL sleep time-out */
-       u32 tidx;       /* toggle table index */
-       u32 chpd;       /* current hotplug enable indicator */
-       u32 clid;       /* current lid state*/
-       u32 cdck;       /* current docking state */
-       u32 sxsw;       /* Sx state resume */
-       u32 evts;       /* ASL supported events */
-       u32 cnot;       /* current OS notification */
-       u32 nrdy;       /* driver status */
-       u8 rsvd2[60];
+	u32 drdy;       /* driver readiness */
+	u32 csts;       /* notification status */
+	u32 cevt;       /* current event */
+	u8 rsvd1[20];
+	u32 didl[8];    /* supported display devices ID list */
+	u32 cpdl[8];    /* currently presented display list */
+	u32 cadl[8];    /* currently active display list */
+	u32 nadl[8];    /* next active devices list */
+	u32 aslp;       /* ASL sleep time-out */
+	u32 tidx;       /* toggle table index */
+	u32 chpd;       /* current hotplug enable indicator */
+	u32 clid;       /* current lid state*/
+	u32 cdck;       /* current docking state */
+	u32 sxsw;       /* Sx state resume */
+	u32 evts;       /* ASL supported events */
+	u32 cnot;       /* current OS notification */
+	u32 nrdy;       /* driver status */
+	u8 rsvd2[60];
 } __attribute__((packed));
 
 /* OpRegion mailbox #2: SWSCI */
 struct opregion_swsci {
-       u32 scic;       /* SWSCI command|status|data */
-       u32 parm;       /* command parameters */
-       u32 dslp;       /* driver sleep time-out */
-       u8 rsvd[244];
+	u32 scic;       /* SWSCI command|status|data */
+	u32 parm;       /* command parameters */
+	u32 dslp;       /* driver sleep time-out */
+	u8 rsvd[244];
 } __attribute__((packed));
 
 /* OpRegion mailbox #3: ASLE */
 struct opregion_asle {
-       u32 ardy;       /* driver readiness */
-       u32 aslc;       /* ASLE interrupt command */
-       u32 tche;       /* technology enabled indicator */
-       u32 alsi;       /* current ALS illuminance reading */
-       u32 bclp;       /* backlight brightness to set */
-       u32 pfit;       /* panel fitting state */
-       u32 cblv;       /* current brightness level */
-       u16 bclm[20];   /* backlight level duty cycle mapping table */
-       u32 cpfm;       /* current panel fitting mode */
-       u32 epfm;       /* enabled panel fitting modes */
-       u8 plut[74];    /* panel LUT and identifier */
-       u32 pfmb;       /* PWM freq and min brightness */
-       u8 rsvd[102];
+	u32 ardy;       /* driver readiness */
+	u32 aslc;       /* ASLE interrupt command */
+	u32 tche;       /* technology enabled indicator */
+	u32 alsi;       /* current ALS illuminance reading */
+	u32 bclp;       /* backlight brightness to set */
+	u32 pfit;       /* panel fitting state */
+	u32 cblv;       /* current brightness level */
+	u16 bclm[20];   /* backlight level duty cycle mapping table */
+	u32 cpfm;       /* current panel fitting mode */
+	u32 epfm;       /* enabled panel fitting modes */
+	u8 plut[74];    /* panel LUT and identifier */
+	u32 pfmb;       /* PWM freq and min brightness */
+	u8 rsvd[102];
 } __attribute__((packed));
 
 /* ASLE irq request bits */
@@ -361,7 +361,7 @@
 
 	list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) {
 		if (i >= 8) {
-			dev_printk (KERN_ERR, &dev->pdev->dev,
+			dev_printk(KERN_ERR, &dev->pdev->dev,
 				    "More than 8 outputs detected\n");
 			return;
 		}
@@ -387,7 +387,7 @@
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		int output_type = ACPI_OTHER_OUTPUT;
 		if (i >= 8) {
-			dev_printk (KERN_ERR, &dev->pdev->dev,
+			dev_printk(KERN_ERR, &dev->pdev->dev,
 				    "More than 8 outputs detected\n");
 			return;
 		}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_overlay.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_overlay.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_overlay.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_overlay.c	2012-01-04 18:55:44.000000000 -0500
@@ -117,57 +117,57 @@
 
 /* memory bufferd overlay registers */
 struct overlay_registers {
-    u32 OBUF_0Y;
-    u32 OBUF_1Y;
-    u32 OBUF_0U;
-    u32 OBUF_0V;
-    u32 OBUF_1U;
-    u32 OBUF_1V;
-    u32 OSTRIDE;
-    u32 YRGB_VPH;
-    u32 UV_VPH;
-    u32 HORZ_PH;
-    u32 INIT_PHS;
-    u32 DWINPOS;
-    u32 DWINSZ;
-    u32 SWIDTH;
-    u32 SWIDTHSW;
-    u32 SHEIGHT;
-    u32 YRGBSCALE;
-    u32 UVSCALE;
-    u32 OCLRC0;
-    u32 OCLRC1;
-    u32 DCLRKV;
-    u32 DCLRKM;
-    u32 SCLRKVH;
-    u32 SCLRKVL;
-    u32 SCLRKEN;
-    u32 OCONFIG;
-    u32 OCMD;
-    u32 RESERVED1; /* 0x6C */
-    u32 OSTART_0Y;
-    u32 OSTART_1Y;
-    u32 OSTART_0U;
-    u32 OSTART_0V;
-    u32 OSTART_1U;
-    u32 OSTART_1V;
-    u32 OTILEOFF_0Y;
-    u32 OTILEOFF_1Y;
-    u32 OTILEOFF_0U;
-    u32 OTILEOFF_0V;
-    u32 OTILEOFF_1U;
-    u32 OTILEOFF_1V;
-    u32 FASTHSCALE; /* 0xA0 */
-    u32 UVSCALEV; /* 0xA4 */
-    u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
-    u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
-    u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
-    u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
-    u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
-    u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
-    u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
-    u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
-    u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
+	u32 OBUF_0Y;
+	u32 OBUF_1Y;
+	u32 OBUF_0U;
+	u32 OBUF_0V;
+	u32 OBUF_1U;
+	u32 OBUF_1V;
+	u32 OSTRIDE;
+	u32 YRGB_VPH;
+	u32 UV_VPH;
+	u32 HORZ_PH;
+	u32 INIT_PHS;
+	u32 DWINPOS;
+	u32 DWINSZ;
+	u32 SWIDTH;
+	u32 SWIDTHSW;
+	u32 SHEIGHT;
+	u32 YRGBSCALE;
+	u32 UVSCALE;
+	u32 OCLRC0;
+	u32 OCLRC1;
+	u32 DCLRKV;
+	u32 DCLRKM;
+	u32 SCLRKVH;
+	u32 SCLRKVL;
+	u32 SCLRKEN;
+	u32 OCONFIG;
+	u32 OCMD;
+	u32 RESERVED1; /* 0x6C */
+	u32 OSTART_0Y;
+	u32 OSTART_1Y;
+	u32 OSTART_0U;
+	u32 OSTART_0V;
+	u32 OSTART_1U;
+	u32 OSTART_1V;
+	u32 OTILEOFF_0Y;
+	u32 OTILEOFF_1Y;
+	u32 OTILEOFF_0U;
+	u32 OTILEOFF_0V;
+	u32 OTILEOFF_1U;
+	u32 OTILEOFF_1V;
+	u32 FASTHSCALE; /* 0xA0 */
+	u32 UVSCALEV; /* 0xA4 */
+	u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
+	u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
+	u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
+	u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
+	u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
+	u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
+	u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
+	u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
+	u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
 };
 
 struct intel_overlay {
@@ -192,7 +192,7 @@
 static struct overlay_registers *
 intel_overlay_map_regs(struct intel_overlay *overlay)
 {
-        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
+	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
 	struct overlay_registers *regs;
 
 	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
@@ -264,7 +264,7 @@
 
 	mode = drm_mode_duplicate(dev, &vesa_640x480);
 	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
-	if(!drm_crtc_helper_set_mode(&crtc->base, mode,
+	if (!drm_crtc_helper_set_mode(&crtc->base, mode,
 				       crtc->base.x, crtc->base.y,
 				       crtc->base.fb))
 		return 0;
@@ -332,7 +332,7 @@
 				  bool load_polyphase_filter)
 {
 	struct drm_device *dev = overlay->dev;
-        drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_request *request;
 	u32 flip_addr = overlay->flip_addr;
 	u32 tmp;
@@ -359,7 +359,7 @@
 	}
 	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
 	OUT_RING(flip_addr);
-        ADVANCE_LP_RING();
+	ADVANCE_LP_RING();
 
 	ret = i915_add_request(LP_RING(dev_priv), NULL, request);
 	if (ret) {
@@ -583,7 +583,7 @@
 	ret = ((offset + width + mask) >> shift) - (offset >> shift);
 	if (!IS_GEN2(dev))
 		ret <<= 1;
-	ret -=1;
+	ret -= 1;
 	return ret << 2;
 }
 
@@ -817,7 +817,7 @@
 	regs->SWIDTHSW = calc_swidthsw(overlay->dev,
 				       params->offset_Y, tmp_width);
 	regs->SHEIGHT = params->src_h;
-	regs->OBUF_0Y = new_bo->gtt_offset + params-> offset_Y;
+	regs->OBUF_0Y = new_bo->gtt_offset + params->offset_Y;
 	regs->OSTRIDE = params->stride_Y;
 
 	if (params->format & I915_OVERLAY_YUV_PLANAR) {
@@ -917,7 +917,7 @@
 	 * line with the intel documentation for the i965
 	 */
 	if (INTEL_INFO(dev)->gen >= 4) {
-	       	/* on i965 use the PGM reg to read out the autoscaler values */
+		/* on i965 use the PGM reg to read out the autoscaler values */
 		ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
 	} else {
 		if (pfit_control & VERT_AUTO_SCALE)
@@ -1098,7 +1098,7 @@
 }
 
 int intel_overlay_put_image(struct drm_device *dev, void *data,
-                            struct drm_file *file_priv)
+			    struct drm_file *file_priv)
 {
 	struct drm_intel_overlay_put_image *put_image_rec = data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -1301,10 +1301,10 @@
 }
 
 int intel_overlay_attrs(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
+			struct drm_file *file_priv)
 {
 	struct drm_intel_overlay_attrs *attrs = data;
-        drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_overlay *overlay;
 	struct overlay_registers *regs;
 	int ret;
@@ -1393,7 +1393,7 @@
 
 void intel_setup_overlay(struct drm_device *dev)
 {
-        drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_overlay *overlay;
 	struct drm_i915_gem_object *reg_bo;
 	struct overlay_registers *regs;
@@ -1421,24 +1421,24 @@
 		ret = i915_gem_attach_phys_object(dev, reg_bo,
 						  I915_GEM_PHYS_OVERLAY_REGS,
 						  PAGE_SIZE);
-                if (ret) {
-                        DRM_ERROR("failed to attach phys overlay regs\n");
-                        goto out_free_bo;
-                }
+		if (ret) {
+			DRM_ERROR("failed to attach phys overlay regs\n");
+			goto out_free_bo;
+		}
 		overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
 	} else {
 		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true);
 		if (ret) {
-                        DRM_ERROR("failed to pin overlay register bo\n");
-                        goto out_free_bo;
-                }
+			DRM_ERROR("failed to pin overlay register bo\n");
+			goto out_free_bo;
+		}
 		overlay->flip_addr = reg_bo->gtt_offset;
 
 		ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
 		if (ret) {
-                        DRM_ERROR("failed to move overlay register bo into the GTT\n");
-                        goto out_unpin_bo;
-                }
+			DRM_ERROR("failed to move overlay register bo into the GTT\n");
+			goto out_unpin_bo;
+		}
 	}
 
 	/* init all values */
@@ -1525,7 +1525,7 @@
 struct intel_overlay_error_state *
 intel_overlay_capture_error_state(struct drm_device *dev)
 {
-        drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_overlay *overlay = dev_priv->overlay;
 	struct intel_overlay_error_state *error;
 	struct overlay_registers __iomem *regs;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_panel.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_panel.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_panel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_panel.c	2012-01-04 18:55:44.000000000 -0500
@@ -84,7 +84,7 @@
 			if (scaled_width > scaled_height) { /* pillar */
 				width = scaled_height / mode->vdisplay;
 				if (width & 1)
-				    	width++;
+					width++;
 				x = (adjusted_mode->hdisplay - width + 1) / 2;
 				y = 0;
 				height = adjusted_mode->vdisplay;
@@ -178,13 +178,10 @@
 	if (HAS_PCH_SPLIT(dev)) {
 		max >>= 16;
 	} else {
-		if (IS_PINEVIEW(dev)) {
+		if (INTEL_INFO(dev)->gen < 4)
 			max >>= 17;
-		} else {
+		else
 			max >>= 16;
-			if (INTEL_INFO(dev)->gen < 4)
-				max &= ~1;
-		}
 
 		if (is_backlight_combination_mode(dev))
 			max *= 0xff;
@@ -203,13 +200,12 @@
 		val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
 	} else {
 		val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
-		if (IS_PINEVIEW(dev))
+		if (INTEL_INFO(dev)->gen < 4)
 			val >>= 1;
 
-		if (is_backlight_combination_mode(dev)){
+		if (is_backlight_combination_mode(dev)) {
 			u8 lbpc;
 
-			val &= ~1;
 			pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
 			val *= lbpc;
 		}
@@ -226,7 +222,7 @@
 	I915_WRITE(BLC_PWM_CPU_CTL, val | level);
 }
 
-void intel_panel_set_backlight(struct drm_device *dev, u32 level)
+static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 tmp;
@@ -236,7 +232,7 @@
 	if (HAS_PCH_SPLIT(dev))
 		return intel_pch_panel_set_backlight(dev, level);
 
-	if (is_backlight_combination_mode(dev)){
+	if (is_backlight_combination_mode(dev)) {
 		u32 max = intel_panel_get_max_backlight(dev);
 		u8 lbpc;
 
@@ -246,24 +242,27 @@
 	}
 
 	tmp = I915_READ(BLC_PWM_CTL);
-	if (IS_PINEVIEW(dev)) {
-		tmp &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1);
+	if (INTEL_INFO(dev)->gen < 4) 
 		level <<= 1;
-	} else
-		tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
+	tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
 	I915_WRITE(BLC_PWM_CTL, tmp | level);
 }
 
-void intel_panel_disable_backlight(struct drm_device *dev)
+void intel_panel_set_backlight(struct drm_device *dev, u32 level)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (dev_priv->backlight_enabled) {
-		dev_priv->backlight_level = intel_panel_get_backlight(dev);
-		dev_priv->backlight_enabled = false;
-	}
+	dev_priv->backlight_level = level;
+	if (dev_priv->backlight_enabled)
+		intel_panel_actually_set_backlight(dev, level);
+}
 
-	intel_panel_set_backlight(dev, 0);
+void intel_panel_disable_backlight(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	dev_priv->backlight_enabled = false;
+	intel_panel_actually_set_backlight(dev, 0);
 }
 
 void intel_panel_enable_backlight(struct drm_device *dev)
@@ -273,8 +272,8 @@
 	if (dev_priv->backlight_level == 0)
 		dev_priv->backlight_level = intel_panel_get_max_backlight(dev);
 
-	intel_panel_set_backlight(dev, dev_priv->backlight_level);
 	dev_priv->backlight_enabled = true;
+	intel_panel_actually_set_backlight(dev, dev_priv->backlight_level);
 }
 
 static void intel_panel_init_backlight(struct drm_device *dev)
@@ -321,7 +320,8 @@
 static int intel_panel_get_brightness(struct backlight_device *bd)
 {
 	struct drm_device *dev = bl_get_data(bd);
-	return intel_panel_get_backlight(dev);
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	return dev_priv->backlight_level;
 }
 
 static const struct backlight_ops intel_panel_bl_ops = {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,16 @@
 #include "i915_trace.h"
 #include "intel_drv.h"
 
+/*
+ * 965+ support PIPE_CONTROL commands, which provide finer grained control
+ * over cache flushing.
+ */
+struct pipe_control {
+	struct drm_i915_gem_object *obj;
+	volatile u32 *cpu_page;
+	u32 gtt_offset;
+};
+
 static inline int ring_space(struct intel_ring_buffer *ring)
 {
 	int space = (ring->head & HEAD_ADDR) - (ring->tail + 8);
@@ -123,6 +133,118 @@
 	return 0;
 }
 
+/**
+ * Emits a PIPE_CONTROL with a non-zero post-sync operation, for
+ * implementing two workarounds on gen6.  From section 1.4.7.1
+ * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1:
+ *
+ * [DevSNB-C+{W/A}] Before any depth stall flush (including those
+ * produced by non-pipelined state commands), software needs to first
+ * send a PIPE_CONTROL with no bits set except Post-Sync Operation !=
+ * 0.
+ *
+ * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable
+ * =1, a PIPE_CONTROL with any non-zero post-sync-op is required.
+ *
+ * And the workaround for these two requires this workaround first:
+ *
+ * [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent
+ * BEFORE the pipe-control with a post-sync op and no write-cache
+ * flushes.
+ *
+ * And this last workaround is tricky because of the requirements on
+ * that bit.  From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM
+ * volume 2 part 1:
+ *
+ *     "1 of the following must also be set:
+ *      - Render Target Cache Flush Enable ([12] of DW1)
+ *      - Depth Cache Flush Enable ([0] of DW1)
+ *      - Stall at Pixel Scoreboard ([1] of DW1)
+ *      - Depth Stall ([13] of DW1)
+ *      - Post-Sync Operation ([13] of DW1)
+ *      - Notify Enable ([8] of DW1)"
+ *
+ * The cache flushes require the workaround flush that triggered this
+ * one, so we can't use it.  Depth stall would trigger the same.
+ * Post-sync nonzero is what triggered this second workaround, so we
+ * can't use that one either.  Notify enable is IRQs, which aren't
+ * really our business.  That leaves only stall at scoreboard.
+ */
+static int
+intel_emit_post_sync_nonzero_flush(struct intel_ring_buffer *ring)
+{
+	struct pipe_control *pc = ring->private;
+	u32 scratch_addr = pc->gtt_offset + 128;
+	int ret;
+
+
+	ret = intel_ring_begin(ring, 6);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
+	intel_ring_emit(ring, PIPE_CONTROL_CS_STALL |
+			PIPE_CONTROL_STALL_AT_SCOREBOARD);
+	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
+	intel_ring_emit(ring, 0); /* low dword */
+	intel_ring_emit(ring, 0); /* high dword */
+	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_advance(ring);
+
+	ret = intel_ring_begin(ring, 6);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
+	intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE);
+	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
+	intel_ring_emit(ring, 0);
+	intel_ring_emit(ring, 0);
+	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_advance(ring);
+
+	return 0;
+}
+
+static int
+gen6_render_ring_flush(struct intel_ring_buffer *ring,
+                         u32 invalidate_domains, u32 flush_domains)
+{
+	u32 flags = 0;
+	struct pipe_control *pc = ring->private;
+	u32 scratch_addr = pc->gtt_offset + 128;
+	int ret;
+
+	/* Force SNB workarounds for PIPE_CONTROL flushes */
+	intel_emit_post_sync_nonzero_flush(ring);
+
+	/* Just flush everything.  Experiments have shown that reducing the
+	 * number of bits based on the write domains has little performance
+	 * impact.
+	 */
+	flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
+	flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
+	flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
+	flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+	flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
+	flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
+	flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
+
+	ret = intel_ring_begin(ring, 6);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
+	intel_ring_emit(ring, flags);
+	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
+	intel_ring_emit(ring, 0); /* lower dword */
+	intel_ring_emit(ring, 0); /* uppwer dword */
+	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_advance(ring);
+
+	return 0;
+}
+
 static void ring_write_tail(struct intel_ring_buffer *ring,
 			    u32 value)
 {
@@ -206,16 +328,6 @@
 	return 0;
 }
 
-/*
- * 965+ support PIPE_CONTROL commands, which provide finer grained control
- * over cache flushing.
- */
-struct pipe_control {
-	struct drm_i915_gem_object *obj;
-	volatile u32 *cpu_page;
-	u32 gtt_offset;
-};
-
 static int
 init_pipe_control(struct intel_ring_buffer *ring)
 {
@@ -296,8 +408,7 @@
 				   GFX_MODE_ENABLE(GFX_REPLAY_MODE));
 	}
 
-	if (INTEL_INFO(dev)->gen >= 6) {
-	} else if (IS_GEN5(dev)) {
+	if (INTEL_INFO(dev)->gen >= 5) {
 		ret = init_pipe_control(ring);
 		if (ret)
 			return ret;
@@ -315,83 +426,131 @@
 }
 
 static void
-update_semaphore(struct intel_ring_buffer *ring, int i, u32 seqno)
+update_mboxes(struct intel_ring_buffer *ring,
+	    u32 seqno,
+	    u32 mmio_offset)
 {
-	struct drm_device *dev = ring->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int id;
-
-	/*
-	 * cs -> 1 = vcs, 0 = bcs
-	 * vcs -> 1 = bcs, 0 = cs,
-	 * bcs -> 1 = cs, 0 = vcs.
-	 */
-	id = ring - dev_priv->ring;
-	id += 2 - i;
-	id %= 3;
-
-	intel_ring_emit(ring,
-			MI_SEMAPHORE_MBOX |
-			MI_SEMAPHORE_REGISTER |
-			MI_SEMAPHORE_UPDATE);
+	intel_ring_emit(ring, MI_SEMAPHORE_MBOX |
+			      MI_SEMAPHORE_GLOBAL_GTT |
+			      MI_SEMAPHORE_REGISTER |
+			      MI_SEMAPHORE_UPDATE);
 	intel_ring_emit(ring, seqno);
-	intel_ring_emit(ring,
-			RING_SYNC_0(dev_priv->ring[id].mmio_base) + 4*i);
+	intel_ring_emit(ring, mmio_offset);
 }
 
+/**
+ * gen6_add_request - Update the semaphore mailbox registers
+ * 
+ * @ring - ring that is adding a request
+ * @seqno - return seqno stuck into the ring
+ *
+ * Update the mailbox registers in the *other* rings with the current seqno.
+ * This acts like a signal in the canonical semaphore.
+ */
 static int
 gen6_add_request(struct intel_ring_buffer *ring,
-		 u32 *result)
+		 u32 *seqno)
 {
-	u32 seqno;
+	u32 mbox1_reg;
+	u32 mbox2_reg;
 	int ret;
 
 	ret = intel_ring_begin(ring, 10);
 	if (ret)
 		return ret;
 
-	seqno = i915_gem_get_seqno(ring->dev);
-	update_semaphore(ring, 0, seqno);
-	update_semaphore(ring, 1, seqno);
+	mbox1_reg = ring->signal_mbox[0];
+	mbox2_reg = ring->signal_mbox[1];
 
+	*seqno = i915_gem_get_seqno(ring->dev);
+
+	update_mboxes(ring, *seqno, mbox1_reg);
+	update_mboxes(ring, *seqno, mbox2_reg);
 	intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
 	intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-	intel_ring_emit(ring, seqno);
+	intel_ring_emit(ring, *seqno);
 	intel_ring_emit(ring, MI_USER_INTERRUPT);
 	intel_ring_advance(ring);
 
-	*result = seqno;
 	return 0;
 }
 
-int
-intel_ring_sync(struct intel_ring_buffer *ring,
-		struct intel_ring_buffer *to,
+/**
+ * intel_ring_sync - sync the waiter to the signaller on seqno
+ *
+ * @waiter - ring that is waiting
+ * @signaller - ring which has, or will signal
+ * @seqno - seqno which the waiter will block on
+ */
+static int
+intel_ring_sync(struct intel_ring_buffer *waiter,
+		struct intel_ring_buffer *signaller,
+		int ring,
 		u32 seqno)
 {
 	int ret;
+	u32 dw1 = MI_SEMAPHORE_MBOX |
+		  MI_SEMAPHORE_COMPARE |
+		  MI_SEMAPHORE_REGISTER;
 
-	ret = intel_ring_begin(ring, 4);
+	ret = intel_ring_begin(waiter, 4);
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring,
-			MI_SEMAPHORE_MBOX |
-			MI_SEMAPHORE_REGISTER |
-			intel_ring_sync_index(ring, to) << 17 |
-			MI_SEMAPHORE_COMPARE);
-	intel_ring_emit(ring, seqno);
-	intel_ring_emit(ring, 0);
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_advance(ring);
+	intel_ring_emit(waiter, dw1 | signaller->semaphore_register[ring]);
+	intel_ring_emit(waiter, seqno);
+	intel_ring_emit(waiter, 0);
+	intel_ring_emit(waiter, MI_NOOP);
+	intel_ring_advance(waiter);
 
 	return 0;
 }
 
+/* VCS->RCS (RVSYNC) or BCS->RCS (RBSYNC) */
+int
+render_ring_sync_to(struct intel_ring_buffer *waiter,
+		    struct intel_ring_buffer *signaller,
+		    u32 seqno)
+{
+	WARN_ON(signaller->semaphore_register[RCS] == MI_SEMAPHORE_SYNC_INVALID);
+	return intel_ring_sync(waiter,
+			       signaller,
+			       RCS,
+			       seqno);
+}
+
+/* RCS->VCS (VRSYNC) or BCS->VCS (VBSYNC) */
+int
+gen6_bsd_ring_sync_to(struct intel_ring_buffer *waiter,
+		      struct intel_ring_buffer *signaller,
+		      u32 seqno)
+{
+	WARN_ON(signaller->semaphore_register[VCS] == MI_SEMAPHORE_SYNC_INVALID);
+	return intel_ring_sync(waiter,
+			       signaller,
+			       VCS,
+			       seqno);
+}
+
+/* RCS->BCS (BRSYNC) or VCS->BCS (BVSYNC) */
+int
+gen6_blt_ring_sync_to(struct intel_ring_buffer *waiter,
+		      struct intel_ring_buffer *signaller,
+		      u32 seqno)
+{
+	WARN_ON(signaller->semaphore_register[BCS] == MI_SEMAPHORE_SYNC_INVALID);
+	return intel_ring_sync(waiter,
+			       signaller,
+			       BCS,
+			       seqno);
+}
+
+
+
 #define PIPE_CONTROL_FLUSH(ring__, addr__)					\
 do {									\
-	intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |		\
-		 PIPE_CONTROL_DEPTH_STALL | 2);				\
+	intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |		\
+		 PIPE_CONTROL_DEPTH_STALL);				\
 	intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT);			\
 	intel_ring_emit(ring__, 0);							\
 	intel_ring_emit(ring__, 0);							\
@@ -419,8 +578,9 @@
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
-			PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
+	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
+			PIPE_CONTROL_WRITE_FLUSH |
+			PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE);
 	intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
 	intel_ring_emit(ring, seqno);
 	intel_ring_emit(ring, 0);
@@ -435,8 +595,9 @@
 	PIPE_CONTROL_FLUSH(ring, scratch_addr);
 	scratch_addr += 128;
 	PIPE_CONTROL_FLUSH(ring, scratch_addr);
-	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
-			PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
+	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
+			PIPE_CONTROL_WRITE_FLUSH |
+			PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
 			PIPE_CONTROL_NOTIFY);
 	intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
 	intel_ring_emit(ring, seqno);
@@ -1026,7 +1187,12 @@
 	.irq_get		= render_ring_get_irq,
 	.irq_put		= render_ring_put_irq,
 	.dispatch_execbuffer	= render_ring_dispatch_execbuffer,
-       .cleanup			= render_ring_cleanup,
+	.cleanup		= render_ring_cleanup,
+	.sync_to		= render_ring_sync_to,
+	.semaphore_register	= {MI_SEMAPHORE_SYNC_INVALID,
+				   MI_SEMAPHORE_SYNC_RV,
+				   MI_SEMAPHORE_SYNC_RB},
+	.signal_mbox		= {GEN6_VRSYNC, GEN6_BRSYNC},
 };
 
 /* ring buffer for bit-stream decoder */
@@ -1050,23 +1216,23 @@
 static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring,
 				     u32 value)
 {
-       drm_i915_private_t *dev_priv = ring->dev->dev_private;
+	drm_i915_private_t *dev_priv = ring->dev->dev_private;
 
        /* Every tail move must follow the sequence below */
-       I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
-	       GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
-	       GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE);
-       I915_WRITE(GEN6_BSD_RNCID, 0x0);
+	I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
+		GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
+		GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE);
+	I915_WRITE(GEN6_BSD_RNCID, 0x0);
 
-       if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) &
-                               GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0,
-                       50))
-               DRM_ERROR("timed out waiting for IDLE Indicator\n");
+	if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) &
+		GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0,
+		50))
+	DRM_ERROR("timed out waiting for IDLE Indicator\n");
 
-       I915_WRITE_TAIL(ring, value);
-       I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
-	       GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
-	       GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE);
+	I915_WRITE_TAIL(ring, value);
+	I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
+		GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
+		GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE);
 }
 
 static int gen6_ring_flush(struct intel_ring_buffer *ring,
@@ -1094,18 +1260,18 @@
 gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
 			      u32 offset, u32 len)
 {
-       int ret;
+	int ret;
 
-       ret = intel_ring_begin(ring, 2);
-       if (ret)
-	       return ret;
+	ret = intel_ring_begin(ring, 2);
+	if (ret)
+		return ret;
 
-       intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965);
-       /* bit0-7 is the length on GEN6+ */
-       intel_ring_emit(ring, offset);
-       intel_ring_advance(ring);
+	intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965);
+	/* bit0-7 is the length on GEN6+ */
+	intel_ring_emit(ring, offset);
+	intel_ring_advance(ring);
 
-       return 0;
+	return 0;
 }
 
 static bool
@@ -1154,6 +1320,11 @@
 	.irq_get		= gen6_bsd_ring_get_irq,
 	.irq_put		= gen6_bsd_ring_put_irq,
 	.dispatch_execbuffer	= gen6_ring_dispatch_execbuffer,
+	.sync_to		= gen6_bsd_ring_sync_to,
+	.semaphore_register	= {MI_SEMAPHORE_SYNC_VR,
+				   MI_SEMAPHORE_SYNC_INVALID,
+				   MI_SEMAPHORE_SYNC_VB},
+	.signal_mbox		= {GEN6_RVSYNC, GEN6_BVSYNC},
 };
 
 /* Blitter support (SandyBridge+) */
@@ -1272,19 +1443,24 @@
 }
 
 static const struct intel_ring_buffer gen6_blt_ring = {
-       .name			= "blt ring",
-       .id			= RING_BLT,
-       .mmio_base		= BLT_RING_BASE,
-       .size			= 32 * PAGE_SIZE,
-       .init			= blt_ring_init,
-       .write_tail		= ring_write_tail,
-       .flush			= blt_ring_flush,
-       .add_request		= gen6_add_request,
-       .get_seqno		= ring_get_seqno,
-       .irq_get			= blt_ring_get_irq,
-       .irq_put			= blt_ring_put_irq,
-       .dispatch_execbuffer	= gen6_ring_dispatch_execbuffer,
-       .cleanup			= blt_ring_cleanup,
+	.name			= "blt ring",
+	.id			= RING_BLT,
+	.mmio_base		= BLT_RING_BASE,
+	.size			= 32 * PAGE_SIZE,
+	.init			= blt_ring_init,
+	.write_tail		= ring_write_tail,
+	.flush			= blt_ring_flush,
+	.add_request		= gen6_add_request,
+	.get_seqno		= ring_get_seqno,
+	.irq_get		= blt_ring_get_irq,
+	.irq_put		= blt_ring_put_irq,
+	.dispatch_execbuffer	= gen6_ring_dispatch_execbuffer,
+	.cleanup		= blt_ring_cleanup,
+	.sync_to		= gen6_blt_ring_sync_to,
+	.semaphore_register	= {MI_SEMAPHORE_SYNC_BR,
+				   MI_SEMAPHORE_SYNC_BV,
+				   MI_SEMAPHORE_SYNC_INVALID},
+	.signal_mbox		= {GEN6_RBSYNC, GEN6_VBSYNC},
 };
 
 int intel_init_render_ring_buffer(struct drm_device *dev)
@@ -1295,6 +1471,7 @@
 	*ring = render_ring;
 	if (INTEL_INFO(dev)->gen >= 6) {
 		ring->add_request = gen6_add_request;
+		ring->flush = gen6_render_ring_flush;
 		ring->irq_get = gen6_render_ring_get_irq;
 		ring->irq_put = gen6_render_ring_put_irq;
 	} else if (IS_GEN5(dev)) {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,10 +2,10 @@
 #define _INTEL_RINGBUFFER_H_
 
 enum {
-    RCS = 0x0,
-    VCS,
-    BCS,
-    I915_NUM_RINGS,
+	RCS = 0x0,
+	VCS,
+	BCS,
+	I915_NUM_RINGS,
 };
 
 struct  intel_hw_status_page {
@@ -75,7 +75,12 @@
 	int		(*dispatch_execbuffer)(struct intel_ring_buffer *ring,
 					       u32 offset, u32 length);
 	void		(*cleanup)(struct intel_ring_buffer *ring);
+	int		(*sync_to)(struct intel_ring_buffer *ring,
+				   struct intel_ring_buffer *to,
+				   u32 seqno);
 
+	u32		semaphore_register[3]; /*our mbox written by others */
+	u32		signal_mbox[2]; /* mboxes this ring signals to */
 	/**
 	 * List of objects currently involved in rendering from the
 	 * ringbuffer.
@@ -180,9 +185,6 @@
 void intel_ring_advance(struct intel_ring_buffer *ring);
 
 u32 intel_ring_get_seqno(struct intel_ring_buffer *ring);
-int intel_ring_sync(struct intel_ring_buffer *ring,
-		    struct intel_ring_buffer *to,
-		    u32 seqno);
 
 int intel_init_render_ring_buffer(struct drm_device *dev);
 int intel_init_bsd_ring_buffer(struct drm_device *dev);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_sdvo.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_sdvo.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_sdvo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_sdvo.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 #include "drmP.h"
 #include "drm.h"
 #include "drm_crtc.h"
@@ -43,12 +44,13 @@
 #define SDVO_TV_MASK   (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_SVID0)
 
 #define SDVO_OUTPUT_MASK (SDVO_TMDS_MASK | SDVO_RGB_MASK | SDVO_LVDS_MASK |\
-                         SDVO_TV_MASK)
+			SDVO_TV_MASK)
 
 #define IS_TV(c)	(c->output_flag & SDVO_TV_MASK)
 #define IS_TMDS(c)	(c->output_flag & SDVO_TMDS_MASK)
 #define IS_LVDS(c)	(c->output_flag & SDVO_LVDS_MASK)
 #define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK))
+#define IS_DIGITAL(c) (c->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK))
 
 
 static const char *tv_format_names[] = {
@@ -288,117 +290,117 @@
 	u8 cmd;
 	const char *name;
 } sdvo_cmd_names[] = {
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_POWER_STATES),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POWER_STATE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODER_POWER_STATE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DISPLAY_POWER_STATE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_POWER_STATES),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POWER_STATE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODER_POWER_STATE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DISPLAY_POWER_STATE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS),
 
-    /* Add the op code for SDVO enhancements */
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HPOS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HPOS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HPOS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_VPOS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_VPOS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_VPOS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SATURATION),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SATURATION),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SATURATION),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HUE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HUE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HUE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_CONTRAST),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CONTRAST),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTRAST),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_BRIGHTNESS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_BRIGHTNESS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_BRIGHTNESS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_H),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_H),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_H),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_V),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_V),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_V),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_ADAPTIVE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_ADAPTIVE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_ADAPTIVE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_2D),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_2D),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_2D),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SHARPNESS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SHARPNESS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SHARPNESS),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DOT_CRAWL),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DOT_CRAWL),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_CHROMA_FILTER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_CHROMA_FILTER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_CHROMA_FILTER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_LUMA_FILTER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_LUMA_FILTER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_LUMA_FILTER),
+	/* Add the op code for SDVO enhancements */
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HPOS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HPOS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HPOS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_VPOS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_VPOS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_VPOS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SATURATION),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SATURATION),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SATURATION),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HUE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HUE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HUE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_CONTRAST),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CONTRAST),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTRAST),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_BRIGHTNESS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_BRIGHTNESS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_BRIGHTNESS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_H),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_H),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_H),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_V),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_V),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_V),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_ADAPTIVE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_ADAPTIVE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_ADAPTIVE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_2D),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_2D),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_2D),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SHARPNESS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SHARPNESS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SHARPNESS),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DOT_CRAWL),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DOT_CRAWL),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_CHROMA_FILTER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_CHROMA_FILTER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_CHROMA_FILTER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_LUMA_FILTER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_LUMA_FILTER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_LUMA_FILTER),
 
-    /* HDMI op code */
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPP_ENCODE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_PIXEL_REPLI),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PIXEL_REPLI),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY_CAP),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_COLORIMETRY),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_AUDIO_STAT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_STAT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INDEX),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_INDEX),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INFO),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_AV_SPLIT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_AV_SPLIT),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_TXRATE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_TXRATE),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_DATA),
-    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_DATA),
+	/* HDMI op code */
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPP_ENCODE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_PIXEL_REPLI),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PIXEL_REPLI),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY_CAP),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_COLORIMETRY),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_AUDIO_STAT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_STAT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INDEX),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_INDEX),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INFO),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_AV_SPLIT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_AV_SPLIT),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_TXRATE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_TXRATE),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_DATA),
+	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_DATA),
 };
 
 #define IS_SDVOB(reg)	(reg == SDVOB || reg == PCH_SDVOB)
@@ -1085,8 +1087,12 @@
 		}
 		sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
 	}
-	if (intel_crtc->pipe == 1)
-		sdvox |= SDVO_PIPE_B_SELECT;
+
+	if (INTEL_PCH_TYPE(dev) >= PCH_CPT)
+		sdvox |= TRANSCODER_CPT(intel_crtc->pipe);
+	else
+		sdvox |= TRANSCODER(intel_crtc->pipe);
+
 	if (intel_sdvo->has_hdmi_audio)
 		sdvox |= SDVO_AUDIO_ENABLE;
 
@@ -1232,8 +1238,7 @@
 intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo)
 {
 	/* Is there more than one type of output? */
-	int caps = intel_sdvo->caps.output_flags & 0xf;
-	return caps & -caps;
+	return hweight16(intel_sdvo->caps.output_flags) > 1;
 }
 
 static struct edid *
@@ -1254,7 +1259,7 @@
 }
 
 enum drm_connector_status
-intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
+intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
 {
 	struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
 	enum drm_connector_status status;
@@ -1314,6 +1319,18 @@
 	return status;
 }
 
+static bool
+intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo,
+				  struct edid *edid)
+{
+	bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL);
+	bool connector_is_digital = !!IS_DIGITAL(sdvo);
+
+	DRM_DEBUG_KMS("connector_is_digital? %d, monitor_is_digital? %d\n",
+		      connector_is_digital, monitor_is_digital);
+	return connector_is_digital == monitor_is_digital;
+}
+
 static enum drm_connector_status
 intel_sdvo_detect(struct drm_connector *connector, bool force)
 {
@@ -1349,7 +1366,7 @@
 	if ((intel_sdvo_connector->output_flag & response) == 0)
 		ret = connector_status_disconnected;
 	else if (IS_TMDS(intel_sdvo_connector))
-		ret = intel_sdvo_hdmi_sink_detect(connector);
+		ret = intel_sdvo_tmds_sink_detect(connector);
 	else {
 		struct edid *edid;
 
@@ -1358,10 +1375,12 @@
 		if (edid == NULL)
 			edid = intel_sdvo_get_analog_edid(connector);
 		if (edid != NULL) {
-			if (edid->input & DRM_EDID_INPUT_DIGITAL)
-				ret = connector_status_disconnected;
-			else
+			if (intel_sdvo_connector_matches_edid(intel_sdvo_connector,
+							      edid))
 				ret = connector_status_connected;
+			else
+				ret = connector_status_disconnected;
+
 			connector->display_info.raw_edid = NULL;
 			kfree(edid);
 		} else
@@ -1402,11 +1421,8 @@
 		edid = intel_sdvo_get_analog_edid(connector);
 
 	if (edid != NULL) {
-		struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
-		bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL);
-		bool connector_is_digital = !!IS_TMDS(intel_sdvo_connector);
-
-		if (connector_is_digital == monitor_is_digital) {
+		if (intel_sdvo_connector_matches_edid(to_intel_sdvo_connector(connector),
+						      edid)) {
 			drm_mode_connector_update_edid_property(connector, edid);
 			drm_add_edid_modes(connector, edid);
 		}
@@ -1896,7 +1912,7 @@
 			  struct intel_sdvo *sdvo, u32 reg)
 {
 	struct sdvo_device_mapping *mapping;
-	u8 pin, speed;
+	u8 pin;
 
 	if (IS_SDVOB(reg))
 		mapping = &dev_priv->sdvo_mappings[0];
@@ -1904,18 +1920,16 @@
 		mapping = &dev_priv->sdvo_mappings[1];
 
 	pin = GMBUS_PORT_DPB;
-	speed = GMBUS_RATE_1MHZ >> 8;
-	if (mapping->initialized) {
+	if (mapping->initialized)
 		pin = mapping->i2c_pin;
-		speed = mapping->i2c_speed;
-	}
 
 	if (pin < GMBUS_NUM_PORTS) {
 		sdvo->i2c = &dev_priv->gmbus[pin].adapter;
-		intel_gmbus_set_speed(sdvo->i2c, speed);
+		intel_gmbus_set_speed(sdvo->i2c, GMBUS_RATE_1MHZ);
 		intel_gmbus_force_bit(sdvo->i2c, true);
-	} else
+	} else {
 		sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter;
+	}
 }
 
 static bool
@@ -2206,7 +2220,7 @@
 			      bytes[0], bytes[1]);
 		return false;
 	}
-	intel_sdvo->base.crtc_mask = (1 << 0) | (1 << 1);
+	intel_sdvo->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
 	return true;
 }
@@ -2275,7 +2289,7 @@
 		DRM_DEBUG_KMS(#name ": max %d, default %d, current %d\n", \
 			      data_value[0], data_value[1], response); \
 	} \
-} while(0)
+} while (0)
 
 static bool
 intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo,
@@ -2442,7 +2456,7 @@
 
 	if (IS_TV(intel_sdvo_connector))
 		return intel_sdvo_create_enhance_property_tv(intel_sdvo, intel_sdvo_connector, enhancements.reply);
-	else if(IS_LVDS(intel_sdvo_connector))
+	else if (IS_LVDS(intel_sdvo_connector))
 		return intel_sdvo_create_enhance_property_lvds(intel_sdvo, intel_sdvo_connector, enhancements.reply);
 	else
 		return true;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_sdvo_regs.h linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_sdvo_regs.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_sdvo_regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_sdvo_regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -46,63 +46,63 @@
 #define SDVO_OUTPUT_LAST    (14)
 
 struct intel_sdvo_caps {
-    u8 vendor_id;
-    u8 device_id;
-    u8 device_rev_id;
-    u8 sdvo_version_major;
-    u8 sdvo_version_minor;
-    unsigned int sdvo_inputs_mask:2;
-    unsigned int smooth_scaling:1;
-    unsigned int sharp_scaling:1;
-    unsigned int up_scaling:1;
-    unsigned int down_scaling:1;
-    unsigned int stall_support:1;
-    unsigned int pad:1;
-    u16 output_flags;
+	u8 vendor_id;
+	u8 device_id;
+	u8 device_rev_id;
+	u8 sdvo_version_major;
+	u8 sdvo_version_minor;
+	unsigned int sdvo_inputs_mask:2;
+	unsigned int smooth_scaling:1;
+	unsigned int sharp_scaling:1;
+	unsigned int up_scaling:1;
+	unsigned int down_scaling:1;
+	unsigned int stall_support:1;
+	unsigned int pad:1;
+	u16 output_flags;
 } __attribute__((packed));
 
 /** This matches the EDID DTD structure, more or less */
 struct intel_sdvo_dtd {
-    struct {
-	u16 clock;		/**< pixel clock, in 10kHz units */
-	u8 h_active;		/**< lower 8 bits (pixels) */
-	u8 h_blank;		/**< lower 8 bits (pixels) */
-	u8 h_high;		/**< upper 4 bits each h_active, h_blank */
-	u8 v_active;		/**< lower 8 bits (lines) */
-	u8 v_blank;		/**< lower 8 bits (lines) */
-	u8 v_high;		/**< upper 4 bits each v_active, v_blank */
-    } part1;
+	struct {
+		u16 clock;	/**< pixel clock, in 10kHz units */
+		u8 h_active;	/**< lower 8 bits (pixels) */
+		u8 h_blank;	/**< lower 8 bits (pixels) */
+		u8 h_high;	/**< upper 4 bits each h_active, h_blank */
+		u8 v_active;	/**< lower 8 bits (lines) */
+		u8 v_blank;	/**< lower 8 bits (lines) */
+		u8 v_high;	/**< upper 4 bits each v_active, v_blank */
+	} part1;
 
-    struct {
-	u8 h_sync_off;	/**< lower 8 bits, from hblank start */
-	u8 h_sync_width;	/**< lower 8 bits (pixels) */
-	/** lower 4 bits each vsync offset, vsync width */
-	u8 v_sync_off_width;
-	/**
-	 * 2 high bits of hsync offset, 2 high bits of hsync width,
-	 * bits 4-5 of vsync offset, and 2 high bits of vsync width.
-	 */
-	u8 sync_off_width_high;
-	u8 dtd_flags;
-	u8 sdvo_flags;
-	/** bits 6-7 of vsync offset at bits 6-7 */
-	u8 v_sync_off_high;
-	u8 reserved;
-    } part2;
+	struct {
+		u8 h_sync_off;	/**< lower 8 bits, from hblank start */
+		u8 h_sync_width;	/**< lower 8 bits (pixels) */
+		/** lower 4 bits each vsync offset, vsync width */
+		u8 v_sync_off_width;
+		/**
+		* 2 high bits of hsync offset, 2 high bits of hsync width,
+		* bits 4-5 of vsync offset, and 2 high bits of vsync width.
+		*/
+		u8 sync_off_width_high;
+		u8 dtd_flags;
+		u8 sdvo_flags;
+		/** bits 6-7 of vsync offset at bits 6-7 */
+		u8 v_sync_off_high;
+		u8 reserved;
+	} part2;
 } __attribute__((packed));
 
 struct intel_sdvo_pixel_clock_range {
-    u16 min;			/**< pixel clock, in 10kHz units */
-    u16 max;			/**< pixel clock, in 10kHz units */
+	u16 min;	/**< pixel clock, in 10kHz units */
+	u16 max;	/**< pixel clock, in 10kHz units */
 } __attribute__((packed));
 
 struct intel_sdvo_preferred_input_timing_args {
-    u16 clock;
-    u16 width;
-    u16 height;
-    u8	interlace:1;
-    u8	scaled:1;
-    u8	pad:6;
+	u16 clock;
+	u16 width;
+	u16 height;
+	u8	interlace:1;
+	u8	scaled:1;
+	u8	pad:6;
 } __attribute__((packed));
 
 /* I2C registers for SDVO */
@@ -154,9 +154,9 @@
  */
 #define SDVO_CMD_GET_TRAINED_INPUTS			0x03
 struct intel_sdvo_get_trained_inputs_response {
-    unsigned int input0_trained:1;
-    unsigned int input1_trained:1;
-    unsigned int pad:6;
+	unsigned int input0_trained:1;
+	unsigned int input1_trained:1;
+	unsigned int pad:6;
 } __attribute__((packed));
 
 /** Returns a struct intel_sdvo_output_flags of active outputs. */
@@ -177,7 +177,7 @@
  */
 #define SDVO_CMD_GET_IN_OUT_MAP				0x06
 struct intel_sdvo_in_out_map {
-    u16 in0, in1;
+	u16 in0, in1;
 };
 
 /**
@@ -210,10 +210,10 @@
 
 #define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE		0x0f
 struct intel_sdvo_get_interrupt_event_source_response {
-    u16 interrupt_status;
-    unsigned int ambient_light_interrupt:1;
-    unsigned int hdmi_audio_encrypt_change:1;
-    unsigned int pad:6;
+	u16 interrupt_status;
+	unsigned int ambient_light_interrupt:1;
+	unsigned int hdmi_audio_encrypt_change:1;
+	unsigned int pad:6;
 } __attribute__((packed));
 
 /**
@@ -225,8 +225,8 @@
  */
 #define SDVO_CMD_SET_TARGET_INPUT			0x10
 struct intel_sdvo_set_target_input_args {
-    unsigned int target_1:1;
-    unsigned int pad:7;
+	unsigned int target_1:1;
+	unsigned int pad:7;
 } __attribute__((packed));
 
 /**
@@ -314,57 +314,57 @@
 #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS		0x27
 /** 6 bytes of bit flags for TV formats shared by all TV format functions */
 struct intel_sdvo_tv_format {
-    unsigned int ntsc_m:1;
-    unsigned int ntsc_j:1;
-    unsigned int ntsc_443:1;
-    unsigned int pal_b:1;
-    unsigned int pal_d:1;
-    unsigned int pal_g:1;
-    unsigned int pal_h:1;
-    unsigned int pal_i:1;
+	unsigned int ntsc_m:1;
+	unsigned int ntsc_j:1;
+	unsigned int ntsc_443:1;
+	unsigned int pal_b:1;
+	unsigned int pal_d:1;
+	unsigned int pal_g:1;
+	unsigned int pal_h:1;
+	unsigned int pal_i:1;
 
-    unsigned int pal_m:1;
-    unsigned int pal_n:1;
-    unsigned int pal_nc:1;
-    unsigned int pal_60:1;
-    unsigned int secam_b:1;
-    unsigned int secam_d:1;
-    unsigned int secam_g:1;
-    unsigned int secam_k:1;
+	unsigned int pal_m:1;
+	unsigned int pal_n:1;
+	unsigned int pal_nc:1;
+	unsigned int pal_60:1;
+	unsigned int secam_b:1;
+	unsigned int secam_d:1;
+	unsigned int secam_g:1;
+	unsigned int secam_k:1;
 
-    unsigned int secam_k1:1;
-    unsigned int secam_l:1;
-    unsigned int secam_60:1;
-    unsigned int hdtv_std_smpte_240m_1080i_59:1;
-    unsigned int hdtv_std_smpte_240m_1080i_60:1;
-    unsigned int hdtv_std_smpte_260m_1080i_59:1;
-    unsigned int hdtv_std_smpte_260m_1080i_60:1;
-    unsigned int hdtv_std_smpte_274m_1080i_50:1;
+	unsigned int secam_k1:1;
+	unsigned int secam_l:1;
+	unsigned int secam_60:1;
+	unsigned int hdtv_std_smpte_240m_1080i_59:1;
+	unsigned int hdtv_std_smpte_240m_1080i_60:1;
+	unsigned int hdtv_std_smpte_260m_1080i_59:1;
+	unsigned int hdtv_std_smpte_260m_1080i_60:1;
+	unsigned int hdtv_std_smpte_274m_1080i_50:1;
 
-    unsigned int hdtv_std_smpte_274m_1080i_59:1;
-    unsigned int hdtv_std_smpte_274m_1080i_60:1;
-    unsigned int hdtv_std_smpte_274m_1080p_23:1;
-    unsigned int hdtv_std_smpte_274m_1080p_24:1;
-    unsigned int hdtv_std_smpte_274m_1080p_25:1;
-    unsigned int hdtv_std_smpte_274m_1080p_29:1;
-    unsigned int hdtv_std_smpte_274m_1080p_30:1;
-    unsigned int hdtv_std_smpte_274m_1080p_50:1;
+	unsigned int hdtv_std_smpte_274m_1080i_59:1;
+	unsigned int hdtv_std_smpte_274m_1080i_60:1;
+	unsigned int hdtv_std_smpte_274m_1080p_23:1;
+	unsigned int hdtv_std_smpte_274m_1080p_24:1;
+	unsigned int hdtv_std_smpte_274m_1080p_25:1;
+	unsigned int hdtv_std_smpte_274m_1080p_29:1;
+	unsigned int hdtv_std_smpte_274m_1080p_30:1;
+	unsigned int hdtv_std_smpte_274m_1080p_50:1;
 
-    unsigned int hdtv_std_smpte_274m_1080p_59:1;
-    unsigned int hdtv_std_smpte_274m_1080p_60:1;
-    unsigned int hdtv_std_smpte_295m_1080i_50:1;
-    unsigned int hdtv_std_smpte_295m_1080p_50:1;
-    unsigned int hdtv_std_smpte_296m_720p_59:1;
-    unsigned int hdtv_std_smpte_296m_720p_60:1;
-    unsigned int hdtv_std_smpte_296m_720p_50:1;
-    unsigned int hdtv_std_smpte_293m_480p_59:1;
+	unsigned int hdtv_std_smpte_274m_1080p_59:1;
+	unsigned int hdtv_std_smpte_274m_1080p_60:1;
+	unsigned int hdtv_std_smpte_295m_1080i_50:1;
+	unsigned int hdtv_std_smpte_295m_1080p_50:1;
+	unsigned int hdtv_std_smpte_296m_720p_59:1;
+	unsigned int hdtv_std_smpte_296m_720p_60:1;
+	unsigned int hdtv_std_smpte_296m_720p_50:1;
+	unsigned int hdtv_std_smpte_293m_480p_59:1;
 
-    unsigned int hdtv_std_smpte_170m_480i_59:1;
-    unsigned int hdtv_std_iturbt601_576i_50:1;
-    unsigned int hdtv_std_iturbt601_576p_50:1;
-    unsigned int hdtv_std_eia_7702a_480i_60:1;
-    unsigned int hdtv_std_eia_7702a_480p_60:1;
-    unsigned int pad:3;
+	unsigned int hdtv_std_smpte_170m_480i_59:1;
+	unsigned int hdtv_std_iturbt601_576i_50:1;
+	unsigned int hdtv_std_iturbt601_576p_50:1;
+	unsigned int hdtv_std_eia_7702a_480i_60:1;
+	unsigned int hdtv_std_eia_7702a_480p_60:1;
+	unsigned int pad:3;
 } __attribute__((packed));
 
 #define SDVO_CMD_GET_TV_FORMAT				0x28
@@ -374,53 +374,53 @@
 /** Returns the resolutiosn that can be used with the given TV format */
 #define SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT		0x83
 struct intel_sdvo_sdtv_resolution_request {
-    unsigned int ntsc_m:1;
-    unsigned int ntsc_j:1;
-    unsigned int ntsc_443:1;
-    unsigned int pal_b:1;
-    unsigned int pal_d:1;
-    unsigned int pal_g:1;
-    unsigned int pal_h:1;
-    unsigned int pal_i:1;
+	unsigned int ntsc_m:1;
+	unsigned int ntsc_j:1;
+	unsigned int ntsc_443:1;
+	unsigned int pal_b:1;
+	unsigned int pal_d:1;
+	unsigned int pal_g:1;
+	unsigned int pal_h:1;
+	unsigned int pal_i:1;
 
-    unsigned int pal_m:1;
-    unsigned int pal_n:1;
-    unsigned int pal_nc:1;
-    unsigned int pal_60:1;
-    unsigned int secam_b:1;
-    unsigned int secam_d:1;
-    unsigned int secam_g:1;
-    unsigned int secam_k:1;
+	unsigned int pal_m:1;
+	unsigned int pal_n:1;
+	unsigned int pal_nc:1;
+	unsigned int pal_60:1;
+	unsigned int secam_b:1;
+	unsigned int secam_d:1;
+	unsigned int secam_g:1;
+	unsigned int secam_k:1;
 
-    unsigned int secam_k1:1;
-    unsigned int secam_l:1;
-    unsigned int secam_60:1;
-    unsigned int pad:5;
+	unsigned int secam_k1:1;
+	unsigned int secam_l:1;
+	unsigned int secam_60:1;
+	unsigned int pad:5;
 } __attribute__((packed));
 
 struct intel_sdvo_sdtv_resolution_reply {
-    unsigned int res_320x200:1;
-    unsigned int res_320x240:1;
-    unsigned int res_400x300:1;
-    unsigned int res_640x350:1;
-    unsigned int res_640x400:1;
-    unsigned int res_640x480:1;
-    unsigned int res_704x480:1;
-    unsigned int res_704x576:1;
+	unsigned int res_320x200:1;
+	unsigned int res_320x240:1;
+	unsigned int res_400x300:1;
+	unsigned int res_640x350:1;
+	unsigned int res_640x400:1;
+	unsigned int res_640x480:1;
+	unsigned int res_704x480:1;
+	unsigned int res_704x576:1;
 
-    unsigned int res_720x350:1;
-    unsigned int res_720x400:1;
-    unsigned int res_720x480:1;
-    unsigned int res_720x540:1;
-    unsigned int res_720x576:1;
-    unsigned int res_768x576:1;
-    unsigned int res_800x600:1;
-    unsigned int res_832x624:1;
+	unsigned int res_720x350:1;
+	unsigned int res_720x400:1;
+	unsigned int res_720x480:1;
+	unsigned int res_720x540:1;
+	unsigned int res_720x576:1;
+	unsigned int res_768x576:1;
+	unsigned int res_800x600:1;
+	unsigned int res_832x624:1;
 
-    unsigned int res_920x766:1;
-    unsigned int res_1024x768:1;
-    unsigned int res_1280x1024:1;
-    unsigned int pad:5;
+	unsigned int res_920x766:1;
+	unsigned int res_1024x768:1;
+	unsigned int res_1280x1024:1;
+	unsigned int pad:5;
 } __attribute__((packed));
 
 /* Get supported resolution with squire pixel aspect ratio that can be
@@ -428,90 +428,90 @@
 #define SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT		0x85
 
 struct intel_sdvo_hdtv_resolution_request {
-    unsigned int hdtv_std_smpte_240m_1080i_59:1;
-    unsigned int hdtv_std_smpte_240m_1080i_60:1;
-    unsigned int hdtv_std_smpte_260m_1080i_59:1;
-    unsigned int hdtv_std_smpte_260m_1080i_60:1;
-    unsigned int hdtv_std_smpte_274m_1080i_50:1;
-    unsigned int hdtv_std_smpte_274m_1080i_59:1;
-    unsigned int hdtv_std_smpte_274m_1080i_60:1;
-    unsigned int hdtv_std_smpte_274m_1080p_23:1;
+	unsigned int hdtv_std_smpte_240m_1080i_59:1;
+	unsigned int hdtv_std_smpte_240m_1080i_60:1;
+	unsigned int hdtv_std_smpte_260m_1080i_59:1;
+	unsigned int hdtv_std_smpte_260m_1080i_60:1;
+	unsigned int hdtv_std_smpte_274m_1080i_50:1;
+	unsigned int hdtv_std_smpte_274m_1080i_59:1;
+	unsigned int hdtv_std_smpte_274m_1080i_60:1;
+	unsigned int hdtv_std_smpte_274m_1080p_23:1;
 
-    unsigned int hdtv_std_smpte_274m_1080p_24:1;
-    unsigned int hdtv_std_smpte_274m_1080p_25:1;
-    unsigned int hdtv_std_smpte_274m_1080p_29:1;
-    unsigned int hdtv_std_smpte_274m_1080p_30:1;
-    unsigned int hdtv_std_smpte_274m_1080p_50:1;
-    unsigned int hdtv_std_smpte_274m_1080p_59:1;
-    unsigned int hdtv_std_smpte_274m_1080p_60:1;
-    unsigned int hdtv_std_smpte_295m_1080i_50:1;
+	unsigned int hdtv_std_smpte_274m_1080p_24:1;
+	unsigned int hdtv_std_smpte_274m_1080p_25:1;
+	unsigned int hdtv_std_smpte_274m_1080p_29:1;
+	unsigned int hdtv_std_smpte_274m_1080p_30:1;
+	unsigned int hdtv_std_smpte_274m_1080p_50:1;
+	unsigned int hdtv_std_smpte_274m_1080p_59:1;
+	unsigned int hdtv_std_smpte_274m_1080p_60:1;
+	unsigned int hdtv_std_smpte_295m_1080i_50:1;
 
-    unsigned int hdtv_std_smpte_295m_1080p_50:1;
-    unsigned int hdtv_std_smpte_296m_720p_59:1;
-    unsigned int hdtv_std_smpte_296m_720p_60:1;
-    unsigned int hdtv_std_smpte_296m_720p_50:1;
-    unsigned int hdtv_std_smpte_293m_480p_59:1;
-    unsigned int hdtv_std_smpte_170m_480i_59:1;
-    unsigned int hdtv_std_iturbt601_576i_50:1;
-    unsigned int hdtv_std_iturbt601_576p_50:1;
+	unsigned int hdtv_std_smpte_295m_1080p_50:1;
+	unsigned int hdtv_std_smpte_296m_720p_59:1;
+	unsigned int hdtv_std_smpte_296m_720p_60:1;
+	unsigned int hdtv_std_smpte_296m_720p_50:1;
+	unsigned int hdtv_std_smpte_293m_480p_59:1;
+	unsigned int hdtv_std_smpte_170m_480i_59:1;
+	unsigned int hdtv_std_iturbt601_576i_50:1;
+	unsigned int hdtv_std_iturbt601_576p_50:1;
 
-    unsigned int hdtv_std_eia_7702a_480i_60:1;
-    unsigned int hdtv_std_eia_7702a_480p_60:1;
-    unsigned int pad:6;
+	unsigned int hdtv_std_eia_7702a_480i_60:1;
+	unsigned int hdtv_std_eia_7702a_480p_60:1;
+	unsigned int pad:6;
 } __attribute__((packed));
 
 struct intel_sdvo_hdtv_resolution_reply {
-    unsigned int res_640x480:1;
-    unsigned int res_800x600:1;
-    unsigned int res_1024x768:1;
-    unsigned int res_1280x960:1;
-    unsigned int res_1400x1050:1;
-    unsigned int res_1600x1200:1;
-    unsigned int res_1920x1440:1;
-    unsigned int res_2048x1536:1;
+	unsigned int res_640x480:1;
+	unsigned int res_800x600:1;
+	unsigned int res_1024x768:1;
+	unsigned int res_1280x960:1;
+	unsigned int res_1400x1050:1;
+	unsigned int res_1600x1200:1;
+	unsigned int res_1920x1440:1;
+	unsigned int res_2048x1536:1;
 
-    unsigned int res_2560x1920:1;
-    unsigned int res_3200x2400:1;
-    unsigned int res_3840x2880:1;
-    unsigned int pad1:5;
+	unsigned int res_2560x1920:1;
+	unsigned int res_3200x2400:1;
+	unsigned int res_3840x2880:1;
+	unsigned int pad1:5;
 
-    unsigned int res_848x480:1;
-    unsigned int res_1064x600:1;
-    unsigned int res_1280x720:1;
-    unsigned int res_1360x768:1;
-    unsigned int res_1704x960:1;
-    unsigned int res_1864x1050:1;
-    unsigned int res_1920x1080:1;
-    unsigned int res_2128x1200:1;
+	unsigned int res_848x480:1;
+	unsigned int res_1064x600:1;
+	unsigned int res_1280x720:1;
+	unsigned int res_1360x768:1;
+	unsigned int res_1704x960:1;
+	unsigned int res_1864x1050:1;
+	unsigned int res_1920x1080:1;
+	unsigned int res_2128x1200:1;
 
-    unsigned int res_2560x1400:1;
-    unsigned int res_2728x1536:1;
-    unsigned int res_3408x1920:1;
-    unsigned int res_4264x2400:1;
-    unsigned int res_5120x2880:1;
-    unsigned int pad2:3;
+	unsigned int res_2560x1400:1;
+	unsigned int res_2728x1536:1;
+	unsigned int res_3408x1920:1;
+	unsigned int res_4264x2400:1;
+	unsigned int res_5120x2880:1;
+	unsigned int pad2:3;
 
-    unsigned int res_768x480:1;
-    unsigned int res_960x600:1;
-    unsigned int res_1152x720:1;
-    unsigned int res_1124x768:1;
-    unsigned int res_1536x960:1;
-    unsigned int res_1680x1050:1;
-    unsigned int res_1728x1080:1;
-    unsigned int res_1920x1200:1;
+	unsigned int res_768x480:1;
+	unsigned int res_960x600:1;
+	unsigned int res_1152x720:1;
+	unsigned int res_1124x768:1;
+	unsigned int res_1536x960:1;
+	unsigned int res_1680x1050:1;
+	unsigned int res_1728x1080:1;
+	unsigned int res_1920x1200:1;
 
-    unsigned int res_2304x1440:1;
-    unsigned int res_2456x1536:1;
-    unsigned int res_3072x1920:1;
-    unsigned int res_3840x2400:1;
-    unsigned int res_4608x2880:1;
-    unsigned int pad3:3;
+	unsigned int res_2304x1440:1;
+	unsigned int res_2456x1536:1;
+	unsigned int res_3072x1920:1;
+	unsigned int res_3840x2400:1;
+	unsigned int res_4608x2880:1;
+	unsigned int pad3:3;
 
-    unsigned int res_1280x1024:1;
-    unsigned int pad4:7;
+	unsigned int res_1280x1024:1;
+	unsigned int pad4:7;
 
-    unsigned int res_1280x768:1;
-    unsigned int pad5:7;
+	unsigned int res_1280x768:1;
+	unsigned int pad5:7;
 } __attribute__((packed));
 
 /* Get supported power state returns info for encoder and monitor, rely on
@@ -539,25 +539,25 @@
  * The high fields are bits 8:9 of the 10-bit values.
  */
 struct sdvo_panel_power_sequencing {
-    u8 t0;
-    u8 t1;
-    u8 t2;
-    u8 t3;
-    u8 t4;
+	u8 t0;
+	u8 t1;
+	u8 t2;
+	u8 t3;
+	u8 t4;
 
-    unsigned int t0_high:2;
-    unsigned int t1_high:2;
-    unsigned int t2_high:2;
-    unsigned int t3_high:2;
+	unsigned int t0_high:2;
+	unsigned int t1_high:2;
+	unsigned int t2_high:2;
+	unsigned int t3_high:2;
 
-    unsigned int t4_high:2;
-    unsigned int pad:6;
+	unsigned int t4_high:2;
+	unsigned int pad:6;
 } __attribute__((packed));
 
 #define SDVO_CMD_GET_MAX_BACKLIGHT_LEVEL		0x30
 struct sdvo_max_backlight_reply {
-    u8 max_value;
-    u8 default_value;
+	u8 max_value;
+	u8 default_value;
 } __attribute__((packed));
 
 #define SDVO_CMD_GET_BACKLIGHT_LEVEL			0x31
@@ -565,16 +565,16 @@
 
 #define SDVO_CMD_GET_AMBIENT_LIGHT			0x33
 struct sdvo_get_ambient_light_reply {
-    u16 trip_low;
-    u16 trip_high;
-    u16 value;
+	u16 trip_low;
+	u16 trip_high;
+	u16 value;
 } __attribute__((packed));
 #define SDVO_CMD_SET_AMBIENT_LIGHT			0x34
 struct sdvo_set_ambient_light_reply {
-    u16 trip_low;
-    u16 trip_high;
-    unsigned int enable:1;
-    unsigned int pad:7;
+	u16 trip_low;
+	u16 trip_high;
+	unsigned int enable:1;
+	unsigned int pad:7;
 } __attribute__((packed));
 
 /* Set display power state */
@@ -586,23 +586,23 @@
 
 #define SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS		0x84
 struct intel_sdvo_enhancements_reply {
-    unsigned int flicker_filter:1;
-    unsigned int flicker_filter_adaptive:1;
-    unsigned int flicker_filter_2d:1;
-    unsigned int saturation:1;
-    unsigned int hue:1;
-    unsigned int brightness:1;
-    unsigned int contrast:1;
-    unsigned int overscan_h:1;
+	unsigned int flicker_filter:1;
+	unsigned int flicker_filter_adaptive:1;
+	unsigned int flicker_filter_2d:1;
+	unsigned int saturation:1;
+	unsigned int hue:1;
+	unsigned int brightness:1;
+	unsigned int contrast:1;
+	unsigned int overscan_h:1;
 
-    unsigned int overscan_v:1;
-    unsigned int hpos:1;
-    unsigned int vpos:1;
-    unsigned int sharpness:1;
-    unsigned int dot_crawl:1;
-    unsigned int dither:1;
-    unsigned int tv_chroma_filter:1;
-    unsigned int tv_luma_filter:1;
+	unsigned int overscan_v:1;
+	unsigned int hpos:1;
+	unsigned int vpos:1;
+	unsigned int sharpness:1;
+	unsigned int dot_crawl:1;
+	unsigned int dither:1;
+	unsigned int tv_chroma_filter:1;
+	unsigned int tv_luma_filter:1;
 } __attribute__((packed));
 
 /* Picture enhancement limits below are dependent on the current TV format,
@@ -623,8 +623,8 @@
 #define SDVO_CMD_GET_MAX_TV_CHROMA_FILTER		0x74
 #define SDVO_CMD_GET_MAX_TV_LUMA_FILTER			0x77
 struct intel_sdvo_enhancement_limits_reply {
-    u16 max_value;
-    u16 default_value;
+	u16 max_value;
+	u16 default_value;
 } __attribute__((packed));
 
 #define SDVO_CMD_GET_LVDS_PANEL_INFORMATION		0x7f
@@ -665,8 +665,8 @@
 #define SDVO_CMD_GET_TV_LUMA_FILTER			0x78
 #define SDVO_CMD_SET_TV_LUMA_FILTER			0x79
 struct intel_sdvo_enhancements_arg {
-    u16 value;
-}__attribute__((packed));
+	u16 value;
+} __attribute__((packed));
 
 #define SDVO_CMD_GET_DOT_CRAWL				0x70
 #define SDVO_CMD_SET_DOT_CRAWL				0x71
@@ -717,7 +717,7 @@
 #define SDVO_CMD_GET_AUDIO_TX_INFO	0x9c
 #define SDVO_NEED_TO_STALL  (1 << 7)
 
-struct intel_sdvo_encode{
-    u8 dvi_rev;
-    u8 hdmi_rev;
+struct intel_sdvo_encode {
+	u8 dvi_rev;
+	u8 hdmi_rev;
 } __attribute__ ((packed));
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_tv.c linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_tv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/i915/intel_tv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/i915/intel_tv.c	2012-01-04 18:55:44.000000000 -0500
@@ -194,10 +194,10 @@
  *
  *     if (f >= 1) {
  *         exp = 0x7;
- * 	   mant = 1 << 8;
+ *	   mant = 1 << 8;
  *     } else {
  *         for (exp = 0; exp < 3 && f < 0.5; exp++)
- * 	       f *= 2.0;
+ *	   f *= 2.0;
  *         mant = (f * (1 << 9) + 0.5);
  *         if (mant >= (1 << 9))
  *             mant = (1 << 9) - 1;
@@ -430,7 +430,7 @@
 		.vsync_start_f1	= 6,		    .vsync_start_f2	= 7,
 		.vsync_len	= 6,
 
-		.veq_ena	= true,		    .veq_start_f1    	= 0,
+		.veq_ena	= true,		    .veq_start_f1	= 0,
 		.veq_start_f2	= 1,		    .veq_len		= 18,
 
 		.vi_end_f1	= 20,		    .vi_end_f2		= 21,
@@ -472,7 +472,7 @@
 		.vsync_start_f1 = 6,		    .vsync_start_f2	= 7,
 		.vsync_len	= 6,
 
-		.veq_ena	= true,		    .veq_start_f1    	= 0,
+		.veq_ena	= true,		    .veq_start_f1	= 0,
 		.veq_start_f2	= 1,		    .veq_len		= 18,
 
 		.vi_end_f1	= 20,		    .vi_end_f2		= 21,
@@ -515,7 +515,7 @@
 		.vsync_start_f1	= 6,	    .vsync_start_f2	= 7,
 		.vsync_len	= 6,
 
-		.veq_ena	= true,		    .veq_start_f1    	= 0,
+		.veq_ena      = true,	    .veq_start_f1	= 0,
 		.veq_start_f2 = 1,	    .veq_len		= 18,
 
 		.vi_end_f1	= 20,		    .vi_end_f2		= 21,
@@ -558,7 +558,7 @@
 		.vsync_start_f1	= 6,		    .vsync_start_f2	= 7,
 		.vsync_len	= 6,
 
-		.veq_ena	= true,		    .veq_start_f1    	= 0,
+		.veq_ena	= true,		    .veq_start_f1	= 0,
 		.veq_start_f2	= 1,		    .veq_len		= 18,
 
 		.vi_end_f1	= 20,		    .vi_end_f2		= 21,
@@ -602,14 +602,14 @@
 		.vsync_start_f1	= 6,	   .vsync_start_f2	= 7,
 		.vsync_len	= 6,
 
-		.veq_ena	= true,		    .veq_start_f1    	= 0,
+		.veq_ena	= true,		    .veq_start_f1	= 0,
 		.veq_start_f2	= 1,		    .veq_len		= 18,
 
 		.vi_end_f1	= 24,		    .vi_end_f2		= 25,
 		.nbr_end	= 286,
 
 		.burst_ena	= true,
-		.hburst_start = 73,	    	    .hburst_len		= 34,
+		.hburst_start = 73,	    .hburst_len		= 34,
 		.vburst_start_f1 = 8,	    .vburst_end_f1	= 285,
 		.vburst_start_f2 = 8,	    .vburst_end_f2	= 286,
 		.vburst_start_f3 = 9,	    .vburst_end_f3	= 286,
@@ -646,7 +646,7 @@
 		.vsync_start_f1	= 5,	    .vsync_start_f2	= 6,
 		.vsync_len	= 5,
 
-		.veq_ena	= true,		    .veq_start_f1    	= 0,
+		.veq_ena	= true,	    .veq_start_f1	= 0,
 		.veq_start_f2	= 1,	    .veq_len		= 15,
 
 		.vi_end_f1	= 24,		    .vi_end_f2		= 25,
@@ -675,7 +675,7 @@
 	},
 	{
 		.name       = "480p@59.94Hz",
-		.clock 	= 107520,
+		.clock		= 107520,
 		.refresh	= 59940,
 		.oversample     = TV_OVERSAMPLE_4X,
 		.component_only = 1,
@@ -683,7 +683,7 @@
 		.hsync_end      = 64,               .hblank_end         = 122,
 		.hblank_start   = 842,              .htotal             = 857,
 
-		.progressive    = true,.trilevel_sync = false,
+		.progressive    = true,		    .trilevel_sync = false,
 
 		.vsync_start_f1 = 12,               .vsync_start_f2     = 12,
 		.vsync_len      = 12,
@@ -699,7 +699,7 @@
 	},
 	{
 		.name       = "480p@60Hz",
-		.clock 	= 107520,
+		.clock		= 107520,
 		.refresh	= 60000,
 		.oversample     = TV_OVERSAMPLE_4X,
 		.component_only = 1,
@@ -707,7 +707,7 @@
 		.hsync_end      = 64,               .hblank_end         = 122,
 		.hblank_start   = 842,              .htotal             = 856,
 
-		.progressive    = true,.trilevel_sync = false,
+		.progressive    = true,		    .trilevel_sync = false,
 
 		.vsync_start_f1 = 12,               .vsync_start_f2     = 12,
 		.vsync_len      = 12,
@@ -723,7 +723,7 @@
 	},
 	{
 		.name       = "576p",
-		.clock 	= 107520,
+		.clock		= 107520,
 		.refresh	= 50000,
 		.oversample     = TV_OVERSAMPLE_4X,
 		.component_only = 1,
@@ -755,7 +755,7 @@
 		.hsync_end      = 80,               .hblank_end         = 300,
 		.hblank_start   = 1580,             .htotal             = 1649,
 
-		.progressive    = true, 	    .trilevel_sync = true,
+		.progressive	= true,		    .trilevel_sync = true,
 
 		.vsync_start_f1 = 10,               .vsync_start_f2     = 10,
 		.vsync_len      = 10,
@@ -779,7 +779,7 @@
 		.hsync_end      = 80,               .hblank_end         = 300,
 		.hblank_start   = 1580,             .htotal             = 1651,
 
-		.progressive    = true, 	    .trilevel_sync = true,
+		.progressive	= true,		    .trilevel_sync = true,
 
 		.vsync_start_f1 = 10,               .vsync_start_f2     = 10,
 		.vsync_len      = 10,
@@ -803,7 +803,7 @@
 		.hsync_end      = 80,               .hblank_end         = 300,
 		.hblank_start   = 1580,             .htotal             = 1979,
 
-		.progressive    = true, 	        .trilevel_sync = true,
+		.progressive	= true,		    .trilevel_sync = true,
 
 		.vsync_start_f1 = 10,               .vsync_start_f2     = 10,
 		.vsync_len      = 10,
@@ -828,12 +828,12 @@
 		.hsync_end      = 88,               .hblank_end         = 235,
 		.hblank_start   = 2155,             .htotal             = 2639,
 
-		.progressive    = false, 	    .trilevel_sync = true,
+		.progressive	= false,	  .trilevel_sync = true,
 
 		.vsync_start_f1 = 4,              .vsync_start_f2     = 5,
 		.vsync_len      = 10,
 
-		.veq_ena	= true,		    .veq_start_f1    	= 4,
+		.veq_ena	= true,	    .veq_start_f1	= 4,
 		.veq_start_f2   = 4,	    .veq_len		= 10,
 
 
@@ -854,12 +854,12 @@
 		.hsync_end      = 88,               .hblank_end         = 235,
 		.hblank_start   = 2155,             .htotal             = 2199,
 
-		.progressive    = false, 	    .trilevel_sync = true,
+		.progressive	= false,	    .trilevel_sync = true,
 
 		.vsync_start_f1 = 4,               .vsync_start_f2     = 5,
 		.vsync_len      = 10,
 
-		.veq_ena	= true,		    .veq_start_f1    	= 4,
+		.veq_ena	= true,		    .veq_start_f1	= 4,
 		.veq_start_f2	= 4,		    .veq_len		= 10,
 
 
@@ -880,16 +880,16 @@
 		.hsync_end      = 88,               .hblank_end         = 235,
 		.hblank_start   = 2155,             .htotal             = 2201,
 
-		.progressive    = false, 	    .trilevel_sync = true,
+		.progressive	= false,	    .trilevel_sync = true,
 
 		.vsync_start_f1 = 4,            .vsync_start_f2    = 5,
 		.vsync_len      = 10,
 
 		.veq_ena	= true,		    .veq_start_f1	= 4,
-		.veq_start_f2 = 4,	    	    .veq_len = 10,
+		.veq_start_f2	= 4,		.veq_len	  = 10,
 
 
-		.vi_end_f1      = 21,           .vi_end_f2         	= 22,
+		.vi_end_f1	= 21,		.vi_end_f2	  = 22,
 		.nbr_end        = 539,
 
 		.burst_ena      = false,
@@ -916,7 +916,7 @@
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	switch(mode) {
+	switch (mode) {
 	case DRM_MODE_DPMS_ON:
 		I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
 		break;
@@ -933,7 +933,7 @@
 {
 	int i;
 
-	for (i = 0; i < sizeof(tv_modes) / sizeof (tv_modes[0]); i++) {
+	for (i = 0; i < sizeof(tv_modes) / sizeof(tv_modes[0]); i++) {
 		const struct tv_mode *tv_mode = &tv_modes[i];
 
 		if (!strcmp(tv_format, tv_mode->name))
@@ -1128,7 +1128,7 @@
 	if (color_conversion) {
 		I915_WRITE(TV_CSC_Y, (color_conversion->ry << 16) |
 			   color_conversion->gy);
-		I915_WRITE(TV_CSC_Y2,(color_conversion->by << 16) |
+		I915_WRITE(TV_CSC_Y2, (color_conversion->by << 16) |
 			   color_conversion->ay);
 		I915_WRITE(TV_CSC_U, (color_conversion->ru << 16) |
 			   color_conversion->gu);
@@ -1232,7 +1232,7 @@
  * \return false if TV is disconnected.
  */
 static int
-intel_tv_detect_type (struct intel_tv *intel_tv,
+intel_tv_detect_type(struct intel_tv *intel_tv,
 		      struct drm_connector *connector)
 {
 	struct drm_encoder *encoder = &intel_tv->base.base;
@@ -1486,7 +1486,7 @@
 }
 
 static void
-intel_tv_destroy (struct drm_connector *connector)
+intel_tv_destroy(struct drm_connector *connector)
 {
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/Kconfig linux-libre-3.2-gnu/drivers/gpu/drm/Kconfig
--- linux-libre-3.1-gnu/drivers/gpu/drm/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -9,7 +9,6 @@
 	depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU
 	select I2C
 	select I2C_ALGOBIT
-	select SLOW_WORK
 	help
 	  Kernel-level support for the Direct Rendering Infrastructure (DRI)
 	  introduced in XFree86 4.0. If you say Y here, you need to select
@@ -96,6 +95,7 @@
 	select FB_CFB_IMAGEBLIT
 	# i915 depends on ACPI_VIDEO when ACPI is enabled
 	# but for select to work, need to select ACPI_VIDEO's dependencies, ick
+	select BACKLIGHT_LCD_SUPPORT if ACPI
 	select BACKLIGHT_CLASS_DEVICE if ACPI
 	select VIDEO_OUTPUT_CONTROL if ACPI
 	select INPUT if ACPI
@@ -158,3 +158,7 @@
 	help
 	  Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
 	  chipset. If M is selected the module will be called savage.
+
+source "drivers/gpu/drm/exynos/Kconfig"
+
+source "drivers/gpu/drm/vmwgfx/Kconfig"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/Makefile linux-libre-3.2-gnu/drivers/gpu/drm/Makefile
--- linux-libre-3.1-gnu/drivers/gpu/drm/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -35,4 +35,5 @@
 obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/
 obj-$(CONFIG_DRM_VIA)	+=via/
 obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/
+obj-$(CONFIG_DRM_EXYNOS) +=exynos/
 obj-y			+= i2c/
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/mga/mga_drv.c linux-libre-3.2-gnu/drivers/gpu/drm/mga/mga_drv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/mga/mga_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/mga/mga_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,8 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "drm.h"
 #include "mga_drm.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/mga/mga_warp.c linux-libre-3.2-gnu/drivers/gpu/drm/mga/mga_warp.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/mga/mga_warp.c	2012-03-19 21:29:47.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/mga/mga_warp.c	2012-03-19 21:31:27.000000000 -0400
@@ -30,6 +30,7 @@
 #include <linux/firmware.h>
 #include <linux/ihex.h>
 #include <linux/platform_device.h>
+#include <linux/module.h>
 
 #include "drmP.h"
 #include "drm.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/Makefile linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/Makefile
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -21,16 +21,17 @@
              nv40_grctx.o nv50_grctx.o nvc0_grctx.o \
              nv84_crypt.o \
              nva3_copy.o nvc0_copy.o \
-             nv40_mpeg.o nv50_mpeg.o \
+             nv31_mpeg.o nv50_mpeg.o \
              nv04_instmem.o nv50_instmem.o nvc0_instmem.o \
-             nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \
-             nv50_cursor.o nv50_display.o \
              nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
              nv04_crtc.o nv04_display.o nv04_cursor.o \
+             nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \
+             nv50_cursor.o nv50_display.o \
+             nvd0_display.o \
              nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o \
              nv10_gpio.o nv50_gpio.o \
 	     nv50_calc.o \
-	     nv04_pm.o nv50_pm.o nva3_pm.o \
+	     nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \
 	     nv50_vram.o nvc0_vram.o \
 	     nv50_vm.o nvc0_vm.o
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,8 +37,10 @@
 #include "nouveau_drv.h"
 #include "nouveau_drm.h"
 #include "nouveau_reg.h"
+#include "nouveau_encoder.h"
 
-static int nv40_get_intensity(struct backlight_device *bd)
+static int
+nv40_get_intensity(struct backlight_device *bd)
 {
 	struct drm_device *dev = bl_get_data(bd);
 	int val = (nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK)
@@ -47,7 +49,8 @@
 	return val;
 }
 
-static int nv40_set_intensity(struct backlight_device *bd)
+static int
+nv40_set_intensity(struct backlight_device *bd)
 {
 	struct drm_device *dev = bl_get_data(bd);
 	int val = bd->props.brightness;
@@ -65,30 +68,8 @@
 	.update_status = nv40_set_intensity,
 };
 
-static int nv50_get_intensity(struct backlight_device *bd)
-{
-	struct drm_device *dev = bl_get_data(bd);
-
-	return nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT);
-}
-
-static int nv50_set_intensity(struct backlight_device *bd)
-{
-	struct drm_device *dev = bl_get_data(bd);
-	int val = bd->props.brightness;
-
-	nv_wr32(dev, NV50_PDISPLAY_SOR_BACKLIGHT,
-		val | NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE);
-	return 0;
-}
-
-static const struct backlight_ops nv50_bl_ops = {
-	.options = BL_CORE_SUSPENDRESUME,
-	.get_brightness = nv50_get_intensity,
-	.update_status = nv50_set_intensity,
-};
-
-static int nouveau_nv40_backlight_init(struct drm_connector *connector)
+static int
+nv40_backlight_init(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -113,34 +94,129 @@
 	return 0;
 }
 
-static int nouveau_nv50_backlight_init(struct drm_connector *connector)
+static int
+nv50_get_intensity(struct backlight_device *bd)
+{
+	struct nouveau_encoder *nv_encoder = bl_get_data(bd);
+	struct drm_device *dev = nv_encoder->base.base.dev;
+	int or = nv_encoder->or;
+	u32 div = 1025;
+	u32 val;
+
+	val  = nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(or));
+	val &= NV50_PDISP_SOR_PWM_CTL_VAL;
+	return ((val * 100) + (div / 2)) / div;
+}
+
+static int
+nv50_set_intensity(struct backlight_device *bd)
+{
+	struct nouveau_encoder *nv_encoder = bl_get_data(bd);
+	struct drm_device *dev = nv_encoder->base.base.dev;
+	int or = nv_encoder->or;
+	u32 div = 1025;
+	u32 val = (bd->props.brightness * div) / 100;
+
+	nv_wr32(dev, NV50_PDISP_SOR_PWM_CTL(or),
+		     NV50_PDISP_SOR_PWM_CTL_NEW | val);
+	return 0;
+}
+
+static const struct backlight_ops nv50_bl_ops = {
+	.options = BL_CORE_SUSPENDRESUME,
+	.get_brightness = nv50_get_intensity,
+	.update_status = nv50_set_intensity,
+};
+
+static int
+nva3_get_intensity(struct backlight_device *bd)
+{
+	struct nouveau_encoder *nv_encoder = bl_get_data(bd);
+	struct drm_device *dev = nv_encoder->base.base.dev;
+	int or = nv_encoder->or;
+	u32 div, val;
+
+	div  = nv_rd32(dev, NV50_PDISP_SOR_PWM_DIV(or));
+	val  = nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(or));
+	val &= NVA3_PDISP_SOR_PWM_CTL_VAL;
+	if (div && div >= val)
+		return ((val * 100) + (div / 2)) / div;
+
+	return 100;
+}
+
+static int
+nva3_set_intensity(struct backlight_device *bd)
+{
+	struct nouveau_encoder *nv_encoder = bl_get_data(bd);
+	struct drm_device *dev = nv_encoder->base.base.dev;
+	int or = nv_encoder->or;
+	u32 div, val;
+
+	div = nv_rd32(dev, NV50_PDISP_SOR_PWM_DIV(or));
+	val = (bd->props.brightness * div) / 100;
+	if (div) {
+		nv_wr32(dev, NV50_PDISP_SOR_PWM_CTL(or), val |
+			     NV50_PDISP_SOR_PWM_CTL_NEW |
+			     NVA3_PDISP_SOR_PWM_CTL_UNK);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static const struct backlight_ops nva3_bl_ops = {
+	.options = BL_CORE_SUSPENDRESUME,
+	.get_brightness = nva3_get_intensity,
+	.update_status = nva3_set_intensity,
+};
+
+static int
+nv50_backlight_init(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_encoder *nv_encoder;
 	struct backlight_properties props;
 	struct backlight_device *bd;
+	const struct backlight_ops *ops;
 
-	if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT))
+	nv_encoder = find_encoder(connector, OUTPUT_LVDS);
+	if (!nv_encoder) {
+		nv_encoder = find_encoder(connector, OUTPUT_DP);
+		if (!nv_encoder)
+			return -ENODEV;
+	}
+
+	if (!nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(nv_encoder->or)))
 		return 0;
 
+	if (dev_priv->chipset <= 0xa0 ||
+	    dev_priv->chipset == 0xaa ||
+	    dev_priv->chipset == 0xac)
+		ops = &nv50_bl_ops;
+	else
+		ops = &nva3_bl_ops;
+
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.type = BACKLIGHT_RAW;
-	props.max_brightness = 1025;
-	bd = backlight_device_register("nv_backlight", &connector->kdev, dev,
-				       &nv50_bl_ops, &props);
+	props.max_brightness = 100;
+	bd = backlight_device_register("nv_backlight", &connector->kdev,
+				       nv_encoder, ops, &props);
 	if (IS_ERR(bd))
 		return PTR_ERR(bd);
 
 	dev_priv->backlight = bd;
-	bd->props.brightness = nv50_get_intensity(bd);
+	bd->props.brightness = bd->ops->get_brightness(bd);
 	backlight_update_status(bd);
 	return 0;
 }
 
-int nouveau_backlight_init(struct drm_connector *connector)
+int
+nouveau_backlight_init(struct drm_device *dev)
 {
-	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_connector *connector;
 
 #ifdef CONFIG_ACPI
 	if (acpi_video_backlight_support()) {
@@ -150,21 +226,28 @@
 	}
 #endif
 
-	switch (dev_priv->card_type) {
-	case NV_40:
-		return nouveau_nv40_backlight_init(connector);
-	case NV_50:
-		return nouveau_nv50_backlight_init(connector);
-	default:
-		break;
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
+		    connector->connector_type != DRM_MODE_CONNECTOR_eDP)
+			continue;
+
+		switch (dev_priv->card_type) {
+		case NV_40:
+			return nv40_backlight_init(connector);
+		case NV_50:
+			return nv50_backlight_init(connector);
+		default:
+			break;
+		}
 	}
 
+
 	return 0;
 }
 
-void nouveau_backlight_exit(struct drm_connector *connector)
+void
+nouveau_backlight_exit(struct drm_device *dev)
 {
-	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
 	if (dev_priv->backlight) {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c	2012-01-04 18:55:44.000000000 -0500
@@ -296,6 +296,11 @@
 	if (dev_priv->card_type < NV_50)
 		return reg;
 
+	if (reg & 0x80000000) {
+		BUG_ON(bios->display.crtc < 0);
+		reg += bios->display.crtc * 0x800;
+	}
+
 	if (reg & 0x40000000) {
 		BUG_ON(!dcbent);
 
@@ -304,7 +309,7 @@
 			reg += 0x00000080;
 	}
 
-	reg &= ~0x60000000;
+	reg &= ~0xe0000000;
 	return reg;
 }
 
@@ -635,10 +640,9 @@
 nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	uint32_t reg0 = nv_rd32(dev, reg + 0);
-	uint32_t reg1 = nv_rd32(dev, reg + 4);
 	struct nouveau_pll_vals pll;
 	struct pll_lims pll_limits;
+	u32 ctrl, mask, coef;
 	int ret;
 
 	ret = get_pll_limits(dev, reg, &pll_limits);
@@ -649,15 +653,20 @@
 	if (!clk)
 		return -ERANGE;
 
-	reg0 = (reg0 & 0xfff8ffff) | (pll.log2P << 16);
-	reg1 = (reg1 & 0xffff0000) | (pll.N1 << 8) | pll.M1;
-
-	if (dev_priv->vbios.execute) {
-		still_alive();
-		nv_wr32(dev, reg + 4, reg1);
-		nv_wr32(dev, reg + 0, reg0);
+	coef = pll.N1 << 8 | pll.M1;
+	ctrl = pll.log2P << 16;
+	mask = 0x00070000;
+	if (reg == 0x004008) {
+		mask |= 0x01f80000;
+		ctrl |= (pll_limits.log2p_bias << 19);
+		ctrl |= (pll.log2P << 22);
 	}
 
+	if (!dev_priv->vbios.execute)
+		return 0;
+
+	nv_mask(dev, reg + 0, mask, ctrl);
+	nv_wr32(dev, reg + 4, coef);
 	return 0;
 }
 
@@ -1174,22 +1183,19 @@
 	 *
 	 */
 
-	struct bit_displayport_encoder_table *dpe = NULL;
 	struct dcb_entry *dcb = bios->display.output;
 	struct drm_device *dev = bios->dev;
 	uint8_t cond = bios->data[offset + 1];
-	int dummy;
+	uint8_t *table, *entry;
 
 	BIOSLOG(bios, "0x%04X: subop 0x%02X\n", offset, cond);
 
 	if (!iexec->execute)
 		return 3;
 
-	dpe = nouveau_bios_dp_table(dev, dcb, &dummy);
-	if (!dpe) {
-		NV_ERROR(dev, "0x%04X: INIT_3A: no encoder table!!\n", offset);
+	table = nouveau_dp_bios_data(dev, dcb, &entry);
+	if (!table)
 		return 3;
-	}
 
 	switch (cond) {
 	case 0:
@@ -1203,7 +1209,7 @@
 		break;
 	case 1:
 	case 2:
-		if (!(dpe->unknown & cond))
+		if (!(entry[5] & cond))
 			iexec->execute = false;
 		break;
 	case 5:
@@ -3221,6 +3227,49 @@
 	return 1;
 }
 
+static void
+init_gpio_unknv50(struct nvbios *bios, struct dcb_gpio_entry *gpio)
+{
+	const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c };
+	u32 r, s, v;
+
+	/* Not a clue, needs de-magicing */
+	r = nv50_gpio_ctl[gpio->line >> 4];
+	s = (gpio->line & 0x0f);
+	v = bios_rd32(bios, r) & ~(0x00010001 << s);
+	switch ((gpio->entry & 0x06000000) >> 25) {
+	case 1:
+		v |= (0x00000001 << s);
+		break;
+	case 2:
+		v |= (0x00010000 << s);
+		break;
+	default:
+		break;
+	}
+
+	bios_wr32(bios, r, v);
+}
+
+static void
+init_gpio_unknvd0(struct nvbios *bios, struct dcb_gpio_entry *gpio)
+{
+	u32 v, i;
+
+	v  = bios_rd32(bios, 0x00d610 + (gpio->line * 4));
+	v &= 0xffffff00;
+	v |= (gpio->entry & 0x00ff0000) >> 16;
+	bios_wr32(bios, 0x00d610 + (gpio->line * 4), v);
+
+	i = (gpio->entry & 0x1f000000) >> 24;
+	if (i) {
+		v  = bios_rd32(bios, 0x00d640 + ((i - 1) * 4));
+		v &= 0xffffff00;
+		v |= gpio->line;
+		bios_wr32(bios, 0x00d640 + ((i - 1) * 4), v);
+	}
+}
+
 static int
 init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
@@ -3235,7 +3284,6 @@
 
 	struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
 	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
-	const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c };
 	int i;
 
 	if (dev_priv->card_type < NV_50) {
@@ -3248,33 +3296,20 @@
 
 	for (i = 0; i < bios->dcb.gpio.entries; i++) {
 		struct dcb_gpio_entry *gpio = &bios->dcb.gpio.entry[i];
-		uint32_t r, s, v;
 
 		BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);
 
 		BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n",
 			offset, gpio->tag, gpio->state_default);
-		if (bios->execute)
-			pgpio->set(bios->dev, gpio->tag, gpio->state_default);
 
-		/* The NVIDIA binary driver doesn't appear to actually do
-		 * any of this, my VBIOS does however.
-		 */
-		/* Not a clue, needs de-magicing */
-		r = nv50_gpio_ctl[gpio->line >> 4];
-		s = (gpio->line & 0x0f);
-		v = bios_rd32(bios, r) & ~(0x00010001 << s);
-		switch ((gpio->entry & 0x06000000) >> 25) {
-		case 1:
-			v |= (0x00000001 << s);
-			break;
-		case 2:
-			v |= (0x00010000 << s);
-			break;
-		default:
-			break;
-		}
-		bios_wr32(bios, r, v);
+		if (!bios->execute)
+			continue;
+
+		pgpio->set(bios->dev, gpio->tag, gpio->state_default);
+		if (dev_priv->card_type < NV_D0)
+			init_gpio_unknv50(bios, gpio);
+		else
+			init_gpio_unknvd0(bios, gpio);
 	}
 
 	return 1;
@@ -3737,6 +3772,10 @@
 	int count = 0, i, ret;
 	uint8_t id;
 
+	/* catch NULL script pointers */
+	if (offset == 0)
+		return 0;
+
 	/*
 	 * Loop until INIT_DONE causes us to break out of the loop
 	 * (or until offset > bios length just in case... )
@@ -4389,86 +4428,37 @@
 	return 0;
 }
 
-static uint8_t *
-bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent,
-			 uint16_t record, int record_len, int record_nr,
-			 bool match_link)
+/* BIT 'U'/'d' table encoder subtables have hashes matching them to
+ * a particular set of encoders.
+ *
+ * This function returns true if a particular DCB entry matches.
+ */
+bool
+bios_encoder_match(struct dcb_entry *dcb, u32 hash)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->vbios;
-	uint32_t entry;
-	uint16_t table;
-	int i, v;
+	if ((hash & 0x000000f0) != (dcb->location << 4))
+		return false;
+	if ((hash & 0x0000000f) != dcb->type)
+		return false;
+	if (!(hash & (dcb->or << 16)))
+		return false;
 
-	switch (dcbent->type) {
+	switch (dcb->type) {
 	case OUTPUT_TMDS:
 	case OUTPUT_LVDS:
 	case OUTPUT_DP:
-		break;
-	default:
-		match_link = false;
-		break;
-	}
-
-	for (i = 0; i < record_nr; i++, record += record_len) {
-		table = ROM16(bios->data[record]);
-		if (!table)
-			continue;
-		entry = ROM32(bios->data[table]);
-
-		if (match_link) {
-			v = (entry & 0x00c00000) >> 22;
-			if (!(v & dcbent->sorconf.link))
-				continue;
+		if (hash & 0x00c00000) {
+			if (!(hash & (dcb->sorconf.link << 22)))
+				return false;
 		}
-
-		v = (entry & 0x000f0000) >> 16;
-		if (!(v & dcbent->or))
-			continue;
-
-		v = (entry & 0x000000f0) >> 4;
-		if (v != dcbent->location)
-			continue;
-
-		v = (entry & 0x0000000f);
-		if (v != dcbent->type)
-			continue;
-
-		return &bios->data[table];
-	}
-
-	return NULL;
-}
-
-void *
-nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
-		      int *length)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->vbios;
-	uint8_t *table;
-
-	if (!bios->display.dp_table_ptr) {
-		NV_ERROR(dev, "No pointer to DisplayPort table\n");
-		return NULL;
-	}
-	table = &bios->data[bios->display.dp_table_ptr];
-
-	if (table[0] != 0x20 && table[0] != 0x21) {
-		NV_ERROR(dev, "DisplayPort table version 0x%02x unknown\n",
-			 table[0]);
-		return NULL;
+	default:
+		return true;
 	}
-
-	*length = table[4];
-	return bios_output_config_match(dev, dcbent,
-					bios->display.dp_table_ptr + table[1],
-					table[2], table[3], table[0] >= 0x21);
 }
 
 int
-nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
-			       uint32_t sub, int pxclk)
+nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk,
+			       struct dcb_entry *dcbent, int crtc)
 {
 	/*
 	 * The display script table is located by the BIT 'U' table.
@@ -4498,7 +4488,7 @@
 	uint8_t *table = &bios->data[bios->display.script_table_ptr];
 	uint8_t *otable = NULL;
 	uint16_t script;
-	int i = 0;
+	int i;
 
 	if (!bios->display.script_table_ptr) {
 		NV_ERROR(dev, "No pointer to output script table\n");
@@ -4550,30 +4540,33 @@
 
 	NV_DEBUG_KMS(dev, "Searching for output entry for %d %d %d\n",
 			dcbent->type, dcbent->location, dcbent->or);
-	otable = bios_output_config_match(dev, dcbent, table[1] +
-					  bios->display.script_table_ptr,
-					  table[2], table[3], table[0] >= 0x21);
+	for (i = 0; i < table[3]; i++) {
+		otable = ROMPTR(bios, table[table[1] + (i * table[2])]);
+		if (otable && bios_encoder_match(dcbent, ROM32(otable[0])))
+			break;
+	}
+
 	if (!otable) {
 		NV_DEBUG_KMS(dev, "failed to match any output table\n");
 		return 1;
 	}
 
-	if (pxclk < -2 || pxclk > 0) {
+	if (pclk < -2 || pclk > 0) {
 		/* Try to find matching script table entry */
 		for (i = 0; i < otable[5]; i++) {
-			if (ROM16(otable[table[4] + i*6]) == sub)
+			if (ROM16(otable[table[4] + i*6]) == type)
 				break;
 		}
 
 		if (i == otable[5]) {
 			NV_ERROR(dev, "Table 0x%04x not found for %d/%d, "
 				      "using first\n",
-				 sub, dcbent->type, dcbent->or);
+				 type, dcbent->type, dcbent->or);
 			i = 0;
 		}
 	}
 
-	if (pxclk == 0) {
+	if (pclk == 0) {
 		script = ROM16(otable[6]);
 		if (!script) {
 			NV_DEBUG_KMS(dev, "output script 0 not found\n");
@@ -4581,9 +4574,9 @@
 		}
 
 		NV_DEBUG_KMS(dev, "0x%04X: parsing output script 0\n", script);
-		nouveau_bios_run_init_table(dev, script, dcbent);
+		nouveau_bios_run_init_table(dev, script, dcbent, crtc);
 	} else
-	if (pxclk == -1) {
+	if (pclk == -1) {
 		script = ROM16(otable[8]);
 		if (!script) {
 			NV_DEBUG_KMS(dev, "output script 1 not found\n");
@@ -4591,9 +4584,9 @@
 		}
 
 		NV_DEBUG_KMS(dev, "0x%04X: parsing output script 1\n", script);
-		nouveau_bios_run_init_table(dev, script, dcbent);
+		nouveau_bios_run_init_table(dev, script, dcbent, crtc);
 	} else
-	if (pxclk == -2) {
+	if (pclk == -2) {
 		if (table[4] >= 12)
 			script = ROM16(otable[10]);
 		else
@@ -4604,31 +4597,31 @@
 		}
 
 		NV_DEBUG_KMS(dev, "0x%04X: parsing output script 2\n", script);
-		nouveau_bios_run_init_table(dev, script, dcbent);
+		nouveau_bios_run_init_table(dev, script, dcbent, crtc);
 	} else
-	if (pxclk > 0) {
+	if (pclk > 0) {
 		script = ROM16(otable[table[4] + i*6 + 2]);
 		if (script)
-			script = clkcmptable(bios, script, pxclk);
+			script = clkcmptable(bios, script, pclk);
 		if (!script) {
 			NV_DEBUG_KMS(dev, "clock script 0 not found\n");
 			return 1;
 		}
 
 		NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 0\n", script);
-		nouveau_bios_run_init_table(dev, script, dcbent);
+		nouveau_bios_run_init_table(dev, script, dcbent, crtc);
 	} else
-	if (pxclk < 0) {
+	if (pclk < 0) {
 		script = ROM16(otable[table[4] + i*6 + 4]);
 		if (script)
-			script = clkcmptable(bios, script, -pxclk);
+			script = clkcmptable(bios, script, -pclk);
 		if (!script) {
 			NV_DEBUG_KMS(dev, "clock script 1 not found\n");
 			return 1;
 		}
 
 		NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 1\n", script);
-		nouveau_bios_run_init_table(dev, script, dcbent);
+		nouveau_bios_run_init_table(dev, script, dcbent, crtc);
 	}
 
 	return 0;
@@ -5478,14 +5471,6 @@
 	return 0;
 }
 
-static int
-parse_bit_displayport_tbl_entry(struct drm_device *dev, struct nvbios *bios,
-				struct bit_entry *bitentry)
-{
-	bios->display.dp_table_ptr = ROM16(bios->data[bitentry->offset]);
-	return 0;
-}
-
 struct bit_table {
 	const char id;
 	int (* const parse_fn)(struct drm_device *, struct nvbios *, struct bit_entry *);
@@ -5559,7 +5544,6 @@
 	parse_bit_table(bios, bitoffset, &BIT_TABLE('L', lvds));
 	parse_bit_table(bios, bitoffset, &BIT_TABLE('T', tmds));
 	parse_bit_table(bios, bitoffset, &BIT_TABLE('U', U));
-	parse_bit_table(bios, bitoffset, &BIT_TABLE('d', displayport));
 
 	return 0;
 }
@@ -5884,9 +5868,15 @@
 			}
 
 			e->line = (e->entry & 0x0000001f) >> 0;
-			e->state_default = (e->entry & 0x01000000) >> 24;
-			e->state[0] = (e->entry & 0x18000000) >> 27;
-			e->state[1] = (e->entry & 0x60000000) >> 29;
+			if (gpio[0] == 0x40) {
+				e->state_default = (e->entry & 0x01000000) >> 24;
+				e->state[0] = (e->entry & 0x18000000) >> 27;
+				e->state[1] = (e->entry & 0x60000000) >> 29;
+			} else {
+				e->state_default = (e->entry & 0x00000080) >> 7;
+				e->state[0] = (entry[4] >> 4) & 3;
+				e->state[1] = (entry[4] >> 6) & 3;
+			}
 		}
 	}
 
@@ -6156,7 +6146,14 @@
 	}
 	case OUTPUT_DP:
 		entry->dpconf.sor.link = (conf & 0x00000030) >> 4;
-		entry->dpconf.link_bw = (conf & 0x00e00000) >> 21;
+		switch ((conf & 0x00e00000) >> 21) {
+		case 0:
+			entry->dpconf.link_bw = 162000;
+			break;
+		default:
+			entry->dpconf.link_bw = 270000;
+			break;
+		}
 		switch ((conf & 0x0f000000) >> 24) {
 		case 0xf:
 			entry->dpconf.link_nr = 4;
@@ -6769,7 +6766,7 @@
 
 void
 nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table,
-			    struct dcb_entry *dcbent)
+			    struct dcb_entry *dcbent, int crtc)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nvbios *bios = &dev_priv->vbios;
@@ -6777,11 +6774,22 @@
 
 	spin_lock_bh(&bios->lock);
 	bios->display.output = dcbent;
+	bios->display.crtc = crtc;
 	parse_init_table(bios, table, &iexec);
 	bios->display.output = NULL;
 	spin_unlock_bh(&bios->lock);
 }
 
+void
+nouveau_bios_init_exec(struct drm_device *dev, uint16_t table)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->vbios;
+	struct init_exec iexec = { true, false };
+
+	parse_init_table(bios, table, &iexec);
+}
+
 static bool NVInitVBIOS(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -6863,9 +6871,8 @@
 
 	if (dev_priv->card_type >= NV_50) {
 		for (i = 0; i < bios->dcb.entries; i++) {
-			nouveau_bios_run_display_table(dev,
-						       &bios->dcb.entry[i],
-						       0, 0);
+			nouveau_bios_run_display_table(dev, 0, 0,
+						       &bios->dcb.entry[i], -1);
 		}
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_bios.h linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_bios.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_bios.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_bios.h	2012-01-04 18:55:44.000000000 -0500
@@ -289,8 +289,8 @@
 
 	struct {
 		struct dcb_entry *output;
+		int crtc;
 		uint16_t script_table_ptr;
-		uint16_t dp_table_ptr;
 	} display;
 
 	struct {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c	2012-01-04 18:55:44.000000000 -0500
@@ -148,7 +148,7 @@
 
 	if (dev_priv->card_type == NV_10 &&
 	    nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) &&
-	    nvbo->bo.mem.num_pages < vram_pages / 2) {
+	    nvbo->bo.mem.num_pages < vram_pages / 4) {
 		/*
 		 * Make sure that the color and depth buffers are handled
 		 * by independent memory controller units. Up to a 9x
@@ -956,7 +956,7 @@
 			break;
 		}
 
-		if (dev_priv->card_type == NV_C0)
+		if (dev_priv->card_type >= NV_C0)
 			page_shift = node->page_shift;
 		else
 			page_shift = 12;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_channel.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_channel.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_channel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_channel.c	2012-01-04 18:55:44.000000000 -0500
@@ -158,6 +158,7 @@
 	INIT_LIST_HEAD(&chan->nvsw.vbl_wait);
 	INIT_LIST_HEAD(&chan->nvsw.flip);
 	INIT_LIST_HEAD(&chan->fence.pending);
+	spin_lock_init(&chan->fence.lock);
 
 	/* setup channel's memory and vm */
 	ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
@@ -411,13 +412,17 @@
 		return ret;
 	init->channel  = chan->id;
 
-	if (chan->dma.ib_max)
-		init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM |
-					NOUVEAU_GEM_DOMAIN_GART;
-	else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM)
+	if (nouveau_vram_pushbuf == 0) {
+		if (chan->dma.ib_max)
+			init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM |
+						NOUVEAU_GEM_DOMAIN_GART;
+		else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM)
+			init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM;
+		else
+			init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART;
+	} else {
 		init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM;
-	else
-		init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART;
+	}
 
 	if (dev_priv->card_type < NV_C0) {
 		init->subchan[0].handle = NvM2MF;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,7 +39,7 @@
 
 static void nouveau_connector_hotplug(void *, int);
 
-static struct nouveau_encoder *
+struct nouveau_encoder *
 find_encoder(struct drm_connector *connector, int type)
 {
 	struct drm_device *dev = connector->dev;
@@ -116,10 +116,6 @@
 				      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);
@@ -712,12 +708,9 @@
 	case OUTPUT_TV:
 		return get_slave_funcs(encoder)->mode_valid(encoder, mode);
 	case OUTPUT_DP:
-		if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7)
-			max_clock = nv_encoder->dp.link_nr * 270000;
-		else
-			max_clock = nv_encoder->dp.link_nr * 162000;
-
-		clock = clock * nouveau_connector_bpp(connector) / 8;
+		max_clock  = nv_encoder->dp.link_nr;
+		max_clock *= nv_encoder->dp.link_bw;
+		clock = clock * nouveau_connector_bpp(connector) / 10;
 		break;
 	default:
 		BUG_ON(1);
@@ -871,7 +864,6 @@
 					dev->mode_config.scaling_mode_property,
 					nv_connector->scaling_mode);
 		}
-		connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 		/* fall-through */
 	case DCB_CONNECTOR_TV_0:
 	case DCB_CONNECTOR_TV_1:
@@ -888,27 +880,20 @@
 				dev->mode_config.dithering_mode_property,
 				nv_connector->use_dithering ?
 				DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF);
-
-		if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS) {
-			if (dev_priv->card_type >= NV_50)
-				connector->polled = DRM_CONNECTOR_POLL_HPD;
-			else
-				connector->polled = DRM_CONNECTOR_POLL_CONNECT;
-		}
 		break;
 	}
 
-	if (pgpio->irq_register) {
+	if (nv_connector->dcb->gpio_tag != 0xff && pgpio->irq_register) {
 		pgpio->irq_register(dev, nv_connector->dcb->gpio_tag,
 				    nouveau_connector_hotplug, connector);
+
+		connector->polled = DRM_CONNECTOR_POLL_HPD;
+	} else {
+		connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 	}
 
 	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;
 
@@ -925,22 +910,13 @@
 	struct drm_connector *connector = data;
 	struct drm_device *dev = connector->dev;
 
-	NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un",
-		drm_get_connector_name(connector));
-
-	if (connector->encoder && connector->encoder->crtc &&
-	    connector->encoder->crtc->enabled) {
-		struct nouveau_encoder *nv_encoder = nouveau_encoder(connector->encoder);
-		struct drm_encoder_helper_funcs *helper =
-			connector->encoder->helper_private;
+	NV_DEBUG(dev, "%splugged %s\n", plugged ? "" : "un",
+		 drm_get_connector_name(connector));
 
-		if (nv_encoder->dcb->type == OUTPUT_DP) {
-			if (plugged)
-				helper->dpms(connector->encoder, DRM_MODE_DPMS_ON);
-			else
-				helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF);
-		}
-	}
+	if (plugged)
+		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+	else
+		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
 
 	drm_helper_hpd_irq_event(dev);
 }
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_crtc.h linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_crtc.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_crtc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_crtc.h	2012-01-04 18:55:44.000000000 -0500
@@ -82,14 +82,13 @@
 }
 
 int nv50_crtc_create(struct drm_device *dev, int index);
-int nv50_cursor_init(struct nouveau_crtc *);
-void nv50_cursor_fini(struct nouveau_crtc *);
 int nv50_crtc_cursor_set(struct drm_crtc *drm_crtc, struct drm_file *file_priv,
 			 uint32_t buffer_handle, uint32_t width,
 			 uint32_t height);
 int nv50_crtc_cursor_move(struct drm_crtc *drm_crtc, int x, int y);
 
 int nv04_cursor_init(struct nouveau_crtc *);
+int nv50_cursor_init(struct nouveau_crtc *);
 
 struct nouveau_connector *
 nouveau_crtc_connector_get(struct nouveau_crtc *crtc);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_display.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_display.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_display.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_display.c	2012-01-04 18:55:44.000000000 -0500
@@ -105,9 +105,12 @@
 		if (dev_priv->chipset == 0x50)
 			nv_fb->r_format |= (tile_flags << 8);
 
-		if (!tile_flags)
-			nv_fb->r_pitch = 0x00100000 | fb->pitch;
-		else {
+		if (!tile_flags) {
+			if (dev_priv->card_type < NV_D0)
+				nv_fb->r_pitch = 0x00100000 | fb->pitch;
+			else
+				nv_fb->r_pitch = 0x01000000 | fb->pitch;
+		} else {
 			u32 mode = nvbo->tile_mode;
 			if (dev_priv->card_type >= NV_C0)
 				mode >>= 4;
@@ -366,3 +369,48 @@
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 	return 0;
 }
+
+int
+nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
+			    struct drm_mode_create_dumb *args)
+{
+	struct nouveau_bo *bo;
+	int ret;
+
+	args->pitch = roundup(args->width * (args->bpp / 8), 256);
+	args->size = args->pitch * args->height;
+	args->size = roundup(args->size, PAGE_SIZE);
+
+	ret = nouveau_gem_new(dev, args->size, 0, TTM_PL_FLAG_VRAM, 0, 0, &bo);
+	if (ret)
+		return ret;
+
+	ret = drm_gem_handle_create(file_priv, bo->gem, &args->handle);
+	drm_gem_object_unreference_unlocked(bo->gem);
+	return ret;
+}
+
+int
+nouveau_display_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev,
+			     uint32_t handle)
+{
+	return drm_gem_handle_delete(file_priv, handle);
+}
+
+int
+nouveau_display_dumb_map_offset(struct drm_file *file_priv,
+				struct drm_device *dev,
+				uint32_t handle, uint64_t *poffset)
+{
+	struct drm_gem_object *gem;
+
+	gem = drm_gem_object_lookup(dev, file_priv, handle);
+	if (gem) {
+		struct nouveau_bo *bo = gem->driver_private;
+		*poffset = bo->bo.addr_space_offset;
+		drm_gem_object_unreference_unlocked(gem);
+		return 0;
+	}
+
+	return -ENOENT;
+}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,557 +28,669 @@
 #include "nouveau_i2c.h"
 #include "nouveau_connector.h"
 #include "nouveau_encoder.h"
+#include "nouveau_crtc.h"
 
-static int
-auxch_rd(struct drm_encoder *encoder, int address, uint8_t *buf, int size)
-{
-	struct drm_device *dev = encoder->dev;
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct nouveau_i2c_chan *auxch;
-	int ret;
-
-	auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
-	if (!auxch)
-		return -ENODEV;
-
-	ret = nouveau_dp_auxch(auxch, 9, address, buf, size);
-	if (ret)
-		return ret;
+/******************************************************************************
+ * aux channel util functions
+ *****************************************************************************/
+#define AUX_DBG(fmt, args...) do {                                             \
+	if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_AUXCH) {                     \
+		NV_PRINTK(KERN_DEBUG, dev, "AUXCH(%d): " fmt, ch, ##args);     \
+	}                                                                      \
+} while (0)
+#define AUX_ERR(fmt, args...) NV_ERROR(dev, "AUXCH(%d): " fmt, ch, ##args)
 
-	return 0;
+static void
+auxch_fini(struct drm_device *dev, int ch)
+{
+	nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000);
 }
 
 static int
-auxch_wr(struct drm_encoder *encoder, int address, uint8_t *buf, int size)
+auxch_init(struct drm_device *dev, int ch)
 {
-	struct drm_device *dev = encoder->dev;
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct nouveau_i2c_chan *auxch;
-	int ret;
+	const u32 unksel = 1; /* nfi which to use, or if it matters.. */
+	const u32 ureq = unksel ? 0x00100000 : 0x00200000;
+	const u32 urep = unksel ? 0x01000000 : 0x02000000;
+	u32 ctrl, timeout;
 
-	auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
-	if (!auxch)
-		return -ENODEV;
+	/* wait up to 1ms for any previous transaction to be done... */
+	timeout = 1000;
+	do {
+		ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
+		udelay(1);
+		if (!timeout--) {
+			AUX_ERR("begin idle timeout 0x%08x", ctrl);
+			return -EBUSY;
+		}
+	} while (ctrl & 0x03010000);
 
-	ret = nouveau_dp_auxch(auxch, 8, address, buf, size);
-	return ret;
+	/* set some magic, and wait up to 1ms for it to appear */
+	nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq);
+	timeout = 1000;
+	do {
+		ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
+		udelay(1);
+		if (!timeout--) {
+			AUX_ERR("magic wait 0x%08x\n", ctrl);
+			auxch_fini(dev, ch);
+			return -EBUSY;
+		}
+	} while ((ctrl & 0x03000000) != urep);
+
+	return 0;
 }
 
 static int
-nouveau_dp_lane_count_set(struct drm_encoder *encoder, uint8_t cmd)
+auxch_tx(struct drm_device *dev, int ch, u8 type, u32 addr, u8 *data, u8 size)
 {
-	struct drm_device *dev = encoder->dev;
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	uint32_t tmp;
-	int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1);
+	u32 ctrl, stat, timeout, retries;
+	u32 xbuf[4] = {};
+	int ret, i;
 
-	tmp  = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
-	tmp &= ~(NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED |
-		 NV50_SOR_DP_CTRL_LANE_MASK);
-	tmp |= ((1 << (cmd & DP_LANE_COUNT_MASK)) - 1) << 16;
-	if (cmd & DP_LANE_COUNT_ENHANCED_FRAME_EN)
-		tmp |= NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED;
-	nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp);
+	AUX_DBG("%d: 0x%08x %d\n", type, addr, size);
 
-	return auxch_wr(encoder, DP_LANE_COUNT_SET, &cmd, 1);
-}
+	ret = auxch_init(dev, ch);
+	if (ret)
+		goto out;
 
-static int
-nouveau_dp_link_bw_set(struct drm_encoder *encoder, uint8_t cmd)
-{
-	struct drm_device *dev = encoder->dev;
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	uint32_t tmp;
-	int reg = 0x614300 + (nv_encoder->or * 0x800);
+	stat = nv_rd32(dev, 0x00e4e8 + (ch * 0x50));
+	if (!(stat & 0x10000000)) {
+		AUX_DBG("sink not detected\n");
+		ret = -ENXIO;
+		goto out;
+	}
 
-	tmp  = nv_rd32(dev, reg);
-	tmp &= 0xfff3ffff;
-	if (cmd == DP_LINK_BW_2_7)
-		tmp |= 0x00040000;
-	nv_wr32(dev, reg, tmp);
+	if (!(type & 1)) {
+		memcpy(xbuf, data, size);
+		for (i = 0; i < 16; i += 4) {
+			AUX_DBG("wr 0x%08x\n", xbuf[i / 4]);
+			nv_wr32(dev, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]);
+		}
+	}
 
-	return auxch_wr(encoder, DP_LINK_BW_SET, &cmd, 1);
-}
+	ctrl  = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
+	ctrl &= ~0x0001f0ff;
+	ctrl |= type << 12;
+	ctrl |= size - 1;
+	nv_wr32(dev, 0x00e4e0 + (ch * 0x50), addr);
 
-static int
-nouveau_dp_link_train_set(struct drm_encoder *encoder, int pattern)
-{
-	struct drm_device *dev = encoder->dev;
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	uint32_t tmp;
-	uint8_t cmd;
-	int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1);
-	int ret;
+	/* retry transaction a number of times on failure... */
+	ret = -EREMOTEIO;
+	for (retries = 0; retries < 32; retries++) {
+		/* reset, and delay a while if this is a retry */
+		nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl);
+		nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl);
+		if (retries)
+			udelay(400);
 
-	tmp  = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
-	tmp &= ~NV50_SOR_DP_CTRL_TRAINING_PATTERN;
-	tmp |= (pattern << 24);
-	nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp);
+		/* transaction request, wait up to 1ms for it to complete */
+		nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl);
 
-	ret = auxch_rd(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1);
-	if (ret)
-		return ret;
-	cmd &= ~DP_TRAINING_PATTERN_MASK;
-	cmd |= (pattern & DP_TRAINING_PATTERN_MASK);
-	return auxch_wr(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1);
-}
+		timeout = 1000;
+		do {
+			ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50));
+			udelay(1);
+			if (!timeout--) {
+				AUX_ERR("tx req timeout 0x%08x\n", ctrl);
+				goto out;
+			}
+		} while (ctrl & 0x00010000);
 
-static int
-nouveau_dp_max_voltage_swing(struct drm_encoder *encoder)
-{
-	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 i, dpe_headerlen, max_vs = 0;
+		/* read status, and check if transaction completed ok */
+		stat = nv_mask(dev, 0x00e4e8 + (ch * 0x50), 0, 0);
+		if (!(stat & 0x000f0f00)) {
+			ret = 0;
+			break;
+		}
 
-	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
-	if (!dpe)
-		return false;
-	dpse = (void *)((char *)dpe + dpe_headerlen);
+		AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat);
+	}
 
-	for (i = 0; i < dpe_headerlen; i++, dpse++) {
-		if (dpse->vs_level > max_vs)
-			max_vs = dpse->vs_level;
+	if (type & 1) {
+		for (i = 0; i < 16; i += 4) {
+			xbuf[i / 4] = nv_rd32(dev, 0x00e4d0 + (ch * 0x50) + i);
+			AUX_DBG("rd 0x%08x\n", xbuf[i / 4]);
+		}
+		memcpy(data, xbuf, size);
 	}
 
-	return max_vs;
+out:
+	auxch_fini(dev, ch);
+	return ret;
 }
 
-static int
-nouveau_dp_max_pre_emphasis(struct drm_encoder *encoder, int vs)
+static u32
+dp_link_bw_get(struct drm_device *dev, int or, int link)
 {
-	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 i, dpe_headerlen, max_pre = 0;
-
-	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
-	if (!dpe)
-		return false;
-	dpse = (void *)((char *)dpe + dpe_headerlen);
-
-	for (i = 0; i < dpe_headerlen; i++, dpse++) {
-		if (dpse->vs_level != vs)
-			continue;
+	u32 ctrl = nv_rd32(dev, 0x614300 + (or * 0x800));
+	if (!(ctrl & 0x000c0000))
+		return 162000;
+	return 270000;
+}
 
-		if (dpse->pre_level > max_pre)
-			max_pre = dpse->pre_level;
+static int
+dp_lane_count_get(struct drm_device *dev, int or, int link)
+{
+	u32 ctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
+	switch (ctrl & 0x000f0000) {
+	case 0x00010000: return 1;
+	case 0x00030000: return 2;
+	default:
+		return 4;
 	}
-
-	return max_pre;
 }
 
-static bool
-nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config)
+void
+nouveau_dp_tu_update(struct drm_device *dev, int or, int link, u32 clk, u32 bpp)
 {
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct bit_displayport_encoder_table *dpe;
-	int ret, i, dpe_headerlen, vs = 0, pre = 0;
-	uint8_t request[2];
+	const u32 symbol = 100000;
+	int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0;
+	int TU, VTUi, VTUf, VTUa;
+	u64 link_data_rate, link_ratio, unk;
+	u32 best_diff = 64 * symbol;
+	u32 link_nr, link_bw, r;
 
-	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
-	if (!dpe)
-		return false;
+	/* calculate packed data rate for each lane */
+	link_nr = dp_lane_count_get(dev, or, link);
+	link_data_rate = (clk * bpp / 8) / link_nr;
 
-	ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2);
-	if (ret)
-		return false;
+	/* calculate ratio of packed data rate to link symbol rate */
+	link_bw = dp_link_bw_get(dev, or, link);
+	link_ratio = link_data_rate * symbol;
+	r = do_div(link_ratio, link_bw);
 
-	NV_DEBUG_KMS(dev, "\t\tadjust 0x%02x 0x%02x\n", request[0], request[1]);
+	for (TU = 64; TU >= 32; TU--) {
+		/* calculate average number of valid symbols in each TU */
+		u32 tu_valid = link_ratio * TU;
+		u32 calc, diff;
 
-	/* Keep all lanes at the same level.. */
-	for (i = 0; i < nv_encoder->dp.link_nr; i++) {
-		int lane_req = (request[i >> 1] >> ((i & 1) << 2)) & 0xf;
-		int lane_vs = lane_req & 3;
-		int lane_pre = (lane_req >> 2) & 3;
+		/* find a hw representation for the fraction.. */
+		VTUi = tu_valid / symbol;
+		calc = VTUi * symbol;
+		diff = tu_valid - calc;
+		if (diff) {
+			if (diff >= (symbol / 2)) {
+				VTUf = symbol / (symbol - diff);
+				if (symbol - (VTUf * diff))
+					VTUf++;
 
-		if (lane_vs > vs)
-			vs = lane_vs;
-		if (lane_pre > pre)
-			pre = lane_pre;
-	}
+				if (VTUf <= 15) {
+					VTUa  = 1;
+					calc += symbol - (symbol / VTUf);
+				} else {
+					VTUa  = 0;
+					VTUf  = 1;
+					calc += symbol;
+				}
+			} else {
+				VTUa  = 0;
+				VTUf  = min((int)(symbol / diff), 15);
+				calc += symbol / VTUf;
+			}
 
-	if (vs >= nouveau_dp_max_voltage_swing(encoder)) {
-		vs  = nouveau_dp_max_voltage_swing(encoder);
-		vs |= 4;
+			diff = calc - tu_valid;
+		} else {
+			/* no remainder, but the hw doesn't like the fractional
+			 * part to be zero.  decrement the integer part and
+			 * have the fraction add a whole symbol back
+			 */
+			VTUa = 0;
+			VTUf = 1;
+			VTUi--;
+		}
+
+		if (diff < best_diff) {
+			best_diff = diff;
+			bestTU = TU;
+			bestVTUa = VTUa;
+			bestVTUf = VTUf;
+			bestVTUi = VTUi;
+			if (diff == 0)
+				break;
+		}
 	}
 
-	if (pre >= nouveau_dp_max_pre_emphasis(encoder, vs & 3)) {
-		pre  = nouveau_dp_max_pre_emphasis(encoder, vs & 3);
-		pre |= 4;
+	if (!bestTU) {
+		NV_ERROR(dev, "DP: unable to find suitable config\n");
+		return;
 	}
 
-	/* Update the configuration for all lanes.. */
-	for (i = 0; i < nv_encoder->dp.link_nr; i++)
-		config[i] = (pre << 3) | vs;
+	/* XXX close to vbios numbers, but not right */
+	unk  = (symbol - link_ratio) * bestTU;
+	unk *= link_ratio;
+	r = do_div(unk, symbol);
+	r = do_div(unk, symbol);
+	unk += 6;
 
-	return true;
+	nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2);
+	nv_mask(dev, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 |
+							     bestVTUf << 16 |
+							     bestVTUi << 8 |
+							     unk);
 }
 
-static bool
-nouveau_dp_link_train_commit(struct drm_encoder *encoder, uint8_t *config)
+u8 *
+nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry)
 {
-	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 or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1);
-	int dpe_headerlen, ret, i;
-
-	NV_DEBUG_KMS(dev, "\t\tconfig 0x%02x 0x%02x 0x%02x 0x%02x\n",
-		 config[0], config[1], config[2], config[3]);
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->vbios;
+	struct bit_entry d;
+	u8 *table;
+	int i;
 
-	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
-	if (!dpe)
-		return false;
-	dpse = (void *)((char *)dpe + dpe_headerlen);
+	if (bit_table(dev, 'd', &d)) {
+		NV_ERROR(dev, "BIT 'd' table not found\n");
+		return NULL;
+	}
 
-	for (i = 0; i < dpe->record_nr; i++, dpse++) {
-		if (dpse->vs_level == (config[0] & 3) &&
-		    dpse->pre_level == ((config[0] >> 3) & 3))
-			break;
+	if (d.version != 1) {
+		NV_ERROR(dev, "BIT 'd' table version %d unknown\n", d.version);
+		return NULL;
 	}
-	BUG_ON(i == dpe->record_nr);
 
-	for (i = 0; i < nv_encoder->dp.link_nr; i++) {
-		const int shift[4] = { 16, 8, 0, 24 };
-		uint32_t mask = 0xff << shift[i];
-		uint32_t reg0, reg1, reg2;
+	table = ROMPTR(bios, d.data[0]);
+	if (!table) {
+		NV_ERROR(dev, "displayport table pointer invalid\n");
+		return NULL;
+	}
 
-		reg0  = nv_rd32(dev, NV50_SOR_DP_UNK118(or, link)) & ~mask;
-		reg0 |= (dpse->reg0 << shift[i]);
-		reg1  = nv_rd32(dev, NV50_SOR_DP_UNK120(or, link)) & ~mask;
-		reg1 |= (dpse->reg1 << shift[i]);
-		reg2  = nv_rd32(dev, NV50_SOR_DP_UNK130(or, link)) & 0xffff00ff;
-		reg2 |= (dpse->reg2 << 8);
-		nv_wr32(dev, NV50_SOR_DP_UNK118(or, link), reg0);
-		nv_wr32(dev, NV50_SOR_DP_UNK120(or, link), reg1);
-		nv_wr32(dev, NV50_SOR_DP_UNK130(or, link), reg2);
+	switch (table[0]) {
+	case 0x20:
+	case 0x21:
+	case 0x30:
+		break;
+	default:
+		NV_ERROR(dev, "displayport table 0x%02x unknown\n", table[0]);
+		return NULL;
 	}
 
-	ret = auxch_wr(encoder, DP_TRAINING_LANE0_SET, config, 4);
-	if (ret)
-		return false;
+	for (i = 0; i < table[3]; i++) {
+		*entry = ROMPTR(bios, table[table[1] + (i * table[2])]);
+		if (*entry && bios_encoder_match(dcb, ROM32((*entry)[0])))
+			return table;
+	}
 
-	return true;
+	NV_ERROR(dev, "displayport encoder table not found\n");
+	return NULL;
 }
 
-bool
-nouveau_dp_link_train(struct drm_encoder *encoder)
+/******************************************************************************
+ * link training
+ *****************************************************************************/
+struct dp_state {
+	struct dcb_entry *dcb;
+	u8 *table;
+	u8 *entry;
+	int auxch;
+	int crtc;
+	int or;
+	int link;
+	u8 *dpcd;
+	int link_nr;
+	u32 link_bw;
+	u8  stat[6];
+	u8  conf[4];
+};
+
+static void
+dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
 {
-	struct drm_device *dev = encoder->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct nouveau_connector *nv_connector;
-	struct bit_displayport_encoder_table *dpe;
-	int dpe_headerlen;
-	uint8_t config[4], status[3];
-	bool cr_done, cr_max_vs, eq_done, hpd_state;
-	int ret = 0, i, tries, voltage;
-
-	NV_DEBUG_KMS(dev, "link training!!\n");
+	int or = dp->or, link = dp->link;
+	u8 *entry, sink[2];
+	u32 dp_ctrl;
+	u16 script;
 
-	nv_connector = nouveau_encoder_connector_get(nv_encoder);
-	if (!nv_connector)
-		return false;
+	NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw);
 
-	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
-	if (!dpe) {
-		NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or);
-		return false;
+	/* set selected link rate on source */
+	switch (dp->link_bw) {
+	case 270000:
+		nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00040000);
+		sink[0] = DP_LINK_BW_2_7;
+		break;
+	default:
+		nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00000000);
+		sink[0] = DP_LINK_BW_1_62;
+		break;
 	}
 
-	/* disable hotplug detect, this flips around on some panels during
-	 * link training.
+	/* offset +0x0a of each dp encoder table entry is a pointer to another
+	 * table, that has (among other things) pointers to more scripts that
+	 * need to be executed, this time depending on link speed.
 	 */
-	hpd_state = pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);
+	entry = ROMPTR(&dev_priv->vbios, dp->entry[10]);
+	if (entry) {
+		if (dp->table[0] < 0x30) {
+			while (dp->link_bw < (ROM16(entry[0]) * 10))
+				entry += 4;
+			script = ROM16(entry[2]);
+		} else {
+			while (dp->link_bw < (entry[0] * 27000))
+				entry += 3;
+			script = ROM16(entry[1]);
+		}
 
-	if (dpe->script0) {
-		NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or);
-		nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0),
-					    nv_encoder->dcb);
+		nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc);
 	}
 
-train:
-	cr_done = eq_done = false;
+	/* configure lane count on the source */
+	dp_ctrl = ((1 << dp->link_nr) - 1) << 16;
+	sink[1] = dp->link_nr;
+	if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) {
+		dp_ctrl |= 0x00004000;
+		sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+	}
 
-	/* set link configuration */
-	NV_DEBUG_KMS(dev, "\tbegin train: bw %d, lanes %d\n",
-		 nv_encoder->dp.link_bw, nv_encoder->dp.link_nr);
+	nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x001f4000, dp_ctrl);
 
-	ret = nouveau_dp_link_bw_set(encoder, nv_encoder->dp.link_bw);
-	if (ret)
-		return false;
+	/* inform the sink of the new configuration */
+	auxch_tx(dev, dp->auxch, 8, DP_LINK_BW_SET, sink, 2);
+}
 
-	config[0] = nv_encoder->dp.link_nr;
-	if (nv_encoder->dp.dpcd_version >= 0x11 &&
-	    nv_encoder->dp.enhanced_frame)
-		config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+static void
+dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 tp)
+{
+	u8 sink_tp;
 
-	ret = nouveau_dp_lane_count_set(encoder, config[0]);
-	if (ret)
-		return false;
+	NV_DEBUG_KMS(dev, "training pattern %d\n", tp);
 
-	/* clock recovery */
-	NV_DEBUG_KMS(dev, "\tbegin cr\n");
-	ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_1);
-	if (ret)
-		goto stop;
+	nv_mask(dev, NV50_SOR_DP_CTRL(dp->or, dp->link), 0x0f000000, tp << 24);
 
-	tries = 0;
-	voltage = -1;
-	memset(config, 0x00, sizeof(config));
-	for (;;) {
-		if (!nouveau_dp_link_train_commit(encoder, config))
-			break;
+	auxch_tx(dev, dp->auxch, 9, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
+	sink_tp &= ~DP_TRAINING_PATTERN_MASK;
+	sink_tp |= tp;
+	auxch_tx(dev, dp->auxch, 8, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
+}
 
-		udelay(100);
+static const u8 nv50_lane_map[] = { 16, 8, 0, 24 };
+static const u8 nvaf_lane_map[] = { 24, 16, 8, 0 };
 
-		ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 2);
-		if (ret)
-			break;
-		NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n",
-			 status[0], status[1]);
+static int
+dp_link_train_commit(struct drm_device *dev, struct dp_state *dp)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	u32 mask = 0, drv = 0, pre = 0, unk = 0;
+	const u8 *shifts;
+	int link = dp->link;
+	int or = dp->or;
+	int i;
 
-		cr_done = true;
-		cr_max_vs = false;
-		for (i = 0; i < nv_encoder->dp.link_nr; i++) {
-			int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf;
+	if (dev_priv->chipset != 0xaf)
+		shifts = nv50_lane_map;
+	else
+		shifts = nvaf_lane_map;
 
-			if (!(lane & DP_LANE_CR_DONE)) {
-				cr_done = false;
-				if (config[i] & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED)
-					cr_max_vs = true;
-				break;
+	for (i = 0; i < dp->link_nr; i++) {
+		u8 *conf = dp->entry + dp->table[4];
+		u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf;
+		u8 lpre = (lane & 0x0c) >> 2;
+		u8 lvsw = (lane & 0x03) >> 0;
+
+		mask |= 0xff << shifts[i];
+		unk |= 1 << (shifts[i] >> 3);
+
+		dp->conf[i] = (lpre << 3) | lvsw;
+		if (lvsw == DP_TRAIN_VOLTAGE_SWING_1200)
+			dp->conf[i] |= DP_TRAIN_MAX_SWING_REACHED;
+		if (lpre == DP_TRAIN_PRE_EMPHASIS_9_5)
+			dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+		NV_DEBUG_KMS(dev, "config lane %d %02x\n", i, dp->conf[i]);
+
+		if (dp->table[0] < 0x30) {
+			u8 *last = conf + (dp->entry[4] * dp->table[5]);
+			while (lvsw != conf[0] || lpre != conf[1]) {
+				conf += dp->table[5];
+				if (conf >= last)
+					return -EINVAL;
 			}
-		}
 
-		if ((config[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) {
-			voltage = config[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
-			tries = 0;
-		}
+			conf += 2;
+		} else {
+			/* no lookup table anymore, set entries for each
+			 * combination of voltage swing and pre-emphasis
+			 * level allowed by the DP spec.
+			 */
+			switch (lvsw) {
+			case 0: lpre += 0; break;
+			case 1: lpre += 4; break;
+			case 2: lpre += 7; break;
+			case 3: lpre += 9; break;
+			}
 
-		if (cr_done || cr_max_vs || (++tries == 5))
-			break;
+			conf = conf + (lpre * dp->table[5]);
+			conf++;
+		}
 
-		if (!nouveau_dp_link_train_adjust(encoder, config))
-			break;
+		drv |= conf[0] << shifts[i];
+		pre |= conf[1] << shifts[i];
+		unk  = (unk & ~0x0000ff00) | (conf[2] << 8);
 	}
 
-	if (!cr_done)
-		goto stop;
+	nv_mask(dev, NV50_SOR_DP_UNK118(or, link), mask, drv);
+	nv_mask(dev, NV50_SOR_DP_UNK120(or, link), mask, pre);
+	nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000ff0f, unk);
 
-	/* channel equalisation */
-	NV_DEBUG_KMS(dev, "\tbegin eq\n");
-	ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_2);
+	return auxch_tx(dev, dp->auxch, 8, DP_TRAINING_LANE0_SET, dp->conf, 4);
+}
+
+static int
+dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay)
+{
+	int ret;
+
+	udelay(delay);
+
+	ret = auxch_tx(dev, dp->auxch, 9, DP_LANE0_1_STATUS, dp->stat, 6);
 	if (ret)
-		goto stop;
+		return ret;
 
-	for (tries = 0; tries <= 5; tries++) {
-		udelay(400);
+	NV_DEBUG_KMS(dev, "status %02x %02x %02x %02x %02x %02x\n",
+		     dp->stat[0], dp->stat[1], dp->stat[2], dp->stat[3],
+		     dp->stat[4], dp->stat[5]);
+	return 0;
+}
 
-		ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 3);
-		if (ret)
-			break;
-		NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n",
-			 status[0], status[1]);
+static int
+dp_link_train_cr(struct drm_device *dev, struct dp_state *dp)
+{
+	bool cr_done = false, abort = false;
+	int voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+	int tries = 0, i;
 
-		eq_done = true;
-		if (!(status[2] & DP_INTERLANE_ALIGN_DONE))
-			eq_done = false;
+	dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_1);
 
-		for (i = 0; eq_done && i < nv_encoder->dp.link_nr; i++) {
-			int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf;
+	do {
+		if (dp_link_train_commit(dev, dp) ||
+		    dp_link_train_update(dev, dp, 100))
+			break;
 
+		cr_done = true;
+		for (i = 0; i < dp->link_nr; i++) {
+			u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf;
 			if (!(lane & DP_LANE_CR_DONE)) {
 				cr_done = false;
+				if (dp->conf[i] & DP_TRAIN_MAX_SWING_REACHED)
+					abort = true;
 				break;
 			}
+		}
 
-			if (!(lane & DP_LANE_CHANNEL_EQ_DONE) ||
-			    !(lane & DP_LANE_SYMBOL_LOCKED)) {
-				eq_done = false;
-				break;
-			}
+		if ((dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) {
+			voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+			tries = 0;
 		}
+	} while (!cr_done && !abort && ++tries < 5);
 
-		if (eq_done || !cr_done)
-			break;
+	return cr_done ? 0 : -1;
+}
 
-		if (!nouveau_dp_link_train_adjust(encoder, config) ||
-		    !nouveau_dp_link_train_commit(encoder, config))
-			break;
-	}
+static int
+dp_link_train_eq(struct drm_device *dev, struct dp_state *dp)
+{
+	bool eq_done, cr_done = true;
+	int tries = 0, i;
 
-stop:
-	/* end link training */
-	ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_DISABLE);
-	if (ret)
-		return false;
+	dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_2);
 
-	/* retry at a lower setting, if possible */
-	if (!ret && !(eq_done && cr_done)) {
-		NV_DEBUG_KMS(dev, "\twe failed\n");
-		if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62) {
-			NV_DEBUG_KMS(dev, "retry link training at low rate\n");
-			nv_encoder->dp.link_bw = DP_LINK_BW_1_62;
-			goto train;
-		}
-	}
+	do {
+		if (dp_link_train_update(dev, dp, 400))
+			break;
 
-	if (dpe->script1) {
-		NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or);
-		nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1),
-					    nv_encoder->dcb);
-	}
+		eq_done = !!(dp->stat[2] & DP_INTERLANE_ALIGN_DONE);
+		for (i = 0; i < dp->link_nr && eq_done; i++) {
+			u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf;
+			if (!(lane & DP_LANE_CR_DONE))
+				cr_done = false;
+			if (!(lane & DP_LANE_CHANNEL_EQ_DONE) ||
+			    !(lane & DP_LANE_SYMBOL_LOCKED))
+				eq_done = false;
+		}
 
-	/* re-enable hotplug detect */
-	pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, hpd_state);
+		if (dp_link_train_commit(dev, dp))
+			break;
+	} while (!eq_done && cr_done && ++tries <= 5);
 
-	return eq_done;
+	return eq_done ? 0 : -1;
 }
 
 bool
-nouveau_dp_detect(struct drm_encoder *encoder)
+nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
 {
+	struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
+	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+	struct nouveau_connector *nv_connector =
+		nouveau_encoder_connector_get(nv_encoder);
 	struct drm_device *dev = encoder->dev;
-	uint8_t dpcd[4];
-	int ret;
+	struct nouveau_i2c_chan *auxch;
+	const u32 bw_list[] = { 270000, 162000, 0 };
+	const u32 *link_bw = bw_list;
+	struct dp_state dp;
 
-	ret = auxch_rd(encoder, 0x0000, dpcd, 4);
-	if (ret)
+	auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
+	if (!auxch)
 		return false;
 
-	NV_DEBUG_KMS(dev, "encoder: link_bw %d, link_nr %d\n"
-		      "display: link_bw %d, link_nr %d version 0x%02x\n",
-		 nv_encoder->dcb->dpconf.link_bw,
-		 nv_encoder->dcb->dpconf.link_nr,
-		 dpcd[1], dpcd[2] & 0x0f, dpcd[0]);
+	dp.table = nouveau_dp_bios_data(dev, nv_encoder->dcb, &dp.entry);
+	if (!dp.table)
+		return -EINVAL;
 
-	nv_encoder->dp.dpcd_version = dpcd[0];
+	dp.dcb = nv_encoder->dcb;
+	dp.crtc = nv_crtc->index;
+	dp.auxch = auxch->rd;
+	dp.or = nv_encoder->or;
+	dp.link = !(nv_encoder->dcb->sorconf.link & 1);
+	dp.dpcd = nv_encoder->dp.dpcd;
 
-	nv_encoder->dp.link_bw = dpcd[1];
-	if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62 &&
-	    !nv_encoder->dcb->dpconf.link_bw)
-		nv_encoder->dp.link_bw = DP_LINK_BW_1_62;
+	/* some sinks toggle hotplug in response to some of the actions
+	 * we take during link training (DP_SET_POWER is one), we need
+	 * to ignore them for the moment to avoid races.
+	 */
+	pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);
 
-	nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
-	if (nv_encoder->dp.link_nr > nv_encoder->dcb->dpconf.link_nr)
-		nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr;
+	/* enable down-spreading, if possible */
+	if (dp.table[1] >= 16) {
+		u16 script = ROM16(dp.entry[14]);
+		if (nv_encoder->dp.dpcd[3] & 1)
+			script = ROM16(dp.entry[12]);
 
-	nv_encoder->dp.enhanced_frame = (dpcd[2] & DP_ENHANCED_FRAME_CAP);
+		nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc);
+	}
 
-	return true;
-}
+	/* execute pre-train script from vbios */
+	nouveau_bios_run_init_table(dev, ROM16(dp.entry[6]), dp.dcb, dp.crtc);
 
-int
-nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
-		 uint8_t *data, int data_nr)
-{
-	struct drm_device *dev = auxch->dev;
-	uint32_t tmp, ctrl, stat = 0, data32[4] = {};
-	int ret = 0, i, index = auxch->rd;
+	/* start off at highest link rate supported by encoder and display */
+	while (*link_bw > nv_encoder->dp.link_bw)
+		link_bw++;
 
-	NV_DEBUG_KMS(dev, "ch %d cmd %d addr 0x%x len %d\n", index, cmd, addr, data_nr);
+	while (link_bw[0]) {
+		/* find minimum required lane count at this link rate */
+		dp.link_nr = nv_encoder->dp.link_nr;
+		while ((dp.link_nr >> 1) * link_bw[0] > datarate)
+			dp.link_nr >>= 1;
 
-	tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
-	nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp | 0x00100000);
-	tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
-	if (!(tmp & 0x01000000)) {
-		NV_ERROR(dev, "expected bit 24 == 1, got 0x%08x\n", tmp);
-		ret = -EIO;
-		goto out;
-	}
+		/* drop link rate to minimum with this lane count */
+		while ((link_bw[1] * dp.link_nr) > datarate)
+			link_bw++;
+		dp.link_bw = link_bw[0];
 
-	for (i = 0; i < 3; i++) {
-		tmp = nv_rd32(dev, NV50_AUXCH_STAT(auxch->rd));
-		if (tmp & NV50_AUXCH_STAT_STATE_READY)
+		/* program selected link configuration */
+		dp_set_link_config(dev, &dp);
+
+		/* attempt to train the link at this configuration */
+		memset(dp.stat, 0x00, sizeof(dp.stat));
+		if (!dp_link_train_cr(dev, &dp) &&
+		    !dp_link_train_eq(dev, &dp))
 			break;
-		udelay(100);
-	}
 
-	if (i == 3) {
-		ret = -EBUSY;
-		goto out;
+		/* retry at lower rate */
+		link_bw++;
 	}
 
-	if (!(cmd & 1)) {
-		memcpy(data32, data, data_nr);
-		for (i = 0; i < 4; i++) {
-			NV_DEBUG_KMS(dev, "wr %d: 0x%08x\n", i, data32[i]);
-			nv_wr32(dev, NV50_AUXCH_DATA_OUT(index, i), data32[i]);
-		}
-	}
+	/* finish link training */
+	dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE);
 
-	nv_wr32(dev, NV50_AUXCH_ADDR(index), addr);
-	ctrl  = nv_rd32(dev, NV50_AUXCH_CTRL(index));
-	ctrl &= ~(NV50_AUXCH_CTRL_CMD | NV50_AUXCH_CTRL_LEN);
-	ctrl |= (cmd << NV50_AUXCH_CTRL_CMD_SHIFT);
-	ctrl |= ((data_nr - 1) << NV50_AUXCH_CTRL_LEN_SHIFT);
+	/* execute post-train script from vbios */
+	nouveau_bios_run_init_table(dev, ROM16(dp.entry[8]), dp.dcb, dp.crtc);
 
-	for (i = 0; i < 16; i++) {
-		nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000);
-		nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl);
-		nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x00010000);
-		if (!nv_wait(dev, NV50_AUXCH_CTRL(index),
-			     0x00010000, 0x00000000)) {
-			NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n",
-				 nv_rd32(dev, NV50_AUXCH_CTRL(index)));
-			ret = -EBUSY;
-			goto out;
-		}
+	/* re-enable hotplug detect */
+	pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true);
+	return true;
+}
 
-		udelay(400);
+bool
+nouveau_dp_detect(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_i2c_chan *auxch;
+	u8 *dpcd = nv_encoder->dp.dpcd;
+	int ret;
 
-		stat = nv_rd32(dev, NV50_AUXCH_STAT(index));
-		if ((stat & NV50_AUXCH_STAT_REPLY_AUX) !=
-			    NV50_AUXCH_STAT_REPLY_AUX_DEFER)
-			break;
-	}
+	auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
+	if (!auxch)
+		return false;
 
-	if (i == 16) {
-		NV_ERROR(dev, "auxch DEFER too many times, bailing\n");
-		ret = -EREMOTEIO;
-		goto out;
-	}
+	ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8);
+	if (ret)
+		return false;
 
-	if (cmd & 1) {
-		if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) {
-			ret = -EREMOTEIO;
-			goto out;
-		}
+	nv_encoder->dp.link_bw = 27000 * dpcd[1];
+	nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
 
-		for (i = 0; i < 4; i++) {
-			data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i));
-			NV_DEBUG_KMS(dev, "rd %d: 0x%08x\n", i, data32[i]);
-		}
-		memcpy(data, data32, data_nr);
-	}
+	NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n",
+		     nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]);
+	NV_DEBUG_KMS(dev, "encoder: %dx%d\n",
+		     nv_encoder->dcb->dpconf.link_nr,
+		     nv_encoder->dcb->dpconf.link_bw);
 
-out:
-	tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
-	nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp & ~0x00100000);
-	tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
-	if (tmp & 0x01000000) {
-		NV_ERROR(dev, "expected bit 24 == 0, got 0x%08x\n", tmp);
-		ret = -EIO;
-	}
+	if (nv_encoder->dcb->dpconf.link_nr < nv_encoder->dp.link_nr)
+		nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr;
+	if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw)
+		nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw;
 
-	udelay(400);
+	NV_DEBUG_KMS(dev, "maximum: %dx%d\n",
+		     nv_encoder->dp.link_nr, nv_encoder->dp.link_bw);
 
-	return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY);
+	return true;
+}
+
+int
+nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
+		 uint8_t *data, int data_nr)
+{
+	return auxch_tx(auxch->dev, auxch->rd, cmd, addr, data, data_nr);
 }
 
 static int
 nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 {
 	struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adap;
-	struct drm_device *dev = auxch->dev;
 	struct i2c_msg *msg = msgs;
 	int ret, mcnt = num;
 
@@ -602,19 +714,6 @@
 			if (ret < 0)
 				return ret;
 
-			switch (ret & NV50_AUXCH_STAT_REPLY_I2C) {
-			case NV50_AUXCH_STAT_REPLY_I2C_ACK:
-				break;
-			case NV50_AUXCH_STAT_REPLY_I2C_NACK:
-				return -EREMOTEIO;
-			case NV50_AUXCH_STAT_REPLY_I2C_DEFER:
-				udelay(100);
-				continue;
-			default:
-				NV_ERROR(dev, "bad auxch reply: 0x%08x\n", ret);
-				return -EREMOTEIO;
-			}
-
 			ptr += cnt;
 			remaining -= cnt;
 		}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_drv.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_drv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
  */
 
 #include <linux/console.h>
+#include <linux/module.h>
 
 #include "drmP.h"
 #include "drm.h"
@@ -41,7 +42,7 @@
 module_param_named(agpmode, nouveau_agpmode, int, 0400);
 
 MODULE_PARM_DESC(modeset, "Enable kernel modesetting");
-static int nouveau_modeset = -1; /* kms */
+int nouveau_modeset = -1;
 module_param_named(modeset, nouveau_modeset, int, 0400);
 
 MODULE_PARM_DESC(vbios, "Override default VBIOS location");
@@ -432,6 +433,10 @@
 	.gem_open_object = nouveau_gem_object_open,
 	.gem_close_object = nouveau_gem_object_close,
 
+	.dumb_create = nouveau_display_dumb_create,
+	.dumb_map_offset = nouveau_display_dumb_map_offset,
+	.dumb_destroy = nouveau_display_dumb_destroy,
+
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
 #ifdef GIT_REVISION
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_drv.h linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_drv.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_drv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_drv.h	2012-01-04 18:55:44.000000000 -0500
@@ -414,12 +414,13 @@
 };
 
 struct nouveau_pm_voltage_level {
-	u8 voltage;
-	u8 vid;
+	u32 voltage; /* microvolts */
+	u8  vid;
 };
 
 struct nouveau_pm_voltage {
 	bool supported;
+	u8 version;
 	u8 vid_mask;
 
 	struct nouveau_pm_voltage_level *level;
@@ -428,17 +429,48 @@
 
 struct nouveau_pm_memtiming {
 	int id;
-	u32 reg_100220;
-	u32 reg_100224;
-	u32 reg_100228;
-	u32 reg_10022c;
-	u32 reg_100230;
-	u32 reg_100234;
-	u32 reg_100238;
-	u32 reg_10023c;
-	u32 reg_100240;
+	u32 reg_0; /* 0x10f290 on Fermi, 0x100220 for older */
+	u32 reg_1;
+	u32 reg_2;
+	u32 reg_3;
+	u32 reg_4;
+	u32 reg_5;
+	u32 reg_6;
+	u32 reg_7;
+	u32 reg_8;
+	/* To be written to 0x1002c0 */
+	u8 CL;
+	u8 WR;
+};
+
+struct nouveau_pm_tbl_header{
+	u8 version;
+	u8 header_len;
+	u8 entry_cnt;
+	u8 entry_len;
+};
+
+struct nouveau_pm_tbl_entry{
+	u8 tWR;
+	u8 tUNK_1;
+	u8 tCL;
+	u8 tRP;		/* Byte 3 */
+	u8 empty_4;
+	u8 tRAS;	/* Byte 5 */
+	u8 empty_6;
+	u8 tRFC;	/* Byte 7 */
+	u8 empty_8;
+	u8 tRC;		/* Byte 9 */
+	u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14;
+	u8 empty_15,empty_16,empty_17;
+	u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21;
 };
 
+/* nouveau_mem.c */
+void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
+							struct nouveau_pm_tbl_entry *e, uint8_t magic_number,
+							struct nouveau_pm_memtiming *timing);
+
 #define NOUVEAU_PM_MAX_LEVEL 8
 struct nouveau_pm_level {
 	struct device_attribute dev_attr;
@@ -448,11 +480,19 @@
 	u32 core;
 	u32 memory;
 	u32 shader;
-	u32 unk05;
-	u32 unk0a;
+	u32 rop;
+	u32 copy;
+	u32 daemon;
+	u32 vdec;
+	u32 unk05;	/* nv50:nva3, roughly.. */
+	u32 unka0;	/* nva3:nvc0 */
+	u32 hub01;	/* nvc0- */
+	u32 hub06;	/* nvc0- */
+	u32 hub07;	/* nvc0- */
 
-	u8 voltage;
-	u8 fanspeed;
+	u32 volt_min; /* microvolts */
+	u32 volt_max;
+	u8  fanspeed;
 
 	u16 memscript;
 	struct nouveau_pm_memtiming *timing;
@@ -496,6 +536,11 @@
 	void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *,
 			   u32 id, int khz);
 	void (*clock_set)(struct drm_device *, void *);
+
+	int  (*clocks_get)(struct drm_device *, struct nouveau_pm_level *);
+	void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *);
+	void (*clocks_set)(struct drm_device *, void *);
+
 	int (*voltage_get)(struct drm_device *);
 	int (*voltage_set)(struct drm_device *, int voltage);
 	int (*fanspeed_get)(struct drm_device *);
@@ -504,7 +549,7 @@
 };
 
 struct nouveau_vram_engine {
-	struct nouveau_mm *mm;
+	struct nouveau_mm mm;
 
 	int  (*init)(struct drm_device *);
 	void (*takedown)(struct drm_device *dev);
@@ -623,6 +668,7 @@
 	NV_40      = 0x40,
 	NV_50      = 0x50,
 	NV_C0      = 0xc0,
+	NV_D0      = 0xd0
 };
 
 struct drm_nouveau_private {
@@ -633,8 +679,8 @@
 	enum nouveau_card_type card_type;
 	/* exact chipset, derived from NV_PMC_BOOT_0 */
 	int chipset;
-	int stepping;
 	int flags;
+	u32 crystal;
 
 	void __iomem *mmio;
 
@@ -721,7 +767,6 @@
 	uint64_t vram_size;
 	uint64_t vram_sys_base;
 
-	uint64_t fb_phys;
 	uint64_t fb_available_size;
 	uint64_t fb_mappable_pages;
 	uint64_t fb_aper_free;
@@ -784,6 +829,7 @@
 }
 
 /* nouveau_drv.c */
+extern int nouveau_modeset;
 extern int nouveau_agpmode;
 extern int nouveau_duallink;
 extern int nouveau_uscript_lvds;
@@ -824,6 +870,8 @@
 			    uint32_t reg, uint32_t mask, uint32_t val);
 extern bool nouveau_wait_ne(struct drm_device *, uint64_t timeout,
 			    uint32_t reg, uint32_t mask, uint32_t val);
+extern bool nouveau_wait_cb(struct drm_device *, u64 timeout,
+			    bool (*cond)(void *), void *);
 extern bool nouveau_wait_for_idle(struct drm_device *);
 extern int  nouveau_card_init(struct drm_device *);
 
@@ -1006,15 +1054,15 @@
 
 /* nouveau_backlight.c */
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
-extern int nouveau_backlight_init(struct drm_connector *);
-extern void nouveau_backlight_exit(struct drm_connector *);
+extern int nouveau_backlight_init(struct drm_device *);
+extern void nouveau_backlight_exit(struct drm_device *);
 #else
-static inline int nouveau_backlight_init(struct drm_connector *dev)
+static inline int nouveau_backlight_init(struct drm_device *dev)
 {
 	return 0;
 }
 
-static inline void nouveau_backlight_exit(struct drm_connector *dev) { }
+static inline void nouveau_backlight_exit(struct drm_device *dev) { }
 #endif
 
 /* nouveau_bios.c */
@@ -1022,7 +1070,8 @@
 extern void nouveau_bios_takedown(struct drm_device *dev);
 extern int nouveau_run_vbios_init(struct drm_device *);
 extern void nouveau_bios_run_init_table(struct drm_device *, uint16_t table,
-					struct dcb_entry *);
+					struct dcb_entry *, int crtc);
+extern void nouveau_bios_init_exec(struct drm_device *, uint16_t table);
 extern struct dcb_gpio_entry *nouveau_bios_gpio_entry(struct drm_device *,
 						      enum dcb_gpio_tag);
 extern struct dcb_connector_table_entry *
@@ -1030,11 +1079,8 @@
 extern u32 get_pll_register(struct drm_device *, enum pll_types);
 extern int get_pll_limits(struct drm_device *, uint32_t limit_match,
 			  struct pll_lims *);
-extern int nouveau_bios_run_display_table(struct drm_device *,
-					  struct dcb_entry *,
-					  uint32_t script, int pxclk);
-extern void *nouveau_bios_dp_table(struct drm_device *, struct dcb_entry *,
-				   int *length);
+extern int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk,
+					  struct dcb_entry *, int crtc);
 extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *);
 extern uint8_t *nouveau_bios_embedded_edid(struct drm_device *);
 extern int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk,
@@ -1043,6 +1089,7 @@
 			  int head, int pxclk);
 extern int call_lvds_script(struct drm_device *, struct dcb_entry *, int head,
 			    enum LVDS_script, int pxclk);
+bool bios_encoder_match(struct dcb_entry *, u32 hash);
 
 /* nouveau_ttm.c */
 int nouveau_ttm_global_init(struct drm_nouveau_private *);
@@ -1053,7 +1100,9 @@
 int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
 		     uint8_t *data, int data_nr);
 bool nouveau_dp_detect(struct drm_encoder *);
-bool nouveau_dp_link_train(struct drm_encoder *);
+bool nouveau_dp_link_train(struct drm_encoder *, u32 datarate);
+void nouveau_dp_tu_update(struct drm_device *, int, int, u32, u32);
+u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **);
 
 /* nv04_fb.c */
 extern int  nv04_fb_init(struct drm_device *);
@@ -1179,8 +1228,8 @@
 /* nvc0_copy.c */
 extern int  nvc0_copy_create(struct drm_device *dev, int engine);
 
-/* nv40_mpeg.c */
-extern int  nv40_mpeg_create(struct drm_device *dev);
+/* nv31_mpeg.c */
+extern int  nv31_mpeg_create(struct drm_device *dev);
 
 /* nv50_mpeg.c */
 extern int  nv50_mpeg_create(struct drm_device *dev);
@@ -1265,6 +1314,11 @@
 extern int nv04_display_init(struct drm_device *);
 extern void nv04_display_destroy(struct drm_device *);
 
+/* nvd0_display.c */
+extern int nvd0_display_create(struct drm_device *);
+extern int nvd0_display_init(struct drm_device *);
+extern void nvd0_display_destroy(struct drm_device *);
+
 /* nv04_crtc.c */
 extern int nv04_crtc_create(struct drm_device *, int index);
 
@@ -1364,6 +1418,12 @@
 			   struct drm_pending_vblank_event *event);
 int nouveau_finish_page_flip(struct nouveau_channel *,
 			     struct nouveau_page_flip_state *);
+int nouveau_display_dumb_create(struct drm_file *, struct drm_device *,
+				struct drm_mode_create_dumb *args);
+int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *,
+				    uint32_t handle, uint64_t *offset);
+int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *,
+				 uint32_t handle);
 
 /* nv10_gpio.c */
 int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
@@ -1374,6 +1434,8 @@
 void nv50_gpio_fini(struct drm_device *dev);
 int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
 int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
+int nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
+int nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
 int  nv50_gpio_irq_register(struct drm_device *, enum dcb_gpio_tag,
 			    void (*)(void *, int), void *);
 void nv50_gpio_irq_unregister(struct drm_device *, enum dcb_gpio_tag,
@@ -1448,6 +1510,8 @@
 	nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val))
 #define nv_wait_ne(dev, reg, mask, val) \
 	nouveau_wait_ne(dev, 2000000000ULL, (reg), (mask), (val))
+#define nv_wait_cb(dev, func, data) \
+	nouveau_wait_cb(dev, 2000000000ULL, (func), (data))
 
 /* PRAMIN access */
 static inline u32 nv_ri32(struct drm_device *dev, unsigned offset)
@@ -1514,6 +1578,7 @@
 	NOUVEAU_REG_DEBUG_RMVIO          = 0x80,
 	NOUVEAU_REG_DEBUG_VGAATTR        = 0x100,
 	NOUVEAU_REG_DEBUG_EVO            = 0x200,
+	NOUVEAU_REG_DEBUG_AUXCH          = 0x400
 };
 
 #define NV_REG_DEBUG(type, dev, fmt, arg...) do { \
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_encoder.h linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_encoder.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_encoder.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_encoder.h	2012-01-04 18:55:44.000000000 -0500
@@ -49,17 +49,17 @@
 
 	union {
 		struct {
-			int mc_unknown;
-			uint32_t unk0;
-			uint32_t unk1;
-			int dpcd_version;
+			u8  dpcd[8];
 			int link_nr;
 			int link_bw;
-			bool enhanced_frame;
+			u32 datarate;
 		} dp;
 	};
 };
 
+struct nouveau_encoder *
+find_encoder(struct drm_connector *connector, int type);
+
 static inline struct nouveau_encoder *nouveau_encoder(struct drm_encoder *enc)
 {
 	struct drm_encoder_slave *slave = to_encoder_slave(enc);
@@ -83,21 +83,4 @@
 int nv50_sor_create(struct drm_connector *, struct dcb_entry *);
 int nv50_dac_create(struct drm_connector *, struct dcb_entry *);
 
-struct bit_displayport_encoder_table {
-	uint32_t match;
-	uint8_t  record_nr;
-	uint8_t  unknown;
-	uint16_t script0;
-	uint16_t script1;
-	uint16_t unknown_table;
-} __attribute__ ((packed));
-
-struct bit_displayport_encoder_table_entry {
-	uint8_t vs_level;
-	uint8_t pre_level;
-	uint8_t reg0;
-	uint8_t reg1;
-	uint8_t reg2;
-} __attribute__ ((packed));
-
 #endif /* __NOUVEAU_ENCODER_H__ */
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c	2012-01-04 18:55:44.000000000 -0500
@@ -487,6 +487,7 @@
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_fbdev *nfbdev;
+	int preferred_bpp;
 	int ret;
 
 	nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL);
@@ -505,7 +506,15 @@
 	}
 
 	drm_fb_helper_single_add_all_connectors(&nfbdev->helper);
-	drm_fb_helper_initial_config(&nfbdev->helper, 32);
+
+	if (dev_priv->vram_size <= 32 * 1024 * 1024)
+		preferred_bpp = 8;
+	else if (dev_priv->vram_size <= 64 * 1024 * 1024)
+		preferred_bpp = 16;
+	else
+		preferred_bpp = 32;
+
+	drm_fb_helper_initial_config(&nfbdev->helper, preferred_bpp);
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c	2012-01-04 18:55:44.000000000 -0500
@@ -519,7 +519,7 @@
 	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,
+		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_FROM_MEMORY,
 					     mem->start << PAGE_SHIFT,
 					     mem->size, NV_MEM_ACCESS_RW,
 					     NV_MEM_TARGET_VRAM, &obj);
@@ -539,8 +539,6 @@
 			return ret;
 	}
 
-	INIT_LIST_HEAD(&chan->fence.pending);
-	spin_lock_init(&chan->fence.lock);
 	atomic_set(&chan->fence.last_sequence_irq, 0);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_i2c.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_i2c.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,8 @@
  * Authors: Ben Skeggs
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "nouveau_drv.h"
 #include "nouveau_i2c.h"
@@ -107,6 +109,13 @@
 	return !!((nv_rd32(dev, i2c->rd) >> 16) & 8);
 }
 
+static const uint32_t nv50_i2c_port[] = {
+	0x00e138, 0x00e150, 0x00e168, 0x00e180,
+	0x00e254, 0x00e274, 0x00e764, 0x00e780,
+	0x00e79c, 0x00e7b8
+};
+#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port)
+
 static int
 nv50_i2c_getscl(void *data)
 {
@@ -130,28 +139,32 @@
 nv50_i2c_setscl(void *data, int state)
 {
 	struct nouveau_i2c_chan *i2c = data;
-	struct drm_device *dev = i2c->dev;
 
-	nv_wr32(dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0));
+	nv_wr32(i2c->dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0));
 }
 
 static void
 nv50_i2c_setsda(void *data, int state)
 {
 	struct nouveau_i2c_chan *i2c = data;
-	struct drm_device *dev = i2c->dev;
 
-	nv_wr32(dev, i2c->wr,
-			(nv_rd32(dev, i2c->rd) & 1) | 4 | (state ? 2 : 0));
+	nv_mask(i2c->dev, i2c->wr, 0x00000006, 4 | (state ? 2 : 0));
 	i2c->data = state;
 }
 
-static const uint32_t nv50_i2c_port[] = {
-	0x00e138, 0x00e150, 0x00e168, 0x00e180,
-	0x00e254, 0x00e274, 0x00e764, 0x00e780,
-	0x00e79c, 0x00e7b8
-};
-#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port)
+static int
+nvd0_i2c_getscl(void *data)
+{
+	struct nouveau_i2c_chan *i2c = data;
+	return !!(nv_rd32(i2c->dev, i2c->rd) & 0x10);
+}
+
+static int
+nvd0_i2c_getsda(void *data)
+{
+	struct nouveau_i2c_chan *i2c = data;
+	return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20);
+}
 
 int
 nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index)
@@ -163,7 +176,8 @@
 	if (entry->chan)
 		return -EEXIST;
 
-	if (dev_priv->card_type >= NV_50 && entry->read >= NV50_I2C_PORTS) {
+	if (dev_priv->card_type >= NV_50 &&
+	    dev_priv->card_type <= NV_C0 && entry->read >= NV50_I2C_PORTS) {
 		NV_ERROR(dev, "unknown i2c port %d\n", entry->read);
 		return -EINVAL;
 	}
@@ -192,10 +206,17 @@
 	case 5:
 		i2c->bit.setsda = nv50_i2c_setsda;
 		i2c->bit.setscl = nv50_i2c_setscl;
-		i2c->bit.getsda = nv50_i2c_getsda;
-		i2c->bit.getscl = nv50_i2c_getscl;
-		i2c->rd = nv50_i2c_port[entry->read];
-		i2c->wr = i2c->rd;
+		if (dev_priv->card_type < NV_D0) {
+			i2c->bit.getsda = nv50_i2c_getsda;
+			i2c->bit.getscl = nv50_i2c_getscl;
+			i2c->rd = nv50_i2c_port[entry->read];
+			i2c->wr = i2c->rd;
+		} else {
+			i2c->bit.getsda = nvd0_i2c_getsda;
+			i2c->bit.getscl = nvd0_i2c_getscl;
+			i2c->rd = 0x00d014 + (entry->read * 0x20);
+			i2c->wr = i2c->rd;
+		}
 		break;
 	case 6:
 		i2c->rd = entry->read;
@@ -267,7 +288,10 @@
 			val  = 0xe001;
 		}
 
-		nv_wr32(dev, reg, (nv_rd32(dev, reg) & ~0xf003) | val);
+		/* nfi, but neither auxch or i2c work if it's 1 */
+		nv_mask(dev, reg + 0x0c, 0x00000001, 0x00000000);
+		/* nfi, but switches auxch vs normal i2c */
+		nv_mask(dev, reg + 0x00, 0x0000f003, val);
 	}
 
 	if (!i2c->chan && nouveau_i2c_init(dev, i2c, index))
@@ -309,7 +333,7 @@
 
 	NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index);
 
-	for (i = 0; info[i].addr; i++) {
+	for (i = 0; i2c && info[i].addr; i++) {
 		if (nouveau_probe_i2c_addr(i2c, info[i].addr) &&
 		    (!match || match(i2c, &info[i]))) {
 			NV_INFO(dev, "Detected %s: %s\n", what, info[i].type);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_mem.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_mem.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_mem.c	2012-01-04 18:55:44.000000000 -0500
@@ -408,8 +408,6 @@
 	if (ret)
 		return ret;
 
-	dev_priv->fb_phys = pci_resource_start(dev->pdev, 1);
-
 	ret = nouveau_ttm_global_init(dev_priv);
 	if (ret)
 		return ret;
@@ -504,35 +502,146 @@
 	return 0;
 }
 
+/* XXX: For now a dummy. More samples required, possibly even a card
+ * Called from nouveau_perf.c */
+void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
+							struct nouveau_pm_tbl_entry *e, uint8_t magic_number,
+							struct nouveau_pm_memtiming *timing) {
+
+	NV_DEBUG(dev,"Timing entry format unknown, please contact nouveau developers");
+}
+
+void nv40_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
+							struct nouveau_pm_tbl_entry *e, uint8_t magic_number,
+							struct nouveau_pm_memtiming *timing) {
+
+	timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP);
+
+	/* XXX: I don't trust the -1's and +1's... they must come
+	 *      from somewhere! */
+	timing->reg_1 = (e->tWR + 2 + magic_number) << 24 |
+				  1 << 16 |
+				  (e->tUNK_1 + 2 + magic_number) << 8 |
+				  (e->tCL + 2 - magic_number);
+	timing->reg_2 = (magic_number << 24 | e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10);
+	timing->reg_2 |= 0x20200000;
+
+	NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x\n", timing->id,
+		 timing->reg_0, timing->reg_1,timing->reg_2);
+}
+
+void nv50_mem_timing_entry(struct drm_device *dev, struct bit_entry *P, struct nouveau_pm_tbl_header *hdr,
+							struct nouveau_pm_tbl_entry *e, uint8_t magic_number,struct nouveau_pm_memtiming *timing) {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	uint8_t unk18 = 1,
+		unk19 = 1,
+		unk20 = 0,
+		unk21 = 0;
+
+	switch (min(hdr->entry_len, (u8) 22)) {
+	case 22:
+		unk21 = e->tUNK_21;
+	case 21:
+		unk20 = e->tUNK_20;
+	case 20:
+		unk19 = e->tUNK_19;
+	case 19:
+		unk18 = e->tUNK_18;
+		break;
+	}
+
+	timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP);
+
+	/* XXX: I don't trust the -1's and +1's... they must come
+	 *      from somewhere! */
+	timing->reg_1 = (e->tWR + unk19 + 1 + magic_number) << 24 |
+				  max(unk18, (u8) 1) << 16 |
+				  (e->tUNK_1 + unk19 + 1 + magic_number) << 8;
+	if (dev_priv->chipset == 0xa8) {
+		timing->reg_1 |= (e->tCL - 1);
+	} else {
+		timing->reg_1 |= (e->tCL + 2 - magic_number);
+	}
+	timing->reg_2 = (e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10);
+
+	timing->reg_5 = (e->tRAS << 24 | e->tRC);
+	timing->reg_5 += max(e->tUNK_10, e->tUNK_11) << 16;
+
+	if (P->version == 1) {
+		timing->reg_2 |= magic_number << 24;
+		timing->reg_3 = (0x14 + e->tCL) << 24 |
+						0x16 << 16 |
+						(e->tCL - 1) << 8 |
+						(e->tCL - 1);
+		timing->reg_4 = (nv_rd32(dev,0x10022c) & 0xffff0000) | e->tUNK_13 << 8  | e->tUNK_13;
+		timing->reg_5 |= (e->tCL + 2) << 8;
+		timing->reg_7 = 0x4000202 | (e->tCL - 1) << 16;
+	} else {
+		timing->reg_2 |= (unk19 - 1) << 24;
+		/* XXX: reg_10022c for recentish cards pretty much unknown*/
+		timing->reg_3 = e->tCL - 1;
+		timing->reg_4 = (unk20 << 24 | unk21 << 16 |
+							e->tUNK_13 << 8  | e->tUNK_13);
+		/* XXX: +6? */
+		timing->reg_5 |= (unk19 + 6) << 8;
+
+		/* XXX: reg_10023c currently unknown
+		 * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */
+		timing->reg_7 = 0x202;
+	}
+
+	NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", timing->id,
+		 timing->reg_0, timing->reg_1,
+		 timing->reg_2, timing->reg_3);
+	NV_DEBUG(dev, "         230: %08x %08x %08x %08x\n",
+		 timing->reg_4, timing->reg_5,
+		 timing->reg_6, timing->reg_7);
+	NV_DEBUG(dev, "         240: %08x\n", timing->reg_8);
+}
+
+void nvc0_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr,
+							struct nouveau_pm_tbl_entry *e, struct nouveau_pm_memtiming *timing) {
+	timing->reg_0 = (e->tRC << 24 | (e->tRFC & 0x7f) << 17 | e->tRAS << 8 | e->tRP);
+	timing->reg_1 = (nv_rd32(dev,0x10f294) & 0xff000000) | (e->tUNK_11&0x0f) << 20 | (e->tUNK_19 << 7) | (e->tCL & 0x0f);
+	timing->reg_2 = (nv_rd32(dev,0x10f298) & 0xff0000ff) | e->tWR << 16 | e->tUNK_1 << 8;
+	timing->reg_3 = e->tUNK_20 << 9 | e->tUNK_13;
+	timing->reg_4 = (nv_rd32(dev,0x10f2a0) & 0xfff000ff) | e->tUNK_12 << 15;
+	NV_DEBUG(dev, "Entry %d: 290: %08x %08x %08x %08x\n", timing->id,
+		 timing->reg_0, timing->reg_1,
+		 timing->reg_2, timing->reg_3);
+	NV_DEBUG(dev, "         2a0: %08x %08x %08x %08x\n",
+		 timing->reg_4, timing->reg_5,
+		 timing->reg_6, timing->reg_7);
+}
+
+/**
+ * Processes the Memory Timing BIOS table, stores generated
+ * register values
+ * @pre init scripts were run, memtiming regs are initialized
+ */
 void
 nouveau_mem_timing_init(struct drm_device *dev)
 {
-	/* cards < NVC0 only */
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
 	struct nouveau_pm_memtimings *memtimings = &pm->memtimings;
 	struct nvbios *bios = &dev_priv->vbios;
 	struct bit_entry P;
-	u8 tUNK_0, tUNK_1, tUNK_2;
-	u8 tRP;		/* Byte 3 */
-	u8 tRAS;	/* Byte 5 */
-	u8 tRFC;	/* Byte 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;
+	struct nouveau_pm_tbl_header *hdr = NULL;
+	uint8_t magic_number;
+	u8 *entry;
+	int i;
 
 	if (bios->type == NVBIOS_BIT) {
 		if (bit_table(dev, 'P', &P))
 			return;
 
 		if (P.version == 1)
-			mem = ROMPTR(bios, P.data[4]);
+			hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[4]);
 		else
 		if (P.version == 2)
-			mem = ROMPTR(bios, P.data[8]);
+			hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[8]);
 		else {
 			NV_WARN(dev, "unknown mem for BIT P %d\n", P.version);
 		}
@@ -541,150 +650,56 @@
 		return;
 	}
 
-	if (!mem) {
+	if (!hdr) {
 		NV_DEBUG(dev, "memory timing table pointer invalid\n");
 		return;
 	}
 
-	if (mem[0] != 0x10) {
-		NV_WARN(dev, "memory timing table 0x%02x unknown\n", mem[0]);
+	if (hdr->version != 0x10) {
+		NV_WARN(dev, "memory timing table 0x%02x unknown\n", hdr->version);
 		return;
 	}
 
 	/* validate record length */
-	entries   = mem[2];
-	recordlen = mem[3];
-	if (recordlen < 15) {
-		NV_ERROR(dev, "mem timing table length unknown: %d\n", mem[3]);
+	if (hdr->entry_len < 15) {
+		NV_ERROR(dev, "mem timing table length unknown: %d\n", hdr->entry_len);
 		return;
 	}
 
 	/* parse vbios entries into common format */
 	memtimings->timing =
-		kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL);
+		kcalloc(hdr->entry_cnt, sizeof(*memtimings->timing), GFP_KERNEL);
 	if (!memtimings->timing)
 		return;
 
 	/* Get "some number" from the timing reg for NV_40 and NV_50
-	 * Used in calculations later */
-	if (dev_priv->card_type >= NV_40 && dev_priv->chipset < 0x98) {
+	 * Used in calculations later... source unknown */
+	magic_number = 0;
+	if (P.version == 1) {
 		magic_number = (nv_rd32(dev, 0x100228) & 0x0f000000) >> 24;
 	}
 
-	entry = mem + mem[1];
-	for (i = 0; i < entries; i++, entry += recordlen) {
+	entry = (u8*) hdr + hdr->header_len;
+	for (i = 0; i < hdr->entry_cnt; i++, entry += hdr->entry_len) {
 		struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i];
 		if (entry[0] == 0)
 			continue;
 
-		tUNK_18 = 1;
-		tUNK_19 = 1;
-		tUNK_20 = 0;
-		tUNK_21 = 0;
-		switch (min(recordlen, 22)) {
-		case 22:
-			tUNK_21 = entry[21];
-		case 21:
-			tUNK_20 = entry[20];
-		case 20:
-			tUNK_19 = entry[19];
-		case 19:
-			tUNK_18 = entry[18];
-		default:
-			tUNK_0  = entry[0];
-			tUNK_1  = entry[1];
-			tUNK_2  = entry[2];
-			tRP     = entry[3];
-			tRAS    = entry[5];
-			tRFC    = entry[7];
-			tRC     = entry[9];
-			tUNK_10 = entry[10];
-			tUNK_11 = entry[11];
-			tUNK_12 = entry[12];
-			tUNK_13 = entry[13];
-			tUNK_14 = entry[14];
-			break;
-		}
-
-		timing->reg_100220 = (tRC << 24 | tRFC << 16 | tRAS << 8 | tRP);
-
-		/* XXX: I don't trust the -1's and +1's... they must come
-		 *      from somewhere! */
-		timing->reg_100224 = (tUNK_0 + tUNK_19 + 1 + magic_number) << 24 |
-				      max(tUNK_18, (u8) 1) << 16 |
-				      (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 (dev_priv->chipset >= 0xa3 && dev_priv->chipset < 0xaa)
-			timing->reg_100228 |= (tUNK_19 - 1) << 24;
-		else
-			timing->reg_100228 |= magic_number << 24;
-
-		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;
-		} else if (dev_priv->card_type >= NV_50) {
-			if (dev_priv->chipset < 0x98 ||
-			    (dev_priv->chipset == 0x98 &&
-			     dev_priv->stepping <= 0xa1)) {
-				timing->reg_10022c = (0x14 + tUNK_2) << 24 |
-						     0x16 << 16 |
-						     (tUNK_2 - 1) << 8 |
-						     (tUNK_2 - 1);
-			} else {
-				/* XXX: reg_10022c for recentish cards */
-				timing->reg_10022c = tUNK_2 - 1;
-			}
-
-			timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 |
-						  tUNK_13 << 8  | tUNK_13);
-
-			timing->reg_100234 = (tRAS << 24 | tRC);
-			timing->reg_100234 += max(tUNK_10, tUNK_11) << 16;
-
-			if (dev_priv->chipset < 0x98 ||
-			    (dev_priv->chipset == 0x98 &&
-			     dev_priv->stepping <= 0xa1)) {
-				timing->reg_100234 |= (tUNK_2 + 2) << 8;
-			} else {
-				/* XXX: +6? */
-				timing->reg_100234 |= (tUNK_19 + 6) << 8;
-			}
-
-			/* XXX; reg_100238
-			 * reg_100238: 0x00?????? */
-			timing->reg_10023c = 0x202;
-			if (dev_priv->chipset < 0x98 ||
-			    (dev_priv->chipset == 0x98 &&
-			     dev_priv->stepping <= 0xa1)) {
-				timing->reg_10023c |= 0x4000000 | (tUNK_2 - 1) << 16;
-			} else {
-				/* XXX: reg_10023c
-				 * currently unknown
-				 * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */
-			}
-
-			/* XXX: reg_100240? */
-		}
 		timing->id = i;
+		timing->WR = entry[0];
+		timing->CL = entry[2];
 
-		NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i,
-			 timing->reg_100220, timing->reg_100224,
-			 timing->reg_100228, timing->reg_10022c);
-		NV_DEBUG(dev, "         230: %08x %08x %08x %08x\n",
-			 timing->reg_100230, timing->reg_100234,
-			 timing->reg_100238, timing->reg_10023c);
-		NV_DEBUG(dev, "         240: %08x\n", timing->reg_100240);
+		if(dev_priv->card_type <= NV_40) {
+			nv40_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]);
+		} else if(dev_priv->card_type == NV_50){
+			nv50_mem_timing_entry(dev,&P,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]);
+		} else if(dev_priv->card_type == NV_C0) {
+			nvc0_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,&pm->memtimings.timing[i]);
+		}
 	}
 
-	memtimings->nr_timing = entries;
-	memtimings->supported = (dev_priv->chipset <= 0x98);
+	memtimings->nr_timing = hdr->entry_cnt;
+	memtimings->supported = P.version == 1;
 }
 
 void
@@ -693,7 +708,10 @@
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_pm_memtimings *mem = &dev_priv->engine.pm.memtimings;
 
-	kfree(mem->timing);
+	if(mem->timing) {
+		kfree(mem->timing);
+		mem->timing = NULL;
+	}
 }
 
 static int
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_mm.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_mm.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_mm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_mm.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,7 @@
 #include "nouveau_mm.h"
 
 static inline void
-region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a)
+region_put(struct nouveau_mm *mm, struct nouveau_mm_node *a)
 {
 	list_del(&a->nl_entry);
 	list_del(&a->fl_entry);
@@ -35,7 +35,7 @@
 }
 
 static struct nouveau_mm_node *
-region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size)
+region_split(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size)
 {
 	struct nouveau_mm_node *b;
 
@@ -57,33 +57,33 @@
 	return b;
 }
 
-#define node(root, dir) ((root)->nl_entry.dir == &rmm->nodes) ? NULL : \
+#define node(root, dir) ((root)->nl_entry.dir == &mm->nodes) ? NULL : \
 	list_entry((root)->nl_entry.dir, struct nouveau_mm_node, nl_entry)
 
 void
-nouveau_mm_put(struct nouveau_mm *rmm, struct nouveau_mm_node *this)
+nouveau_mm_put(struct nouveau_mm *mm, struct nouveau_mm_node *this)
 {
 	struct nouveau_mm_node *prev = node(this, prev);
 	struct nouveau_mm_node *next = node(this, next);
 
-	list_add(&this->fl_entry, &rmm->free);
+	list_add(&this->fl_entry, &mm->free);
 	this->type = 0;
 
 	if (prev && prev->type == 0) {
 		prev->length += this->length;
-		region_put(rmm, this);
+		region_put(mm, this);
 		this = prev;
 	}
 
 	if (next && next->type == 0) {
 		next->offset  = this->offset;
 		next->length += this->length;
-		region_put(rmm, this);
+		region_put(mm, this);
 	}
 }
 
 int
-nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc,
+nouveau_mm_get(struct nouveau_mm *mm, int type, u32 size, u32 size_nc,
 	       u32 align, struct nouveau_mm_node **pnode)
 {
 	struct nouveau_mm_node *prev, *this, *next;
@@ -92,17 +92,17 @@
 	u32 splitoff;
 	u32 s, e;
 
-	list_for_each_entry(this, &rmm->free, fl_entry) {
+	list_for_each_entry(this, &mm->free, fl_entry) {
 		e = this->offset + this->length;
 		s = this->offset;
 
 		prev = node(this, prev);
 		if (prev && prev->type != type)
-			s = roundup(s, rmm->block_size);
+			s = roundup(s, mm->block_size);
 
 		next = node(this, next);
 		if (next && next->type != type)
-			e = rounddown(e, rmm->block_size);
+			e = rounddown(e, mm->block_size);
 
 		s  = (s + align_mask) & ~align_mask;
 		e &= ~align_mask;
@@ -110,10 +110,10 @@
 			continue;
 
 		splitoff = s - this->offset;
-		if (splitoff && !region_split(rmm, this, splitoff))
+		if (splitoff && !region_split(mm, this, splitoff))
 			return -ENOMEM;
 
-		this = region_split(rmm, this, min(size, e - s));
+		this = region_split(mm, this, min(size, e - s));
 		if (!this)
 			return -ENOMEM;
 
@@ -127,52 +127,49 @@
 }
 
 int
-nouveau_mm_init(struct nouveau_mm **prmm, u32 offset, u32 length, u32 block)
+nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
 {
-	struct nouveau_mm *rmm;
-	struct nouveau_mm_node *heap;
+	struct nouveau_mm_node *node;
 
-	heap = kzalloc(sizeof(*heap), GFP_KERNEL);
-	if (!heap)
-		return -ENOMEM;
-	heap->offset = roundup(offset, block);
-	heap->length = rounddown(offset + length, block) - heap->offset;
+	if (block) {
+		mutex_init(&mm->mutex);
+		INIT_LIST_HEAD(&mm->nodes);
+		INIT_LIST_HEAD(&mm->free);
+		mm->block_size = block;
+		mm->heap_nodes = 0;
+	}
 
-	rmm = kzalloc(sizeof(*rmm), GFP_KERNEL);
-	if (!rmm) {
-		kfree(heap);
+	node = kzalloc(sizeof(*node), GFP_KERNEL);
+	if (!node)
 		return -ENOMEM;
-	}
-	rmm->block_size = block;
-	mutex_init(&rmm->mutex);
-	INIT_LIST_HEAD(&rmm->nodes);
-	INIT_LIST_HEAD(&rmm->free);
-	list_add(&heap->nl_entry, &rmm->nodes);
-	list_add(&heap->fl_entry, &rmm->free);
+	node->offset = roundup(offset, mm->block_size);
+	node->length = rounddown(offset + length, mm->block_size) - node->offset;
 
-	*prmm = rmm;
+	list_add_tail(&node->nl_entry, &mm->nodes);
+	list_add_tail(&node->fl_entry, &mm->free);
+	mm->heap_nodes++;
 	return 0;
 }
 
 int
-nouveau_mm_fini(struct nouveau_mm **prmm)
+nouveau_mm_fini(struct nouveau_mm *mm)
 {
-	struct nouveau_mm *rmm = *prmm;
 	struct nouveau_mm_node *node, *heap =
-		list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry);
+		list_first_entry(&mm->nodes, struct nouveau_mm_node, nl_entry);
+	int nodes = 0;
 
-	if (!list_is_singular(&rmm->nodes)) {
-		printk(KERN_ERR "nouveau_mm not empty at destroy time!\n");
-		list_for_each_entry(node, &rmm->nodes, nl_entry) {
-			printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n",
-			       node->type, node->offset, node->length);
+	list_for_each_entry(node, &mm->nodes, nl_entry) {
+		if (nodes++ == mm->heap_nodes) {
+			printk(KERN_ERR "nouveau_mm in use at destroy time!\n");
+			list_for_each_entry(node, &mm->nodes, nl_entry) {
+				printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n",
+				       node->type, node->offset, node->length);
+			}
+			WARN_ON(1);
+			return -EBUSY;
 		}
-		WARN_ON(1);
-		return -EBUSY;
 	}
 
 	kfree(heap);
-	kfree(rmm);
-	*prmm = NULL;
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_mm.h linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_mm.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_mm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_mm.h	2012-01-04 18:55:44.000000000 -0500
@@ -42,10 +42,11 @@
 	struct mutex mutex;
 
 	u32 block_size;
+	int heap_nodes;
 };
 
-int  nouveau_mm_init(struct nouveau_mm **, u32 offset, u32 length, u32 block);
-int  nouveau_mm_fini(struct nouveau_mm **);
+int  nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);
+int  nouveau_mm_fini(struct nouveau_mm *);
 int  nouveau_mm_pre(struct nouveau_mm *);
 int  nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc,
 		    u32 align, struct nouveau_mm_node **);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_object.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_object.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_object.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_object.c	2012-01-04 18:55:44.000000000 -0500
@@ -680,7 +680,7 @@
 		return ret;
 	}
 
-	ret = drm_mm_init(&chan->ramin_heap, base, size);
+	ret = drm_mm_init(&chan->ramin_heap, base, size - base);
 	if (ret) {
 		NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret);
 		nouveau_gpuobj_ref(NULL, &chan->ramin);
@@ -693,6 +693,7 @@
 static int
 nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm)
 {
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
 	struct drm_device *dev = chan->dev;
 	struct nouveau_gpuobj *pgd = NULL;
 	struct nouveau_vm_pgd *vpgd;
@@ -722,6 +723,9 @@
 	nv_wo32(chan->ramin, 0x020c, 0x000000ff);
 
 	/* map display semaphore buffers into channel's vm */
+	if (dev_priv->card_type >= NV_D0)
+		return 0;
+
 	for (i = 0; i < 2; i++) {
 		struct nv50_display_crtc *dispc = &nv50_display(dev)->crtc[i];
 
@@ -746,7 +750,7 @@
 	int ret, i;
 
 	NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
-	if (dev_priv->card_type == NV_C0)
+	if (dev_priv->card_type >= NV_C0)
 		return nvc0_gpuobj_channel_init(chan, vm);
 
 	/* Allocate a chunk of memory for per-channel object storage */
@@ -793,7 +797,7 @@
 			return ret;
 
 		/* dma objects for display sync channel semaphore blocks */
-		for (i = 0; i < 2; i++) {
+		for (i = 0; i < dev->mode_config.num_crtc; i++) {
 			struct nouveau_gpuobj *sem = NULL;
 			struct nv50_display_crtc *dispc =
 				&nv50_display(dev)->crtc[i];
@@ -875,18 +879,18 @@
 
 	NV_DEBUG(dev, "ch%d\n", chan->id);
 
-	if (dev_priv->card_type >= NV_50) {
+	if (dev_priv->card_type >= NV_50 && dev_priv->card_type <= NV_C0) {
 		struct nv50_display *disp = nv50_display(dev);
 
-		for (i = 0; i < 2; i++) {
+		for (i = 0; i < dev->mode_config.num_crtc; i++) {
 			struct nv50_display_crtc *dispc = &disp->crtc[i];
 			nouveau_bo_vma_del(dispc->sem.bo, &chan->dispc_vma[i]);
 		}
-
-		nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
-		nouveau_gpuobj_ref(NULL, &chan->vm_pd);
 	}
 
+	nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
+	nouveau_gpuobj_ref(NULL, &chan->vm_pd);
+
 	if (drm_mm_initialized(&chan->ramin_heap))
 		drm_mm_takedown(&chan->ramin_heap);
 	nouveau_gpuobj_ref(NULL, &chan->ramin);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_perf.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_perf.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_perf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_perf.c	2012-01-04 18:55:44.000000000 -0500
@@ -127,13 +127,57 @@
 
 	entry += ramcfg * recordlen;
 	if (entry[1] >= pm->memtimings.nr_timing) {
-		NV_WARN(dev, "timingset %d does not exist\n", entry[1]);
+		if (entry[1] != 0xff)
+			NV_WARN(dev, "timingset %d does not exist\n", entry[1]);
 		return NULL;
 	}
 
 	return &pm->memtimings.timing[entry[1]];
 }
 
+static void
+nouveau_perf_voltage(struct drm_device *dev, struct bit_entry *P,
+		     struct nouveau_pm_level *perflvl)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->vbios;
+	u8 *vmap;
+	int id;
+
+	id = perflvl->volt_min;
+	perflvl->volt_min = 0;
+
+	/* boards using voltage table version <0x40 store the voltage
+	 * level directly in the perflvl entry as a multiple of 10mV
+	 */
+	if (dev_priv->engine.pm.voltage.version < 0x40) {
+		perflvl->volt_min = id * 10000;
+		perflvl->volt_max = perflvl->volt_min;
+		return;
+	}
+
+	/* on newer ones, the perflvl stores an index into yet another
+	 * vbios table containing a min/max voltage value for the perflvl
+	 */
+	if (P->version != 2 || P->length < 34) {
+		NV_DEBUG(dev, "where's our volt map table ptr? %d %d\n",
+			 P->version, P->length);
+		return;
+	}
+
+	vmap = ROMPTR(bios, P->data[32]);
+	if (!vmap) {
+		NV_DEBUG(dev, "volt map table pointer invalid\n");
+		return;
+	}
+
+	if (id < vmap[3]) {
+		vmap += vmap[1] + (vmap[2] * id);
+		perflvl->volt_min = ROM32(vmap[0]);
+		perflvl->volt_max = ROM32(vmap[4]);
+	}
+}
+
 void
 nouveau_perf_init(struct drm_device *dev)
 {
@@ -141,6 +185,8 @@
 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
 	struct nvbios *bios = &dev_priv->vbios;
 	struct bit_entry P;
+	struct nouveau_pm_memtimings *memtimings = &pm->memtimings;
+	struct nouveau_pm_tbl_header mt_hdr;
 	u8 version, headerlen, recordlen, entries;
 	u8 *perf, *entry;
 	int vid, i;
@@ -188,6 +234,22 @@
 	}
 
 	entry = perf + headerlen;
+
+	/* For version 0x15, initialize memtiming table */
+	if(version == 0x15) {
+		memtimings->timing =
+				kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL);
+		if (!memtimings->timing) {
+			NV_WARN(dev,"Could not allocate memtiming table\n");
+			return;
+		}
+
+		mt_hdr.entry_cnt = entries;
+		mt_hdr.entry_len = 14;
+		mt_hdr.version = version;
+		mt_hdr.header_len = 4;
+	}
+
 	for (i = 0; i < entries; i++) {
 		struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl];
 
@@ -203,7 +265,8 @@
 		case 0x13:
 		case 0x15:
 			perflvl->fanspeed = entry[55];
-			perflvl->voltage = (recordlen > 56) ? entry[56] : 0;
+			if (recordlen > 56)
+				perflvl->volt_min = entry[56];
 			perflvl->core = ROM32(entry[1]) * 10;
 			perflvl->memory = ROM32(entry[5]) * 20;
 			break;
@@ -211,9 +274,10 @@
 		case 0x23:
 		case 0x24:
 			perflvl->fanspeed = entry[4];
-			perflvl->voltage = entry[5];
-			perflvl->core = ROM16(entry[6]) * 1000;
-
+			perflvl->volt_min = entry[5];
+			perflvl->shader = ROM16(entry[6]) * 1000;
+			perflvl->core = perflvl->shader;
+			perflvl->core += (signed char)entry[8] * 1000;
 			if (dev_priv->chipset == 0x49 ||
 			    dev_priv->chipset == 0x4b)
 				perflvl->memory = ROM16(entry[11]) * 1000;
@@ -223,7 +287,7 @@
 			break;
 		case 0x25:
 			perflvl->fanspeed = entry[4];
-			perflvl->voltage = entry[5];
+			perflvl->volt_min = entry[5];
 			perflvl->core = ROM16(entry[6]) * 1000;
 			perflvl->shader = ROM16(entry[10]) * 1000;
 			perflvl->memory = ROM16(entry[12]) * 1000;
@@ -232,7 +296,7 @@
 			perflvl->memscript = ROM16(entry[2]);
 		case 0x35:
 			perflvl->fanspeed = entry[6];
-			perflvl->voltage = entry[7];
+			perflvl->volt_min = entry[7];
 			perflvl->core = ROM16(entry[8]) * 1000;
 			perflvl->shader = ROM16(entry[10]) * 1000;
 			perflvl->memory = ROM16(entry[12]) * 1000;
@@ -240,30 +304,34 @@
 			perflvl->unk05 = ROM16(entry[16]) * 1000;
 			break;
 		case 0x40:
-#define subent(n) entry[perf[2] + ((n) * perf[3])]
+#define subent(n) (ROM16(entry[perf[2] + ((n) * perf[3])]) & 0xfff) * 1000
 			perflvl->fanspeed = 0; /*XXX*/
-			perflvl->voltage = entry[2];
+			perflvl->volt_min = entry[2];
 			if (dev_priv->card_type == NV_50) {
-				perflvl->core = ROM16(subent(0)) & 0xfff;
-				perflvl->shader = ROM16(subent(1)) & 0xfff;
-				perflvl->memory = ROM16(subent(2)) & 0xfff;
+				perflvl->core   = subent(0);
+				perflvl->shader = subent(1);
+				perflvl->memory = subent(2);
+				perflvl->vdec   = subent(3);
+				perflvl->unka0  = subent(4);
 			} else {
-				perflvl->shader = ROM16(subent(3)) & 0xfff;
+				perflvl->hub06  = subent(0);
+				perflvl->hub01  = subent(1);
+				perflvl->copy   = subent(2);
+				perflvl->shader = subent(3);
+				perflvl->rop    = subent(4);
+				perflvl->memory = subent(5);
+				perflvl->vdec   = subent(6);
+				perflvl->daemon = subent(10);
+				perflvl->hub07  = subent(11);
 				perflvl->core   = perflvl->shader / 2;
-				perflvl->unk0a  = ROM16(subent(4)) & 0xfff;
-				perflvl->memory = ROM16(subent(5)) & 0xfff;
 			}
-
-			perflvl->core *= 1000;
-			perflvl->shader *= 1000;
-			perflvl->memory *= 1000;
-			perflvl->unk0a *= 1000;
 			break;
 		}
 
 		/* make sure vid is valid */
-		if (pm->voltage.supported && perflvl->voltage) {
-			vid = nouveau_volt_vid_lookup(dev, perflvl->voltage);
+		nouveau_perf_voltage(dev, &P, perflvl);
+		if (pm->voltage.supported && perflvl->volt_min) {
+			vid = nouveau_volt_vid_lookup(dev, perflvl->volt_min);
 			if (vid < 0) {
 				NV_DEBUG(dev, "drop perflvl %d, bad vid\n", i);
 				entry += recordlen;
@@ -272,7 +340,11 @@
 		}
 
 		/* get the corresponding memory timings */
-		if (version > 0x15) {
+		if (version == 0x15) {
+			memtimings->timing[i].id = i;
+			nv30_mem_timing_entry(dev,&mt_hdr,(struct nouveau_pm_tbl_entry*) &entry[41],0,&memtimings->timing[i]);
+			perflvl->timing = &memtimings->timing[i];
+		} else if (version > 0x15) {
 			/* last 3 args are for < 0x40, ignored for >= 0x40 */
 			perflvl->timing =
 				nouveau_perf_timing(dev, &P,
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_pm.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_pm.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -64,18 +64,26 @@
 	if (perflvl == pm->cur)
 		return 0;
 
-	if (pm->voltage.supported && pm->voltage_set && perflvl->voltage) {
-		ret = pm->voltage_set(dev, perflvl->voltage);
+	if (pm->voltage.supported && pm->voltage_set && perflvl->volt_min) {
+		ret = pm->voltage_set(dev, perflvl->volt_min);
 		if (ret) {
 			NV_ERROR(dev, "voltage_set %d failed: %d\n",
-				 perflvl->voltage, ret);
+				 perflvl->volt_min, ret);
 		}
 	}
 
-	nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core);
-	nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader);
-	nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory);
-	nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05);
+	if (pm->clocks_pre) {
+		void *state = pm->clocks_pre(dev, perflvl);
+		if (IS_ERR(state))
+			return PTR_ERR(state);
+		pm->clocks_set(dev, state);
+	} else
+	if (pm->clock_set) {
+		nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core);
+		nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader);
+		nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory);
+		nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05);
+	}
 
 	pm->cur = perflvl;
 	return 0;
@@ -92,9 +100,6 @@
 	if (nouveau_perflvl_wr != 7777)
 		return -EPERM;
 
-	if (!pm->clock_set)
-		return -EINVAL;
-
 	if (!strncmp(profile, "boot", 4))
 		perflvl = &pm->boot;
 	else {
@@ -123,31 +128,37 @@
 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
 	int ret;
 
-	if (!pm->clock_get)
-		return -EINVAL;
-
 	memset(perflvl, 0, sizeof(*perflvl));
 
-	ret = pm->clock_get(dev, PLL_CORE);
-	if (ret > 0)
-		perflvl->core = ret;
+	if (pm->clocks_get) {
+		ret = pm->clocks_get(dev, perflvl);
+		if (ret)
+			return ret;
+	} else
+	if (pm->clock_get) {
+		ret = pm->clock_get(dev, PLL_CORE);
+		if (ret > 0)
+			perflvl->core = ret;
 
-	ret = pm->clock_get(dev, PLL_MEMORY);
-	if (ret > 0)
-		perflvl->memory = ret;
+		ret = pm->clock_get(dev, PLL_MEMORY);
+		if (ret > 0)
+			perflvl->memory = ret;
 
-	ret = pm->clock_get(dev, PLL_SHADER);
-	if (ret > 0)
-		perflvl->shader = ret;
+		ret = pm->clock_get(dev, PLL_SHADER);
+		if (ret > 0)
+			perflvl->shader = ret;
 
-	ret = pm->clock_get(dev, PLL_UNK05);
-	if (ret > 0)
-		perflvl->unk05 = ret;
+		ret = pm->clock_get(dev, PLL_UNK05);
+		if (ret > 0)
+			perflvl->unk05 = ret;
+	}
 
 	if (pm->voltage.supported && pm->voltage_get) {
 		ret = pm->voltage_get(dev);
-		if (ret > 0)
-			perflvl->voltage = ret;
+		if (ret > 0) {
+			perflvl->volt_min = ret;
+			perflvl->volt_max = ret;
+		}
 	}
 
 	return 0;
@@ -156,7 +167,7 @@
 static void
 nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len)
 {
-	char c[16], s[16], v[16], f[16], t[16];
+	char c[16], s[16], v[32], f[16], t[16], m[16];
 
 	c[0] = '\0';
 	if (perflvl->core)
@@ -166,9 +177,19 @@
 	if (perflvl->shader)
 		snprintf(s, sizeof(s), " shader %dMHz", perflvl->shader / 1000);
 
+	m[0] = '\0';
+	if (perflvl->memory)
+		snprintf(m, sizeof(m), " memory %dMHz", perflvl->memory / 1000);
+
 	v[0] = '\0';
-	if (perflvl->voltage)
-		snprintf(v, sizeof(v), " voltage %dmV", perflvl->voltage * 10);
+	if (perflvl->volt_min && perflvl->volt_min != perflvl->volt_max) {
+		snprintf(v, sizeof(v), " voltage %dmV-%dmV",
+			 perflvl->volt_min / 1000, perflvl->volt_max / 1000);
+	} else
+	if (perflvl->volt_min) {
+		snprintf(v, sizeof(v), " voltage %dmV",
+			 perflvl->volt_min / 1000);
+	}
 
 	f[0] = '\0';
 	if (perflvl->fanspeed)
@@ -178,8 +199,7 @@
 	if (perflvl->timing)
 		snprintf(t, sizeof(t), " timing %d", perflvl->timing->id);
 
-	snprintf(ptr, len, "memory %dMHz%s%s%s%s%s\n", perflvl->memory / 1000,
-		 c, s, v, f, t);
+	snprintf(ptr, len, "%s%s%s%s%s%s\n", c, s, m, t, v, f);
 }
 
 static ssize_t
@@ -190,7 +210,7 @@
 	char *ptr = buf;
 	int len = PAGE_SIZE;
 
-	snprintf(ptr, len, "%d: ", perflvl->id);
+	snprintf(ptr, len, "%d:", perflvl->id);
 	ptr += strlen(buf);
 	len -= strlen(buf);
 
@@ -211,9 +231,9 @@
 	if (!pm->cur)
 		snprintf(ptr, len, "setting: boot\n");
 	else if (pm->cur == &pm->boot)
-		snprintf(ptr, len, "setting: boot\nc: ");
+		snprintf(ptr, len, "setting: boot\nc:");
 	else
-		snprintf(ptr, len, "setting: static %d\nc: ", pm->cur->id);
+		snprintf(ptr, len, "setting: static %d\nc:", pm->cur->id);
 	ptr += strlen(buf);
 	len -= strlen(buf);
 
@@ -292,7 +312,7 @@
 	}
 }
 
-#ifdef CONFIG_HWMON
+#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
 static ssize_t
 nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf)
 {
@@ -409,7 +429,7 @@
 static int
 nouveau_hwmon_init(struct drm_device *dev)
 {
-#ifdef CONFIG_HWMON
+#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
 	struct device *hwmon_dev;
@@ -442,7 +462,7 @@
 static void
 nouveau_hwmon_fini(struct drm_device *dev)
 {
-#ifdef CONFIG_HWMON
+#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
 
@@ -488,7 +508,7 @@
 	NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl);
 	for (i = 0; i < pm->nr_perflvl; i++) {
 		nouveau_pm_perflvl_info(&pm->perflvl[i], info, sizeof(info));
-		NV_INFO(dev, "%d: %s", pm->perflvl[i].id, info);
+		NV_INFO(dev, "%d:%s", pm->perflvl[i].id, info);
 	}
 
 	/* determine current ("boot") performance level */
@@ -498,7 +518,7 @@
 		pm->cur = &pm->boot;
 
 		nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info));
-		NV_INFO(dev, "c: %s", info);
+		NV_INFO(dev, "c:%s", info);
 	}
 
 	/* switch performance levels now if requested */
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_pm.h linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_pm.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_pm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_pm.h	2012-01-04 18:55:44.000000000 -0500
@@ -52,6 +52,11 @@
 			u32 id, int khz);
 void nv04_pm_clock_set(struct drm_device *, void *);
 
+/* nv40_pm.c */
+int nv40_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *);
+void *nv40_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *);
+void nv40_pm_clocks_set(struct drm_device *, void *);
+
 /* nv50_pm.c */
 int nv50_pm_clock_get(struct drm_device *, u32 id);
 void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *,
@@ -59,10 +64,12 @@
 void nv50_pm_clock_set(struct drm_device *, void *);
 
 /* nva3_pm.c */
-int nva3_pm_clock_get(struct drm_device *, u32 id);
-void *nva3_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *,
-			u32 id, int khz);
-void nva3_pm_clock_set(struct drm_device *, void *);
+int nva3_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *);
+void *nva3_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *);
+void nva3_pm_clocks_set(struct drm_device *, void *);
+
+/* nvc0_pm.c */
+int nvc0_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *);
 
 /* nouveau_temp.c */
 void nouveau_temp_init(struct drm_device *dev);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_reg.h linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_reg.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_reg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -826,9 +826,12 @@
 #define NV50_PDISPLAY_SOR_DPMS_STATE_ACTIVE                          0x00030000
 #define NV50_PDISPLAY_SOR_DPMS_STATE_BLANKED                         0x00080000
 #define NV50_PDISPLAY_SOR_DPMS_STATE_WAIT                            0x10000000
-#define NV50_PDISPLAY_SOR_BACKLIGHT                                  0x0061c084
-#define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE                           0x80000000
-#define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL                            0x00000fff
+#define NV50_PDISP_SOR_PWM_DIV(i)                     (0x0061c080 + (i) * 0x800)
+#define NV50_PDISP_SOR_PWM_CTL(i)                     (0x0061c084 + (i) * 0x800)
+#define NV50_PDISP_SOR_PWM_CTL_NEW                                   0x80000000
+#define NVA3_PDISP_SOR_PWM_CTL_UNK                                   0x40000000
+#define NV50_PDISP_SOR_PWM_CTL_VAL                                   0x000007ff
+#define NVA3_PDISP_SOR_PWM_CTL_VAL                                   0x00ffffff
 #define NV50_SOR_DP_CTRL(i, l)           (0x0061c10c + (i) * 0x800 + (l) * 0x80)
 #define NV50_SOR_DP_CTRL_ENABLED                                     0x00000001
 #define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED                      0x00004000
@@ -843,7 +846,7 @@
 #define NV50_SOR_DP_CTRL_TRAINING_PATTERN_2                          0x02000000
 #define NV50_SOR_DP_UNK118(i, l)         (0x0061c118 + (i) * 0x800 + (l) * 0x80)
 #define NV50_SOR_DP_UNK120(i, l)         (0x0061c120 + (i) * 0x800 + (l) * 0x80)
-#define NV50_SOR_DP_UNK128(i, l)         (0x0061c128 + (i) * 0x800 + (l) * 0x80)
+#define NV50_SOR_DP_SCFG(i, l)           (0x0061c128 + (i) * 0x800 + (l) * 0x80)
 #define NV50_SOR_DP_UNK130(i, l)         (0x0061c130 + (i) * 0x800 + (l) * 0x80)
 
 #define NV50_PDISPLAY_USER(i)                        ((i) * 0x1000 + 0x00640000)
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_sgdma.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_sgdma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_sgdma.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,8 +12,8 @@
 	struct drm_device *dev;
 
 	dma_addr_t *pages;
-	bool *ttm_alloced;
 	unsigned nr_pages;
+	bool unmap_pages;
 
 	u64 offset;
 	bool bound;
@@ -26,43 +26,28 @@
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
 	struct drm_device *dev = nvbe->dev;
+	int i;
 
 	NV_DEBUG(nvbe->dev, "num_pages = %ld\n", num_pages);
 
-	if (nvbe->pages)
-		return -EINVAL;
-
-	nvbe->pages = kmalloc(sizeof(dma_addr_t) * num_pages, GFP_KERNEL);
-	if (!nvbe->pages)
-		return -ENOMEM;
+	nvbe->pages = dma_addrs;
+	nvbe->nr_pages = num_pages;
+	nvbe->unmap_pages = true;
 
-	nvbe->ttm_alloced = kmalloc(sizeof(bool) * num_pages, GFP_KERNEL);
-	if (!nvbe->ttm_alloced) {
-		kfree(nvbe->pages);
-		nvbe->pages = NULL;
-		return -ENOMEM;
+	/* this code path isn't called and is incorrect anyways */
+	if (0) { /* dma_addrs[0] != DMA_ERROR_CODE) { */
+		nvbe->unmap_pages = false;
+		return 0;
 	}
 
-	nvbe->nr_pages = 0;
-	while (num_pages--) {
-		/* 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;
-			}
-			nvbe->ttm_alloced[nvbe->nr_pages] = false;
+	for (i = 0; i < num_pages; i++) {
+		nvbe->pages[i] = pci_map_page(dev->pdev, pages[i], 0,
+					      PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+		if (pci_dma_mapping_error(dev->pdev, nvbe->pages[i])) {
+			nvbe->nr_pages = --i;
+			be->func->clear(be);
+			return -EFAULT;
 		}
-
-		nvbe->nr_pages++;
 	}
 
 	return 0;
@@ -72,26 +57,20 @@
 nouveau_sgdma_clear(struct ttm_backend *be)
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
-	struct drm_device *dev;
-
-	if (nvbe && nvbe->pages) {
-		dev = nvbe->dev;
-		NV_DEBUG(dev, "\n");
+	struct drm_device *dev = nvbe->dev;
 
-		if (nvbe->bound)
-			be->func->unbind(be);
+	if (nvbe->bound)
+		be->func->unbind(be);
 
+	if (nvbe->unmap_pages) {
 		while (nvbe->nr_pages--) {
-			if (!nvbe->ttm_alloced[nvbe->nr_pages])
-				pci_unmap_page(dev->pdev, nvbe->pages[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;
+		nvbe->unmap_pages = false;
 	}
+
+	nvbe->pages = NULL;
 }
 
 static void
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_state.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_state.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_state.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_state.c	2012-01-04 18:55:44.000000000 -0500
@@ -286,9 +286,9 @@
 		engine->gpio.get		= nv10_gpio_get;
 		engine->gpio.set		= nv10_gpio_set;
 		engine->gpio.irq_enable		= NULL;
-		engine->pm.clock_get		= nv04_pm_clock_get;
-		engine->pm.clock_pre		= nv04_pm_clock_pre;
-		engine->pm.clock_set		= nv04_pm_clock_set;
+		engine->pm.clocks_get		= nv40_pm_clocks_get;
+		engine->pm.clocks_pre		= nv40_pm_clocks_pre;
+		engine->pm.clocks_set		= nv40_pm_clocks_set;
 		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
 		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
 		engine->pm.temp_get		= nv40_temp_get;
@@ -299,7 +299,7 @@
 	case 0x50:
 	case 0x80: /* gotta love NVIDIA's consistency.. */
 	case 0x90:
-	case 0xA0:
+	case 0xa0:
 		engine->instmem.init		= nv50_instmem_init;
 		engine->instmem.takedown	= nv50_instmem_takedown;
 		engine->instmem.suspend		= nv50_instmem_suspend;
@@ -359,9 +359,9 @@
 			engine->pm.clock_set	= nv50_pm_clock_set;
 			break;
 		default:
-			engine->pm.clock_get	= nva3_pm_clock_get;
-			engine->pm.clock_pre	= nva3_pm_clock_pre;
-			engine->pm.clock_set	= nva3_pm_clock_set;
+			engine->pm.clocks_get	= nva3_pm_clocks_get;
+			engine->pm.clocks_pre	= nva3_pm_clocks_pre;
+			engine->pm.clocks_set	= nva3_pm_clocks_set;
 			break;
 		}
 		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
@@ -376,7 +376,7 @@
 		engine->vram.put		= nv50_vram_del;
 		engine->vram.flags_valid	= nv50_vram_flags_valid;
 		break;
-	case 0xC0:
+	case 0xc0:
 		engine->instmem.init		= nvc0_instmem_init;
 		engine->instmem.takedown	= nvc0_instmem_takedown;
 		engine->instmem.suspend		= nvc0_instmem_suspend;
@@ -422,12 +422,73 @@
 		engine->vram.put		= nv50_vram_del;
 		engine->vram.flags_valid	= nvc0_vram_flags_valid;
 		engine->pm.temp_get		= nv84_temp_get;
+		engine->pm.clocks_get		= nvc0_pm_clocks_get;
+		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
+		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
+		break;
+	case 0xd0:
+		engine->instmem.init		= nvc0_instmem_init;
+		engine->instmem.takedown	= nvc0_instmem_takedown;
+		engine->instmem.suspend		= nvc0_instmem_suspend;
+		engine->instmem.resume		= nvc0_instmem_resume;
+		engine->instmem.get		= nv50_instmem_get;
+		engine->instmem.put		= nv50_instmem_put;
+		engine->instmem.map		= nv50_instmem_map;
+		engine->instmem.unmap		= nv50_instmem_unmap;
+		engine->instmem.flush		= nv84_instmem_flush;
+		engine->mc.init			= nv50_mc_init;
+		engine->mc.takedown		= nv50_mc_takedown;
+		engine->timer.init		= nv04_timer_init;
+		engine->timer.read		= nv04_timer_read;
+		engine->timer.takedown		= nv04_timer_takedown;
+		engine->fb.init			= nvc0_fb_init;
+		engine->fb.takedown		= nvc0_fb_takedown;
+		engine->fifo.channels		= 128;
+		engine->fifo.init		= nvc0_fifo_init;
+		engine->fifo.takedown		= nvc0_fifo_takedown;
+		engine->fifo.disable		= nvc0_fifo_disable;
+		engine->fifo.enable		= nvc0_fifo_enable;
+		engine->fifo.reassign		= nvc0_fifo_reassign;
+		engine->fifo.channel_id		= nvc0_fifo_channel_id;
+		engine->fifo.create_context	= nvc0_fifo_create_context;
+		engine->fifo.destroy_context	= nvc0_fifo_destroy_context;
+		engine->fifo.load_context	= nvc0_fifo_load_context;
+		engine->fifo.unload_context	= nvc0_fifo_unload_context;
+		engine->display.early_init	= nouveau_stub_init;
+		engine->display.late_takedown	= nouveau_stub_takedown;
+		engine->display.create		= nvd0_display_create;
+		engine->display.init		= nvd0_display_init;
+		engine->display.destroy		= nvd0_display_destroy;
+		engine->gpio.init		= nv50_gpio_init;
+		engine->gpio.takedown		= nouveau_stub_takedown;
+		engine->gpio.get		= nvd0_gpio_get;
+		engine->gpio.set		= nvd0_gpio_set;
+		engine->gpio.irq_register	= nv50_gpio_irq_register;
+		engine->gpio.irq_unregister	= nv50_gpio_irq_unregister;
+		engine->gpio.irq_enable		= nv50_gpio_irq_enable;
+		engine->vram.init		= nvc0_vram_init;
+		engine->vram.takedown		= nv50_vram_fini;
+		engine->vram.get		= nvc0_vram_new;
+		engine->vram.put		= nv50_vram_del;
+		engine->vram.flags_valid	= nvc0_vram_flags_valid;
+		engine->pm.clocks_get		= nvc0_pm_clocks_get;
+		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
+		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
 		break;
 	default:
 		NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
 		return 1;
 	}
 
+	/* headless mode */
+	if (nouveau_modeset == 2) {
+		engine->display.early_init = nouveau_stub_init;
+		engine->display.late_takedown = nouveau_stub_takedown;
+		engine->display.create = nouveau_stub_init;
+		engine->display.init = nouveau_stub_init;
+		engine->display.destroy = nouveau_stub_takedown;
+	}
+
 	return 0;
 }
 
@@ -449,21 +510,6 @@
 		return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
 }
 
-static int
-nouveau_card_init_channel(struct drm_device *dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	int ret;
-
-	ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL,
-				    NvDmaFB, NvDmaTT);
-	if (ret)
-		return ret;
-
-	mutex_unlock(&dev_priv->channel->mutex);
-	return 0;
-}
-
 static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
 					 enum vga_switcheroo_state state)
 {
@@ -533,6 +579,14 @@
 	if (ret)
 		goto out_display_early;
 
+	/* workaround an odd issue on nvc1 by disabling the device's
+	 * nosnoop capability.  hopefully won't cause issues until a
+	 * better fix is found - assuming there is one...
+	 */
+	if (dev_priv->chipset == 0xc1) {
+		nv_mask(dev, 0x00088080, 0x00000800, 0x00000000);
+	}
+
 	nouveau_pm_init(dev);
 
 	ret = engine->vram.init(dev);
@@ -630,8 +684,11 @@
 			break;
 		}
 
-		if (dev_priv->card_type == NV_40)
-			nv40_mpeg_create(dev);
+		if (dev_priv->card_type == NV_40 ||
+		    dev_priv->chipset == 0x31 ||
+		    dev_priv->chipset == 0x34 ||
+		    dev_priv->chipset == 0x36)
+			nv31_mpeg_create(dev);
 		else
 		if (dev_priv->card_type == NV_50 &&
 		    (dev_priv->chipset < 0x98 || dev_priv->chipset == 0xa0))
@@ -651,41 +708,69 @@
 			goto out_engine;
 	}
 
-	ret = engine->display.create(dev);
+	ret = nouveau_irq_init(dev);
 	if (ret)
 		goto out_fifo;
 
-	ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1);
-	if (ret)
-		goto out_vblank;
+	/* initialise general modesetting */
+	drm_mode_config_init(dev);
+	drm_mode_create_scaling_mode_property(dev);
+	drm_mode_create_dithering_property(dev);
+	dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs;
+	dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1);
+	dev->mode_config.min_width = 0;
+	dev->mode_config.min_height = 0;
+	if (dev_priv->card_type < NV_10) {
+		dev->mode_config.max_width = 2048;
+		dev->mode_config.max_height = 2048;
+	} else
+	if (dev_priv->card_type < NV_50) {
+		dev->mode_config.max_width = 4096;
+		dev->mode_config.max_height = 4096;
+	} else {
+		dev->mode_config.max_width = 8192;
+		dev->mode_config.max_height = 8192;
+	}
 
-	ret = nouveau_irq_init(dev);
+	ret = engine->display.create(dev);
 	if (ret)
-		goto out_vblank;
+		goto out_irq;
 
-	/* what about PVIDEO/PCRTC/PRAMDAC etc? */
+	nouveau_backlight_init(dev);
 
 	if (dev_priv->eng[NVOBJ_ENGINE_GR]) {
 		ret = nouveau_fence_init(dev);
 		if (ret)
-			goto out_irq;
+			goto out_disp;
 
-		ret = nouveau_card_init_channel(dev);
+		ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL,
+					    NvDmaFB, NvDmaTT);
 		if (ret)
 			goto out_fence;
+
+		mutex_unlock(&dev_priv->channel->mutex);
+	}
+
+	if (dev->mode_config.num_crtc) {
+		ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+		if (ret)
+			goto out_chan;
+
+		nouveau_fbcon_init(dev);
+		drm_kms_helper_poll_init(dev);
 	}
 
-	nouveau_fbcon_init(dev);
-	drm_kms_helper_poll_init(dev);
 	return 0;
 
+out_chan:
+	nouveau_channel_put_unlocked(&dev_priv->channel);
 out_fence:
 	nouveau_fence_fini(dev);
+out_disp:
+	nouveau_backlight_exit(dev);
+	engine->display.destroy(dev);
 out_irq:
 	nouveau_irq_fini(dev);
-out_vblank:
-	drm_vblank_cleanup(dev);
-	engine->display.destroy(dev);
 out_fifo:
 	if (!dev_priv->noaccel)
 		engine->fifo.takedown(dev);
@@ -732,15 +817,20 @@
 	struct nouveau_engine *engine = &dev_priv->engine;
 	int e;
 
-	drm_kms_helper_poll_fini(dev);
-	nouveau_fbcon_fini(dev);
+	if (dev->mode_config.num_crtc) {
+		drm_kms_helper_poll_fini(dev);
+		nouveau_fbcon_fini(dev);
+		drm_vblank_cleanup(dev);
+	}
 
 	if (dev_priv->channel) {
 		nouveau_channel_put_unlocked(&dev_priv->channel);
 		nouveau_fence_fini(dev);
 	}
 
+	nouveau_backlight_exit(dev);
 	engine->display.destroy(dev);
+	drm_mode_config_cleanup(dev);
 
 	if (!dev_priv->noaccel) {
 		engine->fifo.takedown(dev);
@@ -774,7 +864,6 @@
 	engine->vram.takedown(dev);
 
 	nouveau_irq_fini(dev);
-	drm_vblank_cleanup(dev);
 
 	nouveau_pm_fini(dev);
 	nouveau_bios_takedown(dev);
@@ -907,7 +996,7 @@
 int nouveau_load(struct drm_device *dev, unsigned long flags)
 {
 	struct drm_nouveau_private *dev_priv;
-	uint32_t reg0;
+	uint32_t reg0, strap;
 	resource_size_t mmio_start_offs;
 	int ret;
 
@@ -951,13 +1040,11 @@
 
 	/* Time to determine the card architecture */
 	reg0 = nv_rd32(dev, NV03_PMC_BOOT_0);
-	dev_priv->stepping = 0; /* XXX: add stepping for pre-NV10? */
 
 	/* We're dealing with >=NV10 */
 	if ((reg0 & 0x0f000000) > 0) {
 		/* Bit 27-20 contain the architecture in hex */
 		dev_priv->chipset = (reg0 & 0xff00000) >> 20;
-		dev_priv->stepping = (reg0 & 0xff);
 	/* NV04 or NV05 */
 	} else if ((reg0 & 0xff00fff0) == 0x20004000) {
 		if (reg0 & 0x00f00000)
@@ -987,6 +1074,9 @@
 	case 0xc0:
 		dev_priv->card_type = NV_C0;
 		break;
+	case 0xd0:
+		dev_priv->card_type = NV_D0;
+		break;
 	default:
 		NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0);
 		ret = -EINVAL;
@@ -996,6 +1086,23 @@
 	NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n",
 		dev_priv->card_type, reg0);
 
+	/* determine frequency of timing crystal */
+	strap = nv_rd32(dev, 0x101000);
+	if ( dev_priv->chipset < 0x17 ||
+	    (dev_priv->chipset >= 0x20 && dev_priv->chipset <= 0x25))
+		strap &= 0x00000040;
+	else
+		strap &= 0x00400040;
+
+	switch (strap) {
+	case 0x00000000: dev_priv->crystal = 13500; break;
+	case 0x00000040: dev_priv->crystal = 14318; break;
+	case 0x00400000: dev_priv->crystal = 27000; break;
+	case 0x00400040: dev_priv->crystal = 25000; break;
+	}
+
+	NV_DEBUG(dev, "crystal freq: %dKHz\n", dev_priv->crystal);
+
 	/* Determine whether we'll attempt acceleration or not, some
 	 * cards are disabled by default here due to them being known
 	 * non-functional, or never been tested due to lack of hw.
@@ -1003,12 +1110,13 @@
 	dev_priv->noaccel = !!nouveau_noaccel;
 	if (nouveau_noaccel == -1) {
 		switch (dev_priv->chipset) {
-		case 0xc1: /* known broken */
-		case 0xc8: /* never tested */
+#if 0
+		case 0xXX: /* known broken */
 			NV_INFO(dev, "acceleration disabled by default, pass "
 				     "noaccel=0 to force enable\n");
 			dev_priv->noaccel = true;
 			break;
+#endif
 		default:
 			dev_priv->noaccel = false;
 			break;
@@ -1030,7 +1138,7 @@
 			ioremap(pci_resource_start(dev->pdev, ramin_bar),
 				dev_priv->ramin_size);
 		if (!dev_priv->ramin) {
-			NV_ERROR(dev, "Failed to PRAMIN BAR");
+			NV_ERROR(dev, "Failed to map PRAMIN BAR\n");
 			ret = -ENOMEM;
 			goto err_mmio;
 		}
@@ -1130,7 +1238,7 @@
 		getparam->value = 1;
 		break;
 	case NOUVEAU_GETPARAM_HAS_PAGEFLIP:
-		getparam->value = 1;
+		getparam->value = dev_priv->card_type < NV_D0;
 		break;
 	case NOUVEAU_GETPARAM_GRAPH_UNITS:
 		/* NV40 and NV50 versions are quite different, but register
@@ -1195,6 +1303,23 @@
 			return true;
 	} while (ptimer->read(dev) - start < timeout);
 
+	return false;
+}
+
+/* Wait until cond(data) == true, up until timeout has hit */
+bool
+nouveau_wait_cb(struct drm_device *dev, u64 timeout,
+		bool (*cond)(void *), void *data)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
+	u64 start = ptimer->read(dev);
+
+	do {
+		if (cond(data) == true)
+			return true;
+	} while (ptimer->read(dev) - start < timeout);
+
 	return false;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_temp.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_temp.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_temp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_temp.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,8 @@
  * Authors: Martin Peres
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 
 #include "nouveau_drv.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_vm.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_vm.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_vm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_vm.c	2012-01-04 18:55:44.000000000 -0500
@@ -172,9 +172,9 @@
 			vm->map_pgt(vpgd->obj, pde, vpgt->obj);
 		}
 
-		mutex_unlock(&vm->mm->mutex);
+		mutex_unlock(&vm->mm.mutex);
 		nouveau_gpuobj_ref(NULL, &pgt);
-		mutex_lock(&vm->mm->mutex);
+		mutex_lock(&vm->mm.mutex);
 	}
 }
 
@@ -191,18 +191,18 @@
 	pgt_size  = (1 << (vm->pgt_bits + 12)) >> type;
 	pgt_size *= 8;
 
-	mutex_unlock(&vm->mm->mutex);
+	mutex_unlock(&vm->mm.mutex);
 	ret = nouveau_gpuobj_new(vm->dev, NULL, pgt_size, 0x1000,
 				 NVOBJ_FLAG_ZERO_ALLOC, &pgt);
-	mutex_lock(&vm->mm->mutex);
+	mutex_lock(&vm->mm.mutex);
 	if (unlikely(ret))
 		return ret;
 
 	/* someone beat us to filling the PDE while we didn't have the lock */
 	if (unlikely(vpgt->refcount[big]++)) {
-		mutex_unlock(&vm->mm->mutex);
+		mutex_unlock(&vm->mm.mutex);
 		nouveau_gpuobj_ref(NULL, &pgt);
-		mutex_lock(&vm->mm->mutex);
+		mutex_lock(&vm->mm.mutex);
 		return 0;
 	}
 
@@ -223,10 +223,10 @@
 	u32 fpde, lpde, pde;
 	int ret;
 
-	mutex_lock(&vm->mm->mutex);
-	ret = nouveau_mm_get(vm->mm, page_shift, msize, 0, align, &vma->node);
+	mutex_lock(&vm->mm.mutex);
+	ret = nouveau_mm_get(&vm->mm, page_shift, msize, 0, align, &vma->node);
 	if (unlikely(ret != 0)) {
-		mutex_unlock(&vm->mm->mutex);
+		mutex_unlock(&vm->mm.mutex);
 		return ret;
 	}
 
@@ -245,13 +245,13 @@
 		if (ret) {
 			if (pde != fpde)
 				nouveau_vm_unmap_pgt(vm, big, fpde, pde - 1);
-			nouveau_mm_put(vm->mm, vma->node);
-			mutex_unlock(&vm->mm->mutex);
+			nouveau_mm_put(&vm->mm, vma->node);
+			mutex_unlock(&vm->mm.mutex);
 			vma->node = NULL;
 			return ret;
 		}
 	}
-	mutex_unlock(&vm->mm->mutex);
+	mutex_unlock(&vm->mm.mutex);
 
 	vma->vm     = vm;
 	vma->offset = (u64)vma->node->offset << 12;
@@ -270,11 +270,11 @@
 	fpde = (vma->node->offset >> vm->pgt_bits);
 	lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits;
 
-	mutex_lock(&vm->mm->mutex);
+	mutex_lock(&vm->mm.mutex);
 	nouveau_vm_unmap_pgt(vm, vma->node->type != vm->spg_shift, fpde, lpde);
-	nouveau_mm_put(vm->mm, vma->node);
+	nouveau_mm_put(&vm->mm, vma->node);
 	vma->node = NULL;
-	mutex_unlock(&vm->mm->mutex);
+	mutex_unlock(&vm->mm.mutex);
 }
 
 int
@@ -306,7 +306,7 @@
 			block = length;
 
 	} else
-	if (dev_priv->card_type == NV_C0) {
+	if (dev_priv->card_type >= NV_C0) {
 		vm->map_pgt = nvc0_vm_map_pgt;
 		vm->map = nvc0_vm_map;
 		vm->map_sg = nvc0_vm_map_sg;
@@ -360,11 +360,11 @@
 
 	nouveau_gpuobj_ref(pgd, &vpgd->obj);
 
-	mutex_lock(&vm->mm->mutex);
+	mutex_lock(&vm->mm.mutex);
 	for (i = vm->fpde; i <= vm->lpde; i++)
 		vm->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj);
 	list_add(&vpgd->head, &vm->pgd_list);
-	mutex_unlock(&vm->mm->mutex);
+	mutex_unlock(&vm->mm.mutex);
 	return 0;
 }
 
@@ -377,7 +377,7 @@
 	if (!mpgd)
 		return;
 
-	mutex_lock(&vm->mm->mutex);
+	mutex_lock(&vm->mm.mutex);
 	list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
 		if (vpgd->obj == mpgd) {
 			pgd = vpgd->obj;
@@ -386,7 +386,7 @@
 			break;
 		}
 	}
-	mutex_unlock(&vm->mm->mutex);
+	mutex_unlock(&vm->mm.mutex);
 
 	nouveau_gpuobj_ref(NULL, &pgd);
 }
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_vm.h linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_vm.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_vm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_vm.h	2012-01-04 18:55:44.000000000 -0500
@@ -51,7 +51,7 @@
 
 struct nouveau_vm {
 	struct drm_device *dev;
-	struct nouveau_mm *mm;
+	struct nouveau_mm mm;
 	int refcount;
 
 	struct list_head pgd_list;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_volt.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_volt.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nouveau_volt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nouveau_volt.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,7 @@
 #include "nouveau_drv.h"
 #include "nouveau_pm.h"
 
-static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a };
+static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 };
 static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]);
 
 int
@@ -170,6 +170,13 @@
 		 */
 		vidshift  = 2;
 		break;
+	case 0x40:
+		headerlen = volt[1];
+		recordlen = volt[2];
+		entries   = volt[3]; /* not a clue what the entries are for.. */
+		vidmask   = volt[11]; /* guess.. */
+		vidshift  = 0;
+		break;
 	default:
 		NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]);
 		return;
@@ -197,16 +204,37 @@
 	}
 
 	/* parse vbios entries into common format */
-	voltage->level = kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL);
-	if (!voltage->level)
-		return;
+	voltage->version = volt[0];
+	if (voltage->version < 0x40) {
+		voltage->nr_level = entries;
+		voltage->level =
+			kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL);
+		if (!voltage->level)
+			return;
 
-	entry = volt + headerlen;
-	for (i = 0; i < entries; i++, entry += recordlen) {
-		voltage->level[i].voltage = entry[0];
-		voltage->level[i].vid     = entry[1] >> vidshift;
+		entry = volt + headerlen;
+		for (i = 0; i < entries; i++, entry += recordlen) {
+			voltage->level[i].voltage = entry[0] * 10000;
+			voltage->level[i].vid     = entry[1] >> vidshift;
+		}
+	} else {
+		u32 volt_uv = ROM32(volt[4]);
+		s16 step_uv = ROM16(volt[8]);
+		u8 vid;
+
+		voltage->nr_level = voltage->vid_mask + 1;
+		voltage->level = kcalloc(voltage->nr_level,
+					 sizeof(*voltage->level), GFP_KERNEL);
+		if (!voltage->level)
+			return;
+
+		for (vid = 0; vid <= voltage->vid_mask; vid++) {
+			voltage->level[vid].voltage = volt_uv;
+			voltage->level[vid].vid = vid;
+			volt_uv += step_uv;
+		}
 	}
-	voltage->nr_level  = entries;
+
 	voltage->supported = true;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv04_display.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv04_display.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv04_display.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv04_display.c	2012-01-04 18:55:44.000000000 -0500
@@ -126,27 +126,6 @@
 
 	nouveau_hw_save_vga_fonts(dev, 1);
 
-	drm_mode_config_init(dev);
-	drm_mode_create_scaling_mode_property(dev);
-	drm_mode_create_dithering_property(dev);
-
-	dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs;
-
-	dev->mode_config.min_width = 0;
-	dev->mode_config.min_height = 0;
-	switch (dev_priv->card_type) {
-	case NV_04:
-		dev->mode_config.max_width = 2048;
-		dev->mode_config.max_height = 2048;
-		break;
-	default:
-		dev->mode_config.max_width = 4096;
-		dev->mode_config.max_height = 4096;
-		break;
-	}
-
-	dev->mode_config.fb_base = dev_priv->fb_phys;
-
 	nv04_crtc_create(dev, 0);
 	if (nv_two_heads(dev))
 		nv04_crtc_create(dev, 1);
@@ -235,8 +214,6 @@
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
 		crtc->funcs->restore(crtc);
 
-	drm_mode_config_cleanup(dev);
-
 	nouveau_hw_save_vga_fonts(dev, 0);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv04_pm.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv04_pm.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv04_pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv04_pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,6 +68,7 @@
 nv04_pm_clock_set(struct drm_device *dev, void *pre_state)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
 	struct nv04_pm_state *state = pre_state;
 	u32 reg = state->pll.reg;
 
@@ -85,6 +86,9 @@
 		nv_mask(dev, 0x1002c0, 0, 1 << 8);
 	}
 
+	if (reg == NV_PRAMDAC_NVPLL_COEFF)
+		ptimer->init(dev);
+
 	kfree(state);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv04_timer.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv04_timer.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv04_timer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv04_timer.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,43 +6,75 @@
 int
 nv04_timer_init(struct drm_device *dev)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	u32 m, n, d;
+
 	nv_wr32(dev, NV04_PTIMER_INTR_EN_0, 0x00000000);
 	nv_wr32(dev, NV04_PTIMER_INTR_0, 0xFFFFFFFF);
 
-	/* Just use the pre-existing values when possible for now; these regs
-	 * are not written in nv (driver writer missed a /4 on the address), and
-	 * writing 8 and 3 to the correct regs breaks the timings on the LVDS
-	 * hardware sequencing microcode.
-	 * A correct solution (involving calculations with the GPU PLL) can
-	 * be done when kernel modesetting lands
-	 */
-	if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) ||
-				!nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) {
-		nv_wr32(dev, NV04_PTIMER_NUMERATOR, 0x00000008);
-		nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 0x00000003);
+	/* aim for 31.25MHz, which gives us nanosecond timestamps */
+	d = 1000000 / 32;
+
+	/* determine base clock for timer source */
+	if (dev_priv->chipset < 0x40) {
+		n = dev_priv->engine.pm.clock_get(dev, PLL_CORE);
+	} else
+	if (dev_priv->chipset == 0x40) {
+		/*XXX: figure this out */
+		n = 0;
+	} else {
+		n = dev_priv->crystal;
+		m = 1;
+		while (n < (d * 2)) {
+			n += (n / m);
+			m++;
+		}
+
+		nv_wr32(dev, 0x009220, m - 1);
+	}
+
+	if (!n) {
+		NV_WARN(dev, "PTIMER: unknown input clock freq\n");
+		if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) ||
+		    !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) {
+			nv_wr32(dev, NV04_PTIMER_NUMERATOR, 1);
+			nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 1);
+		}
+		return 0;
 	}
 
+	/* reduce ratio to acceptable values */
+	while (((n % 5) == 0) && ((d % 5) == 0)) {
+		n /= 5;
+		d /= 5;
+	}
+
+	while (((n % 2) == 0) && ((d % 2) == 0)) {
+		n /= 2;
+		d /= 2;
+	}
+
+	while (n > 0xffff || d > 0xffff) {
+		n >>= 1;
+		d >>= 1;
+	}
+
+	nv_wr32(dev, NV04_PTIMER_NUMERATOR, n);
+	nv_wr32(dev, NV04_PTIMER_DENOMINATOR, d);
 	return 0;
 }
 
-uint64_t
+u64
 nv04_timer_read(struct drm_device *dev)
 {
-	uint32_t low;
-	/* From kmmio dumps on nv28 this looks like how the blob does this.
-	 * It reads the high dword twice, before and after.
-	 * The only explanation seems to be that the 64-bit timer counter
-	 * advances between high and low dword reads and may corrupt the
-	 * result. Not confirmed.
-	 */
-	uint32_t high2 = nv_rd32(dev, NV04_PTIMER_TIME_1);
-	uint32_t high1;
+	u32 hi, lo;
+
 	do {
-		high1 = high2;
-		low = nv_rd32(dev, NV04_PTIMER_TIME_0);
-		high2 = nv_rd32(dev, NV04_PTIMER_TIME_1);
-	} while (high1 != high2);
-	return (((uint64_t)high2) << 32) | (uint64_t)low;
+		hi = nv_rd32(dev, NV04_PTIMER_TIME_1);
+		lo = nv_rd32(dev, NV04_PTIMER_TIME_0);
+	} while (hi != nv_rd32(dev, NV04_PTIMER_TIME_1));
+
+	return ((u64)hi << 32 | lo);
 }
 
 void
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv31_mpeg.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv31_mpeg.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv31_mpeg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv31_mpeg.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_ramht.h"
+
+struct nv31_mpeg_engine {
+	struct nouveau_exec_engine base;
+	atomic_t refcount;
+};
+
+
+static int
+nv31_mpeg_context_new(struct nouveau_channel *chan, int engine)
+{
+	struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine);
+
+	if (!atomic_add_unless(&pmpeg->refcount, 1, 1))
+		return -EBUSY;
+
+	chan->engctx[engine] = (void *)0xdeadcafe;
+	return 0;
+}
+
+static void
+nv31_mpeg_context_del(struct nouveau_channel *chan, int engine)
+{
+	struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine);
+	atomic_dec(&pmpeg->refcount);
+	chan->engctx[engine] = NULL;
+}
+
+static int
+nv40_mpeg_context_new(struct nouveau_channel *chan, int engine)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *ctx = NULL;
+	unsigned long flags;
+	int ret;
+
+	NV_DEBUG(dev, "ch%d\n", chan->id);
+
+	ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC |
+				 NVOBJ_FLAG_ZERO_FREE, &ctx);
+	if (ret)
+		return ret;
+
+	nv_wo32(ctx, 0x78, 0x02001ec1);
+
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
+	if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id)
+		nv_wr32(dev, 0x00330c, ctx->pinst >> 4);
+	nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4);
+	nv_mask(dev, 0x002500, 0x00000001, 0x00000001);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+
+	chan->engctx[engine] = ctx;
+	return 0;
+}
+
+static void
+nv40_mpeg_context_del(struct nouveau_channel *chan, int engine)
+{
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct nouveau_gpuobj *ctx = chan->engctx[engine];
+	struct drm_device *dev = chan->dev;
+	unsigned long flags;
+	u32 inst = 0x80000000 | (ctx->pinst >> 4);
+
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
+	if (nv_rd32(dev, 0x00b318) == inst)
+		nv_mask(dev, 0x00b318, 0x80000000, 0x00000000);
+	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+
+	nouveau_gpuobj_ref(NULL, &ctx);
+	chan->engctx[engine] = NULL;
+}
+
+static int
+nv31_mpeg_object_new(struct nouveau_channel *chan, int engine,
+		      u32 handle, u16 class)
+{
+	struct drm_device *dev = chan->dev;
+	struct nouveau_gpuobj *obj = NULL;
+	int ret;
+
+	ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC |
+				 NVOBJ_FLAG_ZERO_FREE, &obj);
+	if (ret)
+		return ret;
+	obj->engine = 2;
+	obj->class  = class;
+
+	nv_wo32(obj, 0x00, class);
+
+	ret = nouveau_ramht_insert(chan, handle, obj);
+	nouveau_gpuobj_ref(NULL, &obj);
+	return ret;
+}
+
+static int
+nv31_mpeg_init(struct drm_device *dev, int engine)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine);
+	int i;
+
+	/* VPE init */
+	nv_mask(dev, 0x000200, 0x00000002, 0x00000000);
+	nv_mask(dev, 0x000200, 0x00000002, 0x00000002);
+	nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
+	nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
+
+	for (i = 0; i < dev_priv->engine.fb.num_tiles; i++)
+		pmpeg->base.set_tile_region(dev, i);
+
+	/* PMPEG init */
+	nv_wr32(dev, 0x00b32c, 0x00000000);
+	nv_wr32(dev, 0x00b314, 0x00000100);
+	nv_wr32(dev, 0x00b220, nv44_graph_class(dev) ? 0x00000044 : 0x00000031);
+	nv_wr32(dev, 0x00b300, 0x02001ec1);
+	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
+
+	nv_wr32(dev, 0x00b100, 0xffffffff);
+	nv_wr32(dev, 0x00b140, 0xffffffff);
+
+	if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) {
+		NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200));
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int
+nv31_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
+{
+	/*XXX: context save? */
+	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
+	nv_wr32(dev, 0x00b140, 0x00000000);
+	return 0;
+}
+
+static int
+nv31_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
+{
+	struct drm_device *dev = chan->dev;
+	u32 inst = data << 4;
+	u32 dma0 = nv_ri32(dev, inst + 0);
+	u32 dma1 = nv_ri32(dev, inst + 4);
+	u32 dma2 = nv_ri32(dev, inst + 8);
+	u32 base = (dma2 & 0xfffff000) | (dma0 >> 20);
+	u32 size = dma1 + 1;
+
+	/* only allow linear DMA objects */
+	if (!(dma0 & 0x00002000))
+		return -EINVAL;
+
+	if (mthd == 0x0190) {
+		/* DMA_CMD */
+		nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000));
+		nv_wr32(dev, 0x00b334, base);
+		nv_wr32(dev, 0x00b324, size);
+	} else
+	if (mthd == 0x01a0) {
+		/* DMA_DATA */
+		nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2);
+		nv_wr32(dev, 0x00b360, base);
+		nv_wr32(dev, 0x00b364, size);
+	} else {
+		/* DMA_IMAGE, VRAM only */
+		if (dma0 & 0x000c0000)
+			return -EINVAL;
+
+		nv_wr32(dev, 0x00b370, base);
+		nv_wr32(dev, 0x00b374, size);
+	}
+
+	return 0;
+}
+
+static int
+nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *ctx;
+	unsigned long flags;
+	int i;
+
+	/* hardcode drm channel id on nv3x, so swmthd lookup works */
+	if (dev_priv->card_type < NV_40)
+		return 0;
+
+	spin_lock_irqsave(&dev_priv->channels.lock, flags);
+	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
+		if (!dev_priv->channels.ptr[i])
+			continue;
+
+		ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG];
+		if (ctx && ctx->pinst == inst)
+			break;
+	}
+	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
+	return i;
+}
+
+static void
+nv31_vpe_set_tile_region(struct drm_device *dev, int i)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
+
+	nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch);
+	nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit);
+	nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr);
+}
+
+static void
+nv31_mpeg_isr(struct drm_device *dev)
+{
+	u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4;
+	u32 chid = nv31_mpeg_isr_chid(dev, inst);
+	u32 stat = nv_rd32(dev, 0x00b100);
+	u32 type = nv_rd32(dev, 0x00b230);
+	u32 mthd = nv_rd32(dev, 0x00b234);
+	u32 data = nv_rd32(dev, 0x00b238);
+	u32 show = stat;
+
+	if (stat & 0x01000000) {
+		/* happens on initial binding of the object */
+		if (type == 0x00000020 && mthd == 0x0000) {
+			nv_mask(dev, 0x00b308, 0x00000000, 0x00000000);
+			show &= ~0x01000000;
+		}
+
+		if (type == 0x00000010) {
+			if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data))
+				show &= ~0x01000000;
+		}
+	}
+
+	nv_wr32(dev, 0x00b100, stat);
+	nv_wr32(dev, 0x00b230, 0x00000001);
+
+	if (show && nouveau_ratelimit()) {
+		NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n",
+			chid, inst, stat, type, mthd, data);
+	}
+}
+
+static void
+nv31_vpe_isr(struct drm_device *dev)
+{
+	if (nv_rd32(dev, 0x00b100))
+		nv31_mpeg_isr(dev);
+
+	if (nv_rd32(dev, 0x00b800)) {
+		u32 stat = nv_rd32(dev, 0x00b800);
+		NV_INFO(dev, "PMSRCH: 0x%08x\n", stat);
+		nv_wr32(dev, 0xb800, stat);
+	}
+}
+
+static void
+nv31_mpeg_destroy(struct drm_device *dev, int engine)
+{
+	struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine);
+
+	nouveau_irq_unregister(dev, 0);
+
+	NVOBJ_ENGINE_DEL(dev, MPEG);
+	kfree(pmpeg);
+}
+
+int
+nv31_mpeg_create(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv31_mpeg_engine *pmpeg;
+
+	pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL);
+	if (!pmpeg)
+		return -ENOMEM;
+	atomic_set(&pmpeg->refcount, 0);
+
+	pmpeg->base.destroy = nv31_mpeg_destroy;
+	pmpeg->base.init = nv31_mpeg_init;
+	pmpeg->base.fini = nv31_mpeg_fini;
+	if (dev_priv->card_type < NV_40) {
+		pmpeg->base.context_new = nv31_mpeg_context_new;
+		pmpeg->base.context_del = nv31_mpeg_context_del;
+	} else {
+		pmpeg->base.context_new = nv40_mpeg_context_new;
+		pmpeg->base.context_del = nv40_mpeg_context_del;
+	}
+	pmpeg->base.object_new = nv31_mpeg_object_new;
+
+	/* ISR vector, PMC_ENABLE bit,  and TILE regs are shared between
+	 * all VPE engines, for this driver's purposes the PMPEG engine
+	 * will be treated as the "master" and handle the global VPE
+	 * bits too
+	 */
+	pmpeg->base.set_tile_region = nv31_vpe_set_tile_region;
+	nouveau_irq_register(dev, 0, nv31_vpe_isr);
+
+	NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base);
+	NVOBJ_CLASS(dev, 0x3174, MPEG);
+	NVOBJ_MTHD (dev, 0x3174, 0x0190, nv31_mpeg_mthd_dma);
+	NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv31_mpeg_mthd_dma);
+	NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv31_mpeg_mthd_dma);
+
+#if 0
+	NVOBJ_ENGINE_ADD(dev, ME, &pme->base);
+	NVOBJ_CLASS(dev, 0x4075, ME);
+#endif
+	return 0;
+
+}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv40_mpeg.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv40_mpeg.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv40_mpeg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv40_mpeg.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,311 +0,0 @@
-/*
- * Copyright 2011 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-
-#include "drmP.h"
-#include "nouveau_drv.h"
-#include "nouveau_ramht.h"
-
-struct nv40_mpeg_engine {
-	struct nouveau_exec_engine base;
-};
-
-static int
-nv40_mpeg_context_new(struct nouveau_channel *chan, int engine)
-{
-	struct drm_device *dev = chan->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_gpuobj *ctx = NULL;
-	unsigned long flags;
-	int ret;
-
-	NV_DEBUG(dev, "ch%d\n", chan->id);
-
-	ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC |
-				 NVOBJ_FLAG_ZERO_FREE, &ctx);
-	if (ret)
-		return ret;
-
-	nv_wo32(ctx, 0x78, 0x02001ec1);
-
-	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-	nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
-	if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id)
-		nv_wr32(dev, 0x00330c, ctx->pinst >> 4);
-	nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4);
-	nv_mask(dev, 0x002500, 0x00000001, 0x00000001);
-	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
-
-	chan->engctx[engine] = ctx;
-	return 0;
-}
-
-static void
-nv40_mpeg_context_del(struct nouveau_channel *chan, int engine)
-{
-	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
-	struct nouveau_gpuobj *ctx = chan->engctx[engine];
-	struct drm_device *dev = chan->dev;
-	unsigned long flags;
-	u32 inst = 0x80000000 | (ctx->pinst >> 4);
-
-	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
-	if (nv_rd32(dev, 0x00b318) == inst)
-		nv_mask(dev, 0x00b318, 0x80000000, 0x00000000);
-	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
-	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
-
-	nouveau_gpuobj_ref(NULL, &ctx);
-	chan->engctx[engine] = NULL;
-}
-
-static int
-nv40_mpeg_object_new(struct nouveau_channel *chan, int engine,
-		      u32 handle, u16 class)
-{
-	struct drm_device *dev = chan->dev;
-	struct nouveau_gpuobj *obj = NULL;
-	int ret;
-
-	ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC |
-				 NVOBJ_FLAG_ZERO_FREE, &obj);
-	if (ret)
-		return ret;
-	obj->engine = 2;
-	obj->class  = class;
-
-	nv_wo32(obj, 0x00, class);
-
-	ret = nouveau_ramht_insert(chan, handle, obj);
-	nouveau_gpuobj_ref(NULL, &obj);
-	return ret;
-}
-
-static int
-nv40_mpeg_init(struct drm_device *dev, int engine)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine);
-	int i;
-
-	/* VPE init */
-	nv_mask(dev, 0x000200, 0x00000002, 0x00000000);
-	nv_mask(dev, 0x000200, 0x00000002, 0x00000002);
-	nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
-	nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
-
-	for (i = 0; i < dev_priv->engine.fb.num_tiles; i++)
-		pmpeg->base.set_tile_region(dev, i);
-
-	/* PMPEG init */
-	nv_wr32(dev, 0x00b32c, 0x00000000);
-	nv_wr32(dev, 0x00b314, 0x00000100);
-	nv_wr32(dev, 0x00b220, 0x00000044);
-	nv_wr32(dev, 0x00b300, 0x02001ec1);
-	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
-
-	nv_wr32(dev, 0x00b100, 0xffffffff);
-	nv_wr32(dev, 0x00b140, 0xffffffff);
-
-	if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) {
-		NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200));
-		return -EBUSY;
-	}
-
-	return 0;
-}
-
-static int
-nv40_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
-{
-	/*XXX: context save? */
-	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
-	nv_wr32(dev, 0x00b140, 0x00000000);
-	return 0;
-}
-
-static int
-nv40_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
-{
-	struct drm_device *dev = chan->dev;
-	u32 inst = data << 4;
-	u32 dma0 = nv_ri32(dev, inst + 0);
-	u32 dma1 = nv_ri32(dev, inst + 4);
-	u32 dma2 = nv_ri32(dev, inst + 8);
-	u32 base = (dma2 & 0xfffff000) | (dma0 >> 20);
-	u32 size = dma1 + 1;
-
-	/* only allow linear DMA objects */
-	if (!(dma0 & 0x00002000))
-		return -EINVAL;
-
-	if (mthd == 0x0190) {
-		/* DMA_CMD */
-		nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000));
-		nv_wr32(dev, 0x00b334, base);
-		nv_wr32(dev, 0x00b324, size);
-	} else
-	if (mthd == 0x01a0) {
-		/* DMA_DATA */
-		nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2);
-		nv_wr32(dev, 0x00b360, base);
-		nv_wr32(dev, 0x00b364, size);
-	} else {
-		/* DMA_IMAGE, VRAM only */
-		if (dma0 & 0x000c0000)
-			return -EINVAL;
-
-		nv_wr32(dev, 0x00b370, base);
-		nv_wr32(dev, 0x00b374, size);
-	}
-
-	return 0;
-}
-
-static int
-nv40_mpeg_isr_chid(struct drm_device *dev, u32 inst)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_gpuobj *ctx;
-	unsigned long flags;
-	int i;
-
-	spin_lock_irqsave(&dev_priv->channels.lock, flags);
-	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
-		if (!dev_priv->channels.ptr[i])
-			continue;
-
-		ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG];
-		if (ctx && ctx->pinst == inst)
-			break;
-	}
-	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
-	return i;
-}
-
-static void
-nv40_vpe_set_tile_region(struct drm_device *dev, int i)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
-
-	nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch);
-	nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit);
-	nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr);
-}
-
-static void
-nv40_mpeg_isr(struct drm_device *dev)
-{
-	u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4;
-	u32 chid = nv40_mpeg_isr_chid(dev, inst);
-	u32 stat = nv_rd32(dev, 0x00b100);
-	u32 type = nv_rd32(dev, 0x00b230);
-	u32 mthd = nv_rd32(dev, 0x00b234);
-	u32 data = nv_rd32(dev, 0x00b238);
-	u32 show = stat;
-
-	if (stat & 0x01000000) {
-		/* happens on initial binding of the object */
-		if (type == 0x00000020 && mthd == 0x0000) {
-			nv_mask(dev, 0x00b308, 0x00000000, 0x00000000);
-			show &= ~0x01000000;
-		}
-
-		if (type == 0x00000010) {
-			if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data))
-				show &= ~0x01000000;
-		}
-	}
-
-	nv_wr32(dev, 0x00b100, stat);
-	nv_wr32(dev, 0x00b230, 0x00000001);
-
-	if (show && nouveau_ratelimit()) {
-		NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n",
-			chid, inst, stat, type, mthd, data);
-	}
-}
-
-static void
-nv40_vpe_isr(struct drm_device *dev)
-{
-	if (nv_rd32(dev, 0x00b100))
-		nv40_mpeg_isr(dev);
-
-	if (nv_rd32(dev, 0x00b800)) {
-		u32 stat = nv_rd32(dev, 0x00b800);
-		NV_INFO(dev, "PMSRCH: 0x%08x\n", stat);
-		nv_wr32(dev, 0xb800, stat);
-	}
-}
-
-static void
-nv40_mpeg_destroy(struct drm_device *dev, int engine)
-{
-	struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine);
-
-	nouveau_irq_unregister(dev, 0);
-
-	NVOBJ_ENGINE_DEL(dev, MPEG);
-	kfree(pmpeg);
-}
-
-int
-nv40_mpeg_create(struct drm_device *dev)
-{
-	struct nv40_mpeg_engine *pmpeg;
-
-	pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL);
-	if (!pmpeg)
-		return -ENOMEM;
-
-	pmpeg->base.destroy = nv40_mpeg_destroy;
-	pmpeg->base.init = nv40_mpeg_init;
-	pmpeg->base.fini = nv40_mpeg_fini;
-	pmpeg->base.context_new = nv40_mpeg_context_new;
-	pmpeg->base.context_del = nv40_mpeg_context_del;
-	pmpeg->base.object_new = nv40_mpeg_object_new;
-
-	/* ISR vector, PMC_ENABLE bit,  and TILE regs are shared between
-	 * all VPE engines, for this driver's purposes the PMPEG engine
-	 * will be treated as the "master" and handle the global VPE
-	 * bits too
-	 */
-	pmpeg->base.set_tile_region = nv40_vpe_set_tile_region;
-	nouveau_irq_register(dev, 0, nv40_vpe_isr);
-
-	NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base);
-	NVOBJ_CLASS(dev, 0x3174, MPEG);
-	NVOBJ_MTHD (dev, 0x3174, 0x0190, nv40_mpeg_mthd_dma);
-	NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv40_mpeg_mthd_dma);
-	NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv40_mpeg_mthd_dma);
-
-#if 0
-	NVOBJ_ENGINE_ADD(dev, ME, &pme->base);
-	NVOBJ_CLASS(dev, 0x4075, ME);
-#endif
-	return 0;
-
-}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv40_pm.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv40_pm.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv40_pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv40_pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,348 @@
+/*
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_bios.h"
+#include "nouveau_pm.h"
+#include "nouveau_hw.h"
+
+#define min2(a,b) ((a) < (b) ? (a) : (b))
+
+static u32
+read_pll_1(struct drm_device *dev, u32 reg)
+{
+	u32 ctrl = nv_rd32(dev, reg + 0x00);
+	int P = (ctrl & 0x00070000) >> 16;
+	int N = (ctrl & 0x0000ff00) >> 8;
+	int M = (ctrl & 0x000000ff) >> 0;
+	u32 ref = 27000, clk = 0;
+
+	if (ctrl & 0x80000000)
+		clk = ref * N / M;
+
+	return clk >> P;
+}
+
+static u32
+read_pll_2(struct drm_device *dev, u32 reg)
+{
+	u32 ctrl = nv_rd32(dev, reg + 0x00);
+	u32 coef = nv_rd32(dev, reg + 0x04);
+	int N2 = (coef & 0xff000000) >> 24;
+	int M2 = (coef & 0x00ff0000) >> 16;
+	int N1 = (coef & 0x0000ff00) >> 8;
+	int M1 = (coef & 0x000000ff) >> 0;
+	int P = (ctrl & 0x00070000) >> 16;
+	u32 ref = 27000, clk = 0;
+
+	if ((ctrl & 0x80000000) && M1) {
+		clk = ref * N1 / M1;
+		if ((ctrl & 0x40000100) == 0x40000000) {
+			if (M2)
+				clk = clk * N2 / M2;
+			else
+				clk = 0;
+		}
+	}
+
+	return clk >> P;
+}
+
+static u32
+read_clk(struct drm_device *dev, u32 src)
+{
+	switch (src) {
+	case 3:
+		return read_pll_2(dev, 0x004000);
+	case 2:
+		return read_pll_1(dev, 0x004008);
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+int
+nv40_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
+{
+	u32 ctrl = nv_rd32(dev, 0x00c040);
+
+	perflvl->core   = read_clk(dev, (ctrl & 0x00000003) >> 0);
+	perflvl->shader = read_clk(dev, (ctrl & 0x00000030) >> 4);
+	perflvl->memory = read_pll_2(dev, 0x4020);
+	return 0;
+}
+
+struct nv40_pm_state {
+	u32 ctrl;
+	u32 npll_ctrl;
+	u32 npll_coef;
+	u32 spll;
+	u32 mpll_ctrl;
+	u32 mpll_coef;
+};
+
+static int
+nv40_calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll,
+	      u32 clk, int *N1, int *M1, int *N2, int *M2, int *log2P)
+{
+	struct nouveau_pll_vals coef;
+	int ret;
+
+	ret = get_pll_limits(dev, reg, pll);
+	if (ret)
+		return ret;
+
+	if (clk < pll->vco1.maxfreq)
+		pll->vco2.maxfreq = 0;
+
+	ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef);
+	if (ret == 0)
+		return -ERANGE;
+
+	*N1 = coef.N1;
+	*M1 = coef.M1;
+	if (N2 && M2) {
+		if (pll->vco2.maxfreq) {
+			*N2 = coef.N2;
+			*M2 = coef.M2;
+		} else {
+			*N2 = 1;
+			*M2 = 1;
+		}
+	}
+	*log2P = coef.log2P;
+	return 0;
+}
+
+void *
+nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
+{
+	struct nv40_pm_state *info;
+	struct pll_lims pll;
+	int N1, N2, M1, M2, log2P;
+	int ret;
+
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return ERR_PTR(-ENOMEM);
+
+	/* core/geometric clock */
+	ret = nv40_calc_pll(dev, 0x004000, &pll, perflvl->core,
+			    &N1, &M1, &N2, &M2, &log2P);
+	if (ret < 0)
+		goto out;
+
+	if (N2 == M2) {
+		info->npll_ctrl = 0x80000100 | (log2P << 16);
+		info->npll_coef = (N1 << 8) | M1;
+	} else {
+		info->npll_ctrl = 0xc0000000 | (log2P << 16);
+		info->npll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1;
+	}
+
+	/* use the second PLL for shader/rop clock, if it differs from core */
+	if (perflvl->shader && perflvl->shader != perflvl->core) {
+		ret = nv40_calc_pll(dev, 0x004008, &pll, perflvl->shader,
+				    &N1, &M1, NULL, NULL, &log2P);
+		if (ret < 0)
+			goto out;
+
+		info->spll = 0xc0000000 | (log2P << 16) | (N1 << 8) | M1;
+		info->ctrl = 0x00000223;
+	} else {
+		info->spll = 0x00000000;
+		info->ctrl = 0x00000333;
+	}
+
+	/* memory clock */
+	if (!perflvl->memory) {
+		info->mpll_ctrl = 0x00000000;
+		goto out;
+	}
+
+	ret = nv40_calc_pll(dev, 0x004020, &pll, perflvl->memory,
+			    &N1, &M1, &N2, &M2, &log2P);
+	if (ret < 0)
+		goto out;
+
+	info->mpll_ctrl  = 0x80000000 | (log2P << 16);
+	info->mpll_ctrl |= min2(pll.log2p_bias + log2P, pll.max_log2p) << 20;
+	if (N2 == M2) {
+		info->mpll_ctrl |= 0x00000100;
+		info->mpll_coef  = (N1 << 8) | M1;
+	} else {
+		info->mpll_ctrl |= 0x40000000;
+		info->mpll_coef  = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1;
+	}
+
+out:
+	if (ret < 0) {
+		kfree(info);
+		info = ERR_PTR(ret);
+	}
+	return info;
+}
+
+static bool
+nv40_pm_gr_idle(void *data)
+{
+	struct drm_device *dev = data;
+
+	if ((nv_rd32(dev, 0x400760) & 0x000000f0) >> 4 !=
+	    (nv_rd32(dev, 0x400760) & 0x0000000f))
+		return false;
+
+	if (nv_rd32(dev, 0x400700))
+		return false;
+
+	return true;
+}
+
+void
+nv40_pm_clocks_set(struct drm_device *dev, void *pre_state)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv40_pm_state *info = pre_state;
+	unsigned long flags;
+	struct bit_entry M;
+	u32 crtc_mask = 0;
+	u8 sr1[2];
+	int i;
+
+	/* determine which CRTCs are active, fetch VGA_SR1 for each */
+	for (i = 0; i < 2; i++) {
+		u32 vbl = nv_rd32(dev, 0x600808 + (i * 0x2000));
+		u32 cnt = 0;
+		do {
+			if (vbl != nv_rd32(dev, 0x600808 + (i * 0x2000))) {
+				nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01);
+				sr1[i] = nv_rd08(dev, 0x0c03c5 + (i * 0x2000));
+				if (!(sr1[i] & 0x20))
+					crtc_mask |= (1 << i);
+				break;
+			}
+			udelay(1);
+		} while (cnt++ < 32);
+	}
+
+	/* halt and idle engines */
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
+	if (!nv_wait(dev, 0x002500, 0x00000010, 0x00000000))
+		goto resume;
+	nv_mask(dev, 0x003220, 0x00000001, 0x00000000);
+	if (!nv_wait(dev, 0x003220, 0x00000010, 0x00000000))
+		goto resume;
+	nv_mask(dev, 0x003200, 0x00000001, 0x00000000);
+	nv04_fifo_cache_pull(dev, false);
+
+	if (!nv_wait_cb(dev, nv40_pm_gr_idle, dev))
+		goto resume;
+
+	/* set engine clocks */
+	nv_mask(dev, 0x00c040, 0x00000333, 0x00000000);
+	nv_wr32(dev, 0x004004, info->npll_coef);
+	nv_mask(dev, 0x004000, 0xc0070100, info->npll_ctrl);
+	nv_mask(dev, 0x004008, 0xc007ffff, info->spll);
+	mdelay(5);
+	nv_mask(dev, 0x00c040, 0x00000333, info->ctrl);
+
+	if (!info->mpll_ctrl)
+		goto resume;
+
+	/* wait for vblank start on active crtcs, disable memory access */
+	for (i = 0; i < 2; i++) {
+		if (!(crtc_mask & (1 << i)))
+			continue;
+		nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00000000);
+		nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000);
+		nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01);
+		nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i] | 0x20);
+	}
+
+	/* prepare ram for reclocking */
+	nv_wr32(dev, 0x1002d4, 0x00000001); /* precharge */
+	nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */
+	nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */
+	nv_mask(dev, 0x100210, 0x80000000, 0x00000000); /* no auto refresh */
+	nv_wr32(dev, 0x1002dc, 0x00000001); /* enable self-refresh */
+
+	/* change the PLL of each memory partition */
+	nv_mask(dev, 0x00c040, 0x0000c000, 0x00000000);
+	switch (dev_priv->chipset) {
+	case 0x40:
+	case 0x45:
+	case 0x41:
+	case 0x42:
+	case 0x47:
+		nv_mask(dev, 0x004044, 0xc0771100, info->mpll_ctrl);
+		nv_mask(dev, 0x00402c, 0xc0771100, info->mpll_ctrl);
+		nv_wr32(dev, 0x004048, info->mpll_coef);
+		nv_wr32(dev, 0x004030, info->mpll_coef);
+	case 0x43:
+	case 0x49:
+	case 0x4b:
+		nv_mask(dev, 0x004038, 0xc0771100, info->mpll_ctrl);
+		nv_wr32(dev, 0x00403c, info->mpll_coef);
+	default:
+		nv_mask(dev, 0x004020, 0xc0771100, info->mpll_ctrl);
+		nv_wr32(dev, 0x004024, info->mpll_coef);
+		break;
+	}
+	udelay(100);
+	nv_mask(dev, 0x00c040, 0x0000c000, 0x0000c000);
+
+	/* re-enable normal operation of memory controller */
+	nv_wr32(dev, 0x1002dc, 0x00000000);
+	nv_mask(dev, 0x100210, 0x80000000, 0x80000000);
+	udelay(100);
+
+	/* execute memory reset script from vbios */
+	if (!bit_table(dev, 'M', &M))
+		nouveau_bios_init_exec(dev, ROM16(M.data[0]));
+
+	/* make sure we're in vblank (hopefully the same one as before), and
+	 * then re-enable crtc memory access
+	 */
+	for (i = 0; i < 2; i++) {
+		if (!(crtc_mask & (1 << i)))
+			continue;
+		nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000);
+		nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01);
+		nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i]);
+	}
+
+	/* resume engines */
+resume:
+	nv_wr32(dev, 0x003250, 0x00000001);
+	nv_mask(dev, 0x003220, 0x00000001, 0x00000001);
+	nv_wr32(dev, 0x003200, 0x00000001);
+	nv_wr32(dev, 0x002500, 0x00000001);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+
+	kfree(info);
+}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_crtc.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_crtc.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_crtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_crtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -329,8 +329,6 @@
 
 	drm_crtc_cleanup(&nv_crtc->base);
 
-	nv50_cursor_fini(nv_crtc);
-
 	nouveau_bo_unmap(nv_crtc->lut.nvbo);
 	nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
 	nouveau_bo_unmap(nv_crtc->cursor.nvbo);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_cursor.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_cursor.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_cursor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_cursor.c	2012-01-04 18:55:44.000000000 -0500
@@ -137,21 +137,3 @@
 	nv_crtc->cursor.show = nv50_cursor_show;
 	return 0;
 }
-
-void
-nv50_cursor_fini(struct nouveau_crtc *nv_crtc)
-{
-	struct drm_device *dev = nv_crtc->base.dev;
-	int idx = nv_crtc->index;
-
-	NV_DEBUG_KMS(dev, "\n");
-
-	nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0);
-	if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx),
-		     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) {
-		NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n");
-		NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n",
-			 nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx)));
-	}
-}
-
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_display.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_display.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_display.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_display.c	2012-01-04 18:55:44.000000000 -0500
@@ -247,6 +247,16 @@
 		}
 	}
 
+	for (i = 0; i < 2; i++) {
+		nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0);
+		if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i),
+			     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) {
+			NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n");
+			NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n",
+				 nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i)));
+		}
+	}
+
 	nv50_evo_fini(dev);
 
 	for (i = 0; i < 3; i++) {
@@ -286,23 +296,6 @@
 		return -ENOMEM;
 	dev_priv->engine.display.priv = priv;
 
-	/* init basic kernel modesetting */
-	drm_mode_config_init(dev);
-
-	/* Initialise some optional connector properties. */
-	drm_mode_create_scaling_mode_property(dev);
-	drm_mode_create_dithering_property(dev);
-
-	dev->mode_config.min_width = 0;
-	dev->mode_config.min_height = 0;
-
-	dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs;
-
-	dev->mode_config.max_width = 8192;
-	dev->mode_config.max_height = 8192;
-
-	dev->mode_config.fb_base = dev_priv->fb_phys;
-
 	/* Create CRTC objects */
 	for (i = 0; i < 2; i++)
 		nv50_crtc_create(dev, i);
@@ -364,8 +357,6 @@
 
 	NV_DEBUG_KMS(dev, "\n");
 
-	drm_mode_config_cleanup(dev);
-
 	nv50_display_disable(dev);
 	nouveau_irq_unregister(dev, 26);
 	kfree(disp);
@@ -625,7 +616,7 @@
 	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;
+	int i, crtc, or = 0, type = OUTPUT_ANY;
 
 	NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
 	disp->irq.dcb = NULL;
@@ -698,7 +689,7 @@
 		struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i];
 
 		if (dcb->type == type && (dcb->or & (1 << or))) {
-			nouveau_bios_run_display_table(dev, dcb, 0, -1);
+			nouveau_bios_run_display_table(dev, 0, -1, dcb, -1);
 			disp->irq.dcb = dcb;
 			goto ack;
 		}
@@ -711,49 +702,18 @@
 }
 
 static void
-nv50_display_unk20_dp_hack(struct drm_device *dev, struct dcb_entry *dcb)
-{
-	int or = ffs(dcb->or) - 1, link = !(dcb->dpconf.sor.link & 1);
-	struct drm_encoder *encoder;
-	uint32_t tmp, unk0 = 0, unk1 = 0;
-
-	if (dcb->type != OUTPUT_DP)
-		return;
-
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-
-		if (nv_encoder->dcb == dcb) {
-			unk0 = nv_encoder->dp.unk0;
-			unk1 = nv_encoder->dp.unk1;
-			break;
-		}
-	}
-
-	if (unk0 || unk1) {
-		tmp  = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
-		tmp &= 0xfffffe03;
-		nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp | unk0);
-
-		tmp  = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link));
-		tmp &= 0xfef080c0;
-		nv_wr32(dev, NV50_SOR_DP_UNK128(or, link), tmp | unk1);
-	}
-}
-
-static void
 nv50_display_unk20_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), tmp, pclk, script, mc = 0;
 	struct dcb_entry *dcb;
-	int i, crtc, or, type = OUTPUT_ANY;
+	int i, crtc, or = 0, type = OUTPUT_ANY;
 
 	NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
 	dcb = disp->irq.dcb;
 	if (dcb) {
-		nouveau_bios_run_display_table(dev, dcb, 0, -2);
+		nouveau_bios_run_display_table(dev, 0, -2, dcb, -1);
 		disp->irq.dcb = NULL;
 	}
 
@@ -837,9 +797,15 @@
 	}
 
 	script = nv50_display_script_select(dev, dcb, mc, pclk);
-	nouveau_bios_run_display_table(dev, dcb, script, pclk);
+	nouveau_bios_run_display_table(dev, script, pclk, dcb, -1);
 
-	nv50_display_unk20_dp_hack(dev, dcb);
+	if (type == OUTPUT_DP) {
+		int link = !(dcb->dpconf.sor.link & 1);
+		if ((mc & 0x000f0000) == 0x00020000)
+			nouveau_dp_tu_update(dev, or, link, pclk, 18);
+		else
+			nouveau_dp_tu_update(dev, or, link, pclk, 24);
+	}
 
 	if (dcb->type != OUTPUT_ANALOG) {
 		tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or));
@@ -904,7 +870,7 @@
 	if (!dcb)
 		goto ack;
 
-	nouveau_bios_run_display_table(dev, dcb, script, -pclk);
+	nouveau_bios_run_display_table(dev, script, -pclk, dcb, -1);
 	nv50_display_unk40_dp_set_tmds(dev, dcb);
 
 ack:
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_gpio.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_gpio.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -98,6 +98,37 @@
 }
 
 int
+nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
+{
+	struct dcb_gpio_entry *gpio;
+	u32 v;
+
+	gpio = nouveau_bios_gpio_entry(dev, tag);
+	if (!gpio)
+		return -ENOENT;
+
+	v  = nv_rd32(dev, 0x00d610 + (gpio->line * 4));
+	v &= 0x00004000;
+	return (!!v == (gpio->state[1] & 1));
+}
+
+int
+nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
+{
+	struct dcb_gpio_entry *gpio;
+	u32 v;
+
+	gpio = nouveau_bios_gpio_entry(dev, tag);
+	if (!gpio)
+		return -ENOENT;
+
+	v = gpio->state[state] ^ 2;
+
+	nv_mask(dev, 0x00d610 + (gpio->line * 4), 0x00003000, v << 12);
+	return 0;
+}
+
+int
 nv50_gpio_irq_register(struct drm_device *dev, enum dcb_gpio_tag tag,
 		       void (*handler)(void *, int), void *data)
 {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_graph.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_graph.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_graph.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_graph.c	2012-01-04 18:55:44.000000000 -0500
@@ -120,70 +120,62 @@
 	return 0;
 }
 
-static void
-nv50_graph_init_reset(struct drm_device *dev)
-{
-	uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21);
-	NV_DEBUG(dev, "\n");
-
-	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e);
-	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |  pmc_e);
-}
-
-static void
-nv50_graph_init_intr(struct drm_device *dev)
-{
-	NV_DEBUG(dev, "\n");
-
-	nv_wr32(dev, NV03_PGRAPH_INTR, 0xffffffff);
-	nv_wr32(dev, 0x400138, 0xffffffff);
-	nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xffffffff);
-}
-
-static void
-nv50_graph_init_regs__nv(struct drm_device *dev)
+static int
+nv50_graph_init(struct drm_device *dev, int engine)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	uint32_t units = nv_rd32(dev, 0x1540);
+	struct nv50_graph_engine *pgraph = nv_engine(dev, engine);
+	u32 units = nv_rd32(dev, 0x001540);
 	int i;
 
 	NV_DEBUG(dev, "\n");
 
+	/* master reset */
+	nv_mask(dev, 0x000200, 0x00201000, 0x00000000);
+	nv_mask(dev, 0x000200, 0x00201000, 0x00201000);
+	nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */
+
+	/* reset/enable traps and interrupts */
 	nv_wr32(dev, 0x400804, 0xc0000000);
 	nv_wr32(dev, 0x406800, 0xc0000000);
 	nv_wr32(dev, 0x400c04, 0xc0000000);
 	nv_wr32(dev, 0x401800, 0xc0000000);
 	nv_wr32(dev, 0x405018, 0xc0000000);
 	nv_wr32(dev, 0x402000, 0xc0000000);
-
 	for (i = 0; i < 16; i++) {
-		if (units & 1 << i) {
-			if (dev_priv->chipset < 0xa0) {
-				nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000);
-				nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000);
-				nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000);
-			} else {
-				nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000);
-				nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000);
-				nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000);
-			}
+		if (!(units & (1 << i)))
+			continue;
+
+		if (dev_priv->chipset < 0xa0) {
+			nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000);
+			nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000);
+			nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000);
+		} else {
+			nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000);
+			nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000);
+			nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000);
 		}
 	}
 
 	nv_wr32(dev, 0x400108, 0xffffffff);
-
-	nv_wr32(dev, 0x400824, 0x00004000);
+	nv_wr32(dev, 0x400138, 0xffffffff);
+	nv_wr32(dev, 0x400100, 0xffffffff);
+	nv_wr32(dev, 0x40013c, 0xffffffff);
 	nv_wr32(dev, 0x400500, 0x00010001);
-}
 
-static void
-nv50_graph_init_zcull(struct drm_device *dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	int i;
-
-	NV_DEBUG(dev, "\n");
+	/* upload context program, initialise ctxctl defaults */
+	nv_wr32(dev, 0x400324, 0x00000000);
+	for (i = 0; i < pgraph->ctxprog_size; i++)
+		nv_wr32(dev, 0x400328, pgraph->ctxprog[i]);
+	nv_wr32(dev, 0x400824, 0x00000000);
+	nv_wr32(dev, 0x400828, 0x00000000);
+	nv_wr32(dev, 0x40082c, 0x00000000);
+	nv_wr32(dev, 0x400830, 0x00000000);
+	nv_wr32(dev, 0x400724, 0x00000000);
+	nv_wr32(dev, 0x40032c, 0x00000000);
+	nv_wr32(dev, 0x400320, 4);	/* CTXCTL_CMD = NEWCTXDMA */
 
+	/* some unknown zcull magic */
 	switch (dev_priv->chipset & 0xf0) {
 	case 0x50:
 	case 0x80:
@@ -212,43 +204,7 @@
 		nv_wr32(dev, 0x402c28 + (i * 8), 0x00000000);
 		nv_wr32(dev, 0x402c2c + (i * 8), 0x00000000);
 	}
-}
-
-static int
-nv50_graph_init_ctxctl(struct drm_device *dev)
-{
-	struct nv50_graph_engine *pgraph = nv_engine(dev, NVOBJ_ENGINE_GR);
-	int i;
 
-	NV_DEBUG(dev, "\n");
-
-	nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
-	for (i = 0; i < pgraph->ctxprog_size; i++)
-		nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, pgraph->ctxprog[i]);
-
-	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);
-	return 0;
-}
-
-static int
-nv50_graph_init(struct drm_device *dev, int engine)
-{
-	int ret;
-
-	NV_DEBUG(dev, "\n");
-
-	nv50_graph_init_reset(dev);
-	nv50_graph_init_regs__nv(dev);
-	nv50_graph_init_zcull(dev);
-
-	ret = nv50_graph_init_ctxctl(dev);
-	if (ret)
-		return ret;
-
-	nv50_graph_init_intr(dev);
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_grctx.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_grctx.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_grctx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_grctx.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,12 @@
 #define CP_FLAG_UNK0B                 ((0 * 32) + 0xb)
 #define CP_FLAG_UNK0B_CLEAR           0
 #define CP_FLAG_UNK0B_SET             1
+#define CP_FLAG_XFER_SWITCH           ((0 * 32) + 0xe)
+#define CP_FLAG_XFER_SWITCH_DISABLE   0
+#define CP_FLAG_XFER_SWITCH_ENABLE    1
+#define CP_FLAG_STATE                 ((0 * 32) + 0x1c)
+#define CP_FLAG_STATE_STOPPED         0
+#define CP_FLAG_STATE_RUNNING         1
 #define CP_FLAG_UNK1D                 ((0 * 32) + 0x1d)
 #define CP_FLAG_UNK1D_CLEAR           0
 #define CP_FLAG_UNK1D_SET             1
@@ -194,6 +200,9 @@
 				   "the devs.\n");
 		return -ENOSYS;
 	}
+
+	cp_set (ctx, STATE, RUNNING);
+	cp_set (ctx, XFER_SWITCH, ENABLE);
 	/* decide whether we're loading/unloading the context */
 	cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save);
 	cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save);
@@ -260,6 +269,8 @@
 	cp_name(ctx, cp_exit);
 	cp_set (ctx, USER_SAVE, NOT_PENDING);
 	cp_set (ctx, USER_LOAD, NOT_PENDING);
+	cp_set (ctx, XFER_SWITCH, DISABLE);
+	cp_set (ctx, STATE, STOPPED);
 	cp_out (ctx, CP_END);
 	ctx->ctxvals_pos += 0x400; /* padding... no idea why you need it */
 
@@ -590,7 +601,7 @@
 					gr_def(ctx, offset + 0x1c, 0x00880000);
 					break;
 				case 0x86:
-					gr_def(ctx, offset + 0x1c, 0x008c0000);
+					gr_def(ctx, offset + 0x1c, 0x018c0000);
 					break;
 				case 0x92:
 				case 0x96:
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_pm.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_pm.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -115,15 +115,15 @@
 	    BIT_M.version == 1 && BIT_M.length >= 0x0b) {
 		script = ROM16(BIT_M.data[0x05]);
 		if (script)
-			nouveau_bios_run_init_table(dev, script, NULL);
+			nouveau_bios_run_init_table(dev, script, NULL, -1);
 		script = ROM16(BIT_M.data[0x07]);
 		if (script)
-			nouveau_bios_run_init_table(dev, script, NULL);
+			nouveau_bios_run_init_table(dev, script, NULL, -1);
 		script = ROM16(BIT_M.data[0x09]);
 		if (script)
-			nouveau_bios_run_init_table(dev, script, NULL);
+			nouveau_bios_run_init_table(dev, script, NULL, -1);
 
-		nouveau_bios_run_init_table(dev, perflvl->memscript, NULL);
+		nouveau_bios_run_init_table(dev, perflvl->memscript, NULL, -1);
 	}
 
 	if (state->type == PLL_MEMORY) {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_sor.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_sor.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_sor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_sor.c	2012-01-04 18:55:44.000000000 -0500
@@ -124,7 +124,7 @@
 		if (mode == DRM_MODE_DPMS_ON) {
 			u8 status = DP_SET_POWER_D0;
 			nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1);
-			nouveau_dp_link_train(encoder);
+			nouveau_dp_link_train(encoder, nv_encoder->dp.datarate);
 		} else {
 			u8 status = DP_SET_POWER_D3;
 			nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1);
@@ -187,14 +187,13 @@
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct drm_device *dev = encoder->dev;
 	struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc);
+	struct nouveau_connector *nv_connector;
 	uint32_t mode_ctl = 0;
 	int ret;
 
 	NV_DEBUG_KMS(dev, "or %d type %d -> crtc %d\n",
 		     nv_encoder->or, nv_encoder->dcb->type, crtc->index);
 
-	nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON);
-
 	switch (nv_encoder->dcb->type) {
 	case OUTPUT_TMDS:
 		if (nv_encoder->dcb->sorconf.link & 1) {
@@ -206,7 +205,15 @@
 			mode_ctl = 0x0200;
 		break;
 	case OUTPUT_DP:
-		mode_ctl |= (nv_encoder->dp.mc_unknown << 16);
+		nv_connector = nouveau_encoder_connector_get(nv_encoder);
+		if (nv_connector && nv_connector->base.display_info.bpc == 6) {
+			nv_encoder->dp.datarate = crtc->mode->clock * 18 / 8;
+			mode_ctl |= 0x00020000;
+		} else {
+			nv_encoder->dp.datarate = crtc->mode->clock * 24 / 8;
+			mode_ctl |= 0x00050000;
+		}
+
 		if (nv_encoder->dcb->sorconf.link & 1)
 			mode_ctl |= 0x00000800;
 		else
@@ -227,6 +234,8 @@
 	if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
 		mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NVSYNC;
 
+	nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON);
+
 	ret = RING_SPACE(evo, 2);
 	if (ret) {
 		NV_ERROR(dev, "no space while connecting SOR\n");
@@ -313,31 +322,6 @@
 	encoder->possible_crtcs = entry->heads;
 	encoder->possible_clones = 0;
 
-	if (nv_encoder->dcb->type == OUTPUT_DP) {
-		int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1);
-		uint32_t tmp;
-
-		tmp = nv_rd32(dev, 0x61c700 + (or * 0x800));
-		if (!tmp)
-			tmp = nv_rd32(dev, 0x610798 + (or * 8));
-
-		switch ((tmp & 0x00000f00) >> 8) {
-		case 8:
-		case 9:
-			nv_encoder->dp.mc_unknown = (tmp & 0x000f0000) >> 16;
-			tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
-			nv_encoder->dp.unk0 = tmp & 0x000001fc;
-			tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link));
-			nv_encoder->dp.unk1 = tmp & 0x010f7f3f;
-			break;
-		default:
-			break;
-		}
-
-		if (!nv_encoder->dp.mc_unknown)
-			nv_encoder->dp.mc_unknown = 5;
-	}
-
 	drm_mode_connector_attach_encoder(connector, encoder);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_vram.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_vram.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nv50_vram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nv50_vram.c	2012-01-04 18:55:44.000000000 -0500
@@ -51,7 +51,7 @@
 nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_mm *mm = dev_priv->engine.vram.mm;
+	struct nouveau_mm *mm = &dev_priv->engine.vram.mm;
 	struct nouveau_mm_node *this;
 	struct nouveau_mem *mem;
 
@@ -82,7 +82,7 @@
 	      u32 memtype, struct nouveau_mem **pmem)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_mm *mm = dev_priv->engine.vram.mm;
+	struct nouveau_mm *mm = &dev_priv->engine.vram.mm;
 	struct nouveau_mm_node *r;
 	struct nouveau_mem *mem;
 	int comp = (memtype & 0x300) >> 8;
@@ -160,7 +160,7 @@
 	colbits  =  (r4 & 0x0000f000) >> 12;
 	rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
 	rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
-	banks    = ((r4 & 0x01000000) ? 8 : 4);
+	banks    = 1 << (((r4 & 0x03000000) >> 24) + 2);
 
 	rowsize = parts * banks * (1 << colbits) * 8;
 	predicted = rowsize << rowbitsa;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nva3_pm.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nva3_pm.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nva3_pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nva3_pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,178 +27,316 @@
 #include "nouveau_bios.h"
 #include "nouveau_pm.h"
 
-/* This is actually a lot more complex than it appears here, but hopefully
- * this should be able to deal with what the VBIOS leaves for us..
- *
- * If not, well, I'll jump off that bridge when I come to it.
- */
+static u32 read_clk(struct drm_device *, int, bool);
+static u32 read_pll(struct drm_device *, int, u32);
 
-struct nva3_pm_state {
-	enum pll_types type;
-	u32 src0;
-	u32 src1;
-	u32 ctrl;
-	u32 coef;
-	u32 old_pnm;
-	u32 new_pnm;
-	u32 new_div;
-};
+static u32
+read_vco(struct drm_device *dev, int clk)
+{
+	u32 sctl = nv_rd32(dev, 0x4120 + (clk * 4));
+	if ((sctl & 0x00000030) != 0x00000030)
+		return read_pll(dev, 0x41, 0x00e820);
+	return read_pll(dev, 0x42, 0x00e8a0);
+}
 
-static int
-nva3_pm_pll_offset(u32 id)
+static u32
+read_clk(struct drm_device *dev, int clk, bool ignore_en)
 {
-	static const u32 pll_map[] = {
-		0x00, PLL_CORE,
-		0x01, PLL_SHADER,
-		0x02, PLL_MEMORY,
-		0x00, 0x00
-	};
-	const u32 *map = pll_map;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	u32 sctl, sdiv, sclk;
 
-	while (map[1]) {
-		if (id == map[1])
-			return map[0];
-		map += 2;
+	/* refclk for the 0xe8xx plls is a fixed frequency */
+	if (clk >= 0x40) {
+		if (dev_priv->chipset == 0xaf) {
+			/* no joke.. seriously.. sigh.. */
+			return nv_rd32(dev, 0x00471c) * 1000;
+		}
+
+		return dev_priv->crystal;
 	}
 
-	return -ENOENT;
+	sctl = nv_rd32(dev, 0x4120 + (clk * 4));
+	if (!ignore_en && !(sctl & 0x00000100))
+		return 0;
+
+	switch (sctl & 0x00003000) {
+	case 0x00000000:
+		return dev_priv->crystal;
+	case 0x00002000:
+		if (sctl & 0x00000040)
+			return 108000;
+		return 100000;
+	case 0x00003000:
+		sclk = read_vco(dev, clk);
+		sdiv = ((sctl & 0x003f0000) >> 16) + 2;
+		return (sclk * 2) / sdiv;
+	default:
+		return 0;
+	}
 }
 
-int
-nva3_pm_clock_get(struct drm_device *dev, u32 id)
+static u32
+read_pll(struct drm_device *dev, int clk, u32 pll)
 {
-	u32 src0, src1, ctrl, coef;
-	struct pll_lims pll;
-	int ret, off;
-	int P, N, M;
+	u32 ctrl = nv_rd32(dev, pll + 0);
+	u32 sclk = 0, P = 1, N = 1, M = 1;
 
-	ret = get_pll_limits(dev, id, &pll);
+	if (!(ctrl & 0x00000008)) {
+		if (ctrl & 0x00000001) {
+			u32 coef = nv_rd32(dev, pll + 4);
+			M = (coef & 0x000000ff) >> 0;
+			N = (coef & 0x0000ff00) >> 8;
+			P = (coef & 0x003f0000) >> 16;
+
+			/* no post-divider on these.. */
+			if ((pll & 0x00ff00) == 0x00e800)
+				P = 1;
+
+			sclk = read_clk(dev, 0x00 + clk, false);
+		}
+	} else {
+		sclk = read_clk(dev, 0x10 + clk, false);
+	}
+
+	return sclk * N / (M * P);
+}
+
+struct creg {
+	u32 clk;
+	u32 pll;
+};
+
+static int
+calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg)
+{
+	struct pll_lims limits;
+	u32 oclk, sclk, sdiv;
+	int P, N, M, diff;
+	int ret;
+
+	reg->pll = 0;
+	reg->clk = 0;
+	if (!khz) {
+		NV_DEBUG(dev, "no clock for 0x%04x/0x%02x\n", pll, clk);
+		return 0;
+	}
+
+	switch (khz) {
+	case 27000:
+		reg->clk = 0x00000100;
+		return khz;
+	case 100000:
+		reg->clk = 0x00002100;
+		return khz;
+	case 108000:
+		reg->clk = 0x00002140;
+		return khz;
+	default:
+		sclk = read_vco(dev, clk);
+		sdiv = min((sclk * 2) / (khz - 2999), (u32)65);
+		/* if the clock has a PLL attached, and we can get a within
+		 * [-2, 3) MHz of a divider, we'll disable the PLL and use
+		 * the divider instead.
+		 *
+		 * divider can go as low as 2, limited here because NVIDIA
+		 * and the VBIOS on my NVA8 seem to prefer using the PLL
+		 * for 810MHz - is there a good reason?
+		 */
+		if (sdiv > 4) {
+			oclk = (sclk * 2) / sdiv;
+			diff = khz - oclk;
+			if (!pll || (diff >= -2000 && diff < 3000)) {
+				reg->clk = (((sdiv - 2) << 16) | 0x00003100);
+				return oclk;
+			}
+		}
+
+		if (!pll) {
+			NV_ERROR(dev, "bad freq %02x: %d %d\n", clk, khz, sclk);
+			return -ERANGE;
+		}
+
+		break;
+	}
+
+	ret = get_pll_limits(dev, pll, &limits);
 	if (ret)
 		return ret;
 
-	off = nva3_pm_pll_offset(id);
-	if (off < 0)
-		return off;
+	limits.refclk = read_clk(dev, clk - 0x10, true);
+	if (!limits.refclk)
+		return -EINVAL;
 
-	src0 = nv_rd32(dev, 0x4120 + (off * 4));
-	src1 = nv_rd32(dev, 0x4160 + (off * 4));
-	ctrl = nv_rd32(dev, pll.reg + 0);
-	coef = nv_rd32(dev, pll.reg + 4);
-	NV_DEBUG(dev, "PLL %02x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
-		      id, src0, src1, ctrl, coef);
+	ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P);
+	if (ret >= 0) {
+		reg->clk = nv_rd32(dev, 0x4120 + (clk * 4));
+		reg->pll = (P << 16) | (N << 8) | M;
+	}
+	return ret;
+}
 
-	if (ctrl & 0x00000008) {
-		u32 div = ((src1 & 0x003c0000) >> 18) + 1;
-		return (pll.refclk * 2) / div;
+static void
+prog_pll(struct drm_device *dev, int clk, u32 pll, struct creg *reg)
+{
+	const u32 src0 = 0x004120 + (clk * 4);
+	const u32 src1 = 0x004160 + (clk * 4);
+	const u32 ctrl = pll + 0;
+	const u32 coef = pll + 4;
+	u32 cntl;
+
+	if (!reg->clk && !reg->pll) {
+		NV_DEBUG(dev, "no clock for %02x\n", clk);
+		return;
 	}
 
-	P = (coef & 0x003f0000) >> 16;
-	N = (coef & 0x0000ff00) >> 8;
-	M = (coef & 0x000000ff);
-	return pll.refclk * N / M / P;
+	cntl = nv_rd32(dev, ctrl) & 0xfffffff2;
+	if (reg->pll) {
+		nv_mask(dev, src0, 0x00000101, 0x00000101);
+		nv_wr32(dev, coef, reg->pll);
+		nv_wr32(dev, ctrl, cntl | 0x00000015);
+		nv_mask(dev, src1, 0x00000100, 0x00000000);
+		nv_mask(dev, src1, 0x00000001, 0x00000000);
+	} else {
+		nv_mask(dev, src1, 0x003f3141, 0x00000101 | reg->clk);
+		nv_wr32(dev, ctrl, cntl | 0x0000001d);
+		nv_mask(dev, ctrl, 0x00000001, 0x00000000);
+		nv_mask(dev, src0, 0x00000100, 0x00000000);
+		nv_mask(dev, src0, 0x00000001, 0x00000000);
+	}
 }
 
-void *
-nva3_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl,
-		  u32 id, int khz)
+static void
+prog_clk(struct drm_device *dev, int clk, struct creg *reg)
 {
-	struct nva3_pm_state *pll;
-	struct pll_lims limits;
-	int N, M, P, diff;
-	int ret, off;
+	if (!reg->clk) {
+		NV_DEBUG(dev, "no clock for %02x\n", clk);
+		return;
+	}
 
-	ret = get_pll_limits(dev, id, &limits);
-	if (ret < 0)
-		return (ret == -ENOENT) ? NULL : ERR_PTR(ret);
+	nv_mask(dev, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | reg->clk);
+}
 
-	off = nva3_pm_pll_offset(id);
-	if (id < 0)
-		return ERR_PTR(-EINVAL);
+int
+nva3_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
+{
+	perflvl->core   = read_pll(dev, 0x00, 0x4200);
+	perflvl->shader = read_pll(dev, 0x01, 0x4220);
+	perflvl->memory = read_pll(dev, 0x02, 0x4000);
+	perflvl->unka0  = read_clk(dev, 0x20, false);
+	perflvl->vdec   = read_clk(dev, 0x21, false);
+	perflvl->daemon = read_clk(dev, 0x25, false);
+	perflvl->copy   = perflvl->core;
+	return 0;
+}
+
+struct nva3_pm_state {
+	struct creg nclk;
+	struct creg sclk;
+	struct creg mclk;
+	struct creg vdec;
+	struct creg unka0;
+};
 
+void *
+nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
+{
+	struct nva3_pm_state *info;
+	int ret;
 
-	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
-	if (!pll)
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
 		return ERR_PTR(-ENOMEM);
-	pll->type = id;
-	pll->src0 = 0x004120 + (off * 4);
-	pll->src1 = 0x004160 + (off * 4);
-	pll->ctrl = limits.reg + 0;
-	pll->coef = limits.reg + 4;
 
-	/* If target clock is within [-2, 3) MHz of a divisor, we'll
-	 * use that instead of calculating MNP values
-	 */
-	pll->new_div = min((limits.refclk * 2) / (khz - 2999), 16);
-	if (pll->new_div) {
-		diff = khz - ((limits.refclk * 2) / pll->new_div);
-		if (diff < -2000 || diff >= 3000)
-			pll->new_div = 0;
-	}
+	ret = calc_clk(dev, 0x10, 0x4200, perflvl->core, &info->nclk);
+	if (ret < 0)
+		goto out;
 
-	if (!pll->new_div) {
-		ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P);
-		if (ret < 0)
-			return ERR_PTR(ret);
+	ret = calc_clk(dev, 0x11, 0x4220, perflvl->shader, &info->sclk);
+	if (ret < 0)
+		goto out;
 
-		pll->new_pnm = (P << 16) | (N << 8) | M;
-		pll->new_div = 2 - 1;
-	} else {
-		pll->new_pnm = 0;
-		pll->new_div--;
+	ret = calc_clk(dev, 0x12, 0x4000, perflvl->memory, &info->mclk);
+	if (ret < 0)
+		goto out;
+
+	ret = calc_clk(dev, 0x20, 0x0000, perflvl->unka0, &info->unka0);
+	if (ret < 0)
+		goto out;
+
+	ret = calc_clk(dev, 0x21, 0x0000, perflvl->vdec, &info->vdec);
+	if (ret < 0)
+		goto out;
+
+out:
+	if (ret < 0) {
+		kfree(info);
+		info = ERR_PTR(ret);
 	}
+	return info;
+}
 
-	if ((nv_rd32(dev, pll->src1) & 0x00000101) != 0x00000101)
-		pll->old_pnm = nv_rd32(dev, pll->coef);
-	return pll;
+static bool
+nva3_pm_grcp_idle(void *data)
+{
+	struct drm_device *dev = data;
+
+	if (!(nv_rd32(dev, 0x400304) & 0x00000001))
+		return true;
+	if (nv_rd32(dev, 0x400308) == 0x0050001c)
+		return true;
+	return false;
 }
 
 void
-nva3_pm_clock_set(struct drm_device *dev, void *pre_state)
+nva3_pm_clocks_set(struct drm_device *dev, void *pre_state)
 {
-	struct nva3_pm_state *pll = pre_state;
-	u32 ctrl = 0;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nva3_pm_state *info = pre_state;
+	unsigned long flags;
 
-	/* For the memory clock, NVIDIA will build a "script" describing
-	 * the reclocking process and ask PDAEMON to execute it.
-	 */
-	if (pll->type == PLL_MEMORY) {
-		nv_wr32(dev, 0x100210, 0);
-		nv_wr32(dev, 0x1002dc, 1);
-		nv_wr32(dev, 0x004018, 0x00001000);
-		ctrl = 0x18000100;
+	/* prevent any new grctx switches from starting */
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	nv_wr32(dev, 0x400324, 0x00000000);
+	nv_wr32(dev, 0x400328, 0x0050001c); /* wait flag 0x1c */
+	/* wait for any pending grctx switches to complete */
+	if (!nv_wait_cb(dev, nva3_pm_grcp_idle, dev)) {
+		NV_ERROR(dev, "pm: ctxprog didn't go idle\n");
+		goto cleanup;
 	}
-
-	if (pll->old_pnm || !pll->new_pnm) {
-		nv_mask(dev, pll->src1, 0x003c0101, 0x00000101 |
-						    (pll->new_div << 18));
-		nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl);
-		nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000);
+	/* freeze PFIFO */
+	nv_mask(dev, 0x002504, 0x00000001, 0x00000001);
+	if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) {
+		NV_ERROR(dev, "pm: fifo didn't go idle\n");
+		goto cleanup;
 	}
 
-	if (pll->new_pnm) {
-		nv_mask(dev, pll->src0, 0x00000101, 0x00000101);
-		nv_wr32(dev, pll->coef, pll->new_pnm);
-		nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl);
-		nv_mask(dev, pll->ctrl, 0x00000010, 0x00000000);
-		nv_mask(dev, pll->ctrl, 0x00020010, 0x00020010);
-		nv_wr32(dev, pll->ctrl, 0x00010015 | ctrl);
-		nv_mask(dev, pll->src1, 0x00000100, 0x00000000);
-		nv_mask(dev, pll->src1, 0x00000001, 0x00000000);
-		if (pll->type == PLL_MEMORY)
-			nv_wr32(dev, 0x4018, 0x10005000);
-	} else {
-		nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000);
-		nv_mask(dev, pll->src0, 0x00000100, 0x00000000);
-		nv_mask(dev, pll->src0, 0x00000001, 0x00000000);
-		if (pll->type == PLL_MEMORY)
-			nv_wr32(dev, 0x4018, 0x1000d000);
-	}
+	prog_pll(dev, 0x00, 0x004200, &info->nclk);
+	prog_pll(dev, 0x01, 0x004220, &info->sclk);
+	prog_clk(dev, 0x20, &info->unka0);
+	prog_clk(dev, 0x21, &info->vdec);
 
-	if (pll->type == PLL_MEMORY) {
+	if (info->mclk.clk || info->mclk.pll) {
+		nv_wr32(dev, 0x100210, 0);
+		nv_wr32(dev, 0x1002dc, 1);
+		nv_wr32(dev, 0x004018, 0x00001000);
+		prog_pll(dev, 0x02, 0x004000, &info->mclk);
+		if (nv_rd32(dev, 0x4000) & 0x00000008)
+			nv_wr32(dev, 0x004018, 0x1000d000);
+		else
+			nv_wr32(dev, 0x004018, 0x10005000);
 		nv_wr32(dev, 0x1002dc, 0);
 		nv_wr32(dev, 0x100210, 0x80000000);
 	}
 
-	kfree(pll);
+cleanup:
+	/* unfreeze PFIFO */
+	nv_mask(dev, 0x002504, 0x00000001, 0x00000000);
+	/* restore ctxprog to normal */
+	nv_wr32(dev, 0x400324, 0x00000000);
+	nv_wr32(dev, 0x400328, 0x0070009c); /* set flag 0x1c */
+	/* unblock it if necessary */
+	if (nv_rd32(dev, 0x400308) == 0x0050001c)
+		nv_mask(dev, 0x400824, 0x10000000, 0x10000000);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+	kfree(info);
 }
-
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_fb.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_fb.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_fb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_fb.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,30 @@
 	dma_addr_t r100c10;
 };
 
+static inline void
+nvc0_mfb_subp_isr(struct drm_device *dev, int unit, int subp)
+{
+	u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400);
+	u32 stat = nv_rd32(dev, subp_base + 0x020);
+
+	if (stat) {
+		NV_INFO(dev, "PMFB%d_SUBP%d: 0x%08x\n", unit, subp, stat);
+		nv_wr32(dev, subp_base + 0x020, stat);
+	}
+}
+
+static void
+nvc0_mfb_isr(struct drm_device *dev)
+{
+	u32 units = nv_rd32(dev, 0x00017c);
+	while (units) {
+		u32 subp, unit = ffs(units) - 1;
+		for (subp = 0; subp < 2; subp++)
+			nvc0_mfb_subp_isr(dev, unit, subp);
+		units &= ~(1 << unit);
+	}
+}
+
 static void
 nvc0_fb_destroy(struct drm_device *dev)
 {
@@ -39,6 +63,8 @@
 	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
 	struct nvc0_fb_priv *priv = pfb->priv;
 
+	nouveau_irq_unregister(dev, 25);
+
 	if (priv->r100c10_page) {
 		pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE,
 			       PCI_DMA_BIDIRECTIONAL);
@@ -74,6 +100,7 @@
 		return -EFAULT;
 	}
 
+	nouveau_irq_register(dev, 25, nvc0_mfb_isr);
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_fifo.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_fifo.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_fifo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_fifo.c	2012-01-04 18:55:44.000000000 -0500
@@ -322,7 +322,7 @@
 	}
 
 	/* PSUBFIFO[n] */
-	for (i = 0; i < 3; i++) {
+	for (i = 0; i < priv->spoon_nr; i++) {
 		nv_mask(dev, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000);
 		nv_wr32(dev, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */
 		nv_wr32(dev, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTR_EN */
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_graph.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_graph.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_graph.c	2012-03-19 21:29:40.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_graph.c	2012-03-19 21:31:22.000000000 -0400
@@ -23,6 +23,7 @@
  */
 
 #include <linux/firmware.h>
+#include <linux/module.h>
 
 #include "drmP.h"
 
@@ -156,8 +157,8 @@
 	struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR);
 	struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
 	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	int i = 0, gpc, tp, ret;
-	u32 magic;
 
 	ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM,
 				 &grch->unk408004);
@@ -206,14 +207,37 @@
 	nv_wo32(grch->mmio, i++ * 4, 0x0041880c);
 	nv_wo32(grch->mmio, i++ * 4, 0x80000018);
 
-	magic = 0x02180000;
-	nv_wo32(grch->mmio, i++ * 4, 0x00405830);
-	nv_wo32(grch->mmio, i++ * 4, magic);
-	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
-		for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x0324) {
-			u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800);
-			nv_wo32(grch->mmio, i++ * 4, reg);
-			nv_wo32(grch->mmio, i++ * 4, magic);
+	if (dev_priv->chipset != 0xc1) {
+		u32 magic = 0x02180000;
+		nv_wo32(grch->mmio, i++ * 4, 0x00405830);
+		nv_wo32(grch->mmio, i++ * 4, magic);
+		for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+			for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
+				u32 reg = TP_UNIT(gpc, tp, 0x520);
+				nv_wo32(grch->mmio, i++ * 4, reg);
+				nv_wo32(grch->mmio, i++ * 4, magic);
+				magic += 0x0324;
+			}
+		}
+	} else {
+		u32 magic = 0x02180000;
+		nv_wo32(grch->mmio, i++ * 4, 0x00405830);
+		nv_wo32(grch->mmio, i++ * 4, magic | 0x0000218);
+		nv_wo32(grch->mmio, i++ * 4, 0x004064c4);
+		nv_wo32(grch->mmio, i++ * 4, 0x0086ffff);
+		for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+			for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
+				u32 reg = TP_UNIT(gpc, tp, 0x520);
+				nv_wo32(grch->mmio, i++ * 4, reg);
+				nv_wo32(grch->mmio, i++ * 4, (1 << 28) | magic);
+				magic += 0x0324;
+			}
+			for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
+				u32 reg = TP_UNIT(gpc, tp, 0x544);
+				nv_wo32(grch->mmio, i++ * 4, reg);
+				nv_wo32(grch->mmio, i++ * 4, magic);
+				magic += 0x0324;
+			}
 		}
 	}
 
@@ -357,6 +381,8 @@
 	u8  tpnr[GPC_MAX];
 	int i, gpc, tpc;
 
+	nv_wr32(dev, TP_UNIT(0, 0, 0x5c), 1); /* affects TFB offset queries */
+
 	/*
 	 *      TP      ROP UNKVAL(magic_not_rop_nr)
 	 * 450: 4/0/0/0 2        3
@@ -390,7 +416,7 @@
 	}
 
 	nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918);
-	nv_wr32(dev, GPC_BCAST(0x08ac), priv->rop_nr);
+	nv_wr32(dev, GPC_BCAST(0x08ac), nv_rd32(dev, 0x100800));
 }
 
 static void
@@ -700,22 +726,6 @@
 	nv_wr32(dev, 0x400500, 0x00010001);
 }
 
-static void
-nvc0_runk140_isr(struct drm_device *dev)
-{
-	u32 units = nv_rd32(dev, 0x00017c) & 0x1f;
-
-	while (units) {
-		u32 unit = ffs(units) - 1;
-		u32 reg = 0x140000 + unit * 0x2000;
-		u32 st0 = nv_mask(dev, reg + 0x1020, 0, 0);
-		u32 st1 = nv_mask(dev, reg + 0x1420, 0, 0);
-
-		NV_DEBUG(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1);
-		units &= ~(1 << unit);
-	}
-}
-
 static int
 nvc0_graph_create_fw(struct drm_device *dev, const char *fwname,
 		     struct nvc0_graph_fuc *fuc)
@@ -764,7 +774,6 @@
 	}
 
 	nouveau_irq_unregister(dev, 12);
-	nouveau_irq_unregister(dev, 25);
 
 	nouveau_gpuobj_ref(NULL, &priv->unk4188b8);
 	nouveau_gpuobj_ref(NULL, &priv->unk4188b4);
@@ -803,7 +812,6 @@
 
 	NVOBJ_ENGINE_ADD(dev, GR, &priv->base);
 	nouveau_irq_register(dev, 12, nvc0_graph_isr);
-	nouveau_irq_register(dev, 25, nvc0_runk140_isr);
 
 	if (nouveau_ctxfw) {
 		NV_INFO(dev, "PGRAPH: using external firmware\n");
@@ -864,6 +872,9 @@
 	case 0xce: /* 4/4/0/0, 4 */
 		priv->magic_not_rop_nr = 0x03;
 		break;
+	case 0xcf: /* 4/0/0/0, 3 */
+		priv->magic_not_rop_nr = 0x03;
+		break;
 	}
 
 	if (!priv->magic_not_rop_nr) {
@@ -889,5 +900,3 @@
 	nvc0_graph_destroy(dev, NVOBJ_ENGINE_GR);
 	return ret;
 }
-
-/*(DEBLOBBED)*/
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_graph.h linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_graph.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_graph.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_graph.h	2012-01-04 18:55:44.000000000 -0500
@@ -82,6 +82,7 @@
 	case 0xc3:
 	case 0xc4:
 	case 0xce: /* guess, mmio trace shows only 0x9097 state */
+	case 0xcf: /* guess, mmio trace shows only 0x9097 state */
 		return 0x9097;
 	case 0xc1:
 		return 0x9197;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_grctx.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_grctx.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_grctx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_grctx.c	2012-01-04 18:55:44.000000000 -0500
@@ -1678,7 +1678,10 @@
 	nv_wr32(dev, 0x419c04, 0x00000006);
 	nv_wr32(dev, 0x419c08, 0x00000002);
 	nv_wr32(dev, 0x419c20, 0x00000000);
-	nv_wr32(dev, 0x419cb0, 0x00060048); //XXX: 0xce 0x00020048
+	if (chipset == 0xce || chipset == 0xcf)
+		nv_wr32(dev, 0x419cb0, 0x00020048);
+	else
+		nv_wr32(dev, 0x419cb0, 0x00060048);
 	nv_wr32(dev, 0x419ce8, 0x00000000);
 	nv_wr32(dev, 0x419cf4, 0x00000183);
 	nv_wr32(dev, 0x419d20, chipset != 0xc1 ? 0x02180000 : 0x12180000);
@@ -1783,11 +1786,7 @@
 	nv_wr32(dev, 0x40587c, 0x00000000);
 
 	if (1) {
-		const u8 chipset_tp_max[] = { 16, 4, 0, 4, 8, 0, 0, 0,
-					      16, 0, 0, 0, 0, 0, 8, 0 };
-		u8 max = chipset_tp_max[dev_priv->chipset & 0x0f];
-		u8 tpnr[GPC_MAX];
-		u8 data[TP_MAX];
+		u8 tpnr[GPC_MAX], data[TP_MAX];
 
 		memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
 		memset(data, 0x1f, sizeof(data));
@@ -1801,7 +1800,7 @@
 			data[tp] = gpc;
 		}
 
-		for (i = 0; i < max / 4; i++)
+		for (i = 0; i < 4; i++)
 			nv_wr32(dev, 0x4060a8 + (i * 4), ((u32 *)data)[i]);
 	}
 
@@ -1813,6 +1812,7 @@
 		/* calculate first set of magics */
 		memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
 
+		gpc = -1;
 		for (tp = 0; tp < priv->tp_total; tp++) {
 			do {
 				gpc = (gpc + 1) % priv->gpc_nr;
@@ -1862,30 +1862,26 @@
 
 	if (1) {
 		u32 tp_mask = 0, tp_set = 0;
-		u8  tpnr[GPC_MAX];
+		u8  tpnr[GPC_MAX], a, b;
 
 		memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
 		for (gpc = 0; gpc < priv->gpc_nr; gpc++)
 			tp_mask |= ((1 << priv->tp_nr[gpc]) - 1) << (gpc * 8);
 
-		gpc = -1;
-		for (i = 0, gpc = -1; i < 32; i++) {
-			int ltp = i * (priv->tp_total - 1) / 32;
-
-			do {
-				gpc = (gpc + 1) % priv->gpc_nr;
-			} while (!tpnr[gpc]);
-			tp = priv->tp_nr[gpc] - tpnr[gpc]--;
+		for (i = 0, gpc = -1, b = -1; i < 32; i++) {
+			a = (i * (priv->tp_total - 1)) / 32;
+			if (a != b) {
+				b = a;
+				do {
+					gpc = (gpc + 1) % priv->gpc_nr;
+				} while (!tpnr[gpc]);
+				tp = priv->tp_nr[gpc] - tpnr[gpc]--;
 
-			tp_set |= 1 << ((gpc * 8) + tp);
+				tp_set |= 1 << ((gpc * 8) + tp);
+			}
 
-			do {
-				nv_wr32(dev, 0x406800 + (i * 0x20), tp_set);
-				tp_set ^= tp_mask;
-				nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set);
-				tp_set ^= tp_mask;
-			} while (ltp == (++i * (priv->tp_total - 1) / 32));
-			i--;
+			nv_wr32(dev, 0x406800 + (i * 0x20), tp_set);
+			nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set ^ tp_mask);
 		}
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc	2012-01-04 18:55:44.000000000 -0500
@@ -77,6 +77,11 @@
 .b16 nvc0_gpc_mmio_tail
 .b16 nvc0_tpc_mmio_head
 .b16 nvc3_tpc_mmio_tail
+.b8  0xcf 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvcf_tpc_mmio_tail
 .b8  0 0 0 0
 
 // GPC mmio lists
@@ -134,8 +139,9 @@
 nvc0_tpc_mmio_tail:
 mmctx_data(0x000758, 1)
 mmctx_data(0x0002c4, 1)
-mmctx_data(0x0004bc, 1)
 mmctx_data(0x0006e0, 1)
+nvcf_tpc_mmio_tail:
+mmctx_data(0x0004bc, 1)
 nvc3_tpc_mmio_tail:
 mmctx_data(0x000544, 1)
 nvc1_tpc_mmio_tail:
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h	2012-01-04 18:55:44.000000000 -0500
@@ -25,23 +25,26 @@
 	0x00000000,
 	0x00000000,
 	0x000000c0,
-	0x011000b0,
-	0x01640114,
+	0x011c00bc,
+	0x01700120,
 	0x000000c1,
-	0x011400b0,
-	0x01780114,
+	0x012000bc,
+	0x01840120,
 	0x000000c3,
-	0x011000b0,
-	0x01740114,
+	0x011c00bc,
+	0x01800120,
 	0x000000c4,
-	0x011000b0,
-	0x01740114,
+	0x011c00bc,
+	0x01800120,
 	0x000000c8,
-	0x011000b0,
-	0x01640114,
+	0x011c00bc,
+	0x01700120,
 	0x000000ce,
-	0x011000b0,
-	0x01740114,
+	0x011c00bc,
+	0x01800120,
+	0x000000cf,
+	0x011c00bc,
+	0x017c0120,
 	0x00000000,
 	0x00000380,
 	0x14000400,
@@ -90,8 +93,8 @@
 	0x04000750,
 	0x00000758,
 	0x000002c4,
-	0x000004bc,
 	0x000006e0,
+	0x000004bc,
 	0x00000544,
 };
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_grhub.fuc linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_grhub.fuc
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_grhub.fuc	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_grhub.fuc	2012-01-04 18:55:44.000000000 -0500
@@ -56,6 +56,9 @@
 .b8  0xce 0 0 0
 .b16 nvc0_hub_mmio_head
 .b16 nvc0_hub_mmio_tail
+.b8  0xcf 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
 .b8  0 0 0 0
 
 nvc0_hub_mmio_head:
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h	2012-01-04 18:55:44.000000000 -0500
@@ -23,17 +23,19 @@
 	0x00000000,
 	0x00000000,
 	0x000000c0,
-	0x012c0090,
+	0x01340098,
 	0x000000c1,
-	0x01300090,
+	0x01380098,
 	0x000000c3,
-	0x012c0090,
+	0x01340098,
 	0x000000c4,
-	0x012c0090,
+	0x01340098,
 	0x000000c8,
-	0x012c0090,
+	0x01340098,
 	0x000000ce,
-	0x012c0090,
+	0x01340098,
+	0x000000cf,
+	0x01340098,
 	0x00000000,
 	0x0417e91c,
 	0x04400204,
@@ -78,8 +80,6 @@
 	0x00000000,
 	0x00000000,
 	0x00000000,
-	0x00000000,
-	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_pm.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_pm.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_bios.h"
+#include "nouveau_pm.h"
+
+static u32 read_div(struct drm_device *, int, u32, u32);
+static u32 read_pll(struct drm_device *, u32);
+
+static u32
+read_vco(struct drm_device *dev, u32 dsrc)
+{
+	u32 ssrc = nv_rd32(dev, dsrc);
+	if (!(ssrc & 0x00000100))
+		return read_pll(dev, 0x00e800);
+	return read_pll(dev, 0x00e820);
+}
+
+static u32
+read_pll(struct drm_device *dev, u32 pll)
+{
+	u32 ctrl = nv_rd32(dev, pll + 0);
+	u32 coef = nv_rd32(dev, pll + 4);
+	u32 P = (coef & 0x003f0000) >> 16;
+	u32 N = (coef & 0x0000ff00) >> 8;
+	u32 M = (coef & 0x000000ff) >> 0;
+	u32 sclk, doff;
+
+	if (!(ctrl & 0x00000001))
+		return 0;
+
+	switch (pll & 0xfff000) {
+	case 0x00e000:
+		sclk = 27000;
+		P = 1;
+		break;
+	case 0x137000:
+		doff = (pll - 0x137000) / 0x20;
+		sclk = read_div(dev, doff, 0x137120, 0x137140);
+		break;
+	case 0x132000:
+		switch (pll) {
+		case 0x132000:
+			sclk = read_pll(dev, 0x132020);
+			break;
+		case 0x132020:
+			sclk = read_div(dev, 0, 0x137320, 0x137330);
+			break;
+		default:
+			return 0;
+		}
+		break;
+	default:
+		return 0;
+	}
+
+	return sclk * N / M / P;
+}
+
+static u32
+read_div(struct drm_device *dev, int doff, u32 dsrc, u32 dctl)
+{
+	u32 ssrc = nv_rd32(dev, dsrc + (doff * 4));
+	u32 sctl = nv_rd32(dev, dctl + (doff * 4));
+
+	switch (ssrc & 0x00000003) {
+	case 0:
+		if ((ssrc & 0x00030000) != 0x00030000)
+			return 27000;
+		return 108000;
+	case 2:
+		return 100000;
+	case 3:
+		if (sctl & 0x80000000) {
+			u32 sclk = read_vco(dev, dsrc + (doff * 4));
+			u32 sdiv = (sctl & 0x0000003f) + 2;
+			return (sclk * 2) / sdiv;
+		}
+
+		return read_vco(dev, dsrc + (doff * 4));
+	default:
+		return 0;
+	}
+}
+
+static u32
+read_mem(struct drm_device *dev)
+{
+	u32 ssel = nv_rd32(dev, 0x1373f0);
+	if (ssel & 0x00000001)
+		return read_div(dev, 0, 0x137300, 0x137310);
+	return read_pll(dev, 0x132000);
+}
+
+static u32
+read_clk(struct drm_device *dev, int clk)
+{
+	u32 sctl = nv_rd32(dev, 0x137250 + (clk * 4));
+	u32 ssel = nv_rd32(dev, 0x137100);
+	u32 sclk, sdiv;
+
+	if (ssel & (1 << clk)) {
+		if (clk < 7)
+			sclk = read_pll(dev, 0x137000 + (clk * 0x20));
+		else
+			sclk = read_pll(dev, 0x1370e0);
+		sdiv = ((sctl & 0x00003f00) >> 8) + 2;
+	} else {
+		sclk = read_div(dev, clk, 0x137160, 0x1371d0);
+		sdiv = ((sctl & 0x0000003f) >> 0) + 2;
+	}
+
+	if (sctl & 0x80000000)
+		return (sclk * 2) / sdiv;
+	return sclk;
+}
+
+int
+nvc0_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
+{
+	perflvl->shader = read_clk(dev, 0x00);
+	perflvl->core   = perflvl->shader / 2;
+	perflvl->memory = read_mem(dev);
+	perflvl->rop    = read_clk(dev, 0x01);
+	perflvl->hub07  = read_clk(dev, 0x02);
+	perflvl->hub06  = read_clk(dev, 0x07);
+	perflvl->hub01  = read_clk(dev, 0x08);
+	perflvl->copy   = read_clk(dev, 0x09);
+	perflvl->daemon = read_clk(dev, 0x0c);
+	perflvl->vdec   = read_clk(dev, 0x0e);
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_vram.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_vram.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvc0_vram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvc0_vram.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,7 @@
 	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, 3, 1, 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
@@ -61,7 +61,7 @@
 	      u32 type, struct nouveau_mem **pmem)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_mm *mm = dev_priv->engine.vram.mm;
+	struct nouveau_mm *mm = &dev_priv->engine.vram.mm;
 	struct nouveau_mm_node *r;
 	struct nouveau_mem *mem;
 	int ret;
@@ -106,12 +106,54 @@
 	struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
 	const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
 	const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
-	u32 length;
+	u32 parts = nv_rd32(dev, 0x121c74);
+	u32 bsize = nv_rd32(dev, 0x10f20c);
+	u32 offset, length;
+	bool uniform = true;
+	int ret, part;
 
-	dev_priv->vram_size  = nv_rd32(dev, 0x10f20c) << 20;
-	dev_priv->vram_size *= nv_rd32(dev, 0x121c74);
+	NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800));
+	NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize);
 
-	length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
+	/* read amount of vram attached to each memory controller */
+	part = 0;
+	while (parts) {
+		u32 psize = nv_rd32(dev, 0x11020c + (part++ * 0x1000));
+		if (psize == 0)
+			continue;
+		parts--;
 
-	return nouveau_mm_init(&vram->mm, rsvd_head, length, 1);
+		if (psize != bsize) {
+			if (psize < bsize)
+				bsize = psize;
+			uniform = false;
+		}
+
+		NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize);
+		dev_priv->vram_size += (u64)psize << 20;
+	}
+
+	/* if all controllers have the same amount attached, there's no holes */
+	if (uniform) {
+		offset = rsvd_head;
+		length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
+		return nouveau_mm_init(&vram->mm, offset, length, 1);
+	}
+
+	/* otherwise, address lowest common amount from 0GiB */
+	ret = nouveau_mm_init(&vram->mm, rsvd_head, (bsize << 8) * parts, 1);
+	if (ret)
+		return ret;
+
+	/* and the rest starting from (8GiB + common_size) */
+	offset = (0x0200000000ULL >> 12) + (bsize << 8);
+	length = (dev_priv->vram_size >> 12) - (bsize << 8) - rsvd_tail;
+
+	ret = nouveau_mm_init(&vram->mm, offset, length, 0);
+	if (ret) {
+		nouveau_mm_fini(&vram->mm);
+		return ret;
+	}
+
+	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvd0_display.c linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvd0_display.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/nouveau/nvd0_display.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/nouveau/nvd0_display.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1473 @@
+/*
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <linux/dma-mapping.h>
+
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+
+#include "nouveau_drv.h"
+#include "nouveau_connector.h"
+#include "nouveau_encoder.h"
+#include "nouveau_crtc.h"
+#include "nouveau_dma.h"
+#include "nouveau_fb.h"
+#include "nv50_display.h"
+
+struct nvd0_display {
+	struct nouveau_gpuobj *mem;
+	struct {
+		dma_addr_t handle;
+		u32 *ptr;
+	} evo[1];
+
+	struct tasklet_struct tasklet;
+	u32 modeset;
+};
+
+static struct nvd0_display *
+nvd0_display(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	return dev_priv->engine.display.priv;
+}
+
+static inline int
+evo_icmd(struct drm_device *dev, int id, u32 mthd, u32 data)
+{
+	int ret = 0;
+	nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000001);
+	nv_wr32(dev, 0x610704 + (id * 0x10), data);
+	nv_mask(dev, 0x610704 + (id * 0x10), 0x80000ffc, 0x80000000 | mthd);
+	if (!nv_wait(dev, 0x610704 + (id * 0x10), 0x80000000, 0x00000000))
+		ret = -EBUSY;
+	nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000000);
+	return ret;
+}
+
+static u32 *
+evo_wait(struct drm_device *dev, int id, int nr)
+{
+	struct nvd0_display *disp = nvd0_display(dev);
+	u32 put = nv_rd32(dev, 0x640000 + (id * 0x1000)) / 4;
+
+	if (put + nr >= (PAGE_SIZE / 4)) {
+		disp->evo[id].ptr[put] = 0x20000000;
+
+		nv_wr32(dev, 0x640000 + (id * 0x1000), 0x00000000);
+		if (!nv_wait(dev, 0x640004 + (id * 0x1000), ~0, 0x00000000)) {
+			NV_ERROR(dev, "evo %d dma stalled\n", id);
+			return NULL;
+		}
+
+		put = 0;
+	}
+
+	return disp->evo[id].ptr + put;
+}
+
+static void
+evo_kick(u32 *push, struct drm_device *dev, int id)
+{
+	struct nvd0_display *disp = nvd0_display(dev);
+	nv_wr32(dev, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2);
+}
+
+#define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m))
+#define evo_data(p,d)   *((p)++) = (d)
+
+static struct drm_crtc *
+nvd0_display_crtc_get(struct drm_encoder *encoder)
+{
+	return nouveau_encoder(encoder)->crtc;
+}
+
+/******************************************************************************
+ * CRTC
+ *****************************************************************************/
+static int
+nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update)
+{
+	struct drm_device *dev = nv_crtc->base.dev;
+	u32 *push, mode;
+
+	mode = 0x00000000;
+	if (on) {
+		/* 0x11: 6bpc dynamic 2x2
+		 * 0x13: 8bpc dynamic 2x2
+		 * 0x19: 6bpc static 2x2
+		 * 0x1b: 8bpc static 2x2
+		 * 0x21: 6bpc temporal
+		 * 0x23: 8bpc temporal
+		 */
+		mode = 0x00000011;
+	}
+
+	push = evo_wait(dev, 0, 4);
+	if (push) {
+		evo_mthd(push, 0x0490 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, mode);
+		if (update) {
+			evo_mthd(push, 0x0080, 1);
+			evo_data(push, 0x00000000);
+		}
+		evo_kick(push, dev, 0);
+	}
+
+	return 0;
+}
+
+static int
+nvd0_crtc_set_scale(struct nouveau_crtc *nv_crtc, int type, bool update)
+{
+	struct drm_display_mode *mode = &nv_crtc->base.mode;
+	struct drm_device *dev = nv_crtc->base.dev;
+	struct nouveau_connector *nv_connector;
+	u32 *push, outX, outY;
+
+	outX = mode->hdisplay;
+	outY = mode->vdisplay;
+
+	nv_connector = nouveau_crtc_connector_get(nv_crtc);
+	if (nv_connector && nv_connector->native_mode) {
+		struct drm_display_mode *native = nv_connector->native_mode;
+		u32 xratio = (native->hdisplay << 19) / mode->hdisplay;
+		u32 yratio = (native->vdisplay << 19) / mode->vdisplay;
+
+		switch (type) {
+		case DRM_MODE_SCALE_ASPECT:
+			if (xratio > yratio) {
+				outX = (mode->hdisplay * yratio) >> 19;
+				outY = (mode->vdisplay * yratio) >> 19;
+			} else {
+				outX = (mode->hdisplay * xratio) >> 19;
+				outY = (mode->vdisplay * xratio) >> 19;
+			}
+			break;
+		case DRM_MODE_SCALE_FULLSCREEN:
+			outX = native->hdisplay;
+			outY = native->vdisplay;
+			break;
+		default:
+			break;
+		}
+	}
+
+	push = evo_wait(dev, 0, 16);
+	if (push) {
+		evo_mthd(push, 0x04c0 + (nv_crtc->index * 0x300), 3);
+		evo_data(push, (outY << 16) | outX);
+		evo_data(push, (outY << 16) | outX);
+		evo_data(push, (outY << 16) | outX);
+		evo_mthd(push, 0x0494 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, 0x00000000);
+		evo_mthd(push, 0x04b8 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, (mode->vdisplay << 16) | mode->hdisplay);
+		if (update) {
+			evo_mthd(push, 0x0080, 1);
+			evo_data(push, 0x00000000);
+		}
+		evo_kick(push, dev, 0);
+	}
+
+	return 0;
+}
+
+static int
+nvd0_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb,
+		    int x, int y, bool update)
+{
+	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(fb);
+	u32 *push;
+
+	push = evo_wait(fb->dev, 0, 16);
+	if (push) {
+		evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, nvfb->nvbo->bo.offset >> 8);
+		evo_mthd(push, 0x0468 + (nv_crtc->index * 0x300), 4);
+		evo_data(push, (fb->height << 16) | fb->width);
+		evo_data(push, nvfb->r_pitch);
+		evo_data(push, nvfb->r_format);
+		evo_data(push, nvfb->r_dma);
+		evo_mthd(push, 0x04b0 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, (y << 16) | x);
+		if (update) {
+			evo_mthd(push, 0x0080, 1);
+			evo_data(push, 0x00000000);
+		}
+		evo_kick(push, fb->dev, 0);
+	}
+
+	nv_crtc->fb.tile_flags = nvfb->r_dma;
+	return 0;
+}
+
+static void
+nvd0_crtc_cursor_show(struct nouveau_crtc *nv_crtc, bool show, bool update)
+{
+	struct drm_device *dev = nv_crtc->base.dev;
+	u32 *push = evo_wait(dev, 0, 16);
+	if (push) {
+		if (show) {
+			evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2);
+			evo_data(push, 0x85000000);
+			evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
+			evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
+			evo_data(push, NvEvoVRAM);
+		} else {
+			evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 1);
+			evo_data(push, 0x05000000);
+			evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
+			evo_data(push, 0x00000000);
+		}
+
+		if (update) {
+			evo_mthd(push, 0x0080, 1);
+			evo_data(push, 0x00000000);
+		}
+
+		evo_kick(push, dev, 0);
+	}
+}
+
+static void
+nvd0_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+}
+
+static void
+nvd0_crtc_prepare(struct drm_crtc *crtc)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	u32 *push;
+
+	push = evo_wait(crtc->dev, 0, 2);
+	if (push) {
+		evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, 0x00000000);
+		evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, 0x03000000);
+		evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
+		evo_data(push, 0x00000000);
+		evo_kick(push, crtc->dev, 0);
+	}
+
+	nvd0_crtc_cursor_show(nv_crtc, false, false);
+}
+
+static void
+nvd0_crtc_commit(struct drm_crtc *crtc)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	u32 *push;
+
+	push = evo_wait(crtc->dev, 0, 32);
+	if (push) {
+		evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, nv_crtc->fb.tile_flags);
+		evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4);
+		evo_data(push, 0x83000000);
+		evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
+		evo_data(push, 0x00000000);
+		evo_data(push, 0x00000000);
+		evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
+		evo_data(push, NvEvoVRAM);
+		evo_mthd(push, 0x0430 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, 0xffffff00);
+		evo_kick(push, crtc->dev, 0);
+	}
+
+	nvd0_crtc_cursor_show(nv_crtc, nv_crtc->cursor.visible, true);
+}
+
+static bool
+nvd0_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode,
+		     struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static int
+nvd0_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
+{
+	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
+	int ret;
+
+	ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM);
+	if (ret)
+		return ret;
+
+	if (old_fb) {
+		nvfb = nouveau_framebuffer(old_fb);
+		nouveau_bo_unpin(nvfb->nvbo);
+	}
+
+	return 0;
+}
+
+static int
+nvd0_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
+		   struct drm_display_mode *mode, int x, int y,
+		   struct drm_framebuffer *old_fb)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct nouveau_connector *nv_connector;
+	u32 htotal = mode->htotal;
+	u32 vtotal = mode->vtotal;
+	u32 hsyncw = mode->hsync_end - mode->hsync_start - 1;
+	u32 vsyncw = mode->vsync_end - mode->vsync_start - 1;
+	u32 hfrntp = mode->hsync_start - mode->hdisplay;
+	u32 vfrntp = mode->vsync_start - mode->vdisplay;
+	u32 hbackp = mode->htotal - mode->hsync_end;
+	u32 vbackp = mode->vtotal - mode->vsync_end;
+	u32 hss2be = hsyncw + hbackp;
+	u32 vss2be = vsyncw + vbackp;
+	u32 hss2de = htotal - hfrntp;
+	u32 vss2de = vtotal - vfrntp;
+	u32 syncs, *push;
+	int ret;
+
+	syncs = 0x00000001;
+	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+		syncs |= 0x00000008;
+	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+		syncs |= 0x00000010;
+
+	ret = nvd0_crtc_swap_fbs(crtc, old_fb);
+	if (ret)
+		return ret;
+
+	push = evo_wait(crtc->dev, 0, 64);
+	if (push) {
+		evo_mthd(push, 0x0410 + (nv_crtc->index * 0x300), 5);
+		evo_data(push, 0x00000000);
+		evo_data(push, (vtotal << 16) | htotal);
+		evo_data(push, (vsyncw << 16) | hsyncw);
+		evo_data(push, (vss2be << 16) | hss2be);
+		evo_data(push, (vss2de << 16) | hss2de);
+		evo_mthd(push, 0x042c + (nv_crtc->index * 0x300), 1);
+		evo_data(push, 0x00000000); /* ??? */
+		evo_mthd(push, 0x0450 + (nv_crtc->index * 0x300), 3);
+		evo_data(push, mode->clock * 1000);
+		evo_data(push, 0x00200000); /* ??? */
+		evo_data(push, mode->clock * 1000);
+		evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 1);
+		evo_data(push, syncs);
+		evo_kick(push, crtc->dev, 0);
+	}
+
+	nv_connector = nouveau_crtc_connector_get(nv_crtc);
+	nvd0_crtc_set_dither(nv_crtc, nv_connector->use_dithering, false);
+	nvd0_crtc_set_scale(nv_crtc, nv_connector->scaling_mode, false);
+	nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, false);
+	return 0;
+}
+
+static int
+nvd0_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+			struct drm_framebuffer *old_fb)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	int ret;
+
+	if (!crtc->fb) {
+		NV_DEBUG_KMS(crtc->dev, "No FB bound\n");
+		return 0;
+	}
+
+	ret = nvd0_crtc_swap_fbs(crtc, old_fb);
+	if (ret)
+		return ret;
+
+	nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, true);
+	return 0;
+}
+
+static int
+nvd0_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
+			       struct drm_framebuffer *fb, int x, int y,
+			       enum mode_set_atomic state)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	nvd0_crtc_set_image(nv_crtc, fb, x, y, true);
+	return 0;
+}
+
+static void
+nvd0_crtc_lut_load(struct drm_crtc *crtc)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo);
+	int i;
+
+	for (i = 0; i < 256; i++) {
+		writew(0x6000 + (nv_crtc->lut.r[i] >> 2), lut + (i * 0x20) + 0);
+		writew(0x6000 + (nv_crtc->lut.g[i] >> 2), lut + (i * 0x20) + 2);
+		writew(0x6000 + (nv_crtc->lut.b[i] >> 2), lut + (i * 0x20) + 4);
+	}
+}
+
+static int
+nvd0_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
+		     uint32_t handle, uint32_t width, uint32_t height)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct drm_gem_object *gem;
+	struct nouveau_bo *nvbo;
+	bool visible = (handle != 0);
+	int i, ret = 0;
+
+	if (visible) {
+		if (width != 64 || height != 64)
+			return -EINVAL;
+
+		gem = drm_gem_object_lookup(dev, file_priv, handle);
+		if (unlikely(!gem))
+			return -ENOENT;
+		nvbo = nouveau_gem_object(gem);
+
+		ret = nouveau_bo_map(nvbo);
+		if (ret == 0) {
+			for (i = 0; i < 64 * 64; i++) {
+				u32 v = nouveau_bo_rd32(nvbo, i);
+				nouveau_bo_wr32(nv_crtc->cursor.nvbo, i, v);
+			}
+			nouveau_bo_unmap(nvbo);
+		}
+
+		drm_gem_object_unreference_unlocked(gem);
+	}
+
+	if (visible != nv_crtc->cursor.visible) {
+		nvd0_crtc_cursor_show(nv_crtc, visible, true);
+		nv_crtc->cursor.visible = visible;
+	}
+
+	return ret;
+}
+
+static int
+nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	const u32 data = (y << 16) | x;
+
+	nv_wr32(crtc->dev, 0x64d084 + (nv_crtc->index * 0x1000), data);
+	nv_wr32(crtc->dev, 0x64d080 + (nv_crtc->index * 0x1000), 0x00000000);
+	return 0;
+}
+
+static void
+nvd0_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
+		    uint32_t start, uint32_t size)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	u32 end = max(start + size, (u32)256);
+	u32 i;
+
+	for (i = start; i < end; i++) {
+		nv_crtc->lut.r[i] = r[i];
+		nv_crtc->lut.g[i] = g[i];
+		nv_crtc->lut.b[i] = b[i];
+	}
+
+	nvd0_crtc_lut_load(crtc);
+}
+
+static void
+nvd0_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	nouveau_bo_unmap(nv_crtc->cursor.nvbo);
+	nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
+	nouveau_bo_unmap(nv_crtc->lut.nvbo);
+	nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
+	drm_crtc_cleanup(crtc);
+	kfree(crtc);
+}
+
+static const struct drm_crtc_helper_funcs nvd0_crtc_hfunc = {
+	.dpms = nvd0_crtc_dpms,
+	.prepare = nvd0_crtc_prepare,
+	.commit = nvd0_crtc_commit,
+	.mode_fixup = nvd0_crtc_mode_fixup,
+	.mode_set = nvd0_crtc_mode_set,
+	.mode_set_base = nvd0_crtc_mode_set_base,
+	.mode_set_base_atomic = nvd0_crtc_mode_set_base_atomic,
+	.load_lut = nvd0_crtc_lut_load,
+};
+
+static const struct drm_crtc_funcs nvd0_crtc_func = {
+	.cursor_set = nvd0_crtc_cursor_set,
+	.cursor_move = nvd0_crtc_cursor_move,
+	.gamma_set = nvd0_crtc_gamma_set,
+	.set_config = drm_crtc_helper_set_config,
+	.destroy = nvd0_crtc_destroy,
+};
+
+static void
+nvd0_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
+{
+}
+
+static void
+nvd0_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset)
+{
+}
+
+static int
+nvd0_crtc_create(struct drm_device *dev, int index)
+{
+	struct nouveau_crtc *nv_crtc;
+	struct drm_crtc *crtc;
+	int ret, i;
+
+	nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL);
+	if (!nv_crtc)
+		return -ENOMEM;
+
+	nv_crtc->index = index;
+	nv_crtc->set_dither = nvd0_crtc_set_dither;
+	nv_crtc->set_scale = nvd0_crtc_set_scale;
+	nv_crtc->cursor.set_offset = nvd0_cursor_set_offset;
+	nv_crtc->cursor.set_pos = nvd0_cursor_set_pos;
+	for (i = 0; i < 256; i++) {
+		nv_crtc->lut.r[i] = i << 8;
+		nv_crtc->lut.g[i] = i << 8;
+		nv_crtc->lut.b[i] = i << 8;
+	}
+
+	crtc = &nv_crtc->base;
+	drm_crtc_init(dev, crtc, &nvd0_crtc_func);
+	drm_crtc_helper_add(crtc, &nvd0_crtc_hfunc);
+	drm_mode_crtc_set_gamma_size(crtc, 256);
+
+	ret = nouveau_bo_new(dev, 64 * 64 * 4, 0x100, TTM_PL_FLAG_VRAM,
+			     0, 0x0000, &nv_crtc->cursor.nvbo);
+	if (!ret) {
+		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
+		if (!ret)
+			ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
+		if (ret)
+			nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
+	}
+
+	if (ret)
+		goto out;
+
+	ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM,
+			     0, 0x0000, &nv_crtc->lut.nvbo);
+	if (!ret) {
+		ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM);
+		if (!ret)
+			ret = nouveau_bo_map(nv_crtc->lut.nvbo);
+		if (ret)
+			nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
+	}
+
+	if (ret)
+		goto out;
+
+	nvd0_crtc_lut_load(crtc);
+
+out:
+	if (ret)
+		nvd0_crtc_destroy(crtc);
+	return ret;
+}
+
+/******************************************************************************
+ * DAC
+ *****************************************************************************/
+static void
+nvd0_dac_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	int or = nv_encoder->or;
+	u32 dpms_ctrl;
+
+	dpms_ctrl = 0x80000000;
+	if (mode == DRM_MODE_DPMS_STANDBY || mode == DRM_MODE_DPMS_OFF)
+		dpms_ctrl |= 0x00000001;
+	if (mode == DRM_MODE_DPMS_SUSPEND || mode == DRM_MODE_DPMS_OFF)
+		dpms_ctrl |= 0x00000004;
+
+	nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000);
+	nv_mask(dev, 0x61a004 + (or * 0x0800), 0xc000007f, dpms_ctrl);
+	nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000);
+}
+
+static bool
+nvd0_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
+		    struct drm_display_mode *adjusted_mode)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nouveau_connector *nv_connector;
+
+	nv_connector = nouveau_encoder_connector_get(nv_encoder);
+	if (nv_connector && nv_connector->native_mode) {
+		if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) {
+			int id = adjusted_mode->base.id;
+			*adjusted_mode = *nv_connector->native_mode;
+			adjusted_mode->base.id = id;
+		}
+	}
+
+	return true;
+}
+
+static void
+nvd0_dac_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void
+nvd0_dac_commit(struct drm_encoder *encoder)
+{
+}
+
+static void
+nvd0_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
+		  struct drm_display_mode *adjusted_mode)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+	u32 *push;
+
+	nvd0_dac_dpms(encoder, DRM_MODE_DPMS_ON);
+
+	push = evo_wait(encoder->dev, 0, 4);
+	if (push) {
+		evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 2);
+		evo_data(push, 1 << nv_crtc->index);
+		evo_data(push, 0x00ff);
+		evo_kick(push, encoder->dev, 0);
+	}
+
+	nv_encoder->crtc = encoder->crtc;
+}
+
+static void
+nvd0_dac_disconnect(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	u32 *push;
+
+	if (nv_encoder->crtc) {
+		nvd0_crtc_prepare(nv_encoder->crtc);
+
+		push = evo_wait(dev, 0, 4);
+		if (push) {
+			evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 1);
+			evo_data(push, 0x00000000);
+			evo_mthd(push, 0x0080, 1);
+			evo_data(push, 0x00000000);
+			evo_kick(push, dev, 0);
+		}
+
+		nv_encoder->crtc = NULL;
+	}
+}
+
+static enum drm_connector_status
+nvd0_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+	enum drm_connector_status status = connector_status_disconnected;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	int or = nv_encoder->or;
+	u32 load;
+
+	nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00100000);
+	udelay(9500);
+	nv_wr32(dev, 0x61a00c + (or * 0x800), 0x80000000);
+
+	load = nv_rd32(dev, 0x61a00c + (or * 0x800));
+	if ((load & 0x38000000) == 0x38000000)
+		status = connector_status_connected;
+
+	nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00000000);
+	return status;
+}
+
+static void
+nvd0_dac_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+	kfree(encoder);
+}
+
+static const struct drm_encoder_helper_funcs nvd0_dac_hfunc = {
+	.dpms = nvd0_dac_dpms,
+	.mode_fixup = nvd0_dac_mode_fixup,
+	.prepare = nvd0_dac_prepare,
+	.commit = nvd0_dac_commit,
+	.mode_set = nvd0_dac_mode_set,
+	.disable = nvd0_dac_disconnect,
+	.get_crtc = nvd0_display_crtc_get,
+	.detect = nvd0_dac_detect
+};
+
+static const struct drm_encoder_funcs nvd0_dac_func = {
+	.destroy = nvd0_dac_destroy,
+};
+
+static int
+nvd0_dac_create(struct drm_connector *connector, struct dcb_entry *dcbe)
+{
+	struct drm_device *dev = connector->dev;
+	struct nouveau_encoder *nv_encoder;
+	struct drm_encoder *encoder;
+
+	nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
+	if (!nv_encoder)
+		return -ENOMEM;
+	nv_encoder->dcb = dcbe;
+	nv_encoder->or = ffs(dcbe->or) - 1;
+
+	encoder = to_drm_encoder(nv_encoder);
+	encoder->possible_crtcs = dcbe->heads;
+	encoder->possible_clones = 0;
+	drm_encoder_init(dev, encoder, &nvd0_dac_func, DRM_MODE_ENCODER_DAC);
+	drm_encoder_helper_add(encoder, &nvd0_dac_hfunc);
+
+	drm_mode_connector_attach_encoder(connector, encoder);
+	return 0;
+}
+
+/******************************************************************************
+ * SOR
+ *****************************************************************************/
+static void
+nvd0_sor_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct drm_encoder *partner;
+	int or = nv_encoder->or;
+	u32 dpms_ctrl;
+
+	nv_encoder->last_dpms = mode;
+
+	list_for_each_entry(partner, &dev->mode_config.encoder_list, head) {
+		struct nouveau_encoder *nv_partner = nouveau_encoder(partner);
+
+		if (partner->encoder_type != DRM_MODE_ENCODER_TMDS)
+			continue;
+
+		if (nv_partner != nv_encoder &&
+		    nv_partner->dcb->or == nv_encoder->dcb->or) {
+			if (nv_partner->last_dpms == DRM_MODE_DPMS_ON)
+				return;
+			break;
+		}
+	}
+
+	dpms_ctrl  = (mode == DRM_MODE_DPMS_ON);
+	dpms_ctrl |= 0x80000000;
+
+	nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000);
+	nv_mask(dev, 0x61c004 + (or * 0x0800), 0x80000001, dpms_ctrl);
+	nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000);
+	nv_wait(dev, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000);
+}
+
+static bool
+nvd0_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
+		    struct drm_display_mode *adjusted_mode)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nouveau_connector *nv_connector;
+
+	nv_connector = nouveau_encoder_connector_get(nv_encoder);
+	if (nv_connector && nv_connector->native_mode) {
+		if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) {
+			int id = adjusted_mode->base.id;
+			*adjusted_mode = *nv_connector->native_mode;
+			adjusted_mode->base.id = id;
+		}
+	}
+
+	return true;
+}
+
+static void
+nvd0_sor_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void
+nvd0_sor_commit(struct drm_encoder *encoder)
+{
+}
+
+static void
+nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
+		  struct drm_display_mode *mode)
+{
+	struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+	struct nouveau_connector *nv_connector;
+	struct nvbios *bios = &dev_priv->vbios;
+	u32 mode_ctrl = (1 << nv_crtc->index);
+	u32 *push, or_config;
+
+	nv_connector = nouveau_encoder_connector_get(nv_encoder);
+	switch (nv_encoder->dcb->type) {
+	case OUTPUT_TMDS:
+		if (nv_encoder->dcb->sorconf.link & 1) {
+			if (mode->clock < 165000)
+				mode_ctrl |= 0x00000100;
+			else
+				mode_ctrl |= 0x00000500;
+		} else {
+			mode_ctrl |= 0x00000200;
+		}
+
+		or_config = (mode_ctrl & 0x00000f00) >> 8;
+		if (mode->clock >= 165000)
+			or_config |= 0x0100;
+		break;
+	case OUTPUT_LVDS:
+		or_config = (mode_ctrl & 0x00000f00) >> 8;
+		if (bios->fp_no_ddc) {
+			if (bios->fp.dual_link)
+				or_config |= 0x0100;
+			if (bios->fp.if_is_24bit)
+				or_config |= 0x0200;
+		} else {
+			if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) {
+				if (((u8 *)nv_connector->edid)[121] == 2)
+					or_config |= 0x0100;
+			} else
+			if (mode->clock >= bios->fp.duallink_transition_clk) {
+				or_config |= 0x0100;
+			}
+
+			if (or_config & 0x0100) {
+				if (bios->fp.strapless_is_24bit & 2)
+					or_config |= 0x0200;
+			} else {
+				if (bios->fp.strapless_is_24bit & 1)
+					or_config |= 0x0200;
+			}
+
+			if (nv_connector->base.display_info.bpc == 8)
+				or_config |= 0x0200;
+
+		}
+		break;
+	default:
+		BUG_ON(1);
+		break;
+	}
+
+	nvd0_sor_dpms(encoder, DRM_MODE_DPMS_ON);
+
+	push = evo_wait(encoder->dev, 0, 4);
+	if (push) {
+		evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 2);
+		evo_data(push, mode_ctrl);
+		evo_data(push, or_config);
+		evo_kick(push, encoder->dev, 0);
+	}
+
+	nv_encoder->crtc = encoder->crtc;
+}
+
+static void
+nvd0_sor_disconnect(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	u32 *push;
+
+	if (nv_encoder->crtc) {
+		nvd0_crtc_prepare(nv_encoder->crtc);
+
+		push = evo_wait(dev, 0, 4);
+		if (push) {
+			evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1);
+			evo_data(push, 0x00000000);
+			evo_mthd(push, 0x0080, 1);
+			evo_data(push, 0x00000000);
+			evo_kick(push, dev, 0);
+		}
+
+		nv_encoder->crtc = NULL;
+		nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
+	}
+}
+
+static void
+nvd0_sor_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+	kfree(encoder);
+}
+
+static const struct drm_encoder_helper_funcs nvd0_sor_hfunc = {
+	.dpms = nvd0_sor_dpms,
+	.mode_fixup = nvd0_sor_mode_fixup,
+	.prepare = nvd0_sor_prepare,
+	.commit = nvd0_sor_commit,
+	.mode_set = nvd0_sor_mode_set,
+	.disable = nvd0_sor_disconnect,
+	.get_crtc = nvd0_display_crtc_get,
+};
+
+static const struct drm_encoder_funcs nvd0_sor_func = {
+	.destroy = nvd0_sor_destroy,
+};
+
+static int
+nvd0_sor_create(struct drm_connector *connector, struct dcb_entry *dcbe)
+{
+	struct drm_device *dev = connector->dev;
+	struct nouveau_encoder *nv_encoder;
+	struct drm_encoder *encoder;
+
+	nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
+	if (!nv_encoder)
+		return -ENOMEM;
+	nv_encoder->dcb = dcbe;
+	nv_encoder->or = ffs(dcbe->or) - 1;
+	nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
+
+	encoder = to_drm_encoder(nv_encoder);
+	encoder->possible_crtcs = dcbe->heads;
+	encoder->possible_clones = 0;
+	drm_encoder_init(dev, encoder, &nvd0_sor_func, DRM_MODE_ENCODER_TMDS);
+	drm_encoder_helper_add(encoder, &nvd0_sor_hfunc);
+
+	drm_mode_connector_attach_encoder(connector, encoder);
+	return 0;
+}
+
+/******************************************************************************
+ * IRQ
+ *****************************************************************************/
+static struct dcb_entry *
+lookup_dcb(struct drm_device *dev, int id, u32 mc)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int type, or, i;
+
+	if (id < 4) {
+		type = OUTPUT_ANALOG;
+		or   = id;
+	} else {
+		switch (mc & 0x00000f00) {
+		case 0x00000000: type = OUTPUT_LVDS; break;
+		case 0x00000100: type = OUTPUT_TMDS; break;
+		case 0x00000200: type = OUTPUT_TMDS; break;
+		case 0x00000500: type = OUTPUT_TMDS; break;
+		default:
+			NV_ERROR(dev, "PDISP: unknown SOR mc 0x%08x\n", mc);
+			return NULL;
+		}
+
+		or = id - 4;
+	}
+
+	for (i = 0; i < dev_priv->vbios.dcb.entries; i++) {
+		struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i];
+		if (dcb->type == type && (dcb->or & (1 << or)))
+			return dcb;
+	}
+
+	NV_ERROR(dev, "PDISP: DCB for %d/0x%08x not found\n", id, mc);
+	return NULL;
+}
+
+static void
+nvd0_display_unk1_handler(struct drm_device *dev, u32 crtc, u32 mask)
+{
+	struct dcb_entry *dcb;
+	int i;
+
+	for (i = 0; mask && i < 8; i++) {
+		u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20));
+		if (!(mcc & (1 << crtc)))
+			continue;
+
+		dcb = lookup_dcb(dev, i, mcc);
+		if (!dcb)
+			continue;
+
+		nouveau_bios_run_display_table(dev, 0x0000, -1, dcb, crtc);
+	}
+
+	nv_wr32(dev, 0x6101d4, 0x00000000);
+	nv_wr32(dev, 0x6109d4, 0x00000000);
+	nv_wr32(dev, 0x6101d0, 0x80000000);
+}
+
+static void
+nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask)
+{
+	struct dcb_entry *dcb;
+	u32 or, tmp, pclk;
+	int i;
+
+	for (i = 0; mask && i < 8; i++) {
+		u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20));
+		if (!(mcc & (1 << crtc)))
+			continue;
+
+		dcb = lookup_dcb(dev, i, mcc);
+		if (!dcb)
+			continue;
+
+		nouveau_bios_run_display_table(dev, 0x0000, -2, dcb, crtc);
+	}
+
+	pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000;
+	if (mask & 0x00010000) {
+		nv50_crtc_set_clock(dev, crtc, pclk);
+	}
+
+	for (i = 0; mask && i < 8; i++) {
+		u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20));
+		u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20));
+		if (!(mcp & (1 << crtc)))
+			continue;
+
+		dcb = lookup_dcb(dev, i, mcp);
+		if (!dcb)
+			continue;
+		or = ffs(dcb->or) - 1;
+
+		nouveau_bios_run_display_table(dev, cfg, pclk, dcb, crtc);
+
+		nv_wr32(dev, 0x612200 + (crtc * 0x800), 0x00000000);
+		switch (dcb->type) {
+		case OUTPUT_ANALOG:
+			nv_wr32(dev, 0x612280 + (or * 0x800), 0x00000000);
+			break;
+		case OUTPUT_TMDS:
+		case OUTPUT_LVDS:
+			if (cfg & 0x00000100)
+				tmp = 0x00000101;
+			else
+				tmp = 0x00000000;
+
+			nv_mask(dev, 0x612300 + (or * 0x800), 0x00000707, tmp);
+			break;
+		default:
+			break;
+		}
+
+		break;
+	}
+
+	nv_wr32(dev, 0x6101d4, 0x00000000);
+	nv_wr32(dev, 0x6109d4, 0x00000000);
+	nv_wr32(dev, 0x6101d0, 0x80000000);
+}
+
+static void
+nvd0_display_unk4_handler(struct drm_device *dev, u32 crtc, u32 mask)
+{
+	struct dcb_entry *dcb;
+	int pclk, i;
+
+	pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000;
+
+	for (i = 0; mask && i < 8; i++) {
+		u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20));
+		u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20));
+		if (!(mcp & (1 << crtc)))
+			continue;
+
+		dcb = lookup_dcb(dev, i, mcp);
+		if (!dcb)
+			continue;
+
+		nouveau_bios_run_display_table(dev, cfg, -pclk, dcb, crtc);
+	}
+
+	nv_wr32(dev, 0x6101d4, 0x00000000);
+	nv_wr32(dev, 0x6109d4, 0x00000000);
+	nv_wr32(dev, 0x6101d0, 0x80000000);
+}
+
+static void
+nvd0_display_bh(unsigned long data)
+{
+	struct drm_device *dev = (struct drm_device *)data;
+	struct nvd0_display *disp = nvd0_display(dev);
+	u32 mask, crtc;
+	int i;
+
+	if (drm_debug & (DRM_UT_DRIVER | DRM_UT_KMS)) {
+		NV_INFO(dev, "PDISP: modeset req %d\n", disp->modeset);
+		NV_INFO(dev, " STAT: 0x%08x 0x%08x 0x%08x\n",
+			 nv_rd32(dev, 0x6101d0),
+			 nv_rd32(dev, 0x6101d4), nv_rd32(dev, 0x6109d4));
+		for (i = 0; i < 8; i++) {
+			NV_INFO(dev, " %s%d: 0x%08x 0x%08x\n",
+				i < 4 ? "DAC" : "SOR", i,
+				nv_rd32(dev, 0x640180 + (i * 0x20)),
+				nv_rd32(dev, 0x660180 + (i * 0x20)));
+		}
+	}
+
+	mask = nv_rd32(dev, 0x6101d4);
+	crtc = 0;
+	if (!mask) {
+		mask = nv_rd32(dev, 0x6109d4);
+		crtc = 1;
+	}
+
+	if (disp->modeset & 0x00000001)
+		nvd0_display_unk1_handler(dev, crtc, mask);
+	if (disp->modeset & 0x00000002)
+		nvd0_display_unk2_handler(dev, crtc, mask);
+	if (disp->modeset & 0x00000004)
+		nvd0_display_unk4_handler(dev, crtc, mask);
+}
+
+static void
+nvd0_display_intr(struct drm_device *dev)
+{
+	struct nvd0_display *disp = nvd0_display(dev);
+	u32 intr = nv_rd32(dev, 0x610088);
+
+	if (intr & 0x00000002) {
+		u32 stat = nv_rd32(dev, 0x61009c);
+		int chid = ffs(stat) - 1;
+		if (chid >= 0) {
+			u32 mthd = nv_rd32(dev, 0x6101f0 + (chid * 12));
+			u32 data = nv_rd32(dev, 0x6101f4 + (chid * 12));
+			u32 unkn = nv_rd32(dev, 0x6101f8 + (chid * 12));
+
+			NV_INFO(dev, "EvoCh: chid %d mthd 0x%04x data 0x%08x "
+				     "0x%08x 0x%08x\n",
+				chid, (mthd & 0x0000ffc), data, mthd, unkn);
+			nv_wr32(dev, 0x61009c, (1 << chid));
+			nv_wr32(dev, 0x6101f0 + (chid * 12), 0x90000000);
+		}
+
+		intr &= ~0x00000002;
+	}
+
+	if (intr & 0x00100000) {
+		u32 stat = nv_rd32(dev, 0x6100ac);
+
+		if (stat & 0x00000007) {
+			disp->modeset = stat;
+			tasklet_schedule(&disp->tasklet);
+
+			nv_wr32(dev, 0x6100ac, (stat & 0x00000007));
+			stat &= ~0x00000007;
+		}
+
+		if (stat) {
+			NV_INFO(dev, "PDISP: unknown intr24 0x%08x\n", stat);
+			nv_wr32(dev, 0x6100ac, stat);
+		}
+
+		intr &= ~0x00100000;
+	}
+
+	if (intr & 0x01000000) {
+		u32 stat = nv_rd32(dev, 0x6100bc);
+		nv_wr32(dev, 0x6100bc, stat);
+		intr &= ~0x01000000;
+	}
+
+	if (intr & 0x02000000) {
+		u32 stat = nv_rd32(dev, 0x6108bc);
+		nv_wr32(dev, 0x6108bc, stat);
+		intr &= ~0x02000000;
+	}
+
+	if (intr)
+		NV_INFO(dev, "PDISP: unknown intr 0x%08x\n", intr);
+}
+
+/******************************************************************************
+ * Init
+ *****************************************************************************/
+static void
+nvd0_display_fini(struct drm_device *dev)
+{
+	int i;
+
+	/* fini cursors */
+	for (i = 14; i >= 13; i--) {
+		if (!(nv_rd32(dev, 0x610490 + (i * 0x10)) & 0x00000001))
+			continue;
+
+		nv_mask(dev, 0x610490 + (i * 0x10), 0x00000001, 0x00000000);
+		nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00000000);
+		nv_mask(dev, 0x610090, 1 << i, 0x00000000);
+		nv_mask(dev, 0x6100a0, 1 << i, 0x00000000);
+	}
+
+	/* fini master */
+	if (nv_rd32(dev, 0x610490) & 0x00000010) {
+		nv_mask(dev, 0x610490, 0x00000010, 0x00000000);
+		nv_mask(dev, 0x610490, 0x00000003, 0x00000000);
+		nv_wait(dev, 0x610490, 0x80000000, 0x00000000);
+		nv_mask(dev, 0x610090, 0x00000001, 0x00000000);
+		nv_mask(dev, 0x6100a0, 0x00000001, 0x00000000);
+	}
+}
+
+int
+nvd0_display_init(struct drm_device *dev)
+{
+	struct nvd0_display *disp = nvd0_display(dev);
+	u32 *push;
+	int i;
+
+	if (nv_rd32(dev, 0x6100ac) & 0x00000100) {
+		nv_wr32(dev, 0x6100ac, 0x00000100);
+		nv_mask(dev, 0x6194e8, 0x00000001, 0x00000000);
+		if (!nv_wait(dev, 0x6194e8, 0x00000002, 0x00000000)) {
+			NV_ERROR(dev, "PDISP: 0x6194e8 0x%08x\n",
+				 nv_rd32(dev, 0x6194e8));
+			return -EBUSY;
+		}
+	}
+
+	/* nfi what these are exactly, i do know that SOR_MODE_CTRL won't
+	 * work at all unless you do the SOR part below.
+	 */
+	for (i = 0; i < 3; i++) {
+		u32 dac = nv_rd32(dev, 0x61a000 + (i * 0x800));
+		nv_wr32(dev, 0x6101c0 + (i * 0x800), dac);
+	}
+
+	for (i = 0; i < 4; i++) {
+		u32 sor = nv_rd32(dev, 0x61c000 + (i * 0x800));
+		nv_wr32(dev, 0x6301c4 + (i * 0x800), sor);
+	}
+
+	for (i = 0; i < 2; i++) {
+		u32 crtc0 = nv_rd32(dev, 0x616104 + (i * 0x800));
+		u32 crtc1 = nv_rd32(dev, 0x616108 + (i * 0x800));
+		u32 crtc2 = nv_rd32(dev, 0x61610c + (i * 0x800));
+		nv_wr32(dev, 0x6101b4 + (i * 0x800), crtc0);
+		nv_wr32(dev, 0x6101b8 + (i * 0x800), crtc1);
+		nv_wr32(dev, 0x6101bc + (i * 0x800), crtc2);
+	}
+
+	/* point at our hash table / objects, enable interrupts */
+	nv_wr32(dev, 0x610010, (disp->mem->vinst >> 8) | 9);
+	nv_mask(dev, 0x6100b0, 0x00000307, 0x00000307);
+
+	/* init master */
+	nv_wr32(dev, 0x610494, (disp->evo[0].handle >> 8) | 3);
+	nv_wr32(dev, 0x610498, 0x00010000);
+	nv_wr32(dev, 0x61049c, 0x00000001);
+	nv_mask(dev, 0x610490, 0x00000010, 0x00000010);
+	nv_wr32(dev, 0x640000, 0x00000000);
+	nv_wr32(dev, 0x610490, 0x01000013);
+	if (!nv_wait(dev, 0x610490, 0x80000000, 0x00000000)) {
+		NV_ERROR(dev, "PDISP: master 0x%08x\n",
+			 nv_rd32(dev, 0x610490));
+		return -EBUSY;
+	}
+	nv_mask(dev, 0x610090, 0x00000001, 0x00000001);
+	nv_mask(dev, 0x6100a0, 0x00000001, 0x00000001);
+
+	/* init cursors */
+	for (i = 13; i <= 14; i++) {
+		nv_wr32(dev, 0x610490 + (i * 0x10), 0x00000001);
+		if (!nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00010000)) {
+			NV_ERROR(dev, "PDISP: curs%d 0x%08x\n", i,
+				 nv_rd32(dev, 0x610490 + (i * 0x10)));
+			return -EBUSY;
+		}
+
+		nv_mask(dev, 0x610090, 1 << i, 1 << i);
+		nv_mask(dev, 0x6100a0, 1 << i, 1 << i);
+	}
+
+	push = evo_wait(dev, 0, 32);
+	if (!push)
+		return -EBUSY;
+	evo_mthd(push, 0x0088, 1);
+	evo_data(push, NvEvoSync);
+	evo_mthd(push, 0x0084, 1);
+	evo_data(push, 0x00000000);
+	evo_mthd(push, 0x0084, 1);
+	evo_data(push, 0x80000000);
+	evo_mthd(push, 0x008c, 1);
+	evo_data(push, 0x00000000);
+	evo_kick(push, dev, 0);
+
+	return 0;
+}
+
+void
+nvd0_display_destroy(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvd0_display *disp = nvd0_display(dev);
+	struct pci_dev *pdev = dev->pdev;
+
+	nvd0_display_fini(dev);
+
+	pci_free_consistent(pdev, PAGE_SIZE, disp->evo[0].ptr, disp->evo[0].handle);
+	nouveau_gpuobj_ref(NULL, &disp->mem);
+	nouveau_irq_unregister(dev, 26);
+
+	dev_priv->engine.display.priv = NULL;
+	kfree(disp);
+}
+
+int
+nvd0_display_create(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
+	struct dcb_table *dcb = &dev_priv->vbios.dcb;
+	struct drm_connector *connector, *tmp;
+	struct pci_dev *pdev = dev->pdev;
+	struct nvd0_display *disp;
+	struct dcb_entry *dcbe;
+	int ret, i;
+
+	disp = kzalloc(sizeof(*disp), GFP_KERNEL);
+	if (!disp)
+		return -ENOMEM;
+	dev_priv->engine.display.priv = disp;
+
+	/* create crtc objects to represent the hw heads */
+	for (i = 0; i < 2; i++) {
+		ret = nvd0_crtc_create(dev, i);
+		if (ret)
+			goto out;
+	}
+
+	/* create encoder/connector objects based on VBIOS DCB table */
+	for (i = 0, dcbe = &dcb->entry[0]; i < dcb->entries; i++, dcbe++) {
+		connector = nouveau_connector_create(dev, dcbe->connector);
+		if (IS_ERR(connector))
+			continue;
+
+		if (dcbe->location != DCB_LOC_ON_CHIP) {
+			NV_WARN(dev, "skipping off-chip encoder %d/%d\n",
+				dcbe->type, ffs(dcbe->or) - 1);
+			continue;
+		}
+
+		switch (dcbe->type) {
+		case OUTPUT_TMDS:
+		case OUTPUT_LVDS:
+			nvd0_sor_create(connector, dcbe);
+			break;
+		case OUTPUT_ANALOG:
+			nvd0_dac_create(connector, dcbe);
+			break;
+		default:
+			NV_WARN(dev, "skipping unsupported encoder %d/%d\n",
+				dcbe->type, ffs(dcbe->or) - 1);
+			continue;
+		}
+	}
+
+	/* cull any connectors we created that don't have an encoder */
+	list_for_each_entry_safe(connector, tmp, &dev->mode_config.connector_list, head) {
+		if (connector->encoder_ids[0])
+			continue;
+
+		NV_WARN(dev, "%s has no encoders, removing\n",
+			drm_get_connector_name(connector));
+		connector->funcs->destroy(connector);
+	}
+
+	/* setup interrupt handling */
+	tasklet_init(&disp->tasklet, nvd0_display_bh, (unsigned long)dev);
+	nouveau_irq_register(dev, 26, nvd0_display_intr);
+
+	/* hash table and dma objects for the memory areas we care about */
+	ret = nouveau_gpuobj_new(dev, NULL, 0x4000, 0x10000,
+				 NVOBJ_FLAG_ZERO_ALLOC, &disp->mem);
+	if (ret)
+		goto out;
+
+	nv_wo32(disp->mem, 0x1000, 0x00000049);
+	nv_wo32(disp->mem, 0x1004, (disp->mem->vinst + 0x2000) >> 8);
+	nv_wo32(disp->mem, 0x1008, (disp->mem->vinst + 0x2fff) >> 8);
+	nv_wo32(disp->mem, 0x100c, 0x00000000);
+	nv_wo32(disp->mem, 0x1010, 0x00000000);
+	nv_wo32(disp->mem, 0x1014, 0x00000000);
+	nv_wo32(disp->mem, 0x0000, NvEvoSync);
+	nv_wo32(disp->mem, 0x0004, (0x1000 << 9) | 0x00000001);
+
+	nv_wo32(disp->mem, 0x1020, 0x00000049);
+	nv_wo32(disp->mem, 0x1024, 0x00000000);
+	nv_wo32(disp->mem, 0x1028, (dev_priv->vram_size - 1) >> 8);
+	nv_wo32(disp->mem, 0x102c, 0x00000000);
+	nv_wo32(disp->mem, 0x1030, 0x00000000);
+	nv_wo32(disp->mem, 0x1034, 0x00000000);
+	nv_wo32(disp->mem, 0x0008, NvEvoVRAM);
+	nv_wo32(disp->mem, 0x000c, (0x1020 << 9) | 0x00000001);
+
+	nv_wo32(disp->mem, 0x1040, 0x00000009);
+	nv_wo32(disp->mem, 0x1044, 0x00000000);
+	nv_wo32(disp->mem, 0x1048, (dev_priv->vram_size - 1) >> 8);
+	nv_wo32(disp->mem, 0x104c, 0x00000000);
+	nv_wo32(disp->mem, 0x1050, 0x00000000);
+	nv_wo32(disp->mem, 0x1054, 0x00000000);
+	nv_wo32(disp->mem, 0x0010, NvEvoVRAM_LP);
+	nv_wo32(disp->mem, 0x0014, (0x1040 << 9) | 0x00000001);
+
+	nv_wo32(disp->mem, 0x1060, 0x0fe00009);
+	nv_wo32(disp->mem, 0x1064, 0x00000000);
+	nv_wo32(disp->mem, 0x1068, (dev_priv->vram_size - 1) >> 8);
+	nv_wo32(disp->mem, 0x106c, 0x00000000);
+	nv_wo32(disp->mem, 0x1070, 0x00000000);
+	nv_wo32(disp->mem, 0x1074, 0x00000000);
+	nv_wo32(disp->mem, 0x0018, NvEvoFB32);
+	nv_wo32(disp->mem, 0x001c, (0x1060 << 9) | 0x00000001);
+
+	pinstmem->flush(dev);
+
+	/* push buffers for evo channels */
+	disp->evo[0].ptr =
+		pci_alloc_consistent(pdev, PAGE_SIZE, &disp->evo[0].handle);
+	if (!disp->evo[0].ptr) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = nvd0_display_init(dev);
+	if (ret)
+		goto out;
+
+out:
+	if (ret)
+		nvd0_display_destroy(dev);
+	return ret;
+}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/r128/r128_cce.c linux-libre-3.2-gnu/drivers/gpu/drm/r128/r128_cce.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/r128/r128_cce.c	2012-03-19 21:29:53.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/r128/r128_cce.c	2012-03-19 21:31:33.000000000 -0400
@@ -32,6 +32,7 @@
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include "drmP.h"
 #include "drm.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/r128/r128_drv.c linux-libre-3.2-gnu/drivers/gpu/drm/r128/r128_drv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/r128/r128_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/r128/r128_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,8 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "drm.h"
 #include "r128_drm.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/atombios_crtc.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/atombios_crtc.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/atombios_crtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/atombios_crtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -558,7 +558,7 @@
 				bpc = connector->display_info.bpc;
 			encoder_mode = atombios_get_encoder_mode(encoder);
 			if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
-			    radeon_encoder_is_dp_bridge(encoder)) {
+			    (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) {
 				if (connector) {
 					struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 					struct radeon_connector_atom_dig *dig_connector =
@@ -638,44 +638,29 @@
 				if (ss_enabled && ss->percentage)
 					args.v3.sInput.ucDispPllConfig |=
 						DISPPLL_CONFIG_SS_ENABLE;
-				if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT) ||
-				    radeon_encoder_is_dp_bridge(encoder)) {
+				if (ENCODER_MODE_IS_DP(encoder_mode)) {
+					args.v3.sInput.ucDispPllConfig |=
+						DISPPLL_CONFIG_COHERENT_MODE;
+					/* 16200 or 27000 */
+					args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
+				} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
 					struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-					if (encoder_mode == ATOM_ENCODER_MODE_DP) {
+					if (encoder_mode == ATOM_ENCODER_MODE_HDMI)
+						/* deep color support */
+						args.v3.sInput.usPixelClock =
+							cpu_to_le16((mode->clock * bpc / 8) / 10);
+					if (dig->coherent_mode)
 						args.v3.sInput.ucDispPllConfig |=
 							DISPPLL_CONFIG_COHERENT_MODE;
-						/* 16200 or 27000 */
-						args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
-					} else {
-						if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
-							/* deep color support */
-							args.v3.sInput.usPixelClock =
-								cpu_to_le16((mode->clock * bpc / 8) / 10);
-						}
-						if (dig->coherent_mode)
-							args.v3.sInput.ucDispPllConfig |=
-								DISPPLL_CONFIG_COHERENT_MODE;
-						if (mode->clock > 165000)
-							args.v3.sInput.ucDispPllConfig |=
-								DISPPLL_CONFIG_DUAL_LINK;
-					}
-				} else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-					if (encoder_mode == ATOM_ENCODER_MODE_DP) {
+					if (mode->clock > 165000)
 						args.v3.sInput.ucDispPllConfig |=
-							DISPPLL_CONFIG_COHERENT_MODE;
-						/* 16200 or 27000 */
-						args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
-					} else if (encoder_mode != ATOM_ENCODER_MODE_LVDS) {
-						if (mode->clock > 165000)
-							args.v3.sInput.ucDispPllConfig |=
-								DISPPLL_CONFIG_DUAL_LINK;
-					}
+							DISPPLL_CONFIG_DUAL_LINK;
 				}
-				if (radeon_encoder_is_dp_bridge(encoder)) {
-					struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-					struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
-					args.v3.sInput.ucExtTransmitterID = ext_radeon_encoder->encoder_id;
-				} else
+				if (radeon_encoder_get_dp_bridge_encoder_id(encoder) !=
+				    ENCODER_OBJECT_ID_NONE)
+					args.v3.sInput.ucExtTransmitterID =
+						radeon_encoder_get_dp_bridge_encoder_id(encoder);
+				else
 					args.v3.sInput.ucExtTransmitterID = 0;
 
 				atom_execute_table(rdev->mode_info.atom_context,
@@ -945,6 +930,7 @@
 		bpc = connector->display_info.bpc;
 
 		switch (encoder_mode) {
+		case ATOM_ENCODER_MODE_DP_MST:
 		case ATOM_ENCODER_MODE_DP:
 			/* DP/eDP */
 			dp_clock = dig_connector->dp_clock / 10;
@@ -1121,9 +1107,40 @@
 		return -EINVAL;
 	}
 
-	if (tiling_flags & RADEON_TILING_MACRO)
+	if (tiling_flags & RADEON_TILING_MACRO) {
+		if (rdev->family >= CHIP_CAYMAN)
+			tmp = rdev->config.cayman.tile_config;
+		else
+			tmp = rdev->config.evergreen.tile_config;
+
+		switch ((tmp & 0xf0) >> 4) {
+		case 0: /* 4 banks */
+			fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK);
+			break;
+		case 1: /* 8 banks */
+		default:
+			fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK);
+			break;
+		case 2: /* 16 banks */
+			fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK);
+			break;
+		}
+
+		switch ((tmp & 0xf000) >> 12) {
+		case 0: /* 1KB rows */
+		default:
+			fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_1KB);
+			break;
+		case 1: /* 2KB rows */
+			fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_2KB);
+			break;
+		case 2: /* 4KB rows */
+			fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_4KB);
+			break;
+		}
+
 		fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1);
-	else if (tiling_flags & RADEON_TILING_MICRO)
+	} else if (tiling_flags & RADEON_TILING_MICRO)
 		fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1);
 
 	switch (radeon_crtc->crtc_id) {
@@ -1450,7 +1467,7 @@
 				 * PPLL/DCPLL programming and only program the DP DTO for the
 				 * crtc virtual pixel clock.
 				 */
-				if (atombios_get_encoder_mode(test_encoder) == ATOM_ENCODER_MODE_DP) {
+				if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
 					if (ASIC_IS_DCE5(rdev) || rdev->clock.dp_extclk)
 						return ATOM_PPLL_INVALID;
 				}
@@ -1536,12 +1553,6 @@
 				     struct drm_display_mode *mode,
 				     struct drm_display_mode *adjusted_mode)
 {
-	struct drm_device *dev = crtc->dev;
-	struct radeon_device *rdev = dev->dev_private;
-
-	/* adjust pm to upcoming mode change */
-	radeon_pm_compute_clocks(rdev);
-
 	if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
 		return false;
 	return true;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/atombios_dp.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/atombios_dp.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/atombios_dp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/atombios_dp.c	2012-01-04 18:55:44.000000000 -0500
@@ -283,7 +283,7 @@
 		}
 	}
 
-	DRM_ERROR("aux i2c too many retries, giving up\n");
+	DRM_DEBUG_KMS("aux i2c too many retries, giving up\n");
 	return -EREMOTEIO;
 }
 
@@ -482,7 +482,8 @@
 	int bpp = convert_bpc_to_bpp(connector->display_info.bpc);
 	int lane_num, max_pix_clock;
 
-	if (radeon_connector_encoder_is_dp_bridge(connector))
+	if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
+	    ENCODER_OBJECT_ID_NUTMEG)
 		return 270000;
 
 	lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock);
@@ -553,17 +554,32 @@
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
 
 	if (!ASIC_IS_DCE4(rdev))
 		return;
 
-	if (radeon_connector_encoder_is_dp_bridge(connector))
+	if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
+	    ENCODER_OBJECT_ID_NUTMEG)
 		panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
+	else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
+		 ENCODER_OBJECT_ID_TRAVIS)
+		panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
+	else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+		u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
+		if (tmp & 1)
+			panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
+	}
 
 	atombios_dig_encoder_setup(encoder,
 				   ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
 				   panel_mode);
+
+	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) &&
+	    (panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) {
+		radeon_write_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_SET, 1);
+	}
 }
 
 void radeon_dp_set_link_config(struct drm_connector *connector,
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/atombios_encoders.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/atombios_encoders.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/atombios_encoders.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/atombios_encoders.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2369 @@
+/*
+ * Copyright 2007-11 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ */
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+#include "atom.h"
+
+extern int atom_debug;
+
+/* evil but including atombios.h is much worse */
+bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
+				struct drm_display_mode *mode);
+
+
+static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static struct drm_connector *
+radeon_get_connector_for_encoder_init(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		radeon_connector = to_radeon_connector(connector);
+		if (radeon_encoder->devices & radeon_connector->devices)
+			return connector;
+	}
+	return NULL;
+}
+
+static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+
+	/* set the active encoder to connector routing */
+	radeon_encoder_set_active_device(encoder);
+	drm_mode_set_crtcinfo(adjusted_mode, 0);
+
+	/* hw bug */
+	if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
+	    && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
+		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
+
+	/* get the native mode for LVDS */
+	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
+		radeon_panel_mode_fixup(encoder, adjusted_mode);
+
+	/* get the native mode for TV */
+	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
+		struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
+		if (tv_dac) {
+			if (tv_dac->tv_std == TV_STD_NTSC ||
+			    tv_dac->tv_std == TV_STD_NTSC_J ||
+			    tv_dac->tv_std == TV_STD_PAL_M)
+				radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
+			else
+				radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
+		}
+	}
+
+	if (ASIC_IS_DCE3(rdev) &&
+	    ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
+	     (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) {
+		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+		radeon_dp_set_link_config(connector, mode);
+	}
+
+	return true;
+}
+
+static void
+atombios_dac_setup(struct drm_encoder *encoder, int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
+	int index = 0;
+	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
+
+	memset(&args, 0, sizeof(args));
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+		index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
+		break;
+	}
+
+	args.ucAction = action;
+
+	if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
+		args.ucDacStandard = ATOM_DAC1_PS2;
+	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+		args.ucDacStandard = ATOM_DAC1_CV;
+	else {
+		switch (dac_info->tv_std) {
+		case TV_STD_PAL:
+		case TV_STD_PAL_M:
+		case TV_STD_SCART_PAL:
+		case TV_STD_SECAM:
+		case TV_STD_PAL_CN:
+			args.ucDacStandard = ATOM_DAC1_PAL;
+			break;
+		case TV_STD_NTSC:
+		case TV_STD_NTSC_J:
+		case TV_STD_PAL_60:
+		default:
+			args.ucDacStandard = ATOM_DAC1_NTSC;
+			break;
+		}
+	}
+	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+static void
+atombios_tv_setup(struct drm_encoder *encoder, int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	TV_ENCODER_CONTROL_PS_ALLOCATION args;
+	int index = 0;
+	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
+
+	memset(&args, 0, sizeof(args));
+
+	index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
+
+	args.sTVEncoder.ucAction = action;
+
+	if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
+	else {
+		switch (dac_info->tv_std) {
+		case TV_STD_NTSC:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
+			break;
+		case TV_STD_PAL:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
+			break;
+		case TV_STD_PAL_M:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
+			break;
+		case TV_STD_PAL_60:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
+			break;
+		case TV_STD_NTSC_J:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
+			break;
+		case TV_STD_SCART_PAL:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
+			break;
+		case TV_STD_SECAM:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
+			break;
+		case TV_STD_PAL_CN:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
+			break;
+		default:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
+			break;
+		}
+	}
+
+	args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+union dvo_encoder_control {
+	ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds;
+	DVO_ENCODER_CONTROL_PS_ALLOCATION dvo;
+	DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3;
+};
+
+void
+atombios_dvo_setup(struct drm_encoder *encoder, int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	union dvo_encoder_control args;
+	int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
+	uint8_t frev, crev;
+
+	memset(&args, 0, sizeof(args));
+
+	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+		return;
+
+	switch (frev) {
+	case 1:
+		switch (crev) {
+		case 1:
+			/* R4xx, R5xx */
+			args.ext_tmds.sXTmdsEncoder.ucEnable = action;
+
+			if (radeon_encoder->pixel_clock > 165000)
+				args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+
+			args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
+			break;
+		case 2:
+			/* RS600/690/740 */
+			args.dvo.sDVOEncoder.ucAction = action;
+			args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			/* DFP1, CRT1, TV1 depending on the type of port */
+			args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
+
+			if (radeon_encoder->pixel_clock > 165000)
+				args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
+			break;
+		case 3:
+			/* R6xx */
+			args.dvo_v3.ucAction = action;
+			args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			args.dvo_v3.ucDVOConfig = 0; /* XXX */
+			break;
+		default:
+			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+			break;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+		break;
+	}
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+union lvds_encoder_control {
+	LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
+	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
+};
+
+void
+atombios_digital_setup(struct drm_encoder *encoder, int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+	union lvds_encoder_control args;
+	int index = 0;
+	int hdmi_detected = 0;
+	uint8_t frev, crev;
+
+	if (!dig)
+		return;
+
+	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
+		hdmi_detected = 1;
+
+	memset(&args, 0, sizeof(args));
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+		index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+		index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
+		else
+			index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
+		break;
+	}
+
+	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+		return;
+
+	switch (frev) {
+	case 1:
+	case 2:
+		switch (crev) {
+		case 1:
+			args.v1.ucMisc = 0;
+			args.v1.ucAction = action;
+			if (hdmi_detected)
+				args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
+			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
+					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+				if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
+					args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
+			} else {
+				if (dig->linkb)
+					args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
+				if (radeon_encoder->pixel_clock > 165000)
+					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+				/*if (pScrn->rgbBits == 8) */
+				args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
+			}
+			break;
+		case 2:
+		case 3:
+			args.v2.ucMisc = 0;
+			args.v2.ucAction = action;
+			if (crev == 3) {
+				if (dig->coherent_mode)
+					args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
+			}
+			if (hdmi_detected)
+				args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
+			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			args.v2.ucTruncate = 0;
+			args.v2.ucSpatial = 0;
+			args.v2.ucTemporal = 0;
+			args.v2.ucFRC = 0;
+			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
+					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+				if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) {
+					args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
+					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
+						args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
+				}
+				if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) {
+					args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
+					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
+						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
+					if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
+						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
+				}
+			} else {
+				if (dig->linkb)
+					args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
+				if (radeon_encoder->pixel_clock > 165000)
+					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+			}
+			break;
+		default:
+			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+			break;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+		break;
+	}
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+int
+atombios_get_encoder_mode(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
+	struct radeon_connector_atom_dig *dig_connector;
+
+	/* dp bridges are always DP */
+	if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)
+		return ATOM_ENCODER_MODE_DP;
+
+	/* DVO is always DVO */
+	if (radeon_encoder->encoder_id == ATOM_ENCODER_MODE_DVO)
+		return ATOM_ENCODER_MODE_DVO;
+
+	connector = radeon_get_connector_for_encoder(encoder);
+	/* if we don't have an active device yet, just use one of
+	 * the connectors tied to the encoder.
+	 */
+	if (!connector)
+		connector = radeon_get_connector_for_encoder_init(encoder);
+	radeon_connector = to_radeon_connector(connector);
+
+	switch (connector->connector_type) {
+	case DRM_MODE_CONNECTOR_DVII:
+	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
+		if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
+			/* fix me */
+			if (ASIC_IS_DCE4(rdev))
+				return ATOM_ENCODER_MODE_DVI;
+			else
+				return ATOM_ENCODER_MODE_HDMI;
+		} else if (radeon_connector->use_digital)
+			return ATOM_ENCODER_MODE_DVI;
+		else
+			return ATOM_ENCODER_MODE_CRT;
+		break;
+	case DRM_MODE_CONNECTOR_DVID:
+	case DRM_MODE_CONNECTOR_HDMIA:
+	default:
+		if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
+			/* fix me */
+			if (ASIC_IS_DCE4(rdev))
+				return ATOM_ENCODER_MODE_DVI;
+			else
+				return ATOM_ENCODER_MODE_HDMI;
+		} else
+			return ATOM_ENCODER_MODE_DVI;
+		break;
+	case DRM_MODE_CONNECTOR_LVDS:
+		return ATOM_ENCODER_MODE_LVDS;
+		break;
+	case DRM_MODE_CONNECTOR_DisplayPort:
+		dig_connector = radeon_connector->con_priv;
+		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
+		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
+			return ATOM_ENCODER_MODE_DP;
+		else if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
+			/* fix me */
+			if (ASIC_IS_DCE4(rdev))
+				return ATOM_ENCODER_MODE_DVI;
+			else
+				return ATOM_ENCODER_MODE_HDMI;
+		} else
+			return ATOM_ENCODER_MODE_DVI;
+		break;
+	case DRM_MODE_CONNECTOR_eDP:
+		return ATOM_ENCODER_MODE_DP;
+	case DRM_MODE_CONNECTOR_DVIA:
+	case DRM_MODE_CONNECTOR_VGA:
+		return ATOM_ENCODER_MODE_CRT;
+		break;
+	case DRM_MODE_CONNECTOR_Composite:
+	case DRM_MODE_CONNECTOR_SVIDEO:
+	case DRM_MODE_CONNECTOR_9PinDIN:
+		/* fix me */
+		return ATOM_ENCODER_MODE_TV;
+		/*return ATOM_ENCODER_MODE_CV;*/
+		break;
+	}
+}
+
+/*
+ * DIG Encoder/Transmitter Setup
+ *
+ * DCE 3.0/3.1
+ * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
+ * Supports up to 3 digital outputs
+ * - 2 DIG encoder blocks.
+ * DIG1 can drive UNIPHY link A or link B
+ * DIG2 can drive UNIPHY link B or LVTMA
+ *
+ * DCE 3.2
+ * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
+ * Supports up to 5 digital outputs
+ * - 2 DIG encoder blocks.
+ * DIG1/2 can drive UNIPHY0/1/2 link A or link B
+ *
+ * DCE 4.0/5.0
+ * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
+ * Supports up to 6 digital outputs
+ * - 6 DIG encoder blocks.
+ * - DIG to PHY mapping is hardcoded
+ * DIG1 drives UNIPHY0 link A, A+B
+ * DIG2 drives UNIPHY0 link B
+ * DIG3 drives UNIPHY1 link A, A+B
+ * DIG4 drives UNIPHY1 link B
+ * DIG5 drives UNIPHY2 link A, A+B
+ * DIG6 drives UNIPHY2 link B
+ *
+ * DCE 4.1
+ * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
+ * Supports up to 6 digital outputs
+ * - 2 DIG encoder blocks.
+ * DIG1/2 can drive UNIPHY0/1/2 link A or link B
+ *
+ * Routing
+ * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
+ * Examples:
+ * crtc0 -> dig2 -> LVTMA   links A+B -> TMDS/HDMI
+ * crtc1 -> dig1 -> UNIPHY0 link  B   -> DP
+ * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
+ * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
+ */
+
+union dig_encoder_control {
+	DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
+	DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
+	DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
+	DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
+};
+
+void
+atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+	union dig_encoder_control args;
+	int index = 0;
+	uint8_t frev, crev;
+	int dp_clock = 0;
+	int dp_lane_count = 0;
+	int hpd_id = RADEON_HPD_NONE;
+	int bpc = 8;
+
+	if (connector) {
+		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+		struct radeon_connector_atom_dig *dig_connector =
+			radeon_connector->con_priv;
+
+		dp_clock = dig_connector->dp_clock;
+		dp_lane_count = dig_connector->dp_lane_count;
+		hpd_id = radeon_connector->hpd.hpd;
+		bpc = connector->display_info.bpc;
+	}
+
+	/* no dig encoder assigned */
+	if (dig->dig_encoder == -1)
+		return;
+
+	memset(&args, 0, sizeof(args));
+
+	if (ASIC_IS_DCE4(rdev))
+		index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
+	else {
+		if (dig->dig_encoder)
+			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
+		else
+			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
+	}
+
+	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+		return;
+
+	switch (frev) {
+	case 1:
+		switch (crev) {
+		case 1:
+			args.v1.ucAction = action;
+			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
+				args.v3.ucPanelMode = panel_mode;
+			else
+				args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
+				args.v1.ucLaneNum = dp_lane_count;
+			else if (radeon_encoder->pixel_clock > 165000)
+				args.v1.ucLaneNum = 8;
+			else
+				args.v1.ucLaneNum = 4;
+
+			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000))
+				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
+			switch (radeon_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+				args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
+				break;
+			}
+			if (dig->linkb)
+				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
+			else
+				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
+			break;
+		case 2:
+		case 3:
+			args.v3.ucAction = action;
+			args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
+				args.v3.ucPanelMode = panel_mode;
+			else
+				args.v3.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
+				args.v3.ucLaneNum = dp_lane_count;
+			else if (radeon_encoder->pixel_clock > 165000)
+				args.v3.ucLaneNum = 8;
+			else
+				args.v3.ucLaneNum = 4;
+
+			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000))
+				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
+			args.v3.acConfig.ucDigSel = dig->dig_encoder;
+			switch (bpc) {
+			case 0:
+				args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE;
+				break;
+			case 6:
+				args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR;
+				break;
+			case 8:
+			default:
+				args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
+				break;
+			case 10:
+				args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR;
+				break;
+			case 12:
+				args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR;
+				break;
+			case 16:
+				args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR;
+				break;
+			}
+			break;
+		case 4:
+			args.v4.ucAction = action;
+			args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
+				args.v4.ucPanelMode = panel_mode;
+			else
+				args.v4.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
+				args.v4.ucLaneNum = dp_lane_count;
+			else if (radeon_encoder->pixel_clock > 165000)
+				args.v4.ucLaneNum = 8;
+			else
+				args.v4.ucLaneNum = 4;
+
+			if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode)) {
+				if (dp_clock == 270000)
+					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
+				else if (dp_clock == 540000)
+					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
+			}
+			args.v4.acConfig.ucDigSel = dig->dig_encoder;
+			switch (bpc) {
+			case 0:
+				args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE;
+				break;
+			case 6:
+				args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR;
+				break;
+			case 8:
+			default:
+				args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR;
+				break;
+			case 10:
+				args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR;
+				break;
+			case 12:
+				args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR;
+				break;
+			case 16:
+				args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR;
+				break;
+			}
+			if (hpd_id == RADEON_HPD_NONE)
+				args.v4.ucHPD_ID = 0;
+			else
+				args.v4.ucHPD_ID = hpd_id + 1;
+			break;
+		default:
+			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+			break;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+		break;
+	}
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+union dig_transmitter_control {
+	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
+};
+
+void
+atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+	struct drm_connector *connector;
+	union dig_transmitter_control args;
+	int index = 0;
+	uint8_t frev, crev;
+	bool is_dp = false;
+	int pll_id = 0;
+	int dp_clock = 0;
+	int dp_lane_count = 0;
+	int connector_object_id = 0;
+	int igp_lane_info = 0;
+	int dig_encoder = dig->dig_encoder;
+
+	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+		connector = radeon_get_connector_for_encoder_init(encoder);
+		/* just needed to avoid bailing in the encoder check.  the encoder
+		 * isn't used for init
+		 */
+		dig_encoder = 0;
+	} else
+		connector = radeon_get_connector_for_encoder(encoder);
+
+	if (connector) {
+		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+		struct radeon_connector_atom_dig *dig_connector =
+			radeon_connector->con_priv;
+
+		dp_clock = dig_connector->dp_clock;
+		dp_lane_count = dig_connector->dp_lane_count;
+		connector_object_id =
+			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
+		igp_lane_info = dig_connector->igp_lane_info;
+	}
+
+	if (encoder->crtc) {
+		struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+		pll_id = radeon_crtc->pll_id;
+	}
+
+	/* no dig encoder assigned */
+	if (dig_encoder == -1)
+		return;
+
+	if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)))
+		is_dp = true;
+
+	memset(&args, 0, sizeof(args));
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
+		break;
+	}
+
+	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+		return;
+
+	switch (frev) {
+	case 1:
+		switch (crev) {
+		case 1:
+			args.v1.ucAction = action;
+			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+				args.v1.usInitInfo = cpu_to_le16(connector_object_id);
+			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+				args.v1.asMode.ucLaneSel = lane_num;
+				args.v1.asMode.ucLaneSet = lane_set;
+			} else {
+				if (is_dp)
+					args.v1.usPixelClock =
+						cpu_to_le16(dp_clock / 10);
+				else if (radeon_encoder->pixel_clock > 165000)
+					args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
+				else
+					args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			}
+
+			args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
+
+			if (dig_encoder)
+				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
+			else
+				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
+
+			if ((rdev->flags & RADEON_IS_IGP) &&
+			    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
+				if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
+					if (igp_lane_info & 0x1)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
+					else if (igp_lane_info & 0x2)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
+					else if (igp_lane_info & 0x4)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
+					else if (igp_lane_info & 0x8)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
+				} else {
+					if (igp_lane_info & 0x3)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
+					else if (igp_lane_info & 0xc)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
+				}
+			}
+
+			if (dig->linkb)
+				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
+			else
+				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
+
+			if (is_dp)
+				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
+			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+				if (dig->coherent_mode)
+					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
+				if (radeon_encoder->pixel_clock > 165000)
+					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
+			}
+			break;
+		case 2:
+			args.v2.ucAction = action;
+			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+				args.v2.usInitInfo = cpu_to_le16(connector_object_id);
+			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+				args.v2.asMode.ucLaneSel = lane_num;
+				args.v2.asMode.ucLaneSet = lane_set;
+			} else {
+				if (is_dp)
+					args.v2.usPixelClock =
+						cpu_to_le16(dp_clock / 10);
+				else if (radeon_encoder->pixel_clock > 165000)
+					args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
+				else
+					args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			}
+
+			args.v2.acConfig.ucEncoderSel = dig_encoder;
+			if (dig->linkb)
+				args.v2.acConfig.ucLinkSel = 1;
+
+			switch (radeon_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+				args.v2.acConfig.ucTransmitterSel = 0;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+				args.v2.acConfig.ucTransmitterSel = 1;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+				args.v2.acConfig.ucTransmitterSel = 2;
+				break;
+			}
+
+			if (is_dp) {
+				args.v2.acConfig.fCoherentMode = 1;
+				args.v2.acConfig.fDPConnector = 1;
+			} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+				if (dig->coherent_mode)
+					args.v2.acConfig.fCoherentMode = 1;
+				if (radeon_encoder->pixel_clock > 165000)
+					args.v2.acConfig.fDualLinkConnector = 1;
+			}
+			break;
+		case 3:
+			args.v3.ucAction = action;
+			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+				args.v3.usInitInfo = cpu_to_le16(connector_object_id);
+			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+				args.v3.asMode.ucLaneSel = lane_num;
+				args.v3.asMode.ucLaneSet = lane_set;
+			} else {
+				if (is_dp)
+					args.v3.usPixelClock =
+						cpu_to_le16(dp_clock / 10);
+				else if (radeon_encoder->pixel_clock > 165000)
+					args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
+				else
+					args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			}
+
+			if (is_dp)
+				args.v3.ucLaneNum = dp_lane_count;
+			else if (radeon_encoder->pixel_clock > 165000)
+				args.v3.ucLaneNum = 8;
+			else
+				args.v3.ucLaneNum = 4;
+
+			if (dig->linkb)
+				args.v3.acConfig.ucLinkSel = 1;
+			if (dig_encoder & 1)
+				args.v3.acConfig.ucEncoderSel = 1;
+
+			/* Select the PLL for the PHY
+			 * DP PHY should be clocked from external src if there is
+			 * one.
+			 */
+			/* On DCE4, if there is an external clock, it generates the DP ref clock */
+			if (is_dp && rdev->clock.dp_extclk)
+				args.v3.acConfig.ucRefClkSource = 2; /* external src */
+			else
+				args.v3.acConfig.ucRefClkSource = pll_id;
+
+			switch (radeon_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+				args.v3.acConfig.ucTransmitterSel = 0;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+				args.v3.acConfig.ucTransmitterSel = 1;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+				args.v3.acConfig.ucTransmitterSel = 2;
+				break;
+			}
+
+			if (is_dp)
+				args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
+			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+				if (dig->coherent_mode)
+					args.v3.acConfig.fCoherentMode = 1;
+				if (radeon_encoder->pixel_clock > 165000)
+					args.v3.acConfig.fDualLinkConnector = 1;
+			}
+			break;
+		case 4:
+			args.v4.ucAction = action;
+			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+				args.v4.usInitInfo = cpu_to_le16(connector_object_id);
+			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+				args.v4.asMode.ucLaneSel = lane_num;
+				args.v4.asMode.ucLaneSet = lane_set;
+			} else {
+				if (is_dp)
+					args.v4.usPixelClock =
+						cpu_to_le16(dp_clock / 10);
+				else if (radeon_encoder->pixel_clock > 165000)
+					args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
+				else
+					args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			}
+
+			if (is_dp)
+				args.v4.ucLaneNum = dp_lane_count;
+			else if (radeon_encoder->pixel_clock > 165000)
+				args.v4.ucLaneNum = 8;
+			else
+				args.v4.ucLaneNum = 4;
+
+			if (dig->linkb)
+				args.v4.acConfig.ucLinkSel = 1;
+			if (dig_encoder & 1)
+				args.v4.acConfig.ucEncoderSel = 1;
+
+			/* Select the PLL for the PHY
+			 * DP PHY should be clocked from external src if there is
+			 * one.
+			 */
+			/* On DCE5 DCPLL usually generates the DP ref clock */
+			if (is_dp) {
+				if (rdev->clock.dp_extclk)
+					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK;
+				else
+					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL;
+			} else
+				args.v4.acConfig.ucRefClkSource = pll_id;
+
+			switch (radeon_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+				args.v4.acConfig.ucTransmitterSel = 0;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+				args.v4.acConfig.ucTransmitterSel = 1;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+				args.v4.acConfig.ucTransmitterSel = 2;
+				break;
+			}
+
+			if (is_dp)
+				args.v4.acConfig.fCoherentMode = 1; /* DP requires coherent */
+			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+				if (dig->coherent_mode)
+					args.v4.acConfig.fCoherentMode = 1;
+				if (radeon_encoder->pixel_clock > 165000)
+					args.v4.acConfig.fDualLinkConnector = 1;
+			}
+			break;
+		default:
+			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+			break;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+		break;
+	}
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+bool
+atombios_set_edp_panel_power(struct drm_connector *connector, int action)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	struct drm_device *dev = radeon_connector->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	union dig_transmitter_control args;
+	int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
+	uint8_t frev, crev;
+
+	if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
+		goto done;
+
+	if (!ASIC_IS_DCE4(rdev))
+		goto done;
+
+	if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) &&
+	    (action != ATOM_TRANSMITTER_ACTION_POWER_OFF))
+		goto done;
+
+	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+		goto done;
+
+	memset(&args, 0, sizeof(args));
+
+	args.v1.ucAction = action;
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+	/* wait for the panel to power up */
+	if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) {
+		int i;
+
+		for (i = 0; i < 300; i++) {
+			if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
+				return true;
+			mdelay(1);
+		}
+		return false;
+	}
+done:
+	return true;
+}
+
+union external_encoder_control {
+	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
+	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
+};
+
+static void
+atombios_external_encoder_setup(struct drm_encoder *encoder,
+				struct drm_encoder *ext_encoder,
+				int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
+	union external_encoder_control args;
+	struct drm_connector *connector;
+	int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
+	u8 frev, crev;
+	int dp_clock = 0;
+	int dp_lane_count = 0;
+	int connector_object_id = 0;
+	u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
+	int bpc = 8;
+
+	if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
+		connector = radeon_get_connector_for_encoder_init(encoder);
+	else
+		connector = radeon_get_connector_for_encoder(encoder);
+
+	if (connector) {
+		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+		struct radeon_connector_atom_dig *dig_connector =
+			radeon_connector->con_priv;
+
+		dp_clock = dig_connector->dp_clock;
+		dp_lane_count = dig_connector->dp_lane_count;
+		connector_object_id =
+			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
+		bpc = connector->display_info.bpc;
+	}
+
+	memset(&args, 0, sizeof(args));
+
+	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+		return;
+
+	switch (frev) {
+	case 1:
+		/* no params on frev 1 */
+		break;
+	case 2:
+		switch (crev) {
+		case 1:
+		case 2:
+			args.v1.sDigEncoder.ucAction = action;
+			args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+			if (ENCODER_MODE_IS_DP(args.v1.sDigEncoder.ucEncoderMode)) {
+				if (dp_clock == 270000)
+					args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
+				args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
+			} else if (radeon_encoder->pixel_clock > 165000)
+				args.v1.sDigEncoder.ucLaneNum = 8;
+			else
+				args.v1.sDigEncoder.ucLaneNum = 4;
+			break;
+		case 3:
+			args.v3.sExtEncoder.ucAction = action;
+			if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
+				args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id);
+			else
+				args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+			if (ENCODER_MODE_IS_DP(args.v3.sExtEncoder.ucEncoderMode)) {
+				if (dp_clock == 270000)
+					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
+				else if (dp_clock == 540000)
+					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
+				args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
+			} else if (radeon_encoder->pixel_clock > 165000)
+				args.v3.sExtEncoder.ucLaneNum = 8;
+			else
+				args.v3.sExtEncoder.ucLaneNum = 4;
+			switch (ext_enum) {
+			case GRAPH_OBJECT_ENUM_ID1:
+				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
+				break;
+			case GRAPH_OBJECT_ENUM_ID2:
+				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
+				break;
+			case GRAPH_OBJECT_ENUM_ID3:
+				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
+				break;
+			}
+			switch (bpc) {
+			case 0:
+				args.v3.sExtEncoder.ucBitPerColor = PANEL_BPC_UNDEFINE;
+				break;
+			case 6:
+				args.v3.sExtEncoder.ucBitPerColor = PANEL_6BIT_PER_COLOR;
+				break;
+			case 8:
+			default:
+				args.v3.sExtEncoder.ucBitPerColor = PANEL_8BIT_PER_COLOR;
+				break;
+			case 10:
+				args.v3.sExtEncoder.ucBitPerColor = PANEL_10BIT_PER_COLOR;
+				break;
+			case 12:
+				args.v3.sExtEncoder.ucBitPerColor = PANEL_12BIT_PER_COLOR;
+				break;
+			case 16:
+				args.v3.sExtEncoder.ucBitPerColor = PANEL_16BIT_PER_COLOR;
+				break;
+			}
+			break;
+		default:
+			DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
+			return;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
+		return;
+	}
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+static void
+atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+	ENABLE_YUV_PS_ALLOCATION args;
+	int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
+	uint32_t temp, reg;
+
+	memset(&args, 0, sizeof(args));
+
+	if (rdev->family >= CHIP_R600)
+		reg = R600_BIOS_3_SCRATCH;
+	else
+		reg = RADEON_BIOS_3_SCRATCH;
+
+	/* XXX: fix up scratch reg handling */
+	temp = RREG32(reg);
+	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+		WREG32(reg, (ATOM_S3_TV1_ACTIVE |
+			     (radeon_crtc->crtc_id << 18)));
+	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+		WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
+	else
+		WREG32(reg, 0);
+
+	if (enable)
+		args.ucEnable = ATOM_ENABLE;
+	args.ucCRTC = radeon_crtc->crtc_id;
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+	WREG32(reg, temp);
+}
+
+static void
+radeon_atom_encoder_dpms_avivo(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
+	int index = 0;
+
+	memset(&args, 0, sizeof(args));
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+		index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+		index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
+		else
+			index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
+		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
+		else
+			index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
+		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
+		else
+			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
+		break;
+	default:
+		return;
+	}
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		args.ucAction = ATOM_ENABLE;
+		/* workaround for DVOOutputControl on some RS690 systems */
+		if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
+			u32 reg = RREG32(RADEON_BIOS_3_SCRATCH);
+			WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
+			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+			WREG32(RADEON_BIOS_3_SCRATCH, reg);
+		} else
+			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+			args.ucAction = ATOM_LCD_BLON;
+			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+		}
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		args.ucAction = ATOM_DISABLE;
+		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+			args.ucAction = ATOM_LCD_BLOFF;
+			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+		}
+		break;
+	}
+}
+
+static void
+radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+	struct radeon_connector *radeon_connector = NULL;
+	struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
+
+	if (connector) {
+		radeon_connector = to_radeon_connector(connector);
+		radeon_dig_connector = radeon_connector->con_priv;
+	}
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		/* some early dce3.2 boards have a bug in their transmitter control table */
+		if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730))
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+		else
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
+		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
+			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+				atombios_set_edp_panel_power(connector,
+							     ATOM_TRANSMITTER_ACTION_POWER_ON);
+				radeon_dig_connector->edp_on = true;
+			}
+			if (ASIC_IS_DCE4(rdev))
+				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
+			radeon_dp_link_train(encoder, connector);
+			if (ASIC_IS_DCE4(rdev))
+				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
+		}
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
+		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
+			if (ASIC_IS_DCE4(rdev))
+				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
+			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+				atombios_set_edp_panel_power(connector,
+							     ATOM_TRANSMITTER_ACTION_POWER_OFF);
+				radeon_dig_connector->edp_on = false;
+			}
+		}
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
+		break;
+	}
+}
+
+static void
+radeon_atom_encoder_dpms_ext(struct drm_encoder *encoder,
+			     struct drm_encoder *ext_encoder,
+			     int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+	default:
+		if (ASIC_IS_DCE41(rdev)) {
+			atombios_external_encoder_setup(encoder, ext_encoder,
+							EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
+			atombios_external_encoder_setup(encoder, ext_encoder,
+							EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
+		} else
+			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		if (ASIC_IS_DCE41(rdev)) {
+			atombios_external_encoder_setup(encoder, ext_encoder,
+							EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
+			atombios_external_encoder_setup(encoder, ext_encoder,
+							EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
+		} else
+			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
+		break;
+	}
+}
+
+static void
+radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+
+	DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
+		  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
+		  radeon_encoder->active_device);
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		radeon_atom_encoder_dpms_avivo(encoder, mode);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		radeon_atom_encoder_dpms_dig(encoder, mode);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+		if (ASIC_IS_DCE5(rdev)) {
+			switch (mode) {
+			case DRM_MODE_DPMS_ON:
+				atombios_dvo_setup(encoder, ATOM_ENABLE);
+				break;
+			case DRM_MODE_DPMS_STANDBY:
+			case DRM_MODE_DPMS_SUSPEND:
+			case DRM_MODE_DPMS_OFF:
+				atombios_dvo_setup(encoder, ATOM_DISABLE);
+				break;
+			}
+		} else if (ASIC_IS_DCE3(rdev))
+			radeon_atom_encoder_dpms_dig(encoder, mode);
+		else
+			radeon_atom_encoder_dpms_avivo(encoder, mode);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+		if (ASIC_IS_DCE5(rdev)) {
+			switch (mode) {
+			case DRM_MODE_DPMS_ON:
+				atombios_dac_setup(encoder, ATOM_ENABLE);
+				break;
+			case DRM_MODE_DPMS_STANDBY:
+			case DRM_MODE_DPMS_SUSPEND:
+			case DRM_MODE_DPMS_OFF:
+				atombios_dac_setup(encoder, ATOM_DISABLE);
+				break;
+			}
+		} else
+			radeon_atom_encoder_dpms_avivo(encoder, mode);
+		break;
+	default:
+		return;
+	}
+
+	if (ext_encoder)
+		radeon_atom_encoder_dpms_ext(encoder, ext_encoder, mode);
+
+	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+
+}
+
+union crtc_source_param {
+	SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
+	SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
+};
+
+static void
+atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+	union crtc_source_param args;
+	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
+	uint8_t frev, crev;
+	struct radeon_encoder_atom_dig *dig;
+
+	memset(&args, 0, sizeof(args));
+
+	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+		return;
+
+	switch (frev) {
+	case 1:
+		switch (crev) {
+		case 1:
+		default:
+			if (ASIC_IS_AVIVO(rdev))
+				args.v1.ucCRTC = radeon_crtc->crtc_id;
+			else {
+				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) {
+					args.v1.ucCRTC = radeon_crtc->crtc_id;
+				} else {
+					args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
+				}
+			}
+			switch (radeon_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+				args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+			case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+				if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
+					args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
+				else
+					args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+			case ENCODER_OBJECT_ID_INTERNAL_DDI:
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+				args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
+				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
+				else
+					args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
+				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
+				else
+					args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
+				break;
+			}
+			break;
+		case 2:
+			args.v2.ucCRTC = radeon_crtc->crtc_id;
+			if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) {
+				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+
+				if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
+					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
+				else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA)
+					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT;
+				else
+					args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
+			} else
+				args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
+			switch (radeon_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+				dig = radeon_encoder->enc_priv;
+				switch (dig->dig_encoder) {
+				case 0:
+					args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
+					break;
+				case 1:
+					args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
+					break;
+				case 2:
+					args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
+					break;
+				case 3:
+					args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
+					break;
+				case 4:
+					args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
+					break;
+				case 5:
+					args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
+					break;
+				}
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+				args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+				else
+					args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+				else
+					args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
+				break;
+			}
+			break;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
+		return;
+	}
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+	/* update scratch regs with new routing */
+	radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
+}
+
+static void
+atombios_apply_encoder_quirks(struct drm_encoder *encoder,
+			      struct drm_display_mode *mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+
+	/* Funky macbooks */
+	if ((dev->pdev->device == 0x71C5) &&
+	    (dev->pdev->subsystem_vendor == 0x106b) &&
+	    (dev->pdev->subsystem_device == 0x0080)) {
+		if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
+			uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
+
+			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
+			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
+
+			WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
+		}
+	}
+
+	/* set scaler clears this on some chips */
+	if (ASIC_IS_AVIVO(rdev) &&
+	    (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) {
+		if (ASIC_IS_DCE4(rdev)) {
+			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,
+				       EVERGREEN_INTERLEAVE_EN);
+			else
+				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
+		} else {
+			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
+				       AVIVO_D1MODE_INTERLEAVE_EN);
+			else
+				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
+		}
+	}
+}
+
+static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_encoder *test_encoder;
+	struct radeon_encoder_atom_dig *dig;
+	uint32_t dig_enc_in_use = 0;
+
+	/* DCE4/5 */
+	if (ASIC_IS_DCE4(rdev)) {
+		dig = radeon_encoder->enc_priv;
+		if (ASIC_IS_DCE41(rdev)) {
+			/* ontario follows DCE4 */
+			if (rdev->family == CHIP_PALM) {
+				if (dig->linkb)
+					return 1;
+				else
+					return 0;
+			} else
+				/* llano follows DCE3.2 */
+				return radeon_crtc->crtc_id;
+		} else {
+			switch (radeon_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+				if (dig->linkb)
+					return 1;
+				else
+					return 0;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+				if (dig->linkb)
+					return 3;
+				else
+					return 2;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+				if (dig->linkb)
+					return 5;
+				else
+					return 4;
+				break;
+			}
+		}
+	}
+
+	/* on DCE32 and encoder can driver any block so just crtc id */
+	if (ASIC_IS_DCE32(rdev)) {
+		return radeon_crtc->crtc_id;
+	}
+
+	/* on DCE3 - LVTMA can only be driven by DIGB */
+	list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
+		struct radeon_encoder *radeon_test_encoder;
+
+		if (encoder == test_encoder)
+			continue;
+
+		if (!radeon_encoder_is_digital(test_encoder))
+			continue;
+
+		radeon_test_encoder = to_radeon_encoder(test_encoder);
+		dig = radeon_test_encoder->enc_priv;
+
+		if (dig->dig_encoder >= 0)
+			dig_enc_in_use |= (1 << dig->dig_encoder);
+	}
+
+	if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) {
+		if (dig_enc_in_use & 0x2)
+			DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n");
+		return 1;
+	}
+	if (!(dig_enc_in_use & 1))
+		return 0;
+	return 1;
+}
+
+/* This only needs to be called once at startup */
+void
+radeon_atom_encoder_init(struct radeon_device *rdev)
+{
+	struct drm_device *dev = rdev->ddev;
+	struct drm_encoder *encoder;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+		struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+
+		switch (radeon_encoder->encoder_id) {
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
+			break;
+		default:
+			break;
+		}
+
+		if (ext_encoder && ASIC_IS_DCE41(rdev))
+			atombios_external_encoder_setup(encoder, ext_encoder,
+							EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
+	}
+}
+
+static void
+radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
+			     struct drm_display_mode *mode,
+			     struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+
+	radeon_encoder->pixel_clock = adjusted_mode->clock;
+
+	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
+		if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
+			atombios_yuv_setup(encoder, true);
+		else
+			atombios_yuv_setup(encoder, false);
+	}
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		if (ASIC_IS_DCE4(rdev)) {
+			/* disable the transmitter */
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+			/* setup and enable the encoder */
+			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
+
+			/* enable the transmitter */
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+		} else {
+			/* disable the encoder and transmitter */
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
+
+			/* setup and enable the encoder and transmitter */
+			atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+		}
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+		atombios_dvo_setup(encoder, ATOM_ENABLE);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		atombios_dac_setup(encoder, ATOM_ENABLE);
+		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
+			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
+				atombios_tv_setup(encoder, ATOM_ENABLE);
+			else
+				atombios_tv_setup(encoder, ATOM_DISABLE);
+		}
+		break;
+	}
+
+	if (ext_encoder) {
+		if (ASIC_IS_DCE41(rdev))
+			atombios_external_encoder_setup(encoder, ext_encoder,
+							EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
+		else
+			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
+	}
+
+	atombios_apply_encoder_quirks(encoder, adjusted_mode);
+
+	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
+		r600_hdmi_enable(encoder);
+		r600_hdmi_setmode(encoder, adjusted_mode);
+	}
+}
+
+static bool
+atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
+				       ATOM_DEVICE_CV_SUPPORT |
+				       ATOM_DEVICE_CRT_SUPPORT)) {
+		DAC_LOAD_DETECTION_PS_ALLOCATION args;
+		int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
+		uint8_t frev, crev;
+
+		memset(&args, 0, sizeof(args));
+
+		if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+			return false;
+
+		args.sDacload.ucMisc = 0;
+
+		if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
+		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
+			args.sDacload.ucDacType = ATOM_DAC_A;
+		else
+			args.sDacload.ucDacType = ATOM_DAC_B;
+
+		if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
+			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
+		else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
+			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
+		else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
+			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
+			if (crev >= 3)
+				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
+		} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
+			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
+			if (crev >= 3)
+				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
+		}
+
+		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+		return true;
+	} else
+		return false;
+}
+
+static enum drm_connector_status
+radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	uint32_t bios_0_scratch;
+
+	if (!atombios_dac_load_detect(encoder, connector)) {
+		DRM_DEBUG_KMS("detect returned false \n");
+		return connector_status_unknown;
+	}
+
+	if (rdev->family >= CHIP_R600)
+		bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
+	else
+		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
+
+	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
+	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
+		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
+			return connector_status_connected;
+	}
+	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
+		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
+			return connector_status_connected;
+	}
+	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
+		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
+			return connector_status_connected;
+	}
+	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
+		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
+			return connector_status_connected; /* CTV */
+		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
+			return connector_status_connected; /* STV */
+	}
+	return connector_status_disconnected;
+}
+
+static enum drm_connector_status
+radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+	u32 bios_0_scratch;
+
+	if (!ASIC_IS_DCE4(rdev))
+		return connector_status_unknown;
+
+	if (!ext_encoder)
+		return connector_status_unknown;
+
+	if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0)
+		return connector_status_unknown;
+
+	/* load detect on the dp bridge */
+	atombios_external_encoder_setup(encoder, ext_encoder,
+					EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
+
+	bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
+
+	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
+	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
+		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
+			return connector_status_connected;
+	}
+	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
+		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
+			return connector_status_connected;
+	}
+	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
+		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
+			return connector_status_connected;
+	}
+	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
+		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
+			return connector_status_connected; /* CTV */
+		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
+			return connector_status_connected; /* STV */
+	}
+	return connector_status_disconnected;
+}
+
+void
+radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder)
+{
+	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+
+	if (ext_encoder)
+		/* ddc_setup on the dp bridge */
+		atombios_external_encoder_setup(encoder, ext_encoder,
+						EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
+
+}
+
+static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+
+	if ((radeon_encoder->active_device &
+	     (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
+	    (radeon_encoder_get_dp_bridge_encoder_id(encoder) !=
+	     ENCODER_OBJECT_ID_NONE)) {
+		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+		if (dig)
+			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
+	}
+
+	radeon_atom_output_lock(encoder, true);
+	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+
+	if (connector) {
+		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+		/* select the clock/data port if it uses a router */
+		if (radeon_connector->router.cd_valid)
+			radeon_router_select_cd_port(radeon_connector);
+
+		/* turn eDP panel on for mode set */
+		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+			atombios_set_edp_panel_power(connector,
+						     ATOM_TRANSMITTER_ACTION_POWER_ON);
+	}
+
+	/* this is needed for the pll/ss setup to work correctly in some cases */
+	atombios_set_encoder_crtc_source(encoder);
+}
+
+static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
+{
+	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
+	radeon_atom_output_lock(encoder, false);
+}
+
+static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig;
+
+	/* check for pre-DCE3 cards with shared encoders;
+	 * can't really use the links individually, so don't disable
+	 * the encoder if it's in use by another connector
+	 */
+	if (!ASIC_IS_DCE3(rdev)) {
+		struct drm_encoder *other_encoder;
+		struct radeon_encoder *other_radeon_encoder;
+
+		list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
+			other_radeon_encoder = to_radeon_encoder(other_encoder);
+			if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) &&
+			    drm_helper_encoder_in_use(other_encoder))
+				goto disable_done;
+		}
+	}
+
+	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		if (ASIC_IS_DCE4(rdev))
+			/* disable the transmitter */
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+		else {
+			/* disable the encoder and transmitter */
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
+		}
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+		atombios_dvo_setup(encoder, ATOM_DISABLE);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		atombios_dac_setup(encoder, ATOM_DISABLE);
+		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
+			atombios_tv_setup(encoder, ATOM_DISABLE);
+		break;
+	}
+
+disable_done:
+	if (radeon_encoder_is_digital(encoder)) {
+		if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
+			r600_hdmi_disable(encoder);
+		dig = radeon_encoder->enc_priv;
+		dig->dig_encoder = -1;
+	}
+	radeon_encoder->active_device = 0;
+}
+
+/* these are handled by the primary encoders */
+static void radeon_atom_ext_prepare(struct drm_encoder *encoder)
+{
+
+}
+
+static void radeon_atom_ext_commit(struct drm_encoder *encoder)
+{
+
+}
+
+static void
+radeon_atom_ext_mode_set(struct drm_encoder *encoder,
+			 struct drm_display_mode *mode,
+			 struct drm_display_mode *adjusted_mode)
+{
+
+}
+
+static void radeon_atom_ext_disable(struct drm_encoder *encoder)
+{
+
+}
+
+static void
+radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode)
+{
+
+}
+
+static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder,
+				       struct drm_display_mode *mode,
+				       struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = {
+	.dpms = radeon_atom_ext_dpms,
+	.mode_fixup = radeon_atom_ext_mode_fixup,
+	.prepare = radeon_atom_ext_prepare,
+	.mode_set = radeon_atom_ext_mode_set,
+	.commit = radeon_atom_ext_commit,
+	.disable = radeon_atom_ext_disable,
+	/* no detect for TMDS/LVDS yet */
+};
+
+static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
+	.dpms = radeon_atom_encoder_dpms,
+	.mode_fixup = radeon_atom_mode_fixup,
+	.prepare = radeon_atom_encoder_prepare,
+	.mode_set = radeon_atom_encoder_mode_set,
+	.commit = radeon_atom_encoder_commit,
+	.disable = radeon_atom_encoder_disable,
+	.detect = radeon_atom_dig_detect,
+};
+
+static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
+	.dpms = radeon_atom_encoder_dpms,
+	.mode_fixup = radeon_atom_mode_fixup,
+	.prepare = radeon_atom_encoder_prepare,
+	.mode_set = radeon_atom_encoder_mode_set,
+	.commit = radeon_atom_encoder_commit,
+	.detect = radeon_atom_dac_detect,
+};
+
+void radeon_enc_destroy(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	kfree(radeon_encoder->enc_priv);
+	drm_encoder_cleanup(encoder);
+	kfree(radeon_encoder);
+}
+
+static const struct drm_encoder_funcs radeon_atom_enc_funcs = {
+	.destroy = radeon_enc_destroy,
+};
+
+struct radeon_encoder_atom_dac *
+radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
+{
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
+
+	if (!dac)
+		return NULL;
+
+	dac->tv_std = radeon_atombios_get_tv_info(rdev);
+	return dac;
+}
+
+struct radeon_encoder_atom_dig *
+radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
+{
+	int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
+	struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
+
+	if (!dig)
+		return NULL;
+
+	/* coherent mode by default */
+	dig->coherent_mode = true;
+	dig->dig_encoder = -1;
+
+	if (encoder_enum == 2)
+		dig->linkb = true;
+	else
+		dig->linkb = false;
+
+	return dig;
+}
+
+void
+radeon_add_atom_encoder(struct drm_device *dev,
+			uint32_t encoder_enum,
+			uint32_t supported_device,
+			u16 caps)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_encoder *encoder;
+	struct radeon_encoder *radeon_encoder;
+
+	/* see if we already added it */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		radeon_encoder = to_radeon_encoder(encoder);
+		if (radeon_encoder->encoder_enum == encoder_enum) {
+			radeon_encoder->devices |= supported_device;
+			return;
+		}
+
+	}
+
+	/* add a new one */
+	radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
+	if (!radeon_encoder)
+		return;
+
+	encoder = &radeon_encoder->base;
+	switch (rdev->num_crtc) {
+	case 1:
+		encoder->possible_crtcs = 0x1;
+		break;
+	case 2:
+	default:
+		encoder->possible_crtcs = 0x3;
+		break;
+	case 4:
+		encoder->possible_crtcs = 0xf;
+		break;
+	case 6:
+		encoder->possible_crtcs = 0x3f;
+		break;
+	}
+
+	radeon_encoder->enc_priv = NULL;
+
+	radeon_encoder->encoder_enum = encoder_enum;
+	radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
+	radeon_encoder->devices = supported_device;
+	radeon_encoder->rmx_type = RMX_OFF;
+	radeon_encoder->underscan_type = UNDERSCAN_OFF;
+	radeon_encoder->is_ext_encoder = false;
+	radeon_encoder->caps = caps;
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+			radeon_encoder->rmx_type = RMX_FULL;
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
+			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
+		} else {
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
+			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
+		}
+		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
+		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
+		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
+		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
+		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+			radeon_encoder->rmx_type = RMX_FULL;
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
+			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
+		} else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
+			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
+		} else {
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
+			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
+		}
+		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
+		break;
+	case ENCODER_OBJECT_ID_SI170B:
+	case ENCODER_OBJECT_ID_CH7303:
+	case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
+	case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
+	case ENCODER_OBJECT_ID_TITFP513:
+	case ENCODER_OBJECT_ID_VT1623:
+	case ENCODER_OBJECT_ID_HDMI_SI1930:
+	case ENCODER_OBJECT_ID_TRAVIS:
+	case ENCODER_OBJECT_ID_NUTMEG:
+		/* these are handled by the primary encoders */
+		radeon_encoder->is_ext_encoder = true;
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
+		else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
+		else
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
+		drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs);
+		break;
+	}
+}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/evergreen_blit_kms.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/evergreen_blit_kms.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/evergreen_blit_kms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/evergreen_blit_kms.c	2012-01-04 18:55:44.000000000 -0500
@@ -56,7 +56,9 @@
 	if (h < 8)
 		h = 8;
 
-	cb_color_info = ((format << 2) | (1 << 24) | (1 << 8));
+	cb_color_info = CB_FORMAT(format) |
+		CB_SOURCE_FORMAT(CB_SF_EXPORT_NORM) |
+		CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
 	pitch = (w / 8) - 1;
 	slice = ((w * h) / 64) - 1;
 
@@ -67,7 +69,7 @@
 	radeon_ring_write(rdev, slice);
 	radeon_ring_write(rdev, 0);
 	radeon_ring_write(rdev, cb_color_info);
-	radeon_ring_write(rdev, (1 << 4));
+	radeon_ring_write(rdev, 0);
 	radeon_ring_write(rdev, (w - 1) | ((h - 1) << 16));
 	radeon_ring_write(rdev, 0);
 	radeon_ring_write(rdev, 0);
@@ -92,6 +94,15 @@
 	else
 		cp_coher_size = ((size + 255) >> 8);
 
+	if (rdev->family >= CHIP_CAYMAN) {
+		/* CP_COHER_CNTL2 has to be set manually when submitting a surface_sync
+		 * to the RB directly. For IBs, the CP programs this as part of the
+		 * surface_sync packet.
+		 */
+		radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
+		radeon_ring_write(rdev, (0x85e8 - PACKET3_SET_CONFIG_REG_START) >> 2);
+		radeon_ring_write(rdev, 0); /* CP_COHER_CNTL2 */
+	}
 	radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3));
 	radeon_ring_write(rdev, sync_type);
 	radeon_ring_write(rdev, cp_coher_size);
@@ -133,12 +144,16 @@
 	u32 sq_vtx_constant_word2, sq_vtx_constant_word3;
 
 	/* high addr, stride */
-	sq_vtx_constant_word2 = ((upper_32_bits(gpu_addr) & 0xff) | (16 << 8));
+	sq_vtx_constant_word2 = SQ_VTXC_BASE_ADDR_HI(upper_32_bits(gpu_addr) & 0xff) |
+		SQ_VTXC_STRIDE(16);
 #ifdef __BIG_ENDIAN
-	sq_vtx_constant_word2 |= (2 << 30);
+	sq_vtx_constant_word2 |= SQ_VTXC_ENDIAN_SWAP(SQ_ENDIAN_8IN32);
 #endif
 	/* xyzw swizzles */
-	sq_vtx_constant_word3 = (0 << 3) | (1 << 6) | (2 << 9) | (3 << 12);
+	sq_vtx_constant_word3 = SQ_VTCX_SEL_X(SQ_SEL_X) |
+		SQ_VTCX_SEL_Y(SQ_SEL_Y) |
+		SQ_VTCX_SEL_Z(SQ_SEL_Z) |
+		SQ_VTCX_SEL_W(SQ_SEL_W);
 
 	radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 8));
 	radeon_ring_write(rdev, 0x580);
@@ -149,7 +164,7 @@
 	radeon_ring_write(rdev, 0);
 	radeon_ring_write(rdev, 0);
 	radeon_ring_write(rdev, 0);
-	radeon_ring_write(rdev, SQ_TEX_VTX_VALID_BUFFER << 30);
+	radeon_ring_write(rdev, S__SQ_CONSTANT_TYPE(SQ_TEX_VTX_VALID_BUFFER));
 
 	if ((rdev->family == CHIP_CEDAR) ||
 	    (rdev->family == CHIP_PALM) ||
@@ -168,7 +183,7 @@
 static void
 set_tex_resource(struct radeon_device *rdev,
 		 int format, int w, int h, int pitch,
-		 u64 gpu_addr)
+		 u64 gpu_addr, u32 size)
 {
 	u32 sq_tex_resource_word0, sq_tex_resource_word1;
 	u32 sq_tex_resource_word4, sq_tex_resource_word7;
@@ -176,14 +191,22 @@
 	if (h < 1)
 		h = 1;
 
-	sq_tex_resource_word0 = (1 << 0); /* 2D */
+	sq_tex_resource_word0 = TEX_DIM(SQ_TEX_DIM_2D);
 	sq_tex_resource_word0 |= ((((pitch >> 3) - 1) << 6) |
 				  ((w - 1) << 18));
-	sq_tex_resource_word1 = ((h - 1) << 0) | (1 << 28);
+	sq_tex_resource_word1 = ((h - 1) << 0) |
+				TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
 	/* xyzw swizzles */
-	sq_tex_resource_word4 = (0 << 16) | (1 << 19) | (2 << 22) | (3 << 25);
+	sq_tex_resource_word4 = TEX_DST_SEL_X(SQ_SEL_X) |
+				TEX_DST_SEL_Y(SQ_SEL_Y) |
+				TEX_DST_SEL_Z(SQ_SEL_Z) |
+				TEX_DST_SEL_W(SQ_SEL_W);
 
-	sq_tex_resource_word7 = format | (SQ_TEX_VTX_VALID_TEXTURE << 30);
+	sq_tex_resource_word7 = format |
+		S__SQ_CONSTANT_TYPE(SQ_TEX_VTX_VALID_TEXTURE);
+
+	cp_set_surface_sync(rdev,
+			    PACKET3_TC_ACTION_ENA, size, gpu_addr);
 
 	radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 8));
 	radeon_ring_write(rdev, 0);
@@ -584,31 +607,6 @@
 
 }
 
-static inline uint32_t i2f(uint32_t input)
-{
-	u32 result, i, exponent, fraction;
-
-	if ((input & 0x3fff) == 0)
-		result = 0; /* 0 is a special case */
-	else {
-		exponent = 140; /* exponent biased by 127; */
-		fraction = (input & 0x3fff) << 10; /* cheat and only
-						      handle numbers below 2^^15 */
-		for (i = 0; i < 14; i++) {
-			if (fraction & 0x800000)
-				break;
-			else {
-				fraction = fraction << 1; /* keep
-							     shifting left until top bit = 1 */
-				exponent = exponent - 1;
-			}
-		}
-		result = exponent << 23 | (fraction & 0x7fffff); /* mask
-								    off top bit; assumed 1 */
-	}
-	return result;
-}
-
 int evergreen_blit_init(struct radeon_device *rdev)
 {
 	u32 obj_size;
@@ -617,6 +615,26 @@
 	u32 packet2s[16];
 	int num_packet2s = 0;
 
+	rdev->r600_blit.primitives.set_render_target = set_render_target;
+	rdev->r600_blit.primitives.cp_set_surface_sync = cp_set_surface_sync;
+	rdev->r600_blit.primitives.set_shaders = set_shaders;
+	rdev->r600_blit.primitives.set_vtx_resource = set_vtx_resource;
+	rdev->r600_blit.primitives.set_tex_resource = set_tex_resource;
+	rdev->r600_blit.primitives.set_scissors = set_scissors;
+	rdev->r600_blit.primitives.draw_auto = draw_auto;
+	rdev->r600_blit.primitives.set_default_state = set_default_state;
+
+	rdev->r600_blit.ring_size_common = 55; /* shaders + def state */
+	rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */
+	rdev->r600_blit.ring_size_common += 5; /* done copy */
+	rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */
+
+	rdev->r600_blit.ring_size_per_loop = 74;
+	if (rdev->family >= CHIP_CAYMAN)
+		rdev->r600_blit.ring_size_per_loop += 9; /* additional DWs for surface sync */
+
+	rdev->r600_blit.max_dim = 16384;
+
 	/* pin copy shader into vram if already initialized */
 	if (rdev->r600_blit.shader_obj)
 		goto done;
@@ -712,277 +730,3 @@
 	radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
 	return 0;
 }
-
-void evergreen_blit_fini(struct radeon_device *rdev)
-{
-	int r;
-
-	radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
-	if (rdev->r600_blit.shader_obj == NULL)
-		return;
-	/* If we can't reserve the bo, unref should be enough to destroy
-	 * it when it becomes idle.
-	 */
-	r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
-	if (!r) {
-		radeon_bo_unpin(rdev->r600_blit.shader_obj);
-		radeon_bo_unreserve(rdev->r600_blit.shader_obj);
-	}
-	radeon_bo_unref(&rdev->r600_blit.shader_obj);
-}
-
-static int evergreen_vb_ib_get(struct radeon_device *rdev)
-{
-	int r;
-	r = radeon_ib_get(rdev, &rdev->r600_blit.vb_ib);
-	if (r) {
-		DRM_ERROR("failed to get IB for vertex buffer\n");
-		return r;
-	}
-
-	rdev->r600_blit.vb_total = 64*1024;
-	rdev->r600_blit.vb_used = 0;
-	return 0;
-}
-
-static void evergreen_vb_ib_put(struct radeon_device *rdev)
-{
-	radeon_fence_emit(rdev, rdev->r600_blit.vb_ib->fence);
-	radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
-}
-
-int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes)
-{
-	int r;
-	int ring_size, line_size;
-	int max_size;
-	/* loops of emits + fence emit possible */
-	int dwords_per_loop = 74, num_loops;
-
-	r = evergreen_vb_ib_get(rdev);
-	if (r)
-		return r;
-
-	/* 8 bpp vs 32 bpp for xfer unit */
-	if (size_bytes & 3)
-		line_size = 8192;
-	else
-		line_size = 8192 * 4;
-
-	max_size = 8192 * line_size;
-
-	/* major loops cover the max size transfer */
-	num_loops = ((size_bytes + max_size) / max_size);
-	/* minor loops cover the extra non aligned bits */
-	num_loops += ((size_bytes % line_size) ? 1 : 0);
-	/* calculate number of loops correctly */
-	ring_size = num_loops * dwords_per_loop;
-	/* set default  + shaders */
-	ring_size += 55; /* shaders + def state */
-	ring_size += 10; /* fence emit for VB IB */
-	ring_size += 5; /* done copy */
-	ring_size += 10; /* fence emit for done copy */
-	r = radeon_ring_lock(rdev, ring_size);
-	if (r)
-		return r;
-
-	set_default_state(rdev); /* 36 */
-	set_shaders(rdev); /* 16 */
-	return 0;
-}
-
-void evergreen_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence)
-{
-	int r;
-
-	if (rdev->r600_blit.vb_ib)
-		evergreen_vb_ib_put(rdev);
-
-	if (fence)
-		r = radeon_fence_emit(rdev, fence);
-
-	radeon_ring_unlock_commit(rdev);
-}
-
-void evergreen_kms_blit_copy(struct radeon_device *rdev,
-			     u64 src_gpu_addr, u64 dst_gpu_addr,
-			     int size_bytes)
-{
-	int max_bytes;
-	u64 vb_gpu_addr;
-	u32 *vb;
-
-	DRM_DEBUG("emitting copy %16llx %16llx %d %d\n", src_gpu_addr, dst_gpu_addr,
-		  size_bytes, rdev->r600_blit.vb_used);
-	vb = (u32 *)(rdev->r600_blit.vb_ib->ptr + rdev->r600_blit.vb_used);
-	if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) {
-		max_bytes = 8192;
-
-		while (size_bytes) {
-			int cur_size = size_bytes;
-			int src_x = src_gpu_addr & 255;
-			int dst_x = dst_gpu_addr & 255;
-			int h = 1;
-			src_gpu_addr = src_gpu_addr & ~255ULL;
-			dst_gpu_addr = dst_gpu_addr & ~255ULL;
-
-			if (!src_x && !dst_x) {
-				h = (cur_size / max_bytes);
-				if (h > 8192)
-					h = 8192;
-				if (h == 0)
-					h = 1;
-				else
-					cur_size = max_bytes;
-			} else {
-				if (cur_size > max_bytes)
-					cur_size = max_bytes;
-				if (cur_size > (max_bytes - dst_x))
-					cur_size = (max_bytes - dst_x);
-				if (cur_size > (max_bytes - src_x))
-					cur_size = (max_bytes - src_x);
-			}
-
-			if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
-				WARN_ON(1);
-			}
-
-			vb[0] = i2f(dst_x);
-			vb[1] = 0;
-			vb[2] = i2f(src_x);
-			vb[3] = 0;
-
-			vb[4] = i2f(dst_x);
-			vb[5] = i2f(h);
-			vb[6] = i2f(src_x);
-			vb[7] = i2f(h);
-
-			vb[8] = i2f(dst_x + cur_size);
-			vb[9] = i2f(h);
-			vb[10] = i2f(src_x + cur_size);
-			vb[11] = i2f(h);
-
-			/* src 10 */
-			set_tex_resource(rdev, FMT_8,
-					 src_x + cur_size, h, src_x + cur_size,
-					 src_gpu_addr);
-
-			/* 5 */
-			cp_set_surface_sync(rdev,
-					    PACKET3_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
-
-
-			/* dst 17 */
-			set_render_target(rdev, COLOR_8,
-					  dst_x + cur_size, h,
-					  dst_gpu_addr);
-
-			/* scissors 12 */
-			set_scissors(rdev, dst_x, 0, dst_x + cur_size, h);
-
-			/* 15 */
-			vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
-			set_vtx_resource(rdev, vb_gpu_addr);
-
-			/* draw 10 */
-			draw_auto(rdev);
-
-			/* 5 */
-			cp_set_surface_sync(rdev,
-					    PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
-					    cur_size * h, dst_gpu_addr);
-
-			vb += 12;
-			rdev->r600_blit.vb_used += 12 * 4;
-
-			src_gpu_addr += cur_size * h;
-			dst_gpu_addr += cur_size * h;
-			size_bytes -= cur_size * h;
-		}
-	} else {
-		max_bytes = 8192 * 4;
-
-		while (size_bytes) {
-			int cur_size = size_bytes;
-			int src_x = (src_gpu_addr & 255);
-			int dst_x = (dst_gpu_addr & 255);
-			int h = 1;
-			src_gpu_addr = src_gpu_addr & ~255ULL;
-			dst_gpu_addr = dst_gpu_addr & ~255ULL;
-
-			if (!src_x && !dst_x) {
-				h = (cur_size / max_bytes);
-				if (h > 8192)
-					h = 8192;
-				if (h == 0)
-					h = 1;
-				else
-					cur_size = max_bytes;
-			} else {
-				if (cur_size > max_bytes)
-					cur_size = max_bytes;
-				if (cur_size > (max_bytes - dst_x))
-					cur_size = (max_bytes - dst_x);
-				if (cur_size > (max_bytes - src_x))
-					cur_size = (max_bytes - src_x);
-			}
-
-			if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
-				WARN_ON(1);
-			}
-
-			vb[0] = i2f(dst_x / 4);
-			vb[1] = 0;
-			vb[2] = i2f(src_x / 4);
-			vb[3] = 0;
-
-			vb[4] = i2f(dst_x / 4);
-			vb[5] = i2f(h);
-			vb[6] = i2f(src_x / 4);
-			vb[7] = i2f(h);
-
-			vb[8] = i2f((dst_x + cur_size) / 4);
-			vb[9] = i2f(h);
-			vb[10] = i2f((src_x + cur_size) / 4);
-			vb[11] = i2f(h);
-
-			/* src 10 */
-			set_tex_resource(rdev, FMT_8_8_8_8,
-					 (src_x + cur_size) / 4,
-					 h, (src_x + cur_size) / 4,
-					 src_gpu_addr);
-			/* 5 */
-			cp_set_surface_sync(rdev,
-					    PACKET3_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
-
-			/* dst 17 */
-			set_render_target(rdev, COLOR_8_8_8_8,
-					  (dst_x + cur_size) / 4, h,
-					  dst_gpu_addr);
-
-			/* scissors 12  */
-			set_scissors(rdev, (dst_x / 4), 0, (dst_x + cur_size / 4), h);
-
-			/* Vertex buffer setup 15 */
-			vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
-			set_vtx_resource(rdev, vb_gpu_addr);
-
-			/* draw 10 */
-			draw_auto(rdev);
-
-			/* 5 */
-			cp_set_surface_sync(rdev,
-					    PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
-					    cur_size * h, dst_gpu_addr);
-
-			/* 74 ring dwords per loop */
-			vb += 12;
-			rdev->r600_blit.vb_used += 12 * 4;
-
-			src_gpu_addr += cur_size * h;
-			dst_gpu_addr += cur_size * h;
-			size_bytes -= cur_size * h;
-		}
-	}
-}
-
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/evergreen.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/evergreen.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/evergreen.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/evergreen.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,7 +39,7 @@
 
 static void evergreen_gpu_init(struct radeon_device *rdev);
 void evergreen_fini(struct radeon_device *rdev);
-static void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
+void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
 
 void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
 {
@@ -82,6 +82,7 @@
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset);
+	int i;
 
 	/* Lock the graphics update lock */
 	tmp |= EVERGREEN_GRPH_UPDATE_LOCK;
@@ -99,7 +100,11 @@
 	       (u32)crtc_base);
 
 	/* Wait for update_pending to go high. */
-	while (!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING));
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)
+			break;
+		udelay(1);
+	}
 	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
 
 	/* Unlock the lock, so double-buffering can take place inside vblank */
@@ -157,6 +162,57 @@
 	return actual_temp * 1000;
 }
 
+void sumo_pm_init_profile(struct radeon_device *rdev)
+{
+	int idx;
+
+	/* default */
+	rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
+	rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+	rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
+
+	/* low,mid sh/mh */
+	if (rdev->flags & RADEON_IS_MOBILITY)
+		idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
+	else
+		idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+
+	rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+
+	rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+
+	rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
+
+	rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
+
+	/* high sh/mh */
+	idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+	rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx =
+		rdev->pm.power_state[idx].num_clock_modes - 1;
+
+	rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx;
+	rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx =
+		rdev->pm.power_state[idx].num_clock_modes - 1;
+}
+
 void evergreen_pm_misc(struct radeon_device *rdev)
 {
 	int req_ps_idx = rdev->pm.requested_power_state_index;
@@ -353,6 +409,7 @@
 		default:
 			break;
 		}
+		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
 	}
 	if (rdev->irq.installed)
 		evergreen_irq_set(rdev);
@@ -893,7 +950,7 @@
 	u32 tmp;
 	int r;
 
-	if (rdev->gart.table.vram.robj == NULL) {
+	if (rdev->gart.robj == NULL) {
 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
 		return -EINVAL;
 	}
@@ -935,6 +992,9 @@
 	WREG32(VM_CONTEXT1_CNTL, 0);
 
 	evergreen_pcie_gart_tlb_flush(rdev);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+		 (unsigned)(rdev->mc.gtt_size >> 20),
+		 (unsigned long long)rdev->gart.table_addr);
 	rdev->gart.ready = true;
 	return 0;
 }
@@ -942,7 +1002,6 @@
 void evergreen_pcie_gart_disable(struct radeon_device *rdev)
 {
 	u32 tmp;
-	int r;
 
 	/* Disable all tables */
 	WREG32(VM_CONTEXT0_CNTL, 0);
@@ -962,14 +1021,7 @@
 	WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
 	WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
 	WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
-	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);
-		}
-	}
+	radeon_gart_table_vram_unpin(rdev);
 }
 
 void evergreen_pcie_gart_fini(struct radeon_device *rdev)
@@ -1223,7 +1275,7 @@
 		WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
 			rdev->mc.vram_end >> 12);
 	}
-	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
+	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12);
 	if (rdev->flags & RADEON_IS_IGP) {
 		tmp = RREG32(MC_FUS_VM_FB_OFFSET) & 0x000FFFFF;
 		tmp |= ((rdev->mc.vram_end >> 20) & 0xF) << 24;
@@ -2586,7 +2638,7 @@
 	return 0;
 }
 
-static inline void evergreen_irq_ack(struct radeon_device *rdev)
+static void evergreen_irq_ack(struct radeon_device *rdev)
 {
 	u32 tmp;
 
@@ -2697,7 +2749,7 @@
 	r600_rlc_stop(rdev);
 }
 
-static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev)
+static u32 evergreen_get_ih_wptr(struct radeon_device *rdev)
 {
 	u32 wptr, tmp;
 
@@ -3003,8 +3055,7 @@
 	int r;
 
 	/* enable pcie gen2 link */
-	if (!ASIC_IS_DCE5(rdev))
-		evergreen_pcie_gen2_enable(rdev);
+	evergreen_pcie_gen2_enable(rdev);
 
 	if (ASIC_IS_DCE5(rdev)) {
 		if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
@@ -3029,6 +3080,10 @@
 		}
 	}
 
+	r = r600_vram_scratch_init(rdev);
+	if (r)
+		return r;
+
 	evergreen_mc_program(rdev);
 	if (rdev->flags & RADEON_IS_AGP) {
 		evergreen_agp_enable(rdev);
@@ -3041,7 +3096,7 @@
 
 	r = evergreen_blit_init(rdev);
 	if (r) {
-		evergreen_blit_fini(rdev);
+		r600_blit_fini(rdev);
 		rdev->asic->copy = NULL;
 		dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
 	}
@@ -3107,45 +3162,14 @@
 
 int evergreen_suspend(struct radeon_device *rdev)
 {
-	int r;
-
 	/* FIXME: we should wait for ring to be empty */
 	r700_cp_stop(rdev);
 	rdev->cp.ready = false;
 	evergreen_irq_suspend(rdev);
 	radeon_wb_disable(rdev);
 	evergreen_pcie_gart_disable(rdev);
+	r600_blit_suspend(rdev);
 
-	/* 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);
-	}
-
-	return 0;
-}
-
-int evergreen_copy_blit(struct radeon_device *rdev,
-			uint64_t src_offset,
-			uint64_t dst_offset,
-			unsigned num_gpu_pages,
-			struct radeon_fence *fence)
-{
-	int r;
-
-	mutex_lock(&rdev->r600_blit.mutex);
-	rdev->r600_blit.vb_ib = NULL;
-	r = evergreen_blit_prepare_copy(rdev, num_gpu_pages * RADEON_GPU_PAGE_SIZE);
-	if (r) {
-		if (rdev->r600_blit.vb_ib)
-			radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
-		mutex_unlock(&rdev->r600_blit.mutex);
-		return r;
-	}
-	evergreen_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages * RADEON_GPU_PAGE_SIZE);
-	evergreen_blit_done_copy(rdev, fence);
-	mutex_unlock(&rdev->r600_blit.mutex);
 	return 0;
 }
 
@@ -3252,18 +3276,31 @@
 			rdev->accel_working = false;
 		}
 	}
+
+	/* Don't start up if the MC ucode is missing on BTC parts.
+	 * The default clocks and voltages before the MC ucode
+	 * is loaded are not suffient for advanced operations.
+	 */
+	if (ASIC_IS_DCE5(rdev)) {
+		if (!rdev->mc_fw && !(rdev->flags & RADEON_IS_IGP)) {
+			DRM_ERROR("radeon: MC ucode required for NI+.\n");
+			return -EINVAL;
+		}
+	}
+
 	return 0;
 }
 
 void evergreen_fini(struct radeon_device *rdev)
 {
-	evergreen_blit_fini(rdev);
+	r600_blit_fini(rdev);
 	r700_cp_fini(rdev);
 	r600_irq_fini(rdev);
 	radeon_wb_fini(rdev);
 	radeon_ib_pool_fini(rdev);
 	radeon_irq_kms_fini(rdev);
 	evergreen_pcie_gart_fini(rdev);
+	r600_vram_scratch_fini(rdev);
 	radeon_gem_fini(rdev);
 	radeon_fence_driver_fini(rdev);
 	radeon_agp_fini(rdev);
@@ -3273,7 +3310,7 @@
 	rdev->bios = NULL;
 }
 
-static void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
+void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
 {
 	u32 link_width_cntl, speed_cntl;
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/evergreen_cs.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/evergreen_cs.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/evergreen_cs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/evergreen_cs.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,7 @@
 	u32			group_size;
 	u32			nbanks;
 	u32			npipes;
+	u32			row_size;
 	/* value we track */
 	u32			nsamples;
 	u32			cb_color_base_last[12];
@@ -77,6 +78,44 @@
 	struct radeon_bo	*db_s_write_bo;
 };
 
+static u32 evergreen_cs_get_aray_mode(u32 tiling_flags)
+{
+	if (tiling_flags & RADEON_TILING_MACRO)
+		return ARRAY_2D_TILED_THIN1;
+	else if (tiling_flags & RADEON_TILING_MICRO)
+		return ARRAY_1D_TILED_THIN1;
+	else
+		return ARRAY_LINEAR_GENERAL;
+}
+
+static u32 evergreen_cs_get_num_banks(u32 nbanks)
+{
+	switch (nbanks) {
+	case 2:
+		return ADDR_SURF_2_BANK;
+	case 4:
+		return ADDR_SURF_4_BANK;
+	case 8:
+	default:
+		return ADDR_SURF_8_BANK;
+	case 16:
+		return ADDR_SURF_16_BANK;
+	}
+}
+
+static u32 evergreen_cs_get_tile_split(u32 row_size)
+{
+	switch (row_size) {
+	case 1:
+	default:
+		return ADDR_SURF_TILE_SPLIT_1KB;
+	case 2:
+		return ADDR_SURF_TILE_SPLIT_2KB;
+	case 4:
+		return ADDR_SURF_TILE_SPLIT_4KB;
+	}
+}
+
 static void evergreen_cs_track_init(struct evergreen_cs_track *track)
 {
 	int i;
@@ -122,12 +161,6 @@
 	track->db_s_write_bo = NULL;
 }
 
-static inline int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
-{
-	/* XXX fill in */
-	return 0;
-}
-
 static int evergreen_cs_track_check(struct radeon_cs_parser *p)
 {
 	struct evergreen_cs_track *track = p->track;
@@ -236,28 +269,6 @@
 }
 
 /**
- * evergreen_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc
- * @parser:		parser structure holding parsing context.
- *
- * Check next packet is relocation packet3, do bo validation and compute
- * GPU offset using the provided start.
- **/
-static inline int evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
-{
-	struct radeon_cs_packet p3reloc;
-	int r;
-
-	r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
-	if (r) {
-		return 0;
-	}
-	if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
-		return 0;
-	}
-	return 1;
-}
-
-/**
  * evergreen_cs_packet_next_vline() - parse userspace VLINE packet
  * @parser:		parser structure holding parsing context.
  *
@@ -414,7 +425,7 @@
  * if register is safe. If register is not flag as safe this function
  * will test it against a list of register needind special handling.
  */
-static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
+static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
 {
 	struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track;
 	struct radeon_cs_reloc *reloc;
@@ -508,21 +519,22 @@
 		}
 		break;
 	case DB_Z_INFO:
-		r = evergreen_cs_packet_next_reloc(p, &reloc);
-		if (r) {
-			dev_warn(p->dev, "bad SET_CONTEXT_REG "
-					"0x%04X\n", reg);
-			return -EINVAL;
-		}
 		track->db_z_info = radeon_get_ib_value(p, idx);
-		ib[idx] &= ~Z_ARRAY_MODE(0xf);
-		track->db_z_info &= ~Z_ARRAY_MODE(0xf);
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
-			ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-			track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-		} else {
-			ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
-			track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+		if (!p->keep_tiling_flags) {
+			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] &= ~Z_ARRAY_MODE(0xf);
+			track->db_z_info &= ~Z_ARRAY_MODE(0xf);
+			ib[idx] |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
+			track->db_z_info |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+				ib[idx] |= DB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
+				ib[idx] |= DB_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size));
+			}
 		}
 		break;
 	case DB_STENCIL_INFO:
@@ -635,40 +647,34 @@
 	case CB_COLOR5_INFO:
 	case CB_COLOR6_INFO:
 	case CB_COLOR7_INFO:
-		r = evergreen_cs_packet_next_reloc(p, &reloc);
-		if (r) {
-			dev_warn(p->dev, "bad SET_CONTEXT_REG "
-					"0x%04X\n", reg);
-			return -EINVAL;
-		}
 		tmp = (reg - CB_COLOR0_INFO) / 0x3c;
 		track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
-			ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-			track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-		} else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
-			ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
-			track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+		if (!p->keep_tiling_flags) {
+			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] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
+			track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
 		}
 		break;
 	case CB_COLOR8_INFO:
 	case CB_COLOR9_INFO:
 	case CB_COLOR10_INFO:
 	case CB_COLOR11_INFO:
-		r = evergreen_cs_packet_next_reloc(p, &reloc);
-		if (r) {
-			dev_warn(p->dev, "bad SET_CONTEXT_REG "
-					"0x%04X\n", reg);
-			return -EINVAL;
-		}
 		tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;
 		track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
-			ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-			track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-		} else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
-			ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
-			track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+		if (!p->keep_tiling_flags) {
+			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] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
+			track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
 		}
 		break;
 	case CB_COLOR0_PITCH:
@@ -723,6 +729,16 @@
 	case CB_COLOR9_ATTRIB:
 	case CB_COLOR10_ATTRIB:
 	case CB_COLOR11_ATTRIB:
+		r = evergreen_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+					"0x%04X\n", reg);
+			return -EINVAL;
+		}
+		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+			ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
+			ib[idx] |= CB_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size));
+		}
 		break;
 	case CB_COLOR0_DIM:
 	case CB_COLOR1_DIM:
@@ -990,7 +1006,7 @@
  * This function will check that the resource has valid field and that
  * the texture and mipmap bo object are big enough to cover this resource.
  */
-static inline int evergreen_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
+static int evergreen_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
 						   struct radeon_bo *texture,
 						   struct radeon_bo *mipmap)
 {
@@ -1339,10 +1355,16 @@
 					return -EINVAL;
 				}
 				ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
-				if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-					ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-				else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-					ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+				if (!p->keep_tiling_flags) {
+					ib[idx+1+(i*8)+1] |=
+						TEX_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
+					if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+						ib[idx+1+(i*8)+6] |=
+							TEX_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size));
+						ib[idx+1+(i*8)+7] |=
+							TEX_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
+					}
+				}
 				texture = reloc->robj;
 				/* tex mip base */
 				r = evergreen_cs_packet_next_reloc(p, &reloc);
@@ -1442,6 +1464,7 @@
 {
 	struct radeon_cs_packet pkt;
 	struct evergreen_cs_track *track;
+	u32 tmp;
 	int r;
 
 	if (p->track == NULL) {
@@ -1450,9 +1473,63 @@
 		if (track == NULL)
 			return -ENOMEM;
 		evergreen_cs_track_init(track);
-		track->npipes = p->rdev->config.evergreen.tiling_npipes;
-		track->nbanks = p->rdev->config.evergreen.tiling_nbanks;
-		track->group_size = p->rdev->config.evergreen.tiling_group_size;
+		if (p->rdev->family >= CHIP_CAYMAN)
+			tmp = p->rdev->config.cayman.tile_config;
+		else
+			tmp = p->rdev->config.evergreen.tile_config;
+
+		switch (tmp & 0xf) {
+		case 0:
+			track->npipes = 1;
+			break;
+		case 1:
+		default:
+			track->npipes = 2;
+			break;
+		case 2:
+			track->npipes = 4;
+			break;
+		case 3:
+			track->npipes = 8;
+			break;
+		}
+
+		switch ((tmp & 0xf0) >> 4) {
+		case 0:
+			track->nbanks = 4;
+			break;
+		case 1:
+		default:
+			track->nbanks = 8;
+			break;
+		case 2:
+			track->nbanks = 16;
+			break;
+		}
+
+		switch ((tmp & 0xf00) >> 8) {
+		case 0:
+			track->group_size = 256;
+			break;
+		case 1:
+		default:
+			track->group_size = 512;
+			break;
+		}
+
+		switch ((tmp & 0xf000) >> 12) {
+		case 0:
+			track->row_size = 1;
+			break;
+		case 1:
+		default:
+			track->row_size = 2;
+			break;
+		case 2:
+			track->row_size = 4;
+			break;
+		}
+
 		p->track = track;
 	}
 	do {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/evergreend.h linux-libre-3.2-gnu/drivers/gpu/drm/radeon/evergreend.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/evergreend.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/evergreend.h	2012-01-04 18:55:44.000000000 -0500
@@ -899,6 +899,10 @@
 #define DB_HTILE_DATA_BASE				0x28014
 #define DB_Z_INFO					0x28040
 #       define Z_ARRAY_MODE(x)                          ((x) << 4)
+#       define DB_TILE_SPLIT(x)                         (((x) & 0x7) << 8)
+#       define DB_NUM_BANKS(x)                          (((x) & 0x3) << 12)
+#       define DB_BANK_WIDTH(x)                         (((x) & 0x3) << 16)
+#       define DB_BANK_HEIGHT(x)                        (((x) & 0x3) << 20)
 #define DB_STENCIL_INFO					0x28044
 #define DB_Z_READ_BASE					0x28048
 #define DB_STENCIL_READ_BASE				0x2804c
@@ -941,12 +945,39 @@
 #define	CB_COLOR0_SLICE					0x28c68
 #define	CB_COLOR0_VIEW					0x28c6c
 #define	CB_COLOR0_INFO					0x28c70
+#	define CB_FORMAT(x)				((x) << 2)
 #       define CB_ARRAY_MODE(x)                         ((x) << 8)
 #       define ARRAY_LINEAR_GENERAL                     0
 #       define ARRAY_LINEAR_ALIGNED                     1
 #       define ARRAY_1D_TILED_THIN1                     2
 #       define ARRAY_2D_TILED_THIN1                     4
+#	define CB_SOURCE_FORMAT(x)			((x) << 24)
+#	define CB_SF_EXPORT_FULL			0
+#	define CB_SF_EXPORT_NORM			1
 #define	CB_COLOR0_ATTRIB				0x28c74
+#       define CB_TILE_SPLIT(x)                         (((x) & 0x7) << 5)
+#       define ADDR_SURF_TILE_SPLIT_64B                 0
+#       define ADDR_SURF_TILE_SPLIT_128B                1
+#       define ADDR_SURF_TILE_SPLIT_256B                2
+#       define ADDR_SURF_TILE_SPLIT_512B                3
+#       define ADDR_SURF_TILE_SPLIT_1KB                 4
+#       define ADDR_SURF_TILE_SPLIT_2KB                 5
+#       define ADDR_SURF_TILE_SPLIT_4KB                 6
+#       define CB_NUM_BANKS(x)                          (((x) & 0x3) << 10)
+#       define ADDR_SURF_2_BANK                         0
+#       define ADDR_SURF_4_BANK                         1
+#       define ADDR_SURF_8_BANK                         2
+#       define ADDR_SURF_16_BANK                        3
+#       define CB_BANK_WIDTH(x)                         (((x) & 0x3) << 13)
+#       define ADDR_SURF_BANK_WIDTH_1                   0
+#       define ADDR_SURF_BANK_WIDTH_2                   1
+#       define ADDR_SURF_BANK_WIDTH_4                   2
+#       define ADDR_SURF_BANK_WIDTH_8                   3
+#       define CB_BANK_HEIGHT(x)                        (((x) & 0x3) << 16)
+#       define ADDR_SURF_BANK_HEIGHT_1                  0
+#       define ADDR_SURF_BANK_HEIGHT_2                  1
+#       define ADDR_SURF_BANK_HEIGHT_4                  2
+#       define ADDR_SURF_BANK_HEIGHT_8                  3
 #define	CB_COLOR0_DIM					0x28c78
 /* only CB0-7 blocks have these regs */
 #define	CB_COLOR0_CMASK					0x28c7c
@@ -1107,14 +1138,56 @@
 #define	CB_COLOR7_CLEAR_WORD3				0x28e3c
 
 #define SQ_TEX_RESOURCE_WORD0_0                         0x30000
+#	define TEX_DIM(x)				((x) << 0)
+#	define SQ_TEX_DIM_1D				0
+#	define SQ_TEX_DIM_2D				1
+#	define SQ_TEX_DIM_3D				2
+#	define SQ_TEX_DIM_CUBEMAP			3
+#	define SQ_TEX_DIM_1D_ARRAY			4
+#	define SQ_TEX_DIM_2D_ARRAY			5
+#	define SQ_TEX_DIM_2D_MSAA			6
+#	define SQ_TEX_DIM_2D_ARRAY_MSAA			7
 #define SQ_TEX_RESOURCE_WORD1_0                         0x30004
 #       define TEX_ARRAY_MODE(x)                        ((x) << 28)
 #define SQ_TEX_RESOURCE_WORD2_0                         0x30008
 #define SQ_TEX_RESOURCE_WORD3_0                         0x3000C
 #define SQ_TEX_RESOURCE_WORD4_0                         0x30010
+#	define TEX_DST_SEL_X(x)				((x) << 16)
+#	define TEX_DST_SEL_Y(x)				((x) << 19)
+#	define TEX_DST_SEL_Z(x)				((x) << 22)
+#	define TEX_DST_SEL_W(x)				((x) << 25)
+#	define SQ_SEL_X					0
+#	define SQ_SEL_Y					1
+#	define SQ_SEL_Z					2
+#	define SQ_SEL_W					3
+#	define SQ_SEL_0					4
+#	define SQ_SEL_1					5
 #define SQ_TEX_RESOURCE_WORD5_0                         0x30014
 #define SQ_TEX_RESOURCE_WORD6_0                         0x30018
+#       define TEX_TILE_SPLIT(x)                        (((x) & 0x7) << 29)
 #define SQ_TEX_RESOURCE_WORD7_0                         0x3001c
+#       define TEX_BANK_WIDTH(x)                        (((x) & 0x3) << 8)
+#       define TEX_BANK_HEIGHT(x)                       (((x) & 0x3) << 10)
+#       define TEX_NUM_BANKS(x)                         (((x) & 0x3) << 16)
+
+#define SQ_VTX_CONSTANT_WORD0_0				0x30000
+#define SQ_VTX_CONSTANT_WORD1_0				0x30004
+#define SQ_VTX_CONSTANT_WORD2_0				0x30008
+#	define SQ_VTXC_BASE_ADDR_HI(x)			((x) << 0)
+#	define SQ_VTXC_STRIDE(x)			((x) << 8)
+#	define SQ_VTXC_ENDIAN_SWAP(x)			((x) << 30)
+#	define SQ_ENDIAN_NONE				0
+#	define SQ_ENDIAN_8IN16				1
+#	define SQ_ENDIAN_8IN32				2
+#define SQ_VTX_CONSTANT_WORD3_0				0x3000C
+#	define SQ_VTCX_SEL_X(x)				((x) << 3)
+#	define SQ_VTCX_SEL_Y(x)				((x) << 6)
+#	define SQ_VTCX_SEL_Z(x)				((x) << 9)
+#	define SQ_VTCX_SEL_W(x)				((x) << 12)
+#define SQ_VTX_CONSTANT_WORD4_0				0x30010
+#define SQ_VTX_CONSTANT_WORD5_0                         0x30014
+#define SQ_VTX_CONSTANT_WORD6_0                         0x30018
+#define SQ_VTX_CONSTANT_WORD7_0                         0x3001c
 
 /* cayman 3D regs */
 #define CAYMAN_VGT_OFFCHIP_LDS_BASE			0x89B0
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/evergreen_reg.h linux-libre-3.2-gnu/drivers/gpu/drm/radeon/evergreen_reg.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/evergreen_reg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/evergreen_reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,17 @@
 #       define EVERGREEN_GRPH_DEPTH_8BPP                0
 #       define EVERGREEN_GRPH_DEPTH_16BPP               1
 #       define EVERGREEN_GRPH_DEPTH_32BPP               2
+#       define EVERGREEN_GRPH_NUM_BANKS(x)              (((x) & 0x3) << 2)
+#       define EVERGREEN_ADDR_SURF_2_BANK               0
+#       define EVERGREEN_ADDR_SURF_4_BANK               1
+#       define EVERGREEN_ADDR_SURF_8_BANK               2
+#       define EVERGREEN_ADDR_SURF_16_BANK              3
+#       define EVERGREEN_GRPH_Z(x)                      (((x) & 0x3) << 4)
+#       define EVERGREEN_GRPH_BANK_WIDTH(x)             (((x) & 0x3) << 6)
+#       define EVERGREEN_ADDR_SURF_BANK_WIDTH_1         0
+#       define EVERGREEN_ADDR_SURF_BANK_WIDTH_2         1
+#       define EVERGREEN_ADDR_SURF_BANK_WIDTH_4         2
+#       define EVERGREEN_ADDR_SURF_BANK_WIDTH_8         3
 #       define EVERGREEN_GRPH_FORMAT(x)                 (((x) & 0x7) << 8)
 /* 8 BPP */
 #       define EVERGREEN_GRPH_FORMAT_INDEXED            0
@@ -61,6 +72,24 @@
 #       define EVERGREEN_GRPH_FORMAT_8B_BGRA1010102     5
 #       define EVERGREEN_GRPH_FORMAT_RGB111110          6
 #       define EVERGREEN_GRPH_FORMAT_BGR101111          7
+#       define EVERGREEN_GRPH_BANK_HEIGHT(x)            (((x) & 0x3) << 11)
+#       define EVERGREEN_ADDR_SURF_BANK_HEIGHT_1        0
+#       define EVERGREEN_ADDR_SURF_BANK_HEIGHT_2        1
+#       define EVERGREEN_ADDR_SURF_BANK_HEIGHT_4        2
+#       define EVERGREEN_ADDR_SURF_BANK_HEIGHT_8        3
+#       define EVERGREEN_GRPH_TILE_SPLIT(x)             (((x) & 0x7) << 13)
+#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_64B       0
+#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_128B      1
+#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_256B      2
+#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_512B      3
+#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_1KB       4
+#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_2KB       5
+#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_4KB       6
+#       define EVERGREEN_GRPH_MACRO_TILE_ASPECT(x)      (((x) & 0x3) << 18)
+#       define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_1  0
+#       define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_2  1
+#       define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_4  2
+#       define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_8  3
 #       define EVERGREEN_GRPH_ARRAY_MODE(x)             (((x) & 0x7) << 20)
 #       define EVERGREEN_GRPH_ARRAY_LINEAR_GENERAL      0
 #       define EVERGREEN_GRPH_ARRAY_LINEAR_ALIGNED      1
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/Makefile linux-libre-3.2-gnu/drivers/gpu/drm/radeon/Makefile
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -70,7 +70,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 cayman_blit_shaders.o
+	radeon_trace_points.o ni.o cayman_blit_shaders.o atombios_encoders.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/ni.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/ni.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/ni.c	2012-03-19 21:30:50.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/ni.c	2012-03-19 21:32:24.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include "drmP.h"
 #include "radeon.h"
 #include "radeon_asic.h"
@@ -40,6 +41,7 @@
 extern void evergreen_irq_suspend(struct radeon_device *rdev);
 extern int evergreen_mc_init(struct radeon_device *rdev);
 extern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev);
+extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
 
 #define EVERGREEN_PFP_UCODE_SIZE 1120
 #define EVERGREEN_PM4_UCODE_SIZE 1376
@@ -219,8 +221,11 @@
 		WREG32(MC_SEQ_SUP_CNTL, 0x00000001);
 
 		/* wait for training to complete */
-		while (!(RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD))
-			udelay(10);
+		for (i = 0; i < rdev->usec_timeout; i++) {
+			if (RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD)
+				break;
+			udelay(1);
+		}
 
 		if (running)
 			WREG32(MC_SHARED_BLACKOUT_CNTL, blackout);
@@ -890,7 +895,7 @@
 {
 	int r;
 
-	if (rdev->gart.table.vram.robj == NULL) {
+	if (rdev->gart.robj == NULL) {
 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
 		return -EINVAL;
 	}
@@ -926,14 +931,15 @@
 	WREG32(VM_CONTEXT1_CNTL, 0);
 
 	cayman_pcie_gart_tlb_flush(rdev);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+		 (unsigned)(rdev->mc.gtt_size >> 20),
+		 (unsigned long long)rdev->gart.table_addr);
 	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);
@@ -949,14 +955,7 @@
 	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);
-		}
-	}
+	radeon_gart_table_vram_unpin(rdev);
 }
 
 void cayman_pcie_gart_fini(struct radeon_device *rdev)
@@ -1300,6 +1299,9 @@
 {
 	int r;
 
+	/* enable pcie gen2 link */
+	evergreen_pcie_gen2_enable(rdev);
+
 	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
 		r = ni_init_microcode(rdev);
 		if (r) {
@@ -1313,6 +1315,10 @@
 		return r;
 	}
 
+	r = r600_vram_scratch_init(rdev);
+	if (r)
+		return r;
+
 	evergreen_mc_program(rdev);
 	r = cayman_pcie_gart_enable(rdev);
 	if (r)
@@ -1321,7 +1327,7 @@
 
 	r = evergreen_blit_init(rdev);
 	if (r) {
-		evergreen_blit_fini(rdev);
+		r600_blit_fini(rdev);
 		rdev->asic->copy = NULL;
 		dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
 	}
@@ -1382,21 +1388,13 @@
 
 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);
-
-	/* 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);
-	}
+	r600_blit_suspend(rdev);
 
 	return 0;
 }
@@ -1509,13 +1507,14 @@
 
 void cayman_fini(struct radeon_device *rdev)
 {
-	evergreen_blit_fini(rdev);
+	r600_blit_fini(rdev);
 	cayman_cp_fini(rdev);
 	r600_irq_fini(rdev);
 	radeon_wb_fini(rdev);
 	radeon_ib_pool_fini(rdev);
 	radeon_irq_kms_fini(rdev);
 	cayman_pcie_gart_fini(rdev);
+	r600_vram_scratch_fini(rdev);
 	radeon_gem_fini(rdev);
 	radeon_fence_driver_fini(rdev);
 	radeon_bo_fini(rdev);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r100.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r100.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r100.c	2012-03-19 21:30:22.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r100.c	2012-03-19 21:31:56.000000000 -0400
@@ -41,6 +41,7 @@
 
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
+#include <linux/module.h>
 
 #include "r100_reg_safe.h"
 #include "rn50_reg_safe.h"
@@ -62,6 +63,108 @@
  * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
  */
 
+int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
+			    struct radeon_cs_packet *pkt,
+			    unsigned idx,
+			    unsigned reg)
+{
+	int r;
+	u32 tile_flags = 0;
+	u32 tmp;
+	struct radeon_cs_reloc *reloc;
+	u32 value;
+
+	r = r100_cs_packet_next_reloc(p, &reloc);
+	if (r) {
+		DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+			  idx, reg);
+		r100_cs_dump_packet(p, pkt);
+		return r;
+	}
+	value = radeon_get_ib_value(p, idx);
+	tmp = value & 0x003fffff;
+	tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
+
+	if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+		tile_flags |= RADEON_DST_TILE_MACRO;
+	if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+		if (reg == RADEON_SRC_PITCH_OFFSET) {
+			DRM_ERROR("Cannot src blit from microtiled surface\n");
+			r100_cs_dump_packet(p, pkt);
+			return -EINVAL;
+		}
+		tile_flags |= RADEON_DST_TILE_MICRO;
+	}
+
+	tmp |= tile_flags;
+	p->ib->ptr[idx] = (value & 0x3fc00000) | tmp;
+	return 0;
+}
+
+int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
+			     struct radeon_cs_packet *pkt,
+			     int idx)
+{
+	unsigned c, i;
+	struct radeon_cs_reloc *reloc;
+	struct r100_cs_track *track;
+	int r = 0;
+	volatile uint32_t *ib;
+	u32 idx_value;
+
+	ib = p->ib->ptr;
+	track = (struct r100_cs_track *)p->track;
+	c = radeon_get_ib_value(p, idx++) & 0x1F;
+	if (c > 16) {
+	    DRM_ERROR("Only 16 vertex buffers are allowed %d\n",
+		      pkt->opcode);
+	    r100_cs_dump_packet(p, pkt);
+	    return -EINVAL;
+	}
+	track->num_arrays = c;
+	for (i = 0; i < (c - 1); i+=2, idx+=3) {
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for packet3 %d\n",
+				  pkt->opcode);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+		idx_value = radeon_get_ib_value(p, idx);
+		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
+
+		track->arrays[i + 0].esize = idx_value >> 8;
+		track->arrays[i + 0].robj = reloc->robj;
+		track->arrays[i + 0].esize &= 0x7F;
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for packet3 %d\n",
+				  pkt->opcode);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+		ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset);
+		track->arrays[i + 1].robj = reloc->robj;
+		track->arrays[i + 1].esize = idx_value >> 24;
+		track->arrays[i + 1].esize &= 0x7F;
+	}
+	if (c & 1) {
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for packet3 %d\n",
+					  pkt->opcode);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+		idx_value = radeon_get_ib_value(p, idx);
+		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
+		track->arrays[i + 0].robj = reloc->robj;
+		track->arrays[i + 0].esize = idx_value >> 8;
+		track->arrays[i + 0].esize &= 0x7F;
+	}
+	return r;
+}
+
 void r100_pre_page_flip(struct radeon_device *rdev, int crtc)
 {
 	/* enable the pflip int */
@@ -78,13 +181,18 @@
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
+	int i;
 
 	/* Lock the graphics update lock */
 	/* update the scanout addresses */
 	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
 
 	/* Wait for update_pending to go high. */
-	while (!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET));
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)
+			break;
+		udelay(1);
+	}
 	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
 
 	/* Unlock the lock, so double-buffering can take place inside vblank */
@@ -428,6 +536,7 @@
 		default:
 			break;
 		}
+		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
 	}
 	if (rdev->irq.installed)
 		r100_irq_set(rdev);
@@ -468,7 +577,7 @@
 {
 	int r;
 
-	if (rdev->gart.table.ram.ptr) {
+	if (rdev->gart.ptr) {
 		WARN(1, "R100 PCI GART already initialized\n");
 		return 0;
 	}
@@ -507,6 +616,9 @@
 	tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN;
 	WREG32(RADEON_AIC_CNTL, tmp);
 	r100_pci_gart_tlb_flush(rdev);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+		 (unsigned)(rdev->mc.gtt_size >> 20),
+		 (unsigned long long)rdev->gart.table_addr);
 	rdev->gart.ready = true;
 	return 0;
 }
@@ -524,10 +636,12 @@
 
 int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 {
+	u32 *gtt = rdev->gart.ptr;
+
 	if (i < 0 || i > rdev->gart.num_gpu_pages) {
 		return -EINVAL;
 	}
-	rdev->gart.table.ram.ptr[i] = cpu_to_le32(lower_32_bits(addr));
+	gtt[i] = cpu_to_le32(lower_32_bits(addr));
 	return 0;
 }
 
@@ -582,7 +696,7 @@
 	WREG32(R_000044_GEN_INT_STATUS, tmp);
 }
 
-static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
+static uint32_t r100_irq_ack(struct radeon_device *rdev)
 {
 	uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS);
 	uint32_t irq_mask = RADEON_SW_INT_TEST |
@@ -3141,7 +3255,7 @@
 	}
 }
 
-static inline void r100_cs_track_texture_print(struct r100_cs_track_texture *t)
+static void r100_cs_track_texture_print(struct r100_cs_track_texture *t)
 {
 	DRM_ERROR("pitch                      %d\n", t->pitch);
 	DRM_ERROR("use_pitch                  %d\n", t->use_pitch);
@@ -3959,3 +4073,43 @@
 	}
 	return 0;
 }
+
+uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+	if (reg < rdev->rmmio_size)
+		return readl(((void __iomem *)rdev->rmmio) + reg);
+	else {
+		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
+		return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+	}
+}
+
+void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+	if (reg < rdev->rmmio_size)
+		writel(v, ((void __iomem *)rdev->rmmio) + reg);
+	else {
+		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
+		writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+	}
+}
+
+u32 r100_io_rreg(struct radeon_device *rdev, u32 reg)
+{
+	if (reg < rdev->rio_mem_size)
+		return ioread32(rdev->rio_mem + reg);
+	else {
+		iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
+		return ioread32(rdev->rio_mem + RADEON_MM_DATA);
+	}
+}
+
+void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v)
+{
+	if (reg < rdev->rio_mem_size)
+		iowrite32(v, rdev->rio_mem + reg);
+	else {
+		iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
+		iowrite32(v, rdev->rio_mem + RADEON_MM_DATA);
+	}
+}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r100_track.h linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r100_track.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r100_track.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r100_track.h	2012-01-04 18:55:44.000000000 -0500
@@ -92,106 +92,10 @@
 		       struct radeon_cs_packet *pkt,
 		       unsigned idx, unsigned reg);
 
-
-
-static inline int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
-					  struct radeon_cs_packet *pkt,
-					  unsigned idx,
-					  unsigned reg)
-{
-	int r;
-	u32 tile_flags = 0;
-	u32 tmp;
-	struct radeon_cs_reloc *reloc;
-	u32 value;
-
-	r = r100_cs_packet_next_reloc(p, &reloc);
-	if (r) {
-		DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
-			  idx, reg);
-		r100_cs_dump_packet(p, pkt);
-		return r;
-	}
-	value = radeon_get_ib_value(p, idx);
-	tmp = value & 0x003fffff;
-	tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
-
-	if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-		tile_flags |= RADEON_DST_TILE_MACRO;
-	if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
-		if (reg == RADEON_SRC_PITCH_OFFSET) {
-			DRM_ERROR("Cannot src blit from microtiled surface\n");
-			r100_cs_dump_packet(p, pkt);
-			return -EINVAL;
-		}
-		tile_flags |= RADEON_DST_TILE_MICRO;
-	}
-
-	tmp |= tile_flags;
-	p->ib->ptr[idx] = (value & 0x3fc00000) | tmp;
-	return 0;
-}
-
-static inline int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
-					   struct radeon_cs_packet *pkt,
-					   int idx)
-{
-	unsigned c, i;
-	struct radeon_cs_reloc *reloc;
-	struct r100_cs_track *track;
-	int r = 0;
-	volatile uint32_t *ib;
-	u32 idx_value;
-
-	ib = p->ib->ptr;
-	track = (struct r100_cs_track *)p->track;
-	c = radeon_get_ib_value(p, idx++) & 0x1F;
-	if (c > 16) {
-	    DRM_ERROR("Only 16 vertex buffers are allowed %d\n",
-		      pkt->opcode);
-	    r100_cs_dump_packet(p, pkt);
-	    return -EINVAL;
-	}
-	track->num_arrays = c;
-	for (i = 0; i < (c - 1); i+=2, idx+=3) {
-		r = r100_cs_packet_next_reloc(p, &reloc);
-		if (r) {
-			DRM_ERROR("No reloc for packet3 %d\n",
-				  pkt->opcode);
-			r100_cs_dump_packet(p, pkt);
-			return r;
-		}
-		idx_value = radeon_get_ib_value(p, idx);
-		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
-
-		track->arrays[i + 0].esize = idx_value >> 8;
-		track->arrays[i + 0].robj = reloc->robj;
-		track->arrays[i + 0].esize &= 0x7F;
-		r = r100_cs_packet_next_reloc(p, &reloc);
-		if (r) {
-			DRM_ERROR("No reloc for packet3 %d\n",
-				  pkt->opcode);
-			r100_cs_dump_packet(p, pkt);
-			return r;
-		}
-		ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset);
-		track->arrays[i + 1].robj = reloc->robj;
-		track->arrays[i + 1].esize = idx_value >> 24;
-		track->arrays[i + 1].esize &= 0x7F;
-	}
-	if (c & 1) {
-		r = r100_cs_packet_next_reloc(p, &reloc);
-		if (r) {
-			DRM_ERROR("No reloc for packet3 %d\n",
-					  pkt->opcode);
-			r100_cs_dump_packet(p, pkt);
-			return r;
-		}
-		idx_value = radeon_get_ib_value(p, idx);
-		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
-		track->arrays[i + 0].robj = reloc->robj;
-		track->arrays[i + 0].esize = idx_value >> 8;
-		track->arrays[i + 0].esize &= 0x7F;
-	}
-	return r;
-}
+int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
+			    struct radeon_cs_packet *pkt,
+			    unsigned idx,
+			    unsigned reg);
+int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
+			     struct radeon_cs_packet *pkt,
+			     int idx);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r300.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r300.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r300.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r300.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,7 +74,7 @@
 
 int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 {
-	void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+	void __iomem *ptr = rdev->gart.ptr;
 
 	if (i < 0 || i > rdev->gart.num_gpu_pages) {
 		return -EINVAL;
@@ -93,7 +93,7 @@
 {
 	int r;
 
-	if (rdev->gart.table.vram.robj) {
+	if (rdev->gart.robj) {
 		WARN(1, "RV370 PCIE GART already initialized\n");
 		return 0;
 	}
@@ -116,7 +116,7 @@
 	uint32_t tmp;
 	int r;
 
-	if (rdev->gart.table.vram.robj == NULL) {
+	if (rdev->gart.robj == NULL) {
 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
 		return -EINVAL;
 	}
@@ -144,8 +144,9 @@
 	tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
 	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
 	rv370_pcie_gart_tlb_flush(rdev);
-	DRM_INFO("PCIE GART of %uM enabled (table at 0x%08X).\n",
-		 (unsigned)(rdev->mc.gtt_size >> 20), table_addr);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+		 (unsigned)(rdev->mc.gtt_size >> 20),
+		 (unsigned long long)table_addr);
 	rdev->gart.ready = true;
 	return 0;
 }
@@ -153,7 +154,6 @@
 void rv370_pcie_gart_disable(struct radeon_device *rdev)
 {
 	u32 tmp;
-	int r;
 
 	WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, 0);
 	WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, 0);
@@ -162,14 +162,7 @@
 	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
 	tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
 	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN);
-	if (rdev->gart.table.vram.robj) {
-		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);
-		}
-	}
+	radeon_gart_table_vram_unpin(rdev);
 }
 
 void rv370_pcie_gart_fini(struct radeon_device *rdev)
@@ -708,16 +701,21 @@
 			return r;
 		}
 
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-			tile_flags |= R300_TXO_MACRO_TILE;
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-			tile_flags |= R300_TXO_MICRO_TILE;
-		else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
-			tile_flags |= R300_TXO_MICRO_TILE_SQUARE;
+		if (p->keep_tiling_flags) {
+			ib[idx] = (idx_value & 31) | /* keep the 1st 5 bits */
+				  ((idx_value & ~31) + (u32)reloc->lobj.gpu_offset);
+		} else {
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+				tile_flags |= R300_TXO_MACRO_TILE;
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+				tile_flags |= R300_TXO_MICRO_TILE;
+			else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
+				tile_flags |= R300_TXO_MICRO_TILE_SQUARE;
 
-		tmp = idx_value + ((u32)reloc->lobj.gpu_offset);
-		tmp |= tile_flags;
-		ib[idx] = tmp;
+			tmp = idx_value + ((u32)reloc->lobj.gpu_offset);
+			tmp |= tile_flags;
+			ib[idx] = tmp;
+		}
 		track->textures[i].robj = reloc->robj;
 		track->tex_dirty = true;
 		break;
@@ -767,24 +765,26 @@
 		/* RB3D_COLORPITCH1 */
 		/* RB3D_COLORPITCH2 */
 		/* RB3D_COLORPITCH3 */
-		r = r100_cs_packet_next_reloc(p, &reloc);
-		if (r) {
-			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
-				  idx, reg);
-			r100_cs_dump_packet(p, pkt);
-			return r;
-		}
+		if (!p->keep_tiling_flags) {
+			r = r100_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+					  idx, reg);
+				r100_cs_dump_packet(p, pkt);
+				return r;
+			}
 
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-			tile_flags |= R300_COLOR_TILE_ENABLE;
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-			tile_flags |= R300_COLOR_MICROTILE_ENABLE;
-		else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
-			tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE;
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+				tile_flags |= R300_COLOR_TILE_ENABLE;
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+				tile_flags |= R300_COLOR_MICROTILE_ENABLE;
+			else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
+				tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE;
 
-		tmp = idx_value & ~(0x7 << 16);
-		tmp |= tile_flags;
-		ib[idx] = tmp;
+			tmp = idx_value & ~(0x7 << 16);
+			tmp |= tile_flags;
+			ib[idx] = tmp;
+		}
 		i = (reg - 0x4E38) >> 2;
 		track->cb[i].pitch = idx_value & 0x3FFE;
 		switch (((idx_value >> 21) & 0xF)) {
@@ -850,25 +850,26 @@
 		break;
 	case 0x4F24:
 		/* ZB_DEPTHPITCH */
-		r = r100_cs_packet_next_reloc(p, &reloc);
-		if (r) {
-			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
-				  idx, reg);
-			r100_cs_dump_packet(p, pkt);
-			return r;
-		}
-
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-			tile_flags |= R300_DEPTHMACROTILE_ENABLE;
-		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-			tile_flags |= R300_DEPTHMICROTILE_TILED;
-		else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
-			tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE;
+		if (!p->keep_tiling_flags) {
+			r = r100_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+					  idx, reg);
+				r100_cs_dump_packet(p, pkt);
+				return r;
+			}
 
-		tmp = idx_value & ~(0x7 << 16);
-		tmp |= tile_flags;
-		ib[idx] = tmp;
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+				tile_flags |= R300_DEPTHMACROTILE_ENABLE;
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+				tile_flags |= R300_DEPTHMICROTILE_TILED;
+			else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
+				tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE;
 
+			tmp = idx_value & ~(0x7 << 16);
+			tmp |= tile_flags;
+			ib[idx] = tmp;
+		}
 		track->zb.pitch = idx_value & 0x3FFC;
 		track->zb_dirty = true;
 		break;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r300_cmdbuf.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r300_cmdbuf.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r300_cmdbuf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r300_cmdbuf.c	2012-01-04 18:55:44.000000000 -0500
@@ -791,7 +791,7 @@
 /**
  * Emit the sequence to pacify R300.
  */
-static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
+static void r300_pacify(drm_radeon_private_t *dev_priv)
 {
 	uint32_t cache_z, cache_3d, cache_2d;
 	RING_LOCALS;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r600_blit.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r600_blit.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r600_blit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r600_blit.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,7 +41,7 @@
 #define COLOR_5_6_5           0x8
 #define COLOR_8_8_8_8         0x1a
 
-static inline void
+static void
 set_render_target(drm_radeon_private_t *dev_priv, int format, int w, int h, u64 gpu_addr)
 {
 	u32 cb_color_info;
@@ -99,7 +99,7 @@
 	ADVANCE_RING();
 }
 
-static inline void
+static void
 cp_set_surface_sync(drm_radeon_private_t *dev_priv,
 		    u32 sync_type, u32 size, u64 mc_addr)
 {
@@ -121,7 +121,7 @@
 	ADVANCE_RING();
 }
 
-static inline void
+static void
 set_shaders(struct drm_device *dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -184,7 +184,7 @@
 			    R600_SH_ACTION_ENA, 512, gpu_addr);
 }
 
-static inline void
+static void
 set_vtx_resource(drm_radeon_private_t *dev_priv, u64 gpu_addr)
 {
 	uint32_t sq_vtx_constant_word2;
@@ -220,7 +220,7 @@
 				    R600_VC_ACTION_ENA, 48, gpu_addr);
 }
 
-static inline void
+static void
 set_tex_resource(drm_radeon_private_t *dev_priv,
 		 int format, int w, int h, int pitch, u64 gpu_addr)
 {
@@ -258,7 +258,7 @@
 
 }
 
-static inline void
+static void
 set_scissors(drm_radeon_private_t *dev_priv, int x1, int y1, int x2, int y2)
 {
 	RING_LOCALS;
@@ -282,7 +282,7 @@
 	ADVANCE_RING();
 }
 
-static inline void
+static void
 draw_auto(drm_radeon_private_t *dev_priv)
 {
 	RING_LOCALS;
@@ -311,7 +311,7 @@
 	COMMIT_RING();
 }
 
-static inline void
+static void
 set_default_state(drm_radeon_private_t *dev_priv)
 {
 	int i;
@@ -489,7 +489,7 @@
 	ADVANCE_RING();
 }
 
-static inline uint32_t i2f(uint32_t input)
+static uint32_t i2f(uint32_t input)
 {
 	u32 result, i, exponent, fraction;
 
@@ -515,7 +515,7 @@
 }
 
 
-static inline int r600_nomm_get_vb(struct drm_device *dev)
+static int r600_nomm_get_vb(struct drm_device *dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	dev_priv->blit_vb = radeon_freelist_get(dev);
@@ -526,7 +526,7 @@
 	return 0;
 }
 
-static inline void r600_nomm_put_vb(struct drm_device *dev)
+static void r600_nomm_put_vb(struct drm_device *dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 
@@ -534,7 +534,7 @@
 	radeon_cp_discard_buffer(dev, dev_priv->blit_vb->file_priv->master, dev_priv->blit_vb);
 }
 
-static inline void *r600_nomm_get_vb_ptr(struct drm_device *dev)
+static void *r600_nomm_get_vb_ptr(struct drm_device *dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	return (((char *)dev->agp_buffer_map->handle +
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r600_blit_kms.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r600_blit_kms.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r600_blit_kms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r600_blit_kms.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,9 @@
 #define COLOR_5_6_5           0x8
 #define COLOR_8_8_8_8         0x1a
 
+#define RECT_UNIT_H           32
+#define RECT_UNIT_W           (RADEON_GPU_PAGE_SIZE / 4 / RECT_UNIT_H)
+
 /* emits 21 on rv770+, 23 on r600 */
 static void
 set_render_target(struct radeon_device *rdev, int format,
@@ -54,7 +57,9 @@
 	if (h < 8)
 		h = 8;
 
-	cb_color_info = ((format << 2) | (1 << 27) | (1 << 8));
+	cb_color_info = CB_FORMAT(format) |
+		CB_SOURCE_FORMAT(CB_SF_EXPORT_NORM) |
+		CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
 	pitch = (w / 8) - 1;
 	slice = ((w * h) / 64) - 1;
 
@@ -164,9 +169,10 @@
 {
 	u32 sq_vtx_constant_word2;
 
-	sq_vtx_constant_word2 = ((upper_32_bits(gpu_addr) & 0xff) | (16 << 8));
+	sq_vtx_constant_word2 = SQ_VTXC_BASE_ADDR_HI(upper_32_bits(gpu_addr) & 0xff) |
+		SQ_VTXC_STRIDE(16);
 #ifdef __BIG_ENDIAN
-	sq_vtx_constant_word2 |= (2 << 30);
+	sq_vtx_constant_word2 |=  SQ_VTXC_ENDIAN_SWAP(SQ_ENDIAN_8IN32);
 #endif
 
 	radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 7));
@@ -195,25 +201,29 @@
 static void
 set_tex_resource(struct radeon_device *rdev,
 		 int format, int w, int h, int pitch,
-		 u64 gpu_addr)
+		 u64 gpu_addr, u32 size)
 {
 	uint32_t sq_tex_resource_word0, sq_tex_resource_word1, sq_tex_resource_word4;
 
 	if (h < 1)
 		h = 1;
 
-	sq_tex_resource_word0 = (1 << 0) | (1 << 3);
-	sq_tex_resource_word0 |= ((((pitch >> 3) - 1) << 8) |
-				  ((w - 1) << 19));
+	sq_tex_resource_word0 = S_038000_DIM(V_038000_SQ_TEX_DIM_2D) |
+		S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+	sq_tex_resource_word0 |= S_038000_PITCH((pitch >> 3) - 1) |
+		S_038000_TEX_WIDTH(w - 1);
 
-	sq_tex_resource_word1 = (format << 26);
-	sq_tex_resource_word1 |= ((h - 1) << 0);
+	sq_tex_resource_word1 = S_038004_DATA_FORMAT(format);
+	sq_tex_resource_word1 |= S_038004_TEX_HEIGHT(h - 1);
 
-	sq_tex_resource_word4 = ((1 << 14) |
-				 (0 << 16) |
-				 (1 << 19) |
-				 (2 << 22) |
-				 (3 << 25));
+	sq_tex_resource_word4 = S_038010_REQUEST_SIZE(1) |
+		S_038010_DST_SEL_X(SQ_SEL_X) |
+		S_038010_DST_SEL_Y(SQ_SEL_Y) |
+		S_038010_DST_SEL_Z(SQ_SEL_Z) |
+		S_038010_DST_SEL_W(SQ_SEL_W);
+
+	cp_set_surface_sync(rdev,
+			    PACKET3_TC_ACTION_ENA, size, gpu_addr);
 
 	radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 7));
 	radeon_ring_write(rdev, 0);
@@ -450,7 +460,7 @@
 	radeon_ring_write(rdev, sq_stack_resource_mgmt_2);
 }
 
-static inline uint32_t i2f(uint32_t input)
+static uint32_t i2f(uint32_t input)
 {
 	u32 result, i, exponent, fraction;
 
@@ -483,6 +493,27 @@
 	u32 packet2s[16];
 	int num_packet2s = 0;
 
+	rdev->r600_blit.primitives.set_render_target = set_render_target;
+	rdev->r600_blit.primitives.cp_set_surface_sync = cp_set_surface_sync;
+	rdev->r600_blit.primitives.set_shaders = set_shaders;
+	rdev->r600_blit.primitives.set_vtx_resource = set_vtx_resource;
+	rdev->r600_blit.primitives.set_tex_resource = set_tex_resource;
+	rdev->r600_blit.primitives.set_scissors = set_scissors;
+	rdev->r600_blit.primitives.draw_auto = draw_auto;
+	rdev->r600_blit.primitives.set_default_state = set_default_state;
+
+	rdev->r600_blit.ring_size_common = 40; /* shaders + def state */
+	rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */
+	rdev->r600_blit.ring_size_common += 5; /* done copy */
+	rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */
+
+	rdev->r600_blit.ring_size_per_loop = 76;
+	/* set_render_target emits 2 extra dwords on rv6xx */
+	if (rdev->family > CHIP_R600 && rdev->family < CHIP_RV770)
+		rdev->r600_blit.ring_size_per_loop += 2;
+
+	rdev->r600_blit.max_dim = 8192;
+
 	/* pin copy shader into vram if already initialized */
 	if (rdev->r600_blit.shader_obj)
 		goto done;
@@ -600,47 +631,80 @@
 	radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
 }
 
-int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes)
+static unsigned r600_blit_create_rect(unsigned num_gpu_pages,
+				      int *width, int *height, int max_dim)
+{
+	unsigned max_pages;
+	unsigned pages = num_gpu_pages;
+	int w, h;
+
+	if (num_gpu_pages == 0) {
+		/* not supposed to be called with no pages, but just in case */
+		h = 0;
+		w = 0;
+		pages = 0;
+		WARN_ON(1);
+	} else {
+		int rect_order = 2;
+		h = RECT_UNIT_H;
+		while (num_gpu_pages / rect_order) {
+			h *= 2;
+			rect_order *= 4;
+			if (h >= max_dim) {
+				h = max_dim;
+				break;
+			}
+		}
+		max_pages = (max_dim * h) / (RECT_UNIT_W * RECT_UNIT_H);
+		if (pages > max_pages)
+			pages = max_pages;
+		w = (pages * RECT_UNIT_W * RECT_UNIT_H) / h;
+		w = (w / RECT_UNIT_W) * RECT_UNIT_W;
+		pages = (w * h) / (RECT_UNIT_W * RECT_UNIT_H);
+		BUG_ON(pages == 0);
+	}
+
+
+	DRM_DEBUG("blit_rectangle: h=%d, w=%d, pages=%d\n", h, w, pages);
+
+	/* return width and height only of the caller wants it */
+	if (height)
+		*height = h;
+	if (width)
+		*width = w;
+
+	return pages;
+}
+
+
+int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages)
 {
 	int r;
-	int ring_size, line_size;
-	int max_size;
-	/* loops of emits 64 + fence emit possible */
-	int dwords_per_loop = 76, num_loops;
+	int ring_size;
+	int num_loops = 0;
+	int dwords_per_loop = rdev->r600_blit.ring_size_per_loop;
 
 	r = r600_vb_ib_get(rdev);
 	if (r)
 		return r;
 
-	/* set_render_target emits 2 extra dwords on rv6xx */
-	if (rdev->family > CHIP_R600 && rdev->family < CHIP_RV770)
-		dwords_per_loop += 2;
-
-	/* 8 bpp vs 32 bpp for xfer unit */
-	if (size_bytes & 3)
-		line_size = 8192;
-	else
-		line_size = 8192*4;
-
-	max_size = 8192 * line_size;
+	/* num loops */
+	while (num_gpu_pages) {
+		num_gpu_pages -=
+			r600_blit_create_rect(num_gpu_pages, NULL, NULL,
+					      rdev->r600_blit.max_dim);
+		num_loops++;
+	}
 
-	/* major loops cover the max size transfer */
-	num_loops = ((size_bytes + max_size) / max_size);
-	/* minor loops cover the extra non aligned bits */
-	num_loops += ((size_bytes % line_size) ? 1 : 0);
 	/* calculate number of loops correctly */
 	ring_size = num_loops * dwords_per_loop;
-	/* set default  + shaders */
-	ring_size += 40; /* shaders + def state */
-	ring_size += 10; /* fence emit for VB IB */
-	ring_size += 5; /* done copy */
-	ring_size += 10; /* fence emit for done copy */
+	ring_size += rdev->r600_blit.ring_size_common;
 	r = radeon_ring_lock(rdev, ring_size);
 	if (r)
 		return r;
 
-	set_default_state(rdev); /* 14 */
-	set_shaders(rdev); /* 26 */
+	rdev->r600_blit.primitives.set_default_state(rdev);
+	rdev->r600_blit.primitives.set_shaders(rdev);
 	return 0;
 }
 
@@ -659,182 +723,61 @@
 
 void r600_kms_blit_copy(struct radeon_device *rdev,
 			u64 src_gpu_addr, u64 dst_gpu_addr,
-			int size_bytes)
+			unsigned num_gpu_pages)
 {
-	int max_bytes;
 	u64 vb_gpu_addr;
 	u32 *vb;
 
-	DRM_DEBUG("emitting copy %16llx %16llx %d %d\n", src_gpu_addr, dst_gpu_addr,
-		  size_bytes, rdev->r600_blit.vb_used);
+	DRM_DEBUG("emitting copy %16llx %16llx %d %d\n",
+		  src_gpu_addr, dst_gpu_addr,
+		  num_gpu_pages, rdev->r600_blit.vb_used);
 	vb = (u32 *)(rdev->r600_blit.vb_ib->ptr + rdev->r600_blit.vb_used);
-	if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) {
-		max_bytes = 8192;
-
-		while (size_bytes) {
-			int cur_size = size_bytes;
-			int src_x = src_gpu_addr & 255;
-			int dst_x = dst_gpu_addr & 255;
-			int h = 1;
-			src_gpu_addr = src_gpu_addr & ~255ULL;
-			dst_gpu_addr = dst_gpu_addr & ~255ULL;
 
-			if (!src_x && !dst_x) {
-				h = (cur_size / max_bytes);
-				if (h > 8192)
-					h = 8192;
-				if (h == 0)
-					h = 1;
-				else
-					cur_size = max_bytes;
-			} else {
-				if (cur_size > max_bytes)
-					cur_size = max_bytes;
-				if (cur_size > (max_bytes - dst_x))
-					cur_size = (max_bytes - dst_x);
-				if (cur_size > (max_bytes - src_x))
-					cur_size = (max_bytes - src_x);
-			}
-
-			if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
-				WARN_ON(1);
-			}
-
-			vb[0] = i2f(dst_x);
-			vb[1] = 0;
-			vb[2] = i2f(src_x);
-			vb[3] = 0;
-
-			vb[4] = i2f(dst_x);
-			vb[5] = i2f(h);
-			vb[6] = i2f(src_x);
-			vb[7] = i2f(h);
-
-			vb[8] = i2f(dst_x + cur_size);
-			vb[9] = i2f(h);
-			vb[10] = i2f(src_x + cur_size);
-			vb[11] = i2f(h);
-
-			/* src 9 */
-			set_tex_resource(rdev, FMT_8,
-					 src_x + cur_size, h, src_x + cur_size,
-					 src_gpu_addr);
-
-			/* 5 */
-			cp_set_surface_sync(rdev,
-					    PACKET3_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
-
-			/* dst 23 */
-			set_render_target(rdev, COLOR_8,
-					  dst_x + cur_size, h,
-					  dst_gpu_addr);
-
-			/* scissors 12 */
-			set_scissors(rdev, dst_x, 0, dst_x + cur_size, h);
-
-			/* 14 */
-			vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
-			set_vtx_resource(rdev, vb_gpu_addr);
-
-			/* draw 10 */
-			draw_auto(rdev);
-
-			/* 5 */
-			cp_set_surface_sync(rdev,
-					    PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
-					    cur_size * h, dst_gpu_addr);
+	while (num_gpu_pages) {
+		int w, h;
+		unsigned size_in_bytes;
+		unsigned pages_per_loop =
+			r600_blit_create_rect(num_gpu_pages, &w, &h,
+					      rdev->r600_blit.max_dim);
 
-			vb += 12;
-			rdev->r600_blit.vb_used += 12 * 4;
+		size_in_bytes = pages_per_loop * RADEON_GPU_PAGE_SIZE;
+		DRM_DEBUG("rectangle w=%d h=%d\n", w, h);
 
-			src_gpu_addr += cur_size * h;
-			dst_gpu_addr += cur_size * h;
-			size_bytes -= cur_size * h;
+		if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
+			WARN_ON(1);
 		}
-	} else {
-		max_bytes = 8192 * 4;
-
-		while (size_bytes) {
-			int cur_size = size_bytes;
-			int src_x = (src_gpu_addr & 255);
-			int dst_x = (dst_gpu_addr & 255);
-			int h = 1;
-			src_gpu_addr = src_gpu_addr & ~255ULL;
-			dst_gpu_addr = dst_gpu_addr & ~255ULL;
-
-			if (!src_x && !dst_x) {
-				h = (cur_size / max_bytes);
-				if (h > 8192)
-					h = 8192;
-				if (h == 0)
-					h = 1;
-				else
-					cur_size = max_bytes;
-			} else {
-				if (cur_size > max_bytes)
-					cur_size = max_bytes;
-				if (cur_size > (max_bytes - dst_x))
-					cur_size = (max_bytes - dst_x);
-				if (cur_size > (max_bytes - src_x))
-					cur_size = (max_bytes - src_x);
-			}
-
-			if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
-				WARN_ON(1);
-			}
-
-			vb[0] = i2f(dst_x / 4);
-			vb[1] = 0;
-			vb[2] = i2f(src_x / 4);
-			vb[3] = 0;
-
-			vb[4] = i2f(dst_x / 4);
-			vb[5] = i2f(h);
-			vb[6] = i2f(src_x / 4);
-			vb[7] = i2f(h);
-
-			vb[8] = i2f((dst_x + cur_size) / 4);
-			vb[9] = i2f(h);
-			vb[10] = i2f((src_x + cur_size) / 4);
-			vb[11] = i2f(h);
-
-			/* src 9 */
-			set_tex_resource(rdev, FMT_8_8_8_8,
-					 (src_x + cur_size) / 4,
-					 h, (src_x + cur_size) / 4,
-					 src_gpu_addr);
-			/* 5 */
-			cp_set_surface_sync(rdev,
-					    PACKET3_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
 
-			/* dst 23 */
-			set_render_target(rdev, COLOR_8_8_8_8,
-					  (dst_x + cur_size) / 4, h,
-					  dst_gpu_addr);
-
-			/* scissors 12  */
-			set_scissors(rdev, (dst_x / 4), 0, (dst_x + cur_size / 4), h);
-
-			/* Vertex buffer setup 14 */
-			vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
-			set_vtx_resource(rdev, vb_gpu_addr);
+		vb[0] = 0;
+		vb[1] = 0;
+		vb[2] = 0;
+		vb[3] = 0;
 
-			/* draw 10 */
-			draw_auto(rdev);
+		vb[4] = 0;
+		vb[5] = i2f(h);
+		vb[6] = 0;
+		vb[7] = i2f(h);
 
-			/* 5 */
-			cp_set_surface_sync(rdev,
-					    PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
-					    cur_size * h, dst_gpu_addr);
+		vb[8] = i2f(w);
+		vb[9] = i2f(h);
+		vb[10] = i2f(w);
+		vb[11] = i2f(h);
 
-			/* 78 ring dwords per loop */
-			vb += 12;
-			rdev->r600_blit.vb_used += 12 * 4;
+		rdev->r600_blit.primitives.set_tex_resource(rdev, FMT_8_8_8_8,
+							    w, h, w, src_gpu_addr, size_in_bytes);
+		rdev->r600_blit.primitives.set_render_target(rdev, COLOR_8_8_8_8,
+							     w, h, dst_gpu_addr);
+		rdev->r600_blit.primitives.set_scissors(rdev, 0, 0, w, h);
+		vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
+		rdev->r600_blit.primitives.set_vtx_resource(rdev, vb_gpu_addr);
+		rdev->r600_blit.primitives.draw_auto(rdev);
+		rdev->r600_blit.primitives.cp_set_surface_sync(rdev,
+				    PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
+				    size_in_bytes, dst_gpu_addr);
 
-			src_gpu_addr += cur_size * h;
-			dst_gpu_addr += cur_size * h;
-			size_bytes -= cur_size * h;
-		}
+		vb += 12;
+		rdev->r600_blit.vb_used += 4*12;
+		src_gpu_addr += size_in_bytes;
+		dst_gpu_addr += size_in_bytes;
+		num_gpu_pages -= pages_per_loop;
 	}
 }
-
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r600.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r600.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r600.c	2012-03-19 21:30:33.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r600.c	2012-03-19 21:32:08.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/seq_file.h>
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
+#include <linux/module.h>
 #include "drmP.h"
 #include "radeon_drm.h"
 #include "radeon.h"
@@ -247,24 +248,6 @@
 		  pcie_lanes);
 }
 
-static int r600_pm_get_type_index(struct radeon_device *rdev,
-				  enum radeon_pm_state_type ps_type,
-				  int instance)
-{
-	int i;
-	int found_instance = -1;
-
-	for (i = 0; i < rdev->pm.num_power_states; i++) {
-		if (rdev->pm.power_state[i].type == ps_type) {
-			found_instance++;
-			if (found_instance == instance)
-				return i;
-		}
-	}
-	/* return default if no match */
-	return rdev->pm.default_power_state_index;
-}
-
 void rs780_pm_init_profile(struct radeon_device *rdev)
 {
 	if (rdev->pm.num_power_states == 2) {
@@ -380,6 +363,8 @@
 
 void r600_pm_init_profile(struct radeon_device *rdev)
 {
+	int idx;
+
 	if (rdev->family == CHIP_R600) {
 		/* XXX */
 		/* default */
@@ -461,81 +446,43 @@
 			rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
 			rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2;
 			/* low sh */
-			if (rdev->flags & RADEON_IS_MOBILITY) {
-				rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
-				rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
-				rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
-				rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
-			} else {
-				rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-				rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-				rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
-				rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
-			}
+			if (rdev->flags & RADEON_IS_MOBILITY)
+				idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
+			else
+				idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+			rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
+			rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
 			/* mid sh */
-			if (rdev->flags & RADEON_IS_MOBILITY) {
-				rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
-				rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
-				rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
-				rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
-			} else {
-				rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-				rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-				rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
-				rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
-			}
+			rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+			rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
 			/* high sh */
-			rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx =
-				r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-			rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx =
-				r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+			idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+			rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx;
 			rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
 			rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2;
 			/* low mh */
-			if (rdev->flags & RADEON_IS_MOBILITY) {
-				rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
-				rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
-				rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
-				rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
-			} else {
-				rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-				rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-				rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
-				rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
-			}
+			if (rdev->flags & RADEON_IS_MOBILITY)
+				idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
+			else
+				idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
+			rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
+			rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
 			/* mid mh */
-			if (rdev->flags & RADEON_IS_MOBILITY) {
-				rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
-				rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
-				rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
-				rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
-			} else {
-				rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-				rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx =
-					r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-				rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
-				rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
-			}
+			rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+			rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
 			/* high mh */
-			rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx =
-				r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-			rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx =
-				r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
+			idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
+			rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx;
+			rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx;
 			rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
 			rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2;
 		}
@@ -722,13 +669,14 @@
 	struct drm_device *dev = rdev->ddev;
 	struct drm_connector *connector;
 
-	if (ASIC_IS_DCE3(rdev)) {
-		u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa);
-		if (ASIC_IS_DCE32(rdev))
-			tmp |= DC_HPDx_EN;
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+		if (ASIC_IS_DCE3(rdev)) {
+			u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa);
+			if (ASIC_IS_DCE32(rdev))
+				tmp |= DC_HPDx_EN;
 
-		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-			struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 			switch (radeon_connector->hpd.hpd) {
 			case RADEON_HPD_1:
 				WREG32(DC_HPD1_CONTROL, tmp);
@@ -758,10 +706,7 @@
 			default:
 				break;
 			}
-		}
-	} else {
-		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-			struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+		} else {
 			switch (radeon_connector->hpd.hpd) {
 			case RADEON_HPD_1:
 				WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN);
@@ -779,6 +724,7 @@
 				break;
 			}
 		}
+		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
 	}
 	if (rdev->irq.installed)
 		r600_irq_set(rdev);
@@ -856,7 +802,7 @@
 	/* flush hdp cache so updates hit vram */
 	if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
 	    !(rdev->flags & RADEON_IS_AGP)) {
-		void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+		void __iomem *ptr = (void *)rdev->gart.ptr;
 		u32 tmp;
 
 		/* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
@@ -891,7 +837,7 @@
 {
 	int r;
 
-	if (rdev->gart.table.vram.robj) {
+	if (rdev->gart.robj) {
 		WARN(1, "R600 PCIE GART already initialized\n");
 		return 0;
 	}
@@ -908,7 +854,7 @@
 	u32 tmp;
 	int r, i;
 
-	if (rdev->gart.table.vram.robj == NULL) {
+	if (rdev->gart.robj == NULL) {
 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
 		return -EINVAL;
 	}
@@ -953,6 +899,9 @@
 		WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
 
 	r600_pcie_gart_tlb_flush(rdev);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+		 (unsigned)(rdev->mc.gtt_size >> 20),
+		 (unsigned long long)rdev->gart.table_addr);
 	rdev->gart.ready = true;
 	return 0;
 }
@@ -960,7 +909,7 @@
 void r600_pcie_gart_disable(struct radeon_device *rdev)
 {
 	u32 tmp;
-	int i, r;
+	int i;
 
 	/* Disable all tables */
 	for (i = 0; i < 7; i++)
@@ -987,14 +936,7 @@
 	WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp);
 	WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp);
 	WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp);
-	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);
-		}
-	}
+	radeon_gart_table_vram_unpin(rdev);
 }
 
 void r600_pcie_gart_fini(struct radeon_device *rdev)
@@ -1094,7 +1036,7 @@
 		WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start >> 12);
 		WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end >> 12);
 	}
-	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
+	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12);
 	tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
 	tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
 	WREG32(MC_VM_FB_LOCATION, tmp);
@@ -1233,6 +1175,53 @@
 	return 0;
 }
 
+int r600_vram_scratch_init(struct radeon_device *rdev)
+{
+	int r;
+
+	if (rdev->vram_scratch.robj == NULL) {
+		r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE,
+				     PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
+				     &rdev->vram_scratch.robj);
+		if (r) {
+			return r;
+		}
+	}
+
+	r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
+	if (unlikely(r != 0))
+		return r;
+	r = radeon_bo_pin(rdev->vram_scratch.robj,
+			  RADEON_GEM_DOMAIN_VRAM, &rdev->vram_scratch.gpu_addr);
+	if (r) {
+		radeon_bo_unreserve(rdev->vram_scratch.robj);
+		return r;
+	}
+	r = radeon_bo_kmap(rdev->vram_scratch.robj,
+				(void **)&rdev->vram_scratch.ptr);
+	if (r)
+		radeon_bo_unpin(rdev->vram_scratch.robj);
+	radeon_bo_unreserve(rdev->vram_scratch.robj);
+
+	return r;
+}
+
+void r600_vram_scratch_fini(struct radeon_device *rdev)
+{
+	int r;
+
+	if (rdev->vram_scratch.robj == NULL) {
+		return;
+	}
+	r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
+	if (likely(r == 0)) {
+		radeon_bo_kunmap(rdev->vram_scratch.robj);
+		radeon_bo_unpin(rdev->vram_scratch.robj);
+		radeon_bo_unreserve(rdev->vram_scratch.robj);
+	}
+	radeon_bo_unref(&rdev->vram_scratch.robj);
+}
+
 /* We doesn't check that the GPU really needs a reset we simply do the
  * reset, it's up to the caller to determine if the GPU needs one. We
  * might add an helper function to check that.
@@ -2288,6 +2277,14 @@
 	if (rdev->wb.use_event) {
 		u64 addr = rdev->wb.gpu_addr + R600_WB_EVENT_OFFSET +
 			(u64)(rdev->fence_drv.scratch_reg - rdev->scratch.reg_base);
+		/* flush read cache over gart */
+		radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3));
+		radeon_ring_write(rdev, PACKET3_TC_ACTION_ENA |
+					PACKET3_VC_ACTION_ENA |
+					PACKET3_SH_ACTION_ENA);
+		radeon_ring_write(rdev, 0xFFFFFFFF);
+		radeon_ring_write(rdev, 0);
+		radeon_ring_write(rdev, 10); /* poll interval */
 		/* EVENT_WRITE_EOP - flush caches, send int */
 		radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
 		radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5));
@@ -2296,6 +2293,14 @@
 		radeon_ring_write(rdev, fence->seq);
 		radeon_ring_write(rdev, 0);
 	} else {
+		/* flush read cache over gart */
+		radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3));
+		radeon_ring_write(rdev, PACKET3_TC_ACTION_ENA |
+					PACKET3_VC_ACTION_ENA |
+					PACKET3_SH_ACTION_ENA);
+		radeon_ring_write(rdev, 0xFFFFFFFF);
+		radeon_ring_write(rdev, 0);
+		radeon_ring_write(rdev, 10); /* poll interval */
 		radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0));
 		radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0));
 		/* wait for 3D idle clean */
@@ -2322,19 +2327,33 @@
 
 	mutex_lock(&rdev->r600_blit.mutex);
 	rdev->r600_blit.vb_ib = NULL;
-	r = r600_blit_prepare_copy(rdev, num_gpu_pages * RADEON_GPU_PAGE_SIZE);
+	r = r600_blit_prepare_copy(rdev, num_gpu_pages);
 	if (r) {
 		if (rdev->r600_blit.vb_ib)
 			radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
 		mutex_unlock(&rdev->r600_blit.mutex);
 		return r;
 	}
-	r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages * RADEON_GPU_PAGE_SIZE);
+	r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages);
 	r600_blit_done_copy(rdev, fence);
 	mutex_unlock(&rdev->r600_blit.mutex);
 	return 0;
 }
 
+void r600_blit_suspend(struct radeon_device *rdev)
+{
+	int r;
+
+	/* unpin shaders bo */
+	if (rdev->r600_blit.shader_obj) {
+		r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+		if (!r) {
+			radeon_bo_unpin(rdev->r600_blit.shader_obj);
+			radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+		}
+	}
+}
+
 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)
@@ -2363,6 +2382,10 @@
 		}
 	}
 
+	r = r600_vram_scratch_init(rdev);
+	if (r)
+		return r;
+
 	r600_mc_program(rdev);
 	if (rdev->flags & RADEON_IS_AGP) {
 		r600_agp_enable(rdev);
@@ -2454,8 +2477,6 @@
 
 int r600_suspend(struct radeon_device *rdev)
 {
-	int r;
-
 	r600_audio_fini(rdev);
 	/* FIXME: we should wait for ring to be empty */
 	r600_cp_stop(rdev);
@@ -2463,14 +2484,8 @@
 	r600_irq_suspend(rdev);
 	radeon_wb_disable(rdev);
 	r600_pcie_gart_disable(rdev);
-	/* unpin shaders bo */
-	if (rdev->r600_blit.shader_obj) {
-		r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
-		if (!r) {
-			radeon_bo_unpin(rdev->r600_blit.shader_obj);
-			radeon_bo_unreserve(rdev->r600_blit.shader_obj);
-		}
-	}
+	r600_blit_suspend(rdev);
+
 	return 0;
 }
 
@@ -2591,6 +2606,7 @@
 	radeon_ib_pool_fini(rdev);
 	radeon_irq_kms_fini(rdev);
 	r600_pcie_gart_fini(rdev);
+	r600_vram_scratch_fini(rdev);
 	radeon_agp_fini(rdev);
 	radeon_gem_fini(rdev);
 	radeon_fence_driver_fini(rdev);
@@ -3097,7 +3113,7 @@
 	return 0;
 }
 
-static inline void r600_irq_ack(struct radeon_device *rdev)
+static void r600_irq_ack(struct radeon_device *rdev)
 {
 	u32 tmp;
 
@@ -3198,7 +3214,7 @@
 	r600_disable_interrupt_state(rdev);
 }
 
-static inline u32 r600_get_ih_wptr(struct radeon_device *rdev)
+static u32 r600_get_ih_wptr(struct radeon_device *rdev)
 {
 	u32 wptr, tmp;
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r600_cp.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r600_cp.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r600_cp.c	2012-03-19 21:30:44.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r600_cp.c	2012-03-19 21:32:16.000000000 -0400
@@ -26,6 +26,8 @@
  *     Alex Deucher <alexander.deucher@amd.com>
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "drm.h"
 #include "radeon_drm.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r600_cs.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r600_cs.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r600_cs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r600_cs.c	2012-01-04 18:55:44.000000000 -0500
@@ -162,7 +162,7 @@
 	[V_038004_FMT_32_AS_32_32_32_32] = { 1, 1, 4, 0, CHIP_CEDAR},
 };
 
-static inline bool fmt_is_valid_color(u32 format)
+static bool fmt_is_valid_color(u32 format)
 {
 	if (format >= ARRAY_SIZE(color_formats_table))
 		return false;
@@ -173,7 +173,7 @@
 	return false;
 }
 
-static inline bool fmt_is_valid_texture(u32 format, enum radeon_family family)
+static bool fmt_is_valid_texture(u32 format, enum radeon_family family)
 {
 	if (format >= ARRAY_SIZE(color_formats_table))
 		return false;
@@ -187,7 +187,7 @@
 	return false;
 }
 
-static inline int fmt_get_blocksize(u32 format)
+static int fmt_get_blocksize(u32 format)
 {
 	if (format >= ARRAY_SIZE(color_formats_table))
 		return 0;
@@ -195,7 +195,7 @@
 	return color_formats_table[format].blocksize;
 }
 
-static inline int fmt_get_nblocksx(u32 format, u32 w)
+static int fmt_get_nblocksx(u32 format, u32 w)
 {
 	unsigned bw;
 
@@ -209,7 +209,7 @@
 	return (w + bw - 1) / bw;
 }
 
-static inline int fmt_get_nblocksy(u32 format, u32 h)
+static int fmt_get_nblocksy(u32 format, u32 h)
 {
 	unsigned bh;
 
@@ -223,25 +223,6 @@
 	return (h + bh - 1) / bh;
 }
 
-static inline int r600_bpe_from_format(u32 *bpe, u32 format)
-{
- 	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 {
 	int array_mode;
 	u32 group_size;
@@ -252,7 +233,7 @@
 };
 
 /* returns alignment in pixels for pitch/height/depth and bytes for base */
-static inline int r600_get_array_mode_alignment(struct array_mode_checker *values,
+static int r600_get_array_mode_alignment(struct array_mode_checker *values,
 						u32 *pitch_align,
 						u32 *height_align,
 						u32 *depth_align,
@@ -331,7 +312,7 @@
 	track->db_depth_control = 0xFFFFFFFF;
 }
 
-static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
+static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
 {
 	struct r600_cs_track *track = p->track;
 	u32 slice_tile_max, size, tmp;
@@ -737,7 +718,7 @@
  * Check next packet is relocation packet3, do bo validation and compute
  * GPU offset using the provided start.
  **/
-static inline int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
+static int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
 {
 	struct radeon_cs_packet p3reloc;
 	int r;
@@ -911,7 +892,7 @@
  * if register is safe. If register is not flag as safe this function
  * will test it against a list of register needind special handling.
  */
-static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
+static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
 {
 	struct r600_cs_track *track = (struct r600_cs_track *)p->track;
 	struct radeon_cs_reloc *reloc;
@@ -960,7 +941,8 @@
 		track->db_depth_control = radeon_get_ib_value(p, idx);
 		break;
 	case R_028010_DB_DEPTH_INFO:
-		if (r600_cs_packet_next_is_pkt3_nop(p)) {
+		if (!p->keep_tiling_flags &&
+		    r600_cs_packet_next_is_pkt3_nop(p)) {
 			r = r600_cs_packet_next_reloc(p, &reloc);
 			if (r) {
 				dev_warn(p->dev, "bad SET_CONTEXT_REG "
@@ -1011,7 +993,8 @@
 	case R_0280B4_CB_COLOR5_INFO:
 	case R_0280B8_CB_COLOR6_INFO:
 	case R_0280BC_CB_COLOR7_INFO:
-		if (r600_cs_packet_next_is_pkt3_nop(p)) {
+		if (!p->keep_tiling_flags &&
+		     r600_cs_packet_next_is_pkt3_nop(p)) {
 			r = r600_cs_packet_next_reloc(p, &reloc);
 			if (r) {
 				dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
@@ -1215,7 +1198,7 @@
 	return 0;
 }
 
-static inline unsigned mip_minify(unsigned size, unsigned level)
+static unsigned mip_minify(unsigned size, unsigned level)
 {
 	unsigned val;
 
@@ -1285,7 +1268,7 @@
  * This function will check that the resource has valid field and that
  * the texture and mipmap bo object are big enough to cover this resource.
  */
-static inline int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
+static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
 					      struct radeon_bo *texture,
 					      struct radeon_bo *mipmap,
 					      u64 base_offset,
@@ -1310,10 +1293,12 @@
 	mip_offset <<= 8;
 
 	word0 = radeon_get_ib_value(p, idx + 0);
-	if (tiling_flags & RADEON_TILING_MACRO)
-		word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
-	else if (tiling_flags & RADEON_TILING_MICRO)
-		word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+	if (!p->keep_tiling_flags) {
+		if (tiling_flags & RADEON_TILING_MACRO)
+			word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
+		else if (tiling_flags & RADEON_TILING_MICRO)
+			word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+	}
 	word1 = radeon_get_ib_value(p, idx + 1);
 	w0 = G_038000_TEX_WIDTH(word0) + 1;
 	h0 = G_038004_TEX_HEIGHT(word1) + 1;
@@ -1640,10 +1625,12 @@
 					return -EINVAL;
 				}
 				base_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
-				if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-					ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
-				else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-					ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+				if (!p->keep_tiling_flags) {
+					if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+						ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
+					else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+						ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+				}
 				texture = reloc->robj;
 				/* tex mip base */
 				r = r600_cs_packet_next_reloc(p, &reloc);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r600d.h linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r600d.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/r600d.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/r600d.h	2012-01-04 18:55:44.000000000 -0500
@@ -79,6 +79,11 @@
 #define CB_COLOR0_SIZE                                  0x28060
 #define CB_COLOR0_VIEW                                  0x28080
 #define CB_COLOR0_INFO                                  0x280a0
+#	define CB_FORMAT(x)				((x) << 2)
+#       define CB_ARRAY_MODE(x)                         ((x) << 8)
+#	define CB_SOURCE_FORMAT(x)			((x) << 27)
+#	define CB_SF_EXPORT_FULL			0
+#	define CB_SF_EXPORT_NORM			1
 #define CB_COLOR0_TILE                                  0x280c0
 #define CB_COLOR0_FRAG                                  0x280e0
 #define CB_COLOR0_MASK                                  0x28100
@@ -417,6 +422,17 @@
 #define	SQ_PGM_START_VS					0x28858
 #define SQ_PGM_RESOURCES_VS                             0x28868
 #define SQ_PGM_CF_OFFSET_VS                             0x288d0
+
+#define SQ_VTX_CONSTANT_WORD0_0				0x30000
+#define SQ_VTX_CONSTANT_WORD1_0				0x30004
+#define SQ_VTX_CONSTANT_WORD2_0				0x30008
+#	define SQ_VTXC_BASE_ADDR_HI(x)			((x) << 0)
+#	define SQ_VTXC_STRIDE(x)			((x) << 8)
+#	define SQ_VTXC_ENDIAN_SWAP(x)			((x) << 30)
+#	define SQ_ENDIAN_NONE				0
+#	define SQ_ENDIAN_8IN16				1
+#	define SQ_ENDIAN_8IN32				2
+#define SQ_VTX_CONSTANT_WORD3_0				0x3000c
 #define	SQ_VTX_CONSTANT_WORD6_0				0x38018
 #define		S__SQ_VTX_CONSTANT_TYPE(x)			(((x) & 3) << 30)
 #define		G__SQ_VTX_CONSTANT_TYPE(x)			(((x) >> 30) & 3)
@@ -1352,6 +1368,12 @@
 #define   S_038010_DST_SEL_W(x)                        (((x) & 0x7) << 25)
 #define   G_038010_DST_SEL_W(x)                        (((x) >> 25) & 0x7)
 #define   C_038010_DST_SEL_W                           0xF1FFFFFF
+#	define SQ_SEL_X					0
+#	define SQ_SEL_Y					1
+#	define SQ_SEL_Z					2
+#	define SQ_SEL_W					3
+#	define SQ_SEL_0					4
+#	define SQ_SEL_1					5
 #define   S_038010_BASE_LEVEL(x)                       (((x) & 0xF) << 28)
 #define   G_038010_BASE_LEVEL(x)                       (((x) >> 28) & 0xF)
 #define   C_038010_BASE_LEVEL                          0x0FFFFFFF
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_acpi.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_acpi.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_acpi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_acpi.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,7 +35,8 @@
 
 	/* Fail only if calling the method fails and ATIF is supported */
 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-		printk(KERN_DEBUG "failed to evaluate ATIF got %s\n", acpi_format_exception(status));
+		DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n",
+				 acpi_format_exception(status));
 		kfree(buffer.pointer);
 		return 1;
 	}
@@ -50,13 +51,13 @@
 	acpi_handle handle;
 	int ret;
 
-	/* No need to proceed if we're sure that ATIF is not supported */
-	if (!ASIC_IS_AVIVO(rdev) || !rdev->bios)
-		return 0;
-
 	/* Get the device handle */
 	handle = DEVICE_ACPI_HANDLE(&rdev->pdev->dev);
 
+	/* No need to proceed if we're sure that ATIF is not supported */
+	if (!ASIC_IS_AVIVO(rdev) || !rdev->bios || !handle)
+		return 0;
+
 	/* Call the ATIF method */
 	ret = radeon_atif_call(handle);
 	if (ret)
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_asic.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_asic.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_asic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_asic.c	2012-01-04 18:55:44.000000000 -0500
@@ -765,9 +765,9 @@
 	.get_vblank_counter = &evergreen_get_vblank_counter,
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &evergreen_cs_parse,
-	.copy_blit = &evergreen_copy_blit,
+	.copy_blit = &r600_copy_blit,
 	.copy_dma = NULL,
-	.copy = &evergreen_copy_blit,
+	.copy = &r600_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = &radeon_atom_get_memory_clock,
@@ -812,9 +812,9 @@
 	.get_vblank_counter = &evergreen_get_vblank_counter,
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &evergreen_cs_parse,
-	.copy_blit = &evergreen_copy_blit,
+	.copy_blit = &r600_copy_blit,
 	.copy_dma = NULL,
-	.copy = &evergreen_copy_blit,
+	.copy = &r600_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = NULL,
@@ -834,7 +834,7 @@
 	.pm_misc = &evergreen_pm_misc,
 	.pm_prepare = &evergreen_pm_prepare,
 	.pm_finish = &evergreen_pm_finish,
-	.pm_init_profile = &rs780_pm_init_profile,
+	.pm_init_profile = &sumo_pm_init_profile,
 	.pm_get_dynpm_state = &r600_pm_get_dynpm_state,
 	.pre_page_flip = &evergreen_pre_page_flip,
 	.page_flip = &evergreen_page_flip,
@@ -859,9 +859,9 @@
 	.get_vblank_counter = &evergreen_get_vblank_counter,
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &evergreen_cs_parse,
-	.copy_blit = &evergreen_copy_blit,
+	.copy_blit = &r600_copy_blit,
 	.copy_dma = NULL,
-	.copy = &evergreen_copy_blit,
+	.copy = &r600_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = &radeon_atom_get_memory_clock,
@@ -906,9 +906,9 @@
 	.get_vblank_counter = &evergreen_get_vblank_counter,
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &evergreen_cs_parse,
-	.copy_blit = &evergreen_copy_blit,
+	.copy_blit = &r600_copy_blit,
 	.copy_dma = NULL,
-	.copy = &evergreen_copy_blit,
+	.copy = &r600_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = &radeon_atom_get_memory_clock,
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_asic.h linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_asic.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_asic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_asic.h	2012-01-04 18:55:44.000000000 -0500
@@ -364,11 +364,11 @@
 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);
+int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages);
 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);
+			unsigned num_gpu_pages);
 
 /*
  * rv770,rv730,rv710,rv740
@@ -401,9 +401,6 @@
 int evergreen_asic_reset(struct radeon_device *rdev);
 void evergreen_bandwidth_update(struct radeon_device *rdev);
 void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
-int evergreen_copy_blit(struct radeon_device *rdev,
-			uint64_t src_offset, uint64_t dst_offset,
-			unsigned num_gpu_pages, struct radeon_fence *fence);
 void evergreen_hpd_init(struct radeon_device *rdev);
 void evergreen_hpd_fini(struct radeon_device *rdev);
 bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
@@ -416,18 +413,12 @@
 extern void evergreen_pm_misc(struct radeon_device *rdev);
 extern void evergreen_pm_prepare(struct radeon_device *rdev);
 extern void evergreen_pm_finish(struct radeon_device *rdev);
+extern void sumo_pm_init_profile(struct radeon_device *rdev);
 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
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_atombios.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_atombios.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_atombios.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_atombios.c	2012-01-04 18:55:44.000000000 -0500
@@ -62,7 +62,88 @@
 	struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1;
 };
 
-static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,
+static void radeon_lookup_i2c_gpio_quirks(struct radeon_device *rdev,
+					  ATOM_GPIO_I2C_ASSIGMENT *gpio,
+					  u8 index)
+{
+	/* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */
+	if ((rdev->family == CHIP_R420) ||
+	    (rdev->family == CHIP_R423) ||
+	    (rdev->family == CHIP_RV410)) {
+		if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) ||
+		    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) ||
+		    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) {
+			gpio->ucClkMaskShift = 0x19;
+			gpio->ucDataMaskShift = 0x18;
+		}
+	}
+
+	/* some evergreen boards have bad data for this entry */
+	if (ASIC_IS_DCE4(rdev)) {
+		if ((index == 7) &&
+		    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
+		    (gpio->sucI2cId.ucAccess == 0)) {
+			gpio->sucI2cId.ucAccess = 0x97;
+			gpio->ucDataMaskShift = 8;
+			gpio->ucDataEnShift = 8;
+			gpio->ucDataY_Shift = 8;
+			gpio->ucDataA_Shift = 8;
+		}
+	}
+
+	/* some DCE3 boards have bad data for this entry */
+	if (ASIC_IS_DCE3(rdev)) {
+		if ((index == 4) &&
+		    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
+		    (gpio->sucI2cId.ucAccess == 0x94))
+			gpio->sucI2cId.ucAccess = 0x14;
+	}
+}
+
+static struct radeon_i2c_bus_rec radeon_get_bus_rec_for_i2c_gpio(ATOM_GPIO_I2C_ASSIGMENT *gpio)
+{
+	struct radeon_i2c_bus_rec i2c;
+
+	memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
+
+	i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
+	i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
+	i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
+	i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
+	i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
+	i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
+	i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
+	i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
+	i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
+	i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
+	i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
+	i2c.en_data_mask = (1 << gpio->ucDataEnShift);
+	i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
+	i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
+	i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
+	i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
+
+	if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
+		i2c.hw_capable = true;
+	else
+		i2c.hw_capable = false;
+
+	if (gpio->sucI2cId.ucAccess == 0xa0)
+		i2c.mm_i2c = true;
+	else
+		i2c.mm_i2c = false;
+
+	i2c.i2c_id = gpio->sucI2cId.ucAccess;
+
+	if (i2c.mask_clk_reg)
+		i2c.valid = true;
+	else
+		i2c.valid = false;
+
+	return i2c;
+}
+
+static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,
 							       uint8_t id)
 {
 	struct atom_context *ctx = rdev->mode_info.atom_context;
@@ -85,59 +166,10 @@
 		for (i = 0; i < num_indices; i++) {
 			gpio = &i2c_info->asGPIO_Info[i];
 
-			/* some evergreen boards have bad data for this entry */
-			if (ASIC_IS_DCE4(rdev)) {
-				if ((i == 7) &&
-				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
-				    (gpio->sucI2cId.ucAccess == 0)) {
-					gpio->sucI2cId.ucAccess = 0x97;
-					gpio->ucDataMaskShift = 8;
-					gpio->ucDataEnShift = 8;
-					gpio->ucDataY_Shift = 8;
-					gpio->ucDataA_Shift = 8;
-				}
-			}
-
-			/* some DCE3 boards have bad data for this entry */
-			if (ASIC_IS_DCE3(rdev)) {
-				if ((i == 4) &&
-				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
-				    (gpio->sucI2cId.ucAccess == 0x94))
-					gpio->sucI2cId.ucAccess = 0x14;
-			}
+			radeon_lookup_i2c_gpio_quirks(rdev, gpio, i);
 
 			if (gpio->sucI2cId.ucAccess == id) {
-				i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
-				i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
-				i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
-				i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
-				i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
-				i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
-				i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
-				i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
-				i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
-				i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
-				i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
-				i2c.en_data_mask = (1 << gpio->ucDataEnShift);
-				i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
-				i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
-				i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
-				i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
-
-				if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
-					i2c.hw_capable = true;
-				else
-					i2c.hw_capable = false;
-
-				if (gpio->sucI2cId.ucAccess == 0xa0)
-					i2c.mm_i2c = true;
-				else
-					i2c.mm_i2c = false;
-
-				i2c.i2c_id = gpio->sucI2cId.ucAccess;
-
-				if (i2c.mask_clk_reg)
-					i2c.valid = true;
+				i2c = radeon_get_bus_rec_for_i2c_gpio(gpio);
 				break;
 			}
 		}
@@ -157,8 +189,6 @@
 	int i, num_indices;
 	char stmp[32];
 
-	memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
-
 	if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
 		i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
 
@@ -167,60 +197,12 @@
 
 		for (i = 0; i < num_indices; i++) {
 			gpio = &i2c_info->asGPIO_Info[i];
-			i2c.valid = false;
-
-			/* some evergreen boards have bad data for this entry */
-			if (ASIC_IS_DCE4(rdev)) {
-				if ((i == 7) &&
-				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
-				    (gpio->sucI2cId.ucAccess == 0)) {
-					gpio->sucI2cId.ucAccess = 0x97;
-					gpio->ucDataMaskShift = 8;
-					gpio->ucDataEnShift = 8;
-					gpio->ucDataY_Shift = 8;
-					gpio->ucDataA_Shift = 8;
-				}
-			}
-
-			/* some DCE3 boards have bad data for this entry */
-			if (ASIC_IS_DCE3(rdev)) {
-				if ((i == 4) &&
-				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
-				    (gpio->sucI2cId.ucAccess == 0x94))
-					gpio->sucI2cId.ucAccess = 0x14;
-			}
-
-			i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
-			i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
-			i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
-			i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
-			i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
-			i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
-			i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
-			i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
-			i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
-			i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
-			i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
-			i2c.en_data_mask = (1 << gpio->ucDataEnShift);
-			i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
-			i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
-			i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
-			i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
 
-			if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
-				i2c.hw_capable = true;
-			else
-				i2c.hw_capable = false;
-
-			if (gpio->sucI2cId.ucAccess == 0xa0)
-				i2c.mm_i2c = true;
-			else
-				i2c.mm_i2c = false;
+			radeon_lookup_i2c_gpio_quirks(rdev, gpio, i);
 
-			i2c.i2c_id = gpio->sucI2cId.ucAccess;
+			i2c = radeon_get_bus_rec_for_i2c_gpio(gpio);
 
-			if (i2c.mask_clk_reg) {
-				i2c.valid = true;
+			if (i2c.valid) {
 				sprintf(stmp, "0x%x", i2c.i2c_id);
 				rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp);
 			}
@@ -228,7 +210,7 @@
 	}
 }
 
-static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev,
+static struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev,
 							u8 id)
 {
 	struct atom_context *ctx = rdev->mode_info.atom_context;
@@ -1996,10 +1978,14 @@
 		return state_index;
 	/* last mode is usually default, array is low to high */
 	for (i = 0; i < num_modes; i++) {
+		rdev->pm.power_state[state_index].clock_info =
+			kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+		if (!rdev->pm.power_state[state_index].clock_info)
+			return state_index;
+		rdev->pm.power_state[state_index].num_clock_modes = 1;
 		rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
 		switch (frev) {
 		case 1:
-			rdev->pm.power_state[state_index].num_clock_modes = 1;
 			rdev->pm.power_state[state_index].clock_info[0].mclk =
 				le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock);
 			rdev->pm.power_state[state_index].clock_info[0].sclk =
@@ -2035,7 +2021,6 @@
 			state_index++;
 			break;
 		case 2:
-			rdev->pm.power_state[state_index].num_clock_modes = 1;
 			rdev->pm.power_state[state_index].clock_info[0].mclk =
 				le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock);
 			rdev->pm.power_state[state_index].clock_info[0].sclk =
@@ -2072,7 +2057,6 @@
 			state_index++;
 			break;
 		case 3:
-			rdev->pm.power_state[state_index].num_clock_modes = 1;
 			rdev->pm.power_state[state_index].clock_info[0].mclk =
 				le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock);
 			rdev->pm.power_state[state_index].clock_info[0].sclk =
@@ -2257,7 +2241,7 @@
 		rdev->pm.default_power_state_index = state_index;
 		rdev->pm.power_state[state_index].default_clock_mode =
 			&rdev->pm.power_state[state_index].clock_info[mode_index - 1];
-		if (ASIC_IS_DCE5(rdev)) {
+		if (ASIC_IS_DCE5(rdev) && !(rdev->flags & RADEON_IS_IGP)) {
 			/* NI chips post without MC ucode, so default clocks are strobe mode only */
 			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;
@@ -2377,17 +2361,31 @@
 			 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) +
 			 (power_state->v1.ucNonClockStateIndex *
 			  power_info->pplib.ucNonClockSize));
-		for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) {
-			clock_info = (union pplib_clock_info *)
-				(mode_info->atom_context->bios + data_offset +
-				 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) +
-				 (power_state->v1.ucClockStateIndices[j] *
-				  power_info->pplib.ucClockInfoSize));
-			valid = radeon_atombios_parse_pplib_clock_info(rdev,
-								       state_index, mode_index,
-								       clock_info);
-			if (valid)
-				mode_index++;
+		rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) *
+							     ((power_info->pplib.ucStateEntrySize - 1) ?
+							      (power_info->pplib.ucStateEntrySize - 1) : 1),
+							     GFP_KERNEL);
+		if (!rdev->pm.power_state[i].clock_info)
+			return state_index;
+		if (power_info->pplib.ucStateEntrySize - 1) {
+			for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) {
+				clock_info = (union pplib_clock_info *)
+					(mode_info->atom_context->bios + data_offset +
+					 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) +
+					 (power_state->v1.ucClockStateIndices[j] *
+					  power_info->pplib.ucClockInfoSize));
+				valid = radeon_atombios_parse_pplib_clock_info(rdev,
+									       state_index, mode_index,
+									       clock_info);
+				if (valid)
+					mode_index++;
+			}
+		} else {
+			rdev->pm.power_state[state_index].clock_info[0].mclk =
+				rdev->clock.default_mclk;
+			rdev->pm.power_state[state_index].clock_info[0].sclk =
+				rdev->clock.default_sclk;
+			mode_index++;
 		}
 		rdev->pm.power_state[state_index].num_clock_modes = mode_index;
 		if (mode_index) {
@@ -2456,18 +2454,32 @@
 		non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */
 		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
 			&non_clock_info_array->nonClockInfo[non_clock_array_index];
-		for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
-			clock_array_index = power_state->v2.clockInfoIndex[j];
-			/* XXX this might be an inagua bug... */
-			if (clock_array_index >= clock_info_array->ucNumEntries)
-				continue;
-			clock_info = (union pplib_clock_info *)
-				&clock_info_array->clockInfo[clock_array_index];
-			valid = radeon_atombios_parse_pplib_clock_info(rdev,
-								       state_index, mode_index,
-								       clock_info);
-			if (valid)
-				mode_index++;
+		rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) *
+							     (power_state->v2.ucNumDPMLevels ?
+							      power_state->v2.ucNumDPMLevels : 1),
+							     GFP_KERNEL);
+		if (!rdev->pm.power_state[i].clock_info)
+			return state_index;
+		if (power_state->v2.ucNumDPMLevels) {
+			for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
+				clock_array_index = power_state->v2.clockInfoIndex[j];
+				/* XXX this might be an inagua bug... */
+				if (clock_array_index >= clock_info_array->ucNumEntries)
+					continue;
+				clock_info = (union pplib_clock_info *)
+					&clock_info_array->clockInfo[clock_array_index];
+				valid = radeon_atombios_parse_pplib_clock_info(rdev,
+									       state_index, mode_index,
+									       clock_info);
+				if (valid)
+					mode_index++;
+			}
+		} else {
+			rdev->pm.power_state[state_index].clock_info[0].mclk =
+				rdev->clock.default_mclk;
+			rdev->pm.power_state[state_index].clock_info[0].sclk =
+				rdev->clock.default_sclk;
+			mode_index++;
 		}
 		rdev->pm.power_state[state_index].num_clock_modes = mode_index;
 		if (mode_index) {
@@ -2524,19 +2536,23 @@
 	} else {
 		rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state), GFP_KERNEL);
 		if (rdev->pm.power_state) {
-			/* add the default mode */
-			rdev->pm.power_state[state_index].type =
-				POWER_STATE_TYPE_DEFAULT;
-			rdev->pm.power_state[state_index].num_clock_modes = 1;
-			rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
-			rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
-			rdev->pm.power_state[state_index].default_clock_mode =
-				&rdev->pm.power_state[state_index].clock_info[0];
-			rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
-			rdev->pm.power_state[state_index].pcie_lanes = 16;
-			rdev->pm.default_power_state_index = state_index;
-			rdev->pm.power_state[state_index].flags = 0;
-			state_index++;
+			rdev->pm.power_state[0].clock_info =
+				kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+			if (rdev->pm.power_state[0].clock_info) {
+				/* add the default mode */
+				rdev->pm.power_state[state_index].type =
+					POWER_STATE_TYPE_DEFAULT;
+				rdev->pm.power_state[state_index].num_clock_modes = 1;
+				rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
+				rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
+				rdev->pm.power_state[state_index].default_clock_mode =
+					&rdev->pm.power_state[state_index].clock_info[0];
+				rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
+				rdev->pm.power_state[state_index].pcie_lanes = 16;
+				rdev->pm.default_power_state_index = state_index;
+				rdev->pm.power_state[state_index].flags = 0;
+				state_index++;
+			}
 		}
 	}
 
@@ -2544,7 +2560,11 @@
 
 	rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
 	rdev->pm.current_clock_mode_index = 0;
-	rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+	if (rdev->pm.default_power_state_index >= 0)
+		rdev->pm.current_vddc =
+			rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+	else
+		rdev->pm.current_vddc = 0;
 }
 
 void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_benchmark.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_benchmark.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_benchmark.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_benchmark.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,21 +26,81 @@
 #include "radeon_reg.h"
 #include "radeon.h"
 
-void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
-			   unsigned sdomain, unsigned ddomain)
+#define RADEON_BENCHMARK_COPY_BLIT 1
+#define RADEON_BENCHMARK_COPY_DMA  0
+
+#define RADEON_BENCHMARK_ITERATIONS 1024
+#define RADEON_BENCHMARK_COMMON_MODES_N 17
+
+static int radeon_benchmark_do_move(struct radeon_device *rdev, unsigned size,
+				    uint64_t saddr, uint64_t daddr,
+				    int flag, int n)
+{
+	unsigned long start_jiffies;
+	unsigned long end_jiffies;
+	struct radeon_fence *fence = NULL;
+	int i, r;
+
+	start_jiffies = jiffies;
+	for (i = 0; i < n; i++) {
+		r = radeon_fence_create(rdev, &fence);
+		if (r)
+			return r;
+
+		switch (flag) {
+		case RADEON_BENCHMARK_COPY_DMA:
+			r = radeon_copy_dma(rdev, saddr, daddr,
+					    size / RADEON_GPU_PAGE_SIZE,
+					    fence);
+			break;
+		case RADEON_BENCHMARK_COPY_BLIT:
+			r = radeon_copy_blit(rdev, saddr, daddr,
+					     size / RADEON_GPU_PAGE_SIZE,
+					     fence);
+			break;
+		default:
+			DRM_ERROR("Unknown copy method\n");
+			r = -EINVAL;
+		}
+		if (r)
+			goto exit_do_move;
+		r = radeon_fence_wait(fence, false);
+		if (r)
+			goto exit_do_move;
+		radeon_fence_unref(&fence);
+	}
+	end_jiffies = jiffies;
+	r = jiffies_to_msecs(end_jiffies - start_jiffies);
+
+exit_do_move:
+	if (fence)
+		radeon_fence_unref(&fence);
+	return r;
+}
+
+
+static void radeon_benchmark_log_results(int n, unsigned size,
+					 unsigned int time,
+					 unsigned sdomain, unsigned ddomain,
+					 char *kind)
+{
+	unsigned int throughput = (n * (size >> 10)) / time;
+	DRM_INFO("radeon: %s %u bo moves of %u kB from"
+		 " %d to %d in %u ms, throughput: %u Mb/s or %u MB/s\n",
+		 kind, n, size >> 10, sdomain, ddomain, time,
+		 throughput * 8, throughput);
+}
+
+static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size,
+				  unsigned sdomain, unsigned ddomain)
 {
 	struct radeon_bo *dobj = NULL;
 	struct radeon_bo *sobj = NULL;
-	struct radeon_fence *fence = NULL;
 	uint64_t saddr, daddr;
-	unsigned long start_jiffies;
-	unsigned long end_jiffies;
-	unsigned long time;
-	unsigned i, n, size;
-	int r;
+	int r, n;
+	int time;
 
-	size = bsize;
-	n = 1024;
+	n = RADEON_BENCHMARK_ITERATIONS;
 	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, &sobj);
 	if (r) {
 		goto out_cleanup;
@@ -67,65 +127,26 @@
 	}
 
 	/* r100 doesn't have dma engine so skip the test */
-	if (rdev->asic->copy_dma) {
-
-		start_jiffies = jiffies;
-		for (i = 0; i < n; i++) {
-			r = radeon_fence_create(rdev, &fence);
-			if (r) {
-				goto out_cleanup;
-			}
-
-			r = radeon_copy_dma(rdev, saddr, daddr,
-					size / RADEON_GPU_PAGE_SIZE, fence);
-
-			if (r) {
-				goto out_cleanup;
-			}
-			r = radeon_fence_wait(fence, false);
-			if (r) {
-				goto out_cleanup;
-			}
-			radeon_fence_unref(&fence);
-		}
-		end_jiffies = jiffies;
-		time = end_jiffies - start_jiffies;
-		time = jiffies_to_msecs(time);
-		if (time > 0) {
-			i = ((n * size) >> 10) / time;
-			printk(KERN_INFO "radeon: dma %u bo moves of %ukb from"
-					" %d to %d in %lums (%ukb/ms %ukb/s %uM/s)\n",
-					n, size >> 10,
-					sdomain, ddomain, time,
-					i, i * 1000, (i * 1000) / 1024);
-		}
-	}
-
-	start_jiffies = jiffies;
-	for (i = 0; i < n; i++) {
-		r = radeon_fence_create(rdev, &fence);
-		if (r) {
-			goto out_cleanup;
-		}
-		r = radeon_copy_blit(rdev, saddr, daddr, size / RADEON_GPU_PAGE_SIZE, fence);
-		if (r) {
-			goto out_cleanup;
-		}
-		r = radeon_fence_wait(fence, false);
-		if (r) {
+	/* also, VRAM-to-VRAM test doesn't make much sense for DMA */
+	/* skip it as well if domains are the same */
+	if ((rdev->asic->copy_dma) && (sdomain != ddomain)) {
+		time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
+						RADEON_BENCHMARK_COPY_DMA, n);
+		if (time < 0)
 			goto out_cleanup;
-		}
-		radeon_fence_unref(&fence);
-	}
-	end_jiffies = jiffies;
-	time = end_jiffies - start_jiffies;
-	time = jiffies_to_msecs(time);
-	if (time > 0) {
-		i = ((n * size) >> 10) / time;
-		printk(KERN_INFO "radeon: blit %u bo moves of %ukb from %d to %d"
-		       " in %lums (%ukb/ms %ukb/s %uM/s)\n", n, size >> 10,
-		       sdomain, ddomain, time, i, i * 1000, (i * 1000) / 1024);
+		if (time > 0)
+			radeon_benchmark_log_results(n, size, time,
+						     sdomain, ddomain, "dma");
 	}
+
+	time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
+					RADEON_BENCHMARK_COPY_BLIT, n);
+	if (time < 0)
+		goto out_cleanup;
+	if (time > 0)
+		radeon_benchmark_log_results(n, size, time,
+					     sdomain, ddomain, "blit");
+
 out_cleanup:
 	if (sobj) {
 		r = radeon_bo_reserve(sobj, false);
@@ -143,18 +164,92 @@
 		}
 		radeon_bo_unref(&dobj);
 	}
-	if (fence) {
-		radeon_fence_unref(&fence);
-	}
+
 	if (r) {
-		printk(KERN_WARNING "Error while benchmarking BO move.\n");
+		DRM_ERROR("Error while benchmarking BO move.\n");
 	}
 }
 
-void radeon_benchmark(struct radeon_device *rdev)
+void radeon_benchmark(struct radeon_device *rdev, int test_number)
 {
-	radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_GTT,
-			      RADEON_GEM_DOMAIN_VRAM);
-	radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM,
-			      RADEON_GEM_DOMAIN_GTT);
+	int i;
+	int common_modes[RADEON_BENCHMARK_COMMON_MODES_N] = {
+		640 * 480 * 4,
+		720 * 480 * 4,
+		800 * 600 * 4,
+		848 * 480 * 4,
+		1024 * 768 * 4,
+		1152 * 768 * 4,
+		1280 * 720 * 4,
+		1280 * 800 * 4,
+		1280 * 854 * 4,
+		1280 * 960 * 4,
+		1280 * 1024 * 4,
+		1440 * 900 * 4,
+		1400 * 1050 * 4,
+		1680 * 1050 * 4,
+		1600 * 1200 * 4,
+		1920 * 1080 * 4,
+		1920 * 1200 * 4
+	};
+
+	switch (test_number) {
+	case 1:
+		/* simple test, VRAM to GTT and GTT to VRAM */
+		radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_GTT,
+				      RADEON_GEM_DOMAIN_VRAM);
+		radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM,
+				      RADEON_GEM_DOMAIN_GTT);
+		break;
+	case 2:
+		/* simple test, VRAM to VRAM */
+		radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM,
+				      RADEON_GEM_DOMAIN_VRAM);
+		break;
+	case 3:
+		/* GTT to VRAM, buffer size sweep, powers of 2 */
+		for (i = 1; i <= 65536; i <<= 1)
+			radeon_benchmark_move(rdev, i*1024,
+					      RADEON_GEM_DOMAIN_GTT,
+					      RADEON_GEM_DOMAIN_VRAM);
+		break;
+	case 4:
+		/* VRAM to GTT, buffer size sweep, powers of 2 */
+		for (i = 1; i <= 65536; i <<= 1)
+			radeon_benchmark_move(rdev, i*1024,
+					      RADEON_GEM_DOMAIN_VRAM,
+					      RADEON_GEM_DOMAIN_GTT);
+		break;
+	case 5:
+		/* VRAM to VRAM, buffer size sweep, powers of 2 */
+		for (i = 1; i <= 65536; i <<= 1)
+			radeon_benchmark_move(rdev, i*1024,
+					      RADEON_GEM_DOMAIN_VRAM,
+					      RADEON_GEM_DOMAIN_VRAM);
+		break;
+	case 6:
+		/* GTT to VRAM, buffer size sweep, common modes */
+		for (i = 1; i < RADEON_BENCHMARK_COMMON_MODES_N; i++)
+			radeon_benchmark_move(rdev, common_modes[i],
+					      RADEON_GEM_DOMAIN_GTT,
+					      RADEON_GEM_DOMAIN_VRAM);
+		break;
+	case 7:
+		/* VRAM to GTT, buffer size sweep, common modes */
+		for (i = 1; i < RADEON_BENCHMARK_COMMON_MODES_N; i++)
+			radeon_benchmark_move(rdev, common_modes[i],
+					      RADEON_GEM_DOMAIN_VRAM,
+					      RADEON_GEM_DOMAIN_GTT);
+		break;
+	case 8:
+		/* VRAM to VRAM, buffer size sweep, common modes */
+		for (i = 1; i < RADEON_BENCHMARK_COMMON_MODES_N; i++)
+			radeon_benchmark_move(rdev, common_modes[i],
+					      RADEON_GEM_DOMAIN_VRAM,
+					      RADEON_GEM_DOMAIN_VRAM);
+		break;
+
+	default:
+		DRM_ERROR("Unknown benchmark\n");
+	}
 }
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_combios.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_combios.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_combios.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_combios.c	2012-01-04 18:55:44.000000000 -0500
@@ -620,8 +620,8 @@
 		i2c.y_data_mask = 0x80;
 	} else {
 		/* default masks for ddc pads */
-		i2c.mask_clk_mask = RADEON_GPIO_EN_1;
-		i2c.mask_data_mask = RADEON_GPIO_EN_0;
+		i2c.mask_clk_mask = RADEON_GPIO_MASK_1;
+		i2c.mask_data_mask = RADEON_GPIO_MASK_0;
 		i2c.a_clk_mask = RADEON_GPIO_A_1;
 		i2c.a_data_mask = RADEON_GPIO_A_0;
 		i2c.en_clk_mask = RADEON_GPIO_EN_1;
@@ -2563,14 +2563,17 @@
 
 	/* allocate 2 power states */
 	rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * 2, GFP_KERNEL);
-	if (!rdev->pm.power_state) {
-		rdev->pm.default_power_state_index = state_index;
-		rdev->pm.num_power_states = 0;
-
-		rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
-		rdev->pm.current_clock_mode_index = 0;
-		return;
-	}
+	if (rdev->pm.power_state) {
+		/* allocate 1 clock mode per state */
+		rdev->pm.power_state[0].clock_info =
+			kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+		rdev->pm.power_state[1].clock_info =
+			kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+		if (!rdev->pm.power_state[0].clock_info ||
+		    !rdev->pm.power_state[1].clock_info)
+			goto pm_failed;
+	} else
+		goto pm_failed;
 
 	/* check for a thermal chip */
 	offset = combios_get_table_offset(dev, COMBIOS_OVERDRIVE_INFO_TABLE);
@@ -2735,6 +2738,14 @@
 
 	rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
 	rdev->pm.current_clock_mode_index = 0;
+	return;
+
+pm_failed:
+	rdev->pm.default_power_state_index = state_index;
+	rdev->pm.num_power_states = 0;
+
+	rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
+	rdev->pm.current_clock_mode_index = 0;
 }
 
 void radeon_external_tmds_setup(struct drm_encoder *encoder)
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_connectors.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_connectors.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_connectors.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_connectors.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,8 +44,6 @@
 radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
 			     struct drm_connector *drm_connector);
 
-bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector);
-
 void radeon_connector_hotplug(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
@@ -432,55 +430,6 @@
 	return 0;
 }
 
-/*
- * Some integrated ATI Radeon chipset implementations (e. g.
- * Asus M2A-VM HDMI) may indicate the availability of a DDC,
- * even when there's no monitor connected. For these connectors
- * following DDC probe extension will be applied: check also for the
- * availability of EDID with at least a correct EDID header. Only then,
- * DDC is assumed to be available. This prevents drm_get_edid() and
- * drm_edid_block_valid() from periodically dumping data and kernel
- * errors into the logs and onto the terminal.
- */
-static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
-				     uint32_t supported_device,
-				     int connector_type)
-{
-	/* Asus M2A-VM HDMI board sends data to i2c bus even,
-	 * if HDMI add-on card is not plugged in or HDMI is disabled in
-	 * BIOS. Valid DDC can only be assumed, if also a valid EDID header
-	 * can be retrieved via i2c bus during DDC probe */
-	if ((dev->pdev->device == 0x791e) &&
-	    (dev->pdev->subsystem_vendor == 0x1043) &&
-	    (dev->pdev->subsystem_device == 0x826d)) {
-		if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
-		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
-			return true;
-	}
-	/* ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
-	 * for a DVI connector that is not implemented */
-	if ((dev->pdev->device == 0x796e) &&
-	    (dev->pdev->subsystem_vendor == 0x1019) &&
-	    (dev->pdev->subsystem_device == 0x2615)) {
-		if ((connector_type == DRM_MODE_CONNECTOR_DVID) &&
-		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
-			return true;
-	}
-	/* TOSHIBA Satellite L300D with ATI Mobility Radeon x1100
-	 * (RS690M) sends data to i2c bus for a HDMI connector that
-	 * is not implemented */
-	if ((dev->pdev->device == 0x791f) &&
-	    (dev->pdev->subsystem_vendor == 0x1179) &&
-	    (dev->pdev->subsystem_device == 0xff68)) {
-		if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
-		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
-			return true;
-	}
-
-	/* Default: no EDID header probe required for DDC probing */
-	return false;
-}
-
 static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
 					  struct drm_connector *connector)
 {
@@ -721,9 +670,9 @@
 		ret = connector_status_disconnected;
 
 	if (radeon_connector->ddc_bus)
-		dret = radeon_ddc_probe(radeon_connector,
-					radeon_connector->requires_extended_probe);
+		dret = radeon_ddc_probe(radeon_connector);
 	if (dret) {
+		radeon_connector->detected_by_load = false;
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
 			radeon_connector->edid = NULL;
@@ -750,12 +699,21 @@
 	} else {
 
 		/* if we aren't forcing don't do destructive polling */
-		if (!force)
-			return connector->status;
+		if (!force) {
+			/* only return the previous status if we last
+			 * detected a monitor via load.
+			 */
+			if (radeon_connector->detected_by_load)
+				return connector->status;
+			else
+				return ret;
+		}
 
 		if (radeon_connector->dac_load_detect && encoder) {
 			encoder_funcs = encoder->helper_private;
 			ret = encoder_funcs->detect(encoder, connector);
+			if (ret != connector_status_disconnected)
+				radeon_connector->detected_by_load = true;
 		}
 	}
 
@@ -894,9 +852,9 @@
 	bool dret = false;
 
 	if (radeon_connector->ddc_bus)
-		dret = radeon_ddc_probe(radeon_connector,
-					radeon_connector->requires_extended_probe);
+		dret = radeon_ddc_probe(radeon_connector);
 	if (dret) {
+		radeon_connector->detected_by_load = false;
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
 			radeon_connector->edid = NULL;
@@ -959,8 +917,18 @@
 	if ((ret == connector_status_connected) && (radeon_connector->use_digital == true))
 		goto out;
 
+	/* DVI-D and HDMI-A are digital only */
+	if ((connector->connector_type == DRM_MODE_CONNECTOR_DVID) ||
+	    (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA))
+		goto out;
+
+	/* if we aren't forcing don't do destructive polling */
 	if (!force) {
-		ret = connector->status;
+		/* only return the previous status if we last
+		 * detected a monitor via load.
+		 */
+		if (radeon_connector->detected_by_load)
+			ret = connector->status;
 		goto out;
 	}
 
@@ -985,6 +953,8 @@
 					if (ret == connector_status_connected) {
 						radeon_connector->use_digital = false;
 					}
+					if (ret != connector_status_disconnected)
+						radeon_connector->detected_by_load = true;
 				}
 				break;
 			}
@@ -1181,7 +1151,8 @@
 		}
 	} else {
 		/* need to setup ddc on the bridge */
-		if (radeon_connector_encoder_is_dp_bridge(connector)) {
+		if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
+			ENCODER_OBJECT_ID_NONE) {
 			if (encoder)
 				radeon_atom_ext_encoder_setup_ddc(encoder);
 		}
@@ -1191,13 +1162,12 @@
 	return ret;
 }
 
-bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector)
+u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector)
 {
 	struct drm_mode_object *obj;
 	struct drm_encoder *encoder;
 	struct radeon_encoder *radeon_encoder;
 	int i;
-	bool found = false;
 
 	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
 		if (connector->encoder_ids[i] == 0)
@@ -1213,14 +1183,13 @@
 		switch (radeon_encoder->encoder_id) {
 		case ENCODER_OBJECT_ID_TRAVIS:
 		case ENCODER_OBJECT_ID_NUTMEG:
-			found = true;
-			break;
+			return radeon_encoder->encoder_id;
 		default:
 			break;
 		}
 	}
 
-	return found;
+	return ENCODER_OBJECT_ID_NONE;
 }
 
 bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector)
@@ -1297,7 +1266,8 @@
 		if (!radeon_dig_connector->edp_on)
 			atombios_set_edp_panel_power(connector,
 						     ATOM_TRANSMITTER_ACTION_POWER_OFF);
-	} else if (radeon_connector_encoder_is_dp_bridge(connector)) {
+	} else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
+		   ENCODER_OBJECT_ID_NONE) {
 		/* DP bridges are always DP */
 		radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
 		/* get the DPCD from the bridge */
@@ -1306,8 +1276,7 @@
 		if (encoder) {
 			/* setup ddc on the bridge */
 			radeon_atom_ext_encoder_setup_ddc(encoder);
-			if (radeon_ddc_probe(radeon_connector,
-					     radeon_connector->requires_extended_probe)) /* try DDC */
+			if (radeon_ddc_probe(radeon_connector)) /* try DDC */
 				ret = connector_status_connected;
 			else if (radeon_connector->dac_load_detect) { /* try load detection */
 				struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
@@ -1325,8 +1294,7 @@
 				if (radeon_dp_getdpcd(radeon_connector))
 					ret = connector_status_connected;
 			} else {
-				if (radeon_ddc_probe(radeon_connector,
-						     radeon_connector->requires_extended_probe))
+				if (radeon_ddc_probe(radeon_connector))
 					ret = connector_status_connected;
 			}
 		}
@@ -1471,9 +1439,7 @@
 	radeon_connector->shared_ddc = shared_ddc;
 	radeon_connector->connector_object_id = connector_object_id;
 	radeon_connector->hpd = *hpd;
-	radeon_connector->requires_extended_probe =
-		radeon_connector_needs_extended_probe(rdev, supported_device,
-							connector_type);
+
 	radeon_connector->router = *router;
 	if (router->ddc_valid || router->cd_valid) {
 		radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
@@ -1820,9 +1786,7 @@
 	radeon_connector->devices = supported_device;
 	radeon_connector->connector_object_id = connector_object_id;
 	radeon_connector->hpd = *hpd;
-	radeon_connector->requires_extended_probe =
-		radeon_connector_needs_extended_probe(rdev, supported_device,
-							connector_type);
+
 	switch (connector_type) {
 	case DRM_MODE_CONNECTOR_VGA:
 		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_cp.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_cp.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_cp.c	2012-03-19 21:30:06.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_cp.c	2012-03-19 21:31:45.000000000 -0400
@@ -29,6 +29,8 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "drm.h"
 #include "drm_sarea.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_cs.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_cs.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_cs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_cs.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,7 +93,7 @@
 {
 	struct drm_radeon_cs *cs = data;
 	uint64_t *chunk_array_ptr;
-	unsigned size, i;
+	unsigned size, i, flags = 0;
 
 	if (!cs->num_chunks) {
 		return 0;
@@ -140,6 +140,10 @@
 			if (p->chunks[i].length_dw == 0)
 				return -EINVAL;
 		}
+		if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS &&
+		    !p->chunks[i].length_dw) {
+			return -EINVAL;
+		}
 
 		p->chunks[i].length_dw = user_chunk.length_dw;
 		p->chunks[i].user_ptr = (void __user *)(unsigned long)user_chunk.chunk_data;
@@ -155,6 +159,9 @@
 					       p->chunks[i].user_ptr, size)) {
 				return -EFAULT;
 			}
+			if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS) {
+				flags = p->chunks[i].kdata[0];
+			}
 		} else {
 			p->chunks[i].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL);
 			p->chunks[i].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL);
@@ -174,6 +181,8 @@
 			  p->chunks[p->chunk_ib_idx].length_dw);
 		return -EINVAL;
 	}
+
+	p->keep_tiling_flags = (flags & RADEON_CS_KEEP_TILING_FLAGS) != 0;
 	return 0;
 }
 
@@ -222,7 +231,7 @@
 	struct radeon_cs_chunk *ib_chunk;
 	int r;
 
-	mutex_lock(&rdev->cs_mutex);
+	radeon_mutex_lock(&rdev->cs_mutex);
 	/* initialize parser */
 	memset(&parser, 0, sizeof(struct radeon_cs_parser));
 	parser.filp = filp;
@@ -233,14 +242,14 @@
 	if (r) {
 		DRM_ERROR("Failed to initialize parser !\n");
 		radeon_cs_parser_fini(&parser, r);
-		mutex_unlock(&rdev->cs_mutex);
+		radeon_mutex_unlock(&rdev->cs_mutex);
 		return r;
 	}
 	r =  radeon_ib_get(rdev, &parser.ib);
 	if (r) {
 		DRM_ERROR("Failed to get ib !\n");
 		radeon_cs_parser_fini(&parser, r);
-		mutex_unlock(&rdev->cs_mutex);
+		radeon_mutex_unlock(&rdev->cs_mutex);
 		return r;
 	}
 	r = radeon_cs_parser_relocs(&parser);
@@ -248,7 +257,7 @@
 		if (r != -ERESTARTSYS)
 			DRM_ERROR("Failed to parse relocation %d!\n", r);
 		radeon_cs_parser_fini(&parser, r);
-		mutex_unlock(&rdev->cs_mutex);
+		radeon_mutex_unlock(&rdev->cs_mutex);
 		return r;
 	}
 	/* Copy the packet into the IB, the parser will read from the
@@ -260,14 +269,14 @@
 	if (r || parser.parser_error) {
 		DRM_ERROR("Invalid command stream !\n");
 		radeon_cs_parser_fini(&parser, r);
-		mutex_unlock(&rdev->cs_mutex);
+		radeon_mutex_unlock(&rdev->cs_mutex);
 		return r;
 	}
 	r = radeon_cs_finish_pages(&parser);
 	if (r) {
 		DRM_ERROR("Invalid command stream !\n");
 		radeon_cs_parser_fini(&parser, r);
-		mutex_unlock(&rdev->cs_mutex);
+		radeon_mutex_unlock(&rdev->cs_mutex);
 		return r;
 	}
 	r = radeon_ib_schedule(rdev, parser.ib);
@@ -275,7 +284,7 @@
 		DRM_ERROR("Failed to schedule IB !\n");
 	}
 	radeon_cs_parser_fini(&parser, r);
-	mutex_unlock(&rdev->cs_mutex);
+	radeon_mutex_unlock(&rdev->cs_mutex);
 	return r;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_device.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_device.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_device.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_device.c	2012-01-04 18:55:44.000000000 -0500
@@ -716,7 +716,7 @@
 
 	/* mutex initialization are all done here so we
 	 * can recall function without having locking issues */
-	mutex_init(&rdev->cs_mutex);
+	radeon_mutex_init(&rdev->cs_mutex);
 	mutex_init(&rdev->ib_pool.mutex);
 	mutex_init(&rdev->cp.mutex);
 	mutex_init(&rdev->dc_hw_i2c_mutex);
@@ -750,14 +750,15 @@
 
 	/* set DMA mask + need_dma32 flags.
 	 * PCIE - can handle 40-bits.
-	 * IGP - can handle 40-bits (in theory)
+	 * IGP - can handle 40-bits
 	 * AGP - generally dma32 is safest
-	 * PCI - only dma32
+	 * PCI - dma32 for legacy pci gart, 40 bits on newer asics
 	 */
 	rdev->need_dma32 = false;
 	if (rdev->flags & RADEON_IS_AGP)
 		rdev->need_dma32 = true;
-	if (rdev->flags & RADEON_IS_PCI)
+	if ((rdev->flags & RADEON_IS_PCI) &&
+	    (rdev->family < CHIP_RS400))
 		rdev->need_dma32 = true;
 
 	dma_bits = rdev->need_dma32 ? 32 : 40;
@@ -817,7 +818,7 @@
 		radeon_test_moves(rdev);
 	}
 	if (radeon_benchmarking) {
-		radeon_benchmark(rdev);
+		radeon_benchmark(rdev, radeon_benchmarking);
 	}
 	return 0;
 }
@@ -954,6 +955,9 @@
 	int r;
 	int resched;
 
+	/* Prevent CS ioctl from interfering */
+	radeon_mutex_lock(&rdev->cs_mutex);
+
 	radeon_save_bios_scratch_regs(rdev);
 	/* block TTM */
 	resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
@@ -966,10 +970,15 @@
 		radeon_restore_bios_scratch_regs(rdev);
 		drm_helper_resume_force_mode(rdev->ddev);
 		ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-		return 0;
 	}
-	/* bad news, how to tell it to userspace ? */
-	dev_info(rdev->dev, "GPU reset failed\n");
+
+	radeon_mutex_unlock(&rdev->cs_mutex);
+
+	if (r) {
+		/* bad news, how to tell it to userspace ? */
+		dev_info(rdev->dev, "GPU reset failed\n");
+	}
+
 	return r;
 }
 
@@ -981,7 +990,7 @@
 	struct drm_info_list	*files;
 	unsigned		num_files;
 };
-static struct radeon_debugfs _radeon_debugfs[RADEON_DEBUGFS_MAX_NUM_FILES];
+static struct radeon_debugfs _radeon_debugfs[RADEON_DEBUGFS_MAX_COMPONENTS];
 static unsigned _radeon_debugfs_count = 0;
 
 int radeon_debugfs_add_files(struct radeon_device *rdev,
@@ -996,14 +1005,17 @@
 			return 0;
 		}
 	}
-	if ((_radeon_debugfs_count + nfiles) > RADEON_DEBUGFS_MAX_NUM_FILES) {
-		DRM_ERROR("Reached maximum number of debugfs files.\n");
-		DRM_ERROR("Report so we increase RADEON_DEBUGFS_MAX_NUM_FILES.\n");
+
+	i = _radeon_debugfs_count + 1;
+	if (i > RADEON_DEBUGFS_MAX_COMPONENTS) {
+		DRM_ERROR("Reached maximum number of debugfs components.\n");
+		DRM_ERROR("Report so we increase "
+		          "RADEON_DEBUGFS_MAX_COMPONENTS.\n");
 		return -EINVAL;
 	}
 	_radeon_debugfs[_radeon_debugfs_count].files = files;
 	_radeon_debugfs[_radeon_debugfs_count].num_files = nfiles;
-	_radeon_debugfs_count++;
+	_radeon_debugfs_count = i;
 #if defined(CONFIG_DEBUG_FS)
 	drm_debugfs_create_files(files, nfiles,
 				 rdev->ddev->control->debugfs_root,
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_display.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_display.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_display.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_display.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,8 +33,6 @@
 #include "drm_crtc_helper.h"
 #include "drm_edid.h"
 
-static int radeon_ddc_dump(struct drm_connector *connector);
-
 static void avivo_crtc_load_lut(struct drm_crtc *crtc)
 {
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
@@ -669,7 +667,6 @@
 static bool radeon_setup_enc_conn(struct drm_device *dev)
 {
 	struct radeon_device *rdev = dev->dev_private;
-	struct drm_connector *drm_connector;
 	bool ret = false;
 
 	if (rdev->bios) {
@@ -689,8 +686,6 @@
 	if (ret) {
 		radeon_setup_encoder_clones(dev);
 		radeon_print_display_setup(dev);
-		list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
-			radeon_ddc_dump(drm_connector);
 	}
 
 	return ret;
@@ -708,7 +703,8 @@
 
 	if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
 	    (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) ||
-	    radeon_connector_encoder_is_dp_bridge(&radeon_connector->base)) {
+	    (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) !=
+	     ENCODER_OBJECT_ID_NONE)) {
 		struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
 
 		if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
@@ -743,34 +739,6 @@
 	return 0;
 }
 
-static int radeon_ddc_dump(struct drm_connector *connector)
-{
-	struct edid *edid;
-	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-	int ret = 0;
-
-	/* on hw with routers, select right port */
-	if (radeon_connector->router.ddc_valid)
-		radeon_router_select_ddc_port(radeon_connector);
-
-	if (!radeon_connector->ddc_bus)
-		return -1;
-	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
-	/* Log EDID retrieval status here. In particular with regard to
-	 * connectors with requires_extended_probe flag set, that will prevent
-	 * function radeon_dvi_detect() to fetch EDID on this connector,
-	 * as long as there is no valid EDID header found */
-	if (edid) {
-		DRM_INFO("Radeon display connector %s: Found valid EDID",
-				drm_get_connector_name(connector));
-		kfree(edid);
-	} else {
-		DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
-				drm_get_connector_name(connector));
-	}
-	return ret;
-}
-
 /* avivo */
 static void avivo_get_fb_div(struct radeon_pll *pll,
 			     u32 target_clock,
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_drv.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_drv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 
 #include "drm_pciids.h"
 #include <linux/console.h>
+#include <linux/module.h>
 
 
 /*
@@ -52,9 +53,10 @@
  *   2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query
  *   2.10.0 - fusion 2D tiling
  *   2.11.0 - backend map, initial compute support for the CS checker
+ *   2.12.0 - RADEON_CS_KEEP_TILING_FLAGS
  */
 #define KMS_DRIVER_MAJOR	2
-#define KMS_DRIVER_MINOR	11
+#define KMS_DRIVER_MINOR	12
 #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);
@@ -118,6 +120,7 @@
 int radeon_disp_priority = 0;
 int radeon_hw_i2c = 0;
 int radeon_pcie_gen2 = 0;
+int radeon_msi = -1;
 
 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -164,6 +167,9 @@
 MODULE_PARM_DESC(pcie_gen2, "PCIE Gen2 mode (1 = enable)");
 module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444);
 
+MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)");
+module_param_named(msi, radeon_msi, int, 0444);
+
 static int radeon_suspend(struct drm_device *dev, pm_message_t state)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_encoders.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_encoders.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_encoders.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_encoders.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,12 +29,6 @@
 #include "radeon.h"
 #include "atom.h"
 
-extern int atom_debug;
-
-/* evil but including atombios.h is much worse */
-bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
-				struct drm_display_mode *mode);
-
 static uint32_t radeon_encoder_clones(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
@@ -156,27 +150,6 @@
 	return ret;
 }
 
-static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder)
-{
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-	case ENCODER_OBJECT_ID_INTERNAL_DDI:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-		return true;
-	default:
-		return false;
-	}
-}
-
 void
 radeon_link_encoder_connector(struct drm_device *dev)
 {
@@ -229,23 +202,7 @@
 	return NULL;
 }
 
-static struct drm_connector *
-radeon_get_connector_for_encoder_init(struct drm_encoder *encoder)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector;
-
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		radeon_connector = to_radeon_connector(connector);
-		if (radeon_encoder->devices & radeon_connector->devices)
-			return connector;
-	}
-	return NULL;
-}
-
-struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder)
+struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
@@ -266,9 +223,9 @@
 	return NULL;
 }
 
-bool radeon_encoder_is_dp_bridge(struct drm_encoder *encoder)
+u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder)
 {
-	struct drm_encoder *other_encoder = radeon_atom_get_external_encoder(encoder);
+	struct drm_encoder *other_encoder = radeon_get_external_encoder(encoder);
 
 	if (other_encoder) {
 		struct radeon_encoder *radeon_encoder = to_radeon_encoder(other_encoder);
@@ -276,13 +233,12 @@
 		switch (radeon_encoder->encoder_id) {
 		case ENCODER_OBJECT_ID_TRAVIS:
 		case ENCODER_OBJECT_ID_NUTMEG:
-			return true;
+			return radeon_encoder->encoder_id;
 		default:
-			return false;
+			return ENCODER_OBJECT_ID_NONE;
 		}
 	}
-
-	return false;
+	return ENCODER_OBJECT_ID_NONE;
 }
 
 void radeon_panel_mode_fixup(struct drm_encoder *encoder,
@@ -332,2105 +288,3 @@
 
 }
 
-static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
-				   struct drm_display_mode *mode,
-				   struct drm_display_mode *adjusted_mode)
-{
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-
-	/* set the active encoder to connector routing */
-	radeon_encoder_set_active_device(encoder);
-	drm_mode_set_crtcinfo(adjusted_mode, 0);
-
-	/* hw bug */
-	if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
-	    && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
-		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
-
-	/* get the native mode for LVDS */
-	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
-		radeon_panel_mode_fixup(encoder, adjusted_mode);
-
-	/* get the native mode for TV */
-	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
-		struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
-		if (tv_dac) {
-			if (tv_dac->tv_std == TV_STD_NTSC ||
-			    tv_dac->tv_std == TV_STD_NTSC_J ||
-			    tv_dac->tv_std == TV_STD_PAL_M)
-				radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
-			else
-				radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
-		}
-	}
-
-	if (ASIC_IS_DCE3(rdev) &&
-	    ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
-	     radeon_encoder_is_dp_bridge(encoder))) {
-		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-		radeon_dp_set_link_config(connector, mode);
-	}
-
-	return true;
-}
-
-static void
-atombios_dac_setup(struct drm_encoder *encoder, int action)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
-	int index = 0;
-	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
-
-	memset(&args, 0, sizeof(args));
-
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-		index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-		index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
-		break;
-	}
-
-	args.ucAction = action;
-
-	if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
-		args.ucDacStandard = ATOM_DAC1_PS2;
-	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-		args.ucDacStandard = ATOM_DAC1_CV;
-	else {
-		switch (dac_info->tv_std) {
-		case TV_STD_PAL:
-		case TV_STD_PAL_M:
-		case TV_STD_SCART_PAL:
-		case TV_STD_SECAM:
-		case TV_STD_PAL_CN:
-			args.ucDacStandard = ATOM_DAC1_PAL;
-			break;
-		case TV_STD_NTSC:
-		case TV_STD_NTSC_J:
-		case TV_STD_PAL_60:
-		default:
-			args.ucDacStandard = ATOM_DAC1_NTSC;
-			break;
-		}
-	}
-	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-}
-
-static void
-atombios_tv_setup(struct drm_encoder *encoder, int action)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	TV_ENCODER_CONTROL_PS_ALLOCATION args;
-	int index = 0;
-	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
-
-	memset(&args, 0, sizeof(args));
-
-	index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
-
-	args.sTVEncoder.ucAction = action;
-
-	if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
-	else {
-		switch (dac_info->tv_std) {
-		case TV_STD_NTSC:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
-			break;
-		case TV_STD_PAL:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
-			break;
-		case TV_STD_PAL_M:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
-			break;
-		case TV_STD_PAL_60:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
-			break;
-		case TV_STD_NTSC_J:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
-			break;
-		case TV_STD_SCART_PAL:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
-			break;
-		case TV_STD_SECAM:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
-			break;
-		case TV_STD_PAL_CN:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
-			break;
-		default:
-			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
-			break;
-		}
-	}
-
-	args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-}
-
-union dvo_encoder_control {
-	ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds;
-	DVO_ENCODER_CONTROL_PS_ALLOCATION dvo;
-	DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3;
-};
-
-void
-atombios_dvo_setup(struct drm_encoder *encoder, int action)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	union dvo_encoder_control args;
-	int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
-
-	memset(&args, 0, sizeof(args));
-
-	if (ASIC_IS_DCE3(rdev)) {
-		/* DCE3+ */
-		args.dvo_v3.ucAction = action;
-		args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-		args.dvo_v3.ucDVOConfig = 0; /* XXX */
-	} else if (ASIC_IS_DCE2(rdev)) {
-		/* DCE2 (pre-DCE3 R6xx, RS600/690/740 */
-		args.dvo.sDVOEncoder.ucAction = action;
-		args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-		/* DFP1, CRT1, TV1 depending on the type of port */
-		args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
-
-		if (radeon_encoder->pixel_clock > 165000)
-			args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
-	} else {
-		/* R4xx, R5xx */
-		args.ext_tmds.sXTmdsEncoder.ucEnable = action;
-
-		if (radeon_encoder->pixel_clock > 165000)
-			args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-
-		/*if (pScrn->rgbBits == 8)*/
-		args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
-	}
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
-union lvds_encoder_control {
-	LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
-	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
-};
-
-void
-atombios_digital_setup(struct drm_encoder *encoder, int action)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	union lvds_encoder_control args;
-	int index = 0;
-	int hdmi_detected = 0;
-	uint8_t frev, crev;
-
-	if (!dig)
-		return;
-
-	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
-		hdmi_detected = 1;
-
-	memset(&args, 0, sizeof(args));
-
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-		index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-		index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-			index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
-		else
-			index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
-		break;
-	}
-
-	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-		return;
-
-	switch (frev) {
-	case 1:
-	case 2:
-		switch (crev) {
-		case 1:
-			args.v1.ucMisc = 0;
-			args.v1.ucAction = action;
-			if (hdmi_detected)
-				args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
-			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
-					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-				if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
-					args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
-			} else {
-				if (dig->linkb)
-					args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
-				if (radeon_encoder->pixel_clock > 165000)
-					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-				/*if (pScrn->rgbBits == 8) */
-				args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
-			}
-			break;
-		case 2:
-		case 3:
-			args.v2.ucMisc = 0;
-			args.v2.ucAction = action;
-			if (crev == 3) {
-				if (dig->coherent_mode)
-					args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
-			}
-			if (hdmi_detected)
-				args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
-			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-			args.v2.ucTruncate = 0;
-			args.v2.ucSpatial = 0;
-			args.v2.ucTemporal = 0;
-			args.v2.ucFRC = 0;
-			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-				if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL)
-					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-				if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) {
-					args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
-					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
-						args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
-				}
-				if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) {
-					args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
-					if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB)
-						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
-					if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
-						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
-				}
-			} else {
-				if (dig->linkb)
-					args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
-				if (radeon_encoder->pixel_clock > 165000)
-					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-			}
-			break;
-		default:
-			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
-			break;
-		}
-		break;
-	default:
-		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
-		break;
-	}
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
-int
-atombios_get_encoder_mode(struct drm_encoder *encoder)
-{
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector;
-	struct radeon_connector_atom_dig *dig_connector;
-
-	/* dp bridges are always DP */
-	if (radeon_encoder_is_dp_bridge(encoder))
-		return ATOM_ENCODER_MODE_DP;
-
-	/* DVO is always DVO */
-	if (radeon_encoder->encoder_id == ATOM_ENCODER_MODE_DVO)
-		return ATOM_ENCODER_MODE_DVO;
-
-	connector = radeon_get_connector_for_encoder(encoder);
-	/* if we don't have an active device yet, just use one of
-	 * the connectors tied to the encoder.
-	 */
-	if (!connector)
-		connector = radeon_get_connector_for_encoder_init(encoder);
-	radeon_connector = to_radeon_connector(connector);
-
-	switch (connector->connector_type) {
-	case DRM_MODE_CONNECTOR_DVII:
-	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
-		if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
-			/* fix me */
-			if (ASIC_IS_DCE4(rdev))
-				return ATOM_ENCODER_MODE_DVI;
-			else
-				return ATOM_ENCODER_MODE_HDMI;
-		} else if (radeon_connector->use_digital)
-			return ATOM_ENCODER_MODE_DVI;
-		else
-			return ATOM_ENCODER_MODE_CRT;
-		break;
-	case DRM_MODE_CONNECTOR_DVID:
-	case DRM_MODE_CONNECTOR_HDMIA:
-	default:
-		if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
-			/* fix me */
-			if (ASIC_IS_DCE4(rdev))
-				return ATOM_ENCODER_MODE_DVI;
-			else
-				return ATOM_ENCODER_MODE_HDMI;
-		} else
-			return ATOM_ENCODER_MODE_DVI;
-		break;
-	case DRM_MODE_CONNECTOR_LVDS:
-		return ATOM_ENCODER_MODE_LVDS;
-		break;
-	case DRM_MODE_CONNECTOR_DisplayPort:
-		dig_connector = radeon_connector->con_priv;
-		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
-		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
-			return ATOM_ENCODER_MODE_DP;
-		else if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) {
-			/* fix me */
-			if (ASIC_IS_DCE4(rdev))
-				return ATOM_ENCODER_MODE_DVI;
-			else
-				return ATOM_ENCODER_MODE_HDMI;
-		} else
-			return ATOM_ENCODER_MODE_DVI;
-		break;
-	case DRM_MODE_CONNECTOR_eDP:
-		return ATOM_ENCODER_MODE_DP;
-	case DRM_MODE_CONNECTOR_DVIA:
-	case DRM_MODE_CONNECTOR_VGA:
-		return ATOM_ENCODER_MODE_CRT;
-		break;
-	case DRM_MODE_CONNECTOR_Composite:
-	case DRM_MODE_CONNECTOR_SVIDEO:
-	case DRM_MODE_CONNECTOR_9PinDIN:
-		/* fix me */
-		return ATOM_ENCODER_MODE_TV;
-		/*return ATOM_ENCODER_MODE_CV;*/
-		break;
-	}
-}
-
-/*
- * DIG Encoder/Transmitter Setup
- *
- * DCE 3.0/3.1
- * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
- * Supports up to 3 digital outputs
- * - 2 DIG encoder blocks.
- * DIG1 can drive UNIPHY link A or link B
- * DIG2 can drive UNIPHY link B or LVTMA
- *
- * DCE 3.2
- * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
- * Supports up to 5 digital outputs
- * - 2 DIG encoder blocks.
- * DIG1/2 can drive UNIPHY0/1/2 link A or link B
- *
- * DCE 4.0/5.0
- * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
- * Supports up to 6 digital outputs
- * - 6 DIG encoder blocks.
- * - DIG to PHY mapping is hardcoded
- * DIG1 drives UNIPHY0 link A, A+B
- * DIG2 drives UNIPHY0 link B
- * DIG3 drives UNIPHY1 link A, A+B
- * DIG4 drives UNIPHY1 link B
- * DIG5 drives UNIPHY2 link A, A+B
- * DIG6 drives UNIPHY2 link B
- *
- * DCE 4.1
- * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B).
- * Supports up to 6 digital outputs
- * - 2 DIG encoder blocks.
- * DIG1/2 can drive UNIPHY0/1/2 link A or link B
- *
- * Routing
- * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
- * Examples:
- * crtc0 -> dig2 -> LVTMA   links A+B -> TMDS/HDMI
- * crtc1 -> dig1 -> UNIPHY0 link  B   -> DP
- * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
- * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
- */
-
-union dig_encoder_control {
-	DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
-	DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
-	DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
-	DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
-};
-
-void
-atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-	union dig_encoder_control args;
-	int index = 0;
-	uint8_t frev, crev;
-	int dp_clock = 0;
-	int dp_lane_count = 0;
-	int hpd_id = RADEON_HPD_NONE;
-	int bpc = 8;
-
-	if (connector) {
-		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-		struct radeon_connector_atom_dig *dig_connector =
-			radeon_connector->con_priv;
-
-		dp_clock = dig_connector->dp_clock;
-		dp_lane_count = dig_connector->dp_lane_count;
-		hpd_id = radeon_connector->hpd.hpd;
-		bpc = connector->display_info.bpc;
-	}
-
-	/* no dig encoder assigned */
-	if (dig->dig_encoder == -1)
-		return;
-
-	memset(&args, 0, sizeof(args));
-
-	if (ASIC_IS_DCE4(rdev))
-		index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
-	else {
-		if (dig->dig_encoder)
-			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
-		else
-			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
-	}
-
-	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-		return;
-
-	args.v1.ucAction = action;
-	args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-	if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
-		args.v3.ucPanelMode = panel_mode;
-	else
-		args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
-
-	if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) ||
-	    (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST))
-		args.v1.ucLaneNum = dp_lane_count;
-	else if (radeon_encoder->pixel_clock > 165000)
-		args.v1.ucLaneNum = 8;
-	else
-		args.v1.ucLaneNum = 4;
-
-	if (ASIC_IS_DCE5(rdev)) {
-		if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) ||
-		    (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)) {
-			if (dp_clock == 270000)
-				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
-			else if (dp_clock == 540000)
-				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
-		}
-		args.v4.acConfig.ucDigSel = dig->dig_encoder;
-		switch (bpc) {
-		case 0:
-			args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE;
-			break;
-		case 6:
-			args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR;
-			break;
-		case 8:
-		default:
-			args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR;
-			break;
-		case 10:
-			args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR;
-			break;
-		case 12:
-			args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR;
-			break;
-		case 16:
-			args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR;
-			break;
-		}
-		if (hpd_id == RADEON_HPD_NONE)
-			args.v4.ucHPD_ID = 0;
-		else
-			args.v4.ucHPD_ID = hpd_id + 1;
-	} else if (ASIC_IS_DCE4(rdev)) {
-		if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) && (dp_clock == 270000))
-			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
-		args.v3.acConfig.ucDigSel = dig->dig_encoder;
-		switch (bpc) {
-		case 0:
-			args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE;
-			break;
-		case 6:
-			args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR;
-			break;
-		case 8:
-		default:
-			args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
-			break;
-		case 10:
-			args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR;
-			break;
-		case 12:
-			args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR;
-			break;
-		case 16:
-			args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR;
-			break;
-		}
-	} else {
-		if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) && (dp_clock == 270000))
-			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
-		switch (radeon_encoder->encoder_id) {
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
-			break;
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
-			break;
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
-			break;
-		}
-		if (dig->linkb)
-			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
-		else
-			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
-	}
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-}
-
-union dig_transmitter_control {
-	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
-	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
-	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
-	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
-};
-
-void
-atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	struct drm_connector *connector;
-	union dig_transmitter_control args;
-	int index = 0;
-	uint8_t frev, crev;
-	bool is_dp = false;
-	int pll_id = 0;
-	int dp_clock = 0;
-	int dp_lane_count = 0;
-	int connector_object_id = 0;
-	int igp_lane_info = 0;
-	int dig_encoder = dig->dig_encoder;
-
-	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
-		connector = radeon_get_connector_for_encoder_init(encoder);
-		/* just needed to avoid bailing in the encoder check.  the encoder
-		 * isn't used for init
-		 */
-		dig_encoder = 0;
-	} else
-		connector = radeon_get_connector_for_encoder(encoder);
-
-	if (connector) {
-		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-		struct radeon_connector_atom_dig *dig_connector =
-			radeon_connector->con_priv;
-
-		dp_clock = dig_connector->dp_clock;
-		dp_lane_count = dig_connector->dp_lane_count;
-		connector_object_id =
-			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
-		igp_lane_info = dig_connector->igp_lane_info;
-	}
-
-	/* no dig encoder assigned */
-	if (dig_encoder == -1)
-		return;
-
-	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP)
-		is_dp = true;
-
-	memset(&args, 0, sizeof(args));
-
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-		index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-		index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
-		break;
-	}
-
-	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-		return;
-
-	args.v1.ucAction = action;
-	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
-		args.v1.usInitInfo = cpu_to_le16(connector_object_id);
-	} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
-		args.v1.asMode.ucLaneSel = lane_num;
-		args.v1.asMode.ucLaneSet = lane_set;
-	} else {
-		if (is_dp)
-			args.v1.usPixelClock =
-				cpu_to_le16(dp_clock / 10);
-		else if (radeon_encoder->pixel_clock > 165000)
-			args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
-		else
-			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-	}
-	if (ASIC_IS_DCE4(rdev)) {
-		if (is_dp)
-			args.v3.ucLaneNum = dp_lane_count;
-		else if (radeon_encoder->pixel_clock > 165000)
-			args.v3.ucLaneNum = 8;
-		else
-			args.v3.ucLaneNum = 4;
-
-		if (dig->linkb)
-			args.v3.acConfig.ucLinkSel = 1;
-		if (dig_encoder & 1)
-			args.v3.acConfig.ucEncoderSel = 1;
-
-		/* Select the PLL for the PHY
-		 * DP PHY should be clocked from external src if there is
-		 * one.
-		 */
-		if (encoder->crtc) {
-			struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-			pll_id = radeon_crtc->pll_id;
-		}
-
-		if (ASIC_IS_DCE5(rdev)) {
-			/* On DCE5 DCPLL usually generates the DP ref clock */
-			if (is_dp) {
-				if (rdev->clock.dp_extclk)
-					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK;
-				else
-					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL;
-			} else
-				args.v4.acConfig.ucRefClkSource = pll_id;
-		} else {
-			/* On DCE4, if there is an external clock, it generates the DP ref clock */
-			if (is_dp && rdev->clock.dp_extclk)
-				args.v3.acConfig.ucRefClkSource = 2; /* external src */
-			else
-				args.v3.acConfig.ucRefClkSource = pll_id;
-		}
-
-		switch (radeon_encoder->encoder_id) {
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-			args.v3.acConfig.ucTransmitterSel = 0;
-			break;
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-			args.v3.acConfig.ucTransmitterSel = 1;
-			break;
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-			args.v3.acConfig.ucTransmitterSel = 2;
-			break;
-		}
-
-		if (is_dp)
-			args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
-		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
-			if (dig->coherent_mode)
-				args.v3.acConfig.fCoherentMode = 1;
-			if (radeon_encoder->pixel_clock > 165000)
-				args.v3.acConfig.fDualLinkConnector = 1;
-		}
-	} else if (ASIC_IS_DCE32(rdev)) {
-		args.v2.acConfig.ucEncoderSel = dig_encoder;
-		if (dig->linkb)
-			args.v2.acConfig.ucLinkSel = 1;
-
-		switch (radeon_encoder->encoder_id) {
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-			args.v2.acConfig.ucTransmitterSel = 0;
-			break;
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-			args.v2.acConfig.ucTransmitterSel = 1;
-			break;
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-			args.v2.acConfig.ucTransmitterSel = 2;
-			break;
-		}
-
-		if (is_dp) {
-			args.v2.acConfig.fCoherentMode = 1;
-			args.v2.acConfig.fDPConnector = 1;
-		} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
-			if (dig->coherent_mode)
-				args.v2.acConfig.fCoherentMode = 1;
-			if (radeon_encoder->pixel_clock > 165000)
-				args.v2.acConfig.fDualLinkConnector = 1;
-		}
-	} else {
-		args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
-
-		if (dig_encoder)
-			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
-		else
-			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
-
-		if ((rdev->flags & RADEON_IS_IGP) &&
-		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
-			if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
-				if (igp_lane_info & 0x1)
-					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
-				else if (igp_lane_info & 0x2)
-					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
-				else if (igp_lane_info & 0x4)
-					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
-				else if (igp_lane_info & 0x8)
-					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
-			} else {
-				if (igp_lane_info & 0x3)
-					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
-				else if (igp_lane_info & 0xc)
-					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
-			}
-		}
-
-		if (dig->linkb)
-			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
-		else
-			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
-
-		if (is_dp)
-			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
-		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
-			if (dig->coherent_mode)
-				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
-			if (radeon_encoder->pixel_clock > 165000)
-				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
-		}
-	}
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
-bool
-atombios_set_edp_panel_power(struct drm_connector *connector, int action)
-{
-	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-	struct drm_device *dev = radeon_connector->base.dev;
-	struct radeon_device *rdev = dev->dev_private;
-	union dig_transmitter_control args;
-	int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
-	uint8_t frev, crev;
-
-	if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
-		goto done;
-
-	if (!ASIC_IS_DCE4(rdev))
-		goto done;
-
-	if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) &&
-	    (action != ATOM_TRANSMITTER_ACTION_POWER_OFF))
-		goto done;
-
-	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-		goto done;
-
-	memset(&args, 0, sizeof(args));
-
-	args.v1.ucAction = action;
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-	/* wait for the panel to power up */
-	if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) {
-		int i;
-
-		for (i = 0; i < 300; i++) {
-			if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
-				return true;
-			mdelay(1);
-		}
-		return false;
-	}
-done:
-	return true;
-}
-
-union external_encoder_control {
-	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
-	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
-};
-
-static void
-atombios_external_encoder_setup(struct drm_encoder *encoder,
-				struct drm_encoder *ext_encoder,
-				int action)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
-	union external_encoder_control args;
-	struct drm_connector *connector;
-	int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
-	u8 frev, crev;
-	int dp_clock = 0;
-	int dp_lane_count = 0;
-	int connector_object_id = 0;
-	u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
-	int bpc = 8;
-
-	if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
-		connector = radeon_get_connector_for_encoder_init(encoder);
-	else
-		connector = radeon_get_connector_for_encoder(encoder);
-
-	if (connector) {
-		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-		struct radeon_connector_atom_dig *dig_connector =
-			radeon_connector->con_priv;
-
-		dp_clock = dig_connector->dp_clock;
-		dp_lane_count = dig_connector->dp_lane_count;
-		connector_object_id =
-			(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
-		bpc = connector->display_info.bpc;
-	}
-
-	memset(&args, 0, sizeof(args));
-
-	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-		return;
-
-	switch (frev) {
-	case 1:
-		/* no params on frev 1 */
-		break;
-	case 2:
-		switch (crev) {
-		case 1:
-		case 2:
-			args.v1.sDigEncoder.ucAction = action;
-			args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-			args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
-
-			if (args.v1.sDigEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
-				if (dp_clock == 270000)
-					args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
-				args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
-			} else if (radeon_encoder->pixel_clock > 165000)
-				args.v1.sDigEncoder.ucLaneNum = 8;
-			else
-				args.v1.sDigEncoder.ucLaneNum = 4;
-			break;
-		case 3:
-			args.v3.sExtEncoder.ucAction = action;
-			if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT)
-				args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id);
-			else
-				args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
-			args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder);
-
-			if (args.v3.sExtEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
-				if (dp_clock == 270000)
-					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
-				else if (dp_clock == 540000)
-					args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
-				args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
-			} else if (radeon_encoder->pixel_clock > 165000)
-				args.v3.sExtEncoder.ucLaneNum = 8;
-			else
-				args.v3.sExtEncoder.ucLaneNum = 4;
-			switch (ext_enum) {
-			case GRAPH_OBJECT_ENUM_ID1:
-				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
-				break;
-			case GRAPH_OBJECT_ENUM_ID2:
-				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
-				break;
-			case GRAPH_OBJECT_ENUM_ID3:
-				args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
-				break;
-			}
-			switch (bpc) {
-			case 0:
-				args.v3.sExtEncoder.ucBitPerColor = PANEL_BPC_UNDEFINE;
-				break;
-			case 6:
-				args.v3.sExtEncoder.ucBitPerColor = PANEL_6BIT_PER_COLOR;
-				break;
-			case 8:
-			default:
-				args.v3.sExtEncoder.ucBitPerColor = PANEL_8BIT_PER_COLOR;
-				break;
-			case 10:
-				args.v3.sExtEncoder.ucBitPerColor = PANEL_10BIT_PER_COLOR;
-				break;
-			case 12:
-				args.v3.sExtEncoder.ucBitPerColor = PANEL_12BIT_PER_COLOR;
-				break;
-			case 16:
-				args.v3.sExtEncoder.ucBitPerColor = PANEL_16BIT_PER_COLOR;
-				break;
-			}
-			break;
-		default:
-			DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
-			return;
-		}
-		break;
-	default:
-		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
-		return;
-	}
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
-static void
-atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-	ENABLE_YUV_PS_ALLOCATION args;
-	int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
-	uint32_t temp, reg;
-
-	memset(&args, 0, sizeof(args));
-
-	if (rdev->family >= CHIP_R600)
-		reg = R600_BIOS_3_SCRATCH;
-	else
-		reg = RADEON_BIOS_3_SCRATCH;
-
-	/* XXX: fix up scratch reg handling */
-	temp = RREG32(reg);
-	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-		WREG32(reg, (ATOM_S3_TV1_ACTIVE |
-			     (radeon_crtc->crtc_id << 18)));
-	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-		WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
-	else
-		WREG32(reg, 0);
-
-	if (enable)
-		args.ucEnable = ATOM_ENABLE;
-	args.ucCRTC = radeon_crtc->crtc_id;
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-	WREG32(reg, temp);
-}
-
-static void
-radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
-	int index = 0;
-	bool is_dig = false;
-	bool is_dce5_dac = false;
-	bool is_dce5_dvo = false;
-
-	memset(&args, 0, sizeof(args));
-
-	DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
-		  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
-		  radeon_encoder->active_device);
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-		index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-		is_dig = true;
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-	case ENCODER_OBJECT_ID_INTERNAL_DDI:
-		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-		if (ASIC_IS_DCE5(rdev))
-			is_dce5_dvo = true;
-		else if (ASIC_IS_DCE3(rdev))
-			is_dig = true;
-		else
-			index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-		index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
-		else
-			index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-		if (ASIC_IS_DCE5(rdev))
-			is_dce5_dac = true;
-		else {
-			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-				index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
-			else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-				index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
-			else
-				index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
-		}
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
-		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
-		else
-			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
-		break;
-	}
-
-	if (is_dig) {
-		switch (mode) {
-		case DRM_MODE_DPMS_ON:
-			/* some early dce3.2 boards have a bug in their transmitter control table */
-			if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730))
-				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
-			else
-				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
-			if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
-				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-
-				if (connector &&
-				    (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
-					struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-					struct radeon_connector_atom_dig *radeon_dig_connector =
-						radeon_connector->con_priv;
-					atombios_set_edp_panel_power(connector,
-								     ATOM_TRANSMITTER_ACTION_POWER_ON);
-					radeon_dig_connector->edp_on = true;
-				}
-				if (ASIC_IS_DCE4(rdev))
-					atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
-				radeon_dp_link_train(encoder, connector);
-				if (ASIC_IS_DCE4(rdev))
-					atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
-			}
-			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
-			break;
-		case DRM_MODE_DPMS_STANDBY:
-		case DRM_MODE_DPMS_SUSPEND:
-		case DRM_MODE_DPMS_OFF:
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
-			if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
-				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-
-				if (ASIC_IS_DCE4(rdev))
-					atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
-				if (connector &&
-				    (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
-					struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-					struct radeon_connector_atom_dig *radeon_dig_connector =
-						radeon_connector->con_priv;
-					atombios_set_edp_panel_power(connector,
-								     ATOM_TRANSMITTER_ACTION_POWER_OFF);
-					radeon_dig_connector->edp_on = false;
-				}
-			}
-			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
-			break;
-		}
-	} else if (is_dce5_dac) {
-		switch (mode) {
-		case DRM_MODE_DPMS_ON:
-			atombios_dac_setup(encoder, ATOM_ENABLE);
-			break;
-		case DRM_MODE_DPMS_STANDBY:
-		case DRM_MODE_DPMS_SUSPEND:
-		case DRM_MODE_DPMS_OFF:
-			atombios_dac_setup(encoder, ATOM_DISABLE);
-			break;
-		}
-	} else if (is_dce5_dvo) {
-		switch (mode) {
-		case DRM_MODE_DPMS_ON:
-			atombios_dvo_setup(encoder, ATOM_ENABLE);
-			break;
-		case DRM_MODE_DPMS_STANDBY:
-		case DRM_MODE_DPMS_SUSPEND:
-		case DRM_MODE_DPMS_OFF:
-			atombios_dvo_setup(encoder, ATOM_DISABLE);
-			break;
-		}
-	} else {
-		switch (mode) {
-		case DRM_MODE_DPMS_ON:
-			args.ucAction = ATOM_ENABLE;
-			/* workaround for DVOOutputControl on some RS690 systems */
-			if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
-				u32 reg = RREG32(RADEON_BIOS_3_SCRATCH);
-				WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
-				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-				WREG32(RADEON_BIOS_3_SCRATCH, reg);
-			} else
-				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-				args.ucAction = ATOM_LCD_BLON;
-				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-			}
-			break;
-		case DRM_MODE_DPMS_STANDBY:
-		case DRM_MODE_DPMS_SUSPEND:
-		case DRM_MODE_DPMS_OFF:
-			args.ucAction = ATOM_DISABLE;
-			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-				args.ucAction = ATOM_LCD_BLOFF;
-				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-			}
-			break;
-		}
-	}
-
-	if (ext_encoder) {
-		switch (mode) {
-		case DRM_MODE_DPMS_ON:
-		default:
-			if (ASIC_IS_DCE41(rdev)) {
-				atombios_external_encoder_setup(encoder, ext_encoder,
-								EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
-				atombios_external_encoder_setup(encoder, ext_encoder,
-								EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
-			} else
-				atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
-			break;
-		case DRM_MODE_DPMS_STANDBY:
-		case DRM_MODE_DPMS_SUSPEND:
-		case DRM_MODE_DPMS_OFF:
-			if (ASIC_IS_DCE41(rdev)) {
-				atombios_external_encoder_setup(encoder, ext_encoder,
-								EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
-				atombios_external_encoder_setup(encoder, ext_encoder,
-								EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
-			} else
-				atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
-			break;
-		}
-	}
-
-	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
-
-}
-
-union crtc_source_param {
-	SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
-	SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
-};
-
-static void
-atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-	union crtc_source_param args;
-	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
-	uint8_t frev, crev;
-	struct radeon_encoder_atom_dig *dig;
-
-	memset(&args, 0, sizeof(args));
-
-	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-		return;
-
-	switch (frev) {
-	case 1:
-		switch (crev) {
-		case 1:
-		default:
-			if (ASIC_IS_AVIVO(rdev))
-				args.v1.ucCRTC = radeon_crtc->crtc_id;
-			else {
-				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) {
-					args.v1.ucCRTC = radeon_crtc->crtc_id;
-				} else {
-					args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
-				}
-			}
-			switch (radeon_encoder->encoder_id) {
-			case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-				args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-			case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-				if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
-					args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
-				else
-					args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-			case ENCODER_OBJECT_ID_INTERNAL_DDI:
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-				args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
-				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
-				else
-					args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
-				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
-				else
-					args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
-				break;
-			}
-			break;
-		case 2:
-			args.v2.ucCRTC = radeon_crtc->crtc_id;
-			if (radeon_encoder_is_dp_bridge(encoder)) {
-				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-
-				if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
-					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
-				else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA)
-					args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT;
-				else
-					args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
-			} else
-				args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
-			switch (radeon_encoder->encoder_id) {
-			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-				dig = radeon_encoder->enc_priv;
-				switch (dig->dig_encoder) {
-				case 0:
-					args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
-					break;
-				case 1:
-					args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
-					break;
-				case 2:
-					args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
-					break;
-				case 3:
-					args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
-					break;
-				case 4:
-					args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
-					break;
-				case 5:
-					args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
-					break;
-				}
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-				args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
-				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
-				else
-					args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
-				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
-				else
-					args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
-				break;
-			}
-			break;
-		}
-		break;
-	default:
-		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
-		return;
-	}
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-	/* update scratch regs with new routing */
-	radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
-}
-
-static void
-atombios_apply_encoder_quirks(struct drm_encoder *encoder,
-			      struct drm_display_mode *mode)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-
-	/* Funky macbooks */
-	if ((dev->pdev->device == 0x71C5) &&
-	    (dev->pdev->subsystem_vendor == 0x106b) &&
-	    (dev->pdev->subsystem_device == 0x0080)) {
-		if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
-			uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
-
-			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
-			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
-
-			WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
-		}
-	}
-
-	/* set scaler clears this on some chips */
-	if (ASIC_IS_AVIVO(rdev) &&
-	    (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) {
-		if (ASIC_IS_DCE4(rdev)) {
-			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
-				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,
-				       EVERGREEN_INTERLEAVE_EN);
-			else
-				WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
-		} else {
-			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
-				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
-				       AVIVO_D1MODE_INTERLEAVE_EN);
-			else
-				WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
-		}
-	}
-}
-
-static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct drm_encoder *test_encoder;
-	struct radeon_encoder_atom_dig *dig;
-	uint32_t dig_enc_in_use = 0;
-
-	/* DCE4/5 */
-	if (ASIC_IS_DCE4(rdev)) {
-		dig = radeon_encoder->enc_priv;
-		if (ASIC_IS_DCE41(rdev)) {
-			/* ontario follows DCE4 */
-			if (rdev->family == CHIP_PALM) {
-				if (dig->linkb)
-					return 1;
-				else
-					return 0;
-			} else
-				/* llano follows DCE3.2 */
-				return radeon_crtc->crtc_id;
-		} else {
-			switch (radeon_encoder->encoder_id) {
-			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-				if (dig->linkb)
-					return 1;
-				else
-					return 0;
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-				if (dig->linkb)
-					return 3;
-				else
-					return 2;
-				break;
-			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-				if (dig->linkb)
-					return 5;
-				else
-					return 4;
-				break;
-			}
-		}
-	}
-
-	/* on DCE32 and encoder can driver any block so just crtc id */
-	if (ASIC_IS_DCE32(rdev)) {
-		return radeon_crtc->crtc_id;
-	}
-
-	/* on DCE3 - LVTMA can only be driven by DIGB */
-	list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
-		struct radeon_encoder *radeon_test_encoder;
-
-		if (encoder == test_encoder)
-			continue;
-
-		if (!radeon_encoder_is_digital(test_encoder))
-			continue;
-
-		radeon_test_encoder = to_radeon_encoder(test_encoder);
-		dig = radeon_test_encoder->enc_priv;
-
-		if (dig->dig_encoder >= 0)
-			dig_enc_in_use |= (1 << dig->dig_encoder);
-	}
-
-	if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) {
-		if (dig_enc_in_use & 0x2)
-			DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n");
-		return 1;
-	}
-	if (!(dig_enc_in_use & 1))
-		return 0;
-	return 1;
-}
-
-/* This only needs to be called once at startup */
-void
-radeon_atom_encoder_init(struct radeon_device *rdev)
-{
-	struct drm_device *dev = rdev->ddev;
-	struct drm_encoder *encoder;
-
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-		struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-
-		switch (radeon_encoder->encoder_id) {
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
-			break;
-		default:
-			break;
-		}
-
-		if (ext_encoder && ASIC_IS_DCE41(rdev))
-			atombios_external_encoder_setup(encoder, ext_encoder,
-							EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
-	}
-}
-
-static void
-radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
-			     struct drm_display_mode *mode,
-			     struct drm_display_mode *adjusted_mode)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-
-	radeon_encoder->pixel_clock = adjusted_mode->clock;
-
-	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
-		if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
-			atombios_yuv_setup(encoder, true);
-		else
-			atombios_yuv_setup(encoder, false);
-	}
-
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-		if (ASIC_IS_DCE4(rdev)) {
-			/* disable the transmitter */
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-			/* setup and enable the encoder */
-			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
-
-			/* enable the transmitter */
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
-		} else {
-			/* disable the encoder and transmitter */
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
-
-			/* setup and enable the encoder and transmitter */
-			atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
-		}
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DDI:
-	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-		atombios_dvo_setup(encoder, ATOM_ENABLE);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-		atombios_dac_setup(encoder, ATOM_ENABLE);
-		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
-			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
-				atombios_tv_setup(encoder, ATOM_ENABLE);
-			else
-				atombios_tv_setup(encoder, ATOM_DISABLE);
-		}
-		break;
-	}
-
-	if (ext_encoder) {
-		if (ASIC_IS_DCE41(rdev))
-			atombios_external_encoder_setup(encoder, ext_encoder,
-							EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
-		else
-			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
-	}
-
-	atombios_apply_encoder_quirks(encoder, adjusted_mode);
-
-	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
-		r600_hdmi_enable(encoder);
-		r600_hdmi_setmode(encoder, adjusted_mode);
-	}
-}
-
-static bool
-atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-
-	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
-				       ATOM_DEVICE_CV_SUPPORT |
-				       ATOM_DEVICE_CRT_SUPPORT)) {
-		DAC_LOAD_DETECTION_PS_ALLOCATION args;
-		int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
-		uint8_t frev, crev;
-
-		memset(&args, 0, sizeof(args));
-
-		if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
-			return false;
-
-		args.sDacload.ucMisc = 0;
-
-		if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
-		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
-			args.sDacload.ucDacType = ATOM_DAC_A;
-		else
-			args.sDacload.ucDacType = ATOM_DAC_B;
-
-		if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
-			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
-		else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
-			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
-		else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
-			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
-			if (crev >= 3)
-				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
-		} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
-			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
-			if (crev >= 3)
-				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
-		}
-
-		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-		return true;
-	} else
-		return false;
-}
-
-static enum drm_connector_status
-radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-	uint32_t bios_0_scratch;
-
-	if (!atombios_dac_load_detect(encoder, connector)) {
-		DRM_DEBUG_KMS("detect returned false \n");
-		return connector_status_unknown;
-	}
-
-	if (rdev->family >= CHIP_R600)
-		bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
-	else
-		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
-
-	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
-	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
-		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
-			return connector_status_connected;
-	}
-	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
-		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
-			return connector_status_connected;
-	}
-	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
-		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
-			return connector_status_connected;
-	}
-	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
-		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
-			return connector_status_connected; /* CTV */
-		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
-			return connector_status_connected; /* STV */
-	}
-	return connector_status_disconnected;
-}
-
-static enum drm_connector_status
-radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-	struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-	u32 bios_0_scratch;
-
-	if (!ASIC_IS_DCE4(rdev))
-		return connector_status_unknown;
-
-	if (!ext_encoder)
-		return connector_status_unknown;
-
-	if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0)
-		return connector_status_unknown;
-
-	/* load detect on the dp bridge */
-	atombios_external_encoder_setup(encoder, ext_encoder,
-					EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
-
-	bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
-
-	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
-	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
-		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
-			return connector_status_connected;
-	}
-	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
-		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
-			return connector_status_connected;
-	}
-	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
-		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
-			return connector_status_connected;
-	}
-	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
-		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
-			return connector_status_connected; /* CTV */
-		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
-			return connector_status_connected; /* STV */
-	}
-	return connector_status_disconnected;
-}
-
-void
-radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder)
-{
-	struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
-
-	if (ext_encoder)
-		/* ddc_setup on the dp bridge */
-		atombios_external_encoder_setup(encoder, ext_encoder,
-						EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
-
-}
-
-static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
-{
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-
-	if ((radeon_encoder->active_device &
-	     (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
-	    radeon_encoder_is_dp_bridge(encoder)) {
-		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-		if (dig)
-			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
-	}
-
-	radeon_atom_output_lock(encoder, true);
-	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
-
-	if (connector) {
-		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-
-		/* select the clock/data port if it uses a router */
-		if (radeon_connector->router.cd_valid)
-			radeon_router_select_cd_port(radeon_connector);
-
-		/* turn eDP panel on for mode set */
-		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
-			atombios_set_edp_panel_power(connector,
-						     ATOM_TRANSMITTER_ACTION_POWER_ON);
-	}
-
-	/* this is needed for the pll/ss setup to work correctly in some cases */
-	atombios_set_encoder_crtc_source(encoder);
-}
-
-static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
-{
-	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
-	radeon_atom_output_lock(encoder, false);
-}
-
-static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
-{
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig;
-
-	/* check for pre-DCE3 cards with shared encoders;
-	 * can't really use the links individually, so don't disable
-	 * the encoder if it's in use by another connector
-	 */
-	if (!ASIC_IS_DCE3(rdev)) {
-		struct drm_encoder *other_encoder;
-		struct radeon_encoder *other_radeon_encoder;
-
-		list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
-			other_radeon_encoder = to_radeon_encoder(other_encoder);
-			if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) &&
-			    drm_helper_encoder_in_use(other_encoder))
-				goto disable_done;
-		}
-	}
-
-	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
-
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-		if (ASIC_IS_DCE4(rdev))
-			/* disable the transmitter */
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-		else {
-			/* disable the encoder and transmitter */
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
-		}
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DDI:
-	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-		atombios_dvo_setup(encoder, ATOM_DISABLE);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-		atombios_dac_setup(encoder, ATOM_DISABLE);
-		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
-			atombios_tv_setup(encoder, ATOM_DISABLE);
-		break;
-	}
-
-disable_done:
-	if (radeon_encoder_is_digital(encoder)) {
-		if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
-			r600_hdmi_disable(encoder);
-		dig = radeon_encoder->enc_priv;
-		dig->dig_encoder = -1;
-	}
-	radeon_encoder->active_device = 0;
-}
-
-/* these are handled by the primary encoders */
-static void radeon_atom_ext_prepare(struct drm_encoder *encoder)
-{
-
-}
-
-static void radeon_atom_ext_commit(struct drm_encoder *encoder)
-{
-
-}
-
-static void
-radeon_atom_ext_mode_set(struct drm_encoder *encoder,
-			 struct drm_display_mode *mode,
-			 struct drm_display_mode *adjusted_mode)
-{
-
-}
-
-static void radeon_atom_ext_disable(struct drm_encoder *encoder)
-{
-
-}
-
-static void
-radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode)
-{
-
-}
-
-static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder,
-				       struct drm_display_mode *mode,
-				       struct drm_display_mode *adjusted_mode)
-{
-	return true;
-}
-
-static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = {
-	.dpms = radeon_atom_ext_dpms,
-	.mode_fixup = radeon_atom_ext_mode_fixup,
-	.prepare = radeon_atom_ext_prepare,
-	.mode_set = radeon_atom_ext_mode_set,
-	.commit = radeon_atom_ext_commit,
-	.disable = radeon_atom_ext_disable,
-	/* no detect for TMDS/LVDS yet */
-};
-
-static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
-	.dpms = radeon_atom_encoder_dpms,
-	.mode_fixup = radeon_atom_mode_fixup,
-	.prepare = radeon_atom_encoder_prepare,
-	.mode_set = radeon_atom_encoder_mode_set,
-	.commit = radeon_atom_encoder_commit,
-	.disable = radeon_atom_encoder_disable,
-	.detect = radeon_atom_dig_detect,
-};
-
-static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
-	.dpms = radeon_atom_encoder_dpms,
-	.mode_fixup = radeon_atom_mode_fixup,
-	.prepare = radeon_atom_encoder_prepare,
-	.mode_set = radeon_atom_encoder_mode_set,
-	.commit = radeon_atom_encoder_commit,
-	.detect = radeon_atom_dac_detect,
-};
-
-void radeon_enc_destroy(struct drm_encoder *encoder)
-{
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	kfree(radeon_encoder->enc_priv);
-	drm_encoder_cleanup(encoder);
-	kfree(radeon_encoder);
-}
-
-static const struct drm_encoder_funcs radeon_atom_enc_funcs = {
-	.destroy = radeon_enc_destroy,
-};
-
-struct radeon_encoder_atom_dac *
-radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
-{
-	struct drm_device *dev = radeon_encoder->base.dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
-
-	if (!dac)
-		return NULL;
-
-	dac->tv_std = radeon_atombios_get_tv_info(rdev);
-	return dac;
-}
-
-struct radeon_encoder_atom_dig *
-radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
-{
-	int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
-	struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
-
-	if (!dig)
-		return NULL;
-
-	/* coherent mode by default */
-	dig->coherent_mode = true;
-	dig->dig_encoder = -1;
-
-	if (encoder_enum == 2)
-		dig->linkb = true;
-	else
-		dig->linkb = false;
-
-	return dig;
-}
-
-void
-radeon_add_atom_encoder(struct drm_device *dev,
-			uint32_t encoder_enum,
-			uint32_t supported_device,
-			u16 caps)
-{
-	struct radeon_device *rdev = dev->dev_private;
-	struct drm_encoder *encoder;
-	struct radeon_encoder *radeon_encoder;
-
-	/* see if we already added it */
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		radeon_encoder = to_radeon_encoder(encoder);
-		if (radeon_encoder->encoder_enum == encoder_enum) {
-			radeon_encoder->devices |= supported_device;
-			return;
-		}
-
-	}
-
-	/* add a new one */
-	radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
-	if (!radeon_encoder)
-		return;
-
-	encoder = &radeon_encoder->base;
-	switch (rdev->num_crtc) {
-	case 1:
-		encoder->possible_crtcs = 0x1;
-		break;
-	case 2:
-	default:
-		encoder->possible_crtcs = 0x3;
-		break;
-	case 4:
-		encoder->possible_crtcs = 0xf;
-		break;
-	case 6:
-		encoder->possible_crtcs = 0x3f;
-		break;
-	}
-
-	radeon_encoder->enc_priv = NULL;
-
-	radeon_encoder->encoder_enum = encoder_enum;
-	radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
-	radeon_encoder->devices = supported_device;
-	radeon_encoder->rmx_type = RMX_OFF;
-	radeon_encoder->underscan_type = UNDERSCAN_OFF;
-	radeon_encoder->is_ext_encoder = false;
-	radeon_encoder->caps = caps;
-
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
-	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
-		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-			radeon_encoder->rmx_type = RMX_FULL;
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
-			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
-		} else {
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
-			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
-		}
-		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
-		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
-		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
-		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
-		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
-		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
-		break;
-	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-	case ENCODER_OBJECT_ID_INTERNAL_DDI:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-			radeon_encoder->rmx_type = RMX_FULL;
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
-			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
-		} else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
-			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
-		} else {
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
-			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
-		}
-		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
-		break;
-	case ENCODER_OBJECT_ID_SI170B:
-	case ENCODER_OBJECT_ID_CH7303:
-	case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
-	case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
-	case ENCODER_OBJECT_ID_TITFP513:
-	case ENCODER_OBJECT_ID_VT1623:
-	case ENCODER_OBJECT_ID_HDMI_SI1930:
-	case ENCODER_OBJECT_ID_TRAVIS:
-	case ENCODER_OBJECT_ID_NUTMEG:
-		/* these are handled by the primary encoders */
-		radeon_encoder->is_ext_encoder = true;
-		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
-		else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
-		else
-			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
-		drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs);
-		break;
-	}
-}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_fence.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_fence.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_fence.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_fence.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,7 +48,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;
-		rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq);;
+		rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq);
 	} else
 		WREG32(rdev->fence_drv.scratch_reg, seq);
 }
@@ -263,7 +263,7 @@
 		 */
 		if (seq == rdev->fence_drv.last_seq && radeon_gpu_is_lockup(rdev)) {
 			/* good news we believe it's a lockup */
-			WARN(1, "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n",
+			printk(KERN_WARNING "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n",
 			     fence->seq, seq);
 			/* FIXME: what should we do ? marking everyone
 			 * as signaled for now
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_gart.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_gart.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_gart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_gart.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,27 +49,27 @@
 			      rdev->gart.table_size >> PAGE_SHIFT);
 	}
 #endif
-	rdev->gart.table.ram.ptr = ptr;
-	memset((void *)rdev->gart.table.ram.ptr, 0, rdev->gart.table_size);
+	rdev->gart.ptr = ptr;
+	memset((void *)rdev->gart.ptr, 0, rdev->gart.table_size);
 	return 0;
 }
 
 void radeon_gart_table_ram_free(struct radeon_device *rdev)
 {
-	if (rdev->gart.table.ram.ptr == NULL) {
+	if (rdev->gart.ptr == NULL) {
 		return;
 	}
 #ifdef CONFIG_X86
 	if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 ||
 	    rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
-		set_memory_wb((unsigned long)rdev->gart.table.ram.ptr,
+		set_memory_wb((unsigned long)rdev->gart.ptr,
 			      rdev->gart.table_size >> PAGE_SHIFT);
 	}
 #endif
 	pci_free_consistent(rdev->pdev, rdev->gart.table_size,
-			    (void *)rdev->gart.table.ram.ptr,
+			    (void *)rdev->gart.ptr,
 			    rdev->gart.table_addr);
-	rdev->gart.table.ram.ptr = NULL;
+	rdev->gart.ptr = NULL;
 	rdev->gart.table_addr = 0;
 }
 
@@ -77,10 +77,10 @@
 {
 	int r;
 
-	if (rdev->gart.table.vram.robj == NULL) {
+	if (rdev->gart.robj == NULL) {
 		r = radeon_bo_create(rdev, rdev->gart.table_size,
 				     PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
-				     &rdev->gart.table.vram.robj);
+				     &rdev->gart.robj);
 		if (r) {
 			return r;
 		}
@@ -93,38 +93,46 @@
 	uint64_t gpu_addr;
 	int r;
 
-	r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
+	r = radeon_bo_reserve(rdev->gart.robj, false);
 	if (unlikely(r != 0))
 		return r;
-	r = radeon_bo_pin(rdev->gart.table.vram.robj,
+	r = radeon_bo_pin(rdev->gart.robj,
 				RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
 	if (r) {
-		radeon_bo_unreserve(rdev->gart.table.vram.robj);
+		radeon_bo_unreserve(rdev->gart.robj);
 		return r;
 	}
-	r = radeon_bo_kmap(rdev->gart.table.vram.robj,
-				(void **)&rdev->gart.table.vram.ptr);
+	r = radeon_bo_kmap(rdev->gart.robj, &rdev->gart.ptr);
 	if (r)
-		radeon_bo_unpin(rdev->gart.table.vram.robj);
-	radeon_bo_unreserve(rdev->gart.table.vram.robj);
+		radeon_bo_unpin(rdev->gart.robj);
+	radeon_bo_unreserve(rdev->gart.robj);
 	rdev->gart.table_addr = gpu_addr;
 	return r;
 }
 
-void radeon_gart_table_vram_free(struct radeon_device *rdev)
+void radeon_gart_table_vram_unpin(struct radeon_device *rdev)
 {
 	int r;
 
-	if (rdev->gart.table.vram.robj == NULL) {
+	if (rdev->gart.robj == NULL) {
 		return;
 	}
-	r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
+	r = radeon_bo_reserve(rdev->gart.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);
+		radeon_bo_kunmap(rdev->gart.robj);
+		radeon_bo_unpin(rdev->gart.robj);
+		radeon_bo_unreserve(rdev->gart.robj);
+		rdev->gart.ptr = NULL;
 	}
-	radeon_bo_unref(&rdev->gart.table.vram.robj);
+}
+
+void radeon_gart_table_vram_free(struct radeon_device *rdev)
+{
+	if (rdev->gart.robj == NULL) {
+		return;
+	}
+	radeon_gart_table_vram_unpin(rdev);
+	radeon_bo_unref(&rdev->gart.robj);
 }
 
 
@@ -142,7 +150,7 @@
 	u64 page_base;
 
 	if (!rdev->gart.ready) {
-		WARN(1, "trying to unbind memory to unitialized GART !\n");
+		WARN(1, "trying to unbind memory from uninitialized GART !\n");
 		return;
 	}
 	t = offset / RADEON_GPU_PAGE_SIZE;
@@ -151,12 +159,14 @@
 		if (rdev->gart.pages[p]) {
 			if (!rdev->gart.ttm_alloced[p])
 				pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p],
-				       		PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+						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];
 			for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
-				radeon_gart_set_page(rdev, t, page_base);
+				if (rdev->gart.ptr) {
+					radeon_gart_set_page(rdev, t, page_base);
+				}
 				page_base += RADEON_GPU_PAGE_SIZE;
 			}
 		}
@@ -174,7 +184,7 @@
 	int i, j;
 
 	if (!rdev->gart.ready) {
-		WARN(1, "trying to bind memory to unitialized GART !\n");
+		WARN(1, "trying to bind memory to uninitialized GART !\n");
 		return -EINVAL;
 	}
 	t = offset / RADEON_GPU_PAGE_SIZE;
@@ -199,10 +209,12 @@
 			}
 		}
 		rdev->gart.pages[p] = pagelist[i];
-		page_base = rdev->gart.pages_addr[p];
-		for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
-			radeon_gart_set_page(rdev, t, page_base);
-			page_base += RADEON_GPU_PAGE_SIZE;
+		if (rdev->gart.ptr) {
+			page_base = rdev->gart.pages_addr[p];
+			for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
+				radeon_gart_set_page(rdev, t, page_base);
+				page_base += RADEON_GPU_PAGE_SIZE;
+			}
 		}
 	}
 	mb();
@@ -215,6 +227,9 @@
 	int i, j, t;
 	u64 page_base;
 
+	if (!rdev->gart.ptr) {
+		return;
+	}
 	for (i = 0, t = 0; i < rdev->gart.num_cpu_pages; i++) {
 		page_base = rdev->gart.pages_addr[i];
 		for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon.h linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon.h	2012-01-04 18:55:44.000000000 -0500
@@ -93,6 +93,7 @@
 extern int radeon_disp_priority;
 extern int radeon_hw_i2c;
 extern int radeon_pcie_gen2;
+extern int radeon_msi;
 
 /*
  * Copy from radeon_drv.h so we don't have to include both and have conflicting
@@ -102,7 +103,7 @@
 #define RADEON_FENCE_JIFFIES_TIMEOUT	(HZ / 2)
 /* RADEON_IB_POOL_SIZE must be a power of 2 */
 #define RADEON_IB_POOL_SIZE		16
-#define RADEON_DEBUGFS_MAX_NUM_FILES	32
+#define RADEON_DEBUGFS_MAX_COMPONENTS	32
 #define RADEONFB_CONN_LIMIT		4
 #define RADEON_BIOS_NUM_SCRATCH		8
 
@@ -306,30 +307,17 @@
  */
 struct radeon_mc;
 
-struct radeon_gart_table_ram {
-	volatile uint32_t		*ptr;
-};
-
-struct radeon_gart_table_vram {
-	struct radeon_bo		*robj;
-	volatile uint32_t		*ptr;
-};
-
-union radeon_gart_table {
-	struct radeon_gart_table_ram	ram;
-	struct radeon_gart_table_vram	vram;
-};
-
 #define RADEON_GPU_PAGE_SIZE 4096
 #define RADEON_GPU_PAGE_MASK (RADEON_GPU_PAGE_SIZE - 1)
 #define RADEON_GPU_PAGE_SHIFT 12
 
 struct radeon_gart {
 	dma_addr_t			table_addr;
+	struct radeon_bo		*robj;
+	void				*ptr;
 	unsigned			num_gpu_pages;
 	unsigned			num_cpu_pages;
 	unsigned			table_size;
-	union radeon_gart_table		table;
 	struct page			**pages;
 	dma_addr_t			*pages_addr;
 	bool				*ttm_alloced;
@@ -340,6 +328,8 @@
 void radeon_gart_table_ram_free(struct radeon_device *rdev);
 int radeon_gart_table_vram_alloc(struct radeon_device *rdev);
 void radeon_gart_table_vram_free(struct radeon_device *rdev);
+int radeon_gart_table_vram_pin(struct radeon_device *rdev);
+void radeon_gart_table_vram_unpin(struct radeon_device *rdev);
 int radeon_gart_init(struct radeon_device *rdev);
 void radeon_gart_fini(struct radeon_device *rdev);
 void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
@@ -347,6 +337,7 @@
 int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
 		     int pages, struct page **pagelist,
 		     dma_addr_t *dma_addr);
+void radeon_gart_restore(struct radeon_device *rdev);
 
 
 /*
@@ -437,25 +428,26 @@
 	struct evergreen_irq_stat_regs evergreen;
 };
 
+#define RADEON_MAX_HPD_PINS 6
+#define RADEON_MAX_CRTCS 6
+#define RADEON_MAX_HDMI_BLOCKS 2
+
 struct radeon_irq {
 	bool		installed;
 	bool		sw_int;
-	/* FIXME: use a define max crtc rather than hardcode it */
-	bool		crtc_vblank_int[6];
-	bool		pflip[6];
+	bool		crtc_vblank_int[RADEON_MAX_CRTCS];
+	bool		pflip[RADEON_MAX_CRTCS];
 	wait_queue_head_t	vblank_queue;
-	/* FIXME: use defines for max hpd/dacs */
-	bool            hpd[6];
+	bool            hpd[RADEON_MAX_HPD_PINS];
 	bool            gui_idle;
 	bool            gui_idle_acked;
 	wait_queue_head_t	idle_queue;
-	/* FIXME: use defines for max HDMI blocks */
-	bool		hdmi[2];
+	bool		hdmi[RADEON_MAX_HDMI_BLOCKS];
 	spinlock_t sw_lock;
 	int sw_refcount;
 	union radeon_irq_stat_regs stat_regs;
-	spinlock_t pflip_lock[6];
-	int pflip_refcount[6];
+	spinlock_t pflip_lock[RADEON_MAX_CRTCS];
+	int pflip_refcount[RADEON_MAX_CRTCS];
 };
 
 int radeon_irq_kms_init(struct radeon_device *rdev);
@@ -523,9 +515,30 @@
 	bool                    enabled;
 };
 
+struct r600_blit_cp_primitives {
+	void (*set_render_target)(struct radeon_device *rdev, int format,
+				  int w, int h, u64 gpu_addr);
+	void (*cp_set_surface_sync)(struct radeon_device *rdev,
+				    u32 sync_type, u32 size,
+				    u64 mc_addr);
+	void (*set_shaders)(struct radeon_device *rdev);
+	void (*set_vtx_resource)(struct radeon_device *rdev, u64 gpu_addr);
+	void (*set_tex_resource)(struct radeon_device *rdev,
+				 int format, int w, int h, int pitch,
+				 u64 gpu_addr, u32 size);
+	void (*set_scissors)(struct radeon_device *rdev, int x1, int y1,
+			     int x2, int y2);
+	void (*draw_auto)(struct radeon_device *rdev);
+	void (*set_default_state)(struct radeon_device *rdev);
+};
+
 struct r600_blit {
 	struct mutex		mutex;
 	struct radeon_bo	*shader_obj;
+	struct r600_blit_cp_primitives primitives;
+	int max_dim;
+	int ring_size_common;
+	int ring_size_per_loop;
 	u64 shader_gpu_addr;
 	u32 vs_offset, ps_offset;
 	u32 state_offset;
@@ -534,6 +547,8 @@
 	struct radeon_ib *vb_ib;
 };
 
+void r600_blit_suspend(struct radeon_device *rdev);
+
 int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib);
 void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib);
 int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib);
@@ -596,37 +611,13 @@
 	struct radeon_ib	*ib;
 	void			*track;
 	unsigned		family;
-	int parser_error;
+	int			parser_error;
+	bool			keep_tiling_flags;
 };
 
 extern int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx);
 extern int radeon_cs_finish_pages(struct radeon_cs_parser *p);
-
-
-static inline u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx)
-{
-	struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx];
-	u32 pg_idx, pg_offset;
-	u32 idx_value = 0;
-	int new_page;
-
-	pg_idx = (idx * 4) / PAGE_SIZE;
-	pg_offset = (idx * 4) % PAGE_SIZE;
-
-	if (ibc->kpage_idx[0] == pg_idx)
-		return ibc->kpage[0][pg_offset/4];
-	if (ibc->kpage_idx[1] == pg_idx)
-		return ibc->kpage[1][pg_offset/4];
-
-	new_page = radeon_cs_update_pages(p, pg_idx);
-	if (new_page < 0) {
-		p->parser_error = new_page;
-		return 0;
-	}
-
-	idx_value = ibc->kpage[new_page][pg_offset/4];
-	return idx_value;
-}
+extern u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx);
 
 struct radeon_cs_packet {
 	unsigned	idx;
@@ -794,8 +785,7 @@
 
 struct radeon_power_state {
 	enum radeon_pm_state_type type;
-	/* XXX: use a define for num clock modes */
-	struct radeon_pm_clock_info clock_info[8];
+	struct radeon_pm_clock_info *clock_info;
 	/* number of valid clock modes in this power state */
 	int num_clock_modes;
 	struct radeon_pm_clock_info *default_clock_mode;
@@ -865,11 +855,14 @@
 	struct device	        *int_hwmon_dev;
 };
 
+int radeon_pm_get_type_index(struct radeon_device *rdev,
+			     enum radeon_pm_state_type ps_type,
+			     int instance);
 
 /*
  * Benchmarking
  */
-void radeon_benchmark(struct radeon_device *rdev);
+void radeon_benchmark(struct radeon_device *rdev, int test_number);
 
 
 /*
@@ -1145,12 +1138,55 @@
 int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *filp);
 
-/* VRAM scratch page for HDP bug */
-struct r700_vram_scratch {
+/* VRAM scratch page for HDP bug, default vram page */
+struct r600_vram_scratch {
 	struct radeon_bo		*robj;
 	volatile uint32_t		*ptr;
+	u64				gpu_addr;
 };
 
+
+/*
+ * Mutex which allows recursive locking from the same process.
+ */
+struct radeon_mutex {
+	struct mutex		mutex;
+	struct task_struct	*owner;
+	int			level;
+};
+
+static inline void radeon_mutex_init(struct radeon_mutex *mutex)
+{
+	mutex_init(&mutex->mutex);
+	mutex->owner = NULL;
+	mutex->level = 0;
+}
+
+static inline void radeon_mutex_lock(struct radeon_mutex *mutex)
+{
+	if (mutex_trylock(&mutex->mutex)) {
+		/* The mutex was unlocked before, so it's ours now */
+		mutex->owner = current;
+	} else if (mutex->owner != current) {
+		/* Another process locked the mutex, take it */
+		mutex_lock(&mutex->mutex);
+		mutex->owner = current;
+	}
+	/* Otherwise the mutex was already locked by this process */
+
+	mutex->level++;
+}
+
+static inline void radeon_mutex_unlock(struct radeon_mutex *mutex)
+{
+	if (--mutex->level > 0)
+		return;
+
+	mutex->owner = NULL;
+	mutex_unlock(&mutex->mutex);
+}
+
+
 /*
  * Core structure, functions and helpers.
  */
@@ -1206,7 +1242,7 @@
 	struct radeon_gem		gem;
 	struct radeon_pm		pm;
 	uint32_t			bios_scratch[RADEON_BIOS_NUM_SCRATCH];
-	struct mutex			cs_mutex;
+	struct radeon_mutex		cs_mutex;
 	struct radeon_wb		wb;
 	struct radeon_dummy_page	dummy_page;
 	bool				gpu_lockup;
@@ -1220,7 +1256,7 @@
 	const struct firmware *rlc_fw;	/* r6/700 RLC firmware */
 	const struct firmware *mc_fw;	/* NI MC firmware */
 	struct r600_blit r600_blit;
-	struct r700_vram_scratch vram_scratch;
+	struct r600_vram_scratch vram_scratch;
 	int msi_enabled; /* msi enabled */
 	struct r600_ih ih; /* r6/700 interrupt ring */
 	struct work_struct hotplug_work;
@@ -1252,45 +1288,10 @@
 void radeon_device_fini(struct radeon_device *rdev);
 int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
 
-static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
-{
-	if (reg < rdev->rmmio_size)
-		return readl((rdev->rmmio) + reg);
-	else {
-		writel(reg, (rdev->rmmio) + RADEON_MM_INDEX);
-		return readl((rdev->rmmio) + RADEON_MM_DATA);
-	}
-}
-
-static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
-{
-	if (reg < rdev->rmmio_size)
-		writel(v, (rdev->rmmio) + reg);
-	else {
-		writel(reg, (rdev->rmmio) + RADEON_MM_INDEX);
-		writel(v, (rdev->rmmio) + RADEON_MM_DATA);
-	}
-}
-
-static inline u32 r100_io_rreg(struct radeon_device *rdev, u32 reg)
-{
-	if (reg < rdev->rio_mem_size)
-		return ioread32(rdev->rio_mem + reg);
-	else {
-		iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
-		return ioread32(rdev->rio_mem + RADEON_MM_DATA);
-	}
-}
-
-static inline void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v)
-{
-	if (reg < rdev->rio_mem_size)
-		iowrite32(v, rdev->rio_mem + reg);
-	else {
-		iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
-		iowrite32(v, rdev->rio_mem + RADEON_MM_DATA);
-	}
-}
+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);
+u32 r100_io_rreg(struct radeon_device *rdev, u32 reg);
+void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);
 
 /*
  * Cast helper
@@ -1413,19 +1414,19 @@
 /*
  * RING helpers.
  */
+
+#if DRM_DEBUG_CODE == 0
 static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
 {
-#if DRM_DEBUG_CODE
-	if (rdev->cp.count_dw <= 0) {
-		DRM_ERROR("radeon: writting more dword to ring than expected !\n");
-	}
-#endif
 	rdev->cp.ring[rdev->cp.wptr++] = v;
 	rdev->cp.wptr &= rdev->cp.ptr_mask;
 	rdev->cp.count_dw--;
 	rdev->cp.ring_free_dw--;
 }
-
+#else
+/* With debugging this is just too big to inline */
+void radeon_ring_write(struct radeon_device *rdev, uint32_t v);
+#endif
 
 /*
  * ASICs macro.
@@ -1479,8 +1480,6 @@
 /* AGP */
 extern int radeon_gpu_reset(struct radeon_device *rdev);
 extern void radeon_agp_disable(struct radeon_device *rdev);
-extern int radeon_gart_table_vram_pin(struct radeon_device *rdev);
-extern void radeon_gart_restore(struct radeon_device *rdev);
 extern int radeon_modeset_init(struct radeon_device *rdev);
 extern void radeon_modeset_fini(struct radeon_device *rdev);
 extern bool radeon_card_posted(struct radeon_device *rdev);
@@ -1504,6 +1503,12 @@
 extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size);
 
 /*
+ * R600 vram scratch functions
+ */
+int r600_vram_scratch_init(struct radeon_device *rdev);
+void r600_vram_scratch_fini(struct radeon_device *rdev);
+
+/*
  * r600 functions used by radeon_encoder.c
  */
 extern void r600_hdmi_enable(struct drm_encoder *encoder);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_i2c.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_i2c.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,8 @@
  * Authors: Dave Airlie
  *          Alex Deucher
  */
+#include <linux/export.h>
+
 #include "drmP.h"
 #include "radeon_drm.h"
 #include "radeon.h"
@@ -32,7 +34,7 @@
  * radeon_ddc_probe
  *
  */
-bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe)
+bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 {
 	u8 out = 0x0;
 	u8 buf[8];
@@ -47,15 +49,11 @@
 		{
 			.addr = 0x50,
 			.flags = I2C_M_RD,
-			.len = 1,
+			.len = 8,
 			.buf = buf,
 		}
 	};
 
-	/* Read 8 bytes from i2c for extended probe of EDID header */
-	if (requires_extended_probe)
-		msgs[1].len = 8;
-
 	/* on hw with routers, select right port */
 	if (radeon_connector->router.ddc_valid)
 		radeon_router_select_ddc_port(radeon_connector);
@@ -64,25 +62,24 @@
 	if (ret != 2)
 		/* Couldn't find an accessible DDC on this connector */
 		return false;
-	if (requires_extended_probe) {
-		/* Probe also for valid EDID header
-		 * EDID header starts with:
-		 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
-		 * Only the first 6 bytes must be valid as
-		 * drm_edid_block_valid() can fix the last 2 bytes */
-		if (drm_edid_header_is_valid(buf) < 6) {
-			/* Couldn't find an accessible EDID on this
-			 * connector */
-			return false;
-		}
+	/* Probe also for valid EDID header
+	 * EDID header starts with:
+	 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
+	 * Only the first 6 bytes must be valid as
+	 * drm_edid_block_valid() can fix the last 2 bytes */
+	if (drm_edid_header_is_valid(buf) < 6) {
+		/* Couldn't find an accessible EDID on this
+		 * connector */
+		return false;
 	}
 	return true;
 }
 
 /* bit banging i2c */
 
-static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
+static int pre_xfer(struct i2c_adapter *i2c_adap)
 {
+	struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
 	struct radeon_device *rdev = i2c->dev->dev_private;
 	struct radeon_i2c_bus_rec *rec = &i2c->rec;
 	uint32_t temp;
@@ -137,19 +134,30 @@
 	WREG32(rec->en_data_reg, temp);
 
 	/* mask the gpio pins for software use */
-	temp = RREG32(rec->mask_clk_reg);
-	if (lock_state)
-		temp |= rec->mask_clk_mask;
-	else
-		temp &= ~rec->mask_clk_mask;
+	temp = RREG32(rec->mask_clk_reg) | rec->mask_clk_mask;
 	WREG32(rec->mask_clk_reg, temp);
 	temp = RREG32(rec->mask_clk_reg);
 
+	temp = RREG32(rec->mask_data_reg) | rec->mask_data_mask;
+	WREG32(rec->mask_data_reg, temp);
 	temp = RREG32(rec->mask_data_reg);
-	if (lock_state)
-		temp |= rec->mask_data_mask;
-	else
-		temp &= ~rec->mask_data_mask;
+
+	return 0;
+}
+
+static void post_xfer(struct i2c_adapter *i2c_adap)
+{
+	struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
+	struct radeon_device *rdev = i2c->dev->dev_private;
+	struct radeon_i2c_bus_rec *rec = &i2c->rec;
+	uint32_t temp;
+
+	/* unmask the gpio pins for software use */
+	temp = RREG32(rec->mask_clk_reg) & ~rec->mask_clk_mask;
+	WREG32(rec->mask_clk_reg, temp);
+	temp = RREG32(rec->mask_clk_reg);
+
+	temp = RREG32(rec->mask_data_reg) & ~rec->mask_data_mask;
 	WREG32(rec->mask_data_reg, temp);
 	temp = RREG32(rec->mask_data_reg);
 }
@@ -209,22 +217,6 @@
 	WREG32(rec->en_data_reg, val);
 }
 
-static int pre_xfer(struct i2c_adapter *i2c_adap)
-{
-	struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
-
-	radeon_i2c_do_lock(i2c, 1);
-
-	return 0;
-}
-
-static void post_xfer(struct i2c_adapter *i2c_adap)
-{
-	struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
-
-	radeon_i2c_do_lock(i2c, 0);
-}
-
 /* hw i2c */
 
 static u32 radeon_get_i2c_prescale(struct radeon_device *rdev)
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_irq.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_irq.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -129,7 +129,7 @@
 	}
 }
 
-static inline u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_disp_int)
+static u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_disp_int)
 {
 	u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS);
 	u32 irq_mask = RADEON_SW_INT_TEST;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_irq_kms.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_irq_kms.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_irq_kms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_irq_kms.c	2012-01-04 18:55:44.000000000 -0500
@@ -67,10 +67,10 @@
 	/* Disable *all* interrupts */
 	rdev->irq.sw_int = false;
 	rdev->irq.gui_idle = false;
-	for (i = 0; i < rdev->num_crtc; i++)
-		rdev->irq.crtc_vblank_int[i] = false;
-	for (i = 0; i < 6; i++) {
+	for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
 		rdev->irq.hpd[i] = false;
+	for (i = 0; i < RADEON_MAX_CRTCS; i++) {
+		rdev->irq.crtc_vblank_int[i] = false;
 		rdev->irq.pflip[i] = false;
 	}
 	radeon_irq_set(rdev);
@@ -99,15 +99,55 @@
 	/* Disable *all* interrupts */
 	rdev->irq.sw_int = false;
 	rdev->irq.gui_idle = false;
-	for (i = 0; i < rdev->num_crtc; i++)
-		rdev->irq.crtc_vblank_int[i] = false;
-	for (i = 0; i < 6; i++) {
+	for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
 		rdev->irq.hpd[i] = false;
+	for (i = 0; i < RADEON_MAX_CRTCS; i++) {
+		rdev->irq.crtc_vblank_int[i] = false;
 		rdev->irq.pflip[i] = false;
 	}
 	radeon_irq_set(rdev);
 }
 
+static bool radeon_msi_ok(struct radeon_device *rdev)
+{
+	/* RV370/RV380 was first asic with MSI support */
+	if (rdev->family < CHIP_RV380)
+		return false;
+
+	/* MSIs don't work on AGP */
+	if (rdev->flags & RADEON_IS_AGP)
+		return false;
+
+	/* force MSI on */
+	if (radeon_msi == 1)
+		return true;
+	else if (radeon_msi == 0)
+		return false;
+
+	/* Quirks */
+	/* HP RS690 only seems to work with MSIs. */
+	if ((rdev->pdev->device == 0x791f) &&
+	    (rdev->pdev->subsystem_vendor == 0x103c) &&
+	    (rdev->pdev->subsystem_device == 0x30c2))
+		return true;
+
+	/* Dell RS690 only seems to work with MSIs. */
+	if ((rdev->pdev->device == 0x791f) &&
+	    (rdev->pdev->subsystem_vendor == 0x1028) &&
+	    (rdev->pdev->subsystem_device == 0x01fd))
+		return true;
+
+	if (rdev->flags & RADEON_IS_IGP) {
+		/* APUs work fine with MSIs */
+		if (rdev->family >= CHIP_PALM)
+			return true;
+		/* lots of IGPs have problems with MSIs */
+		return false;
+	}
+
+	return true;
+}
+
 int radeon_irq_kms_init(struct radeon_device *rdev)
 {
 	int i;
@@ -124,12 +164,8 @@
 	}
 	/* enable msi */
 	rdev->msi_enabled = 0;
-	/* MSIs don't seem to work reliably on all IGP
-	 * chips.  Disable MSI on them for now.
-	 */
-	if ((rdev->family >= CHIP_RV380) &&
-	    ((!(rdev->flags & RADEON_IS_IGP)) || (rdev->family >= CHIP_PALM)) &&
-	    (!(rdev->flags & RADEON_IS_AGP))) {
+
+	if (radeon_msi_ok(rdev)) {
 		int ret = pci_enable_msi(rdev->pdev);
 		if (!ret) {
 			rdev->msi_enabled = 1;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_legacy_crtc.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_legacy_crtc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_legacy_crtc.c	2012-01-04 18:55:44.000000000 -0500
@@ -991,12 +991,6 @@
 				   struct drm_display_mode *mode,
 				   struct drm_display_mode *adjusted_mode)
 {
-	struct drm_device *dev = crtc->dev;
-	struct radeon_device *rdev = dev->dev_private;
-
-	/* adjust pm to upcoming mode change */
-	radeon_pm_compute_clocks(rdev);
-
 	if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
 		return false;
 	return true;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_legacy_tv.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_legacy_tv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_legacy_tv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_legacy_tv.c	2012-01-04 18:55:44.000000000 -0500
@@ -864,7 +864,7 @@
 	*v_sync_strt_wid = tmp;
 }
 
-static inline int get_post_div(int value)
+static int get_post_div(int value)
 {
 	int post_div;
 	switch (value) {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_mode.h linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_mode.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_mode.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_mode.h	2012-01-04 18:55:44.000000000 -0500
@@ -438,15 +438,13 @@
 	struct radeon_i2c_chan *ddc_bus;
 	/* some systems have an hdmi and vga port with a shared ddc line */
 	bool shared_ddc;
-	/* for some Radeon chip families we apply an additional EDID header
-	   check as part of the DDC probe */
-	bool requires_extended_probe;
 	bool use_digital;
 	/* we need to mind the EDID between detect
 	   and get modes due to analog/digital/tvencoder */
 	struct edid *edid;
 	void *con_priv;
 	bool dac_load_detect;
+	bool detected_by_load; /* if the connection status was determined by load */
 	uint16_t connector_object_id;
 	struct radeon_hpd hpd;
 	struct radeon_router router;
@@ -458,6 +456,8 @@
 	struct drm_gem_object *obj;
 };
 
+#define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \
+				((em) == ATOM_ENCODER_MODE_DP_MST))
 
 extern enum radeon_tv_std
 radeon_combios_get_tv_info(struct radeon_device *rdev);
@@ -467,8 +467,8 @@
 extern struct drm_connector *
 radeon_get_connector_for_encoder(struct drm_encoder *encoder);
 
-extern bool radeon_encoder_is_dp_bridge(struct drm_encoder *encoder);
-extern bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector);
+extern u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder);
+extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector);
 extern bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector);
 extern bool radeon_connector_is_dp12_capable(struct drm_connector *connector);
 
@@ -488,7 +488,7 @@
 					   int action, uint8_t lane_num,
 					   uint8_t lane_set);
 extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder);
-extern struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder);
+extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder);
 extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 				u8 write_byte, u8 *read_byte);
 
@@ -518,8 +518,7 @@
 				u8 val);
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
-extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector,
-			bool requires_extended_probe);
+extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_object.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_object.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_object.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_object.c	2012-01-04 18:55:44.000000000 -0500
@@ -515,3 +515,44 @@
 	}
 	return 0;
 }
+
+int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, bool no_wait)
+{
+	int r;
+
+	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
+	if (unlikely(r != 0))
+		return r;
+	spin_lock(&bo->tbo.bdev->fence_lock);
+	if (mem_type)
+		*mem_type = bo->tbo.mem.mem_type;
+	if (bo->tbo.sync_obj)
+		r = ttm_bo_wait(&bo->tbo, true, true, no_wait);
+	spin_unlock(&bo->tbo.bdev->fence_lock);
+	ttm_bo_unreserve(&bo->tbo);
+	return r;
+}
+
+
+/**
+ * radeon_bo_reserve - reserve bo
+ * @bo:		bo structure
+ * @no_wait:		don't sleep while trying to reserve (return -EBUSY)
+ *
+ * Returns:
+ * -EBUSY: buffer is busy and @no_wait is true
+ * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by
+ * a signal. Release all buffer reservations and return to user-space.
+ */
+int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait)
+{
+	int r;
+
+	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
+	if (unlikely(r != 0)) {
+		if (r != -ERESTARTSYS)
+			dev_err(bo->rdev->dev, "%p reserve failed\n", bo);
+		return r;
+	}
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_object.h linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_object.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_object.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_object.h	2012-01-04 18:55:44.000000000 -0500
@@ -52,28 +52,7 @@
 	return 0;
 }
 
-/**
- * radeon_bo_reserve - reserve bo
- * @bo:		bo structure
- * @no_wait:		don't sleep while trying to reserve (return -EBUSY)
- *
- * Returns:
- * -EBUSY: buffer is busy and @no_wait is true
- * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by
- * a signal. Release all buffer reservations and return to user-space.
- */
-static inline int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait)
-{
-	int r;
-
-	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
-	if (unlikely(r != 0)) {
-		if (r != -ERESTARTSYS)
-			dev_err(bo->rdev->dev, "%p reserve failed\n", bo);
-		return r;
-	}
-	return 0;
-}
+int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait);
 
 static inline void radeon_bo_unreserve(struct radeon_bo *bo)
 {
@@ -118,23 +97,8 @@
 	return bo->tbo.addr_space_offset;
 }
 
-static inline int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type,
-					bool no_wait)
-{
-	int r;
-
-	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
-	if (unlikely(r != 0))
-		return r;
-	spin_lock(&bo->tbo.bdev->fence_lock);
-	if (mem_type)
-		*mem_type = bo->tbo.mem.mem_type;
-	if (bo->tbo.sync_obj)
-		r = ttm_bo_wait(&bo->tbo, true, true, no_wait);
-	spin_unlock(&bo->tbo.bdev->fence_lock);
-	ttm_bo_unreserve(&bo->tbo);
-	return r;
-}
+extern int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type,
+			  bool no_wait);
 
 extern int radeon_bo_create(struct radeon_device *rdev,
 				unsigned long size, int byte_align,
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_pm.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_pm.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_pm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_pm.c	2012-01-04 18:55:44.000000000 -0500
@@ -53,6 +53,24 @@
 
 #define ACPI_AC_CLASS           "ac_adapter"
 
+int radeon_pm_get_type_index(struct radeon_device *rdev,
+			     enum radeon_pm_state_type ps_type,
+			     int instance)
+{
+	int i;
+	int found_instance = -1;
+
+	for (i = 0; i < rdev->pm.num_power_states; i++) {
+		if (rdev->pm.power_state[i].type == ps_type) {
+			found_instance++;
+			if (found_instance == instance)
+				return i;
+		}
+	}
+	/* return default if no match */
+	return rdev->pm.default_power_state_index;
+}
+
 #ifdef CONFIG_ACPI
 static int radeon_acpi_event(struct notifier_block *nb,
 			     unsigned long val,
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_ring.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_ring.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_ring.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_ring.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,44 @@
 
 int radeon_debugfs_ib_init(struct radeon_device *rdev);
 
+u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx)
+{
+	struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx];
+	u32 pg_idx, pg_offset;
+	u32 idx_value = 0;
+	int new_page;
+
+	pg_idx = (idx * 4) / PAGE_SIZE;
+	pg_offset = (idx * 4) % PAGE_SIZE;
+
+	if (ibc->kpage_idx[0] == pg_idx)
+		return ibc->kpage[0][pg_offset/4];
+	if (ibc->kpage_idx[1] == pg_idx)
+		return ibc->kpage[1][pg_offset/4];
+
+	new_page = radeon_cs_update_pages(p, pg_idx);
+	if (new_page < 0) {
+		p->parser_error = new_page;
+		return 0;
+	}
+
+	idx_value = ibc->kpage[new_page][pg_offset/4];
+	return idx_value;
+}
+
+void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
+{
+#if DRM_DEBUG_CODE
+	if (rdev->cp.count_dw <= 0) {
+		DRM_ERROR("radeon: writting more dword to ring than expected !\n");
+	}
+#endif
+	rdev->cp.ring[rdev->cp.wptr++] = v;
+	rdev->cp.wptr &= rdev->cp.ptr_mask;
+	rdev->cp.count_dw--;
+	rdev->cp.ring_free_dw--;
+}
+
 void radeon_ib_bogus_cleanup(struct radeon_device *rdev)
 {
 	struct radeon_ib *ib, *n;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_state.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_state.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/radeon_state.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/radeon_state.c	2012-01-04 18:55:44.000000000 -0500
@@ -272,12 +272,12 @@
 	return 0;
 }
 
-static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
-						     dev_priv,
-						     struct drm_file *file_priv,
-						     drm_radeon_kcmd_buffer_t *
-						     cmdbuf,
-						     unsigned int *cmdsz)
+static int radeon_check_and_fixup_packet3(drm_radeon_private_t *
+					  dev_priv,
+					  struct drm_file *file_priv,
+					  drm_radeon_kcmd_buffer_t *
+					  cmdbuf,
+					  unsigned int *cmdsz)
 {
 	u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
 	u32 offset, narrays;
@@ -446,8 +446,8 @@
  * CP hardware state programming functions
  */
 
-static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
-					     struct drm_clip_rect * box)
+static void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
+				  struct drm_clip_rect * box)
 {
 	RING_LOCALS;
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/rs400.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/rs400.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/rs400.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/rs400.c	2012-01-04 18:55:44.000000000 -0500
@@ -77,7 +77,7 @@
 {
 	int r;
 
-	if (rdev->gart.table.ram.ptr) {
+	if (rdev->gart.ptr) {
 		WARN(1, "RS400 GART already initialized\n");
 		return 0;
 	}
@@ -182,6 +182,9 @@
 	/* Enable gart */
 	WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | size_reg));
 	rs400_gart_tlb_flush(rdev);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+		 (unsigned)(rdev->mc.gtt_size >> 20),
+		 (unsigned long long)rdev->gart.table_addr);
 	rdev->gart.ready = true;
 	return 0;
 }
@@ -209,6 +212,7 @@
 int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 {
 	uint32_t entry;
+	u32 *gtt = rdev->gart.ptr;
 
 	if (i < 0 || i > rdev->gart.num_gpu_pages) {
 		return -EINVAL;
@@ -218,7 +222,7 @@
 		((upper_32_bits(addr) & 0xff) << 4) |
 		RS400_PTE_WRITEABLE | RS400_PTE_READABLE;
 	entry = cpu_to_le32(entry);
-	rdev->gart.table.ram.ptr[i] = entry;
+	gtt[i] = entry;
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/rs600.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/rs600.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/rs600.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/rs600.c	2012-01-04 18:55:44.000000000 -0500
@@ -62,6 +62,7 @@
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
+	int i;
 
 	/* Lock the graphics update lock */
 	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
@@ -74,7 +75,11 @@
 	       (u32)crtc_base);
 
 	/* Wait for update_pending to go high. */
-	while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING));
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
+			break;
+		udelay(1);
+	}
 	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
 
 	/* Unlock the lock, so double-buffering can take place inside vblank */
@@ -287,6 +292,7 @@
 		default:
 			break;
 		}
+		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
 	}
 	if (rdev->irq.installed)
 		rs600_irq_set(rdev);
@@ -413,7 +419,7 @@
 {
 	int r;
 
-	if (rdev->gart.table.vram.robj) {
+	if (rdev->gart.robj) {
 		WARN(1, "RS600 GART already initialized\n");
 		return 0;
 	}
@@ -431,7 +437,7 @@
 	u32 tmp;
 	int r, i;
 
-	if (rdev->gart.table.vram.robj == NULL) {
+	if (rdev->gart.robj == NULL) {
 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
 		return -EINVAL;
 	}
@@ -484,6 +490,9 @@
 	tmp = RREG32_MC(R_000009_MC_CNTL1);
 	WREG32_MC(R_000009_MC_CNTL1, (tmp | S_000009_ENABLE_PAGE_TABLES(1)));
 	rs600_gart_tlb_flush(rdev);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+		 (unsigned)(rdev->mc.gtt_size >> 20),
+		 (unsigned long long)rdev->gart.table_addr);
 	rdev->gart.ready = true;
 	return 0;
 }
@@ -491,20 +500,12 @@
 void rs600_gart_disable(struct radeon_device *rdev)
 {
 	u32 tmp;
-	int r;
 
 	/* FIXME: disable out of gart access */
 	WREG32_MC(R_000100_MC_PT0_CNTL, 0);
 	tmp = RREG32_MC(R_000009_MC_CNTL1);
 	WREG32_MC(R_000009_MC_CNTL1, tmp & C_000009_ENABLE_PAGE_TABLES);
-	if (rdev->gart.table.vram.robj) {
-		r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
-		if (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);
-		}
-	}
+	radeon_gart_table_vram_unpin(rdev);
 }
 
 void rs600_gart_fini(struct radeon_device *rdev)
@@ -522,7 +523,7 @@
 
 int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 {
-	void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+	void __iomem *ptr = (void *)rdev->gart.ptr;
 
 	if (i < 0 || i > rdev->gart.num_gpu_pages) {
 		return -EINVAL;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/radeon/rv770.c linux-libre-3.2-gnu/drivers/gpu/drm/radeon/rv770.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/radeon/rv770.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/radeon/rv770.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,7 @@
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
+	int i;
 
 	/* Lock the graphics update lock */
 	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
@@ -66,7 +67,11 @@
 	       (u32)crtc_base);
 
 	/* Wait for update_pending to go high. */
-	while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING));
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
+			break;
+		udelay(1);
+	}
 	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
 
 	/* Unlock the lock, so double-buffering can take place inside vblank */
@@ -124,7 +129,7 @@
 	u32 tmp;
 	int r, i;
 
-	if (rdev->gart.table.vram.robj == NULL) {
+	if (rdev->gart.robj == NULL) {
 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
 		return -EINVAL;
 	}
@@ -161,6 +166,9 @@
 		WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
 
 	r600_pcie_gart_tlb_flush(rdev);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+		 (unsigned)(rdev->mc.gtt_size >> 20),
+		 (unsigned long long)rdev->gart.table_addr);
 	rdev->gart.ready = true;
 	return 0;
 }
@@ -168,7 +176,7 @@
 void rv770_pcie_gart_disable(struct radeon_device *rdev)
 {
 	u32 tmp;
-	int i, r;
+	int i;
 
 	/* Disable all tables */
 	for (i = 0; i < 7; i++)
@@ -188,14 +196,7 @@
 	WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
 	WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
 	WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
-	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);
-		}
-	}
+	radeon_gart_table_vram_unpin(rdev);
 }
 
 void rv770_pcie_gart_fini(struct radeon_device *rdev)
@@ -279,7 +280,7 @@
 		WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
 			rdev->mc.vram_end >> 12);
 	}
-	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
+	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12);
 	tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
 	tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
 	WREG32(MC_VM_FB_LOCATION, tmp);
@@ -956,54 +957,6 @@
 
 }
 
-static int rv770_vram_scratch_init(struct radeon_device *rdev)
-{
-	int r;
-	u64 gpu_addr;
-
-	if (rdev->vram_scratch.robj == NULL) {
-		r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE,
-				     PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
-				     &rdev->vram_scratch.robj);
-		if (r) {
-			return r;
-		}
-	}
-
-	r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
-	if (unlikely(r != 0))
-		return r;
-	r = radeon_bo_pin(rdev->vram_scratch.robj,
-			  RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
-	if (r) {
-		radeon_bo_unreserve(rdev->vram_scratch.robj);
-		return r;
-	}
-	r = radeon_bo_kmap(rdev->vram_scratch.robj,
-				(void **)&rdev->vram_scratch.ptr);
-	if (r)
-		radeon_bo_unpin(rdev->vram_scratch.robj);
-	radeon_bo_unreserve(rdev->vram_scratch.robj);
-
-	return r;
-}
-
-static void rv770_vram_scratch_fini(struct radeon_device *rdev)
-{
-	int r;
-
-	if (rdev->vram_scratch.robj == NULL) {
-		return;
-	}
-	r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
-	if (likely(r == 0)) {
-		radeon_bo_kunmap(rdev->vram_scratch.robj);
-		radeon_bo_unpin(rdev->vram_scratch.robj);
-		radeon_bo_unreserve(rdev->vram_scratch.robj);
-	}
-	radeon_bo_unref(&rdev->vram_scratch.robj);
-}
-
 void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
 {
 	u64 size_bf, size_af;
@@ -1103,6 +1056,10 @@
 		}
 	}
 
+	r = r600_vram_scratch_init(rdev);
+	if (r)
+		return r;
+
 	rv770_mc_program(rdev);
 	if (rdev->flags & RADEON_IS_AGP) {
 		rv770_agp_enable(rdev);
@@ -1111,9 +1068,7 @@
 		if (r)
 			return r;
 	}
-	r = rv770_vram_scratch_init(rdev);
-	if (r)
-		return r;
+
 	rv770_gpu_init(rdev);
 	r = r600_blit_init(rdev);
 	if (r) {
@@ -1184,8 +1139,6 @@
 
 int rv770_suspend(struct radeon_device *rdev)
 {
-	int r;
-
 	r600_audio_fini(rdev);
 	/* FIXME: we should wait for ring to be empty */
 	r700_cp_stop(rdev);
@@ -1193,14 +1146,8 @@
 	r600_irq_suspend(rdev);
 	radeon_wb_disable(rdev);
 	rv770_pcie_gart_disable(rdev);
-	/* unpin shaders bo */
-	if (rdev->r600_blit.shader_obj) {
-		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);
-		}
-	}
+	r600_blit_suspend(rdev);
+
 	return 0;
 }
 
@@ -1321,7 +1268,7 @@
 	radeon_ib_pool_fini(rdev);
 	radeon_irq_kms_fini(rdev);
 	rv770_pcie_gart_fini(rdev);
-	rv770_vram_scratch_fini(rdev);
+	r600_vram_scratch_fini(rdev);
 	radeon_gem_fini(rdev);
 	radeon_fence_driver_fini(rdev);
 	radeon_agp_fini(rdev);
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/savage/savage_drv.c linux-libre-3.2-gnu/drivers/gpu/drm/savage/savage_drv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/savage/savage_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/savage/savage_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,8 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "savage_drm.h"
 #include "savage_drv.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/sis/sis_drv.c linux-libre-3.2-gnu/drivers/gpu/drm/sis/sis_drv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/sis/sis_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/sis/sis_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,8 @@
  *
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "sis_drm.h"
 #include "sis_drv.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/tdfx/tdfx_drv.c linux-libre-3.2-gnu/drivers/gpu/drm/tdfx/tdfx_drv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/tdfx/tdfx_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/tdfx/tdfx_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,8 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "tdfx_drv.h"
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/ttm/ttm_bo.c linux-libre-3.2-gnu/drivers/gpu/drm/ttm/ttm_bo.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/ttm/ttm_bo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/ttm/ttm_bo.c	2012-01-04 18:55:44.000000000 -0500
@@ -574,10 +574,16 @@
 		return ret;
 
 	spin_lock(&glob->lru_lock);
+
+	if (unlikely(list_empty(&bo->ddestroy))) {
+		spin_unlock(&glob->lru_lock);
+		return 0;
+	}
+
 	ret = ttm_bo_reserve_locked(bo, interruptible,
 				    no_wait_reserve, false, 0);
 
-	if (unlikely(ret != 0) || list_empty(&bo->ddestroy)) {
+	if (unlikely(ret != 0)) {
 		spin_unlock(&glob->lru_lock);
 		return ret;
 	}
@@ -1293,6 +1299,7 @@
 
 	return ret;
 }
+EXPORT_SYMBOL(ttm_bo_create);
 
 static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev,
 					unsigned mem_type, bool allow_errors)
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/ttm/ttm_tt.c linux-libre-3.2-gnu/drivers/gpu/drm/ttm/ttm_tt.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/ttm/ttm_tt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/ttm/ttm_tt.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <linux/file.h>
 #include <linux/swap.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "drm_cache.h"
 #include "drm_mem_util.h"
 #include "ttm/ttm_module.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/via/via_drv.c linux-libre-3.2-gnu/drivers/gpu/drm/via/via_drv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/via/via_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/via/via_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,8 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/module.h>
+
 #include "drmP.h"
 #include "via_drm.h"
 #include "via_drv.h"
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/Kconfig linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/Kconfig
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,8 @@
 	select FB_CFB_IMAGEBLIT
 	select DRM_TTM
 	help
-	  KMS enabled DRM driver for SVGA2 virtual hardware.
-
-	  If unsure say n. The compiled module will be
-	  called vmwgfx.ko
+	  Choose this option if you would like to run 3D acceleration
+	  in a VMware virtual machine.
+	  This is a KMS enabled DRM driver for the VMware SVGA2
+	  virtual hardware.
+	  The compiled module will be called "vmwgfx.ko".
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/Makefile linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/Makefile
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@
 vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
 	    vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \
 	    vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
-	    vmwgfx_overlay.o vmwgfx_fence.o vmwgfx_gmrid_manager.o
+	    vmwgfx_overlay.o vmwgfx_marker.o vmwgfx_gmrid_manager.o \
+	    vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o
 
 obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/svga3d_reg.h linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/svga3d_reg.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/svga3d_reg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/svga3d_reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -57,7 +57,8 @@
    SVGA3D_HWVERSION_WS6_B1    = SVGA3D_MAKE_HWVERSION(1, 1),
    SVGA3D_HWVERSION_FUSION_11 = SVGA3D_MAKE_HWVERSION(1, 4),
    SVGA3D_HWVERSION_WS65_B1   = SVGA3D_MAKE_HWVERSION(2, 0),
-   SVGA3D_HWVERSION_CURRENT   = SVGA3D_HWVERSION_WS65_B1,
+   SVGA3D_HWVERSION_WS8_B1    = SVGA3D_MAKE_HWVERSION(2, 1),
+   SVGA3D_HWVERSION_CURRENT   = SVGA3D_HWVERSION_WS8_B1,
 } SVGA3dHardwareVersion;
 
 /*
@@ -67,7 +68,8 @@
 typedef uint32 SVGA3dBool; /* 32-bit Bool definition */
 #define SVGA3D_NUM_CLIPPLANES                   6
 #define SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS  8
-
+#define SVGA3D_MAX_CONTEXT_IDS                  256
+#define SVGA3D_MAX_SURFACE_IDS                  (32 * 1024)
 
 /*
  * Surface formats.
@@ -79,76 +81,91 @@
  */
 
 typedef enum SVGA3dSurfaceFormat {
-   SVGA3D_FORMAT_INVALID = 0,
+   SVGA3D_FORMAT_INVALID               = 0,
 
-   SVGA3D_X8R8G8B8       = 1,
-   SVGA3D_A8R8G8B8       = 2,
+   SVGA3D_X8R8G8B8                     = 1,
+   SVGA3D_A8R8G8B8                     = 2,
 
-   SVGA3D_R5G6B5         = 3,
-   SVGA3D_X1R5G5B5       = 4,
-   SVGA3D_A1R5G5B5       = 5,
-   SVGA3D_A4R4G4B4       = 6,
+   SVGA3D_R5G6B5                       = 3,
+   SVGA3D_X1R5G5B5                     = 4,
+   SVGA3D_A1R5G5B5                     = 5,
+   SVGA3D_A4R4G4B4                     = 6,
 
-   SVGA3D_Z_D32          = 7,
-   SVGA3D_Z_D16          = 8,
-   SVGA3D_Z_D24S8        = 9,
-   SVGA3D_Z_D15S1        = 10,
+   SVGA3D_Z_D32                        = 7,
+   SVGA3D_Z_D16                        = 8,
+   SVGA3D_Z_D24S8                      = 9,
+   SVGA3D_Z_D15S1                      = 10,
 
-   SVGA3D_LUMINANCE8            = 11,
-   SVGA3D_LUMINANCE4_ALPHA4     = 12,
-   SVGA3D_LUMINANCE16           = 13,
-   SVGA3D_LUMINANCE8_ALPHA8     = 14,
+   SVGA3D_LUMINANCE8                   = 11,
+   SVGA3D_LUMINANCE4_ALPHA4            = 12,
+   SVGA3D_LUMINANCE16                  = 13,
+   SVGA3D_LUMINANCE8_ALPHA8            = 14,
 
-   SVGA3D_DXT1           = 15,
-   SVGA3D_DXT2           = 16,
-   SVGA3D_DXT3           = 17,
-   SVGA3D_DXT4           = 18,
-   SVGA3D_DXT5           = 19,
+   SVGA3D_DXT1                         = 15,
+   SVGA3D_DXT2                         = 16,
+   SVGA3D_DXT3                         = 17,
+   SVGA3D_DXT4                         = 18,
+   SVGA3D_DXT5                         = 19,
 
-   SVGA3D_BUMPU8V8       = 20,
-   SVGA3D_BUMPL6V5U5     = 21,
-   SVGA3D_BUMPX8L8V8U8   = 22,
-   SVGA3D_BUMPL8V8U8     = 23,
+   SVGA3D_BUMPU8V8                     = 20,
+   SVGA3D_BUMPL6V5U5                   = 21,
+   SVGA3D_BUMPX8L8V8U8                 = 22,
+   SVGA3D_BUMPL8V8U8                   = 23,
 
-   SVGA3D_ARGB_S10E5     = 24,   /* 16-bit floating-point ARGB */
-   SVGA3D_ARGB_S23E8     = 25,   /* 32-bit floating-point ARGB */
+   SVGA3D_ARGB_S10E5                   = 24,   /* 16-bit floating-point ARGB */
+   SVGA3D_ARGB_S23E8                   = 25,   /* 32-bit floating-point ARGB */
 
-   SVGA3D_A2R10G10B10    = 26,
+   SVGA3D_A2R10G10B10                  = 26,
 
    /* signed formats */
-   SVGA3D_V8U8           = 27,
-   SVGA3D_Q8W8V8U8       = 28,
-   SVGA3D_CxV8U8         = 29,
+   SVGA3D_V8U8                         = 27,
+   SVGA3D_Q8W8V8U8                     = 28,
+   SVGA3D_CxV8U8                       = 29,
 
    /* mixed formats */
-   SVGA3D_X8L8V8U8       = 30,
-   SVGA3D_A2W10V10U10    = 31,
+   SVGA3D_X8L8V8U8                     = 30,
+   SVGA3D_A2W10V10U10                  = 31,
 
-   SVGA3D_ALPHA8         = 32,
+   SVGA3D_ALPHA8                       = 32,
 
    /* Single- and dual-component floating point formats */
-   SVGA3D_R_S10E5        = 33,
-   SVGA3D_R_S23E8        = 34,
-   SVGA3D_RG_S10E5       = 35,
-   SVGA3D_RG_S23E8       = 36,
+   SVGA3D_R_S10E5                      = 33,
+   SVGA3D_R_S23E8                      = 34,
+   SVGA3D_RG_S10E5                     = 35,
+   SVGA3D_RG_S23E8                     = 36,
 
    /*
     * Any surface can be used as a buffer object, but SVGA3D_BUFFER is
     * the most efficient format to use when creating new surfaces
     * expressly for index or vertex data.
     */
-   SVGA3D_BUFFER         = 37,
 
-   SVGA3D_Z_D24X8        = 38,
+   SVGA3D_BUFFER                       = 37,
 
-   SVGA3D_V16U16         = 39,
+   SVGA3D_Z_D24X8                      = 38,
 
-   SVGA3D_G16R16         = 40,
-   SVGA3D_A16B16G16R16   = 41,
+   SVGA3D_V16U16                       = 39,
+
+   SVGA3D_G16R16                       = 40,
+   SVGA3D_A16B16G16R16                 = 41,
 
    /* Packed Video formats */
-   SVGA3D_UYVY           = 42,
-   SVGA3D_YUY2           = 43,
+   SVGA3D_UYVY                         = 42,
+   SVGA3D_YUY2                         = 43,
+
+   /* Planar video formats */
+   SVGA3D_NV12                         = 44,
+
+   /* Video format with alpha */
+   SVGA3D_AYUV                         = 45,
+
+   SVGA3D_BC4_UNORM                    = 108,
+   SVGA3D_BC5_UNORM                    = 111,
+
+   /* Advanced D3D9 depth formats. */
+   SVGA3D_Z_DF16                       = 118,
+   SVGA3D_Z_DF24                       = 119,
+   SVGA3D_Z_D24S8_INT                  = 120,
 
    SVGA3D_FORMAT_MAX
 } SVGA3dSurfaceFormat;
@@ -414,10 +431,20 @@
    SVGA3D_RS_SRCBLENDALPHA             = 94,    /* SVGA3dBlendOp */
    SVGA3D_RS_DSTBLENDALPHA             = 95,    /* SVGA3dBlendOp */
    SVGA3D_RS_BLENDEQUATIONALPHA        = 96,    /* SVGA3dBlendEquation */
+   SVGA3D_RS_TRANSPARENCYANTIALIAS     = 97,    /* SVGA3dTransparencyAntialiasType */
+   SVGA3D_RS_LINEAA                    = 98,    /* SVGA3dBool */
+   SVGA3D_RS_LINEWIDTH                 = 99,    /* float */
    SVGA3D_RS_MAX
 } SVGA3dRenderStateName;
 
 typedef enum {
+   SVGA3D_TRANSPARENCYANTIALIAS_NORMAL            = 0,
+   SVGA3D_TRANSPARENCYANTIALIAS_ALPHATOCOVERAGE   = 1,
+   SVGA3D_TRANSPARENCYANTIALIAS_SUPERSAMPLE       = 2,
+   SVGA3D_TRANSPARENCYANTIALIAS_MAX
+} SVGA3dTransparencyAntialiasType;
+
+typedef enum {
    SVGA3D_VERTEXMATERIAL_NONE     = 0,    /* Use the value in the current material */
    SVGA3D_VERTEXMATERIAL_DIFFUSE  = 1,    /* Use the value in the diffuse component */
    SVGA3D_VERTEXMATERIAL_SPECULAR = 2,    /* Use the value in the specular component */
@@ -728,10 +755,10 @@
    SVGA3D_TEX_FILTER_NEAREST        = 1,
    SVGA3D_TEX_FILTER_LINEAR         = 2,
    SVGA3D_TEX_FILTER_ANISOTROPIC    = 3,
-   SVGA3D_TEX_FILTER_FLATCUBIC      = 4, // Deprecated, not implemented
-   SVGA3D_TEX_FILTER_GAUSSIANCUBIC  = 5, // Deprecated, not implemented
-   SVGA3D_TEX_FILTER_PYRAMIDALQUAD  = 6, // Not currently implemented
-   SVGA3D_TEX_FILTER_GAUSSIANQUAD   = 7, // Not currently implemented
+   SVGA3D_TEX_FILTER_FLATCUBIC      = 4, /* Deprecated, not implemented */
+   SVGA3D_TEX_FILTER_GAUSSIANCUBIC  = 5, /* Deprecated, not implemented */
+   SVGA3D_TEX_FILTER_PYRAMIDALQUAD  = 6, /* Not currently implemented */
+   SVGA3D_TEX_FILTER_GAUSSIANQUAD   = 7, /* Not currently implemented */
    SVGA3D_TEX_FILTER_MAX
 } SVGA3dTextureFilter;
 
@@ -799,19 +826,19 @@
 
 typedef enum {
    SVGA3D_DECLUSAGE_POSITION     = 0,
-   SVGA3D_DECLUSAGE_BLENDWEIGHT,       //  1
-   SVGA3D_DECLUSAGE_BLENDINDICES,      //  2
-   SVGA3D_DECLUSAGE_NORMAL,            //  3
-   SVGA3D_DECLUSAGE_PSIZE,             //  4
-   SVGA3D_DECLUSAGE_TEXCOORD,          //  5
-   SVGA3D_DECLUSAGE_TANGENT,           //  6
-   SVGA3D_DECLUSAGE_BINORMAL,          //  7
-   SVGA3D_DECLUSAGE_TESSFACTOR,        //  8
-   SVGA3D_DECLUSAGE_POSITIONT,         //  9
-   SVGA3D_DECLUSAGE_COLOR,             // 10
-   SVGA3D_DECLUSAGE_FOG,               // 11
-   SVGA3D_DECLUSAGE_DEPTH,             // 12
-   SVGA3D_DECLUSAGE_SAMPLE,            // 13
+   SVGA3D_DECLUSAGE_BLENDWEIGHT,       /*  1 */
+   SVGA3D_DECLUSAGE_BLENDINDICES,      /*  2 */
+   SVGA3D_DECLUSAGE_NORMAL,            /*  3 */
+   SVGA3D_DECLUSAGE_PSIZE,             /*  4 */
+   SVGA3D_DECLUSAGE_TEXCOORD,          /*  5 */
+   SVGA3D_DECLUSAGE_TANGENT,           /*  6 */
+   SVGA3D_DECLUSAGE_BINORMAL,          /*  7 */
+   SVGA3D_DECLUSAGE_TESSFACTOR,        /*  8 */
+   SVGA3D_DECLUSAGE_POSITIONT,         /*  9 */
+   SVGA3D_DECLUSAGE_COLOR,             /* 10 */
+   SVGA3D_DECLUSAGE_FOG,               /* 11 */
+   SVGA3D_DECLUSAGE_DEPTH,             /* 12 */
+   SVGA3D_DECLUSAGE_SAMPLE,            /* 13 */
    SVGA3D_DECLUSAGE_MAX
 } SVGA3dDeclUsage;
 
@@ -819,10 +846,10 @@
    SVGA3D_DECLMETHOD_DEFAULT     = 0,
    SVGA3D_DECLMETHOD_PARTIALU,
    SVGA3D_DECLMETHOD_PARTIALV,
-   SVGA3D_DECLMETHOD_CROSSUV,          // Normal
+   SVGA3D_DECLMETHOD_CROSSUV,          /* Normal */
    SVGA3D_DECLMETHOD_UV,
-   SVGA3D_DECLMETHOD_LOOKUP,           // Lookup a displacement map
-   SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED, // Lookup a pre-sampled displacement map
+   SVGA3D_DECLMETHOD_LOOKUP,           /* Lookup a displacement map */
+   SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED, /* Lookup a pre-sampled displacement map */
 } SVGA3dDeclMethod;
 
 typedef enum {
@@ -930,7 +957,6 @@
 } SVGA3dCubeFace;
 
 typedef enum {
-   SVGA3D_SHADERTYPE_COMPILED_DX8               = 0,
    SVGA3D_SHADERTYPE_VS                         = 1,
    SVGA3D_SHADERTYPE_PS                         = 2,
    SVGA3D_SHADERTYPE_MAX
@@ -968,12 +994,18 @@
 } SVGA3dTransferType;
 
 /*
- * The maximum number vertex arrays we're guaranteed to support in
+ * The maximum number of vertex arrays we're guaranteed to support in
  * SVGA_3D_CMD_DRAWPRIMITIVES.
  */
 #define SVGA3D_MAX_VERTEX_ARRAYS   32
 
 /*
+ * The maximum number of primitive ranges we're guaranteed to support
+ * in SVGA_3D_CMD_DRAWPRIMITIVES.
+ */
+#define SVGA3D_MAX_DRAW_PRIMITIVE_RANGES 32
+
+/*
  * Identifiers for commands in the command FIFO.
  *
  * IDs between 1000 and 1039 (inclusive) were used by obsolete versions of
@@ -990,7 +1022,7 @@
 #define SVGA_3D_CMD_LEGACY_BASE            1000
 #define SVGA_3D_CMD_BASE                   1040
 
-#define SVGA_3D_CMD_SURFACE_DEFINE         SVGA_3D_CMD_BASE + 0
+#define SVGA_3D_CMD_SURFACE_DEFINE         SVGA_3D_CMD_BASE + 0     /* Deprecated */
 #define SVGA_3D_CMD_SURFACE_DESTROY        SVGA_3D_CMD_BASE + 1
 #define SVGA_3D_CMD_SURFACE_COPY           SVGA_3D_CMD_BASE + 2
 #define SVGA_3D_CMD_SURFACE_STRETCHBLT     SVGA_3D_CMD_BASE + 3
@@ -1008,7 +1040,7 @@
 #define SVGA_3D_CMD_SETVIEWPORT            SVGA_3D_CMD_BASE + 15
 #define SVGA_3D_CMD_SETCLIPPLANE           SVGA_3D_CMD_BASE + 16
 #define SVGA_3D_CMD_CLEAR                  SVGA_3D_CMD_BASE + 17
-#define SVGA_3D_CMD_PRESENT                SVGA_3D_CMD_BASE + 18    // Deprecated
+#define SVGA_3D_CMD_PRESENT                SVGA_3D_CMD_BASE + 18    /* Deprecated */
 #define SVGA_3D_CMD_SHADER_DEFINE          SVGA_3D_CMD_BASE + 19
 #define SVGA_3D_CMD_SHADER_DESTROY         SVGA_3D_CMD_BASE + 20
 #define SVGA_3D_CMD_SET_SHADER             SVGA_3D_CMD_BASE + 21
@@ -1018,9 +1050,13 @@
 #define SVGA_3D_CMD_BEGIN_QUERY            SVGA_3D_CMD_BASE + 25
 #define SVGA_3D_CMD_END_QUERY              SVGA_3D_CMD_BASE + 26
 #define SVGA_3D_CMD_WAIT_FOR_QUERY         SVGA_3D_CMD_BASE + 27
-#define SVGA_3D_CMD_PRESENT_READBACK       SVGA_3D_CMD_BASE + 28    // Deprecated
+#define SVGA_3D_CMD_PRESENT_READBACK       SVGA_3D_CMD_BASE + 28    /* Deprecated */
 #define SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN SVGA_3D_CMD_BASE + 29
-#define SVGA_3D_CMD_MAX                    SVGA_3D_CMD_BASE + 30
+#define SVGA_3D_CMD_SURFACE_DEFINE_V2      SVGA_3D_CMD_BASE + 30
+#define SVGA_3D_CMD_GENERATE_MIPMAPS       SVGA_3D_CMD_BASE + 31
+#define SVGA_3D_CMD_ACTIVATE_SURFACE       SVGA_3D_CMD_BASE + 40
+#define SVGA_3D_CMD_DEACTIVATE_SURFACE     SVGA_3D_CMD_BASE + 41
+#define SVGA_3D_CMD_MAX                    SVGA_3D_CMD_BASE + 42
 
 #define SVGA_3D_CMD_FUTURE_MAX             2000
 
@@ -1031,9 +1067,9 @@
 typedef struct {
    union {
       struct {
-         uint16  function;       // SVGA3dFogFunction
-         uint8   type;           // SVGA3dFogType
-         uint8   base;           // SVGA3dFogBase
+         uint16  function;       /* SVGA3dFogFunction */
+         uint8   type;           /* SVGA3dFogType */
+         uint8   base;           /* SVGA3dFogBase */
       };
       uint32     uintValue;
    };
@@ -1109,6 +1145,8 @@
    SVGA3D_SURFACE_HINT_RENDERTARGET    = (1 << 6),
    SVGA3D_SURFACE_HINT_DEPTHSTENCIL    = (1 << 7),
    SVGA3D_SURFACE_HINT_WRITEONLY       = (1 << 8),
+   SVGA3D_SURFACE_MASKABLE_ANTIALIAS   = (1 << 9),
+   SVGA3D_SURFACE_AUTOGENMIPMAPS       = (1 << 10),
 } SVGA3dSurfaceFlags;
 
 typedef
@@ -1121,6 +1159,12 @@
    uint32                      sid;
    SVGA3dSurfaceFlags          surfaceFlags;
    SVGA3dSurfaceFormat         format;
+   /*
+    * If surfaceFlags has SVGA3D_SURFACE_CUBEMAP bit set, all SVGA3dSurfaceFace
+    * structures must have the same value of numMipLevels field.
+    * Otherwise, all but the first SVGA3dSurfaceFace structures must have the
+    * numMipLevels set to 0.
+    */
    SVGA3dSurfaceFace           face[SVGA3D_MAX_SURFACE_FACES];
    /*
     * Followed by an SVGA3dSize structure for each mip level in each face.
@@ -1135,6 +1179,31 @@
 
 typedef
 struct {
+   uint32                      sid;
+   SVGA3dSurfaceFlags          surfaceFlags;
+   SVGA3dSurfaceFormat         format;
+   /*
+    * If surfaceFlags has SVGA3D_SURFACE_CUBEMAP bit set, all SVGA3dSurfaceFace
+    * structures must have the same value of numMipLevels field.
+    * Otherwise, all but the first SVGA3dSurfaceFace structures must have the
+    * numMipLevels set to 0.
+    */
+   SVGA3dSurfaceFace           face[SVGA3D_MAX_SURFACE_FACES];
+   uint32                      multisampleCount;
+   SVGA3dTextureFilter         autogenFilter;
+   /*
+    * Followed by an SVGA3dSize structure for each mip level in each face.
+    *
+    * A note on surface sizes: Sizes are always specified in pixels,
+    * even if the true surface size is not a multiple of the minimum
+    * block size of the surface's format. For example, a 3x3x1 DXT1
+    * compressed texture would actually be stored as a 4x4x1 image in
+    * memory.
+    */
+} SVGA3dCmdDefineSurface_v2;     /* SVGA_3D_CMD_SURFACE_DEFINE_V2 */
+
+typedef
+struct {
    uint32               sid;
 } SVGA3dCmdDestroySurface;      /* SVGA_3D_CMD_SURFACE_DESTROY */
 
@@ -1474,10 +1543,12 @@
     * SVGA3dCmdDrawPrimitives structure. In order,
     * they are:
     *
-    * 1. SVGA3dVertexDecl, quantity 'numVertexDecls'
-    * 2. SVGA3dPrimitiveRange, quantity 'numRanges'
+    * 1. SVGA3dVertexDecl, quantity 'numVertexDecls', but no more than
+    *    SVGA3D_MAX_VERTEX_ARRAYS;
+    * 2. SVGA3dPrimitiveRange, quantity 'numRanges', but no more than
+    *    SVGA3D_MAX_DRAW_PRIMITIVE_RANGES;
     * 3. Optionally, SVGA3dVertexDivisor, quantity 'numVertexDecls' (contains
-    *    the frequency divisor for this the corresponding vertex decl)
+    *    the frequency divisor for the corresponding vertex decl).
     */
 } SVGA3dCmdDrawPrimitives;      /* SVGA_3D_CMD_DRAWPRIMITIVES */
 
@@ -1671,6 +1742,12 @@
    /* Clipping: zero or more SVGASignedRects follow */
 } SVGA3dCmdBlitSurfaceToScreen;         /* SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN */
 
+typedef
+struct {
+   uint32               sid;
+   SVGA3dTextureFilter  filter;
+} SVGA3dCmdGenerateMipmaps;             /* SVGA_3D_CMD_GENERATE_MIPMAPS */
+
 
 /*
  * Capability query index.
@@ -1774,6 +1851,32 @@
    SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16           = 67,
    SVGA3D_DEVCAP_SURFACEFMT_UYVY                   = 68,
    SVGA3D_DEVCAP_SURFACEFMT_YUY2                   = 69,
+   SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES    = 70,
+   SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES       = 71,
+   SVGA3D_DEVCAP_ALPHATOCOVERAGE                   = 72,
+   SVGA3D_DEVCAP_SUPERSAMPLE                       = 73,
+   SVGA3D_DEVCAP_AUTOGENMIPMAPS                    = 74,
+   SVGA3D_DEVCAP_SURFACEFMT_NV12                   = 75,
+   SVGA3D_DEVCAP_SURFACEFMT_AYUV                   = 76,
+
+   /*
+    * This is the maximum number of SVGA context IDs that the guest
+    * can define using SVGA_3D_CMD_CONTEXT_DEFINE.
+    */
+   SVGA3D_DEVCAP_MAX_CONTEXT_IDS                   = 77,
+
+   /*
+    * This is the maximum number of SVGA surface IDs that the guest
+    * can define using SVGA_3D_CMD_SURFACE_DEFINE*.
+    */
+   SVGA3D_DEVCAP_MAX_SURFACE_IDS                   = 78,
+
+   SVGA3D_DEVCAP_SURFACEFMT_Z_DF16                 = 79,
+   SVGA3D_DEVCAP_SURFACEFMT_Z_DF24                 = 80,
+   SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT            = 81,
+
+   SVGA3D_DEVCAP_SURFACEFMT_BC4_UNORM              = 82,
+   SVGA3D_DEVCAP_SURFACEFMT_BC5_UNORM              = 83,
 
    /*
     * Don't add new caps into the previous section; the values in this
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/svga_escape.h linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/svga_escape.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/svga_escape.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/svga_escape.h	2012-01-04 18:55:44.000000000 -0500
@@ -75,7 +75,7 @@
  */
 
 #define SVGA_ESCAPE_VMWARE_HINT               0x00030000
-#define SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN    0x00030001  // Deprecated
+#define SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN    0x00030001  /* Deprecated */
 
 typedef
 struct {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/svga_overlay.h linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/svga_overlay.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/svga_overlay.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/svga_overlay.h	2012-01-04 18:55:44.000000000 -0500
@@ -38,9 +38,9 @@
  * Video formats we support
  */
 
-#define VMWARE_FOURCC_YV12 0x32315659 // 'Y' 'V' '1' '2'
-#define VMWARE_FOURCC_YUY2 0x32595559 // 'Y' 'U' 'Y' '2'
-#define VMWARE_FOURCC_UYVY 0x59565955 // 'U' 'Y' 'V' 'Y'
+#define VMWARE_FOURCC_YV12 0x32315659 /* 'Y' 'V' '1' '2' */
+#define VMWARE_FOURCC_YUY2 0x32595559 /* 'Y' 'U' 'Y' '2' */
+#define VMWARE_FOURCC_UYVY 0x59565955 /* 'U' 'Y' 'V' 'Y' */
 
 typedef enum {
    SVGA_OVERLAY_FORMAT_INVALID = 0,
@@ -68,7 +68,7 @@
       uint32 streamId;
    } header;
 
-   // May include zero or more items.
+   /* May include zero or more items. */
    struct {
       uint32 registerId;
       uint32 value;
@@ -134,12 +134,12 @@
  */
 
 static inline bool
-VMwareVideoGetAttributes(const SVGAOverlayFormat format,    // IN
-                         uint32 *width,                     // IN / OUT
-                         uint32 *height,                    // IN / OUT
-                         uint32 *size,                      // OUT
-                         uint32 *pitches,                   // OUT (optional)
-                         uint32 *offsets)                   // OUT (optional)
+VMwareVideoGetAttributes(const SVGAOverlayFormat format,    /* IN */
+                         uint32 *width,                     /* IN / OUT */
+                         uint32 *height,                    /* IN / OUT */
+                         uint32 *size,                      /* OUT */
+                         uint32 *pitches,                   /* OUT (optional) */
+                         uint32 *offsets)                   /* OUT (optional) */
 {
     int tmp;
 
@@ -198,4 +198,4 @@
     return true;
 }
 
-#endif // _SVGA_OVERLAY_H_
+#endif /* _SVGA_OVERLAY_H_ */
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/svga_reg.h linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/svga_reg.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/svga_reg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/svga_reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,15 @@
 #define PCI_DEVICE_ID_VMWARE_SVGA2      0x0405
 
 /*
+ * SVGA_REG_ENABLE bit definitions.
+ */
+#define SVGA_REG_ENABLE_DISABLE     0
+#define SVGA_REG_ENABLE_ENABLE      1
+#define SVGA_REG_ENABLE_HIDE        2
+#define SVGA_REG_ENABLE_ENABLE_HIDE (SVGA_REG_ENABLE_ENABLE |\
+				     SVGA_REG_ENABLE_HIDE)
+
+/*
  * Legal values for the SVGA_REG_CURSOR_ON register in old-fashioned
  * cursor bypass mode. This is still supported, but no new guest
  * drivers should use it.
@@ -158,7 +167,9 @@
    SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH = 44,
 
    SVGA_REG_TRACES = 45,            /* Enable trace-based updates even when FIFO is on */
-   SVGA_REG_TOP = 46,               /* Must be 1 more than the last register */
+   SVGA_REG_GMRS_MAX_PAGES = 46,    /* Maximum number of 4KB pages for all GMRs */
+   SVGA_REG_MEMORY_SIZE = 47,       /* Total dedicated device memory excluding FIFO */
+   SVGA_REG_TOP = 48,               /* Must be 1 more than the last register */
 
    SVGA_PALETTE_BASE = 1024,        /* Base of SVGA color map */
    /* Next 768 (== 256*3) registers exist for colormap */
@@ -265,7 +276,7 @@
  * possible.
  */
 #define SVGA_GMR_NULL         ((uint32) -1)
-#define SVGA_GMR_FRAMEBUFFER  ((uint32) -2)  // Guest Framebuffer (GFB)
+#define SVGA_GMR_FRAMEBUFFER  ((uint32) -2)  /* Guest Framebuffer (GFB) */
 
 typedef
 struct SVGAGuestMemDescriptor {
@@ -306,13 +317,35 @@
       struct {
          uint32 bitsPerPixel : 8;
          uint32 colorDepth   : 8;
-         uint32 reserved     : 16;  // Must be zero
+         uint32 reserved     : 16;  /* Must be zero */
       };
 
       uint32 value;
    };
 } SVGAGMRImageFormat;
 
+typedef
+struct SVGAGuestImage {
+   SVGAGuestPtr         ptr;
+
+   /*
+    * A note on interpretation of pitch: This value of pitch is the
+    * number of bytes between vertically adjacent image
+    * blocks. Normally this is the number of bytes between the first
+    * pixel of two adjacent scanlines. With compressed textures,
+    * however, this may represent the number of bytes between
+    * compression blocks rather than between rows of pixels.
+    *
+    * XXX: Compressed textures currently must be tightly packed in guest memory.
+    *
+    * If the image is 1-dimensional, pitch is ignored.
+    *
+    * If 'pitch' is zero, the SVGA3D device calculates a pitch value
+    * assuming each row of blocks is tightly packed.
+    */
+   uint32 pitch;
+} SVGAGuestImage;
+
 /*
  * SVGAColorBGRX --
  *
@@ -328,7 +361,7 @@
          uint32 b : 8;
          uint32 g : 8;
          uint32 r : 8;
-         uint32 x : 8;  // Unused
+         uint32 x : 8;  /* Unused */
       };
 
       uint32 value;
@@ -370,23 +403,34 @@
  *  Note the holes in the bitfield. Missing bits have been deprecated,
  *  and must not be reused. Those capabilities will never be reported
  *  by new versions of the SVGA device.
+ *
+ * SVGA_CAP_GMR2 --
+ *    Provides asynchronous commands to define and remap guest memory
+ *    regions.  Adds device registers SVGA_REG_GMRS_MAX_PAGES and
+ *    SVGA_REG_MEMORY_SIZE.
+ *
+ * SVGA_CAP_SCREEN_OBJECT_2 --
+ *    Allow screen object support, and require backing stores from the
+ *    guest for each screen object.
  */
 
 #define SVGA_CAP_NONE               0x00000000
 #define SVGA_CAP_RECT_COPY          0x00000002
 #define SVGA_CAP_CURSOR             0x00000020
-#define SVGA_CAP_CURSOR_BYPASS      0x00000040   // Legacy (Use Cursor Bypass 3 instead)
-#define SVGA_CAP_CURSOR_BYPASS_2    0x00000080   // Legacy (Use Cursor Bypass 3 instead)
+#define SVGA_CAP_CURSOR_BYPASS      0x00000040   /* Legacy (Use Cursor Bypass 3 instead) */
+#define SVGA_CAP_CURSOR_BYPASS_2    0x00000080   /* Legacy (Use Cursor Bypass 3 instead) */
 #define SVGA_CAP_8BIT_EMULATION     0x00000100
 #define SVGA_CAP_ALPHA_CURSOR       0x00000200
 #define SVGA_CAP_3D                 0x00004000
 #define SVGA_CAP_EXTENDED_FIFO      0x00008000
-#define SVGA_CAP_MULTIMON           0x00010000   // Legacy multi-monitor support
+#define SVGA_CAP_MULTIMON           0x00010000   /* Legacy multi-monitor support */
 #define SVGA_CAP_PITCHLOCK          0x00020000
 #define SVGA_CAP_IRQMASK            0x00040000
-#define SVGA_CAP_DISPLAY_TOPOLOGY   0x00080000   // Legacy multi-monitor support
+#define SVGA_CAP_DISPLAY_TOPOLOGY   0x00080000   /* Legacy multi-monitor support */
 #define SVGA_CAP_GMR                0x00100000
 #define SVGA_CAP_TRACES             0x00200000
+#define SVGA_CAP_GMR2               0x00400000
+#define SVGA_CAP_SCREEN_OBJECT_2    0x00800000
 
 
 /*
@@ -431,7 +475,7 @@
 
    SVGA_FIFO_CAPABILITIES = 4,
    SVGA_FIFO_FLAGS,
-   // Valid with SVGA_FIFO_CAP_FENCE:
+   /* Valid with SVGA_FIFO_CAP_FENCE: */
    SVGA_FIFO_FENCE,
 
    /*
@@ -444,33 +488,47 @@
     * extended FIFO.
     */
 
-   // Valid if exists (i.e. if extended FIFO enabled):
+   /* Valid if exists (i.e. if extended FIFO enabled): */
    SVGA_FIFO_3D_HWVERSION,       /* See SVGA3dHardwareVersion in svga3d_reg.h */
-   // Valid with SVGA_FIFO_CAP_PITCHLOCK:
+   /* Valid with SVGA_FIFO_CAP_PITCHLOCK: */
    SVGA_FIFO_PITCHLOCK,
 
-   // Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3:
+   /* Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3: */
    SVGA_FIFO_CURSOR_ON,          /* Cursor bypass 3 show/hide register */
    SVGA_FIFO_CURSOR_X,           /* Cursor bypass 3 x register */
    SVGA_FIFO_CURSOR_Y,           /* Cursor bypass 3 y register */
    SVGA_FIFO_CURSOR_COUNT,       /* Incremented when any of the other 3 change */
    SVGA_FIFO_CURSOR_LAST_UPDATED,/* Last time the host updated the cursor */
 
-   // Valid with SVGA_FIFO_CAP_RESERVE:
+   /* Valid with SVGA_FIFO_CAP_RESERVE: */
    SVGA_FIFO_RESERVED,           /* Bytes past NEXT_CMD with real contents */
 
    /*
-    * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT:
+    * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2:
     *
     * By default this is SVGA_ID_INVALID, to indicate that the cursor
     * coordinates are specified relative to the virtual root. If this
     * is set to a specific screen ID, cursor position is reinterpreted
-    * as a signed offset relative to that screen's origin. This is the
-    * only way to place the cursor on a non-rooted screen.
+    * as a signed offset relative to that screen's origin.
     */
    SVGA_FIFO_CURSOR_SCREEN_ID,
 
    /*
+    * Valid with SVGA_FIFO_CAP_DEAD
+    *
+    * An arbitrary value written by the host, drivers should not use it.
+    */
+   SVGA_FIFO_DEAD,
+
+   /*
+    * Valid with SVGA_FIFO_CAP_3D_HWVERSION_REVISED:
+    *
+    * Contains 3D HWVERSION (see SVGA3dHardwareVersion in svga3d_reg.h)
+    * on platforms that can enforce graphics resource limits.
+    */
+   SVGA_FIFO_3D_HWVERSION_REVISED,
+
+   /*
     * XXX: The gap here, up until SVGA_FIFO_3D_CAPS, can be used for new
     * registers, but this must be done carefully and with judicious use of
     * capability bits, since comparisons based on SVGA_FIFO_MIN aren't
@@ -508,7 +566,7 @@
     * sets SVGA_FIFO_MIN high enough to leave room for them.
     */
 
-   // Valid if register exists:
+   /* Valid if register exists: */
    SVGA_FIFO_GUEST_3D_HWVERSION, /* Guest driver's 3D version */
    SVGA_FIFO_FENCE_GOAL,         /* Matching target for SVGA_IRQFLAG_FENCE_GOAL */
    SVGA_FIFO_BUSY,               /* See "FIFO Synchronization Registers" */
@@ -709,6 +767,37 @@
  *
  *       - When a screen is resized, either using Screen Object commands or
  *         legacy multimon registers, its contents are preserved.
+ *
+ * SVGA_FIFO_CAP_GMR2 --
+ *
+ *    Provides new commands to define and remap guest memory regions (GMR).
+ *
+ *    New 2D commands:
+ *       DEFINE_GMR2, REMAP_GMR2.
+ *
+ * SVGA_FIFO_CAP_3D_HWVERSION_REVISED --
+ *
+ *    Indicates new register SVGA_FIFO_3D_HWVERSION_REVISED exists.
+ *    This register may replace SVGA_FIFO_3D_HWVERSION on platforms
+ *    that enforce graphics resource limits.  This allows the platform
+ *    to clear SVGA_FIFO_3D_HWVERSION and disable 3D in legacy guest
+ *    drivers that do not limit their resources.
+ *
+ *    Note this is an alias to SVGA_FIFO_CAP_GMR2 because these indicators
+ *    are codependent (and thus we use a single capability bit).
+ *
+ * SVGA_FIFO_CAP_SCREEN_OBJECT_2 --
+ *
+ *    Modifies the DEFINE_SCREEN command to include a guest provided
+ *    backing store in GMR memory and the bytesPerLine for the backing
+ *    store.  This capability requires the use of a backing store when
+ *    creating screen objects.  However if SVGA_FIFO_CAP_SCREEN_OBJECT
+ *    is present then backing stores are optional.
+ *
+ * SVGA_FIFO_CAP_DEAD --
+ *
+ *    Drivers should not use this cap bit.  This cap bit can not be
+ *    reused since some hosts already expose it.
  */
 
 #define SVGA_FIFO_CAP_NONE                  0
@@ -720,6 +809,10 @@
 #define SVGA_FIFO_CAP_ESCAPE            (1<<5)
 #define SVGA_FIFO_CAP_RESERVE           (1<<6)
 #define SVGA_FIFO_CAP_SCREEN_OBJECT     (1<<7)
+#define SVGA_FIFO_CAP_GMR2              (1<<8)
+#define SVGA_FIFO_CAP_3D_HWVERSION_REVISED  SVGA_FIFO_CAP_GMR2
+#define SVGA_FIFO_CAP_SCREEN_OBJECT_2   (1<<9)
+#define SVGA_FIFO_CAP_DEAD              (1<<10)
 
 
 /*
@@ -730,7 +823,7 @@
 
 #define SVGA_FIFO_FLAG_NONE                 0
 #define SVGA_FIFO_FLAG_ACCELFRONT       (1<<0)
-#define SVGA_FIFO_FLAG_RESERVED        (1<<31) // Internal use only
+#define SVGA_FIFO_FLAG_RESERVED        (1<<31) /* Internal use only */
 
 /*
  * FIFO reservation sentinel value
@@ -763,22 +856,22 @@
    SVGA_VIDEO_DATA_OFFSET,
    SVGA_VIDEO_FORMAT,
    SVGA_VIDEO_COLORKEY,
-   SVGA_VIDEO_SIZE,          // Deprecated
+   SVGA_VIDEO_SIZE,          /* Deprecated */
    SVGA_VIDEO_WIDTH,
    SVGA_VIDEO_HEIGHT,
    SVGA_VIDEO_SRC_X,
    SVGA_VIDEO_SRC_Y,
    SVGA_VIDEO_SRC_WIDTH,
    SVGA_VIDEO_SRC_HEIGHT,
-   SVGA_VIDEO_DST_X,         // Signed int32
-   SVGA_VIDEO_DST_Y,         // Signed int32
+   SVGA_VIDEO_DST_X,         /* Signed int32 */
+   SVGA_VIDEO_DST_Y,         /* Signed int32 */
    SVGA_VIDEO_DST_WIDTH,
    SVGA_VIDEO_DST_HEIGHT,
    SVGA_VIDEO_PITCH_1,
    SVGA_VIDEO_PITCH_2,
    SVGA_VIDEO_PITCH_3,
-   SVGA_VIDEO_DATA_GMRID,    // Optional, defaults to SVGA_GMR_FRAMEBUFFER
-   SVGA_VIDEO_DST_SCREEN_ID, // Optional, defaults to virtual coords (SVGA_ID_INVALID)
+   SVGA_VIDEO_DATA_GMRID,    /* Optional, defaults to SVGA_GMR_FRAMEBUFFER */
+   SVGA_VIDEO_DST_SCREEN_ID, /* Optional, defaults to virtual coords (SVGA_ID_INVALID) */
    SVGA_VIDEO_NUM_REGS
 };
 
@@ -829,15 +922,51 @@
  *    compatibility. New flags can be added, and the struct may grow,
  *    but existing fields must retain their meaning.
  *
+ *    Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2 are required fields of
+ *    a SVGAGuestPtr that is used to back the screen contents.  This
+ *    memory must come from the GFB.  The guest is not allowed to
+ *    access the memory and doing so will have undefined results.  The
+ *    backing store is required to be page aligned and the size is
+ *    padded to the next page boundry.  The number of pages is:
+ *       (bytesPerLine * size.width * 4 + PAGE_SIZE - 1) / PAGE_SIZE
+ *
+ *    The pitch in the backingStore is required to be at least large
+ *    enough to hold a 32bbp scanline.  It is recommended that the
+ *    driver pad bytesPerLine for a potential performance win.
+ *
+ *    The cloneCount field is treated as a hint from the guest that
+ *    the user wants this display to be cloned, countCount times.  A
+ *    value of zero means no cloning should happen.
  */
 
-#define SVGA_SCREEN_HAS_ROOT    (1 << 0)  // Screen is present in the virtual coord space
-#define SVGA_SCREEN_IS_PRIMARY  (1 << 1)  // Guest considers this screen to be 'primary'
-#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2)   // Guest is running a fullscreen app here
+#define SVGA_SCREEN_MUST_BE_SET     (1 << 0) /* Must be set or results undefined */
+#define SVGA_SCREEN_HAS_ROOT SVGA_SCREEN_MUST_BE_SET /* Deprecated */
+#define SVGA_SCREEN_IS_PRIMARY      (1 << 1) /* Guest considers this screen to be 'primary' */
+#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2) /* Guest is running a fullscreen app here */
+
+/*
+ * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2.  When the screen is
+ * deactivated the base layer is defined to lose all contents and
+ * become black.  When a screen is deactivated the backing store is
+ * optional.  When set backingPtr and bytesPerLine will be ignored.
+ */
+#define SVGA_SCREEN_DEACTIVATE  (1 << 3)
+
+/*
+ * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2.  When this flag is set
+ * the screen contents will be outputted as all black to the user
+ * though the base layer contents is preserved.  The screen base layer
+ * can still be read and written to like normal though the no visible
+ * effect will be seen by the user.  When the flag is changed the
+ * screen will be blanked or redrawn to the current contents as needed
+ * without any extra commands from the driver.  This flag only has an
+ * effect when the screen is not deactivated.
+ */
+#define SVGA_SCREEN_BLANKING (1 << 4)
 
 typedef
 struct SVGAScreenObject {
-   uint32 structSize;   // sizeof(SVGAScreenObject)
+   uint32 structSize;   /* sizeof(SVGAScreenObject) */
    uint32 id;
    uint32 flags;
    struct {
@@ -847,7 +976,14 @@
    struct {
       int32 x;
       int32 y;
-   } root;              // Only used if SVGA_SCREEN_HAS_ROOT is set.
+   } root;
+
+   /*
+    * Added and required by SVGA_FIFO_CAP_SCREEN_OBJECT_2, optional
+    * with SVGA_FIFO_CAP_SCREEN_OBJECT.
+    */
+   SVGAGuestImage backingStore;
+   uint32 cloneCount;
 } SVGAScreenObject;
 
 
@@ -885,6 +1021,8 @@
    SVGA_CMD_BLIT_SCREEN_TO_GMRFB  = 38,
    SVGA_CMD_ANNOTATION_FILL       = 39,
    SVGA_CMD_ANNOTATION_COPY       = 40,
+   SVGA_CMD_DEFINE_GMR2           = 41,
+   SVGA_CMD_REMAP_GMR2            = 42,
    SVGA_CMD_MAX
 } SVGAFifoCmdId;
 
@@ -920,7 +1058,7 @@
  */
 
 typedef
-struct {
+struct SVGAFifoCmdUpdate {
    uint32 x;
    uint32 y;
    uint32 width;
@@ -939,7 +1077,7 @@
  */
 
 typedef
-struct {
+struct SVGAFifoCmdRectCopy {
    uint32 srcX;
    uint32 srcY;
    uint32 destX;
@@ -963,14 +1101,14 @@
  */
 
 typedef
-struct {
-   uint32 id;             // Reserved, must be zero.
+struct SVGAFifoCmdDefineCursor {
+   uint32 id;             /* Reserved, must be zero. */
    uint32 hotspotX;
    uint32 hotspotY;
    uint32 width;
    uint32 height;
-   uint32 andMaskDepth;   // Value must be 1 or equal to BITS_PER_PIXEL
-   uint32 xorMaskDepth;   // Value must be 1 or equal to BITS_PER_PIXEL
+   uint32 andMaskDepth;   /* Value must be 1 or equal to BITS_PER_PIXEL */
+   uint32 xorMaskDepth;   /* Value must be 1 or equal to BITS_PER_PIXEL */
    /*
     * Followed by scanline data for AND mask, then XOR mask.
     * Each scanline is padded to a 32-bit boundary.
@@ -992,8 +1130,8 @@
  */
 
 typedef
-struct {
-   uint32 id;             // Reserved, must be zero.
+struct SVGAFifoCmdDefineAlphaCursor {
+   uint32 id;             /* Reserved, must be zero. */
    uint32 hotspotX;
    uint32 hotspotY;
    uint32 width;
@@ -1015,7 +1153,7 @@
  */
 
 typedef
-struct {
+struct SVGAFifoCmdUpdateVerbose {
    uint32 x;
    uint32 y;
    uint32 width;
@@ -1040,13 +1178,13 @@
 #define  SVGA_ROP_COPY                    0x03
 
 typedef
-struct {
-   uint32 color;     // In the same format as the GFB
+struct SVGAFifoCmdFrontRopFill {
+   uint32 color;     /* In the same format as the GFB */
    uint32 x;
    uint32 y;
    uint32 width;
    uint32 height;
-   uint32 rop;       // Must be SVGA_ROP_COPY
+   uint32 rop;       /* Must be SVGA_ROP_COPY */
 } SVGAFifoCmdFrontRopFill;
 
 
@@ -1083,7 +1221,7 @@
  */
 
 typedef
-struct {
+struct SVGAFifoCmdEscape {
    uint32 nsid;
    uint32 size;
    /* followed by 'size' bytes of data */
@@ -1113,12 +1251,12 @@
  *    registers (SVGA_REG_NUM_GUEST_DISPLAYS, SVGA_REG_DISPLAY_*).
  *
  * Availability:
- *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
  */
 
 typedef
 struct {
-   SVGAScreenObject screen;   // Variable-length according to version
+   SVGAScreenObject screen;   /* Variable-length according to version */
 } SVGAFifoCmdDefineScreen;
 
 
@@ -1129,7 +1267,7 @@
  *    re-use.
  *
  * Availability:
- *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
  */
 
 typedef
@@ -1182,7 +1320,7 @@
  *    GMRFB.
  *
  * Availability:
- *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
  */
 
 typedef
@@ -1219,7 +1357,7 @@
  *    SVGA_CMD_ANNOTATION_* commands for details.
  *
  * Availability:
- *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
  */
 
 typedef
@@ -1267,7 +1405,7 @@
  *    the time any subsequent FENCE commands are reached.
  *
  * Availability:
- *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
  */
 
 typedef
@@ -1302,7 +1440,7 @@
  *    user's display is being remoted over a network connection.
  *
  * Availability:
- *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
  */
 
 typedef
@@ -1334,7 +1472,7 @@
  *    undefined.
  *
  * Availability:
- *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
  */
 
 typedef
@@ -1343,4 +1481,72 @@
    uint32           srcScreenId;
 } SVGAFifoCmdAnnotationCopy;
 
+
+/*
+ * SVGA_CMD_DEFINE_GMR2 --
+ *
+ *    Define guest memory region v2.  See the description of GMRs above.
+ *
+ * Availability:
+ *    SVGA_CAP_GMR2
+ */
+
+typedef
+struct {
+   uint32 gmrId;
+   uint32 numPages;
+} SVGAFifoCmdDefineGMR2;
+
+
+/*
+ * SVGA_CMD_REMAP_GMR2 --
+ *
+ *    Remap guest memory region v2.  See the description of GMRs above.
+ *
+ *    This command allows guest to modify a portion of an existing GMR by
+ *    invalidating it or reassigning it to different guest physical pages.
+ *    The pages are identified by physical page number (PPN).  The pages
+ *    are assumed to be pinned and valid for DMA operations.
+ *
+ *    Description of command flags:
+ *
+ *    SVGA_REMAP_GMR2_VIA_GMR: If enabled, references a PPN list in a GMR.
+ *       The PPN list must not overlap with the remap region (this can be
+ *       handled trivially by referencing a separate GMR).  If flag is
+ *       disabled, PPN list is appended to SVGARemapGMR command.
+ *
+ *    SVGA_REMAP_GMR2_PPN64: If set, PPN list is in PPN64 format, otherwise
+ *       it is in PPN32 format.
+ *
+ *    SVGA_REMAP_GMR2_SINGLE_PPN: If set, PPN list contains a single entry.
+ *       A single PPN can be used to invalidate a portion of a GMR or
+ *       map it to to a single guest scratch page.
+ *
+ * Availability:
+ *    SVGA_CAP_GMR2
+ */
+
+typedef enum {
+   SVGA_REMAP_GMR2_PPN32         = 0,
+   SVGA_REMAP_GMR2_VIA_GMR       = (1 << 0),
+   SVGA_REMAP_GMR2_PPN64         = (1 << 1),
+   SVGA_REMAP_GMR2_SINGLE_PPN    = (1 << 2),
+} SVGARemapGMR2Flags;
+
+typedef
+struct {
+   uint32 gmrId;
+   SVGARemapGMR2Flags flags;
+   uint32 offsetPages; /* offset in pages to begin remap */
+   uint32 numPages; /* number of pages to remap */
+   /*
+    * Followed by additional data depending on SVGARemapGMR2Flags.
+    *
+    * If flag SVGA_REMAP_GMR2_VIA_GMR is set, single SVGAGuestPtr follows.
+    * Otherwise an array of page descriptors in PPN32 or PPN64 format
+    * (according to flag SVGA_REMAP_GMR2_PPN64) follows.  If flag
+    * SVGA_REMAP_GMR2_SINGLE_PPN is set, array contains a single entry.
+    */
+} SVGAFifoCmdRemapGMR2;
+
 #endif
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,10 @@
 static uint32_t gmr_placement_flags = VMW_PL_FLAG_GMR |
 	TTM_PL_FLAG_CACHED;
 
+static uint32_t gmr_ne_placement_flags = VMW_PL_FLAG_GMR |
+	TTM_PL_FLAG_CACHED |
+	TTM_PL_FLAG_NO_EVICT;
+
 struct ttm_placement vmw_vram_placement = {
 	.fpfn = 0,
 	.lpfn = 0,
@@ -56,6 +60,11 @@
 	VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED
 };
 
+static uint32_t gmr_vram_placement_flags[] = {
+	VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED,
+	TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED
+};
+
 struct ttm_placement vmw_vram_gmr_placement = {
 	.fpfn = 0,
 	.lpfn = 0,
@@ -65,6 +74,20 @@
 	.busy_placement = &gmr_placement_flags
 };
 
+static uint32_t vram_gmr_ne_placement_flags[] = {
+	TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT,
+	VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT
+};
+
+struct ttm_placement vmw_vram_gmr_ne_placement = {
+	.fpfn = 0,
+	.lpfn = 0,
+	.num_placement = 2,
+	.placement = vram_gmr_ne_placement_flags,
+	.num_busy_placement = 1,
+	.busy_placement = &gmr_ne_placement_flags
+};
+
 struct ttm_placement vmw_vram_sys_placement = {
 	.fpfn = 0,
 	.lpfn = 0,
@@ -92,6 +115,30 @@
 	.busy_placement = &sys_placement_flags
 };
 
+static uint32_t evictable_placement_flags[] = {
+	TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED,
+	TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED,
+	VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED
+};
+
+struct ttm_placement vmw_evictable_placement = {
+	.fpfn = 0,
+	.lpfn = 0,
+	.num_placement = 3,
+	.placement = evictable_placement_flags,
+	.num_busy_placement = 1,
+	.busy_placement = &sys_placement_flags
+};
+
+struct ttm_placement vmw_srf_placement = {
+	.fpfn = 0,
+	.lpfn = 0,
+	.num_placement = 1,
+	.num_busy_placement = 2,
+	.placement = &gmr_placement_flags,
+	.busy_placement = gmr_vram_placement_flags
+};
+
 struct vmw_ttm_backend {
 	struct ttm_backend backend;
 	struct page **pages;
@@ -274,39 +321,39 @@
 
 static void *vmw_sync_obj_ref(void *sync_obj)
 {
-	return sync_obj;
+
+	return (void *)
+		vmw_fence_obj_reference((struct vmw_fence_obj *) sync_obj);
 }
 
 static void vmw_sync_obj_unref(void **sync_obj)
 {
-	*sync_obj = NULL;
+	vmw_fence_obj_unreference((struct vmw_fence_obj **) sync_obj);
 }
 
 static int vmw_sync_obj_flush(void *sync_obj, void *sync_arg)
 {
-	struct vmw_private *dev_priv = (struct vmw_private *)sync_arg;
-
-	mutex_lock(&dev_priv->hw_mutex);
-	vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
-	mutex_unlock(&dev_priv->hw_mutex);
+	vmw_fence_obj_flush((struct vmw_fence_obj *) sync_obj);
 	return 0;
 }
 
 static bool vmw_sync_obj_signaled(void *sync_obj, void *sync_arg)
 {
-	struct vmw_private *dev_priv = (struct vmw_private *)sync_arg;
-	uint32_t sequence = (unsigned long) sync_obj;
+	unsigned long flags = (unsigned long) sync_arg;
+	return	vmw_fence_obj_signaled((struct vmw_fence_obj *) sync_obj,
+				       (uint32_t) flags);
 
-	return vmw_fence_signaled(dev_priv, sequence);
 }
 
 static int vmw_sync_obj_wait(void *sync_obj, void *sync_arg,
 			     bool lazy, bool interruptible)
 {
-	struct vmw_private *dev_priv = (struct vmw_private *)sync_arg;
-	uint32_t sequence = (unsigned long) sync_obj;
+	unsigned long flags = (unsigned long) sync_arg;
 
-	return vmw_wait_fence(dev_priv, false, sequence, false, 3*HZ);
+	return vmw_fence_obj_wait((struct vmw_fence_obj *) sync_obj,
+				  (uint32_t) flags,
+				  lazy, interruptible,
+				  VMW_FENCE_WAIT_TIMEOUT);
 }
 
 struct ttm_bo_driver vmw_bo_driver = {
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,322 @@
+/**************************************************************************
+ *
+ * Copyright Â© 2011 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "ttm/ttm_placement.h"
+
+#include "drmP.h"
+#include "vmwgfx_drv.h"
+
+
+/**
+ * vmw_dmabuf_to_placement - Validate a buffer to placement.
+ *
+ * @dev_priv:  Driver private.
+ * @buf:  DMA buffer to move.
+ * @pin:  Pin buffer if true.
+ * @interruptible:  Use interruptible wait.
+ *
+ * May only be called by the current master since it assumes that the
+ * master lock is the current master's lock.
+ * This function takes the master's lock in write mode.
+ * Flushes and unpins the query bo to avoid failures.
+ *
+ * Returns
+ *  -ERESTARTSYS if interrupted by a signal.
+ */
+int vmw_dmabuf_to_placement(struct vmw_private *dev_priv,
+			    struct vmw_dma_buffer *buf,
+			    struct ttm_placement *placement,
+			    bool interruptible)
+{
+	struct vmw_master *vmaster = dev_priv->active_master;
+	struct ttm_buffer_object *bo = &buf->base;
+	int ret;
+
+	ret = ttm_write_lock(&vmaster->lock, interruptible);
+	if (unlikely(ret != 0))
+		return ret;
+
+	vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
+
+	ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+	if (unlikely(ret != 0))
+		goto err;
+
+	ret = ttm_bo_validate(bo, placement, interruptible, false, false);
+
+	ttm_bo_unreserve(bo);
+
+err:
+	ttm_write_unlock(&vmaster->lock);
+	return ret;
+}
+
+/**
+ * vmw_dmabuf_to_vram_or_gmr - Move a buffer to vram or gmr.
+ *
+ * May only be called by the current master since it assumes that the
+ * master lock is the current master's lock.
+ * This function takes the master's lock in write mode.
+ * Flushes and unpins the query bo if @pin == true to avoid failures.
+ *
+ * @dev_priv:  Driver private.
+ * @buf:  DMA buffer to move.
+ * @pin:  Pin buffer if true.
+ * @interruptible:  Use interruptible wait.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv,
+			      struct vmw_dma_buffer *buf,
+			      bool pin, bool interruptible)
+{
+	struct vmw_master *vmaster = dev_priv->active_master;
+	struct ttm_buffer_object *bo = &buf->base;
+	struct ttm_placement *placement;
+	int ret;
+
+	ret = ttm_write_lock(&vmaster->lock, interruptible);
+	if (unlikely(ret != 0))
+		return ret;
+
+	if (pin)
+		vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
+
+	ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+	if (unlikely(ret != 0))
+		goto err;
+
+	/**
+	 * Put BO in VRAM if there is space, otherwise as a GMR.
+	 * If there is no space in VRAM and GMR ids are all used up,
+	 * start evicting GMRs to make room. If the DMA buffer can't be
+	 * used as a GMR, this will return -ENOMEM.
+	 */
+
+	if (pin)
+		placement = &vmw_vram_gmr_ne_placement;
+	else
+		placement = &vmw_vram_gmr_placement;
+
+	ret = ttm_bo_validate(bo, placement, interruptible, false, false);
+	if (likely(ret == 0) || ret == -ERESTARTSYS)
+		goto err_unreserve;
+
+
+	/**
+	 * If that failed, try VRAM again, this time evicting
+	 * previous contents.
+	 */
+
+	if (pin)
+		placement = &vmw_vram_ne_placement;
+	else
+		placement = &vmw_vram_placement;
+
+	ret = ttm_bo_validate(bo, placement, interruptible, false, false);
+
+err_unreserve:
+	ttm_bo_unreserve(bo);
+err:
+	ttm_write_unlock(&vmaster->lock);
+	return ret;
+}
+
+/**
+ * vmw_dmabuf_to_vram - Move a buffer to vram.
+ *
+ * May only be called by the current master since it assumes that the
+ * master lock is the current master's lock.
+ * This function takes the master's lock in write mode.
+ *
+ * @dev_priv:  Driver private.
+ * @buf:  DMA buffer to move.
+ * @pin:  Pin buffer in vram if true.
+ * @interruptible:  Use interruptible wait.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+int vmw_dmabuf_to_vram(struct vmw_private *dev_priv,
+		       struct vmw_dma_buffer *buf,
+		       bool pin, bool interruptible)
+{
+	struct ttm_placement *placement;
+
+	if (pin)
+		placement = &vmw_vram_ne_placement;
+	else
+		placement = &vmw_vram_placement;
+
+	return vmw_dmabuf_to_placement(dev_priv, buf,
+				       placement,
+				       interruptible);
+}
+
+/**
+ * vmw_dmabuf_to_start_of_vram - Move a buffer to start of vram.
+ *
+ * May only be called by the current master since it assumes that the
+ * master lock is the current master's lock.
+ * This function takes the master's lock in write mode.
+ * Flushes and unpins the query bo if @pin == true to avoid failures.
+ *
+ * @dev_priv:  Driver private.
+ * @buf:  DMA buffer to move.
+ * @pin:  Pin buffer in vram if true.
+ * @interruptible:  Use interruptible wait.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+int vmw_dmabuf_to_start_of_vram(struct vmw_private *dev_priv,
+				struct vmw_dma_buffer *buf,
+				bool pin, bool interruptible)
+{
+	struct vmw_master *vmaster = dev_priv->active_master;
+	struct ttm_buffer_object *bo = &buf->base;
+	struct ttm_placement placement;
+	int ret = 0;
+
+	if (pin)
+		placement = vmw_vram_ne_placement;
+	else
+		placement = vmw_vram_placement;
+	placement.lpfn = bo->num_pages;
+
+	ret = ttm_write_lock(&vmaster->lock, interruptible);
+	if (unlikely(ret != 0))
+		return ret;
+
+	if (pin)
+		vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
+
+	ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+	if (unlikely(ret != 0))
+		goto err_unlock;
+
+	/* Is this buffer already in vram but not at the start of it? */
+	if (bo->mem.mem_type == TTM_PL_VRAM &&
+	    bo->mem.start < bo->num_pages &&
+	    bo->mem.start > 0)
+		(void) ttm_bo_validate(bo, &vmw_sys_placement, false,
+				       false, false);
+
+	ret = ttm_bo_validate(bo, &placement, interruptible, false, false);
+
+	/* For some reason we didn't up at the start of vram */
+	WARN_ON(ret == 0 && bo->offset != 0);
+
+	ttm_bo_unreserve(bo);
+err_unlock:
+	ttm_write_unlock(&vmaster->lock);
+
+	return ret;
+}
+
+
+/**
+ * vmw_dmabuf_upin - Unpin the buffer given buffer, does not move the buffer.
+ *
+ * May only be called by the current master since it assumes that the
+ * master lock is the current master's lock.
+ * This function takes the master's lock in write mode.
+ *
+ * @dev_priv:  Driver private.
+ * @buf:  DMA buffer to unpin.
+ * @interruptible:  Use interruptible wait.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+int vmw_dmabuf_unpin(struct vmw_private *dev_priv,
+		     struct vmw_dma_buffer *buf,
+		     bool interruptible)
+{
+	/*
+	 * We could in theory early out if the buffer is
+	 * unpinned but we need to lock and reserve the buffer
+	 * anyways so we don't gain much by that.
+	 */
+	return vmw_dmabuf_to_placement(dev_priv, buf,
+				       &vmw_evictable_placement,
+				       interruptible);
+}
+
+
+/**
+ * vmw_bo_get_guest_ptr - Get the guest ptr representing the current placement
+ * of a buffer.
+ *
+ * @bo: Pointer to a struct ttm_buffer_object. Must be pinned or reserved.
+ * @ptr: SVGAGuestPtr returning the result.
+ */
+void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *bo,
+			  SVGAGuestPtr *ptr)
+{
+	if (bo->mem.mem_type == TTM_PL_VRAM) {
+		ptr->gmrId = SVGA_GMR_FRAMEBUFFER;
+		ptr->offset = bo->offset;
+	} else {
+		ptr->gmrId = bo->mem.start;
+		ptr->offset = 0;
+	}
+}
+
+
+/**
+ * vmw_bo_pin - Pin or unpin a buffer object without moving it.
+ *
+ * @bo: The buffer object. Must be reserved, and present either in VRAM
+ * or GMR memory.
+ * @pin: Whether to pin or unpin.
+ *
+ */
+void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin)
+{
+	uint32_t pl_flags;
+	struct ttm_placement placement;
+	uint32_t old_mem_type = bo->mem.mem_type;
+	int ret;
+
+	BUG_ON(!atomic_read(&bo->reserved));
+	BUG_ON(old_mem_type != TTM_PL_VRAM &&
+	       old_mem_type != VMW_PL_FLAG_GMR);
+
+	pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED;
+	if (pin)
+		pl_flags |= TTM_PL_FLAG_NO_EVICT;
+
+	memset(&placement, 0, sizeof(placement));
+	placement.num_placement = 1;
+	placement.placement = &pl_flags;
+
+	ret = ttm_bo_validate(bo, &placement, false, true, true);
+
+	BUG_ON(ret != 0 || bo->mem.mem_type != old_mem_type);
+}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  **************************************************************************/
+#include <linux/module.h>
 
 #include "drmP.h"
 #include "vmwgfx_drv.h"
@@ -82,17 +83,31 @@
 #define DRM_IOCTL_VMW_EXECBUF					\
 	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_EXECBUF,		\
 		struct drm_vmw_execbuf_arg)
-#define DRM_IOCTL_VMW_FIFO_DEBUG				\
-	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FIFO_DEBUG,		\
-		 struct drm_vmw_fifo_debug_arg)
+#define DRM_IOCTL_VMW_GET_3D_CAP				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_GET_3D_CAP,		\
+		 struct drm_vmw_get_3d_cap_arg)
 #define DRM_IOCTL_VMW_FENCE_WAIT				\
 	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_WAIT,		\
 		 struct drm_vmw_fence_wait_arg)
+#define DRM_IOCTL_VMW_FENCE_SIGNALED				\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_SIGNALED,	\
+		 struct drm_vmw_fence_signaled_arg)
+#define DRM_IOCTL_VMW_FENCE_UNREF				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_FENCE_UNREF,		\
+		 struct drm_vmw_fence_arg)
+#define DRM_IOCTL_VMW_FENCE_EVENT				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_FENCE_EVENT,		\
+		 struct drm_vmw_fence_event_arg)
+#define DRM_IOCTL_VMW_PRESENT					\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT,		\
+		 struct drm_vmw_present_arg)
+#define DRM_IOCTL_VMW_PRESENT_READBACK				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT_READBACK,	\
+		 struct drm_vmw_present_readback_arg)
 #define DRM_IOCTL_VMW_UPDATE_LAYOUT				\
-	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT,	\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT,	\
 		 struct drm_vmw_update_layout_arg)
 
-
 /**
  * The core DRM version of this macro doesn't account for
  * DRM_COMMAND_BASE.
@@ -135,12 +150,28 @@
 		      DRM_AUTH | DRM_UNLOCKED),
 	VMW_IOCTL_DEF(VMW_EXECBUF, vmw_execbuf_ioctl,
 		      DRM_AUTH | DRM_UNLOCKED),
-	VMW_IOCTL_DEF(VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl,
-		      DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED),
-	VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_wait_ioctl,
+	VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl,
 		      DRM_AUTH | DRM_UNLOCKED),
-	VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT, vmw_kms_update_layout_ioctl,
-		      DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED)
+	VMW_IOCTL_DEF(VMW_FENCE_SIGNALED,
+		      vmw_fence_obj_signaled_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(VMW_FENCE_UNREF, vmw_fence_obj_unref_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(VMW_FENCE_EVENT,
+		      vmw_fence_event_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(VMW_GET_3D_CAP, vmw_get_cap_3d_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+
+	/* these allow direct access to the framebuffers mark as master only */
+	VMW_IOCTL_DEF(VMW_PRESENT, vmw_present_ioctl,
+		      DRM_MASTER | DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(VMW_PRESENT_READBACK,
+		      vmw_present_readback_ioctl,
+		      DRM_MASTER | DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
+		      vmw_kms_update_layout_ioctl,
+		      DRM_MASTER | DRM_UNLOCKED),
 };
 
 static struct pci_device_id vmw_pci_id_list[] = {
@@ -189,8 +220,78 @@
 		DRM_INFO("  GMR.\n");
 	if (capabilities & SVGA_CAP_TRACES)
 		DRM_INFO("  Traces.\n");
+	if (capabilities & SVGA_CAP_GMR2)
+		DRM_INFO("  GMR2.\n");
+	if (capabilities & SVGA_CAP_SCREEN_OBJECT_2)
+		DRM_INFO("  Screen Object 2.\n");
+}
+
+
+/**
+ * vmw_execbuf_prepare_dummy_query - Initialize a query result structure at
+ * the start of a buffer object.
+ *
+ * @dev_priv: The device private structure.
+ *
+ * This function will idle the buffer using an uninterruptible wait, then
+ * map the first page and initialize a pending occlusion query result structure,
+ * Finally it will unmap the buffer.
+ *
+ * TODO: Since we're only mapping a single page, we should optimize the map
+ * to use kmap_atomic / iomap_atomic.
+ */
+static void vmw_dummy_query_bo_prepare(struct vmw_private *dev_priv)
+{
+	struct ttm_bo_kmap_obj map;
+	volatile SVGA3dQueryResult *result;
+	bool dummy;
+	int ret;
+	struct ttm_bo_device *bdev = &dev_priv->bdev;
+	struct ttm_buffer_object *bo = dev_priv->dummy_query_bo;
+
+	ttm_bo_reserve(bo, false, false, false, 0);
+	spin_lock(&bdev->fence_lock);
+	ret = ttm_bo_wait(bo, false, false, false);
+	spin_unlock(&bdev->fence_lock);
+	if (unlikely(ret != 0))
+		(void) vmw_fallback_wait(dev_priv, false, true, 0, false,
+					 10*HZ);
+
+	ret = ttm_bo_kmap(bo, 0, 1, &map);
+	if (likely(ret == 0)) {
+		result = ttm_kmap_obj_virtual(&map, &dummy);
+		result->totalSize = sizeof(*result);
+		result->state = SVGA3D_QUERYSTATE_PENDING;
+		result->result32 = 0xff;
+		ttm_bo_kunmap(&map);
+	} else
+		DRM_ERROR("Dummy query buffer map failed.\n");
+	ttm_bo_unreserve(bo);
+}
+
+
+/**
+ * vmw_dummy_query_bo_create - create a bo to hold a dummy query result
+ *
+ * @dev_priv: A device private structure.
+ *
+ * This function creates a small buffer object that holds the query
+ * result for dummy queries emitted as query barriers.
+ * No interruptible waits are done within this function.
+ *
+ * Returns an error if bo creation fails.
+ */
+static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
+{
+	return ttm_bo_create(&dev_priv->bdev,
+			     PAGE_SIZE,
+			     ttm_bo_type_device,
+			     &vmw_vram_sys_placement,
+			     0, 0, false, NULL,
+			     &dev_priv->dummy_query_bo);
 }
 
+
 static int vmw_request_device(struct vmw_private *dev_priv)
 {
 	int ret;
@@ -200,16 +301,42 @@
 		DRM_ERROR("Unable to initialize FIFO.\n");
 		return ret;
 	}
+	vmw_fence_fifo_up(dev_priv->fman);
+	ret = vmw_dummy_query_bo_create(dev_priv);
+	if (unlikely(ret != 0))
+		goto out_no_query_bo;
+	vmw_dummy_query_bo_prepare(dev_priv);
 
 	return 0;
+
+out_no_query_bo:
+	vmw_fence_fifo_down(dev_priv->fman);
+	vmw_fifo_release(dev_priv, &dev_priv->fifo);
+	return ret;
 }
 
 static void vmw_release_device(struct vmw_private *dev_priv)
 {
+	/*
+	 * Previous destructions should've released
+	 * the pinned bo.
+	 */
+
+	BUG_ON(dev_priv->pinned_bo != NULL);
+
+	ttm_bo_unref(&dev_priv->dummy_query_bo);
+	vmw_fence_fifo_down(dev_priv->fman);
 	vmw_fifo_release(dev_priv, &dev_priv->fifo);
 }
 
-int vmw_3d_resource_inc(struct vmw_private *dev_priv)
+/**
+ * Increase the 3d resource refcount.
+ * If the count was prevously zero, initialize the fifo, switching to svga
+ * mode. Note that the master holds a ref as well, and may request an
+ * explicit switch to svga mode if fb is not running, using @unhide_svga.
+ */
+int vmw_3d_resource_inc(struct vmw_private *dev_priv,
+			bool unhide_svga)
 {
 	int ret = 0;
 
@@ -218,19 +345,42 @@
 		ret = vmw_request_device(dev_priv);
 		if (unlikely(ret != 0))
 			--dev_priv->num_3d_resources;
+	} else if (unhide_svga) {
+		mutex_lock(&dev_priv->hw_mutex);
+		vmw_write(dev_priv, SVGA_REG_ENABLE,
+			  vmw_read(dev_priv, SVGA_REG_ENABLE) &
+			  ~SVGA_REG_ENABLE_HIDE);
+		mutex_unlock(&dev_priv->hw_mutex);
 	}
+
 	mutex_unlock(&dev_priv->release_mutex);
 	return ret;
 }
 
-
-void vmw_3d_resource_dec(struct vmw_private *dev_priv)
+/**
+ * Decrease the 3d resource refcount.
+ * If the count reaches zero, disable the fifo, switching to vga mode.
+ * Note that the master holds a refcount as well, and may request an
+ * explicit switch to vga mode when it releases its refcount to account
+ * for the situation of an X server vt switch to VGA with 3d resources
+ * active.
+ */
+void vmw_3d_resource_dec(struct vmw_private *dev_priv,
+			 bool hide_svga)
 {
 	int32_t n3d;
 
 	mutex_lock(&dev_priv->release_mutex);
 	if (unlikely(--dev_priv->num_3d_resources == 0))
 		vmw_release_device(dev_priv);
+	else if (hide_svga) {
+		mutex_lock(&dev_priv->hw_mutex);
+		vmw_write(dev_priv, SVGA_REG_ENABLE,
+			  vmw_read(dev_priv, SVGA_REG_ENABLE) |
+			  SVGA_REG_ENABLE_HIDE);
+		mutex_unlock(&dev_priv->hw_mutex);
+	}
+
 	n3d = (int32_t) dev_priv->num_3d_resources;
 	mutex_unlock(&dev_priv->release_mutex);
 
@@ -252,7 +402,7 @@
 
 	dev_priv->dev = dev;
 	dev_priv->vmw_chipset = chipset;
-	dev_priv->last_read_sequence = (uint32_t) -100;
+	dev_priv->last_read_seqno = (uint32_t) -100;
 	mutex_init(&dev_priv->hw_mutex);
 	mutex_init(&dev_priv->cmdbuf_mutex);
 	mutex_init(&dev_priv->release_mutex);
@@ -263,8 +413,10 @@
 	mutex_init(&dev_priv->init_mutex);
 	init_waitqueue_head(&dev_priv->fence_queue);
 	init_waitqueue_head(&dev_priv->fifo_queue);
-	atomic_set(&dev_priv->fence_queue_waiters, 0);
+	dev_priv->fence_queue_waiters = 0;
 	atomic_set(&dev_priv->fifo_queue_waiters, 0);
+	INIT_LIST_HEAD(&dev_priv->surface_lru);
+	dev_priv->used_memory_size = 0;
 
 	dev_priv->io_start = pci_resource_start(dev->pdev, 0);
 	dev_priv->vram_start = pci_resource_start(dev->pdev, 1);
@@ -285,6 +437,10 @@
 
 	dev_priv->capabilities = vmw_read(dev_priv, SVGA_REG_CAPABILITIES);
 
+	dev_priv->vram_size = vmw_read(dev_priv, SVGA_REG_VRAM_SIZE);
+	dev_priv->mmio_size = vmw_read(dev_priv, SVGA_REG_MEM_SIZE);
+	dev_priv->fb_max_width = vmw_read(dev_priv, SVGA_REG_MAX_WIDTH);
+	dev_priv->fb_max_height = vmw_read(dev_priv, SVGA_REG_MAX_HEIGHT);
 	if (dev_priv->capabilities & SVGA_CAP_GMR) {
 		dev_priv->max_gmr_descriptors =
 			vmw_read(dev_priv,
@@ -292,11 +448,19 @@
 		dev_priv->max_gmr_ids =
 			vmw_read(dev_priv, SVGA_REG_GMR_MAX_IDS);
 	}
-
-	dev_priv->vram_size = vmw_read(dev_priv, SVGA_REG_VRAM_SIZE);
-	dev_priv->mmio_size = vmw_read(dev_priv, SVGA_REG_MEM_SIZE);
-	dev_priv->fb_max_width = vmw_read(dev_priv, SVGA_REG_MAX_WIDTH);
-	dev_priv->fb_max_height = vmw_read(dev_priv, SVGA_REG_MAX_HEIGHT);
+	if (dev_priv->capabilities & SVGA_CAP_GMR2) {
+		dev_priv->max_gmr_pages =
+			vmw_read(dev_priv, SVGA_REG_GMRS_MAX_PAGES);
+		dev_priv->memory_size =
+			vmw_read(dev_priv, SVGA_REG_MEMORY_SIZE);
+		dev_priv->memory_size -= dev_priv->vram_size;
+	} else {
+		/*
+		 * An arbitrary limit of 512MiB on surface
+		 * memory. But all HWV8 hardware supports GMR2.
+		 */
+		dev_priv->memory_size = 512*1024*1024;
+	}
 
 	mutex_unlock(&dev_priv->hw_mutex);
 
@@ -308,6 +472,12 @@
 		DRM_INFO("Max GMR descriptors is %u\n",
 			 (unsigned)dev_priv->max_gmr_descriptors);
 	}
+	if (dev_priv->capabilities & SVGA_CAP_GMR2) {
+		DRM_INFO("Max number of GMR pages is %u\n",
+			 (unsigned)dev_priv->max_gmr_pages);
+		DRM_INFO("Max dedicated hypervisor surface memory is %u kiB\n",
+			 (unsigned)dev_priv->memory_size / 1024);
+	}
 	DRM_INFO("VRAM at 0x%08x size is %u kiB\n",
 		 dev_priv->vram_start, dev_priv->vram_size / 1024);
 	DRM_INFO("MMIO at 0x%08x size is %u kiB\n",
@@ -394,22 +564,34 @@
 			goto out_no_device;
 		}
 	}
+
+	dev_priv->fman = vmw_fence_manager_init(dev_priv);
+	if (unlikely(dev_priv->fman == NULL))
+		goto out_no_fman;
+
+	/* Need to start the fifo to check if we can do screen objects */
+	ret = vmw_3d_resource_inc(dev_priv, true);
+	if (unlikely(ret != 0))
+		goto out_no_fifo;
+	vmw_kms_save_vga(dev_priv);
+
+	/* Start kms and overlay systems, needs fifo. */
 	ret = vmw_kms_init(dev_priv);
 	if (unlikely(ret != 0))
 		goto out_no_kms;
 	vmw_overlay_init(dev_priv);
+
+	/* 3D Depends on Screen Objects being used. */
+	DRM_INFO("Detected %sdevice 3D availability.\n",
+		 vmw_fifo_have_3d(dev_priv) ?
+		 "" : "no ");
+
+	/* We might be done with the fifo now */
 	if (dev_priv->enable_fb) {
-		ret = vmw_3d_resource_inc(dev_priv);
-		if (unlikely(ret != 0))
-			goto out_no_fifo;
-		vmw_kms_save_vga(dev_priv);
 		vmw_fb_init(dev_priv);
-		DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ?
-			 "Detected device 3D availability.\n" :
-			 "Detected no device 3D availability.\n");
 	} else {
-		DRM_INFO("Delayed 3D detection since we're not "
-			 "running the device in SVGA mode yet.\n");
+		vmw_kms_restore_vga(dev_priv);
+		vmw_3d_resource_dec(dev_priv, true);
 	}
 
 	if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
@@ -426,15 +608,19 @@
 	return 0;
 
 out_no_irq:
-	if (dev_priv->enable_fb) {
+	if (dev_priv->enable_fb)
 		vmw_fb_close(dev_priv);
-		vmw_kms_restore_vga(dev_priv);
-		vmw_3d_resource_dec(dev_priv);
-	}
-out_no_fifo:
 	vmw_overlay_close(dev_priv);
 	vmw_kms_close(dev_priv);
 out_no_kms:
+	/* We still have a 3D resource reference held */
+	if (dev_priv->enable_fb) {
+		vmw_kms_restore_vga(dev_priv);
+		vmw_3d_resource_dec(dev_priv, false);
+	}
+out_no_fifo:
+	vmw_fence_manager_takedown(dev_priv->fman);
+out_no_fman:
 	if (dev_priv->stealth)
 		pci_release_region(dev->pdev, 2);
 	else
@@ -467,15 +653,18 @@
 
 	unregister_pm_notifier(&dev_priv->pm_nb);
 
+	if (dev_priv->ctx.cmd_bounce)
+		vfree(dev_priv->ctx.cmd_bounce);
 	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
 		drm_irq_uninstall(dev_priv->dev);
 	if (dev_priv->enable_fb) {
 		vmw_fb_close(dev_priv);
 		vmw_kms_restore_vga(dev_priv);
-		vmw_3d_resource_dec(dev_priv);
+		vmw_3d_resource_dec(dev_priv, false);
 	}
 	vmw_kms_close(dev_priv);
 	vmw_overlay_close(dev_priv);
+	vmw_fence_manager_takedown(dev_priv->fman);
 	if (dev_priv->stealth)
 		pci_release_region(dev->pdev, 2);
 	else
@@ -646,7 +835,7 @@
 	int ret = 0;
 
 	if (!dev_priv->enable_fb) {
-		ret = vmw_3d_resource_inc(dev_priv);
+		ret = vmw_3d_resource_inc(dev_priv, true);
 		if (unlikely(ret != 0))
 			return ret;
 		vmw_kms_save_vga(dev_priv);
@@ -688,7 +877,7 @@
 		vmw_write(dev_priv, SVGA_REG_TRACES, 1);
 		mutex_unlock(&dev_priv->hw_mutex);
 		vmw_kms_restore_vga(dev_priv);
-		vmw_3d_resource_dec(dev_priv);
+		vmw_3d_resource_dec(dev_priv, true);
 	}
 	return ret;
 }
@@ -709,7 +898,7 @@
 
 	vmw_fp->locked_master = drm_master_get(file_priv->master);
 	ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile);
-	vmw_kms_idle_workqueues(vmaster);
+	vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
 
 	if (unlikely((ret != 0))) {
 		DRM_ERROR("Unable to lock TTM at VT switch.\n");
@@ -726,7 +915,7 @@
 		vmw_write(dev_priv, SVGA_REG_TRACES, 1);
 		mutex_unlock(&dev_priv->hw_mutex);
 		vmw_kms_restore_vga(dev_priv);
-		vmw_3d_resource_dec(dev_priv);
+		vmw_3d_resource_dec(dev_priv, true);
 	}
 
 	dev_priv->active_master = &dev_priv->fbdev_master;
@@ -761,6 +950,7 @@
 		 * This empties VRAM and unbinds all GMR bindings.
 		 * Buffer contents is moved to swappable memory.
 		 */
+		vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
 		ttm_bo_swapout_all(&dev_priv->bdev);
 
 		break;
@@ -835,7 +1025,7 @@
 	 */
 	dev_priv->suspended = true;
 	if (dev_priv->enable_fb)
-		vmw_3d_resource_dec(dev_priv);
+			vmw_3d_resource_dec(dev_priv, true);
 
 	if (dev_priv->num_3d_resources != 0) {
 
@@ -843,7 +1033,7 @@
 			 "while 3D resources are active.\n");
 
 		if (dev_priv->enable_fb)
-			vmw_3d_resource_inc(dev_priv);
+			vmw_3d_resource_inc(dev_priv, true);
 		dev_priv->suspended = false;
 		return -EBUSY;
 	}
@@ -862,7 +1052,7 @@
 	 * start fifo.
 	 */
 	if (dev_priv->enable_fb)
-		vmw_3d_resource_inc(dev_priv);
+			vmw_3d_resource_inc(dev_priv, false);
 
 	dev_priv->suspended = false;
 }
@@ -886,6 +1076,8 @@
 	.irq_uninstall = vmw_irq_uninstall,
 	.irq_handler = vmw_irq_handler,
 	.get_vblank_counter = vmw_get_vblank_counter,
+	.enable_vblank = vmw_enable_vblank,
+	.disable_vblank = vmw_disable_vblank,
 	.reclaim_buffers_locked = NULL,
 	.ioctls = vmw_ioctls,
 	.num_ioctls = DRM_ARRAY_SIZE(vmw_ioctls),
@@ -902,7 +1094,8 @@
 		 .release = drm_release,
 		 .unlocked_ioctl = vmw_unlocked_ioctl,
 		 .mmap = vmw_mmap,
-		 .poll = drm_poll,
+		 .poll = vmw_fops_poll,
+		 .read = vmw_fops_read,
 		 .fasync = drm_fasync,
 #if defined(CONFIG_COMPAT)
 		 .compat_ioctl = drm_compat_ioctl,
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h	2012-01-04 18:55:44.000000000 -0500
@@ -38,20 +38,27 @@
 #include "ttm/ttm_lock.h"
 #include "ttm/ttm_execbuf_util.h"
 #include "ttm/ttm_module.h"
+#include "vmwgfx_fence.h"
 
-#define VMWGFX_DRIVER_DATE "20100927"
-#define VMWGFX_DRIVER_MAJOR 1
-#define VMWGFX_DRIVER_MINOR 4
+#define VMWGFX_DRIVER_DATE "20111025"
+#define VMWGFX_DRIVER_MAJOR 2
+#define VMWGFX_DRIVER_MINOR 3
 #define VMWGFX_DRIVER_PATCHLEVEL 0
 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
 #define VMWGFX_MAX_RELOCATIONS 2048
-#define VMWGFX_MAX_GMRS 2048
+#define VMWGFX_MAX_VALIDATIONS 2048
 #define VMWGFX_MAX_DISPLAYS 16
+#define VMWGFX_CMD_BOUNCE_INIT_SIZE 32768
 
 #define VMW_PL_GMR TTM_PL_PRIV0
 #define VMW_PL_FLAG_GMR TTM_PL_FLAG_PRIV0
 
+#define VMW_RES_CONTEXT ttm_driver_type0
+#define VMW_RES_SURFACE ttm_driver_type1
+#define VMW_RES_STREAM ttm_driver_type2
+#define VMW_RES_FENCE ttm_driver_type3
+
 struct vmw_fpriv {
 	struct drm_master *locked_master;
 	struct ttm_object_file *tfile;
@@ -72,9 +79,11 @@
 	int id;
 	enum ttm_object_type res_type;
 	bool avail;
+	void (*remove_from_lists) (struct vmw_resource *res);
 	void (*hw_destroy) (struct vmw_resource *res);
 	void (*res_free) (struct vmw_resource *res);
-
+	struct list_head validate_head;
+	struct list_head query_head; /* Protected by the cmdbuf mutex */
 	/* TODO is a generic snooper needed? */
 #if 0
 	void (*snoop)(struct vmw_resource *res,
@@ -90,8 +99,12 @@
 	uint32_t *image;
 };
 
+struct vmw_framebuffer;
+struct vmw_surface_offset;
+
 struct vmw_surface {
 	struct vmw_resource res;
+	struct list_head lru_head; /* Protected by the resource lock */
 	uint32_t flags;
 	uint32_t format;
 	uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES];
@@ -102,9 +115,12 @@
 
 	/* TODO so far just a extra pointer */
 	struct vmw_cursor_snooper snooper;
+	struct ttm_buffer_object *backup;
+	struct vmw_surface_offset *offsets;
+	uint32_t backup_size;
 };
 
-struct vmw_fence_queue {
+struct vmw_marker_queue {
 	struct list_head head;
 	struct timespec lag;
 	struct timespec lag_time;
@@ -115,16 +131,12 @@
 	unsigned long reserved_size;
 	__le32 *dynamic_buffer;
 	__le32 *static_buffer;
-	__le32 *last_buffer;
-	uint32_t last_data_size;
-	uint32_t last_buffer_size;
-	bool last_buffer_add;
 	unsigned long static_buffer_size;
 	bool using_bounce_buffer;
 	uint32_t capabilities;
 	struct mutex fifo_mutex;
 	struct rw_semaphore rwsem;
-	struct vmw_fence_queue fence_queue;
+	struct vmw_marker_queue marker_queue;
 };
 
 struct vmw_relocation {
@@ -136,6 +148,8 @@
 	struct ida bo_list;
 	uint32_t last_cid;
 	bool cid_valid;
+	bool kernel; /**< is the called made from the kernel */
+	struct vmw_resource *cur_ctx;
 	uint32_t last_sid;
 	uint32_t sid_translation;
 	bool sid_valid;
@@ -143,8 +157,16 @@
 	struct list_head validate_nodes;
 	struct vmw_relocation relocs[VMWGFX_MAX_RELOCATIONS];
 	uint32_t cur_reloc;
-	struct ttm_validate_buffer val_bufs[VMWGFX_MAX_GMRS];
+	struct ttm_validate_buffer val_bufs[VMWGFX_MAX_VALIDATIONS];
 	uint32_t cur_val_buf;
+	uint32_t *cmd_bounce;
+	uint32_t cmd_bounce_size;
+	struct list_head resource_list;
+	uint32_t fence_flags;
+	struct list_head query_list;
+	struct ttm_buffer_object *cur_query_bo;
+	uint32_t cur_query_cid;
+	bool query_cid_valid;
 };
 
 struct vmw_legacy_display;
@@ -185,6 +207,8 @@
 	uint32_t capabilities;
 	uint32_t max_gmr_descriptors;
 	uint32_t max_gmr_ids;
+	uint32_t max_gmr_pages;
+	uint32_t memory_size;
 	bool has_gmr;
 	struct mutex hw_mutex;
 
@@ -195,12 +219,7 @@
 	struct vmw_vga_topology_state vga_save[VMWGFX_MAX_DISPLAYS];
 	uint32_t vga_width;
 	uint32_t vga_height;
-	uint32_t vga_depth;
 	uint32_t vga_bpp;
-	uint32_t vga_pseudo;
-	uint32_t vga_red_mask;
-	uint32_t vga_green_mask;
-	uint32_t vga_blue_mask;
 	uint32_t vga_bpl;
 	uint32_t vga_pitchlock;
 
@@ -212,6 +231,7 @@
 
 	void *fb_info;
 	struct vmw_legacy_display *ldu_priv;
+	struct vmw_screen_object_display *sou_priv;
 	struct vmw_overlay *overlay_priv;
 
 	/*
@@ -240,13 +260,16 @@
 	 * Fencing and IRQs.
 	 */
 
-	atomic_t fence_seq;
+	atomic_t marker_seq;
 	wait_queue_head_t fence_queue;
 	wait_queue_head_t fifo_queue;
-	atomic_t fence_queue_waiters;
+	int fence_queue_waiters; /* Protected by hw_mutex */
+	int goal_queue_waiters; /* Protected by hw_mutex */
 	atomic_t fifo_queue_waiters;
-	uint32_t last_read_sequence;
+	uint32_t last_read_seqno;
 	spinlock_t irq_lock;
+	struct vmw_fence_manager *fman;
+	uint32_t irq_mask;
 
 	/*
 	 * Device state
@@ -285,6 +308,26 @@
 
 	struct mutex release_mutex;
 	uint32_t num_3d_resources;
+
+	/*
+	 * Query processing. These members
+	 * are protected by the cmdbuf mutex.
+	 */
+
+	struct ttm_buffer_object *dummy_query_bo;
+	struct ttm_buffer_object *pinned_bo;
+	uint32_t query_cid;
+	bool dummy_query_bo_pinned;
+
+	/*
+	 * Surface swapping. The "surface_lru" list is protected by the
+	 * resource lock in order to be able to destroy a surface and take
+	 * it off the lru atomically. "used_memory_size" is currently
+	 * protected by the cmdbuf mutex for simplicity.
+	 */
+
+	struct list_head surface_lru;
+	uint32_t used_memory_size;
 };
 
 static inline struct vmw_private *vmw_priv(struct drm_device *dev)
@@ -319,8 +362,8 @@
 	return val;
 }
 
-int vmw_3d_resource_inc(struct vmw_private *dev_priv);
-void vmw_3d_resource_dec(struct vmw_private *dev_priv);
+int vmw_3d_resource_inc(struct vmw_private *dev_priv, bool unhide_svga);
+void vmw_3d_resource_dec(struct vmw_private *dev_priv, bool hide_svga);
 
 /**
  * GMR utilities - vmwgfx_gmr.c
@@ -345,7 +388,13 @@
 				    struct drm_file *file_priv);
 extern int vmw_context_check(struct vmw_private *dev_priv,
 			     struct ttm_object_file *tfile,
-			     int id);
+			     int id,
+			     struct vmw_resource **p_res);
+extern int vmw_user_lookup_handle(struct vmw_private *dev_priv,
+				  struct ttm_object_file *tfile,
+				  uint32_t handle,
+				  struct vmw_surface **out_surf,
+				  struct vmw_dma_buffer **out_buf);
 extern void vmw_surface_res_free(struct vmw_resource *res);
 extern int vmw_surface_init(struct vmw_private *dev_priv,
 			    struct vmw_surface *srf,
@@ -363,6 +412,8 @@
 extern int vmw_surface_check(struct vmw_private *dev_priv,
 			     struct ttm_object_file *tfile,
 			     uint32_t handle, int *id);
+extern int vmw_surface_validate(struct vmw_private *dev_priv,
+				struct vmw_surface *srf);
 extern void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo);
 extern int vmw_dmabuf_init(struct vmw_private *dev_priv,
 			   struct vmw_dma_buffer *vmw_bo,
@@ -378,10 +429,6 @@
 extern void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo);
 extern int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
 				  uint32_t id, struct vmw_dma_buffer **out);
-extern int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
-				       struct vmw_dma_buffer *bo);
-extern int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv,
-				struct vmw_dma_buffer *bo);
 extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
 				  struct drm_file *file_priv);
 extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
@@ -390,7 +437,30 @@
 				  struct ttm_object_file *tfile,
 				  uint32_t *inout_id,
 				  struct vmw_resource **out);
+extern void vmw_resource_unreserve(struct list_head *list);
 
+/**
+ * DMA buffer helper routines - vmwgfx_dmabuf.c
+ */
+extern int vmw_dmabuf_to_placement(struct vmw_private *vmw_priv,
+				   struct vmw_dma_buffer *bo,
+				   struct ttm_placement *placement,
+				   bool interruptible);
+extern int vmw_dmabuf_to_vram(struct vmw_private *dev_priv,
+			      struct vmw_dma_buffer *buf,
+			      bool pin, bool interruptible);
+extern int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv,
+				     struct vmw_dma_buffer *buf,
+				     bool pin, bool interruptible);
+extern int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
+				       struct vmw_dma_buffer *bo,
+				       bool pin, bool interruptible);
+extern int vmw_dmabuf_unpin(struct vmw_private *vmw_priv,
+			    struct vmw_dma_buffer *bo,
+			    bool interruptible);
+extern void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *buf,
+				 SVGAGuestPtr *ptr);
+extern void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin);
 
 /**
  * Misc Ioctl functionality - vmwgfx_ioctl.c
@@ -398,8 +468,16 @@
 
 extern int vmw_getparam_ioctl(struct drm_device *dev, void *data,
 			      struct drm_file *file_priv);
-extern int vmw_fifo_debug_ioctl(struct drm_device *dev, void *data,
+extern int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
+extern int vmw_present_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv);
+extern int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
+				      struct drm_file *file_priv);
+extern unsigned int vmw_fops_poll(struct file *filp,
+				  struct poll_table_struct *wait);
+extern ssize_t vmw_fops_read(struct file *filp, char __user *buffer,
+			     size_t count, loff_t *offset);
 
 /**
  * Fifo utilities - vmwgfx_fifo.c
@@ -412,11 +490,12 @@
 extern void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes);
 extern void vmw_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes);
 extern int vmw_fifo_send_fence(struct vmw_private *dev_priv,
-			       uint32_t *sequence);
+			       uint32_t *seqno);
 extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason);
-extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma);
 extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv);
 extern bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv);
+extern int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv,
+				     uint32_t cid);
 
 /**
  * TTM glue - vmwgfx_ttm_glue.c
@@ -434,7 +513,10 @@
 extern struct ttm_placement vmw_vram_ne_placement;
 extern struct ttm_placement vmw_vram_sys_placement;
 extern struct ttm_placement vmw_vram_gmr_placement;
+extern struct ttm_placement vmw_vram_gmr_ne_placement;
 extern struct ttm_placement vmw_sys_placement;
+extern struct ttm_placement vmw_evictable_placement;
+extern struct ttm_placement vmw_srf_placement;
 extern struct ttm_bo_driver vmw_bo_driver;
 extern int vmw_dma_quiescent(struct drm_device *dev);
 
@@ -444,45 +526,70 @@
 
 extern int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
 			     struct drm_file *file_priv);
+extern int vmw_execbuf_process(struct drm_file *file_priv,
+			       struct vmw_private *dev_priv,
+			       void __user *user_commands,
+			       void *kernel_commands,
+			       uint32_t command_size,
+			       uint64_t throttle_us,
+			       struct drm_vmw_fence_rep __user
+			       *user_fence_rep);
+
+extern void
+vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
+			      bool only_on_cid_match, uint32_t cid);
+
+extern int vmw_execbuf_fence_commands(struct drm_file *file_priv,
+				      struct vmw_private *dev_priv,
+				      struct vmw_fence_obj **p_fence,
+				      uint32_t *p_handle);
+extern void vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
+					struct vmw_fpriv *vmw_fp,
+					int ret,
+					struct drm_vmw_fence_rep __user
+					*user_fence_rep,
+					struct vmw_fence_obj *fence,
+					uint32_t fence_handle);
 
 /**
  * IRQs and wating - vmwgfx_irq.c
  */
 
 extern irqreturn_t vmw_irq_handler(DRM_IRQ_ARGS);
-extern int vmw_wait_fence(struct vmw_private *dev_priv, bool lazy,
-			  uint32_t sequence, bool interruptible,
-			  unsigned long timeout);
+extern int vmw_wait_seqno(struct vmw_private *dev_priv, bool lazy,
+			     uint32_t seqno, bool interruptible,
+			     unsigned long timeout);
 extern void vmw_irq_preinstall(struct drm_device *dev);
 extern int vmw_irq_postinstall(struct drm_device *dev);
 extern void vmw_irq_uninstall(struct drm_device *dev);
-extern bool vmw_fence_signaled(struct vmw_private *dev_priv,
-			       uint32_t sequence);
-extern int vmw_fence_wait_ioctl(struct drm_device *dev, void *data,
-				struct drm_file *file_priv);
+extern bool vmw_seqno_passed(struct vmw_private *dev_priv,
+				uint32_t seqno);
 extern int vmw_fallback_wait(struct vmw_private *dev_priv,
 			     bool lazy,
 			     bool fifo_idle,
-			     uint32_t sequence,
+			     uint32_t seqno,
 			     bool interruptible,
 			     unsigned long timeout);
-extern void vmw_update_sequence(struct vmw_private *dev_priv,
+extern void vmw_update_seqno(struct vmw_private *dev_priv,
 				struct vmw_fifo_state *fifo_state);
-
+extern void vmw_seqno_waiter_add(struct vmw_private *dev_priv);
+extern void vmw_seqno_waiter_remove(struct vmw_private *dev_priv);
+extern void vmw_goal_waiter_add(struct vmw_private *dev_priv);
+extern void vmw_goal_waiter_remove(struct vmw_private *dev_priv);
 
 /**
- * Rudimentary fence objects currently used only for throttling -
- * vmwgfx_fence.c
+ * Rudimentary fence-like objects currently used only for throttling -
+ * vmwgfx_marker.c
  */
 
-extern void vmw_fence_queue_init(struct vmw_fence_queue *queue);
-extern void vmw_fence_queue_takedown(struct vmw_fence_queue *queue);
-extern int vmw_fence_push(struct vmw_fence_queue *queue,
-			  uint32_t sequence);
-extern int vmw_fence_pull(struct vmw_fence_queue *queue,
-			  uint32_t signaled_sequence);
+extern void vmw_marker_queue_init(struct vmw_marker_queue *queue);
+extern void vmw_marker_queue_takedown(struct vmw_marker_queue *queue);
+extern int vmw_marker_push(struct vmw_marker_queue *queue,
+			  uint32_t seqno);
+extern int vmw_marker_pull(struct vmw_marker_queue *queue,
+			  uint32_t signaled_seqno);
 extern int vmw_wait_lag(struct vmw_private *dev_priv,
-			struct vmw_fence_queue *queue, uint32_t us);
+			struct vmw_marker_queue *queue, uint32_t us);
 
 /**
  * Kernel framebuffer - vmwgfx_fb.c
@@ -508,16 +615,31 @@
 			  struct ttm_object_file *tfile,
 			  struct ttm_buffer_object *bo,
 			  SVGA3dCmdHeader *header);
-void vmw_kms_write_svga(struct vmw_private *vmw_priv,
-			unsigned width, unsigned height, unsigned pitch,
-			unsigned bbp, unsigned depth);
-int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
-				struct drm_file *file_priv);
+int vmw_kms_write_svga(struct vmw_private *vmw_priv,
+		       unsigned width, unsigned height, unsigned pitch,
+		       unsigned bpp, unsigned depth);
 void vmw_kms_idle_workqueues(struct vmw_master *vmaster);
 bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
 				uint32_t pitch,
 				uint32_t height);
 u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc);
+int vmw_enable_vblank(struct drm_device *dev, int crtc);
+void vmw_disable_vblank(struct drm_device *dev, int crtc);
+int vmw_kms_present(struct vmw_private *dev_priv,
+		    struct drm_file *file_priv,
+		    struct vmw_framebuffer *vfb,
+		    struct vmw_surface *surface,
+		    uint32_t sid, int32_t destX, int32_t destY,
+		    struct drm_vmw_rect *clips,
+		    uint32_t num_clips);
+int vmw_kms_readback(struct vmw_private *dev_priv,
+		     struct drm_file *file_priv,
+		     struct vmw_framebuffer *vfb,
+		     struct drm_vmw_fence_rep __user *user_fence_rep,
+		     struct drm_vmw_rect *clips,
+		     uint32_t num_clips);
+int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv);
 
 /**
  * Overlay control - vmwgfx_overlay.c
@@ -576,4 +698,8 @@
 	return NULL;
 }
 
+static inline struct ttm_mem_global *vmw_mem_glob(struct vmw_private *dev_priv)
+{
+	return (struct ttm_mem_global *) dev_priv->mem_global_ref.object;
+}
 #endif
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,10 +44,71 @@
 	return 0;
 }
 
+static void vmw_resource_to_validate_list(struct vmw_sw_context *sw_context,
+					  struct vmw_resource **p_res)
+{
+	struct vmw_resource *res = *p_res;
+
+	if (list_empty(&res->validate_head)) {
+		list_add_tail(&res->validate_head, &sw_context->resource_list);
+		*p_res = NULL;
+	} else
+		vmw_resource_unreference(p_res);
+}
+
+/**
+ * vmw_bo_to_validate_list - add a bo to a validate list
+ *
+ * @sw_context: The software context used for this command submission batch.
+ * @bo: The buffer object to add.
+ * @fence_flags: Fence flags to be or'ed with any other fence flags for
+ * this buffer on this submission batch.
+ * @p_val_node: If non-NULL Will be updated with the validate node number
+ * on return.
+ *
+ * Returns -EINVAL if the limit of number of buffer objects per command
+ * submission is reached.
+ */
+static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
+				   struct ttm_buffer_object *bo,
+				   uint32_t fence_flags,
+				   uint32_t *p_val_node)
+{
+	uint32_t val_node;
+	struct ttm_validate_buffer *val_buf;
+
+	val_node = vmw_dmabuf_validate_node(bo, sw_context->cur_val_buf);
+
+	if (unlikely(val_node >= VMWGFX_MAX_VALIDATIONS)) {
+		DRM_ERROR("Max number of DMA buffers per submission"
+			  " exceeded.\n");
+		return -EINVAL;
+	}
+
+	val_buf = &sw_context->val_bufs[val_node];
+	if (unlikely(val_node == sw_context->cur_val_buf)) {
+		val_buf->new_sync_obj_arg = NULL;
+		val_buf->bo = ttm_bo_reference(bo);
+		list_add_tail(&val_buf->head, &sw_context->validate_nodes);
+		++sw_context->cur_val_buf;
+	}
+
+	val_buf->new_sync_obj_arg = (void *)
+		((unsigned long) val_buf->new_sync_obj_arg | fence_flags);
+	sw_context->fence_flags |= fence_flags;
+
+	if (p_val_node)
+		*p_val_node = val_node;
+
+	return 0;
+}
+
 static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
 			     struct vmw_sw_context *sw_context,
 			     SVGA3dCmdHeader *header)
 {
+	struct vmw_resource *ctx;
+
 	struct vmw_cid_cmd {
 		SVGA3dCmdHeader header;
 		__le32 cid;
@@ -58,7 +119,8 @@
 	if (likely(sw_context->cid_valid && cmd->cid == sw_context->last_cid))
 		return 0;
 
-	ret = vmw_context_check(dev_priv, sw_context->tfile, cmd->cid);
+	ret = vmw_context_check(dev_priv, sw_context->tfile, cmd->cid,
+				&ctx);
 	if (unlikely(ret != 0)) {
 		DRM_ERROR("Could not find or use context %u\n",
 			  (unsigned) cmd->cid);
@@ -67,6 +129,8 @@
 
 	sw_context->last_cid = cmd->cid;
 	sw_context->cid_valid = true;
+	sw_context->cur_ctx = ctx;
+	vmw_resource_to_validate_list(sw_context, &ctx);
 
 	return 0;
 }
@@ -75,29 +139,45 @@
 			     struct vmw_sw_context *sw_context,
 			     uint32_t *sid)
 {
+	struct vmw_surface *srf;
+	int ret;
+	struct vmw_resource *res;
+
 	if (*sid == SVGA3D_INVALID_ID)
 		return 0;
 
-	if (unlikely((!sw_context->sid_valid  ||
-		      *sid != sw_context->last_sid))) {
-		int real_id;
-		int ret = vmw_surface_check(dev_priv, sw_context->tfile,
-					    *sid, &real_id);
+	if (likely((sw_context->sid_valid  &&
+		      *sid == sw_context->last_sid))) {
+		*sid = sw_context->sid_translation;
+		return 0;
+	}
 
-		if (unlikely(ret != 0)) {
-			DRM_ERROR("Could ot find or use surface 0x%08x "
-				  "address 0x%08lx\n",
-				  (unsigned int) *sid,
-				  (unsigned long) sid);
-			return ret;
-		}
+	ret = vmw_user_surface_lookup_handle(dev_priv,
+					     sw_context->tfile,
+					     *sid, &srf);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Could ot find or use surface 0x%08x "
+			  "address 0x%08lx\n",
+			  (unsigned int) *sid,
+			  (unsigned long) sid);
+		return ret;
+	}
 
-		sw_context->last_sid = *sid;
-		sw_context->sid_valid = true;
-		*sid = real_id;
-		sw_context->sid_translation = real_id;
-	} else
-		*sid = sw_context->sid_translation;
+	ret = vmw_surface_validate(dev_priv, srf);
+	if (unlikely(ret != 0)) {
+		if (ret != -ERESTARTSYS)
+			DRM_ERROR("Could not validate surface.\n");
+		vmw_surface_unreference(&srf);
+		return ret;
+	}
+
+	sw_context->last_sid = *sid;
+	sw_context->sid_valid = true;
+	sw_context->sid_translation = srf->res.id;
+	*sid = sw_context->sid_translation;
+
+	res = &srf->res;
+	vmw_resource_to_validate_list(sw_context, &res);
 
 	return 0;
 }
@@ -166,6 +246,12 @@
 	} *cmd;
 
 	cmd = container_of(header, struct vmw_sid_cmd, header);
+
+	if (unlikely(!sw_context->kernel)) {
+		DRM_ERROR("Kernel only SVGA3d command: %u.\n", cmd->header.id);
+		return -EPERM;
+	}
+
 	return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.srcImage.sid);
 }
 
@@ -178,10 +264,179 @@
 		SVGA3dCmdPresent body;
 	} *cmd;
 
+
 	cmd = container_of(header, struct vmw_sid_cmd, header);
+
+	if (unlikely(!sw_context->kernel)) {
+		DRM_ERROR("Kernel only SVGA3d command: %u.\n", cmd->header.id);
+		return -EPERM;
+	}
+
 	return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.sid);
 }
 
+/**
+ * vmw_query_bo_switch_prepare - Prepare to switch pinned buffer for queries.
+ *
+ * @dev_priv: The device private structure.
+ * @cid: The hardware context for the next query.
+ * @new_query_bo: The new buffer holding query results.
+ * @sw_context: The software context used for this command submission.
+ *
+ * This function checks whether @new_query_bo is suitable for holding
+ * query results, and if another buffer currently is pinned for query
+ * results. If so, the function prepares the state of @sw_context for
+ * switching pinned buffers after successful submission of the current
+ * command batch. It also checks whether we're using a new query context.
+ * In that case, it makes sure we emit a query barrier for the old
+ * context before the current query buffer is fenced.
+ */
+static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
+				       uint32_t cid,
+				       struct ttm_buffer_object *new_query_bo,
+				       struct vmw_sw_context *sw_context)
+{
+	int ret;
+	bool add_cid = false;
+	uint32_t cid_to_add;
+
+	if (unlikely(new_query_bo != sw_context->cur_query_bo)) {
+
+		if (unlikely(new_query_bo->num_pages > 4)) {
+			DRM_ERROR("Query buffer too large.\n");
+			return -EINVAL;
+		}
+
+		if (unlikely(sw_context->cur_query_bo != NULL)) {
+			BUG_ON(!sw_context->query_cid_valid);
+			add_cid = true;
+			cid_to_add = sw_context->cur_query_cid;
+			ret = vmw_bo_to_validate_list(sw_context,
+						      sw_context->cur_query_bo,
+						      DRM_VMW_FENCE_FLAG_EXEC,
+						      NULL);
+			if (unlikely(ret != 0))
+				return ret;
+		}
+		sw_context->cur_query_bo = new_query_bo;
+
+		ret = vmw_bo_to_validate_list(sw_context,
+					      dev_priv->dummy_query_bo,
+					      DRM_VMW_FENCE_FLAG_EXEC,
+					      NULL);
+		if (unlikely(ret != 0))
+			return ret;
+
+	}
+
+	if (unlikely(cid != sw_context->cur_query_cid &&
+		     sw_context->query_cid_valid)) {
+		add_cid = true;
+		cid_to_add = sw_context->cur_query_cid;
+	}
+
+	sw_context->cur_query_cid = cid;
+	sw_context->query_cid_valid = true;
+
+	if (add_cid) {
+		struct vmw_resource *ctx = sw_context->cur_ctx;
+
+		if (list_empty(&ctx->query_head))
+			list_add_tail(&ctx->query_head,
+				      &sw_context->query_list);
+		ret = vmw_bo_to_validate_list(sw_context,
+					      dev_priv->dummy_query_bo,
+					      DRM_VMW_FENCE_FLAG_EXEC,
+					      NULL);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+	return 0;
+}
+
+
+/**
+ * vmw_query_bo_switch_commit - Finalize switching pinned query buffer
+ *
+ * @dev_priv: The device private structure.
+ * @sw_context: The software context used for this command submission batch.
+ *
+ * This function will check if we're switching query buffers, and will then,
+ * if no other query waits are issued this command submission batch,
+ * issue a dummy occlusion query wait used as a query barrier. When the fence
+ * object following that query wait has signaled, we are sure that all
+ * preseding queries have finished, and the old query buffer can be unpinned.
+ * However, since both the new query buffer and the old one are fenced with
+ * that fence, we can do an asynchronus unpin now, and be sure that the
+ * old query buffer won't be moved until the fence has signaled.
+ *
+ * As mentioned above, both the new - and old query buffers need to be fenced
+ * using a sequence emitted *after* calling this function.
+ */
+static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv,
+				     struct vmw_sw_context *sw_context)
+{
+
+	struct vmw_resource *ctx, *next_ctx;
+	int ret;
+
+	/*
+	 * The validate list should still hold references to all
+	 * contexts here.
+	 */
+
+	list_for_each_entry_safe(ctx, next_ctx, &sw_context->query_list,
+				 query_head) {
+		list_del_init(&ctx->query_head);
+
+		BUG_ON(list_empty(&ctx->validate_head));
+
+		ret = vmw_fifo_emit_dummy_query(dev_priv, ctx->id);
+
+		if (unlikely(ret != 0))
+			DRM_ERROR("Out of fifo space for dummy query.\n");
+	}
+
+	if (dev_priv->pinned_bo != sw_context->cur_query_bo) {
+		if (dev_priv->pinned_bo) {
+			vmw_bo_pin(dev_priv->pinned_bo, false);
+			ttm_bo_unref(&dev_priv->pinned_bo);
+		}
+
+		vmw_bo_pin(sw_context->cur_query_bo, true);
+
+		/*
+		 * We pin also the dummy_query_bo buffer so that we
+		 * don't need to validate it when emitting
+		 * dummy queries in context destroy paths.
+		 */
+
+		vmw_bo_pin(dev_priv->dummy_query_bo, true);
+		dev_priv->dummy_query_bo_pinned = true;
+
+		dev_priv->query_cid = sw_context->cur_query_cid;
+		dev_priv->pinned_bo =
+			ttm_bo_reference(sw_context->cur_query_bo);
+	}
+}
+
+/**
+ * vmw_query_switch_backoff - clear query barrier list
+ * @sw_context: The sw context used for this submission batch.
+ *
+ * This function is used as part of an error path, where a previously
+ * set up list of query barriers needs to be cleared.
+ *
+ */
+static void vmw_query_switch_backoff(struct vmw_sw_context *sw_context)
+{
+	struct list_head *list, *next;
+
+	list_for_each_safe(list, next, &sw_context->query_list) {
+		list_del_init(list);
+	}
+}
+
 static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
 				   struct vmw_sw_context *sw_context,
 				   SVGAGuestPtr *ptr,
@@ -191,8 +446,6 @@
 	struct ttm_buffer_object *bo;
 	uint32_t handle = ptr->gmrId;
 	struct vmw_relocation *reloc;
-	uint32_t cur_validate_node;
-	struct ttm_validate_buffer *val_buf;
 	int ret;
 
 	ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo);
@@ -212,22 +465,11 @@
 	reloc = &sw_context->relocs[sw_context->cur_reloc++];
 	reloc->location = ptr;
 
-	cur_validate_node = vmw_dmabuf_validate_node(bo, sw_context->cur_val_buf);
-	if (unlikely(cur_validate_node >= VMWGFX_MAX_GMRS)) {
-		DRM_ERROR("Max number of DMA buffers per submission"
-			  " exceeded.\n");
-		ret = -EINVAL;
+	ret = vmw_bo_to_validate_list(sw_context, bo, DRM_VMW_FENCE_FLAG_EXEC,
+				      &reloc->index);
+	if (unlikely(ret != 0))
 		goto out_no_reloc;
-	}
 
-	reloc->index = cur_validate_node;
-	if (unlikely(cur_validate_node == sw_context->cur_val_buf)) {
-		val_buf = &sw_context->val_bufs[cur_validate_node];
-		val_buf->bo = ttm_bo_reference(bo);
-		val_buf->new_sync_obj_arg = (void *) dev_priv;
-		list_add_tail(&val_buf->head, &sw_context->validate_nodes);
-		++sw_context->cur_val_buf;
-	}
 	*vmw_bo_p = vmw_bo;
 	return 0;
 
@@ -259,8 +501,11 @@
 	if (unlikely(ret != 0))
 		return ret;
 
+	ret = vmw_query_bo_switch_prepare(dev_priv, cmd->q.cid,
+					  &vmw_bo->base, sw_context);
+
 	vmw_dmabuf_unreference(&vmw_bo);
-	return 0;
+	return ret;
 }
 
 static int vmw_cmd_wait_query(struct vmw_private *dev_priv,
@@ -273,6 +518,7 @@
 		SVGA3dCmdWaitForQuery q;
 	} *cmd;
 	int ret;
+	struct vmw_resource *ctx;
 
 	cmd = container_of(header, struct vmw_query_cmd, header);
 	ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
@@ -286,10 +532,19 @@
 		return ret;
 
 	vmw_dmabuf_unreference(&vmw_bo);
+
+	/*
+	 * This wait will act as a barrier for previous waits for this
+	 * context.
+	 */
+
+	ctx = sw_context->cur_ctx;
+	if (!list_empty(&ctx->query_head))
+		list_del_init(&ctx->query_head);
+
 	return 0;
 }
 
-
 static int vmw_cmd_dma(struct vmw_private *dev_priv,
 		       struct vmw_sw_context *sw_context,
 		       SVGA3dCmdHeader *header)
@@ -302,6 +557,7 @@
 		SVGA3dCmdSurfaceDMA dma;
 	} *cmd;
 	int ret;
+	struct vmw_resource *res;
 
 	cmd = container_of(header, struct vmw_dma_cmd, header);
 	ret = vmw_translate_guest_ptr(dev_priv, sw_context,
@@ -318,18 +574,28 @@
 		goto out_no_reloc;
 	}
 
-	/**
+	ret = vmw_surface_validate(dev_priv, srf);
+	if (unlikely(ret != 0)) {
+		if (ret != -ERESTARTSYS)
+			DRM_ERROR("Culd not validate surface.\n");
+		goto out_no_validate;
+	}
+
+	/*
 	 * Patch command stream with device SID.
 	 */
-
 	cmd->dma.host.sid = srf->res.id;
 	vmw_kms_cursor_snoop(srf, sw_context->tfile, bo, header);
-	/**
-	 * FIXME: May deadlock here when called from the
-	 * command parsing code.
-	 */
-	vmw_surface_unreference(&srf);
 
+	vmw_dmabuf_unreference(&vmw_bo);
+
+	res = &srf->res;
+	vmw_resource_to_validate_list(sw_context, &res);
+
+	return 0;
+
+out_no_validate:
+	vmw_surface_unreference(&srf);
 out_no_reloc:
 	vmw_dmabuf_unreference(&vmw_bo);
 	return ret;
@@ -419,6 +685,71 @@
 	return 0;
 }
 
+static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv,
+				      struct vmw_sw_context *sw_context,
+				      void *buf)
+{
+	struct vmw_dma_buffer *vmw_bo;
+	int ret;
+
+	struct {
+		uint32_t header;
+		SVGAFifoCmdDefineGMRFB body;
+	} *cmd = buf;
+
+	ret = vmw_translate_guest_ptr(dev_priv, sw_context,
+				      &cmd->body.ptr,
+				      &vmw_bo);
+	if (unlikely(ret != 0))
+		return ret;
+
+	vmw_dmabuf_unreference(&vmw_bo);
+
+	return ret;
+}
+
+static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv,
+				struct vmw_sw_context *sw_context,
+				void *buf, uint32_t *size)
+{
+	uint32_t size_remaining = *size;
+	uint32_t cmd_id;
+
+	cmd_id = le32_to_cpu(((uint32_t *)buf)[0]);
+	switch (cmd_id) {
+	case SVGA_CMD_UPDATE:
+		*size = sizeof(uint32_t) + sizeof(SVGAFifoCmdUpdate);
+		break;
+	case SVGA_CMD_DEFINE_GMRFB:
+		*size = sizeof(uint32_t) + sizeof(SVGAFifoCmdDefineGMRFB);
+		break;
+	case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
+		*size = sizeof(uint32_t) + sizeof(SVGAFifoCmdBlitGMRFBToScreen);
+		break;
+	case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
+		*size = sizeof(uint32_t) + sizeof(SVGAFifoCmdBlitGMRFBToScreen);
+		break;
+	default:
+		DRM_ERROR("Unsupported SVGA command: %u.\n", cmd_id);
+		return -EINVAL;
+	}
+
+	if (*size > size_remaining) {
+		DRM_ERROR("Invalid SVGA command (size mismatch):"
+			  " %u.\n", cmd_id);
+		return -EINVAL;
+	}
+
+	if (unlikely(!sw_context->kernel)) {
+		DRM_ERROR("Kernel only SVGA command: %u.\n", cmd_id);
+		return -EPERM;
+	}
+
+	if (cmd_id == SVGA_CMD_DEFINE_GMRFB)
+		return vmw_cmd_check_define_gmrfb(dev_priv, sw_context, buf);
+
+	return 0;
+}
 
 typedef int (*vmw_cmd_func) (struct vmw_private *,
 			     struct vmw_sw_context *,
@@ -471,11 +802,11 @@
 	SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf;
 	int ret;
 
-	cmd_id = ((uint32_t *)buf)[0];
-	if (cmd_id == SVGA_CMD_UPDATE) {
-		*size = 5 << 2;
-		return 0;
-	}
+	cmd_id = le32_to_cpu(((uint32_t *)buf)[0]);
+	/* Handle any none 3D commands */
+	if (unlikely(cmd_id < SVGA_CMD_MAX))
+		return vmw_cmd_check_not_3d(dev_priv, sw_context, buf, size);
+
 
 	cmd_id = le32_to_cpu(header->id);
 	*size = le32_to_cpu(header->size) + sizeof(SVGA3dCmdHeader);
@@ -500,7 +831,8 @@
 
 static int vmw_cmd_check_all(struct vmw_private *dev_priv,
 			     struct vmw_sw_context *sw_context,
-			     void *buf, uint32_t size)
+			     void *buf,
+			     uint32_t size)
 {
 	int32_t cur_size = size;
 	int ret;
@@ -550,7 +882,11 @@
 static void vmw_clear_validations(struct vmw_sw_context *sw_context)
 {
 	struct ttm_validate_buffer *entry, *next;
+	struct vmw_resource *res, *res_next;
 
+	/*
+	 * Drop references to DMA buffers held during command submission.
+	 */
 	list_for_each_entry_safe(entry, next, &sw_context->validate_nodes,
 				 head) {
 		list_del(&entry->head);
@@ -559,6 +895,16 @@
 		sw_context->cur_val_buf--;
 	}
 	BUG_ON(sw_context->cur_val_buf != 0);
+
+	/*
+	 * Drop references to resources held during command submission.
+	 */
+	vmw_resource_unreserve(&sw_context->resource_list);
+	list_for_each_entry_safe(res, res_next, &sw_context->resource_list,
+				 validate_head) {
+		list_del_init(&res->validate_head);
+		vmw_resource_unreference(&res);
+	}
 }
 
 static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
@@ -566,6 +912,16 @@
 {
 	int ret;
 
+
+	/*
+	 * Don't validate pinned buffers.
+	 */
+
+	if (bo == dev_priv->pinned_bo ||
+	    (bo == dev_priv->dummy_query_bo &&
+	     dev_priv->dummy_query_bo_pinned))
+		return 0;
+
 	/**
 	 * Put BO in VRAM if there is space, otherwise as a GMR.
 	 * If there is no space in VRAM and GMR ids are all used up,
@@ -602,57 +958,208 @@
 	return 0;
 }
 
-int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
-		      struct drm_file *file_priv)
+static int vmw_resize_cmd_bounce(struct vmw_sw_context *sw_context,
+				 uint32_t size)
+{
+	if (likely(sw_context->cmd_bounce_size >= size))
+		return 0;
+
+	if (sw_context->cmd_bounce_size == 0)
+		sw_context->cmd_bounce_size = VMWGFX_CMD_BOUNCE_INIT_SIZE;
+
+	while (sw_context->cmd_bounce_size < size) {
+		sw_context->cmd_bounce_size =
+			PAGE_ALIGN(sw_context->cmd_bounce_size +
+				   (sw_context->cmd_bounce_size >> 1));
+	}
+
+	if (sw_context->cmd_bounce != NULL)
+		vfree(sw_context->cmd_bounce);
+
+	sw_context->cmd_bounce = vmalloc(sw_context->cmd_bounce_size);
+
+	if (sw_context->cmd_bounce == NULL) {
+		DRM_ERROR("Failed to allocate command bounce buffer.\n");
+		sw_context->cmd_bounce_size = 0;
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/**
+ * vmw_execbuf_fence_commands - create and submit a command stream fence
+ *
+ * Creates a fence object and submits a command stream marker.
+ * If this fails for some reason, We sync the fifo and return NULL.
+ * It is then safe to fence buffers with a NULL pointer.
+ *
+ * If @p_handle is not NULL @file_priv must also not be NULL. Creates
+ * a userspace handle if @p_handle is not NULL, otherwise not.
+ */
+
+int vmw_execbuf_fence_commands(struct drm_file *file_priv,
+			       struct vmw_private *dev_priv,
+			       struct vmw_fence_obj **p_fence,
+			       uint32_t *p_handle)
 {
-	struct vmw_private *dev_priv = vmw_priv(dev);
-	struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data;
-	struct drm_vmw_fence_rep fence_rep;
-	struct drm_vmw_fence_rep __user *user_fence_rep;
-	int ret;
-	void *user_cmd;
-	void *cmd;
 	uint32_t sequence;
-	struct vmw_sw_context *sw_context = &dev_priv->ctx;
-	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	int ret;
+	bool synced = false;
 
-	ret = ttm_read_lock(&vmaster->lock, true);
-	if (unlikely(ret != 0))
-		return ret;
+	/* p_handle implies file_priv. */
+	BUG_ON(p_handle != NULL && file_priv == NULL);
 
-	ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex);
+	ret = vmw_fifo_send_fence(dev_priv, &sequence);
 	if (unlikely(ret != 0)) {
-		ret = -ERESTARTSYS;
-		goto out_no_cmd_mutex;
+		DRM_ERROR("Fence submission error. Syncing.\n");
+		synced = true;
 	}
 
-	cmd = vmw_fifo_reserve(dev_priv, arg->command_size);
-	if (unlikely(cmd == NULL)) {
-		DRM_ERROR("Failed reserving fifo space for commands.\n");
-		ret = -ENOMEM;
-		goto out_unlock;
+	if (p_handle != NULL)
+		ret = vmw_user_fence_create(file_priv, dev_priv->fman,
+					    sequence,
+					    DRM_VMW_FENCE_FLAG_EXEC,
+					    p_fence, p_handle);
+	else
+		ret = vmw_fence_create(dev_priv->fman, sequence,
+				       DRM_VMW_FENCE_FLAG_EXEC,
+				       p_fence);
+
+	if (unlikely(ret != 0 && !synced)) {
+		(void) vmw_fallback_wait(dev_priv, false, false,
+					 sequence, false,
+					 VMW_FENCE_WAIT_TIMEOUT);
+		*p_fence = NULL;
 	}
 
-	user_cmd = (void __user *)(unsigned long)arg->commands;
-	ret = copy_from_user(cmd, user_cmd, arg->command_size);
+	return 0;
+}
 
-	if (unlikely(ret != 0)) {
-		ret = -EFAULT;
-		DRM_ERROR("Failed copying commands.\n");
-		goto out_commit;
+/**
+ * vmw_execbuf_copy_fence_user - copy fence object information to
+ * user-space.
+ *
+ * @dev_priv: Pointer to a vmw_private struct.
+ * @vmw_fp: Pointer to the struct vmw_fpriv representing the calling file.
+ * @ret: Return value from fence object creation.
+ * @user_fence_rep: User space address of a struct drm_vmw_fence_rep to
+ * which the information should be copied.
+ * @fence: Pointer to the fenc object.
+ * @fence_handle: User-space fence handle.
+ *
+ * This function copies fence information to user-space. If copying fails,
+ * The user-space struct drm_vmw_fence_rep::error member is hopefully
+ * left untouched, and if it's preloaded with an -EFAULT by user-space,
+ * the error will hopefully be detected.
+ * Also if copying fails, user-space will be unable to signal the fence
+ * object so we wait for it immediately, and then unreference the
+ * user-space reference.
+ */
+void
+vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
+			    struct vmw_fpriv *vmw_fp,
+			    int ret,
+			    struct drm_vmw_fence_rep __user *user_fence_rep,
+			    struct vmw_fence_obj *fence,
+			    uint32_t fence_handle)
+{
+	struct drm_vmw_fence_rep fence_rep;
+
+	if (user_fence_rep == NULL)
+		return;
+
+	memset(&fence_rep, 0, sizeof(fence_rep));
+
+	fence_rep.error = ret;
+	if (ret == 0) {
+		BUG_ON(fence == NULL);
+
+		fence_rep.handle = fence_handle;
+		fence_rep.seqno = fence->seqno;
+		vmw_update_seqno(dev_priv, &dev_priv->fifo);
+		fence_rep.passed_seqno = dev_priv->last_read_seqno;
 	}
 
+	/*
+	 * copy_to_user errors will be detected by user space not
+	 * seeing fence_rep::error filled in. Typically
+	 * user-space would have pre-set that member to -EFAULT.
+	 */
+	ret = copy_to_user(user_fence_rep, &fence_rep,
+			   sizeof(fence_rep));
+
+	/*
+	 * User-space lost the fence object. We need to sync
+	 * and unreference the handle.
+	 */
+	if (unlikely(ret != 0) && (fence_rep.error == 0)) {
+		ttm_ref_object_base_unref(vmw_fp->tfile,
+					  fence_handle, TTM_REF_USAGE);
+		DRM_ERROR("Fence copy error. Syncing.\n");
+		(void) vmw_fence_obj_wait(fence, fence->signal_mask,
+					  false, false,
+					  VMW_FENCE_WAIT_TIMEOUT);
+	}
+}
+
+int vmw_execbuf_process(struct drm_file *file_priv,
+			struct vmw_private *dev_priv,
+			void __user *user_commands,
+			void *kernel_commands,
+			uint32_t command_size,
+			uint64_t throttle_us,
+			struct drm_vmw_fence_rep __user *user_fence_rep)
+{
+	struct vmw_sw_context *sw_context = &dev_priv->ctx;
+	struct vmw_fence_obj *fence;
+	uint32_t handle;
+	void *cmd;
+	int ret;
+
+	ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex);
+	if (unlikely(ret != 0))
+		return -ERESTARTSYS;
+
+	if (kernel_commands == NULL) {
+		sw_context->kernel = false;
+
+		ret = vmw_resize_cmd_bounce(sw_context, command_size);
+		if (unlikely(ret != 0))
+			goto out_unlock;
+
+
+		ret = copy_from_user(sw_context->cmd_bounce,
+				     user_commands, command_size);
+
+		if (unlikely(ret != 0)) {
+			ret = -EFAULT;
+			DRM_ERROR("Failed copying commands.\n");
+			goto out_unlock;
+		}
+		kernel_commands = sw_context->cmd_bounce;
+	} else
+		sw_context->kernel = true;
+
 	sw_context->tfile = vmw_fpriv(file_priv)->tfile;
 	sw_context->cid_valid = false;
 	sw_context->sid_valid = false;
 	sw_context->cur_reloc = 0;
 	sw_context->cur_val_buf = 0;
+	sw_context->fence_flags = 0;
+	INIT_LIST_HEAD(&sw_context->query_list);
+	INIT_LIST_HEAD(&sw_context->resource_list);
+	sw_context->cur_query_bo = dev_priv->pinned_bo;
+	sw_context->cur_query_cid = dev_priv->query_cid;
+	sw_context->query_cid_valid = (dev_priv->pinned_bo != NULL);
 
 	INIT_LIST_HEAD(&sw_context->validate_nodes);
 
-	ret = vmw_cmd_check_all(dev_priv, sw_context, cmd, arg->command_size);
+	ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands,
+				command_size);
 	if (unlikely(ret != 0))
 		goto out_err;
+
 	ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes);
 	if (unlikely(ret != 0))
 		goto out_err;
@@ -663,57 +1170,206 @@
 
 	vmw_apply_relocations(sw_context);
 
-	if (arg->throttle_us) {
-		ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.fence_queue,
-				   arg->throttle_us);
+	if (throttle_us) {
+		ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.marker_queue,
+				   throttle_us);
 
 		if (unlikely(ret != 0))
-			goto out_err;
+			goto out_throttle;
 	}
 
-	vmw_fifo_commit(dev_priv, arg->command_size);
-
-	ret = vmw_fifo_send_fence(dev_priv, &sequence);
+	cmd = vmw_fifo_reserve(dev_priv, command_size);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed reserving fifo space for commands.\n");
+		ret = -ENOMEM;
+		goto out_throttle;
+	}
 
-	ttm_eu_fence_buffer_objects(&sw_context->validate_nodes,
-				    (void *)(unsigned long) sequence);
-	vmw_clear_validations(sw_context);
-	mutex_unlock(&dev_priv->cmdbuf_mutex);
+	memcpy(cmd, kernel_commands, command_size);
+	vmw_fifo_commit(dev_priv, command_size);
 
+	vmw_query_bo_switch_commit(dev_priv, sw_context);
+	ret = vmw_execbuf_fence_commands(file_priv, dev_priv,
+					 &fence,
+					 (user_fence_rep) ? &handle : NULL);
 	/*
 	 * This error is harmless, because if fence submission fails,
-	 * vmw_fifo_send_fence will sync.
+	 * vmw_fifo_send_fence will sync. The error will be propagated to
+	 * user-space in @fence_rep
 	 */
 
 	if (ret != 0)
 		DRM_ERROR("Fence submission error. Syncing.\n");
 
-	fence_rep.error = ret;
-	fence_rep.fence_seq = (uint64_t) sequence;
-	fence_rep.pad64 = 0;
-
-	user_fence_rep = (struct drm_vmw_fence_rep __user *)
-	    (unsigned long)arg->fence_rep;
+	ttm_eu_fence_buffer_objects(&sw_context->validate_nodes,
+				    (void *) fence);
 
-	/*
-	 * copy_to_user errors will be detected by user space not
-	 * seeing fence_rep::error filled in.
-	 */
+	vmw_clear_validations(sw_context);
+	vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret,
+				    user_fence_rep, fence, handle);
 
-	ret = copy_to_user(user_fence_rep, &fence_rep, sizeof(fence_rep));
+	if (likely(fence != NULL))
+		vmw_fence_obj_unreference(&fence);
 
-	vmw_kms_cursor_post_execbuf(dev_priv);
-	ttm_read_unlock(&vmaster->lock);
+	mutex_unlock(&dev_priv->cmdbuf_mutex);
 	return 0;
+
 out_err:
 	vmw_free_relocations(sw_context);
+out_throttle:
+	vmw_query_switch_backoff(sw_context);
 	ttm_eu_backoff_reservation(&sw_context->validate_nodes);
 	vmw_clear_validations(sw_context);
-out_commit:
-	vmw_fifo_commit(dev_priv, 0);
 out_unlock:
 	mutex_unlock(&dev_priv->cmdbuf_mutex);
-out_no_cmd_mutex:
+	return ret;
+}
+
+/**
+ * vmw_execbuf_unpin_panic - Idle the fifo and unpin the query buffer.
+ *
+ * @dev_priv: The device private structure.
+ *
+ * This function is called to idle the fifo and unpin the query buffer
+ * if the normal way to do this hits an error, which should typically be
+ * extremely rare.
+ */
+static void vmw_execbuf_unpin_panic(struct vmw_private *dev_priv)
+{
+	DRM_ERROR("Can't unpin query buffer. Trying to recover.\n");
+
+	(void) vmw_fallback_wait(dev_priv, false, true, 0, false, 10*HZ);
+	vmw_bo_pin(dev_priv->pinned_bo, false);
+	vmw_bo_pin(dev_priv->dummy_query_bo, false);
+	dev_priv->dummy_query_bo_pinned = false;
+}
+
+
+/**
+ * vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned
+ * query bo.
+ *
+ * @dev_priv: The device private structure.
+ * @only_on_cid_match: Only flush and unpin if the current active query cid
+ * matches @cid.
+ * @cid: Optional context id to match.
+ *
+ * This function should be used to unpin the pinned query bo, or
+ * as a query barrier when we need to make sure that all queries have
+ * finished before the next fifo command. (For example on hardware
+ * context destructions where the hardware may otherwise leak unfinished
+ * queries).
+ *
+ * This function does not return any failure codes, but make attempts
+ * to do safe unpinning in case of errors.
+ *
+ * The function will synchronize on the previous query barrier, and will
+ * thus not finish until that barrier has executed.
+ */
+void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
+				   bool only_on_cid_match, uint32_t cid)
+{
+	int ret = 0;
+	struct list_head validate_list;
+	struct ttm_validate_buffer pinned_val, query_val;
+	struct vmw_fence_obj *fence;
+
+	mutex_lock(&dev_priv->cmdbuf_mutex);
+
+	if (dev_priv->pinned_bo == NULL)
+		goto out_unlock;
+
+	if (only_on_cid_match && cid != dev_priv->query_cid)
+		goto out_unlock;
+
+	INIT_LIST_HEAD(&validate_list);
+
+	pinned_val.new_sync_obj_arg = (void *)(unsigned long)
+		DRM_VMW_FENCE_FLAG_EXEC;
+	pinned_val.bo = ttm_bo_reference(dev_priv->pinned_bo);
+	list_add_tail(&pinned_val.head, &validate_list);
+
+	query_val.new_sync_obj_arg = pinned_val.new_sync_obj_arg;
+	query_val.bo = ttm_bo_reference(dev_priv->dummy_query_bo);
+	list_add_tail(&query_val.head, &validate_list);
+
+	do {
+		ret = ttm_eu_reserve_buffers(&validate_list);
+	} while (ret == -ERESTARTSYS);
+
+	if (unlikely(ret != 0)) {
+		vmw_execbuf_unpin_panic(dev_priv);
+		goto out_no_reserve;
+	}
+
+	ret = vmw_fifo_emit_dummy_query(dev_priv, dev_priv->query_cid);
+	if (unlikely(ret != 0)) {
+		vmw_execbuf_unpin_panic(dev_priv);
+		goto out_no_emit;
+	}
+
+	vmw_bo_pin(dev_priv->pinned_bo, false);
+	vmw_bo_pin(dev_priv->dummy_query_bo, false);
+	dev_priv->dummy_query_bo_pinned = false;
+
+	(void) vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
+	ttm_eu_fence_buffer_objects(&validate_list, (void *) fence);
+
+	ttm_bo_unref(&query_val.bo);
+	ttm_bo_unref(&pinned_val.bo);
+	ttm_bo_unref(&dev_priv->pinned_bo);
+
+out_unlock:
+	mutex_unlock(&dev_priv->cmdbuf_mutex);
+	return;
+
+out_no_emit:
+	ttm_eu_backoff_reservation(&validate_list);
+out_no_reserve:
+	ttm_bo_unref(&query_val.bo);
+	ttm_bo_unref(&pinned_val.bo);
+	ttm_bo_unref(&dev_priv->pinned_bo);
+	mutex_unlock(&dev_priv->cmdbuf_mutex);
+}
+
+
+int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	int ret;
+
+	/*
+	 * This will allow us to extend the ioctl argument while
+	 * maintaining backwards compatibility:
+	 * We take different code paths depending on the value of
+	 * arg->version.
+	 */
+
+	if (unlikely(arg->version != DRM_VMW_EXECBUF_VERSION)) {
+		DRM_ERROR("Incorrect execbuf version.\n");
+		DRM_ERROR("You're running outdated experimental "
+			  "vmwgfx user-space drivers.");
+		return -EINVAL;
+	}
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = vmw_execbuf_process(file_priv, dev_priv,
+				  (void __user *)(unsigned long)arg->commands,
+				  NULL, arg->command_size, arg->throttle_us,
+				  (void __user *)(unsigned long)arg->fence_rep);
+
+	if (unlikely(ret != 0))
+		goto out_unlock;
+
+	vmw_kms_cursor_post_execbuf(dev_priv);
+
+out_unlock:
 	ttm_read_unlock(&vmaster->lock);
 	return ret;
 }
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,8 @@
  *
  **************************************************************************/
 
+#include <linux/export.h>
+
 #include "drmP.h"
 #include "vmwgfx_drv.h"
 
@@ -158,10 +160,14 @@
 {
 	struct vmw_fb_par *par = info->par;
 	struct vmw_private *vmw_priv = par->vmw_priv;
+	int ret;
+
+	ret = vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
+				 info->fix.line_length,
+				 par->bpp, par->depth);
+	if (ret)
+		return ret;
 
-	vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
-			   info->fix.line_length,
-			   par->bpp, par->depth);
 	if (vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) {
 		/* TODO check if pitch and offset changes */
 		vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
@@ -405,14 +411,14 @@
 	struct fb_info *info;
 	unsigned initial_width, initial_height;
 	unsigned fb_width, fb_height;
-	unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size;
+	unsigned fb_bpp, fb_depth, fb_offset, fb_pitch, fb_size;
 	int ret;
 
 	/* XXX These shouldn't be hardcoded. */
 	initial_width = 800;
 	initial_height = 600;
 
-	fb_bbp = 32;
+	fb_bpp = 32;
 	fb_depth = 24;
 
 	/* XXX As shouldn't these be as well. */
@@ -422,7 +428,7 @@
 	initial_width = min(fb_width, initial_width);
 	initial_height = min(fb_height, initial_height);
 
-	fb_pitch = fb_width * fb_bbp / 8;
+	fb_pitch = fb_width * fb_bpp / 8;
 	fb_size = fb_pitch * fb_height;
 	fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET);
 
@@ -437,7 +443,7 @@
 	par = info->par;
 	par->vmw_priv = vmw_priv;
 	par->depth = fb_depth;
-	par->bpp = fb_bbp;
+	par->bpp = fb_bpp;
 	par->vmalloc = NULL;
 	par->max_width = fb_width;
 	par->max_height = fb_height;
@@ -588,58 +594,6 @@
 	return 0;
 }
 
-int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv,
-			 struct vmw_dma_buffer *vmw_bo)
-{
-	struct ttm_buffer_object *bo = &vmw_bo->base;
-	int ret = 0;
-
-	ret = ttm_bo_reserve(bo, false, false, false, 0);
-	if (unlikely(ret != 0))
-		return ret;
-
-	ret = ttm_bo_validate(bo, &vmw_sys_placement, false, false, false);
-	ttm_bo_unreserve(bo);
-
-	return ret;
-}
-
-int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
-				struct vmw_dma_buffer *vmw_bo)
-{
-	struct ttm_buffer_object *bo = &vmw_bo->base;
-	struct ttm_placement ne_placement = vmw_vram_ne_placement;
-	int ret = 0;
-
-	ne_placement.lpfn = bo->num_pages;
-
-	/* interuptable? */
-	ret = ttm_write_lock(&vmw_priv->active_master->lock, false);
-	if (unlikely(ret != 0))
-		return ret;
-
-	ret = ttm_bo_reserve(bo, false, false, false, 0);
-	if (unlikely(ret != 0))
-		goto err_unlock;
-
-	if (bo->mem.mem_type == TTM_PL_VRAM &&
-	    bo->mem.start < bo->num_pages &&
-	    bo->mem.start > 0)
-		(void) ttm_bo_validate(bo, &vmw_sys_placement, false,
-				       false, false);
-
-	ret = ttm_bo_validate(bo, &ne_placement, false, false, false);
-
-	/* Could probably bug on */
-	WARN_ON(bo->offset != 0);
-
-	ttm_bo_unreserve(bo);
-err_unlock:
-	ttm_write_unlock(&vmw_priv->active_master->lock);
-
-	return ret;
-}
-
 int vmw_fb_off(struct vmw_private *vmw_priv)
 {
 	struct fb_info *info;
@@ -661,7 +615,7 @@
 	par->bo_ptr = NULL;
 	ttm_bo_kunmap(&par->map);
 
-	vmw_dmabuf_from_vram(vmw_priv, par->vmw_bo);
+	vmw_dmabuf_unpin(vmw_priv, par->vmw_bo, false);
 
 	return 0;
 }
@@ -687,7 +641,7 @@
 	/* Make sure that all overlays are stoped when we take over */
 	vmw_overlay_stop_all(vmw_priv);
 
-	ret = vmw_dmabuf_to_start_of_vram(vmw_priv, par->vmw_bo);
+	ret = vmw_dmabuf_to_start_of_vram(vmw_priv, par->vmw_bo, true, false);
 	if (unlikely(ret != 0)) {
 		DRM_ERROR("could not move buffer to start of VRAM\n");
 		goto err_no_buffer;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 /**************************************************************************
  *
- * Copyright (C) 2010 VMware, Inc., Palo Alto, CA., USA
+ * Copyright Â© 2011 VMware, Inc., Palo Alto, CA., USA
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -25,149 +25,1100 @@
  *
  **************************************************************************/
 
-
+#include "drmP.h"
 #include "vmwgfx_drv.h"
 
-struct vmw_fence {
-	struct list_head head;
-	uint32_t sequence;
-	struct timespec submitted;
+#define VMW_FENCE_WRAP (1 << 31)
+
+struct vmw_fence_manager {
+	int num_fence_objects;
+	struct vmw_private *dev_priv;
+	spinlock_t lock;
+	struct list_head fence_list;
+	struct work_struct work;
+	u32 user_fence_size;
+	u32 fence_size;
+	u32 event_fence_action_size;
+	bool fifo_down;
+	struct list_head cleanup_list;
+	uint32_t pending_actions[VMW_ACTION_MAX];
+	struct mutex goal_irq_mutex;
+	bool goal_irq_on; /* Protected by @goal_irq_mutex */
+	bool seqno_valid; /* Protected by @lock, and may not be set to true
+			     without the @goal_irq_mutex held. */
 };
 
-void vmw_fence_queue_init(struct vmw_fence_queue *queue)
+struct vmw_user_fence {
+	struct ttm_base_object base;
+	struct vmw_fence_obj fence;
+};
+
+/**
+ * struct vmw_event_fence_action - fence action that delivers a drm event.
+ *
+ * @e: A struct drm_pending_event that controls the event delivery.
+ * @action: A struct vmw_fence_action to hook up to a fence.
+ * @fence: A referenced pointer to the fence to keep it alive while @action
+ * hangs on it.
+ * @dev: Pointer to a struct drm_device so we can access the event stuff.
+ * @kref: Both @e and @action has destructors, so we need to refcount.
+ * @size: Size accounted for this object.
+ * @tv_sec: If non-null, the variable pointed to will be assigned
+ * current time tv_sec val when the fence signals.
+ * @tv_usec: Must be set if @tv_sec is set, and the variable pointed to will
+ * be assigned the current time tv_usec val when the fence signals.
+ */
+struct vmw_event_fence_action {
+	struct drm_pending_event e;
+	struct vmw_fence_action action;
+	struct vmw_fence_obj *fence;
+	struct drm_device *dev;
+	struct kref kref;
+	uint32_t size;
+	uint32_t *tv_sec;
+	uint32_t *tv_usec;
+};
+
+/**
+ * Note on fencing subsystem usage of irqs:
+ * Typically the vmw_fences_update function is called
+ *
+ * a) When a new fence seqno has been submitted by the fifo code.
+ * b) On-demand when we have waiters. Sleeping waiters will switch on the
+ * ANY_FENCE irq and call vmw_fences_update function each time an ANY_FENCE
+ * irq is received. When the last fence waiter is gone, that IRQ is masked
+ * away.
+ *
+ * In situations where there are no waiters and we don't submit any new fences,
+ * fence objects may not be signaled. This is perfectly OK, since there are
+ * no consumers of the signaled data, but that is NOT ok when there are fence
+ * actions attached to a fence. The fencing subsystem then makes use of the
+ * FENCE_GOAL irq and sets the fence goal seqno to that of the next fence
+ * which has an action attached, and each time vmw_fences_update is called,
+ * the subsystem makes sure the fence goal seqno is updated.
+ *
+ * The fence goal seqno irq is on as long as there are unsignaled fence
+ * objects with actions attached to them.
+ */
+
+static void vmw_fence_obj_destroy_locked(struct kref *kref)
 {
-	INIT_LIST_HEAD(&queue->head);
-	queue->lag = ns_to_timespec(0);
-	getrawmonotonic(&queue->lag_time);
-	spin_lock_init(&queue->lock);
+	struct vmw_fence_obj *fence =
+		container_of(kref, struct vmw_fence_obj, kref);
+
+	struct vmw_fence_manager *fman = fence->fman;
+	unsigned int num_fences;
+
+	list_del_init(&fence->head);
+	num_fences = --fman->num_fence_objects;
+	spin_unlock_irq(&fman->lock);
+	if (fence->destroy)
+		fence->destroy(fence);
+	else
+		kfree(fence);
+
+	spin_lock_irq(&fman->lock);
 }
 
-void vmw_fence_queue_takedown(struct vmw_fence_queue *queue)
+
+/**
+ * Execute signal actions on fences recently signaled.
+ * This is done from a workqueue so we don't have to execute
+ * signal actions from atomic context.
+ */
+
+static void vmw_fence_work_func(struct work_struct *work)
 {
-	struct vmw_fence *fence, *next;
+	struct vmw_fence_manager *fman =
+		container_of(work, struct vmw_fence_manager, work);
+	struct list_head list;
+	struct vmw_fence_action *action, *next_action;
+	bool seqno_valid;
 
-	spin_lock(&queue->lock);
-	list_for_each_entry_safe(fence, next, &queue->head, head) {
-		kfree(fence);
-	}
-	spin_unlock(&queue->lock);
+	do {
+		INIT_LIST_HEAD(&list);
+		mutex_lock(&fman->goal_irq_mutex);
+
+		spin_lock_irq(&fman->lock);
+		list_splice_init(&fman->cleanup_list, &list);
+		seqno_valid = fman->seqno_valid;
+		spin_unlock_irq(&fman->lock);
+
+		if (!seqno_valid && fman->goal_irq_on) {
+			fman->goal_irq_on = false;
+			vmw_goal_waiter_remove(fman->dev_priv);
+		}
+		mutex_unlock(&fman->goal_irq_mutex);
+
+		if (list_empty(&list))
+			return;
+
+		/*
+		 * At this point, only we should be able to manipulate the
+		 * list heads of the actions we have on the private list.
+		 * hence fman::lock not held.
+		 */
+
+		list_for_each_entry_safe(action, next_action, &list, head) {
+			list_del_init(&action->head);
+			if (action->cleanup)
+				action->cleanup(action);
+		}
+	} while (1);
 }
 
-int vmw_fence_push(struct vmw_fence_queue *queue,
-		   uint32_t sequence)
+struct vmw_fence_manager *vmw_fence_manager_init(struct vmw_private *dev_priv)
 {
-	struct vmw_fence *fence = kmalloc(sizeof(*fence), GFP_KERNEL);
+	struct vmw_fence_manager *fman = kzalloc(sizeof(*fman), GFP_KERNEL);
 
-	if (unlikely(!fence))
-		return -ENOMEM;
+	if (unlikely(fman == NULL))
+		return NULL;
 
-	fence->sequence = sequence;
-	getrawmonotonic(&fence->submitted);
-	spin_lock(&queue->lock);
-	list_add_tail(&fence->head, &queue->head);
-	spin_unlock(&queue->lock);
+	fman->dev_priv = dev_priv;
+	spin_lock_init(&fman->lock);
+	INIT_LIST_HEAD(&fman->fence_list);
+	INIT_LIST_HEAD(&fman->cleanup_list);
+	INIT_WORK(&fman->work, &vmw_fence_work_func);
+	fman->fifo_down = true;
+	fman->user_fence_size = ttm_round_pot(sizeof(struct vmw_user_fence));
+	fman->fence_size = ttm_round_pot(sizeof(struct vmw_fence_obj));
+	fman->event_fence_action_size =
+		ttm_round_pot(sizeof(struct vmw_event_fence_action));
+	mutex_init(&fman->goal_irq_mutex);
 
-	return 0;
+	return fman;
 }
 
-int vmw_fence_pull(struct vmw_fence_queue *queue,
-		   uint32_t signaled_sequence)
+void vmw_fence_manager_takedown(struct vmw_fence_manager *fman)
 {
-	struct vmw_fence *fence, *next;
-	struct timespec now;
-	bool updated = false;
+	unsigned long irq_flags;
+	bool lists_empty;
 
-	spin_lock(&queue->lock);
-	getrawmonotonic(&now);
+	(void) cancel_work_sync(&fman->work);
 
-	if (list_empty(&queue->head)) {
-		queue->lag = ns_to_timespec(0);
-		queue->lag_time = now;
-		updated = true;
+	spin_lock_irqsave(&fman->lock, irq_flags);
+	lists_empty = list_empty(&fman->fence_list) &&
+		list_empty(&fman->cleanup_list);
+	spin_unlock_irqrestore(&fman->lock, irq_flags);
+
+	BUG_ON(!lists_empty);
+	kfree(fman);
+}
+
+static int vmw_fence_obj_init(struct vmw_fence_manager *fman,
+			      struct vmw_fence_obj *fence,
+			      u32 seqno,
+			      uint32_t mask,
+			      void (*destroy) (struct vmw_fence_obj *fence))
+{
+	unsigned long irq_flags;
+	unsigned int num_fences;
+	int ret = 0;
+
+	fence->seqno = seqno;
+	INIT_LIST_HEAD(&fence->seq_passed_actions);
+	fence->fman = fman;
+	fence->signaled = 0;
+	fence->signal_mask = mask;
+	kref_init(&fence->kref);
+	fence->destroy = destroy;
+	init_waitqueue_head(&fence->queue);
+
+	spin_lock_irqsave(&fman->lock, irq_flags);
+	if (unlikely(fman->fifo_down)) {
+		ret = -EBUSY;
 		goto out_unlock;
 	}
+	list_add_tail(&fence->head, &fman->fence_list);
+	num_fences = ++fman->num_fence_objects;
 
-	list_for_each_entry_safe(fence, next, &queue->head, head) {
-		if (signaled_sequence - fence->sequence > (1 << 30))
-			continue;
+out_unlock:
+	spin_unlock_irqrestore(&fman->lock, irq_flags);
+	return ret;
 
-		queue->lag = timespec_sub(now, fence->submitted);
-		queue->lag_time = now;
-		updated = true;
-		list_del(&fence->head);
-		kfree(fence);
+}
+
+struct vmw_fence_obj *vmw_fence_obj_reference(struct vmw_fence_obj *fence)
+{
+	if (unlikely(fence == NULL))
+		return NULL;
+
+	kref_get(&fence->kref);
+	return fence;
+}
+
+/**
+ * vmw_fence_obj_unreference
+ *
+ * Note that this function may not be entered with disabled irqs since
+ * it may re-enable them in the destroy function.
+ *
+ */
+void vmw_fence_obj_unreference(struct vmw_fence_obj **fence_p)
+{
+	struct vmw_fence_obj *fence = *fence_p;
+	struct vmw_fence_manager *fman;
+
+	if (unlikely(fence == NULL))
+		return;
+
+	fman = fence->fman;
+	*fence_p = NULL;
+	spin_lock_irq(&fman->lock);
+	BUG_ON(atomic_read(&fence->kref.refcount) == 0);
+	kref_put(&fence->kref, vmw_fence_obj_destroy_locked);
+	spin_unlock_irq(&fman->lock);
+}
+
+void vmw_fences_perform_actions(struct vmw_fence_manager *fman,
+				struct list_head *list)
+{
+	struct vmw_fence_action *action, *next_action;
+
+	list_for_each_entry_safe(action, next_action, list, head) {
+		list_del_init(&action->head);
+		fman->pending_actions[action->type]--;
+		if (action->seq_passed != NULL)
+			action->seq_passed(action);
+
+		/*
+		 * Add the cleanup action to the cleanup list so that
+		 * it will be performed by a worker task.
+		 */
+
+		list_add_tail(&action->head, &fman->cleanup_list);
 	}
+}
 
-out_unlock:
-	spin_unlock(&queue->lock);
+/**
+ * vmw_fence_goal_new_locked - Figure out a new device fence goal
+ * seqno if needed.
+ *
+ * @fman: Pointer to a fence manager.
+ * @passed_seqno: The seqno the device currently signals as passed.
+ *
+ * This function should be called with the fence manager lock held.
+ * It is typically called when we have a new passed_seqno, and
+ * we might need to update the fence goal. It checks to see whether
+ * the current fence goal has already passed, and, in that case,
+ * scans through all unsignaled fences to get the next fence object with an
+ * action attached, and sets the seqno of that fence as a new fence goal.
+ *
+ * returns true if the device goal seqno was updated. False otherwise.
+ */
+static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman,
+				      u32 passed_seqno)
+{
+	u32 goal_seqno;
+	__le32 __iomem *fifo_mem;
+	struct vmw_fence_obj *fence;
 
-	return (updated) ? 0 : -EBUSY;
+	if (likely(!fman->seqno_valid))
+		return false;
+
+	fifo_mem = fman->dev_priv->mmio_virt;
+	goal_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE_GOAL);
+	if (likely(passed_seqno - goal_seqno >= VMW_FENCE_WRAP))
+		return false;
+
+	fman->seqno_valid = false;
+	list_for_each_entry(fence, &fman->fence_list, head) {
+		if (!list_empty(&fence->seq_passed_actions)) {
+			fman->seqno_valid = true;
+			iowrite32(fence->seqno,
+				  fifo_mem + SVGA_FIFO_FENCE_GOAL);
+			break;
+		}
+	}
+
+	return true;
 }
 
-static struct timespec vmw_timespec_add(struct timespec t1,
-					struct timespec t2)
+
+/**
+ * vmw_fence_goal_check_locked - Replace the device fence goal seqno if
+ * needed.
+ *
+ * @fence: Pointer to a struct vmw_fence_obj the seqno of which should be
+ * considered as a device fence goal.
+ *
+ * This function should be called with the fence manager lock held.
+ * It is typically called when an action has been attached to a fence to
+ * check whether the seqno of that fence should be used for a fence
+ * goal interrupt. This is typically needed if the current fence goal is
+ * invalid, or has a higher seqno than that of the current fence object.
+ *
+ * returns true if the device goal seqno was updated. False otherwise.
+ */
+static bool vmw_fence_goal_check_locked(struct vmw_fence_obj *fence)
 {
-	t1.tv_sec += t2.tv_sec;
-	t1.tv_nsec += t2.tv_nsec;
-	if (t1.tv_nsec >= 1000000000L) {
-		t1.tv_sec += 1;
-		t1.tv_nsec -= 1000000000L;
+	u32 goal_seqno;
+	__le32 __iomem *fifo_mem;
+
+	if (fence->signaled & DRM_VMW_FENCE_FLAG_EXEC)
+		return false;
+
+	fifo_mem = fence->fman->dev_priv->mmio_virt;
+	goal_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE_GOAL);
+	if (likely(fence->fman->seqno_valid &&
+		   goal_seqno - fence->seqno < VMW_FENCE_WRAP))
+		return false;
+
+	iowrite32(fence->seqno, fifo_mem + SVGA_FIFO_FENCE_GOAL);
+	fence->fman->seqno_valid = true;
+
+	return true;
+}
+
+void vmw_fences_update(struct vmw_fence_manager *fman)
+{
+	unsigned long flags;
+	struct vmw_fence_obj *fence, *next_fence;
+	struct list_head action_list;
+	bool needs_rerun;
+	uint32_t seqno, new_seqno;
+	__le32 __iomem *fifo_mem = fman->dev_priv->mmio_virt;
+
+	seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+rerun:
+	spin_lock_irqsave(&fman->lock, flags);
+	list_for_each_entry_safe(fence, next_fence, &fman->fence_list, head) {
+		if (seqno - fence->seqno < VMW_FENCE_WRAP) {
+			list_del_init(&fence->head);
+			fence->signaled |= DRM_VMW_FENCE_FLAG_EXEC;
+			INIT_LIST_HEAD(&action_list);
+			list_splice_init(&fence->seq_passed_actions,
+					 &action_list);
+			vmw_fences_perform_actions(fman, &action_list);
+			wake_up_all(&fence->queue);
+		} else
+			break;
 	}
 
-	return t1;
+	needs_rerun = vmw_fence_goal_new_locked(fman, seqno);
+
+	if (!list_empty(&fman->cleanup_list))
+		(void) schedule_work(&fman->work);
+	spin_unlock_irqrestore(&fman->lock, flags);
+
+	/*
+	 * Rerun if the fence goal seqno was updated, and the
+	 * hardware might have raced with that update, so that
+	 * we missed a fence_goal irq.
+	 */
+
+	if (unlikely(needs_rerun)) {
+		new_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+		if (new_seqno != seqno) {
+			seqno = new_seqno;
+			goto rerun;
+		}
+	}
 }
 
-static struct timespec vmw_fifo_lag(struct vmw_fence_queue *queue)
+bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence,
+			    uint32_t flags)
 {
-	struct timespec now;
+	struct vmw_fence_manager *fman = fence->fman;
+	unsigned long irq_flags;
+	uint32_t signaled;
 
-	spin_lock(&queue->lock);
-	getrawmonotonic(&now);
-	queue->lag = vmw_timespec_add(queue->lag,
-				      timespec_sub(now, queue->lag_time));
-	queue->lag_time = now;
-	spin_unlock(&queue->lock);
-	return queue->lag;
+	spin_lock_irqsave(&fman->lock, irq_flags);
+	signaled = fence->signaled;
+	spin_unlock_irqrestore(&fman->lock, irq_flags);
+
+	flags &= fence->signal_mask;
+	if ((signaled & flags) == flags)
+		return 1;
+
+	if ((signaled & DRM_VMW_FENCE_FLAG_EXEC) == 0)
+		vmw_fences_update(fman);
+
+	spin_lock_irqsave(&fman->lock, irq_flags);
+	signaled = fence->signaled;
+	spin_unlock_irqrestore(&fman->lock, irq_flags);
+
+	return ((signaled & flags) == flags);
 }
 
+int vmw_fence_obj_wait(struct vmw_fence_obj *fence,
+		       uint32_t flags, bool lazy,
+		       bool interruptible, unsigned long timeout)
+{
+	struct vmw_private *dev_priv = fence->fman->dev_priv;
+	long ret;
+
+	if (likely(vmw_fence_obj_signaled(fence, flags)))
+		return 0;
 
-static bool vmw_lag_lt(struct vmw_fence_queue *queue,
-		       uint32_t us)
+	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
+	vmw_seqno_waiter_add(dev_priv);
+
+	if (interruptible)
+		ret = wait_event_interruptible_timeout
+			(fence->queue,
+			 vmw_fence_obj_signaled(fence, flags),
+			 timeout);
+	else
+		ret = wait_event_timeout
+			(fence->queue,
+			 vmw_fence_obj_signaled(fence, flags),
+			 timeout);
+
+	vmw_seqno_waiter_remove(dev_priv);
+
+	if (unlikely(ret == 0))
+		ret = -EBUSY;
+	else if (likely(ret > 0))
+		ret = 0;
+
+	return ret;
+}
+
+void vmw_fence_obj_flush(struct vmw_fence_obj *fence)
 {
-	struct timespec lag, cond;
+	struct vmw_private *dev_priv = fence->fman->dev_priv;
 
-	cond = ns_to_timespec((s64) us * 1000);
-	lag = vmw_fifo_lag(queue);
-	return (timespec_compare(&lag, &cond) < 1);
+	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
 }
 
-int vmw_wait_lag(struct vmw_private *dev_priv,
-		 struct vmw_fence_queue *queue, uint32_t us)
+static void vmw_fence_destroy(struct vmw_fence_obj *fence)
 {
-	struct vmw_fence *fence;
-	uint32_t sequence;
+	struct vmw_fence_manager *fman = fence->fman;
+
+	kfree(fence);
+	/*
+	 * Free kernel space accounting.
+	 */
+	ttm_mem_global_free(vmw_mem_glob(fman->dev_priv),
+			    fman->fence_size);
+}
+
+int vmw_fence_create(struct vmw_fence_manager *fman,
+		     uint32_t seqno,
+		     uint32_t mask,
+		     struct vmw_fence_obj **p_fence)
+{
+	struct ttm_mem_global *mem_glob = vmw_mem_glob(fman->dev_priv);
+	struct vmw_fence_obj *fence;
 	int ret;
 
-	while (!vmw_lag_lt(queue, us)) {
-		spin_lock(&queue->lock);
-		if (list_empty(&queue->head))
-			sequence = atomic_read(&dev_priv->fence_seq);
-		else {
-			fence = list_first_entry(&queue->head,
-						 struct vmw_fence, head);
-			sequence = fence->sequence;
+	ret = ttm_mem_global_alloc(mem_glob, fman->fence_size,
+				   false, false);
+	if (unlikely(ret != 0))
+		return ret;
+
+	fence = kzalloc(sizeof(*fence), GFP_KERNEL);
+	if (unlikely(fence == NULL)) {
+		ret = -ENOMEM;
+		goto out_no_object;
+	}
+
+	ret = vmw_fence_obj_init(fman, fence, seqno, mask,
+				 vmw_fence_destroy);
+	if (unlikely(ret != 0))
+		goto out_err_init;
+
+	*p_fence = fence;
+	return 0;
+
+out_err_init:
+	kfree(fence);
+out_no_object:
+	ttm_mem_global_free(mem_glob, fman->fence_size);
+	return ret;
+}
+
+
+static void vmw_user_fence_destroy(struct vmw_fence_obj *fence)
+{
+	struct vmw_user_fence *ufence =
+		container_of(fence, struct vmw_user_fence, fence);
+	struct vmw_fence_manager *fman = fence->fman;
+
+	kfree(ufence);
+	/*
+	 * Free kernel space accounting.
+	 */
+	ttm_mem_global_free(vmw_mem_glob(fman->dev_priv),
+			    fman->user_fence_size);
+}
+
+static void vmw_user_fence_base_release(struct ttm_base_object **p_base)
+{
+	struct ttm_base_object *base = *p_base;
+	struct vmw_user_fence *ufence =
+		container_of(base, struct vmw_user_fence, base);
+	struct vmw_fence_obj *fence = &ufence->fence;
+
+	*p_base = NULL;
+	vmw_fence_obj_unreference(&fence);
+}
+
+int vmw_user_fence_create(struct drm_file *file_priv,
+			  struct vmw_fence_manager *fman,
+			  uint32_t seqno,
+			  uint32_t mask,
+			  struct vmw_fence_obj **p_fence,
+			  uint32_t *p_handle)
+{
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_user_fence *ufence;
+	struct vmw_fence_obj *tmp;
+	struct ttm_mem_global *mem_glob = vmw_mem_glob(fman->dev_priv);
+	int ret;
+
+	/*
+	 * Kernel memory space accounting, since this object may
+	 * be created by a user-space request.
+	 */
+
+	ret = ttm_mem_global_alloc(mem_glob, fman->user_fence_size,
+				   false, false);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ufence = kzalloc(sizeof(*ufence), GFP_KERNEL);
+	if (unlikely(ufence == NULL)) {
+		ret = -ENOMEM;
+		goto out_no_object;
+	}
+
+	ret = vmw_fence_obj_init(fman, &ufence->fence, seqno,
+				 mask, vmw_user_fence_destroy);
+	if (unlikely(ret != 0)) {
+		kfree(ufence);
+		goto out_no_object;
+	}
+
+	/*
+	 * The base object holds a reference which is freed in
+	 * vmw_user_fence_base_release.
+	 */
+	tmp = vmw_fence_obj_reference(&ufence->fence);
+	ret = ttm_base_object_init(tfile, &ufence->base, false,
+				   VMW_RES_FENCE,
+				   &vmw_user_fence_base_release, NULL);
+
+
+	if (unlikely(ret != 0)) {
+		/*
+		 * Free the base object's reference
+		 */
+		vmw_fence_obj_unreference(&tmp);
+		goto out_err;
+	}
+
+	*p_fence = &ufence->fence;
+	*p_handle = ufence->base.hash.key;
+
+	return 0;
+out_err:
+	tmp = &ufence->fence;
+	vmw_fence_obj_unreference(&tmp);
+out_no_object:
+	ttm_mem_global_free(mem_glob, fman->user_fence_size);
+	return ret;
+}
+
+
+/**
+ * vmw_fence_fifo_down - signal all unsignaled fence objects.
+ */
+
+void vmw_fence_fifo_down(struct vmw_fence_manager *fman)
+{
+	unsigned long irq_flags;
+	struct list_head action_list;
+	int ret;
+
+	/*
+	 * The list may be altered while we traverse it, so always
+	 * restart when we've released the fman->lock.
+	 */
+
+	spin_lock_irqsave(&fman->lock, irq_flags);
+	fman->fifo_down = true;
+	while (!list_empty(&fman->fence_list)) {
+		struct vmw_fence_obj *fence =
+			list_entry(fman->fence_list.prev, struct vmw_fence_obj,
+				   head);
+		kref_get(&fence->kref);
+		spin_unlock_irq(&fman->lock);
+
+		ret = vmw_fence_obj_wait(fence, fence->signal_mask,
+					 false, false,
+					 VMW_FENCE_WAIT_TIMEOUT);
+
+		if (unlikely(ret != 0)) {
+			list_del_init(&fence->head);
+			fence->signaled |= DRM_VMW_FENCE_FLAG_EXEC;
+			INIT_LIST_HEAD(&action_list);
+			list_splice_init(&fence->seq_passed_actions,
+					 &action_list);
+			vmw_fences_perform_actions(fman, &action_list);
+			wake_up_all(&fence->queue);
 		}
-		spin_unlock(&queue->lock);
 
-		ret = vmw_wait_fence(dev_priv, false, sequence, true,
-				     3*HZ);
+		spin_lock_irq(&fman->lock);
 
-		if (unlikely(ret != 0))
-			return ret;
+		BUG_ON(!list_empty(&fence->head));
+		kref_put(&fence->kref, vmw_fence_obj_destroy_locked);
+	}
+	spin_unlock_irqrestore(&fman->lock, irq_flags);
+}
 
-		(void) vmw_fence_pull(queue, sequence);
+void vmw_fence_fifo_up(struct vmw_fence_manager *fman)
+{
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&fman->lock, irq_flags);
+	fman->fifo_down = false;
+	spin_unlock_irqrestore(&fman->lock, irq_flags);
+}
+
+
+int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv)
+{
+	struct drm_vmw_fence_wait_arg *arg =
+	    (struct drm_vmw_fence_wait_arg *)data;
+	unsigned long timeout;
+	struct ttm_base_object *base;
+	struct vmw_fence_obj *fence;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	int ret;
+	uint64_t wait_timeout = ((uint64_t)arg->timeout_us * HZ);
+
+	/*
+	 * 64-bit division not present on 32-bit systems, so do an
+	 * approximation. (Divide by 1000000).
+	 */
+
+	wait_timeout = (wait_timeout >> 20) + (wait_timeout >> 24) -
+	  (wait_timeout >> 26);
+
+	if (!arg->cookie_valid) {
+		arg->cookie_valid = 1;
+		arg->kernel_cookie = jiffies + wait_timeout;
+	}
+
+	base = ttm_base_object_lookup(tfile, arg->handle);
+	if (unlikely(base == NULL)) {
+		printk(KERN_ERR "Wait invalid fence object handle "
+		       "0x%08lx.\n",
+		       (unsigned long)arg->handle);
+		return -EINVAL;
+	}
+
+	fence = &(container_of(base, struct vmw_user_fence, base)->fence);
+
+	timeout = jiffies;
+	if (time_after_eq(timeout, (unsigned long)arg->kernel_cookie)) {
+		ret = ((vmw_fence_obj_signaled(fence, arg->flags)) ?
+		       0 : -EBUSY);
+		goto out;
 	}
+
+	timeout = (unsigned long)arg->kernel_cookie - timeout;
+
+	ret = vmw_fence_obj_wait(fence, arg->flags, arg->lazy, true, timeout);
+
+out:
+	ttm_base_object_unref(&base);
+
+	/*
+	 * Optionally unref the fence object.
+	 */
+
+	if (ret == 0 && (arg->wait_options & DRM_VMW_WAIT_OPTION_UNREF))
+		return ttm_ref_object_base_unref(tfile, arg->handle,
+						 TTM_REF_USAGE);
+	return ret;
+}
+
+int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data,
+				 struct drm_file *file_priv)
+{
+	struct drm_vmw_fence_signaled_arg *arg =
+		(struct drm_vmw_fence_signaled_arg *) data;
+	struct ttm_base_object *base;
+	struct vmw_fence_obj *fence;
+	struct vmw_fence_manager *fman;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_private *dev_priv = vmw_priv(dev);
+
+	base = ttm_base_object_lookup(tfile, arg->handle);
+	if (unlikely(base == NULL)) {
+		printk(KERN_ERR "Fence signaled invalid fence object handle "
+		       "0x%08lx.\n",
+		       (unsigned long)arg->handle);
+		return -EINVAL;
+	}
+
+	fence = &(container_of(base, struct vmw_user_fence, base)->fence);
+	fman = fence->fman;
+
+	arg->signaled = vmw_fence_obj_signaled(fence, arg->flags);
+	spin_lock_irq(&fman->lock);
+
+	arg->signaled_flags = fence->signaled;
+	arg->passed_seqno = dev_priv->last_read_seqno;
+	spin_unlock_irq(&fman->lock);
+
+	ttm_base_object_unref(&base);
+
 	return 0;
 }
 
 
+int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv)
+{
+	struct drm_vmw_fence_arg *arg =
+		(struct drm_vmw_fence_arg *) data;
+
+	return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
+					 arg->handle,
+					 TTM_REF_USAGE);
+}
+
+/**
+ * vmw_event_fence_action_destroy
+ *
+ * @kref: The struct kref embedded in a struct vmw_event_fence_action.
+ *
+ * The vmw_event_fence_action destructor that may be called either after
+ * the fence action cleanup, or when the event is delivered.
+ * It frees both the vmw_event_fence_action struct and the actual
+ * event structure copied to user-space.
+ */
+static void vmw_event_fence_action_destroy(struct kref *kref)
+{
+	struct vmw_event_fence_action *eaction =
+		container_of(kref, struct vmw_event_fence_action, kref);
+	struct ttm_mem_global *mem_glob =
+		vmw_mem_glob(vmw_priv(eaction->dev));
+	uint32_t size = eaction->size;
+
+	kfree(eaction->e.event);
+	kfree(eaction);
+	ttm_mem_global_free(mem_glob, size);
+}
+
+
+/**
+ * vmw_event_fence_action_delivered
+ *
+ * @e: The struct drm_pending_event embedded in a struct
+ * vmw_event_fence_action.
+ *
+ * The struct drm_pending_event destructor that is called by drm
+ * once the event is delivered. Since we don't know whether this function
+ * will be called before or after the fence action destructor, we
+ * free a refcount and destroy if it becomes zero.
+ */
+static void vmw_event_fence_action_delivered(struct drm_pending_event *e)
+{
+	struct vmw_event_fence_action *eaction =
+		container_of(e, struct vmw_event_fence_action, e);
+
+	kref_put(&eaction->kref, vmw_event_fence_action_destroy);
+}
+
+
+/**
+ * vmw_event_fence_action_seq_passed
+ *
+ * @action: The struct vmw_fence_action embedded in a struct
+ * vmw_event_fence_action.
+ *
+ * This function is called when the seqno of the fence where @action is
+ * attached has passed. It queues the event on the submitter's event list.
+ * This function is always called from atomic context, and may be called
+ * from irq context. It ups a refcount reflecting that we now have two
+ * destructors.
+ */
+static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action)
+{
+	struct vmw_event_fence_action *eaction =
+		container_of(action, struct vmw_event_fence_action, action);
+	struct drm_device *dev = eaction->dev;
+	struct drm_file *file_priv = eaction->e.file_priv;
+	unsigned long irq_flags;
+
+	kref_get(&eaction->kref);
+	spin_lock_irqsave(&dev->event_lock, irq_flags);
+
+	if (likely(eaction->tv_sec != NULL)) {
+		struct timeval tv;
+
+		do_gettimeofday(&tv);
+		*eaction->tv_sec = tv.tv_sec;
+		*eaction->tv_usec = tv.tv_usec;
+	}
+
+	list_add_tail(&eaction->e.link, &file_priv->event_list);
+	wake_up_all(&file_priv->event_wait);
+	spin_unlock_irqrestore(&dev->event_lock, irq_flags);
+}
+
+/**
+ * vmw_event_fence_action_cleanup
+ *
+ * @action: The struct vmw_fence_action embedded in a struct
+ * vmw_event_fence_action.
+ *
+ * This function is the struct vmw_fence_action destructor. It's typically
+ * called from a workqueue.
+ */
+static void vmw_event_fence_action_cleanup(struct vmw_fence_action *action)
+{
+	struct vmw_event_fence_action *eaction =
+		container_of(action, struct vmw_event_fence_action, action);
+
+	vmw_fence_obj_unreference(&eaction->fence);
+	kref_put(&eaction->kref, vmw_event_fence_action_destroy);
+}
+
+
+/**
+ * vmw_fence_obj_add_action - Add an action to a fence object.
+ *
+ * @fence - The fence object.
+ * @action - The action to add.
+ *
+ * Note that the action callbacks may be executed before this function
+ * returns.
+ */
+void vmw_fence_obj_add_action(struct vmw_fence_obj *fence,
+			      struct vmw_fence_action *action)
+{
+	struct vmw_fence_manager *fman = fence->fman;
+	unsigned long irq_flags;
+	bool run_update = false;
+
+	mutex_lock(&fman->goal_irq_mutex);
+	spin_lock_irqsave(&fman->lock, irq_flags);
+
+	fman->pending_actions[action->type]++;
+	if (fence->signaled & DRM_VMW_FENCE_FLAG_EXEC) {
+		struct list_head action_list;
+
+		INIT_LIST_HEAD(&action_list);
+		list_add_tail(&action->head, &action_list);
+		vmw_fences_perform_actions(fman, &action_list);
+	} else {
+		list_add_tail(&action->head, &fence->seq_passed_actions);
+
+		/*
+		 * This function may set fman::seqno_valid, so it must
+		 * be run with the goal_irq_mutex held.
+		 */
+		run_update = vmw_fence_goal_check_locked(fence);
+	}
+
+	spin_unlock_irqrestore(&fman->lock, irq_flags);
+
+	if (run_update) {
+		if (!fman->goal_irq_on) {
+			fman->goal_irq_on = true;
+			vmw_goal_waiter_add(fman->dev_priv);
+		}
+		vmw_fences_update(fman);
+	}
+	mutex_unlock(&fman->goal_irq_mutex);
+
+}
+
+/**
+ * vmw_event_fence_action_create - Post an event for sending when a fence
+ * object seqno has passed.
+ *
+ * @file_priv: The file connection on which the event should be posted.
+ * @fence: The fence object on which to post the event.
+ * @event: Event to be posted. This event should've been alloced
+ * using k[mz]alloc, and should've been completely initialized.
+ * @interruptible: Interruptible waits if possible.
+ *
+ * As a side effect, the object pointed to by @event may have been
+ * freed when this function returns. If this function returns with
+ * an error code, the caller needs to free that object.
+ */
+
+int vmw_event_fence_action_create(struct drm_file *file_priv,
+				  struct vmw_fence_obj *fence,
+				  struct drm_event *event,
+				  uint32_t *tv_sec,
+				  uint32_t *tv_usec,
+				  bool interruptible)
+{
+	struct vmw_event_fence_action *eaction;
+	struct ttm_mem_global *mem_glob =
+		vmw_mem_glob(fence->fman->dev_priv);
+	struct vmw_fence_manager *fman = fence->fman;
+	uint32_t size = fman->event_fence_action_size +
+		ttm_round_pot(event->length);
+	int ret;
+
+	/*
+	 * Account for internal structure size as well as the
+	 * event size itself.
+	 */
+
+	ret = ttm_mem_global_alloc(mem_glob, size, false, interruptible);
+	if (unlikely(ret != 0))
+		return ret;
+
+	eaction = kzalloc(sizeof(*eaction), GFP_KERNEL);
+	if (unlikely(eaction == NULL)) {
+		ttm_mem_global_free(mem_glob, size);
+		return -ENOMEM;
+	}
+
+	eaction->e.event = event;
+	eaction->e.file_priv = file_priv;
+	eaction->e.destroy = vmw_event_fence_action_delivered;
+
+	eaction->action.seq_passed = vmw_event_fence_action_seq_passed;
+	eaction->action.cleanup = vmw_event_fence_action_cleanup;
+	eaction->action.type = VMW_ACTION_EVENT;
+
+	eaction->fence = vmw_fence_obj_reference(fence);
+	eaction->dev = fman->dev_priv->dev;
+	eaction->size = size;
+	eaction->tv_sec = tv_sec;
+	eaction->tv_usec = tv_usec;
+
+	kref_init(&eaction->kref);
+	vmw_fence_obj_add_action(fence, &eaction->action);
+
+	return 0;
+}
+
+int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct drm_vmw_fence_event_arg *arg =
+		(struct drm_vmw_fence_event_arg *) data;
+	struct vmw_fence_obj *fence = NULL;
+	struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
+	struct drm_vmw_fence_rep __user *user_fence_rep =
+		(struct drm_vmw_fence_rep __user *)(unsigned long)
+		arg->fence_rep;
+	uint32_t handle;
+	unsigned long irq_flags;
+	struct drm_vmw_event_fence *event;
+	int ret;
+
+	/*
+	 * Look up an existing fence object,
+	 * and if user-space wants a new reference,
+	 * add one.
+	 */
+	if (arg->handle) {
+		struct ttm_base_object *base =
+			ttm_base_object_lookup(vmw_fp->tfile, arg->handle);
+
+		if (unlikely(base == NULL)) {
+			DRM_ERROR("Fence event invalid fence object handle "
+				  "0x%08lx.\n",
+				  (unsigned long)arg->handle);
+			return -EINVAL;
+		}
+		fence = &(container_of(base, struct vmw_user_fence,
+				       base)->fence);
+		(void) vmw_fence_obj_reference(fence);
+
+		if (user_fence_rep != NULL) {
+			bool existed;
+
+			ret = ttm_ref_object_add(vmw_fp->tfile, base,
+						 TTM_REF_USAGE, &existed);
+			if (unlikely(ret != 0)) {
+				DRM_ERROR("Failed to reference a fence "
+					  "object.\n");
+				goto out_no_ref_obj;
+			}
+			handle = base->hash.key;
+		}
+		ttm_base_object_unref(&base);
+	}
+
+	/*
+	 * Create a new fence object.
+	 */
+	if (!fence) {
+		ret = vmw_execbuf_fence_commands(file_priv, dev_priv,
+						 &fence,
+						 (user_fence_rep) ?
+						 &handle : NULL);
+		if (unlikely(ret != 0)) {
+			DRM_ERROR("Fence event failed to create fence.\n");
+			return ret;
+		}
+	}
+
+	BUG_ON(fence == NULL);
+
+	spin_lock_irqsave(&dev->event_lock, irq_flags);
+
+	ret = (file_priv->event_space < sizeof(*event)) ? -EBUSY : 0;
+	if (likely(ret == 0))
+		file_priv->event_space -= sizeof(*event);
+
+	spin_unlock_irqrestore(&dev->event_lock, irq_flags);
+
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed to allocate event space for this file.\n");
+		goto out_no_event_space;
+	}
+
+	event = kzalloc(sizeof(*event), GFP_KERNEL);
+	if (unlikely(event == NULL)) {
+		DRM_ERROR("Failed to allocate an event.\n");
+		goto out_no_event;
+	}
+
+	event->base.type = DRM_VMW_EVENT_FENCE_SIGNALED;
+	event->base.length = sizeof(*event);
+	event->user_data = arg->user_data;
+
+	if (arg->flags & DRM_VMW_FE_FLAG_REQ_TIME)
+		ret = vmw_event_fence_action_create(file_priv, fence,
+						    &event->base,
+						    &event->tv_sec,
+						    &event->tv_usec,
+						    true);
+	else
+		ret = vmw_event_fence_action_create(file_priv, fence,
+						    &event->base,
+						    NULL,
+						    NULL,
+						    true);
+
+	if (unlikely(ret != 0)) {
+		if (ret != -ERESTARTSYS)
+			DRM_ERROR("Failed to attach event to fence.\n");
+		goto out_no_attach;
+	}
+
+	vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence,
+				    handle);
+	vmw_fence_obj_unreference(&fence);
+	return 0;
+out_no_attach:
+	kfree(event);
+out_no_event:
+	spin_lock_irqsave(&dev->event_lock, irq_flags);
+	file_priv->event_space += sizeof(*event);
+	spin_unlock_irqrestore(&dev->event_lock, irq_flags);
+out_no_event_space:
+	if (user_fence_rep != NULL)
+		ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
+					  handle, TTM_REF_USAGE);
+out_no_ref_obj:
+	vmw_fence_obj_unreference(&fence);
+	return ret;
+}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,113 @@
+/**************************************************************************
+ *
+ * Copyright Â© 2011 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef _VMWGFX_FENCE_H_
+
+#define VMW_FENCE_WAIT_TIMEOUT (5*HZ)
+
+struct vmw_private;
+
+struct vmw_fence_manager;
+
+/**
+ *
+ *
+ */
+enum vmw_action_type {
+	VMW_ACTION_EVENT = 0,
+	VMW_ACTION_MAX
+};
+
+struct vmw_fence_action {
+	struct list_head head;
+	enum vmw_action_type type;
+	void (*seq_passed) (struct vmw_fence_action *action);
+	void (*cleanup) (struct vmw_fence_action *action);
+};
+
+struct vmw_fence_obj {
+	struct kref kref;
+	u32 seqno;
+
+	struct vmw_fence_manager *fman;
+	struct list_head head;
+	uint32_t signaled;
+	uint32_t signal_mask;
+	struct list_head seq_passed_actions;
+	void (*destroy)(struct vmw_fence_obj *fence);
+	wait_queue_head_t queue;
+};
+
+extern struct vmw_fence_manager *
+vmw_fence_manager_init(struct vmw_private *dev_priv);
+
+extern void vmw_fence_manager_takedown(struct vmw_fence_manager *fman);
+
+extern void vmw_fence_obj_unreference(struct vmw_fence_obj **fence_p);
+
+extern struct vmw_fence_obj *
+vmw_fence_obj_reference(struct vmw_fence_obj *fence);
+
+extern void vmw_fences_update(struct vmw_fence_manager *fman);
+
+extern bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence,
+				   uint32_t flags);
+
+extern int vmw_fence_obj_wait(struct vmw_fence_obj *fence, uint32_t flags,
+			      bool lazy,
+			      bool interruptible, unsigned long timeout);
+
+extern void vmw_fence_obj_flush(struct vmw_fence_obj *fence);
+
+extern int vmw_fence_create(struct vmw_fence_manager *fman,
+			    uint32_t seqno,
+			    uint32_t mask,
+			    struct vmw_fence_obj **p_fence);
+
+extern int vmw_user_fence_create(struct drm_file *file_priv,
+				 struct vmw_fence_manager *fman,
+				 uint32_t sequence,
+				 uint32_t mask,
+				 struct vmw_fence_obj **p_fence,
+				 uint32_t *p_handle);
+
+extern void vmw_fence_fifo_up(struct vmw_fence_manager *fman);
+
+extern void vmw_fence_fifo_down(struct vmw_fence_manager *fman);
+
+extern int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
+				    struct drm_file *file_priv);
+
+extern int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data,
+					struct drm_file *file_priv);
+
+extern int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data,
+				     struct drm_file *file_priv);
+extern int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
+				 struct drm_file *file_priv);
+
+#endif /* _VMWGFX_FENCE_H_ */
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 {
 	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
 	uint32_t fifo_min, hwversion;
+	const struct vmw_fifo_state *fifo = &dev_priv->fifo;
 
 	if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
 		return false;
@@ -41,11 +42,20 @@
 	if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
 		return false;
 
-	hwversion = ioread32(fifo_mem + SVGA_FIFO_3D_HWVERSION);
+	hwversion = ioread32(fifo_mem +
+			     ((fifo->capabilities &
+			       SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ?
+			      SVGA_FIFO_3D_HWVERSION_REVISED :
+			      SVGA_FIFO_3D_HWVERSION));
+
 	if (hwversion == 0)
 		return false;
 
-	if (hwversion < SVGA3D_HWVERSION_WS65_B1)
+	if (hwversion < SVGA3D_HWVERSION_WS8_B1)
+		return false;
+
+	/* Non-Screen Object path does not support surfaces */
+	if (!dev_priv->sou_priv)
 		return false;
 
 	return true;
@@ -72,22 +82,12 @@
 	uint32_t max;
 	uint32_t min;
 	uint32_t dummy;
-	int ret;
 
 	fifo->static_buffer_size = VMWGFX_FIFO_STATIC_SIZE;
 	fifo->static_buffer = vmalloc(fifo->static_buffer_size);
 	if (unlikely(fifo->static_buffer == NULL))
 		return -ENOMEM;
 
-	fifo->last_buffer_size = VMWGFX_FIFO_STATIC_SIZE;
-	fifo->last_data_size = 0;
-	fifo->last_buffer_add = false;
-	fifo->last_buffer = vmalloc(fifo->last_buffer_size);
-	if (unlikely(fifo->last_buffer == NULL)) {
-		ret = -ENOMEM;
-		goto out_err;
-	}
-
 	fifo->dynamic_buffer = NULL;
 	fifo->reserved_size = 0;
 	fifo->using_bounce_buffer = false;
@@ -137,14 +137,10 @@
 		 (unsigned int) min,
 		 (unsigned int) fifo->capabilities);
 
-	atomic_set(&dev_priv->fence_seq, dev_priv->last_read_sequence);
-	iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE);
-	vmw_fence_queue_init(&fifo->fence_queue);
+	atomic_set(&dev_priv->marker_seq, dev_priv->last_read_seqno);
+	iowrite32(dev_priv->last_read_seqno, fifo_mem + SVGA_FIFO_FENCE);
+	vmw_marker_queue_init(&fifo->marker_queue);
 	return vmw_fifo_send_fence(dev_priv, &dummy);
-out_err:
-	vfree(fifo->static_buffer);
-	fifo->static_buffer = NULL;
-	return ret;
 }
 
 void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason)
@@ -170,7 +166,7 @@
 	while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0)
 		vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
 
-	dev_priv->last_read_sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+	dev_priv->last_read_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
 
 	vmw_write(dev_priv, SVGA_REG_CONFIG_DONE,
 		  dev_priv->config_done_state);
@@ -180,12 +176,7 @@
 		  dev_priv->traces_state);
 
 	mutex_unlock(&dev_priv->hw_mutex);
-	vmw_fence_queue_takedown(&fifo->fence_queue);
-
-	if (likely(fifo->last_buffer != NULL)) {
-		vfree(fifo->last_buffer);
-		fifo->last_buffer = NULL;
-	}
+	vmw_marker_queue_takedown(&fifo->marker_queue);
 
 	if (likely(fifo->static_buffer != NULL)) {
 		vfree(fifo->static_buffer);
@@ -262,9 +253,8 @@
 		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
 		outl(SVGA_IRQFLAG_FIFO_PROGRESS,
 		     dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
-		vmw_write(dev_priv, SVGA_REG_IRQMASK,
-			  vmw_read(dev_priv, SVGA_REG_IRQMASK) |
-			  SVGA_IRQFLAG_FIFO_PROGRESS);
+		dev_priv->irq_mask |= SVGA_IRQFLAG_FIFO_PROGRESS;
+		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
 		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
 	}
 	mutex_unlock(&dev_priv->hw_mutex);
@@ -286,9 +276,8 @@
 	mutex_lock(&dev_priv->hw_mutex);
 	if (atomic_dec_and_test(&dev_priv->fifo_queue_waiters)) {
 		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
-		vmw_write(dev_priv, SVGA_REG_IRQMASK,
-			  vmw_read(dev_priv, SVGA_REG_IRQMASK) &
-			  ~SVGA_IRQFLAG_FIFO_PROGRESS);
+		dev_priv->irq_mask &= ~SVGA_IRQFLAG_FIFO_PROGRESS;
+		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
 		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
 	}
 	mutex_unlock(&dev_priv->hw_mutex);
@@ -296,6 +285,16 @@
 	return ret;
 }
 
+/**
+ * Reserve @bytes number of bytes in the fifo.
+ *
+ * This function will return NULL (error) on two conditions:
+ *  If it timeouts waiting for fifo space, or if @bytes is larger than the
+ *   available fifo space.
+ *
+ * Returns:
+ *   Pointer to the fifo, or null on error (possible hardware hang).
+ */
 void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes)
 {
 	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
@@ -466,7 +465,7 @@
 	mutex_unlock(&fifo_state->fifo_mutex);
 }
 
-int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence)
+int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *seqno)
 {
 	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
 	struct svga_fifo_cmd_fence *cmd_fence;
@@ -476,16 +475,16 @@
 
 	fm = vmw_fifo_reserve(dev_priv, bytes);
 	if (unlikely(fm == NULL)) {
-		*sequence = atomic_read(&dev_priv->fence_seq);
+		*seqno = atomic_read(&dev_priv->marker_seq);
 		ret = -ENOMEM;
-		(void)vmw_fallback_wait(dev_priv, false, true, *sequence,
+		(void)vmw_fallback_wait(dev_priv, false, true, *seqno,
 					false, 3*HZ);
 		goto out_err;
 	}
 
 	do {
-		*sequence = atomic_add_return(1, &dev_priv->fence_seq);
-	} while (*sequence == 0);
+		*seqno = atomic_add_return(1, &dev_priv->marker_seq);
+	} while (*seqno == 0);
 
 	if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE)) {
 
@@ -502,61 +501,68 @@
 	cmd_fence = (struct svga_fifo_cmd_fence *)
 	    ((unsigned long)fm + sizeof(__le32));
 
-	iowrite32(*sequence, &cmd_fence->fence);
-	fifo_state->last_buffer_add = true;
+	iowrite32(*seqno, &cmd_fence->fence);
 	vmw_fifo_commit(dev_priv, bytes);
-	fifo_state->last_buffer_add = false;
-	(void) vmw_fence_push(&fifo_state->fence_queue, *sequence);
-	vmw_update_sequence(dev_priv, fifo_state);
+	(void) vmw_marker_push(&fifo_state->marker_queue, *seqno);
+	vmw_update_seqno(dev_priv, fifo_state);
 
 out_err:
 	return ret;
 }
 
 /**
- * Map the first page of the FIFO read-only to user-space.
+ * vmw_fifo_emit_dummy_query - emits a dummy query to the fifo.
+ *
+ * @dev_priv: The device private structure.
+ * @cid: The hardware context id used for the query.
+ *
+ * This function is used to emit a dummy occlusion query with
+ * no primitives rendered between query begin and query end.
+ * It's used to provide a query barrier, in order to know that when
+ * this query is finished, all preceding queries are also finished.
+ *
+ * A Query results structure should have been initialized at the start
+ * of the dev_priv->dummy_query_bo buffer object. And that buffer object
+ * must also be either reserved or pinned when this function is called.
+ *
+ * Returns -ENOMEM on failure to reserve fifo space.
  */
-
-static int vmw_fifo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv,
+			      uint32_t cid)
 {
-	int ret;
-	unsigned long address = (unsigned long)vmf->virtual_address;
-
-	if (address != vma->vm_start)
-		return VM_FAULT_SIGBUS;
+	/*
+	 * A query wait without a preceding query end will
+	 * actually finish all queries for this cid
+	 * without writing to the query result structure.
+	 */
 
-	ret = vm_insert_pfn(vma, address, vma->vm_pgoff);
-	if (likely(ret == -EBUSY || ret == 0))
-		return VM_FAULT_NOPAGE;
-	else if (ret == -ENOMEM)
-		return VM_FAULT_OOM;
+	struct ttm_buffer_object *bo = dev_priv->dummy_query_bo;
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdWaitForQuery body;
+	} *cmd;
 
-	return VM_FAULT_SIGBUS;
-}
+	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
 
-static struct vm_operations_struct vmw_fifo_vm_ops = {
-	.fault = vmw_fifo_vm_fault,
-	.open = NULL,
-	.close = NULL
-};
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Out of fifo space for dummy query.\n");
+		return -ENOMEM;
+	}
 
-int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-	struct drm_file *file_priv;
-	struct vmw_private *dev_priv;
+	cmd->header.id = SVGA_3D_CMD_WAIT_FOR_QUERY;
+	cmd->header.size = sizeof(cmd->body);
+	cmd->body.cid = cid;
+	cmd->body.type = SVGA3D_QUERYTYPE_OCCLUSION;
 
-	file_priv = filp->private_data;
-	dev_priv = vmw_priv(file_priv->minor->dev);
+	if (bo->mem.mem_type == TTM_PL_VRAM) {
+		cmd->body.guestResult.gmrId = SVGA_GMR_FRAMEBUFFER;
+		cmd->body.guestResult.offset = bo->offset;
+	} else {
+		cmd->body.guestResult.gmrId = bo->mem.start;
+		cmd->body.guestResult.offset = 0;
+	}
 
-	if (vma->vm_pgoff != (dev_priv->mmio_start >> PAGE_SHIFT) ||
-	    (vma->vm_end - vma->vm_start) != PAGE_SIZE)
-		return -EINVAL;
+	vmw_fifo_commit(dev_priv, sizeof(*cmd));
 
-	vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
-	vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_SHARED;
-	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
-	vma->vm_page_prot = ttm_io_prot(TTM_PL_FLAG_UNCACHED,
-					vma->vm_page_prot);
-	vma->vm_ops = &vmw_fifo_vm_ops;
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 /**************************************************************************
  *
- * Copyright Â© 2009 VMware, Inc., Palo Alto, CA., USA
+ * Copyright Â© 2009-2011 VMware, Inc., Palo Alto, CA., USA
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -29,6 +29,77 @@
 #include "drmP.h"
 #include "ttm/ttm_bo_driver.h"
 
+#define VMW_PPN_SIZE sizeof(unsigned long)
+
+static int vmw_gmr2_bind(struct vmw_private *dev_priv,
+			 struct page *pages[],
+			 unsigned long num_pages,
+			 int gmr_id)
+{
+	SVGAFifoCmdDefineGMR2 define_cmd;
+	SVGAFifoCmdRemapGMR2 remap_cmd;
+	uint32_t define_size = sizeof(define_cmd) + 4;
+	uint32_t remap_size = VMW_PPN_SIZE * num_pages + sizeof(remap_cmd) + 4;
+	uint32_t *cmd;
+	uint32_t *cmd_orig;
+	uint32_t i;
+
+	cmd_orig = cmd = vmw_fifo_reserve(dev_priv, define_size + remap_size);
+	if (unlikely(cmd == NULL))
+		return -ENOMEM;
+
+	define_cmd.gmrId = gmr_id;
+	define_cmd.numPages = num_pages;
+
+	remap_cmd.gmrId = gmr_id;
+	remap_cmd.flags = (VMW_PPN_SIZE > sizeof(*cmd)) ?
+		SVGA_REMAP_GMR2_PPN64 : SVGA_REMAP_GMR2_PPN32;
+	remap_cmd.offsetPages = 0;
+	remap_cmd.numPages = num_pages;
+
+	*cmd++ = SVGA_CMD_DEFINE_GMR2;
+	memcpy(cmd, &define_cmd, sizeof(define_cmd));
+	cmd += sizeof(define_cmd) / sizeof(uint32);
+
+	*cmd++ = SVGA_CMD_REMAP_GMR2;
+	memcpy(cmd, &remap_cmd, sizeof(remap_cmd));
+	cmd += sizeof(remap_cmd) / sizeof(uint32);
+
+	for (i = 0; i < num_pages; ++i) {
+		if (VMW_PPN_SIZE > 4)
+			*cmd = page_to_pfn(*pages++);
+		else
+			*((uint64_t *)cmd) = page_to_pfn(*pages++);
+
+		cmd += VMW_PPN_SIZE / sizeof(*cmd);
+	}
+
+	vmw_fifo_commit(dev_priv, define_size + remap_size);
+
+	return 0;
+}
+
+static void vmw_gmr2_unbind(struct vmw_private *dev_priv,
+			    int gmr_id)
+{
+	SVGAFifoCmdDefineGMR2 define_cmd;
+	uint32_t define_size = sizeof(define_cmd) + 4;
+	uint32_t *cmd;
+
+	cmd = vmw_fifo_reserve(dev_priv, define_size);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("GMR2 unbind failed.\n");
+		return;
+	}
+	define_cmd.gmrId = gmr_id;
+	define_cmd.numPages = 0;
+
+	*cmd++ = SVGA_CMD_DEFINE_GMR2;
+	memcpy(cmd, &define_cmd, sizeof(define_cmd));
+
+	vmw_fifo_commit(dev_priv, define_size);
+}
+
 /**
  * FIXME: Adjust to the ttm lowmem / highmem storage to minimize
  * the number of used descriptors.
@@ -170,6 +241,9 @@
 	struct list_head desc_pages;
 	int ret;
 
+	if (likely(dev_priv->capabilities & SVGA_CAP_GMR2))
+		return vmw_gmr2_bind(dev_priv, pages, num_pages, gmr_id);
+
 	if (unlikely(!(dev_priv->capabilities & SVGA_CAP_GMR)))
 		return -EINVAL;
 
@@ -192,6 +266,11 @@
 
 void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id)
 {
+	if (likely(dev_priv->capabilities & SVGA_CAP_GMR2)) {
+		vmw_gmr2_unbind(dev_priv, gmr_id);
+		return;
+	}
+
 	mutex_lock(&dev_priv->hw_mutex);
 	vmw_write(dev_priv, SVGA_REG_GMR_ID, gmr_id);
 	wmb();
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,8 @@
 	spinlock_t lock;
 	struct ida gmr_ida;
 	uint32_t max_gmr_ids;
+	uint32_t max_gmr_pages;
+	uint32_t used_gmr_pages;
 };
 
 static int vmw_gmrid_man_get_node(struct ttm_mem_type_manager *man,
@@ -49,33 +51,50 @@
 {
 	struct vmwgfx_gmrid_man *gman =
 		(struct vmwgfx_gmrid_man *)man->priv;
-	int ret;
+	int ret = 0;
 	int id;
 
 	mem->mm_node = NULL;
 
-	do {
-		if (unlikely(ida_pre_get(&gman->gmr_ida, GFP_KERNEL) == 0))
-			return -ENOMEM;
+	spin_lock(&gman->lock);
 
+	if (gman->max_gmr_pages > 0) {
+		gman->used_gmr_pages += bo->num_pages;
+		if (unlikely(gman->used_gmr_pages > gman->max_gmr_pages))
+			goto out_err_locked;
+	}
+
+	do {
+		spin_unlock(&gman->lock);
+		if (unlikely(ida_pre_get(&gman->gmr_ida, GFP_KERNEL) == 0)) {
+			ret = -ENOMEM;
+			goto out_err;
+		}
 		spin_lock(&gman->lock);
-		ret = ida_get_new(&gman->gmr_ida, &id);
 
+		ret = ida_get_new(&gman->gmr_ida, &id);
 		if (unlikely(ret == 0 && id >= gman->max_gmr_ids)) {
 			ida_remove(&gman->gmr_ida, id);
-			spin_unlock(&gman->lock);
-			return 0;
+			ret = 0;
+			goto out_err_locked;
 		}
-
-		spin_unlock(&gman->lock);
-
 	} while (ret == -EAGAIN);
 
 	if (likely(ret == 0)) {
 		mem->mm_node = gman;
 		mem->start = id;
-	}
+		mem->num_pages = bo->num_pages;
+	} else
+		goto out_err_locked;
 
+	spin_unlock(&gman->lock);
+	return 0;
+
+out_err:
+	spin_lock(&gman->lock);
+out_err_locked:
+	gman->used_gmr_pages -= bo->num_pages;
+	spin_unlock(&gman->lock);
 	return ret;
 }
 
@@ -88,6 +107,7 @@
 	if (mem->mm_node) {
 		spin_lock(&gman->lock);
 		ida_remove(&gman->gmr_ida, mem->start);
+		gman->used_gmr_pages -= mem->num_pages;
 		spin_unlock(&gman->lock);
 		mem->mm_node = NULL;
 	}
@@ -96,6 +116,8 @@
 static int vmw_gmrid_man_init(struct ttm_mem_type_manager *man,
 			      unsigned long p_size)
 {
+	struct vmw_private *dev_priv =
+		container_of(man->bdev, struct vmw_private, bdev);
 	struct vmwgfx_gmrid_man *gman =
 		kzalloc(sizeof(*gman), GFP_KERNEL);
 
@@ -103,6 +125,8 @@
 		return -ENOMEM;
 
 	spin_lock_init(&gman->lock);
+	gman->max_gmr_pages = dev_priv->max_gmr_pages;
+	gman->used_gmr_pages = 0;
 	ida_init(&gman->gmr_ida);
 	gman->max_gmr_ids = p_size;
 	man->priv = (void *) gman;
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 
 #include "vmwgfx_drv.h"
 #include "vmwgfx_drm.h"
+#include "vmwgfx_kms.h"
 
 int vmw_getparam_ioctl(struct drm_device *dev, void *data,
 		       struct drm_file *file_priv)
@@ -45,9 +46,6 @@
 	case DRM_VMW_PARAM_3D:
 		param->value = vmw_fifo_have_3d(dev_priv) ? 1 : 0;
 		break;
-	case DRM_VMW_PARAM_FIFO_OFFSET:
-		param->value = dev_priv->mmio_start;
-		break;
 	case DRM_VMW_PARAM_HW_CAPS:
 		param->value = dev_priv->capabilities;
 		break;
@@ -57,6 +55,19 @@
 	case DRM_VMW_PARAM_MAX_FB_SIZE:
 		param->value = dev_priv->vram_size;
 		break;
+	case DRM_VMW_PARAM_FIFO_HW_VERSION:
+	{
+		__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+		const struct vmw_fifo_state *fifo = &dev_priv->fifo;
+
+		param->value =
+			ioread32(fifo_mem +
+				 ((fifo->capabilities &
+				   SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ?
+				  SVGA_FIFO_3D_HWVERSION_REVISED :
+				  SVGA_FIFO_3D_HWVERSION));
+		break;
+	}
 	default:
 		DRM_ERROR("Illegal vmwgfx get param request: %d\n",
 			  param->param);
@@ -66,25 +77,253 @@
 	return 0;
 }
 
-int vmw_fifo_debug_ioctl(struct drm_device *dev, void *data,
+
+int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv)
 {
+	struct drm_vmw_get_3d_cap_arg *arg =
+		(struct drm_vmw_get_3d_cap_arg *) data;
 	struct vmw_private *dev_priv = vmw_priv(dev);
-	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
-	struct drm_vmw_fifo_debug_arg *arg =
-	    (struct drm_vmw_fifo_debug_arg *)data;
-	__le32 __user *buffer = (__le32 __user *)
-	    (unsigned long)arg->debug_buffer;
+	uint32_t size;
+	__le32 __iomem *fifo_mem;
+	void __user *buffer = (void __user *)((unsigned long)(arg->buffer));
+	void *bounce;
+	int ret;
 
-	if (unlikely(fifo_state->last_buffer == NULL))
+	if (unlikely(arg->pad64 != 0)) {
+		DRM_ERROR("Illegal GET_3D_CAP argument.\n");
 		return -EINVAL;
+	}
 
-	if (arg->debug_buffer_size < fifo_state->last_data_size) {
-		arg->used_size = arg->debug_buffer_size;
-		arg->did_not_fit = 1;
-	} else {
-		arg->used_size = fifo_state->last_data_size;
-		arg->did_not_fit = 0;
+	size = (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1) << 2;
+
+	if (arg->max_size < size)
+		size = arg->max_size;
+
+	bounce = vmalloc(size);
+	if (unlikely(bounce == NULL)) {
+		DRM_ERROR("Failed to allocate bounce buffer for 3D caps.\n");
+		return -ENOMEM;
 	}
-	return copy_to_user(buffer, fifo_state->last_buffer, arg->used_size);
+
+	fifo_mem = dev_priv->mmio_virt;
+	memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
+
+	ret = copy_to_user(buffer, bounce, size);
+	vfree(bounce);
+
+	if (unlikely(ret != 0))
+		DRM_ERROR("Failed to report 3D caps info.\n");
+
+	return ret;
+}
+
+int vmw_present_ioctl(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
+{
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct drm_vmw_present_arg *arg =
+		(struct drm_vmw_present_arg *)data;
+	struct vmw_surface *surface;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	struct drm_vmw_rect __user *clips_ptr;
+	struct drm_vmw_rect *clips = NULL;
+	struct drm_mode_object *obj;
+	struct vmw_framebuffer *vfb;
+	uint32_t num_clips;
+	int ret;
+
+	num_clips = arg->num_clips;
+	clips_ptr = (struct drm_vmw_rect *)(unsigned long)arg->clips_ptr;
+
+	if (unlikely(num_clips == 0))
+		return 0;
+
+	if (clips_ptr == NULL) {
+		DRM_ERROR("Variable clips_ptr must be specified.\n");
+		ret = -EINVAL;
+		goto out_clips;
+	}
+
+	clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
+	if (clips == NULL) {
+		DRM_ERROR("Failed to allocate clip rect list.\n");
+		ret = -ENOMEM;
+		goto out_clips;
+	}
+
+	ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips));
+	if (ret) {
+		DRM_ERROR("Failed to copy clip rects from userspace.\n");
+		ret = -EFAULT;
+		goto out_no_copy;
+	}
+
+	ret = mutex_lock_interruptible(&dev->mode_config.mutex);
+	if (unlikely(ret != 0)) {
+		ret = -ERESTARTSYS;
+		goto out_no_mode_mutex;
+	}
+
+	obj = drm_mode_object_find(dev, arg->fb_id, DRM_MODE_OBJECT_FB);
+	if (!obj) {
+		DRM_ERROR("Invalid framebuffer id.\n");
+		ret = -EINVAL;
+		goto out_no_fb;
+	}
+	vfb = vmw_framebuffer_to_vfb(obj_to_fb(obj));
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		goto out_no_ttm_lock;
+
+	ret = vmw_user_surface_lookup_handle(dev_priv, tfile, arg->sid,
+					     &surface);
+	if (ret)
+		goto out_no_surface;
+
+	ret = vmw_kms_present(dev_priv, file_priv,
+			      vfb, surface, arg->sid,
+			      arg->dest_x, arg->dest_y,
+			      clips, num_clips);
+
+	/* vmw_user_surface_lookup takes one ref so does new_fb */
+	vmw_surface_unreference(&surface);
+
+out_no_surface:
+	ttm_read_unlock(&vmaster->lock);
+out_no_ttm_lock:
+out_no_fb:
+	mutex_unlock(&dev->mode_config.mutex);
+out_no_mode_mutex:
+out_no_copy:
+	kfree(clips);
+out_clips:
+	return ret;
+}
+
+int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
+			       struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct drm_vmw_present_readback_arg *arg =
+		(struct drm_vmw_present_readback_arg *)data;
+	struct drm_vmw_fence_rep __user *user_fence_rep =
+		(struct drm_vmw_fence_rep __user *)
+		(unsigned long)arg->fence_rep;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	struct drm_vmw_rect __user *clips_ptr;
+	struct drm_vmw_rect *clips = NULL;
+	struct drm_mode_object *obj;
+	struct vmw_framebuffer *vfb;
+	uint32_t num_clips;
+	int ret;
+
+	num_clips = arg->num_clips;
+	clips_ptr = (struct drm_vmw_rect *)(unsigned long)arg->clips_ptr;
+
+	if (unlikely(num_clips == 0))
+		return 0;
+
+	if (clips_ptr == NULL) {
+		DRM_ERROR("Argument clips_ptr must be specified.\n");
+		ret = -EINVAL;
+		goto out_clips;
+	}
+
+	clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
+	if (clips == NULL) {
+		DRM_ERROR("Failed to allocate clip rect list.\n");
+		ret = -ENOMEM;
+		goto out_clips;
+	}
+
+	ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips));
+	if (ret) {
+		DRM_ERROR("Failed to copy clip rects from userspace.\n");
+		ret = -EFAULT;
+		goto out_no_copy;
+	}
+
+	ret = mutex_lock_interruptible(&dev->mode_config.mutex);
+	if (unlikely(ret != 0)) {
+		ret = -ERESTARTSYS;
+		goto out_no_mode_mutex;
+	}
+
+	obj = drm_mode_object_find(dev, arg->fb_id, DRM_MODE_OBJECT_FB);
+	if (!obj) {
+		DRM_ERROR("Invalid framebuffer id.\n");
+		ret = -EINVAL;
+		goto out_no_fb;
+	}
+
+	vfb = vmw_framebuffer_to_vfb(obj_to_fb(obj));
+	if (!vfb->dmabuf) {
+		DRM_ERROR("Framebuffer not dmabuf backed.\n");
+		ret = -EINVAL;
+		goto out_no_fb;
+	}
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		goto out_no_ttm_lock;
+
+	ret = vmw_kms_readback(dev_priv, file_priv,
+			       vfb, user_fence_rep,
+			       clips, num_clips);
+
+	ttm_read_unlock(&vmaster->lock);
+out_no_ttm_lock:
+out_no_fb:
+	mutex_unlock(&dev->mode_config.mutex);
+out_no_mode_mutex:
+out_no_copy:
+	kfree(clips);
+out_clips:
+	return ret;
+}
+
+
+/**
+ * vmw_fops_poll - wrapper around the drm_poll function
+ *
+ * @filp: See the linux fops poll documentation.
+ * @wait: See the linux fops poll documentation.
+ *
+ * Wrapper around the drm_poll function that makes sure the device is
+ * processing the fifo if drm_poll decides to wait.
+ */
+unsigned int vmw_fops_poll(struct file *filp, struct poll_table_struct *wait)
+{
+	struct drm_file *file_priv = filp->private_data;
+	struct vmw_private *dev_priv =
+		vmw_priv(file_priv->minor->dev);
+
+	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
+	return drm_poll(filp, wait);
+}
+
+
+/**
+ * vmw_fops_read - wrapper around the drm_read function
+ *
+ * @filp: See the linux fops read documentation.
+ * @buffer: See the linux fops read documentation.
+ * @count: See the linux fops read documentation.
+ * offset: See the linux fops read documentation.
+ *
+ * Wrapper around the drm_read function that makes sure the device is
+ * processing the fifo if drm_read decides to wait.
+ */
+ssize_t vmw_fops_read(struct file *filp, char __user *buffer,
+		      size_t count, loff_t *offset)
+{
+	struct drm_file *file_priv = filp->private_data;
+	struct vmw_private *dev_priv =
+		vmw_priv(file_priv->minor->dev);
+
+	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
+	return drm_read(filp, buffer, count, offset);
 }
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,26 +34,33 @@
 {
 	struct drm_device *dev = (struct drm_device *)arg;
 	struct vmw_private *dev_priv = vmw_priv(dev);
-	uint32_t status;
+	uint32_t status, masked_status;
 
 	spin_lock(&dev_priv->irq_lock);
 	status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+	masked_status = status & dev_priv->irq_mask;
 	spin_unlock(&dev_priv->irq_lock);
 
-	if (status & SVGA_IRQFLAG_ANY_FENCE)
+	if (likely(status))
+		outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+
+	if (!masked_status)
+		return IRQ_NONE;
+
+	if (masked_status & (SVGA_IRQFLAG_ANY_FENCE |
+			     SVGA_IRQFLAG_FENCE_GOAL)) {
+		vmw_fences_update(dev_priv->fman);
 		wake_up_all(&dev_priv->fence_queue);
-	if (status & SVGA_IRQFLAG_FIFO_PROGRESS)
+	}
+
+	if (masked_status & SVGA_IRQFLAG_FIFO_PROGRESS)
 		wake_up_all(&dev_priv->fifo_queue);
 
-	if (likely(status)) {
-		outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
-		return IRQ_HANDLED;
-	}
 
-	return IRQ_NONE;
+	return IRQ_HANDLED;
 }
 
-static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t sequence)
+static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t seqno)
 {
 	uint32_t busy;
 
@@ -64,43 +71,43 @@
 	return (busy == 0);
 }
 
-void vmw_update_sequence(struct vmw_private *dev_priv,
+void vmw_update_seqno(struct vmw_private *dev_priv,
 			 struct vmw_fifo_state *fifo_state)
 {
 	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+	uint32_t seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
 
-	uint32_t sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
-
-	if (dev_priv->last_read_sequence != sequence) {
-		dev_priv->last_read_sequence = sequence;
-		vmw_fence_pull(&fifo_state->fence_queue, sequence);
+	if (dev_priv->last_read_seqno != seqno) {
+		dev_priv->last_read_seqno = seqno;
+		vmw_marker_pull(&fifo_state->marker_queue, seqno);
+		vmw_fences_update(dev_priv->fman);
 	}
 }
 
-bool vmw_fence_signaled(struct vmw_private *dev_priv,
-			uint32_t sequence)
+bool vmw_seqno_passed(struct vmw_private *dev_priv,
+			 uint32_t seqno)
 {
 	struct vmw_fifo_state *fifo_state;
 	bool ret;
 
-	if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
+	if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
 		return true;
 
 	fifo_state = &dev_priv->fifo;
-	vmw_update_sequence(dev_priv, fifo_state);
-	if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
+	vmw_update_seqno(dev_priv, fifo_state);
+	if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
 		return true;
 
 	if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE) &&
-	    vmw_fifo_idle(dev_priv, sequence))
+	    vmw_fifo_idle(dev_priv, seqno))
 		return true;
 
 	/**
-	 * Then check if the sequence is higher than what we've actually
+	 * Then check if the seqno is higher than what we've actually
 	 * emitted. Then the fence is stale and signaled.
 	 */
 
-	ret = ((atomic_read(&dev_priv->fence_seq) - sequence)
+	ret = ((atomic_read(&dev_priv->marker_seq) - seqno)
 	       > VMW_FENCE_WRAP);
 
 	return ret;
@@ -109,7 +116,7 @@
 int vmw_fallback_wait(struct vmw_private *dev_priv,
 		      bool lazy,
 		      bool fifo_idle,
-		      uint32_t sequence,
+		      uint32_t seqno,
 		      bool interruptible,
 		      unsigned long timeout)
 {
@@ -123,7 +130,7 @@
 	DEFINE_WAIT(__wait);
 
 	wait_condition = (fifo_idle) ? &vmw_fifo_idle :
-		&vmw_fence_signaled;
+		&vmw_seqno_passed;
 
 	/**
 	 * Block command submission while waiting for idle.
@@ -131,14 +138,14 @@
 
 	if (fifo_idle)
 		down_read(&fifo_state->rwsem);
-	signal_seq = atomic_read(&dev_priv->fence_seq);
+	signal_seq = atomic_read(&dev_priv->marker_seq);
 	ret = 0;
 
 	for (;;) {
 		prepare_to_wait(&dev_priv->fence_queue, &__wait,
 				(interruptible) ?
 				TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
-		if (wait_condition(dev_priv, sequence))
+		if (wait_condition(dev_priv, seqno))
 			break;
 		if (time_after_eq(jiffies, end_jiffies)) {
 			DRM_ERROR("SVGA device lockup.\n");
@@ -175,68 +182,110 @@
 	return ret;
 }
 
-int vmw_wait_fence(struct vmw_private *dev_priv,
-		   bool lazy, uint32_t sequence,
-		   bool interruptible, unsigned long timeout)
+void vmw_seqno_waiter_add(struct vmw_private *dev_priv)
+{
+	mutex_lock(&dev_priv->hw_mutex);
+	if (dev_priv->fence_queue_waiters++ == 0) {
+		unsigned long irq_flags;
+
+		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+		outl(SVGA_IRQFLAG_ANY_FENCE,
+		     dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+		dev_priv->irq_mask |= SVGA_IRQFLAG_ANY_FENCE;
+		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+	}
+	mutex_unlock(&dev_priv->hw_mutex);
+}
+
+void vmw_seqno_waiter_remove(struct vmw_private *dev_priv)
+{
+	mutex_lock(&dev_priv->hw_mutex);
+	if (--dev_priv->fence_queue_waiters == 0) {
+		unsigned long irq_flags;
+
+		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+		dev_priv->irq_mask &= ~SVGA_IRQFLAG_ANY_FENCE;
+		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+	}
+	mutex_unlock(&dev_priv->hw_mutex);
+}
+
+
+void vmw_goal_waiter_add(struct vmw_private *dev_priv)
+{
+	mutex_lock(&dev_priv->hw_mutex);
+	if (dev_priv->goal_queue_waiters++ == 0) {
+		unsigned long irq_flags;
+
+		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+		outl(SVGA_IRQFLAG_FENCE_GOAL,
+		     dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+		dev_priv->irq_mask |= SVGA_IRQFLAG_FENCE_GOAL;
+		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+	}
+	mutex_unlock(&dev_priv->hw_mutex);
+}
+
+void vmw_goal_waiter_remove(struct vmw_private *dev_priv)
+{
+	mutex_lock(&dev_priv->hw_mutex);
+	if (--dev_priv->goal_queue_waiters == 0) {
+		unsigned long irq_flags;
+
+		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+		dev_priv->irq_mask &= ~SVGA_IRQFLAG_FENCE_GOAL;
+		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+	}
+	mutex_unlock(&dev_priv->hw_mutex);
+}
+
+int vmw_wait_seqno(struct vmw_private *dev_priv,
+		      bool lazy, uint32_t seqno,
+		      bool interruptible, unsigned long timeout)
 {
 	long ret;
-	unsigned long irq_flags;
 	struct vmw_fifo_state *fifo = &dev_priv->fifo;
 
-	if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
+	if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
 		return 0;
 
-	if (likely(vmw_fence_signaled(dev_priv, sequence)))
+	if (likely(vmw_seqno_passed(dev_priv, seqno)))
 		return 0;
 
 	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
 
 	if (!(fifo->capabilities & SVGA_FIFO_CAP_FENCE))
-		return vmw_fallback_wait(dev_priv, lazy, true, sequence,
+		return vmw_fallback_wait(dev_priv, lazy, true, seqno,
 					 interruptible, timeout);
 
 	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
-		return vmw_fallback_wait(dev_priv, lazy, false, sequence,
+		return vmw_fallback_wait(dev_priv, lazy, false, seqno,
 					 interruptible, timeout);
 
-	mutex_lock(&dev_priv->hw_mutex);
-	if (atomic_add_return(1, &dev_priv->fence_queue_waiters) > 0) {
-		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
-		outl(SVGA_IRQFLAG_ANY_FENCE,
-		     dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
-		vmw_write(dev_priv, SVGA_REG_IRQMASK,
-			  vmw_read(dev_priv, SVGA_REG_IRQMASK) |
-			  SVGA_IRQFLAG_ANY_FENCE);
-		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
-	}
-	mutex_unlock(&dev_priv->hw_mutex);
+	vmw_seqno_waiter_add(dev_priv);
 
 	if (interruptible)
 		ret = wait_event_interruptible_timeout
 		    (dev_priv->fence_queue,
-		     vmw_fence_signaled(dev_priv, sequence),
+		     vmw_seqno_passed(dev_priv, seqno),
 		     timeout);
 	else
 		ret = wait_event_timeout
 		    (dev_priv->fence_queue,
-		     vmw_fence_signaled(dev_priv, sequence),
+		     vmw_seqno_passed(dev_priv, seqno),
 		     timeout);
 
+	vmw_seqno_waiter_remove(dev_priv);
+
 	if (unlikely(ret == 0))
 		ret = -EBUSY;
 	else if (likely(ret > 0))
 		ret = 0;
 
-	mutex_lock(&dev_priv->hw_mutex);
-	if (atomic_dec_and_test(&dev_priv->fence_queue_waiters)) {
-		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
-		vmw_write(dev_priv, SVGA_REG_IRQMASK,
-			  vmw_read(dev_priv, SVGA_REG_IRQMASK) &
-			  ~SVGA_IRQFLAG_ANY_FENCE);
-		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
-	}
-	mutex_unlock(&dev_priv->hw_mutex);
-
 	return ret;
 }
 
@@ -273,25 +322,3 @@
 	status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
 	outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
 }
-
-#define VMW_FENCE_WAIT_TIMEOUT 3*HZ;
-
-int vmw_fence_wait_ioctl(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv)
-{
-	struct drm_vmw_fence_wait_arg *arg =
-	    (struct drm_vmw_fence_wait_arg *)data;
-	unsigned long timeout;
-
-	if (!arg->cookie_valid) {
-		arg->cookie_valid = 1;
-		arg->kernel_cookie = jiffies + VMW_FENCE_WAIT_TIMEOUT;
-	}
-
-	timeout = jiffies;
-	if (time_after_eq(timeout, (unsigned long)arg->kernel_cookie))
-		return -EBUSY;
-
-	timeout = (unsigned long)arg->kernel_cookie - timeout;
-	return vmw_wait_fence(vmw_priv(dev), true, arg->sequence, true, timeout);
-}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,11 +27,47 @@
 
 #include "vmwgfx_kms.h"
 
+
 /* Might need a hrtimer here? */
 #define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1)
 
-static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb);
-static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb);
+
+struct vmw_clip_rect {
+	int x1, x2, y1, y2;
+};
+
+/**
+ * Clip @num_rects number of @rects against @clip storing the
+ * results in @out_rects and the number of passed rects in @out_num.
+ */
+void vmw_clip_cliprects(struct drm_clip_rect *rects,
+			int num_rects,
+			struct vmw_clip_rect clip,
+			SVGASignedRect *out_rects,
+			int *out_num)
+{
+	int i, k;
+
+	for (i = 0, k = 0; i < num_rects; i++) {
+		int x1 = max_t(int, clip.x1, rects[i].x1);
+		int y1 = max_t(int, clip.y1, rects[i].y1);
+		int x2 = min_t(int, clip.x2, rects[i].x2);
+		int y2 = min_t(int, clip.y2, rects[i].y2);
+
+		if (x1 >= x2)
+			continue;
+		if (y1 >= y2)
+			continue;
+
+		out_rects[k].left   = x1;
+		out_rects[k].top    = y1;
+		out_rects[k].right  = x2;
+		out_rects[k].bottom = y2;
+		k++;
+	}
+
+	*out_num = k;
+}
 
 void vmw_display_unit_cleanup(struct vmw_display_unit *du)
 {
@@ -84,6 +120,43 @@
 	return 0;
 }
 
+int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
+			     struct vmw_dma_buffer *dmabuf,
+			     u32 width, u32 height,
+			     u32 hotspotX, u32 hotspotY)
+{
+	struct ttm_bo_kmap_obj map;
+	unsigned long kmap_offset;
+	unsigned long kmap_num;
+	void *virtual;
+	bool dummy;
+	int ret;
+
+	kmap_offset = 0;
+	kmap_num = (width*height*4 + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+	ret = ttm_bo_reserve(&dmabuf->base, true, false, false, 0);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("reserve failed\n");
+		return -EINVAL;
+	}
+
+	ret = ttm_bo_kmap(&dmabuf->base, kmap_offset, kmap_num, &map);
+	if (unlikely(ret != 0))
+		goto err_unreserve;
+
+	virtual = ttm_kmap_obj_virtual(&map, &dummy);
+	ret = vmw_cursor_update_image(dev_priv, virtual, width, height,
+				      hotspotX, hotspotY);
+
+	ttm_bo_kunmap(&map);
+err_unreserve:
+	ttm_bo_unreserve(&dmabuf->base);
+
+	return ret;
+}
+
+
 void vmw_cursor_update_position(struct vmw_private *dev_priv,
 				bool show, int x, int y)
 {
@@ -107,24 +180,26 @@
 	struct vmw_dma_buffer *dmabuf = NULL;
 	int ret;
 
+	/* A lot of the code assumes this */
+	if (handle && (width != 64 || height != 64))
+		return -EINVAL;
+
 	if (handle) {
-		ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
-						     handle, &surface);
-		if (!ret) {
-			if (!surface->snooper.image) {
-				DRM_ERROR("surface not suitable for cursor\n");
-				return -EINVAL;
-			}
-		} else {
-			ret = vmw_user_dmabuf_lookup(tfile,
-						     handle, &dmabuf);
-			if (ret) {
-				DRM_ERROR("failed to find surface or dmabuf: %i\n", ret);
-				return -EINVAL;
-			}
+		ret = vmw_user_lookup_handle(dev_priv, tfile,
+					     handle, &surface, &dmabuf);
+		if (ret) {
+			DRM_ERROR("failed to find surface or dmabuf: %i\n", ret);
+			return -EINVAL;
 		}
 	}
 
+	/* need to do this before taking down old image */
+	if (surface && !surface->snooper.image) {
+		DRM_ERROR("surface not suitable for cursor\n");
+		vmw_surface_unreference(&surface);
+		return -EINVAL;
+	}
+
 	/* takedown old cursor */
 	if (du->cursor_surface) {
 		du->cursor_surface->snooper.crtc = NULL;
@@ -143,42 +218,19 @@
 		vmw_cursor_update_image(dev_priv, surface->snooper.image,
 					64, 64, du->hotspot_x, du->hotspot_y);
 	} else if (dmabuf) {
-		struct ttm_bo_kmap_obj map;
-		unsigned long kmap_offset;
-		unsigned long kmap_num;
-		void *virtual;
-		bool dummy;
-
 		/* vmw_user_surface_lookup takes one reference */
 		du->cursor_dmabuf = dmabuf;
 
-		kmap_offset = 0;
-		kmap_num = (64*64*4) >> PAGE_SHIFT;
-
-		ret = ttm_bo_reserve(&dmabuf->base, true, false, false, 0);
-		if (unlikely(ret != 0)) {
-			DRM_ERROR("reserve failed\n");
-			return -EINVAL;
-		}
-
-		ret = ttm_bo_kmap(&dmabuf->base, kmap_offset, kmap_num, &map);
-		if (unlikely(ret != 0))
-			goto err_unreserve;
-
-		virtual = ttm_kmap_obj_virtual(&map, &dummy);
-		vmw_cursor_update_image(dev_priv, virtual, 64, 64,
-					du->hotspot_x, du->hotspot_y);
-
-		ttm_bo_kunmap(&map);
-err_unreserve:
-		ttm_bo_unreserve(&dmabuf->base);
-
+		ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, width, height,
+					       du->hotspot_x, du->hotspot_y);
 	} else {
 		vmw_cursor_update_position(dev_priv, false, 0, 0);
 		return 0;
 	}
 
-	vmw_cursor_update_position(dev_priv, true, du->cursor_x, du->cursor_y);
+	vmw_cursor_update_position(dev_priv, true,
+				   du->cursor_x + du->hotspot_x,
+				   du->cursor_y + du->hotspot_y);
 
 	return 0;
 }
@@ -193,7 +245,8 @@
 	du->cursor_y = y + crtc->y;
 
 	vmw_cursor_update_position(dev_priv, shown,
-				   du->cursor_x, du->cursor_y);
+				   du->cursor_x + du->hotspot_x,
+				   du->cursor_y + du->hotspot_y);
 
 	return 0;
 }
@@ -214,7 +267,7 @@
 		SVGA3dCmdHeader header;
 		SVGA3dCmdSurfaceDMA dma;
 	} *cmd;
-	int ret;
+	int i, ret;
 
 	cmd = container_of(header, struct vmw_dma_cmd, header);
 
@@ -236,16 +289,19 @@
 	box_count = (cmd->header.size - sizeof(SVGA3dCmdSurfaceDMA)) /
 			sizeof(SVGA3dCopyBox);
 
-	if (cmd->dma.guest.pitch != (64 * 4) ||
-	    cmd->dma.guest.ptr.offset % PAGE_SIZE ||
+	if (cmd->dma.guest.ptr.offset % PAGE_SIZE ||
 	    box->x != 0    || box->y != 0    || box->z != 0    ||
 	    box->srcx != 0 || box->srcy != 0 || box->srcz != 0 ||
-	    box->w != 64   || box->h != 64   || box->d != 1    ||
-	    box_count != 1) {
+	    box->d != 1    || box_count != 1) {
 		/* TODO handle none page aligned offsets */
-		/* TODO handle partial uploads and pitch != 256 */
-		/* TODO handle more then one copy (size != 64) */
-		DRM_ERROR("lazy programmer, can't handle weird stuff\n");
+		/* TODO handle more dst & src != 0 */
+		/* TODO handle more then one copy */
+		DRM_ERROR("Cant snoop dma request for cursor!\n");
+		DRM_ERROR("(%u, %u, %u) (%u, %u, %u) (%ux%ux%u) %u %u\n",
+			  box->srcx, box->srcy, box->srcz,
+			  box->x, box->y, box->z,
+			  box->w, box->h, box->d, box_count,
+			  cmd->dma.guest.ptr.offset);
 		return;
 	}
 
@@ -264,7 +320,16 @@
 
 	virtual = ttm_kmap_obj_virtual(&map, &dummy);
 
-	memcpy(srf->snooper.image, virtual, 64*64*4);
+	if (box->w == 64 && cmd->dma.guest.pitch == 64*4) {
+		memcpy(srf->snooper.image, virtual, 64*64*4);
+	} else {
+		/* Image is unsigned pointer. */
+		for (i = 0; i < box->h; i++)
+			memcpy(srf->snooper.image + i * 64,
+			       virtual + i * cmd->dma.guest.pitch,
+			       box->w * 4);
+	}
+
 	srf->snooper.age++;
 
 	/* we can't call this function from this function since execbuf has
@@ -329,41 +394,10 @@
 	struct vmw_framebuffer base;
 	struct vmw_surface *surface;
 	struct vmw_dma_buffer *buffer;
-	struct delayed_work d_work;
-	struct mutex work_lock;
-	bool present_fs;
 	struct list_head head;
 	struct drm_master *master;
 };
 
-/**
- * vmw_kms_idle_workqueues - Flush workqueues on this master
- *
- * @vmaster - Pointer identifying the master, for the surfaces of which
- * we idle the dirty work queues.
- *
- * This function should be called with the ttm lock held in exclusive mode
- * to idle all dirty work queues before the fifo is taken down.
- *
- * The work task may actually requeue itself, but after the flush returns we're
- * sure that there's nothing to present, since the ttm lock is held in
- * exclusive mode, so the fifo will never get used.
- */
-
-void vmw_kms_idle_workqueues(struct vmw_master *vmaster)
-{
-	struct vmw_framebuffer_surface *entry;
-
-	mutex_lock(&vmaster->fb_surf_mutex);
-	list_for_each_entry(entry, &vmaster->fb_surf, head) {
-		if (cancel_delayed_work_sync(&entry->d_work))
-			(void) entry->d_work.work.func(&entry->d_work.work);
-
-		(void) cancel_delayed_work_sync(&entry->d_work);
-	}
-	mutex_unlock(&vmaster->fb_surf_mutex);
-}
-
 void vmw_framebuffer_surface_destroy(struct drm_framebuffer *framebuffer)
 {
 	struct vmw_framebuffer_surface *vfbs =
@@ -375,64 +409,157 @@
 	list_del(&vfbs->head);
 	mutex_unlock(&vmaster->fb_surf_mutex);
 
-	cancel_delayed_work_sync(&vfbs->d_work);
 	drm_master_put(&vfbs->master);
 	drm_framebuffer_cleanup(framebuffer);
 	vmw_surface_unreference(&vfbs->surface);
+	ttm_base_object_unref(&vfbs->base.user_obj);
 
 	kfree(vfbs);
 }
 
-static void vmw_framebuffer_present_fs_callback(struct work_struct *work)
+static int do_surface_dirty_sou(struct vmw_private *dev_priv,
+				struct drm_file *file_priv,
+				struct vmw_framebuffer *framebuffer,
+				unsigned flags, unsigned color,
+				struct drm_clip_rect *clips,
+				unsigned num_clips, int inc)
 {
-	struct delayed_work *d_work =
-		container_of(work, struct delayed_work, work);
-	struct vmw_framebuffer_surface *vfbs =
-		container_of(d_work, struct vmw_framebuffer_surface, d_work);
-	struct vmw_surface *surf = vfbs->surface;
-	struct drm_framebuffer *framebuffer = &vfbs->base.base;
-	struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
+	struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS];
+	struct drm_clip_rect *clips_ptr;
+	struct drm_clip_rect *tmp;
+	struct drm_crtc *crtc;
+	size_t fifo_size;
+	int i, num_units;
+	int ret = 0; /* silence warning */
+	int left, right, top, bottom;
 
 	struct {
 		SVGA3dCmdHeader header;
-		SVGA3dCmdPresent body;
-		SVGA3dCopyRect cr;
+		SVGA3dCmdBlitSurfaceToScreen body;
 	} *cmd;
+	SVGASignedRect *blits;
 
-	/**
-	 * Strictly we should take the ttm_lock in read mode before accessing
-	 * the fifo, to make sure the fifo is present and up. However,
-	 * instead we flush all workqueues under the ttm lock in exclusive mode
-	 * before taking down the fifo.
-	 */
-	mutex_lock(&vfbs->work_lock);
-	if (!vfbs->present_fs)
-		goto out_unlock;
+	num_units = 0;
+	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list,
+			    head) {
+		if (crtc->fb != &framebuffer->base)
+			continue;
+		units[num_units++] = vmw_crtc_to_du(crtc);
+	}
 
-	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
-	if (unlikely(cmd == NULL))
-		goto out_resched;
+	BUG_ON(!clips || !num_clips);
 
-	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_PRESENT);
-	cmd->header.size = cpu_to_le32(sizeof(cmd->body) + sizeof(cmd->cr));
-	cmd->body.sid = cpu_to_le32(surf->res.id);
-	cmd->cr.x = cpu_to_le32(0);
-	cmd->cr.y = cpu_to_le32(0);
-	cmd->cr.srcx = cmd->cr.x;
-	cmd->cr.srcy = cmd->cr.y;
-	cmd->cr.w = cpu_to_le32(framebuffer->width);
-	cmd->cr.h = cpu_to_le32(framebuffer->height);
-	vfbs->present_fs = false;
-	vmw_fifo_commit(dev_priv, sizeof(*cmd));
-out_resched:
-	/**
-	 * Will not re-add if already pending.
-	 */
-	schedule_delayed_work(&vfbs->d_work, VMWGFX_PRESENT_RATE);
-out_unlock:
-	mutex_unlock(&vfbs->work_lock);
-}
+	tmp = kzalloc(sizeof(*tmp) * num_clips, GFP_KERNEL);
+	if (unlikely(tmp == NULL)) {
+		DRM_ERROR("Temporary cliprect memory alloc failed.\n");
+		return -ENOMEM;
+	}
+
+	fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num_clips;
+	cmd = kzalloc(fifo_size, GFP_KERNEL);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Temporary fifo memory alloc failed.\n");
+		ret = -ENOMEM;
+		goto out_free_tmp;
+	}
+
+	/* setup blits pointer */
+	blits = (SVGASignedRect *)&cmd[1];
+
+	/* initial clip region */
+	left = clips->x1;
+	right = clips->x2;
+	top = clips->y1;
+	bottom = clips->y2;
+
+	/* skip the first clip rect */
+	for (i = 1, clips_ptr = clips + inc;
+	     i < num_clips; i++, clips_ptr += inc) {
+		left = min_t(int, left, (int)clips_ptr->x1);
+		right = max_t(int, right, (int)clips_ptr->x2);
+		top = min_t(int, top, (int)clips_ptr->y1);
+		bottom = max_t(int, bottom, (int)clips_ptr->y2);
+	}
+
+	/* only need to do this once */
+	memset(cmd, 0, fifo_size);
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN);
+	cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header));
+
+	cmd->body.srcRect.left = left;
+	cmd->body.srcRect.right = right;
+	cmd->body.srcRect.top = top;
+	cmd->body.srcRect.bottom = bottom;
+
+	clips_ptr = clips;
+	for (i = 0; i < num_clips; i++, clips_ptr += inc) {
+		tmp[i].x1 = clips_ptr->x1 - left;
+		tmp[i].x2 = clips_ptr->x2 - left;
+		tmp[i].y1 = clips_ptr->y1 - top;
+		tmp[i].y2 = clips_ptr->y2 - top;
+	}
+
+	/* do per unit writing, reuse fifo for each */
+	for (i = 0; i < num_units; i++) {
+		struct vmw_display_unit *unit = units[i];
+		struct vmw_clip_rect clip;
+		int num;
+
+		clip.x1 = left - unit->crtc.x;
+		clip.y1 = top - unit->crtc.y;
+		clip.x2 = right - unit->crtc.x;
+		clip.y2 = bottom - unit->crtc.y;
+
+		/* skip any crtcs that misses the clip region */
+		if (clip.x1 >= unit->crtc.mode.hdisplay ||
+		    clip.y1 >= unit->crtc.mode.vdisplay ||
+		    clip.x2 <= 0 || clip.y2 <= 0)
+			continue;
+
+		/*
+		 * In order for the clip rects to be correctly scaled
+		 * the src and dest rects needs to be the same size.
+		 */
+		cmd->body.destRect.left = clip.x1;
+		cmd->body.destRect.right = clip.x2;
+		cmd->body.destRect.top = clip.y1;
+		cmd->body.destRect.bottom = clip.y2;
+
+		/* create a clip rect of the crtc in dest coords */
+		clip.x2 = unit->crtc.mode.hdisplay - clip.x1;
+		clip.y2 = unit->crtc.mode.vdisplay - clip.y1;
+		clip.x1 = 0 - clip.x1;
+		clip.y1 = 0 - clip.y1;
+
+		/* need to reset sid as it is changed by execbuf */
+		cmd->body.srcImage.sid = cpu_to_le32(framebuffer->user_handle);
+		cmd->body.destScreenId = unit->unit;
+
+		/* clip and write blits to cmd stream */
+		vmw_clip_cliprects(tmp, num_clips, clip, blits, &num);
+
+		/* if no cliprects hit skip this */
+		if (num == 0)
+			continue;
+
+
+		/* recalculate package length */
+		fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num;
+		cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header));
+		ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd,
+					  fifo_size, 0, NULL);
 
+		if (unlikely(ret != 0))
+			break;
+	}
+
+
+	kfree(cmd);
+out_free_tmp:
+	kfree(tmp);
+
+	return ret;
+}
 
 int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
 				  struct drm_file *file_priv,
@@ -444,44 +571,20 @@
 	struct vmw_master *vmaster = vmw_master(file_priv->master);
 	struct vmw_framebuffer_surface *vfbs =
 		vmw_framebuffer_to_vfbs(framebuffer);
-	struct vmw_surface *surf = vfbs->surface;
 	struct drm_clip_rect norect;
-	SVGA3dCopyRect *cr;
-	int i, inc = 1;
-	int ret;
-
-	struct {
-		SVGA3dCmdHeader header;
-		SVGA3dCmdPresent body;
-		SVGA3dCopyRect cr;
-	} *cmd;
+	int ret, inc = 1;
 
 	if (unlikely(vfbs->master != file_priv->master))
 		return -EINVAL;
 
+	/* Require ScreenObject support for 3D */
+	if (!dev_priv->sou_priv)
+		return -EINVAL;
+
 	ret = ttm_read_lock(&vmaster->lock, true);
 	if (unlikely(ret != 0))
 		return ret;
 
-	if (!num_clips ||
-	    !(dev_priv->fifo.capabilities &
-	      SVGA_FIFO_CAP_SCREEN_OBJECT)) {
-		int ret;
-
-		mutex_lock(&vfbs->work_lock);
-		vfbs->present_fs = true;
-		ret = schedule_delayed_work(&vfbs->d_work, VMWGFX_PRESENT_RATE);
-		mutex_unlock(&vfbs->work_lock);
-		if (ret) {
-			/**
-			 * No work pending, Force immediate present.
-			 */
-			vmw_framebuffer_present_fs_callback(&vfbs->d_work.work);
-		}
-		ttm_read_unlock(&vmaster->lock);
-		return 0;
-	}
-
 	if (!num_clips) {
 		num_clips = 1;
 		clips = &norect;
@@ -493,29 +596,10 @@
 		inc = 2; /* skip source rects */
 	}
 
-	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr));
-	if (unlikely(cmd == NULL)) {
-		DRM_ERROR("Fifo reserve failed.\n");
-		ttm_read_unlock(&vmaster->lock);
-		return -ENOMEM;
-	}
-
-	memset(cmd, 0, sizeof(*cmd));
-
-	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_PRESENT);
-	cmd->header.size = cpu_to_le32(sizeof(cmd->body) + num_clips * sizeof(cmd->cr));
-	cmd->body.sid = cpu_to_le32(surf->res.id);
-
-	for (i = 0, cr = &cmd->cr; i < num_clips; i++, cr++, clips += inc) {
-		cr->x = cpu_to_le16(clips->x1);
-		cr->y = cpu_to_le16(clips->y1);
-		cr->srcx = cr->x;
-		cr->srcy = cr->y;
-		cr->w = cpu_to_le16(clips->x2 - clips->x1);
-		cr->h = cpu_to_le16(clips->y2 - clips->y1);
-	}
+	ret = do_surface_dirty_sou(dev_priv, file_priv, &vfbs->base,
+				   flags, color,
+				   clips, num_clips, inc);
 
-	vmw_fifo_commit(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr));
 	ttm_read_unlock(&vmaster->lock);
 	return 0;
 }
@@ -540,10 +624,18 @@
 	struct vmw_master *vmaster = vmw_master(file_priv->master);
 	int ret;
 
+	/* 3D is only supported on HWv8 hosts which supports screen objects */
+	if (!dev_priv->sou_priv)
+		return -ENOSYS;
+
 	/*
 	 * Sanity checks.
 	 */
 
+	/* Surface must be marked as a scanout. */
+	if (unlikely(!surface->scanout))
+		return -EINVAL;
+
 	if (unlikely(surface->mip_levels[0] != 1 ||
 		     surface->num_sizes != 1 ||
 		     surface->sizes[0].width < mode_cmd->width ||
@@ -567,6 +659,9 @@
 	case 15:
 		format = SVGA3D_A1R5G5B5;
 		break;
+	case 8:
+		format = SVGA3D_LUMINANCE8;
+		break;
 	default:
 		DRM_ERROR("Invalid color depth: %d\n", mode_cmd->depth);
 		return -EINVAL;
@@ -599,14 +694,11 @@
 	vfbs->base.base.depth = mode_cmd->depth;
 	vfbs->base.base.width = mode_cmd->width;
 	vfbs->base.base.height = mode_cmd->height;
-	vfbs->base.pin = &vmw_surface_dmabuf_pin;
-	vfbs->base.unpin = &vmw_surface_dmabuf_unpin;
 	vfbs->surface = surface;
+	vfbs->base.user_handle = mode_cmd->handle;
 	vfbs->master = drm_master_get(file_priv->master);
-	mutex_init(&vfbs->work_lock);
 
 	mutex_lock(&vmaster->fb_surf_mutex);
-	INIT_DELAYED_WORK(&vfbs->d_work, &vmw_framebuffer_present_fs_callback);
 	list_add_tail(&vfbs->head, &vmaster->fb_surf);
 	mutex_unlock(&vmaster->fb_surf_mutex);
 
@@ -641,48 +733,33 @@
 
 	drm_framebuffer_cleanup(framebuffer);
 	vmw_dmabuf_unreference(&vfbd->buffer);
+	ttm_base_object_unref(&vfbd->base.user_obj);
 
 	kfree(vfbd);
 }
 
-int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
-				 struct drm_file *file_priv,
-				 unsigned flags, unsigned color,
-				 struct drm_clip_rect *clips,
-				 unsigned num_clips)
+static int do_dmabuf_dirty_ldu(struct vmw_private *dev_priv,
+			       struct vmw_framebuffer *framebuffer,
+			       unsigned flags, unsigned color,
+			       struct drm_clip_rect *clips,
+			       unsigned num_clips, int increment)
 {
-	struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
-	struct vmw_master *vmaster = vmw_master(file_priv->master);
-	struct drm_clip_rect norect;
-	int ret;
+	size_t fifo_size;
+	int i;
+
 	struct {
 		uint32_t header;
 		SVGAFifoCmdUpdate body;
 	} *cmd;
-	int i, increment = 1;
-
-	ret = ttm_read_lock(&vmaster->lock, true);
-	if (unlikely(ret != 0))
-		return ret;
-
-	if (!num_clips) {
-		num_clips = 1;
-		clips = &norect;
-		norect.x1 = norect.y1 = 0;
-		norect.x2 = framebuffer->width;
-		norect.y2 = framebuffer->height;
-	} else if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) {
-		num_clips /= 2;
-		increment = 2;
-	}
 
-	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) * num_clips);
+	fifo_size = sizeof(*cmd) * num_clips;
+	cmd = vmw_fifo_reserve(dev_priv, fifo_size);
 	if (unlikely(cmd == NULL)) {
 		DRM_ERROR("Fifo reserve failed.\n");
-		ttm_read_unlock(&vmaster->lock);
 		return -ENOMEM;
 	}
 
+	memset(cmd, 0, fifo_size);
 	for (i = 0; i < num_clips; i++, clips += increment) {
 		cmd[i].header = cpu_to_le32(SVGA_CMD_UPDATE);
 		cmd[i].body.x = cpu_to_le32(clips->x1);
@@ -691,57 +768,196 @@
 		cmd[i].body.height = cpu_to_le32(clips->y2 - clips->y1);
 	}
 
-	vmw_fifo_commit(dev_priv, sizeof(*cmd) * num_clips);
-	ttm_read_unlock(&vmaster->lock);
-
+	vmw_fifo_commit(dev_priv, fifo_size);
 	return 0;
 }
 
-static struct drm_framebuffer_funcs vmw_framebuffer_dmabuf_funcs = {
-	.destroy = vmw_framebuffer_dmabuf_destroy,
-	.dirty = vmw_framebuffer_dmabuf_dirty,
-	.create_handle = vmw_framebuffer_create_handle,
-};
-
-static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb)
+static int do_dmabuf_define_gmrfb(struct drm_file *file_priv,
+				  struct vmw_private *dev_priv,
+				  struct vmw_framebuffer *framebuffer)
 {
-	struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
-	struct vmw_framebuffer_surface *vfbs =
-		vmw_framebuffer_to_vfbs(&vfb->base);
-	unsigned long size = vfbs->base.base.pitch * vfbs->base.base.height;
+	int depth = framebuffer->base.depth;
+	size_t fifo_size;
 	int ret;
 
-	vfbs->buffer = kzalloc(sizeof(*vfbs->buffer), GFP_KERNEL);
-	if (unlikely(vfbs->buffer == NULL))
+	struct {
+		uint32_t header;
+		SVGAFifoCmdDefineGMRFB body;
+	} *cmd;
+
+	/* Emulate RGBA support, contrary to svga_reg.h this is not
+	 * supported by hosts. This is only a problem if we are reading
+	 * this value later and expecting what we uploaded back.
+	 */
+	if (depth == 32)
+		depth = 24;
+
+	fifo_size = sizeof(*cmd);
+	cmd = kmalloc(fifo_size, GFP_KERNEL);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed to allocate temporary cmd buffer.\n");
 		return -ENOMEM;
+	}
 
-	vmw_overlay_pause_all(dev_priv);
-	ret = vmw_dmabuf_init(dev_priv, vfbs->buffer, size,
-			       &vmw_vram_ne_placement,
-			       false, &vmw_dmabuf_bo_free);
-	vmw_overlay_resume_all(dev_priv);
+	memset(cmd, 0, fifo_size);
+	cmd->header = SVGA_CMD_DEFINE_GMRFB;
+	cmd->body.format.bitsPerPixel = framebuffer->base.bits_per_pixel;
+	cmd->body.format.colorDepth = depth;
+	cmd->body.format.reserved = 0;
+	cmd->body.bytesPerLine = framebuffer->base.pitch;
+	cmd->body.ptr.gmrId = framebuffer->user_handle;
+	cmd->body.ptr.offset = 0;
+
+	ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd,
+				  fifo_size, 0, NULL);
+
+	kfree(cmd);
+
+	return ret;
+}
+
+static int do_dmabuf_dirty_sou(struct drm_file *file_priv,
+			       struct vmw_private *dev_priv,
+			       struct vmw_framebuffer *framebuffer,
+			       unsigned flags, unsigned color,
+			       struct drm_clip_rect *clips,
+			       unsigned num_clips, int increment)
+{
+	struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS];
+	struct drm_clip_rect *clips_ptr;
+	int i, k, num_units, ret;
+	struct drm_crtc *crtc;
+	size_t fifo_size;
+
+	struct {
+		uint32_t header;
+		SVGAFifoCmdBlitGMRFBToScreen body;
+	} *blits;
+
+	ret = do_dmabuf_define_gmrfb(file_priv, dev_priv, framebuffer);
 	if (unlikely(ret != 0))
-		vfbs->buffer = NULL;
+		return ret; /* define_gmrfb prints warnings */
+
+	fifo_size = sizeof(*blits) * num_clips;
+	blits = kmalloc(fifo_size, GFP_KERNEL);
+	if (unlikely(blits == NULL)) {
+		DRM_ERROR("Failed to allocate temporary cmd buffer.\n");
+		return -ENOMEM;
+	}
+
+	num_units = 0;
+	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
+		if (crtc->fb != &framebuffer->base)
+			continue;
+		units[num_units++] = vmw_crtc_to_du(crtc);
+	}
+
+	for (k = 0; k < num_units; k++) {
+		struct vmw_display_unit *unit = units[k];
+		int hit_num = 0;
+
+		clips_ptr = clips;
+		for (i = 0; i < num_clips; i++, clips_ptr += increment) {
+			int clip_x1 = clips_ptr->x1 - unit->crtc.x;
+			int clip_y1 = clips_ptr->y1 - unit->crtc.y;
+			int clip_x2 = clips_ptr->x2 - unit->crtc.x;
+			int clip_y2 = clips_ptr->y2 - unit->crtc.y;
+			int move_x, move_y;
+
+			/* skip any crtcs that misses the clip region */
+			if (clip_x1 >= unit->crtc.mode.hdisplay ||
+			    clip_y1 >= unit->crtc.mode.vdisplay ||
+			    clip_x2 <= 0 || clip_y2 <= 0)
+				continue;
+
+			/* clip size to crtc size */
+			clip_x2 = min_t(int, clip_x2, unit->crtc.mode.hdisplay);
+			clip_y2 = min_t(int, clip_y2, unit->crtc.mode.vdisplay);
+
+			/* translate both src and dest to bring clip into screen */
+			move_x = min_t(int, clip_x1, 0);
+			move_y = min_t(int, clip_y1, 0);
+
+			/* actual translate done here */
+			blits[hit_num].header = SVGA_CMD_BLIT_GMRFB_TO_SCREEN;
+			blits[hit_num].body.destScreenId = unit->unit;
+			blits[hit_num].body.srcOrigin.x = clips_ptr->x1 - move_x;
+			blits[hit_num].body.srcOrigin.y = clips_ptr->y1 - move_y;
+			blits[hit_num].body.destRect.left = clip_x1 - move_x;
+			blits[hit_num].body.destRect.top = clip_y1 - move_y;
+			blits[hit_num].body.destRect.right = clip_x2;
+			blits[hit_num].body.destRect.bottom = clip_y2;
+			hit_num++;
+		}
+
+		/* no clips hit the crtc */
+		if (hit_num == 0)
+			continue;
+
+		fifo_size = sizeof(*blits) * hit_num;
+		ret = vmw_execbuf_process(file_priv, dev_priv, NULL, blits,
+					  fifo_size, 0, NULL);
+
+		if (unlikely(ret != 0))
+			break;
+	}
+
+	kfree(blits);
 
 	return ret;
 }
 
-static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb)
+int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
+				 struct drm_file *file_priv,
+				 unsigned flags, unsigned color,
+				 struct drm_clip_rect *clips,
+				 unsigned num_clips)
 {
-	struct ttm_buffer_object *bo;
-	struct vmw_framebuffer_surface *vfbs =
-		vmw_framebuffer_to_vfbs(&vfb->base);
+	struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	struct vmw_framebuffer_dmabuf *vfbd =
+		vmw_framebuffer_to_vfbd(framebuffer);
+	struct drm_clip_rect norect;
+	int ret, increment = 1;
 
-	if (unlikely(vfbs->buffer == NULL))
-		return 0;
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
 
-	bo = &vfbs->buffer->base;
-	ttm_bo_unref(&bo);
-	vfbs->buffer = NULL;
+	if (!num_clips) {
+		num_clips = 1;
+		clips = &norect;
+		norect.x1 = norect.y1 = 0;
+		norect.x2 = framebuffer->width;
+		norect.y2 = framebuffer->height;
+	} else if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) {
+		num_clips /= 2;
+		increment = 2;
+	}
 
-	return 0;
+	if (dev_priv->ldu_priv) {
+		ret = do_dmabuf_dirty_ldu(dev_priv, &vfbd->base,
+					  flags, color,
+					  clips, num_clips, increment);
+	} else {
+		ret = do_dmabuf_dirty_sou(file_priv, dev_priv, &vfbd->base,
+					  flags, color,
+					  clips, num_clips, increment);
+	}
+
+	ttm_read_unlock(&vmaster->lock);
+	return ret;
 }
 
+static struct drm_framebuffer_funcs vmw_framebuffer_dmabuf_funcs = {
+	.destroy = vmw_framebuffer_dmabuf_destroy,
+	.dirty = vmw_framebuffer_dmabuf_dirty,
+	.create_handle = vmw_framebuffer_create_handle,
+};
+
+/**
+ * Pin the dmabuffer to the start of vram.
+ */
 static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
 {
 	struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
@@ -749,10 +965,12 @@
 		vmw_framebuffer_to_vfbd(&vfb->base);
 	int ret;
 
+	/* This code should not be used with screen objects */
+	BUG_ON(dev_priv->sou_priv);
 
 	vmw_overlay_pause_all(dev_priv);
 
-	ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer);
+	ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer, true, false);
 
 	vmw_overlay_resume_all(dev_priv);
 
@@ -772,7 +990,7 @@
 		return 0;
 	}
 
-	return vmw_dmabuf_from_vram(dev_priv, vfbd->buffer);
+	return vmw_dmabuf_unpin(dev_priv, vfbd->buffer, false);
 }
 
 static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
@@ -794,6 +1012,33 @@
 		return -EINVAL;
 	}
 
+	/* Limited framebuffer color depth support for screen objects */
+	if (dev_priv->sou_priv) {
+		switch (mode_cmd->depth) {
+		case 32:
+		case 24:
+			/* Only support 32 bpp for 32 and 24 depth fbs */
+			if (mode_cmd->bpp == 32)
+				break;
+
+			DRM_ERROR("Invalid color depth/bbp: %d %d\n",
+				  mode_cmd->depth, mode_cmd->bpp);
+			return -EINVAL;
+		case 16:
+		case 15:
+			/* Only support 16 bpp for 16 and 15 depth fbs */
+			if (mode_cmd->bpp == 16)
+				break;
+
+			DRM_ERROR("Invalid color depth/bbp: %d %d\n",
+				  mode_cmd->depth, mode_cmd->bpp);
+			return -EINVAL;
+		default:
+			DRM_ERROR("Invalid color depth: %d\n", mode_cmd->depth);
+			return -EINVAL;
+		}
+	}
+
 	vfbd = kzalloc(sizeof(*vfbd), GFP_KERNEL);
 	if (!vfbd) {
 		ret = -ENOMEM;
@@ -815,9 +1060,13 @@
 	vfbd->base.base.depth = mode_cmd->depth;
 	vfbd->base.base.width = mode_cmd->width;
 	vfbd->base.base.height = mode_cmd->height;
-	vfbd->base.pin = vmw_framebuffer_dmabuf_pin;
-	vfbd->base.unpin = vmw_framebuffer_dmabuf_unpin;
+	if (!dev_priv->sou_priv) {
+		vfbd->base.pin = vmw_framebuffer_dmabuf_pin;
+		vfbd->base.unpin = vmw_framebuffer_dmabuf_unpin;
+	}
+	vfbd->base.dmabuf = true;
 	vfbd->buffer = dmabuf;
+	vfbd->base.user_handle = mode_cmd->handle;
 	*out = &vfbd->base;
 
 	return 0;
@@ -843,7 +1092,7 @@
 	struct vmw_framebuffer *vfb = NULL;
 	struct vmw_surface *surface = NULL;
 	struct vmw_dma_buffer *bo = NULL;
-	u64 required_size;
+	struct ttm_base_object *user_obj;
 	int ret;
 
 	/**
@@ -852,69 +1101,308 @@
 	 * requested framebuffer.
 	 */
 
-	required_size = mode_cmd->pitch * mode_cmd->height;
-	if (unlikely(required_size > (u64) dev_priv->vram_size)) {
+	if (!vmw_kms_validate_mode_vram(dev_priv,
+					mode_cmd->pitch,
+					mode_cmd->height)) {
 		DRM_ERROR("VRAM size is too small for requested mode.\n");
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 	}
 
-	/**
-	 * End conditioned code.
+	/*
+	 * Take a reference on the user object of the resource
+	 * backing the kms fb. This ensures that user-space handle
+	 * lookups on that resource will always work as long as
+	 * it's registered with a kms framebuffer. This is important,
+	 * since vmw_execbuf_process identifies resources in the
+	 * command stream using user-space handles.
 	 */
 
-	ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
-					     mode_cmd->handle, &surface);
-	if (ret)
-		goto try_dmabuf;
+	user_obj = ttm_base_object_lookup(tfile, mode_cmd->handle);
+	if (unlikely(user_obj == NULL)) {
+		DRM_ERROR("Could not locate requested kms frame buffer.\n");
+		return ERR_PTR(-ENOENT);
+	}
 
-	if (!surface->scanout)
-		goto err_not_scanout;
+	/* returns either a dmabuf or surface */
+	ret = vmw_user_lookup_handle(dev_priv, tfile,
+				     mode_cmd->handle,
+				     &surface, &bo);
+	if (ret)
+		goto err_out;
 
-	ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv, surface,
-					      &vfb, mode_cmd);
+	/* Create the new framebuffer depending one what we got back */
+	if (bo)
+		ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb,
+						     mode_cmd);
+	else if (surface)
+		ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv,
+						      surface, &vfb, mode_cmd);
+	else
+		BUG();
 
-	/* vmw_user_surface_lookup takes one ref so does new_fb */
-	vmw_surface_unreference(&surface);
+err_out:
+	/* vmw_user_lookup_handle takes one ref so does new_fb */
+	if (bo)
+		vmw_dmabuf_unreference(&bo);
+	if (surface)
+		vmw_surface_unreference(&surface);
 
 	if (ret) {
 		DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret);
+		ttm_base_object_unref(&user_obj);
 		return ERR_PTR(ret);
-	}
+	} else
+		vfb->user_obj = user_obj;
+
 	return &vfb->base;
+}
 
-try_dmabuf:
-	DRM_INFO("%s: trying buffer\n", __func__);
+static struct drm_mode_config_funcs vmw_kms_funcs = {
+	.fb_create = vmw_kms_fb_create,
+};
 
-	ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo);
-	if (ret) {
-		DRM_ERROR("failed to find buffer: %i\n", ret);
-		return ERR_PTR(-ENOENT);
+int vmw_kms_present(struct vmw_private *dev_priv,
+		    struct drm_file *file_priv,
+		    struct vmw_framebuffer *vfb,
+		    struct vmw_surface *surface,
+		    uint32_t sid,
+		    int32_t destX, int32_t destY,
+		    struct drm_vmw_rect *clips,
+		    uint32_t num_clips)
+{
+	struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS];
+	struct drm_clip_rect *tmp;
+	struct drm_crtc *crtc;
+	size_t fifo_size;
+	int i, k, num_units;
+	int ret = 0; /* silence warning */
+	int left, right, top, bottom;
+
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdBlitSurfaceToScreen body;
+	} *cmd;
+	SVGASignedRect *blits;
+
+	num_units = 0;
+	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
+		if (crtc->fb != &vfb->base)
+			continue;
+		units[num_units++] = vmw_crtc_to_du(crtc);
 	}
 
-	ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb,
-					     mode_cmd);
+	BUG_ON(surface == NULL);
+	BUG_ON(!clips || !num_clips);
 
-	/* vmw_user_dmabuf_lookup takes one ref so does new_fb */
-	vmw_dmabuf_unreference(&bo);
+	tmp = kzalloc(sizeof(*tmp) * num_clips, GFP_KERNEL);
+	if (unlikely(tmp == NULL)) {
+		DRM_ERROR("Temporary cliprect memory alloc failed.\n");
+		return -ENOMEM;
+	}
 
-	if (ret) {
-		DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret);
-		return ERR_PTR(ret);
+	fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num_clips;
+	cmd = kmalloc(fifo_size, GFP_KERNEL);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed to allocate temporary fifo memory.\n");
+		ret = -ENOMEM;
+		goto out_free_tmp;
 	}
 
-	return &vfb->base;
+	left = clips->x;
+	right = clips->x + clips->w;
+	top = clips->y;
+	bottom = clips->y + clips->h;
 
-err_not_scanout:
-	DRM_ERROR("surface not marked as scanout\n");
-	/* vmw_user_surface_lookup takes one ref */
-	vmw_surface_unreference(&surface);
+	for (i = 1; i < num_clips; i++) {
+		left = min_t(int, left, (int)clips[i].x);
+		right = max_t(int, right, (int)clips[i].x + clips[i].w);
+		top = min_t(int, top, (int)clips[i].y);
+		bottom = max_t(int, bottom, (int)clips[i].y + clips[i].h);
+	}
 
-	return ERR_PTR(-EINVAL);
+	/* only need to do this once */
+	memset(cmd, 0, fifo_size);
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN);
+
+	blits = (SVGASignedRect *)&cmd[1];
+
+	cmd->body.srcRect.left = left;
+	cmd->body.srcRect.right = right;
+	cmd->body.srcRect.top = top;
+	cmd->body.srcRect.bottom = bottom;
+
+	for (i = 0; i < num_clips; i++) {
+		tmp[i].x1 = clips[i].x - left;
+		tmp[i].x2 = clips[i].x + clips[i].w - left;
+		tmp[i].y1 = clips[i].y - top;
+		tmp[i].y2 = clips[i].y + clips[i].h - top;
+	}
+
+	for (k = 0; k < num_units; k++) {
+		struct vmw_display_unit *unit = units[k];
+		struct vmw_clip_rect clip;
+		int num;
+
+		clip.x1 = left + destX - unit->crtc.x;
+		clip.y1 = top + destY - unit->crtc.y;
+		clip.x2 = right + destX - unit->crtc.x;
+		clip.y2 = bottom + destY - unit->crtc.y;
+
+		/* skip any crtcs that misses the clip region */
+		if (clip.x1 >= unit->crtc.mode.hdisplay ||
+		    clip.y1 >= unit->crtc.mode.vdisplay ||
+		    clip.x2 <= 0 || clip.y2 <= 0)
+			continue;
+
+		/*
+		 * In order for the clip rects to be correctly scaled
+		 * the src and dest rects needs to be the same size.
+		 */
+		cmd->body.destRect.left = clip.x1;
+		cmd->body.destRect.right = clip.x2;
+		cmd->body.destRect.top = clip.y1;
+		cmd->body.destRect.bottom = clip.y2;
+
+		/* create a clip rect of the crtc in dest coords */
+		clip.x2 = unit->crtc.mode.hdisplay - clip.x1;
+		clip.y2 = unit->crtc.mode.vdisplay - clip.y1;
+		clip.x1 = 0 - clip.x1;
+		clip.y1 = 0 - clip.y1;
+
+		/* need to reset sid as it is changed by execbuf */
+		cmd->body.srcImage.sid = sid;
+		cmd->body.destScreenId = unit->unit;
+
+		/* clip and write blits to cmd stream */
+		vmw_clip_cliprects(tmp, num_clips, clip, blits, &num);
+
+		/* if no cliprects hit skip this */
+		if (num == 0)
+			continue;
+
+		/* recalculate package length */
+		fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num;
+		cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header));
+		ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd,
+					  fifo_size, 0, NULL);
+
+		if (unlikely(ret != 0))
+			break;
+	}
+
+	kfree(cmd);
+out_free_tmp:
+	kfree(tmp);
+
+	return ret;
 }
 
-static struct drm_mode_config_funcs vmw_kms_funcs = {
-	.fb_create = vmw_kms_fb_create,
-};
+int vmw_kms_readback(struct vmw_private *dev_priv,
+		     struct drm_file *file_priv,
+		     struct vmw_framebuffer *vfb,
+		     struct drm_vmw_fence_rep __user *user_fence_rep,
+		     struct drm_vmw_rect *clips,
+		     uint32_t num_clips)
+{
+	struct vmw_framebuffer_dmabuf *vfbd =
+		vmw_framebuffer_to_vfbd(&vfb->base);
+	struct vmw_dma_buffer *dmabuf = vfbd->buffer;
+	struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS];
+	struct drm_crtc *crtc;
+	size_t fifo_size;
+	int i, k, ret, num_units, blits_pos;
+
+	struct {
+		uint32_t header;
+		SVGAFifoCmdDefineGMRFB body;
+	} *cmd;
+	struct {
+		uint32_t header;
+		SVGAFifoCmdBlitScreenToGMRFB body;
+	} *blits;
+
+	num_units = 0;
+	list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) {
+		if (crtc->fb != &vfb->base)
+			continue;
+		units[num_units++] = vmw_crtc_to_du(crtc);
+	}
+
+	BUG_ON(dmabuf == NULL);
+	BUG_ON(!clips || !num_clips);
+
+	/* take a safe guess at fifo size */
+	fifo_size = sizeof(*cmd) + sizeof(*blits) * num_clips * num_units;
+	cmd = kmalloc(fifo_size, GFP_KERNEL);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed to allocate temporary fifo memory.\n");
+		return -ENOMEM;
+	}
+
+	memset(cmd, 0, fifo_size);
+	cmd->header = SVGA_CMD_DEFINE_GMRFB;
+	cmd->body.format.bitsPerPixel = vfb->base.bits_per_pixel;
+	cmd->body.format.colorDepth = vfb->base.depth;
+	cmd->body.format.reserved = 0;
+	cmd->body.bytesPerLine = vfb->base.pitch;
+	cmd->body.ptr.gmrId = vfb->user_handle;
+	cmd->body.ptr.offset = 0;
+
+	blits = (void *)&cmd[1];
+	blits_pos = 0;
+	for (i = 0; i < num_units; i++) {
+		struct drm_vmw_rect *c = clips;
+		for (k = 0; k < num_clips; k++, c++) {
+			/* transform clip coords to crtc origin based coords */
+			int clip_x1 = c->x - units[i]->crtc.x;
+			int clip_x2 = c->x - units[i]->crtc.x + c->w;
+			int clip_y1 = c->y - units[i]->crtc.y;
+			int clip_y2 = c->y - units[i]->crtc.y + c->h;
+			int dest_x = c->x;
+			int dest_y = c->y;
+
+			/* compensate for clipping, we negate
+			 * a negative number and add that.
+			 */
+			if (clip_x1 < 0)
+				dest_x += -clip_x1;
+			if (clip_y1 < 0)
+				dest_y += -clip_y1;
+
+			/* clip */
+			clip_x1 = max(clip_x1, 0);
+			clip_y1 = max(clip_y1, 0);
+			clip_x2 = min(clip_x2, units[i]->crtc.mode.hdisplay);
+			clip_y2 = min(clip_y2, units[i]->crtc.mode.vdisplay);
+
+			/* and cull any rects that misses the crtc */
+			if (clip_x1 >= units[i]->crtc.mode.hdisplay ||
+			    clip_y1 >= units[i]->crtc.mode.vdisplay ||
+			    clip_x2 <= 0 || clip_y2 <= 0)
+				continue;
+
+			blits[blits_pos].header = SVGA_CMD_BLIT_SCREEN_TO_GMRFB;
+			blits[blits_pos].body.srcScreenId = units[i]->unit;
+			blits[blits_pos].body.destOrigin.x = dest_x;
+			blits[blits_pos].body.destOrigin.y = dest_y;
+
+			blits[blits_pos].body.srcRect.left = clip_x1;
+			blits[blits_pos].body.srcRect.top = clip_y1;
+			blits[blits_pos].body.srcRect.right = clip_x2;
+			blits[blits_pos].body.srcRect.bottom = clip_y2;
+			blits_pos++;
+		}
+	}
+	/* reset size here and use calculated exact size from loops */
+	fifo_size = sizeof(*cmd) + sizeof(*blits) * blits_pos;
+
+	ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, fifo_size,
+				  0, user_fence_rep);
+
+	kfree(cmd);
+
+	return ret;
+}
 
 int vmw_kms_init(struct vmw_private *dev_priv)
 {
@@ -929,7 +1417,9 @@
 	dev->mode_config.max_width = 8192;
 	dev->mode_config.max_height = 8192;
 
-	ret = vmw_kms_init_legacy_display_system(dev_priv);
+	ret = vmw_kms_init_screen_object_display(dev_priv);
+	if (ret) /* Fallback */
+		(void)vmw_kms_init_legacy_display_system(dev_priv);
 
 	return 0;
 }
@@ -942,7 +1432,10 @@
 	 * drm_encoder_cleanup which takes the lock we deadlock.
 	 */
 	drm_mode_config_cleanup(dev_priv->dev);
-	vmw_kms_close_legacy_display_system(dev_priv);
+	if (dev_priv->sou_priv)
+		vmw_kms_close_screen_object_display(dev_priv);
+	else
+		vmw_kms_close_legacy_display_system(dev_priv);
 	return 0;
 }
 
@@ -987,9 +1480,9 @@
 	return ret;
 }
 
-void vmw_kms_write_svga(struct vmw_private *vmw_priv,
+int vmw_kms_write_svga(struct vmw_private *vmw_priv,
 			unsigned width, unsigned height, unsigned pitch,
-			unsigned bbp, unsigned depth)
+			unsigned bpp, unsigned depth)
 {
 	if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
 		vmw_write(vmw_priv, SVGA_REG_PITCHLOCK, pitch);
@@ -997,11 +1490,15 @@
 		iowrite32(pitch, vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
 	vmw_write(vmw_priv, SVGA_REG_WIDTH, width);
 	vmw_write(vmw_priv, SVGA_REG_HEIGHT, height);
-	vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, bbp);
-	vmw_write(vmw_priv, SVGA_REG_DEPTH, depth);
-	vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
-	vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
-	vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
+	vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, bpp);
+
+	if (vmw_read(vmw_priv, SVGA_REG_DEPTH) != depth) {
+		DRM_ERROR("Invalid depth %u for %u bpp, host expects %u\n",
+			  depth, bpp, vmw_read(vmw_priv, SVGA_REG_DEPTH));
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
 int vmw_kms_save_vga(struct vmw_private *vmw_priv)
@@ -1011,12 +1508,7 @@
 
 	vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH);
 	vmw_priv->vga_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT);
-	vmw_priv->vga_depth = vmw_read(vmw_priv, SVGA_REG_DEPTH);
 	vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
-	vmw_priv->vga_pseudo = vmw_read(vmw_priv, SVGA_REG_PSEUDOCOLOR);
-	vmw_priv->vga_red_mask = vmw_read(vmw_priv, SVGA_REG_RED_MASK);
-	vmw_priv->vga_blue_mask = vmw_read(vmw_priv, SVGA_REG_BLUE_MASK);
-	vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
 	if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
 		vmw_priv->vga_pitchlock =
 		  vmw_read(vmw_priv, SVGA_REG_PITCHLOCK);
@@ -1065,12 +1557,7 @@
 
 	vmw_write(vmw_priv, SVGA_REG_WIDTH, vmw_priv->vga_width);
 	vmw_write(vmw_priv, SVGA_REG_HEIGHT, vmw_priv->vga_height);
-	vmw_write(vmw_priv, SVGA_REG_DEPTH, vmw_priv->vga_depth);
 	vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, vmw_priv->vga_bpp);
-	vmw_write(vmw_priv, SVGA_REG_PSEUDOCOLOR, vmw_priv->vga_pseudo);
-	vmw_write(vmw_priv, SVGA_REG_RED_MASK, vmw_priv->vga_red_mask);
-	vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, vmw_priv->vga_green_mask);
-	vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, vmw_priv->vga_blue_mask);
 	if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
 		vmw_write(vmw_priv, SVGA_REG_PITCHLOCK,
 			  vmw_priv->vga_pitchlock);
@@ -1095,6 +1582,312 @@
 	return 0;
 }
 
+bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
+				uint32_t pitch,
+				uint32_t height)
+{
+	return ((u64) pitch * (u64) height) < (u64) dev_priv->vram_size;
+}
+
+
+/**
+ * Function called by DRM code called with vbl_lock held.
+ */
+u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+	return 0;
+}
+
+/**
+ * Function called by DRM code called with vbl_lock held.
+ */
+int vmw_enable_vblank(struct drm_device *dev, int crtc)
+{
+	return -ENOSYS;
+}
+
+/**
+ * Function called by DRM code called with vbl_lock held.
+ */
+void vmw_disable_vblank(struct drm_device *dev, int crtc)
+{
+}
+
+
+/*
+ * Small shared kms functions.
+ */
+
+int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
+			 struct drm_vmw_rect *rects)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct vmw_display_unit *du;
+	struct drm_connector *con;
+
+	mutex_lock(&dev->mode_config.mutex);
+
+#if 0
+	{
+		unsigned int i;
+
+		DRM_INFO("%s: new layout ", __func__);
+		for (i = 0; i < num; i++)
+			DRM_INFO("(%i, %i %ux%u) ", rects[i].x, rects[i].y,
+				 rects[i].w, rects[i].h);
+		DRM_INFO("\n");
+	}
+#endif
+
+	list_for_each_entry(con, &dev->mode_config.connector_list, head) {
+		du = vmw_connector_to_du(con);
+		if (num > du->unit) {
+			du->pref_width = rects[du->unit].w;
+			du->pref_height = rects[du->unit].h;
+			du->pref_active = true;
+			du->gui_x = rects[du->unit].x;
+			du->gui_y = rects[du->unit].y;
+		} else {
+			du->pref_width = 800;
+			du->pref_height = 600;
+			du->pref_active = false;
+		}
+		con->status = vmw_du_connector_detect(con, true);
+	}
+
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return 0;
+}
+
+void vmw_du_crtc_save(struct drm_crtc *crtc)
+{
+}
+
+void vmw_du_crtc_restore(struct drm_crtc *crtc)
+{
+}
+
+void vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
+			   u16 *r, u16 *g, u16 *b,
+			   uint32_t start, uint32_t size)
+{
+	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
+	int i;
+
+	for (i = 0; i < size; i++) {
+		DRM_DEBUG("%d r/g/b = 0x%04x / 0x%04x / 0x%04x\n", i,
+			  r[i], g[i], b[i]);
+		vmw_write(dev_priv, SVGA_PALETTE_BASE + i * 3 + 0, r[i] >> 8);
+		vmw_write(dev_priv, SVGA_PALETTE_BASE + i * 3 + 1, g[i] >> 8);
+		vmw_write(dev_priv, SVGA_PALETTE_BASE + i * 3 + 2, b[i] >> 8);
+	}
+}
+
+void vmw_du_connector_dpms(struct drm_connector *connector, int mode)
+{
+}
+
+void vmw_du_connector_save(struct drm_connector *connector)
+{
+}
+
+void vmw_du_connector_restore(struct drm_connector *connector)
+{
+}
+
+enum drm_connector_status
+vmw_du_connector_detect(struct drm_connector *connector, bool force)
+{
+	uint32_t num_displays;
+	struct drm_device *dev = connector->dev;
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_display_unit *du = vmw_connector_to_du(connector);
+
+	mutex_lock(&dev_priv->hw_mutex);
+	num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS);
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	return ((vmw_connector_to_du(connector)->unit < num_displays &&
+		 du->pref_active) ?
+		connector_status_connected : connector_status_disconnected);
+}
+
+static struct drm_display_mode vmw_kms_connector_builtin[] = {
+	/* 640x480@60Hz */
+	{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
+		   752, 800, 0, 480, 489, 492, 525, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 800x600@60Hz */
+	{ 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) },
+	/* 1024x768@60Hz */
+	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
+		   1184, 1344, 0, 768, 771, 777, 806, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1152x864@75Hz */
+	{ DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
+		   1344, 1600, 0, 864, 865, 868, 900, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1280x768@60Hz */
+	{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344,
+		   1472, 1664, 0, 768, 771, 778, 798, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1280x800@60Hz */
+	{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352,
+		   1480, 1680, 0, 800, 803, 809, 831, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1280x960@60Hz */
+	{ DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376,
+		   1488, 1800, 0, 960, 961, 964, 1000, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1280x1024@60Hz */
+	{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328,
+		   1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1360x768@60Hz */
+	{ DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424,
+		   1536, 1792, 0, 768, 771, 777, 795, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1440x1050@60Hz */
+	{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488,
+		   1632, 1864, 0, 1050, 1053, 1057, 1089, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1440x900@60Hz */
+	{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520,
+		   1672, 1904, 0, 900, 903, 909, 934, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1600x1200@60Hz */
+	{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664,
+		   1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1680x1050@60Hz */
+	{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784,
+		   1960, 2240, 0, 1050, 1053, 1059, 1089, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1792x1344@60Hz */
+	{ DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920,
+		   2120, 2448, 0, 1344, 1345, 1348, 1394, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1853x1392@60Hz */
+	{ DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952,
+		   2176, 2528, 0, 1392, 1393, 1396, 1439, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1920x1200@60Hz */
+	{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056,
+		   2256, 2592, 0, 1200, 1203, 1209, 1245, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1920x1440@60Hz */
+	{ DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048,
+		   2256, 2600, 0, 1440, 1441, 1444, 1500, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 2560x1600@60Hz */
+	{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752,
+		   3032, 3504, 0, 1600, 1603, 1609, 1658, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* Terminate */
+	{ DRM_MODE("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) },
+};
+
+/**
+ * vmw_guess_mode_timing - Provide fake timings for a
+ * 60Hz vrefresh mode.
+ *
+ * @mode - Pointer to a struct drm_display_mode with hdisplay and vdisplay
+ * members filled in.
+ */
+static void vmw_guess_mode_timing(struct drm_display_mode *mode)
+{
+	mode->hsync_start = mode->hdisplay + 50;
+	mode->hsync_end = mode->hsync_start + 50;
+	mode->htotal = mode->hsync_end + 50;
+
+	mode->vsync_start = mode->vdisplay + 50;
+	mode->vsync_end = mode->vsync_start + 50;
+	mode->vtotal = mode->vsync_end + 50;
+
+	mode->clock = (u32)mode->htotal * (u32)mode->vtotal / 100 * 6;
+	mode->vrefresh = drm_mode_vrefresh(mode);
+}
+
+
+int vmw_du_connector_fill_modes(struct drm_connector *connector,
+				uint32_t max_width, uint32_t max_height)
+{
+	struct vmw_display_unit *du = vmw_connector_to_du(connector);
+	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,
+		DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
+	};
+	int i;
+
+	/* Add preferred mode */
+	{
+		mode = drm_mode_duplicate(dev, &prefmode);
+		if (!mode)
+			return 0;
+		mode->hdisplay = du->pref_width;
+		mode->vdisplay = du->pref_height;
+		vmw_guess_mode_timing(mode);
+
+		if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2,
+					       mode->vdisplay)) {
+			drm_mode_probed_add(connector, mode);
+		} else {
+			drm_mode_destroy(dev, mode);
+			mode = NULL;
+		}
+
+		if (du->pref_mode) {
+			list_del_init(&du->pref_mode->head);
+			drm_mode_destroy(dev, du->pref_mode);
+		}
+
+		/* mode might be null here, this is intended */
+		du->pref_mode = mode;
+	}
+
+	for (i = 0; vmw_kms_connector_builtin[i].type != 0; i++) {
+		bmode = &vmw_kms_connector_builtin[i];
+		if (bmode->hdisplay > max_width ||
+		    bmode->vdisplay > max_height)
+			continue;
+
+		if (!vmw_kms_validate_mode_vram(dev_priv, bmode->hdisplay * 2,
+						bmode->vdisplay))
+			continue;
+
+		mode = drm_mode_duplicate(dev, bmode);
+		if (!mode)
+			return 0;
+		mode->vrefresh = drm_mode_vrefresh(mode);
+
+		drm_mode_probed_add(connector, mode);
+	}
+
+	/* Move the prefered mode first, help apps pick the right mode. */
+	if (du->pref_mode)
+		list_move(&du->pref_mode->head, &connector->probed_modes);
+
+	drm_mode_connector_list_update(connector);
+
+	return 1;
+}
+
+int vmw_du_connector_set_property(struct drm_connector *connector,
+				  struct drm_property *property,
+				  uint64_t val)
+{
+	return 0;
+}
+
+
 int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv)
 {
@@ -1106,6 +1899,8 @@
 	struct drm_vmw_rect *rects;
 	unsigned rects_size;
 	int ret;
+	int i;
+	struct drm_mode_config *mode_config = &dev->mode_config;
 
 	ret = ttm_read_lock(&vmaster->lock, true);
 	if (unlikely(ret != 0))
@@ -1113,12 +1908,13 @@
 
 	if (!arg->num_outputs) {
 		struct drm_vmw_rect def_rect = {0, 0, 800, 600};
-		vmw_kms_ldu_update_layout(dev_priv, 1, &def_rect);
+		vmw_du_update_layout(dev_priv, 1, &def_rect);
 		goto out_unlock;
 	}
 
 	rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect);
-	rects = kzalloc(rects_size, GFP_KERNEL);
+	rects = kcalloc(arg->num_outputs, sizeof(struct drm_vmw_rect),
+			GFP_KERNEL);
 	if (unlikely(!rects)) {
 		ret = -ENOMEM;
 		goto out_unlock;
@@ -1132,7 +1928,18 @@
 		goto out_free;
 	}
 
-	vmw_kms_ldu_update_layout(dev_priv, arg->num_outputs, rects);
+	for (i = 0; i < arg->num_outputs; ++i) {
+		if (rects[i].x < 0 ||
+		    rects[i].y < 0 ||
+		    rects[i].x + rects[i].w > mode_config->max_width ||
+		    rects[i].y + rects[i].h > mode_config->max_height) {
+			DRM_ERROR("Invalid GUI layout.\n");
+			ret = -EINVAL;
+			goto out_free;
+		}
+	}
+
+	vmw_du_update_layout(dev_priv, arg->num_outputs, rects);
 
 out_free:
 	kfree(rects);
@@ -1140,15 +1947,3 @@
 	ttm_read_unlock(&vmaster->lock);
 	return ret;
 }
-
-bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
-				uint32_t pitch,
-				uint32_t height)
-{
-	return ((u64) pitch * (u64) height) < (u64) dev_priv->vram_size;
-}
-
-u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc)
-{
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,8 @@
 #include "drmP.h"
 #include "vmwgfx_drv.h"
 
+#define VMWGFX_NUM_DISPLAY_UNITS 8
+
 
 #define vmw_framebuffer_to_vfb(x) \
 	container_of(x, struct vmw_framebuffer, base)
@@ -45,6 +47,9 @@
 	struct drm_framebuffer base;
 	int (*pin)(struct vmw_framebuffer *fb);
 	int (*unpin)(struct vmw_framebuffer *fb);
+	bool dmabuf;
+	struct ttm_base_object *user_obj;
+	uint32_t user_handle;
 };
 
 
@@ -57,9 +62,14 @@
 int vmw_cursor_update_image(struct vmw_private *dev_priv,
 			    u32 *image, u32 width, u32 height,
 			    u32 hotspotX, u32 hotspotY);
+int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
+			     struct vmw_dma_buffer *dmabuf,
+			     u32 width, u32 height,
+			     u32 hotspotX, u32 hotspotY);
 void vmw_cursor_update_position(struct vmw_private *dev_priv,
 				bool show, int x, int y);
 
+
 /**
  * Base class display unit.
  *
@@ -83,22 +93,65 @@
 	int hotspot_y;
 
 	unsigned unit;
+
+	/*
+	 * Prefered mode tracking.
+	 */
+	unsigned pref_width;
+	unsigned pref_height;
+	bool pref_active;
+	struct drm_display_mode *pref_mode;
+
+	/*
+	 * Gui positioning
+	 */
+	int gui_x;
+	int gui_y;
+	bool is_implicit;
 };
 
+#define vmw_crtc_to_du(x) \
+	container_of(x, struct vmw_display_unit, crtc)
+#define vmw_connector_to_du(x) \
+	container_of(x, struct vmw_display_unit, connector)
+
+
 /*
  * Shared display unit functions - vmwgfx_kms.c
  */
 void vmw_display_unit_cleanup(struct vmw_display_unit *du);
+void vmw_du_crtc_save(struct drm_crtc *crtc);
+void vmw_du_crtc_restore(struct drm_crtc *crtc);
+void vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
+			   u16 *r, u16 *g, u16 *b,
+			   uint32_t start, uint32_t size);
 int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
 			   uint32_t handle, uint32_t width, uint32_t height);
 int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
+void vmw_du_connector_dpms(struct drm_connector *connector, int mode);
+void vmw_du_connector_save(struct drm_connector *connector);
+void vmw_du_connector_restore(struct drm_connector *connector);
+enum drm_connector_status
+vmw_du_connector_detect(struct drm_connector *connector, bool force);
+int vmw_du_connector_fill_modes(struct drm_connector *connector,
+				uint32_t max_width, uint32_t max_height);
+int vmw_du_connector_set_property(struct drm_connector *connector,
+				  struct drm_property *property,
+				  uint64_t val);
+
 
 /*
  * Legacy display unit functions - vmwgfx_ldu.c
  */
 int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv);
 int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv);
-int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
+
+/*
+ * Screen Objects display functions - vmwgfx_scrn.c
+ */
+int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv);
+int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv);
+int vmw_kms_sou_update_layout(struct vmw_private *dev_priv, unsigned num,
 			      struct drm_vmw_rect *rects);
 
 #endif
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,7 +27,6 @@
 
 #include "vmwgfx_kms.h"
 
-#define VMWGFX_LDU_NUM_DU 8
 
 #define vmw_crtc_to_ldu(x) \
 	container_of(x, struct vmw_legacy_display_unit, base.crtc)
@@ -51,11 +50,6 @@
 struct vmw_legacy_display_unit {
 	struct vmw_display_unit base;
 
-	unsigned pref_width;
-	unsigned pref_height;
-	bool pref_active;
-	struct drm_display_mode *pref_mode;
-
 	struct list_head active;
 };
 
@@ -71,20 +65,6 @@
  * Legacy Display Unit CRTC functions
  */
 
-static void vmw_ldu_crtc_save(struct drm_crtc *crtc)
-{
-}
-
-static void vmw_ldu_crtc_restore(struct drm_crtc *crtc)
-{
-}
-
-static void vmw_ldu_crtc_gamma_set(struct drm_crtc *crtc,
-				   u16 *r, u16 *g, u16 *b,
-				   uint32_t start, uint32_t size)
-{
-}
-
 static void vmw_ldu_crtc_destroy(struct drm_crtc *crtc)
 {
 	vmw_ldu_destroy(vmw_crtc_to_ldu(crtc));
@@ -94,9 +74,10 @@
 {
 	struct vmw_legacy_display *lds = dev_priv->ldu_priv;
 	struct vmw_legacy_display_unit *entry;
+	struct vmw_display_unit *du = NULL;
 	struct drm_framebuffer *fb = NULL;
 	struct drm_crtc *crtc = NULL;
-	int i = 0;
+	int i = 0, ret;
 
 	/* If there is no display topology the host just assumes
 	 * that the guest will set the same layout as the host.
@@ -114,10 +95,8 @@
 			return 0;
 		fb = entry->base.crtc.fb;
 
-		vmw_kms_write_svga(dev_priv, w, h, fb->pitch,
-				   fb->bits_per_pixel, fb->depth);
-
-		return 0;
+		return vmw_kms_write_svga(dev_priv, w, h, fb->pitch,
+					  fb->bits_per_pixel, fb->depth);
 	}
 
 	if (!list_empty(&lds->active)) {
@@ -151,6 +130,25 @@
 
 	lds->last_num_active = lds->num_active;
 
+
+	/* Find the first du with a cursor. */
+	list_for_each_entry(entry, &lds->active, active) {
+		du = &entry->base;
+
+		if (!du->cursor_dmabuf)
+			continue;
+
+		ret = vmw_cursor_update_dmabuf(dev_priv,
+					       du->cursor_dmabuf,
+					       64, 64,
+					       du->hotspot_x,
+					       du->hotspot_y);
+		if (ret == 0)
+			break;
+
+		DRM_ERROR("Could not update cursor image\n");
+	}
+
 	return 0;
 }
 
@@ -265,9 +263,7 @@
 
 		vmw_ldu_del_active(dev_priv, ldu);
 
-		vmw_ldu_commit_list(dev_priv);
-
-		return 0;
+		return vmw_ldu_commit_list(dev_priv);
 	}
 
 
@@ -292,21 +288,20 @@
 
 	vmw_ldu_add_active(dev_priv, ldu, vfb);
 
-	vmw_ldu_commit_list(dev_priv);
-
-	return 0;
+	return vmw_ldu_commit_list(dev_priv);
 }
 
 static struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
-	.save = vmw_ldu_crtc_save,
-	.restore = vmw_ldu_crtc_restore,
+	.save = vmw_du_crtc_save,
+	.restore = vmw_du_crtc_restore,
 	.cursor_set = vmw_du_crtc_cursor_set,
 	.cursor_move = vmw_du_crtc_cursor_move,
-	.gamma_set = vmw_ldu_crtc_gamma_set,
+	.gamma_set = vmw_du_crtc_gamma_set,
 	.destroy = vmw_ldu_crtc_destroy,
 	.set_config = vmw_ldu_crtc_set_config,
 };
 
+
 /*
  * Legacy Display Unit encoder functions
  */
@@ -324,183 +319,18 @@
  * Legacy Display Unit connector functions
  */
 
-static void vmw_ldu_connector_dpms(struct drm_connector *connector, int mode)
-{
-}
-
-static void vmw_ldu_connector_save(struct drm_connector *connector)
-{
-}
-
-static void vmw_ldu_connector_restore(struct drm_connector *connector)
-{
-}
-
-static enum drm_connector_status
-	vmw_ldu_connector_detect(struct drm_connector *connector,
-				 bool force)
-{
-	if (vmw_connector_to_ldu(connector)->pref_active)
-		return connector_status_connected;
-	return connector_status_disconnected;
-}
-
-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,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
-	/* 800x600@60Hz */
-	{ 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) },
-	/* 1024x768@60Hz */
-	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
-		   1184, 1344, 0, 768, 771, 777, 806, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
-	/* 1152x864@75Hz */
-	{ DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
-		   1344, 1600, 0, 864, 865, 868, 900, 0,
-		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1280x768@60Hz */
-	{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344,
-		   1472, 1664, 0, 768, 771, 778, 798, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1280x800@60Hz */
-	{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352,
-		   1480, 1680, 0, 800, 803, 809, 831, 0,
-		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
-	/* 1280x960@60Hz */
-	{ DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376,
-		   1488, 1800, 0, 960, 961, 964, 1000, 0,
-		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1280x1024@60Hz */
-	{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328,
-		   1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
-		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1360x768@60Hz */
-	{ DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424,
-		   1536, 1792, 0, 768, 771, 777, 795, 0,
-		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1440x1050@60Hz */
-	{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488,
-		   1632, 1864, 0, 1050, 1053, 1057, 1089, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1440x900@60Hz */
-	{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520,
-		   1672, 1904, 0, 900, 903, 909, 934, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1600x1200@60Hz */
-	{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664,
-		   1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
-		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1680x1050@60Hz */
-	{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784,
-		   1960, 2240, 0, 1050, 1053, 1059, 1089, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1792x1344@60Hz */
-	{ DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920,
-		   2120, 2448, 0, 1344, 1345, 1348, 1394, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1853x1392@60Hz */
-	{ DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952,
-		   2176, 2528, 0, 1392, 1393, 1396, 1439, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1920x1200@60Hz */
-	{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056,
-		   2256, 2592, 0, 1200, 1203, 1209, 1245, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 1920x1440@60Hz */
-	{ DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048,
-		   2256, 2600, 0, 1440, 1441, 1444, 1500, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* 2560x1600@60Hz */
-	{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752,
-		   3032, 3504, 0, 1600, 1603, 1609, 1658, 0,
-		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	/* Terminate */
-	{ DRM_MODE("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) },
-};
-
-static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
-					uint32_t max_width, uint32_t max_height)
-{
-	struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector);
-	struct drm_device *dev = connector->dev;
-	struct vmw_private *dev_priv = vmw_priv(dev);
-	struct drm_display_mode *mode = NULL;
-	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,
-		DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
-	};
-	int i;
-
-	/* Add preferred mode */
-	{
-		mode = drm_mode_duplicate(dev, &prefmode);
-		if (!mode)
-			return 0;
-		mode->hdisplay = ldu->pref_width;
-		mode->vdisplay = ldu->pref_height;
-		mode->vrefresh = drm_mode_vrefresh(mode);
-		if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2,
-					       mode->vdisplay)) {
-			drm_mode_probed_add(connector, mode);
-
-			if (ldu->pref_mode) {
-				list_del_init(&ldu->pref_mode->head);
-				drm_mode_destroy(dev, ldu->pref_mode);
-			}
-
-			ldu->pref_mode = mode;
-		}
-	}
-
-	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)
-			continue;
-
-		if (!vmw_kms_validate_mode_vram(dev_priv, bmode->hdisplay * 2,
-						bmode->vdisplay))
-			continue;
-
-		mode = drm_mode_duplicate(dev, bmode);
-		if (!mode)
-			return 0;
-		mode->vrefresh = drm_mode_vrefresh(mode);
-
-		drm_mode_probed_add(connector, mode);
-	}
-
-	drm_mode_connector_list_update(connector);
-
-	return 1;
-}
-
-static int vmw_ldu_connector_set_property(struct drm_connector *connector,
-					  struct drm_property *property,
-					  uint64_t val)
-{
-	return 0;
-}
-
 static void vmw_ldu_connector_destroy(struct drm_connector *connector)
 {
 	vmw_ldu_destroy(vmw_connector_to_ldu(connector));
 }
 
 static struct drm_connector_funcs vmw_legacy_connector_funcs = {
-	.dpms = vmw_ldu_connector_dpms,
-	.save = vmw_ldu_connector_save,
-	.restore = vmw_ldu_connector_restore,
-	.detect = vmw_ldu_connector_detect,
-	.fill_modes = vmw_ldu_connector_fill_modes,
-	.set_property = vmw_ldu_connector_set_property,
+	.dpms = vmw_du_connector_dpms,
+	.save = vmw_du_connector_save,
+	.restore = vmw_du_connector_restore,
+	.detect = vmw_du_connector_detect,
+	.fill_modes = vmw_du_connector_fill_modes,
+	.set_property = vmw_du_connector_set_property,
 	.destroy = vmw_ldu_connector_destroy,
 };
 
@@ -523,23 +353,26 @@
 
 	INIT_LIST_HEAD(&ldu->active);
 
-	ldu->pref_active = (unit == 0);
-	ldu->pref_width = 800;
-	ldu->pref_height = 600;
-	ldu->pref_mode = NULL;
+	ldu->base.pref_active = (unit == 0);
+	ldu->base.pref_width = 800;
+	ldu->base.pref_height = 600;
+	ldu->base.pref_mode = NULL;
+	ldu->base.is_implicit = true;
 
 	drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
-			   DRM_MODE_CONNECTOR_LVDS);
-	connector->status = vmw_ldu_connector_detect(connector, true);
+			   DRM_MODE_CONNECTOR_VIRTUAL);
+	connector->status = vmw_du_connector_detect(connector, true);
 
 	drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
-			 DRM_MODE_ENCODER_LVDS);
+			 DRM_MODE_ENCODER_VIRTUAL);
 	drm_mode_connector_attach_encoder(connector, encoder);
 	encoder->possible_crtcs = (1 << unit);
 	encoder->possible_clones = 0;
 
 	drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
 
+	drm_mode_crtc_set_gamma_size(crtc, 256);
+
 	drm_connector_attach_property(connector,
 				      dev->mode_config.dirty_info_property,
 				      1);
@@ -550,8 +383,7 @@
 int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
-	int i;
-	int ret;
+	int i, ret;
 
 	if (dev_priv->ldu_priv) {
 		DRM_INFO("ldu system already on\n");
@@ -559,7 +391,6 @@
 	}
 
 	dev_priv->ldu_priv = kmalloc(sizeof(*dev_priv->ldu_priv), GFP_KERNEL);
-
 	if (!dev_priv->ldu_priv)
 		return -ENOMEM;
 
@@ -568,18 +399,31 @@
 	dev_priv->ldu_priv->last_num_active = 0;
 	dev_priv->ldu_priv->fb = NULL;
 
-	drm_mode_create_dirty_info_property(dev_priv->dev);
+	/* for old hardware without multimon only enable one display */
+	if (dev_priv->capabilities & SVGA_CAP_MULTIMON)
+		ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
+	else
+		ret = drm_vblank_init(dev, 1);
+	if (ret != 0)
+		goto err_free;
 
-	if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
-		for (i = 0; i < VMWGFX_LDU_NUM_DU; ++i)
+	ret = drm_mode_create_dirty_info_property(dev);
+	if (ret != 0)
+		goto err_vblank_cleanup;
+
+	if (dev_priv->capabilities & SVGA_CAP_MULTIMON)
+		for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
 			vmw_ldu_init(dev_priv, i);
-		ret = drm_vblank_init(dev, VMWGFX_LDU_NUM_DU);
-	} else {
-		/* for old hardware without multimon only enable one display */
+	else
 		vmw_ldu_init(dev_priv, 0);
-		ret = drm_vblank_init(dev, 1);
-	}
 
+	return 0;
+
+err_vblank_cleanup:
+	drm_vblank_cleanup(dev);
+err_free:
+	kfree(dev_priv->ldu_priv);
+	dev_priv->ldu_priv = NULL;
 	return ret;
 }
 
@@ -587,52 +431,14 @@
 {
 	struct drm_device *dev = dev_priv->dev;
 
-	drm_vblank_cleanup(dev);
 	if (!dev_priv->ldu_priv)
 		return -ENOSYS;
 
+	drm_vblank_cleanup(dev);
+
 	BUG_ON(!list_empty(&dev_priv->ldu_priv->active));
 
 	kfree(dev_priv->ldu_priv);
 
 	return 0;
 }
-
-int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
-			      struct drm_vmw_rect *rects)
-{
-	struct drm_device *dev = dev_priv->dev;
-	struct vmw_legacy_display_unit *ldu;
-	struct drm_connector *con;
-	int i;
-
-	mutex_lock(&dev->mode_config.mutex);
-
-#if 0
-	DRM_INFO("%s: new layout ", __func__);
-	for (i = 0; i < (int)num; i++)
-		DRM_INFO("(%i, %i %ux%u) ", rects[i].x, rects[i].y,
-			 rects[i].w, rects[i].h);
-	DRM_INFO("\n");
-#else
-	(void)i;
-#endif
-
-	list_for_each_entry(con, &dev->mode_config.connector_list, head) {
-		ldu = vmw_connector_to_ldu(con);
-		if (num > ldu->base.unit) {
-			ldu->pref_width = rects[ldu->base.unit].w;
-			ldu->pref_height = rects[ldu->base.unit].h;
-			ldu->pref_active = true;
-		} else {
-			ldu->pref_width = 800;
-			ldu->pref_height = 600;
-			ldu->pref_active = false;
-		}
-		con->status = vmw_ldu_connector_detect(con, true);
-	}
-
-	mutex_unlock(&dev->mode_config.mutex);
-
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,171 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2010 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "vmwgfx_drv.h"
+
+struct vmw_marker {
+	struct list_head head;
+	uint32_t seqno;
+	struct timespec submitted;
+};
+
+void vmw_marker_queue_init(struct vmw_marker_queue *queue)
+{
+	INIT_LIST_HEAD(&queue->head);
+	queue->lag = ns_to_timespec(0);
+	getrawmonotonic(&queue->lag_time);
+	spin_lock_init(&queue->lock);
+}
+
+void vmw_marker_queue_takedown(struct vmw_marker_queue *queue)
+{
+	struct vmw_marker *marker, *next;
+
+	spin_lock(&queue->lock);
+	list_for_each_entry_safe(marker, next, &queue->head, head) {
+		kfree(marker);
+	}
+	spin_unlock(&queue->lock);
+}
+
+int vmw_marker_push(struct vmw_marker_queue *queue,
+		   uint32_t seqno)
+{
+	struct vmw_marker *marker = kmalloc(sizeof(*marker), GFP_KERNEL);
+
+	if (unlikely(!marker))
+		return -ENOMEM;
+
+	marker->seqno = seqno;
+	getrawmonotonic(&marker->submitted);
+	spin_lock(&queue->lock);
+	list_add_tail(&marker->head, &queue->head);
+	spin_unlock(&queue->lock);
+
+	return 0;
+}
+
+int vmw_marker_pull(struct vmw_marker_queue *queue,
+		   uint32_t signaled_seqno)
+{
+	struct vmw_marker *marker, *next;
+	struct timespec now;
+	bool updated = false;
+
+	spin_lock(&queue->lock);
+	getrawmonotonic(&now);
+
+	if (list_empty(&queue->head)) {
+		queue->lag = ns_to_timespec(0);
+		queue->lag_time = now;
+		updated = true;
+		goto out_unlock;
+	}
+
+	list_for_each_entry_safe(marker, next, &queue->head, head) {
+		if (signaled_seqno - marker->seqno > (1 << 30))
+			continue;
+
+		queue->lag = timespec_sub(now, marker->submitted);
+		queue->lag_time = now;
+		updated = true;
+		list_del(&marker->head);
+		kfree(marker);
+	}
+
+out_unlock:
+	spin_unlock(&queue->lock);
+
+	return (updated) ? 0 : -EBUSY;
+}
+
+static struct timespec vmw_timespec_add(struct timespec t1,
+					struct timespec t2)
+{
+	t1.tv_sec += t2.tv_sec;
+	t1.tv_nsec += t2.tv_nsec;
+	if (t1.tv_nsec >= 1000000000L) {
+		t1.tv_sec += 1;
+		t1.tv_nsec -= 1000000000L;
+	}
+
+	return t1;
+}
+
+static struct timespec vmw_fifo_lag(struct vmw_marker_queue *queue)
+{
+	struct timespec now;
+
+	spin_lock(&queue->lock);
+	getrawmonotonic(&now);
+	queue->lag = vmw_timespec_add(queue->lag,
+				      timespec_sub(now, queue->lag_time));
+	queue->lag_time = now;
+	spin_unlock(&queue->lock);
+	return queue->lag;
+}
+
+
+static bool vmw_lag_lt(struct vmw_marker_queue *queue,
+		       uint32_t us)
+{
+	struct timespec lag, cond;
+
+	cond = ns_to_timespec((s64) us * 1000);
+	lag = vmw_fifo_lag(queue);
+	return (timespec_compare(&lag, &cond) < 1);
+}
+
+int vmw_wait_lag(struct vmw_private *dev_priv,
+		 struct vmw_marker_queue *queue, uint32_t us)
+{
+	struct vmw_marker *marker;
+	uint32_t seqno;
+	int ret;
+
+	while (!vmw_lag_lt(queue, us)) {
+		spin_lock(&queue->lock);
+		if (list_empty(&queue->head))
+			seqno = atomic_read(&dev_priv->marker_seq);
+		else {
+			marker = list_first_entry(&queue->head,
+						 struct vmw_marker, head);
+			seqno = marker->seqno;
+		}
+		spin_unlock(&queue->lock);
+
+		ret = vmw_wait_seqno(dev_priv, false, seqno, true,
+					3*HZ);
+
+		if (unlikely(ret != 0))
+			return ret;
+
+		(void) vmw_marker_pull(queue, seqno);
+	}
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c	2012-01-04 18:55:44.000000000 -0500
@@ -87,48 +87,6 @@
 }
 
 /**
- * Pin or unpin a buffer in vram.
- *
- * @dev_priv:  Driver private.
- * @buf:  DMA buffer to pin or unpin.
- * @pin:  Pin buffer in vram if true.
- * @interruptible:  Use interruptible wait.
- *
- * Takes the current masters ttm lock in read.
- *
- * Returns
- * -ERESTARTSYS if interrupted by a signal.
- */
-static int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv,
-				  struct vmw_dma_buffer *buf,
-				  bool pin, bool interruptible)
-{
-	struct ttm_buffer_object *bo = &buf->base;
-	struct ttm_placement *overlay_placement = &vmw_vram_placement;
-	int ret;
-
-	ret = ttm_read_lock(&dev_priv->active_master->lock, interruptible);
-	if (unlikely(ret != 0))
-		return ret;
-
-	ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
-	if (unlikely(ret != 0))
-		goto err;
-
-	if (pin)
-		overlay_placement = &vmw_vram_ne_placement;
-
-	ret = ttm_bo_validate(bo, overlay_placement, interruptible, false, false);
-
-	ttm_bo_unreserve(bo);
-
-err:
-	ttm_read_unlock(&dev_priv->active_master->lock);
-
-	return ret;
-}
-
-/**
  * Send put command to hw.
  *
  * Returns
@@ -139,68 +97,80 @@
 				struct drm_vmw_control_stream_arg *arg,
 				bool interruptible)
 {
+	struct vmw_escape_video_flush *flush;
+	size_t fifo_size;
+	bool have_so = dev_priv->sou_priv ? true : false;
+	int i, num_items;
+	SVGAGuestPtr ptr;
+
 	struct {
 		struct vmw_escape_header escape;
 		struct {
-			struct {
-				uint32_t cmdType;
-				uint32_t streamId;
-			} header;
-			struct {
-				uint32_t registerId;
-				uint32_t value;
-			} items[SVGA_VIDEO_PITCH_3 + 1];
-		} body;
-		struct vmw_escape_video_flush flush;
+			uint32_t cmdType;
+			uint32_t streamId;
+		} header;
 	} *cmds;
-	uint32_t offset;
-	int i, ret;
+	struct {
+		uint32_t registerId;
+		uint32_t value;
+	} *items;
 
-	for (;;) {
-		cmds = vmw_fifo_reserve(dev_priv, sizeof(*cmds));
-		if (cmds)
-			break;
+	/* defines are a index needs + 1 */
+	if (have_so)
+		num_items = SVGA_VIDEO_DST_SCREEN_ID + 1;
+	else
+		num_items = SVGA_VIDEO_PITCH_3 + 1;
 
-		ret = vmw_fallback_wait(dev_priv, false, true, 0,
-					interruptible, 3*HZ);
-		if (interruptible && ret == -ERESTARTSYS)
-			return ret;
-		else
-			BUG_ON(ret != 0);
-	}
+	fifo_size = sizeof(*cmds) + sizeof(*flush) + sizeof(*items) * num_items;
 
-	fill_escape(&cmds->escape, sizeof(cmds->body));
-	cmds->body.header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
-	cmds->body.header.streamId = arg->stream_id;
+	cmds = vmw_fifo_reserve(dev_priv, fifo_size);
+	/* hardware has hung, can't do anything here */
+	if (!cmds)
+		return -ENOMEM;
 
-	for (i = 0; i <= SVGA_VIDEO_PITCH_3; i++)
-		cmds->body.items[i].registerId = i;
+	items = (typeof(items))&cmds[1];
+	flush = (struct vmw_escape_video_flush *)&items[num_items];
 
-	offset = buf->base.offset + arg->offset;
+	/* the size is header + number of items */
+	fill_escape(&cmds->escape, sizeof(*items) * (num_items + 1));
 
-	cmds->body.items[SVGA_VIDEO_ENABLED].value     = true;
-	cmds->body.items[SVGA_VIDEO_FLAGS].value       = arg->flags;
-	cmds->body.items[SVGA_VIDEO_DATA_OFFSET].value = offset;
-	cmds->body.items[SVGA_VIDEO_FORMAT].value      = arg->format;
-	cmds->body.items[SVGA_VIDEO_COLORKEY].value    = arg->color_key;
-	cmds->body.items[SVGA_VIDEO_SIZE].value        = arg->size;
-	cmds->body.items[SVGA_VIDEO_WIDTH].value       = arg->width;
-	cmds->body.items[SVGA_VIDEO_HEIGHT].value      = arg->height;
-	cmds->body.items[SVGA_VIDEO_SRC_X].value       = arg->src.x;
-	cmds->body.items[SVGA_VIDEO_SRC_Y].value       = arg->src.y;
-	cmds->body.items[SVGA_VIDEO_SRC_WIDTH].value   = arg->src.w;
-	cmds->body.items[SVGA_VIDEO_SRC_HEIGHT].value  = arg->src.h;
-	cmds->body.items[SVGA_VIDEO_DST_X].value       = arg->dst.x;
-	cmds->body.items[SVGA_VIDEO_DST_Y].value       = arg->dst.y;
-	cmds->body.items[SVGA_VIDEO_DST_WIDTH].value   = arg->dst.w;
-	cmds->body.items[SVGA_VIDEO_DST_HEIGHT].value  = arg->dst.h;
-	cmds->body.items[SVGA_VIDEO_PITCH_1].value     = arg->pitch[0];
-	cmds->body.items[SVGA_VIDEO_PITCH_2].value     = arg->pitch[1];
-	cmds->body.items[SVGA_VIDEO_PITCH_3].value     = arg->pitch[2];
+	cmds->header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
+	cmds->header.streamId = arg->stream_id;
 
-	fill_flush(&cmds->flush, arg->stream_id);
+	/* the IDs are neatly numbered */
+	for (i = 0; i < num_items; i++)
+		items[i].registerId = i;
 
-	vmw_fifo_commit(dev_priv, sizeof(*cmds));
+	vmw_bo_get_guest_ptr(&buf->base, &ptr);
+	ptr.offset += arg->offset;
+
+	items[SVGA_VIDEO_ENABLED].value     = true;
+	items[SVGA_VIDEO_FLAGS].value       = arg->flags;
+	items[SVGA_VIDEO_DATA_OFFSET].value = ptr.offset;
+	items[SVGA_VIDEO_FORMAT].value      = arg->format;
+	items[SVGA_VIDEO_COLORKEY].value    = arg->color_key;
+	items[SVGA_VIDEO_SIZE].value        = arg->size;
+	items[SVGA_VIDEO_WIDTH].value       = arg->width;
+	items[SVGA_VIDEO_HEIGHT].value      = arg->height;
+	items[SVGA_VIDEO_SRC_X].value       = arg->src.x;
+	items[SVGA_VIDEO_SRC_Y].value       = arg->src.y;
+	items[SVGA_VIDEO_SRC_WIDTH].value   = arg->src.w;
+	items[SVGA_VIDEO_SRC_HEIGHT].value  = arg->src.h;
+	items[SVGA_VIDEO_DST_X].value       = arg->dst.x;
+	items[SVGA_VIDEO_DST_Y].value       = arg->dst.y;
+	items[SVGA_VIDEO_DST_WIDTH].value   = arg->dst.w;
+	items[SVGA_VIDEO_DST_HEIGHT].value  = arg->dst.h;
+	items[SVGA_VIDEO_PITCH_1].value     = arg->pitch[0];
+	items[SVGA_VIDEO_PITCH_2].value     = arg->pitch[1];
+	items[SVGA_VIDEO_PITCH_3].value     = arg->pitch[2];
+	if (have_so) {
+		items[SVGA_VIDEO_DATA_GMRID].value    = ptr.gmrId;
+		items[SVGA_VIDEO_DST_SCREEN_ID].value = SVGA_ID_INVALID;
+	}
+
+	fill_flush(flush, arg->stream_id);
+
+	vmw_fifo_commit(dev_priv, fifo_size);
 
 	return 0;
 }
@@ -248,6 +218,25 @@
 }
 
 /**
+ * Move a buffer to vram or gmr if @pin is set, else unpin the buffer.
+ *
+ * With the introduction of screen objects buffers could now be
+ * used with GMRs instead of being locked to vram.
+ */
+static int vmw_overlay_move_buffer(struct vmw_private *dev_priv,
+				   struct vmw_dma_buffer *buf,
+				   bool pin, bool inter)
+{
+	if (!pin)
+		return vmw_dmabuf_unpin(dev_priv, buf, inter);
+
+	if (!dev_priv->sou_priv)
+		return vmw_dmabuf_to_vram(dev_priv, buf, true, inter);
+
+	return vmw_dmabuf_to_vram_or_gmr(dev_priv, buf, true, inter);
+}
+
+/**
  * Stop or pause a stream.
  *
  * If the stream is paused the no evict flag is removed from the buffer
@@ -279,8 +268,8 @@
 			return ret;
 
 		/* We just remove the NO_EVICT flag so no -ENOMEM */
-		ret = vmw_dmabuf_pin_in_vram(dev_priv, stream->buf, false,
-					     interruptible);
+		ret = vmw_overlay_move_buffer(dev_priv, stream->buf, false,
+					      interruptible);
 		if (interruptible && ret == -ERESTARTSYS)
 			return ret;
 		else
@@ -342,7 +331,7 @@
 	/* We don't start the old stream if we are interrupted.
 	 * Might return -ENOMEM if it can't fit the buffer in vram.
 	 */
-	ret = vmw_dmabuf_pin_in_vram(dev_priv, buf, true, interruptible);
+	ret = vmw_overlay_move_buffer(dev_priv, buf, true, interruptible);
 	if (ret)
 		return ret;
 
@@ -351,7 +340,8 @@
 		/* This one needs to happen no matter what. We only remove
 		 * the NO_EVICT flag so this is safe from -ENOMEM.
 		 */
-		BUG_ON(vmw_dmabuf_pin_in_vram(dev_priv, buf, false, false) != 0);
+		BUG_ON(vmw_overlay_move_buffer(dev_priv, buf, false, false)
+		       != 0);
 		return ret;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,10 +31,6 @@
 #include "ttm/ttm_placement.h"
 #include "drmP.h"
 
-#define VMW_RES_CONTEXT ttm_driver_type0
-#define VMW_RES_SURFACE ttm_driver_type1
-#define VMW_RES_STREAM ttm_driver_type2
-
 struct vmw_user_context {
 	struct ttm_base_object base;
 	struct vmw_resource res;
@@ -43,6 +39,7 @@
 struct vmw_user_surface {
 	struct ttm_base_object base;
 	struct vmw_surface srf;
+	uint32_t size;
 };
 
 struct vmw_user_dma_buffer {
@@ -65,6 +62,17 @@
 	struct vmw_stream stream;
 };
 
+struct vmw_surface_offset {
+	uint32_t face;
+	uint32_t mip;
+	uint32_t bo_offset;
+};
+
+
+static uint64_t vmw_user_context_size;
+static uint64_t vmw_user_surface_size;
+static uint64_t vmw_user_stream_size;
+
 static inline struct vmw_dma_buffer *
 vmw_dma_buffer(struct ttm_buffer_object *bo)
 {
@@ -84,13 +92,36 @@
 	return res;
 }
 
+
+/**
+ * vmw_resource_release_id - release a resource id to the id manager.
+ *
+ * @res: Pointer to the resource.
+ *
+ * Release the resource id to the resource id manager and set it to -1
+ */
+static void vmw_resource_release_id(struct vmw_resource *res)
+{
+	struct vmw_private *dev_priv = res->dev_priv;
+
+	write_lock(&dev_priv->resource_lock);
+	if (res->id != -1)
+		idr_remove(res->idr, res->id);
+	res->id = -1;
+	write_unlock(&dev_priv->resource_lock);
+}
+
 static void vmw_resource_release(struct kref *kref)
 {
 	struct vmw_resource *res =
 	    container_of(kref, struct vmw_resource, kref);
 	struct vmw_private *dev_priv = res->dev_priv;
+	int id = res->id;
+	struct idr *idr = res->idr;
 
-	idr_remove(res->idr, res->id);
+	res->avail = false;
+	if (res->remove_from_lists != NULL)
+		res->remove_from_lists(res);
 	write_unlock(&dev_priv->resource_lock);
 
 	if (likely(res->hw_destroy != NULL))
@@ -102,6 +133,9 @@
 		kfree(res);
 
 	write_lock(&dev_priv->resource_lock);
+
+	if (id != -1)
+		idr_remove(idr, id);
 }
 
 void vmw_resource_unreference(struct vmw_resource **p_res)
@@ -115,28 +149,29 @@
 	write_unlock(&dev_priv->resource_lock);
 }
 
-static int vmw_resource_init(struct vmw_private *dev_priv,
-			     struct vmw_resource *res,
-			     struct idr *idr,
-			     enum ttm_object_type obj_type,
-			     void (*res_free) (struct vmw_resource *res))
+
+/**
+ * vmw_resource_alloc_id - release a resource id to the id manager.
+ *
+ * @dev_priv: Pointer to the device private structure.
+ * @res: Pointer to the resource.
+ *
+ * Allocate the lowest free resource from the resource manager, and set
+ * @res->id to that id. Returns 0 on success and -ENOMEM on failure.
+ */
+static int vmw_resource_alloc_id(struct vmw_private *dev_priv,
+				 struct vmw_resource *res)
 {
 	int ret;
 
-	kref_init(&res->kref);
-	res->hw_destroy = NULL;
-	res->res_free = res_free;
-	res->res_type = obj_type;
-	res->idr = idr;
-	res->avail = false;
-	res->dev_priv = dev_priv;
+	BUG_ON(res->id != -1);
 
 	do {
-		if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
+		if (unlikely(idr_pre_get(res->idr, GFP_KERNEL) == 0))
 			return -ENOMEM;
 
 		write_lock(&dev_priv->resource_lock);
-		ret = idr_get_new_above(idr, res, 1, &res->id);
+		ret = idr_get_new_above(res->idr, res, 1, &res->id);
 		write_unlock(&dev_priv->resource_lock);
 
 	} while (ret == -EAGAIN);
@@ -144,6 +179,33 @@
 	return ret;
 }
 
+
+static int vmw_resource_init(struct vmw_private *dev_priv,
+			     struct vmw_resource *res,
+			     struct idr *idr,
+			     enum ttm_object_type obj_type,
+			     bool delay_id,
+			     void (*res_free) (struct vmw_resource *res),
+			     void (*remove_from_lists)
+			     (struct vmw_resource *res))
+{
+	kref_init(&res->kref);
+	res->hw_destroy = NULL;
+	res->res_free = res_free;
+	res->remove_from_lists = remove_from_lists;
+	res->res_type = obj_type;
+	res->idr = idr;
+	res->avail = false;
+	res->dev_priv = dev_priv;
+	INIT_LIST_HEAD(&res->query_head);
+	INIT_LIST_HEAD(&res->validate_head);
+	res->id = -1;
+	if (delay_id)
+		return 0;
+	else
+		return vmw_resource_alloc_id(dev_priv, res);
+}
+
 /**
  * vmw_resource_activate
  *
@@ -198,8 +260,12 @@
 	struct {
 		SVGA3dCmdHeader header;
 		SVGA3dCmdDestroyContext body;
-	} *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+	} *cmd;
+
+
+	vmw_execbuf_release_pinned_bo(dev_priv, true, res->id);
 
+	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
 	if (unlikely(cmd == NULL)) {
 		DRM_ERROR("Failed reserving FIFO space for surface "
 			  "destruction.\n");
@@ -211,7 +277,7 @@
 	cmd->body.cid = cpu_to_le32(res->id);
 
 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
-	vmw_3d_resource_dec(dev_priv);
+	vmw_3d_resource_dec(dev_priv, false);
 }
 
 static int vmw_context_init(struct vmw_private *dev_priv,
@@ -226,14 +292,17 @@
 	} *cmd;
 
 	ret = vmw_resource_init(dev_priv, res, &dev_priv->context_idr,
-				VMW_RES_CONTEXT, res_free);
+				VMW_RES_CONTEXT, false, res_free, NULL);
 
 	if (unlikely(ret != 0)) {
-		if (res_free == NULL)
-			kfree(res);
-		else
-			res_free(res);
-		return ret;
+		DRM_ERROR("Failed to allocate a resource id.\n");
+		goto out_early;
+	}
+
+	if (unlikely(res->id >= SVGA3D_MAX_CONTEXT_IDS)) {
+		DRM_ERROR("Out of hw context ids.\n");
+		vmw_resource_unreference(&res);
+		return -ENOMEM;
 	}
 
 	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
@@ -248,9 +317,16 @@
 	cmd->body.cid = cpu_to_le32(res->id);
 
 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
-	(void) vmw_3d_resource_inc(dev_priv);
+	(void) vmw_3d_resource_inc(dev_priv, false);
 	vmw_resource_activate(res, vmw_hw_context_destroy);
 	return 0;
+
+out_early:
+	if (res_free == NULL)
+		kfree(res);
+	else
+		res_free(res);
+	return ret;
 }
 
 struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv)
@@ -273,8 +349,11 @@
 {
 	struct vmw_user_context *ctx =
 	    container_of(res, struct vmw_user_context, res);
+	struct vmw_private *dev_priv = res->dev_priv;
 
 	kfree(ctx);
+	ttm_mem_global_free(vmw_mem_glob(dev_priv),
+			    vmw_user_context_size);
 }
 
 /**
@@ -328,23 +407,56 @@
 			     struct drm_file *file_priv)
 {
 	struct vmw_private *dev_priv = vmw_priv(dev);
-	struct vmw_user_context *ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+	struct vmw_user_context *ctx;
 	struct vmw_resource *res;
 	struct vmw_resource *tmp;
 	struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
 	int ret;
 
-	if (unlikely(ctx == NULL))
-		return -ENOMEM;
+
+	/*
+	 * Approximate idr memory usage with 128 bytes. It will be limited
+	 * by maximum number_of contexts anyway.
+	 */
+
+	if (unlikely(vmw_user_context_size == 0))
+		vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128;
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+				   vmw_user_context_size,
+				   false, true);
+	if (unlikely(ret != 0)) {
+		if (ret != -ERESTARTSYS)
+			DRM_ERROR("Out of graphics memory for context"
+				  " creation.\n");
+		goto out_unlock;
+	}
+
+	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+	if (unlikely(ctx == NULL)) {
+		ttm_mem_global_free(vmw_mem_glob(dev_priv),
+				    vmw_user_context_size);
+		ret = -ENOMEM;
+		goto out_unlock;
+	}
 
 	res = &ctx->res;
 	ctx->base.shareable = false;
 	ctx->base.tfile = NULL;
 
+	/*
+	 * From here on, the destructor takes over resource freeing.
+	 */
+
 	ret = vmw_context_init(dev_priv, res, vmw_user_context_free);
 	if (unlikely(ret != 0))
-		return ret;
+		goto out_unlock;
 
 	tmp = vmw_resource_reference(&ctx->res);
 	ret = ttm_base_object_init(tfile, &ctx->base, false, VMW_RES_CONTEXT,
@@ -358,13 +470,16 @@
 	arg->cid = res->id;
 out_err:
 	vmw_resource_unreference(&res);
+out_unlock:
+	ttm_read_unlock(&vmaster->lock);
 	return ret;
 
 }
 
 int vmw_context_check(struct vmw_private *dev_priv,
 		      struct ttm_object_file *tfile,
-		      int id)
+		      int id,
+		      struct vmw_resource **p_res)
 {
 	struct vmw_resource *res;
 	int ret = 0;
@@ -376,6 +491,8 @@
 			container_of(res, struct vmw_user_context, res);
 		if (ctx->base.tfile != tfile && !ctx->base.shareable)
 			ret = -EPERM;
+		if (p_res)
+			*p_res = vmw_resource_reference(res);
 	} else
 		ret = -EINVAL;
 	read_unlock(&dev_priv->resource_lock);
@@ -383,102 +500,638 @@
 	return ret;
 }
 
+struct vmw_bpp {
+	uint8_t bpp;
+	uint8_t s_bpp;
+};
+
+/*
+ * Size table for the supported SVGA3D surface formats. It consists of
+ * two values. The bpp value and the s_bpp value which is short for
+ * "stride bits per pixel" The values are given in such a way that the
+ * minimum stride for the image is calculated using
+ *
+ * min_stride = w*s_bpp
+ *
+ * and the total memory requirement for the image is
+ *
+ * h*min_stride*bpp/s_bpp
+ *
+ */
+static const struct vmw_bpp vmw_sf_bpp[] = {
+	[SVGA3D_FORMAT_INVALID] = {0, 0},
+	[SVGA3D_X8R8G8B8] = {32, 32},
+	[SVGA3D_A8R8G8B8] = {32, 32},
+	[SVGA3D_R5G6B5] = {16, 16},
+	[SVGA3D_X1R5G5B5] = {16, 16},
+	[SVGA3D_A1R5G5B5] = {16, 16},
+	[SVGA3D_A4R4G4B4] = {16, 16},
+	[SVGA3D_Z_D32] = {32, 32},
+	[SVGA3D_Z_D16] = {16, 16},
+	[SVGA3D_Z_D24S8] = {32, 32},
+	[SVGA3D_Z_D15S1] = {16, 16},
+	[SVGA3D_LUMINANCE8] = {8, 8},
+	[SVGA3D_LUMINANCE4_ALPHA4] = {8, 8},
+	[SVGA3D_LUMINANCE16] = {16, 16},
+	[SVGA3D_LUMINANCE8_ALPHA8] = {16, 16},
+	[SVGA3D_DXT1] = {4, 16},
+	[SVGA3D_DXT2] = {8, 32},
+	[SVGA3D_DXT3] = {8, 32},
+	[SVGA3D_DXT4] = {8, 32},
+	[SVGA3D_DXT5] = {8, 32},
+	[SVGA3D_BUMPU8V8] = {16, 16},
+	[SVGA3D_BUMPL6V5U5] = {16, 16},
+	[SVGA3D_BUMPX8L8V8U8] = {32, 32},
+	[SVGA3D_ARGB_S10E5] = {16, 16},
+	[SVGA3D_ARGB_S23E8] = {32, 32},
+	[SVGA3D_A2R10G10B10] = {32, 32},
+	[SVGA3D_V8U8] = {16, 16},
+	[SVGA3D_Q8W8V8U8] = {32, 32},
+	[SVGA3D_CxV8U8] = {16, 16},
+	[SVGA3D_X8L8V8U8] = {32, 32},
+	[SVGA3D_A2W10V10U10] = {32, 32},
+	[SVGA3D_ALPHA8] = {8, 8},
+	[SVGA3D_R_S10E5] = {16, 16},
+	[SVGA3D_R_S23E8] = {32, 32},
+	[SVGA3D_RG_S10E5] = {16, 16},
+	[SVGA3D_RG_S23E8] = {32, 32},
+	[SVGA3D_BUFFER] = {8, 8},
+	[SVGA3D_Z_D24X8] = {32, 32},
+	[SVGA3D_V16U16] = {32, 32},
+	[SVGA3D_G16R16] = {32, 32},
+	[SVGA3D_A16B16G16R16] = {64,  64},
+	[SVGA3D_UYVY] = {12, 12},
+	[SVGA3D_YUY2] = {12, 12},
+	[SVGA3D_NV12] = {12, 8},
+	[SVGA3D_AYUV] = {32, 32},
+	[SVGA3D_BC4_UNORM] = {4,  16},
+	[SVGA3D_BC5_UNORM] = {8,  32},
+	[SVGA3D_Z_DF16] = {16,  16},
+	[SVGA3D_Z_DF24] = {24,  24},
+	[SVGA3D_Z_D24S8_INT] = {32,  32}
+};
+
 
 /**
  * Surface management.
  */
 
+struct vmw_surface_dma {
+	SVGA3dCmdHeader header;
+	SVGA3dCmdSurfaceDMA body;
+	SVGA3dCopyBox cb;
+	SVGA3dCmdSurfaceDMASuffix suffix;
+};
+
+struct vmw_surface_define {
+	SVGA3dCmdHeader header;
+	SVGA3dCmdDefineSurface body;
+};
+
+struct vmw_surface_destroy {
+	SVGA3dCmdHeader header;
+	SVGA3dCmdDestroySurface body;
+};
+
+
+/**
+ * vmw_surface_dma_size - Compute fifo size for a dma command.
+ *
+ * @srf: Pointer to a struct vmw_surface
+ *
+ * Computes the required size for a surface dma command for backup or
+ * restoration of the surface represented by @srf.
+ */
+static inline uint32_t vmw_surface_dma_size(const struct vmw_surface *srf)
+{
+	return srf->num_sizes * sizeof(struct vmw_surface_dma);
+}
+
+
+/**
+ * vmw_surface_define_size - Compute fifo size for a surface define command.
+ *
+ * @srf: Pointer to a struct vmw_surface
+ *
+ * Computes the required size for a surface define command for the definition
+ * of the surface represented by @srf.
+ */
+static inline uint32_t vmw_surface_define_size(const struct vmw_surface *srf)
+{
+	return sizeof(struct vmw_surface_define) + srf->num_sizes *
+		sizeof(SVGA3dSize);
+}
+
+
+/**
+ * vmw_surface_destroy_size - Compute fifo size for a surface destroy command.
+ *
+ * Computes the required size for a surface destroy command for the destruction
+ * of a hw surface.
+ */
+static inline uint32_t vmw_surface_destroy_size(void)
+{
+	return sizeof(struct vmw_surface_destroy);
+}
+
+/**
+ * vmw_surface_destroy_encode - Encode a surface_destroy command.
+ *
+ * @id: The surface id
+ * @cmd_space: Pointer to memory area in which the commands should be encoded.
+ */
+static void vmw_surface_destroy_encode(uint32_t id,
+				       void *cmd_space)
+{
+	struct vmw_surface_destroy *cmd = (struct vmw_surface_destroy *)
+		cmd_space;
+
+	cmd->header.id = SVGA_3D_CMD_SURFACE_DESTROY;
+	cmd->header.size = sizeof(cmd->body);
+	cmd->body.sid = id;
+}
+
+/**
+ * vmw_surface_define_encode - Encode a surface_define command.
+ *
+ * @srf: Pointer to a struct vmw_surface object.
+ * @cmd_space: Pointer to memory area in which the commands should be encoded.
+ */
+static void vmw_surface_define_encode(const struct vmw_surface *srf,
+				      void *cmd_space)
+{
+	struct vmw_surface_define *cmd = (struct vmw_surface_define *)
+		cmd_space;
+	struct drm_vmw_size *src_size;
+	SVGA3dSize *cmd_size;
+	uint32_t cmd_len;
+	int i;
+
+	cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize);
+
+	cmd->header.id = SVGA_3D_CMD_SURFACE_DEFINE;
+	cmd->header.size = cmd_len;
+	cmd->body.sid = srf->res.id;
+	cmd->body.surfaceFlags = srf->flags;
+	cmd->body.format = cpu_to_le32(srf->format);
+	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
+		cmd->body.face[i].numMipLevels = srf->mip_levels[i];
+
+	cmd += 1;
+	cmd_size = (SVGA3dSize *) cmd;
+	src_size = srf->sizes;
+
+	for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) {
+		cmd_size->width = src_size->width;
+		cmd_size->height = src_size->height;
+		cmd_size->depth = src_size->depth;
+	}
+}
+
+
+/**
+ * vmw_surface_dma_encode - Encode a surface_dma command.
+ *
+ * @srf: Pointer to a struct vmw_surface object.
+ * @cmd_space: Pointer to memory area in which the commands should be encoded.
+ * @ptr: Pointer to an SVGAGuestPtr indicating where the surface contents
+ * should be placed or read from.
+ * @to_surface: Boolean whether to DMA to the surface or from the surface.
+ */
+static void vmw_surface_dma_encode(struct vmw_surface *srf,
+				   void *cmd_space,
+				   const SVGAGuestPtr *ptr,
+				   bool to_surface)
+{
+	uint32_t i;
+	uint32_t bpp = vmw_sf_bpp[srf->format].bpp;
+	uint32_t stride_bpp = vmw_sf_bpp[srf->format].s_bpp;
+	struct vmw_surface_dma *cmd = (struct vmw_surface_dma *)cmd_space;
+
+	for (i = 0; i < srf->num_sizes; ++i) {
+		SVGA3dCmdHeader *header = &cmd->header;
+		SVGA3dCmdSurfaceDMA *body = &cmd->body;
+		SVGA3dCopyBox *cb = &cmd->cb;
+		SVGA3dCmdSurfaceDMASuffix *suffix = &cmd->suffix;
+		const struct vmw_surface_offset *cur_offset = &srf->offsets[i];
+		const struct drm_vmw_size *cur_size = &srf->sizes[i];
+
+		header->id = SVGA_3D_CMD_SURFACE_DMA;
+		header->size = sizeof(*body) + sizeof(*cb) + sizeof(*suffix);
+
+		body->guest.ptr = *ptr;
+		body->guest.ptr.offset += cur_offset->bo_offset;
+		body->guest.pitch = (cur_size->width * stride_bpp + 7) >> 3;
+		body->host.sid = srf->res.id;
+		body->host.face = cur_offset->face;
+		body->host.mipmap = cur_offset->mip;
+		body->transfer = ((to_surface) ?  SVGA3D_WRITE_HOST_VRAM :
+				  SVGA3D_READ_HOST_VRAM);
+		cb->x = 0;
+		cb->y = 0;
+		cb->z = 0;
+		cb->srcx = 0;
+		cb->srcy = 0;
+		cb->srcz = 0;
+		cb->w = cur_size->width;
+		cb->h = cur_size->height;
+		cb->d = cur_size->depth;
+
+		suffix->suffixSize = sizeof(*suffix);
+		suffix->maximumOffset = body->guest.pitch*cur_size->height*
+			cur_size->depth*bpp / stride_bpp;
+		suffix->flags.discard = 0;
+		suffix->flags.unsynchronized = 0;
+		suffix->flags.reserved = 0;
+		++cmd;
+	}
+};
+
+
 static void vmw_hw_surface_destroy(struct vmw_resource *res)
 {
 
 	struct vmw_private *dev_priv = res->dev_priv;
-	struct {
-		SVGA3dCmdHeader header;
-		SVGA3dCmdDestroySurface body;
-	} *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+	struct vmw_surface *srf;
+	void *cmd;
 
-	if (unlikely(cmd == NULL)) {
-		DRM_ERROR("Failed reserving FIFO space for surface "
-			  "destruction.\n");
-		return;
-	}
+	if (res->id != -1) {
 
-	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DESTROY);
-	cmd->header.size = cpu_to_le32(sizeof(cmd->body));
-	cmd->body.sid = cpu_to_le32(res->id);
+		cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size());
+		if (unlikely(cmd == NULL)) {
+			DRM_ERROR("Failed reserving FIFO space for surface "
+				  "destruction.\n");
+			return;
+		}
 
-	vmw_fifo_commit(dev_priv, sizeof(*cmd));
-	vmw_3d_resource_dec(dev_priv);
+		vmw_surface_destroy_encode(res->id, cmd);
+		vmw_fifo_commit(dev_priv, vmw_surface_destroy_size());
+
+		/*
+		 * used_memory_size_atomic, or separate lock
+		 * to avoid taking dev_priv::cmdbuf_mutex in
+		 * the destroy path.
+		 */
+
+		mutex_lock(&dev_priv->cmdbuf_mutex);
+		srf = container_of(res, struct vmw_surface, res);
+		dev_priv->used_memory_size -= srf->backup_size;
+		mutex_unlock(&dev_priv->cmdbuf_mutex);
+
+	}
+	vmw_3d_resource_dec(dev_priv, false);
 }
 
 void vmw_surface_res_free(struct vmw_resource *res)
 {
 	struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
 
+	if (srf->backup)
+		ttm_bo_unref(&srf->backup);
+	kfree(srf->offsets);
 	kfree(srf->sizes);
 	kfree(srf->snooper.image);
 	kfree(srf);
 }
 
-int vmw_surface_init(struct vmw_private *dev_priv,
-		     struct vmw_surface *srf,
-		     void (*res_free) (struct vmw_resource *res))
+
+/**
+ * vmw_surface_do_validate - make a surface available to the device.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @srf: Pointer to a struct vmw_surface.
+ *
+ * If the surface doesn't have a hw id, allocate one, and optionally
+ * DMA the backed up surface contents to the device.
+ *
+ * Returns -EBUSY if there wasn't sufficient device resources to
+ * complete the validation. Retry after freeing up resources.
+ *
+ * May return other errors if the kernel is out of guest resources.
+ */
+int vmw_surface_do_validate(struct vmw_private *dev_priv,
+			    struct vmw_surface *srf)
 {
-	int ret;
-	struct {
-		SVGA3dCmdHeader header;
-		SVGA3dCmdDefineSurface body;
-	} *cmd;
-	SVGA3dSize *cmd_size;
 	struct vmw_resource *res = &srf->res;
-	struct drm_vmw_size *src_size;
-	size_t submit_size;
-	uint32_t cmd_len;
-	int i;
+	struct list_head val_list;
+	struct ttm_validate_buffer val_buf;
+	uint32_t submit_size;
+	uint8_t *cmd;
+	int ret;
 
-	BUG_ON(res_free == NULL);
-	ret = vmw_resource_init(dev_priv, res, &dev_priv->surface_idr,
-				VMW_RES_SURFACE, res_free);
+	if (likely(res->id != -1))
+		return 0;
+
+	if (unlikely(dev_priv->used_memory_size + srf->backup_size >=
+		     dev_priv->memory_size))
+		return -EBUSY;
+
+	/*
+	 * Reserve- and validate the backup DMA bo.
+	 */
+
+	if (srf->backup) {
+		INIT_LIST_HEAD(&val_list);
+		val_buf.bo = ttm_bo_reference(srf->backup);
+		val_buf.new_sync_obj_arg = (void *)((unsigned long)
+						    DRM_VMW_FENCE_FLAG_EXEC);
+		list_add_tail(&val_buf.head, &val_list);
+		ret = ttm_eu_reserve_buffers(&val_list);
+		if (unlikely(ret != 0))
+			goto out_no_reserve;
+
+		ret = ttm_bo_validate(srf->backup, &vmw_srf_placement,
+				      true, false, false);
+		if (unlikely(ret != 0))
+			goto out_no_validate;
+	}
 
+	/*
+	 * Alloc id for the resource.
+	 */
+
+	ret = vmw_resource_alloc_id(dev_priv, res);
 	if (unlikely(ret != 0)) {
-		res_free(res);
-		return ret;
+		DRM_ERROR("Failed to allocate a surface id.\n");
+		goto out_no_id;
+	}
+	if (unlikely(res->id >= SVGA3D_MAX_SURFACE_IDS)) {
+		ret = -EBUSY;
+		goto out_no_fifo;
 	}
 
-	submit_size = sizeof(*cmd) + srf->num_sizes * sizeof(SVGA3dSize);
-	cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize);
+
+	/*
+	 * Encode surface define- and dma commands.
+	 */
+
+	submit_size = vmw_surface_define_size(srf);
+	if (srf->backup)
+		submit_size += vmw_surface_dma_size(srf);
 
 	cmd = vmw_fifo_reserve(dev_priv, submit_size);
 	if (unlikely(cmd == NULL)) {
-		DRM_ERROR("Fifo reserve failed for create surface.\n");
-		vmw_resource_unreference(&res);
-		return -ENOMEM;
+		DRM_ERROR("Failed reserving FIFO space for surface "
+			  "validation.\n");
+		ret = -ENOMEM;
+		goto out_no_fifo;
 	}
 
-	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DEFINE);
-	cmd->header.size = cpu_to_le32(cmd_len);
-	cmd->body.sid = cpu_to_le32(res->id);
-	cmd->body.surfaceFlags = cpu_to_le32(srf->flags);
-	cmd->body.format = cpu_to_le32(srf->format);
-	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
-		cmd->body.face[i].numMipLevels =
-		    cpu_to_le32(srf->mip_levels[i]);
+	vmw_surface_define_encode(srf, cmd);
+	if (srf->backup) {
+		SVGAGuestPtr ptr;
+
+		cmd += vmw_surface_define_size(srf);
+		vmw_bo_get_guest_ptr(srf->backup, &ptr);
+		vmw_surface_dma_encode(srf, cmd, &ptr, true);
 	}
 
-	cmd += 1;
-	cmd_size = (SVGA3dSize *) cmd;
-	src_size = srf->sizes;
+	vmw_fifo_commit(dev_priv, submit_size);
 
-	for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) {
-		cmd_size->width = cpu_to_le32(src_size->width);
-		cmd_size->height = cpu_to_le32(src_size->height);
-		cmd_size->depth = cpu_to_le32(src_size->depth);
+	/*
+	 * Create a fence object and fence the backup buffer.
+	 */
+
+	if (srf->backup) {
+		struct vmw_fence_obj *fence;
+
+		(void) vmw_execbuf_fence_commands(NULL, dev_priv,
+						  &fence, NULL);
+		ttm_eu_fence_buffer_objects(&val_list, fence);
+		if (likely(fence != NULL))
+			vmw_fence_obj_unreference(&fence);
+		ttm_bo_unref(&val_buf.bo);
+		ttm_bo_unref(&srf->backup);
+	}
+
+	/*
+	 * Surface memory usage accounting.
+	 */
+
+	dev_priv->used_memory_size += srf->backup_size;
+
+	return 0;
+
+out_no_fifo:
+	vmw_resource_release_id(res);
+out_no_id:
+out_no_validate:
+	if (srf->backup)
+		ttm_eu_backoff_reservation(&val_list);
+out_no_reserve:
+	if (srf->backup)
+		ttm_bo_unref(&val_buf.bo);
+	return ret;
+}
+
+/**
+ * vmw_surface_evict - Evict a hw surface.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @srf: Pointer to a struct vmw_surface
+ *
+ * DMA the contents of a hw surface to a backup guest buffer object,
+ * and destroy the hw surface, releasing its id.
+ */
+int vmw_surface_evict(struct vmw_private *dev_priv,
+		      struct vmw_surface *srf)
+{
+	struct vmw_resource *res = &srf->res;
+	struct list_head val_list;
+	struct ttm_validate_buffer val_buf;
+	uint32_t submit_size;
+	uint8_t *cmd;
+	int ret;
+	struct vmw_fence_obj *fence;
+	SVGAGuestPtr ptr;
+
+	BUG_ON(res->id == -1);
+
+	/*
+	 * Create a surface backup buffer object.
+	 */
+
+	if (!srf->backup) {
+		ret = ttm_bo_create(&dev_priv->bdev, srf->backup_size,
+				    ttm_bo_type_device,
+				    &vmw_srf_placement, 0, 0, true,
+				    NULL, &srf->backup);
+		if (unlikely(ret != 0))
+			return ret;
 	}
 
+	/*
+	 * Reserve- and validate the backup DMA bo.
+	 */
+
+	INIT_LIST_HEAD(&val_list);
+	val_buf.bo = ttm_bo_reference(srf->backup);
+	val_buf.new_sync_obj_arg = (void *)(unsigned long)
+		DRM_VMW_FENCE_FLAG_EXEC;
+	list_add_tail(&val_buf.head, &val_list);
+	ret = ttm_eu_reserve_buffers(&val_list);
+	if (unlikely(ret != 0))
+		goto out_no_reserve;
+
+	ret = ttm_bo_validate(srf->backup, &vmw_srf_placement,
+			      true, false, false);
+	if (unlikely(ret != 0))
+		goto out_no_validate;
+
+
+	/*
+	 * Encode the dma- and surface destroy commands.
+	 */
+
+	submit_size = vmw_surface_dma_size(srf) + vmw_surface_destroy_size();
+	cmd = vmw_fifo_reserve(dev_priv, submit_size);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed reserving FIFO space for surface "
+			  "eviction.\n");
+		ret = -ENOMEM;
+		goto out_no_fifo;
+	}
+
+	vmw_bo_get_guest_ptr(srf->backup, &ptr);
+	vmw_surface_dma_encode(srf, cmd, &ptr, false);
+	cmd += vmw_surface_dma_size(srf);
+	vmw_surface_destroy_encode(res->id, cmd);
 	vmw_fifo_commit(dev_priv, submit_size);
-	(void) vmw_3d_resource_inc(dev_priv);
-	vmw_resource_activate(res, vmw_hw_surface_destroy);
+
+	/*
+	 * Surface memory usage accounting.
+	 */
+
+	dev_priv->used_memory_size -= srf->backup_size;
+
+	/*
+	 * Create a fence object and fence the DMA buffer.
+	 */
+
+	(void) vmw_execbuf_fence_commands(NULL, dev_priv,
+					  &fence, NULL);
+	ttm_eu_fence_buffer_objects(&val_list, fence);
+	if (likely(fence != NULL))
+		vmw_fence_obj_unreference(&fence);
+	ttm_bo_unref(&val_buf.bo);
+
+	/*
+	 * Release the surface ID.
+	 */
+
+	vmw_resource_release_id(res);
+
 	return 0;
+
+out_no_fifo:
+out_no_validate:
+	if (srf->backup)
+		ttm_eu_backoff_reservation(&val_list);
+out_no_reserve:
+	ttm_bo_unref(&val_buf.bo);
+	ttm_bo_unref(&srf->backup);
+	return ret;
+}
+
+
+/**
+ * vmw_surface_validate - make a surface available to the device, evicting
+ * other surfaces if needed.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @srf: Pointer to a struct vmw_surface.
+ *
+ * Try to validate a surface and if it fails due to limited device resources,
+ * repeatedly try to evict other surfaces until the request can be
+ * acommodated.
+ *
+ * May return errors if out of resources.
+ */
+int vmw_surface_validate(struct vmw_private *dev_priv,
+			 struct vmw_surface *srf)
+{
+	int ret;
+	struct vmw_surface *evict_srf;
+
+	do {
+		write_lock(&dev_priv->resource_lock);
+		list_del_init(&srf->lru_head);
+		write_unlock(&dev_priv->resource_lock);
+
+		ret = vmw_surface_do_validate(dev_priv, srf);
+		if (likely(ret != -EBUSY))
+			break;
+
+		write_lock(&dev_priv->resource_lock);
+		if (list_empty(&dev_priv->surface_lru)) {
+			DRM_ERROR("Out of device memory for surfaces.\n");
+			ret = -EBUSY;
+			write_unlock(&dev_priv->resource_lock);
+			break;
+		}
+
+		evict_srf = vmw_surface_reference
+			(list_first_entry(&dev_priv->surface_lru,
+					  struct vmw_surface,
+					  lru_head));
+		list_del_init(&evict_srf->lru_head);
+
+		write_unlock(&dev_priv->resource_lock);
+		(void) vmw_surface_evict(dev_priv, evict_srf);
+
+		vmw_surface_unreference(&evict_srf);
+
+	} while (1);
+
+	if (unlikely(ret != 0 && srf->res.id != -1)) {
+		write_lock(&dev_priv->resource_lock);
+		list_add_tail(&srf->lru_head, &dev_priv->surface_lru);
+		write_unlock(&dev_priv->resource_lock);
+	}
+
+	return ret;
+}
+
+
+/**
+ * vmw_surface_remove_from_lists - Remove surface resources from lookup lists
+ *
+ * @res: Pointer to a struct vmw_resource embedded in a struct vmw_surface
+ *
+ * As part of the resource destruction, remove the surface from any
+ * lookup lists.
+ */
+static void vmw_surface_remove_from_lists(struct vmw_resource *res)
+{
+	struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
+
+	list_del_init(&srf->lru_head);
+}
+
+int vmw_surface_init(struct vmw_private *dev_priv,
+		     struct vmw_surface *srf,
+		     void (*res_free) (struct vmw_resource *res))
+{
+	int ret;
+	struct vmw_resource *res = &srf->res;
+
+	BUG_ON(res_free == NULL);
+	INIT_LIST_HEAD(&srf->lru_head);
+	ret = vmw_resource_init(dev_priv, res, &dev_priv->surface_idr,
+				VMW_RES_SURFACE, true, res_free,
+				vmw_surface_remove_from_lists);
+
+	if (unlikely(ret != 0))
+		res_free(res);
+
+	/*
+	 * The surface won't be visible to hardware until a
+	 * surface validate.
+	 */
+
+	(void) vmw_3d_resource_inc(dev_priv, false);
+	vmw_resource_activate(res, vmw_hw_surface_destroy);
+	return ret;
 }
 
 static void vmw_user_surface_free(struct vmw_resource *res)
@@ -486,12 +1139,81 @@
 	struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
 	struct vmw_user_surface *user_srf =
 	    container_of(srf, struct vmw_user_surface, srf);
+	struct vmw_private *dev_priv = srf->res.dev_priv;
+	uint32_t size = user_srf->size;
 
+	if (srf->backup)
+		ttm_bo_unref(&srf->backup);
+	kfree(srf->offsets);
 	kfree(srf->sizes);
 	kfree(srf->snooper.image);
 	kfree(user_srf);
+	ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
+}
+
+/**
+ * vmw_resource_unreserve - unreserve resources previously reserved for
+ * command submission.
+ *
+ * @list_head: list of resources to unreserve.
+ *
+ * Currently only surfaces are considered, and unreserving a surface
+ * means putting it back on the device's surface lru list,
+ * so that it can be evicted if necessary.
+ * This function traverses the resource list and
+ * checks whether resources are surfaces, and in that case puts them back
+ * on the device's surface LRU list.
+ */
+void vmw_resource_unreserve(struct list_head *list)
+{
+	struct vmw_resource *res;
+	struct vmw_surface *srf;
+	rwlock_t *lock = NULL;
+
+	list_for_each_entry(res, list, validate_head) {
+
+		if (res->res_free != &vmw_surface_res_free &&
+		    res->res_free != &vmw_user_surface_free)
+			continue;
+
+		if (unlikely(lock == NULL)) {
+			lock = &res->dev_priv->resource_lock;
+			write_lock(lock);
+		}
+
+		srf = container_of(res, struct vmw_surface, res);
+		list_del_init(&srf->lru_head);
+		list_add_tail(&srf->lru_head, &res->dev_priv->surface_lru);
+	}
+
+	if (lock != NULL)
+		write_unlock(lock);
+}
+
+/**
+ * Helper function that looks either a surface or dmabuf.
+ *
+ * The pointer this pointed at by out_surf and out_buf needs to be null.
+ */
+int vmw_user_lookup_handle(struct vmw_private *dev_priv,
+			   struct ttm_object_file *tfile,
+			   uint32_t handle,
+			   struct vmw_surface **out_surf,
+			   struct vmw_dma_buffer **out_buf)
+{
+	int ret;
+
+	BUG_ON(*out_surf || *out_buf);
+
+	ret = vmw_user_surface_lookup_handle(dev_priv, tfile, handle, out_surf);
+	if (!ret)
+		return 0;
+
+	ret = vmw_user_dmabuf_lookup(tfile, handle, out_buf);
+	return ret;
 }
 
+
 int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv,
 				   struct ttm_object_file *tfile,
 				   uint32_t handle, struct vmw_surface **out)
@@ -556,8 +1278,7 @@
 			     struct drm_file *file_priv)
 {
 	struct vmw_private *dev_priv = vmw_priv(dev);
-	struct vmw_user_surface *user_srf =
-	    kmalloc(sizeof(*user_srf), GFP_KERNEL);
+	struct vmw_user_surface *user_srf;
 	struct vmw_surface *srf;
 	struct vmw_resource *res;
 	struct vmw_resource *tmp;
@@ -568,10 +1289,51 @@
 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
 	struct drm_vmw_size __user *user_sizes;
 	int ret;
-	int i;
+	int i, j;
+	uint32_t cur_bo_offset;
+	struct drm_vmw_size *cur_size;
+	struct vmw_surface_offset *cur_offset;
+	uint32_t stride_bpp;
+	uint32_t bpp;
+	uint32_t num_sizes;
+	uint32_t size;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
 
-	if (unlikely(user_srf == NULL))
-		return -ENOMEM;
+	if (unlikely(vmw_user_surface_size == 0))
+		vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
+			128;
+
+	num_sizes = 0;
+	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
+		num_sizes += req->mip_levels[i];
+
+	if (num_sizes > DRM_VMW_MAX_SURFACE_FACES *
+	    DRM_VMW_MAX_MIP_LEVELS)
+		return -EINVAL;
+
+	size = vmw_user_surface_size + 128 +
+		ttm_round_pot(num_sizes * sizeof(struct drm_vmw_size)) +
+		ttm_round_pot(num_sizes * sizeof(struct vmw_surface_offset));
+
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+				   size, false, true);
+	if (unlikely(ret != 0)) {
+		if (ret != -ERESTARTSYS)
+			DRM_ERROR("Out of graphics memory for surface"
+				  " creation.\n");
+		goto out_unlock;
+	}
+
+	user_srf = kmalloc(sizeof(*user_srf), GFP_KERNEL);
+	if (unlikely(user_srf == NULL)) {
+		ret = -ENOMEM;
+		goto out_no_user_srf;
+	}
 
 	srf = &user_srf->srf;
 	res = &srf->res;
@@ -579,21 +1341,22 @@
 	srf->flags = req->flags;
 	srf->format = req->format;
 	srf->scanout = req->scanout;
-	memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
-	srf->num_sizes = 0;
-	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
-		srf->num_sizes += srf->mip_levels[i];
+	srf->backup = NULL;
 
-	if (srf->num_sizes > DRM_VMW_MAX_SURFACE_FACES *
-	    DRM_VMW_MAX_MIP_LEVELS) {
-		ret = -EINVAL;
-		goto out_err0;
-	}
+	memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
+	srf->num_sizes = num_sizes;
+	user_srf->size = size;
 
 	srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL);
 	if (unlikely(srf->sizes == NULL)) {
 		ret = -ENOMEM;
-		goto out_err0;
+		goto out_no_sizes;
+	}
+	srf->offsets = kmalloc(srf->num_sizes * sizeof(*srf->offsets),
+			       GFP_KERNEL);
+	if (unlikely(srf->sizes == NULL)) {
+		ret = -ENOMEM;
+		goto out_no_offsets;
 	}
 
 	user_sizes = (struct drm_vmw_size __user *)(unsigned long)
@@ -603,9 +1366,32 @@
 			     srf->num_sizes * sizeof(*srf->sizes));
 	if (unlikely(ret != 0)) {
 		ret = -EFAULT;
-		goto out_err1;
+		goto out_no_copy;
 	}
 
+	cur_bo_offset = 0;
+	cur_offset = srf->offsets;
+	cur_size = srf->sizes;
+
+	bpp = vmw_sf_bpp[srf->format].bpp;
+	stride_bpp = vmw_sf_bpp[srf->format].s_bpp;
+
+	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
+		for (j = 0; j < srf->mip_levels[i]; ++j) {
+			uint32_t stride =
+				(cur_size->width * stride_bpp + 7) >> 3;
+
+			cur_offset->face = i;
+			cur_offset->mip = j;
+			cur_offset->bo_offset = cur_bo_offset;
+			cur_bo_offset += stride * cur_size->height *
+				cur_size->depth * bpp / stride_bpp;
+			++cur_offset;
+			++cur_size;
+		}
+	}
+	srf->backup_size = cur_bo_offset;
+
 	if (srf->scanout &&
 	    srf->num_sizes == 1 &&
 	    srf->sizes[0].width == 64 &&
@@ -617,7 +1403,7 @@
 		if (!srf->snooper.image) {
 			DRM_ERROR("Failed to allocate cursor_image\n");
 			ret = -ENOMEM;
-			goto out_err1;
+			goto out_no_copy;
 		}
 	} else {
 		srf->snooper.image = NULL;
@@ -634,7 +1420,7 @@
 
 	ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
 	if (unlikely(ret != 0))
-		return ret;
+		goto out_unlock;
 
 	tmp = vmw_resource_reference(&srf->res);
 	ret = ttm_base_object_init(tfile, &user_srf->base,
@@ -644,7 +1430,7 @@
 	if (unlikely(ret != 0)) {
 		vmw_resource_unreference(&tmp);
 		vmw_resource_unreference(&res);
-		return ret;
+		goto out_unlock;
 	}
 
 	rep->sid = user_srf->base.hash.key;
@@ -652,11 +1438,19 @@
 		DRM_ERROR("Created bad Surface ID.\n");
 
 	vmw_resource_unreference(&res);
+
+	ttm_read_unlock(&vmaster->lock);
 	return 0;
-out_err1:
+out_no_copy:
+	kfree(srf->offsets);
+out_no_offsets:
 	kfree(srf->sizes);
-out_err0:
+out_no_sizes:
 	kfree(user_srf);
+out_no_user_srf:
+	ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
+out_unlock:
+	ttm_read_unlock(&vmaster->lock);
 	return ret;
 }
 
@@ -970,7 +1764,7 @@
 	int ret;
 
 	ret = vmw_resource_init(dev_priv, res, &dev_priv->stream_idr,
-				VMW_RES_STREAM, res_free);
+				VMW_RES_STREAM, false, res_free, NULL);
 
 	if (unlikely(ret != 0)) {
 		if (res_free == NULL)
@@ -1000,8 +1794,11 @@
 {
 	struct vmw_user_stream *stream =
 	    container_of(res, struct vmw_user_stream, stream.res);
+	struct vmw_private *dev_priv = res->dev_priv;
 
 	kfree(stream);
+	ttm_mem_global_free(vmw_mem_glob(dev_priv),
+			    vmw_user_stream_size);
 }
 
 /**
@@ -1055,23 +1852,56 @@
 			   struct drm_file *file_priv)
 {
 	struct vmw_private *dev_priv = vmw_priv(dev);
-	struct vmw_user_stream *stream = kmalloc(sizeof(*stream), GFP_KERNEL);
+	struct vmw_user_stream *stream;
 	struct vmw_resource *res;
 	struct vmw_resource *tmp;
 	struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data;
 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
 	int ret;
 
-	if (unlikely(stream == NULL))
-		return -ENOMEM;
+	/*
+	 * Approximate idr memory usage with 128 bytes. It will be limited
+	 * by maximum number_of streams anyway?
+	 */
+
+	if (unlikely(vmw_user_stream_size == 0))
+		vmw_user_stream_size = ttm_round_pot(sizeof(*stream)) + 128;
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+				   vmw_user_stream_size,
+				   false, true);
+	if (unlikely(ret != 0)) {
+		if (ret != -ERESTARTSYS)
+			DRM_ERROR("Out of graphics memory for stream"
+				  " creation.\n");
+		goto out_unlock;
+	}
+
+
+	stream = kmalloc(sizeof(*stream), GFP_KERNEL);
+	if (unlikely(stream == NULL)) {
+		ttm_mem_global_free(vmw_mem_glob(dev_priv),
+				    vmw_user_stream_size);
+		ret = -ENOMEM;
+		goto out_unlock;
+	}
 
 	res = &stream->stream.res;
 	stream->base.shareable = false;
 	stream->base.tfile = NULL;
 
+	/*
+	 * From here on, the destructor takes over resource freeing.
+	 */
+
 	ret = vmw_stream_init(dev_priv, &stream->stream, vmw_user_stream_free);
 	if (unlikely(ret != 0))
-		return ret;
+		goto out_unlock;
 
 	tmp = vmw_resource_reference(res);
 	ret = ttm_base_object_init(tfile, &stream->base, false, VMW_RES_STREAM,
@@ -1085,6 +1915,8 @@
 	arg->stream_id = res->id;
 out_err:
 	vmw_resource_unreference(&res);
+out_unlock:
+	ttm_read_unlock(&vmaster->lock);
 	return ret;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,537 @@
+/**************************************************************************
+ *
+ * Copyright Â© 2011 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_kms.h"
+
+
+#define vmw_crtc_to_sou(x) \
+	container_of(x, struct vmw_screen_object_unit, base.crtc)
+#define vmw_encoder_to_sou(x) \
+	container_of(x, struct vmw_screen_object_unit, base.encoder)
+#define vmw_connector_to_sou(x) \
+	container_of(x, struct vmw_screen_object_unit, base.connector)
+
+struct vmw_screen_object_display {
+	unsigned num_implicit;
+
+	struct vmw_framebuffer *implicit_fb;
+};
+
+/**
+ * Display unit using screen objects.
+ */
+struct vmw_screen_object_unit {
+	struct vmw_display_unit base;
+
+	unsigned long buffer_size; /**< Size of allocated buffer */
+	struct vmw_dma_buffer *buffer; /**< Backing store buffer */
+
+	bool defined;
+	bool active_implicit;
+};
+
+static void vmw_sou_destroy(struct vmw_screen_object_unit *sou)
+{
+	vmw_display_unit_cleanup(&sou->base);
+	kfree(sou);
+}
+
+
+/*
+ * Screen Object Display Unit CRTC functions
+ */
+
+static void vmw_sou_crtc_destroy(struct drm_crtc *crtc)
+{
+	vmw_sou_destroy(vmw_crtc_to_sou(crtc));
+}
+
+static void vmw_sou_del_active(struct vmw_private *vmw_priv,
+			      struct vmw_screen_object_unit *sou)
+{
+	struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
+
+	if (sou->active_implicit) {
+		if (--(ld->num_implicit) == 0)
+			ld->implicit_fb = NULL;
+		sou->active_implicit = false;
+	}
+}
+
+static void vmw_sou_add_active(struct vmw_private *vmw_priv,
+			      struct vmw_screen_object_unit *sou,
+			      struct vmw_framebuffer *vfb)
+{
+	struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
+
+	BUG_ON(!ld->num_implicit && ld->implicit_fb);
+
+	if (!sou->active_implicit && sou->base.is_implicit) {
+		ld->implicit_fb = vfb;
+		sou->active_implicit = true;
+		ld->num_implicit++;
+	}
+}
+
+/**
+ * Send the fifo command to create a screen.
+ */
+static int vmw_sou_fifo_create(struct vmw_private *dev_priv,
+			       struct vmw_screen_object_unit *sou,
+			       uint32_t x, uint32_t y,
+			       struct drm_display_mode *mode)
+{
+	size_t fifo_size;
+
+	struct {
+		struct {
+			uint32_t cmdType;
+		} header;
+		SVGAScreenObject obj;
+	} *cmd;
+
+	BUG_ON(!sou->buffer);
+
+	fifo_size = sizeof(*cmd);
+	cmd = vmw_fifo_reserve(dev_priv, fifo_size);
+	/* The hardware has hung, nothing we can do about it here. */
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed.\n");
+		return -ENOMEM;
+	}
+
+	memset(cmd, 0, fifo_size);
+	cmd->header.cmdType = SVGA_CMD_DEFINE_SCREEN;
+	cmd->obj.structSize = sizeof(SVGAScreenObject);
+	cmd->obj.id = sou->base.unit;
+	cmd->obj.flags = SVGA_SCREEN_HAS_ROOT |
+		(sou->base.unit == 0 ? SVGA_SCREEN_IS_PRIMARY : 0);
+	cmd->obj.size.width = mode->hdisplay;
+	cmd->obj.size.height = mode->vdisplay;
+	if (sou->base.is_implicit) {
+		cmd->obj.root.x = x;
+		cmd->obj.root.y = y;
+	} else {
+		cmd->obj.root.x = sou->base.gui_x;
+		cmd->obj.root.y = sou->base.gui_y;
+	}
+
+	/* Ok to assume that buffer is pinned in vram */
+	vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr);
+	cmd->obj.backingStore.pitch = mode->hdisplay * 4;
+
+	vmw_fifo_commit(dev_priv, fifo_size);
+
+	sou->defined = true;
+
+	return 0;
+}
+
+/**
+ * Send the fifo command to destroy a screen.
+ */
+static int vmw_sou_fifo_destroy(struct vmw_private *dev_priv,
+				struct vmw_screen_object_unit *sou)
+{
+	size_t fifo_size;
+	int ret;
+
+	struct {
+		struct {
+			uint32_t cmdType;
+		} header;
+		SVGAFifoCmdDestroyScreen body;
+	} *cmd;
+
+	/* no need to do anything */
+	if (unlikely(!sou->defined))
+		return 0;
+
+	fifo_size = sizeof(*cmd);
+	cmd = vmw_fifo_reserve(dev_priv, fifo_size);
+	/* the hardware has hung, nothing we can do about it here */
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed.\n");
+		return -ENOMEM;
+	}
+
+	memset(cmd, 0, fifo_size);
+	cmd->header.cmdType = SVGA_CMD_DESTROY_SCREEN;
+	cmd->body.screenId = sou->base.unit;
+
+	vmw_fifo_commit(dev_priv, fifo_size);
+
+	/* Force sync */
+	ret = vmw_fallback_wait(dev_priv, false, true, 0, false, 3*HZ);
+	if (unlikely(ret != 0))
+		DRM_ERROR("Failed to sync with HW");
+	else
+		sou->defined = false;
+
+	return ret;
+}
+
+/**
+ * Free the backing store.
+ */
+static void vmw_sou_backing_free(struct vmw_private *dev_priv,
+				 struct vmw_screen_object_unit *sou)
+{
+	struct ttm_buffer_object *bo;
+
+	if (unlikely(sou->buffer == NULL))
+		return;
+
+	bo = &sou->buffer->base;
+	ttm_bo_unref(&bo);
+	sou->buffer = NULL;
+	sou->buffer_size = 0;
+}
+
+/**
+ * Allocate the backing store for the buffer.
+ */
+static int vmw_sou_backing_alloc(struct vmw_private *dev_priv,
+				 struct vmw_screen_object_unit *sou,
+				 unsigned long size)
+{
+	int ret;
+
+	if (sou->buffer_size == size)
+		return 0;
+
+	if (sou->buffer)
+		vmw_sou_backing_free(dev_priv, sou);
+
+	sou->buffer = kzalloc(sizeof(*sou->buffer), GFP_KERNEL);
+	if (unlikely(sou->buffer == NULL))
+		return -ENOMEM;
+
+	/* After we have alloced the backing store might not be able to
+	 * resume the overlays, this is preferred to failing to alloc.
+	 */
+	vmw_overlay_pause_all(dev_priv);
+	ret = vmw_dmabuf_init(dev_priv, sou->buffer, size,
+			      &vmw_vram_ne_placement,
+			      false, &vmw_dmabuf_bo_free);
+	vmw_overlay_resume_all(dev_priv);
+
+	if (unlikely(ret != 0))
+		sou->buffer = NULL; /* vmw_dmabuf_init frees on error */
+	else
+		sou->buffer_size = size;
+
+	return ret;
+}
+
+static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
+{
+	struct vmw_private *dev_priv;
+	struct vmw_screen_object_unit *sou;
+	struct drm_connector *connector;
+	struct drm_display_mode *mode;
+	struct drm_encoder *encoder;
+	struct vmw_framebuffer *vfb;
+	struct drm_framebuffer *fb;
+	struct drm_crtc *crtc;
+	int ret = 0;
+
+	if (!set)
+		return -EINVAL;
+
+	if (!set->crtc)
+		return -EINVAL;
+
+	/* get the sou */
+	crtc = set->crtc;
+	sou = vmw_crtc_to_sou(crtc);
+	vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL;
+	dev_priv = vmw_priv(crtc->dev);
+
+	if (set->num_connectors > 1) {
+		DRM_ERROR("to many connectors\n");
+		return -EINVAL;
+	}
+
+	if (set->num_connectors == 1 &&
+	    set->connectors[0] != &sou->base.connector) {
+		DRM_ERROR("connector doesn't match %p %p\n",
+			set->connectors[0], &sou->base.connector);
+		return -EINVAL;
+	}
+
+	/* sou only supports one fb active at the time */
+	if (sou->base.is_implicit &&
+	    dev_priv->sou_priv->implicit_fb && vfb &&
+	    !(dev_priv->sou_priv->num_implicit == 1 &&
+	      sou->active_implicit) &&
+	    dev_priv->sou_priv->implicit_fb != vfb) {
+		DRM_ERROR("Multiple framebuffers not supported\n");
+		return -EINVAL;
+	}
+
+	/* since they always map one to one these are safe */
+	connector = &sou->base.connector;
+	encoder = &sou->base.encoder;
+
+	/* should we turn the crtc off */
+	if (set->num_connectors == 0 || !set->mode || !set->fb) {
+		ret = vmw_sou_fifo_destroy(dev_priv, sou);
+		/* the hardware has hung don't do anything more */
+		if (unlikely(ret != 0))
+			return ret;
+
+		connector->encoder = NULL;
+		encoder->crtc = NULL;
+		crtc->fb = NULL;
+		crtc->x = 0;
+		crtc->y = 0;
+
+		vmw_sou_del_active(dev_priv, sou);
+
+		vmw_sou_backing_free(dev_priv, sou);
+
+		return 0;
+	}
+
+
+	/* we now know we want to set a mode */
+	mode = set->mode;
+	fb = set->fb;
+
+	if (set->x + mode->hdisplay > fb->width ||
+	    set->y + mode->vdisplay > fb->height) {
+		DRM_ERROR("set outside of framebuffer\n");
+		return -EINVAL;
+	}
+
+	vmw_fb_off(dev_priv);
+
+	if (mode->hdisplay != crtc->mode.hdisplay ||
+	    mode->vdisplay != crtc->mode.vdisplay) {
+		/* no need to check if depth is different, because backing
+		 * store depth is forced to 4 by the device.
+		 */
+
+		ret = vmw_sou_fifo_destroy(dev_priv, sou);
+		/* the hardware has hung don't do anything more */
+		if (unlikely(ret != 0))
+			return ret;
+
+		vmw_sou_backing_free(dev_priv, sou);
+	}
+
+	if (!sou->buffer) {
+		/* forced to depth 4 by the device */
+		size_t size = mode->hdisplay * mode->vdisplay * 4;
+		ret = vmw_sou_backing_alloc(dev_priv, sou, size);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+
+	ret = vmw_sou_fifo_create(dev_priv, sou, set->x, set->y, mode);
+	if (unlikely(ret != 0)) {
+		/*
+		 * We are in a bit of a situation here, the hardware has
+		 * hung and we may or may not have a buffer hanging of
+		 * the screen object, best thing to do is not do anything
+		 * if we where defined, if not just turn the crtc of.
+		 * Not what userspace wants but it needs to htfu.
+		 */
+		if (sou->defined)
+			return ret;
+
+		connector->encoder = NULL;
+		encoder->crtc = NULL;
+		crtc->fb = NULL;
+		crtc->x = 0;
+		crtc->y = 0;
+
+		return ret;
+	}
+
+	vmw_sou_add_active(dev_priv, sou, vfb);
+
+	connector->encoder = encoder;
+	encoder->crtc = crtc;
+	crtc->mode = *mode;
+	crtc->fb = fb;
+	crtc->x = set->x;
+	crtc->y = set->y;
+
+	return 0;
+}
+
+static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
+	.save = vmw_du_crtc_save,
+	.restore = vmw_du_crtc_restore,
+	.cursor_set = vmw_du_crtc_cursor_set,
+	.cursor_move = vmw_du_crtc_cursor_move,
+	.gamma_set = vmw_du_crtc_gamma_set,
+	.destroy = vmw_sou_crtc_destroy,
+	.set_config = vmw_sou_crtc_set_config,
+};
+
+/*
+ * Screen Object Display Unit encoder functions
+ */
+
+static void vmw_sou_encoder_destroy(struct drm_encoder *encoder)
+{
+	vmw_sou_destroy(vmw_encoder_to_sou(encoder));
+}
+
+static struct drm_encoder_funcs vmw_screen_object_encoder_funcs = {
+	.destroy = vmw_sou_encoder_destroy,
+};
+
+/*
+ * Screen Object Display Unit connector functions
+ */
+
+static void vmw_sou_connector_destroy(struct drm_connector *connector)
+{
+	vmw_sou_destroy(vmw_connector_to_sou(connector));
+}
+
+static struct drm_connector_funcs vmw_legacy_connector_funcs = {
+	.dpms = vmw_du_connector_dpms,
+	.save = vmw_du_connector_save,
+	.restore = vmw_du_connector_restore,
+	.detect = vmw_du_connector_detect,
+	.fill_modes = vmw_du_connector_fill_modes,
+	.set_property = vmw_du_connector_set_property,
+	.destroy = vmw_sou_connector_destroy,
+};
+
+static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
+{
+	struct vmw_screen_object_unit *sou;
+	struct drm_device *dev = dev_priv->dev;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	struct drm_crtc *crtc;
+
+	sou = kzalloc(sizeof(*sou), GFP_KERNEL);
+	if (!sou)
+		return -ENOMEM;
+
+	sou->base.unit = unit;
+	crtc = &sou->base.crtc;
+	encoder = &sou->base.encoder;
+	connector = &sou->base.connector;
+
+	sou->active_implicit = false;
+
+	sou->base.pref_active = (unit == 0);
+	sou->base.pref_width = 800;
+	sou->base.pref_height = 600;
+	sou->base.pref_mode = NULL;
+	sou->base.is_implicit = true;
+
+	drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
+			   DRM_MODE_CONNECTOR_VIRTUAL);
+	connector->status = vmw_du_connector_detect(connector, true);
+
+	drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
+			 DRM_MODE_ENCODER_VIRTUAL);
+	drm_mode_connector_attach_encoder(connector, encoder);
+	encoder->possible_crtcs = (1 << unit);
+	encoder->possible_clones = 0;
+
+	drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
+
+	drm_mode_crtc_set_gamma_size(crtc, 256);
+
+	drm_connector_attach_property(connector,
+				      dev->mode_config.dirty_info_property,
+				      1);
+
+	return 0;
+}
+
+int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	int i, ret;
+
+	if (dev_priv->sou_priv) {
+		DRM_INFO("sou system already on\n");
+		return -EINVAL;
+	}
+
+	if (!(dev_priv->fifo.capabilities & SVGA_FIFO_CAP_SCREEN_OBJECT_2)) {
+		DRM_INFO("Not using screen objects,"
+			 " missing cap SCREEN_OBJECT_2\n");
+		return -ENOSYS;
+	}
+
+	ret = -ENOMEM;
+	dev_priv->sou_priv = kmalloc(sizeof(*dev_priv->sou_priv), GFP_KERNEL);
+	if (unlikely(!dev_priv->sou_priv))
+		goto err_no_mem;
+
+	dev_priv->sou_priv->num_implicit = 0;
+	dev_priv->sou_priv->implicit_fb = NULL;
+
+	ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
+	if (unlikely(ret != 0))
+		goto err_free;
+
+	ret = drm_mode_create_dirty_info_property(dev);
+	if (unlikely(ret != 0))
+		goto err_vblank_cleanup;
+
+	for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
+		vmw_sou_init(dev_priv, i);
+
+	DRM_INFO("Screen objects system initialized\n");
+
+	return 0;
+
+err_vblank_cleanup:
+	drm_vblank_cleanup(dev);
+err_free:
+	kfree(dev_priv->sou_priv);
+	dev_priv->sou_priv = NULL;
+err_no_mem:
+	return ret;
+}
+
+int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+
+	if (!dev_priv->sou_priv)
+		return -ENOSYS;
+
+	drm_vblank_cleanup(dev);
+
+	kfree(dev_priv->sou_priv);
+
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
--- linux-libre-3.1-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,9 +34,8 @@
 	struct vmw_private *dev_priv;
 
 	if (unlikely(vma->vm_pgoff < VMWGFX_FILE_PAGE_OFFSET)) {
-		if (vmw_fifo_mmap(filp, vma) == 0)
-			return 0;
-		return drm_mmap(filp, vma);
+		DRM_ERROR("Illegal attempt to mmap old fifo space.\n");
+		return -EINVAL;
 	}
 
 	file_priv = filp->private_data;
diff -druN linux-libre-3.1-gnu/drivers/gpu/vga/vgaarb.c linux-libre-3.2-gnu/drivers/gpu/vga/vgaarb.c
--- linux-libre-3.1-gnu/drivers/gpu/vga/vgaarb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/gpu/vga/vgaarb.c	2012-01-04 18:55:44.000000000 -0500
@@ -465,31 +465,29 @@
 	while (new_bus) {
 		new_bridge = new_bus->self;
 
-		if (new_bridge) {
-			/* go through list of devices already registered */
-			list_for_each_entry(same_bridge_vgadev, &vga_list, list) {
-				bus = same_bridge_vgadev->pdev->bus;
-				bridge = bus->self;
+		/* go through list of devices already registered */
+		list_for_each_entry(same_bridge_vgadev, &vga_list, list) {
+			bus = same_bridge_vgadev->pdev->bus;
+			bridge = bus->self;
 
-				/* see if the share a bridge with this device */
-				if (new_bridge == bridge) {
-					/* if their direct parent bridge is the same
-					   as any bridge of this device then it can't be used
-					   for that device */
-					same_bridge_vgadev->bridge_has_one_vga = false;
-				}
+			/* see if the share a bridge with this device */
+			if (new_bridge == bridge) {
+				/* if their direct parent bridge is the same
+				   as any bridge of this device then it can't be used
+				   for that device */
+				same_bridge_vgadev->bridge_has_one_vga = false;
+			}
 
-				/* now iterate the previous devices bridge hierarchy */
-				/* if the new devices parent bridge is in the other devices
-				   hierarchy then we can't use it to control this device */
-				while (bus) {
-					bridge = bus->self;
-					if (bridge) {
-						if (bridge == vgadev->pdev->bus->self)
-							vgadev->bridge_has_one_vga = false;
-					}
-					bus = bus->parent;
+			/* now iterate the previous devices bridge hierarchy */
+			/* if the new devices parent bridge is in the other devices
+			   hierarchy then we can't use it to control this device */
+			while (bus) {
+				bridge = bus->self;
+				if (bridge) {
+					if (bridge == vgadev->pdev->bus->self)
+						vgadev->bridge_has_one_vga = false;
 				}
+				bus = bus->parent;
 			}
 		}
 		new_bus = new_bus->parent;
@@ -993,14 +991,20 @@
 				uc = &priv->cards[i];
 		}
 
-		if (!uc)
-			return -EINVAL;
+		if (!uc) {
+			ret_val = -EINVAL;
+			goto done;
+		}
 
-		if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0)
-			return -EINVAL;
+		if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0) {
+			ret_val = -EINVAL;
+			goto done;
+		}
 
-		if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0)
-			return -EINVAL;
+		if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0) {
+			ret_val = -EINVAL;
+			goto done;
+		}
 
 		vga_put(pdev, io_state);
 
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-apple.c linux-libre-3.2-gnu/drivers/hid/hid-apple.c
--- linux-libre-3.1-gnu/drivers/hid/hid-apple.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-apple.c	2012-01-04 18:55:44.000000000 -0500
@@ -455,6 +455,9 @@
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
 			APPLE_ISO_KEYBOARD },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO),
+		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+			APPLE_ISO_KEYBOARD },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
@@ -493,6 +496,24 @@
 		.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_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS),
+		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS),
+		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_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-3.1-gnu/drivers/hid/hid-axff.c linux-libre-3.2-gnu/drivers/hid/hid-axff.c
--- linux-libre-3.1-gnu/drivers/hid/hid-axff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-axff.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,7 +6,7 @@
  * Xbox 360 controller.
  *
  * 1a34:0802 "ACRUX USB GAMEPAD 8116"
- *  - tested with a EXEQ EQ-PCU-02090 game controller.
+ *  - tested with an EXEQ EQ-PCU-02090 game controller.
  *
  * Copyright (c) 2010 Sergei Kolzun <x0r@dv-life.ru>
  */
@@ -31,6 +31,7 @@
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
+#include <linux/module.h>
 
 #include "hid-ids.h"
 
@@ -45,7 +46,10 @@
 {
 	struct hid_device *hid = input_get_drvdata(dev);
 	struct axff_device *axff = data;
+	struct hid_report *report = axff->report;
+	int field_count = 0;
 	int left, right;
+	int i, j;
 
 	left = effect->u.rumble.strong_magnitude;
 	right = effect->u.rumble.weak_magnitude;
@@ -55,10 +59,14 @@
 	left = left * 0xff / 0xffff;
 	right = right * 0xff / 0xffff;
 
-	axff->report->field[0]->value[0] = left;
-	axff->report->field[1]->value[0] = right;
-	axff->report->field[2]->value[0] = left;
-	axff->report->field[3]->value[0] = right;
+	for (i = 0; i < report->maxfield; i++) {
+		for (j = 0; j < report->field[i]->report_count; j++) {
+			report->field[i]->value[j] =
+				field_count % 2 ? right : left;
+			field_count++;
+		}
+	}
+
 	dbg_hid("running with 0x%02x 0x%02x", left, right);
 	usbhid_submit_report(hid, axff->report, USB_DIR_OUT);
 
@@ -72,6 +80,8 @@
 	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 field_count = 0;
+	int i, j;
 	int error;
 
 	if (list_empty(report_list)) {
@@ -80,9 +90,16 @@
 	}
 
 	report = list_first_entry(report_list, struct hid_report, list);
+	for (i = 0; i < report->maxfield; i++) {
+		for (j = 0; j < report->field[i]->report_count; j++) {
+			report->field[i]->value[j] = 0x00;
+			field_count++;
+		}
+	}
 
-	if (report->maxfield < 4) {
-		hid_err(hid, "no fields in the report: %d\n", report->maxfield);
+	if (field_count < 4) {
+		hid_err(hid, "not enough fields in the report: %d\n",
+			field_count);
 		return -ENODEV;
 	}
 
@@ -97,13 +114,9 @@
 		goto err_free_mem;
 
 	axff->report = report;
-	axff->report->field[0]->value[0] = 0x00;
-	axff->report->field[1]->value[0] = 0x00;
-	axff->report->field[2]->value[0] = 0x00;
-	axff->report->field[3]->value[0] = 0x00;
 	usbhid_submit_report(hid, axff->report, USB_DIR_OUT);
 
-	hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun<x0r@dv-life.ru>\n");
+	hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun <x0r@dv-life.ru>\n");
 
 	return 0;
 
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-core.c linux-libre-3.2-gnu/drivers/hid/hid-core.c
--- linux-libre-3.1-gnu/drivers/hid/hid-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/wait.h>
 #include <linux/vmalloc.h>
 #include <linux/sched.h>
+#include <linux/semaphore.h>
 
 #include <linux/hid.h>
 #include <linux/hiddev.h>
@@ -1085,16 +1086,25 @@
 	struct hid_report *report;
 	char *buf;
 	unsigned int i;
-	int ret;
+	int ret = 0;
 
-	if (!hid || !hid->driver)
+	if (!hid)
 		return -ENODEV;
+
+	if (down_trylock(&hid->driver_lock))
+		return -EBUSY;
+
+	if (!hid->driver) {
+		ret = -ENODEV;
+		goto unlock;
+	}
 	report_enum = hid->report_enum + type;
 	hdrv = hid->driver;
 
 	if (!size) {
 		dbg_hid("empty report\n");
-		return -1;
+		ret = -1;
+		goto unlock;
 	}
 
 	buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
@@ -1118,18 +1128,24 @@
 nomem:
 	report = hid_get_report(report_enum, data);
 
-	if (!report)
-		return -1;
+	if (!report) {
+		ret = -1;
+		goto unlock;
+	}
 
 	if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
 		ret = hdrv->raw_event(hid, report, data, size);
-		if (ret != 0)
-			return ret < 0 ? ret : 0;
+		if (ret != 0) {
+			ret = ret < 0 ? ret : 0;
+			goto unlock;
+		}
 	}
 
 	hid_report_raw_event(hid, type, data, size, interrupt);
 
-	return 0;
+unlock:
+	up(&hid->driver_lock);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(hid_input_report);
 
@@ -1212,6 +1228,12 @@
 	if ((connect_mask & HID_CONNECT_HIDINPUT) && !hidinput_connect(hdev,
 				connect_mask & HID_CONNECT_HIDINPUT_FORCE))
 		hdev->claimed |= HID_CLAIMED_INPUT;
+	if (hdev->quirks & HID_QUIRK_MULTITOUCH) {
+		/* this device should be handled by hid-multitouch, skip it */
+		hdev->quirks &= ~HID_QUIRK_MULTITOUCH;
+		return -ENODEV;
+	}
+
 	if ((connect_mask & HID_CONNECT_HIDDEV) && hdev->hiddev_connect &&
 			!hdev->hiddev_connect(hdev,
 				connect_mask & HID_CONNECT_HIDDEV_FORCE))
@@ -1340,12 +1362,22 @@
 	{ 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_WELLSPRING5A_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_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) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) },
 	{ 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) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) },
@@ -1391,6 +1423,7 @@
 	{ 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_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6650) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
@@ -1399,6 +1432,7 @@
 	{ 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_LG, USB_DEVICE_ID_LG_MULTITOUCH) },
 	{ 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) },
@@ -1420,8 +1454,11 @@
 	{ 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_DFGT_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_G27_WHEEL) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2) },
 	{ 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) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) },
@@ -1461,6 +1498,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
 	{ 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) },
@@ -1501,6 +1539,10 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
@@ -1620,10 +1662,15 @@
 	const struct hid_device_id *id;
 	int ret = 0;
 
+	if (down_interruptible(&hdev->driver_lock))
+		return -EINTR;
+
 	if (!hdev->driver) {
 		id = hid_match_device(hdev, hdrv);
-		if (id == NULL)
-			return -ENODEV;
+		if (id == NULL) {
+			ret = -ENODEV;
+			goto unlock;
+		}
 
 		hdev->driver = hdrv;
 		if (hdrv->probe) {
@@ -1636,14 +1683,20 @@
 		if (ret)
 			hdev->driver = NULL;
 	}
+unlock:
+	up(&hdev->driver_lock);
 	return ret;
 }
 
 static int hid_device_remove(struct device *dev)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct hid_driver *hdrv = hdev->driver;
+	struct hid_driver *hdrv;
 
+	if (down_interruptible(&hdev->driver_lock))
+		return -EINTR;
+
+	hdrv = hdev->driver;
 	if (hdrv) {
 		if (hdrv->remove)
 			hdrv->remove(hdev);
@@ -1652,6 +1705,7 @@
 		hdev->driver = NULL;
 	}
 
+	up(&hdev->driver_lock);
 	return 0;
 }
 
@@ -1717,8 +1771,8 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30) },
@@ -1892,6 +1946,15 @@
 	{ 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_WELLSPRING5A_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_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) },
 	{ }
@@ -1999,6 +2062,7 @@
 
 	init_waitqueue_head(&hdev->debug_wait);
 	INIT_LIST_HEAD(&hdev->debug_list);
+	sema_init(&hdev->driver_lock, 1);
 
 	return hdev;
 err:
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-debug.c linux-libre-3.2-gnu/drivers/hid/hid-debug.c
--- linux-libre-3.1-gnu/drivers/hid/hid-debug.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-debug.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/sched.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 #include <linux/poll.h>
@@ -450,6 +451,11 @@
 		seq_printf(f, "Logical(");
 		hid_resolv_usage(field->logical, f); seq_printf(f, ")\n");
 	}
+	if (field->application) {
+		tab(n, f);
+		seq_printf(f, "Application(");
+		hid_resolv_usage(field->application, f); seq_printf(f, ")\n");
+	}
 	tab(n, f); seq_printf(f, "Usage(%d)\n", field->maxusage);
 	for (j = 0; j < field->maxusage; j++) {
 		tab(n+2, f); hid_resolv_usage(field->usage[j].hid, f); seq_printf(f, "\n");
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-dr.c linux-libre-3.2-gnu/drivers/hid/hid-dr.c
--- linux-libre-3.1-gnu/drivers/hid/hid-dr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-dr.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
+#include <linux/module.h>
 
 #include "hid-ids.h"
 
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-emsff.c linux-libre-3.2-gnu/drivers/hid/hid-emsff.c
--- linux-libre-3.1-gnu/drivers/hid/hid-emsff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-emsff.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/hid.h>
 #include <linux/input.h>
 #include <linux/usb.h>
+#include <linux/module.h>
 
 #include "hid-ids.h"
 #include "usbhid/usbhid.h"
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-gaff.c linux-libre-3.2-gnu/drivers/hid/hid-gaff.c
--- linux-libre-3.1-gnu/drivers/hid/hid-gaff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-gaff.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
+#include <linux/module.h>
 #include "hid-ids.h"
 
 #ifdef CONFIG_GREENASIA_FF
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-holtekff.c linux-libre-3.2-gnu/drivers/hid/hid-holtekff.c
--- linux-libre-3.1-gnu/drivers/hid/hid-holtekff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-holtekff.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 
 #include <linux/hid.h>
 #include <linux/input.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
 
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-ids.h linux-libre-3.2-gnu/drivers/hid/hid-ids.h
--- linux-libre-3.1-gnu/drivers/hid/hid-ids.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-ids.h	2012-01-04 18:55:44.000000000 -0500
@@ -112,9 +112,19 @@
 #define USB_DEVICE_ID_APPLE_ALU_REVB_ANSI	0x024f
 #define USB_DEVICE_ID_APPLE_ALU_REVB_ISO	0x0250
 #define USB_DEVICE_ID_APPLE_ALU_REVB_JIS	0x0251
+#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI	0x0252
+#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO	0x0253
+#define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS	0x0254
+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI	0x0249
+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO	0x024a
+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS	0x024b
+#define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI	0x024c
+#define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO	0x024d
+#define USB_DEVICE_ID_APPLE_WELLSPRING6_JIS	0x024e
 #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
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO   0x0256
 #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY	0x030a
 #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY	0x030b
 #define USB_DEVICE_ID_APPLE_ATV_IRCONTROL	0x8241
@@ -256,7 +266,7 @@
 #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR	0x0002
 
 #define USB_VENDOR_ID_GENERAL_TOUCH	0x0dfc
-#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0001
+#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003
 
 #define USB_VENDOR_ID_GLAB		0x06c2
 #define USB_DEVICE_ID_4_PHIDGETSERVO_30	0x0038
@@ -351,6 +361,9 @@
 #define USB_DEVICE_ID_UGCI_FLYING	0x0020
 #define USB_DEVICE_ID_UGCI_FIGHTING	0x0030
 
+#define USB_VENDOR_ID_IDEACOM		0x1cb6
+#define USB_DEVICE_ID_IDEACOM_IDC6650	0x6650
+
 #define USB_VENDOR_ID_ILITEK		0x222a
 #define USB_DEVICE_ID_ILITEK_MULTITOUCH	0x0001
 
@@ -423,6 +436,9 @@
 #define USB_DEVICE_ID_LD_HYBRID		0x2090
 #define USB_DEVICE_ID_LD_HEATCONTROL	0x20A0
 
+#define USB_VENDOR_ID_LG		0x1fd2
+#define USB_DEVICE_ID_LG_MULTITOUCH	0x0064
+
 #define USB_VENDOR_ID_LOGITECH		0x046d
 #define USB_DEVICE_ID_LOGITECH_RECEIVER	0xc101
 #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST  0xc110
@@ -440,6 +456,7 @@
 #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_DFGT_WHEEL	0xc29a
 #define USB_DEVICE_ID_LOGITECH_G27_WHEEL	0xc29b
 #define USB_DEVICE_ID_LOGITECH_WII_WHEEL	0xc29c
 #define USB_DEVICE_ID_LOGITECH_ELITE_KBD	0xc30a
@@ -447,6 +464,8 @@
 #define USB_DEVICE_ID_S510_RECEIVER_2	0xc517
 #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500	0xc512
 #define USB_DEVICE_ID_MX3000_RECEIVER	0xc513
+#define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER	0xc52b
+#define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2	0xc532
 #define USB_DEVICE_ID_SPACETRAVELLER	0xc623
 #define USB_DEVICE_ID_SPACENAVIGATOR	0xc626
 #define USB_DEVICE_ID_DINOVO_DESKTOP	0xc704
@@ -678,6 +697,9 @@
 #define USB_VENDOR_ID_WISEGROUP_LTD	0x6666
 #define USB_VENDOR_ID_WISEGROUP_LTD2	0x6677
 #define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802
+#define USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO 0x8801
+#define USB_DEVICE_ID_SUPER_DUAL_BOX_PRO 0x8802
+#define USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO 0x8804
 
 #define USB_VENDOR_ID_X_TENSIONS               0x1ae7
 #define USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE    0x9001
@@ -693,4 +715,7 @@
 #define USB_VENDOR_ID_ZYDACRON	0x13EC
 #define USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL	0x0006
 
+#define USB_VENDOR_ID_PRIMAX	0x0461
+#define USB_DEVICE_ID_PRIMAX_KEYBOARD	0x4e05
+
 #endif
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-input.c linux-libre-3.2-gnu/drivers/hid/hid-input.c
--- linux-libre-3.1-gnu/drivers/hid/hid-input.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-input.c	2012-01-04 18:55:44.000000000 -0500
@@ -474,6 +474,10 @@
 			map_key_clear(BTN_STYLUS2);
 			break;
 
+		case 0x51: /* ContactID */
+			device->quirks |= HID_QUIRK_MULTITOUCH;
+			goto unknown;
+
 		default:  goto unknown;
 		}
 		break;
@@ -978,6 +982,13 @@
 		}
 	}
 
+	if (hid->quirks & HID_QUIRK_MULTITOUCH) {
+		/* generic hid does not know how to handle multitouch devices */
+		if (hidinput)
+			goto out_cleanup;
+		goto out_unwind;
+	}
+
 	if (hidinput && input_register_device(hidinput->input))
 		goto out_cleanup;
 
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-lg4ff.c linux-libre-3.2-gnu/drivers/hid/hid-lg4ff.c
--- linux-libre-3.1-gnu/drivers/hid/hid-lg4ff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-lg4ff.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,19 +29,108 @@
 
 #include "usbhid/usbhid.h"
 #include "hid-lg.h"
+#include "hid-ids.h"
 
-struct lg4ff_device {
-	struct hid_report *report;
+#define DFGT_REV_MAJ 0x13
+#define DFGT_REV_MIN 0x22
+#define DFP_REV_MAJ 0x11
+#define DFP_REV_MIN 0x06
+#define FFEX_REV_MAJ 0x21
+#define FFEX_REV_MIN 0x00
+#define G25_REV_MAJ 0x12
+#define G25_REV_MIN 0x22
+#define G27_REV_MAJ 0x12
+#define G27_REV_MIN 0x38
+
+#define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
+
+static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range);
+static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range);
+static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+
+static DEVICE_ATTR(range, S_IRWXU | S_IRWXG | S_IRWXO, lg4ff_range_show, lg4ff_range_store);
+
+static bool list_inited;
+
+struct lg4ff_device_entry {
+	char  *device_id;	/* Use name in respective kobject structure's address as the ID */
+	__u16 range;
+	__u16 min_range;
+	__u16 max_range;
+	__u8  leds;
+	struct list_head list;
+	void (*set_range)(struct hid_device *hid, u16 range);
 };
 
-static const signed short ff4_wheel_ac[] = {
+static struct lg4ff_device_entry device_list;
+
+static const signed short lg4ff_wheel_effects[] = {
 	FF_CONSTANT,
 	FF_AUTOCENTER,
 	-1
 };
 
-static int hid_lg4ff_play(struct input_dev *dev, void *data,
-			 struct ff_effect *effect)
+struct lg4ff_wheel {
+	const __u32 product_id;
+	const signed short *ff_effects;
+	const __u16 min_range;
+	const __u16 max_range;
+	void (*set_range)(struct hid_device *hid, u16 range);
+};
+
+static const struct lg4ff_wheel lg4ff_devices[] = {
+	{USB_DEVICE_ID_LOGITECH_WHEEL,       lg4ff_wheel_effects, 40, 270, NULL},
+	{USB_DEVICE_ID_LOGITECH_MOMO_WHEEL,  lg4ff_wheel_effects, 40, 270, NULL},
+	{USB_DEVICE_ID_LOGITECH_DFP_WHEEL,   lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_dfp},
+	{USB_DEVICE_ID_LOGITECH_G25_WHEEL,   lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25},
+	{USB_DEVICE_ID_LOGITECH_DFGT_WHEEL,  lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25},
+	{USB_DEVICE_ID_LOGITECH_G27_WHEEL,   lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25},
+	{USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, NULL},
+	{USB_DEVICE_ID_LOGITECH_WII_WHEEL,   lg4ff_wheel_effects, 40, 270, NULL}
+};
+
+struct lg4ff_native_cmd {
+	const __u8 cmd_num;	/* Number of commands to send */
+	const __u8 cmd[];
+};
+
+struct lg4ff_usb_revision {
+	const __u16 rev_maj;
+	const __u16 rev_min;
+	const struct lg4ff_native_cmd *command;
+};
+
+static const struct lg4ff_native_cmd native_dfp = {
+	1,
+	{0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+static const struct lg4ff_native_cmd native_dfgt = {
+	2,
+	{0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 1st command */
+	 0xf8, 0x09, 0x03, 0x01, 0x00, 0x00, 0x00}	/* 2nd command */
+};
+
+static const struct lg4ff_native_cmd native_g25 = {
+	1,
+	{0xf8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+static const struct lg4ff_native_cmd native_g27 = {
+	2,
+	{0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 1st command */
+	 0xf8, 0x09, 0x04, 0x01, 0x00, 0x00, 0x00}	/* 2nd command */
+};
+
+static const struct lg4ff_usb_revision lg4ff_revs[] = {
+	{DFGT_REV_MAJ, DFGT_REV_MIN, &native_dfgt},	/* Driving Force GT */
+	{DFP_REV_MAJ,  DFP_REV_MIN,  &native_dfp},	/* Driving Force Pro */
+	{G25_REV_MAJ,  G25_REV_MIN,  &native_g25},	/* G25 */
+	{G27_REV_MAJ,  G27_REV_MIN,  &native_g27},	/* G27 */
+};
+
+static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
 {
 	struct hid_device *hid = input_get_drvdata(dev);
 	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
@@ -55,13 +144,12 @@
 		x = effect->u.ramp.start_level + 0x80;	/* 0x80 is no force */
 		CLAMP(x);
 		report->field[0]->value[0] = 0x11;	/* Slot 1 */
-		report->field[0]->value[1] = 0x10;
+		report->field[0]->value[1] = 0x08;
 		report->field[0]->value[2] = x;
-		report->field[0]->value[3] = 0x00;
+		report->field[0]->value[3] = 0x80;
 		report->field[0]->value[4] = 0x00;
-		report->field[0]->value[5] = 0x08;
+		report->field[0]->value[5] = 0x00;
 		report->field[0]->value[6] = 0x00;
-		dbg_hid("Autocenter, x=0x%02X\n", x);
 
 		usbhid_submit_report(hid, report, USB_DIR_OUT);
 		break;
@@ -69,24 +157,184 @@
 	return 0;
 }
 
-static void hid_lg4ff_set_autocenter(struct input_dev *dev, u16 magnitude)
+/* Sends default autocentering command compatible with
+ * all wheels except Formula Force EX */
+static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude)
 {
 	struct hid_device *hid = input_get_drvdata(dev);
 	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
 	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
-	__s32 *value = report->field[0]->value;
 
-	*value++ = 0xfe;
-	*value++ = 0x0d;
-	*value++ = 0x07;
-	*value++ = 0x07;
-	*value++ = (magnitude >> 8) & 0xff;
-	*value++ = 0x00;
-	*value = 0x00;
+	report->field[0]->value[0] = 0xfe;
+	report->field[0]->value[1] = 0x0d;
+	report->field[0]->value[2] = magnitude >> 13;
+	report->field[0]->value[3] = magnitude >> 13;
+	report->field[0]->value[4] = magnitude >> 8;
+	report->field[0]->value[5] = 0x00;
+	report->field[0]->value[6] = 0x00;
 
 	usbhid_submit_report(hid, report, USB_DIR_OUT);
 }
 
+/* Sends autocentering command compatible with Formula Force EX */
+static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+	magnitude = magnitude * 90 / 65535;
+	
+
+	report->field[0]->value[0] = 0xfe;
+	report->field[0]->value[1] = 0x03;
+	report->field[0]->value[2] = magnitude >> 14;
+	report->field[0]->value[3] = magnitude >> 14;
+	report->field[0]->value[4] = magnitude;
+	report->field[0]->value[5] = 0x00;
+	report->field[0]->value[6] = 0x00;
+
+	usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+/* Sends command to set range compatible with G25/G27/Driving Force GT */
+static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range)
+{
+	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+	dbg_hid("G25/G27/DFGT: setting range to %u\n", range);
+
+	report->field[0]->value[0] = 0xf8;
+	report->field[0]->value[1] = 0x81;
+	report->field[0]->value[2] = range & 0x00ff;
+	report->field[0]->value[3] = (range & 0xff00) >> 8;
+	report->field[0]->value[4] = 0x00;
+	report->field[0]->value[5] = 0x00;
+	report->field[0]->value[6] = 0x00;
+
+	usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+/* Sends commands to set range compatible with Driving Force Pro wheel */
+static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
+{
+	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+	int start_left, start_right, full_range;
+	dbg_hid("Driving Force Pro: setting range to %u\n", range);
+
+	/* Prepare "coarse" limit command */
+	report->field[0]->value[0] = 0xf8;
+	report->field[0]->value[1] = 0x00; 	/* Set later */
+	report->field[0]->value[2] = 0x00;
+	report->field[0]->value[3] = 0x00;
+	report->field[0]->value[4] = 0x00;
+	report->field[0]->value[5] = 0x00;
+	report->field[0]->value[6] = 0x00;
+
+	if (range > 200) {
+		report->field[0]->value[1] = 0x03;
+		full_range = 900;
+	} else {
+		report->field[0]->value[1] = 0x02;
+		full_range = 200;
+	}
+	usbhid_submit_report(hid, report, USB_DIR_OUT);
+
+	/* Prepare "fine" limit command */
+	report->field[0]->value[0] = 0x81;
+	report->field[0]->value[1] = 0x0b;
+	report->field[0]->value[2] = 0x00;
+	report->field[0]->value[3] = 0x00;
+	report->field[0]->value[4] = 0x00;
+	report->field[0]->value[5] = 0x00;
+	report->field[0]->value[6] = 0x00;
+
+	if (range == 200 || range == 900) {	/* Do not apply any fine limit */
+		usbhid_submit_report(hid, report, USB_DIR_OUT);
+		return;
+	}
+
+	/* Construct fine limit command */
+	start_left = (((full_range - range + 1) * 2047) / full_range);
+	start_right = 0xfff - start_left;
+
+	report->field[0]->value[2] = start_left >> 4;
+	report->field[0]->value[3] = start_right >> 4;
+	report->field[0]->value[4] = 0xff;
+	report->field[0]->value[5] = (start_right & 0xe) << 4 | (start_left & 0xe);
+	report->field[0]->value[6] = 0xff;
+
+	usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_native_cmd *cmd)
+{
+	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+	__u8 i, j;
+
+	j = 0;
+	while (j < 7*cmd->cmd_num) {
+		for (i = 0; i < 7; i++)
+			report->field[0]->value[i] = cmd->cmd[j++];
+
+		usbhid_submit_report(hid, report, USB_DIR_OUT);
+	}
+}
+
+/* Read current range and display it in terminal */
+static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct lg4ff_device_entry *uninitialized_var(entry);
+	struct list_head *h;
+	struct hid_device *hid = to_hid_device(dev);
+	size_t count;
+
+	list_for_each(h, &device_list.list) {
+		entry = list_entry(h, struct lg4ff_device_entry, list);
+		if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0)
+			break;
+	}
+	if (h == &device_list.list) {
+		dbg_hid("Device not found!");
+		return 0;
+	}
+
+	count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->range);
+	return count;
+}
+
+/* Set range to user specified value, call appropriate function
+ * according to the type of the wheel */
+static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lg4ff_device_entry *uninitialized_var(entry);
+	struct list_head *h;
+	struct hid_device *hid = to_hid_device(dev);
+	__u16 range = simple_strtoul(buf, NULL, 10);
+
+	list_for_each(h, &device_list.list) {
+		entry = list_entry(h, struct lg4ff_device_entry, list);
+		if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0)
+			break;
+	}
+	if (h == &device_list.list) {
+		dbg_hid("Device not found!");
+		return count;
+	}
+
+	if (range == 0)
+		range = entry->max_range;
+
+	/* Check if the wheel supports range setting
+	 * and that the range is within limits for the wheel */
+	if (entry->set_range != NULL && range >= entry->min_range && range <= entry->max_range) {
+		entry->set_range(hid, range);
+		entry->range = range;
+	}
+
+	return count;
+}
 
 int lg4ff_init(struct hid_device *hid)
 {
@@ -95,9 +343,10 @@
 	struct input_dev *dev = hidinput->input;
 	struct hid_report *report;
 	struct hid_field *field;
-	const signed short *ff_bits = ff4_wheel_ac;
-	int error;
-	int i;
+	struct lg4ff_device_entry *entry;
+	struct usb_device_descriptor *udesc;
+	int error, i, j;
+	__u16 bcdDevice, rev_maj, rev_min;
 
 	/* Find the report to use */
 	if (list_empty(report_list)) {
@@ -118,18 +367,122 @@
 		return -1;
 	}
 
-	for (i = 0; ff_bits[i] >= 0; i++)
-		set_bit(ff_bits[i], dev->ffbit);
+	/* Check what wheel has been connected */
+	for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) {
+		if (hid->product == lg4ff_devices[i].product_id) {
+			dbg_hid("Found compatible device, product ID %04X\n", lg4ff_devices[i].product_id);
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(lg4ff_devices)) {
+		hid_err(hid, "Device is not supported by lg4ff driver. If you think it should be, consider reporting a bug to"
+			     "LKML, Simon Wood <simon@mungewell.org> or Michal Maly <madcatxster@gmail.com>\n");
+		return -1;
+	}
+
+	/* Attempt to switch wheel to native mode when applicable */
+	udesc = &(hid_to_usb_dev(hid)->descriptor);
+	if (!udesc) {
+		hid_err(hid, "NULL USB device descriptor\n");
+		return -1;
+	}
+	bcdDevice = le16_to_cpu(udesc->bcdDevice);
+	rev_maj = bcdDevice >> 8;
+	rev_min = bcdDevice & 0xff;
+
+	if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_WHEEL) {
+		dbg_hid("Generic wheel detected, can it do native?\n");
+		dbg_hid("USB revision: %2x.%02x\n", rev_maj, rev_min);
+
+		for (j = 0; j < ARRAY_SIZE(lg4ff_revs); j++) {
+			if (lg4ff_revs[j].rev_maj == rev_maj && lg4ff_revs[j].rev_min == rev_min) {
+				hid_lg4ff_switch_native(hid, lg4ff_revs[j].command);
+				hid_info(hid, "Switched to native mode\n");
+			}
+		}
+	}
+
+	/* Set supported force feedback capabilities */
+	for (j = 0; lg4ff_devices[i].ff_effects[j] >= 0; j++)
+		set_bit(lg4ff_devices[i].ff_effects[j], dev->ffbit);
 
 	error = input_ff_create_memless(dev, NULL, hid_lg4ff_play);
 
 	if (error)
 		return error;
 
-	if (test_bit(FF_AUTOCENTER, dev->ffbit))
-		dev->ff->set_autocenter = hid_lg4ff_set_autocenter;
+	/* Check if autocentering is available and
+	 * set the centering force to zero by default */
+	if (test_bit(FF_AUTOCENTER, dev->ffbit)) {
+		if(rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN)	/* Formula Force EX expects different autocentering command */
+			dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex;
+		else
+			dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default;
+
+		dev->ff->set_autocenter(dev, 0);
+	}
+
+		/* Initialize device_list if this is the first device to handle by lg4ff */
+	if (!list_inited) {
+		INIT_LIST_HEAD(&device_list.list);
+		list_inited = 1;
+	}
+
+	/* Add the device to device_list */
+	entry = (struct lg4ff_device_entry *)kzalloc(sizeof(struct lg4ff_device_entry), GFP_KERNEL);
+	if (!entry) {
+		hid_err(hid, "Cannot add device, insufficient memory.\n");
+		return -ENOMEM;
+	}
+	entry->device_id = kstrdup((&hid->dev)->kobj.name, GFP_KERNEL);
+	if (!entry->device_id) {
+		hid_err(hid, "Cannot set device_id, insufficient memory.\n");
+		kfree(entry);
+		return -ENOMEM;
+	}
+	entry->min_range = lg4ff_devices[i].min_range;
+	entry->max_range = lg4ff_devices[i].max_range;
+	entry->set_range = lg4ff_devices[i].set_range;
+	list_add(&entry->list, &device_list.list);
+
+	/* Create sysfs interface */
+	error = device_create_file(&hid->dev, &dev_attr_range);
+	if (error)
+		return error;
+	dbg_hid("sysfs interface created\n");
+
+	/* Set the maximum range to start with */
+	entry->range = entry->max_range;
+	if (entry->set_range != NULL)
+		entry->set_range(hid, entry->range);
 
 	hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n");
 	return 0;
 }
 
+int lg4ff_deinit(struct hid_device *hid)
+{
+	bool found = 0;
+	struct lg4ff_device_entry *entry;
+	struct list_head *h, *g;
+	list_for_each_safe(h, g, &device_list.list) {
+		entry = list_entry(h, struct lg4ff_device_entry, list);
+		if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0) {
+			list_del(h);
+			kfree(entry->device_id);
+			kfree(entry);
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found) {
+		dbg_hid("Device entry not found!\n");
+		return -1;
+	}
+
+	device_remove_file(&hid->dev, &dev_attr_range);
+	dbg_hid("Device successfully unregistered\n");
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-lg.c linux-libre-3.2-gnu/drivers/hid/hid-lg.c
--- linux-libre-3.1-gnu/drivers/hid/hid-lg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-lg.c	2012-01-04 18:55:44.000000000 -0500
@@ -363,7 +363,7 @@
 		goto err_free;
 	}
 
-	if (quirks & (LG_FF | LG_FF2 | LG_FF3))
+	if (quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4))
 		connect_mask &= ~HID_CONNECT_FF;
 
 	ret = hid_hw_start(hdev, connect_mask);
@@ -372,7 +372,8 @@
 		goto err_free;
 	}
 
-	if (quirks & LG_FF4) {
+	/* Setup wireless link with Logitech Wii wheel */
+	if(hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
 		unsigned char buf[] = { 0x00, 0xAF,  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
 		ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
@@ -405,6 +406,15 @@
 	return ret;
 }
 
+static void lg_remove(struct hid_device *hdev)
+{
+	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+	if(quirks & LG_FF4)
+		lg4ff_deinit(hdev);
+
+	hid_hw_stop(hdev);
+}
+
 static const struct hid_device_id lg_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
 		.driver_data = LG_RDESC | LG_WIRELESS },
@@ -431,7 +441,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D),
 		.driver_data = LG_NOGET },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
-		.driver_data = LG_NOGET | LG_FF },
+		.driver_data = LG_NOGET | LG_FF4 },
 
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD),
 		.driver_data = LG_FF2 },
@@ -444,15 +454,17 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),
 		.driver_data = LG_FF },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL),
-		.driver_data = LG_FF },
+		.driver_data = LG_FF4 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
-		.driver_data = LG_FF },
+		.driver_data = LG_FF4 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
-		.driver_data = LG_FF },
+		.driver_data = LG_FF4 },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL),
+		.driver_data = LG_FF4 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL),
-		.driver_data = LG_FF },
+		.driver_data = LG_FF4 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
-		.driver_data = LG_NOGET | LG_FF },
+		.driver_data = LG_NOGET | LG_FF4 },
 	{ 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 ),
@@ -478,6 +490,7 @@
 	.input_mapped = lg_input_mapped,
 	.event = lg_event,
 	.probe = lg_probe,
+	.remove = lg_remove,
 };
 
 static int __init lg_init(void)
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-lgff.c linux-libre-3.2-gnu/drivers/hid/hid-lgff.c
--- linux-libre-3.1-gnu/drivers/hid/hid-lgff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-lgff.c	2012-01-04 18:55:44.000000000 -0500
@@ -58,12 +58,6 @@
 	-1
 };
 
-static const signed short ff_wheel[] = {
-	FF_CONSTANT,
-	FF_AUTOCENTER,
-	-1
-};
-
 static const struct dev_type devices[] = {
 	{ 0x046d, 0xc211, ff_rumble },
 	{ 0x046d, 0xc219, ff_rumble },
@@ -71,14 +65,7 @@
 	{ 0x046d, 0xc286, ff_joystick_ac },
 	{ 0x046d, 0xc287, ff_joystick_ac },
 	{ 0x046d, 0xc293, ff_joystick },
-	{ 0x046d, 0xc294, ff_wheel },
-	{ 0x046d, 0xc298, ff_wheel },
-	{ 0x046d, 0xc299, ff_wheel },
-	{ 0x046d, 0xc29b, ff_wheel },
 	{ 0x046d, 0xc295, ff_joystick },
-	{ 0x046d, 0xc298, ff_wheel },
-	{ 0x046d, 0xc299, ff_wheel },
-	{ 0x046d, 0xca03, ff_wheel },
 };
 
 static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-lg.h linux-libre-3.2-gnu/drivers/hid/hid-lg.h
--- linux-libre-3.1-gnu/drivers/hid/hid-lg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-lg.h	2012-01-04 18:55:44.000000000 -0500
@@ -19,10 +19,12 @@
 static inline int lg3ff_init(struct hid_device *hdev) { return -1; }
 #endif
 
-#ifdef CONFIG_LOGIWII_FF
+#ifdef CONFIG_LOGIWHEELS_FF
 int lg4ff_init(struct hid_device *hdev);
+int lg4ff_deinit(struct hid_device *hdev);
 #else
 static inline int lg4ff_init(struct hid_device *hdev) { return -1; }
+static inline int lg4ff_deinit(struct hid_device *hdev) { return -1; }
 #endif
 
 #endif
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-logitech-dj.c linux-libre-3.2-gnu/drivers/hid/hid-logitech-dj.c
--- linux-libre-3.1-gnu/drivers/hid/hid-logitech-dj.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hid/hid-logitech-dj.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,922 @@
+/*
+ *  HID driver for Logitech Unifying receivers
+ *
+ *  Copyright (c) 2011 Logitech
+ */
+
+/*
+ * This program is free software; you can 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usbhid/usbhid.h"
+#include "hid-ids.h"
+#include "hid-logitech-dj.h"
+
+/* Keyboard descriptor (1) */
+static const char kbd_descriptor[] = {
+	0x05, 0x01,		/* USAGE_PAGE (generic Desktop)     */
+	0x09, 0x06,		/* USAGE (Keyboard)         */
+	0xA1, 0x01,		/* COLLECTION (Application)     */
+	0x85, 0x01,		/* REPORT_ID (1)            */
+	0x95, 0x08,		/*   REPORT_COUNT (8)           */
+	0x75, 0x01,		/*   REPORT_SIZE (1)            */
+	0x15, 0x00,		/*   LOGICAL_MINIMUM (0)        */
+	0x25, 0x01,		/*   LOGICAL_MAXIMUM (1)        */
+	0x05, 0x07,		/*   USAGE_PAGE (Keyboard)      */
+	0x19, 0xE0,		/*   USAGE_MINIMUM (Left Control)   */
+	0x29, 0xE7,		/*   USAGE_MAXIMUM (Right GUI)      */
+	0x81, 0x02,		/*   INPUT (Data,Var,Abs)       */
+	0x95, 0x05,		/*   REPORT COUNT (5)           */
+	0x05, 0x08,		/*   USAGE PAGE (LED page)      */
+	0x19, 0x01,		/*   USAGE MINIMUM (1)          */
+	0x29, 0x05,		/*   USAGE MAXIMUM (5)          */
+	0x91, 0x02,		/*   OUTPUT (Data, Variable, Absolute)  */
+	0x95, 0x01,		/*   REPORT COUNT (1)           */
+	0x75, 0x03,		/*   REPORT SIZE (3)            */
+	0x91, 0x01,		/*   OUTPUT (Constant)          */
+	0x95, 0x06,		/*   REPORT_COUNT (6)           */
+	0x75, 0x08,		/*   REPORT_SIZE (8)            */
+	0x15, 0x00,		/*   LOGICAL_MINIMUM (0)        */
+	0x26, 0xFF, 0x00,	/*   LOGICAL_MAXIMUM (255)      */
+	0x05, 0x07,		/*   USAGE_PAGE (Keyboard)      */
+	0x19, 0x00,		/*   USAGE_MINIMUM (no event)       */
+	0x2A, 0xFF, 0x00,	/*   USAGE_MAXIMUM (reserved)       */
+	0x81, 0x00,		/*   INPUT (Data,Ary,Abs)       */
+	0xC0
+};
+
+/* Mouse descriptor (2)     */
+static const char mse_descriptor[] = {
+	0x05, 0x01,		/*  USAGE_PAGE (Generic Desktop)        */
+	0x09, 0x02,		/*  USAGE (Mouse)                       */
+	0xA1, 0x01,		/*  COLLECTION (Application)            */
+	0x85, 0x02,		/*    REPORT_ID = 2                     */
+	0x09, 0x01,		/*    USAGE (pointer)                   */
+	0xA1, 0x00,		/*    COLLECTION (physical)             */
+	0x05, 0x09,		/*      USAGE_PAGE (buttons)            */
+	0x19, 0x01,		/*      USAGE_MIN (1)                   */
+	0x29, 0x10,		/*      USAGE_MAX (16)                  */
+	0x15, 0x00,		/*      LOGICAL_MIN (0)                 */
+	0x25, 0x01,		/*      LOGICAL_MAX (1)                 */
+	0x95, 0x10,		/*      REPORT_COUNT (16)               */
+	0x75, 0x01,		/*      REPORT_SIZE (1)                 */
+	0x81, 0x02,		/*      INPUT (data var abs)            */
+	0x05, 0x01,		/*      USAGE_PAGE (generic desktop)    */
+	0x16, 0x01, 0xF8,	/*      LOGICAL_MIN (-2047)             */
+	0x26, 0xFF, 0x07,	/*      LOGICAL_MAX (2047)              */
+	0x75, 0x0C,		/*      REPORT_SIZE (12)                */
+	0x95, 0x02,		/*      REPORT_COUNT (2)                */
+	0x09, 0x30,		/*      USAGE (X)                       */
+	0x09, 0x31,		/*      USAGE (Y)                       */
+	0x81, 0x06,		/*      INPUT                           */
+	0x15, 0x81,		/*      LOGICAL_MIN (-127)              */
+	0x25, 0x7F,		/*      LOGICAL_MAX (127)               */
+	0x75, 0x08,		/*      REPORT_SIZE (8)                 */
+	0x95, 0x01,		/*      REPORT_COUNT (1)                */
+	0x09, 0x38,		/*      USAGE (wheel)                   */
+	0x81, 0x06,		/*      INPUT                           */
+	0x05, 0x0C,		/*      USAGE_PAGE(consumer)            */
+	0x0A, 0x38, 0x02,	/*      USAGE(AC Pan)                   */
+	0x95, 0x01,		/*      REPORT_COUNT (1)                */
+	0x81, 0x06,		/*      INPUT                           */
+	0xC0,			/*    END_COLLECTION                    */
+	0xC0,			/*  END_COLLECTION                      */
+};
+
+/* Consumer Control descriptor (3) */
+static const char consumer_descriptor[] = {
+	0x05, 0x0C,		/* USAGE_PAGE (Consumer Devices)       */
+	0x09, 0x01,		/* USAGE (Consumer Control)            */
+	0xA1, 0x01,		/* COLLECTION (Application)            */
+	0x85, 0x03,		/* REPORT_ID = 3                       */
+	0x75, 0x10,		/* REPORT_SIZE (16)                    */
+	0x95, 0x02,		/* REPORT_COUNT (2)                    */
+	0x15, 0x01,		/* LOGICAL_MIN (1)                     */
+	0x26, 0x8C, 0x02,	/* LOGICAL_MAX (652)                   */
+	0x19, 0x01,		/* USAGE_MIN (1)                       */
+	0x2A, 0x8C, 0x02,	/* USAGE_MAX (652)                     */
+	0x81, 0x00,		/* INPUT (Data Ary Abs)                */
+	0xC0,			/* END_COLLECTION                      */
+};				/*                                     */
+
+/* System control descriptor (4) */
+static const char syscontrol_descriptor[] = {
+	0x05, 0x01,		/*   USAGE_PAGE (Generic Desktop)      */
+	0x09, 0x80,		/*   USAGE (System Control)            */
+	0xA1, 0x01,		/*   COLLECTION (Application)          */
+	0x85, 0x04,		/*   REPORT_ID = 4                     */
+	0x75, 0x02,		/*   REPORT_SIZE (2)                   */
+	0x95, 0x01,		/*   REPORT_COUNT (1)                  */
+	0x15, 0x01,		/*   LOGICAL_MIN (1)                   */
+	0x25, 0x03,		/*   LOGICAL_MAX (3)                   */
+	0x09, 0x82,		/*   USAGE (System Sleep)              */
+	0x09, 0x81,		/*   USAGE (System Power Down)         */
+	0x09, 0x83,		/*   USAGE (System Wake Up)            */
+	0x81, 0x60,		/*   INPUT (Data Ary Abs NPrf Null)    */
+	0x75, 0x06,		/*   REPORT_SIZE (6)                   */
+	0x81, 0x03,		/*   INPUT (Cnst Var Abs)              */
+	0xC0,			/*   END_COLLECTION                    */
+};
+
+/* Media descriptor (8) */
+static const char media_descriptor[] = {
+	0x06, 0xbc, 0xff,	/* Usage Page 0xffbc                   */
+	0x09, 0x88,		/* Usage 0x0088                        */
+	0xa1, 0x01,		/* BeginCollection                     */
+	0x85, 0x08,		/*   Report ID 8                       */
+	0x19, 0x01,		/*   Usage Min 0x0001                  */
+	0x29, 0xff,		/*   Usage Max 0x00ff                  */
+	0x15, 0x01,		/*   Logical Min 1                     */
+	0x26, 0xff, 0x00,	/*   Logical Max 255                   */
+	0x75, 0x08,		/*   Report Size 8                     */
+	0x95, 0x01,		/*   Report Count 1                    */
+	0x81, 0x00,		/*   Input                             */
+	0xc0,			/* EndCollection                       */
+};				/*                                     */
+
+/* Maximum size of all defined hid reports in bytes (including report id) */
+#define MAX_REPORT_SIZE 8
+
+/* Number of possible hid report types that can be created by this driver.
+ *
+ * Right now, RF report types have the same report types (or report id's)
+ * than the hid report created from those RF reports. In the future
+ * this doesnt have to be true.
+ *
+ * For instance, RF report type 0x01 which has a size of 8 bytes, corresponds
+ * to hid report id 0x01, this is standard keyboard. Same thing applies to mice
+ * reports and consumer control, etc. If a new RF report is created, it doesn't
+ * has to have the same report id as its corresponding hid report, so an
+ * translation may have to take place for future report types.
+ */
+#define NUMBER_OF_HID_REPORTS 32
+static const u8 hid_reportid_size_map[NUMBER_OF_HID_REPORTS] = {
+	[1] = 8,		/* Standard keyboard */
+	[2] = 8,		/* Standard mouse */
+	[3] = 5,		/* Consumer control */
+	[4] = 2,		/* System control */
+	[8] = 2,		/* Media Center */
+};
+
+
+#define LOGITECH_DJ_INTERFACE_NUMBER 0x02
+
+static struct hid_ll_driver logi_dj_ll_driver;
+
+static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
+					size_t count,
+					unsigned char report_type);
+
+static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,
+						struct dj_report *dj_report)
+{
+	/* Called in delayed work context */
+	struct dj_device *dj_dev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&djrcv_dev->lock, flags);
+	dj_dev = djrcv_dev->paired_dj_devices[dj_report->device_index];
+	djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL;
+	spin_unlock_irqrestore(&djrcv_dev->lock, flags);
+
+	if (dj_dev != NULL) {
+		hid_destroy_device(dj_dev->hdev);
+		kfree(dj_dev);
+	} else {
+		dev_err(&djrcv_dev->hdev->dev, "%s: can't destroy a NULL device\n",
+			__func__);
+	}
+}
+
+static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
+					  struct dj_report *dj_report)
+{
+	/* Called in delayed work context */
+	struct hid_device *djrcv_hdev = djrcv_dev->hdev;
+	struct usb_interface *intf = to_usb_interface(djrcv_hdev->dev.parent);
+	struct usb_device *usbdev = interface_to_usbdev(intf);
+	struct hid_device *dj_hiddev;
+	struct dj_device *dj_dev;
+
+	/* Device index goes from 1 to 6, we need 3 bytes to store the
+	 * semicolon, the index, and a null terminator
+	 */
+	unsigned char tmpstr[3];
+
+	if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
+	    SPFUNCTION_DEVICE_LIST_EMPTY) {
+		dbg_hid("%s: device list is empty\n", __func__);
+		return;
+	}
+
+	if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||
+	    (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {
+		dev_err(&djrcv_hdev->dev, "%s: invalid device index:%d\n",
+			__func__, dj_report->device_index);
+		return;
+	}
+
+	dj_hiddev = hid_allocate_device();
+	if (IS_ERR(dj_hiddev)) {
+		dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n",
+			__func__);
+		return;
+	}
+
+	dj_hiddev->ll_driver = &logi_dj_ll_driver;
+	dj_hiddev->hid_output_raw_report = logi_dj_output_hidraw_report;
+
+	dj_hiddev->dev.parent = &djrcv_hdev->dev;
+	dj_hiddev->bus = BUS_USB;
+	dj_hiddev->vendor = le16_to_cpu(usbdev->descriptor.idVendor);
+	dj_hiddev->product = le16_to_cpu(usbdev->descriptor.idProduct);
+	snprintf(dj_hiddev->name, sizeof(dj_hiddev->name),
+		"Logitech Unifying Device. Wireless PID:%02x%02x",
+		dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB],
+		dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB]);
+
+	usb_make_path(usbdev, dj_hiddev->phys, sizeof(dj_hiddev->phys));
+	snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index);
+	strlcat(dj_hiddev->phys, tmpstr, sizeof(dj_hiddev->phys));
+
+	dj_dev = kzalloc(sizeof(struct dj_device), GFP_KERNEL);
+
+	if (!dj_dev) {
+		dev_err(&djrcv_hdev->dev, "%s: failed allocating dj_device\n",
+			__func__);
+		goto dj_device_allocate_fail;
+	}
+
+	dj_dev->reports_supported = le32_to_cpu(
+		dj_report->report_params[DEVICE_PAIRED_RF_REPORT_TYPE]);
+	dj_dev->hdev = dj_hiddev;
+	dj_dev->dj_receiver_dev = djrcv_dev;
+	dj_dev->device_index = dj_report->device_index;
+	dj_hiddev->driver_data = dj_dev;
+
+	djrcv_dev->paired_dj_devices[dj_report->device_index] = dj_dev;
+
+	if (hid_add_device(dj_hiddev)) {
+		dev_err(&djrcv_hdev->dev, "%s: failed adding dj_device\n",
+			__func__);
+		goto hid_add_device_fail;
+	}
+
+	return;
+
+hid_add_device_fail:
+	djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL;
+	kfree(dj_dev);
+dj_device_allocate_fail:
+	hid_destroy_device(dj_hiddev);
+}
+
+static void delayedwork_callback(struct work_struct *work)
+{
+	struct dj_receiver_dev *djrcv_dev =
+		container_of(work, struct dj_receiver_dev, work);
+
+	struct dj_report dj_report;
+	unsigned long flags;
+	int count;
+
+	dbg_hid("%s\n", __func__);
+
+	spin_lock_irqsave(&djrcv_dev->lock, flags);
+
+	count = kfifo_out(&djrcv_dev->notif_fifo, &dj_report,
+				sizeof(struct dj_report));
+
+	if (count != sizeof(struct dj_report)) {
+		dev_err(&djrcv_dev->hdev->dev, "%s: workitem triggered without "
+			"notifications available\n", __func__);
+		spin_unlock_irqrestore(&djrcv_dev->lock, flags);
+		return;
+	}
+
+	if (!kfifo_is_empty(&djrcv_dev->notif_fifo)) {
+		if (schedule_work(&djrcv_dev->work) == 0) {
+			dbg_hid("%s: did not schedule the work item, was "
+				"already queued\n", __func__);
+		}
+	}
+
+	spin_unlock_irqrestore(&djrcv_dev->lock, flags);
+
+	switch (dj_report.report_type) {
+	case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
+		logi_dj_recv_add_djhid_device(djrcv_dev, &dj_report);
+		break;
+	case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
+		logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);
+		break;
+	default:
+		dbg_hid("%s: unexpected report type\n", __func__);
+	}
+}
+
+static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev,
+					   struct dj_report *dj_report)
+{
+	/* We are called from atomic context (tasklet && djrcv->lock held) */
+
+	kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
+
+	if (schedule_work(&djrcv_dev->work) == 0) {
+		dbg_hid("%s: did not schedule the work item, was already "
+			"queued\n", __func__);
+	}
+}
+
+static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev,
+					     struct dj_report *dj_report)
+{
+	/* We are called from atomic context (tasklet && djrcv->lock held) */
+	unsigned int i;
+	u8 reportbuffer[MAX_REPORT_SIZE];
+	struct dj_device *djdev;
+
+	djdev = djrcv_dev->paired_dj_devices[dj_report->device_index];
+
+	if (!djdev) {
+		dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
+			" is NULL, index %d\n", dj_report->device_index);
+		return;
+	}
+
+	memset(reportbuffer, 0, sizeof(reportbuffer));
+
+	for (i = 0; i < NUMBER_OF_HID_REPORTS; i++) {
+		if (djdev->reports_supported & (1 << i)) {
+			reportbuffer[0] = i;
+			if (hid_input_report(djdev->hdev,
+					     HID_INPUT_REPORT,
+					     reportbuffer,
+					     hid_reportid_size_map[i], 1)) {
+				dbg_hid("hid_input_report error sending null "
+					"report\n");
+			}
+		}
+	}
+}
+
+static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev,
+					struct dj_report *dj_report)
+{
+	/* We are called from atomic context (tasklet && djrcv->lock held) */
+	struct dj_device *dj_device;
+
+	dj_device = djrcv_dev->paired_dj_devices[dj_report->device_index];
+
+	if (dj_device == NULL) {
+		dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
+			" is NULL, index %d\n", dj_report->device_index);
+		return;
+	}
+
+	if ((dj_report->report_type > ARRAY_SIZE(hid_reportid_size_map) - 1) ||
+	    (hid_reportid_size_map[dj_report->report_type] == 0)) {
+		dbg_hid("invalid report type:%x\n", dj_report->report_type);
+		return;
+	}
+
+	if (hid_input_report(dj_device->hdev,
+			HID_INPUT_REPORT, &dj_report->report_type,
+			hid_reportid_size_map[dj_report->report_type], 1)) {
+		dbg_hid("hid_input_report error\n");
+	}
+}
+
+
+static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
+				    struct dj_report *dj_report)
+{
+	struct hid_device *hdev = djrcv_dev->hdev;
+	int sent_bytes;
+
+	if (!hdev->hid_output_raw_report) {
+		dev_err(&hdev->dev, "%s:"
+			"hid_output_raw_report is null\n", __func__);
+		return -ENODEV;
+	}
+
+	sent_bytes = hdev->hid_output_raw_report(hdev, (u8 *) dj_report,
+						 sizeof(struct dj_report),
+						 HID_OUTPUT_REPORT);
+
+	return (sent_bytes < 0) ? sent_bytes : 0;
+}
+
+static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
+{
+	struct dj_report dj_report;
+
+	memset(&dj_report, 0, sizeof(dj_report));
+	dj_report.report_id = REPORT_ID_DJ_SHORT;
+	dj_report.device_index = 0xFF;
+	dj_report.report_type = REPORT_TYPE_CMD_GET_PAIRED_DEVICES;
+	return logi_dj_recv_send_report(djrcv_dev, &dj_report);
+}
+
+static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
+					  unsigned timeout)
+{
+	struct dj_report dj_report;
+
+	memset(&dj_report, 0, sizeof(dj_report));
+	dj_report.report_id = REPORT_ID_DJ_SHORT;
+	dj_report.device_index = 0xFF;
+	dj_report.report_type = REPORT_TYPE_CMD_SWITCH;
+	dj_report.report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x1F;
+	dj_report.report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] = (u8)timeout;
+	return logi_dj_recv_send_report(djrcv_dev, &dj_report);
+}
+
+
+static int logi_dj_ll_open(struct hid_device *hid)
+{
+	dbg_hid("%s:%s\n", __func__, hid->phys);
+	return 0;
+
+}
+
+static void logi_dj_ll_close(struct hid_device *hid)
+{
+	dbg_hid("%s:%s\n", __func__, hid->phys);
+}
+
+static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
+					size_t count,
+					unsigned char report_type)
+{
+	/* Called by hid raw to send data */
+	dbg_hid("%s\n", __func__);
+
+	return 0;
+}
+
+static int logi_dj_ll_parse(struct hid_device *hid)
+{
+	struct dj_device *djdev = hid->driver_data;
+	int retval;
+
+	dbg_hid("%s\n", __func__);
+
+	djdev->hdev->version = 0x0111;
+	djdev->hdev->country = 0x00;
+
+	if (djdev->reports_supported & STD_KEYBOARD) {
+		dbg_hid("%s: sending a kbd descriptor, reports_supported: %x\n",
+			__func__, djdev->reports_supported);
+		retval = hid_parse_report(hid,
+					  (u8 *) kbd_descriptor,
+					  sizeof(kbd_descriptor));
+		if (retval) {
+			dbg_hid("%s: sending a kbd descriptor, hid_parse failed"
+				" error: %d\n", __func__, retval);
+			return retval;
+		}
+	}
+
+	if (djdev->reports_supported & STD_MOUSE) {
+		dbg_hid("%s: sending a mouse descriptor, reports_supported: "
+			"%x\n", __func__, djdev->reports_supported);
+		retval = hid_parse_report(hid,
+					  (u8 *) mse_descriptor,
+					  sizeof(mse_descriptor));
+		if (retval) {
+			dbg_hid("%s: sending a mouse descriptor, hid_parse "
+				"failed error: %d\n", __func__, retval);
+			return retval;
+		}
+	}
+
+	if (djdev->reports_supported & MULTIMEDIA) {
+		dbg_hid("%s: sending a multimedia report descriptor: %x\n",
+			__func__, djdev->reports_supported);
+		retval = hid_parse_report(hid,
+					  (u8 *) consumer_descriptor,
+					  sizeof(consumer_descriptor));
+		if (retval) {
+			dbg_hid("%s: sending a consumer_descriptor, hid_parse "
+				"failed error: %d\n", __func__, retval);
+			return retval;
+		}
+	}
+
+	if (djdev->reports_supported & POWER_KEYS) {
+		dbg_hid("%s: sending a power keys report descriptor: %x\n",
+			__func__, djdev->reports_supported);
+		retval = hid_parse_report(hid,
+					  (u8 *) syscontrol_descriptor,
+					  sizeof(syscontrol_descriptor));
+		if (retval) {
+			dbg_hid("%s: sending a syscontrol_descriptor, "
+				"hid_parse failed error: %d\n",
+				__func__, retval);
+			return retval;
+		}
+	}
+
+	if (djdev->reports_supported & MEDIA_CENTER) {
+		dbg_hid("%s: sending a media center report descriptor: %x\n",
+			__func__, djdev->reports_supported);
+		retval = hid_parse_report(hid,
+					  (u8 *) media_descriptor,
+					  sizeof(media_descriptor));
+		if (retval) {
+			dbg_hid("%s: sending a media_descriptor, hid_parse "
+				"failed error: %d\n", __func__, retval);
+			return retval;
+		}
+	}
+
+	if (djdev->reports_supported & KBD_LEDS) {
+		dbg_hid("%s: need to send kbd leds report descriptor: %x\n",
+			__func__, djdev->reports_supported);
+	}
+
+	return 0;
+}
+
+static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
+				  unsigned int code, int value)
+{
+	/* Sent by the input layer to handle leds and Force Feedback */
+	struct hid_device *dj_hiddev = input_get_drvdata(dev);
+	struct dj_device *dj_dev = dj_hiddev->driver_data;
+
+	struct dj_receiver_dev *djrcv_dev =
+	    dev_get_drvdata(dj_hiddev->dev.parent);
+	struct hid_device *dj_rcv_hiddev = djrcv_dev->hdev;
+	struct hid_report_enum *output_report_enum;
+
+	struct hid_field *field;
+	struct hid_report *report;
+	unsigned char data[8];
+	int offset;
+
+	dbg_hid("%s: %s, type:%d | code:%d | value:%d\n",
+		__func__, dev->phys, type, code, value);
+
+	if (type != EV_LED)
+		return -1;
+
+	offset = hidinput_find_field(dj_hiddev, type, code, &field);
+
+	if (offset == -1) {
+		dev_warn(&dev->dev, "event field not found\n");
+		return -1;
+	}
+	hid_set_field(field, offset, value);
+	hid_output_report(field->report, &data[0]);
+
+	output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT];
+	report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
+	hid_set_field(report->field[0], 0, dj_dev->device_index);
+	hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS);
+	hid_set_field(report->field[0], 2, data[1]);
+
+	usbhid_submit_report(dj_rcv_hiddev, report, USB_DIR_OUT);
+
+	return 0;
+
+}
+
+static int logi_dj_ll_start(struct hid_device *hid)
+{
+	dbg_hid("%s\n", __func__);
+	return 0;
+}
+
+static void logi_dj_ll_stop(struct hid_device *hid)
+{
+	dbg_hid("%s\n", __func__);
+}
+
+
+static struct hid_ll_driver logi_dj_ll_driver = {
+	.parse = logi_dj_ll_parse,
+	.start = logi_dj_ll_start,
+	.stop = logi_dj_ll_stop,
+	.open = logi_dj_ll_open,
+	.close = logi_dj_ll_close,
+	.hidinput_input_event = logi_dj_ll_input_event,
+};
+
+
+static int logi_dj_raw_event(struct hid_device *hdev,
+			     struct hid_report *report, u8 *data,
+			     int size)
+{
+	struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
+	struct dj_report *dj_report = (struct dj_report *) data;
+	unsigned long flags;
+	bool report_processed = false;
+
+	dbg_hid("%s, size:%d\n", __func__, size);
+
+	/* Here we receive all data coming from iface 2, there are 4 cases:
+	 *
+	 * 1) Data should continue its normal processing i.e. data does not
+	 * come from the DJ collection, in which case we do nothing and
+	 * return 0, so hid-core can continue normal processing (will forward
+	 * to associated hidraw device)
+	 *
+	 * 2) Data is from DJ collection, and is intended for this driver i. e.
+	 * data contains arrival, departure, etc notifications, in which case
+	 * we queue them for delayed processing by the work queue. We return 1
+	 * to hid-core as no further processing is required from it.
+	 *
+	 * 3) Data is from DJ collection, and informs a connection change,
+	 * if the change means rf link loss, then we must send a null report
+	 * to the upper layer to discard potentially pressed keys that may be
+	 * repeated forever by the input layer. Return 1 to hid-core as no
+	 * further processing is required.
+	 *
+	 * 4) Data is from DJ collection and is an actual input event from
+	 * a paired DJ device in which case we forward it to the correct hid
+	 * device (via hid_input_report() ) and return 1 so hid-core does not do
+	 * anything else with it.
+	 */
+
+	spin_lock_irqsave(&djrcv_dev->lock, flags);
+	if (dj_report->report_id == REPORT_ID_DJ_SHORT) {
+		switch (dj_report->report_type) {
+		case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
+		case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
+			logi_dj_recv_queue_notification(djrcv_dev, dj_report);
+			break;
+		case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
+			if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] ==
+			    STATUS_LINKLOSS) {
+				logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
+			}
+			break;
+		default:
+			logi_dj_recv_forward_report(djrcv_dev, dj_report);
+		}
+		report_processed = true;
+	}
+	spin_unlock_irqrestore(&djrcv_dev->lock, flags);
+
+	return report_processed;
+}
+
+static int logi_dj_probe(struct hid_device *hdev,
+			 const struct hid_device_id *id)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct dj_receiver_dev *djrcv_dev;
+	int retval;
+
+	if (is_dj_device((struct dj_device *)hdev->driver_data))
+		return -ENODEV;
+
+	dbg_hid("%s called for ifnum %d\n", __func__,
+		intf->cur_altsetting->desc.bInterfaceNumber);
+
+	/* Ignore interfaces 0 and 1, they will not carry any data, dont create
+	 * any hid_device for them */
+	if (intf->cur_altsetting->desc.bInterfaceNumber !=
+	    LOGITECH_DJ_INTERFACE_NUMBER) {
+		dbg_hid("%s: ignoring ifnum %d\n", __func__,
+			intf->cur_altsetting->desc.bInterfaceNumber);
+		return -ENODEV;
+	}
+
+	/* Treat interface 2 */
+
+	djrcv_dev = kzalloc(sizeof(struct dj_receiver_dev), GFP_KERNEL);
+	if (!djrcv_dev) {
+		dev_err(&hdev->dev,
+			"%s:failed allocating dj_receiver_dev\n", __func__);
+		return -ENOMEM;
+	}
+	djrcv_dev->hdev = hdev;
+	INIT_WORK(&djrcv_dev->work, delayedwork_callback);
+	spin_lock_init(&djrcv_dev->lock);
+	if (kfifo_alloc(&djrcv_dev->notif_fifo,
+			DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct dj_report),
+			GFP_KERNEL)) {
+		dev_err(&hdev->dev,
+			"%s:failed allocating notif_fifo\n", __func__);
+		kfree(djrcv_dev);
+		return -ENOMEM;
+	}
+	hid_set_drvdata(hdev, djrcv_dev);
+
+	/* Call  to usbhid to fetch the HID descriptors of interface 2 and
+	 * subsequently call to the hid/hid-core to parse the fetched
+	 * descriptors, this will in turn create the hidraw and hiddev nodes
+	 * for interface 2 of the receiver */
+	retval = hid_parse(hdev);
+	if (retval) {
+		dev_err(&hdev->dev,
+			"%s:parse of interface 2 failed\n", __func__);
+		goto hid_parse_fail;
+	}
+
+	/* Starts the usb device and connects to upper interfaces hiddev and
+	 * hidraw */
+	retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (retval) {
+		dev_err(&hdev->dev,
+			"%s:hid_hw_start returned error\n", __func__);
+		goto hid_hw_start_fail;
+	}
+
+	retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
+	if (retval < 0) {
+		dev_err(&hdev->dev,
+			"%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
+			__func__, retval);
+		goto switch_to_dj_mode_fail;
+	}
+
+	/* This is enabling the polling urb on the IN endpoint */
+	retval = hdev->ll_driver->open(hdev);
+	if (retval < 0) {
+		dev_err(&hdev->dev, "%s:hdev->ll_driver->open returned "
+			"error:%d\n", __func__, retval);
+		goto llopen_failed;
+	}
+
+	retval = logi_dj_recv_query_paired_devices(djrcv_dev);
+	if (retval < 0) {
+		dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices "
+			"error:%d\n", __func__, retval);
+		goto logi_dj_recv_query_paired_devices_failed;
+	}
+
+	return retval;
+
+logi_dj_recv_query_paired_devices_failed:
+	hdev->ll_driver->close(hdev);
+
+llopen_failed:
+switch_to_dj_mode_fail:
+	hid_hw_stop(hdev);
+
+hid_hw_start_fail:
+hid_parse_fail:
+	kfifo_free(&djrcv_dev->notif_fifo);
+	kfree(djrcv_dev);
+	hid_set_drvdata(hdev, NULL);
+	return retval;
+
+}
+
+#ifdef CONFIG_PM
+static int logi_dj_reset_resume(struct hid_device *hdev)
+{
+	int retval;
+	struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
+
+	retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
+	if (retval < 0) {
+		dev_err(&hdev->dev,
+			"%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
+			__func__, retval);
+	}
+
+	return 0;
+}
+#endif
+
+static void logi_dj_remove(struct hid_device *hdev)
+{
+	struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
+	struct dj_device *dj_dev;
+	int i;
+
+	dbg_hid("%s\n", __func__);
+
+	cancel_work_sync(&djrcv_dev->work);
+
+	hdev->ll_driver->close(hdev);
+	hid_hw_stop(hdev);
+
+	/* I suppose that at this point the only context that can access
+	 * the djrecv_data is this thread as the work item is guaranteed to
+	 * have finished and no more raw_event callbacks should arrive after
+	 * the remove callback was triggered so no locks are put around the
+	 * code below */
+	for (i = 0; i < (DJ_MAX_PAIRED_DEVICES + DJ_DEVICE_INDEX_MIN); i++) {
+		dj_dev = djrcv_dev->paired_dj_devices[i];
+		if (dj_dev != NULL) {
+			hid_destroy_device(dj_dev->hdev);
+			kfree(dj_dev);
+			djrcv_dev->paired_dj_devices[i] = NULL;
+		}
+	}
+
+	kfifo_free(&djrcv_dev->notif_fifo);
+	kfree(djrcv_dev);
+	hid_set_drvdata(hdev, NULL);
+}
+
+static int logi_djdevice_probe(struct hid_device *hdev,
+			 const struct hid_device_id *id)
+{
+	int ret;
+	struct dj_device *dj_dev = hdev->driver_data;
+
+	if (!is_dj_device(dj_dev))
+		return -ENODEV;
+
+	ret = hid_parse(hdev);
+	if (!ret)
+		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+
+	return ret;
+}
+
+static const struct hid_device_id logi_dj_receivers[] = {
+	{HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+		USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)},
+	{HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+		USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)},
+	{}
+};
+
+MODULE_DEVICE_TABLE(hid, logi_dj_receivers);
+
+static struct hid_driver logi_djreceiver_driver = {
+	.name = "logitech-djreceiver",
+	.id_table = logi_dj_receivers,
+	.probe = logi_dj_probe,
+	.remove = logi_dj_remove,
+	.raw_event = logi_dj_raw_event,
+#ifdef CONFIG_PM
+	.reset_resume = logi_dj_reset_resume,
+#endif
+};
+
+
+static const struct hid_device_id logi_dj_devices[] = {
+	{HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+		USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)},
+	{HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+		USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)},
+	{}
+};
+
+static struct hid_driver logi_djdevice_driver = {
+	.name = "logitech-djdevice",
+	.id_table = logi_dj_devices,
+	.probe = logi_djdevice_probe,
+};
+
+
+static int __init logi_dj_init(void)
+{
+	int retval;
+
+	dbg_hid("Logitech-DJ:%s\n", __func__);
+
+	retval = hid_register_driver(&logi_djreceiver_driver);
+	if (retval)
+		return retval;
+
+	retval = hid_register_driver(&logi_djdevice_driver);
+	if (retval)
+		hid_unregister_driver(&logi_djreceiver_driver);
+
+	return retval;
+
+}
+
+static void __exit logi_dj_exit(void)
+{
+	dbg_hid("Logitech-DJ:%s\n", __func__);
+
+	hid_unregister_driver(&logi_djdevice_driver);
+	hid_unregister_driver(&logi_djreceiver_driver);
+
+}
+
+module_init(logi_dj_init);
+module_exit(logi_dj_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Logitech");
+MODULE_AUTHOR("Nestor Lopez Casado");
+MODULE_AUTHOR("nlopezcasad@logitech.com");
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-logitech-dj.h linux-libre-3.2-gnu/drivers/hid/hid-logitech-dj.h
--- linux-libre-3.1-gnu/drivers/hid/hid-logitech-dj.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hid/hid-logitech-dj.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,123 @@
+#ifndef __HID_LOGITECH_DJ_H
+#define __HID_LOGITECH_DJ_H
+
+/*
+ *  HID driver for Logitech Unifying receivers
+ *
+ *  Copyright (c) 2011 Logitech
+ */
+
+/*
+ * This program is free software; you can 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/kfifo.h>
+
+#define DJ_MAX_PAIRED_DEVICES			6
+#define DJ_MAX_NUMBER_NOTIFICATIONS		8
+#define DJ_DEVICE_INDEX_MIN 			1
+#define DJ_DEVICE_INDEX_MAX 			6
+
+#define DJREPORT_SHORT_LENGTH			15
+#define DJREPORT_LONG_LENGTH			32
+
+#define REPORT_ID_DJ_SHORT			0x20
+#define REPORT_ID_DJ_LONG			0x21
+
+#define REPORT_TYPE_RFREPORT_FIRST		0x01
+#define REPORT_TYPE_RFREPORT_LAST		0x1F
+
+/* Command Switch to DJ mode */
+#define REPORT_TYPE_CMD_SWITCH			0x80
+#define CMD_SWITCH_PARAM_DEVBITFIELD		0x00
+#define CMD_SWITCH_PARAM_TIMEOUT_SECONDS	0x01
+#define TIMEOUT_NO_KEEPALIVE			0x00
+
+/* Command to Get the list of Paired devices */
+#define REPORT_TYPE_CMD_GET_PAIRED_DEVICES	0x81
+
+/* Device Paired Notification */
+#define REPORT_TYPE_NOTIF_DEVICE_PAIRED		0x41
+#define SPFUNCTION_MORE_NOTIF_EXPECTED		0x01
+#define SPFUNCTION_DEVICE_LIST_EMPTY		0x02
+#define DEVICE_PAIRED_PARAM_SPFUNCTION		0x00
+#define DEVICE_PAIRED_PARAM_EQUAD_ID_LSB	0x01
+#define DEVICE_PAIRED_PARAM_EQUAD_ID_MSB	0x02
+#define DEVICE_PAIRED_RF_REPORT_TYPE		0x03
+
+/* Device Un-Paired Notification */
+#define REPORT_TYPE_NOTIF_DEVICE_UNPAIRED	0x40
+
+
+/* Connection Status Notification */
+#define REPORT_TYPE_NOTIF_CONNECTION_STATUS	0x42
+#define CONNECTION_STATUS_PARAM_STATUS		0x00
+#define STATUS_LINKLOSS				0x01
+
+/* Error Notification */
+#define REPORT_TYPE_NOTIF_ERROR			0x7F
+#define NOTIF_ERROR_PARAM_ETYPE			0x00
+#define ETYPE_KEEPALIVE_TIMEOUT			0x01
+
+/* supported DJ HID && RF report types */
+#define REPORT_TYPE_KEYBOARD			0x01
+#define REPORT_TYPE_MOUSE			0x02
+#define REPORT_TYPE_CONSUMER_CONTROL		0x03
+#define REPORT_TYPE_SYSTEM_CONTROL		0x04
+#define REPORT_TYPE_MEDIA_CENTER		0x08
+#define REPORT_TYPE_LEDS			0x0E
+
+/* RF Report types bitfield */
+#define STD_KEYBOARD				0x00000002
+#define STD_MOUSE				0x00000004
+#define MULTIMEDIA				0x00000008
+#define POWER_KEYS				0x00000010
+#define MEDIA_CENTER				0x00000100
+#define KBD_LEDS				0x00004000
+
+struct dj_report {
+	u8 report_id;
+	u8 device_index;
+	u8 report_type;
+	u8 report_params[DJREPORT_SHORT_LENGTH - 3];
+};
+
+struct dj_receiver_dev {
+	struct hid_device *hdev;
+	struct dj_device *paired_dj_devices[DJ_MAX_PAIRED_DEVICES +
+					    DJ_DEVICE_INDEX_MIN];
+	struct work_struct work;
+	struct kfifo notif_fifo;
+	spinlock_t lock;
+};
+
+struct dj_device {
+	struct hid_device *hdev;
+	struct dj_receiver_dev *dj_receiver_dev;
+	u32 reports_supported;
+	u8 device_index;
+};
+
+/**
+ * is_dj_device - know if the given dj_device is not the receiver.
+ * @dj_dev: the dj device to test
+ *
+ * This macro tests if a struct dj_device pointer is a device created
+ * by the bus enumarator.
+ */
+#define is_dj_device(dj_dev) \
+	(&(dj_dev)->dj_receiver_dev->hdev->dev == (dj_dev)->hdev->dev.parent)
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-magicmouse.c linux-libre-3.2-gnu/drivers/hid/hid-magicmouse.c
--- linux-libre-3.1-gnu/drivers/hid/hid-magicmouse.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-magicmouse.c	2012-01-04 18:55:44.000000000 -0500
@@ -405,6 +405,13 @@
 			__set_bit(REL_HWHEEL, input->relbit);
 		}
 	} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
+		/* input->keybit is initialized with incorrect button info
+		 * for Magic Trackpad. There really is only one physical
+		 * button (BTN_LEFT == BTN_MOUSE). Make sure we don't
+		 * advertise buttons that don't exist...
+		 */
+		__clear_bit(BTN_RIGHT, input->keybit);
+		__clear_bit(BTN_MIDDLE, input->keybit);
 		__set_bit(BTN_MOUSE, input->keybit);
 		__set_bit(BTN_TOOL_FINGER, input->keybit);
 		__set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-multitouch.c linux-libre-3.2-gnu/drivers/hid/hid-multitouch.c
--- linux-libre-3.1-gnu/drivers/hid/hid-multitouch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-multitouch.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,10 +47,11 @@
 #define MT_QUIRK_SLOT_IS_CONTACTID	(1 << 1)
 #define MT_QUIRK_CYPRESS		(1 << 2)
 #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)
-#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE	(1 << 7)
+#define MT_QUIRK_ALWAYS_VALID		(1 << 4)
+#define MT_QUIRK_VALID_IS_INRANGE	(1 << 5)
+#define MT_QUIRK_VALID_IS_CONFIDENCE	(1 << 6)
+#define MT_QUIRK_EGALAX_XYZ_FIXUP	(1 << 7)
+#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE	(1 << 8)
 
 struct mt_slot {
 	__s32 x, y, p, w, h;
@@ -86,11 +87,12 @@
 /* classes of device behavior */
 #define MT_CLS_DEFAULT				0x0001
 
-#define MT_CLS_CONFIDENCE			0x0002
-#define MT_CLS_CONFIDENCE_MINUS_ONE		0x0003
-#define MT_CLS_DUAL_INRANGE_CONTACTID		0x0004
-#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER	0x0005
-#define MT_CLS_DUAL_NSMU_CONTACTID		0x0006
+#define MT_CLS_SERIAL				0x0002
+#define MT_CLS_CONFIDENCE			0x0003
+#define MT_CLS_CONFIDENCE_MINUS_ONE		0x0004
+#define MT_CLS_DUAL_INRANGE_CONTACTID		0x0005
+#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER	0x0006
+#define MT_CLS_DUAL_NSMU_CONTACTID		0x0007
 
 /* vendor specific classes */
 #define MT_CLS_3M				0x0101
@@ -134,6 +136,8 @@
 struct mt_class mt_classes[] = {
 	{ .name = MT_CLS_DEFAULT,
 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
+	{ .name = MT_CLS_SERIAL,
+		.quirks = MT_QUIRK_ALWAYS_VALID},
 	{ .name = MT_CLS_CONFIDENCE,
 		.quirks = MT_QUIRK_VALID_IS_CONFIDENCE },
 	{ .name = MT_CLS_CONFIDENCE_MINUS_ONE,
@@ -213,6 +217,16 @@
 	struct mt_class *cls = td->mtclass;
 	__s32 quirks = cls->quirks;
 
+	/* Only map fields from TouchScreen or TouchPad collections.
+         * We need to ignore fields that belong to other collections
+         * such as Mouse that might have the same GenericDesktop usages. */
+	if (field->application == HID_DG_TOUCHSCREEN)
+		set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
+	else if (field->application == HID_DG_TOUCHPAD)
+		set_bit(INPUT_PROP_POINTER, hi->input->propbit);
+	else
+		return 0;
+
 	switch (usage->hid & HID_USAGE_PAGE) {
 
 	case HID_UP_GENDESK:
@@ -435,7 +449,9 @@
 	if (hid->claimed & HID_CLAIMED_INPUT && td->slots) {
 		switch (usage->hid) {
 		case HID_DG_INRANGE:
-			if (quirks & MT_QUIRK_VALID_IS_INRANGE)
+			if (quirks & MT_QUIRK_ALWAYS_VALID)
+				td->curvalid = true;
+			else if (quirks & MT_QUIRK_VALID_IS_INRANGE)
 				td->curvalid = value;
 			break;
 		case HID_DG_TIPSWITCH:
@@ -662,6 +678,11 @@
 		HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH,
 			USB_DEVICE_ID_GOODTOUCH_000f) },
 
+	/* Ideacom panel */
+	{ .driver_data = MT_CLS_SERIAL,
+		HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM,
+			USB_DEVICE_ID_IDEACOM_IDC6650) },
+
 	/* Ilitek dual touch panel */
 	{  .driver_data = MT_CLS_DEFAULT,
 		HID_USB_DEVICE(USB_VENDOR_ID_ILITEK,
@@ -672,6 +693,11 @@
 		HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS,
 			USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
 
+	/* LG Display panels */
+	{ .driver_data = MT_CLS_DEFAULT,
+		HID_USB_DEVICE(USB_VENDOR_ID_LG,
+			USB_DEVICE_ID_LG_MULTITOUCH) },
+
 	/* Lumio panels */
 	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
 		HID_USB_DEVICE(USB_VENDOR_ID_LUMIO,
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-picolcd.c linux-libre-3.2-gnu/drivers/hid/hid-picolcd.c
--- linux-libre-3.1-gnu/drivers/hid/hid-picolcd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-picolcd.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 
 #include <linux/completion.h>
 #include <linux/uaccess.h>
+#include <linux/module.h>
 
 #define PICOLCD_NAME "PicoLCD (graphic)"
 
@@ -2409,7 +2410,7 @@
 #ifdef CONFIG_PM
 static int picolcd_suspend(struct hid_device *hdev, pm_message_t message)
 {
-	if (message.event & PM_EVENT_AUTO)
+	if (PMSG_IS_AUTO(message))
 		return 0;
 
 	picolcd_suspend_backlight(hid_get_drvdata(hdev));
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-pl.c linux-libre-3.2-gnu/drivers/hid/hid-pl.c
--- linux-libre-3.1-gnu/drivers/hid/hid-pl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-pl.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,7 @@
 
 #include <linux/input.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
 
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-primax.c linux-libre-3.2-gnu/drivers/hid/hid-primax.c
--- linux-libre-3.1-gnu/drivers/hid/hid-primax.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hid/hid-primax.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,117 @@
+/*
+ * HID driver for primax and similar keyboards with in-band modifiers
+ *
+ * Copyright 2011 Google Inc. All Rights Reserved
+ *
+ * Author:
+ *	Terry Lambert <tlambert@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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+static int px_raw_event(struct hid_device *hid, struct hid_report *report,
+	 u8 *data, int size)
+{
+	int idx = size;
+
+	switch (report->id) {
+	case 0:		/* keyboard input */
+		/*
+		 * Convert in-band modifier key values into out of band
+		 * modifier bits and pull the key strokes from the report.
+		 * Thus a report data set which looked like:
+		 *
+		 * [00][00][E0][30][00][00][00][00]
+		 * (no modifier bits + "Left Shift" key + "1" key)
+		 *
+		 * Would be converted to:
+		 *
+		 * [01][00][00][30][00][00][00][00]
+		 * (Left Shift modifier bit + "1" key)
+		 *
+		 * As long as it's in the size range, the upper level
+		 * drivers don't particularly care if there are in-band
+		 * 0-valued keys, so they don't stop parsing.
+		 */
+		while (--idx > 1) {
+			if (data[idx] < 0xE0 || data[idx] > 0xE7)
+				continue;
+			data[0] |= (1 << (data[idx] - 0xE0));
+			data[idx] = 0;
+		}
+		hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, 0);
+		return 1;
+
+	default:	/* unknown report */
+		/* Unknown report type; pass upstream */
+		hid_info(hid, "unknown report type %d\n", report->id);
+		break;
+	}
+
+	return 0;
+}
+
+static int px_probe(struct hid_device *hid, const struct hid_device_id *id)
+{
+	int ret;
+
+	ret = hid_parse(hid);
+	if (ret) {
+		hid_err(hid, "parse failed\n");
+		goto fail;
+	}
+
+	ret = hid_hw_start(hid, HID_CONNECT_DEFAULT);
+	if (ret)
+		hid_err(hid, "hw start failed\n");
+
+fail:
+	return ret;
+}
+
+static void px_remove(struct hid_device *hid)
+{
+	hid_hw_stop(hid);
+}
+
+static const struct hid_device_id px_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, px_devices);
+
+static struct hid_driver px_driver = {
+	.name = "primax",
+	.id_table = px_devices,
+	.raw_event = px_raw_event,
+	.probe = px_probe,
+	.remove = px_remove,
+};
+
+static int __init px_init(void)
+{
+	return hid_register_driver(&px_driver);
+}
+
+static void __exit px_exit(void)
+{
+	hid_unregister_driver(&px_driver);
+}
+
+module_init(px_init);
+module_exit(px_exit);
+MODULE_AUTHOR("Terry Lambert <tlambert@google.com>");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-prodikeys.c linux-libre-3.2-gnu/drivers/hid/hid-prodikeys.c
--- linux-libre-3.1-gnu/drivers/hid/hid-prodikeys.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-prodikeys.c	2012-01-04 18:55:44.000000000 -0500
@@ -816,7 +816,7 @@
 	if (pm == NULL) {
 		hid_err(hdev, "can't alloc descriptor\n");
 		ret = -ENOMEM;
-		goto err_free;
+		goto err_free_pk;
 	}
 
 	pm->pk = pk;
@@ -849,10 +849,10 @@
 err_stop:
 	hid_hw_stop(hdev);
 err_free:
-	if (pm != NULL)
-		kfree(pm);
-
+	kfree(pm);
+err_free_pk:
 	kfree(pk);
+
 	return ret;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/hid/hidraw.c linux-libre-3.2-gnu/drivers/hid/hidraw.c
--- linux-libre-3.1-gnu/drivers/hid/hidraw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hidraw.c	2012-01-04 18:55:44.000000000 -0500
@@ -259,7 +259,6 @@
 
 	mutex_lock(&minors_lock);
 	if (!hidraw_table[minor]) {
-		kfree(list);
 		err = -ENODEV;
 		goto out_unlock;
 	}
@@ -272,8 +271,10 @@
 	dev = hidraw_table[minor];
 	if (!dev->open++) {
 		err = hid_hw_power(dev->hid, PM_HINT_FULLON);
-		if (err < 0)
+		if (err < 0) {
+			dev->open--;
 			goto out_unlock;
+		}
 
 		err = hid_hw_open(dev->hid);
 		if (err < 0) {
@@ -285,6 +286,8 @@
 out_unlock:
 	mutex_unlock(&minors_lock);
 out:
+	if (err < 0)
+		kfree(list);
 	return err;
 
 }
@@ -510,13 +513,12 @@
 {
 	struct hidraw *hidraw = hid->hidraw;
 
+	mutex_lock(&minors_lock);
 	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);
 
 	if (hidraw->open) {
 		hid_hw_close(hid);
@@ -524,6 +526,7 @@
 	} else {
 		kfree(hidraw);
 	}
+	mutex_unlock(&minors_lock);
 }
 EXPORT_SYMBOL_GPL(hidraw_disconnect);
 
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-roccat.c linux-libre-3.2-gnu/drivers/hid/hid-roccat.c
--- linux-libre-3.1-gnu/drivers/hid/hid-roccat.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-roccat.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include <linux/hid-roccat.h>
+#include <linux/module.h>
 
 #define ROCCAT_FIRST_MINOR 0
 #define ROCCAT_MAX_DEVICES 8
@@ -162,27 +163,27 @@
 
 	device = devices[minor];
 
-	mutex_lock(&device->readers_lock);
-
 	if (!device) {
 		pr_emerg("roccat device with minor %d doesn't exist\n", minor);
 		error = -ENODEV;
-		goto exit_err;
+		goto exit_err_devices;
 	}
 
+	mutex_lock(&device->readers_lock);
+
 	if (!device->open++) {
 		/* power on device on adding first reader */
 		error = hid_hw_power(device->hid, PM_HINT_FULLON);
 		if (error < 0) {
 			--device->open;
-			goto exit_err;
+			goto exit_err_readers;
 		}
 
 		error = hid_hw_open(device->hid);
 		if (error < 0) {
 			hid_hw_power(device->hid, PM_HINT_NORMAL);
 			--device->open;
-			goto exit_err;
+			goto exit_err_readers;
 		}
 	}
 
@@ -193,13 +194,13 @@
 	list_add_tail(&reader->node, &device->readers);
 	file->private_data = reader;
 
-exit_unlock:
+exit_err_readers:
 	mutex_unlock(&device->readers_lock);
+exit_err_devices:
 	mutex_unlock(&devices_lock);
+	if (error)
+		kfree(reader);
 	return error;
-exit_err:
-	kfree(reader);
-	goto exit_unlock;
 }
 
 static int roccat_release(struct inode *inode, struct file *file)
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-roccat-common.c linux-libre-3.2-gnu/drivers/hid/hid-roccat-common.c
--- linux-libre-3.1-gnu/drivers/hid/hid-roccat-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-roccat-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 
 #include <linux/hid.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include "hid-roccat-common.h"
 
 static inline uint16_t roccat_common_feature_report(uint8_t report_id)
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-roccat-kone.c linux-libre-3.2-gnu/drivers/hid/hid-roccat-kone.c
--- linux-libre-3.1-gnu/drivers/hid/hid-roccat-kone.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-roccat-kone.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,21 @@
 
 static uint profile_numbers[5] = {0, 1, 2, 3, 4};
 
+static void kone_profile_activated(struct kone_device *kone, uint new_profile)
+{
+	kone->actual_profile = new_profile;
+	kone->actual_dpi = kone->profiles[new_profile - 1].startup_dpi;
+}
+
+static void kone_profile_report(struct kone_device *kone, uint new_profile)
+{
+	struct kone_roccat_report roccat_report;
+	roccat_report.event = kone_mouse_event_switch_profile;
+	roccat_report.value = new_profile;
+	roccat_report.key = 0;
+	roccat_report_event(kone->chrdev_minor, (uint8_t *)&roccat_report);
+}
+
 static int kone_receive(struct usb_device *usb_dev, uint usb_command,
 		void *data, uint size)
 {
@@ -283,7 +298,7 @@
 			container_of(kobj, struct device, kobj)->parent->parent;
 	struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
 	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
-	int retval = 0, difference;
+	int retval = 0, difference, old_profile;
 
 	/* I need to get my data in one piece */
 	if (off != 0 || count != sizeof(struct kone_settings))
@@ -294,21 +309,20 @@
 	if (difference) {
 		retval = kone_set_settings(usb_dev,
 				(struct kone_settings const *)buf);
-		if (!retval)
-			memcpy(&kone->settings, buf,
-					sizeof(struct kone_settings));
-	}
-	mutex_unlock(&kone->kone_lock);
+		if (retval) {
+			mutex_unlock(&kone->kone_lock);
+			return retval;
+		}
 
-	if (retval)
-		return retval;
+		old_profile = kone->settings.startup_profile;
+		memcpy(&kone->settings, buf, sizeof(struct kone_settings));
 
-	/*
-	 * If we get here, treat settings as okay and update actual values
-	 * according to startup_profile
-	 */
-	kone->actual_profile = kone->settings.startup_profile;
-	kone->actual_dpi = kone->profiles[kone->actual_profile - 1].startup_dpi;
+		kone_profile_activated(kone, kone->settings.startup_profile);
+
+		if (kone->settings.startup_profile != old_profile)
+			kone_profile_report(kone, kone->settings.startup_profile);
+	}
+	mutex_unlock(&kone->kone_lock);
 
 	return sizeof(struct kone_settings);
 }
@@ -501,6 +515,8 @@
 				goto exit_no_settings;
 			goto exit_unlock;
 		}
+		/* calibration resets profile */
+		kone_profile_activated(kone, kone->settings.startup_profile);
 	}
 
 	retval = size;
@@ -544,16 +560,16 @@
 	kone_set_settings_checksum(&kone->settings);
 
 	retval = kone_set_settings(usb_dev, &kone->settings);
-
-	mutex_unlock(&kone->kone_lock);
-
-	if (retval)
+	if (retval) {
+		mutex_unlock(&kone->kone_lock);
 		return retval;
+	}
 
 	/* changing the startup profile immediately activates this profile */
-	kone->actual_profile = new_startup_profile;
-	kone->actual_dpi = kone->profiles[kone->actual_profile - 1].startup_dpi;
+	kone_profile_activated(kone, new_startup_profile);
+	kone_profile_report(kone, new_startup_profile);
 
+	mutex_unlock(&kone->kone_lock);
 	return size;
 }
 
@@ -665,8 +681,7 @@
 	if (retval)
 		return retval;
 
-	kone->actual_profile = kone->settings.startup_profile;
-	kone->actual_dpi = kone->profiles[kone->actual_profile].startup_dpi;
+	kone_profile_activated(kone, kone->settings.startup_profile);
 
 	return 0;
 }
@@ -776,10 +791,10 @@
 {
 	switch (event->event) {
 	case kone_mouse_event_switch_profile:
+		kone->actual_dpi = kone->profiles[event->value - 1].
+				startup_dpi;
 	case kone_mouse_event_osd_profile:
 		kone->actual_profile = event->value;
-		kone->actual_dpi = kone->profiles[kone->actual_profile - 1].
-				startup_dpi;
 		break;
 	case kone_mouse_event_switch_dpi:
 	case kone_mouse_event_osd_dpi:
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-roccat-kovaplus.c linux-libre-3.2-gnu/drivers/hid/hid-roccat-kovaplus.c
--- linux-libre-3.1-gnu/drivers/hid/hid-roccat-kovaplus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-roccat-kovaplus.c	2012-01-04 18:55:44.000000000 -0500
@@ -323,6 +323,7 @@
 	struct usb_device *usb_dev;
 	unsigned long profile;
 	int retval;
+	struct kovaplus_roccat_report roccat_report;
 
 	dev = dev->parent->parent;
 	kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
@@ -337,10 +338,22 @@
 
 	mutex_lock(&kovaplus->kovaplus_lock);
 	retval = kovaplus_set_actual_profile(usb_dev, profile);
+	if (retval) {
+		mutex_unlock(&kovaplus->kovaplus_lock);
+		return retval;
+	}
+
 	kovaplus_profile_activated(kovaplus, profile);
+
+	roccat_report.type = KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1;
+	roccat_report.profile = profile + 1;
+	roccat_report.button = 0;
+	roccat_report.data1 = profile + 1;
+	roccat_report.data2 = 0;
+	roccat_report_event(kovaplus->chrdev_minor,
+			(uint8_t const *)&roccat_report);
+
 	mutex_unlock(&kovaplus->kovaplus_lock);
-	if (retval)
-		return retval;
 
 	return size;
 }
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-roccat-pyra.c linux-libre-3.2-gnu/drivers/hid/hid-roccat-pyra.c
--- linux-libre-3.1-gnu/drivers/hid/hid-roccat-pyra.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-roccat-pyra.c	2012-01-04 18:55:44.000000000 -0500
@@ -298,6 +298,7 @@
 	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
 	int retval = 0;
 	int difference;
+	struct pyra_roccat_report roccat_report;
 
 	if (off != 0 || count != sizeof(struct pyra_settings))
 		return -EINVAL;
@@ -307,17 +308,23 @@
 	if (difference) {
 		retval = pyra_set_settings(usb_dev,
 				(struct pyra_settings const *)buf);
-		if (!retval)
-			memcpy(&pyra->settings, buf,
-					sizeof(struct pyra_settings));
-	}
-	mutex_unlock(&pyra->pyra_lock);
+		if (retval) {
+			mutex_unlock(&pyra->pyra_lock);
+			return retval;
+		}
 
-	if (retval)
-		return retval;
+		memcpy(&pyra->settings, buf,
+				sizeof(struct pyra_settings));
 
-	profile_activated(pyra, pyra->settings.startup_profile);
+		profile_activated(pyra, pyra->settings.startup_profile);
 
+		roccat_report.type = PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2;
+		roccat_report.value = pyra->settings.startup_profile + 1;
+		roccat_report.key = 0;
+		roccat_report_event(pyra->chrdev_minor,
+				(uint8_t const *)&roccat_report);
+	}
+	mutex_unlock(&pyra->pyra_lock);
 	return sizeof(struct pyra_settings);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-sjoy.c linux-libre-3.2-gnu/drivers/hid/hid-sjoy.c
--- linux-libre-3.1-gnu/drivers/hid/hid-sjoy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-sjoy.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
+#include <linux/module.h>
 #include "hid-ids.h"
 
 #ifdef CONFIG_SMARTJOYPLUS_FF
@@ -65,8 +66,7 @@
 {
 	struct sjoyff_device *sjoyff;
 	struct hid_report *report;
-	struct hid_input *hidinput = list_entry(hid->inputs.next,
-						struct hid_input, list);
+	struct hid_input *hidinput;
 	struct list_head *report_list =
 			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
 	struct list_head *report_ptr = report_list;
@@ -78,43 +78,45 @@
 		return -ENODEV;
 	}
 
-	report_ptr = report_ptr->next;
+	list_for_each_entry(hidinput, &hid->inputs, list) {
+		report_ptr = report_ptr->next;
 
-	if (report_ptr == report_list) {
-		hid_err(hid, "required output report is missing\n");
-		return -ENODEV;
-	}
+		if (report_ptr == report_list) {
+			hid_err(hid, "required output report is missing\n");
+			return -ENODEV;
+		}
 
-	report = list_entry(report_ptr, struct hid_report, list);
-	if (report->maxfield < 1) {
-		hid_err(hid, "no fields in the report\n");
-		return -ENODEV;
-	}
+		report = list_entry(report_ptr, 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 < 3) {
-		hid_err(hid, "not enough values in the field\n");
-		return -ENODEV;
-	}
+		if (report->field[0]->report_count < 3) {
+			hid_err(hid, "not enough values in the field\n");
+			return -ENODEV;
+		}
 
-	sjoyff = kzalloc(sizeof(struct sjoyff_device), GFP_KERNEL);
-	if (!sjoyff)
-		return -ENOMEM;
+		sjoyff = kzalloc(sizeof(struct sjoyff_device), GFP_KERNEL);
+		if (!sjoyff)
+			return -ENOMEM;
 
-	dev = hidinput->input;
+		dev = hidinput->input;
 
-	set_bit(FF_RUMBLE, dev->ffbit);
+		set_bit(FF_RUMBLE, dev->ffbit);
 
-	error = input_ff_create_memless(dev, sjoyff, hid_sjoyff_play);
-	if (error) {
-		kfree(sjoyff);
-		return error;
-	}
+		error = input_ff_create_memless(dev, sjoyff, hid_sjoyff_play);
+		if (error) {
+			kfree(sjoyff);
+			return error;
+		}
 
-	sjoyff->report = report;
-	sjoyff->report->field[0]->value[0] = 0x01;
-	sjoyff->report->field[0]->value[1] = 0x00;
-	sjoyff->report->field[0]->value[2] = 0x00;
-	usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
+		sjoyff->report = report;
+		sjoyff->report->field[0]->value[0] = 0x01;
+		sjoyff->report->field[0]->value[1] = 0x00;
+		sjoyff->report->field[0]->value[2] = 0x00;
+		usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
+	}
 
 	hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n");
 
@@ -131,6 +133,8 @@
 {
 	int ret;
 
+	hdev->quirks |= id->driver_data;
+
 	ret = hid_parse(hdev);
 	if (ret) {
 		hid_err(hdev, "parse failed\n");
@@ -151,7 +155,17 @@
 }
 
 static const struct hid_device_id sjoy_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO),
+		.driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET |
+			       HID_QUIRK_SKIP_OUTPUT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO),
+		.driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET |
+			       HID_QUIRK_SKIP_OUTPUT_REPORTS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD),
+		.driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET |
+			       HID_QUIRK_SKIP_OUTPUT_REPORTS },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, sjoy_devices);
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-tmff.c linux-libre-3.2-gnu/drivers/hid/hid-tmff.c
--- linux-libre-3.1-gnu/drivers/hid/hid-tmff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-tmff.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/input.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
+#include <linux/module.h>
 
 #include "hid-ids.h"
 
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-wacom.c linux-libre-3.2-gnu/drivers/hid/hid-wacom.c
--- linux-libre-3.1-gnu/drivers/hid/hid-wacom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-wacom.c	2012-01-04 18:55:44.000000000 -0500
@@ -304,11 +304,51 @@
 	return 1;
 }
 
+static int wacom_input_mapped(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;
+
+	__set_bit(INPUT_PROP_POINTER, input->propbit);
+
+	/* Basics */
+	input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
+
+	__set_bit(REL_WHEEL, input->relbit);
+
+	__set_bit(BTN_TOOL_PEN, input->keybit);
+	__set_bit(BTN_TOUCH, input->keybit);
+	__set_bit(BTN_STYLUS, input->keybit);
+	__set_bit(BTN_STYLUS2, input->keybit);
+	__set_bit(BTN_LEFT, input->keybit);
+	__set_bit(BTN_RIGHT, input->keybit);
+	__set_bit(BTN_MIDDLE, input->keybit);
+
+	/* Pad */
+	input->evbit[0] |= BIT(EV_MSC);
+
+	__set_bit(MSC_SERIAL, input->mscbit);
+
+	__set_bit(BTN_0, input->keybit);
+	__set_bit(BTN_1, input->keybit);
+	__set_bit(BTN_TOOL_FINGER, input->keybit);
+
+	/* Distance, rubber and mouse */
+	__set_bit(BTN_TOOL_RUBBER, input->keybit);
+	__set_bit(BTN_TOOL_MOUSE, input->keybit);
+
+	input_set_abs_params(input, ABS_X, 0, 16704, 4, 0);
+	input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0);
+	input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0);
+	input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0);
+
+	return 0;
+}
+
 static int wacom_probe(struct hid_device *hdev,
 		const struct hid_device_id *id)
 {
-	struct hid_input *hidinput;
-	struct input_dev *input;
 	struct wacom_data *wdata;
 	int ret;
 
@@ -370,42 +410,6 @@
 		goto err_ac;
 	}
 #endif
-	hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
-	input = hidinput->input;
-
-	__set_bit(INPUT_PROP_POINTER, input->propbit);
-
-	/* Basics */
-	input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
-
-	__set_bit(REL_WHEEL, input->relbit);
-
-	__set_bit(BTN_TOOL_PEN, input->keybit);
-	__set_bit(BTN_TOUCH, input->keybit);
-	__set_bit(BTN_STYLUS, input->keybit);
-	__set_bit(BTN_STYLUS2, input->keybit);
-	__set_bit(BTN_LEFT, input->keybit);
-	__set_bit(BTN_RIGHT, input->keybit);
-	__set_bit(BTN_MIDDLE, input->keybit);
-
-	/* Pad */
-	input->evbit[0] |= BIT(EV_MSC);
-
-	__set_bit(MSC_SERIAL, input->mscbit);
-
-	__set_bit(BTN_0, input->keybit);
-	__set_bit(BTN_1, input->keybit);
-	__set_bit(BTN_TOOL_FINGER, input->keybit);
-
-	/* Distance, rubber and mouse */
-	__set_bit(BTN_TOOL_RUBBER, input->keybit);
-	__set_bit(BTN_TOOL_MOUSE, input->keybit);
-
-	input_set_abs_params(input, ABS_X, 0, 16704, 4, 0);
-	input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0);
-	input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0);
-	input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0);
-
 	return 0;
 
 #ifdef CONFIG_HID_WACOM_POWER_SUPPLY
@@ -448,6 +452,7 @@
 	.probe = wacom_probe,
 	.remove = wacom_remove,
 	.raw_event = wacom_raw_event,
+	.input_mapped = wacom_input_mapped,
 };
 
 static int __init wacom_init(void)
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-wiimote.c linux-libre-3.2-gnu/drivers/hid/hid-wiimote.c
--- linux-libre-3.1-gnu/drivers/hid/hid-wiimote.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-wiimote.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,15 +10,18 @@
  * any later version.
  */
 
+#include <linux/completion.h>
 #include <linux/device.h>
 #include <linux/hid.h>
 #include <linux/input.h>
 #include <linux/leds.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/power_supply.h>
 #include <linux/spinlock.h>
 #include "hid-ids.h"
 
-#define WIIMOTE_VERSION "0.1"
+#define WIIMOTE_VERSION "0.2"
 #define WIIMOTE_NAME "Nintendo Wii Remote"
 #define WIIMOTE_BUFSIZE 32
 
@@ -30,12 +33,26 @@
 struct wiimote_state {
 	spinlock_t lock;
 	__u8 flags;
+	__u8 accel_split[2];
+
+	/* synchronous cmd requests */
+	struct mutex sync;
+	struct completion ready;
+	int cmd;
+	__u32 opt;
+
+	/* results of synchronous requests */
+	__u8 cmd_battery;
+	__u8 cmd_err;
 };
 
 struct wiimote_data {
 	struct hid_device *hdev;
 	struct input_dev *input;
 	struct led_classdev *leds[4];
+	struct input_dev *accel;
+	struct input_dev *ir;
+	struct power_supply battery;
 
 	spinlock_t qlock;
 	__u8 head;
@@ -46,23 +63,47 @@
 	struct wiimote_state state;
 };
 
-#define WIIPROTO_FLAG_LED1 0x01
-#define WIIPROTO_FLAG_LED2 0x02
-#define WIIPROTO_FLAG_LED3 0x04
-#define WIIPROTO_FLAG_LED4 0x08
+#define WIIPROTO_FLAG_LED1		0x01
+#define WIIPROTO_FLAG_LED2		0x02
+#define WIIPROTO_FLAG_LED3		0x04
+#define WIIPROTO_FLAG_LED4		0x08
+#define WIIPROTO_FLAG_RUMBLE		0x10
+#define WIIPROTO_FLAG_ACCEL		0x20
+#define WIIPROTO_FLAG_IR_BASIC		0x40
+#define WIIPROTO_FLAG_IR_EXT		0x80
+#define WIIPROTO_FLAG_IR_FULL		0xc0 /* IR_BASIC | IR_EXT */
 #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
 					WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
+#define WIIPROTO_FLAGS_IR (WIIPROTO_FLAG_IR_BASIC | WIIPROTO_FLAG_IR_EXT | \
+							WIIPROTO_FLAG_IR_FULL)
 
 /* return flag for led \num */
 #define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1))
 
 enum wiiproto_reqs {
 	WIIPROTO_REQ_NULL = 0x0,
+	WIIPROTO_REQ_RUMBLE = 0x10,
 	WIIPROTO_REQ_LED = 0x11,
 	WIIPROTO_REQ_DRM = 0x12,
+	WIIPROTO_REQ_IR1 = 0x13,
+	WIIPROTO_REQ_SREQ = 0x15,
+	WIIPROTO_REQ_WMEM = 0x16,
+	WIIPROTO_REQ_RMEM = 0x17,
+	WIIPROTO_REQ_IR2 = 0x1a,
 	WIIPROTO_REQ_STATUS = 0x20,
+	WIIPROTO_REQ_DATA = 0x21,
 	WIIPROTO_REQ_RETURN = 0x22,
 	WIIPROTO_REQ_DRM_K = 0x30,
+	WIIPROTO_REQ_DRM_KA = 0x31,
+	WIIPROTO_REQ_DRM_KE = 0x32,
+	WIIPROTO_REQ_DRM_KAI = 0x33,
+	WIIPROTO_REQ_DRM_KEE = 0x34,
+	WIIPROTO_REQ_DRM_KAE = 0x35,
+	WIIPROTO_REQ_DRM_KIE = 0x36,
+	WIIPROTO_REQ_DRM_KAIE = 0x37,
+	WIIPROTO_REQ_DRM_E = 0x3d,
+	WIIPROTO_REQ_DRM_SKAI1 = 0x3e,
+	WIIPROTO_REQ_DRM_SKAI2 = 0x3f,
 };
 
 enum wiiproto_keys {
@@ -94,6 +135,56 @@
 	BTN_MODE,	/* WIIPROTO_KEY_HOME */
 };
 
+static enum power_supply_property wiimote_battery_props[] = {
+	POWER_SUPPLY_PROP_CAPACITY
+};
+
+/* requires the state.lock spinlock to be held */
+static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd,
+								__u32 opt)
+{
+	return wdata->state.cmd == cmd && wdata->state.opt == opt;
+}
+
+/* requires the state.lock spinlock to be held */
+static inline void wiimote_cmd_complete(struct wiimote_data *wdata)
+{
+	wdata->state.cmd = WIIPROTO_REQ_NULL;
+	complete(&wdata->state.ready);
+}
+
+static inline int wiimote_cmd_acquire(struct wiimote_data *wdata)
+{
+	return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0;
+}
+
+/* requires the state.lock spinlock to be held */
+static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd,
+								__u32 opt)
+{
+	INIT_COMPLETION(wdata->state.ready);
+	wdata->state.cmd = cmd;
+	wdata->state.opt = opt;
+}
+
+static inline void wiimote_cmd_release(struct wiimote_data *wdata)
+{
+	mutex_unlock(&wdata->state.sync);
+}
+
+static inline int wiimote_cmd_wait(struct wiimote_data *wdata)
+{
+	int ret;
+
+	ret = wait_for_completion_interruptible_timeout(&wdata->state.ready, HZ);
+	if (ret < 0)
+		return -ERESTARTSYS;
+	else if (ret == 0)
+		return -EIO;
+	else
+		return 0;
+}
+
 static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer,
 								size_t count)
 {
@@ -172,6 +263,39 @@
 	spin_unlock_irqrestore(&wdata->qlock, flags);
 }
 
+/*
+ * This sets the rumble bit on the given output report if rumble is
+ * currently enabled.
+ * \cmd1 must point to the second byte in the output report => &cmd[1]
+ * This must be called on nearly every output report before passing it
+ * into the output queue!
+ */
+static inline void wiiproto_keep_rumble(struct wiimote_data *wdata, __u8 *cmd1)
+{
+	if (wdata->state.flags & WIIPROTO_FLAG_RUMBLE)
+		*cmd1 |= 0x01;
+}
+
+static void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble)
+{
+	__u8 cmd[2];
+
+	rumble = !!rumble;
+	if (rumble == !!(wdata->state.flags & WIIPROTO_FLAG_RUMBLE))
+		return;
+
+	if (rumble)
+		wdata->state.flags |= WIIPROTO_FLAG_RUMBLE;
+	else
+		wdata->state.flags &= ~WIIPROTO_FLAG_RUMBLE;
+
+	cmd[0] = WIIPROTO_REQ_RUMBLE;
+	cmd[1] = 0;
+
+	wiiproto_keep_rumble(wdata, &cmd[1]);
+	wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
 static void wiiproto_req_leds(struct wiimote_data *wdata, int leds)
 {
 	__u8 cmd[2];
@@ -193,6 +317,7 @@
 	if (leds & WIIPROTO_FLAG_LED4)
 		cmd[1] |= 0x80;
 
+	wiiproto_keep_rumble(wdata, &cmd[1]);
 	wiimote_queue(wdata, cmd, sizeof(cmd));
 }
 
@@ -203,7 +328,23 @@
  */
 static __u8 select_drm(struct wiimote_data *wdata)
 {
-	return WIIPROTO_REQ_DRM_K;
+	__u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR;
+
+	if (ir == WIIPROTO_FLAG_IR_BASIC) {
+		if (wdata->state.flags & WIIPROTO_FLAG_ACCEL)
+			return WIIPROTO_REQ_DRM_KAIE;
+		else
+			return WIIPROTO_REQ_DRM_KIE;
+	} else if (ir == WIIPROTO_FLAG_IR_EXT) {
+		return WIIPROTO_REQ_DRM_KAI;
+	} else if (ir == WIIPROTO_FLAG_IR_FULL) {
+		return WIIPROTO_REQ_DRM_SKAI1;
+	} else {
+		if (wdata->state.flags & WIIPROTO_FLAG_ACCEL)
+			return WIIPROTO_REQ_DRM_KA;
+		else
+			return WIIPROTO_REQ_DRM_K;
+	}
 }
 
 static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm)
@@ -217,9 +358,256 @@
 	cmd[1] = 0;
 	cmd[2] = drm;
 
+	wiiproto_keep_rumble(wdata, &cmd[1]);
+	wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
+static void wiiproto_req_status(struct wiimote_data *wdata)
+{
+	__u8 cmd[2];
+
+	cmd[0] = WIIPROTO_REQ_SREQ;
+	cmd[1] = 0;
+
+	wiiproto_keep_rumble(wdata, &cmd[1]);
+	wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
+static void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel)
+{
+	accel = !!accel;
+	if (accel == !!(wdata->state.flags & WIIPROTO_FLAG_ACCEL))
+		return;
+
+	if (accel)
+		wdata->state.flags |= WIIPROTO_FLAG_ACCEL;
+	else
+		wdata->state.flags &= ~WIIPROTO_FLAG_ACCEL;
+
+	wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+}
+
+static void wiiproto_req_ir1(struct wiimote_data *wdata, __u8 flags)
+{
+	__u8 cmd[2];
+
+	cmd[0] = WIIPROTO_REQ_IR1;
+	cmd[1] = flags;
+
+	wiiproto_keep_rumble(wdata, &cmd[1]);
+	wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
+static void wiiproto_req_ir2(struct wiimote_data *wdata, __u8 flags)
+{
+	__u8 cmd[2];
+
+	cmd[0] = WIIPROTO_REQ_IR2;
+	cmd[1] = flags;
+
+	wiiproto_keep_rumble(wdata, &cmd[1]);
+	wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
+#define wiiproto_req_wreg(wdata, os, buf, sz) \
+			wiiproto_req_wmem((wdata), false, (os), (buf), (sz))
+
+#define wiiproto_req_weeprom(wdata, os, buf, sz) \
+			wiiproto_req_wmem((wdata), true, (os), (buf), (sz))
+
+static void wiiproto_req_wmem(struct wiimote_data *wdata, bool eeprom,
+				__u32 offset, const __u8 *buf, __u8 size)
+{
+	__u8 cmd[22];
+
+	if (size > 16 || size == 0) {
+		hid_warn(wdata->hdev, "Invalid length %d wmem request\n", size);
+		return;
+	}
+
+	memset(cmd, 0, sizeof(cmd));
+	cmd[0] = WIIPROTO_REQ_WMEM;
+	cmd[2] = (offset >> 16) & 0xff;
+	cmd[3] = (offset >> 8) & 0xff;
+	cmd[4] = offset & 0xff;
+	cmd[5] = size;
+	memcpy(&cmd[6], buf, size);
+
+	if (!eeprom)
+		cmd[1] |= 0x04;
+
+	wiiproto_keep_rumble(wdata, &cmd[1]);
 	wiimote_queue(wdata, cmd, sizeof(cmd));
 }
 
+/* requries the cmd-mutex to be held */
+static int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset,
+						const __u8 *wmem, __u8 size)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wiimote_cmd_set(wdata, WIIPROTO_REQ_WMEM, 0);
+	wiiproto_req_wreg(wdata, offset, wmem, size);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	ret = wiimote_cmd_wait(wdata);
+	if (!ret && wdata->state.cmd_err)
+		ret = -EIO;
+
+	return ret;
+}
+
+static int wiimote_battery_get_property(struct power_supply *psy,
+						enum power_supply_property psp,
+						union power_supply_propval *val)
+{
+	struct wiimote_data *wdata = container_of(psy,
+						struct wiimote_data, battery);
+	int ret = 0, state;
+	unsigned long flags;
+
+	ret = wiimote_cmd_acquire(wdata);
+	if (ret)
+		return ret;
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wiimote_cmd_set(wdata, WIIPROTO_REQ_SREQ, 0);
+	wiiproto_req_status(wdata);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	ret = wiimote_cmd_wait(wdata);
+	state = wdata->state.cmd_battery;
+	wiimote_cmd_release(wdata);
+
+	if (ret)
+		return ret;
+
+	switch (psp) {
+		case POWER_SUPPLY_PROP_CAPACITY:
+			val->intval = state * 100 / 255;
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+	}
+
+	return ret;
+}
+
+static int wiimote_init_ir(struct wiimote_data *wdata, __u16 mode)
+{
+	int ret;
+	unsigned long flags;
+	__u8 format = 0;
+	static const __u8 data_enable[] = { 0x01 };
+	static const __u8 data_sens1[] = { 0x02, 0x00, 0x00, 0x71, 0x01,
+						0x00, 0xaa, 0x00, 0x64 };
+	static const __u8 data_sens2[] = { 0x63, 0x03 };
+	static const __u8 data_fin[] = { 0x08 };
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+
+	if (mode == (wdata->state.flags & WIIPROTO_FLAGS_IR)) {
+		spin_unlock_irqrestore(&wdata->state.lock, flags);
+		return 0;
+	}
+
+	if (mode == 0) {
+		wdata->state.flags &= ~WIIPROTO_FLAGS_IR;
+		wiiproto_req_ir1(wdata, 0);
+		wiiproto_req_ir2(wdata, 0);
+		wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+		spin_unlock_irqrestore(&wdata->state.lock, flags);
+		return 0;
+	}
+
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	ret = wiimote_cmd_acquire(wdata);
+	if (ret)
+		return ret;
+
+	/* send PIXEL CLOCK ENABLE cmd first */
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wiimote_cmd_set(wdata, WIIPROTO_REQ_IR1, 0);
+	wiiproto_req_ir1(wdata, 0x06);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	ret = wiimote_cmd_wait(wdata);
+	if (ret)
+		goto unlock;
+	if (wdata->state.cmd_err) {
+		ret = -EIO;
+		goto unlock;
+	}
+
+	/* enable IR LOGIC */
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wiimote_cmd_set(wdata, WIIPROTO_REQ_IR2, 0);
+	wiiproto_req_ir2(wdata, 0x06);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	ret = wiimote_cmd_wait(wdata);
+	if (ret)
+		goto unlock;
+	if (wdata->state.cmd_err) {
+		ret = -EIO;
+		goto unlock;
+	}
+
+	/* enable IR cam but do not make it send data, yet */
+	ret = wiimote_cmd_write(wdata, 0xb00030, data_enable,
+							sizeof(data_enable));
+	if (ret)
+		goto unlock;
+
+	/* write first sensitivity block */
+	ret = wiimote_cmd_write(wdata, 0xb00000, data_sens1,
+							sizeof(data_sens1));
+	if (ret)
+		goto unlock;
+
+	/* write second sensitivity block */
+	ret = wiimote_cmd_write(wdata, 0xb0001a, data_sens2,
+							sizeof(data_sens2));
+	if (ret)
+		goto unlock;
+
+	/* put IR cam into desired state */
+	switch (mode) {
+		case WIIPROTO_FLAG_IR_FULL:
+			format = 5;
+			break;
+		case WIIPROTO_FLAG_IR_EXT:
+			format = 3;
+			break;
+		case WIIPROTO_FLAG_IR_BASIC:
+			format = 1;
+			break;
+	}
+	ret = wiimote_cmd_write(wdata, 0xb00033, &format, sizeof(format));
+	if (ret)
+		goto unlock;
+
+	/* make IR cam send data */
+	ret = wiimote_cmd_write(wdata, 0xb00030, data_fin, sizeof(data_fin));
+	if (ret)
+		goto unlock;
+
+	/* request new DRM mode compatible to IR mode */
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wdata->state.flags &= ~WIIPROTO_FLAGS_IR;
+	wdata->state.flags |= mode & WIIPROTO_FLAGS_IR;
+	wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+unlock:
+	wiimote_cmd_release(wdata);
+	return ret;
+}
+
 static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev)
 {
 	struct wiimote_data *wdata;
@@ -268,9 +656,28 @@
 	}
 }
 
-static int wiimote_input_event(struct input_dev *dev, unsigned int type,
-						unsigned int code, int value)
+static int wiimote_ff_play(struct input_dev *dev, void *data,
+							struct ff_effect *eff)
 {
+	struct wiimote_data *wdata = input_get_drvdata(dev);
+	__u8 value;
+	unsigned long flags;
+
+	/*
+	 * The wiimote supports only a single rumble motor so if any magnitude
+	 * is set to non-zero then we start the rumble motor. If both are set to
+	 * zero, we stop the rumble motor.
+	 */
+
+	if (eff->u.rumble.strong_magnitude || eff->u.rumble.weak_magnitude)
+		value = 1;
+	else
+		value = 0;
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wiiproto_req_rumble(wdata, value);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
 	return 0;
 }
 
@@ -288,6 +695,61 @@
 	hid_hw_close(wdata->hdev);
 }
 
+static int wiimote_accel_open(struct input_dev *dev)
+{
+	struct wiimote_data *wdata = input_get_drvdata(dev);
+	int ret;
+	unsigned long flags;
+
+	ret = hid_hw_open(wdata->hdev);
+	if (ret)
+		return ret;
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wiiproto_req_accel(wdata, true);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	return 0;
+}
+
+static void wiimote_accel_close(struct input_dev *dev)
+{
+	struct wiimote_data *wdata = input_get_drvdata(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+	wiiproto_req_accel(wdata, false);
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	hid_hw_close(wdata->hdev);
+}
+
+static int wiimote_ir_open(struct input_dev *dev)
+{
+	struct wiimote_data *wdata = input_get_drvdata(dev);
+	int ret;
+
+	ret = hid_hw_open(wdata->hdev);
+	if (ret)
+		return ret;
+
+	ret = wiimote_init_ir(wdata, WIIPROTO_FLAG_IR_BASIC);
+	if (ret) {
+		hid_hw_close(wdata->hdev);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void wiimote_ir_close(struct input_dev *dev)
+{
+	struct wiimote_data *wdata = input_get_drvdata(dev);
+
+	wiimote_init_ir(wdata, 0);
+	hid_hw_close(wdata->hdev);
+}
+
 static void handler_keys(struct wiimote_data *wdata, const __u8 *payload)
 {
 	input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT],
@@ -315,12 +777,100 @@
 	input_sync(wdata->input);
 }
 
+static void handler_accel(struct wiimote_data *wdata, const __u8 *payload)
+{
+	__u16 x, y, z;
+
+	if (!(wdata->state.flags & WIIPROTO_FLAG_ACCEL))
+		return;
+
+	/*
+	 * payload is: BB BB XX YY ZZ
+	 * Accelerometer data is encoded into 3 10bit values. XX, YY and ZZ
+	 * contain the upper 8 bits of each value. The lower 2 bits are
+	 * contained in the buttons data BB BB.
+	 * Bits 6 and 7 of the first buttons byte BB is the lower 2 bits of the
+	 * X accel value. Bit 5 of the second buttons byte is the 2nd bit of Y
+	 * accel value and bit 6 is the second bit of the Z value.
+	 * The first bit of Y and Z values is not available and always set to 0.
+	 * 0x200 is returned on no movement.
+	 */
+
+	x = payload[2] << 2;
+	y = payload[3] << 2;
+	z = payload[4] << 2;
+
+	x |= (payload[0] >> 5) & 0x3;
+	y |= (payload[1] >> 4) & 0x2;
+	z |= (payload[1] >> 5) & 0x2;
+
+	input_report_abs(wdata->accel, ABS_RX, x - 0x200);
+	input_report_abs(wdata->accel, ABS_RY, y - 0x200);
+	input_report_abs(wdata->accel, ABS_RZ, z - 0x200);
+	input_sync(wdata->accel);
+}
+
+#define ir_to_input0(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
+							ABS_HAT0X, ABS_HAT0Y)
+#define ir_to_input1(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
+							ABS_HAT1X, ABS_HAT1Y)
+#define ir_to_input2(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
+							ABS_HAT2X, ABS_HAT2Y)
+#define ir_to_input3(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
+							ABS_HAT3X, ABS_HAT3Y)
+
+static void __ir_to_input(struct wiimote_data *wdata, const __u8 *ir,
+						bool packed, __u8 xid, __u8 yid)
+{
+	__u16 x, y;
+
+	if (!(wdata->state.flags & WIIPROTO_FLAGS_IR))
+		return;
+
+	/*
+	 * Basic IR data is encoded into 3 bytes. The first two bytes are the
+	 * upper 8 bit of the X/Y data, the 3rd byte contains the lower 2 bits
+	 * of both.
+	 * If data is packed, then the 3rd byte is put first and slightly
+	 * reordered. This allows to interleave packed and non-packed data to
+	 * have two IR sets in 5 bytes instead of 6.
+	 * The resulting 10bit X/Y values are passed to the ABS_HATXY input dev.
+	 */
+
+	if (packed) {
+		x = ir[1] << 2;
+		y = ir[2] << 2;
+
+		x |= ir[0] & 0x3;
+		y |= (ir[0] >> 2) & 0x3;
+	} else {
+		x = ir[0] << 2;
+		y = ir[1] << 2;
+
+		x |= (ir[2] >> 4) & 0x3;
+		y |= (ir[2] >> 6) & 0x3;
+	}
+
+	input_report_abs(wdata->ir, xid, x);
+	input_report_abs(wdata->ir, yid, y);
+}
+
 static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
 {
 	handler_keys(wdata, payload);
 
 	/* on status reports the drm is reset so we need to resend the drm */
 	wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+
+	if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) {
+		wdata->state.cmd_battery = payload[5];
+		wiimote_cmd_complete(wdata);
+	}
+}
+
+static void handler_data(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
 }
 
 static void handler_return(struct wiimote_data *wdata, const __u8 *payload)
@@ -330,9 +880,105 @@
 
 	handler_keys(wdata, payload);
 
-	if (err)
+	if (wiimote_cmd_pending(wdata, cmd, 0)) {
+		wdata->state.cmd_err = err;
+		wiimote_cmd_complete(wdata);
+	} else if (err) {
 		hid_warn(wdata->hdev, "Remote error %hhu on req %hhu\n", err,
 									cmd);
+	}
+}
+
+static void handler_drm_KA(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+	handler_accel(wdata, payload);
+}
+
+static void handler_drm_KE(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+}
+
+static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+	handler_accel(wdata, payload);
+	ir_to_input0(wdata, &payload[5], false);
+	ir_to_input1(wdata, &payload[8], false);
+	ir_to_input2(wdata, &payload[11], false);
+	ir_to_input3(wdata, &payload[14], false);
+	input_sync(wdata->ir);
+}
+
+static void handler_drm_KEE(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+}
+
+static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+	ir_to_input0(wdata, &payload[2], false);
+	ir_to_input1(wdata, &payload[4], true);
+	ir_to_input2(wdata, &payload[7], false);
+	ir_to_input3(wdata, &payload[9], true);
+	input_sync(wdata->ir);
+}
+
+static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+	handler_accel(wdata, payload);
+}
+
+static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+	handler_accel(wdata, payload);
+	ir_to_input0(wdata, &payload[5], false);
+	ir_to_input1(wdata, &payload[7], true);
+	ir_to_input2(wdata, &payload[10], false);
+	ir_to_input3(wdata, &payload[12], true);
+	input_sync(wdata->ir);
+}
+
+static void handler_drm_E(struct wiimote_data *wdata, const __u8 *payload)
+{
+}
+
+static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload)
+{
+	handler_keys(wdata, payload);
+
+	wdata->state.accel_split[0] = payload[2];
+	wdata->state.accel_split[1] = (payload[0] >> 1) & (0x10 | 0x20);
+	wdata->state.accel_split[1] |= (payload[1] << 1) & (0x40 | 0x80);
+
+	ir_to_input0(wdata, &payload[3], false);
+	ir_to_input1(wdata, &payload[12], false);
+	input_sync(wdata->ir);
+}
+
+static void handler_drm_SKAI2(struct wiimote_data *wdata, const __u8 *payload)
+{
+	__u8 buf[5];
+
+	handler_keys(wdata, payload);
+
+	wdata->state.accel_split[1] |= (payload[0] >> 5) & (0x01 | 0x02);
+	wdata->state.accel_split[1] |= (payload[1] >> 3) & (0x04 | 0x08);
+
+	buf[0] = 0;
+	buf[1] = 0;
+	buf[2] = wdata->state.accel_split[0];
+	buf[3] = payload[2];
+	buf[4] = wdata->state.accel_split[1];
+	handler_accel(wdata, buf);
+
+	ir_to_input2(wdata, &payload[3], false);
+	ir_to_input3(wdata, &payload[12], false);
+	input_sync(wdata->ir);
 }
 
 struct wiiproto_handler {
@@ -343,8 +989,19 @@
 
 static struct wiiproto_handler handlers[] = {
 	{ .id = WIIPROTO_REQ_STATUS, .size = 6, .func = handler_status },
+	{ .id = WIIPROTO_REQ_DATA, .size = 21, .func = handler_data },
 	{ .id = WIIPROTO_REQ_RETURN, .size = 4, .func = handler_return },
 	{ .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys },
+	{ .id = WIIPROTO_REQ_DRM_KA, .size = 5, .func = handler_drm_KA },
+	{ .id = WIIPROTO_REQ_DRM_KE, .size = 10, .func = handler_drm_KE },
+	{ .id = WIIPROTO_REQ_DRM_KAI, .size = 17, .func = handler_drm_KAI },
+	{ .id = WIIPROTO_REQ_DRM_KEE, .size = 21, .func = handler_drm_KEE },
+	{ .id = WIIPROTO_REQ_DRM_KAE, .size = 21, .func = handler_drm_KAE },
+	{ .id = WIIPROTO_REQ_DRM_KIE, .size = 21, .func = handler_drm_KIE },
+	{ .id = WIIPROTO_REQ_DRM_KAIE, .size = 21, .func = handler_drm_KAIE },
+	{ .id = WIIPROTO_REQ_DRM_E, .size = 21, .func = handler_drm_E },
+	{ .id = WIIPROTO_REQ_DRM_SKAI1, .size = 21, .func = handler_drm_SKAI1 },
+	{ .id = WIIPROTO_REQ_DRM_SKAI2, .size = 21, .func = handler_drm_SKAI2 },
 	{ .id = 0 }
 };
 
@@ -355,6 +1012,7 @@
 	struct wiiproto_handler *h;
 	int i;
 	unsigned long flags;
+	bool handled = false;
 
 	if (size < 1)
 		return -EINVAL;
@@ -363,10 +1021,16 @@
 
 	for (i = 0; handlers[i].id; ++i) {
 		h = &handlers[i];
-		if (h->id == raw_data[0] && h->size < size)
+		if (h->id == raw_data[0] && h->size < size) {
 			h->func(wdata, &raw_data[1]);
+			handled = true;
+		}
 	}
 
+	if (!handled)
+		hid_warn(hdev, "Unhandled report %hhu size %d\n", raw_data[0],
+									size);
+
 	spin_unlock_irqrestore(&wdata->state.lock, flags);
 
 	return 0;
@@ -434,16 +1098,13 @@
 		return NULL;
 
 	wdata->input = input_allocate_device();
-	if (!wdata->input) {
-		kfree(wdata);
-		return NULL;
-	}
+	if (!wdata->input)
+		goto err;
 
 	wdata->hdev = hdev;
 	hid_set_drvdata(hdev, wdata);
 
 	input_set_drvdata(wdata->input, wdata);
-	wdata->input->event = wiimote_input_event;
 	wdata->input->open = wiimote_input_open;
 	wdata->input->close = wiimote_input_close;
 	wdata->input->dev.parent = &wdata->hdev->dev;
@@ -457,18 +1118,89 @@
 	for (i = 0; i < WIIPROTO_KEY_COUNT; ++i)
 		set_bit(wiiproto_keymap[i], wdata->input->keybit);
 
+	set_bit(FF_RUMBLE, wdata->input->ffbit);
+	if (input_ff_create_memless(wdata->input, NULL, wiimote_ff_play))
+		goto err_input;
+
+	wdata->accel = input_allocate_device();
+	if (!wdata->accel)
+		goto err_input;
+
+	input_set_drvdata(wdata->accel, wdata);
+	wdata->accel->open = wiimote_accel_open;
+	wdata->accel->close = wiimote_accel_close;
+	wdata->accel->dev.parent = &wdata->hdev->dev;
+	wdata->accel->id.bustype = wdata->hdev->bus;
+	wdata->accel->id.vendor = wdata->hdev->vendor;
+	wdata->accel->id.product = wdata->hdev->product;
+	wdata->accel->id.version = wdata->hdev->version;
+	wdata->accel->name = WIIMOTE_NAME " Accelerometer";
+
+	set_bit(EV_ABS, wdata->accel->evbit);
+	set_bit(ABS_RX, wdata->accel->absbit);
+	set_bit(ABS_RY, wdata->accel->absbit);
+	set_bit(ABS_RZ, wdata->accel->absbit);
+	input_set_abs_params(wdata->accel, ABS_RX, -500, 500, 2, 4);
+	input_set_abs_params(wdata->accel, ABS_RY, -500, 500, 2, 4);
+	input_set_abs_params(wdata->accel, ABS_RZ, -500, 500, 2, 4);
+
+	wdata->ir = input_allocate_device();
+	if (!wdata->ir)
+		goto err_ir;
+
+	input_set_drvdata(wdata->ir, wdata);
+	wdata->ir->open = wiimote_ir_open;
+	wdata->ir->close = wiimote_ir_close;
+	wdata->ir->dev.parent = &wdata->hdev->dev;
+	wdata->ir->id.bustype = wdata->hdev->bus;
+	wdata->ir->id.vendor = wdata->hdev->vendor;
+	wdata->ir->id.product = wdata->hdev->product;
+	wdata->ir->id.version = wdata->hdev->version;
+	wdata->ir->name = WIIMOTE_NAME " IR";
+
+	set_bit(EV_ABS, wdata->ir->evbit);
+	set_bit(ABS_HAT0X, wdata->ir->absbit);
+	set_bit(ABS_HAT0Y, wdata->ir->absbit);
+	set_bit(ABS_HAT1X, wdata->ir->absbit);
+	set_bit(ABS_HAT1Y, wdata->ir->absbit);
+	set_bit(ABS_HAT2X, wdata->ir->absbit);
+	set_bit(ABS_HAT2Y, wdata->ir->absbit);
+	set_bit(ABS_HAT3X, wdata->ir->absbit);
+	set_bit(ABS_HAT3Y, wdata->ir->absbit);
+	input_set_abs_params(wdata->ir, ABS_HAT0X, 0, 1023, 2, 4);
+	input_set_abs_params(wdata->ir, ABS_HAT0Y, 0, 767, 2, 4);
+	input_set_abs_params(wdata->ir, ABS_HAT1X, 0, 1023, 2, 4);
+	input_set_abs_params(wdata->ir, ABS_HAT1Y, 0, 767, 2, 4);
+	input_set_abs_params(wdata->ir, ABS_HAT2X, 0, 1023, 2, 4);
+	input_set_abs_params(wdata->ir, ABS_HAT2Y, 0, 767, 2, 4);
+	input_set_abs_params(wdata->ir, ABS_HAT3X, 0, 1023, 2, 4);
+	input_set_abs_params(wdata->ir, ABS_HAT3Y, 0, 767, 2, 4);
+
 	spin_lock_init(&wdata->qlock);
 	INIT_WORK(&wdata->worker, wiimote_worker);
 
 	spin_lock_init(&wdata->state.lock);
+	init_completion(&wdata->state.ready);
+	mutex_init(&wdata->state.sync);
 
 	return wdata;
+
+err_ir:
+	input_free_device(wdata->accel);
+err_input:
+	input_free_device(wdata->input);
+err:
+	kfree(wdata);
+	return NULL;
 }
 
 static void wiimote_destroy(struct wiimote_data *wdata)
 {
 	wiimote_leds_destroy(wdata);
 
+	power_supply_unregister(&wdata->battery);
+	input_unregister_device(wdata->accel);
+	input_unregister_device(wdata->ir);
 	input_unregister_device(wdata->input);
 	cancel_work_sync(&wdata->worker);
 	hid_hw_stop(wdata->hdev);
@@ -500,12 +1232,37 @@
 		goto err;
 	}
 
-	ret = input_register_device(wdata->input);
+	ret = input_register_device(wdata->accel);
 	if (ret) {
 		hid_err(hdev, "Cannot register input device\n");
 		goto err_stop;
 	}
 
+	ret = input_register_device(wdata->ir);
+	if (ret) {
+		hid_err(hdev, "Cannot register input device\n");
+		goto err_ir;
+	}
+
+	ret = input_register_device(wdata->input);
+	if (ret) {
+		hid_err(hdev, "Cannot register input device\n");
+		goto err_input;
+	}
+
+	wdata->battery.properties = wiimote_battery_props;
+	wdata->battery.num_properties = ARRAY_SIZE(wiimote_battery_props);
+	wdata->battery.get_property = wiimote_battery_get_property;
+	wdata->battery.name = "wiimote_battery";
+	wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+	wdata->battery.use_for_apm = 0;
+
+	ret = power_supply_register(&wdata->hdev->dev, &wdata->battery);
+	if (ret) {
+		hid_err(hdev, "Cannot register battery device\n");
+		goto err_battery;
+	}
+
 	ret = wiimote_leds_create(wdata);
 	if (ret)
 		goto err_free;
@@ -523,9 +1280,20 @@
 	wiimote_destroy(wdata);
 	return ret;
 
+err_battery:
+	input_unregister_device(wdata->input);
+	wdata->input = NULL;
+err_input:
+	input_unregister_device(wdata->ir);
+	wdata->ir = NULL;
+err_ir:
+	input_unregister_device(wdata->accel);
+	wdata->accel = NULL;
 err_stop:
 	hid_hw_stop(hdev);
 err:
+	input_free_device(wdata->ir);
+	input_free_device(wdata->accel);
 	input_free_device(wdata->input);
 	kfree(wdata);
 	return ret;
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-zpff.c linux-libre-3.2-gnu/drivers/hid/hid-zpff.c
--- linux-libre-3.1-gnu/drivers/hid/hid-zpff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-zpff.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/input.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
+#include <linux/module.h>
 
 #include "hid-ids.h"
 
diff -druN linux-libre-3.1-gnu/drivers/hid/hid-zydacron.c linux-libre-3.2-gnu/drivers/hid/hid-zydacron.c
--- linux-libre-3.1-gnu/drivers/hid/hid-zydacron.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/hid-zydacron.c	2012-01-04 18:55:44.000000000 -0500
@@ -201,9 +201,7 @@
 	struct zc_device *zc = hid_get_drvdata(hdev);
 
 	hid_hw_stop(hdev);
-
-	if (NULL != zc)
-		kfree(zc);
+	kfree(zc);
 }
 
 static const struct hid_device_id zc_devices[] = {
diff -druN linux-libre-3.1-gnu/drivers/hid/Kconfig linux-libre-3.2-gnu/drivers/hid/Kconfig
--- linux-libre-3.1-gnu/drivers/hid/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -69,7 +69,7 @@
 	Say Y here if you want to enable support for ACRUX game controllers.
 
 config HID_ACRUX_FF
-	tristate "ACRUX force feedback support"
+	bool "ACRUX force feedback support"
 	depends on HID_ACRUX
 	select INPUT_FF_MEMLESS
 	---help---
@@ -245,6 +245,15 @@
 	---help---
 	Support for Logitech devices that are not fully compliant with HID standard.
 
+config HID_LOGITECH_DJ
+	tristate "Logitech Unifying receivers full support"
+	depends on HID_LOGITECH
+	default m
+	---help---
+	Say Y if you want support for Logitech Unifying receivers and devices.
+	Unifying receivers are capable of pairing up to 6 Logitech compliant
+	devices to the same receiver.
+
 config LOGITECH_FF
 	bool "Logitech force feedback support"
 	depends on HID_LOGITECH
@@ -278,13 +287,21 @@
 	  Say Y here if you want to enable force feedback support for Logitech
 	  Flight System G940 devices.
 
-config LOGIWII_FF
-	bool "Logitech Speed Force Wireless force feedback support"
+config LOGIWHEELS_FF
+	bool "Logitech wheels configuration and force feedback support"
 	depends on HID_LOGITECH
 	select INPUT_FF_MEMLESS
+	default LOGITECH_FF
 	help
-	  Say Y here if you want to enable force feedback support for Logitech
-	  Speed Force Wireless (Wii) devices.
+	  Say Y here if you want to enable force feedback and range setting
+	  support for following Logitech wheels:
+	  - Logitech Driving Force
+	  - Logitech Driving Force Pro
+	  - Logitech Driving Force GT
+	  - Logitech G25
+	  - Logitech G27
+	  - Logitech MOMO/MOMO 2
+	  - Logitech Formula Force EX
 
 config HID_MAGICMOUSE
 	tristate "Apple MagicMouse multi-touch support"
@@ -328,6 +345,7 @@
 	  - Hanvon dual touch panels
 	  - Ilitek dual touch panels
 	  - IrTouch Infrared USB panels
+	  - LG Display panels (Dell ST2220Tc)
 	  - Lumio CrystalTouch panels
 	  - MosArt dual-touch panels
 	  - PenMount dual touch panels
@@ -441,6 +459,13 @@
 	---help---
 	  Provide access to PicoLCD's GPO pins via leds class.
 
+config HID_PRIMAX
+	tristate "Primax non-fully HID-compliant devices"
+	depends on USB_HID
+	---help---
+	Support for Primax devices that are not fully compliant with the
+	HID standard.
+
 config HID_QUANTA
 	tristate "Quanta Optical Touch panels"
 	depends on USB_HID
@@ -539,7 +564,11 @@
 	tristate "SmartJoy PLUS PS2/USB adapter support"
 	depends on USB_HID
 	---help---
-	Support for SmartJoy PLUS PS2/USB adapter.
+	Support for SmartJoy PLUS PS2/USB adapter, Super Dual Box,
+	Super Joy Box 3 Pro, Super Dual Box Pro, and Super Joy Box 5 Pro.
+
+	Note that DDR (Dance Dance Revolution) mode is not supported, nor
+	is pressure sensitive buttons on the pro models.
 
 config SMARTJOYPLUS_FF
 	bool "SmartJoy PLUS PS2/USB adapter force feedback support"
@@ -590,6 +619,7 @@
 	tristate "Nintendo Wii Remote support"
 	depends on BT_HIDP
 	depends on LEDS_CLASS
+	select POWER_SUPPLY
 	---help---
 	Support for the Nintendo Wii Remote bluetooth device.
 
diff -druN linux-libre-3.1-gnu/drivers/hid/Makefile linux-libre-3.2-gnu/drivers/hid/Makefile
--- linux-libre-3.1-gnu/drivers/hid/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
 ifdef CONFIG_LOGIG940_FF
 	hid-logitech-y	+= hid-lg3ff.o
 endif
-ifdef CONFIG_LOGIWII_FF
+ifdef CONFIG_LOGIWHEELS_FF
 	hid-logitech-y	+= hid-lg4ff.o
 endif
 
@@ -43,6 +43,7 @@
 obj-$(CONFIG_HID_KYE)		+= hid-kye.o
 obj-$(CONFIG_HID_LCPOWER)       += hid-lcpower.o
 obj-$(CONFIG_HID_LOGITECH)	+= hid-logitech.o
+obj-$(CONFIG_HID_LOGITECH_DJ)	+= hid-logitech-dj.o
 obj-$(CONFIG_HID_MAGICMOUSE)    += hid-magicmouse.o
 obj-$(CONFIG_HID_MICROSOFT)	+= hid-microsoft.o
 obj-$(CONFIG_HID_MONTEREY)	+= hid-monterey.o
@@ -54,6 +55,7 @@
 obj-$(CONFIG_HID_PANTHERLORD)	+= hid-pl.o
 obj-$(CONFIG_HID_PETALYNX)	+= hid-petalynx.o
 obj-$(CONFIG_HID_PICOLCD)	+= hid-picolcd.o
+obj-$(CONFIG_HID_PRIMAX)	+= hid-primax.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
diff -druN linux-libre-3.1-gnu/drivers/hid/usbhid/hid-core.c linux-libre-3.2-gnu/drivers/hid/usbhid/hid-core.c
--- linux-libre-3.1-gnu/drivers/hid/usbhid/hid-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/usbhid/hid-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -1270,7 +1270,7 @@
 
 static void hid_cease_io(struct usbhid_device *usbhid)
 {
-	del_timer(&usbhid->io_retry);
+	del_timer_sync(&usbhid->io_retry);
 	usb_kill_urb(usbhid->urbin);
 	usb_kill_urb(usbhid->urbctrl);
 	usb_kill_urb(usbhid->urbout);
@@ -1332,7 +1332,7 @@
 	struct usbhid_device *usbhid = hid->driver_data;
 	int status;
 
-	if (message.event & PM_EVENT_AUTO) {
+	if (PMSG_IS_AUTO(message)) {
 		spin_lock_irq(&usbhid->lock);	/* Sync with error handler */
 		if (!test_bit(HID_RESET_PENDING, &usbhid->iofl)
 		    && !test_bit(HID_CLEAR_HALT, &usbhid->iofl)
@@ -1367,7 +1367,7 @@
 			return -EIO;
 	}
 
-	if (!ignoreled && (message.event & PM_EVENT_AUTO)) {
+	if (!ignoreled && PMSG_IS_AUTO(message)) {
 		spin_lock_irq(&usbhid->lock);
 		if (test_bit(HID_LED_ON, &usbhid->iofl)) {
 			spin_unlock_irq(&usbhid->lock);
@@ -1380,8 +1380,7 @@
 	hid_cancel_delayed_stuff(usbhid);
 	hid_cease_io(usbhid);
 
-	if ((message.event & PM_EVENT_AUTO) &&
-			test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) {
+	if (PMSG_IS_AUTO(message) && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) {
 		/* lost race against keypresses */
 		status = hid_start_in(hid);
 		if (status < 0)
diff -druN linux-libre-3.1-gnu/drivers/hid/usbhid/hiddev.c linux-libre-3.2-gnu/drivers/hid/usbhid/hiddev.c
--- linux-libre-3.1-gnu/drivers/hid/usbhid/hiddev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/usbhid/hiddev.c	2012-01-04 18:55:44.000000000 -0500
@@ -641,6 +641,8 @@
 			struct usb_device *dev = hid_to_usb_dev(hid);
 			struct usbhid_device *usbhid = hid->driver_data;
 
+			memset(&dinfo, 0, sizeof(dinfo));
+
 			dinfo.bustype = BUS_USB;
 			dinfo.busnum = dev->bus->busnum;
 			dinfo.devnum = dev->devnum;
diff -druN linux-libre-3.1-gnu/drivers/hid/usbhid/hid-quirks.c linux-libre-3.2-gnu/drivers/hid/usbhid/hid-quirks.c
--- linux-libre-3.1-gnu/drivers/hid/usbhid/hid-quirks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hid/usbhid/hid-quirks.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
  */
 
 #include <linux/hid.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 
 #include "../hid-ids.h"
@@ -80,10 +81,8 @@
 	{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH, HID_QUIRK_MULTI_INPUT },
-	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 
-	{ USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 
 	{ USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE },
diff -druN linux-libre-3.1-gnu/drivers/hv/channel.c linux-libre-3.2-gnu/drivers/hv/channel.c
--- linux-libre-3.1-gnu/drivers/hv/channel.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hv/channel.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,815 @@
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/hyperv.h>
+
+#include "hyperv_vmbus.h"
+
+#define NUM_PAGES_SPANNED(addr, len) \
+((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))
+
+/* Internal routines */
+static int create_gpadl_header(
+	void *kbuffer,	/* must be phys and virt contiguous */
+	u32 size,	/* page-size multiple */
+	struct vmbus_channel_msginfo **msginfo,
+	u32 *messagecount);
+static void vmbus_setevent(struct vmbus_channel *channel);
+
+/*
+ * vmbus_setevent- Trigger an event notification on the specified
+ * channel.
+ */
+static void vmbus_setevent(struct vmbus_channel *channel)
+{
+	struct hv_monitor_page *monitorpage;
+
+	if (channel->offermsg.monitor_allocated) {
+		/* Each u32 represents 32 channels */
+		sync_set_bit(channel->offermsg.child_relid & 31,
+			(unsigned long *) vmbus_connection.send_int_page +
+			(channel->offermsg.child_relid >> 5));
+
+		monitorpage = vmbus_connection.monitor_pages;
+		monitorpage++; /* Get the child to parent monitor page */
+
+		sync_set_bit(channel->monitor_bit,
+			(unsigned long *)&monitorpage->trigger_group
+					[channel->monitor_grp].pending);
+
+	} else {
+		vmbus_set_event(channel->offermsg.child_relid);
+	}
+}
+
+/*
+ * vmbus_get_debug_info -Retrieve various channel debug info
+ */
+void vmbus_get_debug_info(struct vmbus_channel *channel,
+			      struct vmbus_channel_debug_info *debuginfo)
+{
+	struct hv_monitor_page *monitorpage;
+	u8 monitor_group = (u8)channel->offermsg.monitorid / 32;
+	u8 monitor_offset = (u8)channel->offermsg.monitorid % 32;
+
+	debuginfo->relid = channel->offermsg.child_relid;
+	debuginfo->state = channel->state;
+	memcpy(&debuginfo->interfacetype,
+	       &channel->offermsg.offer.if_type, sizeof(uuid_le));
+	memcpy(&debuginfo->interface_instance,
+	       &channel->offermsg.offer.if_instance,
+	       sizeof(uuid_le));
+
+	monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages;
+
+	debuginfo->monitorid = channel->offermsg.monitorid;
+
+	debuginfo->servermonitor_pending =
+			monitorpage->trigger_group[monitor_group].pending;
+	debuginfo->servermonitor_latency =
+			monitorpage->latency[monitor_group][monitor_offset];
+	debuginfo->servermonitor_connectionid =
+			monitorpage->parameter[monitor_group]
+					[monitor_offset].connectionid.u.id;
+
+	monitorpage++;
+
+	debuginfo->clientmonitor_pending =
+			monitorpage->trigger_group[monitor_group].pending;
+	debuginfo->clientmonitor_latency =
+			monitorpage->latency[monitor_group][monitor_offset];
+	debuginfo->clientmonitor_connectionid =
+			monitorpage->parameter[monitor_group]
+					[monitor_offset].connectionid.u.id;
+
+	hv_ringbuffer_get_debuginfo(&channel->inbound, &debuginfo->inbound);
+	hv_ringbuffer_get_debuginfo(&channel->outbound, &debuginfo->outbound);
+}
+
+/*
+ * vmbus_open - Open the specified channel.
+ */
+int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
+		     u32 recv_ringbuffer_size, void *userdata, u32 userdatalen,
+		     void (*onchannelcallback)(void *context), void *context)
+{
+	struct vmbus_channel_open_channel *open_msg;
+	struct vmbus_channel_msginfo *open_info = NULL;
+	void *in, *out;
+	unsigned long flags;
+	int ret, t, err = 0;
+
+	newchannel->onchannel_callback = onchannelcallback;
+	newchannel->channel_callback_context = context;
+
+	/* Allocate the ring buffer */
+	out = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
+		get_order(send_ringbuffer_size + recv_ringbuffer_size));
+
+	if (!out)
+		return -ENOMEM;
+
+
+	in = (void *)((unsigned long)out + send_ringbuffer_size);
+
+	newchannel->ringbuffer_pages = out;
+	newchannel->ringbuffer_pagecount = (send_ringbuffer_size +
+					   recv_ringbuffer_size) >> PAGE_SHIFT;
+
+	ret = hv_ringbuffer_init(
+		&newchannel->outbound, out, send_ringbuffer_size);
+
+	if (ret != 0) {
+		err = ret;
+		goto errorout;
+	}
+
+	ret = hv_ringbuffer_init(
+		&newchannel->inbound, in, recv_ringbuffer_size);
+	if (ret != 0) {
+		err = ret;
+		goto errorout;
+	}
+
+
+	/* Establish the gpadl for the ring buffer */
+	newchannel->ringbuffer_gpadlhandle = 0;
+
+	ret = vmbus_establish_gpadl(newchannel,
+					 newchannel->outbound.ring_buffer,
+					 send_ringbuffer_size +
+					 recv_ringbuffer_size,
+					 &newchannel->ringbuffer_gpadlhandle);
+
+	if (ret != 0) {
+		err = ret;
+		goto errorout;
+	}
+
+	/* Create and init the channel open message */
+	open_info = kmalloc(sizeof(*open_info) +
+			   sizeof(struct vmbus_channel_open_channel),
+			   GFP_KERNEL);
+	if (!open_info) {
+		err = -ENOMEM;
+		goto errorout;
+	}
+
+	init_completion(&open_info->waitevent);
+
+	open_msg = (struct vmbus_channel_open_channel *)open_info->msg;
+	open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
+	open_msg->openid = newchannel->offermsg.child_relid;
+	open_msg->child_relid = newchannel->offermsg.child_relid;
+	open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
+	open_msg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >>
+						  PAGE_SHIFT;
+	open_msg->server_contextarea_gpadlhandle = 0;
+
+	if (userdatalen > MAX_USER_DEFINED_BYTES) {
+		err = -EINVAL;
+		goto errorout;
+	}
+
+	if (userdatalen)
+		memcpy(open_msg->userdata, userdata, userdatalen);
+
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_add_tail(&open_info->msglistentry,
+		      &vmbus_connection.chn_msg_list);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	ret = vmbus_post_msg(open_msg,
+			       sizeof(struct vmbus_channel_open_channel));
+
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
+	if (t == 0) {
+		err = -ETIMEDOUT;
+		goto errorout;
+	}
+
+
+	if (open_info->response.open_result.status)
+		err = open_info->response.open_result.status;
+
+cleanup:
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_del(&open_info->msglistentry);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	kfree(open_info);
+	return err;
+
+errorout:
+	hv_ringbuffer_cleanup(&newchannel->outbound);
+	hv_ringbuffer_cleanup(&newchannel->inbound);
+	free_pages((unsigned long)out,
+		get_order(send_ringbuffer_size + recv_ringbuffer_size));
+	kfree(open_info);
+	return err;
+}
+EXPORT_SYMBOL_GPL(vmbus_open);
+
+/*
+ * create_gpadl_header - Creates a gpadl for the specified buffer
+ */
+static int create_gpadl_header(void *kbuffer, u32 size,
+					 struct vmbus_channel_msginfo **msginfo,
+					 u32 *messagecount)
+{
+	int i;
+	int pagecount;
+	unsigned long long pfn;
+	struct vmbus_channel_gpadl_header *gpadl_header;
+	struct vmbus_channel_gpadl_body *gpadl_body;
+	struct vmbus_channel_msginfo *msgheader;
+	struct vmbus_channel_msginfo *msgbody = NULL;
+	u32 msgsize;
+
+	int pfnsum, pfncount, pfnleft, pfncurr, pfnsize;
+
+	pagecount = size >> PAGE_SHIFT;
+	pfn = virt_to_phys(kbuffer) >> PAGE_SHIFT;
+
+	/* do we need a gpadl body msg */
+	pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
+		  sizeof(struct vmbus_channel_gpadl_header) -
+		  sizeof(struct gpa_range);
+	pfncount = pfnsize / sizeof(u64);
+
+	if (pagecount > pfncount) {
+		/* we need a gpadl body */
+		/* fill in the header */
+		msgsize = sizeof(struct vmbus_channel_msginfo) +
+			  sizeof(struct vmbus_channel_gpadl_header) +
+			  sizeof(struct gpa_range) + pfncount * sizeof(u64);
+		msgheader =  kzalloc(msgsize, GFP_KERNEL);
+		if (!msgheader)
+			goto nomem;
+
+		INIT_LIST_HEAD(&msgheader->submsglist);
+		msgheader->msgsize = msgsize;
+
+		gpadl_header = (struct vmbus_channel_gpadl_header *)
+			msgheader->msg;
+		gpadl_header->rangecount = 1;
+		gpadl_header->range_buflen = sizeof(struct gpa_range) +
+					 pagecount * sizeof(u64);
+		gpadl_header->range[0].byte_offset = 0;
+		gpadl_header->range[0].byte_count = size;
+		for (i = 0; i < pfncount; i++)
+			gpadl_header->range[0].pfn_array[i] = pfn+i;
+		*msginfo = msgheader;
+		*messagecount = 1;
+
+		pfnsum = pfncount;
+		pfnleft = pagecount - pfncount;
+
+		/* how many pfns can we fit */
+		pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
+			  sizeof(struct vmbus_channel_gpadl_body);
+		pfncount = pfnsize / sizeof(u64);
+
+		/* fill in the body */
+		while (pfnleft) {
+			if (pfnleft > pfncount)
+				pfncurr = pfncount;
+			else
+				pfncurr = pfnleft;
+
+			msgsize = sizeof(struct vmbus_channel_msginfo) +
+				  sizeof(struct vmbus_channel_gpadl_body) +
+				  pfncurr * sizeof(u64);
+			msgbody = kzalloc(msgsize, GFP_KERNEL);
+
+			if (!msgbody) {
+				struct vmbus_channel_msginfo *pos = NULL;
+				struct vmbus_channel_msginfo *tmp = NULL;
+				/*
+				 * Free up all the allocated messages.
+				 */
+				list_for_each_entry_safe(pos, tmp,
+					&msgheader->submsglist,
+					msglistentry) {
+
+					list_del(&pos->msglistentry);
+					kfree(pos);
+				}
+
+				goto nomem;
+			}
+
+			msgbody->msgsize = msgsize;
+			(*messagecount)++;
+			gpadl_body =
+				(struct vmbus_channel_gpadl_body *)msgbody->msg;
+
+			/*
+			 * Gpadl is u32 and we are using a pointer which could
+			 * be 64-bit
+			 * This is governed by the guest/host protocol and
+			 * so the hypervisor gurantees that this is ok.
+			 */
+			for (i = 0; i < pfncurr; i++)
+				gpadl_body->pfn[i] = pfn + pfnsum + i;
+
+			/* add to msg header */
+			list_add_tail(&msgbody->msglistentry,
+				      &msgheader->submsglist);
+			pfnsum += pfncurr;
+			pfnleft -= pfncurr;
+		}
+	} else {
+		/* everything fits in a header */
+		msgsize = sizeof(struct vmbus_channel_msginfo) +
+			  sizeof(struct vmbus_channel_gpadl_header) +
+			  sizeof(struct gpa_range) + pagecount * sizeof(u64);
+		msgheader = kzalloc(msgsize, GFP_KERNEL);
+		if (msgheader == NULL)
+			goto nomem;
+		msgheader->msgsize = msgsize;
+
+		gpadl_header = (struct vmbus_channel_gpadl_header *)
+			msgheader->msg;
+		gpadl_header->rangecount = 1;
+		gpadl_header->range_buflen = sizeof(struct gpa_range) +
+					 pagecount * sizeof(u64);
+		gpadl_header->range[0].byte_offset = 0;
+		gpadl_header->range[0].byte_count = size;
+		for (i = 0; i < pagecount; i++)
+			gpadl_header->range[0].pfn_array[i] = pfn+i;
+
+		*msginfo = msgheader;
+		*messagecount = 1;
+	}
+
+	return 0;
+nomem:
+	kfree(msgheader);
+	kfree(msgbody);
+	return -ENOMEM;
+}
+
+/*
+ * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer
+ *
+ * @channel: a channel
+ * @kbuffer: from kmalloc
+ * @size: page-size multiple
+ * @gpadl_handle: some funky thing
+ */
+int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
+			       u32 size, u32 *gpadl_handle)
+{
+	struct vmbus_channel_gpadl_header *gpadlmsg;
+	struct vmbus_channel_gpadl_body *gpadl_body;
+	struct vmbus_channel_msginfo *msginfo = NULL;
+	struct vmbus_channel_msginfo *submsginfo;
+	u32 msgcount;
+	struct list_head *curr;
+	u32 next_gpadl_handle;
+	unsigned long flags;
+	int ret = 0;
+	int t;
+
+	next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle);
+	atomic_inc(&vmbus_connection.next_gpadl_handle);
+
+	ret = create_gpadl_header(kbuffer, size, &msginfo, &msgcount);
+	if (ret)
+		return ret;
+
+	init_completion(&msginfo->waitevent);
+
+	gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg;
+	gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER;
+	gpadlmsg->child_relid = channel->offermsg.child_relid;
+	gpadlmsg->gpadl = next_gpadl_handle;
+
+
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_add_tail(&msginfo->msglistentry,
+		      &vmbus_connection.chn_msg_list);
+
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
+			       sizeof(*msginfo));
+	if (ret != 0)
+		goto cleanup;
+
+	if (msgcount > 1) {
+		list_for_each(curr, &msginfo->submsglist) {
+
+			submsginfo = (struct vmbus_channel_msginfo *)curr;
+			gpadl_body =
+			     (struct vmbus_channel_gpadl_body *)submsginfo->msg;
+
+			gpadl_body->header.msgtype =
+				CHANNELMSG_GPADL_BODY;
+			gpadl_body->gpadl = next_gpadl_handle;
+
+			ret = vmbus_post_msg(gpadl_body,
+					       submsginfo->msgsize -
+					       sizeof(*submsginfo));
+			if (ret != 0)
+				goto cleanup;
+
+		}
+	}
+	t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
+	BUG_ON(t == 0);
+
+
+	/* At this point, we received the gpadl created msg */
+	*gpadl_handle = gpadlmsg->gpadl;
+
+cleanup:
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_del(&msginfo->msglistentry);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	kfree(msginfo);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vmbus_establish_gpadl);
+
+/*
+ * vmbus_teardown_gpadl -Teardown the specified GPADL handle
+ */
+int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
+{
+	struct vmbus_channel_gpadl_teardown *msg;
+	struct vmbus_channel_msginfo *info;
+	unsigned long flags;
+	int ret, t;
+
+	info = kmalloc(sizeof(*info) +
+		       sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	init_completion(&info->waitevent);
+
+	msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
+
+	msg->header.msgtype = CHANNELMSG_GPADL_TEARDOWN;
+	msg->child_relid = channel->offermsg.child_relid;
+	msg->gpadl = gpadl_handle;
+
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_add_tail(&info->msglistentry,
+		      &vmbus_connection.chn_msg_list);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+	ret = vmbus_post_msg(msg,
+			       sizeof(struct vmbus_channel_gpadl_teardown));
+
+	BUG_ON(ret != 0);
+	t = wait_for_completion_timeout(&info->waitevent, 5*HZ);
+	BUG_ON(t == 0);
+
+	/* Received a torndown response */
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_del(&info->msglistentry);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	kfree(info);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
+
+/*
+ * vmbus_close - Close the specified channel
+ */
+void vmbus_close(struct vmbus_channel *channel)
+{
+	struct vmbus_channel_close_channel *msg;
+	int ret;
+	unsigned long flags;
+
+	/* Stop callback and cancel the timer asap */
+	spin_lock_irqsave(&channel->inbound_lock, flags);
+	channel->onchannel_callback = NULL;
+	spin_unlock_irqrestore(&channel->inbound_lock, flags);
+
+	/* Send a closing message */
+
+	msg = &channel->close_msg.msg;
+
+	msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
+	msg->child_relid = channel->offermsg.child_relid;
+
+	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
+
+	BUG_ON(ret != 0);
+	/* Tear down the gpadl for the channel's ring buffer */
+	if (channel->ringbuffer_gpadlhandle)
+		vmbus_teardown_gpadl(channel,
+					  channel->ringbuffer_gpadlhandle);
+
+	/* Cleanup the ring buffers for this channel */
+	hv_ringbuffer_cleanup(&channel->outbound);
+	hv_ringbuffer_cleanup(&channel->inbound);
+
+	free_pages((unsigned long)channel->ringbuffer_pages,
+		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
+
+
+}
+EXPORT_SYMBOL_GPL(vmbus_close);
+
+/**
+ * vmbus_sendpacket() - Send the specified buffer on the given channel
+ * @channel: Pointer to vmbus_channel structure.
+ * @buffer: Pointer to the buffer you want to receive the data into.
+ * @bufferlen: Maximum size of what the the buffer will hold
+ * @requestid: Identifier of the request
+ * @type: Type of packet that is being send e.g. negotiate, time
+ * packet etc.
+ *
+ * Sends data in @buffer directly to hyper-v via the vmbus
+ * This will send the data unparsed to hyper-v.
+ *
+ * Mainly used by Hyper-V drivers.
+ */
+int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
+			   u32 bufferlen, u64 requestid,
+			   enum vmbus_packet_type type, u32 flags)
+{
+	struct vmpacket_descriptor desc;
+	u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
+	u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
+	struct scatterlist bufferlist[3];
+	u64 aligned_data = 0;
+	int ret;
+
+
+	/* Setup the descriptor */
+	desc.type = type; /* VmbusPacketTypeDataInBand; */
+	desc.flags = flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
+	/* in 8-bytes granularity */
+	desc.offset8 = sizeof(struct vmpacket_descriptor) >> 3;
+	desc.len8 = (u16)(packetlen_aligned >> 3);
+	desc.trans_id = requestid;
+
+	sg_init_table(bufferlist, 3);
+	sg_set_buf(&bufferlist[0], &desc, sizeof(struct vmpacket_descriptor));
+	sg_set_buf(&bufferlist[1], buffer, bufferlen);
+	sg_set_buf(&bufferlist[2], &aligned_data,
+		   packetlen_aligned - packetlen);
+
+	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
+
+	if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
+		vmbus_setevent(channel);
+
+	return ret;
+}
+EXPORT_SYMBOL(vmbus_sendpacket);
+
+/*
+ * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
+ * packets using a GPADL Direct packet type.
+ */
+int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
+				     struct hv_page_buffer pagebuffers[],
+				     u32 pagecount, void *buffer, u32 bufferlen,
+				     u64 requestid)
+{
+	int ret;
+	int i;
+	struct vmbus_channel_packet_page_buffer desc;
+	u32 descsize;
+	u32 packetlen;
+	u32 packetlen_aligned;
+	struct scatterlist bufferlist[3];
+	u64 aligned_data = 0;
+
+	if (pagecount > MAX_PAGE_BUFFER_COUNT)
+		return -EINVAL;
+
+
+	/*
+	 * Adjust the size down since vmbus_channel_packet_page_buffer is the
+	 * largest size we support
+	 */
+	descsize = sizeof(struct vmbus_channel_packet_page_buffer) -
+			  ((MAX_PAGE_BUFFER_COUNT - pagecount) *
+			  sizeof(struct hv_page_buffer));
+	packetlen = descsize + bufferlen;
+	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
+
+	/* Setup the descriptor */
+	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
+	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
+	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
+	desc.length8 = (u16)(packetlen_aligned >> 3);
+	desc.transactionid = requestid;
+	desc.rangecount = pagecount;
+
+	for (i = 0; i < pagecount; i++) {
+		desc.range[i].len = pagebuffers[i].len;
+		desc.range[i].offset = pagebuffers[i].offset;
+		desc.range[i].pfn	 = pagebuffers[i].pfn;
+	}
+
+	sg_init_table(bufferlist, 3);
+	sg_set_buf(&bufferlist[0], &desc, descsize);
+	sg_set_buf(&bufferlist[1], buffer, bufferlen);
+	sg_set_buf(&bufferlist[2], &aligned_data,
+		packetlen_aligned - packetlen);
+
+	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
+
+	if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
+		vmbus_setevent(channel);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
+
+/*
+ * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
+ * using a GPADL Direct packet type.
+ */
+int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
+				struct hv_multipage_buffer *multi_pagebuffer,
+				void *buffer, u32 bufferlen, u64 requestid)
+{
+	int ret;
+	struct vmbus_channel_packet_multipage_buffer desc;
+	u32 descsize;
+	u32 packetlen;
+	u32 packetlen_aligned;
+	struct scatterlist bufferlist[3];
+	u64 aligned_data = 0;
+	u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
+					 multi_pagebuffer->len);
+
+
+	if ((pfncount < 0) || (pfncount > MAX_MULTIPAGE_BUFFER_COUNT))
+		return -EINVAL;
+
+	/*
+	 * Adjust the size down since vmbus_channel_packet_multipage_buffer is
+	 * the largest size we support
+	 */
+	descsize = sizeof(struct vmbus_channel_packet_multipage_buffer) -
+			  ((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) *
+			  sizeof(u64));
+	packetlen = descsize + bufferlen;
+	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
+
+
+	/* Setup the descriptor */
+	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
+	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
+	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
+	desc.length8 = (u16)(packetlen_aligned >> 3);
+	desc.transactionid = requestid;
+	desc.rangecount = 1;
+
+	desc.range.len = multi_pagebuffer->len;
+	desc.range.offset = multi_pagebuffer->offset;
+
+	memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
+	       pfncount * sizeof(u64));
+
+	sg_init_table(bufferlist, 3);
+	sg_set_buf(&bufferlist[0], &desc, descsize);
+	sg_set_buf(&bufferlist[1], buffer, bufferlen);
+	sg_set_buf(&bufferlist[2], &aligned_data,
+		packetlen_aligned - packetlen);
+
+	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
+
+	if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
+		vmbus_setevent(channel);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
+
+/**
+ * vmbus_recvpacket() - Retrieve the user packet on the specified channel
+ * @channel: Pointer to vmbus_channel structure.
+ * @buffer: Pointer to the buffer you want to receive the data into.
+ * @bufferlen: Maximum size of what the the buffer will hold
+ * @buffer_actual_len: The actual size of the data after it was received
+ * @requestid: Identifier of the request
+ *
+ * Receives directly from the hyper-v vmbus and puts the data it received
+ * into Buffer. This will receive the data unparsed from hyper-v.
+ *
+ * Mainly used by Hyper-V drivers.
+ */
+int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
+			u32 bufferlen, u32 *buffer_actual_len, u64 *requestid)
+{
+	struct vmpacket_descriptor desc;
+	u32 packetlen;
+	u32 userlen;
+	int ret;
+
+	*buffer_actual_len = 0;
+	*requestid = 0;
+
+
+	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
+			     sizeof(struct vmpacket_descriptor));
+	if (ret != 0)
+		return 0;
+
+	packetlen = desc.len8 << 3;
+	userlen = packetlen - (desc.offset8 << 3);
+
+	*buffer_actual_len = userlen;
+
+	if (userlen > bufferlen) {
+
+		pr_err("Buffer too small - got %d needs %d\n",
+			   bufferlen, userlen);
+		return -ETOOSMALL;
+	}
+
+	*requestid = desc.trans_id;
+
+	/* Copy over the packet to the user buffer */
+	ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
+			     (desc.offset8 << 3));
+
+
+	return 0;
+}
+EXPORT_SYMBOL(vmbus_recvpacket);
+
+/*
+ * vmbus_recvpacket_raw - Retrieve the raw packet on the specified channel
+ */
+int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
+			      u32 bufferlen, u32 *buffer_actual_len,
+			      u64 *requestid)
+{
+	struct vmpacket_descriptor desc;
+	u32 packetlen;
+	u32 userlen;
+	int ret;
+
+	*buffer_actual_len = 0;
+	*requestid = 0;
+
+
+	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
+			     sizeof(struct vmpacket_descriptor));
+	if (ret != 0)
+		return 0;
+
+
+	packetlen = desc.len8 << 3;
+	userlen = packetlen - (desc.offset8 << 3);
+
+	*buffer_actual_len = packetlen;
+
+	if (packetlen > bufferlen) {
+		pr_err("Buffer too small - needed %d bytes but "
+			"got space for only %d bytes\n",
+			packetlen, bufferlen);
+		return -ENOBUFS;
+	}
+
+	*requestid = desc.trans_id;
+
+	/* Copy over the entire packet to the user buffer */
+	ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);
diff -druN linux-libre-3.1-gnu/drivers/hv/channel_mgmt.c linux-libre-3.2-gnu/drivers/hv/channel_mgmt.c
--- linux-libre-3.1-gnu/drivers/hv/channel_mgmt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hv/channel_mgmt.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,646 @@
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/completion.h>
+#include <linux/hyperv.h>
+
+#include "hyperv_vmbus.h"
+
+struct vmbus_channel_message_table_entry {
+	enum vmbus_channel_message_type message_type;
+	void (*message_handler)(struct vmbus_channel_message_header *msg);
+};
+
+#define MAX_MSG_TYPES                    4
+#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8
+
+static const uuid_le
+	supported_device_classes[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = {
+	/* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
+	/* Storage - SCSI */
+	{
+		.b  = {
+			0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
+			0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f
+		}
+	},
+
+	/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
+	/* Network */
+	{
+		.b = {
+			0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
+			0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E
+		}
+	},
+
+	/* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */
+	/* Input */
+	{
+		.b = {
+			0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c,
+			0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A
+		}
+	},
+
+	/* {32412632-86cb-44a2-9b5c-50d1417354f5} */
+	/* IDE */
+	{
+		.b = {
+			0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44,
+			0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5
+		}
+	},
+	/* 0E0B6031-5213-4934-818B-38D90CED39DB */
+	/* Shutdown */
+	{
+		.b = {
+			0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
+			0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB
+		}
+	},
+	/* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
+	/* TimeSync */
+	{
+		.b = {
+			0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
+			0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
+		}
+	},
+	/* {57164f39-9115-4e78-ab55-382f3bd5422d} */
+	/* Heartbeat */
+	{
+		.b = {
+			0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
+			0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d
+		}
+	},
+	/* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */
+	/* KVP */
+	{
+		.b = {
+			0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
+			0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3,  0xe6
+	}
+	},
+
+};
+
+
+/**
+ * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message
+ * @icmsghdrp: Pointer to msg header structure
+ * @icmsg_negotiate: Pointer to negotiate message structure
+ * @buf: Raw buffer channel data
+ *
+ * @icmsghdrp is of type &struct icmsg_hdr.
+ * @negop is of type &struct icmsg_negotiate.
+ * Set up and fill in default negotiate response message. This response can
+ * come from both the vmbus driver and the hv_utils driver. The current api
+ * will respond properly to both Windows 2008 and Windows 2008-R2 operating
+ * systems.
+ *
+ * Mainly used by Hyper-V drivers.
+ */
+void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
+			       struct icmsg_negotiate *negop, u8 *buf)
+{
+	if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+		icmsghdrp->icmsgsize = 0x10;
+
+		negop = (struct icmsg_negotiate *)&buf[
+			sizeof(struct vmbuspipe_hdr) +
+			sizeof(struct icmsg_hdr)];
+
+		if (negop->icframe_vercnt == 2 &&
+		   negop->icversion_data[1].major == 3) {
+			negop->icversion_data[0].major = 3;
+			negop->icversion_data[0].minor = 0;
+			negop->icversion_data[1].major = 3;
+			negop->icversion_data[1].minor = 0;
+		} else {
+			negop->icversion_data[0].major = 1;
+			negop->icversion_data[0].minor = 0;
+			negop->icversion_data[1].major = 1;
+			negop->icversion_data[1].minor = 0;
+		}
+
+		negop->icframe_vercnt = 1;
+		negop->icmsg_vercnt = 1;
+	}
+}
+EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp);
+
+/*
+ * alloc_channel - Allocate and initialize a vmbus channel object
+ */
+static struct vmbus_channel *alloc_channel(void)
+{
+	struct vmbus_channel *channel;
+
+	channel = kzalloc(sizeof(*channel), GFP_ATOMIC);
+	if (!channel)
+		return NULL;
+
+	spin_lock_init(&channel->inbound_lock);
+
+	channel->controlwq = create_workqueue("hv_vmbus_ctl");
+	if (!channel->controlwq) {
+		kfree(channel);
+		return NULL;
+	}
+
+	return channel;
+}
+
+/*
+ * release_hannel - Release the vmbus channel object itself
+ */
+static void release_channel(struct work_struct *work)
+{
+	struct vmbus_channel *channel = container_of(work,
+						     struct vmbus_channel,
+						     work);
+
+	destroy_workqueue(channel->controlwq);
+
+	kfree(channel);
+}
+
+/*
+ * free_channel - Release the resources used by the vmbus channel object
+ */
+static void free_channel(struct vmbus_channel *channel)
+{
+
+	/*
+	 * We have to release the channel's workqueue/thread in the vmbus's
+	 * workqueue/thread context
+	 * ie we can't destroy ourselves.
+	 */
+	INIT_WORK(&channel->work, release_channel);
+	queue_work(vmbus_connection.work_queue, &channel->work);
+}
+
+
+
+/*
+ * vmbus_process_rescind_offer -
+ * Rescind the offer by initiating a device removal
+ */
+static void vmbus_process_rescind_offer(struct work_struct *work)
+{
+	struct vmbus_channel *channel = container_of(work,
+						     struct vmbus_channel,
+						     work);
+
+	vmbus_device_unregister(channel->device_obj);
+}
+
+/*
+ * vmbus_process_offer - Process the offer by creating a channel/device
+ * associated with this offer
+ */
+static void vmbus_process_offer(struct work_struct *work)
+{
+	struct vmbus_channel *newchannel = container_of(work,
+							struct vmbus_channel,
+							work);
+	struct vmbus_channel *channel;
+	bool fnew = true;
+	int ret;
+	unsigned long flags;
+
+	/* The next possible work is rescind handling */
+	INIT_WORK(&newchannel->work, vmbus_process_rescind_offer);
+
+	/* Make sure this is a new offer */
+	spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
+
+	list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
+		if (!uuid_le_cmp(channel->offermsg.offer.if_type,
+			newchannel->offermsg.offer.if_type) &&
+			!uuid_le_cmp(channel->offermsg.offer.if_instance,
+				newchannel->offermsg.offer.if_instance)) {
+			fnew = false;
+			break;
+		}
+	}
+
+	if (fnew)
+		list_add_tail(&newchannel->listentry,
+			      &vmbus_connection.chn_list);
+
+	spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
+
+	if (!fnew) {
+		free_channel(newchannel);
+		return;
+	}
+
+	/*
+	 * Start the process of binding this offer to the driver
+	 * We need to set the DeviceObject field before calling
+	 * vmbus_child_dev_add()
+	 */
+	newchannel->device_obj = vmbus_device_create(
+		&newchannel->offermsg.offer.if_type,
+		&newchannel->offermsg.offer.if_instance,
+		newchannel);
+
+	/*
+	 * Add the new device to the bus. This will kick off device-driver
+	 * binding which eventually invokes the device driver's AddDevice()
+	 * method.
+	 */
+	ret = vmbus_device_register(newchannel->device_obj);
+	if (ret != 0) {
+		pr_err("unable to add child device object (relid %d)\n",
+			   newchannel->offermsg.child_relid);
+
+		spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
+		list_del(&newchannel->listentry);
+		spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
+
+		free_channel(newchannel);
+	} else {
+		/*
+		 * This state is used to indicate a successful open
+		 * so that when we do close the channel normally, we
+		 * can cleanup properly
+		 */
+		newchannel->state = CHANNEL_OPEN_STATE;
+	}
+}
+
+/*
+ * vmbus_onoffer - Handler for channel offers from vmbus in parent partition.
+ *
+ */
+static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_offer_channel *offer;
+	struct vmbus_channel *newchannel;
+	uuid_le *guidtype;
+	uuid_le *guidinstance;
+	int i;
+	int fsupported = 0;
+
+	offer = (struct vmbus_channel_offer_channel *)hdr;
+	for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) {
+		if (!uuid_le_cmp(offer->offer.if_type,
+				supported_device_classes[i])) {
+			fsupported = 1;
+			break;
+		}
+	}
+
+	if (!fsupported)
+		return;
+
+	guidtype = &offer->offer.if_type;
+	guidinstance = &offer->offer.if_instance;
+
+	/* Allocate the channel object and save this offer. */
+	newchannel = alloc_channel();
+	if (!newchannel) {
+		pr_err("Unable to allocate channel object\n");
+		return;
+	}
+
+	memcpy(&newchannel->offermsg, offer,
+	       sizeof(struct vmbus_channel_offer_channel));
+	newchannel->monitor_grp = (u8)offer->monitorid / 32;
+	newchannel->monitor_bit = (u8)offer->monitorid % 32;
+
+	INIT_WORK(&newchannel->work, vmbus_process_offer);
+	queue_work(newchannel->controlwq, &newchannel->work);
+}
+
+/*
+ * vmbus_onoffer_rescind - Rescind offer handler.
+ *
+ * We queue a work item to process this offer synchronously
+ */
+static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_rescind_offer *rescind;
+	struct vmbus_channel *channel;
+
+	rescind = (struct vmbus_channel_rescind_offer *)hdr;
+	channel = relid2channel(rescind->child_relid);
+
+	if (channel == NULL)
+		/* Just return here, no channel found */
+		return;
+
+	/* work is initialized for vmbus_process_rescind_offer() from
+	 * vmbus_process_offer() where the channel got created */
+	queue_work(channel->controlwq, &channel->work);
+}
+
+/*
+ * vmbus_onoffers_delivered -
+ * This is invoked when all offers have been delivered.
+ *
+ * Nothing to do here.
+ */
+static void vmbus_onoffers_delivered(
+			struct vmbus_channel_message_header *hdr)
+{
+}
+
+/*
+ * vmbus_onopen_result - Open result handler.
+ *
+ * This is invoked when we received a response to our channel open request.
+ * Find the matching request, copy the response and signal the requesting
+ * thread.
+ */
+static void vmbus_onopen_result(struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_open_result *result;
+	struct vmbus_channel_msginfo *msginfo;
+	struct vmbus_channel_message_header *requestheader;
+	struct vmbus_channel_open_channel *openmsg;
+	unsigned long flags;
+
+	result = (struct vmbus_channel_open_result *)hdr;
+
+	/*
+	 * Find the open msg, copy the result and signal/unblock the wait event
+	 */
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+
+	list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+				msglistentry) {
+		requestheader =
+			(struct vmbus_channel_message_header *)msginfo->msg;
+
+		if (requestheader->msgtype == CHANNELMSG_OPENCHANNEL) {
+			openmsg =
+			(struct vmbus_channel_open_channel *)msginfo->msg;
+			if (openmsg->child_relid == result->child_relid &&
+			    openmsg->openid == result->openid) {
+				memcpy(&msginfo->response.open_result,
+				       result,
+				       sizeof(
+					struct vmbus_channel_open_result));
+				complete(&msginfo->waitevent);
+				break;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+}
+
+/*
+ * vmbus_ongpadl_created - GPADL created handler.
+ *
+ * This is invoked when we received a response to our gpadl create request.
+ * Find the matching request, copy the response and signal the requesting
+ * thread.
+ */
+static void vmbus_ongpadl_created(struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_gpadl_created *gpadlcreated;
+	struct vmbus_channel_msginfo *msginfo;
+	struct vmbus_channel_message_header *requestheader;
+	struct vmbus_channel_gpadl_header *gpadlheader;
+	unsigned long flags;
+
+	gpadlcreated = (struct vmbus_channel_gpadl_created *)hdr;
+
+	/*
+	 * Find the establish msg, copy the result and signal/unblock the wait
+	 * event
+	 */
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+
+	list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+				msglistentry) {
+		requestheader =
+			(struct vmbus_channel_message_header *)msginfo->msg;
+
+		if (requestheader->msgtype == CHANNELMSG_GPADL_HEADER) {
+			gpadlheader =
+			(struct vmbus_channel_gpadl_header *)requestheader;
+
+			if ((gpadlcreated->child_relid ==
+			     gpadlheader->child_relid) &&
+			    (gpadlcreated->gpadl == gpadlheader->gpadl)) {
+				memcpy(&msginfo->response.gpadl_created,
+				       gpadlcreated,
+				       sizeof(
+					struct vmbus_channel_gpadl_created));
+				complete(&msginfo->waitevent);
+				break;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+}
+
+/*
+ * vmbus_ongpadl_torndown - GPADL torndown handler.
+ *
+ * This is invoked when we received a response to our gpadl teardown request.
+ * Find the matching request, copy the response and signal the requesting
+ * thread.
+ */
+static void vmbus_ongpadl_torndown(
+			struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_gpadl_torndown *gpadl_torndown;
+	struct vmbus_channel_msginfo *msginfo;
+	struct vmbus_channel_message_header *requestheader;
+	struct vmbus_channel_gpadl_teardown *gpadl_teardown;
+	unsigned long flags;
+
+	gpadl_torndown = (struct vmbus_channel_gpadl_torndown *)hdr;
+
+	/*
+	 * Find the open msg, copy the result and signal/unblock the wait event
+	 */
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+
+	list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+				msglistentry) {
+		requestheader =
+			(struct vmbus_channel_message_header *)msginfo->msg;
+
+		if (requestheader->msgtype == CHANNELMSG_GPADL_TEARDOWN) {
+			gpadl_teardown =
+			(struct vmbus_channel_gpadl_teardown *)requestheader;
+
+			if (gpadl_torndown->gpadl == gpadl_teardown->gpadl) {
+				memcpy(&msginfo->response.gpadl_torndown,
+				       gpadl_torndown,
+				       sizeof(
+					struct vmbus_channel_gpadl_torndown));
+				complete(&msginfo->waitevent);
+				break;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+}
+
+/*
+ * vmbus_onversion_response - Version response handler
+ *
+ * This is invoked when we received a response to our initiate contact request.
+ * Find the matching request, copy the response and signal the requesting
+ * thread.
+ */
+static void vmbus_onversion_response(
+		struct vmbus_channel_message_header *hdr)
+{
+	struct vmbus_channel_msginfo *msginfo;
+	struct vmbus_channel_message_header *requestheader;
+	struct vmbus_channel_initiate_contact *initiate;
+	struct vmbus_channel_version_response *version_response;
+	unsigned long flags;
+
+	version_response = (struct vmbus_channel_version_response *)hdr;
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+
+	list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+				msglistentry) {
+		requestheader =
+			(struct vmbus_channel_message_header *)msginfo->msg;
+
+		if (requestheader->msgtype ==
+		    CHANNELMSG_INITIATE_CONTACT) {
+			initiate =
+			(struct vmbus_channel_initiate_contact *)requestheader;
+			memcpy(&msginfo->response.version_response,
+			      version_response,
+			      sizeof(struct vmbus_channel_version_response));
+			complete(&msginfo->waitevent);
+		}
+	}
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+}
+
+/* Channel message dispatch table */
+static struct vmbus_channel_message_table_entry
+	channel_message_table[CHANNELMSG_COUNT] = {
+	{CHANNELMSG_INVALID,			NULL},
+	{CHANNELMSG_OFFERCHANNEL,		vmbus_onoffer},
+	{CHANNELMSG_RESCIND_CHANNELOFFER,	vmbus_onoffer_rescind},
+	{CHANNELMSG_REQUESTOFFERS,		NULL},
+	{CHANNELMSG_ALLOFFERS_DELIVERED,	vmbus_onoffers_delivered},
+	{CHANNELMSG_OPENCHANNEL,		NULL},
+	{CHANNELMSG_OPENCHANNEL_RESULT,	vmbus_onopen_result},
+	{CHANNELMSG_CLOSECHANNEL,		NULL},
+	{CHANNELMSG_GPADL_HEADER,		NULL},
+	{CHANNELMSG_GPADL_BODY,		NULL},
+	{CHANNELMSG_GPADL_CREATED,		vmbus_ongpadl_created},
+	{CHANNELMSG_GPADL_TEARDOWN,		NULL},
+	{CHANNELMSG_GPADL_TORNDOWN,		vmbus_ongpadl_torndown},
+	{CHANNELMSG_RELID_RELEASED,		NULL},
+	{CHANNELMSG_INITIATE_CONTACT,		NULL},
+	{CHANNELMSG_VERSION_RESPONSE,		vmbus_onversion_response},
+	{CHANNELMSG_UNLOAD,			NULL},
+};
+
+/*
+ * vmbus_onmessage - Handler for channel protocol messages.
+ *
+ * This is invoked in the vmbus worker thread context.
+ */
+void vmbus_onmessage(void *context)
+{
+	struct hv_message *msg = context;
+	struct vmbus_channel_message_header *hdr;
+	int size;
+
+	hdr = (struct vmbus_channel_message_header *)msg->u.payload;
+	size = msg->header.payload_size;
+
+	if (hdr->msgtype >= CHANNELMSG_COUNT) {
+		pr_err("Received invalid channel message type %d size %d\n",
+			   hdr->msgtype, size);
+		print_hex_dump_bytes("", DUMP_PREFIX_NONE,
+				     (unsigned char *)msg->u.payload, size);
+		return;
+	}
+
+	if (channel_message_table[hdr->msgtype].message_handler)
+		channel_message_table[hdr->msgtype].message_handler(hdr);
+	else
+		pr_err("Unhandled channel message type %d\n", hdr->msgtype);
+}
+
+/*
+ * vmbus_request_offers - Send a request to get all our pending offers.
+ */
+int vmbus_request_offers(void)
+{
+	struct vmbus_channel_message_header *msg;
+	struct vmbus_channel_msginfo *msginfo;
+	int ret, t;
+
+	msginfo = kmalloc(sizeof(*msginfo) +
+			  sizeof(struct vmbus_channel_message_header),
+			  GFP_KERNEL);
+	if (!msginfo)
+		return -ENOMEM;
+
+	init_completion(&msginfo->waitevent);
+
+	msg = (struct vmbus_channel_message_header *)msginfo->msg;
+
+	msg->msgtype = CHANNELMSG_REQUESTOFFERS;
+
+
+	ret = vmbus_post_msg(msg,
+			       sizeof(struct vmbus_channel_message_header));
+	if (ret != 0) {
+		pr_err("Unable to request offers - %d\n", ret);
+
+		goto cleanup;
+	}
+
+	t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+
+
+cleanup:
+	kfree(msginfo);
+
+	return ret;
+}
+
+/* eof */
diff -druN linux-libre-3.1-gnu/drivers/hv/connection.c linux-libre-3.2-gnu/drivers/hv/connection.c
--- linux-libre-3.1-gnu/drivers/hv/connection.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hv/connection.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,318 @@
+/*
+ *
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/hyperv.h>
+#include <asm/hyperv.h>
+#include "hyperv_vmbus.h"
+
+
+struct vmbus_connection vmbus_connection = {
+	.conn_state		= DISCONNECTED,
+	.next_gpadl_handle	= ATOMIC_INIT(0xE1E10),
+};
+
+/*
+ * vmbus_connect - Sends a connect request on the partition service connection
+ */
+int vmbus_connect(void)
+{
+	int ret = 0;
+	int t;
+	struct vmbus_channel_msginfo *msginfo = NULL;
+	struct vmbus_channel_initiate_contact *msg;
+	unsigned long flags;
+
+	/* Initialize the vmbus connection */
+	vmbus_connection.conn_state = CONNECTING;
+	vmbus_connection.work_queue = create_workqueue("hv_vmbus_con");
+	if (!vmbus_connection.work_queue) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	INIT_LIST_HEAD(&vmbus_connection.chn_msg_list);
+	spin_lock_init(&vmbus_connection.channelmsg_lock);
+
+	INIT_LIST_HEAD(&vmbus_connection.chn_list);
+	spin_lock_init(&vmbus_connection.channel_lock);
+
+	/*
+	 * Setup the vmbus event connection for channel interrupt
+	 * abstraction stuff
+	 */
+	vmbus_connection.int_page =
+	(void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, 0);
+	if (vmbus_connection.int_page == NULL) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	vmbus_connection.recv_int_page = vmbus_connection.int_page;
+	vmbus_connection.send_int_page =
+		(void *)((unsigned long)vmbus_connection.int_page +
+			(PAGE_SIZE >> 1));
+
+	/*
+	 * Setup the monitor notification facility. The 1st page for
+	 * parent->child and the 2nd page for child->parent
+	 */
+	vmbus_connection.monitor_pages =
+	(void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 1);
+	if (vmbus_connection.monitor_pages == NULL) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	msginfo = kzalloc(sizeof(*msginfo) +
+			  sizeof(struct vmbus_channel_initiate_contact),
+			  GFP_KERNEL);
+	if (msginfo == NULL) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	init_completion(&msginfo->waitevent);
+
+	msg = (struct vmbus_channel_initiate_contact *)msginfo->msg;
+
+	msg->header.msgtype = CHANNELMSG_INITIATE_CONTACT;
+	msg->vmbus_version_requested = VMBUS_REVISION_NUMBER;
+	msg->interrupt_page = virt_to_phys(vmbus_connection.int_page);
+	msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages);
+	msg->monitor_page2 = virt_to_phys(
+			(void *)((unsigned long)vmbus_connection.monitor_pages +
+				 PAGE_SIZE));
+
+	/*
+	 * Add to list before we send the request since we may
+	 * receive the response before returning from this routine
+	 */
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_add_tail(&msginfo->msglistentry,
+		      &vmbus_connection.chn_msg_list);
+
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	ret = vmbus_post_msg(msg,
+			       sizeof(struct vmbus_channel_initiate_contact));
+	if (ret != 0) {
+		spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+		list_del(&msginfo->msglistentry);
+		spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock,
+					flags);
+		goto cleanup;
+	}
+
+	/* Wait for the connection response */
+	t =  wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
+	if (t == 0) {
+		spin_lock_irqsave(&vmbus_connection.channelmsg_lock,
+				flags);
+		list_del(&msginfo->msglistentry);
+		spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock,
+					flags);
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_del(&msginfo->msglistentry);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+	/* Check if successful */
+	if (msginfo->response.version_response.version_supported) {
+		vmbus_connection.conn_state = CONNECTED;
+	} else {
+		pr_err("Unable to connect, "
+			"Version %d not supported by Hyper-V\n",
+			VMBUS_REVISION_NUMBER);
+		ret = -ECONNREFUSED;
+		goto cleanup;
+	}
+
+	kfree(msginfo);
+	return 0;
+
+cleanup:
+	vmbus_connection.conn_state = DISCONNECTED;
+
+	if (vmbus_connection.work_queue)
+		destroy_workqueue(vmbus_connection.work_queue);
+
+	if (vmbus_connection.int_page) {
+		free_pages((unsigned long)vmbus_connection.int_page, 0);
+		vmbus_connection.int_page = NULL;
+	}
+
+	if (vmbus_connection.monitor_pages) {
+		free_pages((unsigned long)vmbus_connection.monitor_pages, 1);
+		vmbus_connection.monitor_pages = NULL;
+	}
+
+	kfree(msginfo);
+
+	return ret;
+}
+
+
+/*
+ * relid2channel - Get the channel object given its
+ * child relative id (ie channel id)
+ */
+struct vmbus_channel *relid2channel(u32 relid)
+{
+	struct vmbus_channel *channel;
+	struct vmbus_channel *found_channel  = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
+	list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
+		if (channel->offermsg.child_relid == relid) {
+			found_channel = channel;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
+
+	return found_channel;
+}
+
+/*
+ * process_chn_event - Process a channel event notification
+ */
+static void process_chn_event(u32 relid)
+{
+	struct vmbus_channel *channel;
+	unsigned long flags;
+
+	/*
+	 * Find the channel based on this relid and invokes the
+	 * channel callback to process the event
+	 */
+	channel = relid2channel(relid);
+
+	if (!channel) {
+		pr_err("channel not found for relid - %u\n", relid);
+		return;
+	}
+
+	/*
+	 * A channel once created is persistent even when there
+	 * is no driver handling the device. An unloading driver
+	 * sets the onchannel_callback to NULL under the
+	 * protection of the channel inbound_lock. Thus, checking
+	 * and invoking the driver specific callback takes care of
+	 * orderly unloading of the driver.
+	 */
+
+	spin_lock_irqsave(&channel->inbound_lock, flags);
+	if (channel->onchannel_callback != NULL)
+		channel->onchannel_callback(channel->channel_callback_context);
+	else
+		pr_err("no channel callback for relid - %u\n", relid);
+
+	spin_unlock_irqrestore(&channel->inbound_lock, flags);
+}
+
+/*
+ * vmbus_on_event - Handler for events
+ */
+void vmbus_on_event(unsigned long data)
+{
+	u32 dword;
+	u32 maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5;
+	int bit;
+	u32 relid;
+	u32 *recv_int_page = vmbus_connection.recv_int_page;
+
+	/* Check events */
+	if (!recv_int_page)
+		return;
+	for (dword = 0; dword < maxdword; dword++) {
+		if (!recv_int_page[dword])
+			continue;
+		for (bit = 0; bit < 32; bit++) {
+			if (sync_test_and_clear_bit(bit,
+				(unsigned long *)&recv_int_page[dword])) {
+				relid = (dword << 5) + bit;
+
+				if (relid == 0)
+					/*
+					 * Special case - vmbus
+					 * channel protocol msg
+					 */
+					continue;
+
+				process_chn_event(relid);
+			}
+		}
+	}
+}
+
+/*
+ * vmbus_post_msg - Send a msg on the vmbus's message connection
+ */
+int vmbus_post_msg(void *buffer, size_t buflen)
+{
+	union hv_connection_id conn_id;
+	int ret = 0;
+	int retries = 0;
+
+	conn_id.asu32 = 0;
+	conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID;
+
+	/*
+	 * hv_post_message() can have transient failures because of
+	 * insufficient resources. Retry the operation a couple of
+	 * times before giving up.
+	 */
+	while (retries < 3) {
+		ret =  hv_post_message(conn_id, 1, buffer, buflen);
+		if (ret != HV_STATUS_INSUFFICIENT_BUFFERS)
+			return ret;
+		retries++;
+		msleep(100);
+	}
+	return ret;
+}
+
+/*
+ * vmbus_set_event - Send an event notification to the parent
+ */
+int vmbus_set_event(u32 child_relid)
+{
+	/* Each u32 represents 32 channels */
+	sync_set_bit(child_relid & 31,
+		(unsigned long *)vmbus_connection.send_int_page +
+		(child_relid >> 5));
+
+	return hv_signal_event();
+}
diff -druN linux-libre-3.1-gnu/drivers/hv/hv.c linux-libre-3.2-gnu/drivers/hv/hv.c
--- linux-libre-3.1-gnu/drivers/hv/hv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hv/hv.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/hyperv.h>
+#include <asm/hyperv.h>
+#include "hyperv_vmbus.h"
+
+/* The one and only */
+struct hv_context hv_context = {
+	.synic_initialized	= false,
+	.hypercall_page		= NULL,
+	.signal_event_param	= NULL,
+	.signal_event_buffer	= NULL,
+};
+
+/*
+ * query_hypervisor_presence
+ * - Query the cpuid for presence of windows hypervisor
+ */
+static int query_hypervisor_presence(void)
+{
+	unsigned int eax;
+	unsigned int ebx;
+	unsigned int ecx;
+	unsigned int edx;
+	unsigned int op;
+
+	eax = 0;
+	ebx = 0;
+	ecx = 0;
+	edx = 0;
+	op = HVCPUID_VERSION_FEATURES;
+	cpuid(op, &eax, &ebx, &ecx, &edx);
+
+	return ecx & HV_PRESENT_BIT;
+}
+
+/*
+ * query_hypervisor_info - Get version info of the windows hypervisor
+ */
+static int query_hypervisor_info(void)
+{
+	unsigned int eax;
+	unsigned int ebx;
+	unsigned int ecx;
+	unsigned int edx;
+	unsigned int max_leaf;
+	unsigned int op;
+
+	/*
+	* Its assumed that this is called after confirming that Viridian
+	* is present. Query id and revision.
+	*/
+	eax = 0;
+	ebx = 0;
+	ecx = 0;
+	edx = 0;
+	op = HVCPUID_VENDOR_MAXFUNCTION;
+	cpuid(op, &eax, &ebx, &ecx, &edx);
+
+	max_leaf = eax;
+
+	if (max_leaf >= HVCPUID_VERSION) {
+		eax = 0;
+		ebx = 0;
+		ecx = 0;
+		edx = 0;
+		op = HVCPUID_VERSION;
+		cpuid(op, &eax, &ebx, &ecx, &edx);
+		pr_info("Hyper-V Host OS Build:%d-%d.%d-%d-%d.%d\n",
+			    eax,
+			    ebx >> 16,
+			    ebx & 0xFFFF,
+			    ecx,
+			    edx >> 24,
+			    edx & 0xFFFFFF);
+	}
+	return max_leaf;
+}
+
+/*
+ * do_hypercall- Invoke the specified hypercall
+ */
+static u64 do_hypercall(u64 control, void *input, void *output)
+{
+#ifdef CONFIG_X86_64
+	u64 hv_status = 0;
+	u64 input_address = (input) ? virt_to_phys(input) : 0;
+	u64 output_address = (output) ? virt_to_phys(output) : 0;
+	void *hypercall_page = hv_context.hypercall_page;
+
+	__asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8");
+	__asm__ __volatile__("call *%3" : "=a" (hv_status) :
+			     "c" (control), "d" (input_address),
+			     "m" (hypercall_page));
+
+	return hv_status;
+
+#else
+
+	u32 control_hi = control >> 32;
+	u32 control_lo = control & 0xFFFFFFFF;
+	u32 hv_status_hi = 1;
+	u32 hv_status_lo = 1;
+	u64 input_address = (input) ? virt_to_phys(input) : 0;
+	u32 input_address_hi = input_address >> 32;
+	u32 input_address_lo = input_address & 0xFFFFFFFF;
+	u64 output_address = (output) ? virt_to_phys(output) : 0;
+	u32 output_address_hi = output_address >> 32;
+	u32 output_address_lo = output_address & 0xFFFFFFFF;
+	void *hypercall_page = hv_context.hypercall_page;
+
+	__asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi),
+			      "=a"(hv_status_lo) : "d" (control_hi),
+			      "a" (control_lo), "b" (input_address_hi),
+			      "c" (input_address_lo), "D"(output_address_hi),
+			      "S"(output_address_lo), "m" (hypercall_page));
+
+	return hv_status_lo | ((u64)hv_status_hi << 32);
+#endif /* !x86_64 */
+}
+
+/*
+ * hv_init - Main initialization routine.
+ *
+ * This routine must be called before any other routines in here are called
+ */
+int hv_init(void)
+{
+	int max_leaf;
+	union hv_x64_msr_hypercall_contents hypercall_msr;
+	void *virtaddr = NULL;
+
+	memset(hv_context.synic_event_page, 0, sizeof(void *) * MAX_NUM_CPUS);
+	memset(hv_context.synic_message_page, 0,
+	       sizeof(void *) * MAX_NUM_CPUS);
+
+	if (!query_hypervisor_presence())
+		goto cleanup;
+
+	max_leaf = query_hypervisor_info();
+
+	rdmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid);
+
+	if (hv_context.guestid != 0)
+		goto cleanup;
+
+	/* Write our OS info */
+	wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID);
+	hv_context.guestid = HV_LINUX_GUEST_ID;
+
+	/* See if the hypercall page is already set */
+	rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+
+	virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC);
+
+	if (!virtaddr)
+		goto cleanup;
+
+	hypercall_msr.enable = 1;
+
+	hypercall_msr.guest_physical_address = vmalloc_to_pfn(virtaddr);
+	wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+
+	/* Confirm that hypercall page did get setup. */
+	hypercall_msr.as_uint64 = 0;
+	rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+
+	if (!hypercall_msr.enable)
+		goto cleanup;
+
+	hv_context.hypercall_page = virtaddr;
+
+	/* Setup the global signal event param for the signal event hypercall */
+	hv_context.signal_event_buffer =
+			kmalloc(sizeof(struct hv_input_signal_event_buffer),
+				GFP_KERNEL);
+	if (!hv_context.signal_event_buffer)
+		goto cleanup;
+
+	hv_context.signal_event_param =
+		(struct hv_input_signal_event *)
+			(ALIGN((unsigned long)
+				  hv_context.signal_event_buffer,
+				  HV_HYPERCALL_PARAM_ALIGN));
+	hv_context.signal_event_param->connectionid.asu32 = 0;
+	hv_context.signal_event_param->connectionid.u.id =
+						VMBUS_EVENT_CONNECTION_ID;
+	hv_context.signal_event_param->flag_number = 0;
+	hv_context.signal_event_param->rsvdz = 0;
+
+	return 0;
+
+cleanup:
+	if (virtaddr) {
+		if (hypercall_msr.enable) {
+			hypercall_msr.as_uint64 = 0;
+			wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+		}
+
+		vfree(virtaddr);
+	}
+
+	return -ENOTSUPP;
+}
+
+/*
+ * hv_cleanup - Cleanup routine.
+ *
+ * This routine is called normally during driver unloading or exiting.
+ */
+void hv_cleanup(void)
+{
+	union hv_x64_msr_hypercall_contents hypercall_msr;
+
+	kfree(hv_context.signal_event_buffer);
+	hv_context.signal_event_buffer = NULL;
+	hv_context.signal_event_param = NULL;
+
+	if (hv_context.hypercall_page) {
+		hypercall_msr.as_uint64 = 0;
+		wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
+		vfree(hv_context.hypercall_page);
+		hv_context.hypercall_page = NULL;
+	}
+}
+
+/*
+ * hv_post_message - Post a message using the hypervisor message IPC.
+ *
+ * This involves a hypercall.
+ */
+u16 hv_post_message(union hv_connection_id connection_id,
+		  enum hv_message_type message_type,
+		  void *payload, size_t payload_size)
+{
+	struct aligned_input {
+		u64 alignment8;
+		struct hv_input_post_message msg;
+	};
+
+	struct hv_input_post_message *aligned_msg;
+	u16 status;
+	unsigned long addr;
+
+	if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT)
+		return -EMSGSIZE;
+
+	addr = (unsigned long)kmalloc(sizeof(struct aligned_input), GFP_ATOMIC);
+	if (!addr)
+		return -ENOMEM;
+
+	aligned_msg = (struct hv_input_post_message *)
+			(ALIGN(addr, HV_HYPERCALL_PARAM_ALIGN));
+
+	aligned_msg->connectionid = connection_id;
+	aligned_msg->message_type = message_type;
+	aligned_msg->payload_size = payload_size;
+	memcpy((void *)aligned_msg->payload, payload, payload_size);
+
+	status = do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL)
+		& 0xFFFF;
+
+	kfree((void *)addr);
+
+	return status;
+}
+
+
+/*
+ * hv_signal_event -
+ * Signal an event on the specified connection using the hypervisor event IPC.
+ *
+ * This involves a hypercall.
+ */
+u16 hv_signal_event(void)
+{
+	u16 status;
+
+	status = do_hypercall(HVCALL_SIGNAL_EVENT,
+			       hv_context.signal_event_param,
+			       NULL) & 0xFFFF;
+	return status;
+}
+
+/*
+ * hv_synic_init - Initialize the Synthethic Interrupt Controller.
+ *
+ * If it is already initialized by another entity (ie x2v shim), we need to
+ * retrieve the initialized message and event pages.  Otherwise, we create and
+ * initialize the message and event pages.
+ */
+void hv_synic_init(void *irqarg)
+{
+	u64 version;
+	union hv_synic_simp simp;
+	union hv_synic_siefp siefp;
+	union hv_synic_sint shared_sint;
+	union hv_synic_scontrol sctrl;
+
+	u32 irq_vector = *((u32 *)(irqarg));
+	int cpu = smp_processor_id();
+
+	if (!hv_context.hypercall_page)
+		return;
+
+	/* Check the version */
+	rdmsrl(HV_X64_MSR_SVERSION, version);
+
+	hv_context.synic_message_page[cpu] =
+		(void *)get_zeroed_page(GFP_ATOMIC);
+
+	if (hv_context.synic_message_page[cpu] == NULL) {
+		pr_err("Unable to allocate SYNIC message page\n");
+		goto cleanup;
+	}
+
+	hv_context.synic_event_page[cpu] =
+		(void *)get_zeroed_page(GFP_ATOMIC);
+
+	if (hv_context.synic_event_page[cpu] == NULL) {
+		pr_err("Unable to allocate SYNIC event page\n");
+		goto cleanup;
+	}
+
+	/* Setup the Synic's message page */
+	rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
+	simp.simp_enabled = 1;
+	simp.base_simp_gpa = virt_to_phys(hv_context.synic_message_page[cpu])
+		>> PAGE_SHIFT;
+
+	wrmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
+
+	/* Setup the Synic's event page */
+	rdmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
+	siefp.siefp_enabled = 1;
+	siefp.base_siefp_gpa = virt_to_phys(hv_context.synic_event_page[cpu])
+		>> PAGE_SHIFT;
+
+	wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
+
+	/* Setup the shared SINT. */
+	rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
+
+	shared_sint.as_uint64 = 0;
+	shared_sint.vector = irq_vector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */
+	shared_sint.masked = false;
+	shared_sint.auto_eoi = false;
+
+	wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
+
+	/* Enable the global synic bit */
+	rdmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
+	sctrl.enable = 1;
+
+	wrmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
+
+	hv_context.synic_initialized = true;
+	return;
+
+cleanup:
+	if (hv_context.synic_event_page[cpu])
+		free_page((unsigned long)hv_context.synic_event_page[cpu]);
+
+	if (hv_context.synic_message_page[cpu])
+		free_page((unsigned long)hv_context.synic_message_page[cpu]);
+	return;
+}
+
+/*
+ * hv_synic_cleanup - Cleanup routine for hv_synic_init().
+ */
+void hv_synic_cleanup(void *arg)
+{
+	union hv_synic_sint shared_sint;
+	union hv_synic_simp simp;
+	union hv_synic_siefp siefp;
+	int cpu = smp_processor_id();
+
+	if (!hv_context.synic_initialized)
+		return;
+
+	rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
+
+	shared_sint.masked = 1;
+
+	/* Need to correctly cleanup in the case of SMP!!! */
+	/* Disable the interrupt */
+	wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
+
+	rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
+	simp.simp_enabled = 0;
+	simp.base_simp_gpa = 0;
+
+	wrmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
+
+	rdmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
+	siefp.siefp_enabled = 0;
+	siefp.base_siefp_gpa = 0;
+
+	wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
+
+	free_page((unsigned long)hv_context.synic_message_page[cpu]);
+	free_page((unsigned long)hv_context.synic_event_page[cpu]);
+}
diff -druN linux-libre-3.1-gnu/drivers/hv/hv_kvp.c linux-libre-3.2-gnu/drivers/hv/hv_kvp.c
--- linux-libre-3.1-gnu/drivers/hv/hv_kvp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hv/hv_kvp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,339 @@
+/*
+ * An implementation of key value pair (KVP) functionality for Linux.
+ *
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.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, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You 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.
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/net.h>
+#include <linux/nls.h>
+#include <linux/connector.h>
+#include <linux/workqueue.h>
+#include <linux/hyperv.h>
+
+#include "hv_kvp.h"
+
+
+
+/*
+ * Global state maintained for transaction that is being processed.
+ * Note that only one transaction can be active at any point in time.
+ *
+ * This state is set when we receive a request from the host; we
+ * cleanup this state when the transaction is completed - when we respond
+ * to the host with the key value.
+ */
+
+static struct {
+	bool active; /* transaction status - active or not */
+	int recv_len; /* number of bytes received. */
+	int index; /* current index */
+	struct vmbus_channel *recv_channel; /* chn we got the request */
+	u64 recv_req_id; /* request ID. */
+} kvp_transaction;
+
+static void kvp_send_key(struct work_struct *dummy);
+
+#define TIMEOUT_FIRED 1
+
+static void kvp_respond_to_host(char *key, char *value, int error);
+static void kvp_work_func(struct work_struct *dummy);
+static void kvp_register(void);
+
+static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func);
+static DECLARE_WORK(kvp_sendkey_work, kvp_send_key);
+
+static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL };
+static const char kvp_name[] = "kvp_kernel_module";
+static u8 *recv_buffer;
+/*
+ * Register the kernel component with the user-level daemon.
+ * As part of this registration, pass the LIC version number.
+ */
+
+static void
+kvp_register(void)
+{
+
+	struct cn_msg *msg;
+
+	msg = kzalloc(sizeof(*msg) + strlen(HV_DRV_VERSION) + 1 , GFP_ATOMIC);
+
+	if (msg) {
+		msg->id.idx =  CN_KVP_IDX;
+		msg->id.val = CN_KVP_VAL;
+		msg->seq = KVP_REGISTER;
+		strcpy(msg->data, HV_DRV_VERSION);
+		msg->len = strlen(HV_DRV_VERSION) + 1;
+		cn_netlink_send(msg, 0, GFP_ATOMIC);
+		kfree(msg);
+	}
+}
+static void
+kvp_work_func(struct work_struct *dummy)
+{
+	/*
+	 * If the timer fires, the user-mode component has not responded;
+	 * process the pending transaction.
+	 */
+	kvp_respond_to_host("Unknown key", "Guest timed out", TIMEOUT_FIRED);
+}
+
+/*
+ * Callback when data is received from user mode.
+ */
+
+static void
+kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
+{
+	struct hv_ku_msg *message;
+
+	message = (struct hv_ku_msg *)msg->data;
+	if (msg->seq == KVP_REGISTER) {
+		pr_info("KVP: user-mode registering done.\n");
+		kvp_register();
+	}
+
+	if (msg->seq == KVP_USER_SET) {
+		/*
+		 * Complete the transaction by forwarding the key value
+		 * to the host. But first, cancel the timeout.
+		 */
+		if (cancel_delayed_work_sync(&kvp_work))
+			kvp_respond_to_host(message->kvp_key,
+						message->kvp_value,
+						!strlen(message->kvp_key));
+	}
+}
+
+static void
+kvp_send_key(struct work_struct *dummy)
+{
+	struct cn_msg *msg;
+	int index = kvp_transaction.index;
+
+	msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);
+
+	if (msg) {
+		msg->id.idx =  CN_KVP_IDX;
+		msg->id.val = CN_KVP_VAL;
+		msg->seq = KVP_KERNEL_GET;
+		((struct hv_ku_msg *)msg->data)->kvp_index = index;
+		msg->len = sizeof(struct hv_ku_msg);
+		cn_netlink_send(msg, 0, GFP_ATOMIC);
+		kfree(msg);
+	}
+	return;
+}
+
+/*
+ * Send a response back to the host.
+ */
+
+static void
+kvp_respond_to_host(char *key, char *value, int error)
+{
+	struct hv_kvp_msg  *kvp_msg;
+	struct hv_kvp_msg_enumerate  *kvp_data;
+	char	*key_name;
+	struct icmsg_hdr *icmsghdrp;
+	int	keylen, valuelen;
+	u32	buf_len;
+	struct vmbus_channel *channel;
+	u64	req_id;
+
+	/*
+	 * If a transaction is not active; log and return.
+	 */
+
+	if (!kvp_transaction.active) {
+		/*
+		 * This is a spurious call!
+		 */
+		pr_warn("KVP: Transaction not active\n");
+		return;
+	}
+	/*
+	 * Copy the global state for completing the transaction. Note that
+	 * only one transaction can be active at a time.
+	 */
+
+	buf_len = kvp_transaction.recv_len;
+	channel = kvp_transaction.recv_channel;
+	req_id = kvp_transaction.recv_req_id;
+
+	kvp_transaction.active = false;
+
+	if (channel->onchannel_callback == NULL)
+		/*
+		 * We have raced with util driver being unloaded;
+		 * silently return.
+		 */
+		return;
+
+	icmsghdrp = (struct icmsg_hdr *)
+			&recv_buffer[sizeof(struct vmbuspipe_hdr)];
+	kvp_msg = (struct hv_kvp_msg *)
+			&recv_buffer[sizeof(struct vmbuspipe_hdr) +
+			sizeof(struct icmsg_hdr)];
+	kvp_data = &kvp_msg->kvp_data;
+	key_name = key;
+
+	/*
+	 * If the error parameter is set, terminate the host's enumeration.
+	 */
+	if (error) {
+		/*
+		 * We don't support this index or the we have timedout;
+		 * terminate the host-side iteration by returning an error.
+		 */
+		icmsghdrp->status = HV_E_FAIL;
+		goto response_done;
+	}
+
+	/*
+	 * The windows host expects the key/value pair to be encoded
+	 * in utf16.
+	 */
+	keylen = utf8s_to_utf16s(key_name, strlen(key_name),
+				(wchar_t *)kvp_data->data.key);
+	kvp_data->data.key_size = 2*(keylen + 1); /* utf16 encoding */
+	valuelen = utf8s_to_utf16s(value, strlen(value),
+				(wchar_t *)kvp_data->data.value);
+	kvp_data->data.value_size = 2*(valuelen + 1); /* utf16 encoding */
+
+	kvp_data->data.value_type = REG_SZ; /* all our values are strings */
+	icmsghdrp->status = HV_S_OK;
+
+response_done:
+	icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
+
+	vmbus_sendpacket(channel, recv_buffer, buf_len, req_id,
+				VM_PKT_DATA_INBAND, 0);
+
+}
+
+/*
+ * This callback is invoked when we get a KVP message from the host.
+ * The host ensures that only one KVP transaction can be active at a time.
+ * KVP implementation in Linux needs to forward the key to a user-mde
+ * component to retrive the corresponding value. Consequently, we cannot
+ * respond to the host in the conext of this callback. Since the host
+ * guarantees that at most only one transaction can be active at a time,
+ * we stash away the transaction state in a set of global variables.
+ */
+
+void hv_kvp_onchannelcallback(void *context)
+{
+	struct vmbus_channel *channel = context;
+	u32 recvlen;
+	u64 requestid;
+
+	struct hv_kvp_msg *kvp_msg;
+	struct hv_kvp_msg_enumerate *kvp_data;
+
+	struct icmsg_hdr *icmsghdrp;
+	struct icmsg_negotiate *negop = NULL;
+
+
+	vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid);
+
+	if (recvlen > 0) {
+		icmsghdrp = (struct icmsg_hdr *)&recv_buffer[
+			sizeof(struct vmbuspipe_hdr)];
+
+		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+			vmbus_prep_negotiate_resp(icmsghdrp, negop, recv_buffer);
+		} else {
+			kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
+				sizeof(struct vmbuspipe_hdr) +
+				sizeof(struct icmsg_hdr)];
+
+			kvp_data = &kvp_msg->kvp_data;
+
+			/*
+			 * We only support the "get" operation on
+			 * "KVP_POOL_AUTO" pool.
+			 */
+
+			if ((kvp_msg->kvp_hdr.pool != KVP_POOL_AUTO) ||
+				(kvp_msg->kvp_hdr.operation !=
+				KVP_OP_ENUMERATE)) {
+				icmsghdrp->status = HV_E_FAIL;
+				goto callback_done;
+			}
+
+			/*
+			 * Stash away this global state for completing the
+			 * transaction; note transactions are serialized.
+			 */
+			kvp_transaction.recv_len = recvlen;
+			kvp_transaction.recv_channel = channel;
+			kvp_transaction.recv_req_id = requestid;
+			kvp_transaction.active = true;
+			kvp_transaction.index = kvp_data->index;
+
+			/*
+			 * Get the information from the
+			 * user-mode component.
+			 * component. This transaction will be
+			 * completed when we get the value from
+			 * the user-mode component.
+			 * Set a timeout to deal with
+			 * user-mode not responding.
+			 */
+			schedule_work(&kvp_sendkey_work);
+			schedule_delayed_work(&kvp_work, 5*HZ);
+
+			return;
+
+		}
+
+callback_done:
+
+		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+			| ICMSGHDRFLAG_RESPONSE;
+
+		vmbus_sendpacket(channel, recv_buffer,
+				       recvlen, requestid,
+				       VM_PKT_DATA_INBAND, 0);
+	}
+
+}
+
+int
+hv_kvp_init(struct hv_util_service *srv)
+{
+	int err;
+
+	err = cn_add_callback(&kvp_id, kvp_name, kvp_cn_callback);
+	if (err)
+		return err;
+	recv_buffer = srv->recv_buffer;
+
+	return 0;
+}
+
+void hv_kvp_deinit(void)
+{
+	cn_del_callback(&kvp_id);
+	cancel_delayed_work_sync(&kvp_work);
+	cancel_work_sync(&kvp_sendkey_work);
+}
diff -druN linux-libre-3.1-gnu/drivers/hv/hv_kvp.h linux-libre-3.2-gnu/drivers/hv/hv_kvp.h
--- linux-libre-3.1-gnu/drivers/hv/hv_kvp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hv/hv_kvp.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,184 @@
+/*
+ * An implementation of HyperV key value pair (KVP) functionality for Linux.
+ *
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.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, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You 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	_KVP_H
+#define	_KVP_H_
+
+/*
+ * Maximum value size - used for both key names and value data, and includes
+ * any applicable NULL terminators.
+ *
+ * Note:  This limit is somewhat arbitrary, but falls easily within what is
+ * supported for all native guests (back to Win 2000) and what is reasonable
+ * for the IC KVP exchange functionality.  Note that Windows Me/98/95 are
+ * limited to 255 character key names.
+ *
+ * MSDN recommends not storing data values larger than 2048 bytes in the
+ * registry.
+ *
+ * Note:  This value is used in defining the KVP exchange message - this value
+ * cannot be modified without affecting the message size and compatibility.
+ */
+
+/*
+ * bytes, including any null terminators
+ */
+#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE          (2048)
+
+
+/*
+ * Maximum key size - the registry limit for the length of an entry name
+ * is 256 characters, including the null terminator
+ */
+
+#define HV_KVP_EXCHANGE_MAX_KEY_SIZE            (512)
+
+/*
+ * In Linux, we implement the KVP functionality in two components:
+ * 1) The kernel component which is packaged as part of the hv_utils driver
+ * is responsible for communicating with the host and responsible for
+ * implementing the host/guest protocol. 2) A user level daemon that is
+ * responsible for data gathering.
+ *
+ * Host/Guest Protocol: The host iterates over an index and expects the guest
+ * to assign a key name to the index and also return the value corresponding to
+ * the key. The host will have atmost one KVP transaction outstanding at any
+ * given point in time. The host side iteration stops when the guest returns
+ * an error. Microsoft has specified the following mapping of key names to
+ * host specified index:
+ *
+ *	Index		Key Name
+ *	0		FullyQualifiedDomainName
+ *	1		IntegrationServicesVersion
+ *	2		NetworkAddressIPv4
+ *	3		NetworkAddressIPv6
+ *	4		OSBuildNumber
+ *	5		OSName
+ *	6		OSMajorVersion
+ *	7		OSMinorVersion
+ *	8		OSVersion
+ *	9		ProcessorArchitecture
+ *
+ * The Windows host expects the Key Name and Key Value to be encoded in utf16.
+ *
+ * Guest Kernel/KVP Daemon Protocol: As noted earlier, we implement all of the
+ * data gathering functionality in a user mode daemon. The user level daemon
+ * is also responsible for binding the key name to the index as well. The
+ * kernel and user-level daemon communicate using a connector channel.
+ *
+ * The user mode component first registers with the
+ * the kernel component. Subsequently, the kernel component requests, data
+ * for the specified keys. In response to this message the user mode component
+ * fills in the value corresponding to the specified key. We overload the
+ * sequence field in the cn_msg header to define our KVP message types.
+ *
+ *
+ * The kernel component simply acts as a conduit for communication between the
+ * Windows host and the user-level daemon. The kernel component passes up the
+ * index received from the Host to the user-level daemon. If the index is
+ * valid (supported), the corresponding key as well as its
+ * value (both are strings) is returned. If the index is invalid
+ * (not supported), a NULL key string is returned.
+ */
+
+/*
+ *
+ * The following definitions are shared with the user-mode component; do not
+ * change any of this without making the corresponding changes in
+ * the KVP user-mode component.
+ */
+
+#define CN_KVP_VAL             0x1 /* This supports queries from the kernel */
+#define CN_KVP_USER_VAL       0x2 /* This supports queries from the user */
+
+enum hv_ku_op {
+	KVP_REGISTER = 0, /* Register the user mode component */
+	KVP_KERNEL_GET, /* Kernel is requesting the value */
+	KVP_KERNEL_SET, /* Kernel is providing the value */
+	KVP_USER_GET,  /* User is requesting the value */
+	KVP_USER_SET  /* User is providing the value */
+};
+
+struct hv_ku_msg {
+	__u32 kvp_index; /* Key index */
+	__u8  kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */
+	__u8  kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key  value */
+};
+
+
+
+
+#ifdef __KERNEL__
+
+/*
+ * Registry value types.
+ */
+
+#define REG_SZ 1
+
+enum hv_kvp_exchg_op {
+	KVP_OP_GET = 0,
+	KVP_OP_SET,
+	KVP_OP_DELETE,
+	KVP_OP_ENUMERATE,
+	KVP_OP_COUNT /* Number of operations, must be last. */
+};
+
+enum hv_kvp_exchg_pool {
+	KVP_POOL_EXTERNAL = 0,
+	KVP_POOL_GUEST,
+	KVP_POOL_AUTO,
+	KVP_POOL_AUTO_EXTERNAL,
+	KVP_POOL_AUTO_INTERNAL,
+	KVP_POOL_COUNT /* Number of pools, must be last. */
+};
+
+struct hv_kvp_hdr {
+	u8 operation;
+	u8 pool;
+};
+
+struct hv_kvp_exchg_msg_value {
+	u32 value_type;
+	u32 key_size;
+	u32 value_size;
+	u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
+	u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
+};
+
+struct hv_kvp_msg_enumerate {
+	u32 index;
+	struct hv_kvp_exchg_msg_value data;
+};
+
+struct hv_kvp_msg {
+	struct hv_kvp_hdr	kvp_hdr;
+	struct hv_kvp_msg_enumerate	kvp_data;
+};
+
+int hv_kvp_init(struct hv_util_service *);
+void hv_kvp_deinit(void);
+void hv_kvp_onchannelcallback(void *);
+
+#endif /* __KERNEL__ */
+#endif	/* _KVP_H */
+
diff -druN linux-libre-3.1-gnu/drivers/hv/hv_util.c linux-libre-3.2-gnu/drivers/hv/hv_util.c
--- linux-libre-3.1-gnu/drivers/hv/hv_util.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hv/hv_util.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2010, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/sysctl.h>
+#include <linux/reboot.h>
+#include <linux/hyperv.h>
+
+#include "hv_kvp.h"
+
+
+static void shutdown_onchannelcallback(void *context);
+static struct hv_util_service util_shutdown = {
+	.util_cb = shutdown_onchannelcallback,
+};
+
+static void timesync_onchannelcallback(void *context);
+static struct hv_util_service util_timesynch = {
+	.util_cb = timesync_onchannelcallback,
+};
+
+static void heartbeat_onchannelcallback(void *context);
+static struct hv_util_service util_heartbeat = {
+	.util_cb = heartbeat_onchannelcallback,
+};
+
+static struct hv_util_service util_kvp = {
+	.util_cb = hv_kvp_onchannelcallback,
+	.util_init = hv_kvp_init,
+	.util_deinit = hv_kvp_deinit,
+};
+
+static void shutdown_onchannelcallback(void *context)
+{
+	struct vmbus_channel *channel = context;
+	u32 recvlen;
+	u64 requestid;
+	u8  execute_shutdown = false;
+	u8  *shut_txf_buf = util_shutdown.recv_buffer;
+
+	struct shutdown_msg_data *shutdown_msg;
+
+	struct icmsg_hdr *icmsghdrp;
+	struct icmsg_negotiate *negop = NULL;
+
+	vmbus_recvpacket(channel, shut_txf_buf,
+			 PAGE_SIZE, &recvlen, &requestid);
+
+	if (recvlen > 0) {
+		icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[
+			sizeof(struct vmbuspipe_hdr)];
+
+		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+			vmbus_prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf);
+		} else {
+			shutdown_msg =
+				(struct shutdown_msg_data *)&shut_txf_buf[
+					sizeof(struct vmbuspipe_hdr) +
+					sizeof(struct icmsg_hdr)];
+
+			switch (shutdown_msg->flags) {
+			case 0:
+			case 1:
+				icmsghdrp->status = HV_S_OK;
+				execute_shutdown = true;
+
+				pr_info("Shutdown request received -"
+					    " graceful shutdown initiated\n");
+				break;
+			default:
+				icmsghdrp->status = HV_E_FAIL;
+				execute_shutdown = false;
+
+				pr_info("Shutdown request received -"
+					    " Invalid request\n");
+				break;
+			}
+		}
+
+		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+			| ICMSGHDRFLAG_RESPONSE;
+
+		vmbus_sendpacket(channel, shut_txf_buf,
+				       recvlen, requestid,
+				       VM_PKT_DATA_INBAND, 0);
+	}
+
+	if (execute_shutdown == true)
+		orderly_poweroff(true);
+}
+
+/*
+ * Set guest time to host UTC time.
+ */
+static inline void do_adj_guesttime(u64 hosttime)
+{
+	s64 host_tns;
+	struct timespec host_ts;
+
+	host_tns = (hosttime - WLTIMEDELTA) * 100;
+	host_ts = ns_to_timespec(host_tns);
+
+	do_settimeofday(&host_ts);
+}
+
+/*
+ * Set the host time in a process context.
+ */
+
+struct adj_time_work {
+	struct work_struct work;
+	u64	host_time;
+};
+
+static void hv_set_host_time(struct work_struct *work)
+{
+	struct adj_time_work	*wrk;
+
+	wrk = container_of(work, struct adj_time_work, work);
+	do_adj_guesttime(wrk->host_time);
+	kfree(wrk);
+}
+
+/*
+ * Synchronize time with host after reboot, restore, etc.
+ *
+ * ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM.
+ * After reboot the flag ICTIMESYNCFLAG_SYNC is included in the first time
+ * message after the timesync channel is opened. Since the hv_utils module is
+ * loaded after hv_vmbus, the first message is usually missed. The other
+ * thing is, systime is automatically set to emulated hardware clock which may
+ * not be UTC time or in the same time zone. So, to override these effects, we
+ * use the first 50 time samples for initial system time setting.
+ */
+static inline void adj_guesttime(u64 hosttime, u8 flags)
+{
+	struct adj_time_work    *wrk;
+	static s32 scnt = 50;
+
+	wrk = kmalloc(sizeof(struct adj_time_work), GFP_ATOMIC);
+	if (wrk == NULL)
+		return;
+
+	wrk->host_time = hosttime;
+	if ((flags & ICTIMESYNCFLAG_SYNC) != 0) {
+		INIT_WORK(&wrk->work, hv_set_host_time);
+		schedule_work(&wrk->work);
+		return;
+	}
+
+	if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 && scnt > 0) {
+		scnt--;
+		INIT_WORK(&wrk->work, hv_set_host_time);
+		schedule_work(&wrk->work);
+	} else
+		kfree(wrk);
+}
+
+/*
+ * Time Sync Channel message handler.
+ */
+static void timesync_onchannelcallback(void *context)
+{
+	struct vmbus_channel *channel = context;
+	u32 recvlen;
+	u64 requestid;
+	struct icmsg_hdr *icmsghdrp;
+	struct ictimesync_data *timedatap;
+	u8 *time_txf_buf = util_timesynch.recv_buffer;
+
+	vmbus_recvpacket(channel, time_txf_buf,
+			 PAGE_SIZE, &recvlen, &requestid);
+
+	if (recvlen > 0) {
+		icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
+				sizeof(struct vmbuspipe_hdr)];
+
+		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+			vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf);
+		} else {
+			timedatap = (struct ictimesync_data *)&time_txf_buf[
+				sizeof(struct vmbuspipe_hdr) +
+				sizeof(struct icmsg_hdr)];
+			adj_guesttime(timedatap->parenttime, timedatap->flags);
+		}
+
+		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+			| ICMSGHDRFLAG_RESPONSE;
+
+		vmbus_sendpacket(channel, time_txf_buf,
+				recvlen, requestid,
+				VM_PKT_DATA_INBAND, 0);
+	}
+}
+
+/*
+ * Heartbeat functionality.
+ * Every two seconds, Hyper-V send us a heartbeat request message.
+ * we respond to this message, and Hyper-V knows we are alive.
+ */
+static void heartbeat_onchannelcallback(void *context)
+{
+	struct vmbus_channel *channel = context;
+	u32 recvlen;
+	u64 requestid;
+	struct icmsg_hdr *icmsghdrp;
+	struct heartbeat_msg_data *heartbeat_msg;
+	u8 *hbeat_txf_buf = util_heartbeat.recv_buffer;
+
+	vmbus_recvpacket(channel, hbeat_txf_buf,
+			 PAGE_SIZE, &recvlen, &requestid);
+
+	if (recvlen > 0) {
+		icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
+				sizeof(struct vmbuspipe_hdr)];
+
+		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+			vmbus_prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf);
+		} else {
+			heartbeat_msg =
+				(struct heartbeat_msg_data *)&hbeat_txf_buf[
+					sizeof(struct vmbuspipe_hdr) +
+					sizeof(struct icmsg_hdr)];
+
+			heartbeat_msg->seq_num += 1;
+		}
+
+		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+			| ICMSGHDRFLAG_RESPONSE;
+
+		vmbus_sendpacket(channel, hbeat_txf_buf,
+				       recvlen, requestid,
+				       VM_PKT_DATA_INBAND, 0);
+	}
+}
+
+static int util_probe(struct hv_device *dev,
+			const struct hv_vmbus_device_id *dev_id)
+{
+	struct hv_util_service *srv =
+		(struct hv_util_service *)dev_id->driver_data;
+	int ret;
+
+	srv->recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!srv->recv_buffer)
+		return -ENOMEM;
+	if (srv->util_init) {
+		ret = srv->util_init(srv);
+		if (ret) {
+			ret = -ENODEV;
+			goto error1;
+		}
+	}
+
+	ret = vmbus_open(dev->channel, 2 * PAGE_SIZE, 2 * PAGE_SIZE, NULL, 0,
+			srv->util_cb, dev->channel);
+	if (ret)
+		goto error;
+
+	hv_set_drvdata(dev, srv);
+	return 0;
+
+error:
+	if (srv->util_deinit)
+		srv->util_deinit();
+error1:
+	kfree(srv->recv_buffer);
+	return ret;
+}
+
+static int util_remove(struct hv_device *dev)
+{
+	struct hv_util_service *srv = hv_get_drvdata(dev);
+
+	vmbus_close(dev->channel);
+	if (srv->util_deinit)
+		srv->util_deinit();
+	kfree(srv->recv_buffer);
+
+	return 0;
+}
+
+static const struct hv_vmbus_device_id id_table[] = {
+	/* Shutdown guid */
+	{ VMBUS_DEVICE(0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
+		       0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB)
+	  .driver_data = (unsigned long)&util_shutdown },
+	/* Time synch guid */
+	{ VMBUS_DEVICE(0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
+		       0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf)
+	  .driver_data = (unsigned long)&util_timesynch },
+	/* Heartbeat guid */
+	{ VMBUS_DEVICE(0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
+		       0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d)
+	  .driver_data = (unsigned long)&util_heartbeat },
+	/* KVP guid */
+	{ VMBUS_DEVICE(0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
+		       0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3,  0xe6)
+	  .driver_data = (unsigned long)&util_kvp },
+	{ },
+};
+
+MODULE_DEVICE_TABLE(vmbus, id_table);
+
+/* The one and only one */
+static  struct hv_driver util_drv = {
+	.name = "hv_util",
+	.id_table = id_table,
+	.probe =  util_probe,
+	.remove =  util_remove,
+};
+
+static int __init init_hyperv_utils(void)
+{
+	pr_info("Registering HyperV Utility Driver\n");
+
+	return vmbus_driver_register(&util_drv);
+}
+
+static void exit_hyperv_utils(void)
+{
+	pr_info("De-Registered HyperV Utility Driver\n");
+
+	vmbus_driver_unregister(&util_drv);
+}
+
+module_init(init_hyperv_utils);
+module_exit(exit_hyperv_utils);
+
+MODULE_DESCRIPTION("Hyper-V Utilities");
+MODULE_VERSION(HV_DRV_VERSION);
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/hv/hyperv_vmbus.h linux-libre-3.2-gnu/drivers/hv/hyperv_vmbus.h
--- linux-libre-3.1-gnu/drivers/hv/hyperv_vmbus.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hv/hyperv_vmbus.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,626 @@
+/*
+ *
+ * Copyright (c) 2011, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
+ *
+ */
+
+#ifndef _HYPERV_VMBUS_H
+#define _HYPERV_VMBUS_H
+
+#include <linux/list.h>
+#include <asm/sync_bitops.h>
+#include <linux/atomic.h>
+#include <linux/hyperv.h>
+
+/*
+ * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
+ * is set by CPUID(HVCPUID_VERSION_FEATURES).
+ */
+enum hv_cpuid_function {
+	HVCPUID_VERSION_FEATURES		= 0x00000001,
+	HVCPUID_VENDOR_MAXFUNCTION		= 0x40000000,
+	HVCPUID_INTERFACE			= 0x40000001,
+
+	/*
+	 * The remaining functions depend on the value of
+	 * HVCPUID_INTERFACE
+	 */
+	HVCPUID_VERSION			= 0x40000002,
+	HVCPUID_FEATURES			= 0x40000003,
+	HVCPUID_ENLIGHTENMENT_INFO	= 0x40000004,
+	HVCPUID_IMPLEMENTATION_LIMITS		= 0x40000005,
+};
+
+/* Define version of the synthetic interrupt controller. */
+#define HV_SYNIC_VERSION		(1)
+
+/* Define the expected SynIC version. */
+#define HV_SYNIC_VERSION_1		(0x1)
+
+/* Define synthetic interrupt controller message constants. */
+#define HV_MESSAGE_SIZE			(256)
+#define HV_MESSAGE_PAYLOAD_BYTE_COUNT	(240)
+#define HV_MESSAGE_PAYLOAD_QWORD_COUNT	(30)
+#define HV_ANY_VP			(0xFFFFFFFF)
+
+/* Define synthetic interrupt controller flag constants. */
+#define HV_EVENT_FLAGS_COUNT		(256 * 8)
+#define HV_EVENT_FLAGS_BYTE_COUNT	(256)
+#define HV_EVENT_FLAGS_DWORD_COUNT	(256 / sizeof(u32))
+
+/* Define hypervisor message types. */
+enum hv_message_type {
+	HVMSG_NONE			= 0x00000000,
+
+	/* Memory access messages. */
+	HVMSG_UNMAPPED_GPA		= 0x80000000,
+	HVMSG_GPA_INTERCEPT		= 0x80000001,
+
+	/* Timer notification messages. */
+	HVMSG_TIMER_EXPIRED			= 0x80000010,
+
+	/* Error messages. */
+	HVMSG_INVALID_VP_REGISTER_VALUE	= 0x80000020,
+	HVMSG_UNRECOVERABLE_EXCEPTION	= 0x80000021,
+	HVMSG_UNSUPPORTED_FEATURE		= 0x80000022,
+
+	/* Trace buffer complete messages. */
+	HVMSG_EVENTLOG_BUFFERCOMPLETE	= 0x80000040,
+
+	/* Platform-specific processor intercept messages. */
+	HVMSG_X64_IOPORT_INTERCEPT		= 0x80010000,
+	HVMSG_X64_MSR_INTERCEPT		= 0x80010001,
+	HVMSG_X64_CPUID_INTERCEPT		= 0x80010002,
+	HVMSG_X64_EXCEPTION_INTERCEPT	= 0x80010003,
+	HVMSG_X64_APIC_EOI			= 0x80010004,
+	HVMSG_X64_LEGACY_FP_ERROR		= 0x80010005
+};
+
+/* Define the number of synthetic interrupt sources. */
+#define HV_SYNIC_SINT_COUNT		(16)
+#define HV_SYNIC_STIMER_COUNT		(4)
+
+/* Define invalid partition identifier. */
+#define HV_PARTITION_ID_INVALID		((u64)0x0)
+
+/* Define connection identifier type. */
+union hv_connection_id {
+	u32 asu32;
+	struct {
+		u32 id:24;
+		u32 reserved:8;
+	} u;
+};
+
+/* Define port identifier type. */
+union hv_port_id {
+	u32 asu32;
+	struct {
+		u32 id:24;
+		u32 reserved:8;
+	} u ;
+};
+
+/* Define port type. */
+enum hv_port_type {
+	HVPORT_MSG	= 1,
+	HVPORT_EVENT		= 2,
+	HVPORT_MONITOR	= 3
+};
+
+/* Define port information structure. */
+struct hv_port_info {
+	enum hv_port_type port_type;
+	u32 padding;
+	union {
+		struct {
+			u32 target_sint;
+			u32 target_vp;
+			u64 rsvdz;
+		} message_port_info;
+		struct {
+			u32 target_sint;
+			u32 target_vp;
+			u16 base_flag_bumber;
+			u16 flag_count;
+			u32 rsvdz;
+		} event_port_info;
+		struct {
+			u64 monitor_address;
+			u64 rsvdz;
+		} monitor_port_info;
+	};
+};
+
+struct hv_connection_info {
+	enum hv_port_type port_type;
+	u32 padding;
+	union {
+		struct {
+			u64 rsvdz;
+		} message_connection_info;
+		struct {
+			u64 rsvdz;
+		} event_connection_info;
+		struct {
+			u64 monitor_address;
+		} monitor_connection_info;
+	};
+};
+
+/* Define synthetic interrupt controller message flags. */
+union hv_message_flags {
+	u8 asu8;
+	struct {
+		u8 msg_pending:1;
+		u8 reserved:7;
+	};
+};
+
+/* Define synthetic interrupt controller message header. */
+struct hv_message_header {
+	enum hv_message_type message_type;
+	u8 payload_size;
+	union hv_message_flags message_flags;
+	u8 reserved[2];
+	union {
+		u64 sender;
+		union hv_port_id port;
+	};
+};
+
+/* Define timer message payload structure. */
+struct hv_timer_message_payload {
+	u32 timer_index;
+	u32 reserved;
+	u64 expiration_time;	/* When the timer expired */
+	u64 delivery_time;	/* When the message was delivered */
+};
+
+/* Define synthetic interrupt controller message format. */
+struct hv_message {
+	struct hv_message_header header;
+	union {
+		u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
+	} u ;
+};
+
+/* Define the number of message buffers associated with each port. */
+#define HV_PORT_MESSAGE_BUFFER_COUNT	(16)
+
+/* Define the synthetic interrupt message page layout. */
+struct hv_message_page {
+	struct hv_message sint_message[HV_SYNIC_SINT_COUNT];
+};
+
+/* Define the synthetic interrupt controller event flags format. */
+union hv_synic_event_flags {
+	u8 flags8[HV_EVENT_FLAGS_BYTE_COUNT];
+	u32 flags32[HV_EVENT_FLAGS_DWORD_COUNT];
+};
+
+/* Define the synthetic interrupt flags page layout. */
+struct hv_synic_event_flags_page {
+	union hv_synic_event_flags sintevent_flags[HV_SYNIC_SINT_COUNT];
+};
+
+/* Define SynIC control register. */
+union hv_synic_scontrol {
+	u64 as_uint64;
+	struct {
+		u64 enable:1;
+		u64 reserved:63;
+	};
+};
+
+/* Define synthetic interrupt source. */
+union hv_synic_sint {
+	u64 as_uint64;
+	struct {
+		u64 vector:8;
+		u64 reserved1:8;
+		u64 masked:1;
+		u64 auto_eoi:1;
+		u64 reserved2:46;
+	};
+};
+
+/* Define the format of the SIMP register */
+union hv_synic_simp {
+	u64 as_uint64;
+	struct {
+		u64 simp_enabled:1;
+		u64 preserved:11;
+		u64 base_simp_gpa:52;
+	};
+};
+
+/* Define the format of the SIEFP register */
+union hv_synic_siefp {
+	u64 as_uint64;
+	struct {
+		u64 siefp_enabled:1;
+		u64 preserved:11;
+		u64 base_siefp_gpa:52;
+	};
+};
+
+/* Definitions for the monitored notification facility */
+union hv_monitor_trigger_group {
+	u64 as_uint64;
+	struct {
+		u32 pending;
+		u32 armed;
+	};
+};
+
+struct hv_monitor_parameter {
+	union hv_connection_id connectionid;
+	u16 flagnumber;
+	u16 rsvdz;
+};
+
+union hv_monitor_trigger_state {
+	u32 asu32;
+
+	struct {
+		u32 group_enable:4;
+		u32 rsvdz:28;
+	};
+};
+
+/* struct hv_monitor_page Layout */
+/* ------------------------------------------------------ */
+/* | 0   | TriggerState (4 bytes) | Rsvd1 (4 bytes)     | */
+/* | 8   | TriggerGroup[0]                              | */
+/* | 10  | TriggerGroup[1]                              | */
+/* | 18  | TriggerGroup[2]                              | */
+/* | 20  | TriggerGroup[3]                              | */
+/* | 28  | Rsvd2[0]                                     | */
+/* | 30  | Rsvd2[1]                                     | */
+/* | 38  | Rsvd2[2]                                     | */
+/* | 40  | NextCheckTime[0][0]    | NextCheckTime[0][1] | */
+/* | ...                                                | */
+/* | 240 | Latency[0][0..3]                             | */
+/* | 340 | Rsvz3[0]                                     | */
+/* | 440 | Parameter[0][0]                              | */
+/* | 448 | Parameter[0][1]                              | */
+/* | ...                                                | */
+/* | 840 | Rsvd4[0]                                     | */
+/* ------------------------------------------------------ */
+struct hv_monitor_page {
+	union hv_monitor_trigger_state trigger_state;
+	u32 rsvdz1;
+
+	union hv_monitor_trigger_group trigger_group[4];
+	u64 rsvdz2[3];
+
+	s32 next_checktime[4][32];
+
+	u16 latency[4][32];
+	u64 rsvdz3[32];
+
+	struct hv_monitor_parameter parameter[4][32];
+
+	u8 rsvdz4[1984];
+};
+
+/* Declare the various hypercall operations. */
+enum hv_call_code {
+	HVCALL_POST_MESSAGE	= 0x005c,
+	HVCALL_SIGNAL_EVENT	= 0x005d,
+};
+
+/* Definition of the hv_post_message hypercall input structure. */
+struct hv_input_post_message {
+	union hv_connection_id connectionid;
+	u32 reserved;
+	enum hv_message_type message_type;
+	u32 payload_size;
+	u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
+};
+
+/* Definition of the hv_signal_event hypercall input structure. */
+struct hv_input_signal_event {
+	union hv_connection_id connectionid;
+	u16 flag_number;
+	u16 rsvdz;
+};
+
+/*
+ * Versioning definitions used for guests reporting themselves to the
+ * hypervisor, and visa versa.
+ */
+
+/* Version info reported by guest OS's */
+enum hv_guest_os_vendor {
+	HVGUESTOS_VENDOR_MICROSOFT	= 0x0001
+};
+
+enum hv_guest_os_microsoft_ids {
+	HVGUESTOS_MICROSOFT_UNDEFINED	= 0x00,
+	HVGUESTOS_MICROSOFT_MSDOS		= 0x01,
+	HVGUESTOS_MICROSOFT_WINDOWS3X	= 0x02,
+	HVGUESTOS_MICROSOFT_WINDOWS9X	= 0x03,
+	HVGUESTOS_MICROSOFT_WINDOWSNT	= 0x04,
+	HVGUESTOS_MICROSOFT_WINDOWSCE	= 0x05
+};
+
+/*
+ * Declare the MSR used to identify the guest OS.
+ */
+#define HV_X64_MSR_GUEST_OS_ID	0x40000000
+
+union hv_x64_msr_guest_os_id_contents {
+	u64 as_uint64;
+	struct {
+		u64 build_number:16;
+		u64 service_version:8; /* Service Pack, etc. */
+		u64 minor_version:8;
+		u64 major_version:8;
+		u64 os_id:8; /* enum hv_guest_os_microsoft_ids (if Vendor=MS) */
+		u64 vendor_id:16; /* enum hv_guest_os_vendor */
+	};
+};
+
+/*
+ * Declare the MSR used to setup pages used to communicate with the hypervisor.
+ */
+#define HV_X64_MSR_HYPERCALL	0x40000001
+
+union hv_x64_msr_hypercall_contents {
+	u64 as_uint64;
+	struct {
+		u64 enable:1;
+		u64 reserved:11;
+		u64 guest_physical_address:52;
+	};
+};
+
+
+enum {
+	VMBUS_MESSAGE_CONNECTION_ID	= 1,
+	VMBUS_MESSAGE_PORT_ID		= 1,
+	VMBUS_EVENT_CONNECTION_ID	= 2,
+	VMBUS_EVENT_PORT_ID		= 2,
+	VMBUS_MONITOR_CONNECTION_ID	= 3,
+	VMBUS_MONITOR_PORT_ID		= 3,
+	VMBUS_MESSAGE_SINT		= 2,
+};
+
+/* #defines */
+
+#define HV_PRESENT_BIT			0x80000000
+
+#define HV_LINUX_GUEST_ID_LO		0x00000000
+#define HV_LINUX_GUEST_ID_HI		0xB16B00B5
+#define HV_LINUX_GUEST_ID		(((u64)HV_LINUX_GUEST_ID_HI << 32) | \
+					   HV_LINUX_GUEST_ID_LO)
+
+#define HV_CPU_POWER_MANAGEMENT		(1 << 0)
+#define HV_RECOMMENDATIONS_MAX		4
+
+#define HV_X64_MAX			5
+#define HV_CAPS_MAX			8
+
+
+#define HV_HYPERCALL_PARAM_ALIGN	sizeof(u64)
+
+
+/* Service definitions */
+
+#define HV_SERVICE_PARENT_PORT				(0)
+#define HV_SERVICE_PARENT_CONNECTION			(0)
+
+#define HV_SERVICE_CONNECT_RESPONSE_SUCCESS		(0)
+#define HV_SERVICE_CONNECT_RESPONSE_INVALID_PARAMETER	(1)
+#define HV_SERVICE_CONNECT_RESPONSE_UNKNOWN_SERVICE	(2)
+#define HV_SERVICE_CONNECT_RESPONSE_CONNECTION_REJECTED	(3)
+
+#define HV_SERVICE_CONNECT_REQUEST_MESSAGE_ID		(1)
+#define HV_SERVICE_CONNECT_RESPONSE_MESSAGE_ID		(2)
+#define HV_SERVICE_DISCONNECT_REQUEST_MESSAGE_ID	(3)
+#define HV_SERVICE_DISCONNECT_RESPONSE_MESSAGE_ID	(4)
+#define HV_SERVICE_MAX_MESSAGE_ID				(4)
+
+#define HV_SERVICE_PROTOCOL_VERSION (0x0010)
+#define HV_CONNECT_PAYLOAD_BYTE_COUNT 64
+
+/* #define VMBUS_REVISION_NUMBER	6 */
+
+/* Our local vmbus's port and connection id. Anything >0 is fine */
+/* #define VMBUS_PORT_ID		11 */
+
+/* 628180B8-308D-4c5e-B7DB-1BEB62E62EF4 */
+static const uuid_le VMBUS_SERVICE_ID = {
+	.b = {
+		0xb8, 0x80, 0x81, 0x62, 0x8d, 0x30, 0x5e, 0x4c,
+		0xb7, 0xdb, 0x1b, 0xeb, 0x62, 0xe6, 0x2e, 0xf4
+	},
+};
+
+#define MAX_NUM_CPUS	32
+
+
+struct hv_input_signal_event_buffer {
+	u64 align8;
+	struct hv_input_signal_event event;
+};
+
+struct hv_context {
+	/* We only support running on top of Hyper-V
+	* So at this point this really can only contain the Hyper-V ID
+	*/
+	u64 guestid;
+
+	void *hypercall_page;
+
+	bool synic_initialized;
+
+	/*
+	 * This is used as an input param to HvCallSignalEvent hypercall. The
+	 * input param is immutable in our usage and must be dynamic mem (vs
+	 * stack or global). */
+	struct hv_input_signal_event_buffer *signal_event_buffer;
+	/* 8-bytes aligned of the buffer above */
+	struct hv_input_signal_event *signal_event_param;
+
+	void *synic_message_page[MAX_NUM_CPUS];
+	void *synic_event_page[MAX_NUM_CPUS];
+};
+
+extern struct hv_context hv_context;
+
+
+/* Hv Interface */
+
+extern int hv_init(void);
+
+extern void hv_cleanup(void);
+
+extern u16 hv_post_message(union hv_connection_id connection_id,
+			 enum hv_message_type message_type,
+			 void *payload, size_t payload_size);
+
+extern u16 hv_signal_event(void);
+
+extern void hv_synic_init(void *irqarg);
+
+extern void hv_synic_cleanup(void *arg);
+
+
+/* Interface */
+
+
+int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, void *buffer,
+		   u32 buflen);
+
+void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info);
+
+int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info,
+		    struct scatterlist *sglist,
+		    u32 sgcount);
+
+int hv_ringbuffer_peek(struct hv_ring_buffer_info *ring_info, void *buffer,
+		   u32 buflen);
+
+int hv_ringbuffer_read(struct hv_ring_buffer_info *ring_info,
+		   void *buffer,
+		   u32 buflen,
+		   u32 offset);
+
+u32 hv_get_ringbuffer_interrupt_mask(struct hv_ring_buffer_info *ring_info);
+
+void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
+			    struct hv_ring_buffer_debug_info *debug_info);
+
+/*
+ * Maximum channels is determined by the size of the interrupt page
+ * which is PAGE_SIZE. 1/2 of PAGE_SIZE is for send endpoint interrupt
+ * and the other is receive endpoint interrupt
+ */
+#define MAX_NUM_CHANNELS	((PAGE_SIZE >> 1) << 3)	/* 16348 channels */
+
+/* The value here must be in multiple of 32 */
+/* TODO: Need to make this configurable */
+#define MAX_NUM_CHANNELS_SUPPORTED	256
+
+
+enum vmbus_connect_state {
+	DISCONNECTED,
+	CONNECTING,
+	CONNECTED,
+	DISCONNECTING
+};
+
+#define MAX_SIZE_CHANNEL_MESSAGE	HV_MESSAGE_PAYLOAD_BYTE_COUNT
+
+struct vmbus_connection {
+	enum vmbus_connect_state conn_state;
+
+	atomic_t next_gpadl_handle;
+
+	/*
+	 * Represents channel interrupts. Each bit position represents a
+	 * channel.  When a channel sends an interrupt via VMBUS, it finds its
+	 * bit in the sendInterruptPage, set it and calls Hv to generate a port
+	 * event. The other end receives the port event and parse the
+	 * recvInterruptPage to see which bit is set
+	 */
+	void *int_page;
+	void *send_int_page;
+	void *recv_int_page;
+
+	/*
+	 * 2 pages - 1st page for parent->child notification and 2nd
+	 * is child->parent notification
+	 */
+	void *monitor_pages;
+	struct list_head chn_msg_list;
+	spinlock_t channelmsg_lock;
+
+	/* List of channels */
+	struct list_head chn_list;
+	spinlock_t channel_lock;
+
+	struct workqueue_struct *work_queue;
+};
+
+
+struct vmbus_msginfo {
+	/* Bookkeeping stuff */
+	struct list_head msglist_entry;
+
+	/* The message itself */
+	unsigned char msg[0];
+};
+
+
+extern struct vmbus_connection vmbus_connection;
+
+/* General vmbus interface */
+
+struct hv_device *vmbus_device_create(uuid_le *type,
+					 uuid_le *instance,
+					 struct vmbus_channel *channel);
+
+int vmbus_device_register(struct hv_device *child_device_obj);
+void vmbus_device_unregister(struct hv_device *device_obj);
+
+/* static void */
+/* VmbusChildDeviceDestroy( */
+/* struct hv_device *); */
+
+struct vmbus_channel *relid2channel(u32 relid);
+
+
+/* Connection interface */
+
+int vmbus_connect(void);
+
+int vmbus_post_msg(void *buffer, size_t buflen);
+
+int vmbus_set_event(u32 child_relid);
+
+void vmbus_on_event(unsigned long data);
+
+
+#endif /* _HYPERV_VMBUS_H */
diff -druN linux-libre-3.1-gnu/drivers/hv/Kconfig linux-libre-3.2-gnu/drivers/hv/Kconfig
--- linux-libre-3.1-gnu/drivers/hv/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hv/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,14 @@
+config HYPERV
+	tristate "Microsoft Hyper-V client drivers"
+	depends on X86 && ACPI && PCI
+	help
+	  Select this option to run Linux as a Hyper-V client operating
+	  system.
+
+config HYPERV_UTILS
+	tristate "Microsoft Hyper-V Utilities driver"
+	depends on HYPERV && CONNECTOR && NLS
+	help
+	  Select this option to enable the Hyper-V Utilities.
+
+
diff -druN linux-libre-3.1-gnu/drivers/hv/Makefile linux-libre-3.2-gnu/drivers/hv/Makefile
--- linux-libre-3.1-gnu/drivers/hv/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hv/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,7 @@
+obj-$(CONFIG_HYPERV)		+= hv_vmbus.o
+obj-$(CONFIG_HYPERV_UTILS)	+= hv_utils.o
+
+hv_vmbus-y := vmbus_drv.o \
+		 hv.o connection.o channel.o \
+		 channel_mgmt.o ring_buffer.o
+hv_utils-y := hv_util.o hv_kvp.o
diff -druN linux-libre-3.1-gnu/drivers/hv/ring_buffer.c linux-libre-3.2-gnu/drivers/hv/ring_buffer.c
--- linux-libre-3.1-gnu/drivers/hv/ring_buffer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hv/ring_buffer.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,496 @@
+/*
+ *
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/hyperv.h>
+
+#include "hyperv_vmbus.h"
+
+
+/* #defines */
+
+
+/* Amount of space to write to */
+#define BYTES_AVAIL_TO_WRITE(r, w, z) \
+	((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w))
+
+
+/*
+ *
+ * hv_get_ringbuffer_availbytes()
+ *
+ * Get number of bytes available to read and to write to
+ * for the specified ring buffer
+ */
+static inline void
+hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi,
+			  u32 *read, u32 *write)
+{
+	u32 read_loc, write_loc;
+
+	smp_read_barrier_depends();
+
+	/* Capture the read/write indices before they changed */
+	read_loc = rbi->ring_buffer->read_index;
+	write_loc = rbi->ring_buffer->write_index;
+
+	*write = BYTES_AVAIL_TO_WRITE(read_loc, write_loc, rbi->ring_datasize);
+	*read = rbi->ring_datasize - *write;
+}
+
+/*
+ * hv_get_next_write_location()
+ *
+ * Get the next write location for the specified ring buffer
+ *
+ */
+static inline u32
+hv_get_next_write_location(struct hv_ring_buffer_info *ring_info)
+{
+	u32 next = ring_info->ring_buffer->write_index;
+
+	return next;
+}
+
+/*
+ * hv_set_next_write_location()
+ *
+ * Set the next write location for the specified ring buffer
+ *
+ */
+static inline void
+hv_set_next_write_location(struct hv_ring_buffer_info *ring_info,
+		     u32 next_write_location)
+{
+	ring_info->ring_buffer->write_index = next_write_location;
+}
+
+/*
+ * hv_get_next_read_location()
+ *
+ * Get the next read location for the specified ring buffer
+ */
+static inline u32
+hv_get_next_read_location(struct hv_ring_buffer_info *ring_info)
+{
+	u32 next = ring_info->ring_buffer->read_index;
+
+	return next;
+}
+
+/*
+ * hv_get_next_readlocation_withoffset()
+ *
+ * Get the next read location + offset for the specified ring buffer.
+ * This allows the caller to skip
+ */
+static inline u32
+hv_get_next_readlocation_withoffset(struct hv_ring_buffer_info *ring_info,
+				 u32 offset)
+{
+	u32 next = ring_info->ring_buffer->read_index;
+
+	next += offset;
+	next %= ring_info->ring_datasize;
+
+	return next;
+}
+
+/*
+ *
+ * hv_set_next_read_location()
+ *
+ * Set the next read location for the specified ring buffer
+ *
+ */
+static inline void
+hv_set_next_read_location(struct hv_ring_buffer_info *ring_info,
+		    u32 next_read_location)
+{
+	ring_info->ring_buffer->read_index = next_read_location;
+}
+
+
+/*
+ *
+ * hv_get_ring_buffer()
+ *
+ * Get the start of the ring buffer
+ */
+static inline void *
+hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info)
+{
+	return (void *)ring_info->ring_buffer->buffer;
+}
+
+
+/*
+ *
+ * hv_get_ring_buffersize()
+ *
+ * Get the size of the ring buffer
+ */
+static inline u32
+hv_get_ring_buffersize(struct hv_ring_buffer_info *ring_info)
+{
+	return ring_info->ring_datasize;
+}
+
+/*
+ *
+ * hv_get_ring_bufferindices()
+ *
+ * Get the read and write indices as u64 of the specified ring buffer
+ *
+ */
+static inline u64
+hv_get_ring_bufferindices(struct hv_ring_buffer_info *ring_info)
+{
+	return (u64)ring_info->ring_buffer->write_index << 32;
+}
+
+/*
+ *
+ * hv_copyfrom_ringbuffer()
+ *
+ * Helper routine to copy to source from ring buffer.
+ * Assume there is enough room. Handles wrap-around in src case only!!
+ *
+ */
+static u32 hv_copyfrom_ringbuffer(
+	struct hv_ring_buffer_info	*ring_info,
+	void				*dest,
+	u32				destlen,
+	u32				start_read_offset)
+{
+	void *ring_buffer = hv_get_ring_buffer(ring_info);
+	u32 ring_buffer_size = hv_get_ring_buffersize(ring_info);
+
+	u32 frag_len;
+
+	/* wrap-around detected at the src */
+	if (destlen > ring_buffer_size - start_read_offset) {
+		frag_len = ring_buffer_size - start_read_offset;
+
+		memcpy(dest, ring_buffer + start_read_offset, frag_len);
+		memcpy(dest + frag_len, ring_buffer, destlen - frag_len);
+	} else
+
+		memcpy(dest, ring_buffer + start_read_offset, destlen);
+
+
+	start_read_offset += destlen;
+	start_read_offset %= ring_buffer_size;
+
+	return start_read_offset;
+}
+
+
+/*
+ *
+ * hv_copyto_ringbuffer()
+ *
+ * Helper routine to copy from source to ring buffer.
+ * Assume there is enough room. Handles wrap-around in dest case only!!
+ *
+ */
+static u32 hv_copyto_ringbuffer(
+	struct hv_ring_buffer_info	*ring_info,
+	u32				start_write_offset,
+	void				*src,
+	u32				srclen)
+{
+	void *ring_buffer = hv_get_ring_buffer(ring_info);
+	u32 ring_buffer_size = hv_get_ring_buffersize(ring_info);
+	u32 frag_len;
+
+	/* wrap-around detected! */
+	if (srclen > ring_buffer_size - start_write_offset) {
+		frag_len = ring_buffer_size - start_write_offset;
+		memcpy(ring_buffer + start_write_offset, src, frag_len);
+		memcpy(ring_buffer, src + frag_len, srclen - frag_len);
+	} else
+		memcpy(ring_buffer + start_write_offset, src, srclen);
+
+	start_write_offset += srclen;
+	start_write_offset %= ring_buffer_size;
+
+	return start_write_offset;
+}
+
+/*
+ *
+ * hv_ringbuffer_get_debuginfo()
+ *
+ * Get various debug metrics for the specified ring buffer
+ *
+ */
+void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
+			    struct hv_ring_buffer_debug_info *debug_info)
+{
+	u32 bytes_avail_towrite;
+	u32 bytes_avail_toread;
+
+	if (ring_info->ring_buffer) {
+		hv_get_ringbuffer_availbytes(ring_info,
+					&bytes_avail_toread,
+					&bytes_avail_towrite);
+
+		debug_info->bytes_avail_toread = bytes_avail_toread;
+		debug_info->bytes_avail_towrite = bytes_avail_towrite;
+		debug_info->current_read_index =
+			ring_info->ring_buffer->read_index;
+		debug_info->current_write_index =
+			ring_info->ring_buffer->write_index;
+		debug_info->current_interrupt_mask =
+			ring_info->ring_buffer->interrupt_mask;
+	}
+}
+
+
+/*
+ *
+ * hv_get_ringbuffer_interrupt_mask()
+ *
+ * Get the interrupt mask for the specified ring buffer
+ *
+ */
+u32 hv_get_ringbuffer_interrupt_mask(struct hv_ring_buffer_info *rbi)
+{
+	return rbi->ring_buffer->interrupt_mask;
+}
+
+/*
+ *
+ * hv_ringbuffer_init()
+ *
+ *Initialize the ring buffer
+ *
+ */
+int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
+		   void *buffer, u32 buflen)
+{
+	if (sizeof(struct hv_ring_buffer) != PAGE_SIZE)
+		return -EINVAL;
+
+	memset(ring_info, 0, sizeof(struct hv_ring_buffer_info));
+
+	ring_info->ring_buffer = (struct hv_ring_buffer *)buffer;
+	ring_info->ring_buffer->read_index =
+		ring_info->ring_buffer->write_index = 0;
+
+	ring_info->ring_size = buflen;
+	ring_info->ring_datasize = buflen - sizeof(struct hv_ring_buffer);
+
+	spin_lock_init(&ring_info->ring_lock);
+
+	return 0;
+}
+
+/*
+ *
+ * hv_ringbuffer_cleanup()
+ *
+ * Cleanup the ring buffer
+ *
+ */
+void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info)
+{
+}
+
+/*
+ *
+ * hv_ringbuffer_write()
+ *
+ * Write to the ring buffer
+ *
+ */
+int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
+		    struct scatterlist *sglist, u32 sgcount)
+{
+	int i = 0;
+	u32 bytes_avail_towrite;
+	u32 bytes_avail_toread;
+	u32 totalbytes_towrite = 0;
+
+	struct scatterlist *sg;
+	u32 next_write_location;
+	u64 prev_indices = 0;
+	unsigned long flags;
+
+	for_each_sg(sglist, sg, sgcount, i)
+	{
+		totalbytes_towrite += sg->length;
+	}
+
+	totalbytes_towrite += sizeof(u64);
+
+	spin_lock_irqsave(&outring_info->ring_lock, flags);
+
+	hv_get_ringbuffer_availbytes(outring_info,
+				&bytes_avail_toread,
+				&bytes_avail_towrite);
+
+
+	/* If there is only room for the packet, assume it is full. */
+	/* Otherwise, the next time around, we think the ring buffer */
+	/* is empty since the read index == write index */
+	if (bytes_avail_towrite <= totalbytes_towrite) {
+		spin_unlock_irqrestore(&outring_info->ring_lock, flags);
+		return -EAGAIN;
+	}
+
+	/* Write to the ring buffer */
+	next_write_location = hv_get_next_write_location(outring_info);
+
+	for_each_sg(sglist, sg, sgcount, i)
+	{
+		next_write_location = hv_copyto_ringbuffer(outring_info,
+						     next_write_location,
+						     sg_virt(sg),
+						     sg->length);
+	}
+
+	/* Set previous packet start */
+	prev_indices = hv_get_ring_bufferindices(outring_info);
+
+	next_write_location = hv_copyto_ringbuffer(outring_info,
+					     next_write_location,
+					     &prev_indices,
+					     sizeof(u64));
+
+	/* Make sure we flush all writes before updating the writeIndex */
+	smp_wmb();
+
+	/* Now, update the write location */
+	hv_set_next_write_location(outring_info, next_write_location);
+
+
+	spin_unlock_irqrestore(&outring_info->ring_lock, flags);
+	return 0;
+}
+
+
+/*
+ *
+ * hv_ringbuffer_peek()
+ *
+ * Read without advancing the read index
+ *
+ */
+int hv_ringbuffer_peek(struct hv_ring_buffer_info *Inring_info,
+		   void *Buffer, u32 buflen)
+{
+	u32 bytes_avail_towrite;
+	u32 bytes_avail_toread;
+	u32 next_read_location = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&Inring_info->ring_lock, flags);
+
+	hv_get_ringbuffer_availbytes(Inring_info,
+				&bytes_avail_toread,
+				&bytes_avail_towrite);
+
+	/* Make sure there is something to read */
+	if (bytes_avail_toread < buflen) {
+
+		spin_unlock_irqrestore(&Inring_info->ring_lock, flags);
+
+		return -EAGAIN;
+	}
+
+	/* Convert to byte offset */
+	next_read_location = hv_get_next_read_location(Inring_info);
+
+	next_read_location = hv_copyfrom_ringbuffer(Inring_info,
+						Buffer,
+						buflen,
+						next_read_location);
+
+	spin_unlock_irqrestore(&Inring_info->ring_lock, flags);
+
+	return 0;
+}
+
+
+/*
+ *
+ * hv_ringbuffer_read()
+ *
+ * Read and advance the read index
+ *
+ */
+int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer,
+		   u32 buflen, u32 offset)
+{
+	u32 bytes_avail_towrite;
+	u32 bytes_avail_toread;
+	u32 next_read_location = 0;
+	u64 prev_indices = 0;
+	unsigned long flags;
+
+	if (buflen <= 0)
+		return -EINVAL;
+
+	spin_lock_irqsave(&inring_info->ring_lock, flags);
+
+	hv_get_ringbuffer_availbytes(inring_info,
+				&bytes_avail_toread,
+				&bytes_avail_towrite);
+
+	/* Make sure there is something to read */
+	if (bytes_avail_toread < buflen) {
+		spin_unlock_irqrestore(&inring_info->ring_lock, flags);
+
+		return -EAGAIN;
+	}
+
+	next_read_location =
+		hv_get_next_readlocation_withoffset(inring_info, offset);
+
+	next_read_location = hv_copyfrom_ringbuffer(inring_info,
+						buffer,
+						buflen,
+						next_read_location);
+
+	next_read_location = hv_copyfrom_ringbuffer(inring_info,
+						&prev_indices,
+						sizeof(u64),
+						next_read_location);
+
+	/* Make sure all reads are done before we update the read index since */
+	/* the writer may start writing to the read area once the read index */
+	/*is updated */
+	smp_mb();
+
+	/* Update the read index */
+	hv_set_next_read_location(inring_info, next_read_location);
+
+	spin_unlock_irqrestore(&inring_info->ring_lock, flags);
+
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/drivers/hv/vmbus_drv.c linux-libre-3.2-gnu/drivers/hv/vmbus_drv.c
--- linux-libre-3.1-gnu/drivers/hv/vmbus_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hv/vmbus_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,786 @@
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *   K. Y. Srinivasan <kys@microsoft.com>
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/sysctl.h>
+#include <linux/slab.h>
+#include <linux/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <linux/completion.h>
+#include <linux/hyperv.h>
+#include <asm/hyperv.h>
+#include "hyperv_vmbus.h"
+
+
+static struct acpi_device  *hv_acpi_dev;
+
+static struct tasklet_struct msg_dpc;
+static struct tasklet_struct event_dpc;
+static struct completion probe_event;
+static int irq;
+
+struct hv_device_info {
+	u32 chn_id;
+	u32 chn_state;
+	uuid_le chn_type;
+	uuid_le chn_instance;
+
+	u32 monitor_id;
+	u32 server_monitor_pending;
+	u32 server_monitor_latency;
+	u32 server_monitor_conn_id;
+	u32 client_monitor_pending;
+	u32 client_monitor_latency;
+	u32 client_monitor_conn_id;
+
+	struct hv_dev_port_info inbound;
+	struct hv_dev_port_info outbound;
+};
+
+
+static void get_channel_info(struct hv_device *device,
+			     struct hv_device_info *info)
+{
+	struct vmbus_channel_debug_info debug_info;
+
+	if (!device->channel)
+		return;
+
+	vmbus_get_debug_info(device->channel, &debug_info);
+
+	info->chn_id = debug_info.relid;
+	info->chn_state = debug_info.state;
+	memcpy(&info->chn_type, &debug_info.interfacetype,
+	       sizeof(uuid_le));
+	memcpy(&info->chn_instance, &debug_info.interface_instance,
+	       sizeof(uuid_le));
+
+	info->monitor_id = debug_info.monitorid;
+
+	info->server_monitor_pending = debug_info.servermonitor_pending;
+	info->server_monitor_latency = debug_info.servermonitor_latency;
+	info->server_monitor_conn_id = debug_info.servermonitor_connectionid;
+
+	info->client_monitor_pending = debug_info.clientmonitor_pending;
+	info->client_monitor_latency = debug_info.clientmonitor_latency;
+	info->client_monitor_conn_id = debug_info.clientmonitor_connectionid;
+
+	info->inbound.int_mask = debug_info.inbound.current_interrupt_mask;
+	info->inbound.read_idx = debug_info.inbound.current_read_index;
+	info->inbound.write_idx = debug_info.inbound.current_write_index;
+	info->inbound.bytes_avail_toread =
+		debug_info.inbound.bytes_avail_toread;
+	info->inbound.bytes_avail_towrite =
+		debug_info.inbound.bytes_avail_towrite;
+
+	info->outbound.int_mask =
+		debug_info.outbound.current_interrupt_mask;
+	info->outbound.read_idx = debug_info.outbound.current_read_index;
+	info->outbound.write_idx = debug_info.outbound.current_write_index;
+	info->outbound.bytes_avail_toread =
+		debug_info.outbound.bytes_avail_toread;
+	info->outbound.bytes_avail_towrite =
+		debug_info.outbound.bytes_avail_towrite;
+}
+
+#define VMBUS_ALIAS_LEN ((sizeof((struct hv_vmbus_device_id *)0)->guid) * 2)
+static void print_alias_name(struct hv_device *hv_dev, char *alias_name)
+{
+	int i;
+	for (i = 0; i < VMBUS_ALIAS_LEN; i += 2)
+		sprintf(&alias_name[i], "%02x", hv_dev->dev_type.b[i/2]);
+}
+
+/*
+ * vmbus_show_device_attr - Show the device attribute in sysfs.
+ *
+ * This is invoked when user does a
+ * "cat /sys/bus/vmbus/devices/<busdevice>/<attr name>"
+ */
+static ssize_t vmbus_show_device_attr(struct device *dev,
+				      struct device_attribute *dev_attr,
+				      char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+	struct hv_device_info *device_info;
+	char alias_name[VMBUS_ALIAS_LEN + 1];
+	int ret = 0;
+
+	device_info = kzalloc(sizeof(struct hv_device_info), GFP_KERNEL);
+	if (!device_info)
+		return ret;
+
+	get_channel_info(hv_dev, device_info);
+
+	if (!strcmp(dev_attr->attr.name, "class_id")) {
+		ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
+			       "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
+			       device_info->chn_type.b[3],
+			       device_info->chn_type.b[2],
+			       device_info->chn_type.b[1],
+			       device_info->chn_type.b[0],
+			       device_info->chn_type.b[5],
+			       device_info->chn_type.b[4],
+			       device_info->chn_type.b[7],
+			       device_info->chn_type.b[6],
+			       device_info->chn_type.b[8],
+			       device_info->chn_type.b[9],
+			       device_info->chn_type.b[10],
+			       device_info->chn_type.b[11],
+			       device_info->chn_type.b[12],
+			       device_info->chn_type.b[13],
+			       device_info->chn_type.b[14],
+			       device_info->chn_type.b[15]);
+	} else if (!strcmp(dev_attr->attr.name, "device_id")) {
+		ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
+			       "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
+			       device_info->chn_instance.b[3],
+			       device_info->chn_instance.b[2],
+			       device_info->chn_instance.b[1],
+			       device_info->chn_instance.b[0],
+			       device_info->chn_instance.b[5],
+			       device_info->chn_instance.b[4],
+			       device_info->chn_instance.b[7],
+			       device_info->chn_instance.b[6],
+			       device_info->chn_instance.b[8],
+			       device_info->chn_instance.b[9],
+			       device_info->chn_instance.b[10],
+			       device_info->chn_instance.b[11],
+			       device_info->chn_instance.b[12],
+			       device_info->chn_instance.b[13],
+			       device_info->chn_instance.b[14],
+			       device_info->chn_instance.b[15]);
+	} else if (!strcmp(dev_attr->attr.name, "modalias")) {
+		print_alias_name(hv_dev, alias_name);
+		ret = sprintf(buf, "vmbus:%s\n", alias_name);
+	} else if (!strcmp(dev_attr->attr.name, "state")) {
+		ret = sprintf(buf, "%d\n", device_info->chn_state);
+	} else if (!strcmp(dev_attr->attr.name, "id")) {
+		ret = sprintf(buf, "%d\n", device_info->chn_id);
+	} else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) {
+		ret = sprintf(buf, "%d\n", device_info->outbound.int_mask);
+	} else if (!strcmp(dev_attr->attr.name, "out_read_index")) {
+		ret = sprintf(buf, "%d\n", device_info->outbound.read_idx);
+	} else if (!strcmp(dev_attr->attr.name, "out_write_index")) {
+		ret = sprintf(buf, "%d\n", device_info->outbound.write_idx);
+	} else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail")) {
+		ret = sprintf(buf, "%d\n",
+			       device_info->outbound.bytes_avail_toread);
+	} else if (!strcmp(dev_attr->attr.name, "out_write_bytes_avail")) {
+		ret = sprintf(buf, "%d\n",
+			       device_info->outbound.bytes_avail_towrite);
+	} else if (!strcmp(dev_attr->attr.name, "in_intr_mask")) {
+		ret = sprintf(buf, "%d\n", device_info->inbound.int_mask);
+	} else if (!strcmp(dev_attr->attr.name, "in_read_index")) {
+		ret = sprintf(buf, "%d\n", device_info->inbound.read_idx);
+	} else if (!strcmp(dev_attr->attr.name, "in_write_index")) {
+		ret = sprintf(buf, "%d\n", device_info->inbound.write_idx);
+	} else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail")) {
+		ret = sprintf(buf, "%d\n",
+			       device_info->inbound.bytes_avail_toread);
+	} else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) {
+		ret = sprintf(buf, "%d\n",
+			       device_info->inbound.bytes_avail_towrite);
+	} else if (!strcmp(dev_attr->attr.name, "monitor_id")) {
+		ret = sprintf(buf, "%d\n", device_info->monitor_id);
+	} else if (!strcmp(dev_attr->attr.name, "server_monitor_pending")) {
+		ret = sprintf(buf, "%d\n", device_info->server_monitor_pending);
+	} else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) {
+		ret = sprintf(buf, "%d\n", device_info->server_monitor_latency);
+	} else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) {
+		ret = sprintf(buf, "%d\n",
+			       device_info->server_monitor_conn_id);
+	} else if (!strcmp(dev_attr->attr.name, "client_monitor_pending")) {
+		ret = sprintf(buf, "%d\n", device_info->client_monitor_pending);
+	} else if (!strcmp(dev_attr->attr.name, "client_monitor_latency")) {
+		ret = sprintf(buf, "%d\n", device_info->client_monitor_latency);
+	} else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) {
+		ret = sprintf(buf, "%d\n",
+			       device_info->client_monitor_conn_id);
+	}
+
+	kfree(device_info);
+	return ret;
+}
+
+/* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */
+static struct device_attribute vmbus_device_attrs[] = {
+	__ATTR(id, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(state, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(class_id, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(monitor_id, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(modalias, S_IRUGO, vmbus_show_device_attr, NULL),
+
+	__ATTR(server_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(server_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(server_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL),
+
+	__ATTR(client_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(client_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(client_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL),
+
+	__ATTR(out_intr_mask, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(out_read_index, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(out_write_index, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(out_read_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(out_write_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
+
+	__ATTR(in_intr_mask, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(in_read_index, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(in_write_index, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(in_read_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR(in_write_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
+	__ATTR_NULL
+};
+
+
+/*
+ * vmbus_uevent - add uevent for our device
+ *
+ * This routine is invoked when a device is added or removed on the vmbus to
+ * generate a uevent to udev in the userspace. The udev will then look at its
+ * rule and the uevent generated here to load the appropriate driver
+ *
+ * The alias string will be of the form vmbus:guid where guid is the string
+ * representation of the device guid (each byte of the guid will be
+ * represented with two hex characters.
+ */
+static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
+{
+	struct hv_device *dev = device_to_hv_device(device);
+	int ret;
+	char alias_name[VMBUS_ALIAS_LEN + 1];
+
+	print_alias_name(dev, alias_name);
+	ret = add_uevent_var(env, "MODALIAS=vmbus:%s", alias_name);
+	return ret;
+}
+
+static uuid_le null_guid;
+
+static inline bool is_null_guid(const __u8 *guid)
+{
+	if (memcmp(guid, &null_guid, sizeof(uuid_le)))
+		return false;
+	return true;
+}
+
+/*
+ * Return a matching hv_vmbus_device_id pointer.
+ * If there is no match, return NULL.
+ */
+static const struct hv_vmbus_device_id *hv_vmbus_get_id(
+					const struct hv_vmbus_device_id *id,
+					__u8 *guid)
+{
+	for (; !is_null_guid(id->guid); id++)
+		if (!memcmp(&id->guid, guid, sizeof(uuid_le)))
+			return id;
+
+	return NULL;
+}
+
+
+
+/*
+ * vmbus_match - Attempt to match the specified device to the specified driver
+ */
+static int vmbus_match(struct device *device, struct device_driver *driver)
+{
+	struct hv_driver *drv = drv_to_hv_drv(driver);
+	struct hv_device *hv_dev = device_to_hv_device(device);
+
+	if (hv_vmbus_get_id(drv->id_table, hv_dev->dev_type.b))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * vmbus_probe - Add the new vmbus's child device
+ */
+static int vmbus_probe(struct device *child_device)
+{
+	int ret = 0;
+	struct hv_driver *drv =
+			drv_to_hv_drv(child_device->driver);
+	struct hv_device *dev = device_to_hv_device(child_device);
+	const struct hv_vmbus_device_id *dev_id;
+
+	dev_id = hv_vmbus_get_id(drv->id_table, dev->dev_type.b);
+	if (drv->probe) {
+		ret = drv->probe(dev, dev_id);
+		if (ret != 0)
+			pr_err("probe failed for device %s (%d)\n",
+			       dev_name(child_device), ret);
+
+	} else {
+		pr_err("probe not set for driver %s\n",
+		       dev_name(child_device));
+		ret = -ENODEV;
+	}
+	return ret;
+}
+
+/*
+ * vmbus_remove - Remove a vmbus device
+ */
+static int vmbus_remove(struct device *child_device)
+{
+	struct hv_driver *drv = drv_to_hv_drv(child_device->driver);
+	struct hv_device *dev = device_to_hv_device(child_device);
+
+	if (drv->remove)
+		drv->remove(dev);
+	else
+		pr_err("remove not set for driver %s\n",
+			dev_name(child_device));
+
+	return 0;
+}
+
+
+/*
+ * vmbus_shutdown - Shutdown a vmbus device
+ */
+static void vmbus_shutdown(struct device *child_device)
+{
+	struct hv_driver *drv;
+	struct hv_device *dev = device_to_hv_device(child_device);
+
+
+	/* The device may not be attached yet */
+	if (!child_device->driver)
+		return;
+
+	drv = drv_to_hv_drv(child_device->driver);
+
+	if (drv->shutdown)
+		drv->shutdown(dev);
+
+	return;
+}
+
+
+/*
+ * vmbus_device_release - Final callback release of the vmbus child device
+ */
+static void vmbus_device_release(struct device *device)
+{
+	struct hv_device *hv_dev = device_to_hv_device(device);
+
+	kfree(hv_dev);
+
+}
+
+/* The one and only one */
+static struct bus_type  hv_bus = {
+	.name =		"vmbus",
+	.match =		vmbus_match,
+	.shutdown =		vmbus_shutdown,
+	.remove =		vmbus_remove,
+	.probe =		vmbus_probe,
+	.uevent =		vmbus_uevent,
+	.dev_attrs =	vmbus_device_attrs,
+};
+
+static const char *driver_name = "hyperv";
+
+
+struct onmessage_work_context {
+	struct work_struct work;
+	struct hv_message msg;
+};
+
+static void vmbus_onmessage_work(struct work_struct *work)
+{
+	struct onmessage_work_context *ctx;
+
+	ctx = container_of(work, struct onmessage_work_context,
+			   work);
+	vmbus_onmessage(&ctx->msg);
+	kfree(ctx);
+}
+
+static void vmbus_on_msg_dpc(unsigned long data)
+{
+	int cpu = smp_processor_id();
+	void *page_addr = hv_context.synic_message_page[cpu];
+	struct hv_message *msg = (struct hv_message *)page_addr +
+				  VMBUS_MESSAGE_SINT;
+	struct onmessage_work_context *ctx;
+
+	while (1) {
+		if (msg->header.message_type == HVMSG_NONE) {
+			/* no msg */
+			break;
+		} else {
+			ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
+			if (ctx == NULL)
+				continue;
+			INIT_WORK(&ctx->work, vmbus_onmessage_work);
+			memcpy(&ctx->msg, msg, sizeof(*msg));
+			queue_work(vmbus_connection.work_queue, &ctx->work);
+		}
+
+		msg->header.message_type = HVMSG_NONE;
+
+		/*
+		 * Make sure the write to MessageType (ie set to
+		 * HVMSG_NONE) happens before we read the
+		 * MessagePending and EOMing. Otherwise, the EOMing
+		 * will not deliver any more messages since there is
+		 * no empty slot
+		 */
+		smp_mb();
+
+		if (msg->header.message_flags.msg_pending) {
+			/*
+			 * This will cause message queue rescan to
+			 * possibly deliver another msg from the
+			 * hypervisor
+			 */
+			wrmsrl(HV_X64_MSR_EOM, 0);
+		}
+	}
+}
+
+static irqreturn_t vmbus_isr(int irq, void *dev_id)
+{
+	int cpu = smp_processor_id();
+	void *page_addr;
+	struct hv_message *msg;
+	union hv_synic_event_flags *event;
+	bool handled = false;
+
+	/*
+	 * Check for events before checking for messages. This is the order
+	 * in which events and messages are checked in Windows guests on
+	 * Hyper-V, and the Windows team suggested we do the same.
+	 */
+
+	page_addr = hv_context.synic_event_page[cpu];
+	event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
+
+	/* Since we are a child, we only need to check bit 0 */
+	if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) {
+		handled = true;
+		tasklet_schedule(&event_dpc);
+	}
+
+	page_addr = hv_context.synic_message_page[cpu];
+	msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
+
+	/* Check if there are actual msgs to be processed */
+	if (msg->header.message_type != HVMSG_NONE) {
+		handled = true;
+		tasklet_schedule(&msg_dpc);
+	}
+
+	if (handled)
+		return IRQ_HANDLED;
+	else
+		return IRQ_NONE;
+}
+
+/*
+ * vmbus_bus_init -Main vmbus driver initialization routine.
+ *
+ * Here, we
+ *	- initialize the vmbus driver context
+ *	- invoke the vmbus hv main init routine
+ *	- get the irq resource
+ *	- retrieve the channel offers
+ */
+static int vmbus_bus_init(int irq)
+{
+	int ret;
+	unsigned int vector;
+
+	/* Hypervisor initialization...setup hypercall page..etc */
+	ret = hv_init();
+	if (ret != 0) {
+		pr_err("Unable to initialize the hypervisor - 0x%x\n", ret);
+		return ret;
+	}
+
+	tasklet_init(&msg_dpc, vmbus_on_msg_dpc, 0);
+	tasklet_init(&event_dpc, vmbus_on_event, 0);
+
+	ret = bus_register(&hv_bus);
+	if (ret)
+		goto err_cleanup;
+
+	ret = request_irq(irq, vmbus_isr, IRQF_SAMPLE_RANDOM,
+			driver_name, hv_acpi_dev);
+
+	if (ret != 0) {
+		pr_err("Unable to request IRQ %d\n",
+			   irq);
+		goto err_unregister;
+	}
+
+	vector = IRQ0_VECTOR + irq;
+
+	/*
+	 * Notify the hypervisor of our irq and
+	 * connect to the host.
+	 */
+	on_each_cpu(hv_synic_init, (void *)&vector, 1);
+	ret = vmbus_connect();
+	if (ret)
+		goto err_irq;
+
+	vmbus_request_offers();
+
+	return 0;
+
+err_irq:
+	free_irq(irq, hv_acpi_dev);
+
+err_unregister:
+	bus_unregister(&hv_bus);
+
+err_cleanup:
+	hv_cleanup();
+
+	return ret;
+}
+
+/**
+ * __vmbus_child_driver_register - Register a vmbus's driver
+ * @drv: Pointer to driver structure you want to register
+ * @owner: owner module of the drv
+ * @mod_name: module name string
+ *
+ * Registers the given driver with Linux through the 'driver_register()' call
+ * and sets up the hyper-v vmbus handling for this driver.
+ * It will return the state of the 'driver_register()' call.
+ *
+ */
+int __vmbus_driver_register(struct hv_driver *hv_driver, struct module *owner, const char *mod_name)
+{
+	int ret;
+
+	pr_info("registering driver %s\n", hv_driver->name);
+
+	hv_driver->driver.name = hv_driver->name;
+	hv_driver->driver.owner = owner;
+	hv_driver->driver.mod_name = mod_name;
+	hv_driver->driver.bus = &hv_bus;
+
+	ret = driver_register(&hv_driver->driver);
+
+	vmbus_request_offers();
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(__vmbus_driver_register);
+
+/**
+ * vmbus_driver_unregister() - Unregister a vmbus's driver
+ * @drv: Pointer to driver structure you want to un-register
+ *
+ * Un-register the given driver that was previous registered with a call to
+ * vmbus_driver_register()
+ */
+void vmbus_driver_unregister(struct hv_driver *hv_driver)
+{
+	pr_info("unregistering driver %s\n", hv_driver->name);
+
+	driver_unregister(&hv_driver->driver);
+
+}
+EXPORT_SYMBOL_GPL(vmbus_driver_unregister);
+
+/*
+ * vmbus_device_create - Creates and registers a new child device
+ * on the vmbus.
+ */
+struct hv_device *vmbus_device_create(uuid_le *type,
+					    uuid_le *instance,
+					    struct vmbus_channel *channel)
+{
+	struct hv_device *child_device_obj;
+
+	child_device_obj = kzalloc(sizeof(struct hv_device), GFP_KERNEL);
+	if (!child_device_obj) {
+		pr_err("Unable to allocate device object for child device\n");
+		return NULL;
+	}
+
+	child_device_obj->channel = channel;
+	memcpy(&child_device_obj->dev_type, type, sizeof(uuid_le));
+	memcpy(&child_device_obj->dev_instance, instance,
+	       sizeof(uuid_le));
+
+
+	return child_device_obj;
+}
+
+/*
+ * vmbus_device_register - Register the child device
+ */
+int vmbus_device_register(struct hv_device *child_device_obj)
+{
+	int ret = 0;
+
+	static atomic_t device_num = ATOMIC_INIT(0);
+
+	dev_set_name(&child_device_obj->device, "vmbus_0_%d",
+		     atomic_inc_return(&device_num));
+
+	child_device_obj->device.bus = &hv_bus;
+	child_device_obj->device.parent = &hv_acpi_dev->dev;
+	child_device_obj->device.release = vmbus_device_release;
+
+	/*
+	 * Register with the LDM. This will kick off the driver/device
+	 * binding...which will eventually call vmbus_match() and vmbus_probe()
+	 */
+	ret = device_register(&child_device_obj->device);
+
+	if (ret)
+		pr_err("Unable to register child device\n");
+	else
+		pr_info("child device %s registered\n",
+			dev_name(&child_device_obj->device));
+
+	return ret;
+}
+
+/*
+ * vmbus_device_unregister - Remove the specified child device
+ * from the vmbus.
+ */
+void vmbus_device_unregister(struct hv_device *device_obj)
+{
+	/*
+	 * Kick off the process of unregistering the device.
+	 * This will call vmbus_remove() and eventually vmbus_device_release()
+	 */
+	device_unregister(&device_obj->device);
+
+	pr_info("child device %s unregistered\n",
+		dev_name(&device_obj->device));
+}
+
+
+/*
+ * VMBUS is an acpi enumerated device. Get the the IRQ information
+ * from DSDT.
+ */
+
+static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *irq)
+{
+
+	if (res->type == ACPI_RESOURCE_TYPE_IRQ) {
+		struct acpi_resource_irq *irqp;
+		irqp = &res->data.irq;
+
+		*((unsigned int *)irq) = irqp->interrupts[0];
+	}
+
+	return AE_OK;
+}
+
+static int vmbus_acpi_add(struct acpi_device *device)
+{
+	acpi_status result;
+
+	hv_acpi_dev = device;
+
+	result = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
+					vmbus_walk_resources, &irq);
+
+	if (ACPI_FAILURE(result)) {
+		complete(&probe_event);
+		return -ENODEV;
+	}
+	complete(&probe_event);
+	return 0;
+}
+
+static const struct acpi_device_id vmbus_acpi_device_ids[] = {
+	{"VMBUS", 0},
+	{"VMBus", 0},
+	{"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, vmbus_acpi_device_ids);
+
+static struct acpi_driver vmbus_acpi_driver = {
+	.name = "vmbus",
+	.ids = vmbus_acpi_device_ids,
+	.ops = {
+		.add = vmbus_acpi_add,
+	},
+};
+
+static int __init hv_acpi_init(void)
+{
+	int ret, t;
+
+	init_completion(&probe_event);
+
+	/*
+	 * Get irq resources first.
+	 */
+
+	ret = acpi_bus_register_driver(&vmbus_acpi_driver);
+
+	if (ret)
+		return ret;
+
+	t = wait_for_completion_timeout(&probe_event, 5*HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
+
+	if (irq <= 0) {
+		ret = -ENODEV;
+		goto cleanup;
+	}
+
+	ret = vmbus_bus_init(irq);
+	if (ret)
+		goto cleanup;
+
+	return 0;
+
+cleanup:
+	acpi_bus_unregister_driver(&vmbus_acpi_driver);
+	return ret;
+}
+
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION(HV_DRV_VERSION);
+
+module_init(hv_acpi_init);
diff -druN linux-libre-3.1-gnu/drivers/hwmon/ad7314.c linux-libre-3.2-gnu/drivers/hwmon/ad7314.c
--- linux-libre-3.1-gnu/drivers/hwmon/ad7314.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hwmon/ad7314.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,185 @@
+/*
+ * AD7314 digital temperature sensor driver for AD7314, ADT7301 and ADT7302
+ *
+ * Copyright 2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ *
+ * Conversion to hwmon from IIO done by Jonathan Cameron <jic23@cam.ac.uk>
+ */
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+/*
+ * AD7314 power mode
+ */
+#define AD7314_PD		0x2000
+
+/*
+ * AD7314 temperature masks
+ */
+#define AD7314_TEMP_SIGN		0x200
+#define AD7314_TEMP_MASK		0x7FE0
+#define AD7314_TEMP_OFFSET		5
+
+/*
+ * ADT7301 and ADT7302 temperature masks
+ */
+#define ADT7301_TEMP_SIGN		0x2000
+#define ADT7301_TEMP_MASK		0x3FFF
+
+enum ad7314_variant {
+	adt7301,
+	adt7302,
+	ad7314,
+};
+
+struct ad7314_data {
+	struct spi_device	*spi_dev;
+	struct device		*hwmon_dev;
+	u16 rx ____cacheline_aligned;
+};
+
+static int ad7314_spi_read(struct ad7314_data *chip, s16 *data)
+{
+	int ret;
+
+	ret = spi_read(chip->spi_dev, (u8 *)&chip->rx, sizeof(chip->rx));
+	if (ret < 0) {
+		dev_err(&chip->spi_dev->dev, "SPI read error\n");
+		return ret;
+	}
+
+	*data = be16_to_cpu(chip->rx);
+
+	return ret;
+}
+
+static ssize_t ad7314_show_temperature(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct ad7314_data *chip = dev_get_drvdata(dev);
+	s16 data;
+	int ret;
+
+	ret = ad7314_spi_read(chip, &data);
+	if (ret < 0)
+		return ret;
+	switch (spi_get_device_id(chip->spi_dev)->driver_data) {
+	case ad7314:
+		data = (data & AD7314_TEMP_MASK) >> AD7314_TEMP_OFFSET;
+		data = (data << 6) >> 6;
+
+		return sprintf(buf, "%d\n", 250 * data);
+	case adt7301:
+	case adt7302:
+		/*
+		 * Documented as a 13 bit twos complement register
+		 * with a sign bit - which is a 14 bit 2's complement
+		 * register.  1lsb - 31.25 milli degrees centigrade
+		 */
+		data &= ADT7301_TEMP_MASK;
+		data = (data << 2) >> 2;
+
+		return sprintf(buf, "%d\n",
+			       DIV_ROUND_CLOSEST(data * 3125, 100));
+	default:
+		return -EINVAL;
+	}
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
+			  ad7314_show_temperature, NULL, 0);
+
+static struct attribute *ad7314_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group ad7314_group = {
+	.attrs = ad7314_attributes,
+};
+
+static int __devinit ad7314_probe(struct spi_device *spi_dev)
+{
+	int ret;
+	struct ad7314_data *chip;
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (chip == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	dev_set_drvdata(&spi_dev->dev, chip);
+
+	ret = sysfs_create_group(&spi_dev->dev.kobj, &ad7314_group);
+	if (ret < 0)
+		goto error_free_chip;
+	chip->hwmon_dev = hwmon_device_register(&spi_dev->dev);
+	if (IS_ERR(chip->hwmon_dev)) {
+		ret = PTR_ERR(chip->hwmon_dev);
+		goto error_remove_group;
+	}
+
+	return 0;
+error_remove_group:
+	sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group);
+error_free_chip:
+	kfree(chip);
+error_ret:
+	return ret;
+}
+
+static int __devexit ad7314_remove(struct spi_device *spi_dev)
+{
+	struct ad7314_data *chip = dev_get_drvdata(&spi_dev->dev);
+
+	hwmon_device_unregister(chip->hwmon_dev);
+	sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group);
+	kfree(chip);
+
+	return 0;
+}
+
+static const struct spi_device_id ad7314_id[] = {
+	{ "adt7301", adt7301 },
+	{ "adt7302", adt7302 },
+	{ "ad7314", ad7314 },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, ad7314_id);
+
+static struct spi_driver ad7314_driver = {
+	.driver = {
+		.name = "ad7314",
+		.owner = THIS_MODULE,
+	},
+	.probe = ad7314_probe,
+	.remove = __devexit_p(ad7314_remove),
+	.id_table = ad7314_id,
+};
+
+static __init int ad7314_init(void)
+{
+	return spi_register_driver(&ad7314_driver);
+}
+module_init(ad7314_init);
+
+static __exit void ad7314_exit(void)
+{
+	spi_unregister_driver(&ad7314_driver);
+}
+module_exit(ad7314_exit);
+
+MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital"
+			" temperature sensor driver");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-3.1-gnu/drivers/hwmon/ad7414.c linux-libre-3.2-gnu/drivers/hwmon/ad7414.c
--- linux-libre-3.1-gnu/drivers/hwmon/ad7414.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/ad7414.c	2012-01-04 18:55:44.000000000 -0500
@@ -58,10 +58,9 @@
 
 static inline int ad7414_read(struct i2c_client *client, u8 reg)
 {
-	if (reg == AD7414_REG_TEMP) {
-		int value = i2c_smbus_read_word_data(client, reg);
-		return (value < 0) ? value : swab16(value);
-	} else
+	if (reg == AD7414_REG_TEMP)
+		return i2c_smbus_read_word_swapped(client, reg);
+	else
 		return i2c_smbus_read_byte_data(client, reg);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/hwmon/ad7418.c linux-libre-3.2-gnu/drivers/hwmon/ad7418.c
--- linux-libre-3.1-gnu/drivers/hwmon/ad7418.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/ad7418.c	2012-01-04 18:55:44.000000000 -0500
@@ -76,20 +76,6 @@
 	.id_table	= ad7418_id,
 };
 
-/* All registers are word-sized, except for the configuration registers.
- * AD7418 uses a high-byte first convention. Do NOT use those functions to
- * access the configuration registers CONF and CONF2, as they are byte-sized.
- */
-static inline int ad7418_read(struct i2c_client *client, u8 reg)
-{
-	return swab16(i2c_smbus_read_word_data(client, reg));
-}
-
-static inline int ad7418_write(struct i2c_client *client, u8 reg, u16 value)
-{
-	return i2c_smbus_write_word_data(client, reg, swab16(value));
-}
-
 static void ad7418_init_client(struct i2c_client *client)
 {
 	struct ad7418_data *data = i2c_get_clientdata(client);
@@ -128,7 +114,9 @@
 		udelay(30);
 
 		for (i = 0; i < 3; i++) {
-			data->temp[i] = ad7418_read(client, AD7418_REG_TEMP[i]);
+			data->temp[i] =
+				i2c_smbus_read_word_swapped(client,
+						AD7418_REG_TEMP[i]);
 		}
 
 		for (i = 0, ch = 4; i < data->adc_max; i++, ch--) {
@@ -138,11 +126,12 @@
 
 			udelay(15);
 			data->in[data->adc_max - 1 - i] =
-				ad7418_read(client, AD7418_REG_ADC);
+				i2c_smbus_read_word_swapped(client,
+						AD7418_REG_ADC);
 		}
 
 		/* restore old configuration value */
-		ad7418_write(client, AD7418_REG_CONF, cfg);
+		i2c_smbus_write_word_swapped(client, AD7418_REG_CONF, cfg);
 
 		data->last_updated = jiffies;
 		data->valid = 1;
@@ -182,7 +171,9 @@
 
 	mutex_lock(&data->lock);
 	data->temp[attr->index] = LM75_TEMP_TO_REG(temp);
-	ad7418_write(client, AD7418_REG_TEMP[attr->index], data->temp[attr->index]);
+	i2c_smbus_write_word_swapped(client,
+				     AD7418_REG_TEMP[attr->index],
+				     data->temp[attr->index]);
 	mutex_unlock(&data->lock);
 	return count;
 }
diff -druN linux-libre-3.1-gnu/drivers/hwmon/ads1015.c linux-libre-3.2-gnu/drivers/hwmon/ads1015.c
--- linux-libre-3.1-gnu/drivers/hwmon/ads1015.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/ads1015.c	2012-01-04 18:55:44.000000000 -0500
@@ -59,19 +59,6 @@
 	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)
 {
@@ -87,7 +74,7 @@
 	mutex_lock(&data->update_lock);
 
 	/* get channel parameters */
-	res = ads1015_read_reg(client, ADS1015_CONFIG);
+	res = i2c_smbus_read_word_swapped(client, ADS1015_CONFIG);
 	if (res < 0)
 		goto err_unlock;
 	config = res;
@@ -101,13 +88,13 @@
 	config |= (pga & 0x0007) << 9;
 	config |= (data_rate & 0x0007) << 5;
 
-	res = ads1015_write_reg(client, ADS1015_CONFIG, config);
+	res = i2c_smbus_write_word_swapped(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);
+	res = i2c_smbus_read_word_swapped(client, ADS1015_CONFIG);
 	if (res < 0)
 		goto err_unlock;
 	config = res;
@@ -117,7 +104,7 @@
 		goto err_unlock;
 	}
 
-	res = ads1015_read_reg(client, ADS1015_CONVERSION);
+	res = i2c_smbus_read_word_swapped(client, ADS1015_CONVERSION);
 	if (res < 0)
 		goto err_unlock;
 	conversion = res;
diff -druN linux-libre-3.1-gnu/drivers/hwmon/ads7828.c linux-libre-3.2-gnu/drivers/hwmon/ads7828.c
--- linux-libre-3.1-gnu/drivers/hwmon/ads7828.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/ads7828.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,13 +74,6 @@
 static int ads7828_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id);
 
-/* The ADS7828 returns the 12-bit sample in two bytes,
-	these are read as a word then byte-swapped */
-static u16 ads7828_read_value(struct i2c_client *client, u8 reg)
-{
-	return swab16(i2c_smbus_read_word_data(client, reg));
-}
-
 static inline u8 channel_cmd_byte(int ch)
 {
 	/* cmd byte C2,C1,C0 - see datasheet */
@@ -104,7 +97,8 @@
 
 		for (ch = 0; ch < ADS7828_NCH; ch++) {
 			u8 cmd = channel_cmd_byte(ch);
-			data->adc_input[ch] = ads7828_read_value(client, cmd);
+			data->adc_input[ch] =
+				i2c_smbus_read_word_swapped(client, cmd);
 		}
 		data->last_updated = jiffies;
 		data->valid = 1;
@@ -203,7 +197,7 @@
 	for (ch = 0; ch < ADS7828_NCH; ch++) {
 		u16 in_data;
 		u8 cmd = channel_cmd_byte(ch);
-		in_data = ads7828_read_value(client, cmd);
+		in_data = i2c_smbus_read_word_swapped(client, cmd);
 		if (in_data & 0xF000) {
 			pr_debug("%s : Doesn't look like an ads7828 device\n",
 				 __func__);
diff -druN linux-libre-3.1-gnu/drivers/hwmon/ads7871.c linux-libre-3.2-gnu/drivers/hwmon/ads7871.c
--- linux-libre-3.1-gnu/drivers/hwmon/ads7871.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/ads7871.c	2012-01-04 18:55:44.000000000 -0500
@@ -227,7 +227,6 @@
 static struct spi_driver ads7871_driver = {
 	.driver = {
 		.name = DEVICE_NAME,
-		.bus = &spi_bus_type,
 		.owner = THIS_MODULE,
 	},
 
diff -druN linux-libre-3.1-gnu/drivers/hwmon/asb100.c linux-libre-3.2-gnu/drivers/hwmon/asb100.c
--- linux-libre-3.1-gnu/drivers/hwmon/asb100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/asb100.c	2012-01-04 18:55:44.000000000 -0500
@@ -829,17 +829,17 @@
 		/* convert from ISA to LM75 I2C addresses */
 		switch (reg & 0xff) {
 		case 0x50: /* TEMP */
-			res = swab16(i2c_smbus_read_word_data(cl, 0));
+			res = i2c_smbus_read_word_swapped(cl, 0);
 			break;
 		case 0x52: /* CONFIG */
 			res = i2c_smbus_read_byte_data(cl, 1);
 			break;
 		case 0x53: /* HYST */
-			res = swab16(i2c_smbus_read_word_data(cl, 2));
+			res = i2c_smbus_read_word_swapped(cl, 2);
 			break;
 		case 0x55: /* MAX */
 		default:
-			res = swab16(i2c_smbus_read_word_data(cl, 3));
+			res = i2c_smbus_read_word_swapped(cl, 3);
 			break;
 		}
 	}
@@ -877,10 +877,10 @@
 			i2c_smbus_write_byte_data(cl, 1, value & 0xff);
 			break;
 		case 0x53: /* HYST */
-			i2c_smbus_write_word_data(cl, 2, swab16(value));
+			i2c_smbus_write_word_swapped(cl, 2, value);
 			break;
 		case 0x55: /* MAX */
-			i2c_smbus_write_word_data(cl, 3, swab16(value));
+			i2c_smbus_write_word_swapped(cl, 3, value);
 			break;
 		}
 	}
diff -druN linux-libre-3.1-gnu/drivers/hwmon/coretemp.c linux-libre-3.2-gnu/drivers/hwmon/coretemp.c
--- linux-libre-3.1-gnu/drivers/hwmon/coretemp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/coretemp.c	2012-01-04 18:55:44.000000000 -0500
@@ -60,14 +60,13 @@
 #ifdef CONFIG_SMP
 #define TO_PHYS_ID(cpu)		cpu_data(cpu).phys_proc_id
 #define TO_CORE_ID(cpu)		cpu_data(cpu).cpu_core_id
-#define TO_ATTR_NO(cpu)		(TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
 #define for_each_sibling(i, cpu)	for_each_cpu(i, cpu_sibling_mask(cpu))
 #else
 #define TO_PHYS_ID(cpu)		(cpu)
 #define TO_CORE_ID(cpu)		(cpu)
-#define TO_ATTR_NO(cpu)		(cpu)
 #define for_each_sibling(i, cpu)	for (i = 0; false; )
 #endif
+#define TO_ATTR_NO(cpu)		(TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
 
 /*
  * Per-Core Temperature Data
@@ -325,15 +324,6 @@
 	return adjust_tjmax(c, id, dev);
 }
 
-static void __devinit get_ucode_rev_on_cpu(void *edx)
-{
-	u32 eax;
-
-	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
-	sync_core();
-	rdmsr(MSR_IA32_UCODE_REV, eax, *(u32 *)edx);
-}
-
 static int create_name_attr(struct platform_data *pdata, struct device *dev)
 {
 	sysfs_attr_init(&pdata->name_attr.attr);
@@ -380,27 +370,16 @@
 static int __cpuinit chk_ucode_version(unsigned int cpu)
 {
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
-	int err;
-	u32 edx;
 
 	/*
 	 * Check if we have problem with errata AE18 of Core processors:
 	 * Readings might stop update when processor visited too deep sleep,
 	 * fixed for stepping D0 (6EC).
 	 */
-	if (c->x86_model == 0xe && c->x86_mask < 0xc) {
-		/* check for microcode update */
-		err = smp_call_function_single(cpu, get_ucode_rev_on_cpu,
-					       &edx, 1);
-		if (err) {
-			pr_err("Cannot determine microcode revision of "
-			       "CPU#%u (%d)!\n", cpu, err);
-			return -ENODEV;
-		} else if (edx < 0x39) {
-			pr_err("Errata AE18 not fixed, update BIOS or "
-			       "microcode of the CPU!\n");
-			return -ENODEV;
-		}
+	if (c->x86_model == 0xe && c->x86_mask < 0xc && c->microcode < 0x39) {
+		pr_err("Errata AE18 not fixed, update BIOS or "
+		       "microcode of the CPU!\n");
+		return -ENODEV;
 	}
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/hwmon/ds1621.c linux-libre-3.2-gnu/drivers/hwmon/ds1621.c
--- linux-libre-3.1-gnu/drivers/hwmon/ds1621.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/ds1621.c	2012-01-04 18:55:44.000000000 -0500
@@ -80,24 +80,6 @@
 	u8 conf;			/* Register encoding, combined */
 };
 
-/* Temperature registers are word-sized.
-   DS1621 uses a high-byte first convention, which is exactly opposite to
-   the SMBus standard. */
-static int ds1621_read_temp(struct i2c_client *client, u8 reg)
-{
-	int ret;
-
-	ret = i2c_smbus_read_word_data(client, reg);
-	if (ret < 0)
-		return ret;
-	return swab16(ret);
-}
-
-static int ds1621_write_temp(struct i2c_client *client, u8 reg, u16 value)
-{
-	return i2c_smbus_write_word_data(client, reg, swab16(value));
-}
-
 static void ds1621_init_client(struct i2c_client *client)
 {
 	u8 conf, new_conf;
@@ -136,7 +118,7 @@
 		data->conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
 
 		for (i = 0; i < ARRAY_SIZE(data->temp); i++)
-			data->temp[i] = ds1621_read_temp(client,
+			data->temp[i] = i2c_smbus_read_word_swapped(client,
 							 DS1621_REG_TEMP[i]);
 
 		/* reset alarms if necessary */
@@ -177,8 +159,8 @@
 
 	mutex_lock(&data->update_lock);
 	data->temp[attr->index] = val;
-	ds1621_write_temp(client, DS1621_REG_TEMP[attr->index],
-			  data->temp[attr->index]);
+	i2c_smbus_write_word_swapped(client, DS1621_REG_TEMP[attr->index],
+				     data->temp[attr->index]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
diff -druN linux-libre-3.1-gnu/drivers/hwmon/ds620.c linux-libre-3.2-gnu/drivers/hwmon/ds620.c
--- linux-libre-3.1-gnu/drivers/hwmon/ds620.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/ds620.c	2012-01-04 18:55:44.000000000 -0500
@@ -75,33 +75,13 @@
 	s16 temp[3];		/* Register values, word */
 };
 
-/*
- *  Temperature registers are word-sized.
- *  DS620 uses a high-byte first convention, which is exactly opposite to
- *  the SMBus standard.
- */
-static int ds620_read_temp(struct i2c_client *client, u8 reg)
-{
-	int ret;
-
-	ret = i2c_smbus_read_word_data(client, reg);
-	if (ret < 0)
-		return ret;
-	return swab16(ret);
-}
-
-static int ds620_write_temp(struct i2c_client *client, u8 reg, u16 value)
-{
-	return i2c_smbus_write_word_data(client, reg, swab16(value));
-}
-
 static void ds620_init_client(struct i2c_client *client)
 {
 	struct ds620_platform_data *ds620_info = client->dev.platform_data;
 	u16 conf, new_conf;
 
 	new_conf = conf =
-	    swab16(i2c_smbus_read_word_data(client, DS620_REG_CONF));
+	    i2c_smbus_read_word_swapped(client, DS620_REG_CONF);
 
 	/* switch to continuous conversion mode */
 	new_conf &= ~DS620_REG_CONFIG_1SHOT;
@@ -118,8 +98,7 @@
 	new_conf |= DS620_REG_CONFIG_R1 | DS620_REG_CONFIG_R0;
 
 	if (conf != new_conf)
-		i2c_smbus_write_word_data(client, DS620_REG_CONF,
-					  swab16(new_conf));
+		i2c_smbus_write_word_swapped(client, DS620_REG_CONF, new_conf);
 
 	/* start conversion */
 	i2c_smbus_write_byte(client, DS620_COM_START);
@@ -141,8 +120,8 @@
 		dev_dbg(&client->dev, "Starting ds620 update\n");
 
 		for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
-			res = ds620_read_temp(client,
-					      DS620_REG_TEMP[i]);
+			res = i2c_smbus_read_word_swapped(client,
+							  DS620_REG_TEMP[i]);
 			if (res < 0) {
 				ret = ERR_PTR(res);
 				goto abort;
@@ -191,8 +170,8 @@
 
 	mutex_lock(&data->update_lock);
 	data->temp[attr->index] = val;
-	ds620_write_temp(client, DS620_REG_TEMP[attr->index],
-			 data->temp[attr->index]);
+	i2c_smbus_write_word_swapped(client, DS620_REG_TEMP[attr->index],
+				     data->temp[attr->index]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -210,16 +189,15 @@
 		return PTR_ERR(data);
 
 	/* reset alarms if necessary */
-	res = i2c_smbus_read_word_data(client, DS620_REG_CONF);
+	res = i2c_smbus_read_word_swapped(client, DS620_REG_CONF);
 	if (res < 0)
 		return res;
 
-	conf = swab16(res);
-	new_conf = conf;
+	new_conf = conf = res;
 	new_conf &= ~attr->index;
 	if (conf != new_conf) {
-		res = i2c_smbus_write_word_data(client, DS620_REG_CONF,
-						swab16(new_conf));
+		res = i2c_smbus_write_word_swapped(client, DS620_REG_CONF,
+						   new_conf);
 		if (res < 0)
 			return res;
 	}
diff -druN linux-libre-3.1-gnu/drivers/hwmon/exynos4_tmu.c linux-libre-3.2-gnu/drivers/hwmon/exynos4_tmu.c
--- linux-libre-3.1-gnu/drivers/hwmon/exynos4_tmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hwmon/exynos4_tmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,514 @@
+/*
+ * exynos4_tmu.c - Samsung EXYNOS4 TMU (Thermal Management Unit)
+ *
+ *  Copyright (C) 2011 Samsung Electronics
+ *  Donggeun Kim <dg77.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 version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/err.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/workqueue.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+#include <linux/platform_data/exynos4_tmu.h>
+
+#define EXYNOS4_TMU_REG_TRIMINFO	0x0
+#define EXYNOS4_TMU_REG_CONTROL		0x20
+#define EXYNOS4_TMU_REG_STATUS		0x28
+#define EXYNOS4_TMU_REG_CURRENT_TEMP	0x40
+#define EXYNOS4_TMU_REG_THRESHOLD_TEMP	0x44
+#define EXYNOS4_TMU_REG_TRIG_LEVEL0	0x50
+#define EXYNOS4_TMU_REG_TRIG_LEVEL1	0x54
+#define EXYNOS4_TMU_REG_TRIG_LEVEL2	0x58
+#define EXYNOS4_TMU_REG_TRIG_LEVEL3	0x5C
+#define EXYNOS4_TMU_REG_PAST_TEMP0	0x60
+#define EXYNOS4_TMU_REG_PAST_TEMP1	0x64
+#define EXYNOS4_TMU_REG_PAST_TEMP2	0x68
+#define EXYNOS4_TMU_REG_PAST_TEMP3	0x6C
+#define EXYNOS4_TMU_REG_INTEN		0x70
+#define EXYNOS4_TMU_REG_INTSTAT		0x74
+#define EXYNOS4_TMU_REG_INTCLEAR	0x78
+
+#define EXYNOS4_TMU_GAIN_SHIFT		8
+#define EXYNOS4_TMU_REF_VOLTAGE_SHIFT	24
+
+#define EXYNOS4_TMU_TRIM_TEMP_MASK	0xff
+#define EXYNOS4_TMU_CORE_ON	3
+#define EXYNOS4_TMU_CORE_OFF	2
+#define EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET	50
+#define EXYNOS4_TMU_TRIG_LEVEL0_MASK	0x1
+#define EXYNOS4_TMU_TRIG_LEVEL1_MASK	0x10
+#define EXYNOS4_TMU_TRIG_LEVEL2_MASK	0x100
+#define EXYNOS4_TMU_TRIG_LEVEL3_MASK	0x1000
+#define EXYNOS4_TMU_INTCLEAR_VAL	0x1111
+
+struct exynos4_tmu_data {
+	struct exynos4_tmu_platform_data *pdata;
+	struct device *hwmon_dev;
+	struct resource *mem;
+	void __iomem *base;
+	int irq;
+	struct work_struct irq_work;
+	struct mutex lock;
+	struct clk *clk;
+	u8 temp_error1, temp_error2;
+};
+
+/*
+ * TMU treats temperature as a mapped temperature code.
+ * The temperature is converted differently depending on the calibration type.
+ */
+static int temp_to_code(struct exynos4_tmu_data *data, u8 temp)
+{
+	struct exynos4_tmu_platform_data *pdata = data->pdata;
+	int temp_code;
+
+	/* temp should range between 25 and 125 */
+	if (temp < 25 || temp > 125) {
+		temp_code = -EINVAL;
+		goto out;
+	}
+
+	switch (pdata->cal_type) {
+	case TYPE_TWO_POINT_TRIMMING:
+		temp_code = (temp - 25) *
+		    (data->temp_error2 - data->temp_error1) /
+		    (85 - 25) + data->temp_error1;
+		break;
+	case TYPE_ONE_POINT_TRIMMING:
+		temp_code = temp + data->temp_error1 - 25;
+		break;
+	default:
+		temp_code = temp + EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET;
+		break;
+	}
+out:
+	return temp_code;
+}
+
+/*
+ * Calculate a temperature value from a temperature code.
+ * The unit of the temperature is degree Celsius.
+ */
+static int code_to_temp(struct exynos4_tmu_data *data, u8 temp_code)
+{
+	struct exynos4_tmu_platform_data *pdata = data->pdata;
+	int temp;
+
+	/* temp_code should range between 75 and 175 */
+	if (temp_code < 75 || temp_code > 175) {
+		temp = -ENODATA;
+		goto out;
+	}
+
+	switch (pdata->cal_type) {
+	case TYPE_TWO_POINT_TRIMMING:
+		temp = (temp_code - data->temp_error1) * (85 - 25) /
+		    (data->temp_error2 - data->temp_error1) + 25;
+		break;
+	case TYPE_ONE_POINT_TRIMMING:
+		temp = temp_code - data->temp_error1 + 25;
+		break;
+	default:
+		temp = temp_code - EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET;
+		break;
+	}
+out:
+	return temp;
+}
+
+static int exynos4_tmu_initialize(struct platform_device *pdev)
+{
+	struct exynos4_tmu_data *data = platform_get_drvdata(pdev);
+	struct exynos4_tmu_platform_data *pdata = data->pdata;
+	unsigned int status, trim_info;
+	int ret = 0, threshold_code;
+
+	mutex_lock(&data->lock);
+	clk_enable(data->clk);
+
+	status = readb(data->base + EXYNOS4_TMU_REG_STATUS);
+	if (!status) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/* Save trimming info in order to perform calibration */
+	trim_info = readl(data->base + EXYNOS4_TMU_REG_TRIMINFO);
+	data->temp_error1 = trim_info & EXYNOS4_TMU_TRIM_TEMP_MASK;
+	data->temp_error2 = ((trim_info >> 8) & EXYNOS4_TMU_TRIM_TEMP_MASK);
+
+	/* Write temperature code for threshold */
+	threshold_code = temp_to_code(data, pdata->threshold);
+	if (threshold_code < 0) {
+		ret = threshold_code;
+		goto out;
+	}
+	writeb(threshold_code,
+		data->base + EXYNOS4_TMU_REG_THRESHOLD_TEMP);
+
+	writeb(pdata->trigger_levels[0],
+		data->base + EXYNOS4_TMU_REG_TRIG_LEVEL0);
+	writeb(pdata->trigger_levels[1],
+		data->base + EXYNOS4_TMU_REG_TRIG_LEVEL1);
+	writeb(pdata->trigger_levels[2],
+		data->base + EXYNOS4_TMU_REG_TRIG_LEVEL2);
+	writeb(pdata->trigger_levels[3],
+		data->base + EXYNOS4_TMU_REG_TRIG_LEVEL3);
+
+	writel(EXYNOS4_TMU_INTCLEAR_VAL,
+		data->base + EXYNOS4_TMU_REG_INTCLEAR);
+out:
+	clk_disable(data->clk);
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static void exynos4_tmu_control(struct platform_device *pdev, bool on)
+{
+	struct exynos4_tmu_data *data = platform_get_drvdata(pdev);
+	struct exynos4_tmu_platform_data *pdata = data->pdata;
+	unsigned int con, interrupt_en;
+
+	mutex_lock(&data->lock);
+	clk_enable(data->clk);
+
+	con = pdata->reference_voltage << EXYNOS4_TMU_REF_VOLTAGE_SHIFT |
+		pdata->gain << EXYNOS4_TMU_GAIN_SHIFT;
+	if (on) {
+		con |= EXYNOS4_TMU_CORE_ON;
+		interrupt_en = pdata->trigger_level3_en << 12 |
+			pdata->trigger_level2_en << 8 |
+			pdata->trigger_level1_en << 4 |
+			pdata->trigger_level0_en;
+	} else {
+		con |= EXYNOS4_TMU_CORE_OFF;
+		interrupt_en = 0; /* Disable all interrupts */
+	}
+	writel(interrupt_en, data->base + EXYNOS4_TMU_REG_INTEN);
+	writel(con, data->base + EXYNOS4_TMU_REG_CONTROL);
+
+	clk_disable(data->clk);
+	mutex_unlock(&data->lock);
+}
+
+static int exynos4_tmu_read(struct exynos4_tmu_data *data)
+{
+	u8 temp_code;
+	int temp;
+
+	mutex_lock(&data->lock);
+	clk_enable(data->clk);
+
+	temp_code = readb(data->base + EXYNOS4_TMU_REG_CURRENT_TEMP);
+	temp = code_to_temp(data, temp_code);
+
+	clk_disable(data->clk);
+	mutex_unlock(&data->lock);
+
+	return temp;
+}
+
+static void exynos4_tmu_work(struct work_struct *work)
+{
+	struct exynos4_tmu_data *data = container_of(work,
+			struct exynos4_tmu_data, irq_work);
+
+	mutex_lock(&data->lock);
+	clk_enable(data->clk);
+
+	writel(EXYNOS4_TMU_INTCLEAR_VAL, data->base + EXYNOS4_TMU_REG_INTCLEAR);
+
+	kobject_uevent(&data->hwmon_dev->kobj, KOBJ_CHANGE);
+
+	enable_irq(data->irq);
+
+	clk_disable(data->clk);
+	mutex_unlock(&data->lock);
+}
+
+static irqreturn_t exynos4_tmu_irq(int irq, void *id)
+{
+	struct exynos4_tmu_data *data = id;
+
+	disable_irq_nosync(irq);
+	schedule_work(&data->irq_work);
+
+	return IRQ_HANDLED;
+}
+
+static ssize_t exynos4_tmu_show_name(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "exynos4-tmu\n");
+}
+
+static ssize_t exynos4_tmu_show_temp(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct exynos4_tmu_data *data = dev_get_drvdata(dev);
+	int ret;
+
+	ret = exynos4_tmu_read(data);
+	if (ret < 0)
+		return ret;
+
+	/* convert from degree Celsius to millidegree Celsius */
+	return sprintf(buf, "%d\n", ret * 1000);
+}
+
+static ssize_t exynos4_tmu_show_alarm(struct device *dev,
+		struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct exynos4_tmu_data *data = dev_get_drvdata(dev);
+	struct exynos4_tmu_platform_data *pdata = data->pdata;
+	int temp;
+	unsigned int trigger_level;
+
+	temp = exynos4_tmu_read(data);
+	if (temp < 0)
+		return temp;
+
+	trigger_level = pdata->threshold + pdata->trigger_levels[attr->index];
+
+	return sprintf(buf, "%d\n", !!(temp > trigger_level));
+}
+
+static ssize_t exynos4_tmu_show_level(struct device *dev,
+		struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct exynos4_tmu_data *data = dev_get_drvdata(dev);
+	struct exynos4_tmu_platform_data *pdata = data->pdata;
+	unsigned int temp = pdata->threshold +
+			pdata->trigger_levels[attr->index];
+
+	return sprintf(buf, "%u\n", temp * 1000);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, exynos4_tmu_show_name, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, exynos4_tmu_show_temp, NULL, 0);
+
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO,
+		exynos4_tmu_show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO,
+		exynos4_tmu_show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp1_emergency_alarm, S_IRUGO,
+		exynos4_tmu_show_alarm, NULL, 3);
+
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, exynos4_tmu_show_level, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, exynos4_tmu_show_level, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp1_emergency, S_IRUGO,
+		exynos4_tmu_show_level, NULL, 3);
+
+static struct attribute *exynos4_tmu_attributes[] = {
+	&dev_attr_name.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_emergency_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&sensor_dev_attr_temp1_emergency.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group exynos4_tmu_attr_group = {
+	.attrs = exynos4_tmu_attributes,
+};
+
+static int __devinit exynos4_tmu_probe(struct platform_device *pdev)
+{
+	struct exynos4_tmu_data *data;
+	struct exynos4_tmu_platform_data *pdata = pdev->dev.platform_data;
+	int ret;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "No platform init data supplied.\n");
+		return -ENODEV;
+	}
+
+	data = kzalloc(sizeof(struct exynos4_tmu_data), GFP_KERNEL);
+	if (!data) {
+		dev_err(&pdev->dev, "Failed to allocate driver structure\n");
+		return -ENOMEM;
+	}
+
+	data->irq = platform_get_irq(pdev, 0);
+	if (data->irq < 0) {
+		ret = data->irq;
+		dev_err(&pdev->dev, "Failed to get platform irq\n");
+		goto err_free;
+	}
+
+	INIT_WORK(&data->irq_work, exynos4_tmu_work);
+
+	data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!data->mem) {
+		ret = -ENOENT;
+		dev_err(&pdev->dev, "Failed to get platform resource\n");
+		goto err_free;
+	}
+
+	data->mem = request_mem_region(data->mem->start,
+			resource_size(data->mem), pdev->name);
+	if (!data->mem) {
+		ret = -ENODEV;
+		dev_err(&pdev->dev, "Failed to request memory region\n");
+		goto err_free;
+	}
+
+	data->base = ioremap(data->mem->start, resource_size(data->mem));
+	if (!data->base) {
+		ret = -ENODEV;
+		dev_err(&pdev->dev, "Failed to ioremap memory\n");
+		goto err_mem_region;
+	}
+
+	ret = request_irq(data->irq, exynos4_tmu_irq,
+		IRQF_TRIGGER_RISING,
+		"exynos4-tmu", data);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
+		goto err_io_remap;
+	}
+
+	data->clk = clk_get(NULL, "tmu_apbif");
+	if (IS_ERR(data->clk)) {
+		ret = PTR_ERR(data->clk);
+		dev_err(&pdev->dev, "Failed to get clock\n");
+		goto err_irq;
+	}
+
+	data->pdata = pdata;
+	platform_set_drvdata(pdev, data);
+	mutex_init(&data->lock);
+
+	ret = exynos4_tmu_initialize(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to initialize TMU\n");
+		goto err_clk;
+	}
+
+	ret = sysfs_create_group(&pdev->dev.kobj, &exynos4_tmu_attr_group);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to create sysfs group\n");
+		goto err_clk;
+	}
+
+	data->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		ret = PTR_ERR(data->hwmon_dev);
+		dev_err(&pdev->dev, "Failed to register hwmon device\n");
+		goto err_create_group;
+	}
+
+	exynos4_tmu_control(pdev, true);
+
+	return 0;
+
+err_create_group:
+	sysfs_remove_group(&pdev->dev.kobj, &exynos4_tmu_attr_group);
+err_clk:
+	platform_set_drvdata(pdev, NULL);
+	clk_put(data->clk);
+err_irq:
+	free_irq(data->irq, data);
+err_io_remap:
+	iounmap(data->base);
+err_mem_region:
+	release_mem_region(data->mem->start, resource_size(data->mem));
+err_free:
+	kfree(data);
+
+	return ret;
+}
+
+static int __devexit exynos4_tmu_remove(struct platform_device *pdev)
+{
+	struct exynos4_tmu_data *data = platform_get_drvdata(pdev);
+
+	exynos4_tmu_control(pdev, false);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&pdev->dev.kobj, &exynos4_tmu_attr_group);
+
+	clk_put(data->clk);
+
+	free_irq(data->irq, data);
+
+	iounmap(data->base);
+	release_mem_region(data->mem->start, resource_size(data->mem));
+
+	platform_set_drvdata(pdev, NULL);
+
+	kfree(data);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int exynos4_tmu_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	exynos4_tmu_control(pdev, false);
+
+	return 0;
+}
+
+static int exynos4_tmu_resume(struct platform_device *pdev)
+{
+	exynos4_tmu_initialize(pdev);
+	exynos4_tmu_control(pdev, true);
+
+	return 0;
+}
+#else
+#define exynos4_tmu_suspend NULL
+#define exynos4_tmu_resume NULL
+#endif
+
+static struct platform_driver exynos4_tmu_driver = {
+	.driver = {
+		.name   = "exynos4-tmu",
+		.owner  = THIS_MODULE,
+	},
+	.probe = exynos4_tmu_probe,
+	.remove	= __devexit_p(exynos4_tmu_remove),
+	.suspend = exynos4_tmu_suspend,
+	.resume = exynos4_tmu_resume,
+};
+
+module_platform_driver(exynos4_tmu_driver);
+
+MODULE_DESCRIPTION("EXYNOS4 TMU Driver");
+MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:exynos4-tmu");
diff -druN linux-libre-3.1-gnu/drivers/hwmon/f71882fg.c linux-libre-3.2-gnu/drivers/hwmon/f71882fg.c
--- linux-libre-3.1-gnu/drivers/hwmon/f71882fg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/f71882fg.c	2012-01-04 18:55:44.000000000 -0500
@@ -605,7 +605,7 @@
 
 /* PWM attr for the f71862fg, fewer pwms and fewer zones per pwm than the
    standard models */
-static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
+static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[3][7] = { {
 	SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
 		      store_pwm_auto_point_channel, 0, 0),
@@ -627,7 +627,7 @@
 		      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),
@@ -649,7 +649,7 @@
 		      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),
@@ -671,12 +671,12 @@
 		      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 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[] = {
+static struct sensor_device_attribute_2 f71869_auto_pwm_attr[3][8] = { {
 	SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
 		      store_pwm_auto_point_channel, 0, 0),
@@ -701,7 +701,7 @@
 		      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),
@@ -726,7 +726,7 @@
 		      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),
@@ -751,7 +751,7 @@
 		      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] = { {
@@ -928,7 +928,7 @@
 /* PWM attr for the f8000, zones mapped to temp instead of to pwm!
    Also the register block at offset A0 maps to TEMP1 (so our temp2, as the
    F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */
-static struct sensor_device_attribute_2 f8000_auto_pwm_attr[] = {
+static struct sensor_device_attribute_2 f8000_auto_pwm_attr[3][14] = { {
 	SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
 		      store_pwm_auto_point_channel, 0, 0),
@@ -969,7 +969,7 @@
 		      show_pwm_auto_point_temp_hyst, NULL, 2, 2),
 	SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO,
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 2),
-
+}, {
 	SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
 		      store_pwm_auto_point_channel, 0, 1),
@@ -1010,7 +1010,7 @@
 		      show_pwm_auto_point_temp_hyst, NULL, 2, 0),
 	SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO,
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 0),
-
+}, {
 	SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
 		      store_pwm_auto_point_channel, 0, 2),
@@ -1051,7 +1051,7 @@
 		      show_pwm_auto_point_temp_hyst, NULL, 2, 1),
 	SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO,
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 1),
-};
+} };
 
 /* Super I/O functions */
 static inline int superio_inb(int base, int reg)
@@ -2154,6 +2154,104 @@
 		device_remove_file(&pdev->dev, &attr[i].dev_attr);
 }
 
+static int __devinit f71882fg_create_fan_sysfs_files(
+	struct platform_device *pdev, int idx)
+{
+	struct f71882fg_data *data = platform_get_drvdata(pdev);
+	int err;
+
+	/* Sanity check the pwm setting */
+	err = 0;
+	switch (data->type) {
+	case f71858fg:
+		if (((data->pwm_enable >> (idx * 2)) & 3) == 3)
+			err = 1;
+		break;
+	case f71862fg:
+		if (((data->pwm_enable >> (idx * 2)) & 1) != 1)
+			err = 1;
+		break;
+	case f8000:
+		if (idx == 2)
+			err = data->pwm_enable & 0x20;
+		break;
+	default:
+		break;
+	}
+	if (err) {
+		dev_err(&pdev->dev,
+			"Invalid (reserved) pwm settings: 0x%02x, "
+			"skipping fan %d\n",
+			(data->pwm_enable >> (idx * 2)) & 3, idx + 1);
+		return 0; /* This is a non fatal condition */
+	}
+
+	err = f71882fg_create_sysfs_files(pdev, &fxxxx_fan_attr[idx][0],
+					  ARRAY_SIZE(fxxxx_fan_attr[0]));
+	if (err)
+		return err;
+
+	if (f71882fg_fan_has_beep[data->type]) {
+		err = f71882fg_create_sysfs_files(pdev,
+						  &fxxxx_fan_beep_attr[idx],
+						  1);
+		if (err)
+			return err;
+	}
+
+	dev_info(&pdev->dev, "Fan: %d is in %s mode\n", idx + 1,
+		 (data->pwm_enable & (1 << (2 * idx))) ? "duty-cycle" : "RPM");
+
+	/* Check for unsupported auto pwm settings */
+	switch (data->type) {
+	case f71808e:
+	case f71808a:
+	case f71869:
+	case f71869a:
+	case f71889fg:
+	case f71889ed:
+	case f71889a:
+		data->pwm_auto_point_mapping[idx] =
+			f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(idx));
+		if ((data->pwm_auto_point_mapping[idx] & 0x80) ||
+		    (data->pwm_auto_point_mapping[idx] & 3) == 0) {
+			dev_warn(&pdev->dev,
+				 "Auto pwm controlled by raw digital "
+				 "data, disabling pwm auto_point "
+				 "sysfs attributes for fan %d\n", idx + 1);
+			return 0; /* This is a non fatal condition */
+		}
+		break;
+	default:
+		break;
+	}
+
+	switch (data->type) {
+	case f71862fg:
+		err = f71882fg_create_sysfs_files(pdev,
+					&f71862fg_auto_pwm_attr[idx][0],
+					ARRAY_SIZE(f71862fg_auto_pwm_attr[0]));
+		break;
+	case f71808e:
+	case f71869:
+		err = f71882fg_create_sysfs_files(pdev,
+					&f71869_auto_pwm_attr[idx][0],
+					ARRAY_SIZE(f71869_auto_pwm_attr[0]));
+		break;
+	case f8000:
+		err = f71882fg_create_sysfs_files(pdev,
+					&f8000_auto_pwm_attr[idx][0],
+					ARRAY_SIZE(f8000_auto_pwm_attr[0]));
+		break;
+	default:
+		err = f71882fg_create_sysfs_files(pdev,
+					&fxxxx_auto_pwm_attr[idx][0],
+					ARRAY_SIZE(fxxxx_auto_pwm_attr[0]));
+	}
+
+	return err;
+}
+
 static int __devinit f71882fg_probe(struct platform_device *pdev)
 {
 	struct f71882fg_data *data;
@@ -2272,117 +2370,29 @@
 		data->pwm_enable =
 			f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
 
-		/* Sanity check the pwm settings */
-		switch (data->type) {
-		case f71858fg:
-			err = 0;
-			for (i = 0; i < nr_fans; i++)
-				if (((data->pwm_enable >> (i * 2)) & 3) == 3)
-					err = 1;
-			break;
-		case f71862fg:
-			err = (data->pwm_enable & 0x15) != 0x15;
-			break;
-		case f8000:
-			err = data->pwm_enable & 0x20;
-			break;
-		default:
-			err = 0;
-			break;
-		}
-		if (err) {
-			dev_err(&pdev->dev,
-				"Invalid (reserved) pwm settings: 0x%02x\n",
-				(unsigned int)data->pwm_enable);
-			err = -ENODEV;
-			goto exit_unregister_sysfs;
-		}
-
-		err = f71882fg_create_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
-				ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
-		if (err)
-			goto exit_unregister_sysfs;
-
-		if (f71882fg_fan_has_beep[data->type]) {
-			err = f71882fg_create_sysfs_files(pdev,
-					fxxxx_fan_beep_attr, nr_fans);
+		for (i = 0; i < nr_fans; i++) {
+			err = f71882fg_create_fan_sysfs_files(pdev, i);
 			if (err)
 				goto exit_unregister_sysfs;
 		}
 
-		switch (data->type) {
-		case f71808e:
-		case f71808a:
-		case f71869:
-		case f71869a:
-		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;
-		}
-
+		/* Some types have 1 extra fan with limited functionality */
 		switch (data->type) {
 		case f71808a:
 			err = f71882fg_create_sysfs_files(pdev,
-				&fxxxx_auto_pwm_attr[0][0],
-				ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
-			if (err)
-				goto exit_unregister_sysfs;
-			err = f71882fg_create_sysfs_files(pdev,
 					f71808a_fan3_attr,
 					ARRAY_SIZE(f71808a_fan3_attr));
 			break;
-		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,
 					ARRAY_SIZE(f8000_fan_attr));
-			if (err)
-				goto exit_unregister_sysfs;
-			err = f71882fg_create_sysfs_files(pdev,
-					f8000_auto_pwm_attr,
-					ARRAY_SIZE(f8000_auto_pwm_attr));
 			break;
 		default:
-			err = f71882fg_create_sysfs_files(pdev,
-				&fxxxx_auto_pwm_attr[0][0],
-				ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
+			break;
 		}
 		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)) ?
-				 "duty-cycle" : "RPM");
 	}
 
 	data->hwmon_dev = hwmon_device_register(&pdev->dev);
@@ -2476,22 +2486,23 @@
 			break;
 		case f71862fg:
 			f71882fg_remove_sysfs_files(pdev,
-					f71862fg_auto_pwm_attr,
-					ARRAY_SIZE(f71862fg_auto_pwm_attr));
+				&f71862fg_auto_pwm_attr[0][0],
+				ARRAY_SIZE(f71862fg_auto_pwm_attr[0]) *
+					nr_fans);
 			break;
 		case f71808e:
 		case f71869:
 			f71882fg_remove_sysfs_files(pdev,
-					f71869_auto_pwm_attr,
-					ARRAY_SIZE(f71869_auto_pwm_attr));
+				&f71869_auto_pwm_attr[0][0],
+				ARRAY_SIZE(f71869_auto_pwm_attr[0]) * nr_fans);
 			break;
 		case f8000:
 			f71882fg_remove_sysfs_files(pdev,
 					f8000_fan_attr,
 					ARRAY_SIZE(f8000_fan_attr));
 			f71882fg_remove_sysfs_files(pdev,
-					f8000_auto_pwm_attr,
-					ARRAY_SIZE(f8000_auto_pwm_attr));
+				&f8000_auto_pwm_attr[0][0],
+				ARRAY_SIZE(f8000_auto_pwm_attr[0]) * nr_fans);
 			break;
 		default:
 			f71882fg_remove_sysfs_files(pdev,
diff -druN linux-libre-3.1-gnu/drivers/hwmon/gl518sm.c linux-libre-3.2-gnu/drivers/hwmon/gl518sm.c
--- linux-libre-3.1-gnu/drivers/hwmon/gl518sm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/gl518sm.c	2012-01-04 18:55:44.000000000 -0500
@@ -591,7 +591,7 @@
 static int gl518_read_value(struct i2c_client *client, u8 reg)
 {
 	if ((reg >= 0x07) && (reg <= 0x0c))
-		return swab16(i2c_smbus_read_word_data(client, reg));
+		return i2c_smbus_read_word_swapped(client, reg);
 	else
 		return i2c_smbus_read_byte_data(client, reg);
 }
@@ -599,7 +599,7 @@
 static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value)
 {
 	if ((reg >= 0x07) && (reg <= 0x0c))
-		return i2c_smbus_write_word_data(client, reg, swab16(value));
+		return i2c_smbus_write_word_swapped(client, reg, value);
 	else
 		return i2c_smbus_write_byte_data(client, reg, value);
 }
diff -druN linux-libre-3.1-gnu/drivers/hwmon/gl520sm.c linux-libre-3.2-gnu/drivers/hwmon/gl520sm.c
--- linux-libre-3.1-gnu/drivers/hwmon/gl520sm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/gl520sm.c	2012-01-04 18:55:44.000000000 -0500
@@ -821,7 +821,7 @@
 static int gl520_read_value(struct i2c_client *client, u8 reg)
 {
 	if ((reg >= 0x07) && (reg <= 0x0c))
-		return swab16(i2c_smbus_read_word_data(client, reg));
+		return i2c_smbus_read_word_swapped(client, reg);
 	else
 		return i2c_smbus_read_byte_data(client, reg);
 }
@@ -829,7 +829,7 @@
 static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value)
 {
 	if ((reg >= 0x07) && (reg <= 0x0c))
-		return i2c_smbus_write_word_data(client, reg, swab16(value));
+		return i2c_smbus_write_word_swapped(client, reg, value);
 	else
 		return i2c_smbus_write_byte_data(client, reg, value);
 }
diff -druN linux-libre-3.1-gnu/drivers/hwmon/gpio-fan.c linux-libre-3.2-gnu/drivers/hwmon/gpio-fan.c
--- linux-libre-3.1-gnu/drivers/hwmon/gpio-fan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/gpio-fan.c	2012-01-04 18:55:44.000000000 -0500
@@ -539,18 +539,7 @@
 	},
 };
 
-static int __init gpio_fan_init(void)
-{
-	return platform_driver_register(&gpio_fan_driver);
-}
-
-static void __exit gpio_fan_exit(void)
-{
-	platform_driver_unregister(&gpio_fan_driver);
-}
-
-module_init(gpio_fan_init);
-module_exit(gpio_fan_exit);
+module_platform_driver(gpio_fan_driver);
 
 MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
 MODULE_DESCRIPTION("GPIO FAN driver");
diff -druN linux-libre-3.1-gnu/drivers/hwmon/hwmon.c linux-libre-3.2-gnu/drivers/hwmon/hwmon.c
--- linux-libre-3.1-gnu/drivers/hwmon/hwmon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/hwmon.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,8 +27,7 @@
 
 static struct class *hwmon_class;
 
-static DEFINE_IDR(hwmon_idr);
-static DEFINE_SPINLOCK(idr_lock);
+static DEFINE_IDA(hwmon_ida);
 
 /**
  * hwmon_device_register - register w/ hwmon
@@ -42,30 +41,17 @@
 struct device *hwmon_device_register(struct device *dev)
 {
 	struct device *hwdev;
-	int id, err;
-
-again:
-	if (unlikely(idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0))
-		return ERR_PTR(-ENOMEM);
-
-	spin_lock(&idr_lock);
-	err = idr_get_new(&hwmon_idr, NULL, &id);
-	spin_unlock(&idr_lock);
+	int id;
 
-	if (unlikely(err == -EAGAIN))
-		goto again;
-	else if (unlikely(err))
-		return ERR_PTR(err);
+	id = ida_simple_get(&hwmon_ida, 0, 0, GFP_KERNEL);
+	if (id < 0)
+		return ERR_PTR(id);
 
-	id = id & MAX_ID_MASK;
 	hwdev = device_create(hwmon_class, dev, MKDEV(0, 0), NULL,
 			      HWMON_ID_FORMAT, id);
 
-	if (IS_ERR(hwdev)) {
-		spin_lock(&idr_lock);
-		idr_remove(&hwmon_idr, id);
-		spin_unlock(&idr_lock);
-	}
+	if (IS_ERR(hwdev))
+		ida_simple_remove(&hwmon_ida, id);
 
 	return hwdev;
 }
@@ -81,9 +67,7 @@
 
 	if (likely(sscanf(dev_name(dev), HWMON_ID_FORMAT, &id) == 1)) {
 		device_unregister(dev);
-		spin_lock(&idr_lock);
-		idr_remove(&hwmon_idr, id);
-		spin_unlock(&idr_lock);
+		ida_simple_remove(&hwmon_ida, id);
 	} else
 		dev_dbg(dev->parent,
 			"hwmon_device_unregister() failed: bad class ID!\n");
diff -druN linux-libre-3.1-gnu/drivers/hwmon/ibmaem.c linux-libre-3.2-gnu/drivers/hwmon/ibmaem.c
--- linux-libre-3.1-gnu/drivers/hwmon/ibmaem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/ibmaem.c	2012-01-04 18:55:44.000000000 -0500
@@ -88,8 +88,7 @@
 #define AEM_MIN_POWER_INTERVAL	200
 #define UJ_PER_MJ		1000L
 
-static DEFINE_IDR(aem_idr);
-static DEFINE_SPINLOCK(aem_idr_lock);
+static DEFINE_IDA(aem_ida);
 
 static struct platform_driver aem_driver = {
 	.driver = {
@@ -148,8 +147,9 @@
 	int			id;
 	struct aem_ipmi_data	ipmi;
 
-	/* Function to update sensors */
+	/* Function and buffer to update sensors */
 	void (*update)(struct aem_data *data);
+	struct aem_read_sensor_resp *rs_resp;
 
 	/*
 	 * AEM 1.x sensors:
@@ -246,8 +246,6 @@
 static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data);
 
 static void aem_remove_sensors(struct aem_data *data);
-static int aem_init_aem1(struct aem_ipmi_data *probe);
-static int aem_init_aem2(struct aem_ipmi_data *probe);
 static int aem1_find_sensors(struct aem_data *data);
 static int aem2_find_sensors(struct aem_data *data);
 static void update_aem1_sensors(struct aem_data *data);
@@ -356,47 +354,16 @@
 	complete(&data->read_complete);
 }
 
-/* ID functions */
-
-/* Obtain an id */
-static int aem_idr_get(int *id)
-{
-	int i, err;
-
-again:
-	if (unlikely(!idr_pre_get(&aem_idr, GFP_KERNEL)))
-		return -ENOMEM;
-
-	spin_lock(&aem_idr_lock);
-	err = idr_get_new(&aem_idr, NULL, &i);
-	spin_unlock(&aem_idr_lock);
-
-	if (unlikely(err == -EAGAIN))
-		goto again;
-	else if (unlikely(err))
-		return err;
-
-	*id = i & MAX_ID_MASK;
-	return 0;
-}
-
-/* Release an object ID */
-static void aem_idr_put(int id)
-{
-	spin_lock(&aem_idr_lock);
-	idr_remove(&aem_idr, id);
-	spin_unlock(&aem_idr_lock);
-}
-
 /* Sensor support functions */
 
-/* Read a sensor value */
+/* Read a sensor value; must be called with data->lock held */
 static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
 			   void *buf, size_t size)
 {
 	int rs_size, res;
 	struct aem_read_sensor_req rs_req;
-	struct aem_read_sensor_resp *rs_resp;
+	/* Use preallocated rx buffer */
+	struct aem_read_sensor_resp *rs_resp = data->rs_resp;
 	struct aem_ipmi_data *ipmi = &data->ipmi;
 
 	/* AEM registers are 1, 2, 4 or 8 bytes */
@@ -422,10 +389,6 @@
 	ipmi->tx_message.data_len = sizeof(rs_req);
 
 	rs_size = sizeof(*rs_resp) + size;
-	rs_resp = kzalloc(rs_size, GFP_KERNEL);
-	if (!rs_resp)
-		return -ENOMEM;
-
 	ipmi->rx_msg_data = rs_resp;
 	ipmi->rx_msg_len = rs_size;
 
@@ -468,7 +431,6 @@
 	res = 0;
 
 out:
-	kfree(rs_resp);
 	return res;
 }
 
@@ -526,11 +488,12 @@
 {
 	list_del(&data->list);
 	aem_remove_sensors(data);
+	kfree(data->rs_resp);
 	hwmon_device_unregister(data->hwmon_dev);
 	ipmi_destroy_user(data->ipmi.user);
 	platform_set_drvdata(data->pdev, NULL);
 	platform_device_unregister(data->pdev);
-	aem_idr_put(data->id);
+	ida_simple_remove(&aem_ida, data->id);
 	kfree(data);
 }
 
@@ -587,7 +550,8 @@
 		data->power_period[i] = AEM_DEFAULT_POWER_INTERVAL;
 
 	/* Create sub-device for this fw instance */
-	if (aem_idr_get(&data->id))
+	data->id = ida_simple_get(&aem_ida, 0, 0, GFP_KERNEL);
+	if (data->id < 0)
 		goto id_err;
 
 	data->pdev = platform_device_alloc(DRVNAME, data->id);
@@ -602,24 +566,31 @@
 	platform_set_drvdata(data->pdev, data);
 
 	/* Set up IPMI interface */
-	if (aem_init_ipmi_data(&data->ipmi, probe->interface,
-			       probe->bmc_device))
+	res = aem_init_ipmi_data(&data->ipmi, probe->interface,
+				 probe->bmc_device);
+	if (res)
 		goto ipmi_err;
 
 	/* Register with hwmon */
 	data->hwmon_dev = hwmon_device_register(&data->pdev->dev);
-
 	if (IS_ERR(data->hwmon_dev)) {
 		dev_err(&data->pdev->dev, "Unable to register hwmon "
 			"device for IPMI interface %d\n",
 			probe->interface);
+		res = PTR_ERR(data->hwmon_dev);
 		goto hwmon_reg_err;
 	}
 
 	data->update = update_aem1_sensors;
+	data->rs_resp = kzalloc(sizeof(*(data->rs_resp)) + 8, GFP_KERNEL);
+	if (!data->rs_resp) {
+		res = -ENOMEM;
+		goto alloc_resp_err;
+	}
 
 	/* Find sensors */
-	if (aem1_find_sensors(data))
+	res = aem1_find_sensors(data);
+	if (res)
 		goto sensor_err;
 
 	/* Add to our list of AEM devices */
@@ -631,6 +602,8 @@
 	return 0;
 
 sensor_err:
+	kfree(data->rs_resp);
+alloc_resp_err:
 	hwmon_device_unregister(data->hwmon_dev);
 hwmon_reg_err:
 	ipmi_destroy_user(data->ipmi.user);
@@ -638,7 +611,7 @@
 	platform_set_drvdata(data->pdev, NULL);
 	platform_device_unregister(data->pdev);
 dev_err:
-	aem_idr_put(data->id);
+	ida_simple_remove(&aem_ida, data->id);
 id_err:
 	kfree(data);
 
@@ -646,7 +619,7 @@
 }
 
 /* Find and initialize all AEM1 instances */
-static int aem_init_aem1(struct aem_ipmi_data *probe)
+static void aem_init_aem1(struct aem_ipmi_data *probe)
 {
 	int num, i, err;
 
@@ -657,11 +630,8 @@
 			dev_err(probe->bmc_device,
 				"Error %d initializing AEM1 0x%X\n",
 				err, i);
-			return err;
 		}
 	}
-
-	return 0;
 }
 
 /* Probe functions for AEM2 devices */
@@ -720,7 +690,8 @@
 		data->power_period[i] = AEM_DEFAULT_POWER_INTERVAL;
 
 	/* Create sub-device for this fw instance */
-	if (aem_idr_get(&data->id))
+	data->id = ida_simple_get(&aem_ida, 0, 0, GFP_KERNEL);
+	if (data->id < 0)
 		goto id_err;
 
 	data->pdev = platform_device_alloc(DRVNAME, data->id);
@@ -735,24 +706,31 @@
 	platform_set_drvdata(data->pdev, data);
 
 	/* Set up IPMI interface */
-	if (aem_init_ipmi_data(&data->ipmi, probe->interface,
-			       probe->bmc_device))
+	res = aem_init_ipmi_data(&data->ipmi, probe->interface,
+				 probe->bmc_device);
+	if (res)
 		goto ipmi_err;
 
 	/* Register with hwmon */
 	data->hwmon_dev = hwmon_device_register(&data->pdev->dev);
-
 	if (IS_ERR(data->hwmon_dev)) {
 		dev_err(&data->pdev->dev, "Unable to register hwmon "
 			"device for IPMI interface %d\n",
 			probe->interface);
+		res = PTR_ERR(data->hwmon_dev);
 		goto hwmon_reg_err;
 	}
 
 	data->update = update_aem2_sensors;
+	data->rs_resp = kzalloc(sizeof(*(data->rs_resp)) + 8, GFP_KERNEL);
+	if (!data->rs_resp) {
+		res = -ENOMEM;
+		goto alloc_resp_err;
+	}
 
 	/* Find sensors */
-	if (aem2_find_sensors(data))
+	res = aem2_find_sensors(data);
+	if (res)
 		goto sensor_err;
 
 	/* Add to our list of AEM devices */
@@ -764,6 +742,8 @@
 	return 0;
 
 sensor_err:
+	kfree(data->rs_resp);
+alloc_resp_err:
 	hwmon_device_unregister(data->hwmon_dev);
 hwmon_reg_err:
 	ipmi_destroy_user(data->ipmi.user);
@@ -771,7 +751,7 @@
 	platform_set_drvdata(data->pdev, NULL);
 	platform_device_unregister(data->pdev);
 dev_err:
-	aem_idr_put(data->id);
+	ida_simple_remove(&aem_ida, data->id);
 id_err:
 	kfree(data);
 
@@ -779,7 +759,7 @@
 }
 
 /* Find and initialize all AEM2 instances */
-static int aem_init_aem2(struct aem_ipmi_data *probe)
+static void aem_init_aem2(struct aem_ipmi_data *probe)
 {
 	struct aem_find_instance_resp fi_resp;
 	int err;
@@ -798,12 +778,9 @@
 			dev_err(probe->bmc_device,
 				"Error %d initializing AEM2 0x%X\n",
 				err, fi_resp.module_handle);
-			return err;
 		}
 		i++;
 	}
-
-	return 0;
 }
 
 /* Probe a BMC for AEM firmware instances */
diff -druN linux-libre-3.1-gnu/drivers/hwmon/jc42.c linux-libre-3.2-gnu/drivers/hwmon/jc42.c
--- linux-libre-3.1-gnu/drivers/hwmon/jc42.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/jc42.c	2012-01-04 18:55:44.000000000 -0500
@@ -154,8 +154,6 @@
 		      const struct i2c_device_id *id);
 static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info);
 static int jc42_remove(struct i2c_client *client);
-static int jc42_read_value(struct i2c_client *client, u8 reg);
-static int jc42_write_value(struct i2c_client *client, u8 reg, u16 value);
 
 static struct jc42_data *jc42_update_device(struct device *dev);
 
@@ -187,7 +185,7 @@
 	struct jc42_data *data = i2c_get_clientdata(client);
 
 	data->config |= JC42_CFG_SHUTDOWN;
-	jc42_write_value(client, JC42_REG_CONFIG, data->config);
+	i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, data->config);
 	return 0;
 }
 
@@ -197,7 +195,7 @@
 	struct jc42_data *data = i2c_get_clientdata(client);
 
 	data->config &= ~JC42_CFG_SHUTDOWN;
-	jc42_write_value(client, JC42_REG_CONFIG, data->config);
+	i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, data->config);
 	return 0;
 }
 
@@ -315,7 +313,7 @@
 		return -EINVAL;						\
 	mutex_lock(&data->update_lock);					\
 	data->value = jc42_temp_to_reg(val, data->extended);		\
-	err = jc42_write_value(client, reg, data->value);		\
+	err = i2c_smbus_write_word_swapped(client, reg, data->value);	\
 	if (err < 0)							\
 		ret = err;						\
 	mutex_unlock(&data->update_lock);				\
@@ -357,7 +355,8 @@
 	data->config = (data->config
 			& ~(JC42_CFG_HYST_MASK << JC42_CFG_HYST_SHIFT))
 	  | (hyst << JC42_CFG_HYST_SHIFT);
-	err = jc42_write_value(client, JC42_REG_CONFIG, data->config);
+	err = i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG,
+					   data->config);
 	if (err < 0)
 		ret = err;
 	mutex_unlock(&data->update_lock);
@@ -452,10 +451,10 @@
 				     I2C_FUNC_SMBUS_WORD_DATA))
 		return -ENODEV;
 
-	cap = jc42_read_value(new_client, JC42_REG_CAP);
-	config = jc42_read_value(new_client, JC42_REG_CONFIG);
-	manid = jc42_read_value(new_client, JC42_REG_MANID);
-	devid = jc42_read_value(new_client, JC42_REG_DEVICEID);
+	cap = i2c_smbus_read_word_swapped(new_client, JC42_REG_CAP);
+	config = i2c_smbus_read_word_swapped(new_client, JC42_REG_CONFIG);
+	manid = i2c_smbus_read_word_swapped(new_client, JC42_REG_MANID);
+	devid = i2c_smbus_read_word_swapped(new_client, JC42_REG_DEVICEID);
 
 	if (cap < 0 || config < 0 || manid < 0 || devid < 0)
 		return -ENODEV;
@@ -489,14 +488,14 @@
 	i2c_set_clientdata(new_client, data);
 	mutex_init(&data->update_lock);
 
-	cap = jc42_read_value(new_client, JC42_REG_CAP);
+	cap = i2c_smbus_read_word_swapped(new_client, JC42_REG_CAP);
 	if (cap < 0) {
 		err = -EINVAL;
 		goto exit_free;
 	}
 	data->extended = !!(cap & JC42_CAP_RANGE);
 
-	config = jc42_read_value(new_client, JC42_REG_CONFIG);
+	config = i2c_smbus_read_word_swapped(new_client, JC42_REG_CONFIG);
 	if (config < 0) {
 		err = -EINVAL;
 		goto exit_free;
@@ -504,7 +503,8 @@
 	data->orig_config = config;
 	if (config & JC42_CFG_SHUTDOWN) {
 		config &= ~JC42_CFG_SHUTDOWN;
-		jc42_write_value(new_client, JC42_REG_CONFIG, config);
+		i2c_smbus_write_word_swapped(new_client, JC42_REG_CONFIG,
+					     config);
 	}
 	data->config = config;
 
@@ -535,25 +535,12 @@
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &jc42_group);
 	if (data->config != data->orig_config)
-		jc42_write_value(client, JC42_REG_CONFIG, data->orig_config);
+		i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG,
+					     data->orig_config);
 	kfree(data);
 	return 0;
 }
 
-/* All registers are word-sized. */
-static int jc42_read_value(struct i2c_client *client, u8 reg)
-{
-	int ret = i2c_smbus_read_word_data(client, reg);
-	if (ret < 0)
-		return ret;
-	return swab16(ret);
-}
-
-static int jc42_write_value(struct i2c_client *client, u8 reg, u16 value)
-{
-	return i2c_smbus_write_word_data(client, reg, swab16(value));
-}
-
 static struct jc42_data *jc42_update_device(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -564,28 +551,29 @@
 	mutex_lock(&data->update_lock);
 
 	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
-		val = jc42_read_value(client, JC42_REG_TEMP);
+		val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP);
 		if (val < 0) {
 			ret = ERR_PTR(val);
 			goto abort;
 		}
 		data->temp_input = val;
 
-		val = jc42_read_value(client, JC42_REG_TEMP_CRITICAL);
+		val = i2c_smbus_read_word_swapped(client,
+						  JC42_REG_TEMP_CRITICAL);
 		if (val < 0) {
 			ret = ERR_PTR(val);
 			goto abort;
 		}
 		data->temp_crit = val;
 
-		val = jc42_read_value(client, JC42_REG_TEMP_LOWER);
+		val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP_LOWER);
 		if (val < 0) {
 			ret = ERR_PTR(val);
 			goto abort;
 		}
 		data->temp_min = val;
 
-		val = jc42_read_value(client, JC42_REG_TEMP_UPPER);
+		val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP_UPPER);
 		if (val < 0) {
 			ret = ERR_PTR(val);
 			goto abort;
diff -druN linux-libre-3.1-gnu/drivers/hwmon/jz4740-hwmon.c linux-libre-3.2-gnu/drivers/hwmon/jz4740-hwmon.c
--- linux-libre-3.1-gnu/drivers/hwmon/jz4740-hwmon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/jz4740-hwmon.c	2012-01-04 18:55:44.000000000 -0500
@@ -59,7 +59,7 @@
 {
 	struct jz4740_hwmon *hwmon = dev_get_drvdata(dev);
 	struct completion *completion = &hwmon->read_completion;
-	unsigned long t;
+	long t;
 	unsigned long val;
 	int ret;
 
@@ -203,7 +203,7 @@
 	return 0;
 }
 
-struct platform_driver jz4740_hwmon_driver = {
+static struct platform_driver jz4740_hwmon_driver = {
 	.probe	= jz4740_hwmon_probe,
 	.remove = __devexit_p(jz4740_hwmon_remove),
 	.driver = {
@@ -212,17 +212,7 @@
 	},
 };
 
-static int __init jz4740_hwmon_init(void)
-{
-	return platform_driver_register(&jz4740_hwmon_driver);
-}
-module_init(jz4740_hwmon_init);
-
-static void __exit jz4740_hwmon_exit(void)
-{
-	platform_driver_unregister(&jz4740_hwmon_driver);
-}
-module_exit(jz4740_hwmon_exit);
+module_platform_driver(jz4740_hwmon_driver);
 
 MODULE_DESCRIPTION("JZ4740 SoC HWMON driver");
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
diff -druN linux-libre-3.1-gnu/drivers/hwmon/Kconfig linux-libre-3.2-gnu/drivers/hwmon/Kconfig
--- linux-libre-3.1-gnu/drivers/hwmon/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -68,6 +68,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called abituguru3.
 
+config SENSORS_AD7314
+	tristate "Analog Devices AD7314 and compatibles"
+	depends on SPI && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Analog Devices
+	  AD7314, ADT7301 and ADT7302 temperature sensors.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called ad7314.
+
 config SENSORS_AD7414
 	tristate "Analog Devices AD7414"
 	depends on I2C && EXPERIMENTAL
@@ -303,6 +313,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called ds1621.
 
+config SENSORS_EXYNOS4_TMU
+	tristate "Temperature sensor on Samsung EXYNOS4"
+	depends on ARCH_EXYNOS4
+	help
+	  If you say yes here you get support for TMU (Thermal Managment
+	  Unit) on SAMSUNG EXYNOS4 series of SoC.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called exynos4-tmu.
+
 config SENSORS_I5K_AMB
 	tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets"
 	depends on PCI && EXPERIMENTAL
@@ -315,6 +335,7 @@
 
 config SENSORS_F71805F
 	tristate "Fintek F71805F/FG, F71806F/FG and F71872F/FG"
+	depends on !PPC
 	help
 	  If you say yes here you get support for hardware monitoring
 	  features of the Fintek F71805F/FG, F71806F/FG and F71872F/FG
@@ -325,6 +346,7 @@
 
 config SENSORS_F71882FG
 	tristate "Fintek F71882FG and compatibles"
+	depends on !PPC
 	help
 	  If you say yes here you get support for hardware monitoring
 	  features of many Fintek Super-I/O (LPC) chips. The currently
@@ -448,6 +470,7 @@
 
 config SENSORS_IT87
 	tristate "ITE IT87xx and compatibles"
+	depends on !PPC
 	select HWMON_VID
 	help
 	  If you say yes here you get support for ITE IT8705F, IT8712F,
@@ -531,6 +554,7 @@
 	  If you say yes here you get support for one common type of
 	  temperature sensor chip, with models including:
 
+		- Analog Devices ADT75
 		- Dallas Semiconductor DS75 and DS1775
 		- Maxim MAX6625 and MAX6626
 		- Microchip MCP980x
@@ -803,6 +827,7 @@
 
 config SENSORS_PC87360
 	tristate "National Semiconductor PC87360 family"
+	depends on !PPC
 	select HWMON_VID
 	help
 	  If you say yes here you get access to the hardware monitoring
@@ -816,6 +841,7 @@
 
 config SENSORS_PC87427
 	tristate "National Semiconductor PC87427"
+	depends on !PPC
 	help
 	  If you say yes here you get access to the hardware monitoring
 	  functions of the National Semiconductor PC87427 Super-I/O chip.
@@ -907,7 +933,7 @@
 
 config SENSORS_DME1737
 	tristate "SMSC DME1737, SCH311x and compatibles"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C && EXPERIMENTAL && !PPC
 	select HWMON_VID
 	help
 	  If you say yes here you get support for the hardware monitoring
@@ -949,6 +975,7 @@
 
 config SENSORS_SMSC47M1
 	tristate "SMSC LPC47M10x and compatibles"
+	depends on !PPC
 	help
 	  If you say yes here you get support for the integrated fan
 	  monitoring and control capabilities of the SMSC LPC47B27x,
@@ -982,7 +1009,7 @@
 
 config SENSORS_SMSC47B397
 	tristate "SMSC LPC47B397-NC"
-	depends on EXPERIMENTAL
+	depends on EXPERIMENTAL && !PPC
 	help
 	  If you say yes here you get support for the SMSC LPC47B397-NC
 	  sensor chip.
@@ -996,6 +1023,7 @@
 
 config SENSORS_SCH5627
 	tristate "SMSC SCH5627"
+	depends on !PPC
 	select SENSORS_SCH56XX_COMMON
 	help
 	  If you say yes here you get support for the hardware monitoring
@@ -1006,6 +1034,7 @@
 
 config SENSORS_SCH5636
 	tristate "SMSC SCH5636"
+	depends on !PPC
 	select SENSORS_SCH56XX_COMMON
 	help
 	  SMSC SCH5636 Super I/O chips include an embedded microcontroller for
@@ -1129,6 +1158,7 @@
 
 config SENSORS_VT1211
 	tristate "VIA VT1211"
+	depends on !PPC
 	select HWMON_VID
 	help
 	  If you say yes here then you get support for hardware monitoring
@@ -1241,6 +1271,7 @@
 
 config SENSORS_W83627HF
 	tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF"
+	depends on !PPC
 	select HWMON_VID
 	help
 	  If you say yes here you get support for the Winbond W836X7 series
@@ -1251,7 +1282,8 @@
 	  will be called w83627hf.
 
 config SENSORS_W83627EHF
-	tristate "Winbond W83627EHF/EHG/DHG, W83667HG, NCT6775F, NCT6776F"
+	tristate "Winbond W83627EHF/EHG/DHG/UHG, W83667HG, NCT6775F, NCT6776F"
+	depends on !PPC
 	select HWMON_VID
 	help
 	  If you say yes here you get support for the hardware
@@ -1260,7 +1292,8 @@
 	  This driver also supports the W83627EHG, which is the lead-free
 	  version of the W83627EHF, and the W83627DHG, which is a similar
 	  chip suited for specific Intel processors that use PECI such as
-	  the Core 2 Duo.
+	  the Core 2 Duo. And also the W83627UHG, which is a stripped down
+	  version of the W83627DHG (as far as hardware monitoring goes.)
 
 	  This driver also supports Nuvoton W83667HG, W83667HG-B, NCT6775F
 	  (also known as W83667HG-I), and NCT6776F.
diff -druN linux-libre-3.1-gnu/drivers/hwmon/lm73.c linux-libre-3.2-gnu/drivers/hwmon/lm73.c
--- linux-libre-3.1-gnu/drivers/hwmon/lm73.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/lm73.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,7 +34,7 @@
 #define LM73_REG_CTRL		0x04
 #define LM73_REG_ID		0x07
 
-#define LM73_ID			0x9001 /* or 0x190 after a swab16() */
+#define LM73_ID			0x9001	/* 0x0190, byte-swapped */
 #define DRVNAME			"lm73"
 #define LM73_TEMP_MIN		(-40)
 #define LM73_TEMP_MAX		150
@@ -57,7 +57,7 @@
 	/* Write value */
 	value = (short) SENSORS_LIMIT(temp/250, (LM73_TEMP_MIN*4),
 		(LM73_TEMP_MAX*4)) << 5;
-	i2c_smbus_write_word_data(client, attr->index, swab16(value));
+	i2c_smbus_write_word_swapped(client, attr->index, value);
 	return count;
 }
 
@@ -68,8 +68,8 @@
 	struct i2c_client *client = to_i2c_client(dev);
 	/* use integer division instead of equivalent right shift to
 	   guarantee arithmetic shift and preserve the sign */
-	int temp = ((s16) (swab16(i2c_smbus_read_word_data(client,
-		attr->index)))*250) / 32;
+	int temp = ((s16) (i2c_smbus_read_word_swapped(client,
+		    attr->index))*250) / 32;
 	return sprintf(buf, "%d\n", temp);
 }
 
@@ -150,17 +150,31 @@
 			struct i2c_board_info *info)
 {
 	struct i2c_adapter *adapter = new_client->adapter;
-	u16 id;
-	u8 ctrl;
+	int id, ctrl, conf;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
 					I2C_FUNC_SMBUS_WORD_DATA))
 		return -ENODEV;
 
+	/*
+	 * Do as much detection as possible with byte reads first, as word
+	 * reads can confuse other devices.
+	 */
+	ctrl = i2c_smbus_read_byte_data(new_client, LM73_REG_CTRL);
+	if (ctrl < 0 || (ctrl & 0x10))
+		return -ENODEV;
+
+	conf = i2c_smbus_read_byte_data(new_client, LM73_REG_CONF);
+	if (conf < 0 || (conf & 0x0c))
+		return -ENODEV;
+
+	id = i2c_smbus_read_byte_data(new_client, LM73_REG_ID);
+	if (id < 0 || id != (LM73_ID & 0xff))
+		return -ENODEV;
+
 	/* Check device ID */
 	id = i2c_smbus_read_word_data(new_client, LM73_REG_ID);
-	ctrl = i2c_smbus_read_byte_data(new_client, LM73_REG_CTRL);
-	if ((id != LM73_ID) || (ctrl & 0x10))
+	if (id < 0 || id != LM73_ID)
 		return -ENODEV;
 
 	strlcpy(info->type, "lm73", I2C_NAME_SIZE);
diff -druN linux-libre-3.1-gnu/drivers/hwmon/lm75.c linux-libre-3.2-gnu/drivers/hwmon/lm75.c
--- linux-libre-3.1-gnu/drivers/hwmon/lm75.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/lm75.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
  */
 
 enum lm75_type {		/* keep sorted in alphabetical order */
+	adt75,
 	ds1775,
 	ds75,
 	lm75,
@@ -213,6 +214,7 @@
 }
 
 static const struct i2c_device_id lm75_ids[] = {
+	{ "adt75", adt75, },
 	{ "ds1775", ds1775, },
 	{ "ds75", ds75, },
 	{ "lm75", lm75, },
@@ -247,19 +249,30 @@
 				     I2C_FUNC_SMBUS_WORD_DATA))
 		return -ENODEV;
 
-	/* Now, we do the remaining detection. There is no identification-
-	   dedicated register so we have to rely on several tricks:
-	   unused bits, registers cycling over 8-address boundaries,
-	   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.
-
-	   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. */
+	/*
+	 * Now, we do the remaining detection. There is no identification-
+	 * dedicated register so we have to rely on several tricks:
+	 * unused bits, registers cycling over 8-address boundaries,
+	 * 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.
+	 *
+	 * 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.
+	 *
+	 * Note that this function only detects the original National
+	 * Semiconductor LM75 and the LM75A. Clones from other vendors
+	 * aren't detected, on purpose, because they are typically never
+	 * found on PC hardware. They are found on embedded designs where
+	 * they can be instantiated explicitly so detection is not needed.
+	 * The absence of identification registers on all these clones
+	 * would make their exhaustive detection very difficult and weak,
+	 * and odds are that the driver would bind to unsupported devices.
+	 */
 
 	/* Unused bits */
 	conf = i2c_smbus_read_byte_data(new_client, 1);
@@ -371,13 +384,10 @@
  */
 static int lm75_read_value(struct i2c_client *client, u8 reg)
 {
-	int value;
-
 	if (reg == LM75_REG_CONF)
 		return i2c_smbus_read_byte_data(client, reg);
-
-	value = i2c_smbus_read_word_data(client, reg);
-	return (value < 0) ? value : swab16(value);
+	else
+		return i2c_smbus_read_word_swapped(client, reg);
 }
 
 static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
@@ -385,7 +395,7 @@
 	if (reg == LM75_REG_CONF)
 		return i2c_smbus_write_byte_data(client, reg, value);
 	else
-		return i2c_smbus_write_word_data(client, reg, swab16(value));
+		return i2c_smbus_write_word_swapped(client, reg, value);
 }
 
 static struct lm75_data *lm75_update_device(struct device *dev)
diff -druN linux-libre-3.1-gnu/drivers/hwmon/lm77.c linux-libre-3.2-gnu/drivers/hwmon/lm77.c
--- linux-libre-3.1-gnu/drivers/hwmon/lm77.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/lm77.c	2012-01-04 18:55:44.000000000 -0500
@@ -365,7 +365,7 @@
 	if (reg == LM77_REG_CONF)
 		return i2c_smbus_read_byte_data(client, reg);
 	else
-		return swab16(i2c_smbus_read_word_data(client, reg));
+		return i2c_smbus_read_word_swapped(client, reg);
 }
 
 static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value)
@@ -373,7 +373,7 @@
 	if (reg == LM77_REG_CONF)
 		return i2c_smbus_write_byte_data(client, reg, value);
 	else
-		return i2c_smbus_write_word_data(client, reg, swab16(value));
+		return i2c_smbus_write_word_swapped(client, reg, value);
 }
 
 static void lm77_init_client(struct i2c_client *client)
diff -druN linux-libre-3.1-gnu/drivers/hwmon/lm90.c linux-libre-3.2-gnu/drivers/hwmon/lm90.c
--- linux-libre-3.1-gnu/drivers/hwmon/lm90.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/lm90.c	2012-01-04 18:55:44.000000000 -0500
@@ -1105,41 +1105,37 @@
  */
 
 /* Return 0 if detection is successful, -ENODEV otherwise */
-static int lm90_detect(struct i2c_client *new_client,
+static int lm90_detect(struct i2c_client *client,
 		       struct i2c_board_info *info)
 {
-	struct i2c_adapter *adapter = new_client->adapter;
-	int address = new_client->addr;
+	struct i2c_adapter *adapter = client->adapter;
+	int address = client->addr;
 	const char *name = NULL;
-	int man_id, chip_id, reg_config1, reg_config2, reg_convrate;
+	int man_id, chip_id, config1, config2, convrate;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
 
 	/* detection and identification */
-	if ((man_id = i2c_smbus_read_byte_data(new_client,
-						LM90_REG_R_MAN_ID)) < 0
-	 || (chip_id = i2c_smbus_read_byte_data(new_client,
-						LM90_REG_R_CHIP_ID)) < 0
-	 || (reg_config1 = i2c_smbus_read_byte_data(new_client,
-						LM90_REG_R_CONFIG1)) < 0
-	 || (reg_convrate = i2c_smbus_read_byte_data(new_client,
-						LM90_REG_R_CONVRATE)) < 0)
+	man_id = i2c_smbus_read_byte_data(client, LM90_REG_R_MAN_ID);
+	chip_id = i2c_smbus_read_byte_data(client, LM90_REG_R_CHIP_ID);
+	config1 = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG1);
+	convrate = i2c_smbus_read_byte_data(client, LM90_REG_R_CONVRATE);
+	if (man_id < 0 || chip_id < 0 || config1 < 0 || convrate < 0)
 		return -ENODEV;
 
 	if (man_id == 0x01 || man_id == 0x5C || man_id == 0x41) {
-		reg_config2 = i2c_smbus_read_byte_data(new_client,
-						LM90_REG_R_CONFIG2);
-		if (reg_config2 < 0)
+		config2 = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG2);
+		if (config2 < 0)
 			return -ENODEV;
 	} else
-		reg_config2 = 0;	/* Make compiler happy */
+		config2 = 0;		/* Make compiler happy */
 
 	if ((address == 0x4C || address == 0x4D)
 	 && man_id == 0x01) { /* National Semiconductor */
-		if ((reg_config1 & 0x2A) == 0x00
-		 && (reg_config2 & 0xF8) == 0x00
-		 && reg_convrate <= 0x09) {
+		if ((config1 & 0x2A) == 0x00
+		 && (config2 & 0xF8) == 0x00
+		 && convrate <= 0x09) {
 			if (address == 0x4C
 			 && (chip_id & 0xF0) == 0x20) { /* LM90 */
 				name = "lm90";
@@ -1163,8 +1159,8 @@
 	if ((address == 0x4C || address == 0x4D)
 	 && man_id == 0x41) { /* Analog Devices */
 		if ((chip_id & 0xF0) == 0x40 /* ADM1032 */
-		 && (reg_config1 & 0x3F) == 0x00
-		 && reg_convrate <= 0x0A) {
+		 && (config1 & 0x3F) == 0x00
+		 && convrate <= 0x0A) {
 			name = "adm1032";
 			/* The ADM1032 supports PEC, but only if combined
 			   transactions are not used. */
@@ -1173,18 +1169,18 @@
 				info->flags |= I2C_CLIENT_PEC;
 		} else
 		if (chip_id == 0x51 /* ADT7461 */
-		 && (reg_config1 & 0x1B) == 0x00
-		 && reg_convrate <= 0x0A) {
+		 && (config1 & 0x1B) == 0x00
+		 && convrate <= 0x0A) {
 			name = "adt7461";
 		} else
 		if (chip_id == 0x57 /* ADT7461A, NCT1008 */
-		 && (reg_config1 & 0x1B) == 0x00
-		 && reg_convrate <= 0x0A) {
+		 && (config1 & 0x1B) == 0x00
+		 && convrate <= 0x0A) {
 			name = "adt7461a";
 		}
 	} else
 	if (man_id == 0x4D) { /* Maxim */
-		int reg_emerg, reg_emerg2, reg_status2;
+		int emerg, emerg2, status2;
 
 		/*
 		 * We read MAX6659_REG_R_REMOTE_EMERG twice, and re-read
@@ -1192,13 +1188,15 @@
 		 * exists, both readings will reflect the same value. Otherwise,
 		 * the readings will be different.
 		 */
-		if ((reg_emerg = i2c_smbus_read_byte_data(new_client,
-						MAX6659_REG_R_REMOTE_EMERG)) < 0
-		 || i2c_smbus_read_byte_data(new_client, LM90_REG_R_MAN_ID) < 0
-		 || (reg_emerg2 = i2c_smbus_read_byte_data(new_client,
-						MAX6659_REG_R_REMOTE_EMERG)) < 0
-		 || (reg_status2 = i2c_smbus_read_byte_data(new_client,
-						MAX6696_REG_R_STATUS2)) < 0)
+		emerg = i2c_smbus_read_byte_data(client,
+						 MAX6659_REG_R_REMOTE_EMERG);
+		man_id = i2c_smbus_read_byte_data(client,
+						  LM90_REG_R_MAN_ID);
+		emerg2 = i2c_smbus_read_byte_data(client,
+						  MAX6659_REG_R_REMOTE_EMERG);
+		status2 = i2c_smbus_read_byte_data(client,
+						   MAX6696_REG_R_STATUS2);
+		if (emerg < 0 || man_id < 0 || emerg2 < 0 || status2 < 0)
 			return -ENODEV;
 
 		/*
@@ -1216,8 +1214,8 @@
 		 */
 		if (chip_id == man_id
 		 && (address == 0x4C || address == 0x4D || address == 0x4E)
-		 && (reg_config1 & 0x1F) == (man_id & 0x0F)
-		 && reg_convrate <= 0x09) {
+		 && (config1 & 0x1F) == (man_id & 0x0F)
+		 && convrate <= 0x09) {
 			if (address == 0x4C)
 				name = "max6657";
 			else
@@ -1235,10 +1233,10 @@
 		 * one of those registers exists.
 		 */
 		if (chip_id == 0x01
-		 && (reg_config1 & 0x10) == 0x00
-		 && (reg_status2 & 0x01) == 0x00
-		 && reg_emerg == reg_emerg2
-		 && reg_convrate <= 0x07) {
+		 && (config1 & 0x10) == 0x00
+		 && (status2 & 0x01) == 0x00
+		 && emerg == emerg2
+		 && convrate <= 0x07) {
 			name = "max6696";
 		} else
 		/*
@@ -1248,8 +1246,8 @@
 		 * second to last bit of config1 (software reset).
 		 */
 		if (chip_id == 0x01
-		 && (reg_config1 & 0x03) == 0x00
-		 && reg_convrate <= 0x07) {
+		 && (config1 & 0x03) == 0x00
+		 && convrate <= 0x07) {
 			name = "max6680";
 		} else
 		/*
@@ -1258,21 +1256,21 @@
 		 * register are unused and should return zero when read.
 		 */
 		if (chip_id == 0x59
-		 && (reg_config1 & 0x3f) == 0x00
-		 && reg_convrate <= 0x07) {
+		 && (config1 & 0x3f) == 0x00
+		 && convrate <= 0x07) {
 			name = "max6646";
 		}
 	} else
 	if (address == 0x4C
 	 && man_id == 0x5C) { /* Winbond/Nuvoton */
-		if ((reg_config1 & 0x2A) == 0x00
-		 && (reg_config2 & 0xF8) == 0x00) {
+		if ((config1 & 0x2A) == 0x00
+		 && (config2 & 0xF8) == 0x00) {
 			if (chip_id == 0x01 /* W83L771W/G */
-			 && reg_convrate <= 0x09) {
+			 && convrate <= 0x09) {
 				name = "w83l771";
 			} else
 			if ((chip_id & 0xFE) == 0x10 /* W83L771AWG/ASG */
-			 && reg_convrate <= 0x08) {
+			 && convrate <= 0x08) {
 				name = "w83l771";
 			}
 		}
@@ -1280,9 +1278,9 @@
 	if (address >= 0x48 && address <= 0x4F
 	 && man_id == 0xA1) { /*  NXP Semiconductor/Philips */
 		if (chip_id == 0x00
-		 && (reg_config1 & 0x2A) == 0x00
-		 && (reg_config2 & 0xFE) == 0x00
-		 && reg_convrate <= 0x09) {
+		 && (config1 & 0x2A) == 0x00
+		 && (config2 & 0xFE) == 0x00
+		 && convrate <= 0x09) {
 			name = "sa56004";
 		}
 	}
@@ -1301,19 +1299,18 @@
 
 static void lm90_remove_files(struct i2c_client *client, struct lm90_data *data)
 {
+	struct device *dev = &client->dev;
+
 	if (data->flags & LM90_HAVE_TEMP3)
-		sysfs_remove_group(&client->dev.kobj, &lm90_temp3_group);
+		sysfs_remove_group(&dev->kobj, &lm90_temp3_group);
 	if (data->flags & LM90_HAVE_EMERGENCY_ALARM)
-		sysfs_remove_group(&client->dev.kobj,
-				   &lm90_emergency_alarm_group);
+		sysfs_remove_group(&dev->kobj, &lm90_emergency_alarm_group);
 	if (data->flags & LM90_HAVE_EMERGENCY)
-		sysfs_remove_group(&client->dev.kobj,
-				   &lm90_emergency_group);
+		sysfs_remove_group(&dev->kobj, &lm90_emergency_group);
 	if (data->flags & LM90_HAVE_OFFSET)
-		device_remove_file(&client->dev,
-				   &sensor_dev_attr_temp2_offset.dev_attr);
-	device_remove_file(&client->dev, &dev_attr_pec);
-	sysfs_remove_group(&client->dev.kobj, &lm90_group);
+		device_remove_file(dev, &sensor_dev_attr_temp2_offset.dev_attr);
+	device_remove_file(dev, &dev_attr_pec);
+	sysfs_remove_group(&dev->kobj, &lm90_group);
 }
 
 static void lm90_init_client(struct i2c_client *client)
@@ -1362,10 +1359,11 @@
 		i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config);
 }
 
-static int lm90_probe(struct i2c_client *new_client,
+static int lm90_probe(struct i2c_client *client,
 		      const struct i2c_device_id *id)
 {
-	struct i2c_adapter *adapter = to_i2c_adapter(new_client->dev.parent);
+	struct device *dev = &client->dev;
+	struct i2c_adapter *adapter = to_i2c_adapter(dev->parent);
 	struct lm90_data *data;
 	int err;
 
@@ -1374,14 +1372,14 @@
 		err = -ENOMEM;
 		goto exit;
 	}
-	i2c_set_clientdata(new_client, data);
+	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
 
 	/* Set the device type */
 	data->kind = id->driver_data;
 	if (data->kind == adm1032) {
 		if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
-			new_client->flags &= ~I2C_CLIENT_PEC;
+			client->flags &= ~I2C_CLIENT_PEC;
 	}
 
 	/* Different devices have different alarm bits triggering the
@@ -1396,43 +1394,41 @@
 	data->max_convrate = lm90_params[data->kind].max_convrate;
 
 	/* Initialize the LM90 chip */
-	lm90_init_client(new_client);
+	lm90_init_client(client);
 
 	/* Register sysfs hooks */
-	err = sysfs_create_group(&new_client->dev.kobj, &lm90_group);
+	err = sysfs_create_group(&dev->kobj, &lm90_group);
 	if (err)
 		goto exit_free;
-	if (new_client->flags & I2C_CLIENT_PEC) {
-		err = device_create_file(&new_client->dev, &dev_attr_pec);
+	if (client->flags & I2C_CLIENT_PEC) {
+		err = device_create_file(dev, &dev_attr_pec);
 		if (err)
 			goto exit_remove_files;
 	}
 	if (data->flags & LM90_HAVE_OFFSET) {
-		err = device_create_file(&new_client->dev,
+		err = device_create_file(dev,
 					&sensor_dev_attr_temp2_offset.dev_attr);
 		if (err)
 			goto exit_remove_files;
 	}
 	if (data->flags & LM90_HAVE_EMERGENCY) {
-		err = sysfs_create_group(&new_client->dev.kobj,
-					 &lm90_emergency_group);
+		err = sysfs_create_group(&dev->kobj, &lm90_emergency_group);
 		if (err)
 			goto exit_remove_files;
 	}
 	if (data->flags & LM90_HAVE_EMERGENCY_ALARM) {
-		err = sysfs_create_group(&new_client->dev.kobj,
+		err = sysfs_create_group(&dev->kobj,
 					 &lm90_emergency_alarm_group);
 		if (err)
 			goto exit_remove_files;
 	}
 	if (data->flags & LM90_HAVE_TEMP3) {
-		err = sysfs_create_group(&new_client->dev.kobj,
-					 &lm90_temp3_group);
+		err = sysfs_create_group(&dev->kobj, &lm90_temp3_group);
 		if (err)
 			goto exit_remove_files;
 	}
 
-	data->hwmon_dev = hwmon_device_register(&new_client->dev);
+	data->hwmon_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->hwmon_dev)) {
 		err = PTR_ERR(data->hwmon_dev);
 		goto exit_remove_files;
@@ -1441,7 +1437,7 @@
 	return 0;
 
 exit_remove_files:
-	lm90_remove_files(new_client, data);
+	lm90_remove_files(client, data);
 exit_free:
 	kfree(data);
 exit:
diff -druN linux-libre-3.1-gnu/drivers/hwmon/lm92.c linux-libre-3.2-gnu/drivers/hwmon/lm92.c
--- linux-libre-3.1-gnu/drivers/hwmon/lm92.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/lm92.c	2012-01-04 18:55:44.000000000 -0500
@@ -117,16 +117,16 @@
 	if (time_after(jiffies, data->last_updated + HZ)
 	 || !data->valid) {
 		dev_dbg(&client->dev, "Updating lm92 data\n");
-		data->temp1_input = swab16(i2c_smbus_read_word_data(client,
-				    LM92_REG_TEMP));
-		data->temp1_hyst = swab16(i2c_smbus_read_word_data(client,
-				    LM92_REG_TEMP_HYST));
-		data->temp1_crit = swab16(i2c_smbus_read_word_data(client,
-				    LM92_REG_TEMP_CRIT));
-		data->temp1_min = swab16(i2c_smbus_read_word_data(client,
-				    LM92_REG_TEMP_LOW));
-		data->temp1_max = swab16(i2c_smbus_read_word_data(client,
-				    LM92_REG_TEMP_HIGH));
+		data->temp1_input = i2c_smbus_read_word_swapped(client,
+				    LM92_REG_TEMP);
+		data->temp1_hyst = i2c_smbus_read_word_swapped(client,
+				    LM92_REG_TEMP_HYST);
+		data->temp1_crit = i2c_smbus_read_word_swapped(client,
+				    LM92_REG_TEMP_CRIT);
+		data->temp1_min = i2c_smbus_read_word_swapped(client,
+				    LM92_REG_TEMP_LOW);
+		data->temp1_max = i2c_smbus_read_word_swapped(client,
+				    LM92_REG_TEMP_HIGH);
 
 		data->last_updated = jiffies;
 		data->valid = 1;
@@ -158,7 +158,7 @@
  \
 	mutex_lock(&data->update_lock); \
 	data->value = TEMP_TO_REG(val); \
-	i2c_smbus_write_word_data(client, reg, swab16(data->value)); \
+	i2c_smbus_write_word_swapped(client, reg, data->value); \
 	mutex_unlock(&data->update_lock); \
 	return count; \
 }
@@ -194,8 +194,8 @@
 
 	mutex_lock(&data->update_lock);
 	data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) - val;
-	i2c_smbus_write_word_data(client, LM92_REG_TEMP_HYST,
-				  swab16(TEMP_TO_REG(data->temp1_hyst)));
+	i2c_smbus_write_word_swapped(client, LM92_REG_TEMP_HYST,
+				     TEMP_TO_REG(data->temp1_hyst));
 	mutex_unlock(&data->update_lock);
 	return count;
 }
diff -druN linux-libre-3.1-gnu/drivers/hwmon/Makefile linux-libre-3.2-gnu/drivers/hwmon/Makefile
--- linux-libre-3.1-gnu/drivers/hwmon/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 
 obj-$(CONFIG_SENSORS_ABITUGURU)	+= abituguru.o
 obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o
+obj-$(CONFIG_SENSORS_AD7314)	+= ad7314.o
 obj-$(CONFIG_SENSORS_AD7414)	+= ad7414.o
 obj-$(CONFIG_SENSORS_AD7418)	+= ad7418.o
 obj-$(CONFIG_SENSORS_ADCXX)	+= adcxx.o
@@ -47,6 +48,7 @@
 obj-$(CONFIG_SENSORS_EMC1403)	+= emc1403.o
 obj-$(CONFIG_SENSORS_EMC2103)	+= emc2103.o
 obj-$(CONFIG_SENSORS_EMC6W201)	+= emc6w201.o
+obj-$(CONFIG_SENSORS_EXYNOS4_TMU)	+= exynos4_tmu.o
 obj-$(CONFIG_SENSORS_F71805F)	+= f71805f.o
 obj-$(CONFIG_SENSORS_F71882FG)	+= f71882fg.o
 obj-$(CONFIG_SENSORS_F75375S)	+= f75375s.o
diff -druN linux-libre-3.1-gnu/drivers/hwmon/max16065.c linux-libre-3.2-gnu/drivers/hwmon/max16065.c
--- linux-libre-3.1-gnu/drivers/hwmon/max16065.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/max16065.c	2012-01-04 18:55:44.000000000 -0500
@@ -137,10 +137,10 @@
 {
 	int rv;
 
-	rv = i2c_smbus_read_word_data(client, reg);
+	rv = i2c_smbus_read_word_swapped(client, reg);
 	if (unlikely(rv < 0))
 		return rv;
-	return ((rv & 0xff) << 2) | ((rv >> 14) & 0x03);
+	return rv >> 6;
 }
 
 static struct max16065_data *max16065_update_device(struct device *dev)
diff -druN linux-libre-3.1-gnu/drivers/hwmon/mc13783-adc.c linux-libre-3.2-gnu/drivers/hwmon/mc13783-adc.c
--- linux-libre-3.1-gnu/drivers/hwmon/mc13783-adc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/mc13783-adc.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,7 @@
 #define MC13783_ADC_NAME	"mc13783-adc"
 
 struct mc13783_adc_priv {
-	struct mc13783 *mc13783;
+	struct mc13xxx *mc13xxx;
 	struct device *hwmon_dev;
 };
 
@@ -51,8 +51,8 @@
 	unsigned int sample[4];
 	int ret;
 
-	ret = mc13783_adc_do_conversion(priv->mc13783,
-			MC13783_ADC_MODE_MULT_CHAN,
+	ret = mc13xxx_adc_do_conversion(priv->mc13xxx,
+			MC13XXX_ADC_MODE_MULT_CHAN,
 			channel, sample);
 	if (ret)
 		return ret;
@@ -147,9 +147,9 @@
 static int mc13783_adc_use_touchscreen(struct platform_device *pdev)
 {
 	struct mc13783_adc_priv *priv = platform_get_drvdata(pdev);
-	unsigned flags = mc13783_get_flags(priv->mc13783);
+	unsigned flags = mc13xxx_get_flags(priv->mc13xxx);
 
-	return flags & MC13783_USE_TOUCHSCREEN;
+	return flags & MC13XXX_USE_TOUCHSCREEN;
 }
 
 static int __init mc13783_adc_probe(struct platform_device *pdev)
@@ -161,7 +161,7 @@
 	if (!priv)
 		return -ENOMEM;
 
-	priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
+	priv->mc13xxx = dev_get_drvdata(pdev->dev.parent);
 
 	platform_set_drvdata(pdev, priv);
 
diff -druN linux-libre-3.1-gnu/drivers/hwmon/ntc_thermistor.c linux-libre-3.2-gnu/drivers/hwmon/ntc_thermistor.c
--- linux-libre-3.1-gnu/drivers/hwmon/ntc_thermistor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/ntc_thermistor.c	2012-01-04 18:55:44.000000000 -0500
@@ -432,19 +432,7 @@
 	.id_table = ntc_thermistor_id,
 };
 
-static int __init ntc_thermistor_init(void)
-{
-	return platform_driver_register(&ntc_thermistor_driver);
-}
-
-module_init(ntc_thermistor_init);
-
-static void __exit ntc_thermistor_cleanup(void)
-{
-	platform_driver_unregister(&ntc_thermistor_driver);
-}
-
-module_exit(ntc_thermistor_cleanup);
+module_platform_driver(ntc_thermistor_driver);
 
 MODULE_DESCRIPTION("NTC Thermistor Driver");
 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
diff -druN linux-libre-3.1-gnu/drivers/hwmon/pmbus/adm1275.c linux-libre-3.2-gnu/drivers/hwmon/pmbus/adm1275.c
--- linux-libre-3.1-gnu/drivers/hwmon/pmbus/adm1275.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/pmbus/adm1275.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,8 @@
 #include <linux/i2c.h>
 #include "pmbus.h"
 
+enum chips { adm1275, adm1276 };
+
 #define ADM1275_PEAK_IOUT		0xd0
 #define ADM1275_PEAK_VIN		0xd1
 #define ADM1275_PEAK_VOUT		0xd2
@@ -31,14 +33,47 @@
 #define ADM1275_VIN_VOUT_SELECT		(1 << 6)
 #define ADM1275_VRANGE			(1 << 5)
 
+#define ADM1275_IOUT_WARN2_LIMIT	0xd7
+#define ADM1275_DEVICE_CONFIG		0xd8
+
+#define ADM1275_IOUT_WARN2_SELECT	(1 << 4)
+
+#define ADM1276_PEAK_PIN		0xda
+
+#define ADM1275_MFR_STATUS_IOUT_WARN2	(1 << 0)
+
+struct adm1275_data {
+	int id;
+	bool have_oc_fault;
+	struct pmbus_driver_info info;
+};
+
+#define to_adm1275_data(x)  container_of(x, struct adm1275_data, info)
+
 static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
 {
-	int ret;
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	const struct adm1275_data *data = to_adm1275_data(info);
+	int ret = 0;
 
 	if (page)
-		return -EINVAL;
+		return -ENXIO;
 
 	switch (reg) {
+	case PMBUS_IOUT_UC_FAULT_LIMIT:
+		if (data->have_oc_fault) {
+			ret = -ENXIO;
+			break;
+		}
+		ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
+		break;
+	case PMBUS_IOUT_OC_FAULT_LIMIT:
+		if (!data->have_oc_fault) {
+			ret = -ENXIO;
+			break;
+		}
+		ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
+		break;
 	case PMBUS_VIRT_READ_IOUT_MAX:
 		ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT);
 		break;
@@ -48,10 +83,20 @@
 	case PMBUS_VIRT_READ_VIN_MAX:
 		ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN);
 		break;
+	case PMBUS_VIRT_READ_PIN_MAX:
+		if (data->id != adm1276) {
+			ret = -ENXIO;
+			break;
+		}
+		ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN);
+		break;
 	case PMBUS_VIRT_RESET_IOUT_HISTORY:
 	case PMBUS_VIRT_RESET_VOUT_HISTORY:
 	case PMBUS_VIRT_RESET_VIN_HISTORY:
-		ret = 0;
+		break;
+	case PMBUS_VIRT_RESET_PIN_HISTORY:
+		if (data->id != adm1276)
+			ret = -ENXIO;
 		break;
 	default:
 		ret = -ENODATA;
@@ -66,9 +111,14 @@
 	int ret;
 
 	if (page)
-		return -EINVAL;
+		return -ENXIO;
 
 	switch (reg) {
+	case PMBUS_IOUT_UC_FAULT_LIMIT:
+	case PMBUS_IOUT_OC_FAULT_LIMIT:
+		ret = pmbus_write_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT,
+					    word);
+		break;
 	case PMBUS_VIRT_RESET_IOUT_HISTORY:
 		ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0);
 		break;
@@ -78,6 +128,41 @@
 	case PMBUS_VIRT_RESET_VIN_HISTORY:
 		ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VIN, 0);
 		break;
+	case PMBUS_VIRT_RESET_PIN_HISTORY:
+		ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0);
+		break;
+	default:
+		ret = -ENODATA;
+		break;
+	}
+	return ret;
+}
+
+static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	const struct adm1275_data *data = to_adm1275_data(info);
+	int mfr_status, ret;
+
+	if (page > 0)
+		return -ENXIO;
+
+	switch (reg) {
+	case PMBUS_STATUS_IOUT:
+		ret = pmbus_read_byte_data(client, page, PMBUS_STATUS_IOUT);
+		if (ret < 0)
+			break;
+		mfr_status = pmbus_read_byte_data(client, page,
+						  PMBUS_STATUS_MFR_SPECIFIC);
+		if (mfr_status < 0) {
+			ret = mfr_status;
+			break;
+		}
+		if (mfr_status & ADM1275_MFR_STATUS_IOUT_WARN2) {
+			ret |= data->have_oc_fault ?
+			  PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT;
+		}
+		break;
 	default:
 		ret = -ENODATA;
 		break;
@@ -88,16 +173,17 @@
 static int adm1275_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
-	int config;
+	int config, device_config;
 	int ret;
 	struct pmbus_driver_info *info;
+	struct adm1275_data *data;
 
 	if (!i2c_check_functionality(client->adapter,
 				     I2C_FUNC_SMBUS_READ_BYTE_DATA))
 		return -ENODEV;
 
-	info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL);
-	if (!info)
+	data = kzalloc(sizeof(struct adm1275_data), GFP_KERNEL);
+	if (!data)
 		return -ENOMEM;
 
 	config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG);
@@ -106,6 +192,15 @@
 		goto err_mem;
 	}
 
+	device_config = i2c_smbus_read_byte_data(client, ADM1275_DEVICE_CONFIG);
+	if (device_config < 0) {
+		ret = device_config;
+		goto err_mem;
+	}
+
+	data->id = id->driver_data;
+	info = &data->info;
+
 	info->pages = 1;
 	info->format[PSC_VOLTAGE_IN] = direct;
 	info->format[PSC_VOLTAGE_OUT] = direct;
@@ -116,6 +211,7 @@
 	info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
 
 	info->read_word_data = adm1275_read_word_data;
+	info->read_byte_data = adm1275_read_byte_data;
 	info->write_word_data = adm1275_write_word_data;
 
 	if (config & ADM1275_VRANGE) {
@@ -134,10 +230,36 @@
 		info->R[PSC_VOLTAGE_OUT] = -1;
 	}
 
-	if (config & ADM1275_VIN_VOUT_SELECT)
-		info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
-	else
-		info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
+	if (device_config & ADM1275_IOUT_WARN2_SELECT)
+		data->have_oc_fault = true;
+
+	switch (id->driver_data) {
+	case adm1275:
+		if (config & ADM1275_VIN_VOUT_SELECT)
+			info->func[0] |=
+			  PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+		else
+			info->func[0] |=
+			  PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
+		break;
+	case adm1276:
+		info->format[PSC_POWER] = direct;
+		info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN
+		  | PMBUS_HAVE_STATUS_INPUT;
+		if (config & ADM1275_VIN_VOUT_SELECT)
+			info->func[0] |=
+			  PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+		if (config & ADM1275_VRANGE) {
+			info->m[PSC_POWER] = 6043;
+			info->b[PSC_POWER] = 0;
+			info->R[PSC_POWER] = -2;
+		} else {
+			info->m[PSC_POWER] = 2115;
+			info->b[PSC_POWER] = 0;
+			info->R[PSC_POWER] = -1;
+		}
+		break;
+	}
 
 	ret = pmbus_do_probe(client, id, info);
 	if (ret)
@@ -145,22 +267,23 @@
 	return 0;
 
 err_mem:
-	kfree(info);
+	kfree(data);
 	return ret;
 }
 
 static int adm1275_remove(struct i2c_client *client)
 {
 	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
-	int ret;
+	const struct adm1275_data *data = to_adm1275_data(info);
 
-	ret = pmbus_do_remove(client);
-	kfree(info);
-	return ret;
+	pmbus_do_remove(client);
+	kfree(data);
+	return 0;
 }
 
 static const struct i2c_device_id adm1275_id[] = {
-	{"adm1275", 0},
+	{ "adm1275", adm1275 },
+	{ "adm1276", adm1276 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adm1275_id);
@@ -185,7 +308,7 @@
 }
 
 MODULE_AUTHOR("Guenter Roeck");
-MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275");
+MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275 and compatibles");
 MODULE_LICENSE("GPL");
 module_init(adm1275_init);
 module_exit(adm1275_exit);
diff -druN linux-libre-3.1-gnu/drivers/hwmon/pmbus/Kconfig linux-libre-3.2-gnu/drivers/hwmon/pmbus/Kconfig
--- linux-libre-3.1-gnu/drivers/hwmon/pmbus/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/pmbus/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -20,17 +20,18 @@
 	help
 	  If you say yes here you get hardware monitoring support for generic
 	  PMBus devices, including but not limited to ADP4000, BMR450, BMR451,
-	  BMR453, BMR454, LTC2978, NCP4200, and NCP4208.
+	  BMR453, BMR454, NCP4200, and NCP4208.
 
 	  This driver can also be built as a module. If so, the module will
 	  be called pmbus.
 
 config SENSORS_ADM1275
-	tristate "Analog Devices ADM1275"
+	tristate "Analog Devices ADM1275 and compatibles"
 	default n
 	help
 	  If you say yes here you get hardware monitoring support for Analog
-	  Devices ADM1275 Hot-Swap Controller and Digital Power Monitor.
+	  Devices ADM1275 and ADM1276 Hot-Swap Controller and Digital Power
+	  Monitor.
 
 	  This driver can also be built as a module. If so, the module will
 	  be called adm1275.
@@ -45,6 +46,16 @@
 	  This driver can also be built as a module. If so, the module will
 	  be called lm25066.
 
+config SENSORS_LTC2978
+	tristate "Linear Technologies LTC2978 and LTC3880"
+	default n
+	help
+	  If you say yes here you get hardware monitoring support for Linear
+	  Technology LTC2978 and LTC3880.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called ltc2978.
+
 config SENSORS_MAX16064
 	tristate "Maxim MAX16064"
 	default n
@@ -97,4 +108,15 @@
 	  This driver can also be built as a module. If so, the module will
 	  be called ucd9200.
 
+config SENSORS_ZL6100
+	tristate "Intersil ZL6100 and compatibles"
+	default n
+	help
+	  If you say yes here you get hardware monitoring support for Intersil
+	  ZL2004, ZL2006, ZL2008, ZL2105, ZL2106, ZL6100, and ZL6105 Digital
+	  DC/DC Controllers.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called zl6100.
+
 endif # PMBUS
diff -druN linux-libre-3.1-gnu/drivers/hwmon/pmbus/lm25066.c linux-libre-3.2-gnu/drivers/hwmon/pmbus/lm25066.c
--- linux-libre-3.1-gnu/drivers/hwmon/pmbus/lm25066.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/pmbus/lm25066.c	2012-01-04 18:55:44.000000000 -0500
@@ -57,7 +57,7 @@
 	int ret;
 
 	if (page > 1)
-		return -EINVAL;
+		return -ENXIO;
 
 	/* Map READ_VAUX into READ_VOUT register on page 1 */
 	if (page == 1) {
@@ -85,7 +85,7 @@
 			break;
 		default:
 			/* No other valid registers on page 1 */
-			ret = -EINVAL;
+			ret = -ENXIO;
 			break;
 		}
 		goto done;
@@ -138,7 +138,7 @@
 	int ret;
 
 	if (page > 1)
-		return -EINVAL;
+		return -ENXIO;
 
 	switch (reg) {
 	case PMBUS_IIN_OC_WARN_LIMIT:
@@ -164,10 +164,10 @@
 static int lm25066_write_byte(struct i2c_client *client, int page, u8 value)
 {
 	if (page > 1)
-		return -EINVAL;
+		return -ENXIO;
 
-	if (page == 0)
-		return pmbus_write_byte(client, 0, value);
+	if (page <= 0)
+		return pmbus_write_byte(client, page, value);
 
 	return 0;
 }
@@ -309,11 +309,10 @@
 {
 	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 	const struct lm25066_data *data = to_lm25066_data(info);
-	int ret;
 
-	ret = pmbus_do_remove(client);
+	pmbus_do_remove(client);
 	kfree(data);
-	return ret;
+	return 0;
 }
 
 static const struct i2c_device_id lm25066_id[] = {
diff -druN linux-libre-3.1-gnu/drivers/hwmon/pmbus/ltc2978.c linux-libre-3.2-gnu/drivers/hwmon/pmbus/ltc2978.c
--- linux-libre-3.1-gnu/drivers/hwmon/pmbus/ltc2978.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hwmon/pmbus/ltc2978.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,408 @@
+/*
+ * Hardware monitoring driver for LTC2978 and LTC3880
+ *
+ * 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/slab.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+enum chips { ltc2978, ltc3880 };
+
+/* LTC2978 and LTC3880 */
+#define LTC2978_MFR_VOUT_PEAK		0xdd
+#define LTC2978_MFR_VIN_PEAK		0xde
+#define LTC2978_MFR_TEMPERATURE_PEAK	0xdf
+#define LTC2978_MFR_SPECIAL_ID		0xe7
+
+/* LTC2978 only */
+#define LTC2978_MFR_VOUT_MIN		0xfb
+#define LTC2978_MFR_VIN_MIN		0xfc
+#define LTC2978_MFR_TEMPERATURE_MIN	0xfd
+
+/* LTC3880 only */
+#define LTC3880_MFR_IOUT_PEAK		0xd7
+#define LTC3880_MFR_CLEAR_PEAKS		0xe3
+#define LTC3880_MFR_TEMPERATURE2_PEAK	0xf4
+
+#define LTC2978_ID_REV1			0x0121
+#define LTC2978_ID_REV2			0x0122
+#define LTC3880_ID			0x4000
+#define LTC3880_ID_MASK			0xff00
+
+/*
+ * LTC2978 clears peak data whenever the CLEAR_FAULTS command is executed, which
+ * happens pretty much each time chip data is updated. Raw peak data therefore
+ * does not provide much value. To be able to provide useful peak data, keep an
+ * internal cache of measured peak data, which is only cleared if an explicit
+ * "clear peak" command is executed for the sensor in question.
+ */
+struct ltc2978_data {
+	enum chips id;
+	int vin_min, vin_max;
+	int temp_min, temp_max;
+	int vout_min[8], vout_max[8];
+	int iout_max[2];
+	int temp2_max[2];
+	struct pmbus_driver_info info;
+};
+
+#define to_ltc2978_data(x)  container_of(x, struct ltc2978_data, info)
+
+static inline int lin11_to_val(int data)
+{
+	s16 e = ((s16)data) >> 11;
+	s32 m = (((s16)(data << 5)) >> 5);
+
+	/*
+	 * mantissa is 10 bit + sign, exponent adds up to 15 bit.
+	 * Add 6 bit to exponent for maximum accuracy (10 + 15 + 6 = 31).
+	 */
+	e += 6;
+	return (e < 0 ? m >> -e : m << e);
+}
+
+static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
+					 int reg)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct ltc2978_data *data = to_ltc2978_data(info);
+	int ret;
+
+	switch (reg) {
+	case PMBUS_VIRT_READ_VIN_MAX:
+		ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_PEAK);
+		if (ret >= 0) {
+			if (lin11_to_val(ret) > lin11_to_val(data->vin_max))
+				data->vin_max = ret;
+			ret = data->vin_max;
+		}
+		break;
+	case PMBUS_VIRT_READ_VOUT_MAX:
+		ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_PEAK);
+		if (ret >= 0) {
+			/*
+			 * VOUT is 16 bit unsigned with fixed exponent,
+			 * so we can compare it directly
+			 */
+			if (ret > data->vout_max[page])
+				data->vout_max[page] = ret;
+			ret = data->vout_max[page];
+		}
+		break;
+	case PMBUS_VIRT_READ_TEMP_MAX:
+		ret = pmbus_read_word_data(client, page,
+					   LTC2978_MFR_TEMPERATURE_PEAK);
+		if (ret >= 0) {
+			if (lin11_to_val(ret) > lin11_to_val(data->temp_max))
+				data->temp_max = ret;
+			ret = data->temp_max;
+		}
+		break;
+	case PMBUS_VIRT_RESET_VOUT_HISTORY:
+	case PMBUS_VIRT_RESET_VIN_HISTORY:
+	case PMBUS_VIRT_RESET_TEMP_HISTORY:
+		ret = 0;
+		break;
+	default:
+		ret = -ENODATA;
+		break;
+	}
+	return ret;
+}
+
+static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct ltc2978_data *data = to_ltc2978_data(info);
+	int ret;
+
+	switch (reg) {
+	case PMBUS_VIRT_READ_VIN_MIN:
+		ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_MIN);
+		if (ret >= 0) {
+			if (lin11_to_val(ret) < lin11_to_val(data->vin_min))
+				data->vin_min = ret;
+			ret = data->vin_min;
+		}
+		break;
+	case PMBUS_VIRT_READ_VOUT_MIN:
+		ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_MIN);
+		if (ret >= 0) {
+			/*
+			 * VOUT_MIN is known to not be supported on some lots
+			 * of LTC2978 revision 1, and will return the maximum
+			 * possible voltage if read. If VOUT_MAX is valid and
+			 * lower than the reading of VOUT_MIN, use it instead.
+			 */
+			if (data->vout_max[page] && ret > data->vout_max[page])
+				ret = data->vout_max[page];
+			if (ret < data->vout_min[page])
+				data->vout_min[page] = ret;
+			ret = data->vout_min[page];
+		}
+		break;
+	case PMBUS_VIRT_READ_TEMP_MIN:
+		ret = pmbus_read_word_data(client, page,
+					   LTC2978_MFR_TEMPERATURE_MIN);
+		if (ret >= 0) {
+			if (lin11_to_val(ret)
+			    < lin11_to_val(data->temp_min))
+				data->temp_min = ret;
+			ret = data->temp_min;
+		}
+		break;
+	case PMBUS_VIRT_READ_IOUT_MAX:
+	case PMBUS_VIRT_RESET_IOUT_HISTORY:
+	case PMBUS_VIRT_READ_TEMP2_MAX:
+	case PMBUS_VIRT_RESET_TEMP2_HISTORY:
+		ret = -ENXIO;
+		break;
+	default:
+		ret = ltc2978_read_word_data_common(client, page, reg);
+		break;
+	}
+	return ret;
+}
+
+static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct ltc2978_data *data = to_ltc2978_data(info);
+	int ret;
+
+	switch (reg) {
+	case PMBUS_VIRT_READ_IOUT_MAX:
+		ret = pmbus_read_word_data(client, page, LTC3880_MFR_IOUT_PEAK);
+		if (ret >= 0) {
+			if (lin11_to_val(ret)
+			    > lin11_to_val(data->iout_max[page]))
+				data->iout_max[page] = ret;
+			ret = data->iout_max[page];
+		}
+		break;
+	case PMBUS_VIRT_READ_TEMP2_MAX:
+		ret = pmbus_read_word_data(client, page,
+					   LTC3880_MFR_TEMPERATURE2_PEAK);
+		if (ret >= 0) {
+			if (lin11_to_val(ret)
+			    > lin11_to_val(data->temp2_max[page]))
+				data->temp2_max[page] = ret;
+			ret = data->temp2_max[page];
+		}
+		break;
+	case PMBUS_VIRT_READ_VIN_MIN:
+	case PMBUS_VIRT_READ_VOUT_MIN:
+	case PMBUS_VIRT_READ_TEMP_MIN:
+		ret = -ENXIO;
+		break;
+	case PMBUS_VIRT_RESET_IOUT_HISTORY:
+	case PMBUS_VIRT_RESET_TEMP2_HISTORY:
+		ret = 0;
+		break;
+	default:
+		ret = ltc2978_read_word_data_common(client, page, reg);
+		break;
+	}
+	return ret;
+}
+
+static int ltc2978_clear_peaks(struct i2c_client *client, int page,
+			       enum chips id)
+{
+	int ret;
+
+	if (id == ltc2978)
+		ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
+	else
+		ret = pmbus_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS);
+
+	return ret;
+}
+
+static int ltc2978_write_word_data(struct i2c_client *client, int page,
+				    int reg, u16 word)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct ltc2978_data *data = to_ltc2978_data(info);
+	int ret;
+
+	switch (reg) {
+	case PMBUS_VIRT_RESET_IOUT_HISTORY:
+		data->iout_max[page] = 0x7fff;
+		ret = ltc2978_clear_peaks(client, page, data->id);
+		break;
+	case PMBUS_VIRT_RESET_TEMP2_HISTORY:
+		data->temp2_max[page] = 0x7fff;
+		ret = ltc2978_clear_peaks(client, page, data->id);
+		break;
+	case PMBUS_VIRT_RESET_VOUT_HISTORY:
+		data->vout_min[page] = 0xffff;
+		data->vout_max[page] = 0;
+		ret = ltc2978_clear_peaks(client, page, data->id);
+		break;
+	case PMBUS_VIRT_RESET_VIN_HISTORY:
+		data->vin_min = 0x7bff;
+		data->vin_max = 0;
+		ret = ltc2978_clear_peaks(client, page, data->id);
+		break;
+	case PMBUS_VIRT_RESET_TEMP_HISTORY:
+		data->temp_min = 0x7bff;
+		data->temp_max = 0x7fff;
+		ret = ltc2978_clear_peaks(client, page, data->id);
+		break;
+	default:
+		ret = -ENODATA;
+		break;
+	}
+	return ret;
+}
+
+static const struct i2c_device_id ltc2978_id[] = {
+	{"ltc2978", ltc2978},
+	{"ltc3880", ltc3880},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, ltc2978_id);
+
+static int ltc2978_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	int chip_id, ret, i;
+	struct ltc2978_data *data;
+	struct pmbus_driver_info *info;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_READ_WORD_DATA))
+		return -ENODEV;
+
+	data = kzalloc(sizeof(struct ltc2978_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	chip_id = i2c_smbus_read_word_data(client, LTC2978_MFR_SPECIAL_ID);
+	if (chip_id < 0) {
+		ret = chip_id;
+		goto err_mem;
+	}
+
+	if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2) {
+		data->id = ltc2978;
+	} else if ((chip_id & LTC3880_ID_MASK) == LTC3880_ID) {
+		data->id = ltc3880;
+	} else {
+		dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id);
+		ret = -ENODEV;
+		goto err_mem;
+	}
+	if (data->id != id->driver_data)
+		dev_warn(&client->dev,
+			 "Device mismatch: Configured %s, detected %s\n",
+			 id->name,
+			 ltc2978_id[data->id].name);
+
+	info = &data->info;
+	info->write_word_data = ltc2978_write_word_data;
+
+	data->vout_min[0] = 0xffff;
+	data->vin_min = 0x7bff;
+	data->temp_min = 0x7bff;
+	data->temp_max = 0x7fff;
+
+	switch (id->driver_data) {
+	case ltc2978:
+		info->read_word_data = ltc2978_read_word_data;
+		info->pages = 8;
+		info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
+		  | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+		for (i = 1; i < 8; i++) {
+			info->func[i] = PMBUS_HAVE_VOUT
+			  | PMBUS_HAVE_STATUS_VOUT;
+			data->vout_min[i] = 0xffff;
+		}
+		break;
+	case ltc3880:
+		info->read_word_data = ltc3880_read_word_data;
+		info->pages = 2;
+		info->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_POUT | PMBUS_HAVE_TEMP
+		  | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
+		info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+		  | PMBUS_HAVE_POUT
+		  | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+		data->vout_min[1] = 0xffff;
+		break;
+	default:
+		ret = -ENODEV;
+		goto err_mem;
+	}
+
+	ret = pmbus_do_probe(client, id, info);
+	if (ret)
+		goto err_mem;
+	return 0;
+
+err_mem:
+	kfree(data);
+	return ret;
+}
+
+static int ltc2978_remove(struct i2c_client *client)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	const struct ltc2978_data *data = to_ltc2978_data(info);
+
+	pmbus_do_remove(client);
+	kfree(data);
+	return 0;
+}
+
+/* This is the driver that will be inserted */
+static struct i2c_driver ltc2978_driver = {
+	.driver = {
+		   .name = "ltc2978",
+		   },
+	.probe = ltc2978_probe,
+	.remove = ltc2978_remove,
+	.id_table = ltc2978_id,
+};
+
+static int __init ltc2978_init(void)
+{
+	return i2c_add_driver(&ltc2978_driver);
+}
+
+static void __exit ltc2978_exit(void)
+{
+	i2c_del_driver(&ltc2978_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("PMBus driver for LTC2978 and LTC3880");
+MODULE_LICENSE("GPL");
+module_init(ltc2978_init);
+module_exit(ltc2978_exit);
diff -druN linux-libre-3.1-gnu/drivers/hwmon/pmbus/Makefile linux-libre-3.2-gnu/drivers/hwmon/pmbus/Makefile
--- linux-libre-3.1-gnu/drivers/hwmon/pmbus/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/pmbus/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -6,8 +6,10 @@
 obj-$(CONFIG_SENSORS_PMBUS)	+= pmbus.o
 obj-$(CONFIG_SENSORS_ADM1275)	+= adm1275.o
 obj-$(CONFIG_SENSORS_LM25066)	+= lm25066.o
+obj-$(CONFIG_SENSORS_LTC2978)	+= ltc2978.o
 obj-$(CONFIG_SENSORS_MAX16064)	+= max16064.o
 obj-$(CONFIG_SENSORS_MAX34440)	+= max34440.o
 obj-$(CONFIG_SENSORS_MAX8688)	+= max8688.o
 obj-$(CONFIG_SENSORS_UCD9000)	+= ucd9000.o
 obj-$(CONFIG_SENSORS_UCD9200)	+= ucd9200.o
+obj-$(CONFIG_SENSORS_ZL6100)	+= zl6100.o
diff -druN linux-libre-3.1-gnu/drivers/hwmon/pmbus/max16064.c linux-libre-3.2-gnu/drivers/hwmon/pmbus/max16064.c
--- linux-libre-3.1-gnu/drivers/hwmon/pmbus/max16064.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/pmbus/max16064.c	2012-01-04 18:55:44.000000000 -0500
@@ -105,7 +105,8 @@
 
 static int max16064_remove(struct i2c_client *client)
 {
-	return pmbus_do_remove(client);
+	pmbus_do_remove(client);
+	return 0;
 }
 
 static const struct i2c_device_id max16064_id[] = {
diff -druN linux-libre-3.1-gnu/drivers/hwmon/pmbus/max34440.c linux-libre-3.2-gnu/drivers/hwmon/pmbus/max34440.c
--- linux-libre-3.1-gnu/drivers/hwmon/pmbus/max34440.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/pmbus/max34440.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,12 +93,14 @@
 
 static int max34440_read_byte_data(struct i2c_client *client, int page, int reg)
 {
-	int ret;
+	int ret = 0;
 	int mfg_status;
 
-	ret = pmbus_set_page(client, page);
-	if (ret < 0)
-		return ret;
+	if (page >= 0) {
+		ret = pmbus_set_page(client, page);
+		if (ret < 0)
+			return ret;
+	}
 
 	switch (reg) {
 	case PMBUS_STATUS_IOUT:
@@ -224,7 +226,8 @@
 
 static int max34440_remove(struct i2c_client *client)
 {
-	return pmbus_do_remove(client);
+	pmbus_do_remove(client);
+	return 0;
 }
 
 static const struct i2c_device_id max34440_id[] = {
diff -druN linux-libre-3.1-gnu/drivers/hwmon/pmbus/max8688.c linux-libre-3.2-gnu/drivers/hwmon/pmbus/max8688.c
--- linux-libre-3.1-gnu/drivers/hwmon/pmbus/max8688.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/pmbus/max8688.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,7 +45,7 @@
 	int ret;
 
 	if (page)
-		return -EINVAL;
+		return -ENXIO;
 
 	switch (reg) {
 	case PMBUS_VIRT_READ_VOUT_MAX:
@@ -101,8 +101,8 @@
 	int ret = 0;
 	int mfg_status;
 
-	if (page)
-		return -EINVAL;
+	if (page > 0)
+		return -ENXIO;
 
 	switch (reg) {
 	case PMBUS_STATUS_VOUT:
@@ -182,7 +182,8 @@
 
 static int max8688_remove(struct i2c_client *client)
 {
-	return pmbus_do_remove(client);
+	pmbus_do_remove(client);
+	return 0;
 }
 
 static const struct i2c_device_id max8688_id[] = {
diff -druN linux-libre-3.1-gnu/drivers/hwmon/pmbus/pmbus.c linux-libre-3.2-gnu/drivers/hwmon/pmbus/pmbus.c
--- linux-libre-3.1-gnu/drivers/hwmon/pmbus/pmbus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/pmbus/pmbus.c	2012-01-04 18:55:44.000000000 -0500
@@ -187,13 +187,12 @@
 
 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);
+	pmbus_do_remove(client);
 	kfree(info);
-	return ret;
+	return 0;
 }
 
 /*
@@ -205,10 +204,13 @@
 	{"bmr451", 1},
 	{"bmr453", 1},
 	{"bmr454", 1},
-	{"ltc2978", 8},
 	{"ncp4200", 1},
 	{"ncp4208", 1},
+	{"pdt003", 1},
+	{"pdt006", 1},
+	{"pdt012", 1},
 	{"pmbus", 0},
+	{"udt020", 1},
 	{}
 };
 
diff -druN linux-libre-3.1-gnu/drivers/hwmon/pmbus/pmbus_core.c linux-libre-3.2-gnu/drivers/hwmon/pmbus/pmbus_core.c
--- linux-libre-3.1-gnu/drivers/hwmon/pmbus/pmbus_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/pmbus/pmbus_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -160,7 +160,7 @@
 		rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
 		newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE);
 		if (newpage != page)
-			rv = -EINVAL;
+			rv = -EIO;
 		else
 			data->currpage = page;
 	}
@@ -229,7 +229,7 @@
 			return status;
 	}
 	if (reg >= PMBUS_VIRT_BASE)
-		return -EINVAL;
+		return -ENXIO;
 	return pmbus_write_word_data(client, page, reg, word);
 }
 
@@ -261,7 +261,7 @@
 			return status;
 	}
 	if (reg >= PMBUS_VIRT_BASE)
-		return -EINVAL;
+		return -ENXIO;
 	return pmbus_read_word_data(client, page, reg);
 }
 
@@ -316,11 +316,11 @@
 {
 	int status, status2;
 
-	status = pmbus_read_byte_data(client, -1, PMBUS_STATUS_BYTE);
+	status = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_BYTE);
 	if (status < 0 || (status & PB_STATUS_CML)) {
-		status2 = pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML);
+		status2 = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML);
 		if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND))
-			return -EINVAL;
+			return -EIO;
 	}
 	return 0;
 }
@@ -371,8 +371,8 @@
 
 		for (i = 0; i < info->pages; i++)
 			data->status[PB_STATUS_BASE + i]
-			    = pmbus_read_byte_data(client, i,
-						   PMBUS_STATUS_BYTE);
+			    = _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;
@@ -445,13 +445,8 @@
 		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 */
+		exponent = ((s16)sensor->data) >> 11;
+		mantissa = ((s16)((sensor->data & 0x7ff) << 5)) >> 5;
 	}
 
 	val = mantissa;
@@ -1401,7 +1396,42 @@
 	}
 };
 
-static const struct pmbus_limit_attr temp_limit_attrs23[] = {
+static const struct pmbus_limit_attr temp_limit_attrs2[] = {
+	{
+		.reg = PMBUS_UT_WARN_LIMIT,
+		.low = true,
+		.attr = "min",
+		.alarm = "min_alarm",
+		.sbit = PB_TEMP_UT_WARNING,
+	}, {
+		.reg = PMBUS_UT_FAULT_LIMIT,
+		.low = true,
+		.attr = "lcrit",
+		.alarm = "lcrit_alarm",
+		.sbit = PB_TEMP_UT_FAULT,
+	}, {
+		.reg = PMBUS_OT_WARN_LIMIT,
+		.attr = "max",
+		.alarm = "max_alarm",
+		.sbit = PB_TEMP_OT_WARNING,
+	}, {
+		.reg = PMBUS_OT_FAULT_LIMIT,
+		.attr = "crit",
+		.alarm = "crit_alarm",
+		.sbit = PB_TEMP_OT_FAULT,
+	}, {
+		.reg = PMBUS_VIRT_READ_TEMP2_MIN,
+		.attr = "lowest",
+	}, {
+		.reg = PMBUS_VIRT_READ_TEMP2_MAX,
+		.attr = "highest",
+	}, {
+		.reg = PMBUS_VIRT_RESET_TEMP2_HISTORY,
+		.attr = "reset_history",
+	}
+};
+
+static const struct pmbus_limit_attr temp_limit_attrs3[] = {
 	{
 		.reg = PMBUS_UT_WARN_LIMIT,
 		.low = true,
@@ -1450,8 +1480,8 @@
 		.sfunc = PMBUS_HAVE_STATUS_TEMP,
 		.sbase = PB_STATUS_TEMP_BASE,
 		.gbit = PB_STATUS_TEMPERATURE,
-		.limit = temp_limit_attrs23,
-		.nlimit = ARRAY_SIZE(temp_limit_attrs23),
+		.limit = temp_limit_attrs2,
+		.nlimit = ARRAY_SIZE(temp_limit_attrs2),
 	}, {
 		.reg = PMBUS_READ_TEMPERATURE_3,
 		.class = PSC_TEMPERATURE,
@@ -1462,8 +1492,8 @@
 		.sfunc = PMBUS_HAVE_STATUS_TEMP,
 		.sbase = PB_STATUS_TEMP_BASE,
 		.gbit = PB_STATUS_TEMPERATURE,
-		.limit = temp_limit_attrs23,
-		.nlimit = ARRAY_SIZE(temp_limit_attrs23),
+		.limit = temp_limit_attrs3,
+		.nlimit = ARRAY_SIZE(temp_limit_attrs3),
 	}
 };
 
@@ -1593,10 +1623,10 @@
 static int pmbus_identify_common(struct i2c_client *client,
 				 struct pmbus_data *data)
 {
-	int vout_mode = -1, exponent;
+	int vout_mode = -1;
 
 	if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE))
-		vout_mode = pmbus_read_byte_data(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,
@@ -1607,11 +1637,7 @@
 			if (data->info->format[PSC_VOLTAGE_OUT] != linear)
 				return -ENODEV;
 
-			exponent = vout_mode & 0x1f;
-			/* and sign-extend it */
-			if (exponent & 0x10)
-				exponent |= ~0x1f;
-			data->exponent = exponent;
+			data->exponent = ((s8)(vout_mode << 3)) >> 3;
 			break;
 		case 1: /* VID mode         */
 			if (data->info->format[PSC_VOLTAGE_OUT] != vid)
@@ -1682,7 +1708,7 @@
 	if (info->pages <= 0 || info->pages > PMBUS_PAGES) {
 		dev_err(&client->dev, "Bad number of PMBus pages: %d\n",
 			info->pages);
-		ret = -EINVAL;
+		ret = -ENODEV;
 		goto out_data;
 	}
 
@@ -1764,7 +1790,7 @@
 }
 EXPORT_SYMBOL_GPL(pmbus_do_probe);
 
-int pmbus_do_remove(struct i2c_client *client)
+void pmbus_do_remove(struct i2c_client *client)
 {
 	struct pmbus_data *data = i2c_get_clientdata(client);
 	hwmon_device_unregister(data->hwmon_dev);
@@ -1774,7 +1800,6 @@
 	kfree(data->booleans);
 	kfree(data->sensors);
 	kfree(data);
-	return 0;
 }
 EXPORT_SYMBOL_GPL(pmbus_do_remove);
 
diff -druN linux-libre-3.1-gnu/drivers/hwmon/pmbus/pmbus.h linux-libre-3.2-gnu/drivers/hwmon/pmbus/pmbus.h
--- linux-libre-3.1-gnu/drivers/hwmon/pmbus/pmbus.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/pmbus/pmbus.h	2012-01-04 18:55:44.000000000 -0500
@@ -134,8 +134,16 @@
  * Semantics:
  * Virtual registers are all word size.
  * READ registers are read-only; writes are either ignored or return an error.
- * RESET registers are read/write. Reading returns zero (used for detection),
- * writing any value causes the associated history to be reset.
+ * RESET registers are read/write. Reading reset registers returns zero
+ * (used for detection), writing any value causes the associated history to be
+ * reset.
+ * Virtual registers have to be handled in device specific driver code. Chip
+ * driver code returns non-negative register values if a virtual register is
+ * supported, or a negative error code if not. The chip driver may return
+ * -ENODATA or any other error code in this case, though an error code other
+ * than -ENODATA is handled more efficiently and thus preferred. Either case,
+ * the calling PMBus core code will abort if the chip driver returns an error
+ * code when reading or writing virtual registers.
  */
 #define PMBUS_VIRT_BASE			0x100
 #define PMBUS_VIRT_READ_TEMP_MIN	(PMBUS_VIRT_BASE + 0)
@@ -160,6 +168,9 @@
 #define PMBUS_VIRT_READ_IOUT_MIN	(PMBUS_VIRT_BASE + 19)
 #define PMBUS_VIRT_READ_IOUT_MAX	(PMBUS_VIRT_BASE + 20)
 #define PMBUS_VIRT_RESET_IOUT_HISTORY	(PMBUS_VIRT_BASE + 21)
+#define PMBUS_VIRT_READ_TEMP2_MIN	(PMBUS_VIRT_BASE + 22)
+#define PMBUS_VIRT_READ_TEMP2_MAX	(PMBUS_VIRT_BASE + 23)
+#define PMBUS_VIRT_RESET_TEMP2_HISTORY	(PMBUS_VIRT_BASE + 24)
 
 /*
  * CAPABILITY
@@ -320,6 +331,12 @@
 	 * The following functions map manufacturing specific register values
 	 * to PMBus standard register values. Specify only if mapping is
 	 * necessary.
+	 * Functions return the register value (read) or zero (write) if
+	 * successful. A return value of -ENODATA indicates that there is no
+	 * manufacturer specific register, but that a standard PMBus register
+	 * may exist. Any other negative return value indicates that the
+	 * register does not exist, and that no attempt should be made to read
+	 * the standard register.
 	 */
 	int (*read_byte_data)(struct i2c_client *client, int page, int reg);
 	int (*read_word_data)(struct i2c_client *client, int page, int reg);
@@ -347,7 +364,7 @@
 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);
+void pmbus_do_remove(struct i2c_client *client);
 const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client
 						      *client);
 
diff -druN linux-libre-3.1-gnu/drivers/hwmon/pmbus/ucd9000.c linux-libre-3.2-gnu/drivers/hwmon/pmbus/ucd9000.c
--- linux-libre-3.1-gnu/drivers/hwmon/pmbus/ucd9000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/pmbus/ucd9000.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,8 +74,8 @@
 
 	switch (reg) {
 	case PMBUS_FAN_CONFIG_12:
-		if (page)
-			return -EINVAL;
+		if (page > 0)
+			return -ENXIO;
 
 		ret = ucd9000_get_fan_config(client, 0);
 		if (ret < 0)
@@ -88,8 +88,8 @@
 		ret = fan_config;
 		break;
 	case PMBUS_FAN_CONFIG_34:
-		if (page)
-			return -EINVAL;
+		if (page > 0)
+			return -ENXIO;
 
 		ret = ucd9000_get_fan_config(client, 2);
 		if (ret < 0)
@@ -239,13 +239,12 @@
 
 static int ucd9000_remove(struct i2c_client *client)
 {
-	int ret;
 	struct ucd9000_data *data;
 
 	data = to_ucd9000_data(pmbus_get_driver_info(client));
-	ret = pmbus_do_remove(client);
+	pmbus_do_remove(client);
 	kfree(data);
-	return ret;
+	return 0;
 }
 
 
diff -druN linux-libre-3.1-gnu/drivers/hwmon/pmbus/ucd9200.c linux-libre-3.2-gnu/drivers/hwmon/pmbus/ucd9200.c
--- linux-libre-3.1-gnu/drivers/hwmon/pmbus/ucd9200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/pmbus/ucd9200.c	2012-01-04 18:55:44.000000000 -0500
@@ -171,13 +171,12 @@
 
 static int ucd9200_remove(struct i2c_client *client)
 {
-	int ret;
 	const struct pmbus_driver_info *info;
 
 	info = pmbus_get_driver_info(client);
-	ret = pmbus_do_remove(client);
+	pmbus_do_remove(client);
 	kfree(info);
-	return ret;
+	return 0;
 }
 
 
diff -druN linux-libre-3.1-gnu/drivers/hwmon/pmbus/zl6100.c linux-libre-3.2-gnu/drivers/hwmon/pmbus/zl6100.c
--- linux-libre-3.1-gnu/drivers/hwmon/pmbus/zl6100.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hwmon/pmbus/zl6100.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,256 @@
+/*
+ * Hardware monitoring driver for ZL6100 and compatibles
+ *
+ * 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/slab.h>
+#include <linux/i2c.h>
+#include <linux/ktime.h>
+#include <linux/delay.h>
+#include "pmbus.h"
+
+enum chips { zl2004, zl2006, zl2008, zl2105, zl2106, zl6100, zl6105 };
+
+struct zl6100_data {
+	int id;
+	ktime_t access;		/* chip access time */
+	struct pmbus_driver_info info;
+};
+
+#define to_zl6100_data(x)  container_of(x, struct zl6100_data, info)
+
+#define ZL6100_DEVICE_ID		0xe4
+
+#define ZL6100_WAIT_TIME		1000	/* uS	*/
+
+static ushort delay = ZL6100_WAIT_TIME;
+module_param(delay, ushort, 0644);
+MODULE_PARM_DESC(delay, "Delay between chip accesses in uS");
+
+/* Some chips need a delay between accesses */
+static inline void zl6100_wait(const struct zl6100_data *data)
+{
+	if (delay) {
+		s64 delta = ktime_us_delta(ktime_get(), data->access);
+		if (delta < delay)
+			udelay(delay - delta);
+	}
+}
+
+static int zl6100_read_word_data(struct i2c_client *client, int page, int reg)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct zl6100_data *data = to_zl6100_data(info);
+	int ret;
+
+	if (page || reg >= PMBUS_VIRT_BASE)
+		return -ENXIO;
+
+	zl6100_wait(data);
+	ret = pmbus_read_word_data(client, page, reg);
+	data->access = ktime_get();
+
+	return ret;
+}
+
+static int zl6100_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct zl6100_data *data = to_zl6100_data(info);
+	int ret;
+
+	if (page > 0)
+		return -ENXIO;
+
+	zl6100_wait(data);
+	ret = pmbus_read_byte_data(client, page, reg);
+	data->access = ktime_get();
+
+	return ret;
+}
+
+static int zl6100_write_word_data(struct i2c_client *client, int page, int reg,
+				  u16 word)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct zl6100_data *data = to_zl6100_data(info);
+	int ret;
+
+	if (page || reg >= PMBUS_VIRT_BASE)
+		return -ENXIO;
+
+	zl6100_wait(data);
+	ret = pmbus_write_word_data(client, page, reg, word);
+	data->access = ktime_get();
+
+	return ret;
+}
+
+static int zl6100_write_byte(struct i2c_client *client, int page, u8 value)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct zl6100_data *data = to_zl6100_data(info);
+	int ret;
+
+	if (page > 0)
+		return -ENXIO;
+
+	zl6100_wait(data);
+	ret = pmbus_write_byte(client, page, value);
+	data->access = ktime_get();
+
+	return ret;
+}
+
+static const struct i2c_device_id zl6100_id[] = {
+	{"zl2004", zl2004},
+	{"zl2006", zl2006},
+	{"zl2008", zl2008},
+	{"zl2105", zl2105},
+	{"zl2106", zl2106},
+	{"zl6100", zl6100},
+	{"zl6105", zl6105},
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, zl6100_id);
+
+static int zl6100_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int ret;
+	struct zl6100_data *data;
+	struct pmbus_driver_info *info;
+	u8 device_id[I2C_SMBUS_BLOCK_MAX + 1];
+	const struct i2c_device_id *mid;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_READ_BYTE_DATA
+				     | I2C_FUNC_SMBUS_READ_BLOCK_DATA))
+		return -ENODEV;
+
+	ret = i2c_smbus_read_block_data(client, ZL6100_DEVICE_ID,
+					device_id);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to read device ID\n");
+		return ret;
+	}
+	device_id[ret] = '\0';
+	dev_info(&client->dev, "Device ID %s\n", device_id);
+
+	mid = NULL;
+	for (mid = zl6100_id; mid->name[0]; mid++) {
+		if (!strncasecmp(mid->name, device_id, strlen(mid->name)))
+			break;
+	}
+	if (!mid->name[0]) {
+		dev_err(&client->dev, "Unsupported device\n");
+		return -ENODEV;
+	}
+	if (id->driver_data != mid->driver_data)
+		dev_notice(&client->dev,
+			   "Device mismatch: Configured %s, detected %s\n",
+			   id->name, mid->name);
+
+	data = kzalloc(sizeof(struct zl6100_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->id = mid->driver_data;
+
+	/*
+	 * ZL2008, ZL2105, and ZL6100 are known to require a wait time
+	 * between I2C accesses. ZL2004 and ZL6105 are known to be safe.
+	 *
+	 * Only clear the wait time for chips known to be safe. The wait time
+	 * can be cleared later for additional chips if tests show that it
+	 * is not needed (in other words, better be safe than sorry).
+	 */
+	if (data->id == zl2004 || data->id == zl6105)
+		delay = 0;
+
+	/*
+	 * Since there was a direct I2C device access above, wait before
+	 * accessing the chip again.
+	 * Set the timestamp, wait, then set it again. This should provide
+	 * enough buffer time to be safe.
+	 */
+	data->access = ktime_get();
+	zl6100_wait(data);
+	data->access = ktime_get();
+
+	info = &data->info;
+
+	info->pages = 1;
+	info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
+	  | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+	  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+	  | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
+
+	info->read_word_data = zl6100_read_word_data;
+	info->read_byte_data = zl6100_read_byte_data;
+	info->write_word_data = zl6100_write_word_data;
+	info->write_byte = zl6100_write_byte;
+
+	ret = pmbus_do_probe(client, mid, info);
+	if (ret)
+		goto err_mem;
+	return 0;
+
+err_mem:
+	kfree(data);
+	return ret;
+}
+
+static int zl6100_remove(struct i2c_client *client)
+{
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	const struct zl6100_data *data = to_zl6100_data(info);
+
+	pmbus_do_remove(client);
+	kfree(data);
+	return 0;
+}
+
+static struct i2c_driver zl6100_driver = {
+	.driver = {
+		   .name = "zl6100",
+		   },
+	.probe = zl6100_probe,
+	.remove = zl6100_remove,
+	.id_table = zl6100_id,
+};
+
+static int __init zl6100_init(void)
+{
+	return i2c_add_driver(&zl6100_driver);
+}
+
+static void __exit zl6100_exit(void)
+{
+	i2c_del_driver(&zl6100_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("PMBus driver for ZL6100 and compatibles");
+MODULE_LICENSE("GPL");
+module_init(zl6100_init);
+module_exit(zl6100_exit);
diff -druN linux-libre-3.1-gnu/drivers/hwmon/s3c-hwmon.c linux-libre-3.2-gnu/drivers/hwmon/s3c-hwmon.c
--- linux-libre-3.1-gnu/drivers/hwmon/s3c-hwmon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/s3c-hwmon.c	2012-01-04 18:55:44.000000000 -0500
@@ -393,18 +393,7 @@
 	.remove		= __devexit_p(s3c_hwmon_remove),
 };
 
-static int __init s3c_hwmon_init(void)
-{
-	return platform_driver_register(&s3c_hwmon_driver);
-}
-
-static void __exit s3c_hwmon_exit(void)
-{
-	platform_driver_unregister(&s3c_hwmon_driver);
-}
-
-module_init(s3c_hwmon_init);
-module_exit(s3c_hwmon_exit);
+module_platform_driver(s3c_hwmon_driver);
 
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("S3C ADC HWMon driver");
diff -druN linux-libre-3.1-gnu/drivers/hwmon/sch5627.c linux-libre-3.2-gnu/drivers/hwmon/sch5627.c
--- linux-libre-3.1-gnu/drivers/hwmon/sch5627.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/sch5627.c	2012-01-04 18:55:44.000000000 -0500
@@ -590,19 +590,8 @@
 	.remove		= sch5627_remove,
 };
 
-static int __init sch5627_init(void)
-{
-	return platform_driver_register(&sch5627_driver);
-}
-
-static void __exit sch5627_exit(void)
-{
-	platform_driver_unregister(&sch5627_driver);
-}
+module_platform_driver(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-3.1-gnu/drivers/hwmon/sch5636.c linux-libre-3.2-gnu/drivers/hwmon/sch5636.c
--- linux-libre-3.1-gnu/drivers/hwmon/sch5636.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/sch5636.c	2012-01-04 18:55:44.000000000 -0500
@@ -521,19 +521,8 @@
 	.remove		= sch5636_remove,
 };
 
-static int __init sch5636_init(void)
-{
-	return platform_driver_register(&sch5636_driver);
-}
-
-static void __exit sch5636_exit(void)
-{
-	platform_driver_unregister(&sch5636_driver);
-}
+module_platform_driver(sch5636_driver);
 
 MODULE_DESCRIPTION("SMSC SCH5636 Hardware Monitoring Driver");
 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_LICENSE("GPL");
-
-module_init(sch5636_init);
-module_exit(sch5636_exit);
diff -druN linux-libre-3.1-gnu/drivers/hwmon/sht21.c linux-libre-3.2-gnu/drivers/hwmon/sht21.c
--- linux-libre-3.1-gnu/drivers/hwmon/sht21.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/sht21.c	2012-01-04 18:55:44.000000000 -0500
@@ -83,25 +83,6 @@
 }
 
 /**
- * sht21_read_word_data() - read word from register
- * @client: I2C client device
- * @reg: I2C command byte
- *
- * Returns value, negative errno on error.
- */
-static inline int sht21_read_word_data(struct i2c_client *client, u8 reg)
-{
-	int ret = i2c_smbus_read_word_data(client, reg);
-	if (ret < 0)
-		return ret;
-	/*
-	 * SMBus specifies low byte first, but the SHT21 returns MSB
-	 * first, so we have to swab16 the values
-	 */
-	return swab16(ret);
-}
-
-/**
  * sht21_update_measurements() - get updated measurements from device
  * @client: I2C client device
  *
@@ -119,12 +100,13 @@
 	 * maximum two measurements per second at 12bit accuracy shall be made.
 	 */
 	if (time_after(jiffies, sht21->last_update + HZ / 2) || !sht21->valid) {
-		ret = sht21_read_word_data(client, SHT21_TRIG_T_MEASUREMENT_HM);
+		ret = i2c_smbus_read_word_swapped(client,
+						  SHT21_TRIG_T_MEASUREMENT_HM);
 		if (ret < 0)
 			goto out;
 		sht21->temperature = sht21_temp_ticks_to_millicelsius(ret);
-		ret = sht21_read_word_data(client,
-					SHT21_TRIG_RH_MEASUREMENT_HM);
+		ret = i2c_smbus_read_word_swapped(client,
+						  SHT21_TRIG_RH_MEASUREMENT_HM);
 		if (ret < 0)
 			goto out;
 		sht21->humidity = sht21_rh_ticks_to_per_cent_mille(ret);
diff -druN linux-libre-3.1-gnu/drivers/hwmon/smm665.c linux-libre-3.2-gnu/drivers/hwmon/smm665.c
--- linux-libre-3.1-gnu/drivers/hwmon/smm665.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/smm665.c	2012-01-04 18:55:44.000000000 -0500
@@ -214,33 +214,26 @@
 	 *
 	 * Neither i2c_smbus_read_byte() nor
 	 * i2c_smbus_read_block_data() worked here,
-	 * so use i2c_smbus_read_word_data() instead.
+	 * so use i2c_smbus_read_word_swapped() instead.
 	 * We could also try to use i2c_master_recv(),
 	 * but that is not always supported.
 	 */
-	rv = i2c_smbus_read_word_data(client, 0);
+	rv = i2c_smbus_read_word_swapped(client, 0);
 	if (rv < 0) {
 		dev_dbg(&client->dev, "Failed to read ADC value: error %d", rv);
 		return -1;
 	}
 	/*
 	 * Validate/verify readback adc channel (in bit 11..14).
-	 * High byte is in lower 8 bit of rv, so only shift by 3.
 	 */
-	radc = (rv >> 3) & 0x0f;
+	radc = (rv >> 11) & 0x0f;
 	if (radc != adc) {
 		dev_dbg(&client->dev, "Unexpected RADC: Expected %d got %d",
 			adc, radc);
 		return -EIO;
 	}
-	/*
-	 * Chip replies with H/L, while SMBus expects L/H.
-	 * Thus, byte order is reversed, and we have to swap
-	 * the result.
-	 */
-	rv = swab16(rv) & SMM665_ADC_MASK;
 
-	return rv;
+	return rv & SMM665_ADC_MASK;
 }
 
 static struct smm665_data *smm665_update_device(struct device *dev)
diff -druN linux-libre-3.1-gnu/drivers/hwmon/smsc47b397.c linux-libre-3.2-gnu/drivers/hwmon/smsc47b397.c
--- linux-libre-3.1-gnu/drivers/hwmon/smsc47b397.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/smsc47b397.c	2012-01-04 18:55:44.000000000 -0500
@@ -113,7 +113,7 @@
 	u8 temp[4];
 };
 
-static int smsc47b397_read_value(struct smsc47b397_data* data, u8 reg)
+static int smsc47b397_read_value(struct smsc47b397_data *data, u8 reg)
 {
 	int res;
 
@@ -265,7 +265,8 @@
 		return -EBUSY;
 	}
 
-	if (!(data = kzalloc(sizeof(struct smsc47b397_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct smsc47b397_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		goto error_release;
 	}
@@ -276,7 +277,8 @@
 	mutex_init(&data->update_lock);
 	platform_set_drvdata(pdev, data);
 
-	if ((err = sysfs_create_group(&dev->kobj, &smsc47b397_group)))
+	err = sysfs_create_group(&dev->kobj, &smsc47b397_group);
+	if (err)
 		goto error_free;
 
 	data->hwmon_dev = hwmon_device_register(dev);
@@ -345,7 +347,7 @@
 	superio_enter();
 	id = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID);
 
-	switch(id) {
+	switch (id) {
 	case 0x81:
 		name = "SCH5307-NS";
 		break;
@@ -379,7 +381,8 @@
 	unsigned short address;
 	int ret;
 
-	if ((ret = smsc47b397_find(&address)))
+	ret = smsc47b397_find(&address);
+	if (ret)
 		return ret;
 
 	ret = platform_driver_register(&smsc47b397_driver);
diff -druN linux-libre-3.1-gnu/drivers/hwmon/tmp102.c linux-libre-3.2-gnu/drivers/hwmon/tmp102.c
--- linux-libre-3.1-gnu/drivers/hwmon/tmp102.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/tmp102.c	2012-01-04 18:55:44.000000000 -0500
@@ -55,19 +55,6 @@
 	int temp[3];
 };
 
-/* SMBus specifies low byte first, but the TMP102 returns high byte first,
- * so we have to swab16 the values */
-static inline int tmp102_read_reg(struct i2c_client *client, u8 reg)
-{
-	int result = i2c_smbus_read_word_data(client, reg);
-	return result < 0 ? result : swab16(result);
-}
-
-static inline int tmp102_write_reg(struct i2c_client *client, u8 reg, u16 val)
-{
-	return i2c_smbus_write_word_data(client, reg, swab16(val));
-}
-
 /* convert left adjusted 13-bit TMP102 register value to milliCelsius */
 static inline int tmp102_reg_to_mC(s16 val)
 {
@@ -94,7 +81,8 @@
 	if (time_after(jiffies, tmp102->last_update + HZ / 3)) {
 		int i;
 		for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) {
-			int status = tmp102_read_reg(client, tmp102_reg[i]);
+			int status = i2c_smbus_read_word_swapped(client,
+								 tmp102_reg[i]);
 			if (status > -1)
 				tmp102->temp[i] = tmp102_reg_to_mC(status);
 		}
@@ -130,8 +118,8 @@
 
 	mutex_lock(&tmp102->lock);
 	tmp102->temp[sda->index] = val;
-	status = tmp102_write_reg(client, tmp102_reg[sda->index],
-				  tmp102_mC_to_reg(val));
+	status = i2c_smbus_write_word_swapped(client, tmp102_reg[sda->index],
+					      tmp102_mC_to_reg(val));
 	mutex_unlock(&tmp102->lock);
 	return status ? : count;
 }
@@ -178,18 +166,19 @@
 	}
 	i2c_set_clientdata(client, tmp102);
 
-	status = tmp102_read_reg(client, TMP102_CONF_REG);
+	status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
 	if (status < 0) {
 		dev_err(&client->dev, "error reading config register\n");
 		goto fail_free;
 	}
 	tmp102->config_orig = status;
-	status = tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONFIG);
+	status = i2c_smbus_write_word_swapped(client, TMP102_CONF_REG,
+					      TMP102_CONFIG);
 	if (status < 0) {
 		dev_err(&client->dev, "error writing config register\n");
 		goto fail_restore_config;
 	}
-	status = tmp102_read_reg(client, TMP102_CONF_REG);
+	status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
 	if (status < 0) {
 		dev_err(&client->dev, "error reading config register\n");
 		goto fail_restore_config;
@@ -222,7 +211,8 @@
 fail_remove_sysfs:
 	sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
 fail_restore_config:
-	tmp102_write_reg(client, TMP102_CONF_REG, tmp102->config_orig);
+	i2c_smbus_write_word_swapped(client, TMP102_CONF_REG,
+				     tmp102->config_orig);
 fail_free:
 	kfree(tmp102);
 
@@ -240,10 +230,10 @@
 	if (tmp102->config_orig & TMP102_CONF_SD) {
 		int config;
 
-		config = tmp102_read_reg(client, TMP102_CONF_REG);
+		config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
 		if (config >= 0)
-			tmp102_write_reg(client, TMP102_CONF_REG,
-					 config | TMP102_CONF_SD);
+			i2c_smbus_write_word_swapped(client, TMP102_CONF_REG,
+						     config | TMP102_CONF_SD);
 	}
 
 	kfree(tmp102);
@@ -257,12 +247,12 @@
 	struct i2c_client *client = to_i2c_client(dev);
 	int config;
 
-	config = tmp102_read_reg(client, TMP102_CONF_REG);
+	config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
 	if (config < 0)
 		return config;
 
 	config |= TMP102_CONF_SD;
-	return tmp102_write_reg(client, TMP102_CONF_REG, config);
+	return i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config);
 }
 
 static int tmp102_resume(struct device *dev)
@@ -270,12 +260,12 @@
 	struct i2c_client *client = to_i2c_client(dev);
 	int config;
 
-	config = tmp102_read_reg(client, TMP102_CONF_REG);
+	config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
 	if (config < 0)
 		return config;
 
 	config &= ~TMP102_CONF_SD;
-	return tmp102_write_reg(client, TMP102_CONF_REG, config);
+	return i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config);
 }
 
 static const struct dev_pm_ops tmp102_dev_pm_ops = {
diff -druN linux-libre-3.1-gnu/drivers/hwmon/twl4030-madc-hwmon.c linux-libre-3.2-gnu/drivers/hwmon/twl4030-madc-hwmon.c
--- linux-libre-3.1-gnu/drivers/hwmon/twl4030-madc-hwmon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/twl4030-madc-hwmon.c	2012-01-04 18:55:44.000000000 -0500
@@ -136,19 +136,7 @@
 		   },
 };
 
-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_platform_driver(twl4030_madc_hwmon_driver);
 
 MODULE_DESCRIPTION("TWL4030 ADC Hwmon driver");
 MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/hwmon/ultra45_env.c linux-libre-3.2-gnu/drivers/hwmon/ultra45_env.c
--- linux-libre-3.1-gnu/drivers/hwmon/ultra45_env.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/ultra45_env.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/io.h>
 #include <linux/hwmon.h>
@@ -308,15 +309,4 @@
 	.remove		= __devexit_p(env_remove),
 };
 
-static int __init env_init(void)
-{
-	return platform_driver_register(&env_driver);
-}
-
-static void __exit env_exit(void)
-{
-	platform_driver_unregister(&env_driver);
-}
-
-module_init(env_init);
-module_exit(env_exit);
+module_platform_driver(env_driver);
diff -druN linux-libre-3.1-gnu/drivers/hwmon/w83627ehf.c linux-libre-3.2-gnu/drivers/hwmon/w83627ehf.c
--- linux-libre-3.1-gnu/drivers/hwmon/w83627ehf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/w83627ehf.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
     w83627ehf - Driver for the hardware monitoring functionality of
 		the Winbond W83627EHF Super-I/O chip
-    Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
+    Copyright (C) 2005-2011  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>
@@ -39,6 +39,7 @@
 					       0x8860 0xa1
     w83627dhg    9      5       4       3      0xa020 0xc1    0x5ca3
     w83627dhg-p  9      5       4       3      0xb070 0xc1    0x5ca3
+    w83627uhg    8      2       2       2      0xa230 0xc1    0x5ca3
     w83667hg     9      5       3       3      0xa510 0xc1    0x5ca3
     w83667hg-b   9      5       3       4      0xb350 0xc1    0x5ca3
     nct6775f     9      4       3       9      0xb470 0xc1    0x5ca3
@@ -61,14 +62,17 @@
 #include <linux/io.h>
 #include "lm75.h"
 
-enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg, w83667hg_b, nct6775,
-	nct6776 };
+enum kinds {
+	w83627ehf, w83627dhg, w83627dhg_p, w83627uhg,
+	w83667hg, w83667hg_b, nct6775, nct6776,
+};
 
 /* used to set data->name = w83627ehf_device_names[data->sio_kind] */
 static const char * const w83627ehf_device_names[] = {
 	"w83627ehf",
 	"w83627dhg",
 	"w83627dhg",
+	"w83627uhg",
 	"w83667hg",
 	"w83667hg",
 	"nct6775",
@@ -104,6 +108,7 @@
 #define SIO_W83627EHG_ID	0x8860
 #define SIO_W83627DHG_ID	0xa020
 #define SIO_W83627DHG_P_ID	0xb070
+#define SIO_W83627UHG_ID	0xa230
 #define SIO_W83667HG_ID		0xa510
 #define SIO_W83667HG_B_ID	0xb350
 #define SIO_NCT6775_ID		0xb470
@@ -197,6 +202,9 @@
 #define W83627EHF_REG_ALARM2		0x45A
 #define W83627EHF_REG_ALARM3		0x45B
 
+#define W83627EHF_REG_CASEOPEN_DET	0x42 /* SMI STATUS #2 */
+#define W83627EHF_REG_CASEOPEN_CLR	0x46 /* SMI MASK #3 */
+
 /* SmartFan registers */
 #define W83627EHF_REG_FAN_STEPUP_TIME 0x0f
 #define W83627EHF_REG_FAN_STEPDOWN_TIME 0x0e
@@ -316,7 +324,7 @@
 
 #define NUM_REG_TEMP	ARRAY_SIZE(NCT6775_REG_TEMP)
 
-static inline int is_word_sized(u16 reg)
+static int is_word_sized(u16 reg)
 {
 	return ((((reg & 0xff00) == 0x100
 	      || (reg & 0xff00) == 0x200)
@@ -385,35 +393,23 @@
 	return 1 << reg;
 }
 
-static inline int
-temp_from_reg(u16 reg, s16 regval)
-{
-	if (is_word_sized(reg))
-		return LM75_TEMP_FROM_REG(regval);
-	return ((s8)regval) * 1000;
-}
-
-static inline u16
-temp_to_reg(u16 reg, long temp)
-{
-	if (is_word_sized(reg))
-		return LM75_TEMP_TO_REG(temp);
-	return (s8)DIV_ROUND_CLOSEST(SENSORS_LIMIT(temp, -127000, 128000),
-				     1000);
-}
-
-/* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */
-
-static u8 scale_in[10] = { 8, 8, 16, 16, 8, 8, 8, 16, 16, 8 };
+/* Some of the voltage inputs have internal scaling, the tables below
+ * contain 8 (the ADC LSB in mV) * scaling factor * 100 */
+static const u16 scale_in_common[10] = {
+	800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800
+};
+static const u16 scale_in_w83627uhg[9] = {
+	800, 800, 3328, 3424, 800, 800, 0, 3328, 3400
+};
 
-static inline long in_from_reg(u8 reg, u8 nr)
+static inline long in_from_reg(u8 reg, u8 nr, const u16 *scale_in)
 {
-	return reg * scale_in[nr];
+	return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
 }
 
-static inline u8 in_to_reg(u32 val, u8 nr)
+static inline u8 in_to_reg(u32 val, u8 nr, const u16 *scale_in)
 {
-	return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0,
+	return SENSORS_LIMIT(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0,
 			     255);
 }
 
@@ -444,6 +440,7 @@
 	const u16 *REG_FAN_STOP_TIME;
 	const u16 *REG_FAN_MAX_OUTPUT;
 	const u16 *REG_FAN_STEP_OUTPUT;
+	const u16 *scale_in;
 
 	unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
 	unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
@@ -469,6 +466,7 @@
 	s16 temp_max[9];
 	s16 temp_max_hyst[9];
 	u32 alarms;
+	u8 caseopen;
 
 	u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */
 	u8 pwm_enable[4]; /* 1->manual
@@ -494,7 +492,8 @@
 	u8 vrm;
 
 	u16 have_temp;
-	u8 in6_skip;
+	u8 in6_skip:1;
+	u8 temp3_val_only:1;
 };
 
 struct w83627ehf_sio_data {
@@ -557,6 +556,26 @@
 	return 0;
 }
 
+/* We left-align 8-bit temperature values to make the code simpler */
+static u16 w83627ehf_read_temp(struct w83627ehf_data *data, u16 reg)
+{
+	u16 res;
+
+	res = w83627ehf_read_value(data, reg);
+	if (!is_word_sized(reg))
+		res <<= 8;
+
+	return res;
+}
+
+static int w83627ehf_write_temp(struct w83627ehf_data *data, u16 reg,
+				       u16 value)
+{
+	if (!is_word_sized(reg))
+		value >>= 8;
+	return w83627ehf_write_value(data, reg, value);
+}
+
 /* This function assumes that the caller holds data->update_lock */
 static void nct6775_write_fan_div(struct w83627ehf_data *data, int nr)
 {
@@ -771,6 +790,9 @@
 
 		/* Measured voltages and limits */
 		for (i = 0; i < data->in_num; i++) {
+			if ((i == 6) && data->in6_skip)
+				continue;
+
 			data->in[i] = w83627ehf_read_value(data,
 				      W83627EHF_REG_IN(i));
 			data->in_min[i] = w83627ehf_read_value(data,
@@ -855,15 +877,15 @@
 		for (i = 0; i < NUM_REG_TEMP; i++) {
 			if (!(data->have_temp & (1 << i)))
 				continue;
-			data->temp[i] = w83627ehf_read_value(data,
+			data->temp[i] = w83627ehf_read_temp(data,
 						data->reg_temp[i]);
 			if (data->reg_temp_over[i])
 				data->temp_max[i]
-				  = w83627ehf_read_value(data,
+				  = w83627ehf_read_temp(data,
 						data->reg_temp_over[i]);
 			if (data->reg_temp_hyst[i])
 				data->temp_max_hyst[i]
-				  = w83627ehf_read_value(data,
+				  = w83627ehf_read_temp(data,
 						data->reg_temp_hyst[i]);
 		}
 
@@ -874,6 +896,9 @@
 			       (w83627ehf_read_value(data,
 					W83627EHF_REG_ALARM3) << 16);
 
+		data->caseopen = w83627ehf_read_value(data,
+						W83627EHF_REG_CASEOPEN_DET);
+
 		data->last_updated = jiffies;
 		data->valid = 1;
 	}
@@ -894,7 +919,8 @@
 	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)); \
+	return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr, \
+		       data->scale_in)); \
 }
 show_in_reg(in)
 show_in_reg(in_min)
@@ -915,7 +941,7 @@
 	if (err < 0) \
 		return err; \
 	mutex_lock(&data->update_lock); \
-	data->in_##reg[nr] = in_to_reg(val, nr); \
+	data->in_##reg[nr] = in_to_reg(val, nr, data->scale_in); \
 	w83627ehf_write_value(data, W83627EHF_REG_IN_##REG(nr), \
 			      data->in_##reg[nr]); \
 	mutex_unlock(&data->update_lock); \
@@ -1156,8 +1182,7 @@
 	struct sensor_device_attribute *sensor_attr = \
 		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
-	return sprintf(buf, "%d\n", \
-		       temp_from_reg(data->addr[nr], data->reg[nr])); \
+	return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->reg[nr])); \
 }
 show_temp_reg(reg_temp, temp);
 show_temp_reg(reg_temp_over, temp_max);
@@ -1178,9 +1203,8 @@
 	if (err < 0) \
 		return err; \
 	mutex_lock(&data->update_lock); \
-	data->reg[nr] = temp_to_reg(data->addr[nr], val); \
-	w83627ehf_write_value(data, data->addr[nr], \
-			      data->reg[nr]); \
+	data->reg[nr] = LM75_TEMP_TO_REG(val); \
+	w83627ehf_write_temp(data, data->addr[nr], data->reg[nr]); \
 	mutex_unlock(&data->update_lock); \
 	return count; \
 }
@@ -1606,25 +1630,28 @@
 		    store_fan_step_output, 3),
 };
 
+static struct sensor_device_attribute sda_sf3_arrays_fan3[] = {
+	SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
+		    store_fan_stop_time, 2),
+	SENSOR_ATTR(pwm3_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
+		    store_fan_start_output, 2),
+	SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
+		    store_fan_stop_output, 2),
+};
+
 static struct sensor_device_attribute sda_sf3_arrays[] = {
 	SENSOR_ATTR(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
 		    store_fan_stop_time, 0),
 	SENSOR_ATTR(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
 		    store_fan_stop_time, 1),
-	SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
-		    store_fan_stop_time, 2),
 	SENSOR_ATTR(pwm1_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
 		    store_fan_start_output, 0),
 	SENSOR_ATTR(pwm2_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
 		    store_fan_start_output, 1),
-	SENSOR_ATTR(pwm3_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
-		    store_fan_start_output, 2),
 	SENSOR_ATTR(pwm1_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
 		    store_fan_stop_output, 0),
 	SENSOR_ATTR(pwm2_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
 		    store_fan_stop_output, 1),
-	SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
-		    store_fan_stop_output, 2),
 };
 
 
@@ -1655,6 +1682,48 @@
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
+
+/* Case open detection */
+
+static ssize_t
+show_caseopen(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83627ehf_data *data = w83627ehf_update_device(dev);
+
+	return sprintf(buf, "%d\n",
+		!!(data->caseopen & to_sensor_dev_attr_2(attr)->index));
+}
+
+static ssize_t
+clear_caseopen(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct w83627ehf_data *data = dev_get_drvdata(dev);
+	unsigned long val;
+	u16 reg, mask;
+
+	if (strict_strtoul(buf, 10, &val) || val != 0)
+		return -EINVAL;
+
+	mask = to_sensor_dev_attr_2(attr)->nr;
+
+	mutex_lock(&data->update_lock);
+	reg = w83627ehf_read_value(data, W83627EHF_REG_CASEOPEN_CLR);
+	w83627ehf_write_value(data, W83627EHF_REG_CASEOPEN_CLR, reg | mask);
+	w83627ehf_write_value(data, W83627EHF_REG_CASEOPEN_CLR, reg & ~mask);
+	data->valid = 0;	/* Force cache refresh */
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static struct sensor_device_attribute_2 sda_caseopen[] = {
+	SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_caseopen,
+			clear_caseopen, 0x80, 0x10),
+	SENSOR_ATTR_2(intrusion1_alarm, S_IWUSR | S_IRUGO, show_caseopen,
+			clear_caseopen, 0x40, 0x40),
+};
+
 /*
  * Driver and device management
  */
@@ -1675,6 +1744,8 @@
 		    data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff)
 			device_remove_file(dev, &attr->dev_attr);
 	}
+	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan3); i++)
+		device_remove_file(dev, &sda_sf3_arrays_fan3[i].dev_attr);
 	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++)
 		device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr);
 	for (i = 0; i < data->in_num; i++) {
@@ -1703,6 +1774,8 @@
 			continue;
 		device_remove_file(dev, &sda_temp_input[i].dev_attr);
 		device_remove_file(dev, &sda_temp_label[i].dev_attr);
+		if (i == 2 && data->temp3_val_only)
+			continue;
 		device_remove_file(dev, &sda_temp_max[i].dev_attr);
 		device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr);
 		if (i > 2)
@@ -1711,6 +1784,9 @@
 		device_remove_file(dev, &sda_temp_type[i].dev_attr);
 	}
 
+	device_remove_file(dev, &sda_caseopen[0].dev_attr);
+	device_remove_file(dev, &sda_caseopen[1].dev_attr);
+
 	device_remove_file(dev, &dev_attr_name);
 	device_remove_file(dev, &dev_attr_cpu0_vid);
 }
@@ -1752,11 +1828,24 @@
 	case w83627ehf:
 		diode = w83627ehf_read_value(data, W83627EHF_REG_DIODE);
 		break;
+	case w83627uhg:
+		diode = 0x00;
+		break;
 	default:
 		diode = 0x70;
 	}
 	for (i = 0; i < 3; i++) {
-		if ((tmp & (0x02 << i)))
+		const char *label = NULL;
+
+		if (data->temp_label)
+			label = data->temp_label[data->temp_src[i]];
+
+		/* Digital source overrides analog type */
+		if (label && strncmp(label, "PECI", 4) == 0)
+			data->temp_type[i] = 6;
+		else if (label && strncmp(label, "AMD", 3) == 0)
+			data->temp_type[i] = 5;
+		else if ((tmp & (0x02 << i)))
 			data->temp_type[i] = (diode & (0x10 << i)) ? 1 : 3;
 		else
 			data->temp_type[i] = 4; /* thermistor */
@@ -1789,13 +1878,98 @@
 	data->reg_temp_config[r2] = tmp;
 }
 
+static void __devinit
+w83627ehf_set_temp_reg_ehf(struct w83627ehf_data *data, int n_temp)
+{
+	int i;
+
+	for (i = 0; i < n_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];
+	}
+}
+
+static void __devinit
+w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
+			   struct w83627ehf_data *data)
+{
+	int fan3pin, fan4pin, fan4min, fan5pin, regval;
+
+	/* The W83627UHG is simple, only two fan inputs, no config */
+	if (sio_data->kind == w83627uhg) {
+		data->has_fan = 0x03; /* fan1 and fan2 */
+		data->has_fan_min = 0x03;
+		return;
+	}
+
+	superio_enter(sio_data->sioreg);
+
+	/* fan4 and fan5 share some pins with the GPIO and serial flash */
+	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 {
+		fan3pin = 1;
+		fan4pin = !(superio_inb(sio_data->sioreg, 0x29) & 0x06);
+		fan5pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x02);
+		fan4min = fan4pin;
+	}
+
+	superio_exit(sio_data->sioreg);
+
+	data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
+	data->has_fan |= (fan3pin << 2);
+	data->has_fan_min |= (fan3pin << 2);
+
+	if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
+		/*
+		 * NCT6775F and NCT6776F don't have the W83627EHF_REG_FANDIV1
+		 * register
+		 */
+		data->has_fan |= (fan4pin << 3) | (fan5pin << 4);
+		data->has_fan_min |= (fan4min << 3) | (fan5pin << 4);
+	} else {
+		/*
+		 * It looks like fan4 and fan5 pins can be alternatively used
+		 * as fan on/off switches, but fan5 control is write only :/
+		 * We assume that if the serial interface is disabled, designers
+		 * connected fan5 as input unless they are emitting log 1, which
+		 * is not the default.
+		 */
+		regval = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1);
+		if ((regval & (1 << 2)) && fan4pin) {
+			data->has_fan |= (1 << 3);
+			data->has_fan_min |= (1 << 3);
+		}
+		if (!(regval & (1 << 1)) && fan5pin) {
+			data->has_fan |= (1 << 4);
+			data->has_fan_min |= (1 << 4);
+		}
+	}
+}
+
 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 fan3pin, fan4pin, fan4min, fan5pin, en_vrm10;
+	u8 en_vrm10;
 	int i, err = 0;
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
@@ -1821,23 +1995,24 @@
 
 	/* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */
 	data->in_num = (sio_data->kind == w83627ehf) ? 10 : 9;
-	/* 667HG, NCT6775F, and NCT6776F have 3 pwms */
-	data->pwm_num = (sio_data->kind == w83667hg
-			 || sio_data->kind == w83667hg_b
-			 || sio_data->kind == nct6775
-			 || sio_data->kind == nct6776) ? 3 : 4;
+	/* 667HG, NCT6775F, and NCT6776F have 3 pwms, and 627UHG has only 2 */
+	switch (sio_data->kind) {
+	default:
+		data->pwm_num = 4;
+		break;
+	case w83667hg:
+	case w83667hg_b:
+	case nct6775:
+	case nct6776:
+		data->pwm_num = 3;
+		break;
+	case w83627uhg:
+		data->pwm_num = 2;
+		break;
+	}
 
+	/* Default to 3 temperature inputs, code below will adjust as needed */
 	data->have_temp = 0x07;
-	/* Check temp3 configuration bit for 667HG */
-	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 */
-	}
 
 	/* Deal with temperature register setup first. */
 	if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
@@ -1914,16 +2089,12 @@
 	} else if (sio_data->kind == w83667hg_b) {
 		u8 reg;
 
+		w83627ehf_set_temp_reg_ehf(data, 4);
+
 		/*
 		 * 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);
@@ -1957,13 +2128,60 @@
 			data->in6_skip = 1;
 
 		data->temp_label = w83667hg_b_temp_label;
+	} else if (sio_data->kind == w83627uhg) {
+		u8 reg;
+
+		w83627ehf_set_temp_reg_ehf(data, 3);
+
+		/*
+		 * Temperature sources for temp1 and temp2 are selected with
+		 * bank 0, registers 0x49 and 0x4a.
+		 */
+		data->temp_src[0] = 0;	/* SYSTIN */
+		reg = w83627ehf_read_value(data, 0x49) & 0x07;
+		/* Adjust to have the same mapping as other source registers */
+		if (reg == 0)
+			data->temp_src[1]++;
+		else if (reg >= 2 && reg <= 5)
+			data->temp_src[1] += 2;
+		else	/* should never happen */
+			data->have_temp &= ~(1 << 1);
+		reg = w83627ehf_read_value(data, 0x4a);
+		data->temp_src[2] = reg >> 5;
+
+		/*
+		 * Skip temp3 if source is invalid or the same as temp1
+		 * or temp2.
+		 */
+		if (data->temp_src[2] == 2 || data->temp_src[2] == 3 ||
+		    data->temp_src[2] == data->temp_src[0] ||
+		    ((data->have_temp & (1 << 1)) &&
+		     data->temp_src[2] == data->temp_src[1]))
+			data->have_temp &= ~(1 << 2);
+		else
+			data->temp3_val_only = 1;	/* No limit regs */
+
+		data->in6_skip = 1;			/* No VIN3 */
+
+		data->temp_label = w83667hg_b_temp_label;
 	} else {
+		w83627ehf_set_temp_reg_ehf(data, 3);
+
 		/* 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 == w83667hg) {
+			u8 reg;
+
+			/*
+			 * Chip supports either AUXTIN or VIN3. Try to find
+			 * out which one.
+			 */
+			reg = w83627ehf_read_value(data,
+						W83627EHF_REG_TEMP_CONFIG[2]);
+			if (reg & 0x01)
+				data->have_temp &= ~(1 << 2);
+			else
+				data->in6_skip = 1;
 		}
 	}
 
@@ -2023,6 +2241,12 @@
 		  W83627EHF_REG_FAN_STEP_OUTPUT_COMMON;
 	}
 
+	/* Setup input voltage scaling factors */
+	if (sio_data->kind == w83627uhg)
+		data->scale_in = scale_in_w83627uhg;
+	else
+		data->scale_in = scale_in_common;
+
 	/* Initialize the chip */
 	w83627ehf_init_device(data, sio_data->kind);
 
@@ -2039,7 +2263,7 @@
 		err = device_create_file(dev, &dev_attr_cpu0_vid);
 		if (err)
 			goto exit_release;
-	} else {
+	} else if (sio_data->kind != w83627uhg) {
 		superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
 		if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) {
 			/* Set VID input sensibility if needed. In theory the
@@ -2080,30 +2304,6 @@
 		}
 	}
 
-	/* fan4 and fan5 share some pins with the GPIO and serial flash */
-	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 {
-		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;
@@ -2121,34 +2321,7 @@
 
 	superio_exit(sio_data->sioreg);
 
-	/* It looks like fan4 and fan5 pins can be alternatively used
-	   as fan on/off switches, but fan5 control is write only :/
-	   We assume that if the serial interface is disabled, designers
-	   connected fan5 as input unless they are emitting log 1, which
-	   is not the default. */
-
-	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);
-		}
-	}
+	w83627ehf_check_fan_inputs(sio_data, data);
 
 	/* Read fan clock dividers immediately */
 	w83627ehf_update_fan_div_common(dev, data);
@@ -2180,7 +2353,14 @@
 				goto exit_remove;
 		}
 	}
-	/* if fan4 is enabled create the sf3 files for it */
+	/* if fan3 and fan4 are enabled create the sf3 files for them */
+	if ((data->has_fan & (1 << 2)) && data->pwm_num >= 3)
+		for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan3); i++) {
+			err = device_create_file(dev,
+					&sda_sf3_arrays_fan3[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
 	if ((data->has_fan & (1 << 3)) && data->pwm_num >= 4)
 		for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) {
 			err = device_create_file(dev,
@@ -2248,6 +2428,8 @@
 			if (err)
 				goto exit_remove;
 		}
+		if (i == 2 && data->temp3_val_only)
+			continue;
 		if (data->reg_temp_over[i]) {
 			err = device_create_file(dev,
 				&sda_temp_max[i].dev_attr);
@@ -2269,6 +2451,16 @@
 			goto exit_remove;
 	}
 
+	err = device_create_file(dev, &sda_caseopen[0].dev_attr);
+	if (err)
+		goto exit_remove;
+
+	if (sio_data->kind == nct6776) {
+		err = device_create_file(dev, &sda_caseopen[1].dev_attr);
+		if (err)
+			goto exit_remove;
+	}
+
 	err = device_create_file(dev, &dev_attr_name);
 	if (err)
 		goto exit_remove;
@@ -2321,6 +2513,7 @@
 	static const char __initdata sio_name_W83627EHG[] = "W83627EHG";
 	static const char __initdata sio_name_W83627DHG[] = "W83627DHG";
 	static const char __initdata sio_name_W83627DHG_P[] = "W83627DHG-P";
+	static const char __initdata sio_name_W83627UHG[] = "W83627UHG";
 	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";
@@ -2353,6 +2546,10 @@
 		sio_data->kind = w83627dhg_p;
 		sio_name = sio_name_W83627DHG_P;
 		break;
+	case SIO_W83627UHG_ID:
+		sio_data->kind = w83627uhg;
+		sio_name = sio_name_W83627UHG;
+		break;
 	case SIO_W83667HG_ID:
 		sio_data->kind = w83667hg;
 		sio_name = sio_name_W83667HG;
diff -druN linux-libre-3.1-gnu/drivers/hwmon/w83781d.c linux-libre-3.2-gnu/drivers/hwmon/w83781d.c
--- linux-libre-3.1-gnu/drivers/hwmon/w83781d.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/w83781d.c	2012-01-04 18:55:44.000000000 -0500
@@ -1245,17 +1245,17 @@
 		/* convert from ISA to LM75 I2C addresses */
 		switch (reg & 0xff) {
 		case 0x50:	/* TEMP */
-			res = swab16(i2c_smbus_read_word_data(cl, 0));
+			res = i2c_smbus_read_word_swapped(cl, 0);
 			break;
 		case 0x52:	/* CONFIG */
 			res = i2c_smbus_read_byte_data(cl, 1);
 			break;
 		case 0x53:	/* HYST */
-			res = swab16(i2c_smbus_read_word_data(cl, 2));
+			res = i2c_smbus_read_word_swapped(cl, 2);
 			break;
 		case 0x55:	/* OVER */
 		default:
-			res = swab16(i2c_smbus_read_word_data(cl, 3));
+			res = i2c_smbus_read_word_swapped(cl, 3);
 			break;
 		}
 	}
@@ -1289,10 +1289,10 @@
 			i2c_smbus_write_byte_data(cl, 1, value & 0xff);
 			break;
 		case 0x53:	/* HYST */
-			i2c_smbus_write_word_data(cl, 2, swab16(value));
+			i2c_smbus_write_word_swapped(cl, 2, value);
 			break;
 		case 0x55:	/* OVER */
-			i2c_smbus_write_word_data(cl, 3, swab16(value));
+			i2c_smbus_write_word_swapped(cl, 3, value);
 			break;
 		}
 	}
diff -druN linux-libre-3.1-gnu/drivers/hwmon/wm831x-hwmon.c linux-libre-3.2-gnu/drivers/hwmon/wm831x-hwmon.c
--- linux-libre-3.1-gnu/drivers/hwmon/wm831x-hwmon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/wm831x-hwmon.c	2012-01-04 18:55:44.000000000 -0500
@@ -209,17 +209,7 @@
 	},
 };
 
-static int __init wm831x_hwmon_init(void)
-{
-	return platform_driver_register(&wm831x_hwmon_driver);
-}
-module_init(wm831x_hwmon_init);
-
-static void __exit wm831x_hwmon_exit(void)
-{
-	platform_driver_unregister(&wm831x_hwmon_driver);
-}
-module_exit(wm831x_hwmon_exit);
+module_platform_driver(wm831x_hwmon_driver);
 
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_DESCRIPTION("WM831x Hardware Monitoring");
diff -druN linux-libre-3.1-gnu/drivers/hwmon/wm8350-hwmon.c linux-libre-3.2-gnu/drivers/hwmon/wm8350-hwmon.c
--- linux-libre-3.1-gnu/drivers/hwmon/wm8350-hwmon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwmon/wm8350-hwmon.c	2012-01-04 18:55:44.000000000 -0500
@@ -133,17 +133,7 @@
 	},
 };
 
-static int __init wm8350_hwmon_init(void)
-{
-	return platform_driver_register(&wm8350_hwmon_driver);
-}
-module_init(wm8350_hwmon_init);
-
-static void __exit wm8350_hwmon_exit(void)
-{
-	platform_driver_unregister(&wm8350_hwmon_driver);
-}
-module_exit(wm8350_hwmon_exit);
+module_platform_driver(wm8350_hwmon_driver);
 
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_DESCRIPTION("WM8350 Hardware Monitoring");
diff -druN linux-libre-3.1-gnu/drivers/hwspinlock/hwspinlock_core.c linux-libre-3.2-gnu/drivers/hwspinlock/hwspinlock_core.c
--- linux-libre-3.1-gnu/drivers/hwspinlock/hwspinlock_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwspinlock/hwspinlock_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/radix-tree.h>
 #include <linux/hwspinlock.h>
 #include <linux/pm_runtime.h>
+#include <linux/mutex.h>
 
 #include "hwspinlock_internal.h"
 
@@ -52,10 +53,12 @@
 static RADIX_TREE(hwspinlock_tree, GFP_KERNEL);
 
 /*
- * Synchronization of access to the tree is achieved using this spinlock,
+ * Synchronization of access to the tree is achieved using this mutex,
  * as the radix-tree API requires that users provide all synchronisation.
+ * A mutex is needed because we're using non-atomic radix tree allocations.
  */
-static DEFINE_SPINLOCK(hwspinlock_tree_lock);
+static DEFINE_MUTEX(hwspinlock_tree_lock);
+
 
 /**
  * __hwspin_trylock() - attempt to lock a specific hwspinlock
@@ -114,7 +117,7 @@
 		return -EBUSY;
 
 	/* try to take the hwspinlock device */
-	ret = hwlock->ops->trylock(hwlock);
+	ret = hwlock->bank->ops->trylock(hwlock);
 
 	/* if hwlock is already taken, undo spin_trylock_* and exit */
 	if (!ret) {
@@ -196,8 +199,8 @@
 		 * Allow platform-specific relax handlers to prevent
 		 * hogging the interconnect (no sleeping, though)
 		 */
-		if (hwlock->ops->relax)
-			hwlock->ops->relax(hwlock);
+		if (hwlock->bank->ops->relax)
+			hwlock->bank->ops->relax(hwlock);
 	}
 
 	return ret;
@@ -242,7 +245,7 @@
 	 */
 	mb();
 
-	hwlock->ops->unlock(hwlock);
+	hwlock->bank->ops->unlock(hwlock);
 
 	/* Undo the spin_trylock{_irq, _irqsave} called while locking */
 	if (mode == HWLOCK_IRQSTATE)
@@ -254,68 +257,37 @@
 }
 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)
+static int hwspin_lock_register_single(struct hwspinlock *hwlock, int id)
 {
 	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);
+	mutex_lock(&hwspinlock_tree_lock);
 
-	ret = radix_tree_insert(&hwspinlock_tree, hwlock->id, hwlock);
-	if (ret)
+	ret = radix_tree_insert(&hwspinlock_tree, id, hwlock);
+	if (ret) {
+		if (ret == -EEXIST)
+			pr_err("hwspinlock id %d already exists!\n", id);
 		goto out;
+	}
 
 	/* mark this hwspinlock as available */
-	tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock->id,
-							HWSPINLOCK_UNUSED);
+	tmp = radix_tree_tag_set(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
 
 	/* self-sanity check which should never fail */
 	WARN_ON(tmp != hwlock);
 
 out:
-	spin_unlock(&hwspinlock_tree_lock);
-	return ret;
+	mutex_unlock(&hwspinlock_tree_lock);
+	return 0;
 }
-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)
+static struct hwspinlock *hwspin_lock_unregister_single(unsigned int id)
 {
 	struct hwspinlock *hwlock = NULL;
 	int ret;
 
-	spin_lock(&hwspinlock_tree_lock);
+	mutex_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);
@@ -331,9 +303,91 @@
 	}
 
 out:
-	spin_unlock(&hwspinlock_tree_lock);
+	mutex_unlock(&hwspinlock_tree_lock);
 	return hwlock;
 }
+
+/**
+ * hwspin_lock_register() - register a new hw spinlock device
+ * @bank: the hwspinlock device, which usually provides numerous hw locks
+ * @dev: the backing device
+ * @ops: hwspinlock handlers for this device
+ * @base_id: id of the first hardware spinlock in this bank
+ * @num_locks: number of hwspinlocks provided by this device
+ *
+ * This function should be called from the underlying platform-specific
+ * implementation, to register a new hwspinlock device instance.
+ *
+ * Should be called from a process context (might sleep)
+ *
+ * Returns 0 on success, or an appropriate error code on failure
+ */
+int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
+		const struct hwspinlock_ops *ops, int base_id, int num_locks)
+{
+	struct hwspinlock *hwlock;
+	int ret = 0, i;
+
+	if (!bank || !ops || !dev || !num_locks || !ops->trylock ||
+							!ops->unlock) {
+		pr_err("invalid parameters\n");
+		return -EINVAL;
+	}
+
+	bank->dev = dev;
+	bank->ops = ops;
+	bank->base_id = base_id;
+	bank->num_locks = num_locks;
+
+	for (i = 0; i < num_locks; i++) {
+		hwlock = &bank->lock[i];
+
+		spin_lock_init(&hwlock->lock);
+		hwlock->bank = bank;
+
+		ret = hwspin_lock_register_single(hwlock, i);
+		if (ret)
+			goto reg_failed;
+	}
+
+	return 0;
+
+reg_failed:
+	while (--i >= 0)
+		hwspin_lock_unregister_single(i);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(hwspin_lock_register);
+
+/**
+ * hwspin_lock_unregister() - unregister an hw spinlock device
+ * @bank: the hwspinlock device, which usually provides numerous hw locks
+ *
+ * This function should be called from the underlying platform-specific
+ * implementation, to unregister an existing (and unused) hwspinlock.
+ *
+ * Should be called from a process context (might sleep)
+ *
+ * Returns 0 on success, or an appropriate error code on failure
+ */
+int hwspin_lock_unregister(struct hwspinlock_device *bank)
+{
+	struct hwspinlock *hwlock, *tmp;
+	int i;
+
+	for (i = 0; i < bank->num_locks; i++) {
+		hwlock = &bank->lock[i];
+
+		tmp = hwspin_lock_unregister_single(bank->base_id + i);
+		if (!tmp)
+			return -EBUSY;
+
+		/* self-sanity check that should never fail */
+		WARN_ON(tmp != hwlock);
+	}
+
+	return 0;
+}
 EXPORT_SYMBOL_GPL(hwspin_lock_unregister);
 
 /**
@@ -348,24 +402,25 @@
  */
 static int __hwspin_lock_request(struct hwspinlock *hwlock)
 {
+	struct device *dev = hwlock->bank->dev;
 	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__);
+	if (!try_module_get(dev->driver->owner)) {
+		dev_err(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);
+	ret = pm_runtime_get_sync(dev);
 	if (ret < 0) {
-		dev_err(hwlock->dev, "%s: can't power on device\n", __func__);
+		dev_err(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,
+	tmp = radix_tree_tag_clear(&hwspinlock_tree, hwlock_to_id(hwlock),
 							HWSPINLOCK_UNUSED);
 
 	/* self-sanity check that should never fail */
@@ -387,7 +442,7 @@
 		return -EINVAL;
 	}
 
-	return hwlock->id;
+	return hwlock_to_id(hwlock);
 }
 EXPORT_SYMBOL_GPL(hwspin_lock_get_id);
 
@@ -400,9 +455,7 @@
  * 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).
+ * Should be called from a process context (might sleep)
  *
  * Returns the address of the assigned hwspinlock, or NULL on error
  */
@@ -411,7 +464,7 @@
 	struct hwspinlock *hwlock;
 	int ret;
 
-	spin_lock(&hwspinlock_tree_lock);
+	mutex_lock(&hwspinlock_tree_lock);
 
 	/* look for an unused lock */
 	ret = radix_tree_gang_lookup_tag(&hwspinlock_tree, (void **)&hwlock,
@@ -431,7 +484,7 @@
 		hwlock = NULL;
 
 out:
-	spin_unlock(&hwspinlock_tree_lock);
+	mutex_unlock(&hwspinlock_tree_lock);
 	return hwlock;
 }
 EXPORT_SYMBOL_GPL(hwspin_lock_request);
@@ -445,9 +498,7 @@
  * 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).
+ * Should be called from a process context (might sleep)
  *
  * Returns the address of the assigned hwspinlock, or NULL on error
  */
@@ -456,7 +507,7 @@
 	struct hwspinlock *hwlock;
 	int ret;
 
-	spin_lock(&hwspinlock_tree_lock);
+	mutex_lock(&hwspinlock_tree_lock);
 
 	/* make sure this hwspinlock exists */
 	hwlock = radix_tree_lookup(&hwspinlock_tree, id);
@@ -466,7 +517,7 @@
 	}
 
 	/* sanity check (this shouldn't happen) */
-	WARN_ON(hwlock->id != id);
+	WARN_ON(hwlock_to_id(hwlock) != id);
 
 	/* make sure this hwspinlock is unused */
 	ret = radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
@@ -482,7 +533,7 @@
 		hwlock = NULL;
 
 out:
-	spin_unlock(&hwspinlock_tree_lock);
+	mutex_unlock(&hwspinlock_tree_lock);
 	return hwlock;
 }
 EXPORT_SYMBOL_GPL(hwspin_lock_request_specific);
@@ -495,14 +546,13 @@
  * 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).
+ * Should be called from a process context (might sleep)
  *
  * Returns 0 on success, or an appropriate error code on failure
  */
 int hwspin_lock_free(struct hwspinlock *hwlock)
 {
+	struct device *dev = hwlock->bank->dev;
 	struct hwspinlock *tmp;
 	int ret;
 
@@ -511,34 +561,34 @@
 		return -EINVAL;
 	}
 
-	spin_lock(&hwspinlock_tree_lock);
+	mutex_lock(&hwspinlock_tree_lock);
 
 	/* make sure the hwspinlock is used */
-	ret = radix_tree_tag_get(&hwspinlock_tree, hwlock->id,
+	ret = radix_tree_tag_get(&hwspinlock_tree, hwlock_to_id(hwlock),
 							HWSPINLOCK_UNUSED);
 	if (ret == 1) {
-		dev_err(hwlock->dev, "%s: hwlock is already free\n", __func__);
+		dev_err(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);
+	ret = pm_runtime_put(dev);
 	if (ret < 0)
 		goto out;
 
 	/* mark this hwspinlock as available */
-	tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock->id,
+	tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock_to_id(hwlock),
 							HWSPINLOCK_UNUSED);
 
 	/* sanity check (this shouldn't happen) */
 	WARN_ON(tmp != hwlock);
 
-	module_put(hwlock->owner);
+	module_put(dev->driver->owner);
 
 out:
-	spin_unlock(&hwspinlock_tree_lock);
+	mutex_unlock(&hwspinlock_tree_lock);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(hwspin_lock_free);
diff -druN linux-libre-3.1-gnu/drivers/hwspinlock/hwspinlock_internal.h linux-libre-3.2-gnu/drivers/hwspinlock/hwspinlock_internal.h
--- linux-libre-3.1-gnu/drivers/hwspinlock/hwspinlock_internal.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwspinlock/hwspinlock_internal.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,8 @@
 #include <linux/spinlock.h>
 #include <linux/device.h>
 
+struct hwspinlock_device;
+
 /**
  * struct hwspinlock_ops - platform-specific hwspinlock handlers
  *
@@ -39,23 +41,37 @@
 
 /**
  * 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.
+ * @bank: the hwspinlock_device structure which owns this 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.
+ * @priv: private data, owned by the underlying platform-specific hwspinlock drv
  */
 struct hwspinlock {
+	struct hwspinlock_device *bank;
+	spinlock_t lock;
+	void *priv;
+};
+
+/**
+ * struct hwspinlock_device - a device which usually spans numerous hwspinlocks
+ * @dev: underlying device, will be used to invoke runtime PM api
+ * @ops: platform-specific hwspinlock handlers
+ * @base_id: id index of the first lock in this device
+ * @num_locks: number of locks in this device
+ * @lock: dynamically allocated array of 'struct hwspinlock'
+ */
+struct hwspinlock_device {
 	struct device *dev;
 	const struct hwspinlock_ops *ops;
-	int id;
-	spinlock_t lock;
-	struct module *owner;
+	int base_id;
+	int num_locks;
+	struct hwspinlock lock[0];
 };
 
+static inline int hwlock_to_id(struct hwspinlock *hwlock)
+{
+	int local_id = hwlock - &hwlock->bank->lock[0];
+
+	return hwlock->bank->base_id + local_id;
+}
+
 #endif /* __HWSPINLOCK_HWSPINLOCK_H */
diff -druN linux-libre-3.1-gnu/drivers/hwspinlock/Kconfig linux-libre-3.2-gnu/drivers/hwspinlock/Kconfig
--- linux-libre-3.1-gnu/drivers/hwspinlock/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwspinlock/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -2,22 +2,31 @@
 # Generic HWSPINLOCK framework
 #
 
+# HWSPINLOCK always gets selected by whoever wants it.
 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).
+	tristate
 
-	  If unsure, say N.
+menu "Hardware Spinlock drivers"
 
 config HWSPINLOCK_OMAP
 	tristate "OMAP Hardware Spinlock device"
-	depends on HWSPINLOCK && ARCH_OMAP4
+	depends on ARCH_OMAP4
+	select HWSPINLOCK
 	help
 	  Say y here to support the OMAP Hardware Spinlock device (firstly
 	  introduced in OMAP4).
 
 	  If unsure, say N.
+
+config HSEM_U8500
+	tristate "STE Hardware Semaphore functionality"
+	depends on ARCH_U8500
+	select HWSPINLOCK
+	help
+	  Say y here to support the STE Hardware Semaphore functionality, which
+	  provides a synchronisation mechanism for the various processor on the
+	  SoC.
+
+	  If unsure, say N.
+
+endmenu
diff -druN linux-libre-3.1-gnu/drivers/hwspinlock/Makefile linux-libre-3.2-gnu/drivers/hwspinlock/Makefile
--- linux-libre-3.1-gnu/drivers/hwspinlock/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwspinlock/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_HWSPINLOCK)		+= hwspinlock_core.o
 obj-$(CONFIG_HWSPINLOCK_OMAP)		+= omap_hwspinlock.o
+obj-$(CONFIG_HSEM_U8500)		+= u8500_hsem.o
diff -druN linux-libre-3.1-gnu/drivers/hwspinlock/omap_hwspinlock.c linux-libre-3.2-gnu/drivers/hwspinlock/omap_hwspinlock.c
--- linux-libre-3.1-gnu/drivers/hwspinlock/omap_hwspinlock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/hwspinlock/omap_hwspinlock.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,33 +41,20 @@
 #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);
+	void __iomem *lock_addr = lock->priv;
 
 	/* attempt to acquire the lock by reading its value */
-	return (SPINLOCK_NOTTAKEN == readl(omap_lock->addr));
+	return (SPINLOCK_NOTTAKEN == readl(lock_addr));
 }
 
 static void omap_hwspinlock_unlock(struct hwspinlock *lock)
 {
-	struct omap_hwspinlock *omap_lock = to_omap_hwspinlock(lock);
+	void __iomem *lock_addr = lock->priv;
 
 	/* release the lock by writing 0 to it */
-	writel(SPINLOCK_NOTTAKEN, omap_lock->addr);
+	writel(SPINLOCK_NOTTAKEN, lock_addr);
 }
 
 /*
@@ -93,26 +80,23 @@
 
 static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
 {
-	struct omap_hwspinlock *omap_lock;
-	struct omap_hwspinlock_state *state;
-	struct hwspinlock *lock;
+	struct hwspinlock_pdata *pdata = pdev->dev.platform_data;
+	struct hwspinlock_device *bank;
+	struct hwspinlock *hwlock;
 	struct resource *res;
 	void __iomem *io_base;
-	int i, ret;
+	int num_locks, i, ret;
+
+	if (!pdata)
+		return -ENODEV;
 
 	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;
-	}
+	if (!io_base)
+		return -ENOMEM;
 
 	/* Determine number of locks */
 	i = readl(io_base + SYSSTATUS_OFFSET);
@@ -124,10 +108,18 @@
 		goto iounmap_base;
 	}
 
-	state->num_locks = i * 32;
-	state->io_base = io_base;
+	num_locks = i * 32; /* actual number of locks in this device */
 
-	platform_set_drvdata(pdev, state);
+	bank = kzalloc(sizeof(*bank) + num_locks * sizeof(*hwlock), GFP_KERNEL);
+	if (!bank) {
+		ret = -ENOMEM;
+		goto iounmap_base;
+	}
+
+	platform_set_drvdata(pdev, bank);
+
+	for (i = 0, hwlock = &bank->lock[0]; i < num_locks; i++, hwlock++)
+		hwlock->priv = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i;
 
 	/*
 	 * runtime PM will make sure the clock of this module is
@@ -135,79 +127,46 @@
 	 */
 	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;
-		}
-	}
+	ret = hwspin_lock_register(bank, &pdev->dev, &omap_hwspinlock_ops,
+						pdata->base_id, num_locks);
+	if (ret)
+		goto reg_fail;
 
 	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);
-	}
+reg_fail:
 	pm_runtime_disable(&pdev->dev);
+	kfree(bank);
 iounmap_base:
 	iounmap(io_base);
-free_state:
-	kfree(state);
 	return ret;
 }
 
-static int omap_hwspinlock_remove(struct platform_device *pdev)
+static int __devexit 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;
-		}
+	struct hwspinlock_device *bank = platform_get_drvdata(pdev);
+	void __iomem *io_base = bank->lock[0].priv - LOCK_BASE_OFFSET;
+	int ret;
 
-		omap_lock = to_omap_hwspinlock(lock);
-		kfree(omap_lock);
+	ret = hwspin_lock_unregister(bank);
+	if (ret) {
+		dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret);
+		return ret;
 	}
 
 	pm_runtime_disable(&pdev->dev);
-	iounmap(state->io_base);
-	kfree(state);
+	iounmap(io_base);
+	kfree(bank);
 
 	return 0;
 }
 
 static struct platform_driver omap_hwspinlock_driver = {
 	.probe		= omap_hwspinlock_probe,
-	.remove		= omap_hwspinlock_remove,
+	.remove		= __devexit_p(omap_hwspinlock_remove),
 	.driver		= {
 		.name	= "omap_hwspinlock",
+		.owner	= THIS_MODULE,
 	},
 };
 
diff -druN linux-libre-3.1-gnu/drivers/hwspinlock/u8500_hsem.c linux-libre-3.2-gnu/drivers/hwspinlock/u8500_hsem.c
--- linux-libre-3.1-gnu/drivers/hwspinlock/u8500_hsem.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/hwspinlock/u8500_hsem.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,197 @@
+/*
+ * u8500 HWSEM driver
+ *
+ * Copyright (C) 2010-2011 ST-Ericsson
+ *
+ * Implements u8500 semaphore handling for protocol 1, no interrupts.
+ *
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ * Heavily borrowed from the work of :
+ *   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/module.h>
+#include <linux/delay.h>
+#include <linux/io.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"
+
+/*
+ * Implementation of STE's HSem protocol 1 without interrutps.
+ * The only masterID we allow is '0x01' to force people to use
+ * HSems for synchronisation between processors rather than processes
+ * on the ARM core.
+ */
+
+#define U8500_MAX_SEMAPHORE		32	/* a total of 32 semaphore */
+#define RESET_SEMAPHORE			(0)	/* free */
+
+/*
+ * CPU ID for master running u8500 kernel.
+ * Hswpinlocks should only be used to synchonise operations
+ * between the Cortex A9 core and the other CPUs.  Hence
+ * forcing the masterID to a preset value.
+ */
+#define HSEM_MASTER_ID			0x01
+
+#define HSEM_REGISTER_OFFSET		0x08
+
+#define HSEM_CTRL_REG			0x00
+#define HSEM_ICRALL			0x90
+#define HSEM_PROTOCOL_1			0x01
+
+static int u8500_hsem_trylock(struct hwspinlock *lock)
+{
+	void __iomem *lock_addr = lock->priv;
+
+	writel(HSEM_MASTER_ID, lock_addr);
+
+	/* get only first 4 bit and compare to masterID.
+	 * if equal, we have the semaphore, otherwise
+	 * someone else has it.
+	 */
+	return (HSEM_MASTER_ID == (0x0F & readl(lock_addr)));
+}
+
+static void u8500_hsem_unlock(struct hwspinlock *lock)
+{
+	void __iomem *lock_addr = lock->priv;
+
+	/* release the lock by writing 0 to it */
+	writel(RESET_SEMAPHORE, lock_addr);
+}
+
+/*
+ * u8500: what value is recommended here ?
+ */
+static void u8500_hsem_relax(struct hwspinlock *lock)
+{
+	ndelay(50);
+}
+
+static const struct hwspinlock_ops u8500_hwspinlock_ops = {
+	.trylock	= u8500_hsem_trylock,
+	.unlock		= u8500_hsem_unlock,
+	.relax		= u8500_hsem_relax,
+};
+
+static int __devinit u8500_hsem_probe(struct platform_device *pdev)
+{
+	struct hwspinlock_pdata *pdata = pdev->dev.platform_data;
+	struct hwspinlock_device *bank;
+	struct hwspinlock *hwlock;
+	struct resource *res;
+	void __iomem *io_base;
+	int i, ret, num_locks = U8500_MAX_SEMAPHORE;
+	ulong val;
+
+	if (!pdata)
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	io_base = ioremap(res->start, resource_size(res));
+	if (!io_base)
+		return -ENOMEM;
+
+	/* make sure protocol 1 is selected */
+	val = readl(io_base + HSEM_CTRL_REG);
+	writel((val & ~HSEM_PROTOCOL_1), io_base + HSEM_CTRL_REG);
+
+	/* clear all interrupts */
+	writel(0xFFFF, io_base + HSEM_ICRALL);
+
+	bank = kzalloc(sizeof(*bank) + num_locks * sizeof(*hwlock), GFP_KERNEL);
+	if (!bank) {
+		ret = -ENOMEM;
+		goto iounmap_base;
+	}
+
+	platform_set_drvdata(pdev, bank);
+
+	for (i = 0, hwlock = &bank->lock[0]; i < num_locks; i++, hwlock++)
+		hwlock->priv = io_base + HSEM_REGISTER_OFFSET + sizeof(u32) * i;
+
+	/* no pm needed for HSem but required to comply with hwspilock core */
+	pm_runtime_enable(&pdev->dev);
+
+	ret = hwspin_lock_register(bank, &pdev->dev, &u8500_hwspinlock_ops,
+						pdata->base_id, num_locks);
+	if (ret)
+		goto reg_fail;
+
+	return 0;
+
+reg_fail:
+	pm_runtime_disable(&pdev->dev);
+	kfree(bank);
+iounmap_base:
+	iounmap(io_base);
+	return ret;
+}
+
+static int __devexit u8500_hsem_remove(struct platform_device *pdev)
+{
+	struct hwspinlock_device *bank = platform_get_drvdata(pdev);
+	void __iomem *io_base = bank->lock[0].priv - HSEM_REGISTER_OFFSET;
+	int ret;
+
+	/* clear all interrupts */
+	writel(0xFFFF, io_base + HSEM_ICRALL);
+
+	ret = hwspin_lock_unregister(bank);
+	if (ret) {
+		dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret);
+		return ret;
+	}
+
+	pm_runtime_disable(&pdev->dev);
+	iounmap(io_base);
+	kfree(bank);
+
+	return 0;
+}
+
+static struct platform_driver u8500_hsem_driver = {
+	.probe		= u8500_hsem_probe,
+	.remove		= __devexit_p(u8500_hsem_remove),
+	.driver		= {
+		.name	= "u8500_hsem",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init u8500_hsem_init(void)
+{
+	return platform_driver_register(&u8500_hsem_driver);
+}
+/* board init code might need to reserve hwspinlocks for predefined purposes */
+postcore_initcall(u8500_hsem_init);
+
+static void __exit u8500_hsem_exit(void)
+{
+	platform_driver_unregister(&u8500_hsem_driver);
+}
+module_exit(u8500_hsem_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Hardware Spinlock driver for u8500");
+MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier@linaro.org>");
diff -druN linux-libre-3.1-gnu/drivers/i2c/algos/i2c-algo-bit.c linux-libre-3.2-gnu/drivers/i2c/algos/i2c-algo-bit.c
--- linux-libre-3.1-gnu/drivers/i2c/algos/i2c-algo-bit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/algos/i2c-algo-bit.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,8 +47,8 @@
 /* ----- global variables ---------------------------------------------	*/
 
 static int bit_test;	/* see if the line-setting functions work	*/
-module_param(bit_test, bool, 0);
-MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
+module_param(bit_test, int, S_IRUGO);
+MODULE_PARM_DESC(bit_test, "lines testing - 0 off; 1 report; 2 fail if stuck");
 
 #ifdef DEBUG
 static int i2c_debug = 1;
@@ -250,7 +250,9 @@
 	sda = getsda(adap);
 	scl = (adap->getscl == NULL) ? 1 : getscl(adap);
 	if (!scl || !sda) {
-		printk(KERN_WARNING "%s: bus seems to be busy\n", name);
+		printk(KERN_WARNING
+		       "%s: bus seems to be busy (scl=%d, sda=%d)\n",
+		       name, scl, sda);
 		goto bailout;
 	}
 
@@ -441,7 +443,7 @@
 					acknak(i2c_adap, 0);
 				dev_err(&i2c_adap->dev, "readbytes: invalid "
 					"block length (%d)\n", inval);
-				return -EREMOTEIO;
+				return -EPROTO;
 			}
 			/* The original count value accounts for the extra
 			   bytes, that is, either 1 for a regular transaction,
@@ -470,7 +472,7 @@
  * reads, writes as well as 10bit-addresses.
  * returns:
  *  0 everything went okay, the chip ack'ed, or IGNORE_NAK flag was set
- * -x an error occurred (like: -EREMOTEIO if the device did not answer, or
+ * -x an error occurred (like: -ENXIO if the device did not answer, or
  *	-ETIMEDOUT, for example if the lines are stuck...)
  */
 static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
@@ -486,21 +488,21 @@
 
 	if (flags & I2C_M_TEN) {
 		/* a ten bit address */
-		addr = 0xf0 | ((msg->addr >> 7) & 0x03);
+		addr = 0xf0 | ((msg->addr >> 7) & 0x06);
 		bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);
 		/* try extended address code...*/
 		ret = try_address(i2c_adap, addr, retries);
 		if ((ret != 1) && !nak_ok)  {
 			dev_err(&i2c_adap->dev,
 				"died at extended address code\n");
-			return -EREMOTEIO;
+			return -ENXIO;
 		}
 		/* the remaining 8 bit address */
-		ret = i2c_outb(i2c_adap, msg->addr & 0x7f);
+		ret = i2c_outb(i2c_adap, msg->addr & 0xff);
 		if ((ret != 1) && !nak_ok) {
 			/* the chip did not ack / xmission error occurred */
 			dev_err(&i2c_adap->dev, "died at 2nd address code\n");
-			return -EREMOTEIO;
+			return -ENXIO;
 		}
 		if (flags & I2C_M_RD) {
 			bit_dbg(3, &i2c_adap->dev, "emitting repeated "
@@ -512,7 +514,7 @@
 			if ((ret != 1) && !nak_ok) {
 				dev_err(&i2c_adap->dev,
 					"died at repeated address code\n");
-				return -EREMOTEIO;
+				return -EIO;
 			}
 		}
 	} else {		/* normal 7bit address	*/
@@ -570,7 +572,7 @@
 					ret, ret == 1 ? "" : "s");
 			if (ret < pmsg->len) {
 				if (ret >= 0)
-					ret = -EREMOTEIO;
+					ret = -EIO;
 				goto bailout;
 			}
 		} else {
@@ -581,7 +583,7 @@
 					ret, ret == 1 ? "" : "s");
 			if (ret < pmsg->len) {
 				if (ret >= 0)
-					ret = -EREMOTEIO;
+					ret = -EIO;
 				goto bailout;
 			}
 		}
@@ -624,7 +626,7 @@
 
 	if (bit_test) {
 		ret = test_bus(adap);
-		if (ret < 0)
+		if (bit_test >= 2 && ret < 0)
 			return -ENODEV;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/i2c/algos/i2c-algo-pca.c linux-libre-3.2-gnu/drivers/i2c/algos/i2c-algo-pca.c
--- linux-libre-3.1-gnu/drivers/i2c/algos/i2c-algo-pca.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/algos/i2c-algo-pca.c	2012-01-04 18:55:44.000000000 -0500
@@ -196,7 +196,7 @@
 		} else {
 			dev_dbg(&i2c_adap->dev, "bus is not idle. status is "
 				"%#04x\n", state);
-			return -EAGAIN;
+			return -EBUSY;
 		}
 	}
 
@@ -224,7 +224,7 @@
 	}
 
 	curmsg = 0;
-	ret = -EREMOTEIO;
+	ret = -EIO;
 	while (curmsg < num) {
 		state = pca_status(adap);
 
@@ -259,6 +259,7 @@
 		case 0x20: /* SLA+W has been transmitted; NOT ACK has been received */
 			DEB2("NOT ACK received after SLA+W\n");
 			pca_stop(adap);
+			ret = -ENXIO;
 			goto out;
 
 		case 0x40: /* SLA+R has been transmitted; ACK has been received */
@@ -283,6 +284,7 @@
 		case 0x48: /* SLA+R has been transmitted; NOT ACK has been received */
 			DEB2("NOT ACK received after SLA+R\n");
 			pca_stop(adap);
+			ret = -ENXIO;
 			goto out;
 
 		case 0x30: /* Data byte in I2CDAT has been transmitted; NOT ACK has been received */
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-au1550.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-au1550.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-au1550.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-au1550.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,32 +36,44 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 
-#include <asm/mach-au1x00/au1xxx.h>
+#include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_psc.h>
 
+#define PSC_SEL		0x00
+#define PSC_CTRL	0x04
+#define PSC_SMBCFG	0x08
+#define PSC_SMBMSK	0x0C
+#define PSC_SMBPCR	0x10
+#define PSC_SMBSTAT	0x14
+#define PSC_SMBEVNT	0x18
+#define PSC_SMBTXRX	0x1C
+#define PSC_SMBTMR	0x20
+
 struct i2c_au1550_data {
-	u32	psc_base;
+	void __iomem *psc_base;
 	int	xfer_timeout;
-	int	ack_timeout;
 	struct i2c_adapter adap;
 	struct resource *ioarea;
 };
 
-static int
-wait_xfer_done(struct i2c_au1550_data *adap)
+static inline void WR(struct i2c_au1550_data *a, int r, unsigned long v)
 {
-	u32	stat;
-	int	i;
-	volatile psc_smb_t	*sp;
+	__raw_writel(v, a->psc_base + r);
+	wmb();
+}
 
-	sp = (volatile psc_smb_t *)(adap->psc_base);
+static inline unsigned long RD(struct i2c_au1550_data *a, int r)
+{
+	return __raw_readl(a->psc_base + r);
+}
 
-	/* Wait for Tx Buffer Empty
-	*/
+static int wait_xfer_done(struct i2c_au1550_data *adap)
+{
+	int i;
+
+	/* Wait for Tx Buffer Empty */
 	for (i = 0; i < adap->xfer_timeout; i++) {
-		stat = sp->psc_smbstat;
-		au_sync();
-		if ((stat & PSC_SMBSTAT_TE) != 0)
+		if (RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_TE)
 			return 0;
 
 		udelay(1);
@@ -70,41 +82,27 @@
 	return -ETIMEDOUT;
 }
 
-static int
-wait_ack(struct i2c_au1550_data *adap)
+static int wait_ack(struct i2c_au1550_data *adap)
 {
-	u32	stat;
-	volatile psc_smb_t	*sp;
+	unsigned long stat;
 
 	if (wait_xfer_done(adap))
 		return -ETIMEDOUT;
 
-	sp = (volatile psc_smb_t *)(adap->psc_base);
-
-	stat = sp->psc_smbevnt;
-	au_sync();
-
+	stat = RD(adap, PSC_SMBEVNT);
 	if ((stat & (PSC_SMBEVNT_DN | PSC_SMBEVNT_AN | PSC_SMBEVNT_AL)) != 0)
 		return -ETIMEDOUT;
 
 	return 0;
 }
 
-static int
-wait_master_done(struct i2c_au1550_data *adap)
+static int wait_master_done(struct i2c_au1550_data *adap)
 {
-	u32	stat;
-	int	i;
-	volatile psc_smb_t	*sp;
-
-	sp = (volatile psc_smb_t *)(adap->psc_base);
+	int i;
 
-	/* Wait for Master Done.
-	*/
-	for (i = 0; i < adap->xfer_timeout; i++) {
-		stat = sp->psc_smbevnt;
-		au_sync();
-		if ((stat & PSC_SMBEVNT_MD) != 0)
+	/* Wait for Master Done. */
+	for (i = 0; i < 2 * adap->xfer_timeout; i++) {
+		if ((RD(adap, PSC_SMBEVNT) & PSC_SMBEVNT_MD) != 0)
 			return 0;
 		udelay(1);
 	}
@@ -115,29 +113,20 @@
 static int
 do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q)
 {
-	volatile psc_smb_t	*sp;
-	u32			stat;
-
-	sp = (volatile psc_smb_t *)(adap->psc_base);
+	unsigned long stat;
 
-	/* Reset the FIFOs, clear events.
-	*/
-	stat = sp->psc_smbstat;
-	sp->psc_smbevnt = PSC_SMBEVNT_ALLCLR;
-	au_sync();
+	/* Reset the FIFOs, clear events. */
+	stat = RD(adap, PSC_SMBSTAT);
+	WR(adap, PSC_SMBEVNT, PSC_SMBEVNT_ALLCLR);
 
 	if (!(stat & PSC_SMBSTAT_TE) || !(stat & PSC_SMBSTAT_RE)) {
-		sp->psc_smbpcr = PSC_SMBPCR_DC;
-		au_sync();
-		do {
-			stat = sp->psc_smbpcr;
-			au_sync();
-		} while ((stat & PSC_SMBPCR_DC) != 0);
+		WR(adap, PSC_SMBPCR, PSC_SMBPCR_DC);
+		while ((RD(adap, PSC_SMBPCR) & PSC_SMBPCR_DC) != 0)
+			cpu_relax();
 		udelay(50);
 	}
 
-	/* Write out the i2c chip address and specify operation
-	*/
+	/* Write out the i2c chip address and specify operation */
 	addr <<= 1;
 	if (rd)
 		addr |= 1;
@@ -146,56 +135,42 @@
 	if (q)
 		addr |= PSC_SMBTXRX_STP;
 
-	/* Put byte into fifo, start up master.
-	*/
-	sp->psc_smbtxrx = addr;
-	au_sync();
-	sp->psc_smbpcr = PSC_SMBPCR_MS;
-	au_sync();
+	/* Put byte into fifo, start up master. */
+	WR(adap, PSC_SMBTXRX, addr);
+	WR(adap, PSC_SMBPCR, PSC_SMBPCR_MS);
 	if (wait_ack(adap))
 		return -EIO;
 	return (q) ? wait_master_done(adap) : 0;
 }
 
-static u32
-wait_for_rx_byte(struct i2c_au1550_data *adap, u32 *ret_data)
+static int wait_for_rx_byte(struct i2c_au1550_data *adap, unsigned char *out)
 {
-	int	j;
-	u32	data, stat;
-	volatile psc_smb_t	*sp;
+	int j;
 
 	if (wait_xfer_done(adap))
 		return -EIO;
 
-	sp = (volatile psc_smb_t *)(adap->psc_base);
-
 	j =  adap->xfer_timeout * 100;
 	do {
 		j--;
 		if (j <= 0)
 			return -EIO;
 
-		stat = sp->psc_smbstat;
-		au_sync();
-		if ((stat & PSC_SMBSTAT_RE) == 0)
+		if ((RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_RE) == 0)
 			j = 0;
 		else
 			udelay(1);
 	} while (j > 0);
-	data = sp->psc_smbtxrx;
-	au_sync();
-	*ret_data = data;
+
+	*out = RD(adap, PSC_SMBTXRX);
 
 	return 0;
 }
 
-static int
-i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
+static int i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
 		    unsigned int len)
 {
-	int	i;
-	u32	data;
-	volatile psc_smb_t	*sp;
+	int i;
 
 	if (len == 0)
 		return 0;
@@ -204,62 +179,46 @@
 	 * zero bytes for timing, waiting for bytes to appear in the
 	 * receive fifo, then reading the bytes.
 	 */
-
-	sp = (volatile psc_smb_t *)(adap->psc_base);
-
 	i = 0;
-	while (i < (len-1)) {
-		sp->psc_smbtxrx = 0;
-		au_sync();
-		if (wait_for_rx_byte(adap, &data))
+	while (i < (len - 1)) {
+		WR(adap, PSC_SMBTXRX, 0);
+		if (wait_for_rx_byte(adap, &buf[i]))
 			return -EIO;
 
-		buf[i] = data;
 		i++;
 	}
 
-	/* The last byte has to indicate transfer done.
-	*/
-	sp->psc_smbtxrx = PSC_SMBTXRX_STP;
-	au_sync();
+	/* The last byte has to indicate transfer done. */
+	WR(adap, PSC_SMBTXRX, PSC_SMBTXRX_STP);
 	if (wait_master_done(adap))
 		return -EIO;
 
-	data = sp->psc_smbtxrx;
-	au_sync();
-	buf[i] = data;
+	buf[i] = (unsigned char)(RD(adap, PSC_SMBTXRX) & 0xff);
 	return 0;
 }
 
-static int
-i2c_write(struct i2c_au1550_data *adap, unsigned char *buf,
+static int i2c_write(struct i2c_au1550_data *adap, unsigned char *buf,
 		     unsigned int len)
 {
-	int	i;
-	u32	data;
-	volatile psc_smb_t	*sp;
+	int i;
+	unsigned long data;
 
 	if (len == 0)
 		return 0;
 
-	sp = (volatile psc_smb_t *)(adap->psc_base);
-
 	i = 0;
 	while (i < (len-1)) {
 		data = buf[i];
-		sp->psc_smbtxrx = data;
-		au_sync();
+		WR(adap, PSC_SMBTXRX, data);
 		if (wait_ack(adap))
 			return -EIO;
 		i++;
 	}
 
-	/* The last byte has to indicate transfer done.
-	*/
+	/* The last byte has to indicate transfer done. */
 	data = buf[i];
 	data |= PSC_SMBTXRX_STP;
-	sp->psc_smbtxrx = data;
-	au_sync();
+	WR(adap, PSC_SMBTXRX, data);
 	if (wait_master_done(adap))
 		return -EIO;
 	return 0;
@@ -269,12 +228,10 @@
 au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
 {
 	struct i2c_au1550_data *adap = i2c_adap->algo_data;
-	volatile psc_smb_t *sp = (volatile psc_smb_t *)adap->psc_base;
 	struct i2c_msg *p;
 	int i, err = 0;
 
-	sp->psc_ctrl = PSC_CTRL_ENABLE;
-	au_sync();
+	WR(adap, PSC_CTRL, PSC_CTRL_ENABLE);
 
 	for (i = 0; !err && i < num; i++) {
 		p = &msgs[i];
@@ -293,14 +250,12 @@
 	if (err == 0)
 		err = num;
 
-	sp->psc_ctrl = PSC_CTRL_SUSPEND;
-	au_sync();
+	WR(adap, PSC_CTRL, PSC_CTRL_SUSPEND);
 
 	return err;
 }
 
-static u32
-au1550_func(struct i2c_adapter *adap)
+static u32 au1550_func(struct i2c_adapter *adap)
 {
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
@@ -312,57 +267,45 @@
 
 static void i2c_au1550_setup(struct i2c_au1550_data *priv)
 {
-	volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
-	u32 stat;
+	unsigned long cfg;
 
-	sp->psc_ctrl = PSC_CTRL_DISABLE;
-	au_sync();
-	sp->psc_sel = PSC_SEL_PS_SMBUSMODE;
-	sp->psc_smbcfg = 0;
-	au_sync();
-	sp->psc_ctrl = PSC_CTRL_ENABLE;
-	au_sync();
-	do {
-		stat = sp->psc_smbstat;
-		au_sync();
-	} while ((stat & PSC_SMBSTAT_SR) == 0);
+	WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
+	WR(priv, PSC_SEL, PSC_SEL_PS_SMBUSMODE);
+	WR(priv, PSC_SMBCFG, 0);
+	WR(priv, PSC_CTRL, PSC_CTRL_ENABLE);
+	while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
+		cpu_relax();
 
-	sp->psc_smbcfg = (PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 |
-				PSC_SMBCFG_DD_DISABLE);
+	cfg = PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 | PSC_SMBCFG_DD_DISABLE;
+	WR(priv, PSC_SMBCFG, cfg);
 
 	/* Divide by 8 to get a 6.25 MHz clock.  The later protocol
 	 * timings are based on this clock.
 	 */
-	sp->psc_smbcfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
-	sp->psc_smbmsk = PSC_SMBMSK_ALLMASK;
-	au_sync();
+	cfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
+	WR(priv, PSC_SMBCFG, cfg);
+	WR(priv, PSC_SMBMSK, PSC_SMBMSK_ALLMASK);
 
 	/* Set the protocol timer values.  See Table 71 in the
 	 * Au1550 Data Book for standard timing values.
 	 */
-	sp->psc_smbtmr = PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
+	WR(priv, PSC_SMBTMR, PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
 		PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \
 		PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \
-		PSC_SMBTMR_SET_CH(15);
-	au_sync();
+		PSC_SMBTMR_SET_CH(15));
 
-	sp->psc_smbcfg |= PSC_SMBCFG_DE_ENABLE;
-	do {
-		stat = sp->psc_smbstat;
-		au_sync();
-	} while ((stat & PSC_SMBSTAT_SR) == 0);
+	cfg |= PSC_SMBCFG_DE_ENABLE;
+	WR(priv, PSC_SMBCFG, cfg);
+	while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
+		cpu_relax();
 
-	sp->psc_ctrl = PSC_CTRL_SUSPEND;
-	au_sync();
+	WR(priv, PSC_CTRL, PSC_CTRL_SUSPEND);
 }
 
 static void i2c_au1550_disable(struct i2c_au1550_data *priv)
 {
-	volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
-
-	sp->psc_smbcfg = 0;
-	sp->psc_ctrl = PSC_CTRL_DISABLE;
-	au_sync();
+	WR(priv, PSC_SMBCFG, 0);
+	WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
 }
 
 /*
@@ -396,9 +339,12 @@
 		goto out_mem;
 	}
 
-	priv->psc_base = CKSEG1ADDR(r->start);
+	priv->psc_base = ioremap(r->start, resource_size(r));
+	if (!priv->psc_base) {
+		ret = -EIO;
+		goto out_map;
+	}
 	priv->xfer_timeout = 200;
-	priv->ack_timeout = 200;
 
 	priv->adap.nr = pdev->id;
 	priv->adap.algo = &au1550_algo;
@@ -406,8 +352,7 @@
 	priv->adap.dev.parent = &pdev->dev;
 	strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name));
 
-	/* Now, set up the PSC for SMBus PIO mode.
-	*/
+	/* Now, set up the PSC for SMBus PIO mode. */
 	i2c_au1550_setup(priv);
 
 	ret = i2c_add_numbered_adapter(&priv->adap);
@@ -417,7 +362,8 @@
 	}
 
 	i2c_au1550_disable(priv);
-
+	iounmap(priv->psc_base);
+out_map:
 	release_resource(priv->ioarea);
 	kfree(priv->ioarea);
 out_mem:
@@ -426,14 +372,14 @@
 	return ret;
 }
 
-static int __devexit
-i2c_au1550_remove(struct platform_device *pdev)
+static int __devexit i2c_au1550_remove(struct platform_device *pdev)
 {
 	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
 
 	platform_set_drvdata(pdev, NULL);
 	i2c_del_adapter(&priv->adap);
 	i2c_au1550_disable(priv);
+	iounmap(priv->psc_base);
 	release_resource(priv->ioarea);
 	kfree(priv->ioarea);
 	kfree(priv);
@@ -441,49 +387,51 @@
 }
 
 #ifdef CONFIG_PM
-static int
-i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state)
+static int i2c_au1550_suspend(struct device *dev)
 {
-	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
+	struct i2c_au1550_data *priv = dev_get_drvdata(dev);
 
 	i2c_au1550_disable(priv);
 
 	return 0;
 }
 
-static int
-i2c_au1550_resume(struct platform_device *pdev)
+static int i2c_au1550_resume(struct device *dev)
 {
-	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
+	struct i2c_au1550_data *priv = dev_get_drvdata(dev);
 
 	i2c_au1550_setup(priv);
 
 	return 0;
 }
+
+static const struct dev_pm_ops i2c_au1550_pmops = {
+	.suspend	= i2c_au1550_suspend,
+	.resume		= i2c_au1550_resume,
+};
+
+#define AU1XPSC_SMBUS_PMOPS (&i2c_au1550_pmops)
+
 #else
-#define i2c_au1550_suspend	NULL
-#define i2c_au1550_resume	NULL
+#define AU1XPSC_SMBUS_PMOPS NULL
 #endif
 
 static struct platform_driver au1xpsc_smbus_driver = {
 	.driver = {
 		.name	= "au1xpsc_smbus",
 		.owner	= THIS_MODULE,
+		.pm	= AU1XPSC_SMBUS_PMOPS,
 	},
 	.probe		= i2c_au1550_probe,
 	.remove		= __devexit_p(i2c_au1550_remove),
-	.suspend	= i2c_au1550_suspend,
-	.resume		= i2c_au1550_resume,
 };
 
-static int __init
-i2c_au1550_init(void)
+static int __init i2c_au1550_init(void)
 {
 	return platform_driver_register(&au1xpsc_smbus_driver);
 }
 
-static void __exit
-i2c_au1550_exit(void)
+static void __exit i2c_au1550_exit(void)
 {
 	platform_driver_unregister(&au1xpsc_smbus_driver);
 }
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-bfin-twi.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-bfin-twi.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-bfin-twi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-bfin-twi.c	2012-01-04 18:55:44.000000000 -0500
@@ -631,7 +631,7 @@
 	struct bfin_twi_iface *iface = platform_get_drvdata(pdev);
 
 	int rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
-		IRQF_DISABLED, pdev->name, iface);
+		0, pdev->name, iface);
 	if (rc) {
 		dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq);
 		return -ENODEV;
@@ -702,7 +702,7 @@
 	}
 
 	rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
-		IRQF_DISABLED, pdev->name, iface);
+		0, pdev->name, iface);
 	if (rc) {
 		dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq);
 		rc = -ENODEV;
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-designware.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-designware.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-designware.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-designware.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,847 +0,0 @@
-/*
- * Synopsys DesignWare I2C adapter driver (master only).
- *
- * Based on the TI DAVINCI I2C adapter driver.
- *
- * Copyright (C) 2006 Texas Instruments.
- * Copyright (C) 2007 MontaVista Software Inc.
- * Copyright (C) 2009 Provigent Ltd.
- *
- * ----------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- * ----------------------------------------------------------------------------
- *
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/clk.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-/*
- * Registers offset
- */
-#define DW_IC_CON		0x0
-#define DW_IC_TAR		0x4
-#define DW_IC_DATA_CMD		0x10
-#define DW_IC_SS_SCL_HCNT	0x14
-#define DW_IC_SS_SCL_LCNT	0x18
-#define DW_IC_FS_SCL_HCNT	0x1c
-#define DW_IC_FS_SCL_LCNT	0x20
-#define DW_IC_INTR_STAT		0x2c
-#define DW_IC_INTR_MASK		0x30
-#define DW_IC_RAW_INTR_STAT	0x34
-#define DW_IC_RX_TL		0x38
-#define DW_IC_TX_TL		0x3c
-#define DW_IC_CLR_INTR		0x40
-#define DW_IC_CLR_RX_UNDER	0x44
-#define DW_IC_CLR_RX_OVER	0x48
-#define DW_IC_CLR_TX_OVER	0x4c
-#define DW_IC_CLR_RD_REQ	0x50
-#define DW_IC_CLR_TX_ABRT	0x54
-#define DW_IC_CLR_RX_DONE	0x58
-#define DW_IC_CLR_ACTIVITY	0x5c
-#define DW_IC_CLR_STOP_DET	0x60
-#define DW_IC_CLR_START_DET	0x64
-#define DW_IC_CLR_GEN_CALL	0x68
-#define DW_IC_ENABLE		0x6c
-#define DW_IC_STATUS		0x70
-#define DW_IC_TXFLR		0x74
-#define DW_IC_RXFLR		0x78
-#define DW_IC_COMP_PARAM_1	0xf4
-#define DW_IC_TX_ABRT_SOURCE	0x80
-
-#define DW_IC_CON_MASTER		0x1
-#define DW_IC_CON_SPEED_STD		0x2
-#define DW_IC_CON_SPEED_FAST		0x4
-#define DW_IC_CON_10BITADDR_MASTER	0x10
-#define DW_IC_CON_RESTART_EN		0x20
-#define DW_IC_CON_SLAVE_DISABLE		0x40
-
-#define DW_IC_INTR_RX_UNDER	0x001
-#define DW_IC_INTR_RX_OVER	0x002
-#define DW_IC_INTR_RX_FULL	0x004
-#define DW_IC_INTR_TX_OVER	0x008
-#define DW_IC_INTR_TX_EMPTY	0x010
-#define DW_IC_INTR_RD_REQ	0x020
-#define DW_IC_INTR_TX_ABRT	0x040
-#define DW_IC_INTR_RX_DONE	0x080
-#define DW_IC_INTR_ACTIVITY	0x100
-#define DW_IC_INTR_STOP_DET	0x200
-#define DW_IC_INTR_START_DET	0x400
-#define DW_IC_INTR_GEN_CALL	0x800
-
-#define DW_IC_INTR_DEFAULT_MASK		(DW_IC_INTR_RX_FULL | \
-					 DW_IC_INTR_TX_EMPTY | \
-					 DW_IC_INTR_TX_ABRT | \
-					 DW_IC_INTR_STOP_DET)
-
-#define DW_IC_STATUS_ACTIVITY	0x1
-
-#define DW_IC_ERR_TX_ABRT	0x1
-
-/*
- * status codes
- */
-#define STATUS_IDLE			0x0
-#define STATUS_WRITE_IN_PROGRESS	0x1
-#define STATUS_READ_IN_PROGRESS		0x2
-
-#define TIMEOUT			20 /* ms */
-
-/*
- * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register
- *
- * only expected abort codes are listed here
- * refer to the datasheet for the full list
- */
-#define ABRT_7B_ADDR_NOACK	0
-#define ABRT_10ADDR1_NOACK	1
-#define ABRT_10ADDR2_NOACK	2
-#define ABRT_TXDATA_NOACK	3
-#define ABRT_GCALL_NOACK	4
-#define ABRT_GCALL_READ		5
-#define ABRT_SBYTE_ACKDET	7
-#define ABRT_SBYTE_NORSTRT	9
-#define ABRT_10B_RD_NORSTRT	10
-#define ABRT_MASTER_DIS		11
-#define ARB_LOST		12
-
-#define DW_IC_TX_ABRT_7B_ADDR_NOACK	(1UL << ABRT_7B_ADDR_NOACK)
-#define DW_IC_TX_ABRT_10ADDR1_NOACK	(1UL << ABRT_10ADDR1_NOACK)
-#define DW_IC_TX_ABRT_10ADDR2_NOACK	(1UL << ABRT_10ADDR2_NOACK)
-#define DW_IC_TX_ABRT_TXDATA_NOACK	(1UL << ABRT_TXDATA_NOACK)
-#define DW_IC_TX_ABRT_GCALL_NOACK	(1UL << ABRT_GCALL_NOACK)
-#define DW_IC_TX_ABRT_GCALL_READ	(1UL << ABRT_GCALL_READ)
-#define DW_IC_TX_ABRT_SBYTE_ACKDET	(1UL << ABRT_SBYTE_ACKDET)
-#define DW_IC_TX_ABRT_SBYTE_NORSTRT	(1UL << ABRT_SBYTE_NORSTRT)
-#define DW_IC_TX_ABRT_10B_RD_NORSTRT	(1UL << ABRT_10B_RD_NORSTRT)
-#define DW_IC_TX_ABRT_MASTER_DIS	(1UL << ABRT_MASTER_DIS)
-#define DW_IC_TX_ARB_LOST		(1UL << ARB_LOST)
-
-#define DW_IC_TX_ABRT_NOACK		(DW_IC_TX_ABRT_7B_ADDR_NOACK | \
-					 DW_IC_TX_ABRT_10ADDR1_NOACK | \
-					 DW_IC_TX_ABRT_10ADDR2_NOACK | \
-					 DW_IC_TX_ABRT_TXDATA_NOACK | \
-					 DW_IC_TX_ABRT_GCALL_NOACK)
-
-static char *abort_sources[] = {
-	[ABRT_7B_ADDR_NOACK] =
-		"slave address not acknowledged (7bit mode)",
-	[ABRT_10ADDR1_NOACK] =
-		"first address byte not acknowledged (10bit mode)",
-	[ABRT_10ADDR2_NOACK] =
-		"second address byte not acknowledged (10bit mode)",
-	[ABRT_TXDATA_NOACK] =
-		"data not acknowledged",
-	[ABRT_GCALL_NOACK] =
-		"no acknowledgement for a general call",
-	[ABRT_GCALL_READ] =
-		"read after general call",
-	[ABRT_SBYTE_ACKDET] =
-		"start byte acknowledged",
-	[ABRT_SBYTE_NORSTRT] =
-		"trying to send start byte when restart is disabled",
-	[ABRT_10B_RD_NORSTRT] =
-		"trying to read when restart is disabled (10bit mode)",
-	[ABRT_MASTER_DIS] =
-		"trying to use disabled adapter",
-	[ARB_LOST] =
-		"lost arbitration",
-};
-
-/**
- * struct dw_i2c_dev - private i2c-designware data
- * @dev: driver model device node
- * @base: IO registers pointer
- * @cmd_complete: tx completion indicator
- * @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 transferred
- * @msgs_num: the number of elements in msgs
- * @msg_write_idx: the element index of the current tx message in the msgs
- *	array
- * @tx_buf_len: the length of the current tx buffer
- * @tx_buf: the current tx buffer
- * @msg_read_idx: the element index of the current rx message in the msgs
- *	array
- * @rx_buf_len: the length of the current rx buffer
- * @rx_buf: the current rx buffer
- * @msg_err: error status of the current transfer
- * @status: i2c master status, one of STATUS_*
- * @abort_source: copy of the TX_ABRT_SOURCE register
- * @irq: interrupt number for the i2c master
- * @adapter: i2c subsystem adapter node
- * @tx_fifo_depth: depth of the hardware tx fifo
- * @rx_fifo_depth: depth of the hardware rx fifo
- */
-struct dw_i2c_dev {
-	struct device		*dev;
-	void __iomem		*base;
-	struct completion	cmd_complete;
-	struct mutex		lock;
-	struct clk		*clk;
-	int			cmd_err;
-	struct i2c_msg		*msgs;
-	int			msgs_num;
-	int			msg_write_idx;
-	u32			tx_buf_len;
-	u8			*tx_buf;
-	int			msg_read_idx;
-	u32			rx_buf_len;
-	u8			*rx_buf;
-	int			msg_err;
-	unsigned int		status;
-	u32			abort_source;
-	int			irq;
-	struct i2c_adapter	adapter;
-	unsigned int		tx_fifo_depth;
-	unsigned int		rx_fifo_depth;
-};
-
-static u32
-i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
-{
-	/*
-	 * DesignWare I2C core doesn't seem to have solid strategy to meet
-	 * the tHD;STA timing spec.  Configuring _HCNT based on tHIGH spec
-	 * will result in violation of the tHD;STA spec.
-	 */
-	if (cond)
-		/*
-		 * Conditional expression:
-		 *
-		 *   IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH
-		 *
-		 * This is based on the DW manuals, and represents an ideal
-		 * configuration.  The resulting I2C bus speed will be
-		 * faster than any of the others.
-		 *
-		 * If your hardware is free from tHD;STA issue, try this one.
-		 */
-		return (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset;
-	else
-		/*
-		 * Conditional expression:
-		 *
-		 *   IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf)
-		 *
-		 * This is just experimental rule; the tHD;STA period turned
-		 * out to be proportinal to (_HCNT + 3).  With this setting,
-		 * we could meet both tHIGH and tHD;STA timing specs.
-		 *
-		 * If unsure, you'd better to take this alternative.
-		 *
-		 * The reason why we need to take into account "tf" here,
-		 * is the same as described in i2c_dw_scl_lcnt().
-		 */
-		return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset;
-}
-
-static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
-{
-	/*
-	 * Conditional expression:
-	 *
-	 *   IC_[FS]S_SCL_LCNT + 1 >= IC_CLK * (tLOW + tf)
-	 *
-	 * DW I2C core starts counting the SCL CNTs for the LOW period
-	 * of the SCL clock (tLOW) as soon as it pulls the SCL line.
-	 * In order to meet the tLOW timing spec, we need to take into
-	 * account the fall time of SCL signal (tf).  Default tf value
-	 * should be 0.3 us, for safety.
-	 */
-	return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset;
-}
-
-/**
- * i2c_dw_init() - initialize the designware i2c master hardware
- * @dev: device private data
- *
- * This functions configures and enables the I2C master.
- * This function is called during I2C init function, and in case of timeout at
- * run time.
- */
-static void i2c_dw_init(struct dw_i2c_dev *dev)
-{
-	u32 input_clock_khz = clk_get_rate(dev->clk) / 1000;
-	u32 ic_con, hcnt, lcnt;
-
-	/* Disable the adapter */
-	writel(0, dev->base + DW_IC_ENABLE);
-
-	/* set standard and fast speed deviders for high/low periods */
-
-	/* Standard-mode */
-	hcnt = i2c_dw_scl_hcnt(input_clock_khz,
-				40,	/* tHD;STA = tHIGH = 4.0 us */
-				3,	/* tf = 0.3 us */
-				0,	/* 0: DW default, 1: Ideal */
-				0);	/* No offset */
-	lcnt = i2c_dw_scl_lcnt(input_clock_khz,
-				47,	/* tLOW = 4.7 us */
-				3,	/* tf = 0.3 us */
-				0);	/* No offset */
-	writel(hcnt, dev->base + DW_IC_SS_SCL_HCNT);
-	writel(lcnt, dev->base + DW_IC_SS_SCL_LCNT);
-	dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
-
-	/* Fast-mode */
-	hcnt = i2c_dw_scl_hcnt(input_clock_khz,
-				6,	/* tHD;STA = tHIGH = 0.6 us */
-				3,	/* tf = 0.3 us */
-				0,	/* 0: DW default, 1: Ideal */
-				0);	/* No offset */
-	lcnt = i2c_dw_scl_lcnt(input_clock_khz,
-				13,	/* tLOW = 1.3 us */
-				3,	/* tf = 0.3 us */
-				0);	/* No offset */
-	writel(hcnt, dev->base + DW_IC_FS_SCL_HCNT);
-	writel(lcnt, dev->base + DW_IC_FS_SCL_LCNT);
-	dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
-
-	/* Configure Tx/Rx FIFO threshold levels */
-	writel(dev->tx_fifo_depth - 1, dev->base + DW_IC_TX_TL);
-	writel(0, dev->base + DW_IC_RX_TL);
-
-	/* configure the i2c master */
-	ic_con = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
-		DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
-	writel(ic_con, dev->base + DW_IC_CON);
-}
-
-/*
- * Waiting for bus not busy
- */
-static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
-{
-	int timeout = TIMEOUT;
-
-	while (readl(dev->base + DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
-		if (timeout <= 0) {
-			dev_warn(dev->dev, "timeout waiting for bus ready\n");
-			return -ETIMEDOUT;
-		}
-		timeout--;
-		mdelay(1);
-	}
-
-	return 0;
-}
-
-static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
-{
-	struct i2c_msg *msgs = dev->msgs;
-	u32 ic_con;
-
-	/* Disable the adapter */
-	writel(0, dev->base + DW_IC_ENABLE);
-
-	/* set the slave (target) address */
-	writel(msgs[dev->msg_write_idx].addr, dev->base + DW_IC_TAR);
-
-	/* if the slave address is ten bit address, enable 10BITADDR */
-	ic_con = readl(dev->base + DW_IC_CON);
-	if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
-		ic_con |= DW_IC_CON_10BITADDR_MASTER;
-	else
-		ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
-	writel(ic_con, dev->base + DW_IC_CON);
-
-	/* Enable the adapter */
-	writel(1, dev->base + DW_IC_ENABLE);
-
-	/* Enable interrupts */
-	writel(DW_IC_INTR_DEFAULT_MASK, dev->base + DW_IC_INTR_MASK);
-}
-
-/*
- * Initiate (and continue) low level master read/write transaction.
- * This function is only called from i2c_dw_isr, and pumping i2c_msg
- * messages into the tx buffer.  Even if the size of i2c_msg data is
- * longer than the size of the tx buffer, it handles everything.
- */
-static void
-i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
-{
-	struct i2c_msg *msgs = dev->msgs;
-	u32 intr_mask;
-	int tx_limit, rx_limit;
-	u32 addr = msgs[dev->msg_write_idx].addr;
-	u32 buf_len = dev->tx_buf_len;
-	u8 *buf = dev->tx_buf;;
-
-	intr_mask = DW_IC_INTR_DEFAULT_MASK;
-
-	for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) {
-		/*
-		 * if target address has changed, we need to
-		 * reprogram the target address in the i2c
-		 * adapter when we are done with this transfer
-		 */
-		if (msgs[dev->msg_write_idx].addr != addr) {
-			dev_err(dev->dev,
-				"%s: invalid target address\n", __func__);
-			dev->msg_err = -EINVAL;
-			break;
-		}
-
-		if (msgs[dev->msg_write_idx].len == 0) {
-			dev_err(dev->dev,
-				"%s: invalid message length\n", __func__);
-			dev->msg_err = -EINVAL;
-			break;
-		}
-
-		if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) {
-			/* new i2c_msg */
-			buf = msgs[dev->msg_write_idx].buf;
-			buf_len = msgs[dev->msg_write_idx].len;
-		}
-
-		tx_limit = dev->tx_fifo_depth - readl(dev->base + DW_IC_TXFLR);
-		rx_limit = dev->rx_fifo_depth - readl(dev->base + DW_IC_RXFLR);
-
-		while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
-			if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
-				writel(0x100, dev->base + DW_IC_DATA_CMD);
-				rx_limit--;
-			} else
-				writel(*buf++, dev->base + DW_IC_DATA_CMD);
-			tx_limit--; buf_len--;
-		}
-
-		dev->tx_buf = buf;
-		dev->tx_buf_len = buf_len;
-
-		if (buf_len > 0) {
-			/* more bytes to be written */
-			dev->status |= STATUS_WRITE_IN_PROGRESS;
-			break;
-		} else
-			dev->status &= ~STATUS_WRITE_IN_PROGRESS;
-	}
-
-	/*
-	 * If i2c_msg index search is completed, we don't need TX_EMPTY
-	 * interrupt any more.
-	 */
-	if (dev->msg_write_idx == dev->msgs_num)
-		intr_mask &= ~DW_IC_INTR_TX_EMPTY;
-
-	if (dev->msg_err)
-		intr_mask = 0;
-
-	writel(intr_mask, dev->base + DW_IC_INTR_MASK);
-}
-
-static void
-i2c_dw_read(struct dw_i2c_dev *dev)
-{
-	struct i2c_msg *msgs = dev->msgs;
-	int rx_valid;
-
-	for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) {
-		u32 len;
-		u8 *buf;
-
-		if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD))
-			continue;
-
-		if (!(dev->status & STATUS_READ_IN_PROGRESS)) {
-			len = msgs[dev->msg_read_idx].len;
-			buf = msgs[dev->msg_read_idx].buf;
-		} else {
-			len = dev->rx_buf_len;
-			buf = dev->rx_buf;
-		}
-
-		rx_valid = readl(dev->base + DW_IC_RXFLR);
-
-		for (; len > 0 && rx_valid > 0; len--, rx_valid--)
-			*buf++ = readl(dev->base + DW_IC_DATA_CMD);
-
-		if (len > 0) {
-			dev->status |= STATUS_READ_IN_PROGRESS;
-			dev->rx_buf_len = len;
-			dev->rx_buf = buf;
-			return;
-		} else
-			dev->status &= ~STATUS_READ_IN_PROGRESS;
-	}
-}
-
-static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
-{
-	unsigned long abort_source = dev->abort_source;
-	int i;
-
-	if (abort_source & DW_IC_TX_ABRT_NOACK) {
-		for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
-			dev_dbg(dev->dev,
-				"%s: %s\n", __func__, abort_sources[i]);
-		return -EREMOTEIO;
-	}
-
-	for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
-		dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]);
-
-	if (abort_source & DW_IC_TX_ARB_LOST)
-		return -EAGAIN;
-	else if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
-		return -EINVAL; /* wrong msgs[] data */
-	else
-		return -EIO;
-}
-
-/*
- * Prepare controller for a transaction and call i2c_dw_xfer_msg
- */
-static int
-i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
-{
-	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
-	int ret;
-
-	dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
-
-	mutex_lock(&dev->lock);
-
-	INIT_COMPLETION(dev->cmd_complete);
-	dev->msgs = msgs;
-	dev->msgs_num = num;
-	dev->cmd_err = 0;
-	dev->msg_write_idx = 0;
-	dev->msg_read_idx = 0;
-	dev->msg_err = 0;
-	dev->status = STATUS_IDLE;
-	dev->abort_source = 0;
-
-	ret = i2c_dw_wait_bus_not_busy(dev);
-	if (ret < 0)
-		goto done;
-
-	/* start the transfers */
-	i2c_dw_xfer_init(dev);
-
-	/* wait for tx to complete */
-	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ);
-	if (ret == 0) {
-		dev_err(dev->dev, "controller timed out\n");
-		i2c_dw_init(dev);
-		ret = -ETIMEDOUT;
-		goto done;
-	} else if (ret < 0)
-		goto done;
-
-	if (dev->msg_err) {
-		ret = dev->msg_err;
-		goto done;
-	}
-
-	/* no error */
-	if (likely(!dev->cmd_err)) {
-		/* Disable the adapter */
-		writel(0, dev->base + DW_IC_ENABLE);
-		ret = num;
-		goto done;
-	}
-
-	/* We have an error */
-	if (dev->cmd_err == DW_IC_ERR_TX_ABRT) {
-		ret = i2c_dw_handle_tx_abort(dev);
-		goto done;
-	}
-	ret = -EIO;
-
-done:
-	mutex_unlock(&dev->lock);
-
-	return ret;
-}
-
-static u32 i2c_dw_func(struct i2c_adapter *adap)
-{
-	return	I2C_FUNC_I2C |
-		I2C_FUNC_10BIT_ADDR |
-		I2C_FUNC_SMBUS_BYTE |
-		I2C_FUNC_SMBUS_BYTE_DATA |
-		I2C_FUNC_SMBUS_WORD_DATA |
-		I2C_FUNC_SMBUS_I2C_BLOCK;
-}
-
-static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
-{
-	u32 stat;
-
-	/*
-	 * The IC_INTR_STAT register just indicates "enabled" interrupts.
-	 * Ths unmasked raw version of interrupt status bits are available
-	 * in the IC_RAW_INTR_STAT register.
-	 *
-	 * That is,
-	 *   stat = readl(IC_INTR_STAT);
-	 * equals to,
-	 *   stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK);
-	 *
-	 * The raw version might be useful for debugging purposes.
-	 */
-	stat = readl(dev->base + DW_IC_INTR_STAT);
-
-	/*
-	 * Do not use the IC_CLR_INTR register to clear interrupts, or
-	 * you'll miss some interrupts, triggered during the period from
-	 * readl(IC_INTR_STAT) to readl(IC_CLR_INTR).
-	 *
-	 * Instead, use the separately-prepared IC_CLR_* registers.
-	 */
-	if (stat & DW_IC_INTR_RX_UNDER)
-		readl(dev->base + DW_IC_CLR_RX_UNDER);
-	if (stat & DW_IC_INTR_RX_OVER)
-		readl(dev->base + DW_IC_CLR_RX_OVER);
-	if (stat & DW_IC_INTR_TX_OVER)
-		readl(dev->base + DW_IC_CLR_TX_OVER);
-	if (stat & DW_IC_INTR_RD_REQ)
-		readl(dev->base + DW_IC_CLR_RD_REQ);
-	if (stat & DW_IC_INTR_TX_ABRT) {
-		/*
-		 * The IC_TX_ABRT_SOURCE register is cleared whenever
-		 * the IC_CLR_TX_ABRT is read.  Preserve it beforehand.
-		 */
-		dev->abort_source = readl(dev->base + DW_IC_TX_ABRT_SOURCE);
-		readl(dev->base + DW_IC_CLR_TX_ABRT);
-	}
-	if (stat & DW_IC_INTR_RX_DONE)
-		readl(dev->base + DW_IC_CLR_RX_DONE);
-	if (stat & DW_IC_INTR_ACTIVITY)
-		readl(dev->base + DW_IC_CLR_ACTIVITY);
-	if (stat & DW_IC_INTR_STOP_DET)
-		readl(dev->base + DW_IC_CLR_STOP_DET);
-	if (stat & DW_IC_INTR_START_DET)
-		readl(dev->base + DW_IC_CLR_START_DET);
-	if (stat & DW_IC_INTR_GEN_CALL)
-		readl(dev->base + DW_IC_CLR_GEN_CALL);
-
-	return stat;
-}
-
-/*
- * Interrupt service routine. This gets called whenever an I2C interrupt
- * occurs.
- */
-static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
-{
-	struct dw_i2c_dev *dev = dev_id;
-	u32 stat;
-
-	stat = i2c_dw_read_clear_intrbits(dev);
-	dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
-
-	if (stat & DW_IC_INTR_TX_ABRT) {
-		dev->cmd_err |= DW_IC_ERR_TX_ABRT;
-		dev->status = STATUS_IDLE;
-
-		/*
-		 * Anytime TX_ABRT is set, the contents of the tx/rx
-		 * buffers are flushed.  Make sure to skip them.
-		 */
-		writel(0, dev->base + DW_IC_INTR_MASK);
-		goto tx_aborted;
-	}
-
-	if (stat & DW_IC_INTR_RX_FULL)
-		i2c_dw_read(dev);
-
-	if (stat & DW_IC_INTR_TX_EMPTY)
-		i2c_dw_xfer_msg(dev);
-
-	/*
-	 * No need to modify or disable the interrupt mask here.
-	 * i2c_dw_xfer_msg() will take care of it according to
-	 * the current transmit status.
-	 */
-
-tx_aborted:
-	if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
-		complete(&dev->cmd_complete);
-
-	return IRQ_HANDLED;
-}
-
-static struct i2c_algorithm i2c_dw_algo = {
-	.master_xfer	= i2c_dw_xfer,
-	.functionality	= i2c_dw_func,
-};
-
-static int __devinit dw_i2c_probe(struct platform_device *pdev)
-{
-	struct dw_i2c_dev *dev;
-	struct i2c_adapter *adap;
-	struct resource *mem, *ioarea;
-	int irq, r;
-
-	/* NOTE: driver uses the static register mapping */
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem) {
-		dev_err(&pdev->dev, "no mem resource?\n");
-		return -EINVAL;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "no irq resource?\n");
-		return irq; /* -ENXIO */
-	}
-
-	ioarea = request_mem_region(mem->start, resource_size(mem),
-			pdev->name);
-	if (!ioarea) {
-		dev_err(&pdev->dev, "I2C region already claimed\n");
-		return -EBUSY;
-	}
-
-	dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
-	if (!dev) {
-		r = -ENOMEM;
-		goto err_release_region;
-	}
-
-	init_completion(&dev->cmd_complete);
-	mutex_init(&dev->lock);
-	dev->dev = get_device(&pdev->dev);
-	dev->irq = irq;
-	platform_set_drvdata(pdev, dev);
-
-	dev->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(dev->clk)) {
-		r = -ENODEV;
-		goto err_free_mem;
-	}
-	clk_enable(dev->clk);
-
-	dev->base = ioremap(mem->start, resource_size(mem));
-	if (dev->base == NULL) {
-		dev_err(&pdev->dev, "failure mapping io resources\n");
-		r = -EBUSY;
-		goto err_unuse_clocks;
-	}
-	{
-		u32 param1 = readl(dev->base + DW_IC_COMP_PARAM_1);
-
-		dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
-		dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
-	}
-	i2c_dw_init(dev);
-
-	writel(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */
-	r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev);
-	if (r) {
-		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
-		goto err_iounmap;
-	}
-
-	adap = &dev->adapter;
-	i2c_set_adapdata(adap, dev);
-	adap->owner = THIS_MODULE;
-	adap->class = I2C_CLASS_HWMON;
-	strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
-			sizeof(adap->name));
-	adap->algo = &i2c_dw_algo;
-	adap->dev.parent = &pdev->dev;
-
-	adap->nr = pdev->id;
-	r = i2c_add_numbered_adapter(adap);
-	if (r) {
-		dev_err(&pdev->dev, "failure adding adapter\n");
-		goto err_free_irq;
-	}
-
-	return 0;
-
-err_free_irq:
-	free_irq(dev->irq, dev);
-err_iounmap:
-	iounmap(dev->base);
-err_unuse_clocks:
-	clk_disable(dev->clk);
-	clk_put(dev->clk);
-	dev->clk = NULL;
-err_free_mem:
-	platform_set_drvdata(pdev, NULL);
-	put_device(&pdev->dev);
-	kfree(dev);
-err_release_region:
-	release_mem_region(mem->start, resource_size(mem));
-
-	return r;
-}
-
-static int __devexit dw_i2c_remove(struct platform_device *pdev)
-{
-	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
-	struct resource *mem;
-
-	platform_set_drvdata(pdev, NULL);
-	i2c_del_adapter(&dev->adapter);
-	put_device(&pdev->dev);
-
-	clk_disable(dev->clk);
-	clk_put(dev->clk);
-	dev->clk = NULL;
-
-	writel(0, dev->base + DW_IC_ENABLE);
-	free_irq(dev->irq, dev);
-	kfree(dev);
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(mem->start, resource_size(mem));
-	return 0;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:i2c_designware");
-
-static struct platform_driver dw_i2c_driver = {
-	.remove		= __devexit_p(dw_i2c_remove),
-	.driver		= {
-		.name	= "i2c_designware",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init dw_i2c_init_driver(void)
-{
-	return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
-}
-module_init(dw_i2c_init_driver);
-
-static void __exit dw_i2c_exit_driver(void)
-{
-	platform_driver_unregister(&dw_i2c_driver);
-}
-module_exit(dw_i2c_exit_driver);
-
-MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
-MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-designware-core.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-designware-core.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-designware-core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-designware-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,705 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include "i2c-designware-core.h"
+
+/*
+ * Registers offset
+ */
+#define DW_IC_CON		0x0
+#define DW_IC_TAR		0x4
+#define DW_IC_DATA_CMD		0x10
+#define DW_IC_SS_SCL_HCNT	0x14
+#define DW_IC_SS_SCL_LCNT	0x18
+#define DW_IC_FS_SCL_HCNT	0x1c
+#define DW_IC_FS_SCL_LCNT	0x20
+#define DW_IC_INTR_STAT		0x2c
+#define DW_IC_INTR_MASK		0x30
+#define DW_IC_RAW_INTR_STAT	0x34
+#define DW_IC_RX_TL		0x38
+#define DW_IC_TX_TL		0x3c
+#define DW_IC_CLR_INTR		0x40
+#define DW_IC_CLR_RX_UNDER	0x44
+#define DW_IC_CLR_RX_OVER	0x48
+#define DW_IC_CLR_TX_OVER	0x4c
+#define DW_IC_CLR_RD_REQ	0x50
+#define DW_IC_CLR_TX_ABRT	0x54
+#define DW_IC_CLR_RX_DONE	0x58
+#define DW_IC_CLR_ACTIVITY	0x5c
+#define DW_IC_CLR_STOP_DET	0x60
+#define DW_IC_CLR_START_DET	0x64
+#define DW_IC_CLR_GEN_CALL	0x68
+#define DW_IC_ENABLE		0x6c
+#define DW_IC_STATUS		0x70
+#define DW_IC_TXFLR		0x74
+#define DW_IC_RXFLR		0x78
+#define DW_IC_TX_ABRT_SOURCE	0x80
+#define DW_IC_COMP_PARAM_1	0xf4
+#define DW_IC_COMP_TYPE		0xfc
+#define DW_IC_COMP_TYPE_VALUE	0x44570140
+
+#define DW_IC_INTR_RX_UNDER	0x001
+#define DW_IC_INTR_RX_OVER	0x002
+#define DW_IC_INTR_RX_FULL	0x004
+#define DW_IC_INTR_TX_OVER	0x008
+#define DW_IC_INTR_TX_EMPTY	0x010
+#define DW_IC_INTR_RD_REQ	0x020
+#define DW_IC_INTR_TX_ABRT	0x040
+#define DW_IC_INTR_RX_DONE	0x080
+#define DW_IC_INTR_ACTIVITY	0x100
+#define DW_IC_INTR_STOP_DET	0x200
+#define DW_IC_INTR_START_DET	0x400
+#define DW_IC_INTR_GEN_CALL	0x800
+
+#define DW_IC_INTR_DEFAULT_MASK		(DW_IC_INTR_RX_FULL | \
+					 DW_IC_INTR_TX_EMPTY | \
+					 DW_IC_INTR_TX_ABRT | \
+					 DW_IC_INTR_STOP_DET)
+
+#define DW_IC_STATUS_ACTIVITY	0x1
+
+#define DW_IC_ERR_TX_ABRT	0x1
+
+/*
+ * status codes
+ */
+#define STATUS_IDLE			0x0
+#define STATUS_WRITE_IN_PROGRESS	0x1
+#define STATUS_READ_IN_PROGRESS		0x2
+
+#define TIMEOUT			20 /* ms */
+
+/*
+ * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register
+ *
+ * only expected abort codes are listed here
+ * refer to the datasheet for the full list
+ */
+#define ABRT_7B_ADDR_NOACK	0
+#define ABRT_10ADDR1_NOACK	1
+#define ABRT_10ADDR2_NOACK	2
+#define ABRT_TXDATA_NOACK	3
+#define ABRT_GCALL_NOACK	4
+#define ABRT_GCALL_READ		5
+#define ABRT_SBYTE_ACKDET	7
+#define ABRT_SBYTE_NORSTRT	9
+#define ABRT_10B_RD_NORSTRT	10
+#define ABRT_MASTER_DIS		11
+#define ARB_LOST		12
+
+#define DW_IC_TX_ABRT_7B_ADDR_NOACK	(1UL << ABRT_7B_ADDR_NOACK)
+#define DW_IC_TX_ABRT_10ADDR1_NOACK	(1UL << ABRT_10ADDR1_NOACK)
+#define DW_IC_TX_ABRT_10ADDR2_NOACK	(1UL << ABRT_10ADDR2_NOACK)
+#define DW_IC_TX_ABRT_TXDATA_NOACK	(1UL << ABRT_TXDATA_NOACK)
+#define DW_IC_TX_ABRT_GCALL_NOACK	(1UL << ABRT_GCALL_NOACK)
+#define DW_IC_TX_ABRT_GCALL_READ	(1UL << ABRT_GCALL_READ)
+#define DW_IC_TX_ABRT_SBYTE_ACKDET	(1UL << ABRT_SBYTE_ACKDET)
+#define DW_IC_TX_ABRT_SBYTE_NORSTRT	(1UL << ABRT_SBYTE_NORSTRT)
+#define DW_IC_TX_ABRT_10B_RD_NORSTRT	(1UL << ABRT_10B_RD_NORSTRT)
+#define DW_IC_TX_ABRT_MASTER_DIS	(1UL << ABRT_MASTER_DIS)
+#define DW_IC_TX_ARB_LOST		(1UL << ARB_LOST)
+
+#define DW_IC_TX_ABRT_NOACK		(DW_IC_TX_ABRT_7B_ADDR_NOACK | \
+					 DW_IC_TX_ABRT_10ADDR1_NOACK | \
+					 DW_IC_TX_ABRT_10ADDR2_NOACK | \
+					 DW_IC_TX_ABRT_TXDATA_NOACK | \
+					 DW_IC_TX_ABRT_GCALL_NOACK)
+
+static char *abort_sources[] = {
+	[ABRT_7B_ADDR_NOACK] =
+		"slave address not acknowledged (7bit mode)",
+	[ABRT_10ADDR1_NOACK] =
+		"first address byte not acknowledged (10bit mode)",
+	[ABRT_10ADDR2_NOACK] =
+		"second address byte not acknowledged (10bit mode)",
+	[ABRT_TXDATA_NOACK] =
+		"data not acknowledged",
+	[ABRT_GCALL_NOACK] =
+		"no acknowledgement for a general call",
+	[ABRT_GCALL_READ] =
+		"read after general call",
+	[ABRT_SBYTE_ACKDET] =
+		"start byte acknowledged",
+	[ABRT_SBYTE_NORSTRT] =
+		"trying to send start byte when restart is disabled",
+	[ABRT_10B_RD_NORSTRT] =
+		"trying to read when restart is disabled (10bit mode)",
+	[ABRT_MASTER_DIS] =
+		"trying to use disabled adapter",
+	[ARB_LOST] =
+		"lost arbitration",
+};
+
+u32 dw_readl(struct dw_i2c_dev *dev, int offset)
+{
+	u32 value = readl(dev->base + offset);
+
+	if (dev->swab)
+		return swab32(value);
+	else
+		return value;
+}
+
+void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
+{
+	if (dev->swab)
+		b = swab32(b);
+
+	writel(b, dev->base + offset);
+}
+
+static u32
+i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
+{
+	/*
+	 * DesignWare I2C core doesn't seem to have solid strategy to meet
+	 * the tHD;STA timing spec.  Configuring _HCNT based on tHIGH spec
+	 * will result in violation of the tHD;STA spec.
+	 */
+	if (cond)
+		/*
+		 * Conditional expression:
+		 *
+		 *   IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH
+		 *
+		 * This is based on the DW manuals, and represents an ideal
+		 * configuration.  The resulting I2C bus speed will be
+		 * faster than any of the others.
+		 *
+		 * If your hardware is free from tHD;STA issue, try this one.
+		 */
+		return (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset;
+	else
+		/*
+		 * Conditional expression:
+		 *
+		 *   IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf)
+		 *
+		 * This is just experimental rule; the tHD;STA period turned
+		 * out to be proportinal to (_HCNT + 3).  With this setting,
+		 * we could meet both tHIGH and tHD;STA timing specs.
+		 *
+		 * If unsure, you'd better to take this alternative.
+		 *
+		 * The reason why we need to take into account "tf" here,
+		 * is the same as described in i2c_dw_scl_lcnt().
+		 */
+		return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset;
+}
+
+static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
+{
+	/*
+	 * Conditional expression:
+	 *
+	 *   IC_[FS]S_SCL_LCNT + 1 >= IC_CLK * (tLOW + tf)
+	 *
+	 * DW I2C core starts counting the SCL CNTs for the LOW period
+	 * of the SCL clock (tLOW) as soon as it pulls the SCL line.
+	 * In order to meet the tLOW timing spec, we need to take into
+	 * account the fall time of SCL signal (tf).  Default tf value
+	 * should be 0.3 us, for safety.
+	 */
+	return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset;
+}
+
+/**
+ * i2c_dw_init() - initialize the designware i2c master hardware
+ * @dev: device private data
+ *
+ * This functions configures and enables the I2C master.
+ * This function is called during I2C init function, and in case of timeout at
+ * run time.
+ */
+int i2c_dw_init(struct dw_i2c_dev *dev)
+{
+	u32 input_clock_khz;
+	u32 hcnt, lcnt;
+	u32 reg;
+
+	input_clock_khz = dev->get_clk_rate_khz(dev);
+
+	/* Configure register endianess access */
+	reg = dw_readl(dev, DW_IC_COMP_TYPE);
+	if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
+		dev->swab = 1;
+		reg = DW_IC_COMP_TYPE_VALUE;
+	}
+
+	if (reg != DW_IC_COMP_TYPE_VALUE) {
+		dev_err(dev->dev, "Unknown Synopsys component type: "
+			"0x%08x\n", reg);
+		return -ENODEV;
+	}
+
+	/* Disable the adapter */
+	dw_writel(dev, 0, DW_IC_ENABLE);
+
+	/* set standard and fast speed deviders for high/low periods */
+
+	/* Standard-mode */
+	hcnt = i2c_dw_scl_hcnt(input_clock_khz,
+				40,	/* tHD;STA = tHIGH = 4.0 us */
+				3,	/* tf = 0.3 us */
+				0,	/* 0: DW default, 1: Ideal */
+				0);	/* No offset */
+	lcnt = i2c_dw_scl_lcnt(input_clock_khz,
+				47,	/* tLOW = 4.7 us */
+				3,	/* tf = 0.3 us */
+				0);	/* No offset */
+	dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT);
+	dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
+	dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
+
+	/* Fast-mode */
+	hcnt = i2c_dw_scl_hcnt(input_clock_khz,
+				6,	/* tHD;STA = tHIGH = 0.6 us */
+				3,	/* tf = 0.3 us */
+				0,	/* 0: DW default, 1: Ideal */
+				0);	/* No offset */
+	lcnt = i2c_dw_scl_lcnt(input_clock_khz,
+				13,	/* tLOW = 1.3 us */
+				3,	/* tf = 0.3 us */
+				0);	/* No offset */
+	dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT);
+	dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
+	dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
+
+	/* Configure Tx/Rx FIFO threshold levels */
+	dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL);
+	dw_writel(dev, 0, DW_IC_RX_TL);
+
+	/* configure the i2c master */
+	dw_writel(dev, dev->master_cfg , DW_IC_CON);
+	return 0;
+}
+
+/*
+ * Waiting for bus not busy
+ */
+static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
+{
+	int timeout = TIMEOUT;
+
+	while (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
+		if (timeout <= 0) {
+			dev_warn(dev->dev, "timeout waiting for bus ready\n");
+			return -ETIMEDOUT;
+		}
+		timeout--;
+		mdelay(1);
+	}
+
+	return 0;
+}
+
+static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
+{
+	struct i2c_msg *msgs = dev->msgs;
+	u32 ic_con;
+
+	/* Disable the adapter */
+	dw_writel(dev, 0, DW_IC_ENABLE);
+
+	/* set the slave (target) address */
+	dw_writel(dev, msgs[dev->msg_write_idx].addr, DW_IC_TAR);
+
+	/* if the slave address is ten bit address, enable 10BITADDR */
+	ic_con = dw_readl(dev, DW_IC_CON);
+	if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
+		ic_con |= DW_IC_CON_10BITADDR_MASTER;
+	else
+		ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
+	dw_writel(dev, ic_con, DW_IC_CON);
+
+	/* Enable the adapter */
+	dw_writel(dev, 1, DW_IC_ENABLE);
+
+	/* Enable interrupts */
+	dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK);
+}
+
+/*
+ * Initiate (and continue) low level master read/write transaction.
+ * This function is only called from i2c_dw_isr, and pumping i2c_msg
+ * messages into the tx buffer.  Even if the size of i2c_msg data is
+ * longer than the size of the tx buffer, it handles everything.
+ */
+void
+i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
+{
+	struct i2c_msg *msgs = dev->msgs;
+	u32 intr_mask;
+	int tx_limit, rx_limit;
+	u32 addr = msgs[dev->msg_write_idx].addr;
+	u32 buf_len = dev->tx_buf_len;
+	u8 *buf = dev->tx_buf;
+
+	intr_mask = DW_IC_INTR_DEFAULT_MASK;
+
+	for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) {
+		/*
+		 * if target address has changed, we need to
+		 * reprogram the target address in the i2c
+		 * adapter when we are done with this transfer
+		 */
+		if (msgs[dev->msg_write_idx].addr != addr) {
+			dev_err(dev->dev,
+				"%s: invalid target address\n", __func__);
+			dev->msg_err = -EINVAL;
+			break;
+		}
+
+		if (msgs[dev->msg_write_idx].len == 0) {
+			dev_err(dev->dev,
+				"%s: invalid message length\n", __func__);
+			dev->msg_err = -EINVAL;
+			break;
+		}
+
+		if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) {
+			/* new i2c_msg */
+			buf = msgs[dev->msg_write_idx].buf;
+			buf_len = msgs[dev->msg_write_idx].len;
+		}
+
+		tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR);
+		rx_limit = dev->rx_fifo_depth - dw_readl(dev, DW_IC_RXFLR);
+
+		while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
+			if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
+				dw_writel(dev, 0x100, DW_IC_DATA_CMD);
+				rx_limit--;
+			} else
+				dw_writel(dev, *buf++, DW_IC_DATA_CMD);
+			tx_limit--; buf_len--;
+		}
+
+		dev->tx_buf = buf;
+		dev->tx_buf_len = buf_len;
+
+		if (buf_len > 0) {
+			/* more bytes to be written */
+			dev->status |= STATUS_WRITE_IN_PROGRESS;
+			break;
+		} else
+			dev->status &= ~STATUS_WRITE_IN_PROGRESS;
+	}
+
+	/*
+	 * If i2c_msg index search is completed, we don't need TX_EMPTY
+	 * interrupt any more.
+	 */
+	if (dev->msg_write_idx == dev->msgs_num)
+		intr_mask &= ~DW_IC_INTR_TX_EMPTY;
+
+	if (dev->msg_err)
+		intr_mask = 0;
+
+	dw_writel(dev, intr_mask,  DW_IC_INTR_MASK);
+}
+
+static void
+i2c_dw_read(struct dw_i2c_dev *dev)
+{
+	struct i2c_msg *msgs = dev->msgs;
+	int rx_valid;
+
+	for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) {
+		u32 len;
+		u8 *buf;
+
+		if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD))
+			continue;
+
+		if (!(dev->status & STATUS_READ_IN_PROGRESS)) {
+			len = msgs[dev->msg_read_idx].len;
+			buf = msgs[dev->msg_read_idx].buf;
+		} else {
+			len = dev->rx_buf_len;
+			buf = dev->rx_buf;
+		}
+
+		rx_valid = dw_readl(dev, DW_IC_RXFLR);
+
+		for (; len > 0 && rx_valid > 0; len--, rx_valid--)
+			*buf++ = dw_readl(dev, DW_IC_DATA_CMD);
+
+		if (len > 0) {
+			dev->status |= STATUS_READ_IN_PROGRESS;
+			dev->rx_buf_len = len;
+			dev->rx_buf = buf;
+			return;
+		} else
+			dev->status &= ~STATUS_READ_IN_PROGRESS;
+	}
+}
+
+static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
+{
+	unsigned long abort_source = dev->abort_source;
+	int i;
+
+	if (abort_source & DW_IC_TX_ABRT_NOACK) {
+		for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
+			dev_dbg(dev->dev,
+				"%s: %s\n", __func__, abort_sources[i]);
+		return -EREMOTEIO;
+	}
+
+	for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
+		dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]);
+
+	if (abort_source & DW_IC_TX_ARB_LOST)
+		return -EAGAIN;
+	else if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
+		return -EINVAL; /* wrong msgs[] data */
+	else
+		return -EIO;
+}
+
+/*
+ * Prepare controller for a transaction and call i2c_dw_xfer_msg
+ */
+int
+i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
+	int ret;
+
+	dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
+
+	mutex_lock(&dev->lock);
+	pm_runtime_get_sync(dev->dev);
+
+	INIT_COMPLETION(dev->cmd_complete);
+	dev->msgs = msgs;
+	dev->msgs_num = num;
+	dev->cmd_err = 0;
+	dev->msg_write_idx = 0;
+	dev->msg_read_idx = 0;
+	dev->msg_err = 0;
+	dev->status = STATUS_IDLE;
+	dev->abort_source = 0;
+
+	ret = i2c_dw_wait_bus_not_busy(dev);
+	if (ret < 0)
+		goto done;
+
+	/* start the transfers */
+	i2c_dw_xfer_init(dev);
+
+	/* wait for tx to complete */
+	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ);
+	if (ret == 0) {
+		dev_err(dev->dev, "controller timed out\n");
+		i2c_dw_init(dev);
+		ret = -ETIMEDOUT;
+		goto done;
+	} else if (ret < 0)
+		goto done;
+
+	if (dev->msg_err) {
+		ret = dev->msg_err;
+		goto done;
+	}
+
+	/* no error */
+	if (likely(!dev->cmd_err)) {
+		/* Disable the adapter */
+		dw_writel(dev, 0, DW_IC_ENABLE);
+		ret = num;
+		goto done;
+	}
+
+	/* We have an error */
+	if (dev->cmd_err == DW_IC_ERR_TX_ABRT) {
+		ret = i2c_dw_handle_tx_abort(dev);
+		goto done;
+	}
+	ret = -EIO;
+
+done:
+	pm_runtime_put(dev->dev);
+	mutex_unlock(&dev->lock);
+
+	return ret;
+}
+
+u32 i2c_dw_func(struct i2c_adapter *adap)
+{
+	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
+	return dev->functionality;
+}
+
+static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
+{
+	u32 stat;
+
+	/*
+	 * The IC_INTR_STAT register just indicates "enabled" interrupts.
+	 * Ths unmasked raw version of interrupt status bits are available
+	 * in the IC_RAW_INTR_STAT register.
+	 *
+	 * That is,
+	 *   stat = dw_readl(IC_INTR_STAT);
+	 * equals to,
+	 *   stat = dw_readl(IC_RAW_INTR_STAT) & dw_readl(IC_INTR_MASK);
+	 *
+	 * The raw version might be useful for debugging purposes.
+	 */
+	stat = dw_readl(dev, DW_IC_INTR_STAT);
+
+	/*
+	 * Do not use the IC_CLR_INTR register to clear interrupts, or
+	 * you'll miss some interrupts, triggered during the period from
+	 * dw_readl(IC_INTR_STAT) to dw_readl(IC_CLR_INTR).
+	 *
+	 * Instead, use the separately-prepared IC_CLR_* registers.
+	 */
+	if (stat & DW_IC_INTR_RX_UNDER)
+		dw_readl(dev, DW_IC_CLR_RX_UNDER);
+	if (stat & DW_IC_INTR_RX_OVER)
+		dw_readl(dev, DW_IC_CLR_RX_OVER);
+	if (stat & DW_IC_INTR_TX_OVER)
+		dw_readl(dev, DW_IC_CLR_TX_OVER);
+	if (stat & DW_IC_INTR_RD_REQ)
+		dw_readl(dev, DW_IC_CLR_RD_REQ);
+	if (stat & DW_IC_INTR_TX_ABRT) {
+		/*
+		 * The IC_TX_ABRT_SOURCE register is cleared whenever
+		 * the IC_CLR_TX_ABRT is read.  Preserve it beforehand.
+		 */
+		dev->abort_source = dw_readl(dev, DW_IC_TX_ABRT_SOURCE);
+		dw_readl(dev, DW_IC_CLR_TX_ABRT);
+	}
+	if (stat & DW_IC_INTR_RX_DONE)
+		dw_readl(dev, DW_IC_CLR_RX_DONE);
+	if (stat & DW_IC_INTR_ACTIVITY)
+		dw_readl(dev, DW_IC_CLR_ACTIVITY);
+	if (stat & DW_IC_INTR_STOP_DET)
+		dw_readl(dev, DW_IC_CLR_STOP_DET);
+	if (stat & DW_IC_INTR_START_DET)
+		dw_readl(dev, DW_IC_CLR_START_DET);
+	if (stat & DW_IC_INTR_GEN_CALL)
+		dw_readl(dev, DW_IC_CLR_GEN_CALL);
+
+	return stat;
+}
+
+/*
+ * Interrupt service routine. This gets called whenever an I2C interrupt
+ * occurs.
+ */
+irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
+{
+	struct dw_i2c_dev *dev = dev_id;
+	u32 stat, enabled;
+
+	enabled = dw_readl(dev, DW_IC_ENABLE);
+	stat = dw_readl(dev, DW_IC_RAW_INTR_STAT);
+	dev_dbg(dev->dev, "%s:  %s enabled= 0x%x stat=0x%x\n", __func__,
+		dev->adapter.name, enabled, stat);
+	if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY))
+		return IRQ_NONE;
+
+	stat = i2c_dw_read_clear_intrbits(dev);
+
+	if (stat & DW_IC_INTR_TX_ABRT) {
+		dev->cmd_err |= DW_IC_ERR_TX_ABRT;
+		dev->status = STATUS_IDLE;
+
+		/*
+		 * Anytime TX_ABRT is set, the contents of the tx/rx
+		 * buffers are flushed.  Make sure to skip them.
+		 */
+		dw_writel(dev, 0, DW_IC_INTR_MASK);
+		goto tx_aborted;
+	}
+
+	if (stat & DW_IC_INTR_RX_FULL)
+		i2c_dw_read(dev);
+
+	if (stat & DW_IC_INTR_TX_EMPTY)
+		i2c_dw_xfer_msg(dev);
+
+	/*
+	 * No need to modify or disable the interrupt mask here.
+	 * i2c_dw_xfer_msg() will take care of it according to
+	 * the current transmit status.
+	 */
+
+tx_aborted:
+	if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
+		complete(&dev->cmd_complete);
+
+	return IRQ_HANDLED;
+}
+
+void i2c_dw_enable(struct dw_i2c_dev *dev)
+{
+       /* Enable the adapter */
+	dw_writel(dev, 1, DW_IC_ENABLE);
+}
+
+u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev)
+{
+	return dw_readl(dev, DW_IC_ENABLE);
+}
+
+void i2c_dw_disable(struct dw_i2c_dev *dev)
+{
+	/* Disable controller */
+	dw_writel(dev, 0, DW_IC_ENABLE);
+
+	/* Disable all interupts */
+	dw_writel(dev, 0, DW_IC_INTR_MASK);
+	dw_readl(dev, DW_IC_CLR_INTR);
+}
+
+void i2c_dw_clear_int(struct dw_i2c_dev *dev)
+{
+	dw_readl(dev, DW_IC_CLR_INTR);
+}
+
+void i2c_dw_disable_int(struct dw_i2c_dev *dev)
+{
+	dw_writel(dev, 0, DW_IC_INTR_MASK);
+}
+
+u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
+{
+	return dw_readl(dev, DW_IC_COMP_PARAM_1);
+}
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-designware-core.h linux-libre-3.2-gnu/drivers/i2c/busses/i2c-designware-core.h
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-designware-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-designware-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,105 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+
+#define DW_IC_CON_MASTER		0x1
+#define DW_IC_CON_SPEED_STD		0x2
+#define DW_IC_CON_SPEED_FAST		0x4
+#define DW_IC_CON_10BITADDR_MASTER	0x10
+#define DW_IC_CON_RESTART_EN		0x20
+#define DW_IC_CON_SLAVE_DISABLE		0x40
+
+
+/**
+ * struct dw_i2c_dev - private i2c-designware data
+ * @dev: driver model device node
+ * @base: IO registers pointer
+ * @cmd_complete: tx completion indicator
+ * @lock: protect this struct and IO registers
+ * @clk: input reference clock
+ * @cmd_err: run time hadware error code
+ * @msgs: points to an array of messages currently being transfered
+ * @msgs_num: the number of elements in msgs
+ * @msg_write_idx: the element index of the current tx message in the msgs
+ *	array
+ * @tx_buf_len: the length of the current tx buffer
+ * @tx_buf: the current tx buffer
+ * @msg_read_idx: the element index of the current rx message in the msgs
+ *	array
+ * @rx_buf_len: the length of the current rx buffer
+ * @rx_buf: the current rx buffer
+ * @msg_err: error status of the current transfer
+ * @status: i2c master status, one of STATUS_*
+ * @abort_source: copy of the TX_ABRT_SOURCE register
+ * @irq: interrupt number for the i2c master
+ * @adapter: i2c subsystem adapter node
+ * @tx_fifo_depth: depth of the hardware tx fifo
+ * @rx_fifo_depth: depth of the hardware rx fifo
+ */
+struct dw_i2c_dev {
+	struct device		*dev;
+	void __iomem		*base;
+	struct completion	cmd_complete;
+	struct mutex		lock;
+	struct clk		*clk;
+	u32			(*get_clk_rate_khz) (struct dw_i2c_dev *dev);
+	struct dw_pci_controller *controller;
+	int			cmd_err;
+	struct i2c_msg		*msgs;
+	int			msgs_num;
+	int			msg_write_idx;
+	u32			tx_buf_len;
+	u8			*tx_buf;
+	int			msg_read_idx;
+	u32			rx_buf_len;
+	u8			*rx_buf;
+	int			msg_err;
+	unsigned int		status;
+	u32			abort_source;
+	int			irq;
+	int			swab;
+	struct i2c_adapter	adapter;
+	u32			functionality;
+	u32			master_cfg;
+	unsigned int		tx_fifo_depth;
+	unsigned int		rx_fifo_depth;
+};
+
+extern u32 dw_readl(struct dw_i2c_dev *dev, int offset);
+extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
+extern int i2c_dw_init(struct dw_i2c_dev *dev);
+extern int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+		int num);
+extern u32 i2c_dw_func(struct i2c_adapter *adap);
+extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id);
+extern void i2c_dw_enable(struct dw_i2c_dev *dev);
+extern u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev);
+extern void i2c_dw_disable(struct dw_i2c_dev *dev);
+extern void i2c_dw_clear_int(struct dw_i2c_dev *dev);
+extern void i2c_dw_disable_int(struct dw_i2c_dev *dev);
+extern u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev);
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-designware-pcidrv.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-designware-pcidrv.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-designware-pcidrv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-designware-pcidrv.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,392 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/pm_runtime.h>
+#include "i2c-designware-core.h"
+
+#define DRIVER_NAME "i2c-designware-pci"
+
+enum dw_pci_ctl_id_t {
+	moorestown_0,
+	moorestown_1,
+	moorestown_2,
+
+	medfield_0,
+	medfield_1,
+	medfield_2,
+	medfield_3,
+	medfield_4,
+	medfield_5,
+};
+
+struct dw_pci_controller {
+	u32 bus_num;
+	u32 bus_cfg;
+	u32 tx_fifo_depth;
+	u32 rx_fifo_depth;
+	u32 clk_khz;
+};
+
+#define INTEL_MID_STD_CFG  (DW_IC_CON_MASTER |			\
+				DW_IC_CON_SLAVE_DISABLE |	\
+				DW_IC_CON_RESTART_EN)
+
+static struct  dw_pci_controller  dw_pci_controllers[] = {
+	[moorestown_0] = {
+		.bus_num     = 0,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[moorestown_1] = {
+		.bus_num     = 1,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[moorestown_2] = {
+		.bus_num     = 2,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_0] = {
+		.bus_num     = 0,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_1] = {
+		.bus_num     = 1,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_2] = {
+		.bus_num     = 2,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_3] = {
+		.bus_num     = 3,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_STD,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_4] = {
+		.bus_num     = 4,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_5] = {
+		.bus_num     = 5,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+};
+static struct i2c_algorithm i2c_dw_algo = {
+	.master_xfer	= i2c_dw_xfer,
+	.functionality	= i2c_dw_func,
+};
+
+static int i2c_dw_pci_suspend(struct device *dev)
+{
+	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+	struct dw_i2c_dev *i2c = pci_get_drvdata(pdev);
+	int err;
+
+
+	i2c_dw_disable(i2c);
+
+	err = pci_save_state(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "pci_save_state failed\n");
+		return err;
+	}
+
+	err = pci_set_power_state(pdev, PCI_D3hot);
+	if (err) {
+		dev_err(&pdev->dev, "pci_set_power_state failed\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int i2c_dw_pci_resume(struct device *dev)
+{
+	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+	struct dw_i2c_dev *i2c = pci_get_drvdata(pdev);
+	int err;
+	u32 enabled;
+
+	enabled = i2c_dw_is_enabled(i2c);
+	if (enabled)
+		return 0;
+
+	err = pci_set_power_state(pdev, PCI_D0);
+	if (err) {
+		dev_err(&pdev->dev, "pci_set_power_state() failed\n");
+		return err;
+	}
+
+	pci_restore_state(pdev);
+
+	i2c_dw_init(i2c);
+	i2c_dw_enable(i2c);
+	return 0;
+}
+
+static int i2c_dw_pci_runtime_idle(struct device *dev)
+{
+	int err = pm_schedule_suspend(dev, 500);
+	dev_dbg(dev, "runtime_idle called\n");
+
+	if (err != 0)
+		return 0;
+	return -EBUSY;
+}
+
+static const struct dev_pm_ops i2c_dw_pm_ops = {
+	.resume         = i2c_dw_pci_resume,
+	.suspend        = i2c_dw_pci_suspend,
+	SET_RUNTIME_PM_OPS(i2c_dw_pci_suspend, i2c_dw_pci_resume,
+			   i2c_dw_pci_runtime_idle)
+};
+
+static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
+{
+	return dev->controller->clk_khz;
+}
+
+static int __devinit i2c_dw_pci_probe(struct pci_dev *pdev,
+const struct pci_device_id *id)
+{
+	struct dw_i2c_dev *dev;
+	struct i2c_adapter *adap;
+	unsigned long start, len;
+	void __iomem *base;
+	int r;
+	struct  dw_pci_controller *controller;
+
+	if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) {
+		printk(KERN_ERR "dw_i2c_pci_probe: invalid driver data %ld\n",
+			id->driver_data);
+		return -EINVAL;
+	}
+
+	controller = &dw_pci_controllers[id->driver_data];
+
+	r = pci_enable_device(pdev);
+	if (r) {
+		dev_err(&pdev->dev, "Failed to enable I2C PCI device (%d)\n",
+			r);
+		goto exit;
+	}
+
+	/* Determine the address of the I2C area */
+	start = pci_resource_start(pdev, 0);
+	len = pci_resource_len(pdev, 0);
+	if (!start || len == 0) {
+		dev_err(&pdev->dev, "base address not set\n");
+		r = -ENODEV;
+		goto exit;
+	}
+
+	r = pci_request_region(pdev, 0, DRIVER_NAME);
+	if (r) {
+		dev_err(&pdev->dev, "failed to request I2C region "
+			"0x%lx-0x%lx\n", start,
+			(unsigned long)pci_resource_end(pdev, 0));
+		goto exit;
+	}
+
+	base = ioremap_nocache(start, len);
+	if (!base) {
+		dev_err(&pdev->dev, "I/O memory remapping failed\n");
+		r = -ENOMEM;
+		goto err_release_region;
+	}
+
+
+	dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
+	if (!dev) {
+		r = -ENOMEM;
+		goto err_release_region;
+	}
+
+	init_completion(&dev->cmd_complete);
+	mutex_init(&dev->lock);
+	dev->clk = NULL;
+	dev->controller = controller;
+	dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
+	dev->base = base;
+	dev->dev = get_device(&pdev->dev);
+	dev->functionality =
+		I2C_FUNC_I2C |
+		I2C_FUNC_SMBUS_BYTE |
+		I2C_FUNC_SMBUS_BYTE_DATA |
+		I2C_FUNC_SMBUS_WORD_DATA |
+		I2C_FUNC_SMBUS_I2C_BLOCK;
+	dev->master_cfg =  controller->bus_cfg;
+
+	pci_set_drvdata(pdev, dev);
+
+	dev->tx_fifo_depth = controller->tx_fifo_depth;
+	dev->rx_fifo_depth = controller->rx_fifo_depth;
+	r = i2c_dw_init(dev);
+	if (r)
+		goto err_iounmap;
+
+	adap = &dev->adapter;
+	i2c_set_adapdata(adap, dev);
+	adap->owner = THIS_MODULE;
+	adap->class = 0;
+	adap->algo = &i2c_dw_algo;
+	adap->dev.parent = &pdev->dev;
+	adap->nr = controller->bus_num;
+	snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci-%d",
+		adap->nr);
+
+	r = request_irq(pdev->irq, i2c_dw_isr, IRQF_SHARED, adap->name, dev);
+	if (r) {
+		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
+		goto err_iounmap;
+	}
+
+	i2c_dw_disable_int(dev);
+	i2c_dw_clear_int(dev);
+	r = i2c_add_numbered_adapter(adap);
+	if (r) {
+		dev_err(&pdev->dev, "failure adding adapter\n");
+		goto err_free_irq;
+	}
+
+	pm_runtime_put_noidle(&pdev->dev);
+	pm_runtime_allow(&pdev->dev);
+
+	return 0;
+
+err_free_irq:
+	free_irq(pdev->irq, dev);
+err_iounmap:
+	iounmap(dev->base);
+	pci_set_drvdata(pdev, NULL);
+	put_device(&pdev->dev);
+	kfree(dev);
+err_release_region:
+	pci_release_region(pdev, 0);
+exit:
+	return r;
+}
+
+static void __devexit i2c_dw_pci_remove(struct pci_dev *pdev)
+{
+	struct dw_i2c_dev *dev = pci_get_drvdata(pdev);
+
+	i2c_dw_disable(dev);
+	pm_runtime_forbid(&pdev->dev);
+	pm_runtime_get_noresume(&pdev->dev);
+
+	pci_set_drvdata(pdev, NULL);
+	i2c_del_adapter(&dev->adapter);
+	put_device(&pdev->dev);
+
+	free_irq(dev->irq, dev);
+	kfree(dev);
+	pci_release_region(pdev, 0);
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("i2c_designware-pci");
+
+DEFINE_PCI_DEVICE_TABLE(i2_designware_pci_ids) = {
+	/* Moorestown */
+	{ PCI_VDEVICE(INTEL, 0x0802), moorestown_0 },
+	{ PCI_VDEVICE(INTEL, 0x0803), moorestown_1 },
+	{ PCI_VDEVICE(INTEL, 0x0804), moorestown_2 },
+	/* Medfield */
+	{ PCI_VDEVICE(INTEL, 0x0817), medfield_3,},
+	{ PCI_VDEVICE(INTEL, 0x0818), medfield_4 },
+	{ PCI_VDEVICE(INTEL, 0x0819), medfield_5 },
+	{ PCI_VDEVICE(INTEL, 0x082C), medfield_0 },
+	{ PCI_VDEVICE(INTEL, 0x082D), medfield_1 },
+	{ PCI_VDEVICE(INTEL, 0x082E), medfield_2 },
+	{ 0,}
+};
+MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids);
+
+static struct pci_driver dw_i2c_driver = {
+	.name		= DRIVER_NAME,
+	.id_table	= i2_designware_pci_ids,
+	.probe		= i2c_dw_pci_probe,
+	.remove		= __devexit_p(i2c_dw_pci_remove),
+	.driver         = {
+		.pm     = &i2c_dw_pm_ops,
+	},
+};
+
+static int __init dw_i2c_init_driver(void)
+{
+	return  pci_register_driver(&dw_i2c_driver);
+}
+module_init(dw_i2c_init_driver);
+
+static void __exit dw_i2c_exit_driver(void)
+{
+	pci_unregister_driver(&dw_i2c_driver);
+}
+module_exit(dw_i2c_exit_driver);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("Synopsys DesignWare PCI I2C bus adapter");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-designware-platdrv.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-designware-platdrv.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-designware-platdrv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-designware-platdrv.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,215 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include "i2c-designware-core.h"
+
+static struct i2c_algorithm i2c_dw_algo = {
+	.master_xfer	= i2c_dw_xfer,
+	.functionality	= i2c_dw_func,
+};
+static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
+{
+	return clk_get_rate(dev->clk)/1000;
+}
+
+static int __devinit dw_i2c_probe(struct platform_device *pdev)
+{
+	struct dw_i2c_dev *dev;
+	struct i2c_adapter *adap;
+	struct resource *mem, *ioarea;
+	int irq, r;
+
+	/* NOTE: driver uses the static register mapping */
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "no mem resource?\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no irq resource?\n");
+		return irq; /* -ENXIO */
+	}
+
+	ioarea = request_mem_region(mem->start, resource_size(mem),
+			pdev->name);
+	if (!ioarea) {
+		dev_err(&pdev->dev, "I2C region already claimed\n");
+		return -EBUSY;
+	}
+
+	dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
+	if (!dev) {
+		r = -ENOMEM;
+		goto err_release_region;
+	}
+
+	init_completion(&dev->cmd_complete);
+	mutex_init(&dev->lock);
+	dev->dev = get_device(&pdev->dev);
+	dev->irq = irq;
+	platform_set_drvdata(pdev, dev);
+
+	dev->clk = clk_get(&pdev->dev, NULL);
+	dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
+
+	if (IS_ERR(dev->clk)) {
+		r = -ENODEV;
+		goto err_free_mem;
+	}
+	clk_enable(dev->clk);
+
+	dev->functionality =
+		I2C_FUNC_I2C |
+		I2C_FUNC_10BIT_ADDR |
+		I2C_FUNC_SMBUS_BYTE |
+		I2C_FUNC_SMBUS_BYTE_DATA |
+		I2C_FUNC_SMBUS_WORD_DATA |
+		I2C_FUNC_SMBUS_I2C_BLOCK;
+	dev->master_cfg =  DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
+		DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
+
+	dev->base = ioremap(mem->start, resource_size(mem));
+	if (dev->base == NULL) {
+		dev_err(&pdev->dev, "failure mapping io resources\n");
+		r = -EBUSY;
+		goto err_unuse_clocks;
+	}
+	{
+		u32 param1 = i2c_dw_read_comp_param(dev);
+
+		dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
+		dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
+	}
+	r = i2c_dw_init(dev);
+	if (r)
+		goto err_iounmap;
+
+	i2c_dw_disable_int(dev);
+	r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev);
+	if (r) {
+		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
+		goto err_iounmap;
+	}
+
+	adap = &dev->adapter;
+	i2c_set_adapdata(adap, dev);
+	adap->owner = THIS_MODULE;
+	adap->class = I2C_CLASS_HWMON;
+	strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
+			sizeof(adap->name));
+	adap->algo = &i2c_dw_algo;
+	adap->dev.parent = &pdev->dev;
+
+	adap->nr = pdev->id;
+	r = i2c_add_numbered_adapter(adap);
+	if (r) {
+		dev_err(&pdev->dev, "failure adding adapter\n");
+		goto err_free_irq;
+	}
+
+	return 0;
+
+err_free_irq:
+	free_irq(dev->irq, dev);
+err_iounmap:
+	iounmap(dev->base);
+err_unuse_clocks:
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
+	dev->clk = NULL;
+err_free_mem:
+	platform_set_drvdata(pdev, NULL);
+	put_device(&pdev->dev);
+	kfree(dev);
+err_release_region:
+	release_mem_region(mem->start, resource_size(mem));
+
+	return r;
+}
+
+static int __devexit dw_i2c_remove(struct platform_device *pdev)
+{
+	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+	struct resource *mem;
+
+	platform_set_drvdata(pdev, NULL);
+	i2c_del_adapter(&dev->adapter);
+	put_device(&pdev->dev);
+
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
+	dev->clk = NULL;
+
+	i2c_dw_disable(dev);
+	free_irq(dev->irq, dev);
+	kfree(dev);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+	return 0;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:i2c_designware");
+
+static struct platform_driver dw_i2c_driver = {
+	.remove		= __devexit_p(dw_i2c_remove),
+	.driver		= {
+		.name	= "i2c_designware",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init dw_i2c_init_driver(void)
+{
+	return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
+}
+module_init(dw_i2c_init_driver);
+
+static void __exit dw_i2c_exit_driver(void)
+{
+	platform_driver_unregister(&dw_i2c_driver);
+}
+module_exit(dw_i2c_exit_driver);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-eg20t.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-eg20t.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-eg20t.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-eg20t.c	2012-01-04 18:55:44.000000000 -0500
@@ -64,6 +64,7 @@
 #define TEN_BIT_ADDR_DEFAULT	0xF000
 #define TEN_BIT_ADDR_MASK	0xF0
 #define PCH_START		0x0020
+#define PCH_RESTART		0x0004
 #define PCH_ESR_START		0x0001
 #define PCH_BUFF_START		0x1
 #define PCH_REPSTART		0x0004
@@ -273,23 +274,24 @@
 				     s32 timeout)
 {
 	void __iomem *p = adap->pch_base_address;
+	ktime_t ns_val;
+
+	if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
+		return 0;
 
 	/* MAX timeout value is timeout*1000*1000nsec */
-	ktime_t ns_val = ktime_add_ns(ktime_get(), timeout*1000*1000);
+	ns_val = ktime_add_ns(ktime_get(), timeout*1000*1000);
 	do {
-		if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
-			break;
 		msleep(20);
+		if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
+			return 0;
 	} while (ktime_lt(ktime_get(), ns_val));
 
 	pch_dbg(adap, "I2CSR = %x\n", ioread32(p + PCH_I2CSR));
+	pch_err(adap, "%s: Timeout Error.return%d\n", __func__, -ETIME);
+	pch_i2c_init(adap);
 
-	if (timeout == 0) {
-		pch_err(adap, "%s: Timeout Error.return%d\n", __func__, -ETIME);
-		return -ETIME;
-	}
-
-	return 0;
+	return -ETIME;
 }
 
 /**
@@ -311,21 +313,19 @@
  */
 static s32 pch_i2c_wait_for_xfer_complete(struct i2c_algo_pch_data *adap)
 {
-	s32 ret;
+	long ret;
 	ret = wait_event_timeout(pch_event,
 			(adap->pch_event_flag != 0), msecs_to_jiffies(50));
-	if (ret < 0) {
-		pch_err(adap, "timeout: %x\n", adap->pch_event_flag);
-		return ret;
-	}
 
 	if (ret == 0) {
 		pch_err(adap, "timeout: %x\n", adap->pch_event_flag);
+		adap->pch_event_flag = 0;
 		return -ETIMEDOUT;
 	}
 
 	if (adap->pch_event_flag & I2C_ERROR_MASK) {
 		pch_err(adap, "error bits set: %x\n", adap->pch_event_flag);
+		adap->pch_event_flag = 0;
 		return -EIO;
 	}
 
@@ -394,6 +394,7 @@
 	u32 addr_2_msb;
 	u32 addr_8_lsb;
 	s32 wrcount;
+	s32 rtn;
 	void __iomem *p = adap->pch_base_address;
 
 	length = msgs->len;
@@ -412,15 +413,29 @@
 	}
 
 	if (msgs->flags & I2C_M_TEN) {
-		addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7);
+		addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7) & 0x06;
 		iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
 		if (first)
 			pch_i2c_start(adap);
-		if (pch_i2c_wait_for_xfer_complete(adap) == 0 &&
-		    pch_i2c_getack(adap) == 0) {
+
+		rtn = pch_i2c_wait_for_xfer_complete(adap);
+		if (rtn == 0) {
+			if (pch_i2c_getack(adap)) {
+				pch_dbg(adap, "Receive NACK for slave address"
+					"setting\n");
+				return -EIO;
+			}
 			addr_8_lsb = (addr & I2C_ADDR_MSK);
 			iowrite32(addr_8_lsb, p + PCH_I2CDR);
-		} else {
+		} else if (rtn == -EIO) { /* Arbitration Lost */
+			pch_err(adap, "Lost Arbitration\n");
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMAL_BIT);
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMIF_BIT);
+			pch_i2c_init(adap);
+			return -EAGAIN;
+		} else { /* wait-event timeout */
 			pch_i2c_stop(adap);
 			return -ETIME;
 		}
@@ -431,30 +446,51 @@
 			pch_i2c_start(adap);
 	}
 
-	if ((pch_i2c_wait_for_xfer_complete(adap) == 0) &&
-	    (pch_i2c_getack(adap) == 0)) {
-		for (wrcount = 0; wrcount < length; ++wrcount) {
-			/* write buffer value to I2C data register */
-			iowrite32(buf[wrcount], p + PCH_I2CDR);
-			pch_dbg(adap, "writing %x to Data register\n",
-				buf[wrcount]);
+	rtn = pch_i2c_wait_for_xfer_complete(adap);
+	if (rtn == 0) {
+		if (pch_i2c_getack(adap)) {
+			pch_dbg(adap, "Receive NACK for slave address"
+				"setting\n");
+			return -EIO;
+		}
+	} else if (rtn == -EIO) { /* Arbitration Lost */
+		pch_err(adap, "Lost Arbitration\n");
+		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
+		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
+		pch_i2c_init(adap);
+		return -EAGAIN;
+	} else { /* wait-event timeout */
+		pch_i2c_stop(adap);
+		return -ETIME;
+	}
 
-			if (pch_i2c_wait_for_xfer_complete(adap) != 0)
-				return -ETIME;
+	for (wrcount = 0; wrcount < length; ++wrcount) {
+		/* write buffer value to I2C data register */
+		iowrite32(buf[wrcount], p + PCH_I2CDR);
+		pch_dbg(adap, "writing %x to Data register\n", buf[wrcount]);
 
-			if (pch_i2c_getack(adap))
+		rtn = pch_i2c_wait_for_xfer_complete(adap);
+		if (rtn == 0) {
+			if (pch_i2c_getack(adap)) {
+				pch_dbg(adap, "Receive NACK for slave address"
+					"setting\n");
 				return -EIO;
+			}
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMCF_BIT);
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMIF_BIT);
+		} else { /* wait-event timeout */
+			pch_i2c_stop(adap);
+			return -ETIME;
 		}
+	}
 
-		/* check if this is the last message */
-		if (last)
-			pch_i2c_stop(adap);
-		else
-			pch_i2c_repstart(adap);
-	} else {
+	/* check if this is the last message */
+	if (last)
 		pch_i2c_stop(adap);
-		return -EIO;
-	}
+	else
+		pch_i2c_repstart(adap);
 
 	pch_dbg(adap, "return=%d\n", wrcount);
 
@@ -484,6 +520,19 @@
 }
 
 /**
+ * pch_i2c_restart() - Generate I2C restart condition in normal mode.
+ * @adap:	Pointer to struct i2c_algo_pch_data.
+ *
+ * Generate I2C restart condition in normal mode by setting I2CCTL.I2CRSTA.
+ */
+static void pch_i2c_restart(struct i2c_algo_pch_data *adap)
+{
+	void __iomem *p = adap->pch_base_address;
+	pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL));
+	pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_RESTART);
+}
+
+/**
  * pch_i2c_readbytes() - read data  from I2C bus in normal mode.
  * @i2c_adap:	Pointer to the struct i2c_adapter.
  * @msgs:	Pointer to i2c_msg structure.
@@ -500,7 +549,9 @@
 	u32 length;
 	u32 addr;
 	u32 addr_2_msb;
+	u32 addr_8_lsb;
 	void __iomem *p = adap->pch_base_address;
+	s32 rtn;
 
 	length = msgs->len;
 	buf = msgs->buf;
@@ -515,9 +566,55 @@
 	}
 
 	if (msgs->flags & I2C_M_TEN) {
-		addr_2_msb = (((addr & I2C_MSB_2B_MSK) >> 7) | (I2C_RD));
+		addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7);
 		iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
+		if (first)
+			pch_i2c_start(adap);
 
+		rtn = pch_i2c_wait_for_xfer_complete(adap);
+		if (rtn == 0) {
+			if (pch_i2c_getack(adap)) {
+				pch_dbg(adap, "Receive NACK for slave address"
+					"setting\n");
+				return -EIO;
+			}
+			addr_8_lsb = (addr & I2C_ADDR_MSK);
+			iowrite32(addr_8_lsb, p + PCH_I2CDR);
+		} else if (rtn == -EIO) { /* Arbitration Lost */
+			pch_err(adap, "Lost Arbitration\n");
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMAL_BIT);
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMIF_BIT);
+			pch_i2c_init(adap);
+			return -EAGAIN;
+		} else { /* wait-event timeout */
+			pch_i2c_stop(adap);
+			return -ETIME;
+		}
+		pch_i2c_restart(adap);
+		rtn = pch_i2c_wait_for_xfer_complete(adap);
+		if (rtn == 0) {
+			if (pch_i2c_getack(adap)) {
+				pch_dbg(adap, "Receive NACK for slave address"
+					"setting\n");
+				return -EIO;
+			}
+			addr_2_msb |= I2C_RD;
+			iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK,
+				  p + PCH_I2CDR);
+		} else if (rtn == -EIO) { /* Arbitration Lost */
+			pch_err(adap, "Lost Arbitration\n");
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMAL_BIT);
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMIF_BIT);
+			pch_i2c_init(adap);
+			return -EAGAIN;
+		} else { /* wait-event timeout */
+			pch_i2c_stop(adap);
+			return -ETIME;
+		}
 	} else {
 		/* 7 address bits + R/W bit */
 		addr = (((addr) << 1) | (I2C_RD));
@@ -528,56 +625,81 @@
 	if (first)
 		pch_i2c_start(adap);
 
-	if ((pch_i2c_wait_for_xfer_complete(adap) == 0) &&
-	    (pch_i2c_getack(adap) == 0)) {
-		pch_dbg(adap, "return %d\n", 0);
+	rtn = pch_i2c_wait_for_xfer_complete(adap);
+	if (rtn == 0) {
+		if (pch_i2c_getack(adap)) {
+			pch_dbg(adap, "Receive NACK for slave address"
+				"setting\n");
+			return -EIO;
+		}
+	} else if (rtn == -EIO) { /* Arbitration Lost */
+		pch_err(adap, "Lost Arbitration\n");
+		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
+		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
+		pch_i2c_init(adap);
+		return -EAGAIN;
+	} else { /* wait-event timeout */
+		pch_i2c_stop(adap);
+		return -ETIME;
+	}
 
-		if (length == 0) {
-			pch_i2c_stop(adap);
-			ioread32(p + PCH_I2CDR); /* Dummy read needs */
+	if (length == 0) {
+		pch_i2c_stop(adap);
+		ioread32(p + PCH_I2CDR); /* Dummy read needs */
 
-			count = length;
-		} else {
-			int read_index;
-			int loop;
-			pch_i2c_sendack(adap);
+		count = length;
+	} else {
+		int read_index;
+		int loop;
+		pch_i2c_sendack(adap);
 
-			/* Dummy read */
-			for (loop = 1, read_index = 0; loop < length; loop++) {
-				buf[read_index] = ioread32(p + PCH_I2CDR);
+		/* Dummy read */
+		for (loop = 1, read_index = 0; loop < length; loop++) {
+			buf[read_index] = ioread32(p + PCH_I2CDR);
 
-				if (loop != 1)
-					read_index++;
+			if (loop != 1)
+				read_index++;
 
-				if (pch_i2c_wait_for_xfer_complete(adap) != 0) {
-					pch_i2c_stop(adap);
-					return -ETIME;
+			rtn = pch_i2c_wait_for_xfer_complete(adap);
+			if (rtn == 0) {
+				if (pch_i2c_getack(adap)) {
+					pch_dbg(adap, "Receive NACK for slave"
+						"address setting\n");
+					return -EIO;
 				}
-			}	/* end for */
+			} else { /* wait-event timeout */
+				pch_i2c_stop(adap);
+				return -ETIME;
+			}
 
-			pch_i2c_sendnack(adap);
+		}	/* end for */
 
-			buf[read_index] = ioread32(p + PCH_I2CDR);
+		pch_i2c_sendnack(adap);
 
-			if (length != 1)
-				read_index++;
+		buf[read_index] = ioread32(p + PCH_I2CDR); /* Read final - 1 */
 
-			if (pch_i2c_wait_for_xfer_complete(adap) == 0) {
-				if (last)
-					pch_i2c_stop(adap);
-				else
-					pch_i2c_repstart(adap);
+		if (length != 1)
+			read_index++;
 
-				buf[read_index++] = ioread32(p + PCH_I2CDR);
-				count = read_index;
-			} else {
-				count = -ETIME;
+		rtn = pch_i2c_wait_for_xfer_complete(adap);
+		if (rtn == 0) {
+			if (pch_i2c_getack(adap)) {
+				pch_dbg(adap, "Receive NACK for slave"
+					"address setting\n");
+				return -EIO;
 			}
-
+		} else { /* wait-event timeout */
+			pch_i2c_stop(adap);
+			return -ETIME;
 		}
-	} else {
-		count = -ETIME;
-		pch_i2c_stop(adap);
+
+		if (last)
+			pch_i2c_stop(adap);
+		else
+			pch_i2c_repstart(adap);
+
+		buf[read_index++] = ioread32(p + PCH_I2CDR); /* Read Final */
+		count = read_index;
 	}
 
 	return count;
@@ -771,6 +893,13 @@
 	/* Set the number of I2C channel instance */
 	adap_info->ch_num = id->driver_data;
 
+	ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED,
+		  KBUILD_MODNAME, adap_info);
+	if (ret) {
+		pch_pci_err(pdev, "request_irq FAILED\n");
+		goto err_request_irq;
+	}
+
 	for (i = 0; i < adap_info->ch_num; i++) {
 		pch_adap = &adap_info->pch_data[i].pch_adapter;
 		adap_info->pch_i2c_suspended = false;
@@ -788,28 +917,23 @@
 
 		pch_adap->dev.parent = &pdev->dev;
 
+		pch_i2c_init(&adap_info->pch_data[i]);
 		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;
+			goto err_add_adapter;
 		}
-
-		pch_i2c_init(&adap_info->pch_data[i]);
-	}
-	ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED,
-		  KBUILD_MODNAME, adap_info);
-	if (ret) {
-		pch_pci_err(pdev, "request_irq FAILED\n");
-		goto err_i2c_add_adapter;
 	}
 
 	pci_set_drvdata(pdev, adap_info);
 	pch_pci_dbg(pdev, "returns %d.\n", ret);
 	return 0;
 
-err_i2c_add_adapter:
+err_add_adapter:
 	for (j = 0; j < i; j++)
 		i2c_del_adapter(&adap_info->pch_data[j].pch_adapter);
+	free_irq(pdev->irq, adap_info);
+err_request_irq:
 	pci_iounmap(pdev, base_addr);
 err_pci_iomap:
 	pci_release_regions(pdev);
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-highlander.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-highlander.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-highlander.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-highlander.c	2012-01-04 18:55:44.000000000 -0500
@@ -387,7 +387,7 @@
 		dev->irq = 0;
 
 	if (dev->irq) {
-		ret = request_irq(dev->irq, highlander_i2c_irq, IRQF_DISABLED,
+		ret = request_irq(dev->irq, highlander_i2c_irq, 0,
 				  pdev->name, dev);
 		if (unlikely(ret))
 			goto err_unmap;
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-imx.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-imx.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-imx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-imx.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,6 +48,9 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_i2c.h>
 
 #include <mach/irqs.h>
 #include <mach/hardware.h>
@@ -125,6 +128,11 @@
 	unsigned int		ifdr; /* IMX_I2C_IFDR */
 };
 
+static const struct of_device_id i2c_imx_dt_ids[] = {
+	{ .compatible = "fsl,imx1-i2c", },
+	{ /* sentinel */ }
+};
+
 /** Functions for IMX I2C adapter driver ***************************************
 *******************************************************************************/
 
@@ -466,10 +474,10 @@
 {
 	struct imx_i2c_struct *i2c_imx;
 	struct resource *res;
-	struct imxi2c_platform_data *pdata;
+	struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
 	void __iomem *base;
 	resource_size_t res_size;
-	int irq;
+	int irq, bitrate;
 	int ret;
 
 	dev_dbg(&pdev->dev, "<%s>\n", __func__);
@@ -485,19 +493,11 @@
 		return -ENOENT;
 	}
 
-	pdata = pdev->dev.platform_data;
-
-	if (pdata && pdata->init) {
-		ret = pdata->init(&pdev->dev);
-		if (ret)
-			return ret;
-	}
-
 	res_size = resource_size(res);
 
 	if (!request_mem_region(res->start, res_size, DRIVER_NAME)) {
-		ret = -EBUSY;
-		goto fail0;
+		dev_err(&pdev->dev, "request_mem_region failed\n");
+		return -EBUSY;
 	}
 
 	base = ioremap(res->start, res_size);
@@ -520,6 +520,7 @@
 	i2c_imx->adapter.algo		= &i2c_imx_algo;
 	i2c_imx->adapter.dev.parent	= &pdev->dev;
 	i2c_imx->adapter.nr 		= pdev->id;
+	i2c_imx->adapter.dev.of_node	= pdev->dev.of_node;
 	i2c_imx->irq			= irq;
 	i2c_imx->base			= base;
 	i2c_imx->res			= res;
@@ -546,10 +547,12 @@
 	i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);
 
 	/* Set up clock divider */
-	if (pdata && pdata->bitrate)
-		i2c_imx_set_clk(i2c_imx, pdata->bitrate);
-	else
-		i2c_imx_set_clk(i2c_imx, IMX_I2C_BIT_RATE);
+	bitrate = IMX_I2C_BIT_RATE;
+	ret = of_property_read_u32(pdev->dev.of_node,
+				   "clock-frequency", &bitrate);
+	if (ret < 0 && pdata && pdata->bitrate)
+		bitrate = pdata->bitrate;
+	i2c_imx_set_clk(i2c_imx, bitrate);
 
 	/* Set up chip registers to defaults */
 	writeb(0, i2c_imx->base + IMX_I2C_I2CR);
@@ -562,6 +565,8 @@
 		goto fail5;
 	}
 
+	of_i2c_register_devices(&i2c_imx->adapter);
+
 	/* Set up platform driver data */
 	platform_set_drvdata(pdev, i2c_imx);
 
@@ -586,16 +591,12 @@
 	iounmap(base);
 fail1:
 	release_mem_region(res->start, resource_size(res));
-fail0:
-	if (pdata && pdata->exit)
-		pdata->exit(&pdev->dev);
 	return ret; /* Return error number */
 }
 
 static int __exit i2c_imx_remove(struct platform_device *pdev)
 {
 	struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev);
-	struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
 
 	/* remove adapter */
 	dev_dbg(&i2c_imx->adapter.dev, "adapter removed\n");
@@ -611,10 +612,6 @@
 	writeb(0, i2c_imx->base + IMX_I2C_I2CR);
 	writeb(0, i2c_imx->base + IMX_I2C_I2SR);
 
-	/* Shut down hardware */
-	if (pdata && pdata->exit)
-		pdata->exit(&pdev->dev);
-
 	clk_put(i2c_imx->clk);
 
 	iounmap(i2c_imx->base);
@@ -628,6 +625,7 @@
 	.driver	= {
 		.name	= DRIVER_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = i2c_imx_dt_ids,
 	}
 };
 
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-ixp2000.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-ixp2000.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-ixp2000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-ixp2000.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,7 +35,7 @@
 #include <linux/slab.h>
 
 #include <mach/hardware.h>	/* Pick up IXP2000-specific bits */
-#include <mach/gpio.h>
+#include <mach/gpio-ixp2000.h>
 
 static inline int ixp2000_scl_pin(void *data)
 {
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-nomadik.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-nomadik.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-nomadik.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-nomadik.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,11 +63,11 @@
 /* Master controller (MCR) register */
 #define I2C_MCR_OP		(0x1 << 0)	/* Operation */
 #define I2C_MCR_A7		(0x7f << 1)	/* 7-bit address */
-#define I2C_MCR_EA10		(0x7 << 8) 	/* 10-bit Extended address */
+#define I2C_MCR_EA10		(0x7 << 8)	/* 10-bit Extended address */
 #define I2C_MCR_SB		(0x1 << 11)	/* Extended address */
 #define I2C_MCR_AM		(0x3 << 12)	/* Address type */
-#define I2C_MCR_STOP		(0x1 << 14) 	/* Stop condition */
-#define I2C_MCR_LENGTH		(0x7ff << 15) 	/* Transaction length */
+#define I2C_MCR_STOP		(0x1 << 14)	/* Stop condition */
+#define I2C_MCR_LENGTH		(0x7ff << 15)	/* Transaction length */
 
 /* Status register (SR) */
 #define I2C_SR_OP		(0x3 << 0)	/* Operation */
@@ -77,7 +77,7 @@
 #define I2C_SR_LENGTH		(0x7ff << 9)	/* Transfer length */
 
 /* Interrupt mask set/clear (IMSCR) bits */
-#define I2C_IT_TXFE 		(0x1 << 0)
+#define I2C_IT_TXFE		(0x1 << 0)
 #define I2C_IT_TXFNE		(0x1 << 1)
 #define I2C_IT_TXFF		(0x1 << 2)
 #define I2C_IT_TXFOVR		(0x1 << 3)
@@ -135,31 +135,31 @@
 };
 
 /**
- * struct nmk_i2c_dev - private data structure of the controller
- * @pdev: parent platform device
- * @adap: corresponding I2C adapter
- * @irq: interrupt line for the controller
- * @virtbase: virtual io memory area
- * @clk: hardware i2c block clock
- * @cfg: machine provided controller configuration
- * @cli: holder of client specific data
- * @stop: stop condition
- * @xfer_complete: acknowledge completion for a I2C message
- * @result: controller propogated result
- * @regulator: pointer to i2c regulator
- * @busy: Busy doing transfer
+ * struct nmk_i2c_dev - private data structure of the controller.
+ * @pdev: parent platform device.
+ * @adap: corresponding I2C adapter.
+ * @irq: interrupt line for the controller.
+ * @virtbase: virtual io memory area.
+ * @clk: hardware i2c block clock.
+ * @cfg: machine provided controller configuration.
+ * @cli: holder of client specific data.
+ * @stop: stop condition.
+ * @xfer_complete: acknowledge completion for a I2C message.
+ * @result: controller propogated result.
+ * @regulator: pointer to i2c regulator.
+ * @busy: Busy doing transfer.
  */
 struct nmk_i2c_dev {
 	struct platform_device		*pdev;
-	struct i2c_adapter 		adap;
-	int 				irq;
+	struct i2c_adapter		adap;
+	int				irq;
 	void __iomem			*virtbase;
 	struct clk			*clk;
 	struct nmk_i2c_controller	cfg;
 	struct i2c_nmk_client		cli;
-	int 				stop;
+	int				stop;
 	struct completion		xfer_complete;
-	int 				result;
+	int				result;
 	struct regulator		*regulator;
 	bool				busy;
 };
@@ -217,8 +217,9 @@
 		}
 	}
 
-	dev_err(&dev->pdev->dev, "flushing operation timed out "
-		"giving up after %d attempts", LOOP_ATTEMPTS);
+	dev_err(&dev->pdev->dev,
+		"flushing operation timed out giving up after %d attempts",
+		LOOP_ATTEMPTS);
 
 	return -ETIMEDOUT;
 }
@@ -270,7 +271,7 @@
 }
 
 /* enable peripheral, master mode operation */
-#define DEFAULT_I2C_REG_CR 	((1 << 1) | I2C_CR_PE)
+#define DEFAULT_I2C_REG_CR	((1 << 1) | I2C_CR_PE)
 
 /**
  * load_i2c_mcr_reg() - load the MCR register
@@ -363,8 +364,8 @@
 	 * and high speed (up to 3.4 Mb/s)
 	 */
 	if (dev->cfg.sm > I2C_FREQ_MODE_FAST) {
-		dev_err(&dev->pdev->dev, "do not support this mode "
-			"defaulting to std. mode\n");
+		dev_err(&dev->pdev->dev,
+			"do not support this mode defaulting to std. mode\n");
 		brcr2 = i2c_clk/(100000 * 2) & 0xffff;
 		writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR);
 		writel(I2C_FREQ_MODE_STANDARD << 4,
@@ -423,7 +424,7 @@
 
 	if (timeout < 0) {
 		dev_err(&dev->pdev->dev,
-			"wait_for_completion_timeout"
+			"wait_for_completion_timeout "
 			"returned %d waiting for event\n", timeout);
 		status = timeout;
 	}
@@ -556,8 +557,8 @@
 		if (((i2c_sr >> 2) & 0x3) == 0x3) {
 			/* get the abort cause */
 			cause =	(i2c_sr >> 4) & 0x7;
-			dev_err(&dev->pdev->dev, "%s\n", cause
-				>= ARRAY_SIZE(abort_causes) ?
+			dev_err(&dev->pdev->dev, "%s\n",
+				cause >= ARRAY_SIZE(abort_causes) ?
 				"unknown reason" :
 				abort_causes[cause]);
 		}
@@ -582,13 +583,13 @@
  *
  * NOTE:
  * READ TRANSFER : We impose a restriction of the first message to be the
- * 		index message for any read transaction.
- * 		- a no index is coded as '0',
- * 		- 2byte big endian index is coded as '3'
- * 		!!! msg[0].buf holds the actual index.
- * 		This is compatible with generic messages of smbus emulator
- * 		that send a one byte index.
- * 		eg. a I2C transation to read 2 bytes from index 0
+ *		index message for any read transaction.
+ *		- a no index is coded as '0',
+ *		- 2byte big endian index is coded as '3'
+ *		!!! msg[0].buf holds the actual index.
+ *		This is compatible with generic messages of smbus emulator
+ *		that send a one byte index.
+ *		eg. a I2C transation to read 2 bytes from index 0
  *			idx = 0;
  *			msg[0].addr = client->addr;
  *			msg[0].flags = 0x0;
@@ -644,8 +645,8 @@
 
 		for (i = 0; i < num_msgs; i++) {
 			if (unlikely(msgs[i].flags & I2C_M_TEN)) {
-				dev_err(&dev->pdev->dev, "10 bit addressing"
-						"not supported\n");
+				dev_err(&dev->pdev->dev,
+					"10 bit addressing not supported\n");
 
 				status = -EINVAL;
 				goto out;
@@ -789,8 +790,9 @@
 
 		if (dev->cli.count) {
 			dev->result = -EIO;
-			dev_err(&dev->pdev->dev, "%lu bytes still remain to be"
-					"xfered\n", dev->cli.count);
+			dev_err(&dev->pdev->dev,
+				"%lu bytes still remain to be xfered\n",
+				dev->cli.count);
 			(void) init_hw(dev);
 		}
 		complete(&dev->xfer_complete);
@@ -923,7 +925,7 @@
 	}
 
 	if (request_mem_region(res->start, resource_size(res),
-		DRIVER_NAME "I/O region") == 	NULL)	{
+		DRIVER_NAME "I/O region") == NULL) {
 		ret = -EBUSY;
 		goto err_no_region;
 	}
@@ -935,7 +937,7 @@
 	}
 
 	dev->irq = platform_get_irq(pdev, 0);
-	ret = request_irq(dev->irq, i2c_irq_handler, IRQF_DISABLED,
+	ret = request_irq(dev->irq, i2c_irq_handler, 0,
 				DRIVER_NAME, dev);
 	if (ret) {
 		dev_err(&pdev->dev, "cannot claim the irq %d\n", dev->irq);
@@ -980,8 +982,9 @@
 
 	i2c_set_adapdata(adap, dev);
 
-	dev_info(&pdev->dev, "initialize %s on virtual "
-		"base %p\n", adap->name, dev->virtbase);
+	dev_info(&pdev->dev,
+		 "initialize %s on virtual base %p\n",
+		 adap->name, dev->virtbase);
 
 	ret = i2c_add_numbered_adapter(adap);
 	if (ret) {
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-nuc900.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-nuc900.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-nuc900.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-nuc900.c	2012-01-04 18:55:44.000000000 -0500
@@ -593,7 +593,7 @@
 	i2c->adap.algo_data = i2c;
 	i2c->adap.dev.parent = &pdev->dev;
 
-	mfp_set_groupg(&pdev->dev);
+	mfp_set_groupg(&pdev->dev, NULL);
 
 	clk_get_rate(i2c->clk);
 
@@ -610,7 +610,7 @@
 		goto err_iomap;
 	}
 
-	ret = request_irq(i2c->irq, nuc900_i2c_irq, IRQF_DISABLED | IRQF_SHARED,
+	ret = request_irq(i2c->irq, nuc900_i2c_irq, IRQF_SHARED,
 			  dev_name(&pdev->dev), i2c);
 
 	if (ret != 0) {
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-omap.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-omap.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-omap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-omap.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,12 +42,12 @@
 #include <linux/pm_runtime.h>
 
 /* I2C controller revisions */
-#define OMAP_I2C_REV_2			0x20
+#define OMAP_I2C_OMAP1_REV_2		0x20
 
 /* I2C controller revisions present on specific hardware */
 #define OMAP_I2C_REV_ON_2430		0x36
 #define OMAP_I2C_REV_ON_3430		0x3C
-#define OMAP_I2C_REV_ON_4430		0x40
+#define OMAP_I2C_REV_ON_3530_4430	0x40
 
 /* timeout waiting for the controller to respond */
 #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
@@ -72,11 +72,12 @@
 	OMAP_I2C_SCLH_REG,
 	OMAP_I2C_SYSTEST_REG,
 	OMAP_I2C_BUFSTAT_REG,
-	OMAP_I2C_REVNB_LO,
-	OMAP_I2C_REVNB_HI,
-	OMAP_I2C_IRQSTATUS_RAW,
-	OMAP_I2C_IRQENABLE_SET,
-	OMAP_I2C_IRQENABLE_CLR,
+	/* only on OMAP4430 */
+	OMAP_I2C_IP_V2_REVNB_LO,
+	OMAP_I2C_IP_V2_REVNB_HI,
+	OMAP_I2C_IP_V2_IRQSTATUS_RAW,
+	OMAP_I2C_IP_V2_IRQENABLE_SET,
+	OMAP_I2C_IP_V2_IRQENABLE_CLR,
 };
 
 /* I2C Interrupt Enable Register (OMAP_I2C_IE): */
@@ -193,7 +194,6 @@
 						 */
 	u8			rev;
 	unsigned		b_hw:1;		/* bad h/w fixes */
-	unsigned		idle:1;
 	u16			iestate;	/* Saved interrupt register */
 	u16			pscstate;
 	u16			scllstate;
@@ -204,7 +204,7 @@
 	u16			errata;
 };
 
-static const u8 reg_map[] = {
+static const u8 reg_map_ip_v1[] = {
 	[OMAP_I2C_REV_REG] = 0x00,
 	[OMAP_I2C_IE_REG] = 0x01,
 	[OMAP_I2C_STAT_REG] = 0x02,
@@ -225,7 +225,7 @@
 	[OMAP_I2C_BUFSTAT_REG] = 0x10,
 };
 
-static const u8 omap4_reg_map[] = {
+static const u8 reg_map_ip_v2[] = {
 	[OMAP_I2C_REV_REG] = 0x04,
 	[OMAP_I2C_IE_REG] = 0x2c,
 	[OMAP_I2C_STAT_REG] = 0x28,
@@ -244,11 +244,11 @@
 	[OMAP_I2C_SCLH_REG] = 0xb8,
 	[OMAP_I2C_SYSTEST_REG] = 0xbC,
 	[OMAP_I2C_BUFSTAT_REG] = 0xc0,
-	[OMAP_I2C_REVNB_LO] = 0x00,
-	[OMAP_I2C_REVNB_HI] = 0x04,
-	[OMAP_I2C_IRQSTATUS_RAW] = 0x24,
-	[OMAP_I2C_IRQENABLE_SET] = 0x2c,
-	[OMAP_I2C_IRQENABLE_CLR] = 0x30,
+	[OMAP_I2C_IP_V2_REVNB_LO] = 0x00,
+	[OMAP_I2C_IP_V2_REVNB_HI] = 0x04,
+	[OMAP_I2C_IP_V2_IRQSTATUS_RAW] = 0x24,
+	[OMAP_I2C_IP_V2_IRQENABLE_SET] = 0x2c,
+	[OMAP_I2C_IP_V2_IRQENABLE_CLR] = 0x30,
 };
 
 static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
@@ -266,17 +266,11 @@
 
 static void omap_i2c_unidle(struct omap_i2c_dev *dev)
 {
-	struct platform_device *pdev;
 	struct omap_i2c_bus_platform_data *pdata;
 
-	WARN_ON(!dev->idle);
-
-	pdev = to_platform_device(dev->dev);
-	pdata = pdev->dev.platform_data;
-
-	pm_runtime_get_sync(&pdev->dev);
+	pdata = dev->dev->platform_data;
 
-	if (cpu_is_omap34xx()) {
+	if (pdata->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
 		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
 		omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate);
 		omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate);
@@ -286,7 +280,6 @@
 		omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
 		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
 	}
-	dev->idle = 0;
 
 	/*
 	 * Don't write to this register if the IE state is 0 as it can
@@ -298,32 +291,25 @@
 
 static void omap_i2c_idle(struct omap_i2c_dev *dev)
 {
-	struct platform_device *pdev;
 	struct omap_i2c_bus_platform_data *pdata;
 	u16 iv;
 
-	WARN_ON(dev->idle);
-
-	pdev = to_platform_device(dev->dev);
-	pdata = pdev->dev.platform_data;
+	pdata = dev->dev->platform_data;
 
 	dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
-	if (dev->rev >= OMAP_I2C_REV_ON_4430)
-		omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_CLR, 1);
+	if (pdata->rev == OMAP_I2C_IP_VERSION_2)
+		omap_i2c_write_reg(dev, OMAP_I2C_IP_V2_IRQENABLE_CLR, 1);
 	else
 		omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
 
-	if (dev->rev < OMAP_I2C_REV_2) {
+	if (dev->rev < OMAP_I2C_OMAP1_REV_2) {
 		iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
 	} else {
 		omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
 
-		/* Flush posted write before the dev->idle store occurs */
+		/* Flush posted write */
 		omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
 	}
-	dev->idle = 1;
-
-	pm_runtime_put_sync(&pdev->dev);
 }
 
 static int omap_i2c_init(struct omap_i2c_dev *dev)
@@ -334,8 +320,11 @@
 	unsigned long timeout;
 	unsigned long internal_clk = 0;
 	struct clk *fclk;
+	struct omap_i2c_bus_platform_data *pdata;
 
-	if (dev->rev >= OMAP_I2C_REV_2) {
+	pdata = dev->dev->platform_data;
+
+	if (dev->rev >= OMAP_I2C_OMAP1_REV_2) {
 		/* Disable I2C controller before soft reset */
 		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
 			omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) &
@@ -378,12 +367,13 @@
 			 * REVISIT: Some wkup sources might not be needed.
 			 */
 			dev->westate = OMAP_I2C_WE_ALL;
-			omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
+			omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
+							dev->westate);
 		}
 	}
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
 
-	if (cpu_class_is_omap1()) {
+	if (pdata->flags & OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK) {
 		/*
 		 * The I2C functional clock is the armxor_ck, so there's
 		 * no need to get "armxor_ck" separately.  Now, if OMAP2420
@@ -407,7 +397,7 @@
 			psc = fclk_rate / 12000000;
 	}
 
-	if (!(cpu_class_is_omap1() || cpu_is_omap2420())) {
+	if (!(pdata->flags & OMAP_I2C_FLAG_SIMPLE_CLOCK)) {
 
 		/*
 		 * HSI2C controller internal clk rate should be 19.2 Mhz for
@@ -415,7 +405,8 @@
 		 * to get longer filter period for better noise suppression.
 		 * The filter is iclk (fclk for HS) period.
 		 */
-		if (dev->speed > 400 || cpu_is_omap2430())
+		if (dev->speed > 400 ||
+			       pdata->flags & OMAP_I2C_FLAG_FORCE_19200_INT_CLK)
 			internal_clk = 19200;
 		else if (dev->speed > 100)
 			internal_clk = 9600;
@@ -484,7 +475,7 @@
 
 	dev->errata = 0;
 
-	if (cpu_is_omap2430() || cpu_is_omap34xx())
+	if (pdata->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207)
 		dev->errata |= I2C_OMAP_ERRATA_I207;
 
 	/* Enable interrupts */
@@ -493,7 +484,7 @@
 			OMAP_I2C_IE_AL)  | ((dev->fifo_size) ?
 				(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0);
 	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
-	if (cpu_is_omap34xx()) {
+	if (pdata->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
 		dev->pscstate = psc;
 		dev->scllstate = scll;
 		dev->sclhstate = sclh;
@@ -642,7 +633,7 @@
 	int i;
 	int r;
 
-	omap_i2c_unidle(dev);
+	pm_runtime_get_sync(dev->dev);
 
 	r = omap_i2c_wait_for_bb(dev);
 	if (r < 0)
@@ -665,7 +656,7 @@
 
 	omap_i2c_wait_for_bb(dev);
 out:
-	omap_i2c_idle(dev);
+	pm_runtime_put(dev->dev);
 	return r;
 }
 
@@ -720,12 +711,12 @@
 #ifdef CONFIG_ARCH_OMAP15XX
 
 static irqreturn_t
-omap_i2c_rev1_isr(int this_irq, void *dev_id)
+omap_i2c_omap1_isr(int this_irq, void *dev_id)
 {
 	struct omap_i2c_dev *dev = dev_id;
 	u16 iv, w;
 
-	if (dev->idle)
+	if (pm_runtime_suspended(dev->dev))
 		return IRQ_NONE;
 
 	iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
@@ -774,7 +765,7 @@
 	return IRQ_HANDLED;
 }
 #else
-#define omap_i2c_rev1_isr		NULL
+#define omap_i2c_omap1_isr		NULL
 #endif
 
 /*
@@ -813,8 +804,11 @@
 	u16 bits;
 	u16 stat, w;
 	int err, count = 0;
+	struct omap_i2c_bus_platform_data *pdata;
 
-	if (dev->idle)
+	pdata = dev->dev->platform_data;
+
+	if (pm_runtime_suspended(dev->dev))
 		return IRQ_NONE;
 
 	bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
@@ -881,8 +875,8 @@
 					 * Data reg in 2430, omap3 and
 					 * omap4 is 8 bit wide
 					 */
-					if (cpu_class_is_omap1() ||
-							cpu_is_omap2420()) {
+					if (pdata->flags &
+						 OMAP_I2C_FLAG_16BIT_DATA_REG) {
 						if (dev->buf_len) {
 							*dev->buf++ = w >> 8;
 							dev->buf_len--;
@@ -924,8 +918,8 @@
 					 * Data reg in 2430, omap3 and
 					 * omap4 is 8 bit wide
 					 */
-					if (cpu_class_is_omap1() ||
-							cpu_is_omap2420()) {
+					if (pdata->flags &
+						 OMAP_I2C_FLAG_16BIT_DATA_REG) {
 						if (dev->buf_len) {
 							w |= *dev->buf++ << 8;
 							dev->buf_len--;
@@ -1016,7 +1010,6 @@
 	}
 
 	dev->speed = speed;
-	dev->idle = 1;
 	dev->dev = &pdev->dev;
 	dev->irq = irq->start;
 	dev->base = ioremap(mem->start, resource_size(mem));
@@ -1027,27 +1020,22 @@
 
 	platform_set_drvdata(pdev, dev);
 
-	if (cpu_is_omap7xx())
-		dev->reg_shift = 1;
-	else if (cpu_is_omap44xx())
-		dev->reg_shift = 0;
-	else
-		dev->reg_shift = 2;
+	dev->reg_shift = (pdata->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3;
 
-	if (cpu_is_omap44xx())
-		dev->regs = (u8 *) omap4_reg_map;
+	if (pdata->rev == OMAP_I2C_IP_VERSION_2)
+		dev->regs = (u8 *)reg_map_ip_v2;
 	else
-		dev->regs = (u8 *) reg_map;
+		dev->regs = (u8 *)reg_map_ip_v1;
 
-	pm_runtime_enable(&pdev->dev);
-	omap_i2c_unidle(dev);
+	pm_runtime_enable(dev->dev);
+	pm_runtime_get_sync(dev->dev);
 
 	dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
 
 	if (dev->rev <= OMAP_I2C_REV_ON_3430)
 		dev->errata |= I2C_OMAP3_1P153;
 
-	if (!(cpu_class_is_omap1() || cpu_is_omap2420())) {
+	if (!(pdata->flags & OMAP_I2C_FLAG_NO_FIFO)) {
 		u16 s;
 
 		/* Set up the fifo size - Get total size */
@@ -1059,13 +1047,14 @@
 		 * size. This is to ensure that we can handle the status on int
 		 * call back latencies.
 		 */
-		if (dev->rev >= OMAP_I2C_REV_ON_4430) {
-			dev->fifo_size = 0;
+
+		dev->fifo_size = (dev->fifo_size / 2);
+
+		if (dev->rev >= OMAP_I2C_REV_ON_3530_4430)
 			dev->b_hw = 0; /* Disable hardware fixes */
-		} else {
-			dev->fifo_size = (dev->fifo_size / 2);
+		else
 			dev->b_hw = 1; /* Enable hardware fixes */
-		}
+
 		/* calculate wakeup latency constraint for MPU */
 		if (dev->set_mpu_wkup_lat != NULL)
 			dev->latency = (1000000 * dev->fifo_size) /
@@ -1075,7 +1064,8 @@
 	/* reset ASAP, clearing any IRQs */
 	omap_i2c_init(dev);
 
-	isr = (dev->rev < OMAP_I2C_REV_2) ? omap_i2c_rev1_isr : omap_i2c_isr;
+	isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_isr :
+								   omap_i2c_isr;
 	r = request_irq(dev->irq, isr, 0, pdev->name, dev);
 
 	if (r) {
@@ -1083,10 +1073,10 @@
 		goto err_unuse_clocks;
 	}
 
-	dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n",
-		 pdev->id, dev->rev >> 4, dev->rev & 0xf, dev->speed);
+	dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", pdev->id,
+		 pdata->rev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
 
-	omap_i2c_idle(dev);
+	pm_runtime_put(dev->dev);
 
 	adap = &dev->adapter;
 	i2c_set_adapdata(adap, dev);
@@ -1110,7 +1100,7 @@
 	free_irq(dev->irq, dev);
 err_unuse_clocks:
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
-	omap_i2c_idle(dev);
+	pm_runtime_put(dev->dev);
 	iounmap(dev->base);
 err_free_mem:
 	platform_set_drvdata(pdev, NULL);
@@ -1139,12 +1129,43 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM_RUNTIME
+static int omap_i2c_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_i2c_dev *_dev = platform_get_drvdata(pdev);
+
+	omap_i2c_idle(_dev);
+
+	return 0;
+}
+
+static int omap_i2c_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_i2c_dev *_dev = platform_get_drvdata(pdev);
+
+	omap_i2c_unidle(_dev);
+
+	return 0;
+}
+
+static struct dev_pm_ops omap_i2c_pm_ops = {
+	.runtime_suspend = omap_i2c_runtime_suspend,
+	.runtime_resume = omap_i2c_runtime_resume,
+};
+#define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops)
+#else
+#define OMAP_I2C_PM_OPS NULL
+#endif
+
 static struct platform_driver omap_i2c_driver = {
 	.probe		= omap_i2c_probe,
 	.remove		= omap_i2c_remove,
 	.driver		= {
 		.name	= "omap_i2c",
 		.owner	= THIS_MODULE,
+		.pm	= OMAP_I2C_PM_OPS,
 	},
 };
 
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-pmcmsp.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-pmcmsp.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-pmcmsp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-pmcmsp.c	2012-01-04 18:55:44.000000000 -0500
@@ -306,7 +306,7 @@
 	pmcmsptwi_data.irq = platform_get_irq(pldev, 0);
 	if (pmcmsptwi_data.irq) {
 		rc = request_irq(pmcmsptwi_data.irq, &pmcmsptwi_interrupt,
-			IRQF_SHARED | IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
+			IRQF_SHARED | IRQF_SAMPLE_RANDOM,
 			pldev->name, &pmcmsptwi_data);
 		if (rc == 0) {
 			/*
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-pxa-pci.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-pxa-pci.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-pxa-pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-pxa-pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -3,6 +3,7 @@
  * It does not support slave mode, the register slightly moved. This PCI
  * device provides three bars, every contains a single I2C controller.
  */
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/i2c/pxa-i2c.h>
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-s3c2410.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-s3c2410.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-s3c2410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-s3c2410.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,8 @@
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/of_i2c.h>
+#include <linux/of_gpio.h>
 
 #include <asm/irq.h>
 
@@ -78,6 +80,8 @@
 	struct resource		*ioarea;
 	struct i2c_adapter	adap;
 
+	struct s3c2410_platform_i2c	*pdata;
+	int			gpios[2];
 #ifdef CONFIG_CPU_FREQ
 	struct notifier_block	freq_transition;
 #endif
@@ -95,6 +99,12 @@
 	struct platform_device *pdev = to_platform_device(i2c->dev);
 	enum s3c24xx_i2c_type type;
 
+#ifdef CONFIG_OF
+	if (i2c->dev->of_node)
+		return of_device_is_compatible(i2c->dev->of_node,
+				"samsung,s3c2440-i2c");
+#endif
+
 	type = platform_get_device_id(pdev)->driver_data;
 	return type == TYPE_S3C2440;
 }
@@ -524,6 +534,7 @@
 
 	/* first, try busy waiting briefly */
 	do {
+		cpu_relax();
 		iicstat = readl(i2c->regs + S3C2410_IICSTAT);
 	} while ((iicstat & S3C2410_IICSTAT_START) && --spins);
 
@@ -625,7 +636,7 @@
 
 static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
 {
-	struct s3c2410_platform_i2c *pdata = i2c->dev->platform_data;
+	struct s3c2410_platform_i2c *pdata = i2c->pdata;
 	unsigned long clkin = clk_get_rate(i2c->clk);
 	unsigned int divs, div1;
 	unsigned long target_frequency;
@@ -741,6 +752,49 @@
 }
 #endif
 
+#ifdef CONFIG_OF
+static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
+{
+	int idx, gpio, ret;
+
+	for (idx = 0; idx < 2; idx++) {
+		gpio = of_get_gpio(i2c->dev->of_node, idx);
+		if (!gpio_is_valid(gpio)) {
+			dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio);
+			goto free_gpio;
+		}
+
+		ret = gpio_request(gpio, "i2c-bus");
+		if (ret) {
+			dev_err(i2c->dev, "gpio [%d] request failed\n", gpio);
+			goto free_gpio;
+		}
+	}
+	return 0;
+
+free_gpio:
+	while (--idx >= 0)
+		gpio_free(i2c->gpios[idx]);
+	return -EINVAL;
+}
+
+static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c)
+{
+	unsigned int idx;
+	for (idx = 0; idx < 2; idx++)
+		gpio_free(i2c->gpios[idx]);
+}
+#else
+static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
+{
+	return 0;
+}
+
+static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c)
+{
+}
+#endif
+
 /* s3c24xx_i2c_init
  *
  * initialise the controller, set the IO lines and frequency
@@ -754,12 +808,15 @@
 
 	/* get the plafrom data */
 
-	pdata = i2c->dev->platform_data;
+	pdata = i2c->pdata;
 
 	/* inititalise the gpio */
 
 	if (pdata->cfg_gpio)
 		pdata->cfg_gpio(to_platform_device(i2c->dev));
+	else
+		if (s3c24xx_i2c_parse_dt_gpio(i2c))
+			return -EINVAL;
 
 	/* write slave address */
 
@@ -785,6 +842,34 @@
 	return 0;
 }
 
+#ifdef CONFIG_OF
+/* s3c24xx_i2c_parse_dt
+ *
+ * Parse the device tree node and retreive the platform data.
+*/
+
+static void
+s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c)
+{
+	struct s3c2410_platform_i2c *pdata = i2c->pdata;
+
+	if (!np)
+		return;
+
+	pdata->bus_num = -1; /* i2c bus number is dynamically assigned */
+	of_property_read_u32(np, "samsung,i2c-sda-delay", &pdata->sda_delay);
+	of_property_read_u32(np, "samsung,i2c-slave-addr", &pdata->slave_addr);
+	of_property_read_u32(np, "samsung,i2c-max-bus-freq",
+				(u32 *)&pdata->frequency);
+}
+#else
+static void
+s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c)
+{
+	return;
+}
+#endif
+
 /* s3c24xx_i2c_probe
  *
  * called by the bus driver when a suitable device is found
@@ -793,14 +878,16 @@
 static int s3c24xx_i2c_probe(struct platform_device *pdev)
 {
 	struct s3c24xx_i2c *i2c;
-	struct s3c2410_platform_i2c *pdata;
+	struct s3c2410_platform_i2c *pdata = NULL;
 	struct resource *res;
 	int ret;
 
-	pdata = pdev->dev.platform_data;
-	if (!pdata) {
-		dev_err(&pdev->dev, "no platform data\n");
-		return -EINVAL;
+	if (!pdev->dev.of_node) {
+		pdata = pdev->dev.platform_data;
+		if (!pdata) {
+			dev_err(&pdev->dev, "no platform data\n");
+			return -EINVAL;
+		}
 	}
 
 	i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL);
@@ -809,6 +896,17 @@
 		return -ENOMEM;
 	}
 
+	i2c->pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!i2c->pdata) {
+		ret = -ENOMEM;
+		goto err_noclk;
+	}
+
+	if (pdata)
+		memcpy(i2c->pdata, pdata, sizeof(*pdata));
+	else
+		s3c24xx_i2c_parse_dt(pdev->dev.of_node, i2c);
+
 	strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
 	i2c->adap.owner   = THIS_MODULE;
 	i2c->adap.algo    = &s3c24xx_i2c_algorithm;
@@ -883,7 +981,7 @@
 		goto err_iomap;
 	}
 
-	ret = request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED,
+	ret = request_irq(i2c->irq, s3c24xx_i2c_irq, 0,
 			  dev_name(&pdev->dev), i2c);
 
 	if (ret != 0) {
@@ -903,7 +1001,8 @@
 	 * being bus 0.
 	 */
 
-	i2c->adap.nr = pdata->bus_num;
+	i2c->adap.nr = i2c->pdata->bus_num;
+	i2c->adap.dev.of_node = pdev->dev.of_node;
 
 	ret = i2c_add_numbered_adapter(&i2c->adap);
 	if (ret < 0) {
@@ -911,6 +1010,7 @@
 		goto err_cpufreq;
 	}
 
+	of_i2c_register_devices(&i2c->adap);
 	platform_set_drvdata(pdev, i2c);
 
 	dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
@@ -959,6 +1059,7 @@
 	iounmap(i2c->regs);
 
 	release_resource(i2c->ioarea);
+	s3c24xx_i2c_dt_gpio_free(i2c);
 	kfree(i2c->ioarea);
 	kfree(i2c);
 
@@ -1012,6 +1113,17 @@
 };
 MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
 
+#ifdef CONFIG_OF
+static const struct of_device_id s3c24xx_i2c_match[] = {
+	{ .compatible = "samsung,s3c2410-i2c" },
+	{ .compatible = "samsung,s3c2440-i2c" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match);
+#else
+#define s3c24xx_i2c_match NULL
+#endif
+
 static struct platform_driver s3c24xx_i2c_driver = {
 	.probe		= s3c24xx_i2c_probe,
 	.remove		= s3c24xx_i2c_remove,
@@ -1020,6 +1132,7 @@
 		.owner	= THIS_MODULE,
 		.name	= "s3c-i2c",
 		.pm	= S3C24XX_DEV_PM_OPS,
+		.of_match_table = s3c24xx_i2c_match,
 	},
 };
 
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-sh7760.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-sh7760.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-sh7760.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-sh7760.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/module.h>
 
 #include <asm/clock.h>
 #include <asm/i2c-sh7760.h>
@@ -502,7 +503,7 @@
 	}
 	OUT32(id, I2CCCR, ret);
 
-	if (request_irq(id->irq, sh7760_i2c_irq, IRQF_DISABLED,
+	if (request_irq(id->irq, sh7760_i2c_irq, 0,
 			SH7760_I2C_DEVNAME, id)) {
 		dev_err(&pdev->dev, "cannot get irq %d\n", id->irq);
 		ret = -EBUSY;
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-sh_mobile.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-sh_mobile.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-sh_mobile.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-sh_mobile.c	2012-01-04 18:55:44.000000000 -0500
@@ -543,7 +543,7 @@
 
 	while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {
 		for (n = res->start; hook && n <= res->end; n++) {
-			if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED,
+			if (request_irq(n, sh_mobile_i2c_isr, 0,
 					dev_name(&dev->dev), dev)) {
 				for (n--; n >= res->start; n--)
 					free_irq(n, dev);
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-stu300.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-stu300.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-stu300.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-stu300.c	2012-01-04 18:55:44.000000000 -0500
@@ -916,7 +916,7 @@
 	}
 
 	dev->irq = platform_get_irq(pdev, 0);
-	if (request_irq(dev->irq, stu300_irh, IRQF_DISABLED,
+	if (request_irq(dev->irq, stu300_irh, 0,
 			NAME, dev)) {
 		ret = -EIO;
 		goto err_no_irq;
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/i2c-tegra.c linux-libre-3.2-gnu/drivers/i2c/busses/i2c-tegra.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/i2c-tegra.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/i2c-tegra.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/i2c-tegra.h>
 #include <linux/of_i2c.h>
+#include <linux/module.h>
 
 #include <asm/unaligned.h>
 
@@ -566,7 +567,7 @@
 	struct clk *clk;
 	struct clk *i2c_clk;
 	const unsigned int *prop;
-	void *base;
+	void __iomem *base;
 	int irq;
 	int ret = 0;
 
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/Kconfig linux-libre-3.2-gnu/drivers/i2c/busses/Kconfig
--- linux-libre-3.1-gnu/drivers/i2c/busses/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -110,7 +110,6 @@
 config I2C_ISCH
 	tristate "Intel SCH SMBus 1.0"
 	depends on PCI
-	select MFD_CORE
 	select LPC_SCH
 	help
 	  Say Y here if you want to use SMBus controller on the Intel SCH
@@ -301,7 +300,7 @@
 
 config I2C_AU1550
 	tristate "Au1550/Au1200 SMBus interface"
-	depends on SOC_AU1550 || SOC_AU1200
+	depends on MIPS_ALCHEMY
 	help
 	  If you say yes to this option, support will be included for the
 	  Au1550 and Au1200 SMBus interface.
@@ -350,15 +349,25 @@
 	  devices such as DaVinci NIC.
 	  For details please see http://www.ti.com/davinci
 
-config I2C_DESIGNWARE
-	tristate "Synopsys DesignWare"
+config I2C_DESIGNWARE_PLATFORM
+	tristate "Synopsys DesignWare Platfrom"
 	depends on HAVE_CLK
 	help
 	  If you say yes to this option, support will be included for the
 	  Synopsys DesignWare I2C adapter. Only master mode is supported.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called i2c-designware.
+	  will be called i2c-designware-platform.
+
+config I2C_DESIGNWARE_PCI
+	tristate "Synopsys DesignWare PCI"
+	depends on PCI
+	help
+	  If you say yes to this option, support will be included for the
+	  Synopsys DesignWare I2C adapter. Only master mode is supported.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-designware-pci.
 
 config I2C_GPIO
 	tristate "GPIO-based bitbanging I2C"
@@ -789,7 +798,7 @@
 
 config I2C_ELEKTOR
 	tristate "Elektor ISA card"
-	depends on ISA && BROKEN_ON_SMP
+	depends on ISA && HAS_IOPORT && BROKEN_ON_SMP
 	select I2C_ALGOPCF
 	help
 	  This supports the PCF8584 ISA bus I2C adapter.  Say Y if you own
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/Makefile linux-libre-3.2-gnu/drivers/i2c/busses/Makefile
--- linux-libre-3.1-gnu/drivers/i2c/busses/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,10 @@
 obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
 obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
 obj-$(CONFIG_I2C_DAVINCI)	+= i2c-davinci.o
-obj-$(CONFIG_I2C_DESIGNWARE)	+= i2c-designware.o
+obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM)	+= i2c-designware-platform.o
+i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o
+obj-$(CONFIG_I2C_DESIGNWARE_PCI)	+= i2c-designware-pci.o
+i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o
 obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o
 obj-$(CONFIG_I2C_HIGHLANDER)	+= i2c-highlander.o
 obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
diff -druN linux-libre-3.1-gnu/drivers/i2c/busses/scx200_acb.c linux-libre-3.2-gnu/drivers/i2c/busses/scx200_acb.c
--- linux-libre-3.1-gnu/drivers/i2c/busses/scx200_acb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/busses/scx200_acb.c	2012-01-04 18:55:44.000000000 -0500
@@ -550,7 +550,7 @@
 	return 0;
 }
 
-static struct platform_driver scx200_pci_drv = {
+static struct platform_driver scx200_pci_driver = {
 	.driver = {
 		.name = "cs5535-smb",
 		.owner = THIS_MODULE,
@@ -593,14 +593,14 @@
 		return 0;
 
 	/* No ISA devices; register the platform driver for PCI-based devices */
-	return platform_driver_register(&scx200_pci_drv);
+	return platform_driver_register(&scx200_pci_driver);
 }
 
 static void __exit scx200_acb_cleanup(void)
 {
 	struct scx200_acb_iface *iface;
 
-	platform_driver_unregister(&scx200_pci_drv);
+	platform_driver_unregister(&scx200_pci_driver);
 
 	mutex_lock(&scx200_acb_list_mutex);
 	while ((iface = scx200_acb_list) != NULL) {
diff -druN linux-libre-3.1-gnu/drivers/i2c/i2c-boardinfo.c linux-libre-3.2-gnu/drivers/i2c/i2c-boardinfo.c
--- linux-libre-3.1-gnu/drivers/i2c/i2c-boardinfo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/i2c-boardinfo.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/rwsem.h>
 
 #include "i2c-core.h"
diff -druN linux-libre-3.1-gnu/drivers/i2c/i2c-core.c linux-libre-3.2-gnu/drivers/i2c/i2c-core.c
--- linux-libre-3.1-gnu/drivers/i2c/i2c-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/i2c-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -539,8 +539,10 @@
 	client->dev.type = &i2c_client_type;
 	client->dev.of_node = info->of_node;
 
+	/* For 10-bit clients, add an arbitrary offset to avoid collisions */
 	dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
-		     client->addr);
+		     client->addr | ((client->flags & I2C_CLIENT_TEN)
+				     ? 0xa000 : 0));
 	status = device_register(&client->dev);
 	if (status)
 		goto out_err;
diff -druN linux-libre-3.1-gnu/drivers/i2c/i2c-dev.c linux-libre-3.2-gnu/drivers/i2c/i2c-dev.c
--- linux-libre-3.1-gnu/drivers/i2c/i2c-dev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/i2c/i2c-dev.c	2012-01-04 18:55:44.000000000 -0500
@@ -579,7 +579,7 @@
 	return 0;
 }
 
-int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
+static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
 			 void *data)
 {
 	struct device *dev = data;
diff -druN linux-libre-3.1-gnu/drivers/ide/at91_ide.c linux-libre-3.2-gnu/drivers/ide/at91_ide.c
--- linux-libre-3.1-gnu/drivers/ide/at91_ide.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/at91_ide.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/platform_device.h>
 
 #include <mach/board.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
 #include <mach/at91sam9_smc.h>
 
 #define DRV_NAME "at91_ide"
diff -druN linux-libre-3.1-gnu/drivers/ide/au1xxx-ide.c linux-libre-3.2-gnu/drivers/ide/au1xxx-ide.c
--- linux-libre-3.1-gnu/drivers/ide/au1xxx-ide.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/au1xxx-ide.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,13 +36,17 @@
 #include <linux/ide.h>
 #include <linux/scatterlist.h>
 
-#include <asm/mach-au1x00/au1xxx.h>
+#include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
 #include <asm/mach-au1x00/au1xxx_ide.h>
 
 #define DRV_NAME	"au1200-ide"
 #define DRV_AUTHOR	"Enrico Walther <enrico.walther@amd.com> / Pete Popov <ppopov@embeddedalley.com>"
 
+#ifndef IDE_REG_SHIFT
+#define IDE_REG_SHIFT 5
+#endif
+
 /* enable the burstmode in the dbdma */
 #define IDE_AU1XXX_BURSTMODE	1
 
@@ -317,10 +321,11 @@
 }
 #endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */
 
-static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 devwidth, u32 flags)
+static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize,
+				 u32 devwidth, u32 flags, u32 regbase)
 {
 	dev->dev_id          = dev_id;
-	dev->dev_physaddr    = (u32)IDE_PHYS_ADDR;
+	dev->dev_physaddr    = CPHYSADDR(regbase);
 	dev->dev_intlevel    = 0;
 	dev->dev_intpolarity = 0;
 	dev->dev_tsize       = tsize;
@@ -344,7 +349,7 @@
 	dbdev_tab_t source_dev_tab, target_dev_tab;
 	u32 dev_id, tsize, devwidth, flags;
 
-	dev_id	 = IDE_DDMA_REQ;
+	dev_id	 = hwif->ddma_id;
 
 	tsize    =  8; /*  1 */
 	devwidth = 32; /* 16 */
@@ -356,20 +361,17 @@
 #endif
 
 	/* setup dev_tab for tx channel */
-	auide_init_dbdma_dev( &source_dev_tab,
-			      dev_id,
-			      tsize, devwidth, DEV_FLAGS_OUT | flags);
+	auide_init_dbdma_dev(&source_dev_tab, dev_id, tsize, devwidth,
+			     DEV_FLAGS_OUT | flags, auide->regbase);
  	auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
 
-	auide_init_dbdma_dev( &source_dev_tab,
-			      dev_id,
-			      tsize, devwidth, DEV_FLAGS_IN | flags);
+	auide_init_dbdma_dev(&source_dev_tab, dev_id, tsize, devwidth,
+			     DEV_FLAGS_IN | flags, auide->regbase);
  	auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
 	
 	/* We also need to add a target device for the DMA */
-	auide_init_dbdma_dev( &target_dev_tab,
-			      (u32)DSCR_CMD0_ALWAYS,
-			      tsize, devwidth, DEV_FLAGS_ANYUSE);
+	auide_init_dbdma_dev(&target_dev_tab, (u32)DSCR_CMD0_ALWAYS, tsize,
+			     devwidth, DEV_FLAGS_ANYUSE, auide->regbase);
 	auide->target_dev_id = au1xxx_ddma_add_device(&target_dev_tab);	
  
 	/* Get a channel for TX */
@@ -411,14 +413,12 @@
 #endif
 
 	/* setup dev_tab for tx channel */
-	auide_init_dbdma_dev( &source_dev_tab,
-			      (u32)DSCR_CMD0_ALWAYS,
-			      8, 32, DEV_FLAGS_OUT | flags);
+	auide_init_dbdma_dev(&source_dev_tab, (u32)DSCR_CMD0_ALWAYS, 8, 32,
+			     DEV_FLAGS_OUT | flags, auide->regbase);
  	auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
 
-	auide_init_dbdma_dev( &source_dev_tab,
-			      (u32)DSCR_CMD0_ALWAYS,
-			      8, 32, DEV_FLAGS_IN | flags);
+	auide_init_dbdma_dev(&source_dev_tab, (u32)DSCR_CMD0_ALWAYS, 8, 32,
+			     DEV_FLAGS_IN | flags, auide->regbase);
  	auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
 	
 	/* Get a channel for TX */
@@ -540,6 +540,14 @@
 		goto out;
 	}
 
+	res = platform_get_resource(dev, IORESOURCE_DMA, 0);
+	if (!res) {
+		pr_debug("%s: no DDMA ID resource\n", DRV_NAME);
+		ret = -ENODEV;
+		goto out;
+	}
+	ahwif->ddma_id = res->start;
+
 	memset(&hw, 0, sizeof(hw));
 	auide_setup_ports(&hw, ahwif);
 	hw.irq = ahwif->irq;
diff -druN linux-libre-3.1-gnu/drivers/ide/buddha.c linux-libre-3.2-gnu/drivers/ide/buddha.c
--- linux-libre-3.1-gnu/drivers/ide/buddha.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/buddha.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/zorro.h>
 #include <linux/ide.h>
 #include <linux/init.h>
+#include <linux/module.h>
 
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
diff -druN linux-libre-3.1-gnu/drivers/ide/cmd640.c linux-libre-3.2-gnu/drivers/ide/cmd640.c
--- linux-libre-3.1-gnu/drivers/ide/cmd640.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/cmd640.c	2012-01-04 18:55:44.000000000 -0500
@@ -105,6 +105,7 @@
 #include <linux/delay.h>
 #include <linux/ide.h>
 #include <linux/init.h>
+#include <linux/module.h>
 
 #include <asm/io.h>
 
diff -druN linux-libre-3.1-gnu/drivers/ide/cy82c693.c linux-libre-3.2-gnu/drivers/ide/cy82c693.c
--- linux-libre-3.1-gnu/drivers/ide/cy82c693.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/cy82c693.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer
  *  Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator
- *  Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz
+ *  Copyright (C) 2007-2011 Bartlomiej Zolnierkiewicz
  *
  * CYPRESS CY82C693 chipset IDE controller
  *
@@ -90,7 +90,7 @@
 	u8 time_16, time_8;
 
 	/* select primary or secondary channel */
-	if (hwif->index > 0) {  /* drive is on the secondary channel */
+	if (drive->dn > 1) {  /* drive is on the secondary channel */
 		dev = pci_get_slot(dev->bus, dev->devfn+1);
 		if (!dev) {
 			printk(KERN_ERR "%s: tune_drive: "
@@ -141,7 +141,7 @@
 		pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, time_16);
 		pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, time_8);
 	}
-	if (hwif->index > 0)
+	if (drive->dn > 1)
 		pci_dev_put(dev);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/ide/icside.c linux-libre-3.2-gnu/drivers/ide/icside.c
--- linux-libre-3.1-gnu/drivers/ide/icside.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/icside.c	2012-01-04 18:55:44.000000000 -0500
@@ -521,8 +521,8 @@
 	if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
 		d.init_dma = icside_dma_init;
 		d.port_ops = &icside_v6_port_ops;
+	} else
 		d.dma_ops = NULL;
-	}
 
 	ret = ide_host_register(host, &d, hws);
 	if (ret)
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-acpi.c linux-libre-3.2-gnu/drivers/ide/ide-acpi.c
--- linux-libre-3.1-gnu/drivers/ide/ide-acpi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-acpi.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/ide.h>
 #include <linux/pci.h>
 #include <linux/dmi.h>
+#include <linux/module.h>
 
 #include <acpi/acpi_bus.h>
 
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-atapi.c linux-libre-3.2-gnu/drivers/ide/ide-atapi.c
--- linux-libre-3.1-gnu/drivers/ide/ide-atapi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-atapi.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,7 @@
 #include <linux/kernel.h>
 #include <linux/cdrom.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 #include <linux/ide.h>
 #include <linux/scatterlist.h>
 #include <linux/gfp.h>
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-cd.c linux-libre-3.2-gnu/drivers/ide/ide-cd.c
--- linux-libre-3.1-gnu/drivers/ide/ide-cd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-cd.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,6 @@
 /* For SCSI -> ATAPI command conversion */
 #include <scsi/scsi.h>
 
-#include <linux/irq.h>
 #include <linux/io.h>
 #include <asm/byteorder.h>
 #include <linux/uaccess.h>
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-disk_proc.c linux-libre-3.2-gnu/drivers/ide/ide-disk_proc.c
--- linux-libre-3.1-gnu/drivers/ide/ide-disk_proc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-disk_proc.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 #include <linux/kernel.h>
 #include <linux/ide.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/seq_file.h>
 
 #include "ide-disk.h"
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-dma.c linux-libre-3.2-gnu/drivers/ide/ide-dma.c
--- linux-libre-3.1-gnu/drivers/ide/ide-dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/types.h>
 #include <linux/gfp.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/ide.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-dma-sff.c linux-libre-3.2-gnu/drivers/ide/ide-dma-sff.c
--- linux-libre-3.1-gnu/drivers/ide/ide-dma-sff.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-dma-sff.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/ide.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-eh.c linux-libre-3.2-gnu/drivers/ide/ide-eh.c
--- linux-libre-3.1-gnu/drivers/ide/ide-eh.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-eh.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/ide.h>
 #include <linux/delay.h>
 
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-floppy.c linux-libre-3.2-gnu/drivers/ide/ide-floppy.c
--- linux-libre-3.1-gnu/drivers/ide/ide-floppy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-floppy.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,7 +35,6 @@
 #include <scsi/scsi_ioctl.h>
 
 #include <asm/byteorder.h>
-#include <linux/irq.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <asm/unaligned.h>
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-floppy_proc.c linux-libre-3.2-gnu/drivers/ide/ide-floppy_proc.c
--- linux-libre-3.1-gnu/drivers/ide/ide-floppy_proc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-floppy_proc.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,5 @@
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/ide.h>
 #include <linux/seq_file.h>
 
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-ioctls.c linux-libre-3.2-gnu/drivers/ide/ide-ioctls.c
--- linux-libre-3.1-gnu/drivers/ide/ide-ioctls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-ioctls.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,7 @@
  * IDE ioctls handling.
  */
 
+#include <linux/export.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <linux/slab.h>
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-io-std.c linux-libre-3.2-gnu/drivers/ide/ide-io-std.c
--- linux-libre-3.1-gnu/drivers/ide/ide-io-std.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-io-std.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,6 @@
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/ide.h>
 
 #if defined(CONFIG_ARM) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) || \
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-legacy.c linux-libre-3.2-gnu/drivers/ide/ide-legacy.c
--- linux-libre-3.1-gnu/drivers/ide/ide-legacy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-legacy.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,5 @@
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/ide.h>
 
 static void ide_legacy_init_one(struct ide_hw **hws, struct ide_hw *hw,
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-lib.c linux-libre-3.2-gnu/drivers/ide/ide-lib.c
--- linux-libre-3.1-gnu/drivers/ide/ide-lib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-lib.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/ide.h>
 #include <linux/bitops.h>
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-pnp.c linux-libre-3.2-gnu/drivers/ide/ide-pnp.c
--- linux-libre-3.1-gnu/drivers/ide/ide-pnp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-pnp.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/pnp.h>
 #include <linux/ide.h>
+#include <linux/module.h>
 
 #define DRV_NAME "ide-pnp"
 
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-tape.c linux-libre-3.2-gnu/drivers/ide/ide-tape.c
--- linux-libre-3.1-gnu/drivers/ide/ide-tape.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-tape.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,7 +41,6 @@
 #include <scsi/scsi.h>
 
 #include <asm/byteorder.h>
-#include <linux/irq.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <asm/unaligned.h>
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-taskfile.c linux-libre-3.2-gnu/drivers/ide/ide-taskfile.c
--- linux-libre-3.1-gnu/drivers/ide/ide-taskfile.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-taskfile.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
diff -druN linux-libre-3.1-gnu/drivers/ide/ide-xfer-mode.c linux-libre-3.2-gnu/drivers/ide/ide-xfer-mode.c
--- linux-libre-3.1-gnu/drivers/ide/ide-xfer-mode.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/ide-xfer-mode.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/ide.h>
 #include <linux/bitops.h>
diff -druN linux-libre-3.1-gnu/drivers/ide/Kconfig linux-libre-3.2-gnu/drivers/ide/Kconfig
--- linux-libre-3.1-gnu/drivers/ide/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -677,19 +677,19 @@
 
 config BLK_DEV_IDE_AU1XXX
        bool "IDE for AMD Alchemy Au1200"
-       depends on SOC_AU1200
+       depends on MIPS_ALCHEMY
        select IDE_XFER_MODE
 choice
        prompt "IDE Mode for AMD Alchemy Au1200"
-       default CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
-       depends on SOC_AU1200 && BLK_DEV_IDE_AU1XXX
+       default BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+       depends on BLK_DEV_IDE_AU1XXX
 
 config BLK_DEV_IDE_AU1XXX_PIO_DBDMA
        bool "PIO+DbDMA IDE for AMD Alchemy Au1200"
 
 config BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
        bool "MDMA2+DbDMA IDE for AMD Alchemy Au1200"
-       depends on SOC_AU1200 && BLK_DEV_IDE_AU1XXX
+       depends on BLK_DEV_IDE_AU1XXX
 endchoice
 
 config BLK_DEV_IDE_TX4938
diff -druN linux-libre-3.1-gnu/drivers/ide/macide.c linux-libre-3.2-gnu/drivers/ide/macide.c
--- linux-libre-3.1-gnu/drivers/ide/macide.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/macide.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/ide.h>
+#include <linux/module.h>
 
 #include <asm/macintosh.h>
 #include <asm/macints.h>
diff -druN linux-libre-3.1-gnu/drivers/ide/piix.c linux-libre-3.2-gnu/drivers/ide/piix.c
--- linux-libre-3.1-gnu/drivers/ide/piix.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/piix.c	2012-01-04 18:55:44.000000000 -0500
@@ -331,7 +331,7 @@
 		.udma_mask	= udma,			\
 	}
 
-#define DECLARE_ICH_DEV(udma) \
+#define DECLARE_ICH_DEV(mwdma, udma) \
 	{ \
 		.name		= DRV_NAME, \
 		.init_chipset	= init_chipset_ich, \
@@ -340,7 +340,7 @@
 		.port_ops	= &ich_port_ops, \
 		.pio_mask	= ATA_PIO4, \
 		.swdma_mask	= ATA_SWDMA2_ONLY, \
-		.mwdma_mask	= ATA_MWDMA12_ONLY, \
+		.mwdma_mask	= mwdma, \
 		.udma_mask	= udma, \
 	}
 
@@ -362,13 +362,15 @@
 	/* 2: PIIX4 */
 	DECLARE_PIIX_DEV(ATA_UDMA2),
 	/* 3: ICH0 */
-	DECLARE_ICH_DEV(ATA_UDMA2),
+	DECLARE_ICH_DEV(ATA_MWDMA12_ONLY, ATA_UDMA2),
 	/* 4: ICH */
-	DECLARE_ICH_DEV(ATA_UDMA4),
+	DECLARE_ICH_DEV(ATA_MWDMA12_ONLY, ATA_UDMA4),
 	/* 5: PIIX4 */
 	DECLARE_PIIX_DEV(ATA_UDMA4),
-	/* 6: ICH[2-7]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */
-	DECLARE_ICH_DEV(ATA_UDMA5),
+	/* 6: ICH[2-6]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */
+	DECLARE_ICH_DEV(ATA_MWDMA12_ONLY, ATA_UDMA5),
+	/* 7: ICH7/7-R, no MWDMA1 */
+	DECLARE_ICH_DEV(ATA_MWDMA2_ONLY, ATA_UDMA5),
 };
 
 /**
@@ -438,9 +440,9 @@
 #endif
 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2),      6 },
 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19),    6 },
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21),    6 },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21),    7 },
 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1),  6 },
-	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18),    6 },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18),    7 },
 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6),     6 },
 	{ 0, },
 };
diff -druN linux-libre-3.1-gnu/drivers/ide/pmac.c linux-libre-3.2-gnu/drivers/ide/pmac.c
--- linux-libre-3.1-gnu/drivers/ide/pmac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/pmac.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/delay.h>
 #include <linux/ide.h>
 #include <linux/notifier.h>
+#include <linux/module.h>
 #include <linux/reboot.h>
 #include <linux/pci.h>
 #include <linux/adb.h>
diff -druN linux-libre-3.1-gnu/drivers/ide/q40ide.c linux-libre-3.2-gnu/drivers/ide/q40ide.c
--- linux-libre-3.1-gnu/drivers/ide/q40ide.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/q40ide.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
 #include <linux/ide.h>
+#include <linux/module.h>
 
 #include <asm/ide.h>
 
diff -druN linux-libre-3.1-gnu/drivers/ide/setup-pci.c linux-libre-3.2-gnu/drivers/ide/setup-pci.c
--- linux-libre-3.1-gnu/drivers/ide/setup-pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/setup-pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
diff -druN linux-libre-3.1-gnu/drivers/ide/tc86c001.c linux-libre-3.2-gnu/drivers/ide/tc86c001.c
--- linux-libre-3.1-gnu/drivers/ide/tc86c001.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/tc86c001.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/ide.h>
+#include <linux/module.h>
 
 #define DRV_NAME "tc86c001"
 
diff -druN linux-libre-3.1-gnu/drivers/ide/triflex.c linux-libre-3.2-gnu/drivers/ide/triflex.c
--- linux-libre-3.1-gnu/drivers/ide/triflex.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/ide/triflex.c	2012-01-04 18:55:44.000000000 -0500
@@ -113,12 +113,26 @@
 };
 MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);
 
+#ifdef CONFIG_PM
+static int triflex_ide_pci_suspend(struct pci_dev *dev, pm_message_t state)
+{
+	/*
+	 * We must not disable or powerdown the device.
+	 * APM bios refuses to suspend if IDE is not accessible.
+	 */
+	pci_save_state(dev);
+	return 0;
+}
+#else
+#define triflex_ide_pci_suspend NULL
+#endif
+
 static struct pci_driver triflex_pci_driver = {
 	.name		= "TRIFLEX_IDE",
 	.id_table	= triflex_pci_tbl,
 	.probe		= triflex_init_one,
 	.remove		= ide_pci_remove,
-	.suspend	= ide_pci_suspend,
+	.suspend	= triflex_ide_pci_suspend,
 	.resume		= ide_pci_resume,
 };
 
diff -druN linux-libre-3.1-gnu/drivers/idle/intel_idle.c linux-libre-3.2-gnu/drivers/idle/intel_idle.c
--- linux-libre-3.1-gnu/drivers/idle/intel_idle.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/idle/intel_idle.c	2012-01-04 18:55:44.000000000 -0500
@@ -61,6 +61,7 @@
 #include <linux/sched.h>
 #include <linux/notifier.h>
 #include <linux/cpu.h>
+#include <linux/module.h>
 #include <asm/mwait.h>
 #include <asm/msr.h>
 
@@ -81,7 +82,8 @@
 static unsigned int lapic_timer_reliable_states = (1 << 1);	 /* Default to only C1 */
 
 static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
-static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
+static int intel_idle(struct cpuidle_device *dev,
+			struct cpuidle_driver *drv, int index);
 
 static struct cpuidle_state *cpuidle_state_table;
 
@@ -109,7 +111,6 @@
 	{ /* MWAIT C1 */
 		.name = "C1-NHM",
 		.desc = "MWAIT 0x00",
-		.driver_data = (void *) 0x00,
 		.flags = CPUIDLE_FLAG_TIME_VALID,
 		.exit_latency = 3,
 		.target_residency = 6,
@@ -117,7 +118,6 @@
 	{ /* MWAIT C2 */
 		.name = "C3-NHM",
 		.desc = "MWAIT 0x10",
-		.driver_data = (void *) 0x10,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 20,
 		.target_residency = 80,
@@ -125,7 +125,6 @@
 	{ /* MWAIT C3 */
 		.name = "C6-NHM",
 		.desc = "MWAIT 0x20",
-		.driver_data = (void *) 0x20,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 200,
 		.target_residency = 800,
@@ -137,7 +136,6 @@
 	{ /* MWAIT C1 */
 		.name = "C1-SNB",
 		.desc = "MWAIT 0x00",
-		.driver_data = (void *) 0x00,
 		.flags = CPUIDLE_FLAG_TIME_VALID,
 		.exit_latency = 1,
 		.target_residency = 1,
@@ -145,7 +143,6 @@
 	{ /* MWAIT C2 */
 		.name = "C3-SNB",
 		.desc = "MWAIT 0x10",
-		.driver_data = (void *) 0x10,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 80,
 		.target_residency = 211,
@@ -153,7 +150,6 @@
 	{ /* MWAIT C3 */
 		.name = "C6-SNB",
 		.desc = "MWAIT 0x20",
-		.driver_data = (void *) 0x20,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 104,
 		.target_residency = 345,
@@ -161,7 +157,6 @@
 	{ /* MWAIT C4 */
 		.name = "C7-SNB",
 		.desc = "MWAIT 0x30",
-		.driver_data = (void *) 0x30,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 109,
 		.target_residency = 345,
@@ -173,7 +168,6 @@
 	{ /* MWAIT C1 */
 		.name = "C1-ATM",
 		.desc = "MWAIT 0x00",
-		.driver_data = (void *) 0x00,
 		.flags = CPUIDLE_FLAG_TIME_VALID,
 		.exit_latency = 1,
 		.target_residency = 4,
@@ -181,7 +175,6 @@
 	{ /* MWAIT C2 */
 		.name = "C2-ATM",
 		.desc = "MWAIT 0x10",
-		.driver_data = (void *) 0x10,
 		.flags = CPUIDLE_FLAG_TIME_VALID,
 		.exit_latency = 20,
 		.target_residency = 80,
@@ -190,7 +183,6 @@
 	{ /* MWAIT C4 */
 		.name = "C4-ATM",
 		.desc = "MWAIT 0x30",
-		.driver_data = (void *) 0x30,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 100,
 		.target_residency = 400,
@@ -199,23 +191,55 @@
 	{ /* MWAIT C6 */
 		.name = "C6-ATM",
 		.desc = "MWAIT 0x52",
-		.driver_data = (void *) 0x52,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 140,
 		.target_residency = 560,
 		.enter = &intel_idle },
 };
 
+static int get_driver_data(int cstate)
+{
+	int driver_data;
+	switch (cstate) {
+
+	case 1:	/* MWAIT C1 */
+		driver_data = 0x00;
+		break;
+	case 2:	/* MWAIT C2 */
+		driver_data = 0x10;
+		break;
+	case 3:	/* MWAIT C3 */
+		driver_data = 0x20;
+		break;
+	case 4:	/* MWAIT C4 */
+		driver_data = 0x30;
+		break;
+	case 5:	/* MWAIT C5 */
+		driver_data = 0x40;
+		break;
+	case 6:	/* MWAIT C6 */
+		driver_data = 0x52;
+		break;
+	default:
+		driver_data = 0x00;
+	}
+	return driver_data;
+}
+
 /**
  * intel_idle
  * @dev: cpuidle_device
- * @state: cpuidle state
+ * @drv: cpuidle driver
+ * @index: index of cpuidle state
  *
  */
-static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
+static int intel_idle(struct cpuidle_device *dev,
+		struct cpuidle_driver *drv, int index)
 {
 	unsigned long ecx = 1; /* break on interrupt flag */
-	unsigned long eax = (unsigned long)cpuidle_get_statedata(state);
+	struct cpuidle_state *state = &drv->states[index];
+	struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+	unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage);
 	unsigned int cstate;
 	ktime_t kt_before, kt_after;
 	s64 usec_delta;
@@ -256,7 +280,10 @@
 	if (!(lapic_timer_reliable_states & (1 << (cstate))))
 		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
 
-	return usec_delta;
+	/* Update cpuidle counters */
+	dev->last_residency = (int)usec_delta;
+
+	return index;
 }
 
 static void __setup_broadcast_timer(void *arg)
@@ -397,6 +424,60 @@
 	return;
 }
 /*
+ * intel_idle_cpuidle_driver_init()
+ * allocate, initialize cpuidle_states
+ */
+static int intel_idle_cpuidle_driver_init(void)
+{
+	int cstate;
+	struct cpuidle_driver *drv = &intel_idle_driver;
+
+	drv->state_count = 1;
+
+	for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) {
+		int num_substates;
+
+		if (cstate > max_cstate) {
+			printk(PREFIX "max_cstate %d reached\n",
+				max_cstate);
+			break;
+		}
+
+		/* does the state exist in CPUID.MWAIT? */
+		num_substates = (mwait_substates >> ((cstate) * 4))
+					& MWAIT_SUBSTATE_MASK;
+		if (num_substates == 0)
+			continue;
+		/* is the state not enabled? */
+		if (cpuidle_state_table[cstate].enter == NULL) {
+			/* does the driver not know about the state? */
+			if (*cpuidle_state_table[cstate].name == '\0')
+				pr_debug(PREFIX "unaware of model 0x%x"
+					" MWAIT %d please"
+					" contact lenb@kernel.org",
+				boot_cpu_data.x86_model, cstate);
+			continue;
+		}
+
+		if ((cstate > 2) &&
+			!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
+			mark_tsc_unstable("TSC halts in idle"
+					" states deeper than C2");
+
+		drv->states[drv->state_count] =	/* structure copy */
+			cpuidle_state_table[cstate];
+
+		drv->state_count += 1;
+	}
+
+	if (auto_demotion_disable_flags)
+		smp_call_function(auto_demotion_disable, NULL, 1);
+
+	return 0;
+}
+
+
+/*
  * intel_idle_cpuidle_devices_init()
  * allocate, initialize, register cpuidle_devices
  */
@@ -430,22 +511,11 @@
 				continue;
 			/* is the state not enabled? */
 			if (cpuidle_state_table[cstate].enter == NULL) {
-				/* does the driver not know about the state? */
-				if (*cpuidle_state_table[cstate].name == '\0')
-					pr_debug(PREFIX "unaware of model 0x%x"
-						" MWAIT %d please"
-						" contact lenb@kernel.org",
-					boot_cpu_data.x86_model, cstate);
 				continue;
 			}
 
-			if ((cstate > 2) &&
-				!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
-				mark_tsc_unstable("TSC halts in idle"
-					" states deeper than C2");
-
-			dev->states[dev->state_count] =	/* structure copy */
-				cpuidle_state_table[cstate];
+			dev->states_usage[dev->state_count].driver_data =
+				(void *)get_driver_data(cstate);
 
 			dev->state_count += 1;
 		}
@@ -458,8 +528,6 @@
 			return -EIO;
 		}
 	}
-	if (auto_demotion_disable_flags)
-		smp_call_function(auto_demotion_disable, NULL, 1);
 
 	return 0;
 }
@@ -477,6 +545,7 @@
 	if (retval)
 		return retval;
 
+	intel_idle_cpuidle_driver_init();
 	retval = cpuidle_register_driver(&intel_idle_driver);
 	if (retval) {
 		printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/addr.c linux-libre-3.2-gnu/drivers/infiniband/core/addr.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/addr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/addr.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/inetdevice.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
+#include <linux/module.h>
 #include <net/arp.h>
 #include <net/neighbour.h>
 #include <net/route.h>
@@ -215,7 +216,9 @@
 
 	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev);
 	if (!neigh || !(neigh->nud_state & NUD_VALID)) {
+		rcu_read_lock();
 		neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
+		rcu_read_unlock();
 		ret = -ENODATA;
 		if (neigh)
 			goto release;
@@ -273,15 +276,16 @@
 		goto put;
 	}
 
+	rcu_read_lock();
 	neigh = dst_get_neighbour(dst);
 	if (!neigh || !(neigh->nud_state & NUD_VALID)) {
 		if (neigh)
 			neigh_event_send(neigh, NULL);
 		ret = -ENODATA;
-		goto put;
+	} else {
+		ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
 	}
-
-	ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
+	rcu_read_unlock();
 put:
 	dst_release(dst);
 	return ret;
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/cma.c linux-libre-3.2-gnu/drivers/infiniband/core/cma.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/cma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/cma.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
 #include <linux/idr.h>
 #include <linux/inetdevice.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include <net/tcp.h>
 #include <net/ipv6.h>
@@ -81,6 +82,7 @@
 static DEFINE_IDR(tcp_ps);
 static DEFINE_IDR(udp_ps);
 static DEFINE_IDR(ipoib_ps);
+static DEFINE_IDR(ib_ps);
 
 struct cma_device {
 	struct list_head	list;
@@ -1179,6 +1181,15 @@
 	event->param.conn.qp_num = req_data->remote_qpn;
 }
 
+static int cma_check_req_qp_type(struct rdma_cm_id *id, struct ib_cm_event *ib_event)
+{
+	return (((ib_event->event == IB_CM_REQ_RECEIVED) ||
+		 (ib_event->param.req_rcvd.qp_type == id->qp_type)) ||
+		((ib_event->event == IB_CM_SIDR_REQ_RECEIVED) &&
+		 (id->qp_type == IB_QPT_UD)) ||
+		(!id->qp_type));
+}
+
 static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
 {
 	struct rdma_id_private *listen_id, *conn_id;
@@ -1186,13 +1197,16 @@
 	int offset, ret;
 
 	listen_id = cm_id->context;
+	if (!cma_check_req_qp_type(&listen_id->id, ib_event))
+		return -EINVAL;
+
 	if (cma_disable_callback(listen_id, RDMA_CM_LISTEN))
 		return -ECONNABORTED;
 
 	memset(&event, 0, sizeof event);
 	offset = cma_user_data_offset(listen_id->id.ps);
 	event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
-	if (listen_id->id.qp_type == IB_QPT_UD) {
+	if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED) {
 		conn_id = cma_new_udp_id(&listen_id->id, ib_event);
 		event.param.ud.private_data = ib_event->private_data + offset;
 		event.param.ud.private_data_len =
@@ -1328,6 +1342,8 @@
 		switch (iw_event->status) {
 		case 0:
 			event.event = RDMA_CM_EVENT_ESTABLISHED;
+			event.param.conn.initiator_depth = iw_event->ird;
+			event.param.conn.responder_resources = iw_event->ord;
 			break;
 		case -ECONNRESET:
 		case -ECONNREFUSED:
@@ -1343,6 +1359,8 @@
 		break;
 	case IW_CM_EVENT_ESTABLISHED:
 		event.event = RDMA_CM_EVENT_ESTABLISHED;
+		event.param.conn.initiator_depth = iw_event->ird;
+		event.param.conn.responder_resources = iw_event->ord;
 		break;
 	default:
 		BUG_ON(1);
@@ -1433,8 +1451,8 @@
 	event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
 	event.param.conn.private_data = iw_event->private_data;
 	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;
+	event.param.conn.initiator_depth = iw_event->ird;
+	event.param.conn.responder_resources = iw_event->ord;
 
 	/*
 	 * Protect against the user destroying conn_id from another thread
@@ -2234,6 +2252,9 @@
 	case RDMA_PS_IPOIB:
 		ps = &ipoib_ps;
 		break;
+	case RDMA_PS_IB:
+		ps = &ib_ps;
+		break;
 	default:
 		return -EPROTONOSUPPORT;
 	}
@@ -2492,6 +2513,9 @@
 
 	req.private_data_len = sizeof(struct cma_hdr) +
 			       conn_param->private_data_len;
+	if (req.private_data_len < conn_param->private_data_len)
+		return -EINVAL;
+
 	req.private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
 	if (!req.private_data)
 		return -ENOMEM;
@@ -2541,6 +2565,9 @@
 	memset(&req, 0, sizeof req);
 	offset = cma_user_data_offset(id_priv->id.ps);
 	req.private_data_len = offset + conn_param->private_data_len;
+	if (req.private_data_len < conn_param->private_data_len)
+		return -EINVAL;
+
 	private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
 	if (!private_data)
 		return -ENOMEM;
@@ -2569,7 +2596,7 @@
 	req.service_id = cma_get_service_id(id_priv->id.ps,
 					    (struct sockaddr *) &route->addr.dst_addr);
 	req.qp_num = id_priv->qp_num;
-	req.qp_type = IB_QPT_RC;
+	req.qp_type = id_priv->id.qp_type;
 	req.starting_psn = id_priv->seq_num;
 	req.responder_resources = conn_param->responder_resources;
 	req.initiator_depth = conn_param->initiator_depth;
@@ -2616,14 +2643,16 @@
 	if (ret)
 		goto out;
 
-	iw_param.ord = conn_param->initiator_depth;
-	iw_param.ird = conn_param->responder_resources;
-	iw_param.private_data = conn_param->private_data;
-	iw_param.private_data_len = conn_param->private_data_len;
-	if (id_priv->id.qp)
+	if (conn_param) {
+		iw_param.ord = conn_param->initiator_depth;
+		iw_param.ird = conn_param->responder_resources;
+		iw_param.private_data = conn_param->private_data;
+		iw_param.private_data_len = conn_param->private_data_len;
+		iw_param.qpn = id_priv->id.qp ? id_priv->qp_num : conn_param->qp_num;
+	} else {
+		memset(&iw_param, 0, sizeof iw_param);
 		iw_param.qpn = id_priv->qp_num;
-	else
-		iw_param.qpn = conn_param->qp_num;
+	}
 	ret = iw_cm_connect(cm_id, &iw_param);
 out:
 	if (ret) {
@@ -2765,14 +2794,20 @@
 
 	switch (rdma_node_get_transport(id->device->node_type)) {
 	case RDMA_TRANSPORT_IB:
-		if (id->qp_type == IB_QPT_UD)
-			ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
-						conn_param->private_data,
-						conn_param->private_data_len);
-		else if (conn_param)
-			ret = cma_accept_ib(id_priv, conn_param);
-		else
-			ret = cma_rep_recv(id_priv);
+		if (id->qp_type == IB_QPT_UD) {
+			if (conn_param)
+				ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
+							conn_param->private_data,
+							conn_param->private_data_len);
+			else
+				ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
+							NULL, 0);
+		} else {
+			if (conn_param)
+				ret = cma_accept_ib(id_priv, conn_param);
+			else
+				ret = cma_rep_recv(id_priv);
+		}
 		break;
 	case RDMA_TRANSPORT_IWARP:
 		ret = cma_accept_iw(id_priv, conn_param);
@@ -3460,6 +3495,7 @@
 	idr_destroy(&tcp_ps);
 	idr_destroy(&udp_ps);
 	idr_destroy(&ipoib_ps);
+	idr_destroy(&ib_ps);
 }
 
 module_init(cma_init);
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/cm.c linux-libre-3.2-gnu/drivers/infiniband/core/cm.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/cm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/cm.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 #include <linux/completion.h>
 #include <linux/dma-mapping.h>
 #include <linux/device.h>
+#include <linux/module.h>
 #include <linux/err.h>
 #include <linux/idr.h>
 #include <linux/interrupt.h>
@@ -889,6 +890,8 @@
 		break;
 	case IB_CM_ESTABLISHED:
 		spin_unlock_irq(&cm_id_priv->lock);
+		if (cm_id_priv->qp_type == IB_QPT_XRC_TGT)
+			break;
 		ib_send_cm_dreq(cm_id, NULL, 0);
 		goto retest;
 	case IB_CM_DREQ_SENT:
@@ -1008,7 +1011,6 @@
 	req_msg->service_id = param->service_id;
 	req_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
 	cm_req_set_local_qpn(req_msg, cpu_to_be32(param->qp_num));
-	cm_req_set_resp_res(req_msg, param->responder_resources);
 	cm_req_set_init_depth(req_msg, param->initiator_depth);
 	cm_req_set_remote_resp_timeout(req_msg,
 				       param->remote_cm_response_timeout);
@@ -1017,12 +1019,16 @@
 	cm_req_set_starting_psn(req_msg, cpu_to_be32(param->starting_psn));
 	cm_req_set_local_resp_timeout(req_msg,
 				      param->local_cm_response_timeout);
-	cm_req_set_retry_count(req_msg, param->retry_count);
 	req_msg->pkey = param->primary_path->pkey;
 	cm_req_set_path_mtu(req_msg, param->primary_path->mtu);
-	cm_req_set_rnr_retry_count(req_msg, param->rnr_retry_count);
 	cm_req_set_max_cm_retries(req_msg, param->max_cm_retries);
-	cm_req_set_srq(req_msg, param->srq);
+
+	if (param->qp_type != IB_QPT_XRC_INI) {
+		cm_req_set_resp_res(req_msg, param->responder_resources);
+		cm_req_set_retry_count(req_msg, param->retry_count);
+		cm_req_set_rnr_retry_count(req_msg, param->rnr_retry_count);
+		cm_req_set_srq(req_msg, param->srq);
+	}
 
 	if (pri_path->hop_limit <= 1) {
 		req_msg->primary_local_lid = pri_path->slid;
@@ -1080,7 +1086,8 @@
 	if (!param->primary_path)
 		return -EINVAL;
 
-	if (param->qp_type != IB_QPT_RC && param->qp_type != IB_QPT_UC)
+	if (param->qp_type != IB_QPT_RC && param->qp_type != IB_QPT_UC &&
+	    param->qp_type != IB_QPT_XRC_INI)
 		return -EINVAL;
 
 	if (param->private_data &&
@@ -1601,18 +1608,24 @@
 	cm_format_mad_hdr(&rep_msg->hdr, CM_REP_ATTR_ID, cm_id_priv->tid);
 	rep_msg->local_comm_id = cm_id_priv->id.local_id;
 	rep_msg->remote_comm_id = cm_id_priv->id.remote_id;
-	cm_rep_set_local_qpn(rep_msg, cpu_to_be32(param->qp_num));
 	cm_rep_set_starting_psn(rep_msg, cpu_to_be32(param->starting_psn));
 	rep_msg->resp_resources = param->responder_resources;
-	rep_msg->initiator_depth = param->initiator_depth;
 	cm_rep_set_target_ack_delay(rep_msg,
 				    cm_id_priv->av.port->cm_dev->ack_delay);
 	cm_rep_set_failover(rep_msg, param->failover_accepted);
-	cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
 	cm_rep_set_rnr_retry_count(rep_msg, param->rnr_retry_count);
-	cm_rep_set_srq(rep_msg, param->srq);
 	rep_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
 
+	if (cm_id_priv->qp_type != IB_QPT_XRC_TGT) {
+		rep_msg->initiator_depth = param->initiator_depth;
+		cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
+		cm_rep_set_srq(rep_msg, param->srq);
+		cm_rep_set_local_qpn(rep_msg, cpu_to_be32(param->qp_num));
+	} else {
+		cm_rep_set_srq(rep_msg, 1);
+		cm_rep_set_local_eecn(rep_msg, cpu_to_be32(param->qp_num));
+	}
+
 	if (param->private_data && param->private_data_len)
 		memcpy(rep_msg->private_data, param->private_data,
 		       param->private_data_len);
@@ -1660,7 +1673,7 @@
 	cm_id_priv->initiator_depth = param->initiator_depth;
 	cm_id_priv->responder_resources = param->responder_resources;
 	cm_id_priv->rq_psn = cm_rep_get_starting_psn(rep_msg);
-	cm_id_priv->local_qpn = cm_rep_get_local_qpn(rep_msg);
+	cm_id_priv->local_qpn = cpu_to_be32(param->qp_num & 0xFFFFFF);
 
 out:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 	return ret;
@@ -1731,7 +1744,7 @@
 }
 EXPORT_SYMBOL(ib_send_cm_rtu);
 
-static void cm_format_rep_event(struct cm_work *work)
+static void cm_format_rep_event(struct cm_work *work, enum ib_qp_type qp_type)
 {
 	struct cm_rep_msg *rep_msg;
 	struct ib_cm_rep_event_param *param;
@@ -1740,7 +1753,7 @@
 	param = &work->cm_event.param.rep_rcvd;
 	param->remote_ca_guid = rep_msg->local_ca_guid;
 	param->remote_qkey = be32_to_cpu(rep_msg->local_qkey);
-	param->remote_qpn = be32_to_cpu(cm_rep_get_local_qpn(rep_msg));
+	param->remote_qpn = be32_to_cpu(cm_rep_get_qpn(rep_msg, qp_type));
 	param->starting_psn = be32_to_cpu(cm_rep_get_starting_psn(rep_msg));
 	param->responder_resources = rep_msg->initiator_depth;
 	param->initiator_depth = rep_msg->resp_resources;
@@ -1808,7 +1821,7 @@
 		return -EINVAL;
 	}
 
-	cm_format_rep_event(work);
+	cm_format_rep_event(work, cm_id_priv->qp_type);
 
 	spin_lock_irq(&cm_id_priv->lock);
 	switch (cm_id_priv->id.state) {
@@ -1823,7 +1836,7 @@
 
 	cm_id_priv->timewait_info->work.remote_id = rep_msg->local_comm_id;
 	cm_id_priv->timewait_info->remote_ca_guid = rep_msg->local_ca_guid;
-	cm_id_priv->timewait_info->remote_qpn = cm_rep_get_local_qpn(rep_msg);
+	cm_id_priv->timewait_info->remote_qpn = cm_rep_get_qpn(rep_msg, cm_id_priv->qp_type);
 
 	spin_lock(&cm.lock);
 	/* Check for duplicate REP. */
@@ -1850,7 +1863,7 @@
 
 	cm_id_priv->id.state = IB_CM_REP_RCVD;
 	cm_id_priv->id.remote_id = rep_msg->local_comm_id;
-	cm_id_priv->remote_qpn = cm_rep_get_local_qpn(rep_msg);
+	cm_id_priv->remote_qpn = cm_rep_get_qpn(rep_msg, cm_id_priv->qp_type);
 	cm_id_priv->initiator_depth = rep_msg->resp_resources;
 	cm_id_priv->responder_resources = rep_msg->initiator_depth;
 	cm_id_priv->sq_psn = cm_rep_get_starting_psn(rep_msg);
@@ -3492,7 +3505,8 @@
 		qp_attr->path_mtu = cm_id_priv->path_mtu;
 		qp_attr->dest_qp_num = be32_to_cpu(cm_id_priv->remote_qpn);
 		qp_attr->rq_psn = be32_to_cpu(cm_id_priv->rq_psn);
-		if (cm_id_priv->qp_type == IB_QPT_RC) {
+		if (cm_id_priv->qp_type == IB_QPT_RC ||
+		    cm_id_priv->qp_type == IB_QPT_XRC_TGT) {
 			*qp_attr_mask |= IB_QP_MAX_DEST_RD_ATOMIC |
 					 IB_QP_MIN_RNR_TIMER;
 			qp_attr->max_dest_rd_atomic =
@@ -3537,15 +3551,21 @@
 		if (cm_id_priv->id.lap_state == IB_CM_LAP_UNINIT) {
 			*qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN;
 			qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn);
-			if (cm_id_priv->qp_type == IB_QPT_RC) {
-				*qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
-						 IB_QP_RNR_RETRY |
+			switch (cm_id_priv->qp_type) {
+			case IB_QPT_RC:
+			case IB_QPT_XRC_INI:
+				*qp_attr_mask |= IB_QP_RETRY_CNT | IB_QP_RNR_RETRY |
 						 IB_QP_MAX_QP_RD_ATOMIC;
-				qp_attr->timeout = cm_id_priv->av.timeout;
 				qp_attr->retry_cnt = cm_id_priv->retry_count;
 				qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
-				qp_attr->max_rd_atomic =
-					cm_id_priv->initiator_depth;
+				qp_attr->max_rd_atomic = cm_id_priv->initiator_depth;
+				/* fall through */
+			case IB_QPT_XRC_TGT:
+				*qp_attr_mask |= IB_QP_TIMEOUT;
+				qp_attr->timeout = cm_id_priv->av.timeout;
+				break;
+			default:
+				break;
 			}
 			if (cm_id_priv->alt_av.ah_attr.dlid) {
 				*qp_attr_mask |= IB_QP_PATH_MIG_STATE;
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/cm_msgs.h linux-libre-3.2-gnu/drivers/infiniband/core/cm_msgs.h
--- linux-libre-3.1-gnu/drivers/infiniband/core/cm_msgs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/cm_msgs.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2011 Intel Corporation.  All rights reserved.
  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
  * Copyright (c) 2004 Voltaire Corporation.  All rights reserved.
  *
@@ -86,7 +86,7 @@
 	__be16 pkey;
 	/* path MTU:4, RDC exists:1, RNR retry count:3. */
 	u8 offset50;
-	/* max CM Retries:4, SRQ:1, rsvd:3 */
+	/* max CM Retries:4, SRQ:1, extended transport type:3 */
 	u8 offset51;
 
 	__be16 primary_local_lid;
@@ -175,6 +175,11 @@
 	switch(transport_type) {
 	case 0: return IB_QPT_RC;
 	case 1: return IB_QPT_UC;
+	case 3:
+		switch (req_msg->offset51 & 0x7) {
+		case 1: return IB_QPT_XRC_TGT;
+		default: return 0;
+		}
 	default: return 0;
 	}
 }
@@ -188,6 +193,12 @@
 						  req_msg->offset40) &
 						   0xFFFFFFF9) | 0x2);
 		break;
+	case IB_QPT_XRC_INI:
+		req_msg->offset40 = cpu_to_be32((be32_to_cpu(
+						 req_msg->offset40) &
+						   0xFFFFFFF9) | 0x6);
+		req_msg->offset51 = (req_msg->offset51 & 0xF8) | 1;
+		break;
 	default:
 		req_msg->offset40 = cpu_to_be32(be32_to_cpu(
 						 req_msg->offset40) &
@@ -527,6 +538,23 @@
 			    (be32_to_cpu(rep_msg->offset12) & 0x000000FF));
 }
 
+static inline __be32 cm_rep_get_local_eecn(struct cm_rep_msg *rep_msg)
+{
+	return cpu_to_be32(be32_to_cpu(rep_msg->offset16) >> 8);
+}
+
+static inline void cm_rep_set_local_eecn(struct cm_rep_msg *rep_msg, __be32 eecn)
+{
+	rep_msg->offset16 = cpu_to_be32((be32_to_cpu(eecn) << 8) |
+			    (be32_to_cpu(rep_msg->offset16) & 0x000000FF));
+}
+
+static inline __be32 cm_rep_get_qpn(struct cm_rep_msg *rep_msg, enum ib_qp_type qp_type)
+{
+	return (qp_type == IB_QPT_XRC_INI) ?
+		cm_rep_get_local_eecn(rep_msg) : cm_rep_get_local_qpn(rep_msg);
+}
+
 static inline __be32 cm_rep_get_starting_psn(struct cm_rep_msg *rep_msg)
 {
 	return cpu_to_be32(be32_to_cpu(rep_msg->offset20) >> 8);
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/fmr_pool.c linux-libre-3.2-gnu/drivers/infiniband/core/fmr_pool.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/fmr_pool.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/fmr_pool.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 
 #include <linux/errno.h>
 #include <linux/spinlock.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/jhash.h>
 #include <linux/kthread.h>
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/iwcm.c linux-libre-3.2-gnu/drivers/infiniband/core/iwcm.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/iwcm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/iwcm.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,6 +45,7 @@
 #include <linux/workqueue.h>
 #include <linux/completion.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include <rdma/iw_cm.h>
 #include <rdma/ib_addr.h>
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/mad.c linux-libre-3.2-gnu/drivers/infiniband/core/mad.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/mad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/mad.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
  */
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <rdma/ib_cache.h>
 
 #include "mad_priv.h"
@@ -1596,6 +1597,9 @@
 					mad->mad_hdr.class_version].class;
 			if (!class)
 				goto out;
+			if (convert_mgmt_class(mad->mad_hdr.mgmt_class) >=
+			    IB_MGMT_MAX_METHODS)
+				goto out;
 			method = class->method_table[convert_mgmt_class(
 							mad->mad_hdr.mgmt_class)];
 			if (method)
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/multicast.c linux-libre-3.2-gnu/drivers/infiniband/core/multicast.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/multicast.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/multicast.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/bitops.h>
 #include <linux/random.h>
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/netlink.c linux-libre-3.2-gnu/drivers/infiniband/core/netlink.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/netlink.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/netlink.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 
 #define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__
 
+#include <linux/export.h>
 #include <net/netlink.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/packer.c linux-libre-3.2-gnu/drivers/infiniband/core/packer.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/packer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/packer.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
  * SOFTWARE.
  */
 
+#include <linux/export.h>
 #include <linux/string.h>
 
 #include <rdma/ib_pack.h>
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/sysfs.c linux-libre-3.2-gnu/drivers/infiniband/core/sysfs.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include "core_priv.h"
 
 #include <linux/slab.h>
+#include <linux/stat.h>
 #include <linux/string.h>
 
 #include <rdma/ib_mad.h>
@@ -185,17 +186,35 @@
 	if (ret)
 		return ret;
 
+	rate = (25 * attr.active_speed) / 10;
+
 	switch (attr.active_speed) {
-	case 2: speed = " DDR"; break;
-	case 4: speed = " QDR"; break;
+	case 2:
+		speed = " DDR";
+		break;
+	case 4:
+		speed = " QDR";
+		break;
+	case 8:
+		speed = " FDR10";
+		rate = 10;
+		break;
+	case 16:
+		speed = " FDR";
+		rate = 14;
+		break;
+	case 32:
+		speed = " EDR";
+		rate = 25;
+		break;
 	}
 
-	rate = 25 * ib_width_enum_to_int(attr.active_width) * attr.active_speed;
+	rate *= ib_width_enum_to_int(attr.active_width);
 	if (rate < 0)
 		return -EINVAL;
 
 	return sprintf(buf, "%d%s Gb/sec (%dX%s)\n",
-		       rate / 10, rate % 10 ? ".5" : "",
+		       rate, (attr.active_speed == 1) ? ".5" : "",
 		       ib_width_enum_to_int(attr.active_width), speed);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/ucma.c linux-libre-3.2-gnu/drivers/infiniband/core/ucma.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/ucma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/ucma.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
+#include <linux/module.h>
 
 #include <rdma/rdma_user_cm.h>
 #include <rdma/ib_marshall.h>
@@ -276,7 +277,7 @@
 	ucma_set_event_context(ctx, event, uevent);
 	uevent->resp.event = event->event;
 	uevent->resp.status = event->status;
-	if (cm_id->ps == RDMA_PS_UDP || cm_id->ps == RDMA_PS_IPOIB)
+	if (cm_id->qp_type == IB_QPT_UD)
 		ucma_copy_ud_event(&uevent->resp.param.ud, &event->param.ud);
 	else
 		ucma_copy_conn_event(&uevent->resp.param.conn,
@@ -377,6 +378,9 @@
 	case RDMA_PS_IPOIB:
 		*qp_type = IB_QPT_UD;
 		return 0;
+	case RDMA_PS_IB:
+		*qp_type = cmd->qp_type;
+		return 0;
 	default:
 		return -EINVAL;
 	}
@@ -1270,7 +1274,7 @@
 	if (copy_from_user(&hdr, buf, sizeof(hdr)))
 		return -EFAULT;
 
-	if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucma_cmd_table))
+	if (hdr.cmd >= ARRAY_SIZE(ucma_cmd_table))
 		return -EINVAL;
 
 	if (hdr.in + sizeof(hdr) > len)
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/ucm.c linux-libre-3.2-gnu/drivers/infiniband/core/ucm.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/ucm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/ucm.c	2012-01-04 18:55:44.000000000 -0500
@@ -1122,7 +1122,7 @@
 	if (copy_from_user(&hdr, buf, sizeof(hdr)))
 		return -EFAULT;
 
-	if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucm_cmd_table))
+	if (hdr.cmd >= ARRAY_SIZE(ucm_cmd_table))
 		return -EINVAL;
 
 	if (hdr.in + sizeof(hdr) > len)
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/ud_header.c linux-libre-3.2-gnu/drivers/infiniband/core/ud_header.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/ud_header.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/ud_header.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/export.h>
 #include <linux/if_ether.h>
 
 #include <rdma/ib_pack.h>
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/umem.c linux-libre-3.2-gnu/drivers/infiniband/core/umem.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/umem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/umem.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/sched.h>
+#include <linux/export.h>
 #include <linux/hugetlb.h>
 #include <linux/dma-attrs.h>
 #include <linux/slab.h>
@@ -136,7 +137,7 @@
 
 	down_write(&current->mm->mmap_sem);
 
-	locked     = npages + current->mm->locked_vm;
+	locked     = npages + current->mm->pinned_vm;
 	lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
 
 	if ((locked > lock_limit) && !capable(CAP_IPC_LOCK)) {
@@ -206,7 +207,7 @@
 		__ib_umem_release(context->device, umem, 0);
 		kfree(umem);
 	} else
-		current->mm->locked_vm = locked;
+		current->mm->pinned_vm = locked;
 
 	up_write(&current->mm->mmap_sem);
 	if (vma_list)
@@ -222,7 +223,7 @@
 	struct ib_umem *umem = container_of(work, struct ib_umem, work);
 
 	down_write(&umem->mm->mmap_sem);
-	umem->mm->locked_vm -= umem->diff;
+	umem->mm->pinned_vm -= umem->diff;
 	up_write(&umem->mm->mmap_sem);
 	mmput(umem->mm);
 	kfree(umem);
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/user_mad.c linux-libre-3.2-gnu/drivers/infiniband/core/user_mad.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/user_mad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/user_mad.c	2012-01-04 18:55:44.000000000 -0500
@@ -458,8 +458,7 @@
 		goto err;
 	}
 
-	if (packet->mad.hdr.id < 0 ||
-	    packet->mad.hdr.id >= IB_UMAD_MAX_AGENTS) {
+	if (packet->mad.hdr.id >= IB_UMAD_MAX_AGENTS) {
 		ret = -EINVAL;
 		goto err;
 	}
@@ -703,7 +702,7 @@
 	mutex_lock(&file->port->file_mutex);
 	mutex_lock(&file->mutex);
 
-	if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
+	if (id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
 		ret = -EINVAL;
 		goto out;
 	}
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/uverbs_cmd.c linux-libre-3.2-gnu/drivers/infiniband/core/uverbs_cmd.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/uverbs_cmd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/uverbs_cmd.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,7 @@
 static struct lock_class_key qp_lock_key;
 static struct lock_class_key ah_lock_key;
 static struct lock_class_key srq_lock_key;
+static struct lock_class_key xrcd_lock_key;
 
 #define INIT_UDATA(udata, ibuf, obuf, ilen, olen)			\
 	do {								\
@@ -255,6 +256,18 @@
 	put_uobj_read(srq->uobject);
 }
 
+static struct ib_xrcd *idr_read_xrcd(int xrcd_handle, struct ib_ucontext *context,
+				     struct ib_uobject **uobj)
+{
+	*uobj = idr_read_uobj(&ib_uverbs_xrcd_idr, xrcd_handle, context, 0);
+	return *uobj ? (*uobj)->object : NULL;
+}
+
+static void put_xrcd_read(struct ib_uobject *uobj)
+{
+	put_uobj_read(uobj);
+}
+
 ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
 			      const char __user *buf,
 			      int in_len, int out_len)
@@ -298,6 +311,7 @@
 	INIT_LIST_HEAD(&ucontext->qp_list);
 	INIT_LIST_HEAD(&ucontext->srq_list);
 	INIT_LIST_HEAD(&ucontext->ah_list);
+	INIT_LIST_HEAD(&ucontext->xrcd_list);
 	ucontext->closing = 0;
 
 	resp.num_comp_vectors = file->device->num_comp_vectors;
@@ -579,6 +593,310 @@
 	return in_len;
 }
 
+struct xrcd_table_entry {
+	struct rb_node  node;
+	struct ib_xrcd *xrcd;
+	struct inode   *inode;
+};
+
+static int xrcd_table_insert(struct ib_uverbs_device *dev,
+			    struct inode *inode,
+			    struct ib_xrcd *xrcd)
+{
+	struct xrcd_table_entry *entry, *scan;
+	struct rb_node **p = &dev->xrcd_tree.rb_node;
+	struct rb_node *parent = NULL;
+
+	entry = kmalloc(sizeof *entry, GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+
+	entry->xrcd  = xrcd;
+	entry->inode = inode;
+
+	while (*p) {
+		parent = *p;
+		scan = rb_entry(parent, struct xrcd_table_entry, node);
+
+		if (inode < scan->inode) {
+			p = &(*p)->rb_left;
+		} else if (inode > scan->inode) {
+			p = &(*p)->rb_right;
+		} else {
+			kfree(entry);
+			return -EEXIST;
+		}
+	}
+
+	rb_link_node(&entry->node, parent, p);
+	rb_insert_color(&entry->node, &dev->xrcd_tree);
+	igrab(inode);
+	return 0;
+}
+
+static struct xrcd_table_entry *xrcd_table_search(struct ib_uverbs_device *dev,
+						  struct inode *inode)
+{
+	struct xrcd_table_entry *entry;
+	struct rb_node *p = dev->xrcd_tree.rb_node;
+
+	while (p) {
+		entry = rb_entry(p, struct xrcd_table_entry, node);
+
+		if (inode < entry->inode)
+			p = p->rb_left;
+		else if (inode > entry->inode)
+			p = p->rb_right;
+		else
+			return entry;
+	}
+
+	return NULL;
+}
+
+static struct ib_xrcd *find_xrcd(struct ib_uverbs_device *dev, struct inode *inode)
+{
+	struct xrcd_table_entry *entry;
+
+	entry = xrcd_table_search(dev, inode);
+	if (!entry)
+		return NULL;
+
+	return entry->xrcd;
+}
+
+static void xrcd_table_delete(struct ib_uverbs_device *dev,
+			      struct inode *inode)
+{
+	struct xrcd_table_entry *entry;
+
+	entry = xrcd_table_search(dev, inode);
+	if (entry) {
+		iput(inode);
+		rb_erase(&entry->node, &dev->xrcd_tree);
+		kfree(entry);
+	}
+}
+
+ssize_t ib_uverbs_open_xrcd(struct ib_uverbs_file *file,
+			    const char __user *buf, int in_len,
+			    int out_len)
+{
+	struct ib_uverbs_open_xrcd	cmd;
+	struct ib_uverbs_open_xrcd_resp	resp;
+	struct ib_udata			udata;
+	struct ib_uxrcd_object         *obj;
+	struct ib_xrcd                 *xrcd = NULL;
+	struct file                    *f = NULL;
+	struct inode                   *inode = NULL;
+	int				ret = 0;
+	int				new_xrcd = 0;
+
+	if (out_len < sizeof resp)
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	INIT_UDATA(&udata, buf + sizeof cmd,
+		   (unsigned long) cmd.response + sizeof resp,
+		   in_len - sizeof cmd, out_len - sizeof  resp);
+
+	mutex_lock(&file->device->xrcd_tree_mutex);
+
+	if (cmd.fd != -1) {
+		/* search for file descriptor */
+		f = fget(cmd.fd);
+		if (!f) {
+			ret = -EBADF;
+			goto err_tree_mutex_unlock;
+		}
+
+		inode = f->f_dentry->d_inode;
+		if (!inode) {
+			ret = -EBADF;
+			goto err_tree_mutex_unlock;
+		}
+
+		xrcd = find_xrcd(file->device, inode);
+		if (!xrcd && !(cmd.oflags & O_CREAT)) {
+			/* no file descriptor. Need CREATE flag */
+			ret = -EAGAIN;
+			goto err_tree_mutex_unlock;
+		}
+
+		if (xrcd && cmd.oflags & O_EXCL) {
+			ret = -EINVAL;
+			goto err_tree_mutex_unlock;
+		}
+	}
+
+	obj = kmalloc(sizeof *obj, GFP_KERNEL);
+	if (!obj) {
+		ret = -ENOMEM;
+		goto err_tree_mutex_unlock;
+	}
+
+	init_uobj(&obj->uobject, 0, file->ucontext, &xrcd_lock_key);
+
+	down_write(&obj->uobject.mutex);
+
+	if (!xrcd) {
+		xrcd = file->device->ib_dev->alloc_xrcd(file->device->ib_dev,
+							file->ucontext, &udata);
+		if (IS_ERR(xrcd)) {
+			ret = PTR_ERR(xrcd);
+			goto err;
+		}
+
+		xrcd->inode   = inode;
+		xrcd->device  = file->device->ib_dev;
+		atomic_set(&xrcd->usecnt, 0);
+		mutex_init(&xrcd->tgt_qp_mutex);
+		INIT_LIST_HEAD(&xrcd->tgt_qp_list);
+		new_xrcd = 1;
+	}
+
+	atomic_set(&obj->refcnt, 0);
+	obj->uobject.object = xrcd;
+	ret = idr_add_uobj(&ib_uverbs_xrcd_idr, &obj->uobject);
+	if (ret)
+		goto err_idr;
+
+	memset(&resp, 0, sizeof resp);
+	resp.xrcd_handle = obj->uobject.id;
+
+	if (inode) {
+		if (new_xrcd) {
+			/* create new inode/xrcd table entry */
+			ret = xrcd_table_insert(file->device, inode, xrcd);
+			if (ret)
+				goto err_insert_xrcd;
+		}
+		atomic_inc(&xrcd->usecnt);
+	}
+
+	if (copy_to_user((void __user *) (unsigned long) cmd.response,
+			 &resp, sizeof resp)) {
+		ret = -EFAULT;
+		goto err_copy;
+	}
+
+	if (f)
+		fput(f);
+
+	mutex_lock(&file->mutex);
+	list_add_tail(&obj->uobject.list, &file->ucontext->xrcd_list);
+	mutex_unlock(&file->mutex);
+
+	obj->uobject.live = 1;
+	up_write(&obj->uobject.mutex);
+
+	mutex_unlock(&file->device->xrcd_tree_mutex);
+	return in_len;
+
+err_copy:
+	if (inode) {
+		if (new_xrcd)
+			xrcd_table_delete(file->device, inode);
+		atomic_dec(&xrcd->usecnt);
+	}
+
+err_insert_xrcd:
+	idr_remove_uobj(&ib_uverbs_xrcd_idr, &obj->uobject);
+
+err_idr:
+	ib_dealloc_xrcd(xrcd);
+
+err:
+	put_uobj_write(&obj->uobject);
+
+err_tree_mutex_unlock:
+	if (f)
+		fput(f);
+
+	mutex_unlock(&file->device->xrcd_tree_mutex);
+
+	return ret;
+}
+
+ssize_t ib_uverbs_close_xrcd(struct ib_uverbs_file *file,
+			     const char __user *buf, int in_len,
+			     int out_len)
+{
+	struct ib_uverbs_close_xrcd cmd;
+	struct ib_uobject           *uobj;
+	struct ib_xrcd              *xrcd = NULL;
+	struct inode                *inode = NULL;
+	struct ib_uxrcd_object      *obj;
+	int                         live;
+	int                         ret = 0;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	mutex_lock(&file->device->xrcd_tree_mutex);
+	uobj = idr_write_uobj(&ib_uverbs_xrcd_idr, cmd.xrcd_handle, file->ucontext);
+	if (!uobj) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	xrcd  = uobj->object;
+	inode = xrcd->inode;
+	obj   = container_of(uobj, struct ib_uxrcd_object, uobject);
+	if (atomic_read(&obj->refcnt)) {
+		put_uobj_write(uobj);
+		ret = -EBUSY;
+		goto out;
+	}
+
+	if (!inode || atomic_dec_and_test(&xrcd->usecnt)) {
+		ret = ib_dealloc_xrcd(uobj->object);
+		if (!ret)
+			uobj->live = 0;
+	}
+
+	live = uobj->live;
+	if (inode && ret)
+		atomic_inc(&xrcd->usecnt);
+
+	put_uobj_write(uobj);
+
+	if (ret)
+		goto out;
+
+	if (inode && !live)
+		xrcd_table_delete(file->device, inode);
+
+	idr_remove_uobj(&ib_uverbs_xrcd_idr, uobj);
+	mutex_lock(&file->mutex);
+	list_del(&uobj->list);
+	mutex_unlock(&file->mutex);
+
+	put_uobj(uobj);
+	ret = in_len;
+
+out:
+	mutex_unlock(&file->device->xrcd_tree_mutex);
+	return ret;
+}
+
+void ib_uverbs_dealloc_xrcd(struct ib_uverbs_device *dev,
+			    struct ib_xrcd *xrcd)
+{
+	struct inode *inode;
+
+	inode = xrcd->inode;
+	if (inode && !atomic_dec_and_test(&xrcd->usecnt))
+		return;
+
+	ib_dealloc_xrcd(xrcd);
+
+	if (inode)
+		xrcd_table_delete(dev, inode);
+}
+
 ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
 			 const char __user *buf, int in_len,
 			 int out_len)
@@ -1052,9 +1370,12 @@
 	struct ib_uverbs_create_qp_resp resp;
 	struct ib_udata                 udata;
 	struct ib_uqp_object           *obj;
-	struct ib_pd                   *pd;
-	struct ib_cq                   *scq, *rcq;
-	struct ib_srq                  *srq;
+	struct ib_device	       *device;
+	struct ib_pd                   *pd = NULL;
+	struct ib_xrcd		       *xrcd = NULL;
+	struct ib_uobject	       *uninitialized_var(xrcd_uobj);
+	struct ib_cq                   *scq = NULL, *rcq = NULL;
+	struct ib_srq                  *srq = NULL;
 	struct ib_qp                   *qp;
 	struct ib_qp_init_attr          attr;
 	int ret;
@@ -1076,15 +1397,39 @@
 	init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
 	down_write(&obj->uevent.uobject.mutex);
 
-	srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL;
-	pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
-	scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
-	rcq = cmd.recv_cq_handle == cmd.send_cq_handle ?
-		scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
+	if (cmd.qp_type == IB_QPT_XRC_TGT) {
+		xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
+		if (!xrcd) {
+			ret = -EINVAL;
+			goto err_put;
+		}
+		device = xrcd->device;
+	} else {
+		pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
+		scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
+		if (!pd || !scq) {
+			ret = -EINVAL;
+			goto err_put;
+		}
 
-	if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) {
-		ret = -EINVAL;
-		goto err_put;
+		if (cmd.qp_type == IB_QPT_XRC_INI) {
+			cmd.max_recv_wr = cmd.max_recv_sge = 0;
+		} else {
+			if (cmd.is_srq) {
+				srq = idr_read_srq(cmd.srq_handle, file->ucontext);
+				if (!srq || srq->srq_type != IB_SRQT_BASIC) {
+					ret = -EINVAL;
+					goto err_put;
+				}
+			}
+			rcq = (cmd.recv_cq_handle == cmd.send_cq_handle) ?
+			       scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
+			if (!rcq) {
+				ret = -EINVAL;
+				goto err_put;
+			}
+		}
+		device = pd->device;
 	}
 
 	attr.event_handler = ib_uverbs_qp_event_handler;
@@ -1092,6 +1437,7 @@
 	attr.send_cq       = scq;
 	attr.recv_cq       = rcq;
 	attr.srq           = srq;
+	attr.xrcd	   = xrcd;
 	attr.sq_sig_type   = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
 	attr.qp_type       = cmd.qp_type;
 	attr.create_flags  = 0;
@@ -1106,26 +1452,34 @@
 	INIT_LIST_HEAD(&obj->uevent.event_list);
 	INIT_LIST_HEAD(&obj->mcast_list);
 
-	qp = pd->device->create_qp(pd, &attr, &udata);
+	if (cmd.qp_type == IB_QPT_XRC_TGT)
+		qp = ib_create_qp(pd, &attr);
+	else
+		qp = device->create_qp(pd, &attr, &udata);
+
 	if (IS_ERR(qp)) {
 		ret = PTR_ERR(qp);
 		goto err_put;
 	}
 
-	qp->device     	  = pd->device;
-	qp->pd         	  = pd;
-	qp->send_cq    	  = attr.send_cq;
-	qp->recv_cq    	  = attr.recv_cq;
-	qp->srq	       	  = attr.srq;
-	qp->uobject       = &obj->uevent.uobject;
-	qp->event_handler = attr.event_handler;
-	qp->qp_context    = attr.qp_context;
-	qp->qp_type	  = attr.qp_type;
-	atomic_inc(&pd->usecnt);
-	atomic_inc(&attr.send_cq->usecnt);
-	atomic_inc(&attr.recv_cq->usecnt);
-	if (attr.srq)
-		atomic_inc(&attr.srq->usecnt);
+	if (cmd.qp_type != IB_QPT_XRC_TGT) {
+		qp->real_qp	  = qp;
+		qp->device	  = device;
+		qp->pd		  = pd;
+		qp->send_cq	  = attr.send_cq;
+		qp->recv_cq	  = attr.recv_cq;
+		qp->srq		  = attr.srq;
+		qp->event_handler = attr.event_handler;
+		qp->qp_context	  = attr.qp_context;
+		qp->qp_type	  = attr.qp_type;
+		atomic_inc(&pd->usecnt);
+		atomic_inc(&attr.send_cq->usecnt);
+		if (attr.recv_cq)
+			atomic_inc(&attr.recv_cq->usecnt);
+		if (attr.srq)
+			atomic_inc(&attr.srq->usecnt);
+	}
+	qp->uobject = &obj->uevent.uobject;
 
 	obj->uevent.uobject.object = qp;
 	ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
@@ -1147,9 +1501,13 @@
 		goto err_copy;
 	}
 
-	put_pd_read(pd);
-	put_cq_read(scq);
-	if (rcq != scq)
+	if (xrcd)
+		put_xrcd_read(xrcd_uobj);
+	if (pd)
+		put_pd_read(pd);
+	if (scq)
+		put_cq_read(scq);
+	if (rcq && rcq != scq)
 		put_cq_read(rcq);
 	if (srq)
 		put_srq_read(srq);
@@ -1171,6 +1529,8 @@
 	ib_destroy_qp(qp);
 
 err_put:
+	if (xrcd)
+		put_xrcd_read(xrcd_uobj);
 	if (pd)
 		put_pd_read(pd);
 	if (scq)
@@ -1184,6 +1544,98 @@
 	return ret;
 }
 
+ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file,
+			  const char __user *buf, int in_len, int out_len)
+{
+	struct ib_uverbs_open_qp        cmd;
+	struct ib_uverbs_create_qp_resp resp;
+	struct ib_udata                 udata;
+	struct ib_uqp_object           *obj;
+	struct ib_xrcd		       *xrcd;
+	struct ib_uobject	       *uninitialized_var(xrcd_uobj);
+	struct ib_qp                   *qp;
+	struct ib_qp_open_attr          attr;
+	int ret;
+
+	if (out_len < sizeof resp)
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	INIT_UDATA(&udata, buf + sizeof cmd,
+		   (unsigned long) cmd.response + sizeof resp,
+		   in_len - sizeof cmd, out_len - sizeof resp);
+
+	obj = kmalloc(sizeof *obj, GFP_KERNEL);
+	if (!obj)
+		return -ENOMEM;
+
+	init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
+	down_write(&obj->uevent.uobject.mutex);
+
+	xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
+	if (!xrcd) {
+		ret = -EINVAL;
+		goto err_put;
+	}
+
+	attr.event_handler = ib_uverbs_qp_event_handler;
+	attr.qp_context    = file;
+	attr.qp_num        = cmd.qpn;
+	attr.qp_type       = cmd.qp_type;
+
+	obj->uevent.events_reported = 0;
+	INIT_LIST_HEAD(&obj->uevent.event_list);
+	INIT_LIST_HEAD(&obj->mcast_list);
+
+	qp = ib_open_qp(xrcd, &attr);
+	if (IS_ERR(qp)) {
+		ret = PTR_ERR(qp);
+		goto err_put;
+	}
+
+	qp->uobject = &obj->uevent.uobject;
+
+	obj->uevent.uobject.object = qp;
+	ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
+	if (ret)
+		goto err_destroy;
+
+	memset(&resp, 0, sizeof resp);
+	resp.qpn       = qp->qp_num;
+	resp.qp_handle = obj->uevent.uobject.id;
+
+	if (copy_to_user((void __user *) (unsigned long) cmd.response,
+			 &resp, sizeof resp)) {
+		ret = -EFAULT;
+		goto err_remove;
+	}
+
+	put_xrcd_read(xrcd_uobj);
+
+	mutex_lock(&file->mutex);
+	list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list);
+	mutex_unlock(&file->mutex);
+
+	obj->uevent.uobject.live = 1;
+
+	up_write(&obj->uevent.uobject.mutex);
+
+	return in_len;
+
+err_remove:
+	idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
+
+err_destroy:
+	ib_destroy_qp(qp);
+
+err_put:
+	put_xrcd_read(xrcd_uobj);
+	put_uobj_write(&obj->uevent.uobject);
+	return ret;
+}
+
 ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file,
 			   const char __user *buf, int in_len,
 			   int out_len)
@@ -1284,6 +1736,20 @@
 	return ret ? ret : in_len;
 }
 
+/* Remove ignored fields set in the attribute mask */
+static int modify_qp_mask(enum ib_qp_type qp_type, int mask)
+{
+	switch (qp_type) {
+	case IB_QPT_XRC_INI:
+		return mask & ~(IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MIN_RNR_TIMER);
+	case IB_QPT_XRC_TGT:
+		return mask & ~(IB_QP_MAX_QP_RD_ATOMIC | IB_QP_RETRY_CNT |
+				IB_QP_RNR_RETRY);
+	default:
+		return mask;
+	}
+}
+
 ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
 			    const char __user *buf, int in_len,
 			    int out_len)
@@ -1356,7 +1822,12 @@
 	attr->alt_ah_attr.ah_flags 	    = cmd.alt_dest.is_global ? IB_AH_GRH : 0;
 	attr->alt_ah_attr.port_num 	    = cmd.alt_dest.port_num;
 
-	ret = qp->device->modify_qp(qp, attr, cmd.attr_mask, &udata);
+	if (qp->real_qp == qp) {
+		ret = qp->device->modify_qp(qp, attr,
+			modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
+	} else {
+		ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask));
+	}
 
 	put_qp_read(qp);
 
@@ -1553,7 +2024,7 @@
 	}
 
 	resp.bad_wr = 0;
-	ret = qp->device->post_send(qp, wr, &bad_wr);
+	ret = qp->device->post_send(qp->real_qp, wr, &bad_wr);
 	if (ret)
 		for (next = wr; next; next = next->next) {
 			++resp.bad_wr;
@@ -1691,7 +2162,7 @@
 		goto out;
 
 	resp.bad_wr = 0;
-	ret = qp->device->post_recv(qp, wr, &bad_wr);
+	ret = qp->device->post_recv(qp->real_qp, wr, &bad_wr);
 
 	put_qp_read(qp);
 
@@ -1975,107 +2446,199 @@
 	return ret ? ret : in_len;
 }
 
-ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
-			     const char __user *buf, int in_len,
-			     int out_len)
+int __uverbs_create_xsrq(struct ib_uverbs_file *file,
+			 struct ib_uverbs_create_xsrq *cmd,
+			 struct ib_udata *udata)
 {
-	struct ib_uverbs_create_srq      cmd;
 	struct ib_uverbs_create_srq_resp resp;
-	struct ib_udata                  udata;
-	struct ib_uevent_object         *obj;
+	struct ib_usrq_object           *obj;
 	struct ib_pd                    *pd;
 	struct ib_srq                   *srq;
+	struct ib_uobject               *uninitialized_var(xrcd_uobj);
 	struct ib_srq_init_attr          attr;
 	int ret;
 
-	if (out_len < sizeof resp)
-		return -ENOSPC;
-
-	if (copy_from_user(&cmd, buf, sizeof cmd))
-		return -EFAULT;
-
-	INIT_UDATA(&udata, buf + sizeof cmd,
-		   (unsigned long) cmd.response + sizeof resp,
-		   in_len - sizeof cmd, out_len - sizeof resp);
-
 	obj = kmalloc(sizeof *obj, GFP_KERNEL);
 	if (!obj)
 		return -ENOMEM;
 
-	init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &srq_lock_key);
-	down_write(&obj->uobject.mutex);
+	init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext, &srq_lock_key);
+	down_write(&obj->uevent.uobject.mutex);
 
-	pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
+	pd  = idr_read_pd(cmd->pd_handle, file->ucontext);
 	if (!pd) {
 		ret = -EINVAL;
 		goto err;
 	}
 
+	if (cmd->srq_type == IB_SRQT_XRC) {
+		attr.ext.xrc.cq  = idr_read_cq(cmd->cq_handle, file->ucontext, 0);
+		if (!attr.ext.xrc.cq) {
+			ret = -EINVAL;
+			goto err_put_pd;
+		}
+
+		attr.ext.xrc.xrcd  = idr_read_xrcd(cmd->xrcd_handle, file->ucontext, &xrcd_uobj);
+		if (!attr.ext.xrc.xrcd) {
+			ret = -EINVAL;
+			goto err_put_cq;
+		}
+
+		obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject);
+		atomic_inc(&obj->uxrcd->refcnt);
+	}
+
 	attr.event_handler  = ib_uverbs_srq_event_handler;
 	attr.srq_context    = file;
-	attr.attr.max_wr    = cmd.max_wr;
-	attr.attr.max_sge   = cmd.max_sge;
-	attr.attr.srq_limit = cmd.srq_limit;
+	attr.srq_type       = cmd->srq_type;
+	attr.attr.max_wr    = cmd->max_wr;
+	attr.attr.max_sge   = cmd->max_sge;
+	attr.attr.srq_limit = cmd->srq_limit;
 
-	obj->events_reported     = 0;
-	INIT_LIST_HEAD(&obj->event_list);
+	obj->uevent.events_reported = 0;
+	INIT_LIST_HEAD(&obj->uevent.event_list);
 
-	srq = pd->device->create_srq(pd, &attr, &udata);
+	srq = pd->device->create_srq(pd, &attr, udata);
 	if (IS_ERR(srq)) {
 		ret = PTR_ERR(srq);
 		goto err_put;
 	}
 
-	srq->device    	   = pd->device;
-	srq->pd        	   = pd;
-	srq->uobject       = &obj->uobject;
+	srq->device        = pd->device;
+	srq->pd            = pd;
+	srq->srq_type	   = cmd->srq_type;
+	srq->uobject       = &obj->uevent.uobject;
 	srq->event_handler = attr.event_handler;
 	srq->srq_context   = attr.srq_context;
+
+	if (cmd->srq_type == IB_SRQT_XRC) {
+		srq->ext.xrc.cq   = attr.ext.xrc.cq;
+		srq->ext.xrc.xrcd = attr.ext.xrc.xrcd;
+		atomic_inc(&attr.ext.xrc.cq->usecnt);
+		atomic_inc(&attr.ext.xrc.xrcd->usecnt);
+	}
+
 	atomic_inc(&pd->usecnt);
 	atomic_set(&srq->usecnt, 0);
 
-	obj->uobject.object = srq;
-	ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uobject);
+	obj->uevent.uobject.object = srq;
+	ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
 	if (ret)
 		goto err_destroy;
 
 	memset(&resp, 0, sizeof resp);
-	resp.srq_handle = obj->uobject.id;
+	resp.srq_handle = obj->uevent.uobject.id;
 	resp.max_wr     = attr.attr.max_wr;
 	resp.max_sge    = attr.attr.max_sge;
+	if (cmd->srq_type == IB_SRQT_XRC)
+		resp.srqn = srq->ext.xrc.srq_num;
 
-	if (copy_to_user((void __user *) (unsigned long) cmd.response,
+	if (copy_to_user((void __user *) (unsigned long) cmd->response,
 			 &resp, sizeof resp)) {
 		ret = -EFAULT;
 		goto err_copy;
 	}
 
+	if (cmd->srq_type == IB_SRQT_XRC) {
+		put_uobj_read(xrcd_uobj);
+		put_cq_read(attr.ext.xrc.cq);
+	}
 	put_pd_read(pd);
 
 	mutex_lock(&file->mutex);
-	list_add_tail(&obj->uobject.list, &file->ucontext->srq_list);
+	list_add_tail(&obj->uevent.uobject.list, &file->ucontext->srq_list);
 	mutex_unlock(&file->mutex);
 
-	obj->uobject.live = 1;
+	obj->uevent.uobject.live = 1;
 
-	up_write(&obj->uobject.mutex);
+	up_write(&obj->uevent.uobject.mutex);
 
-	return in_len;
+	return 0;
 
 err_copy:
-	idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uobject);
+	idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
 
 err_destroy:
 	ib_destroy_srq(srq);
 
 err_put:
+	if (cmd->srq_type == IB_SRQT_XRC) {
+		atomic_dec(&obj->uxrcd->refcnt);
+		put_uobj_read(xrcd_uobj);
+	}
+
+err_put_cq:
+	if (cmd->srq_type == IB_SRQT_XRC)
+		put_cq_read(attr.ext.xrc.cq);
+
+err_put_pd:
 	put_pd_read(pd);
 
 err:
-	put_uobj_write(&obj->uobject);
+	put_uobj_write(&obj->uevent.uobject);
 	return ret;
 }
 
+ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
+			     const char __user *buf, int in_len,
+			     int out_len)
+{
+	struct ib_uverbs_create_srq      cmd;
+	struct ib_uverbs_create_xsrq     xcmd;
+	struct ib_uverbs_create_srq_resp resp;
+	struct ib_udata                  udata;
+	int ret;
+
+	if (out_len < sizeof resp)
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	xcmd.response	 = cmd.response;
+	xcmd.user_handle = cmd.user_handle;
+	xcmd.srq_type	 = IB_SRQT_BASIC;
+	xcmd.pd_handle	 = cmd.pd_handle;
+	xcmd.max_wr	 = cmd.max_wr;
+	xcmd.max_sge	 = cmd.max_sge;
+	xcmd.srq_limit	 = cmd.srq_limit;
+
+	INIT_UDATA(&udata, buf + sizeof cmd,
+		   (unsigned long) cmd.response + sizeof resp,
+		   in_len - sizeof cmd, out_len - sizeof resp);
+
+	ret = __uverbs_create_xsrq(file, &xcmd, &udata);
+	if (ret)
+		return ret;
+
+	return in_len;
+}
+
+ssize_t ib_uverbs_create_xsrq(struct ib_uverbs_file *file,
+			      const char __user *buf, int in_len, int out_len)
+{
+	struct ib_uverbs_create_xsrq     cmd;
+	struct ib_uverbs_create_srq_resp resp;
+	struct ib_udata                  udata;
+	int ret;
+
+	if (out_len < sizeof resp)
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	INIT_UDATA(&udata, buf + sizeof cmd,
+		   (unsigned long) cmd.response + sizeof resp,
+		   in_len - sizeof cmd, out_len - sizeof resp);
+
+	ret = __uverbs_create_xsrq(file, &cmd, &udata);
+	if (ret)
+		return ret;
+
+	return in_len;
+}
+
 ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
 			     const char __user *buf, int in_len,
 			     int out_len)
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/uverbs.h linux-libre-3.2-gnu/drivers/infiniband/core/uverbs.h
--- linux-libre-3.1-gnu/drivers/infiniband/core/uverbs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/uverbs.h	2012-01-04 18:55:44.000000000 -0500
@@ -76,6 +76,8 @@
 	struct ib_device		       *ib_dev;
 	int					devnum;
 	struct cdev			        cdev;
+	struct rb_root				xrcd_tree;
+	struct mutex				xrcd_tree_mutex;
 };
 
 struct ib_uverbs_event_file {
@@ -120,6 +122,16 @@
 	u32			events_reported;
 };
 
+struct ib_uxrcd_object {
+	struct ib_uobject	uobject;
+	atomic_t		refcnt;
+};
+
+struct ib_usrq_object {
+	struct ib_uevent_object	uevent;
+	struct ib_uxrcd_object *uxrcd;
+};
+
 struct ib_uqp_object {
 	struct ib_uevent_object	uevent;
 	struct list_head 	mcast_list;
@@ -142,6 +154,7 @@
 extern struct idr ib_uverbs_cq_idr;
 extern struct idr ib_uverbs_qp_idr;
 extern struct idr ib_uverbs_srq_idr;
+extern struct idr ib_uverbs_xrcd_idr;
 
 void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj);
 
@@ -161,6 +174,7 @@
 void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
 void ib_uverbs_event_handler(struct ib_event_handler *handler,
 			     struct ib_event *event);
+void ib_uverbs_dealloc_xrcd(struct ib_uverbs_device *dev, struct ib_xrcd *xrcd);
 
 #define IB_UVERBS_DECLARE_CMD(name)					\
 	ssize_t ib_uverbs_##name(struct ib_uverbs_file *file,		\
@@ -181,6 +195,7 @@
 IB_UVERBS_DECLARE_CMD(req_notify_cq);
 IB_UVERBS_DECLARE_CMD(destroy_cq);
 IB_UVERBS_DECLARE_CMD(create_qp);
+IB_UVERBS_DECLARE_CMD(open_qp);
 IB_UVERBS_DECLARE_CMD(query_qp);
 IB_UVERBS_DECLARE_CMD(modify_qp);
 IB_UVERBS_DECLARE_CMD(destroy_qp);
@@ -195,5 +210,8 @@
 IB_UVERBS_DECLARE_CMD(modify_srq);
 IB_UVERBS_DECLARE_CMD(query_srq);
 IB_UVERBS_DECLARE_CMD(destroy_srq);
+IB_UVERBS_DECLARE_CMD(create_xsrq);
+IB_UVERBS_DECLARE_CMD(open_xrcd);
+IB_UVERBS_DECLARE_CMD(close_xrcd);
 
 #endif /* UVERBS_H */
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/uverbs_main.c linux-libre-3.2-gnu/drivers/infiniband/core/uverbs_main.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/uverbs_main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/uverbs_main.c	2012-01-04 18:55:44.000000000 -0500
@@ -72,6 +72,7 @@
 DEFINE_IDR(ib_uverbs_cq_idr);
 DEFINE_IDR(ib_uverbs_qp_idr);
 DEFINE_IDR(ib_uverbs_srq_idr);
+DEFINE_IDR(ib_uverbs_xrcd_idr);
 
 static DEFINE_SPINLOCK(map_lock);
 static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -107,6 +108,10 @@
 	[IB_USER_VERBS_CMD_MODIFY_SRQ]		= ib_uverbs_modify_srq,
 	[IB_USER_VERBS_CMD_QUERY_SRQ]		= ib_uverbs_query_srq,
 	[IB_USER_VERBS_CMD_DESTROY_SRQ]		= ib_uverbs_destroy_srq,
+	[IB_USER_VERBS_CMD_OPEN_XRCD]		= ib_uverbs_open_xrcd,
+	[IB_USER_VERBS_CMD_CLOSE_XRCD]		= ib_uverbs_close_xrcd,
+	[IB_USER_VERBS_CMD_CREATE_XSRQ]		= ib_uverbs_create_xsrq,
+	[IB_USER_VERBS_CMD_OPEN_QP]		= ib_uverbs_open_qp
 };
 
 static void ib_uverbs_add_one(struct ib_device *device);
@@ -202,8 +207,12 @@
 			container_of(uobj, struct ib_uqp_object, uevent.uobject);
 
 		idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
-		ib_uverbs_detach_umcast(qp, uqp);
-		ib_destroy_qp(qp);
+		if (qp != qp->real_qp) {
+			ib_close_qp(qp);
+		} else {
+			ib_uverbs_detach_umcast(qp, uqp);
+			ib_destroy_qp(qp);
+		}
 		ib_uverbs_release_uevent(file, &uqp->uevent);
 		kfree(uqp);
 	}
@@ -241,6 +250,18 @@
 		kfree(uobj);
 	}
 
+	mutex_lock(&file->device->xrcd_tree_mutex);
+	list_for_each_entry_safe(uobj, tmp, &context->xrcd_list, list) {
+		struct ib_xrcd *xrcd = uobj->object;
+		struct ib_uxrcd_object *uxrcd =
+			container_of(uobj, struct ib_uxrcd_object, uobject);
+
+		idr_remove_uobj(&ib_uverbs_xrcd_idr, uobj);
+		ib_uverbs_dealloc_xrcd(file->device, xrcd);
+		kfree(uxrcd);
+	}
+	mutex_unlock(&file->device->xrcd_tree_mutex);
+
 	list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) {
 		struct ib_pd *pd = uobj->object;
 
@@ -557,8 +578,7 @@
 	if (hdr.in_words * 4 != count)
 		return -EINVAL;
 
-	if (hdr.command < 0				||
-	    hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
+	if (hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
 	    !uverbs_cmd_table[hdr.command])
 		return -EINVAL;
 
@@ -741,6 +761,8 @@
 
 	kref_init(&uverbs_dev->ref);
 	init_completion(&uverbs_dev->comp);
+	uverbs_dev->xrcd_tree = RB_ROOT;
+	mutex_init(&uverbs_dev->xrcd_tree_mutex);
 
 	spin_lock(&map_lock);
 	devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/uverbs_marshall.c linux-libre-3.2-gnu/drivers/infiniband/core/uverbs_marshall.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/uverbs_marshall.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/uverbs_marshall.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
  * SOFTWARE.
  */
 
+#include <linux/export.h>
 #include <rdma/ib_marshall.h>
 
 void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst,
diff -druN linux-libre-3.1-gnu/drivers/infiniband/core/verbs.c linux-libre-3.2-gnu/drivers/infiniband/core/verbs.c
--- linux-libre-3.1-gnu/drivers/infiniband/core/verbs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/core/verbs.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,7 +38,9 @@
 
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <linux/string.h>
+#include <linux/slab.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_cache.h>
@@ -77,6 +79,31 @@
 }
 EXPORT_SYMBOL(mult_to_ib_rate);
 
+int ib_rate_to_mbps(enum ib_rate rate)
+{
+	switch (rate) {
+	case IB_RATE_2_5_GBPS: return 2500;
+	case IB_RATE_5_GBPS:   return 5000;
+	case IB_RATE_10_GBPS:  return 10000;
+	case IB_RATE_20_GBPS:  return 20000;
+	case IB_RATE_30_GBPS:  return 30000;
+	case IB_RATE_40_GBPS:  return 40000;
+	case IB_RATE_60_GBPS:  return 60000;
+	case IB_RATE_80_GBPS:  return 80000;
+	case IB_RATE_120_GBPS: return 120000;
+	case IB_RATE_14_GBPS:  return 14062;
+	case IB_RATE_56_GBPS:  return 56250;
+	case IB_RATE_112_GBPS: return 112500;
+	case IB_RATE_168_GBPS: return 168750;
+	case IB_RATE_25_GBPS:  return 25781;
+	case IB_RATE_100_GBPS: return 103125;
+	case IB_RATE_200_GBPS: return 206250;
+	case IB_RATE_300_GBPS: return 309375;
+	default:	       return -1;
+	}
+}
+EXPORT_SYMBOL(ib_rate_to_mbps);
+
 enum rdma_transport_type
 rdma_node_get_transport(enum rdma_node_type node_type)
 {
@@ -250,6 +277,13 @@
 		srq->uobject       = NULL;
 		srq->event_handler = srq_init_attr->event_handler;
 		srq->srq_context   = srq_init_attr->srq_context;
+		srq->srq_type      = srq_init_attr->srq_type;
+		if (srq->srq_type == IB_SRQT_XRC) {
+			srq->ext.xrc.xrcd = srq_init_attr->ext.xrc.xrcd;
+			srq->ext.xrc.cq   = srq_init_attr->ext.xrc.cq;
+			atomic_inc(&srq->ext.xrc.xrcd->usecnt);
+			atomic_inc(&srq->ext.xrc.cq->usecnt);
+		}
 		atomic_inc(&pd->usecnt);
 		atomic_set(&srq->usecnt, 0);
 	}
@@ -279,16 +313,29 @@
 int ib_destroy_srq(struct ib_srq *srq)
 {
 	struct ib_pd *pd;
+	enum ib_srq_type srq_type;
+	struct ib_xrcd *uninitialized_var(xrcd);
+	struct ib_cq *uninitialized_var(cq);
 	int ret;
 
 	if (atomic_read(&srq->usecnt))
 		return -EBUSY;
 
 	pd = srq->pd;
+	srq_type = srq->srq_type;
+	if (srq_type == IB_SRQT_XRC) {
+		xrcd = srq->ext.xrc.xrcd;
+		cq = srq->ext.xrc.cq;
+	}
 
 	ret = srq->device->destroy_srq(srq);
-	if (!ret)
+	if (!ret) {
 		atomic_dec(&pd->usecnt);
+		if (srq_type == IB_SRQT_XRC) {
+			atomic_dec(&xrcd->usecnt);
+			atomic_dec(&cq->usecnt);
+		}
+	}
 
 	return ret;
 }
@@ -296,28 +343,123 @@
 
 /* Queue pairs */
 
+static void __ib_shared_qp_event_handler(struct ib_event *event, void *context)
+{
+	struct ib_qp *qp = context;
+
+	list_for_each_entry(event->element.qp, &qp->open_list, open_list)
+		event->element.qp->event_handler(event, event->element.qp->qp_context);
+}
+
+static void __ib_insert_xrcd_qp(struct ib_xrcd *xrcd, struct ib_qp *qp)
+{
+	mutex_lock(&xrcd->tgt_qp_mutex);
+	list_add(&qp->xrcd_list, &xrcd->tgt_qp_list);
+	mutex_unlock(&xrcd->tgt_qp_mutex);
+}
+
+static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp,
+				  void (*event_handler)(struct ib_event *, void *),
+				  void *qp_context)
+{
+	struct ib_qp *qp;
+	unsigned long flags;
+
+	qp = kzalloc(sizeof *qp, GFP_KERNEL);
+	if (!qp)
+		return ERR_PTR(-ENOMEM);
+
+	qp->real_qp = real_qp;
+	atomic_inc(&real_qp->usecnt);
+	qp->device = real_qp->device;
+	qp->event_handler = event_handler;
+	qp->qp_context = qp_context;
+	qp->qp_num = real_qp->qp_num;
+	qp->qp_type = real_qp->qp_type;
+
+	spin_lock_irqsave(&real_qp->device->event_handler_lock, flags);
+	list_add(&qp->open_list, &real_qp->open_list);
+	spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags);
+
+	return qp;
+}
+
+struct ib_qp *ib_open_qp(struct ib_xrcd *xrcd,
+			 struct ib_qp_open_attr *qp_open_attr)
+{
+	struct ib_qp *qp, *real_qp;
+
+	if (qp_open_attr->qp_type != IB_QPT_XRC_TGT)
+		return ERR_PTR(-EINVAL);
+
+	qp = ERR_PTR(-EINVAL);
+	mutex_lock(&xrcd->tgt_qp_mutex);
+	list_for_each_entry(real_qp, &xrcd->tgt_qp_list, xrcd_list) {
+		if (real_qp->qp_num == qp_open_attr->qp_num) {
+			qp = __ib_open_qp(real_qp, qp_open_attr->event_handler,
+					  qp_open_attr->qp_context);
+			break;
+		}
+	}
+	mutex_unlock(&xrcd->tgt_qp_mutex);
+	return qp;
+}
+EXPORT_SYMBOL(ib_open_qp);
+
 struct ib_qp *ib_create_qp(struct ib_pd *pd,
 			   struct ib_qp_init_attr *qp_init_attr)
 {
-	struct ib_qp *qp;
+	struct ib_qp *qp, *real_qp;
+	struct ib_device *device;
 
-	qp = pd->device->create_qp(pd, qp_init_attr, NULL);
+	device = pd ? pd->device : qp_init_attr->xrcd->device;
+	qp = device->create_qp(pd, qp_init_attr, NULL);
 
 	if (!IS_ERR(qp)) {
-		qp->device     	  = pd->device;
-		qp->pd         	  = pd;
-		qp->send_cq    	  = qp_init_attr->send_cq;
-		qp->recv_cq    	  = qp_init_attr->recv_cq;
-		qp->srq	       	  = qp_init_attr->srq;
-		qp->uobject       = NULL;
-		qp->event_handler = qp_init_attr->event_handler;
-		qp->qp_context    = qp_init_attr->qp_context;
-		qp->qp_type	  = qp_init_attr->qp_type;
-		atomic_inc(&pd->usecnt);
-		atomic_inc(&qp_init_attr->send_cq->usecnt);
-		atomic_inc(&qp_init_attr->recv_cq->usecnt);
-		if (qp_init_attr->srq)
-			atomic_inc(&qp_init_attr->srq->usecnt);
+		qp->device     = device;
+		qp->real_qp    = qp;
+		qp->uobject    = NULL;
+		qp->qp_type    = qp_init_attr->qp_type;
+
+		if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {
+			qp->event_handler = __ib_shared_qp_event_handler;
+			qp->qp_context = qp;
+			qp->pd = NULL;
+			qp->send_cq = qp->recv_cq = NULL;
+			qp->srq = NULL;
+			qp->xrcd = qp_init_attr->xrcd;
+			atomic_inc(&qp_init_attr->xrcd->usecnt);
+			INIT_LIST_HEAD(&qp->open_list);
+			atomic_set(&qp->usecnt, 0);
+
+			real_qp = qp;
+			qp = __ib_open_qp(real_qp, qp_init_attr->event_handler,
+					  qp_init_attr->qp_context);
+			if (!IS_ERR(qp))
+				__ib_insert_xrcd_qp(qp_init_attr->xrcd, real_qp);
+			else
+				real_qp->device->destroy_qp(real_qp);
+		} else {
+			qp->event_handler = qp_init_attr->event_handler;
+			qp->qp_context = qp_init_attr->qp_context;
+			if (qp_init_attr->qp_type == IB_QPT_XRC_INI) {
+				qp->recv_cq = NULL;
+				qp->srq = NULL;
+			} else {
+				qp->recv_cq = qp_init_attr->recv_cq;
+				atomic_inc(&qp_init_attr->recv_cq->usecnt);
+				qp->srq = qp_init_attr->srq;
+				if (qp->srq)
+					atomic_inc(&qp_init_attr->srq->usecnt);
+			}
+
+			qp->pd	    = pd;
+			qp->send_cq = qp_init_attr->send_cq;
+			qp->xrcd    = NULL;
+
+			atomic_inc(&pd->usecnt);
+			atomic_inc(&qp_init_attr->send_cq->usecnt);
+		}
 	}
 
 	return qp;
@@ -326,8 +468,8 @@
 
 static const struct {
 	int			valid;
-	enum ib_qp_attr_mask	req_param[IB_QPT_RAW_ETHERTYPE + 1];
-	enum ib_qp_attr_mask	opt_param[IB_QPT_RAW_ETHERTYPE + 1];
+	enum ib_qp_attr_mask	req_param[IB_QPT_MAX];
+	enum ib_qp_attr_mask	opt_param[IB_QPT_MAX];
 } qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
 	[IB_QPS_RESET] = {
 		[IB_QPS_RESET] = { .valid = 1 },
@@ -343,6 +485,12 @@
 				[IB_QPT_RC]  = (IB_QP_PKEY_INDEX		|
 						IB_QP_PORT			|
 						IB_QP_ACCESS_FLAGS),
+				[IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX		|
+						IB_QP_PORT			|
+						IB_QP_ACCESS_FLAGS),
+				[IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX		|
+						IB_QP_PORT			|
+						IB_QP_ACCESS_FLAGS),
 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -365,6 +513,12 @@
 				[IB_QPT_RC]  = (IB_QP_PKEY_INDEX		|
 						IB_QP_PORT			|
 						IB_QP_ACCESS_FLAGS),
+				[IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX		|
+						IB_QP_PORT			|
+						IB_QP_ACCESS_FLAGS),
+				[IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX		|
+						IB_QP_PORT			|
+						IB_QP_ACCESS_FLAGS),
 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -384,6 +538,16 @@
 						IB_QP_RQ_PSN			|
 						IB_QP_MAX_DEST_RD_ATOMIC	|
 						IB_QP_MIN_RNR_TIMER),
+				[IB_QPT_XRC_INI] = (IB_QP_AV			|
+						IB_QP_PATH_MTU			|
+						IB_QP_DEST_QPN			|
+						IB_QP_RQ_PSN),
+				[IB_QPT_XRC_TGT] = (IB_QP_AV			|
+						IB_QP_PATH_MTU			|
+						IB_QP_DEST_QPN			|
+						IB_QP_RQ_PSN			|
+						IB_QP_MAX_DEST_RD_ATOMIC	|
+						IB_QP_MIN_RNR_TIMER),
 			},
 			.opt_param = {
 				 [IB_QPT_UD]  = (IB_QP_PKEY_INDEX		|
@@ -394,6 +558,12 @@
 				 [IB_QPT_RC]  = (IB_QP_ALT_PATH			|
 						 IB_QP_ACCESS_FLAGS		|
 						 IB_QP_PKEY_INDEX),
+				 [IB_QPT_XRC_INI] = (IB_QP_ALT_PATH		|
+						 IB_QP_ACCESS_FLAGS		|
+						 IB_QP_PKEY_INDEX),
+				 [IB_QPT_XRC_TGT] = (IB_QP_ALT_PATH		|
+						 IB_QP_ACCESS_FLAGS		|
+						 IB_QP_PKEY_INDEX),
 				 [IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 						 IB_QP_QKEY),
 				 [IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -414,6 +584,13 @@
 						IB_QP_RNR_RETRY			|
 						IB_QP_SQ_PSN			|
 						IB_QP_MAX_QP_RD_ATOMIC),
+				[IB_QPT_XRC_INI] = (IB_QP_TIMEOUT		|
+						IB_QP_RETRY_CNT			|
+						IB_QP_RNR_RETRY			|
+						IB_QP_SQ_PSN			|
+						IB_QP_MAX_QP_RD_ATOMIC),
+				[IB_QPT_XRC_TGT] = (IB_QP_TIMEOUT		|
+						IB_QP_SQ_PSN),
 				[IB_QPT_SMI] = IB_QP_SQ_PSN,
 				[IB_QPT_GSI] = IB_QP_SQ_PSN,
 			},
@@ -429,6 +606,15 @@
 						 IB_QP_ACCESS_FLAGS		|
 						 IB_QP_MIN_RNR_TIMER		|
 						 IB_QP_PATH_MIG_STATE),
+				 [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE		|
+						 IB_QP_ALT_PATH			|
+						 IB_QP_ACCESS_FLAGS		|
+						 IB_QP_PATH_MIG_STATE),
+				 [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE		|
+						 IB_QP_ALT_PATH			|
+						 IB_QP_ACCESS_FLAGS		|
+						 IB_QP_MIN_RNR_TIMER		|
+						 IB_QP_PATH_MIG_STATE),
 				 [IB_QPT_SMI] = (IB_QP_CUR_STATE		|
 						 IB_QP_QKEY),
 				 [IB_QPT_GSI] = (IB_QP_CUR_STATE		|
@@ -453,6 +639,15 @@
 						IB_QP_ALT_PATH			|
 						IB_QP_PATH_MIG_STATE		|
 						IB_QP_MIN_RNR_TIMER),
+				[IB_QPT_XRC_INI] = (IB_QP_CUR_STATE		|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_ALT_PATH			|
+						IB_QP_PATH_MIG_STATE),
+				[IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE		|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_ALT_PATH			|
+						IB_QP_PATH_MIG_STATE		|
+						IB_QP_MIN_RNR_TIMER),
 				[IB_QPT_SMI] = (IB_QP_CUR_STATE			|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_CUR_STATE			|
@@ -465,6 +660,8 @@
 				[IB_QPT_UD]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
 				[IB_QPT_UC]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
 				[IB_QPT_RC]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
+				[IB_QPT_XRC_INI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
+				[IB_QPT_XRC_TGT] = IB_QP_EN_SQD_ASYNC_NOTIFY, /* ??? */
 				[IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
 				[IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY
 			}
@@ -487,6 +684,15 @@
 						IB_QP_ACCESS_FLAGS		|
 						IB_QP_MIN_RNR_TIMER		|
 						IB_QP_PATH_MIG_STATE),
+				[IB_QPT_XRC_INI] = (IB_QP_CUR_STATE		|
+						IB_QP_ALT_PATH			|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_PATH_MIG_STATE),
+				[IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE		|
+						IB_QP_ALT_PATH			|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_MIN_RNR_TIMER		|
+						IB_QP_PATH_MIG_STATE),
 				[IB_QPT_SMI] = (IB_QP_CUR_STATE			|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_CUR_STATE			|
@@ -515,6 +721,25 @@
 						IB_QP_PKEY_INDEX		|
 						IB_QP_MIN_RNR_TIMER		|
 						IB_QP_PATH_MIG_STATE),
+				[IB_QPT_XRC_INI] = (IB_QP_PORT			|
+						IB_QP_AV			|
+						IB_QP_TIMEOUT			|
+						IB_QP_RETRY_CNT			|
+						IB_QP_RNR_RETRY			|
+						IB_QP_MAX_QP_RD_ATOMIC		|
+						IB_QP_ALT_PATH			|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_PKEY_INDEX		|
+						IB_QP_PATH_MIG_STATE),
+				[IB_QPT_XRC_TGT] = (IB_QP_PORT			|
+						IB_QP_AV			|
+						IB_QP_TIMEOUT			|
+						IB_QP_MAX_DEST_RD_ATOMIC	|
+						IB_QP_ALT_PATH			|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_PKEY_INDEX		|
+						IB_QP_MIN_RNR_TIMER		|
+						IB_QP_PATH_MIG_STATE),
 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -579,7 +804,7 @@
 		 struct ib_qp_attr *qp_attr,
 		 int qp_attr_mask)
 {
-	return qp->device->modify_qp(qp, qp_attr, qp_attr_mask, NULL);
+	return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL);
 }
 EXPORT_SYMBOL(ib_modify_qp);
 
@@ -589,11 +814,59 @@
 		struct ib_qp_init_attr *qp_init_attr)
 {
 	return qp->device->query_qp ?
-		qp->device->query_qp(qp, qp_attr, qp_attr_mask, qp_init_attr) :
+		qp->device->query_qp(qp->real_qp, qp_attr, qp_attr_mask, qp_init_attr) :
 		-ENOSYS;
 }
 EXPORT_SYMBOL(ib_query_qp);
 
+int ib_close_qp(struct ib_qp *qp)
+{
+	struct ib_qp *real_qp;
+	unsigned long flags;
+
+	real_qp = qp->real_qp;
+	if (real_qp == qp)
+		return -EINVAL;
+
+	spin_lock_irqsave(&real_qp->device->event_handler_lock, flags);
+	list_del(&qp->open_list);
+	spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags);
+
+	atomic_dec(&real_qp->usecnt);
+	kfree(qp);
+
+	return 0;
+}
+EXPORT_SYMBOL(ib_close_qp);
+
+static int __ib_destroy_shared_qp(struct ib_qp *qp)
+{
+	struct ib_xrcd *xrcd;
+	struct ib_qp *real_qp;
+	int ret;
+
+	real_qp = qp->real_qp;
+	xrcd = real_qp->xrcd;
+
+	mutex_lock(&xrcd->tgt_qp_mutex);
+	ib_close_qp(qp);
+	if (atomic_read(&real_qp->usecnt) == 0)
+		list_del(&real_qp->xrcd_list);
+	else
+		real_qp = NULL;
+	mutex_unlock(&xrcd->tgt_qp_mutex);
+
+	if (real_qp) {
+		ret = ib_destroy_qp(real_qp);
+		if (!ret)
+			atomic_dec(&xrcd->usecnt);
+		else
+			__ib_insert_xrcd_qp(xrcd, real_qp);
+	}
+
+	return 0;
+}
+
 int ib_destroy_qp(struct ib_qp *qp)
 {
 	struct ib_pd *pd;
@@ -601,16 +874,25 @@
 	struct ib_srq *srq;
 	int ret;
 
-	pd  = qp->pd;
-	scq = qp->send_cq;
-	rcq = qp->recv_cq;
-	srq = qp->srq;
+	if (atomic_read(&qp->usecnt))
+		return -EBUSY;
+
+	if (qp->real_qp != qp)
+		return __ib_destroy_shared_qp(qp);
+
+	pd   = qp->pd;
+	scq  = qp->send_cq;
+	rcq  = qp->recv_cq;
+	srq  = qp->srq;
 
 	ret = qp->device->destroy_qp(qp);
 	if (!ret) {
-		atomic_dec(&pd->usecnt);
-		atomic_dec(&scq->usecnt);
-		atomic_dec(&rcq->usecnt);
+		if (pd)
+			atomic_dec(&pd->usecnt);
+		if (scq)
+			atomic_dec(&scq->usecnt);
+		if (rcq)
+			atomic_dec(&rcq->usecnt);
 		if (srq)
 			atomic_dec(&srq->usecnt);
 	}
@@ -920,3 +1202,42 @@
 	return qp->device->detach_mcast(qp, gid, lid);
 }
 EXPORT_SYMBOL(ib_detach_mcast);
+
+struct ib_xrcd *ib_alloc_xrcd(struct ib_device *device)
+{
+	struct ib_xrcd *xrcd;
+
+	if (!device->alloc_xrcd)
+		return ERR_PTR(-ENOSYS);
+
+	xrcd = device->alloc_xrcd(device, NULL, NULL);
+	if (!IS_ERR(xrcd)) {
+		xrcd->device = device;
+		xrcd->inode = NULL;
+		atomic_set(&xrcd->usecnt, 0);
+		mutex_init(&xrcd->tgt_qp_mutex);
+		INIT_LIST_HEAD(&xrcd->tgt_qp_list);
+	}
+
+	return xrcd;
+}
+EXPORT_SYMBOL(ib_alloc_xrcd);
+
+int ib_dealloc_xrcd(struct ib_xrcd *xrcd)
+{
+	struct ib_qp *qp;
+	int ret;
+
+	if (atomic_read(&xrcd->usecnt))
+		return -EBUSY;
+
+	while (!list_empty(&xrcd->tgt_qp_list)) {
+		qp = list_entry(xrcd->tgt_qp_list.next, struct ib_qp, xrcd_list);
+		ret = ib_destroy_qp(qp);
+		if (ret)
+			return ret;
+	}
+
+	return xrcd->device->dealloc_xrcd(xrcd);
+}
+EXPORT_SYMBOL(ib_dealloc_xrcd);
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/amso1100/c2_ae.c linux-libre-3.2-gnu/drivers/infiniband/hw/amso1100/c2_ae.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/amso1100/c2_ae.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/amso1100/c2_ae.c	2012-01-04 18:55:44.000000000 -0500
@@ -288,6 +288,11 @@
 		cm_event.private_data_len =
 			be32_to_cpu(req->private_data_length);
 		cm_event.private_data = req->private_data;
+		/*
+		 * Until ird/ord negotiation via MPAv2 support is added, send
+		 * max supported values
+		 */
+		cm_event.ird = cm_event.ord = 128;
 
 		if (cm_id->event_handler)
 			cm_id->event_handler(cm_id, &cm_event);
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/amso1100/c2.c linux-libre-3.2-gnu/drivers/infiniband/hw/amso1100/c2.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/amso1100/c2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/amso1100/c2.c	2012-01-04 18:55:44.000000000 -0500
@@ -800,13 +800,10 @@
 	/* Loop thru additional data fragments and queue them */
 	if (skb_shinfo(skb)->nr_frags) {
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-			maplen = frag->size;
-			mapaddr =
-			    pci_map_page(c2dev->pcidev, frag->page,
-					 frag->page_offset, maplen,
-					 PCI_DMA_TODEVICE);
-
+			const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+			maplen = skb_frag_size(frag);
+			mapaddr = skb_frag_dma_map(&c2dev->pcidev->dev, frag,
+						   0, maplen, DMA_TO_DEVICE);
 			elem = elem->next;
 			elem->skb = NULL;
 			elem->mapaddr = mapaddr;
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/amso1100/c2_intr.c linux-libre-3.2-gnu/drivers/infiniband/hw/amso1100/c2_intr.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/amso1100/c2_intr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/amso1100/c2_intr.c	2012-01-04 18:55:44.000000000 -0500
@@ -183,6 +183,11 @@
 	case IW_CM_EVENT_ESTABLISHED:
 		c2_set_qp_state(req->qp,
 				C2_QP_STATE_RTS);
+		/*
+		 * Until ird/ord negotiation via MPAv2 support is added, send
+		 * max supported values
+		 */
+		cm_event.ird = cm_event.ord = 128;
 	case IW_CM_EVENT_CLOSE:
 
 		/*
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/amso1100/c2_provider.c linux-libre-3.2-gnu/drivers/infiniband/hw/amso1100/c2_provider.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/amso1100/c2_provider.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/amso1100/c2_provider.c	2012-01-04 18:55:44.000000000 -0500
@@ -753,10 +753,7 @@
 	memcpy_fromio(netdev->dev_addr, c2dev->kva + C2_REGS_RDMA_ENADDR, 6);
 
 	/* Print out the MAC address */
-	pr_debug("%s: MAC %02X:%02X:%02X:%02X:%02X:%02X\n",
-		netdev->name,
-		netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
-		netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
+	pr_debug("%s: MAC %pM\n", netdev->name, netdev->dev_addr);
 
 #if 0
 	/* Disable network packets */
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb3/iwch_cm.c linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb3/iwch_cm.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb3/iwch_cm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb3/iwch_cm.c	2012-01-04 18:55:44.000000000 -0500
@@ -753,6 +753,11 @@
 	event.private_data_len = ep->plen;
 	event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
 	event.provider_data = ep;
+	/*
+	 * Until ird/ord negotiation via MPAv2 support is added, send max
+	 * supported values
+	 */
+	event.ird = event.ord = 8;
 	if (state_read(&ep->parent_ep->com) != DEAD) {
 		get_ep(&ep->com);
 		ep->parent_ep->com.cm_id->event_handler(
@@ -770,6 +775,11 @@
 	PDBG("%s ep %p\n", __func__, ep);
 	memset(&event, 0, sizeof(event));
 	event.event = IW_CM_EVENT_ESTABLISHED;
+	/*
+	 * Until ird/ord negotiation via MPAv2 support is added, send max
+	 * supported values
+	 */
+	event.ird = event.ord = 8;
 	if (ep->com.cm_id) {
 		PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid);
 		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
@@ -1365,8 +1375,10 @@
 		goto reject;
 	}
 	dst = &rt->dst;
+	rcu_read_lock();
 	neigh = dst_get_neighbour(dst);
 	l2t = t3_l2t_get(tdev, neigh, neigh->dev);
+	rcu_read_unlock();
 	if (!l2t) {
 		printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
 		       __func__);
@@ -1936,10 +1948,12 @@
 	}
 	ep->dst = &rt->dst;
 
+	rcu_read_lock();
 	neigh = dst_get_neighbour(ep->dst);
 
 	/* get a l2t entry */
 	ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev);
+	rcu_read_unlock();
 	if (!ep->l2t) {
 		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
 		err = -ENOMEM;
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb3/iwch_ev.c linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb3/iwch_ev.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb3/iwch_ev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb3/iwch_ev.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,6 +46,7 @@
 	struct ib_event event;
 	struct iwch_qp_attributes attrs;
 	struct iwch_qp *qhp;
+	unsigned long flag;
 
 	spin_lock(&rnicp->lock);
 	qhp = get_qhp(rnicp, CQE_QPID(rsp_msg->cqe));
@@ -94,7 +95,9 @@
 	if (qhp->ibqp.event_handler)
 		(*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
 
+	spin_lock_irqsave(&chp->comp_handler_lock, flag);
 	(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+	spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
 
 	if (atomic_dec_and_test(&qhp->refcnt))
 		wake_up(&qhp->wait);
@@ -107,6 +110,7 @@
 	struct iwch_cq *chp;
 	struct iwch_qp *qhp;
 	u32 cqid = RSPQ_CQID(rsp_msg);
+	unsigned long flag;
 
 	rnicp = (struct iwch_dev *) rdev_p->ulp;
 	spin_lock(&rnicp->lock);
@@ -170,7 +174,9 @@
 		 */
 		if (qhp->ep && SQ_TYPE(rsp_msg->cqe))
 			dst_confirm(qhp->ep->dst);
+		spin_lock_irqsave(&chp->comp_handler_lock, flag);
 		(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+		spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
 		break;
 
 	case TPT_ERR_STAG:
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.c linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.c	2012-01-04 18:55:44.000000000 -0500
@@ -190,6 +190,7 @@
 	chp->rhp = rhp;
 	chp->ibcq.cqe = 1 << chp->cq.size_log2;
 	spin_lock_init(&chp->lock);
+	spin_lock_init(&chp->comp_handler_lock);
 	atomic_set(&chp->refcnt, 1);
 	init_waitqueue_head(&chp->wait);
 	if (insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid)) {
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.h linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.h
--- linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.h	2012-01-04 18:55:44.000000000 -0500
@@ -103,6 +103,7 @@
 	struct iwch_dev *rhp;
 	struct t3_cq cq;
 	spinlock_t lock;
+	spinlock_t comp_handler_lock;
 	atomic_t refcnt;
 	wait_queue_head_t wait;
 	u32 __user *user_rptr_addr;
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb3/iwch_qp.c linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb3/iwch_qp.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb3/iwch_qp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb3/iwch_qp.c	2012-01-04 18:55:44.000000000 -0500
@@ -822,8 +822,11 @@
 	flushed = cxio_flush_rq(&qhp->wq, &rchp->cq, count);
 	spin_unlock(&qhp->lock);
 	spin_unlock_irqrestore(&rchp->lock, *flag);
-	if (flushed)
+	if (flushed) {
+		spin_lock_irqsave(&rchp->comp_handler_lock, *flag);
 		(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+		spin_unlock_irqrestore(&rchp->comp_handler_lock, *flag);
+	}
 
 	/* locking hierarchy: cq lock first, then qp lock. */
 	spin_lock_irqsave(&schp->lock, *flag);
@@ -833,8 +836,11 @@
 	flushed = cxio_flush_sq(&qhp->wq, &schp->cq, count);
 	spin_unlock(&qhp->lock);
 	spin_unlock_irqrestore(&schp->lock, *flag);
-	if (flushed)
+	if (flushed) {
+		spin_lock_irqsave(&schp->comp_handler_lock, *flag);
 		(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
+		spin_unlock_irqrestore(&schp->comp_handler_lock, *flag);
+	}
 
 	/* deref */
 	if (atomic_dec_and_test(&qhp->refcnt))
@@ -853,11 +859,15 @@
 	if (qhp->ibqp.uobject) {
 		cxio_set_wq_in_error(&qhp->wq);
 		cxio_set_cq_in_error(&rchp->cq);
+		spin_lock_irqsave(&rchp->comp_handler_lock, *flag);
 		(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+		spin_unlock_irqrestore(&rchp->comp_handler_lock, *flag);
 		if (schp != rchp) {
 			cxio_set_cq_in_error(&schp->cq);
+			spin_lock_irqsave(&schp->comp_handler_lock, *flag);
 			(*schp->ibcq.comp_handler)(&schp->ibcq,
 						   schp->ibcq.cq_context);
+			spin_unlock_irqrestore(&schp->comp_handler_lock, *flag);
 		}
 		return;
 	}
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb3/Makefile linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb3/Makefile
--- linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb3/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb3/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-ccflags-y := -Idrivers/net/cxgb3
+ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb3
 
 obj-$(CONFIG_INFINIBAND_CXGB3) += iw_cxgb3.o
 
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb4/cm.c linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb4/cm.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb4/cm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb4/cm.c	2012-01-04 18:55:44.000000000 -0500
@@ -103,7 +103,8 @@
 static int mpa_rev = 1;
 module_param(mpa_rev, int, 0644);
 MODULE_PARM_DESC(mpa_rev, "MPA Revision, 0 supports amso1100, "
-		 "1 is spec compliant. (default=1)");
+		"1 is RFC0544 spec compliant, 2 is IETF MPA Peer Connect Draft"
+		" compliant (default=1)");
 
 static int markers_enabled;
 module_param(markers_enabled, int, 0644);
@@ -497,17 +498,21 @@
 	return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
 }
 
-static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb)
+static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
+		u8 mpa_rev_to_use)
 {
 	int mpalen, wrlen;
 	struct fw_ofld_tx_data_wr *req;
 	struct mpa_message *mpa;
+	struct mpa_v2_conn_params mpa_v2_params;
 
 	PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
 
 	BUG_ON(skb_cloned(skb));
 
 	mpalen = sizeof(*mpa) + ep->plen;
+	if (mpa_rev_to_use == 2)
+		mpalen += sizeof(struct mpa_v2_conn_params);
 	wrlen = roundup(mpalen + sizeof *req, 16);
 	skb = get_skb(skb, wrlen, GFP_KERNEL);
 	if (!skb) {
@@ -533,12 +538,41 @@
 	mpa = (struct mpa_message *)(req + 1);
 	memcpy(mpa->key, MPA_KEY_REQ, sizeof(mpa->key));
 	mpa->flags = (crc_enabled ? MPA_CRC : 0) |
-		     (markers_enabled ? MPA_MARKERS : 0);
+		     (markers_enabled ? MPA_MARKERS : 0) |
+		     (mpa_rev_to_use == 2 ? MPA_ENHANCED_RDMA_CONN : 0);
 	mpa->private_data_size = htons(ep->plen);
-	mpa->revision = mpa_rev;
+	mpa->revision = mpa_rev_to_use;
+	if (mpa_rev_to_use == 1) {
+		ep->tried_with_mpa_v1 = 1;
+		ep->retry_with_mpa_v1 = 0;
+	}
 
-	if (ep->plen)
-		memcpy(mpa->private_data, ep->mpa_pkt + sizeof(*mpa), ep->plen);
+	if (mpa_rev_to_use == 2) {
+		mpa->private_data_size +=
+			htons(sizeof(struct mpa_v2_conn_params));
+		mpa_v2_params.ird = htons((u16)ep->ird);
+		mpa_v2_params.ord = htons((u16)ep->ord);
+
+		if (peer2peer) {
+			mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL);
+			if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE)
+				mpa_v2_params.ord |=
+					htons(MPA_V2_RDMA_WRITE_RTR);
+			else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ)
+				mpa_v2_params.ord |=
+					htons(MPA_V2_RDMA_READ_RTR);
+		}
+		memcpy(mpa->private_data, &mpa_v2_params,
+		       sizeof(struct mpa_v2_conn_params));
+
+		if (ep->plen)
+			memcpy(mpa->private_data +
+			       sizeof(struct mpa_v2_conn_params),
+			       ep->mpa_pkt + sizeof(*mpa), ep->plen);
+	} else
+		if (ep->plen)
+			memcpy(mpa->private_data,
+					ep->mpa_pkt + sizeof(*mpa), ep->plen);
 
 	/*
 	 * Reference the mpa skb.  This ensures the data area
@@ -562,10 +596,13 @@
 	struct fw_ofld_tx_data_wr *req;
 	struct mpa_message *mpa;
 	struct sk_buff *skb;
+	struct mpa_v2_conn_params mpa_v2_params;
 
 	PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
 
 	mpalen = sizeof(*mpa) + plen;
+	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn)
+		mpalen += sizeof(struct mpa_v2_conn_params);
 	wrlen = roundup(mpalen + sizeof *req, 16);
 
 	skb = get_skb(NULL, wrlen, GFP_KERNEL);
@@ -595,8 +632,29 @@
 	mpa->flags = MPA_REJECT;
 	mpa->revision = mpa_rev;
 	mpa->private_data_size = htons(plen);
-	if (plen)
-		memcpy(mpa->private_data, pdata, plen);
+
+	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
+		mpa->flags |= MPA_ENHANCED_RDMA_CONN;
+		mpa->private_data_size +=
+			htons(sizeof(struct mpa_v2_conn_params));
+		mpa_v2_params.ird = htons(((u16)ep->ird) |
+					  (peer2peer ? MPA_V2_PEER2PEER_MODEL :
+					   0));
+		mpa_v2_params.ord = htons(((u16)ep->ord) | (peer2peer ?
+					  (p2p_type ==
+					   FW_RI_INIT_P2PTYPE_RDMA_WRITE ?
+					   MPA_V2_RDMA_WRITE_RTR : p2p_type ==
+					   FW_RI_INIT_P2PTYPE_READ_REQ ?
+					   MPA_V2_RDMA_READ_RTR : 0) : 0));
+		memcpy(mpa->private_data, &mpa_v2_params,
+		       sizeof(struct mpa_v2_conn_params));
+
+		if (ep->plen)
+			memcpy(mpa->private_data +
+			       sizeof(struct mpa_v2_conn_params), pdata, plen);
+	} else
+		if (plen)
+			memcpy(mpa->private_data, pdata, plen);
 
 	/*
 	 * Reference the mpa skb again.  This ensures the data area
@@ -617,10 +675,13 @@
 	struct fw_ofld_tx_data_wr *req;
 	struct mpa_message *mpa;
 	struct sk_buff *skb;
+	struct mpa_v2_conn_params mpa_v2_params;
 
 	PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
 
 	mpalen = sizeof(*mpa) + plen;
+	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn)
+		mpalen += sizeof(struct mpa_v2_conn_params);
 	wrlen = roundup(mpalen + sizeof *req, 16);
 
 	skb = get_skb(NULL, wrlen, GFP_KERNEL);
@@ -649,10 +710,36 @@
 	memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key));
 	mpa->flags = (ep->mpa_attr.crc_enabled ? MPA_CRC : 0) |
 		     (markers_enabled ? MPA_MARKERS : 0);
-	mpa->revision = mpa_rev;
+	mpa->revision = ep->mpa_attr.version;
 	mpa->private_data_size = htons(plen);
-	if (plen)
-		memcpy(mpa->private_data, pdata, plen);
+
+	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
+		mpa->flags |= MPA_ENHANCED_RDMA_CONN;
+		mpa->private_data_size +=
+			htons(sizeof(struct mpa_v2_conn_params));
+		mpa_v2_params.ird = htons((u16)ep->ird);
+		mpa_v2_params.ord = htons((u16)ep->ord);
+		if (peer2peer && (ep->mpa_attr.p2p_type !=
+					FW_RI_INIT_P2PTYPE_DISABLED)) {
+			mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL);
+
+			if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE)
+				mpa_v2_params.ord |=
+					htons(MPA_V2_RDMA_WRITE_RTR);
+			else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ)
+				mpa_v2_params.ord |=
+					htons(MPA_V2_RDMA_READ_RTR);
+		}
+
+		memcpy(mpa->private_data, &mpa_v2_params,
+		       sizeof(struct mpa_v2_conn_params));
+
+		if (ep->plen)
+			memcpy(mpa->private_data +
+			       sizeof(struct mpa_v2_conn_params), pdata, plen);
+	} else
+		if (plen)
+			memcpy(mpa->private_data, pdata, plen);
 
 	/*
 	 * Reference the mpa skb.  This ensures the data area
@@ -695,7 +782,10 @@
 
 	/* start MPA negotiation */
 	send_flowc(ep, NULL);
-	send_mpa_req(ep, skb);
+	if (ep->retry_with_mpa_v1)
+		send_mpa_req(ep, skb, 1);
+	else
+		send_mpa_req(ep, skb, mpa_rev);
 
 	return 0;
 }
@@ -769,8 +859,19 @@
 	event.remote_addr = ep->com.remote_addr;
 
 	if ((status == 0) || (status == -ECONNREFUSED)) {
-		event.private_data_len = ep->plen;
-		event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
+		if (!ep->tried_with_mpa_v1) {
+			/* this means MPA_v2 is used */
+			event.private_data_len = ep->plen -
+				sizeof(struct mpa_v2_conn_params);
+			event.private_data = ep->mpa_pkt +
+				sizeof(struct mpa_message) +
+				sizeof(struct mpa_v2_conn_params);
+		} else {
+			/* this means MPA_v1 is used */
+			event.private_data_len = ep->plen;
+			event.private_data = ep->mpa_pkt +
+				sizeof(struct mpa_message);
+		}
 	}
 
 	PDBG("%s ep %p tid %u status %d\n", __func__, ep,
@@ -793,9 +894,22 @@
 	event.event = IW_CM_EVENT_CONNECT_REQUEST;
 	event.local_addr = ep->com.local_addr;
 	event.remote_addr = ep->com.remote_addr;
-	event.private_data_len = ep->plen;
-	event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
 	event.provider_data = ep;
+	if (!ep->tried_with_mpa_v1) {
+		/* this means MPA_v2 is used */
+		event.ord = ep->ord;
+		event.ird = ep->ird;
+		event.private_data_len = ep->plen -
+			sizeof(struct mpa_v2_conn_params);
+		event.private_data = ep->mpa_pkt + sizeof(struct mpa_message) +
+			sizeof(struct mpa_v2_conn_params);
+	} else {
+		/* this means MPA_v1 is used. Send max supported */
+		event.ord = c4iw_max_read_depth;
+		event.ird = c4iw_max_read_depth;
+		event.private_data_len = ep->plen;
+		event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
+	}
 	if (state_read(&ep->parent_ep->com) != DEAD) {
 		c4iw_get_ep(&ep->com);
 		ep->parent_ep->com.cm_id->event_handler(
@@ -813,6 +927,8 @@
 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 	memset(&event, 0, sizeof(event));
 	event.event = IW_CM_EVENT_ESTABLISHED;
+	event.ird = ep->ird;
+	event.ord = ep->ord;
 	if (ep->com.cm_id) {
 		PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
@@ -848,7 +964,10 @@
 static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
 {
 	struct mpa_message *mpa;
+	struct mpa_v2_conn_params *mpa_v2_params;
 	u16 plen;
+	u16 resp_ird, resp_ord;
+	u8 rtr_mismatch = 0, insuff_ird = 0;
 	struct c4iw_qp_attributes attrs;
 	enum c4iw_qp_attr_mask mask;
 	int err;
@@ -888,7 +1007,9 @@
 	mpa = (struct mpa_message *) ep->mpa_pkt;
 
 	/* Validate MPA header. */
-	if (mpa->revision != mpa_rev) {
+	if (mpa->revision > mpa_rev) {
+		printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d,"
+		       " Received = %d\n", __func__, mpa_rev, mpa->revision);
 		err = -EPROTO;
 		goto err;
 	}
@@ -938,13 +1059,66 @@
 	ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
 	ep->mpa_attr.recv_marker_enabled = markers_enabled;
 	ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
-	ep->mpa_attr.version = mpa_rev;
-	ep->mpa_attr.p2p_type = peer2peer ? p2p_type :
-					    FW_RI_INIT_P2PTYPE_DISABLED;
+	ep->mpa_attr.version = mpa->revision;
+	ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
+
+	if (mpa->revision == 2) {
+		ep->mpa_attr.enhanced_rdma_conn =
+			mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0;
+		if (ep->mpa_attr.enhanced_rdma_conn) {
+			mpa_v2_params = (struct mpa_v2_conn_params *)
+				(ep->mpa_pkt + sizeof(*mpa));
+			resp_ird = ntohs(mpa_v2_params->ird) &
+				MPA_V2_IRD_ORD_MASK;
+			resp_ord = ntohs(mpa_v2_params->ord) &
+				MPA_V2_IRD_ORD_MASK;
+
+			/*
+			 * This is a double-check. Ideally, below checks are
+			 * not required since ird/ord stuff has been taken
+			 * care of in c4iw_accept_cr
+			 */
+			if ((ep->ird < resp_ord) || (ep->ord > resp_ird)) {
+				err = -ENOMEM;
+				ep->ird = resp_ord;
+				ep->ord = resp_ird;
+				insuff_ird = 1;
+			}
+
+			if (ntohs(mpa_v2_params->ird) &
+					MPA_V2_PEER2PEER_MODEL) {
+				if (ntohs(mpa_v2_params->ord) &
+						MPA_V2_RDMA_WRITE_RTR)
+					ep->mpa_attr.p2p_type =
+						FW_RI_INIT_P2PTYPE_RDMA_WRITE;
+				else if (ntohs(mpa_v2_params->ord) &
+						MPA_V2_RDMA_READ_RTR)
+					ep->mpa_attr.p2p_type =
+						FW_RI_INIT_P2PTYPE_READ_REQ;
+			}
+		}
+	} else if (mpa->revision == 1)
+		if (peer2peer)
+			ep->mpa_attr.p2p_type = p2p_type;
+
 	PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
-	     "xmit_marker_enabled=%d, version=%d\n", __func__,
-	     ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
-	     ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version);
+	     "xmit_marker_enabled=%d, version=%d p2p_type=%d local-p2p_type = "
+	     "%d\n", __func__, ep->mpa_attr.crc_enabled,
+	     ep->mpa_attr.recv_marker_enabled,
+	     ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version,
+	     ep->mpa_attr.p2p_type, p2p_type);
+
+	/*
+	 * If responder's RTR does not match with that of initiator, assign
+	 * FW_RI_INIT_P2PTYPE_DISABLED in mpa attributes so that RTR is not
+	 * generated when moving QP to RTS state.
+	 * A TERM message will be sent after QP has moved to RTS state
+	 */
+	if ((ep->mpa_attr.version == 2) &&
+			(ep->mpa_attr.p2p_type != p2p_type)) {
+		ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
+		rtr_mismatch = 1;
+	}
 
 	attrs.mpa_attr = ep->mpa_attr;
 	attrs.max_ird = ep->ird;
@@ -961,6 +1135,39 @@
 			     ep->com.qp, mask, &attrs, 1);
 	if (err)
 		goto err;
+
+	/*
+	 * If responder's RTR requirement did not match with what initiator
+	 * supports, generate TERM message
+	 */
+	if (rtr_mismatch) {
+		printk(KERN_ERR "%s: RTR mismatch, sending TERM\n", __func__);
+		attrs.layer_etype = LAYER_MPA | DDP_LLP;
+		attrs.ecode = MPA_NOMATCH_RTR;
+		attrs.next_state = C4IW_QP_STATE_TERMINATE;
+		err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
+				C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+		err = -ENOMEM;
+		goto out;
+	}
+
+	/*
+	 * Generate TERM if initiator IRD is not sufficient for responder
+	 * provided ORD. Currently, we do the same behaviour even when
+	 * responder provided IRD is also not sufficient as regards to
+	 * initiator ORD.
+	 */
+	if (insuff_ird) {
+		printk(KERN_ERR "%s: Insufficient IRD, sending TERM\n",
+				__func__);
+		attrs.layer_etype = LAYER_MPA | DDP_LLP;
+		attrs.ecode = MPA_INSUFF_IRD;
+		attrs.next_state = C4IW_QP_STATE_TERMINATE;
+		err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
+				C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+		err = -ENOMEM;
+		goto out;
+	}
 	goto out;
 err:
 	state_set(&ep->com, ABORTING);
@@ -973,6 +1180,7 @@
 static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
 {
 	struct mpa_message *mpa;
+	struct mpa_v2_conn_params *mpa_v2_params;
 	u16 plen;
 
 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
@@ -1013,7 +1221,9 @@
 	/*
 	 * Validate MPA Header.
 	 */
-	if (mpa->revision != mpa_rev) {
+	if (mpa->revision > mpa_rev) {
+		printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d,"
+		       " Received = %d\n", __func__, mpa_rev, mpa->revision);
 		abort_connection(ep, skb, GFP_KERNEL);
 		return;
 	}
@@ -1056,9 +1266,37 @@
 	ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
 	ep->mpa_attr.recv_marker_enabled = markers_enabled;
 	ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
-	ep->mpa_attr.version = mpa_rev;
-	ep->mpa_attr.p2p_type = peer2peer ? p2p_type :
-					    FW_RI_INIT_P2PTYPE_DISABLED;
+	ep->mpa_attr.version = mpa->revision;
+	if (mpa->revision == 1)
+		ep->tried_with_mpa_v1 = 1;
+	ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
+
+	if (mpa->revision == 2) {
+		ep->mpa_attr.enhanced_rdma_conn =
+			mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0;
+		if (ep->mpa_attr.enhanced_rdma_conn) {
+			mpa_v2_params = (struct mpa_v2_conn_params *)
+				(ep->mpa_pkt + sizeof(*mpa));
+			ep->ird = ntohs(mpa_v2_params->ird) &
+				MPA_V2_IRD_ORD_MASK;
+			ep->ord = ntohs(mpa_v2_params->ord) &
+				MPA_V2_IRD_ORD_MASK;
+			if (ntohs(mpa_v2_params->ird) & MPA_V2_PEER2PEER_MODEL)
+				if (peer2peer) {
+					if (ntohs(mpa_v2_params->ord) &
+							MPA_V2_RDMA_WRITE_RTR)
+						ep->mpa_attr.p2p_type =
+						FW_RI_INIT_P2PTYPE_RDMA_WRITE;
+					else if (ntohs(mpa_v2_params->ord) &
+							MPA_V2_RDMA_READ_RTR)
+						ep->mpa_attr.p2p_type =
+						FW_RI_INIT_P2PTYPE_READ_REQ;
+				}
+		}
+	} else if (mpa->revision == 1)
+		if (peer2peer)
+			ep->mpa_attr.p2p_type = p2p_type;
+
 	PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
 	     "xmit_marker_enabled=%d, version=%d p2p_type=%d\n", __func__,
 	     ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
@@ -1358,6 +1596,7 @@
 		goto reject;
 	}
 	dst = &rt->dst;
+	rcu_read_lock();
 	neigh = dst_get_neighbour(dst);
 	if (neigh->dev->flags & IFF_LOOPBACK) {
 		pdev = ip_dev_find(&init_net, peer_ip);
@@ -1384,6 +1623,7 @@
 		rss_qid = dev->rdev.lldi.rxq_ids[
 			  cxgb4_port_idx(neigh->dev) * step];
 	}
+	rcu_read_unlock();
 	if (!l2t) {
 		printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
 		       __func__);
@@ -1550,6 +1790,114 @@
 	       status == CPL_ERR_PERSIST_NEG_ADVICE;
 }
 
+static int c4iw_reconnect(struct c4iw_ep *ep)
+{
+	int err = 0;
+	struct rtable *rt;
+	struct net_device *pdev;
+	struct neighbour *neigh;
+	int step;
+
+	PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id);
+	init_timer(&ep->timer);
+
+	/*
+	 * Allocate an active TID to initiate a TCP connection.
+	 */
+	ep->atid = cxgb4_alloc_atid(ep->com.dev->rdev.lldi.tids, ep);
+	if (ep->atid == -1) {
+		printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__);
+		err = -ENOMEM;
+		goto fail2;
+	}
+
+	/* find a route */
+	rt = find_route(ep->com.dev,
+			ep->com.cm_id->local_addr.sin_addr.s_addr,
+			ep->com.cm_id->remote_addr.sin_addr.s_addr,
+			ep->com.cm_id->local_addr.sin_port,
+			ep->com.cm_id->remote_addr.sin_port, 0);
+	if (!rt) {
+		printk(KERN_ERR MOD "%s - cannot find route.\n", __func__);
+		err = -EHOSTUNREACH;
+		goto fail3;
+	}
+	ep->dst = &rt->dst;
+
+	rcu_read_lock();
+	neigh = dst_get_neighbour(ep->dst);
+
+	/* get a l2t entry */
+	if (neigh->dev->flags & IFF_LOOPBACK) {
+		PDBG("%s LOOPBACK\n", __func__);
+		pdev = ip_dev_find(&init_net,
+				   ep->com.cm_id->remote_addr.sin_addr.s_addr);
+		ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
+					neigh, pdev, 0);
+		ep->mtu = pdev->mtu;
+		ep->tx_chan = cxgb4_port_chan(pdev);
+		ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
+		step = ep->com.dev->rdev.lldi.ntxq /
+			ep->com.dev->rdev.lldi.nchan;
+		ep->txq_idx = cxgb4_port_idx(pdev) * step;
+		step = ep->com.dev->rdev.lldi.nrxq /
+			ep->com.dev->rdev.lldi.nchan;
+		ep->ctrlq_idx = cxgb4_port_idx(pdev);
+		ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
+			cxgb4_port_idx(pdev) * step];
+		dev_put(pdev);
+	} else {
+		ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
+					neigh, neigh->dev, 0);
+		ep->mtu = dst_mtu(ep->dst);
+		ep->tx_chan = cxgb4_port_chan(neigh->dev);
+		ep->smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;
+		step = ep->com.dev->rdev.lldi.ntxq /
+			ep->com.dev->rdev.lldi.nchan;
+		ep->txq_idx = cxgb4_port_idx(neigh->dev) * step;
+		ep->ctrlq_idx = cxgb4_port_idx(neigh->dev);
+		step = ep->com.dev->rdev.lldi.nrxq /
+			ep->com.dev->rdev.lldi.nchan;
+		ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
+			cxgb4_port_idx(neigh->dev) * step];
+	}
+	rcu_read_unlock();
+	if (!ep->l2t) {
+		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
+		err = -ENOMEM;
+		goto fail4;
+	}
+
+	PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n",
+	     __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid,
+	     ep->l2t->idx);
+
+	state_set(&ep->com, CONNECTING);
+	ep->tos = 0;
+
+	/* send connect request to rnic */
+	err = send_connect(ep);
+	if (!err)
+		goto out;
+
+	cxgb4_l2t_release(ep->l2t);
+fail4:
+	dst_release(ep->dst);
+fail3:
+	cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
+fail2:
+	/*
+	 * remember to send notification to upper layer.
+	 * We are in here so the upper layer is not aware that this is
+	 * re-connect attempt and so, upper layer is still waiting for
+	 * response of 1st connect request.
+	 */
+	connect_reply_upcall(ep, -ECONNRESET);
+	c4iw_put_ep(&ep->com);
+out:
+	return err;
+}
+
 static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
 {
 	struct cpl_abort_req_rss *req = cplhdr(skb);
@@ -1573,8 +1921,11 @@
 
 	/*
 	 * Wake up any threads in rdma_init() or rdma_fini().
+	 * However, this is not needed if com state is just
+	 * MPA_REQ_SENT
 	 */
-	c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
+	if (ep->com.state != MPA_REQ_SENT)
+		c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
 
 	mutex_lock(&ep->com.mutex);
 	switch (ep->com.state) {
@@ -1585,7 +1936,21 @@
 		break;
 	case MPA_REQ_SENT:
 		stop_ep_timer(ep);
-		connect_reply_upcall(ep, -ECONNRESET);
+		if (mpa_rev == 2 && ep->tried_with_mpa_v1)
+			connect_reply_upcall(ep, -ECONNRESET);
+		else {
+			/*
+			 * we just don't send notification upwards because we
+			 * want to retry with mpa_v1 without upper layers even
+			 * knowing it.
+			 *
+			 * do some housekeeping so as to re-initiate the
+			 * connection
+			 */
+			PDBG("%s: mpa_rev=%d. Retrying with mpav1\n", __func__,
+			     mpa_rev);
+			ep->retry_with_mpa_v1 = 1;
+		}
 		break;
 	case MPA_REP_SENT:
 		break;
@@ -1621,7 +1986,9 @@
 	dst_confirm(ep->dst);
 	if (ep->com.state != ABORTING) {
 		__state_set(&ep->com, DEAD);
-		release = 1;
+		/* we don't release if we want to retry with mpa_v1 */
+		if (!ep->retry_with_mpa_v1)
+			release = 1;
 	}
 	mutex_unlock(&ep->com.mutex);
 
@@ -1641,6 +2008,15 @@
 out:
 	if (release)
 		release_ep_resources(ep);
+
+	/* retry with mpa-v1 */
+	if (ep && ep->retry_with_mpa_v1) {
+		cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid);
+		dst_release(ep->dst);
+		cxgb4_l2t_release(ep->l2t);
+		c4iw_reconnect(ep);
+	}
+
 	return 0;
 }
 
@@ -1792,18 +2168,40 @@
 		goto err;
 	}
 
-	cm_id->add_ref(cm_id);
-	ep->com.cm_id = cm_id;
-	ep->com.qp = qp;
+	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
+		if (conn_param->ord > ep->ird) {
+			ep->ird = conn_param->ird;
+			ep->ord = conn_param->ord;
+			send_mpa_reject(ep, conn_param->private_data,
+					conn_param->private_data_len);
+			abort_connection(ep, NULL, GFP_KERNEL);
+			err = -ENOMEM;
+			goto err;
+		}
+		if (conn_param->ird > ep->ord) {
+			if (!ep->ord)
+				conn_param->ird = 1;
+			else {
+				abort_connection(ep, NULL, GFP_KERNEL);
+				err = -ENOMEM;
+				goto err;
+			}
+		}
 
+	}
 	ep->ird = conn_param->ird;
 	ep->ord = conn_param->ord;
 
-	if (peer2peer && ep->ird == 0)
-		ep->ird = 1;
+	if (ep->mpa_attr.version != 2)
+		if (peer2peer && ep->ird == 0)
+			ep->ird = 1;
 
 	PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord);
 
+	cm_id->add_ref(cm_id);
+	ep->com.cm_id = cm_id;
+	ep->com.qp = qp;
+
 	/* bind QP to EP and move to RTS */
 	attrs.mpa_attr = ep->mpa_attr;
 	attrs.max_ird = ep->ird;
@@ -1909,6 +2307,7 @@
 	}
 	ep->dst = &rt->dst;
 
+	rcu_read_lock();
 	neigh = dst_get_neighbour(ep->dst);
 
 	/* get a l2t entry */
@@ -1944,7 +2343,10 @@
 		       ep->com.dev->rdev.lldi.nchan;
 		ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
 			      cxgb4_port_idx(neigh->dev) * step];
+		ep->retry_with_mpa_v1 = 0;
+		ep->tried_with_mpa_v1 = 0;
 	}
+	rcu_read_unlock();
 	if (!ep->l2t) {
 		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
 		err = -ENOMEM;
@@ -2323,8 +2725,11 @@
 
 	/*
 	 * Wake up any threads in rdma_init() or rdma_fini().
+	 * However, this is not needed if com state is just
+	 * MPA_REQ_SENT
 	 */
-	c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
+	if (ep->com.state != MPA_REQ_SENT)
+		c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
 	sched(dev, skb);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb4/cq.c linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb4/cq.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb4/cq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb4/cq.c	2012-01-04 18:55:44.000000000 -0500
@@ -185,7 +185,7 @@
 				 V_CQE_OPCODE(FW_RI_SEND) |
 				 V_CQE_TYPE(0) |
 				 V_CQE_SWCQE(1) |
-				 V_CQE_QPID(wq->rq.qid));
+				 V_CQE_QPID(wq->sq.qid));
 	cqe.bits_type_ts = cpu_to_be64(V_CQE_GENBIT((u64)cq->gen));
 	cq->sw_queue[cq->sw_pidx] = cqe;
 	t4_swcq_produce(cq);
@@ -311,7 +311,7 @@
 	while (ptr != cq->sw_pidx) {
 		cqe = &cq->sw_queue[ptr];
 		if (RQ_TYPE(cqe) && (CQE_OPCODE(cqe) != FW_RI_READ_RESP) &&
-		    (CQE_QPID(cqe) == wq->rq.qid) && cqe_completes_wr(cqe, wq))
+		    (CQE_QPID(cqe) == wq->sq.qid) && cqe_completes_wr(cqe, wq))
 			(*count)++;
 		if (++ptr == cq->size)
 			ptr = 0;
@@ -818,6 +818,7 @@
 	chp->cq.size--;				/* status page */
 	chp->ibcq.cqe = entries - 2;
 	spin_lock_init(&chp->lock);
+	spin_lock_init(&chp->comp_handler_lock);
 	atomic_set(&chp->refcnt, 1);
 	init_waitqueue_head(&chp->wait);
 	ret = insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid);
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb4/device.c linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb4/device.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb4/device.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb4/device.c	2012-01-04 18:55:44.000000000 -0500
@@ -376,10 +376,8 @@
 	struct c4iw_dev *dev;
 };
 
-static void c4iw_remove(struct uld_ctx *ctx)
+static void c4iw_dealloc(struct uld_ctx *ctx)
 {
-	PDBG("%s c4iw_dev %p\n", __func__,  ctx->dev);
-	c4iw_unregister_device(ctx->dev);
 	c4iw_rdev_close(&ctx->dev->rdev);
 	idr_destroy(&ctx->dev->cqidr);
 	idr_destroy(&ctx->dev->qpidr);
@@ -389,11 +387,30 @@
 	ctx->dev = NULL;
 }
 
+static void c4iw_remove(struct uld_ctx *ctx)
+{
+	PDBG("%s c4iw_dev %p\n", __func__,  ctx->dev);
+	c4iw_unregister_device(ctx->dev);
+	c4iw_dealloc(ctx);
+}
+
+static int rdma_supported(const struct cxgb4_lld_info *infop)
+{
+	return infop->vr->stag.size > 0 && infop->vr->pbl.size > 0 &&
+	       infop->vr->rq.size > 0 && infop->vr->qp.size > 0 &&
+	       infop->vr->cq.size > 0 && infop->vr->ocq.size > 0;
+}
+
 static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
 {
 	struct c4iw_dev *devp;
 	int ret;
 
+	if (!rdma_supported(infop)) {
+		printk(KERN_INFO MOD "%s: RDMA not supported on this device.\n",
+		       pci_name(infop->pdev));
+		return ERR_PTR(-ENOSYS);
+	}
 	devp = (struct c4iw_dev *)ib_alloc_device(sizeof(*devp));
 	if (!devp) {
 		printk(KERN_ERR MOD "Cannot allocate ib device\n");
@@ -414,7 +431,6 @@
 
 	ret = c4iw_rdev_open(&devp->rdev);
 	if (ret) {
-		mutex_unlock(&dev_mutex);
 		printk(KERN_ERR MOD "Unable to open CXIO rdev err %d\n", ret);
 		ib_dealloc_device(&devp->ibdev);
 		return ERR_PTR(ret);
@@ -519,15 +535,24 @@
 	case CXGB4_STATE_UP:
 		printk(KERN_INFO MOD "%s: Up\n", pci_name(ctx->lldi.pdev));
 		if (!ctx->dev) {
-			int ret = 0;
+			int ret;
 
 			ctx->dev = c4iw_alloc(&ctx->lldi);
-			if (!IS_ERR(ctx->dev))
-				ret = c4iw_register_device(ctx->dev);
-			if (IS_ERR(ctx->dev) || ret)
+			if (IS_ERR(ctx->dev)) {
+				printk(KERN_ERR MOD
+				       "%s: initialization failed: %ld\n",
+				       pci_name(ctx->lldi.pdev),
+				       PTR_ERR(ctx->dev));
+				ctx->dev = NULL;
+				break;
+			}
+			ret = c4iw_register_device(ctx->dev);
+			if (ret) {
 				printk(KERN_ERR MOD
 				       "%s: RDMA registration failed: %d\n",
 				       pci_name(ctx->lldi.pdev), ret);
+				c4iw_dealloc(ctx);
+			}
 		}
 		break;
 	case CXGB4_STATE_DOWN:
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb4/ev.c linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb4/ev.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb4/ev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb4/ev.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,6 +42,7 @@
 {
 	struct ib_event event;
 	struct c4iw_qp_attributes attrs;
+	unsigned long flag;
 
 	if ((qhp->attr.state == C4IW_QP_STATE_ERROR) ||
 	    (qhp->attr.state == C4IW_QP_STATE_TERMINATE)) {
@@ -72,7 +73,9 @@
 	if (qhp->ibqp.event_handler)
 		(*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
 
+	spin_lock_irqsave(&chp->comp_handler_lock, flag);
 	(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+	spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
 }
 
 void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
@@ -183,11 +186,14 @@
 int c4iw_ev_handler(struct c4iw_dev *dev, u32 qid)
 {
 	struct c4iw_cq *chp;
+	unsigned long flag;
 
 	chp = get_chp(dev, qid);
-	if (chp)
+	if (chp) {
+		spin_lock_irqsave(&chp->comp_handler_lock, flag);
 		(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
-	else
+		spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
+	} else
 		PDBG("%s unknown cqid 0x%x\n", __func__, qid);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
--- linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h	2012-01-04 18:55:44.000000000 -0500
@@ -309,6 +309,7 @@
 	struct c4iw_dev *rhp;
 	struct t4_cq cq;
 	spinlock_t lock;
+	spinlock_t comp_handler_lock;
 	atomic_t refcnt;
 	wait_queue_head_t wait;
 };
@@ -323,6 +324,7 @@
 	u8 recv_marker_enabled;
 	u8 xmit_marker_enabled;
 	u8 crc_enabled;
+	u8 enhanced_rdma_conn;
 	u8 version;
 	u8 p2p_type;
 };
@@ -349,6 +351,8 @@
 	u8 is_terminate_local;
 	struct c4iw_mpa_attributes mpa_attr;
 	struct c4iw_ep *llp_stream_handle;
+	u8 layer_etype;
+	u8 ecode;
 };
 
 struct c4iw_qp {
@@ -501,11 +505,18 @@
 #define MPA_KEY_REP "MPA ID Rep Frame"
 
 #define MPA_MAX_PRIVATE_DATA	256
+#define MPA_ENHANCED_RDMA_CONN	0x10
 #define MPA_REJECT		0x20
 #define MPA_CRC			0x40
 #define MPA_MARKERS		0x80
 #define MPA_FLAGS_MASK		0xE0
 
+#define MPA_V2_PEER2PEER_MODEL          0x8000
+#define MPA_V2_ZERO_LEN_FPDU_RTR        0x4000
+#define MPA_V2_RDMA_WRITE_RTR           0x8000
+#define MPA_V2_RDMA_READ_RTR            0x4000
+#define MPA_V2_IRD_ORD_MASK             0x3FFF
+
 #define c4iw_put_ep(ep) { \
 	PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __func__, __LINE__,  \
 	     ep, atomic_read(&((ep)->kref.refcount))); \
@@ -528,6 +539,11 @@
 	u8 private_data[0];
 };
 
+struct mpa_v2_conn_params {
+	__be16 ird;
+	__be16 ord;
+};
+
 struct terminate_message {
 	u8 layer_etype;
 	u8 ecode;
@@ -580,7 +596,10 @@
 
 enum c4iw_mpa_ecodes {
 	MPA_CRC_ERR		= 0x02,
-	MPA_MARKER_ERR		= 0x03
+	MPA_MARKER_ERR          = 0x03,
+	MPA_LOCAL_CATA          = 0x05,
+	MPA_INSUFF_IRD          = 0x06,
+	MPA_NOMATCH_RTR         = 0x07,
 };
 
 enum c4iw_ep_state {
@@ -651,6 +670,8 @@
 	u16 txq_idx;
 	u16 ctrlq_idx;
 	u8 tos;
+	u8 retry_with_mpa_v1;
+	u8 tried_with_mpa_v1;
 };
 
 static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id)
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb4/Makefile linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb4/Makefile
--- linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb4/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb4/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-ccflags-y := -Idrivers/net/cxgb4
+ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4
 
 obj-$(CONFIG_INFINIBAND_CXGB4) += iw_cxgb4.o
 
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb4/qp.c linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb4/qp.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/cxgb4/qp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/cxgb4/qp.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,9 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
+
+#include <linux/module.h>
+
 #include "iw_cxgb4.h"
 
 static int ocqp_support = 1;
@@ -917,7 +920,11 @@
 	wqe->u.terminate.type = FW_RI_TYPE_TERMINATE;
 	wqe->u.terminate.immdlen = cpu_to_be32(sizeof *term);
 	term = (struct terminate_message *)wqe->u.terminate.termmsg;
-	build_term_codes(err_cqe, &term->layer_etype, &term->ecode);
+	if (qhp->attr.layer_etype == (LAYER_MPA|DDP_LLP)) {
+		term->layer_etype = qhp->attr.layer_etype;
+		term->ecode = qhp->attr.ecode;
+	} else
+		build_term_codes(err_cqe, &term->layer_etype, &term->ecode);
 	c4iw_ofld_send(&qhp->rhp->rdev, skb);
 }
 
@@ -941,8 +948,11 @@
 	flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count);
 	spin_unlock(&qhp->lock);
 	spin_unlock_irqrestore(&rchp->lock, flag);
-	if (flushed)
+	if (flushed) {
+		spin_lock_irqsave(&rchp->comp_handler_lock, flag);
 		(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+		spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
+	}
 
 	/* locking hierarchy: cq lock first, then qp lock. */
 	spin_lock_irqsave(&schp->lock, flag);
@@ -952,13 +962,17 @@
 	flushed = c4iw_flush_sq(&qhp->wq, &schp->cq, count);
 	spin_unlock(&qhp->lock);
 	spin_unlock_irqrestore(&schp->lock, flag);
-	if (flushed)
+	if (flushed) {
+		spin_lock_irqsave(&schp->comp_handler_lock, flag);
 		(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
+		spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
+	}
 }
 
 static void flush_qp(struct c4iw_qp *qhp)
 {
 	struct c4iw_cq *rchp, *schp;
+	unsigned long flag;
 
 	rchp = get_chp(qhp->rhp, qhp->attr.rcq);
 	schp = get_chp(qhp->rhp, qhp->attr.scq);
@@ -966,8 +980,16 @@
 	if (qhp->ibqp.uobject) {
 		t4_set_wq_in_error(&qhp->wq);
 		t4_set_cq_in_error(&rchp->cq);
-		if (schp != rchp)
+		spin_lock_irqsave(&rchp->comp_handler_lock, flag);
+		(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+		spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
+		if (schp != rchp) {
 			t4_set_cq_in_error(&schp->cq);
+			spin_lock_irqsave(&schp->comp_handler_lock, flag);
+			(*schp->ibcq.comp_handler)(&schp->ibcq,
+					schp->ibcq.cq_context);
+			spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
+		}
 		return;
 	}
 	__flush_qp(qhp, rchp, schp);
@@ -1012,6 +1034,7 @@
 
 static void build_rtr_msg(u8 p2p_type, struct fw_ri_init *init)
 {
+	PDBG("%s p2p_type = %d\n", __func__, p2p_type);
 	memset(&init->u, 0, sizeof init->u);
 	switch (p2p_type) {
 	case FW_RI_INIT_P2PTYPE_RDMA_WRITE:
@@ -1206,12 +1229,16 @@
 				disconnect = 1;
 				c4iw_get_ep(&qhp->ep->com);
 			}
+			if (qhp->ibqp.uobject)
+				t4_set_wq_in_error(&qhp->wq);
 			ret = rdma_fini(rhp, qhp, ep);
 			if (ret)
 				goto err;
 			break;
 		case C4IW_QP_STATE_TERMINATE:
 			set_state(qhp, C4IW_QP_STATE_TERMINATE);
+			qhp->attr.layer_etype = attrs->layer_etype;
+			qhp->attr.ecode = attrs->ecode;
 			if (qhp->ibqp.uobject)
 				t4_set_wq_in_error(&qhp->wq);
 			ep = qhp->ep;
@@ -1222,6 +1249,8 @@
 			break;
 		case C4IW_QP_STATE_ERROR:
 			set_state(qhp, C4IW_QP_STATE_ERROR);
+			if (qhp->ibqp.uobject)
+				t4_set_wq_in_error(&qhp->wq);
 			if (!internal) {
 				abort = 1;
 				disconnect = 1;
@@ -1334,7 +1363,10 @@
 	rhp = qhp->rhp;
 
 	attrs.next_state = C4IW_QP_STATE_ERROR;
-	c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+	if (qhp->attr.state == C4IW_QP_STATE_TERMINATE)
+		c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
+	else
+		c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
 	wait_event(qhp->wait, !qhp->ep);
 
 	remove_handle(rhp, &rhp->qpidr, qhp->wq.sq.qid);
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/ehca/ehca_eq.c linux-libre-3.2-gnu/drivers/infiniband/hw/ehca/ehca_eq.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/ehca/ehca_eq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/ehca/ehca_eq.c	2012-01-04 18:55:44.000000000 -0500
@@ -125,7 +125,7 @@
 		tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca);
 
 		ret = ibmebus_request_irq(eq->ist, ehca_interrupt_eq,
-					  IRQF_DISABLED, "ehca_eq",
+					  0, "ehca_eq",
 					  (void *)shca);
 		if (ret < 0)
 			ehca_err(ib_dev, "Can't map interrupt handler.");
@@ -133,7 +133,7 @@
 		tasklet_init(&eq->interrupt_task, ehca_tasklet_neq, (long)shca);
 
 		ret = ibmebus_request_irq(eq->ist, ehca_interrupt_neq,
-					  IRQF_DISABLED, "ehca_neq",
+					  0, "ehca_neq",
 					  (void *)shca);
 		if (ret < 0)
 			ehca_err(ib_dev, "Can't map interrupt handler.");
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/ehca/ehca_qp.c linux-libre-3.2-gnu/drivers/infiniband/hw/ehca/ehca_qp.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/ehca/ehca_qp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/ehca/ehca_qp.c	2012-01-04 18:55:44.000000000 -0500
@@ -977,6 +977,9 @@
 	struct hcp_modify_qp_control_block *mqpcb;
 	u64 hret, update_mask;
 
+	if (srq_init_attr->srq_type != IB_SRQT_BASIC)
+		return ERR_PTR(-ENOSYS);
+
 	/* For common attributes, internal_create_qp() takes its info
 	 * out of qp_init_attr, so copy all common attrs there.
 	 */
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/ipath/ipath_diag.c linux-libre-3.2-gnu/drivers/infiniband/hw/ipath/ipath_diag.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/ipath/ipath_diag.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/ipath/ipath_diag.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,6 +45,7 @@
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
+#include <linux/export.h>
 #include <asm/uaccess.h>
 
 #include "ipath_kernel.h"
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/ipath/ipath_driver.c linux-libre-3.2-gnu/drivers/infiniband/hw/ipath/ipath_driver.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/ipath/ipath_driver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/ipath/ipath_driver.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,7 @@
 #include <linux/vmalloc.h>
 #include <linux/bitmap.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include "ipath_kernel.h"
 #include "ipath_verbs.h"
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/ipath/ipath_file_ops.c linux-libre-3.2-gnu/drivers/infiniband/hw/ipath/ipath_file_ops.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/ipath/ipath_file_ops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/ipath/ipath_file_ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <linux/poll.h>
 #include <linux/cdev.h>
 #include <linux/swap.h>
+#include <linux/export.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 #include <linux/highmem.h>
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/ipath/ipath_init_chip.c linux-libre-3.2-gnu/drivers/infiniband/hw/ipath/ipath_init_chip.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/ipath/ipath_init_chip.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/ipath/ipath_init_chip.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,9 @@
 
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/moduleparam.h>
 #include <linux/slab.h>
+#include <linux/stat.h>
 #include <linux/vmalloc.h>
 
 #include "ipath_kernel.h"
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/ipath/ipath_srq.c linux-libre-3.2-gnu/drivers/infiniband/hw/ipath/ipath_srq.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/ipath/ipath_srq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/ipath/ipath_srq.c	2012-01-04 18:55:44.000000000 -0500
@@ -107,6 +107,11 @@
 	u32 sz;
 	struct ib_srq *ret;
 
+	if (srq_init_attr->srq_type != IB_SRQT_BASIC) {
+		ret = ERR_PTR(-ENOSYS);
+		goto done;
+	}
+
 	if (srq_init_attr->attr.max_wr == 0) {
 		ret = ERR_PTR(-EINVAL);
 		goto done;
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/ipath/ipath_sysfs.c linux-libre-3.2-gnu/drivers/infiniband/hw/ipath/ipath_sysfs.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/ipath/ipath_sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/ipath/ipath_sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
  */
 
 #include <linux/ctype.h>
+#include <linux/stat.h>
 
 #include "ipath_kernel.h"
 #include "ipath_verbs.h"
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/ipath/ipath_user_pages.c linux-libre-3.2-gnu/drivers/infiniband/hw/ipath/ipath_user_pages.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/ipath/ipath_user_pages.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/ipath/ipath_user_pages.c	2012-01-04 18:55:44.000000000 -0500
@@ -79,7 +79,7 @@
 			goto bail_release;
 	}
 
-	current->mm->locked_vm += num_pages;
+	current->mm->pinned_vm += num_pages;
 
 	ret = 0;
 	goto bail;
@@ -178,7 +178,7 @@
 
 	__ipath_release_user_pages(p, num_pages, 1);
 
-	current->mm->locked_vm -= num_pages;
+	current->mm->pinned_vm -= num_pages;
 
 	up_write(&current->mm->mmap_sem);
 }
@@ -195,7 +195,7 @@
 		container_of(_work, struct ipath_user_pages_work, work);
 
 	down_write(&work->mm->mmap_sem);
-	work->mm->locked_vm -= work->num_pages;
+	work->mm->pinned_vm -= work->num_pages;
 	up_write(&work->mm->mmap_sem);
 	mmput(work->mm);
 	kfree(work);
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/ipath/ipath_verbs.c linux-libre-3.2-gnu/drivers/infiniband/hw/ipath/ipath_verbs.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/ipath/ipath_verbs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/ipath/ipath_verbs.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <rdma/ib_user_verbs.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <linux/utsname.h>
 #include <linux/rculist.h>
 
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/mlx4/Kconfig linux-libre-3.2-gnu/drivers/infiniband/hw/mlx4/Kconfig
--- linux-libre-3.1-gnu/drivers/infiniband/hw/mlx4/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/mlx4/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,7 @@
 config MLX4_INFINIBAND
 	tristate "Mellanox ConnectX HCA support"
-	depends on NETDEVICES && NETDEV_10000 && PCI
+	depends on NETDEVICES && ETHERNET && PCI
+	select NET_VENDOR_MELLANOX
 	select MLX4_CORE
 	---help---
 	  This driver provides low-level InfiniBand support for
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/mlx4/main.c linux-libre-3.2-gnu/drivers/infiniband/hw/mlx4/main.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/mlx4/main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/mlx4/main.c	2012-01-04 18:55:44.000000000 -0500
@@ -128,6 +128,8 @@
 	    (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_REMOTE_INV) &&
 	    (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_FAST_REG_WR))
 		props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
+	if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC)
+		props->device_cap_flags |= IB_DEVICE_XRC;
 
 	props->vendor_id	   = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
 		0xffffff;
@@ -181,8 +183,12 @@
 
 static int ib_link_query_port(struct ib_device *ibdev, u8 port,
 			      struct ib_port_attr *props,
+			      struct ib_smp *in_mad,
 			      struct ib_smp *out_mad)
 {
+	int ext_active_speed;
+	int err;
+
 	props->lid		= be16_to_cpup((__be16 *) (out_mad->data + 16));
 	props->lmc		= out_mad->data[34] & 0x7;
 	props->sm_lid		= be16_to_cpup((__be16 *) (out_mad->data + 18));
@@ -203,6 +209,39 @@
 	props->max_vl_num	= out_mad->data[37] >> 4;
 	props->init_type_reply	= out_mad->data[41] >> 4;
 
+	/* Check if extended speeds (EDR/FDR/...) are supported */
+	if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) {
+		ext_active_speed = out_mad->data[62] >> 4;
+
+		switch (ext_active_speed) {
+		case 1:
+			props->active_speed = 16; /* FDR */
+			break;
+		case 2:
+			props->active_speed = 32; /* EDR */
+			break;
+		}
+	}
+
+	/* If reported active speed is QDR, check if is FDR-10 */
+	if (props->active_speed == 4) {
+		if (to_mdev(ibdev)->dev->caps.ext_port_cap[port] &
+		    MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) {
+			init_query_mad(in_mad);
+			in_mad->attr_id = MLX4_ATTR_EXTENDED_PORT_INFO;
+			in_mad->attr_mod = cpu_to_be32(port);
+
+			err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port,
+					   NULL, NULL, in_mad, out_mad);
+			if (err)
+				return err;
+
+			/* Checking LinkSpeedActive for FDR-10 */
+			if (out_mad->data[15] & 0x1)
+				props->active_speed = 8;
+		}
+	}
+
 	return 0;
 }
 
@@ -227,7 +266,7 @@
 	props->pkey_tbl_len	= 1;
 	props->bad_pkey_cntr	= be16_to_cpup((__be16 *) (out_mad->data + 46));
 	props->qkey_viol_cntr	= be16_to_cpup((__be16 *) (out_mad->data + 48));
-	props->max_mtu		= IB_MTU_2048;
+	props->max_mtu		= IB_MTU_4096;
 	props->subnet_timeout	= 0;
 	props->max_vl_num	= out_mad->data[37] >> 4;
 	props->init_type_reply	= 0;
@@ -274,7 +313,7 @@
 		goto out;
 
 	err = mlx4_ib_port_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND ?
-		ib_link_query_port(ibdev, port, props, out_mad) :
+		ib_link_query_port(ibdev, port, props, in_mad, out_mad) :
 		eth_link_query_port(ibdev, port, props, out_mad);
 
 out:
@@ -566,6 +605,57 @@
 	return 0;
 }
 
+static struct ib_xrcd *mlx4_ib_alloc_xrcd(struct ib_device *ibdev,
+					  struct ib_ucontext *context,
+					  struct ib_udata *udata)
+{
+	struct mlx4_ib_xrcd *xrcd;
+	int err;
+
+	if (!(to_mdev(ibdev)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
+		return ERR_PTR(-ENOSYS);
+
+	xrcd = kmalloc(sizeof *xrcd, GFP_KERNEL);
+	if (!xrcd)
+		return ERR_PTR(-ENOMEM);
+
+	err = mlx4_xrcd_alloc(to_mdev(ibdev)->dev, &xrcd->xrcdn);
+	if (err)
+		goto err1;
+
+	xrcd->pd = ib_alloc_pd(ibdev);
+	if (IS_ERR(xrcd->pd)) {
+		err = PTR_ERR(xrcd->pd);
+		goto err2;
+	}
+
+	xrcd->cq = ib_create_cq(ibdev, NULL, NULL, xrcd, 1, 0);
+	if (IS_ERR(xrcd->cq)) {
+		err = PTR_ERR(xrcd->cq);
+		goto err3;
+	}
+
+	return &xrcd->ibxrcd;
+
+err3:
+	ib_dealloc_pd(xrcd->pd);
+err2:
+	mlx4_xrcd_free(to_mdev(ibdev)->dev, xrcd->xrcdn);
+err1:
+	kfree(xrcd);
+	return ERR_PTR(err);
+}
+
+static int mlx4_ib_dealloc_xrcd(struct ib_xrcd *xrcd)
+{
+	ib_destroy_cq(to_mxrcd(xrcd)->cq);
+	ib_dealloc_pd(to_mxrcd(xrcd)->pd);
+	mlx4_xrcd_free(to_mdev(xrcd->device)->dev, to_mxrcd(xrcd)->xrcdn);
+	kfree(xrcd);
+
+	return 0;
+}
+
 static int add_gid_entry(struct ib_qp *ibqp, union ib_gid *gid)
 {
 	struct mlx4_ib_qp *mqp = to_mqp(ibqp);
@@ -1044,7 +1134,9 @@
 		(1ull << IB_USER_VERBS_CMD_CREATE_SRQ)		|
 		(1ull << IB_USER_VERBS_CMD_MODIFY_SRQ)		|
 		(1ull << IB_USER_VERBS_CMD_QUERY_SRQ)		|
-		(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
+		(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ)		|
+		(1ull << IB_USER_VERBS_CMD_CREATE_XSRQ)		|
+		(1ull << IB_USER_VERBS_CMD_OPEN_QP);
 
 	ibdev->ib_dev.query_device	= mlx4_ib_query_device;
 	ibdev->ib_dev.query_port	= mlx4_ib_query_port;
@@ -1093,6 +1185,14 @@
 	ibdev->ib_dev.unmap_fmr		= mlx4_ib_unmap_fmr;
 	ibdev->ib_dev.dealloc_fmr	= mlx4_ib_fmr_dealloc;
 
+	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) {
+		ibdev->ib_dev.alloc_xrcd = mlx4_ib_alloc_xrcd;
+		ibdev->ib_dev.dealloc_xrcd = mlx4_ib_dealloc_xrcd;
+		ibdev->ib_dev.uverbs_cmd_mask |=
+			(1ull << IB_USER_VERBS_CMD_OPEN_XRCD) |
+			(1ull << IB_USER_VERBS_CMD_CLOSE_XRCD);
+	}
+
 	spin_lock_init(&iboe->lock);
 
 	if (init_node_data(ibdev))
@@ -1144,7 +1244,8 @@
 
 err_counter:
 	for (; i; --i)
-		mlx4_counter_free(ibdev->dev, ibdev->counters[i - 1]);
+		if (ibdev->counters[i - 1] != -1)
+			mlx4_counter_free(ibdev->dev, ibdev->counters[i - 1]);
 
 err_map:
 	iounmap(ibdev->uar_map);
@@ -1175,7 +1276,8 @@
 	}
 	iounmap(ibdev->uar_map);
 	for (p = 0; p < ibdev->num_ports; ++p)
-		mlx4_counter_free(ibdev->dev, ibdev->counters[p]);
+		if (ibdev->counters[p] != -1)
+			mlx4_counter_free(ibdev->dev, ibdev->counters[p]);
 	mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB)
 		mlx4_CLOSE_PORT(dev, p);
 
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/mlx4/mlx4_ib.h linux-libre-3.2-gnu/drivers/infiniband/hw/mlx4/mlx4_ib.h
--- linux-libre-3.1-gnu/drivers/infiniband/hw/mlx4/mlx4_ib.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/mlx4/mlx4_ib.h	2012-01-04 18:55:44.000000000 -0500
@@ -56,6 +56,13 @@
 	u32			pdn;
 };
 
+struct mlx4_ib_xrcd {
+	struct ib_xrcd		ibxrcd;
+	u32			xrcdn;
+	struct ib_pd	       *pd;
+	struct ib_cq	       *cq;
+};
+
 struct mlx4_ib_cq_buf {
 	struct mlx4_buf		buf;
 	struct mlx4_mtt		mtt;
@@ -138,6 +145,7 @@
 	struct mlx4_mtt		mtt;
 	int			buf_size;
 	struct mutex		mutex;
+	u16			xrcdn;
 	u32			flags;
 	u8			port;
 	u8			alt_port;
@@ -211,6 +219,11 @@
 	return container_of(ibpd, struct mlx4_ib_pd, ibpd);
 }
 
+static inline struct mlx4_ib_xrcd *to_mxrcd(struct ib_xrcd *ibxrcd)
+{
+	return container_of(ibxrcd, struct mlx4_ib_xrcd, ibxrcd);
+}
+
 static inline struct mlx4_ib_cq *to_mcq(struct ib_cq *ibcq)
 {
 	return container_of(ibcq, struct mlx4_ib_cq, ibcq);
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/mlx4/qp.c linux-libre-3.2-gnu/drivers/infiniband/hw/mlx4/qp.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/mlx4/qp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/mlx4/qp.c	2012-01-04 18:55:44.000000000 -0500
@@ -302,15 +302,14 @@
 }
 
 static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
-		       int is_user, int has_srq, struct mlx4_ib_qp *qp)
+		       int is_user, int has_rq, struct mlx4_ib_qp *qp)
 {
 	/* Sanity check RQ size before proceeding */
 	if (cap->max_recv_wr  > dev->dev->caps.max_wqes  ||
 	    cap->max_recv_sge > dev->dev->caps.max_rq_sg)
 		return -EINVAL;
 
-	if (has_srq) {
-		/* QPs attached to an SRQ should have no RQ */
+	if (!has_rq) {
 		if (cap->max_recv_wr)
 			return -EINVAL;
 
@@ -463,6 +462,14 @@
 	return 0;
 }
 
+static int qp_has_rq(struct ib_qp_init_attr *attr)
+{
+	if (attr->qp_type == IB_QPT_XRC_INI || attr->qp_type == IB_QPT_XRC_TGT)
+		return 0;
+
+	return !attr->srq;
+}
+
 static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 			    struct ib_qp_init_attr *init_attr,
 			    struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp)
@@ -479,7 +486,7 @@
 	if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
 		qp->sq_signal_bits = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE);
 
-	err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, !!init_attr->srq, qp);
+	err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, qp_has_rq(init_attr), qp);
 	if (err)
 		goto err;
 
@@ -513,7 +520,7 @@
 		if (err)
 			goto err_mtt;
 
-		if (!init_attr->srq) {
+		if (qp_has_rq(init_attr)) {
 			err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context),
 						  ucmd.db_addr, &qp->db);
 			if (err)
@@ -532,7 +539,7 @@
 		if (err)
 			goto err;
 
-		if (!init_attr->srq) {
+		if (qp_has_rq(init_attr)) {
 			err = mlx4_db_alloc(dev->dev, &qp->db, 0);
 			if (err)
 				goto err;
@@ -575,6 +582,9 @@
 	if (err)
 		goto err_qpn;
 
+	if (init_attr->qp_type == IB_QPT_XRC_TGT)
+		qp->mqp.qpn |= (1 << 23);
+
 	/*
 	 * Hardware wants QPN written in big-endian order (after
 	 * shifting) for send doorbell.  Precompute this value to save
@@ -592,9 +602,8 @@
 
 err_wrid:
 	if (pd->uobject) {
-		if (!init_attr->srq)
-			mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context),
-					      &qp->db);
+		if (qp_has_rq(init_attr))
+			mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &qp->db);
 	} else {
 		kfree(qp->sq.wrid);
 		kfree(qp->rq.wrid);
@@ -610,7 +619,7 @@
 		mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
 
 err_db:
-	if (!pd->uobject && !init_attr->srq)
+	if (!pd->uobject && qp_has_rq(init_attr))
 		mlx4_db_free(dev->dev, &qp->db);
 
 err:
@@ -671,6 +680,33 @@
 	}
 }
 
+static struct mlx4_ib_pd *get_pd(struct mlx4_ib_qp *qp)
+{
+	if (qp->ibqp.qp_type == IB_QPT_XRC_TGT)
+		return to_mpd(to_mxrcd(qp->ibqp.xrcd)->pd);
+	else
+		return to_mpd(qp->ibqp.pd);
+}
+
+static void get_cqs(struct mlx4_ib_qp *qp,
+		    struct mlx4_ib_cq **send_cq, struct mlx4_ib_cq **recv_cq)
+{
+	switch (qp->ibqp.qp_type) {
+	case IB_QPT_XRC_TGT:
+		*send_cq = to_mcq(to_mxrcd(qp->ibqp.xrcd)->cq);
+		*recv_cq = *send_cq;
+		break;
+	case IB_QPT_XRC_INI:
+		*send_cq = to_mcq(qp->ibqp.send_cq);
+		*recv_cq = *send_cq;
+		break;
+	default:
+		*send_cq = to_mcq(qp->ibqp.send_cq);
+		*recv_cq = to_mcq(qp->ibqp.recv_cq);
+		break;
+	}
+}
+
 static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
 			      int is_user)
 {
@@ -682,8 +718,7 @@
 			printk(KERN_WARNING "mlx4_ib: modify QP %06x to RESET failed.\n",
 			       qp->mqp.qpn);
 
-	send_cq = to_mcq(qp->ibqp.send_cq);
-	recv_cq = to_mcq(qp->ibqp.recv_cq);
+	get_cqs(qp, &send_cq, &recv_cq);
 
 	mlx4_ib_lock_cqs(send_cq, recv_cq);
 
@@ -706,7 +741,7 @@
 	mlx4_mtt_cleanup(dev->dev, &qp->mtt);
 
 	if (is_user) {
-		if (!qp->ibqp.srq)
+		if (qp->rq.wqe_cnt)
 			mlx4_ib_db_unmap_user(to_mucontext(qp->ibqp.uobject->context),
 					      &qp->db);
 		ib_umem_release(qp->umem);
@@ -714,7 +749,7 @@
 		kfree(qp->sq.wrid);
 		kfree(qp->rq.wrid);
 		mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
-		if (!qp->ibqp.srq)
+		if (qp->rq.wqe_cnt)
 			mlx4_db_free(dev->dev, &qp->db);
 	}
 
@@ -725,10 +760,10 @@
 				struct ib_qp_init_attr *init_attr,
 				struct ib_udata *udata)
 {
-	struct mlx4_ib_dev *dev = to_mdev(pd->device);
 	struct mlx4_ib_sqp *sqp;
 	struct mlx4_ib_qp *qp;
 	int err;
+	u16 xrcdn = 0;
 
 	/*
 	 * We only support LSO and multicast loopback blocking, and
@@ -739,10 +774,20 @@
 		return ERR_PTR(-EINVAL);
 
 	if (init_attr->create_flags &&
-	    (pd->uobject || init_attr->qp_type != IB_QPT_UD))
+	    (udata || init_attr->qp_type != IB_QPT_UD))
 		return ERR_PTR(-EINVAL);
 
 	switch (init_attr->qp_type) {
+	case IB_QPT_XRC_TGT:
+		pd = to_mxrcd(init_attr->xrcd)->pd;
+		xrcdn = to_mxrcd(init_attr->xrcd)->xrcdn;
+		init_attr->send_cq = to_mxrcd(init_attr->xrcd)->cq;
+		/* fall through */
+	case IB_QPT_XRC_INI:
+		if (!(to_mdev(pd->device)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
+			return ERR_PTR(-ENOSYS);
+		init_attr->recv_cq = init_attr->send_cq;
+		/* fall through */
 	case IB_QPT_RC:
 	case IB_QPT_UC:
 	case IB_QPT_UD:
@@ -751,13 +796,14 @@
 		if (!qp)
 			return ERR_PTR(-ENOMEM);
 
-		err = create_qp_common(dev, pd, init_attr, udata, 0, qp);
+		err = create_qp_common(to_mdev(pd->device), pd, init_attr, udata, 0, qp);
 		if (err) {
 			kfree(qp);
 			return ERR_PTR(err);
 		}
 
 		qp->ibqp.qp_num = qp->mqp.qpn;
+		qp->xrcdn = xrcdn;
 
 		break;
 	}
@@ -765,7 +811,7 @@
 	case IB_QPT_GSI:
 	{
 		/* Userspace is not allowed to create special QPs: */
-		if (pd->uobject)
+		if (udata)
 			return ERR_PTR(-EINVAL);
 
 		sqp = kzalloc(sizeof *sqp, GFP_KERNEL);
@@ -774,8 +820,8 @@
 
 		qp = &sqp->qp;
 
-		err = create_qp_common(dev, pd, init_attr, udata,
-				       dev->dev->caps.sqp_start +
+		err = create_qp_common(to_mdev(pd->device), pd, init_attr, udata,
+				       to_mdev(pd->device)->dev->caps.sqp_start +
 				       (init_attr->qp_type == IB_QPT_SMI ? 0 : 2) +
 				       init_attr->port_num - 1,
 				       qp);
@@ -801,11 +847,13 @@
 {
 	struct mlx4_ib_dev *dev = to_mdev(qp->device);
 	struct mlx4_ib_qp *mqp = to_mqp(qp);
+	struct mlx4_ib_pd *pd;
 
 	if (is_qp0(dev, mqp))
 		mlx4_CLOSE_PORT(dev->dev, mqp->port);
 
-	destroy_qp_common(dev, mqp, !!qp->pd->uobject);
+	pd = get_pd(mqp);
+	destroy_qp_common(dev, mqp, !!pd->ibpd.uobject);
 
 	if (is_sqp(dev, mqp))
 		kfree(to_msqp(mqp));
@@ -821,6 +869,8 @@
 	case IB_QPT_RC:		return MLX4_QP_ST_RC;
 	case IB_QPT_UC:		return MLX4_QP_ST_UC;
 	case IB_QPT_UD:		return MLX4_QP_ST_UD;
+	case IB_QPT_XRC_INI:
+	case IB_QPT_XRC_TGT:	return MLX4_QP_ST_XRC;
 	case IB_QPT_SMI:
 	case IB_QPT_GSI:	return MLX4_QP_ST_MLX;
 	default:		return -1;
@@ -959,6 +1009,8 @@
 {
 	struct mlx4_ib_dev *dev = to_mdev(ibqp->device);
 	struct mlx4_ib_qp *qp = to_mqp(ibqp);
+	struct mlx4_ib_pd *pd;
+	struct mlx4_ib_cq *send_cq, *recv_cq;
 	struct mlx4_qp_context *context;
 	enum mlx4_qp_optpar optpar = 0;
 	int sqd_event;
@@ -1014,8 +1066,10 @@
 		context->sq_size_stride = ilog2(qp->sq.wqe_cnt) << 3;
 	context->sq_size_stride |= qp->sq.wqe_shift - 4;
 
-	if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+	if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
 		context->sq_size_stride |= !!qp->sq_no_prefetch << 7;
+		context->xrcd = cpu_to_be32((u32) qp->xrcdn);
+	}
 
 	if (qp->ibqp.uobject)
 		context->usr_page = cpu_to_be32(to_mucontext(ibqp->uobject->context)->uar.index);
@@ -1079,8 +1133,12 @@
 		optpar |= MLX4_QP_OPTPAR_ALT_ADDR_PATH;
 	}
 
-	context->pd	    = cpu_to_be32(to_mpd(ibqp->pd)->pdn);
-	context->params1    = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
+	pd = get_pd(qp);
+	get_cqs(qp, &send_cq, &recv_cq);
+	context->pd       = cpu_to_be32(pd->pdn);
+	context->cqn_send = cpu_to_be32(send_cq->mcq.cqn);
+	context->cqn_recv = cpu_to_be32(recv_cq->mcq.cqn);
+	context->params1  = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
 
 	/* Set "fast registration enabled" for all kernel QPs */
 	if (!qp->ibqp.uobject)
@@ -1106,8 +1164,6 @@
 	if (attr_mask & IB_QP_SQ_PSN)
 		context->next_send_psn = cpu_to_be32(attr->sq_psn);
 
-	context->cqn_send = cpu_to_be32(to_mcq(ibqp->send_cq)->mcq.cqn);
-
 	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
 		if (attr->max_dest_rd_atomic)
 			context->params2 |=
@@ -1130,8 +1186,6 @@
 	if (attr_mask & IB_QP_RQ_PSN)
 		context->rnr_nextrecvpsn |= cpu_to_be32(attr->rq_psn);
 
-	context->cqn_recv = cpu_to_be32(to_mcq(ibqp->recv_cq)->mcq.cqn);
-
 	if (attr_mask & IB_QP_QKEY) {
 		context->qkey = cpu_to_be32(attr->qkey);
 		optpar |= MLX4_QP_OPTPAR_Q_KEY;
@@ -1140,7 +1194,7 @@
 	if (ibqp->srq)
 		context->srqn = cpu_to_be32(1 << 24 | to_msrq(ibqp->srq)->msrq.srqn);
 
-	if (!ibqp->srq && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+	if (qp->rq.wqe_cnt && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
 		context->db_rec_addr = cpu_to_be64(qp->db.dma);
 
 	if (cur_state == IB_QPS_INIT &&
@@ -1225,17 +1279,17 @@
 	 * entries and reinitialize the QP.
 	 */
 	if (new_state == IB_QPS_RESET && !ibqp->uobject) {
-		mlx4_ib_cq_clean(to_mcq(ibqp->recv_cq), qp->mqp.qpn,
+		mlx4_ib_cq_clean(recv_cq, qp->mqp.qpn,
 				 ibqp->srq ? to_msrq(ibqp->srq): NULL);
-		if (ibqp->send_cq != ibqp->recv_cq)
-			mlx4_ib_cq_clean(to_mcq(ibqp->send_cq), qp->mqp.qpn, NULL);
+		if (send_cq != recv_cq)
+			mlx4_ib_cq_clean(send_cq, qp->mqp.qpn, NULL);
 
 		qp->rq.head = 0;
 		qp->rq.tail = 0;
 		qp->sq.head = 0;
 		qp->sq.tail = 0;
 		qp->sq_next_wqe = 0;
-		if (!ibqp->srq)
+		if (qp->rq.wqe_cnt)
 			*qp->db.db  = 0;
 	}
 
@@ -1547,14 +1601,13 @@
 }
 
 static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg,
-			     struct ib_send_wr *wr, __be16 *vlan)
+			     struct ib_send_wr *wr)
 {
 	memcpy(dseg->av, &to_mah(wr->wr.ud.ah)->av, sizeof (struct mlx4_av));
 	dseg->dqpn = cpu_to_be32(wr->wr.ud.remote_qpn);
 	dseg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
 	dseg->vlan = to_mah(wr->wr.ud.ah)->av.eth.vlan;
 	memcpy(dseg->mac, to_mah(wr->wr.ud.ah)->av.eth.mac, 6);
-	*vlan = dseg->vlan;
 }
 
 static void set_mlx_icrc_seg(void *dseg)
@@ -1657,7 +1710,6 @@
 	__be32 uninitialized_var(lso_hdr_sz);
 	__be32 blh;
 	int i;
-	__be16 vlan = cpu_to_be16(0xffff);
 
 	spin_lock_irqsave(&qp->sq.lock, flags);
 
@@ -1761,7 +1813,7 @@
 			break;
 
 		case IB_QPT_UD:
-			set_datagram_seg(wqe, wr, &vlan);
+			set_datagram_seg(wqe, wr);
 			wqe  += sizeof (struct mlx4_wqe_datagram_seg);
 			size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
 
@@ -1824,11 +1876,6 @@
 		ctrl->fence_size = (wr->send_flags & IB_SEND_FENCE ?
 				    MLX4_WQE_CTRL_FENCE : 0) | size;
 
-		if (be16_to_cpu(vlan) < 0x1000) {
-			ctrl->ins_vlan = 1 << 6;
-			ctrl->vlan_tag = vlan;
-		}
-
 		/*
 		 * Make sure descriptor is fully written before
 		 * setting ownership bit (because HW can start
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/mlx4/srq.c linux-libre-3.2-gnu/drivers/infiniband/hw/mlx4/srq.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/mlx4/srq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/mlx4/srq.c	2012-01-04 18:55:44.000000000 -0500
@@ -76,6 +76,8 @@
 	struct mlx4_ib_srq *srq;
 	struct mlx4_wqe_srq_next_seg *next;
 	struct mlx4_wqe_data_seg *scatter;
+	u32 cqn;
+	u16 xrcdn;
 	int desc_size;
 	int buf_size;
 	int err;
@@ -174,12 +176,18 @@
 		}
 	}
 
-	err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, &srq->mtt,
+	cqn = (init_attr->srq_type == IB_SRQT_XRC) ?
+		to_mcq(init_attr->ext.xrc.cq)->mcq.cqn : 0;
+	xrcdn = (init_attr->srq_type == IB_SRQT_XRC) ?
+		to_mxrcd(init_attr->ext.xrc.xrcd)->xrcdn :
+		(u16) dev->dev->caps.reserved_xrcds;
+	err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, cqn, xrcdn, &srq->mtt,
 			     srq->db.dma, &srq->msrq);
 	if (err)
 		goto err_wrid;
 
 	srq->msrq.event = mlx4_ib_srq_event;
+	srq->ibsrq.ext.xrc.srq_num = srq->msrq.srqn;
 
 	if (pd->uobject)
 		if (ib_copy_to_udata(udata, &srq->msrq.srqn, sizeof (__u32))) {
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/mthca/mthca_catas.c linux-libre-3.2-gnu/drivers/infiniband/hw/mthca/mthca_catas.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/mthca/mthca_catas.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/mthca/mthca_catas.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
  */
 
 #include <linux/jiffies.h>
+#include <linux/module.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/mthca/mthca_cmd.c linux-libre-3.2-gnu/drivers/infiniband/hw/mthca/mthca_cmd.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/mthca/mthca_cmd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/mthca/mthca_cmd.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 #include <linux/pci.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <rdma/ib_mad.h>
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/mthca/mthca_mr.c linux-libre-3.2-gnu/drivers/infiniband/hw/mthca/mthca_mr.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/mthca/mthca_mr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/mthca/mthca_mr.c	2012-01-04 18:55:44.000000000 -0500
@@ -146,7 +146,7 @@
 
 	buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
 			      GFP_KERNEL);
-	buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof (int *),
+	buddy->num_free = kcalloc((buddy->max_order + 1), sizeof *buddy->num_free,
 				  GFP_KERNEL);
 	if (!buddy->bits || !buddy->num_free)
 		goto err_out;
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/mthca/mthca_provider.c linux-libre-3.2-gnu/drivers/infiniband/hw/mthca/mthca_provider.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/mthca/mthca_provider.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/mthca/mthca_provider.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,7 +40,9 @@
 
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/stat.h>
 #include <linux/mm.h>
+#include <linux/export.h>
 
 #include "mthca_dev.h"
 #include "mthca_cmd.h"
@@ -438,6 +440,9 @@
 	struct mthca_srq *srq;
 	int err;
 
+	if (init_attr->srq_type != IB_SRQT_BASIC)
+		return ERR_PTR(-ENOSYS);
+
 	srq = kmalloc(sizeof *srq, GFP_KERNEL);
 	if (!srq)
 		return ERR_PTR(-ENOMEM);
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/nes/Makefile linux-libre-3.2-gnu/drivers/infiniband/hw/nes/Makefile
--- linux-libre-3.1-gnu/drivers/infiniband/hw/nes/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/nes/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INFINIBAND_NES) += iw_nes.o
 
-iw_nes-objs := nes.o nes_hw.o nes_nic.o nes_utils.o nes_verbs.o nes_cm.o
+iw_nes-objs := nes.o nes_hw.o nes_nic.o nes_utils.o nes_verbs.o nes_cm.o nes_mgt.o
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes.c linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes.c	2012-01-04 18:55:44.000000000 -0500
@@ -84,7 +84,7 @@
 MODULE_PARM_DESC(send_first, "Send RDMA Message First on Active Connection");
 
 
-unsigned int nes_drv_opt = 0;
+unsigned int nes_drv_opt = NES_DRV_OPT_DISABLE_INT_MOD | NES_DRV_OPT_ENABLE_PAU;
 module_param(nes_drv_opt, int, 0644);
 MODULE_PARM_DESC(nes_drv_opt, "Driver option parameters");
 
@@ -130,9 +130,6 @@
 	.notifier_call = nes_net_event
 };
 
-
-
-
 /**
  * nes_inetaddr_event
  */
@@ -321,6 +318,9 @@
 	}
 
 	if (atomic_dec_and_test(&nesqp->refcount)) {
+		if (nesqp->pau_mode)
+			nes_destroy_pau_qp(nesdev, nesqp);
+
 		/* Destroy the QP */
 		cqp_request = nes_get_cqp_request(nesdev);
 		if (cqp_request == NULL) {
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_cm.c linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_cm.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_cm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_cm.c	2012-01-04 18:55:44.000000000 -0500
@@ -77,26 +77,19 @@
 atomic_t cm_accel_dropped_pkts;
 atomic_t cm_resets_recvd;
 
-static inline int mini_cm_accelerated(struct nes_cm_core *,
-	struct nes_cm_node *);
-static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *,
-	struct nes_vnic *, struct nes_cm_info *);
+static inline int mini_cm_accelerated(struct nes_cm_core *, struct nes_cm_node *);
+static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *, struct nes_vnic *, struct nes_cm_info *);
 static int mini_cm_del_listen(struct nes_cm_core *, struct nes_cm_listener *);
-static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *,
-	struct nes_vnic *, u16, void *, struct nes_cm_info *);
+static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *, struct nes_vnic *, u16, void *, struct nes_cm_info *);
 static int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *);
-static int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *,
-	struct nes_cm_node *);
-static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *,
-	struct nes_cm_node *);
-static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *,
-	struct sk_buff *);
+static int mini_cm_accept(struct nes_cm_core *, struct nes_cm_node *);
+static int mini_cm_reject(struct nes_cm_core *, struct nes_cm_node *);
+static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, struct sk_buff *);
 static int mini_cm_dealloc_core(struct nes_cm_core *);
 static int mini_cm_get(struct nes_cm_core *);
 static int mini_cm_set(struct nes_cm_core *, u32, u32);
 
-static void form_cm_frame(struct sk_buff *, struct nes_cm_node *,
-	void *, u32, void *, u32, u8);
+static void form_cm_frame(struct sk_buff *, struct nes_cm_node *, void *, u32, void *, u32, u8);
 static int add_ref_cm_node(struct nes_cm_node *);
 static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *);
 
@@ -111,16 +104,14 @@
 static int send_reset(struct nes_cm_node *, struct sk_buff *);
 static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb);
 static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb);
-static void process_packet(struct nes_cm_node *, struct sk_buff *,
-	struct nes_cm_core *);
+static void process_packet(struct nes_cm_node *, struct sk_buff *, struct nes_cm_core *);
 
 static void active_open_err(struct nes_cm_node *, struct sk_buff *, int);
 static void passive_open_err(struct nes_cm_node *, struct sk_buff *, int);
 static void cleanup_retrans_entry(struct nes_cm_node *);
 static void handle_rcv_mpa(struct nes_cm_node *, struct sk_buff *);
 static void free_retrans_entry(struct nes_cm_node *cm_node);
-static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
-	struct sk_buff *skb, int optionsize, int passive);
+static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, struct sk_buff *skb, int optionsize, int passive);
 
 /* CM event handler functions */
 static void cm_event_connected(struct nes_cm_event *);
@@ -130,6 +121,12 @@
 static void cm_event_mpa_reject(struct nes_cm_event *);
 static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node);
 
+/* MPA build functions */
+static int cm_build_mpa_frame(struct nes_cm_node *, u8 **, u16 *, u8 *, u8);
+static void build_mpa_v2(struct nes_cm_node *, void *, u8);
+static void build_mpa_v1(struct nes_cm_node *, void *, u8);
+static void build_rdma0_msg(struct nes_cm_node *, struct nes_qp **);
+
 static void print_core(struct nes_cm_core *core);
 
 /* External CM API Interface */
@@ -159,12 +156,21 @@
 atomic_t cm_connect_reqs;
 atomic_t cm_rejects;
 
+int nes_add_ref_cm_node(struct nes_cm_node *cm_node)
+{
+	return add_ref_cm_node(cm_node);
+}
+
+int nes_rem_ref_cm_node(struct nes_cm_node *cm_node)
+{
+	return rem_ref_cm_node(cm_node->cm_core, cm_node);
+}
 
 /**
  * create_event
  */
-static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
-		enum nes_cm_event_type type)
+static struct nes_cm_event *create_event(struct nes_cm_node *	cm_node,
+					 enum nes_cm_event_type type)
 {
 	struct nes_cm_event *event;
 
@@ -186,10 +192,10 @@
 	event->cm_info.cm_id = cm_node->cm_id;
 
 	nes_debug(NES_DBG_CM, "cm_node=%p Created event=%p, type=%u, "
-		"dst_addr=%08x[%x], src_addr=%08x[%x]\n",
-		cm_node, event, type, event->cm_info.loc_addr,
-		event->cm_info.loc_port, event->cm_info.rem_addr,
-		event->cm_info.rem_port);
+		  "dst_addr=%08x[%x], src_addr=%08x[%x]\n",
+		  cm_node, event, type, event->cm_info.loc_addr,
+		  event->cm_info.loc_port, event->cm_info.rem_addr,
+		  event->cm_info.rem_port);
 
 	nes_cm_post_event(event);
 	return event;
@@ -201,14 +207,19 @@
  */
 static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb)
 {
+	u8 start_addr = 0;
+	u8 *start_ptr = &start_addr;
+	u8 **start_buff = &start_ptr;
+	u16 buff_len = 0;
+
 	if (!skb) {
 		nes_debug(NES_DBG_CM, "skb set to NULL\n");
 		return -1;
 	}
 
 	/* send an MPA Request frame */
-	form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame,
-			cm_node->mpa_frame_size, SET_ACK);
+	cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REQUEST);
+	form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK);
 
 	return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
 }
@@ -217,7 +228,11 @@
 
 static int send_mpa_reject(struct nes_cm_node *cm_node)
 {
-	struct sk_buff  *skb = NULL;
+	struct sk_buff *skb = NULL;
+	u8 start_addr = 0;
+	u8 *start_ptr = &start_addr;
+	u8 **start_buff = &start_ptr;
+	u16 buff_len = 0;
 
 	skb = dev_alloc_skb(MAX_CM_BUFFER);
 	if (!skb) {
@@ -226,8 +241,8 @@
 	}
 
 	/* send an MPA reject frame */
-	form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame,
-			cm_node->mpa_frame_size, SET_ACK | SET_FIN);
+	cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REPLY);
+	form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK | SET_FIN);
 
 	cm_node->state = NES_CM_STATE_FIN_WAIT1;
 	return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
@@ -239,24 +254,31 @@
  * IETF MPA frame
  */
 static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,
-		u32 len)
+		     u32 len)
 {
-	struct ietf_mpa_frame *mpa_frame;
+	struct ietf_mpa_v1 *mpa_frame;
+	struct ietf_mpa_v2 *mpa_v2_frame;
+	struct ietf_rtr_msg *rtr_msg;
+	int mpa_hdr_len;
+	int priv_data_len;
 
 	*type = NES_MPA_REQUEST_ACCEPT;
 
 	/* assume req frame is in tcp data payload */
-	if (len < sizeof(struct ietf_mpa_frame)) {
+	if (len < sizeof(struct ietf_mpa_v1)) {
 		nes_debug(NES_DBG_CM, "The received ietf buffer was too small (%x)\n", len);
 		return -EINVAL;
 	}
 
-	mpa_frame = (struct ietf_mpa_frame *)buffer;
-	cm_node->mpa_frame_size = ntohs(mpa_frame->priv_data_len);
+	/* points to the beginning of the frame, which could be MPA V1 or V2 */
+	mpa_frame = (struct ietf_mpa_v1 *)buffer;
+	mpa_hdr_len = sizeof(struct ietf_mpa_v1);
+	priv_data_len = ntohs(mpa_frame->priv_data_len);
+
 	/* make sure mpa private data len is less than 512 bytes */
-	if (cm_node->mpa_frame_size > IETF_MAX_PRIV_DATA_LEN) {
+	if (priv_data_len > IETF_MAX_PRIV_DATA_LEN) {
 		nes_debug(NES_DBG_CM, "The received Length of Private"
-			" Data field exceeds 512 octets\n");
+			  " Data field exceeds 512 octets\n");
 		return -EINVAL;
 	}
 	/*
@@ -264,11 +286,22 @@
 	 * received MPA version and MPA key information
 	 *
 	 */
-	if (mpa_frame->rev != mpa_version) {
+	if (mpa_frame->rev != IETF_MPA_V1 && mpa_frame->rev != IETF_MPA_V2) {
 		nes_debug(NES_DBG_CM, "The received mpa version"
-				" can not be interoperated\n");
+			  " is not supported\n");
+		return -EINVAL;
+	}
+	/*
+	* backwards compatibility only
+	*/
+	if (mpa_frame->rev > cm_node->mpa_frame_rev) {
+		nes_debug(NES_DBG_CM, "The received mpa version"
+			" can not be interoperated\n");
 		return -EINVAL;
+	} else {
+		cm_node->mpa_frame_rev = mpa_frame->rev;
 	}
+
 	if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) {
 		if (memcmp(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE)) {
 			nes_debug(NES_DBG_CM, "Unexpected MPA Key received \n");
@@ -281,25 +314,75 @@
 		}
 	}
 
-	if (cm_node->mpa_frame_size + sizeof(struct ietf_mpa_frame) != len) {
+
+	if (priv_data_len + mpa_hdr_len != len) {
 		nes_debug(NES_DBG_CM, "The received ietf buffer was not right"
-				" complete (%x + %x != %x)\n",
-				cm_node->mpa_frame_size,
-				(u32)sizeof(struct ietf_mpa_frame), len);
+			" complete (%x + %x != %x)\n",
+			priv_data_len, mpa_hdr_len, len);
 		return -EINVAL;
 	}
 	/* make sure it does not exceed the max size */
 	if (len > MAX_CM_BUFFER) {
 		nes_debug(NES_DBG_CM, "The received ietf buffer was too large"
-				" (%x + %x != %x)\n",
-				cm_node->mpa_frame_size,
-				(u32)sizeof(struct ietf_mpa_frame), len);
+			" (%x + %x != %x)\n",
+			priv_data_len, mpa_hdr_len, len);
 		return -EINVAL;
 	}
 
+	cm_node->mpa_frame_size = priv_data_len;
+
+	switch (mpa_frame->rev) {
+	case IETF_MPA_V2: {
+		u16 ird_size;
+		u16 ord_size;
+		mpa_v2_frame = (struct ietf_mpa_v2 *)buffer;
+		mpa_hdr_len += IETF_RTR_MSG_SIZE;
+		cm_node->mpa_frame_size -= IETF_RTR_MSG_SIZE;
+		rtr_msg = &mpa_v2_frame->rtr_msg;
+
+		/* parse rtr message */
+		rtr_msg->ctrl_ird = ntohs(rtr_msg->ctrl_ird);
+		rtr_msg->ctrl_ord = ntohs(rtr_msg->ctrl_ord);
+		ird_size = rtr_msg->ctrl_ird & IETF_NO_IRD_ORD;
+		ord_size = rtr_msg->ctrl_ord & IETF_NO_IRD_ORD;
+
+		if (!(rtr_msg->ctrl_ird & IETF_PEER_TO_PEER)) {
+			/* send reset */
+			return -EINVAL;
+		}
+
+		if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) {
+			/* responder */
+			if (cm_node->ord_size > ird_size)
+				cm_node->ord_size = ird_size;
+		} else {
+			/* initiator */
+			if (cm_node->ord_size > ird_size)
+				cm_node->ord_size = ird_size;
+
+			if (cm_node->ird_size < ord_size) {
+				/* no resources available */
+				/* send terminate message */
+				return -EINVAL;
+			}
+		}
+
+		if (rtr_msg->ctrl_ord & IETF_RDMA0_READ) {
+			cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO;
+		} else if (rtr_msg->ctrl_ord & IETF_RDMA0_WRITE) {
+			cm_node->send_rdma0_op = SEND_RDMA_WRITE_ZERO;
+		} else {        /* Not supported RDMA0 operation */
+			return -EINVAL;
+		}
+		break;
+	}
+	case IETF_MPA_V1:
+	default:
+		break;
+	}
+
 	/* copy entire MPA frame to our cm_node's frame */
-	memcpy(cm_node->mpa_frame_buf, buffer + sizeof(struct ietf_mpa_frame),
-			cm_node->mpa_frame_size);
+	memcpy(cm_node->mpa_frame_buf, buffer + mpa_hdr_len, cm_node->mpa_frame_size);
 
 	if (mpa_frame->flags & IETF_MPA_FLAGS_REJECT)
 		*type = NES_MPA_REQUEST_REJECT;
@@ -312,8 +395,8 @@
  * node info to build.
  */
 static void form_cm_frame(struct sk_buff *skb,
-	struct nes_cm_node *cm_node, void *options, u32 optionsize,
-	void *data, u32 datasize, u8 flags)
+			  struct nes_cm_node *cm_node, void *options, u32 optionsize,
+			  void *data, u32 datasize, u8 flags)
 {
 	struct tcphdr *tcph;
 	struct iphdr *iph;
@@ -322,14 +405,14 @@
 	u16 packetsize = sizeof(*iph);
 
 	packetsize += sizeof(*tcph);
-	packetsize +=  optionsize + datasize;
+	packetsize += optionsize + datasize;
 
+	skb_trim(skb, 0);
 	memset(skb->data, 0x00, ETH_HLEN + sizeof(*iph) + sizeof(*tcph));
 
-	skb->len = 0;
 	buf = skb_put(skb, packetsize + ETH_HLEN);
 
-	ethh = (struct ethhdr *) buf;
+	ethh = (struct ethhdr *)buf;
 	buf += ETH_HLEN;
 
 	iph = (struct iphdr *)buf;
@@ -337,7 +420,7 @@
 	tcph = (struct tcphdr *)buf;
 	skb_reset_mac_header(skb);
 	skb_set_network_header(skb, ETH_HLEN);
-	skb_set_transport_header(skb, ETH_HLEN+sizeof(*iph));
+	skb_set_transport_header(skb, ETH_HLEN + sizeof(*iph));
 	buf += sizeof(*tcph);
 
 	skb->ip_summed = CHECKSUM_PARTIAL;
@@ -350,14 +433,14 @@
 	ethh->h_proto = htons(0x0800);
 
 	iph->version = IPVERSION;
-	iph->ihl = 5;		/* 5 * 4Byte words, IP headr len */
+	iph->ihl = 5;           /* 5 * 4Byte words, IP headr len */
 	iph->tos = 0;
 	iph->tot_len = htons(packetsize);
 	iph->id = htons(++cm_node->tcp_cntxt.loc_id);
 
 	iph->frag_off = htons(0x4000);
 	iph->ttl = 0x40;
-	iph->protocol = 0x06;	/* IPPROTO_TCP */
+	iph->protocol = 0x06;   /* IPPROTO_TCP */
 
 	iph->saddr = htonl(cm_node->loc_addr);
 	iph->daddr = htonl(cm_node->rem_addr);
@@ -370,14 +453,16 @@
 		cm_node->tcp_cntxt.loc_ack_num = cm_node->tcp_cntxt.rcv_nxt;
 		tcph->ack_seq = htonl(cm_node->tcp_cntxt.loc_ack_num);
 		tcph->ack = 1;
-	} else
+	} else {
 		tcph->ack_seq = 0;
+	}
 
 	if (flags & SET_SYN) {
 		cm_node->tcp_cntxt.loc_seq_num++;
 		tcph->syn = 1;
-	} else
+	} else {
 		cm_node->tcp_cntxt.loc_seq_num += datasize;
+	}
 
 	if (flags & SET_FIN) {
 		cm_node->tcp_cntxt.loc_seq_num++;
@@ -398,10 +483,8 @@
 
 	skb_shinfo(skb)->nr_frags = 0;
 	cm_packets_created++;
-
 }
 
-
 /**
  * print_core - dump a cm core
  */
@@ -413,7 +496,7 @@
 		return;
 	nes_debug(NES_DBG_CM, "---------------------------------------------\n");
 
-	nes_debug(NES_DBG_CM, "State         : %u \n",  core->state);
+	nes_debug(NES_DBG_CM, "State         : %u \n", core->state);
 
 	nes_debug(NES_DBG_CM, "Listen Nodes  : %u \n", atomic_read(&core->listen_node_cnt));
 	nes_debug(NES_DBG_CM, "Active Nodes  : %u \n", atomic_read(&core->node_cnt));
@@ -423,6 +506,147 @@
 	nes_debug(NES_DBG_CM, "-------------- end core ---------------\n");
 }
 
+/**
+ * cm_build_mpa_frame - build a MPA V1 frame or MPA V2 frame
+ */
+static int cm_build_mpa_frame(struct nes_cm_node *cm_node, u8 **start_buff,
+			      u16 *buff_len, u8 *pci_mem, u8 mpa_key)
+{
+	int ret = 0;
+
+	*start_buff = (pci_mem) ? pci_mem : &cm_node->mpa_frame_buf[0];
+
+	switch (cm_node->mpa_frame_rev) {
+	case IETF_MPA_V1:
+		*start_buff = (u8 *)*start_buff + sizeof(struct ietf_rtr_msg);
+		*buff_len = sizeof(struct ietf_mpa_v1) + cm_node->mpa_frame_size;
+		build_mpa_v1(cm_node, *start_buff, mpa_key);
+		break;
+	case IETF_MPA_V2:
+		*buff_len = sizeof(struct ietf_mpa_v2) + cm_node->mpa_frame_size;
+		build_mpa_v2(cm_node, *start_buff, mpa_key);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+/**
+ * build_mpa_v2 - build a MPA V2 frame
+ */
+static void build_mpa_v2(struct nes_cm_node *cm_node,
+			 void *start_addr, u8 mpa_key)
+{
+	struct ietf_mpa_v2 *mpa_frame = (struct ietf_mpa_v2 *)start_addr;
+	struct ietf_rtr_msg *rtr_msg = &mpa_frame->rtr_msg;
+
+	/* initialize the upper 5 bytes of the frame */
+	build_mpa_v1(cm_node, start_addr, mpa_key);
+	mpa_frame->flags |= IETF_MPA_V2_FLAG; /* set a bit to indicate MPA V2 */
+	mpa_frame->priv_data_len += htons(IETF_RTR_MSG_SIZE);
+
+	/* initialize RTR msg */
+	rtr_msg->ctrl_ird = (cm_node->ird_size > IETF_NO_IRD_ORD) ?
+			    IETF_NO_IRD_ORD : cm_node->ird_size;
+	rtr_msg->ctrl_ord = (cm_node->ord_size > IETF_NO_IRD_ORD) ?
+			    IETF_NO_IRD_ORD : cm_node->ord_size;
+
+	rtr_msg->ctrl_ird |= IETF_PEER_TO_PEER;
+	rtr_msg->ctrl_ird |= IETF_FLPDU_ZERO_LEN;
+
+	switch (mpa_key) {
+	case MPA_KEY_REQUEST:
+		rtr_msg->ctrl_ord |= IETF_RDMA0_WRITE;
+		rtr_msg->ctrl_ord |= IETF_RDMA0_READ;
+		break;
+	case MPA_KEY_REPLY:
+		switch (cm_node->send_rdma0_op) {
+		case SEND_RDMA_WRITE_ZERO:
+			rtr_msg->ctrl_ord |= IETF_RDMA0_WRITE;
+			break;
+		case SEND_RDMA_READ_ZERO:
+			rtr_msg->ctrl_ord |= IETF_RDMA0_READ;
+			break;
+		}
+	}
+	rtr_msg->ctrl_ird = htons(rtr_msg->ctrl_ird);
+	rtr_msg->ctrl_ord = htons(rtr_msg->ctrl_ord);
+}
+
+/**
+ * build_mpa_v1 - build a MPA V1 frame
+ */
+static void build_mpa_v1(struct nes_cm_node *cm_node, void *start_addr, u8 mpa_key)
+{
+	struct ietf_mpa_v1 *mpa_frame = (struct ietf_mpa_v1 *)start_addr;
+
+	switch (mpa_key) {
+	case MPA_KEY_REQUEST:
+		memcpy(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE);
+		break;
+	case MPA_KEY_REPLY:
+		memcpy(mpa_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
+		break;
+	}
+	mpa_frame->flags = IETF_MPA_FLAGS_CRC;
+	mpa_frame->rev = cm_node->mpa_frame_rev;
+	mpa_frame->priv_data_len = htons(cm_node->mpa_frame_size);
+}
+
+static void build_rdma0_msg(struct nes_cm_node *cm_node, struct nes_qp **nesqp_addr)
+{
+	u64 u64temp;
+	struct nes_qp *nesqp = *nesqp_addr;
+	struct nes_hw_qp_wqe *wqe = &nesqp->hwqp.sq_vbase[0];
+
+	u64temp = (unsigned long)nesqp;
+	u64temp |= NES_SW_CONTEXT_ALIGN >> 1;
+	set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, u64temp);
+
+	wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0;
+	wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0;
+
+	switch (cm_node->send_rdma0_op) {
+	case SEND_RDMA_WRITE_ZERO:
+		nes_debug(NES_DBG_CM, "Sending first write.\n");
+		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
+			cpu_to_le32(NES_IWARP_SQ_OP_RDMAW);
+		wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
+		break;
+
+	case SEND_RDMA_READ_ZERO:
+	default:
+		if (cm_node->send_rdma0_op != SEND_RDMA_READ_ZERO) {
+			printk(KERN_ERR "%s[%u]: Unsupported RDMA0 len operation=%u\n",
+				 __func__, __LINE__, cm_node->send_rdma0_op);
+			WARN_ON(1);
+		}
+		nes_debug(NES_DBG_CM, "Sending first rdma operation.\n");
+		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
+			cpu_to_le32(NES_IWARP_SQ_OP_RDMAR);
+		wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX] = 1;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_HIGH_IDX] = 0;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX] = 0;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_STAG_IDX] = 1;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 1;
+		break;
+	}
+
+	if (nesqp->sq_kmapped) {
+		nesqp->sq_kmapped = 0;
+		kunmap(nesqp->page);
+	}
+
+	/*use the reserved spot on the WQ for the extra first WQE*/
+	nesqp->nesqp_context->ird_ord_sizes &= cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
+							     NES_QPCONTEXT_ORDIRD_WRPDU |
+							     NES_QPCONTEXT_ORDIRD_ALSMM));
+	nesqp->skip_lsmm = 1;
+	nesqp->hwqp.sq_tail = 0;
+}
 
 /**
  * schedule_nes_timer
@@ -430,10 +654,10 @@
  *			rem_ref_cm_node(cm_core, cm_node);add_ref_cm_node(cm_node);
  */
 int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
-		enum nes_timer_type type, int send_retrans,
-		int close_when_complete)
+		       enum nes_timer_type type, int send_retrans,
+		       int close_when_complete)
 {
-	unsigned long  flags;
+	unsigned long flags;
 	struct nes_cm_core *cm_core = cm_node->cm_core;
 	struct nes_timer_entry *new_send;
 	int ret = 0;
@@ -454,7 +678,7 @@
 	new_send->close_when_complete = close_when_complete;
 
 	if (type == NES_TIMER_TYPE_CLOSE) {
-		new_send->timetosend += (HZ/10);
+		new_send->timetosend += (HZ / 10);
 		if (cm_node->recv_entry) {
 			kfree(new_send);
 			WARN_ON(1);
@@ -475,7 +699,7 @@
 		ret = nes_nic_cm_xmit(new_send->skb, cm_node->netdev);
 		if (ret != NETDEV_TX_OK) {
 			nes_debug(NES_DBG_CM, "Error sending packet %p "
-				"(jiffies = %lu)\n", new_send, jiffies);
+				  "(jiffies = %lu)\n", new_send, jiffies);
 			new_send->timetosend = jiffies;
 			ret = NETDEV_TX_OK;
 		} else {
@@ -504,6 +728,7 @@
 	struct iw_cm_id *cm_id = cm_node->cm_id;
 	enum nes_cm_node_state state = cm_node->state;
 	cm_node->state = NES_CM_STATE_CLOSED;
+
 	switch (state) {
 	case NES_CM_STATE_SYN_RCVD:
 	case NES_CM_STATE_CLOSING:
@@ -536,10 +761,10 @@
 		spin_lock_irqsave(&nesqp->lock, qplockflags);
 		if (nesqp->cm_id) {
 			nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, "
-				"refcount = %d: HIT A "
-				"NES_TIMER_TYPE_CLOSE with something "
-				"to do!!!\n", nesqp->hwqp.qp_id, cm_id,
-				atomic_read(&nesqp->refcount));
+				  "refcount = %d: HIT A "
+				  "NES_TIMER_TYPE_CLOSE with something "
+				  "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
+				  atomic_read(&nesqp->refcount));
 			nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
 			nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
 			nesqp->ibqp_state = IB_QPS_ERR;
@@ -548,10 +773,10 @@
 		} else {
 			spin_unlock_irqrestore(&nesqp->lock, qplockflags);
 			nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, "
-				"refcount = %d: HIT A "
-				"NES_TIMER_TYPE_CLOSE with nothing "
-				"to do!!!\n", nesqp->hwqp.qp_id, cm_id,
-				atomic_read(&nesqp->refcount));
+				  "refcount = %d: HIT A "
+				  "NES_TIMER_TYPE_CLOSE with nothing "
+				  "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
+				  atomic_read(&nesqp->refcount));
 		}
 	} else if (rem_node) {
 		/* TIME_WAIT state */
@@ -580,11 +805,12 @@
 	int ret = NETDEV_TX_OK;
 
 	struct list_head timer_list;
+
 	INIT_LIST_HEAD(&timer_list);
 	spin_lock_irqsave(&cm_core->ht_lock, flags);
 
 	list_for_each_safe(list_node, list_core_temp,
-				&cm_core->connected_nodes) {
+			   &cm_core->connected_nodes) {
 		cm_node = container_of(list_node, struct nes_cm_node, list);
 		if ((cm_node->recv_entry) || (cm_node->send_entry)) {
 			add_ref_cm_node(cm_node);
@@ -595,18 +821,19 @@
 
 	list_for_each_safe(list_node, list_core_temp, &timer_list) {
 		cm_node = container_of(list_node, struct nes_cm_node,
-					timer_entry);
+				       timer_entry);
 		recv_entry = cm_node->recv_entry;
 
 		if (recv_entry) {
 			if (time_after(recv_entry->timetosend, jiffies)) {
 				if (nexttimeout > recv_entry->timetosend ||
-						!settimer) {
+				    !settimer) {
 					nexttimeout = recv_entry->timetosend;
 					settimer = 1;
 				}
-			} else
+			} else {
 				handle_recv_entry(cm_node, 1);
+			}
 		}
 
 		spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
@@ -617,8 +844,8 @@
 			if (time_after(send_entry->timetosend, jiffies)) {
 				if (cm_node->state != NES_CM_STATE_TSA) {
 					if ((nexttimeout >
-						send_entry->timetosend) ||
-						!settimer) {
+					     send_entry->timetosend) ||
+					    !settimer) {
 						nexttimeout =
 							send_entry->timetosend;
 						settimer = 1;
@@ -630,13 +857,13 @@
 			}
 
 			if ((cm_node->state == NES_CM_STATE_TSA) ||
-				(cm_node->state == NES_CM_STATE_CLOSED)) {
+			    (cm_node->state == NES_CM_STATE_CLOSED)) {
 				free_retrans_entry(cm_node);
 				break;
 			}
 
 			if (!send_entry->retranscount ||
-				!send_entry->retrycount) {
+			    !send_entry->retrycount) {
 				cm_packets_dropped++;
 				free_retrans_entry(cm_node);
 
@@ -645,28 +872,28 @@
 				nes_retrans_expired(cm_node);
 				cm_node->state = NES_CM_STATE_CLOSED;
 				spin_lock_irqsave(&cm_node->retrans_list_lock,
-					flags);
+						  flags);
 				break;
 			}
 			atomic_inc(&send_entry->skb->users);
 			cm_packets_retrans++;
 			nes_debug(NES_DBG_CM, "Retransmitting send_entry %p "
-				"for node %p, jiffies = %lu, time to send = "
-				"%lu, retranscount = %u, send_entry->seq_num = "
-				"0x%08X, cm_node->tcp_cntxt.rem_ack_num = "
-				"0x%08X\n", send_entry, cm_node, jiffies,
-				send_entry->timetosend,
-				send_entry->retranscount,
-				send_entry->seq_num,
-				cm_node->tcp_cntxt.rem_ack_num);
+				  "for node %p, jiffies = %lu, time to send = "
+				  "%lu, retranscount = %u, send_entry->seq_num = "
+				  "0x%08X, cm_node->tcp_cntxt.rem_ack_num = "
+				  "0x%08X\n", send_entry, cm_node, jiffies,
+				  send_entry->timetosend,
+				  send_entry->retranscount,
+				  send_entry->seq_num,
+				  cm_node->tcp_cntxt.rem_ack_num);
 
 			spin_unlock_irqrestore(&cm_node->retrans_list_lock,
-				flags);
+					       flags);
 			ret = nes_nic_cm_xmit(send_entry->skb, cm_node->netdev);
 			spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
 			if (ret != NETDEV_TX_OK) {
 				nes_debug(NES_DBG_CM, "rexmit failed for "
-					"node=%p\n", cm_node);
+					  "node=%p\n", cm_node);
 				cm_packets_bounced++;
 				send_entry->retrycount--;
 				nexttimeout = jiffies + NES_SHORT_TIME;
@@ -676,18 +903,18 @@
 				cm_packets_sent++;
 			}
 			nes_debug(NES_DBG_CM, "Packet Sent: retrans count = "
-				"%u, retry count = %u.\n",
-				send_entry->retranscount,
-				send_entry->retrycount);
+				  "%u, retry count = %u.\n",
+				  send_entry->retranscount,
+				  send_entry->retrycount);
 			if (send_entry->send_retrans) {
 				send_entry->retranscount--;
 				timetosend = (NES_RETRY_TIMEOUT <<
-					(NES_DEFAULT_RETRANS - send_entry->retranscount));
+					      (NES_DEFAULT_RETRANS - send_entry->retranscount));
 
 				send_entry->timetosend = jiffies +
-					min(timetosend, NES_MAX_TIMEOUT);
+							 min(timetosend, NES_MAX_TIMEOUT);
 				if (nexttimeout > send_entry->timetosend ||
-					!settimer) {
+				    !settimer) {
 					nexttimeout = send_entry->timetosend;
 					settimer = 1;
 				}
@@ -696,11 +923,11 @@
 				close_when_complete =
 					send_entry->close_when_complete;
 				nes_debug(NES_DBG_CM, "cm_node=%p state=%d\n",
-					cm_node, cm_node->state);
+					  cm_node, cm_node->state);
 				free_retrans_entry(cm_node);
 				if (close_when_complete)
 					rem_ref_cm_node(cm_node->cm_core,
-						cm_node);
+							cm_node);
 			}
 		} while (0);
 
@@ -710,7 +937,7 @@
 
 	if (settimer) {
 		if (!timer_pending(&cm_core->tcp_timer)) {
-			cm_core->tcp_timer.expires  = nexttimeout;
+			cm_core->tcp_timer.expires = nexttimeout;
 			add_timer(&cm_core->tcp_timer);
 		}
 	}
@@ -721,13 +948,13 @@
  * send_syn
  */
 static int send_syn(struct nes_cm_node *cm_node, u32 sendack,
-	struct sk_buff *skb)
+		    struct sk_buff *skb)
 {
 	int ret;
 	int flags = SET_SYN;
 	char optionsbuffer[sizeof(struct option_mss) +
-		sizeof(struct option_windowscale) + sizeof(struct option_base) +
-		TCP_OPTIONS_PADDING];
+			   sizeof(struct option_windowscale) + sizeof(struct option_base) +
+			   TCP_OPTIONS_PADDING];
 
 	int optionssize = 0;
 	/* Sending MSS option */
@@ -854,7 +1081,7 @@
  * find_node - find a cm node that matches the reference cm node
  */
 static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
-		u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr)
+				     u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr)
 {
 	unsigned long flags;
 	struct list_head *hte;
@@ -868,12 +1095,12 @@
 	list_for_each_entry(cm_node, hte, list) {
 		/* compare quad, return node handle if a match */
 		nes_debug(NES_DBG_CM, "finding node %x:%x =? %x:%x ^ %x:%x =? %x:%x\n",
-				cm_node->loc_addr, cm_node->loc_port,
-				loc_addr, loc_port,
-				cm_node->rem_addr, cm_node->rem_port,
-				rem_addr, rem_port);
+			  cm_node->loc_addr, cm_node->loc_port,
+			  loc_addr, loc_port,
+			  cm_node->rem_addr, cm_node->rem_port,
+			  rem_addr, rem_port);
 		if ((cm_node->loc_addr == loc_addr) && (cm_node->loc_port == loc_port) &&
-				(cm_node->rem_addr == rem_addr) && (cm_node->rem_port == rem_port)) {
+		    (cm_node->rem_addr == rem_addr) && (cm_node->rem_port == rem_port)) {
 			add_ref_cm_node(cm_node);
 			spin_unlock_irqrestore(&cm_core->ht_lock, flags);
 			return cm_node;
@@ -890,7 +1117,7 @@
  * find_listener - find a cm node listening on this addr-port pair
  */
 static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
-		nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state)
+					     nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state)
 {
 	unsigned long flags;
 	struct nes_cm_listener *listen_node;
@@ -900,9 +1127,9 @@
 	list_for_each_entry(listen_node, &cm_core->listen_list.list, list) {
 		/* compare node pair, return node handle if a match */
 		if (((listen_node->loc_addr == dst_addr) ||
-				listen_node->loc_addr == 0x00000000) &&
-				(listen_node->loc_port == dst_port) &&
-				(listener_state & listen_node->listener_state)) {
+		     listen_node->loc_addr == 0x00000000) &&
+		    (listen_node->loc_port == dst_port) &&
+		    (listener_state & listen_node->listener_state)) {
 			atomic_inc(&listen_node->ref_count);
 			spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
 			return listen_node;
@@ -927,7 +1154,7 @@
 		return -EINVAL;
 
 	nes_debug(NES_DBG_CM, "Adding Node %p to Active Connection HT\n",
-		cm_node);
+		  cm_node);
 
 	spin_lock_irqsave(&cm_core->ht_lock, flags);
 
@@ -946,7 +1173,7 @@
  * mini_cm_dec_refcnt_listen
  */
 static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
-	struct nes_cm_listener *listener, int free_hanging_nodes)
+				     struct nes_cm_listener *listener, int free_hanging_nodes)
 {
 	int ret = -EINVAL;
 	int err = 0;
@@ -957,8 +1184,8 @@
 	struct list_head reset_list;
 
 	nes_debug(NES_DBG_CM, "attempting listener= %p free_nodes= %d, "
-		"refcnt=%d\n", listener, free_hanging_nodes,
-		atomic_read(&listener->ref_count));
+		  "refcnt=%d\n", listener, free_hanging_nodes,
+		  atomic_read(&listener->ref_count));
 	/* free non-accelerated child nodes for this listener */
 	INIT_LIST_HEAD(&reset_list);
 	if (free_hanging_nodes) {
@@ -966,7 +1193,7 @@
 		list_for_each_safe(list_pos, list_temp,
 				   &g_cm_core->connected_nodes) {
 			cm_node = container_of(list_pos, struct nes_cm_node,
-				list);
+					       list);
 			if ((cm_node->listener == listener) &&
 			    (!cm_node->accelerated)) {
 				add_ref_cm_node(cm_node);
@@ -978,7 +1205,7 @@
 
 	list_for_each_safe(list_pos, list_temp, &reset_list) {
 		cm_node = container_of(list_pos, struct nes_cm_node,
-				reset_entry);
+				       reset_entry);
 		{
 			struct nes_cm_node *loopback = cm_node->loopbackpartner;
 			enum nes_cm_node_state old_state;
@@ -990,7 +1217,7 @@
 					err = send_reset(cm_node, NULL);
 					if (err) {
 						cm_node->state =
-							 NES_CM_STATE_CLOSED;
+							NES_CM_STATE_CLOSED;
 						WARN_ON(1);
 					} else {
 						old_state = cm_node->state;
@@ -1035,10 +1262,9 @@
 
 		spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
 
-		if (listener->nesvnic) {
+		if (listener->nesvnic)
 			nes_manage_apbvt(listener->nesvnic, listener->loc_port,
-					PCI_FUNC(listener->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL);
-		}
+					 PCI_FUNC(listener->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL);
 
 		nes_debug(NES_DBG_CM, "destroying listener (%p)\n", listener);
 
@@ -1052,8 +1278,8 @@
 	if (listener) {
 		if (atomic_read(&listener->pend_accepts_cnt) > 0)
 			nes_debug(NES_DBG_CM, "destroying listener (%p)"
-					" with non-zero pending accepts=%u\n",
-					listener, atomic_read(&listener->pend_accepts_cnt));
+				  " with non-zero pending accepts=%u\n",
+				  listener, atomic_read(&listener->pend_accepts_cnt));
 	}
 
 	return ret;
@@ -1064,7 +1290,7 @@
  * mini_cm_del_listen
  */
 static int mini_cm_del_listen(struct nes_cm_core *cm_core,
-		struct nes_cm_listener *listener)
+			      struct nes_cm_listener *listener)
 {
 	listener->listener_state = NES_CM_LISTENER_PASSIVE_STATE;
 	listener->cm_id = NULL; /* going to be destroyed pretty soon */
@@ -1076,9 +1302,10 @@
  * mini_cm_accelerated
  */
 static inline int mini_cm_accelerated(struct nes_cm_core *cm_core,
-		struct nes_cm_node *cm_node)
+				      struct nes_cm_node *cm_node)
 {
 	u32 was_timer_set;
+
 	cm_node->accelerated = 1;
 
 	if (cm_node->accept_pend) {
@@ -1112,7 +1339,7 @@
 	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);
+		       __func__, dst_ip);
 		return rc;
 	}
 
@@ -1130,7 +1357,7 @@
 
 			if (arpindex >= 0) {
 				if (!memcmp(nesadapter->arp_table[arpindex].mac_addr,
-							neigh->ha, ETH_ALEN)){
+					    neigh->ha, ETH_ALEN)) {
 					/* Mac address same as in nes_arp_table */
 					neigh_release(neigh);
 					ip_rt_put(rt);
@@ -1138,8 +1365,8 @@
 				}
 
 				nes_manage_arp_cache(nesvnic->netdev,
-						nesadapter->arp_table[arpindex].mac_addr,
-						dst_ip, NES_ARP_DELETE);
+						     nesadapter->arp_table[arpindex].mac_addr,
+						     dst_ip, NES_ARP_DELETE);
 			}
 
 			nes_manage_arp_cache(nesvnic->netdev, neigh->ha,
@@ -1150,9 +1377,11 @@
 		neigh_release(neigh);
 	}
 
-	if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID)))
+	if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) {
+		rcu_read_lock();
 		neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
-
+		rcu_read_unlock();
+	}
 	ip_rt_put(rt);
 	return rc;
 }
@@ -1161,8 +1390,8 @@
  * make_cm_node - create a new instance of a cm node
  */
 static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
-		struct nes_vnic *nesvnic, struct nes_cm_info *cm_info,
-		struct nes_cm_listener *listener)
+					struct nes_vnic *nesvnic, struct nes_cm_info *cm_info,
+					struct nes_cm_listener *listener)
 {
 	struct nes_cm_node *cm_node;
 	struct timespec ts;
@@ -1181,7 +1410,12 @@
 	cm_node->rem_addr = cm_info->rem_addr;
 	cm_node->loc_port = cm_info->loc_port;
 	cm_node->rem_port = cm_info->rem_port;
-	cm_node->send_write0 = send_first;
+
+	cm_node->mpa_frame_rev = mpa_version;
+	cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO;
+	cm_node->ird_size = IETF_NO_IRD_ORD;
+	cm_node->ord_size = IETF_NO_IRD_ORD;
+
 	nes_debug(NES_DBG_CM, "Make node addresses : loc = %pI4:%x, rem = %pI4:%x\n",
 		  &cm_node->loc_addr, cm_node->loc_port,
 		  &cm_node->rem_addr, cm_node->rem_port);
@@ -1191,7 +1425,7 @@
 	memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN);
 
 	nes_debug(NES_DBG_CM, "listener=%p, cm_id=%p\n", cm_node->listener,
-			cm_node->cm_id);
+		  cm_node->cm_id);
 
 	spin_lock_init(&cm_node->retrans_list_lock);
 
@@ -1202,11 +1436,11 @@
 	cm_node->tcp_cntxt.loc_id = NES_CM_DEF_LOCAL_ID;
 	cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE;
 	cm_node->tcp_cntxt.rcv_wnd = NES_CM_DEFAULT_RCV_WND_SCALED >>
-			NES_CM_DEFAULT_RCV_WND_SCALE;
+				     NES_CM_DEFAULT_RCV_WND_SCALE;
 	ts = current_kernel_time();
 	cm_node->tcp_cntxt.loc_seq_num = htonl(ts.tv_nsec);
 	cm_node->tcp_cntxt.mss = nesvnic->max_frame_size - sizeof(struct iphdr) -
-			sizeof(struct tcphdr) - ETH_HLEN - VLAN_HLEN;
+				 sizeof(struct tcphdr) - ETH_HLEN - VLAN_HLEN;
 	cm_node->tcp_cntxt.rcv_nxt = 0;
 	/* get a unique session ID , add thread_id to an upcounter to handle race */
 	atomic_inc(&cm_core->node_cnt);
@@ -1222,12 +1456,11 @@
 	cm_node->loopbackpartner = NULL;
 
 	/* get the mac addr for the remote node */
-	if (ipv4_is_loopback(htonl(cm_node->rem_addr)))
+	if (ipv4_is_loopback(htonl(cm_node->rem_addr))) {
 		arpindex = nes_arp_table(nesdev, ntohl(nesvnic->local_ipaddr), NULL, NES_ARP_RESOLVE);
-	else {
+	} else {
 		oldarpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE);
 		arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr, oldarpindex);
-
 	}
 	if (arpindex < 0) {
 		kfree(cm_node);
@@ -1260,7 +1493,7 @@
  * rem_ref_cm_node - destroy an instance of a cm node
  */
 static int rem_ref_cm_node(struct nes_cm_core *cm_core,
-	struct nes_cm_node *cm_node)
+			   struct nes_cm_node *cm_node)
 {
 	unsigned long flags;
 	struct nes_qp *nesqp;
@@ -1291,9 +1524,9 @@
 	} else {
 		if (cm_node->apbvt_set && cm_node->nesvnic) {
 			nes_manage_apbvt(cm_node->nesvnic, cm_node->loc_port,
-				PCI_FUNC(
-				cm_node->nesvnic->nesdev->pcidev->devfn),
-				NES_MANAGE_APBVT_DEL);
+					 PCI_FUNC(
+						 cm_node->nesvnic->nesdev->pcidev->devfn),
+					 NES_MANAGE_APBVT_DEL);
 		}
 	}
 
@@ -1314,7 +1547,7 @@
  * process_options
  */
 static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc,
-	u32 optionsize, u32 syn_packet)
+			   u32 optionsize, u32 syn_packet)
 {
 	u32 tmp;
 	u32 offset = 0;
@@ -1332,15 +1565,15 @@
 			continue;
 		case OPTION_NUMBER_MSS:
 			nes_debug(NES_DBG_CM, "%s: MSS Length: %d Offset: %d "
-				"Size: %d\n", __func__,
-				all_options->as_mss.length, offset, optionsize);
+				  "Size: %d\n", __func__,
+				  all_options->as_mss.length, offset, optionsize);
 			got_mss_option = 1;
 			if (all_options->as_mss.length != 4) {
 				return 1;
 			} else {
 				tmp = ntohs(all_options->as_mss.mss);
 				if (tmp > 0 && tmp <
-					cm_node->tcp_cntxt.mss)
+				    cm_node->tcp_cntxt.mss)
 					cm_node->tcp_cntxt.mss = tmp;
 			}
 			break;
@@ -1348,12 +1581,9 @@
 			cm_node->tcp_cntxt.snd_wscale =
 				all_options->as_windowscale.shiftcount;
 			break;
-		case OPTION_NUMBER_WRITE0:
-			cm_node->send_write0 = 1;
-			break;
 		default:
 			nes_debug(NES_DBG_CM, "TCP Option not understood: %x\n",
-				all_options->as_base.optionnum);
+				  all_options->as_base.optionnum);
 			break;
 		}
 		offset += all_options->as_base.length;
@@ -1372,8 +1602,8 @@
 static void handle_fin_pkt(struct nes_cm_node *cm_node)
 {
 	nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. "
-		"refcnt=%d\n", cm_node, cm_node->state,
-		atomic_read(&cm_node->ref_count));
+		  "refcnt=%d\n", cm_node, cm_node->state,
+		  atomic_read(&cm_node->ref_count));
 	switch (cm_node->state) {
 	case NES_CM_STATE_SYN_RCVD:
 	case NES_CM_STATE_SYN_SENT:
@@ -1439,7 +1669,20 @@
 		nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
 			"listener=%p state=%d\n", __func__, __LINE__, cm_node,
 			cm_node->listener, cm_node->state);
-		active_open_err(cm_node, skb, reset);
+		switch (cm_node->mpa_frame_rev) {
+		case IETF_MPA_V2:
+			cm_node->mpa_frame_rev = IETF_MPA_V1;
+			/* send a syn and goto syn sent state */
+			cm_node->state = NES_CM_STATE_SYN_SENT;
+			if (send_syn(cm_node, 0, NULL)) {
+				active_open_err(cm_node, skb, reset);
+			}
+			break;
+		case IETF_MPA_V1:
+		default:
+			active_open_err(cm_node, skb, reset);
+			break;
+		}
 		break;
 	case NES_CM_STATE_MPAREQ_RCVD:
 		atomic_inc(&cm_node->passive_state);
@@ -1475,21 +1718,21 @@
 
 static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb)
 {
-
-	int	ret = 0;
+	int ret = 0;
 	int datasize = skb->len;
 	u8 *dataloc = skb->data;
 
 	enum nes_cm_event_type type = NES_CM_EVENT_UNKNOWN;
-	u32     res_type;
+	u32 res_type;
+
 	ret = parse_mpa(cm_node, dataloc, &res_type, datasize);
 	if (ret) {
 		nes_debug(NES_DBG_CM, "didn't like MPA Request\n");
 		if (cm_node->state == NES_CM_STATE_MPAREQ_SENT) {
 			nes_debug(NES_DBG_CM, "%s[%u] create abort for "
-				"cm_node=%p listener=%p state=%d\n", __func__,
-				__LINE__, cm_node, cm_node->listener,
-				cm_node->state);
+				  "cm_node=%p listener=%p state=%d\n", __func__,
+				  __LINE__, cm_node, cm_node->listener,
+				  cm_node->state);
 			active_open_err(cm_node, skb, 1);
 		} else {
 			passive_open_err(cm_node, skb, 1);
@@ -1499,16 +1742,15 @@
 
 	switch (cm_node->state) {
 	case NES_CM_STATE_ESTABLISHED:
-		if (res_type == NES_MPA_REQUEST_REJECT) {
+		if (res_type == NES_MPA_REQUEST_REJECT)
 			/*BIG problem as we are receiving the MPA.. So should
-			* not be REJECT.. This is Passive Open.. We can
-			* only receive it Reject for Active Open...*/
+			 * not be REJECT.. This is Passive Open.. We can
+			 * only receive it Reject for Active Open...*/
 			WARN_ON(1);
-		}
 		cm_node->state = NES_CM_STATE_MPAREQ_RCVD;
 		type = NES_CM_EVENT_MPA_REQ;
 		atomic_set(&cm_node->passive_state,
-				NES_PASSIVE_STATE_INDICATED);
+			   NES_PASSIVE_STATE_INDICATED);
 		break;
 	case NES_CM_STATE_MPAREQ_SENT:
 		cleanup_retrans_entry(cm_node);
@@ -1535,8 +1777,8 @@
 	case NES_CM_STATE_SYN_SENT:
 	case NES_CM_STATE_MPAREQ_SENT:
 		nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
-			"listener=%p state=%d\n", __func__, __LINE__, cm_node,
-			cm_node->listener, cm_node->state);
+			  "listener=%p state=%d\n", __func__, __LINE__, cm_node,
+			  cm_node->listener, cm_node->state);
 		active_open_err(cm_node, skb, 1);
 		break;
 	case NES_CM_STATE_ESTABLISHED:
@@ -1550,11 +1792,11 @@
 }
 
 static int check_syn(struct nes_cm_node *cm_node, struct tcphdr *tcph,
-	struct sk_buff *skb)
+		     struct sk_buff *skb)
 {
 	int err;
 
-	err = ((ntohl(tcph->ack_seq) == cm_node->tcp_cntxt.loc_seq_num))? 0 : 1;
+	err = ((ntohl(tcph->ack_seq) == cm_node->tcp_cntxt.loc_seq_num)) ? 0 : 1;
 	if (err)
 		active_open_err(cm_node, skb, 1);
 
@@ -1562,7 +1804,7 @@
 }
 
 static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph,
-	struct sk_buff *skb)
+		     struct sk_buff *skb)
 {
 	int err = 0;
 	u32 seq;
@@ -1570,21 +1812,22 @@
 	u32 loc_seq_num = cm_node->tcp_cntxt.loc_seq_num;
 	u32 rcv_nxt = cm_node->tcp_cntxt.rcv_nxt;
 	u32 rcv_wnd;
+
 	seq = ntohl(tcph->seq);
 	ack_seq = ntohl(tcph->ack_seq);
 	rcv_wnd = cm_node->tcp_cntxt.rcv_wnd;
 	if (ack_seq != loc_seq_num)
 		err = 1;
-	else if (!between(seq, rcv_nxt, (rcv_nxt+rcv_wnd)))
+	else if (!between(seq, rcv_nxt, (rcv_nxt + rcv_wnd)))
 		err = 1;
 	if (err) {
 		nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
-			"listener=%p state=%d\n", __func__, __LINE__, cm_node,
-			cm_node->listener, cm_node->state);
+			  "listener=%p state=%d\n", __func__, __LINE__, cm_node,
+			  cm_node->listener, cm_node->state);
 		indicate_pkt_err(cm_node, skb);
 		nes_debug(NES_DBG_CM, "seq ERROR cm_node =%p seq=0x%08X "
-			"rcv_nxt=0x%08X rcv_wnd=0x%x\n", cm_node, seq, rcv_nxt,
-			rcv_wnd);
+			  "rcv_nxt=0x%08X rcv_wnd=0x%x\n", cm_node, seq, rcv_nxt,
+			  rcv_wnd);
 	}
 	return err;
 }
@@ -1594,9 +1837,8 @@
  * is created with a listener or it may comein as rexmitted packet which in
  * that case will be just dropped.
  */
-
 static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	struct tcphdr *tcph)
+			   struct tcphdr *tcph)
 {
 	int ret;
 	u32 inc_sequence;
@@ -1615,15 +1857,15 @@
 	case NES_CM_STATE_LISTENING:
 		/* Passive OPEN */
 		if (atomic_read(&cm_node->listener->pend_accepts_cnt) >
-				cm_node->listener->backlog) {
+		    cm_node->listener->backlog) {
 			nes_debug(NES_DBG_CM, "drop syn due to backlog "
-				"pressure \n");
+				  "pressure \n");
 			cm_backlog_drops++;
 			passive_open_err(cm_node, skb, 0);
 			break;
 		}
 		ret = handle_tcp_options(cm_node, tcph, skb, optionsize,
-			1);
+					 1);
 		if (ret) {
 			passive_open_err(cm_node, skb, 0);
 			/* drop pkt */
@@ -1657,9 +1899,8 @@
 }
 
 static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	struct tcphdr *tcph)
+			      struct tcphdr *tcph)
 {
-
 	int ret;
 	u32 inc_sequence;
 	int optionsize;
@@ -1678,7 +1919,7 @@
 		ret = handle_tcp_options(cm_node, tcph, skb, optionsize, 0);
 		if (ret) {
 			nes_debug(NES_DBG_CM, "cm_node=%p tcp_options failed\n",
-				cm_node);
+				  cm_node);
 			break;
 		}
 		cleanup_retrans_entry(cm_node);
@@ -1717,12 +1958,13 @@
 }
 
 static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	struct tcphdr *tcph)
+			  struct tcphdr *tcph)
 {
 	int datasize = 0;
 	u32 inc_sequence;
 	int ret = 0;
 	int optionsize;
+
 	optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);
 
 	if (check_seq(cm_node, tcph, skb))
@@ -1743,8 +1985,9 @@
 		if (datasize) {
 			cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
 			handle_rcv_mpa(cm_node, skb);
-		} else  /* rcvd ACK only */
+		} else { /* rcvd ACK only */
 			dev_kfree_skb_any(skb);
+		}
 		break;
 	case NES_CM_STATE_ESTABLISHED:
 		/* Passive OPEN */
@@ -1752,16 +1995,18 @@
 		if (datasize) {
 			cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
 			handle_rcv_mpa(cm_node, skb);
-		} else
+		} else {
 			drop_packet(skb);
+		}
 		break;
 	case NES_CM_STATE_MPAREQ_SENT:
 		cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
 		if (datasize) {
 			cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
 			handle_rcv_mpa(cm_node, skb);
-		} else  /* Could be just an ack pkt.. */
+		} else { /* Could be just an ack pkt.. */
 			dev_kfree_skb_any(skb);
+		}
 		break;
 	case NES_CM_STATE_LISTENING:
 		cleanup_retrans_entry(cm_node);
@@ -1802,14 +2047,15 @@
 
 
 static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
-	struct sk_buff *skb, int optionsize, int passive)
+			      struct sk_buff *skb, int optionsize, int passive)
 {
 	u8 *optionsloc = (u8 *)&tcph[1];
+
 	if (optionsize) {
 		if (process_options(cm_node, optionsloc, optionsize,
-			(u32)tcph->syn)) {
+				    (u32)tcph->syn)) {
 			nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n",
-				__func__, cm_node);
+				  __func__, cm_node);
 			if (passive)
 				passive_open_err(cm_node, skb, 1);
 			else
@@ -1819,7 +2065,7 @@
 	}
 
 	cm_node->tcp_cntxt.snd_wnd = ntohs(tcph->window) <<
-			cm_node->tcp_cntxt.snd_wscale;
+				     cm_node->tcp_cntxt.snd_wscale;
 
 	if (cm_node->tcp_cntxt.snd_wnd > cm_node->tcp_cntxt.max_snd_wnd)
 		cm_node->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.snd_wnd;
@@ -1830,18 +2076,18 @@
  * active_open_err() will send reset() if flag set..
  * It will also send ABORT event.
  */
-
 static void active_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	int reset)
+			    int reset)
 {
 	cleanup_retrans_entry(cm_node);
 	if (reset) {
 		nes_debug(NES_DBG_CM, "ERROR active err called for cm_node=%p, "
-				"state=%d\n", cm_node, cm_node->state);
+			  "state=%d\n", cm_node, cm_node->state);
 		add_ref_cm_node(cm_node);
 		send_reset(cm_node, skb);
-	} else
+	} else {
 		dev_kfree_skb_any(skb);
+	}
 
 	cm_node->state = NES_CM_STATE_CLOSED;
 	create_event(cm_node, NES_CM_EVENT_ABORTED);
@@ -1851,15 +2097,14 @@
  * passive_open_err() will either do a reset() or will free up the skb and
  * remove the cm_node.
  */
-
 static void passive_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	int reset)
+			     int reset)
 {
 	cleanup_retrans_entry(cm_node);
 	cm_node->state = NES_CM_STATE_CLOSED;
 	if (reset) {
 		nes_debug(NES_DBG_CM, "passive_open_err sending RST for "
-			"cm_node=%p state =%d\n", cm_node, cm_node->state);
+			  "cm_node=%p state =%d\n", cm_node, cm_node->state);
 		send_reset(cm_node, skb);
 	} else {
 		dev_kfree_skb_any(skb);
@@ -1874,6 +2119,7 @@
 static void free_retrans_entry(struct nes_cm_node *cm_node)
 {
 	struct nes_timer_entry *send_entry;
+
 	send_entry = cm_node->send_entry;
 	if (send_entry) {
 		cm_node->send_entry = NULL;
@@ -1897,26 +2143,28 @@
  * Returns skb if to be freed, else it will return NULL if already used..
  */
 static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	struct nes_cm_core *cm_core)
+			   struct nes_cm_core *cm_core)
 {
-	enum nes_tcpip_pkt_type	pkt_type = NES_PKT_TYPE_UNKNOWN;
+	enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN;
 	struct tcphdr *tcph = tcp_hdr(skb);
-	u32     fin_set = 0;
+	u32 fin_set = 0;
 	int ret = 0;
+
 	skb_pull(skb, ip_hdr(skb)->ihl << 2);
 
 	nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d "
-		"ack=%d rst=%d fin=%d\n", cm_node, cm_node->state, tcph->syn,
-		tcph->ack, tcph->rst, tcph->fin);
+		  "ack=%d rst=%d fin=%d\n", cm_node, cm_node->state, tcph->syn,
+		  tcph->ack, tcph->rst, tcph->fin);
 
-	if (tcph->rst)
+	if (tcph->rst) {
 		pkt_type = NES_PKT_TYPE_RST;
-	else if (tcph->syn) {
+	} else if (tcph->syn) {
 		pkt_type = NES_PKT_TYPE_SYN;
 		if (tcph->ack)
 			pkt_type = NES_PKT_TYPE_SYNACK;
-	} else if (tcph->ack)
+	} else if (tcph->ack) {
 		pkt_type = NES_PKT_TYPE_ACK;
+	}
 	if (tcph->fin)
 		fin_set = 1;
 
@@ -1947,17 +2195,17 @@
  * mini_cm_listen - create a listen node with params
  */
 static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
-	struct nes_vnic *nesvnic, struct nes_cm_info *cm_info)
+					      struct nes_vnic *nesvnic, struct nes_cm_info *cm_info)
 {
 	struct nes_cm_listener *listener;
 	unsigned long flags;
 
 	nes_debug(NES_DBG_CM, "Search for 0x%08x : 0x%04x\n",
-		cm_info->loc_addr, cm_info->loc_port);
+		  cm_info->loc_addr, cm_info->loc_port);
 
 	/* cannot have multiple matching listeners */
 	listener = find_listener(cm_core, htonl(cm_info->loc_addr),
-			htons(cm_info->loc_port), NES_CM_LISTENER_EITHER_STATE);
+				 htons(cm_info->loc_port), NES_CM_LISTENER_EITHER_STATE);
 	if (listener && listener->listener_state == NES_CM_LISTENER_ACTIVE_STATE) {
 		/* find automatically incs ref count ??? */
 		atomic_dec(&listener->ref_count);
@@ -2003,9 +2251,9 @@
 	}
 
 	nes_debug(NES_DBG_CM, "Api - listen(): addr=0x%08X, port=0x%04x,"
-			" listener = %p, backlog = %d, cm_id = %p.\n",
-			cm_info->loc_addr, cm_info->loc_port,
-			listener, listener->backlog, listener->cm_id);
+		  " listener = %p, backlog = %d, cm_id = %p.\n",
+		  cm_info->loc_addr, cm_info->loc_port,
+		  listener, listener->backlog, listener->cm_id);
 
 	return listener;
 }
@@ -2015,26 +2263,20 @@
  * mini_cm_connect - make a connection node with params
  */
 static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
-	struct nes_vnic *nesvnic, u16 private_data_len,
-	void *private_data, struct nes_cm_info *cm_info)
+					   struct nes_vnic *nesvnic, u16 private_data_len,
+					   void *private_data, struct nes_cm_info *cm_info)
 {
 	int ret = 0;
 	struct nes_cm_node *cm_node;
 	struct nes_cm_listener *loopbackremotelistener;
 	struct nes_cm_node *loopbackremotenode;
 	struct nes_cm_info loopback_cm_info;
-	u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) + private_data_len;
-	struct ietf_mpa_frame *mpa_frame = NULL;
+	u8 *start_buff;
 
 	/* create a CM connection node */
 	cm_node = make_cm_node(cm_core, nesvnic, cm_info, NULL);
 	if (!cm_node)
 		return NULL;
-	mpa_frame = &cm_node->mpa_frame;
-	memcpy(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE);
-	mpa_frame->flags = IETF_MPA_FLAGS_CRC;
-	mpa_frame->rev =  IETF_MPA_VERSION;
-	mpa_frame->priv_data_len = htons(private_data_len);
 
 	/* set our node side to client (active) side */
 	cm_node->tcp_cntxt.client = 1;
@@ -2042,8 +2284,8 @@
 
 	if (cm_info->loc_addr == cm_info->rem_addr) {
 		loopbackremotelistener = find_listener(cm_core,
-				ntohl(nesvnic->local_ipaddr), cm_node->rem_port,
-				NES_CM_LISTENER_ACTIVE_STATE);
+						       ntohl(nesvnic->local_ipaddr), cm_node->rem_port,
+						       NES_CM_LISTENER_ACTIVE_STATE);
 		if (loopbackremotelistener == NULL) {
 			create_event(cm_node, NES_CM_EVENT_ABORTED);
 		} else {
@@ -2052,7 +2294,7 @@
 			loopback_cm_info.rem_port = cm_info->loc_port;
 			loopback_cm_info.cm_id = loopbackremotelistener->cm_id;
 			loopbackremotenode = make_cm_node(cm_core, nesvnic,
-				&loopback_cm_info, loopbackremotelistener);
+							  &loopback_cm_info, loopbackremotelistener);
 			if (!loopbackremotenode) {
 				rem_ref_cm_node(cm_node->cm_core, cm_node);
 				return NULL;
@@ -2063,7 +2305,7 @@
 				NES_CM_DEFAULT_RCV_WND_SCALE;
 			cm_node->loopbackpartner = loopbackremotenode;
 			memcpy(loopbackremotenode->mpa_frame_buf, private_data,
-				private_data_len);
+			       private_data_len);
 			loopbackremotenode->mpa_frame_size = private_data_len;
 
 			/* we are done handling this state. */
@@ -2091,12 +2333,10 @@
 		return cm_node;
 	}
 
-	/* set our node side to client (active) side */
-	cm_node->tcp_cntxt.client = 1;
-	/* init our MPA frame ptr */
-	memcpy(mpa_frame->priv_data, private_data, private_data_len);
+	start_buff = &cm_node->mpa_frame_buf[0] + sizeof(struct ietf_mpa_v2);
+	cm_node->mpa_frame_size = private_data_len;
 
-	cm_node->mpa_frame_size = mpa_frame_size;
+	memcpy(start_buff, private_data, private_data_len);
 
 	/* send a syn and goto syn sent state */
 	cm_node->state = NES_CM_STATE_SYN_SENT;
@@ -2105,18 +2345,19 @@
 	if (ret) {
 		/* error in sending the syn free up the cm_node struct */
 		nes_debug(NES_DBG_CM, "Api - connect() FAILED: dest "
-			"addr=0x%08X, port=0x%04x, cm_node=%p, cm_id = %p.\n",
-			cm_node->rem_addr, cm_node->rem_port, cm_node,
-			cm_node->cm_id);
+			  "addr=0x%08X, port=0x%04x, cm_node=%p, cm_id = %p.\n",
+			  cm_node->rem_addr, cm_node->rem_port, cm_node,
+			  cm_node->cm_id);
 		rem_ref_cm_node(cm_node->cm_core, cm_node);
 		cm_node = NULL;
 	}
 
-	if (cm_node)
+	if (cm_node) {
 		nes_debug(NES_DBG_CM, "Api - connect(): dest addr=0x%08X,"
-			"port=0x%04x, cm_node=%p, cm_id = %p.\n",
-			cm_node->rem_addr, cm_node->rem_port, cm_node,
-			cm_node->cm_id);
+			  "port=0x%04x, cm_node=%p, cm_id = %p.\n",
+			  cm_node->rem_addr, cm_node->rem_port, cm_node,
+			  cm_node->cm_id);
+	}
 
 	return cm_node;
 }
@@ -2126,8 +2367,7 @@
  * mini_cm_accept - accept a connection
  * This function is never called
  */
-static int mini_cm_accept(struct nes_cm_core *cm_core,
-	struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node)
+static int mini_cm_accept(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
 {
 	return 0;
 }
@@ -2136,8 +2376,7 @@
 /**
  * mini_cm_reject - reject and teardown a connection
  */
-static int mini_cm_reject(struct nes_cm_core *cm_core,
-	struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node)
+static int mini_cm_reject(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
 {
 	int ret = 0;
 	int err = 0;
@@ -2147,7 +2386,7 @@
 	struct nes_cm_node *loopback = cm_node->loopbackpartner;
 
 	nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n",
-		__func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state);
+		  __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state);
 
 	if (cm_node->tcp_cntxt.client)
 		return ret;
@@ -2168,8 +2407,9 @@
 					err = send_reset(cm_node, NULL);
 					if (err)
 						WARN_ON(1);
-				} else
+				} else {
 					cm_id->add_ref(cm_id);
+				}
 			}
 		}
 	} else {
@@ -2244,7 +2484,7 @@
 	case NES_CM_STATE_TSA:
 		if (cm_node->send_entry)
 			printk(KERN_ERR "ERROR Close got called from STATE_TSA "
-				"send_entry=%p\n", cm_node->send_entry);
+			       "send_entry=%p\n", cm_node->send_entry);
 		ret = rem_ref_cm_node(cm_core, cm_node);
 		break;
 	}
@@ -2257,7 +2497,7 @@
  * node state machine
  */
 static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
-	struct nes_vnic *nesvnic, struct sk_buff *skb)
+			    struct nes_vnic *nesvnic, struct sk_buff *skb)
 {
 	struct nes_cm_node *cm_node = NULL;
 	struct nes_cm_listener *listener = NULL;
@@ -2269,9 +2509,8 @@
 
 	if (!skb)
 		return 0;
-	if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) {
+	if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr))
 		return 0;
-	}
 
 	iph = (struct iphdr *)skb->data;
 	tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr));
@@ -2289,8 +2528,8 @@
 
 	do {
 		cm_node = find_node(cm_core,
-			nfo.rem_port, nfo.rem_addr,
-			nfo.loc_port, nfo.loc_addr);
+				    nfo.rem_port, nfo.rem_addr,
+				    nfo.loc_port, nfo.loc_addr);
 
 		if (!cm_node) {
 			/* Only type of packet accepted are for */
@@ -2300,8 +2539,8 @@
 				break;
 			}
 			listener = find_listener(cm_core, nfo.loc_addr,
-				nfo.loc_port,
-				NES_CM_LISTENER_ACTIVE_STATE);
+						 nfo.loc_port,
+						 NES_CM_LISTENER_ACTIVE_STATE);
 			if (!listener) {
 				nfo.cm_id = NULL;
 				nfo.conn_type = 0;
@@ -2312,10 +2551,10 @@
 			nfo.cm_id = listener->cm_id;
 			nfo.conn_type = listener->conn_type;
 			cm_node = make_cm_node(cm_core, nesvnic, &nfo,
-				listener);
+					       listener);
 			if (!cm_node) {
 				nes_debug(NES_DBG_CM, "Unable to allocate "
-					"node\n");
+					  "node\n");
 				cm_packets_dropped++;
 				atomic_dec(&listener->ref_count);
 				dev_kfree_skb_any(skb);
@@ -2331,9 +2570,13 @@
 			}
 			add_ref_cm_node(cm_node);
 		} else if (cm_node->state == NES_CM_STATE_TSA) {
-			rem_ref_cm_node(cm_core, cm_node);
-			atomic_inc(&cm_accel_dropped_pkts);
-			dev_kfree_skb_any(skb);
+			if (cm_node->nesqp->pau_mode)
+				nes_queue_mgt_skbs(skb, nesvnic, cm_node->nesqp);
+			else {
+				rem_ref_cm_node(cm_core, cm_node);
+				atomic_inc(&cm_accel_dropped_pkts);
+				dev_kfree_skb_any(skb);
+			}
 			break;
 		}
 		skb_reset_network_header(skb);
@@ -2363,7 +2606,7 @@
 	init_timer(&cm_core->tcp_timer);
 	cm_core->tcp_timer.function = nes_cm_timer_tick;
 
-	cm_core->mtu   = NES_CM_DEFAULT_MTU;
+	cm_core->mtu = NES_CM_DEFAULT_MTU;
 	cm_core->state = NES_CM_STATE_INITED;
 	cm_core->free_tx_pkt_max = NES_CM_DEFAULT_FREE_PKTS;
 
@@ -2401,9 +2644,8 @@
 
 	barrier();
 
-	if (timer_pending(&cm_core->tcp_timer)) {
+	if (timer_pending(&cm_core->tcp_timer))
 		del_timer(&cm_core->tcp_timer);
-	}
 
 	destroy_workqueue(cm_core->event_wq);
 	destroy_workqueue(cm_core->disconn_wq);
@@ -2458,8 +2700,8 @@
 		return -EINVAL;
 
 	nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_IPV4 |
-			NES_QPCONTEXT_MISC_NO_NAGLE | NES_QPCONTEXT_MISC_DO_NOT_FRAG |
-			NES_QPCONTEXT_MISC_DROS);
+						  NES_QPCONTEXT_MISC_NO_NAGLE | NES_QPCONTEXT_MISC_DO_NOT_FRAG |
+						  NES_QPCONTEXT_MISC_DROS);
 
 	if (cm_node->tcp_cntxt.snd_wscale || cm_node->tcp_cntxt.rcv_wscale)
 		nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_WSCALE);
@@ -2469,15 +2711,15 @@
 	nesqp->nesqp_context->mss |= cpu_to_le32(((u32)cm_node->tcp_cntxt.mss) << 16);
 
 	nesqp->nesqp_context->tcp_state_flow_label |= cpu_to_le32(
-			(u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT);
+		(u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT);
 
 	nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32(
-			(cm_node->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) &
-			NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK);
+		(cm_node->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) &
+		NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK);
 
 	nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32(
-			(cm_node->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) &
-			NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK);
+		(cm_node->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) &
+		NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK);
 
 	nesqp->nesqp_context->keepalive = cpu_to_le32(0x80);
 	nesqp->nesqp_context->ts_recent = 0;
@@ -2486,24 +2728,24 @@
 	nesqp->nesqp_context->snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.snd_wnd);
 	nesqp->nesqp_context->rcv_nxt = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt);
 	nesqp->nesqp_context->rcv_wnd = cpu_to_le32(cm_node->tcp_cntxt.rcv_wnd <<
-			cm_node->tcp_cntxt.rcv_wscale);
+						    cm_node->tcp_cntxt.rcv_wscale);
 	nesqp->nesqp_context->snd_max = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
 	nesqp->nesqp_context->snd_una = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
 	nesqp->nesqp_context->srtt = 0;
 	nesqp->nesqp_context->rttvar = cpu_to_le32(0x6);
 	nesqp->nesqp_context->ssthresh = cpu_to_le32(0x3FFFC000);
-	nesqp->nesqp_context->cwnd = cpu_to_le32(2*cm_node->tcp_cntxt.mss);
+	nesqp->nesqp_context->cwnd = cpu_to_le32(2 * cm_node->tcp_cntxt.mss);
 	nesqp->nesqp_context->snd_wl1 = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt);
 	nesqp->nesqp_context->snd_wl2 = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
 	nesqp->nesqp_context->max_snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.max_snd_wnd);
 
 	nes_debug(NES_DBG_CM, "QP%u: rcv_nxt = 0x%08X, snd_nxt = 0x%08X,"
-			" Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n",
-			nesqp->hwqp.qp_id, le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
-			le32_to_cpu(nesqp->nesqp_context->snd_nxt),
-			cm_node->tcp_cntxt.mss, le32_to_cpu(nesqp->nesqp_context->pd_index_wscale),
-			le32_to_cpu(nesqp->nesqp_context->rcv_wnd),
-			le32_to_cpu(nesqp->nesqp_context->misc));
+		  " Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n",
+		  nesqp->hwqp.qp_id, le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
+		  le32_to_cpu(nesqp->nesqp_context->snd_nxt),
+		  cm_node->tcp_cntxt.mss, le32_to_cpu(nesqp->nesqp_context->pd_index_wscale),
+		  le32_to_cpu(nesqp->nesqp_context->rcv_wnd),
+		  le32_to_cpu(nesqp->nesqp_context->misc));
 	nes_debug(NES_DBG_CM, "  snd_wnd  = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->snd_wnd));
 	nes_debug(NES_DBG_CM, "  snd_cwnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->cwnd));
 	nes_debug(NES_DBG_CM, "  max_swnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->max_snd_wnd));
@@ -2524,7 +2766,7 @@
 
 	work = kzalloc(sizeof *work, GFP_ATOMIC);
 	if (!work)
-		return -ENOMEM; /* Timer will clean up */
+		return -ENOMEM;  /* Timer will clean up */
 
 	nes_add_ref(&nesqp->ibqp);
 	work->nesqp = nesqp;
@@ -2544,7 +2786,7 @@
 
 	kfree(dwork);
 	nes_debug(NES_DBG_CM, "processing AEQE id 0x%04X for QP%u.\n",
-			nesqp->last_aeq, nesqp->hwqp.qp_id);
+		  nesqp->last_aeq, nesqp->hwqp.qp_id);
 	nes_cm_disconn_true(nesqp);
 	nes_rem_ref(&nesqp->ibqp);
 }
@@ -2580,7 +2822,7 @@
 	/* make sure we havent already closed this connection */
 	if (!cm_id) {
 		nes_debug(NES_DBG_CM, "QP%u disconnect_worker cmid is NULL\n",
-				nesqp->hwqp.qp_id);
+			  nesqp->hwqp.qp_id);
 		spin_unlock_irqrestore(&nesqp->lock, flags);
 		return -1;
 	}
@@ -2589,7 +2831,7 @@
 	nes_debug(NES_DBG_CM, "Disconnecting QP%u\n", nesqp->hwqp.qp_id);
 
 	original_hw_tcp_state = nesqp->hw_tcp_state;
-	original_ibqp_state   = nesqp->ibqp_state;
+	original_ibqp_state = nesqp->ibqp_state;
 	last_ae = nesqp->last_aeq;
 
 	if (nesqp->term_flags) {
@@ -2647,16 +2889,16 @@
 			cm_event.private_data_len = 0;
 
 			nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event"
-				" for  QP%u, SQ Head = %u, SQ Tail = %u. "
-				"cm_id = %p, refcount = %u.\n",
-				nesqp->hwqp.qp_id, nesqp->hwqp.sq_head,
-				nesqp->hwqp.sq_tail, cm_id,
-				atomic_read(&nesqp->refcount));
+				  " for  QP%u, SQ Head = %u, SQ Tail = %u. "
+				  "cm_id = %p, refcount = %u.\n",
+				  nesqp->hwqp.qp_id, nesqp->hwqp.sq_head,
+				  nesqp->hwqp.sq_tail, cm_id,
+				  atomic_read(&nesqp->refcount));
 
 			ret = cm_id->event_handler(cm_id, &cm_event);
 			if (ret)
 				nes_debug(NES_DBG_CM, "OFA CM event_handler "
-					"returned, ret=%d\n", ret);
+					  "returned, ret=%d\n", ret);
 		}
 
 		if (issue_close) {
@@ -2674,9 +2916,8 @@
 			cm_event.private_data_len = 0;
 
 			ret = cm_id->event_handler(cm_id, &cm_event);
-			if (ret) {
+			if (ret)
 				nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
-			}
 
 			cm_id->rem_ref(cm_id);
 		}
@@ -2716,8 +2957,8 @@
 			if (nesqp->lsmm_mr)
 				nesibdev->ibdev.dereg_mr(nesqp->lsmm_mr);
 			pci_free_consistent(nesdev->pcidev,
-					nesqp->private_data_len+sizeof(struct ietf_mpa_frame),
-					nesqp->ietf_frame, nesqp->ietf_frame_pbase);
+					    nesqp->private_data_len + nesqp->ietf_frame_size,
+					    nesqp->ietf_frame, nesqp->ietf_frame_pbase);
 		}
 	}
 
@@ -2756,6 +2997,12 @@
 	struct ib_phys_buf ibphysbuf;
 	struct nes_pd *nespd;
 	u64 tagged_offset;
+	u8 mpa_frame_offset = 0;
+	struct ietf_mpa_v2 *mpa_v2_frame;
+	u8 start_addr = 0;
+	u8 *start_ptr = &start_addr;
+	u8 **start_buff = &start_ptr;
+	u16 buff_len = 0;
 
 	ibqp = nes_get_qp(cm_id->device, conn_param->qpn);
 	if (!ibqp)
@@ -2796,53 +3043,49 @@
 	nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n",
 			netdev_refcnt_read(nesvnic->netdev));
 
+	nesqp->ietf_frame_size = sizeof(struct ietf_mpa_v2);
 	/* allocate the ietf frame and space for private data */
 	nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev,
-		sizeof(struct ietf_mpa_frame) + conn_param->private_data_len,
-		&nesqp->ietf_frame_pbase);
+						 nesqp->ietf_frame_size + conn_param->private_data_len,
+						 &nesqp->ietf_frame_pbase);
 
 	if (!nesqp->ietf_frame) {
-		nes_debug(NES_DBG_CM, "Unable to allocate memory for private "
-			"data\n");
+		nes_debug(NES_DBG_CM, "Unable to allocate memory for private data\n");
 		return -ENOMEM;
 	}
+	mpa_v2_frame = (struct ietf_mpa_v2 *)nesqp->ietf_frame;
 
+	if (cm_node->mpa_frame_rev == IETF_MPA_V1)
+		mpa_frame_offset = 4;
 
-	/* setup the MPA frame */
-	nesqp->private_data_len = conn_param->private_data_len;
-	memcpy(nesqp->ietf_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
-
-	memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data,
-			conn_param->private_data_len);
+	memcpy(mpa_v2_frame->priv_data, conn_param->private_data,
+	       conn_param->private_data_len);
 
-	nesqp->ietf_frame->priv_data_len =
-		cpu_to_be16(conn_param->private_data_len);
-	nesqp->ietf_frame->rev = mpa_version;
-	nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC;
+	cm_build_mpa_frame(cm_node, start_buff, &buff_len, nesqp->ietf_frame, MPA_KEY_REPLY);
+	nesqp->private_data_len = conn_param->private_data_len;
 
 	/* setup our first outgoing iWarp send WQE (the IETF frame response) */
 	wqe = &nesqp->hwqp.sq_vbase[0];
 
 	if (cm_id->remote_addr.sin_addr.s_addr !=
-			cm_id->local_addr.sin_addr.s_addr) {
+	    cm_id->local_addr.sin_addr.s_addr) {
 		u64temp = (unsigned long)nesqp;
 		nesibdev = nesvnic->nesibdev;
 		nespd = nesqp->nespd;
-		ibphysbuf.addr = nesqp->ietf_frame_pbase;
-		ibphysbuf.size = conn_param->private_data_len +
-					sizeof(struct ietf_mpa_frame);
-		tagged_offset = (u64)(unsigned long)nesqp->ietf_frame;
+		ibphysbuf.addr = nesqp->ietf_frame_pbase + mpa_frame_offset;
+		ibphysbuf.size = buff_len;
+		tagged_offset = (u64)(unsigned long)*start_buff;
 		ibmr = nesibdev->ibdev.reg_phys_mr((struct ib_pd *)nespd,
-						&ibphysbuf, 1,
-						IB_ACCESS_LOCAL_WRITE,
-						&tagged_offset);
+						   &ibphysbuf, 1,
+						   IB_ACCESS_LOCAL_WRITE,
+						   &tagged_offset);
 		if (!ibmr) {
 			nes_debug(NES_DBG_CM, "Unable to register memory region"
-					"for lSMM for cm_node = %p \n",
-					cm_node);
+				  "for lSMM for cm_node = %p \n",
+				  cm_node);
 			pci_free_consistent(nesdev->pcidev,
-				nesqp->private_data_len+sizeof(struct ietf_mpa_frame),
-				nesqp->ietf_frame, nesqp->ietf_frame_pbase);
+					    nesqp->private_data_len + nesqp->ietf_frame_size,
+					    nesqp->ietf_frame, nesqp->ietf_frame_pbase);
 			return -ENOMEM;
 		}
 
@@ -2850,22 +3093,20 @@
 		ibmr->device = nespd->ibpd.device;
 		nesqp->lsmm_mr = ibmr;
 
-		u64temp |= NES_SW_CONTEXT_ALIGN>>1;
+		u64temp |= NES_SW_CONTEXT_ALIGN >> 1;
 		set_wqe_64bit_value(wqe->wqe_words,
-			NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX,
-			u64temp);
+				    NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX,
+				    u64temp);
 		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
 			cpu_to_le32(NES_IWARP_SQ_WQE_STREAMING |
-			NES_IWARP_SQ_WQE_WRPDU);
+				    NES_IWARP_SQ_WQE_WRPDU);
 		wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] =
-			cpu_to_le32(conn_param->private_data_len +
-			sizeof(struct ietf_mpa_frame));
+			cpu_to_le32(buff_len);
 		set_wqe_64bit_value(wqe->wqe_words,
-					NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,
-					(u64)(unsigned long)nesqp->ietf_frame);
+				    NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,
+				    (u64)(unsigned long)(*start_buff));
 		wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] =
-			cpu_to_le32(conn_param->private_data_len +
-			sizeof(struct ietf_mpa_frame));
+			cpu_to_le32(buff_len);
 		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = ibmr->lkey;
 		if (nesqp->sq_kmapped) {
 			nesqp->sq_kmapped = 0;
@@ -2874,7 +3115,7 @@
 
 		nesqp->nesqp_context->ird_ord_sizes |=
 			cpu_to_le32(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
-			NES_QPCONTEXT_ORDIRD_WRPDU);
+				    NES_QPCONTEXT_ORDIRD_WRPDU);
 	} else {
 		nesqp->nesqp_context->ird_ord_sizes |=
 			cpu_to_le32(NES_QPCONTEXT_ORDIRD_WRPDU);
@@ -2888,11 +3129,11 @@
 
 	/*  nesqp->cm_node = (void *)cm_id->provider_data; */
 	cm_id->provider_data = nesqp;
-	nesqp->active_conn   = 0;
+	nesqp->active_conn = 0;
 
 	if (cm_node->state == NES_CM_STATE_TSA)
 		nes_debug(NES_DBG_CM, "Already state = TSA for cm_node=%p\n",
-			cm_node);
+			  cm_node);
 
 	nes_cm_init_tsa_conn(nesqp, cm_node);
 
@@ -2909,13 +3150,13 @@
 			cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr));
 
 	nesqp->nesqp_context->misc2 |= cpu_to_le32(
-			(u32)PCI_FUNC(nesdev->pcidev->devfn) <<
-			NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);
+		(u32)PCI_FUNC(nesdev->pcidev->devfn) <<
+		NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);
 
 	nesqp->nesqp_context->arp_index_vlan |=
 		cpu_to_le32(nes_arp_table(nesdev,
-			le32_to_cpu(nesqp->nesqp_context->ip0), NULL,
-			NES_ARP_RESOLVE) << 16);
+					  le32_to_cpu(nesqp->nesqp_context->ip0), NULL,
+					  NES_ARP_RESOLVE) << 16);
 
 	nesqp->nesqp_context->ts_val_delta = cpu_to_le32(
 		jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW));
@@ -2941,7 +3182,7 @@
 	crc_value = get_crc_value(&nes_quad);
 	nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);
 	nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, CRC = 0x%08X\n",
-		nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask);
+		  nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask);
 
 	nesqp->hte_index &= adapter->hte_index_mask;
 	nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
@@ -2949,17 +3190,15 @@
 	cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node);
 
 	nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = "
-			"0x%08X:0x%04X, rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + "
-			"private data length=%zu.\n", nesqp->hwqp.qp_id,
-			ntohl(cm_id->remote_addr.sin_addr.s_addr),
-			ntohs(cm_id->remote_addr.sin_port),
-			ntohl(cm_id->local_addr.sin_addr.s_addr),
-			ntohs(cm_id->local_addr.sin_port),
-			le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
-			le32_to_cpu(nesqp->nesqp_context->snd_nxt),
-			conn_param->private_data_len +
-			sizeof(struct ietf_mpa_frame));
-
+		  "0x%08X:0x%04X, rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + "
+		  "private data length=%u.\n", nesqp->hwqp.qp_id,
+		  ntohl(cm_id->remote_addr.sin_addr.s_addr),
+		  ntohs(cm_id->remote_addr.sin_port),
+		  ntohl(cm_id->local_addr.sin_addr.s_addr),
+		  ntohs(cm_id->local_addr.sin_port),
+		  le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
+		  le32_to_cpu(nesqp->nesqp_context->snd_nxt),
+		  buff_len);
 
 	/* notify OF layer that accept event was successful */
 	cm_id->add_ref(cm_id);
@@ -2980,12 +3219,12 @@
 			nesqp->private_data_len;
 		/* copy entire MPA frame to our cm_node's frame */
 		memcpy(cm_node->loopbackpartner->mpa_frame_buf,
-			nesqp->ietf_frame->priv_data, nesqp->private_data_len);
+		       conn_param->private_data, conn_param->private_data_len);
 		create_event(cm_node->loopbackpartner, NES_CM_EVENT_CONNECTED);
 	}
 	if (ret)
 		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
-			"ret=%d\n", __func__, __LINE__, ret);
+		       "ret=%d\n", __func__, __LINE__, ret);
 
 	return 0;
 }
@@ -2998,34 +3237,28 @@
 {
 	struct nes_cm_node *cm_node;
 	struct nes_cm_node *loopback;
-
 	struct nes_cm_core *cm_core;
+	u8 *start_buff;
 
 	atomic_inc(&cm_rejects);
-	cm_node = (struct nes_cm_node *) cm_id->provider_data;
+	cm_node = (struct nes_cm_node *)cm_id->provider_data;
 	loopback = cm_node->loopbackpartner;
 	cm_core = cm_node->cm_core;
 	cm_node->cm_id = cm_id;
-	cm_node->mpa_frame_size = sizeof(struct ietf_mpa_frame) + pdata_len;
 
-	if (cm_node->mpa_frame_size > MAX_CM_BUFFER)
+	if (pdata_len + sizeof(struct ietf_mpa_v2) > MAX_CM_BUFFER)
 		return -EINVAL;
 
-	memcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
 	if (loopback) {
 		memcpy(&loopback->mpa_frame.priv_data, pdata, pdata_len);
 		loopback->mpa_frame.priv_data_len = pdata_len;
-		loopback->mpa_frame_size = sizeof(struct ietf_mpa_frame) +
-				pdata_len;
+		loopback->mpa_frame_size = pdata_len;
 	} else {
-		memcpy(&cm_node->mpa_frame.priv_data, pdata, pdata_len);
-		cm_node->mpa_frame.priv_data_len = cpu_to_be16(pdata_len);
+		start_buff = &cm_node->mpa_frame_buf[0] + sizeof(struct ietf_mpa_v2);
+		cm_node->mpa_frame_size = pdata_len;
+		memcpy(start_buff, pdata, pdata_len);
 	}
-
-	cm_node->mpa_frame.rev = mpa_version;
-	cm_node->mpa_frame.flags = IETF_MPA_FLAGS_CRC | IETF_MPA_FLAGS_REJECT;
-
-	return cm_core->api->reject(cm_core, &cm_node->mpa_frame, cm_node);
+	return cm_core->api->reject(cm_core, cm_node);
 }
 
 
@@ -3052,7 +3285,7 @@
 	nesvnic = to_nesvnic(nesqp->ibqp.device);
 	if (!nesvnic)
 		return -EINVAL;
-	nesdev  = nesvnic->nesdev;
+	nesdev = nesvnic->nesdev;
 	if (!nesdev)
 		return -EINVAL;
 
@@ -3060,12 +3293,12 @@
 		return -EINVAL;
 
 	nes_debug(NES_DBG_CM, "QP%u, current IP = 0x%08X, Destination IP = "
-		"0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id,
-		ntohl(nesvnic->local_ipaddr),
-		ntohl(cm_id->remote_addr.sin_addr.s_addr),
-		ntohs(cm_id->remote_addr.sin_port),
-		ntohl(cm_id->local_addr.sin_addr.s_addr),
-		ntohs(cm_id->local_addr.sin_port));
+		  "0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id,
+		  ntohl(nesvnic->local_ipaddr),
+		  ntohl(cm_id->remote_addr.sin_addr.s_addr),
+		  ntohs(cm_id->remote_addr.sin_port),
+		  ntohl(cm_id->local_addr.sin_addr.s_addr),
+		  ntohs(cm_id->local_addr.sin_port));
 
 	atomic_inc(&cm_connects);
 	nesqp->active_conn = 1;
@@ -3079,12 +3312,12 @@
 	nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord);
 	nes_debug(NES_DBG_CM, "requested ord = 0x%08X.\n", (u32)conn_param->ord);
 	nes_debug(NES_DBG_CM, "mpa private data len =%u\n",
-		conn_param->private_data_len);
+		  conn_param->private_data_len);
 
 	if (cm_id->local_addr.sin_addr.s_addr !=
-		cm_id->remote_addr.sin_addr.s_addr) {
+	    cm_id->remote_addr.sin_addr.s_addr) {
 		nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
-			PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);
+				 PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);
 		apbvt_set = 1;
 	}
 
@@ -3100,13 +3333,13 @@
 
 	/* create a connect CM node connection */
 	cm_node = g_cm_core->api->connect(g_cm_core, nesvnic,
-		conn_param->private_data_len, (void *)conn_param->private_data,
-		&cm_info);
+					  conn_param->private_data_len, (void *)conn_param->private_data,
+					  &cm_info);
 	if (!cm_node) {
 		if (apbvt_set)
 			nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
-				PCI_FUNC(nesdev->pcidev->devfn),
-				NES_MANAGE_APBVT_DEL);
+					 PCI_FUNC(nesdev->pcidev->devfn),
+					 NES_MANAGE_APBVT_DEL);
 
 		cm_id->rem_ref(cm_id);
 		return -ENOMEM;
@@ -3156,7 +3389,7 @@
 	cm_node = g_cm_core->api->listen(g_cm_core, nesvnic, &cm_info);
 	if (!cm_node) {
 		printk(KERN_ERR "%s[%u] Error returned from listen API call\n",
-				__func__, __LINE__);
+		       __func__, __LINE__);
 		return -ENOMEM;
 	}
 
@@ -3164,12 +3397,12 @@
 
 	if (!cm_node->reused_node) {
 		err = nes_manage_apbvt(nesvnic,
-			ntohs(cm_id->local_addr.sin_port),
-			PCI_FUNC(nesvnic->nesdev->pcidev->devfn),
-			NES_MANAGE_APBVT_ADD);
+				       ntohs(cm_id->local_addr.sin_port),
+				       PCI_FUNC(nesvnic->nesdev->pcidev->devfn),
+				       NES_MANAGE_APBVT_ADD);
 		if (err) {
 			printk(KERN_ERR "nes_manage_apbvt call returned %d.\n",
-				err);
+			       err);
 			g_cm_core->api->stop_listener(g_cm_core, (void *)cm_node);
 			return err;
 		}
@@ -3206,13 +3439,13 @@
 int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice)
 {
 	int rc = 0;
+
 	cm_packets_received++;
-	if ((g_cm_core) && (g_cm_core->api)) {
+	if ((g_cm_core) && (g_cm_core->api))
 		rc = g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb);
-	} else {
+	else
 		nes_debug(NES_DBG_CM, "Unable to process packet for CM,"
-				" cm is not setup properly.\n");
-	}
+			  " cm is not setup properly.\n");
 
 	return rc;
 }
@@ -3227,11 +3460,10 @@
 	nes_debug(NES_DBG_CM, "\n");
 	/* create the primary CM core, pass this handle to subsequent core inits */
 	g_cm_core = nes_cm_alloc_core();
-	if (g_cm_core) {
+	if (g_cm_core)
 		return 0;
-	} else {
+	else
 		return -ENOMEM;
-	}
 }
 
 
@@ -3252,7 +3484,6 @@
  */
 static void cm_event_connected(struct nes_cm_event *event)
 {
-	u64 u64temp;
 	struct nes_qp *nesqp;
 	struct nes_vnic *nesvnic;
 	struct nes_device *nesdev;
@@ -3261,7 +3492,6 @@
 	struct ib_qp_attr attr;
 	struct iw_cm_id *cm_id;
 	struct iw_cm_event cm_event;
-	struct nes_hw_qp_wqe *wqe;
 	struct nes_v4_quad nes_quad;
 	u32 crc_value;
 	int ret;
@@ -3275,17 +3505,16 @@
 	nesdev = nesvnic->nesdev;
 	nesadapter = nesdev->nesadapter;
 
-	if (nesqp->destroyed) {
+	if (nesqp->destroyed)
 		return;
-	}
 	atomic_inc(&cm_connecteds);
 	nes_debug(NES_DBG_CM, "QP%u attempting to connect to  0x%08X:0x%04X on"
-			" local port 0x%04X. jiffies = %lu.\n",
-			nesqp->hwqp.qp_id,
-			ntohl(cm_id->remote_addr.sin_addr.s_addr),
-			ntohs(cm_id->remote_addr.sin_port),
-			ntohs(cm_id->local_addr.sin_port),
-			jiffies);
+		  " local port 0x%04X. jiffies = %lu.\n",
+		  nesqp->hwqp.qp_id,
+		  ntohl(cm_id->remote_addr.sin_addr.s_addr),
+		  ntohs(cm_id->remote_addr.sin_port),
+		  ntohs(cm_id->local_addr.sin_port),
+		  jiffies);
 
 	nes_cm_init_tsa_conn(nesqp, cm_node);
 
@@ -3316,40 +3545,12 @@
 			NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT);
 
 	/* Adjust tail for not having a LSMM */
-	nesqp->hwqp.sq_tail = 1;
-
-#if defined(NES_SEND_FIRST_WRITE)
-	if (cm_node->send_write0) {
-		nes_debug(NES_DBG_CM, "Sending first write.\n");
-		wqe = &nesqp->hwqp.sq_vbase[0];
-		u64temp = (unsigned long)nesqp;
-		u64temp |= NES_SW_CONTEXT_ALIGN>>1;
-		set_wqe_64bit_value(wqe->wqe_words,
-				NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, u64temp);
-		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
-			cpu_to_le32(NES_IWARP_SQ_OP_RDMAW);
-		wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0;
-		wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0;
-		wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0;
-		wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0;
-		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
+	/*nesqp->hwqp.sq_tail = 1;*/
 
-		if (nesqp->sq_kmapped) {
-			nesqp->sq_kmapped = 0;
-			kunmap(nesqp->page);
-		}
+	build_rdma0_msg(cm_node, &nesqp);
 
-		/* use the reserved spot on the WQ for the extra first WQE */
-		nesqp->nesqp_context->ird_ord_sizes &=
-			cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
-						NES_QPCONTEXT_ORDIRD_WRPDU |
-						NES_QPCONTEXT_ORDIRD_ALSMM));
-		nesqp->skip_lsmm = 1;
-		nesqp->hwqp.sq_tail = 0;
-		nes_write32(nesdev->regs + NES_WQE_ALLOC,
-				(1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);
-	}
-#endif
+	nes_write32(nesdev->regs + NES_WQE_ALLOC,
+		    (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);
 
 	memset(&nes_quad, 0, sizeof(nes_quad));
 
@@ -3366,13 +3567,13 @@
 	crc_value = get_crc_value(&nes_quad);
 	nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);
 	nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, After CRC = 0x%08X\n",
-			nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask);
+		  nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask);
 
 	nesqp->hte_index &= nesadapter->hte_index_mask;
 	nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
 
 	nesqp->ietf_frame = &cm_node->mpa_frame;
-	nesqp->private_data_len = (u8) cm_node->mpa_frame_size;
+	nesqp->private_data_len = (u8)cm_node->mpa_frame_size;
 	cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node);
 
 	/* notify OF layer we successfully created the requested connection */
@@ -3384,7 +3585,9 @@
 	cm_event.remote_addr = cm_id->remote_addr;
 
 	cm_event.private_data = (void *)event->cm_node->mpa_frame_buf;
-	cm_event.private_data_len = (u8) event->cm_node->mpa_frame_size;
+	cm_event.private_data_len = (u8)event->cm_node->mpa_frame_size;
+	cm_event.ird = cm_node->ird_size;
+	cm_event.ord = cm_node->ord_size;
 
 	cm_event.local_addr.sin_addr.s_addr = event->cm_info.rem_addr;
 	ret = cm_id->event_handler(cm_id, &cm_event);
@@ -3392,12 +3595,12 @@
 
 	if (ret)
 		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
-			"ret=%d\n", __func__, __LINE__, ret);
+		       "ret=%d\n", __func__, __LINE__, ret);
 	attr.qp_state = IB_QPS_RTS;
 	nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL);
 
 	nes_debug(NES_DBG_CM, "Exiting connect thread for QP%u. jiffies = "
-		"%lu\n", nesqp->hwqp.qp_id, jiffies);
+		  "%lu\n", nesqp->hwqp.qp_id, jiffies);
 
 	return;
 }
@@ -3418,16 +3621,14 @@
 		return;
 
 	cm_id = event->cm_node->cm_id;
-	if (!cm_id) {
+	if (!cm_id)
 		return;
-	}
 
 	nes_debug(NES_DBG_CM, "cm_node=%p, cm_id=%p\n", event->cm_node, cm_id);
 	nesqp = cm_id->provider_data;
 
-	if (!nesqp) {
+	if (!nesqp)
 		return;
-	}
 
 	/* notify OF layer about this connection error event */
 	/* cm_id->rem_ref(cm_id); */
@@ -3442,14 +3643,14 @@
 	cm_event.private_data_len = 0;
 
 	nes_debug(NES_DBG_CM, "call CM_EVENT REJECTED, local_addr=%08x, "
-		"remove_addr=%08x\n", cm_event.local_addr.sin_addr.s_addr,
-		cm_event.remote_addr.sin_addr.s_addr);
+		  "remove_addr=%08x\n", cm_event.local_addr.sin_addr.s_addr,
+		  cm_event.remote_addr.sin_addr.s_addr);
 
 	ret = cm_id->event_handler(cm_id, &cm_event);
 	nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
 	if (ret)
 		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
-			"ret=%d\n", __func__, __LINE__, ret);
+		       "ret=%d\n", __func__, __LINE__, ret);
 	cm_id->rem_ref(cm_id);
 
 	rem_ref_cm_node(event->cm_node->cm_core, event->cm_node);
@@ -3519,7 +3720,7 @@
  */
 static void cm_event_mpa_req(struct nes_cm_event *event)
 {
-	struct iw_cm_id   *cm_id;
+	struct iw_cm_id *cm_id;
 	struct iw_cm_event cm_event;
 	int ret;
 	struct nes_cm_node *cm_node;
@@ -3531,7 +3732,7 @@
 
 	atomic_inc(&cm_connect_reqs);
 	nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n",
-			cm_node, cm_id, jiffies);
+		  cm_node, cm_id, jiffies);
 
 	cm_event.event = IW_CM_EVENT_CONNECT_REQUEST;
 	cm_event.status = 0;
@@ -3545,19 +3746,21 @@
 	cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port);
 	cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr);
 	cm_event.private_data = cm_node->mpa_frame_buf;
-	cm_event.private_data_len  = (u8) cm_node->mpa_frame_size;
+	cm_event.private_data_len = (u8)cm_node->mpa_frame_size;
+	cm_event.ird = cm_node->ird_size;
+	cm_event.ord = cm_node->ord_size;
 
 	ret = cm_id->event_handler(cm_id, &cm_event);
 	if (ret)
 		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n",
-				__func__, __LINE__, ret);
+		       __func__, __LINE__, ret);
 	return;
 }
 
 
 static void cm_event_mpa_reject(struct nes_cm_event *event)
 {
-	struct iw_cm_id   *cm_id;
+	struct iw_cm_id *cm_id;
 	struct iw_cm_event cm_event;
 	struct nes_cm_node *cm_node;
 	int ret;
@@ -3569,7 +3772,7 @@
 
 	atomic_inc(&cm_connect_reqs);
 	nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n",
-			cm_node, cm_id, jiffies);
+		  cm_node, cm_id, jiffies);
 
 	cm_event.event = IW_CM_EVENT_CONNECT_REPLY;
 	cm_event.status = -ECONNREFUSED;
@@ -3584,17 +3787,17 @@
 	cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr);
 
 	cm_event.private_data = cm_node->mpa_frame_buf;
-	cm_event.private_data_len = (u8) cm_node->mpa_frame_size;
+	cm_event.private_data_len = (u8)cm_node->mpa_frame_size;
 
 	nes_debug(NES_DBG_CM, "call CM_EVENT_MPA_REJECTED, local_addr=%08x, "
-			"remove_addr=%08x\n",
-			cm_event.local_addr.sin_addr.s_addr,
-			cm_event.remote_addr.sin_addr.s_addr);
+		  "remove_addr=%08x\n",
+		  cm_event.local_addr.sin_addr.s_addr,
+		  cm_event.remote_addr.sin_addr.s_addr);
 
 	ret = cm_id->event_handler(cm_id, &cm_event);
 	if (ret)
 		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n",
-				__func__, __LINE__, ret);
+		       __func__, __LINE__, ret);
 
 	return;
 }
@@ -3613,7 +3816,7 @@
 	event->cm_info.cm_id->add_ref(event->cm_info.cm_id);
 	INIT_WORK(&event->event_work, nes_cm_event_handler);
 	nes_debug(NES_DBG_CM, "cm_node=%p queue_work, event=%p\n",
-		event->cm_node, event);
+		  event->cm_node, event);
 
 	queue_work(event->cm_node->cm_core->event_wq, &event->event_work);
 
@@ -3630,7 +3833,7 @@
 static void nes_cm_event_handler(struct work_struct *work)
 {
 	struct nes_cm_event *event = container_of(work, struct nes_cm_event,
-			event_work);
+						  event_work);
 	struct nes_cm_core *cm_core;
 
 	if ((!event) || (!event->cm_node) || (!event->cm_node->cm_core))
@@ -3638,29 +3841,29 @@
 
 	cm_core = event->cm_node->cm_core;
 	nes_debug(NES_DBG_CM, "event=%p, event->type=%u, events posted=%u\n",
-		event, event->type, atomic_read(&cm_core->events_posted));
+		  event, event->type, atomic_read(&cm_core->events_posted));
 
 	switch (event->type) {
 	case NES_CM_EVENT_MPA_REQ:
 		cm_event_mpa_req(event);
 		nes_debug(NES_DBG_CM, "cm_node=%p CM Event: MPA REQUEST\n",
-			event->cm_node);
+			  event->cm_node);
 		break;
 	case NES_CM_EVENT_RESET:
 		nes_debug(NES_DBG_CM, "cm_node = %p CM Event: RESET\n",
-			event->cm_node);
+			  event->cm_node);
 		cm_event_reset(event);
 		break;
 	case NES_CM_EVENT_CONNECTED:
 		if ((!event->cm_node->cm_id) ||
-			(event->cm_node->state != NES_CM_STATE_TSA))
+		    (event->cm_node->state != NES_CM_STATE_TSA))
 			break;
 		cm_event_connected(event);
 		nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n");
 		break;
 	case NES_CM_EVENT_MPA_REJECT:
 		if ((!event->cm_node->cm_id) ||
-				(event->cm_node->state == NES_CM_STATE_TSA))
+		    (event->cm_node->state == NES_CM_STATE_TSA))
 			break;
 		cm_event_mpa_reject(event);
 		nes_debug(NES_DBG_CM, "CM Event: REJECT\n");
@@ -3668,7 +3871,7 @@
 
 	case NES_CM_EVENT_ABORTED:
 		if ((!event->cm_node->cm_id) ||
-			(event->cm_node->state == NES_CM_STATE_TSA))
+		    (event->cm_node->state == NES_CM_STATE_TSA))
 			break;
 		cm_event_connect_error(event);
 		nes_debug(NES_DBG_CM, "CM Event: ABORTED\n");
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_cm.h linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_cm.h
--- linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_cm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_cm.h	2012-01-04 18:55:44.000000000 -0500
@@ -48,7 +48,16 @@
 #define IETF_MPA_KEY_SIZE 16
 #define IETF_MPA_VERSION  1
 #define IETF_MAX_PRIV_DATA_LEN 512
-#define IETF_MPA_FRAME_SIZE     20
+#define IETF_MPA_FRAME_SIZE    20
+#define IETF_RTR_MSG_SIZE      4
+#define IETF_MPA_V2_FLAG       0x10
+
+/* IETF RTR MSG Fields               */
+#define IETF_PEER_TO_PEER       0x8000
+#define IETF_FLPDU_ZERO_LEN     0x4000
+#define IETF_RDMA0_WRITE        0x8000
+#define IETF_RDMA0_READ         0x4000
+#define IETF_NO_IRD_ORD         0x3FFF
 
 enum ietf_mpa_flags {
 	IETF_MPA_FLAGS_MARKERS = 0x80,	/* receive Markers */
@@ -56,7 +65,7 @@
 	IETF_MPA_FLAGS_REJECT  = 0x20,	/* Reject */
 };
 
-struct ietf_mpa_frame {
+struct ietf_mpa_v1 {
 	u8 key[IETF_MPA_KEY_SIZE];
 	u8 flags;
 	u8 rev;
@@ -66,6 +75,20 @@
 
 #define ietf_mpa_req_resp_frame ietf_mpa_frame
 
+struct ietf_rtr_msg {
+	__be16 ctrl_ird;
+	__be16 ctrl_ord;
+};
+
+struct ietf_mpa_v2 {
+	u8 key[IETF_MPA_KEY_SIZE];
+	u8 flags;
+	u8 rev;
+	 __be16 priv_data_len;
+	struct ietf_rtr_msg rtr_msg;
+	u8 priv_data[0];
+};
+
 struct nes_v4_quad {
 	u32 rsvd0;
 	__le32 DstIpAdrIndex;	/* Only most significant 5 bits are valid */
@@ -171,8 +194,7 @@
 
 #define NES_CM_DEF_SEQ2      0x18ed5740
 #define NES_CM_DEF_LOCAL_ID2 0xb807
-#define	MAX_CM_BUFFER	(IETF_MPA_FRAME_SIZE + IETF_MAX_PRIV_DATA_LEN)
-
+#define	MAX_CM_BUFFER	(IETF_MPA_FRAME_SIZE + IETF_RTR_MSG_SIZE + IETF_MAX_PRIV_DATA_LEN)
 
 typedef u32 nes_addr_t;
 
@@ -204,6 +226,21 @@
 	NES_CM_STATE_CLOSED
 };
 
+enum mpa_frame_version {
+	IETF_MPA_V1 = 1,
+	IETF_MPA_V2 = 2
+};
+
+enum mpa_frame_key {
+	MPA_KEY_REQUEST,
+	MPA_KEY_REPLY
+};
+
+enum send_rdma0 {
+	SEND_RDMA_READ_ZERO = 1,
+	SEND_RDMA_WRITE_ZERO = 2
+};
+
 enum nes_tcpip_pkt_type {
 	NES_PKT_TYPE_UNKNOWN,
 	NES_PKT_TYPE_SYN,
@@ -245,9 +282,9 @@
 
 
 enum nes_cm_listener_state {
-	NES_CM_LISTENER_PASSIVE_STATE=1,
-	NES_CM_LISTENER_ACTIVE_STATE=2,
-	NES_CM_LISTENER_EITHER_STATE=3
+	NES_CM_LISTENER_PASSIVE_STATE = 1,
+	NES_CM_LISTENER_ACTIVE_STATE = 2,
+	NES_CM_LISTENER_EITHER_STATE = 3
 };
 
 struct nes_cm_listener {
@@ -283,16 +320,20 @@
 
 	struct nes_cm_node        *loopbackpartner;
 
-	struct nes_timer_entry	*send_entry;
-
+	struct nes_timer_entry	  *send_entry;
+	struct nes_timer_entry    *recv_entry;
 	spinlock_t                retrans_list_lock;
-	struct nes_timer_entry  *recv_entry;
+	enum send_rdma0           send_rdma0_op;
 
-	int                       send_write0;
 	union {
-		struct ietf_mpa_frame mpa_frame;
-		u8                    mpa_frame_buf[MAX_CM_BUFFER];
+		struct ietf_mpa_v1 mpa_frame;
+		struct ietf_mpa_v2 mpa_v2_frame;
+		u8                 mpa_frame_buf[MAX_CM_BUFFER];
 	};
+	enum mpa_frame_version    mpa_frame_rev;
+	u16			  ird_size;
+	u16                       ord_size;
+
 	u16                       mpa_frame_size;
 	struct iw_cm_id           *cm_id;
 	struct list_head          list;
@@ -399,10 +440,8 @@
 			struct nes_vnic *, u16, void *,
 			struct nes_cm_info *);
 	int (*close)(struct nes_cm_core *, struct nes_cm_node *);
-	int (*accept)(struct nes_cm_core *, struct ietf_mpa_frame *,
-			struct nes_cm_node *);
-	int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *,
-			struct nes_cm_node *);
+	int (*accept)(struct nes_cm_core *, struct nes_cm_node *);
+	int (*reject)(struct nes_cm_core *, struct nes_cm_node *);
 	int (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *,
 			struct sk_buff *);
 	int (*destroy_cm_core)(struct nes_cm_core *);
@@ -422,5 +461,7 @@
 int nes_cm_recv(struct sk_buff *, struct net_device *);
 int nes_cm_start(void);
 int nes_cm_stop(void);
+int nes_add_ref_cm_node(struct nes_cm_node *cm_node);
+int nes_rem_ref_cm_node(struct nes_cm_node *cm_node);
 
 #endif			/* NES_CM_H */
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes.h linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes.h
--- linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes.h	2012-01-04 18:55:44.000000000 -0500
@@ -102,6 +102,7 @@
 #define NES_DRV_OPT_NO_INLINE_DATA       0x00000080
 #define NES_DRV_OPT_DISABLE_INT_MOD      0x00000100
 #define NES_DRV_OPT_DISABLE_VIRT_WQ      0x00000200
+#define NES_DRV_OPT_ENABLE_PAU           0x00000400
 
 #define NES_AEQ_EVENT_TIMEOUT         2500
 #define NES_DISCONNECT_EVENT_TIMEOUT  2000
@@ -128,6 +129,7 @@
 #define NES_DBG_IW_RX       0x00020000
 #define NES_DBG_IW_TX       0x00040000
 #define NES_DBG_SHUTDOWN    0x00080000
+#define NES_DBG_PAU         0x00100000
 #define NES_DBG_RSVD1       0x10000000
 #define NES_DBG_RSVD2       0x20000000
 #define NES_DBG_RSVD3       0x40000000
@@ -162,6 +164,7 @@
 #include "nes_context.h"
 #include "nes_user.h"
 #include "nes_cm.h"
+#include "nes_mgt.h"
 
 extern int max_mtu;
 #define max_frame_len (max_mtu+ETH_HLEN)
@@ -202,6 +205,8 @@
 extern atomic_t cm_nodes_destroyed;
 extern atomic_t cm_accel_dropped_pkts;
 extern atomic_t cm_resets_recvd;
+extern atomic_t pau_qps_created;
+extern atomic_t pau_qps_destroyed;
 
 extern u32 int_mod_timer_init;
 extern u32 int_mod_cq_depth_256;
@@ -273,6 +278,14 @@
 	u8                     link_recheck;
 };
 
+/* Receive skb private area - must fit in skb->cb area */
+struct nes_rskb_cb {
+	u64                    busaddr;
+	u32                    maplen;
+	u32                    seqnum;
+	u8                     *data_start;
+	struct nes_qp          *nesqp;
+};
 
 static inline __le32 get_crc_value(struct nes_v4_quad *nes_quad)
 {
@@ -305,8 +318,8 @@
 static inline void
 nes_fill_init_cqp_wqe(struct nes_hw_cqp_wqe *cqp_wqe, struct nes_device *nesdev)
 {
-	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_CTX_LOW_IDX,
-			(u64)((unsigned long) &nesdev->cqp));
+	cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]       = 0;
+	cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX]      = 0;
 	cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX]   = 0;
 	cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]  = 0;
 	cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] = 0;
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_hw.c linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_hw.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_hw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_hw.c	2012-01-04 18:55:44.000000000 -0500
@@ -110,6 +110,14 @@
 };
 #endif
 
+static inline void print_ip(struct nes_cm_node *cm_node)
+{
+	unsigned char *rem_addr;
+	if (cm_node) {
+		rem_addr = (unsigned char *)&cm_node->rem_addr;
+		printk(KERN_ERR PFX "Remote IP addr: %pI4\n", rem_addr);
+	}
+}
 
 /**
  * nes_nic_init_timer_defaults
@@ -1555,6 +1563,7 @@
 	struct nes_hw_nic_rq_wqe *nic_rqe;
 	struct nes_hw_nic *nesnic;
 	struct nes_device *nesdev;
+	struct nes_rskb_cb *cb;
 	u32 rx_wqes_posted = 0;
 
 	nesnic = &nesvnic->nic;
@@ -1580,6 +1589,9 @@
 
 			bus_address = pci_map_single(nesdev->pcidev,
 					skb->data, nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+			cb = (struct nes_rskb_cb *)&skb->cb[0];
+			cb->busaddr = bus_address;
+			cb->maplen = nesvnic->max_frame_size;
 
 			nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_head];
 			nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] =
@@ -1669,6 +1681,7 @@
 	u32 cqp_head;
 	u32 counter;
 	u32 wqe_count;
+	struct nes_rskb_cb *cb;
 	u8 jumbomode=0;
 
 	/* Allocate fragment, SQ, RQ, and CQ; Reuse CEQ based on the PCI function */
@@ -1845,6 +1858,9 @@
 
 		pmem = pci_map_single(nesdev->pcidev, skb->data,
 				nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+		cb = (struct nes_rskb_cb *)&skb->cb[0];
+		cb->busaddr = pmem;
+		cb->maplen = nesvnic->max_frame_size;
 
 		nic_rqe = &nesvnic->nic.rq_vbase[counter];
 		nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32(nesvnic->max_frame_size);
@@ -1873,6 +1889,13 @@
 			jumbomode = 1;
 		nes_nic_init_timer_defaults(nesdev, jumbomode);
 	}
+	if ((nesdev->nesadapter->allow_unaligned_fpdus) &&
+		(nes_init_mgt_qp(nesdev, netdev, nesvnic))) {
+			nes_debug(NES_DBG_INIT, "%s: Out of memory for pau nic\n", netdev->name);
+			nes_destroy_nic_qp(nesvnic);
+		return -ENOMEM;
+	}
+
 	nesvnic->lro_mgr.max_aggr       = nes_lro_max_aggr;
 	nesvnic->lro_mgr.max_desc       = NES_MAX_LRO_DESCRIPTORS;
 	nesvnic->lro_mgr.lro_arr        = nesvnic->lro_desc;
@@ -1895,28 +1918,29 @@
 	struct nes_device *nesdev = nesvnic->nesdev;
 	struct nes_hw_cqp_wqe *cqp_wqe;
 	struct nes_hw_nic_sq_wqe *nic_sqe;
-	struct nes_hw_nic_rq_wqe *nic_rqe;
 	__le16 *wqe_fragment_length;
 	u16  wqe_fragment_index;
-	u64 wqe_frag;
 	u32 cqp_head;
 	u32 wqm_cfg0;
 	unsigned long flags;
+	struct sk_buff *rx_skb;
+	struct nes_rskb_cb *cb;
 	int ret;
 
+	if (nesdev->nesadapter->allow_unaligned_fpdus)
+		nes_destroy_mgt(nesvnic);
+
 	/* clear wqe stall before destroying NIC QP */
 	wqm_cfg0 = nes_read_indexed(nesdev, NES_IDX_WQM_CONFIG0);
 	nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG0, wqm_cfg0 & 0xFFFF7FFF);
 
 	/* Free remaining NIC receive buffers */
 	while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {
-		nic_rqe   = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
-		wqe_frag  = (u64)le32_to_cpu(
-			nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
-		wqe_frag |= ((u64)le32_to_cpu(
-			nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX]))<<32;
-		pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag,
-				nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+		rx_skb = nesvnic->nic.rx_skb[nesvnic->nic.rq_tail];
+		cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
+		pci_unmap_single(nesdev->pcidev, cb->busaddr, cb->maplen,
+			PCI_DMA_FROMDEVICE);
+
 		dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]);
 		nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1);
 	}
@@ -2775,6 +2799,7 @@
 	struct nes_hw_nic_sq_wqe *nic_sqe;
 	struct sk_buff *skb;
 	struct sk_buff *rx_skb;
+	struct nes_rskb_cb *cb;
 	__le16 *wqe_fragment_length;
 	u32 head;
 	u32 cq_size;
@@ -2859,6 +2884,8 @@
 				bus_address += ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;
 				pci_unmap_single(nesdev->pcidev, bus_address,
 						nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+				cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
+				cb->busaddr = 0;
 				/* rx_skb->tail = rx_skb->data + rx_pkt_size; */
 				/* rx_skb->len = rx_pkt_size; */
 				rx_skb->len = 0;  /* TODO: see if this is necessary */
@@ -2983,6 +3010,7 @@
 }
 
 
+
 /**
  * nes_cqp_ce_handler
  */
@@ -2997,6 +3025,8 @@
 	u32 cq_size;
 	u32 cqe_count=0;
 	u32 error_code;
+	u32 opcode;
+	u32 ctx_index;
 	/* u32 counter; */
 
 	head = cq->cq_head;
@@ -3007,12 +3037,9 @@
 		/* nes_debug(NES_DBG_CQP, "head=%u cqe_words=%08X\n", head,
 			  le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])); */
 
-		if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {
-			u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
-					cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
-					((u64)(le32_to_cpu(cq->cq_vbase[head].
-					cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
-			cqp = *((struct nes_hw_cqp **)&u64temp);
+		opcode = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]);
+		if (opcode & NES_CQE_VALID) {
+			cqp = &nesdev->cqp;
 
 			error_code = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]);
 			if (error_code) {
@@ -3021,15 +3048,14 @@
 						le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])&0x3f,
 						(u16)(error_code >> 16),
 						(u16)error_code);
-				nes_debug(NES_DBG_CQP, "cqp: qp_id=%u, sq_head=%u, sq_tail=%u\n",
-						cqp->qp_id, cqp->sq_head, cqp->sq_tail);
 			}
 
-			u64temp = (((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
-					wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) |
-					((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
-					wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX])));
-			cqp_request = *((struct nes_cqp_request **)&u64temp);
+			u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
+					cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
+					((u64)(le32_to_cpu(cq->cq_vbase[head].
+					cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
+
+			cqp_request = (struct nes_cqp_request *)(unsigned long)u64temp;
 			if (cqp_request) {
 				if (cqp_request->waiting) {
 					/* nes_debug(NES_DBG_CQP, "%s: Waking up requestor\n"); */
@@ -3075,9 +3101,15 @@
 		cqp_wqe = &nesdev->cqp.sq_vbase[head];
 		memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
 		barrier();
-		cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] =
+
+		opcode = cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX];
+		if ((opcode & NES_CQP_OPCODE_MASK) == NES_CQP_DOWNLOAD_SEGMENT)
+			ctx_index = NES_CQP_WQE_DL_COMP_CTX_LOW_IDX;
+		else
+			ctx_index = NES_CQP_WQE_COMP_CTX_LOW_IDX;
+		cqp_wqe->wqe_words[ctx_index] =
 			cpu_to_le32((u32)((unsigned long)cqp_request));
-		cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] =
+		cqp_wqe->wqe_words[ctx_index + 1] =
 			cpu_to_le32((u32)(upper_32_bits((unsigned long)cqp_request)));
 		nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) put on CQPs SQ wqe%u.\n",
 				cqp_request, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, head);
@@ -3093,7 +3125,6 @@
 	nes_read32(nesdev->regs+NES_CQE_ALLOC);
 }
 
-
 static u8 *locate_mpa(u8 *pkt, u32 aeq_info)
 {
 	if (aeq_info & NES_AEQE_Q2_DATA_ETHERNET) {
@@ -3553,9 +3584,9 @@
 
 	aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]);
 	if (aeq_info & NES_AEQE_QP) {
-		if ((!nes_is_resource_allocated(nesadapter, nesadapter->allocated_qps,
-				aeqe_cq_id)) ||
-				(atomic_read(&nesqp->close_timer_started)))
+		if (!nes_is_resource_allocated(nesadapter,
+				nesadapter->allocated_qps,
+				aeqe_cq_id))
 			return;
 	}
 
@@ -3566,8 +3597,7 @@
 
 			if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
 				if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) &&
-					(nesqp->ibqp_state == IB_QPS_RTS) &&
-					((nesadapter->eeprom_version >> 16) != NES_A0)) {
+					(nesqp->ibqp_state == IB_QPS_RTS)) {
 					spin_lock_irqsave(&nesqp->lock, flags);
 					nesqp->hw_iwarp_state = iwarp_state;
 					nesqp->hw_tcp_state = tcp_state;
@@ -3594,9 +3624,10 @@
 				return;
 			}
 			spin_lock_irqsave(&nesqp->lock, flags);
-			nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;
+			nesqp->hw_iwarp_state = iwarp_state;
+			nesqp->hw_tcp_state = tcp_state;
+			nesqp->last_aeq = async_event_id;
 			spin_unlock_irqrestore(&nesqp->lock, flags);
-			nes_hw_modify_qp(nesdev, nesqp, NES_CQP_QP_IWARP_STATE_CLOSING, 0, 0);
 			nes_cm_disconn(nesqp);
 			break;
 
@@ -3694,7 +3725,9 @@
 		case NES_AEQE_AEID_ROE_INVALID_RDMA_WRITE_OR_READ_RESP:
 			printk(KERN_ERR PFX "QP[%u] async_event_id=0x%04X IB_EVENT_QP_FATAL\n",
 					nesqp->hwqp.qp_id, async_event_id);
-			nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
+			print_ip(nesqp->cm_node);
+			if (!atomic_read(&nesqp->close_timer_started))
+				nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
 			break;
 
 		case NES_AEQE_AEID_CQ_OPERATION_ERROR:
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_hw.h linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_hw.h
--- linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_hw.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_hw.h	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,11 @@
 #define NES_MULTICAST_PF_MAX 8
 #define NES_A0 3
 
+#define NES_ENABLE_PAU 0x07000001
+#define NES_DISABLE_PAU 0x07000000
+#define NES_PAU_COUNTER 10
+#define NES_CQP_OPCODE_MASK 0x3f
+
 enum pci_regs {
 	NES_INT_STAT = 0x0000,
 	NES_INT_MASK = 0x0004,
@@ -73,8 +78,10 @@
 	NES_IDX_QP_CONTROL = 0x0040,
 	NES_IDX_FLM_CONTROL = 0x0080,
 	NES_IDX_INT_CPU_STATUS = 0x00a0,
+	NES_IDX_GPR_TRIGGER = 0x00bc,
 	NES_IDX_GPIO_CONTROL = 0x00f0,
 	NES_IDX_GPIO_DATA = 0x00f4,
+	NES_IDX_GPR2 = 0x010c,
 	NES_IDX_TCP_CONFIG0 = 0x01e4,
 	NES_IDX_TCP_TIMER_CONFIG = 0x01ec,
 	NES_IDX_TCP_NOW = 0x01f0,
@@ -202,6 +209,7 @@
 	NES_CQP_REGISTER_SHARED_STAG = 0x0c,
 	NES_CQP_DEALLOCATE_STAG = 0x0d,
 	NES_CQP_MANAGE_ARP_CACHE = 0x0f,
+	NES_CQP_DOWNLOAD_SEGMENT = 0x10,
 	NES_CQP_SUSPEND_QPS = 0x11,
 	NES_CQP_UPLOAD_CONTEXT = 0x13,
 	NES_CQP_CREATE_CEQ = 0x16,
@@ -210,7 +218,8 @@
 	NES_CQP_DESTROY_AEQ = 0x1b,
 	NES_CQP_LMI_ACCESS = 0x20,
 	NES_CQP_FLUSH_WQES = 0x22,
-	NES_CQP_MANAGE_APBVT = 0x23
+	NES_CQP_MANAGE_APBVT = 0x23,
+	NES_CQP_MANAGE_QUAD_HASH = 0x25
 };
 
 enum nes_cqp_wqe_word_idx {
@@ -222,6 +231,14 @@
 	NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX = 5,
 };
 
+enum nes_cqp_wqe_word_download_idx { /* format differs from other cqp ops */
+	NES_CQP_WQE_DL_OPCODE_IDX = 0,
+	NES_CQP_WQE_DL_COMP_CTX_LOW_IDX = 1,
+	NES_CQP_WQE_DL_COMP_CTX_HIGH_IDX = 2,
+	NES_CQP_WQE_DL_LENGTH_0_TOTAL_IDX = 3
+	/* For index values 4-15 use NES_NIC_SQ_WQE_ values */
+};
+
 enum nes_cqp_cq_wqeword_idx {
 	NES_CQP_CQ_WQE_PBL_LOW_IDX = 6,
 	NES_CQP_CQ_WQE_PBL_HIGH_IDX = 7,
@@ -242,6 +259,7 @@
 	NES_CQP_STAG_WQE_PBL_LEN_IDX = 14
 };
 
+#define NES_CQP_OP_LOGICAL_PORT_SHIFT 26
 #define NES_CQP_OP_IWARP_STATE_SHIFT 28
 #define NES_CQP_OP_TERMLEN_SHIFT     28
 
@@ -599,6 +617,7 @@
 
 enum nes_nic_cqe_word_idx {
 	NES_NIC_CQE_ACCQP_ID_IDX = 0,
+	NES_NIC_CQE_HASH_RCVNXT = 1,
 	NES_NIC_CQE_TAG_PKT_TYPE_IDX = 2,
 	NES_NIC_CQE_MISC_IDX = 3,
 };
@@ -1005,6 +1024,11 @@
 #define NES_NIC_CQ_DOWNWARD_TREND   16
 #define NES_PFT_SIZE		    48
 
+#define NES_MGT_WQ_COUNT 32
+#define NES_MGT_CTX_SIZE ((NES_NIC_CTX_RQ_SIZE_32) | (NES_NIC_CTX_SQ_SIZE_32))
+#define NES_MGT_QP_OFFSET 36
+#define NES_MGT_QP_COUNT 4
+
 struct nes_hw_tune_timer {
     /* u16 cq_count; */
     u16 threshold_low;
@@ -1118,6 +1142,7 @@
 	u32 et_rate_sample_interval;
 	u32 timer_int_limit;
 	u32 wqm_quanta;
+	u8 allow_unaligned_fpdus;
 
 	/* Adapter base MAC address */
 	u32 mac_addr_low;
@@ -1251,6 +1276,14 @@
 	enum ib_event_type delayed_event;
 	enum ib_event_type last_dispatched_event;
 	spinlock_t port_ibevent_lock;
+	u32 mgt_mem_size;
+	void *mgt_vbase;
+	dma_addr_t mgt_pbase;
+	struct nes_vnic_mgt *mgtvnic[NES_MGT_QP_COUNT];
+	struct task_struct *mgt_thread;
+	wait_queue_head_t mgt_wait_queue;
+	struct sk_buff_head mgt_skb_list;
+
 };
 
 struct nes_ib_device {
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_mgt.c linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_mgt.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_mgt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_mgt.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1162 @@
+/*
+ * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/kthread.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <net/tcp.h>
+#include "nes.h"
+#include "nes_mgt.h"
+
+atomic_t pau_qps_created;
+atomic_t pau_qps_destroyed;
+
+static void nes_replenish_mgt_rq(struct nes_vnic_mgt *mgtvnic)
+{
+	unsigned long flags;
+	dma_addr_t bus_address;
+	struct sk_buff *skb;
+	struct nes_hw_nic_rq_wqe *nic_rqe;
+	struct nes_hw_mgt *nesmgt;
+	struct nes_device *nesdev;
+	struct nes_rskb_cb *cb;
+	u32 rx_wqes_posted = 0;
+
+	nesmgt = &mgtvnic->mgt;
+	nesdev = mgtvnic->nesvnic->nesdev;
+	spin_lock_irqsave(&nesmgt->rq_lock, flags);
+	if (nesmgt->replenishing_rq != 0) {
+		if (((nesmgt->rq_size - 1) == atomic_read(&mgtvnic->rx_skbs_needed)) &&
+		    (atomic_read(&mgtvnic->rx_skb_timer_running) == 0)) {
+			atomic_set(&mgtvnic->rx_skb_timer_running, 1);
+			spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+			mgtvnic->rq_wqes_timer.expires = jiffies + (HZ / 2);      /* 1/2 second */
+			add_timer(&mgtvnic->rq_wqes_timer);
+		} else {
+			spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+		}
+		return;
+	}
+	nesmgt->replenishing_rq = 1;
+	spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+	do {
+		skb = dev_alloc_skb(mgtvnic->nesvnic->max_frame_size);
+		if (skb) {
+			skb->dev = mgtvnic->nesvnic->netdev;
+
+			bus_address = pci_map_single(nesdev->pcidev,
+						     skb->data, mgtvnic->nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+			cb = (struct nes_rskb_cb *)&skb->cb[0];
+			cb->busaddr = bus_address;
+			cb->maplen = mgtvnic->nesvnic->max_frame_size;
+
+			nic_rqe = &nesmgt->rq_vbase[mgtvnic->mgt.rq_head];
+			nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] =
+				cpu_to_le32(mgtvnic->nesvnic->max_frame_size);
+			nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
+			nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] =
+				cpu_to_le32((u32)bus_address);
+			nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] =
+				cpu_to_le32((u32)((u64)bus_address >> 32));
+			nesmgt->rx_skb[nesmgt->rq_head] = skb;
+			nesmgt->rq_head++;
+			nesmgt->rq_head &= nesmgt->rq_size - 1;
+			atomic_dec(&mgtvnic->rx_skbs_needed);
+			barrier();
+			if (++rx_wqes_posted == 255) {
+				nes_write32(nesdev->regs + NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesmgt->qp_id);
+				rx_wqes_posted = 0;
+			}
+		} else {
+			spin_lock_irqsave(&nesmgt->rq_lock, flags);
+			if (((nesmgt->rq_size - 1) == atomic_read(&mgtvnic->rx_skbs_needed)) &&
+			    (atomic_read(&mgtvnic->rx_skb_timer_running) == 0)) {
+				atomic_set(&mgtvnic->rx_skb_timer_running, 1);
+				spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+				mgtvnic->rq_wqes_timer.expires = jiffies + (HZ / 2);      /* 1/2 second */
+				add_timer(&mgtvnic->rq_wqes_timer);
+			} else {
+				spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+			}
+			break;
+		}
+	} while (atomic_read(&mgtvnic->rx_skbs_needed));
+	barrier();
+	if (rx_wqes_posted)
+		nes_write32(nesdev->regs + NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesmgt->qp_id);
+	nesmgt->replenishing_rq = 0;
+}
+
+/**
+ * nes_mgt_rq_wqes_timeout
+ */
+static void nes_mgt_rq_wqes_timeout(unsigned long parm)
+{
+	struct nes_vnic_mgt *mgtvnic = (struct nes_vnic_mgt *)parm;
+
+	atomic_set(&mgtvnic->rx_skb_timer_running, 0);
+	if (atomic_read(&mgtvnic->rx_skbs_needed))
+		nes_replenish_mgt_rq(mgtvnic);
+}
+
+/**
+ * nes_mgt_free_skb - unmap and free skb
+ */
+static void nes_mgt_free_skb(struct nes_device *nesdev, struct sk_buff *skb, u32 dir)
+{
+	struct nes_rskb_cb *cb;
+
+	cb = (struct nes_rskb_cb *)&skb->cb[0];
+	pci_unmap_single(nesdev->pcidev, cb->busaddr, cb->maplen, dir);
+	cb->busaddr = 0;
+	dev_kfree_skb_any(skb);
+}
+
+/**
+ * nes_download_callback - handle download completions
+ */
+static void nes_download_callback(struct nes_device *nesdev, struct nes_cqp_request *cqp_request)
+{
+	struct pau_fpdu_info *fpdu_info = cqp_request->cqp_callback_pointer;
+	struct nes_qp *nesqp = fpdu_info->nesqp;
+	struct sk_buff *skb;
+	int i;
+
+	for (i = 0; i < fpdu_info->frag_cnt; i++) {
+		skb = fpdu_info->frags[i].skb;
+		if (fpdu_info->frags[i].cmplt) {
+			nes_mgt_free_skb(nesdev, skb, PCI_DMA_TODEVICE);
+			nes_rem_ref_cm_node(nesqp->cm_node);
+		}
+	}
+
+	if (fpdu_info->hdr_vbase)
+		pci_free_consistent(nesdev->pcidev, fpdu_info->hdr_len,
+				    fpdu_info->hdr_vbase, fpdu_info->hdr_pbase);
+	kfree(fpdu_info);
+}
+
+/**
+ * nes_get_seq - Get the seq, ack_seq and window from the packet
+ */
+static u32 nes_get_seq(struct sk_buff *skb, u32 *ack, u16 *wnd, u32 *fin_rcvd, u32 *rst_rcvd)
+{
+	struct nes_rskb_cb *cb = (struct nes_rskb_cb *)&skb->cb[0];
+	struct iphdr *iph = (struct iphdr *)(cb->data_start + ETH_HLEN);
+	struct tcphdr *tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+
+	*ack = be32_to_cpu(tcph->ack_seq);
+	*wnd = be16_to_cpu(tcph->window);
+	*fin_rcvd = tcph->fin;
+	*rst_rcvd = tcph->rst;
+	return be32_to_cpu(tcph->seq);
+}
+
+/**
+ * nes_get_next_skb - Get the next skb based on where current skb is in the queue
+ */
+static struct sk_buff *nes_get_next_skb(struct nes_device *nesdev, struct nes_qp *nesqp,
+					struct sk_buff *skb, u32 nextseq, u32 *ack,
+					u16 *wnd, u32 *fin_rcvd, u32 *rst_rcvd)
+{
+	u32 seq;
+	bool processacks;
+	struct sk_buff *old_skb;
+
+	if (skb) {
+		/* Continue processing fpdu */
+		if (skb->next == (struct sk_buff *)&nesqp->pau_list)
+			goto out;
+		skb = skb->next;
+		processacks = false;
+	} else {
+		/* Starting a new one */
+		if (skb_queue_empty(&nesqp->pau_list))
+			goto out;
+		skb = skb_peek(&nesqp->pau_list);
+		processacks = true;
+	}
+
+	while (1) {
+		seq = nes_get_seq(skb, ack, wnd, fin_rcvd, rst_rcvd);
+		if (seq == nextseq) {
+			if (skb->len || processacks)
+				break;
+		} else if (after(seq, nextseq)) {
+			goto out;
+		}
+
+		if (skb->next == (struct sk_buff *)&nesqp->pau_list)
+			goto out;
+
+		old_skb = skb;
+		skb = skb->next;
+		skb_unlink(old_skb, &nesqp->pau_list);
+		nes_mgt_free_skb(nesdev, old_skb, PCI_DMA_TODEVICE);
+		nes_rem_ref_cm_node(nesqp->cm_node);
+	}
+	return skb;
+
+out:
+	return NULL;
+}
+
+/**
+ * get_fpdu_info - Find the next complete fpdu and return its fragments.
+ */
+static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
+			 struct pau_fpdu_info **pau_fpdu_info)
+{
+	struct sk_buff *skb;
+	struct iphdr *iph;
+	struct tcphdr *tcph;
+	struct nes_rskb_cb *cb;
+	struct pau_fpdu_info *fpdu_info = NULL;
+	struct pau_fpdu_frag frags[MAX_FPDU_FRAGS];
+	unsigned long flags;
+	u32 fpdu_len = 0;
+	u32 tmp_len;
+	int frag_cnt = 0;
+	u32 tot_len;
+	u32 frag_tot;
+	u32 ack;
+	u32 fin_rcvd;
+	u32 rst_rcvd;
+	u16 wnd;
+	int i;
+	int rc = 0;
+
+	*pau_fpdu_info = NULL;
+
+	spin_lock_irqsave(&nesqp->pau_lock, flags);
+	skb = nes_get_next_skb(nesdev, nesqp, NULL, nesqp->pau_rcv_nxt, &ack, &wnd, &fin_rcvd, &rst_rcvd);
+	if (!skb) {
+		spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+		goto out;
+	}
+	cb = (struct nes_rskb_cb *)&skb->cb[0];
+	if (skb->len) {
+		fpdu_len = be16_to_cpu(*(__be16 *) skb->data) + MPA_FRAMING;
+		fpdu_len = (fpdu_len + 3) & 0xfffffffc;
+		tmp_len = fpdu_len;
+
+		/* See if we have all of the fpdu */
+		frag_tot = 0;
+		memset(&frags, 0, sizeof frags);
+		for (i = 0; i < MAX_FPDU_FRAGS; i++) {
+			frags[i].physaddr = cb->busaddr;
+			frags[i].physaddr += skb->data - cb->data_start;
+			frags[i].frag_len = min(tmp_len, skb->len);
+			frags[i].skb = skb;
+			frags[i].cmplt = (skb->len == frags[i].frag_len);
+			frag_tot += frags[i].frag_len;
+			frag_cnt++;
+
+			tmp_len -= frags[i].frag_len;
+			if (tmp_len == 0)
+				break;
+
+			skb = nes_get_next_skb(nesdev, nesqp, skb,
+					       nesqp->pau_rcv_nxt + frag_tot, &ack, &wnd, &fin_rcvd, &rst_rcvd);
+			if (!skb) {
+				spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+				goto out;
+			} else if (rst_rcvd) {
+				/* rst received in the middle of fpdu */
+				for (; i >= 0; i--) {
+					skb_unlink(frags[i].skb, &nesqp->pau_list);
+					nes_mgt_free_skb(nesdev, frags[i].skb, PCI_DMA_TODEVICE);
+				}
+				cb = (struct nes_rskb_cb *)&skb->cb[0];
+				frags[0].physaddr = cb->busaddr;
+				frags[0].physaddr += skb->data - cb->data_start;
+				frags[0].frag_len = skb->len;
+				frags[0].skb = skb;
+				frags[0].cmplt = true;
+				frag_cnt = 1;
+				break;
+			}
+
+			cb = (struct nes_rskb_cb *)&skb->cb[0];
+		}
+	} else {
+		/* no data */
+		frags[0].physaddr = cb->busaddr;
+		frags[0].frag_len = 0;
+		frags[0].skb = skb;
+		frags[0].cmplt = true;
+		frag_cnt = 1;
+	}
+
+	spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+
+	/* Found one */
+	fpdu_info = kzalloc(sizeof(*fpdu_info), GFP_ATOMIC);
+	if (fpdu_info == NULL) {
+		nes_debug(NES_DBG_PAU, "Failed to alloc a fpdu_info.\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	fpdu_info->cqp_request = nes_get_cqp_request(nesdev);
+	if (fpdu_info->cqp_request == NULL) {
+		nes_debug(NES_DBG_PAU, "Failed to get a cqp_request.\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	cb = (struct nes_rskb_cb *)&frags[0].skb->cb[0];
+	iph = (struct iphdr *)(cb->data_start + ETH_HLEN);
+	tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+	fpdu_info->hdr_len = (((unsigned char *)tcph) + 4 * (tcph->doff)) - cb->data_start;
+	fpdu_info->data_len = fpdu_len;
+	tot_len = fpdu_info->hdr_len + fpdu_len - ETH_HLEN;
+
+	if (frags[0].cmplt) {
+		fpdu_info->hdr_pbase = cb->busaddr;
+		fpdu_info->hdr_vbase = NULL;
+	} else {
+		fpdu_info->hdr_vbase = pci_alloc_consistent(nesdev->pcidev,
+							    fpdu_info->hdr_len, &fpdu_info->hdr_pbase);
+		if (!fpdu_info->hdr_vbase) {
+			nes_debug(NES_DBG_PAU, "Unable to allocate memory for pau first frag\n");
+			rc = -ENOMEM;
+			goto out;
+		}
+
+		/* Copy hdrs, adjusting len and seqnum */
+		memcpy(fpdu_info->hdr_vbase, cb->data_start, fpdu_info->hdr_len);
+		iph = (struct iphdr *)(fpdu_info->hdr_vbase + ETH_HLEN);
+		tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+	}
+
+	iph->tot_len = cpu_to_be16(tot_len);
+	iph->saddr = cpu_to_be32(0x7f000001);
+
+	tcph->seq = cpu_to_be32(nesqp->pau_rcv_nxt);
+	tcph->ack_seq = cpu_to_be32(ack);
+	tcph->window = cpu_to_be16(wnd);
+
+	nesqp->pau_rcv_nxt += fpdu_len + fin_rcvd;
+
+	memcpy(fpdu_info->frags, frags, sizeof(fpdu_info->frags));
+	fpdu_info->frag_cnt = frag_cnt;
+	fpdu_info->nesqp = nesqp;
+	*pau_fpdu_info = fpdu_info;
+
+	/* Update skb's for next pass */
+	for (i = 0; i < frag_cnt; i++) {
+		cb = (struct nes_rskb_cb *)&frags[i].skb->cb[0];
+		skb_pull(frags[i].skb, frags[i].frag_len);
+
+		if (frags[i].skb->len == 0) {
+			/* Pull skb off the list - it will be freed in the callback */
+			spin_lock_irqsave(&nesqp->pau_lock, flags);
+			skb_unlink(frags[i].skb, &nesqp->pau_list);
+			spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+		} else {
+			/* Last skb still has data so update the seq */
+			iph = (struct iphdr *)(cb->data_start + ETH_HLEN);
+			tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+			tcph->seq = cpu_to_be32(nesqp->pau_rcv_nxt);
+		}
+	}
+
+out:
+	if (rc) {
+		if (fpdu_info) {
+			if (fpdu_info->cqp_request)
+				nes_put_cqp_request(nesdev, fpdu_info->cqp_request);
+			kfree(fpdu_info);
+		}
+	}
+	return rc;
+}
+
+/**
+ * forward_fpdu - send complete fpdus, one at a time
+ */
+static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+	struct nes_device *nesdev = nesvnic->nesdev;
+	struct pau_fpdu_info *fpdu_info;
+	struct nes_hw_cqp_wqe *cqp_wqe;
+	struct nes_cqp_request *cqp_request;
+	u64 u64tmp;
+	u32 u32tmp;
+	int rc;
+
+	while (1) {
+		rc = get_fpdu_info(nesdev, nesqp, &fpdu_info);
+		if (fpdu_info == NULL)
+			return rc;
+
+		cqp_request = fpdu_info->cqp_request;
+		cqp_wqe = &cqp_request->cqp_wqe;
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_DL_OPCODE_IDX,
+				    NES_CQP_DOWNLOAD_SEGMENT |
+				    (((u32)nesvnic->logical_port) << NES_CQP_OP_LOGICAL_PORT_SHIFT));
+
+		u32tmp = fpdu_info->hdr_len << 16;
+		u32tmp |= fpdu_info->hdr_len + (u32)fpdu_info->data_len;
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_DL_LENGTH_0_TOTAL_IDX,
+				    u32tmp);
+
+		u32tmp = (fpdu_info->frags[1].frag_len << 16) | fpdu_info->frags[0].frag_len;
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_LENGTH_2_1_IDX,
+				    u32tmp);
+
+		u32tmp = (fpdu_info->frags[3].frag_len << 16) | fpdu_info->frags[2].frag_len;
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_LENGTH_4_3_IDX,
+				    u32tmp);
+
+		u64tmp = (u64)fpdu_info->hdr_pbase;
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX,
+				    lower_32_bits(u64tmp));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_HIGH_IDX,
+				    upper_32_bits(u64tmp >> 32));
+
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX,
+				    lower_32_bits(fpdu_info->frags[0].physaddr));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_HIGH_IDX,
+				    upper_32_bits(fpdu_info->frags[0].physaddr));
+
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG2_LOW_IDX,
+				    lower_32_bits(fpdu_info->frags[1].physaddr));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG2_HIGH_IDX,
+				    upper_32_bits(fpdu_info->frags[1].physaddr));
+
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG3_LOW_IDX,
+				    lower_32_bits(fpdu_info->frags[2].physaddr));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG3_HIGH_IDX,
+				    upper_32_bits(fpdu_info->frags[2].physaddr));
+
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG4_LOW_IDX,
+				    lower_32_bits(fpdu_info->frags[3].physaddr));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG4_HIGH_IDX,
+				    upper_32_bits(fpdu_info->frags[3].physaddr));
+
+		cqp_request->cqp_callback_pointer = fpdu_info;
+		cqp_request->callback = 1;
+		cqp_request->cqp_callback = nes_download_callback;
+
+		atomic_set(&cqp_request->refcount, 1);
+		nes_post_cqp_request(nesdev, cqp_request);
+	}
+
+	return 0;
+}
+
+static void process_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+	int again = 1;
+	unsigned long flags;
+
+	do {
+		/* Ignore rc - if it failed, tcp retries will cause it to try again */
+		forward_fpdus(nesvnic, nesqp);
+
+		spin_lock_irqsave(&nesqp->pau_lock, flags);
+		if (nesqp->pau_pending) {
+			nesqp->pau_pending = 0;
+		} else {
+			nesqp->pau_busy = 0;
+			again = 0;
+		}
+
+		spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+	} while (again);
+}
+
+/**
+ * queue_fpdus - Handle fpdu's that hw passed up to sw
+ */
+static void queue_fpdus(struct sk_buff *skb, struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+	struct sk_buff *tmpskb;
+	struct nes_rskb_cb *cb;
+	struct iphdr *iph;
+	struct tcphdr *tcph;
+	unsigned char *tcph_end;
+	u32 rcv_nxt;
+	u32 rcv_wnd;
+	u32 seqnum;
+	u32 len;
+	bool process_it = false;
+	unsigned long flags;
+
+	/* Move data ptr to after tcp header */
+	iph = (struct iphdr *)skb->data;
+	tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+	seqnum = be32_to_cpu(tcph->seq);
+	tcph_end = (((char *)tcph) + (4 * tcph->doff));
+
+	len = be16_to_cpu(iph->tot_len);
+	if (skb->len > len)
+		skb_trim(skb, len);
+	skb_pull(skb, tcph_end - skb->data);
+
+	/* Initialize tracking values */
+	cb = (struct nes_rskb_cb *)&skb->cb[0];
+	cb->seqnum = seqnum;
+
+	/* Make sure data is in the receive window */
+	rcv_nxt = nesqp->pau_rcv_nxt;
+	rcv_wnd = le32_to_cpu(nesqp->nesqp_context->rcv_wnd);
+	if (!between(seqnum, rcv_nxt, (rcv_nxt + rcv_wnd))) {
+		nes_mgt_free_skb(nesvnic->nesdev, skb, PCI_DMA_TODEVICE);
+		nes_rem_ref_cm_node(nesqp->cm_node);
+		return;
+	}
+
+	spin_lock_irqsave(&nesqp->pau_lock, flags);
+
+	if (nesqp->pau_busy)
+		nesqp->pau_pending = 1;
+	else
+		nesqp->pau_busy = 1;
+
+	/* Queue skb by sequence number */
+	if (skb_queue_len(&nesqp->pau_list) == 0) {
+		skb_queue_head(&nesqp->pau_list, skb);
+	} else {
+		tmpskb = nesqp->pau_list.next;
+		while (tmpskb != (struct sk_buff *)&nesqp->pau_list) {
+			cb = (struct nes_rskb_cb *)&tmpskb->cb[0];
+			if (before(seqnum, cb->seqnum))
+				break;
+			tmpskb = tmpskb->next;
+		}
+		skb_insert(tmpskb, skb, &nesqp->pau_list);
+	}
+	if (nesqp->pau_state == PAU_READY)
+		process_it = true;
+	spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+
+	if (process_it)
+		process_fpdus(nesvnic, nesqp);
+
+	return;
+}
+
+/**
+ * mgt_thread - Handle mgt skbs in a safe context
+ */
+static int mgt_thread(void *context)
+{
+	struct nes_vnic *nesvnic = context;
+	struct sk_buff *skb;
+	struct nes_rskb_cb *cb;
+
+	while (!kthread_should_stop()) {
+		wait_event_interruptible(nesvnic->mgt_wait_queue,
+					 skb_queue_len(&nesvnic->mgt_skb_list) || kthread_should_stop());
+		while ((skb_queue_len(&nesvnic->mgt_skb_list)) && !kthread_should_stop()) {
+			skb = skb_dequeue(&nesvnic->mgt_skb_list);
+			cb = (struct nes_rskb_cb *)&skb->cb[0];
+			cb->data_start = skb->data - ETH_HLEN;
+			cb->busaddr = pci_map_single(nesvnic->nesdev->pcidev, cb->data_start,
+						     nesvnic->max_frame_size, PCI_DMA_TODEVICE);
+			queue_fpdus(skb, nesvnic, cb->nesqp);
+		}
+	}
+
+	/* Closing down so delete any entries on the queue */
+	while (skb_queue_len(&nesvnic->mgt_skb_list)) {
+		skb = skb_dequeue(&nesvnic->mgt_skb_list);
+		cb = (struct nes_rskb_cb *)&skb->cb[0];
+		nes_rem_ref_cm_node(cb->nesqp->cm_node);
+		dev_kfree_skb_any(skb);
+	}
+	return 0;
+}
+
+/**
+ * nes_queue_skbs - Queue skb so it can be handled in a thread context
+ */
+void nes_queue_mgt_skbs(struct sk_buff *skb, struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+	struct nes_rskb_cb *cb;
+
+	cb = (struct nes_rskb_cb *)&skb->cb[0];
+	cb->nesqp = nesqp;
+	skb_queue_tail(&nesvnic->mgt_skb_list, skb);
+	wake_up_interruptible(&nesvnic->mgt_wait_queue);
+}
+
+void nes_destroy_pau_qp(struct nes_device *nesdev, struct nes_qp *nesqp)
+{
+	struct sk_buff *skb;
+	unsigned long flags;
+	atomic_inc(&pau_qps_destroyed);
+
+	/* Free packets that have not yet been forwarded */
+	/* Lock is acquired by skb_dequeue when removing the skb */
+	spin_lock_irqsave(&nesqp->pau_lock, flags);
+	while (skb_queue_len(&nesqp->pau_list)) {
+		skb = skb_dequeue(&nesqp->pau_list);
+		nes_mgt_free_skb(nesdev, skb, PCI_DMA_TODEVICE);
+		nes_rem_ref_cm_node(nesqp->cm_node);
+	}
+	spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+}
+
+static void nes_chg_qh_handler(struct nes_device *nesdev, struct nes_cqp_request *cqp_request)
+{
+	struct pau_qh_chg *qh_chg = cqp_request->cqp_callback_pointer;
+	struct nes_cqp_request *new_request;
+	struct nes_hw_cqp_wqe *cqp_wqe;
+	struct nes_adapter *nesadapter;
+	struct nes_qp *nesqp;
+	struct nes_v4_quad nes_quad;
+	u32 crc_value;
+	u64 u64temp;
+
+	nesadapter = nesdev->nesadapter;
+	nesqp = qh_chg->nesqp;
+
+	/* Should we handle the bad completion */
+	if (cqp_request->major_code) {
+		printk(KERN_ERR PFX "Invalid cqp_request major_code=0x%x\n",
+		       cqp_request->major_code);
+		WARN_ON(1);
+	}
+
+	switch (nesqp->pau_state) {
+	case PAU_DEL_QH:
+		/* Old hash code deleted, now set the new one */
+		nesqp->pau_state = PAU_ADD_LB_QH;
+		new_request = nes_get_cqp_request(nesdev);
+		if (new_request == NULL) {
+			nes_debug(NES_DBG_PAU, "Failed to get a new_request.\n");
+			WARN_ON(1);
+			return;
+		}
+
+		memset(&nes_quad, 0, sizeof(nes_quad));
+		nes_quad.DstIpAdrIndex =
+			cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24);
+		nes_quad.SrcIpadr = cpu_to_be32(0x7f000001);
+		nes_quad.TcpPorts[0] = swab16(nesqp->nesqp_context->tcpPorts[1]);
+		nes_quad.TcpPorts[1] = swab16(nesqp->nesqp_context->tcpPorts[0]);
+
+		/* Produce hash key */
+		crc_value = get_crc_value(&nes_quad);
+		nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);
+		nes_debug(NES_DBG_PAU, "new HTE Index = 0x%08X, CRC = 0x%08X\n",
+			  nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask);
+
+		nesqp->hte_index &= nesadapter->hte_index_mask;
+		nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
+		nesqp->nesqp_context->ip0 = cpu_to_le32(0x7f000001);
+		nesqp->nesqp_context->rcv_nxt = cpu_to_le32(nesqp->pau_rcv_nxt);
+
+		cqp_wqe = &new_request->cqp_wqe;
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+		set_wqe_32bit_value(cqp_wqe->wqe_words,
+				    NES_CQP_WQE_OPCODE_IDX, NES_CQP_MANAGE_QUAD_HASH |
+				    NES_CQP_QP_TYPE_IWARP | NES_CQP_QP_CONTEXT_VALID | NES_CQP_QP_IWARP_STATE_RTS);
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id);
+		u64temp = (u64)nesqp->nesqp_context_pbase;
+		set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
+
+		nes_debug(NES_DBG_PAU, "Waiting for CQP completion for adding the quad hash.\n");
+
+		new_request->cqp_callback_pointer = qh_chg;
+		new_request->callback = 1;
+		new_request->cqp_callback = nes_chg_qh_handler;
+		atomic_set(&new_request->refcount, 1);
+		nes_post_cqp_request(nesdev, new_request);
+		break;
+
+	case PAU_ADD_LB_QH:
+		/* Start processing the queued fpdu's */
+		nesqp->pau_state = PAU_READY;
+		process_fpdus(qh_chg->nesvnic, qh_chg->nesqp);
+		kfree(qh_chg);
+		break;
+	}
+}
+
+/**
+ * nes_change_quad_hash
+ */
+static int nes_change_quad_hash(struct nes_device *nesdev,
+				struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+	struct nes_cqp_request *cqp_request = NULL;
+	struct pau_qh_chg *qh_chg = NULL;
+	u64 u64temp;
+	struct nes_hw_cqp_wqe *cqp_wqe;
+	int ret = 0;
+
+	cqp_request = nes_get_cqp_request(nesdev);
+	if (cqp_request == NULL) {
+		nes_debug(NES_DBG_PAU, "Failed to get a cqp_request.\n");
+		ret = -ENOMEM;
+		goto chg_qh_err;
+	}
+
+	qh_chg = kmalloc(sizeof *qh_chg, GFP_ATOMIC);
+	if (qh_chg == NULL) {
+		nes_debug(NES_DBG_PAU, "Failed to get a cqp_request.\n");
+		ret = -ENOMEM;
+		goto chg_qh_err;
+	}
+	qh_chg->nesdev = nesdev;
+	qh_chg->nesvnic = nesvnic;
+	qh_chg->nesqp = nesqp;
+	nesqp->pau_state = PAU_DEL_QH;
+
+	cqp_wqe = &cqp_request->cqp_wqe;
+	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+	set_wqe_32bit_value(cqp_wqe->wqe_words,
+			    NES_CQP_WQE_OPCODE_IDX, NES_CQP_MANAGE_QUAD_HASH | NES_CQP_QP_DEL_HTE |
+			    NES_CQP_QP_TYPE_IWARP | NES_CQP_QP_CONTEXT_VALID | NES_CQP_QP_IWARP_STATE_RTS);
+	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id);
+	u64temp = (u64)nesqp->nesqp_context_pbase;
+	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
+
+	nes_debug(NES_DBG_PAU, "Waiting for CQP completion for deleting the quad hash.\n");
+
+	cqp_request->cqp_callback_pointer = qh_chg;
+	cqp_request->callback = 1;
+	cqp_request->cqp_callback = nes_chg_qh_handler;
+	atomic_set(&cqp_request->refcount, 1);
+	nes_post_cqp_request(nesdev, cqp_request);
+
+	return ret;
+
+chg_qh_err:
+	kfree(qh_chg);
+	if (cqp_request)
+		nes_put_cqp_request(nesdev, cqp_request);
+	return ret;
+}
+
+/**
+ * nes_mgt_ce_handler
+ * This management code deals with any packed and unaligned (pau) fpdu's
+ * that the hardware cannot handle.
+ */
+static void nes_mgt_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
+{
+	struct nes_vnic_mgt *mgtvnic = container_of(cq, struct nes_vnic_mgt, mgt_cq);
+	struct nes_adapter *nesadapter = nesdev->nesadapter;
+	u32 head;
+	u32 cq_size;
+	u32 cqe_count = 0;
+	u32 cqe_misc;
+	u32 qp_id = 0;
+	u32 skbs_needed;
+	unsigned long context;
+	struct nes_qp *nesqp;
+	struct sk_buff *rx_skb;
+	struct nes_rskb_cb *cb;
+
+	head = cq->cq_head;
+	cq_size = cq->cq_size;
+
+	while (1) {
+		cqe_misc = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]);
+		if (!(cqe_misc & NES_NIC_CQE_VALID))
+			break;
+
+		nesqp = NULL;
+		if (cqe_misc & NES_NIC_CQE_ACCQP_VALID) {
+			qp_id = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_ACCQP_ID_IDX]);
+			qp_id &= 0x001fffff;
+			if (qp_id < nesadapter->max_qp) {
+				context = (unsigned long)nesadapter->qp_table[qp_id - NES_FIRST_QPN];
+				nesqp = (struct nes_qp *)context;
+			}
+		}
+
+		if (nesqp) {
+			if (nesqp->pau_mode == false) {
+				nesqp->pau_mode = true; /* First time for this qp */
+				nesqp->pau_rcv_nxt = le32_to_cpu(
+					cq->cq_vbase[head].cqe_words[NES_NIC_CQE_HASH_RCVNXT]);
+				skb_queue_head_init(&nesqp->pau_list);
+				spin_lock_init(&nesqp->pau_lock);
+				atomic_inc(&pau_qps_created);
+				nes_change_quad_hash(nesdev, mgtvnic->nesvnic, nesqp);
+			}
+
+			rx_skb = mgtvnic->mgt.rx_skb[mgtvnic->mgt.rq_tail];
+			rx_skb->len = 0;
+			skb_put(rx_skb, cqe_misc & 0x0000ffff);
+			rx_skb->protocol = eth_type_trans(rx_skb, mgtvnic->nesvnic->netdev);
+			cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
+			pci_unmap_single(nesdev->pcidev, cb->busaddr, cb->maplen, PCI_DMA_FROMDEVICE);
+			cb->busaddr = 0;
+			mgtvnic->mgt.rq_tail++;
+			mgtvnic->mgt.rq_tail &= mgtvnic->mgt.rq_size - 1;
+
+			nes_add_ref_cm_node(nesqp->cm_node);
+			nes_queue_mgt_skbs(rx_skb, mgtvnic->nesvnic, nesqp);
+		} else {
+			printk(KERN_ERR PFX "Invalid QP %d for packed/unaligned handling\n", qp_id);
+		}
+
+		cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX] = 0;
+		cqe_count++;
+		if (++head >= cq_size)
+			head = 0;
+
+		if (cqe_count == 255) {
+			/* Replenish mgt CQ */
+			nes_write32(nesdev->regs + NES_CQE_ALLOC, cq->cq_number | (cqe_count << 16));
+			nesdev->currcq_count += cqe_count;
+			cqe_count = 0;
+		}
+
+		skbs_needed = atomic_inc_return(&mgtvnic->rx_skbs_needed);
+		if (skbs_needed > (mgtvnic->mgt.rq_size >> 1))
+			nes_replenish_mgt_rq(mgtvnic);
+	}
+
+	cq->cq_head = head;
+	nes_write32(nesdev->regs + NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
+		    cq->cq_number | (cqe_count << 16));
+	nes_read32(nesdev->regs + NES_CQE_ALLOC);
+	nesdev->currcq_count += cqe_count;
+}
+
+/**
+ * nes_init_mgt_qp
+ */
+int nes_init_mgt_qp(struct nes_device *nesdev, struct net_device *netdev, struct nes_vnic *nesvnic)
+{
+	struct nes_vnic_mgt *mgtvnic;
+	u32 counter;
+	void *vmem;
+	dma_addr_t pmem;
+	struct nes_hw_cqp_wqe *cqp_wqe;
+	u32 cqp_head;
+	unsigned long flags;
+	struct nes_hw_nic_qp_context *mgt_context;
+	u64 u64temp;
+	struct nes_hw_nic_rq_wqe *mgt_rqe;
+	struct sk_buff *skb;
+	u32 wqe_count;
+	struct nes_rskb_cb *cb;
+	u32 mgt_mem_size;
+	void *mgt_vbase;
+	dma_addr_t mgt_pbase;
+	int i;
+	int ret;
+
+	/* Allocate space the all mgt QPs once */
+	mgtvnic = kzalloc(NES_MGT_QP_COUNT * sizeof(struct nes_vnic_mgt), GFP_KERNEL);
+	if (mgtvnic == NULL) {
+		nes_debug(NES_DBG_INIT, "Unable to allocate memory for mgt structure\n");
+		return -ENOMEM;
+	}
+
+	/* Allocate fragment, RQ, and CQ; Reuse CEQ based on the PCI function */
+	/* We are not sending from this NIC so sq is not allocated */
+	mgt_mem_size = 256 +
+		       (NES_MGT_WQ_COUNT * sizeof(struct nes_hw_nic_rq_wqe)) +
+		       (NES_MGT_WQ_COUNT * sizeof(struct nes_hw_nic_cqe)) +
+		       sizeof(struct nes_hw_nic_qp_context);
+	mgt_mem_size = (mgt_mem_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+	mgt_vbase = pci_alloc_consistent(nesdev->pcidev, NES_MGT_QP_COUNT * mgt_mem_size, &mgt_pbase);
+	if (!mgt_vbase) {
+		kfree(mgtvnic);
+		nes_debug(NES_DBG_INIT, "Unable to allocate memory for mgt host descriptor rings\n");
+		return -ENOMEM;
+	}
+
+	nesvnic->mgt_mem_size = NES_MGT_QP_COUNT * mgt_mem_size;
+	nesvnic->mgt_vbase = mgt_vbase;
+	nesvnic->mgt_pbase = mgt_pbase;
+
+	skb_queue_head_init(&nesvnic->mgt_skb_list);
+	init_waitqueue_head(&nesvnic->mgt_wait_queue);
+	nesvnic->mgt_thread = kthread_run(mgt_thread, nesvnic, "nes_mgt_thread");
+
+	for (i = 0; i < NES_MGT_QP_COUNT; i++) {
+		mgtvnic->nesvnic = nesvnic;
+		mgtvnic->mgt.qp_id = nesdev->mac_index + NES_MGT_QP_OFFSET + i;
+		memset(mgt_vbase, 0, mgt_mem_size);
+		nes_debug(NES_DBG_INIT, "Allocated mgt QP structures at %p (phys = %016lX), size = %u.\n",
+			  mgt_vbase, (unsigned long)mgt_pbase, mgt_mem_size);
+
+		vmem = (void *)(((unsigned long)mgt_vbase + (256 - 1)) &
+				~(unsigned long)(256 - 1));
+		pmem = (dma_addr_t)(((unsigned long long)mgt_pbase + (256 - 1)) &
+				    ~(unsigned long long)(256 - 1));
+
+		spin_lock_init(&mgtvnic->mgt.rq_lock);
+
+		/* setup the RQ */
+		mgtvnic->mgt.rq_vbase = vmem;
+		mgtvnic->mgt.rq_pbase = pmem;
+		mgtvnic->mgt.rq_head = 0;
+		mgtvnic->mgt.rq_tail = 0;
+		mgtvnic->mgt.rq_size = NES_MGT_WQ_COUNT;
+
+		/* setup the CQ */
+		vmem += (NES_MGT_WQ_COUNT * sizeof(struct nes_hw_nic_rq_wqe));
+		pmem += (NES_MGT_WQ_COUNT * sizeof(struct nes_hw_nic_rq_wqe));
+
+		mgtvnic->mgt_cq.cq_number = mgtvnic->mgt.qp_id;
+		mgtvnic->mgt_cq.cq_vbase = vmem;
+		mgtvnic->mgt_cq.cq_pbase = pmem;
+		mgtvnic->mgt_cq.cq_head = 0;
+		mgtvnic->mgt_cq.cq_size = NES_MGT_WQ_COUNT;
+
+		mgtvnic->mgt_cq.ce_handler = nes_mgt_ce_handler;
+
+		/* Send CreateCQ request to CQP */
+		spin_lock_irqsave(&nesdev->cqp.lock, flags);
+		cqp_head = nesdev->cqp.sq_head;
+
+		cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+
+		cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(
+			NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |
+			((u32)mgtvnic->mgt_cq.cq_size << 16));
+		cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(
+			mgtvnic->mgt_cq.cq_number | ((u32)nesdev->ceq_index << 16));
+		u64temp = (u64)mgtvnic->mgt_cq.cq_pbase;
+		set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
+		cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0;
+		u64temp = (unsigned long)&mgtvnic->mgt_cq;
+		cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] = cpu_to_le32((u32)(u64temp >> 1));
+		cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =
+			cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);
+		cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;
+
+		if (++cqp_head >= nesdev->cqp.sq_size)
+			cqp_head = 0;
+		cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+
+		/* Send CreateQP request to CQP */
+		mgt_context = (void *)(&mgtvnic->mgt_cq.cq_vbase[mgtvnic->mgt_cq.cq_size]);
+		mgt_context->context_words[NES_NIC_CTX_MISC_IDX] =
+			cpu_to_le32((u32)NES_MGT_CTX_SIZE |
+				    ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 12));
+		nes_debug(NES_DBG_INIT, "RX_WINDOW_BUFFER_PAGE_TABLE_SIZE = 0x%08X, RX_WINDOW_BUFFER_SIZE = 0x%08X\n",
+			  nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_PAGE_TABLE_SIZE),
+			  nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE));
+		if (nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE) != 0)
+			mgt_context->context_words[NES_NIC_CTX_MISC_IDX] |= cpu_to_le32(NES_NIC_BACK_STORE);
+
+		u64temp = (u64)mgtvnic->mgt.rq_pbase;
+		mgt_context->context_words[NES_NIC_CTX_SQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
+		mgt_context->context_words[NES_NIC_CTX_SQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
+		u64temp = (u64)mgtvnic->mgt.rq_pbase;
+		mgt_context->context_words[NES_NIC_CTX_RQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
+		mgt_context->context_words[NES_NIC_CTX_RQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
+
+		cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_QP |
+									 NES_CQP_QP_TYPE_NIC);
+		cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(mgtvnic->mgt.qp_id);
+		u64temp = (u64)mgtvnic->mgt_cq.cq_pbase +
+			  (mgtvnic->mgt_cq.cq_size * sizeof(struct nes_hw_nic_cqe));
+		set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
+
+		if (++cqp_head >= nesdev->cqp.sq_size)
+			cqp_head = 0;
+		nesdev->cqp.sq_head = cqp_head;
+
+		barrier();
+
+		/* Ring doorbell (2 WQEs) */
+		nes_write32(nesdev->regs + NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);
+
+		spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
+		nes_debug(NES_DBG_INIT, "Waiting for create MGT QP%u to complete.\n",
+			  mgtvnic->mgt.qp_id);
+
+		ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),
+					 NES_EVENT_TIMEOUT);
+		nes_debug(NES_DBG_INIT, "Create MGT QP%u completed, wait_event_timeout ret = %u.\n",
+			  mgtvnic->mgt.qp_id, ret);
+		if (!ret) {
+			nes_debug(NES_DBG_INIT, "MGT QP%u create timeout expired\n", mgtvnic->mgt.qp_id);
+			if (i == 0) {
+				pci_free_consistent(nesdev->pcidev, nesvnic->mgt_mem_size, nesvnic->mgt_vbase,
+						    nesvnic->mgt_pbase);
+				kfree(mgtvnic);
+			} else {
+				nes_destroy_mgt(nesvnic);
+			}
+			return -EIO;
+		}
+
+		/* Populate the RQ */
+		for (counter = 0; counter < (NES_MGT_WQ_COUNT - 1); counter++) {
+			skb = dev_alloc_skb(nesvnic->max_frame_size);
+			if (!skb) {
+				nes_debug(NES_DBG_INIT, "%s: out of memory for receive skb\n", netdev->name);
+				return -ENOMEM;
+			}
+
+			skb->dev = netdev;
+
+			pmem = pci_map_single(nesdev->pcidev, skb->data,
+					      nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+			cb = (struct nes_rskb_cb *)&skb->cb[0];
+			cb->busaddr = pmem;
+			cb->maplen = nesvnic->max_frame_size;
+
+			mgt_rqe = &mgtvnic->mgt.rq_vbase[counter];
+			mgt_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32((u32)nesvnic->max_frame_size);
+			mgt_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
+			mgt_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] = cpu_to_le32((u32)pmem);
+			mgt_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] = cpu_to_le32((u32)((u64)pmem >> 32));
+			mgtvnic->mgt.rx_skb[counter] = skb;
+		}
+
+		init_timer(&mgtvnic->rq_wqes_timer);
+		mgtvnic->rq_wqes_timer.function = nes_mgt_rq_wqes_timeout;
+		mgtvnic->rq_wqes_timer.data = (unsigned long)mgtvnic;
+
+		wqe_count = NES_MGT_WQ_COUNT - 1;
+		mgtvnic->mgt.rq_head = wqe_count;
+		barrier();
+		do {
+			counter = min(wqe_count, ((u32)255));
+			wqe_count -= counter;
+			nes_write32(nesdev->regs + NES_WQE_ALLOC, (counter << 24) | mgtvnic->mgt.qp_id);
+		} while (wqe_count);
+
+		nes_write32(nesdev->regs + NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
+			    mgtvnic->mgt_cq.cq_number);
+		nes_read32(nesdev->regs + NES_CQE_ALLOC);
+
+		mgt_vbase += mgt_mem_size;
+		mgt_pbase += mgt_mem_size;
+		nesvnic->mgtvnic[i] = mgtvnic++;
+	}
+	return 0;
+}
+
+
+void nes_destroy_mgt(struct nes_vnic *nesvnic)
+{
+	struct nes_device *nesdev = nesvnic->nesdev;
+	struct nes_vnic_mgt *mgtvnic;
+	struct nes_vnic_mgt *first_mgtvnic;
+	unsigned long flags;
+	struct nes_hw_cqp_wqe *cqp_wqe;
+	u32 cqp_head;
+	struct sk_buff *rx_skb;
+	int i;
+	int ret;
+
+	kthread_stop(nesvnic->mgt_thread);
+
+	/* Free remaining NIC receive buffers */
+	first_mgtvnic = nesvnic->mgtvnic[0];
+	for (i = 0; i < NES_MGT_QP_COUNT; i++) {
+		mgtvnic = nesvnic->mgtvnic[i];
+		if (mgtvnic == NULL)
+			continue;
+
+		while (mgtvnic->mgt.rq_head != mgtvnic->mgt.rq_tail) {
+			rx_skb = mgtvnic->mgt.rx_skb[mgtvnic->mgt.rq_tail];
+			nes_mgt_free_skb(nesdev, rx_skb, PCI_DMA_FROMDEVICE);
+			mgtvnic->mgt.rq_tail++;
+			mgtvnic->mgt.rq_tail &= (mgtvnic->mgt.rq_size - 1);
+		}
+
+		spin_lock_irqsave(&nesdev->cqp.lock, flags);
+
+		/* Destroy NIC QP */
+		cqp_head = nesdev->cqp.sq_head;
+		cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
+				    (NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_NIC));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
+				    mgtvnic->mgt.qp_id);
+
+		if (++cqp_head >= nesdev->cqp.sq_size)
+			cqp_head = 0;
+
+		cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
+
+		/* Destroy NIC CQ */
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
+				    (NES_CQP_DESTROY_CQ | ((u32)mgtvnic->mgt_cq.cq_size << 16)));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
+				    (mgtvnic->mgt_cq.cq_number | ((u32)nesdev->ceq_index << 16)));
+
+		if (++cqp_head >= nesdev->cqp.sq_size)
+			cqp_head = 0;
+
+		nesdev->cqp.sq_head = cqp_head;
+		barrier();
+
+		/* Ring doorbell (2 WQEs) */
+		nes_write32(nesdev->regs + NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);
+
+		spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
+		nes_debug(NES_DBG_SHUTDOWN, "Waiting for CQP, cqp_head=%u, cqp.sq_head=%u,"
+			  " cqp.sq_tail=%u, cqp.sq_size=%u\n",
+			  cqp_head, nesdev->cqp.sq_head,
+			  nesdev->cqp.sq_tail, nesdev->cqp.sq_size);
+
+		ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),
+					 NES_EVENT_TIMEOUT);
+
+		nes_debug(NES_DBG_SHUTDOWN, "Destroy MGT QP returned, wait_event_timeout ret = %u, cqp_head=%u,"
+			  " cqp.sq_head=%u, cqp.sq_tail=%u\n",
+			  ret, cqp_head, nesdev->cqp.sq_head, nesdev->cqp.sq_tail);
+		if (!ret)
+			nes_debug(NES_DBG_SHUTDOWN, "MGT QP%u destroy timeout expired\n",
+				  mgtvnic->mgt.qp_id);
+
+		nesvnic->mgtvnic[i] = NULL;
+	}
+
+	if (nesvnic->mgt_vbase) {
+		pci_free_consistent(nesdev->pcidev, nesvnic->mgt_mem_size, nesvnic->mgt_vbase,
+				    nesvnic->mgt_pbase);
+		nesvnic->mgt_vbase = NULL;
+		nesvnic->mgt_pbase = 0;
+	}
+
+	kfree(first_mgtvnic);
+}
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_mgt.h linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_mgt.h
--- linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_mgt.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_mgt.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,97 @@
+/*
+* Copyright (c) 2010 Intel-NE, Inc.  All rights reserved.
+*
+* This software is available to you under a choice of one of two
+* licenses.  You may choose to be licensed under the terms of the GNU
+* General Public License (GPL) Version 2, available from the file
+* COPYING in the main directory of this source tree, or the
+* OpenIB.org BSD license below:
+*
+*     Redistribution and use in source and binary forms, with or
+*     without modification, are permitted provided that the following
+*     conditions are met:
+*
+*      - Redistributions of source code must retain the above
+*        copyright notice, this list of conditions and the following
+*        disclaimer.
+*
+*      - Redistributions in binary form must reproduce the above
+*        copyright notice, this list of conditions and the following
+*        disclaimer in the documentation and/or other materials
+*        provided with the distribution.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*/
+
+#ifndef __NES_MGT_H
+#define __NES_MGT_H
+
+#define MPA_FRAMING 6	/* length is 2 bytes, crc is 4 bytes */
+
+int nes_init_mgt_qp(struct nes_device *nesdev, struct net_device *netdev, struct nes_vnic *nesvnic);
+void nes_queue_mgt_skbs(struct sk_buff *skb, struct nes_vnic *nesvnic, struct nes_qp *nesqp);
+void nes_destroy_mgt(struct nes_vnic *nesvnic);
+void nes_destroy_pau_qp(struct nes_device *nesdev, struct nes_qp *nesqp);
+
+struct nes_hw_mgt {
+	struct nes_hw_nic_rq_wqe *rq_vbase;	/* virtual address of rq */
+	dma_addr_t rq_pbase;			/* PCI memory for host rings */
+	struct sk_buff *rx_skb[NES_NIC_WQ_SIZE];
+	u16 qp_id;
+	u16 sq_head;
+	u16 rq_head;
+	u16 rq_tail;
+	u16 rq_size;
+	u8 replenishing_rq;
+	u8 reserved;
+	spinlock_t rq_lock;
+};
+
+struct nes_vnic_mgt {
+	struct nes_vnic        *nesvnic;
+	struct nes_hw_mgt      mgt;
+	struct nes_hw_nic_cq   mgt_cq;
+	atomic_t               rx_skbs_needed;
+	struct timer_list      rq_wqes_timer;
+	atomic_t               rx_skb_timer_running;
+};
+
+#define MAX_FPDU_FRAGS 4
+struct pau_fpdu_frag {
+	struct sk_buff         *skb;
+	u64                    physaddr;
+	u32                    frag_len;
+	bool                   cmplt;
+};
+
+struct pau_fpdu_info {
+	struct nes_qp          *nesqp;
+	struct nes_cqp_request *cqp_request;
+	void                   *hdr_vbase;
+	dma_addr_t             hdr_pbase;
+	int                    hdr_len;
+	u16                    data_len;
+	u16                    frag_cnt;
+	struct pau_fpdu_frag   frags[MAX_FPDU_FRAGS];
+};
+
+enum pau_qh_state {
+	PAU_DEL_QH,
+	PAU_ADD_LB_QH,
+	PAU_READY
+};
+
+struct pau_qh_chg {
+	struct nes_device *nesdev;
+	struct nes_vnic *nesvnic;
+	struct nes_qp *nesqp;
+};
+
+#endif          /* __NES_MGT_H */
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_nic.c linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_nic.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_nic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_nic.c	2012-01-04 18:55:44.000000000 -0500
@@ -441,13 +441,13 @@
 		nesnic->tx_skb[nesnic->sq_head] = skb;
 		for (skb_fragment_index = 0; skb_fragment_index < skb_shinfo(skb)->nr_frags;
 				skb_fragment_index++) {
-			bus_address = pci_map_page( nesdev->pcidev,
-					skb_shinfo(skb)->frags[skb_fragment_index].page,
-					skb_shinfo(skb)->frags[skb_fragment_index].page_offset,
-					skb_shinfo(skb)->frags[skb_fragment_index].size,
-					PCI_DMA_TODEVICE);
+			skb_frag_t *frag =
+				&skb_shinfo(skb)->frags[skb_fragment_index];
+			bus_address = skb_frag_dma_map(&nesdev->pcidev->dev,
+						       frag, 0, skb_frag_size(frag),
+						       DMA_TO_DEVICE);
 			wqe_fragment_length[wqe_fragment_index] =
-					cpu_to_le16(skb_shinfo(skb)->frags[skb_fragment_index].size);
+					cpu_to_le16(skb_frag_size(&skb_shinfo(skb)->frags[skb_fragment_index]));
 			set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index),
 				bus_address);
 			wqe_fragment_index++;
@@ -561,11 +561,12 @@
 			/* Map all the buffers */
 			for (tso_frag_count=0; tso_frag_count < skb_shinfo(skb)->nr_frags;
 					tso_frag_count++) {
-				tso_bus_address[tso_frag_count] = pci_map_page( nesdev->pcidev,
-						skb_shinfo(skb)->frags[tso_frag_count].page,
-						skb_shinfo(skb)->frags[tso_frag_count].page_offset,
-						skb_shinfo(skb)->frags[tso_frag_count].size,
-						PCI_DMA_TODEVICE);
+				skb_frag_t *frag =
+					&skb_shinfo(skb)->frags[tso_frag_count];
+				tso_bus_address[tso_frag_count] =
+					skb_frag_dma_map(&nesdev->pcidev->dev,
+							 frag, 0, skb_frag_size(frag),
+							 DMA_TO_DEVICE);
 			}
 
 			tso_frag_index = 0;
@@ -636,11 +637,11 @@
 				}
 				while (wqe_fragment_index < 5) {
 					wqe_fragment_length[wqe_fragment_index] =
-							cpu_to_le16(skb_shinfo(skb)->frags[tso_frag_index].size);
+							cpu_to_le16(skb_frag_size(&skb_shinfo(skb)->frags[tso_frag_index]));
 					set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index),
 						(u64)tso_bus_address[tso_frag_index]);
 					wqe_fragment_index++;
-					tso_wqe_length += skb_shinfo(skb)->frags[tso_frag_index++].size;
+					tso_wqe_length += skb_frag_size(&skb_shinfo(skb)->frags[tso_frag_index++]);
 					if (wqe_fragment_index < 5)
 						wqe_fragment_length[wqe_fragment_index] = 0;
 					if (tso_frag_index == tso_frag_count)
@@ -1090,6 +1091,8 @@
 	"LRO aggregated",
 	"LRO flushed",
 	"LRO no_desc",
+	"PAU CreateQPs",
+	"PAU DestroyQPs",
 };
 #define NES_ETHTOOL_STAT_COUNT  ARRAY_SIZE(nes_ethtool_stringset)
 
@@ -1305,6 +1308,8 @@
 	target_stat_values[++index] = nesvnic->lro_mgr.stats.aggregated;
 	target_stat_values[++index] = nesvnic->lro_mgr.stats.flushed;
 	target_stat_values[++index] = nesvnic->lro_mgr.stats.no_desc;
+	target_stat_values[++index] = atomic_read(&pau_qps_created);
+	target_stat_values[++index] = atomic_read(&pau_qps_destroyed);
 }
 
 /**
@@ -1638,7 +1643,7 @@
 	.ndo_get_stats		= nes_netdev_get_stats,
 	.ndo_tx_timeout		= nes_netdev_tx_timeout,
 	.ndo_set_mac_address	= nes_netdev_set_mac_address,
-	.ndo_set_multicast_list = nes_netdev_set_multicast_list,
+	.ndo_set_rx_mode	= nes_netdev_set_multicast_list,
 	.ndo_change_mtu		= nes_netdev_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_fix_features	= nes_fix_features,
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_utils.c linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_utils.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_utils.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_utils.c	2012-01-04 18:55:44.000000000 -0500
@@ -51,13 +51,34 @@
 
 #include "nes.h"
 
-
-
 static u16 nes_read16_eeprom(void __iomem *addr, u16 offset);
 
 u32 mh_detected;
 u32 mh_pauses_sent;
 
+u32 nes_set_pau(struct nes_device *nesdev)
+{
+	u32 ret = 0;
+	u32 counter;
+
+	nes_write_indexed(nesdev, NES_IDX_GPR2, NES_ENABLE_PAU);
+	nes_write_indexed(nesdev, NES_IDX_GPR_TRIGGER, 1);
+
+	for (counter = 0; counter < NES_PAU_COUNTER; counter++) {
+		udelay(30);
+		if (!nes_read_indexed(nesdev, NES_IDX_GPR2)) {
+			printk(KERN_INFO PFX "PAU is supported.\n");
+			break;
+		}
+		nes_write_indexed(nesdev, NES_IDX_GPR_TRIGGER, 1);
+	}
+	if (counter == NES_PAU_COUNTER) {
+		printk(KERN_INFO PFX "PAU is not supported.\n");
+		return -EPERM;
+	}
+	return ret;
+}
+
 /**
  * nes_read_eeprom_values -
  */
@@ -187,6 +208,11 @@
 		if (((major_ver == 3) && (minor_ver >= 16)) || (major_ver > 3))
 			nesadapter->send_term_ok = 1;
 
+		if (nes_drv_opt & NES_DRV_OPT_ENABLE_PAU) {
+			if (!nes_set_pau(nesdev))
+				nesadapter->allow_unaligned_fpdus = 1;
+		}
+
 		nesadapter->firmware_version = (((u32)(u8)(eeprom_data>>8))  <<  16) +
 				(u32)((u8)eeprom_data);
 
@@ -594,6 +620,7 @@
 		nes_free_cqp_request(nesdev, cqp_request);
 }
 
+
 /**
  * nes_post_cqp_request
  */
@@ -604,6 +631,8 @@
 	unsigned long flags;
 	u32 cqp_head;
 	u64 u64temp;
+	u32 opcode;
+	int ctx_index = NES_CQP_WQE_COMP_CTX_LOW_IDX;
 
 	spin_lock_irqsave(&nesdev->cqp.lock, flags);
 
@@ -614,17 +643,20 @@
 		nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
 		cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
 		memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
+		opcode = le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX]);
+		if ((opcode & NES_CQP_OPCODE_MASK) == NES_CQP_DOWNLOAD_SEGMENT)
+			ctx_index = NES_CQP_WQE_DL_COMP_CTX_LOW_IDX;
 		barrier();
 		u64temp = (unsigned long)cqp_request;
-		set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_SCRATCH_LOW_IDX,
-				    u64temp);
+		set_wqe_64bit_value(cqp_wqe->wqe_words, ctx_index, u64temp);
 		nes_debug(NES_DBG_CQP, "CQP request (opcode 0x%02X), line 1 = 0x%08X put on CQPs SQ,"
-				" request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u,"
-				" waiting = %d, refcount = %d.\n",
-				le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f,
-				le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request,
-				nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size,
-				cqp_request->waiting, atomic_read(&cqp_request->refcount));
+			" request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u,"
+			" waiting = %d, refcount = %d.\n",
+			opcode & NES_CQP_OPCODE_MASK,
+			le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request,
+			nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size,
+			cqp_request->waiting, atomic_read(&cqp_request->refcount));
+
 		barrier();
 
 		/* Ring doorbell (1 WQEs) */
@@ -645,7 +677,6 @@
 	return;
 }
 
-
 /**
  * nes_arp_table
  */
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_verbs.c linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_verbs.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_verbs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_verbs.c	2012-01-04 18:55:44.000000000 -0500
@@ -1458,7 +1458,7 @@
 	struct ib_qp_attr attr;
 	struct iw_cm_id *cm_id;
 	struct iw_cm_event cm_event;
-	int ret;
+	int ret = 0;
 
 	atomic_inc(&sw_qps_destroyed);
 	nesqp->destroyed = 1;
@@ -1511,7 +1511,6 @@
 		if ((nesqp->nesrcq) && (nesqp->nesrcq != nesqp->nesscq))
 			nes_clean_cq(nesqp, nesqp->nesrcq);
 	}
-
 	nes_rem_ref(&nesqp->ibqp);
 	return 0;
 }
@@ -2338,8 +2337,10 @@
 
 	skip_pages = ((u32)region->offset) >> 12;
 
-	if (ib_copy_from_udata(&req, udata, sizeof(req)))
+	if (ib_copy_from_udata(&req, udata, sizeof(req))) {
+		ib_umem_release(region);
 		return ERR_PTR(-EFAULT);
+	}
 	nes_debug(NES_DBG_MR, "Memory Registration type = %08X.\n", req.reg_type);
 
 	switch (req.reg_type) {
@@ -2631,6 +2632,7 @@
 			return &nesmr->ibmr;
 	}
 
+	ib_umem_release(region);
 	return ERR_PTR(-ENOSYS);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_verbs.h linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_verbs.h
--- linux-libre-3.1-gnu/drivers/infiniband/hw/nes/nes_verbs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/nes/nes_verbs.h	2012-01-04 18:55:44.000000000 -0500
@@ -139,7 +139,8 @@
 	struct nes_cq         *nesrcq;
 	struct nes_pd         *nespd;
 	void *cm_node; /* handle of the node this QP is associated with */
-	struct ietf_mpa_frame *ietf_frame;
+	void                  *ietf_frame;
+	u8                    ietf_frame_size;
 	dma_addr_t            ietf_frame_pbase;
 	struct ib_mr          *lsmm_mr;
 	struct nes_hw_qp      hwqp;
@@ -154,6 +155,7 @@
 	u32                   mmap_sq_db_index;
 	u32                   mmap_rq_db_index;
 	spinlock_t            lock;
+	spinlock_t            pau_lock;
 	struct nes_qp_context *nesqp_context;
 	dma_addr_t            nesqp_context_pbase;
 	void	              *pbl_vbase;
@@ -161,6 +163,8 @@
 	struct page           *page;
 	struct timer_list     terminate_timer;
 	enum ib_event_type    terminate_eventtype;
+	struct sk_buff_head   pau_list;
+	u32                   pau_rcv_nxt;
 	u16                   active_conn:1;
 	u16                   skip_lsmm:1;
 	u16                   user_mode:1;
@@ -168,7 +172,8 @@
 	u16                   flush_issued:1;
 	u16                   destroyed:1;
 	u16                   sig_all:1;
-	u16                   rsvd:9;
+	u16                   pau_mode:1;
+	u16                   rsvd:8;
 	u16                   private_data_len;
 	u16                   term_sq_flush_code;
 	u16                   term_rq_flush_code;
@@ -176,5 +181,8 @@
 	u8                    hw_tcp_state;
 	u8                    term_flags;
 	u8                    sq_kmapped;
+	u8                    pau_busy;
+	u8                    pau_pending;
+	u8                    pau_state;
 };
 #endif			/* NES_VERBS_H */
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_diag.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_diag.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_diag.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_diag.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,6 +46,7 @@
 #include <linux/pci.h>
 #include <linux/poll.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 #include <linux/fs.h>
 #include <linux/uaccess.h>
 
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_driver.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_driver.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_driver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_driver.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/vmalloc.h>
+#include <linux/module.h>
 
 #include "qib.h"
 
@@ -279,10 +280,10 @@
  */
 static inline void *qib_get_egrbuf(const struct qib_ctxtdata *rcd, u32 etail)
 {
-	const u32 chunk = etail / rcd->rcvegrbufs_perchunk;
-	const u32 idx =  etail % rcd->rcvegrbufs_perchunk;
+	const u32 chunk = etail >> rcd->rcvegrbufs_perchunk_shift;
+	const u32 idx =  etail & ((u32)rcd->rcvegrbufs_perchunk - 1);
 
-	return rcd->rcvegrbuf[chunk] + idx * rcd->dd->rcvegrbufsize;
+	return rcd->rcvegrbuf[chunk] + (idx << rcd->dd->rcvegrbufsize_shift);
 }
 
 /*
@@ -310,7 +311,6 @@
 		u32 opcode;
 		u32 psn;
 		int diff;
-		unsigned long flags;
 
 		/* Sanity check packet */
 		if (tlen < 24)
@@ -365,7 +365,6 @@
 
 			switch (qp->ibqp.qp_type) {
 			case IB_QPT_RC:
-				spin_lock_irqsave(&qp->s_lock, flags);
 				ruc_res =
 					qib_ruc_check_hdr(
 						ibp, hdr,
@@ -373,11 +372,8 @@
 						qp,
 						be32_to_cpu(ohdr->bth[0]));
 				if (ruc_res) {
-					spin_unlock_irqrestore(&qp->s_lock,
-							       flags);
 					goto unlock;
 				}
-				spin_unlock_irqrestore(&qp->s_lock, flags);
 
 				/* Only deal with RDMA Writes for now */
 				if (opcode <
@@ -547,6 +543,15 @@
 			updegr = 0;
 		}
 	}
+	/*
+	 * Notify qib_destroy_qp() if it is waiting
+	 * for lookaside_qp to finish.
+	 */
+	if (rcd->lookaside_qp) {
+		if (atomic_dec_and_test(&rcd->lookaside_qp->refcount))
+			wake_up(&rcd->lookaside_qp->wait);
+		rcd->lookaside_qp = NULL;
+	}
 
 	rcd->head = l;
 	rcd->pkt_count += i;
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_file_ops.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_file_ops.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_file_ops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_file_ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@
 #include <linux/jiffies.h>
 #include <asm/pgtable.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 
 #include "qib.h"
 #include "qib_common.h"
@@ -1284,6 +1285,7 @@
 	strlcpy(rcd->comm, current->comm, sizeof(rcd->comm));
 	ctxt_fp(fp) = rcd;
 	qib_stats.sps_ctxts++;
+	dd->freectxts--;
 	ret = 0;
 	goto bail;
 
@@ -1792,6 +1794,7 @@
 		if (dd->pageshadow)
 			unlock_expected_tids(rcd);
 		qib_stats.sps_ctxts--;
+		dd->freectxts++;
 	}
 
 	mutex_unlock(&qib_mutex);
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib.h linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib.h
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib.h	2012-01-04 18:55:44.000000000 -0500
@@ -171,7 +171,9 @@
 	/* how many alloc_pages() chunks in rcvegrbuf_pages */
 	u32 rcvegrbuf_chunks;
 	/* how many egrbufs per chunk */
-	u32 rcvegrbufs_perchunk;
+	u16 rcvegrbufs_perchunk;
+	/* ilog2 of above */
+	u16 rcvegrbufs_perchunk_shift;
 	/* order for rcvegrbuf_pages */
 	size_t rcvegrbuf_size;
 	/* rcvhdrq size (for freeing) */
@@ -221,6 +223,9 @@
 	/* ctxt rcvhdrq head offset */
 	u32 head;
 	u32 pkt_count;
+	/* lookaside fields */
+	struct qib_qp *lookaside_qp;
+	u32 lookaside_qpn;
 	/* QPs waiting for context processing */
 	struct list_head qp_wait_list;
 };
@@ -807,6 +812,10 @@
 	 * supports, less gives more pio bufs/ctxt, etc.
 	 */
 	u32 cfgctxts;
+	/*
+	 * number of ctxts available for PSM open
+	 */
+	u32 freectxts;
 
 	/*
 	 * hint that we should update pioavailshadow before
@@ -936,7 +945,9 @@
 	/* chip address space used by 4k pio buffers */
 	u32 align4k;
 	/* size of each rcvegrbuffer */
-	u32 rcvegrbufsize;
+	u16 rcvegrbufsize;
+	/* log2 of above */
+	u16 rcvegrbufsize_shift;
 	/* localbus width (1, 2,4,8,16,32) from config space  */
 	u32 lbus_width;
 	/* localbus speed in MHz */
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_iba6120.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_iba6120.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_iba6120.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_iba6120.c	2012-01-04 18:55:44.000000000 -0500
@@ -3273,6 +3273,8 @@
 	/* we always allocate at least 2048 bytes for eager buffers */
 	ret = ib_mtu_enum_to_int(qib_ibmtu);
 	dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU;
+	BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
+	dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
 
 	qib_6120_tidtemplate(dd);
 
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_iba7220.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_iba7220.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_iba7220.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_iba7220.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <linux/io.h>
 #include <rdma/ib_verbs.h>
 
@@ -4085,6 +4086,8 @@
 	/* we always allocate at least 2048 bytes for eager buffers */
 	ret = ib_mtu_enum_to_int(qib_ibmtu);
 	dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU;
+	BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
+	dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
 
 	qib_7220_tidtemplate(dd);
 
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_iba7322.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_iba7322.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_iba7322.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_iba7322.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/jiffies.h>
+#include <linux/module.h>
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_smi.h>
 
@@ -2306,16 +2307,11 @@
 		SYM_LSB(IBCCtrlA_0, MaxPktLen);
 	ppd->cpspec->ibcctrl_a = ibc; /* without linkcmd or linkinitcmd! */
 
-	/* initially come up waiting for TS1, without sending anything. */
-	val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
-		QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
-
 	/*
 	 * Reset the PCS interface to the serdes (and also ibc, which is still
 	 * in reset from above).  Writes new value of ibcctrl_a as last step.
 	 */
 	qib_7322_mini_pcs_reset(ppd);
-	qib_write_kreg(dd, kr_scratch, 0ULL);
 
 	if (!ppd->cpspec->ibcctrl_b) {
 		unsigned lse = ppd->link_speed_enabled;
@@ -2381,17 +2377,20 @@
 	ppd->cpspec->ibcctrl_a |= SYM_MASK(IBCCtrlA_0, IBLinkEn);
 	set_vls(ppd);
 
+	/* initially come up DISABLED, without sending anything. */
+	val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
+					QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
+	qib_write_kreg_port(ppd, krp_ibcctrl_a, val);
+	qib_write_kreg(dd, kr_scratch, 0ULL);
+	/* clear the linkinit cmds */
+	ppd->cpspec->ibcctrl_a = val & ~SYM_MASK(IBCCtrlA_0, LinkInitCmd);
+
 	/* be paranoid against later code motion, etc. */
 	spin_lock_irqsave(&dd->cspec->rcvmod_lock, flags);
 	ppd->p_rcvctrl |= SYM_MASK(RcvCtrl_0, RcvIBPortEnable);
 	qib_write_kreg_port(ppd, krp_rcvctrl, ppd->p_rcvctrl);
 	spin_unlock_irqrestore(&dd->cspec->rcvmod_lock, flags);
 
-	/* Hold the link state machine for mezz boards */
-	if (IS_QMH(dd) || IS_QME(dd))
-		qib_set_ib_7322_lstate(ppd, 0,
-				       QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
-
 	/* Also enable IBSTATUSCHG interrupt.  */
 	val = qib_read_kreg_port(ppd, krp_errmask);
 	qib_write_kreg_port(ppd, krp_errmask,
@@ -2853,9 +2852,8 @@
 		for (i = 0; i < dd->first_user_ctxt; i++) {
 			if (ctxtrbits & rmask) {
 				ctxtrbits &= ~rmask;
-				if (dd->rcd[i]) {
+				if (dd->rcd[i])
 					qib_kreceive(dd->rcd[i], NULL, &npkts);
-				}
 			}
 			rmask <<= 1;
 		}
@@ -5230,6 +5228,8 @@
 				     QIBL_IB_AUTONEG_INPROG)))
 			set_7322_ibspeed_fast(ppd, ppd->link_speed_enabled);
 		if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG)) {
+			struct qib_qsfp_data *qd =
+				&ppd->cpspec->qsfp_data;
 			/* unlock the Tx settings, speed may change */
 			qib_write_kreg_port(ppd, krp_tx_deemph_override,
 				SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
@@ -5237,6 +5237,12 @@
 			qib_cancel_sends(ppd);
 			/* on link down, ensure sane pcs state */
 			qib_7322_mini_pcs_reset(ppd);
+			/* schedule the qsfp refresh which should turn the link
+			   off */
+			if (ppd->dd->flags & QIB_HAS_QSFP) {
+				qd->t_insert = get_jiffies_64();
+				queue_work(ib_wq, &qd->work);
+			}
 			spin_lock_irqsave(&ppd->sdma_lock, flags);
 			if (__qib_sdma_running(ppd))
 				__qib_sdma_process_event(ppd,
@@ -5587,43 +5593,79 @@
 	struct qib_qsfp_data *qd;
 	struct qib_pportdata *ppd;
 	u64 pwrup;
+	unsigned long flags;
 	int ret;
 	u32 le2;
 
 	qd = container_of(work, struct qib_qsfp_data, work);
 	ppd = qd->ppd;
-	pwrup = qd->t_insert + msecs_to_jiffies(QSFP_PWR_LAG_MSEC);
+	pwrup = qd->t_insert +
+		msecs_to_jiffies(QSFP_PWR_LAG_MSEC - QSFP_MODPRS_LAG_MSEC);
 
-	/*
-	 * Some QSFP's not only do not respond until the full power-up
-	 * time, but may behave badly if we try. So hold off responding
-	 * to insertion.
-	 */
-	while (1) {
-		u64 now = get_jiffies_64();
-		if (time_after64(now, pwrup))
-			break;
-		msleep(20);
-	}
-	ret = qib_refresh_qsfp_cache(ppd, &qd->cache);
-	/*
-	 * Need to change LE2 back to defaults if we couldn't
-	 * read the cable type (to handle cable swaps), so do this
-	 * even on failure to read cable information.  We don't
-	 * get here for QME, so IS_QME check not needed here.
-	 */
-	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
+	/* Delay for 20 msecs to allow ModPrs resistor to setup */
+	mdelay(QSFP_MODPRS_LAG_MSEC);
+
+	if (!qib_qsfp_mod_present(ppd)) {
+		ppd->cpspec->qsfp_data.modpresent = 0;
+		/* Set the physical link to disabled */
+		qib_set_ib_7322_lstate(ppd, 0,
+				       QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
+		spin_lock_irqsave(&ppd->lflags_lock, flags);
+		ppd->lflags &= ~QIBL_LINKV;
+		spin_unlock_irqrestore(&ppd->lflags_lock, flags);
+	} else {
+		/*
+		 * Some QSFP's not only do not respond until the full power-up
+		 * time, but may behave badly if we try. So hold off responding
+		 * to insertion.
+		 */
+		while (1) {
+			u64 now = get_jiffies_64();
+			if (time_after64(now, pwrup))
+				break;
+			msleep(20);
+		}
+
+		ret = qib_refresh_qsfp_cache(ppd, &qd->cache);
+
+		/*
+		 * Need to change LE2 back to defaults if we couldn't
+		 * read the cable type (to handle cable swaps), so do this
+		 * even on failure to read cable information.  We don't
+		 * get here for QME, so IS_QME check not needed here.
+		 */
+		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;
-	} else
-		le2 = LE2_DEFAULT;
-	ibsd_wr_allchans(ppd, 13, (le2 << 7), BMASK(9, 7));
-	init_txdds_table(ppd, 0);
+		ibsd_wr_allchans(ppd, 13, (le2 << 7), BMASK(9, 7));
+		/*
+		 * We always change parameteters, since we can choose
+		 * values for cables without eeproms, and the cable may have
+		 * changed from a cable with full or partial eeprom content
+		 * to one with partial or no content.
+		 */
+		init_txdds_table(ppd, 0);
+		/* The physical link is being re-enabled only when the
+		 * previous state was DISABLED and the VALID bit is not
+		 * set. This should only happen when  the cable has been
+		 * physically pulled. */
+		if (!ppd->cpspec->qsfp_data.modpresent &&
+		    (ppd->lflags & (QIBL_LINKV | QIBL_IB_LINK_DISABLED))) {
+			ppd->cpspec->qsfp_data.modpresent = 1;
+			qib_set_ib_7322_lstate(ppd, 0,
+				QLOGIC_IB_IBCC_LINKINITCMD_SLEEP);
+			spin_lock_irqsave(&ppd->lflags_lock, flags);
+			ppd->lflags |= QIBL_LINKV;
+			spin_unlock_irqrestore(&ppd->lflags_lock, flags);
+		}
+	}
 }
 
 /*
@@ -5727,7 +5769,8 @@
 			/* now change the IBC and serdes, overriding generic */
 			init_txdds_table(ppd, 1);
 			/* Re-enable the physical state machine on mezz boards
-			 * now that the correct settings have been set. */
+			 * now that the correct settings have been set.
+			 * QSFP boards are handles by the QSFP event handler */
 			if (IS_QMH(dd) || IS_QME(dd))
 				qib_set_ib_7322_lstate(ppd, 0,
 					    QLOGIC_IB_IBCC_LINKINITCMD_SLEEP);
@@ -6205,6 +6248,8 @@
 
 	/* we always allocate at least 2048 bytes for eager buffers */
 	dd->rcvegrbufsize = max(mtu, 2048);
+	BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
+	dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
 
 	qib_7322_tidtemplate(dd);
 
@@ -7147,7 +7192,8 @@
 		}
 	}
 
-	/* Lookup serdes setting by cable type and attenuation */
+	/* Active cables don't have attenuation so we only set SERDES
+	 * settings to account for the attenuation of the board traces. */
 	if (!override && QSFP_IS_ACTIVE(qd->tech)) {
 		*sdr_dds = txdds_sdr + ppd->dd->board_atten;
 		*ddr_dds = txdds_ddr + ppd->dd->board_atten;
@@ -7464,12 +7510,6 @@
 	u32 le_val, rxcaldone;
 	int chan, chan_done = (1 << SERDES_CHANS) - 1;
 
-	/*
-	 * Initialize the Tx DDS tables.  Also done every QSFP event,
-	 * for adapters with QSFP
-	 */
-	init_txdds_table(ppd, 0);
-
 	/* Clear cmode-override, may be set from older driver */
 	ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 10, 0 << 14, 1 << 14);
 
@@ -7655,6 +7695,12 @@
 	/* VGA output common mode */
 	ibsd_wr_allchans(ppd, 12, (3 << 2), BMASK(3, 2));
 
+	/*
+	 * Initialize the Tx DDS tables.  Also done every QSFP event,
+	 * for adapters with QSFP
+	 */
+	init_txdds_table(ppd, 0);
+
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_init.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_init.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_init.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/idr.h>
+#include <linux/module.h>
 
 #include "qib.h"
 #include "qib_common.h"
@@ -183,6 +184,9 @@
 		rcd->rcvegrbuf_chunks = (rcd->rcvegrcnt +
 			rcd->rcvegrbufs_perchunk - 1) /
 			rcd->rcvegrbufs_perchunk;
+		BUG_ON(!is_power_of_2(rcd->rcvegrbufs_perchunk));
+		rcd->rcvegrbufs_perchunk_shift =
+			ilog2(rcd->rcvegrbufs_perchunk);
 	}
 	return rcd;
 }
@@ -398,6 +402,7 @@
 		if (rcd)
 			dd->f_rcvctrl(rcd->ppd, rcvmask, i);
 	}
+	dd->freectxts = dd->cfgctxts - dd->first_user_ctxt;
 }
 
 static void verify_interrupt(unsigned long opaque)
@@ -581,10 +586,6 @@
 			continue;
 		}
 
-		/* let link come up, and enable IBC */
-		spin_lock_irqsave(&ppd->lflags_lock, flags);
-		ppd->lflags &= ~QIBL_IB_LINK_DISABLED;
-		spin_unlock_irqrestore(&ppd->lflags_lock, flags);
 		portok++;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_pcie.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_pcie.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_pcie.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_pcie.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
 #include <linux/aer.h>
+#include <linux/module.h>
 
 #include "qib.h"
 
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_qp.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_qp.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_qp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_qp.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 
 #include <linux/err.h>
 #include <linux/vmalloc.h>
+#include <linux/jhash.h>
 
 #include "qib.h"
 
@@ -204,6 +205,13 @@
 		clear_bit(qpn & BITS_PER_PAGE_MASK, map->page);
 }
 
+static inline unsigned qpn_hash(struct qib_ibdev *dev, u32 qpn)
+{
+	return jhash_1word(qpn, dev->qp_rnd) &
+		(dev->qp_table_size - 1);
+}
+
+
 /*
  * Put the QP into the hash table.
  * The hash table holds a reference to the QP.
@@ -211,22 +219,23 @@
 static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp)
 {
 	struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
-	unsigned n = qp->ibqp.qp_num % dev->qp_table_size;
 	unsigned long flags;
+	unsigned n = qpn_hash(dev, qp->ibqp.qp_num);
 
 	spin_lock_irqsave(&dev->qpt_lock, flags);
+	atomic_inc(&qp->refcount);
 
 	if (qp->ibqp.qp_num == 0)
-		ibp->qp0 = qp;
+		rcu_assign_pointer(ibp->qp0, qp);
 	else if (qp->ibqp.qp_num == 1)
-		ibp->qp1 = qp;
+		rcu_assign_pointer(ibp->qp1, qp);
 	else {
 		qp->next = dev->qp_table[n];
-		dev->qp_table[n] = qp;
+		rcu_assign_pointer(dev->qp_table[n], qp);
 	}
-	atomic_inc(&qp->refcount);
 
 	spin_unlock_irqrestore(&dev->qpt_lock, flags);
+	synchronize_rcu();
 }
 
 /*
@@ -236,29 +245,32 @@
 static void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp)
 {
 	struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
-	struct qib_qp *q, **qpp;
+	unsigned n = qpn_hash(dev, qp->ibqp.qp_num);
 	unsigned long flags;
 
-	qpp = &dev->qp_table[qp->ibqp.qp_num % dev->qp_table_size];
-
 	spin_lock_irqsave(&dev->qpt_lock, flags);
 
 	if (ibp->qp0 == qp) {
-		ibp->qp0 = NULL;
 		atomic_dec(&qp->refcount);
+		rcu_assign_pointer(ibp->qp0, NULL);
 	} else if (ibp->qp1 == qp) {
-		ibp->qp1 = NULL;
 		atomic_dec(&qp->refcount);
-	} else
+		rcu_assign_pointer(ibp->qp1, NULL);
+	} else {
+		struct qib_qp *q, **qpp;
+
+		qpp = &dev->qp_table[n];
 		for (; (q = *qpp) != NULL; qpp = &q->next)
 			if (q == qp) {
-				*qpp = qp->next;
-				qp->next = NULL;
 				atomic_dec(&qp->refcount);
+				rcu_assign_pointer(*qpp, qp->next);
+				qp->next = NULL;
 				break;
 			}
+	}
 
 	spin_unlock_irqrestore(&dev->qpt_lock, flags);
+	synchronize_rcu();
 }
 
 /**
@@ -280,21 +292,24 @@
 
 		if (!qib_mcast_tree_empty(ibp))
 			qp_inuse++;
-		if (ibp->qp0)
+		rcu_read_lock();
+		if (rcu_dereference(ibp->qp0))
 			qp_inuse++;
-		if (ibp->qp1)
+		if (rcu_dereference(ibp->qp1))
 			qp_inuse++;
+		rcu_read_unlock();
 	}
 
 	spin_lock_irqsave(&dev->qpt_lock, flags);
 	for (n = 0; n < dev->qp_table_size; n++) {
 		qp = dev->qp_table[n];
-		dev->qp_table[n] = NULL;
+		rcu_assign_pointer(dev->qp_table[n], NULL);
 
 		for (; qp; qp = qp->next)
 			qp_inuse++;
 	}
 	spin_unlock_irqrestore(&dev->qpt_lock, flags);
+	synchronize_rcu();
 
 	return qp_inuse;
 }
@@ -309,25 +324,28 @@
  */
 struct qib_qp *qib_lookup_qpn(struct qib_ibport *ibp, u32 qpn)
 {
-	struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev;
-	unsigned long flags;
-	struct qib_qp *qp;
+	struct qib_qp *qp = NULL;
 
-	spin_lock_irqsave(&dev->qpt_lock, flags);
+	if (unlikely(qpn <= 1)) {
+		rcu_read_lock();
+		if (qpn == 0)
+			qp = rcu_dereference(ibp->qp0);
+		else
+			qp = rcu_dereference(ibp->qp1);
+	} else {
+		struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev;
+		unsigned n = qpn_hash(dev, qpn);
 
-	if (qpn == 0)
-		qp = ibp->qp0;
-	else if (qpn == 1)
-		qp = ibp->qp1;
-	else
-		for (qp = dev->qp_table[qpn % dev->qp_table_size]; qp;
-		     qp = qp->next)
+		rcu_read_lock();
+		for (qp = dev->qp_table[n]; rcu_dereference(qp); qp = qp->next)
 			if (qp->ibqp.qp_num == qpn)
 				break;
+	}
 	if (qp)
-		atomic_inc(&qp->refcount);
+		if (unlikely(!atomic_inc_not_zero(&qp->refcount)))
+			qp = NULL;
 
-	spin_unlock_irqrestore(&dev->qpt_lock, flags);
+	rcu_read_unlock();
 	return qp;
 }
 
@@ -765,8 +783,10 @@
 		}
 	}
 
-	if (attr_mask & IB_QP_PATH_MTU)
+	if (attr_mask & IB_QP_PATH_MTU) {
 		qp->path_mtu = pmtu;
+		qp->pmtu = ib_mtu_enum_to_int(pmtu);
+	}
 
 	if (attr_mask & IB_QP_RETRY_CNT) {
 		qp->s_retry_cnt = attr->retry_cnt;
@@ -781,8 +801,12 @@
 	if (attr_mask & IB_QP_MIN_RNR_TIMER)
 		qp->r_min_rnr_timer = attr->min_rnr_timer;
 
-	if (attr_mask & IB_QP_TIMEOUT)
+	if (attr_mask & IB_QP_TIMEOUT) {
 		qp->timeout = attr->timeout;
+		qp->timeout_jiffies =
+			usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
+				1000UL);
+	}
 
 	if (attr_mask & IB_QP_QKEY)
 		qp->qkey = attr->qkey;
@@ -1013,6 +1037,10 @@
 			ret = ERR_PTR(-ENOMEM);
 			goto bail_swq;
 		}
+		RCU_INIT_POINTER(qp->next, NULL);
+		qp->timeout_jiffies =
+			usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
+				1000UL);
 		if (init_attr->srq)
 			sz = 0;
 		else {
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_qsfp.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_qsfp.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_qsfp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_qsfp.c	2012-01-04 18:55:44.000000000 -0500
@@ -273,18 +273,12 @@
 	int ret;
 	int idx;
 	u16 cks;
-	u32 mask;
 	u8 peek[4];
 
 	/* ensure sane contents on invalid reads, for cable swaps */
 	memset(cp, 0, sizeof(*cp));
 
-	mask = QSFP_GPIO_MOD_PRS_N;
-	if (ppd->hw_pidx)
-		mask <<= QSFP_GPIO_PORT2_SHIFT;
-
-	ret = ppd->dd->f_gpio_mod(ppd->dd, 0, 0, 0);
-	if (ret & mask) {
+	if (!qib_qsfp_mod_present(ppd)) {
 		ret = -ENODEV;
 		goto bail;
 	}
@@ -444,6 +438,19 @@
 
 static const char *pwr_codes = "1.5W2.0W2.5W3.5W";
 
+int qib_qsfp_mod_present(struct qib_pportdata *ppd)
+{
+	u32 mask;
+	int ret;
+
+	mask = QSFP_GPIO_MOD_PRS_N <<
+		(ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT);
+	ret = ppd->dd->f_gpio_mod(ppd->dd, 0, 0, 0);
+
+	return !((ret & mask) >>
+		 ((ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT) + 3));
+}
+
 /*
  * Initialize structures that control access to QSFP. Called once per port
  * on cards that support QSFP.
@@ -452,7 +459,6 @@
 		   void (*fevent)(struct work_struct *))
 {
 	u32 mask, highs;
-	int pins;
 
 	struct qib_devdata *dd = qd->ppd->dd;
 
@@ -474,19 +480,6 @@
 	udelay(20); /* Generous RST dwell */
 
 	dd->f_gpio_mod(dd, mask, mask, mask);
-	/* Spec says module can take up to two seconds! */
-	mask = QSFP_GPIO_MOD_PRS_N;
-	if (qd->ppd->hw_pidx)
-		mask <<= QSFP_GPIO_PORT2_SHIFT;
-
-	/* Do not try to wait here. Better to let event handle it */
-	pins = dd->f_gpio_mod(dd, 0, 0, 0);
-	if (pins & mask)
-		goto bail;
-	/* We see a module, but it may be unwise to look yet. Just schedule */
-	qd->t_insert = get_jiffies_64();
-	queue_work(ib_wq, &qd->work);
-bail:
 	return;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_qsfp.h linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_qsfp.h
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_qsfp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_qsfp.h	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 
 #define QSFP_DEV 0xA0
 #define QSFP_PWR_LAG_MSEC 2000
+#define QSFP_MODPRS_LAG_MSEC 20
 
 /*
  * Below are masks for various QSFP signals, for Port 1.
@@ -177,10 +178,12 @@
 	struct work_struct work;
 	struct qib_qsfp_cache cache;
 	u64 t_insert;
+	u8 modpresent;
 };
 
 extern int qib_refresh_qsfp_cache(struct qib_pportdata *ppd,
 				  struct qib_qsfp_cache *cp);
+extern int qib_qsfp_mod_present(struct qib_pportdata *ppd);
 extern void qib_qsfp_init(struct qib_qsfp_data *qd,
 			  void (*fevent)(struct work_struct *));
 extern void qib_qsfp_deinit(struct qib_qsfp_data *qd);
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_rc.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_rc.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_rc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_rc.c	2012-01-04 18:55:44.000000000 -0500
@@ -59,8 +59,7 @@
 	qp->s_flags |= QIB_S_TIMER;
 	qp->s_timer.function = rc_timeout;
 	/* 4.096 usec. * (1 << qp->timeout) */
-	qp->s_timer.expires = jiffies +
-		usecs_to_jiffies((4096UL * (1UL << qp->timeout)) / 1000UL);
+	qp->s_timer.expires = jiffies + qp->timeout_jiffies;
 	add_timer(&qp->s_timer);
 }
 
@@ -239,7 +238,7 @@
 	u32 len;
 	u32 bth0;
 	u32 bth2;
-	u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+	u32 pmtu = qp->pmtu;
 	char newreq;
 	unsigned long flags;
 	int ret = 0;
@@ -272,13 +271,9 @@
 			goto bail;
 		}
 		wqe = get_swqe_ptr(qp, qp->s_last);
-		while (qp->s_last != qp->s_acked) {
-			qib_send_complete(qp, wqe, IB_WC_SUCCESS);
-			if (++qp->s_last >= qp->s_size)
-				qp->s_last = 0;
-			wqe = get_swqe_ptr(qp, qp->s_last);
-		}
-		qib_send_complete(qp, wqe, IB_WC_WR_FLUSH_ERR);
+		qib_send_complete(qp, wqe, qp->s_last != qp->s_acked ?
+			IB_WC_SUCCESS : IB_WC_WR_FLUSH_ERR);
+		/* will get called again */
 		goto done;
 	}
 
@@ -1519,9 +1514,7 @@
 		 * 4.096 usec. * (1 << qp->timeout)
 		 */
 		qp->s_flags |= QIB_S_TIMER;
-		mod_timer(&qp->s_timer, jiffies +
-			usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
-					 1000UL));
+		mod_timer(&qp->s_timer, jiffies + qp->timeout_jiffies);
 		if (qp->s_flags & QIB_S_WAIT_ACK) {
 			qp->s_flags &= ~QIB_S_WAIT_ACK;
 			qib_schedule_send(qp);
@@ -1732,7 +1725,7 @@
 		 * same request.
 		 */
 		offset = ((psn - e->psn) & QIB_PSN_MASK) *
-			ib_mtu_enum_to_int(qp->path_mtu);
+			qp->pmtu;
 		len = be32_to_cpu(reth->length);
 		if (unlikely(offset + len != e->rdma_sge.sge_length))
 			goto unlock_done;
@@ -1876,7 +1869,7 @@
 	u32 psn;
 	u32 pad;
 	struct ib_wc wc;
-	u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+	u32 pmtu = qp->pmtu;
 	int diff;
 	struct ib_reth *reth;
 	unsigned long flags;
@@ -1892,10 +1885,8 @@
 	}
 
 	opcode = be32_to_cpu(ohdr->bth[0]);
-	spin_lock_irqsave(&qp->s_lock, flags);
 	if (qib_ruc_check_hdr(ibp, hdr, has_grh, qp, opcode))
-		goto sunlock;
-	spin_unlock_irqrestore(&qp->s_lock, flags);
+		return;
 
 	psn = be32_to_cpu(ohdr->bth[2]);
 	opcode >>= 24;
@@ -1955,8 +1946,6 @@
 		break;
 	}
 
-	memset(&wc, 0, sizeof wc);
-
 	if (qp->state == IB_QPS_RTR && !(qp->r_flags & QIB_R_COMM_EST)) {
 		qp->r_flags |= QIB_R_COMM_EST;
 		if (qp->ibqp.event_handler) {
@@ -2009,16 +1998,19 @@
 			goto rnr_nak;
 		qp->r_rcv_len = 0;
 		if (opcode == OP(SEND_ONLY))
-			goto send_last;
-		/* FALLTHROUGH */
+			goto no_immediate_data;
+		/* FALLTHROUGH for SEND_ONLY_WITH_IMMEDIATE */
 	case OP(SEND_LAST_WITH_IMMEDIATE):
 send_last_imm:
 		wc.ex.imm_data = ohdr->u.imm_data;
 		hdrsize += 4;
 		wc.wc_flags = IB_WC_WITH_IMM;
-		/* FALLTHROUGH */
+		goto send_last;
 	case OP(SEND_LAST):
 	case OP(RDMA_WRITE_LAST):
+no_immediate_data:
+		wc.wc_flags = 0;
+		wc.ex.imm_data = 0;
 send_last:
 		/* Get the number of bytes the message was padded by. */
 		pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
@@ -2051,6 +2043,12 @@
 		wc.src_qp = qp->remote_qpn;
 		wc.slid = qp->remote_ah_attr.dlid;
 		wc.sl = qp->remote_ah_attr.sl;
+		/* zero fields that are N/A */
+		wc.vendor_err = 0;
+		wc.pkey_index = 0;
+		wc.dlid_path_bits = 0;
+		wc.port_num = 0;
+		wc.csum_ok = 0;
 		/* Signal completion event if the solicited bit is set. */
 		qib_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
 			     (ohdr->bth[0] &
@@ -2089,7 +2087,7 @@
 		if (opcode == OP(RDMA_WRITE_FIRST))
 			goto send_middle;
 		else if (opcode == OP(RDMA_WRITE_ONLY))
-			goto send_last;
+			goto no_immediate_data;
 		ret = qib_get_rwqe(qp, 1);
 		if (ret < 0)
 			goto nack_op_err;
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_ruc.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_ruc.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_ruc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_ruc.c	2012-01-04 18:55:44.000000000 -0500
@@ -260,12 +260,15 @@
 
 /*
  *
- * This should be called with the QP s_lock held.
+ * This should be called with the QP r_lock held.
+ *
+ * The s_lock will be acquired around the qib_migrate_qp() call.
  */
 int qib_ruc_check_hdr(struct qib_ibport *ibp, struct qib_ib_header *hdr,
 		      int has_grh, struct qib_qp *qp, u32 bth0)
 {
 	__be64 guid;
+	unsigned long flags;
 
 	if (qp->s_mig_state == IB_MIG_ARMED && (bth0 & IB_BTH_MIG_REQ)) {
 		if (!has_grh) {
@@ -295,7 +298,9 @@
 		if (be16_to_cpu(hdr->lrh[3]) != qp->alt_ah_attr.dlid ||
 		    ppd_from_ibp(ibp)->port != qp->alt_ah_attr.port_num)
 			goto err;
+		spin_lock_irqsave(&qp->s_lock, flags);
 		qib_migrate_qp(qp);
+		spin_unlock_irqrestore(&qp->s_lock, flags);
 	} else {
 		if (!has_grh) {
 			if (qp->remote_ah_attr.ah_flags & IB_AH_GRH)
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_sd7220.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_sd7220.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_sd7220.c	2012-03-19 22:01:20.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_sd7220.c	2012-03-19 22:04:51.000000000 -0400
@@ -38,6 +38,7 @@
 
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <linux/firmware.h>
 
 #include "qib.h"
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_sdma.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_sdma.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_sdma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_sdma.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/netdevice.h>
+#include <linux/moduleparam.h>
 
 #include "qib.h"
 #include "qib_common.h"
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_srq.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_srq.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_srq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_srq.c	2012-01-04 18:55:44.000000000 -0500
@@ -107,6 +107,11 @@
 	u32 sz;
 	struct ib_srq *ret;
 
+	if (srq_init_attr->srq_type != IB_SRQT_BASIC) {
+		ret = ERR_PTR(-ENOSYS);
+		goto done;
+	}
+
 	if (srq_init_attr->attr.max_sge == 0 ||
 	    srq_init_attr->attr.max_sge > ib_qib_max_srq_sges ||
 	    srq_init_attr->attr.max_wr == 0 ||
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_sysfs.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_sysfs.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -515,8 +515,7 @@
 	struct qib_devdata *dd = dd_from_dev(dev);
 
 	/* Return the number of free user ports (contexts) available. */
-	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->cfgctxts -
-		dd->first_user_ctxt - (u32)qib_stats.sps_ctxts);
+	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->freectxts);
 }
 
 static ssize_t show_serial(struct device *device,
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_tx.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_tx.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_tx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_tx.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/vmalloc.h>
+#include <linux/moduleparam.h>
 
 #include "qib.h"
 
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_uc.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_uc.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_uc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_uc.c	2012-01-04 18:55:44.000000000 -0500
@@ -51,7 +51,7 @@
 	u32 hwords;
 	u32 bth0;
 	u32 len;
-	u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+	u32 pmtu = qp->pmtu;
 	int ret = 0;
 
 	spin_lock_irqsave(&qp->s_lock, flags);
@@ -243,13 +243,12 @@
 		int has_grh, void *data, u32 tlen, struct qib_qp *qp)
 {
 	struct qib_other_headers *ohdr;
-	unsigned long flags;
 	u32 opcode;
 	u32 hdrsize;
 	u32 psn;
 	u32 pad;
 	struct ib_wc wc;
-	u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+	u32 pmtu = qp->pmtu;
 	struct ib_reth *reth;
 	int ret;
 
@@ -263,14 +262,11 @@
 	}
 
 	opcode = be32_to_cpu(ohdr->bth[0]);
-	spin_lock_irqsave(&qp->s_lock, flags);
 	if (qib_ruc_check_hdr(ibp, hdr, has_grh, qp, opcode))
-		goto sunlock;
-	spin_unlock_irqrestore(&qp->s_lock, flags);
+		return;
 
 	psn = be32_to_cpu(ohdr->bth[2]);
 	opcode >>= 24;
-	memset(&wc, 0, sizeof wc);
 
 	/* Compare the PSN verses the expected PSN. */
 	if (unlikely(qib_cmp24(psn, qp->r_psn) != 0)) {
@@ -370,7 +366,7 @@
 		}
 		qp->r_rcv_len = 0;
 		if (opcode == OP(SEND_ONLY))
-			goto send_last;
+			goto no_immediate_data;
 		else if (opcode == OP(SEND_ONLY_WITH_IMMEDIATE))
 			goto send_last_imm;
 		/* FALLTHROUGH */
@@ -389,8 +385,11 @@
 		wc.ex.imm_data = ohdr->u.imm_data;
 		hdrsize += 4;
 		wc.wc_flags = IB_WC_WITH_IMM;
-		/* FALLTHROUGH */
+		goto send_last;
 	case OP(SEND_LAST):
+no_immediate_data:
+		wc.ex.imm_data = 0;
+		wc.wc_flags = 0;
 send_last:
 		/* Get the number of bytes the message was padded by. */
 		pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
@@ -418,6 +417,12 @@
 		wc.src_qp = qp->remote_qpn;
 		wc.slid = qp->remote_ah_attr.dlid;
 		wc.sl = qp->remote_ah_attr.sl;
+		/* zero fields that are N/A */
+		wc.vendor_err = 0;
+		wc.pkey_index = 0;
+		wc.dlid_path_bits = 0;
+		wc.port_num = 0;
+		wc.csum_ok = 0;
 		/* Signal completion event if the solicited bit is set. */
 		qib_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
 			     (ohdr->bth[0] &
@@ -546,6 +551,4 @@
 	qib_rc_error(qp, IB_WC_LOC_QP_OP_ERR);
 	return;
 
-sunlock:
-	spin_unlock_irqrestore(&qp->s_lock, flags);
 }
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_user_pages.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_user_pages.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_user_pages.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_user_pages.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,7 +74,7 @@
 			goto bail_release;
 	}
 
-	current->mm->locked_vm += num_pages;
+	current->mm->pinned_vm += num_pages;
 
 	ret = 0;
 	goto bail;
@@ -151,7 +151,7 @@
 	__qib_release_user_pages(p, num_pages, 1);
 
 	if (current->mm) {
-		current->mm->locked_vm -= num_pages;
+		current->mm->pinned_vm -= num_pages;
 		up_write(&current->mm->mmap_sem);
 	}
 }
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_verbs.c linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_verbs.c
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_verbs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_verbs.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,14 +35,16 @@
 #include <rdma/ib_mad.h>
 #include <rdma/ib_user_verbs.h>
 #include <linux/io.h>
+#include <linux/module.h>
 #include <linux/utsname.h>
 #include <linux/rculist.h>
 #include <linux/mm.h>
+#include <linux/random.h>
 
 #include "qib.h"
 #include "qib_common.h"
 
-static unsigned int ib_qib_qp_table_size = 251;
+static unsigned int ib_qib_qp_table_size = 256;
 module_param_named(qp_table_size, ib_qib_qp_table_size, uint, S_IRUGO);
 MODULE_PARM_DESC(qp_table_size, "QP table size");
 
@@ -659,17 +661,25 @@
 		if (atomic_dec_return(&mcast->refcount) <= 1)
 			wake_up(&mcast->wait);
 	} else {
-		qp = qib_lookup_qpn(ibp, qp_num);
-		if (!qp)
-			goto drop;
+		if (rcd->lookaside_qp) {
+			if (rcd->lookaside_qpn != qp_num) {
+				if (atomic_dec_and_test(
+					&rcd->lookaside_qp->refcount))
+					wake_up(
+					 &rcd->lookaside_qp->wait);
+					rcd->lookaside_qp = NULL;
+				}
+		}
+		if (!rcd->lookaside_qp) {
+			qp = qib_lookup_qpn(ibp, qp_num);
+			if (!qp)
+				goto drop;
+			rcd->lookaside_qp = qp;
+			rcd->lookaside_qpn = qp_num;
+		} else
+			qp = rcd->lookaside_qp;
 		ibp->n_unicast_rcv++;
 		qib_qp_rcv(rcd, hdr, lnh == QIB_LRH_GRH, data, tlen, qp);
-		/*
-		 * Notify qib_destroy_qp() if it is waiting
-		 * for us to finish.
-		 */
-		if (atomic_dec_and_test(&qp->refcount))
-			wake_up(&qp->wait);
 	}
 	return;
 
@@ -1974,6 +1984,8 @@
 	ibp->z_excessive_buffer_overrun_errors =
 		cntrs.excessive_buffer_overrun_errors;
 	ibp->z_vl15_dropped = cntrs.vl15_dropped;
+	RCU_INIT_POINTER(ibp->qp0, NULL);
+	RCU_INIT_POINTER(ibp->qp1, NULL);
 }
 
 /**
@@ -1990,12 +2002,15 @@
 	int ret;
 
 	dev->qp_table_size = ib_qib_qp_table_size;
-	dev->qp_table = kzalloc(dev->qp_table_size * sizeof *dev->qp_table,
+	get_random_bytes(&dev->qp_rnd, sizeof(dev->qp_rnd));
+	dev->qp_table = kmalloc(dev->qp_table_size * sizeof *dev->qp_table,
 				GFP_KERNEL);
 	if (!dev->qp_table) {
 		ret = -ENOMEM;
 		goto err_qpt;
 	}
+	for (i = 0; i < dev->qp_table_size; i++)
+		RCU_INIT_POINTER(dev->qp_table[i], NULL);
 
 	for (i = 0; i < dd->num_pports; i++)
 		init_ibport(ppd + i);
diff -druN linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_verbs.h linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_verbs.h
--- linux-libre-3.1-gnu/drivers/infiniband/hw/qib/qib_verbs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/hw/qib/qib_verbs.h	2012-01-04 18:55:44.000000000 -0500
@@ -485,6 +485,7 @@
 	u8 alt_timeout;         /* Alternate path timeout for this QP */
 	u8 port_num;
 	enum ib_mtu path_mtu;
+	u32 pmtu;		/* decoded from path_mtu */
 	u32 remote_qpn;
 	u32 qkey;               /* QKEY for this QP (for UD or RD) */
 	u32 s_size;             /* send work queue size */
@@ -495,6 +496,7 @@
 	u32 s_last;             /* last completed entry */
 	u32 s_ssn;              /* SSN of tail entry */
 	u32 s_lsn;              /* limit sequence number (credit) */
+	unsigned long timeout_jiffies;  /* computed from timeout */
 	struct qib_swqe *s_wq;  /* send work queue */
 	struct qib_swqe *s_wqe;
 	struct qib_rq r_rq;             /* receive work queue */
@@ -723,7 +725,8 @@
 	dma_addr_t pio_hdrs_phys;
 	/* list of QPs waiting for RNR timer */
 	spinlock_t pending_lock; /* protect wait lists, PMA counters, etc. */
-	unsigned qp_table_size; /* size of the hash table */
+	u32 qp_table_size; /* size of the hash table */
+	u32 qp_rnd; /* random bytes for hash */
 	spinlock_t qpt_lock;
 
 	u32 n_piowait;
diff -druN linux-libre-3.1-gnu/drivers/infiniband/ulp/ipoib/ipoib_cm.c linux-libre-3.2-gnu/drivers/infiniband/ulp/ipoib/ipoib_cm.c
--- linux-libre-3.1-gnu/drivers/infiniband/ulp/ipoib/ipoib_cm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/ulp/ipoib/ipoib_cm.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/moduleparam.h>
 
 #include "ipoib.h"
 
@@ -84,7 +85,7 @@
 	ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_CM_HEAD_SIZE, DMA_FROM_DEVICE);
 
 	for (i = 0; i < frags; ++i)
-		ib_dma_unmap_single(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
+		ib_dma_unmap_page(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
 }
 
 static int ipoib_cm_post_receive_srq(struct net_device *dev, int id)
@@ -169,7 +170,7 @@
 			goto partial_error;
 		skb_fill_page_desc(skb, i, page, 0, PAGE_SIZE);
 
-		mapping[i + 1] = ib_dma_map_page(priv->ca, skb_shinfo(skb)->frags[i].page,
+		mapping[i + 1] = ib_dma_map_page(priv->ca, page,
 						 0, PAGE_SIZE, DMA_FROM_DEVICE);
 		if (unlikely(ib_dma_mapping_error(priv->ca, mapping[i + 1])))
 			goto partial_error;
@@ -183,7 +184,7 @@
 	ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_CM_HEAD_SIZE, DMA_FROM_DEVICE);
 
 	for (; i > 0; --i)
-		ib_dma_unmap_single(priv->ca, mapping[i], PAGE_SIZE, DMA_FROM_DEVICE);
+		ib_dma_unmap_page(priv->ca, mapping[i], PAGE_SIZE, DMA_FROM_DEVICE);
 
 	dev_kfree_skb_any(skb);
 	return NULL;
@@ -537,12 +538,13 @@
 
 		if (length == 0) {
 			/* don't need this page */
-			skb_fill_page_desc(toskb, i, frag->page, 0, PAGE_SIZE);
+			skb_fill_page_desc(toskb, i, skb_frag_page(frag),
+					   0, PAGE_SIZE);
 			--skb_shinfo(skb)->nr_frags;
 		} else {
 			size = min(length, (unsigned) PAGE_SIZE);
 
-			frag->size = size;
+			skb_frag_size_set(frag, size);
 			skb->data_len += size;
 			skb->truesize += size;
 			skb->len += size;
@@ -1496,6 +1498,7 @@
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ib_srq_init_attr srq_init_attr = {
+		.srq_type = IB_SRQT_BASIC,
 		.attr = {
 			.max_wr  = ipoib_recvq_size,
 			.max_sge = max_sge
diff -druN linux-libre-3.1-gnu/drivers/infiniband/ulp/ipoib/ipoib_fs.c linux-libre-3.2-gnu/drivers/infiniband/ulp/ipoib/ipoib_fs.c
--- linux-libre-3.1-gnu/drivers/infiniband/ulp/ipoib/ipoib_fs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/ulp/ipoib/ipoib_fs.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 struct file_operations;
 
 #include <linux/debugfs.h>
+#include <linux/export.h>
 
 #include "ipoib.h"
 
@@ -212,16 +213,15 @@
 		   gid_buf, path.pathrec.dlid ? "yes" : "no");
 
 	if (path.pathrec.dlid) {
-		rate = ib_rate_to_mult(path.pathrec.rate) * 25;
+		rate = ib_rate_to_mbps(path.pathrec.rate);
 
 		seq_printf(file,
 			   "  DLID:     0x%04x\n"
 			   "  SL: %12d\n"
-			   "  rate: %*d%s Gb/sec\n",
+			   "  rate: %8d.%d Gb/sec\n",
 			   be16_to_cpu(path.pathrec.dlid),
 			   path.pathrec.sl,
-			   10 - ((rate % 10) ? 2 : 0),
-			   rate / 10, rate % 10 ? ".5" : "");
+			   rate / 1000, rate % 1000);
 	}
 
 	seq_putc(file, '\n');
diff -druN linux-libre-3.1-gnu/drivers/infiniband/ulp/ipoib/ipoib_ib.c linux-libre-3.2-gnu/drivers/infiniband/ulp/ipoib/ipoib_ib.c
--- linux-libre-3.1-gnu/drivers/infiniband/ulp/ipoib/ipoib_ib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/ulp/ipoib/ipoib_ib.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/moduleparam.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 
@@ -56,21 +57,24 @@
 				 struct ib_pd *pd, struct ib_ah_attr *attr)
 {
 	struct ipoib_ah *ah;
+	struct ib_ah *vah;
 
 	ah = kmalloc(sizeof *ah, GFP_KERNEL);
 	if (!ah)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	ah->dev       = dev;
 	ah->last_send = 0;
 	kref_init(&ah->ref);
 
-	ah->ah = ib_create_ah(pd, attr);
-	if (IS_ERR(ah->ah)) {
+	vah = ib_create_ah(pd, attr);
+	if (IS_ERR(vah)) {
 		kfree(ah);
-		ah = NULL;
-	} else
+		ah = (struct ipoib_ah *)vah;
+	} else {
+		ah->ah = vah;
 		ipoib_dbg(netdev_priv(dev), "Created ah %p\n", ah->ah);
+	}
 
 	return ah;
 }
@@ -117,7 +121,7 @@
 
 		size = length - IPOIB_UD_HEAD_SIZE;
 
-		frag->size     = size;
+		skb_frag_size_set(frag, size);
 		skb->data_len += size;
 		skb->truesize += size;
 	} else
@@ -182,7 +186,7 @@
 			goto partial_error;
 		skb_fill_page_desc(skb, 0, page, 0, PAGE_SIZE);
 		mapping[1] =
-			ib_dma_map_page(priv->ca, skb_shinfo(skb)->frags[0].page,
+			ib_dma_map_page(priv->ca, page,
 					0, PAGE_SIZE, DMA_FROM_DEVICE);
 		if (unlikely(ib_dma_mapping_error(priv->ca, mapping[1])))
 			goto partial_error;
@@ -322,9 +326,10 @@
 		off = 0;
 
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) {
-		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-		mapping[i + off] = ib_dma_map_page(ca, frag->page,
-						 frag->page_offset, frag->size,
+		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+		mapping[i + off] = ib_dma_map_page(ca,
+						 skb_frag_page(frag),
+						 frag->page_offset, skb_frag_size(frag),
 						 DMA_TO_DEVICE);
 		if (unlikely(ib_dma_mapping_error(ca, mapping[i + off])))
 			goto partial_error;
@@ -333,8 +338,9 @@
 
 partial_error:
 	for (; i > 0; --i) {
-		skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
-		ib_dma_unmap_page(ca, mapping[i - !off], frag->size, DMA_TO_DEVICE);
+		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
+
+		ib_dma_unmap_page(ca, mapping[i - !off], skb_frag_size(frag), DMA_TO_DEVICE);
 	}
 
 	if (off)
@@ -358,8 +364,9 @@
 		off = 0;
 
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) {
-		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-		ib_dma_unmap_page(ca, mapping[i + off], frag->size,
+		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+		ib_dma_unmap_page(ca, mapping[i + off], skb_frag_size(frag),
 				  DMA_TO_DEVICE);
 	}
 }
@@ -509,7 +516,7 @@
 
 	for (i = 0; i < nr_frags; ++i) {
 		priv->tx_sge[i + off].addr = mapping[i + off];
-		priv->tx_sge[i + off].length = frags[i].size;
+		priv->tx_sge[i + off].length = skb_frag_size(&frags[i]);
 	}
 	priv->tx_wr.num_sge	     = nr_frags + off;
 	priv->tx_wr.wr_id 	     = wr_id;
diff -druN linux-libre-3.1-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c linux-libre-3.2-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c
--- linux-libre-3.1-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c	2012-01-04 18:55:44.000000000 -0500
@@ -432,7 +432,7 @@
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	if (ah) {
+	if (!IS_ERR_OR_NULL(ah)) {
 		path->pathrec = *pathrec;
 
 		old_ah   = path->ah;
@@ -555,6 +555,7 @@
 	return 0;
 }
 
+/* called with rcu_read_lock */
 static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -636,6 +637,7 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 }
 
+/* called with rcu_read_lock */
 static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
@@ -720,13 +722,14 @@
 	struct neighbour *n = NULL;
 	unsigned long flags;
 
+	rcu_read_lock();
 	if (likely(skb_dst(skb)))
 		n = dst_get_neighbour(skb_dst(skb));
 
 	if (likely(n)) {
 		if (unlikely(!*to_ipoib_neigh(n))) {
 			ipoib_path_lookup(skb, dev);
-			return NETDEV_TX_OK;
+			goto unlock;
 		}
 
 		neigh = *to_ipoib_neigh(n);
@@ -749,17 +752,17 @@
 			ipoib_neigh_free(dev, neigh);
 			spin_unlock_irqrestore(&priv->lock, flags);
 			ipoib_path_lookup(skb, dev);
-			return NETDEV_TX_OK;
+			goto unlock;
 		}
 
 		if (ipoib_cm_get(neigh)) {
 			if (ipoib_cm_up(neigh)) {
 				ipoib_cm_send(dev, skb, ipoib_cm_get(neigh));
-				return NETDEV_TX_OK;
+				goto unlock;
 			}
 		} else if (neigh->ah) {
 			ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha));
-			return NETDEV_TX_OK;
+			goto unlock;
 		}
 
 		if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
@@ -793,13 +796,14 @@
 					   phdr->hwaddr + 4);
 				dev_kfree_skb_any(skb);
 				++dev->stats.tx_dropped;
-				return NETDEV_TX_OK;
+				goto unlock;
 			}
 
 			unicast_arp_send(skb, dev, phdr);
 		}
 	}
-
+unlock:
+	rcu_read_unlock();
 	return NETDEV_TX_OK;
 }
 
@@ -837,7 +841,7 @@
 	dst = skb_dst(skb);
 	n = NULL;
 	if (dst)
-		n = dst_get_neighbour(dst);
+		n = dst_get_neighbour_raw(dst);
 	if ((!dst || !n) && daddr) {
 		struct ipoib_pseudoheader *phdr =
 			(struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
@@ -998,7 +1002,7 @@
 	.ndo_fix_features	 = ipoib_fix_features,
 	.ndo_start_xmit	 	 = ipoib_start_xmit,
 	.ndo_tx_timeout		 = ipoib_timeout,
-	.ndo_set_multicast_list	 = ipoib_set_mcast_list,
+	.ndo_set_rx_mode	 = ipoib_set_mcast_list,
 	.ndo_neigh_setup	 = ipoib_neigh_setup_dev,
 };
 
diff -druN linux-libre-3.1-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c linux-libre-3.2-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
--- linux-libre-3.1-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
+#include <linux/moduleparam.h>
 #include <linux/ip.h>
 #include <linux/in.h>
 #include <linux/igmp.h>
@@ -239,8 +240,11 @@
 		av.grh.dgid = mcast->mcmember.mgid;
 
 		ah = ipoib_create_ah(dev, priv->pd, &av);
-		if (!ah) {
-			ipoib_warn(priv, "ib_address_create failed\n");
+		if (IS_ERR(ah)) {
+			ipoib_warn(priv, "ib_address_create failed %ld\n",
+				-PTR_ERR(ah));
+			/* use original error */
+			return PTR_ERR(ah);
 		} else {
 			spin_lock_irq(&priv->lock);
 			mcast->ah = ah;
@@ -265,7 +269,7 @@
 
 		skb->dev = dev;
 		if (dst)
-			n = dst_get_neighbour(dst);
+			n = dst_get_neighbour_raw(dst);
 		if (!dst || !n) {
 			/* put pseudoheader back on for next time */
 			skb_push(skb, sizeof (struct ipoib_pseudoheader));
@@ -721,6 +725,8 @@
 	if (mcast && mcast->ah) {
 		struct dst_entry *dst = skb_dst(skb);
 		struct neighbour *n = NULL;
+
+		rcu_read_lock();
 		if (dst)
 			n = dst_get_neighbour(dst);
 		if (n && !*to_ipoib_neigh(n)) {
@@ -733,7 +739,7 @@
 				list_add_tail(&neigh->list, &mcast->neigh_list);
 			}
 		}
-
+		rcu_read_unlock();
 		spin_unlock_irqrestore(&priv->lock, flags);
 		ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
 		return;
diff -druN linux-libre-3.1-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c linux-libre-3.2-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c
--- linux-libre-3.1-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c	2012-01-04 18:55:44.000000000 -0500
@@ -57,6 +57,7 @@
 #include <linux/scatterlist.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include <net/sock.h>
 
@@ -151,7 +152,6 @@
 	tx_desc->tx_sg[0].length = ISER_HEADERS_LEN;
 	tx_desc->tx_sg[0].lkey   = device->mr->lkey;
 
-	iser_task->headers_initialized	= 1;
 	iser_task->iser_conn		= iser_conn;
 	return 0;
 }
@@ -166,8 +166,7 @@
 {
 	struct iscsi_iser_task *iser_task = task->dd_data;
 
-	if (!iser_task->headers_initialized)
-		if (iser_initialize_task_headers(task, &iser_task->desc))
+	if (iser_initialize_task_headers(task, &iser_task->desc))
 			return -ENOMEM;
 
 	/* mgmt task */
@@ -278,6 +277,13 @@
 static void iscsi_iser_cleanup_task(struct iscsi_task *task)
 {
 	struct iscsi_iser_task *iser_task = task->dd_data;
+	struct iser_tx_desc	*tx_desc = &iser_task->desc;
+
+	struct iscsi_iser_conn *iser_conn = task->conn->dd_data;
+	struct iser_device     *device    = iser_conn->ib_conn->device;
+
+	ib_dma_unmap_single(device->ib_device,
+		tx_desc->dma_addr, ISER_HEADERS_LEN, DMA_TO_DEVICE);
 
 	/* mgmt tasks do not need special cleanup */
 	if (!task->sc)
@@ -632,6 +638,59 @@
 	iser_conn_terminate(ib_conn);
 }
 
+static mode_t iser_attr_is_visible(int param_type, int param)
+{
+	switch (param_type) {
+	case ISCSI_HOST_PARAM:
+		switch (param) {
+		case ISCSI_HOST_PARAM_NETDEV_NAME:
+		case ISCSI_HOST_PARAM_HWADDRESS:
+		case ISCSI_HOST_PARAM_INITIATOR_NAME:
+			return S_IRUGO;
+		default:
+			return 0;
+		}
+	case ISCSI_PARAM:
+		switch (param) {
+		case ISCSI_PARAM_MAX_RECV_DLENGTH:
+		case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+		case ISCSI_PARAM_HDRDGST_EN:
+		case ISCSI_PARAM_DATADGST_EN:
+		case ISCSI_PARAM_CONN_ADDRESS:
+		case ISCSI_PARAM_CONN_PORT:
+		case ISCSI_PARAM_EXP_STATSN:
+		case ISCSI_PARAM_PERSISTENT_ADDRESS:
+		case ISCSI_PARAM_PERSISTENT_PORT:
+		case ISCSI_PARAM_PING_TMO:
+		case ISCSI_PARAM_RECV_TMO:
+		case ISCSI_PARAM_INITIAL_R2T_EN:
+		case ISCSI_PARAM_MAX_R2T:
+		case ISCSI_PARAM_IMM_DATA_EN:
+		case ISCSI_PARAM_FIRST_BURST:
+		case ISCSI_PARAM_MAX_BURST:
+		case ISCSI_PARAM_PDU_INORDER_EN:
+		case ISCSI_PARAM_DATASEQ_INORDER_EN:
+		case ISCSI_PARAM_TARGET_NAME:
+		case ISCSI_PARAM_TPGT:
+		case ISCSI_PARAM_USERNAME:
+		case ISCSI_PARAM_PASSWORD:
+		case ISCSI_PARAM_USERNAME_IN:
+		case ISCSI_PARAM_PASSWORD_IN:
+		case ISCSI_PARAM_FAST_ABORT:
+		case ISCSI_PARAM_ABORT_TMO:
+		case ISCSI_PARAM_LU_RESET_TMO:
+		case ISCSI_PARAM_TGT_RESET_TMO:
+		case ISCSI_PARAM_IFACE_NAME:
+		case ISCSI_PARAM_INITIATOR_NAME:
+			return S_IRUGO;
+		default:
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
 static struct scsi_host_template iscsi_iser_sht = {
 	.module                 = THIS_MODULE,
 	.name                   = "iSCSI Initiator over iSER, v." DRV_VER,
@@ -653,32 +712,6 @@
 	.owner                  = THIS_MODULE,
 	.name                   = "iser",
 	.caps                   = CAP_RECOVERY_L0 | CAP_MULTI_R2T,
-	.param_mask		= ISCSI_MAX_RECV_DLENGTH |
-				  ISCSI_MAX_XMIT_DLENGTH |
-				  ISCSI_HDRDGST_EN |
-				  ISCSI_DATADGST_EN |
-				  ISCSI_INITIAL_R2T_EN |
-				  ISCSI_MAX_R2T |
-				  ISCSI_IMM_DATA_EN |
-				  ISCSI_FIRST_BURST |
-				  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 |
-				  ISCSI_TARGET_NAME | ISCSI_TPGT |
-				  ISCSI_USERNAME | ISCSI_PASSWORD |
-				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
-				  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
-				  ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
-				  ISCSI_PING_TMO | ISCSI_RECV_TMO |
-				  ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
-	.host_param_mask	= ISCSI_HOST_HWADDRESS |
-				  ISCSI_HOST_NETDEV_NAME |
-				  ISCSI_HOST_INITIATOR_NAME,
 	/* session management */
 	.create_session         = iscsi_iser_session_create,
 	.destroy_session        = iscsi_iser_session_destroy,
@@ -686,6 +719,7 @@
 	.create_conn            = iscsi_iser_conn_create,
 	.bind_conn              = iscsi_iser_conn_bind,
 	.destroy_conn           = iscsi_iser_conn_destroy,
+	.attr_is_visible	= iser_attr_is_visible,
 	.set_param              = iscsi_iser_set_param,
 	.get_conn_param		= iscsi_conn_get_param,
 	.get_ep_param		= iscsi_iser_get_ep_param,
diff -druN linux-libre-3.1-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h linux-libre-3.2-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h
--- linux-libre-3.1-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h	2012-01-04 18:55:44.000000000 -0500
@@ -257,7 +257,8 @@
 	struct list_head	     conn_list;       /* entry in ig conn list */
 
 	char  			     *login_buf;
-	u64 			     login_dma;
+	char			     *login_req_buf, *login_resp_buf;
+	u64			     login_req_dma, login_resp_dma;
 	unsigned int 		     rx_desc_head;
 	struct iser_rx_desc	     *rx_descs;
 	struct ib_recv_wr	     rx_wr[ISER_MIN_POSTED_RX];
@@ -277,7 +278,6 @@
 	struct iser_regd_buf         rdma_regd[ISER_DIRS_NUM];/* regd rdma buf */
 	struct iser_data_buf         data[ISER_DIRS_NUM];     /* orig. data des*/
 	struct iser_data_buf         data_copy[ISER_DIRS_NUM];/* contig. copy  */
-	int                          headers_initialized;
 };
 
 struct iser_page_vec {
diff -druN linux-libre-3.1-gnu/drivers/infiniband/ulp/iser/iser_initiator.c linux-libre-3.2-gnu/drivers/infiniband/ulp/iser/iser_initiator.c
--- linux-libre-3.1-gnu/drivers/infiniband/ulp/iser/iser_initiator.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/ulp/iser/iser_initiator.c	2012-01-04 18:55:44.000000000 -0500
@@ -221,8 +221,14 @@
 	struct iser_device *device = ib_conn->device;
 
 	if (ib_conn->login_buf) {
-		ib_dma_unmap_single(device->ib_device, ib_conn->login_dma,
-			ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
+		if (ib_conn->login_req_dma)
+			ib_dma_unmap_single(device->ib_device,
+				ib_conn->login_req_dma,
+				ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_TO_DEVICE);
+		if (ib_conn->login_resp_dma)
+			ib_dma_unmap_single(device->ib_device,
+				ib_conn->login_resp_dma,
+				ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
 		kfree(ib_conn->login_buf);
 	}
 
@@ -394,6 +400,7 @@
 	unsigned long data_seg_len;
 	int err = 0;
 	struct iser_device *device;
+	struct iser_conn *ib_conn = iser_conn->ib_conn;
 
 	/* build the tx desc regd header and add it to the tx desc dto */
 	mdesc->type = ISCSI_TX_CONTROL;
@@ -409,9 +416,19 @@
 			iser_err("data present on non login task!!!\n");
 			goto send_control_error;
 		}
-		memcpy(iser_conn->ib_conn->login_buf, task->data,
+
+		ib_dma_sync_single_for_cpu(device->ib_device,
+			ib_conn->login_req_dma, task->data_count,
+			DMA_TO_DEVICE);
+
+		memcpy(iser_conn->ib_conn->login_req_buf, task->data,
 							task->data_count);
-		tx_dsg->addr    = iser_conn->ib_conn->login_dma;
+
+		ib_dma_sync_single_for_device(device->ib_device,
+			ib_conn->login_req_dma, task->data_count,
+			DMA_TO_DEVICE);
+
+		tx_dsg->addr    = iser_conn->ib_conn->login_req_dma;
 		tx_dsg->length  = task->data_count;
 		tx_dsg->lkey    = device->mr->lkey;
 		mdesc->num_sge = 2;
@@ -445,8 +462,8 @@
 	int rx_buflen, outstanding, count, err;
 
 	/* differentiate between login to all other PDUs */
-	if ((char *)rx_desc == ib_conn->login_buf) {
-		rx_dma = ib_conn->login_dma;
+	if ((char *)rx_desc == ib_conn->login_resp_buf) {
+		rx_dma = ib_conn->login_resp_dma;
 		rx_buflen = ISER_RX_LOGIN_SIZE;
 	} else {
 		rx_dma = rx_desc->dma_addr;
@@ -473,7 +490,7 @@
 	 * for the posted rx bufs refcount to become zero handles everything   */
 	conn->ib_conn->post_recv_buf_count--;
 
-	if (rx_dma == ib_conn->login_dma)
+	if (rx_dma == ib_conn->login_resp_dma)
 		return;
 
 	outstanding = ib_conn->post_recv_buf_count;
diff -druN linux-libre-3.1-gnu/drivers/infiniband/ulp/iser/iser_verbs.c linux-libre-3.2-gnu/drivers/infiniband/ulp/iser/iser_verbs.c
--- linux-libre-3.1-gnu/drivers/infiniband/ulp/iser/iser_verbs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/infiniband/ulp/iser/iser_verbs.c	2012-01-04 18:55:44.000000000 -0500
@@ -155,20 +155,39 @@
 {
 	struct iser_device	*device;
 	struct ib_qp_init_attr	init_attr;
-	int			ret = -ENOMEM;
+	int			req_err, resp_err, ret = -ENOMEM;
 	struct ib_fmr_pool_param params;
 
 	BUG_ON(ib_conn->device == NULL);
 
 	device = ib_conn->device;
 
-	ib_conn->login_buf = kmalloc(ISER_RX_LOGIN_SIZE, GFP_KERNEL);
+	ib_conn->login_buf = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN +
+					ISER_RX_LOGIN_SIZE, GFP_KERNEL);
 	if (!ib_conn->login_buf)
 		goto out_err;
 
-	ib_conn->login_dma = ib_dma_map_single(ib_conn->device->ib_device,
-				(void *)ib_conn->login_buf, ISER_RX_LOGIN_SIZE,
-				DMA_FROM_DEVICE);
+	ib_conn->login_req_buf  = ib_conn->login_buf;
+	ib_conn->login_resp_buf = ib_conn->login_buf + ISCSI_DEF_MAX_RECV_SEG_LEN;
+
+	ib_conn->login_req_dma = ib_dma_map_single(ib_conn->device->ib_device,
+				(void *)ib_conn->login_req_buf,
+				ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_TO_DEVICE);
+
+	ib_conn->login_resp_dma = ib_dma_map_single(ib_conn->device->ib_device,
+				(void *)ib_conn->login_resp_buf,
+				ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
+
+	req_err  = ib_dma_mapping_error(device->ib_device, ib_conn->login_req_dma);
+	resp_err = ib_dma_mapping_error(device->ib_device, ib_conn->login_resp_dma);
+
+	if (req_err || resp_err) {
+		if (req_err)
+			ib_conn->login_req_dma = 0;
+		if (resp_err)
+			ib_conn->login_resp_dma = 0;
+		goto out_err;
+	}
 
 	ib_conn->page_vec = kmalloc(sizeof(struct iser_page_vec) +
 				    (sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE +1)),
@@ -658,11 +677,11 @@
 	struct ib_sge	  sge;
 	int ib_ret;
 
-	sge.addr   = ib_conn->login_dma;
+	sge.addr   = ib_conn->login_resp_dma;
 	sge.length = ISER_RX_LOGIN_SIZE;
 	sge.lkey   = ib_conn->device->mr->lkey;
 
-	rx_wr.wr_id   = (unsigned long)ib_conn->login_buf;
+	rx_wr.wr_id   = (unsigned long)ib_conn->login_resp_buf;
 	rx_wr.sg_list = &sge;
 	rx_wr.num_sge = 1;
 	rx_wr.next    = NULL;
diff -druN linux-libre-3.1-gnu/drivers/input/ff-core.c linux-libre-3.2-gnu/drivers/input/ff-core.c
--- linux-libre-3.1-gnu/drivers/input/ff-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/ff-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -309,9 +309,10 @@
  * Once ff device is created you need to setup its upload, erase,
  * playback and other handlers before registering input device
  */
-int input_ff_create(struct input_dev *dev, int max_effects)
+int input_ff_create(struct input_dev *dev, unsigned int max_effects)
 {
 	struct ff_device *ff;
+	size_t ff_dev_size;
 	int i;
 
 	if (!max_effects) {
@@ -319,8 +320,12 @@
 		return -EINVAL;
 	}
 
-	ff = kzalloc(sizeof(struct ff_device) +
-		     max_effects * sizeof(struct file *), GFP_KERNEL);
+	ff_dev_size = sizeof(struct ff_device) +
+				max_effects * sizeof(struct file *);
+	if (ff_dev_size < max_effects) /* overflow */
+		return -EINVAL;
+
+	ff = kzalloc(ff_dev_size, GFP_KERNEL);
 	if (!ff)
 		return -ENOMEM;
 
diff -druN linux-libre-3.1-gnu/drivers/input/input-compat.c linux-libre-3.2-gnu/drivers/input/input-compat.c
--- linux-libre-3.1-gnu/drivers/input/input-compat.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/input-compat.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  * the Free Software Foundation.
  */
 
+#include <linux/export.h>
 #include <asm/uaccess.h>
 #include "input-compat.h"
 
diff -druN linux-libre-3.1-gnu/drivers/input/input-mt.c linux-libre-3.2-gnu/drivers/input/input-mt.c
--- linux-libre-3.1-gnu/drivers/input/input-mt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/input-mt.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include <linux/input/mt.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 
 #define TRKID_SGN	((TRKID_MAX + 1) >> 1)
@@ -117,6 +118,7 @@
 	input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2);
 	input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3);
 	input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count == 4);
+	input_event(dev, EV_KEY, BTN_TOOL_QUINTTAP, count == 5);
 }
 EXPORT_SYMBOL(input_mt_report_finger_count);
 
diff -druN linux-libre-3.1-gnu/drivers/input/input-polldev.c linux-libre-3.2-gnu/drivers/input/input-polldev.c
--- linux-libre-3.1-gnu/drivers/input/input-polldev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/input-polldev.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/workqueue.h>
+#include <linux/module.h>
 #include <linux/input-polldev.h>
 
 MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
@@ -49,8 +50,10 @@
 		dev->open(dev);
 
 	/* Only start polling if polling is enabled */
-	if (dev->poll_interval > 0)
-		queue_delayed_work(system_freezable_wq, &dev->work, 0);
+	if (dev->poll_interval > 0) {
+		dev->poll(dev);
+		input_polldev_queue_work(dev);
+	}
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/input/joystick/as5011.c linux-libre-3.2-gnu/drivers/input/joystick/as5011.c
--- linux-libre-3.1-gnu/drivers/input/joystick/as5011.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/joystick/as5011.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/delay.h>
 #include <linux/input/as5011.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define DRIVER_DESC "Driver for Austria Microsystems AS5011 joystick"
 #define MODULE_DEVICE_ALIAS "as5011"
diff -druN linux-libre-3.1-gnu/drivers/input/Kconfig linux-libre-3.2-gnu/drivers/input/Kconfig
--- linux-libre-3.1-gnu/drivers/input/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
 #
 
 menu "Input device support"
-	depends on !S390
+	depends on !S390 && !UML
 
 config INPUT
 	tristate "Generic input layer (needed for keyboard, mouse, ...)" if EXPERT
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/adp5588-keys.c linux-libre-3.2-gnu/drivers/input/keyboard/adp5588-keys.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/adp5588-keys.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/adp5588-keys.c	2012-01-04 18:55:44.000000000 -0500
@@ -550,7 +550,7 @@
 	}
 
 	error = request_irq(client->irq, adp5588_irq,
-			    IRQF_TRIGGER_FALLING | IRQF_DISABLED,
+			    IRQF_TRIGGER_FALLING,
 			    client->dev.driver->name, kpad);
 	if (error) {
 		dev_err(&client->dev, "irq %d busy?\n", client->irq);
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/adp5589-keys.c linux-libre-3.2-gnu/drivers/input/keyboard/adp5589-keys.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/adp5589-keys.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/adp5589-keys.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Description:  keypad driver for ADP5589
+ * Description:  keypad driver for ADP5589, ADP5585
  *		 I2C QWERTY Keypad and IO Expander
  * Bugs: Enter bugs at http://blackfin.uclinux.org/
  *
@@ -22,35 +22,165 @@
 
 #include <linux/input/adp5589.h>
 
+/* ADP5589/ADP5585 Common Registers */
+#define ADP5589_5_ID			0x00
+#define ADP5589_5_INT_STATUS		0x01
+#define ADP5589_5_STATUS		0x02
+#define ADP5589_5_FIFO_1		0x03
+#define ADP5589_5_FIFO_2		0x04
+#define ADP5589_5_FIFO_3		0x05
+#define ADP5589_5_FIFO_4		0x06
+#define ADP5589_5_FIFO_5		0x07
+#define ADP5589_5_FIFO_6		0x08
+#define ADP5589_5_FIFO_7		0x09
+#define ADP5589_5_FIFO_8		0x0A
+#define ADP5589_5_FIFO_9		0x0B
+#define ADP5589_5_FIFO_10		0x0C
+#define ADP5589_5_FIFO_11		0x0D
+#define ADP5589_5_FIFO_12		0x0E
+#define ADP5589_5_FIFO_13		0x0F
+#define ADP5589_5_FIFO_14		0x10
+#define ADP5589_5_FIFO_15		0x11
+#define ADP5589_5_FIFO_16		0x12
+#define ADP5589_5_GPI_INT_STAT_A	0x13
+#define ADP5589_5_GPI_INT_STAT_B	0x14
+
+/* ADP5589 Registers */
+#define ADP5589_GPI_INT_STAT_C		0x15
+#define ADP5589_GPI_STATUS_A		0x16
+#define ADP5589_GPI_STATUS_B		0x17
+#define ADP5589_GPI_STATUS_C		0x18
+#define ADP5589_RPULL_CONFIG_A		0x19
+#define ADP5589_RPULL_CONFIG_B		0x1A
+#define ADP5589_RPULL_CONFIG_C		0x1B
+#define ADP5589_RPULL_CONFIG_D		0x1C
+#define ADP5589_RPULL_CONFIG_E		0x1D
+#define ADP5589_GPI_INT_LEVEL_A		0x1E
+#define ADP5589_GPI_INT_LEVEL_B		0x1F
+#define ADP5589_GPI_INT_LEVEL_C		0x20
+#define ADP5589_GPI_EVENT_EN_A		0x21
+#define ADP5589_GPI_EVENT_EN_B		0x22
+#define ADP5589_GPI_EVENT_EN_C		0x23
+#define ADP5589_GPI_INTERRUPT_EN_A	0x24
+#define ADP5589_GPI_INTERRUPT_EN_B	0x25
+#define ADP5589_GPI_INTERRUPT_EN_C	0x26
+#define ADP5589_DEBOUNCE_DIS_A		0x27
+#define ADP5589_DEBOUNCE_DIS_B		0x28
+#define ADP5589_DEBOUNCE_DIS_C		0x29
+#define ADP5589_GPO_DATA_OUT_A		0x2A
+#define ADP5589_GPO_DATA_OUT_B		0x2B
+#define ADP5589_GPO_DATA_OUT_C		0x2C
+#define ADP5589_GPO_OUT_MODE_A		0x2D
+#define ADP5589_GPO_OUT_MODE_B		0x2E
+#define ADP5589_GPO_OUT_MODE_C		0x2F
+#define ADP5589_GPIO_DIRECTION_A	0x30
+#define ADP5589_GPIO_DIRECTION_B	0x31
+#define ADP5589_GPIO_DIRECTION_C	0x32
+#define ADP5589_UNLOCK1			0x33
+#define ADP5589_UNLOCK2			0x34
+#define ADP5589_EXT_LOCK_EVENT		0x35
+#define ADP5589_UNLOCK_TIMERS		0x36
+#define ADP5589_LOCK_CFG		0x37
+#define ADP5589_RESET1_EVENT_A		0x38
+#define ADP5589_RESET1_EVENT_B		0x39
+#define ADP5589_RESET1_EVENT_C		0x3A
+#define ADP5589_RESET2_EVENT_A		0x3B
+#define ADP5589_RESET2_EVENT_B		0x3C
+#define ADP5589_RESET_CFG		0x3D
+#define ADP5589_PWM_OFFT_LOW		0x3E
+#define ADP5589_PWM_OFFT_HIGH		0x3F
+#define ADP5589_PWM_ONT_LOW		0x40
+#define ADP5589_PWM_ONT_HIGH		0x41
+#define ADP5589_PWM_CFG			0x42
+#define ADP5589_CLOCK_DIV_CFG		0x43
+#define ADP5589_LOGIC_1_CFG		0x44
+#define ADP5589_LOGIC_2_CFG		0x45
+#define ADP5589_LOGIC_FF_CFG		0x46
+#define ADP5589_LOGIC_INT_EVENT_EN	0x47
+#define ADP5589_POLL_PTIME_CFG		0x48
+#define ADP5589_PIN_CONFIG_A		0x49
+#define ADP5589_PIN_CONFIG_B		0x4A
+#define ADP5589_PIN_CONFIG_C		0x4B
+#define ADP5589_PIN_CONFIG_D		0x4C
+#define ADP5589_GENERAL_CFG		0x4D
+#define ADP5589_INT_EN			0x4E
+
+/* ADP5585 Registers */
+#define ADP5585_GPI_STATUS_A		0x15
+#define ADP5585_GPI_STATUS_B		0x16
+#define ADP5585_RPULL_CONFIG_A		0x17
+#define ADP5585_RPULL_CONFIG_B		0x18
+#define ADP5585_RPULL_CONFIG_C		0x19
+#define ADP5585_RPULL_CONFIG_D		0x1A
+#define ADP5585_GPI_INT_LEVEL_A		0x1B
+#define ADP5585_GPI_INT_LEVEL_B		0x1C
+#define ADP5585_GPI_EVENT_EN_A		0x1D
+#define ADP5585_GPI_EVENT_EN_B		0x1E
+#define ADP5585_GPI_INTERRUPT_EN_A	0x1F
+#define ADP5585_GPI_INTERRUPT_EN_B	0x20
+#define ADP5585_DEBOUNCE_DIS_A		0x21
+#define ADP5585_DEBOUNCE_DIS_B		0x22
+#define ADP5585_GPO_DATA_OUT_A		0x23
+#define ADP5585_GPO_DATA_OUT_B		0x24
+#define ADP5585_GPO_OUT_MODE_A		0x25
+#define ADP5585_GPO_OUT_MODE_B		0x26
+#define ADP5585_GPIO_DIRECTION_A	0x27
+#define ADP5585_GPIO_DIRECTION_B	0x28
+#define ADP5585_RESET1_EVENT_A		0x29
+#define ADP5585_RESET1_EVENT_B		0x2A
+#define ADP5585_RESET1_EVENT_C		0x2B
+#define ADP5585_RESET2_EVENT_A		0x2C
+#define ADP5585_RESET2_EVENT_B		0x2D
+#define ADP5585_RESET_CFG		0x2E
+#define ADP5585_PWM_OFFT_LOW		0x2F
+#define ADP5585_PWM_OFFT_HIGH		0x30
+#define ADP5585_PWM_ONT_LOW		0x31
+#define ADP5585_PWM_ONT_HIGH		0x32
+#define ADP5585_PWM_CFG			0x33
+#define ADP5585_LOGIC_CFG		0x34
+#define ADP5585_LOGIC_FF_CFG		0x35
+#define ADP5585_LOGIC_INT_EVENT_EN	0x36
+#define ADP5585_POLL_PTIME_CFG		0x37
+#define ADP5585_PIN_CONFIG_A		0x38
+#define ADP5585_PIN_CONFIG_B		0x39
+#define ADP5585_PIN_CONFIG_D		0x3A
+#define ADP5585_GENERAL_CFG		0x3B
+#define ADP5585_INT_EN			0x3C
+
+/* ID Register */
+#define ADP5589_5_DEVICE_ID_MASK	0xF
+#define ADP5589_5_MAN_ID_MASK		0xF
+#define ADP5589_5_MAN_ID_SHIFT		4
+#define ADP5589_5_MAN_ID		0x02
+
 /* GENERAL_CFG Register */
 #define OSC_EN		(1 << 7)
 #define CORE_CLK(x)	(((x) & 0x3) << 5)
-#define LCK_TRK_LOGIC	(1 << 4)
-#define LCK_TRK_GPI	(1 << 3)
+#define LCK_TRK_LOGIC	(1 << 4)	/* ADP5589 only */
+#define LCK_TRK_GPI	(1 << 3)	/* ADP5589 only */
 #define INT_CFG		(1 << 1)
 #define RST_CFG		(1 << 0)
 
 /* INT_EN Register */
-#define LOGIC2_IEN	(1 << 5)
+#define LOGIC2_IEN	(1 << 5)	/* ADP5589 only */
 #define LOGIC1_IEN	(1 << 4)
-#define LOCK_IEN	(1 << 3)
+#define LOCK_IEN	(1 << 3)	/* ADP5589 only */
 #define OVRFLOW_IEN	(1 << 2)
 #define GPI_IEN		(1 << 1)
 #define EVENT_IEN	(1 << 0)
 
 /* Interrupt Status Register */
-#define LOGIC2_INT	(1 << 5)
+#define LOGIC2_INT	(1 << 5)	/* ADP5589 only */
 #define LOGIC1_INT	(1 << 4)
-#define LOCK_INT	(1 << 3)
+#define LOCK_INT	(1 << 3)	/* ADP5589 only */
 #define OVRFLOW_INT	(1 << 2)
 #define GPI_INT		(1 << 1)
 #define EVENT_INT	(1 << 0)
 
 /* STATUS Register */
-
-#define LOGIC2_STAT	(1 << 7)
+#define LOGIC2_STAT	(1 << 7)	/* ADP5589 only */
 #define LOGIC1_STAT	(1 << 6)
-#define LOCK_STAT	(1 << 5)
+#define LOCK_STAT	(1 << 5)	/* ADP5589 only */
 #define KEC		0xF
 
 /* PIN_CONFIG_D Register */
@@ -61,27 +191,54 @@
 #define LOCK_EN		(1 << 0)
 
 #define PTIME_MASK	0x3
-#define LTIME_MASK	0x3
+#define LTIME_MASK	0x3		/* ADP5589 only */
 
 /* Key Event Register xy */
 #define KEY_EV_PRESSED		(1 << 7)
 #define KEY_EV_MASK		(0x7F)
 
 #define KEYP_MAX_EVENT		16
+#define ADP5589_MAXGPIO		19
+#define ADP5585_MAXGPIO		11 /* 10 on the ADP5585-01, 11 on ADP5585-02 */
 
-#define MAXGPIO			19
-#define ADP_BANK(offs)		((offs) >> 3)
-#define ADP_BIT(offs)		(1u << ((offs) & 0x7))
+enum {
+	ADP5589,
+	ADP5585_01,
+	ADP5585_02
+};
+
+struct adp_constants {
+	u8 maxgpio;
+	u8 keymapsize;
+	u8 gpi_pin_row_base;
+	u8 gpi_pin_row_end;
+	u8 gpi_pin_col_base;
+	u8 gpi_pin_base;
+	u8 gpi_pin_end;
+	u8 gpimapsize_max;
+	u8 max_row_num;
+	u8 max_col_num;
+	u8 row_mask;
+	u8 col_mask;
+	u8 col_shift;
+	u8 c4_extend_cfg;
+	u8 (*bank) (u8 offset);
+	u8 (*bit) (u8 offset);
+	u8 (*reg) (u8 reg);
+};
 
 struct adp5589_kpad {
 	struct i2c_client *client;
 	struct input_dev *input;
+	const struct adp_constants *var;
 	unsigned short keycode[ADP5589_KEYMAPSIZE];
 	const struct adp5589_gpi_map *gpimap;
 	unsigned short gpimapsize;
 	unsigned extend_cfg;
+	bool is_adp5585;
+	bool adp5585_support_row5;
 #ifdef CONFIG_GPIOLIB
-	unsigned char gpiomap[MAXGPIO];
+	unsigned char gpiomap[ADP5589_MAXGPIO];
 	bool export_gpio;
 	struct gpio_chip gc;
 	struct mutex gpio_lock;	/* Protect cached dir, dat_out */
@@ -90,6 +247,129 @@
 #endif
 };
 
+/*
+ *  ADP5589 / ADP5585 derivative / variant handling
+ */
+
+
+/* ADP5589 */
+
+static unsigned char adp5589_bank(unsigned char offset)
+{
+	return offset >> 3;
+}
+
+static unsigned char adp5589_bit(unsigned char offset)
+{
+	return 1u << (offset & 0x7);
+}
+
+static unsigned char adp5589_reg(unsigned char reg)
+{
+	return reg;
+}
+
+static const struct adp_constants const_adp5589 = {
+	.maxgpio		= ADP5589_MAXGPIO,
+	.keymapsize		= ADP5589_KEYMAPSIZE,
+	.gpi_pin_row_base	= ADP5589_GPI_PIN_ROW_BASE,
+	.gpi_pin_row_end	= ADP5589_GPI_PIN_ROW_END,
+	.gpi_pin_col_base	= ADP5589_GPI_PIN_COL_BASE,
+	.gpi_pin_base		= ADP5589_GPI_PIN_BASE,
+	.gpi_pin_end		= ADP5589_GPI_PIN_END,
+	.gpimapsize_max		= ADP5589_GPIMAPSIZE_MAX,
+	.c4_extend_cfg		= 12,
+	.max_row_num		= ADP5589_MAX_ROW_NUM,
+	.max_col_num		= ADP5589_MAX_COL_NUM,
+	.row_mask		= ADP5589_ROW_MASK,
+	.col_mask		= ADP5589_COL_MASK,
+	.col_shift		= ADP5589_COL_SHIFT,
+	.bank			= adp5589_bank,
+	.bit			= adp5589_bit,
+	.reg			= adp5589_reg,
+};
+
+/* ADP5585 */
+
+static unsigned char adp5585_bank(unsigned char offset)
+{
+	return offset > ADP5585_MAX_ROW_NUM;
+}
+
+static unsigned char adp5585_bit(unsigned char offset)
+{
+	return (offset > ADP5585_MAX_ROW_NUM) ?
+		1u << (offset - ADP5585_COL_SHIFT) : 1u << offset;
+}
+
+static const unsigned char adp5585_reg_lut[] = {
+	[ADP5589_GPI_STATUS_A]		= ADP5585_GPI_STATUS_A,
+	[ADP5589_GPI_STATUS_B]		= ADP5585_GPI_STATUS_B,
+	[ADP5589_RPULL_CONFIG_A]	= ADP5585_RPULL_CONFIG_A,
+	[ADP5589_RPULL_CONFIG_B]	= ADP5585_RPULL_CONFIG_B,
+	[ADP5589_RPULL_CONFIG_C]	= ADP5585_RPULL_CONFIG_C,
+	[ADP5589_RPULL_CONFIG_D]	= ADP5585_RPULL_CONFIG_D,
+	[ADP5589_GPI_INT_LEVEL_A]	= ADP5585_GPI_INT_LEVEL_A,
+	[ADP5589_GPI_INT_LEVEL_B]	= ADP5585_GPI_INT_LEVEL_B,
+	[ADP5589_GPI_EVENT_EN_A]	= ADP5585_GPI_EVENT_EN_A,
+	[ADP5589_GPI_EVENT_EN_B]	= ADP5585_GPI_EVENT_EN_B,
+	[ADP5589_GPI_INTERRUPT_EN_A]	= ADP5585_GPI_INTERRUPT_EN_A,
+	[ADP5589_GPI_INTERRUPT_EN_B]	= ADP5585_GPI_INTERRUPT_EN_B,
+	[ADP5589_DEBOUNCE_DIS_A]	= ADP5585_DEBOUNCE_DIS_A,
+	[ADP5589_DEBOUNCE_DIS_B]	= ADP5585_DEBOUNCE_DIS_B,
+	[ADP5589_GPO_DATA_OUT_A]	= ADP5585_GPO_DATA_OUT_A,
+	[ADP5589_GPO_DATA_OUT_B]	= ADP5585_GPO_DATA_OUT_B,
+	[ADP5589_GPO_OUT_MODE_A]	= ADP5585_GPO_OUT_MODE_A,
+	[ADP5589_GPO_OUT_MODE_B]	= ADP5585_GPO_OUT_MODE_B,
+	[ADP5589_GPIO_DIRECTION_A]	= ADP5585_GPIO_DIRECTION_A,
+	[ADP5589_GPIO_DIRECTION_B]	= ADP5585_GPIO_DIRECTION_B,
+	[ADP5589_RESET1_EVENT_A]	= ADP5585_RESET1_EVENT_A,
+	[ADP5589_RESET1_EVENT_B]	= ADP5585_RESET1_EVENT_B,
+	[ADP5589_RESET1_EVENT_C]	= ADP5585_RESET1_EVENT_C,
+	[ADP5589_RESET2_EVENT_A]	= ADP5585_RESET2_EVENT_A,
+	[ADP5589_RESET2_EVENT_B]	= ADP5585_RESET2_EVENT_B,
+	[ADP5589_RESET_CFG]		= ADP5585_RESET_CFG,
+	[ADP5589_PWM_OFFT_LOW]		= ADP5585_PWM_OFFT_LOW,
+	[ADP5589_PWM_OFFT_HIGH]		= ADP5585_PWM_OFFT_HIGH,
+	[ADP5589_PWM_ONT_LOW]		= ADP5585_PWM_ONT_LOW,
+	[ADP5589_PWM_ONT_HIGH]		= ADP5585_PWM_ONT_HIGH,
+	[ADP5589_PWM_CFG]		= ADP5585_PWM_CFG,
+	[ADP5589_LOGIC_1_CFG]		= ADP5585_LOGIC_CFG,
+	[ADP5589_LOGIC_FF_CFG]		= ADP5585_LOGIC_FF_CFG,
+	[ADP5589_LOGIC_INT_EVENT_EN]	= ADP5585_LOGIC_INT_EVENT_EN,
+	[ADP5589_POLL_PTIME_CFG]	= ADP5585_POLL_PTIME_CFG,
+	[ADP5589_PIN_CONFIG_A]		= ADP5585_PIN_CONFIG_A,
+	[ADP5589_PIN_CONFIG_B]		= ADP5585_PIN_CONFIG_B,
+	[ADP5589_PIN_CONFIG_D]		= ADP5585_PIN_CONFIG_D,
+	[ADP5589_GENERAL_CFG]		= ADP5585_GENERAL_CFG,
+	[ADP5589_INT_EN]		= ADP5585_INT_EN,
+};
+
+static unsigned char adp5585_reg(unsigned char reg)
+{
+	return adp5585_reg_lut[reg];
+}
+
+static const struct adp_constants const_adp5585 = {
+	.maxgpio		= ADP5585_MAXGPIO,
+	.keymapsize		= ADP5585_KEYMAPSIZE,
+	.gpi_pin_row_base	= ADP5585_GPI_PIN_ROW_BASE,
+	.gpi_pin_row_end	= ADP5585_GPI_PIN_ROW_END,
+	.gpi_pin_col_base	= ADP5585_GPI_PIN_COL_BASE,
+	.gpi_pin_base		= ADP5585_GPI_PIN_BASE,
+	.gpi_pin_end		= ADP5585_GPI_PIN_END,
+	.gpimapsize_max		= ADP5585_GPIMAPSIZE_MAX,
+	.c4_extend_cfg		= 10,
+	.max_row_num		= ADP5585_MAX_ROW_NUM,
+	.max_col_num		= ADP5585_MAX_COL_NUM,
+	.row_mask		= ADP5585_ROW_MASK,
+	.col_mask		= ADP5585_COL_MASK,
+	.col_shift		= ADP5585_COL_SHIFT,
+	.bank			= adp5585_bank,
+	.bit			= adp5585_bit,
+	.reg			= adp5585_reg,
+};
+
 static int adp5589_read(struct i2c_client *client, u8 reg)
 {
 	int ret = i2c_smbus_read_byte_data(client, reg);
@@ -109,19 +389,20 @@
 static int adp5589_gpio_get_value(struct gpio_chip *chip, unsigned off)
 {
 	struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc);
-	unsigned int bank = ADP_BANK(kpad->gpiomap[off]);
-	unsigned int bit = ADP_BIT(kpad->gpiomap[off]);
+	unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
+	unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
 
-	return !!(adp5589_read(kpad->client, ADP5589_GPI_STATUS_A + bank) &
-		  bit);
+	return !!(adp5589_read(kpad->client,
+			       kpad->var->reg(ADP5589_GPI_STATUS_A) + bank) &
+			       bit);
 }
 
 static void adp5589_gpio_set_value(struct gpio_chip *chip,
 				   unsigned off, int val)
 {
 	struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc);
-	unsigned int bank = ADP_BANK(kpad->gpiomap[off]);
-	unsigned int bit = ADP_BIT(kpad->gpiomap[off]);
+	unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
+	unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
 
 	mutex_lock(&kpad->gpio_lock);
 
@@ -130,8 +411,8 @@
 	else
 		kpad->dat_out[bank] &= ~bit;
 
-	adp5589_write(kpad->client, ADP5589_GPO_DATA_OUT_A + bank,
-		      kpad->dat_out[bank]);
+	adp5589_write(kpad->client, kpad->var->reg(ADP5589_GPO_DATA_OUT_A) +
+		      bank, kpad->dat_out[bank]);
 
 	mutex_unlock(&kpad->gpio_lock);
 }
@@ -139,14 +420,15 @@
 static int adp5589_gpio_direction_input(struct gpio_chip *chip, unsigned off)
 {
 	struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc);
-	unsigned int bank = ADP_BANK(kpad->gpiomap[off]);
-	unsigned int bit = ADP_BIT(kpad->gpiomap[off]);
+	unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
+	unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
 	int ret;
 
 	mutex_lock(&kpad->gpio_lock);
 
 	kpad->dir[bank] &= ~bit;
-	ret = adp5589_write(kpad->client, ADP5589_GPIO_DIRECTION_A + bank,
+	ret = adp5589_write(kpad->client,
+			    kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank,
 			    kpad->dir[bank]);
 
 	mutex_unlock(&kpad->gpio_lock);
@@ -158,8 +440,8 @@
 					 unsigned off, int val)
 {
 	struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc);
-	unsigned int bank = ADP_BANK(kpad->gpiomap[off]);
-	unsigned int bit = ADP_BIT(kpad->gpiomap[off]);
+	unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
+	unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
 	int ret;
 
 	mutex_lock(&kpad->gpio_lock);
@@ -171,9 +453,10 @@
 	else
 		kpad->dat_out[bank] &= ~bit;
 
-	ret = adp5589_write(kpad->client, ADP5589_GPO_DATA_OUT_A + bank,
-			    kpad->dat_out[bank]);
-	ret |= adp5589_write(kpad->client, ADP5589_GPIO_DIRECTION_A + bank,
+	ret = adp5589_write(kpad->client, kpad->var->reg(ADP5589_GPO_DATA_OUT_A)
+			    + bank, kpad->dat_out[bank]);
+	ret |= adp5589_write(kpad->client,
+			     kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank,
 			     kpad->dir[bank]);
 
 	mutex_unlock(&kpad->gpio_lock);
@@ -184,26 +467,29 @@
 static int __devinit adp5589_build_gpiomap(struct adp5589_kpad *kpad,
 				const struct adp5589_kpad_platform_data *pdata)
 {
-	bool pin_used[MAXGPIO];
+	bool pin_used[ADP5589_MAXGPIO];
 	int n_unused = 0;
 	int i;
 
 	memset(pin_used, false, sizeof(pin_used));
 
-	for (i = 0; i < MAXGPIO; i++)
+	for (i = 0; i < kpad->var->maxgpio; i++)
 		if (pdata->keypad_en_mask & (1 << i))
 			pin_used[i] = true;
 
 	for (i = 0; i < kpad->gpimapsize; i++)
-		pin_used[kpad->gpimap[i].pin - ADP5589_GPI_PIN_BASE] = true;
+		pin_used[kpad->gpimap[i].pin - kpad->var->gpi_pin_base] = true;
 
 	if (kpad->extend_cfg & R4_EXTEND_CFG)
 		pin_used[4] = true;
 
 	if (kpad->extend_cfg & C4_EXTEND_CFG)
-		pin_used[12] = true;
+		pin_used[kpad->var->c4_extend_cfg] = true;
 
-	for (i = 0; i < MAXGPIO; i++)
+	if (!kpad->adp5585_support_row5)
+		pin_used[5] = true;
+
+	for (i = 0; i < kpad->var->maxgpio; i++)
 		if (!pin_used[i])
 			kpad->gpiomap[n_unused++] = i;
 
@@ -246,11 +532,11 @@
 		return error;
 	}
 
-	for (i = 0; i <= ADP_BANK(MAXGPIO); i++) {
-		kpad->dat_out[i] = adp5589_read(kpad->client,
-						ADP5589_GPO_DATA_OUT_A + i);
-		kpad->dir[i] = adp5589_read(kpad->client,
-					    ADP5589_GPIO_DIRECTION_A + i);
+	for (i = 0; i <= kpad->var->bank(kpad->var->maxgpio); i++) {
+		kpad->dat_out[i] = adp5589_read(kpad->client, kpad->var->reg(
+						ADP5589_GPO_DATA_OUT_A) + i);
+		kpad->dir[i] = adp5589_read(kpad->client, kpad->var->reg(
+					    ADP5589_GPIO_DIRECTION_A) + i);
 	}
 
 	if (gpio_data->setup) {
@@ -317,11 +603,11 @@
 	int i;
 
 	for (i = 0; i < ev_cnt; i++) {
-		int key = adp5589_read(kpad->client, ADP5589_FIFO_1 + i);
+		int key = adp5589_read(kpad->client, ADP5589_5_FIFO_1 + i);
 		int key_val = key & KEY_EV_MASK;
 
-		if (key_val >= ADP5589_GPI_PIN_BASE &&
-		    key_val <= ADP5589_GPI_PIN_END) {
+		if (key_val >= kpad->var->gpi_pin_base &&
+		    key_val <= kpad->var->gpi_pin_end) {
 			adp5589_report_switches(kpad, key, key_val);
 		} else {
 			input_report_key(kpad->input,
@@ -337,29 +623,30 @@
 	struct i2c_client *client = kpad->client;
 	int status, ev_cnt;
 
-	status = adp5589_read(client, ADP5589_INT_STATUS);
+	status = adp5589_read(client, ADP5589_5_INT_STATUS);
 
 	if (status & OVRFLOW_INT)	/* Unlikely and should never happen */
 		dev_err(&client->dev, "Event Overflow Error\n");
 
 	if (status & EVENT_INT) {
-		ev_cnt = adp5589_read(client, ADP5589_STATUS) & KEC;
+		ev_cnt = adp5589_read(client, ADP5589_5_STATUS) & KEC;
 		if (ev_cnt) {
 			adp5589_report_events(kpad, ev_cnt);
 			input_sync(kpad->input);
 		}
 	}
 
-	adp5589_write(client, ADP5589_INT_STATUS, status);	/* Status is W1C */
+	adp5589_write(client, ADP5589_5_INT_STATUS, status); /* Status is W1C */
 
 	return IRQ_HANDLED;
 }
 
-static int __devinit adp5589_get_evcode(struct adp5589_kpad *kpad, unsigned short key)
+static int __devinit adp5589_get_evcode(struct adp5589_kpad *kpad,
+					unsigned short key)
 {
 	int i;
 
-	for (i = 0; i < ADP5589_KEYMAPSIZE; i++)
+	for (i = 0; i < kpad->var->keymapsize; i++)
 		if (key == kpad->keycode[i])
 			return (i + 1) | KEY_EV_PRESSED;
 
@@ -372,19 +659,23 @@
 {
 	struct i2c_client *client = kpad->client;
 	const struct adp5589_kpad_platform_data *pdata =
-	    client->dev.platform_data;
-	int i, ret;
+		client->dev.platform_data;
+	u8 (*reg) (u8) = kpad->var->reg;
 	unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0;
 	unsigned char pull_mask = 0;
+	int i, ret;
 
-	ret = adp5589_write(client, ADP5589_PIN_CONFIG_A,
-			    pdata->keypad_en_mask & 0xFF);
-	ret |= adp5589_write(client, ADP5589_PIN_CONFIG_B,
-			     (pdata->keypad_en_mask >> 8) & 0xFF);
-	ret |= adp5589_write(client, ADP5589_PIN_CONFIG_C,
-			     (pdata->keypad_en_mask >> 16) & 0xFF);
+	ret = adp5589_write(client, reg(ADP5589_PIN_CONFIG_A),
+			    pdata->keypad_en_mask & kpad->var->row_mask);
+	ret |= adp5589_write(client, reg(ADP5589_PIN_CONFIG_B),
+			     (pdata->keypad_en_mask >> kpad->var->col_shift) &
+			     kpad->var->col_mask);
 
-	if (pdata->en_keylock) {
+	if (!kpad->is_adp5585)
+		ret |= adp5589_write(client, ADP5589_PIN_CONFIG_C,
+				     (pdata->keypad_en_mask >> 16) & 0xFF);
+
+	if (!kpad->is_adp5585 && pdata->en_keylock) {
 		ret |= adp5589_write(client, ADP5589_UNLOCK1,
 				     pdata->unlock_key1);
 		ret |= adp5589_write(client, ADP5589_UNLOCK2,
@@ -395,96 +686,130 @@
 	}
 
 	for (i = 0; i < KEYP_MAX_EVENT; i++)
-		ret |= adp5589_read(client, ADP5589_FIFO_1 + i);
+		ret |= adp5589_read(client, ADP5589_5_FIFO_1 + i);
 
 	for (i = 0; i < pdata->gpimapsize; i++) {
 		unsigned short pin = pdata->gpimap[i].pin;
 
-		if (pin <= ADP5589_GPI_PIN_ROW_END) {
-			evt_mode1 |= (1 << (pin - ADP5589_GPI_PIN_ROW_BASE));
+		if (pin <= kpad->var->gpi_pin_row_end) {
+			evt_mode1 |= (1 << (pin - kpad->var->gpi_pin_row_base));
 		} else {
 			evt_mode2 |=
-			    ((1 << (pin - ADP5589_GPI_PIN_COL_BASE)) & 0xFF);
-			evt_mode3 |=
-			    ((1 << (pin - ADP5589_GPI_PIN_COL_BASE)) >> 8);
+			    ((1 << (pin - kpad->var->gpi_pin_col_base)) & 0xFF);
+			if (!kpad->is_adp5585)
+				evt_mode3 |= ((1 << (pin -
+					kpad->var->gpi_pin_col_base)) >> 8);
 		}
 	}
 
 	if (pdata->gpimapsize) {
-		ret |= adp5589_write(client, ADP5589_GPI_EVENT_EN_A, evt_mode1);
-		ret |= adp5589_write(client, ADP5589_GPI_EVENT_EN_B, evt_mode2);
-		ret |= adp5589_write(client, ADP5589_GPI_EVENT_EN_C, evt_mode3);
+		ret |= adp5589_write(client, reg(ADP5589_GPI_EVENT_EN_A),
+				     evt_mode1);
+		ret |= adp5589_write(client, reg(ADP5589_GPI_EVENT_EN_B),
+				     evt_mode2);
+		if (!kpad->is_adp5585)
+			ret |= adp5589_write(client,
+					     reg(ADP5589_GPI_EVENT_EN_C),
+					     evt_mode3);
 	}
 
 	if (pdata->pull_dis_mask & pdata->pullup_en_100k &
-	    pdata->pullup_en_300k & pdata->pulldown_en_300k)
+		pdata->pullup_en_300k & pdata->pulldown_en_300k)
 		dev_warn(&client->dev, "Conflicting pull resistor config\n");
 
-	for (i = 0; i < MAXGPIO; i++) {
-		unsigned val = 0;
+	for (i = 0; i <= kpad->var->max_row_num; i++) {
+		unsigned val = 0, bit = (1 << i);
+		if (pdata->pullup_en_300k & bit)
+			val = 0;
+		else if (pdata->pulldown_en_300k & bit)
+			val = 1;
+		else if (pdata->pullup_en_100k & bit)
+			val = 2;
+		else if (pdata->pull_dis_mask & bit)
+			val = 3;
 
-		if (pdata->pullup_en_300k & (1 << i))
+		pull_mask |= val << (2 * (i & 0x3));
+
+		if (i == 3 || i == kpad->var->max_row_num) {
+			ret |= adp5589_write(client, reg(ADP5585_RPULL_CONFIG_A)
+					     + (i >> 2), pull_mask);
+			pull_mask = 0;
+		}
+	}
+
+	for (i = 0; i <= kpad->var->max_col_num; i++) {
+		unsigned val = 0, bit = 1 << (i + kpad->var->col_shift);
+		if (pdata->pullup_en_300k & bit)
 			val = 0;
-		else if (pdata->pulldown_en_300k & (1 << i))
+		else if (pdata->pulldown_en_300k & bit)
 			val = 1;
-		else if (pdata->pullup_en_100k & (1 << i))
+		else if (pdata->pullup_en_100k & bit)
 			val = 2;
-		else if (pdata->pull_dis_mask & (1 << i))
+		else if (pdata->pull_dis_mask & bit)
 			val = 3;
 
 		pull_mask |= val << (2 * (i & 0x3));
 
-		if ((i & 0x3) == 0x3 || i == MAXGPIO - 1) {
+		if (i == 3 || i == kpad->var->max_col_num) {
 			ret |= adp5589_write(client,
-					     ADP5589_RPULL_CONFIG_A + (i >> 2),
-					     pull_mask);
+					     reg(ADP5585_RPULL_CONFIG_C) +
+					     (i >> 2), pull_mask);
 			pull_mask = 0;
 		}
 	}
 
 	if (pdata->reset1_key_1 && pdata->reset1_key_2 && pdata->reset1_key_3) {
-		ret |= adp5589_write(client, ADP5589_RESET1_EVENT_A,
+		ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_A),
 				     adp5589_get_evcode(kpad,
 							pdata->reset1_key_1));
-		ret |= adp5589_write(client, ADP5589_RESET1_EVENT_B,
+		ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_B),
 				     adp5589_get_evcode(kpad,
 							pdata->reset1_key_2));
-		ret |= adp5589_write(client, ADP5589_RESET1_EVENT_C,
+		ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_C),
 				     adp5589_get_evcode(kpad,
 							pdata->reset1_key_3));
 		kpad->extend_cfg |= R4_EXTEND_CFG;
 	}
 
 	if (pdata->reset2_key_1 && pdata->reset2_key_2) {
-		ret |= adp5589_write(client, ADP5589_RESET2_EVENT_A,
+		ret |= adp5589_write(client, reg(ADP5589_RESET2_EVENT_A),
 				     adp5589_get_evcode(kpad,
 							pdata->reset2_key_1));
-		ret |= adp5589_write(client, ADP5589_RESET2_EVENT_B,
+		ret |= adp5589_write(client, reg(ADP5589_RESET2_EVENT_B),
 				     adp5589_get_evcode(kpad,
 							pdata->reset2_key_2));
 		kpad->extend_cfg |= C4_EXTEND_CFG;
 	}
 
 	if (kpad->extend_cfg) {
-		ret |= adp5589_write(client, ADP5589_RESET_CFG,
+		ret |= adp5589_write(client, reg(ADP5589_RESET_CFG),
 				     pdata->reset_cfg);
-		ret |= adp5589_write(client, ADP5589_PIN_CONFIG_D,
+		ret |= adp5589_write(client, reg(ADP5589_PIN_CONFIG_D),
 				     kpad->extend_cfg);
 	}
 
-	for (i = 0; i <= ADP_BANK(MAXGPIO); i++)
-		ret |= adp5589_write(client, ADP5589_DEBOUNCE_DIS_A + i,
-				     pdata->debounce_dis_mask >> (i * 8));
+	ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_A),
+			    pdata->debounce_dis_mask & kpad->var->row_mask);
 
-	ret |= adp5589_write(client, ADP5589_POLL_PTIME_CFG,
+	ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_B),
+			     (pdata->debounce_dis_mask >> kpad->var->col_shift)
+			     & kpad->var->col_mask);
+
+	if (!kpad->is_adp5585)
+		ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_C),
+				     (pdata->debounce_dis_mask >> 16) & 0xFF);
+
+	ret |= adp5589_write(client, reg(ADP5589_POLL_PTIME_CFG),
 			     pdata->scan_cycle_time & PTIME_MASK);
-	ret |= adp5589_write(client, ADP5589_INT_STATUS, LOGIC2_INT |
-			     LOGIC1_INT | OVRFLOW_INT | LOCK_INT |
+	ret |= adp5589_write(client, ADP5589_5_INT_STATUS,
+			     (kpad->is_adp5585 ? 0 : LOGIC2_INT) |
+			     LOGIC1_INT | OVRFLOW_INT |
+			     (kpad->is_adp5585 ? 0 : LOCK_INT) |
 			     GPI_INT | EVENT_INT);	/* Status is W1C */
 
-	ret |= adp5589_write(client, ADP5589_GENERAL_CFG,
+	ret |= adp5589_write(client, reg(ADP5589_GENERAL_CFG),
 			     INT_CFG | OSC_EN | CORE_CLK(3));
-	ret |= adp5589_write(client, ADP5589_INT_EN,
+	ret |= adp5589_write(client, reg(ADP5589_INT_EN),
 			     OVRFLOW_IEN | GPI_IEN | EVENT_IEN);
 
 	if (ret < 0) {
@@ -497,30 +822,33 @@
 
 static void __devinit adp5589_report_switch_state(struct adp5589_kpad *kpad)
 {
-	int gpi_stat1 = adp5589_read(kpad->client, ADP5589_GPI_STATUS_A);
-	int gpi_stat2 = adp5589_read(kpad->client, ADP5589_GPI_STATUS_B);
-	int gpi_stat3 = adp5589_read(kpad->client, ADP5589_GPI_STATUS_C);
 	int gpi_stat_tmp, pin_loc;
 	int i;
+	int gpi_stat1 = adp5589_read(kpad->client,
+				     kpad->var->reg(ADP5589_GPI_STATUS_A));
+	int gpi_stat2 = adp5589_read(kpad->client,
+				     kpad->var->reg(ADP5589_GPI_STATUS_B));
+	int gpi_stat3 = !kpad->is_adp5585 ?
+			adp5589_read(kpad->client, ADP5589_GPI_STATUS_C) : 0;
 
 	for (i = 0; i < kpad->gpimapsize; i++) {
 		unsigned short pin = kpad->gpimap[i].pin;
 
-		if (pin <= ADP5589_GPI_PIN_ROW_END) {
+		if (pin <= kpad->var->gpi_pin_row_end) {
 			gpi_stat_tmp = gpi_stat1;
-			pin_loc = pin - ADP5589_GPI_PIN_ROW_BASE;
-		} else if ((pin - ADP5589_GPI_PIN_COL_BASE) < 8) {
+			pin_loc = pin - kpad->var->gpi_pin_row_base;
+		} else if ((pin - kpad->var->gpi_pin_col_base) < 8) {
 			gpi_stat_tmp = gpi_stat2;
-			pin_loc = pin - ADP5589_GPI_PIN_COL_BASE;
+			pin_loc = pin - kpad->var->gpi_pin_col_base;
 		} else {
 			gpi_stat_tmp = gpi_stat3;
-			pin_loc = pin - ADP5589_GPI_PIN_COL_BASE - 8;
+			pin_loc = pin - kpad->var->gpi_pin_col_base - 8;
 		}
 
 		if (gpi_stat_tmp < 0) {
 			dev_err(&kpad->client->dev,
-				"Can't read GPIO_DAT_STAT switch"
-				" %d default to OFF\n", pin);
+				"Can't read GPIO_DAT_STAT switch %d, default to OFF\n",
+				pin);
 			gpi_stat_tmp = 0;
 		}
 
@@ -536,7 +864,8 @@
 				   const struct i2c_device_id *id)
 {
 	struct adp5589_kpad *kpad;
-	const struct adp5589_kpad_platform_data *pdata;
+	const struct adp5589_kpad_platform_data *pdata =
+		client->dev.platform_data;
 	struct input_dev *input;
 	unsigned int revid;
 	int ret, i;
@@ -548,56 +877,79 @@
 		return -EIO;
 	}
 
-	pdata = client->dev.platform_data;
 	if (!pdata) {
 		dev_err(&client->dev, "no platform data?\n");
 		return -EINVAL;
 	}
 
-	if (!((pdata->keypad_en_mask & 0xFF) &&
-			(pdata->keypad_en_mask >> 8)) || !pdata->keymap) {
+	kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
+	if (!kpad)
+		return -ENOMEM;
+
+	switch (id->driver_data) {
+	case ADP5585_02:
+		kpad->adp5585_support_row5 = true;
+	case ADP5585_01:
+		kpad->is_adp5585 = true;
+		kpad->var = &const_adp5585;
+		break;
+	case ADP5589:
+		kpad->var = &const_adp5589;
+		break;
+	}
+
+	if (!((pdata->keypad_en_mask & kpad->var->row_mask) &&
+			(pdata->keypad_en_mask >> kpad->var->col_shift)) ||
+			!pdata->keymap) {
 		dev_err(&client->dev, "no rows, cols or keymap from pdata\n");
-		return -EINVAL;
+		error = -EINVAL;
+		goto err_free_mem;
 	}
 
-	if (pdata->keymapsize != ADP5589_KEYMAPSIZE) {
+	if (pdata->keymapsize != kpad->var->keymapsize) {
 		dev_err(&client->dev, "invalid keymapsize\n");
-		return -EINVAL;
+		error = -EINVAL;
+		goto err_free_mem;
 	}
 
 	if (!pdata->gpimap && pdata->gpimapsize) {
 		dev_err(&client->dev, "invalid gpimap from pdata\n");
-		return -EINVAL;
+		error = -EINVAL;
+		goto err_free_mem;
 	}
 
-	if (pdata->gpimapsize > ADP5589_GPIMAPSIZE_MAX) {
+	if (pdata->gpimapsize > kpad->var->gpimapsize_max) {
 		dev_err(&client->dev, "invalid gpimapsize\n");
-		return -EINVAL;
+		error = -EINVAL;
+		goto err_free_mem;
 	}
 
 	for (i = 0; i < pdata->gpimapsize; i++) {
 		unsigned short pin = pdata->gpimap[i].pin;
 
-		if (pin < ADP5589_GPI_PIN_BASE || pin > ADP5589_GPI_PIN_END) {
+		if (pin < kpad->var->gpi_pin_base ||
+				pin > kpad->var->gpi_pin_end) {
 			dev_err(&client->dev, "invalid gpi pin data\n");
-			return -EINVAL;
+			error = -EINVAL;
+			goto err_free_mem;
 		}
 
-		if ((1 << (pin - ADP5589_GPI_PIN_ROW_BASE)) &
+		if ((1 << (pin - kpad->var->gpi_pin_row_base)) &
 				pdata->keypad_en_mask) {
 			dev_err(&client->dev, "invalid gpi row/col data\n");
-			return -EINVAL;
+			error = -EINVAL;
+			goto err_free_mem;
 		}
 	}
 
 	if (!client->irq) {
 		dev_err(&client->dev, "no IRQ?\n");
-		return -EINVAL;
+		error = -EINVAL;
+		goto err_free_mem;
 	}
 
-	kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
 	input = input_allocate_device();
-	if (!kpad || !input) {
+	if (!input) {
 		error = -ENOMEM;
 		goto err_free_mem;
 	}
@@ -605,13 +957,13 @@
 	kpad->client = client;
 	kpad->input = input;
 
-	ret = adp5589_read(client, ADP5589_ID);
+	ret = adp5589_read(client, ADP5589_5_ID);
 	if (ret < 0) {
 		error = ret;
-		goto err_free_mem;
+		goto err_free_input;
 	}
 
-	revid = (u8) ret & ADP5589_DEVICE_ID_MASK;
+	revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK;
 
 	input->name = client->name;
 	input->phys = "adp5589-keys/input0";
@@ -652,7 +1004,7 @@
 	error = input_register_device(input);
 	if (error) {
 		dev_err(&client->dev, "unable to register input device\n");
-		goto err_free_mem;
+		goto err_free_input;
 	}
 
 	error = request_threaded_irq(client->irq, NULL, adp5589_irq,
@@ -685,8 +1037,9 @@
 err_unreg_dev:
 	input_unregister_device(input);
 	input = NULL;
-err_free_mem:
+err_free_input:
 	input_free_device(input);
+err_free_mem:
 	kfree(kpad);
 
 	return error;
@@ -696,7 +1049,7 @@
 {
 	struct adp5589_kpad *kpad = i2c_get_clientdata(client);
 
-	adp5589_write(client, ADP5589_GENERAL_CFG, 0);
+	adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
 	free_irq(client->irq, kpad);
 	input_unregister_device(kpad->input);
 	adp5589_gpio_remove(kpad);
@@ -736,7 +1089,9 @@
 static SIMPLE_DEV_PM_OPS(adp5589_dev_pm_ops, adp5589_suspend, adp5589_resume);
 
 static const struct i2c_device_id adp5589_id[] = {
-	{"adp5589-keys", 0},
+	{"adp5589-keys", ADP5589},
+	{"adp5585-keys", ADP5585_01},
+	{"adp5585-02-keys", ADP5585_02}, /* Adds ROW5 to ADP5585 */
 	{}
 };
 
@@ -767,4 +1122,4 @@
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("ADP5589 Keypad driver");
+MODULE_DESCRIPTION("ADP5589/ADP5585 Keypad driver");
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/davinci_keyscan.c linux-libre-3.2-gnu/drivers/input/keyboard/davinci_keyscan.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/davinci_keyscan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/davinci_keyscan.c	2012-01-04 18:55:44.000000000 -0500
@@ -271,7 +271,7 @@
 	}
 
 	error = request_irq(davinci_ks->irq, davinci_ks_interrupt,
-			  IRQF_DISABLED, pdev->name, davinci_ks);
+			  0, pdev->name, davinci_ks);
 	if (error < 0) {
 		dev_err(dev, "unable to register davinci key scan interrupt\n");
 		goto fail5;
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/ep93xx_keypad.c linux-libre-3.2-gnu/drivers/input/keyboard/ep93xx_keypad.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/ep93xx_keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/ep93xx_keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -323,7 +323,7 @@
 	platform_set_drvdata(pdev, keypad);
 
 	err = request_irq(keypad->irq, ep93xx_keypad_irq_handler,
-			  IRQF_DISABLED, pdev->name, keypad);
+			  0, pdev->name, keypad);
 	if (err)
 		goto failed_free_dev;
 
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/gpio_keys.c linux-libre-3.2-gnu/drivers/input/keyboard/gpio_keys.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/gpio_keys.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/gpio_keys.c	2012-01-04 18:55:44.000000000 -0500
@@ -461,8 +461,7 @@
 	struct device_node *node, *pp;
 	int i;
 	struct gpio_keys_button *buttons;
-	const u32 *reg;
-	int len;
+	u32 reg;
 
 	node = dev->of_node;
 	if (node == NULL)
@@ -470,7 +469,7 @@
 
 	memset(pdata, 0, sizeof *pdata);
 
-	pdata->rep = !!of_get_property(node, "autorepeat", &len);
+	pdata->rep = !!of_get_property(node, "autorepeat", NULL);
 
 	/* First count the subnodes */
 	pdata->nbuttons = 0;
@@ -498,22 +497,25 @@
 		buttons[i].gpio = of_get_gpio_flags(pp, 0, &flags);
 		buttons[i].active_low = flags & OF_GPIO_ACTIVE_LOW;
 
-		reg = of_get_property(pp, "linux,code", &len);
-		if (!reg) {
+		if (of_property_read_u32(pp, "linux,code", &reg)) {
 			dev_err(dev, "Button without keycode: 0x%x\n", buttons[i].gpio);
 			goto out_fail;
 		}
-		buttons[i].code = be32_to_cpup(reg);
+		buttons[i].code = reg;
 
-		buttons[i].desc = of_get_property(pp, "label", &len);
+		buttons[i].desc = of_get_property(pp, "label", NULL);
 
-		reg = of_get_property(pp, "linux,input-type", &len);
-		buttons[i].type = reg ? be32_to_cpup(reg) : EV_KEY;
+		if (of_property_read_u32(pp, "linux,input-type", &reg) == 0)
+			buttons[i].type = reg;
+		else
+			buttons[i].type = EV_KEY;
 
 		buttons[i].wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
 
-		reg = of_get_property(pp, "debounce-interval", &len);
-		buttons[i].debounce_interval = reg ? be32_to_cpup(reg) : 5;
+		if (of_property_read_u32(pp, "debounce-interval", &reg) == 0)
+			buttons[i].debounce_interval = reg;
+		else
+			buttons[i].debounce_interval = 5;
 
 		i++;
 	}
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/imx_keypad.c linux-libre-3.2-gnu/drivers/input/keyboard/imx_keypad.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/imx_keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/imx_keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -510,7 +510,7 @@
 	/* Ensure that the keypad will stay dormant until opened */
 	imx_keypad_inhibit(keypad);
 
-	error = request_irq(irq, imx_keypad_irq_handler, IRQF_DISABLED,
+	error = request_irq(irq, imx_keypad_irq_handler, 0,
 			    pdev->name, keypad);
 	if (error) {
 		dev_err(&pdev->dev, "failed to request IRQ\n");
@@ -567,10 +567,54 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int imx_kbd_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct imx_keypad *kbd = platform_get_drvdata(pdev);
+	struct input_dev *input_dev = kbd->input_dev;
+
+	/* imx kbd can wake up system even clock is disabled */
+	mutex_lock(&input_dev->mutex);
+
+	if (input_dev->users)
+		clk_disable(kbd->clk);
+
+	mutex_unlock(&input_dev->mutex);
+
+	if (device_may_wakeup(&pdev->dev))
+		enable_irq_wake(kbd->irq);
+
+	return 0;
+}
+
+static int imx_kbd_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct imx_keypad *kbd = platform_get_drvdata(pdev);
+	struct input_dev *input_dev = kbd->input_dev;
+
+	if (device_may_wakeup(&pdev->dev))
+		disable_irq_wake(kbd->irq);
+
+	mutex_lock(&input_dev->mutex);
+
+	if (input_dev->users)
+		clk_enable(kbd->clk);
+
+	mutex_unlock(&input_dev->mutex);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(imx_kbd_pm_ops, imx_kbd_suspend, imx_kbd_resume);
+
 static struct platform_driver imx_keypad_driver = {
 	.driver		= {
 		.name	= "imx-keypad",
 		.owner	= THIS_MODULE,
+		.pm	= &imx_kbd_pm_ops,
 	},
 	.probe		= imx_keypad_probe,
 	.remove		= __devexit_p(imx_keypad_remove),
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/jornada720_kbd.c linux-libre-3.2-gnu/drivers/input/keyboard/jornada720_kbd.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/jornada720_kbd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/jornada720_kbd.c	2012-01-04 18:55:44.000000000 -0500
@@ -129,7 +129,7 @@
 
 	err = request_irq(IRQ_GPIO0,
 			  jornada720_kbd_interrupt,
-			  IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+			  IRQF_TRIGGER_FALLING,
 			  "jornadakbd", pdev);
 	if (err) {
 		printk(KERN_INFO "jornadakbd720_kbd: Unable to grab IRQ\n");
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/Kconfig linux-libre-3.2-gnu/drivers/input/keyboard/Kconfig
--- linux-libre-3.1-gnu/drivers/input/keyboard/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -33,10 +33,10 @@
 	  module will be called adp5588-keys.
 
 config KEYBOARD_ADP5589
-	tristate "ADP5589 I2C QWERTY Keypad and IO Expander"
+	tristate "ADP5585/ADP5589 I2C QWERTY Keypad and IO Expander"
 	depends on I2C
 	help
-	  Say Y here if you want to use a ADP5589 attached to your
+	  Say Y here if you want to use a ADP5585/ADP5589 attached to your
 	  system I2C bus.
 
 	  To compile this driver as a module, choose M here: the
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/lm8323.c linux-libre-3.2-gnu/drivers/input/keyboard/lm8323.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/lm8323.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/lm8323.c	2012-01-04 18:55:44.000000000 -0500
@@ -788,7 +788,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 /*
  * We don't need to explicitly suspend the chip, as it already switches off
  * when there's no activity.
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/matrix_keypad.c linux-libre-3.2-gnu/drivers/input/keyboard/matrix_keypad.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/matrix_keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/matrix_keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -343,7 +343,6 @@
 		for (i = 0; i < pdata->num_row_gpios; i++) {
 			err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
 					matrix_keypad_interrupt,
-					IRQF_DISABLED |
 					IRQF_TRIGGER_RISING |
 					IRQF_TRIGGER_FALLING,
 					"matrix-keypad", keypad);
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/nomadik-ske-keypad.c linux-libre-3.2-gnu/drivers/input/keyboard/nomadik-ske-keypad.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/nomadik-ske-keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/nomadik-ske-keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/input.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
+#include <linux/module.h>
 
 #include <plat/ske.h>
 
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/omap-keypad.c linux-libre-3.2-gnu/drivers/input/keyboard/omap-keypad.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/omap-keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/omap-keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,7 +35,7 @@
 #include <linux/mutex.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
 #include <plat/keypad.h>
 #include <plat/menelaus.h>
 #include <asm/irq.h>
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/pxa27x_keypad.c linux-libre-3.2-gnu/drivers/input/keyboard/pxa27x_keypad.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/pxa27x_keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/pxa27x_keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -535,7 +535,7 @@
 		input_dev->evbit[0] |= BIT_MASK(EV_REL);
 	}
 
-	error = request_irq(irq, pxa27x_keypad_irq_handler, IRQF_DISABLED,
+	error = request_irq(irq, pxa27x_keypad_irq_handler, 0,
 			    pdev->name, keypad);
 	if (error) {
 		dev_err(&pdev->dev, "failed to request IRQ\n");
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/pxa930_rotary.c linux-libre-3.2-gnu/drivers/input/keyboard/pxa930_rotary.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/pxa930_rotary.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/pxa930_rotary.c	2012-01-04 18:55:44.000000000 -0500
@@ -148,7 +148,7 @@
 	r->input_dev = input_dev;
 	input_set_drvdata(input_dev, r);
 
-	err = request_irq(irq, rotary_irq, IRQF_DISABLED,
+	err = request_irq(irq, rotary_irq, 0,
 			"enhanced rotary", r);
 	if (err) {
 		dev_err(&pdev->dev, "failed to request IRQ\n");
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/tc3589x-keypad.c linux-libre-3.2-gnu/drivers/input/keyboard/tc3589x-keypad.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/tc3589x-keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/tc3589x-keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -90,7 +90,7 @@
 	bool keypad_stopped;
 };
 
-static int __devinit tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad)
+static int tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad)
 {
 	int ret;
 	struct tc3589x *tc3589x = keypad->tc3589x;
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/tegra-kbc.c linux-libre-3.2-gnu/drivers/input/keyboard/tegra-kbc.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/tegra-kbc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/tegra-kbc.c	2012-01-04 18:55:44.000000000 -0500
@@ -55,6 +55,7 @@
 
 #define KBC_ROW_CFG0_0	0x8
 #define KBC_COL_CFG0_0	0x18
+#define KBC_TO_CNT_0	0x24
 #define KBC_INIT_DLY_0	0x28
 #define KBC_RPT_DLY_0	0x2c
 #define KBC_KP_ENT0_0	0x30
@@ -70,6 +71,7 @@
 	spinlock_t lock;
 	unsigned int repoll_dly;
 	unsigned long cp_dly_jiffies;
+	unsigned int cp_to_wkup_dly;
 	bool use_fn_map;
 	bool use_ghost_filter;
 	const struct tegra_kbc_platform_data *pdata;
@@ -258,12 +260,10 @@
 	u32 val = 0;
 	unsigned int i;
 	unsigned int num_down = 0;
-	unsigned long flags;
 	bool fn_keypress = false;
 	bool key_in_same_row = false;
 	bool key_in_same_col = false;
 
-	spin_lock_irqsave(&kbc->lock, flags);
 	for (i = 0; i < KBC_MAX_KPENT; i++) {
 		if ((i % 4) == 0)
 			val = readl(kbc->mmio + KBC_KP_ENT0_0 + i);
@@ -292,7 +292,7 @@
 	 * any 2 of the 3 keys share a row, and any 2 of them share a column.
 	 * If so ignore the key presses for this iteration.
 	 */
-	if ((kbc->use_ghost_filter) && (num_down >= 3)) {
+	if (kbc->use_ghost_filter && num_down >= 3) {
 		for (i = 0; i < num_down; i++) {
 			unsigned int j;
 			u8 curr_col = scancodes[i] & 0x07;
@@ -325,8 +325,6 @@
 		}
 	}
 
-	spin_unlock_irqrestore(&kbc->lock, flags);
-
 	/* Ignore the key presses for this iteration? */
 	if (key_in_same_col && key_in_same_row)
 		return;
@@ -341,6 +339,18 @@
 	kbc->num_pressed_keys = num_down;
 }
 
+static void tegra_kbc_set_fifo_interrupt(struct tegra_kbc *kbc, bool enable)
+{
+	u32 val;
+
+	val = readl(kbc->mmio + KBC_CONTROL_0);
+	if (enable)
+		val |= KBC_CONTROL_FIFO_CNT_INT_EN;
+	else
+		val &= ~KBC_CONTROL_FIFO_CNT_INT_EN;
+	writel(val, kbc->mmio + KBC_CONTROL_0);
+}
+
 static void tegra_kbc_keypress_timer(unsigned long data)
 {
 	struct tegra_kbc *kbc = (struct tegra_kbc *)data;
@@ -348,6 +358,8 @@
 	u32 val;
 	unsigned int i;
 
+	spin_lock_irqsave(&kbc->lock, flags);
+
 	val = (readl(kbc->mmio + KBC_INT_0) >> 4) & 0xf;
 	if (val) {
 		unsigned long dly;
@@ -369,26 +381,19 @@
 		kbc->num_pressed_keys = 0;
 
 		/* All keys are released so enable the keypress interrupt */
-		spin_lock_irqsave(&kbc->lock, flags);
-		val = readl(kbc->mmio + KBC_CONTROL_0);
-		val |= KBC_CONTROL_FIFO_CNT_INT_EN;
-		writel(val, kbc->mmio + KBC_CONTROL_0);
-		spin_unlock_irqrestore(&kbc->lock, flags);
+		tegra_kbc_set_fifo_interrupt(kbc, true);
 	}
+
+	spin_unlock_irqrestore(&kbc->lock, flags);
 }
 
 static irqreturn_t tegra_kbc_isr(int irq, void *args)
 {
 	struct tegra_kbc *kbc = args;
-	u32 val, ctl;
+	unsigned long flags;
+	u32 val;
 
-	/*
-	 * Until all keys are released, defer further processing to
-	 * the polling loop in tegra_kbc_keypress_timer
-	 */
-	ctl = readl(kbc->mmio + KBC_CONTROL_0);
-	ctl &= ~KBC_CONTROL_FIFO_CNT_INT_EN;
-	writel(ctl, kbc->mmio + KBC_CONTROL_0);
+	spin_lock_irqsave(&kbc->lock, flags);
 
 	/*
 	 * Quickly bail out & reenable interrupts if the fifo threshold
@@ -399,15 +404,15 @@
 
 	if (val & KBC_INT_FIFO_CNT_INT_STATUS) {
 		/*
-		 * Schedule timer to run when hardware is in continuous
-		 * polling mode.
+		 * Until all keys are released, defer further processing to
+		 * the polling loop in tegra_kbc_keypress_timer.
 		 */
+		tegra_kbc_set_fifo_interrupt(kbc, false);
 		mod_timer(&kbc->timer, jiffies + kbc->cp_dly_jiffies);
-	} else {
-		ctl |= KBC_CONTROL_FIFO_CNT_INT_EN;
-		writel(ctl, kbc->mmio + KBC_CONTROL_0);
 	}
 
+	spin_unlock_irqrestore(&kbc->lock, flags);
+
 	return IRQ_HANDLED;
 }
 
@@ -455,7 +460,6 @@
 static int tegra_kbc_start(struct tegra_kbc *kbc)
 {
 	const struct tegra_kbc_platform_data *pdata = kbc->pdata;
-	unsigned long flags;
 	unsigned int debounce_cnt;
 	u32 val = 0;
 
@@ -493,7 +497,6 @@
 	 * Atomically clear out any remaining entries in the key FIFO
 	 * and enable keyboard interrupts.
 	 */
-	spin_lock_irqsave(&kbc->lock, flags);
 	while (1) {
 		val = readl(kbc->mmio + KBC_INT_0);
 		val >>= 4;
@@ -504,7 +507,6 @@
 		val = readl(kbc->mmio + KBC_KP_ENT1_0);
 	}
 	writel(0x7, kbc->mmio + KBC_INT_0);
-	spin_unlock_irqrestore(&kbc->lock, flags);
 
 	enable_irq(kbc->irq);
 
@@ -734,18 +736,30 @@
 	struct platform_device *pdev = to_platform_device(dev);
 	struct tegra_kbc *kbc = platform_get_drvdata(pdev);
 
+	mutex_lock(&kbc->idev->mutex);
 	if (device_may_wakeup(&pdev->dev)) {
-		tegra_kbc_setup_wakekeys(kbc, true);
-		enable_irq_wake(kbc->irq);
+		disable_irq(kbc->irq);
+		del_timer_sync(&kbc->timer);
+		tegra_kbc_set_fifo_interrupt(kbc, false);
+
 		/* Forcefully clear the interrupt status */
 		writel(0x7, kbc->mmio + KBC_INT_0);
+		/*
+		 * Store the previous resident time of continuous polling mode.
+		 * Force the keyboard into interrupt mode.
+		 */
+		kbc->cp_to_wkup_dly = readl(kbc->mmio + KBC_TO_CNT_0);
+		writel(0, kbc->mmio + KBC_TO_CNT_0);
+
+		tegra_kbc_setup_wakekeys(kbc, true);
 		msleep(30);
+
+		enable_irq_wake(kbc->irq);
 	} else {
-		mutex_lock(&kbc->idev->mutex);
 		if (kbc->idev->users)
 			tegra_kbc_stop(kbc);
-		mutex_unlock(&kbc->idev->mutex);
 	}
+	mutex_unlock(&kbc->idev->mutex);
 
 	return 0;
 }
@@ -756,15 +770,22 @@
 	struct tegra_kbc *kbc = platform_get_drvdata(pdev);
 	int err = 0;
 
+	mutex_lock(&kbc->idev->mutex);
 	if (device_may_wakeup(&pdev->dev)) {
 		disable_irq_wake(kbc->irq);
 		tegra_kbc_setup_wakekeys(kbc, false);
+
+		/* Restore the resident time of continuous polling mode. */
+		writel(kbc->cp_to_wkup_dly, kbc->mmio + KBC_TO_CNT_0);
+
+		tegra_kbc_set_fifo_interrupt(kbc, true);
+
+		enable_irq(kbc->irq);
 	} else {
-		mutex_lock(&kbc->idev->mutex);
 		if (kbc->idev->users)
 			err = tegra_kbc_start(kbc);
-		mutex_unlock(&kbc->idev->mutex);
 	}
+	mutex_unlock(&kbc->idev->mutex);
 
 	return err;
 }
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/tnetv107x-keypad.c linux-libre-3.2-gnu/drivers/input/keyboard/tnetv107x-keypad.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/tnetv107x-keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/tnetv107x-keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/input/matrix_keypad.h>
+#include <linux/module.h>
 
 #define BITS(x)			(BIT(x) - 1)
 
diff -druN linux-libre-3.1-gnu/drivers/input/keyboard/w90p910_keypad.c linux-libre-3.2-gnu/drivers/input/keyboard/w90p910_keypad.c
--- linux-libre-3.1-gnu/drivers/input/keyboard/w90p910_keypad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/keyboard/w90p910_keypad.c	2012-01-04 18:55:44.000000000 -0500
@@ -203,7 +203,7 @@
 				   input_dev->keycode, input_dev->keybit);
 
 	error = request_irq(keypad->irq, w90p910_keypad_irq_handler,
-			    IRQF_DISABLED, pdev->name, keypad);
+			    0, pdev->name, keypad);
 	if (error) {
 		dev_err(&pdev->dev, "failed to request IRQ\n");
 		goto failed_put_clk;
diff -druN linux-libre-3.1-gnu/drivers/input/misc/ad714x.c linux-libre-3.2-gnu/drivers/input/misc/ad714x.c
--- linux-libre-3.1-gnu/drivers/input/misc/ad714x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/misc/ad714x.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/input/ad714x.h>
+#include <linux/module.h>
 #include "ad714x.h"
 
 #define AD714X_PWR_CTRL           0x0
diff -druN linux-libre-3.1-gnu/drivers/input/misc/ad714x-i2c.c linux-libre-3.2-gnu/drivers/input/misc/ad714x-i2c.c
--- linux-libre-3.1-gnu/drivers/input/misc/ad714x-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/misc/ad714x-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -116,13 +116,13 @@
 	.id_table = ad714x_id,
 };
 
-static __init int ad714x_i2c_init(void)
+static int __init ad714x_i2c_init(void)
 {
 	return i2c_add_driver(&ad714x_i2c_driver);
 }
 module_init(ad714x_i2c_init);
 
-static __exit void ad714x_i2c_exit(void)
+static void __exit ad714x_i2c_exit(void)
 {
 	i2c_del_driver(&ad714x_i2c_driver);
 }
diff -druN linux-libre-3.1-gnu/drivers/input/misc/adxl34x.c linux-libre-3.2-gnu/drivers/input/misc/adxl34x.c
--- linux-libre-3.1-gnu/drivers/input/misc/adxl34x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/misc/adxl34x.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/input/adxl34x.h>
+#include <linux/module.h>
 
 #include "adxl34x.h"
 
diff -druN linux-libre-3.1-gnu/drivers/input/misc/ati_remote2.c linux-libre-3.2-gnu/drivers/input/misc/ati_remote2.c
--- linux-libre-3.1-gnu/drivers/input/misc/ati_remote2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/misc/ati_remote2.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 
 #include <linux/usb/input.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define DRIVER_DESC    "ATI/Philips USB RF remote driver"
 #define DRIVER_VERSION "0.3"
diff -druN linux-libre-3.1-gnu/drivers/input/misc/ati_remote.c linux-libre-3.2-gnu/drivers/input/misc/ati_remote.c
--- linux-libre-3.1-gnu/drivers/input/misc/ati_remote.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/misc/ati_remote.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,867 +0,0 @@
-/*
- *  USB ATI Remote support
- *
- *  Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net>
- *  Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev
- *
- *  This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including
- *  porting to the 2.6 kernel interfaces, along with other modification
- *  to better match the style of the existing usb/input drivers.  However, the
- *  protocol and hardware handling is essentially unchanged from 2.1.1.
- *
- *  The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by
- *  Vojtech Pavlik.
- *
- *  Changes:
- *
- *  Feb 2004: Torrey Hoffman <thoffman@arnor.net>
- *            Version 2.2.0
- *  Jun 2004: Torrey Hoffman <thoffman@arnor.net>
- *            Version 2.2.1
- *            Added key repeat support contributed by:
- *                Vincent Vanackere <vanackere@lif.univ-mrs.fr>
- *            Added support for the "Lola" remote contributed by:
- *                Seth Cohn <sethcohn@yahoo.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
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * Hardware & software notes
- *
- * These remote controls are distributed by ATI as part of their
- * "All-In-Wonder" video card packages.  The receiver self-identifies as a
- * "USB Receiver" with manufacturer "X10 Wireless Technology Inc".
- *
- * The "Lola" remote is available from X10.  See:
- *    http://www.x10.com/products/lola_sg1.htm
- * The Lola is similar to the ATI remote but has no mouse support, and slightly
- * different keys.
- *
- * It is possible to use multiple receivers and remotes on multiple computers
- * simultaneously by configuring them to use specific channels.
- *
- * The RF protocol used by the remote supports 16 distinct channels, 1 to 16.
- * Actually, it may even support more, at least in some revisions of the
- * hardware.
- *
- * Each remote can be configured to transmit on one channel as follows:
- *   - Press and hold the "hand icon" button.
- *   - When the red LED starts to blink, let go of the "hand icon" button.
- *   - When it stops blinking, input the channel code as two digits, from 01
- *     to 16, and press the hand icon again.
- *
- * The timing can be a little tricky.  Try loading the module with debug=1
- * to have the kernel print out messages about the remote control number
- * and mask.  Note: debugging prints remote numbers as zero-based hexadecimal.
- *
- * The driver has a "channel_mask" parameter. This bitmask specifies which
- * channels will be ignored by the module.  To mask out channels, just add
- * all the 2^channel_number values together.
- *
- * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote
- * ignore signals coming from remote controls transmitting on channel 4, but
- * accept all other channels.
- *
- * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be
- * ignored.
- *
- * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this
- * parameter are unused.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/usb/input.h>
-#include <linux/wait.h>
-#include <linux/jiffies.h>
-
-/*
- * Module and Version Information, Module Parameters
- */
-
-#define ATI_REMOTE_VENDOR_ID		0x0bc7
-#define LOLA_REMOTE_PRODUCT_ID		0x0002
-#define LOLA2_REMOTE_PRODUCT_ID		0x0003
-#define ATI_REMOTE_PRODUCT_ID		0x0004
-#define NVIDIA_REMOTE_PRODUCT_ID	0x0005
-#define MEDION_REMOTE_PRODUCT_ID	0x0006
-
-#define DRIVER_VERSION	        "2.2.1"
-#define DRIVER_AUTHOR           "Torrey Hoffman <thoffman@arnor.net>"
-#define DRIVER_DESC             "ATI/X10 RF USB Remote Control"
-
-#define NAME_BUFSIZE      80    /* size of product name, path buffers */
-#define DATA_BUFSIZE      63    /* size of URB data buffers */
-
-/*
- * Duplicate event filtering time.
- * Sequential, identical KIND_FILTERED inputs with less than
- * FILTER_TIME milliseconds between them are considered as repeat
- * events. The hardware generates 5 events for the first keypress
- * and we have to take this into account for an accurate repeat
- * behaviour.
- */
-#define FILTER_TIME	60 /* msec */
-#define REPEAT_DELAY	500 /* msec */
-
-static unsigned long channel_mask;
-module_param(channel_mask, ulong, 0644);
-MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore");
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Enable extra debug messages and information");
-
-static int repeat_filter = FILTER_TIME;
-module_param(repeat_filter, int, 0644);
-MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec");
-
-static int repeat_delay = REPEAT_DELAY;
-module_param(repeat_delay, int, 0644);
-MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec");
-
-#define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
-#undef err
-#define err(format, arg...) printk(KERN_ERR format , ## arg)
-
-static struct usb_device_id ati_remote_table[] = {
-	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) },
-	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA2_REMOTE_PRODUCT_ID) },
-	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) },
-	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, NVIDIA_REMOTE_PRODUCT_ID) },
-	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID) },
-	{}	/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, ati_remote_table);
-
-/* Get hi and low bytes of a 16-bits int */
-#define HI(a)	((unsigned char)((a) >> 8))
-#define LO(a)	((unsigned char)((a) & 0xff))
-
-#define SEND_FLAG_IN_PROGRESS	1
-#define SEND_FLAG_COMPLETE	2
-
-/* Device initialization strings */
-static char init1[] = { 0x01, 0x00, 0x20, 0x14 };
-static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 };
-
-struct ati_remote {
-	struct input_dev *idev;
-	struct usb_device *udev;
-	struct usb_interface *interface;
-
-	struct urb *irq_urb;
-	struct urb *out_urb;
-	struct usb_endpoint_descriptor *endpoint_in;
-	struct usb_endpoint_descriptor *endpoint_out;
-	unsigned char *inbuf;
-	unsigned char *outbuf;
-	dma_addr_t inbuf_dma;
-	dma_addr_t outbuf_dma;
-
-	unsigned char old_data[2];  /* Detect duplicate events */
-	unsigned long old_jiffies;
-	unsigned long acc_jiffies;  /* handle acceleration */
-	unsigned long first_jiffies;
-
-	unsigned int repeat_count;
-
-	char name[NAME_BUFSIZE];
-	char phys[NAME_BUFSIZE];
-
-	wait_queue_head_t wait;
-	int send_flags;
-};
-
-/* "Kinds" of messages sent from the hardware to the driver. */
-#define KIND_END        0
-#define KIND_LITERAL    1   /* Simply pass to input system */
-#define KIND_FILTERED   2   /* Add artificial key-up events, drop keyrepeats */
-#define KIND_LU         3   /* Directional keypad diagonals - left up, */
-#define KIND_RU         4   /*   right up,  */
-#define KIND_LD         5   /*   left down, */
-#define KIND_RD         6   /*   right down */
-#define KIND_ACCEL      7   /* Directional keypad - left, right, up, down.*/
-
-/* Translation table from hardware messages to input events. */
-static const struct {
-	short kind;
-	unsigned char data1, data2;
-	int type;
-	unsigned int code;
-	int value;
-}  ati_remote_tbl[] = {
-	/* Directional control pad axes */
-	{KIND_ACCEL,   0x35, 0x70, EV_REL, REL_X, -1},	 /* left */
-	{KIND_ACCEL,   0x36, 0x71, EV_REL, REL_X, 1},    /* right */
-	{KIND_ACCEL,   0x37, 0x72, EV_REL, REL_Y, -1},	 /* up */
-	{KIND_ACCEL,   0x38, 0x73, EV_REL, REL_Y, 1},    /* down */
-	/* Directional control pad diagonals */
-	{KIND_LU,      0x39, 0x74, EV_REL, 0, 0},        /* left up */
-	{KIND_RU,      0x3a, 0x75, EV_REL, 0, 0},        /* right up */
-	{KIND_LD,      0x3c, 0x77, EV_REL, 0, 0},        /* left down */
-	{KIND_RD,      0x3b, 0x76, EV_REL, 0, 0},        /* right down */
-
-	/* "Mouse button" buttons */
-	{KIND_LITERAL, 0x3d, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */
-	{KIND_LITERAL, 0x3e, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */
-	{KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */
-	{KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */
-
-	/* Artificial "doubleclick" events are generated by the hardware.
-	 * They are mapped to the "side" and "extra" mouse buttons here. */
-	{KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */
-	{KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */
-
-	/* keyboard. */
-	{KIND_FILTERED, 0xd2, 0x0d, EV_KEY, KEY_1, 1},
-	{KIND_FILTERED, 0xd3, 0x0e, EV_KEY, KEY_2, 1},
-	{KIND_FILTERED, 0xd4, 0x0f, EV_KEY, KEY_3, 1},
-	{KIND_FILTERED, 0xd5, 0x10, EV_KEY, KEY_4, 1},
-	{KIND_FILTERED, 0xd6, 0x11, EV_KEY, KEY_5, 1},
-	{KIND_FILTERED, 0xd7, 0x12, EV_KEY, KEY_6, 1},
-	{KIND_FILTERED, 0xd8, 0x13, EV_KEY, KEY_7, 1},
-	{KIND_FILTERED, 0xd9, 0x14, EV_KEY, KEY_8, 1},
-	{KIND_FILTERED, 0xda, 0x15, EV_KEY, KEY_9, 1},
-	{KIND_FILTERED, 0xdc, 0x17, EV_KEY, KEY_0, 1},
-	{KIND_FILTERED, 0xc5, 0x00, EV_KEY, KEY_A, 1},
-	{KIND_FILTERED, 0xc6, 0x01, EV_KEY, KEY_B, 1},
-	{KIND_FILTERED, 0xde, 0x19, EV_KEY, KEY_C, 1},
-	{KIND_FILTERED, 0xe0, 0x1b, EV_KEY, KEY_D, 1},
-	{KIND_FILTERED, 0xe6, 0x21, EV_KEY, KEY_E, 1},
-	{KIND_FILTERED, 0xe8, 0x23, EV_KEY, KEY_F, 1},
-
-	/* "special" keys */
-	{KIND_FILTERED, 0xdd, 0x18, EV_KEY, KEY_KPENTER, 1},    /* "check" */
-	{KIND_FILTERED, 0xdb, 0x16, EV_KEY, KEY_MENU, 1},       /* "menu" */
-	{KIND_FILTERED, 0xc7, 0x02, EV_KEY, KEY_POWER, 1},      /* Power */
-	{KIND_FILTERED, 0xc8, 0x03, EV_KEY, KEY_TV, 1},         /* TV */
-	{KIND_FILTERED, 0xc9, 0x04, EV_KEY, KEY_DVD, 1},        /* DVD */
-	{KIND_FILTERED, 0xca, 0x05, EV_KEY, KEY_WWW, 1},        /* WEB */
-	{KIND_FILTERED, 0xcb, 0x06, EV_KEY, KEY_BOOKMARKS, 1},  /* "book" */
-	{KIND_FILTERED, 0xcc, 0x07, EV_KEY, KEY_EDIT, 1},       /* "hand" */
-	{KIND_FILTERED, 0xe1, 0x1c, EV_KEY, KEY_COFFEE, 1},     /* "timer" */
-	{KIND_FILTERED, 0xe5, 0x20, EV_KEY, KEY_FRONT, 1},      /* "max" */
-	{KIND_FILTERED, 0xe2, 0x1d, EV_KEY, KEY_LEFT, 1},       /* left */
-	{KIND_FILTERED, 0xe4, 0x1f, EV_KEY, KEY_RIGHT, 1},      /* right */
-	{KIND_FILTERED, 0xe7, 0x22, EV_KEY, KEY_DOWN, 1},       /* down */
-	{KIND_FILTERED, 0xdf, 0x1a, EV_KEY, KEY_UP, 1},         /* up */
-	{KIND_FILTERED, 0xe3, 0x1e, EV_KEY, KEY_OK, 1},         /* "OK" */
-	{KIND_FILTERED, 0xce, 0x09, EV_KEY, KEY_VOLUMEDOWN, 1}, /* VOL + */
-	{KIND_FILTERED, 0xcd, 0x08, EV_KEY, KEY_VOLUMEUP, 1},   /* VOL - */
-	{KIND_FILTERED, 0xcf, 0x0a, EV_KEY, KEY_MUTE, 1},       /* MUTE  */
-	{KIND_FILTERED, 0xd0, 0x0b, EV_KEY, KEY_CHANNELUP, 1},  /* CH + */
-	{KIND_FILTERED, 0xd1, 0x0c, EV_KEY, KEY_CHANNELDOWN, 1},/* CH - */
-	{KIND_FILTERED, 0xec, 0x27, EV_KEY, KEY_RECORD, 1},     /* ( o) red */
-	{KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1},       /* ( >) */
-	{KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1},     /* (<<) */
-	{KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1},    /* (>>) */
-	{KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1},       /* ([]) */
-	{KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1},      /* ('') */
-	{KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1},   /* (<-) */
-	{KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1},       /* (>+) */
-	{KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1},       /* PLAYING */
-	{KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1},       /* TOP */
-	{KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1},        /* END */
-	{KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1},     /* SELECT */
-
-	{KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0}
-};
-
-/* Local function prototypes */
-static int ati_remote_open		(struct input_dev *inputdev);
-static void ati_remote_close		(struct input_dev *inputdev);
-static int ati_remote_sendpacket	(struct ati_remote *ati_remote, u16 cmd, unsigned char *data);
-static void ati_remote_irq_out		(struct urb *urb);
-static void ati_remote_irq_in		(struct urb *urb);
-static void ati_remote_input_report	(struct urb *urb);
-static int ati_remote_initialize	(struct ati_remote *ati_remote);
-static int ati_remote_probe		(struct usb_interface *interface, const struct usb_device_id *id);
-static void ati_remote_disconnect	(struct usb_interface *interface);
-
-/* usb specific object to register with the usb subsystem */
-static struct usb_driver ati_remote_driver = {
-	.name         = "ati_remote",
-	.probe        = ati_remote_probe,
-	.disconnect   = ati_remote_disconnect,
-	.id_table     = ati_remote_table,
-};
-
-/*
- *	ati_remote_dump_input
- */
-static void ati_remote_dump(struct device *dev, unsigned char *data,
-			    unsigned int len)
-{
-	if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00))
-		dev_warn(dev, "Weird byte 0x%02x\n", data[0]);
-	else if (len == 4)
-		dev_warn(dev, "Weird key %02x %02x %02x %02x\n",
-		     data[0], data[1], data[2], data[3]);
-	else
-		dev_warn(dev, "Weird data, len=%d %02x %02x %02x %02x %02x %02x ...\n",
-		     len, data[0], data[1], data[2], data[3], data[4], data[5]);
-}
-
-/*
- *	ati_remote_open
- */
-static int ati_remote_open(struct input_dev *inputdev)
-{
-	struct ati_remote *ati_remote = input_get_drvdata(inputdev);
-
-	/* On first open, submit the read urb which was set up previously. */
-	ati_remote->irq_urb->dev = ati_remote->udev;
-	if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) {
-		dev_err(&ati_remote->interface->dev,
-			"%s: usb_submit_urb failed!\n", __func__);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-/*
- *	ati_remote_close
- */
-static void ati_remote_close(struct input_dev *inputdev)
-{
-	struct ati_remote *ati_remote = input_get_drvdata(inputdev);
-
-	usb_kill_urb(ati_remote->irq_urb);
-}
-
-/*
- *		ati_remote_irq_out
- */
-static void ati_remote_irq_out(struct urb *urb)
-{
-	struct ati_remote *ati_remote = urb->context;
-
-	if (urb->status) {
-		dev_dbg(&ati_remote->interface->dev, "%s: status %d\n",
-			__func__, urb->status);
-		return;
-	}
-
-	ati_remote->send_flags |= SEND_FLAG_COMPLETE;
-	wmb();
-	wake_up(&ati_remote->wait);
-}
-
-/*
- *	ati_remote_sendpacket
- *
- *	Used to send device initialization strings
- */
-static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data)
-{
-	int retval = 0;
-
-	/* Set up out_urb */
-	memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd));
-	((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd);
-
-	ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1;
-	ati_remote->out_urb->dev = ati_remote->udev;
-	ati_remote->send_flags = SEND_FLAG_IN_PROGRESS;
-
-	retval = usb_submit_urb(ati_remote->out_urb, GFP_ATOMIC);
-	if (retval) {
-		dev_dbg(&ati_remote->interface->dev,
-			 "sendpacket: usb_submit_urb failed: %d\n", retval);
-		return retval;
-	}
-
-	wait_event_timeout(ati_remote->wait,
-		((ati_remote->out_urb->status != -EINPROGRESS) ||
-			(ati_remote->send_flags & SEND_FLAG_COMPLETE)),
-		HZ);
-	usb_kill_urb(ati_remote->out_urb);
-
-	return retval;
-}
-
-/*
- *	ati_remote_event_lookup
- */
-static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2)
-{
-	int i;
-
-	for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) {
-		/*
-		 * Decide if the table entry matches the remote input.
-		 */
-		if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) &&
-		    ((((ati_remote_tbl[i].data1 >> 4) -
-		       (d1 >> 4) + rem) & 0x0f) == 0x0f) &&
-		    (ati_remote_tbl[i].data2 == d2))
-			return i;
-
-	}
-	return -1;
-}
-
-/*
- *	ati_remote_compute_accel
- *
- * Implements acceleration curve for directional control pad
- * If elapsed time since last event is > 1/4 second, user "stopped",
- * so reset acceleration. Otherwise, user is probably holding the control
- * pad down, so we increase acceleration, ramping up over two seconds to
- * a maximum speed.
- */
-static int ati_remote_compute_accel(struct ati_remote *ati_remote)
-{
-	static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
-	unsigned long now = jiffies;
-	int acc;
-
-	if (time_after(now, ati_remote->old_jiffies + msecs_to_jiffies(250))) {
-		acc = 1;
-		ati_remote->acc_jiffies = now;
-	}
-	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(125)))
-		acc = accel[0];
-	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(250)))
-		acc = accel[1];
-	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(500)))
-		acc = accel[2];
-	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1000)))
-		acc = accel[3];
-	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1500)))
-		acc = accel[4];
-	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(2000)))
-		acc = accel[5];
-	else
-		acc = accel[6];
-
-	return acc;
-}
-
-/*
- *	ati_remote_report_input
- */
-static void ati_remote_input_report(struct urb *urb)
-{
-	struct ati_remote *ati_remote = urb->context;
-	unsigned char *data= ati_remote->inbuf;
-	struct input_dev *dev = ati_remote->idev;
-	int index, acc;
-	int remote_num;
-
-	/* Deal with strange looking inputs */
-	if ( (urb->actual_length != 4) || (data[0] != 0x14) ||
-		((data[3] & 0x0f) != 0x00) ) {
-		ati_remote_dump(&urb->dev->dev, data, urb->actual_length);
-		return;
-	}
-
-	/* Mask unwanted remote channels.  */
-	/* note: remote_num is 0-based, channel 1 on remote == 0 here */
-	remote_num = (data[3] >> 4) & 0x0f;
-        if (channel_mask & (1 << (remote_num + 1))) {
-		dbginfo(&ati_remote->interface->dev,
-			"Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n",
-			remote_num, data[1], data[2], channel_mask);
-		return;
-	}
-
-	/* Look up event code index in translation table */
-	index = ati_remote_event_lookup(remote_num, data[1], data[2]);
-	if (index < 0) {
-		dev_warn(&ati_remote->interface->dev,
-			 "Unknown input from channel 0x%02x: data %02x,%02x\n",
-			 remote_num, data[1], data[2]);
-		return;
-	}
-	dbginfo(&ati_remote->interface->dev,
-		"channel 0x%02x; data %02x,%02x; index %d; keycode %d\n",
-		remote_num, data[1], data[2], index, ati_remote_tbl[index].code);
-
-	if (ati_remote_tbl[index].kind == KIND_LITERAL) {
-		input_event(dev, ati_remote_tbl[index].type,
-			ati_remote_tbl[index].code,
-			ati_remote_tbl[index].value);
-		input_sync(dev);
-
-		ati_remote->old_jiffies = jiffies;
-		return;
-	}
-
-	if (ati_remote_tbl[index].kind == KIND_FILTERED) {
-		unsigned long now = jiffies;
-
-		/* Filter duplicate events which happen "too close" together. */
-		if (ati_remote->old_data[0] == data[1] &&
-		    ati_remote->old_data[1] == data[2] &&
-		    time_before(now, ati_remote->old_jiffies +
-				     msecs_to_jiffies(repeat_filter))) {
-			ati_remote->repeat_count++;
-		} else {
-			ati_remote->repeat_count = 0;
-			ati_remote->first_jiffies = now;
-		}
-
-		ati_remote->old_data[0] = data[1];
-		ati_remote->old_data[1] = data[2];
-		ati_remote->old_jiffies = now;
-
-		/* Ensure we skip at least the 4 first duplicate events (generated
-		 * by a single keypress), and continue skipping until repeat_delay
-		 * msecs have passed
-		 */
-		if (ati_remote->repeat_count > 0 &&
-		    (ati_remote->repeat_count < 5 ||
-		     time_before(now, ati_remote->first_jiffies +
-				      msecs_to_jiffies(repeat_delay))))
-			return;
-
-
-		input_event(dev, ati_remote_tbl[index].type,
-			ati_remote_tbl[index].code, 1);
-		input_sync(dev);
-		input_event(dev, ati_remote_tbl[index].type,
-			ati_remote_tbl[index].code, 0);
-		input_sync(dev);
-
-	} else {
-
-		/*
-		 * Other event kinds are from the directional control pad, and have an
-		 * acceleration factor applied to them.  Without this acceleration, the
-		 * control pad is mostly unusable.
-		 */
-		acc = ati_remote_compute_accel(ati_remote);
-
-		switch (ati_remote_tbl[index].kind) {
-		case KIND_ACCEL:
-			input_event(dev, ati_remote_tbl[index].type,
-				ati_remote_tbl[index].code,
-				ati_remote_tbl[index].value * acc);
-			break;
-		case KIND_LU:
-			input_report_rel(dev, REL_X, -acc);
-			input_report_rel(dev, REL_Y, -acc);
-			break;
-		case KIND_RU:
-			input_report_rel(dev, REL_X, acc);
-			input_report_rel(dev, REL_Y, -acc);
-			break;
-		case KIND_LD:
-			input_report_rel(dev, REL_X, -acc);
-			input_report_rel(dev, REL_Y, acc);
-			break;
-		case KIND_RD:
-			input_report_rel(dev, REL_X, acc);
-			input_report_rel(dev, REL_Y, acc);
-			break;
-		default:
-			dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n",
-				ati_remote_tbl[index].kind);
-		}
-		input_sync(dev);
-
-		ati_remote->old_jiffies = jiffies;
-		ati_remote->old_data[0] = data[1];
-		ati_remote->old_data[1] = data[2];
-	}
-}
-
-/*
- *	ati_remote_irq_in
- */
-static void ati_remote_irq_in(struct urb *urb)
-{
-	struct ati_remote *ati_remote = urb->context;
-	int retval;
-
-	switch (urb->status) {
-	case 0:			/* success */
-		ati_remote_input_report(urb);
-		break;
-	case -ECONNRESET:	/* unlink */
-	case -ENOENT:
-	case -ESHUTDOWN:
-		dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n",
-			__func__);
-		return;
-	default:		/* error */
-		dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n",
-			__func__, urb->status);
-	}
-
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
-	if (retval)
-		dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n",
-			__func__, retval);
-}
-
-/*
- *	ati_remote_alloc_buffers
- */
-static int ati_remote_alloc_buffers(struct usb_device *udev,
-				    struct ati_remote *ati_remote)
-{
-	ati_remote->inbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC,
-					       &ati_remote->inbuf_dma);
-	if (!ati_remote->inbuf)
-		return -1;
-
-	ati_remote->outbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC,
-					        &ati_remote->outbuf_dma);
-	if (!ati_remote->outbuf)
-		return -1;
-
-	ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!ati_remote->irq_urb)
-		return -1;
-
-	ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!ati_remote->out_urb)
-		return -1;
-
-	return 0;
-}
-
-/*
- *	ati_remote_free_buffers
- */
-static void ati_remote_free_buffers(struct ati_remote *ati_remote)
-{
-	usb_free_urb(ati_remote->irq_urb);
-	usb_free_urb(ati_remote->out_urb);
-
-	usb_free_coherent(ati_remote->udev, DATA_BUFSIZE,
-		ati_remote->inbuf, ati_remote->inbuf_dma);
-
-	usb_free_coherent(ati_remote->udev, DATA_BUFSIZE,
-		ati_remote->outbuf, ati_remote->outbuf_dma);
-}
-
-static void ati_remote_input_init(struct ati_remote *ati_remote)
-{
-	struct input_dev *idev = ati_remote->idev;
-	int i;
-
-	idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
-	idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
-		BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
-	idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
-	for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++)
-		if (ati_remote_tbl[i].type == EV_KEY)
-			set_bit(ati_remote_tbl[i].code, idev->keybit);
-
-	input_set_drvdata(idev, ati_remote);
-
-	idev->open = ati_remote_open;
-	idev->close = ati_remote_close;
-
-	idev->name = ati_remote->name;
-	idev->phys = ati_remote->phys;
-
-	usb_to_input_id(ati_remote->udev, &idev->id);
-	idev->dev.parent = &ati_remote->udev->dev;
-}
-
-static int ati_remote_initialize(struct ati_remote *ati_remote)
-{
-	struct usb_device *udev = ati_remote->udev;
-	int pipe, maxp;
-
-	init_waitqueue_head(&ati_remote->wait);
-
-	/* Set up irq_urb */
-	pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress);
-	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
-	maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp;
-
-	usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf,
-			 maxp, ati_remote_irq_in, ati_remote,
-			 ati_remote->endpoint_in->bInterval);
-	ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma;
-	ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	/* Set up out_urb */
-	pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress);
-	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
-	maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp;
-
-	usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf,
-			 maxp, ati_remote_irq_out, ati_remote,
-			 ati_remote->endpoint_out->bInterval);
-	ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma;
-	ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	/* send initialization strings */
-	if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) ||
-	    (ati_remote_sendpacket(ati_remote, 0x8007, init2))) {
-		dev_err(&ati_remote->interface->dev,
-			 "Initializing ati_remote hardware failed.\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-/*
- *	ati_remote_probe
- */
-static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(interface);
-	struct usb_host_interface *iface_host = interface->cur_altsetting;
-	struct usb_endpoint_descriptor *endpoint_in, *endpoint_out;
-	struct ati_remote *ati_remote;
-	struct input_dev *input_dev;
-	int err = -ENOMEM;
-
-	if (iface_host->desc.bNumEndpoints != 2) {
-		err("%s: Unexpected desc.bNumEndpoints\n", __func__);
-		return -ENODEV;
-	}
-
-	endpoint_in = &iface_host->endpoint[0].desc;
-	endpoint_out = &iface_host->endpoint[1].desc;
-
-	if (!usb_endpoint_is_int_in(endpoint_in)) {
-		err("%s: Unexpected endpoint_in\n", __func__);
-		return -ENODEV;
-	}
-	if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) {
-		err("%s: endpoint_in message size==0? \n", __func__);
-		return -ENODEV;
-	}
-
-	ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!ati_remote || !input_dev)
-		goto fail1;
-
-	/* Allocate URB buffers, URBs */
-	if (ati_remote_alloc_buffers(udev, ati_remote))
-		goto fail2;
-
-	ati_remote->endpoint_in = endpoint_in;
-	ati_remote->endpoint_out = endpoint_out;
-	ati_remote->udev = udev;
-	ati_remote->idev = input_dev;
-	ati_remote->interface = interface;
-
-	usb_make_path(udev, ati_remote->phys, sizeof(ati_remote->phys));
-	strlcat(ati_remote->phys, "/input0", sizeof(ati_remote->phys));
-
-	if (udev->manufacturer)
-		strlcpy(ati_remote->name, udev->manufacturer, sizeof(ati_remote->name));
-
-	if (udev->product)
-		snprintf(ati_remote->name, sizeof(ati_remote->name),
-			 "%s %s", ati_remote->name, udev->product);
-
-	if (!strlen(ati_remote->name))
-		snprintf(ati_remote->name, sizeof(ati_remote->name),
-			DRIVER_DESC "(%04x,%04x)",
-			le16_to_cpu(ati_remote->udev->descriptor.idVendor),
-			le16_to_cpu(ati_remote->udev->descriptor.idProduct));
-
-	ati_remote_input_init(ati_remote);
-
-	/* Device Hardware Initialization - fills in ati_remote->idev from udev. */
-	err = ati_remote_initialize(ati_remote);
-	if (err)
-		goto fail3;
-
-	/* Set up and register input device */
-	err = input_register_device(ati_remote->idev);
-	if (err)
-		goto fail3;
-
-	usb_set_intfdata(interface, ati_remote);
-	return 0;
-
- fail3:	usb_kill_urb(ati_remote->irq_urb);
-	usb_kill_urb(ati_remote->out_urb);
- fail2:	ati_remote_free_buffers(ati_remote);
- fail1:	input_free_device(input_dev);
-	kfree(ati_remote);
-	return err;
-}
-
-/*
- *	ati_remote_disconnect
- */
-static void ati_remote_disconnect(struct usb_interface *interface)
-{
-	struct ati_remote *ati_remote;
-
-	ati_remote = usb_get_intfdata(interface);
-	usb_set_intfdata(interface, NULL);
-	if (!ati_remote) {
-		dev_warn(&interface->dev, "%s - null device?\n", __func__);
-		return;
-	}
-
-	usb_kill_urb(ati_remote->irq_urb);
-	usb_kill_urb(ati_remote->out_urb);
-	input_unregister_device(ati_remote->idev);
-	ati_remote_free_buffers(ati_remote);
-	kfree(ati_remote);
-}
-
-/*
- *	ati_remote_init
- */
-static int __init ati_remote_init(void)
-{
-	int result;
-
-	result = usb_register(&ati_remote_driver);
-	if (result)
-		printk(KERN_ERR KBUILD_MODNAME
-		       ": usb_register error #%d\n", result);
-	else
-		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-		       DRIVER_DESC "\n");
-
-	return result;
-}
-
-/*
- *	ati_remote_exit
- */
-static void __exit ati_remote_exit(void)
-{
-	usb_deregister(&ati_remote_driver);
-}
-
-/*
- *	module specification
- */
-
-module_init(ati_remote_init);
-module_exit(ati_remote_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/input/misc/bma150.c linux-libre-3.2-gnu/drivers/input/misc/bma150.c
--- linux-libre-3.1-gnu/drivers/input/misc/bma150.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/input/misc/bma150.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,691 @@
+/*
+ * Copyright (c) 2011 Bosch Sensortec GmbH
+ * Copyright (c) 2011 Unixphere
+ *
+ * This driver adds support for Bosch Sensortec's digital acceleration
+ * sensors BMA150 and SMB380.
+ * The SMB380 is fully compatible with BMA150 and only differs in packaging.
+ *
+ * The datasheet for the BMA150 chip can be found here:
+ * http://www.bosch-sensortec.com/content/language1/downloads/BST-BMA150-DS000-07.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/i2c.h>
+#include <linux/input.h>
+#include <linux/input-polldev.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/bma150.h>
+
+#define ABSMAX_ACC_VAL		0x01FF
+#define ABSMIN_ACC_VAL		-(ABSMAX_ACC_VAL)
+
+/* Each axis is represented by a 2-byte data word */
+#define BMA150_XYZ_DATA_SIZE	6
+
+/* Input poll interval in milliseconds */
+#define BMA150_POLL_INTERVAL	10
+#define BMA150_POLL_MAX		200
+#define BMA150_POLL_MIN		0
+
+#define BMA150_BW_25HZ		0
+#define BMA150_BW_50HZ		1
+#define BMA150_BW_100HZ		2
+#define BMA150_BW_190HZ		3
+#define BMA150_BW_375HZ		4
+#define BMA150_BW_750HZ		5
+#define BMA150_BW_1500HZ	6
+
+#define BMA150_RANGE_2G		0
+#define BMA150_RANGE_4G		1
+#define BMA150_RANGE_8G		2
+
+#define BMA150_MODE_NORMAL	0
+#define BMA150_MODE_SLEEP	2
+#define BMA150_MODE_WAKE_UP	3
+
+/* Data register addresses */
+#define BMA150_DATA_0_REG	0x00
+#define BMA150_DATA_1_REG	0x01
+#define BMA150_DATA_2_REG	0x02
+
+/* Control register addresses */
+#define BMA150_CTRL_0_REG	0x0A
+#define BMA150_CTRL_1_REG	0x0B
+#define BMA150_CTRL_2_REG	0x14
+#define BMA150_CTRL_3_REG	0x15
+
+/* Configuration/Setting register addresses */
+#define BMA150_CFG_0_REG	0x0C
+#define BMA150_CFG_1_REG	0x0D
+#define BMA150_CFG_2_REG	0x0E
+#define BMA150_CFG_3_REG	0x0F
+#define BMA150_CFG_4_REG	0x10
+#define BMA150_CFG_5_REG	0x11
+
+#define BMA150_CHIP_ID		2
+#define BMA150_CHIP_ID_REG	BMA150_DATA_0_REG
+
+#define BMA150_ACC_X_LSB_REG	BMA150_DATA_2_REG
+
+#define BMA150_SLEEP_POS	0
+#define BMA150_SLEEP_MSK	0x01
+#define BMA150_SLEEP_REG	BMA150_CTRL_0_REG
+
+#define BMA150_BANDWIDTH_POS	0
+#define BMA150_BANDWIDTH_MSK	0x07
+#define BMA150_BANDWIDTH_REG	BMA150_CTRL_2_REG
+
+#define BMA150_RANGE_POS	3
+#define BMA150_RANGE_MSK	0x18
+#define BMA150_RANGE_REG	BMA150_CTRL_2_REG
+
+#define BMA150_WAKE_UP_POS	0
+#define BMA150_WAKE_UP_MSK	0x01
+#define BMA150_WAKE_UP_REG	BMA150_CTRL_3_REG
+
+#define BMA150_SW_RES_POS	1
+#define BMA150_SW_RES_MSK	0x02
+#define BMA150_SW_RES_REG	BMA150_CTRL_0_REG
+
+/* Any-motion interrupt register fields */
+#define BMA150_ANY_MOTION_EN_POS	6
+#define BMA150_ANY_MOTION_EN_MSK	0x40
+#define BMA150_ANY_MOTION_EN_REG	BMA150_CTRL_1_REG
+
+#define BMA150_ANY_MOTION_DUR_POS	6
+#define BMA150_ANY_MOTION_DUR_MSK	0xC0
+#define BMA150_ANY_MOTION_DUR_REG	BMA150_CFG_5_REG
+
+#define BMA150_ANY_MOTION_THRES_REG	BMA150_CFG_4_REG
+
+/* Advanced interrupt register fields */
+#define BMA150_ADV_INT_EN_POS		6
+#define BMA150_ADV_INT_EN_MSK		0x40
+#define BMA150_ADV_INT_EN_REG		BMA150_CTRL_3_REG
+
+/* High-G interrupt register fields */
+#define BMA150_HIGH_G_EN_POS		1
+#define BMA150_HIGH_G_EN_MSK		0x02
+#define BMA150_HIGH_G_EN_REG		BMA150_CTRL_1_REG
+
+#define BMA150_HIGH_G_HYST_POS		3
+#define BMA150_HIGH_G_HYST_MSK		0x38
+#define BMA150_HIGH_G_HYST_REG		BMA150_CFG_5_REG
+
+#define BMA150_HIGH_G_DUR_REG		BMA150_CFG_3_REG
+#define BMA150_HIGH_G_THRES_REG		BMA150_CFG_2_REG
+
+/* Low-G interrupt register fields */
+#define BMA150_LOW_G_EN_POS		0
+#define BMA150_LOW_G_EN_MSK		0x01
+#define BMA150_LOW_G_EN_REG		BMA150_CTRL_1_REG
+
+#define BMA150_LOW_G_HYST_POS		0
+#define BMA150_LOW_G_HYST_MSK		0x07
+#define BMA150_LOW_G_HYST_REG		BMA150_CFG_5_REG
+
+#define BMA150_LOW_G_DUR_REG		BMA150_CFG_1_REG
+#define BMA150_LOW_G_THRES_REG		BMA150_CFG_0_REG
+
+struct bma150_data {
+	struct i2c_client *client;
+	struct input_polled_dev *input_polled;
+	struct input_dev *input;
+	u8 mode;
+};
+
+/*
+ * The settings for the given range, bandwidth and interrupt features
+ * are stated and verified by Bosch Sensortec where they are configured
+ * to provide a generic sensitivity performance.
+ */
+static struct bma150_cfg default_cfg __devinitdata = {
+	.any_motion_int = 1,
+	.hg_int = 1,
+	.lg_int = 1,
+	.any_motion_dur = 0,
+	.any_motion_thres = 0,
+	.hg_hyst = 0,
+	.hg_dur = 150,
+	.hg_thres = 160,
+	.lg_hyst = 0,
+	.lg_dur = 150,
+	.lg_thres = 20,
+	.range = BMA150_RANGE_2G,
+	.bandwidth = BMA150_BW_50HZ
+};
+
+static int bma150_write_byte(struct i2c_client *client, u8 reg, u8 val)
+{
+	s32 ret;
+
+	/* As per specification, disable irq in between register writes */
+	if (client->irq)
+		disable_irq_nosync(client->irq);
+
+	ret = i2c_smbus_write_byte_data(client, reg, val);
+
+	if (client->irq)
+		enable_irq(client->irq);
+
+	return ret;
+}
+
+static int bma150_set_reg_bits(struct i2c_client *client,
+					int val, int shift, u8 mask, u8 reg)
+{
+	int data;
+
+	data = i2c_smbus_read_byte_data(client, reg);
+	if (data < 0)
+		return data;
+
+	data = (data & ~mask) | ((val << shift) & mask);
+	return bma150_write_byte(client, reg, data);
+}
+
+static int bma150_set_mode(struct bma150_data *bma150, u8 mode)
+{
+	int error;
+
+	error = bma150_set_reg_bits(bma150->client, mode, BMA150_WAKE_UP_POS,
+				BMA150_WAKE_UP_MSK, BMA150_WAKE_UP_REG);
+	if (error)
+		return error;
+
+	error = bma150_set_reg_bits(bma150->client, mode, BMA150_SLEEP_POS,
+				BMA150_SLEEP_MSK, BMA150_SLEEP_REG);
+	if (error)
+		return error;
+
+	if (mode == BMA150_MODE_NORMAL)
+		msleep(2);
+
+	bma150->mode = mode;
+	return 0;
+}
+
+static int __devinit bma150_soft_reset(struct bma150_data *bma150)
+{
+	int error;
+
+	error = bma150_set_reg_bits(bma150->client, 1, BMA150_SW_RES_POS,
+				BMA150_SW_RES_MSK, BMA150_SW_RES_REG);
+	if (error)
+		return error;
+
+	msleep(2);
+	return 0;
+}
+
+static int __devinit bma150_set_range(struct bma150_data *bma150, u8 range)
+{
+	return bma150_set_reg_bits(bma150->client, range, BMA150_RANGE_POS,
+				BMA150_RANGE_MSK, BMA150_RANGE_REG);
+}
+
+static int __devinit bma150_set_bandwidth(struct bma150_data *bma150, u8 bw)
+{
+	return bma150_set_reg_bits(bma150->client, bw, BMA150_BANDWIDTH_POS,
+				BMA150_BANDWIDTH_MSK, BMA150_BANDWIDTH_REG);
+}
+
+static int __devinit bma150_set_low_g_interrupt(struct bma150_data *bma150,
+					u8 enable, u8 hyst, u8 dur, u8 thres)
+{
+	int error;
+
+	error = bma150_set_reg_bits(bma150->client, hyst,
+				BMA150_LOW_G_HYST_POS, BMA150_LOW_G_HYST_MSK,
+				BMA150_LOW_G_HYST_REG);
+	if (error)
+		return error;
+
+	error = bma150_write_byte(bma150->client, BMA150_LOW_G_DUR_REG, dur);
+	if (error)
+		return error;
+
+	error = bma150_write_byte(bma150->client, BMA150_LOW_G_THRES_REG, thres);
+	if (error)
+		return error;
+
+	return bma150_set_reg_bits(bma150->client, !!enable,
+				BMA150_LOW_G_EN_POS, BMA150_LOW_G_EN_MSK,
+				BMA150_LOW_G_EN_REG);
+}
+
+static int __devinit bma150_set_high_g_interrupt(struct bma150_data *bma150,
+					u8 enable, u8 hyst, u8 dur, u8 thres)
+{
+	int error;
+
+	error = bma150_set_reg_bits(bma150->client, hyst,
+				BMA150_HIGH_G_HYST_POS, BMA150_HIGH_G_HYST_MSK,
+				BMA150_HIGH_G_HYST_REG);
+	if (error)
+		return error;
+
+	error = bma150_write_byte(bma150->client,
+				BMA150_HIGH_G_DUR_REG, dur);
+	if (error)
+		return error;
+
+	error = bma150_write_byte(bma150->client,
+				BMA150_HIGH_G_THRES_REG, thres);
+	if (error)
+		return error;
+
+	return bma150_set_reg_bits(bma150->client, !!enable,
+				BMA150_HIGH_G_EN_POS, BMA150_HIGH_G_EN_MSK,
+				BMA150_HIGH_G_EN_REG);
+}
+
+
+static int __devinit bma150_set_any_motion_interrupt(struct bma150_data *bma150,
+						u8 enable, u8 dur, u8 thres)
+{
+	int error;
+
+	error = bma150_set_reg_bits(bma150->client, dur,
+				BMA150_ANY_MOTION_DUR_POS,
+				BMA150_ANY_MOTION_DUR_MSK,
+				BMA150_ANY_MOTION_DUR_REG);
+	if (error)
+		return error;
+
+	error = bma150_write_byte(bma150->client,
+				BMA150_ANY_MOTION_THRES_REG, thres);
+	if (error)
+		return error;
+
+	error = bma150_set_reg_bits(bma150->client, !!enable,
+				BMA150_ADV_INT_EN_POS, BMA150_ADV_INT_EN_MSK,
+				BMA150_ADV_INT_EN_REG);
+	if (error)
+		return error;
+
+	return bma150_set_reg_bits(bma150->client, !!enable,
+				BMA150_ANY_MOTION_EN_POS,
+				BMA150_ANY_MOTION_EN_MSK,
+				BMA150_ANY_MOTION_EN_REG);
+}
+
+static void bma150_report_xyz(struct bma150_data *bma150)
+{
+	u8 data[BMA150_XYZ_DATA_SIZE];
+	s16 x, y, z;
+	s32 ret;
+
+	ret = i2c_smbus_read_i2c_block_data(bma150->client,
+			BMA150_ACC_X_LSB_REG, BMA150_XYZ_DATA_SIZE, data);
+	if (ret != BMA150_XYZ_DATA_SIZE)
+		return;
+
+	x = ((0xc0 & data[0]) >> 6) | (data[1] << 2);
+	y = ((0xc0 & data[2]) >> 6) | (data[3] << 2);
+	z = ((0xc0 & data[4]) >> 6) | (data[5] << 2);
+
+	/* sign extension */
+	x = (s16) (x << 6) >> 6;
+	y = (s16) (y << 6) >> 6;
+	z = (s16) (z << 6) >> 6;
+
+	input_report_abs(bma150->input, ABS_X, x);
+	input_report_abs(bma150->input, ABS_Y, y);
+	input_report_abs(bma150->input, ABS_Z, z);
+	input_sync(bma150->input);
+}
+
+static irqreturn_t bma150_irq_thread(int irq, void *dev)
+{
+	bma150_report_xyz(dev);
+
+	return IRQ_HANDLED;
+}
+
+static void bma150_poll(struct input_polled_dev *dev)
+{
+	bma150_report_xyz(dev->private);
+}
+
+static int bma150_open(struct bma150_data *bma150)
+{
+	int error;
+
+	error = pm_runtime_get_sync(&bma150->client->dev);
+	if (error && error != -ENOSYS)
+		return error;
+
+	/*
+	 * See if runtime PM woke up the device. If runtime PM
+	 * is disabled we need to do it ourselves.
+	 */
+	if (bma150->mode != BMA150_MODE_NORMAL) {
+		error = bma150_set_mode(bma150, BMA150_MODE_NORMAL);
+		if (error)
+			return error;
+	}
+
+	return 0;
+}
+
+static void bma150_close(struct bma150_data *bma150)
+{
+	pm_runtime_put_sync(&bma150->client->dev);
+
+	if (bma150->mode != BMA150_MODE_SLEEP)
+		bma150_set_mode(bma150, BMA150_MODE_SLEEP);
+}
+
+static int bma150_irq_open(struct input_dev *input)
+{
+	struct bma150_data *bma150 = input_get_drvdata(input);
+
+	return bma150_open(bma150);
+}
+
+static void bma150_irq_close(struct input_dev *input)
+{
+	struct bma150_data *bma150 = input_get_drvdata(input);
+
+	bma150_close(bma150);
+}
+
+static void bma150_poll_open(struct input_polled_dev *ipoll_dev)
+{
+	struct bma150_data *bma150 = ipoll_dev->private;
+
+	bma150_open(bma150);
+}
+
+static void bma150_poll_close(struct input_polled_dev *ipoll_dev)
+{
+	struct bma150_data *bma150 = ipoll_dev->private;
+
+	bma150_close(bma150);
+}
+
+static int __devinit bma150_initialize(struct bma150_data *bma150,
+				       const struct bma150_cfg *cfg)
+{
+	int error;
+
+	error = bma150_soft_reset(bma150);
+	if (error)
+		return error;
+
+	error = bma150_set_bandwidth(bma150, cfg->bandwidth);
+	if (error)
+		return error;
+
+	error = bma150_set_range(bma150, cfg->range);
+	if (error)
+		return error;
+
+	if (bma150->client->irq) {
+		error = bma150_set_any_motion_interrupt(bma150,
+					cfg->any_motion_int,
+					cfg->any_motion_dur,
+					cfg->any_motion_thres);
+		if (error)
+			return error;
+
+		error = bma150_set_high_g_interrupt(bma150,
+					cfg->hg_int, cfg->hg_hyst,
+					cfg->hg_dur, cfg->hg_thres);
+		if (error)
+			return error;
+
+		error = bma150_set_low_g_interrupt(bma150,
+					cfg->lg_int, cfg->lg_hyst,
+					cfg->lg_dur, cfg->lg_thres);
+		if (error)
+			return error;
+	}
+
+	return bma150_set_mode(bma150, BMA150_MODE_SLEEP);
+}
+
+static void __devinit bma150_init_input_device(struct bma150_data *bma150,
+						struct input_dev *idev)
+{
+	idev->name = BMA150_DRIVER;
+	idev->phys = BMA150_DRIVER "/input0";
+	idev->id.bustype = BUS_I2C;
+	idev->dev.parent = &bma150->client->dev;
+
+	idev->evbit[0] = BIT_MASK(EV_ABS);
+	input_set_abs_params(idev, ABS_X, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
+	input_set_abs_params(idev, ABS_Y, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
+	input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
+}
+
+static int __devinit bma150_register_input_device(struct bma150_data *bma150)
+{
+	struct input_dev *idev;
+	int error;
+
+	idev = input_allocate_device();
+	if (!idev)
+		return -ENOMEM;
+
+	bma150_init_input_device(bma150, idev);
+
+	idev->open = bma150_irq_open;
+	idev->close = bma150_irq_close;
+	input_set_drvdata(idev, bma150);
+
+	error = input_register_device(idev);
+	if (error) {
+		input_free_device(idev);
+		return error;
+	}
+
+	bma150->input = idev;
+	return 0;
+}
+
+static int __devinit bma150_register_polled_device(struct bma150_data *bma150)
+{
+	struct input_polled_dev *ipoll_dev;
+	int error;
+
+	ipoll_dev = input_allocate_polled_device();
+	if (!ipoll_dev)
+		return -ENOMEM;
+
+	ipoll_dev->private = bma150;
+	ipoll_dev->open = bma150_poll_open;
+	ipoll_dev->close = bma150_poll_close;
+	ipoll_dev->poll = bma150_poll;
+	ipoll_dev->poll_interval = BMA150_POLL_INTERVAL;
+	ipoll_dev->poll_interval_min = BMA150_POLL_MIN;
+	ipoll_dev->poll_interval_max = BMA150_POLL_MAX;
+
+	bma150_init_input_device(bma150, ipoll_dev->input);
+
+	error = input_register_polled_device(ipoll_dev);
+	if (error) {
+		input_free_polled_device(ipoll_dev);
+		return error;
+	}
+
+	bma150->input_polled = ipoll_dev;
+	bma150->input = ipoll_dev->input;
+
+	return 0;
+}
+
+static int __devinit bma150_probe(struct i2c_client *client,
+				  const struct i2c_device_id *id)
+{
+	const struct bma150_platform_data *pdata = client->dev.platform_data;
+	const struct bma150_cfg *cfg;
+	struct bma150_data *bma150;
+	int chip_id;
+	int error;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "i2c_check_functionality error\n");
+		return -EIO;
+	}
+
+	chip_id = i2c_smbus_read_byte_data(client, BMA150_CHIP_ID_REG);
+	if (chip_id != BMA150_CHIP_ID) {
+		dev_err(&client->dev, "BMA150 chip id error: %d\n", chip_id);
+		return -EINVAL;
+	}
+
+	bma150 = kzalloc(sizeof(struct bma150_data), GFP_KERNEL);
+	if (!bma150)
+		return -ENOMEM;
+
+	bma150->client = client;
+
+	if (pdata) {
+		if (pdata->irq_gpio_cfg) {
+			error = pdata->irq_gpio_cfg();
+			if (error) {
+				dev_err(&client->dev,
+					"IRQ GPIO conf. error %d, error %d\n",
+					client->irq, error);
+				goto err_free_mem;
+			}
+		}
+		cfg = &pdata->cfg;
+	} else {
+		cfg = &default_cfg;
+	}
+
+	error = bma150_initialize(bma150, cfg);
+	if (error)
+		goto err_free_mem;
+
+	if (client->irq > 0) {
+		error = bma150_register_input_device(bma150);
+		if (error)
+			goto err_free_mem;
+
+		error = request_threaded_irq(client->irq,
+					NULL, bma150_irq_thread,
+					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+					BMA150_DRIVER, bma150);
+		if (error) {
+			dev_err(&client->dev,
+				"irq request failed %d, error %d\n",
+				client->irq, error);
+			input_unregister_device(bma150->input);
+			goto err_free_mem;
+		}
+	} else {
+		error = bma150_register_polled_device(bma150);
+		if (error)
+			goto err_free_mem;
+	}
+
+	i2c_set_clientdata(client, bma150);
+
+	pm_runtime_enable(&client->dev);
+
+	return 0;
+
+err_free_mem:
+	kfree(bma150);
+	return error;
+}
+
+static int __devexit bma150_remove(struct i2c_client *client)
+{
+	struct bma150_data *bma150 = i2c_get_clientdata(client);
+
+	pm_runtime_disable(&client->dev);
+
+	if (client->irq > 0) {
+		free_irq(client->irq, bma150);
+		input_unregister_device(bma150->input);
+	} else {
+		input_unregister_polled_device(bma150->input_polled);
+		input_free_polled_device(bma150->input_polled);
+	}
+
+	kfree(bma150);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bma150_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct bma150_data *bma150 = i2c_get_clientdata(client);
+
+	return bma150_set_mode(bma150, BMA150_MODE_SLEEP);
+}
+
+static int bma150_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct bma150_data *bma150 = i2c_get_clientdata(client);
+
+	return bma150_set_mode(bma150, BMA150_MODE_NORMAL);
+}
+#endif
+
+static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL);
+
+static const struct i2c_device_id bma150_id[] = {
+	{ "bma150", 0 },
+	{ "smb380", 0 },
+	{ "bma023", 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, bma150_id);
+
+static struct i2c_driver bma150_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= BMA150_DRIVER,
+		.pm	= &bma150_pm,
+	},
+	.class		= I2C_CLASS_HWMON,
+	.id_table	= bma150_id,
+	.probe		= bma150_probe,
+	.remove		= __devexit_p(bma150_remove),
+};
+
+static int __init BMA150_init(void)
+{
+	return i2c_add_driver(&bma150_driver);
+}
+
+static void __exit BMA150_exit(void)
+{
+	i2c_del_driver(&bma150_driver);
+}
+
+MODULE_AUTHOR("Albert Zhang <xu.zhang@bosch-sensortec.com>");
+MODULE_DESCRIPTION("BMA150 driver");
+MODULE_LICENSE("GPL");
+
+module_init(BMA150_init);
+module_exit(BMA150_exit);
diff -druN linux-libre-3.1-gnu/drivers/input/misc/cma3000_d0x.c linux-libre-3.2-gnu/drivers/input/misc/cma3000_d0x.c
--- linux-libre-3.1-gnu/drivers/input/misc/cma3000_d0x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/misc/cma3000_d0x.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/input/cma3000.h>
+#include <linux/module.h>
 
 #include "cma3000_d0x.h"
 
@@ -114,8 +115,8 @@
 static irqreturn_t cma3000_thread_irq(int irq, void *dev_id)
 {
 	struct cma3000_accl_data *data = dev_id;
-	int datax, datay, dataz;
-	u8 ctrl, mode, range, intr_status;
+	int datax, datay, dataz, intr_status;
+	u8 ctrl, mode, range;
 
 	intr_status = CMA3000_READ(data, CMA3000_INTSTATUS, "interrupt status");
 	if (intr_status < 0)
diff -druN linux-libre-3.1-gnu/drivers/input/misc/dm355evm_keys.c linux-libre-3.2-gnu/drivers/input/misc/dm355evm_keys.c
--- linux-libre-3.1-gnu/drivers/input/misc/dm355evm_keys.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/misc/dm355evm_keys.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 
 #include <linux/i2c/dm355evm_msp.h>
+#include <linux/module.h>
 
 
 /*
diff -druN linux-libre-3.1-gnu/drivers/input/misc/ixp4xx-beeper.c linux-libre-3.2-gnu/drivers/input/misc/ixp4xx-beeper.c
--- linux-libre-3.1-gnu/drivers/input/misc/ixp4xx-beeper.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/misc/ixp4xx-beeper.c	2012-01-04 18:55:44.000000000 -0500
@@ -111,7 +111,7 @@
 	input_dev->event = ixp4xx_spkr_event;
 
 	err = request_irq(IRQ_IXP4XX_TIMER2, &ixp4xx_spkr_interrupt,
-			  IRQF_DISABLED | IRQF_NO_SUSPEND, "ixp4xx-beeper",
+			  IRQF_NO_SUSPEND, "ixp4xx-beeper",
 			  (void *) dev->id);
 	if (err)
 		goto err_free_device;
diff -druN linux-libre-3.1-gnu/drivers/input/misc/Kconfig linux-libre-3.2-gnu/drivers/input/misc/Kconfig
--- linux-libre-3.1-gnu/drivers/input/misc/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/misc/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -62,6 +62,17 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad714x-spi.
 
+config INPUT_BMA150
+	tristate "BMA150/SMB380 acceleration sensor support"
+	depends on I2C
+	select INPUT_POLLDEV
+	help
+	  Say Y here if you have Bosch Sensortec's BMA150 or SMB380
+	  acceleration sensor hooked to an I2C bus.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bma150.
+
 config INPUT_PCSPKR
 	tristate "PC Speaker support"
 	depends on PCSPKR_PLATFORM
@@ -74,6 +85,29 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called pcspkr.
 
+config INPUT_PM8XXX_VIBRATOR
+	tristate "Qualcomm PM8XXX vibrator support"
+	depends on MFD_PM8XXX
+	select INPUT_FF_MEMLESS
+	help
+	  This option enables device driver support for the vibrator
+	  on Qualcomm PM8xxx chip. This driver supports ff-memless interface
+	  from input framework.
+
+	  To compile this driver as module, choose M here: the
+	  module will be called pm8xxx-vibrator.
+
+config INPUT_PMIC8XXX_PWRKEY
+	tristate "PMIC8XXX power key support"
+	depends on MFD_PM8XXX
+	help
+	  Say Y here if you want support for the PMIC8XXX power key.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pmic8xxx-pwrkey.
+
 config INPUT_SPARCSPKR
 	tristate "SPARC Speaker support"
 	depends on PCI && SPARC64
@@ -100,6 +134,16 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called max8925_onkey.
 
+config INPUT_MC13783_PWRBUTTON
+	tristate "MC13783 ON buttons"
+	depends on MFD_MC13783
+	help
+	  Support the ON buttons of MC13783 PMIC as an input device
+	  reporting power button status.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called mc13783-pwrbutton.
+
 config INPUT_MMA8450
 	tristate "MMA8450 - Freescale's 3-Axis, 8/12-bit Digital Accelerometer"
 	depends on I2C
@@ -183,22 +227,6 @@
 	  To compile this driver as a module, choose M here: the module will
 	  be called atlas_btns.
 
-config INPUT_ATI_REMOTE
-	tristate "ATI / X10 USB RF remote control"
-	depends on USB_ARCH_HAS_HCD
-	select USB
-	help
-	  Say Y here if you want to use an ATI or X10 "Lola" USB remote control.
-	  These are RF remotes with USB receivers.
-	  The ATI remote comes with many of ATI's All-In-Wonder video cards.
-	  The X10 "Lola" remote is available at:
-	     <http://www.x10.com/products/lola_sg1.htm>
-	  This driver provides mouse pointer, left and right mouse buttons,
-	  and maps all the other remote buttons to keypress events.
-
-	  To compile this driver as a module, choose M here: the module will be
-	  called ati_remote.
-
 config INPUT_ATI_REMOTE2
 	tristate "ATI / Philips USB RF remote control"
 	depends on USB_ARCH_HAS_HCD
@@ -379,17 +407,6 @@
 	  To compile this driver as a module, choose M here: the module will be
 	  called pwm-beeper.
 
-config INPUT_PMIC8XXX_PWRKEY
-	tristate "PMIC8XXX power key support"
-	depends on MFD_PM8XXX
-	help
-	  Say Y here if you want support for the PMIC8XXX power key.
-
-	  If unsure, say N.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called pmic8xxx-pwrkey.
-
 config INPUT_GPIO_ROTARY_ENCODER
 	tristate "Rotary encoders connected to GPIO pins"
 	depends on GPIOLIB && GENERIC_GPIO
diff -druN linux-libre-3.1-gnu/drivers/input/misc/Makefile linux-libre-3.2-gnu/drivers/input/misc/Makefile
--- linux-libre-3.1-gnu/drivers/input/misc/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/misc/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -13,10 +13,10 @@
 obj-$(CONFIG_INPUT_ADXL34X_I2C)		+= adxl34x-i2c.o
 obj-$(CONFIG_INPUT_ADXL34X_SPI)		+= adxl34x-spi.o
 obj-$(CONFIG_INPUT_APANEL)		+= apanel.o
-obj-$(CONFIG_INPUT_ATI_REMOTE)		+= ati_remote.o
 obj-$(CONFIG_INPUT_ATI_REMOTE2)		+= ati_remote2.o
 obj-$(CONFIG_INPUT_ATLAS_BTNS)		+= atlas_btns.o
 obj-$(CONFIG_INPUT_BFIN_ROTARY)		+= bfin_rotary.o
+obj-$(CONFIG_INPUT_BMA150)		+= bma150.o
 obj-$(CONFIG_INPUT_CM109)		+= cm109.o
 obj-$(CONFIG_INPUT_CMA3000)		+= cma3000_d0x.o
 obj-$(CONFIG_INPUT_CMA3000_I2C)		+= cma3000_d0x_i2c.o
@@ -28,15 +28,17 @@
 obj-$(CONFIG_INPUT_KXTJ9)		+= kxtj9.o
 obj-$(CONFIG_INPUT_M68K_BEEP)		+= m68kspkr.o
 obj-$(CONFIG_INPUT_MAX8925_ONKEY)	+= max8925_onkey.o
+obj-$(CONFIG_INPUT_MC13783_PWRBUTTON)	+= mc13783-pwrbutton.o
 obj-$(CONFIG_INPUT_MMA8450)		+= mma8450.o
 obj-$(CONFIG_INPUT_MPU3050)		+= mpu3050.o
 obj-$(CONFIG_INPUT_PCAP)		+= pcap_keys.o
 obj-$(CONFIG_INPUT_PCF50633_PMU)	+= pcf50633-input.o
 obj-$(CONFIG_INPUT_PCF8574)		+= pcf8574_keypad.o
 obj-$(CONFIG_INPUT_PCSPKR)		+= pcspkr.o
+obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR)	+= pm8xxx-vibrator.o
+obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY)	+= pmic8xxx-pwrkey.o
 obj-$(CONFIG_INPUT_POWERMATE)		+= powermate.o
 obj-$(CONFIG_INPUT_PWM_BEEPER)		+= pwm-beeper.o
-obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY)	+= pmic8xxx-pwrkey.o
 obj-$(CONFIG_INPUT_RB532_BUTTON)	+= rb532_button.o
 obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER)	+= rotary_encoder.o
 obj-$(CONFIG_INPUT_SGI_BTNS)		+= sgi_btns.o
diff -druN linux-libre-3.1-gnu/drivers/input/misc/mc13783-pwrbutton.c linux-libre-3.2-gnu/drivers/input/misc/mc13783-pwrbutton.c
--- linux-libre-3.1-gnu/drivers/input/misc/mc13783-pwrbutton.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/input/misc/mc13783-pwrbutton.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,282 @@
+/**
+ * Copyright (C) 2011 Philippe RÃ©tornaz
+ *
+ * Based on twl4030-pwrbutton driver by:
+ *     Peter De Schrijver <peter.de-schrijver@nokia.com>
+ *     Felipe Balbi <felipe.balbi@nokia.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+struct mc13783_pwrb {
+	struct input_dev *pwr;
+	struct mc13xxx *mc13783;
+#define MC13783_PWRB_B1_POL_INVERT	(1 << 0)
+#define MC13783_PWRB_B2_POL_INVERT	(1 << 1)
+#define MC13783_PWRB_B3_POL_INVERT	(1 << 2)
+	int flags;
+	unsigned short keymap[3];
+};
+
+#define MC13783_REG_INTERRUPT_SENSE_1		5
+#define MC13783_IRQSENSE1_ONOFD1S		(1 << 3)
+#define MC13783_IRQSENSE1_ONOFD2S		(1 << 4)
+#define MC13783_IRQSENSE1_ONOFD3S		(1 << 5)
+
+#define MC13783_REG_POWER_CONTROL_2		15
+#define MC13783_POWER_CONTROL_2_ON1BDBNC	4
+#define MC13783_POWER_CONTROL_2_ON2BDBNC	6
+#define MC13783_POWER_CONTROL_2_ON3BDBNC	8
+#define MC13783_POWER_CONTROL_2_ON1BRSTEN	(1 << 1)
+#define MC13783_POWER_CONTROL_2_ON2BRSTEN	(1 << 2)
+#define MC13783_POWER_CONTROL_2_ON3BRSTEN	(1 << 3)
+
+static irqreturn_t button_irq(int irq, void *_priv)
+{
+	struct mc13783_pwrb *priv = _priv;
+	int val;
+
+	mc13xxx_irq_ack(priv->mc13783, irq);
+	mc13xxx_reg_read(priv->mc13783, MC13783_REG_INTERRUPT_SENSE_1, &val);
+
+	switch (irq) {
+	case MC13783_IRQ_ONOFD1:
+		val = val & MC13783_IRQSENSE1_ONOFD1S ? 1 : 0;
+		if (priv->flags & MC13783_PWRB_B1_POL_INVERT)
+			val ^= 1;
+		input_report_key(priv->pwr, priv->keymap[0], val);
+		break;
+
+	case MC13783_IRQ_ONOFD2:
+		val = val & MC13783_IRQSENSE1_ONOFD2S ? 1 : 0;
+		if (priv->flags & MC13783_PWRB_B2_POL_INVERT)
+			val ^= 1;
+		input_report_key(priv->pwr, priv->keymap[1], val);
+		break;
+
+	case MC13783_IRQ_ONOFD3:
+		val = val & MC13783_IRQSENSE1_ONOFD3S ? 1 : 0;
+		if (priv->flags & MC13783_PWRB_B3_POL_INVERT)
+			val ^= 1;
+		input_report_key(priv->pwr, priv->keymap[2], val);
+		break;
+	}
+
+	input_sync(priv->pwr);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit mc13783_pwrbutton_probe(struct platform_device *pdev)
+{
+	const struct mc13xxx_buttons_platform_data *pdata;
+	struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
+	struct input_dev *pwr;
+	struct mc13783_pwrb *priv;
+	int err = 0;
+	int reg = 0;
+
+	pdata = dev_get_platdata(&pdev->dev);
+	if (!pdata) {
+		dev_err(&pdev->dev, "missing platform data\n");
+		return -ENODEV;
+	}
+
+	pwr = input_allocate_device();
+	if (!pwr) {
+		dev_dbg(&pdev->dev, "Can't allocate power button\n");
+		return -ENOMEM;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		err = -ENOMEM;
+		dev_dbg(&pdev->dev, "Can't allocate power button\n");
+		goto free_input_dev;
+	}
+
+	reg |= (pdata->b1on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON1BDBNC;
+	reg |= (pdata->b2on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON2BDBNC;
+	reg |= (pdata->b3on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON3BDBNC;
+
+	priv->pwr = pwr;
+	priv->mc13783 = mc13783;
+
+	mc13xxx_lock(mc13783);
+
+	if (pdata->b1on_flags & MC13783_BUTTON_ENABLE) {
+		priv->keymap[0] = pdata->b1on_key;
+		if (pdata->b1on_key != KEY_RESERVED)
+			__set_bit(pdata->b1on_key, pwr->keybit);
+
+		if (pdata->b1on_flags & MC13783_BUTTON_POL_INVERT)
+			priv->flags |= MC13783_PWRB_B1_POL_INVERT;
+
+		if (pdata->b1on_flags & MC13783_BUTTON_RESET_EN)
+			reg |= MC13783_POWER_CONTROL_2_ON1BRSTEN;
+
+		err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD1,
+					  button_irq, "b1on", priv);
+		if (err) {
+			dev_dbg(&pdev->dev, "Can't request irq\n");
+			goto free_priv;
+		}
+	}
+
+	if (pdata->b2on_flags & MC13783_BUTTON_ENABLE) {
+		priv->keymap[1] = pdata->b2on_key;
+		if (pdata->b2on_key != KEY_RESERVED)
+			__set_bit(pdata->b2on_key, pwr->keybit);
+
+		if (pdata->b2on_flags & MC13783_BUTTON_POL_INVERT)
+			priv->flags |= MC13783_PWRB_B2_POL_INVERT;
+
+		if (pdata->b2on_flags & MC13783_BUTTON_RESET_EN)
+			reg |= MC13783_POWER_CONTROL_2_ON2BRSTEN;
+
+		err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD2,
+					  button_irq, "b2on", priv);
+		if (err) {
+			dev_dbg(&pdev->dev, "Can't request irq\n");
+			goto free_irq_b1;
+		}
+	}
+
+	if (pdata->b3on_flags & MC13783_BUTTON_ENABLE) {
+		priv->keymap[2] = pdata->b3on_key;
+		if (pdata->b3on_key != KEY_RESERVED)
+			__set_bit(pdata->b3on_key, pwr->keybit);
+
+		if (pdata->b3on_flags & MC13783_BUTTON_POL_INVERT)
+			priv->flags |= MC13783_PWRB_B3_POL_INVERT;
+
+		if (pdata->b3on_flags & MC13783_BUTTON_RESET_EN)
+			reg |= MC13783_POWER_CONTROL_2_ON3BRSTEN;
+
+		err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD3,
+					  button_irq, "b3on", priv);
+		if (err) {
+			dev_dbg(&pdev->dev, "Can't request irq: %d\n", err);
+			goto free_irq_b2;
+		}
+	}
+
+	mc13xxx_reg_rmw(mc13783, MC13783_REG_POWER_CONTROL_2, 0x3FE, reg);
+
+	mc13xxx_unlock(mc13783);
+
+	pwr->name = "mc13783_pwrbutton";
+	pwr->phys = "mc13783_pwrbutton/input0";
+	pwr->dev.parent = &pdev->dev;
+
+	pwr->keycode = priv->keymap;
+	pwr->keycodemax = ARRAY_SIZE(priv->keymap);
+	pwr->keycodesize = sizeof(priv->keymap[0]);
+	__set_bit(EV_KEY, pwr->evbit);
+
+	err = input_register_device(pwr);
+	if (err) {
+		dev_dbg(&pdev->dev, "Can't register power button: %d\n", err);
+		goto free_irq;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	return 0;
+
+free_irq:
+	mc13xxx_lock(mc13783);
+
+	if (pdata->b3on_flags & MC13783_BUTTON_ENABLE)
+		mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD3, priv);
+
+free_irq_b2:
+	if (pdata->b2on_flags & MC13783_BUTTON_ENABLE)
+		mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD2, priv);
+
+free_irq_b1:
+	if (pdata->b1on_flags & MC13783_BUTTON_ENABLE)
+		mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD1, priv);
+
+free_priv:
+	mc13xxx_unlock(mc13783);
+	kfree(priv);
+
+free_input_dev:
+	input_free_device(pwr);
+
+	return err;
+}
+
+static int __devexit mc13783_pwrbutton_remove(struct platform_device *pdev)
+{
+	struct mc13783_pwrb *priv = platform_get_drvdata(pdev);
+	const struct mc13xxx_buttons_platform_data *pdata;
+
+	pdata = dev_get_platdata(&pdev->dev);
+
+	mc13xxx_lock(priv->mc13783);
+
+	if (pdata->b3on_flags & MC13783_BUTTON_ENABLE)
+		mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD3, priv);
+	if (pdata->b2on_flags & MC13783_BUTTON_ENABLE)
+		mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD2, priv);
+	if (pdata->b1on_flags & MC13783_BUTTON_ENABLE)
+		mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD1, priv);
+
+	mc13xxx_unlock(priv->mc13783);
+
+	input_unregister_device(priv->pwr);
+	kfree(priv);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+struct platform_driver mc13783_pwrbutton_driver = {
+	.probe		= mc13783_pwrbutton_probe,
+	.remove		= __devexit_p(mc13783_pwrbutton_remove),
+	.driver		= {
+		.name	= "mc13783-pwrbutton",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init mc13783_pwrbutton_init(void)
+{
+	return platform_driver_register(&mc13783_pwrbutton_driver);
+}
+module_init(mc13783_pwrbutton_init);
+
+static void __exit mc13783_pwrbutton_exit(void)
+{
+	platform_driver_unregister(&mc13783_pwrbutton_driver);
+}
+module_exit(mc13783_pwrbutton_exit);
+
+MODULE_ALIAS("platform:mc13783-pwrbutton");
+MODULE_DESCRIPTION("MC13783 Power Button");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Philippe Retornaz");
diff -druN linux-libre-3.1-gnu/drivers/input/misc/mma8450.c linux-libre-3.2-gnu/drivers/input/misc/mma8450.c
--- linux-libre-3.1-gnu/drivers/input/misc/mma8450.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/misc/mma8450.c	2012-01-04 18:55:44.000000000 -0500
@@ -88,13 +88,13 @@
 	return 0;
 }
 
-static int mma8450_read_xyz(struct mma8450 *m, int *x, int *y, int *z)
+static int mma8450_read_block(struct mma8450 *m, unsigned off,
+			      u8 *buf, size_t size)
 {
 	struct i2c_client *c = m->client;
-	u8 buff[6];
 	int err;
 
-	err = i2c_smbus_read_i2c_block_data(c, MMA8450_OUT_X_LSB, 6, buff);
+	err = i2c_smbus_read_i2c_block_data(c, off, size, buf);
 	if (err < 0) {
 		dev_err(&c->dev,
 			"failed to read block data at 0x%02x, error %d\n",
@@ -102,10 +102,6 @@
 		return err;
 	}
 
-	*x = ((buff[1] << 4) & 0xff0) | (buff[0] & 0xf);
-	*y = ((buff[3] << 4) & 0xff0) | (buff[2] & 0xf);
-	*z = ((buff[5] << 4) & 0xff0) | (buff[4] & 0xf);
-
 	return 0;
 }
 
@@ -114,7 +110,7 @@
 	struct mma8450 *m = dev->private;
 	int x, y, z;
 	int ret;
-	int err;
+	u8 buf[6];
 
 	ret = mma8450_read(m, MMA8450_STATUS);
 	if (ret < 0)
@@ -123,10 +119,14 @@
 	if (!(ret & MMA8450_STATUS_ZXYDR))
 		return;
 
-	err = mma8450_read_xyz(m, &x, &y, &z);
-	if (err)
+	ret = mma8450_read_block(m, MMA8450_OUT_X_LSB, buf, sizeof(buf));
+	if (ret < 0)
 		return;
 
+	x = ((buf[1] << 4) & 0xff0) | (buf[0] & 0xf);
+	y = ((buf[3] << 4) & 0xff0) | (buf[2] & 0xf);
+	z = ((buf[5] << 4) & 0xff0) | (buf[4] & 0xf);
+
 	input_report_abs(dev->input, ABS_X, x);
 	input_report_abs(dev->input, ABS_Y, y);
 	input_report_abs(dev->input, ABS_Z, z);
diff -druN linux-libre-3.1-gnu/drivers/input/misc/pm8xxx-vibrator.c linux-libre-3.2-gnu/drivers/input/misc/pm8xxx-vibrator.c
--- linux-libre-3.1-gnu/drivers/input/misc/pm8xxx-vibrator.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/input/misc/pm8xxx-vibrator.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,296 @@
+/* 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.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/mfd/pm8xxx/core.h>
+
+#define VIB_DRV			0x4A
+
+#define VIB_DRV_SEL_MASK	0xf8
+#define VIB_DRV_SEL_SHIFT	0x03
+#define VIB_DRV_EN_MANUAL_MASK	0xfc
+
+#define VIB_MAX_LEVEL_mV	(3100)
+#define VIB_MIN_LEVEL_mV	(1200)
+#define VIB_MAX_LEVELS		(VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV)
+
+#define MAX_FF_SPEED		0xff
+
+/**
+ * struct pm8xxx_vib - structure to hold vibrator data
+ * @vib_input_dev: input device supporting force feedback
+ * @work: work structure to set the vibration parameters
+ * @dev: device supporting force feedback
+ * @speed: speed of vibration set from userland
+ * @active: state of vibrator
+ * @level: level of vibration to set in the chip
+ * @reg_vib_drv: VIB_DRV register value
+ */
+struct pm8xxx_vib {
+	struct input_dev *vib_input_dev;
+	struct work_struct work;
+	struct device *dev;
+	int speed;
+	int level;
+	bool active;
+	u8  reg_vib_drv;
+};
+
+/**
+ * pm8xxx_vib_read_u8 - helper to read a byte from pmic chip
+ * @vib: pointer to vibrator structure
+ * @data: placeholder for data to be read
+ * @reg: register address
+ */
+static int pm8xxx_vib_read_u8(struct pm8xxx_vib *vib,
+				 u8 *data, u16 reg)
+{
+	int rc;
+
+	rc = pm8xxx_readb(vib->dev->parent, reg, data);
+	if (rc < 0)
+		dev_warn(vib->dev, "Error reading pm8xxx reg 0x%x(0x%x)\n",
+				reg, rc);
+	return rc;
+}
+
+/**
+ * pm8xxx_vib_write_u8 - helper to write a byte to pmic chip
+ * @vib: pointer to vibrator structure
+ * @data: data to write
+ * @reg: register address
+ */
+static int pm8xxx_vib_write_u8(struct pm8xxx_vib *vib,
+				 u8 data, u16 reg)
+{
+	int rc;
+
+	rc = pm8xxx_writeb(vib->dev->parent, reg, data);
+	if (rc < 0)
+		dev_warn(vib->dev, "Error writing pm8xxx reg 0x%x(0x%x)\n",
+				reg, rc);
+	return rc;
+}
+
+/**
+ * pm8xxx_vib_set - handler to start/stop vibration
+ * @vib: pointer to vibrator structure
+ * @on: state to set
+ */
+static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on)
+{
+	int rc;
+	u8 val = vib->reg_vib_drv;
+
+	if (on)
+		val |= ((vib->level << VIB_DRV_SEL_SHIFT) & VIB_DRV_SEL_MASK);
+	else
+		val &= ~VIB_DRV_SEL_MASK;
+
+	rc = pm8xxx_vib_write_u8(vib, val, VIB_DRV);
+	if (rc < 0)
+		return rc;
+
+	vib->reg_vib_drv = val;
+	return 0;
+}
+
+/**
+ * pm8xxx_work_handler - worker to set vibration level
+ * @work: pointer to work_struct
+ */
+static void pm8xxx_work_handler(struct work_struct *work)
+{
+	struct pm8xxx_vib *vib = container_of(work, struct pm8xxx_vib, work);
+	int rc;
+	u8 val;
+
+	rc = pm8xxx_vib_read_u8(vib, &val, VIB_DRV);
+	if (rc < 0)
+		return;
+
+	/*
+	 * pmic vibrator supports voltage ranges from 1.2 to 3.1V, so
+	 * scale the level to fit into these ranges.
+	 */
+	if (vib->speed) {
+		vib->active = true;
+		vib->level = ((VIB_MAX_LEVELS * vib->speed) / MAX_FF_SPEED) +
+						VIB_MIN_LEVEL_mV;
+		vib->level /= 100;
+	} else {
+		vib->active = false;
+		vib->level = VIB_MIN_LEVEL_mV / 100;
+	}
+
+	pm8xxx_vib_set(vib, vib->active);
+}
+
+/**
+ * pm8xxx_vib_close - callback of input close callback
+ * @dev: input device pointer
+ *
+ * Turns off the vibrator.
+ */
+static void pm8xxx_vib_close(struct input_dev *dev)
+{
+	struct pm8xxx_vib *vib = input_get_drvdata(dev);
+
+	cancel_work_sync(&vib->work);
+	if (vib->active)
+		pm8xxx_vib_set(vib, false);
+}
+
+/**
+ * pm8xxx_vib_play_effect - function to handle vib effects.
+ * @dev: input device pointer
+ * @data: data of effect
+ * @effect: effect to play
+ *
+ * Currently this driver supports only rumble effects.
+ */
+static int pm8xxx_vib_play_effect(struct input_dev *dev, void *data,
+				  struct ff_effect *effect)
+{
+	struct pm8xxx_vib *vib = input_get_drvdata(dev);
+
+	vib->speed = effect->u.rumble.strong_magnitude >> 8;
+	if (!vib->speed)
+		vib->speed = effect->u.rumble.weak_magnitude >> 9;
+
+	schedule_work(&vib->work);
+
+	return 0;
+}
+
+static int __devinit pm8xxx_vib_probe(struct platform_device *pdev)
+
+{
+	struct pm8xxx_vib *vib;
+	struct input_dev *input_dev;
+	int error;
+	u8 val;
+
+	vib = kzalloc(sizeof(*vib), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!vib || !input_dev) {
+		dev_err(&pdev->dev, "couldn't allocate memory\n");
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	INIT_WORK(&vib->work, pm8xxx_work_handler);
+	vib->dev = &pdev->dev;
+	vib->vib_input_dev = input_dev;
+
+	/* operate in manual mode */
+	error = pm8xxx_vib_read_u8(vib, &val, VIB_DRV);
+	if (error < 0)
+		goto err_free_mem;
+	val &= ~VIB_DRV_EN_MANUAL_MASK;
+	error = pm8xxx_vib_write_u8(vib, val, VIB_DRV);
+	if (error < 0)
+		goto err_free_mem;
+
+	vib->reg_vib_drv = val;
+
+	input_dev->name = "pm8xxx_vib_ffmemless";
+	input_dev->id.version = 1;
+	input_dev->dev.parent = &pdev->dev;
+	input_dev->close = pm8xxx_vib_close;
+	input_set_drvdata(input_dev, vib);
+	input_set_capability(vib->vib_input_dev, EV_FF, FF_RUMBLE);
+
+	error = input_ff_create_memless(input_dev, NULL,
+					pm8xxx_vib_play_effect);
+	if (error) {
+		dev_err(&pdev->dev,
+			"couldn't register vibrator as FF device\n");
+		goto err_free_mem;
+	}
+
+	error = input_register_device(input_dev);
+	if (error) {
+		dev_err(&pdev->dev, "couldn't register input device\n");
+		goto err_destroy_memless;
+	}
+
+	platform_set_drvdata(pdev, vib);
+	return 0;
+
+err_destroy_memless:
+	input_ff_destroy(input_dev);
+err_free_mem:
+	input_free_device(input_dev);
+	kfree(vib);
+
+	return error;
+}
+
+static int __devexit pm8xxx_vib_remove(struct platform_device *pdev)
+{
+	struct pm8xxx_vib *vib = platform_get_drvdata(pdev);
+
+	input_unregister_device(vib->vib_input_dev);
+	kfree(vib);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pm8xxx_vib_suspend(struct device *dev)
+{
+	struct pm8xxx_vib *vib = dev_get_drvdata(dev);
+
+	/* Turn off the vibrator */
+	pm8xxx_vib_set(vib, false);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL);
+
+static struct platform_driver pm8xxx_vib_driver = {
+	.probe		= pm8xxx_vib_probe,
+	.remove		= __devexit_p(pm8xxx_vib_remove),
+	.driver		= {
+		.name	= "pm8xxx-vib",
+		.owner	= THIS_MODULE,
+		.pm	= &pm8xxx_vib_pm_ops,
+	},
+};
+
+static int __init pm8xxx_vib_init(void)
+{
+	return platform_driver_register(&pm8xxx_vib_driver);
+}
+module_init(pm8xxx_vib_init);
+
+static void __exit pm8xxx_vib_exit(void)
+{
+	platform_driver_unregister(&pm8xxx_vib_driver);
+}
+module_exit(pm8xxx_vib_exit);
+
+MODULE_ALIAS("platform:pm8xxx_vib");
+MODULE_DESCRIPTION("PMIC8xxx vibrator driver based on ff-memless framework");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Amy Maloche <amaloche@codeaurora.org>");
diff -druN linux-libre-3.1-gnu/drivers/input/misc/rotary_encoder.c linux-libre-3.2-gnu/drivers/input/misc/rotary_encoder.c
--- linux-libre-3.1-gnu/drivers/input/misc/rotary_encoder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/misc/rotary_encoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,7 +7,7 @@
  * state machine code inspired by code from Tim Ruetz
  *
  * A generic driver for rotary encoders connected to GPIO lines.
- * See file:Documentation/input/rotary_encoder.txt for more information
+ * See file:Documentation/input/rotary-encoder.txt for more information
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff -druN linux-libre-3.1-gnu/drivers/input/misc/twl6040-vibra.c linux-libre-3.2-gnu/drivers/input/misc/twl6040-vibra.c
--- linux-libre-3.1-gnu/drivers/input/misc/twl6040-vibra.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/misc/twl6040-vibra.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,12 +74,12 @@
 	if (status & TWL6040_VIBLOCDET) {
 		dev_warn(info->dev, "Left Vibrator overcurrent detected\n");
 		twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLL,
-				   TWL6040_VIBENAL);
+				   TWL6040_VIBENA);
 	}
 	if (status & TWL6040_VIBROCDET) {
 		dev_warn(info->dev, "Right Vibrator overcurrent detected\n");
 		twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLR,
-				   TWL6040_VIBENAR);
+				   TWL6040_VIBENA);
 	}
 
 	return IRQ_HANDLED;
@@ -97,23 +97,23 @@
 	}
 
 	twl6040_power(info->twl6040, 1);
-	if (twl6040->rev <= TWL6040_REV_ES1_1) {
+	if (twl6040_get_revid(twl6040) <= TWL6040_REV_ES1_1) {
 		/*
 		 * ERRATA: Disable overcurrent protection for at least
 		 * 3ms when enabling vibrator drivers to avoid false
 		 * overcurrent detection
 		 */
 		twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
-				  TWL6040_VIBENAL | TWL6040_VIBCTRLL);
+				  TWL6040_VIBENA | TWL6040_VIBCTRL);
 		twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
-				  TWL6040_VIBENAR | TWL6040_VIBCTRLR);
+				  TWL6040_VIBENA | TWL6040_VIBCTRL);
 		usleep_range(3000, 3500);
 	}
 
 	twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
-			  TWL6040_VIBENAL);
+			  TWL6040_VIBENA);
 	twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
-			  TWL6040_VIBENAR);
+			  TWL6040_VIBENA);
 
 	info->enabled = true;
 }
@@ -201,6 +201,13 @@
 	struct vibra_info *info = input_get_drvdata(input);
 	int ret;
 
+	/* Do not allow effect, while the routing is set to use audio */
+	ret = twl6040_get_vibralr_status(info->twl6040);
+	if (ret & TWL6040_VIBSEL) {
+		dev_info(&input->dev, "Vibra is configured for audio\n");
+		return -EBUSY;
+	}
+
 	info->weak_speed = effect->u.rumble.weak_magnitude;
 	info->strong_speed = effect->u.rumble.strong_magnitude;
 	info->direction = effect->direction < EFFECT_DIR_180_DEG ? 1 : -1;
@@ -228,7 +235,7 @@
 	mutex_unlock(&info->mutex);
 }
 
-#if CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_SLEEP
 static int twl6040_vibra_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
diff -druN linux-libre-3.1-gnu/drivers/input/mouse/alps.c linux-libre-3.2-gnu/drivers/input/mouse/alps.c
--- linux-libre-3.1-gnu/drivers/input/mouse/alps.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/mouse/alps.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,13 +23,6 @@
 #include "psmouse.h"
 #include "alps.h"
 
-#undef DEBUG
-#ifdef DEBUG
-#define dbg(format, arg...) printk(KERN_INFO "alps.c: " format "\n", ## arg)
-#else
-#define dbg(format, arg...) do {} while (0)
-#endif
-
 #define ALPS_OLDPROTO		0x01	/* old style input */
 #define ALPS_DUALPOINT		0x02	/* touchpad has trackstick */
 #define ALPS_PASS		0x04	/* device has a pass-through port */
@@ -297,10 +290,10 @@
 		      psmouse->packet[4] |
 		      psmouse->packet[5]) & 0x80) ||
 		    (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) {
-			dbg("refusing packet %x %x %x %x "
-			    "(suspected interleaved ps/2)\n",
-			    psmouse->packet[3], psmouse->packet[4],
-			    psmouse->packet[5], psmouse->packet[6]);
+			psmouse_dbg(psmouse,
+				    "refusing packet %x %x %x %x (suspected interleaved ps/2)\n",
+				    psmouse->packet[3], psmouse->packet[4],
+				    psmouse->packet[5], psmouse->packet[6]);
 			return PSMOUSE_BAD_DATA;
 		}
 
@@ -319,13 +312,13 @@
 		 * There is also possibility that we got 6-byte ALPS
 		 * packet followed  by 3-byte packet from trackpoint. We
 		 * can not distinguish between these 2 scenarios but
-		 * becase the latter is unlikely to happen in course of
+		 * because the latter is unlikely to happen in course of
 		 * normal operation (user would need to press all
 		 * buttons on the pad and start moving trackpoint
 		 * without touching the pad surface) we assume former.
 		 * Even if we are wrong the wost thing that would happen
 		 * the cursor would jump but we should not get protocol
-		 * desynchronization.
+		 * de-synchronization.
 		 */
 
 		alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3],
@@ -361,10 +354,10 @@
 		if ((psmouse->packet[3] |
 		     psmouse->packet[4] |
 		     psmouse->packet[5]) & 0x80) {
-			dbg("refusing packet %x %x %x "
-			    "(suspected interleaved ps/2)\n",
-			    psmouse->packet[3], psmouse->packet[4],
-			    psmouse->packet[5]);
+			psmouse_dbg(psmouse,
+				    "refusing packet %x %x %x (suspected interleaved ps/2)\n",
+				    psmouse->packet[3], psmouse->packet[4],
+				    psmouse->packet[5]);
 		} else {
 			alps_process_packet(psmouse);
 		}
@@ -396,16 +389,18 @@
 	}
 
 	if (!alps_is_valid_first_byte(model, psmouse->packet[0])) {
-		dbg("refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n",
-		    psmouse->packet[0], model->mask0, model->byte0);
+		psmouse_dbg(psmouse,
+			    "refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n",
+			    psmouse->packet[0], model->mask0, model->byte0);
 		return PSMOUSE_BAD_DATA;
 	}
 
 	/* Bytes 2 - 6 should have 0 in the highest bit */
 	if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 &&
 	    (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
-		dbg("refusing packet[%i] = %x\n",
-		    psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]);
+		psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
+			    psmouse->pktcnt - 1,
+			    psmouse->packet[psmouse->pktcnt - 1]);
 		return PSMOUSE_BAD_DATA;
 	}
 
@@ -439,7 +434,8 @@
 	if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
 		return NULL;
 
-	dbg("E6 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
+	psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x",
+		    param[0], param[1], param[2]);
 
 	if (param[0] != 0 || param[1] != 0 || (param[2] != 10 && param[2] != 100))
 		return NULL;
@@ -459,7 +455,8 @@
 	if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
 		return NULL;
 
-	dbg("E7 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
+	psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x",
+		    param[0], param[1], param[2]);
 
 	if (version) {
 		for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++)
@@ -527,7 +524,8 @@
 	    ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
 		return -1;
 
-	dbg("Status: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
+	psmouse_dbg(psmouse, "Status: %2.2x %2.2x %2.2x",
+		    param[0], param[1], param[2]);
 
 	return 0;
 }
@@ -605,12 +603,12 @@
 	}
 
 	if (alps_tap_mode(psmouse, true)) {
-		printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n");
+		psmouse_warn(psmouse, "Failed to enable hardware tapping\n");
 		return -1;
 	}
 
 	if (alps_absolute_mode(psmouse)) {
-		printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
+		psmouse_err(psmouse, "Failed to enable absolute mode\n");
 		return -1;
 	}
 
@@ -621,7 +619,7 @@
 
 	/* ALPS needs stream mode, otherwise it won't report any data */
 	if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) {
-		printk(KERN_ERR "alps.c: Failed to enable stream mode\n");
+		psmouse_err(psmouse, "Failed to enable stream mode\n");
 		return -1;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/input/mouse/elantech.c linux-libre-3.2-gnu/drivers/input/mouse/elantech.c
--- linux-libre-3.1-gnu/drivers/input/mouse/elantech.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/mouse/elantech.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,8 +10,6 @@
  * Trademarks are the property of their respective owners.
  */
 
-#define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
-
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -25,13 +23,10 @@
 #define elantech_debug(fmt, ...)					\
 	do {								\
 		if (etd->debug)						\
-			printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__);	\
+			psmouse_printk(KERN_DEBUG, psmouse,		\
+					fmt, ##__VA_ARGS__);		\
 	} while (0)
 
-static bool force_elantech;
-module_param_named(force_elantech, force_elantech, bool, 0644);
-MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default).");
-
 /*
  * Send a Synaptics style sliced query command
  */
@@ -40,7 +35,7 @@
 {
 	if (psmouse_sliced_command(psmouse, c) ||
 	    ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) {
-		pr_err("synaptics_send_cmd query 0x%02x failed.\n", c);
+		psmouse_err(psmouse, "%s query 0x%02x failed.\n", __func__, c);
 		return -1;
 	}
 
@@ -69,7 +64,7 @@
 	} while (tries > 0);
 
 	if (rc)
-		pr_err("ps2 command 0x%02x failed.\n", command);
+		psmouse_err(psmouse, "ps2 command 0x%02x failed.\n", command);
 
 	return rc;
 }
@@ -84,7 +79,7 @@
 	unsigned char param[3];
 	int rc = 0;
 
-	if (reg < 0x10 || reg > 0x26)
+	if (reg < 0x07 || reg > 0x26)
 		return -1;
 
 	if (reg > 0x11 && reg < 0x20)
@@ -108,12 +103,24 @@
 			rc = -1;
 		}
 		break;
+
+	case 3 ... 4:
+		if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, reg) ||
+		    elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) {
+			rc = -1;
+		}
+		break;
 	}
 
 	if (rc)
-		pr_err("failed to read register 0x%02x.\n", reg);
-	else
+		psmouse_err(psmouse, "failed to read register 0x%02x.\n", reg);
+	else if (etd->hw_version != 4)
 		*val = param[0];
+	else
+		*val = param[1];
 
 	return rc;
 }
@@ -127,7 +134,7 @@
 	struct elantech_data *etd = psmouse->private;
 	int rc = 0;
 
-	if (reg < 0x10 || reg > 0x26)
+	if (reg < 0x07 || reg > 0x26)
 		return -1;
 
 	if (reg > 0x11 && reg < 0x20)
@@ -154,11 +161,38 @@
 			rc = -1;
 		}
 		break;
+
+	case 3:
+		if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, reg) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, val) ||
+		    elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
+			rc = -1;
+		}
+		break;
+
+	case 4:
+		if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, reg) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+		    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+		    elantech_ps2_command(psmouse, NULL, val) ||
+		    elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
+			rc = -1;
+		}
+		break;
 	}
 
 	if (rc)
-		pr_err("failed to write register 0x%02x with value 0x%02x.\n",
-			reg, val);
+		psmouse_err(psmouse,
+			    "failed to write register 0x%02x with value 0x%02x.\n",
+			    reg, val);
 
 	return rc;
 }
@@ -166,13 +200,13 @@
 /*
  * Dump a complete mouse movement packet to the syslog
  */
-static void elantech_packet_dump(unsigned char *packet, int size)
+static void elantech_packet_dump(struct psmouse *psmouse)
 {
 	int	i;
 
-	printk(KERN_DEBUG pr_fmt("PS/2 packet ["));
-	for (i = 0; i < size; i++)
-		printk("%s0x%02x ", (i) ? ", " : " ", packet[i]);
+	psmouse_printk(KERN_DEBUG, psmouse, "PS/2 packet [");
+	for (i = 0; i < psmouse->pktsize; i++)
+		printk("%s0x%02x ", i ? ", " : " ", psmouse->packet[i]);
 	printk("]\n");
 }
 
@@ -223,7 +257,7 @@
 		input_report_abs(dev, ABS_X,
 			((packet[1] & 0x0c) << 6) | packet[2]);
 		input_report_abs(dev, ABS_Y,
-			ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3]));
+			etd->y_max - (((packet[1] & 0x03) << 8) | packet[3]));
 	}
 
 	input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
@@ -233,7 +267,7 @@
 	input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
 
 	if (etd->fw_version < 0x020000 &&
-	    (etd->capabilities & ETP_CAP_HAS_ROCKER)) {
+	    (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) {
 		/* rocker up */
 		input_report_key(dev, BTN_FORWARD, packet[0] & 0x40);
 		/* rocker down */
@@ -273,11 +307,11 @@
 	struct elantech_data *etd = psmouse->private;
 	struct input_dev *dev = psmouse->dev;
 	unsigned char *packet = psmouse->packet;
-	unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0, width = 0, pres = 0;
+	unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+	unsigned int width = 0, pres = 0;
 
 	/* byte 0: n1  n0   .   .   .   .   R   L */
 	fingers = (packet[0] & 0xc0) >> 6;
-	input_report_key(dev, BTN_TOUCH, fingers != 0);
 
 	switch (fingers) {
 	case 3:
@@ -290,18 +324,15 @@
 		/* pass through... */
 	case 1:
 		/*
-		 * byte 1:  .   .   .   .   .  x10 x9  x8
+		 * byte 1:  .   .   .   .  x11 x10 x9  x8
 		 * byte 2: x7  x6  x5  x4  x4  x2  x1  x0
 		 */
-		x1 = ((packet[1] & 0x07) << 8) | packet[2];
+		x1 = ((packet[1] & 0x0f) << 8) | packet[2];
 		/*
-		 * byte 4:  .   .   .   .   .   .  y9  y8
+		 * byte 4:  .   .   .   .  y11 y10 y9  y8
 		 * byte 5: y7  y6  y5  y4  y3  y2  y1  y0
 		 */
-		y1 = ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5]);
-
-		input_report_abs(dev, ABS_X, x1);
-		input_report_abs(dev, ABS_Y, y1);
+		y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
 
 		pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
 		width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4);
@@ -314,22 +345,18 @@
 		 * byte 0:  .   .  ay8 ax8  .   .   .   .
 		 * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0
 		 */
-		x1 = ((packet[0] & 0x10) << 4) | packet[1];
+		x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2;
 		/* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */
-		y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]);
+		y1 = etd->y_max -
+			((((packet[0] & 0x20) << 3) | packet[2]) << 2);
 		/*
 		 * byte 3:  .   .  by8 bx8  .   .   .   .
 		 * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0
 		 */
-		x2 = ((packet[3] & 0x10) << 4) | packet[4];
+		x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2;
 		/* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */
-		y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]);
-		/*
-		 * For compatibility with the X Synaptics driver scale up
-		 * one coordinate and report as ordinary mouse movent
-		 */
-		input_report_abs(dev, ABS_X, x1 << 2);
-		input_report_abs(dev, ABS_Y, y1 << 2);
+		y2 = etd->y_max -
+			((((packet[3] & 0x20) << 3) | packet[5]) << 2);
 
 		/* Unknown so just report sensible values */
 		pres = 127;
@@ -337,6 +364,11 @@
 		break;
 	}
 
+	input_report_key(dev, BTN_TOUCH, fingers != 0);
+	if (fingers != 0) {
+		input_report_abs(dev, ABS_X, x1);
+		input_report_abs(dev, ABS_Y, y1);
+	}
 	elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
 	input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
 	input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
@@ -352,7 +384,208 @@
 	input_sync(dev);
 }
 
-static int elantech_check_parity_v1(struct psmouse *psmouse)
+/*
+ * Interpret complete data packets and report absolute mode input events for
+ * hardware version 3. (12 byte packets for two fingers)
+ */
+static void elantech_report_absolute_v3(struct psmouse *psmouse,
+					int packet_type)
+{
+	struct input_dev *dev = psmouse->dev;
+	struct elantech_data *etd = psmouse->private;
+	unsigned char *packet = psmouse->packet;
+	unsigned int fingers = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+	unsigned int width = 0, pres = 0;
+
+	/* byte 0: n1  n0   .   .   .   .   R   L */
+	fingers = (packet[0] & 0xc0) >> 6;
+
+	switch (fingers) {
+	case 3:
+	case 1:
+		/*
+		 * byte 1:  .   .   .   .  x11 x10 x9  x8
+		 * byte 2: x7  x6  x5  x4  x4  x2  x1  x0
+		 */
+		x1 = ((packet[1] & 0x0f) << 8) | packet[2];
+		/*
+		 * byte 4:  .   .   .   .  y11 y10 y9  y8
+		 * byte 5: y7  y6  y5  y4  y3  y2  y1  y0
+		 */
+		y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
+		break;
+
+	case 2:
+		if (packet_type == PACKET_V3_HEAD) {
+			/*
+			 * byte 1:   .    .    .    .  ax11 ax10 ax9  ax8
+			 * byte 2: ax7  ax6  ax5  ax4  ax3  ax2  ax1  ax0
+			 */
+			etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2];
+			/*
+			 * byte 4:   .    .    .    .  ay11 ay10 ay9  ay8
+			 * byte 5: ay7  ay6  ay5  ay4  ay3  ay2  ay1  ay0
+			 */
+			etd->mt[0].y = etd->y_max -
+				(((packet[4] & 0x0f) << 8) | packet[5]);
+			/*
+			 * wait for next packet
+			 */
+			return;
+		}
+
+		/* packet_type == PACKET_V3_TAIL */
+		x1 = etd->mt[0].x;
+		y1 = etd->mt[0].y;
+		x2 = ((packet[1] & 0x0f) << 8) | packet[2];
+		y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
+		break;
+	}
+
+	pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
+	width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4);
+
+	input_report_key(dev, BTN_TOUCH, fingers != 0);
+	if (fingers != 0) {
+		input_report_abs(dev, ABS_X, x1);
+		input_report_abs(dev, ABS_Y, y1);
+	}
+	elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
+	input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
+	input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
+	input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
+	input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
+	input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
+	input_report_abs(dev, ABS_PRESSURE, pres);
+	input_report_abs(dev, ABS_TOOL_WIDTH, width);
+
+	input_sync(dev);
+}
+
+static void elantech_input_sync_v4(struct psmouse *psmouse)
+{
+	struct input_dev *dev = psmouse->dev;
+	unsigned char *packet = psmouse->packet;
+
+	input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
+	input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
+	input_mt_report_pointer_emulation(dev, true);
+	input_sync(dev);
+}
+
+static void process_packet_status_v4(struct psmouse *psmouse)
+{
+	struct input_dev *dev = psmouse->dev;
+	unsigned char *packet = psmouse->packet;
+	unsigned fingers;
+	int i;
+
+	/* notify finger state change */
+	fingers = packet[1] & 0x1f;
+	for (i = 0; i < ETP_MAX_FINGERS; i++) {
+		if ((fingers & (1 << i)) == 0) {
+			input_mt_slot(dev, i);
+			input_mt_report_slot_state(dev, MT_TOOL_FINGER, false);
+		}
+	}
+
+	elantech_input_sync_v4(psmouse);
+}
+
+static void process_packet_head_v4(struct psmouse *psmouse)
+{
+	struct input_dev *dev = psmouse->dev;
+	struct elantech_data *etd = psmouse->private;
+	unsigned char *packet = psmouse->packet;
+	int id = ((packet[3] & 0xe0) >> 5) - 1;
+	int pres, traces;
+
+	if (id < 0)
+		return;
+
+	etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2];
+	etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
+	pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
+	traces = (packet[0] & 0xf0) >> 4;
+
+	input_mt_slot(dev, id);
+	input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+
+	input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x);
+	input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y);
+	input_report_abs(dev, ABS_MT_PRESSURE, pres);
+	input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width);
+	/* report this for backwards compatibility */
+	input_report_abs(dev, ABS_TOOL_WIDTH, traces);
+
+	elantech_input_sync_v4(psmouse);
+}
+
+static void process_packet_motion_v4(struct psmouse *psmouse)
+{
+	struct input_dev *dev = psmouse->dev;
+	struct elantech_data *etd = psmouse->private;
+	unsigned char *packet = psmouse->packet;
+	int weight, delta_x1 = 0, delta_y1 = 0, delta_x2 = 0, delta_y2 = 0;
+	int id, sid;
+
+	id = ((packet[0] & 0xe0) >> 5) - 1;
+	if (id < 0)
+		return;
+
+	sid = ((packet[3] & 0xe0) >> 5) - 1;
+	weight = (packet[0] & 0x10) ? ETP_WEIGHT_VALUE : 1;
+	/*
+	 * Motion packets give us the delta of x, y values of specific fingers,
+	 * but in two's complement. Let the compiler do the conversion for us.
+	 * Also _enlarge_ the numbers to int, in case of overflow.
+	 */
+	delta_x1 = (signed char)packet[1];
+	delta_y1 = (signed char)packet[2];
+	delta_x2 = (signed char)packet[4];
+	delta_y2 = (signed char)packet[5];
+
+	etd->mt[id].x += delta_x1 * weight;
+	etd->mt[id].y -= delta_y1 * weight;
+	input_mt_slot(dev, id);
+	input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x);
+	input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y);
+
+	if (sid >= 0) {
+		etd->mt[sid].x += delta_x2 * weight;
+		etd->mt[sid].y -= delta_y2 * weight;
+		input_mt_slot(dev, sid);
+		input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[sid].x);
+		input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[sid].y);
+	}
+
+	elantech_input_sync_v4(psmouse);
+}
+
+static void elantech_report_absolute_v4(struct psmouse *psmouse,
+					int packet_type)
+{
+	switch (packet_type) {
+	case PACKET_V4_STATUS:
+		process_packet_status_v4(psmouse);
+		break;
+
+	case PACKET_V4_HEAD:
+		process_packet_head_v4(psmouse);
+		break;
+
+	case PACKET_V4_MOTION:
+		process_packet_motion_v4(psmouse);
+		break;
+
+	case PACKET_UNKNOWN:
+	default:
+		/* impossible to get here */
+		break;
+	}
+}
+
+static int elantech_packet_check_v1(struct psmouse *psmouse)
 {
 	struct elantech_data *etd = psmouse->private;
 	unsigned char *packet = psmouse->packet;
@@ -376,31 +609,142 @@
 	       etd->parity[packet[3]] == p3;
 }
 
+static int elantech_debounce_check_v2(struct psmouse *psmouse)
+{
+        /*
+         * When we encounter packet that matches this exactly, it means the
+         * hardware is in debounce status. Just ignore the whole packet.
+         */
+        const u8 debounce_packet[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff };
+        unsigned char *packet = psmouse->packet;
+
+        return !memcmp(packet, debounce_packet, sizeof(debounce_packet));
+}
+
+static int elantech_packet_check_v2(struct psmouse *psmouse)
+{
+	struct elantech_data *etd = psmouse->private;
+	unsigned char *packet = psmouse->packet;
+
+	/*
+	 * V2 hardware has two flavors. Older ones that do not report pressure,
+	 * and newer ones that reports pressure and width. With newer ones, all
+	 * packets (1, 2, 3 finger touch) have the same constant bits. With
+	 * older ones, 1/3 finger touch packets and 2 finger touch packets
+	 * have different constant bits.
+	 * With all three cases, if the constant bits are not exactly what I
+	 * expected, I consider them invalid.
+	 */
+	if (etd->reports_pressure)
+		return (packet[0] & 0x0c) == 0x04 &&
+		       (packet[3] & 0x0f) == 0x02;
+
+	if ((packet[0] & 0xc0) == 0x80)
+		return (packet[0] & 0x0c) == 0x0c &&
+		       (packet[3] & 0x0e) == 0x08;
+
+	return (packet[0] & 0x3c) == 0x3c &&
+	       (packet[1] & 0xf0) == 0x00 &&
+	       (packet[3] & 0x3e) == 0x38 &&
+	       (packet[4] & 0xf0) == 0x00;
+}
+
+/*
+ * We check the constant bits to determine what packet type we get,
+ * so packet checking is mandatory for v3 and later hardware.
+ */
+static int elantech_packet_check_v3(struct psmouse *psmouse)
+{
+	const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff };
+	unsigned char *packet = psmouse->packet;
+
+	/*
+	 * check debounce first, it has the same signature in byte 0
+	 * and byte 3 as PACKET_V3_HEAD.
+	 */
+	if (!memcmp(packet, debounce_packet, sizeof(debounce_packet)))
+		return PACKET_DEBOUNCE;
+
+	if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02)
+		return PACKET_V3_HEAD;
+
+	if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
+		return PACKET_V3_TAIL;
+
+	return PACKET_UNKNOWN;
+}
+
+static int elantech_packet_check_v4(struct psmouse *psmouse)
+{
+	unsigned char *packet = psmouse->packet;
+
+	if ((packet[0] & 0x0c) == 0x04 &&
+	    (packet[3] & 0x1f) == 0x11)
+		return PACKET_V4_HEAD;
+
+	if ((packet[0] & 0x0c) == 0x04 &&
+	    (packet[3] & 0x1f) == 0x12)
+		return PACKET_V4_MOTION;
+
+	if ((packet[0] & 0x0c) == 0x04 &&
+	    (packet[3] & 0x1f) == 0x10)
+		return PACKET_V4_STATUS;
+
+	return PACKET_UNKNOWN;
+}
+
 /*
  * Process byte stream from mouse and handle complete packets
  */
 static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
 {
 	struct elantech_data *etd = psmouse->private;
+	int packet_type;
 
 	if (psmouse->pktcnt < psmouse->pktsize)
 		return PSMOUSE_GOOD_DATA;
 
 	if (etd->debug > 1)
-		elantech_packet_dump(psmouse->packet, psmouse->pktsize);
+		elantech_packet_dump(psmouse);
 
 	switch (etd->hw_version) {
 	case 1:
-		if (etd->paritycheck && !elantech_check_parity_v1(psmouse))
+		if (etd->paritycheck && !elantech_packet_check_v1(psmouse))
 			return PSMOUSE_BAD_DATA;
 
 		elantech_report_absolute_v1(psmouse);
 		break;
 
 	case 2:
-		/* We don't know how to check parity in protocol v2 */
+		/* ignore debounce */
+		if (elantech_debounce_check_v2(psmouse))
+			return PSMOUSE_FULL_PACKET;
+
+		if (etd->paritycheck && !elantech_packet_check_v2(psmouse))
+			return PSMOUSE_BAD_DATA;
+
 		elantech_report_absolute_v2(psmouse);
 		break;
+
+	case 3:
+		packet_type = elantech_packet_check_v3(psmouse);
+		/* ignore debounce */
+		if (packet_type == PACKET_DEBOUNCE)
+			return PSMOUSE_FULL_PACKET;
+
+		if (packet_type == PACKET_UNKNOWN)
+			return PSMOUSE_BAD_DATA;
+
+		elantech_report_absolute_v3(psmouse, packet_type);
+		break;
+
+	case 4:
+		packet_type = elantech_packet_check_v4(psmouse);
+		if (packet_type == PACKET_UNKNOWN)
+			return PSMOUSE_BAD_DATA;
+
+		elantech_report_absolute_v4(psmouse, packet_type);
+		break;
 	}
 
 	return PSMOUSE_FULL_PACKET;
@@ -435,15 +779,29 @@
 		    elantech_write_reg(psmouse, 0x11, etd->reg_11) ||
 		    elantech_write_reg(psmouse, 0x21, etd->reg_21)) {
 			rc = -1;
-			break;
 		}
+		break;
+
+	case 3:
+		etd->reg_10 = 0x0b;
+		if (elantech_write_reg(psmouse, 0x10, etd->reg_10))
+			rc = -1;
+
+		break;
+
+	case 4:
+		etd->reg_07 = 0x01;
+		if (elantech_write_reg(psmouse, 0x07, etd->reg_07))
+			rc = -1;
+
+		goto skip_readback_reg_10; /* v4 has no reg 0x10 to read */
 	}
 
 	if (rc == 0) {
 		/*
 		 * Read back reg 0x10. For hardware version 1 we must make
 		 * sure the absolute mode bit is set. For hardware version 2
-		 * the touchpad is probably initalising and not ready until
+		 * the touchpad is probably initializing and not ready until
 		 * we read back the value we just wrote.
 		 */
 		do {
@@ -456,27 +814,115 @@
 		} while (tries > 0);
 
 		if (rc) {
-			pr_err("failed to read back register 0x10.\n");
+			psmouse_err(psmouse,
+				    "failed to read back register 0x10.\n");
 		} else if (etd->hw_version == 1 &&
 			   !(val & ETP_R10_ABSOLUTE_MODE)) {
-			pr_err("touchpad refuses to switch to absolute mode.\n");
+			psmouse_err(psmouse,
+				    "touchpad refuses to switch to absolute mode.\n");
 			rc = -1;
 		}
 	}
 
+ skip_readback_reg_10:
 	if (rc)
-		pr_err("failed to initialise registers.\n");
+		psmouse_err(psmouse, "failed to initialise registers.\n");
 
 	return rc;
 }
 
+static int elantech_set_range(struct psmouse *psmouse,
+			      unsigned int *x_min, unsigned int *y_min,
+			      unsigned int *x_max, unsigned int *y_max,
+			      unsigned int *width)
+{
+	struct elantech_data *etd = psmouse->private;
+	unsigned char param[3];
+	unsigned char traces;
+
+	switch (etd->hw_version) {
+	case 1:
+		*x_min = ETP_XMIN_V1;
+		*y_min = ETP_YMIN_V1;
+		*x_max = ETP_XMAX_V1;
+		*y_max = ETP_YMAX_V1;
+		break;
+
+	case 2:
+		if (etd->fw_version == 0x020800 ||
+		    etd->fw_version == 0x020b00 ||
+		    etd->fw_version == 0x020030) {
+			*x_min = ETP_XMIN_V2;
+			*y_min = ETP_YMIN_V2;
+			*x_max = ETP_XMAX_V2;
+			*y_max = ETP_YMAX_V2;
+		} else {
+			int i;
+			int fixed_dpi;
+
+			i = (etd->fw_version > 0x020800 &&
+			     etd->fw_version < 0x020900) ? 1 : 2;
+
+			if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+				return -1;
+
+			fixed_dpi = param[1] & 0x10;
+
+			if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) {
+				if (synaptics_send_cmd(psmouse, ETP_SAMPLE_QUERY, param))
+					return -1;
+
+				*x_max = (etd->capabilities[1] - i) * param[1] / 2;
+				*y_max = (etd->capabilities[2] - i) * param[2] / 2;
+			} else if (etd->fw_version == 0x040216) {
+				*x_max = 819;
+				*y_max = 405;
+			} else if (etd->fw_version == 0x040219 || etd->fw_version == 0x040215) {
+				*x_max = 900;
+				*y_max = 500;
+			} else {
+				*x_max = (etd->capabilities[1] - i) * 64;
+				*y_max = (etd->capabilities[2] - i) * 64;
+			}
+		}
+		break;
+
+	case 3:
+		if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+			return -1;
+
+		*x_max = (0x0f & param[0]) << 8 | param[1];
+		*y_max = (0xf0 & param[0]) << 4 | param[2];
+		break;
+
+	case 4:
+		if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+			return -1;
+
+		*x_max = (0x0f & param[0]) << 8 | param[1];
+		*y_max = (0xf0 & param[0]) << 4 | param[2];
+		traces = etd->capabilities[1];
+		if ((traces < 2) || (traces > *x_max))
+			return -1;
+
+		*width = *x_max / (traces - 1);
+		break;
+	}
+
+	return 0;
+}
+
 /*
  * Set the appropriate event bits for the input subsystem
  */
-static void elantech_set_input_params(struct psmouse *psmouse)
+static int elantech_set_input_params(struct psmouse *psmouse)
 {
 	struct input_dev *dev = psmouse->dev;
 	struct elantech_data *etd = psmouse->private;
+	unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
+
+	if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width))
+		return -1;
 
 	__set_bit(EV_KEY, dev->evbit);
 	__set_bit(EV_ABS, dev->evbit);
@@ -494,30 +940,64 @@
 	case 1:
 		/* Rocker button */
 		if (etd->fw_version < 0x020000 &&
-		    (etd->capabilities & ETP_CAP_HAS_ROCKER)) {
+		    (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) {
 			__set_bit(BTN_FORWARD, dev->keybit);
 			__set_bit(BTN_BACK, dev->keybit);
 		}
-		input_set_abs_params(dev, ABS_X, ETP_XMIN_V1, ETP_XMAX_V1, 0, 0);
-		input_set_abs_params(dev, ABS_Y, ETP_YMIN_V1, ETP_YMAX_V1, 0, 0);
+		input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
+		input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
 		break;
 
 	case 2:
 		__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
-		input_set_abs_params(dev, ABS_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0);
-		input_set_abs_params(dev, ABS_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0);
+		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
+		/* fall through */
+	case 3:
+		input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
+		input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
 		if (etd->reports_pressure) {
 			input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2,
 					     ETP_PMAX_V2, 0, 0);
 			input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
 					     ETP_WMAX_V2, 0, 0);
 		}
-		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
 		input_mt_init_slots(dev, 2);
-		input_set_abs_params(dev, ABS_MT_POSITION_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0);
-		input_set_abs_params(dev, ABS_MT_POSITION_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0);
+		input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
+		input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
+		break;
+
+	case 4:
+		__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
+		/* For X to recognize me as touchpad. */
+		input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
+		input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
+		/*
+		 * range of pressure and width is the same as v2,
+		 * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility.
+		 */
+		input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2,
+				     ETP_PMAX_V2, 0, 0);
+		input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
+				     ETP_WMAX_V2, 0, 0);
+		/* Multitouch capable pad, up to 5 fingers. */
+		input_mt_init_slots(dev, ETP_MAX_FINGERS);
+		input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
+		input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
+		input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2,
+				     ETP_PMAX_V2, 0, 0);
+		/*
+		 * The firmware reports how many trace lines the finger spans,
+		 * convert to surface unit as Protocol-B requires.
+		 */
+		input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0,
+				     ETP_WMAX_V2 * width, 0, 0);
 		break;
 	}
+
+	etd->y_max = y_max;
+	etd->width = width;
+
+	return 0;
 }
 
 struct elantech_attr_data {
@@ -587,6 +1067,7 @@
 			    elantech_show_int_attr,			\
 			    elantech_set_int_attr)
 
+ELANTECH_INT_ATTR(reg_07, 0x07);
 ELANTECH_INT_ATTR(reg_10, 0x10);
 ELANTECH_INT_ATTR(reg_11, 0x11);
 ELANTECH_INT_ATTR(reg_20, 0x20);
@@ -600,6 +1081,7 @@
 ELANTECH_INT_ATTR(paritycheck, 0);
 
 static struct attribute *elantech_attrs[] = {
+	&psmouse_attr_reg_07.dattr.attr,
 	&psmouse_attr_reg_10.dattr.attr,
 	&psmouse_attr_reg_11.dattr.attr,
 	&psmouse_attr_reg_20.dattr.attr,
@@ -651,7 +1133,7 @@
 	    ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE11) ||
 	    ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE11) ||
 	    ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) {
-		pr_debug("sending Elantech magic knock failed.\n");
+		psmouse_dbg(psmouse, "sending Elantech magic knock failed.\n");
 		return -1;
 	}
 
@@ -659,9 +1141,11 @@
 	 * Report this in case there are Elantech models that use a different
 	 * set of magic numbers
 	 */
-	if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) {
-		pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n",
-			 param[0], param[1], param[2]);
+	if (param[0] != 0x3c || param[1] != 0x03 ||
+	    (param[2] != 0xc8 && param[2] != 0x00)) {
+		psmouse_dbg(psmouse,
+			    "unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n",
+			    param[0], param[1], param[2]);
 		return -1;
 	}
 
@@ -671,20 +1155,18 @@
 	 * to Elantech magic knock and there might be more.
 	 */
 	if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) {
-		pr_debug("failed to query firmware version.\n");
+		psmouse_dbg(psmouse, "failed to query firmware version.\n");
 		return -1;
 	}
 
-	pr_debug("Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n",
-		 param[0], param[1], param[2]);
+	psmouse_dbg(psmouse,
+		    "Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n",
+		    param[0], param[1], param[2]);
 
 	if (!elantech_is_signature_valid(param)) {
-		if (!force_elantech) {
-			pr_debug("Probably not a real Elantech touchpad. Aborting.\n");
-			return -1;
-		}
-
-		pr_debug("Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n");
+		psmouse_dbg(psmouse,
+			    "Probably not a real Elantech touchpad. Aborting.\n");
+		return -1;
 	}
 
 	if (set_properties) {
@@ -715,7 +1197,8 @@
 		return -1;
 
 	if (elantech_set_absolute_mode(psmouse)) {
-		pr_err("failed to put touchpad back into absolute mode.\n");
+		psmouse_err(psmouse,
+			    "failed to put touchpad back into absolute mode.\n");
 		return -1;
 	}
 
@@ -723,6 +1206,58 @@
 }
 
 /*
+ * determine hardware version and set some properties according to it.
+ */
+static int elantech_set_properties(struct elantech_data *etd)
+{
+	/* This represents the version of IC body. */
+	int ver = (etd->fw_version & 0x0f0000) >> 16;
+
+	/* Early version of Elan touchpads doesn't obey the rule. */
+	if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600)
+		etd->hw_version = 1;
+	else {
+		switch (ver) {
+		case 2:
+		case 4:
+			etd->hw_version = 2;
+			break;
+		case 5:
+			etd->hw_version = 3;
+			break;
+		case 6:
+			etd->hw_version = 4;
+			break;
+		default:
+			return -1;
+		}
+	}
+
+	/*
+	 * Turn on packet checking by default.
+	 */
+	etd->paritycheck = 1;
+
+	/*
+	 * This firmware suffers from misreporting coordinates when
+	 * a touch action starts causing the mouse cursor or scrolled page
+	 * to jump. Enable a workaround.
+	 */
+	etd->jumpy_cursor =
+		(etd->fw_version == 0x020022 || etd->fw_version == 0x020600);
+
+	if (etd->hw_version > 1) {
+		/* For now show extra debug information */
+		etd->debug = 1;
+
+		if (etd->fw_version >= 0x020800)
+			etd->reports_pressure = true;
+	}
+
+	return 0;
+}
+
+/*
  * Initialize the touchpad and create sysfs entries
  */
 int elantech_init(struct psmouse *psmouse)
@@ -743,70 +1278,53 @@
 	 * Do the version query again so we can store the result
 	 */
 	if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) {
-		pr_err("failed to query firmware version.\n");
+		psmouse_err(psmouse, "failed to query firmware version.\n");
 		goto init_fail;
 	}
-
 	etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2];
 
-	/*
-	 * Assume every version greater than this is new EeePC style
-	 * hardware with 6 byte packets
-	 */
-	if (etd->fw_version >= 0x020030) {
-		etd->hw_version = 2;
-		/* For now show extra debug information */
-		etd->debug = 1;
-		/* Don't know how to do parity checking for version 2 */
-		etd->paritycheck = 0;
-
-		if (etd->fw_version >= 0x020800)
-			etd->reports_pressure = true;
-
-	} else {
-		etd->hw_version = 1;
-		etd->paritycheck = 1;
-	}
-
-	pr_info("assuming hardware version %d, firmware version %d.%d.%d\n",
-		etd->hw_version, param[0], param[1], param[2]);
-
-	if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) {
-		pr_err("failed to query capabilities.\n");
+	if (elantech_set_properties(etd)) {
+		psmouse_err(psmouse, "unknown hardware version, aborting...\n");
 		goto init_fail;
 	}
-	pr_info("Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n",
-		param[0], param[1], param[2]);
-	etd->capabilities = param[0];
+	psmouse_info(psmouse,
+		     "assuming hardware version %d (with firmware version 0x%02x%02x%02x)\n",
+		     etd->hw_version, param[0], param[1], param[2]);
 
-	/*
-	 * This firmware suffers from misreporting coordinates when
-	 * a touch action starts causing the mouse cursor or scrolled page
-	 * to jump. Enable a workaround.
-	 */
-	if (etd->fw_version == 0x020022 || etd->fw_version == 0x020600) {
-		pr_info("firmware version 2.0.34/2.6.0 detected, enabling jumpy cursor workaround\n");
-		etd->jumpy_cursor = true;
+	if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY,
+	    etd->capabilities)) {
+		psmouse_err(psmouse, "failed to query capabilities.\n");
+		goto init_fail;
 	}
+	psmouse_info(psmouse,
+		     "Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n",
+		     etd->capabilities[0], etd->capabilities[1],
+		     etd->capabilities[2]);
 
 	if (elantech_set_absolute_mode(psmouse)) {
-		pr_err("failed to put touchpad into absolute mode.\n");
+		psmouse_err(psmouse,
+			    "failed to put touchpad into absolute mode.\n");
 		goto init_fail;
 	}
 
-	elantech_set_input_params(psmouse);
+	if (elantech_set_input_params(psmouse)) {
+		psmouse_err(psmouse, "failed to query touchpad range.\n");
+		goto init_fail;
+	}
 
 	error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj,
 				   &elantech_attr_group);
 	if (error) {
-		pr_err("failed to create sysfs attributes, error: %d.\n", error);
+		psmouse_err(psmouse,
+			    "failed to create sysfs attributes, error: %d.\n",
+			    error);
 		goto init_fail;
 	}
 
 	psmouse->protocol_handler = elantech_process_byte;
 	psmouse->disconnect = elantech_disconnect;
 	psmouse->reconnect = elantech_reconnect;
-	psmouse->pktsize = etd->hw_version == 2 ? 6 : 4;
+	psmouse->pktsize = etd->hw_version > 1 ? 6 : 4;
 
 	return 0;
 
diff -druN linux-libre-3.1-gnu/drivers/input/mouse/elantech.h linux-libre-3.2-gnu/drivers/input/mouse/elantech.h
--- linux-libre-3.1-gnu/drivers/input/mouse/elantech.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/mouse/elantech.h	2012-01-04 18:55:44.000000000 -0500
@@ -16,14 +16,17 @@
 /*
  * Command values for Synaptics style queries
  */
+#define ETP_FW_ID_QUERY			0x00
 #define ETP_FW_VERSION_QUERY		0x01
 #define ETP_CAPABILITIES_QUERY		0x02
+#define ETP_SAMPLE_QUERY		0x03
 
 /*
  * Command values for register reading or writing
  */
 #define ETP_REGISTER_READ		0x10
 #define ETP_REGISTER_WRITE		0x11
+#define ETP_REGISTER_READWRITE		0x00
 
 /*
  * Hardware version 2 custom PS/2 command value
@@ -66,16 +69,13 @@
 #define ETP_YMAX_V1			(384 - ETP_EDGE_FUZZ_V1)
 
 /*
- * It seems the resolution for hardware version 2 doubled.
- * Hence the X and Y ranges are doubled too.
- * The bezel around the pad also appears to be smaller
+ * The resolution for older v2 hardware doubled.
+ * (newer v2's firmware provides command so we can query)
  */
-#define ETP_EDGE_FUZZ_V2		8
-
-#define ETP_XMIN_V2			(   0 + ETP_EDGE_FUZZ_V2)
-#define ETP_XMAX_V2			(1152 - ETP_EDGE_FUZZ_V2)
-#define ETP_YMIN_V2			(   0 + ETP_EDGE_FUZZ_V2)
-#define ETP_YMAX_V2			( 768 - ETP_EDGE_FUZZ_V2)
+#define ETP_XMIN_V2			0
+#define ETP_XMAX_V2			1152
+#define ETP_YMIN_V2			0
+#define ETP_YMAX_V2			768
 
 #define ETP_PMIN_V2			0
 #define ETP_PMAX_V2			255
@@ -83,17 +83,37 @@
 #define ETP_WMAX_V2			15
 
 /*
- * For two finger touches the coordinate of each finger gets reported
- * separately but with reduced resolution.
+ * v3 hardware has 2 kinds of packet types,
+ * v4 hardware has 3.
  */
-#define ETP_2FT_FUZZ			4
+#define PACKET_UNKNOWN			0x01
+#define PACKET_DEBOUNCE			0x02
+#define PACKET_V3_HEAD			0x03
+#define PACKET_V3_TAIL			0x04
+#define PACKET_V4_HEAD			0x05
+#define PACKET_V4_MOTION		0x06
+#define PACKET_V4_STATUS		0x07
 
-#define ETP_2FT_XMIN			(  0 + ETP_2FT_FUZZ)
-#define ETP_2FT_XMAX			(288 - ETP_2FT_FUZZ)
-#define ETP_2FT_YMIN			(  0 + ETP_2FT_FUZZ)
-#define ETP_2FT_YMAX			(192 - ETP_2FT_FUZZ)
+/*
+ * track up to 5 fingers for v4 hardware
+ */
+#define ETP_MAX_FINGERS			5
+
+/*
+ * weight value for v4 hardware
+ */
+#define ETP_WEIGHT_VALUE		5
+
+/*
+ * The base position for one finger, v4 hardware
+ */
+struct finger_pos {
+	unsigned int x;
+	unsigned int y;
+};
 
 struct elantech_data {
+	unsigned char reg_07;
 	unsigned char reg_10;
 	unsigned char reg_11;
 	unsigned char reg_20;
@@ -104,13 +124,16 @@
 	unsigned char reg_25;
 	unsigned char reg_26;
 	unsigned char debug;
-	unsigned char capabilities;
+	unsigned char capabilities[3];
 	bool paritycheck;
 	bool jumpy_cursor;
 	bool reports_pressure;
 	unsigned char hw_version;
 	unsigned int fw_version;
 	unsigned int single_finger_reports;
+	unsigned int y_max;
+	unsigned int width;
+	struct finger_pos mt[ETP_MAX_FINGERS];
 	unsigned char parity[256];
 };
 
diff -druN linux-libre-3.1-gnu/drivers/input/mouse/hgpk.c linux-libre-3.2-gnu/drivers/input/mouse/hgpk.c
--- linux-libre-3.1-gnu/drivers/input/mouse/hgpk.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/mouse/hgpk.c	2012-01-04 18:55:44.000000000 -0500
@@ -136,10 +136,10 @@
 	/* discard if too big, or half that but > 4 times the prev delta */
 	if (avx > recalib_delta ||
 		(avx > recalib_delta / 2 && ((avx / 4) > priv->xlast))) {
-		hgpk_err(psmouse, "detected %dpx jump in x\n", x);
+		psmouse_warn(psmouse, "detected %dpx jump in x\n", x);
 		priv->xbigj = avx;
 	} else if (approx_half(avx, priv->xbigj)) {
-		hgpk_err(psmouse, "detected secondary %dpx jump in x\n", x);
+		psmouse_warn(psmouse, "detected secondary %dpx jump in x\n", x);
 		priv->xbigj = avx;
 		priv->xsaw_secondary++;
 	} else {
@@ -151,10 +151,10 @@
 
 	if (avy > recalib_delta ||
 		(avy > recalib_delta / 2 && ((avy / 4) > priv->ylast))) {
-		hgpk_err(psmouse, "detected %dpx jump in y\n", y);
+		psmouse_warn(psmouse, "detected %dpx jump in y\n", y);
 		priv->ybigj = avy;
 	} else if (approx_half(avy, priv->ybigj)) {
-		hgpk_err(psmouse, "detected secondary %dpx jump in y\n", y);
+		psmouse_warn(psmouse, "detected secondary %dpx jump in y\n", y);
 		priv->ybigj = avy;
 		priv->ysaw_secondary++;
 	} else {
@@ -168,7 +168,7 @@
 	priv->ylast = avy;
 
 	if (do_recal && jumpy_delay) {
-		hgpk_err(psmouse, "scheduling recalibration\n");
+		psmouse_warn(psmouse, "scheduling recalibration\n");
 		psmouse_queue_work(psmouse, &priv->recalib_wq,
 				msecs_to_jiffies(jumpy_delay));
 	}
@@ -260,8 +260,8 @@
 		 * movement, it is probably a case of the user moving the
 		 * cursor very slowly across the screen. */
 		if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) {
-			hgpk_err(psmouse, "packet spew detected (%d,%d)\n",
-				 priv->x_tally, priv->y_tally);
+			psmouse_warn(psmouse, "packet spew detected (%d,%d)\n",
+				     priv->x_tally, priv->y_tally);
 			priv->spew_flag = RECALIBRATING;
 			psmouse_queue_work(psmouse, &priv->recalib_wq,
 					   msecs_to_jiffies(spew_delay));
@@ -333,12 +333,12 @@
 	}
 
 	if (!valid)
-		hgpk_dbg(psmouse,
-			 "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n",
-			 priv->mode, pktcnt,
-			 psmouse->packet[0], psmouse->packet[1],
-			 psmouse->packet[2], psmouse->packet[3],
-			 psmouse->packet[4], psmouse->packet[5]);
+		psmouse_dbg(psmouse,
+			    "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n",
+			    priv->mode, pktcnt,
+			    psmouse->packet[0], psmouse->packet[1],
+			    psmouse->packet[2], psmouse->packet[3],
+			    psmouse->packet[4], psmouse->packet[5]);
 
 	return valid;
 }
@@ -361,19 +361,20 @@
 
 		input_report_abs(idev, ABS_PRESSURE, z);
 		if (tpdebug)
-			hgpk_dbg(psmouse, "pd=%d fd=%d z=%d",
-				 pt_down, finger_down, z);
+			psmouse_dbg(psmouse, "pd=%d fd=%d z=%d",
+				    pt_down, finger_down, z);
 	} else {
 		/*
 		 * PenTablet mode does not report pressure, so we don't
 		 * report it here
 		 */
 		if (tpdebug)
-			hgpk_dbg(psmouse, "pd=%d ", down);
+			psmouse_dbg(psmouse, "pd=%d ", down);
 	}
 
 	if (tpdebug)
-		hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y);
+		psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n",
+			    left, right, x, y);
 
 	input_report_key(idev, BTN_TOUCH, down);
 	input_report_key(idev, BTN_LEFT, left);
@@ -395,7 +396,7 @@
 	if (x == priv->abs_x && y == priv->abs_y) {
 		if (++priv->dupe_count > SPEW_WATCH_COUNT) {
 			if (tpdebug)
-				hgpk_dbg(psmouse, "hard spew detected\n");
+				psmouse_dbg(psmouse, "hard spew detected\n");
 			priv->spew_flag = RECALIBRATING;
 			psmouse_queue_work(psmouse, &priv->recalib_wq,
 					   msecs_to_jiffies(spew_delay));
@@ -412,7 +413,7 @@
 		int y_diff = priv->abs_y - y;
 		if (hgpk_discard_decay_hack(psmouse, x_diff, y_diff)) {
 			if (tpdebug)
-				hgpk_dbg(psmouse, "discarding\n");
+				psmouse_dbg(psmouse, "discarding\n");
 			goto done;
 		}
 		hgpk_spewing_hack(psmouse, left, right, x_diff, y_diff);
@@ -437,20 +438,21 @@
 	int y = ((packet[0] << 3) & 0x100) - packet[2];
 
 	if (packet[0] & 0xc0)
-		hgpk_dbg(psmouse,
-			 "overflow -- 0x%02x 0x%02x 0x%02x\n",
-			 packet[0], packet[1], packet[2]);
+		psmouse_dbg(psmouse,
+			    "overflow -- 0x%02x 0x%02x 0x%02x\n",
+			    packet[0], packet[1], packet[2]);
 
 	if (hgpk_discard_decay_hack(psmouse, x, y)) {
 		if (tpdebug)
-			hgpk_dbg(psmouse, "discarding\n");
+			psmouse_dbg(psmouse, "discarding\n");
 		return;
 	}
 
 	hgpk_spewing_hack(psmouse, left, right, x, y);
 
 	if (tpdebug)
-		hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y);
+		psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n",
+			    left, right, x, y);
 
 	input_report_key(dev, BTN_LEFT, left);
 	input_report_key(dev, BTN_RIGHT, right);
@@ -482,9 +484,8 @@
 			 * ugh, got a packet inside our recalibration
 			 * window, schedule another recalibration.
 			 */
-			hgpk_dbg(psmouse,
-				 "packet inside calibration window, "
-				 "queueing another recalibration\n");
+			psmouse_dbg(psmouse,
+				    "packet inside calibration window, queueing another recalibration\n");
 			psmouse_queue_work(psmouse, &priv->recalib_wq,
 					msecs_to_jiffies(post_interrupt_delay));
 		}
@@ -628,7 +629,7 @@
 
 	err = hgpk_select_mode(psmouse);
 	if (err) {
-		hgpk_err(psmouse, "failed to select mode\n");
+		psmouse_err(psmouse, "failed to select mode\n");
 		return err;
 	}
 
@@ -648,11 +649,11 @@
 		return 0;
 
 	if (!autorecal) {
-		hgpk_dbg(psmouse, "recalibrations disabled, ignoring\n");
+		psmouse_dbg(psmouse, "recalibration disabled, ignoring\n");
 		return 0;
 	}
 
-	hgpk_dbg(psmouse, "recalibrating touchpad..\n");
+	psmouse_dbg(psmouse, "recalibrating touchpad..\n");
 
 	/* we don't want to race with the irq handler, nor with resyncs */
 	psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
@@ -675,7 +676,7 @@
 	psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
 
 	if (tpdebug)
-		hgpk_dbg(psmouse, "touchpad reactivated\n");
+		psmouse_dbg(psmouse, "touchpad reactivated\n");
 
 	/*
 	 * If we get packets right away after recalibrating, it's likely
@@ -727,16 +728,16 @@
 
 		err = hgpk_reset_device(psmouse, false);
 		if (err) {
-			hgpk_err(psmouse, "Failed to reset device!\n");
+			psmouse_err(psmouse, "Failed to reset device!\n");
 			return err;
 		}
 
 		/* should be all set, enable the touchpad */
 		ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE);
 		psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
-		hgpk_dbg(psmouse, "Touchpad powered up.\n");
+		psmouse_dbg(psmouse, "Touchpad powered up.\n");
 	} else {
-		hgpk_dbg(psmouse, "Powering off touchpad.\n");
+		psmouse_dbg(psmouse, "Powering off touchpad.\n");
 
 		if (ps2_command(ps2dev, NULL, 0xec) ||
 		    ps2_command(ps2dev, NULL, 0xec) ||
@@ -923,7 +924,7 @@
 	struct psmouse *psmouse = priv->psmouse;
 
 	if (hgpk_force_recalibrate(psmouse))
-		hgpk_err(psmouse, "recalibration failed!\n");
+		psmouse_err(psmouse, "recalibration failed!\n");
 }
 
 static int hgpk_register(struct psmouse *psmouse)
@@ -947,14 +948,15 @@
 	err = device_create_file(&psmouse->ps2dev.serio->dev,
 				 &psmouse_attr_powered.dattr);
 	if (err) {
-		hgpk_err(psmouse, "Failed creating 'powered' sysfs node\n");
+		psmouse_err(psmouse, "Failed creating 'powered' sysfs node\n");
 		return err;
 	}
 
 	err = device_create_file(&psmouse->ps2dev.serio->dev,
 				 &psmouse_attr_hgpk_mode.dattr);
 	if (err) {
-		hgpk_err(psmouse, "Failed creating 'hgpk_mode' sysfs node\n");
+		psmouse_err(psmouse,
+			    "Failed creating 'hgpk_mode' sysfs node\n");
 		goto err_remove_powered;
 	}
 
@@ -963,8 +965,8 @@
 		err = device_create_file(&psmouse->ps2dev.serio->dev,
 					 &psmouse_attr_recalibrate.dattr);
 		if (err) {
-			hgpk_err(psmouse,
-				"Failed creating 'recalibrate' sysfs node\n");
+			psmouse_err(psmouse,
+				    "Failed creating 'recalibrate' sysfs node\n");
 			goto err_remove_mode;
 		}
 	}
@@ -1027,13 +1029,13 @@
 		return -EIO;
 	}
 
-	hgpk_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]);
+	psmouse_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]);
 
 	/* HGPK signature: 0x67, 0x00, 0x<model> */
 	if (param[0] != 0x67 || param[1] != 0x00)
 		return -ENODEV;
 
-	hgpk_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]);
+	psmouse_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]);
 
 	return param[2];
 }
diff -druN linux-libre-3.1-gnu/drivers/input/mouse/hgpk.h linux-libre-3.2-gnu/drivers/input/mouse/hgpk.h
--- linux-libre-3.1-gnu/drivers/input/mouse/hgpk.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/mouse/hgpk.h	2012-01-04 18:55:44.000000000 -0500
@@ -46,17 +46,6 @@
 	int xsaw_secondary, ysaw_secondary; /* jumpiness detection */
 };
 
-#define hgpk_dbg(psmouse, format, arg...)		\
-	dev_dbg(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-#define hgpk_err(psmouse, format, arg...)		\
-	dev_err(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-#define hgpk_info(psmouse, format, arg...)		\
-	dev_info(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-#define hgpk_warn(psmouse, format, arg...)		\
-	dev_warn(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-#define hgpk_notice(psmouse, format, arg...)		\
-	dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg)
-
 #ifdef CONFIG_MOUSE_PS2_OLPC
 void hgpk_module_init(void);
 int hgpk_detect(struct psmouse *psmouse, bool set_properties);
diff -druN linux-libre-3.1-gnu/drivers/input/mouse/lifebook.c linux-libre-3.2-gnu/drivers/input/mouse/lifebook.c
--- linux-libre-3.1-gnu/drivers/input/mouse/lifebook.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/mouse/lifebook.c	2012-01-04 18:55:44.000000000 -0500
@@ -169,8 +169,8 @@
 
 	if (relative_packet) {
 		if (!dev2)
-			printk(KERN_WARNING "lifebook.c: got relative packet "
-				"but no relative device set up\n");
+			psmouse_warn(psmouse,
+				     "got relative packet but no relative device set up\n");
 	} else {
 		if (lifebook_use_6byte_proto) {
 			input_report_abs(dev1, ABS_X,
@@ -212,7 +212,7 @@
 
 	/*
 	 * Enable absolute output -- ps2_command fails always but if
-	 * you leave this call out the touchsreen will never send
+	 * you leave this call out the touchscreen will never send
 	 * absolute coordinates
 	 */
 	param = lifebook_use_6byte_proto ? 0x08 : 0x07;
diff -druN linux-libre-3.1-gnu/drivers/input/mouse/logips2pp.c linux-libre-3.2-gnu/drivers/input/mouse/logips2pp.c
--- linux-libre-3.1-gnu/drivers/input/mouse/logips2pp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/mouse/logips2pp.c	2012-01-04 18:55:44.000000000 -0500
@@ -82,11 +82,11 @@
 			packet[0] = packet[2] | 0x08;
 			break;
 
-#ifdef DEBUG
 		default:
-			printk(KERN_WARNING "psmouse.c: Received PS2++ packet #%x, but don't know how to handle.\n",
-				(packet[1] >> 4) | (packet[0] & 0x30));
-#endif
+			psmouse_dbg(psmouse,
+				    "Received PS2++ packet #%x, but don't know how to handle.\n",
+				    (packet[1] >> 4) | (packet[0] & 0x30));
+			break;
 		}
 	} else {
 		/* Standard PS/2 motion data */
@@ -382,7 +382,7 @@
 		}
 
 	} else {
-		printk(KERN_WARNING "logips2pp: Detected unknown logitech mouse model %d\n", model);
+		psmouse_warn(psmouse, "Detected unknown Logitech mouse model %d\n", model);
 	}
 
 	if (set_properties) {
@@ -400,9 +400,9 @@
 				error = device_create_file(&psmouse->ps2dev.serio->dev,
 							   &psmouse_attr_smartscroll.dattr);
 				if (error) {
-					printk(KERN_ERR
-						"logips2pp.c: failed to create smartscroll "
-						"sysfs attribute, error: %d\n", error);
+					psmouse_err(psmouse,
+						    "failed to create smartscroll sysfs attribute, error: %d\n",
+						    error);
 					return -1;
 				}
 			}
diff -druN linux-libre-3.1-gnu/drivers/input/mouse/psmouse-base.c linux-libre-3.2-gnu/drivers/input/mouse/psmouse-base.c
--- linux-libre-3.1-gnu/drivers/input/mouse/psmouse-base.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/mouse/psmouse-base.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,9 @@
  * the Free Software Foundation.
  */
 
+#define pr_fmt(fmt)		KBUILD_MODNAME ": " fmt
+#define psmouse_fmt(fmt)	fmt
+
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -251,11 +254,14 @@
 	switch (rc) {
 	case PSMOUSE_BAD_DATA:
 		if (psmouse->state == PSMOUSE_ACTIVATED) {
-			printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",
-				psmouse->name, psmouse->phys, psmouse->pktcnt);
+			psmouse_warn(psmouse,
+				     "%s at %s lost sync at byte %d\n",
+				     psmouse->name, psmouse->phys,
+				     psmouse->pktcnt);
 			if (++psmouse->out_of_sync_cnt == psmouse->resetafter) {
 				__psmouse_set_state(psmouse, PSMOUSE_IGNORE);
-				printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n");
+				psmouse_notice(psmouse,
+						"issuing reconnect request\n");
 				serio_reconnect(psmouse->ps2dev.serio);
 				return -1;
 			}
@@ -267,8 +273,9 @@
 		psmouse->pktcnt = 0;
 		if (psmouse->out_of_sync_cnt) {
 			psmouse->out_of_sync_cnt = 0;
-			printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n",
-				psmouse->name, psmouse->phys);
+			psmouse_notice(psmouse,
+					"%s at %s - driver resynced.\n",
+					psmouse->name, psmouse->phys);
 		}
 		break;
 
@@ -295,9 +302,10 @@
 		     ((flags & SERIO_PARITY) && !psmouse->ignore_parity))) {
 
 		if (psmouse->state == PSMOUSE_ACTIVATED)
-			printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n",
-				flags & SERIO_TIMEOUT ? " timeout" : "",
-				flags & SERIO_PARITY ? " bad parity" : "");
+			psmouse_warn(psmouse,
+				     "bad data from KBC -%s%s\n",
+				     flags & SERIO_TIMEOUT ? " timeout" : "",
+				     flags & SERIO_PARITY ? " bad parity" : "");
 		ps2_cmd_aborted(&psmouse->ps2dev);
 		goto out;
 	}
@@ -315,8 +323,8 @@
 
 	if (psmouse->state == PSMOUSE_ACTIVATED &&
 	    psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
-		printk(KERN_INFO "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
-		       psmouse->name, psmouse->phys, psmouse->pktcnt);
+		psmouse_info(psmouse, "%s at %s lost synchronization, throwing %d bytes away.\n",
+			     psmouse->name, psmouse->phys, psmouse->pktcnt);
 		psmouse->badbyte = psmouse->packet[0];
 		__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
 		psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
@@ -943,7 +951,8 @@
  */
 
 	if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_DIS))
-		printk(KERN_WARNING "psmouse.c: Failed to reset mouse on %s\n", ps2dev->serio->phys);
+		psmouse_warn(psmouse, "Failed to reset mouse on %s\n",
+			     ps2dev->serio->phys);
 
 	return 0;
 }
@@ -1005,8 +1014,8 @@
 static void psmouse_activate(struct psmouse *psmouse)
 {
 	if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE))
-		printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n",
-			psmouse->ps2dev.serio->phys);
+		psmouse_warn(psmouse, "Failed to enable mouse on %s\n",
+			     psmouse->ps2dev.serio->phys);
 
 	psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
 }
@@ -1020,14 +1029,14 @@
 static void psmouse_deactivate(struct psmouse *psmouse)
 {
 	if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE))
-		printk(KERN_WARNING "psmouse.c: Failed to deactivate mouse on %s\n",
-			psmouse->ps2dev.serio->phys);
+		psmouse_warn(psmouse, "Failed to deactivate mouse on %s\n",
+			     psmouse->ps2dev.serio->phys);
 
 	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 }
 
 /*
- * psmouse_poll() - default poll hanlder. Everyone except for ALPS uses it.
+ * psmouse_poll() - default poll handler. Everyone except for ALPS uses it.
  */
 
 static int psmouse_poll(struct psmouse *psmouse)
@@ -1115,14 +1124,15 @@
 	}
 
 	if (!enabled) {
-		printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n",
-			psmouse->ps2dev.serio->phys);
+		psmouse_warn(psmouse, "failed to re-enable mouse on %s\n",
+			     psmouse->ps2dev.serio->phys);
 		failed = true;
 	}
 
 	if (failed) {
 		psmouse_set_state(psmouse, PSMOUSE_IGNORE);
-		printk(KERN_INFO "psmouse.c: resync failed, issuing reconnect request\n");
+		psmouse_info(psmouse,
+			     "resync failed, issuing reconnect request\n");
 		serio_reconnect(serio);
 	} else
 		psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
@@ -1155,8 +1165,8 @@
 	 * Disable stream mode so cleanup routine can proceed undisturbed.
 	 */
 	if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE))
-		printk(KERN_WARNING "psmouse.c: Failed to disable mouse on %s\n",
-			psmouse->ps2dev.serio->phys);
+		psmouse_warn(psmouse, "Failed to disable mouse on %s\n",
+			     psmouse->ps2dev.serio->phys);
 
 	if (psmouse->cleanup)
 		psmouse->cleanup(psmouse);
@@ -1400,7 +1410,8 @@
 	int rc = -1;
 
 	if (!drv || !psmouse) {
-		printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n");
+		psmouse_dbg(psmouse,
+			    "reconnect request, but serio is disconnected, ignoring...\n");
 		return -1;
 	}
 
@@ -1427,8 +1438,9 @@
 			goto out;
 	}
 
-	/* ok, the device type (and capabilities) match the old one,
-	 * we can continue using it, complete intialization
+	/*
+	 * OK, the device type (and capabilities) match the old one,
+	 * we can continue using it, complete initialization
 	 */
 	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 
@@ -1586,9 +1598,8 @@
 
 	while (!list_empty(&serio->children)) {
 		if (++retry > 3) {
-			printk(KERN_WARNING
-				"psmouse: failed to destroy children ports, "
-				"protocol change aborted.\n");
+			psmouse_warn(psmouse,
+				     "failed to destroy children ports, protocol change aborted.\n");
 			input_free_device(new_dev);
 			return -EIO;
 		}
@@ -1715,7 +1726,7 @@
 
 	kpsmoused_wq = create_singlethread_workqueue("kpsmoused");
 	if (!kpsmoused_wq) {
-		printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n");
+		pr_err("failed to create kpsmoused workqueue\n");
 		return -ENOMEM;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/input/mouse/psmouse.h linux-libre-3.2-gnu/drivers/input/mouse/psmouse.h
--- linux-libre-3.1-gnu/drivers/input/mouse/psmouse.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/mouse/psmouse.h	2012-01-04 18:55:44.000000000 -0500
@@ -150,4 +150,29 @@
 	static ssize_t _set(struct psmouse *, void *, const char *, size_t);	\
 	__PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, NULL, _set, true)
 
+#ifndef psmouse_fmt
+#define psmouse_fmt(fmt)	KBUILD_BASENAME ": " fmt
+#endif
+
+#define psmouse_dbg(psmouse, format, ...)		\
+	dev_dbg(&(psmouse)->ps2dev.serio->dev,		\
+		psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_info(psmouse, format, ...)		\
+	dev_info(&(psmouse)->ps2dev.serio->dev,		\
+		 psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_warn(psmouse, format, ...)		\
+	dev_warn(&(psmouse)->ps2dev.serio->dev,		\
+		 psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_err(psmouse, format, ...)		\
+	dev_err(&(psmouse)->ps2dev.serio->dev,		\
+		psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_notice(psmouse, format, ...)		\
+	dev_notice(&(psmouse)->ps2dev.serio->dev,	\
+		   psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_printk(level, psmouse, format, ...)	\
+	dev_printk(level,				\
+		   &(psmouse)->ps2dev.serio->dev,	\
+		   psmouse_fmt(format), ##__VA_ARGS__)
+
+
 #endif /* _PSMOUSE_H */
diff -druN linux-libre-3.1-gnu/drivers/input/mouse/pxa930_trkball.c linux-libre-3.2-gnu/drivers/input/mouse/pxa930_trkball.c
--- linux-libre-3.1-gnu/drivers/input/mouse/pxa930_trkball.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/mouse/pxa930_trkball.c	2012-01-04 18:55:44.000000000 -0500
@@ -183,7 +183,7 @@
 	/* held the module in reset, will be enabled in open() */
 	pxa930_trkball_disable(trkball);
 
-	error = request_irq(irq, pxa930_trkball_interrupt, IRQF_DISABLED,
+	error = request_irq(irq, pxa930_trkball_interrupt, 0,
 			    pdev->name, trkball);
 	if (error) {
 		dev_err(&pdev->dev, "failed to request irq: %d\n", error);
diff -druN linux-libre-3.1-gnu/drivers/input/mouse/sentelic.c linux-libre-3.2-gnu/drivers/input/mouse/sentelic.c
--- linux-libre-3.1-gnu/drivers/input/mouse/sentelic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/mouse/sentelic.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
  * Finger Sensing Pad PS/2 mouse driver.
  *
  * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd.
- * Copyright (C) 2005-2010 Tai-hwa Liang, Sentelic Corporation.
+ * Copyright (C) 2005-2011 Tai-hwa Liang, Sentelic Corporation.
  *
  *   This program is free software; you can redistribute it and/or
  *   modify it under the terms of the GNU General Public License
@@ -162,7 +162,7 @@
 	ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2);
 
 	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
-		return -1;
+		goto out;
 
 	if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) {
 		/* inversion is required */
@@ -261,7 +261,7 @@
 	ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
 
 	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
-		return -1;
+		goto out;
 
 	if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) {
 		ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2);
@@ -309,7 +309,7 @@
 	};
 	int val;
 
-	if (fsp_reg_read(psmouse, FSP_REG_TMOD_STATUS1, &val) == -1)
+	if (fsp_reg_read(psmouse, FSP_REG_TMOD_STATUS, &val) == -1)
 		return -EIO;
 
 	*btn = buttons[(val & 0x30) >> 4];
@@ -607,11 +607,12 @@
 
 	ps2_packet_cnt++;
 	jiffies_msec = jiffies_to_msecs(jiffies);
-	printk(KERN_DEBUG "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n",
-		jiffies_msec, packet[0], packet[1], packet[2], packet[3]);
+	psmouse_dbg(psmouse,
+		    "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n",
+		    jiffies_msec, packet[0], packet[1], packet[2], packet[3]);
 
 	if (jiffies_msec - ps2_last_second > 1000) {
-		printk(KERN_DEBUG "PS/2 packets/sec = %d\n", ps2_packet_cnt);
+		psmouse_dbg(psmouse, "PS/2 packets/sec = %d\n", ps2_packet_cnt);
 		ps2_packet_cnt = 0;
 		ps2_last_second = jiffies_msec;
 	}
@@ -820,9 +821,9 @@
 		return -ENODEV;
 	}
 
-	printk(KERN_INFO
-		"Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n",
-		ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7);
+	psmouse_info(psmouse,
+		     "Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n",
+		     ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7);
 
 	psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL);
 	if (!priv)
diff -druN linux-libre-3.1-gnu/drivers/input/mouse/sentelic.h linux-libre-3.2-gnu/drivers/input/mouse/sentelic.h
--- linux-libre-3.1-gnu/drivers/input/mouse/sentelic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/mouse/sentelic.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
  * Finger Sensing Pad PS/2 mouse driver.
  *
  * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd.
- * Copyright (C) 2005-2009 Tai-hwa Liang, Sentelic Corporation.
+ * Copyright (C) 2005-2011 Tai-hwa Liang, Sentelic Corporation.
  *
  *   This program is free software; you can redistribute it and/or
  *   modify it under the terms of the GNU General Public License
@@ -33,6 +33,7 @@
 /* Finger-sensing Pad control registers */
 #define	FSP_REG_SYSCTL1		0x10
 #define	FSP_BIT_EN_REG_CLK	BIT(5)
+#define	FSP_REG_TMOD_STATUS	0x20
 #define	FSP_REG_OPC_QDOWN	0x31
 #define	FSP_BIT_EN_OPC_TAG	BIT(7)
 #define	FSP_REG_OPTZ_XLO	0x34
diff -druN linux-libre-3.1-gnu/drivers/input/mouse/synaptics.c linux-libre-3.2-gnu/drivers/input/mouse/synaptics.c
--- linux-libre-3.1-gnu/drivers/input/mouse/synaptics.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/mouse/synaptics.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/dmi.h>
 #include <linux/input/mt.h>
 #include <linux/serio.h>
@@ -44,6 +45,16 @@
 #define YMIN_NOMINAL 1408
 #define YMAX_NOMINAL 4448
 
+/*
+ * Synaptics touchpads report the y coordinate from bottom to top, which is
+ * opposite from what userspace expects.
+ * This function is used to invert y before reporting.
+ */
+static int synaptics_invert_y(int y)
+{
+	return YMAX_NOMINAL + YMIN_NOMINAL - y;
+}
+
 
 /*****************************************************************************
  *	Stuff we need even when we do not want native Synaptics support
@@ -157,8 +168,8 @@
 
 	if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) {
 		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) {
-			printk(KERN_ERR "Synaptics claims to have extended capabilities,"
-			       " but I'm not able to read them.\n");
+			psmouse_warn(psmouse,
+				     "device claims to have extended capabilities, but I'm not able to read them.\n");
 		} else {
 			priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2];
 
@@ -173,8 +184,8 @@
 
 	if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) {
 		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) {
-			printk(KERN_ERR "Synaptics claims to have extended capability 0x0c,"
-			       " but I'm not able to read it.\n");
+			psmouse_warn(psmouse,
+				     "device claims to have extended capability 0x0c, but I'm not able to read it.\n");
 		} else {
 			priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2];
 		}
@@ -222,8 +233,8 @@
 	if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 &&
 	    SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) {
 		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) {
-			printk(KERN_ERR "Synaptics claims to have max coordinates"
-			       " query, but I'm not able to read it.\n");
+			psmouse_warn(psmouse,
+				     "device claims to have max coordinates query, but I'm not able to read it.\n");
 		} else {
 			priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
 			priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
@@ -233,8 +244,8 @@
 	if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 &&
 	    SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) {
 		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) {
-			printk(KERN_ERR "Synaptics claims to have min coordinates"
-			       " query, but I'm not able to read it.\n");
+			psmouse_warn(psmouse,
+				     "device claims to have min coordinates query, but I'm not able to read it.\n");
 		} else {
 			priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
 			priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
@@ -294,7 +305,8 @@
 	static unsigned char param = 0xc8;
 	struct synaptics_data *priv = psmouse->private;
 
-	if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
+	if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
+			SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)))
 		return 0;
 
 	if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL))
@@ -377,7 +389,8 @@
 			priv->mode &= ~SYN_BIT_FOUR_BYTE_CLIENT;
 
 		if (synaptics_mode_cmd(psmouse, priv->mode))
-			printk(KERN_INFO "synaptics: failed to switch guest protocol\n");
+			psmouse_warn(psmouse,
+				     "failed to switch guest protocol\n");
 	}
 }
 
@@ -387,7 +400,8 @@
 
 	serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
 	if (!serio) {
-		printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
+		psmouse_err(psmouse,
+			    "not enough memory for pass-through port\n");
 		return;
 	}
 
@@ -401,7 +415,8 @@
 
 	psmouse->pt_activate = synaptics_pt_activate;
 
-	printk(KERN_INFO "serio: %s port at %s\n", serio->name, psmouse->phys);
+	psmouse_info(psmouse, "serio: %s port at %s\n",
+		     serio->name, psmouse->phys);
 	serio_register_port(serio);
 }
 
@@ -409,6 +424,44 @@
  *	Functions to interpret the absolute mode packets
  ****************************************************************************/
 
+static void synaptics_mt_state_set(struct synaptics_mt_state *state, int count,
+				   int sgm, int agm)
+{
+	state->count = count;
+	state->sgm = sgm;
+	state->agm = agm;
+}
+
+static void synaptics_parse_agm(const unsigned char buf[],
+				struct synaptics_data *priv,
+				struct synaptics_hw_state *hw)
+{
+	struct synaptics_hw_state *agm = &priv->agm;
+	int agm_packet_type;
+
+	agm_packet_type = (buf[5] & 0x30) >> 4;
+	switch (agm_packet_type) {
+	case 1:
+		/* Gesture packet: (x, y, z) half resolution */
+		agm->w = hw->w;
+		agm->x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
+		agm->y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
+		agm->z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
+		break;
+
+	case 2:
+		/* AGM-CONTACT packet: (count, sgm, agm) */
+		synaptics_mt_state_set(&agm->mt_state, buf[1], buf[2], buf[4]);
+		break;
+
+	default:
+		break;
+	}
+
+	/* Record that at least one AGM has been received since last SGM */
+	priv->agm_pending = true;
+}
+
 static int synaptics_parse_hw_state(const unsigned char buf[],
 				    struct synaptics_data *priv,
 				    struct synaptics_hw_state *hw)
@@ -442,11 +495,10 @@
 			hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
 		}
 
-		if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) {
-			/* Gesture packet: (x, y, z) at half resolution */
-			priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
-			priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
-			priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
+		if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
+			SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
+		    hw->w == 2) {
+			synaptics_parse_agm(buf, priv, hw);
 			return 1;
 		}
 
@@ -502,8 +554,7 @@
 	input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
 	if (active) {
 		input_report_abs(dev, ABS_MT_POSITION_X, x);
-		input_report_abs(dev, ABS_MT_POSITION_Y,
-				 YMAX_NOMINAL + YMIN_NOMINAL - y);
+		input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(y));
 	}
 }
 
@@ -526,6 +577,388 @@
 	}
 }
 
+static void synaptics_report_buttons(struct psmouse *psmouse,
+				     const struct synaptics_hw_state *hw)
+{
+	struct input_dev *dev = psmouse->dev;
+	struct synaptics_data *priv = psmouse->private;
+	int i;
+
+	input_report_key(dev, BTN_LEFT, hw->left);
+	input_report_key(dev, BTN_RIGHT, hw->right);
+
+	if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
+		input_report_key(dev, BTN_MIDDLE, hw->middle);
+
+	if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
+		input_report_key(dev, BTN_FORWARD, hw->up);
+		input_report_key(dev, BTN_BACK, hw->down);
+	}
+
+	for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
+		input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i));
+}
+
+static void synaptics_report_slot(struct input_dev *dev, int slot,
+				  const struct synaptics_hw_state *hw)
+{
+	input_mt_slot(dev, slot);
+	input_mt_report_slot_state(dev, MT_TOOL_FINGER, (hw != NULL));
+	if (!hw)
+		return;
+
+	input_report_abs(dev, ABS_MT_POSITION_X, hw->x);
+	input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(hw->y));
+	input_report_abs(dev, ABS_MT_PRESSURE, hw->z);
+}
+
+static void synaptics_report_mt_data(struct psmouse *psmouse,
+				     struct synaptics_mt_state *mt_state,
+				     const struct synaptics_hw_state *sgm)
+{
+	struct input_dev *dev = psmouse->dev;
+	struct synaptics_data *priv = psmouse->private;
+	struct synaptics_hw_state *agm = &priv->agm;
+	struct synaptics_mt_state *old = &priv->mt_state;
+
+	switch (mt_state->count) {
+	case 0:
+		synaptics_report_slot(dev, 0, NULL);
+		synaptics_report_slot(dev, 1, NULL);
+		break;
+	case 1:
+		if (mt_state->sgm == -1) {
+			synaptics_report_slot(dev, 0, NULL);
+			synaptics_report_slot(dev, 1, NULL);
+		} else if (mt_state->sgm == 0) {
+			synaptics_report_slot(dev, 0, sgm);
+			synaptics_report_slot(dev, 1, NULL);
+		} else {
+			synaptics_report_slot(dev, 0, NULL);
+			synaptics_report_slot(dev, 1, sgm);
+		}
+		break;
+	default:
+		/*
+		 * If the finger slot contained in SGM is valid, and either
+		 * hasn't changed, or is new, then report SGM in MTB slot 0.
+		 * Otherwise, empty MTB slot 0.
+		 */
+		if (mt_state->sgm != -1 &&
+		    (mt_state->sgm == old->sgm || old->sgm == -1))
+			synaptics_report_slot(dev, 0, sgm);
+		else
+			synaptics_report_slot(dev, 0, NULL);
+
+		/*
+		 * If the finger slot contained in AGM is valid, and either
+		 * hasn't changed, or is new, then report AGM in MTB slot 1.
+		 * Otherwise, empty MTB slot 1.
+		 */
+		if (mt_state->agm != -1 &&
+		    (mt_state->agm == old->agm || old->agm == -1))
+			synaptics_report_slot(dev, 1, agm);
+		else
+			synaptics_report_slot(dev, 1, NULL);
+		break;
+	}
+
+	/* Don't use active slot count to generate BTN_TOOL events. */
+	input_mt_report_pointer_emulation(dev, false);
+
+	/* Send the number of fingers reported by touchpad itself. */
+	input_mt_report_finger_count(dev, mt_state->count);
+
+	synaptics_report_buttons(psmouse, sgm);
+
+	input_sync(dev);
+}
+
+/* Handle case where mt_state->count = 0 */
+static void synaptics_image_sensor_0f(struct synaptics_data *priv,
+				      struct synaptics_mt_state *mt_state)
+{
+	synaptics_mt_state_set(mt_state, 0, -1, -1);
+	priv->mt_state_lost = false;
+}
+
+/* Handle case where mt_state->count = 1 */
+static void synaptics_image_sensor_1f(struct synaptics_data *priv,
+				      struct synaptics_mt_state *mt_state)
+{
+	struct synaptics_hw_state *agm = &priv->agm;
+	struct synaptics_mt_state *old = &priv->mt_state;
+
+	/*
+	 * If the last AGM was (0,0,0), and there is only one finger left,
+	 * then we absolutely know that SGM contains slot 0, and all other
+	 * fingers have been removed.
+	 */
+	if (priv->agm_pending && agm->z == 0) {
+		synaptics_mt_state_set(mt_state, 1, 0, -1);
+		priv->mt_state_lost = false;
+		return;
+	}
+
+	switch (old->count) {
+	case 0:
+		synaptics_mt_state_set(mt_state, 1, 0, -1);
+		break;
+	case 1:
+		/*
+		 * If mt_state_lost, then the previous transition was 3->1,
+		 * and SGM now contains either slot 0 or 1, but we don't know
+		 * which.  So, we just assume that the SGM now contains slot 1.
+		 *
+		 * If pending AGM and either:
+		 *   (a) the previous SGM slot contains slot 0, or
+		 *   (b) there was no SGM slot
+		 * then, the SGM now contains slot 1
+		 *
+		 * Case (a) happens with very rapid "drum roll" gestures, where
+		 * slot 0 finger is lifted and a new slot 1 finger touches
+		 * within one reporting interval.
+		 *
+		 * Case (b) happens if initially two or more fingers tap
+		 * briefly, and all but one lift before the end of the first
+		 * reporting interval.
+		 *
+		 * (In both these cases, slot 0 will becomes empty, so SGM
+		 * contains slot 1 with the new finger)
+		 *
+		 * Else, if there was no previous SGM, it now contains slot 0.
+		 *
+		 * Otherwise, SGM still contains the same slot.
+		 */
+		if (priv->mt_state_lost ||
+		    (priv->agm_pending && old->sgm <= 0))
+			synaptics_mt_state_set(mt_state, 1, 1, -1);
+		else if (old->sgm == -1)
+			synaptics_mt_state_set(mt_state, 1, 0, -1);
+		break;
+	case 2:
+		/*
+		 * If mt_state_lost, we don't know which finger SGM contains.
+		 *
+		 * So, report 1 finger, but with both slots empty.
+		 * We will use slot 1 on subsequent 1->1
+		 */
+		if (priv->mt_state_lost) {
+			synaptics_mt_state_set(mt_state, 1, -1, -1);
+			break;
+		}
+		/*
+		 * Since the last AGM was NOT (0,0,0), it was the finger in
+		 * slot 0 that has been removed.
+		 * So, SGM now contains previous AGM's slot, and AGM is now
+		 * empty.
+		 */
+		synaptics_mt_state_set(mt_state, 1, old->agm, -1);
+		break;
+	case 3:
+		/*
+		 * Since last AGM was not (0,0,0), we don't know which finger
+		 * is left.
+		 *
+		 * So, report 1 finger, but with both slots empty.
+		 * We will use slot 1 on subsequent 1->1
+		 */
+		synaptics_mt_state_set(mt_state, 1, -1, -1);
+		priv->mt_state_lost = true;
+		break;
+	case 4:
+	case 5:
+		/* mt_state was updated by AGM-CONTACT packet */
+		break;
+	}
+}
+
+/* Handle case where mt_state->count = 2 */
+static void synaptics_image_sensor_2f(struct synaptics_data *priv,
+				      struct synaptics_mt_state *mt_state)
+{
+	struct synaptics_mt_state *old = &priv->mt_state;
+
+	switch (old->count) {
+	case 0:
+		synaptics_mt_state_set(mt_state, 2, 0, 1);
+		break;
+	case 1:
+		/*
+		 * If previous SGM contained slot 1 or higher, SGM now contains
+		 * slot 0 (the newly touching finger) and AGM contains SGM's
+		 * previous slot.
+		 *
+		 * Otherwise, SGM still contains slot 0 and AGM now contains
+		 * slot 1.
+		 */
+		if (old->sgm >= 1)
+			synaptics_mt_state_set(mt_state, 2, 0, old->sgm);
+		else
+			synaptics_mt_state_set(mt_state, 2, 0, 1);
+		break;
+	case 2:
+		/*
+		 * If mt_state_lost, SGM now contains either finger 1 or 2, but
+		 * we don't know which.
+		 * So, we just assume that the SGM contains slot 0 and AGM 1.
+		 */
+		if (priv->mt_state_lost)
+			synaptics_mt_state_set(mt_state, 2, 0, 1);
+		/*
+		 * Otherwise, use the same mt_state, since it either hasn't
+		 * changed, or was updated by a recently received AGM-CONTACT
+		 * packet.
+		 */
+		break;
+	case 3:
+		/*
+		 * 3->2 transitions have two unsolvable problems:
+		 *  1) no indication is given which finger was removed
+		 *  2) no way to tell if agm packet was for finger 3
+		 *     before 3->2, or finger 2 after 3->2.
+		 *
+		 * So, report 2 fingers, but empty all slots.
+		 * We will guess slots [0,1] on subsequent 2->2.
+		 */
+		synaptics_mt_state_set(mt_state, 2, -1, -1);
+		priv->mt_state_lost = true;
+		break;
+	case 4:
+	case 5:
+		/* mt_state was updated by AGM-CONTACT packet */
+		break;
+	}
+}
+
+/* Handle case where mt_state->count = 3 */
+static void synaptics_image_sensor_3f(struct synaptics_data *priv,
+				      struct synaptics_mt_state *mt_state)
+{
+	struct synaptics_mt_state *old = &priv->mt_state;
+
+	switch (old->count) {
+	case 0:
+		synaptics_mt_state_set(mt_state, 3, 0, 2);
+		break;
+	case 1:
+		/*
+		 * If previous SGM contained slot 2 or higher, SGM now contains
+		 * slot 0 (one of the newly touching fingers) and AGM contains
+		 * SGM's previous slot.
+		 *
+		 * Otherwise, SGM now contains slot 0 and AGM contains slot 2.
+		 */
+		if (old->sgm >= 2)
+			synaptics_mt_state_set(mt_state, 3, 0, old->sgm);
+		else
+			synaptics_mt_state_set(mt_state, 3, 0, 2);
+		break;
+	case 2:
+		/*
+		 * If the AGM previously contained slot 3 or higher, then the
+		 * newly touching finger is in the lowest available slot.
+		 *
+		 * If SGM was previously 1 or higher, then the new SGM is
+		 * now slot 0 (with a new finger), otherwise, the new finger
+		 * is now in a hidden slot between 0 and AGM's slot.
+		 *
+		 * In all such cases, the SGM now contains slot 0, and the AGM
+		 * continues to contain the same slot as before.
+		 */
+		if (old->agm >= 3) {
+			synaptics_mt_state_set(mt_state, 3, 0, old->agm);
+			break;
+		}
+
+		/*
+		 * After some 3->1 and all 3->2 transitions, we lose track
+		 * of which slot is reported by SGM and AGM.
+		 *
+		 * For 2->3 in this state, report 3 fingers, but empty all
+		 * slots, and we will guess (0,2) on a subsequent 0->3.
+		 *
+		 * To userspace, the resulting transition will look like:
+		 *    2:[0,1] -> 3:[-1,-1] -> 3:[0,2]
+		 */
+		if (priv->mt_state_lost) {
+			synaptics_mt_state_set(mt_state, 3, -1, -1);
+			break;
+		}
+
+		/*
+		 * If the (SGM,AGM) really previously contained slots (0, 1),
+		 * then we cannot know what slot was just reported by the AGM,
+		 * because the 2->3 transition can occur either before or after
+		 * the AGM packet. Thus, this most recent AGM could contain
+		 * either the same old slot 1 or the new slot 2.
+		 * Subsequent AGMs will be reporting slot 2.
+		 *
+		 * To userspace, the resulting transition will look like:
+		 *    2:[0,1] -> 3:[0,-1] -> 3:[0,2]
+		 */
+		synaptics_mt_state_set(mt_state, 3, 0, -1);
+		break;
+	case 3:
+		/*
+		 * If, for whatever reason, the previous agm was invalid,
+		 * Assume SGM now contains slot 0, AGM now contains slot 2.
+		 */
+		if (old->agm <= 2)
+			synaptics_mt_state_set(mt_state, 3, 0, 2);
+		/*
+		 * mt_state either hasn't changed, or was updated by a recently
+		 * received AGM-CONTACT packet.
+		 */
+		break;
+
+	case 4:
+	case 5:
+		/* mt_state was updated by AGM-CONTACT packet */
+		break;
+	}
+}
+
+/* Handle case where mt_state->count = 4, or = 5 */
+static void synaptics_image_sensor_45f(struct synaptics_data *priv,
+				       struct synaptics_mt_state *mt_state)
+{
+	/* mt_state was updated correctly by AGM-CONTACT packet */
+	priv->mt_state_lost = false;
+}
+
+static void synaptics_image_sensor_process(struct psmouse *psmouse,
+					   struct synaptics_hw_state *sgm)
+{
+	struct synaptics_data *priv = psmouse->private;
+	struct synaptics_hw_state *agm = &priv->agm;
+	struct synaptics_mt_state mt_state;
+
+	/* Initialize using current mt_state (as updated by last agm) */
+	mt_state = agm->mt_state;
+
+	/*
+	 * Update mt_state using the new finger count and current mt_state.
+	 */
+	if (sgm->z == 0)
+		synaptics_image_sensor_0f(priv, &mt_state);
+	else if (sgm->w >= 4)
+		synaptics_image_sensor_1f(priv, &mt_state);
+	else if (sgm->w == 0)
+		synaptics_image_sensor_2f(priv, &mt_state);
+	else if (sgm->w == 1 && mt_state.count <= 3)
+		synaptics_image_sensor_3f(priv, &mt_state);
+	else
+		synaptics_image_sensor_45f(priv, &mt_state);
+
+	/* Send resulting input events to user space */
+	synaptics_report_mt_data(psmouse, &mt_state, sgm);
+
+	/* Store updated mt_state */
+	priv->mt_state = agm->mt_state = mt_state;
+	priv->agm_pending = false;
+}
+
 /*
  *  called for each full received packet from the touchpad
  */
@@ -536,11 +969,15 @@
 	struct synaptics_hw_state hw;
 	int num_fingers;
 	int finger_width;
-	int i;
 
 	if (synaptics_parse_hw_state(psmouse->packet, priv, &hw))
 		return;
 
+	if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
+		synaptics_image_sensor_process(psmouse, &hw);
+		return;
+	}
+
 	if (hw.scroll) {
 		priv->scroll += hw.scroll;
 
@@ -586,7 +1023,8 @@
 	}
 
 	if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
-		synaptics_report_semi_mt_data(dev, &hw, &priv->mt, num_fingers);
+		synaptics_report_semi_mt_data(dev, &hw, &priv->agm,
+					      num_fingers);
 
 	/* Post events
 	 * BTN_TOUCH has to be first as mousedev relies on it when doing
@@ -597,7 +1035,7 @@
 
 	if (num_fingers > 0) {
 		input_report_abs(dev, ABS_X, hw.x);
-		input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y);
+		input_report_abs(dev, ABS_Y, synaptics_invert_y(hw.y));
 	}
 	input_report_abs(dev, ABS_PRESSURE, hw.z);
 
@@ -605,35 +1043,25 @@
 		input_report_abs(dev, ABS_TOOL_WIDTH, finger_width);
 
 	input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1);
-	input_report_key(dev, BTN_LEFT, hw.left);
-	input_report_key(dev, BTN_RIGHT, hw.right);
-
 	if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
 		input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
 		input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
 	}
 
-	if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
-		input_report_key(dev, BTN_MIDDLE, hw.middle);
-
-	if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
-		input_report_key(dev, BTN_FORWARD, hw.up);
-		input_report_key(dev, BTN_BACK, hw.down);
-	}
-
-	for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
-		input_report_key(dev, BTN_0 + i, hw.ext_buttons & (1 << i));
+	synaptics_report_buttons(psmouse, &hw);
 
 	input_sync(dev);
 }
 
-static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned char pkt_type)
+static int synaptics_validate_byte(struct psmouse *psmouse,
+				   int idx, unsigned char pkt_type)
 {
 	static const unsigned char newabs_mask[]	= { 0xC8, 0x00, 0x00, 0xC8, 0x00 };
 	static const unsigned char newabs_rel_mask[]	= { 0xC0, 0x00, 0x00, 0xC0, 0x00 };
 	static const unsigned char newabs_rslt[]	= { 0x80, 0x00, 0x00, 0xC0, 0x00 };
 	static const unsigned char oldabs_mask[]	= { 0xC0, 0x60, 0x00, 0xC0, 0x60 };
 	static const unsigned char oldabs_rslt[]	= { 0xC0, 0x00, 0x00, 0x80, 0x00 };
+	const char *packet = psmouse->packet;
 
 	if (idx < 0 || idx > 4)
 		return 0;
@@ -651,7 +1079,7 @@
 		return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx];
 
 	default:
-		printk(KERN_ERR "synaptics: unknown packet type %d\n", pkt_type);
+		psmouse_err(psmouse, "unknown packet type %d\n", pkt_type);
 		return 0;
 	}
 }
@@ -661,8 +1089,8 @@
 	int i;
 
 	for (i = 0; i < 5; i++)
-		if (!synaptics_validate_byte(psmouse->packet, i, SYN_NEWABS_STRICT)) {
-			printk(KERN_INFO "synaptics: using relaxed packet validation\n");
+		if (!synaptics_validate_byte(psmouse, i, SYN_NEWABS_STRICT)) {
+			psmouse_info(psmouse, "using relaxed packet validation\n");
 			return SYN_NEWABS_RELAXED;
 		}
 
@@ -687,46 +1115,56 @@
 		return PSMOUSE_FULL_PACKET;
 	}
 
-	return synaptics_validate_byte(psmouse->packet, psmouse->pktcnt - 1, priv->pkt_type) ?
+	return synaptics_validate_byte(psmouse, psmouse->pktcnt - 1, priv->pkt_type) ?
 		PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
 }
 
 /*****************************************************************************
  *	Driver initialization/cleanup functions
  ****************************************************************************/
-static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
+static void set_abs_position_params(struct input_dev *dev,
+				    struct synaptics_data *priv, int x_code,
+				    int y_code)
 {
-	int i;
+	int x_min = priv->x_min ?: XMIN_NOMINAL;
+	int x_max = priv->x_max ?: XMAX_NOMINAL;
+	int y_min = priv->y_min ?: YMIN_NOMINAL;
+	int y_max = priv->y_max ?: YMAX_NOMINAL;
 	int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ?
 			SYN_REDUCED_FILTER_FUZZ : 0;
 
+	input_set_abs_params(dev, x_code, x_min, x_max, fuzz, 0);
+	input_set_abs_params(dev, y_code, y_min, y_max, fuzz, 0);
+	input_abs_set_res(dev, x_code, priv->x_res);
+	input_abs_set_res(dev, y_code, priv->y_res);
+}
+
+static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
+{
+	int i;
+
 	__set_bit(INPUT_PROP_POINTER, dev->propbit);
 
 	__set_bit(EV_ABS, dev->evbit);
-	input_set_abs_params(dev, ABS_X,
-			     priv->x_min ?: XMIN_NOMINAL,
-			     priv->x_max ?: XMAX_NOMINAL,
-			     fuzz, 0);
-	input_set_abs_params(dev, ABS_Y,
-			     priv->y_min ?: YMIN_NOMINAL,
-			     priv->y_max ?: YMAX_NOMINAL,
-			     fuzz, 0);
+	set_abs_position_params(dev, priv, ABS_X, ABS_Y);
 	input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
 
-	if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
-		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
+	if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
 		input_mt_init_slots(dev, 2);
-		input_set_abs_params(dev, ABS_MT_POSITION_X,
-				     priv->x_min ?: XMIN_NOMINAL,
-				     priv->x_max ?: XMAX_NOMINAL,
-				     fuzz, 0);
-		input_set_abs_params(dev, ABS_MT_POSITION_Y,
-				     priv->y_min ?: YMIN_NOMINAL,
-				     priv->y_max ?: YMAX_NOMINAL,
-				     fuzz, 0);
+		set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
+					ABS_MT_POSITION_Y);
+		/* Image sensors can report per-contact pressure */
+		input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
 
-		input_abs_set_res(dev, ABS_MT_POSITION_X, priv->x_res);
-		input_abs_set_res(dev, ABS_MT_POSITION_Y, priv->y_res);
+		/* Image sensors can signal 4 and 5 finger clicks */
+		__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
+		__set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
+	} else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
+		/* Non-image sensors with AGM use semi-mt */
+		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
+		input_mt_init_slots(dev, 2);
+		set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
+					ABS_MT_POSITION_Y);
 	}
 
 	if (SYN_CAP_PALMDETECT(priv->capabilities))
@@ -759,9 +1197,6 @@
 	__clear_bit(REL_X, dev->relbit);
 	__clear_bit(REL_Y, dev->relbit);
 
-	input_abs_set_res(dev, ABS_X, priv->x_res);
-	input_abs_set_res(dev, ABS_Y, priv->y_res);
-
 	if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
 		__set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
 		/* Clickpads report only left button */
@@ -786,6 +1221,16 @@
 
 	do {
 		psmouse_reset(psmouse);
+		if (retry) {
+			/*
+			 * On some boxes, right after resuming, the touchpad
+			 * needs some time to finish initializing (I assume
+			 * it needs time to calibrate) and start responding
+			 * to Synaptics-specific queries, so let's wait a
+			 * bit.
+			 */
+			ssleep(1);
+		}
 		error = synaptics_detect(psmouse, 0);
 	} while (error && ++retry < 3);
 
@@ -793,21 +1238,21 @@
 		return -1;
 
 	if (retry > 1)
-		printk(KERN_DEBUG "Synaptics reconnected after %d tries\n",
-			retry);
+		psmouse_dbg(psmouse, "reconnected after %d tries\n", retry);
 
 	if (synaptics_query_hardware(psmouse)) {
-		printk(KERN_ERR "Unable to query Synaptics hardware.\n");
+		psmouse_err(psmouse, "Unable to query device.\n");
 		return -1;
 	}
 
 	if (synaptics_set_absolute_mode(psmouse)) {
-		printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
+		psmouse_err(psmouse, "Unable to initialize device.\n");
 		return -1;
 	}
 
 	if (synaptics_set_advanced_gesture_mode(psmouse)) {
-		printk(KERN_ERR "Advanced gesture mode reconnect failed.\n");
+		psmouse_err(psmouse,
+			    "Advanced gesture mode reconnect failed.\n");
 		return -1;
 	}
 
@@ -815,12 +1260,12 @@
 	    old_priv.model_id != priv->model_id ||
 	    old_priv.capabilities != priv->capabilities ||
 	    old_priv.ext_cap != priv->ext_cap) {
-		printk(KERN_ERR "Synaptics hardware appears to be different: "
-			"id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n",
-			old_priv.identity, priv->identity,
-			old_priv.model_id, priv->model_id,
-			old_priv.capabilities, priv->capabilities,
-			old_priv.ext_cap, priv->ext_cap);
+		psmouse_err(psmouse,
+			    "hardware appears to be different: id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n",
+			    old_priv.identity, priv->identity,
+			    old_priv.model_id, priv->model_id,
+			    old_priv.capabilities, priv->capabilities,
+			    old_priv.ext_cap, priv->ext_cap);
 		return -1;
 	}
 
@@ -901,7 +1346,8 @@
 	 * just fine.
 	 */
 	if (broken_olpc_ec) {
-		printk(KERN_INFO "synaptics: OLPC XO detected, not enabling Synaptics protocol.\n");
+		psmouse_info(psmouse,
+			     "OLPC XO detected, not enabling Synaptics protocol.\n");
 		return -ENODEV;
 	}
 
@@ -912,26 +1358,28 @@
 	psmouse_reset(psmouse);
 
 	if (synaptics_query_hardware(psmouse)) {
-		printk(KERN_ERR "Unable to query Synaptics hardware.\n");
+		psmouse_err(psmouse, "Unable to query device.\n");
 		goto init_fail;
 	}
 
 	if (synaptics_set_absolute_mode(psmouse)) {
-		printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
+		psmouse_err(psmouse, "Unable to initialize device.\n");
 		goto init_fail;
 	}
 
 	if (synaptics_set_advanced_gesture_mode(psmouse)) {
-		printk(KERN_ERR "Advanced gesture mode init failed.\n");
+		psmouse_err(psmouse, "Advanced gesture mode init failed.\n");
 		goto init_fail;
 	}
 
 	priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
 
-	printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n",
-		SYN_ID_MODEL(priv->identity),
-		SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
-		priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c);
+	psmouse_info(psmouse,
+		     "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n",
+		     SYN_ID_MODEL(priv->identity),
+		     SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
+		     priv->model_id,
+		     priv->capabilities, priv->ext_cap, priv->ext_cap_0c);
 
 	set_input_params(psmouse->dev, priv);
 
@@ -963,8 +1411,9 @@
 	 * the same rate as a standard PS/2 mouse).
 	 */
 	if (psmouse->rate >= 80 && impaired_toshiba_kbc) {
-		printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n",
-			dmi_get_system_info(DMI_PRODUCT_NAME));
+		psmouse_info(psmouse,
+			     "Toshiba %s detected, limiting rate to 40pps.\n",
+			     dmi_get_system_info(DMI_PRODUCT_NAME));
 		psmouse->rate = 40;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/input/mouse/synaptics.h linux-libre-3.2-gnu/drivers/input/mouse/synaptics.h
--- linux-libre-3.1-gnu/drivers/input/mouse/synaptics.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/mouse/synaptics.h	2012-01-04 18:55:44.000000000 -0500
@@ -74,6 +74,8 @@
  * 2	0x04	reduced filtering	firmware does less filtering on
  *					position data, driver should watch
  *					for noise.
+ * 2	0x08	image sensor		image sensor tracks 5 fingers, but only
+ *					reports 2.
  * 2	0x20	report min		query 0x0f gives min coord reported
  */
 #define SYN_CAP_CLICKPAD(ex0c)		((ex0c) & 0x100000) /* 1-button ClickPad */
@@ -82,6 +84,7 @@
 #define SYN_CAP_MIN_DIMENSIONS(ex0c)	((ex0c) & 0x002000)
 #define SYN_CAP_ADV_GESTURE(ex0c)	((ex0c) & 0x080000)
 #define SYN_CAP_REDUCED_FILTERING(ex0c)	((ex0c) & 0x000400)
+#define SYN_CAP_IMAGE_SENSOR(ex0c)	((ex0c) & 0x000800)
 
 /* synaptics modes query bits */
 #define SYN_MODE_ABSOLUTE(m)		((m) & (1 << 7))
@@ -112,9 +115,18 @@
 #define SYN_REDUCED_FILTER_FUZZ		8
 
 /*
- * A structure to describe the state of the touchpad hardware (buttons and pad)
+ * A structure to describe which internal touchpad finger slots are being
+ * reported in raw packets.
  */
+struct synaptics_mt_state {
+	int count;			/* num fingers being tracked */
+	int sgm;			/* which slot is reported by sgm pkt */
+	int agm;			/* which slot is reported by agm pkt*/
+};
 
+/*
+ * A structure to describe the state of the touchpad hardware (buttons and pad)
+ */
 struct synaptics_hw_state {
 	int x;
 	int y;
@@ -127,6 +139,9 @@
 	unsigned int down:1;
 	unsigned char ext_buttons;
 	signed char scroll;
+
+	/* As reported in last AGM-CONTACT packets */
+	struct synaptics_mt_state mt_state;
 };
 
 struct synaptics_data {
@@ -146,7 +161,15 @@
 
 	struct serio *pt_port;			/* Pass-through serio port */
 
-	struct synaptics_hw_state mt;		/* current gesture packet */
+	struct synaptics_mt_state mt_state;	/* Current mt finger state */
+	bool mt_state_lost;			/* mt_state may be incorrect */
+
+	/*
+	 * Last received Advanced Gesture Mode (AGM) packet. An AGM packet
+	 * contains position data for a second contact, at half resolution.
+	 */
+	struct synaptics_hw_state agm;
+	bool agm_pending;			/* new AGM packet received */
 };
 
 void synaptics_module_init(void);
diff -druN linux-libre-3.1-gnu/drivers/input/mouse/synaptics_i2c.c linux-libre-3.2-gnu/drivers/input/mouse/synaptics_i2c.c
--- linux-libre-3.1-gnu/drivers/input/mouse/synaptics_i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/mouse/synaptics_i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -570,7 +570,7 @@
 			 "Requesting IRQ: %d\n", touch->client->irq);
 
 		ret = request_irq(touch->client->irq, synaptics_i2c_irq,
-				  IRQF_DISABLED|IRQ_TYPE_EDGE_FALLING,
+				  IRQ_TYPE_EDGE_FALLING,
 				  DRIVER_NAME, touch);
 		if (ret) {
 			dev_warn(&touch->client->dev,
@@ -619,7 +619,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int synaptics_i2c_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
diff -druN linux-libre-3.1-gnu/drivers/input/serio/ams_delta_serio.c linux-libre-3.2-gnu/drivers/input/serio/ams_delta_serio.c
--- linux-libre-3.1-gnu/drivers/input/serio/ams_delta_serio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/serio/ams_delta_serio.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/irq.h>
 #include <linux/serio.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include <asm/mach-types.h>
 #include <plat/board-ams-delta.h>
diff -druN linux-libre-3.1-gnu/drivers/input/serio/i8042-x86ia64io.h linux-libre-3.2-gnu/drivers/input/serio/i8042-x86ia64io.h
--- linux-libre-3.1-gnu/drivers/input/serio/i8042-x86ia64io.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/serio/i8042-x86ia64io.h	2012-01-04 18:55:44.000000000 -0500
@@ -431,6 +431,13 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
 		},
 	},
+	{
+		/* Newer HP Pavilion dv4 models */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
+		},
+	},
 	{ }
 };
 
@@ -560,6 +567,13 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
 		},
 	},
+	{
+		/* Newer HP Pavilion dv4 models */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
+		},
+	},
 	{ }
 };
 
diff -druN linux-libre-3.1-gnu/drivers/input/serio/serio_raw.c linux-libre-3.2-gnu/drivers/input/serio/serio_raw.c
--- linux-libre-3.1-gnu/drivers/input/serio/serio_raw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/serio/serio_raw.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  * the Free Software Foundation.
  */
 
+#include <linux/kref.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
@@ -33,15 +34,16 @@
 	unsigned int tail, head;
 
 	char name[16];
-	unsigned int refcnt;
+	struct kref kref;
 	struct serio *serio;
 	struct miscdevice dev;
 	wait_queue_head_t wait;
-	struct list_head list;
+	struct list_head client_list;
 	struct list_head node;
+	bool dead;
 };
 
-struct serio_raw_list {
+struct serio_raw_client {
 	struct fasync_struct *fasync;
 	struct serio_raw *serio_raw;
 	struct list_head node;
@@ -49,7 +51,6 @@
 
 static DEFINE_MUTEX(serio_raw_mutex);
 static LIST_HEAD(serio_raw_list);
-static unsigned int serio_raw_no;
 
 /*********************************************************************
  *             Interface with userspace (file operations)            *
@@ -57,9 +58,9 @@
 
 static int serio_raw_fasync(int fd, struct file *file, int on)
 {
-	struct serio_raw_list *list = file->private_data;
+	struct serio_raw_client *client = file->private_data;
 
-	return fasync_helper(fd, file, on, &list->fasync);
+	return fasync_helper(fd, file, on, &client->fasync);
 }
 
 static struct serio_raw *serio_raw_locate(int minor)
@@ -77,8 +78,8 @@
 static int serio_raw_open(struct inode *inode, struct file *file)
 {
 	struct serio_raw *serio_raw;
-	struct serio_raw_list *list;
-	int retval = 0;
+	struct serio_raw_client *client;
+	int retval;
 
 	retval = mutex_lock_interruptible(&serio_raw_mutex);
 	if (retval)
@@ -90,60 +91,61 @@
 		goto out;
 	}
 
-	if (!serio_raw->serio) {
+	if (serio_raw->dead) {
 		retval = -ENODEV;
 		goto out;
 	}
 
-	list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL);
-	if (!list) {
+	client = kzalloc(sizeof(struct serio_raw_client), GFP_KERNEL);
+	if (!client) {
 		retval = -ENOMEM;
 		goto out;
 	}
 
-	list->serio_raw = serio_raw;
-	file->private_data = list;
+	client->serio_raw = serio_raw;
+	file->private_data = client;
 
-	serio_raw->refcnt++;
-	list_add_tail(&list->node, &serio_raw->list);
+	kref_get(&serio_raw->kref);
+
+	serio_pause_rx(serio_raw->serio);
+	list_add_tail(&client->node, &serio_raw->client_list);
+	serio_continue_rx(serio_raw->serio);
 
 out:
 	mutex_unlock(&serio_raw_mutex);
 	return retval;
 }
 
-static int serio_raw_cleanup(struct serio_raw *serio_raw)
+static void serio_raw_free(struct kref *kref)
 {
-	if (--serio_raw->refcnt == 0) {
-		misc_deregister(&serio_raw->dev);
-		list_del_init(&serio_raw->node);
-		kfree(serio_raw);
-
-		return 1;
-	}
+	struct serio_raw *serio_raw =
+			container_of(kref, struct serio_raw, kref);
 
-	return 0;
+	put_device(&serio_raw->serio->dev);
+	kfree(serio_raw);
 }
 
 static int serio_raw_release(struct inode *inode, struct file *file)
 {
-	struct serio_raw_list *list = file->private_data;
-	struct serio_raw *serio_raw = list->serio_raw;
+	struct serio_raw_client *client = file->private_data;
+	struct serio_raw *serio_raw = client->serio_raw;
 
-	mutex_lock(&serio_raw_mutex);
+	serio_pause_rx(serio_raw->serio);
+	list_del(&client->node);
+	serio_continue_rx(serio_raw->serio);
 
-	serio_raw_cleanup(serio_raw);
+	kfree(client);
+
+	kref_put(&serio_raw->kref, serio_raw_free);
 
-	mutex_unlock(&serio_raw_mutex);
 	return 0;
 }
 
-static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
+static bool serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
 {
-	unsigned long flags;
-	int empty;
+	bool empty;
 
-	spin_lock_irqsave(&serio_raw->serio->lock, flags);
+	serio_pause_rx(serio_raw->serio);
 
 	empty = serio_raw->head == serio_raw->tail;
 	if (!empty) {
@@ -151,30 +153,31 @@
 		serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
 	}
 
-	spin_unlock_irqrestore(&serio_raw->serio->lock, flags);
+	serio_continue_rx(serio_raw->serio);
 
 	return !empty;
 }
 
-static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+static ssize_t serio_raw_read(struct file *file, char __user *buffer,
+			      size_t count, loff_t *ppos)
 {
-	struct serio_raw_list *list = file->private_data;
-	struct serio_raw *serio_raw = list->serio_raw;
+	struct serio_raw_client *client = file->private_data;
+	struct serio_raw *serio_raw = client->serio_raw;
 	char uninitialized_var(c);
 	ssize_t retval = 0;
 
-	if (!serio_raw->serio)
+	if (serio_raw->dead)
 		return -ENODEV;
 
 	if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK))
 		return -EAGAIN;
 
-	retval = wait_event_interruptible(list->serio_raw->wait,
-					  serio_raw->head != serio_raw->tail || !serio_raw->serio);
+	retval = wait_event_interruptible(serio_raw->wait,
+			serio_raw->head != serio_raw->tail || serio_raw->dead);
 	if (retval)
 		return retval;
 
-	if (!serio_raw->serio)
+	if (serio_raw->dead)
 		return -ENODEV;
 
 	while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) {
@@ -186,9 +189,11 @@
 	return retval;
 }
 
-static ssize_t serio_raw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
+			       size_t count, loff_t *ppos)
 {
-	struct serio_raw_list *list = file->private_data;
+	struct serio_raw_client *client = file->private_data;
+	struct serio_raw *serio_raw = client->serio_raw;
 	ssize_t written = 0;
 	int retval;
 	unsigned char c;
@@ -197,7 +202,7 @@
 	if (retval)
 		return retval;
 
-	if (!list->serio_raw->serio) {
+	if (serio_raw->dead) {
 		retval = -ENODEV;
 		goto out;
 	}
@@ -210,7 +215,7 @@
 			retval = -EFAULT;
 			goto out;
 		}
-		if (serio_write(list->serio_raw->serio, c)) {
+		if (serio_write(serio_raw->serio, c)) {
 			retval = -EIO;
 			goto out;
 		}
@@ -224,46 +229,49 @@
 
 static unsigned int serio_raw_poll(struct file *file, poll_table *wait)
 {
-	struct serio_raw_list *list = file->private_data;
+	struct serio_raw_client *client = file->private_data;
+	struct serio_raw *serio_raw = client->serio_raw;
+	unsigned int mask;
 
-	poll_wait(file, &list->serio_raw->wait, wait);
+	poll_wait(file, &serio_raw->wait, wait);
 
-	if (list->serio_raw->head != list->serio_raw->tail)
+	mask = serio_raw->dead ? POLLHUP | POLLERR : POLLOUT | POLLWRNORM;
+	if (serio_raw->head != serio_raw->tail)
 		return POLLIN | POLLRDNORM;
 
 	return 0;
 }
 
 static const struct file_operations serio_raw_fops = {
-	.owner =	THIS_MODULE,
-	.open =		serio_raw_open,
-	.release =	serio_raw_release,
-	.read =		serio_raw_read,
-	.write =	serio_raw_write,
-	.poll =		serio_raw_poll,
-	.fasync =	serio_raw_fasync,
-	.llseek = noop_llseek,
+	.owner		= THIS_MODULE,
+	.open		= serio_raw_open,
+	.release	= serio_raw_release,
+	.read		= serio_raw_read,
+	.write		= serio_raw_write,
+	.poll		= serio_raw_poll,
+	.fasync		= serio_raw_fasync,
+	.llseek		= noop_llseek,
 };
 
 
 /*********************************************************************
- *                   Interface with serio port   	             *
+ *                   Interface with serio port                       *
  *********************************************************************/
 
 static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
 					unsigned int dfl)
 {
 	struct serio_raw *serio_raw = serio_get_drvdata(serio);
-	struct serio_raw_list *list;
+	struct serio_raw_client *client;
 	unsigned int head = serio_raw->head;
 
-	/* we are holding serio->lock here so we are prootected */
+	/* we are holding serio->lock here so we are protected */
 	serio_raw->queue[head] = data;
 	head = (head + 1) % SERIO_RAW_QUEUE_LEN;
 	if (likely(head != serio_raw->tail)) {
 		serio_raw->head = head;
-		list_for_each_entry(list, &serio_raw->list, node)
-			kill_fasync(&list->fasync, SIGIO, POLL_IN);
+		list_for_each_entry(client, &serio_raw->client_list, node)
+			kill_fasync(&client->fasync, SIGIO, POLL_IN);
 		wake_up_interruptible(&serio_raw->wait);
 	}
 
@@ -272,29 +280,37 @@
 
 static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
 {
+	static atomic_t serio_raw_no = ATOMIC_INIT(0);
 	struct serio_raw *serio_raw;
 	int err;
 
-	if (!(serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
-		printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n");
+	serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL);
+	if (!serio_raw) {
+		dev_dbg(&serio->dev, "can't allocate memory for a device\n");
 		return -ENOMEM;
 	}
 
-	mutex_lock(&serio_raw_mutex);
+	snprintf(serio_raw->name, sizeof(serio_raw->name),
+		 "serio_raw%ld", (long)atomic_inc_return(&serio_raw_no) - 1);
+	kref_init(&serio_raw->kref);
+	INIT_LIST_HEAD(&serio_raw->client_list);
+	init_waitqueue_head(&serio_raw->wait);
 
-	snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++);
-	serio_raw->refcnt = 1;
 	serio_raw->serio = serio;
-	INIT_LIST_HEAD(&serio_raw->list);
-	init_waitqueue_head(&serio_raw->wait);
+	get_device(&serio->dev);
 
 	serio_set_drvdata(serio, serio_raw);
 
 	err = serio_open(serio, drv);
 	if (err)
-		goto out_free;
+		goto err_free;
+
+	err = mutex_lock_killable(&serio_raw_mutex);
+	if (err)
+		goto err_close;
 
 	list_add_tail(&serio_raw->node, &serio_raw_list);
+	mutex_unlock(&serio_raw_mutex);
 
 	serio_raw->dev.minor = PSMOUSE_MINOR;
 	serio_raw->dev.name = serio_raw->name;
@@ -308,23 +324,23 @@
 	}
 
 	if (err) {
-		printk(KERN_INFO "serio_raw: failed to register raw access device for %s\n",
+		dev_err(&serio->dev,
+			"failed to register raw access device for %s\n",
 			serio->phys);
-		goto out_close;
+		goto err_unlink;
 	}
 
-	printk(KERN_INFO "serio_raw: raw access enabled on %s (%s, minor %d)\n",
-		serio->phys, serio_raw->name, serio_raw->dev.minor);
-	goto out;
+	dev_info(&serio->dev, "raw access enabled on %s (%s, minor %d)\n",
+		 serio->phys, serio_raw->name, serio_raw->dev.minor);
+	return 0;
 
-out_close:
-	serio_close(serio);
+err_unlink:
 	list_del_init(&serio_raw->node);
-out_free:
+err_close:
+	serio_close(serio);
+err_free:
 	serio_set_drvdata(serio, NULL);
-	kfree(serio_raw);
-out:
-	mutex_unlock(&serio_raw_mutex);
+	kref_put(&serio_raw->kref, serio_raw_free);
 	return err;
 }
 
@@ -334,7 +350,8 @@
 	struct serio_driver *drv = serio->drv;
 
 	if (!drv || !serio_raw) {
-		printk(KERN_DEBUG "serio_raw: reconnect request, but serio is disconnected, ignoring...\n");
+		dev_dbg(&serio->dev,
+			"reconnect request, but serio is disconnected, ignoring...\n");
 		return -1;
 	}
 
@@ -345,22 +362,40 @@
 	return 0;
 }
 
+/*
+ * Wake up users waiting for IO so they can disconnect from
+ * dead device.
+ */
+static void serio_raw_hangup(struct serio_raw *serio_raw)
+{
+	struct serio_raw_client *client;
+
+	serio_pause_rx(serio_raw->serio);
+	list_for_each_entry(client, &serio_raw->client_list, node)
+		kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+	serio_continue_rx(serio_raw->serio);
+
+	wake_up_interruptible(&serio_raw->wait);
+}
+
+
 static void serio_raw_disconnect(struct serio *serio)
 {
-	struct serio_raw *serio_raw;
+	struct serio_raw *serio_raw = serio_get_drvdata(serio);
+
+	misc_deregister(&serio_raw->dev);
 
 	mutex_lock(&serio_raw_mutex);
+	serio_raw->dead = true;
+	list_del_init(&serio_raw->node);
+	mutex_unlock(&serio_raw_mutex);
 
-	serio_raw = serio_get_drvdata(serio);
+	serio_raw_hangup(serio_raw);
 
 	serio_close(serio);
-	serio_set_drvdata(serio, NULL);
-
-	serio_raw->serio = NULL;
-	if (!serio_raw_cleanup(serio_raw))
-		wake_up_interruptible(&serio_raw->wait);
+	kref_put(&serio_raw->kref, serio_raw_free);
 
-	mutex_unlock(&serio_raw_mutex);
+	serio_set_drvdata(serio, NULL);
 }
 
 static struct serio_device_id serio_raw_serio_ids[] = {
@@ -391,7 +426,7 @@
 	.connect	= serio_raw_connect,
 	.reconnect	= serio_raw_reconnect,
 	.disconnect	= serio_raw_disconnect,
-	.manual_bind	= 1,
+	.manual_bind	= true,
 };
 
 static int __init serio_raw_init(void)
diff -druN linux-libre-3.1-gnu/drivers/input/sparse-keymap.c linux-libre-3.2-gnu/drivers/input/sparse-keymap.c
--- linux-libre-3.1-gnu/drivers/input/sparse-keymap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/sparse-keymap.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 
 MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
diff -druN linux-libre-3.1-gnu/drivers/input/tablet/wacom.h linux-libre-3.2-gnu/drivers/input/tablet/wacom.h
--- linux-libre-3.1-gnu/drivers/input/tablet/wacom.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/tablet/wacom.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,7 +11,7 @@
  *  Copyright (c) 2000 Daniel Egger		<egger@suse.de>
  *  Copyright (c) 2001 Frederic Lepied		<flepied@mandrakesoft.com>
  *  Copyright (c) 2004 Panagiotis Issaris	<panagiotis.issaris@mech.kuleuven.ac.be>
- *  Copyright (c) 2002-2009 Ping Cheng		<pingc@wacom.com>
+ *  Copyright (c) 2002-2011 Ping Cheng		<pingc@wacom.com>
  *
  *  ChangeLog:
  *      v0.1 (vp)  - Initial release
@@ -93,7 +93,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.52"
+#define DRIVER_VERSION "v1.53"
 #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
 #define DRIVER_DESC "USB Wacom tablet driver"
 #define DRIVER_LICENSE "GPL"
@@ -114,6 +114,12 @@
 	struct mutex lock;
 	bool open;
 	char phys[32];
+	struct wacom_led {
+		u8 select[2]; /* status led selector (0..3) */
+		u8 llv;       /* status led brightness no button (1..127) */
+		u8 hlv;       /* status led brightness button pressed (1..127) */
+		u8 img_lum;   /* OLED matrix display brightness */
+	} led;
 };
 
 extern const struct usb_device_id wacom_ids[];
diff -druN linux-libre-3.1-gnu/drivers/input/tablet/wacom_sys.c linux-libre-3.2-gnu/drivers/input/tablet/wacom_sys.c
--- linux-libre-3.1-gnu/drivers/input/tablet/wacom_sys.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/tablet/wacom_sys.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,27 +48,49 @@
 /* defines to get/set USB message */
 #define USB_REQ_GET_REPORT	0x01
 #define USB_REQ_SET_REPORT	0x09
+
 #define WAC_HID_FEATURE_REPORT	0x03
 #define WAC_MSG_RETRIES		5
 
-static int usb_get_report(struct usb_interface *intf, unsigned char type,
-				unsigned char id, void *buf, int size)
+#define WAC_CMD_LED_CONTROL	0x20
+#define WAC_CMD_ICON_START	0x21
+#define WAC_CMD_ICON_XFER	0x23
+#define WAC_CMD_RETRIES		10
+
+static int wacom_get_report(struct usb_interface *intf, u8 type, u8 id,
+			    void *buf, size_t size, unsigned int retries)
 {
-	return usb_control_msg(interface_to_usbdev(intf),
-		usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
-		USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-		(type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
-		buf, size, 100);
+	struct usb_device *dev = interface_to_usbdev(intf);
+	int retval;
+
+	do {
+		retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+				USB_REQ_GET_REPORT,
+				USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+				(type << 8) + id,
+				intf->altsetting[0].desc.bInterfaceNumber,
+				buf, size, 100);
+	} while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
+
+	return retval;
 }
 
-static int usb_set_report(struct usb_interface *intf, unsigned char type,
-				unsigned char id, void *buf, int size)
+static int wacom_set_report(struct usb_interface *intf, u8 type, u8 id,
+			    void *buf, size_t size, unsigned int retries)
 {
-	return usb_control_msg(interface_to_usbdev(intf),
-		usb_sndctrlpipe(interface_to_usbdev(intf), 0),
-                USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-                (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
-		buf, size, 1000);
+	struct usb_device *dev = interface_to_usbdev(intf);
+	int retval;
+
+	do {
+		retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+				USB_REQ_SET_REPORT,
+				USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+				(type << 8) + id,
+				intf->altsetting[0].desc.bInterfaceNumber,
+				buf, size, 1000);
+	} while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
+
+	return retval;
 }
 
 static void wacom_sys_irq(struct urb *urb)
@@ -319,23 +341,23 @@
 			rep_data[2] = 0;
 			rep_data[3] = 0;
 			report_id = 3;
-			error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
-				report_id, rep_data, 4);
+			error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
+						 report_id, rep_data, 4, 1);
 			if (error >= 0)
-				error = usb_get_report(intf,
-					WAC_HID_FEATURE_REPORT, report_id,
-					rep_data, 4);
+				error = wacom_get_report(intf,
+						WAC_HID_FEATURE_REPORT,
+						report_id, rep_data, 4, 1);
 		} while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES);
 	} else if (features->type != TABLETPC) {
 		do {
 			rep_data[0] = 2;
 			rep_data[1] = 2;
-			error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
-				report_id, rep_data, 2);
+			error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
+						 report_id, rep_data, 2, 1);
 			if (error >= 0)
-				error = usb_get_report(intf,
-					WAC_HID_FEATURE_REPORT, report_id,
-					rep_data, 2);
+				error = wacom_get_report(intf,
+						WAC_HID_FEATURE_REPORT,
+						report_id, rep_data, 2, 1);
 		} while ((error < 0 || rep_data[1] != 2) && limit++ < WAC_MSG_RETRIES);
 	}
 
@@ -454,6 +476,275 @@
 	}
 }
 
+static int wacom_led_control(struct wacom *wacom)
+{
+	unsigned char *buf;
+	int retval, led = 0;
+
+	buf = kzalloc(9, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (wacom->wacom_wac.features.type == WACOM_21UX2)
+		led = (wacom->led.select[1] << 4) | 0x40;
+
+	led |=  wacom->led.select[0] | 0x4;
+
+	buf[0] = WAC_CMD_LED_CONTROL;
+	buf[1] = led;
+	buf[2] = wacom->led.llv;
+	buf[3] = wacom->led.hlv;
+	buf[4] = wacom->led.img_lum;
+
+	retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL,
+				  buf, 9, WAC_CMD_RETRIES);
+	kfree(buf);
+
+	return retval;
+}
+
+static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *img)
+{
+	unsigned char *buf;
+	int i, retval;
+
+	buf = kzalloc(259, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	/* Send 'start' command */
+	buf[0] = WAC_CMD_ICON_START;
+	buf[1] = 1;
+	retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START,
+				  buf, 2, WAC_CMD_RETRIES);
+	if (retval < 0)
+		goto out;
+
+	buf[0] = WAC_CMD_ICON_XFER;
+	buf[1] = button_id & 0x07;
+	for (i = 0; i < 4; i++) {
+		buf[2] = i;
+		memcpy(buf + 3, img + i * 256, 256);
+
+		retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_XFER,
+					  buf, 259, WAC_CMD_RETRIES);
+		if (retval < 0)
+			break;
+	}
+
+	/* Send 'stop' */
+	buf[0] = WAC_CMD_ICON_START;
+	buf[1] = 0;
+	wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START,
+			 buf, 2, WAC_CMD_RETRIES);
+
+out:
+	kfree(buf);
+	return retval;
+}
+
+static ssize_t wacom_led_select_store(struct device *dev, int set_id,
+				      const char *buf, size_t count)
+{
+	struct wacom *wacom = dev_get_drvdata(dev);
+	unsigned int id;
+	int err;
+
+	err = kstrtouint(buf, 10, &id);
+	if (err)
+		return err;
+
+	mutex_lock(&wacom->lock);
+
+	wacom->led.select[set_id] = id & 0x3;
+	err = wacom_led_control(wacom);
+
+	mutex_unlock(&wacom->lock);
+
+	return err < 0 ? err : count;
+}
+
+#define DEVICE_LED_SELECT_ATTR(SET_ID)					\
+static ssize_t wacom_led##SET_ID##_select_store(struct device *dev,	\
+	struct device_attribute *attr, const char *buf, size_t count)	\
+{									\
+	return wacom_led_select_store(dev, SET_ID, buf, count);		\
+}									\
+static ssize_t wacom_led##SET_ID##_select_show(struct device *dev,	\
+	struct device_attribute *attr, char *buf)			\
+{									\
+	struct wacom *wacom = dev_get_drvdata(dev);			\
+	return snprintf(buf, 2, "%d\n", wacom->led.select[SET_ID]);	\
+}									\
+static DEVICE_ATTR(status_led##SET_ID##_select, S_IWUSR | S_IRUSR,	\
+		    wacom_led##SET_ID##_select_show,			\
+		    wacom_led##SET_ID##_select_store)
+
+DEVICE_LED_SELECT_ATTR(0);
+DEVICE_LED_SELECT_ATTR(1);
+
+static ssize_t wacom_luminance_store(struct wacom *wacom, u8 *dest,
+				     const char *buf, size_t count)
+{
+	unsigned int value;
+	int err;
+
+	err = kstrtouint(buf, 10, &value);
+	if (err)
+		return err;
+
+	mutex_lock(&wacom->lock);
+
+	*dest = value & 0x7f;
+	err = wacom_led_control(wacom);
+
+	mutex_unlock(&wacom->lock);
+
+	return err < 0 ? err : count;
+}
+
+#define DEVICE_LUMINANCE_ATTR(name, field)				\
+static ssize_t wacom_##name##_luminance_store(struct device *dev,	\
+	struct device_attribute *attr, const char *buf, size_t count)	\
+{									\
+	struct wacom *wacom = dev_get_drvdata(dev);			\
+									\
+	return wacom_luminance_store(wacom, &wacom->led.field,		\
+				     buf, count);			\
+}									\
+static DEVICE_ATTR(name##_luminance, S_IWUSR,				\
+		   NULL, wacom_##name##_luminance_store)
+
+DEVICE_LUMINANCE_ATTR(status0, llv);
+DEVICE_LUMINANCE_ATTR(status1, hlv);
+DEVICE_LUMINANCE_ATTR(buttons, img_lum);
+
+static ssize_t wacom_button_image_store(struct device *dev, int button_id,
+					const char *buf, size_t count)
+{
+	struct wacom *wacom = dev_get_drvdata(dev);
+	int err;
+
+	if (count != 1024)
+		return -EINVAL;
+
+	mutex_lock(&wacom->lock);
+
+	err = wacom_led_putimage(wacom, button_id, buf);
+
+	mutex_unlock(&wacom->lock);
+
+	return err < 0 ? err : count;
+}
+
+#define DEVICE_BTNIMG_ATTR(BUTTON_ID)					\
+static ssize_t wacom_btnimg##BUTTON_ID##_store(struct device *dev,	\
+	struct device_attribute *attr, const char *buf, size_t count)	\
+{									\
+	return wacom_button_image_store(dev, BUTTON_ID, buf, count);	\
+}									\
+static DEVICE_ATTR(button##BUTTON_ID##_rawimg, S_IWUSR,			\
+		   NULL, wacom_btnimg##BUTTON_ID##_store)
+
+DEVICE_BTNIMG_ATTR(0);
+DEVICE_BTNIMG_ATTR(1);
+DEVICE_BTNIMG_ATTR(2);
+DEVICE_BTNIMG_ATTR(3);
+DEVICE_BTNIMG_ATTR(4);
+DEVICE_BTNIMG_ATTR(5);
+DEVICE_BTNIMG_ATTR(6);
+DEVICE_BTNIMG_ATTR(7);
+
+static struct attribute *cintiq_led_attrs[] = {
+	&dev_attr_status_led0_select.attr,
+	&dev_attr_status_led1_select.attr,
+	NULL
+};
+
+static struct attribute_group cintiq_led_attr_group = {
+	.name = "wacom_led",
+	.attrs = cintiq_led_attrs,
+};
+
+static struct attribute *intuos4_led_attrs[] = {
+	&dev_attr_status0_luminance.attr,
+	&dev_attr_status1_luminance.attr,
+	&dev_attr_status_led0_select.attr,
+	&dev_attr_buttons_luminance.attr,
+	&dev_attr_button0_rawimg.attr,
+	&dev_attr_button1_rawimg.attr,
+	&dev_attr_button2_rawimg.attr,
+	&dev_attr_button3_rawimg.attr,
+	&dev_attr_button4_rawimg.attr,
+	&dev_attr_button5_rawimg.attr,
+	&dev_attr_button6_rawimg.attr,
+	&dev_attr_button7_rawimg.attr,
+	NULL
+};
+
+static struct attribute_group intuos4_led_attr_group = {
+	.name = "wacom_led",
+	.attrs = intuos4_led_attrs,
+};
+
+static int wacom_initialize_leds(struct wacom *wacom)
+{
+	int error;
+
+	/* Initialize default values */
+	switch (wacom->wacom_wac.features.type) {
+	case INTUOS4:
+	case INTUOS4L:
+		wacom->led.select[0] = 0;
+		wacom->led.select[1] = 0;
+		wacom->led.llv = 10;
+		wacom->led.hlv = 20;
+		wacom->led.img_lum = 10;
+		error = sysfs_create_group(&wacom->intf->dev.kobj,
+					   &intuos4_led_attr_group);
+		break;
+
+	case WACOM_21UX2:
+		wacom->led.select[0] = 0;
+		wacom->led.select[1] = 0;
+		wacom->led.llv = 0;
+		wacom->led.hlv = 0;
+		wacom->led.img_lum = 0;
+
+		error = sysfs_create_group(&wacom->intf->dev.kobj,
+					   &cintiq_led_attr_group);
+		break;
+
+	default:
+		return 0;
+	}
+
+	if (error) {
+		dev_err(&wacom->intf->dev,
+			"cannot create sysfs group err: %d\n", error);
+		return error;
+	}
+	wacom_led_control(wacom);
+
+	return 0;
+}
+
+static void wacom_destroy_leds(struct wacom *wacom)
+{
+	switch (wacom->wacom_wac.features.type) {
+	case INTUOS4:
+	case INTUOS4L:
+		sysfs_remove_group(&wacom->intf->dev.kobj,
+				   &intuos4_led_attr_group);
+		break;
+
+	case WACOM_21UX2:
+		sysfs_remove_group(&wacom->intf->dev.kobj,
+				   &cintiq_led_attr_group);
+		break;
+	}
+}
+
 static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
@@ -542,16 +833,21 @@
 	wacom->irq->transfer_dma = wacom->data_dma;
 	wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	error = input_register_device(input_dev);
+	error = wacom_initialize_leds(wacom);
 	if (error)
 		goto fail4;
 
+	error = input_register_device(input_dev);
+	if (error)
+		goto fail5;
+
 	/* Note that if query fails it is not a hard failure */
 	wacom_query_tablet_data(intf, features);
 
 	usb_set_intfdata(intf, wacom);
 	return 0;
 
+ fail5: wacom_destroy_leds(wacom);
  fail4:	wacom_remove_shared_data(wacom_wac);
  fail3:	usb_free_urb(wacom->irq);
  fail2:	usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
@@ -568,6 +864,7 @@
 
 	usb_kill_urb(wacom->irq);
 	input_unregister_device(wacom->wacom_wac.input);
+	wacom_destroy_leds(wacom);
 	usb_free_urb(wacom->irq);
 	usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
 			wacom->wacom_wac.data, wacom->data_dma);
@@ -590,17 +887,16 @@
 {
 	struct wacom *wacom = usb_get_intfdata(intf);
 	struct wacom_features *features = &wacom->wacom_wac.features;
-	int rv;
+	int rv = 0;
 
 	mutex_lock(&wacom->lock);
 
 	/* switch to wacom mode first */
 	wacom_query_tablet_data(intf, features);
+	wacom_led_control(wacom);
 
-	if (wacom->open)
-		rv = usb_submit_urb(wacom->irq, GFP_NOIO);
-	else
-		rv = 0;
+	if (wacom->open && usb_submit_urb(wacom->irq, GFP_NOIO) < 0)
+		rv = -EIO;
 
 	mutex_unlock(&wacom->lock);
 
diff -druN linux-libre-3.1-gnu/drivers/input/tablet/wacom_wac.c linux-libre-3.2-gnu/drivers/input/tablet/wacom_wac.c
--- linux-libre-3.1-gnu/drivers/input/tablet/wacom_wac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/tablet/wacom_wac.c	2012-01-04 18:55:44.000000000 -0500
@@ -874,7 +874,15 @@
 		x = le16_to_cpup((__le16 *)&data[2]);
 		y = le16_to_cpup((__le16 *)&data[4]);
 		p = le16_to_cpup((__le16 *)&data[6]);
-		d = data[8];
+		/*
+		 * Convert distance from out prox to distance from tablet.
+		 * distance will be greater than distance_max once
+		 * touching and applying pressure; do not report negative
+		 * distance.
+		 */
+		if (data[8] <= wacom->features.distance_max)
+			d = wacom->features.distance_max - data[8];
+
 		pen = data[1] & 0x01;
 		btn1 = data[1] & 0x02;
 		btn2 = data[1] & 0x04;
@@ -1030,8 +1038,6 @@
 		features->y_max <<= 5;
 		features->x_fuzz <<= 5;
 		features->y_fuzz <<= 5;
-		features->pressure_max = 256;
-		features->pressure_fuzz = 16;
 		features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES;
 	}
 }
@@ -1241,14 +1247,14 @@
 			input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
 					     0, features->y_max,
 					     features->y_fuzz, 0);
-			input_set_abs_params(input_dev, ABS_MT_PRESSURE,
-					     0, features->pressure_max,
-					     features->pressure_fuzz, 0);
 		} else if (features->device_type == BTN_TOOL_PEN) {
 			__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
 			__set_bit(BTN_TOOL_PEN, input_dev->keybit);
 			__set_bit(BTN_STYLUS, input_dev->keybit);
 			__set_bit(BTN_STYLUS2, input_dev->keybit);
+			input_set_abs_params(input_dev, ABS_DISTANCE, 0,
+					      features->distance_max,
+					      0, 0);
 		}
 		break;
 	}
@@ -1464,42 +1470,45 @@
 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_0xEC =
+	{ "Wacom ISDv4 EC",       WACOM_PKGLEN_GRAPHIRE,  25710, 14500,  255,
+	  0, TABLETPC,    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, 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 };
+	  31, 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 };
+	  31, 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 };
+	  31, 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 };
+	{ "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13700, 1023,
+	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD4 =
 	{ "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
-	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD5 =
-	{ "Wacom Bamboo Pen 6x8",     WACOM_PKGLEN_BBFUN, 21648, 13530, 1023,
-	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+	{ "Wacom Bamboo Pen 6x8",     WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
+	  31, 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 };
+	  31, 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 };
+	  31, 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 };
+	{ "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN,   21648, 13700, 1023,
+	  31, 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 };
+	  31, 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_INTUOS_RES, WACOM_INTUOS_RES };
+	{ "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN,  21648, 13700, 1023,
+	  31, 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, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -1605,6 +1614,7 @@
 	{ USB_DEVICE_WACOM(0xE2) },
 	{ USB_DEVICE_WACOM(0xE3) },
 	{ USB_DEVICE_WACOM(0xE6) },
+	{ USB_DEVICE_WACOM(0xEC) },
 	{ USB_DEVICE_WACOM(0x47) },
 	{ USB_DEVICE_LENOVO(0x6004) },
 	{ }
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/ad7877.c linux-libre-3.2-gnu/drivers/input/touchscreen/ad7877.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/ad7877.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/ad7877.c	2012-01-04 18:55:44.000000000 -0500
@@ -45,6 +45,7 @@
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ad7877.h>
+#include <linux/module.h>
 #include <asm/irq.h>
 
 #define	TS_PEN_UP_TIMEOUT	msecs_to_jiffies(100)
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/ad7879.c linux-libre-3.2-gnu/drivers/input/touchscreen/ad7879.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/ad7879.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/ad7879.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 #include <linux/gpio.h>
 
 #include <linux/spi/ad7879.h>
+#include <linux/module.h>
 #include "ad7879.h"
 
 #define AD7879_REG_ZEROS		0
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/ad7879-i2c.c linux-libre-3.2-gnu/drivers/input/touchscreen/ad7879-i2c.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/ad7879-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/ad7879-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
 
 #define AD7879_DEVID		0x79	/* AD7879-1/AD7889-1 */
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ad7879_i2c_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -36,9 +36,9 @@
 
 	return 0;
 }
+#endif
 
 static SIMPLE_DEV_PM_OPS(ad7879_i2c_pm, ad7879_i2c_suspend, ad7879_i2c_resume);
-#endif
 
 /* All registers are word-sized.
  * AD7879 uses a high-byte first convention.
@@ -119,9 +119,7 @@
 	.driver = {
 		.name	= "ad7879",
 		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
 		.pm	= &ad7879_i2c_pm,
-#endif
 	},
 	.probe		= ad7879_i2c_probe,
 	.remove		= __devexit_p(ad7879_i2c_remove),
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/ad7879-spi.c linux-libre-3.2-gnu/drivers/input/touchscreen/ad7879-spi.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/ad7879-spi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/ad7879-spi.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/input.h>	/* BUS_SPI */
 #include <linux/pm.h>
 #include <linux/spi/spi.h>
+#include <linux/module.h>
 
 #include "ad7879.h"
 
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/ads7846.c linux-libre-3.2-gnu/drivers/input/touchscreen/ads7846.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/ads7846.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/ads7846.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/regulator/consumer.h>
+#include <linux/module.h>
 #include <asm/irq.h>
 
 /*
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/atmel_mxt_ts.c linux-libre-3.2-gnu/drivers/input/touchscreen/atmel_mxt_ts.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/atmel_mxt_ts.c	2012-03-19 22:02:37.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/atmel_mxt_ts.c	2012-03-19 22:05:46.000000000 -0400
@@ -910,12 +910,17 @@
 	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",
+		count += snprintf(buf + count, PAGE_SIZE - count,
+				"Object[%d] (Type %d)\n",
 				i + 1, object->type);
+		if (count >= PAGE_SIZE)
+			return PAGE_SIZE - 1;
 
 		if (!mxt_object_readable(object->type)) {
-			count += sprintf(buf + count, "\n");
+			count += snprintf(buf + count, PAGE_SIZE - count,
+					"\n");
+			if (count >= PAGE_SIZE)
+				return PAGE_SIZE - 1;
 			continue;
 		}
 
@@ -925,11 +930,15 @@
 			if (error)
 				return error;
 
-			count += sprintf(buf + count,
-					"  Byte %d: 0x%x (%d)\n", j, val, val);
+			count += snprintf(buf + count, PAGE_SIZE - count,
+					"\t[%2d]: %02x (%d)\n", j, val, val);
+			if (count >= PAGE_SIZE)
+				return PAGE_SIZE - 1;
 		}
 
-		count += sprintf(buf + count, "\n");
+		count += snprintf(buf + count, PAGE_SIZE - count, "\n");
+		if (count >= PAGE_SIZE)
+			return PAGE_SIZE - 1;
 	}
 
 	return count;
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/atmel_tsadcc.c linux-libre-3.2-gnu/drivers/input/touchscreen/atmel_tsadcc.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/atmel_tsadcc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/atmel_tsadcc.c	2012-01-04 18:55:44.000000000 -0500
@@ -229,7 +229,7 @@
 		goto err_release_mem;
 	}
 
-	err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, IRQF_DISABLED,
+	err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, 0,
 			pdev->dev.driver->name, ts_dev);
 	if (err) {
 		dev_err(&pdev->dev, "failed to allocate irq.\n");
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/bu21013_ts.c linux-libre-3.2-gnu/drivers/input/touchscreen/bu21013_ts.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/bu21013_ts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/bu21013_ts.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/input/bu21013.h>
 #include <linux/slab.h>
 #include <linux/regulator/consumer.h>
+#include <linux/module.h>
 
 #define PEN_DOWN_INTR	0
 #define MAX_FINGERS	2
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/h3600_ts_input.c linux-libre-3.2-gnu/drivers/input/touchscreen/h3600_ts_input.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/h3600_ts_input.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/h3600_ts_input.c	2012-01-04 18:55:44.000000000 -0500
@@ -396,14 +396,14 @@
 	set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE);
 
 	if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler,
-			IRQF_SHARED | IRQF_DISABLED, "h3600_action", ts->dev)) {
+			IRQF_SHARED, "h3600_action", ts->dev)) {
 		printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
 		err = -EBUSY;
 		goto fail1;
 	}
 
 	if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
-			IRQF_SHARED | IRQF_DISABLED, "h3600_suspend", ts->dev)) {
+			IRQF_SHARED, "h3600_suspend", ts->dev)) {
 		printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
 		err = -EBUSY;
 		goto fail2;
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/hp680_ts_input.c linux-libre-3.2-gnu/drivers/input/touchscreen/hp680_ts_input.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/hp680_ts_input.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/hp680_ts_input.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,7 +93,7 @@
 	hp680_ts_dev->phys = "hp680_ts/input0";
 
 	if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt,
-			IRQF_DISABLED, MODNAME, 0) < 0) {
+			0, MODNAME, 0) < 0) {
 		printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n",
 		       HP680_TS_IRQ);
 		err = -EBUSY;
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/jornada720_ts.c linux-libre-3.2-gnu/drivers/input/touchscreen/jornada720_ts.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/jornada720_ts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/jornada720_ts.c	2012-01-04 18:55:44.000000000 -0500
@@ -127,7 +127,7 @@
 
 	error = request_irq(IRQ_GPIO9,
 			jornada720_ts_interrupt,
-			IRQF_DISABLED | IRQF_TRIGGER_RISING,
+			IRQF_TRIGGER_RISING,
 			"HP7XX Touchscreen driver", pdev);
 	if (error) {
 		printk(KERN_INFO "HP7XX TS : Unable to acquire irq!\n");
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/Kconfig linux-libre-3.2-gnu/drivers/input/touchscreen/Kconfig
--- linux-libre-3.1-gnu/drivers/input/touchscreen/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -651,6 +651,18 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called touchit213.
 
+config TOUCHSCREEN_TSC_SERIO
+	tristate "TSC-10/25/40 serial touchscreen support"
+	select SERIO
+	help
+	  Say Y here if you have a TSC-10, 25 or 40 serial touchscreen connected
+	  to your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tsc40.
+
 config TOUCHSCREEN_TSC2005
         tristate "TSC2005 based touchscreens"
         depends on SPI_MASTER && GENERIC_HARDIRQS
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/lpc32xx_ts.c linux-libre-3.2-gnu/drivers/input/touchscreen/lpc32xx_ts.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/lpc32xx_ts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/lpc32xx_ts.c	2012-01-04 18:55:44.000000000 -0500
@@ -276,7 +276,7 @@
 	input_set_drvdata(input, tsc);
 
 	error = request_irq(tsc->irq, lpc32xx_ts_interrupt,
-			    IRQF_DISABLED, pdev->name, tsc);
+			    0, pdev->name, tsc);
 	if (error) {
 		dev_err(&pdev->dev, "failed requesting interrupt\n");
 		goto err_put_clock;
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/Makefile linux-libre-3.2-gnu/drivers/input/touchscreen/Makefile
--- linux-libre-3.1-gnu/drivers/input/touchscreen/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -46,6 +46,7 @@
 obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)	+= touchit213.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)	+= touchright.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)	+= touchwin.o
+obj-$(CONFIG_TOUCHSCREEN_TSC_SERIO)	+= tsc40.o
 obj-$(CONFIG_TOUCHSCREEN_TSC2005)	+= tsc2005.o
 obj-$(CONFIG_TOUCHSCREEN_TSC2007)	+= tsc2007.o
 obj-$(CONFIG_TOUCHSCREEN_UCB1400)	+= ucb1400_ts.o
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/mc13783_ts.c linux-libre-3.2-gnu/drivers/input/touchscreen/mc13783_ts.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/mc13783_ts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/mc13783_ts.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,7 +35,7 @@
 
 struct mc13783_ts_priv {
 	struct input_dev *idev;
-	struct mc13783 *mc13783;
+	struct mc13xxx *mc13xxx;
 	struct delayed_work work;
 	struct workqueue_struct *workq;
 	unsigned int sample[4];
@@ -45,7 +45,7 @@
 {
 	struct mc13783_ts_priv *priv = data;
 
-	mc13783_irq_ack(priv->mc13783, irq);
+	mc13xxx_irq_ack(priv->mc13xxx, irq);
 
 	/*
 	 * Kick off reading coordinates. Note that if work happens already
@@ -121,10 +121,10 @@
 {
 	struct mc13783_ts_priv *priv =
 		container_of(work, struct mc13783_ts_priv, work.work);
-	unsigned int mode = MC13783_ADC_MODE_TS;
+	unsigned int mode = MC13XXX_ADC_MODE_TS;
 	unsigned int channel = 12;
 
-	if (mc13783_adc_do_conversion(priv->mc13783,
+	if (mc13xxx_adc_do_conversion(priv->mc13xxx,
 				mode, channel, priv->sample) == 0)
 		mc13783_ts_report_sample(priv);
 }
@@ -134,21 +134,21 @@
 	struct mc13783_ts_priv *priv = input_get_drvdata(dev);
 	int ret;
 
-	mc13783_lock(priv->mc13783);
+	mc13xxx_lock(priv->mc13xxx);
 
-	mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TS);
+	mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TS);
 
-	ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_TS,
+	ret = mc13xxx_irq_request(priv->mc13xxx, MC13XXX_IRQ_TS,
 		mc13783_ts_handler, MC13783_TS_NAME, priv);
 	if (ret)
 		goto out;
 
-	ret = mc13783_reg_rmw(priv->mc13783, MC13783_ADC0,
-			MC13783_ADC0_TSMOD_MASK, MC13783_ADC0_TSMOD0);
+	ret = mc13xxx_reg_rmw(priv->mc13xxx, MC13XXX_ADC0,
+			MC13XXX_ADC0_TSMOD_MASK, MC13XXX_ADC0_TSMOD0);
 	if (ret)
-		mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv);
+		mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TS, priv);
 out:
-	mc13783_unlock(priv->mc13783);
+	mc13xxx_unlock(priv->mc13xxx);
 	return ret;
 }
 
@@ -156,11 +156,11 @@
 {
 	struct mc13783_ts_priv *priv = input_get_drvdata(dev);
 
-	mc13783_lock(priv->mc13783);
-	mc13783_reg_rmw(priv->mc13783, MC13783_ADC0,
-			MC13783_ADC0_TSMOD_MASK, 0);
-	mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv);
-	mc13783_unlock(priv->mc13783);
+	mc13xxx_lock(priv->mc13xxx);
+	mc13xxx_reg_rmw(priv->mc13xxx, MC13XXX_ADC0,
+			MC13XXX_ADC0_TSMOD_MASK, 0);
+	mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TS, priv);
+	mc13xxx_unlock(priv->mc13xxx);
 
 	cancel_delayed_work_sync(&priv->work);
 }
@@ -177,7 +177,7 @@
 		goto err_free_mem;
 
 	INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
-	priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
+	priv->mc13xxx = dev_get_drvdata(pdev->dev.parent);
 	priv->idev = idev;
 
 	/*
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/penmount.c linux-libre-3.2-gnu/drivers/input/touchscreen/penmount.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/penmount.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/penmount.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,7 @@
  * Penmount serial touchscreen driver
  *
  * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com>
+ * Copyright (c) 2011 John Sung <penmount.touch@gmail.com>
  *
  * Based on ELO driver (drivers/input/touchscreen/elo.c)
  * Copyright (c) 2004 Vojtech Pavlik
@@ -18,12 +19,14 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/input.h>
+#include <linux/input/mt.h>
 #include <linux/serio.h>
 #include <linux/init.h>
 
-#define DRIVER_DESC	"Penmount serial touchscreen driver"
+#define DRIVER_DESC	"PenMount serial touchscreen driver"
 
 MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>");
+MODULE_AUTHOR("John Sung <penmount.touch@gmail.com>");
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
@@ -31,7 +34,19 @@
  * Definitions & global arrays.
  */
 
-#define	PM_MAX_LENGTH	5
+#define	PM_MAX_LENGTH	6
+#define	PM_MAX_MTSLOT	16
+#define	PM_3000_MTSLOT	2
+#define	PM_6250_MTSLOT	12
+
+/*
+ * Multi-touch slot
+ */
+
+struct mt_slot {
+	unsigned short x, y;
+	bool active; /* is the touch valid? */
+};
 
 /*
  * Per-touchscreen data.
@@ -43,25 +58,119 @@
 	int idx;
 	unsigned char data[PM_MAX_LENGTH];
 	char phys[32];
+	unsigned char packetsize;
+	unsigned char maxcontacts;
+	struct mt_slot slots[PM_MAX_MTSLOT];
+	void (*parse_packet)(struct pm *);
 };
 
-static irqreturn_t pm_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags)
+/*
+ * pm_mtevent() sends mt events and also emulates pointer movement
+ */
+
+static void pm_mtevent(struct pm *pm, struct input_dev *input)
+{
+	int i;
+
+	for (i = 0; i < pm->maxcontacts; ++i) {
+		input_mt_slot(input, i);
+		input_mt_report_slot_state(input, MT_TOOL_FINGER,
+				pm->slots[i].active);
+		if (pm->slots[i].active) {
+			input_event(input, EV_ABS, ABS_MT_POSITION_X, pm->slots[i].x);
+			input_event(input, EV_ABS, ABS_MT_POSITION_Y, pm->slots[i].y);
+		}
+	}
+
+	input_mt_report_pointer_emulation(input, true);
+	input_sync(input);
+}
+
+/*
+ * pm_checkpacket() checks if data packet is valid
+ */
+
+static bool pm_checkpacket(unsigned char *packet)
+{
+	int total = 0;
+	int i;
+
+	for (i = 0; i < 5; i++)
+		total += packet[i];
+
+	return packet[5] == (unsigned char)~(total & 0xff);
+}
+
+static void pm_parse_9000(struct pm *pm)
 {
-	struct pm *pm = serio_get_drvdata(serio);
 	struct input_dev *dev = pm->dev;
 
-	pm->data[pm->idx] = data;
+	if ((pm->data[0] & 0x80) && pm->packetsize == ++pm->idx) {
+		input_report_abs(dev, ABS_X, pm->data[1] * 128 + pm->data[2]);
+		input_report_abs(dev, ABS_Y, pm->data[3] * 128 + pm->data[4]);
+		input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40));
+		input_sync(dev);
+		pm->idx = 0;
+	}
+}
 
-	if (pm->data[0] & 0x80) {
-		if (PM_MAX_LENGTH == ++pm->idx) {
-			input_report_abs(dev, ABS_X, pm->data[2] * 128 + pm->data[1]);
-			input_report_abs(dev, ABS_Y, pm->data[4] * 128 + pm->data[3]);
-			input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40));
+static void pm_parse_6000(struct pm *pm)
+{
+	struct input_dev *dev = pm->dev;
+
+	if ((pm->data[0] & 0xbf) == 0x30 && pm->packetsize == ++pm->idx) {
+		if (pm_checkpacket(pm->data)) {
+			input_report_abs(dev, ABS_X,
+					pm->data[2] * 256 + pm->data[1]);
+			input_report_abs(dev, ABS_Y,
+					pm->data[4] * 256 + pm->data[3]);
+			input_report_key(dev, BTN_TOUCH, pm->data[0] & 0x40);
 			input_sync(dev);
-			pm->idx = 0;
 		}
+		pm->idx = 0;
 	}
+}
+
+static void pm_parse_3000(struct pm *pm)
+{
+	struct input_dev *dev = pm->dev;
+
+	if ((pm->data[0] & 0xce) == 0x40 && pm->packetsize == ++pm->idx) {
+		if (pm_checkpacket(pm->data)) {
+			int slotnum = pm->data[0] & 0x0f;
+			pm->slots[slotnum].active = pm->data[0] & 0x30;
+			pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1];
+			pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3];
+			pm_mtevent(pm, dev);
+		}
+		pm->idx = 0;
+	}
+}
+
+static void pm_parse_6250(struct pm *pm)
+{
+	struct input_dev *dev = pm->dev;
+
+	if ((pm->data[0] & 0xb0) == 0x30 && pm->packetsize == ++pm->idx) {
+		if (pm_checkpacket(pm->data)) {
+			int slotnum = pm->data[0] & 0x0f;
+			pm->slots[slotnum].active = pm->data[0] & 0x40;
+			pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1];
+			pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3];
+			pm_mtevent(pm, dev);
+		}
+		pm->idx = 0;
+	}
+}
+
+static irqreturn_t pm_interrupt(struct serio *serio,
+		unsigned char data, unsigned int flags)
+{
+	struct pm *pm = serio_get_drvdata(serio);
+
+	pm->data[pm->idx] = data;
+
+	pm->parse_packet(pm);
 
 	return IRQ_HANDLED;
 }
@@ -74,17 +183,17 @@
 {
 	struct pm *pm = serio_get_drvdata(serio);
 
-	input_get_device(pm->dev);
-	input_unregister_device(pm->dev);
 	serio_close(serio);
-	serio_set_drvdata(serio, NULL);
-	input_put_device(pm->dev);
+
+	input_unregister_device(pm->dev);
 	kfree(pm);
+
+	serio_set_drvdata(serio, NULL);
 }
 
 /*
  * pm_connect() is the routine that is called when someone adds a
- * new serio device that supports Gunze protocol and registers it as
+ * new serio device that supports PenMount protocol and registers it as
  * an input device.
  */
 
@@ -92,6 +201,7 @@
 {
 	struct pm *pm;
 	struct input_dev *input_dev;
+	int max_x, max_y;
 	int err;
 
 	pm = kzalloc(sizeof(struct pm), GFP_KERNEL);
@@ -104,8 +214,9 @@
 	pm->serio = serio;
 	pm->dev = input_dev;
 	snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys);
+	pm->maxcontacts = 1;
 
-	input_dev->name = "Penmount Serial TouchScreen";
+	input_dev->name = "PenMount Serial TouchScreen";
 	input_dev->phys = pm->phys;
 	input_dev->id.bustype = BUS_RS232;
 	input_dev->id.vendor = SERIO_PENMOUNT;
@@ -113,10 +224,52 @@
 	input_dev->id.version = 0x0100;
 	input_dev->dev.parent = &serio->dev;
 
-        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-        input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
-        input_set_abs_params(pm->dev, ABS_X, 0, 0x3ff, 0, 0);
-        input_set_abs_params(pm->dev, ABS_Y, 0, 0x3ff, 0, 0);
+	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+	switch (serio->id.id) {
+	default:
+	case 0:
+		pm->packetsize = 5;
+		pm->parse_packet = pm_parse_9000;
+		input_dev->id.product = 0x9000;
+		max_x = max_y = 0x3ff;
+		break;
+
+	case 1:
+		pm->packetsize = 6;
+		pm->parse_packet = pm_parse_6000;
+		input_dev->id.product = 0x6000;
+		max_x = max_y = 0x3ff;
+		break;
+
+	case 2:
+		pm->packetsize = 6;
+		pm->parse_packet = pm_parse_3000;
+		input_dev->id.product = 0x3000;
+		max_x = max_y = 0x7ff;
+		pm->maxcontacts = PM_3000_MTSLOT;
+		break;
+
+	case 3:
+		pm->packetsize = 6;
+		pm->parse_packet = pm_parse_6250;
+		input_dev->id.product = 0x6250;
+		max_x = max_y = 0x3ff;
+		pm->maxcontacts = PM_6250_MTSLOT;
+		break;
+	}
+
+	input_set_abs_params(pm->dev, ABS_X, 0, max_x, 0, 0);
+	input_set_abs_params(pm->dev, ABS_Y, 0, max_y, 0, 0);
+
+	if (pm->maxcontacts > 1) {
+		input_mt_init_slots(pm->dev, pm->maxcontacts);
+		input_set_abs_params(pm->dev,
+				     ABS_MT_POSITION_X, 0, max_x, 0, 0);
+		input_set_abs_params(pm->dev,
+				     ABS_MT_POSITION_Y, 0, max_y, 0, 0);
+	}
 
 	serio_set_drvdata(serio, pm);
 
@@ -155,7 +308,7 @@
 
 static struct serio_driver pm_drv = {
 	.driver		= {
-		.name	= "penmountlpc",
+		.name	= "serio-penmount",
 	},
 	.description	= DRIVER_DESC,
 	.id_table	= pm_serio_ids,
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/s3c2410_ts.c linux-libre-3.2-gnu/drivers/input/touchscreen/s3c2410_ts.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/s3c2410_ts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/s3c2410_ts.c	2012-01-04 18:55:44.000000000 -0500
@@ -328,7 +328,7 @@
 	ts.shift = info->oversampling_shift;
 	ts.features = platform_get_device_id(pdev)->driver_data;
 
-	ret = request_irq(ts.irq_tc, stylus_irq, IRQF_DISABLED,
+	ret = request_irq(ts.irq_tc, stylus_irq, 0,
 			  "s3c2410_ts_pen", ts.input);
 	if (ret) {
 		dev_err(dev, "cannot get TC interrupt\n");
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/tsc2007.c linux-libre-3.2-gnu/drivers/input/touchscreen/tsc2007.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/tsc2007.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/tsc2007.c	2012-01-04 18:55:44.000000000 -0500
@@ -66,7 +66,6 @@
 struct tsc2007 {
 	struct input_dev	*input;
 	char			phys[32];
-	struct delayed_work	work;
 
 	struct i2c_client	*client;
 
@@ -76,9 +75,11 @@
 	unsigned long		poll_delay;
 	unsigned long		poll_period;
 
-	bool			pendown;
 	int			irq;
 
+	wait_queue_head_t	wait;
+	bool			stopped;
+
 	int			(*get_pendown_state)(void);
 	void			(*clear_penirq)(void);
 };
@@ -141,25 +142,8 @@
 	return rt;
 }
 
-static void tsc2007_send_up_event(struct tsc2007 *tsc)
-{
-	struct input_dev *input = tsc->input;
-
-	dev_dbg(&tsc->client->dev, "UP\n");
-
-	input_report_key(input, BTN_TOUCH, 0);
-	input_report_abs(input, ABS_PRESSURE, 0);
-	input_sync(input);
-}
-
-static void tsc2007_work(struct work_struct *work)
+static bool tsc2007_is_pen_down(struct tsc2007 *ts)
 {
-	struct tsc2007 *ts =
-		container_of(to_delayed_work(work), struct tsc2007, work);
-	bool debounced = false;
-	struct ts_event tc;
-	u32 rt;
-
 	/*
 	 * NOTE: We can't rely on the pressure to determine the pen down
 	 * state, even though this controller has a pressure sensor.
@@ -170,79 +154,82 @@
 	 * The only safe way to check for the pen up condition is in the
 	 * work function by reading the pen signal state (it's a GPIO
 	 * and IRQ). Unfortunately such callback is not always available,
-	 * in that case we have rely on the pressure anyway.
+	 * in that case we assume that the pen is down and expect caller
+	 * to fall back on the pressure reading.
 	 */
-	if (ts->get_pendown_state) {
-		if (unlikely(!ts->get_pendown_state())) {
-			tsc2007_send_up_event(ts);
-			ts->pendown = false;
-			goto out;
-		}
 
-		dev_dbg(&ts->client->dev, "pen is still down\n");
-	}
+	if (!ts->get_pendown_state)
+		return true;
 
-	tsc2007_read_values(ts, &tc);
+	return ts->get_pendown_state();
+}
 
-	rt = tsc2007_calculate_pressure(ts, &tc);
-	if (rt > ts->max_rt) {
-		/*
-		 * Sample found inconsistent by debouncing or pressure is
-		 * beyond the maximum. Don't report it to user space,
-		 * repeat at least once more the measurement.
-		 */
-		dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
-		debounced = true;
-		goto out;
+static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
+{
+	struct tsc2007 *ts = handle;
+	struct input_dev *input = ts->input;
+	struct ts_event tc;
+	u32 rt;
 
-	}
+	while (!ts->stopped && tsc2007_is_pen_down(ts)) {
 
-	if (rt) {
-		struct input_dev *input = ts->input;
+		/* pen is down, continue with the measurement */
+		tsc2007_read_values(ts, &tc);
 
-		if (!ts->pendown) {
-			dev_dbg(&ts->client->dev, "DOWN\n");
+		rt = tsc2007_calculate_pressure(ts, &tc);
 
-			input_report_key(input, BTN_TOUCH, 1);
-			ts->pendown = true;
+		if (rt == 0 && !ts->get_pendown_state) {
+			/*
+			 * If pressure reported is 0 and we don't have
+			 * callback to check pendown state, we have to
+			 * assume that pen was lifted up.
+			 */
+			break;
 		}
 
-		input_report_abs(input, ABS_X, tc.x);
-		input_report_abs(input, ABS_Y, tc.y);
-		input_report_abs(input, ABS_PRESSURE, rt);
+		if (rt <= ts->max_rt) {
+			dev_dbg(&ts->client->dev,
+				"DOWN point(%4d,%4d), pressure (%4u)\n",
+				tc.x, tc.y, rt);
 
-		input_sync(input);
+			input_report_key(input, BTN_TOUCH, 1);
+			input_report_abs(input, ABS_X, tc.x);
+			input_report_abs(input, ABS_Y, tc.y);
+			input_report_abs(input, ABS_PRESSURE, rt);
 
-		dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n",
-			tc.x, tc.y, rt);
+			input_sync(input);
 
-	} else if (!ts->get_pendown_state && ts->pendown) {
-		/*
-		 * We don't have callback to check pendown state, so we
-		 * have to assume that since pressure reported is 0 the
-		 * pen was lifted up.
-		 */
-		tsc2007_send_up_event(ts);
-		ts->pendown = false;
+		} else {
+			/*
+			 * Sample found inconsistent by debouncing or pressure is
+			 * beyond the maximum. Don't report it to user space,
+			 * repeat at least once more the measurement.
+			 */
+			dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
+		}
+
+		wait_event_timeout(ts->wait, ts->stopped,
+				   msecs_to_jiffies(ts->poll_period));
 	}
 
- out:
-	if (ts->pendown || debounced)
-		schedule_delayed_work(&ts->work,
-				      msecs_to_jiffies(ts->poll_period));
-	else
-		enable_irq(ts->irq);
+	dev_dbg(&ts->client->dev, "UP\n");
+
+	input_report_key(input, BTN_TOUCH, 0);
+	input_report_abs(input, ABS_PRESSURE, 0);
+	input_sync(input);
+
+	if (ts->clear_penirq)
+		ts->clear_penirq();
+
+	return IRQ_HANDLED;
 }
 
-static irqreturn_t tsc2007_irq(int irq, void *handle)
+static irqreturn_t tsc2007_hard_irq(int irq, void *handle)
 {
 	struct tsc2007 *ts = handle;
 
-	if (!ts->get_pendown_state || likely(ts->get_pendown_state())) {
-		disable_irq_nosync(ts->irq);
-		schedule_delayed_work(&ts->work,
-				      msecs_to_jiffies(ts->poll_delay));
-	}
+	if (!ts->get_pendown_state || likely(ts->get_pendown_state()))
+		return IRQ_WAKE_THREAD;
 
 	if (ts->clear_penirq)
 		ts->clear_penirq();
@@ -250,17 +237,40 @@
 	return IRQ_HANDLED;
 }
 
-static void tsc2007_free_irq(struct tsc2007 *ts)
+static void tsc2007_stop(struct tsc2007 *ts)
 {
-	free_irq(ts->irq, ts);
-	if (cancel_delayed_work_sync(&ts->work)) {
-		/*
-		 * Work was pending, therefore we need to enable
-		 * IRQ here to balance the disable_irq() done in the
-		 * interrupt handler.
-		 */
-		enable_irq(ts->irq);
+	ts->stopped = true;
+	mb();
+	wake_up(&ts->wait);
+
+	disable_irq(ts->irq);
+}
+
+static int tsc2007_open(struct input_dev *input_dev)
+{
+	struct tsc2007 *ts = input_get_drvdata(input_dev);
+	int err;
+
+	ts->stopped = false;
+	mb();
+
+	enable_irq(ts->irq);
+
+	/* Prepare for touch readings - power down ADC and enable PENIRQ */
+	err = tsc2007_xfer(ts, PWRDOWN);
+	if (err < 0) {
+		tsc2007_stop(ts);
+		return err;
 	}
+
+	return 0;
+}
+
+static void tsc2007_close(struct input_dev *input_dev)
+{
+	struct tsc2007 *ts = input_get_drvdata(input_dev);
+
+	tsc2007_stop(ts);
 }
 
 static int __devinit tsc2007_probe(struct i2c_client *client,
@@ -290,7 +300,7 @@
 	ts->client = client;
 	ts->irq = client->irq;
 	ts->input = input_dev;
-	INIT_DELAYED_WORK(&ts->work, tsc2007_work);
+	init_waitqueue_head(&ts->wait);
 
 	ts->model             = pdata->model;
 	ts->x_plate_ohms      = pdata->x_plate_ohms;
@@ -300,6 +310,12 @@
 	ts->get_pendown_state = pdata->get_pendown_state;
 	ts->clear_penirq      = pdata->clear_penirq;
 
+	if (pdata->x_plate_ohms == 0) {
+		dev_err(&client->dev, "x_plate_ohms is not set up in platform data");
+		err = -EINVAL;
+		goto err_free_mem;
+	}
+
 	snprintf(ts->phys, sizeof(ts->phys),
 		 "%s/input0", dev_name(&client->dev));
 
@@ -307,6 +323,11 @@
 	input_dev->phys = ts->phys;
 	input_dev->id.bustype = BUS_I2C;
 
+	input_dev->open = tsc2007_open;
+	input_dev->close = tsc2007_close;
+
+	input_set_drvdata(input_dev, ts);
+
 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 
@@ -318,17 +339,14 @@
 	if (pdata->init_platform_hw)
 		pdata->init_platform_hw();
 
-	err = request_irq(ts->irq, tsc2007_irq, 0,
-			client->dev.driver->name, ts);
+	err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq,
+				   IRQF_ONESHOT, client->dev.driver->name, ts);
 	if (err < 0) {
 		dev_err(&client->dev, "irq %d busy?\n", ts->irq);
 		goto err_free_mem;
 	}
 
-	/* Prepare for touch readings - power down ADC and enable PENIRQ */
-	err = tsc2007_xfer(ts, PWRDOWN);
-	if (err < 0)
-		goto err_free_irq;
+	tsc2007_stop(ts);
 
 	err = input_register_device(input_dev);
 	if (err)
@@ -339,7 +357,7 @@
 	return 0;
 
  err_free_irq:
-	tsc2007_free_irq(ts);
+	free_irq(ts->irq, ts);
 	if (pdata->exit_platform_hw)
 		pdata->exit_platform_hw();
  err_free_mem:
@@ -353,7 +371,7 @@
 	struct tsc2007	*ts = i2c_get_clientdata(client);
 	struct tsc2007_platform_data *pdata = client->dev.platform_data;
 
-	tsc2007_free_irq(ts);
+	free_irq(ts->irq, ts);
 
 	if (pdata->exit_platform_hw)
 		pdata->exit_platform_hw();
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/tsc40.c linux-libre-3.2-gnu/drivers/input/touchscreen/tsc40.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/tsc40.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/tsc40.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,184 @@
+/*
+ * TSC-40 serial touchscreen driver. It should be compatible with
+ * TSC-10 and 25.
+ *
+ * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ * License: GPLv2 as published by the FSF.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+#define PACKET_LENGTH  5
+struct tsc_ser {
+	struct input_dev *dev;
+	struct serio *serio;
+	u32 idx;
+	unsigned char data[PACKET_LENGTH];
+	char phys[32];
+};
+
+static void tsc_process_data(struct tsc_ser *ptsc)
+{
+	struct input_dev *dev = ptsc->dev;
+	u8 *data = ptsc->data;
+	u32 x;
+	u32 y;
+
+	x = ((data[1] & 0x03) << 8) | data[2];
+	y = ((data[3] & 0x03) << 8) | data[4];
+
+	input_report_abs(dev, ABS_X, x);
+	input_report_abs(dev, ABS_Y, y);
+	input_report_key(dev, BTN_TOUCH, 1);
+
+	input_sync(dev);
+}
+
+static irqreturn_t tsc_interrupt(struct serio *serio,
+		unsigned char data, unsigned int flags)
+{
+	struct tsc_ser *ptsc = serio_get_drvdata(serio);
+	struct input_dev *dev = ptsc->dev;
+
+	ptsc->data[ptsc->idx] = data;
+	switch (ptsc->idx++) {
+	case 0:
+		if (unlikely((data & 0x3e) != 0x10)) {
+			dev_dbg(&serio->dev,
+				"unsynchronized packet start (0x%02x)\n", data);
+			ptsc->idx = 0;
+		} else if (!(data & 0x01)) {
+			input_report_key(dev, BTN_TOUCH, 0);
+			input_sync(dev);
+			ptsc->idx = 0;
+		}
+		break;
+
+	case 1:
+	case 3:
+		if (unlikely(data & 0xfc)) {
+			dev_dbg(&serio->dev,
+				"unsynchronized data 0x%02x at offset %d\n",
+				data, ptsc->idx - 1);
+			ptsc->idx = 0;
+		}
+		break;
+
+	case 4:
+		tsc_process_data(ptsc);
+		ptsc->idx = 0;
+		break;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int tsc_connect(struct serio *serio, struct serio_driver *drv)
+{
+	struct tsc_ser *ptsc;
+	struct input_dev *input_dev;
+	int error;
+
+	ptsc = kzalloc(sizeof(struct tsc_ser), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!ptsc || !input_dev) {
+		error = -ENOMEM;
+		goto fail1;
+	}
+
+	ptsc->serio = serio;
+	ptsc->dev = input_dev;
+	snprintf(ptsc->phys, sizeof(ptsc->phys), "%s/input0", serio->phys);
+
+	input_dev->name = "TSC-10/25/40 Serial TouchScreen";
+	input_dev->phys = ptsc->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = SERIO_TSC40;
+	input_dev->id.product = 40;
+	input_dev->id.version = 0x0001;
+	input_dev->dev.parent = &serio->dev;
+
+	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	__set_bit(BTN_TOUCH, input_dev->keybit);
+	input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0);
+	input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0);
+	input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0);
+
+	serio_set_drvdata(serio, ptsc);
+
+	error = serio_open(serio, drv);
+	if (error)
+		goto fail2;
+
+	error = input_register_device(ptsc->dev);
+	if (error)
+		goto fail3;
+
+	return 0;
+
+fail3:
+	serio_close(serio);
+fail2:
+	serio_set_drvdata(serio, NULL);
+fail1:
+	input_free_device(input_dev);
+	kfree(ptsc);
+	return error;
+}
+
+static void tsc_disconnect(struct serio *serio)
+{
+	struct tsc_ser *ptsc = serio_get_drvdata(serio);
+
+	serio_close(serio);
+
+	input_unregister_device(ptsc->dev);
+	kfree(ptsc);
+
+	serio_set_drvdata(serio, NULL);
+}
+
+static struct serio_device_id tsc_serio_ids[] = {
+	{
+		.type   = SERIO_RS232,
+		.proto  = SERIO_TSC40,
+		.id     = SERIO_ANY,
+		.extra  = SERIO_ANY,
+	},
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(serio, tsc_serio_ids);
+
+#define DRIVER_DESC    "TSC-10/25/40 serial touchscreen driver"
+
+static struct serio_driver tsc_drv = {
+	.driver	= {
+		.name   = "tsc40",
+	},
+	.description    = DRIVER_DESC,
+	.id_table	= tsc_serio_ids,
+	.interrupt      = tsc_interrupt,
+	.connect	= tsc_connect,
+	.disconnect     = tsc_disconnect,
+};
+
+static int __init tsc_ser_init(void)
+{
+	return serio_register_driver(&tsc_drv);
+}
+module_init(tsc_ser_init);
+
+static void __exit tsc_exit(void)
+{
+	serio_unregister_driver(&tsc_drv);
+}
+module_exit(tsc_exit);
+
+MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/w90p910_ts.c linux-libre-3.2-gnu/drivers/input/touchscreen/w90p910_ts.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/w90p910_ts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/w90p910_ts.c	2012-01-04 18:55:44.000000000 -0500
@@ -279,7 +279,7 @@
 
 	w90p910_ts->irq_num = platform_get_irq(pdev, 0);
 	if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt,
-			IRQF_DISABLED, "w90p910ts", w90p910_ts)) {
+			0, "w90p910ts", w90p910_ts)) {
 		err = -EBUSY;
 		goto fail4;
 	}
diff -druN linux-libre-3.1-gnu/drivers/input/touchscreen/wacom_w8001.c linux-libre-3.2-gnu/drivers/input/touchscreen/wacom_w8001.c
--- linux-libre-3.1-gnu/drivers/input/touchscreen/wacom_w8001.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/input/touchscreen/wacom_w8001.c	2012-01-04 18:55:44.000000000 -0500
@@ -367,6 +367,20 @@
 	return rc;
 }
 
+static int w8001_open(struct input_dev *dev)
+{
+	struct w8001 *w8001 = input_get_drvdata(dev);
+
+	return w8001_command(w8001, W8001_CMD_START, false);
+}
+
+static void w8001_close(struct input_dev *dev)
+{
+	struct w8001 *w8001 = input_get_drvdata(dev);
+
+	w8001_command(w8001, W8001_CMD_STOP, false);
+}
+
 static int w8001_setup(struct w8001 *w8001)
 {
 	struct input_dev *dev = w8001->dev;
@@ -476,7 +490,7 @@
 
 	strlcat(w8001->name, " Touchscreen", sizeof(w8001->name));
 
-	return w8001_command(w8001, W8001_CMD_START, false);
+	return 0;
 }
 
 /*
@@ -487,12 +501,12 @@
 {
 	struct w8001 *w8001 = serio_get_drvdata(serio);
 
-	input_get_device(w8001->dev);
-	input_unregister_device(w8001->dev);
 	serio_close(serio);
-	serio_set_drvdata(serio, NULL);
-	input_put_device(w8001->dev);
+
+	input_unregister_device(w8001->dev);
 	kfree(w8001);
+
+	serio_set_drvdata(serio, NULL);
 }
 
 /*
@@ -536,6 +550,11 @@
 	input_dev->id.version = 0x0100;
 	input_dev->dev.parent = &serio->dev;
 
+	input_dev->open = w8001_open;
+	input_dev->close = w8001_close;
+
+	input_set_drvdata(input_dev, w8001);
+
 	err = input_register_device(w8001->dev);
 	if (err)
 		goto fail3;
diff -druN linux-libre-3.1-gnu/drivers/iommu/amd_iommu.c linux-libre-3.2-gnu/drivers/iommu/amd_iommu.c
--- linux-libre-3.1-gnu/drivers/iommu/amd_iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/iommu/amd_iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -1283,7 +1283,7 @@
 		if (!pte || !IOMMU_PTE_PRESENT(*pte))
 			continue;
 
-		dma_ops_reserve_addresses(dma_dom, i << PAGE_SHIFT, 1);
+		dma_ops_reserve_addresses(dma_dom, i >> PAGE_SHIFT, 1);
 	}
 
 	update_domain(&dma_dom->domain);
@@ -2495,7 +2495,7 @@
 
 void __init amd_iommu_init_api(void)
 {
-	register_iommu(&amd_iommu_ops);
+	bus_set_iommu(&pci_bus_type, &amd_iommu_ops);
 }
 
 int __init amd_iommu_init_dma_ops(void)
diff -druN linux-libre-3.1-gnu/drivers/iommu/dmar.c linux-libre-3.2-gnu/drivers/iommu/dmar.c
--- linux-libre-3.1-gnu/drivers/iommu/dmar.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/iommu/dmar.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,7 +46,7 @@
  */
 LIST_HEAD(dmar_drhd_units);
 
-static struct acpi_table_header * __initdata dmar_tbl;
+struct acpi_table_header * __initdata dmar_tbl;
 static acpi_size dmar_tbl_size;
 
 static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
@@ -118,8 +118,8 @@
 	return 0;
 }
 
-static int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
-				       struct pci_dev ***devices, u16 segment)
+int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
+				struct pci_dev ***devices, u16 segment)
 {
 	struct acpi_dmar_device_scope *scope;
 	void * tmp = start;
@@ -217,133 +217,6 @@
 	return ret;
 }
 
-#ifdef CONFIG_DMAR
-LIST_HEAD(dmar_rmrr_units);
-
-static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr)
-{
-	list_add(&rmrr->list, &dmar_rmrr_units);
-}
-
-
-static int __init
-dmar_parse_one_rmrr(struct acpi_dmar_header *header)
-{
-	struct acpi_dmar_reserved_memory *rmrr;
-	struct dmar_rmrr_unit *rmrru;
-
-	rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
-	if (!rmrru)
-		return -ENOMEM;
-
-	rmrru->hdr = header;
-	rmrr = (struct acpi_dmar_reserved_memory *)header;
-	rmrru->base_address = rmrr->base_address;
-	rmrru->end_address = rmrr->end_address;
-
-	dmar_register_rmrr_unit(rmrru);
-	return 0;
-}
-
-static int __init
-rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
-{
-	struct acpi_dmar_reserved_memory *rmrr;
-	int ret;
-
-	rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr;
-	ret = dmar_parse_dev_scope((void *)(rmrr + 1),
-		((void *)rmrr) + rmrr->header.length,
-		&rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
-
-	if (ret || (rmrru->devices_cnt == 0)) {
-		list_del(&rmrru->list);
-		kfree(rmrru);
-	}
-	return ret;
-}
-
-static LIST_HEAD(dmar_atsr_units);
-
-static int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr)
-{
-	struct acpi_dmar_atsr *atsr;
-	struct dmar_atsr_unit *atsru;
-
-	atsr = container_of(hdr, struct acpi_dmar_atsr, header);
-	atsru = kzalloc(sizeof(*atsru), GFP_KERNEL);
-	if (!atsru)
-		return -ENOMEM;
-
-	atsru->hdr = hdr;
-	atsru->include_all = atsr->flags & 0x1;
-
-	list_add(&atsru->list, &dmar_atsr_units);
-
-	return 0;
-}
-
-static int __init atsr_parse_dev(struct dmar_atsr_unit *atsru)
-{
-	int rc;
-	struct acpi_dmar_atsr *atsr;
-
-	if (atsru->include_all)
-		return 0;
-
-	atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
-	rc = dmar_parse_dev_scope((void *)(atsr + 1),
-				(void *)atsr + atsr->header.length,
-				&atsru->devices_cnt, &atsru->devices,
-				atsr->segment);
-	if (rc || !atsru->devices_cnt) {
-		list_del(&atsru->list);
-		kfree(atsru);
-	}
-
-	return rc;
-}
-
-int dmar_find_matched_atsr_unit(struct pci_dev *dev)
-{
-	int i;
-	struct pci_bus *bus;
-	struct acpi_dmar_atsr *atsr;
-	struct dmar_atsr_unit *atsru;
-
-	dev = pci_physfn(dev);
-
-	list_for_each_entry(atsru, &dmar_atsr_units, list) {
-		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
-		if (atsr->segment == pci_domain_nr(dev->bus))
-			goto found;
-	}
-
-	return 0;
-
-found:
-	for (bus = dev->bus; bus; bus = bus->parent) {
-		struct pci_dev *bridge = bus->self;
-
-		if (!bridge || !pci_is_pcie(bridge) ||
-		    bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
-			return 0;
-
-		if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
-			for (i = 0; i < atsru->devices_cnt; i++)
-				if (atsru->devices[i] == bridge)
-					return 1;
-			break;
-		}
-	}
-
-	if (atsru->include_all)
-		return 1;
-
-	return 0;
-}
-#endif
-
 #ifdef CONFIG_ACPI_NUMA
 static int __init
 dmar_parse_one_rhsa(struct acpi_dmar_header *header)
@@ -484,14 +357,10 @@
 			ret = dmar_parse_one_drhd(entry_header);
 			break;
 		case ACPI_DMAR_TYPE_RESERVED_MEMORY:
-#ifdef CONFIG_DMAR
 			ret = dmar_parse_one_rmrr(entry_header);
-#endif
 			break;
 		case ACPI_DMAR_TYPE_ATSR:
-#ifdef CONFIG_DMAR
 			ret = dmar_parse_one_atsr(entry_header);
-#endif
 			break;
 		case ACPI_DMAR_HARDWARE_AFFINITY:
 #ifdef CONFIG_ACPI_NUMA
@@ -557,34 +426,31 @@
 
 int __init dmar_dev_scope_init(void)
 {
+	static int dmar_dev_scope_initialized;
 	struct dmar_drhd_unit *drhd, *drhd_n;
 	int ret = -ENODEV;
 
+	if (dmar_dev_scope_initialized)
+		return dmar_dev_scope_initialized;
+
+	if (list_empty(&dmar_drhd_units))
+		goto fail;
+
 	list_for_each_entry_safe(drhd, drhd_n, &dmar_drhd_units, list) {
 		ret = dmar_parse_dev(drhd);
 		if (ret)
-			return ret;
+			goto fail;
 	}
 
-#ifdef CONFIG_DMAR
-	{
-		struct dmar_rmrr_unit *rmrr, *rmrr_n;
-		struct dmar_atsr_unit *atsr, *atsr_n;
-
-		list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) {
-			ret = rmrr_parse_dev(rmrr);
-			if (ret)
-				return ret;
-		}
+	ret = dmar_parse_rmrr_atsr_dev();
+	if (ret)
+		goto fail;
 
-		list_for_each_entry_safe(atsr, atsr_n, &dmar_atsr_units, list) {
-			ret = atsr_parse_dev(atsr);
-			if (ret)
-				return ret;
-		}
-	}
-#endif
+	dmar_dev_scope_initialized = 1;
+	return 0;
 
+fail:
+	dmar_dev_scope_initialized = ret;
 	return ret;
 }
 
@@ -611,14 +477,6 @@
 		return -ENODEV;
 	}
 
-#ifdef CONFIG_DMAR
-	if (list_empty(&dmar_rmrr_units))
-		printk(KERN_INFO PREFIX "No RMRR found\n");
-
-	if (list_empty(&dmar_atsr_units))
-		printk(KERN_INFO PREFIX "No ATSR found\n");
-#endif
-
 	return 0;
 }
 
@@ -682,9 +540,6 @@
 	return 1;
 
 failed:
-#ifdef CONFIG_DMAR
-	dmar_disabled = 1;
-#endif
 	return 0;
 }
 
@@ -696,22 +551,21 @@
 	if (ret)
 		ret = check_zero_address();
 	{
-#ifdef CONFIG_INTR_REMAP
 		struct acpi_table_dmar *dmar;
 
 		dmar = (struct acpi_table_dmar *) dmar_tbl;
-		if (ret && cpu_has_x2apic && dmar->flags & 0x1)
+
+		if (ret && intr_remapping_enabled && cpu_has_x2apic &&
+		    dmar->flags & 0x1)
 			printk(KERN_INFO
-			       "Queued invalidation will be enabled to support "
-			       "x2apic and Intr-remapping.\n");
-#endif
-#ifdef CONFIG_DMAR
+			       "Queued invalidation will be enabled to support x2apic and Intr-remapping.\n");
+
 		if (ret && !no_iommu && !iommu_detected && !dmar_disabled) {
 			iommu_detected = 1;
 			/* Make sure ACS will be enabled */
 			pci_request_acs();
 		}
-#endif
+
 #ifdef CONFIG_X86
 		if (ret)
 			x86_init.iommu.iommu_init = intel_iommu_init;
@@ -758,7 +612,6 @@
 		goto err_unmap;
 	}
 
-#ifdef CONFIG_DMAR
 	agaw = iommu_calculate_agaw(iommu);
 	if (agaw < 0) {
 		printk(KERN_ERR
@@ -773,7 +626,6 @@
 			iommu->seq_id);
 		goto err_unmap;
 	}
-#endif
 	iommu->agaw = agaw;
 	iommu->msagaw = msagaw;
 
@@ -800,7 +652,7 @@
 		(unsigned long long)iommu->cap,
 		(unsigned long long)iommu->ecap);
 
-	spin_lock_init(&iommu->register_lock);
+	raw_spin_lock_init(&iommu->register_lock);
 
 	drhd->iommu = iommu;
 	return 0;
@@ -817,9 +669,7 @@
 	if (!iommu)
 		return;
 
-#ifdef CONFIG_DMAR
 	free_dmar_iommu(iommu);
-#endif
 
 	if (iommu->reg)
 		iounmap(iommu->reg);
@@ -921,11 +771,11 @@
 restart:
 	rc = 0;
 
-	spin_lock_irqsave(&qi->q_lock, flags);
+	raw_spin_lock_irqsave(&qi->q_lock, flags);
 	while (qi->free_cnt < 3) {
-		spin_unlock_irqrestore(&qi->q_lock, flags);
+		raw_spin_unlock_irqrestore(&qi->q_lock, flags);
 		cpu_relax();
-		spin_lock_irqsave(&qi->q_lock, flags);
+		raw_spin_lock_irqsave(&qi->q_lock, flags);
 	}
 
 	index = qi->free_head;
@@ -965,15 +815,15 @@
 		if (rc)
 			break;
 
-		spin_unlock(&qi->q_lock);
+		raw_spin_unlock(&qi->q_lock);
 		cpu_relax();
-		spin_lock(&qi->q_lock);
+		raw_spin_lock(&qi->q_lock);
 	}
 
 	qi->desc_status[index] = QI_DONE;
 
 	reclaim_free_desc(qi);
-	spin_unlock_irqrestore(&qi->q_lock, flags);
+	raw_spin_unlock_irqrestore(&qi->q_lock, flags);
 
 	if (rc == -EAGAIN)
 		goto restart;
@@ -1062,7 +912,7 @@
 	if (!ecap_qis(iommu->ecap))
 		return;
 
-	spin_lock_irqsave(&iommu->register_lock, flags);
+	raw_spin_lock_irqsave(&iommu->register_lock, flags);
 
 	sts =  dmar_readq(iommu->reg + DMAR_GSTS_REG);
 	if (!(sts & DMA_GSTS_QIES))
@@ -1082,7 +932,7 @@
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl,
 		      !(sts & DMA_GSTS_QIES), sts);
 end:
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
 }
 
 /*
@@ -1097,7 +947,7 @@
 	qi->free_head = qi->free_tail = 0;
 	qi->free_cnt = QI_LENGTH;
 
-	spin_lock_irqsave(&iommu->register_lock, flags);
+	raw_spin_lock_irqsave(&iommu->register_lock, flags);
 
 	/* write zero to the tail reg */
 	writel(0, iommu->reg + DMAR_IQT_REG);
@@ -1110,7 +960,7 @@
 	/* Make sure hardware complete it */
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, (sts & DMA_GSTS_QIES), sts);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
 }
 
 /*
@@ -1159,7 +1009,7 @@
 	qi->free_head = qi->free_tail = 0;
 	qi->free_cnt = QI_LENGTH;
 
-	spin_lock_init(&qi->q_lock);
+	raw_spin_lock_init(&qi->q_lock);
 
 	__dmar_enable_qi(iommu);
 
@@ -1225,11 +1075,11 @@
 	unsigned long flag;
 
 	/* unmask it */
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	writel(0, iommu->reg + DMAR_FECTL_REG);
 	/* Read a reg to force flush the post write */
 	readl(iommu->reg + DMAR_FECTL_REG);
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 void dmar_msi_mask(struct irq_data *data)
@@ -1238,11 +1088,11 @@
 	struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
 
 	/* mask it */
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	writel(DMA_FECTL_IM, iommu->reg + DMAR_FECTL_REG);
 	/* Read a reg to force flush the post write */
 	readl(iommu->reg + DMAR_FECTL_REG);
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 void dmar_msi_write(int irq, struct msi_msg *msg)
@@ -1250,11 +1100,11 @@
 	struct intel_iommu *iommu = irq_get_handler_data(irq);
 	unsigned long flag;
 
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	writel(msg->data, iommu->reg + DMAR_FEDATA_REG);
 	writel(msg->address_lo, iommu->reg + DMAR_FEADDR_REG);
 	writel(msg->address_hi, iommu->reg + DMAR_FEUADDR_REG);
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 void dmar_msi_read(int irq, struct msi_msg *msg)
@@ -1262,11 +1112,11 @@
 	struct intel_iommu *iommu = irq_get_handler_data(irq);
 	unsigned long flag;
 
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	msg->data = readl(iommu->reg + DMAR_FEDATA_REG);
 	msg->address_lo = readl(iommu->reg + DMAR_FEADDR_REG);
 	msg->address_hi = readl(iommu->reg + DMAR_FEUADDR_REG);
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 static int dmar_fault_do_one(struct intel_iommu *iommu, int type,
@@ -1303,7 +1153,7 @@
 	u32 fault_status;
 	unsigned long flag;
 
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	fault_status = readl(iommu->reg + DMAR_FSTS_REG);
 	if (fault_status)
 		printk(KERN_ERR "DRHD: handling fault status reg %x\n",
@@ -1342,7 +1192,7 @@
 		writel(DMA_FRCD_F, iommu->reg + reg +
 			fault_index * PRIMARY_FAULT_REG_LEN + 12);
 
-		spin_unlock_irqrestore(&iommu->register_lock, flag);
+		raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 
 		dmar_fault_do_one(iommu, type, fault_reason,
 				source_id, guest_addr);
@@ -1350,14 +1200,14 @@
 		fault_index++;
 		if (fault_index >= cap_num_fault_regs(iommu->cap))
 			fault_index = 0;
-		spin_lock_irqsave(&iommu->register_lock, flag);
+		raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	}
 clear_rest:
 	/* clear all the other faults */
 	fault_status = readl(iommu->reg + DMAR_FSTS_REG);
 	writel(fault_status, iommu->reg + DMAR_FSTS_REG);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 	return IRQ_HANDLED;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/iommu/intel-iommu.c linux-libre-3.2-gnu/drivers/iommu/intel-iommu.c
--- linux-libre-3.1-gnu/drivers/iommu/intel-iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/iommu/intel-iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/bitmap.h>
 #include <linux/debugfs.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
@@ -398,11 +399,14 @@
 
 static void domain_remove_dev_info(struct dmar_domain *domain);
 
-#ifdef CONFIG_DMAR_DEFAULT_ON
+#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
 int dmar_disabled = 0;
 #else
 int dmar_disabled = 1;
-#endif /*CONFIG_DMAR_DEFAULT_ON*/
+#endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/
+
+int intel_iommu_enabled = 0;
+EXPORT_SYMBOL_GPL(intel_iommu_enabled);
 
 static int dmar_map_gfx = 1;
 static int dmar_forcedac;
@@ -939,7 +943,7 @@
 
 	addr = iommu->root_entry;
 
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	dmar_writeq(iommu->reg + DMAR_RTADDR_REG, virt_to_phys(addr));
 
 	writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
@@ -948,7 +952,7 @@
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
 		      readl, (sts & DMA_GSTS_RTPS), sts);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 static void iommu_flush_write_buffer(struct intel_iommu *iommu)
@@ -959,14 +963,14 @@
 	if (!rwbf_quirk && !cap_rwbf(iommu->cap))
 		return;
 
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
 
 	/* Make sure hardware complete it */
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
 		      readl, (!(val & DMA_GSTS_WBFS)), val);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 /* return value determine if we need a write buffer flush */
@@ -993,14 +997,14 @@
 	}
 	val |= DMA_CCMD_ICC;
 
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
 
 	/* Make sure hardware complete it */
 	IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
 		dmar_readq, (!(val & DMA_CCMD_ICC)), val);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
 /* return value determine if we need a write buffer flush */
@@ -1039,7 +1043,7 @@
 	if (cap_write_drain(iommu->cap))
 		val |= DMA_TLB_WRITE_DRAIN;
 
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	/* Note: Only uses first TLB reg currently */
 	if (val_iva)
 		dmar_writeq(iommu->reg + tlb_offset, val_iva);
@@ -1049,7 +1053,7 @@
 	IOMMU_WAIT_OP(iommu, tlb_offset + 8,
 		dmar_readq, (!(val & DMA_TLB_IVT)), val);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 
 	/* check IOTLB invalidation granularity */
 	if (DMA_TLB_IAIG(val) == 0)
@@ -1165,7 +1169,7 @@
 	u32 pmen;
 	unsigned long flags;
 
-	spin_lock_irqsave(&iommu->register_lock, flags);
+	raw_spin_lock_irqsave(&iommu->register_lock, flags);
 	pmen = readl(iommu->reg + DMAR_PMEN_REG);
 	pmen &= ~DMA_PMEN_EPM;
 	writel(pmen, iommu->reg + DMAR_PMEN_REG);
@@ -1174,7 +1178,7 @@
 	IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG,
 		readl, !(pmen & DMA_PMEN_PRS), pmen);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
 }
 
 static int iommu_enable_translation(struct intel_iommu *iommu)
@@ -1182,7 +1186,7 @@
 	u32 sts;
 	unsigned long flags;
 
-	spin_lock_irqsave(&iommu->register_lock, flags);
+	raw_spin_lock_irqsave(&iommu->register_lock, flags);
 	iommu->gcmd |= DMA_GCMD_TE;
 	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
 
@@ -1190,7 +1194,7 @@
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
 		      readl, (sts & DMA_GSTS_TES), sts);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
 	return 0;
 }
 
@@ -1199,7 +1203,7 @@
 	u32 sts;
 	unsigned long flag;
 
-	spin_lock_irqsave(&iommu->register_lock, flag);
+	raw_spin_lock_irqsave(&iommu->register_lock, flag);
 	iommu->gcmd &= ~DMA_GCMD_TE;
 	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
 
@@ -1207,7 +1211,7 @@
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
 		      readl, (!(sts & DMA_GSTS_TES)), sts);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 	return 0;
 }
 
@@ -2157,7 +2161,7 @@
 		rmrr->end_address);
 }
 
-#ifdef CONFIG_DMAR_FLOPPY_WA
+#ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA
 static inline void iommu_prepare_isa(void)
 {
 	struct pci_dev *pdev;
@@ -2180,7 +2184,7 @@
 {
 	return;
 }
-#endif /* !CONFIG_DMAR_FLPY_WA */
+#endif /* !CONFIG_INTEL_IOMMU_FLPY_WA */
 
 static int md_domain_init(struct dmar_domain *domain, int guest_width);
 
@@ -2491,7 +2495,7 @@
 	if (iommu_pass_through)
 		iommu_identity_mapping |= IDENTMAP_ALL;
 
-#ifdef CONFIG_DMAR_BROKEN_GFX_WA
+#ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA
 	iommu_identity_mapping |= IDENTMAP_GFX;
 #endif
 
@@ -3329,7 +3333,7 @@
 	for_each_active_iommu(iommu, drhd) {
 		iommu_disable_translation(iommu);
 
-		spin_lock_irqsave(&iommu->register_lock, flag);
+		raw_spin_lock_irqsave(&iommu->register_lock, flag);
 
 		iommu->iommu_state[SR_DMAR_FECTL_REG] =
 			readl(iommu->reg + DMAR_FECTL_REG);
@@ -3340,7 +3344,7 @@
 		iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
 			readl(iommu->reg + DMAR_FEUADDR_REG);
 
-		spin_unlock_irqrestore(&iommu->register_lock, flag);
+		raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 	}
 	return 0;
 
@@ -3367,7 +3371,7 @@
 
 	for_each_active_iommu(iommu, drhd) {
 
-		spin_lock_irqsave(&iommu->register_lock, flag);
+		raw_spin_lock_irqsave(&iommu->register_lock, flag);
 
 		writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
 			iommu->reg + DMAR_FECTL_REG);
@@ -3378,7 +3382,7 @@
 		writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
 			iommu->reg + DMAR_FEUADDR_REG);
 
-		spin_unlock_irqrestore(&iommu->register_lock, flag);
+		raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
 	}
 
 	for_each_active_iommu(iommu, drhd)
@@ -3399,6 +3403,151 @@
 static inline void init_iommu_pm_ops(void) {}
 #endif	/* CONFIG_PM */
 
+LIST_HEAD(dmar_rmrr_units);
+
+static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr)
+{
+	list_add(&rmrr->list, &dmar_rmrr_units);
+}
+
+
+int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header)
+{
+	struct acpi_dmar_reserved_memory *rmrr;
+	struct dmar_rmrr_unit *rmrru;
+
+	rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
+	if (!rmrru)
+		return -ENOMEM;
+
+	rmrru->hdr = header;
+	rmrr = (struct acpi_dmar_reserved_memory *)header;
+	rmrru->base_address = rmrr->base_address;
+	rmrru->end_address = rmrr->end_address;
+
+	dmar_register_rmrr_unit(rmrru);
+	return 0;
+}
+
+static int __init
+rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
+{
+	struct acpi_dmar_reserved_memory *rmrr;
+	int ret;
+
+	rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr;
+	ret = dmar_parse_dev_scope((void *)(rmrr + 1),
+		((void *)rmrr) + rmrr->header.length,
+		&rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
+
+	if (ret || (rmrru->devices_cnt == 0)) {
+		list_del(&rmrru->list);
+		kfree(rmrru);
+	}
+	return ret;
+}
+
+static LIST_HEAD(dmar_atsr_units);
+
+int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr)
+{
+	struct acpi_dmar_atsr *atsr;
+	struct dmar_atsr_unit *atsru;
+
+	atsr = container_of(hdr, struct acpi_dmar_atsr, header);
+	atsru = kzalloc(sizeof(*atsru), GFP_KERNEL);
+	if (!atsru)
+		return -ENOMEM;
+
+	atsru->hdr = hdr;
+	atsru->include_all = atsr->flags & 0x1;
+
+	list_add(&atsru->list, &dmar_atsr_units);
+
+	return 0;
+}
+
+static int __init atsr_parse_dev(struct dmar_atsr_unit *atsru)
+{
+	int rc;
+	struct acpi_dmar_atsr *atsr;
+
+	if (atsru->include_all)
+		return 0;
+
+	atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
+	rc = dmar_parse_dev_scope((void *)(atsr + 1),
+				(void *)atsr + atsr->header.length,
+				&atsru->devices_cnt, &atsru->devices,
+				atsr->segment);
+	if (rc || !atsru->devices_cnt) {
+		list_del(&atsru->list);
+		kfree(atsru);
+	}
+
+	return rc;
+}
+
+int dmar_find_matched_atsr_unit(struct pci_dev *dev)
+{
+	int i;
+	struct pci_bus *bus;
+	struct acpi_dmar_atsr *atsr;
+	struct dmar_atsr_unit *atsru;
+
+	dev = pci_physfn(dev);
+
+	list_for_each_entry(atsru, &dmar_atsr_units, list) {
+		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
+		if (atsr->segment == pci_domain_nr(dev->bus))
+			goto found;
+	}
+
+	return 0;
+
+found:
+	for (bus = dev->bus; bus; bus = bus->parent) {
+		struct pci_dev *bridge = bus->self;
+
+		if (!bridge || !pci_is_pcie(bridge) ||
+		    bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
+			return 0;
+
+		if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
+			for (i = 0; i < atsru->devices_cnt; i++)
+				if (atsru->devices[i] == bridge)
+					return 1;
+			break;
+		}
+	}
+
+	if (atsru->include_all)
+		return 1;
+
+	return 0;
+}
+
+int __init dmar_parse_rmrr_atsr_dev(void)
+{
+	struct dmar_rmrr_unit *rmrr, *rmrr_n;
+	struct dmar_atsr_unit *atsr, *atsr_n;
+	int ret = 0;
+
+	list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) {
+		ret = rmrr_parse_dev(rmrr);
+		if (ret)
+			return ret;
+	}
+
+	list_for_each_entry_safe(atsr, atsr_n, &dmar_atsr_units, list) {
+		ret = atsr_parse_dev(atsr);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
 /*
  * Here we only respond to action of unbound device from driver.
  *
@@ -3448,16 +3597,12 @@
 		return 	-ENODEV;
 	}
 
-	if (dmar_dev_scope_init()) {
+	if (dmar_dev_scope_init() < 0) {
 		if (force_on)
 			panic("tboot: Failed to initialize DMAR device scope\n");
 		return 	-ENODEV;
 	}
 
-	/*
-	 * Check the need for DMA-remapping initialization now.
-	 * Above initialization will also be used by Interrupt-remapping.
-	 */
 	if (no_iommu || dmar_disabled)
 		return -ENODEV;
 
@@ -3467,6 +3612,12 @@
 		return 	-ENODEV;
 	}
 
+	if (list_empty(&dmar_rmrr_units))
+		printk(KERN_INFO "DMAR: No RMRR found\n");
+
+	if (list_empty(&dmar_atsr_units))
+		printk(KERN_INFO "DMAR: No ATSR found\n");
+
 	if (dmar_init_reserved_ranges()) {
 		if (force_on)
 			panic("tboot: Failed to reserve iommu ranges\n");
@@ -3495,10 +3646,12 @@
 
 	init_iommu_pm_ops();
 
-	register_iommu(&intel_iommu_ops);
+	bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
 
 	bus_register_notifier(&pci_bus_type, &device_nb);
 
+	intel_iommu_enabled = 1;
+
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/iommu/intr_remapping.c linux-libre-3.2-gnu/drivers/iommu/intr_remapping.c
--- linux-libre-3.1-gnu/drivers/iommu/intr_remapping.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/iommu/intr_remapping.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 
 static int disable_intremap;
 static int disable_sourceid_checking;
+static int no_x2apic_optout;
 
 static __init int setup_nointremap(char *str)
 {
@@ -34,18 +35,26 @@
 	if (!str)
 		return -EINVAL;
 
-	if (!strncmp(str, "on", 2))
-		disable_intremap = 0;
-	else if (!strncmp(str, "off", 3))
-		disable_intremap = 1;
-	else if (!strncmp(str, "nosid", 5))
-		disable_sourceid_checking = 1;
+	while (*str) {
+		if (!strncmp(str, "on", 2))
+			disable_intremap = 0;
+		else if (!strncmp(str, "off", 3))
+			disable_intremap = 1;
+		else if (!strncmp(str, "nosid", 5))
+			disable_sourceid_checking = 1;
+		else if (!strncmp(str, "no_x2apic_optout", 16))
+			no_x2apic_optout = 1;
+
+		str += strcspn(str, ",");
+		while (*str == ',')
+			str++;
+	}
 
 	return 0;
 }
 early_param("intremap", setup_intremap);
 
-static DEFINE_SPINLOCK(irq_2_ir_lock);
+static DEFINE_RAW_SPINLOCK(irq_2_ir_lock);
 
 static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
 {
@@ -62,12 +71,12 @@
 	if (!entry || !irq_iommu)
 		return -1;
 
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
+	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
 
 	index = irq_iommu->irte_index + irq_iommu->sub_handle;
 	*entry = *(irq_iommu->iommu->ir_table->base + index);
 
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+	raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 	return 0;
 }
 
@@ -101,7 +110,7 @@
 		return -1;
 	}
 
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
+	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
 	do {
 		for (i = index; i < index + count; i++)
 			if  (table->base[i].present)
@@ -113,7 +122,7 @@
 		index = (index + count) % INTR_REMAP_TABLE_ENTRIES;
 
 		if (index == start_index) {
-			spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+			raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 			printk(KERN_ERR "can't allocate an IRTE\n");
 			return -1;
 		}
@@ -127,7 +136,7 @@
 	irq_iommu->sub_handle = 0;
 	irq_iommu->irte_mask = mask;
 
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+	raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 
 	return index;
 }
@@ -152,10 +161,10 @@
 	if (!irq_iommu)
 		return -1;
 
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
+	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
 	*sub_handle = irq_iommu->sub_handle;
 	index = irq_iommu->irte_index;
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+	raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 	return index;
 }
 
@@ -167,14 +176,14 @@
 	if (!irq_iommu)
 		return -1;
 
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
+	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
 
 	irq_iommu->iommu = iommu;
 	irq_iommu->irte_index = index;
 	irq_iommu->sub_handle = subhandle;
 	irq_iommu->irte_mask = 0;
 
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+	raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 
 	return 0;
 }
@@ -190,7 +199,7 @@
 	if (!irq_iommu)
 		return -1;
 
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
+	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
 
 	iommu = irq_iommu->iommu;
 
@@ -202,7 +211,7 @@
 	__iommu_flush_cache(iommu, irte, sizeof(*irte));
 
 	rc = qi_flush_iec(iommu, index, 0);
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+	raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 
 	return rc;
 }
@@ -270,7 +279,7 @@
 	if (!irq_iommu)
 		return -1;
 
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
+	raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
 
 	rc = clear_entries(irq_iommu);
 
@@ -279,7 +288,7 @@
 	irq_iommu->sub_handle = 0;
 	irq_iommu->irte_mask = 0;
 
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+	raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 
 	return rc;
 }
@@ -409,7 +418,7 @@
 
 	addr = virt_to_phys((void *)iommu->ir_table->base);
 
-	spin_lock_irqsave(&iommu->register_lock, flags);
+	raw_spin_lock_irqsave(&iommu->register_lock, flags);
 
 	dmar_writeq(iommu->reg + DMAR_IRTA_REG,
 		    (addr) | IR_X2APIC_MODE(mode) | INTR_REMAP_TABLE_REG_SIZE);
@@ -420,7 +429,7 @@
 
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
 		      readl, (sts & DMA_GSTS_IRTPS), sts);
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
 
 	/*
 	 * global invalidation of interrupt entry cache before enabling
@@ -428,7 +437,7 @@
 	 */
 	qi_global_iec(iommu);
 
-	spin_lock_irqsave(&iommu->register_lock, flags);
+	raw_spin_lock_irqsave(&iommu->register_lock, flags);
 
 	/* Enable interrupt-remapping */
 	iommu->gcmd |= DMA_GCMD_IRE;
@@ -437,7 +446,7 @@
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
 		      readl, (sts & DMA_GSTS_IRES), sts);
 
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
 }
 
 
@@ -485,7 +494,7 @@
 	 */
 	qi_global_iec(iommu);
 
-	spin_lock_irqsave(&iommu->register_lock, flags);
+	raw_spin_lock_irqsave(&iommu->register_lock, flags);
 
 	sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
 	if (!(sts & DMA_GSTS_IRES))
@@ -498,7 +507,16 @@
 		      readl, !(sts & DMA_GSTS_IRES), sts);
 
 end:
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
+	raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
+}
+
+static int __init dmar_x2apic_optout(void)
+{
+	struct acpi_table_dmar *dmar;
+	dmar = (struct acpi_table_dmar *)dmar_tbl;
+	if (!dmar || no_x2apic_optout)
+		return 0;
+	return dmar->flags & DMAR_X2APIC_OPT_OUT;
 }
 
 int __init intr_remapping_supported(void)
@@ -521,16 +539,25 @@
 	return 1;
 }
 
-int __init enable_intr_remapping(int eim)
+int __init enable_intr_remapping(void)
 {
 	struct dmar_drhd_unit *drhd;
 	int setup = 0;
+	int eim = 0;
 
 	if (parse_ioapics_under_ir() != 1) {
 		printk(KERN_INFO "Not enable interrupt remapping\n");
 		return -1;
 	}
 
+	if (x2apic_supported()) {
+		eim = !dmar_x2apic_optout();
+		WARN(!eim, KERN_WARNING
+			   "Your BIOS is broken and requested that x2apic be disabled\n"
+			   "This will leave your machine vulnerable to irq-injection attacks\n"
+			   "Use 'intremap=no_x2apic_optout' to override BIOS request\n");
+	}
+
 	for_each_drhd_unit(drhd) {
 		struct intel_iommu *iommu = drhd->iommu;
 
@@ -606,8 +633,9 @@
 		goto error;
 
 	intr_remapping_enabled = 1;
+	pr_info("Enabled IRQ remapping in %s mode\n", eim ? "x2apic" : "xapic");
 
-	return 0;
+	return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE;
 
 error:
 	/*
@@ -745,6 +773,15 @@
 	return ir_supported;
 }
 
+int __init ir_dev_scope_init(void)
+{
+	if (!intr_remapping_enabled)
+		return 0;
+
+	return dmar_dev_scope_init();
+}
+rootfs_initcall(ir_dev_scope_init);
+
 void disable_intr_remapping(void)
 {
 	struct dmar_drhd_unit *drhd;
diff -druN linux-libre-3.1-gnu/drivers/iommu/iommu.c linux-libre-3.2-gnu/drivers/iommu/iommu.c
--- linux-libre-3.1-gnu/drivers/iommu/iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/iommu/iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#include <linux/device.h>
+#include <linux/kernel.h>
 #include <linux/bug.h>
 #include <linux/types.h>
 #include <linux/module.h>
@@ -23,32 +25,78 @@
 #include <linux/errno.h>
 #include <linux/iommu.h>
 
-static struct iommu_ops *iommu_ops;
+static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops)
+{
+}
 
-void register_iommu(struct iommu_ops *ops)
+/**
+ * bus_set_iommu - set iommu-callbacks for the bus
+ * @bus: bus.
+ * @ops: the callbacks provided by the iommu-driver
+ *
+ * This function is called by an iommu driver to set the iommu methods
+ * used for a particular bus. Drivers for devices on that bus can use
+ * the iommu-api after these ops are registered.
+ * This special function is needed because IOMMUs are usually devices on
+ * the bus itself, so the iommu drivers are not initialized when the bus
+ * is set up. With this function the iommu-driver can set the iommu-ops
+ * afterwards.
+ */
+int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops)
 {
-	if (iommu_ops)
-		BUG();
+	if (bus->iommu_ops != NULL)
+		return -EBUSY;
 
-	iommu_ops = ops;
+	bus->iommu_ops = ops;
+
+	/* Do IOMMU specific setup for this bus-type */
+	iommu_bus_init(bus, ops);
+
+	return 0;
 }
+EXPORT_SYMBOL_GPL(bus_set_iommu);
 
-bool iommu_found(void)
+bool iommu_present(struct bus_type *bus)
 {
-	return iommu_ops != NULL;
+	return bus->iommu_ops != NULL;
 }
-EXPORT_SYMBOL_GPL(iommu_found);
+EXPORT_SYMBOL_GPL(iommu_present);
 
-struct iommu_domain *iommu_domain_alloc(void)
+/**
+ * iommu_set_fault_handler() - set a fault handler for an iommu domain
+ * @domain: iommu domain
+ * @handler: fault handler
+ *
+ * This function should be used by IOMMU users which want to be notified
+ * whenever an IOMMU fault happens.
+ *
+ * The fault handler itself should return 0 on success, and an appropriate
+ * error code otherwise.
+ */
+void iommu_set_fault_handler(struct iommu_domain *domain,
+					iommu_fault_handler_t handler)
+{
+	BUG_ON(!domain);
+
+	domain->handler = handler;
+}
+EXPORT_SYMBOL_GPL(iommu_set_fault_handler);
+
+struct iommu_domain *iommu_domain_alloc(struct bus_type *bus)
 {
 	struct iommu_domain *domain;
 	int ret;
 
-	domain = kmalloc(sizeof(*domain), GFP_KERNEL);
+	if (bus == NULL || bus->iommu_ops == NULL)
+		return NULL;
+
+	domain = kzalloc(sizeof(*domain), GFP_KERNEL);
 	if (!domain)
 		return NULL;
 
-	ret = iommu_ops->domain_init(domain);
+	domain->ops = bus->iommu_ops;
+
+	ret = domain->ops->domain_init(domain);
 	if (ret)
 		goto out_free;
 
@@ -63,62 +111,78 @@
 
 void iommu_domain_free(struct iommu_domain *domain)
 {
-	iommu_ops->domain_destroy(domain);
+	if (likely(domain->ops->domain_destroy != NULL))
+		domain->ops->domain_destroy(domain);
+
 	kfree(domain);
 }
 EXPORT_SYMBOL_GPL(iommu_domain_free);
 
 int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
 {
-	return iommu_ops->attach_dev(domain, dev);
+	if (unlikely(domain->ops->attach_dev == NULL))
+		return -ENODEV;
+
+	return domain->ops->attach_dev(domain, dev);
 }
 EXPORT_SYMBOL_GPL(iommu_attach_device);
 
 void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
 {
-	iommu_ops->detach_dev(domain, dev);
+	if (unlikely(domain->ops->detach_dev == NULL))
+		return;
+
+	domain->ops->detach_dev(domain, dev);
 }
 EXPORT_SYMBOL_GPL(iommu_detach_device);
 
 phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
 			       unsigned long iova)
 {
-	return iommu_ops->iova_to_phys(domain, iova);
+	if (unlikely(domain->ops->iova_to_phys == NULL))
+		return 0;
+
+	return domain->ops->iova_to_phys(domain, iova);
 }
 EXPORT_SYMBOL_GPL(iommu_iova_to_phys);
 
 int iommu_domain_has_cap(struct iommu_domain *domain,
 			 unsigned long cap)
 {
-	return iommu_ops->domain_has_cap(domain, cap);
+	if (unlikely(domain->ops->domain_has_cap == NULL))
+		return 0;
+
+	return domain->ops->domain_has_cap(domain, cap);
 }
 EXPORT_SYMBOL_GPL(iommu_domain_has_cap);
 
 int iommu_map(struct iommu_domain *domain, unsigned long iova,
 	      phys_addr_t paddr, int gfp_order, int prot)
 {
-	unsigned long invalid_mask;
 	size_t size;
 
-	size         = 0x1000UL << gfp_order;
-	invalid_mask = size - 1;
+	if (unlikely(domain->ops->map == NULL))
+		return -ENODEV;
 
-	BUG_ON((iova | paddr) & invalid_mask);
+	size         = PAGE_SIZE << gfp_order;
 
-	return iommu_ops->map(domain, iova, paddr, gfp_order, prot);
+	BUG_ON(!IS_ALIGNED(iova | paddr, size));
+
+	return domain->ops->map(domain, iova, paddr, gfp_order, prot);
 }
 EXPORT_SYMBOL_GPL(iommu_map);
 
 int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order)
 {
-	unsigned long invalid_mask;
 	size_t size;
 
-	size         = 0x1000UL << gfp_order;
-	invalid_mask = size - 1;
+	if (unlikely(domain->ops->unmap == NULL))
+		return -ENODEV;
 
-	BUG_ON(iova & invalid_mask);
+	size         = PAGE_SIZE << gfp_order;
 
-	return iommu_ops->unmap(domain, iova, gfp_order);
+	BUG_ON(!IS_ALIGNED(iova, size));
+
+	return domain->ops->unmap(domain, iova, gfp_order);
 }
 EXPORT_SYMBOL_GPL(iommu_unmap);
diff -druN linux-libre-3.1-gnu/drivers/iommu/Kconfig linux-libre-3.2-gnu/drivers/iommu/Kconfig
--- linux-libre-3.1-gnu/drivers/iommu/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/iommu/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -59,10 +59,14 @@
 	  If unsure, say N.
 
 # Intel IOMMU support
-config DMAR
-	bool "Support for DMA Remapping Devices"
+config DMAR_TABLE
+	bool
+
+config INTEL_IOMMU
+	bool "Support for Intel IOMMU using DMA Remapping Devices"
 	depends on PCI_MSI && ACPI && (X86 || IA64_GENERIC)
 	select IOMMU_API
+	select DMAR_TABLE
 	help
 	  DMA remapping (DMAR) devices support enables independent address
 	  translations for Direct Memory Access (DMA) from devices.
@@ -70,18 +74,18 @@
 	  and include PCI device scope covered by these DMA
 	  remapping devices.
 
-config DMAR_DEFAULT_ON
+config INTEL_IOMMU_DEFAULT_ON
 	def_bool y
-	prompt "Enable DMA Remapping Devices by default"
-	depends on DMAR
+	prompt "Enable Intel DMA Remapping Devices by default"
+	depends on INTEL_IOMMU
 	help
 	  Selecting this option will enable a DMAR device at boot time if
 	  one is found. If this option is not selected, DMAR support can
 	  be enabled by passing intel_iommu=on to the kernel.
 
-config DMAR_BROKEN_GFX_WA
+config INTEL_IOMMU_BROKEN_GFX_WA
 	bool "Workaround broken graphics drivers (going away soon)"
-	depends on DMAR && BROKEN && X86
+	depends on INTEL_IOMMU && BROKEN && X86
 	---help---
 	  Current Graphics drivers tend to use physical address
 	  for DMA and avoid using DMA APIs. Setting this config
@@ -90,21 +94,41 @@
 	  to use physical addresses for DMA, at least until this
 	  option is removed in the 2.6.32 kernel.
 
-config DMAR_FLOPPY_WA
+config INTEL_IOMMU_FLOPPY_WA
 	def_bool y
-	depends on DMAR && X86
+	depends on INTEL_IOMMU && X86
 	---help---
 	  Floppy disk drivers are known to bypass DMA API calls
 	  thereby failing to work when IOMMU is enabled. This
 	  workaround will setup a 1:1 mapping for the first
 	  16MiB to make floppy (an ISA device) work.
 
-config INTR_REMAP
+config IRQ_REMAP
 	bool "Support for Interrupt Remapping (EXPERIMENTAL)"
 	depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL
+	select DMAR_TABLE
 	---help---
 	  Supports Interrupt remapping for IO-APIC and MSI devices.
 	  To use x2apic mode in the CPU's which support x2APIC enhancements or
 	  to support platforms with CPU's having > 8 bit APIC ID, say Y.
 
+# OMAP IOMMU support
+config OMAP_IOMMU
+	bool "OMAP IOMMU Support"
+	depends on ARCH_OMAP
+	select IOMMU_API
+
+config OMAP_IOVMM
+	tristate "OMAP IO Virtual Memory Manager Support"
+	depends on OMAP_IOMMU
+
+config OMAP_IOMMU_DEBUG
+       tristate "Export OMAP IOMMU/IOVMM internals in DebugFS"
+       depends on OMAP_IOVMM && DEBUG_FS
+       help
+         Select this to see extensive information about
+         the internal state of OMAP IOMMU/IOVMM in debugfs.
+
+         Say N unless you know you need this.
+
 endif # IOMMU_SUPPORT
diff -druN linux-libre-3.1-gnu/drivers/iommu/Makefile linux-libre-3.2-gnu/drivers/iommu/Makefile
--- linux-libre-3.1-gnu/drivers/iommu/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/iommu/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,9 @@
 obj-$(CONFIG_IOMMU_API) += iommu.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
-obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o
-obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o
+obj-$(CONFIG_DMAR_TABLE) += dmar.o
+obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o
+obj-$(CONFIG_IRQ_REMAP) += intr_remapping.o
+obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
+obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o
+obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
diff -druN linux-libre-3.1-gnu/drivers/iommu/msm_iommu.c linux-libre-3.2-gnu/drivers/iommu/msm_iommu.c
--- linux-libre-3.1-gnu/drivers/iommu/msm_iommu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/iommu/msm_iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -543,6 +543,13 @@
 	}
 
 	ret = __flush_iotlb(domain);
+
+	/*
+	 * the IOMMU API requires us to return the order of the unmapped
+	 * page (on success).
+	 */
+	if (!ret)
+		ret = order;
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 	return ret;
@@ -721,7 +728,7 @@
 static int __init msm_iommu_init(void)
 {
 	setup_iommu_tex_classes();
-	register_iommu(&msm_iommu_ops);
+	bus_set_iommu(&platform_bus_type, &msm_iommu_ops);
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/iommu/omap-iommu.c linux-libre-3.2-gnu/drivers/iommu/omap-iommu.c
--- linux-libre-3.1-gnu/drivers/iommu/omap-iommu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/iommu/omap-iommu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1245 @@
+/*
+ * omap iommu: tlb and pagetable primitives
+ *
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>,
+ *		Paul Mundt and Toshihiro Kobayashi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/iommu.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
+#include <asm/cacheflush.h>
+
+#include <plat/iommu.h>
+
+#include <plat/iopgtable.h>
+
+#define for_each_iotlb_cr(obj, n, __i, cr)				\
+	for (__i = 0;							\
+	     (__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true);	\
+	     __i++)
+
+/**
+ * struct omap_iommu_domain - omap iommu domain
+ * @pgtable:	the page table
+ * @iommu_dev:	an omap iommu device attached to this domain. only a single
+ *		iommu device can be attached for now.
+ * @lock:	domain lock, should be taken when attaching/detaching
+ */
+struct omap_iommu_domain {
+	u32 *pgtable;
+	struct omap_iommu *iommu_dev;
+	spinlock_t lock;
+};
+
+/* accommodate the difference between omap1 and omap2/3 */
+static const struct iommu_functions *arch_iommu;
+
+static struct platform_driver omap_iommu_driver;
+static struct kmem_cache *iopte_cachep;
+
+/**
+ * omap_install_iommu_arch - Install archtecure specific iommu functions
+ * @ops:	a pointer to architecture specific iommu functions
+ *
+ * There are several kind of iommu algorithm(tlb, pagetable) among
+ * omap series. This interface installs such an iommu algorighm.
+ **/
+int omap_install_iommu_arch(const struct iommu_functions *ops)
+{
+	if (arch_iommu)
+		return -EBUSY;
+
+	arch_iommu = ops;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_install_iommu_arch);
+
+/**
+ * omap_uninstall_iommu_arch - Uninstall archtecure specific iommu functions
+ * @ops:	a pointer to architecture specific iommu functions
+ *
+ * This interface uninstalls the iommu algorighm installed previously.
+ **/
+void omap_uninstall_iommu_arch(const struct iommu_functions *ops)
+{
+	if (arch_iommu != ops)
+		pr_err("%s: not your arch\n", __func__);
+
+	arch_iommu = NULL;
+}
+EXPORT_SYMBOL_GPL(omap_uninstall_iommu_arch);
+
+/**
+ * omap_iommu_save_ctx - Save registers for pm off-mode support
+ * @obj:	target iommu
+ **/
+void omap_iommu_save_ctx(struct omap_iommu *obj)
+{
+	arch_iommu->save_ctx(obj);
+}
+EXPORT_SYMBOL_GPL(omap_iommu_save_ctx);
+
+/**
+ * omap_iommu_restore_ctx - Restore registers for pm off-mode support
+ * @obj:	target iommu
+ **/
+void omap_iommu_restore_ctx(struct omap_iommu *obj)
+{
+	arch_iommu->restore_ctx(obj);
+}
+EXPORT_SYMBOL_GPL(omap_iommu_restore_ctx);
+
+/**
+ * omap_iommu_arch_version - Return running iommu arch version
+ **/
+u32 omap_iommu_arch_version(void)
+{
+	return arch_iommu->version;
+}
+EXPORT_SYMBOL_GPL(omap_iommu_arch_version);
+
+static int iommu_enable(struct omap_iommu *obj)
+{
+	int err;
+
+	if (!obj)
+		return -EINVAL;
+
+	if (!arch_iommu)
+		return -ENODEV;
+
+	clk_enable(obj->clk);
+
+	err = arch_iommu->enable(obj);
+
+	clk_disable(obj->clk);
+	return err;
+}
+
+static void iommu_disable(struct omap_iommu *obj)
+{
+	if (!obj)
+		return;
+
+	clk_enable(obj->clk);
+
+	arch_iommu->disable(obj);
+
+	clk_disable(obj->clk);
+}
+
+/*
+ *	TLB operations
+ */
+void omap_iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
+{
+	BUG_ON(!cr || !e);
+
+	arch_iommu->cr_to_e(cr, e);
+}
+EXPORT_SYMBOL_GPL(omap_iotlb_cr_to_e);
+
+static inline int iotlb_cr_valid(struct cr_regs *cr)
+{
+	if (!cr)
+		return -EINVAL;
+
+	return arch_iommu->cr_valid(cr);
+}
+
+static inline struct cr_regs *iotlb_alloc_cr(struct omap_iommu *obj,
+					     struct iotlb_entry *e)
+{
+	if (!e)
+		return NULL;
+
+	return arch_iommu->alloc_cr(obj, e);
+}
+
+static u32 iotlb_cr_to_virt(struct cr_regs *cr)
+{
+	return arch_iommu->cr_to_virt(cr);
+}
+
+static u32 get_iopte_attr(struct iotlb_entry *e)
+{
+	return arch_iommu->get_pte_attr(e);
+}
+
+static u32 iommu_report_fault(struct omap_iommu *obj, u32 *da)
+{
+	return arch_iommu->fault_isr(obj, da);
+}
+
+static void iotlb_lock_get(struct omap_iommu *obj, struct iotlb_lock *l)
+{
+	u32 val;
+
+	val = iommu_read_reg(obj, MMU_LOCK);
+
+	l->base = MMU_LOCK_BASE(val);
+	l->vict = MMU_LOCK_VICT(val);
+
+}
+
+static void iotlb_lock_set(struct omap_iommu *obj, struct iotlb_lock *l)
+{
+	u32 val;
+
+	val = (l->base << MMU_LOCK_BASE_SHIFT);
+	val |= (l->vict << MMU_LOCK_VICT_SHIFT);
+
+	iommu_write_reg(obj, val, MMU_LOCK);
+}
+
+static void iotlb_read_cr(struct omap_iommu *obj, struct cr_regs *cr)
+{
+	arch_iommu->tlb_read_cr(obj, cr);
+}
+
+static void iotlb_load_cr(struct omap_iommu *obj, struct cr_regs *cr)
+{
+	arch_iommu->tlb_load_cr(obj, cr);
+
+	iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
+	iommu_write_reg(obj, 1, MMU_LD_TLB);
+}
+
+/**
+ * iotlb_dump_cr - Dump an iommu tlb entry into buf
+ * @obj:	target iommu
+ * @cr:		contents of cam and ram register
+ * @buf:	output buffer
+ **/
+static inline ssize_t iotlb_dump_cr(struct omap_iommu *obj, struct cr_regs *cr,
+				    char *buf)
+{
+	BUG_ON(!cr || !buf);
+
+	return arch_iommu->dump_cr(obj, cr, buf);
+}
+
+/* only used in iotlb iteration for-loop */
+static struct cr_regs __iotlb_read_cr(struct omap_iommu *obj, int n)
+{
+	struct cr_regs cr;
+	struct iotlb_lock l;
+
+	iotlb_lock_get(obj, &l);
+	l.vict = n;
+	iotlb_lock_set(obj, &l);
+	iotlb_read_cr(obj, &cr);
+
+	return cr;
+}
+
+/**
+ * load_iotlb_entry - Set an iommu tlb entry
+ * @obj:	target iommu
+ * @e:		an iommu tlb entry info
+ **/
+#ifdef PREFETCH_IOTLB
+static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
+{
+	int err = 0;
+	struct iotlb_lock l;
+	struct cr_regs *cr;
+
+	if (!obj || !obj->nr_tlb_entries || !e)
+		return -EINVAL;
+
+	clk_enable(obj->clk);
+
+	iotlb_lock_get(obj, &l);
+	if (l.base == obj->nr_tlb_entries) {
+		dev_warn(obj->dev, "%s: preserve entries full\n", __func__);
+		err = -EBUSY;
+		goto out;
+	}
+	if (!e->prsvd) {
+		int i;
+		struct cr_regs tmp;
+
+		for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, tmp)
+			if (!iotlb_cr_valid(&tmp))
+				break;
+
+		if (i == obj->nr_tlb_entries) {
+			dev_dbg(obj->dev, "%s: full: no entry\n", __func__);
+			err = -EBUSY;
+			goto out;
+		}
+
+		iotlb_lock_get(obj, &l);
+	} else {
+		l.vict = l.base;
+		iotlb_lock_set(obj, &l);
+	}
+
+	cr = iotlb_alloc_cr(obj, e);
+	if (IS_ERR(cr)) {
+		clk_disable(obj->clk);
+		return PTR_ERR(cr);
+	}
+
+	iotlb_load_cr(obj, cr);
+	kfree(cr);
+
+	if (e->prsvd)
+		l.base++;
+	/* increment victim for next tlb load */
+	if (++l.vict == obj->nr_tlb_entries)
+		l.vict = l.base;
+	iotlb_lock_set(obj, &l);
+out:
+	clk_disable(obj->clk);
+	return err;
+}
+
+#else /* !PREFETCH_IOTLB */
+
+static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
+{
+	return 0;
+}
+
+#endif /* !PREFETCH_IOTLB */
+
+static int prefetch_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
+{
+	return load_iotlb_entry(obj, e);
+}
+
+/**
+ * flush_iotlb_page - Clear an iommu tlb entry
+ * @obj:	target iommu
+ * @da:		iommu device virtual address
+ *
+ * Clear an iommu tlb entry which includes 'da' address.
+ **/
+static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
+{
+	int i;
+	struct cr_regs cr;
+
+	clk_enable(obj->clk);
+
+	for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) {
+		u32 start;
+		size_t bytes;
+
+		if (!iotlb_cr_valid(&cr))
+			continue;
+
+		start = iotlb_cr_to_virt(&cr);
+		bytes = iopgsz_to_bytes(cr.cam & 3);
+
+		if ((start <= da) && (da < start + bytes)) {
+			dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n",
+				__func__, start, da, bytes);
+			iotlb_load_cr(obj, &cr);
+			iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
+		}
+	}
+	clk_disable(obj->clk);
+
+	if (i == obj->nr_tlb_entries)
+		dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da);
+}
+
+/**
+ * flush_iotlb_all - Clear all iommu tlb entries
+ * @obj:	target iommu
+ **/
+static void flush_iotlb_all(struct omap_iommu *obj)
+{
+	struct iotlb_lock l;
+
+	clk_enable(obj->clk);
+
+	l.base = 0;
+	l.vict = 0;
+	iotlb_lock_set(obj, &l);
+
+	iommu_write_reg(obj, 1, MMU_GFLUSH);
+
+	clk_disable(obj->clk);
+}
+
+#if defined(CONFIG_OMAP_IOMMU_DEBUG) || defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
+
+ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t bytes)
+{
+	if (!obj || !buf)
+		return -EINVAL;
+
+	clk_enable(obj->clk);
+
+	bytes = arch_iommu->dump_ctx(obj, buf, bytes);
+
+	clk_disable(obj->clk);
+
+	return bytes;
+}
+EXPORT_SYMBOL_GPL(omap_iommu_dump_ctx);
+
+static int
+__dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
+{
+	int i;
+	struct iotlb_lock saved;
+	struct cr_regs tmp;
+	struct cr_regs *p = crs;
+
+	clk_enable(obj->clk);
+	iotlb_lock_get(obj, &saved);
+
+	for_each_iotlb_cr(obj, num, i, tmp) {
+		if (!iotlb_cr_valid(&tmp))
+			continue;
+		*p++ = tmp;
+	}
+
+	iotlb_lock_set(obj, &saved);
+	clk_disable(obj->clk);
+
+	return  p - crs;
+}
+
+/**
+ * omap_dump_tlb_entries - dump cr arrays to given buffer
+ * @obj:	target iommu
+ * @buf:	output buffer
+ **/
+size_t omap_dump_tlb_entries(struct omap_iommu *obj, char *buf, ssize_t bytes)
+{
+	int i, num;
+	struct cr_regs *cr;
+	char *p = buf;
+
+	num = bytes / sizeof(*cr);
+	num = min(obj->nr_tlb_entries, num);
+
+	cr = kcalloc(num, sizeof(*cr), GFP_KERNEL);
+	if (!cr)
+		return 0;
+
+	num = __dump_tlb_entries(obj, cr, num);
+	for (i = 0; i < num; i++)
+		p += iotlb_dump_cr(obj, cr + i, p);
+	kfree(cr);
+
+	return p - buf;
+}
+EXPORT_SYMBOL_GPL(omap_dump_tlb_entries);
+
+int omap_foreach_iommu_device(void *data, int (*fn)(struct device *, void *))
+{
+	return driver_for_each_device(&omap_iommu_driver.driver,
+				      NULL, data, fn);
+}
+EXPORT_SYMBOL_GPL(omap_foreach_iommu_device);
+
+#endif /* CONFIG_OMAP_IOMMU_DEBUG_MODULE */
+
+/*
+ *	H/W pagetable operations
+ */
+static void flush_iopgd_range(u32 *first, u32 *last)
+{
+	/* FIXME: L2 cache should be taken care of if it exists */
+	do {
+		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pgd"
+		    : : "r" (first));
+		first += L1_CACHE_BYTES / sizeof(*first);
+	} while (first <= last);
+}
+
+static void flush_iopte_range(u32 *first, u32 *last)
+{
+	/* FIXME: L2 cache should be taken care of if it exists */
+	do {
+		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pte"
+		    : : "r" (first));
+		first += L1_CACHE_BYTES / sizeof(*first);
+	} while (first <= last);
+}
+
+static void iopte_free(u32 *iopte)
+{
+	/* Note: freed iopte's must be clean ready for re-use */
+	kmem_cache_free(iopte_cachep, iopte);
+}
+
+static u32 *iopte_alloc(struct omap_iommu *obj, u32 *iopgd, u32 da)
+{
+	u32 *iopte;
+
+	/* a table has already existed */
+	if (*iopgd)
+		goto pte_ready;
+
+	/*
+	 * do the allocation outside the page table lock
+	 */
+	spin_unlock(&obj->page_table_lock);
+	iopte = kmem_cache_zalloc(iopte_cachep, GFP_KERNEL);
+	spin_lock(&obj->page_table_lock);
+
+	if (!*iopgd) {
+		if (!iopte)
+			return ERR_PTR(-ENOMEM);
+
+		*iopgd = virt_to_phys(iopte) | IOPGD_TABLE;
+		flush_iopgd_range(iopgd, iopgd);
+
+		dev_vdbg(obj->dev, "%s: a new pte:%p\n", __func__, iopte);
+	} else {
+		/* We raced, free the reduniovant table */
+		iopte_free(iopte);
+	}
+
+pte_ready:
+	iopte = iopte_offset(iopgd, da);
+
+	dev_vdbg(obj->dev,
+		 "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n",
+		 __func__, da, iopgd, *iopgd, iopte, *iopte);
+
+	return iopte;
+}
+
+static int iopgd_alloc_section(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
+{
+	u32 *iopgd = iopgd_offset(obj, da);
+
+	if ((da | pa) & ~IOSECTION_MASK) {
+		dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
+			__func__, da, pa, IOSECTION_SIZE);
+		return -EINVAL;
+	}
+
+	*iopgd = (pa & IOSECTION_MASK) | prot | IOPGD_SECTION;
+	flush_iopgd_range(iopgd, iopgd);
+	return 0;
+}
+
+static int iopgd_alloc_super(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
+{
+	u32 *iopgd = iopgd_offset(obj, da);
+	int i;
+
+	if ((da | pa) & ~IOSUPER_MASK) {
+		dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
+			__func__, da, pa, IOSUPER_SIZE);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < 16; i++)
+		*(iopgd + i) = (pa & IOSUPER_MASK) | prot | IOPGD_SUPER;
+	flush_iopgd_range(iopgd, iopgd + 15);
+	return 0;
+}
+
+static int iopte_alloc_page(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
+{
+	u32 *iopgd = iopgd_offset(obj, da);
+	u32 *iopte = iopte_alloc(obj, iopgd, da);
+
+	if (IS_ERR(iopte))
+		return PTR_ERR(iopte);
+
+	*iopte = (pa & IOPAGE_MASK) | prot | IOPTE_SMALL;
+	flush_iopte_range(iopte, iopte);
+
+	dev_vdbg(obj->dev, "%s: da:%08x pa:%08x pte:%p *pte:%08x\n",
+		 __func__, da, pa, iopte, *iopte);
+
+	return 0;
+}
+
+static int iopte_alloc_large(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
+{
+	u32 *iopgd = iopgd_offset(obj, da);
+	u32 *iopte = iopte_alloc(obj, iopgd, da);
+	int i;
+
+	if ((da | pa) & ~IOLARGE_MASK) {
+		dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
+			__func__, da, pa, IOLARGE_SIZE);
+		return -EINVAL;
+	}
+
+	if (IS_ERR(iopte))
+		return PTR_ERR(iopte);
+
+	for (i = 0; i < 16; i++)
+		*(iopte + i) = (pa & IOLARGE_MASK) | prot | IOPTE_LARGE;
+	flush_iopte_range(iopte, iopte + 15);
+	return 0;
+}
+
+static int
+iopgtable_store_entry_core(struct omap_iommu *obj, struct iotlb_entry *e)
+{
+	int (*fn)(struct omap_iommu *, u32, u32, u32);
+	u32 prot;
+	int err;
+
+	if (!obj || !e)
+		return -EINVAL;
+
+	switch (e->pgsz) {
+	case MMU_CAM_PGSZ_16M:
+		fn = iopgd_alloc_super;
+		break;
+	case MMU_CAM_PGSZ_1M:
+		fn = iopgd_alloc_section;
+		break;
+	case MMU_CAM_PGSZ_64K:
+		fn = iopte_alloc_large;
+		break;
+	case MMU_CAM_PGSZ_4K:
+		fn = iopte_alloc_page;
+		break;
+	default:
+		fn = NULL;
+		BUG();
+		break;
+	}
+
+	prot = get_iopte_attr(e);
+
+	spin_lock(&obj->page_table_lock);
+	err = fn(obj, e->da, e->pa, prot);
+	spin_unlock(&obj->page_table_lock);
+
+	return err;
+}
+
+/**
+ * omap_iopgtable_store_entry - Make an iommu pte entry
+ * @obj:	target iommu
+ * @e:		an iommu tlb entry info
+ **/
+int omap_iopgtable_store_entry(struct omap_iommu *obj, struct iotlb_entry *e)
+{
+	int err;
+
+	flush_iotlb_page(obj, e->da);
+	err = iopgtable_store_entry_core(obj, e);
+	if (!err)
+		prefetch_iotlb_entry(obj, e);
+	return err;
+}
+EXPORT_SYMBOL_GPL(omap_iopgtable_store_entry);
+
+/**
+ * iopgtable_lookup_entry - Lookup an iommu pte entry
+ * @obj:	target iommu
+ * @da:		iommu device virtual address
+ * @ppgd:	iommu pgd entry pointer to be returned
+ * @ppte:	iommu pte entry pointer to be returned
+ **/
+static void
+iopgtable_lookup_entry(struct omap_iommu *obj, u32 da, u32 **ppgd, u32 **ppte)
+{
+	u32 *iopgd, *iopte = NULL;
+
+	iopgd = iopgd_offset(obj, da);
+	if (!*iopgd)
+		goto out;
+
+	if (iopgd_is_table(*iopgd))
+		iopte = iopte_offset(iopgd, da);
+out:
+	*ppgd = iopgd;
+	*ppte = iopte;
+}
+
+static size_t iopgtable_clear_entry_core(struct omap_iommu *obj, u32 da)
+{
+	size_t bytes;
+	u32 *iopgd = iopgd_offset(obj, da);
+	int nent = 1;
+
+	if (!*iopgd)
+		return 0;
+
+	if (iopgd_is_table(*iopgd)) {
+		int i;
+		u32 *iopte = iopte_offset(iopgd, da);
+
+		bytes = IOPTE_SIZE;
+		if (*iopte & IOPTE_LARGE) {
+			nent *= 16;
+			/* rewind to the 1st entry */
+			iopte = iopte_offset(iopgd, (da & IOLARGE_MASK));
+		}
+		bytes *= nent;
+		memset(iopte, 0, nent * sizeof(*iopte));
+		flush_iopte_range(iopte, iopte + (nent - 1) * sizeof(*iopte));
+
+		/*
+		 * do table walk to check if this table is necessary or not
+		 */
+		iopte = iopte_offset(iopgd, 0);
+		for (i = 0; i < PTRS_PER_IOPTE; i++)
+			if (iopte[i])
+				goto out;
+
+		iopte_free(iopte);
+		nent = 1; /* for the next L1 entry */
+	} else {
+		bytes = IOPGD_SIZE;
+		if ((*iopgd & IOPGD_SUPER) == IOPGD_SUPER) {
+			nent *= 16;
+			/* rewind to the 1st entry */
+			iopgd = iopgd_offset(obj, (da & IOSUPER_MASK));
+		}
+		bytes *= nent;
+	}
+	memset(iopgd, 0, nent * sizeof(*iopgd));
+	flush_iopgd_range(iopgd, iopgd + (nent - 1) * sizeof(*iopgd));
+out:
+	return bytes;
+}
+
+/**
+ * iopgtable_clear_entry - Remove an iommu pte entry
+ * @obj:	target iommu
+ * @da:		iommu device virtual address
+ **/
+static size_t iopgtable_clear_entry(struct omap_iommu *obj, u32 da)
+{
+	size_t bytes;
+
+	spin_lock(&obj->page_table_lock);
+
+	bytes = iopgtable_clear_entry_core(obj, da);
+	flush_iotlb_page(obj, da);
+
+	spin_unlock(&obj->page_table_lock);
+
+	return bytes;
+}
+
+static void iopgtable_clear_entry_all(struct omap_iommu *obj)
+{
+	int i;
+
+	spin_lock(&obj->page_table_lock);
+
+	for (i = 0; i < PTRS_PER_IOPGD; i++) {
+		u32 da;
+		u32 *iopgd;
+
+		da = i << IOPGD_SHIFT;
+		iopgd = iopgd_offset(obj, da);
+
+		if (!*iopgd)
+			continue;
+
+		if (iopgd_is_table(*iopgd))
+			iopte_free(iopte_offset(iopgd, 0));
+
+		*iopgd = 0;
+		flush_iopgd_range(iopgd, iopgd);
+	}
+
+	flush_iotlb_all(obj);
+
+	spin_unlock(&obj->page_table_lock);
+}
+
+/*
+ *	Device IOMMU generic operations
+ */
+static irqreturn_t iommu_fault_handler(int irq, void *data)
+{
+	u32 da, errs;
+	u32 *iopgd, *iopte;
+	struct omap_iommu *obj = data;
+	struct iommu_domain *domain = obj->domain;
+
+	if (!obj->refcount)
+		return IRQ_NONE;
+
+	clk_enable(obj->clk);
+	errs = iommu_report_fault(obj, &da);
+	clk_disable(obj->clk);
+	if (errs == 0)
+		return IRQ_HANDLED;
+
+	/* Fault callback or TLB/PTE Dynamic loading */
+	if (!report_iommu_fault(domain, obj->dev, da, 0))
+		return IRQ_HANDLED;
+
+	iommu_disable(obj);
+
+	iopgd = iopgd_offset(obj, da);
+
+	if (!iopgd_is_table(*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: 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;
+}
+
+static int device_match_by_alias(struct device *dev, void *data)
+{
+	struct omap_iommu *obj = to_iommu(dev);
+	const char *name = data;
+
+	pr_debug("%s: %s %s\n", __func__, obj->name, name);
+
+	return strcmp(obj->name, name) == 0;
+}
+
+/**
+ * omap_find_iommu_device() - find an omap iommu device by name
+ * @name:	name of the iommu device
+ *
+ * The generic iommu API requires the caller to provide the device
+ * he wishes to attach to a certain iommu domain.
+ *
+ * Drivers generally should not bother with this as it should just
+ * be taken care of by the DMA-API using dev_archdata.
+ *
+ * This function is provided as an interim solution until the latter
+ * materializes, and omap3isp is fully migrated to the DMA-API.
+ */
+struct device *omap_find_iommu_device(const char *name)
+{
+	return driver_find_device(&omap_iommu_driver.driver, NULL,
+				(void *)name,
+				device_match_by_alias);
+}
+EXPORT_SYMBOL_GPL(omap_find_iommu_device);
+
+/**
+ * omap_iommu_attach() - attach iommu device to an iommu domain
+ * @dev:	target omap iommu device
+ * @iopgd:	page table
+ **/
+static struct omap_iommu *omap_iommu_attach(struct device *dev, u32 *iopgd)
+{
+	int err = -ENOMEM;
+	struct omap_iommu *obj = to_iommu(dev);
+
+	spin_lock(&obj->iommu_lock);
+
+	/* an iommu device can only be attached once */
+	if (++obj->refcount > 1) {
+		dev_err(dev, "%s: already attached!\n", obj->name);
+		err = -EBUSY;
+		goto err_enable;
+	}
+
+	obj->iopgd = iopgd;
+	err = iommu_enable(obj);
+	if (err)
+		goto err_enable;
+	flush_iotlb_all(obj);
+
+	if (!try_module_get(obj->owner))
+		goto err_module;
+
+	spin_unlock(&obj->iommu_lock);
+
+	dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
+	return obj;
+
+err_module:
+	if (obj->refcount == 1)
+		iommu_disable(obj);
+err_enable:
+	obj->refcount--;
+	spin_unlock(&obj->iommu_lock);
+	return ERR_PTR(err);
+}
+
+/**
+ * omap_iommu_detach - release iommu device
+ * @obj:	target iommu
+ **/
+static void omap_iommu_detach(struct omap_iommu *obj)
+{
+	if (!obj || IS_ERR(obj))
+		return;
+
+	spin_lock(&obj->iommu_lock);
+
+	if (--obj->refcount == 0)
+		iommu_disable(obj);
+
+	module_put(obj->owner);
+
+	obj->iopgd = NULL;
+
+	spin_unlock(&obj->iommu_lock);
+
+	dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
+}
+
+/*
+ *	OMAP Device MMU(IOMMU) detection
+ */
+static int __devinit omap_iommu_probe(struct platform_device *pdev)
+{
+	int err = -ENODEV;
+	int irq;
+	struct omap_iommu *obj;
+	struct resource *res;
+	struct iommu_platform_data *pdata = pdev->dev.platform_data;
+
+	if (pdev->num_resources != 2)
+		return -EINVAL;
+
+	obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
+	if (!obj)
+		return -ENOMEM;
+
+	obj->clk = clk_get(&pdev->dev, pdata->clk_name);
+	if (IS_ERR(obj->clk))
+		goto err_clk;
+
+	obj->nr_tlb_entries = pdata->nr_tlb_entries;
+	obj->name = pdata->name;
+	obj->dev = &pdev->dev;
+	obj->ctx = (void *)obj + sizeof(*obj);
+	obj->da_start = pdata->da_start;
+	obj->da_end = pdata->da_end;
+
+	spin_lock_init(&obj->iommu_lock);
+	mutex_init(&obj->mmap_lock);
+	spin_lock_init(&obj->page_table_lock);
+	INIT_LIST_HEAD(&obj->mmap);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -ENODEV;
+		goto err_mem;
+	}
+
+	res = request_mem_region(res->start, resource_size(res),
+				 dev_name(&pdev->dev));
+	if (!res) {
+		err = -EIO;
+		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;
+		goto err_irq;
+	}
+	err = request_irq(irq, iommu_fault_handler, IRQF_SHARED,
+			  dev_name(&pdev->dev), obj);
+	if (err < 0)
+		goto err_irq;
+	platform_set_drvdata(pdev, obj);
+
+	dev_info(&pdev->dev, "%s registered\n", obj->name);
+	return 0;
+
+err_irq:
+	iounmap(obj->regbase);
+err_ioremap:
+	release_mem_region(res->start, resource_size(res));
+err_mem:
+	clk_put(obj->clk);
+err_clk:
+	kfree(obj);
+	return err;
+}
+
+static int __devexit omap_iommu_remove(struct platform_device *pdev)
+{
+	int irq;
+	struct resource *res;
+	struct omap_iommu *obj = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	iopgtable_clear_entry_all(obj);
+
+	irq = platform_get_irq(pdev, 0);
+	free_irq(irq, obj);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+	iounmap(obj->regbase);
+
+	clk_put(obj->clk);
+	dev_info(&pdev->dev, "%s removed\n", obj->name);
+	kfree(obj);
+	return 0;
+}
+
+static struct platform_driver omap_iommu_driver = {
+	.probe	= omap_iommu_probe,
+	.remove	= __devexit_p(omap_iommu_remove),
+	.driver	= {
+		.name	= "omap-iommu",
+	},
+};
+
+static void iopte_cachep_ctor(void *iopte)
+{
+	clean_dcache_area(iopte, IOPTE_TABLE_SIZE);
+}
+
+static int omap_iommu_map(struct iommu_domain *domain, unsigned long da,
+			 phys_addr_t pa, int order, int prot)
+{
+	struct omap_iommu_domain *omap_domain = domain->priv;
+	struct omap_iommu *oiommu = omap_domain->iommu_dev;
+	struct device *dev = oiommu->dev;
+	size_t bytes = PAGE_SIZE << order;
+	struct iotlb_entry e;
+	int omap_pgsz;
+	u32 ret, flags;
+
+	/* we only support mapping a single iommu page for now */
+	omap_pgsz = bytes_to_iopgsz(bytes);
+	if (omap_pgsz < 0) {
+		dev_err(dev, "invalid size to map: %d\n", bytes);
+		return -EINVAL;
+	}
+
+	dev_dbg(dev, "mapping da 0x%lx to pa 0x%x size 0x%x\n", da, pa, bytes);
+
+	flags = omap_pgsz | prot;
+
+	iotlb_init_entry(&e, da, pa, flags);
+
+	ret = omap_iopgtable_store_entry(oiommu, &e);
+	if (ret)
+		dev_err(dev, "omap_iopgtable_store_entry failed: %d\n", ret);
+
+	return ret;
+}
+
+static int omap_iommu_unmap(struct iommu_domain *domain, unsigned long da,
+			    int order)
+{
+	struct omap_iommu_domain *omap_domain = domain->priv;
+	struct omap_iommu *oiommu = omap_domain->iommu_dev;
+	struct device *dev = oiommu->dev;
+	size_t unmap_size;
+
+	dev_dbg(dev, "unmapping da 0x%lx order %d\n", da, order);
+
+	unmap_size = iopgtable_clear_entry(oiommu, da);
+
+	return unmap_size ? get_order(unmap_size) : -EINVAL;
+}
+
+static int
+omap_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
+{
+	struct omap_iommu_domain *omap_domain = domain->priv;
+	struct omap_iommu *oiommu;
+	int ret = 0;
+
+	spin_lock(&omap_domain->lock);
+
+	/* only a single device is supported per domain for now */
+	if (omap_domain->iommu_dev) {
+		dev_err(dev, "iommu domain is already attached\n");
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/* get a handle to and enable the omap iommu */
+	oiommu = omap_iommu_attach(dev, omap_domain->pgtable);
+	if (IS_ERR(oiommu)) {
+		ret = PTR_ERR(oiommu);
+		dev_err(dev, "can't get omap iommu: %d\n", ret);
+		goto out;
+	}
+
+	omap_domain->iommu_dev = oiommu;
+	oiommu->domain = domain;
+
+out:
+	spin_unlock(&omap_domain->lock);
+	return ret;
+}
+
+static void omap_iommu_detach_dev(struct iommu_domain *domain,
+				 struct device *dev)
+{
+	struct omap_iommu_domain *omap_domain = domain->priv;
+	struct omap_iommu *oiommu = to_iommu(dev);
+
+	spin_lock(&omap_domain->lock);
+
+	/* only a single device is supported per domain for now */
+	if (omap_domain->iommu_dev != oiommu) {
+		dev_err(dev, "invalid iommu device\n");
+		goto out;
+	}
+
+	iopgtable_clear_entry_all(oiommu);
+
+	omap_iommu_detach(oiommu);
+
+	omap_domain->iommu_dev = NULL;
+
+out:
+	spin_unlock(&omap_domain->lock);
+}
+
+static int omap_iommu_domain_init(struct iommu_domain *domain)
+{
+	struct omap_iommu_domain *omap_domain;
+
+	omap_domain = kzalloc(sizeof(*omap_domain), GFP_KERNEL);
+	if (!omap_domain) {
+		pr_err("kzalloc failed\n");
+		goto out;
+	}
+
+	omap_domain->pgtable = kzalloc(IOPGD_TABLE_SIZE, GFP_KERNEL);
+	if (!omap_domain->pgtable) {
+		pr_err("kzalloc failed\n");
+		goto fail_nomem;
+	}
+
+	/*
+	 * should never fail, but please keep this around to ensure
+	 * we keep the hardware happy
+	 */
+	BUG_ON(!IS_ALIGNED((long)omap_domain->pgtable, IOPGD_TABLE_SIZE));
+
+	clean_dcache_area(omap_domain->pgtable, IOPGD_TABLE_SIZE);
+	spin_lock_init(&omap_domain->lock);
+
+	domain->priv = omap_domain;
+
+	return 0;
+
+fail_nomem:
+	kfree(omap_domain);
+out:
+	return -ENOMEM;
+}
+
+/* assume device was already detached */
+static void omap_iommu_domain_destroy(struct iommu_domain *domain)
+{
+	struct omap_iommu_domain *omap_domain = domain->priv;
+
+	domain->priv = NULL;
+
+	kfree(omap_domain->pgtable);
+	kfree(omap_domain);
+}
+
+static phys_addr_t omap_iommu_iova_to_phys(struct iommu_domain *domain,
+					  unsigned long da)
+{
+	struct omap_iommu_domain *omap_domain = domain->priv;
+	struct omap_iommu *oiommu = omap_domain->iommu_dev;
+	struct device *dev = oiommu->dev;
+	u32 *pgd, *pte;
+	phys_addr_t ret = 0;
+
+	iopgtable_lookup_entry(oiommu, da, &pgd, &pte);
+
+	if (pte) {
+		if (iopte_is_small(*pte))
+			ret = omap_iommu_translate(*pte, da, IOPTE_MASK);
+		else if (iopte_is_large(*pte))
+			ret = omap_iommu_translate(*pte, da, IOLARGE_MASK);
+		else
+			dev_err(dev, "bogus pte 0x%x", *pte);
+	} else {
+		if (iopgd_is_section(*pgd))
+			ret = omap_iommu_translate(*pgd, da, IOSECTION_MASK);
+		else if (iopgd_is_super(*pgd))
+			ret = omap_iommu_translate(*pgd, da, IOSUPER_MASK);
+		else
+			dev_err(dev, "bogus pgd 0x%x", *pgd);
+	}
+
+	return ret;
+}
+
+static int omap_iommu_domain_has_cap(struct iommu_domain *domain,
+				    unsigned long cap)
+{
+	return 0;
+}
+
+static struct iommu_ops omap_iommu_ops = {
+	.domain_init	= omap_iommu_domain_init,
+	.domain_destroy	= omap_iommu_domain_destroy,
+	.attach_dev	= omap_iommu_attach_dev,
+	.detach_dev	= omap_iommu_detach_dev,
+	.map		= omap_iommu_map,
+	.unmap		= omap_iommu_unmap,
+	.iova_to_phys	= omap_iommu_iova_to_phys,
+	.domain_has_cap	= omap_iommu_domain_has_cap,
+};
+
+static int __init omap_iommu_init(void)
+{
+	struct kmem_cache *p;
+	const unsigned long flags = SLAB_HWCACHE_ALIGN;
+	size_t align = 1 << 10; /* L2 pagetable alignement */
+
+	p = kmem_cache_create("iopte_cache", IOPTE_TABLE_SIZE, align, flags,
+			      iopte_cachep_ctor);
+	if (!p)
+		return -ENOMEM;
+	iopte_cachep = p;
+
+	bus_set_iommu(&platform_bus_type, &omap_iommu_ops);
+
+	return platform_driver_register(&omap_iommu_driver);
+}
+module_init(omap_iommu_init);
+
+static void __exit omap_iommu_exit(void)
+{
+	kmem_cache_destroy(iopte_cachep);
+
+	platform_driver_unregister(&omap_iommu_driver);
+}
+module_exit(omap_iommu_exit);
+
+MODULE_DESCRIPTION("omap iommu: tlb and pagetable primitives");
+MODULE_ALIAS("platform:omap-iommu");
+MODULE_AUTHOR("Hiroshi DOYU, Paul Mundt and Toshihiro Kobayashi");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-3.1-gnu/drivers/iommu/omap-iommu-debug.c linux-libre-3.2-gnu/drivers/iommu/omap-iommu-debug.c
--- linux-libre-3.1-gnu/drivers/iommu/omap-iommu-debug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/iommu/omap-iommu-debug.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,419 @@
+/*
+ * omap iommu: debugfs interface
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+
+#include <plat/iommu.h>
+#include <plat/iovmm.h>
+
+#include <plat/iopgtable.h>
+
+#define MAXCOLUMN 100 /* for short messages */
+
+static DEFINE_MUTEX(iommu_debug_lock);
+
+static struct dentry *iommu_debug_root;
+
+static ssize_t debug_read_ver(struct file *file, char __user *userbuf,
+			      size_t count, loff_t *ppos)
+{
+	u32 ver = omap_iommu_arch_version();
+	char buf[MAXCOLUMN], *p = buf;
+
+	p += sprintf(p, "H/W version: %d.%d\n", (ver >> 4) & 0xf , ver & 0xf);
+
+	return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+}
+
+static ssize_t debug_read_regs(struct file *file, char __user *userbuf,
+			       size_t count, loff_t *ppos)
+{
+	struct omap_iommu *obj = file->private_data;
+	char *p, *buf;
+	ssize_t bytes;
+
+	buf = kmalloc(count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	p = buf;
+
+	mutex_lock(&iommu_debug_lock);
+
+	bytes = omap_iommu_dump_ctx(obj, p, count);
+	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, bytes);
+
+	mutex_unlock(&iommu_debug_lock);
+	kfree(buf);
+
+	return bytes;
+}
+
+static ssize_t debug_read_tlb(struct file *file, char __user *userbuf,
+			      size_t count, loff_t *ppos)
+{
+	struct omap_iommu *obj = file->private_data;
+	char *p, *buf;
+	ssize_t bytes, rest;
+
+	buf = kmalloc(count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	p = buf;
+
+	mutex_lock(&iommu_debug_lock);
+
+	p += sprintf(p, "%8s %8s\n", "cam:", "ram:");
+	p += sprintf(p, "-----------------------------------------\n");
+	rest = count - (p - buf);
+	p += omap_dump_tlb_entries(obj, p, rest);
+
+	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+
+	mutex_unlock(&iommu_debug_lock);
+	kfree(buf);
+
+	return bytes;
+}
+
+static ssize_t debug_write_pagetable(struct file *file,
+		     const char __user *userbuf, size_t count, loff_t *ppos)
+{
+	struct iotlb_entry e;
+	struct cr_regs cr;
+	int err;
+	struct omap_iommu *obj = file->private_data;
+	char buf[MAXCOLUMN], *p = buf;
+
+	count = min(count, sizeof(buf));
+
+	mutex_lock(&iommu_debug_lock);
+	if (copy_from_user(p, userbuf, count)) {
+		mutex_unlock(&iommu_debug_lock);
+		return -EFAULT;
+	}
+
+	sscanf(p, "%x %x", &cr.cam, &cr.ram);
+	if (!cr.cam || !cr.ram) {
+		mutex_unlock(&iommu_debug_lock);
+		return -EINVAL;
+	}
+
+	omap_iotlb_cr_to_e(&cr, &e);
+	err = omap_iopgtable_store_entry(obj, &e);
+	if (err)
+		dev_err(obj->dev, "%s: fail to store cr\n", __func__);
+
+	mutex_unlock(&iommu_debug_lock);
+	return count;
+}
+
+#define dump_ioptable_entry_one(lv, da, val)			\
+	({							\
+		int __err = 0;					\
+		ssize_t bytes;					\
+		const int maxcol = 22;				\
+		const char *str = "%d: %08x %08x\n";		\
+		bytes = snprintf(p, maxcol, str, lv, da, val);	\
+		p += bytes;					\
+		len -= bytes;					\
+		if (len < maxcol)				\
+			__err = -ENOMEM;			\
+		__err;						\
+	})
+
+static ssize_t dump_ioptable(struct omap_iommu *obj, char *buf, ssize_t len)
+{
+	int i;
+	u32 *iopgd;
+	char *p = buf;
+
+	spin_lock(&obj->page_table_lock);
+
+	iopgd = iopgd_offset(obj, 0);
+	for (i = 0; i < PTRS_PER_IOPGD; i++, iopgd++) {
+		int j, err;
+		u32 *iopte;
+		u32 da;
+
+		if (!*iopgd)
+			continue;
+
+		if (!(*iopgd & IOPGD_TABLE)) {
+			da = i << IOPGD_SHIFT;
+
+			err = dump_ioptable_entry_one(1, da, *iopgd);
+			if (err)
+				goto out;
+			continue;
+		}
+
+		iopte = iopte_offset(iopgd, 0);
+
+		for (j = 0; j < PTRS_PER_IOPTE; j++, iopte++) {
+			if (!*iopte)
+				continue;
+
+			da = (i << IOPGD_SHIFT) + (j << IOPTE_SHIFT);
+			err = dump_ioptable_entry_one(2, da, *iopgd);
+			if (err)
+				goto out;
+		}
+	}
+out:
+	spin_unlock(&obj->page_table_lock);
+
+	return p - buf;
+}
+
+static ssize_t debug_read_pagetable(struct file *file, char __user *userbuf,
+				    size_t count, loff_t *ppos)
+{
+	struct omap_iommu *obj = file->private_data;
+	char *p, *buf;
+	size_t bytes;
+
+	buf = (char *)__get_free_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	p = buf;
+
+	p += sprintf(p, "L: %8s %8s\n", "da:", "pa:");
+	p += sprintf(p, "-----------------------------------------\n");
+
+	mutex_lock(&iommu_debug_lock);
+
+	bytes = PAGE_SIZE - (p - buf);
+	p += dump_ioptable(obj, p, bytes);
+
+	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+
+	mutex_unlock(&iommu_debug_lock);
+	free_page((unsigned long)buf);
+
+	return bytes;
+}
+
+static ssize_t debug_read_mmap(struct file *file, char __user *userbuf,
+			       size_t count, loff_t *ppos)
+{
+	struct omap_iommu *obj = file->private_data;
+	char *p, *buf;
+	struct iovm_struct *tmp;
+	int uninitialized_var(i);
+	ssize_t bytes;
+
+	buf = (char *)__get_free_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	p = buf;
+
+	p += sprintf(p, "%-3s %-8s %-8s %6s %8s\n",
+		     "No", "start", "end", "size", "flags");
+	p += sprintf(p, "-------------------------------------------------\n");
+
+	mutex_lock(&iommu_debug_lock);
+
+	list_for_each_entry(tmp, &obj->mmap, list) {
+		size_t len;
+		const char *str = "%3d %08x-%08x %6x %8x\n";
+		const int maxcol = 39;
+
+		len = tmp->da_end - tmp->da_start;
+		p += snprintf(p, maxcol, str,
+			      i, tmp->da_start, tmp->da_end, len, tmp->flags);
+
+		if (PAGE_SIZE - (p - buf) < maxcol)
+			break;
+		i++;
+	}
+
+	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+
+	mutex_unlock(&iommu_debug_lock);
+	free_page((unsigned long)buf);
+
+	return bytes;
+}
+
+static ssize_t debug_read_mem(struct file *file, char __user *userbuf,
+			      size_t count, loff_t *ppos)
+{
+	struct omap_iommu *obj = file->private_data;
+	char *p, *buf;
+	struct iovm_struct *area;
+	ssize_t bytes;
+
+	count = min_t(ssize_t, count, PAGE_SIZE);
+
+	buf = (char *)__get_free_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	p = buf;
+
+	mutex_lock(&iommu_debug_lock);
+
+	area = omap_find_iovm_area(obj, (u32)ppos);
+	if (IS_ERR(area)) {
+		bytes = -EINVAL;
+		goto err_out;
+	}
+	memcpy(p, area->va, count);
+	p += count;
+
+	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+err_out:
+	mutex_unlock(&iommu_debug_lock);
+	free_page((unsigned long)buf);
+
+	return bytes;
+}
+
+static ssize_t debug_write_mem(struct file *file, const char __user *userbuf,
+			       size_t count, loff_t *ppos)
+{
+	struct omap_iommu *obj = file->private_data;
+	struct iovm_struct *area;
+	char *p, *buf;
+
+	count = min_t(size_t, count, PAGE_SIZE);
+
+	buf = (char *)__get_free_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	p = buf;
+
+	mutex_lock(&iommu_debug_lock);
+
+	if (copy_from_user(p, userbuf, count)) {
+		count =  -EFAULT;
+		goto err_out;
+	}
+
+	area = omap_find_iovm_area(obj, (u32)ppos);
+	if (IS_ERR(area)) {
+		count = -EINVAL;
+		goto err_out;
+	}
+	memcpy(area->va, p, count);
+err_out:
+	mutex_unlock(&iommu_debug_lock);
+	free_page((unsigned long)buf);
+
+	return count;
+}
+
+static int debug_open_generic(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+#define DEBUG_FOPS(name)						\
+	static const struct file_operations debug_##name##_fops = {	\
+		.open = debug_open_generic,				\
+		.read = debug_read_##name,				\
+		.write = debug_write_##name,				\
+		.llseek = generic_file_llseek,				\
+	};
+
+#define DEBUG_FOPS_RO(name)						\
+	static const struct file_operations debug_##name##_fops = {	\
+		.open = debug_open_generic,				\
+		.read = debug_read_##name,				\
+		.llseek = generic_file_llseek,				\
+	};
+
+DEBUG_FOPS_RO(ver);
+DEBUG_FOPS_RO(regs);
+DEBUG_FOPS_RO(tlb);
+DEBUG_FOPS(pagetable);
+DEBUG_FOPS_RO(mmap);
+DEBUG_FOPS(mem);
+
+#define __DEBUG_ADD_FILE(attr, mode)					\
+	{								\
+		struct dentry *dent;					\
+		dent = debugfs_create_file(#attr, mode, parent,		\
+					   obj, &debug_##attr##_fops);	\
+		if (!dent)						\
+			return -ENOMEM;					\
+	}
+
+#define DEBUG_ADD_FILE(name) __DEBUG_ADD_FILE(name, 600)
+#define DEBUG_ADD_FILE_RO(name) __DEBUG_ADD_FILE(name, 400)
+
+static int iommu_debug_register(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_iommu *obj = platform_get_drvdata(pdev);
+	struct dentry *d, *parent;
+
+	if (!obj || !obj->dev)
+		return -EINVAL;
+
+	d = debugfs_create_dir(obj->name, iommu_debug_root);
+	if (!d)
+		return -ENOMEM;
+	parent = d;
+
+	d = debugfs_create_u8("nr_tlb_entries", 400, parent,
+			      (u8 *)&obj->nr_tlb_entries);
+	if (!d)
+		return -ENOMEM;
+
+	DEBUG_ADD_FILE_RO(ver);
+	DEBUG_ADD_FILE_RO(regs);
+	DEBUG_ADD_FILE_RO(tlb);
+	DEBUG_ADD_FILE(pagetable);
+	DEBUG_ADD_FILE_RO(mmap);
+	DEBUG_ADD_FILE(mem);
+
+	return 0;
+}
+
+static int __init iommu_debug_init(void)
+{
+	struct dentry *d;
+	int err;
+
+	d = debugfs_create_dir("iommu", NULL);
+	if (!d)
+		return -ENOMEM;
+	iommu_debug_root = d;
+
+	err = omap_foreach_iommu_device(d, iommu_debug_register);
+	if (err)
+		goto err_out;
+	return 0;
+
+err_out:
+	debugfs_remove_recursive(iommu_debug_root);
+	return err;
+}
+module_init(iommu_debug_init)
+
+static void __exit iommu_debugfs_exit(void)
+{
+	debugfs_remove_recursive(iommu_debug_root);
+}
+module_exit(iommu_debugfs_exit)
+
+MODULE_DESCRIPTION("omap iommu: debugfs interface");
+MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-3.1-gnu/drivers/iommu/omap-iovmm.c linux-libre-3.2-gnu/drivers/iommu/omap-iovmm.c
--- linux-libre-3.1-gnu/drivers/iommu/omap-iovmm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/iommu/omap-iovmm.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,743 @@
+/*
+ * omap iommu: simple virtual address space management
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/device.h>
+#include <linux/scatterlist.h>
+#include <linux/iommu.h>
+
+#include <asm/cacheflush.h>
+#include <asm/mach/map.h>
+
+#include <plat/iommu.h>
+#include <plat/iovmm.h>
+
+#include <plat/iopgtable.h>
+
+static struct kmem_cache *iovm_area_cachep;
+
+/* return the offset of the first scatterlist entry in a sg table */
+static unsigned int sgtable_offset(const struct sg_table *sgt)
+{
+	if (!sgt || !sgt->nents)
+		return 0;
+
+	return sgt->sgl->offset;
+}
+
+/* return total bytes of sg buffers */
+static size_t sgtable_len(const struct sg_table *sgt)
+{
+	unsigned int i, total = 0;
+	struct scatterlist *sg;
+
+	if (!sgt)
+		return 0;
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		size_t bytes;
+
+		bytes = sg->length + sg->offset;
+
+		if (!iopgsz_ok(bytes)) {
+			pr_err("%s: sg[%d] not iommu pagesize(%u %u)\n",
+			       __func__, i, bytes, sg->offset);
+			return 0;
+		}
+
+		if (i && sg->offset) {
+			pr_err("%s: sg[%d] offset not allowed in internal "
+					"entries\n", __func__, i);
+			return 0;
+		}
+
+		total += bytes;
+	}
+
+	return total;
+}
+#define sgtable_ok(x)	(!!sgtable_len(x))
+
+static unsigned max_alignment(u32 addr)
+{
+	int i;
+	unsigned pagesize[] = { SZ_16M, SZ_1M, SZ_64K, SZ_4K, };
+	for (i = 0; i < ARRAY_SIZE(pagesize) && addr & (pagesize[i] - 1); i++)
+		;
+	return (i < ARRAY_SIZE(pagesize)) ? pagesize[i] : 0;
+}
+
+/*
+ * calculate the optimal number sg elements from total bytes based on
+ * iommu superpages
+ */
+static unsigned sgtable_nents(size_t bytes, u32 da, u32 pa)
+{
+	unsigned nr_entries = 0, ent_sz;
+
+	if (!IS_ALIGNED(bytes, PAGE_SIZE)) {
+		pr_err("%s: wrong size %08x\n", __func__, bytes);
+		return 0;
+	}
+
+	while (bytes) {
+		ent_sz = max_alignment(da | pa);
+		ent_sz = min_t(unsigned, ent_sz, iopgsz_max(bytes));
+		nr_entries++;
+		da += ent_sz;
+		pa += ent_sz;
+		bytes -= ent_sz;
+	}
+
+	return nr_entries;
+}
+
+/* allocate and initialize sg_table header(a kind of 'superblock') */
+static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags,
+							u32 da, u32 pa)
+{
+	unsigned int nr_entries;
+	int err;
+	struct sg_table *sgt;
+
+	if (!bytes)
+		return ERR_PTR(-EINVAL);
+
+	if (!IS_ALIGNED(bytes, PAGE_SIZE))
+		return ERR_PTR(-EINVAL);
+
+	if (flags & IOVMF_LINEAR) {
+		nr_entries = sgtable_nents(bytes, da, pa);
+		if (!nr_entries)
+			return ERR_PTR(-EINVAL);
+	} else
+		nr_entries =  bytes / PAGE_SIZE;
+
+	sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
+	if (!sgt)
+		return ERR_PTR(-ENOMEM);
+
+	err = sg_alloc_table(sgt, nr_entries, GFP_KERNEL);
+	if (err) {
+		kfree(sgt);
+		return ERR_PTR(err);
+	}
+
+	pr_debug("%s: sgt:%p(%d entries)\n", __func__, sgt, nr_entries);
+
+	return sgt;
+}
+
+/* free sg_table header(a kind of superblock) */
+static void sgtable_free(struct sg_table *sgt)
+{
+	if (!sgt)
+		return;
+
+	sg_free_table(sgt);
+	kfree(sgt);
+
+	pr_debug("%s: sgt:%p\n", __func__, sgt);
+}
+
+/* map 'sglist' to a contiguous mpu virtual area and return 'va' */
+static void *vmap_sg(const struct sg_table *sgt)
+{
+	u32 va;
+	size_t total;
+	unsigned int i;
+	struct scatterlist *sg;
+	struct vm_struct *new;
+	const struct mem_type *mtype;
+
+	mtype = get_mem_type(MT_DEVICE);
+	if (!mtype)
+		return ERR_PTR(-EINVAL);
+
+	total = sgtable_len(sgt);
+	if (!total)
+		return ERR_PTR(-EINVAL);
+
+	new = __get_vm_area(total, VM_IOREMAP, VMALLOC_START, VMALLOC_END);
+	if (!new)
+		return ERR_PTR(-ENOMEM);
+	va = (u32)new->addr;
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		size_t bytes;
+		u32 pa;
+		int err;
+
+		pa = sg_phys(sg) - sg->offset;
+		bytes = sg->length + sg->offset;
+
+		BUG_ON(bytes != PAGE_SIZE);
+
+		err = ioremap_page(va,  pa, mtype);
+		if (err)
+			goto err_out;
+
+		va += bytes;
+	}
+
+	flush_cache_vmap((unsigned long)new->addr,
+				(unsigned long)(new->addr + total));
+	return new->addr;
+
+err_out:
+	WARN_ON(1); /* FIXME: cleanup some mpu mappings */
+	vunmap(new->addr);
+	return ERR_PTR(-EAGAIN);
+}
+
+static inline void vunmap_sg(const void *va)
+{
+	vunmap(va);
+}
+
+static struct iovm_struct *__find_iovm_area(struct omap_iommu *obj,
+							const u32 da)
+{
+	struct iovm_struct *tmp;
+
+	list_for_each_entry(tmp, &obj->mmap, list) {
+		if ((da >= tmp->da_start) && (da < tmp->da_end)) {
+			size_t len;
+
+			len = tmp->da_end - tmp->da_start;
+
+			dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n",
+				__func__, tmp->da_start, da, tmp->da_end, len,
+				tmp->flags);
+
+			return tmp;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * omap_find_iovm_area  -  find iovma which includes @da
+ * @da:		iommu device virtual address
+ *
+ * Find the existing iovma starting at @da
+ */
+struct iovm_struct *omap_find_iovm_area(struct omap_iommu *obj, u32 da)
+{
+	struct iovm_struct *area;
+
+	mutex_lock(&obj->mmap_lock);
+	area = __find_iovm_area(obj, da);
+	mutex_unlock(&obj->mmap_lock);
+
+	return area;
+}
+EXPORT_SYMBOL_GPL(omap_find_iovm_area);
+
+/*
+ * This finds the hole(area) which fits the requested address and len
+ * in iovmas mmap, and returns the new allocated iovma.
+ */
+static struct iovm_struct *alloc_iovm_area(struct omap_iommu *obj, u32 da,
+					   size_t bytes, u32 flags)
+{
+	struct iovm_struct *new, *tmp;
+	u32 start, prev_end, alignment;
+
+	if (!obj || !bytes)
+		return ERR_PTR(-EINVAL);
+
+	start = da;
+	alignment = PAGE_SIZE;
+
+	if (~flags & IOVMF_DA_FIXED) {
+		/* Don't map address 0 */
+		start = obj->da_start ? obj->da_start : alignment;
+
+		if (flags & IOVMF_LINEAR)
+			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);
+	}
+
+	tmp = NULL;
+	if (list_empty(&obj->mmap))
+		goto found;
+
+	prev_end = 0;
+	list_for_each_entry(tmp, &obj->mmap, list) {
+
+		if (prev_end > start)
+			break;
+
+		if (tmp->da_start > start && (tmp->da_start - start) >= bytes)
+			goto found;
+
+		if (tmp->da_end >= start && ~flags & IOVMF_DA_FIXED)
+			start = roundup(tmp->da_end + 1, alignment);
+
+		prev_end = tmp->da_end;
+	}
+
+	if ((start >= prev_end) && (obj->da_end - start >= bytes))
+		goto found;
+
+	dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n",
+		__func__, da, bytes, flags);
+
+	return ERR_PTR(-EINVAL);
+
+found:
+	new = kmem_cache_zalloc(iovm_area_cachep, GFP_KERNEL);
+	if (!new)
+		return ERR_PTR(-ENOMEM);
+
+	new->iommu = obj;
+	new->da_start = start;
+	new->da_end = start + bytes;
+	new->flags = flags;
+
+	/*
+	 * keep ascending order of iovmas
+	 */
+	if (tmp)
+		list_add_tail(&new->list, &tmp->list);
+	else
+		list_add(&new->list, &obj->mmap);
+
+	dev_dbg(obj->dev, "%s: found %08x-%08x-%08x(%x) %08x\n",
+		__func__, new->da_start, start, new->da_end, bytes, flags);
+
+	return new;
+}
+
+static void free_iovm_area(struct omap_iommu *obj, struct iovm_struct *area)
+{
+	size_t bytes;
+
+	BUG_ON(!obj || !area);
+
+	bytes = area->da_end - area->da_start;
+
+	dev_dbg(obj->dev, "%s: %08x-%08x(%x) %08x\n",
+		__func__, area->da_start, area->da_end, bytes, area->flags);
+
+	list_del(&area->list);
+	kmem_cache_free(iovm_area_cachep, area);
+}
+
+/**
+ * omap_da_to_va - convert (d) to (v)
+ * @obj:	objective iommu
+ * @da:		iommu device virtual address
+ * @va:		mpu virtual address
+ *
+ * Returns mpu virtual addr which corresponds to a given device virtual addr
+ */
+void *omap_da_to_va(struct omap_iommu *obj, u32 da)
+{
+	void *va = NULL;
+	struct iovm_struct *area;
+
+	mutex_lock(&obj->mmap_lock);
+
+	area = __find_iovm_area(obj, da);
+	if (!area) {
+		dev_dbg(obj->dev, "%s: no da area(%08x)\n", __func__, da);
+		goto out;
+	}
+	va = area->va;
+out:
+	mutex_unlock(&obj->mmap_lock);
+
+	return va;
+}
+EXPORT_SYMBOL_GPL(omap_da_to_va);
+
+static void sgtable_fill_vmalloc(struct sg_table *sgt, void *_va)
+{
+	unsigned int i;
+	struct scatterlist *sg;
+	void *va = _va;
+	void *va_end;
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		struct page *pg;
+		const size_t bytes = PAGE_SIZE;
+
+		/*
+		 * iommu 'superpage' isn't supported with 'omap_iommu_vmalloc()'
+		 */
+		pg = vmalloc_to_page(va);
+		BUG_ON(!pg);
+		sg_set_page(sg, pg, bytes, 0);
+
+		va += bytes;
+	}
+
+	va_end = _va + PAGE_SIZE * i;
+}
+
+static inline void sgtable_drain_vmalloc(struct sg_table *sgt)
+{
+	/*
+	 * Actually this is not necessary at all, just exists for
+	 * consistency of the code readability.
+	 */
+	BUG_ON(!sgt);
+}
+
+/* create 'da' <-> 'pa' mapping from 'sgt' */
+static int map_iovm_area(struct iommu_domain *domain, struct iovm_struct *new,
+			const struct sg_table *sgt, u32 flags)
+{
+	int err;
+	unsigned int i, j;
+	struct scatterlist *sg;
+	u32 da = new->da_start;
+	int order;
+
+	if (!domain || !sgt)
+		return -EINVAL;
+
+	BUG_ON(!sgtable_ok(sgt));
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		u32 pa;
+		size_t bytes;
+
+		pa = sg_phys(sg) - sg->offset;
+		bytes = sg->length + sg->offset;
+
+		flags &= ~IOVMF_PGSZ_MASK;
+
+		if (bytes_to_iopgsz(bytes) < 0)
+			goto err_out;
+
+		order = get_order(bytes);
+
+		pr_debug("%s: [%d] %08x %08x(%x)\n", __func__,
+			 i, da, pa, bytes);
+
+		err = iommu_map(domain, da, pa, order, flags);
+		if (err)
+			goto err_out;
+
+		da += bytes;
+	}
+	return 0;
+
+err_out:
+	da = new->da_start;
+
+	for_each_sg(sgt->sgl, sg, i, j) {
+		size_t bytes;
+
+		bytes = sg->length + sg->offset;
+		order = get_order(bytes);
+
+		/* ignore failures.. we're already handling one */
+		iommu_unmap(domain, da, order);
+
+		da += bytes;
+	}
+	return err;
+}
+
+/* release 'da' <-> 'pa' mapping */
+static void unmap_iovm_area(struct iommu_domain *domain, struct omap_iommu *obj,
+						struct iovm_struct *area)
+{
+	u32 start;
+	size_t total = area->da_end - area->da_start;
+	const struct sg_table *sgt = area->sgt;
+	struct scatterlist *sg;
+	int i, err;
+
+	BUG_ON(!sgtable_ok(sgt));
+	BUG_ON((!total) || !IS_ALIGNED(total, PAGE_SIZE));
+
+	start = area->da_start;
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		size_t bytes;
+		int order;
+
+		bytes = sg->length + sg->offset;
+		order = get_order(bytes);
+
+		err = iommu_unmap(domain, start, order);
+		if (err < 0)
+			break;
+
+		dev_dbg(obj->dev, "%s: unmap %08x(%x) %08x\n",
+				__func__, start, bytes, area->flags);
+
+		BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE));
+
+		total -= bytes;
+		start += bytes;
+	}
+	BUG_ON(total);
+}
+
+/* template function for all unmapping */
+static struct sg_table *unmap_vm_area(struct iommu_domain *domain,
+				      struct omap_iommu *obj, const u32 da,
+				      void (*fn)(const void *), u32 flags)
+{
+	struct sg_table *sgt = NULL;
+	struct iovm_struct *area;
+
+	if (!IS_ALIGNED(da, PAGE_SIZE)) {
+		dev_err(obj->dev, "%s: alignment err(%08x)\n", __func__, da);
+		return NULL;
+	}
+
+	mutex_lock(&obj->mmap_lock);
+
+	area = __find_iovm_area(obj, da);
+	if (!area) {
+		dev_dbg(obj->dev, "%s: no da area(%08x)\n", __func__, da);
+		goto out;
+	}
+
+	if ((area->flags & flags) != flags) {
+		dev_err(obj->dev, "%s: wrong flags(%08x)\n", __func__,
+			area->flags);
+		goto out;
+	}
+	sgt = (struct sg_table *)area->sgt;
+
+	unmap_iovm_area(domain, obj, area);
+
+	fn(area->va);
+
+	dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n", __func__,
+		area->da_start, da, area->da_end,
+		area->da_end - area->da_start, area->flags);
+
+	free_iovm_area(obj, area);
+out:
+	mutex_unlock(&obj->mmap_lock);
+
+	return sgt;
+}
+
+static u32 map_iommu_region(struct iommu_domain *domain, struct omap_iommu *obj,
+				u32 da, const struct sg_table *sgt, void *va,
+				size_t bytes, u32 flags)
+{
+	int err = -ENOMEM;
+	struct iovm_struct *new;
+
+	mutex_lock(&obj->mmap_lock);
+
+	new = alloc_iovm_area(obj, da, bytes, flags);
+	if (IS_ERR(new)) {
+		err = PTR_ERR(new);
+		goto err_alloc_iovma;
+	}
+	new->va = va;
+	new->sgt = sgt;
+
+	if (map_iovm_area(domain, new, sgt, new->flags))
+		goto err_map;
+
+	mutex_unlock(&obj->mmap_lock);
+
+	dev_dbg(obj->dev, "%s: da:%08x(%x) flags:%08x va:%p\n",
+		__func__, new->da_start, bytes, new->flags, va);
+
+	return new->da_start;
+
+err_map:
+	free_iovm_area(obj, new);
+err_alloc_iovma:
+	mutex_unlock(&obj->mmap_lock);
+	return err;
+}
+
+static inline u32
+__iommu_vmap(struct iommu_domain *domain, struct omap_iommu *obj,
+				u32 da, const struct sg_table *sgt,
+				void *va, size_t bytes, u32 flags)
+{
+	return map_iommu_region(domain, obj, da, sgt, va, bytes, flags);
+}
+
+/**
+ * omap_iommu_vmap  -  (d)-(p)-(v) address mapper
+ * @obj:	objective iommu
+ * @sgt:	address of scatter gather table
+ * @flags:	iovma and page property
+ *
+ * Creates 1-n-1 mapping with given @sgt and returns @da.
+ * All @sgt element must be io page size aligned.
+ */
+u32 omap_iommu_vmap(struct iommu_domain *domain, struct omap_iommu *obj, u32 da,
+		const struct sg_table *sgt, u32 flags)
+{
+	size_t bytes;
+	void *va = NULL;
+
+	if (!obj || !obj->dev || !sgt)
+		return -EINVAL;
+
+	bytes = sgtable_len(sgt);
+	if (!bytes)
+		return -EINVAL;
+	bytes = PAGE_ALIGN(bytes);
+
+	if (flags & IOVMF_MMIO) {
+		va = vmap_sg(sgt);
+		if (IS_ERR(va))
+			return PTR_ERR(va);
+	}
+
+	flags |= IOVMF_DISCONT;
+	flags |= IOVMF_MMIO;
+
+	da = __iommu_vmap(domain, obj, da, sgt, va, bytes, flags);
+	if (IS_ERR_VALUE(da))
+		vunmap_sg(va);
+
+	return da + sgtable_offset(sgt);
+}
+EXPORT_SYMBOL_GPL(omap_iommu_vmap);
+
+/**
+ * omap_iommu_vunmap  -  release virtual mapping obtained by 'omap_iommu_vmap()'
+ * @obj:	objective iommu
+ * @da:		iommu device virtual address
+ *
+ * Free the iommu virtually contiguous memory area starting at
+ * @da, which was returned by 'omap_iommu_vmap()'.
+ */
+struct sg_table *
+omap_iommu_vunmap(struct iommu_domain *domain, struct omap_iommu *obj, u32 da)
+{
+	struct sg_table *sgt;
+	/*
+	 * 'sgt' is allocated before 'omap_iommu_vmalloc()' is called.
+	 * Just returns 'sgt' to the caller to free
+	 */
+	da &= PAGE_MASK;
+	sgt = unmap_vm_area(domain, obj, da, vunmap_sg,
+					IOVMF_DISCONT | IOVMF_MMIO);
+	if (!sgt)
+		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
+	return sgt;
+}
+EXPORT_SYMBOL_GPL(omap_iommu_vunmap);
+
+/**
+ * omap_iommu_vmalloc  -  (d)-(p)-(v) address allocator and mapper
+ * @obj:	objective iommu
+ * @da:		contiguous iommu virtual memory
+ * @bytes:	allocation size
+ * @flags:	iovma and page property
+ *
+ * Allocate @bytes linearly and creates 1-n-1 mapping and returns
+ * @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set.
+ */
+u32
+omap_iommu_vmalloc(struct iommu_domain *domain, struct omap_iommu *obj, u32 da,
+						size_t bytes, u32 flags)
+{
+	void *va;
+	struct sg_table *sgt;
+
+	if (!obj || !obj->dev || !bytes)
+		return -EINVAL;
+
+	bytes = PAGE_ALIGN(bytes);
+
+	va = vmalloc(bytes);
+	if (!va)
+		return -ENOMEM;
+
+	flags |= IOVMF_DISCONT;
+	flags |= IOVMF_ALLOC;
+
+	sgt = sgtable_alloc(bytes, flags, da, 0);
+	if (IS_ERR(sgt)) {
+		da = PTR_ERR(sgt);
+		goto err_sgt_alloc;
+	}
+	sgtable_fill_vmalloc(sgt, va);
+
+	da = __iommu_vmap(domain, obj, da, sgt, va, bytes, flags);
+	if (IS_ERR_VALUE(da))
+		goto err_iommu_vmap;
+
+	return da;
+
+err_iommu_vmap:
+	sgtable_drain_vmalloc(sgt);
+	sgtable_free(sgt);
+err_sgt_alloc:
+	vfree(va);
+	return da;
+}
+EXPORT_SYMBOL_GPL(omap_iommu_vmalloc);
+
+/**
+ * omap_iommu_vfree  -  release memory allocated by 'omap_iommu_vmalloc()'
+ * @obj:	objective iommu
+ * @da:		iommu device virtual address
+ *
+ * Frees the iommu virtually continuous memory area starting at
+ * @da, as obtained from 'omap_iommu_vmalloc()'.
+ */
+void omap_iommu_vfree(struct iommu_domain *domain, struct omap_iommu *obj,
+								const u32 da)
+{
+	struct sg_table *sgt;
+
+	sgt = unmap_vm_area(domain, obj, da, vfree,
+						IOVMF_DISCONT | IOVMF_ALLOC);
+	if (!sgt)
+		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
+	sgtable_free(sgt);
+}
+EXPORT_SYMBOL_GPL(omap_iommu_vfree);
+
+static int __init iovmm_init(void)
+{
+	const unsigned long flags = SLAB_HWCACHE_ALIGN;
+	struct kmem_cache *p;
+
+	p = kmem_cache_create("iovm_area_cache", sizeof(struct iovm_struct), 0,
+			      flags, NULL);
+	if (!p)
+		return -ENOMEM;
+	iovm_area_cachep = p;
+
+	return 0;
+}
+module_init(iovmm_init);
+
+static void __exit iovmm_exit(void)
+{
+	kmem_cache_destroy(iovm_area_cachep);
+}
+module_exit(iovmm_exit);
+
+MODULE_DESCRIPTION("omap iommu: simple virtual address space management");
+MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-3.1-gnu/drivers/isdn/capi/kcapi_proc.c linux-libre-3.2-gnu/drivers/isdn/capi/kcapi_proc.c
--- linux-libre-3.1-gnu/drivers/isdn/capi/kcapi_proc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/capi/kcapi_proc.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
+#include <linux/export.h>
 
 static char *state2str(unsigned short state)
 {
diff -druN linux-libre-3.1-gnu/drivers/isdn/divert/divert_procfs.c linux-libre-3.2-gnu/drivers/isdn/divert/divert_procfs.c
--- linux-libre-3.1-gnu/drivers/isdn/divert/divert_procfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/divert/divert_procfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -242,6 +242,12 @@
 		case IIOCDOCFINT:
 			if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid))
 				return (-EINVAL);	/* invalid driver */
+			if (strnlen(dioctl.cf_ctrl.msn, sizeof(dioctl.cf_ctrl.msn)) ==
+					sizeof(dioctl.cf_ctrl.msn))
+				return -EINVAL;
+			if (strnlen(dioctl.cf_ctrl.fwd_nr, sizeof(dioctl.cf_ctrl.fwd_nr)) ==
+					sizeof(dioctl.cf_ctrl.fwd_nr))
+				return -EINVAL;
 			if ((i = cf_command(dioctl.cf_ctrl.drvid,
 					    (cmd == IIOCDOCFACT) ? 1 : (cmd == IIOCDOCFDIS) ? 0 : 2,
 					    dioctl.cf_ctrl.cfproc,
diff -druN linux-libre-3.1-gnu/drivers/isdn/gigaset/asyncdata.c linux-libre-3.2-gnu/drivers/isdn/gigaset/asyncdata.c
--- linux-libre-3.1-gnu/drivers/isdn/gigaset/asyncdata.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/gigaset/asyncdata.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include "gigaset.h"
 #include <linux/crc-ccitt.h>
 #include <linux/bitrev.h>
+#include <linux/export.h>
 
 /* check if byte must be stuffed/escaped
  * I'm not sure which data should be encoded.
diff -druN linux-libre-3.1-gnu/drivers/isdn/gigaset/capi.c linux-libre-3.2-gnu/drivers/isdn/gigaset/capi.c
--- linux-libre-3.1-gnu/drivers/isdn/gigaset/capi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/gigaset/capi.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/isdn/capilli.h>
 #include <linux/isdn/capicmd.h>
 #include <linux/isdn/capiutil.h>
+#include <linux/export.h>
 
 /* missing from kernelcapi.h */
 #define CapiNcpiNotSupportedByProtocol	0x0001
diff -druN linux-libre-3.1-gnu/drivers/isdn/gigaset/dummyll.c linux-libre-3.2-gnu/drivers/isdn/gigaset/dummyll.c
--- linux-libre-3.1-gnu/drivers/isdn/gigaset/dummyll.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/gigaset/dummyll.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  * =====================================================================
  */
 
+#include <linux/export.h>
 #include "gigaset.h"
 
 void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
diff -druN linux-libre-3.1-gnu/drivers/isdn/gigaset/ev-layer.c linux-libre-3.2-gnu/drivers/isdn/gigaset/ev-layer.c
--- linux-libre-3.1-gnu/drivers/isdn/gigaset/ev-layer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/gigaset/ev-layer.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  * =====================================================================
  */
 
+#include <linux/export.h>
 #include "gigaset.h"
 
 /* ========================================================== */
diff -druN linux-libre-3.1-gnu/drivers/isdn/gigaset/i4l.c linux-libre-3.2-gnu/drivers/isdn/gigaset/i4l.c
--- linux-libre-3.1-gnu/drivers/isdn/gigaset/i4l.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/gigaset/i4l.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 
 #include "gigaset.h"
 #include <linux/isdnif.h>
+#include <linux/export.h>
 
 #define SBUFSIZE	4096	/* sk_buff payload size */
 #define TRANSBUFSIZE	768	/* bytes per skb for transparent receive */
diff -druN linux-libre-3.1-gnu/drivers/isdn/gigaset/interface.c linux-libre-3.2-gnu/drivers/isdn/gigaset/interface.c
--- linux-libre-3.1-gnu/drivers/isdn/gigaset/interface.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/gigaset/interface.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include "gigaset.h"
 #include <linux/gigaset_dev.h>
 #include <linux/tty_flip.h>
+#include <linux/module.h>
 
 /*** our ioctls ***/
 
diff -druN linux-libre-3.1-gnu/drivers/isdn/hardware/mISDN/mISDNisar.c linux-libre-3.2-gnu/drivers/isdn/hardware/mISDN/mISDNisar.c
--- linux-libre-3.1-gnu/drivers/isdn/hardware/mISDN/mISDNisar.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/hardware/mISDN/mISDNisar.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
 #include <linux/mISDNhw.h>
+#include <linux/module.h>
 #include "isar.h"
 
 #define ISAR_REV	"2.1"
diff -druN linux-libre-3.1-gnu/drivers/isdn/hisax/callc.c linux-libre-3.2-gnu/drivers/isdn/hisax/callc.c
--- linux-libre-3.1-gnu/drivers/isdn/hisax/callc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/hisax/callc.c	2012-01-04 18:55:44.000000000 -0500
@@ -65,7 +65,7 @@
 	return (struct IsdnCardState *) 0;
 }
 
-static __attribute__((format(printf, 3, 4))) void
+static __printf(3, 4) void
 link_debug(struct Channel *chanp, int direction, char *fmt, ...)
 {
 	va_list args;
@@ -1068,7 +1068,7 @@
 	return 0;
 }
 
-static __attribute__((format(printf, 2, 3))) void
+static __printf(2, 3) void
 callc_debug(struct FsmInst *fi, char *fmt, ...)
 {
 	va_list args;
diff -druN linux-libre-3.1-gnu/drivers/isdn/hisax/hisax.h linux-libre-3.2-gnu/drivers/isdn/hisax/hisax.h
--- linux-libre-3.1-gnu/drivers/isdn/hisax/hisax.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/hisax/hisax.h	2012-01-04 18:55:44.000000000 -0500
@@ -1287,9 +1287,9 @@
 
 int HiSax_command(isdn_ctrl * ic);
 int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
-__attribute__((format(printf, 3, 4)))
+__printf(3, 4)
 void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
-__attribute__((format(printf, 3, 0)))
+__printf(3, 0)
 void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args);
 void HiSax_reportcard(int cardnr, int sel);
 int QuickHex(char *txt, u_char * p, int cnt);
diff -druN linux-libre-3.1-gnu/drivers/isdn/hisax/isdnl1.h linux-libre-3.2-gnu/drivers/isdn/hisax/isdnl1.h
--- linux-libre-3.1-gnu/drivers/isdn/hisax/isdnl1.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/hisax/isdnl1.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
 #define B_XMTBUFREADY	1
 #define B_ACKPENDING	2
 
-__attribute__((format(printf, 2, 3)))
+__printf(2, 3)
 void debugl1(struct IsdnCardState *cs, char *fmt, ...);
 void DChannel_proc_xmt(struct IsdnCardState *cs);
 void DChannel_proc_rcv(struct IsdnCardState *cs);
diff -druN linux-libre-3.1-gnu/drivers/isdn/hisax/isdnl3.c linux-libre-3.2-gnu/drivers/isdn/hisax/isdnl3.c
--- linux-libre-3.1-gnu/drivers/isdn/hisax/isdnl3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/hisax/isdnl3.c	2012-01-04 18:55:44.000000000 -0500
@@ -66,7 +66,7 @@
 	"EV_TIMEOUT",
 };
 
-static __attribute__((format(printf, 2, 3))) void
+static __printf(2, 3) void
 l3m_debug(struct FsmInst *fi, char *fmt, ...)
 {
 	va_list args;
diff -druN linux-libre-3.1-gnu/drivers/isdn/hisax/l3dss1.c linux-libre-3.2-gnu/drivers/isdn/hisax/l3dss1.c
--- linux-libre-3.1-gnu/drivers/isdn/hisax/l3dss1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/hisax/l3dss1.c	2012-01-04 18:55:44.000000000 -0500
@@ -353,7 +353,7 @@
 			         { l3dss1_dummy_invoke(st, cr, id, ident, p, nlen);
                                    return;
                                  } 
-#ifdef HISAX_DE_AOC
+#ifdef CONFIG_DE_AOC
 			{
 
 #define FOO1(s,a,b) \
@@ -422,9 +422,9 @@
 #undef FOO1
 
 			}
-#else  /* not HISAX_DE_AOC */
+#else  /* not CONFIG_DE_AOC */
                         l3_debug(st, "invoke break");
-#endif /* not HISAX_DE_AOC */
+#endif /* not CONFIG_DE_AOC */
 			break;
 		case 2:	/* return result */
 			 /* if no process available handle separately */ 
diff -druN linux-libre-3.1-gnu/drivers/isdn/hisax/st5481_d.c linux-libre-3.2-gnu/drivers/isdn/hisax/st5481_d.c
--- linux-libre-3.1-gnu/drivers/isdn/hisax/st5481_d.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/hisax/st5481_d.c	2012-01-04 18:55:44.000000000 -0500
@@ -167,7 +167,7 @@
 	{ST_L1_F8, EV_IND_RSY,           l1_ignore},
 };
 
-static __attribute__((format(printf, 2, 3)))
+static __printf(2, 3)
 void l1m_debug(struct FsmInst *fi, char *fmt, ...)
 {
 	va_list args;
@@ -270,7 +270,7 @@
 	"EV_DOUT_UNDERRUN",
 };
 
-static __attribute__((format(printf, 2, 3)))
+static __printf(2, 3)
 void dout_debug(struct FsmInst *fi, char *fmt, ...)
 {
 	va_list args;
diff -druN linux-libre-3.1-gnu/drivers/isdn/i4l/isdn_common.c linux-libre-3.2-gnu/drivers/isdn/i4l/isdn_common.c
--- linux-libre-3.1-gnu/drivers/isdn/i4l/isdn_common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/i4l/isdn_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -2308,11 +2308,11 @@
 	int i;
 	char tmprev[50];
 
-	if (!(dev = vmalloc(sizeof(isdn_dev)))) {
+	dev = vzalloc(sizeof(isdn_dev));
+	if (!dev) {
 		printk(KERN_WARNING "isdn: Could not allocate device-struct.\n");
 		return -EIO;
 	}
-	memset((char *) dev, 0, sizeof(isdn_dev));
 	init_timer(&dev->timer);
 	dev->timer.function = isdn_timer_funct;
 	spin_lock_init(&dev->lock);
diff -druN linux-libre-3.1-gnu/drivers/isdn/i4l/isdn_net.c linux-libre-3.2-gnu/drivers/isdn/i4l/isdn_net.c
--- linux-libre-3.1-gnu/drivers/isdn/i4l/isdn_net.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/i4l/isdn_net.c	2012-01-04 18:55:44.000000000 -0500
@@ -2756,6 +2756,9 @@
 			char *c,
 			*e;
 
+			if (strnlen(cfg->drvid, sizeof(cfg->drvid)) ==
+					sizeof(cfg->drvid))
+				return -EINVAL;
 			drvidx = -1;
 			chidx = -1;
 			strcpy(drvid, cfg->drvid);
diff -druN linux-libre-3.1-gnu/drivers/isdn/i4l/isdn_tty.c linux-libre-3.2-gnu/drivers/isdn/i4l/isdn_tty.c
--- linux-libre-3.1-gnu/drivers/isdn/i4l/isdn_tty.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/i4l/isdn_tty.c	2012-01-04 18:55:44.000000000 -0500
@@ -750,6 +750,7 @@
  * supplementary service (CAPI 2.0 part III)
  */
 #include <linux/isdn/capicmd.h>
+#include <linux/module.h>
 
 int
 isdn_tty_capi_facility(capi_msg *cm) {
@@ -1693,7 +1694,7 @@
 	 * line status register.
 	 */
 	if (info->flags & ISDN_ASYNC_INITIALIZED) {
-		tty_wait_until_sent(tty, 3000);	/* 30 seconds timeout */
+		tty_wait_until_sent_from_close(tty, 3000);	/* 30 seconds timeout */
 		/*
 		 * Before we drop DTR, make sure the UART transmitter
 		 * has completely drained; this is especially
diff -druN linux-libre-3.1-gnu/drivers/isdn/Kconfig linux-libre-3.2-gnu/drivers/isdn/Kconfig
--- linux-libre-3.1-gnu/drivers/isdn/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
 menuconfig ISDN
 	bool "ISDN support"
 	depends on NET
-	depends on !S390
+	depends on !S390 && !UML
 	---help---
 	  ISDN ("Integrated Services Digital Network", called RNIS in France)
 	  is a fully digital telephone service that can be used for voice and
diff -druN linux-libre-3.1-gnu/drivers/isdn/mISDN/clock.c linux-libre-3.2-gnu/drivers/isdn/mISDN/clock.c
--- linux-libre-3.1-gnu/drivers/isdn/mISDN/clock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/mISDN/clock.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,7 @@
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
 #include <linux/mISDNif.h>
+#include <linux/export.h>
 #include "core.h"
 
 static u_int *debug;
diff -druN linux-libre-3.1-gnu/drivers/isdn/mISDN/dsp_audio.c linux-libre-3.2-gnu/drivers/isdn/mISDN/dsp_audio.c
--- linux-libre-3.1-gnu/drivers/isdn/mISDN/dsp_audio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/mISDN/dsp_audio.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/delay.h>
 #include <linux/mISDNif.h>
 #include <linux/mISDNdsp.h>
+#include <linux/export.h>
 #include "core.h"
 #include "dsp.h"
 
diff -druN linux-libre-3.1-gnu/drivers/isdn/mISDN/dsp_core.c linux-libre-3.2-gnu/drivers/isdn/mISDN/dsp_core.c
--- linux-libre-3.1-gnu/drivers/isdn/mISDN/dsp_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/mISDN/dsp_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -1052,12 +1052,11 @@
 	if (crq->protocol != ISDN_P_B_L2DSP
 	 && crq->protocol != ISDN_P_B_L2DSPHDLC)
 		return -EPROTONOSUPPORT;
-	ndsp = vmalloc(sizeof(struct dsp));
+	ndsp = vzalloc(sizeof(struct dsp));
 	if (!ndsp) {
 		printk(KERN_ERR "%s: vmalloc struct dsp failed\n", __func__);
 		return -ENOMEM;
 	}
-	memset(ndsp, 0, sizeof(struct dsp));
 	if (dsp_debug & DEBUG_DSP_CTRL)
 		printk(KERN_DEBUG "%s: creating new dsp instance\n", __func__);
 
diff -druN linux-libre-3.1-gnu/drivers/isdn/mISDN/dsp_pipeline.c linux-libre-3.2-gnu/drivers/isdn/mISDN/dsp_pipeline.c
--- linux-libre-3.1-gnu/drivers/isdn/mISDN/dsp_pipeline.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/mISDN/dsp_pipeline.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/string.h>
 #include <linux/mISDNif.h>
 #include <linux/mISDNdsp.h>
+#include <linux/export.h>
 #include "dsp.h"
 #include "dsp_hwec.h"
 
diff -druN linux-libre-3.1-gnu/drivers/isdn/mISDN/l1oip_codec.c linux-libre-3.2-gnu/drivers/isdn/mISDN/l1oip_codec.c
--- linux-libre-3.1-gnu/drivers/isdn/mISDN/l1oip_codec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/mISDN/l1oip_codec.c	2012-01-04 18:55:44.000000000 -0500
@@ -330,14 +330,12 @@
 		return 0;
 
 	/* alloc conversion tables */
-	table_com = vmalloc(65536);
-	table_dec = vmalloc(512);
+	table_com = vzalloc(65536);
+	table_dec = vzalloc(512);
 	if (!table_com || !table_dec) {
 		l1oip_4bit_free();
 		return -ENOMEM;
 	}
-	memset(table_com, 0, 65536);
-	memset(table_dec, 0, 512);
 	/* generate compression table */
 	i1 = 0;
 	while (i1 < 256) {
diff -druN linux-libre-3.1-gnu/drivers/isdn/mISDN/socket.c linux-libre-3.2-gnu/drivers/isdn/mISDN/socket.c
--- linux-libre-3.1-gnu/drivers/isdn/mISDN/socket.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/isdn/mISDN/socket.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 
 #include <linux/mISDNif.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "core.h"
 
 static u_int	*debug;
diff -druN linux-libre-3.1-gnu/drivers/Kconfig linux-libre-3.2-gnu/drivers/Kconfig
--- linux-libre-3.1-gnu/drivers/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -56,6 +56,8 @@
 
 source "drivers/ptp/Kconfig"
 
+source "drivers/pinctrl/Kconfig"
+
 source "drivers/gpio/Kconfig"
 
 source "drivers/w1/Kconfig"
@@ -130,4 +132,8 @@
 
 source "drivers/virt/Kconfig"
 
+source "drivers/hv/Kconfig"
+
+source "drivers/devfreq/Kconfig"
+
 endmenu
diff -druN linux-libre-3.1-gnu/drivers/leds/dell-led.c linux-libre-3.2-gnu/drivers/leds/dell-led.c
--- linux-libre-3.1-gnu/drivers/leds/dell-led.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/dell-led.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/acpi.h>
 #include <linux/leds.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 MODULE_AUTHOR("Louis Davis/Jim Dailey");
 MODULE_DESCRIPTION("Dell LED Control Driver");
diff -druN linux-libre-3.1-gnu/drivers/leds/Kconfig linux-libre-3.2-gnu/drivers/leds/Kconfig
--- linux-libre-3.1-gnu/drivers/leds/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -113,14 +113,6 @@
 	help
 	  This option enables support for the PCEngines WRAP programmable LEDs.
 
-config LEDS_ALIX2
-	tristate "LED Support for ALIX.2 and ALIX.3 series"
-	depends on LEDS_CLASS
-	depends on X86 && !GPIO_CS5535 && !CS5535_GPIO
-	help
-	  This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs.
-	  You have to set leds-alix2.force=1 for boards with Award BIOS.
-
 config LEDS_COBALT_QUBE
 	tristate "LED Support for the Cobalt Qube series front LED"
 	depends on LEDS_CLASS
@@ -383,6 +375,18 @@
 	  cannot be used. This driver supports hardware blinking with an on+off
 	  period from 62ms to 125s. Say Y to enable LEDs on the HP iPAQ hx4700.
 
+config LEDS_RENESAS_TPU
+	bool "LED support for Renesas TPU"
+	depends on LEDS_CLASS && HAVE_CLK && GENERIC_GPIO
+	help
+	  This option enables build of the LED TPU platform driver,
+	  suitable to drive any TPU channel on newer Renesas SoCs.
+	  The driver controls the GPIO pin connected to the LED via
+	  the GPIO framework and expects the LED to be connected to
+	  a pin that can be driven in both GPIO mode and using TPU
+	  pin function. The latter to support brightness control.
+	  Brightness control is supported but hardware blinking is not.
+
 config LEDS_TRIGGERS
 	bool "LED Trigger support"
 	depends on LEDS_CLASS
@@ -400,7 +404,7 @@
 	  This allows LEDs to be controlled by a programmable timer
 	  via sysfs. Some LED hardware can be programmed to start
 	  blinking the LED without any further software interaction.
-	  For more details read Documentation/leds-class.txt.
+	  For more details read Documentation/leds/leds-class.txt.
 
 	  If unsure, say Y.
 
diff -druN linux-libre-3.1-gnu/drivers/leds/led-class.c linux-libre-3.2-gnu/drivers/leds/led-class.c
--- linux-libre-3.1-gnu/drivers/leds/led-class.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/led-class.c	2012-01-04 18:55:44.000000000 -0500
@@ -267,6 +267,8 @@
 		   unsigned long *delay_on,
 		   unsigned long *delay_off)
 {
+	del_timer_sync(&led_cdev->blink_timer);
+
 	if (led_cdev->blink_set &&
 	    !led_cdev->blink_set(led_cdev, delay_on, delay_off))
 		return;
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-88pm860x.c linux-libre-3.2-gnu/drivers/leds/leds-88pm860x.c
--- linux-libre-3.1-gnu/drivers/leds/leds-88pm860x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-88pm860x.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/mfd/88pm860x.h>
+#include <linux/module.h>
 
 #define LED_PWM_SHIFT		(3)
 #define LED_PWM_MASK		(0x1F)
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-alix2.c linux-libre-3.2-gnu/drivers/leds/leds-alix2.c
--- linux-libre-3.1-gnu/drivers/leds/leds-alix2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-alix2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,239 +0,0 @@
-/*
- * LEDs driver for PCEngines ALIX.2 and ALIX.3
- *
- * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
- */
-
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/leds.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-
-static int force = 0;
-module_param(force, bool, 0444);
-MODULE_PARM_DESC(force, "Assume system has ALIX.2/ALIX.3 style LEDs");
-
-#define MSR_LBAR_GPIO		0x5140000C
-#define CS5535_GPIO_SIZE	256
-
-static u32 gpio_base;
-
-static struct pci_device_id divil_pci[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_NS,  PCI_DEVICE_ID_NS_CS5535_ISA) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
-	{ } /* NULL entry */
-};
-MODULE_DEVICE_TABLE(pci, divil_pci);
-
-struct alix_led {
-	struct led_classdev cdev;
-	unsigned short port;
-	unsigned int on_value;
-	unsigned int off_value;
-};
-
-static void alix_led_set(struct led_classdev *led_cdev,
-			 enum led_brightness brightness)
-{
-	struct alix_led *led_dev =
-		container_of(led_cdev, struct alix_led, cdev);
-
-	if (brightness)
-		outl(led_dev->on_value, gpio_base + led_dev->port);
-	else
-		outl(led_dev->off_value, gpio_base + led_dev->port);
-}
-
-static struct alix_led alix_leds[] = {
-	{
-		.cdev = {
-			.name = "alix:1",
-			.brightness_set = alix_led_set,
-		},
-		.port = 0x00,
-		.on_value = 1 << 22,
-		.off_value = 1 << 6,
-	},
-	{
-		.cdev = {
-			.name = "alix:2",
-			.brightness_set = alix_led_set,
-		},
-		.port = 0x80,
-		.on_value = 1 << 25,
-		.off_value = 1 << 9,
-	},
-	{
-		.cdev = {
-			.name = "alix:3",
-			.brightness_set = alix_led_set,
-		},
-		.port = 0x80,
-		.on_value = 1 << 27,
-		.off_value = 1 << 11,
-	},
-};
-
-static int __init alix_led_probe(struct platform_device *pdev)
-{
-	int i;
-	int ret;
-
-	for (i = 0; i < ARRAY_SIZE(alix_leds); i++) {
-		alix_leds[i].cdev.flags |= LED_CORE_SUSPENDRESUME;
-		ret = led_classdev_register(&pdev->dev, &alix_leds[i].cdev);
-		if (ret < 0)
-			goto fail;
-	}
-	return 0;
-
-fail:
-	while (--i >= 0)
-		led_classdev_unregister(&alix_leds[i].cdev);
-	return ret;
-}
-
-static int alix_led_remove(struct platform_device *pdev)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(alix_leds); i++)
-		led_classdev_unregister(&alix_leds[i].cdev);
-	return 0;
-}
-
-static struct platform_driver alix_led_driver = {
-	.remove = alix_led_remove,
-	.driver = {
-		.name = KBUILD_MODNAME,
-		.owner = THIS_MODULE,
-	},
-};
-
-static int __init alix_present(unsigned long bios_phys,
-				const char *alix_sig,
-				size_t alix_sig_len)
-{
-	const size_t bios_len = 0x00010000;
-	const char *bios_virt;
-	const char *scan_end;
-	const char *p;
-	char name[64];
-
-	if (force) {
-		printk(KERN_NOTICE "%s: forced to skip BIOS test, "
-		       "assume system has ALIX.2 style LEDs\n",
-		       KBUILD_MODNAME);
-		return 1;
-	}
-
-	bios_virt = phys_to_virt(bios_phys);
-	scan_end = bios_virt + bios_len - (alix_sig_len + 2);
-	for (p = bios_virt; p < scan_end; p++) {
-		const char *tail;
-		char *a;
-
-		if (memcmp(p, alix_sig, alix_sig_len) != 0)
-			continue;
-
-		memcpy(name, p, sizeof(name));
-
-		/* remove the first \0 character from string */
-		a = strchr(name, '\0');
-		if (a)
-			*a = ' ';
-
-		/* cut the string at a newline */
-		a = strchr(name, '\r');
-		if (a)
-			*a = '\0';
-
-		tail = p + alix_sig_len;
-		if ((tail[0] == '2' || tail[0] == '3')) {
-			printk(KERN_INFO
-			       "%s: system is recognized as \"%s\"\n",
-			       KBUILD_MODNAME, name);
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-static struct platform_device *pdev;
-
-static int __init alix_pci_led_init(void)
-{
-	u32 low, hi;
-
-	if (pci_dev_present(divil_pci) == 0) {
-		printk(KERN_WARNING KBUILD_MODNAME": DIVIL not found\n");
-		return -ENODEV;
-	}
-
-	/* Grab the GPIO I/O range */
-	rdmsr(MSR_LBAR_GPIO, low, hi);
-
-	/* Check the mask and whether GPIO is enabled (sanity check) */
-	if (hi != 0x0000f001) {
-		printk(KERN_WARNING KBUILD_MODNAME": GPIO not enabled\n");
-		return -ENODEV;
-	}
-
-	/* Mask off the IO base address */
-	gpio_base = low & 0x0000ff00;
-
-	if (!request_region(gpio_base, CS5535_GPIO_SIZE, KBUILD_MODNAME)) {
-		printk(KERN_ERR KBUILD_MODNAME": can't allocate I/O for GPIO\n");
-		return -ENODEV;
-	}
-
-	/* Set GPIO function to output */
-	outl(1 << 6, gpio_base + 0x04);
-	outl(1 << 9, gpio_base + 0x84);
-	outl(1 << 11, gpio_base + 0x84);
-
-	return 0;
-}
-
-static int __init alix_led_init(void)
-{
-	int ret = -ENODEV;
-	const char tinybios_sig[] = "PC Engines ALIX.";
-	const char coreboot_sig[] = "PC Engines\0ALIX.";
-
-	if (alix_present(0xf0000, tinybios_sig, sizeof(tinybios_sig) - 1) ||
-	    alix_present(0x500, coreboot_sig, sizeof(coreboot_sig) - 1))
-		ret = alix_pci_led_init();
-
-	if (ret < 0)
-		return ret;
-
-	pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
-	if (!IS_ERR(pdev)) {
-		ret = platform_driver_probe(&alix_led_driver, alix_led_probe);
-		if (ret)
-			platform_device_unregister(pdev);
-	} else
-		ret = PTR_ERR(pdev);
-
-	return ret;
-}
-
-static void __exit alix_led_exit(void)
-{
-	platform_device_unregister(pdev);
-	platform_driver_unregister(&alix_led_driver);
-	release_region(gpio_base, CS5535_GPIO_SIZE);
-}
-
-module_init(alix_led_init);
-module_exit(alix_led_exit);
-
-MODULE_AUTHOR("Constantin Baranov <const@mimas.ru>");
-MODULE_DESCRIPTION("PCEngines ALIX.2 and ALIX.3 LED driver");
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-asic3.c linux-libre-3.2-gnu/drivers/leds/leds-asic3.c
--- linux-libre-3.1-gnu/drivers/leds/leds-asic3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-asic3.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 
 #include <linux/mfd/asic3.h>
 #include <linux/mfd/core.h>
+#include <linux/module.h>
 
 /*
  *	The HTC ASIC3 LED GPIOs are inputs, not outputs.
@@ -107,9 +108,10 @@
 	}
 
 	led->cdev->name = led->name;
-	led->cdev->default_trigger = led->default_trigger;
+	led->cdev->flags = LED_CORE_SUSPENDRESUME;
 	led->cdev->brightness_set = brightness_set;
 	led->cdev->blink_set = blink_set;
+	led->cdev->default_trigger = led->default_trigger;
 
 	ret = led_classdev_register(&pdev->dev, led->cdev);
 	if (ret < 0)
@@ -136,12 +138,44 @@
 	return mfd_cell_disable(pdev);
 }
 
+static int asic3_led_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	const struct mfd_cell *cell = mfd_get_cell(pdev);
+	int ret;
+
+	ret = 0;
+	if (cell->suspend)
+		ret = (*cell->suspend)(pdev);
+
+	return ret;
+}
+
+static int asic3_led_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	const struct mfd_cell *cell = mfd_get_cell(pdev);
+	int ret;
+
+	ret = 0;
+	if (cell->resume)
+		ret = (*cell->resume)(pdev);
+
+	return ret;
+}
+
+static const struct dev_pm_ops asic3_led_pm_ops = {
+	.suspend	= asic3_led_suspend,
+	.resume		= asic3_led_resume,
+};
+
 static struct platform_driver asic3_led_driver = {
 	.probe		= asic3_led_probe,
 	.remove		= __devexit_p(asic3_led_remove),
 	.driver		= {
 		.name	= "leds-asic3",
 		.owner	= THIS_MODULE,
+		.pm	= &asic3_led_pm_ops,
 	},
 };
 
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-atmel-pwm.c linux-libre-3.2-gnu/drivers/leds/leds-atmel-pwm.c
--- linux-libre-3.1-gnu/drivers/leds/leds-atmel-pwm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-atmel-pwm.c	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@
 #include <linux/io.h>
 #include <linux/atmel_pwm.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 
 struct pwmled {
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-cobalt-raq.c linux-libre-3.2-gnu/drivers/leds/leds-cobalt-raq.c
--- linux-libre-3.1-gnu/drivers/leds/leds-cobalt-raq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-cobalt-raq.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
+#include <linux/export.h>
 
 #define LED_WEB		0x04
 #define LED_POWER_OFF	0x08
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-fsg.c linux-libre-3.2-gnu/drivers/leds/leds-fsg.c
--- linux-libre-3.1-gnu/drivers/leds/leds-fsg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-fsg.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
+#include <linux/module.h>
 #include <mach/hardware.h>
 #include <asm/io.h>
 
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-gpio.c linux-libre-3.2-gnu/drivers/leds/leds-gpio.c
--- linux-libre-3.1-gnu/drivers/leds/leds-gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
+#include <linux/module.h>
 
 #include <asm/gpio.h>
 
@@ -121,7 +122,7 @@
 	}
 	led_dat->cdev.brightness_set = gpio_led_set;
 	if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP)
-		state = !!gpio_get_value(led_dat->gpio) ^ led_dat->active_low;
+		state = !!gpio_get_value_cansleep(led_dat->gpio) ^ led_dat->active_low;
 	else
 		state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
 	led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-lm3530.c linux-libre-3.2-gnu/drivers/leds/leds-lm3530.c
--- linux-libre-3.1-gnu/drivers/leds/leds-lm3530.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-lm3530.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/led-lm3530.h>
 #include <linux/types.h>
 #include <linux/regulator/consumer.h>
+#include <linux/module.h>
 
 #define LM3530_LED_DEV "lcd-backlight"
 #define LM3530_NAME "lm3530-led"
@@ -421,7 +422,6 @@
 err_reg_init:
 	regulator_put(drvdata->regulator);
 err_regulator_get:
-	i2c_set_clientdata(client, NULL);
 	kfree(drvdata);
 err_out:
 	return err;
@@ -449,7 +449,7 @@
 
 static struct i2c_driver lm3530_i2c_driver = {
 	.probe = lm3530_probe,
-	.remove = lm3530_remove,
+	.remove = __devexit_p(lm3530_remove),
 	.id_table = lm3530_id,
 	.driver = {
 		.name = LM3530_NAME,
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-locomo.c linux-libre-3.2-gnu/drivers/leds/leds-locomo.c
--- linux-libre-3.1-gnu/drivers/leds/leds-locomo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-locomo.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/device.h>
 #include <linux/leds.h>
 
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-lp5521.c linux-libre-3.2-gnu/drivers/leds/leds-lp5521.c
--- linux-libre-3.1-gnu/drivers/leds/leds-lp5521.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-lp5521.c	2012-01-04 18:55:44.000000000 -0500
@@ -97,6 +97,9 @@
 /* Status */
 #define LP5521_EXT_CLK_USED		0x08
 
+/* default R channel current register value */
+#define LP5521_REG_R_CURR_DEFAULT	0xAF
+
 struct lp5521_engine {
 	int		id;
 	u8		mode;
@@ -175,14 +178,14 @@
 		mode = LP5521_CMD_DIRECT;
 
 	ret = lp5521_read(client, LP5521_REG_OP_MODE, &engine_state);
+	if (ret < 0)
+		return ret;
 
 	/* set mode only for this engine */
 	engine_state &= ~(engine->engine_mask);
 	mode &= engine->engine_mask;
 	engine_state |= mode;
-	ret |= lp5521_write(client, LP5521_REG_OP_MODE, engine_state);
-
-	return ret;
+	return lp5521_write(client, LP5521_REG_OP_MODE, engine_state);
 }
 
 static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern)
@@ -643,6 +646,7 @@
 	struct lp5521_chip		*chip;
 	struct lp5521_platform_data	*pdata;
 	int ret, i, led;
+	u8 buf;
 
 	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (!chip)
@@ -681,6 +685,20 @@
 				     * Exact value is not available. 10 - 20ms
 				     * appears to be enough for reset.
 				     */
+
+	/*
+	 * Make sure that the chip is reset by reading back the r channel
+	 * current reg. This is dummy read is required on some platforms -
+	 * otherwise further access to the R G B channels in the
+	 * LP5521_REG_ENABLE register will not have any effect - strange!
+	 */
+	lp5521_read(client, LP5521_REG_R_CURRENT, &buf);
+	if (buf != LP5521_REG_R_CURR_DEFAULT) {
+		dev_err(&client->dev, "error in reseting chip\n");
+		goto fail2;
+	}
+	usleep_range(10000, 20000);
+
 	ret = lp5521_detect(client);
 
 	if (ret) {
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-lt3593.c linux-libre-3.2-gnu/drivers/leds/leds-lt3593.c
--- linux-libre-3.1-gnu/drivers/leds/leds-lt3593.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-lt3593.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 struct lt3593_led_data {
 	struct led_classdev cdev;
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-mc13783.c linux-libre-3.2-gnu/drivers/leds/leds-mc13783.c
--- linux-libre-3.1-gnu/drivers/leds/leds-mc13783.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-mc13783.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,13 +21,13 @@
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/workqueue.h>
-#include <linux/mfd/mc13783.h>
+#include <linux/mfd/mc13xxx.h>
 #include <linux/slab.h>
 
 struct mc13783_led {
 	struct led_classdev	cdev;
 	struct work_struct	work;
-	struct mc13783		*master;
+	struct mc13xxx		*master;
 	enum led_brightness	new_brightness;
 	int			id;
 };
@@ -111,11 +111,11 @@
 		break;
 	}
 
-	mc13783_lock(led->master);
+	mc13xxx_lock(led->master);
 
-	mc13783_reg_rmw(led->master, reg, mask, value);
+	mc13xxx_reg_rmw(led->master, reg, mask, value);
 
-	mc13783_unlock(led->master);
+	mc13xxx_unlock(led->master);
 }
 
 static void mc13783_led_set(struct led_classdev *led_cdev,
@@ -172,23 +172,23 @@
 		break;
 	}
 
-	mc13783_lock(led->master);
+	mc13xxx_lock(led->master);
 
-	ret = mc13783_reg_rmw(led->master, reg, mask << shift,
+	ret = mc13xxx_reg_rmw(led->master, reg, mask << shift,
 						value << shift);
 
-	mc13783_unlock(led->master);
+	mc13xxx_unlock(led->master);
 	return ret;
 }
 
 static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
 {
-	struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
-	struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
+	struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct mc13xxx *dev = dev_get_drvdata(pdev->dev.parent);
 	int ret = 0;
 	int reg = 0;
 
-	mc13783_lock(dev);
+	mc13xxx_lock(dev);
 
 	if (pdata->flags & MC13783_LED_TC1HALF)
 		reg |= MC13783_LED_C1_TC1HALF_BIT;
@@ -196,7 +196,7 @@
 	if (pdata->flags & MC13783_LED_SLEWLIMTC)
 		reg |= MC13783_LED_Cx_SLEWLIM_BIT;
 
-	ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_1, reg);
+	ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_1, reg);
 	if (ret)
 		goto out;
 
@@ -206,7 +206,7 @@
 	if (pdata->flags & MC13783_LED_SLEWLIMBL)
 		reg |= MC13783_LED_Cx_SLEWLIM_BIT;
 
-	ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_2, reg);
+	ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_2, reg);
 	if (ret)
 		goto out;
 
@@ -216,7 +216,7 @@
 	if (pdata->flags & MC13783_LED_TRIODE_TC1)
 		reg |= MC13783_LED_Cx_TRIODE_TC_BIT;
 
-	ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_3, reg);
+	ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_3, reg);
 	if (ret)
 		goto out;
 
@@ -226,7 +226,7 @@
 	if (pdata->flags & MC13783_LED_TRIODE_TC2)
 		reg |= MC13783_LED_Cx_TRIODE_TC_BIT;
 
-	ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_4, reg);
+	ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_4, reg);
 	if (ret)
 		goto out;
 
@@ -236,7 +236,7 @@
 	if (pdata->flags & MC13783_LED_TRIODE_TC3)
 		reg |= MC13783_LED_Cx_TRIODE_TC_BIT;
 
-	ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_5, reg);
+	ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_5, reg);
 	if (ret)
 		goto out;
 
@@ -255,17 +255,17 @@
 	reg |= (pdata->abref & MC13783_LED_C0_ABREF_MASK) <<
 							MC13783_LED_C0_ABREF;
 
-	ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_0, reg);
+	ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_0, reg);
 
 out:
-	mc13783_unlock(dev);
+	mc13xxx_unlock(dev);
 	return ret;
 }
 
 static int __devinit mc13783_led_probe(struct platform_device *pdev)
 {
-	struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
-	struct mc13783_led_platform_data *led_cur;
+	struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct mc13xxx_led_platform_data *led_cur;
 	struct mc13783_led *led, *led_dat;
 	int ret, i;
 	int init_led = 0;
@@ -351,9 +351,9 @@
 
 static int __devexit mc13783_led_remove(struct platform_device *pdev)
 {
-	struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct mc13783_led *led = platform_get_drvdata(pdev);
-	struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
+	struct mc13xxx *dev = dev_get_drvdata(pdev->dev.parent);
 	int i;
 
 	for (i = 0; i < pdata->num_leds; i++) {
@@ -361,16 +361,16 @@
 		cancel_work_sync(&led[i].work);
 	}
 
-	mc13783_lock(dev);
+	mc13xxx_lock(dev);
 
-	mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_0, 0);
-	mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_1, 0);
-	mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_2, 0);
-	mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_3, 0);
-	mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_4, 0);
-	mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_5, 0);
+	mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_0, 0);
+	mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_1, 0);
+	mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_2, 0);
+	mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_3, 0);
+	mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_4, 0);
+	mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_5, 0);
 
-	mc13783_unlock(dev);
+	mc13xxx_unlock(dev);
 
 	kfree(led);
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-net48xx.c linux-libre-3.2-gnu/drivers/leds/leds-net48xx.c
--- linux-libre-3.1-gnu/drivers/leds/leds-net48xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-net48xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <asm/io.h>
 #include <linux/nsc_gpio.h>
 #include <linux/scx200_gpio.h>
+#include <linux/module.h>
 
 #define DRVNAME "net48xx-led"
 #define NET48XX_ERROR_LED_GPIO	20
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-net5501.c linux-libre-3.2-gnu/drivers/leds/leds-net5501.c
--- linux-libre-3.1-gnu/drivers/leds/leds-net5501.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-net5501.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/leds.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/module.h>
 
 #include <asm/geode.h>
 
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-ns2.c linux-libre-3.2-gnu/drivers/leds/leds-ns2.c
--- linux-libre-3.1-gnu/drivers/leds/leds-ns2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-ns2.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
+#include <linux/module.h>
 #include <mach/leds-ns2.h>
 
 /*
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-renesas-tpu.c linux-libre-3.2-gnu/drivers/leds/leds-renesas-tpu.c
--- linux-libre-3.1-gnu/drivers/leds/leds-renesas-tpu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/leds/leds-renesas-tpu.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,357 @@
+/*
+ * LED control using Renesas TPU
+ *
+ *  Copyright (C) 2011 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/printk.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/leds.h>
+#include <linux/platform_data/leds-renesas-tpu.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/workqueue.h>
+
+enum r_tpu_pin { R_TPU_PIN_UNUSED, R_TPU_PIN_GPIO, R_TPU_PIN_GPIO_FN };
+enum r_tpu_timer { R_TPU_TIMER_UNUSED, R_TPU_TIMER_ON };
+
+struct r_tpu_priv {
+	struct led_classdev ldev;
+	void __iomem *mapbase;
+	struct clk *clk;
+	struct platform_device *pdev;
+	enum r_tpu_pin pin_state;
+	enum r_tpu_timer timer_state;
+	unsigned long min_rate;
+	unsigned int refresh_rate;
+	struct work_struct work;
+	enum led_brightness new_brightness;
+};
+
+static DEFINE_SPINLOCK(r_tpu_lock);
+
+#define TSTR -1 /* Timer start register (shared register) */
+#define TCR  0 /* Timer control register (+0x00) */
+#define TMDR 1 /* Timer mode register (+0x04) */
+#define TIOR 2 /* Timer I/O control register (+0x08) */
+#define TIER 3 /* Timer interrupt enable register (+0x0c) */
+#define TSR  4 /* Timer status register (+0x10) */
+#define TCNT 5 /* Timer counter (+0x14) */
+#define TGRA 6 /* Timer general register A (+0x18) */
+#define TGRB 7 /* Timer general register B (+0x1c) */
+#define TGRC 8 /* Timer general register C (+0x20) */
+#define TGRD 9 /* Timer general register D (+0x24) */
+
+static inline unsigned short r_tpu_read(struct r_tpu_priv *p, int reg_nr)
+{
+	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
+	void __iomem *base = p->mapbase;
+	unsigned long offs = reg_nr << 2;
+
+	if (reg_nr == TSTR)
+		return ioread16(base - cfg->channel_offset);
+
+	return ioread16(base + offs);
+}
+
+static inline void r_tpu_write(struct r_tpu_priv *p, int reg_nr,
+			       unsigned short value)
+{
+	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
+	void __iomem *base = p->mapbase;
+	unsigned long offs = reg_nr << 2;
+
+	if (reg_nr == TSTR) {
+		iowrite16(value, base - cfg->channel_offset);
+		return;
+	}
+
+	iowrite16(value, base + offs);
+}
+
+static void r_tpu_start_stop_ch(struct r_tpu_priv *p, int start)
+{
+	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
+	unsigned long flags, value;
+
+	/* start stop register shared by multiple timer channels */
+	spin_lock_irqsave(&r_tpu_lock, flags);
+	value = r_tpu_read(p, TSTR);
+
+	if (start)
+		value |= 1 << cfg->timer_bit;
+	else
+		value &= ~(1 << cfg->timer_bit);
+
+	r_tpu_write(p, TSTR, value);
+	spin_unlock_irqrestore(&r_tpu_lock, flags);
+}
+
+static int r_tpu_enable(struct r_tpu_priv *p, enum led_brightness brightness)
+{
+	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
+	int prescaler[] = { 1, 4, 16, 64 };
+	int k, ret;
+	unsigned long rate, tmp;
+
+	if (p->timer_state == R_TPU_TIMER_ON)
+		return 0;
+
+	/* wake up device and enable clock */
+	pm_runtime_get_sync(&p->pdev->dev);
+	ret = clk_enable(p->clk);
+	if (ret) {
+		dev_err(&p->pdev->dev, "cannot enable clock\n");
+		return ret;
+	}
+
+	/* make sure channel is disabled */
+	r_tpu_start_stop_ch(p, 0);
+
+	/* get clock rate after enabling it */
+	rate = clk_get_rate(p->clk);
+
+	/* pick the lowest acceptable rate */
+	for (k = 0; k < ARRAY_SIZE(prescaler); k++)
+		if ((rate / prescaler[k]) < p->min_rate)
+			break;
+
+	if (!k) {
+		dev_err(&p->pdev->dev, "clock rate mismatch\n");
+		goto err0;
+	}
+	dev_dbg(&p->pdev->dev, "rate = %lu, prescaler %u\n",
+		rate, prescaler[k - 1]);
+
+	/* clear TCNT on TGRB match, count on rising edge, set prescaler */
+	r_tpu_write(p, TCR, 0x0040 | (k - 1));
+
+	/* output 0 until TGRA, output 1 until TGRB */
+	r_tpu_write(p, TIOR, 0x0002);
+
+	rate /= prescaler[k - 1] * p->refresh_rate;
+	r_tpu_write(p, TGRB, rate);
+	dev_dbg(&p->pdev->dev, "TRGB = 0x%04lx\n", rate);
+
+	tmp = (cfg->max_brightness - brightness) * rate;
+	r_tpu_write(p, TGRA, tmp / cfg->max_brightness);
+	dev_dbg(&p->pdev->dev, "TRGA = 0x%04lx\n", tmp / cfg->max_brightness);
+
+	/* PWM mode */
+	r_tpu_write(p, TMDR, 0x0002);
+
+	/* enable channel */
+	r_tpu_start_stop_ch(p, 1);
+
+	p->timer_state = R_TPU_TIMER_ON;
+	return 0;
+ err0:
+	clk_disable(p->clk);
+	pm_runtime_put_sync(&p->pdev->dev);
+	return -ENOTSUPP;
+}
+
+static void r_tpu_disable(struct r_tpu_priv *p)
+{
+	if (p->timer_state == R_TPU_TIMER_UNUSED)
+		return;
+
+	/* disable channel */
+	r_tpu_start_stop_ch(p, 0);
+
+	/* stop clock and mark device as idle */
+	clk_disable(p->clk);
+	pm_runtime_put_sync(&p->pdev->dev);
+
+	p->timer_state = R_TPU_TIMER_UNUSED;
+}
+
+static void r_tpu_set_pin(struct r_tpu_priv *p, enum r_tpu_pin new_state,
+			  enum led_brightness brightness)
+{
+	struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
+
+	if (p->pin_state == new_state) {
+		if (p->pin_state == R_TPU_PIN_GPIO)
+			gpio_set_value(cfg->pin_gpio, brightness);
+		return;
+	}
+
+	if (p->pin_state == R_TPU_PIN_GPIO)
+		gpio_free(cfg->pin_gpio);
+
+	if (p->pin_state == R_TPU_PIN_GPIO_FN)
+		gpio_free(cfg->pin_gpio_fn);
+
+	if (new_state == R_TPU_PIN_GPIO) {
+		gpio_request(cfg->pin_gpio, cfg->name);
+		gpio_direction_output(cfg->pin_gpio, !!brightness);
+	}
+	if (new_state == R_TPU_PIN_GPIO_FN)
+		gpio_request(cfg->pin_gpio_fn, cfg->name);
+
+	p->pin_state = new_state;
+}
+
+static void r_tpu_work(struct work_struct *work)
+{
+	struct r_tpu_priv *p = container_of(work, struct r_tpu_priv, work);
+	enum led_brightness brightness = p->new_brightness;
+
+	r_tpu_disable(p);
+
+	/* off and maximum are handled as GPIO pins, in between PWM */
+	if ((brightness == 0) || (brightness == p->ldev.max_brightness))
+		r_tpu_set_pin(p, R_TPU_PIN_GPIO, brightness);
+	else {
+		r_tpu_set_pin(p, R_TPU_PIN_GPIO_FN, 0);
+		r_tpu_enable(p, brightness);
+	}
+}
+
+static void r_tpu_set_brightness(struct led_classdev *ldev,
+				 enum led_brightness brightness)
+{
+	struct r_tpu_priv *p = container_of(ldev, struct r_tpu_priv, ldev);
+	p->new_brightness = brightness;
+	schedule_work(&p->work);
+}
+
+static int __devinit r_tpu_probe(struct platform_device *pdev)
+{
+	struct led_renesas_tpu_config *cfg = pdev->dev.platform_data;
+	struct r_tpu_priv *p;
+	struct resource *res;
+	int ret = -ENXIO;
+
+	if (!cfg) {
+		dev_err(&pdev->dev, "missing platform data\n");
+		goto err0;
+	}
+
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
+	if (p == NULL) {
+		dev_err(&pdev->dev, "failed to allocate driver data\n");
+		ret = -ENOMEM;
+		goto err0;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get I/O memory\n");
+		goto err1;
+	}
+
+	/* map memory, let mapbase point to our channel */
+	p->mapbase = ioremap_nocache(res->start, resource_size(res));
+	if (p->mapbase == NULL) {
+		dev_err(&pdev->dev, "failed to remap I/O memory\n");
+		goto err1;
+	}
+
+	/* get hold of clock */
+	p->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(p->clk)) {
+		dev_err(&pdev->dev, "cannot get clock\n");
+		ret = PTR_ERR(p->clk);
+		goto err2;
+	}
+
+	p->pdev = pdev;
+	p->pin_state = R_TPU_PIN_UNUSED;
+	p->timer_state = R_TPU_TIMER_UNUSED;
+	p->refresh_rate = cfg->refresh_rate ? cfg->refresh_rate : 100;
+	r_tpu_set_pin(p, R_TPU_PIN_GPIO, LED_OFF);
+	platform_set_drvdata(pdev, p);
+
+	INIT_WORK(&p->work, r_tpu_work);
+
+	p->ldev.name = cfg->name;
+	p->ldev.brightness = LED_OFF;
+	p->ldev.max_brightness = cfg->max_brightness;
+	p->ldev.brightness_set = r_tpu_set_brightness;
+	p->ldev.flags |= LED_CORE_SUSPENDRESUME;
+	ret = led_classdev_register(&pdev->dev, &p->ldev);
+	if (ret < 0)
+		goto err3;
+
+	/* max_brightness may be updated by the LED core code */
+	p->min_rate = p->ldev.max_brightness * p->refresh_rate;
+
+	pm_runtime_enable(&pdev->dev);
+	return 0;
+
+ err3:
+	r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF);
+	clk_put(p->clk);
+ err2:
+	iounmap(p->mapbase);
+ err1:
+	kfree(p);
+ err0:
+	return ret;
+}
+
+static int __devexit r_tpu_remove(struct platform_device *pdev)
+{
+	struct r_tpu_priv *p = platform_get_drvdata(pdev);
+
+	r_tpu_set_brightness(&p->ldev, LED_OFF);
+	led_classdev_unregister(&p->ldev);
+	cancel_work_sync(&p->work);
+	r_tpu_disable(p);
+	r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF);
+
+	pm_runtime_disable(&pdev->dev);
+	clk_put(p->clk);
+
+	iounmap(p->mapbase);
+	kfree(p);
+	return 0;
+}
+
+static struct platform_driver r_tpu_device_driver = {
+	.probe		= r_tpu_probe,
+	.remove		= __devexit_p(r_tpu_remove),
+	.driver		= {
+		.name	= "leds-renesas-tpu",
+	}
+};
+
+static int __init r_tpu_init(void)
+{
+	return platform_driver_register(&r_tpu_device_driver);
+}
+
+static void __exit r_tpu_exit(void)
+{
+	platform_driver_unregister(&r_tpu_device_driver);
+}
+
+module_init(r_tpu_init);
+module_exit(r_tpu_exit);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("Renesas TPU LED Driver");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-s3c24xx.c linux-libre-3.2-gnu/drivers/leds/leds-s3c24xx.c
--- linux-libre-3.1-gnu/drivers/leds/leds-s3c24xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-s3c24xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/leds.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include <mach/hardware.h>
 #include <mach/regs-gpio.h>
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-wm831x-status.c linux-libre-3.2-gnu/drivers/leds/leds-wm831x-status.c
--- linux-libre-3.1-gnu/drivers/leds/leds-wm831x-status.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-wm831x-status.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/mfd/wm831x/core.h>
 #include <linux/mfd/wm831x/pdata.h>
 #include <linux/mfd/wm831x/status.h>
+#include <linux/module.h>
 
 
 struct wm831x_status {
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-wm8350.c linux-libre-3.2-gnu/drivers/leds/leds-wm8350.c
--- linux-libre-3.1-gnu/drivers/leds/leds-wm8350.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-wm8350.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/mfd/wm8350/pmic.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 /* Microamps */
 static const int isink_cur[] = {
diff -druN linux-libre-3.1-gnu/drivers/leds/leds-wrap.c linux-libre-3.2-gnu/drivers/leds/leds-wrap.c
--- linux-libre-3.1-gnu/drivers/leds/leds-wrap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/leds-wrap.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/err.h>
 #include <asm/io.h>
 #include <linux/scx200_gpio.h>
+#include <linux/module.h>
 
 #define DRVNAME "wrap-led"
 #define WRAP_POWER_LED_GPIO	2
diff -druN linux-libre-3.1-gnu/drivers/leds/led-triggers.c linux-libre-3.2-gnu/drivers/leds/led-triggers.c
--- linux-libre-3.1-gnu/drivers/leds/led-triggers.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/led-triggers.c	2012-01-04 18:55:44.000000000 -0500
@@ -261,9 +261,12 @@
 	if (trigger) {
 		trigger->name = name;
 		err = led_trigger_register(trigger);
-		if (err < 0)
+		if (err < 0) {
+			kfree(trigger);
+			trigger = NULL;
 			printk(KERN_WARNING "LED trigger %s failed to register"
 				" (%d)\n", name, err);
+		}
 	} else
 		printk(KERN_WARNING "LED trigger %s failed to register"
 			" (no memory)\n", name);
diff -druN linux-libre-3.1-gnu/drivers/leds/Makefile linux-libre-3.2-gnu/drivers/leds/Makefile
--- linux-libre-3.1-gnu/drivers/leds/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/leds/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,6 @@
 obj-$(CONFIG_LEDS_NET48XX)		+= leds-net48xx.o
 obj-$(CONFIG_LEDS_NET5501)		+= leds-net5501.o
 obj-$(CONFIG_LEDS_WRAP)			+= leds-wrap.o
-obj-$(CONFIG_LEDS_ALIX2)		+= leds-alix2.o
 obj-$(CONFIG_LEDS_COBALT_QUBE)		+= leds-cobalt-qube.o
 obj-$(CONFIG_LEDS_COBALT_RAQ)		+= leds-cobalt-raq.o
 obj-$(CONFIG_LEDS_SUNFIRE)		+= leds-sunfire.o
@@ -43,6 +42,7 @@
 obj-$(CONFIG_LEDS_NS2)			+= leds-ns2.o
 obj-$(CONFIG_LEDS_NETXBIG)		+= leds-netxbig.o
 obj-$(CONFIG_LEDS_ASIC3)		+= leds-asic3.o
+obj-$(CONFIG_LEDS_RENESAS_TPU)		+= leds-renesas-tpu.o
 
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_DAC124S085)		+= leds-dac124s085.o
diff -druN linux-libre-3.1-gnu/drivers/lguest/core.c linux-libre-3.2-gnu/drivers/lguest/core.c
--- linux-libre-3.1-gnu/drivers/lguest/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/lguest/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -232,6 +232,13 @@
 			}
 		}
 
+		/*
+		 * All long-lived kernel loops need to check with this horrible
+		 * thing called the freezer.  If the Host is trying to suspend,
+		 * it stops us.
+		 */
+		try_to_freeze();
+
 		/* Check for signals */
 		if (signal_pending(current))
 			return -ERESTARTSYS;
@@ -246,13 +253,6 @@
 			try_deliver_interrupt(cpu, irq, more);
 
 		/*
-		 * All long-lived kernel loops need to check with this horrible
-		 * thing called the freezer.  If the Host is trying to suspend,
-		 * it stops us.
-		 */
-		try_to_freeze();
-
-		/*
 		 * Just make absolutely sure the Guest is still alive.  One of
 		 * those hypercalls could have been fatal, for example.
 		 */
@@ -313,7 +313,7 @@
 	int err;
 
 	/* Lguest can't run under Xen, VMI or itself.  It does Tricky Stuff. */
-	if (paravirt_enabled()) {
+	if (get_kernel_rpl() != 0) {
 		printk("lguest is afraid of being a guest\n");
 		return -EPERM;
 	}
diff -druN linux-libre-3.1-gnu/drivers/lguest/lguest_device.c linux-libre-3.2-gnu/drivers/lguest/lguest_device.c
--- linux-libre-3.1-gnu/drivers/lguest/lguest_device.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/lguest/lguest_device.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/virtio_ring.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/paravirt.h>
diff -druN linux-libre-3.1-gnu/drivers/lguest/lguest_user.c linux-libre-3.2-gnu/drivers/lguest/lguest_user.c
--- linux-libre-3.1-gnu/drivers/lguest/lguest_user.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/lguest/lguest_user.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/eventfd.h>
 #include <linux/file.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "lg.h"
 
 /*L:056
diff -druN linux-libre-3.1-gnu/drivers/macintosh/via-macii.c linux-libre-3.2-gnu/drivers/macintosh/via-macii.c
--- linux-libre-3.1-gnu/drivers/macintosh/via-macii.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/macintosh/via-macii.c	2012-01-04 18:55:44.000000000 -0500
@@ -159,7 +159,7 @@
 	err = macii_init_via();
 	if (err) goto out;
 
-	err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB",
+	err = request_irq(IRQ_MAC_ADB, macii_interrupt, 0, "ADB",
 			  macii_interrupt);
 	if (err) goto out;
 
diff -druN linux-libre-3.1-gnu/drivers/macintosh/via-maciisi.c linux-libre-3.2-gnu/drivers/macintosh/via-maciisi.c
--- linux-libre-3.1-gnu/drivers/macintosh/via-maciisi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/macintosh/via-maciisi.c	2012-01-04 18:55:44.000000000 -0500
@@ -122,8 +122,8 @@
 		return err;
 	}
 
-	if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, IRQ_FLG_LOCK | IRQ_FLG_FAST, 
-			"ADB", maciisi_interrupt)) {
+	if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, 0, "ADB",
+			maciisi_interrupt)) {
 		printk(KERN_ERR "maciisi_init: can't get irq %d\n", IRQ_MAC_ADB);
 		return -EAGAIN;
 	}
diff -druN linux-libre-3.1-gnu/drivers/Makefile linux-libre-3.2-gnu/drivers/Makefile
--- linux-libre-3.1-gnu/drivers/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,8 @@
 # Rewritten to use lists instead of if-statements.
 #
 
+# GPIO must come after pinctrl as gpios may need to mux pins etc
+obj-y				+= pinctrl/
 obj-y				+= gpio/
 obj-$(CONFIG_PCI)		+= pci/
 obj-$(CONFIG_PARISC)		+= parisc/
@@ -127,3 +129,6 @@
 
 # Virtualization drivers
 obj-$(CONFIG_VIRT_DRIVERS)	+= virt/
+obj-$(CONFIG_HYPERV)		+= hv/
+
+obj-$(CONFIG_PM_DEVFREQ)	+= devfreq/
diff -druN linux-libre-3.1-gnu/drivers/md/bitmap.c linux-libre-3.2-gnu/drivers/md/bitmap.c
--- linux-libre-3.1-gnu/drivers/md/bitmap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/bitmap.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,35 +29,6 @@
 #include "md.h"
 #include "bitmap.h"
 
-/* debug macros */
-
-#define DEBUG 0
-
-#if DEBUG
-/* these are for debugging purposes only! */
-
-/* define one and only one of these */
-#define INJECT_FAULTS_1 0 /* cause bitmap_alloc_page to fail always */
-#define INJECT_FAULTS_2 0 /* cause bitmap file to be kicked when first bit set*/
-#define INJECT_FAULTS_3 0 /* treat bitmap file as kicked at init time */
-#define INJECT_FAULTS_4 0 /* undef */
-#define INJECT_FAULTS_5 0 /* undef */
-#define INJECT_FAULTS_6 0
-
-/* if these are defined, the driver will fail! debug only */
-#define INJECT_FATAL_FAULT_1 0 /* fail kmalloc, causing bitmap_create to fail */
-#define INJECT_FATAL_FAULT_2 0 /* undef */
-#define INJECT_FATAL_FAULT_3 0 /* undef */
-#endif
-
-#ifndef PRINTK
-#  if DEBUG > 0
-#    define PRINTK(x...) printk(KERN_DEBUG x)
-#  else
-#    define PRINTK(x...)
-#  endif
-#endif
-
 static inline char *bmname(struct bitmap *bitmap)
 {
 	return bitmap->mddev ? mdname(bitmap->mddev) : "mdX";
@@ -70,16 +41,12 @@
 {
 	unsigned char *page;
 
-#ifdef INJECT_FAULTS_1
-	page = NULL;
-#else
 	page = kzalloc(PAGE_SIZE, GFP_NOIO);
-#endif
 	if (!page)
 		printk("%s: bitmap_alloc_page FAILED\n", bmname(bitmap));
 	else
-		PRINTK("%s: bitmap_alloc_page: allocated page at %p\n",
-			bmname(bitmap), page);
+		pr_debug("%s: bitmap_alloc_page: allocated page at %p\n",
+			 bmname(bitmap), page);
 	return page;
 }
 
@@ -88,7 +55,7 @@
  */
 static void bitmap_free_page(struct bitmap *bitmap, unsigned char *page)
 {
-	PRINTK("%s: bitmap_free_page: free page %p\n", bmname(bitmap), page);
+	pr_debug("%s: bitmap_free_page: free page %p\n", bmname(bitmap), page);
 	kfree(page);
 }
 
@@ -133,8 +100,8 @@
 	spin_lock_irq(&bitmap->lock);
 
 	if (mappage == NULL) {
-		PRINTK("%s: bitmap map page allocation failed, hijacking\n",
-			bmname(bitmap));
+		pr_debug("%s: bitmap map page allocation failed, hijacking\n",
+			 bmname(bitmap));
 		/* failed - set the hijacked flag so that we can use the
 		 * pointer as a counter */
 		if (!bitmap->bp[page].map)
@@ -187,13 +154,13 @@
  */
 
 /* IO operations when bitmap is stored near all superblocks */
-static struct page *read_sb_page(mddev_t *mddev, loff_t offset,
+static struct page *read_sb_page(struct mddev *mddev, loff_t offset,
 				 struct page *page,
 				 unsigned long index, int size)
 {
 	/* choose a good rdev and read the page from there */
 
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	sector_t target;
 	int did_alloc = 0;
 
@@ -226,7 +193,7 @@
 
 }
 
-static mdk_rdev_t *next_active_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
+static struct md_rdev *next_active_rdev(struct md_rdev *rdev, struct mddev *mddev)
 {
 	/* Iterate the disks of an mddev, using rcu to protect access to the
 	 * linked list, and raising the refcount of devices we return to ensure
@@ -247,7 +214,7 @@
 		pos = &rdev->same_set;
 	}
 	list_for_each_continue_rcu(pos, &mddev->disks) {
-		rdev = list_entry(pos, mdk_rdev_t, same_set);
+		rdev = list_entry(pos, struct md_rdev, same_set);
 		if (rdev->raid_disk >= 0 &&
 		    !test_bit(Faulty, &rdev->flags)) {
 			/* this is a usable devices */
@@ -262,9 +229,9 @@
 
 static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
 {
-	mdk_rdev_t *rdev = NULL;
+	struct md_rdev *rdev = NULL;
 	struct block_device *bdev;
-	mddev_t *mddev = bitmap->mddev;
+	struct mddev *mddev = bitmap->mddev;
 
 	while ((rdev = next_active_rdev(rdev, mddev)) != NULL) {
 		int size = PAGE_SIZE;
@@ -409,8 +376,8 @@
 	struct buffer_head *bh;
 	sector_t block;
 
-	PRINTK("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE,
-			(unsigned long long)index << PAGE_SHIFT);
+	pr_debug("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE,
+		 (unsigned long long)index << PAGE_SHIFT);
 
 	page = alloc_page(GFP_KERNEL);
 	if (!page)
@@ -868,7 +835,8 @@
 
 enum bitmap_page_attr {
 	BITMAP_PAGE_DIRTY = 0,     /* there are set bits that need to be synced */
-	BITMAP_PAGE_CLEAN = 1,     /* there are bits that might need to be cleared */
+	BITMAP_PAGE_PENDING = 1,   /* there are bits that are being cleaned.
+				    * i.e. counter is 1 or 2. */
 	BITMAP_PAGE_NEEDWRITE = 2, /* there are cleared bits that need to be synced */
 };
 
@@ -919,7 +887,7 @@
 	else
 		__set_bit_le(bit, kaddr);
 	kunmap_atomic(kaddr, KM_USER0);
-	PRINTK("set file bit %lu page %lu\n", bit, page->index);
+	pr_debug("set file bit %lu page %lu\n", bit, page->index);
 	/* record page number so it gets flushed to disk when unplug occurs */
 	set_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
 }
@@ -997,11 +965,7 @@
 
 	BUG_ON(!file && !bitmap->mddev->bitmap_info.offset);
 
-#ifdef INJECT_FAULTS_3
-	outofdate = 1;
-#else
 	outofdate = bitmap->flags & BITMAP_STALE;
-#endif
 	if (outofdate)
 		printk(KERN_INFO "%s: bitmap file is out of date, doing full "
 			"recovery\n", bmname(bitmap));
@@ -1111,7 +1075,6 @@
 					       (sector_t)i << CHUNK_BLOCK_SHIFT(bitmap),
 					       needed);
 			bit_cnt++;
-			set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
 		}
 	}
 
@@ -1143,9 +1106,12 @@
 	 */
 	int i;
 
+	spin_lock_irq(&bitmap->lock);
 	for (i = 0; i < bitmap->file_pages; i++)
 		set_page_attr(bitmap, bitmap->filemap[i],
 			      BITMAP_PAGE_NEEDWRITE);
+	bitmap->allclean = 0;
+	spin_unlock_irq(&bitmap->lock);
 }
 
 static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc)
@@ -1164,7 +1130,7 @@
  *			out to disk
  */
 
-void bitmap_daemon_work(mddev_t *mddev)
+void bitmap_daemon_work(struct mddev *mddev)
 {
 	struct bitmap *bitmap;
 	unsigned long j;
@@ -1204,17 +1170,15 @@
 
 		if (page != lastpage) {
 			/* skip this page unless it's marked as needing cleaning */
-			if (!test_page_attr(bitmap, page, BITMAP_PAGE_CLEAN)) {
+			if (!test_page_attr(bitmap, page, BITMAP_PAGE_PENDING)) {
 				int need_write = test_page_attr(bitmap, page,
 								BITMAP_PAGE_NEEDWRITE);
 				if (need_write)
 					clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
 
 				spin_unlock_irqrestore(&bitmap->lock, flags);
-				if (need_write) {
+				if (need_write)
 					write_page(bitmap, page, 0);
-					bitmap->allclean = 0;
-				}
 				spin_lock_irqsave(&bitmap->lock, flags);
 				j |= (PAGE_BITS - 1);
 				continue;
@@ -1222,12 +1186,16 @@
 
 			/* grab the new page, sync and release the old */
 			if (lastpage != NULL) {
-				if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) {
-					clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+				if (test_page_attr(bitmap, lastpage,
+						   BITMAP_PAGE_NEEDWRITE)) {
+					clear_page_attr(bitmap, lastpage,
+							BITMAP_PAGE_NEEDWRITE);
 					spin_unlock_irqrestore(&bitmap->lock, flags);
 					write_page(bitmap, lastpage, 0);
 				} else {
-					set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+					set_page_attr(bitmap, lastpage,
+						      BITMAP_PAGE_NEEDWRITE);
+					bitmap->allclean = 0;
 					spin_unlock_irqrestore(&bitmap->lock, flags);
 				}
 			} else
@@ -1249,19 +1217,17 @@
 			}
 			spin_lock_irqsave(&bitmap->lock, flags);
 			if (!bitmap->need_sync)
-				clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+				clear_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
+			else
+				bitmap->allclean = 0;
 		}
 		bmc = bitmap_get_counter(bitmap,
 					 (sector_t)j << CHUNK_BLOCK_SHIFT(bitmap),
 					 &blocks, 0);
-		if (bmc) {
-			if (*bmc)
-				bitmap->allclean = 0;
-
-			if (*bmc == 2) {
-				*bmc = 1; /* maybe clear the bit next time */
-				set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
-			} else if (*bmc == 1 && !bitmap->need_sync) {
+		if (!bmc)
+			j |= PAGE_COUNTER_MASK;
+		else if (*bmc) {
+			if (*bmc == 1 && !bitmap->need_sync) {
 				/* we can clear the bit */
 				*bmc = 0;
 				bitmap_count_page(bitmap,
@@ -1275,13 +1241,16 @@
 						  paddr);
 				else
 					__clear_bit_le(
-							file_page_offset(bitmap,
-									 j),
-							paddr);
+						file_page_offset(bitmap,
+								 j),
+						paddr);
 				kunmap_atomic(paddr, KM_USER0);
+			} else if (*bmc <= 2) {
+				*bmc = 1; /* maybe clear the bit next time */
+				set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
+				bitmap->allclean = 0;
 			}
-		} else
-			j |= PAGE_COUNTER_MASK;
+		}
 	}
 	spin_unlock_irqrestore(&bitmap->lock, flags);
 
@@ -1294,6 +1263,7 @@
 			write_page(bitmap, lastpage, 0);
 		} else {
 			set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+			bitmap->allclean = 0;
 			spin_unlock_irqrestore(&bitmap->lock, flags);
 		}
 	}
@@ -1359,8 +1329,8 @@
 		if (bw > bitmap->behind_writes_used)
 			bitmap->behind_writes_used = bw;
 
-		PRINTK(KERN_DEBUG "inc write-behind count %d/%d\n",
-		       bw, bitmap->max_write_behind);
+		pr_debug("inc write-behind count %d/%lu\n",
+			 bw, bitmap->mddev->bitmap_info.max_write_behind);
 	}
 
 	while (sectors) {
@@ -1407,7 +1377,6 @@
 		else
 			sectors = 0;
 	}
-	bitmap->allclean = 0;
 	return 0;
 }
 EXPORT_SYMBOL(bitmap_startwrite);
@@ -1420,12 +1389,10 @@
 	if (behind) {
 		if (atomic_dec_and_test(&bitmap->behind_writes))
 			wake_up(&bitmap->behind_wait);
-		PRINTK(KERN_DEBUG "dec write-behind count %d/%d\n",
-		  atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
+		pr_debug("dec write-behind count %d/%lu\n",
+			 atomic_read(&bitmap->behind_writes),
+			 bitmap->mddev->bitmap_info.max_write_behind);
 	}
-	if (bitmap->mddev->degraded)
-		/* Never clear bits or update events_cleared when degraded */
-		success = 0;
 
 	while (sectors) {
 		sector_t blocks;
@@ -1439,7 +1406,7 @@
 			return;
 		}
 
-		if (success &&
+		if (success && !bitmap->mddev->degraded &&
 		    bitmap->events_cleared < bitmap->mddev->events) {
 			bitmap->events_cleared = bitmap->mddev->events;
 			bitmap->need_sync = 1;
@@ -1453,13 +1420,14 @@
 			wake_up(&bitmap->overflow_wait);
 
 		(*bmc)--;
-		if (*bmc <= 2)
+		if (*bmc <= 2) {
 			set_page_attr(bitmap,
 				      filemap_get_page(
 					      bitmap,
 					      offset >> CHUNK_BLOCK_SHIFT(bitmap)),
-				      BITMAP_PAGE_CLEAN);
-
+				      BITMAP_PAGE_PENDING);
+			bitmap->allclean = 0;
+		}
 		spin_unlock_irqrestore(&bitmap->lock, flags);
 		offset += blocks;
 		if (sectors > blocks)
@@ -1495,7 +1463,6 @@
 		}
 	}
 	spin_unlock_irq(&bitmap->lock);
-	bitmap->allclean = 0;
 	return rv;
 }
 
@@ -1543,15 +1510,16 @@
 		if (!NEEDED(*bmc) && aborted)
 			*bmc |= NEEDED_MASK;
 		else {
-			if (*bmc <= 2)
+			if (*bmc <= 2) {
 				set_page_attr(bitmap,
 					      filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)),
-					      BITMAP_PAGE_CLEAN);
+					      BITMAP_PAGE_PENDING);
+				bitmap->allclean = 0;
+			}
 		}
 	}
  unlock:
 	spin_unlock_irqrestore(&bitmap->lock, flags);
-	bitmap->allclean = 0;
 }
 EXPORT_SYMBOL(bitmap_end_sync);
 
@@ -1622,10 +1590,10 @@
 		*bmc = 1 | (needed ? NEEDED_MASK : 0);
 		bitmap_count_page(bitmap, offset, 1);
 		page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
-		set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+		set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
+		bitmap->allclean = 0;
 	}
 	spin_unlock_irq(&bitmap->lock);
-	bitmap->allclean = 0;
 }
 
 /* dirty the memory and file bits for bitmap chunks "s" to "e" */
@@ -1636,7 +1604,9 @@
 	for (chunk = s; chunk <= e; chunk++) {
 		sector_t sec = (sector_t)chunk << CHUNK_BLOCK_SHIFT(bitmap);
 		bitmap_set_memory_bits(bitmap, sec, 1);
+		spin_lock_irq(&bitmap->lock);
 		bitmap_file_set_bit(bitmap, sec);
+		spin_unlock_irq(&bitmap->lock);
 		if (sec < bitmap->mddev->recovery_cp)
 			/* We are asserting that the array is dirty,
 			 * so move the recovery_cp address back so
@@ -1649,7 +1619,7 @@
 /*
  * flush out any pending updates
  */
-void bitmap_flush(mddev_t *mddev)
+void bitmap_flush(struct mddev *mddev)
 {
 	struct bitmap *bitmap = mddev->bitmap;
 	long sleep;
@@ -1697,7 +1667,7 @@
 	kfree(bitmap);
 }
 
-void bitmap_destroy(mddev_t *mddev)
+void bitmap_destroy(struct mddev *mddev)
 {
 	struct bitmap *bitmap = mddev->bitmap;
 
@@ -1720,7 +1690,7 @@
  * initialize the bitmap structure
  * if this returns an error, bitmap_destroy must be called to do clean up
  */
-int bitmap_create(mddev_t *mddev)
+int bitmap_create(struct mddev *mddev)
 {
 	struct bitmap *bitmap;
 	sector_t blocks = mddev->resync_max_sectors;
@@ -1802,11 +1772,8 @@
 	bitmap->pages = pages;
 	bitmap->missing_pages = pages;
 
-#ifdef INJECT_FATAL_FAULT_1
-	bitmap->bp = NULL;
-#else
 	bitmap->bp = kzalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
-#endif
+
 	err = -ENOMEM;
 	if (!bitmap->bp)
 		goto error;
@@ -1824,7 +1791,7 @@
 	return err;
 }
 
-int bitmap_load(mddev_t *mddev)
+int bitmap_load(struct mddev *mddev)
 {
 	int err = 0;
 	sector_t start = 0;
@@ -1870,7 +1837,7 @@
 EXPORT_SYMBOL_GPL(bitmap_load);
 
 static ssize_t
-location_show(mddev_t *mddev, char *page)
+location_show(struct mddev *mddev, char *page)
 {
 	ssize_t len;
 	if (mddev->bitmap_info.file)
@@ -1884,7 +1851,7 @@
 }
 
 static ssize_t
-location_store(mddev_t *mddev, const char *buf, size_t len)
+location_store(struct mddev *mddev, const char *buf, size_t len)
 {
 
 	if (mddev->pers) {
@@ -1961,7 +1928,7 @@
 __ATTR(location, S_IRUGO|S_IWUSR, location_show, location_store);
 
 static ssize_t
-timeout_show(mddev_t *mddev, char *page)
+timeout_show(struct mddev *mddev, char *page)
 {
 	ssize_t len;
 	unsigned long secs = mddev->bitmap_info.daemon_sleep / HZ;
@@ -1975,7 +1942,7 @@
 }
 
 static ssize_t
-timeout_store(mddev_t *mddev, const char *buf, size_t len)
+timeout_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	/* timeout can be set at any time */
 	unsigned long timeout;
@@ -2011,13 +1978,13 @@
 __ATTR(time_base, S_IRUGO|S_IWUSR, timeout_show, timeout_store);
 
 static ssize_t
-backlog_show(mddev_t *mddev, char *page)
+backlog_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%lu\n", mddev->bitmap_info.max_write_behind);
 }
 
 static ssize_t
-backlog_store(mddev_t *mddev, const char *buf, size_t len)
+backlog_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	unsigned long backlog;
 	int rv = strict_strtoul(buf, 10, &backlog);
@@ -2033,13 +2000,13 @@
 __ATTR(backlog, S_IRUGO|S_IWUSR, backlog_show, backlog_store);
 
 static ssize_t
-chunksize_show(mddev_t *mddev, char *page)
+chunksize_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%lu\n", mddev->bitmap_info.chunksize);
 }
 
 static ssize_t
-chunksize_store(mddev_t *mddev, const char *buf, size_t len)
+chunksize_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	/* Can only be changed when no bitmap is active */
 	int rv;
@@ -2059,13 +2026,13 @@
 static struct md_sysfs_entry bitmap_chunksize =
 __ATTR(chunksize, S_IRUGO|S_IWUSR, chunksize_show, chunksize_store);
 
-static ssize_t metadata_show(mddev_t *mddev, char *page)
+static ssize_t metadata_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%s\n", (mddev->bitmap_info.external
 				      ? "external" : "internal"));
 }
 
-static ssize_t metadata_store(mddev_t *mddev, const char *buf, size_t len)
+static ssize_t metadata_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	if (mddev->bitmap ||
 	    mddev->bitmap_info.file ||
@@ -2083,7 +2050,7 @@
 static struct md_sysfs_entry bitmap_metadata =
 __ATTR(metadata, S_IRUGO|S_IWUSR, metadata_show, metadata_store);
 
-static ssize_t can_clear_show(mddev_t *mddev, char *page)
+static ssize_t can_clear_show(struct mddev *mddev, char *page)
 {
 	int len;
 	if (mddev->bitmap)
@@ -2094,7 +2061,7 @@
 	return len;
 }
 
-static ssize_t can_clear_store(mddev_t *mddev, const char *buf, size_t len)
+static ssize_t can_clear_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	if (mddev->bitmap == NULL)
 		return -ENOENT;
@@ -2113,7 +2080,7 @@
 __ATTR(can_clear, S_IRUGO|S_IWUSR, can_clear_show, can_clear_store);
 
 static ssize_t
-behind_writes_used_show(mddev_t *mddev, char *page)
+behind_writes_used_show(struct mddev *mddev, char *page)
 {
 	if (mddev->bitmap == NULL)
 		return sprintf(page, "0\n");
@@ -2122,7 +2089,7 @@
 }
 
 static ssize_t
-behind_writes_used_reset(mddev_t *mddev, const char *buf, size_t len)
+behind_writes_used_reset(struct mddev *mddev, const char *buf, size_t len)
 {
 	if (mddev->bitmap)
 		mddev->bitmap->behind_writes_used = 0;
diff -druN linux-libre-3.1-gnu/drivers/md/bitmap.h linux-libre-3.2-gnu/drivers/md/bitmap.h
--- linux-libre-3.1-gnu/drivers/md/bitmap.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/bitmap.h	2012-01-04 18:55:44.000000000 -0500
@@ -193,7 +193,7 @@
 	unsigned long pages; /* total number of pages in the bitmap */
 	unsigned long missing_pages; /* number of pages not yet allocated */
 
-	mddev_t *mddev; /* the md device that the bitmap is for */
+	struct mddev *mddev; /* the md device that the bitmap is for */
 
 	/* bitmap chunksize -- how much data does each bit represent? */
 	unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */
@@ -238,10 +238,10 @@
 /* the bitmap API */
 
 /* these are used only by md/bitmap */
-int  bitmap_create(mddev_t *mddev);
-int bitmap_load(mddev_t *mddev);
-void bitmap_flush(mddev_t *mddev);
-void bitmap_destroy(mddev_t *mddev);
+int  bitmap_create(struct mddev *mddev);
+int bitmap_load(struct mddev *mddev);
+void bitmap_flush(struct mddev *mddev);
+void bitmap_destroy(struct mddev *mddev);
 
 void bitmap_print_sb(struct bitmap *bitmap);
 void bitmap_update_sb(struct bitmap *bitmap);
@@ -262,7 +262,7 @@
 void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector);
 
 void bitmap_unplug(struct bitmap *bitmap);
-void bitmap_daemon_work(mddev_t *mddev);
+void bitmap_daemon_work(struct mddev *mddev);
 #endif
 
 #endif
diff -druN linux-libre-3.1-gnu/drivers/md/dm-bufio.c linux-libre-3.2-gnu/drivers/md/dm-bufio.c
--- linux-libre-3.1-gnu/drivers/md/dm-bufio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/dm-bufio.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1700 @@
+/*
+ * Copyright (C) 2009-2011 Red Hat, Inc.
+ *
+ * Author: Mikulas Patocka <mpatocka@redhat.com>
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-bufio.h"
+
+#include <linux/device-mapper.h>
+#include <linux/dm-io.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/version.h>
+#include <linux/shrinker.h>
+#include <linux/module.h>
+
+#define DM_MSG_PREFIX "bufio"
+
+/*
+ * Memory management policy:
+ *	Limit the number of buffers to DM_BUFIO_MEMORY_PERCENT of main memory
+ *	or DM_BUFIO_VMALLOC_PERCENT of vmalloc memory (whichever is lower).
+ *	Always allocate at least DM_BUFIO_MIN_BUFFERS buffers.
+ *	Start background writeback when there are DM_BUFIO_WRITEBACK_PERCENT
+ *	dirty buffers.
+ */
+#define DM_BUFIO_MIN_BUFFERS		8
+
+#define DM_BUFIO_MEMORY_PERCENT		2
+#define DM_BUFIO_VMALLOC_PERCENT	25
+#define DM_BUFIO_WRITEBACK_PERCENT	75
+
+/*
+ * Check buffer ages in this interval (seconds)
+ */
+#define DM_BUFIO_WORK_TIMER_SECS	10
+
+/*
+ * Free buffers when they are older than this (seconds)
+ */
+#define DM_BUFIO_DEFAULT_AGE_SECS	60
+
+/*
+ * The number of bvec entries that are embedded directly in the buffer.
+ * If the chunk size is larger, dm-io is used to do the io.
+ */
+#define DM_BUFIO_INLINE_VECS		16
+
+/*
+ * Buffer hash
+ */
+#define DM_BUFIO_HASH_BITS	20
+#define DM_BUFIO_HASH(block) \
+	((((block) >> DM_BUFIO_HASH_BITS) ^ (block)) & \
+	 ((1 << DM_BUFIO_HASH_BITS) - 1))
+
+/*
+ * Don't try to use kmem_cache_alloc for blocks larger than this.
+ * For explanation, see alloc_buffer_data below.
+ */
+#define DM_BUFIO_BLOCK_SIZE_SLAB_LIMIT	(PAGE_SIZE >> 1)
+#define DM_BUFIO_BLOCK_SIZE_GFP_LIMIT	(PAGE_SIZE << (MAX_ORDER - 1))
+
+/*
+ * dm_buffer->list_mode
+ */
+#define LIST_CLEAN	0
+#define LIST_DIRTY	1
+#define LIST_SIZE	2
+
+/*
+ * Linking of buffers:
+ *	All buffers are linked to cache_hash with their hash_list field.
+ *
+ *	Clean buffers that are not being written (B_WRITING not set)
+ *	are linked to lru[LIST_CLEAN] with their lru_list field.
+ *
+ *	Dirty and clean buffers that are being written are linked to
+ *	lru[LIST_DIRTY] with their lru_list field. When the write
+ *	finishes, the buffer cannot be relinked immediately (because we
+ *	are in an interrupt context and relinking requires process
+ *	context), so some clean-not-writing buffers can be held on
+ *	dirty_lru too.  They are later added to lru in the process
+ *	context.
+ */
+struct dm_bufio_client {
+	struct mutex lock;
+
+	struct list_head lru[LIST_SIZE];
+	unsigned long n_buffers[LIST_SIZE];
+
+	struct block_device *bdev;
+	unsigned block_size;
+	unsigned char sectors_per_block_bits;
+	unsigned char pages_per_block_bits;
+	unsigned char blocks_per_page_bits;
+	unsigned aux_size;
+	void (*alloc_callback)(struct dm_buffer *);
+	void (*write_callback)(struct dm_buffer *);
+
+	struct dm_io_client *dm_io;
+
+	struct list_head reserved_buffers;
+	unsigned need_reserved_buffers;
+
+	struct hlist_head *cache_hash;
+	wait_queue_head_t free_buffer_wait;
+
+	int async_write_error;
+
+	struct list_head client_list;
+	struct shrinker shrinker;
+};
+
+/*
+ * Buffer state bits.
+ */
+#define B_READING	0
+#define B_WRITING	1
+#define B_DIRTY		2
+
+/*
+ * Describes how the block was allocated:
+ * kmem_cache_alloc(), __get_free_pages() or vmalloc().
+ * See the comment at alloc_buffer_data.
+ */
+enum data_mode {
+	DATA_MODE_SLAB = 0,
+	DATA_MODE_GET_FREE_PAGES = 1,
+	DATA_MODE_VMALLOC = 2,
+	DATA_MODE_LIMIT = 3
+};
+
+struct dm_buffer {
+	struct hlist_node hash_list;
+	struct list_head lru_list;
+	sector_t block;
+	void *data;
+	enum data_mode data_mode;
+	unsigned char list_mode;		/* LIST_* */
+	unsigned hold_count;
+	int read_error;
+	int write_error;
+	unsigned long state;
+	unsigned long last_accessed;
+	struct dm_bufio_client *c;
+	struct bio bio;
+	struct bio_vec bio_vec[DM_BUFIO_INLINE_VECS];
+};
+
+/*----------------------------------------------------------------*/
+
+static struct kmem_cache *dm_bufio_caches[PAGE_SHIFT - SECTOR_SHIFT];
+static char *dm_bufio_cache_names[PAGE_SHIFT - SECTOR_SHIFT];
+
+static inline int dm_bufio_cache_index(struct dm_bufio_client *c)
+{
+	unsigned ret = c->blocks_per_page_bits - 1;
+
+	BUG_ON(ret >= ARRAY_SIZE(dm_bufio_caches));
+
+	return ret;
+}
+
+#define DM_BUFIO_CACHE(c)	(dm_bufio_caches[dm_bufio_cache_index(c)])
+#define DM_BUFIO_CACHE_NAME(c)	(dm_bufio_cache_names[dm_bufio_cache_index(c)])
+
+#define dm_bufio_in_request()	(!!current->bio_list)
+
+static void dm_bufio_lock(struct dm_bufio_client *c)
+{
+	mutex_lock_nested(&c->lock, dm_bufio_in_request());
+}
+
+static int dm_bufio_trylock(struct dm_bufio_client *c)
+{
+	return mutex_trylock(&c->lock);
+}
+
+static void dm_bufio_unlock(struct dm_bufio_client *c)
+{
+	mutex_unlock(&c->lock);
+}
+
+/*
+ * FIXME Move to sched.h?
+ */
+#ifdef CONFIG_PREEMPT_VOLUNTARY
+#  define dm_bufio_cond_resched()		\
+do {						\
+	if (unlikely(need_resched()))		\
+		_cond_resched();		\
+} while (0)
+#else
+#  define dm_bufio_cond_resched()                do { } while (0)
+#endif
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Default cache size: available memory divided by the ratio.
+ */
+static unsigned long dm_bufio_default_cache_size;
+
+/*
+ * Total cache size set by the user.
+ */
+static unsigned long dm_bufio_cache_size;
+
+/*
+ * A copy of dm_bufio_cache_size because dm_bufio_cache_size can change
+ * at any time.  If it disagrees, the user has changed cache size.
+ */
+static unsigned long dm_bufio_cache_size_latch;
+
+static DEFINE_SPINLOCK(param_spinlock);
+
+/*
+ * Buffers are freed after this timeout
+ */
+static unsigned dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS;
+
+static unsigned long dm_bufio_peak_allocated;
+static unsigned long dm_bufio_allocated_kmem_cache;
+static unsigned long dm_bufio_allocated_get_free_pages;
+static unsigned long dm_bufio_allocated_vmalloc;
+static unsigned long dm_bufio_current_allocated;
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Per-client cache: dm_bufio_cache_size / dm_bufio_client_count
+ */
+static unsigned long dm_bufio_cache_size_per_client;
+
+/*
+ * The current number of clients.
+ */
+static int dm_bufio_client_count;
+
+/*
+ * The list of all clients.
+ */
+static LIST_HEAD(dm_bufio_all_clients);
+
+/*
+ * This mutex protects dm_bufio_cache_size_latch,
+ * dm_bufio_cache_size_per_client and dm_bufio_client_count
+ */
+static DEFINE_MUTEX(dm_bufio_clients_lock);
+
+/*----------------------------------------------------------------*/
+
+static void adjust_total_allocated(enum data_mode data_mode, long diff)
+{
+	static unsigned long * const class_ptr[DATA_MODE_LIMIT] = {
+		&dm_bufio_allocated_kmem_cache,
+		&dm_bufio_allocated_get_free_pages,
+		&dm_bufio_allocated_vmalloc,
+	};
+
+	spin_lock(&param_spinlock);
+
+	*class_ptr[data_mode] += diff;
+
+	dm_bufio_current_allocated += diff;
+
+	if (dm_bufio_current_allocated > dm_bufio_peak_allocated)
+		dm_bufio_peak_allocated = dm_bufio_current_allocated;
+
+	spin_unlock(&param_spinlock);
+}
+
+/*
+ * Change the number of clients and recalculate per-client limit.
+ */
+static void __cache_size_refresh(void)
+{
+	BUG_ON(!mutex_is_locked(&dm_bufio_clients_lock));
+	BUG_ON(dm_bufio_client_count < 0);
+
+	dm_bufio_cache_size_latch = dm_bufio_cache_size;
+
+	barrier();
+
+	/*
+	 * Use default if set to 0 and report the actual cache size used.
+	 */
+	if (!dm_bufio_cache_size_latch) {
+		(void)cmpxchg(&dm_bufio_cache_size, 0,
+			      dm_bufio_default_cache_size);
+		dm_bufio_cache_size_latch = dm_bufio_default_cache_size;
+	}
+
+	dm_bufio_cache_size_per_client = dm_bufio_cache_size_latch /
+					 (dm_bufio_client_count ? : 1);
+}
+
+/*
+ * Allocating buffer data.
+ *
+ * Small buffers are allocated with kmem_cache, to use space optimally.
+ *
+ * For large buffers, we choose between get_free_pages and vmalloc.
+ * Each has advantages and disadvantages.
+ *
+ * __get_free_pages can randomly fail if the memory is fragmented.
+ * __vmalloc won't randomly fail, but vmalloc space is limited (it may be
+ * as low as 128M) so using it for caching is not appropriate.
+ *
+ * If the allocation may fail we use __get_free_pages. Memory fragmentation
+ * won't have a fatal effect here, but it just causes flushes of some other
+ * buffers and more I/O will be performed. Don't use __get_free_pages if it
+ * always fails (i.e. order >= MAX_ORDER).
+ *
+ * If the allocation shouldn't fail we use __vmalloc. This is only for the
+ * initial reserve allocation, so there's no risk of wasting all vmalloc
+ * space.
+ */
+static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask,
+			       enum data_mode *data_mode)
+{
+	if (c->block_size <= DM_BUFIO_BLOCK_SIZE_SLAB_LIMIT) {
+		*data_mode = DATA_MODE_SLAB;
+		return kmem_cache_alloc(DM_BUFIO_CACHE(c), gfp_mask);
+	}
+
+	if (c->block_size <= DM_BUFIO_BLOCK_SIZE_GFP_LIMIT &&
+	    gfp_mask & __GFP_NORETRY) {
+		*data_mode = DATA_MODE_GET_FREE_PAGES;
+		return (void *)__get_free_pages(gfp_mask,
+						c->pages_per_block_bits);
+	}
+
+	*data_mode = DATA_MODE_VMALLOC;
+	return __vmalloc(c->block_size, gfp_mask, PAGE_KERNEL);
+}
+
+/*
+ * Free buffer's data.
+ */
+static void free_buffer_data(struct dm_bufio_client *c,
+			     void *data, enum data_mode data_mode)
+{
+	switch (data_mode) {
+	case DATA_MODE_SLAB:
+		kmem_cache_free(DM_BUFIO_CACHE(c), data);
+		break;
+
+	case DATA_MODE_GET_FREE_PAGES:
+		free_pages((unsigned long)data, c->pages_per_block_bits);
+		break;
+
+	case DATA_MODE_VMALLOC:
+		vfree(data);
+		break;
+
+	default:
+		DMCRIT("dm_bufio_free_buffer_data: bad data mode: %d",
+		       data_mode);
+		BUG();
+	}
+}
+
+/*
+ * Allocate buffer and its data.
+ */
+static struct dm_buffer *alloc_buffer(struct dm_bufio_client *c, gfp_t gfp_mask)
+{
+	struct dm_buffer *b = kmalloc(sizeof(struct dm_buffer) + c->aux_size,
+				      gfp_mask);
+
+	if (!b)
+		return NULL;
+
+	b->c = c;
+
+	b->data = alloc_buffer_data(c, gfp_mask, &b->data_mode);
+	if (!b->data) {
+		kfree(b);
+		return NULL;
+	}
+
+	adjust_total_allocated(b->data_mode, (long)c->block_size);
+
+	return b;
+}
+
+/*
+ * Free buffer and its data.
+ */
+static void free_buffer(struct dm_buffer *b)
+{
+	struct dm_bufio_client *c = b->c;
+
+	adjust_total_allocated(b->data_mode, -(long)c->block_size);
+
+	free_buffer_data(c, b->data, b->data_mode);
+	kfree(b);
+}
+
+/*
+ * Link buffer to the hash list and clean or dirty queue.
+ */
+static void __link_buffer(struct dm_buffer *b, sector_t block, int dirty)
+{
+	struct dm_bufio_client *c = b->c;
+
+	c->n_buffers[dirty]++;
+	b->block = block;
+	b->list_mode = dirty;
+	list_add(&b->lru_list, &c->lru[dirty]);
+	hlist_add_head(&b->hash_list, &c->cache_hash[DM_BUFIO_HASH(block)]);
+	b->last_accessed = jiffies;
+}
+
+/*
+ * Unlink buffer from the hash list and dirty or clean queue.
+ */
+static void __unlink_buffer(struct dm_buffer *b)
+{
+	struct dm_bufio_client *c = b->c;
+
+	BUG_ON(!c->n_buffers[b->list_mode]);
+
+	c->n_buffers[b->list_mode]--;
+	hlist_del(&b->hash_list);
+	list_del(&b->lru_list);
+}
+
+/*
+ * Place the buffer to the head of dirty or clean LRU queue.
+ */
+static void __relink_lru(struct dm_buffer *b, int dirty)
+{
+	struct dm_bufio_client *c = b->c;
+
+	BUG_ON(!c->n_buffers[b->list_mode]);
+
+	c->n_buffers[b->list_mode]--;
+	c->n_buffers[dirty]++;
+	b->list_mode = dirty;
+	list_del(&b->lru_list);
+	list_add(&b->lru_list, &c->lru[dirty]);
+}
+
+/*----------------------------------------------------------------
+ * Submit I/O on the buffer.
+ *
+ * Bio interface is faster but it has some problems:
+ *	the vector list is limited (increasing this limit increases
+ *	memory-consumption per buffer, so it is not viable);
+ *
+ *	the memory must be direct-mapped, not vmalloced;
+ *
+ *	the I/O driver can reject requests spuriously if it thinks that
+ *	the requests are too big for the device or if they cross a
+ *	controller-defined memory boundary.
+ *
+ * If the buffer is small enough (up to DM_BUFIO_INLINE_VECS pages) and
+ * it is not vmalloced, try using the bio interface.
+ *
+ * If the buffer is big, if it is vmalloced or if the underlying device
+ * rejects the bio because it is too large, use dm-io layer to do the I/O.
+ * The dm-io layer splits the I/O into multiple requests, avoiding the above
+ * shortcomings.
+ *--------------------------------------------------------------*/
+
+/*
+ * dm-io completion routine. It just calls b->bio.bi_end_io, pretending
+ * that the request was handled directly with bio interface.
+ */
+static void dmio_complete(unsigned long error, void *context)
+{
+	struct dm_buffer *b = context;
+
+	b->bio.bi_end_io(&b->bio, error ? -EIO : 0);
+}
+
+static void use_dmio(struct dm_buffer *b, int rw, sector_t block,
+		     bio_end_io_t *end_io)
+{
+	int r;
+	struct dm_io_request io_req = {
+		.bi_rw = rw,
+		.notify.fn = dmio_complete,
+		.notify.context = b,
+		.client = b->c->dm_io,
+	};
+	struct dm_io_region region = {
+		.bdev = b->c->bdev,
+		.sector = block << b->c->sectors_per_block_bits,
+		.count = b->c->block_size >> SECTOR_SHIFT,
+	};
+
+	if (b->data_mode != DATA_MODE_VMALLOC) {
+		io_req.mem.type = DM_IO_KMEM;
+		io_req.mem.ptr.addr = b->data;
+	} else {
+		io_req.mem.type = DM_IO_VMA;
+		io_req.mem.ptr.vma = b->data;
+	}
+
+	b->bio.bi_end_io = end_io;
+
+	r = dm_io(&io_req, 1, &region, NULL);
+	if (r)
+		end_io(&b->bio, r);
+}
+
+static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block,
+			   bio_end_io_t *end_io)
+{
+	char *ptr;
+	int len;
+
+	bio_init(&b->bio);
+	b->bio.bi_io_vec = b->bio_vec;
+	b->bio.bi_max_vecs = DM_BUFIO_INLINE_VECS;
+	b->bio.bi_sector = block << b->c->sectors_per_block_bits;
+	b->bio.bi_bdev = b->c->bdev;
+	b->bio.bi_end_io = end_io;
+
+	/*
+	 * We assume that if len >= PAGE_SIZE ptr is page-aligned.
+	 * If len < PAGE_SIZE the buffer doesn't cross page boundary.
+	 */
+	ptr = b->data;
+	len = b->c->block_size;
+
+	if (len >= PAGE_SIZE)
+		BUG_ON((unsigned long)ptr & (PAGE_SIZE - 1));
+	else
+		BUG_ON((unsigned long)ptr & (len - 1));
+
+	do {
+		if (!bio_add_page(&b->bio, virt_to_page(ptr),
+				  len < PAGE_SIZE ? len : PAGE_SIZE,
+				  virt_to_phys(ptr) & (PAGE_SIZE - 1))) {
+			BUG_ON(b->c->block_size <= PAGE_SIZE);
+			use_dmio(b, rw, block, end_io);
+			return;
+		}
+
+		len -= PAGE_SIZE;
+		ptr += PAGE_SIZE;
+	} while (len > 0);
+
+	submit_bio(rw, &b->bio);
+}
+
+static void submit_io(struct dm_buffer *b, int rw, sector_t block,
+		      bio_end_io_t *end_io)
+{
+	if (rw == WRITE && b->c->write_callback)
+		b->c->write_callback(b);
+
+	if (b->c->block_size <= DM_BUFIO_INLINE_VECS * PAGE_SIZE &&
+	    b->data_mode != DATA_MODE_VMALLOC)
+		use_inline_bio(b, rw, block, end_io);
+	else
+		use_dmio(b, rw, block, end_io);
+}
+
+/*----------------------------------------------------------------
+ * Writing dirty buffers
+ *--------------------------------------------------------------*/
+
+/*
+ * The endio routine for write.
+ *
+ * Set the error, clear B_WRITING bit and wake anyone who was waiting on
+ * it.
+ */
+static void write_endio(struct bio *bio, int error)
+{
+	struct dm_buffer *b = container_of(bio, struct dm_buffer, bio);
+
+	b->write_error = error;
+	if (error) {
+		struct dm_bufio_client *c = b->c;
+		(void)cmpxchg(&c->async_write_error, 0, error);
+	}
+
+	BUG_ON(!test_bit(B_WRITING, &b->state));
+
+	smp_mb__before_clear_bit();
+	clear_bit(B_WRITING, &b->state);
+	smp_mb__after_clear_bit();
+
+	wake_up_bit(&b->state, B_WRITING);
+}
+
+/*
+ * This function is called when wait_on_bit is actually waiting.
+ */
+static int do_io_schedule(void *word)
+{
+	io_schedule();
+
+	return 0;
+}
+
+/*
+ * Initiate a write on a dirty buffer, but don't wait for it.
+ *
+ * - If the buffer is not dirty, exit.
+ * - If there some previous write going on, wait for it to finish (we can't
+ *   have two writes on the same buffer simultaneously).
+ * - Submit our write and don't wait on it. We set B_WRITING indicating
+ *   that there is a write in progress.
+ */
+static void __write_dirty_buffer(struct dm_buffer *b)
+{
+	if (!test_bit(B_DIRTY, &b->state))
+		return;
+
+	clear_bit(B_DIRTY, &b->state);
+	wait_on_bit_lock(&b->state, B_WRITING,
+			 do_io_schedule, TASK_UNINTERRUPTIBLE);
+
+	submit_io(b, WRITE, b->block, write_endio);
+}
+
+/*
+ * Wait until any activity on the buffer finishes.  Possibly write the
+ * buffer if it is dirty.  When this function finishes, there is no I/O
+ * running on the buffer and the buffer is not dirty.
+ */
+static void __make_buffer_clean(struct dm_buffer *b)
+{
+	BUG_ON(b->hold_count);
+
+	if (!b->state)	/* fast case */
+		return;
+
+	wait_on_bit(&b->state, B_READING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+	__write_dirty_buffer(b);
+	wait_on_bit(&b->state, B_WRITING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+}
+
+/*
+ * Find some buffer that is not held by anybody, clean it, unlink it and
+ * return it.
+ */
+static struct dm_buffer *__get_unclaimed_buffer(struct dm_bufio_client *c)
+{
+	struct dm_buffer *b;
+
+	list_for_each_entry_reverse(b, &c->lru[LIST_CLEAN], lru_list) {
+		BUG_ON(test_bit(B_WRITING, &b->state));
+		BUG_ON(test_bit(B_DIRTY, &b->state));
+
+		if (!b->hold_count) {
+			__make_buffer_clean(b);
+			__unlink_buffer(b);
+			return b;
+		}
+		dm_bufio_cond_resched();
+	}
+
+	list_for_each_entry_reverse(b, &c->lru[LIST_DIRTY], lru_list) {
+		BUG_ON(test_bit(B_READING, &b->state));
+
+		if (!b->hold_count) {
+			__make_buffer_clean(b);
+			__unlink_buffer(b);
+			return b;
+		}
+		dm_bufio_cond_resched();
+	}
+
+	return NULL;
+}
+
+/*
+ * Wait until some other threads free some buffer or release hold count on
+ * some buffer.
+ *
+ * This function is entered with c->lock held, drops it and regains it
+ * before exiting.
+ */
+static void __wait_for_free_buffer(struct dm_bufio_client *c)
+{
+	DECLARE_WAITQUEUE(wait, current);
+
+	add_wait_queue(&c->free_buffer_wait, &wait);
+	set_task_state(current, TASK_UNINTERRUPTIBLE);
+	dm_bufio_unlock(c);
+
+	io_schedule();
+
+	set_task_state(current, TASK_RUNNING);
+	remove_wait_queue(&c->free_buffer_wait, &wait);
+
+	dm_bufio_lock(c);
+}
+
+/*
+ * Allocate a new buffer. If the allocation is not possible, wait until
+ * some other thread frees a buffer.
+ *
+ * May drop the lock and regain it.
+ */
+static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client *c)
+{
+	struct dm_buffer *b;
+
+	/*
+	 * dm-bufio is resistant to allocation failures (it just keeps
+	 * one buffer reserved in cases all the allocations fail).
+	 * So set flags to not try too hard:
+	 *	GFP_NOIO: don't recurse into the I/O layer
+	 *	__GFP_NORETRY: don't retry and rather return failure
+	 *	__GFP_NOMEMALLOC: don't use emergency reserves
+	 *	__GFP_NOWARN: don't print a warning in case of failure
+	 *
+	 * For debugging, if we set the cache size to 1, no new buffers will
+	 * be allocated.
+	 */
+	while (1) {
+		if (dm_bufio_cache_size_latch != 1) {
+			b = alloc_buffer(c, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
+			if (b)
+				return b;
+		}
+
+		if (!list_empty(&c->reserved_buffers)) {
+			b = list_entry(c->reserved_buffers.next,
+				       struct dm_buffer, lru_list);
+			list_del(&b->lru_list);
+			c->need_reserved_buffers++;
+
+			return b;
+		}
+
+		b = __get_unclaimed_buffer(c);
+		if (b)
+			return b;
+
+		__wait_for_free_buffer(c);
+	}
+}
+
+static struct dm_buffer *__alloc_buffer_wait(struct dm_bufio_client *c)
+{
+	struct dm_buffer *b = __alloc_buffer_wait_no_callback(c);
+
+	if (c->alloc_callback)
+		c->alloc_callback(b);
+
+	return b;
+}
+
+/*
+ * Free a buffer and wake other threads waiting for free buffers.
+ */
+static void __free_buffer_wake(struct dm_buffer *b)
+{
+	struct dm_bufio_client *c = b->c;
+
+	if (!c->need_reserved_buffers)
+		free_buffer(b);
+	else {
+		list_add(&b->lru_list, &c->reserved_buffers);
+		c->need_reserved_buffers--;
+	}
+
+	wake_up(&c->free_buffer_wait);
+}
+
+static void __write_dirty_buffers_async(struct dm_bufio_client *c, int no_wait)
+{
+	struct dm_buffer *b, *tmp;
+
+	list_for_each_entry_safe_reverse(b, tmp, &c->lru[LIST_DIRTY], lru_list) {
+		BUG_ON(test_bit(B_READING, &b->state));
+
+		if (!test_bit(B_DIRTY, &b->state) &&
+		    !test_bit(B_WRITING, &b->state)) {
+			__relink_lru(b, LIST_CLEAN);
+			continue;
+		}
+
+		if (no_wait && test_bit(B_WRITING, &b->state))
+			return;
+
+		__write_dirty_buffer(b);
+		dm_bufio_cond_resched();
+	}
+}
+
+/*
+ * Get writeback threshold and buffer limit for a given client.
+ */
+static void __get_memory_limit(struct dm_bufio_client *c,
+			       unsigned long *threshold_buffers,
+			       unsigned long *limit_buffers)
+{
+	unsigned long buffers;
+
+	if (dm_bufio_cache_size != dm_bufio_cache_size_latch) {
+		mutex_lock(&dm_bufio_clients_lock);
+		__cache_size_refresh();
+		mutex_unlock(&dm_bufio_clients_lock);
+	}
+
+	buffers = dm_bufio_cache_size_per_client >>
+		  (c->sectors_per_block_bits + SECTOR_SHIFT);
+
+	if (buffers < DM_BUFIO_MIN_BUFFERS)
+		buffers = DM_BUFIO_MIN_BUFFERS;
+
+	*limit_buffers = buffers;
+	*threshold_buffers = buffers * DM_BUFIO_WRITEBACK_PERCENT / 100;
+}
+
+/*
+ * Check if we're over watermark.
+ * If we are over threshold_buffers, start freeing buffers.
+ * If we're over "limit_buffers", block until we get under the limit.
+ */
+static void __check_watermark(struct dm_bufio_client *c)
+{
+	unsigned long threshold_buffers, limit_buffers;
+
+	__get_memory_limit(c, &threshold_buffers, &limit_buffers);
+
+	while (c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY] >
+	       limit_buffers) {
+
+		struct dm_buffer *b = __get_unclaimed_buffer(c);
+
+		if (!b)
+			return;
+
+		__free_buffer_wake(b);
+		dm_bufio_cond_resched();
+	}
+
+	if (c->n_buffers[LIST_DIRTY] > threshold_buffers)
+		__write_dirty_buffers_async(c, 1);
+}
+
+/*
+ * Find a buffer in the hash.
+ */
+static struct dm_buffer *__find(struct dm_bufio_client *c, sector_t block)
+{
+	struct dm_buffer *b;
+	struct hlist_node *hn;
+
+	hlist_for_each_entry(b, hn, &c->cache_hash[DM_BUFIO_HASH(block)],
+			     hash_list) {
+		dm_bufio_cond_resched();
+		if (b->block == block)
+			return b;
+	}
+
+	return NULL;
+}
+
+/*----------------------------------------------------------------
+ * Getting a buffer
+ *--------------------------------------------------------------*/
+
+enum new_flag {
+	NF_FRESH = 0,
+	NF_READ = 1,
+	NF_GET = 2
+};
+
+static struct dm_buffer *__bufio_new(struct dm_bufio_client *c, sector_t block,
+				     enum new_flag nf, struct dm_buffer **bp,
+				     int *need_submit)
+{
+	struct dm_buffer *b, *new_b = NULL;
+
+	*need_submit = 0;
+
+	b = __find(c, block);
+	if (b) {
+		b->hold_count++;
+		__relink_lru(b, test_bit(B_DIRTY, &b->state) ||
+			     test_bit(B_WRITING, &b->state));
+		return b;
+	}
+
+	if (nf == NF_GET)
+		return NULL;
+
+	new_b = __alloc_buffer_wait(c);
+
+	/*
+	 * We've had a period where the mutex was unlocked, so need to
+	 * recheck the hash table.
+	 */
+	b = __find(c, block);
+	if (b) {
+		__free_buffer_wake(new_b);
+		b->hold_count++;
+		__relink_lru(b, test_bit(B_DIRTY, &b->state) ||
+			     test_bit(B_WRITING, &b->state));
+		return b;
+	}
+
+	__check_watermark(c);
+
+	b = new_b;
+	b->hold_count = 1;
+	b->read_error = 0;
+	b->write_error = 0;
+	__link_buffer(b, block, LIST_CLEAN);
+
+	if (nf == NF_FRESH) {
+		b->state = 0;
+		return b;
+	}
+
+	b->state = 1 << B_READING;
+	*need_submit = 1;
+
+	return b;
+}
+
+/*
+ * The endio routine for reading: set the error, clear the bit and wake up
+ * anyone waiting on the buffer.
+ */
+static void read_endio(struct bio *bio, int error)
+{
+	struct dm_buffer *b = container_of(bio, struct dm_buffer, bio);
+
+	b->read_error = error;
+
+	BUG_ON(!test_bit(B_READING, &b->state));
+
+	smp_mb__before_clear_bit();
+	clear_bit(B_READING, &b->state);
+	smp_mb__after_clear_bit();
+
+	wake_up_bit(&b->state, B_READING);
+}
+
+/*
+ * A common routine for dm_bufio_new and dm_bufio_read.  Operation of these
+ * functions is similar except that dm_bufio_new doesn't read the
+ * buffer from the disk (assuming that the caller overwrites all the data
+ * and uses dm_bufio_mark_buffer_dirty to write new data back).
+ */
+static void *new_read(struct dm_bufio_client *c, sector_t block,
+		      enum new_flag nf, struct dm_buffer **bp)
+{
+	int need_submit;
+	struct dm_buffer *b;
+
+	dm_bufio_lock(c);
+	b = __bufio_new(c, block, nf, bp, &need_submit);
+	dm_bufio_unlock(c);
+
+	if (!b || IS_ERR(b))
+		return b;
+
+	if (need_submit)
+		submit_io(b, READ, b->block, read_endio);
+
+	wait_on_bit(&b->state, B_READING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+
+	if (b->read_error) {
+		int error = b->read_error;
+
+		dm_bufio_release(b);
+
+		return ERR_PTR(error);
+	}
+
+	*bp = b;
+
+	return b->data;
+}
+
+void *dm_bufio_get(struct dm_bufio_client *c, sector_t block,
+		   struct dm_buffer **bp)
+{
+	return new_read(c, block, NF_GET, bp);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get);
+
+void *dm_bufio_read(struct dm_bufio_client *c, sector_t block,
+		    struct dm_buffer **bp)
+{
+	BUG_ON(dm_bufio_in_request());
+
+	return new_read(c, block, NF_READ, bp);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_read);
+
+void *dm_bufio_new(struct dm_bufio_client *c, sector_t block,
+		   struct dm_buffer **bp)
+{
+	BUG_ON(dm_bufio_in_request());
+
+	return new_read(c, block, NF_FRESH, bp);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_new);
+
+void dm_bufio_release(struct dm_buffer *b)
+{
+	struct dm_bufio_client *c = b->c;
+
+	dm_bufio_lock(c);
+
+	BUG_ON(test_bit(B_READING, &b->state));
+	BUG_ON(!b->hold_count);
+
+	b->hold_count--;
+	if (!b->hold_count) {
+		wake_up(&c->free_buffer_wait);
+
+		/*
+		 * If there were errors on the buffer, and the buffer is not
+		 * to be written, free the buffer. There is no point in caching
+		 * invalid buffer.
+		 */
+		if ((b->read_error || b->write_error) &&
+		    !test_bit(B_WRITING, &b->state) &&
+		    !test_bit(B_DIRTY, &b->state)) {
+			__unlink_buffer(b);
+			__free_buffer_wake(b);
+		}
+	}
+
+	dm_bufio_unlock(c);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_release);
+
+void dm_bufio_mark_buffer_dirty(struct dm_buffer *b)
+{
+	struct dm_bufio_client *c = b->c;
+
+	dm_bufio_lock(c);
+
+	if (!test_and_set_bit(B_DIRTY, &b->state))
+		__relink_lru(b, LIST_DIRTY);
+
+	dm_bufio_unlock(c);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_mark_buffer_dirty);
+
+void dm_bufio_write_dirty_buffers_async(struct dm_bufio_client *c)
+{
+	BUG_ON(dm_bufio_in_request());
+
+	dm_bufio_lock(c);
+	__write_dirty_buffers_async(c, 0);
+	dm_bufio_unlock(c);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_write_dirty_buffers_async);
+
+/*
+ * For performance, it is essential that the buffers are written asynchronously
+ * and simultaneously (so that the block layer can merge the writes) and then
+ * waited upon.
+ *
+ * Finally, we flush hardware disk cache.
+ */
+int dm_bufio_write_dirty_buffers(struct dm_bufio_client *c)
+{
+	int a, f;
+	unsigned long buffers_processed = 0;
+	struct dm_buffer *b, *tmp;
+
+	dm_bufio_lock(c);
+	__write_dirty_buffers_async(c, 0);
+
+again:
+	list_for_each_entry_safe_reverse(b, tmp, &c->lru[LIST_DIRTY], lru_list) {
+		int dropped_lock = 0;
+
+		if (buffers_processed < c->n_buffers[LIST_DIRTY])
+			buffers_processed++;
+
+		BUG_ON(test_bit(B_READING, &b->state));
+
+		if (test_bit(B_WRITING, &b->state)) {
+			if (buffers_processed < c->n_buffers[LIST_DIRTY]) {
+				dropped_lock = 1;
+				b->hold_count++;
+				dm_bufio_unlock(c);
+				wait_on_bit(&b->state, B_WRITING,
+					    do_io_schedule,
+					    TASK_UNINTERRUPTIBLE);
+				dm_bufio_lock(c);
+				b->hold_count--;
+			} else
+				wait_on_bit(&b->state, B_WRITING,
+					    do_io_schedule,
+					    TASK_UNINTERRUPTIBLE);
+		}
+
+		if (!test_bit(B_DIRTY, &b->state) &&
+		    !test_bit(B_WRITING, &b->state))
+			__relink_lru(b, LIST_CLEAN);
+
+		dm_bufio_cond_resched();
+
+		/*
+		 * If we dropped the lock, the list is no longer consistent,
+		 * so we must restart the search.
+		 *
+		 * In the most common case, the buffer just processed is
+		 * relinked to the clean list, so we won't loop scanning the
+		 * same buffer again and again.
+		 *
+		 * This may livelock if there is another thread simultaneously
+		 * dirtying buffers, so we count the number of buffers walked
+		 * and if it exceeds the total number of buffers, it means that
+		 * someone is doing some writes simultaneously with us.  In
+		 * this case, stop, dropping the lock.
+		 */
+		if (dropped_lock)
+			goto again;
+	}
+	wake_up(&c->free_buffer_wait);
+	dm_bufio_unlock(c);
+
+	a = xchg(&c->async_write_error, 0);
+	f = dm_bufio_issue_flush(c);
+	if (a)
+		return a;
+
+	return f;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_write_dirty_buffers);
+
+/*
+ * Use dm-io to send and empty barrier flush the device.
+ */
+int dm_bufio_issue_flush(struct dm_bufio_client *c)
+{
+	struct dm_io_request io_req = {
+		.bi_rw = REQ_FLUSH,
+		.mem.type = DM_IO_KMEM,
+		.mem.ptr.addr = NULL,
+		.client = c->dm_io,
+	};
+	struct dm_io_region io_reg = {
+		.bdev = c->bdev,
+		.sector = 0,
+		.count = 0,
+	};
+
+	BUG_ON(dm_bufio_in_request());
+
+	return dm_io(&io_req, 1, &io_reg, NULL);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_issue_flush);
+
+/*
+ * We first delete any other buffer that may be at that new location.
+ *
+ * Then, we write the buffer to the original location if it was dirty.
+ *
+ * Then, if we are the only one who is holding the buffer, relink the buffer
+ * in the hash queue for the new location.
+ *
+ * If there was someone else holding the buffer, we write it to the new
+ * location but not relink it, because that other user needs to have the buffer
+ * at the same place.
+ */
+void dm_bufio_release_move(struct dm_buffer *b, sector_t new_block)
+{
+	struct dm_bufio_client *c = b->c;
+	struct dm_buffer *new;
+
+	BUG_ON(dm_bufio_in_request());
+
+	dm_bufio_lock(c);
+
+retry:
+	new = __find(c, new_block);
+	if (new) {
+		if (new->hold_count) {
+			__wait_for_free_buffer(c);
+			goto retry;
+		}
+
+		/*
+		 * FIXME: Is there any point waiting for a write that's going
+		 * to be overwritten in a bit?
+		 */
+		__make_buffer_clean(new);
+		__unlink_buffer(new);
+		__free_buffer_wake(new);
+	}
+
+	BUG_ON(!b->hold_count);
+	BUG_ON(test_bit(B_READING, &b->state));
+
+	__write_dirty_buffer(b);
+	if (b->hold_count == 1) {
+		wait_on_bit(&b->state, B_WRITING,
+			    do_io_schedule, TASK_UNINTERRUPTIBLE);
+		set_bit(B_DIRTY, &b->state);
+		__unlink_buffer(b);
+		__link_buffer(b, new_block, LIST_DIRTY);
+	} else {
+		sector_t old_block;
+		wait_on_bit_lock(&b->state, B_WRITING,
+				 do_io_schedule, TASK_UNINTERRUPTIBLE);
+		/*
+		 * Relink buffer to "new_block" so that write_callback
+		 * sees "new_block" as a block number.
+		 * After the write, link the buffer back to old_block.
+		 * All this must be done in bufio lock, so that block number
+		 * change isn't visible to other threads.
+		 */
+		old_block = b->block;
+		__unlink_buffer(b);
+		__link_buffer(b, new_block, b->list_mode);
+		submit_io(b, WRITE, new_block, write_endio);
+		wait_on_bit(&b->state, B_WRITING,
+			    do_io_schedule, TASK_UNINTERRUPTIBLE);
+		__unlink_buffer(b);
+		__link_buffer(b, old_block, b->list_mode);
+	}
+
+	dm_bufio_unlock(c);
+	dm_bufio_release(b);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_release_move);
+
+unsigned dm_bufio_get_block_size(struct dm_bufio_client *c)
+{
+	return c->block_size;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_block_size);
+
+sector_t dm_bufio_get_device_size(struct dm_bufio_client *c)
+{
+	return i_size_read(c->bdev->bd_inode) >>
+			   (SECTOR_SHIFT + c->sectors_per_block_bits);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_device_size);
+
+sector_t dm_bufio_get_block_number(struct dm_buffer *b)
+{
+	return b->block;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_block_number);
+
+void *dm_bufio_get_block_data(struct dm_buffer *b)
+{
+	return b->data;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_block_data);
+
+void *dm_bufio_get_aux_data(struct dm_buffer *b)
+{
+	return b + 1;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_aux_data);
+
+struct dm_bufio_client *dm_bufio_get_client(struct dm_buffer *b)
+{
+	return b->c;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_client);
+
+static void drop_buffers(struct dm_bufio_client *c)
+{
+	struct dm_buffer *b;
+	int i;
+
+	BUG_ON(dm_bufio_in_request());
+
+	/*
+	 * An optimization so that the buffers are not written one-by-one.
+	 */
+	dm_bufio_write_dirty_buffers_async(c);
+
+	dm_bufio_lock(c);
+
+	while ((b = __get_unclaimed_buffer(c)))
+		__free_buffer_wake(b);
+
+	for (i = 0; i < LIST_SIZE; i++)
+		list_for_each_entry(b, &c->lru[i], lru_list)
+			DMERR("leaked buffer %llx, hold count %u, list %d",
+			      (unsigned long long)b->block, b->hold_count, i);
+
+	for (i = 0; i < LIST_SIZE; i++)
+		BUG_ON(!list_empty(&c->lru[i]));
+
+	dm_bufio_unlock(c);
+}
+
+/*
+ * Test if the buffer is unused and too old, and commit it.
+ * At if noio is set, we must not do any I/O because we hold
+ * dm_bufio_clients_lock and we would risk deadlock if the I/O gets rerouted to
+ * different bufio client.
+ */
+static int __cleanup_old_buffer(struct dm_buffer *b, gfp_t gfp,
+				unsigned long max_jiffies)
+{
+	if (jiffies - b->last_accessed < max_jiffies)
+		return 1;
+
+	if (!(gfp & __GFP_IO)) {
+		if (test_bit(B_READING, &b->state) ||
+		    test_bit(B_WRITING, &b->state) ||
+		    test_bit(B_DIRTY, &b->state))
+			return 1;
+	}
+
+	if (b->hold_count)
+		return 1;
+
+	__make_buffer_clean(b);
+	__unlink_buffer(b);
+	__free_buffer_wake(b);
+
+	return 0;
+}
+
+static void __scan(struct dm_bufio_client *c, unsigned long nr_to_scan,
+		   struct shrink_control *sc)
+{
+	int l;
+	struct dm_buffer *b, *tmp;
+
+	for (l = 0; l < LIST_SIZE; l++) {
+		list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list)
+			if (!__cleanup_old_buffer(b, sc->gfp_mask, 0) &&
+			    !--nr_to_scan)
+				return;
+		dm_bufio_cond_resched();
+	}
+}
+
+static int shrink(struct shrinker *shrinker, struct shrink_control *sc)
+{
+	struct dm_bufio_client *c =
+	    container_of(shrinker, struct dm_bufio_client, shrinker);
+	unsigned long r;
+	unsigned long nr_to_scan = sc->nr_to_scan;
+
+	if (sc->gfp_mask & __GFP_IO)
+		dm_bufio_lock(c);
+	else if (!dm_bufio_trylock(c))
+		return !nr_to_scan ? 0 : -1;
+
+	if (nr_to_scan)
+		__scan(c, nr_to_scan, sc);
+
+	r = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY];
+	if (r > INT_MAX)
+		r = INT_MAX;
+
+	dm_bufio_unlock(c);
+
+	return r;
+}
+
+/*
+ * Create the buffering interface
+ */
+struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsigned block_size,
+					       unsigned reserved_buffers, unsigned aux_size,
+					       void (*alloc_callback)(struct dm_buffer *),
+					       void (*write_callback)(struct dm_buffer *))
+{
+	int r;
+	struct dm_bufio_client *c;
+	unsigned i;
+
+	BUG_ON(block_size < 1 << SECTOR_SHIFT ||
+	       (block_size & (block_size - 1)));
+
+	c = kmalloc(sizeof(*c), GFP_KERNEL);
+	if (!c) {
+		r = -ENOMEM;
+		goto bad_client;
+	}
+	c->cache_hash = vmalloc(sizeof(struct hlist_head) << DM_BUFIO_HASH_BITS);
+	if (!c->cache_hash) {
+		r = -ENOMEM;
+		goto bad_hash;
+	}
+
+	c->bdev = bdev;
+	c->block_size = block_size;
+	c->sectors_per_block_bits = ffs(block_size) - 1 - SECTOR_SHIFT;
+	c->pages_per_block_bits = (ffs(block_size) - 1 >= PAGE_SHIFT) ?
+				  ffs(block_size) - 1 - PAGE_SHIFT : 0;
+	c->blocks_per_page_bits = (ffs(block_size) - 1 < PAGE_SHIFT ?
+				  PAGE_SHIFT - (ffs(block_size) - 1) : 0);
+
+	c->aux_size = aux_size;
+	c->alloc_callback = alloc_callback;
+	c->write_callback = write_callback;
+
+	for (i = 0; i < LIST_SIZE; i++) {
+		INIT_LIST_HEAD(&c->lru[i]);
+		c->n_buffers[i] = 0;
+	}
+
+	for (i = 0; i < 1 << DM_BUFIO_HASH_BITS; i++)
+		INIT_HLIST_HEAD(&c->cache_hash[i]);
+
+	mutex_init(&c->lock);
+	INIT_LIST_HEAD(&c->reserved_buffers);
+	c->need_reserved_buffers = reserved_buffers;
+
+	init_waitqueue_head(&c->free_buffer_wait);
+	c->async_write_error = 0;
+
+	c->dm_io = dm_io_client_create();
+	if (IS_ERR(c->dm_io)) {
+		r = PTR_ERR(c->dm_io);
+		goto bad_dm_io;
+	}
+
+	mutex_lock(&dm_bufio_clients_lock);
+	if (c->blocks_per_page_bits) {
+		if (!DM_BUFIO_CACHE_NAME(c)) {
+			DM_BUFIO_CACHE_NAME(c) = kasprintf(GFP_KERNEL, "dm_bufio_cache-%u", c->block_size);
+			if (!DM_BUFIO_CACHE_NAME(c)) {
+				r = -ENOMEM;
+				mutex_unlock(&dm_bufio_clients_lock);
+				goto bad_cache;
+			}
+		}
+
+		if (!DM_BUFIO_CACHE(c)) {
+			DM_BUFIO_CACHE(c) = kmem_cache_create(DM_BUFIO_CACHE_NAME(c),
+							      c->block_size,
+							      c->block_size, 0, NULL);
+			if (!DM_BUFIO_CACHE(c)) {
+				r = -ENOMEM;
+				mutex_unlock(&dm_bufio_clients_lock);
+				goto bad_cache;
+			}
+		}
+	}
+	mutex_unlock(&dm_bufio_clients_lock);
+
+	while (c->need_reserved_buffers) {
+		struct dm_buffer *b = alloc_buffer(c, GFP_KERNEL);
+
+		if (!b) {
+			r = -ENOMEM;
+			goto bad_buffer;
+		}
+		__free_buffer_wake(b);
+	}
+
+	mutex_lock(&dm_bufio_clients_lock);
+	dm_bufio_client_count++;
+	list_add(&c->client_list, &dm_bufio_all_clients);
+	__cache_size_refresh();
+	mutex_unlock(&dm_bufio_clients_lock);
+
+	c->shrinker.shrink = shrink;
+	c->shrinker.seeks = 1;
+	c->shrinker.batch = 0;
+	register_shrinker(&c->shrinker);
+
+	return c;
+
+bad_buffer:
+bad_cache:
+	while (!list_empty(&c->reserved_buffers)) {
+		struct dm_buffer *b = list_entry(c->reserved_buffers.next,
+						 struct dm_buffer, lru_list);
+		list_del(&b->lru_list);
+		free_buffer(b);
+	}
+	dm_io_client_destroy(c->dm_io);
+bad_dm_io:
+	vfree(c->cache_hash);
+bad_hash:
+	kfree(c);
+bad_client:
+	return ERR_PTR(r);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_client_create);
+
+/*
+ * Free the buffering interface.
+ * It is required that there are no references on any buffers.
+ */
+void dm_bufio_client_destroy(struct dm_bufio_client *c)
+{
+	unsigned i;
+
+	drop_buffers(c);
+
+	unregister_shrinker(&c->shrinker);
+
+	mutex_lock(&dm_bufio_clients_lock);
+
+	list_del(&c->client_list);
+	dm_bufio_client_count--;
+	__cache_size_refresh();
+
+	mutex_unlock(&dm_bufio_clients_lock);
+
+	for (i = 0; i < 1 << DM_BUFIO_HASH_BITS; i++)
+		BUG_ON(!hlist_empty(&c->cache_hash[i]));
+
+	BUG_ON(c->need_reserved_buffers);
+
+	while (!list_empty(&c->reserved_buffers)) {
+		struct dm_buffer *b = list_entry(c->reserved_buffers.next,
+						 struct dm_buffer, lru_list);
+		list_del(&b->lru_list);
+		free_buffer(b);
+	}
+
+	for (i = 0; i < LIST_SIZE; i++)
+		if (c->n_buffers[i])
+			DMERR("leaked buffer count %d: %ld", i, c->n_buffers[i]);
+
+	for (i = 0; i < LIST_SIZE; i++)
+		BUG_ON(c->n_buffers[i]);
+
+	dm_io_client_destroy(c->dm_io);
+	vfree(c->cache_hash);
+	kfree(c);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_client_destroy);
+
+static void cleanup_old_buffers(void)
+{
+	unsigned long max_age = dm_bufio_max_age;
+	struct dm_bufio_client *c;
+
+	barrier();
+
+	if (max_age > ULONG_MAX / HZ)
+		max_age = ULONG_MAX / HZ;
+
+	mutex_lock(&dm_bufio_clients_lock);
+	list_for_each_entry(c, &dm_bufio_all_clients, client_list) {
+		if (!dm_bufio_trylock(c))
+			continue;
+
+		while (!list_empty(&c->lru[LIST_CLEAN])) {
+			struct dm_buffer *b;
+			b = list_entry(c->lru[LIST_CLEAN].prev,
+				       struct dm_buffer, lru_list);
+			if (__cleanup_old_buffer(b, 0, max_age * HZ))
+				break;
+			dm_bufio_cond_resched();
+		}
+
+		dm_bufio_unlock(c);
+		dm_bufio_cond_resched();
+	}
+	mutex_unlock(&dm_bufio_clients_lock);
+}
+
+static struct workqueue_struct *dm_bufio_wq;
+static struct delayed_work dm_bufio_work;
+
+static void work_fn(struct work_struct *w)
+{
+	cleanup_old_buffers();
+
+	queue_delayed_work(dm_bufio_wq, &dm_bufio_work,
+			   DM_BUFIO_WORK_TIMER_SECS * HZ);
+}
+
+/*----------------------------------------------------------------
+ * Module setup
+ *--------------------------------------------------------------*/
+
+/*
+ * This is called only once for the whole dm_bufio module.
+ * It initializes memory limit.
+ */
+static int __init dm_bufio_init(void)
+{
+	__u64 mem;
+
+	memset(&dm_bufio_caches, 0, sizeof dm_bufio_caches);
+	memset(&dm_bufio_cache_names, 0, sizeof dm_bufio_cache_names);
+
+	mem = (__u64)((totalram_pages - totalhigh_pages) *
+		      DM_BUFIO_MEMORY_PERCENT / 100) << PAGE_SHIFT;
+
+	if (mem > ULONG_MAX)
+		mem = ULONG_MAX;
+
+#ifdef CONFIG_MMU
+	/*
+	 * Get the size of vmalloc space the same way as VMALLOC_TOTAL
+	 * in fs/proc/internal.h
+	 */
+	if (mem > (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100)
+		mem = (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100;
+#endif
+
+	dm_bufio_default_cache_size = mem;
+
+	mutex_lock(&dm_bufio_clients_lock);
+	__cache_size_refresh();
+	mutex_unlock(&dm_bufio_clients_lock);
+
+	dm_bufio_wq = create_singlethread_workqueue("dm_bufio_cache");
+	if (!dm_bufio_wq)
+		return -ENOMEM;
+
+	INIT_DELAYED_WORK(&dm_bufio_work, work_fn);
+	queue_delayed_work(dm_bufio_wq, &dm_bufio_work,
+			   DM_BUFIO_WORK_TIMER_SECS * HZ);
+
+	return 0;
+}
+
+/*
+ * This is called once when unloading the dm_bufio module.
+ */
+static void __exit dm_bufio_exit(void)
+{
+	int bug = 0;
+	int i;
+
+	cancel_delayed_work_sync(&dm_bufio_work);
+	destroy_workqueue(dm_bufio_wq);
+
+	for (i = 0; i < ARRAY_SIZE(dm_bufio_caches); i++) {
+		struct kmem_cache *kc = dm_bufio_caches[i];
+
+		if (kc)
+			kmem_cache_destroy(kc);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(dm_bufio_cache_names); i++)
+		kfree(dm_bufio_cache_names[i]);
+
+	if (dm_bufio_client_count) {
+		DMCRIT("%s: dm_bufio_client_count leaked: %d",
+			__func__, dm_bufio_client_count);
+		bug = 1;
+	}
+
+	if (dm_bufio_current_allocated) {
+		DMCRIT("%s: dm_bufio_current_allocated leaked: %lu",
+			__func__, dm_bufio_current_allocated);
+		bug = 1;
+	}
+
+	if (dm_bufio_allocated_get_free_pages) {
+		DMCRIT("%s: dm_bufio_allocated_get_free_pages leaked: %lu",
+		       __func__, dm_bufio_allocated_get_free_pages);
+		bug = 1;
+	}
+
+	if (dm_bufio_allocated_vmalloc) {
+		DMCRIT("%s: dm_bufio_vmalloc leaked: %lu",
+		       __func__, dm_bufio_allocated_vmalloc);
+		bug = 1;
+	}
+
+	if (bug)
+		BUG();
+}
+
+module_init(dm_bufio_init)
+module_exit(dm_bufio_exit)
+
+module_param_named(max_cache_size_bytes, dm_bufio_cache_size, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_cache_size_bytes, "Size of metadata cache");
+
+module_param_named(max_age_seconds, dm_bufio_max_age, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_age_seconds, "Max age of a buffer in seconds");
+
+module_param_named(peak_allocated_bytes, dm_bufio_peak_allocated, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(peak_allocated_bytes, "Tracks the maximum allocated memory");
+
+module_param_named(allocated_kmem_cache_bytes, dm_bufio_allocated_kmem_cache, ulong, S_IRUGO);
+MODULE_PARM_DESC(allocated_kmem_cache_bytes, "Memory allocated with kmem_cache_alloc");
+
+module_param_named(allocated_get_free_pages_bytes, dm_bufio_allocated_get_free_pages, ulong, S_IRUGO);
+MODULE_PARM_DESC(allocated_get_free_pages_bytes, "Memory allocated with get_free_pages");
+
+module_param_named(allocated_vmalloc_bytes, dm_bufio_allocated_vmalloc, ulong, S_IRUGO);
+MODULE_PARM_DESC(allocated_vmalloc_bytes, "Memory allocated with vmalloc");
+
+module_param_named(current_allocated_bytes, dm_bufio_current_allocated, ulong, S_IRUGO);
+MODULE_PARM_DESC(current_allocated_bytes, "Memory currently used by the cache");
+
+MODULE_AUTHOR("Mikulas Patocka <dm-devel@redhat.com>");
+MODULE_DESCRIPTION(DM_NAME " buffered I/O library");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/md/dm-bufio.h linux-libre-3.2-gnu/drivers/md/dm-bufio.h
--- linux-libre-3.1-gnu/drivers/md/dm-bufio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/dm-bufio.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2009-2011 Red Hat, Inc.
+ *
+ * Author: Mikulas Patocka <mpatocka@redhat.com>
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_BUFIO_H
+#define DM_BUFIO_H
+
+#include <linux/blkdev.h>
+#include <linux/types.h>
+
+/*----------------------------------------------------------------*/
+
+struct dm_bufio_client;
+struct dm_buffer;
+
+/*
+ * Create a buffered IO cache on a given device
+ */
+struct dm_bufio_client *
+dm_bufio_client_create(struct block_device *bdev, unsigned block_size,
+		       unsigned reserved_buffers, unsigned aux_size,
+		       void (*alloc_callback)(struct dm_buffer *),
+		       void (*write_callback)(struct dm_buffer *));
+
+/*
+ * Release a buffered IO cache.
+ */
+void dm_bufio_client_destroy(struct dm_bufio_client *c);
+
+/*
+ * WARNING: to avoid deadlocks, these conditions are observed:
+ *
+ * - At most one thread can hold at most "reserved_buffers" simultaneously.
+ * - Each other threads can hold at most one buffer.
+ * - Threads which call only dm_bufio_get can hold unlimited number of
+ *   buffers.
+ */
+
+/*
+ * Read a given block from disk. Returns pointer to data.  Returns a
+ * pointer to dm_buffer that can be used to release the buffer or to make
+ * it dirty.
+ */
+void *dm_bufio_read(struct dm_bufio_client *c, sector_t block,
+		    struct dm_buffer **bp);
+
+/*
+ * Like dm_bufio_read, but return buffer from cache, don't read
+ * it. If the buffer is not in the cache, return NULL.
+ */
+void *dm_bufio_get(struct dm_bufio_client *c, sector_t block,
+		   struct dm_buffer **bp);
+
+/*
+ * Like dm_bufio_read, but don't read anything from the disk.  It is
+ * expected that the caller initializes the buffer and marks it dirty.
+ */
+void *dm_bufio_new(struct dm_bufio_client *c, sector_t block,
+		   struct dm_buffer **bp);
+
+/*
+ * Release a reference obtained with dm_bufio_{read,get,new}. The data
+ * pointer and dm_buffer pointer is no longer valid after this call.
+ */
+void dm_bufio_release(struct dm_buffer *b);
+
+/*
+ * Mark a buffer dirty. It should be called after the buffer is modified.
+ *
+ * In case of memory pressure, the buffer may be written after
+ * dm_bufio_mark_buffer_dirty, but before dm_bufio_write_dirty_buffers.  So
+ * dm_bufio_write_dirty_buffers guarantees that the buffer is on-disk but
+ * the actual writing may occur earlier.
+ */
+void dm_bufio_mark_buffer_dirty(struct dm_buffer *b);
+
+/*
+ * Initiate writing of dirty buffers, without waiting for completion.
+ */
+void dm_bufio_write_dirty_buffers_async(struct dm_bufio_client *c);
+
+/*
+ * Write all dirty buffers. Guarantees that all dirty buffers created prior
+ * to this call are on disk when this call exits.
+ */
+int dm_bufio_write_dirty_buffers(struct dm_bufio_client *c);
+
+/*
+ * Send an empty write barrier to the device to flush hardware disk cache.
+ */
+int dm_bufio_issue_flush(struct dm_bufio_client *c);
+
+/*
+ * Like dm_bufio_release but also move the buffer to the new
+ * block. dm_bufio_write_dirty_buffers is needed to commit the new block.
+ */
+void dm_bufio_release_move(struct dm_buffer *b, sector_t new_block);
+
+unsigned dm_bufio_get_block_size(struct dm_bufio_client *c);
+sector_t dm_bufio_get_device_size(struct dm_bufio_client *c);
+sector_t dm_bufio_get_block_number(struct dm_buffer *b);
+void *dm_bufio_get_block_data(struct dm_buffer *b);
+void *dm_bufio_get_aux_data(struct dm_buffer *b);
+struct dm_bufio_client *dm_bufio_get_client(struct dm_buffer *b);
+
+/*----------------------------------------------------------------*/
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/md/dm.c linux-libre-3.2-gnu/drivers/md/dm.c
--- linux-libre-3.1-gnu/drivers/md/dm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/dm.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,16 @@
 
 #define DM_MSG_PREFIX "core"
 
+#ifdef CONFIG_PRINTK
+/*
+ * ratelimit state to be used in DMXXX_LIMIT().
+ */
+DEFINE_RATELIMIT_STATE(dm_ratelimit_state,
+		       DEFAULT_RATELIMIT_INTERVAL,
+		       DEFAULT_RATELIMIT_BURST);
+EXPORT_SYMBOL(dm_ratelimit_state);
+#endif
+
 /*
  * Cookies are numeric values sent with CHANGE and REMOVE
  * uevents while resuming, removing or renaming the device.
@@ -130,6 +140,8 @@
 	/* Protect queue and type against concurrent access. */
 	struct mutex type_lock;
 
+	struct target_type *immutable_target_type;
+
 	struct gendisk *disk;
 	char name[16];
 
@@ -180,9 +192,6 @@
 	/* forced geometry settings */
 	struct hd_geometry geometry;
 
-	/* For saving the address of __make_request for request based dm */
-	make_request_fn *saved_make_request_fn;
-
 	/* sysfs handle */
 	struct kobject kobj;
 
@@ -1391,7 +1400,7 @@
  * The request function that just remaps the bio built up by
  * dm_merge_bvec.
  */
-static int _dm_request(struct request_queue *q, struct bio *bio)
+static void _dm_request(struct request_queue *q, struct bio *bio)
 {
 	int rw = bio_data_dir(bio);
 	struct mapped_device *md = q->queuedata;
@@ -1412,19 +1421,12 @@
 			queue_io(md, bio);
 		else
 			bio_io_error(bio);
-		return 0;
+		return;
 	}
 
 	__split_and_process_bio(md, bio);
 	up_read(&md->io_lock);
-	return 0;
-}
-
-static int dm_make_request(struct request_queue *q, struct bio *bio)
-{
-	struct mapped_device *md = q->queuedata;
-
-	return md->saved_make_request_fn(q, bio); /* call __make_request() */
+	return;
 }
 
 static int dm_request_based(struct mapped_device *md)
@@ -1432,14 +1434,14 @@
 	return blk_queue_stackable(md->queue);
 }
 
-static int dm_request(struct request_queue *q, struct bio *bio)
+static void dm_request(struct request_queue *q, struct bio *bio)
 {
 	struct mapped_device *md = q->queuedata;
 
 	if (dm_request_based(md))
-		return dm_make_request(q, bio);
-
-	return _dm_request(q, bio);
+		blk_queue_bio(q, bio);
+	else
+		_dm_request(q, bio);
 }
 
 void dm_dispatch_request(struct request *rq)
@@ -2086,6 +2088,8 @@
 	write_lock_irqsave(&md->map_lock, flags);
 	old_map = md->map;
 	md->map = t;
+	md->immutable_target_type = dm_table_get_immutable_target_type(t);
+
 	dm_table_set_restrictions(t, q, limits);
 	if (merge_is_optional)
 		set_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
@@ -2156,6 +2160,11 @@
 	return md->type;
 }
 
+struct target_type *dm_get_immutable_target_type(struct mapped_device *md)
+{
+	return md->immutable_target_type;
+}
+
 /*
  * Fully initialize a request-based queue (->elevator, ->request_fn, etc).
  */
@@ -2172,7 +2181,6 @@
 		return 0;
 
 	md->queue = q;
-	md->saved_make_request_fn = md->queue->make_request_fn;
 	dm_init_md_queue(md);
 	blk_queue_softirq_done(md->queue, dm_softirq_done);
 	blk_queue_prep_rq(md->queue, dm_prep_fn);
@@ -2231,6 +2239,7 @@
 
 	return md;
 }
+EXPORT_SYMBOL_GPL(dm_get_md);
 
 void *dm_get_mdptr(struct mapped_device *md)
 {
@@ -2316,7 +2325,6 @@
 	while (1) {
 		set_current_state(interruptible);
 
-		smp_mb();
 		if (!md_in_flight(md))
 			break;
 
diff -druN linux-libre-3.1-gnu/drivers/md/dm-exception-store.c linux-libre-3.2-gnu/drivers/md/dm-exception-store.c
--- linux-libre-3.1-gnu/drivers/md/dm-exception-store.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/dm-exception-store.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/vmalloc.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 
 #define DM_MSG_PREFIX "snapshot exception stores"
diff -druN linux-libre-3.1-gnu/drivers/md/dm.h linux-libre-3.2-gnu/drivers/md/dm.h
--- linux-libre-3.1-gnu/drivers/md/dm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/dm.h	2012-01-04 18:55:44.000000000 -0500
@@ -60,6 +60,7 @@
 int dm_table_any_congested(struct dm_table *t, int bdi_bits);
 int dm_table_any_busy_target(struct dm_table *t);
 unsigned dm_table_get_type(struct dm_table *t);
+struct target_type *dm_table_get_immutable_target_type(struct dm_table *t);
 bool dm_table_request_based(struct dm_table *t);
 bool dm_table_supports_discards(struct dm_table *t);
 int dm_table_alloc_md_mempools(struct dm_table *t);
@@ -72,6 +73,7 @@
 void dm_unlock_md_type(struct mapped_device *md);
 void dm_set_md_type(struct mapped_device *md, unsigned type);
 unsigned dm_get_md_type(struct mapped_device *md);
+struct target_type *dm_get_immutable_target_type(struct mapped_device *md);
 
 int dm_setup_md_queue(struct mapped_device *md);
 
diff -druN linux-libre-3.1-gnu/drivers/md/dm-ioctl.c linux-libre-3.2-gnu/drivers/md/dm-ioctl.c
--- linux-libre-3.1-gnu/drivers/md/dm-ioctl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/dm-ioctl.c	2012-01-04 18:55:44.000000000 -0500
@@ -1215,6 +1215,7 @@
 	struct hash_cell *hc;
 	struct dm_table *t;
 	struct mapped_device *md;
+	struct target_type *immutable_target_type;
 
 	md = find_device(param);
 	if (!md)
@@ -1230,6 +1231,16 @@
 		goto out;
 	}
 
+	immutable_target_type = dm_get_immutable_target_type(md);
+	if (immutable_target_type &&
+	    (immutable_target_type != dm_table_get_immutable_target_type(t))) {
+		DMWARN("can't replace immutable target type %s",
+		       immutable_target_type->name);
+		dm_table_destroy(t);
+		r = -EINVAL;
+		goto out;
+	}
+
 	/* Protect md->type and md->queue against concurrent table loads. */
 	dm_lock_md_type(md);
 	if (dm_get_md_type(md) == DM_TYPE_NONE)
diff -druN linux-libre-3.1-gnu/drivers/md/dm-kcopyd.c linux-libre-3.2-gnu/drivers/md/dm-kcopyd.c
--- linux-libre-3.1-gnu/drivers/md/dm-kcopyd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/dm-kcopyd.c	2012-01-04 18:55:44.000000000 -0500
@@ -66,6 +66,8 @@
 	struct list_head pages_jobs;
 };
 
+static struct page_list zero_page_list;
+
 static void wake(struct dm_kcopyd_client *kc)
 {
 	queue_work(kc->kcopyd_wq, &kc->kcopyd_work);
@@ -254,6 +256,9 @@
 	if (!_job_cache)
 		return -ENOMEM;
 
+	zero_page_list.next = &zero_page_list;
+	zero_page_list.page = ZERO_PAGE(0);
+
 	return 0;
 }
 
@@ -322,7 +327,7 @@
 	dm_kcopyd_notify_fn fn = job->fn;
 	struct dm_kcopyd_client *kc = job->kc;
 
-	if (job->pages)
+	if (job->pages && job->pages != &zero_page_list)
 		kcopyd_put_pages(kc, job->pages);
 	/*
 	 * If this is the master job, the sub jobs have already
@@ -484,6 +489,8 @@
 	atomic_inc(&kc->nr_jobs);
 	if (unlikely(!job->source.count))
 		push(&kc->complete_jobs, job);
+	else if (job->pages == &zero_page_list)
+		push(&kc->io_jobs, job);
 	else
 		push(&kc->pages_jobs, job);
 	wake(kc);
@@ -592,14 +599,20 @@
 	job->flags = flags;
 	job->read_err = 0;
 	job->write_err = 0;
-	job->rw = READ;
-
-	job->source = *from;
 
 	job->num_dests = num_dests;
 	memcpy(&job->dests, dests, sizeof(*dests) * num_dests);
 
-	job->pages = NULL;
+	if (from) {
+		job->source = *from;
+		job->pages = NULL;
+		job->rw = READ;
+	} else {
+		memset(&job->source, 0, sizeof job->source);
+		job->source.count = job->dests[0].count;
+		job->pages = &zero_page_list;
+		job->rw = WRITE;
+	}
 
 	job->fn = fn;
 	job->context = context;
@@ -617,6 +630,14 @@
 }
 EXPORT_SYMBOL(dm_kcopyd_copy);
 
+int dm_kcopyd_zero(struct dm_kcopyd_client *kc,
+		   unsigned num_dests, struct dm_io_region *dests,
+		   unsigned flags, dm_kcopyd_notify_fn fn, void *context)
+{
+	return dm_kcopyd_copy(kc, NULL, num_dests, dests, flags, fn, context);
+}
+EXPORT_SYMBOL(dm_kcopyd_zero);
+
 void *dm_kcopyd_prepare_callback(struct dm_kcopyd_client *kc,
 				 dm_kcopyd_notify_fn fn, void *context)
 {
diff -druN linux-libre-3.1-gnu/drivers/md/dm-log-userspace-base.c linux-libre-3.2-gnu/drivers/md/dm-log-userspace-base.c
--- linux-libre-3.1-gnu/drivers/md/dm-log-userspace-base.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/dm-log-userspace-base.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/dm-dirty-log.h>
 #include <linux/device-mapper.h>
 #include <linux/dm-log-userspace.h>
+#include <linux/module.h>
 
 #include "dm-log-userspace-transfer.h"
 
@@ -30,6 +31,7 @@
 
 struct log_c {
 	struct dm_target *ti;
+	struct dm_dev *log_dev;
 	uint32_t region_size;
 	region_t region_count;
 	uint64_t luid;
@@ -146,7 +148,7 @@
  *	<UUID> <other args>
  * Where 'other args' is the userspace implementation specific log
  * arguments.  An example might be:
- *	<UUID> clustered_disk <arg count> <log dev> <region_size> [[no]sync]
+ *	<UUID> clustered-disk <arg count> <log dev> <region_size> [[no]sync]
  *
  * So, this module will strip off the <UUID> for identification purposes
  * when communicating with userspace about a log; but will pass on everything
@@ -161,13 +163,15 @@
 	struct log_c *lc = NULL;
 	uint64_t rdata;
 	size_t rdata_size = sizeof(rdata);
+	char *devices_rdata = NULL;
+	size_t devices_rdata_size = DM_NAME_LEN;
 
 	if (argc < 3) {
 		DMWARN("Too few arguments to userspace dirty log");
 		return -EINVAL;
 	}
 
-	lc = kmalloc(sizeof(*lc), GFP_KERNEL);
+	lc = kzalloc(sizeof(*lc), GFP_KERNEL);
 	if (!lc) {
 		DMWARN("Unable to allocate userspace log context.");
 		return -ENOMEM;
@@ -195,9 +199,19 @@
 		return str_size;
 	}
 
-	/* Send table string */
+	devices_rdata = kzalloc(devices_rdata_size, GFP_KERNEL);
+	if (!devices_rdata) {
+		DMERR("Failed to allocate memory for device information");
+		r = -ENOMEM;
+		goto out;
+	}
+
+	/*
+	 * Send table string and get back any opened device.
+	 */
 	r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_CTR,
-				 ctr_str, str_size, NULL, NULL);
+				 ctr_str, str_size,
+				 devices_rdata, &devices_rdata_size);
 
 	if (r < 0) {
 		if (r == -ESRCH)
@@ -220,7 +234,20 @@
 	lc->region_size = (uint32_t)rdata;
 	lc->region_count = dm_sector_div_up(ti->len, lc->region_size);
 
+	if (devices_rdata_size) {
+		if (devices_rdata[devices_rdata_size - 1] != '\0') {
+			DMERR("DM_ULOG_CTR device return string not properly terminated");
+			r = -EINVAL;
+			goto out;
+		}
+		r = dm_get_device(ti, devices_rdata,
+				  dm_table_get_mode(ti->table), &lc->log_dev);
+		if (r)
+			DMERR("Failed to register %s with device-mapper",
+			      devices_rdata);
+	}
 out:
+	kfree(devices_rdata);
 	if (r) {
 		kfree(lc);
 		kfree(ctr_str);
@@ -241,6 +268,9 @@
 				 NULL, 0,
 				 NULL, NULL);
 
+	if (lc->log_dev)
+		dm_put_device(lc->ti, lc->log_dev);
+
 	kfree(lc->usr_argv_str);
 	kfree(lc);
 
diff -druN linux-libre-3.1-gnu/drivers/md/dm-path-selector.c linux-libre-3.2-gnu/drivers/md/dm-path-selector.c
--- linux-libre-3.1-gnu/drivers/md/dm-path-selector.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/dm-path-selector.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <linux/device-mapper.h>
+#include <linux/module.h>
 
 #include "dm-path-selector.h"
 
diff -druN linux-libre-3.1-gnu/drivers/md/dm-raid.c linux-libre-3.2-gnu/drivers/md/dm-raid.c
--- linux-libre-3.1-gnu/drivers/md/dm-raid.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/dm-raid.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include "md.h"
 #include "raid1.h"
@@ -37,7 +38,7 @@
 	 */
 	struct dm_dev *meta_dev;
 	struct dm_dev *data_dev;
-	struct mdk_rdev_s rdev;
+	struct md_rdev rdev;
 };
 
 /*
@@ -57,7 +58,7 @@
 
 	uint64_t print_flags;
 
-	struct mddev_s md;
+	struct mddev md;
 	struct raid_type *raid_type;
 	struct dm_target_callbacks callbacks;
 
@@ -594,7 +595,7 @@
 				/* Always set to 0 when writing. */
 } __packed;
 
-static int read_disk_sb(mdk_rdev_t *rdev, int size)
+static int read_disk_sb(struct md_rdev *rdev, int size)
 {
 	BUG_ON(!rdev->sb_page);
 
@@ -611,9 +612,9 @@
 	return 0;
 }
 
-static void super_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+static void super_sync(struct mddev *mddev, struct md_rdev *rdev)
 {
-	mdk_rdev_t *r, *t;
+	struct md_rdev *r, *t;
 	uint64_t failed_devices;
 	struct dm_raid_superblock *sb;
 
@@ -651,7 +652,7 @@
  *
  * Return: 1 if use rdev, 0 if use refdev, -Exxx otherwise
  */
-static int super_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev)
+static int super_load(struct md_rdev *rdev, struct md_rdev *refdev)
 {
 	int ret;
 	struct dm_raid_superblock *sb;
@@ -689,7 +690,7 @@
 	return (events_sb > events_refsb) ? 1 : 0;
 }
 
-static int super_init_validation(mddev_t *mddev, mdk_rdev_t *rdev)
+static int super_init_validation(struct mddev *mddev, struct md_rdev *rdev)
 {
 	int role;
 	struct raid_set *rs = container_of(mddev, struct raid_set, md);
@@ -698,7 +699,7 @@
 	struct dm_raid_superblock *sb;
 	uint32_t new_devs = 0;
 	uint32_t rebuilds = 0;
-	mdk_rdev_t *r, *t;
+	struct md_rdev *r, *t;
 	struct dm_raid_superblock *sb2;
 
 	sb = page_address(rdev->sb_page);
@@ -809,7 +810,7 @@
 	return 0;
 }
 
-static int super_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+static int super_validate(struct mddev *mddev, struct md_rdev *rdev)
 {
 	struct dm_raid_superblock *sb = page_address(rdev->sb_page);
 
@@ -849,8 +850,8 @@
 static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
 {
 	int ret;
-	mdk_rdev_t *rdev, *freshest, *tmp;
-	mddev_t *mddev = &rs->md;
+	struct md_rdev *rdev, *freshest, *tmp;
+	struct mddev *mddev = &rs->md;
 
 	freshest = NULL;
 	rdev_for_each(rdev, tmp, mddev) {
@@ -1004,7 +1005,7 @@
 static int raid_map(struct dm_target *ti, struct bio *bio, union map_info *map_context)
 {
 	struct raid_set *rs = ti->private;
-	mddev_t *mddev = &rs->md;
+	struct mddev *mddev = &rs->md;
 
 	mddev->pers->make_request(mddev, bio);
 
@@ -1017,30 +1018,56 @@
 	struct raid_set *rs = ti->private;
 	unsigned raid_param_cnt = 1; /* at least 1 for chunksize */
 	unsigned sz = 0;
-	int i;
+	int i, array_in_sync = 0;
 	sector_t sync;
 
 	switch (type) {
 	case STATUSTYPE_INFO:
 		DMEMIT("%s %d ", rs->raid_type->name, rs->md.raid_disks);
 
-		for (i = 0; i < rs->md.raid_disks; i++) {
-			if (test_bit(Faulty, &rs->dev[i].rdev.flags))
-				DMEMIT("D");
-			else if (test_bit(In_sync, &rs->dev[i].rdev.flags))
-				DMEMIT("A");
-			else
-				DMEMIT("a");
-		}
-
 		if (test_bit(MD_RECOVERY_RUNNING, &rs->md.recovery))
 			sync = rs->md.curr_resync_completed;
 		else
 			sync = rs->md.recovery_cp;
 
-		if (sync > rs->md.resync_max_sectors)
+		if (sync >= rs->md.resync_max_sectors) {
+			array_in_sync = 1;
 			sync = rs->md.resync_max_sectors;
+		} else {
+			/*
+			 * The array may be doing an initial sync, or it may
+			 * be rebuilding individual components.  If all the
+			 * devices are In_sync, then it is the array that is
+			 * being initialized.
+			 */
+			for (i = 0; i < rs->md.raid_disks; i++)
+				if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
+					array_in_sync = 1;
+		}
+		/*
+		 * Status characters:
+		 *  'D' = Dead/Failed device
+		 *  'a' = Alive but not in-sync
+		 *  'A' = Alive and in-sync
+		 */
+		for (i = 0; i < rs->md.raid_disks; i++) {
+			if (test_bit(Faulty, &rs->dev[i].rdev.flags))
+				DMEMIT("D");
+			else if (!array_in_sync ||
+				 !test_bit(In_sync, &rs->dev[i].rdev.flags))
+				DMEMIT("a");
+			else
+				DMEMIT("A");
+		}
 
+		/*
+		 * In-sync ratio:
+		 *  The in-sync ratio shows the progress of:
+		 *   - Initializing the array
+		 *   - Rebuilding a subset of devices of the array
+		 *  The user can distinguish between the two by referring
+		 *  to the status characters.
+		 */
 		DMEMIT(" %llu/%llu",
 		       (unsigned long long) sync,
 		       (unsigned long long) rs->md.resync_max_sectors);
@@ -1097,7 +1124,7 @@
 			       rs->md.bitmap_info.max_write_behind);
 
 		if (rs->print_flags & DMPF_STRIPE_CACHE) {
-			raid5_conf_t *conf = rs->md.private;
+			struct r5conf *conf = rs->md.private;
 
 			/* convert from kiB to sectors */
 			DMEMIT(" stripe_cache %d",
@@ -1146,7 +1173,7 @@
 {
 	struct raid_set *rs = ti->private;
 	unsigned chunk_size = rs->md.chunk_sectors << 9;
-	raid5_conf_t *conf = rs->md.private;
+	struct r5conf *conf = rs->md.private;
 
 	blk_limits_io_min(limits, chunk_size);
 	blk_limits_io_opt(limits, chunk_size * (conf->raid_disks - conf->max_degraded));
diff -druN linux-libre-3.1-gnu/drivers/md/dm-round-robin.c linux-libre-3.2-gnu/drivers/md/dm-round-robin.c
--- linux-libre-3.1-gnu/drivers/md/dm-round-robin.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/dm-round-robin.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 #include "dm-path-selector.h"
 
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define DM_MSG_PREFIX "multipath round-robin"
 
diff -druN linux-libre-3.1-gnu/drivers/md/dm-service-time.c linux-libre-3.2-gnu/drivers/md/dm-service-time.c
--- linux-libre-3.1-gnu/drivers/md/dm-service-time.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/dm-service-time.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include "dm-path-selector.h"
 
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define DM_MSG_PREFIX	"multipath service-time"
 #define ST_MIN_IO	1
diff -druN linux-libre-3.1-gnu/drivers/md/dm-snap-persistent.c linux-libre-3.2-gnu/drivers/md/dm-snap-persistent.c
--- linux-libre-3.1-gnu/drivers/md/dm-snap-persistent.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/dm-snap-persistent.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/dm-io.h>
 
diff -druN linux-libre-3.1-gnu/drivers/md/dm-snap-transient.c linux-libre-3.2-gnu/drivers/md/dm-snap-transient.c
--- linux-libre-3.1-gnu/drivers/md/dm-snap-transient.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/dm-snap-transient.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/dm-io.h>
 
diff -druN linux-libre-3.1-gnu/drivers/md/dm-table.c linux-libre-3.2-gnu/drivers/md/dm-table.c
--- linux-libre-3.1-gnu/drivers/md/dm-table.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/dm-table.c	2012-01-04 18:55:44.000000000 -0500
@@ -54,7 +54,9 @@
 	sector_t *highs;
 	struct dm_target *targets;
 
+	struct target_type *immutable_target_type;
 	unsigned integrity_supported:1;
+	unsigned singleton:1;
 
 	/*
 	 * Indicates the rw permissions for the new logical
@@ -740,6 +742,12 @@
 	char **argv;
 	struct dm_target *tgt;
 
+	if (t->singleton) {
+		DMERR("%s: target type %s must appear alone in table",
+		      dm_device_name(t->md), t->targets->type->name);
+		return -EINVAL;
+	}
+
 	if ((r = check_space(t)))
 		return r;
 
@@ -758,6 +766,36 @@
 		return -EINVAL;
 	}
 
+	if (dm_target_needs_singleton(tgt->type)) {
+		if (t->num_targets) {
+			DMERR("%s: target type %s must appear alone in table",
+			      dm_device_name(t->md), type);
+			return -EINVAL;
+		}
+		t->singleton = 1;
+	}
+
+	if (dm_target_always_writeable(tgt->type) && !(t->mode & FMODE_WRITE)) {
+		DMERR("%s: target type %s may not be included in read-only tables",
+		      dm_device_name(t->md), type);
+		return -EINVAL;
+	}
+
+	if (t->immutable_target_type) {
+		if (t->immutable_target_type != tgt->type) {
+			DMERR("%s: immutable target type %s cannot be mixed with other target types",
+			      dm_device_name(t->md), t->immutable_target_type->name);
+			return -EINVAL;
+		}
+	} else if (dm_target_is_immutable(tgt->type)) {
+		if (t->num_targets) {
+			DMERR("%s: immutable target type %s cannot be mixed with other target types",
+			      dm_device_name(t->md), tgt->type->name);
+			return -EINVAL;
+		}
+		t->immutable_target_type = tgt->type;
+	}
+
 	tgt->table = t;
 	tgt->begin = start;
 	tgt->len = len;
@@ -915,6 +953,11 @@
 	return t->type;
 }
 
+struct target_type *dm_table_get_immutable_target_type(struct dm_table *t)
+{
+	return t->immutable_target_type;
+}
+
 bool dm_table_request_based(struct dm_table *t)
 {
 	return dm_table_get_type(t) == DM_TYPE_REQUEST_BASED;
@@ -1299,6 +1342,31 @@
 	return 1;
 }
 
+static int device_is_nonrot(struct dm_target *ti, struct dm_dev *dev,
+			    sector_t start, sector_t len, void *data)
+{
+	struct request_queue *q = bdev_get_queue(dev->bdev);
+
+	return q && blk_queue_nonrot(q);
+}
+
+static bool dm_table_is_nonrot(struct dm_table *t)
+{
+	struct dm_target *ti;
+	unsigned i = 0;
+
+	/* Ensure that all underlying device are non-rotational. */
+	while (i < dm_table_get_num_targets(t)) {
+		ti = dm_table_get_target(t, i++);
+
+		if (!ti->type->iterate_devices ||
+		    !ti->type->iterate_devices(ti, device_is_nonrot, NULL))
+			return 0;
+	}
+
+	return 1;
+}
+
 void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
 			       struct queue_limits *limits)
 {
@@ -1324,6 +1392,11 @@
 	if (!dm_table_discard_zeroes_data(t))
 		q->limits.discard_zeroes_data = 0;
 
+	if (dm_table_is_nonrot(t))
+		queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
+	else
+		queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q);
+
 	dm_table_set_integrity(t);
 
 	/*
diff -druN linux-libre-3.1-gnu/drivers/md/dm-thin.c linux-libre-3.2-gnu/drivers/md/dm-thin.c
--- linux-libre-3.1-gnu/drivers/md/dm-thin.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/dm-thin.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2428 @@
+/*
+ * Copyright (C) 2011 Red Hat UK.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-thin-metadata.h"
+
+#include <linux/device-mapper.h>
+#include <linux/dm-io.h>
+#include <linux/dm-kcopyd.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#define	DM_MSG_PREFIX	"thin"
+
+/*
+ * Tunable constants
+ */
+#define ENDIO_HOOK_POOL_SIZE 10240
+#define DEFERRED_SET_SIZE 64
+#define MAPPING_POOL_SIZE 1024
+#define PRISON_CELLS 1024
+
+/*
+ * The block size of the device holding pool data must be
+ * between 64KB and 1GB.
+ */
+#define DATA_DEV_BLOCK_SIZE_MIN_SECTORS (64 * 1024 >> SECTOR_SHIFT)
+#define DATA_DEV_BLOCK_SIZE_MAX_SECTORS (1024 * 1024 * 1024 >> SECTOR_SHIFT)
+
+/*
+ * The metadata device is currently limited in size.  The limitation is
+ * checked lower down in dm-space-map-metadata, but we also check it here
+ * so we can fail early.
+ *
+ * We have one block of index, which can hold 255 index entries.  Each
+ * index entry contains allocation info about 16k metadata blocks.
+ */
+#define METADATA_DEV_MAX_SECTORS (255 * (1 << 14) * (THIN_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT)))
+
+/*
+ * Device id is restricted to 24 bits.
+ */
+#define MAX_DEV_ID ((1 << 24) - 1)
+
+/*
+ * How do we handle breaking sharing of data blocks?
+ * =================================================
+ *
+ * We use a standard copy-on-write btree to store the mappings for the
+ * devices (note I'm talking about copy-on-write of the metadata here, not
+ * the data).  When you take an internal snapshot you clone the root node
+ * of the origin btree.  After this there is no concept of an origin or a
+ * snapshot.  They are just two device trees that happen to point to the
+ * same data blocks.
+ *
+ * When we get a write in we decide if it's to a shared data block using
+ * some timestamp magic.  If it is, we have to break sharing.
+ *
+ * Let's say we write to a shared block in what was the origin.  The
+ * steps are:
+ *
+ * i) plug io further to this physical block. (see bio_prison code).
+ *
+ * ii) quiesce any read io to that shared data block.  Obviously
+ * including all devices that share this block.  (see deferred_set code)
+ *
+ * iii) copy the data block to a newly allocate block.  This step can be
+ * missed out if the io covers the block. (schedule_copy).
+ *
+ * iv) insert the new mapping into the origin's btree
+ * (process_prepared_mappings).  This act of inserting breaks some
+ * sharing of btree nodes between the two devices.  Breaking sharing only
+ * effects the btree of that specific device.  Btrees for the other
+ * devices that share the block never change.  The btree for the origin
+ * device as it was after the last commit is untouched, ie. we're using
+ * persistent data structures in the functional programming sense.
+ *
+ * v) unplug io to this physical block, including the io that triggered
+ * the breaking of sharing.
+ *
+ * Steps (ii) and (iii) occur in parallel.
+ *
+ * The metadata _doesn't_ need to be committed before the io continues.  We
+ * get away with this because the io is always written to a _new_ block.
+ * If there's a crash, then:
+ *
+ * - The origin mapping will point to the old origin block (the shared
+ * one).  This will contain the data as it was before the io that triggered
+ * the breaking of sharing came in.
+ *
+ * - The snap mapping still points to the old block.  As it would after
+ * the commit.
+ *
+ * The downside of this scheme is the timestamp magic isn't perfect, and
+ * will continue to think that data block in the snapshot device is shared
+ * even after the write to the origin has broken sharing.  I suspect data
+ * blocks will typically be shared by many different devices, so we're
+ * breaking sharing n + 1 times, rather than n, where n is the number of
+ * devices that reference this data block.  At the moment I think the
+ * benefits far, far outweigh the disadvantages.
+ */
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Sometimes we can't deal with a bio straight away.  We put them in prison
+ * where they can't cause any mischief.  Bios are put in a cell identified
+ * by a key, multiple bios can be in the same cell.  When the cell is
+ * subsequently unlocked the bios become available.
+ */
+struct bio_prison;
+
+struct cell_key {
+	int virtual;
+	dm_thin_id dev;
+	dm_block_t block;
+};
+
+struct cell {
+	struct hlist_node list;
+	struct bio_prison *prison;
+	struct cell_key key;
+	unsigned count;
+	struct bio_list bios;
+};
+
+struct bio_prison {
+	spinlock_t lock;
+	mempool_t *cell_pool;
+
+	unsigned nr_buckets;
+	unsigned hash_mask;
+	struct hlist_head *cells;
+};
+
+static uint32_t calc_nr_buckets(unsigned nr_cells)
+{
+	uint32_t n = 128;
+
+	nr_cells /= 4;
+	nr_cells = min(nr_cells, 8192u);
+
+	while (n < nr_cells)
+		n <<= 1;
+
+	return n;
+}
+
+/*
+ * @nr_cells should be the number of cells you want in use _concurrently_.
+ * Don't confuse it with the number of distinct keys.
+ */
+static struct bio_prison *prison_create(unsigned nr_cells)
+{
+	unsigned i;
+	uint32_t nr_buckets = calc_nr_buckets(nr_cells);
+	size_t len = sizeof(struct bio_prison) +
+		(sizeof(struct hlist_head) * nr_buckets);
+	struct bio_prison *prison = kmalloc(len, GFP_KERNEL);
+
+	if (!prison)
+		return NULL;
+
+	spin_lock_init(&prison->lock);
+	prison->cell_pool = mempool_create_kmalloc_pool(nr_cells,
+							sizeof(struct cell));
+	if (!prison->cell_pool) {
+		kfree(prison);
+		return NULL;
+	}
+
+	prison->nr_buckets = nr_buckets;
+	prison->hash_mask = nr_buckets - 1;
+	prison->cells = (struct hlist_head *) (prison + 1);
+	for (i = 0; i < nr_buckets; i++)
+		INIT_HLIST_HEAD(prison->cells + i);
+
+	return prison;
+}
+
+static void prison_destroy(struct bio_prison *prison)
+{
+	mempool_destroy(prison->cell_pool);
+	kfree(prison);
+}
+
+static uint32_t hash_key(struct bio_prison *prison, struct cell_key *key)
+{
+	const unsigned long BIG_PRIME = 4294967291UL;
+	uint64_t hash = key->block * BIG_PRIME;
+
+	return (uint32_t) (hash & prison->hash_mask);
+}
+
+static int keys_equal(struct cell_key *lhs, struct cell_key *rhs)
+{
+	       return (lhs->virtual == rhs->virtual) &&
+		       (lhs->dev == rhs->dev) &&
+		       (lhs->block == rhs->block);
+}
+
+static struct cell *__search_bucket(struct hlist_head *bucket,
+				    struct cell_key *key)
+{
+	struct cell *cell;
+	struct hlist_node *tmp;
+
+	hlist_for_each_entry(cell, tmp, bucket, list)
+		if (keys_equal(&cell->key, key))
+			return cell;
+
+	return NULL;
+}
+
+/*
+ * This may block if a new cell needs allocating.  You must ensure that
+ * cells will be unlocked even if the calling thread is blocked.
+ *
+ * Returns the number of entries in the cell prior to the new addition
+ * or < 0 on failure.
+ */
+static int bio_detain(struct bio_prison *prison, struct cell_key *key,
+		      struct bio *inmate, struct cell **ref)
+{
+	int r;
+	unsigned long flags;
+	uint32_t hash = hash_key(prison, key);
+	struct cell *uninitialized_var(cell), *cell2 = NULL;
+
+	BUG_ON(hash > prison->nr_buckets);
+
+	spin_lock_irqsave(&prison->lock, flags);
+	cell = __search_bucket(prison->cells + hash, key);
+
+	if (!cell) {
+		/*
+		 * Allocate a new cell
+		 */
+		spin_unlock_irqrestore(&prison->lock, flags);
+		cell2 = mempool_alloc(prison->cell_pool, GFP_NOIO);
+		spin_lock_irqsave(&prison->lock, flags);
+
+		/*
+		 * We've been unlocked, so we have to double check that
+		 * nobody else has inserted this cell in the meantime.
+		 */
+		cell = __search_bucket(prison->cells + hash, key);
+
+		if (!cell) {
+			cell = cell2;
+			cell2 = NULL;
+
+			cell->prison = prison;
+			memcpy(&cell->key, key, sizeof(cell->key));
+			cell->count = 0;
+			bio_list_init(&cell->bios);
+			hlist_add_head(&cell->list, prison->cells + hash);
+		}
+	}
+
+	r = cell->count++;
+	bio_list_add(&cell->bios, inmate);
+	spin_unlock_irqrestore(&prison->lock, flags);
+
+	if (cell2)
+		mempool_free(cell2, prison->cell_pool);
+
+	*ref = cell;
+
+	return r;
+}
+
+/*
+ * @inmates must have been initialised prior to this call
+ */
+static void __cell_release(struct cell *cell, struct bio_list *inmates)
+{
+	struct bio_prison *prison = cell->prison;
+
+	hlist_del(&cell->list);
+
+	if (inmates)
+		bio_list_merge(inmates, &cell->bios);
+
+	mempool_free(cell, prison->cell_pool);
+}
+
+static void cell_release(struct cell *cell, struct bio_list *bios)
+{
+	unsigned long flags;
+	struct bio_prison *prison = cell->prison;
+
+	spin_lock_irqsave(&prison->lock, flags);
+	__cell_release(cell, bios);
+	spin_unlock_irqrestore(&prison->lock, flags);
+}
+
+/*
+ * There are a couple of places where we put a bio into a cell briefly
+ * before taking it out again.  In these situations we know that no other
+ * bio may be in the cell.  This function releases the cell, and also does
+ * a sanity check.
+ */
+static void cell_release_singleton(struct cell *cell, struct bio *bio)
+{
+	struct bio_prison *prison = cell->prison;
+	struct bio_list bios;
+	struct bio *b;
+	unsigned long flags;
+
+	bio_list_init(&bios);
+
+	spin_lock_irqsave(&prison->lock, flags);
+	__cell_release(cell, &bios);
+	spin_unlock_irqrestore(&prison->lock, flags);
+
+	b = bio_list_pop(&bios);
+	BUG_ON(b != bio);
+	BUG_ON(!bio_list_empty(&bios));
+}
+
+static void cell_error(struct cell *cell)
+{
+	struct bio_prison *prison = cell->prison;
+	struct bio_list bios;
+	struct bio *bio;
+	unsigned long flags;
+
+	bio_list_init(&bios);
+
+	spin_lock_irqsave(&prison->lock, flags);
+	__cell_release(cell, &bios);
+	spin_unlock_irqrestore(&prison->lock, flags);
+
+	while ((bio = bio_list_pop(&bios)))
+		bio_io_error(bio);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * We use the deferred set to keep track of pending reads to shared blocks.
+ * We do this to ensure the new mapping caused by a write isn't performed
+ * until these prior reads have completed.  Otherwise the insertion of the
+ * new mapping could free the old block that the read bios are mapped to.
+ */
+
+struct deferred_set;
+struct deferred_entry {
+	struct deferred_set *ds;
+	unsigned count;
+	struct list_head work_items;
+};
+
+struct deferred_set {
+	spinlock_t lock;
+	unsigned current_entry;
+	unsigned sweeper;
+	struct deferred_entry entries[DEFERRED_SET_SIZE];
+};
+
+static void ds_init(struct deferred_set *ds)
+{
+	int i;
+
+	spin_lock_init(&ds->lock);
+	ds->current_entry = 0;
+	ds->sweeper = 0;
+	for (i = 0; i < DEFERRED_SET_SIZE; i++) {
+		ds->entries[i].ds = ds;
+		ds->entries[i].count = 0;
+		INIT_LIST_HEAD(&ds->entries[i].work_items);
+	}
+}
+
+static struct deferred_entry *ds_inc(struct deferred_set *ds)
+{
+	unsigned long flags;
+	struct deferred_entry *entry;
+
+	spin_lock_irqsave(&ds->lock, flags);
+	entry = ds->entries + ds->current_entry;
+	entry->count++;
+	spin_unlock_irqrestore(&ds->lock, flags);
+
+	return entry;
+}
+
+static unsigned ds_next(unsigned index)
+{
+	return (index + 1) % DEFERRED_SET_SIZE;
+}
+
+static void __sweep(struct deferred_set *ds, struct list_head *head)
+{
+	while ((ds->sweeper != ds->current_entry) &&
+	       !ds->entries[ds->sweeper].count) {
+		list_splice_init(&ds->entries[ds->sweeper].work_items, head);
+		ds->sweeper = ds_next(ds->sweeper);
+	}
+
+	if ((ds->sweeper == ds->current_entry) && !ds->entries[ds->sweeper].count)
+		list_splice_init(&ds->entries[ds->sweeper].work_items, head);
+}
+
+static void ds_dec(struct deferred_entry *entry, struct list_head *head)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&entry->ds->lock, flags);
+	BUG_ON(!entry->count);
+	--entry->count;
+	__sweep(entry->ds, head);
+	spin_unlock_irqrestore(&entry->ds->lock, flags);
+}
+
+/*
+ * Returns 1 if deferred or 0 if no pending items to delay job.
+ */
+static int ds_add_work(struct deferred_set *ds, struct list_head *work)
+{
+	int r = 1;
+	unsigned long flags;
+	unsigned next_entry;
+
+	spin_lock_irqsave(&ds->lock, flags);
+	if ((ds->sweeper == ds->current_entry) &&
+	    !ds->entries[ds->current_entry].count)
+		r = 0;
+	else {
+		list_add(work, &ds->entries[ds->current_entry].work_items);
+		next_entry = ds_next(ds->current_entry);
+		if (!ds->entries[next_entry].count)
+			ds->current_entry = next_entry;
+	}
+	spin_unlock_irqrestore(&ds->lock, flags);
+
+	return r;
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Key building.
+ */
+static void build_data_key(struct dm_thin_device *td,
+			   dm_block_t b, struct cell_key *key)
+{
+	key->virtual = 0;
+	key->dev = dm_thin_dev_id(td);
+	key->block = b;
+}
+
+static void build_virtual_key(struct dm_thin_device *td, dm_block_t b,
+			      struct cell_key *key)
+{
+	key->virtual = 1;
+	key->dev = dm_thin_dev_id(td);
+	key->block = b;
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * A pool device ties together a metadata device and a data device.  It
+ * also provides the interface for creating and destroying internal
+ * devices.
+ */
+struct new_mapping;
+struct pool {
+	struct list_head list;
+	struct dm_target *ti;	/* Only set if a pool target is bound */
+
+	struct mapped_device *pool_md;
+	struct block_device *md_dev;
+	struct dm_pool_metadata *pmd;
+
+	uint32_t sectors_per_block;
+	unsigned block_shift;
+	dm_block_t offset_mask;
+	dm_block_t low_water_blocks;
+
+	unsigned zero_new_blocks:1;
+	unsigned low_water_triggered:1;	/* A dm event has been sent */
+	unsigned no_free_space:1;	/* A -ENOSPC warning has been issued */
+
+	struct bio_prison *prison;
+	struct dm_kcopyd_client *copier;
+
+	struct workqueue_struct *wq;
+	struct work_struct worker;
+
+	unsigned ref_count;
+
+	spinlock_t lock;
+	struct bio_list deferred_bios;
+	struct bio_list deferred_flush_bios;
+	struct list_head prepared_mappings;
+
+	struct bio_list retry_on_resume_list;
+
+	struct deferred_set ds;	/* FIXME: move to thin_c */
+
+	struct new_mapping *next_mapping;
+	mempool_t *mapping_pool;
+	mempool_t *endio_hook_pool;
+};
+
+/*
+ * Target context for a pool.
+ */
+struct pool_c {
+	struct dm_target *ti;
+	struct pool *pool;
+	struct dm_dev *data_dev;
+	struct dm_dev *metadata_dev;
+	struct dm_target_callbacks callbacks;
+
+	dm_block_t low_water_blocks;
+	unsigned zero_new_blocks:1;
+};
+
+/*
+ * Target context for a thin.
+ */
+struct thin_c {
+	struct dm_dev *pool_dev;
+	dm_thin_id dev_id;
+
+	struct pool *pool;
+	struct dm_thin_device *td;
+};
+
+/*----------------------------------------------------------------*/
+
+/*
+ * A global list of pools that uses a struct mapped_device as a key.
+ */
+static struct dm_thin_pool_table {
+	struct mutex mutex;
+	struct list_head pools;
+} dm_thin_pool_table;
+
+static void pool_table_init(void)
+{
+	mutex_init(&dm_thin_pool_table.mutex);
+	INIT_LIST_HEAD(&dm_thin_pool_table.pools);
+}
+
+static void __pool_table_insert(struct pool *pool)
+{
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+	list_add(&pool->list, &dm_thin_pool_table.pools);
+}
+
+static void __pool_table_remove(struct pool *pool)
+{
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+	list_del(&pool->list);
+}
+
+static struct pool *__pool_table_lookup(struct mapped_device *md)
+{
+	struct pool *pool = NULL, *tmp;
+
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+
+	list_for_each_entry(tmp, &dm_thin_pool_table.pools, list) {
+		if (tmp->pool_md == md) {
+			pool = tmp;
+			break;
+		}
+	}
+
+	return pool;
+}
+
+static struct pool *__pool_table_lookup_metadata_dev(struct block_device *md_dev)
+{
+	struct pool *pool = NULL, *tmp;
+
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+
+	list_for_each_entry(tmp, &dm_thin_pool_table.pools, list) {
+		if (tmp->md_dev == md_dev) {
+			pool = tmp;
+			break;
+		}
+	}
+
+	return pool;
+}
+
+/*----------------------------------------------------------------*/
+
+static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
+{
+	struct bio *bio;
+	struct bio_list bios;
+
+	bio_list_init(&bios);
+	bio_list_merge(&bios, master);
+	bio_list_init(master);
+
+	while ((bio = bio_list_pop(&bios))) {
+		if (dm_get_mapinfo(bio)->ptr == tc)
+			bio_endio(bio, DM_ENDIO_REQUEUE);
+		else
+			bio_list_add(master, bio);
+	}
+}
+
+static void requeue_io(struct thin_c *tc)
+{
+	struct pool *pool = tc->pool;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	__requeue_bio_list(tc, &pool->deferred_bios);
+	__requeue_bio_list(tc, &pool->retry_on_resume_list);
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+/*
+ * This section of code contains the logic for processing a thin device's IO.
+ * Much of the code depends on pool object resources (lists, workqueues, etc)
+ * but most is exclusively called from the thin target rather than the thin-pool
+ * target.
+ */
+
+static dm_block_t get_bio_block(struct thin_c *tc, struct bio *bio)
+{
+	return bio->bi_sector >> tc->pool->block_shift;
+}
+
+static void remap(struct thin_c *tc, struct bio *bio, dm_block_t block)
+{
+	struct pool *pool = tc->pool;
+
+	bio->bi_bdev = tc->pool_dev->bdev;
+	bio->bi_sector = (block << pool->block_shift) +
+		(bio->bi_sector & pool->offset_mask);
+}
+
+static void remap_and_issue(struct thin_c *tc, struct bio *bio,
+			    dm_block_t block)
+{
+	struct pool *pool = tc->pool;
+	unsigned long flags;
+
+	remap(tc, bio, block);
+
+	/*
+	 * Batch together any FUA/FLUSH bios we find and then issue
+	 * a single commit for them in process_deferred_bios().
+	 */
+	if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
+		spin_lock_irqsave(&pool->lock, flags);
+		bio_list_add(&pool->deferred_flush_bios, bio);
+		spin_unlock_irqrestore(&pool->lock, flags);
+	} else
+		generic_make_request(bio);
+}
+
+/*
+ * wake_worker() is used when new work is queued and when pool_resume is
+ * ready to continue deferred IO processing.
+ */
+static void wake_worker(struct pool *pool)
+{
+	queue_work(pool->wq, &pool->worker);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Bio endio functions.
+ */
+struct endio_hook {
+	struct thin_c *tc;
+	bio_end_io_t *saved_bi_end_io;
+	struct deferred_entry *entry;
+};
+
+struct new_mapping {
+	struct list_head list;
+
+	int prepared;
+
+	struct thin_c *tc;
+	dm_block_t virt_block;
+	dm_block_t data_block;
+	struct cell *cell;
+	int err;
+
+	/*
+	 * If the bio covers the whole area of a block then we can avoid
+	 * zeroing or copying.  Instead this bio is hooked.  The bio will
+	 * still be in the cell, so care has to be taken to avoid issuing
+	 * the bio twice.
+	 */
+	struct bio *bio;
+	bio_end_io_t *saved_bi_end_io;
+};
+
+static void __maybe_add_mapping(struct new_mapping *m)
+{
+	struct pool *pool = m->tc->pool;
+
+	if (list_empty(&m->list) && m->prepared) {
+		list_add(&m->list, &pool->prepared_mappings);
+		wake_worker(pool);
+	}
+}
+
+static void copy_complete(int read_err, unsigned long write_err, void *context)
+{
+	unsigned long flags;
+	struct new_mapping *m = context;
+	struct pool *pool = m->tc->pool;
+
+	m->err = read_err || write_err ? -EIO : 0;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	m->prepared = 1;
+	__maybe_add_mapping(m);
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+static void overwrite_endio(struct bio *bio, int err)
+{
+	unsigned long flags;
+	struct new_mapping *m = dm_get_mapinfo(bio)->ptr;
+	struct pool *pool = m->tc->pool;
+
+	m->err = err;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	m->prepared = 1;
+	__maybe_add_mapping(m);
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+static void shared_read_endio(struct bio *bio, int err)
+{
+	struct list_head mappings;
+	struct new_mapping *m, *tmp;
+	struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
+	unsigned long flags;
+	struct pool *pool = h->tc->pool;
+
+	bio->bi_end_io = h->saved_bi_end_io;
+	bio_endio(bio, err);
+
+	INIT_LIST_HEAD(&mappings);
+	ds_dec(h->entry, &mappings);
+
+	spin_lock_irqsave(&pool->lock, flags);
+	list_for_each_entry_safe(m, tmp, &mappings, list) {
+		list_del(&m->list);
+		INIT_LIST_HEAD(&m->list);
+		__maybe_add_mapping(m);
+	}
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	mempool_free(h, pool->endio_hook_pool);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Workqueue.
+ */
+
+/*
+ * Prepared mapping jobs.
+ */
+
+/*
+ * This sends the bios in the cell back to the deferred_bios list.
+ */
+static void cell_defer(struct thin_c *tc, struct cell *cell,
+		       dm_block_t data_block)
+{
+	struct pool *pool = tc->pool;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	cell_release(cell, &pool->deferred_bios);
+	spin_unlock_irqrestore(&tc->pool->lock, flags);
+
+	wake_worker(pool);
+}
+
+/*
+ * Same as cell_defer above, except it omits one particular detainee,
+ * a write bio that covers the block and has already been processed.
+ */
+static void cell_defer_except(struct thin_c *tc, struct cell *cell,
+			      struct bio *exception)
+{
+	struct bio_list bios;
+	struct bio *bio;
+	struct pool *pool = tc->pool;
+	unsigned long flags;
+
+	bio_list_init(&bios);
+	cell_release(cell, &bios);
+
+	spin_lock_irqsave(&pool->lock, flags);
+	while ((bio = bio_list_pop(&bios)))
+		if (bio != exception)
+			bio_list_add(&pool->deferred_bios, bio);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	wake_worker(pool);
+}
+
+static void process_prepared_mapping(struct new_mapping *m)
+{
+	struct thin_c *tc = m->tc;
+	struct bio *bio;
+	int r;
+
+	bio = m->bio;
+	if (bio)
+		bio->bi_end_io = m->saved_bi_end_io;
+
+	if (m->err) {
+		cell_error(m->cell);
+		return;
+	}
+
+	/*
+	 * Commit the prepared block into the mapping btree.
+	 * Any I/O for this block arriving after this point will get
+	 * remapped to it directly.
+	 */
+	r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block);
+	if (r) {
+		DMERR("dm_thin_insert_block() failed");
+		cell_error(m->cell);
+		return;
+	}
+
+	/*
+	 * Release any bios held while the block was being provisioned.
+	 * If we are processing a write bio that completely covers the block,
+	 * we already processed it so can ignore it now when processing
+	 * the bios in the cell.
+	 */
+	if (bio) {
+		cell_defer_except(tc, m->cell, bio);
+		bio_endio(bio, 0);
+	} else
+		cell_defer(tc, m->cell, m->data_block);
+
+	list_del(&m->list);
+	mempool_free(m, tc->pool->mapping_pool);
+}
+
+static void process_prepared_mappings(struct pool *pool)
+{
+	unsigned long flags;
+	struct list_head maps;
+	struct new_mapping *m, *tmp;
+
+	INIT_LIST_HEAD(&maps);
+	spin_lock_irqsave(&pool->lock, flags);
+	list_splice_init(&pool->prepared_mappings, &maps);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	list_for_each_entry_safe(m, tmp, &maps, list)
+		process_prepared_mapping(m);
+}
+
+/*
+ * Deferred bio jobs.
+ */
+static int io_overwrites_block(struct pool *pool, struct bio *bio)
+{
+	return ((bio_data_dir(bio) == WRITE) &&
+		!(bio->bi_sector & pool->offset_mask)) &&
+		(bio->bi_size == (pool->sectors_per_block << SECTOR_SHIFT));
+}
+
+static void save_and_set_endio(struct bio *bio, bio_end_io_t **save,
+			       bio_end_io_t *fn)
+{
+	*save = bio->bi_end_io;
+	bio->bi_end_io = fn;
+}
+
+static int ensure_next_mapping(struct pool *pool)
+{
+	if (pool->next_mapping)
+		return 0;
+
+	pool->next_mapping = mempool_alloc(pool->mapping_pool, GFP_ATOMIC);
+
+	return pool->next_mapping ? 0 : -ENOMEM;
+}
+
+static struct new_mapping *get_next_mapping(struct pool *pool)
+{
+	struct new_mapping *r = pool->next_mapping;
+
+	BUG_ON(!pool->next_mapping);
+
+	pool->next_mapping = NULL;
+
+	return r;
+}
+
+static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
+			  dm_block_t data_origin, dm_block_t data_dest,
+			  struct cell *cell, struct bio *bio)
+{
+	int r;
+	struct pool *pool = tc->pool;
+	struct new_mapping *m = get_next_mapping(pool);
+
+	INIT_LIST_HEAD(&m->list);
+	m->prepared = 0;
+	m->tc = tc;
+	m->virt_block = virt_block;
+	m->data_block = data_dest;
+	m->cell = cell;
+	m->err = 0;
+	m->bio = NULL;
+
+	ds_add_work(&pool->ds, &m->list);
+
+	/*
+	 * IO to pool_dev remaps to the pool target's data_dev.
+	 *
+	 * If the whole block of data is being overwritten, we can issue the
+	 * bio immediately. Otherwise we use kcopyd to clone the data first.
+	 */
+	if (io_overwrites_block(pool, bio)) {
+		m->bio = bio;
+		save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
+		dm_get_mapinfo(bio)->ptr = m;
+		remap_and_issue(tc, bio, data_dest);
+	} else {
+		struct dm_io_region from, to;
+
+		from.bdev = tc->pool_dev->bdev;
+		from.sector = data_origin * pool->sectors_per_block;
+		from.count = pool->sectors_per_block;
+
+		to.bdev = tc->pool_dev->bdev;
+		to.sector = data_dest * pool->sectors_per_block;
+		to.count = pool->sectors_per_block;
+
+		r = dm_kcopyd_copy(pool->copier, &from, 1, &to,
+				   0, copy_complete, m);
+		if (r < 0) {
+			mempool_free(m, pool->mapping_pool);
+			DMERR("dm_kcopyd_copy() failed");
+			cell_error(cell);
+		}
+	}
+}
+
+static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
+			  dm_block_t data_block, struct cell *cell,
+			  struct bio *bio)
+{
+	struct pool *pool = tc->pool;
+	struct new_mapping *m = get_next_mapping(pool);
+
+	INIT_LIST_HEAD(&m->list);
+	m->prepared = 0;
+	m->tc = tc;
+	m->virt_block = virt_block;
+	m->data_block = data_block;
+	m->cell = cell;
+	m->err = 0;
+	m->bio = NULL;
+
+	/*
+	 * If the whole block of data is being overwritten or we are not
+	 * zeroing pre-existing data, we can issue the bio immediately.
+	 * Otherwise we use kcopyd to zero the data first.
+	 */
+	if (!pool->zero_new_blocks)
+		process_prepared_mapping(m);
+
+	else if (io_overwrites_block(pool, bio)) {
+		m->bio = bio;
+		save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
+		dm_get_mapinfo(bio)->ptr = m;
+		remap_and_issue(tc, bio, data_block);
+
+	} else {
+		int r;
+		struct dm_io_region to;
+
+		to.bdev = tc->pool_dev->bdev;
+		to.sector = data_block * pool->sectors_per_block;
+		to.count = pool->sectors_per_block;
+
+		r = dm_kcopyd_zero(pool->copier, 1, &to, 0, copy_complete, m);
+		if (r < 0) {
+			mempool_free(m, pool->mapping_pool);
+			DMERR("dm_kcopyd_zero() failed");
+			cell_error(cell);
+		}
+	}
+}
+
+static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
+{
+	int r;
+	dm_block_t free_blocks;
+	unsigned long flags;
+	struct pool *pool = tc->pool;
+
+	r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
+	if (r)
+		return r;
+
+	if (free_blocks <= pool->low_water_blocks && !pool->low_water_triggered) {
+		DMWARN("%s: reached low water mark, sending event.",
+		       dm_device_name(pool->pool_md));
+		spin_lock_irqsave(&pool->lock, flags);
+		pool->low_water_triggered = 1;
+		spin_unlock_irqrestore(&pool->lock, flags);
+		dm_table_event(pool->ti->table);
+	}
+
+	if (!free_blocks) {
+		if (pool->no_free_space)
+			return -ENOSPC;
+		else {
+			/*
+			 * Try to commit to see if that will free up some
+			 * more space.
+			 */
+			r = dm_pool_commit_metadata(pool->pmd);
+			if (r) {
+				DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+				      __func__, r);
+				return r;
+			}
+
+			r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
+			if (r)
+				return r;
+
+			/*
+			 * If we still have no space we set a flag to avoid
+			 * doing all this checking and return -ENOSPC.
+			 */
+			if (!free_blocks) {
+				DMWARN("%s: no free space available.",
+				       dm_device_name(pool->pool_md));
+				spin_lock_irqsave(&pool->lock, flags);
+				pool->no_free_space = 1;
+				spin_unlock_irqrestore(&pool->lock, flags);
+				return -ENOSPC;
+			}
+		}
+	}
+
+	r = dm_pool_alloc_data_block(pool->pmd, result);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+/*
+ * If we have run out of space, queue bios until the device is
+ * resumed, presumably after having been reloaded with more space.
+ */
+static void retry_on_resume(struct bio *bio)
+{
+	struct thin_c *tc = dm_get_mapinfo(bio)->ptr;
+	struct pool *pool = tc->pool;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	bio_list_add(&pool->retry_on_resume_list, bio);
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+static void no_space(struct cell *cell)
+{
+	struct bio *bio;
+	struct bio_list bios;
+
+	bio_list_init(&bios);
+	cell_release(cell, &bios);
+
+	while ((bio = bio_list_pop(&bios)))
+		retry_on_resume(bio);
+}
+
+static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
+			  struct cell_key *key,
+			  struct dm_thin_lookup_result *lookup_result,
+			  struct cell *cell)
+{
+	int r;
+	dm_block_t data_block;
+
+	r = alloc_data_block(tc, &data_block);
+	switch (r) {
+	case 0:
+		schedule_copy(tc, block, lookup_result->block,
+			      data_block, cell, bio);
+		break;
+
+	case -ENOSPC:
+		no_space(cell);
+		break;
+
+	default:
+		DMERR("%s: alloc_data_block() failed, error = %d", __func__, r);
+		cell_error(cell);
+		break;
+	}
+}
+
+static void process_shared_bio(struct thin_c *tc, struct bio *bio,
+			       dm_block_t block,
+			       struct dm_thin_lookup_result *lookup_result)
+{
+	struct cell *cell;
+	struct pool *pool = tc->pool;
+	struct cell_key key;
+
+	/*
+	 * If cell is already occupied, then sharing is already in the process
+	 * of being broken so we have nothing further to do here.
+	 */
+	build_data_key(tc->td, lookup_result->block, &key);
+	if (bio_detain(pool->prison, &key, bio, &cell))
+		return;
+
+	if (bio_data_dir(bio) == WRITE)
+		break_sharing(tc, bio, block, &key, lookup_result, cell);
+	else {
+		struct endio_hook *h;
+		h = mempool_alloc(pool->endio_hook_pool, GFP_NOIO);
+
+		h->tc = tc;
+		h->entry = ds_inc(&pool->ds);
+		save_and_set_endio(bio, &h->saved_bi_end_io, shared_read_endio);
+		dm_get_mapinfo(bio)->ptr = h;
+
+		cell_release_singleton(cell, bio);
+		remap_and_issue(tc, bio, lookup_result->block);
+	}
+}
+
+static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block,
+			    struct cell *cell)
+{
+	int r;
+	dm_block_t data_block;
+
+	/*
+	 * Remap empty bios (flushes) immediately, without provisioning.
+	 */
+	if (!bio->bi_size) {
+		cell_release_singleton(cell, bio);
+		remap_and_issue(tc, bio, 0);
+		return;
+	}
+
+	/*
+	 * Fill read bios with zeroes and complete them immediately.
+	 */
+	if (bio_data_dir(bio) == READ) {
+		zero_fill_bio(bio);
+		cell_release_singleton(cell, bio);
+		bio_endio(bio, 0);
+		return;
+	}
+
+	r = alloc_data_block(tc, &data_block);
+	switch (r) {
+	case 0:
+		schedule_zero(tc, block, data_block, cell, bio);
+		break;
+
+	case -ENOSPC:
+		no_space(cell);
+		break;
+
+	default:
+		DMERR("%s: alloc_data_block() failed, error = %d", __func__, r);
+		cell_error(cell);
+		break;
+	}
+}
+
+static void process_bio(struct thin_c *tc, struct bio *bio)
+{
+	int r;
+	dm_block_t block = get_bio_block(tc, bio);
+	struct cell *cell;
+	struct cell_key key;
+	struct dm_thin_lookup_result lookup_result;
+
+	/*
+	 * If cell is already occupied, then the block is already
+	 * being provisioned so we have nothing further to do here.
+	 */
+	build_virtual_key(tc->td, block, &key);
+	if (bio_detain(tc->pool->prison, &key, bio, &cell))
+		return;
+
+	r = dm_thin_find_block(tc->td, block, 1, &lookup_result);
+	switch (r) {
+	case 0:
+		/*
+		 * We can release this cell now.  This thread is the only
+		 * one that puts bios into a cell, and we know there were
+		 * no preceding bios.
+		 */
+		/*
+		 * TODO: this will probably have to change when discard goes
+		 * back in.
+		 */
+		cell_release_singleton(cell, bio);
+
+		if (lookup_result.shared)
+			process_shared_bio(tc, bio, block, &lookup_result);
+		else
+			remap_and_issue(tc, bio, lookup_result.block);
+		break;
+
+	case -ENODATA:
+		provision_block(tc, bio, block, cell);
+		break;
+
+	default:
+		DMERR("dm_thin_find_block() failed, error = %d", r);
+		bio_io_error(bio);
+		break;
+	}
+}
+
+static void process_deferred_bios(struct pool *pool)
+{
+	unsigned long flags;
+	struct bio *bio;
+	struct bio_list bios;
+	int r;
+
+	bio_list_init(&bios);
+
+	spin_lock_irqsave(&pool->lock, flags);
+	bio_list_merge(&bios, &pool->deferred_bios);
+	bio_list_init(&pool->deferred_bios);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	while ((bio = bio_list_pop(&bios))) {
+		struct thin_c *tc = dm_get_mapinfo(bio)->ptr;
+		/*
+		 * If we've got no free new_mapping structs, and processing
+		 * this bio might require one, we pause until there are some
+		 * prepared mappings to process.
+		 */
+		if (ensure_next_mapping(pool)) {
+			spin_lock_irqsave(&pool->lock, flags);
+			bio_list_merge(&pool->deferred_bios, &bios);
+			spin_unlock_irqrestore(&pool->lock, flags);
+
+			break;
+		}
+		process_bio(tc, bio);
+	}
+
+	/*
+	 * If there are any deferred flush bios, we must commit
+	 * the metadata before issuing them.
+	 */
+	bio_list_init(&bios);
+	spin_lock_irqsave(&pool->lock, flags);
+	bio_list_merge(&bios, &pool->deferred_flush_bios);
+	bio_list_init(&pool->deferred_flush_bios);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	if (bio_list_empty(&bios))
+		return;
+
+	r = dm_pool_commit_metadata(pool->pmd);
+	if (r) {
+		DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+		      __func__, r);
+		while ((bio = bio_list_pop(&bios)))
+			bio_io_error(bio);
+		return;
+	}
+
+	while ((bio = bio_list_pop(&bios)))
+		generic_make_request(bio);
+}
+
+static void do_worker(struct work_struct *ws)
+{
+	struct pool *pool = container_of(ws, struct pool, worker);
+
+	process_prepared_mappings(pool);
+	process_deferred_bios(pool);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Mapping functions.
+ */
+
+/*
+ * Called only while mapping a thin bio to hand it over to the workqueue.
+ */
+static void thin_defer_bio(struct thin_c *tc, struct bio *bio)
+{
+	unsigned long flags;
+	struct pool *pool = tc->pool;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	bio_list_add(&pool->deferred_bios, bio);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	wake_worker(pool);
+}
+
+/*
+ * Non-blocking function called from the thin target's map function.
+ */
+static int thin_bio_map(struct dm_target *ti, struct bio *bio,
+			union map_info *map_context)
+{
+	int r;
+	struct thin_c *tc = ti->private;
+	dm_block_t block = get_bio_block(tc, bio);
+	struct dm_thin_device *td = tc->td;
+	struct dm_thin_lookup_result result;
+
+	/*
+	 * Save the thin context for easy access from the deferred bio later.
+	 */
+	map_context->ptr = tc;
+
+	if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
+		thin_defer_bio(tc, bio);
+		return DM_MAPIO_SUBMITTED;
+	}
+
+	r = dm_thin_find_block(td, block, 0, &result);
+
+	/*
+	 * Note that we defer readahead too.
+	 */
+	switch (r) {
+	case 0:
+		if (unlikely(result.shared)) {
+			/*
+			 * We have a race condition here between the
+			 * result.shared value returned by the lookup and
+			 * snapshot creation, which may cause new
+			 * sharing.
+			 *
+			 * To avoid this always quiesce the origin before
+			 * taking the snap.  You want to do this anyway to
+			 * ensure a consistent application view
+			 * (i.e. lockfs).
+			 *
+			 * More distant ancestors are irrelevant. The
+			 * shared flag will be set in their case.
+			 */
+			thin_defer_bio(tc, bio);
+			r = DM_MAPIO_SUBMITTED;
+		} else {
+			remap(tc, bio, result.block);
+			r = DM_MAPIO_REMAPPED;
+		}
+		break;
+
+	case -ENODATA:
+		/*
+		 * In future, the failed dm_thin_find_block above could
+		 * provide the hint to load the metadata into cache.
+		 */
+	case -EWOULDBLOCK:
+		thin_defer_bio(tc, bio);
+		r = DM_MAPIO_SUBMITTED;
+		break;
+	}
+
+	return r;
+}
+
+static int pool_is_congested(struct dm_target_callbacks *cb, int bdi_bits)
+{
+	int r;
+	unsigned long flags;
+	struct pool_c *pt = container_of(cb, struct pool_c, callbacks);
+
+	spin_lock_irqsave(&pt->pool->lock, flags);
+	r = !bio_list_empty(&pt->pool->retry_on_resume_list);
+	spin_unlock_irqrestore(&pt->pool->lock, flags);
+
+	if (!r) {
+		struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
+		r = bdi_congested(&q->backing_dev_info, bdi_bits);
+	}
+
+	return r;
+}
+
+static void __requeue_bios(struct pool *pool)
+{
+	bio_list_merge(&pool->deferred_bios, &pool->retry_on_resume_list);
+	bio_list_init(&pool->retry_on_resume_list);
+}
+
+/*----------------------------------------------------------------
+ * Binding of control targets to a pool object
+ *--------------------------------------------------------------*/
+static int bind_control_target(struct pool *pool, struct dm_target *ti)
+{
+	struct pool_c *pt = ti->private;
+
+	pool->ti = ti;
+	pool->low_water_blocks = pt->low_water_blocks;
+	pool->zero_new_blocks = pt->zero_new_blocks;
+
+	return 0;
+}
+
+static void unbind_control_target(struct pool *pool, struct dm_target *ti)
+{
+	if (pool->ti == ti)
+		pool->ti = NULL;
+}
+
+/*----------------------------------------------------------------
+ * Pool creation
+ *--------------------------------------------------------------*/
+static void __pool_destroy(struct pool *pool)
+{
+	__pool_table_remove(pool);
+
+	if (dm_pool_metadata_close(pool->pmd) < 0)
+		DMWARN("%s: dm_pool_metadata_close() failed.", __func__);
+
+	prison_destroy(pool->prison);
+	dm_kcopyd_client_destroy(pool->copier);
+
+	if (pool->wq)
+		destroy_workqueue(pool->wq);
+
+	if (pool->next_mapping)
+		mempool_free(pool->next_mapping, pool->mapping_pool);
+	mempool_destroy(pool->mapping_pool);
+	mempool_destroy(pool->endio_hook_pool);
+	kfree(pool);
+}
+
+static struct pool *pool_create(struct mapped_device *pool_md,
+				struct block_device *metadata_dev,
+				unsigned long block_size, char **error)
+{
+	int r;
+	void *err_p;
+	struct pool *pool;
+	struct dm_pool_metadata *pmd;
+
+	pmd = dm_pool_metadata_open(metadata_dev, block_size);
+	if (IS_ERR(pmd)) {
+		*error = "Error creating metadata object";
+		return (struct pool *)pmd;
+	}
+
+	pool = kmalloc(sizeof(*pool), GFP_KERNEL);
+	if (!pool) {
+		*error = "Error allocating memory for pool";
+		err_p = ERR_PTR(-ENOMEM);
+		goto bad_pool;
+	}
+
+	pool->pmd = pmd;
+	pool->sectors_per_block = block_size;
+	pool->block_shift = ffs(block_size) - 1;
+	pool->offset_mask = block_size - 1;
+	pool->low_water_blocks = 0;
+	pool->zero_new_blocks = 1;
+	pool->prison = prison_create(PRISON_CELLS);
+	if (!pool->prison) {
+		*error = "Error creating pool's bio prison";
+		err_p = ERR_PTR(-ENOMEM);
+		goto bad_prison;
+	}
+
+	pool->copier = dm_kcopyd_client_create();
+	if (IS_ERR(pool->copier)) {
+		r = PTR_ERR(pool->copier);
+		*error = "Error creating pool's kcopyd client";
+		err_p = ERR_PTR(r);
+		goto bad_kcopyd_client;
+	}
+
+	/*
+	 * Create singlethreaded workqueue that will service all devices
+	 * that use this metadata.
+	 */
+	pool->wq = alloc_ordered_workqueue("dm-" DM_MSG_PREFIX, WQ_MEM_RECLAIM);
+	if (!pool->wq) {
+		*error = "Error creating pool's workqueue";
+		err_p = ERR_PTR(-ENOMEM);
+		goto bad_wq;
+	}
+
+	INIT_WORK(&pool->worker, do_worker);
+	spin_lock_init(&pool->lock);
+	bio_list_init(&pool->deferred_bios);
+	bio_list_init(&pool->deferred_flush_bios);
+	INIT_LIST_HEAD(&pool->prepared_mappings);
+	pool->low_water_triggered = 0;
+	pool->no_free_space = 0;
+	bio_list_init(&pool->retry_on_resume_list);
+	ds_init(&pool->ds);
+
+	pool->next_mapping = NULL;
+	pool->mapping_pool =
+		mempool_create_kmalloc_pool(MAPPING_POOL_SIZE, sizeof(struct new_mapping));
+	if (!pool->mapping_pool) {
+		*error = "Error creating pool's mapping mempool";
+		err_p = ERR_PTR(-ENOMEM);
+		goto bad_mapping_pool;
+	}
+
+	pool->endio_hook_pool =
+		mempool_create_kmalloc_pool(ENDIO_HOOK_POOL_SIZE, sizeof(struct endio_hook));
+	if (!pool->endio_hook_pool) {
+		*error = "Error creating pool's endio_hook mempool";
+		err_p = ERR_PTR(-ENOMEM);
+		goto bad_endio_hook_pool;
+	}
+	pool->ref_count = 1;
+	pool->pool_md = pool_md;
+	pool->md_dev = metadata_dev;
+	__pool_table_insert(pool);
+
+	return pool;
+
+bad_endio_hook_pool:
+	mempool_destroy(pool->mapping_pool);
+bad_mapping_pool:
+	destroy_workqueue(pool->wq);
+bad_wq:
+	dm_kcopyd_client_destroy(pool->copier);
+bad_kcopyd_client:
+	prison_destroy(pool->prison);
+bad_prison:
+	kfree(pool);
+bad_pool:
+	if (dm_pool_metadata_close(pmd))
+		DMWARN("%s: dm_pool_metadata_close() failed.", __func__);
+
+	return err_p;
+}
+
+static void __pool_inc(struct pool *pool)
+{
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+	pool->ref_count++;
+}
+
+static void __pool_dec(struct pool *pool)
+{
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+	BUG_ON(!pool->ref_count);
+	if (!--pool->ref_count)
+		__pool_destroy(pool);
+}
+
+static struct pool *__pool_find(struct mapped_device *pool_md,
+				struct block_device *metadata_dev,
+				unsigned long block_size, char **error)
+{
+	struct pool *pool = __pool_table_lookup_metadata_dev(metadata_dev);
+
+	if (pool) {
+		if (pool->pool_md != pool_md)
+			return ERR_PTR(-EBUSY);
+		__pool_inc(pool);
+
+	} else {
+		pool = __pool_table_lookup(pool_md);
+		if (pool) {
+			if (pool->md_dev != metadata_dev)
+				return ERR_PTR(-EINVAL);
+			__pool_inc(pool);
+
+		} else
+			pool = pool_create(pool_md, metadata_dev, block_size, error);
+	}
+
+	return pool;
+}
+
+/*----------------------------------------------------------------
+ * Pool target methods
+ *--------------------------------------------------------------*/
+static void pool_dtr(struct dm_target *ti)
+{
+	struct pool_c *pt = ti->private;
+
+	mutex_lock(&dm_thin_pool_table.mutex);
+
+	unbind_control_target(pt->pool, ti);
+	__pool_dec(pt->pool);
+	dm_put_device(ti, pt->metadata_dev);
+	dm_put_device(ti, pt->data_dev);
+	kfree(pt);
+
+	mutex_unlock(&dm_thin_pool_table.mutex);
+}
+
+struct pool_features {
+	unsigned zero_new_blocks:1;
+};
+
+static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
+			       struct dm_target *ti)
+{
+	int r;
+	unsigned argc;
+	const char *arg_name;
+
+	static struct dm_arg _args[] = {
+		{0, 1, "Invalid number of pool feature arguments"},
+	};
+
+	/*
+	 * No feature arguments supplied.
+	 */
+	if (!as->argc)
+		return 0;
+
+	r = dm_read_arg_group(_args, as, &argc, &ti->error);
+	if (r)
+		return -EINVAL;
+
+	while (argc && !r) {
+		arg_name = dm_shift_arg(as);
+		argc--;
+
+		if (!strcasecmp(arg_name, "skip_block_zeroing")) {
+			pf->zero_new_blocks = 0;
+			continue;
+		}
+
+		ti->error = "Unrecognised pool feature requested";
+		r = -EINVAL;
+	}
+
+	return r;
+}
+
+/*
+ * thin-pool <metadata dev> <data dev>
+ *	     <data block size (sectors)>
+ *	     <low water mark (blocks)>
+ *	     [<#feature args> [<arg>]*]
+ *
+ * Optional feature arguments are:
+ *	     skip_block_zeroing: skips the zeroing of newly-provisioned blocks.
+ */
+static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
+{
+	int r;
+	struct pool_c *pt;
+	struct pool *pool;
+	struct pool_features pf;
+	struct dm_arg_set as;
+	struct dm_dev *data_dev;
+	unsigned long block_size;
+	dm_block_t low_water_blocks;
+	struct dm_dev *metadata_dev;
+	sector_t metadata_dev_size;
+
+	/*
+	 * FIXME Remove validation from scope of lock.
+	 */
+	mutex_lock(&dm_thin_pool_table.mutex);
+
+	if (argc < 4) {
+		ti->error = "Invalid argument count";
+		r = -EINVAL;
+		goto out_unlock;
+	}
+	as.argc = argc;
+	as.argv = argv;
+
+	r = dm_get_device(ti, argv[0], FMODE_READ | FMODE_WRITE, &metadata_dev);
+	if (r) {
+		ti->error = "Error opening metadata block device";
+		goto out_unlock;
+	}
+
+	metadata_dev_size = i_size_read(metadata_dev->bdev->bd_inode) >> SECTOR_SHIFT;
+	if (metadata_dev_size > METADATA_DEV_MAX_SECTORS) {
+		ti->error = "Metadata device is too large";
+		r = -EINVAL;
+		goto out_metadata;
+	}
+
+	r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev);
+	if (r) {
+		ti->error = "Error getting data device";
+		goto out_metadata;
+	}
+
+	if (kstrtoul(argv[2], 10, &block_size) || !block_size ||
+	    block_size < DATA_DEV_BLOCK_SIZE_MIN_SECTORS ||
+	    block_size > DATA_DEV_BLOCK_SIZE_MAX_SECTORS ||
+	    !is_power_of_2(block_size)) {
+		ti->error = "Invalid block size";
+		r = -EINVAL;
+		goto out;
+	}
+
+	if (kstrtoull(argv[3], 10, (unsigned long long *)&low_water_blocks)) {
+		ti->error = "Invalid low water mark";
+		r = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Set default pool features.
+	 */
+	memset(&pf, 0, sizeof(pf));
+	pf.zero_new_blocks = 1;
+
+	dm_consume_args(&as, 4);
+	r = parse_pool_features(&as, &pf, ti);
+	if (r)
+		goto out;
+
+	pt = kzalloc(sizeof(*pt), GFP_KERNEL);
+	if (!pt) {
+		r = -ENOMEM;
+		goto out;
+	}
+
+	pool = __pool_find(dm_table_get_md(ti->table), metadata_dev->bdev,
+			   block_size, &ti->error);
+	if (IS_ERR(pool)) {
+		r = PTR_ERR(pool);
+		goto out_free_pt;
+	}
+
+	pt->pool = pool;
+	pt->ti = ti;
+	pt->metadata_dev = metadata_dev;
+	pt->data_dev = data_dev;
+	pt->low_water_blocks = low_water_blocks;
+	pt->zero_new_blocks = pf.zero_new_blocks;
+	ti->num_flush_requests = 1;
+	ti->num_discard_requests = 0;
+	ti->private = pt;
+
+	pt->callbacks.congested_fn = pool_is_congested;
+	dm_table_add_target_callbacks(ti->table, &pt->callbacks);
+
+	mutex_unlock(&dm_thin_pool_table.mutex);
+
+	return 0;
+
+out_free_pt:
+	kfree(pt);
+out:
+	dm_put_device(ti, data_dev);
+out_metadata:
+	dm_put_device(ti, metadata_dev);
+out_unlock:
+	mutex_unlock(&dm_thin_pool_table.mutex);
+
+	return r;
+}
+
+static int pool_map(struct dm_target *ti, struct bio *bio,
+		    union map_info *map_context)
+{
+	int r;
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+	unsigned long flags;
+
+	/*
+	 * As this is a singleton target, ti->begin is always zero.
+	 */
+	spin_lock_irqsave(&pool->lock, flags);
+	bio->bi_bdev = pt->data_dev->bdev;
+	r = DM_MAPIO_REMAPPED;
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	return r;
+}
+
+/*
+ * Retrieves the number of blocks of the data device from
+ * the superblock and compares it to the actual device size,
+ * thus resizing the data device in case it has grown.
+ *
+ * This both copes with opening preallocated data devices in the ctr
+ * being followed by a resume
+ * -and-
+ * calling the resume method individually after userspace has
+ * grown the data device in reaction to a table event.
+ */
+static int pool_preresume(struct dm_target *ti)
+{
+	int r;
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+	dm_block_t data_size, sb_data_size;
+
+	/*
+	 * Take control of the pool object.
+	 */
+	r = bind_control_target(pool, ti);
+	if (r)
+		return r;
+
+	data_size = ti->len >> pool->block_shift;
+	r = dm_pool_get_data_dev_size(pool->pmd, &sb_data_size);
+	if (r) {
+		DMERR("failed to retrieve data device size");
+		return r;
+	}
+
+	if (data_size < sb_data_size) {
+		DMERR("pool target too small, is %llu blocks (expected %llu)",
+		      data_size, sb_data_size);
+		return -EINVAL;
+
+	} else if (data_size > sb_data_size) {
+		r = dm_pool_resize_data_dev(pool->pmd, data_size);
+		if (r) {
+			DMERR("failed to resize data device");
+			return r;
+		}
+
+		r = dm_pool_commit_metadata(pool->pmd);
+		if (r) {
+			DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+			      __func__, r);
+			return r;
+		}
+	}
+
+	return 0;
+}
+
+static void pool_resume(struct dm_target *ti)
+{
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	pool->low_water_triggered = 0;
+	pool->no_free_space = 0;
+	__requeue_bios(pool);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	wake_worker(pool);
+}
+
+static void pool_postsuspend(struct dm_target *ti)
+{
+	int r;
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+
+	flush_workqueue(pool->wq);
+
+	r = dm_pool_commit_metadata(pool->pmd);
+	if (r < 0) {
+		DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+		      __func__, r);
+		/* FIXME: invalidate device? error the next FUA or FLUSH bio ?*/
+	}
+}
+
+static int check_arg_count(unsigned argc, unsigned args_required)
+{
+	if (argc != args_required) {
+		DMWARN("Message received with %u arguments instead of %u.",
+		       argc, args_required);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int read_dev_id(char *arg, dm_thin_id *dev_id, int warning)
+{
+	if (!kstrtoull(arg, 10, (unsigned long long *)dev_id) &&
+	    *dev_id <= MAX_DEV_ID)
+		return 0;
+
+	if (warning)
+		DMWARN("Message received with invalid device id: %s", arg);
+
+	return -EINVAL;
+}
+
+static int process_create_thin_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+	dm_thin_id dev_id;
+	int r;
+
+	r = check_arg_count(argc, 2);
+	if (r)
+		return r;
+
+	r = read_dev_id(argv[1], &dev_id, 1);
+	if (r)
+		return r;
+
+	r = dm_pool_create_thin(pool->pmd, dev_id);
+	if (r) {
+		DMWARN("Creation of new thinly-provisioned device with id %s failed.",
+		       argv[1]);
+		return r;
+	}
+
+	return 0;
+}
+
+static int process_create_snap_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+	dm_thin_id dev_id;
+	dm_thin_id origin_dev_id;
+	int r;
+
+	r = check_arg_count(argc, 3);
+	if (r)
+		return r;
+
+	r = read_dev_id(argv[1], &dev_id, 1);
+	if (r)
+		return r;
+
+	r = read_dev_id(argv[2], &origin_dev_id, 1);
+	if (r)
+		return r;
+
+	r = dm_pool_create_snap(pool->pmd, dev_id, origin_dev_id);
+	if (r) {
+		DMWARN("Creation of new snapshot %s of device %s failed.",
+		       argv[1], argv[2]);
+		return r;
+	}
+
+	return 0;
+}
+
+static int process_delete_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+	dm_thin_id dev_id;
+	int r;
+
+	r = check_arg_count(argc, 2);
+	if (r)
+		return r;
+
+	r = read_dev_id(argv[1], &dev_id, 1);
+	if (r)
+		return r;
+
+	r = dm_pool_delete_thin_device(pool->pmd, dev_id);
+	if (r)
+		DMWARN("Deletion of thin device %s failed.", argv[1]);
+
+	return r;
+}
+
+static int process_set_transaction_id_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+	dm_thin_id old_id, new_id;
+	int r;
+
+	r = check_arg_count(argc, 3);
+	if (r)
+		return r;
+
+	if (kstrtoull(argv[1], 10, (unsigned long long *)&old_id)) {
+		DMWARN("set_transaction_id message: Unrecognised id %s.", argv[1]);
+		return -EINVAL;
+	}
+
+	if (kstrtoull(argv[2], 10, (unsigned long long *)&new_id)) {
+		DMWARN("set_transaction_id message: Unrecognised new id %s.", argv[2]);
+		return -EINVAL;
+	}
+
+	r = dm_pool_set_metadata_transaction_id(pool->pmd, old_id, new_id);
+	if (r) {
+		DMWARN("Failed to change transaction id from %s to %s.",
+		       argv[1], argv[2]);
+		return r;
+	}
+
+	return 0;
+}
+
+/*
+ * Messages supported:
+ *   create_thin	<dev_id>
+ *   create_snap	<dev_id> <origin_id>
+ *   delete		<dev_id>
+ *   trim		<dev_id> <new_size_in_sectors>
+ *   set_transaction_id <current_trans_id> <new_trans_id>
+ */
+static int pool_message(struct dm_target *ti, unsigned argc, char **argv)
+{
+	int r = -EINVAL;
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+
+	if (!strcasecmp(argv[0], "create_thin"))
+		r = process_create_thin_mesg(argc, argv, pool);
+
+	else if (!strcasecmp(argv[0], "create_snap"))
+		r = process_create_snap_mesg(argc, argv, pool);
+
+	else if (!strcasecmp(argv[0], "delete"))
+		r = process_delete_mesg(argc, argv, pool);
+
+	else if (!strcasecmp(argv[0], "set_transaction_id"))
+		r = process_set_transaction_id_mesg(argc, argv, pool);
+
+	else
+		DMWARN("Unrecognised thin pool target message received: %s", argv[0]);
+
+	if (!r) {
+		r = dm_pool_commit_metadata(pool->pmd);
+		if (r)
+			DMERR("%s message: dm_pool_commit_metadata() failed, error = %d",
+			      argv[0], r);
+	}
+
+	return r;
+}
+
+/*
+ * Status line is:
+ *    <transaction id> <used metadata sectors>/<total metadata sectors>
+ *    <used data sectors>/<total data sectors> <held metadata root>
+ */
+static int pool_status(struct dm_target *ti, status_type_t type,
+		       char *result, unsigned maxlen)
+{
+	int r;
+	unsigned sz = 0;
+	uint64_t transaction_id;
+	dm_block_t nr_free_blocks_data;
+	dm_block_t nr_free_blocks_metadata;
+	dm_block_t nr_blocks_data;
+	dm_block_t nr_blocks_metadata;
+	dm_block_t held_root;
+	char buf[BDEVNAME_SIZE];
+	char buf2[BDEVNAME_SIZE];
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+
+	switch (type) {
+	case STATUSTYPE_INFO:
+		r = dm_pool_get_metadata_transaction_id(pool->pmd,
+							&transaction_id);
+		if (r)
+			return r;
+
+		r = dm_pool_get_free_metadata_block_count(pool->pmd,
+							  &nr_free_blocks_metadata);
+		if (r)
+			return r;
+
+		r = dm_pool_get_metadata_dev_size(pool->pmd, &nr_blocks_metadata);
+		if (r)
+			return r;
+
+		r = dm_pool_get_free_block_count(pool->pmd,
+						 &nr_free_blocks_data);
+		if (r)
+			return r;
+
+		r = dm_pool_get_data_dev_size(pool->pmd, &nr_blocks_data);
+		if (r)
+			return r;
+
+		r = dm_pool_get_held_metadata_root(pool->pmd, &held_root);
+		if (r)
+			return r;
+
+		DMEMIT("%llu %llu/%llu %llu/%llu ",
+		       (unsigned long long)transaction_id,
+		       (unsigned long long)(nr_blocks_metadata - nr_free_blocks_metadata),
+		       (unsigned long long)nr_blocks_metadata,
+		       (unsigned long long)(nr_blocks_data - nr_free_blocks_data),
+		       (unsigned long long)nr_blocks_data);
+
+		if (held_root)
+			DMEMIT("%llu", held_root);
+		else
+			DMEMIT("-");
+
+		break;
+
+	case STATUSTYPE_TABLE:
+		DMEMIT("%s %s %lu %llu ",
+		       format_dev_t(buf, pt->metadata_dev->bdev->bd_dev),
+		       format_dev_t(buf2, pt->data_dev->bdev->bd_dev),
+		       (unsigned long)pool->sectors_per_block,
+		       (unsigned long long)pt->low_water_blocks);
+
+		DMEMIT("%u ", !pool->zero_new_blocks);
+
+		if (!pool->zero_new_blocks)
+			DMEMIT("skip_block_zeroing ");
+		break;
+	}
+
+	return 0;
+}
+
+static int pool_iterate_devices(struct dm_target *ti,
+				iterate_devices_callout_fn fn, void *data)
+{
+	struct pool_c *pt = ti->private;
+
+	return fn(ti, pt->data_dev, 0, ti->len, data);
+}
+
+static int pool_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
+		      struct bio_vec *biovec, int max_size)
+{
+	struct pool_c *pt = ti->private;
+	struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
+
+	if (!q->merge_bvec_fn)
+		return max_size;
+
+	bvm->bi_bdev = pt->data_dev->bdev;
+
+	return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
+}
+
+static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
+{
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+
+	blk_limits_io_min(limits, 0);
+	blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
+}
+
+static struct target_type pool_target = {
+	.name = "thin-pool",
+	.features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
+		    DM_TARGET_IMMUTABLE,
+	.version = {1, 0, 0},
+	.module = THIS_MODULE,
+	.ctr = pool_ctr,
+	.dtr = pool_dtr,
+	.map = pool_map,
+	.postsuspend = pool_postsuspend,
+	.preresume = pool_preresume,
+	.resume = pool_resume,
+	.message = pool_message,
+	.status = pool_status,
+	.merge = pool_merge,
+	.iterate_devices = pool_iterate_devices,
+	.io_hints = pool_io_hints,
+};
+
+/*----------------------------------------------------------------
+ * Thin target methods
+ *--------------------------------------------------------------*/
+static void thin_dtr(struct dm_target *ti)
+{
+	struct thin_c *tc = ti->private;
+
+	mutex_lock(&dm_thin_pool_table.mutex);
+
+	__pool_dec(tc->pool);
+	dm_pool_close_thin_device(tc->td);
+	dm_put_device(ti, tc->pool_dev);
+	kfree(tc);
+
+	mutex_unlock(&dm_thin_pool_table.mutex);
+}
+
+/*
+ * Thin target parameters:
+ *
+ * <pool_dev> <dev_id>
+ *
+ * pool_dev: the path to the pool (eg, /dev/mapper/my_pool)
+ * dev_id: the internal device identifier
+ */
+static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
+{
+	int r;
+	struct thin_c *tc;
+	struct dm_dev *pool_dev;
+	struct mapped_device *pool_md;
+
+	mutex_lock(&dm_thin_pool_table.mutex);
+
+	if (argc != 2) {
+		ti->error = "Invalid argument count";
+		r = -EINVAL;
+		goto out_unlock;
+	}
+
+	tc = ti->private = kzalloc(sizeof(*tc), GFP_KERNEL);
+	if (!tc) {
+		ti->error = "Out of memory";
+		r = -ENOMEM;
+		goto out_unlock;
+	}
+
+	r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &pool_dev);
+	if (r) {
+		ti->error = "Error opening pool device";
+		goto bad_pool_dev;
+	}
+	tc->pool_dev = pool_dev;
+
+	if (read_dev_id(argv[1], (unsigned long long *)&tc->dev_id, 0)) {
+		ti->error = "Invalid device id";
+		r = -EINVAL;
+		goto bad_common;
+	}
+
+	pool_md = dm_get_md(tc->pool_dev->bdev->bd_dev);
+	if (!pool_md) {
+		ti->error = "Couldn't get pool mapped device";
+		r = -EINVAL;
+		goto bad_common;
+	}
+
+	tc->pool = __pool_table_lookup(pool_md);
+	if (!tc->pool) {
+		ti->error = "Couldn't find pool object";
+		r = -EINVAL;
+		goto bad_pool_lookup;
+	}
+	__pool_inc(tc->pool);
+
+	r = dm_pool_open_thin_device(tc->pool->pmd, tc->dev_id, &tc->td);
+	if (r) {
+		ti->error = "Couldn't open thin internal device";
+		goto bad_thin_open;
+	}
+
+	ti->split_io = tc->pool->sectors_per_block;
+	ti->num_flush_requests = 1;
+	ti->num_discard_requests = 0;
+	ti->discards_supported = 0;
+
+	dm_put(pool_md);
+
+	mutex_unlock(&dm_thin_pool_table.mutex);
+
+	return 0;
+
+bad_thin_open:
+	__pool_dec(tc->pool);
+bad_pool_lookup:
+	dm_put(pool_md);
+bad_common:
+	dm_put_device(ti, tc->pool_dev);
+bad_pool_dev:
+	kfree(tc);
+out_unlock:
+	mutex_unlock(&dm_thin_pool_table.mutex);
+
+	return r;
+}
+
+static int thin_map(struct dm_target *ti, struct bio *bio,
+		    union map_info *map_context)
+{
+	bio->bi_sector -= ti->begin;
+
+	return thin_bio_map(ti, bio, map_context);
+}
+
+static void thin_postsuspend(struct dm_target *ti)
+{
+	if (dm_noflush_suspending(ti))
+		requeue_io((struct thin_c *)ti->private);
+}
+
+/*
+ * <nr mapped sectors> <highest mapped sector>
+ */
+static int thin_status(struct dm_target *ti, status_type_t type,
+		       char *result, unsigned maxlen)
+{
+	int r;
+	ssize_t sz = 0;
+	dm_block_t mapped, highest;
+	char buf[BDEVNAME_SIZE];
+	struct thin_c *tc = ti->private;
+
+	if (!tc->td)
+		DMEMIT("-");
+	else {
+		switch (type) {
+		case STATUSTYPE_INFO:
+			r = dm_thin_get_mapped_count(tc->td, &mapped);
+			if (r)
+				return r;
+
+			r = dm_thin_get_highest_mapped_block(tc->td, &highest);
+			if (r < 0)
+				return r;
+
+			DMEMIT("%llu ", mapped * tc->pool->sectors_per_block);
+			if (r)
+				DMEMIT("%llu", ((highest + 1) *
+						tc->pool->sectors_per_block) - 1);
+			else
+				DMEMIT("-");
+			break;
+
+		case STATUSTYPE_TABLE:
+			DMEMIT("%s %lu",
+			       format_dev_t(buf, tc->pool_dev->bdev->bd_dev),
+			       (unsigned long) tc->dev_id);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int thin_iterate_devices(struct dm_target *ti,
+				iterate_devices_callout_fn fn, void *data)
+{
+	dm_block_t blocks;
+	struct thin_c *tc = ti->private;
+
+	/*
+	 * We can't call dm_pool_get_data_dev_size() since that blocks.  So
+	 * we follow a more convoluted path through to the pool's target.
+	 */
+	if (!tc->pool->ti)
+		return 0;	/* nothing is bound */
+
+	blocks = tc->pool->ti->len >> tc->pool->block_shift;
+	if (blocks)
+		return fn(ti, tc->pool_dev, 0, tc->pool->sectors_per_block * blocks, data);
+
+	return 0;
+}
+
+static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
+{
+	struct thin_c *tc = ti->private;
+
+	blk_limits_io_min(limits, 0);
+	blk_limits_io_opt(limits, tc->pool->sectors_per_block << SECTOR_SHIFT);
+}
+
+static struct target_type thin_target = {
+	.name = "thin",
+	.version = {1, 0, 0},
+	.module	= THIS_MODULE,
+	.ctr = thin_ctr,
+	.dtr = thin_dtr,
+	.map = thin_map,
+	.postsuspend = thin_postsuspend,
+	.status = thin_status,
+	.iterate_devices = thin_iterate_devices,
+	.io_hints = thin_io_hints,
+};
+
+/*----------------------------------------------------------------*/
+
+static int __init dm_thin_init(void)
+{
+	int r;
+
+	pool_table_init();
+
+	r = dm_register_target(&thin_target);
+	if (r)
+		return r;
+
+	r = dm_register_target(&pool_target);
+	if (r)
+		dm_unregister_target(&thin_target);
+
+	return r;
+}
+
+static void dm_thin_exit(void)
+{
+	dm_unregister_target(&thin_target);
+	dm_unregister_target(&pool_target);
+}
+
+module_init(dm_thin_init);
+module_exit(dm_thin_exit);
+
+MODULE_DESCRIPTION(DM_NAME "device-mapper thin provisioning target");
+MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/md/dm-thin-metadata.c linux-libre-3.2-gnu/drivers/md/dm-thin-metadata.c
--- linux-libre-3.1-gnu/drivers/md/dm-thin-metadata.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/dm-thin-metadata.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1391 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-thin-metadata.h"
+#include "persistent-data/dm-btree.h"
+#include "persistent-data/dm-space-map.h"
+#include "persistent-data/dm-space-map-disk.h"
+#include "persistent-data/dm-transaction-manager.h"
+
+#include <linux/list.h>
+#include <linux/device-mapper.h>
+#include <linux/workqueue.h>
+
+/*--------------------------------------------------------------------------
+ * As far as the metadata goes, there is:
+ *
+ * - A superblock in block zero, taking up fewer than 512 bytes for
+ *   atomic writes.
+ *
+ * - A space map managing the metadata blocks.
+ *
+ * - A space map managing the data blocks.
+ *
+ * - A btree mapping our internal thin dev ids onto struct disk_device_details.
+ *
+ * - A hierarchical btree, with 2 levels which effectively maps (thin
+ *   dev id, virtual block) -> block_time.  Block time is a 64-bit
+ *   field holding the time in the low 24 bits, and block in the top 48
+ *   bits.
+ *
+ * BTrees consist solely of btree_nodes, that fill a block.  Some are
+ * internal nodes, as such their values are a __le64 pointing to other
+ * nodes.  Leaf nodes can store data of any reasonable size (ie. much
+ * smaller than the block size).  The nodes consist of the header,
+ * followed by an array of keys, followed by an array of values.  We have
+ * to binary search on the keys so they're all held together to help the
+ * cpu cache.
+ *
+ * Space maps have 2 btrees:
+ *
+ * - One maps a uint64_t onto a struct index_entry.  Which points to a
+ *   bitmap block, and has some details about how many free entries there
+ *   are etc.
+ *
+ * - The bitmap blocks have a header (for the checksum).  Then the rest
+ *   of the block is pairs of bits.  With the meaning being:
+ *
+ *   0 - ref count is 0
+ *   1 - ref count is 1
+ *   2 - ref count is 2
+ *   3 - ref count is higher than 2
+ *
+ * - If the count is higher than 2 then the ref count is entered in a
+ *   second btree that directly maps the block_address to a uint32_t ref
+ *   count.
+ *
+ * The space map metadata variant doesn't have a bitmaps btree.  Instead
+ * it has one single blocks worth of index_entries.  This avoids
+ * recursive issues with the bitmap btree needing to allocate space in
+ * order to insert.  With a small data block size such as 64k the
+ * metadata support data devices that are hundreds of terrabytes.
+ *
+ * The space maps allocate space linearly from front to back.  Space that
+ * is freed in a transaction is never recycled within that transaction.
+ * To try and avoid fragmenting _free_ space the allocator always goes
+ * back and fills in gaps.
+ *
+ * All metadata io is in THIN_METADATA_BLOCK_SIZE sized/aligned chunks
+ * from the block manager.
+ *--------------------------------------------------------------------------*/
+
+#define DM_MSG_PREFIX   "thin metadata"
+
+#define THIN_SUPERBLOCK_MAGIC 27022010
+#define THIN_SUPERBLOCK_LOCATION 0
+#define THIN_VERSION 1
+#define THIN_METADATA_CACHE_SIZE 64
+#define SECTOR_TO_BLOCK_SHIFT 3
+
+/* This should be plenty */
+#define SPACE_MAP_ROOT_SIZE 128
+
+/*
+ * Little endian on-disk superblock and device details.
+ */
+struct thin_disk_superblock {
+	__le32 csum;	/* Checksum of superblock except for this field. */
+	__le32 flags;
+	__le64 blocknr;	/* This block number, dm_block_t. */
+
+	__u8 uuid[16];
+	__le64 magic;
+	__le32 version;
+	__le32 time;
+
+	__le64 trans_id;
+
+	/*
+	 * Root held by userspace transactions.
+	 */
+	__le64 held_root;
+
+	__u8 data_space_map_root[SPACE_MAP_ROOT_SIZE];
+	__u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE];
+
+	/*
+	 * 2-level btree mapping (dev_id, (dev block, time)) -> data block
+	 */
+	__le64 data_mapping_root;
+
+	/*
+	 * Device detail root mapping dev_id -> device_details
+	 */
+	__le64 device_details_root;
+
+	__le32 data_block_size;		/* In 512-byte sectors. */
+
+	__le32 metadata_block_size;	/* In 512-byte sectors. */
+	__le64 metadata_nr_blocks;
+
+	__le32 compat_flags;
+	__le32 compat_ro_flags;
+	__le32 incompat_flags;
+} __packed;
+
+struct disk_device_details {
+	__le64 mapped_blocks;
+	__le64 transaction_id;		/* When created. */
+	__le32 creation_time;
+	__le32 snapshotted_time;
+} __packed;
+
+struct dm_pool_metadata {
+	struct hlist_node hash;
+
+	struct block_device *bdev;
+	struct dm_block_manager *bm;
+	struct dm_space_map *metadata_sm;
+	struct dm_space_map *data_sm;
+	struct dm_transaction_manager *tm;
+	struct dm_transaction_manager *nb_tm;
+
+	/*
+	 * Two-level btree.
+	 * First level holds thin_dev_t.
+	 * Second level holds mappings.
+	 */
+	struct dm_btree_info info;
+
+	/*
+	 * Non-blocking version of the above.
+	 */
+	struct dm_btree_info nb_info;
+
+	/*
+	 * Just the top level for deleting whole devices.
+	 */
+	struct dm_btree_info tl_info;
+
+	/*
+	 * Just the bottom level for creating new devices.
+	 */
+	struct dm_btree_info bl_info;
+
+	/*
+	 * Describes the device details btree.
+	 */
+	struct dm_btree_info details_info;
+
+	struct rw_semaphore root_lock;
+	uint32_t time;
+	int need_commit;
+	dm_block_t root;
+	dm_block_t details_root;
+	struct list_head thin_devices;
+	uint64_t trans_id;
+	unsigned long flags;
+	sector_t data_block_size;
+};
+
+struct dm_thin_device {
+	struct list_head list;
+	struct dm_pool_metadata *pmd;
+	dm_thin_id id;
+
+	int open_count;
+	int changed;
+	uint64_t mapped_blocks;
+	uint64_t transaction_id;
+	uint32_t creation_time;
+	uint32_t snapshotted_time;
+};
+
+/*----------------------------------------------------------------
+ * superblock validator
+ *--------------------------------------------------------------*/
+
+#define SUPERBLOCK_CSUM_XOR 160774
+
+static void sb_prepare_for_write(struct dm_block_validator *v,
+				 struct dm_block *b,
+				 size_t block_size)
+{
+	struct thin_disk_superblock *disk_super = dm_block_data(b);
+
+	disk_super->blocknr = cpu_to_le64(dm_block_location(b));
+	disk_super->csum = cpu_to_le32(dm_bm_checksum(&disk_super->flags,
+						      block_size - sizeof(__le32),
+						      SUPERBLOCK_CSUM_XOR));
+}
+
+static int sb_check(struct dm_block_validator *v,
+		    struct dm_block *b,
+		    size_t block_size)
+{
+	struct thin_disk_superblock *disk_super = dm_block_data(b);
+	__le32 csum_le;
+
+	if (dm_block_location(b) != le64_to_cpu(disk_super->blocknr)) {
+		DMERR("sb_check failed: blocknr %llu: "
+		      "wanted %llu", le64_to_cpu(disk_super->blocknr),
+		      (unsigned long long)dm_block_location(b));
+		return -ENOTBLK;
+	}
+
+	if (le64_to_cpu(disk_super->magic) != THIN_SUPERBLOCK_MAGIC) {
+		DMERR("sb_check failed: magic %llu: "
+		      "wanted %llu", le64_to_cpu(disk_super->magic),
+		      (unsigned long long)THIN_SUPERBLOCK_MAGIC);
+		return -EILSEQ;
+	}
+
+	csum_le = cpu_to_le32(dm_bm_checksum(&disk_super->flags,
+					     block_size - sizeof(__le32),
+					     SUPERBLOCK_CSUM_XOR));
+	if (csum_le != disk_super->csum) {
+		DMERR("sb_check failed: csum %u: wanted %u",
+		      le32_to_cpu(csum_le), le32_to_cpu(disk_super->csum));
+		return -EILSEQ;
+	}
+
+	return 0;
+}
+
+static struct dm_block_validator sb_validator = {
+	.name = "superblock",
+	.prepare_for_write = sb_prepare_for_write,
+	.check = sb_check
+};
+
+/*----------------------------------------------------------------
+ * Methods for the btree value types
+ *--------------------------------------------------------------*/
+
+static uint64_t pack_block_time(dm_block_t b, uint32_t t)
+{
+	return (b << 24) | t;
+}
+
+static void unpack_block_time(uint64_t v, dm_block_t *b, uint32_t *t)
+{
+	*b = v >> 24;
+	*t = v & ((1 << 24) - 1);
+}
+
+static void data_block_inc(void *context, void *value_le)
+{
+	struct dm_space_map *sm = context;
+	__le64 v_le;
+	uint64_t b;
+	uint32_t t;
+
+	memcpy(&v_le, value_le, sizeof(v_le));
+	unpack_block_time(le64_to_cpu(v_le), &b, &t);
+	dm_sm_inc_block(sm, b);
+}
+
+static void data_block_dec(void *context, void *value_le)
+{
+	struct dm_space_map *sm = context;
+	__le64 v_le;
+	uint64_t b;
+	uint32_t t;
+
+	memcpy(&v_le, value_le, sizeof(v_le));
+	unpack_block_time(le64_to_cpu(v_le), &b, &t);
+	dm_sm_dec_block(sm, b);
+}
+
+static int data_block_equal(void *context, void *value1_le, void *value2_le)
+{
+	__le64 v1_le, v2_le;
+	uint64_t b1, b2;
+	uint32_t t;
+
+	memcpy(&v1_le, value1_le, sizeof(v1_le));
+	memcpy(&v2_le, value2_le, sizeof(v2_le));
+	unpack_block_time(le64_to_cpu(v1_le), &b1, &t);
+	unpack_block_time(le64_to_cpu(v2_le), &b2, &t);
+
+	return b1 == b2;
+}
+
+static void subtree_inc(void *context, void *value)
+{
+	struct dm_btree_info *info = context;
+	__le64 root_le;
+	uint64_t root;
+
+	memcpy(&root_le, value, sizeof(root_le));
+	root = le64_to_cpu(root_le);
+	dm_tm_inc(info->tm, root);
+}
+
+static void subtree_dec(void *context, void *value)
+{
+	struct dm_btree_info *info = context;
+	__le64 root_le;
+	uint64_t root;
+
+	memcpy(&root_le, value, sizeof(root_le));
+	root = le64_to_cpu(root_le);
+	if (dm_btree_del(info, root))
+		DMERR("btree delete failed\n");
+}
+
+static int subtree_equal(void *context, void *value1_le, void *value2_le)
+{
+	__le64 v1_le, v2_le;
+	memcpy(&v1_le, value1_le, sizeof(v1_le));
+	memcpy(&v2_le, value2_le, sizeof(v2_le));
+
+	return v1_le == v2_le;
+}
+
+/*----------------------------------------------------------------*/
+
+static int superblock_all_zeroes(struct dm_block_manager *bm, int *result)
+{
+	int r;
+	unsigned i;
+	struct dm_block *b;
+	__le64 *data_le, zero = cpu_to_le64(0);
+	unsigned block_size = dm_bm_block_size(bm) / sizeof(__le64);
+
+	/*
+	 * We can't use a validator here - it may be all zeroes.
+	 */
+	r = dm_bm_read_lock(bm, THIN_SUPERBLOCK_LOCATION, NULL, &b);
+	if (r)
+		return r;
+
+	data_le = dm_block_data(b);
+	*result = 1;
+	for (i = 0; i < block_size; i++) {
+		if (data_le[i] != zero) {
+			*result = 0;
+			break;
+		}
+	}
+
+	return dm_bm_unlock(b);
+}
+
+static int init_pmd(struct dm_pool_metadata *pmd,
+		    struct dm_block_manager *bm,
+		    dm_block_t nr_blocks, int create)
+{
+	int r;
+	struct dm_space_map *sm, *data_sm;
+	struct dm_transaction_manager *tm;
+	struct dm_block *sblock;
+
+	if (create) {
+		r = dm_tm_create_with_sm(bm, THIN_SUPERBLOCK_LOCATION,
+					 &sb_validator, &tm, &sm, &sblock);
+		if (r < 0) {
+			DMERR("tm_create_with_sm failed");
+			return r;
+		}
+
+		data_sm = dm_sm_disk_create(tm, nr_blocks);
+		if (IS_ERR(data_sm)) {
+			DMERR("sm_disk_create failed");
+			r = PTR_ERR(data_sm);
+			goto bad;
+		}
+	} else {
+		struct thin_disk_superblock *disk_super = NULL;
+		size_t space_map_root_offset =
+			offsetof(struct thin_disk_superblock, metadata_space_map_root);
+
+		r = dm_tm_open_with_sm(bm, THIN_SUPERBLOCK_LOCATION,
+				       &sb_validator, space_map_root_offset,
+				       SPACE_MAP_ROOT_SIZE, &tm, &sm, &sblock);
+		if (r < 0) {
+			DMERR("tm_open_with_sm failed");
+			return r;
+		}
+
+		disk_super = dm_block_data(sblock);
+		data_sm = dm_sm_disk_open(tm, disk_super->data_space_map_root,
+					  sizeof(disk_super->data_space_map_root));
+		if (IS_ERR(data_sm)) {
+			DMERR("sm_disk_open failed");
+			r = PTR_ERR(data_sm);
+			goto bad;
+		}
+	}
+
+
+	r = dm_tm_unlock(tm, sblock);
+	if (r < 0) {
+		DMERR("couldn't unlock superblock");
+		goto bad_data_sm;
+	}
+
+	pmd->bm = bm;
+	pmd->metadata_sm = sm;
+	pmd->data_sm = data_sm;
+	pmd->tm = tm;
+	pmd->nb_tm = dm_tm_create_non_blocking_clone(tm);
+	if (!pmd->nb_tm) {
+		DMERR("could not create clone tm");
+		r = -ENOMEM;
+		goto bad_data_sm;
+	}
+
+	pmd->info.tm = tm;
+	pmd->info.levels = 2;
+	pmd->info.value_type.context = pmd->data_sm;
+	pmd->info.value_type.size = sizeof(__le64);
+	pmd->info.value_type.inc = data_block_inc;
+	pmd->info.value_type.dec = data_block_dec;
+	pmd->info.value_type.equal = data_block_equal;
+
+	memcpy(&pmd->nb_info, &pmd->info, sizeof(pmd->nb_info));
+	pmd->nb_info.tm = pmd->nb_tm;
+
+	pmd->tl_info.tm = tm;
+	pmd->tl_info.levels = 1;
+	pmd->tl_info.value_type.context = &pmd->info;
+	pmd->tl_info.value_type.size = sizeof(__le64);
+	pmd->tl_info.value_type.inc = subtree_inc;
+	pmd->tl_info.value_type.dec = subtree_dec;
+	pmd->tl_info.value_type.equal = subtree_equal;
+
+	pmd->bl_info.tm = tm;
+	pmd->bl_info.levels = 1;
+	pmd->bl_info.value_type.context = pmd->data_sm;
+	pmd->bl_info.value_type.size = sizeof(__le64);
+	pmd->bl_info.value_type.inc = data_block_inc;
+	pmd->bl_info.value_type.dec = data_block_dec;
+	pmd->bl_info.value_type.equal = data_block_equal;
+
+	pmd->details_info.tm = tm;
+	pmd->details_info.levels = 1;
+	pmd->details_info.value_type.context = NULL;
+	pmd->details_info.value_type.size = sizeof(struct disk_device_details);
+	pmd->details_info.value_type.inc = NULL;
+	pmd->details_info.value_type.dec = NULL;
+	pmd->details_info.value_type.equal = NULL;
+
+	pmd->root = 0;
+
+	init_rwsem(&pmd->root_lock);
+	pmd->time = 0;
+	pmd->need_commit = 0;
+	pmd->details_root = 0;
+	pmd->trans_id = 0;
+	pmd->flags = 0;
+	INIT_LIST_HEAD(&pmd->thin_devices);
+
+	return 0;
+
+bad_data_sm:
+	dm_sm_destroy(data_sm);
+bad:
+	dm_tm_destroy(tm);
+	dm_sm_destroy(sm);
+
+	return r;
+}
+
+static int __begin_transaction(struct dm_pool_metadata *pmd)
+{
+	int r;
+	u32 features;
+	struct thin_disk_superblock *disk_super;
+	struct dm_block *sblock;
+
+	/*
+	 * __maybe_commit_transaction() resets these
+	 */
+	WARN_ON(pmd->need_commit);
+
+	/*
+	 * We re-read the superblock every time.  Shouldn't need to do this
+	 * really.
+	 */
+	r = dm_bm_read_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+			    &sb_validator, &sblock);
+	if (r)
+		return r;
+
+	disk_super = dm_block_data(sblock);
+	pmd->time = le32_to_cpu(disk_super->time);
+	pmd->root = le64_to_cpu(disk_super->data_mapping_root);
+	pmd->details_root = le64_to_cpu(disk_super->device_details_root);
+	pmd->trans_id = le64_to_cpu(disk_super->trans_id);
+	pmd->flags = le32_to_cpu(disk_super->flags);
+	pmd->data_block_size = le32_to_cpu(disk_super->data_block_size);
+
+	features = le32_to_cpu(disk_super->incompat_flags) & ~THIN_FEATURE_INCOMPAT_SUPP;
+	if (features) {
+		DMERR("could not access metadata due to "
+		      "unsupported optional features (%lx).",
+		      (unsigned long)features);
+		r = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Check for read-only metadata to skip the following RDWR checks.
+	 */
+	if (get_disk_ro(pmd->bdev->bd_disk))
+		goto out;
+
+	features = le32_to_cpu(disk_super->compat_ro_flags) & ~THIN_FEATURE_COMPAT_RO_SUPP;
+	if (features) {
+		DMERR("could not access metadata RDWR due to "
+		      "unsupported optional features (%lx).",
+		      (unsigned long)features);
+		r = -EINVAL;
+	}
+
+out:
+	dm_bm_unlock(sblock);
+	return r;
+}
+
+static int __write_changed_details(struct dm_pool_metadata *pmd)
+{
+	int r;
+	struct dm_thin_device *td, *tmp;
+	struct disk_device_details details;
+	uint64_t key;
+
+	list_for_each_entry_safe(td, tmp, &pmd->thin_devices, list) {
+		if (!td->changed)
+			continue;
+
+		key = td->id;
+
+		details.mapped_blocks = cpu_to_le64(td->mapped_blocks);
+		details.transaction_id = cpu_to_le64(td->transaction_id);
+		details.creation_time = cpu_to_le32(td->creation_time);
+		details.snapshotted_time = cpu_to_le32(td->snapshotted_time);
+		__dm_bless_for_disk(&details);
+
+		r = dm_btree_insert(&pmd->details_info, pmd->details_root,
+				    &key, &details, &pmd->details_root);
+		if (r)
+			return r;
+
+		if (td->open_count)
+			td->changed = 0;
+		else {
+			list_del(&td->list);
+			kfree(td);
+		}
+
+		pmd->need_commit = 1;
+	}
+
+	return 0;
+}
+
+static int __commit_transaction(struct dm_pool_metadata *pmd)
+{
+	/*
+	 * FIXME: Associated pool should be made read-only on failure.
+	 */
+	int r;
+	size_t metadata_len, data_len;
+	struct thin_disk_superblock *disk_super;
+	struct dm_block *sblock;
+
+	/*
+	 * We need to know if the thin_disk_superblock exceeds a 512-byte sector.
+	 */
+	BUILD_BUG_ON(sizeof(struct thin_disk_superblock) > 512);
+
+	r = __write_changed_details(pmd);
+	if (r < 0)
+		goto out;
+
+	if (!pmd->need_commit)
+		goto out;
+
+	r = dm_sm_commit(pmd->data_sm);
+	if (r < 0)
+		goto out;
+
+	r = dm_tm_pre_commit(pmd->tm);
+	if (r < 0)
+		goto out;
+
+	r = dm_sm_root_size(pmd->metadata_sm, &metadata_len);
+	if (r < 0)
+		goto out;
+
+	r = dm_sm_root_size(pmd->metadata_sm, &data_len);
+	if (r < 0)
+		goto out;
+
+	r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+			     &sb_validator, &sblock);
+	if (r)
+		goto out;
+
+	disk_super = dm_block_data(sblock);
+	disk_super->time = cpu_to_le32(pmd->time);
+	disk_super->data_mapping_root = cpu_to_le64(pmd->root);
+	disk_super->device_details_root = cpu_to_le64(pmd->details_root);
+	disk_super->trans_id = cpu_to_le64(pmd->trans_id);
+	disk_super->flags = cpu_to_le32(pmd->flags);
+
+	r = dm_sm_copy_root(pmd->metadata_sm, &disk_super->metadata_space_map_root,
+			    metadata_len);
+	if (r < 0)
+		goto out_locked;
+
+	r = dm_sm_copy_root(pmd->data_sm, &disk_super->data_space_map_root,
+			    data_len);
+	if (r < 0)
+		goto out_locked;
+
+	r = dm_tm_commit(pmd->tm, sblock);
+	if (!r)
+		pmd->need_commit = 0;
+
+out:
+	return r;
+
+out_locked:
+	dm_bm_unlock(sblock);
+	return r;
+}
+
+struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
+					       sector_t data_block_size)
+{
+	int r;
+	struct thin_disk_superblock *disk_super;
+	struct dm_pool_metadata *pmd;
+	sector_t bdev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
+	struct dm_block_manager *bm;
+	int create;
+	struct dm_block *sblock;
+
+	pmd = kmalloc(sizeof(*pmd), GFP_KERNEL);
+	if (!pmd) {
+		DMERR("could not allocate metadata struct");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/*
+	 * Max hex locks:
+	 *  3 for btree insert +
+	 *  2 for btree lookup used within space map
+	 */
+	bm = dm_block_manager_create(bdev, THIN_METADATA_BLOCK_SIZE,
+				     THIN_METADATA_CACHE_SIZE, 5);
+	if (!bm) {
+		DMERR("could not create block manager");
+		kfree(pmd);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	r = superblock_all_zeroes(bm, &create);
+	if (r) {
+		dm_block_manager_destroy(bm);
+		kfree(pmd);
+		return ERR_PTR(r);
+	}
+
+
+	r = init_pmd(pmd, bm, 0, create);
+	if (r) {
+		dm_block_manager_destroy(bm);
+		kfree(pmd);
+		return ERR_PTR(r);
+	}
+	pmd->bdev = bdev;
+
+	if (!create) {
+		r = __begin_transaction(pmd);
+		if (r < 0)
+			goto bad;
+		return pmd;
+	}
+
+	/*
+	 * Create.
+	 */
+	r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+			     &sb_validator, &sblock);
+	if (r)
+		goto bad;
+
+	disk_super = dm_block_data(sblock);
+	disk_super->magic = cpu_to_le64(THIN_SUPERBLOCK_MAGIC);
+	disk_super->version = cpu_to_le32(THIN_VERSION);
+	disk_super->time = 0;
+	disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
+	disk_super->metadata_nr_blocks = cpu_to_le64(bdev_size >> SECTOR_TO_BLOCK_SHIFT);
+	disk_super->data_block_size = cpu_to_le32(data_block_size);
+
+	r = dm_bm_unlock(sblock);
+	if (r < 0)
+		goto bad;
+
+	r = dm_btree_empty(&pmd->info, &pmd->root);
+	if (r < 0)
+		goto bad;
+
+	r = dm_btree_empty(&pmd->details_info, &pmd->details_root);
+	if (r < 0) {
+		DMERR("couldn't create devices root");
+		goto bad;
+	}
+
+	pmd->flags = 0;
+	pmd->need_commit = 1;
+	r = dm_pool_commit_metadata(pmd);
+	if (r < 0) {
+		DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+		      __func__, r);
+		goto bad;
+	}
+
+	return pmd;
+
+bad:
+	if (dm_pool_metadata_close(pmd) < 0)
+		DMWARN("%s: dm_pool_metadata_close() failed.", __func__);
+	return ERR_PTR(r);
+}
+
+int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
+{
+	int r;
+	unsigned open_devices = 0;
+	struct dm_thin_device *td, *tmp;
+
+	down_read(&pmd->root_lock);
+	list_for_each_entry_safe(td, tmp, &pmd->thin_devices, list) {
+		if (td->open_count)
+			open_devices++;
+		else {
+			list_del(&td->list);
+			kfree(td);
+		}
+	}
+	up_read(&pmd->root_lock);
+
+	if (open_devices) {
+		DMERR("attempt to close pmd when %u device(s) are still open",
+		       open_devices);
+		return -EBUSY;
+	}
+
+	r = __commit_transaction(pmd);
+	if (r < 0)
+		DMWARN("%s: __commit_transaction() failed, error = %d",
+		       __func__, r);
+
+	dm_tm_destroy(pmd->tm);
+	dm_tm_destroy(pmd->nb_tm);
+	dm_block_manager_destroy(pmd->bm);
+	dm_sm_destroy(pmd->metadata_sm);
+	dm_sm_destroy(pmd->data_sm);
+	kfree(pmd);
+
+	return 0;
+}
+
+static int __open_device(struct dm_pool_metadata *pmd,
+			 dm_thin_id dev, int create,
+			 struct dm_thin_device **td)
+{
+	int r, changed = 0;
+	struct dm_thin_device *td2;
+	uint64_t key = dev;
+	struct disk_device_details details_le;
+
+	/*
+	 * Check the device isn't already open.
+	 */
+	list_for_each_entry(td2, &pmd->thin_devices, list)
+		if (td2->id == dev) {
+			td2->open_count++;
+			*td = td2;
+			return 0;
+		}
+
+	/*
+	 * Check the device exists.
+	 */
+	r = dm_btree_lookup(&pmd->details_info, pmd->details_root,
+			    &key, &details_le);
+	if (r) {
+		if (r != -ENODATA || !create)
+			return r;
+
+		changed = 1;
+		details_le.mapped_blocks = 0;
+		details_le.transaction_id = cpu_to_le64(pmd->trans_id);
+		details_le.creation_time = cpu_to_le32(pmd->time);
+		details_le.snapshotted_time = cpu_to_le32(pmd->time);
+	}
+
+	*td = kmalloc(sizeof(**td), GFP_NOIO);
+	if (!*td)
+		return -ENOMEM;
+
+	(*td)->pmd = pmd;
+	(*td)->id = dev;
+	(*td)->open_count = 1;
+	(*td)->changed = changed;
+	(*td)->mapped_blocks = le64_to_cpu(details_le.mapped_blocks);
+	(*td)->transaction_id = le64_to_cpu(details_le.transaction_id);
+	(*td)->creation_time = le32_to_cpu(details_le.creation_time);
+	(*td)->snapshotted_time = le32_to_cpu(details_le.snapshotted_time);
+
+	list_add(&(*td)->list, &pmd->thin_devices);
+
+	return 0;
+}
+
+static void __close_device(struct dm_thin_device *td)
+{
+	--td->open_count;
+}
+
+static int __create_thin(struct dm_pool_metadata *pmd,
+			 dm_thin_id dev)
+{
+	int r;
+	dm_block_t dev_root;
+	uint64_t key = dev;
+	struct disk_device_details details_le;
+	struct dm_thin_device *td;
+	__le64 value;
+
+	r = dm_btree_lookup(&pmd->details_info, pmd->details_root,
+			    &key, &details_le);
+	if (!r)
+		return -EEXIST;
+
+	/*
+	 * Create an empty btree for the mappings.
+	 */
+	r = dm_btree_empty(&pmd->bl_info, &dev_root);
+	if (r)
+		return r;
+
+	/*
+	 * Insert it into the main mapping tree.
+	 */
+	value = cpu_to_le64(dev_root);
+	__dm_bless_for_disk(&value);
+	r = dm_btree_insert(&pmd->tl_info, pmd->root, &key, &value, &pmd->root);
+	if (r) {
+		dm_btree_del(&pmd->bl_info, dev_root);
+		return r;
+	}
+
+	r = __open_device(pmd, dev, 1, &td);
+	if (r) {
+		__close_device(td);
+		dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
+		dm_btree_del(&pmd->bl_info, dev_root);
+		return r;
+	}
+	td->changed = 1;
+	__close_device(td);
+
+	return r;
+}
+
+int dm_pool_create_thin(struct dm_pool_metadata *pmd, dm_thin_id dev)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+	r = __create_thin(pmd, dev);
+	up_write(&pmd->root_lock);
+
+	return r;
+}
+
+static int __set_snapshot_details(struct dm_pool_metadata *pmd,
+				  struct dm_thin_device *snap,
+				  dm_thin_id origin, uint32_t time)
+{
+	int r;
+	struct dm_thin_device *td;
+
+	r = __open_device(pmd, origin, 0, &td);
+	if (r)
+		return r;
+
+	td->changed = 1;
+	td->snapshotted_time = time;
+
+	snap->mapped_blocks = td->mapped_blocks;
+	snap->snapshotted_time = time;
+	__close_device(td);
+
+	return 0;
+}
+
+static int __create_snap(struct dm_pool_metadata *pmd,
+			 dm_thin_id dev, dm_thin_id origin)
+{
+	int r;
+	dm_block_t origin_root;
+	uint64_t key = origin, dev_key = dev;
+	struct dm_thin_device *td;
+	struct disk_device_details details_le;
+	__le64 value;
+
+	/* check this device is unused */
+	r = dm_btree_lookup(&pmd->details_info, pmd->details_root,
+			    &dev_key, &details_le);
+	if (!r)
+		return -EEXIST;
+
+	/* find the mapping tree for the origin */
+	r = dm_btree_lookup(&pmd->tl_info, pmd->root, &key, &value);
+	if (r)
+		return r;
+	origin_root = le64_to_cpu(value);
+
+	/* clone the origin, an inc will do */
+	dm_tm_inc(pmd->tm, origin_root);
+
+	/* insert into the main mapping tree */
+	value = cpu_to_le64(origin_root);
+	__dm_bless_for_disk(&value);
+	key = dev;
+	r = dm_btree_insert(&pmd->tl_info, pmd->root, &key, &value, &pmd->root);
+	if (r) {
+		dm_tm_dec(pmd->tm, origin_root);
+		return r;
+	}
+
+	pmd->time++;
+
+	r = __open_device(pmd, dev, 1, &td);
+	if (r)
+		goto bad;
+
+	r = __set_snapshot_details(pmd, td, origin, pmd->time);
+	if (r)
+		goto bad;
+
+	__close_device(td);
+	return 0;
+
+bad:
+	__close_device(td);
+	dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
+	dm_btree_remove(&pmd->details_info, pmd->details_root,
+			&key, &pmd->details_root);
+	return r;
+}
+
+int dm_pool_create_snap(struct dm_pool_metadata *pmd,
+				 dm_thin_id dev,
+				 dm_thin_id origin)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+	r = __create_snap(pmd, dev, origin);
+	up_write(&pmd->root_lock);
+
+	return r;
+}
+
+static int __delete_device(struct dm_pool_metadata *pmd, dm_thin_id dev)
+{
+	int r;
+	uint64_t key = dev;
+	struct dm_thin_device *td;
+
+	/* TODO: failure should mark the transaction invalid */
+	r = __open_device(pmd, dev, 0, &td);
+	if (r)
+		return r;
+
+	if (td->open_count > 1) {
+		__close_device(td);
+		return -EBUSY;
+	}
+
+	list_del(&td->list);
+	kfree(td);
+	r = dm_btree_remove(&pmd->details_info, pmd->details_root,
+			    &key, &pmd->details_root);
+	if (r)
+		return r;
+
+	r = dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
+	if (r)
+		return r;
+
+	pmd->need_commit = 1;
+
+	return 0;
+}
+
+int dm_pool_delete_thin_device(struct dm_pool_metadata *pmd,
+			       dm_thin_id dev)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+	r = __delete_device(pmd, dev);
+	up_write(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd,
+					uint64_t current_id,
+					uint64_t new_id)
+{
+	down_write(&pmd->root_lock);
+	if (pmd->trans_id != current_id) {
+		up_write(&pmd->root_lock);
+		DMERR("mismatched transaction id");
+		return -EINVAL;
+	}
+
+	pmd->trans_id = new_id;
+	pmd->need_commit = 1;
+	up_write(&pmd->root_lock);
+
+	return 0;
+}
+
+int dm_pool_get_metadata_transaction_id(struct dm_pool_metadata *pmd,
+					uint64_t *result)
+{
+	down_read(&pmd->root_lock);
+	*result = pmd->trans_id;
+	up_read(&pmd->root_lock);
+
+	return 0;
+}
+
+static int __get_held_metadata_root(struct dm_pool_metadata *pmd,
+				    dm_block_t *result)
+{
+	int r;
+	struct thin_disk_superblock *disk_super;
+	struct dm_block *sblock;
+
+	r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+			     &sb_validator, &sblock);
+	if (r)
+		return r;
+
+	disk_super = dm_block_data(sblock);
+	*result = le64_to_cpu(disk_super->held_root);
+
+	return dm_bm_unlock(sblock);
+}
+
+int dm_pool_get_held_metadata_root(struct dm_pool_metadata *pmd,
+				   dm_block_t *result)
+{
+	int r;
+
+	down_read(&pmd->root_lock);
+	r = __get_held_metadata_root(pmd, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_open_thin_device(struct dm_pool_metadata *pmd, dm_thin_id dev,
+			     struct dm_thin_device **td)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+	r = __open_device(pmd, dev, 0, td);
+	up_write(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_close_thin_device(struct dm_thin_device *td)
+{
+	down_write(&td->pmd->root_lock);
+	__close_device(td);
+	up_write(&td->pmd->root_lock);
+
+	return 0;
+}
+
+dm_thin_id dm_thin_dev_id(struct dm_thin_device *td)
+{
+	return td->id;
+}
+
+static int __snapshotted_since(struct dm_thin_device *td, uint32_t time)
+{
+	return td->snapshotted_time > time;
+}
+
+int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
+		       int can_block, struct dm_thin_lookup_result *result)
+{
+	int r;
+	uint64_t block_time = 0;
+	__le64 value;
+	struct dm_pool_metadata *pmd = td->pmd;
+	dm_block_t keys[2] = { td->id, block };
+
+	if (can_block) {
+		down_read(&pmd->root_lock);
+		r = dm_btree_lookup(&pmd->info, pmd->root, keys, &value);
+		if (!r)
+			block_time = le64_to_cpu(value);
+		up_read(&pmd->root_lock);
+
+	} else if (down_read_trylock(&pmd->root_lock)) {
+		r = dm_btree_lookup(&pmd->nb_info, pmd->root, keys, &value);
+		if (!r)
+			block_time = le64_to_cpu(value);
+		up_read(&pmd->root_lock);
+
+	} else
+		return -EWOULDBLOCK;
+
+	if (!r) {
+		dm_block_t exception_block;
+		uint32_t exception_time;
+		unpack_block_time(block_time, &exception_block,
+				  &exception_time);
+		result->block = exception_block;
+		result->shared = __snapshotted_since(td, exception_time);
+	}
+
+	return r;
+}
+
+static int __insert(struct dm_thin_device *td, dm_block_t block,
+		    dm_block_t data_block)
+{
+	int r, inserted;
+	__le64 value;
+	struct dm_pool_metadata *pmd = td->pmd;
+	dm_block_t keys[2] = { td->id, block };
+
+	pmd->need_commit = 1;
+	value = cpu_to_le64(pack_block_time(data_block, pmd->time));
+	__dm_bless_for_disk(&value);
+
+	r = dm_btree_insert_notify(&pmd->info, pmd->root, keys, &value,
+				   &pmd->root, &inserted);
+	if (r)
+		return r;
+
+	if (inserted) {
+		td->mapped_blocks++;
+		td->changed = 1;
+	}
+
+	return 0;
+}
+
+int dm_thin_insert_block(struct dm_thin_device *td, dm_block_t block,
+			 dm_block_t data_block)
+{
+	int r;
+
+	down_write(&td->pmd->root_lock);
+	r = __insert(td, block, data_block);
+	up_write(&td->pmd->root_lock);
+
+	return r;
+}
+
+static int __remove(struct dm_thin_device *td, dm_block_t block)
+{
+	int r;
+	struct dm_pool_metadata *pmd = td->pmd;
+	dm_block_t keys[2] = { td->id, block };
+
+	r = dm_btree_remove(&pmd->info, pmd->root, keys, &pmd->root);
+	if (r)
+		return r;
+
+	pmd->need_commit = 1;
+
+	return 0;
+}
+
+int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block)
+{
+	int r;
+
+	down_write(&td->pmd->root_lock);
+	r = __remove(td, block);
+	up_write(&td->pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_alloc_data_block(struct dm_pool_metadata *pmd, dm_block_t *result)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+
+	r = dm_sm_new_block(pmd->data_sm, result);
+	pmd->need_commit = 1;
+
+	up_write(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_commit_metadata(struct dm_pool_metadata *pmd)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+
+	r = __commit_transaction(pmd);
+	if (r <= 0)
+		goto out;
+
+	/*
+	 * Open the next transaction.
+	 */
+	r = __begin_transaction(pmd);
+out:
+	up_write(&pmd->root_lock);
+	return r;
+}
+
+int dm_pool_get_free_block_count(struct dm_pool_metadata *pmd, dm_block_t *result)
+{
+	int r;
+
+	down_read(&pmd->root_lock);
+	r = dm_sm_get_nr_free(pmd->data_sm, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd,
+					  dm_block_t *result)
+{
+	int r;
+
+	down_read(&pmd->root_lock);
+	r = dm_sm_get_nr_free(pmd->metadata_sm, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd,
+				  dm_block_t *result)
+{
+	int r;
+
+	down_read(&pmd->root_lock);
+	r = dm_sm_get_nr_blocks(pmd->metadata_sm, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_get_data_block_size(struct dm_pool_metadata *pmd, sector_t *result)
+{
+	down_read(&pmd->root_lock);
+	*result = pmd->data_block_size;
+	up_read(&pmd->root_lock);
+
+	return 0;
+}
+
+int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result)
+{
+	int r;
+
+	down_read(&pmd->root_lock);
+	r = dm_sm_get_nr_blocks(pmd->data_sm, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_thin_get_mapped_count(struct dm_thin_device *td, dm_block_t *result)
+{
+	struct dm_pool_metadata *pmd = td->pmd;
+
+	down_read(&pmd->root_lock);
+	*result = td->mapped_blocks;
+	up_read(&pmd->root_lock);
+
+	return 0;
+}
+
+static int __highest_block(struct dm_thin_device *td, dm_block_t *result)
+{
+	int r;
+	__le64 value_le;
+	dm_block_t thin_root;
+	struct dm_pool_metadata *pmd = td->pmd;
+
+	r = dm_btree_lookup(&pmd->tl_info, pmd->root, &td->id, &value_le);
+	if (r)
+		return r;
+
+	thin_root = le64_to_cpu(value_le);
+
+	return dm_btree_find_highest_key(&pmd->bl_info, thin_root, result);
+}
+
+int dm_thin_get_highest_mapped_block(struct dm_thin_device *td,
+				     dm_block_t *result)
+{
+	int r;
+	struct dm_pool_metadata *pmd = td->pmd;
+
+	down_read(&pmd->root_lock);
+	r = __highest_block(td, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+static int __resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
+{
+	int r;
+	dm_block_t old_count;
+
+	r = dm_sm_get_nr_blocks(pmd->data_sm, &old_count);
+	if (r)
+		return r;
+
+	if (new_count == old_count)
+		return 0;
+
+	if (new_count < old_count) {
+		DMERR("cannot reduce size of data device");
+		return -EINVAL;
+	}
+
+	r = dm_sm_extend(pmd->data_sm, new_count - old_count);
+	if (!r)
+		pmd->need_commit = 1;
+
+	return r;
+}
+
+int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+	r = __resize_data_dev(pmd, new_count);
+	up_write(&pmd->root_lock);
+
+	return r;
+}
diff -druN linux-libre-3.1-gnu/drivers/md/dm-thin-metadata.h linux-libre-3.2-gnu/drivers/md/dm-thin-metadata.h
--- linux-libre-3.1-gnu/drivers/md/dm-thin-metadata.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/dm-thin-metadata.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2010-2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_THIN_METADATA_H
+#define DM_THIN_METADATA_H
+
+#include "persistent-data/dm-block-manager.h"
+
+#define THIN_METADATA_BLOCK_SIZE 4096
+
+/*----------------------------------------------------------------*/
+
+struct dm_pool_metadata;
+struct dm_thin_device;
+
+/*
+ * Device identifier
+ */
+typedef uint64_t dm_thin_id;
+
+/*
+ * Reopens or creates a new, empty metadata volume.
+ */
+struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
+					       sector_t data_block_size);
+
+int dm_pool_metadata_close(struct dm_pool_metadata *pmd);
+
+/*
+ * Compat feature flags.  Any incompat flags beyond the ones
+ * specified below will prevent use of the thin metadata.
+ */
+#define THIN_FEATURE_COMPAT_SUPP	  0UL
+#define THIN_FEATURE_COMPAT_RO_SUPP	  0UL
+#define THIN_FEATURE_INCOMPAT_SUPP	  0UL
+
+/*
+ * Device creation/deletion.
+ */
+int dm_pool_create_thin(struct dm_pool_metadata *pmd, dm_thin_id dev);
+
+/*
+ * An internal snapshot.
+ *
+ * You can only snapshot a quiesced origin i.e. one that is either
+ * suspended or not instanced at all.
+ */
+int dm_pool_create_snap(struct dm_pool_metadata *pmd, dm_thin_id dev,
+			dm_thin_id origin);
+
+/*
+ * Deletes a virtual device from the metadata.  It _is_ safe to call this
+ * when that device is open.  Operations on that device will just start
+ * failing.  You still need to call close() on the device.
+ */
+int dm_pool_delete_thin_device(struct dm_pool_metadata *pmd,
+			       dm_thin_id dev);
+
+/*
+ * Commits _all_ metadata changes: device creation, deletion, mapping
+ * updates.
+ */
+int dm_pool_commit_metadata(struct dm_pool_metadata *pmd);
+
+/*
+ * Set/get userspace transaction id.
+ */
+int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd,
+					uint64_t current_id,
+					uint64_t new_id);
+
+int dm_pool_get_metadata_transaction_id(struct dm_pool_metadata *pmd,
+					uint64_t *result);
+
+/*
+ * Hold/get root for userspace transaction.
+ */
+int dm_pool_hold_metadata_root(struct dm_pool_metadata *pmd);
+
+int dm_pool_get_held_metadata_root(struct dm_pool_metadata *pmd,
+				   dm_block_t *result);
+
+/*
+ * Actions on a single virtual device.
+ */
+
+/*
+ * Opening the same device more than once will fail with -EBUSY.
+ */
+int dm_pool_open_thin_device(struct dm_pool_metadata *pmd, dm_thin_id dev,
+			     struct dm_thin_device **td);
+
+int dm_pool_close_thin_device(struct dm_thin_device *td);
+
+dm_thin_id dm_thin_dev_id(struct dm_thin_device *td);
+
+struct dm_thin_lookup_result {
+	dm_block_t block;
+	int shared;
+};
+
+/*
+ * Returns:
+ *   -EWOULDBLOCK iff @can_block is set and would block.
+ *   -ENODATA iff that mapping is not present.
+ *   0 success
+ */
+int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
+		       int can_block, struct dm_thin_lookup_result *result);
+
+/*
+ * Obtain an unused block.
+ */
+int dm_pool_alloc_data_block(struct dm_pool_metadata *pmd, dm_block_t *result);
+
+/*
+ * Insert or remove block.
+ */
+int dm_thin_insert_block(struct dm_thin_device *td, dm_block_t block,
+			 dm_block_t data_block);
+
+int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block);
+
+/*
+ * Queries.
+ */
+int dm_thin_get_highest_mapped_block(struct dm_thin_device *td,
+				     dm_block_t *highest_mapped);
+
+int dm_thin_get_mapped_count(struct dm_thin_device *td, dm_block_t *result);
+
+int dm_pool_get_free_block_count(struct dm_pool_metadata *pmd,
+				 dm_block_t *result);
+
+int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd,
+					  dm_block_t *result);
+
+int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd,
+				  dm_block_t *result);
+
+int dm_pool_get_data_block_size(struct dm_pool_metadata *pmd, sector_t *result);
+
+int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result);
+
+/*
+ * Returns -ENOSPC if the new size is too small and already allocated
+ * blocks would be lost.
+ */
+int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_size);
+
+/*----------------------------------------------------------------*/
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/md/dm-uevent.c linux-libre-3.2-gnu/drivers/md/dm-uevent.c
--- linux-libre-3.1-gnu/drivers/md/dm-uevent.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/dm-uevent.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/slab.h>
 #include <linux/kobject.h>
 #include <linux/dm-ioctl.h>
+#include <linux/export.h>
 
 #include "dm.h"
 #include "dm-uevent.h"
diff -druN linux-libre-3.1-gnu/drivers/md/faulty.c linux-libre-3.2-gnu/drivers/md/faulty.c
--- linux-libre-3.1-gnu/drivers/md/faulty.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/faulty.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,6 +63,7 @@
 
 #define MaxFault	50
 #include <linux/blkdev.h>
+#include <linux/module.h>
 #include <linux/raid/md_u.h>
 #include <linux/slab.h>
 #include "md.h"
@@ -81,16 +82,16 @@
 	bio_io_error(b);
 }
 
-typedef struct faulty_conf {
+struct faulty_conf {
 	int period[Modes];
 	atomic_t counters[Modes];
 	sector_t faults[MaxFault];
 	int	modes[MaxFault];
 	int nfaults;
-	mdk_rdev_t *rdev;
-} conf_t;
+	struct md_rdev *rdev;
+};
 
-static int check_mode(conf_t *conf, int mode)
+static int check_mode(struct faulty_conf *conf, int mode)
 {
 	if (conf->period[mode] == 0 &&
 	    atomic_read(&conf->counters[mode]) <= 0)
@@ -105,7 +106,7 @@
 	return 0;
 }
 
-static int check_sector(conf_t *conf, sector_t start, sector_t end, int dir)
+static int check_sector(struct faulty_conf *conf, sector_t start, sector_t end, int dir)
 {
 	/* If we find a ReadFixable sector, we fix it ... */
 	int i;
@@ -129,7 +130,7 @@
 	return 0;
 }
 
-static void add_sector(conf_t *conf, sector_t start, int mode)
+static void add_sector(struct faulty_conf *conf, sector_t start, int mode)
 {
 	int i;
 	int n = conf->nfaults;
@@ -169,9 +170,9 @@
 		conf->nfaults = n+1;
 }
 
-static int make_request(mddev_t *mddev, struct bio *bio)
+static void make_request(struct mddev *mddev, struct bio *bio)
 {
-	conf_t *conf = mddev->private;
+	struct faulty_conf *conf = mddev->private;
 	int failit = 0;
 
 	if (bio_data_dir(bio) == WRITE) {
@@ -181,7 +182,7 @@
 			 * just fail immediately
 			 */
 			bio_endio(bio, -EIO);
-			return 0;
+			return;
 		}
 
 		if (check_sector(conf, bio->bi_sector, bio->bi_sector+(bio->bi_size>>9),
@@ -211,20 +212,20 @@
 	}
 	if (failit) {
 		struct bio *b = bio_clone_mddev(bio, GFP_NOIO, mddev);
+
 		b->bi_bdev = conf->rdev->bdev;
 		b->bi_private = bio;
 		b->bi_end_io = faulty_fail;
-		generic_make_request(b);
-		return 0;
-	} else {
+		bio = b;
+	} else
 		bio->bi_bdev = conf->rdev->bdev;
-		return 1;
-	}
+
+	generic_make_request(bio);
 }
 
-static void status(struct seq_file *seq, mddev_t *mddev)
+static void status(struct seq_file *seq, struct mddev *mddev)
 {
-	conf_t *conf = mddev->private;
+	struct faulty_conf *conf = mddev->private;
 	int n;
 
 	if ((n=atomic_read(&conf->counters[WriteTransient])) != 0)
@@ -255,11 +256,11 @@
 }
 
 
-static int reshape(mddev_t *mddev)
+static int reshape(struct mddev *mddev)
 {
 	int mode = mddev->new_layout & ModeMask;
 	int count = mddev->new_layout >> ModeShift;
-	conf_t *conf = mddev->private;
+	struct faulty_conf *conf = mddev->private;
 
 	if (mddev->new_layout < 0)
 		return 0;
@@ -284,7 +285,7 @@
 	return 0;
 }
 
-static sector_t faulty_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+static sector_t faulty_size(struct mddev *mddev, sector_t sectors, int raid_disks)
 {
 	WARN_ONCE(raid_disks,
 		  "%s does not support generic reshape\n", __func__);
@@ -295,11 +296,11 @@
 	return sectors;
 }
 
-static int run(mddev_t *mddev)
+static int run(struct mddev *mddev)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int i;
-	conf_t *conf;
+	struct faulty_conf *conf;
 
 	if (md_check_no_bitmap(mddev))
 		return -EINVAL;
@@ -325,16 +326,16 @@
 	return 0;
 }
 
-static int stop(mddev_t *mddev)
+static int stop(struct mddev *mddev)
 {
-	conf_t *conf = mddev->private;
+	struct faulty_conf *conf = mddev->private;
 
 	kfree(conf);
 	mddev->private = NULL;
 	return 0;
 }
 
-static struct mdk_personality faulty_personality =
+static struct md_personality faulty_personality =
 {
 	.name		= "faulty",
 	.level		= LEVEL_FAULTY,
diff -druN linux-libre-3.1-gnu/drivers/md/Kconfig linux-libre-3.2-gnu/drivers/md/Kconfig
--- linux-libre-3.1-gnu/drivers/md/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -208,6 +208,16 @@
 
 	  If unsure, say N.
 
+config DM_BUFIO
+       tristate
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       ---help---
+	 This interface allows you to do buffered I/O on a device and acts
+	 as a cache, holding recently-read blocks in memory and performing
+	 delayed writes.
+
+source "drivers/md/persistent-data/Kconfig"
+
 config DM_CRYPT
 	tristate "Crypt target support"
 	depends on BLK_DEV_DM
@@ -233,6 +243,32 @@
        ---help---
          Allow volume managers to take writable snapshots of a device.
 
+config DM_THIN_PROVISIONING
+       tristate "Thin provisioning target (EXPERIMENTAL)"
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       select DM_PERSISTENT_DATA
+       ---help---
+         Provides thin provisioning and snapshots that share a data store.
+
+config DM_DEBUG_BLOCK_STACK_TRACING
+	boolean "Keep stack trace of thin provisioning block lock holders"
+	depends on STACKTRACE_SUPPORT && DM_THIN_PROVISIONING
+	select STACKTRACE
+	---help---
+	  Enable this for messages that may help debug problems with the
+	  block manager locking used by thin provisioning.
+
+	  If unsure, say N.
+
+config DM_DEBUG_SPACE_MAPS
+	boolean "Extra validation for thin provisioning space maps"
+	depends on DM_THIN_PROVISIONING
+	---help---
+	  Enable this for messages that may help debug problems with the
+	  space maps used by thin provisioning.
+
+          If unsure, say N.
+
 config DM_MIRROR
        tristate "Mirror target"
        depends on BLK_DEV_DM
diff -druN linux-libre-3.1-gnu/drivers/md/linear.c linux-libre-3.2-gnu/drivers/md/linear.c
--- linux-libre-3.1-gnu/drivers/md/linear.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/linear.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/blkdev.h>
 #include <linux/raid/md_u.h>
 #include <linux/seq_file.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include "md.h"
 #include "linear.h"
@@ -26,10 +27,10 @@
 /*
  * find which device holds a particular offset 
  */
-static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
+static inline struct dev_info *which_dev(struct mddev *mddev, sector_t sector)
 {
 	int lo, mid, hi;
-	linear_conf_t *conf;
+	struct linear_conf *conf;
 
 	lo = 0;
 	hi = mddev->raid_disks - 1;
@@ -63,8 +64,8 @@
 				 struct bvec_merge_data *bvm,
 				 struct bio_vec *biovec)
 {
-	mddev_t *mddev = q->queuedata;
-	dev_info_t *dev0;
+	struct mddev *mddev = q->queuedata;
+	struct dev_info *dev0;
 	unsigned long maxsectors, bio_sectors = bvm->bi_size >> 9;
 	sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
 
@@ -89,8 +90,8 @@
 
 static int linear_congested(void *data, int bits)
 {
-	mddev_t *mddev = data;
-	linear_conf_t *conf;
+	struct mddev *mddev = data;
+	struct linear_conf *conf;
 	int i, ret = 0;
 
 	if (mddev_congested(mddev, bits))
@@ -108,9 +109,9 @@
 	return ret;
 }
 
-static sector_t linear_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+static sector_t linear_size(struct mddev *mddev, sector_t sectors, int raid_disks)
 {
-	linear_conf_t *conf;
+	struct linear_conf *conf;
 	sector_t array_sectors;
 
 	rcu_read_lock();
@@ -123,13 +124,13 @@
 	return array_sectors;
 }
 
-static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
+static struct linear_conf *linear_conf(struct mddev *mddev, int raid_disks)
 {
-	linear_conf_t *conf;
-	mdk_rdev_t *rdev;
+	struct linear_conf *conf;
+	struct md_rdev *rdev;
 	int i, cnt;
 
-	conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t),
+	conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(struct dev_info),
 			GFP_KERNEL);
 	if (!conf)
 		return NULL;
@@ -139,7 +140,7 @@
 
 	list_for_each_entry(rdev, &mddev->disks, same_set) {
 		int j = rdev->raid_disk;
-		dev_info_t *disk = conf->disks + j;
+		struct dev_info *disk = conf->disks + j;
 		sector_t sectors;
 
 		if (j < 0 || j >= raid_disks || disk->rdev) {
@@ -194,9 +195,9 @@
 	return NULL;
 }
 
-static int linear_run (mddev_t *mddev)
+static int linear_run (struct mddev *mddev)
 {
-	linear_conf_t *conf;
+	struct linear_conf *conf;
 
 	if (md_check_no_bitmap(mddev))
 		return -EINVAL;
@@ -213,7 +214,7 @@
 	return md_integrity_register(mddev);
 }
 
-static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
+static int linear_add(struct mddev *mddev, struct md_rdev *rdev)
 {
 	/* Adding a drive to a linear array allows the array to grow.
 	 * It is permitted if the new drive has a matching superblock
@@ -223,12 +224,13 @@
 	 * The current one is never freed until the array is stopped.
 	 * This avoids races.
 	 */
-	linear_conf_t *newconf, *oldconf;
+	struct linear_conf *newconf, *oldconf;
 
 	if (rdev->saved_raid_disk != mddev->raid_disks)
 		return -EINVAL;
 
 	rdev->raid_disk = rdev->saved_raid_disk;
+	rdev->saved_raid_disk = -1;
 
 	newconf = linear_conf(mddev,mddev->raid_disks+1);
 
@@ -245,9 +247,9 @@
 	return 0;
 }
 
-static int linear_stop (mddev_t *mddev)
+static int linear_stop (struct mddev *mddev)
 {
-	linear_conf_t *conf = mddev->private;
+	struct linear_conf *conf = mddev->private;
 
 	/*
 	 * We do not require rcu protection here since
@@ -264,14 +266,14 @@
 	return 0;
 }
 
-static int linear_make_request (mddev_t *mddev, struct bio *bio)
+static void linear_make_request(struct mddev *mddev, struct bio *bio)
 {
-	dev_info_t *tmp_dev;
+	struct dev_info *tmp_dev;
 	sector_t start_sector;
 
 	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
 		md_flush_request(mddev, bio);
-		return 0;
+		return;
 	}
 
 	rcu_read_lock();
@@ -293,7 +295,7 @@
 		       (unsigned long long)start_sector);
 		rcu_read_unlock();
 		bio_io_error(bio);
-		return 0;
+		return;
 	}
 	if (unlikely(bio->bi_sector + (bio->bi_size >> 9) >
 		     tmp_dev->end_sector)) {
@@ -307,30 +309,27 @@
 
 		bp = bio_split(bio, end_sector - bio->bi_sector);
 
-		if (linear_make_request(mddev, &bp->bio1))
-			generic_make_request(&bp->bio1);
-		if (linear_make_request(mddev, &bp->bio2))
-			generic_make_request(&bp->bio2);
+		linear_make_request(mddev, &bp->bio1);
+		linear_make_request(mddev, &bp->bio2);
 		bio_pair_release(bp);
-		return 0;
+		return;
 	}
 		    
 	bio->bi_bdev = tmp_dev->rdev->bdev;
 	bio->bi_sector = bio->bi_sector - start_sector
 		+ tmp_dev->rdev->data_offset;
 	rcu_read_unlock();
-
-	return 1;
+	generic_make_request(bio);
 }
 
-static void linear_status (struct seq_file *seq, mddev_t *mddev)
+static void linear_status (struct seq_file *seq, struct mddev *mddev)
 {
 
 	seq_printf(seq, " %dk rounding", mddev->chunk_sectors / 2);
 }
 
 
-static struct mdk_personality linear_personality =
+static struct md_personality linear_personality =
 {
 	.name		= "linear",
 	.level		= LEVEL_LINEAR,
diff -druN linux-libre-3.1-gnu/drivers/md/linear.h linux-libre-3.2-gnu/drivers/md/linear.h
--- linux-libre-3.1-gnu/drivers/md/linear.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/linear.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,20 +2,14 @@
 #define _LINEAR_H
 
 struct dev_info {
-	mdk_rdev_t	*rdev;
+	struct md_rdev	*rdev;
 	sector_t	end_sector;
 };
 
-typedef struct dev_info dev_info_t;
-
-struct linear_private_data
+struct linear_conf
 {
 	struct rcu_head		rcu;
 	sector_t		array_sectors;
-	dev_info_t		disks[0];
+	struct dev_info		disks[0];
 };
-
-
-typedef struct linear_private_data linear_conf_t;
-
 #endif
diff -druN linux-libre-3.1-gnu/drivers/md/Makefile linux-libre-3.2-gnu/drivers/md/Makefile
--- linux-libre-3.1-gnu/drivers/md/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 dm-mirror-y	+= dm-raid1.o
 dm-log-userspace-y \
 		+= dm-log-userspace-base.o dm-log-userspace-transfer.o
+dm-thin-pool-y	+= dm-thin.o dm-thin-metadata.o
 md-mod-y	+= md.o bitmap.o
 raid456-y	+= raid5.o
 
@@ -27,6 +28,7 @@
 obj-$(CONFIG_MD_FAULTY)		+= faulty.o
 obj-$(CONFIG_BLK_DEV_MD)	+= md-mod.o
 obj-$(CONFIG_BLK_DEV_DM)	+= dm-mod.o
+obj-$(CONFIG_DM_BUFIO)		+= dm-bufio.o
 obj-$(CONFIG_DM_CRYPT)		+= dm-crypt.o
 obj-$(CONFIG_DM_DELAY)		+= dm-delay.o
 obj-$(CONFIG_DM_FLAKEY)		+= dm-flakey.o
@@ -34,10 +36,12 @@
 obj-$(CONFIG_DM_MULTIPATH_QL)	+= dm-queue-length.o
 obj-$(CONFIG_DM_MULTIPATH_ST)	+= dm-service-time.o
 obj-$(CONFIG_DM_SNAPSHOT)	+= dm-snapshot.o
+obj-$(CONFIG_DM_PERSISTENT_DATA)	+= persistent-data/
 obj-$(CONFIG_DM_MIRROR)		+= dm-mirror.o dm-log.o dm-region-hash.o
 obj-$(CONFIG_DM_LOG_USERSPACE)	+= dm-log-userspace.o
 obj-$(CONFIG_DM_ZERO)		+= dm-zero.o
 obj-$(CONFIG_DM_RAID)	+= dm-raid.o
+obj-$(CONFIG_DM_THIN_PROVISIONING)	+= dm-thin-pool.o
 
 ifeq ($(CONFIG_DM_UEVENT),y)
 dm-mod-objs			+= dm-uevent.o
diff -druN linux-libre-3.1-gnu/drivers/md/md.c linux-libre-3.2-gnu/drivers/md/md.c
--- linux-libre-3.1-gnu/drivers/md/md.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/md.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,6 +44,7 @@
 #include <linux/hdreg.h>
 #include <linux/proc_fs.h>
 #include <linux/random.h>
+#include <linux/module.h>
 #include <linux/reboot.h>
 #include <linux/file.h>
 #include <linux/compat.h>
@@ -54,9 +55,6 @@
 #include "md.h"
 #include "bitmap.h"
 
-#define DEBUG 0
-#define dprintk(x...) ((void)(DEBUG && printk(x)))
-
 #ifndef MODULE
 static void autostart_arrays(int part);
 #endif
@@ -98,13 +96,13 @@
 
 static int sysctl_speed_limit_min = 1000;
 static int sysctl_speed_limit_max = 200000;
-static inline int speed_min(mddev_t *mddev)
+static inline int speed_min(struct mddev *mddev)
 {
 	return mddev->sync_speed_min ?
 		mddev->sync_speed_min : sysctl_speed_limit_min;
 }
 
-static inline int speed_max(mddev_t *mddev)
+static inline int speed_max(struct mddev *mddev)
 {
 	return mddev->sync_speed_max ?
 		mddev->sync_speed_max : sysctl_speed_limit_max;
@@ -160,7 +158,7 @@
 
 static void mddev_bio_destructor(struct bio *bio)
 {
-	mddev_t *mddev, **mddevp;
+	struct mddev *mddev, **mddevp;
 
 	mddevp = (void*)bio;
 	mddev = mddevp[-1];
@@ -169,10 +167,10 @@
 }
 
 struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
-			    mddev_t *mddev)
+			    struct mddev *mddev)
 {
 	struct bio *b;
-	mddev_t **mddevp;
+	struct mddev **mddevp;
 
 	if (!mddev || !mddev->bio_set)
 		return bio_alloc(gfp_mask, nr_iovecs);
@@ -189,10 +187,10 @@
 EXPORT_SYMBOL_GPL(bio_alloc_mddev);
 
 struct bio *bio_clone_mddev(struct bio *bio, gfp_t gfp_mask,
-			    mddev_t *mddev)
+			    struct mddev *mddev)
 {
 	struct bio *b;
-	mddev_t **mddevp;
+	struct mddev **mddevp;
 
 	if (!mddev || !mddev->bio_set)
 		return bio_clone(bio, gfp_mask);
@@ -281,7 +279,7 @@
  */
 static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters);
 static atomic_t md_event_count;
-void md_new_event(mddev_t *mddev)
+void md_new_event(struct mddev *mddev)
 {
 	atomic_inc(&md_event_count);
 	wake_up(&md_event_waiters);
@@ -291,7 +289,7 @@
 /* Alternate version that can be called from interrupts
  * when calling sysfs_notify isn't needed.
  */
-static void md_new_event_inintr(mddev_t *mddev)
+static void md_new_event_inintr(struct mddev *mddev)
 {
 	atomic_inc(&md_event_count);
 	wake_up(&md_event_waiters);
@@ -312,19 +310,19 @@
  * Any code which breaks out of this loop while own
  * a reference to the current mddev and must mddev_put it.
  */
-#define for_each_mddev(mddev,tmp)					\
+#define for_each_mddev(_mddev,_tmp)					\
 									\
 	for (({ spin_lock(&all_mddevs_lock); 				\
-		tmp = all_mddevs.next;					\
-		mddev = NULL;});					\
-	     ({ if (tmp != &all_mddevs)					\
-			mddev_get(list_entry(tmp, mddev_t, all_mddevs));\
+		_tmp = all_mddevs.next;					\
+		_mddev = NULL;});					\
+	     ({ if (_tmp != &all_mddevs)				\
+			mddev_get(list_entry(_tmp, struct mddev, all_mddevs));\
 		spin_unlock(&all_mddevs_lock);				\
-		if (mddev) mddev_put(mddev);				\
-		mddev = list_entry(tmp, mddev_t, all_mddevs);		\
-		tmp != &all_mddevs;});					\
+		if (_mddev) mddev_put(_mddev);				\
+		_mddev = list_entry(_tmp, struct mddev, all_mddevs);	\
+		_tmp != &all_mddevs;});					\
 	     ({ spin_lock(&all_mddevs_lock);				\
-		tmp = tmp->next;})					\
+		_tmp = _tmp->next;})					\
 		)
 
 
@@ -335,18 +333,17 @@
  * call has finished, the bio has been linked into some internal structure
  * and so is visible to ->quiesce(), so we don't need the refcount any more.
  */
-static int md_make_request(struct request_queue *q, struct bio *bio)
+static void md_make_request(struct request_queue *q, struct bio *bio)
 {
 	const int rw = bio_data_dir(bio);
-	mddev_t *mddev = q->queuedata;
-	int rv;
+	struct mddev *mddev = q->queuedata;
 	int cpu;
 	unsigned int sectors;
 
 	if (mddev == NULL || mddev->pers == NULL
 	    || !mddev->ready) {
 		bio_io_error(bio);
-		return 0;
+		return;
 	}
 	smp_rmb(); /* Ensure implications of  'active' are visible */
 	rcu_read_lock();
@@ -371,7 +368,7 @@
 	 * go away inside make_request
 	 */
 	sectors = bio_sectors(bio);
-	rv = mddev->pers->make_request(mddev, bio);
+	mddev->pers->make_request(mddev, bio);
 
 	cpu = part_stat_lock();
 	part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
@@ -380,8 +377,6 @@
 
 	if (atomic_dec_and_test(&mddev->active_io) && mddev->suspended)
 		wake_up(&mddev->sb_wait);
-
-	return rv;
 }
 
 /* mddev_suspend makes sure no new requests are submitted
@@ -390,7 +385,7 @@
  * Once ->stop is called and completes, the module will be completely
  * unused.
  */
-void mddev_suspend(mddev_t *mddev)
+void mddev_suspend(struct mddev *mddev)
 {
 	BUG_ON(mddev->suspended);
 	mddev->suspended = 1;
@@ -400,7 +395,7 @@
 }
 EXPORT_SYMBOL_GPL(mddev_suspend);
 
-void mddev_resume(mddev_t *mddev)
+void mddev_resume(struct mddev *mddev)
 {
 	mddev->suspended = 0;
 	wake_up(&mddev->sb_wait);
@@ -411,7 +406,7 @@
 }
 EXPORT_SYMBOL_GPL(mddev_resume);
 
-int mddev_congested(mddev_t *mddev, int bits)
+int mddev_congested(struct mddev *mddev, int bits)
 {
 	return mddev->suspended;
 }
@@ -423,8 +418,8 @@
 
 static void md_end_flush(struct bio *bio, int err)
 {
-	mdk_rdev_t *rdev = bio->bi_private;
-	mddev_t *mddev = rdev->mddev;
+	struct md_rdev *rdev = bio->bi_private;
+	struct mddev *mddev = rdev->mddev;
 
 	rdev_dec_pending(rdev, mddev);
 
@@ -439,8 +434,8 @@
 
 static void submit_flushes(struct work_struct *ws)
 {
-	mddev_t *mddev = container_of(ws, mddev_t, flush_work);
-	mdk_rdev_t *rdev;
+	struct mddev *mddev = container_of(ws, struct mddev, flush_work);
+	struct md_rdev *rdev;
 
 	INIT_WORK(&mddev->flush_work, md_submit_flush_data);
 	atomic_set(&mddev->flush_pending, 1);
@@ -472,7 +467,7 @@
 
 static void md_submit_flush_data(struct work_struct *ws)
 {
-	mddev_t *mddev = container_of(ws, mddev_t, flush_work);
+	struct mddev *mddev = container_of(ws, struct mddev, flush_work);
 	struct bio *bio = mddev->flush_bio;
 
 	if (bio->bi_size == 0)
@@ -480,15 +475,14 @@
 		bio_endio(bio, 0);
 	else {
 		bio->bi_rw &= ~REQ_FLUSH;
-		if (mddev->pers->make_request(mddev, bio))
-			generic_make_request(bio);
+		mddev->pers->make_request(mddev, bio);
 	}
 
 	mddev->flush_bio = NULL;
 	wake_up(&mddev->sb_wait);
 }
 
-void md_flush_request(mddev_t *mddev, struct bio *bio)
+void md_flush_request(struct mddev *mddev, struct bio *bio)
 {
 	spin_lock_irq(&mddev->write_lock);
 	wait_event_lock_irq(mddev->sb_wait,
@@ -512,7 +506,7 @@
  */
 struct md_plug_cb {
 	struct blk_plug_cb cb;
-	mddev_t *mddev;
+	struct mddev *mddev;
 };
 
 static void plugger_unplug(struct blk_plug_cb *cb)
@@ -526,7 +520,7 @@
 /* Check that an unplug wakeup will come shortly.
  * If not, wakeup the md thread immediately
  */
-int mddev_check_plugged(mddev_t *mddev)
+int mddev_check_plugged(struct mddev *mddev)
 {
 	struct blk_plug *plug = current->plug;
 	struct md_plug_cb *mdcb;
@@ -558,7 +552,7 @@
 }
 EXPORT_SYMBOL_GPL(mddev_check_plugged);
 
-static inline mddev_t *mddev_get(mddev_t *mddev)
+static inline struct mddev *mddev_get(struct mddev *mddev)
 {
 	atomic_inc(&mddev->active);
 	return mddev;
@@ -566,7 +560,7 @@
 
 static void mddev_delayed_delete(struct work_struct *ws);
 
-static void mddev_put(mddev_t *mddev)
+static void mddev_put(struct mddev *mddev)
 {
 	struct bio_set *bs = NULL;
 
@@ -576,7 +570,7 @@
 	    mddev->ctime == 0 && !mddev->hold_active) {
 		/* Array is not configured at all, and not held active,
 		 * so destroy it */
-		list_del(&mddev->all_mddevs);
+		list_del_init(&mddev->all_mddevs);
 		bs = mddev->bio_set;
 		mddev->bio_set = NULL;
 		if (mddev->gendisk) {
@@ -595,7 +589,7 @@
 		bioset_free(bs);
 }
 
-void mddev_init(mddev_t *mddev)
+void mddev_init(struct mddev *mddev)
 {
 	mutex_init(&mddev->open_mutex);
 	mutex_init(&mddev->reconfig_mutex);
@@ -618,9 +612,9 @@
 }
 EXPORT_SYMBOL_GPL(mddev_init);
 
-static mddev_t * mddev_find(dev_t unit)
+static struct mddev * mddev_find(dev_t unit)
 {
-	mddev_t *mddev, *new = NULL;
+	struct mddev *mddev, *new = NULL;
 
 	if (unit && MAJOR(unit) != MD_MAJOR)
 		unit &= ~((1<<MdpMinorShift)-1);
@@ -692,24 +686,24 @@
 	goto retry;
 }
 
-static inline int mddev_lock(mddev_t * mddev)
+static inline int mddev_lock(struct mddev * mddev)
 {
 	return mutex_lock_interruptible(&mddev->reconfig_mutex);
 }
 
-static inline int mddev_is_locked(mddev_t *mddev)
+static inline int mddev_is_locked(struct mddev *mddev)
 {
 	return mutex_is_locked(&mddev->reconfig_mutex);
 }
 
-static inline int mddev_trylock(mddev_t * mddev)
+static inline int mddev_trylock(struct mddev * mddev)
 {
 	return mutex_trylock(&mddev->reconfig_mutex);
 }
 
 static struct attribute_group md_redundancy_group;
 
-static void mddev_unlock(mddev_t * mddev)
+static void mddev_unlock(struct mddev * mddev)
 {
 	if (mddev->to_remove) {
 		/* These cannot be removed under reconfig_mutex as
@@ -744,17 +738,17 @@
 	} else
 		mutex_unlock(&mddev->reconfig_mutex);
 
-	/* was we've dropped the mutex we need a spinlock to
-	 * make sur the thread doesn't disappear
+	/* As we've dropped the mutex we need a spinlock to
+	 * make sure the thread doesn't disappear
 	 */
 	spin_lock(&pers_lock);
 	md_wakeup_thread(mddev->thread);
 	spin_unlock(&pers_lock);
 }
 
-static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
+static struct md_rdev * find_rdev_nr(struct mddev *mddev, int nr)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	list_for_each_entry(rdev, &mddev->disks, same_set)
 		if (rdev->desc_nr == nr)
@@ -763,9 +757,9 @@
 	return NULL;
 }
 
-static mdk_rdev_t * find_rdev(mddev_t * mddev, dev_t dev)
+static struct md_rdev * find_rdev(struct mddev * mddev, dev_t dev)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	list_for_each_entry(rdev, &mddev->disks, same_set)
 		if (rdev->bdev->bd_dev == dev)
@@ -774,9 +768,9 @@
 	return NULL;
 }
 
-static struct mdk_personality *find_pers(int level, char *clevel)
+static struct md_personality *find_pers(int level, char *clevel)
 {
-	struct mdk_personality *pers;
+	struct md_personality *pers;
 	list_for_each_entry(pers, &pers_list, list) {
 		if (level != LEVEL_NONE && pers->level == level)
 			return pers;
@@ -787,13 +781,13 @@
 }
 
 /* return the offset of the super block in 512byte sectors */
-static inline sector_t calc_dev_sboffset(mdk_rdev_t *rdev)
+static inline sector_t calc_dev_sboffset(struct md_rdev *rdev)
 {
 	sector_t num_sectors = i_size_read(rdev->bdev->bd_inode) / 512;
 	return MD_NEW_SIZE_SECTORS(num_sectors);
 }
 
-static int alloc_disk_sb(mdk_rdev_t * rdev)
+static int alloc_disk_sb(struct md_rdev * rdev)
 {
 	if (rdev->sb_page)
 		MD_BUG();
@@ -807,7 +801,7 @@
 	return 0;
 }
 
-static void free_disk_sb(mdk_rdev_t * rdev)
+static void free_disk_sb(struct md_rdev * rdev)
 {
 	if (rdev->sb_page) {
 		put_page(rdev->sb_page);
@@ -825,8 +819,8 @@
 
 static void super_written(struct bio *bio, int error)
 {
-	mdk_rdev_t *rdev = bio->bi_private;
-	mddev_t *mddev = rdev->mddev;
+	struct md_rdev *rdev = bio->bi_private;
+	struct mddev *mddev = rdev->mddev;
 
 	if (error || !test_bit(BIO_UPTODATE, &bio->bi_flags)) {
 		printk("md: super_written gets error=%d, uptodate=%d\n",
@@ -840,7 +834,7 @@
 	bio_put(bio);
 }
 
-void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
+void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
 		   sector_t sector, int size, struct page *page)
 {
 	/* write first size bytes of page to sector of rdev
@@ -861,7 +855,7 @@
 	submit_bio(WRITE_FLUSH_FUA, bio);
 }
 
-void md_super_wait(mddev_t *mddev)
+void md_super_wait(struct mddev *mddev)
 {
 	/* wait for all superblock writes that were scheduled to complete */
 	DEFINE_WAIT(wq);
@@ -879,7 +873,7 @@
 	complete((struct completion*)bio->bi_private);
 }
 
-int sync_page_io(mdk_rdev_t *rdev, sector_t sector, int size,
+int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
 		 struct page *page, int rw, bool metadata_op)
 {
 	struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, rdev->mddev);
@@ -907,7 +901,7 @@
 }
 EXPORT_SYMBOL_GPL(sync_page_io);
 
-static int read_disk_sb(mdk_rdev_t * rdev, int size)
+static int read_disk_sb(struct md_rdev * rdev, int size)
 {
 	char b[BDEVNAME_SIZE];
 	if (!rdev->sb_page) {
@@ -1014,7 +1008,7 @@
  * We rely on user-space to write the initial superblock, and support
  * reading and updating of superblocks.
  * Interface methods are:
- *   int load_super(mdk_rdev_t *dev, mdk_rdev_t *refdev, int minor_version)
+ *   int load_super(struct md_rdev *dev, struct md_rdev *refdev, int minor_version)
  *      loads and validates a superblock on dev.
  *      if refdev != NULL, compare superblocks on both devices
  *    Return:
@@ -1024,13 +1018,13 @@
  *     -EINVAL superblock incompatible or invalid
  *     -othererror e.g. -EIO
  *
- *   int validate_super(mddev_t *mddev, mdk_rdev_t *dev)
+ *   int validate_super(struct mddev *mddev, struct md_rdev *dev)
  *      Verify that dev is acceptable into mddev.
  *       The first time, mddev->raid_disks will be 0, and data from
  *       dev should be merged in.  Subsequent calls check that dev
  *       is new enough.  Return 0 or -EINVAL
  *
- *   void sync_super(mddev_t *mddev, mdk_rdev_t *dev)
+ *   void sync_super(struct mddev *mddev, struct md_rdev *dev)
  *     Update the superblock for rdev with data in mddev
  *     This does not write to disc.
  *
@@ -1039,11 +1033,11 @@
 struct super_type  {
 	char		    *name;
 	struct module	    *owner;
-	int		    (*load_super)(mdk_rdev_t *rdev, mdk_rdev_t *refdev,
+	int		    (*load_super)(struct md_rdev *rdev, struct md_rdev *refdev,
 					  int minor_version);
-	int		    (*validate_super)(mddev_t *mddev, mdk_rdev_t *rdev);
-	void		    (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev);
-	unsigned long long  (*rdev_size_change)(mdk_rdev_t *rdev,
+	int		    (*validate_super)(struct mddev *mddev, struct md_rdev *rdev);
+	void		    (*sync_super)(struct mddev *mddev, struct md_rdev *rdev);
+	unsigned long long  (*rdev_size_change)(struct md_rdev *rdev,
 						sector_t num_sectors);
 };
 
@@ -1055,7 +1049,7 @@
  * has a bitmap. Otherwise, it returns 0.
  *
  */
-int md_check_no_bitmap(mddev_t *mddev)
+int md_check_no_bitmap(struct mddev *mddev)
 {
 	if (!mddev->bitmap_info.file && !mddev->bitmap_info.offset)
 		return 0;
@@ -1068,7 +1062,7 @@
 /*
  * load_super for 0.90.0 
  */
-static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
+static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_version)
 {
 	char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
 	mdp_super_t *sb;
@@ -1163,7 +1157,7 @@
 /*
  * validate_super for 0.90.0
  */
-static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
 {
 	mdp_disk_t *desc;
 	mdp_super_t *sb = page_address(rdev->sb_page);
@@ -1275,10 +1269,10 @@
 /*
  * sync_super for 0.90.0
  */
-static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+static void super_90_sync(struct mddev *mddev, struct md_rdev *rdev)
 {
 	mdp_super_t *sb;
-	mdk_rdev_t *rdev2;
+	struct md_rdev *rdev2;
 	int next_spare = mddev->raid_disks;
 
 
@@ -1419,7 +1413,7 @@
  * rdev_size_change for 0.90.0
  */
 static unsigned long long
-super_90_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
+super_90_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
 {
 	if (num_sectors && num_sectors < rdev->mddev->dev_sectors)
 		return 0; /* component must fit device */
@@ -1469,7 +1463,7 @@
 
 static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors,
 			    int acknowledged);
-static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
+static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_version)
 {
 	struct mdp_superblock_1 *sb;
 	int ret;
@@ -1625,7 +1619,7 @@
 	return ret;
 }
 
-static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
 {
 	struct mdp_superblock_1 *sb = page_address(rdev->sb_page);
 	__u64 ev1 = le64_to_cpu(sb->events);
@@ -1726,10 +1720,10 @@
 	return 0;
 }
 
-static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
 {
 	struct mdp_superblock_1 *sb;
-	mdk_rdev_t *rdev2;
+	struct md_rdev *rdev2;
 	int max_dev, i;
 	/* make rdev->sb match mddev and rdev data. */
 
@@ -1851,7 +1845,7 @@
 }
 
 static unsigned long long
-super_1_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
+super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
 {
 	struct mdp_superblock_1 *sb;
 	sector_t max_sectors;
@@ -1905,7 +1899,7 @@
 	},
 };
 
-static void sync_super(mddev_t *mddev, mdk_rdev_t *rdev)
+static void sync_super(struct mddev *mddev, struct md_rdev *rdev)
 {
 	if (mddev->sync_super) {
 		mddev->sync_super(mddev, rdev);
@@ -1917,9 +1911,9 @@
 	super_types[mddev->major_version].sync_super(mddev, rdev);
 }
 
-static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2)
+static int match_mddev_units(struct mddev *mddev1, struct mddev *mddev2)
 {
-	mdk_rdev_t *rdev, *rdev2;
+	struct md_rdev *rdev, *rdev2;
 
 	rcu_read_lock();
 	rdev_for_each_rcu(rdev, mddev1)
@@ -1942,9 +1936,9 @@
  * from the array. It only succeeds if all working and active component devices
  * are integrity capable with matching profiles.
  */
-int md_integrity_register(mddev_t *mddev)
+int md_integrity_register(struct mddev *mddev)
 {
-	mdk_rdev_t *rdev, *reference = NULL;
+	struct md_rdev *rdev, *reference = NULL;
 
 	if (list_empty(&mddev->disks))
 		return 0; /* nothing to do */
@@ -1989,7 +1983,7 @@
 EXPORT_SYMBOL(md_integrity_register);
 
 /* Disable data integrity if non-capable/non-matching disk is being added */
-void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
+void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
 {
 	struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev);
 	struct blk_integrity *bi_mddev = blk_get_integrity(mddev->gendisk);
@@ -2006,7 +2000,7 @@
 }
 EXPORT_SYMBOL(md_integrity_add_rdev);
 
-static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
+static int bind_rdev_to_array(struct md_rdev * rdev, struct mddev * mddev)
 {
 	char b[BDEVNAME_SIZE];
 	struct kobject *ko;
@@ -2086,12 +2080,12 @@
 
 static void md_delayed_delete(struct work_struct *ws)
 {
-	mdk_rdev_t *rdev = container_of(ws, mdk_rdev_t, del_work);
+	struct md_rdev *rdev = container_of(ws, struct md_rdev, del_work);
 	kobject_del(&rdev->kobj);
 	kobject_put(&rdev->kobj);
 }
 
-static void unbind_rdev_from_array(mdk_rdev_t * rdev)
+static void unbind_rdev_from_array(struct md_rdev * rdev)
 {
 	char b[BDEVNAME_SIZE];
 	if (!rdev->mddev) {
@@ -2123,14 +2117,14 @@
  * otherwise reused by a RAID array (or any other kernel
  * subsystem), by bd_claiming the device.
  */
-static int lock_rdev(mdk_rdev_t *rdev, dev_t dev, int shared)
+static int lock_rdev(struct md_rdev *rdev, dev_t dev, int shared)
 {
 	int err = 0;
 	struct block_device *bdev;
 	char b[BDEVNAME_SIZE];
 
 	bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
-				 shared ? (mdk_rdev_t *)lock_rdev : rdev);
+				 shared ? (struct md_rdev *)lock_rdev : rdev);
 	if (IS_ERR(bdev)) {
 		printk(KERN_ERR "md: could not open %s.\n",
 			__bdevname(dev, b));
@@ -2140,7 +2134,7 @@
 	return err;
 }
 
-static void unlock_rdev(mdk_rdev_t *rdev)
+static void unlock_rdev(struct md_rdev *rdev)
 {
 	struct block_device *bdev = rdev->bdev;
 	rdev->bdev = NULL;
@@ -2151,7 +2145,7 @@
 
 void md_autodetect_dev(dev_t dev);
 
-static void export_rdev(mdk_rdev_t * rdev)
+static void export_rdev(struct md_rdev * rdev)
 {
 	char b[BDEVNAME_SIZE];
 	printk(KERN_INFO "md: export_rdev(%s)\n",
@@ -2167,15 +2161,15 @@
 	kobject_put(&rdev->kobj);
 }
 
-static void kick_rdev_from_array(mdk_rdev_t * rdev)
+static void kick_rdev_from_array(struct md_rdev * rdev)
 {
 	unbind_rdev_from_array(rdev);
 	export_rdev(rdev);
 }
 
-static void export_array(mddev_t *mddev)
+static void export_array(struct mddev *mddev)
 {
-	mdk_rdev_t *rdev, *tmp;
+	struct md_rdev *rdev, *tmp;
 
 	rdev_for_each(rdev, tmp, mddev) {
 		if (!rdev->mddev) {
@@ -2271,7 +2265,7 @@
 		);
 }
 
-static void print_rdev(mdk_rdev_t *rdev, int major_version)
+static void print_rdev(struct md_rdev *rdev, int major_version)
 {
 	char b[BDEVNAME_SIZE];
 	printk(KERN_INFO "md: rdev %s, Sect:%08llu F:%d S:%d DN:%u\n",
@@ -2295,8 +2289,8 @@
 static void md_print_devices(void)
 {
 	struct list_head *tmp;
-	mdk_rdev_t *rdev;
-	mddev_t *mddev;
+	struct md_rdev *rdev;
+	struct mddev *mddev;
 	char b[BDEVNAME_SIZE];
 
 	printk("\n");
@@ -2321,7 +2315,7 @@
 }
 
 
-static void sync_sbs(mddev_t * mddev, int nospares)
+static void sync_sbs(struct mddev * mddev, int nospares)
 {
 	/* Update each superblock (in-memory image), but
 	 * if we are allowed to, skip spares which already
@@ -2329,7 +2323,7 @@
 	 * (which would mean they aren't being marked as dirty
 	 * with the rest of the array)
 	 */
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	list_for_each_entry(rdev, &mddev->disks, same_set) {
 		if (rdev->sb_events == mddev->events ||
 		    (nospares &&
@@ -2344,9 +2338,9 @@
 	}
 }
 
-static void md_update_sb(mddev_t * mddev, int force_change)
+static void md_update_sb(struct mddev * mddev, int force_change)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int sync_req;
 	int nospares = 0;
 	int any_badblocks_changed = 0;
@@ -2442,27 +2436,24 @@
 	sync_sbs(mddev, nospares);
 	spin_unlock_irq(&mddev->write_lock);
 
-	dprintk(KERN_INFO 
-		"md: updating %s RAID superblock on device (in sync %d)\n",
-		mdname(mddev),mddev->in_sync);
+	pr_debug("md: updating %s RAID superblock on device (in sync %d)\n",
+		 mdname(mddev), mddev->in_sync);
 
 	bitmap_update_sb(mddev->bitmap);
 	list_for_each_entry(rdev, &mddev->disks, same_set) {
 		char b[BDEVNAME_SIZE];
-		dprintk(KERN_INFO "md: ");
+
 		if (rdev->sb_loaded != 1)
 			continue; /* no noise on spare devices */
-		if (test_bit(Faulty, &rdev->flags))
-			dprintk("(skipping faulty ");
 
-		dprintk("%s ", bdevname(rdev->bdev,b));
-		if (!test_bit(Faulty, &rdev->flags)) {
+		if (!test_bit(Faulty, &rdev->flags) &&
+		    rdev->saved_raid_disk == -1) {
 			md_super_write(mddev,rdev,
 				       rdev->sb_start, rdev->sb_size,
 				       rdev->sb_page);
-			dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
-				bdevname(rdev->bdev,b),
-				(unsigned long long)rdev->sb_start);
+			pr_debug("md: (write) %s's sb offset: %llu\n",
+				 bdevname(rdev->bdev, b),
+				 (unsigned long long)rdev->sb_start);
 			rdev->sb_events = mddev->events;
 			if (rdev->badblocks.size) {
 				md_super_write(mddev, rdev,
@@ -2472,8 +2463,12 @@
 				rdev->badblocks.size = 0;
 			}
 
-		} else
-			dprintk(")\n");
+		} else if (test_bit(Faulty, &rdev->flags))
+			pr_debug("md: %s (skipping faulty)\n",
+				 bdevname(rdev->bdev, b));
+		else
+			pr_debug("(skipping incremental s/r ");
+
 		if (mddev->level == LEVEL_MULTIPATH)
 			/* only need to write one superblock... */
 			break;
@@ -2527,12 +2522,12 @@
 
 struct rdev_sysfs_entry {
 	struct attribute attr;
-	ssize_t (*show)(mdk_rdev_t *, char *);
-	ssize_t (*store)(mdk_rdev_t *, const char *, size_t);
+	ssize_t (*show)(struct md_rdev *, char *);
+	ssize_t (*store)(struct md_rdev *, const char *, size_t);
 };
 
 static ssize_t
-state_show(mdk_rdev_t *rdev, char *page)
+state_show(struct md_rdev *rdev, char *page)
 {
 	char *sep = "";
 	size_t len = 0;
@@ -2551,7 +2546,8 @@
 		sep = ",";
 	}
 	if (test_bit(Blocked, &rdev->flags) ||
-	    rdev->badblocks.unacked_exist) {
+	    (rdev->badblocks.unacked_exist
+	     && !test_bit(Faulty, &rdev->flags))) {
 		len += sprintf(page+len, "%sblocked", sep);
 		sep = ",";
 	}
@@ -2568,7 +2564,7 @@
 }
 
 static ssize_t
-state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+state_store(struct md_rdev *rdev, const char *buf, size_t len)
 {
 	/* can write
 	 *  faulty  - simulates an error
@@ -2592,7 +2588,7 @@
 		if (rdev->raid_disk >= 0)
 			err = -EBUSY;
 		else {
-			mddev_t *mddev = rdev->mddev;
+			struct mddev *mddev = rdev->mddev;
 			kick_rdev_from_array(rdev);
 			if (mddev->pers)
 				md_update_sb(mddev, 1);
@@ -2641,13 +2637,13 @@
 __ATTR(state, S_IRUGO|S_IWUSR, state_show, state_store);
 
 static ssize_t
-errors_show(mdk_rdev_t *rdev, char *page)
+errors_show(struct md_rdev *rdev, char *page)
 {
 	return sprintf(page, "%d\n", atomic_read(&rdev->corrected_errors));
 }
 
 static ssize_t
-errors_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+errors_store(struct md_rdev *rdev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long n = simple_strtoul(buf, &e, 10);
@@ -2661,7 +2657,7 @@
 __ATTR(errors, S_IRUGO|S_IWUSR, errors_show, errors_store);
 
 static ssize_t
-slot_show(mdk_rdev_t *rdev, char *page)
+slot_show(struct md_rdev *rdev, char *page)
 {
 	if (rdev->raid_disk < 0)
 		return sprintf(page, "none\n");
@@ -2670,7 +2666,7 @@
 }
 
 static ssize_t
-slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+slot_store(struct md_rdev *rdev, const char *buf, size_t len)
 {
 	char *e;
 	int err;
@@ -2701,7 +2697,7 @@
 		set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
 		md_wakeup_thread(rdev->mddev->thread);
 	} else if (rdev->mddev->pers) {
-		mdk_rdev_t *rdev2;
+		struct md_rdev *rdev2;
 		/* Activating a spare .. or possibly reactivating
 		 * if we ever get bitmaps working here.
 		 */
@@ -2728,6 +2724,7 @@
 			rdev->saved_raid_disk = slot;
 		else
 			rdev->saved_raid_disk = -1;
+		clear_bit(In_sync, &rdev->flags);
 		err = rdev->mddev->pers->
 			hot_add_disk(rdev->mddev, rdev);
 		if (err) {
@@ -2757,13 +2754,13 @@
 __ATTR(slot, S_IRUGO|S_IWUSR, slot_show, slot_store);
 
 static ssize_t
-offset_show(mdk_rdev_t *rdev, char *page)
+offset_show(struct md_rdev *rdev, char *page)
 {
 	return sprintf(page, "%llu\n", (unsigned long long)rdev->data_offset);
 }
 
 static ssize_t
-offset_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+offset_store(struct md_rdev *rdev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long long offset = simple_strtoull(buf, &e, 10);
@@ -2783,7 +2780,7 @@
 __ATTR(offset, S_IRUGO|S_IWUSR, offset_show, offset_store);
 
 static ssize_t
-rdev_size_show(mdk_rdev_t *rdev, char *page)
+rdev_size_show(struct md_rdev *rdev, char *page)
 {
 	return sprintf(page, "%llu\n", (unsigned long long)rdev->sectors / 2);
 }
@@ -2818,9 +2815,9 @@
 }
 
 static ssize_t
-rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+rdev_size_store(struct md_rdev *rdev, const char *buf, size_t len)
 {
-	mddev_t *my_mddev = rdev->mddev;
+	struct mddev *my_mddev = rdev->mddev;
 	sector_t oldsectors = rdev->sectors;
 	sector_t sectors;
 
@@ -2846,13 +2843,13 @@
 		 * a deadlock.  We have already changed rdev->sectors, and if
 		 * we have to change it back, we will have the lock again.
 		 */
-		mddev_t *mddev;
+		struct mddev *mddev;
 		int overlap = 0;
 		struct list_head *tmp;
 
 		mddev_unlock(my_mddev);
 		for_each_mddev(mddev, tmp) {
-			mdk_rdev_t *rdev2;
+			struct md_rdev *rdev2;
 
 			mddev_lock(mddev);
 			list_for_each_entry(rdev2, &mddev->disks, same_set)
@@ -2889,7 +2886,7 @@
 __ATTR(size, S_IRUGO|S_IWUSR, rdev_size_show, rdev_size_store);
 
 
-static ssize_t recovery_start_show(mdk_rdev_t *rdev, char *page)
+static ssize_t recovery_start_show(struct md_rdev *rdev, char *page)
 {
 	unsigned long long recovery_start = rdev->recovery_offset;
 
@@ -2900,7 +2897,7 @@
 	return sprintf(page, "%llu\n", recovery_start);
 }
 
-static ssize_t recovery_start_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+static ssize_t recovery_start_store(struct md_rdev *rdev, const char *buf, size_t len)
 {
 	unsigned long long recovery_start;
 
@@ -2930,11 +2927,11 @@
 static ssize_t
 badblocks_store(struct badblocks *bb, const char *page, size_t len, int unack);
 
-static ssize_t bb_show(mdk_rdev_t *rdev, char *page)
+static ssize_t bb_show(struct md_rdev *rdev, char *page)
 {
 	return badblocks_show(&rdev->badblocks, page, 0);
 }
-static ssize_t bb_store(mdk_rdev_t *rdev, const char *page, size_t len)
+static ssize_t bb_store(struct md_rdev *rdev, const char *page, size_t len)
 {
 	int rv = badblocks_store(&rdev->badblocks, page, len, 0);
 	/* Maybe that ack was all we needed */
@@ -2946,11 +2943,11 @@
 __ATTR(bad_blocks, S_IRUGO|S_IWUSR, bb_show, bb_store);
 
 
-static ssize_t ubb_show(mdk_rdev_t *rdev, char *page)
+static ssize_t ubb_show(struct md_rdev *rdev, char *page)
 {
 	return badblocks_show(&rdev->badblocks, page, 1);
 }
-static ssize_t ubb_store(mdk_rdev_t *rdev, const char *page, size_t len)
+static ssize_t ubb_store(struct md_rdev *rdev, const char *page, size_t len)
 {
 	return badblocks_store(&rdev->badblocks, page, len, 1);
 }
@@ -2972,8 +2969,8 @@
 rdev_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
 {
 	struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr);
-	mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj);
-	mddev_t *mddev = rdev->mddev;
+	struct md_rdev *rdev = container_of(kobj, struct md_rdev, kobj);
+	struct mddev *mddev = rdev->mddev;
 	ssize_t rv;
 
 	if (!entry->show)
@@ -2995,9 +2992,9 @@
 	      const char *page, size_t length)
 {
 	struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr);
-	mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj);
+	struct md_rdev *rdev = container_of(kobj, struct md_rdev, kobj);
 	ssize_t rv;
-	mddev_t *mddev = rdev->mddev;
+	struct mddev *mddev = rdev->mddev;
 
 	if (!entry->store)
 		return -EIO;
@@ -3016,7 +3013,7 @@
 
 static void rdev_free(struct kobject *ko)
 {
-	mdk_rdev_t *rdev = container_of(ko, mdk_rdev_t, kobj);
+	struct md_rdev *rdev = container_of(ko, struct md_rdev, kobj);
 	kfree(rdev);
 }
 static const struct sysfs_ops rdev_sysfs_ops = {
@@ -3029,7 +3026,7 @@
 	.default_attrs	= rdev_default_attrs,
 };
 
-int md_rdev_init(mdk_rdev_t *rdev)
+int md_rdev_init(struct md_rdev *rdev)
 {
 	rdev->desc_nr = -1;
 	rdev->saved_raid_disk = -1;
@@ -3072,11 +3069,11 @@
  *
  * a faulty rdev _never_ has rdev->sb set.
  */
-static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_minor)
+static struct md_rdev *md_import_device(dev_t newdev, int super_format, int super_minor)
 {
 	char b[BDEVNAME_SIZE];
 	int err;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	sector_t size;
 
 	rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
@@ -3145,10 +3142,10 @@
  */
 
 
-static void analyze_sbs(mddev_t * mddev)
+static void analyze_sbs(struct mddev * mddev)
 {
 	int i;
-	mdk_rdev_t *rdev, *freshest, *tmp;
+	struct md_rdev *rdev, *freshest, *tmp;
 	char b[BDEVNAME_SIZE];
 
 	freshest = NULL;
@@ -3248,13 +3245,13 @@
 static void md_safemode_timeout(unsigned long data);
 
 static ssize_t
-safe_delay_show(mddev_t *mddev, char *page)
+safe_delay_show(struct mddev *mddev, char *page)
 {
 	int msec = (mddev->safemode_delay*1000)/HZ;
 	return sprintf(page, "%d.%03d\n", msec/1000, msec%1000);
 }
 static ssize_t
-safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len)
+safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len)
 {
 	unsigned long msec;
 
@@ -3276,9 +3273,9 @@
 __ATTR(safe_mode_delay, S_IRUGO|S_IWUSR,safe_delay_show, safe_delay_store);
 
 static ssize_t
-level_show(mddev_t *mddev, char *page)
+level_show(struct mddev *mddev, char *page)
 {
-	struct mdk_personality *p = mddev->pers;
+	struct md_personality *p = mddev->pers;
 	if (p)
 		return sprintf(page, "%s\n", p->name);
 	else if (mddev->clevel[0])
@@ -3290,14 +3287,14 @@
 }
 
 static ssize_t
-level_store(mddev_t *mddev, const char *buf, size_t len)
+level_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char clevel[16];
 	ssize_t rv = len;
-	struct mdk_personality *pers;
+	struct md_personality *pers;
 	long level;
 	void *priv;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	if (mddev->pers == NULL) {
 		if (len == 0)
@@ -3471,7 +3468,7 @@
 
 
 static ssize_t
-layout_show(mddev_t *mddev, char *page)
+layout_show(struct mddev *mddev, char *page)
 {
 	/* just a number, not meaningful for all levels */
 	if (mddev->reshape_position != MaxSector &&
@@ -3482,7 +3479,7 @@
 }
 
 static ssize_t
-layout_store(mddev_t *mddev, const char *buf, size_t len)
+layout_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long n = simple_strtoul(buf, &e, 10);
@@ -3512,7 +3509,7 @@
 
 
 static ssize_t
-raid_disks_show(mddev_t *mddev, char *page)
+raid_disks_show(struct mddev *mddev, char *page)
 {
 	if (mddev->raid_disks == 0)
 		return 0;
@@ -3523,10 +3520,10 @@
 	return sprintf(page, "%d\n", mddev->raid_disks);
 }
 
-static int update_raid_disks(mddev_t *mddev, int raid_disks);
+static int update_raid_disks(struct mddev *mddev, int raid_disks);
 
 static ssize_t
-raid_disks_store(mddev_t *mddev, const char *buf, size_t len)
+raid_disks_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *e;
 	int rv = 0;
@@ -3549,7 +3546,7 @@
 __ATTR(raid_disks, S_IRUGO|S_IWUSR, raid_disks_show, raid_disks_store);
 
 static ssize_t
-chunk_size_show(mddev_t *mddev, char *page)
+chunk_size_show(struct mddev *mddev, char *page)
 {
 	if (mddev->reshape_position != MaxSector &&
 	    mddev->chunk_sectors != mddev->new_chunk_sectors)
@@ -3560,7 +3557,7 @@
 }
 
 static ssize_t
-chunk_size_store(mddev_t *mddev, const char *buf, size_t len)
+chunk_size_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long n = simple_strtoul(buf, &e, 10);
@@ -3589,7 +3586,7 @@
 __ATTR(chunk_size, S_IRUGO|S_IWUSR, chunk_size_show, chunk_size_store);
 
 static ssize_t
-resync_start_show(mddev_t *mddev, char *page)
+resync_start_show(struct mddev *mddev, char *page)
 {
 	if (mddev->recovery_cp == MaxSector)
 		return sprintf(page, "none\n");
@@ -3597,7 +3594,7 @@
 }
 
 static ssize_t
-resync_start_store(mddev_t *mddev, const char *buf, size_t len)
+resync_start_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long long n = simple_strtoull(buf, &e, 10);
@@ -3667,7 +3664,7 @@
 }
 
 static ssize_t
-array_state_show(mddev_t *mddev, char *page)
+array_state_show(struct mddev *mddev, char *page)
 {
 	enum array_state st = inactive;
 
@@ -3700,13 +3697,13 @@
 	return sprintf(page, "%s\n", array_states[st]);
 }
 
-static int do_md_stop(mddev_t * mddev, int ro, int is_open);
-static int md_set_readonly(mddev_t * mddev, int is_open);
-static int do_md_run(mddev_t * mddev);
-static int restart_array(mddev_t *mddev);
+static int do_md_stop(struct mddev * mddev, int ro, int is_open);
+static int md_set_readonly(struct mddev * mddev, int is_open);
+static int do_md_run(struct mddev * mddev);
+static int restart_array(struct mddev *mddev);
 
 static ssize_t
-array_state_store(mddev_t *mddev, const char *buf, size_t len)
+array_state_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	int err = -EINVAL;
 	enum array_state st = match_word(buf, array_states);
@@ -3792,6 +3789,8 @@
 	if (err)
 		return err;
 	else {
+		if (mddev->hold_active == UNTIL_IOCTL)
+			mddev->hold_active = 0;
 		sysfs_notify_dirent_safe(mddev->sysfs_state);
 		return len;
 	}
@@ -3800,13 +3799,13 @@
 __ATTR(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store);
 
 static ssize_t
-max_corrected_read_errors_show(mddev_t *mddev, char *page) {
+max_corrected_read_errors_show(struct mddev *mddev, char *page) {
 	return sprintf(page, "%d\n",
 		       atomic_read(&mddev->max_corr_read_errors));
 }
 
 static ssize_t
-max_corrected_read_errors_store(mddev_t *mddev, const char *buf, size_t len)
+max_corrected_read_errors_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long n = simple_strtoul(buf, &e, 10);
@@ -3823,13 +3822,13 @@
 	max_corrected_read_errors_store);
 
 static ssize_t
-null_show(mddev_t *mddev, char *page)
+null_show(struct mddev *mddev, char *page)
 {
 	return -EINVAL;
 }
 
 static ssize_t
-new_dev_store(mddev_t *mddev, const char *buf, size_t len)
+new_dev_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	/* buf must be %d:%d\n? giving major and minor numbers */
 	/* The new device is added to the array.
@@ -3842,7 +3841,7 @@
 	int major = simple_strtoul(buf, &e, 10);
 	int minor;
 	dev_t dev;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int err;
 
 	if (!*buf || *e != ':' || !e[1] || e[1] == '\n')
@@ -3860,8 +3859,9 @@
 		rdev = md_import_device(dev, mddev->major_version,
 					mddev->minor_version);
 		if (!IS_ERR(rdev) && !list_empty(&mddev->disks)) {
-			mdk_rdev_t *rdev0 = list_entry(mddev->disks.next,
-						       mdk_rdev_t, same_set);
+			struct md_rdev *rdev0
+				= list_entry(mddev->disks.next,
+					     struct md_rdev, same_set);
 			err = super_types[mddev->major_version]
 				.load_super(rdev, rdev0, mddev->minor_version);
 			if (err < 0)
@@ -3885,7 +3885,7 @@
 __ATTR(new_dev, S_IWUSR, null_show, new_dev_store);
 
 static ssize_t
-bitmap_store(mddev_t *mddev, const char *buf, size_t len)
+bitmap_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *end;
 	unsigned long chunk, end_chunk;
@@ -3914,16 +3914,16 @@
 __ATTR(bitmap_set_bits, S_IWUSR, null_show, bitmap_store);
 
 static ssize_t
-size_show(mddev_t *mddev, char *page)
+size_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%llu\n",
 		(unsigned long long)mddev->dev_sectors / 2);
 }
 
-static int update_size(mddev_t *mddev, sector_t num_sectors);
+static int update_size(struct mddev *mddev, sector_t num_sectors);
 
 static ssize_t
-size_store(mddev_t *mddev, const char *buf, size_t len)
+size_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	/* If array is inactive, we can reduce the component size, but
 	 * not increase it (except from 0).
@@ -3958,7 +3958,7 @@
  * or N.M for internally known formats
  */
 static ssize_t
-metadata_show(mddev_t *mddev, char *page)
+metadata_show(struct mddev *mddev, char *page)
 {
 	if (mddev->persistent)
 		return sprintf(page, "%d.%d\n",
@@ -3970,7 +3970,7 @@
 }
 
 static ssize_t
-metadata_store(mddev_t *mddev, const char *buf, size_t len)
+metadata_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	int major, minor;
 	char *e;
@@ -4024,7 +4024,7 @@
 __ATTR(metadata_version, S_IRUGO|S_IWUSR, metadata_show, metadata_store);
 
 static ssize_t
-action_show(mddev_t *mddev, char *page)
+action_show(struct mddev *mddev, char *page)
 {
 	char *type = "idle";
 	if (test_bit(MD_RECOVERY_FROZEN, &mddev->recovery))
@@ -4046,10 +4046,10 @@
 	return sprintf(page, "%s\n", type);
 }
 
-static void reap_sync_thread(mddev_t *mddev);
+static void reap_sync_thread(struct mddev *mddev);
 
 static ssize_t
-action_store(mddev_t *mddev, const char *page, size_t len)
+action_store(struct mddev *mddev, const char *page, size_t len)
 {
 	if (!mddev->pers || !mddev->pers->sync_request)
 		return -EINVAL;
@@ -4095,7 +4095,7 @@
 }
 
 static ssize_t
-mismatch_cnt_show(mddev_t *mddev, char *page)
+mismatch_cnt_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%llu\n",
 		       (unsigned long long) mddev->resync_mismatches);
@@ -4108,14 +4108,14 @@
 static struct md_sysfs_entry md_mismatches = __ATTR_RO(mismatch_cnt);
 
 static ssize_t
-sync_min_show(mddev_t *mddev, char *page)
+sync_min_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%d (%s)\n", speed_min(mddev),
 		       mddev->sync_speed_min ? "local": "system");
 }
 
 static ssize_t
-sync_min_store(mddev_t *mddev, const char *buf, size_t len)
+sync_min_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	int min;
 	char *e;
@@ -4134,14 +4134,14 @@
 __ATTR(sync_speed_min, S_IRUGO|S_IWUSR, sync_min_show, sync_min_store);
 
 static ssize_t
-sync_max_show(mddev_t *mddev, char *page)
+sync_max_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%d (%s)\n", speed_max(mddev),
 		       mddev->sync_speed_max ? "local": "system");
 }
 
 static ssize_t
-sync_max_store(mddev_t *mddev, const char *buf, size_t len)
+sync_max_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	int max;
 	char *e;
@@ -4160,20 +4160,20 @@
 __ATTR(sync_speed_max, S_IRUGO|S_IWUSR, sync_max_show, sync_max_store);
 
 static ssize_t
-degraded_show(mddev_t *mddev, char *page)
+degraded_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%d\n", mddev->degraded);
 }
 static struct md_sysfs_entry md_degraded = __ATTR_RO(degraded);
 
 static ssize_t
-sync_force_parallel_show(mddev_t *mddev, char *page)
+sync_force_parallel_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%d\n", mddev->parallel_resync);
 }
 
 static ssize_t
-sync_force_parallel_store(mddev_t *mddev, const char *buf, size_t len)
+sync_force_parallel_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	long n;
 
@@ -4197,7 +4197,7 @@
        sync_force_parallel_show, sync_force_parallel_store);
 
 static ssize_t
-sync_speed_show(mddev_t *mddev, char *page)
+sync_speed_show(struct mddev *mddev, char *page)
 {
 	unsigned long resync, dt, db;
 	if (mddev->curr_resync == 0)
@@ -4212,7 +4212,7 @@
 static struct md_sysfs_entry md_sync_speed = __ATTR_RO(sync_speed);
 
 static ssize_t
-sync_completed_show(mddev_t *mddev, char *page)
+sync_completed_show(struct mddev *mddev, char *page)
 {
 	unsigned long long max_sectors, resync;
 
@@ -4231,13 +4231,13 @@
 static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed);
 
 static ssize_t
-min_sync_show(mddev_t *mddev, char *page)
+min_sync_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%llu\n",
 		       (unsigned long long)mddev->resync_min);
 }
 static ssize_t
-min_sync_store(mddev_t *mddev, const char *buf, size_t len)
+min_sync_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	unsigned long long min;
 	if (strict_strtoull(buf, 10, &min))
@@ -4262,7 +4262,7 @@
 __ATTR(sync_min, S_IRUGO|S_IWUSR, min_sync_show, min_sync_store);
 
 static ssize_t
-max_sync_show(mddev_t *mddev, char *page)
+max_sync_show(struct mddev *mddev, char *page)
 {
 	if (mddev->resync_max == MaxSector)
 		return sprintf(page, "max\n");
@@ -4271,7 +4271,7 @@
 			       (unsigned long long)mddev->resync_max);
 }
 static ssize_t
-max_sync_store(mddev_t *mddev, const char *buf, size_t len)
+max_sync_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	if (strncmp(buf, "max", 3) == 0)
 		mddev->resync_max = MaxSector;
@@ -4302,13 +4302,13 @@
 __ATTR(sync_max, S_IRUGO|S_IWUSR, max_sync_show, max_sync_store);
 
 static ssize_t
-suspend_lo_show(mddev_t *mddev, char *page)
+suspend_lo_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_lo);
 }
 
 static ssize_t
-suspend_lo_store(mddev_t *mddev, const char *buf, size_t len)
+suspend_lo_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long long new = simple_strtoull(buf, &e, 10);
@@ -4336,13 +4336,13 @@
 
 
 static ssize_t
-suspend_hi_show(mddev_t *mddev, char *page)
+suspend_hi_show(struct mddev *mddev, char *page)
 {
 	return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_hi);
 }
 
 static ssize_t
-suspend_hi_store(mddev_t *mddev, const char *buf, size_t len)
+suspend_hi_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long long new = simple_strtoull(buf, &e, 10);
@@ -4369,7 +4369,7 @@
 __ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store);
 
 static ssize_t
-reshape_position_show(mddev_t *mddev, char *page)
+reshape_position_show(struct mddev *mddev, char *page)
 {
 	if (mddev->reshape_position != MaxSector)
 		return sprintf(page, "%llu\n",
@@ -4379,7 +4379,7 @@
 }
 
 static ssize_t
-reshape_position_store(mddev_t *mddev, const char *buf, size_t len)
+reshape_position_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long long new = simple_strtoull(buf, &e, 10);
@@ -4400,7 +4400,7 @@
        reshape_position_store);
 
 static ssize_t
-array_size_show(mddev_t *mddev, char *page)
+array_size_show(struct mddev *mddev, char *page)
 {
 	if (mddev->external_size)
 		return sprintf(page, "%llu\n",
@@ -4410,7 +4410,7 @@
 }
 
 static ssize_t
-array_size_store(mddev_t *mddev, const char *buf, size_t len)
+array_size_store(struct mddev *mddev, const char *buf, size_t len)
 {
 	sector_t sectors;
 
@@ -4485,16 +4485,25 @@
 md_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
 {
 	struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr);
-	mddev_t *mddev = container_of(kobj, struct mddev_s, kobj);
+	struct mddev *mddev = container_of(kobj, struct mddev, kobj);
 	ssize_t rv;
 
 	if (!entry->show)
 		return -EIO;
+	spin_lock(&all_mddevs_lock);
+	if (list_empty(&mddev->all_mddevs)) {
+		spin_unlock(&all_mddevs_lock);
+		return -EBUSY;
+	}
+	mddev_get(mddev);
+	spin_unlock(&all_mddevs_lock);
+
 	rv = mddev_lock(mddev);
 	if (!rv) {
 		rv = entry->show(mddev, page);
 		mddev_unlock(mddev);
 	}
+	mddev_put(mddev);
 	return rv;
 }
 
@@ -4503,26 +4512,32 @@
 	      const char *page, size_t length)
 {
 	struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr);
-	mddev_t *mddev = container_of(kobj, struct mddev_s, kobj);
+	struct mddev *mddev = container_of(kobj, struct mddev, kobj);
 	ssize_t rv;
 
 	if (!entry->store)
 		return -EIO;
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
+	spin_lock(&all_mddevs_lock);
+	if (list_empty(&mddev->all_mddevs)) {
+		spin_unlock(&all_mddevs_lock);
+		return -EBUSY;
+	}
+	mddev_get(mddev);
+	spin_unlock(&all_mddevs_lock);
 	rv = mddev_lock(mddev);
-	if (mddev->hold_active == UNTIL_IOCTL)
-		mddev->hold_active = 0;
 	if (!rv) {
 		rv = entry->store(mddev, page, length);
 		mddev_unlock(mddev);
 	}
+	mddev_put(mddev);
 	return rv;
 }
 
 static void md_free(struct kobject *ko)
 {
-	mddev_t *mddev = container_of(ko, mddev_t, kobj);
+	struct mddev *mddev = container_of(ko, struct mddev, kobj);
 
 	if (mddev->sysfs_state)
 		sysfs_put(mddev->sysfs_state);
@@ -4551,7 +4566,7 @@
 
 static void mddev_delayed_delete(struct work_struct *ws)
 {
-	mddev_t *mddev = container_of(ws, mddev_t, del_work);
+	struct mddev *mddev = container_of(ws, struct mddev, del_work);
 
 	sysfs_remove_group(&mddev->kobj, &md_bitmap_group);
 	kobject_del(&mddev->kobj);
@@ -4561,7 +4576,7 @@
 static int md_alloc(dev_t dev, char *name)
 {
 	static DEFINE_MUTEX(disks_mutex);
-	mddev_t *mddev = mddev_find(dev);
+	struct mddev *mddev = mddev_find(dev);
 	struct gendisk *disk;
 	int partitioned;
 	int shift;
@@ -4588,7 +4603,7 @@
 	if (name) {
 		/* Need to ensure that 'name' is not a duplicate.
 		 */
-		mddev_t *mddev2;
+		struct mddev *mddev2;
 		spin_lock(&all_mddevs_lock);
 
 		list_for_each_entry(mddev2, &all_mddevs, all_mddevs)
@@ -4689,7 +4704,7 @@
 
 static void md_safemode_timeout(unsigned long data)
 {
-	mddev_t *mddev = (mddev_t *) data;
+	struct mddev *mddev = (struct mddev *) data;
 
 	if (!atomic_read(&mddev->writes_pending)) {
 		mddev->safemode = 1;
@@ -4701,11 +4716,11 @@
 
 static int start_dirty_degraded;
 
-int md_run(mddev_t *mddev)
+int md_run(struct mddev *mddev)
 {
 	int err;
-	mdk_rdev_t *rdev;
-	struct mdk_personality *pers;
+	struct md_rdev *rdev;
+	struct md_personality *pers;
 
 	if (list_empty(&mddev->disks))
 		/* cannot run an array with no devices.. */
@@ -4769,7 +4784,7 @@
 
 	if (mddev->bio_set == NULL)
 		mddev->bio_set = bioset_create(BIO_POOL_SIZE,
-					       sizeof(mddev_t *));
+					       sizeof(struct mddev *));
 
 	spin_lock(&pers_lock);
 	pers = find_pers(mddev->level, mddev->clevel);
@@ -4804,7 +4819,7 @@
 		 * configuration.
 		 */
 		char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
-		mdk_rdev_t *rdev2;
+		struct md_rdev *rdev2;
 		int warned = 0;
 
 		list_for_each_entry(rdev, &mddev->disks, same_set)
@@ -4903,7 +4918,7 @@
 }
 EXPORT_SYMBOL_GPL(md_run);
 
-static int do_md_run(mddev_t *mddev)
+static int do_md_run(struct mddev *mddev)
 {
 	int err;
 
@@ -4927,7 +4942,7 @@
 	return err;
 }
 
-static int restart_array(mddev_t *mddev)
+static int restart_array(struct mddev *mddev)
 {
 	struct gendisk *disk = mddev->gendisk;
 
@@ -4977,7 +4992,7 @@
 	spin_unlock(&inode->i_lock);
 }
 
-static void md_clean(mddev_t *mddev)
+static void md_clean(struct mddev *mddev)
 {
 	mddev->array_sectors = 0;
 	mddev->external_size = 0;
@@ -5020,7 +5035,7 @@
 	mddev->bitmap_info.max_write_behind = 0;
 }
 
-static void __md_stop_writes(mddev_t *mddev)
+static void __md_stop_writes(struct mddev *mddev)
 {
 	if (mddev->sync_thread) {
 		set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
@@ -5040,7 +5055,7 @@
 	}
 }
 
-void md_stop_writes(mddev_t *mddev)
+void md_stop_writes(struct mddev *mddev)
 {
 	mddev_lock(mddev);
 	__md_stop_writes(mddev);
@@ -5048,7 +5063,7 @@
 }
 EXPORT_SYMBOL_GPL(md_stop_writes);
 
-void md_stop(mddev_t *mddev)
+void md_stop(struct mddev *mddev)
 {
 	mddev->ready = 0;
 	mddev->pers->stop(mddev);
@@ -5060,7 +5075,7 @@
 }
 EXPORT_SYMBOL_GPL(md_stop);
 
-static int md_set_readonly(mddev_t *mddev, int is_open)
+static int md_set_readonly(struct mddev *mddev, int is_open)
 {
 	int err = 0;
 	mutex_lock(&mddev->open_mutex);
@@ -5090,10 +5105,10 @@
  *   0 - completely stop and dis-assemble array
  *   2 - stop but do not disassemble array
  */
-static int do_md_stop(mddev_t * mddev, int mode, int is_open)
+static int do_md_stop(struct mddev * mddev, int mode, int is_open)
 {
 	struct gendisk *disk = mddev->gendisk;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	mutex_lock(&mddev->open_mutex);
 	if (atomic_read(&mddev->openers) > is_open ||
@@ -5156,9 +5171,9 @@
 }
 
 #ifndef MODULE
-static void autorun_array(mddev_t *mddev)
+static void autorun_array(struct mddev *mddev)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int err;
 
 	if (list_empty(&mddev->disks))
@@ -5193,8 +5208,8 @@
  */
 static void autorun_devices(int part)
 {
-	mdk_rdev_t *rdev0, *rdev, *tmp;
-	mddev_t *mddev;
+	struct md_rdev *rdev0, *rdev, *tmp;
+	struct mddev *mddev;
 	char b[BDEVNAME_SIZE];
 
 	printk(KERN_INFO "md: autorun ...\n");
@@ -5203,7 +5218,7 @@
 		dev_t dev;
 		LIST_HEAD(candidates);
 		rdev0 = list_entry(pending_raid_disks.next,
-					 mdk_rdev_t, same_set);
+					 struct md_rdev, same_set);
 
 		printk(KERN_INFO "md: considering %s ...\n",
 			bdevname(rdev0->bdev,b));
@@ -5289,11 +5304,11 @@
 	return 0;
 }
 
-static int get_array_info(mddev_t * mddev, void __user * arg)
+static int get_array_info(struct mddev * mddev, void __user * arg)
 {
 	mdu_array_info_t info;
 	int nr,working,insync,failed,spare;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	nr=working=insync=failed=spare=0;
 	list_for_each_entry(rdev, &mddev->disks, same_set) {
@@ -5342,7 +5357,7 @@
 	return 0;
 }
 
-static int get_bitmap_file(mddev_t * mddev, void __user * arg)
+static int get_bitmap_file(struct mddev * mddev, void __user * arg)
 {
 	mdu_bitmap_file_t *file = NULL; /* too big for stack allocation */
 	char *ptr, *buf = NULL;
@@ -5382,10 +5397,10 @@
 	return err;
 }
 
-static int get_disk_info(mddev_t * mddev, void __user * arg)
+static int get_disk_info(struct mddev * mddev, void __user * arg)
 {
 	mdu_disk_info_t info;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	if (copy_from_user(&info, arg, sizeof(info)))
 		return -EFAULT;
@@ -5416,10 +5431,10 @@
 	return 0;
 }
 
-static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
+static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info)
 {
 	char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	dev_t dev = MKDEV(info->major,info->minor);
 
 	if (info->major != MAJOR(dev) || info->minor != MINOR(dev))
@@ -5436,8 +5451,9 @@
 			return PTR_ERR(rdev);
 		}
 		if (!list_empty(&mddev->disks)) {
-			mdk_rdev_t *rdev0 = list_entry(mddev->disks.next,
-							mdk_rdev_t, same_set);
+			struct md_rdev *rdev0
+				= list_entry(mddev->disks.next,
+					     struct md_rdev, same_set);
 			err = super_types[mddev->major_version]
 				.load_super(rdev, rdev0, mddev->minor_version);
 			if (err < 0) {
@@ -5587,10 +5603,10 @@
 	return 0;
 }
 
-static int hot_remove_disk(mddev_t * mddev, dev_t dev)
+static int hot_remove_disk(struct mddev * mddev, dev_t dev)
 {
 	char b[BDEVNAME_SIZE];
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	rdev = find_rdev(mddev, dev);
 	if (!rdev)
@@ -5610,11 +5626,11 @@
 	return -EBUSY;
 }
 
-static int hot_add_disk(mddev_t * mddev, dev_t dev)
+static int hot_add_disk(struct mddev * mddev, dev_t dev)
 {
 	char b[BDEVNAME_SIZE];
 	int err;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	if (!mddev->pers)
 		return -ENODEV;
@@ -5684,7 +5700,7 @@
 	return err;
 }
 
-static int set_bitmap_file(mddev_t *mddev, int fd)
+static int set_bitmap_file(struct mddev *mddev, int fd)
 {
 	int err;
 
@@ -5757,7 +5773,7 @@
  *  The minor and patch _version numbers are also kept incase the
  *  super_block handler wishes to interpret them.
  */
-static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
+static int set_array_info(struct mddev * mddev, mdu_array_info_t *info)
 {
 
 	if (info->raid_disks == 0) {
@@ -5827,7 +5843,7 @@
 	return 0;
 }
 
-void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors)
+void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors)
 {
 	WARN(!mddev_is_locked(mddev), "%s: unlocked mddev!\n", __func__);
 
@@ -5838,9 +5854,9 @@
 }
 EXPORT_SYMBOL(md_set_array_sectors);
 
-static int update_size(mddev_t *mddev, sector_t num_sectors)
+static int update_size(struct mddev *mddev, sector_t num_sectors)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int rv;
 	int fit = (num_sectors == 0);
 
@@ -5876,7 +5892,7 @@
 	return rv;
 }
 
-static int update_raid_disks(mddev_t *mddev, int raid_disks)
+static int update_raid_disks(struct mddev *mddev, int raid_disks)
 {
 	int rv;
 	/* change the number of raid disks */
@@ -5904,7 +5920,7 @@
  * Any differences that cannot be handled will cause an error.
  * Normally, only one change can be managed at a time.
  */
-static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
+static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
 {
 	int rv = 0;
 	int cnt = 0;
@@ -5997,9 +6013,9 @@
 	return rv;
 }
 
-static int set_disk_faulty(mddev_t *mddev, dev_t dev)
+static int set_disk_faulty(struct mddev *mddev, dev_t dev)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	if (mddev->pers == NULL)
 		return -ENODEV;
@@ -6022,7 +6038,7 @@
  */
 static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-	mddev_t *mddev = bdev->bd_disk->private_data;
+	struct mddev *mddev = bdev->bd_disk->private_data;
 
 	geo->heads = 2;
 	geo->sectors = 4;
@@ -6035,7 +6051,7 @@
 {
 	int err = 0;
 	void __user *argp = (void __user *)arg;
-	mddev_t *mddev = NULL;
+	struct mddev *mddev = NULL;
 	int ro;
 
 	if (!capable(CAP_SYS_ADMIN))
@@ -6298,7 +6314,7 @@
 	 * Succeed if we can lock the mddev, which confirms that
 	 * it isn't being stopped right now.
 	 */
-	mddev_t *mddev = mddev_find(bdev->bd_dev);
+	struct mddev *mddev = mddev_find(bdev->bd_dev);
 	int err;
 
 	if (mddev->gendisk != bdev->bd_disk) {
@@ -6327,7 +6343,7 @@
 
 static int md_release(struct gendisk *disk, fmode_t mode)
 {
- 	mddev_t *mddev = disk->private_data;
+ 	struct mddev *mddev = disk->private_data;
 
 	BUG_ON(!mddev);
 	atomic_dec(&mddev->openers);
@@ -6338,14 +6354,14 @@
 
 static int md_media_changed(struct gendisk *disk)
 {
-	mddev_t *mddev = disk->private_data;
+	struct mddev *mddev = disk->private_data;
 
 	return mddev->changed;
 }
 
 static int md_revalidate(struct gendisk *disk)
 {
-	mddev_t *mddev = disk->private_data;
+	struct mddev *mddev = disk->private_data;
 
 	mddev->changed = 0;
 	return 0;
@@ -6366,7 +6382,7 @@
 
 static int md_thread(void * arg)
 {
-	mdk_thread_t *thread = arg;
+	struct md_thread *thread = arg;
 
 	/*
 	 * md_thread is a 'system-thread', it's priority should be very
@@ -6405,21 +6421,21 @@
 	return 0;
 }
 
-void md_wakeup_thread(mdk_thread_t *thread)
+void md_wakeup_thread(struct md_thread *thread)
 {
 	if (thread) {
-		dprintk("md: waking up MD thread %s.\n", thread->tsk->comm);
+		pr_debug("md: waking up MD thread %s.\n", thread->tsk->comm);
 		set_bit(THREAD_WAKEUP, &thread->flags);
 		wake_up(&thread->wqueue);
 	}
 }
 
-mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
+struct md_thread *md_register_thread(void (*run) (struct mddev *), struct mddev *mddev,
 				 const char *name)
 {
-	mdk_thread_t *thread;
+	struct md_thread *thread;
 
-	thread = kzalloc(sizeof(mdk_thread_t), GFP_KERNEL);
+	thread = kzalloc(sizeof(struct md_thread), GFP_KERNEL);
 	if (!thread)
 		return NULL;
 
@@ -6439,12 +6455,12 @@
 	return thread;
 }
 
-void md_unregister_thread(mdk_thread_t **threadp)
+void md_unregister_thread(struct md_thread **threadp)
 {
-	mdk_thread_t *thread = *threadp;
+	struct md_thread *thread = *threadp;
 	if (!thread)
 		return;
-	dprintk("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk));
+	pr_debug("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk));
 	/* Locking ensures that mddev_unlock does not wake_up a
 	 * non-existent thread
 	 */
@@ -6456,7 +6472,7 @@
 	kfree(thread);
 }
 
-void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
+void md_error(struct mddev *mddev, struct md_rdev *rdev)
 {
 	if (!mddev) {
 		MD_BUG();
@@ -6485,7 +6501,7 @@
 static void status_unused(struct seq_file *seq)
 {
 	int i = 0;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	seq_printf(seq, "unused devices: ");
 
@@ -6502,7 +6518,7 @@
 }
 
 
-static void status_resync(struct seq_file *seq, mddev_t * mddev)
+static void status_resync(struct seq_file *seq, struct mddev * mddev)
 {
 	sector_t max_sectors, resync, res;
 	unsigned long dt, db;
@@ -6593,7 +6609,7 @@
 {
 	struct list_head *tmp;
 	loff_t l = *pos;
-	mddev_t *mddev;
+	struct mddev *mddev;
 
 	if (l >= 0x10000)
 		return NULL;
@@ -6604,7 +6620,7 @@
 	spin_lock(&all_mddevs_lock);
 	list_for_each(tmp,&all_mddevs)
 		if (!l--) {
-			mddev = list_entry(tmp, mddev_t, all_mddevs);
+			mddev = list_entry(tmp, struct mddev, all_mddevs);
 			mddev_get(mddev);
 			spin_unlock(&all_mddevs_lock);
 			return mddev;
@@ -6618,7 +6634,7 @@
 static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	struct list_head *tmp;
-	mddev_t *next_mddev, *mddev = v;
+	struct mddev *next_mddev, *mddev = v;
 	
 	++*pos;
 	if (v == (void*)2)
@@ -6630,7 +6646,7 @@
 	else
 		tmp = mddev->all_mddevs.next;
 	if (tmp != &all_mddevs)
-		next_mddev = mddev_get(list_entry(tmp,mddev_t,all_mddevs));
+		next_mddev = mddev_get(list_entry(tmp,struct mddev,all_mddevs));
 	else {
 		next_mddev = (void*)2;
 		*pos = 0x10000;
@@ -6645,7 +6661,7 @@
 
 static void md_seq_stop(struct seq_file *seq, void *v)
 {
-	mddev_t *mddev = v;
+	struct mddev *mddev = v;
 
 	if (mddev && v != (void*)1 && v != (void*)2)
 		mddev_put(mddev);
@@ -6653,13 +6669,13 @@
 
 static int md_seq_show(struct seq_file *seq, void *v)
 {
-	mddev_t *mddev = v;
+	struct mddev *mddev = v;
 	sector_t sectors;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	struct bitmap *bitmap;
 
 	if (v == (void*)1) {
-		struct mdk_personality *pers;
+		struct md_personality *pers;
 		seq_printf(seq, "Personalities : ");
 		spin_lock(&pers_lock);
 		list_for_each_entry(pers, &pers_list, list)
@@ -6815,7 +6831,7 @@
 	.poll		= mdstat_poll,
 };
 
-int register_md_personality(struct mdk_personality *p)
+int register_md_personality(struct md_personality *p)
 {
 	spin_lock(&pers_lock);
 	list_add_tail(&p->list, &pers_list);
@@ -6824,7 +6840,7 @@
 	return 0;
 }
 
-int unregister_md_personality(struct mdk_personality *p)
+int unregister_md_personality(struct md_personality *p)
 {
 	printk(KERN_INFO "md: %s personality unregistered\n", p->name);
 	spin_lock(&pers_lock);
@@ -6833,9 +6849,9 @@
 	return 0;
 }
 
-static int is_mddev_idle(mddev_t *mddev, int init)
+static int is_mddev_idle(struct mddev *mddev, int init)
 {
-	mdk_rdev_t * rdev;
+	struct md_rdev * rdev;
 	int idle;
 	int curr_events;
 
@@ -6877,7 +6893,7 @@
 	return idle;
 }
 
-void md_done_sync(mddev_t *mddev, int blocks, int ok)
+void md_done_sync(struct mddev *mddev, int blocks, int ok)
 {
 	/* another "blocks" (512byte) blocks have been synced */
 	atomic_sub(blocks, &mddev->recovery_active);
@@ -6895,7 +6911,7 @@
  * in superblock) before writing, schedule a superblock update
  * and wait for it to complete.
  */
-void md_write_start(mddev_t *mddev, struct bio *bi)
+void md_write_start(struct mddev *mddev, struct bio *bi)
 {
 	int did_change = 0;
 	if (bio_data_dir(bi) != WRITE)
@@ -6930,7 +6946,7 @@
 		   !test_bit(MD_CHANGE_PENDING, &mddev->flags));
 }
 
-void md_write_end(mddev_t *mddev)
+void md_write_end(struct mddev *mddev)
 {
 	if (atomic_dec_and_test(&mddev->writes_pending)) {
 		if (mddev->safemode == 2)
@@ -6949,7 +6965,7 @@
  * In the ->external case MD_CHANGE_CLEAN can not be cleared until mddev->lock
  * is dropped, so return -EAGAIN after notifying userspace.
  */
-int md_allow_write(mddev_t *mddev)
+int md_allow_write(struct mddev *mddev)
 {
 	if (!mddev->pers)
 		return 0;
@@ -6981,9 +6997,9 @@
 
 #define SYNC_MARKS	10
 #define	SYNC_MARK_STEP	(3*HZ)
-void md_do_sync(mddev_t *mddev)
+void md_do_sync(struct mddev *mddev)
 {
-	mddev_t *mddev2;
+	struct mddev *mddev2;
 	unsigned int currspeed = 0,
 		 window;
 	sector_t max_sectors,j, io_sectors;
@@ -6993,7 +7009,7 @@
 	struct list_head *tmp;
 	sector_t last_check;
 	int skipped = 0;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	char *desc;
 
 	/* just incase thread restarts... */
@@ -7308,9 +7324,9 @@
 }
 EXPORT_SYMBOL_GPL(md_do_sync);
 
-static int remove_and_add_spares(mddev_t *mddev)
+static int remove_and_add_spares(struct mddev *mddev)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int spares = 0;
 
 	mddev->curr_resync_completed = 0;
@@ -7344,17 +7360,16 @@
 					spares++;
 					md_new_event(mddev);
 					set_bit(MD_CHANGE_DEVS, &mddev->flags);
-				} else
-					break;
+				}
 			}
 		}
 	}
 	return spares;
 }
 
-static void reap_sync_thread(mddev_t *mddev)
+static void reap_sync_thread(struct mddev *mddev)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	/* resync has finished, collect result */
 	md_unregister_thread(&mddev->sync_thread);
@@ -7369,15 +7384,19 @@
 	if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
 	    mddev->pers->finish_reshape)
 		mddev->pers->finish_reshape(mddev);
-	md_update_sb(mddev, 1);
 
-	/* if array is no-longer degraded, then any saved_raid_disk
-	 * information must be scrapped
+	/* If array is no-longer degraded, then any saved_raid_disk
+	 * information must be scrapped.  Also if any device is now
+	 * In_sync we must scrape the saved_raid_disk for that device
+	 * do the superblock for an incrementally recovered device
+	 * written out.
 	 */
-	if (!mddev->degraded)
-		list_for_each_entry(rdev, &mddev->disks, same_set)
+	list_for_each_entry(rdev, &mddev->disks, same_set)
+		if (!mddev->degraded ||
+		    test_bit(In_sync, &rdev->flags))
 			rdev->saved_raid_disk = -1;
 
+	md_update_sb(mddev, 1);
 	clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
 	clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
 	clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
@@ -7413,7 +7432,7 @@
  *  5/ If array is degraded, try to add spares devices
  *  6/ If array has spares or is not in-sync, start a resync thread.
  */
-void md_check_recovery(mddev_t *mddev)
+void md_check_recovery(struct mddev *mddev)
 {
 	if (mddev->suspended)
 		return;
@@ -7449,7 +7468,7 @@
 			/* Only thing we do on a ro array is remove
 			 * failed devices.
 			 */
-			mdk_rdev_t *rdev;
+			struct md_rdev *rdev;
 			list_for_each_entry(rdev, &mddev->disks, same_set)
 				if (rdev->raid_disk >= 0 &&
 				    !test_bit(Blocked, &rdev->flags) &&
@@ -7573,7 +7592,7 @@
 	}
 }
 
-void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
+void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev)
 {
 	sysfs_notify_dirent_safe(rdev->sysfs_state);
 	wait_event_timeout(rdev->blocked_wait,
@@ -7831,13 +7850,14 @@
 	return rv;
 }
 
-int rdev_set_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors,
+int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
 		       int acknowledged)
 {
 	int rv = md_set_badblocks(&rdev->badblocks,
 				  s + rdev->data_offset, sectors, acknowledged);
 	if (rv) {
 		/* Make sure they get written out promptly */
+		sysfs_notify_dirent_safe(rdev->sysfs_state);
 		set_bit(MD_CHANGE_CLEAN, &rdev->mddev->flags);
 		md_wakeup_thread(rdev->mddev->thread);
 	}
@@ -7940,7 +7960,7 @@
 	return rv;
 }
 
-int rdev_clear_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors)
+int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors)
 {
 	return md_clear_badblocks(&rdev->badblocks,
 				  s + rdev->data_offset,
@@ -8074,13 +8094,14 @@
 			    unsigned long code, void *x)
 {
 	struct list_head *tmp;
-	mddev_t *mddev;
+	struct mddev *mddev;
+	int need_delay = 0;
 
 	if ((code == SYS_DOWN) || (code == SYS_HALT) || (code == SYS_POWER_OFF)) {
 
 		printk(KERN_INFO "md: stopping all md devices.\n");
 
-		for_each_mddev(mddev, tmp)
+		for_each_mddev(mddev, tmp) {
 			if (mddev_trylock(mddev)) {
 				/* Force a switch to readonly even array
 				 * appears to still be in use.  Hence
@@ -8089,13 +8110,16 @@
 				md_set_readonly(mddev, 100);
 				mddev_unlock(mddev);
 			}
+			need_delay = 1;
+		}
 		/*
 		 * certain more exotic SCSI devices are known to be
 		 * volatile wrt too early system reboots. While the
 		 * right place to handle this issue is the given
 		 * driver, we do want to have a safe RAID driver ...
 		 */
-		mdelay(1000*1);
+		if (need_delay)
+			mdelay(1000*1);
 	}
 	return NOTIFY_DONE;
 }
@@ -8108,7 +8132,7 @@
 
 static void md_geninit(void)
 {
-	dprintk("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t));
+	pr_debug("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t));
 
 	proc_create("mdstat", S_IRUGO, NULL, &md_seq_fops);
 }
@@ -8183,7 +8207,7 @@
 
 static void autostart_arrays(int part)
 {
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	struct detected_devices_node *node_detected_dev;
 	dev_t dev;
 	int i_scanned, i_passed;
@@ -8223,7 +8247,7 @@
 
 static __exit void md_exit(void)
 {
-	mddev_t *mddev;
+	struct mddev *mddev;
 	struct list_head *tmp;
 
 	blk_unregister_region(MKDEV(MD_MAJOR,0), 1U << MINORBITS);
diff -druN linux-libre-3.1-gnu/drivers/md/md.h linux-libre-3.2-gnu/drivers/md/md.h
--- linux-libre-3.1-gnu/drivers/md/md.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/md.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
-   md_k.h : kernel internal structure of the Linux MD driver
+   md.h : kernel internal structure of the Linux MD driver
           Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman
 	  
    This program is free software; you can redistribute it and/or modify
@@ -26,9 +26,6 @@
 
 #define MaxSector (~(sector_t)0)
 
-typedef struct mddev_s mddev_t;
-typedef struct mdk_rdev_s mdk_rdev_t;
-
 /* Bad block numbers are stored sorted in a single page.
  * 64bits is used for each block or extent.
  * 54 bits are sector number, 9 bits are extent size,
@@ -39,12 +36,11 @@
 /*
  * MD's 'extended' device
  */
-struct mdk_rdev_s
-{
+struct md_rdev {
 	struct list_head same_set;	/* RAID devices within the same set */
 
 	sector_t sectors;		/* Device size (in 512bytes sectors) */
-	mddev_t *mddev;			/* RAID array if running */
+	struct mddev *mddev;		/* RAID array if running */
 	int last_events;		/* IO event timestamp */
 
 	/*
@@ -168,7 +164,7 @@
 
 extern int md_is_badblock(struct badblocks *bb, sector_t s, int sectors,
 			  sector_t *first_bad, int *bad_sectors);
-static inline int is_badblock(mdk_rdev_t *rdev, sector_t s, int sectors,
+static inline int is_badblock(struct md_rdev *rdev, sector_t s, int sectors,
 			      sector_t *first_bad, int *bad_sectors)
 {
 	if (unlikely(rdev->badblocks.count)) {
@@ -181,15 +177,14 @@
 	}
 	return 0;
 }
-extern int rdev_set_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors,
+extern int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
 			      int acknowledged);
-extern int rdev_clear_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors);
+extern int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors);
 extern void md_ack_all_badblocks(struct badblocks *bb);
 
-struct mddev_s
-{
+struct mddev {
 	void				*private;
-	struct mdk_personality		*pers;
+	struct md_personality		*pers;
 	dev_t				unit;
 	int				md_minor;
 	struct list_head 		disks;
@@ -256,8 +251,8 @@
 	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 */
+	struct md_thread		*thread;	/* management thread */
+	struct md_thread		*sync_thread;	/* doing resync or reconstruct */
 	sector_t			curr_resync;	/* last block scheduled */
 	/* As resync requests can complete out of order, we cannot easily track
 	 * how much resync has been completed.  So we occasionally pause until
@@ -402,11 +397,11 @@
 	atomic_t flush_pending;
 	struct work_struct flush_work;
 	struct work_struct event_work;	/* used by dm to report failure event */
-	void (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev);
+	void (*sync_super)(struct mddev *mddev, struct md_rdev *rdev);
 };
 
 
-static inline void rdev_dec_pending(mdk_rdev_t *rdev, mddev_t *mddev)
+static inline void rdev_dec_pending(struct md_rdev *rdev, struct mddev *mddev)
 {
 	int faulty = test_bit(Faulty, &rdev->flags);
 	if (atomic_dec_and_test(&rdev->nr_pending) && faulty)
@@ -418,35 +413,35 @@
         atomic_add(nr_sectors, &bdev->bd_contains->bd_disk->sync_io);
 }
 
-struct mdk_personality
+struct md_personality
 {
 	char *name;
 	int level;
 	struct list_head list;
 	struct module *owner;
-	int (*make_request)(mddev_t *mddev, struct bio *bio);
-	int (*run)(mddev_t *mddev);
-	int (*stop)(mddev_t *mddev);
-	void (*status)(struct seq_file *seq, mddev_t *mddev);
+	void (*make_request)(struct mddev *mddev, struct bio *bio);
+	int (*run)(struct mddev *mddev);
+	int (*stop)(struct mddev *mddev);
+	void (*status)(struct seq_file *seq, struct mddev *mddev);
 	/* error_handler must set ->faulty and clear ->in_sync
 	 * if appropriate, and should abort recovery if needed 
 	 */
-	void (*error_handler)(mddev_t *mddev, mdk_rdev_t *rdev);
-	int (*hot_add_disk) (mddev_t *mddev, mdk_rdev_t *rdev);
-	int (*hot_remove_disk) (mddev_t *mddev, int number);
-	int (*spare_active) (mddev_t *mddev);
-	sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster);
-	int (*resize) (mddev_t *mddev, sector_t sectors);
-	sector_t (*size) (mddev_t *mddev, sector_t sectors, int raid_disks);
-	int (*check_reshape) (mddev_t *mddev);
-	int (*start_reshape) (mddev_t *mddev);
-	void (*finish_reshape) (mddev_t *mddev);
+	void (*error_handler)(struct mddev *mddev, struct md_rdev *rdev);
+	int (*hot_add_disk) (struct mddev *mddev, struct md_rdev *rdev);
+	int (*hot_remove_disk) (struct mddev *mddev, int number);
+	int (*spare_active) (struct mddev *mddev);
+	sector_t (*sync_request)(struct mddev *mddev, sector_t sector_nr, int *skipped, int go_faster);
+	int (*resize) (struct mddev *mddev, sector_t sectors);
+	sector_t (*size) (struct mddev *mddev, sector_t sectors, int raid_disks);
+	int (*check_reshape) (struct mddev *mddev);
+	int (*start_reshape) (struct mddev *mddev);
+	void (*finish_reshape) (struct mddev *mddev);
 	/* quiesce moves between quiescence states
 	 * 0 - fully active
 	 * 1 - no new requests allowed
 	 * others - reserved
 	 */
-	void (*quiesce) (mddev_t *mddev, int state);
+	void (*quiesce) (struct mddev *mddev, int state);
 	/* takeover is used to transition an array from one
 	 * personality to another.  The new personality must be able
 	 * to handle the data in the current layout.
@@ -456,14 +451,14 @@
 	 * This needs to be installed and then ->run used to activate the
 	 * array.
 	 */
-	void *(*takeover) (mddev_t *mddev);
+	void *(*takeover) (struct mddev *mddev);
 };
 
 
 struct md_sysfs_entry {
 	struct attribute attr;
-	ssize_t (*show)(mddev_t *, char *);
-	ssize_t (*store)(mddev_t *, const char *, size_t);
+	ssize_t (*show)(struct mddev *, char *);
+	ssize_t (*store)(struct mddev *, const char *, size_t);
 };
 extern struct attribute_group md_bitmap_group;
 
@@ -479,19 +474,19 @@
 		sysfs_notify_dirent(sd);
 }
 
-static inline char * mdname (mddev_t * mddev)
+static inline char * mdname (struct mddev * mddev)
 {
 	return mddev->gendisk ? mddev->gendisk->disk_name : "mdX";
 }
 
-static inline int sysfs_link_rdev(mddev_t *mddev, mdk_rdev_t *rdev)
+static inline int sysfs_link_rdev(struct mddev *mddev, struct md_rdev *rdev)
 {
 	char nm[20];
 	sprintf(nm, "rd%d", rdev->raid_disk);
 	return sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
 }
 
-static inline void sysfs_unlink_rdev(mddev_t *mddev, mdk_rdev_t *rdev)
+static inline void sysfs_unlink_rdev(struct mddev *mddev, struct md_rdev *rdev)
 {
 	char nm[20];
 	sprintf(nm, "rd%d", rdev->raid_disk);
@@ -514,14 +509,14 @@
 #define rdev_for_each_rcu(rdev, mddev)				\
 	list_for_each_entry_rcu(rdev, &((mddev)->disks), same_set)
 
-typedef struct mdk_thread_s {
-	void			(*run) (mddev_t *mddev);
-	mddev_t			*mddev;
+struct md_thread {
+	void			(*run) (struct mddev *mddev);
+	struct mddev		*mddev;
 	wait_queue_head_t	wqueue;
 	unsigned long           flags;
 	struct task_struct	*tsk;
 	unsigned long		timeout;
-} mdk_thread_t;
+};
 
 #define THREAD_WAKEUP  0
 
@@ -556,48 +551,50 @@
 	if (p) put_page(p);
 }
 
-extern int register_md_personality(struct mdk_personality *p);
-extern int unregister_md_personality(struct mdk_personality *p);
-extern mdk_thread_t * md_register_thread(void (*run) (mddev_t *mddev),
-				mddev_t *mddev, const char *name);
-extern void md_unregister_thread(mdk_thread_t **threadp);
-extern void md_wakeup_thread(mdk_thread_t *thread);
-extern void md_check_recovery(mddev_t *mddev);
-extern void md_write_start(mddev_t *mddev, struct bio *bi);
-extern void md_write_end(mddev_t *mddev);
-extern void md_done_sync(mddev_t *mddev, int blocks, int ok);
-extern void md_error(mddev_t *mddev, mdk_rdev_t *rdev);
+extern int register_md_personality(struct md_personality *p);
+extern int unregister_md_personality(struct md_personality *p);
+extern struct md_thread *md_register_thread(
+	void (*run)(struct mddev *mddev),
+	struct mddev *mddev,
+	const char *name);
+extern void md_unregister_thread(struct md_thread **threadp);
+extern void md_wakeup_thread(struct md_thread *thread);
+extern void md_check_recovery(struct mddev *mddev);
+extern void md_write_start(struct mddev *mddev, struct bio *bi);
+extern void md_write_end(struct mddev *mddev);
+extern void md_done_sync(struct mddev *mddev, int blocks, int ok);
+extern void md_error(struct mddev *mddev, struct md_rdev *rdev);
 
-extern int mddev_congested(mddev_t *mddev, int bits);
-extern void md_flush_request(mddev_t *mddev, struct bio *bio);
-extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
+extern int mddev_congested(struct mddev *mddev, int bits);
+extern void md_flush_request(struct mddev *mddev, struct bio *bio);
+extern void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
 			   sector_t sector, int size, struct page *page);
-extern void md_super_wait(mddev_t *mddev);
-extern int sync_page_io(mdk_rdev_t *rdev, sector_t sector, int size, 
+extern void md_super_wait(struct mddev *mddev);
+extern int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, 
 			struct page *page, int rw, bool metadata_op);
-extern void md_do_sync(mddev_t *mddev);
-extern void md_new_event(mddev_t *mddev);
-extern int md_allow_write(mddev_t *mddev);
-extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
-extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors);
-extern int md_check_no_bitmap(mddev_t *mddev);
-extern int md_integrity_register(mddev_t *mddev);
-extern void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
+extern void md_do_sync(struct mddev *mddev);
+extern void md_new_event(struct mddev *mddev);
+extern int md_allow_write(struct mddev *mddev);
+extern void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev);
+extern void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors);
+extern int md_check_no_bitmap(struct mddev *mddev);
+extern int md_integrity_register(struct mddev *mddev);
+extern void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *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 mddev_init(mddev_t *mddev);
-extern int md_run(mddev_t *mddev);
-extern void md_stop(mddev_t *mddev);
-extern void md_stop_writes(mddev_t *mddev);
-extern int md_rdev_init(mdk_rdev_t *rdev);
+extern void mddev_init(struct mddev *mddev);
+extern int md_run(struct mddev *mddev);
+extern void md_stop(struct mddev *mddev);
+extern void md_stop_writes(struct mddev *mddev);
+extern int md_rdev_init(struct md_rdev *rdev);
 
-extern void mddev_suspend(mddev_t *mddev);
-extern void mddev_resume(mddev_t *mddev);
+extern void mddev_suspend(struct mddev *mddev);
+extern void mddev_resume(struct mddev *mddev);
 extern struct bio *bio_clone_mddev(struct bio *bio, gfp_t gfp_mask,
-				   mddev_t *mddev);
+				   struct mddev *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);
+				   struct mddev *mddev);
+extern int mddev_check_plugged(struct mddev *mddev);
 extern void md_trim_bio(struct bio *bio, int offset, int size);
 #endif /* _MD_MD_H */
diff -druN linux-libre-3.1-gnu/drivers/md/multipath.c linux-libre-3.2-gnu/drivers/md/multipath.c
--- linux-libre-3.1-gnu/drivers/md/multipath.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/multipath.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/blkdev.h>
+#include <linux/module.h>
 #include <linux/raid/md_u.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
@@ -31,7 +32,7 @@
 #define	NR_RESERVED_BUFS	32
 
 
-static int multipath_map (multipath_conf_t *conf)
+static int multipath_map (struct mpconf *conf)
 {
 	int i, disks = conf->raid_disks;
 
@@ -42,7 +43,7 @@
 
 	rcu_read_lock();
 	for (i = 0; i < disks; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->multipaths[i].rdev);
 		if (rdev && test_bit(In_sync, &rdev->flags)) {
 			atomic_inc(&rdev->nr_pending);
 			rcu_read_unlock();
@@ -58,8 +59,8 @@
 static void multipath_reschedule_retry (struct multipath_bh *mp_bh)
 {
 	unsigned long flags;
-	mddev_t *mddev = mp_bh->mddev;
-	multipath_conf_t *conf = mddev->private;
+	struct mddev *mddev = mp_bh->mddev;
+	struct mpconf *conf = mddev->private;
 
 	spin_lock_irqsave(&conf->device_lock, flags);
 	list_add(&mp_bh->retry_list, &conf->retry_list);
@@ -76,7 +77,7 @@
 static void multipath_end_bh_io (struct multipath_bh *mp_bh, int err)
 {
 	struct bio *bio = mp_bh->master_bio;
-	multipath_conf_t *conf = mp_bh->mddev->private;
+	struct mpconf *conf = mp_bh->mddev->private;
 
 	bio_endio(bio, err);
 	mempool_free(mp_bh, conf->pool);
@@ -86,8 +87,8 @@
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct multipath_bh *mp_bh = bio->bi_private;
-	multipath_conf_t *conf = mp_bh->mddev->private;
-	mdk_rdev_t *rdev = conf->multipaths[mp_bh->path].rdev;
+	struct mpconf *conf = mp_bh->mddev->private;
+	struct md_rdev *rdev = conf->multipaths[mp_bh->path].rdev;
 
 	if (uptodate)
 		multipath_end_bh_io(mp_bh, 0);
@@ -106,15 +107,15 @@
 	rdev_dec_pending(rdev, conf->mddev);
 }
 
-static int multipath_make_request(mddev_t *mddev, struct bio * bio)
+static void multipath_make_request(struct mddev *mddev, struct bio * bio)
 {
-	multipath_conf_t *conf = mddev->private;
+	struct mpconf *conf = mddev->private;
 	struct multipath_bh * mp_bh;
 	struct multipath_info *multipath;
 
 	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
 		md_flush_request(mddev, bio);
-		return 0;
+		return;
 	}
 
 	mp_bh = mempool_alloc(conf->pool, GFP_NOIO);
@@ -126,7 +127,7 @@
 	if (mp_bh->path < 0) {
 		bio_endio(bio, -EIO);
 		mempool_free(mp_bh, conf->pool);
-		return 0;
+		return;
 	}
 	multipath = conf->multipaths + mp_bh->path;
 
@@ -137,12 +138,12 @@
 	mp_bh->bio.bi_end_io = multipath_end_request;
 	mp_bh->bio.bi_private = mp_bh;
 	generic_make_request(&mp_bh->bio);
-	return 0;
+	return;
 }
 
-static void multipath_status (struct seq_file *seq, mddev_t *mddev)
+static void multipath_status (struct seq_file *seq, struct mddev *mddev)
 {
-	multipath_conf_t *conf = mddev->private;
+	struct mpconf *conf = mddev->private;
 	int i;
 	
 	seq_printf (seq, " [%d/%d] [", conf->raid_disks,
@@ -156,8 +157,8 @@
 
 static int multipath_congested(void *data, int bits)
 {
-	mddev_t *mddev = data;
-	multipath_conf_t *conf = mddev->private;
+	struct mddev *mddev = data;
+	struct mpconf *conf = mddev->private;
 	int i, ret = 0;
 
 	if (mddev_congested(mddev, bits))
@@ -165,7 +166,7 @@
 
 	rcu_read_lock();
 	for (i = 0; i < mddev->raid_disks ; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->multipaths[i].rdev);
 		if (rdev && !test_bit(Faulty, &rdev->flags)) {
 			struct request_queue *q = bdev_get_queue(rdev->bdev);
 
@@ -183,9 +184,9 @@
 /*
  * Careful, this can execute in IRQ contexts as well!
  */
-static void multipath_error (mddev_t *mddev, mdk_rdev_t *rdev)
+static void multipath_error (struct mddev *mddev, struct md_rdev *rdev)
 {
-	multipath_conf_t *conf = mddev->private;
+	struct mpconf *conf = mddev->private;
 	char b[BDEVNAME_SIZE];
 
 	if (conf->raid_disks - mddev->degraded <= 1) {
@@ -218,7 +219,7 @@
 	       conf->raid_disks - mddev->degraded);
 }
 
-static void print_multipath_conf (multipath_conf_t *conf)
+static void print_multipath_conf (struct mpconf *conf)
 {
 	int i;
 	struct multipath_info *tmp;
@@ -242,9 +243,9 @@
 }
 
 
-static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+static int multipath_add_disk(struct mddev *mddev, struct md_rdev *rdev)
 {
-	multipath_conf_t *conf = mddev->private;
+	struct mpconf *conf = mddev->private;
 	struct request_queue *q;
 	int err = -EEXIST;
 	int path;
@@ -291,11 +292,11 @@
 	return err;
 }
 
-static int multipath_remove_disk(mddev_t *mddev, int number)
+static int multipath_remove_disk(struct mddev *mddev, int number)
 {
-	multipath_conf_t *conf = mddev->private;
+	struct mpconf *conf = mddev->private;
 	int err = 0;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	struct multipath_info *p = conf->multipaths + number;
 
 	print_multipath_conf(conf);
@@ -335,12 +336,12 @@
  *	3.	Performs writes following reads for array syncronising.
  */
 
-static void multipathd (mddev_t *mddev)
+static void multipathd (struct mddev *mddev)
 {
 	struct multipath_bh *mp_bh;
 	struct bio *bio;
 	unsigned long flags;
-	multipath_conf_t *conf = mddev->private;
+	struct mpconf *conf = mddev->private;
 	struct list_head *head = &conf->retry_list;
 
 	md_check_recovery(mddev);
@@ -379,7 +380,7 @@
 	spin_unlock_irqrestore(&conf->device_lock, flags);
 }
 
-static sector_t multipath_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+static sector_t multipath_size(struct mddev *mddev, sector_t sectors, int raid_disks)
 {
 	WARN_ONCE(sectors || raid_disks,
 		  "%s does not support generic reshape\n", __func__);
@@ -387,12 +388,12 @@
 	return mddev->dev_sectors;
 }
 
-static int multipath_run (mddev_t *mddev)
+static int multipath_run (struct mddev *mddev)
 {
-	multipath_conf_t *conf;
+	struct mpconf *conf;
 	int disk_idx;
 	struct multipath_info *disk;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int working_disks;
 
 	if (md_check_no_bitmap(mddev))
@@ -409,7 +410,7 @@
 	 * should be freed in multipath_stop()]
 	 */
 
-	conf = kzalloc(sizeof(multipath_conf_t), GFP_KERNEL);
+	conf = kzalloc(sizeof(struct mpconf), GFP_KERNEL);
 	mddev->private = conf;
 	if (!conf) {
 		printk(KERN_ERR 
@@ -510,9 +511,9 @@
 }
 
 
-static int multipath_stop (mddev_t *mddev)
+static int multipath_stop (struct mddev *mddev)
 {
-	multipath_conf_t *conf = mddev->private;
+	struct mpconf *conf = mddev->private;
 
 	md_unregister_thread(&mddev->thread);
 	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
@@ -523,7 +524,7 @@
 	return 0;
 }
 
-static struct mdk_personality multipath_personality =
+static struct md_personality multipath_personality =
 {
 	.name		= "multipath",
 	.level		= LEVEL_MULTIPATH,
diff -druN linux-libre-3.1-gnu/drivers/md/multipath.h linux-libre-3.2-gnu/drivers/md/multipath.h
--- linux-libre-3.1-gnu/drivers/md/multipath.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/multipath.h	2012-01-04 18:55:44.000000000 -0500
@@ -2,11 +2,11 @@
 #define _MULTIPATH_H
 
 struct multipath_info {
-	mdk_rdev_t	*rdev;
+	struct md_rdev	*rdev;
 };
 
-struct multipath_private_data {
-	mddev_t			*mddev;
+struct mpconf {
+	struct mddev			*mddev;
 	struct multipath_info	*multipaths;
 	int			raid_disks;
 	spinlock_t		device_lock;
@@ -15,8 +15,6 @@
 	mempool_t		*pool;
 };
 
-typedef struct multipath_private_data multipath_conf_t;
-
 /*
  * this is our 'private' 'collective' MULTIPATH buffer head.
  * it contains information about what kind of IO operations were started
@@ -24,7 +22,7 @@
  */
 
 struct multipath_bh {
-	mddev_t			*mddev;
+	struct mddev			*mddev;
 	struct bio		*master_bio;
 	struct bio		bio;
 	int			path;
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-block-manager.c linux-libre-3.2-gnu/drivers/md/persistent-data/dm-block-manager.c
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-block-manager.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-block-manager.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+#include "dm-block-manager.h"
+#include "dm-persistent-data-internal.h"
+#include "../dm-bufio.h"
+
+#include <linux/crc32c.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/rwsem.h>
+#include <linux/device-mapper.h>
+#include <linux/stacktrace.h>
+
+#define DM_MSG_PREFIX "block manager"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * This is a read/write semaphore with a couple of differences.
+ *
+ * i) There is a restriction on the number of concurrent read locks that
+ * may be held at once.  This is just an implementation detail.
+ *
+ * ii) Recursive locking attempts are detected and return EINVAL.  A stack
+ * trace is also emitted for the previous lock aquisition.
+ *
+ * iii) Priority is given to write locks.
+ */
+#define MAX_HOLDERS 4
+#define MAX_STACK 10
+
+typedef unsigned long stack_entries[MAX_STACK];
+
+struct block_lock {
+	spinlock_t lock;
+	__s32 count;
+	struct list_head waiters;
+	struct task_struct *holders[MAX_HOLDERS];
+
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+	struct stack_trace traces[MAX_HOLDERS];
+	stack_entries entries[MAX_HOLDERS];
+#endif
+};
+
+struct waiter {
+	struct list_head list;
+	struct task_struct *task;
+	int wants_write;
+};
+
+static unsigned __find_holder(struct block_lock *lock,
+			      struct task_struct *task)
+{
+	unsigned i;
+
+	for (i = 0; i < MAX_HOLDERS; i++)
+		if (lock->holders[i] == task)
+			break;
+
+	BUG_ON(i == MAX_HOLDERS);
+	return i;
+}
+
+/* call this *after* you increment lock->count */
+static void __add_holder(struct block_lock *lock, struct task_struct *task)
+{
+	unsigned h = __find_holder(lock, NULL);
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+	struct stack_trace *t;
+#endif
+
+	get_task_struct(task);
+	lock->holders[h] = task;
+
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+	t = lock->traces + h;
+	t->nr_entries = 0;
+	t->max_entries = MAX_STACK;
+	t->entries = lock->entries[h];
+	t->skip = 2;
+	save_stack_trace(t);
+#endif
+}
+
+/* call this *before* you decrement lock->count */
+static void __del_holder(struct block_lock *lock, struct task_struct *task)
+{
+	unsigned h = __find_holder(lock, task);
+	lock->holders[h] = NULL;
+	put_task_struct(task);
+}
+
+static int __check_holder(struct block_lock *lock)
+{
+	unsigned i;
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+	static struct stack_trace t;
+	static stack_entries entries;
+#endif
+
+	for (i = 0; i < MAX_HOLDERS; i++) {
+		if (lock->holders[i] == current) {
+			DMERR("recursive lock detected in pool metadata");
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+			DMERR("previously held here:");
+			print_stack_trace(lock->traces + i, 4);
+
+			DMERR("subsequent aquisition attempted here:");
+			t.nr_entries = 0;
+			t.max_entries = MAX_STACK;
+			t.entries = entries;
+			t.skip = 3;
+			save_stack_trace(&t);
+			print_stack_trace(&t, 4);
+#endif
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static void __wait(struct waiter *w)
+{
+	for (;;) {
+		set_task_state(current, TASK_UNINTERRUPTIBLE);
+
+		if (!w->task)
+			break;
+
+		schedule();
+	}
+
+	set_task_state(current, TASK_RUNNING);
+}
+
+static void __wake_waiter(struct waiter *w)
+{
+	struct task_struct *task;
+
+	list_del(&w->list);
+	task = w->task;
+	smp_mb();
+	w->task = NULL;
+	wake_up_process(task);
+}
+
+/*
+ * We either wake a few readers or a single writer.
+ */
+static void __wake_many(struct block_lock *lock)
+{
+	struct waiter *w, *tmp;
+
+	BUG_ON(lock->count < 0);
+	list_for_each_entry_safe(w, tmp, &lock->waiters, list) {
+		if (lock->count >= MAX_HOLDERS)
+			return;
+
+		if (w->wants_write) {
+			if (lock->count > 0)
+				return; /* still read locked */
+
+			lock->count = -1;
+			__add_holder(lock, w->task);
+			__wake_waiter(w);
+			return;
+		}
+
+		lock->count++;
+		__add_holder(lock, w->task);
+		__wake_waiter(w);
+	}
+}
+
+static void bl_init(struct block_lock *lock)
+{
+	int i;
+
+	spin_lock_init(&lock->lock);
+	lock->count = 0;
+	INIT_LIST_HEAD(&lock->waiters);
+	for (i = 0; i < MAX_HOLDERS; i++)
+		lock->holders[i] = NULL;
+}
+
+static int __available_for_read(struct block_lock *lock)
+{
+	return lock->count >= 0 &&
+		lock->count < MAX_HOLDERS &&
+		list_empty(&lock->waiters);
+}
+
+static int bl_down_read(struct block_lock *lock)
+{
+	int r;
+	struct waiter w;
+
+	spin_lock(&lock->lock);
+	r = __check_holder(lock);
+	if (r) {
+		spin_unlock(&lock->lock);
+		return r;
+	}
+
+	if (__available_for_read(lock)) {
+		lock->count++;
+		__add_holder(lock, current);
+		spin_unlock(&lock->lock);
+		return 0;
+	}
+
+	get_task_struct(current);
+
+	w.task = current;
+	w.wants_write = 0;
+	list_add_tail(&w.list, &lock->waiters);
+	spin_unlock(&lock->lock);
+
+	__wait(&w);
+	put_task_struct(current);
+	return 0;
+}
+
+static int bl_down_read_nonblock(struct block_lock *lock)
+{
+	int r;
+
+	spin_lock(&lock->lock);
+	r = __check_holder(lock);
+	if (r)
+		goto out;
+
+	if (__available_for_read(lock)) {
+		lock->count++;
+		__add_holder(lock, current);
+		r = 0;
+	} else
+		r = -EWOULDBLOCK;
+
+out:
+	spin_unlock(&lock->lock);
+	return r;
+}
+
+static void bl_up_read(struct block_lock *lock)
+{
+	spin_lock(&lock->lock);
+	BUG_ON(lock->count <= 0);
+	__del_holder(lock, current);
+	--lock->count;
+	if (!list_empty(&lock->waiters))
+		__wake_many(lock);
+	spin_unlock(&lock->lock);
+}
+
+static int bl_down_write(struct block_lock *lock)
+{
+	int r;
+	struct waiter w;
+
+	spin_lock(&lock->lock);
+	r = __check_holder(lock);
+	if (r) {
+		spin_unlock(&lock->lock);
+		return r;
+	}
+
+	if (lock->count == 0 && list_empty(&lock->waiters)) {
+		lock->count = -1;
+		__add_holder(lock, current);
+		spin_unlock(&lock->lock);
+		return 0;
+	}
+
+	get_task_struct(current);
+	w.task = current;
+	w.wants_write = 1;
+
+	/*
+	 * Writers given priority. We know there's only one mutator in the
+	 * system, so ignoring the ordering reversal.
+	 */
+	list_add(&w.list, &lock->waiters);
+	spin_unlock(&lock->lock);
+
+	__wait(&w);
+	put_task_struct(current);
+
+	return 0;
+}
+
+static void bl_up_write(struct block_lock *lock)
+{
+	spin_lock(&lock->lock);
+	__del_holder(lock, current);
+	lock->count = 0;
+	if (!list_empty(&lock->waiters))
+		__wake_many(lock);
+	spin_unlock(&lock->lock);
+}
+
+static void report_recursive_bug(dm_block_t b, int r)
+{
+	if (r == -EINVAL)
+		DMERR("recursive acquisition of block %llu requested.",
+		      (unsigned long long) b);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Block manager is currently implemented using dm-bufio.  struct
+ * dm_block_manager and struct dm_block map directly onto a couple of
+ * structs in the bufio interface.  I want to retain the freedom to move
+ * away from bufio in the future.  So these structs are just cast within
+ * this .c file, rather than making it through to the public interface.
+ */
+static struct dm_buffer *to_buffer(struct dm_block *b)
+{
+	return (struct dm_buffer *) b;
+}
+
+static struct dm_bufio_client *to_bufio(struct dm_block_manager *bm)
+{
+	return (struct dm_bufio_client *) bm;
+}
+
+dm_block_t dm_block_location(struct dm_block *b)
+{
+	return dm_bufio_get_block_number(to_buffer(b));
+}
+EXPORT_SYMBOL_GPL(dm_block_location);
+
+void *dm_block_data(struct dm_block *b)
+{
+	return dm_bufio_get_block_data(to_buffer(b));
+}
+EXPORT_SYMBOL_GPL(dm_block_data);
+
+struct buffer_aux {
+	struct dm_block_validator *validator;
+	struct block_lock lock;
+	int write_locked;
+};
+
+static void dm_block_manager_alloc_callback(struct dm_buffer *buf)
+{
+	struct buffer_aux *aux = dm_bufio_get_aux_data(buf);
+	aux->validator = NULL;
+	bl_init(&aux->lock);
+}
+
+static void dm_block_manager_write_callback(struct dm_buffer *buf)
+{
+	struct buffer_aux *aux = dm_bufio_get_aux_data(buf);
+	if (aux->validator) {
+		aux->validator->prepare_for_write(aux->validator, (struct dm_block *) buf,
+			 dm_bufio_get_block_size(dm_bufio_get_client(buf)));
+	}
+}
+
+/*----------------------------------------------------------------
+ * Public interface
+ *--------------------------------------------------------------*/
+struct dm_block_manager *dm_block_manager_create(struct block_device *bdev,
+						 unsigned block_size,
+						 unsigned cache_size,
+						 unsigned max_held_per_thread)
+{
+	return (struct dm_block_manager *)
+		dm_bufio_client_create(bdev, block_size, max_held_per_thread,
+				       sizeof(struct buffer_aux),
+				       dm_block_manager_alloc_callback,
+				       dm_block_manager_write_callback);
+}
+EXPORT_SYMBOL_GPL(dm_block_manager_create);
+
+void dm_block_manager_destroy(struct dm_block_manager *bm)
+{
+	return dm_bufio_client_destroy(to_bufio(bm));
+}
+EXPORT_SYMBOL_GPL(dm_block_manager_destroy);
+
+unsigned dm_bm_block_size(struct dm_block_manager *bm)
+{
+	return dm_bufio_get_block_size(to_bufio(bm));
+}
+EXPORT_SYMBOL_GPL(dm_bm_block_size);
+
+dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm)
+{
+	return dm_bufio_get_device_size(to_bufio(bm));
+}
+
+static int dm_bm_validate_buffer(struct dm_block_manager *bm,
+				 struct dm_buffer *buf,
+				 struct buffer_aux *aux,
+				 struct dm_block_validator *v)
+{
+	if (unlikely(!aux->validator)) {
+		int r;
+		if (!v)
+			return 0;
+		r = v->check(v, (struct dm_block *) buf, dm_bufio_get_block_size(to_bufio(bm)));
+		if (unlikely(r))
+			return r;
+		aux->validator = v;
+	} else {
+		if (unlikely(aux->validator != v)) {
+			DMERR("validator mismatch (old=%s vs new=%s) for block %llu",
+				aux->validator->name, v ? v->name : "NULL",
+				(unsigned long long)
+					dm_bufio_get_block_number(buf));
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+int dm_bm_read_lock(struct dm_block_manager *bm, dm_block_t b,
+		    struct dm_block_validator *v,
+		    struct dm_block **result)
+{
+	struct buffer_aux *aux;
+	void *p;
+	int r;
+
+	p = dm_bufio_read(to_bufio(bm), b, (struct dm_buffer **) result);
+	if (unlikely(IS_ERR(p)))
+		return PTR_ERR(p);
+
+	aux = dm_bufio_get_aux_data(to_buffer(*result));
+	r = bl_down_read(&aux->lock);
+	if (unlikely(r)) {
+		dm_bufio_release(to_buffer(*result));
+		report_recursive_bug(b, r);
+		return r;
+	}
+
+	aux->write_locked = 0;
+
+	r = dm_bm_validate_buffer(bm, to_buffer(*result), aux, v);
+	if (unlikely(r)) {
+		bl_up_read(&aux->lock);
+		dm_bufio_release(to_buffer(*result));
+		return r;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dm_bm_read_lock);
+
+int dm_bm_write_lock(struct dm_block_manager *bm,
+		     dm_block_t b, struct dm_block_validator *v,
+		     struct dm_block **result)
+{
+	struct buffer_aux *aux;
+	void *p;
+	int r;
+
+	p = dm_bufio_read(to_bufio(bm), b, (struct dm_buffer **) result);
+	if (unlikely(IS_ERR(p)))
+		return PTR_ERR(p);
+
+	aux = dm_bufio_get_aux_data(to_buffer(*result));
+	r = bl_down_write(&aux->lock);
+	if (r) {
+		dm_bufio_release(to_buffer(*result));
+		report_recursive_bug(b, r);
+		return r;
+	}
+
+	aux->write_locked = 1;
+
+	r = dm_bm_validate_buffer(bm, to_buffer(*result), aux, v);
+	if (unlikely(r)) {
+		bl_up_write(&aux->lock);
+		dm_bufio_release(to_buffer(*result));
+		return r;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dm_bm_write_lock);
+
+int dm_bm_read_try_lock(struct dm_block_manager *bm,
+			dm_block_t b, struct dm_block_validator *v,
+			struct dm_block **result)
+{
+	struct buffer_aux *aux;
+	void *p;
+	int r;
+
+	p = dm_bufio_get(to_bufio(bm), b, (struct dm_buffer **) result);
+	if (unlikely(IS_ERR(p)))
+		return PTR_ERR(p);
+	if (unlikely(!p))
+		return -EWOULDBLOCK;
+
+	aux = dm_bufio_get_aux_data(to_buffer(*result));
+	r = bl_down_read_nonblock(&aux->lock);
+	if (r < 0) {
+		dm_bufio_release(to_buffer(*result));
+		report_recursive_bug(b, r);
+		return r;
+	}
+	aux->write_locked = 0;
+
+	r = dm_bm_validate_buffer(bm, to_buffer(*result), aux, v);
+	if (unlikely(r)) {
+		bl_up_read(&aux->lock);
+		dm_bufio_release(to_buffer(*result));
+		return r;
+	}
+
+	return 0;
+}
+
+int dm_bm_write_lock_zero(struct dm_block_manager *bm,
+			  dm_block_t b, struct dm_block_validator *v,
+			  struct dm_block **result)
+{
+	int r;
+	struct buffer_aux *aux;
+	void *p;
+
+	p = dm_bufio_new(to_bufio(bm), b, (struct dm_buffer **) result);
+	if (unlikely(IS_ERR(p)))
+		return PTR_ERR(p);
+
+	memset(p, 0, dm_bm_block_size(bm));
+
+	aux = dm_bufio_get_aux_data(to_buffer(*result));
+	r = bl_down_write(&aux->lock);
+	if (r) {
+		dm_bufio_release(to_buffer(*result));
+		return r;
+	}
+
+	aux->write_locked = 1;
+	aux->validator = v;
+
+	return 0;
+}
+
+int dm_bm_unlock(struct dm_block *b)
+{
+	struct buffer_aux *aux;
+	aux = dm_bufio_get_aux_data(to_buffer(b));
+
+	if (aux->write_locked) {
+		dm_bufio_mark_buffer_dirty(to_buffer(b));
+		bl_up_write(&aux->lock);
+	} else
+		bl_up_read(&aux->lock);
+
+	dm_bufio_release(to_buffer(b));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dm_bm_unlock);
+
+int dm_bm_unlock_move(struct dm_block *b, dm_block_t n)
+{
+	struct buffer_aux *aux;
+
+	aux = dm_bufio_get_aux_data(to_buffer(b));
+
+	if (aux->write_locked) {
+		dm_bufio_mark_buffer_dirty(to_buffer(b));
+		bl_up_write(&aux->lock);
+	} else
+		bl_up_read(&aux->lock);
+
+	dm_bufio_release_move(to_buffer(b), n);
+	return 0;
+}
+
+int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
+			   struct dm_block *superblock)
+{
+	int r;
+
+	r = dm_bufio_write_dirty_buffers(to_bufio(bm));
+	if (unlikely(r))
+		return r;
+	r = dm_bufio_issue_flush(to_bufio(bm));
+	if (unlikely(r))
+		return r;
+
+	dm_bm_unlock(superblock);
+
+	r = dm_bufio_write_dirty_buffers(to_bufio(bm));
+	if (unlikely(r))
+		return r;
+	r = dm_bufio_issue_flush(to_bufio(bm));
+	if (unlikely(r))
+		return r;
+
+	return 0;
+}
+
+u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor)
+{
+	return crc32c(~(u32) 0, data, len) ^ init_xor;
+}
+EXPORT_SYMBOL_GPL(dm_bm_checksum);
+
+/*----------------------------------------------------------------*/
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
+MODULE_DESCRIPTION("Immutable metadata library for dm");
+
+/*----------------------------------------------------------------*/
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-block-manager.h linux-libre-3.2-gnu/drivers/md/persistent-data/dm-block-manager.h
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-block-manager.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-block-manager.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_BLOCK_MANAGER_H
+#define _LINUX_DM_BLOCK_MANAGER_H
+
+#include <linux/types.h>
+#include <linux/blkdev.h>
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Block number.
+ */
+typedef uint64_t dm_block_t;
+struct dm_block;
+
+dm_block_t dm_block_location(struct dm_block *b);
+void *dm_block_data(struct dm_block *b);
+
+/*----------------------------------------------------------------*/
+
+/*
+ * @name should be a unique identifier for the block manager, no longer
+ * than 32 chars.
+ *
+ * @max_held_per_thread should be the maximum number of locks, read or
+ * write, that an individual thread holds at any one time.
+ */
+struct dm_block_manager;
+struct dm_block_manager *dm_block_manager_create(
+	struct block_device *bdev, unsigned block_size,
+	unsigned cache_size, unsigned max_held_per_thread);
+void dm_block_manager_destroy(struct dm_block_manager *bm);
+
+unsigned dm_bm_block_size(struct dm_block_manager *bm);
+dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm);
+
+/*----------------------------------------------------------------*/
+
+/*
+ * The validator allows the caller to verify newly-read data and modify
+ * the data just before writing, e.g. to calculate checksums.  It's
+ * important to be consistent with your use of validators.  The only time
+ * you can change validators is if you call dm_bm_write_lock_zero.
+ */
+struct dm_block_validator {
+	const char *name;
+	void (*prepare_for_write)(struct dm_block_validator *v, struct dm_block *b, size_t block_size);
+
+	/*
+	 * Return 0 if the checksum is valid or < 0 on error.
+	 */
+	int (*check)(struct dm_block_validator *v, struct dm_block *b, size_t block_size);
+};
+
+/*----------------------------------------------------------------*/
+
+/*
+ * You can have multiple concurrent readers or a single writer holding a
+ * block lock.
+ */
+
+/*
+ * dm_bm_lock() locks a block and returns through @result a pointer to
+ * memory that holds a copy of that block.  If you have write-locked the
+ * block then any changes you make to memory pointed to by @result will be
+ * written back to the disk sometime after dm_bm_unlock is called.
+ */
+int dm_bm_read_lock(struct dm_block_manager *bm, dm_block_t b,
+		    struct dm_block_validator *v,
+		    struct dm_block **result);
+
+int dm_bm_write_lock(struct dm_block_manager *bm, dm_block_t b,
+		     struct dm_block_validator *v,
+		     struct dm_block **result);
+
+/*
+ * The *_try_lock variants return -EWOULDBLOCK if the block isn't
+ * available immediately.
+ */
+int dm_bm_read_try_lock(struct dm_block_manager *bm, dm_block_t b,
+			struct dm_block_validator *v,
+			struct dm_block **result);
+
+/*
+ * Use dm_bm_write_lock_zero() when you know you're going to
+ * overwrite the block completely.  It saves a disk read.
+ */
+int dm_bm_write_lock_zero(struct dm_block_manager *bm, dm_block_t b,
+			  struct dm_block_validator *v,
+			  struct dm_block **result);
+
+int dm_bm_unlock(struct dm_block *b);
+
+/*
+ * An optimisation; we often want to copy a block's contents to a new
+ * block.  eg, as part of the shadowing operation.  It's far better for
+ * bufio to do this move behind the scenes than hold 2 locks and memcpy the
+ * data.
+ */
+int dm_bm_unlock_move(struct dm_block *b, dm_block_t n);
+
+/*
+ * It's a common idiom to have a superblock that should be committed last.
+ *
+ * @superblock should be write-locked on entry. It will be unlocked during
+ * this function.  All dirty blocks are guaranteed to be written and flushed
+ * before the superblock.
+ *
+ * This method always blocks.
+ */
+int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
+			   struct dm_block *superblock);
+
+u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor);
+
+/*----------------------------------------------------------------*/
+
+#endif	/* _LINUX_DM_BLOCK_MANAGER_H */
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-btree.c linux-libre-3.2-gnu/drivers/md/persistent-data/dm-btree.c
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-btree.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-btree.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,805 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-btree-internal.h"
+#include "dm-space-map.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/export.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "btree"
+
+/*----------------------------------------------------------------
+ * Array manipulation
+ *--------------------------------------------------------------*/
+static void memcpy_disk(void *dest, const void *src, size_t len)
+	__dm_written_to_disk(src)
+{
+	memcpy(dest, src, len);
+	__dm_unbless_for_disk(src);
+}
+
+static void array_insert(void *base, size_t elt_size, unsigned nr_elts,
+			 unsigned index, void *elt)
+	__dm_written_to_disk(elt)
+{
+	if (index < nr_elts)
+		memmove(base + (elt_size * (index + 1)),
+			base + (elt_size * index),
+			(nr_elts - index) * elt_size);
+
+	memcpy_disk(base + (elt_size * index), elt, elt_size);
+}
+
+/*----------------------------------------------------------------*/
+
+/* makes the assumption that no two keys are the same. */
+static int bsearch(struct node *n, uint64_t key, int want_hi)
+{
+	int lo = -1, hi = le32_to_cpu(n->header.nr_entries);
+
+	while (hi - lo > 1) {
+		int mid = lo + ((hi - lo) / 2);
+		uint64_t mid_key = le64_to_cpu(n->keys[mid]);
+
+		if (mid_key == key)
+			return mid;
+
+		if (mid_key < key)
+			lo = mid;
+		else
+			hi = mid;
+	}
+
+	return want_hi ? hi : lo;
+}
+
+int lower_bound(struct node *n, uint64_t key)
+{
+	return bsearch(n, key, 0);
+}
+
+void inc_children(struct dm_transaction_manager *tm, struct node *n,
+		  struct dm_btree_value_type *vt)
+{
+	unsigned i;
+	uint32_t nr_entries = le32_to_cpu(n->header.nr_entries);
+
+	if (le32_to_cpu(n->header.flags) & INTERNAL_NODE)
+		for (i = 0; i < nr_entries; i++)
+			dm_tm_inc(tm, value64(n, i));
+	else if (vt->inc)
+		for (i = 0; i < nr_entries; i++)
+			vt->inc(vt->context,
+				value_ptr(n, i, vt->size));
+}
+
+static int insert_at(size_t value_size, struct node *node, unsigned index,
+		      uint64_t key, void *value)
+		      __dm_written_to_disk(value)
+{
+	uint32_t nr_entries = le32_to_cpu(node->header.nr_entries);
+	__le64 key_le = cpu_to_le64(key);
+
+	if (index > nr_entries ||
+	    index >= le32_to_cpu(node->header.max_entries)) {
+		DMERR("too many entries in btree node for insert");
+		__dm_unbless_for_disk(value);
+		return -ENOMEM;
+	}
+
+	__dm_bless_for_disk(&key_le);
+
+	array_insert(node->keys, sizeof(*node->keys), nr_entries, index, &key_le);
+	array_insert(value_base(node), value_size, nr_entries, index, value);
+	node->header.nr_entries = cpu_to_le32(nr_entries + 1);
+
+	return 0;
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * We want 3n entries (for some n).  This works more nicely for repeated
+ * insert remove loops than (2n + 1).
+ */
+static uint32_t calc_max_entries(size_t value_size, size_t block_size)
+{
+	uint32_t total, n;
+	size_t elt_size = sizeof(uint64_t) + value_size; /* key + value */
+
+	block_size -= sizeof(struct node_header);
+	total = block_size / elt_size;
+	n = total / 3;		/* rounds down */
+
+	return 3 * n;
+}
+
+int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root)
+{
+	int r;
+	struct dm_block *b;
+	struct node *n;
+	size_t block_size;
+	uint32_t max_entries;
+
+	r = new_block(info, &b);
+	if (r < 0)
+		return r;
+
+	block_size = dm_bm_block_size(dm_tm_get_bm(info->tm));
+	max_entries = calc_max_entries(info->value_type.size, block_size);
+
+	n = dm_block_data(b);
+	memset(n, 0, block_size);
+	n->header.flags = cpu_to_le32(LEAF_NODE);
+	n->header.nr_entries = cpu_to_le32(0);
+	n->header.max_entries = cpu_to_le32(max_entries);
+	n->header.value_size = cpu_to_le32(info->value_type.size);
+
+	*root = dm_block_location(b);
+	return unlock_block(info, b);
+}
+EXPORT_SYMBOL_GPL(dm_btree_empty);
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Deletion uses a recursive algorithm, since we have limited stack space
+ * we explicitly manage our own stack on the heap.
+ */
+#define MAX_SPINE_DEPTH 64
+struct frame {
+	struct dm_block *b;
+	struct node *n;
+	unsigned level;
+	unsigned nr_children;
+	unsigned current_child;
+};
+
+struct del_stack {
+	struct dm_transaction_manager *tm;
+	int top;
+	struct frame spine[MAX_SPINE_DEPTH];
+};
+
+static int top_frame(struct del_stack *s, struct frame **f)
+{
+	if (s->top < 0) {
+		DMERR("btree deletion stack empty");
+		return -EINVAL;
+	}
+
+	*f = s->spine + s->top;
+
+	return 0;
+}
+
+static int unprocessed_frames(struct del_stack *s)
+{
+	return s->top >= 0;
+}
+
+static int push_frame(struct del_stack *s, dm_block_t b, unsigned level)
+{
+	int r;
+	uint32_t ref_count;
+
+	if (s->top >= MAX_SPINE_DEPTH - 1) {
+		DMERR("btree deletion stack out of memory");
+		return -ENOMEM;
+	}
+
+	r = dm_tm_ref(s->tm, b, &ref_count);
+	if (r)
+		return r;
+
+	if (ref_count > 1)
+		/*
+		 * This is a shared node, so we can just decrement it's
+		 * reference counter and leave the children.
+		 */
+		dm_tm_dec(s->tm, b);
+
+	else {
+		struct frame *f = s->spine + ++s->top;
+
+		r = dm_tm_read_lock(s->tm, b, &btree_node_validator, &f->b);
+		if (r) {
+			s->top--;
+			return r;
+		}
+
+		f->n = dm_block_data(f->b);
+		f->level = level;
+		f->nr_children = le32_to_cpu(f->n->header.nr_entries);
+		f->current_child = 0;
+	}
+
+	return 0;
+}
+
+static void pop_frame(struct del_stack *s)
+{
+	struct frame *f = s->spine + s->top--;
+
+	dm_tm_dec(s->tm, dm_block_location(f->b));
+	dm_tm_unlock(s->tm, f->b);
+}
+
+int dm_btree_del(struct dm_btree_info *info, dm_block_t root)
+{
+	int r;
+	struct del_stack *s;
+
+	s = kmalloc(sizeof(*s), GFP_KERNEL);
+	if (!s)
+		return -ENOMEM;
+	s->tm = info->tm;
+	s->top = -1;
+
+	r = push_frame(s, root, 1);
+	if (r)
+		goto out;
+
+	while (unprocessed_frames(s)) {
+		uint32_t flags;
+		struct frame *f;
+		dm_block_t b;
+
+		r = top_frame(s, &f);
+		if (r)
+			goto out;
+
+		if (f->current_child >= f->nr_children) {
+			pop_frame(s);
+			continue;
+		}
+
+		flags = le32_to_cpu(f->n->header.flags);
+		if (flags & INTERNAL_NODE) {
+			b = value64(f->n, f->current_child);
+			f->current_child++;
+			r = push_frame(s, b, f->level);
+			if (r)
+				goto out;
+
+		} else if (f->level != (info->levels - 1)) {
+			b = value64(f->n, f->current_child);
+			f->current_child++;
+			r = push_frame(s, b, f->level + 1);
+			if (r)
+				goto out;
+
+		} else {
+			if (info->value_type.dec) {
+				unsigned i;
+
+				for (i = 0; i < f->nr_children; i++)
+					info->value_type.dec(info->value_type.context,
+							     value_ptr(f->n, i, info->value_type.size));
+			}
+			f->current_child = f->nr_children;
+		}
+	}
+
+out:
+	kfree(s);
+	return r;
+}
+EXPORT_SYMBOL_GPL(dm_btree_del);
+
+/*----------------------------------------------------------------*/
+
+static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key,
+			    int (*search_fn)(struct node *, uint64_t),
+			    uint64_t *result_key, void *v, size_t value_size)
+{
+	int i, r;
+	uint32_t flags, nr_entries;
+
+	do {
+		r = ro_step(s, block);
+		if (r < 0)
+			return r;
+
+		i = search_fn(ro_node(s), key);
+
+		flags = le32_to_cpu(ro_node(s)->header.flags);
+		nr_entries = le32_to_cpu(ro_node(s)->header.nr_entries);
+		if (i < 0 || i >= nr_entries)
+			return -ENODATA;
+
+		if (flags & INTERNAL_NODE)
+			block = value64(ro_node(s), i);
+
+	} while (!(flags & LEAF_NODE));
+
+	*result_key = le64_to_cpu(ro_node(s)->keys[i]);
+	memcpy(v, value_ptr(ro_node(s), i, value_size), value_size);
+
+	return 0;
+}
+
+int dm_btree_lookup(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, void *value_le)
+{
+	unsigned level, last_level = info->levels - 1;
+	int r = -ENODATA;
+	uint64_t rkey;
+	__le64 internal_value_le;
+	struct ro_spine spine;
+
+	init_ro_spine(&spine, info);
+	for (level = 0; level < info->levels; level++) {
+		size_t size;
+		void *value_p;
+
+		if (level == last_level) {
+			value_p = value_le;
+			size = info->value_type.size;
+
+		} else {
+			value_p = &internal_value_le;
+			size = sizeof(uint64_t);
+		}
+
+		r = btree_lookup_raw(&spine, root, keys[level],
+				     lower_bound, &rkey,
+				     value_p, size);
+
+		if (!r) {
+			if (rkey != keys[level]) {
+				exit_ro_spine(&spine);
+				return -ENODATA;
+			}
+		} else {
+			exit_ro_spine(&spine);
+			return r;
+		}
+
+		root = le64_to_cpu(internal_value_le);
+	}
+	exit_ro_spine(&spine);
+
+	return r;
+}
+EXPORT_SYMBOL_GPL(dm_btree_lookup);
+
+/*
+ * Splits a node by creating a sibling node and shifting half the nodes
+ * contents across.  Assumes there is a parent node, and it has room for
+ * another child.
+ *
+ * Before:
+ *	  +--------+
+ *	  | Parent |
+ *	  +--------+
+ *	     |
+ *	     v
+ *	+----------+
+ *	| A ++++++ |
+ *	+----------+
+ *
+ *
+ * After:
+ *		+--------+
+ *		| Parent |
+ *		+--------+
+ *		  |	|
+ *		  v	+------+
+ *	    +---------+	       |
+ *	    | A* +++  |	       v
+ *	    +---------+	  +-------+
+ *			  | B +++ |
+ *			  +-------+
+ *
+ * Where A* is a shadow of A.
+ */
+static int btree_split_sibling(struct shadow_spine *s, dm_block_t root,
+			       unsigned parent_index, uint64_t key)
+{
+	int r;
+	size_t size;
+	unsigned nr_left, nr_right;
+	struct dm_block *left, *right, *parent;
+	struct node *ln, *rn, *pn;
+	__le64 location;
+
+	left = shadow_current(s);
+
+	r = new_block(s->info, &right);
+	if (r < 0)
+		return r;
+
+	ln = dm_block_data(left);
+	rn = dm_block_data(right);
+
+	nr_left = le32_to_cpu(ln->header.nr_entries) / 2;
+	nr_right = le32_to_cpu(ln->header.nr_entries) - nr_left;
+
+	ln->header.nr_entries = cpu_to_le32(nr_left);
+
+	rn->header.flags = ln->header.flags;
+	rn->header.nr_entries = cpu_to_le32(nr_right);
+	rn->header.max_entries = ln->header.max_entries;
+	rn->header.value_size = ln->header.value_size;
+	memcpy(rn->keys, ln->keys + nr_left, nr_right * sizeof(rn->keys[0]));
+
+	size = le32_to_cpu(ln->header.flags) & INTERNAL_NODE ?
+		sizeof(uint64_t) : s->info->value_type.size;
+	memcpy(value_ptr(rn, 0, size), value_ptr(ln, nr_left, size),
+	       size * nr_right);
+
+	/*
+	 * Patch up the parent
+	 */
+	parent = shadow_parent(s);
+
+	pn = dm_block_data(parent);
+	location = cpu_to_le64(dm_block_location(left));
+	__dm_bless_for_disk(&location);
+	memcpy_disk(value_ptr(pn, parent_index, sizeof(__le64)),
+		    &location, sizeof(__le64));
+
+	location = cpu_to_le64(dm_block_location(right));
+	__dm_bless_for_disk(&location);
+
+	r = insert_at(sizeof(__le64), pn, parent_index + 1,
+		      le64_to_cpu(rn->keys[0]), &location);
+	if (r)
+		return r;
+
+	if (key < le64_to_cpu(rn->keys[0])) {
+		unlock_block(s->info, right);
+		s->nodes[1] = left;
+	} else {
+		unlock_block(s->info, left);
+		s->nodes[1] = right;
+	}
+
+	return 0;
+}
+
+/*
+ * Splits a node by creating two new children beneath the given node.
+ *
+ * Before:
+ *	  +----------+
+ *	  | A ++++++ |
+ *	  +----------+
+ *
+ *
+ * After:
+ *	+------------+
+ *	| A (shadow) |
+ *	+------------+
+ *	    |	|
+ *   +------+	+----+
+ *   |		     |
+ *   v		     v
+ * +-------+	 +-------+
+ * | B +++ |	 | C +++ |
+ * +-------+	 +-------+
+ */
+static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
+{
+	int r;
+	size_t size;
+	unsigned nr_left, nr_right;
+	struct dm_block *left, *right, *new_parent;
+	struct node *pn, *ln, *rn;
+	__le64 val;
+
+	new_parent = shadow_current(s);
+
+	r = new_block(s->info, &left);
+	if (r < 0)
+		return r;
+
+	r = new_block(s->info, &right);
+	if (r < 0) {
+		/* FIXME: put left */
+		return r;
+	}
+
+	pn = dm_block_data(new_parent);
+	ln = dm_block_data(left);
+	rn = dm_block_data(right);
+
+	nr_left = le32_to_cpu(pn->header.nr_entries) / 2;
+	nr_right = le32_to_cpu(pn->header.nr_entries) - nr_left;
+
+	ln->header.flags = pn->header.flags;
+	ln->header.nr_entries = cpu_to_le32(nr_left);
+	ln->header.max_entries = pn->header.max_entries;
+	ln->header.value_size = pn->header.value_size;
+
+	rn->header.flags = pn->header.flags;
+	rn->header.nr_entries = cpu_to_le32(nr_right);
+	rn->header.max_entries = pn->header.max_entries;
+	rn->header.value_size = pn->header.value_size;
+
+	memcpy(ln->keys, pn->keys, nr_left * sizeof(pn->keys[0]));
+	memcpy(rn->keys, pn->keys + nr_left, nr_right * sizeof(pn->keys[0]));
+
+	size = le32_to_cpu(pn->header.flags) & INTERNAL_NODE ?
+		sizeof(__le64) : s->info->value_type.size;
+	memcpy(value_ptr(ln, 0, size), value_ptr(pn, 0, size), nr_left * size);
+	memcpy(value_ptr(rn, 0, size), value_ptr(pn, nr_left, size),
+	       nr_right * size);
+
+	/* new_parent should just point to l and r now */
+	pn->header.flags = cpu_to_le32(INTERNAL_NODE);
+	pn->header.nr_entries = cpu_to_le32(2);
+	pn->header.max_entries = cpu_to_le32(
+		calc_max_entries(sizeof(__le64),
+				 dm_bm_block_size(
+					 dm_tm_get_bm(s->info->tm))));
+	pn->header.value_size = cpu_to_le32(sizeof(__le64));
+
+	val = cpu_to_le64(dm_block_location(left));
+	__dm_bless_for_disk(&val);
+	pn->keys[0] = ln->keys[0];
+	memcpy_disk(value_ptr(pn, 0, sizeof(__le64)), &val, sizeof(__le64));
+
+	val = cpu_to_le64(dm_block_location(right));
+	__dm_bless_for_disk(&val);
+	pn->keys[1] = rn->keys[0];
+	memcpy_disk(value_ptr(pn, 1, sizeof(__le64)), &val, sizeof(__le64));
+
+	/*
+	 * rejig the spine.  This is ugly, since it knows too
+	 * much about the spine
+	 */
+	if (s->nodes[0] != new_parent) {
+		unlock_block(s->info, s->nodes[0]);
+		s->nodes[0] = new_parent;
+	}
+	if (key < le64_to_cpu(rn->keys[0])) {
+		unlock_block(s->info, right);
+		s->nodes[1] = left;
+	} else {
+		unlock_block(s->info, left);
+		s->nodes[1] = right;
+	}
+	s->count = 2;
+
+	return 0;
+}
+
+static int btree_insert_raw(struct shadow_spine *s, dm_block_t root,
+			    struct dm_btree_value_type *vt,
+			    uint64_t key, unsigned *index)
+{
+	int r, i = *index, top = 1;
+	struct node *node;
+
+	for (;;) {
+		r = shadow_step(s, root, vt);
+		if (r < 0)
+			return r;
+
+		node = dm_block_data(shadow_current(s));
+
+		/*
+		 * We have to patch up the parent node, ugly, but I don't
+		 * see a way to do this automatically as part of the spine
+		 * op.
+		 */
+		if (shadow_has_parent(s) && i >= 0) { /* FIXME: second clause unness. */
+			__le64 location = cpu_to_le64(dm_block_location(shadow_current(s)));
+
+			__dm_bless_for_disk(&location);
+			memcpy_disk(value_ptr(dm_block_data(shadow_parent(s)), i, sizeof(uint64_t)),
+				    &location, sizeof(__le64));
+		}
+
+		node = dm_block_data(shadow_current(s));
+
+		if (node->header.nr_entries == node->header.max_entries) {
+			if (top)
+				r = btree_split_beneath(s, key);
+			else
+				r = btree_split_sibling(s, root, i, key);
+
+			if (r < 0)
+				return r;
+		}
+
+		node = dm_block_data(shadow_current(s));
+
+		i = lower_bound(node, key);
+
+		if (le32_to_cpu(node->header.flags) & LEAF_NODE)
+			break;
+
+		if (i < 0) {
+			/* change the bounds on the lowest key */
+			node->keys[0] = cpu_to_le64(key);
+			i = 0;
+		}
+
+		root = value64(node, i);
+		top = 0;
+	}
+
+	if (i < 0 || le64_to_cpu(node->keys[i]) != key)
+		i++;
+
+	*index = i;
+	return 0;
+}
+
+static int insert(struct dm_btree_info *info, dm_block_t root,
+		  uint64_t *keys, void *value, dm_block_t *new_root,
+		  int *inserted)
+		  __dm_written_to_disk(value)
+{
+	int r, need_insert;
+	unsigned level, index = -1, last_level = info->levels - 1;
+	dm_block_t block = root;
+	struct shadow_spine spine;
+	struct node *n;
+	struct dm_btree_value_type le64_type;
+
+	le64_type.context = NULL;
+	le64_type.size = sizeof(__le64);
+	le64_type.inc = NULL;
+	le64_type.dec = NULL;
+	le64_type.equal = NULL;
+
+	init_shadow_spine(&spine, info);
+
+	for (level = 0; level < (info->levels - 1); level++) {
+		r = btree_insert_raw(&spine, block, &le64_type, keys[level], &index);
+		if (r < 0)
+			goto bad;
+
+		n = dm_block_data(shadow_current(&spine));
+		need_insert = ((index >= le32_to_cpu(n->header.nr_entries)) ||
+			       (le64_to_cpu(n->keys[index]) != keys[level]));
+
+		if (need_insert) {
+			dm_block_t new_tree;
+			__le64 new_le;
+
+			r = dm_btree_empty(info, &new_tree);
+			if (r < 0)
+				goto bad;
+
+			new_le = cpu_to_le64(new_tree);
+			__dm_bless_for_disk(&new_le);
+
+			r = insert_at(sizeof(uint64_t), n, index,
+				      keys[level], &new_le);
+			if (r)
+				goto bad;
+		}
+
+		if (level < last_level)
+			block = value64(n, index);
+	}
+
+	r = btree_insert_raw(&spine, block, &info->value_type,
+			     keys[level], &index);
+	if (r < 0)
+		goto bad;
+
+	n = dm_block_data(shadow_current(&spine));
+	need_insert = ((index >= le32_to_cpu(n->header.nr_entries)) ||
+		       (le64_to_cpu(n->keys[index]) != keys[level]));
+
+	if (need_insert) {
+		if (inserted)
+			*inserted = 1;
+
+		r = insert_at(info->value_type.size, n, index,
+			      keys[level], value);
+		if (r)
+			goto bad_unblessed;
+	} else {
+		if (inserted)
+			*inserted = 0;
+
+		if (info->value_type.dec &&
+		    (!info->value_type.equal ||
+		     !info->value_type.equal(
+			     info->value_type.context,
+			     value_ptr(n, index, info->value_type.size),
+			     value))) {
+			info->value_type.dec(info->value_type.context,
+					     value_ptr(n, index, info->value_type.size));
+		}
+		memcpy_disk(value_ptr(n, index, info->value_type.size),
+			    value, info->value_type.size);
+	}
+
+	*new_root = shadow_root(&spine);
+	exit_shadow_spine(&spine);
+
+	return 0;
+
+bad:
+	__dm_unbless_for_disk(value);
+bad_unblessed:
+	exit_shadow_spine(&spine);
+	return r;
+}
+
+int dm_btree_insert(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, void *value, dm_block_t *new_root)
+		    __dm_written_to_disk(value)
+{
+	return insert(info, root, keys, value, new_root, NULL);
+}
+EXPORT_SYMBOL_GPL(dm_btree_insert);
+
+int dm_btree_insert_notify(struct dm_btree_info *info, dm_block_t root,
+			   uint64_t *keys, void *value, dm_block_t *new_root,
+			   int *inserted)
+			   __dm_written_to_disk(value)
+{
+	return insert(info, root, keys, value, new_root, inserted);
+}
+EXPORT_SYMBOL_GPL(dm_btree_insert_notify);
+
+/*----------------------------------------------------------------*/
+
+static int find_highest_key(struct ro_spine *s, dm_block_t block,
+			    uint64_t *result_key, dm_block_t *next_block)
+{
+	int i, r;
+	uint32_t flags;
+
+	do {
+		r = ro_step(s, block);
+		if (r < 0)
+			return r;
+
+		flags = le32_to_cpu(ro_node(s)->header.flags);
+		i = le32_to_cpu(ro_node(s)->header.nr_entries);
+		if (!i)
+			return -ENODATA;
+		else
+			i--;
+
+		*result_key = le64_to_cpu(ro_node(s)->keys[i]);
+		if (next_block || flags & INTERNAL_NODE)
+			block = value64(ro_node(s), i);
+
+	} while (flags & INTERNAL_NODE);
+
+	if (next_block)
+		*next_block = block;
+	return 0;
+}
+
+int dm_btree_find_highest_key(struct dm_btree_info *info, dm_block_t root,
+			      uint64_t *result_keys)
+{
+	int r = 0, count = 0, level;
+	struct ro_spine spine;
+
+	init_ro_spine(&spine, info);
+	for (level = 0; level < info->levels; level++) {
+		r = find_highest_key(&spine, root, result_keys + level,
+				     level == info->levels - 1 ? NULL : &root);
+		if (r == -ENODATA) {
+			r = 0;
+			break;
+
+		} else if (r)
+			break;
+
+		count++;
+	}
+	exit_ro_spine(&spine);
+
+	return r ? r : count;
+}
+EXPORT_SYMBOL_GPL(dm_btree_find_highest_key);
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-btree.h linux-libre-3.2-gnu/drivers/md/persistent-data/dm-btree.h
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-btree.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-btree.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+#ifndef _LINUX_DM_BTREE_H
+#define _LINUX_DM_BTREE_H
+
+#include "dm-block-manager.h"
+
+struct dm_transaction_manager;
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Annotations used to check on-disk metadata is handled as little-endian.
+ */
+#ifdef __CHECKER__
+#  define __dm_written_to_disk(x) __releases(x)
+#  define __dm_reads_from_disk(x) __acquires(x)
+#  define __dm_bless_for_disk(x) __acquire(x)
+#  define __dm_unbless_for_disk(x) __release(x)
+#else
+#  define __dm_written_to_disk(x)
+#  define __dm_reads_from_disk(x)
+#  define __dm_bless_for_disk(x)
+#  define __dm_unbless_for_disk(x)
+#endif
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Manipulates hierarchical B+ trees with 64-bit keys and arbitrary-sized
+ * values.
+ */
+
+/*
+ * Infomation about the values stored within the btree.
+ */
+struct dm_btree_value_type {
+	void *context;
+
+	/*
+	 * The size in bytes of each value.
+	 */
+	uint32_t size;
+
+	/*
+	 * Any of these methods can be safely set to NULL if you do not
+	 * need the corresponding feature.
+	 */
+
+	/*
+	 * The btree is making a duplicate of the value, for instance
+	 * because previously-shared btree nodes have now diverged.
+	 * @value argument is the new copy that the copy function may modify.
+	 * (Probably it just wants to increment a reference count
+	 * somewhere.) This method is _not_ called for insertion of a new
+	 * value: It is assumed the ref count is already 1.
+	 */
+	void (*inc)(void *context, void *value);
+
+	/*
+	 * This value is being deleted.  The btree takes care of freeing
+	 * the memory pointed to by @value.  Often the del function just
+	 * needs to decrement a reference count somewhere.
+	 */
+	void (*dec)(void *context, void *value);
+
+	/*
+	 * A test for equality between two values.  When a value is
+	 * overwritten with a new one, the old one has the dec method
+	 * called _unless_ the new and old value are deemed equal.
+	 */
+	int (*equal)(void *context, void *value1, void *value2);
+};
+
+/*
+ * The shape and contents of a btree.
+ */
+struct dm_btree_info {
+	struct dm_transaction_manager *tm;
+
+	/*
+	 * Number of nested btrees. (Not the depth of a single tree.)
+	 */
+	unsigned levels;
+	struct dm_btree_value_type value_type;
+};
+
+/*
+ * Set up an empty tree.  O(1).
+ */
+int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root);
+
+/*
+ * Delete a tree.  O(n) - this is the slow one!  It can also block, so
+ * please don't call it on an IO path.
+ */
+int dm_btree_del(struct dm_btree_info *info, dm_block_t root);
+
+/*
+ * All the lookup functions return -ENODATA if the key cannot be found.
+ */
+
+/*
+ * Tries to find a key that matches exactly.  O(ln(n))
+ */
+int dm_btree_lookup(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, void *value_le);
+
+/*
+ * Insertion (or overwrite an existing value).  O(ln(n))
+ */
+int dm_btree_insert(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, void *value, dm_block_t *new_root)
+		    __dm_written_to_disk(value);
+
+/*
+ * A variant of insert that indicates whether it actually inserted or just
+ * overwrote.  Useful if you're keeping track of the number of entries in a
+ * tree.
+ */
+int dm_btree_insert_notify(struct dm_btree_info *info, dm_block_t root,
+			   uint64_t *keys, void *value, dm_block_t *new_root,
+			   int *inserted)
+			   __dm_written_to_disk(value);
+
+/*
+ * Remove a key if present.  This doesn't remove empty sub trees.  Normally
+ * subtrees represent a separate entity, like a snapshot map, so this is
+ * correct behaviour.  O(ln(n)).
+ */
+int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, dm_block_t *new_root);
+
+/*
+ * Returns < 0 on failure.  Otherwise the number of key entries that have
+ * been filled out.  Remember trees can have zero entries, and as such have
+ * no highest key.
+ */
+int dm_btree_find_highest_key(struct dm_btree_info *info, dm_block_t root,
+			      uint64_t *result_keys);
+
+#endif	/* _LINUX_DM_BTREE_H */
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-btree-internal.h linux-libre-3.2-gnu/drivers/md/persistent-data/dm-btree-internal.h
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-btree-internal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-btree-internal.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_BTREE_INTERNAL_H
+#define DM_BTREE_INTERNAL_H
+
+#include "dm-btree.h"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * We'll need 2 accessor functions for n->csum and n->blocknr
+ * to support dm-btree-spine.c in that case.
+ */
+
+enum node_flags {
+	INTERNAL_NODE = 1,
+	LEAF_NODE = 1 << 1
+};
+
+/*
+ * Every btree node begins with this structure.  Make sure it's a multiple
+ * of 8-bytes in size, otherwise the 64bit keys will be mis-aligned.
+ */
+struct node_header {
+	__le32 csum;
+	__le32 flags;
+	__le64 blocknr; /* Block this node is supposed to live in. */
+
+	__le32 nr_entries;
+	__le32 max_entries;
+	__le32 value_size;
+	__le32 padding;
+} __packed;
+
+struct node {
+	struct node_header header;
+	__le64 keys[0];
+} __packed;
+
+
+void inc_children(struct dm_transaction_manager *tm, struct node *n,
+		  struct dm_btree_value_type *vt);
+
+int new_block(struct dm_btree_info *info, struct dm_block **result);
+int unlock_block(struct dm_btree_info *info, struct dm_block *b);
+
+/*
+ * Spines keep track of the rolling locks.  There are 2 variants, read-only
+ * and one that uses shadowing.  These are separate structs to allow the
+ * type checker to spot misuse, for example accidentally calling read_lock
+ * on a shadow spine.
+ */
+struct ro_spine {
+	struct dm_btree_info *info;
+
+	int count;
+	struct dm_block *nodes[2];
+};
+
+void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info);
+int exit_ro_spine(struct ro_spine *s);
+int ro_step(struct ro_spine *s, dm_block_t new_child);
+struct node *ro_node(struct ro_spine *s);
+
+struct shadow_spine {
+	struct dm_btree_info *info;
+
+	int count;
+	struct dm_block *nodes[2];
+
+	dm_block_t root;
+};
+
+void init_shadow_spine(struct shadow_spine *s, struct dm_btree_info *info);
+int exit_shadow_spine(struct shadow_spine *s);
+
+int shadow_step(struct shadow_spine *s, dm_block_t b,
+		struct dm_btree_value_type *vt);
+
+/*
+ * The spine must have at least one entry before calling this.
+ */
+struct dm_block *shadow_current(struct shadow_spine *s);
+
+/*
+ * The spine must have at least two entries before calling this.
+ */
+struct dm_block *shadow_parent(struct shadow_spine *s);
+
+int shadow_has_parent(struct shadow_spine *s);
+
+int shadow_root(struct shadow_spine *s);
+
+/*
+ * Some inlines.
+ */
+static inline __le64 *key_ptr(struct node *n, uint32_t index)
+{
+	return n->keys + index;
+}
+
+static inline void *value_base(struct node *n)
+{
+	return &n->keys[le32_to_cpu(n->header.max_entries)];
+}
+
+/*
+ * FIXME: Now that value size is stored in node we don't need the third parm.
+ */
+static inline void *value_ptr(struct node *n, uint32_t index, size_t value_size)
+{
+	BUG_ON(value_size != le32_to_cpu(n->header.value_size));
+	return value_base(n) + (value_size * index);
+}
+
+/*
+ * Assumes the values are suitably-aligned and converts to core format.
+ */
+static inline uint64_t value64(struct node *n, uint32_t index)
+{
+	__le64 *values_le = value_base(n);
+
+	return le64_to_cpu(values_le[index]);
+}
+
+/*
+ * Searching for a key within a single node.
+ */
+int lower_bound(struct node *n, uint64_t key);
+
+extern struct dm_block_validator btree_node_validator;
+
+#endif	/* DM_BTREE_INTERNAL_H */
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-btree-remove.c linux-libre-3.2-gnu/drivers/md/persistent-data/dm-btree-remove.c
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-btree-remove.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-btree-remove.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,566 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-btree.h"
+#include "dm-btree-internal.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/export.h>
+
+/*
+ * Removing an entry from a btree
+ * ==============================
+ *
+ * A very important constraint for our btree is that no node, except the
+ * root, may have fewer than a certain number of entries.
+ * (MIN_ENTRIES <= nr_entries <= MAX_ENTRIES).
+ *
+ * Ensuring this is complicated by the way we want to only ever hold the
+ * locks on 2 nodes concurrently, and only change nodes in a top to bottom
+ * fashion.
+ *
+ * Each node may have a left or right sibling.  When decending the spine,
+ * if a node contains only MIN_ENTRIES then we try and increase this to at
+ * least MIN_ENTRIES + 1.  We do this in the following ways:
+ *
+ * [A] No siblings => this can only happen if the node is the root, in which
+ *     case we copy the childs contents over the root.
+ *
+ * [B] No left sibling
+ *     ==> rebalance(node, right sibling)
+ *
+ * [C] No right sibling
+ *     ==> rebalance(left sibling, node)
+ *
+ * [D] Both siblings, total_entries(left, node, right) <= DEL_THRESHOLD
+ *     ==> delete node adding it's contents to left and right
+ *
+ * [E] Both siblings, total_entries(left, node, right) > DEL_THRESHOLD
+ *     ==> rebalance(left, node, right)
+ *
+ * After these operations it's possible that the our original node no
+ * longer contains the desired sub tree.  For this reason this rebalancing
+ * is performed on the children of the current node.  This also avoids
+ * having a special case for the root.
+ *
+ * Once this rebalancing has occurred we can then step into the child node
+ * for internal nodes.  Or delete the entry for leaf nodes.
+ */
+
+/*
+ * Some little utilities for moving node data around.
+ */
+static void node_shift(struct node *n, int shift)
+{
+	uint32_t nr_entries = le32_to_cpu(n->header.nr_entries);
+	uint32_t value_size = le32_to_cpu(n->header.value_size);
+
+	if (shift < 0) {
+		shift = -shift;
+		BUG_ON(shift > nr_entries);
+		BUG_ON((void *) key_ptr(n, shift) >= value_ptr(n, shift, value_size));
+		memmove(key_ptr(n, 0),
+			key_ptr(n, shift),
+			(nr_entries - shift) * sizeof(__le64));
+		memmove(value_ptr(n, 0, value_size),
+			value_ptr(n, shift, value_size),
+			(nr_entries - shift) * value_size);
+	} else {
+		BUG_ON(nr_entries + shift > le32_to_cpu(n->header.max_entries));
+		memmove(key_ptr(n, shift),
+			key_ptr(n, 0),
+			nr_entries * sizeof(__le64));
+		memmove(value_ptr(n, shift, value_size),
+			value_ptr(n, 0, value_size),
+			nr_entries * value_size);
+	}
+}
+
+static void node_copy(struct node *left, struct node *right, int shift)
+{
+	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
+	uint32_t value_size = le32_to_cpu(left->header.value_size);
+	BUG_ON(value_size != le32_to_cpu(right->header.value_size));
+
+	if (shift < 0) {
+		shift = -shift;
+		BUG_ON(nr_left + shift > le32_to_cpu(left->header.max_entries));
+		memcpy(key_ptr(left, nr_left),
+		       key_ptr(right, 0),
+		       shift * sizeof(__le64));
+		memcpy(value_ptr(left, nr_left, value_size),
+		       value_ptr(right, 0, value_size),
+		       shift * value_size);
+	} else {
+		BUG_ON(shift > le32_to_cpu(right->header.max_entries));
+		memcpy(key_ptr(right, 0),
+		       key_ptr(left, nr_left - shift),
+		       shift * sizeof(__le64));
+		memcpy(value_ptr(right, 0, value_size),
+		       value_ptr(left, nr_left - shift, value_size),
+		       shift * value_size);
+	}
+}
+
+/*
+ * Delete a specific entry from a leaf node.
+ */
+static void delete_at(struct node *n, unsigned index)
+{
+	unsigned nr_entries = le32_to_cpu(n->header.nr_entries);
+	unsigned nr_to_copy = nr_entries - (index + 1);
+	uint32_t value_size = le32_to_cpu(n->header.value_size);
+	BUG_ON(index >= nr_entries);
+
+	if (nr_to_copy) {
+		memmove(key_ptr(n, index),
+			key_ptr(n, index + 1),
+			nr_to_copy * sizeof(__le64));
+
+		memmove(value_ptr(n, index, value_size),
+			value_ptr(n, index + 1, value_size),
+			nr_to_copy * value_size);
+	}
+
+	n->header.nr_entries = cpu_to_le32(nr_entries - 1);
+}
+
+static unsigned del_threshold(struct node *n)
+{
+	return le32_to_cpu(n->header.max_entries) / 3;
+}
+
+static unsigned merge_threshold(struct node *n)
+{
+	/*
+	 * The extra one is because we know we're potentially going to
+	 * delete an entry.
+	 */
+	return 2 * (le32_to_cpu(n->header.max_entries) / 3) + 1;
+}
+
+struct child {
+	unsigned index;
+	struct dm_block *block;
+	struct node *n;
+};
+
+static struct dm_btree_value_type le64_type = {
+	.context = NULL,
+	.size = sizeof(__le64),
+	.inc = NULL,
+	.dec = NULL,
+	.equal = NULL
+};
+
+static int init_child(struct dm_btree_info *info, struct node *parent,
+		      unsigned index, struct child *result)
+{
+	int r, inc;
+	dm_block_t root;
+
+	result->index = index;
+	root = value64(parent, index);
+
+	r = dm_tm_shadow_block(info->tm, root, &btree_node_validator,
+			       &result->block, &inc);
+	if (r)
+		return r;
+
+	result->n = dm_block_data(result->block);
+
+	if (inc)
+		inc_children(info->tm, result->n, &le64_type);
+
+	*((__le64 *) value_ptr(parent, index, sizeof(__le64))) =
+		cpu_to_le64(dm_block_location(result->block));
+
+	return 0;
+}
+
+static int exit_child(struct dm_btree_info *info, struct child *c)
+{
+	return dm_tm_unlock(info->tm, c->block);
+}
+
+static void shift(struct node *left, struct node *right, int count)
+{
+	if (!count)
+		return;
+
+	if (count > 0) {
+		node_shift(right, count);
+		node_copy(left, right, count);
+	} else {
+		node_copy(left, right, count);
+		node_shift(right, count);
+	}
+
+	left->header.nr_entries =
+		cpu_to_le32(le32_to_cpu(left->header.nr_entries) - count);
+	BUG_ON(le32_to_cpu(left->header.nr_entries) > le32_to_cpu(left->header.max_entries));
+
+	right->header.nr_entries =
+		cpu_to_le32(le32_to_cpu(right->header.nr_entries) + count);
+	BUG_ON(le32_to_cpu(right->header.nr_entries) > le32_to_cpu(right->header.max_entries));
+}
+
+static void __rebalance2(struct dm_btree_info *info, struct node *parent,
+			 struct child *l, struct child *r)
+{
+	struct node *left = l->n;
+	struct node *right = r->n;
+	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
+	uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
+
+	if (nr_left + nr_right <= merge_threshold(left)) {
+		/*
+		 * Merge
+		 */
+		node_copy(left, right, -nr_right);
+		left->header.nr_entries = cpu_to_le32(nr_left + nr_right);
+		delete_at(parent, r->index);
+
+		/*
+		 * We need to decrement the right block, but not it's
+		 * children, since they're still referenced by left.
+		 */
+		dm_tm_dec(info->tm, dm_block_location(r->block));
+	} else {
+		/*
+		 * Rebalance.
+		 */
+		unsigned target_left = (nr_left + nr_right) / 2;
+		unsigned shift_ = nr_left - target_left;
+		BUG_ON(le32_to_cpu(left->header.max_entries) <= nr_left - shift_);
+		BUG_ON(le32_to_cpu(right->header.max_entries) <= nr_right + shift_);
+		shift(left, right, nr_left - target_left);
+		*key_ptr(parent, r->index) = right->keys[0];
+	}
+}
+
+static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
+		      unsigned left_index)
+{
+	int r;
+	struct node *parent;
+	struct child left, right;
+
+	parent = dm_block_data(shadow_current(s));
+
+	r = init_child(info, parent, left_index, &left);
+	if (r)
+		return r;
+
+	r = init_child(info, parent, left_index + 1, &right);
+	if (r) {
+		exit_child(info, &left);
+		return r;
+	}
+
+	__rebalance2(info, parent, &left, &right);
+
+	r = exit_child(info, &left);
+	if (r) {
+		exit_child(info, &right);
+		return r;
+	}
+
+	return exit_child(info, &right);
+}
+
+static void __rebalance3(struct dm_btree_info *info, struct node *parent,
+			 struct child *l, struct child *c, struct child *r)
+{
+	struct node *left = l->n;
+	struct node *center = c->n;
+	struct node *right = r->n;
+
+	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
+	uint32_t nr_center = le32_to_cpu(center->header.nr_entries);
+	uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
+	uint32_t max_entries = le32_to_cpu(left->header.max_entries);
+
+	unsigned target;
+
+	BUG_ON(left->header.max_entries != center->header.max_entries);
+	BUG_ON(center->header.max_entries != right->header.max_entries);
+
+	if (((nr_left + nr_center + nr_right) / 2) < merge_threshold(center)) {
+		/*
+		 * Delete center node:
+		 *
+		 * We dump as many entries from center as possible into
+		 * left, then the rest in right, then rebalance2.  This
+		 * wastes some cpu, but I want something simple atm.
+		 */
+		unsigned shift = min(max_entries - nr_left, nr_center);
+
+		BUG_ON(nr_left + shift > max_entries);
+		node_copy(left, center, -shift);
+		left->header.nr_entries = cpu_to_le32(nr_left + shift);
+
+		if (shift != nr_center) {
+			shift = nr_center - shift;
+			BUG_ON((nr_right + shift) >= max_entries);
+			node_shift(right, shift);
+			node_copy(center, right, shift);
+			right->header.nr_entries = cpu_to_le32(nr_right + shift);
+		}
+		*key_ptr(parent, r->index) = right->keys[0];
+
+		delete_at(parent, c->index);
+		r->index--;
+
+		dm_tm_dec(info->tm, dm_block_location(c->block));
+		__rebalance2(info, parent, l, r);
+
+		return;
+	}
+
+	/*
+	 * Rebalance
+	 */
+	target = (nr_left + nr_center + nr_right) / 3;
+	BUG_ON(target > max_entries);
+
+	/*
+	 * Adjust the left node
+	 */
+	shift(left, center, nr_left - target);
+
+	/*
+	 * Adjust the right node
+	 */
+	shift(center, right, target - nr_right);
+	*key_ptr(parent, c->index) = center->keys[0];
+	*key_ptr(parent, r->index) = right->keys[0];
+}
+
+static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
+		      unsigned left_index)
+{
+	int r;
+	struct node *parent = dm_block_data(shadow_current(s));
+	struct child left, center, right;
+
+	/*
+	 * FIXME: fill out an array?
+	 */
+	r = init_child(info, parent, left_index, &left);
+	if (r)
+		return r;
+
+	r = init_child(info, parent, left_index + 1, &center);
+	if (r) {
+		exit_child(info, &left);
+		return r;
+	}
+
+	r = init_child(info, parent, left_index + 2, &right);
+	if (r) {
+		exit_child(info, &left);
+		exit_child(info, &center);
+		return r;
+	}
+
+	__rebalance3(info, parent, &left, &center, &right);
+
+	r = exit_child(info, &left);
+	if (r) {
+		exit_child(info, &center);
+		exit_child(info, &right);
+		return r;
+	}
+
+	r = exit_child(info, &center);
+	if (r) {
+		exit_child(info, &right);
+		return r;
+	}
+
+	r = exit_child(info, &right);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static int get_nr_entries(struct dm_transaction_manager *tm,
+			  dm_block_t b, uint32_t *result)
+{
+	int r;
+	struct dm_block *block;
+	struct node *n;
+
+	r = dm_tm_read_lock(tm, b, &btree_node_validator, &block);
+	if (r)
+		return r;
+
+	n = dm_block_data(block);
+	*result = le32_to_cpu(n->header.nr_entries);
+
+	return dm_tm_unlock(tm, block);
+}
+
+static int rebalance_children(struct shadow_spine *s,
+			      struct dm_btree_info *info, uint64_t key)
+{
+	int i, r, has_left_sibling, has_right_sibling;
+	uint32_t child_entries;
+	struct node *n;
+
+	n = dm_block_data(shadow_current(s));
+
+	if (le32_to_cpu(n->header.nr_entries) == 1) {
+		struct dm_block *child;
+		dm_block_t b = value64(n, 0);
+
+		r = dm_tm_read_lock(info->tm, b, &btree_node_validator, &child);
+		if (r)
+			return r;
+
+		memcpy(n, dm_block_data(child),
+		       dm_bm_block_size(dm_tm_get_bm(info->tm)));
+		r = dm_tm_unlock(info->tm, child);
+		if (r)
+			return r;
+
+		dm_tm_dec(info->tm, dm_block_location(child));
+		return 0;
+	}
+
+	i = lower_bound(n, key);
+	if (i < 0)
+		return -ENODATA;
+
+	r = get_nr_entries(info->tm, value64(n, i), &child_entries);
+	if (r)
+		return r;
+
+	if (child_entries > del_threshold(n))
+		return 0;
+
+	has_left_sibling = i > 0;
+	has_right_sibling = i < (le32_to_cpu(n->header.nr_entries) - 1);
+
+	if (!has_left_sibling)
+		r = rebalance2(s, info, i);
+
+	else if (!has_right_sibling)
+		r = rebalance2(s, info, i - 1);
+
+	else
+		r = rebalance3(s, info, i - 1);
+
+	return r;
+}
+
+static int do_leaf(struct node *n, uint64_t key, unsigned *index)
+{
+	int i = lower_bound(n, key);
+
+	if ((i < 0) ||
+	    (i >= le32_to_cpu(n->header.nr_entries)) ||
+	    (le64_to_cpu(n->keys[i]) != key))
+		return -ENODATA;
+
+	*index = i;
+
+	return 0;
+}
+
+/*
+ * Prepares for removal from one level of the hierarchy.  The caller must
+ * call delete_at() to remove the entry at index.
+ */
+static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
+		      struct dm_btree_value_type *vt, dm_block_t root,
+		      uint64_t key, unsigned *index)
+{
+	int i = *index, r;
+	struct node *n;
+
+	for (;;) {
+		r = shadow_step(s, root, vt);
+		if (r < 0)
+			break;
+
+		/*
+		 * We have to patch up the parent node, ugly, but I don't
+		 * see a way to do this automatically as part of the spine
+		 * op.
+		 */
+		if (shadow_has_parent(s)) {
+			__le64 location = cpu_to_le64(dm_block_location(shadow_current(s)));
+			memcpy(value_ptr(dm_block_data(shadow_parent(s)), i, sizeof(__le64)),
+			       &location, sizeof(__le64));
+		}
+
+		n = dm_block_data(shadow_current(s));
+
+		if (le32_to_cpu(n->header.flags) & LEAF_NODE)
+			return do_leaf(n, key, index);
+
+		r = rebalance_children(s, info, key);
+		if (r)
+			break;
+
+		n = dm_block_data(shadow_current(s));
+		if (le32_to_cpu(n->header.flags) & LEAF_NODE)
+			return do_leaf(n, key, index);
+
+		i = lower_bound(n, key);
+
+		/*
+		 * We know the key is present, or else
+		 * rebalance_children would have returned
+		 * -ENODATA
+		 */
+		root = value64(n, i);
+	}
+
+	return r;
+}
+
+int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, dm_block_t *new_root)
+{
+	unsigned level, last_level = info->levels - 1;
+	int index = 0, r = 0;
+	struct shadow_spine spine;
+	struct node *n;
+
+	init_shadow_spine(&spine, info);
+	for (level = 0; level < info->levels; level++) {
+		r = remove_raw(&spine, info,
+			       (level == last_level ?
+				&info->value_type : &le64_type),
+			       root, keys[level], (unsigned *)&index);
+		if (r < 0)
+			break;
+
+		n = dm_block_data(shadow_current(&spine));
+		if (level != last_level) {
+			root = value64(n, index);
+			continue;
+		}
+
+		BUG_ON(index < 0 || index >= le32_to_cpu(n->header.nr_entries));
+
+		if (info->value_type.dec)
+			info->value_type.dec(info->value_type.context,
+					     value_ptr(n, index, info->value_type.size));
+
+		delete_at(n, index);
+	}
+
+	*new_root = shadow_root(&spine);
+	exit_shadow_spine(&spine);
+
+	return r;
+}
+EXPORT_SYMBOL_GPL(dm_btree_remove);
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-btree-spine.c linux-libre-3.2-gnu/drivers/md/persistent-data/dm-btree-spine.c
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-btree-spine.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-btree-spine.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-btree-internal.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "btree spine"
+
+/*----------------------------------------------------------------*/
+
+#define BTREE_CSUM_XOR 121107
+
+static int node_check(struct dm_block_validator *v,
+		      struct dm_block *b,
+		      size_t block_size);
+
+static void node_prepare_for_write(struct dm_block_validator *v,
+				   struct dm_block *b,
+				   size_t block_size)
+{
+	struct node *n = dm_block_data(b);
+	struct node_header *h = &n->header;
+
+	h->blocknr = cpu_to_le64(dm_block_location(b));
+	h->csum = cpu_to_le32(dm_bm_checksum(&h->flags,
+					     block_size - sizeof(__le32),
+					     BTREE_CSUM_XOR));
+
+	BUG_ON(node_check(v, b, 4096));
+}
+
+static int node_check(struct dm_block_validator *v,
+		      struct dm_block *b,
+		      size_t block_size)
+{
+	struct node *n = dm_block_data(b);
+	struct node_header *h = &n->header;
+	size_t value_size;
+	__le32 csum_disk;
+	uint32_t flags;
+
+	if (dm_block_location(b) != le64_to_cpu(h->blocknr)) {
+		DMERR("node_check failed blocknr %llu wanted %llu",
+		      le64_to_cpu(h->blocknr), dm_block_location(b));
+		return -ENOTBLK;
+	}
+
+	csum_disk = cpu_to_le32(dm_bm_checksum(&h->flags,
+					       block_size - sizeof(__le32),
+					       BTREE_CSUM_XOR));
+	if (csum_disk != h->csum) {
+		DMERR("node_check failed csum %u wanted %u",
+		      le32_to_cpu(csum_disk), le32_to_cpu(h->csum));
+		return -EILSEQ;
+	}
+
+	value_size = le32_to_cpu(h->value_size);
+
+	if (sizeof(struct node_header) +
+	    (sizeof(__le64) + value_size) * le32_to_cpu(h->max_entries) > block_size) {
+		DMERR("node_check failed: max_entries too large");
+		return -EILSEQ;
+	}
+
+	if (le32_to_cpu(h->nr_entries) > le32_to_cpu(h->max_entries)) {
+		DMERR("node_check failed, too many entries");
+		return -EILSEQ;
+	}
+
+	/*
+	 * The node must be either INTERNAL or LEAF.
+	 */
+	flags = le32_to_cpu(h->flags);
+	if (!(flags & INTERNAL_NODE) && !(flags & LEAF_NODE)) {
+		DMERR("node_check failed, node is neither INTERNAL or LEAF");
+		return -EILSEQ;
+	}
+
+	return 0;
+}
+
+struct dm_block_validator btree_node_validator = {
+	.name = "btree_node",
+	.prepare_for_write = node_prepare_for_write,
+	.check = node_check
+};
+
+/*----------------------------------------------------------------*/
+
+static int bn_read_lock(struct dm_btree_info *info, dm_block_t b,
+		 struct dm_block **result)
+{
+	return dm_tm_read_lock(info->tm, b, &btree_node_validator, result);
+}
+
+static int bn_shadow(struct dm_btree_info *info, dm_block_t orig,
+	      struct dm_btree_value_type *vt,
+	      struct dm_block **result)
+{
+	int r, inc;
+
+	r = dm_tm_shadow_block(info->tm, orig, &btree_node_validator,
+			       result, &inc);
+	if (!r && inc)
+		inc_children(info->tm, dm_block_data(*result), vt);
+
+	return r;
+}
+
+int new_block(struct dm_btree_info *info, struct dm_block **result)
+{
+	return dm_tm_new_block(info->tm, &btree_node_validator, result);
+}
+
+int unlock_block(struct dm_btree_info *info, struct dm_block *b)
+{
+	return dm_tm_unlock(info->tm, b);
+}
+
+/*----------------------------------------------------------------*/
+
+void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info)
+{
+	s->info = info;
+	s->count = 0;
+	s->nodes[0] = NULL;
+	s->nodes[1] = NULL;
+}
+
+int exit_ro_spine(struct ro_spine *s)
+{
+	int r = 0, i;
+
+	for (i = 0; i < s->count; i++) {
+		int r2 = unlock_block(s->info, s->nodes[i]);
+		if (r2 < 0)
+			r = r2;
+	}
+
+	return r;
+}
+
+int ro_step(struct ro_spine *s, dm_block_t new_child)
+{
+	int r;
+
+	if (s->count == 2) {
+		r = unlock_block(s->info, s->nodes[0]);
+		if (r < 0)
+			return r;
+		s->nodes[0] = s->nodes[1];
+		s->count--;
+	}
+
+	r = bn_read_lock(s->info, new_child, s->nodes + s->count);
+	if (!r)
+		s->count++;
+
+	return r;
+}
+
+struct node *ro_node(struct ro_spine *s)
+{
+	struct dm_block *block;
+
+	BUG_ON(!s->count);
+	block = s->nodes[s->count - 1];
+
+	return dm_block_data(block);
+}
+
+/*----------------------------------------------------------------*/
+
+void init_shadow_spine(struct shadow_spine *s, struct dm_btree_info *info)
+{
+	s->info = info;
+	s->count = 0;
+}
+
+int exit_shadow_spine(struct shadow_spine *s)
+{
+	int r = 0, i;
+
+	for (i = 0; i < s->count; i++) {
+		int r2 = unlock_block(s->info, s->nodes[i]);
+		if (r2 < 0)
+			r = r2;
+	}
+
+	return r;
+}
+
+int shadow_step(struct shadow_spine *s, dm_block_t b,
+		struct dm_btree_value_type *vt)
+{
+	int r;
+
+	if (s->count == 2) {
+		r = unlock_block(s->info, s->nodes[0]);
+		if (r < 0)
+			return r;
+		s->nodes[0] = s->nodes[1];
+		s->count--;
+	}
+
+	r = bn_shadow(s->info, b, vt, s->nodes + s->count);
+	if (!r) {
+		if (!s->count)
+			s->root = dm_block_location(s->nodes[0]);
+
+		s->count++;
+	}
+
+	return r;
+}
+
+struct dm_block *shadow_current(struct shadow_spine *s)
+{
+	BUG_ON(!s->count);
+
+	return s->nodes[s->count - 1];
+}
+
+struct dm_block *shadow_parent(struct shadow_spine *s)
+{
+	BUG_ON(s->count != 2);
+
+	return s->count == 2 ? s->nodes[0] : NULL;
+}
+
+int shadow_has_parent(struct shadow_spine *s)
+{
+	return s->count >= 2;
+}
+
+int shadow_root(struct shadow_spine *s)
+{
+	return s->root;
+}
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-persistent-data-internal.h linux-libre-3.2-gnu/drivers/md/persistent-data/dm-persistent-data-internal.h
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-persistent-data-internal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-persistent-data-internal.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _DM_PERSISTENT_DATA_INTERNAL_H
+#define _DM_PERSISTENT_DATA_INTERNAL_H
+
+#include "dm-block-manager.h"
+
+static inline unsigned dm_hash_block(dm_block_t b, unsigned hash_mask)
+{
+	const unsigned BIG_PRIME = 4294967291UL;
+
+	return (((unsigned) b) * BIG_PRIME) & hash_mask;
+}
+
+#endif	/* _PERSISTENT_DATA_INTERNAL_H */
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map-checker.c linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map-checker.c
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map-checker.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map-checker.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,438 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-space-map-checker.h"
+
+#include <linux/device-mapper.h>
+#include <linux/export.h>
+
+#ifdef CONFIG_DM_DEBUG_SPACE_MAPS
+
+#define DM_MSG_PREFIX "space map checker"
+
+/*----------------------------------------------------------------*/
+
+struct count_array {
+	dm_block_t nr;
+	dm_block_t nr_free;
+
+	uint32_t *counts;
+};
+
+static int ca_get_count(struct count_array *ca, dm_block_t b, uint32_t *count)
+{
+	if (b >= ca->nr)
+		return -EINVAL;
+
+	*count = ca->counts[b];
+	return 0;
+}
+
+static int ca_count_more_than_one(struct count_array *ca, dm_block_t b, int *r)
+{
+	if (b >= ca->nr)
+		return -EINVAL;
+
+	*r = ca->counts[b] > 1;
+	return 0;
+}
+
+static int ca_set_count(struct count_array *ca, dm_block_t b, uint32_t count)
+{
+	uint32_t old_count;
+
+	if (b >= ca->nr)
+		return -EINVAL;
+
+	old_count = ca->counts[b];
+
+	if (!count && old_count)
+		ca->nr_free++;
+
+	else if (count && !old_count)
+		ca->nr_free--;
+
+	ca->counts[b] = count;
+	return 0;
+}
+
+static int ca_inc_block(struct count_array *ca, dm_block_t b)
+{
+	if (b >= ca->nr)
+		return -EINVAL;
+
+	ca_set_count(ca, b, ca->counts[b] + 1);
+	return 0;
+}
+
+static int ca_dec_block(struct count_array *ca, dm_block_t b)
+{
+	if (b >= ca->nr)
+		return -EINVAL;
+
+	BUG_ON(ca->counts[b] == 0);
+	ca_set_count(ca, b, ca->counts[b] - 1);
+	return 0;
+}
+
+static int ca_create(struct count_array *ca, struct dm_space_map *sm)
+{
+	int r;
+	dm_block_t nr_blocks;
+
+	r = dm_sm_get_nr_blocks(sm, &nr_blocks);
+	if (r)
+		return r;
+
+	ca->nr = nr_blocks;
+	ca->nr_free = nr_blocks;
+	ca->counts = kzalloc(sizeof(*ca->counts) * nr_blocks, GFP_KERNEL);
+	if (!ca->counts)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int ca_load(struct count_array *ca, struct dm_space_map *sm)
+{
+	int r;
+	uint32_t count;
+	dm_block_t nr_blocks, i;
+
+	r = dm_sm_get_nr_blocks(sm, &nr_blocks);
+	if (r)
+		return r;
+
+	BUG_ON(ca->nr != nr_blocks);
+
+	DMWARN("Loading debug space map from disk.  This may take some time");
+	for (i = 0; i < nr_blocks; i++) {
+		r = dm_sm_get_count(sm, i, &count);
+		if (r) {
+			DMERR("load failed");
+			return r;
+		}
+
+		ca_set_count(ca, i, count);
+	}
+	DMWARN("Load complete");
+
+	return 0;
+}
+
+static int ca_extend(struct count_array *ca, dm_block_t extra_blocks)
+{
+	dm_block_t nr_blocks = ca->nr + extra_blocks;
+	uint32_t *counts = kzalloc(sizeof(*counts) * nr_blocks, GFP_KERNEL);
+	if (!counts)
+		return -ENOMEM;
+
+	memcpy(counts, ca->counts, sizeof(*counts) * ca->nr);
+	kfree(ca->counts);
+	ca->nr = nr_blocks;
+	ca->nr_free += extra_blocks;
+	ca->counts = counts;
+	return 0;
+}
+
+static int ca_commit(struct count_array *old, struct count_array *new)
+{
+	if (old->nr != new->nr) {
+		BUG_ON(old->nr > new->nr);
+		ca_extend(old, new->nr - old->nr);
+	}
+
+	BUG_ON(old->nr != new->nr);
+	old->nr_free = new->nr_free;
+	memcpy(old->counts, new->counts, sizeof(*old->counts) * old->nr);
+	return 0;
+}
+
+static void ca_destroy(struct count_array *ca)
+{
+	kfree(ca->counts);
+}
+
+/*----------------------------------------------------------------*/
+
+struct sm_checker {
+	struct dm_space_map sm;
+
+	struct count_array old_counts;
+	struct count_array counts;
+
+	struct dm_space_map *real_sm;
+};
+
+static void sm_checker_destroy(struct dm_space_map *sm)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+
+	dm_sm_destroy(smc->real_sm);
+	ca_destroy(&smc->old_counts);
+	ca_destroy(&smc->counts);
+	kfree(smc);
+}
+
+static int sm_checker_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_get_nr_blocks(smc->real_sm, count);
+	if (!r)
+		BUG_ON(smc->old_counts.nr != *count);
+	return r;
+}
+
+static int sm_checker_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_get_nr_free(smc->real_sm, count);
+	if (!r) {
+		/*
+		 * Slow, but we know it's correct.
+		 */
+		dm_block_t b, n = 0;
+		for (b = 0; b < smc->old_counts.nr; b++)
+			if (smc->old_counts.counts[b] == 0 &&
+			    smc->counts.counts[b] == 0)
+				n++;
+
+		if (n != *count)
+			DMERR("free block counts differ, checker %u, sm-disk:%u",
+			      (unsigned) n, (unsigned) *count);
+	}
+	return r;
+}
+
+static int sm_checker_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_new_block(smc->real_sm, b);
+
+	if (!r) {
+		BUG_ON(*b >= smc->old_counts.nr);
+		BUG_ON(smc->old_counts.counts[*b] != 0);
+		BUG_ON(*b >= smc->counts.nr);
+		BUG_ON(smc->counts.counts[*b] != 0);
+		ca_set_count(&smc->counts, *b, 1);
+	}
+
+	return r;
+}
+
+static int sm_checker_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_inc_block(smc->real_sm, b);
+	int r2 = ca_inc_block(&smc->counts, b);
+	BUG_ON(r != r2);
+	return r;
+}
+
+static int sm_checker_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_dec_block(smc->real_sm, b);
+	int r2 = ca_dec_block(&smc->counts, b);
+	BUG_ON(r != r2);
+	return r;
+}
+
+static int sm_checker_get_count(struct dm_space_map *sm, dm_block_t b, uint32_t *result)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	uint32_t result2 = 0;
+	int r = dm_sm_get_count(smc->real_sm, b, result);
+	int r2 = ca_get_count(&smc->counts, b, &result2);
+
+	BUG_ON(r != r2);
+	if (!r)
+		BUG_ON(*result != result2);
+	return r;
+}
+
+static int sm_checker_count_more_than_one(struct dm_space_map *sm, dm_block_t b, int *result)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int result2 = 0;
+	int r = dm_sm_count_is_more_than_one(smc->real_sm, b, result);
+	int r2 = ca_count_more_than_one(&smc->counts, b, &result2);
+
+	BUG_ON(r != r2);
+	if (!r)
+		BUG_ON(!(*result) && result2);
+	return r;
+}
+
+static int sm_checker_set_count(struct dm_space_map *sm, dm_block_t b, uint32_t count)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	uint32_t old_rc;
+	int r = dm_sm_set_count(smc->real_sm, b, count);
+	int r2;
+
+	BUG_ON(b >= smc->counts.nr);
+	old_rc = smc->counts.counts[b];
+	r2 = ca_set_count(&smc->counts, b, count);
+	BUG_ON(r != r2);
+
+	return r;
+}
+
+static int sm_checker_commit(struct dm_space_map *sm)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r;
+
+	r = dm_sm_commit(smc->real_sm);
+	if (r)
+		return r;
+
+	r = ca_commit(&smc->old_counts, &smc->counts);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static int sm_checker_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_extend(smc->real_sm, extra_blocks);
+	if (r)
+		return r;
+
+	return ca_extend(&smc->counts, extra_blocks);
+}
+
+static int sm_checker_root_size(struct dm_space_map *sm, size_t *result)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	return dm_sm_root_size(smc->real_sm, result);
+}
+
+static int sm_checker_copy_root(struct dm_space_map *sm, void *copy_to_here_le, size_t len)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	return dm_sm_copy_root(smc->real_sm, copy_to_here_le, len);
+}
+
+/*----------------------------------------------------------------*/
+
+static struct dm_space_map ops_ = {
+	.destroy = sm_checker_destroy,
+	.get_nr_blocks = sm_checker_get_nr_blocks,
+	.get_nr_free = sm_checker_get_nr_free,
+	.inc_block = sm_checker_inc_block,
+	.dec_block = sm_checker_dec_block,
+	.new_block = sm_checker_new_block,
+	.get_count = sm_checker_get_count,
+	.count_is_more_than_one = sm_checker_count_more_than_one,
+	.set_count = sm_checker_set_count,
+	.commit = sm_checker_commit,
+	.extend = sm_checker_extend,
+	.root_size = sm_checker_root_size,
+	.copy_root = sm_checker_copy_root
+};
+
+struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm)
+{
+	int r;
+	struct sm_checker *smc;
+
+	if (!sm)
+		return NULL;
+
+	smc = kmalloc(sizeof(*smc), GFP_KERNEL);
+	if (!smc)
+		return NULL;
+
+	memcpy(&smc->sm, &ops_, sizeof(smc->sm));
+	r = ca_create(&smc->old_counts, sm);
+	if (r) {
+		kfree(smc);
+		return NULL;
+	}
+
+	r = ca_create(&smc->counts, sm);
+	if (r) {
+		ca_destroy(&smc->old_counts);
+		kfree(smc);
+		return NULL;
+	}
+
+	smc->real_sm = sm;
+
+	r = ca_load(&smc->counts, sm);
+	if (r) {
+		ca_destroy(&smc->counts);
+		ca_destroy(&smc->old_counts);
+		kfree(smc);
+		return NULL;
+	}
+
+	r = ca_commit(&smc->old_counts, &smc->counts);
+	if (r) {
+		ca_destroy(&smc->counts);
+		ca_destroy(&smc->old_counts);
+		kfree(smc);
+		return NULL;
+	}
+
+	return &smc->sm;
+}
+EXPORT_SYMBOL_GPL(dm_sm_checker_create);
+
+struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm)
+{
+	int r;
+	struct sm_checker *smc;
+
+	if (!sm)
+		return NULL;
+
+	smc = kmalloc(sizeof(*smc), GFP_KERNEL);
+	if (!smc)
+		return NULL;
+
+	memcpy(&smc->sm, &ops_, sizeof(smc->sm));
+	r = ca_create(&smc->old_counts, sm);
+	if (r) {
+		kfree(smc);
+		return NULL;
+	}
+
+	r = ca_create(&smc->counts, sm);
+	if (r) {
+		ca_destroy(&smc->old_counts);
+		kfree(smc);
+		return NULL;
+	}
+
+	smc->real_sm = sm;
+	return &smc->sm;
+}
+EXPORT_SYMBOL_GPL(dm_sm_checker_create_fresh);
+
+/*----------------------------------------------------------------*/
+
+#else
+
+struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm)
+{
+	return sm;
+}
+EXPORT_SYMBOL_GPL(dm_sm_checker_create);
+
+struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm)
+{
+	return sm;
+}
+EXPORT_SYMBOL_GPL(dm_sm_checker_create_fresh);
+
+/*----------------------------------------------------------------*/
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map-checker.h linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map-checker.h
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map-checker.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map-checker.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef SNAPSHOTS_SPACE_MAP_CHECKER_H
+#define SNAPSHOTS_SPACE_MAP_CHECKER_H
+
+#include "dm-space-map.h"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * This space map wraps a real on-disk space map, and verifies all of its
+ * operations.  It uses a lot of memory, so only use if you have a specific
+ * problem that you're debugging.
+ *
+ * Ownership of @sm passes.
+ */
+struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm);
+struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm);
+
+/*----------------------------------------------------------------*/
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map-common.c linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map-common.c
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map-common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,705 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-space-map-common.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/bitops.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "space map common"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Index validator.
+ */
+#define INDEX_CSUM_XOR 160478
+
+static void index_prepare_for_write(struct dm_block_validator *v,
+				    struct dm_block *b,
+				    size_t block_size)
+{
+	struct disk_metadata_index *mi_le = dm_block_data(b);
+
+	mi_le->blocknr = cpu_to_le64(dm_block_location(b));
+	mi_le->csum = cpu_to_le32(dm_bm_checksum(&mi_le->padding,
+						 block_size - sizeof(__le32),
+						 INDEX_CSUM_XOR));
+}
+
+static int index_check(struct dm_block_validator *v,
+		       struct dm_block *b,
+		       size_t block_size)
+{
+	struct disk_metadata_index *mi_le = dm_block_data(b);
+	__le32 csum_disk;
+
+	if (dm_block_location(b) != le64_to_cpu(mi_le->blocknr)) {
+		DMERR("index_check failed blocknr %llu wanted %llu",
+		      le64_to_cpu(mi_le->blocknr), dm_block_location(b));
+		return -ENOTBLK;
+	}
+
+	csum_disk = cpu_to_le32(dm_bm_checksum(&mi_le->padding,
+					       block_size - sizeof(__le32),
+					       INDEX_CSUM_XOR));
+	if (csum_disk != mi_le->csum) {
+		DMERR("index_check failed csum %u wanted %u",
+		      le32_to_cpu(csum_disk), le32_to_cpu(mi_le->csum));
+		return -EILSEQ;
+	}
+
+	return 0;
+}
+
+static struct dm_block_validator index_validator = {
+	.name = "index",
+	.prepare_for_write = index_prepare_for_write,
+	.check = index_check
+};
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Bitmap validator
+ */
+#define BITMAP_CSUM_XOR 240779
+
+static void bitmap_prepare_for_write(struct dm_block_validator *v,
+				     struct dm_block *b,
+				     size_t block_size)
+{
+	struct disk_bitmap_header *disk_header = dm_block_data(b);
+
+	disk_header->blocknr = cpu_to_le64(dm_block_location(b));
+	disk_header->csum = cpu_to_le32(dm_bm_checksum(&disk_header->not_used,
+						       block_size - sizeof(__le32),
+						       BITMAP_CSUM_XOR));
+}
+
+static int bitmap_check(struct dm_block_validator *v,
+			struct dm_block *b,
+			size_t block_size)
+{
+	struct disk_bitmap_header *disk_header = dm_block_data(b);
+	__le32 csum_disk;
+
+	if (dm_block_location(b) != le64_to_cpu(disk_header->blocknr)) {
+		DMERR("bitmap check failed blocknr %llu wanted %llu",
+		      le64_to_cpu(disk_header->blocknr), dm_block_location(b));
+		return -ENOTBLK;
+	}
+
+	csum_disk = cpu_to_le32(dm_bm_checksum(&disk_header->not_used,
+					       block_size - sizeof(__le32),
+					       BITMAP_CSUM_XOR));
+	if (csum_disk != disk_header->csum) {
+		DMERR("bitmap check failed csum %u wanted %u",
+		      le32_to_cpu(csum_disk), le32_to_cpu(disk_header->csum));
+		return -EILSEQ;
+	}
+
+	return 0;
+}
+
+static struct dm_block_validator dm_sm_bitmap_validator = {
+	.name = "sm_bitmap",
+	.prepare_for_write = bitmap_prepare_for_write,
+	.check = bitmap_check
+};
+
+/*----------------------------------------------------------------*/
+
+#define ENTRIES_PER_WORD 32
+#define ENTRIES_SHIFT	5
+
+static void *dm_bitmap_data(struct dm_block *b)
+{
+	return dm_block_data(b) + sizeof(struct disk_bitmap_header);
+}
+
+#define WORD_MASK_HIGH 0xAAAAAAAAAAAAAAAAULL
+
+static unsigned bitmap_word_used(void *addr, unsigned b)
+{
+	__le64 *words_le = addr;
+	__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
+
+	uint64_t bits = le64_to_cpu(*w_le);
+	uint64_t mask = (bits + WORD_MASK_HIGH + 1) & WORD_MASK_HIGH;
+
+	return !(~bits & mask);
+}
+
+static unsigned sm_lookup_bitmap(void *addr, unsigned b)
+{
+	__le64 *words_le = addr;
+	__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
+	unsigned hi, lo;
+
+	b = (b & (ENTRIES_PER_WORD - 1)) << 1;
+	hi = !!test_bit_le(b, (void *) w_le);
+	lo = !!test_bit_le(b + 1, (void *) w_le);
+	return (hi << 1) | lo;
+}
+
+static void sm_set_bitmap(void *addr, unsigned b, unsigned val)
+{
+	__le64 *words_le = addr;
+	__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
+
+	b = (b & (ENTRIES_PER_WORD - 1)) << 1;
+
+	if (val & 2)
+		__set_bit_le(b, (void *) w_le);
+	else
+		__clear_bit_le(b, (void *) w_le);
+
+	if (val & 1)
+		__set_bit_le(b + 1, (void *) w_le);
+	else
+		__clear_bit_le(b + 1, (void *) w_le);
+}
+
+static int sm_find_free(void *addr, unsigned begin, unsigned end,
+			unsigned *result)
+{
+	while (begin < end) {
+		if (!(begin & (ENTRIES_PER_WORD - 1)) &&
+		    bitmap_word_used(addr, begin)) {
+			begin += ENTRIES_PER_WORD;
+			continue;
+		}
+
+		if (!sm_lookup_bitmap(addr, begin)) {
+			*result = begin;
+			return 0;
+		}
+
+		begin++;
+	}
+
+	return -ENOSPC;
+}
+
+/*----------------------------------------------------------------*/
+
+static int sm_ll_init(struct ll_disk *ll, struct dm_transaction_manager *tm)
+{
+	ll->tm = tm;
+
+	ll->bitmap_info.tm = tm;
+	ll->bitmap_info.levels = 1;
+
+	/*
+	 * Because the new bitmap blocks are created via a shadow
+	 * operation, the old entry has already had its reference count
+	 * decremented and we don't need the btree to do any bookkeeping.
+	 */
+	ll->bitmap_info.value_type.size = sizeof(struct disk_index_entry);
+	ll->bitmap_info.value_type.inc = NULL;
+	ll->bitmap_info.value_type.dec = NULL;
+	ll->bitmap_info.value_type.equal = NULL;
+
+	ll->ref_count_info.tm = tm;
+	ll->ref_count_info.levels = 1;
+	ll->ref_count_info.value_type.size = sizeof(uint32_t);
+	ll->ref_count_info.value_type.inc = NULL;
+	ll->ref_count_info.value_type.dec = NULL;
+	ll->ref_count_info.value_type.equal = NULL;
+
+	ll->block_size = dm_bm_block_size(dm_tm_get_bm(tm));
+
+	if (ll->block_size > (1 << 30)) {
+		DMERR("block size too big to hold bitmaps");
+		return -EINVAL;
+	}
+
+	ll->entries_per_block = (ll->block_size - sizeof(struct disk_bitmap_header)) *
+		ENTRIES_PER_BYTE;
+	ll->nr_blocks = 0;
+	ll->bitmap_root = 0;
+	ll->ref_count_root = 0;
+
+	return 0;
+}
+
+int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks)
+{
+	int r;
+	dm_block_t i, nr_blocks, nr_indexes;
+	unsigned old_blocks, blocks;
+
+	nr_blocks = ll->nr_blocks + extra_blocks;
+	old_blocks = dm_sector_div_up(ll->nr_blocks, ll->entries_per_block);
+	blocks = dm_sector_div_up(nr_blocks, ll->entries_per_block);
+
+	nr_indexes = dm_sector_div_up(nr_blocks, ll->entries_per_block);
+	if (nr_indexes > ll->max_entries(ll)) {
+		DMERR("space map too large");
+		return -EINVAL;
+	}
+
+	for (i = old_blocks; i < blocks; i++) {
+		struct dm_block *b;
+		struct disk_index_entry idx;
+
+		r = dm_tm_new_block(ll->tm, &dm_sm_bitmap_validator, &b);
+		if (r < 0)
+			return r;
+		idx.blocknr = cpu_to_le64(dm_block_location(b));
+
+		r = dm_tm_unlock(ll->tm, b);
+		if (r < 0)
+			return r;
+
+		idx.nr_free = cpu_to_le32(ll->entries_per_block);
+		idx.none_free_before = 0;
+
+		r = ll->save_ie(ll, i, &idx);
+		if (r < 0)
+			return r;
+	}
+
+	ll->nr_blocks = nr_blocks;
+	return 0;
+}
+
+int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result)
+{
+	int r;
+	dm_block_t index = b;
+	struct disk_index_entry ie_disk;
+	struct dm_block *blk;
+
+	b = do_div(index, ll->entries_per_block);
+	r = ll->load_ie(ll, index, &ie_disk);
+	if (r < 0)
+		return r;
+
+	r = dm_tm_read_lock(ll->tm, le64_to_cpu(ie_disk.blocknr),
+			    &dm_sm_bitmap_validator, &blk);
+	if (r < 0)
+		return r;
+
+	*result = sm_lookup_bitmap(dm_bitmap_data(blk), b);
+
+	return dm_tm_unlock(ll->tm, blk);
+}
+
+int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result)
+{
+	__le32 le_rc;
+	int r = sm_ll_lookup_bitmap(ll, b, result);
+
+	if (r)
+		return r;
+
+	if (*result != 3)
+		return r;
+
+	r = dm_btree_lookup(&ll->ref_count_info, ll->ref_count_root, &b, &le_rc);
+	if (r < 0)
+		return r;
+
+	*result = le32_to_cpu(le_rc);
+
+	return r;
+}
+
+int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
+			  dm_block_t end, dm_block_t *result)
+{
+	int r;
+	struct disk_index_entry ie_disk;
+	dm_block_t i, index_begin = begin;
+	dm_block_t index_end = dm_sector_div_up(end, ll->entries_per_block);
+
+	/*
+	 * FIXME: Use shifts
+	 */
+	begin = do_div(index_begin, ll->entries_per_block);
+	end = do_div(end, ll->entries_per_block);
+
+	for (i = index_begin; i < index_end; i++, begin = 0) {
+		struct dm_block *blk;
+		unsigned position;
+		uint32_t bit_end;
+
+		r = ll->load_ie(ll, i, &ie_disk);
+		if (r < 0)
+			return r;
+
+		if (le32_to_cpu(ie_disk.nr_free) == 0)
+			continue;
+
+		r = dm_tm_read_lock(ll->tm, le64_to_cpu(ie_disk.blocknr),
+				    &dm_sm_bitmap_validator, &blk);
+		if (r < 0)
+			return r;
+
+		bit_end = (i == index_end - 1) ?  end : ll->entries_per_block;
+
+		r = sm_find_free(dm_bitmap_data(blk),
+				 max_t(unsigned, begin, le32_to_cpu(ie_disk.none_free_before)),
+				 bit_end, &position);
+		if (r == -ENOSPC) {
+			/*
+			 * This might happen because we started searching
+			 * part way through the bitmap.
+			 */
+			dm_tm_unlock(ll->tm, blk);
+			continue;
+
+		} else if (r < 0) {
+			dm_tm_unlock(ll->tm, blk);
+			return r;
+		}
+
+		r = dm_tm_unlock(ll->tm, blk);
+		if (r < 0)
+			return r;
+
+		*result = i * ll->entries_per_block + (dm_block_t) position;
+		return 0;
+	}
+
+	return -ENOSPC;
+}
+
+int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
+		 uint32_t ref_count, enum allocation_event *ev)
+{
+	int r;
+	uint32_t bit, old;
+	struct dm_block *nb;
+	dm_block_t index = b;
+	struct disk_index_entry ie_disk;
+	void *bm_le;
+	int inc;
+
+	bit = do_div(index, ll->entries_per_block);
+	r = ll->load_ie(ll, index, &ie_disk);
+	if (r < 0)
+		return r;
+
+	r = dm_tm_shadow_block(ll->tm, le64_to_cpu(ie_disk.blocknr),
+			       &dm_sm_bitmap_validator, &nb, &inc);
+	if (r < 0) {
+		DMERR("dm_tm_shadow_block() failed");
+		return r;
+	}
+	ie_disk.blocknr = cpu_to_le64(dm_block_location(nb));
+
+	bm_le = dm_bitmap_data(nb);
+	old = sm_lookup_bitmap(bm_le, bit);
+
+	if (ref_count <= 2) {
+		sm_set_bitmap(bm_le, bit, ref_count);
+
+		r = dm_tm_unlock(ll->tm, nb);
+		if (r < 0)
+			return r;
+
+#if 0
+		/* FIXME: dm_btree_remove doesn't handle this yet */
+		if (old > 2) {
+			r = dm_btree_remove(&ll->ref_count_info,
+					    ll->ref_count_root,
+					    &b, &ll->ref_count_root);
+			if (r)
+				return r;
+		}
+#endif
+
+	} else {
+		__le32 le_rc = cpu_to_le32(ref_count);
+
+		sm_set_bitmap(bm_le, bit, 3);
+		r = dm_tm_unlock(ll->tm, nb);
+		if (r < 0)
+			return r;
+
+		__dm_bless_for_disk(&le_rc);
+		r = dm_btree_insert(&ll->ref_count_info, ll->ref_count_root,
+				    &b, &le_rc, &ll->ref_count_root);
+		if (r < 0) {
+			DMERR("ref count insert failed");
+			return r;
+		}
+	}
+
+	if (ref_count && !old) {
+		*ev = SM_ALLOC;
+		ll->nr_allocated++;
+		ie_disk.nr_free = cpu_to_le32(le32_to_cpu(ie_disk.nr_free) - 1);
+		if (le32_to_cpu(ie_disk.none_free_before) == bit)
+			ie_disk.none_free_before = cpu_to_le32(bit + 1);
+
+	} else if (old && !ref_count) {
+		*ev = SM_FREE;
+		ll->nr_allocated--;
+		ie_disk.nr_free = cpu_to_le32(le32_to_cpu(ie_disk.nr_free) + 1);
+		ie_disk.none_free_before = cpu_to_le32(min(le32_to_cpu(ie_disk.none_free_before), bit));
+	}
+
+	return ll->save_ie(ll, index, &ie_disk);
+}
+
+int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
+{
+	int r;
+	uint32_t rc;
+
+	r = sm_ll_lookup(ll, b, &rc);
+	if (r)
+		return r;
+
+	return sm_ll_insert(ll, b, rc + 1, ev);
+}
+
+int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
+{
+	int r;
+	uint32_t rc;
+
+	r = sm_ll_lookup(ll, b, &rc);
+	if (r)
+		return r;
+
+	if (!rc)
+		return -EINVAL;
+
+	return sm_ll_insert(ll, b, rc - 1, ev);
+}
+
+int sm_ll_commit(struct ll_disk *ll)
+{
+	return ll->commit(ll);
+}
+
+/*----------------------------------------------------------------*/
+
+static int metadata_ll_load_ie(struct ll_disk *ll, dm_block_t index,
+			       struct disk_index_entry *ie)
+{
+	memcpy(ie, ll->mi_le.index + index, sizeof(*ie));
+	return 0;
+}
+
+static int metadata_ll_save_ie(struct ll_disk *ll, dm_block_t index,
+			       struct disk_index_entry *ie)
+{
+	memcpy(ll->mi_le.index + index, ie, sizeof(*ie));
+	return 0;
+}
+
+static int metadata_ll_init_index(struct ll_disk *ll)
+{
+	int r;
+	struct dm_block *b;
+
+	r = dm_tm_new_block(ll->tm, &index_validator, &b);
+	if (r < 0)
+		return r;
+
+	memcpy(dm_block_data(b), &ll->mi_le, sizeof(ll->mi_le));
+	ll->bitmap_root = dm_block_location(b);
+
+	return dm_tm_unlock(ll->tm, b);
+}
+
+static int metadata_ll_open(struct ll_disk *ll)
+{
+	int r;
+	struct dm_block *block;
+
+	r = dm_tm_read_lock(ll->tm, ll->bitmap_root,
+			    &index_validator, &block);
+	if (r)
+		return r;
+
+	memcpy(&ll->mi_le, dm_block_data(block), sizeof(ll->mi_le));
+	return dm_tm_unlock(ll->tm, block);
+}
+
+static dm_block_t metadata_ll_max_entries(struct ll_disk *ll)
+{
+	return MAX_METADATA_BITMAPS;
+}
+
+static int metadata_ll_commit(struct ll_disk *ll)
+{
+	int r, inc;
+	struct dm_block *b;
+
+	r = dm_tm_shadow_block(ll->tm, ll->bitmap_root, &index_validator, &b, &inc);
+	if (r)
+		return r;
+
+	memcpy(dm_block_data(b), &ll->mi_le, sizeof(ll->mi_le));
+	ll->bitmap_root = dm_block_location(b);
+
+	return dm_tm_unlock(ll->tm, b);
+}
+
+int sm_ll_new_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm)
+{
+	int r;
+
+	r = sm_ll_init(ll, tm);
+	if (r < 0)
+		return r;
+
+	ll->load_ie = metadata_ll_load_ie;
+	ll->save_ie = metadata_ll_save_ie;
+	ll->init_index = metadata_ll_init_index;
+	ll->open_index = metadata_ll_open;
+	ll->max_entries = metadata_ll_max_entries;
+	ll->commit = metadata_ll_commit;
+
+	ll->nr_blocks = 0;
+	ll->nr_allocated = 0;
+
+	r = ll->init_index(ll);
+	if (r < 0)
+		return r;
+
+	r = dm_btree_empty(&ll->ref_count_info, &ll->ref_count_root);
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+
+int sm_ll_open_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm,
+			void *root_le, size_t len)
+{
+	int r;
+	struct disk_sm_root *smr = root_le;
+
+	if (len < sizeof(struct disk_sm_root)) {
+		DMERR("sm_metadata root too small");
+		return -ENOMEM;
+	}
+
+	r = sm_ll_init(ll, tm);
+	if (r < 0)
+		return r;
+
+	ll->load_ie = metadata_ll_load_ie;
+	ll->save_ie = metadata_ll_save_ie;
+	ll->init_index = metadata_ll_init_index;
+	ll->open_index = metadata_ll_open;
+	ll->max_entries = metadata_ll_max_entries;
+	ll->commit = metadata_ll_commit;
+
+	ll->nr_blocks = le64_to_cpu(smr->nr_blocks);
+	ll->nr_allocated = le64_to_cpu(smr->nr_allocated);
+	ll->bitmap_root = le64_to_cpu(smr->bitmap_root);
+	ll->ref_count_root = le64_to_cpu(smr->ref_count_root);
+
+	return ll->open_index(ll);
+}
+
+/*----------------------------------------------------------------*/
+
+static int disk_ll_load_ie(struct ll_disk *ll, dm_block_t index,
+			   struct disk_index_entry *ie)
+{
+	return dm_btree_lookup(&ll->bitmap_info, ll->bitmap_root, &index, ie);
+}
+
+static int disk_ll_save_ie(struct ll_disk *ll, dm_block_t index,
+			   struct disk_index_entry *ie)
+{
+	__dm_bless_for_disk(ie);
+	return dm_btree_insert(&ll->bitmap_info, ll->bitmap_root,
+			       &index, ie, &ll->bitmap_root);
+}
+
+static int disk_ll_init_index(struct ll_disk *ll)
+{
+	return dm_btree_empty(&ll->bitmap_info, &ll->bitmap_root);
+}
+
+static int disk_ll_open(struct ll_disk *ll)
+{
+	/* nothing to do */
+	return 0;
+}
+
+static dm_block_t disk_ll_max_entries(struct ll_disk *ll)
+{
+	return -1ULL;
+}
+
+static int disk_ll_commit(struct ll_disk *ll)
+{
+	return 0;
+}
+
+int sm_ll_new_disk(struct ll_disk *ll, struct dm_transaction_manager *tm)
+{
+	int r;
+
+	r = sm_ll_init(ll, tm);
+	if (r < 0)
+		return r;
+
+	ll->load_ie = disk_ll_load_ie;
+	ll->save_ie = disk_ll_save_ie;
+	ll->init_index = disk_ll_init_index;
+	ll->open_index = disk_ll_open;
+	ll->max_entries = disk_ll_max_entries;
+	ll->commit = disk_ll_commit;
+
+	ll->nr_blocks = 0;
+	ll->nr_allocated = 0;
+
+	r = ll->init_index(ll);
+	if (r < 0)
+		return r;
+
+	r = dm_btree_empty(&ll->ref_count_info, &ll->ref_count_root);
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+
+int sm_ll_open_disk(struct ll_disk *ll, struct dm_transaction_manager *tm,
+		    void *root_le, size_t len)
+{
+	int r;
+	struct disk_sm_root *smr = root_le;
+
+	if (len < sizeof(struct disk_sm_root)) {
+		DMERR("sm_metadata root too small");
+		return -ENOMEM;
+	}
+
+	r = sm_ll_init(ll, tm);
+	if (r < 0)
+		return r;
+
+	ll->load_ie = disk_ll_load_ie;
+	ll->save_ie = disk_ll_save_ie;
+	ll->init_index = disk_ll_init_index;
+	ll->open_index = disk_ll_open;
+	ll->max_entries = disk_ll_max_entries;
+	ll->commit = disk_ll_commit;
+
+	ll->nr_blocks = le64_to_cpu(smr->nr_blocks);
+	ll->nr_allocated = le64_to_cpu(smr->nr_allocated);
+	ll->bitmap_root = le64_to_cpu(smr->bitmap_root);
+	ll->ref_count_root = le64_to_cpu(smr->ref_count_root);
+
+	return ll->open_index(ll);
+}
+
+/*----------------------------------------------------------------*/
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map-common.h linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map-common.h
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map-common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map-common.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_SPACE_MAP_COMMON_H
+#define DM_SPACE_MAP_COMMON_H
+
+#include "dm-btree.h"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Low level disk format
+ *
+ * Bitmap btree
+ * ------------
+ *
+ * Each value stored in the btree is an index_entry.  This points to a
+ * block that is used as a bitmap.  Within the bitmap hold 2 bits per
+ * entry, which represent UNUSED = 0, REF_COUNT = 1, REF_COUNT = 2 and
+ * REF_COUNT = many.
+ *
+ * Refcount btree
+ * --------------
+ *
+ * Any entry that has a ref count higher than 2 gets entered in the ref
+ * count tree.  The leaf values for this tree is the 32-bit ref count.
+ */
+
+struct disk_index_entry {
+	__le64 blocknr;
+	__le32 nr_free;
+	__le32 none_free_before;
+} __packed;
+
+
+#define MAX_METADATA_BITMAPS 255
+struct disk_metadata_index {
+	__le32 csum;
+	__le32 padding;
+	__le64 blocknr;
+
+	struct disk_index_entry index[MAX_METADATA_BITMAPS];
+} __packed;
+
+struct ll_disk;
+
+typedef int (*load_ie_fn)(struct ll_disk *ll, dm_block_t index, struct disk_index_entry *result);
+typedef int (*save_ie_fn)(struct ll_disk *ll, dm_block_t index, struct disk_index_entry *ie);
+typedef int (*init_index_fn)(struct ll_disk *ll);
+typedef int (*open_index_fn)(struct ll_disk *ll);
+typedef dm_block_t (*max_index_entries_fn)(struct ll_disk *ll);
+typedef int (*commit_fn)(struct ll_disk *ll);
+
+struct ll_disk {
+	struct dm_transaction_manager *tm;
+	struct dm_btree_info bitmap_info;
+	struct dm_btree_info ref_count_info;
+
+	uint32_t block_size;
+	uint32_t entries_per_block;
+	dm_block_t nr_blocks;
+	dm_block_t nr_allocated;
+
+	/*
+	 * bitmap_root may be a btree root or a simple index.
+	 */
+	dm_block_t bitmap_root;
+
+	dm_block_t ref_count_root;
+
+	struct disk_metadata_index mi_le;
+	load_ie_fn load_ie;
+	save_ie_fn save_ie;
+	init_index_fn init_index;
+	open_index_fn open_index;
+	max_index_entries_fn max_entries;
+	commit_fn commit;
+};
+
+struct disk_sm_root {
+	__le64 nr_blocks;
+	__le64 nr_allocated;
+	__le64 bitmap_root;
+	__le64 ref_count_root;
+} __packed;
+
+#define ENTRIES_PER_BYTE 4
+
+struct disk_bitmap_header {
+	__le32 csum;
+	__le32 not_used;
+	__le64 blocknr;
+} __packed;
+
+enum allocation_event {
+	SM_NONE,
+	SM_ALLOC,
+	SM_FREE,
+};
+
+/*----------------------------------------------------------------*/
+
+int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks);
+int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result);
+int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result);
+int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
+			  dm_block_t end, dm_block_t *result);
+int sm_ll_insert(struct ll_disk *ll, dm_block_t b, uint32_t ref_count, enum allocation_event *ev);
+int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev);
+int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev);
+int sm_ll_commit(struct ll_disk *ll);
+
+int sm_ll_new_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm);
+int sm_ll_open_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm,
+			void *root_le, size_t len);
+
+int sm_ll_new_disk(struct ll_disk *ll, struct dm_transaction_manager *tm);
+int sm_ll_open_disk(struct ll_disk *ll, struct dm_transaction_manager *tm,
+		    void *root_le, size_t len);
+
+/*----------------------------------------------------------------*/
+
+#endif	/* DM_SPACE_MAP_COMMON_H */
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map-disk.c linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map-disk.c
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map-disk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map-disk.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-space-map-checker.h"
+#include "dm-space-map-common.h"
+#include "dm-space-map-disk.h"
+#include "dm-space-map.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "space map disk"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Space map interface.
+ */
+struct sm_disk {
+	struct dm_space_map sm;
+
+	struct ll_disk ll;
+	struct ll_disk old_ll;
+
+	dm_block_t begin;
+	dm_block_t nr_allocated_this_transaction;
+};
+
+static void sm_disk_destroy(struct dm_space_map *sm)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	kfree(smd);
+}
+
+static int sm_disk_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	return sm_ll_extend(&smd->ll, extra_blocks);
+}
+
+static int sm_disk_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+	*count = smd->old_ll.nr_blocks;
+
+	return 0;
+}
+
+static int sm_disk_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+	*count = (smd->old_ll.nr_blocks - smd->old_ll.nr_allocated) - smd->nr_allocated_this_transaction;
+
+	return 0;
+}
+
+static int sm_disk_get_count(struct dm_space_map *sm, dm_block_t b,
+			     uint32_t *result)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+	return sm_ll_lookup(&smd->ll, b, result);
+}
+
+static int sm_disk_count_is_more_than_one(struct dm_space_map *sm, dm_block_t b,
+					  int *result)
+{
+	int r;
+	uint32_t count;
+
+	r = sm_disk_get_count(sm, b, &count);
+	if (r)
+		return r;
+
+	return count > 1;
+}
+
+static int sm_disk_set_count(struct dm_space_map *sm, dm_block_t b,
+			     uint32_t count)
+{
+	int r;
+	uint32_t old_count;
+	enum allocation_event ev;
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	r = sm_ll_insert(&smd->ll, b, count, &ev);
+	if (!r) {
+		switch (ev) {
+		case SM_NONE:
+			break;
+
+		case SM_ALLOC:
+			/*
+			 * This _must_ be free in the prior transaction
+			 * otherwise we've lost atomicity.
+			 */
+			smd->nr_allocated_this_transaction++;
+			break;
+
+		case SM_FREE:
+			/*
+			 * It's only free if it's also free in the last
+			 * transaction.
+			 */
+			r = sm_ll_lookup(&smd->old_ll, b, &old_count);
+			if (r)
+				return r;
+
+			if (!old_count)
+				smd->nr_allocated_this_transaction--;
+			break;
+		}
+	}
+
+	return r;
+}
+
+static int sm_disk_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+	int r;
+	enum allocation_event ev;
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	r = sm_ll_inc(&smd->ll, b, &ev);
+	if (!r && (ev == SM_ALLOC))
+		/*
+		 * This _must_ be free in the prior transaction
+		 * otherwise we've lost atomicity.
+		 */
+		smd->nr_allocated_this_transaction++;
+
+	return r;
+}
+
+static int sm_disk_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+	int r;
+	uint32_t old_count;
+	enum allocation_event ev;
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	r = sm_ll_dec(&smd->ll, b, &ev);
+	if (!r && (ev == SM_FREE)) {
+		/*
+		 * It's only free if it's also free in the last
+		 * transaction.
+		 */
+		r = sm_ll_lookup(&smd->old_ll, b, &old_count);
+		if (r)
+			return r;
+
+		if (!old_count)
+			smd->nr_allocated_this_transaction--;
+	}
+
+	return r;
+}
+
+static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+	int r;
+	enum allocation_event ev;
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	/* FIXME: we should loop round a couple of times */
+	r = sm_ll_find_free_block(&smd->old_ll, smd->begin, smd->old_ll.nr_blocks, b);
+	if (r)
+		return r;
+
+	smd->begin = *b + 1;
+	r = sm_ll_inc(&smd->ll, *b, &ev);
+	if (!r) {
+		BUG_ON(ev != SM_ALLOC);
+		smd->nr_allocated_this_transaction++;
+	}
+
+	return r;
+}
+
+static int sm_disk_commit(struct dm_space_map *sm)
+{
+	int r;
+	dm_block_t nr_free;
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	r = sm_disk_get_nr_free(sm, &nr_free);
+	if (r)
+		return r;
+
+	r = sm_ll_commit(&smd->ll);
+	if (r)
+		return r;
+
+	memcpy(&smd->old_ll, &smd->ll, sizeof(smd->old_ll));
+	smd->begin = 0;
+	smd->nr_allocated_this_transaction = 0;
+
+	r = sm_disk_get_nr_free(sm, &nr_free);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static int sm_disk_root_size(struct dm_space_map *sm, size_t *result)
+{
+	*result = sizeof(struct disk_sm_root);
+
+	return 0;
+}
+
+static int sm_disk_copy_root(struct dm_space_map *sm, void *where_le, size_t max)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+	struct disk_sm_root root_le;
+
+	root_le.nr_blocks = cpu_to_le64(smd->ll.nr_blocks);
+	root_le.nr_allocated = cpu_to_le64(smd->ll.nr_allocated);
+	root_le.bitmap_root = cpu_to_le64(smd->ll.bitmap_root);
+	root_le.ref_count_root = cpu_to_le64(smd->ll.ref_count_root);
+
+	if (max < sizeof(root_le))
+		return -ENOSPC;
+
+	memcpy(where_le, &root_le, sizeof(root_le));
+
+	return 0;
+}
+
+/*----------------------------------------------------------------*/
+
+static struct dm_space_map ops = {
+	.destroy = sm_disk_destroy,
+	.extend = sm_disk_extend,
+	.get_nr_blocks = sm_disk_get_nr_blocks,
+	.get_nr_free = sm_disk_get_nr_free,
+	.get_count = sm_disk_get_count,
+	.count_is_more_than_one = sm_disk_count_is_more_than_one,
+	.set_count = sm_disk_set_count,
+	.inc_block = sm_disk_inc_block,
+	.dec_block = sm_disk_dec_block,
+	.new_block = sm_disk_new_block,
+	.commit = sm_disk_commit,
+	.root_size = sm_disk_root_size,
+	.copy_root = sm_disk_copy_root
+};
+
+static struct dm_space_map *dm_sm_disk_create_real(
+	struct dm_transaction_manager *tm,
+	dm_block_t nr_blocks)
+{
+	int r;
+	struct sm_disk *smd;
+
+	smd = kmalloc(sizeof(*smd), GFP_KERNEL);
+	if (!smd)
+		return ERR_PTR(-ENOMEM);
+
+	smd->begin = 0;
+	smd->nr_allocated_this_transaction = 0;
+	memcpy(&smd->sm, &ops, sizeof(smd->sm));
+
+	r = sm_ll_new_disk(&smd->ll, tm);
+	if (r)
+		goto bad;
+
+	r = sm_ll_extend(&smd->ll, nr_blocks);
+	if (r)
+		goto bad;
+
+	r = sm_disk_commit(&smd->sm);
+	if (r)
+		goto bad;
+
+	return &smd->sm;
+
+bad:
+	kfree(smd);
+	return ERR_PTR(r);
+}
+
+struct dm_space_map *dm_sm_disk_create(struct dm_transaction_manager *tm,
+				       dm_block_t nr_blocks)
+{
+	struct dm_space_map *sm = dm_sm_disk_create_real(tm, nr_blocks);
+	return dm_sm_checker_create_fresh(sm);
+}
+EXPORT_SYMBOL_GPL(dm_sm_disk_create);
+
+static struct dm_space_map *dm_sm_disk_open_real(
+	struct dm_transaction_manager *tm,
+	void *root_le, size_t len)
+{
+	int r;
+	struct sm_disk *smd;
+
+	smd = kmalloc(sizeof(*smd), GFP_KERNEL);
+	if (!smd)
+		return ERR_PTR(-ENOMEM);
+
+	smd->begin = 0;
+	smd->nr_allocated_this_transaction = 0;
+	memcpy(&smd->sm, &ops, sizeof(smd->sm));
+
+	r = sm_ll_open_disk(&smd->ll, tm, root_le, len);
+	if (r)
+		goto bad;
+
+	r = sm_disk_commit(&smd->sm);
+	if (r)
+		goto bad;
+
+	return &smd->sm;
+
+bad:
+	kfree(smd);
+	return ERR_PTR(r);
+}
+
+struct dm_space_map *dm_sm_disk_open(struct dm_transaction_manager *tm,
+				     void *root_le, size_t len)
+{
+	return dm_sm_checker_create(
+		dm_sm_disk_open_real(tm, root_le, len));
+}
+EXPORT_SYMBOL_GPL(dm_sm_disk_open);
+
+/*----------------------------------------------------------------*/
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map-disk.h linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map-disk.h
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map-disk.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map-disk.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_SPACE_MAP_DISK_H
+#define _LINUX_DM_SPACE_MAP_DISK_H
+
+#include "dm-block-manager.h"
+
+struct dm_space_map;
+struct dm_transaction_manager;
+
+/*
+ * Unfortunately we have to use two-phase construction due to the cycle
+ * between the tm and sm.
+ */
+struct dm_space_map *dm_sm_disk_create(struct dm_transaction_manager *tm,
+				       dm_block_t nr_blocks);
+
+struct dm_space_map *dm_sm_disk_open(struct dm_transaction_manager *tm,
+				     void *root, size_t len);
+
+#endif /* _LINUX_DM_SPACE_MAP_DISK_H */
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map.h linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map.h
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_SPACE_MAP_H
+#define _LINUX_DM_SPACE_MAP_H
+
+#include "dm-block-manager.h"
+
+/*
+ * struct dm_space_map keeps a record of how many times each block in a device
+ * is referenced.  It needs to be fixed on disk as part of the transaction.
+ */
+struct dm_space_map {
+	void (*destroy)(struct dm_space_map *sm);
+
+	/*
+	 * You must commit before allocating the newly added space.
+	 */
+	int (*extend)(struct dm_space_map *sm, dm_block_t extra_blocks);
+
+	/*
+	 * Extensions do not appear in this count until after commit has
+	 * been called.
+	 */
+	int (*get_nr_blocks)(struct dm_space_map *sm, dm_block_t *count);
+
+	/*
+	 * Space maps must never allocate a block from the previous
+	 * transaction, in case we need to rollback.  This complicates the
+	 * semantics of get_nr_free(), it should return the number of blocks
+	 * that are available for allocation _now_.  For instance you may
+	 * have blocks with a zero reference count that will not be
+	 * available for allocation until after the next commit.
+	 */
+	int (*get_nr_free)(struct dm_space_map *sm, dm_block_t *count);
+
+	int (*get_count)(struct dm_space_map *sm, dm_block_t b, uint32_t *result);
+	int (*count_is_more_than_one)(struct dm_space_map *sm, dm_block_t b,
+				      int *result);
+	int (*set_count)(struct dm_space_map *sm, dm_block_t b, uint32_t count);
+
+	int (*commit)(struct dm_space_map *sm);
+
+	int (*inc_block)(struct dm_space_map *sm, dm_block_t b);
+	int (*dec_block)(struct dm_space_map *sm, dm_block_t b);
+
+	/*
+	 * new_block will increment the returned block.
+	 */
+	int (*new_block)(struct dm_space_map *sm, dm_block_t *b);
+
+	/*
+	 * The root contains all the information needed to fix the space map.
+	 * Generally this info is small, so squirrel it away in a disk block
+	 * along with other info.
+	 */
+	int (*root_size)(struct dm_space_map *sm, size_t *result);
+	int (*copy_root)(struct dm_space_map *sm, void *copy_to_here_le, size_t len);
+};
+
+/*----------------------------------------------------------------*/
+
+static inline void dm_sm_destroy(struct dm_space_map *sm)
+{
+	sm->destroy(sm);
+}
+
+static inline int dm_sm_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+	return sm->extend(sm, extra_blocks);
+}
+
+static inline int dm_sm_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+	return sm->get_nr_blocks(sm, count);
+}
+
+static inline int dm_sm_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+	return sm->get_nr_free(sm, count);
+}
+
+static inline int dm_sm_get_count(struct dm_space_map *sm, dm_block_t b,
+				  uint32_t *result)
+{
+	return sm->get_count(sm, b, result);
+}
+
+static inline int dm_sm_count_is_more_than_one(struct dm_space_map *sm,
+					       dm_block_t b, int *result)
+{
+	return sm->count_is_more_than_one(sm, b, result);
+}
+
+static inline int dm_sm_set_count(struct dm_space_map *sm, dm_block_t b,
+				  uint32_t count)
+{
+	return sm->set_count(sm, b, count);
+}
+
+static inline int dm_sm_commit(struct dm_space_map *sm)
+{
+	return sm->commit(sm);
+}
+
+static inline int dm_sm_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+	return sm->inc_block(sm, b);
+}
+
+static inline int dm_sm_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+	return sm->dec_block(sm, b);
+}
+
+static inline int dm_sm_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+	return sm->new_block(sm, b);
+}
+
+static inline int dm_sm_root_size(struct dm_space_map *sm, size_t *result)
+{
+	return sm->root_size(sm, result);
+}
+
+static inline int dm_sm_copy_root(struct dm_space_map *sm, void *copy_to_here_le, size_t len)
+{
+	return sm->copy_root(sm, copy_to_here_le, len);
+}
+
+#endif	/* _LINUX_DM_SPACE_MAP_H */
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map-metadata.c linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map-metadata.c
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map-metadata.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map-metadata.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,596 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-space-map.h"
+#include "dm-space-map-common.h"
+#include "dm-space-map-metadata.h"
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "space map metadata"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Space map interface.
+ *
+ * The low level disk format is written using the standard btree and
+ * transaction manager.  This means that performing disk operations may
+ * cause us to recurse into the space map in order to allocate new blocks.
+ * For this reason we have a pool of pre-allocated blocks large enough to
+ * service any metadata_ll_disk operation.
+ */
+
+/*
+ * FIXME: we should calculate this based on the size of the device.
+ * Only the metadata space map needs this functionality.
+ */
+#define MAX_RECURSIVE_ALLOCATIONS 1024
+
+enum block_op_type {
+	BOP_INC,
+	BOP_DEC
+};
+
+struct block_op {
+	enum block_op_type type;
+	dm_block_t block;
+};
+
+struct sm_metadata {
+	struct dm_space_map sm;
+
+	struct ll_disk ll;
+	struct ll_disk old_ll;
+
+	dm_block_t begin;
+
+	unsigned recursion_count;
+	unsigned allocated_this_transaction;
+	unsigned nr_uncommitted;
+	struct block_op uncommitted[MAX_RECURSIVE_ALLOCATIONS];
+};
+
+static int add_bop(struct sm_metadata *smm, enum block_op_type type, dm_block_t b)
+{
+	struct block_op *op;
+
+	if (smm->nr_uncommitted == MAX_RECURSIVE_ALLOCATIONS) {
+		DMERR("too many recursive allocations");
+		return -ENOMEM;
+	}
+
+	op = smm->uncommitted + smm->nr_uncommitted++;
+	op->type = type;
+	op->block = b;
+
+	return 0;
+}
+
+static int commit_bop(struct sm_metadata *smm, struct block_op *op)
+{
+	int r = 0;
+	enum allocation_event ev;
+
+	switch (op->type) {
+	case BOP_INC:
+		r = sm_ll_inc(&smm->ll, op->block, &ev);
+		break;
+
+	case BOP_DEC:
+		r = sm_ll_dec(&smm->ll, op->block, &ev);
+		break;
+	}
+
+	return r;
+}
+
+static void in(struct sm_metadata *smm)
+{
+	smm->recursion_count++;
+}
+
+static int out(struct sm_metadata *smm)
+{
+	int r = 0;
+
+	/*
+	 * If we're not recursing then very bad things are happening.
+	 */
+	if (!smm->recursion_count) {
+		DMERR("lost track of recursion depth");
+		return -ENOMEM;
+	}
+
+	if (smm->recursion_count == 1 && smm->nr_uncommitted) {
+		while (smm->nr_uncommitted && !r) {
+			smm->nr_uncommitted--;
+			r = commit_bop(smm, smm->uncommitted +
+				       smm->nr_uncommitted);
+			if (r)
+				break;
+		}
+	}
+
+	smm->recursion_count--;
+
+	return r;
+}
+
+/*
+ * When using the out() function above, we often want to combine an error
+ * code for the operation run in the recursive context with that from
+ * out().
+ */
+static int combine_errors(int r1, int r2)
+{
+	return r1 ? r1 : r2;
+}
+
+static int recursing(struct sm_metadata *smm)
+{
+	return smm->recursion_count;
+}
+
+static void sm_metadata_destroy(struct dm_space_map *sm)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	kfree(smm);
+}
+
+static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+	DMERR("doesn't support extend");
+	return -EINVAL;
+}
+
+static int sm_metadata_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	*count = smm->ll.nr_blocks;
+
+	return 0;
+}
+
+static int sm_metadata_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	*count = smm->old_ll.nr_blocks - smm->old_ll.nr_allocated -
+		 smm->allocated_this_transaction;
+
+	return 0;
+}
+
+static int sm_metadata_get_count(struct dm_space_map *sm, dm_block_t b,
+				 uint32_t *result)
+{
+	int r, i;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+	unsigned adjustment = 0;
+
+	/*
+	 * We may have some uncommitted adjustments to add.  This list
+	 * should always be really short.
+	 */
+	for (i = 0; i < smm->nr_uncommitted; i++) {
+		struct block_op *op = smm->uncommitted + i;
+
+		if (op->block != b)
+			continue;
+
+		switch (op->type) {
+		case BOP_INC:
+			adjustment++;
+			break;
+
+		case BOP_DEC:
+			adjustment--;
+			break;
+		}
+	}
+
+	r = sm_ll_lookup(&smm->ll, b, result);
+	if (r)
+		return r;
+
+	*result += adjustment;
+
+	return 0;
+}
+
+static int sm_metadata_count_is_more_than_one(struct dm_space_map *sm,
+					      dm_block_t b, int *result)
+{
+	int r, i, adjustment = 0;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+	uint32_t rc;
+
+	/*
+	 * We may have some uncommitted adjustments to add.  This list
+	 * should always be really short.
+	 */
+	for (i = 0; i < smm->nr_uncommitted; i++) {
+		struct block_op *op = smm->uncommitted + i;
+
+		if (op->block != b)
+			continue;
+
+		switch (op->type) {
+		case BOP_INC:
+			adjustment++;
+			break;
+
+		case BOP_DEC:
+			adjustment--;
+			break;
+		}
+	}
+
+	if (adjustment > 1) {
+		*result = 1;
+		return 0;
+	}
+
+	r = sm_ll_lookup_bitmap(&smm->ll, b, &rc);
+	if (r)
+		return r;
+
+	if (rc == 3)
+		/*
+		 * We err on the side of caution, and always return true.
+		 */
+		*result = 1;
+	else
+		*result = rc + adjustment > 1;
+
+	return 0;
+}
+
+static int sm_metadata_set_count(struct dm_space_map *sm, dm_block_t b,
+				 uint32_t count)
+{
+	int r, r2;
+	enum allocation_event ev;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	if (smm->recursion_count) {
+		DMERR("cannot recurse set_count()");
+		return -EINVAL;
+	}
+
+	in(smm);
+	r = sm_ll_insert(&smm->ll, b, count, &ev);
+	r2 = out(smm);
+
+	return combine_errors(r, r2);
+}
+
+static int sm_metadata_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+	int r, r2 = 0;
+	enum allocation_event ev;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	if (recursing(smm))
+		r = add_bop(smm, BOP_INC, b);
+	else {
+		in(smm);
+		r = sm_ll_inc(&smm->ll, b, &ev);
+		r2 = out(smm);
+	}
+
+	return combine_errors(r, r2);
+}
+
+static int sm_metadata_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+	int r, r2 = 0;
+	enum allocation_event ev;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	if (recursing(smm))
+		r = add_bop(smm, BOP_DEC, b);
+	else {
+		in(smm);
+		r = sm_ll_dec(&smm->ll, b, &ev);
+		r2 = out(smm);
+	}
+
+	return combine_errors(r, r2);
+}
+
+static int sm_metadata_new_block_(struct dm_space_map *sm, dm_block_t *b)
+{
+	int r, r2 = 0;
+	enum allocation_event ev;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	r = sm_ll_find_free_block(&smm->old_ll, smm->begin, smm->old_ll.nr_blocks, b);
+	if (r)
+		return r;
+
+	smm->begin = *b + 1;
+
+	if (recursing(smm))
+		r = add_bop(smm, BOP_INC, *b);
+	else {
+		in(smm);
+		r = sm_ll_inc(&smm->ll, *b, &ev);
+		r2 = out(smm);
+	}
+
+	if (!r)
+		smm->allocated_this_transaction++;
+
+	return combine_errors(r, r2);
+}
+
+static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+	int r = sm_metadata_new_block_(sm, b);
+	if (r)
+		DMERR("out of metadata space");
+	return r;
+}
+
+static int sm_metadata_commit(struct dm_space_map *sm)
+{
+	int r;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	r = sm_ll_commit(&smm->ll);
+	if (r)
+		return r;
+
+	memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll));
+	smm->begin = 0;
+	smm->allocated_this_transaction = 0;
+
+	return 0;
+}
+
+static int sm_metadata_root_size(struct dm_space_map *sm, size_t *result)
+{
+	*result = sizeof(struct disk_sm_root);
+
+	return 0;
+}
+
+static int sm_metadata_copy_root(struct dm_space_map *sm, void *where_le, size_t max)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+	struct disk_sm_root root_le;
+
+	root_le.nr_blocks = cpu_to_le64(smm->ll.nr_blocks);
+	root_le.nr_allocated = cpu_to_le64(smm->ll.nr_allocated);
+	root_le.bitmap_root = cpu_to_le64(smm->ll.bitmap_root);
+	root_le.ref_count_root = cpu_to_le64(smm->ll.ref_count_root);
+
+	if (max < sizeof(root_le))
+		return -ENOSPC;
+
+	memcpy(where_le, &root_le, sizeof(root_le));
+
+	return 0;
+}
+
+static struct dm_space_map ops = {
+	.destroy = sm_metadata_destroy,
+	.extend = sm_metadata_extend,
+	.get_nr_blocks = sm_metadata_get_nr_blocks,
+	.get_nr_free = sm_metadata_get_nr_free,
+	.get_count = sm_metadata_get_count,
+	.count_is_more_than_one = sm_metadata_count_is_more_than_one,
+	.set_count = sm_metadata_set_count,
+	.inc_block = sm_metadata_inc_block,
+	.dec_block = sm_metadata_dec_block,
+	.new_block = sm_metadata_new_block,
+	.commit = sm_metadata_commit,
+	.root_size = sm_metadata_root_size,
+	.copy_root = sm_metadata_copy_root
+};
+
+/*----------------------------------------------------------------*/
+
+/*
+ * When a new space map is created that manages its own space.  We use
+ * this tiny bootstrap allocator.
+ */
+static void sm_bootstrap_destroy(struct dm_space_map *sm)
+{
+}
+
+static int sm_bootstrap_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+	DMERR("boostrap doesn't support extend");
+
+	return -EINVAL;
+}
+
+static int sm_bootstrap_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	return smm->ll.nr_blocks;
+}
+
+static int sm_bootstrap_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	*count = smm->ll.nr_blocks - smm->begin;
+
+	return 0;
+}
+
+static int sm_bootstrap_get_count(struct dm_space_map *sm, dm_block_t b,
+				  uint32_t *result)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	return b < smm->begin ? 1 : 0;
+}
+
+static int sm_bootstrap_count_is_more_than_one(struct dm_space_map *sm,
+					       dm_block_t b, int *result)
+{
+	*result = 0;
+
+	return 0;
+}
+
+static int sm_bootstrap_set_count(struct dm_space_map *sm, dm_block_t b,
+				  uint32_t count)
+{
+	DMERR("boostrap doesn't support set_count");
+
+	return -EINVAL;
+}
+
+static int sm_bootstrap_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	/*
+	 * We know the entire device is unused.
+	 */
+	if (smm->begin == smm->ll.nr_blocks)
+		return -ENOSPC;
+
+	*b = smm->begin++;
+
+	return 0;
+}
+
+static int sm_bootstrap_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	return add_bop(smm, BOP_INC, b);
+}
+
+static int sm_bootstrap_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	return add_bop(smm, BOP_DEC, b);
+}
+
+static int sm_bootstrap_commit(struct dm_space_map *sm)
+{
+	return 0;
+}
+
+static int sm_bootstrap_root_size(struct dm_space_map *sm, size_t *result)
+{
+	DMERR("boostrap doesn't support root_size");
+
+	return -EINVAL;
+}
+
+static int sm_bootstrap_copy_root(struct dm_space_map *sm, void *where,
+				  size_t max)
+{
+	DMERR("boostrap doesn't support copy_root");
+
+	return -EINVAL;
+}
+
+static struct dm_space_map bootstrap_ops = {
+	.destroy = sm_bootstrap_destroy,
+	.extend = sm_bootstrap_extend,
+	.get_nr_blocks = sm_bootstrap_get_nr_blocks,
+	.get_nr_free = sm_bootstrap_get_nr_free,
+	.get_count = sm_bootstrap_get_count,
+	.count_is_more_than_one = sm_bootstrap_count_is_more_than_one,
+	.set_count = sm_bootstrap_set_count,
+	.inc_block = sm_bootstrap_inc_block,
+	.dec_block = sm_bootstrap_dec_block,
+	.new_block = sm_bootstrap_new_block,
+	.commit = sm_bootstrap_commit,
+	.root_size = sm_bootstrap_root_size,
+	.copy_root = sm_bootstrap_copy_root
+};
+
+/*----------------------------------------------------------------*/
+
+struct dm_space_map *dm_sm_metadata_init(void)
+{
+	struct sm_metadata *smm;
+
+	smm = kmalloc(sizeof(*smm), GFP_KERNEL);
+	if (!smm)
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(&smm->sm, &ops, sizeof(smm->sm));
+
+	return &smm->sm;
+}
+
+int dm_sm_metadata_create(struct dm_space_map *sm,
+			  struct dm_transaction_manager *tm,
+			  dm_block_t nr_blocks,
+			  dm_block_t superblock)
+{
+	int r;
+	dm_block_t i;
+	enum allocation_event ev;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	smm->begin = superblock + 1;
+	smm->recursion_count = 0;
+	smm->allocated_this_transaction = 0;
+	smm->nr_uncommitted = 0;
+
+	memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm));
+
+	r = sm_ll_new_metadata(&smm->ll, tm);
+	if (r)
+		return r;
+
+	r = sm_ll_extend(&smm->ll, nr_blocks);
+	if (r)
+		return r;
+
+	memcpy(&smm->sm, &ops, sizeof(smm->sm));
+
+	/*
+	 * Now we need to update the newly created data structures with the
+	 * allocated blocks that they were built from.
+	 */
+	for (i = superblock; !r && i < smm->begin; i++)
+		r = sm_ll_inc(&smm->ll, i, &ev);
+
+	if (r)
+		return r;
+
+	return sm_metadata_commit(sm);
+}
+
+int dm_sm_metadata_open(struct dm_space_map *sm,
+			struct dm_transaction_manager *tm,
+			void *root_le, size_t len)
+{
+	int r;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	r = sm_ll_open_metadata(&smm->ll, tm, root_le, len);
+	if (r)
+		return r;
+
+	smm->begin = 0;
+	smm->recursion_count = 0;
+	smm->allocated_this_transaction = 0;
+	smm->nr_uncommitted = 0;
+
+	memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll));
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map-metadata.h linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map-metadata.h
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-space-map-metadata.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-space-map-metadata.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_SPACE_MAP_METADATA_H
+#define DM_SPACE_MAP_METADATA_H
+
+#include "dm-transaction-manager.h"
+
+/*
+ * Unfortunately we have to use two-phase construction due to the cycle
+ * between the tm and sm.
+ */
+struct dm_space_map *dm_sm_metadata_init(void);
+
+/*
+ * Create a fresh space map.
+ */
+int dm_sm_metadata_create(struct dm_space_map *sm,
+			  struct dm_transaction_manager *tm,
+			  dm_block_t nr_blocks,
+			  dm_block_t superblock);
+
+/*
+ * Open from a previously-recorded root.
+ */
+int dm_sm_metadata_open(struct dm_space_map *sm,
+			struct dm_transaction_manager *tm,
+			void *root_le, size_t len);
+
+#endif	/* DM_SPACE_MAP_METADATA_H */
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-transaction-manager.c linux-libre-3.2-gnu/drivers/md/persistent-data/dm-transaction-manager.c
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-transaction-manager.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-transaction-manager.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+#include "dm-transaction-manager.h"
+#include "dm-space-map.h"
+#include "dm-space-map-checker.h"
+#include "dm-space-map-disk.h"
+#include "dm-space-map-metadata.h"
+#include "dm-persistent-data-internal.h"
+
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "transaction manager"
+
+/*----------------------------------------------------------------*/
+
+struct shadow_info {
+	struct hlist_node hlist;
+	dm_block_t where;
+};
+
+/*
+ * It would be nice if we scaled with the size of transaction.
+ */
+#define HASH_SIZE 256
+#define HASH_MASK (HASH_SIZE - 1)
+
+struct dm_transaction_manager {
+	int is_clone;
+	struct dm_transaction_manager *real;
+
+	struct dm_block_manager *bm;
+	struct dm_space_map *sm;
+
+	spinlock_t lock;
+	struct hlist_head buckets[HASH_SIZE];
+};
+
+/*----------------------------------------------------------------*/
+
+static int is_shadow(struct dm_transaction_manager *tm, dm_block_t b)
+{
+	int r = 0;
+	unsigned bucket = dm_hash_block(b, HASH_MASK);
+	struct shadow_info *si;
+	struct hlist_node *n;
+
+	spin_lock(&tm->lock);
+	hlist_for_each_entry(si, n, tm->buckets + bucket, hlist)
+		if (si->where == b) {
+			r = 1;
+			break;
+		}
+	spin_unlock(&tm->lock);
+
+	return r;
+}
+
+/*
+ * This can silently fail if there's no memory.  We're ok with this since
+ * creating redundant shadows causes no harm.
+ */
+static void insert_shadow(struct dm_transaction_manager *tm, dm_block_t b)
+{
+	unsigned bucket;
+	struct shadow_info *si;
+
+	si = kmalloc(sizeof(*si), GFP_NOIO);
+	if (si) {
+		si->where = b;
+		bucket = dm_hash_block(b, HASH_MASK);
+		spin_lock(&tm->lock);
+		hlist_add_head(&si->hlist, tm->buckets + bucket);
+		spin_unlock(&tm->lock);
+	}
+}
+
+static void wipe_shadow_table(struct dm_transaction_manager *tm)
+{
+	struct shadow_info *si;
+	struct hlist_node *n, *tmp;
+	struct hlist_head *bucket;
+	int i;
+
+	spin_lock(&tm->lock);
+	for (i = 0; i < HASH_SIZE; i++) {
+		bucket = tm->buckets + i;
+		hlist_for_each_entry_safe(si, n, tmp, bucket, hlist)
+			kfree(si);
+
+		INIT_HLIST_HEAD(bucket);
+	}
+
+	spin_unlock(&tm->lock);
+}
+
+/*----------------------------------------------------------------*/
+
+static struct dm_transaction_manager *dm_tm_create(struct dm_block_manager *bm,
+						   struct dm_space_map *sm)
+{
+	int i;
+	struct dm_transaction_manager *tm;
+
+	tm = kmalloc(sizeof(*tm), GFP_KERNEL);
+	if (!tm)
+		return ERR_PTR(-ENOMEM);
+
+	tm->is_clone = 0;
+	tm->real = NULL;
+	tm->bm = bm;
+	tm->sm = sm;
+
+	spin_lock_init(&tm->lock);
+	for (i = 0; i < HASH_SIZE; i++)
+		INIT_HLIST_HEAD(tm->buckets + i);
+
+	return tm;
+}
+
+struct dm_transaction_manager *dm_tm_create_non_blocking_clone(struct dm_transaction_manager *real)
+{
+	struct dm_transaction_manager *tm;
+
+	tm = kmalloc(sizeof(*tm), GFP_KERNEL);
+	if (tm) {
+		tm->is_clone = 1;
+		tm->real = real;
+	}
+
+	return tm;
+}
+EXPORT_SYMBOL_GPL(dm_tm_create_non_blocking_clone);
+
+void dm_tm_destroy(struct dm_transaction_manager *tm)
+{
+	kfree(tm);
+}
+EXPORT_SYMBOL_GPL(dm_tm_destroy);
+
+int dm_tm_pre_commit(struct dm_transaction_manager *tm)
+{
+	int r;
+
+	if (tm->is_clone)
+		return -EWOULDBLOCK;
+
+	r = dm_sm_commit(tm->sm);
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dm_tm_pre_commit);
+
+int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *root)
+{
+	if (tm->is_clone)
+		return -EWOULDBLOCK;
+
+	wipe_shadow_table(tm);
+
+	return dm_bm_flush_and_unlock(tm->bm, root);
+}
+EXPORT_SYMBOL_GPL(dm_tm_commit);
+
+int dm_tm_new_block(struct dm_transaction_manager *tm,
+		    struct dm_block_validator *v,
+		    struct dm_block **result)
+{
+	int r;
+	dm_block_t new_block;
+
+	if (tm->is_clone)
+		return -EWOULDBLOCK;
+
+	r = dm_sm_new_block(tm->sm, &new_block);
+	if (r < 0)
+		return r;
+
+	r = dm_bm_write_lock_zero(tm->bm, new_block, v, result);
+	if (r < 0) {
+		dm_sm_dec_block(tm->sm, new_block);
+		return r;
+	}
+
+	/*
+	 * New blocks count as shadows in that they don't need to be
+	 * shadowed again.
+	 */
+	insert_shadow(tm, new_block);
+
+	return 0;
+}
+
+static int __shadow_block(struct dm_transaction_manager *tm, dm_block_t orig,
+			  struct dm_block_validator *v,
+			  struct dm_block **result)
+{
+	int r;
+	dm_block_t new;
+	struct dm_block *orig_block;
+
+	r = dm_sm_new_block(tm->sm, &new);
+	if (r < 0)
+		return r;
+
+	r = dm_sm_dec_block(tm->sm, orig);
+	if (r < 0)
+		return r;
+
+	r = dm_bm_read_lock(tm->bm, orig, v, &orig_block);
+	if (r < 0)
+		return r;
+
+	r = dm_bm_unlock_move(orig_block, new);
+	if (r < 0) {
+		dm_bm_unlock(orig_block);
+		return r;
+	}
+
+	return dm_bm_write_lock(tm->bm, new, v, result);
+}
+
+int dm_tm_shadow_block(struct dm_transaction_manager *tm, dm_block_t orig,
+		       struct dm_block_validator *v, struct dm_block **result,
+		       int *inc_children)
+{
+	int r;
+
+	if (tm->is_clone)
+		return -EWOULDBLOCK;
+
+	r = dm_sm_count_is_more_than_one(tm->sm, orig, inc_children);
+	if (r < 0)
+		return r;
+
+	if (is_shadow(tm, orig) && !*inc_children)
+		return dm_bm_write_lock(tm->bm, orig, v, result);
+
+	r = __shadow_block(tm, orig, v, result);
+	if (r < 0)
+		return r;
+	insert_shadow(tm, dm_block_location(*result));
+
+	return r;
+}
+
+int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b,
+		    struct dm_block_validator *v,
+		    struct dm_block **blk)
+{
+	if (tm->is_clone)
+		return dm_bm_read_try_lock(tm->real->bm, b, v, blk);
+
+	return dm_bm_read_lock(tm->bm, b, v, blk);
+}
+
+int dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b)
+{
+	return dm_bm_unlock(b);
+}
+EXPORT_SYMBOL_GPL(dm_tm_unlock);
+
+void dm_tm_inc(struct dm_transaction_manager *tm, dm_block_t b)
+{
+	/*
+	 * The non-blocking clone doesn't support this.
+	 */
+	BUG_ON(tm->is_clone);
+
+	dm_sm_inc_block(tm->sm, b);
+}
+EXPORT_SYMBOL_GPL(dm_tm_inc);
+
+void dm_tm_dec(struct dm_transaction_manager *tm, dm_block_t b)
+{
+	/*
+	 * The non-blocking clone doesn't support this.
+	 */
+	BUG_ON(tm->is_clone);
+
+	dm_sm_dec_block(tm->sm, b);
+}
+EXPORT_SYMBOL_GPL(dm_tm_dec);
+
+int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b,
+	      uint32_t *result)
+{
+	if (tm->is_clone)
+		return -EWOULDBLOCK;
+
+	return dm_sm_get_count(tm->sm, b, result);
+}
+
+struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm)
+{
+	return tm->bm;
+}
+
+/*----------------------------------------------------------------*/
+
+static int dm_tm_create_internal(struct dm_block_manager *bm,
+				 dm_block_t sb_location,
+				 struct dm_block_validator *sb_validator,
+				 size_t root_offset, size_t root_max_len,
+				 struct dm_transaction_manager **tm,
+				 struct dm_space_map **sm,
+				 struct dm_block **sblock,
+				 int create)
+{
+	int r;
+	struct dm_space_map *inner;
+
+	inner = dm_sm_metadata_init();
+	if (IS_ERR(inner))
+		return PTR_ERR(inner);
+
+	*tm = dm_tm_create(bm, inner);
+	if (IS_ERR(*tm)) {
+		dm_sm_destroy(inner);
+		return PTR_ERR(*tm);
+	}
+
+	if (create) {
+		r = dm_bm_write_lock_zero(dm_tm_get_bm(*tm), sb_location,
+					  sb_validator, sblock);
+		if (r < 0) {
+			DMERR("couldn't lock superblock");
+			goto bad1;
+		}
+
+		r = dm_sm_metadata_create(inner, *tm, dm_bm_nr_blocks(bm),
+					  sb_location);
+		if (r) {
+			DMERR("couldn't create metadata space map");
+			goto bad2;
+		}
+
+		*sm = dm_sm_checker_create(inner);
+		if (!*sm)
+			goto bad2;
+
+	} else {
+		r = dm_bm_write_lock(dm_tm_get_bm(*tm), sb_location,
+				     sb_validator, sblock);
+		if (r < 0) {
+			DMERR("couldn't lock superblock");
+			goto bad1;
+		}
+
+		r = dm_sm_metadata_open(inner, *tm,
+					dm_block_data(*sblock) + root_offset,
+					root_max_len);
+		if (r) {
+			DMERR("couldn't open metadata space map");
+			goto bad2;
+		}
+
+		*sm = dm_sm_checker_create(inner);
+		if (!*sm)
+			goto bad2;
+	}
+
+	return 0;
+
+bad2:
+	dm_tm_unlock(*tm, *sblock);
+bad1:
+	dm_tm_destroy(*tm);
+	dm_sm_destroy(inner);
+	return r;
+}
+
+int dm_tm_create_with_sm(struct dm_block_manager *bm, dm_block_t sb_location,
+			 struct dm_block_validator *sb_validator,
+			 struct dm_transaction_manager **tm,
+			 struct dm_space_map **sm, struct dm_block **sblock)
+{
+	return dm_tm_create_internal(bm, sb_location, sb_validator,
+				     0, 0, tm, sm, sblock, 1);
+}
+EXPORT_SYMBOL_GPL(dm_tm_create_with_sm);
+
+int dm_tm_open_with_sm(struct dm_block_manager *bm, dm_block_t sb_location,
+		       struct dm_block_validator *sb_validator,
+		       size_t root_offset, size_t root_max_len,
+		       struct dm_transaction_manager **tm,
+		       struct dm_space_map **sm, struct dm_block **sblock)
+{
+	return dm_tm_create_internal(bm, sb_location, sb_validator, root_offset,
+				     root_max_len, tm, sm, sblock, 0);
+}
+EXPORT_SYMBOL_GPL(dm_tm_open_with_sm);
+
+/*----------------------------------------------------------------*/
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/dm-transaction-manager.h linux-libre-3.2-gnu/drivers/md/persistent-data/dm-transaction-manager.h
--- linux-libre-3.1-gnu/drivers/md/persistent-data/dm-transaction-manager.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/dm-transaction-manager.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_TRANSACTION_MANAGER_H
+#define _LINUX_DM_TRANSACTION_MANAGER_H
+
+#include "dm-block-manager.h"
+
+struct dm_transaction_manager;
+struct dm_space_map;
+
+/*----------------------------------------------------------------*/
+
+/*
+ * This manages the scope of a transaction.  It also enforces immutability
+ * of the on-disk data structures by limiting access to writeable blocks.
+ *
+ * Clients should not fiddle with the block manager directly.
+ */
+
+void dm_tm_destroy(struct dm_transaction_manager *tm);
+
+/*
+ * The non-blocking version of a transaction manager is intended for use in
+ * fast path code that needs to do lookups e.g. a dm mapping function.
+ * You create the non-blocking variant from a normal tm.  The interface is
+ * the same, except that most functions will just return -EWOULDBLOCK.
+ * Methods that return void yet may block should not be called on a clone
+ * viz. dm_tm_inc, dm_tm_dec.  Call dm_tm_destroy() as you would with a normal
+ * tm when you've finished with it.  You may not destroy the original prior
+ * to clones.
+ */
+struct dm_transaction_manager *dm_tm_create_non_blocking_clone(struct dm_transaction_manager *real);
+
+/*
+ * We use a 2-phase commit here.
+ *
+ * i) In the first phase the block manager is told to start flushing, and
+ * the changes to the space map are written to disk.  You should interrogate
+ * your particular space map to get detail of its root node etc. to be
+ * included in your superblock.
+ *
+ * ii) @root will be committed last.  You shouldn't use more than the
+ * first 512 bytes of @root if you wish the transaction to survive a power
+ * failure.  You *must* have a write lock held on @root for both stage (i)
+ * and (ii).  The commit will drop the write lock.
+ */
+int dm_tm_pre_commit(struct dm_transaction_manager *tm);
+int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *root);
+
+/*
+ * These methods are the only way to get hold of a writeable block.
+ */
+
+/*
+ * dm_tm_new_block() is pretty self-explanatory.  Make sure you do actually
+ * write to the whole of @data before you unlock, otherwise you could get
+ * a data leak.  (The other option is for tm_new_block() to zero new blocks
+ * before handing them out, which will be redundant in most, if not all,
+ * cases).
+ * Zeroes the new block and returns with write lock held.
+ */
+int dm_tm_new_block(struct dm_transaction_manager *tm,
+		    struct dm_block_validator *v,
+		    struct dm_block **result);
+
+/*
+ * dm_tm_shadow_block() allocates a new block and copies the data from @orig
+ * to it.  It then decrements the reference count on original block.  Use
+ * this to update the contents of a block in a data structure, don't
+ * confuse this with a clone - you shouldn't access the orig block after
+ * this operation.  Because the tm knows the scope of the transaction it
+ * can optimise requests for a shadow of a shadow to a no-op.  Don't forget
+ * to unlock when you've finished with the shadow.
+ *
+ * The @inc_children flag is used to tell the caller whether it needs to
+ * adjust reference counts for children.  (Data in the block may refer to
+ * other blocks.)
+ *
+ * Shadowing implicitly drops a reference on @orig so you must not have
+ * it locked when you call this.
+ */
+int dm_tm_shadow_block(struct dm_transaction_manager *tm, dm_block_t orig,
+		       struct dm_block_validator *v,
+		       struct dm_block **result, int *inc_children);
+
+/*
+ * Read access.  You can lock any block you want.  If there's a write lock
+ * on it outstanding then it'll block.
+ */
+int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b,
+		    struct dm_block_validator *v,
+		    struct dm_block **result);
+
+int dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b);
+
+/*
+ * Functions for altering the reference count of a block directly.
+ */
+void dm_tm_inc(struct dm_transaction_manager *tm, dm_block_t b);
+
+void dm_tm_dec(struct dm_transaction_manager *tm, dm_block_t b);
+
+int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b,
+	      uint32_t *result);
+
+struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm);
+
+/*
+ * A little utility that ties the knot by producing a transaction manager
+ * that has a space map managed by the transaction manager...
+ *
+ * Returns a tm that has an open transaction to write the new disk sm.
+ * Caller should store the new sm root and commit.
+ */
+int dm_tm_create_with_sm(struct dm_block_manager *bm, dm_block_t sb_location,
+			 struct dm_block_validator *sb_validator,
+			 struct dm_transaction_manager **tm,
+			 struct dm_space_map **sm, struct dm_block **sblock);
+
+int dm_tm_open_with_sm(struct dm_block_manager *bm, dm_block_t sb_location,
+		       struct dm_block_validator *sb_validator,
+		       size_t root_offset, size_t root_max_len,
+		       struct dm_transaction_manager **tm,
+		       struct dm_space_map **sm, struct dm_block **sblock);
+
+#endif	/* _LINUX_DM_TRANSACTION_MANAGER_H */
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/Kconfig linux-libre-3.2-gnu/drivers/md/persistent-data/Kconfig
--- linux-libre-3.1-gnu/drivers/md/persistent-data/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,8 @@
+config DM_PERSISTENT_DATA
+       tristate
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       select LIBCRC32C
+       select DM_BUFIO
+       ---help---
+	 Library providing immutable on-disk data structure support for
+	 device-mapper targets such as the thin provisioning target.
diff -druN linux-libre-3.1-gnu/drivers/md/persistent-data/Makefile linux-libre-3.2-gnu/drivers/md/persistent-data/Makefile
--- linux-libre-3.1-gnu/drivers/md/persistent-data/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/md/persistent-data/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,11 @@
+obj-$(CONFIG_DM_PERSISTENT_DATA) += dm-persistent-data.o
+dm-persistent-data-objs := \
+	dm-block-manager.o \
+	dm-space-map-checker.o \
+	dm-space-map-common.o \
+	dm-space-map-disk.o \
+	dm-space-map-metadata.o \
+	dm-transaction-manager.o \
+	dm-btree.o \
+	dm-btree-remove.o \
+	dm-btree-spine.o
diff -druN linux-libre-3.1-gnu/drivers/md/raid0.c linux-libre-3.2-gnu/drivers/md/raid0.c
--- linux-libre-3.1-gnu/drivers/md/raid0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/raid0.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 
 #include <linux/blkdev.h>
 #include <linux/seq_file.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include "md.h"
 #include "raid0.h"
@@ -27,9 +28,9 @@
 
 static int raid0_congested(void *data, int bits)
 {
-	mddev_t *mddev = data;
-	raid0_conf_t *conf = mddev->private;
-	mdk_rdev_t **devlist = conf->devlist;
+	struct mddev *mddev = data;
+	struct r0conf *conf = mddev->private;
+	struct md_rdev **devlist = conf->devlist;
 	int raid_disks = conf->strip_zone[0].nb_dev;
 	int i, ret = 0;
 
@@ -47,52 +48,53 @@
 /*
  * inform the user of the raid configuration
 */
-static void dump_zones(mddev_t *mddev)
+static void dump_zones(struct mddev *mddev)
 {
-	int j, k, h;
+	int j, k;
 	sector_t zone_size = 0;
 	sector_t zone_start = 0;
 	char b[BDEVNAME_SIZE];
-	raid0_conf_t *conf = mddev->private;
+	struct r0conf *conf = mddev->private;
 	int raid_disks = conf->strip_zone[0].nb_dev;
-	printk(KERN_INFO "******* %s configuration *********\n",
-		mdname(mddev));
-	h = 0;
+	printk(KERN_INFO "md: RAID0 configuration for %s - %d zone%s\n",
+	       mdname(mddev),
+	       conf->nr_strip_zones, conf->nr_strip_zones==1?"":"s");
 	for (j = 0; j < conf->nr_strip_zones; j++) {
-		printk(KERN_INFO "zone%d=[", j);
+		printk(KERN_INFO "md: zone%d=[", j);
 		for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
-			printk(KERN_CONT "%s/",
+			printk(KERN_CONT "%s%s", k?"/":"",
 			bdevname(conf->devlist[j*raid_disks
 						+ k]->bdev, b));
 		printk(KERN_CONT "]\n");
 
 		zone_size  = conf->strip_zone[j].zone_end - zone_start;
-		printk(KERN_INFO "        zone offset=%llukb "
-				"device offset=%llukb size=%llukb\n",
+		printk(KERN_INFO "      zone-offset=%10lluKB, "
+				"device-offset=%10lluKB, size=%10lluKB\n",
 			(unsigned long long)zone_start>>1,
 			(unsigned long long)conf->strip_zone[j].dev_start>>1,
 			(unsigned long long)zone_size>>1);
 		zone_start = conf->strip_zone[j].zone_end;
 	}
-	printk(KERN_INFO "**********************************\n\n");
+	printk(KERN_INFO "\n");
 }
 
-static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf)
+static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
 {
 	int i, c, err;
 	sector_t curr_zone_end, sectors;
-	mdk_rdev_t *smallest, *rdev1, *rdev2, *rdev, **dev;
+	struct md_rdev *smallest, *rdev1, *rdev2, *rdev, **dev;
 	struct strip_zone *zone;
 	int cnt;
 	char b[BDEVNAME_SIZE];
-	raid0_conf_t *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
+	char b2[BDEVNAME_SIZE];
+	struct r0conf *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
 
 	if (!conf)
 		return -ENOMEM;
 	list_for_each_entry(rdev1, &mddev->disks, same_set) {
-		printk(KERN_INFO "md/raid0:%s: looking at %s\n",
-		       mdname(mddev),
-		       bdevname(rdev1->bdev, b));
+		pr_debug("md/raid0:%s: looking at %s\n",
+			 mdname(mddev),
+			 bdevname(rdev1->bdev, b));
 		c = 0;
 
 		/* round size to chunk_size */
@@ -101,16 +103,16 @@
 		rdev1->sectors = sectors * mddev->chunk_sectors;
 
 		list_for_each_entry(rdev2, &mddev->disks, same_set) {
-			printk(KERN_INFO "md/raid0:%s:   comparing %s(%llu)",
-			       mdname(mddev),
-			       bdevname(rdev1->bdev,b),
-			       (unsigned long long)rdev1->sectors);
-			printk(KERN_CONT " with %s(%llu)\n",
-			       bdevname(rdev2->bdev,b),
-			       (unsigned long long)rdev2->sectors);
+			pr_debug("md/raid0:%s:   comparing %s(%llu)"
+				 " with %s(%llu)\n",
+				 mdname(mddev),
+				 bdevname(rdev1->bdev,b),
+				 (unsigned long long)rdev1->sectors,
+				 bdevname(rdev2->bdev,b2),
+				 (unsigned long long)rdev2->sectors);
 			if (rdev2 == rdev1) {
-				printk(KERN_INFO "md/raid0:%s:   END\n",
-				       mdname(mddev));
+				pr_debug("md/raid0:%s:   END\n",
+					 mdname(mddev));
 				break;
 			}
 			if (rdev2->sectors == rdev1->sectors) {
@@ -118,30 +120,30 @@
 				 * Not unique, don't count it as a new
 				 * group
 				 */
-				printk(KERN_INFO "md/raid0:%s:   EQUAL\n",
-				       mdname(mddev));
+				pr_debug("md/raid0:%s:   EQUAL\n",
+					 mdname(mddev));
 				c = 1;
 				break;
 			}
-			printk(KERN_INFO "md/raid0:%s:   NOT EQUAL\n",
-			       mdname(mddev));
+			pr_debug("md/raid0:%s:   NOT EQUAL\n",
+				 mdname(mddev));
 		}
 		if (!c) {
-			printk(KERN_INFO "md/raid0:%s:   ==> UNIQUE\n",
-			       mdname(mddev));
+			pr_debug("md/raid0:%s:   ==> UNIQUE\n",
+				 mdname(mddev));
 			conf->nr_strip_zones++;
-			printk(KERN_INFO "md/raid0:%s: %d zones\n",
-			       mdname(mddev), conf->nr_strip_zones);
+			pr_debug("md/raid0:%s: %d zones\n",
+				 mdname(mddev), conf->nr_strip_zones);
 		}
 	}
-	printk(KERN_INFO "md/raid0:%s: FINAL %d zones\n",
-	       mdname(mddev), conf->nr_strip_zones);
+	pr_debug("md/raid0:%s: FINAL %d zones\n",
+		 mdname(mddev), conf->nr_strip_zones);
 	err = -ENOMEM;
 	conf->strip_zone = kzalloc(sizeof(struct strip_zone)*
 				conf->nr_strip_zones, GFP_KERNEL);
 	if (!conf->strip_zone)
 		goto abort;
-	conf->devlist = kzalloc(sizeof(mdk_rdev_t*)*
+	conf->devlist = kzalloc(sizeof(struct md_rdev*)*
 				conf->nr_strip_zones*mddev->raid_disks,
 				GFP_KERNEL);
 	if (!conf->devlist)
@@ -218,44 +220,45 @@
 		zone = conf->strip_zone + i;
 		dev = conf->devlist + i * mddev->raid_disks;
 
-		printk(KERN_INFO "md/raid0:%s: zone %d\n",
-		       mdname(mddev), i);
+		pr_debug("md/raid0:%s: zone %d\n", mdname(mddev), i);
 		zone->dev_start = smallest->sectors;
 		smallest = NULL;
 		c = 0;
 
 		for (j=0; j<cnt; j++) {
 			rdev = conf->devlist[j];
-			printk(KERN_INFO "md/raid0:%s: checking %s ...",
-			       mdname(mddev),
-			       bdevname(rdev->bdev, b));
 			if (rdev->sectors <= zone->dev_start) {
-				printk(KERN_CONT " nope.\n");
+				pr_debug("md/raid0:%s: checking %s ... nope\n",
+					 mdname(mddev),
+					 bdevname(rdev->bdev, b));
 				continue;
 			}
-			printk(KERN_CONT " contained as device %d\n", c);
+			pr_debug("md/raid0:%s: checking %s ..."
+				 " contained as device %d\n",
+				 mdname(mddev),
+				 bdevname(rdev->bdev, b), c);
 			dev[c] = rdev;
 			c++;
 			if (!smallest || rdev->sectors < smallest->sectors) {
 				smallest = rdev;
-				printk(KERN_INFO "md/raid0:%s:  (%llu) is smallest!.\n",
-				       mdname(mddev),
-				       (unsigned long long)rdev->sectors);
+				pr_debug("md/raid0:%s:  (%llu) is smallest!.\n",
+					 mdname(mddev),
+					 (unsigned long long)rdev->sectors);
 			}
 		}
 
 		zone->nb_dev = c;
 		sectors = (smallest->sectors - zone->dev_start) * c;
-		printk(KERN_INFO "md/raid0:%s: zone->nb_dev: %d, sectors: %llu\n",
-		       mdname(mddev),
-		       zone->nb_dev, (unsigned long long)sectors);
+		pr_debug("md/raid0:%s: zone->nb_dev: %d, sectors: %llu\n",
+			 mdname(mddev),
+			 zone->nb_dev, (unsigned long long)sectors);
 
 		curr_zone_end += sectors;
 		zone->zone_end = curr_zone_end;
 
-		printk(KERN_INFO "md/raid0:%s: current zone start: %llu\n",
-		       mdname(mddev),
-		       (unsigned long long)smallest->sectors);
+		pr_debug("md/raid0:%s: current zone start: %llu\n",
+			 mdname(mddev),
+			 (unsigned long long)smallest->sectors);
 	}
 	mddev->queue->backing_dev_info.congested_fn = raid0_congested;
 	mddev->queue->backing_dev_info.congested_data = mddev;
@@ -275,7 +278,7 @@
 	blk_queue_io_opt(mddev->queue,
 			 (mddev->chunk_sectors << 9) * mddev->raid_disks);
 
-	printk(KERN_INFO "md/raid0:%s: done.\n", mdname(mddev));
+	pr_debug("md/raid0:%s: done.\n", mdname(mddev));
 	*private_conf = conf;
 
 	return 0;
@@ -299,7 +302,7 @@
 				struct bvec_merge_data *bvm,
 				struct bio_vec *biovec)
 {
-	mddev_t *mddev = q->queuedata;
+	struct mddev *mddev = q->queuedata;
 	sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
 	int max;
 	unsigned int chunk_sectors = mddev->chunk_sectors;
@@ -318,10 +321,10 @@
 		return max;
 }
 
-static sector_t raid0_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+static sector_t raid0_size(struct mddev *mddev, sector_t sectors, int raid_disks)
 {
 	sector_t array_sectors = 0;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	WARN_ONCE(sectors || raid_disks,
 		  "%s does not support generic reshape\n", __func__);
@@ -332,9 +335,9 @@
 	return array_sectors;
 }
 
-static int raid0_run(mddev_t *mddev)
+static int raid0_run(struct mddev *mddev)
 {
-	raid0_conf_t *conf;
+	struct r0conf *conf;
 	int ret;
 
 	if (mddev->chunk_sectors == 0) {
@@ -382,9 +385,9 @@
 	return md_integrity_register(mddev);
 }
 
-static int raid0_stop(mddev_t *mddev)
+static int raid0_stop(struct mddev *mddev)
 {
-	raid0_conf_t *conf = mddev->private;
+	struct r0conf *conf = mddev->private;
 
 	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
 	kfree(conf->strip_zone);
@@ -397,7 +400,7 @@
 /* Find the zone which holds a particular offset
  * Update *sectorp to be an offset in that zone
  */
-static struct strip_zone *find_zone(struct raid0_private_data *conf,
+static struct strip_zone *find_zone(struct r0conf *conf,
 				    sector_t *sectorp)
 {
 	int i;
@@ -417,12 +420,12 @@
  * remaps the bio to the target device. we separate two flows.
  * power 2 flow and a general flow for the sake of perfromance
 */
-static mdk_rdev_t *map_sector(mddev_t *mddev, struct strip_zone *zone,
+static struct md_rdev *map_sector(struct mddev *mddev, struct strip_zone *zone,
 				sector_t sector, sector_t *sector_offset)
 {
 	unsigned int sect_in_chunk;
 	sector_t chunk;
-	raid0_conf_t *conf = mddev->private;
+	struct r0conf *conf = mddev->private;
 	int raid_disks = conf->strip_zone[0].nb_dev;
 	unsigned int chunk_sects = mddev->chunk_sectors;
 
@@ -453,7 +456,7 @@
 /*
  * Is io distribute over 1 or more chunks ?
 */
-static inline int is_io_in_chunk_boundary(mddev_t *mddev,
+static inline int is_io_in_chunk_boundary(struct mddev *mddev,
 			unsigned int chunk_sects, struct bio *bio)
 {
 	if (likely(is_power_of_2(chunk_sects))) {
@@ -466,16 +469,16 @@
 	}
 }
 
-static int raid0_make_request(mddev_t *mddev, struct bio *bio)
+static void raid0_make_request(struct mddev *mddev, struct bio *bio)
 {
 	unsigned int chunk_sects;
 	sector_t sector_offset;
 	struct strip_zone *zone;
-	mdk_rdev_t *tmp_dev;
+	struct md_rdev *tmp_dev;
 
 	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
 		md_flush_request(mddev, bio);
-		return 0;
+		return;
 	}
 
 	chunk_sects = mddev->chunk_sectors;
@@ -495,13 +498,10 @@
 		else
 			bp = bio_split(bio, chunk_sects -
 				       sector_div(sector, chunk_sects));
-		if (raid0_make_request(mddev, &bp->bio1))
-			generic_make_request(&bp->bio1);
-		if (raid0_make_request(mddev, &bp->bio2))
-			generic_make_request(&bp->bio2);
-
+		raid0_make_request(mddev, &bp->bio1);
+		raid0_make_request(mddev, &bp->bio2);
 		bio_pair_release(bp);
-		return 0;
+		return;
 	}
 
 	sector_offset = bio->bi_sector;
@@ -511,10 +511,9 @@
 	bio->bi_bdev = tmp_dev->bdev;
 	bio->bi_sector = sector_offset + zone->dev_start +
 		tmp_dev->data_offset;
-	/*
-	 * Let the main block layer submit the IO and resolve recursion:
-	 */
-	return 1;
+
+	generic_make_request(bio);
+	return;
 
 bad_map:
 	printk("md/raid0:%s: make_request bug: can't convert block across chunks"
@@ -523,46 +522,19 @@
 	       (unsigned long long)bio->bi_sector, bio->bi_size >> 10);
 
 	bio_io_error(bio);
-	return 0;
+	return;
 }
 
-static void raid0_status(struct seq_file *seq, mddev_t *mddev)
+static void raid0_status(struct seq_file *seq, struct mddev *mddev)
 {
-#undef MD_DEBUG
-#ifdef MD_DEBUG
-	int j, k, h;
-	char b[BDEVNAME_SIZE];
-	raid0_conf_t *conf = mddev->private;
-	int raid_disks = conf->strip_zone[0].nb_dev;
-
-	sector_t zone_size;
-	sector_t zone_start = 0;
-	h = 0;
-
-	for (j = 0; j < conf->nr_strip_zones; j++) {
-		seq_printf(seq, "      z%d", j);
-		seq_printf(seq, "=[");
-		for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
-			seq_printf(seq, "%s/", bdevname(
-				conf->devlist[j*raid_disks + k]
-						->bdev, b));
-
-		zone_size  = conf->strip_zone[j].zone_end - zone_start;
-		seq_printf(seq, "] ze=%lld ds=%lld s=%lld\n",
-			(unsigned long long)zone_start>>1,
-			(unsigned long long)conf->strip_zone[j].dev_start>>1,
-			(unsigned long long)zone_size>>1);
-		zone_start = conf->strip_zone[j].zone_end;
-	}
-#endif
 	seq_printf(seq, " %dk chunks", mddev->chunk_sectors / 2);
 	return;
 }
 
-static void *raid0_takeover_raid45(mddev_t *mddev)
+static void *raid0_takeover_raid45(struct mddev *mddev)
 {
-	mdk_rdev_t *rdev;
-	raid0_conf_t *priv_conf;
+	struct md_rdev *rdev;
+	struct r0conf *priv_conf;
 
 	if (mddev->degraded != 1) {
 		printk(KERN_ERR "md/raid0:%s: raid5 must be degraded! Degraded disks: %d\n",
@@ -593,9 +565,9 @@
 	return priv_conf;
 }
 
-static void *raid0_takeover_raid10(mddev_t *mddev)
+static void *raid0_takeover_raid10(struct mddev *mddev)
 {
-	raid0_conf_t *priv_conf;
+	struct r0conf *priv_conf;
 
 	/* Check layout:
 	 *  - far_copies must be 1
@@ -634,9 +606,9 @@
 	return priv_conf;
 }
 
-static void *raid0_takeover_raid1(mddev_t *mddev)
+static void *raid0_takeover_raid1(struct mddev *mddev)
 {
-	raid0_conf_t *priv_conf;
+	struct r0conf *priv_conf;
 
 	/* Check layout:
 	 *  - (N - 1) mirror drives must be already faulty
@@ -660,7 +632,7 @@
 	return priv_conf;
 }
 
-static void *raid0_takeover(mddev_t *mddev)
+static void *raid0_takeover(struct mddev *mddev)
 {
 	/* raid0 can take over:
 	 *  raid4 - if all data disks are active.
@@ -691,11 +663,11 @@
 	return ERR_PTR(-EINVAL);
 }
 
-static void raid0_quiesce(mddev_t *mddev, int state)
+static void raid0_quiesce(struct mddev *mddev, int state)
 {
 }
 
-static struct mdk_personality raid0_personality=
+static struct md_personality raid0_personality=
 {
 	.name		= "raid0",
 	.level		= 0,
diff -druN linux-libre-3.1-gnu/drivers/md/raid0.h linux-libre-3.2-gnu/drivers/md/raid0.h
--- linux-libre-3.1-gnu/drivers/md/raid0.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/raid0.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,20 +1,16 @@
 #ifndef _RAID0_H
 #define _RAID0_H
 
-struct strip_zone
-{
+struct strip_zone {
 	sector_t zone_end;	/* Start of the next zone (in sectors) */
 	sector_t dev_start;	/* Zone offset in real dev (in sectors) */
 	int nb_dev;		/* # of devices attached to the zone */
 };
 
-struct raid0_private_data
-{
+struct r0conf {
 	struct strip_zone *strip_zone;
-	mdk_rdev_t **devlist; /* lists of rdevs, pointed to by strip_zone->dev */
+	struct md_rdev **devlist; /* lists of rdevs, pointed to by strip_zone->dev */
 	int nr_strip_zones;
 };
 
-typedef struct raid0_private_data raid0_conf_t;
-
 #endif
diff -druN linux-libre-3.1-gnu/drivers/md/raid10.c linux-libre-3.2-gnu/drivers/md/raid10.c
--- linux-libre-3.1-gnu/drivers/md/raid10.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/raid10.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/blkdev.h>
+#include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/ratelimit.h>
 #include "md.h"
@@ -58,13 +59,19 @@
  */
 #define	NR_RAID10_BIOS 256
 
-static void allow_barrier(conf_t *conf);
-static void lower_barrier(conf_t *conf);
+/* When there are this many requests queue to be written by
+ * the raid10 thread, we become 'congested' to provide back-pressure
+ * for writeback.
+ */
+static int max_queued_requests = 1024;
+
+static void allow_barrier(struct r10conf *conf);
+static void lower_barrier(struct r10conf *conf);
 
 static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
 {
-	conf_t *conf = data;
-	int size = offsetof(struct r10bio_s, devs[conf->copies]);
+	struct r10conf *conf = data;
+	int size = offsetof(struct r10bio, devs[conf->copies]);
 
 	/* allocate a r10bio with room for raid_disks entries in the bios array */
 	return kzalloc(size, gfp_flags);
@@ -92,9 +99,9 @@
  */
 static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data)
 {
-	conf_t *conf = data;
+	struct r10conf *conf = data;
 	struct page *page;
-	r10bio_t *r10_bio;
+	struct r10bio *r10_bio;
 	struct bio *bio;
 	int i, j;
 	int nalloc;
@@ -158,8 +165,8 @@
 static void r10buf_pool_free(void *__r10_bio, void *data)
 {
 	int i;
-	conf_t *conf = data;
-	r10bio_t *r10bio = __r10_bio;
+	struct r10conf *conf = data;
+	struct r10bio *r10bio = __r10_bio;
 	int j;
 
 	for (j=0; j < conf->copies; j++) {
@@ -175,7 +182,7 @@
 	r10bio_pool_free(r10bio, conf);
 }
 
-static void put_all_bios(conf_t *conf, r10bio_t *r10_bio)
+static void put_all_bios(struct r10conf *conf, struct r10bio *r10_bio)
 {
 	int i;
 
@@ -187,28 +194,28 @@
 	}
 }
 
-static void free_r10bio(r10bio_t *r10_bio)
+static void free_r10bio(struct r10bio *r10_bio)
 {
-	conf_t *conf = r10_bio->mddev->private;
+	struct r10conf *conf = r10_bio->mddev->private;
 
 	put_all_bios(conf, r10_bio);
 	mempool_free(r10_bio, conf->r10bio_pool);
 }
 
-static void put_buf(r10bio_t *r10_bio)
+static void put_buf(struct r10bio *r10_bio)
 {
-	conf_t *conf = r10_bio->mddev->private;
+	struct r10conf *conf = r10_bio->mddev->private;
 
 	mempool_free(r10_bio, conf->r10buf_pool);
 
 	lower_barrier(conf);
 }
 
-static void reschedule_retry(r10bio_t *r10_bio)
+static void reschedule_retry(struct r10bio *r10_bio)
 {
 	unsigned long flags;
-	mddev_t *mddev = r10_bio->mddev;
-	conf_t *conf = mddev->private;
+	struct mddev *mddev = r10_bio->mddev;
+	struct r10conf *conf = mddev->private;
 
 	spin_lock_irqsave(&conf->device_lock, flags);
 	list_add(&r10_bio->retry_list, &conf->retry_list);
@@ -226,11 +233,11 @@
  * operation and are ready to return a success/failure code to the buffer
  * cache layer.
  */
-static void raid_end_bio_io(r10bio_t *r10_bio)
+static void raid_end_bio_io(struct r10bio *r10_bio)
 {
 	struct bio *bio = r10_bio->master_bio;
 	int done;
-	conf_t *conf = r10_bio->mddev->private;
+	struct r10conf *conf = r10_bio->mddev->private;
 
 	if (bio->bi_phys_segments) {
 		unsigned long flags;
@@ -256,9 +263,9 @@
 /*
  * Update disk head position estimator based on IRQ completion info.
  */
-static inline void update_head_pos(int slot, r10bio_t *r10_bio)
+static inline void update_head_pos(int slot, struct r10bio *r10_bio)
 {
-	conf_t *conf = r10_bio->mddev->private;
+	struct r10conf *conf = r10_bio->mddev->private;
 
 	conf->mirrors[r10_bio->devs[slot].devnum].head_position =
 		r10_bio->devs[slot].addr + (r10_bio->sectors);
@@ -267,7 +274,7 @@
 /*
  * Find the disk number which triggered given bio
  */
-static int find_bio_disk(conf_t *conf, r10bio_t *r10_bio,
+static int find_bio_disk(struct r10conf *conf, struct r10bio *r10_bio,
 			 struct bio *bio, int *slotp)
 {
 	int slot;
@@ -287,9 +294,9 @@
 static void raid10_end_read_request(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r10bio_t *r10_bio = bio->bi_private;
+	struct r10bio *r10_bio = bio->bi_private;
 	int slot, dev;
-	conf_t *conf = r10_bio->mddev->private;
+	struct r10conf *conf = r10_bio->mddev->private;
 
 
 	slot = r10_bio->read_slot;
@@ -327,7 +334,7 @@
 	}
 }
 
-static void close_write(r10bio_t *r10_bio)
+static void close_write(struct r10bio *r10_bio)
 {
 	/* clear the bitmap if all writes complete successfully */
 	bitmap_endwrite(r10_bio->mddev->bitmap, r10_bio->sector,
@@ -337,7 +344,7 @@
 	md_write_end(r10_bio->mddev);
 }
 
-static void one_write_done(r10bio_t *r10_bio)
+static void one_write_done(struct r10bio *r10_bio)
 {
 	if (atomic_dec_and_test(&r10_bio->remaining)) {
 		if (test_bit(R10BIO_WriteError, &r10_bio->state))
@@ -355,10 +362,10 @@
 static void raid10_end_write_request(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r10bio_t *r10_bio = bio->bi_private;
+	struct r10bio *r10_bio = bio->bi_private;
 	int dev;
 	int dec_rdev = 1;
-	conf_t *conf = r10_bio->mddev->private;
+	struct r10conf *conf = r10_bio->mddev->private;
 	int slot;
 
 	dev = find_bio_disk(conf, r10_bio, bio, &slot);
@@ -433,7 +440,7 @@
  * sector offset to a virtual address
  */
 
-static void raid10_find_phys(conf_t *conf, r10bio_t *r10bio)
+static void raid10_find_phys(struct r10conf *conf, struct r10bio *r10bio)
 {
 	int n,f;
 	sector_t sector;
@@ -481,7 +488,7 @@
 	BUG_ON(slot != conf->copies);
 }
 
-static sector_t raid10_find_virt(conf_t *conf, sector_t sector, int dev)
+static sector_t raid10_find_virt(struct r10conf *conf, sector_t sector, int dev)
 {
 	sector_t offset, chunk, vchunk;
 
@@ -522,7 +529,7 @@
 				 struct bvec_merge_data *bvm,
 				 struct bio_vec *biovec)
 {
-	mddev_t *mddev = q->queuedata;
+	struct mddev *mddev = q->queuedata;
 	sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
 	int max;
 	unsigned int chunk_sectors = mddev->chunk_sectors;
@@ -555,14 +562,14 @@
  * FIXME: possibly should rethink readbalancing and do it differently
  * depending on near_copies / far_copies geometry.
  */
-static int read_balance(conf_t *conf, r10bio_t *r10_bio, int *max_sectors)
+static int read_balance(struct r10conf *conf, struct r10bio *r10_bio, int *max_sectors)
 {
 	const sector_t this_sector = r10_bio->sector;
 	int disk, slot;
 	int sectors = r10_bio->sectors;
 	int best_good_sectors;
 	sector_t new_distance, best_dist;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int do_balance;
 	int best_slot;
 
@@ -677,15 +684,19 @@
 
 static int raid10_congested(void *data, int bits)
 {
-	mddev_t *mddev = data;
-	conf_t *conf = mddev->private;
+	struct mddev *mddev = data;
+	struct r10conf *conf = mddev->private;
 	int i, ret = 0;
 
+	if ((bits & (1 << BDI_async_congested)) &&
+	    conf->pending_count >= max_queued_requests)
+		return 1;
+
 	if (mddev_congested(mddev, bits))
 		return 1;
 	rcu_read_lock();
 	for (i = 0; i < conf->raid_disks && ret == 0; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
 		if (rdev && !test_bit(Faulty, &rdev->flags)) {
 			struct request_queue *q = bdev_get_queue(rdev->bdev);
 
@@ -696,7 +707,7 @@
 	return ret;
 }
 
-static void flush_pending_writes(conf_t *conf)
+static void flush_pending_writes(struct r10conf *conf)
 {
 	/* Any writes that have been queued but are awaiting
 	 * bitmap updates get flushed here.
@@ -706,10 +717,12 @@
 	if (conf->pending_bio_list.head) {
 		struct bio *bio;
 		bio = bio_list_get(&conf->pending_bio_list);
+		conf->pending_count = 0;
 		spin_unlock_irq(&conf->device_lock);
 		/* flush any pending bitmap writes to disk
 		 * before proceeding w/ I/O */
 		bitmap_unplug(conf->mddev->bitmap);
+		wake_up(&conf->wait_barrier);
 
 		while (bio) { /* submit pending writes */
 			struct bio *next = bio->bi_next;
@@ -743,7 +756,7 @@
  *    lower_barrier when the particular background IO completes.
  */
 
-static void raise_barrier(conf_t *conf, int force)
+static void raise_barrier(struct r10conf *conf, int force)
 {
 	BUG_ON(force && !conf->barrier);
 	spin_lock_irq(&conf->resync_lock);
@@ -763,7 +776,7 @@
 	spin_unlock_irq(&conf->resync_lock);
 }
 
-static void lower_barrier(conf_t *conf)
+static void lower_barrier(struct r10conf *conf)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&conf->resync_lock, flags);
@@ -772,7 +785,7 @@
 	wake_up(&conf->wait_barrier);
 }
 
-static void wait_barrier(conf_t *conf)
+static void wait_barrier(struct r10conf *conf)
 {
 	spin_lock_irq(&conf->resync_lock);
 	if (conf->barrier) {
@@ -786,7 +799,7 @@
 	spin_unlock_irq(&conf->resync_lock);
 }
 
-static void allow_barrier(conf_t *conf)
+static void allow_barrier(struct r10conf *conf)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&conf->resync_lock, flags);
@@ -795,7 +808,7 @@
 	wake_up(&conf->wait_barrier);
 }
 
-static void freeze_array(conf_t *conf)
+static void freeze_array(struct r10conf *conf)
 {
 	/* stop syncio and normal IO and wait for everything to
 	 * go quiet.
@@ -820,7 +833,7 @@
 	spin_unlock_irq(&conf->resync_lock);
 }
 
-static void unfreeze_array(conf_t *conf)
+static void unfreeze_array(struct r10conf *conf)
 {
 	/* reverse the effect of the freeze */
 	spin_lock_irq(&conf->resync_lock);
@@ -830,11 +843,11 @@
 	spin_unlock_irq(&conf->resync_lock);
 }
 
-static int make_request(mddev_t *mddev, struct bio * bio)
+static void make_request(struct mddev *mddev, struct bio * bio)
 {
-	conf_t *conf = mddev->private;
-	mirror_info_t *mirror;
-	r10bio_t *r10_bio;
+	struct r10conf *conf = mddev->private;
+	struct mirror_info *mirror;
+	struct r10bio *r10_bio;
 	struct bio *read_bio;
 	int i;
 	int chunk_sects = conf->chunk_mask + 1;
@@ -842,14 +855,14 @@
 	const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
 	const unsigned long do_fua = (bio->bi_rw & REQ_FUA);
 	unsigned long flags;
-	mdk_rdev_t *blocked_rdev;
+	struct md_rdev *blocked_rdev;
 	int plugged;
 	int sectors_handled;
 	int max_sectors;
 
 	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
 		md_flush_request(mddev, bio);
-		return 0;
+		return;
 	}
 
 	/* If this request crosses a chunk boundary, we need to
@@ -881,10 +894,8 @@
 		conf->nr_waiting++;
 		spin_unlock_irq(&conf->resync_lock);
 
-		if (make_request(mddev, &bp->bio1))
-			generic_make_request(&bp->bio1);
-		if (make_request(mddev, &bp->bio2))
-			generic_make_request(&bp->bio2);
+		make_request(mddev, &bp->bio1);
+		make_request(mddev, &bp->bio2);
 
 		spin_lock_irq(&conf->resync_lock);
 		conf->nr_waiting--;
@@ -892,14 +903,14 @@
 		spin_unlock_irq(&conf->resync_lock);
 
 		bio_pair_release(bp);
-		return 0;
+		return;
 	bad_map:
 		printk("md/raid10:%s: make_request bug: can't convert block across chunks"
 		       " or bigger than %dk %llu %d\n", mdname(mddev), chunk_sects/2,
 		       (unsigned long long)bio->bi_sector, bio->bi_size >> 10);
 
 		bio_io_error(bio);
-		return 0;
+		return;
 	}
 
 	md_write_start(mddev, bio);
@@ -942,7 +953,7 @@
 		slot = r10_bio->read_slot;
 		if (disk < 0) {
 			raid_end_bio_io(r10_bio);
-			return 0;
+			return;
 		}
 		mirror = conf->mirrors + disk;
 
@@ -990,12 +1001,17 @@
 			goto read_again;
 		} else
 			generic_make_request(read_bio);
-		return 0;
+		return;
 	}
 
 	/*
 	 * WRITE:
 	 */
+	if (conf->pending_count >= max_queued_requests) {
+		md_wakeup_thread(mddev->thread);
+		wait_event(conf->wait_barrier,
+			   conf->pending_count < max_queued_requests);
+	}
 	/* first select target devices under rcu_lock and
 	 * inc refcount on their rdev.  Record them by setting
 	 * bios[x] to bio
@@ -1017,7 +1033,7 @@
 
 	for (i = 0;  i < conf->copies; i++) {
 		int d = r10_bio->devs[i].devnum;
-		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[d].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->mirrors[d].rdev);
 		if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
 			atomic_inc(&rdev->nr_pending);
 			blocked_rdev = rdev;
@@ -1129,6 +1145,7 @@
 		atomic_inc(&r10_bio->remaining);
 		spin_lock_irqsave(&conf->device_lock, flags);
 		bio_list_add(&conf->pending_bio_list, mbio);
+		conf->pending_count++;
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 	}
 
@@ -1158,12 +1175,11 @@
 
 	if (do_sync || !mddev->bitmap || !plugged)
 		md_wakeup_thread(mddev->thread);
-	return 0;
 }
 
-static void status(struct seq_file *seq, mddev_t *mddev)
+static void status(struct seq_file *seq, struct mddev *mddev)
 {
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 	int i;
 
 	if (conf->near_copies < conf->raid_disks)
@@ -1190,7 +1206,7 @@
  * Don't consider the device numbered 'ignore'
  * as we might be about to remove it.
  */
-static int enough(conf_t *conf, int ignore)
+static int enough(struct r10conf *conf, int ignore)
 {
 	int first = 0;
 
@@ -1209,10 +1225,10 @@
 	return 1;
 }
 
-static void error(mddev_t *mddev, mdk_rdev_t *rdev)
+static void error(struct mddev *mddev, struct md_rdev *rdev)
 {
 	char b[BDEVNAME_SIZE];
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 
 	/*
 	 * If it is not operational, then we have already marked it as dead
@@ -1246,10 +1262,10 @@
 	       mdname(mddev), conf->raid_disks - mddev->degraded);
 }
 
-static void print_conf(conf_t *conf)
+static void print_conf(struct r10conf *conf)
 {
 	int i;
-	mirror_info_t *tmp;
+	struct mirror_info *tmp;
 
 	printk(KERN_DEBUG "RAID10 conf printout:\n");
 	if (!conf) {
@@ -1270,7 +1286,7 @@
 	}
 }
 
-static void close_sync(conf_t *conf)
+static void close_sync(struct r10conf *conf)
 {
 	wait_barrier(conf);
 	allow_barrier(conf);
@@ -1279,11 +1295,11 @@
 	conf->r10buf_pool = NULL;
 }
 
-static int raid10_spare_active(mddev_t *mddev)
+static int raid10_spare_active(struct mddev *mddev)
 {
 	int i;
-	conf_t *conf = mddev->private;
-	mirror_info_t *tmp;
+	struct r10conf *conf = mddev->private;
+	struct mirror_info *tmp;
 	int count = 0;
 	unsigned long flags;
 
@@ -1309,9 +1325,9 @@
 }
 
 
-static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
 {
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 	int err = -EEXIST;
 	int mirror;
 	int first = 0;
@@ -1334,10 +1350,10 @@
 	else
 		mirror = first;
 	for ( ; mirror <= last ; mirror++) {
-		mirror_info_t *p = &conf->mirrors[mirror];
+		struct mirror_info *p = &conf->mirrors[mirror];
 		if (p->recovery_disabled == mddev->recovery_disabled)
 			continue;
-		if (!p->rdev)
+		if (p->rdev)
 			continue;
 
 		disk_stack_limits(mddev->gendisk, rdev->bdev,
@@ -1355,6 +1371,7 @@
 		}
 
 		p->head_position = 0;
+		p->recovery_disabled = mddev->recovery_disabled - 1;
 		rdev->raid_disk = mirror;
 		err = 0;
 		if (rdev->saved_raid_disk != mirror)
@@ -1368,12 +1385,12 @@
 	return err;
 }
 
-static int raid10_remove_disk(mddev_t *mddev, int number)
+static int raid10_remove_disk(struct mddev *mddev, int number)
 {
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 	int err = 0;
-	mdk_rdev_t *rdev;
-	mirror_info_t *p = conf->mirrors+ number;
+	struct md_rdev *rdev;
+	struct mirror_info *p = conf->mirrors+ number;
 
 	print_conf(conf);
 	rdev = p->rdev;
@@ -1411,8 +1428,8 @@
 
 static void end_sync_read(struct bio *bio, int error)
 {
-	r10bio_t *r10_bio = bio->bi_private;
-	conf_t *conf = r10_bio->mddev->private;
+	struct r10bio *r10_bio = bio->bi_private;
+	struct r10conf *conf = r10_bio->mddev->private;
 	int d;
 
 	d = find_bio_disk(conf, r10_bio, bio, NULL);
@@ -1439,9 +1456,9 @@
 	}
 }
 
-static void end_sync_request(r10bio_t *r10_bio)
+static void end_sync_request(struct r10bio *r10_bio)
 {
-	mddev_t *mddev = r10_bio->mddev;
+	struct mddev *mddev = r10_bio->mddev;
 
 	while (atomic_dec_and_test(&r10_bio->remaining)) {
 		if (r10_bio->master_bio == NULL) {
@@ -1455,7 +1472,7 @@
 			md_done_sync(mddev, s, 1);
 			break;
 		} else {
-			r10bio_t *r10_bio2 = (r10bio_t *)r10_bio->master_bio;
+			struct r10bio *r10_bio2 = (struct r10bio *)r10_bio->master_bio;
 			if (test_bit(R10BIO_MadeGood, &r10_bio->state) ||
 			    test_bit(R10BIO_WriteError, &r10_bio->state))
 				reschedule_retry(r10_bio);
@@ -1469,9 +1486,9 @@
 static void end_sync_write(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r10bio_t *r10_bio = bio->bi_private;
-	mddev_t *mddev = r10_bio->mddev;
-	conf_t *conf = mddev->private;
+	struct r10bio *r10_bio = bio->bi_private;
+	struct mddev *mddev = r10_bio->mddev;
+	struct r10conf *conf = mddev->private;
 	int d;
 	sector_t first_bad;
 	int bad_sectors;
@@ -1509,9 +1526,9 @@
  * We check if all blocks are in-sync and only write to blocks that
  * aren't in sync
  */
-static void sync_request_write(mddev_t *mddev, r10bio_t *r10_bio)
+static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
 {
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 	int i, first;
 	struct bio *tbio, *fbio;
 
@@ -1609,7 +1626,7 @@
  * The second for writing.
  *
  */
-static void fix_recovery_read_error(r10bio_t *r10_bio)
+static void fix_recovery_read_error(struct r10bio *r10_bio)
 {
 	/* We got a read error during recovery.
 	 * We repeat the read in smaller page-sized sections.
@@ -1618,8 +1635,8 @@
 	 * If a read fails, record a bad block on both old and
 	 * new devices.
 	 */
-	mddev_t *mddev = r10_bio->mddev;
-	conf_t *conf = mddev->private;
+	struct mddev *mddev = r10_bio->mddev;
+	struct r10conf *conf = mddev->private;
 	struct bio *bio = r10_bio->devs[0].bio;
 	sector_t sect = 0;
 	int sectors = r10_bio->sectors;
@@ -1629,7 +1646,7 @@
 
 	while (sectors) {
 		int s = sectors;
-		mdk_rdev_t *rdev;
+		struct md_rdev *rdev;
 		sector_t addr;
 		int ok;
 
@@ -1663,7 +1680,7 @@
 
 			if (rdev != conf->mirrors[dw].rdev) {
 				/* need bad block on destination too */
-				mdk_rdev_t *rdev2 = conf->mirrors[dw].rdev;
+				struct md_rdev *rdev2 = conf->mirrors[dw].rdev;
 				addr = r10_bio->devs[1].addr + sect;
 				ok = rdev_set_badblocks(rdev2, addr, s, 0);
 				if (!ok) {
@@ -1688,9 +1705,9 @@
 	}
 }
 
-static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio)
+static void recovery_request_write(struct mddev *mddev, struct r10bio *r10_bio)
 {
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 	int d;
 	struct bio *wbio;
 
@@ -1719,7 +1736,7 @@
  * since the last recorded read error.
  *
  */
-static void check_decay_read_errors(mddev_t *mddev, mdk_rdev_t *rdev)
+static void check_decay_read_errors(struct mddev *mddev, struct md_rdev *rdev)
 {
 	struct timespec cur_time_mon;
 	unsigned long hours_since_last;
@@ -1750,7 +1767,7 @@
 		atomic_set(&rdev->read_errors, read_errors >> hours_since_last);
 }
 
-static int r10_sync_page_io(mdk_rdev_t *rdev, sector_t sector,
+static int r10_sync_page_io(struct md_rdev *rdev, sector_t sector,
 			    int sectors, struct page *page, int rw)
 {
 	sector_t first_bad;
@@ -1778,11 +1795,11 @@
  *	3.	Performs writes following reads for array synchronising.
  */
 
-static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
+static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10bio *r10_bio)
 {
 	int sect = 0; /* Offset from r10_bio->sector */
 	int sectors = r10_bio->sectors;
-	mdk_rdev_t*rdev;
+	struct md_rdev*rdev;
 	int max_read_errors = atomic_read(&mddev->max_corr_read_errors);
 	int d = r10_bio->devs[r10_bio->read_slot].devnum;
 
@@ -1983,12 +2000,12 @@
 	return test_bit(BIO_UPTODATE, &bio->bi_flags);
 }
 
-static int narrow_write_error(r10bio_t *r10_bio, int i)
+static int narrow_write_error(struct r10bio *r10_bio, int i)
 {
 	struct bio *bio = r10_bio->master_bio;
-	mddev_t *mddev = r10_bio->mddev;
-	conf_t *conf = mddev->private;
-	mdk_rdev_t *rdev = conf->mirrors[r10_bio->devs[i].devnum].rdev;
+	struct mddev *mddev = r10_bio->mddev;
+	struct r10conf *conf = mddev->private;
+	struct md_rdev *rdev = conf->mirrors[r10_bio->devs[i].devnum].rdev;
 	/* bio has the data to be written to slot 'i' where
 	 * we just recently had a write error.
 	 * We repeatedly clone the bio and trim down to one block,
@@ -2040,13 +2057,13 @@
 	return ok;
 }
 
-static void handle_read_error(mddev_t *mddev, r10bio_t *r10_bio)
+static void handle_read_error(struct mddev *mddev, struct r10bio *r10_bio)
 {
 	int slot = r10_bio->read_slot;
 	int mirror = r10_bio->devs[slot].devnum;
 	struct bio *bio;
-	conf_t *conf = mddev->private;
-	mdk_rdev_t *rdev;
+	struct r10conf *conf = mddev->private;
+	struct md_rdev *rdev;
 	char b[BDEVNAME_SIZE];
 	unsigned long do_sync;
 	int max_sectors;
@@ -2139,7 +2156,7 @@
 		generic_make_request(bio);
 }
 
-static void handle_write_completed(conf_t *conf, r10bio_t *r10_bio)
+static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
 {
 	/* Some sort of write request has finished and it
 	 * succeeded in writing where we thought there was a
@@ -2148,7 +2165,7 @@
 	 * a bad block.
 	 */
 	int m;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	if (test_bit(R10BIO_IsSync, &r10_bio->state) ||
 	    test_bit(R10BIO_IsRecover, &r10_bio->state)) {
@@ -2200,11 +2217,11 @@
 	}
 }
 
-static void raid10d(mddev_t *mddev)
+static void raid10d(struct mddev *mddev)
 {
-	r10bio_t *r10_bio;
+	struct r10bio *r10_bio;
 	unsigned long flags;
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 	struct list_head *head = &conf->retry_list;
 	struct blk_plug plug;
 
@@ -2220,7 +2237,7 @@
 			spin_unlock_irqrestore(&conf->device_lock, flags);
 			break;
 		}
-		r10_bio = list_entry(head->prev, r10bio_t, retry_list);
+		r10_bio = list_entry(head->prev, struct r10bio, retry_list);
 		list_del(head->prev);
 		conf->nr_queued--;
 		spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -2252,7 +2269,7 @@
 }
 
 
-static int init_resync(conf_t *conf)
+static int init_resync(struct r10conf *conf)
 {
 	int buffs;
 
@@ -2297,11 +2314,11 @@
  *
  */
 
-static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
+static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
 			     int *skipped, int go_faster)
 {
-	conf_t *conf = mddev->private;
-	r10bio_t *r10_bio;
+	struct r10conf *conf = mddev->private;
+	struct r10bio *r10_bio;
 	struct bio *biolist = NULL, *bio;
 	sector_t max_sector, nr_sectors;
 	int i;
@@ -2393,7 +2410,7 @@
 
 		for (i=0 ; i<conf->raid_disks; i++) {
 			int still_degraded;
-			r10bio_t *rb2;
+			struct r10bio *rb2;
 			sector_t sect;
 			int must_sync;
 			int any_working;
@@ -2453,7 +2470,7 @@
 				int k;
 				int d = r10_bio->devs[j].devnum;
 				sector_t from_addr, to_addr;
-				mdk_rdev_t *rdev;
+				struct md_rdev *rdev;
 				sector_t sector, first_bad;
 				int bad_sectors;
 				if (!conf->mirrors[d].rdev ||
@@ -2547,8 +2564,8 @@
 		}
 		if (biolist == NULL) {
 			while (r10_bio) {
-				r10bio_t *rb2 = r10_bio;
-				r10_bio = (r10bio_t*) rb2->master_bio;
+				struct r10bio *rb2 = r10_bio;
+				r10_bio = (struct r10bio*) rb2->master_bio;
 				rb2->master_bio = NULL;
 				put_buf(rb2);
 			}
@@ -2714,10 +2731,10 @@
 }
 
 static sector_t
-raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+raid10_size(struct mddev *mddev, sector_t sectors, int raid_disks)
 {
 	sector_t size;
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 
 	if (!raid_disks)
 		raid_disks = conf->raid_disks;
@@ -2733,9 +2750,9 @@
 }
 
 
-static conf_t *setup_conf(mddev_t *mddev)
+static struct r10conf *setup_conf(struct mddev *mddev)
 {
-	conf_t *conf = NULL;
+	struct r10conf *conf = NULL;
 	int nc, fc, fo;
 	sector_t stride, size;
 	int err = -EINVAL;
@@ -2760,7 +2777,7 @@
 	}
 
 	err = -ENOMEM;
-	conf = kzalloc(sizeof(conf_t), GFP_KERNEL);
+	conf = kzalloc(sizeof(struct r10conf), GFP_KERNEL);
 	if (!conf)
 		goto out;
 
@@ -2836,12 +2853,12 @@
 	return ERR_PTR(err);
 }
 
-static int run(mddev_t *mddev)
+static int run(struct mddev *mddev)
 {
-	conf_t *conf;
+	struct r10conf *conf;
 	int i, disk_idx, chunk_size;
-	mirror_info_t *disk;
-	mdk_rdev_t *rdev;
+	struct mirror_info *disk;
+	struct md_rdev *rdev;
 	sector_t size;
 
 	/*
@@ -2913,6 +2930,7 @@
 			if (disk->rdev)
 				conf->fullsync = 1;
 		}
+		disk->recovery_disabled = mddev->recovery_disabled - 1;
 	}
 
 	if (mddev->recovery_cp != MaxSector)
@@ -2966,9 +2984,9 @@
 	return -EIO;
 }
 
-static int stop(mddev_t *mddev)
+static int stop(struct mddev *mddev)
 {
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 
 	raise_barrier(conf, 0);
 	lower_barrier(conf);
@@ -2983,9 +3001,9 @@
 	return 0;
 }
 
-static void raid10_quiesce(mddev_t *mddev, int state)
+static void raid10_quiesce(struct mddev *mddev, int state)
 {
-	conf_t *conf = mddev->private;
+	struct r10conf *conf = mddev->private;
 
 	switch(state) {
 	case 1:
@@ -2997,10 +3015,10 @@
 	}
 }
 
-static void *raid10_takeover_raid0(mddev_t *mddev)
+static void *raid10_takeover_raid0(struct mddev *mddev)
 {
-	mdk_rdev_t *rdev;
-	conf_t *conf;
+	struct md_rdev *rdev;
+	struct r10conf *conf;
 
 	if (mddev->degraded > 0) {
 		printk(KERN_ERR "md/raid10:%s: Error: degraded raid0!\n",
@@ -3029,17 +3047,17 @@
 	return conf;
 }
 
-static void *raid10_takeover(mddev_t *mddev)
+static void *raid10_takeover(struct mddev *mddev)
 {
-	struct raid0_private_data *raid0_priv;
+	struct r0conf *raid0_conf;
 
 	/* raid10 can take over:
 	 *  raid0 - providing it has only two drives
 	 */
 	if (mddev->level == 0) {
 		/* for raid0 takeover only one zone is supported */
-		raid0_priv = mddev->private;
-		if (raid0_priv->nr_strip_zones > 1) {
+		raid0_conf = mddev->private;
+		if (raid0_conf->nr_strip_zones > 1) {
 			printk(KERN_ERR "md/raid10:%s: cannot takeover raid 0"
 			       " with more than one zone.\n",
 			       mdname(mddev));
@@ -3050,7 +3068,7 @@
 	return ERR_PTR(-EINVAL);
 }
 
-static struct mdk_personality raid10_personality =
+static struct md_personality raid10_personality =
 {
 	.name		= "raid10",
 	.level		= 10,
@@ -3086,3 +3104,5 @@
 MODULE_ALIAS("md-personality-9"); /* RAID10 */
 MODULE_ALIAS("md-raid10");
 MODULE_ALIAS("md-level-10");
+
+module_param(max_queued_requests, int, S_IRUGO|S_IWUSR);
diff -druN linux-libre-3.1-gnu/drivers/md/raid10.h linux-libre-3.2-gnu/drivers/md/raid10.h
--- linux-libre-3.1-gnu/drivers/md/raid10.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/raid10.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,10 +1,8 @@
 #ifndef _RAID10_H
 #define _RAID10_H
 
-typedef struct mirror_info mirror_info_t;
-
 struct mirror_info {
-	mdk_rdev_t	*rdev;
+	struct md_rdev	*rdev;
 	sector_t	head_position;
 	int		recovery_disabled;	/* matches
 						 * mddev->recovery_disabled
@@ -13,11 +11,9 @@
 						 */
 };
 
-typedef struct r10bio_s r10bio_t;
-
-struct r10_private_data_s {
-	mddev_t			*mddev;
-	mirror_info_t		*mirrors;
+struct r10conf {
+	struct mddev		*mddev;
+	struct mirror_info	*mirrors;
 	int			raid_disks;
 	spinlock_t		device_lock;
 
@@ -46,7 +42,7 @@
 	struct list_head	retry_list;
 	/* queue pending writes and submit them on unplug */
 	struct bio_list		pending_bio_list;
-
+	int			pending_count;
 
 	spinlock_t		resync_lock;
 	int nr_pending;
@@ -68,11 +64,9 @@
 	/* When taking over an array from a different personality, we store
 	 * the new thread here until we fully activate the array.
 	 */
-	struct mdk_thread_s	*thread;
+	struct md_thread	*thread;
 };
 
-typedef struct r10_private_data_s conf_t;
-
 /*
  * this is our 'private' RAID10 bio.
  *
@@ -80,14 +74,14 @@
  * for this RAID10 operation, and about their status:
  */
 
-struct r10bio_s {
+struct r10bio {
 	atomic_t		remaining; /* 'have we finished' count,
 					    * used from IRQ handlers
 					    */
 	sector_t		sector;	/* virtual sector number */
 	int			sectors;
 	unsigned long		state;
-	mddev_t			*mddev;
+	struct mddev		*mddev;
 	/*
 	 * original bio going to /dev/mdx
 	 */
diff -druN linux-libre-3.1-gnu/drivers/md/raid1.c linux-libre-3.2-gnu/drivers/md/raid1.c
--- linux-libre-3.1-gnu/drivers/md/raid1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/raid1.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,28 +34,31 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/blkdev.h>
+#include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/ratelimit.h>
 #include "md.h"
 #include "raid1.h"
 #include "bitmap.h"
 
-#define DEBUG 0
-#define PRINTK(x...) do { if (DEBUG) printk(x); } while (0)
-
 /*
  * Number of guaranteed r1bios in case of extreme VM load:
  */
 #define	NR_RAID1_BIOS 256
 
+/* When there are this many requests queue to be written by
+ * the raid1 thread, we become 'congested' to provide back-pressure
+ * for writeback.
+ */
+static int max_queued_requests = 1024;
 
-static void allow_barrier(conf_t *conf);
-static void lower_barrier(conf_t *conf);
+static void allow_barrier(struct r1conf *conf);
+static void lower_barrier(struct r1conf *conf);
 
 static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data)
 {
 	struct pool_info *pi = data;
-	int size = offsetof(r1bio_t, bios[pi->raid_disks]);
+	int size = offsetof(struct r1bio, bios[pi->raid_disks]);
 
 	/* allocate a r1bio with room for raid_disks entries in the bios array */
 	return kzalloc(size, gfp_flags);
@@ -76,7 +79,7 @@
 {
 	struct pool_info *pi = data;
 	struct page *page;
-	r1bio_t *r1_bio;
+	struct r1bio *r1_bio;
 	struct bio *bio;
 	int i, j;
 
@@ -142,7 +145,7 @@
 {
 	struct pool_info *pi = data;
 	int i,j;
-	r1bio_t *r1bio = __r1_bio;
+	struct r1bio *r1bio = __r1_bio;
 
 	for (i = 0; i < RESYNC_PAGES; i++)
 		for (j = pi->raid_disks; j-- ;) {
@@ -157,7 +160,7 @@
 	r1bio_pool_free(r1bio, data);
 }
 
-static void put_all_bios(conf_t *conf, r1bio_t *r1_bio)
+static void put_all_bios(struct r1conf *conf, struct r1bio *r1_bio)
 {
 	int i;
 
@@ -169,17 +172,17 @@
 	}
 }
 
-static void free_r1bio(r1bio_t *r1_bio)
+static void free_r1bio(struct r1bio *r1_bio)
 {
-	conf_t *conf = r1_bio->mddev->private;
+	struct r1conf *conf = r1_bio->mddev->private;
 
 	put_all_bios(conf, r1_bio);
 	mempool_free(r1_bio, conf->r1bio_pool);
 }
 
-static void put_buf(r1bio_t *r1_bio)
+static void put_buf(struct r1bio *r1_bio)
 {
-	conf_t *conf = r1_bio->mddev->private;
+	struct r1conf *conf = r1_bio->mddev->private;
 	int i;
 
 	for (i=0; i<conf->raid_disks; i++) {
@@ -193,11 +196,11 @@
 	lower_barrier(conf);
 }
 
-static void reschedule_retry(r1bio_t *r1_bio)
+static void reschedule_retry(struct r1bio *r1_bio)
 {
 	unsigned long flags;
-	mddev_t *mddev = r1_bio->mddev;
-	conf_t *conf = mddev->private;
+	struct mddev *mddev = r1_bio->mddev;
+	struct r1conf *conf = mddev->private;
 
 	spin_lock_irqsave(&conf->device_lock, flags);
 	list_add(&r1_bio->retry_list, &conf->retry_list);
@@ -213,11 +216,11 @@
  * operation and are ready to return a success/failure code to the buffer
  * cache layer.
  */
-static void call_bio_endio(r1bio_t *r1_bio)
+static void call_bio_endio(struct r1bio *r1_bio)
 {
 	struct bio *bio = r1_bio->master_bio;
 	int done;
-	conf_t *conf = r1_bio->mddev->private;
+	struct r1conf *conf = r1_bio->mddev->private;
 
 	if (bio->bi_phys_segments) {
 		unsigned long flags;
@@ -240,17 +243,17 @@
 	}
 }
 
-static void raid_end_bio_io(r1bio_t *r1_bio)
+static void raid_end_bio_io(struct r1bio *r1_bio)
 {
 	struct bio *bio = r1_bio->master_bio;
 
 	/* if nobody has done the final endio yet, do it now */
 	if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
-		PRINTK(KERN_DEBUG "raid1: sync end %s on sectors %llu-%llu\n",
-			(bio_data_dir(bio) == WRITE) ? "write" : "read",
-			(unsigned long long) bio->bi_sector,
-			(unsigned long long) bio->bi_sector +
-				(bio->bi_size >> 9) - 1);
+		pr_debug("raid1: sync end %s on sectors %llu-%llu\n",
+			 (bio_data_dir(bio) == WRITE) ? "write" : "read",
+			 (unsigned long long) bio->bi_sector,
+			 (unsigned long long) bio->bi_sector +
+			 (bio->bi_size >> 9) - 1);
 
 		call_bio_endio(r1_bio);
 	}
@@ -260,20 +263,38 @@
 /*
  * Update disk head position estimator based on IRQ completion info.
  */
-static inline void update_head_pos(int disk, r1bio_t *r1_bio)
+static inline void update_head_pos(int disk, struct r1bio *r1_bio)
 {
-	conf_t *conf = r1_bio->mddev->private;
+	struct r1conf *conf = r1_bio->mddev->private;
 
 	conf->mirrors[disk].head_position =
 		r1_bio->sector + (r1_bio->sectors);
 }
 
+/*
+ * Find the disk number which triggered given bio
+ */
+static int find_bio_disk(struct r1bio *r1_bio, struct bio *bio)
+{
+	int mirror;
+	int raid_disks = r1_bio->mddev->raid_disks;
+
+	for (mirror = 0; mirror < raid_disks; mirror++)
+		if (r1_bio->bios[mirror] == bio)
+			break;
+
+	BUG_ON(mirror == raid_disks);
+	update_head_pos(mirror, r1_bio);
+
+	return mirror;
+}
+
 static void raid1_end_read_request(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r1bio_t *r1_bio = bio->bi_private;
+	struct r1bio *r1_bio = bio->bi_private;
 	int mirror;
-	conf_t *conf = r1_bio->mddev->private;
+	struct r1conf *conf = r1_bio->mddev->private;
 
 	mirror = r1_bio->read_disk;
 	/*
@@ -318,7 +339,7 @@
 	rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
 }
 
-static void close_write(r1bio_t *r1_bio)
+static void close_write(struct r1bio *r1_bio)
 {
 	/* it really is the end of this request */
 	if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
@@ -337,7 +358,7 @@
 	md_write_end(r1_bio->mddev);
 }
 
-static void r1_bio_write_done(r1bio_t *r1_bio)
+static void r1_bio_write_done(struct r1bio *r1_bio)
 {
 	if (!atomic_dec_and_test(&r1_bio->remaining))
 		return;
@@ -356,15 +377,12 @@
 static void raid1_end_write_request(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r1bio_t *r1_bio = bio->bi_private;
+	struct r1bio *r1_bio = bio->bi_private;
 	int mirror, behind = test_bit(R1BIO_BehindIO, &r1_bio->state);
-	conf_t *conf = r1_bio->mddev->private;
+	struct r1conf *conf = r1_bio->mddev->private;
 	struct bio *to_put = NULL;
 
-
-	for (mirror = 0; mirror < conf->raid_disks; mirror++)
-		if (r1_bio->bios[mirror] == bio)
-			break;
+	mirror = find_bio_disk(r1_bio, bio);
 
 	/*
 	 * 'one mirror IO has finished' event handler:
@@ -400,8 +418,6 @@
 		}
 	}
 
-	update_head_pos(mirror, r1_bio);
-
 	if (behind) {
 		if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags))
 			atomic_dec(&r1_bio->behind_remaining);
@@ -418,10 +434,11 @@
 			/* Maybe we can return now */
 			if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
 				struct bio *mbio = r1_bio->master_bio;
-				PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n",
-				       (unsigned long long) mbio->bi_sector,
-				       (unsigned long long) mbio->bi_sector +
-				       (mbio->bi_size >> 9) - 1);
+				pr_debug("raid1: behind end write sectors"
+					 " %llu-%llu\n",
+					 (unsigned long long) mbio->bi_sector,
+					 (unsigned long long) mbio->bi_sector +
+					 (mbio->bi_size >> 9) - 1);
 				call_bio_endio(r1_bio);
 			}
 		}
@@ -455,7 +472,7 @@
  *
  * The rdev for the device selected will have nr_pending incremented.
  */
-static int read_balance(conf_t *conf, r1bio_t *r1_bio, int *max_sectors)
+static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sectors)
 {
 	const sector_t this_sector = r1_bio->sector;
 	int sectors;
@@ -464,7 +481,7 @@
 	int best_disk;
 	int i;
 	sector_t best_dist;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	int choose_first;
 
 	rcu_read_lock();
@@ -582,14 +599,18 @@
 	return best_disk;
 }
 
-int md_raid1_congested(mddev_t *mddev, int bits)
+int md_raid1_congested(struct mddev *mddev, int bits)
 {
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 	int i, ret = 0;
 
+	if ((bits & (1 << BDI_async_congested)) &&
+	    conf->pending_count >= max_queued_requests)
+		return 1;
+
 	rcu_read_lock();
 	for (i = 0; i < mddev->raid_disks; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
 		if (rdev && !test_bit(Faulty, &rdev->flags)) {
 			struct request_queue *q = bdev_get_queue(rdev->bdev);
 
@@ -611,13 +632,13 @@
 
 static int raid1_congested(void *data, int bits)
 {
-	mddev_t *mddev = data;
+	struct mddev *mddev = data;
 
 	return mddev_congested(mddev, bits) ||
 		md_raid1_congested(mddev, bits);
 }
 
-static void flush_pending_writes(conf_t *conf)
+static void flush_pending_writes(struct r1conf *conf)
 {
 	/* Any writes that have been queued but are awaiting
 	 * bitmap updates get flushed here.
@@ -627,10 +648,12 @@
 	if (conf->pending_bio_list.head) {
 		struct bio *bio;
 		bio = bio_list_get(&conf->pending_bio_list);
+		conf->pending_count = 0;
 		spin_unlock_irq(&conf->device_lock);
 		/* flush any pending bitmap writes to
 		 * disk before proceeding w/ I/O */
 		bitmap_unplug(conf->mddev->bitmap);
+		wake_up(&conf->wait_barrier);
 
 		while (bio) { /* submit pending writes */
 			struct bio *next = bio->bi_next;
@@ -665,7 +688,7 @@
  */
 #define RESYNC_DEPTH 32
 
-static void raise_barrier(conf_t *conf)
+static void raise_barrier(struct r1conf *conf)
 {
 	spin_lock_irq(&conf->resync_lock);
 
@@ -684,7 +707,7 @@
 	spin_unlock_irq(&conf->resync_lock);
 }
 
-static void lower_barrier(conf_t *conf)
+static void lower_barrier(struct r1conf *conf)
 {
 	unsigned long flags;
 	BUG_ON(conf->barrier <= 0);
@@ -694,7 +717,7 @@
 	wake_up(&conf->wait_barrier);
 }
 
-static void wait_barrier(conf_t *conf)
+static void wait_barrier(struct r1conf *conf)
 {
 	spin_lock_irq(&conf->resync_lock);
 	if (conf->barrier) {
@@ -708,7 +731,7 @@
 	spin_unlock_irq(&conf->resync_lock);
 }
 
-static void allow_barrier(conf_t *conf)
+static void allow_barrier(struct r1conf *conf)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&conf->resync_lock, flags);
@@ -717,7 +740,7 @@
 	wake_up(&conf->wait_barrier);
 }
 
-static void freeze_array(conf_t *conf)
+static void freeze_array(struct r1conf *conf)
 {
 	/* stop syncio and normal IO and wait for everything to
 	 * go quite.
@@ -740,7 +763,7 @@
 			    flush_pending_writes(conf));
 	spin_unlock_irq(&conf->resync_lock);
 }
-static void unfreeze_array(conf_t *conf)
+static void unfreeze_array(struct r1conf *conf)
 {
 	/* reverse the effect of the freeze */
 	spin_lock_irq(&conf->resync_lock);
@@ -753,7 +776,7 @@
 
 /* duplicate the data pages for behind I/O 
  */
-static void alloc_behind_pages(struct bio *bio, r1bio_t *r1_bio)
+static void alloc_behind_pages(struct bio *bio, struct r1bio *r1_bio)
 {
 	int i;
 	struct bio_vec *bvec;
@@ -782,14 +805,14 @@
 		if (bvecs[i].bv_page)
 			put_page(bvecs[i].bv_page);
 	kfree(bvecs);
-	PRINTK("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
+	pr_debug("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
 }
 
-static int make_request(mddev_t *mddev, struct bio * bio)
+static void make_request(struct mddev *mddev, struct bio * bio)
 {
-	conf_t *conf = mddev->private;
-	mirror_info_t *mirror;
-	r1bio_t *r1_bio;
+	struct r1conf *conf = mddev->private;
+	struct mirror_info *mirror;
+	struct r1bio *r1_bio;
 	struct bio *read_bio;
 	int i, disks;
 	struct bitmap *bitmap;
@@ -797,7 +820,7 @@
 	const int rw = bio_data_dir(bio);
 	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;
+	struct md_rdev *blocked_rdev;
 	int plugged;
 	int first_clone;
 	int sectors_handled;
@@ -870,7 +893,7 @@
 		if (rdisk < 0) {
 			/* couldn't find anywhere to read from */
 			raid_end_bio_io(r1_bio);
-			return 0;
+			return;
 		}
 		mirror = conf->mirrors + rdisk;
 
@@ -928,12 +951,17 @@
 			goto read_again;
 		} else
 			generic_make_request(read_bio);
-		return 0;
+		return;
 	}
 
 	/*
 	 * WRITE:
 	 */
+	if (conf->pending_count >= max_queued_requests) {
+		md_wakeup_thread(mddev->thread);
+		wait_event(conf->wait_barrier,
+			   conf->pending_count < max_queued_requests);
+	}
 	/* first select target devices under rcu_lock and
 	 * inc refcount on their rdev.  Record them by setting
 	 * bios[x] to bio
@@ -952,7 +980,7 @@
 	rcu_read_lock();
 	max_sectors = r1_bio->sectors;
 	for (i = 0;  i < disks; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
 		if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
 			atomic_inc(&rdev->nr_pending);
 			blocked_rdev = rdev;
@@ -1097,6 +1125,7 @@
 		atomic_inc(&r1_bio->remaining);
 		spin_lock_irqsave(&conf->device_lock, flags);
 		bio_list_add(&conf->pending_bio_list, mbio);
+		conf->pending_count++;
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 	}
 	/* Mustn't call r1_bio_write_done before this next test,
@@ -1123,20 +1152,18 @@
 
 	if (do_sync || !bitmap || !plugged)
 		md_wakeup_thread(mddev->thread);
-
-	return 0;
 }
 
-static void status(struct seq_file *seq, mddev_t *mddev)
+static void status(struct seq_file *seq, struct mddev *mddev)
 {
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 	int i;
 
 	seq_printf(seq, " [%d/%d] [", conf->raid_disks,
 		   conf->raid_disks - mddev->degraded);
 	rcu_read_lock();
 	for (i = 0; i < conf->raid_disks; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
 		seq_printf(seq, "%s",
 			   rdev && test_bit(In_sync, &rdev->flags) ? "U" : "_");
 	}
@@ -1145,10 +1172,10 @@
 }
 
 
-static void error(mddev_t *mddev, mdk_rdev_t *rdev)
+static void error(struct mddev *mddev, struct md_rdev *rdev)
 {
 	char b[BDEVNAME_SIZE];
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 
 	/*
 	 * If it is not operational, then we have already marked it as dead
@@ -1188,7 +1215,7 @@
 	       mdname(mddev), conf->raid_disks - mddev->degraded);
 }
 
-static void print_conf(conf_t *conf)
+static void print_conf(struct r1conf *conf)
 {
 	int i;
 
@@ -1203,7 +1230,7 @@
 	rcu_read_lock();
 	for (i = 0; i < conf->raid_disks; i++) {
 		char b[BDEVNAME_SIZE];
-		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
 		if (rdev)
 			printk(KERN_DEBUG " disk %d, wo:%d, o:%d, dev:%s\n",
 			       i, !test_bit(In_sync, &rdev->flags),
@@ -1213,7 +1240,7 @@
 	rcu_read_unlock();
 }
 
-static void close_sync(conf_t *conf)
+static void close_sync(struct r1conf *conf)
 {
 	wait_barrier(conf);
 	allow_barrier(conf);
@@ -1222,10 +1249,10 @@
 	conf->r1buf_pool = NULL;
 }
 
-static int raid1_spare_active(mddev_t *mddev)
+static int raid1_spare_active(struct mddev *mddev)
 {
 	int i;
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 	int count = 0;
 	unsigned long flags;
 
@@ -1235,7 +1262,7 @@
 	 * Called under mddev lock, so rcu protection not needed.
 	 */
 	for (i = 0; i < conf->raid_disks; i++) {
-		mdk_rdev_t *rdev = conf->mirrors[i].rdev;
+		struct md_rdev *rdev = conf->mirrors[i].rdev;
 		if (rdev
 		    && !test_bit(Faulty, &rdev->flags)
 		    && !test_and_set_bit(In_sync, &rdev->flags)) {
@@ -1252,12 +1279,12 @@
 }
 
 
-static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
 {
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 	int err = -EEXIST;
 	int mirror = 0;
-	mirror_info_t *p;
+	struct mirror_info *p;
 	int first = 0;
 	int last = mddev->raid_disks - 1;
 
@@ -1300,12 +1327,12 @@
 	return err;
 }
 
-static int raid1_remove_disk(mddev_t *mddev, int number)
+static int raid1_remove_disk(struct mddev *mddev, int number)
 {
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 	int err = 0;
-	mdk_rdev_t *rdev;
-	mirror_info_t *p = conf->mirrors+ number;
+	struct md_rdev *rdev;
+	struct mirror_info *p = conf->mirrors+ number;
 
 	print_conf(conf);
 	rdev = p->rdev;
@@ -1343,14 +1370,10 @@
 
 static void end_sync_read(struct bio *bio, int error)
 {
-	r1bio_t *r1_bio = bio->bi_private;
-	int i;
+	struct r1bio *r1_bio = bio->bi_private;
+
+	update_head_pos(r1_bio->read_disk, r1_bio);
 
-	for (i=r1_bio->mddev->raid_disks; i--; )
-		if (r1_bio->bios[i] == bio)
-			break;
-	BUG_ON(i < 0);
-	update_head_pos(i, r1_bio);
 	/*
 	 * we have read a block, now it needs to be re-written,
 	 * or re-read if the read failed.
@@ -1366,19 +1389,15 @@
 static void end_sync_write(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r1bio_t *r1_bio = bio->bi_private;
-	mddev_t *mddev = r1_bio->mddev;
-	conf_t *conf = mddev->private;
-	int i;
+	struct r1bio *r1_bio = bio->bi_private;
+	struct mddev *mddev = r1_bio->mddev;
+	struct r1conf *conf = mddev->private;
 	int mirror=0;
 	sector_t first_bad;
 	int bad_sectors;
 
-	for (i = 0; i < conf->raid_disks; i++)
-		if (r1_bio->bios[i] == bio) {
-			mirror = i;
-			break;
-		}
+	mirror = find_bio_disk(r1_bio, bio);
+
 	if (!uptodate) {
 		sector_t sync_blocks = 0;
 		sector_t s = r1_bio->sector;
@@ -1404,8 +1423,6 @@
 		)
 		set_bit(R1BIO_MadeGood, &r1_bio->state);
 
-	update_head_pos(mirror, r1_bio);
-
 	if (atomic_dec_and_test(&r1_bio->remaining)) {
 		int s = r1_bio->sectors;
 		if (test_bit(R1BIO_MadeGood, &r1_bio->state) ||
@@ -1418,7 +1435,7 @@
 	}
 }
 
-static int r1_sync_page_io(mdk_rdev_t *rdev, sector_t sector,
+static int r1_sync_page_io(struct md_rdev *rdev, sector_t sector,
 			    int sectors, struct page *page, int rw)
 {
 	if (sync_page_io(rdev, sector, sectors << 9, page, rw, false))
@@ -1432,7 +1449,7 @@
 	return 0;
 }
 
-static int fix_sync_read_error(r1bio_t *r1_bio)
+static int fix_sync_read_error(struct r1bio *r1_bio)
 {
 	/* Try some synchronous reads of other devices to get
 	 * good data, much like with normal read errors.  Only
@@ -1445,8 +1462,8 @@
 	 * made sure that anything with a bad block in range
 	 * will have bi_end_io clear.
 	 */
-	mddev_t *mddev = r1_bio->mddev;
-	conf_t *conf = mddev->private;
+	struct mddev *mddev = r1_bio->mddev;
+	struct r1conf *conf = mddev->private;
 	struct bio *bio = r1_bio->bios[r1_bio->read_disk];
 	sector_t sect = r1_bio->sector;
 	int sectors = r1_bio->sectors;
@@ -1456,7 +1473,7 @@
 		int s = sectors;
 		int d = r1_bio->read_disk;
 		int success = 0;
-		mdk_rdev_t *rdev;
+		struct md_rdev *rdev;
 		int start;
 
 		if (s > (PAGE_SIZE>>9))
@@ -1501,7 +1518,8 @@
 					abort = 1;
 			}
 			if (abort) {
-				mddev->recovery_disabled = 1;
+				conf->recovery_disabled =
+					mddev->recovery_disabled;
 				set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 				md_done_sync(mddev, r1_bio->sectors, 0);
 				put_buf(r1_bio);
@@ -1552,7 +1570,7 @@
 	return 1;
 }
 
-static int process_checks(r1bio_t *r1_bio)
+static int process_checks(struct r1bio *r1_bio)
 {
 	/* We have read all readable devices.  If we haven't
 	 * got the block, then there is no hope left.
@@ -1561,8 +1579,8 @@
 	 * If any blocks failed to read, then we need to
 	 * attempt an over-write
 	 */
-	mddev_t *mddev = r1_bio->mddev;
-	conf_t *conf = mddev->private;
+	struct mddev *mddev = r1_bio->mddev;
+	struct r1conf *conf = mddev->private;
 	int primary;
 	int i;
 
@@ -1634,9 +1652,9 @@
 	return 0;
 }
 
-static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
+static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio)
 {
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 	int i;
 	int disks = conf->raid_disks;
 	struct bio *bio, *wbio;
@@ -1686,16 +1704,16 @@
  *	3.	Performs writes following reads for array synchronising.
  */
 
-static void fix_read_error(conf_t *conf, int read_disk,
+static void fix_read_error(struct r1conf *conf, int read_disk,
 			   sector_t sect, int sectors)
 {
-	mddev_t *mddev = conf->mddev;
+	struct mddev *mddev = conf->mddev;
 	while(sectors) {
 		int s = sectors;
 		int d = read_disk;
 		int success = 0;
 		int start;
-		mdk_rdev_t *rdev;
+		struct md_rdev *rdev;
 
 		if (s > (PAGE_SIZE>>9))
 			s = PAGE_SIZE >> 9;
@@ -1726,7 +1744,7 @@
 
 		if (!success) {
 			/* Cannot read from anywhere - mark it bad */
-			mdk_rdev_t *rdev = conf->mirrors[read_disk].rdev;
+			struct md_rdev *rdev = conf->mirrors[read_disk].rdev;
 			if (!rdev_set_badblocks(rdev, sect, s, 0))
 				md_error(mddev, rdev);
 			break;
@@ -1789,11 +1807,11 @@
 	return test_bit(BIO_UPTODATE, &bio->bi_flags);
 }
 
-static int narrow_write_error(r1bio_t *r1_bio, int i)
+static int narrow_write_error(struct r1bio *r1_bio, int i)
 {
-	mddev_t *mddev = r1_bio->mddev;
-	conf_t *conf = mddev->private;
-	mdk_rdev_t *rdev = conf->mirrors[i].rdev;
+	struct mddev *mddev = r1_bio->mddev;
+	struct r1conf *conf = mddev->private;
+	struct md_rdev *rdev = conf->mirrors[i].rdev;
 	int vcnt, idx;
 	struct bio_vec *vec;
 
@@ -1865,12 +1883,12 @@
 	return ok;
 }
 
-static void handle_sync_write_finished(conf_t *conf, r1bio_t *r1_bio)
+static void handle_sync_write_finished(struct r1conf *conf, struct r1bio *r1_bio)
 {
 	int m;
 	int s = r1_bio->sectors;
 	for (m = 0; m < conf->raid_disks ; m++) {
-		mdk_rdev_t *rdev = conf->mirrors[m].rdev;
+		struct md_rdev *rdev = conf->mirrors[m].rdev;
 		struct bio *bio = r1_bio->bios[m];
 		if (bio->bi_end_io == NULL)
 			continue;
@@ -1888,12 +1906,12 @@
 	md_done_sync(conf->mddev, s, 1);
 }
 
-static void handle_write_finished(conf_t *conf, r1bio_t *r1_bio)
+static void handle_write_finished(struct r1conf *conf, struct r1bio *r1_bio)
 {
 	int m;
 	for (m = 0; m < conf->raid_disks ; m++)
 		if (r1_bio->bios[m] == IO_MADE_GOOD) {
-			mdk_rdev_t *rdev = conf->mirrors[m].rdev;
+			struct md_rdev *rdev = conf->mirrors[m].rdev;
 			rdev_clear_badblocks(rdev,
 					     r1_bio->sector,
 					     r1_bio->sectors);
@@ -1917,14 +1935,14 @@
 	raid_end_bio_io(r1_bio);
 }
 
-static void handle_read_error(conf_t *conf, r1bio_t *r1_bio)
+static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)
 {
 	int disk;
 	int max_sectors;
-	mddev_t *mddev = conf->mddev;
+	struct mddev *mddev = conf->mddev;
 	struct bio *bio;
 	char b[BDEVNAME_SIZE];
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	clear_bit(R1BIO_ReadError, &r1_bio->state);
 	/* we got a read error. Maybe the drive is bad.  Maybe just
@@ -2007,11 +2025,11 @@
 	}
 }
 
-static void raid1d(mddev_t *mddev)
+static void raid1d(struct mddev *mddev)
 {
-	r1bio_t *r1_bio;
+	struct r1bio *r1_bio;
 	unsigned long flags;
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 	struct list_head *head = &conf->retry_list;
 	struct blk_plug plug;
 
@@ -2028,7 +2046,7 @@
 			spin_unlock_irqrestore(&conf->device_lock, flags);
 			break;
 		}
-		r1_bio = list_entry(head->prev, r1bio_t, retry_list);
+		r1_bio = list_entry(head->prev, struct r1bio, retry_list);
 		list_del(head->prev);
 		conf->nr_queued--;
 		spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -2060,7 +2078,7 @@
 }
 
 
-static int init_resync(conf_t *conf)
+static int init_resync(struct r1conf *conf)
 {
 	int buffs;
 
@@ -2084,10 +2102,10 @@
  * that can be installed to exclude normal IO requests.
  */
 
-static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
+static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
-	conf_t *conf = mddev->private;
-	r1bio_t *r1_bio;
+	struct r1conf *conf = mddev->private;
+	struct r1bio *r1_bio;
 	struct bio *bio;
 	sector_t max_sector, nr_sectors;
 	int disk = -1;
@@ -2167,14 +2185,13 @@
 	set_bit(R1BIO_IsSync, &r1_bio->state);
 
 	for (i=0; i < conf->raid_disks; i++) {
-		mdk_rdev_t *rdev;
+		struct md_rdev *rdev;
 		bio = r1_bio->bios[i];
 
 		/* take from bio_init */
 		bio->bi_next = NULL;
 		bio->bi_flags &= ~(BIO_POOL_MASK-1);
 		bio->bi_flags |= 1 << BIO_UPTODATE;
-		bio->bi_comp_cpu = -1;
 		bio->bi_rw = READ;
 		bio->bi_vcnt = 0;
 		bio->bi_idx = 0;
@@ -2239,7 +2256,7 @@
 		int ok = 1;
 		for (i = 0 ; i < conf->raid_disks ; i++)
 			if (r1_bio->bios[i]->bi_end_io == end_sync_write) {
-				mdk_rdev_t *rdev =
+				struct md_rdev *rdev =
 					rcu_dereference(conf->mirrors[i].rdev);
 				ok = rdev_set_badblocks(rdev, sector_nr,
 							min_bad, 0
@@ -2356,7 +2373,7 @@
 	return nr_sectors;
 }
 
-static sector_t raid1_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+static sector_t raid1_size(struct mddev *mddev, sector_t sectors, int raid_disks)
 {
 	if (sectors)
 		return sectors;
@@ -2364,15 +2381,15 @@
 	return mddev->dev_sectors;
 }
 
-static conf_t *setup_conf(mddev_t *mddev)
+static struct r1conf *setup_conf(struct mddev *mddev)
 {
-	conf_t *conf;
+	struct r1conf *conf;
 	int i;
-	mirror_info_t *disk;
-	mdk_rdev_t *rdev;
+	struct mirror_info *disk;
+	struct md_rdev *rdev;
 	int err = -ENOMEM;
 
-	conf = kzalloc(sizeof(conf_t), GFP_KERNEL);
+	conf = kzalloc(sizeof(struct r1conf), GFP_KERNEL);
 	if (!conf)
 		goto abort;
 
@@ -2417,6 +2434,8 @@
 	init_waitqueue_head(&conf->wait_barrier);
 
 	bio_list_init(&conf->pending_bio_list);
+	conf->pending_count = 0;
+	conf->recovery_disabled = mddev->recovery_disabled - 1;
 
 	conf->last_used = -1;
 	for (i = 0; i < conf->raid_disks; i++) {
@@ -2465,11 +2484,11 @@
 	return ERR_PTR(err);
 }
 
-static int run(mddev_t *mddev)
+static int run(struct mddev *mddev)
 {
-	conf_t *conf;
+	struct r1conf *conf;
 	int i;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	if (mddev->level != 1) {
 		printk(KERN_ERR "md/raid1:%s: raid level not set to mirroring (%d)\n",
@@ -2545,9 +2564,9 @@
 	return md_integrity_register(mddev);
 }
 
-static int stop(mddev_t *mddev)
+static int stop(struct mddev *mddev)
 {
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 	struct bitmap *bitmap = mddev->bitmap;
 
 	/* wait for behind writes to complete */
@@ -2572,7 +2591,7 @@
 	return 0;
 }
 
-static int raid1_resize(mddev_t *mddev, sector_t sectors)
+static int raid1_resize(struct mddev *mddev, sector_t sectors)
 {
 	/* no resync is happening, and there is enough space
 	 * on all devices, so we can resize.
@@ -2596,7 +2615,7 @@
 	return 0;
 }
 
-static int raid1_reshape(mddev_t *mddev)
+static int raid1_reshape(struct mddev *mddev)
 {
 	/* We need to:
 	 * 1/ resize the r1bio_pool
@@ -2611,8 +2630,8 @@
 	 */
 	mempool_t *newpool, *oldpool;
 	struct pool_info *newpoolinfo;
-	mirror_info_t *newmirrors;
-	conf_t *conf = mddev->private;
+	struct mirror_info *newmirrors;
+	struct r1conf *conf = mddev->private;
 	int cnt, raid_disks;
 	unsigned long flags;
 	int d, d2, err;
@@ -2668,7 +2687,7 @@
 	conf->r1bio_pool = newpool;
 
 	for (d = d2 = 0; d < conf->raid_disks; d++) {
-		mdk_rdev_t *rdev = conf->mirrors[d].rdev;
+		struct md_rdev *rdev = conf->mirrors[d].rdev;
 		if (rdev && rdev->raid_disk != d2) {
 			sysfs_unlink_rdev(mddev, rdev);
 			rdev->raid_disk = d2;
@@ -2702,9 +2721,9 @@
 	return 0;
 }
 
-static void raid1_quiesce(mddev_t *mddev, int state)
+static void raid1_quiesce(struct mddev *mddev, int state)
 {
-	conf_t *conf = mddev->private;
+	struct r1conf *conf = mddev->private;
 
 	switch(state) {
 	case 2: /* wake for suspend */
@@ -2719,13 +2738,13 @@
 	}
 }
 
-static void *raid1_takeover(mddev_t *mddev)
+static void *raid1_takeover(struct mddev *mddev)
 {
 	/* raid1 can take over:
 	 *  raid5 with 2 devices, any layout or chunk size
 	 */
 	if (mddev->level == 5 && mddev->raid_disks == 2) {
-		conf_t *conf;
+		struct r1conf *conf;
 		mddev->new_level = 1;
 		mddev->new_layout = 0;
 		mddev->new_chunk_sectors = 0;
@@ -2737,7 +2756,7 @@
 	return ERR_PTR(-EINVAL);
 }
 
-static struct mdk_personality raid1_personality =
+static struct md_personality raid1_personality =
 {
 	.name		= "raid1",
 	.level		= 1,
@@ -2775,3 +2794,5 @@
 MODULE_ALIAS("md-personality-3"); /* RAID1 */
 MODULE_ALIAS("md-raid1");
 MODULE_ALIAS("md-level-1");
+
+module_param(max_queued_requests, int, S_IRUGO|S_IWUSR);
diff -druN linux-libre-3.1-gnu/drivers/md/raid1.h linux-libre-3.2-gnu/drivers/md/raid1.h
--- linux-libre-3.1-gnu/drivers/md/raid1.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/raid1.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,10 +1,8 @@
 #ifndef _RAID1_H
 #define _RAID1_H
 
-typedef struct mirror_info mirror_info_t;
-
 struct mirror_info {
-	mdk_rdev_t	*rdev;
+	struct md_rdev	*rdev;
 	sector_t	head_position;
 };
 
@@ -17,61 +15,82 @@
  */
 
 struct pool_info {
-	mddev_t *mddev;
+	struct mddev *mddev;
 	int	raid_disks;
 };
 
-
-typedef struct r1bio_s r1bio_t;
-
-struct r1_private_data_s {
-	mddev_t			*mddev;
-	mirror_info_t		*mirrors;
+struct r1conf {
+	struct mddev		*mddev;
+	struct mirror_info		*mirrors;
 	int			raid_disks;
+
+	/* When choose the best device for a read (read_balance())
+	 * we try to keep sequential reads one the same device
+	 * using 'last_used' and 'next_seq_sect'
+	 */
 	int			last_used;
 	sector_t		next_seq_sect;
+	/* During resync, read_balancing is only allowed on the part
+	 * of the array that has been resynced.  'next_resync' tells us
+	 * where that is.
+	 */
+	sector_t		next_resync;
+
 	spinlock_t		device_lock;
 
+	/* list of 'struct r1bio' that need to be processed by raid1d,
+	 * whether to retry a read, writeout a resync or recovery
+	 * block, or anything else.
+	 */
 	struct list_head	retry_list;
-	/* queue pending writes and submit them on unplug */
-	struct bio_list		pending_bio_list;
 
-	/* for use when syncing mirrors: */
+	/* queue pending writes to be submitted on unplug */
+	struct bio_list		pending_bio_list;
+	int			pending_count;
 
+	/* for use when syncing mirrors:
+	 * We don't allow both normal IO and resync/recovery IO at
+	 * the same time - resync/recovery can only happen when there
+	 * is no other IO.  So when either is active, the other has to wait.
+	 * See more details description in raid1.c near raise_barrier().
+	 */
+	wait_queue_head_t	wait_barrier;
 	spinlock_t		resync_lock;
 	int			nr_pending;
 	int			nr_waiting;
 	int			nr_queued;
 	int			barrier;
-	sector_t		next_resync;
-	int			fullsync;  /* set to 1 if a full sync is needed,
-					    * (fresh device added).
-					    * Cleared when a sync completes.
-					    */
-	int			recovery_disabled; /* when the same as
-						    * mddev->recovery_disabled
-						    * we don't allow recovery
-						    * to be attempted as we
-						    * expect a read error
-						    */
 
-	wait_queue_head_t	wait_barrier;
+	/* Set to 1 if a full sync is needed, (fresh device added).
+	 * Cleared when a sync completes.
+	 */
+	int			fullsync;
+
+	/* When the same as mddev->recovery_disabled we don't allow
+	 * recovery to be attempted as we expect a read error.
+	 */
+	int			recovery_disabled;
 
+
+	/* poolinfo contains information about the content of the
+	 * mempools - it changes when the array grows or shrinks
+	 */
 	struct pool_info	*poolinfo;
+	mempool_t		*r1bio_pool;
+	mempool_t		*r1buf_pool;
 
+	/* temporary buffer to synchronous IO when attempting to repair
+	 * a read error.
+	 */
 	struct page		*tmppage;
 
-	mempool_t *r1bio_pool;
-	mempool_t *r1buf_pool;
 
 	/* When taking over an array from a different personality, we store
 	 * the new thread here until we fully activate the array.
 	 */
-	struct mdk_thread_s	*thread;
+	struct md_thread	*thread;
 };
 
-typedef struct r1_private_data_s conf_t;
-
 /*
  * this is our 'private' RAID1 bio.
  *
@@ -79,7 +98,7 @@
  * for this RAID1 operation, and about their status:
  */
 
-struct r1bio_s {
+struct r1bio {
 	atomic_t		remaining; /* 'have we finished' count,
 					    * used from IRQ handlers
 					    */
@@ -89,7 +108,7 @@
 	sector_t		sector;
 	int			sectors;
 	unsigned long		state;
-	mddev_t			*mddev;
+	struct mddev		*mddev;
 	/*
 	 * original bio going to /dev/mdx
 	 */
@@ -148,6 +167,6 @@
 #define	R1BIO_MadeGood 7
 #define	R1BIO_WriteError 8
 
-extern int md_raid1_congested(mddev_t *mddev, int bits);
+extern int md_raid1_congested(struct mddev *mddev, int bits);
 
 #endif
diff -druN linux-libre-3.1-gnu/drivers/md/raid5.c linux-libre-3.2-gnu/drivers/md/raid5.c
--- linux-libre-3.1-gnu/drivers/md/raid5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/raid5.c	2012-01-04 18:55:44.000000000 -0500
@@ -47,6 +47,7 @@
 #include <linux/kthread.h>
 #include <linux/raid/pq.h>
 #include <linux/async_tx.h>
+#include <linux/module.h>
 #include <linux/async.h>
 #include <linux/seq_file.h>
 #include <linux/cpu.h>
@@ -70,7 +71,11 @@
 #define NR_HASH			(PAGE_SIZE / sizeof(struct hlist_head))
 #define HASH_MASK		(NR_HASH - 1)
 
-#define stripe_hash(conf, sect)	(&((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK]))
+static inline struct hlist_head *stripe_hash(struct r5conf *conf, sector_t sect)
+{
+	int hash = (sect >> STRIPE_SHIFT) & HASH_MASK;
+	return &conf->stripe_hashtbl[hash];
+}
 
 /* bio's attached to a stripe+device for I/O are linked together in bi_sector
  * order without overlap.  There may be several bio's per stripe+device, and
@@ -78,24 +83,17 @@
  * When walking this list for a particular stripe+device, we must never proceed
  * beyond a bio that extends past this device, as the next bio might no longer
  * be valid.
- * This macro is used to determine the 'next' bio in the list, given the sector
+ * This function is used to determine the 'next' bio in the list, given the sector
  * of the current stripe+device
  */
-#define r5_next_bio(bio, sect) ( ( (bio)->bi_sector + ((bio)->bi_size>>9) < sect + STRIPE_SECTORS) ? (bio)->bi_next : NULL)
-/*
- * The following can be used to debug the driver
- */
-#define RAID5_PARANOIA	1
-#if RAID5_PARANOIA && defined(CONFIG_SMP)
-# define CHECK_DEVLOCK() assert_spin_locked(&conf->device_lock)
-#else
-# define CHECK_DEVLOCK()
-#endif
-
-#ifdef DEBUG
-#define inline
-#define __inline__
-#endif
+static inline struct bio *r5_next_bio(struct bio *bio, sector_t sector)
+{
+	int sectors = bio->bi_size >> 9;
+	if (bio->bi_sector + sectors < sector + STRIPE_SECTORS)
+		return bio->bi_next;
+	else
+		return NULL;
+}
 
 /*
  * We maintain a biased count of active stripes in the bottom 16 bits of
@@ -183,7 +181,7 @@
 	}
 }
 
-static void print_raid5_conf (raid5_conf_t *conf);
+static void print_raid5_conf (struct r5conf *conf);
 
 static int stripe_operations_active(struct stripe_head *sh)
 {
@@ -192,7 +190,7 @@
 	       test_bit(STRIPE_COMPUTE_RUN, &sh->state);
 }
 
-static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
+static void __release_stripe(struct r5conf *conf, struct stripe_head *sh)
 {
 	if (atomic_dec_and_test(&sh->count)) {
 		BUG_ON(!list_empty(&sh->lru));
@@ -228,7 +226,7 @@
 
 static void release_stripe(struct stripe_head *sh)
 {
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	unsigned long flags;
 
 	spin_lock_irqsave(&conf->device_lock, flags);
@@ -244,25 +242,23 @@
 	hlist_del_init(&sh->hash);
 }
 
-static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh)
+static inline void insert_hash(struct r5conf *conf, struct stripe_head *sh)
 {
 	struct hlist_head *hp = stripe_hash(conf, sh->sector);
 
 	pr_debug("insert_hash(), stripe %llu\n",
 		(unsigned long long)sh->sector);
 
-	CHECK_DEVLOCK();
 	hlist_add_head(&sh->hash, hp);
 }
 
 
 /* find an idle stripe, make sure it is unhashed, and return it. */
-static struct stripe_head *get_free_stripe(raid5_conf_t *conf)
+static struct stripe_head *get_free_stripe(struct r5conf *conf)
 {
 	struct stripe_head *sh = NULL;
 	struct list_head *first;
 
-	CHECK_DEVLOCK();
 	if (list_empty(&conf->inactive_list))
 		goto out;
 	first = conf->inactive_list.next;
@@ -306,19 +302,18 @@
 }
 
 static void raid5_build_block(struct stripe_head *sh, int i, int previous);
-static void stripe_set_idx(sector_t stripe, raid5_conf_t *conf, int previous,
+static void stripe_set_idx(sector_t stripe, struct r5conf *conf, int previous,
 			    struct stripe_head *sh);
 
 static void init_stripe(struct stripe_head *sh, sector_t sector, int previous)
 {
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int i;
 
 	BUG_ON(atomic_read(&sh->count) != 0);
 	BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
 	BUG_ON(stripe_operations_active(sh));
 
-	CHECK_DEVLOCK();
 	pr_debug("init_stripe called, stripe %llu\n",
 		(unsigned long long)sh->sector);
 
@@ -348,13 +343,12 @@
 	insert_hash(conf, sh);
 }
 
-static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector,
+static struct stripe_head *__find_stripe(struct r5conf *conf, sector_t sector,
 					 short generation)
 {
 	struct stripe_head *sh;
 	struct hlist_node *hn;
 
-	CHECK_DEVLOCK();
 	pr_debug("__find_stripe, sector %llu\n", (unsigned long long)sector);
 	hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash)
 		if (sh->sector == sector && sh->generation == generation)
@@ -376,7 +370,7 @@
  * of the two sections, and some non-in_sync devices may
  * be insync in the section most affected by failed devices.
  */
-static int has_failed(raid5_conf_t *conf)
+static int has_failed(struct r5conf *conf)
 {
 	int degraded;
 	int i;
@@ -386,7 +380,7 @@
 	rcu_read_lock();
 	degraded = 0;
 	for (i = 0; i < conf->previous_raid_disks; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev);
 		if (!rdev || test_bit(Faulty, &rdev->flags))
 			degraded++;
 		else if (test_bit(In_sync, &rdev->flags))
@@ -410,7 +404,7 @@
 	rcu_read_lock();
 	degraded = 0;
 	for (i = 0; i < conf->raid_disks; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
+		struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev);
 		if (!rdev || test_bit(Faulty, &rdev->flags))
 			degraded++;
 		else if (test_bit(In_sync, &rdev->flags))
@@ -431,7 +425,7 @@
 }
 
 static struct stripe_head *
-get_active_stripe(raid5_conf_t *conf, sector_t sector,
+get_active_stripe(struct r5conf *conf, sector_t sector,
 		  int previous, int noblock, int noquiesce)
 {
 	struct stripe_head *sh;
@@ -491,7 +485,7 @@
 
 static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 {
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int i, disks = sh->disks;
 
 	might_sleep();
@@ -499,7 +493,7 @@
 	for (i = disks; i--; ) {
 		int rw;
 		struct bio *bi;
-		mdk_rdev_t *rdev;
+		struct md_rdev *rdev;
 		if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags)) {
 			if (test_and_clear_bit(R5_WantFUA, &sh->dev[i].flags))
 				rw = WRITE_FUA;
@@ -650,7 +644,7 @@
 {
 	struct stripe_head *sh = stripe_head_ref;
 	struct bio *return_bi = NULL;
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int i;
 
 	pr_debug("%s: stripe %llu\n", __func__,
@@ -695,7 +689,7 @@
 static void ops_run_biofill(struct stripe_head *sh)
 {
 	struct dma_async_tx_descriptor *tx = NULL;
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	struct async_submit_ctl submit;
 	int i;
 
@@ -1246,7 +1240,7 @@
 {
 	int overlap_clear = 0, i, disks = sh->disks;
 	struct dma_async_tx_descriptor *tx = NULL;
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int level = conf->level;
 	struct raid5_percpu *percpu;
 	unsigned long cpu;
@@ -1337,7 +1331,7 @@
 #define raid_run_ops __raid_run_ops
 #endif
 
-static int grow_one_stripe(raid5_conf_t *conf)
+static int grow_one_stripe(struct r5conf *conf)
 {
 	struct stripe_head *sh;
 	sh = kmem_cache_zalloc(conf->slab_cache, GFP_KERNEL);
@@ -1362,7 +1356,7 @@
 	return 1;
 }
 
-static int grow_stripes(raid5_conf_t *conf, int num)
+static int grow_stripes(struct r5conf *conf, int num)
 {
 	struct kmem_cache *sc;
 	int devs = max(conf->raid_disks, conf->previous_raid_disks);
@@ -1411,7 +1405,7 @@
 	return len;
 }
 
-static int resize_stripes(raid5_conf_t *conf, int newsize)
+static int resize_stripes(struct r5conf *conf, int newsize)
 {
 	/* Make all the stripes able to hold 'newsize' devices.
 	 * New slots in each stripe get 'page' set to a new page.
@@ -1556,7 +1550,7 @@
 	return err;
 }
 
-static int drop_one_stripe(raid5_conf_t *conf)
+static int drop_one_stripe(struct r5conf *conf)
 {
 	struct stripe_head *sh;
 
@@ -1572,7 +1566,7 @@
 	return 1;
 }
 
-static void shrink_stripes(raid5_conf_t *conf)
+static void shrink_stripes(struct r5conf *conf)
 {
 	while (drop_one_stripe(conf))
 		;
@@ -1585,11 +1579,11 @@
 static void raid5_end_read_request(struct bio * bi, int error)
 {
 	struct stripe_head *sh = bi->bi_private;
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int disks = sh->disks, i;
 	int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
 	char b[BDEVNAME_SIZE];
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 
 	for (i=0 ; i<disks; i++)
@@ -1672,7 +1666,7 @@
 static void raid5_end_write_request(struct bio *bi, int error)
 {
 	struct stripe_head *sh = bi->bi_private;
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int disks = sh->disks, i;
 	int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
 	sector_t first_bad;
@@ -1726,10 +1720,10 @@
 	dev->sector = compute_blocknr(sh, i, previous);
 }
 
-static void error(mddev_t *mddev, mdk_rdev_t *rdev)
+static void error(struct mddev *mddev, struct md_rdev *rdev)
 {
 	char b[BDEVNAME_SIZE];
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	pr_debug("raid456: error called\n");
 
 	if (test_and_clear_bit(In_sync, &rdev->flags)) {
@@ -1758,7 +1752,7 @@
  * Input: a 'big' sector number,
  * Output: index of the data and parity disk, and the sector # in them.
  */
-static sector_t raid5_compute_sector(raid5_conf_t *conf, sector_t r_sector,
+static sector_t raid5_compute_sector(struct r5conf *conf, sector_t r_sector,
 				     int previous, int *dd_idx,
 				     struct stripe_head *sh)
 {
@@ -1963,7 +1957,7 @@
 
 static sector_t compute_blocknr(struct stripe_head *sh, int i, int previous)
 {
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int raid_disks = sh->disks;
 	int data_disks = raid_disks - conf->max_degraded;
 	sector_t new_sector = sh->sector, check;
@@ -2088,7 +2082,7 @@
 			 int rcw, int expand)
 {
 	int i, pd_idx = sh->pd_idx, disks = sh->disks;
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int level = conf->level;
 
 	if (rcw) {
@@ -2173,7 +2167,7 @@
 static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite)
 {
 	struct bio **bip;
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int firstwrite=0;
 
 	pr_debug("adding bi b#%llu to stripe s#%llu\n",
@@ -2235,9 +2229,9 @@
 	return 0;
 }
 
-static void end_reshape(raid5_conf_t *conf);
+static void end_reshape(struct r5conf *conf);
 
-static void stripe_set_idx(sector_t stripe, raid5_conf_t *conf, int previous,
+static void stripe_set_idx(sector_t stripe, struct r5conf *conf, int previous,
 			    struct stripe_head *sh)
 {
 	int sectors_per_chunk =
@@ -2254,7 +2248,7 @@
 }
 
 static void
-handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh,
+handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
 				struct stripe_head_state *s, int disks,
 				struct bio **return_bi)
 {
@@ -2264,7 +2258,7 @@
 		int bitmap_end = 0;
 
 		if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
-			mdk_rdev_t *rdev;
+			struct md_rdev *rdev;
 			rcu_read_lock();
 			rdev = rcu_dereference(conf->disks[i].rdev);
 			if (rdev && test_bit(In_sync, &rdev->flags))
@@ -2359,7 +2353,7 @@
 }
 
 static void
-handle_failed_sync(raid5_conf_t *conf, struct stripe_head *sh,
+handle_failed_sync(struct r5conf *conf, struct stripe_head *sh,
 		   struct stripe_head_state *s)
 {
 	int abort = 0;
@@ -2378,7 +2372,7 @@
 	 * refcounting of rdevs is not needed
 	 */
 	for (i = 0; i < conf->raid_disks; i++) {
-		mdk_rdev_t *rdev = conf->disks[i].rdev;
+		struct md_rdev *rdev = conf->disks[i].rdev;
 		if (!rdev
 		    || test_bit(Faulty, &rdev->flags)
 		    || test_bit(In_sync, &rdev->flags))
@@ -2508,7 +2502,7 @@
  * Note that if we 'wrote' to a failed drive, it will be UPTODATE, but
  * never LOCKED, so we don't need to test 'failed' directly.
  */
-static void handle_stripe_clean_event(raid5_conf_t *conf,
+static void handle_stripe_clean_event(struct r5conf *conf,
 	struct stripe_head *sh, int disks, struct bio **return_bi)
 {
 	int i;
@@ -2553,7 +2547,7 @@
 			md_wakeup_thread(conf->mddev->thread);
 }
 
-static void handle_stripe_dirtying(raid5_conf_t *conf,
+static void handle_stripe_dirtying(struct r5conf *conf,
 				   struct stripe_head *sh,
 				   struct stripe_head_state *s,
 				   int disks)
@@ -2655,7 +2649,7 @@
 		schedule_reconstruction(sh, s, rcw == 0, 0);
 }
 
-static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh,
+static void handle_parity_checks5(struct r5conf *conf, struct stripe_head *sh,
 				struct stripe_head_state *s, int disks)
 {
 	struct r5dev *dev = NULL;
@@ -2743,7 +2737,7 @@
 }
 
 
-static void handle_parity_checks6(raid5_conf_t *conf, struct stripe_head *sh,
+static void handle_parity_checks6(struct r5conf *conf, struct stripe_head *sh,
 				  struct stripe_head_state *s,
 				  int disks)
 {
@@ -2906,7 +2900,7 @@
 	}
 }
 
-static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh)
+static void handle_stripe_expansion(struct r5conf *conf, struct stripe_head *sh)
 {
 	int i;
 
@@ -2985,7 +2979,7 @@
 
 static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
 {
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int disks = sh->disks;
 	struct r5dev *dev;
 	int i;
@@ -3002,7 +2996,7 @@
 	rcu_read_lock();
 	spin_lock_irq(&conf->device_lock);
 	for (i=disks; i--; ) {
-		mdk_rdev_t *rdev;
+		struct md_rdev *rdev;
 		sector_t first_bad;
 		int bad_sectors;
 		int is_bad = 0;
@@ -3042,6 +3036,8 @@
 		if (dev->written)
 			s->written++;
 		rdev = rcu_dereference(conf->disks[i].rdev);
+		if (rdev && test_bit(Faulty, &rdev->flags))
+			rdev = NULL;
 		if (rdev) {
 			is_bad = is_badblock(rdev, sh->sector, STRIPE_SECTORS,
 					     &first_bad, &bad_sectors);
@@ -3069,12 +3065,18 @@
 			}
 		} else if (test_bit(In_sync, &rdev->flags))
 			set_bit(R5_Insync, &dev->flags);
-		else {
+		else if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
 			/* in sync if before recovery_offset */
-			if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
-				set_bit(R5_Insync, &dev->flags);
-		}
-		if (test_bit(R5_WriteError, &dev->flags)) {
+			set_bit(R5_Insync, &dev->flags);
+		else if (test_bit(R5_UPTODATE, &dev->flags) &&
+			 test_bit(R5_Expanded, &dev->flags))
+			/* If we've reshaped into here, we assume it is Insync.
+			 * We will shortly update recovery_offset to make
+			 * it official.
+			 */
+			set_bit(R5_Insync, &dev->flags);
+
+		if (rdev && test_bit(R5_WriteError, &dev->flags)) {
 			clear_bit(R5_Insync, &dev->flags);
 			if (!test_bit(Faulty, &rdev->flags)) {
 				s->handle_bad_blocks = 1;
@@ -3082,7 +3084,7 @@
 			} else
 				clear_bit(R5_WriteError, &dev->flags);
 		}
-		if (test_bit(R5_MadeGood, &dev->flags)) {
+		if (rdev && test_bit(R5_MadeGood, &dev->flags)) {
 			if (!test_bit(Faulty, &rdev->flags)) {
 				s->handle_bad_blocks = 1;
 				atomic_inc(&rdev->nr_pending);
@@ -3109,14 +3111,14 @@
 static void handle_stripe(struct stripe_head *sh)
 {
 	struct stripe_head_state s;
-	raid5_conf_t *conf = sh->raid_conf;
+	struct r5conf *conf = sh->raid_conf;
 	int i;
 	int prexor;
 	int disks = sh->disks;
 	struct r5dev *pdev, *qdev;
 
 	clear_bit(STRIPE_HANDLE, &sh->state);
-	if (test_and_set_bit(STRIPE_ACTIVE, &sh->state)) {
+	if (test_and_set_bit_lock(STRIPE_ACTIVE, &sh->state)) {
 		/* already being handled, ensure it gets handled
 		 * again when current action finishes */
 		set_bit(STRIPE_HANDLE, &sh->state);
@@ -3165,10 +3167,14 @@
 	/* check if the array has lost more than max_degraded devices and,
 	 * if so, some requests might need to be failed.
 	 */
-	if (s.failed > conf->max_degraded && s.to_read+s.to_write+s.written)
-		handle_failed_stripe(conf, sh, &s, disks, &s.return_bi);
-	if (s.failed > conf->max_degraded && s.syncing)
-		handle_failed_sync(conf, sh, &s);
+	if (s.failed > conf->max_degraded) {
+		sh->check_state = 0;
+		sh->reconstruct_state = 0;
+		if (s.to_read+s.to_write+s.written)
+			handle_failed_stripe(conf, sh, &s, disks, &s.return_bi);
+		if (s.syncing)
+			handle_failed_sync(conf, sh, &s);
+	}
 
 	/*
 	 * might be able to return some write requests if the parity blocks
@@ -3341,7 +3347,7 @@
 
 	if (s.handle_bad_blocks)
 		for (i = disks; i--; ) {
-			mdk_rdev_t *rdev;
+			struct md_rdev *rdev;
 			struct r5dev *dev = &sh->dev[i];
 			if (test_and_clear_bit(R5_WriteError, &dev->flags)) {
 				/* We own a safe reference to the rdev */
@@ -3377,10 +3383,10 @@
 
 	return_io(s.return_bi);
 
-	clear_bit(STRIPE_ACTIVE, &sh->state);
+	clear_bit_unlock(STRIPE_ACTIVE, &sh->state);
 }
 
-static void raid5_activate_delayed(raid5_conf_t *conf)
+static void raid5_activate_delayed(struct r5conf *conf)
 {
 	if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) {
 		while (!list_empty(&conf->delayed_list)) {
@@ -3396,7 +3402,7 @@
 	}
 }
 
-static void activate_bit_delay(raid5_conf_t *conf)
+static void activate_bit_delay(struct r5conf *conf)
 {
 	/* device_lock is held */
 	struct list_head head;
@@ -3410,9 +3416,9 @@
 	}
 }
 
-int md_raid5_congested(mddev_t *mddev, int bits)
+int md_raid5_congested(struct mddev *mddev, int bits)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 
 	/* No difference between reads and writes.  Just check
 	 * how busy the stripe_cache is
@@ -3431,7 +3437,7 @@
 
 static int raid5_congested(void *data, int bits)
 {
-	mddev_t *mddev = data;
+	struct mddev *mddev = data;
 
 	return mddev_congested(mddev, bits) ||
 		md_raid5_congested(mddev, bits);
@@ -3444,7 +3450,7 @@
 				struct bvec_merge_data *bvm,
 				struct bio_vec *biovec)
 {
-	mddev_t *mddev = q->queuedata;
+	struct mddev *mddev = q->queuedata;
 	sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
 	int max;
 	unsigned int chunk_sectors = mddev->chunk_sectors;
@@ -3464,7 +3470,7 @@
 }
 
 
-static int in_chunk_boundary(mddev_t *mddev, struct bio *bio)
+static int in_chunk_boundary(struct mddev *mddev, struct bio *bio)
 {
 	sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
 	unsigned int chunk_sectors = mddev->chunk_sectors;
@@ -3480,7 +3486,7 @@
  *  add bio to the retry LIFO  ( in O(1) ... we are in interrupt )
  *  later sampled by raid5d.
  */
-static void add_bio_to_retry(struct bio *bi,raid5_conf_t *conf)
+static void add_bio_to_retry(struct bio *bi,struct r5conf *conf)
 {
 	unsigned long flags;
 
@@ -3494,7 +3500,7 @@
 }
 
 
-static struct bio *remove_bio_from_retry(raid5_conf_t *conf)
+static struct bio *remove_bio_from_retry(struct r5conf *conf)
 {
 	struct bio *bi;
 
@@ -3527,10 +3533,10 @@
 static void raid5_align_endio(struct bio *bi, int error)
 {
 	struct bio* raid_bi  = bi->bi_private;
-	mddev_t *mddev;
-	raid5_conf_t *conf;
+	struct mddev *mddev;
+	struct r5conf *conf;
 	int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	bio_put(bi);
 
@@ -3574,12 +3580,12 @@
 }
 
 
-static int chunk_aligned_read(mddev_t *mddev, struct bio * raid_bio)
+static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	int dd_idx;
 	struct bio* align_bi;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 
 	if (!in_chunk_boundary(mddev, raid_bio)) {
 		pr_debug("chunk_aligned_read : non aligned\n");
@@ -3652,7 +3658,7 @@
  * head of the hold_list has changed, i.e. the head was promoted to the
  * handle_list.
  */
-static struct stripe_head *__get_priority_stripe(raid5_conf_t *conf)
+static struct stripe_head *__get_priority_stripe(struct r5conf *conf)
 {
 	struct stripe_head *sh;
 
@@ -3695,9 +3701,9 @@
 	return sh;
 }
 
-static int make_request(mddev_t *mddev, struct bio * bi)
+static void make_request(struct mddev *mddev, struct bio * bi)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	int dd_idx;
 	sector_t new_sector;
 	sector_t logical_sector, last_sector;
@@ -3708,7 +3714,7 @@
 
 	if (unlikely(bi->bi_rw & REQ_FLUSH)) {
 		md_flush_request(mddev, bi);
-		return 0;
+		return;
 	}
 
 	md_write_start(mddev, bi);
@@ -3716,7 +3722,7 @@
 	if (rw == READ &&
 	     mddev->reshape_position == MaxSector &&
 	     chunk_aligned_read(mddev,bi))
-		return 0;
+		return;
 
 	logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
 	last_sector = bi->bi_sector + (bi->bi_size>>9);
@@ -3851,13 +3857,11 @@
 
 		bio_endio(bi, 0);
 	}
-
-	return 0;
 }
 
-static sector_t raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks);
+static sector_t raid5_size(struct mddev *mddev, sector_t sectors, int raid_disks);
 
-static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped)
+static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *skipped)
 {
 	/* reshaping is quite different to recovery/resync so it is
 	 * handled quite separately ... here.
@@ -3868,7 +3872,7 @@
 	 * As the reads complete, handle_stripe will copy the data
 	 * into the destination stripe and release that stripe.
 	 */
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	struct stripe_head *sh;
 	sector_t first_sector, last_sector;
 	int raid_disks = conf->previous_raid_disks;
@@ -4075,9 +4079,9 @@
 }
 
 /* FIXME go_faster isn't used */
-static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
+static inline sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	struct stripe_head *sh;
 	sector_t max_sector = mddev->dev_sectors;
 	sector_t sync_blocks;
@@ -4162,7 +4166,7 @@
 	return STRIPE_SECTORS;
 }
 
-static int  retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio)
+static int  retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
 {
 	/* We may not be able to submit a whole bio at once as there
 	 * may not be enough stripe_heads available.
@@ -4234,10 +4238,10 @@
  * During the scan, completed stripes are saved for us by the interrupt
  * handler, so that they will not have to wait for our next wakeup.
  */
-static void raid5d(mddev_t *mddev)
+static void raid5d(struct mddev *mddev)
 {
 	struct stripe_head *sh;
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	int handled;
 	struct blk_plug plug;
 
@@ -4301,9 +4305,9 @@
 }
 
 static ssize_t
-raid5_show_stripe_cache_size(mddev_t *mddev, char *page)
+raid5_show_stripe_cache_size(struct mddev *mddev, char *page)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	if (conf)
 		return sprintf(page, "%d\n", conf->max_nr_stripes);
 	else
@@ -4311,9 +4315,9 @@
 }
 
 int
-raid5_set_cache_size(mddev_t *mddev, int size)
+raid5_set_cache_size(struct mddev *mddev, int size)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	int err;
 
 	if (size <= 16 || size > 32768)
@@ -4337,9 +4341,9 @@
 EXPORT_SYMBOL(raid5_set_cache_size);
 
 static ssize_t
-raid5_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len)
+raid5_store_stripe_cache_size(struct mddev *mddev, const char *page, size_t len)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	unsigned long new;
 	int err;
 
@@ -4362,9 +4366,9 @@
 				raid5_store_stripe_cache_size);
 
 static ssize_t
-raid5_show_preread_threshold(mddev_t *mddev, char *page)
+raid5_show_preread_threshold(struct mddev *mddev, char *page)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	if (conf)
 		return sprintf(page, "%d\n", conf->bypass_threshold);
 	else
@@ -4372,9 +4376,9 @@
 }
 
 static ssize_t
-raid5_store_preread_threshold(mddev_t *mddev, const char *page, size_t len)
+raid5_store_preread_threshold(struct mddev *mddev, const char *page, size_t len)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	unsigned long new;
 	if (len >= PAGE_SIZE)
 		return -EINVAL;
@@ -4396,9 +4400,9 @@
 					raid5_store_preread_threshold);
 
 static ssize_t
-stripe_cache_active_show(mddev_t *mddev, char *page)
+stripe_cache_active_show(struct mddev *mddev, char *page)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	if (conf)
 		return sprintf(page, "%d\n", atomic_read(&conf->active_stripes));
 	else
@@ -4420,9 +4424,9 @@
 };
 
 static sector_t
-raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks)
+raid5_size(struct mddev *mddev, sector_t sectors, int raid_disks)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 
 	if (!sectors)
 		sectors = mddev->dev_sectors;
@@ -4435,7 +4439,7 @@
 	return sectors * (raid_disks - conf->max_degraded);
 }
 
-static void raid5_free_percpu(raid5_conf_t *conf)
+static void raid5_free_percpu(struct r5conf *conf)
 {
 	struct raid5_percpu *percpu;
 	unsigned long cpu;
@@ -4457,7 +4461,7 @@
 	free_percpu(conf->percpu);
 }
 
-static void free_conf(raid5_conf_t *conf)
+static void free_conf(struct r5conf *conf)
 {
 	shrink_stripes(conf);
 	raid5_free_percpu(conf);
@@ -4470,7 +4474,7 @@
 static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
 			      void *hcpu)
 {
-	raid5_conf_t *conf = container_of(nfb, raid5_conf_t, cpu_notify);
+	struct r5conf *conf = container_of(nfb, struct r5conf, cpu_notify);
 	long cpu = (long)hcpu;
 	struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
 
@@ -4505,7 +4509,7 @@
 }
 #endif
 
-static int raid5_alloc_percpu(raid5_conf_t *conf)
+static int raid5_alloc_percpu(struct r5conf *conf)
 {
 	unsigned long cpu;
 	struct page *spare_page;
@@ -4547,11 +4551,11 @@
 	return err;
 }
 
-static raid5_conf_t *setup_conf(mddev_t *mddev)
+static struct r5conf *setup_conf(struct mddev *mddev)
 {
-	raid5_conf_t *conf;
+	struct r5conf *conf;
 	int raid_disk, memory, max_disks;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	struct disk_info *disk;
 
 	if (mddev->new_level != 5
@@ -4583,7 +4587,7 @@
 		return ERR_PTR(-EINVAL);
 	}
 
-	conf = kzalloc(sizeof(raid5_conf_t), GFP_KERNEL);
+	conf = kzalloc(sizeof(struct r5conf), GFP_KERNEL);
 	if (conf == NULL)
 		goto abort;
 	spin_lock_init(&conf->device_lock);
@@ -4598,6 +4602,7 @@
 	atomic_set(&conf->preread_active_stripes, 0);
 	atomic_set(&conf->active_aligned_reads, 0);
 	conf->bypass_threshold = BYPASS_THRESHOLD;
+	conf->recovery_disabled = mddev->recovery_disabled - 1;
 
 	conf->raid_disks = mddev->raid_disks;
 	if (mddev->reshape_position == MaxSector)
@@ -4712,12 +4717,12 @@
 	return 0;
 }
 
-static int run(mddev_t *mddev)
+static int run(struct mddev *mddev)
 {
-	raid5_conf_t *conf;
+	struct r5conf *conf;
 	int working_disks = 0;
 	int dirty_parity_disks = 0;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	sector_t reshape_offset = 0;
 
 	if (mddev->recovery_cp != MaxSector)
@@ -4942,18 +4947,16 @@
 	return 0;
 abort:
 	md_unregister_thread(&mddev->thread);
-	if (conf) {
-		print_raid5_conf(conf);
-		free_conf(conf);
-	}
+	print_raid5_conf(conf);
+	free_conf(conf);
 	mddev->private = NULL;
 	printk(KERN_ALERT "md/raid:%s: failed to run raid set.\n", mdname(mddev));
 	return -EIO;
 }
 
-static int stop(mddev_t *mddev)
+static int stop(struct mddev *mddev)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 
 	md_unregister_thread(&mddev->thread);
 	if (mddev->queue)
@@ -4964,44 +4967,9 @@
 	return 0;
 }
 
-#ifdef DEBUG
-static void print_sh(struct seq_file *seq, struct stripe_head *sh)
-{
-	int i;
-
-	seq_printf(seq, "sh %llu, pd_idx %d, state %ld.\n",
-		   (unsigned long long)sh->sector, sh->pd_idx, sh->state);
-	seq_printf(seq, "sh %llu,  count %d.\n",
-		   (unsigned long long)sh->sector, atomic_read(&sh->count));
-	seq_printf(seq, "sh %llu, ", (unsigned long long)sh->sector);
-	for (i = 0; i < sh->disks; i++) {
-		seq_printf(seq, "(cache%d: %p %ld) ",
-			   i, sh->dev[i].page, sh->dev[i].flags);
-	}
-	seq_printf(seq, "\n");
-}
-
-static void printall(struct seq_file *seq, raid5_conf_t *conf)
-{
-	struct stripe_head *sh;
-	struct hlist_node *hn;
-	int i;
-
-	spin_lock_irq(&conf->device_lock);
-	for (i = 0; i < NR_HASH; i++) {
-		hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) {
-			if (sh->raid_conf != conf)
-				continue;
-			print_sh(seq, sh);
-		}
-	}
-	spin_unlock_irq(&conf->device_lock);
-}
-#endif
-
-static void status(struct seq_file *seq, mddev_t *mddev)
+static void status(struct seq_file *seq, struct mddev *mddev)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	int i;
 
 	seq_printf(seq, " level %d, %dk chunk, algorithm %d", mddev->level,
@@ -5012,13 +4980,9 @@
 			       conf->disks[i].rdev &&
 			       test_bit(In_sync, &conf->disks[i].rdev->flags) ? "U" : "_");
 	seq_printf (seq, "]");
-#ifdef DEBUG
-	seq_printf (seq, "\n");
-	printall(seq, conf);
-#endif
 }
 
-static void print_raid5_conf (raid5_conf_t *conf)
+static void print_raid5_conf (struct r5conf *conf)
 {
 	int i;
 	struct disk_info *tmp;
@@ -5042,10 +5006,10 @@
 	}
 }
 
-static int raid5_spare_active(mddev_t *mddev)
+static int raid5_spare_active(struct mddev *mddev)
 {
 	int i;
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	struct disk_info *tmp;
 	int count = 0;
 	unsigned long flags;
@@ -5067,11 +5031,11 @@
 	return count;
 }
 
-static int raid5_remove_disk(mddev_t *mddev, int number)
+static int raid5_remove_disk(struct mddev *mddev, int number)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	int err = 0;
-	mdk_rdev_t *rdev;
+	struct md_rdev *rdev;
 	struct disk_info *p = conf->disks + number;
 
 	print_raid5_conf(conf);
@@ -5110,9 +5074,9 @@
 	return err;
 }
 
-static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	int err = -EEXIST;
 	int disk;
 	struct disk_info *p;
@@ -5153,7 +5117,7 @@
 	return err;
 }
 
-static int raid5_resize(mddev_t *mddev, sector_t sectors)
+static int raid5_resize(struct mddev *mddev, sector_t sectors)
 {
 	/* no resync is happening, and there is enough space
 	 * on all devices, so we can resize.
@@ -5180,7 +5144,7 @@
 	return 0;
 }
 
-static int check_stripe_cache(mddev_t *mddev)
+static int check_stripe_cache(struct mddev *mddev)
 {
 	/* Can only proceed if there are plenty of stripe_heads.
 	 * We need a minimum of one full stripe,, and for sensible progress
@@ -5190,7 +5154,7 @@
 	 * If the chunk size is greater, user-space should request more
 	 * stripe_heads first.
 	 */
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	if (((mddev->chunk_sectors << 9) / STRIPE_SIZE) * 4
 	    > conf->max_nr_stripes ||
 	    ((mddev->new_chunk_sectors << 9) / STRIPE_SIZE) * 4
@@ -5204,9 +5168,9 @@
 	return 1;
 }
 
-static int check_reshape(mddev_t *mddev)
+static int check_reshape(struct mddev *mddev)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 
 	if (mddev->delta_disks == 0 &&
 	    mddev->new_layout == mddev->layout &&
@@ -5236,10 +5200,10 @@
 	return resize_stripes(conf, conf->raid_disks + mddev->delta_disks);
 }
 
-static int raid5_start_reshape(mddev_t *mddev)
+static int raid5_start_reshape(struct mddev *mddev)
 {
-	raid5_conf_t *conf = mddev->private;
-	mdk_rdev_t *rdev;
+	struct r5conf *conf = mddev->private;
+	struct md_rdev *rdev;
 	int spares = 0;
 	unsigned long flags;
 
@@ -5353,7 +5317,7 @@
 /* This is called from the reshape thread and should make any
  * changes needed in 'conf'
  */
-static void end_reshape(raid5_conf_t *conf)
+static void end_reshape(struct r5conf *conf)
 {
 
 	if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) {
@@ -5380,9 +5344,9 @@
 /* This is called from the raid5d thread with mddev_lock held.
  * It makes config changes to the device.
  */
-static void raid5_finish_reshape(mddev_t *mddev)
+static void raid5_finish_reshape(struct mddev *mddev)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 
 	if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
 
@@ -5401,7 +5365,7 @@
 			for (d = conf->raid_disks ;
 			     d < conf->raid_disks - mddev->delta_disks;
 			     d++) {
-				mdk_rdev_t *rdev = conf->disks[d].rdev;
+				struct md_rdev *rdev = conf->disks[d].rdev;
 				if (rdev && raid5_remove_disk(mddev, d) == 0) {
 					sysfs_unlink_rdev(mddev, rdev);
 					rdev->raid_disk = -1;
@@ -5415,9 +5379,9 @@
 	}
 }
 
-static void raid5_quiesce(mddev_t *mddev, int state)
+static void raid5_quiesce(struct mddev *mddev, int state)
 {
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 
 	switch(state) {
 	case 2: /* resume for a suspend */
@@ -5451,20 +5415,20 @@
 }
 
 
-static void *raid45_takeover_raid0(mddev_t *mddev, int level)
+static void *raid45_takeover_raid0(struct mddev *mddev, int level)
 {
-	struct raid0_private_data *raid0_priv = mddev->private;
+	struct r0conf *raid0_conf = mddev->private;
 	sector_t sectors;
 
 	/* for raid0 takeover only one zone is supported */
-	if (raid0_priv->nr_strip_zones > 1) {
+	if (raid0_conf->nr_strip_zones > 1) {
 		printk(KERN_ERR "md/raid:%s: cannot takeover raid0 with more than one zone.\n",
 		       mdname(mddev));
 		return ERR_PTR(-EINVAL);
 	}
 
-	sectors = raid0_priv->strip_zone[0].zone_end;
-	sector_div(sectors, raid0_priv->strip_zone[0].nb_dev);
+	sectors = raid0_conf->strip_zone[0].zone_end;
+	sector_div(sectors, raid0_conf->strip_zone[0].nb_dev);
 	mddev->dev_sectors = sectors;
 	mddev->new_level = level;
 	mddev->new_layout = ALGORITHM_PARITY_N;
@@ -5478,7 +5442,7 @@
 }
 
 
-static void *raid5_takeover_raid1(mddev_t *mddev)
+static void *raid5_takeover_raid1(struct mddev *mddev)
 {
 	int chunksect;
 
@@ -5505,7 +5469,7 @@
 	return setup_conf(mddev);
 }
 
-static void *raid5_takeover_raid6(mddev_t *mddev)
+static void *raid5_takeover_raid6(struct mddev *mddev)
 {
 	int new_layout;
 
@@ -5539,14 +5503,14 @@
 }
 
 
-static int raid5_check_reshape(mddev_t *mddev)
+static int raid5_check_reshape(struct mddev *mddev)
 {
 	/* For a 2-drive array, the layout and chunk size can be changed
 	 * immediately as not restriping is needed.
 	 * For larger arrays we record the new value - after validation
 	 * to be used by a reshape pass.
 	 */
-	raid5_conf_t *conf = mddev->private;
+	struct r5conf *conf = mddev->private;
 	int new_chunk = mddev->new_chunk_sectors;
 
 	if (mddev->new_layout >= 0 && !algorithm_valid_raid5(mddev->new_layout))
@@ -5579,7 +5543,7 @@
 	return check_reshape(mddev);
 }
 
-static int raid6_check_reshape(mddev_t *mddev)
+static int raid6_check_reshape(struct mddev *mddev)
 {
 	int new_chunk = mddev->new_chunk_sectors;
 
@@ -5599,7 +5563,7 @@
 	return check_reshape(mddev);
 }
 
-static void *raid5_takeover(mddev_t *mddev)
+static void *raid5_takeover(struct mddev *mddev)
 {
 	/* raid5 can take over:
 	 *  raid0 - if there is only one strip zone - make it a raid4 layout
@@ -5622,7 +5586,7 @@
 	return ERR_PTR(-EINVAL);
 }
 
-static void *raid4_takeover(mddev_t *mddev)
+static void *raid4_takeover(struct mddev *mddev)
 {
 	/* raid4 can take over:
 	 *  raid0 - if there is only one strip zone
@@ -5639,9 +5603,9 @@
 	return ERR_PTR(-EINVAL);
 }
 
-static struct mdk_personality raid5_personality;
+static struct md_personality raid5_personality;
 
-static void *raid6_takeover(mddev_t *mddev)
+static void *raid6_takeover(struct mddev *mddev)
 {
 	/* Currently can only take over a raid5.  We map the
 	 * personality to an equivalent raid6 personality
@@ -5688,7 +5652,7 @@
 }
 
 
-static struct mdk_personality raid6_personality =
+static struct md_personality raid6_personality =
 {
 	.name		= "raid6",
 	.level		= 6,
@@ -5710,7 +5674,7 @@
 	.quiesce	= raid5_quiesce,
 	.takeover	= raid6_takeover,
 };
-static struct mdk_personality raid5_personality =
+static struct md_personality raid5_personality =
 {
 	.name		= "raid5",
 	.level		= 5,
@@ -5733,7 +5697,7 @@
 	.takeover	= raid5_takeover,
 };
 
-static struct mdk_personality raid4_personality =
+static struct md_personality raid4_personality =
 {
 	.name		= "raid4",
 	.level		= 4,
diff -druN linux-libre-3.1-gnu/drivers/md/raid5.h linux-libre-3.2-gnu/drivers/md/raid5.h
--- linux-libre-3.1-gnu/drivers/md/raid5.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/md/raid5.h	2012-01-04 18:55:44.000000000 -0500
@@ -197,7 +197,7 @@
 struct stripe_head {
 	struct hlist_node	hash;
 	struct list_head	lru;	      /* inactive_list or handle_list */
-	struct raid5_private_data *raid_conf;
+	struct r5conf		*raid_conf;
 	short			generation;	/* increments with every
 						 * reshape */
 	sector_t		sector;		/* sector of this row */
@@ -248,7 +248,7 @@
 	unsigned long ops_request;
 
 	struct bio *return_bi;
-	mdk_rdev_t *blocked_rdev;
+	struct md_rdev *blocked_rdev;
 	int handle_bad_blocks;
 };
 
@@ -344,12 +344,12 @@
 
 
 struct disk_info {
-	mdk_rdev_t	*rdev;
+	struct md_rdev	*rdev;
 };
 
-struct raid5_private_data {
+struct r5conf {
 	struct hlist_head	*stripe_hashtbl;
-	mddev_t			*mddev;
+	struct mddev		*mddev;
 	struct disk_info	*spare;
 	int			chunk_sectors;
 	int			level, algorithm;
@@ -436,11 +436,9 @@
 	/* When taking over an array from a different personality, we store
 	 * the new thread here until we fully activate the array.
 	 */
-	struct mdk_thread_s	*thread;
+	struct md_thread	*thread;
 };
 
-typedef struct raid5_private_data raid5_conf_t;
-
 /*
  * Our supported algorithms
  */
@@ -503,7 +501,7 @@
 	return layout >= 8 && layout <= 10;
 }
 
-extern int md_raid5_congested(mddev_t *mddev, int bits);
-extern void md_raid5_kick_device(raid5_conf_t *conf);
-extern int raid5_set_cache_size(mddev_t *mddev, int size);
+extern int md_raid5_congested(struct mddev *mddev, int bits);
+extern void md_raid5_kick_device(struct r5conf *conf);
+extern int raid5_set_cache_size(struct mddev *mddev, int size);
 #endif
diff -druN linux-libre-3.1-gnu/drivers/media/common/saa7146_core.c linux-libre-3.2-gnu/drivers/media/common/saa7146_core.c
--- linux-libre-3.1-gnu/drivers/media/common/saa7146_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/saa7146_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,10 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <media/saa7146.h>
+#include <linux/module.h>
 
 LIST_HEAD(saa7146_devices);
 DEFINE_MUTEX(saa7146_devices_lock);
@@ -35,10 +38,9 @@
 {
 	int i = 0;
 
-	INFO((" @ %li jiffies:\n",jiffies));
-	for(i = 0; i <= 0x148; i+=4) {
-		printk("0x%03x: 0x%08x\n",i,saa7146_read(dev,i));
-	}
+	pr_info(" @ %li jiffies:\n", jiffies);
+	for (i = 0; i <= 0x148; i += 4)
+		pr_info("0x%03x: 0x%08x\n", i, saa7146_read(dev, i));
 }
 #endif
 
@@ -72,9 +74,8 @@
 		if (saa7146_read(dev, MC2) & 2)
 			break;
 		if (err) {
-			printk(KERN_ERR "%s: %s timed out while waiting for "
-					"registers getting programmed\n",
-					dev->name, __func__);
+			pr_err("%s: %s timed out while waiting for registers getting programmed\n",
+			       dev->name, __func__);
 			return -ETIMEDOUT;
 		}
 		msleep(1);
@@ -88,8 +89,8 @@
 			break;
 		saa7146_read(dev, MC2);
 		if (err) {
-			DEB_S(("%s: %s timed out while waiting for transfer "
-				"completion\n",	dev->name, __func__));
+			DEB_S("%s: %s timed out while waiting for transfer completion\n",
+			      dev->name, __func__);
 			return -ETIMEDOUT;
 		}
 		msleep(1);
@@ -109,9 +110,8 @@
 		if (saa7146_read(dev, MC2) & 2)
 			break;
 		if (!loops--) {
-			printk(KERN_ERR "%s: %s timed out while waiting for "
-					"registers getting programmed\n",
-					dev->name, __func__);
+			pr_err("%s: %s timed out while waiting for registers getting programmed\n",
+			       dev->name, __func__);
 			return -ETIMEDOUT;
 		}
 		udelay(1);
@@ -124,8 +124,8 @@
 			break;
 		saa7146_read(dev, MC2);
 		if (!loops--) {
-			DEB_S(("%s: %s timed out while waiting for transfer "
-				"completion\n", dev->name, __func__));
+			DEB_S("%s: %s timed out while waiting for transfer completion\n",
+			      dev->name, __func__);
 			return -ETIMEDOUT;
 		}
 		udelay(5);
@@ -264,7 +264,9 @@
 	ptr = pt->cpu;
 	for (i = 0; i < sglen; i++, list++) {
 /*
-		printk("i:%d, adr:0x%08x, len:%d, offset:%d\n", i,sg_dma_address(list), sg_dma_len(list), list->offset);
+		pr_debug("i:%d, adr:0x%08x, len:%d, offset:%d\n",
+			 i, sg_dma_address(list), sg_dma_len(list),
+			 list->offset);
 */
 		for (p = 0; p * 4096 < list->length; p++, ptr++) {
 			*ptr = cpu_to_le32(sg_dma_address(list) + p * 4096);
@@ -281,9 +283,9 @@
 
 /*
 	ptr = pt->cpu;
-	printk("offset: %d\n",pt->offset);
+	pr_debug("offset: %d\n", pt->offset);
 	for(i=0;i<5;i++) {
-		printk("ptr1 %d: 0x%08x\n",i,ptr[i]);
+		pr_debug("ptr1 %d: 0x%08x\n", i, ptr[i]);
 	}
 */
 	return 0;
@@ -314,7 +316,7 @@
 		}
 	}
 	if (0 != (isr & (MASK_27))) {
-		DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
+		DEB_INT("irq: RPS0 (0x%08x)\n", isr);
 		if (dev->vv_data && dev->vv_callback)
 			dev->vv_callback(dev,isr);
 		isr &= ~MASK_27;
@@ -333,14 +335,15 @@
 		} else {
 			u32 psr = saa7146_read(dev, PSR);
 			u32 ssr = saa7146_read(dev, SSR);
-			printk(KERN_WARNING "%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
-			       dev->name, isr, psr, ssr);
+			pr_warn("%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
+				dev->name, isr, psr, ssr);
 		}
 		isr &= ~(MASK_16|MASK_17);
 	}
 	if( 0 != isr ) {
-		ERR(("warning: interrupt enabled, but not handled properly.(0x%08x)\n",isr));
-		ERR(("disabling interrupt source(s)!\n"));
+		ERR("warning: interrupt enabled, but not handled properly.(0x%08x)\n",
+		    isr);
+		ERR("disabling interrupt source(s)!\n");
 		SAA7146_IER_DISABLE(dev,isr);
 	}
 	saa7146_write(dev, ISR, ack_isr);
@@ -360,15 +363,15 @@
 	/* clear out mem for sure */
 	dev = kzalloc(sizeof(struct saa7146_dev), GFP_KERNEL);
 	if (!dev) {
-		ERR(("out of memory.\n"));
+		ERR("out of memory\n");
 		goto out;
 	}
 
-	DEB_EE(("pci:%p\n",pci));
+	DEB_EE("pci:%p\n", pci);
 
 	err = pci_enable_device(pci);
 	if (err < 0) {
-		ERR(("pci_enable_device() failed.\n"));
+		ERR("pci_enable_device() failed\n");
 		goto err_free;
 	}
 
@@ -389,7 +392,7 @@
 	dev->mem = ioremap(pci_resource_start(pci, 0),
 			   pci_resource_len(pci, 0));
 	if (!dev->mem) {
-		ERR(("ioremap() failed.\n"));
+		ERR("ioremap() failed\n");
 		err = -ENODEV;
 		goto err_release;
 	}
@@ -414,7 +417,7 @@
 	err = request_irq(pci->irq, interrupt_hw, IRQF_SHARED | IRQF_DISABLED,
 			  dev->name, dev);
 	if (err < 0) {
-		ERR(("request_irq() failed.\n"));
+		ERR("request_irq() failed\n");
 		goto err_unmap;
 	}
 
@@ -444,7 +447,9 @@
 	/* create a nice device name */
 	sprintf(dev->name, "saa7146 (%d)", saa7146_num);
 
-	INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device));
+	pr_info("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x)\n",
+		dev->mem, dev->revision, pci->irq,
+		pci->subsystem_vendor, pci->subsystem_device);
 	dev->ext = ext;
 
 	mutex_init(&dev->v4l2_lock);
@@ -464,12 +469,12 @@
 	err = -ENODEV;
 
 	if (ext->probe && ext->probe(dev)) {
-		DEB_D(("ext->probe() failed for %p. skipping device.\n",dev));
+		DEB_D("ext->probe() failed for %p. skipping device.\n", dev);
 		goto err_free_i2c;
 	}
 
 	if (ext->attach(dev, pci_ext)) {
-		DEB_D(("ext->attach() failed for %p. skipping device.\n",dev));
+		DEB_D("ext->attach() failed for %p. skipping device.\n", dev);
 		goto err_free_i2c;
 	}
 	/* V4L extensions will set the pci drvdata to the v4l2_device in the
@@ -521,7 +526,7 @@
 		{ NULL, 0 }
 	}, *p;
 
-	DEB_EE(("dev:%p\n",dev));
+	DEB_EE("dev:%p\n", dev);
 
 	dev->ext->detach(dev);
 	/* Zero the PCI drvdata after use. */
@@ -552,21 +557,21 @@
 
 int saa7146_register_extension(struct saa7146_extension* ext)
 {
-	DEB_EE(("ext:%p\n",ext));
+	DEB_EE("ext:%p\n", ext);
 
 	ext->driver.name = ext->name;
 	ext->driver.id_table = ext->pci_tbl;
 	ext->driver.probe = saa7146_init_one;
 	ext->driver.remove = saa7146_remove_one;
 
-	printk("saa7146: register extension '%s'.\n",ext->name);
+	pr_info("register extension '%s'\n", ext->name);
 	return pci_register_driver(&ext->driver);
 }
 
 int saa7146_unregister_extension(struct saa7146_extension* ext)
 {
-	DEB_EE(("ext:%p\n",ext));
-	printk("saa7146: unregister extension '%s'.\n",ext->name);
+	DEB_EE("ext:%p\n", ext);
+	pr_info("unregister extension '%s'\n", ext->name);
 	pci_unregister_driver(&ext->driver);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/common/saa7146_fops.c linux-libre-3.2-gnu/drivers/media/common/saa7146_fops.c
--- linux-libre-3.1-gnu/drivers/media/common/saa7146_fops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/saa7146_fops.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,7 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <media/saa7146_vv.h>
+#include <linux/module.h>
 
 /****************************************************************************/
 /* resource management functions, shamelessly stolen from saa7134 driver */
@@ -9,21 +12,23 @@
 	struct saa7146_vv *vv = dev->vv_data;
 
 	if (fh->resources & bit) {
-		DEB_D(("already allocated! want: 0x%02x, cur:0x%02x\n",bit,vv->resources));
+		DEB_D("already allocated! want: 0x%02x, cur:0x%02x\n",
+		      bit, vv->resources);
 		/* have it already allocated */
 		return 1;
 	}
 
 	/* is it free? */
 	if (vv->resources & bit) {
-		DEB_D(("locked! vv->resources:0x%02x, we want:0x%02x\n",vv->resources,bit));
+		DEB_D("locked! vv->resources:0x%02x, we want:0x%02x\n",
+		      vv->resources, bit);
 		/* no, someone else uses it */
 		return 0;
 	}
 	/* it's free, grab it */
-	fh->resources  |= bit;
+	fh->resources |= bit;
 	vv->resources |= bit;
-	DEB_D(("res: get 0x%02x, cur:0x%02x\n",bit,vv->resources));
+	DEB_D("res: get 0x%02x, cur:0x%02x\n", bit, vv->resources);
 	return 1;
 }
 
@@ -34,9 +39,9 @@
 
 	BUG_ON((fh->resources & bits) != bits);
 
-	fh->resources  &= ~bits;
+	fh->resources &= ~bits;
 	vv->resources &= ~bits;
-	DEB_D(("res: put 0x%02x, cur:0x%02x\n",bits,vv->resources));
+	DEB_D("res: put 0x%02x, cur:0x%02x\n", bits, vv->resources);
 }
 
 
@@ -47,7 +52,7 @@
 						struct saa7146_buf *buf)
 {
 	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-	DEB_EE(("dev:%p, buf:%p\n",dev,buf));
+	DEB_EE("dev:%p, buf:%p\n", dev, buf);
 
 	BUG_ON(in_interrupt());
 
@@ -66,18 +71,19 @@
 			 struct saa7146_buf *buf)
 {
 	assert_spin_locked(&dev->slock);
-	DEB_EE(("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf));
+	DEB_EE("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf);
 
 	BUG_ON(!q);
 
 	if (NULL == q->curr) {
 		q->curr = buf;
-		DEB_D(("immediately activating buffer %p\n", buf));
+		DEB_D("immediately activating buffer %p\n", buf);
 		buf->activate(dev,buf,NULL);
 	} else {
 		list_add_tail(&buf->vb.queue,&q->queue);
 		buf->vb.state = VIDEOBUF_QUEUED;
-		DEB_D(("adding buffer %p to queue. (active buffer present)\n", buf));
+		DEB_D("adding buffer %p to queue. (active buffer present)\n",
+		      buf);
 	}
 	return 0;
 }
@@ -87,14 +93,14 @@
 			   int state)
 {
 	assert_spin_locked(&dev->slock);
-	DEB_EE(("dev:%p, dmaq:%p, state:%d\n", dev, q, state));
-	DEB_EE(("q->curr:%p\n",q->curr));
+	DEB_EE("dev:%p, dmaq:%p, state:%d\n", dev, q, state);
+	DEB_EE("q->curr:%p\n", q->curr);
 
 	BUG_ON(!q->curr);
 
 	/* finish current buffer */
 	if (NULL == q->curr) {
-		DEB_D(("aiii. no current buffer\n"));
+		DEB_D("aiii. no current buffer\n");
 		return;
 	}
 
@@ -112,7 +118,7 @@
 
 	BUG_ON(!q);
 
-	DEB_INT(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi));
+	DEB_INT("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi);
 
 	assert_spin_locked(&dev->slock);
 	if (!list_empty(&q->queue)) {
@@ -122,10 +128,11 @@
 		if (!list_empty(&q->queue))
 			next = list_entry(q->queue.next,struct saa7146_buf, vb.queue);
 		q->curr = buf;
-		DEB_INT(("next buffer: buf:%p, prev:%p, next:%p\n", buf, q->queue.prev,q->queue.next));
+		DEB_INT("next buffer: buf:%p, prev:%p, next:%p\n",
+			buf, q->queue.prev, q->queue.next);
 		buf->activate(dev,buf,next);
 	} else {
-		DEB_INT(("no next buffer. stopping.\n"));
+		DEB_INT("no next buffer. stopping.\n");
 		if( 0 != vbi ) {
 			/* turn off video-dma3 */
 			saa7146_write(dev,MC1, MASK_20);
@@ -162,11 +169,11 @@
 	struct saa7146_dev *dev = q->dev;
 	unsigned long flags;
 
-	DEB_EE(("dev:%p, dmaq:%p\n", dev, q));
+	DEB_EE("dev:%p, dmaq:%p\n", dev, q);
 
 	spin_lock_irqsave(&dev->slock,flags);
 	if (q->curr) {
-		DEB_D(("timeout on %p\n", q->curr));
+		DEB_D("timeout on %p\n", q->curr);
 		saa7146_buffer_finish(dev,q,VIDEOBUF_ERROR);
 	}
 
@@ -194,12 +201,12 @@
 
 	enum v4l2_buf_type type;
 
-	DEB_EE(("file:%p, dev:%s\n", file, video_device_node_name(vdev)));
+	DEB_EE("file:%p, dev:%s\n", file, video_device_node_name(vdev));
 
 	if (mutex_lock_interruptible(&saa7146_devices_lock))
 		return -ERESTARTSYS;
 
-	DEB_D(("using: %p\n",dev));
+	DEB_D("using: %p\n", dev);
 
 	type = vdev->vfl_type == VFL_TYPE_GRABBER
 	     ? V4L2_BUF_TYPE_VIDEO_CAPTURE
@@ -207,7 +214,7 @@
 
 	/* check if an extension is registered */
 	if( NULL == dev->ext ) {
-		DEB_S(("no extension registered for this device.\n"));
+		DEB_S("no extension registered for this device\n");
 		result = -ENODEV;
 		goto out;
 	}
@@ -215,7 +222,7 @@
 	/* allocate per open data */
 	fh = kzalloc(sizeof(*fh),GFP_KERNEL);
 	if (NULL == fh) {
-		DEB_S(("cannot allocate memory for per open data.\n"));
+		DEB_S("cannot allocate memory for per open data\n");
 		result = -ENOMEM;
 		goto out;
 	}
@@ -225,13 +232,13 @@
 	fh->type = type;
 
 	if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-		DEB_S(("initializing vbi...\n"));
+		DEB_S("initializing vbi...\n");
 		if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
 			result = saa7146_vbi_uops.open(dev,file);
 		if (dev->ext_vv_data->vbi_fops.open)
 			dev->ext_vv_data->vbi_fops.open(file);
 	} else {
-		DEB_S(("initializing video...\n"));
+		DEB_S("initializing video...\n");
 		result = saa7146_video_uops.open(dev,file);
 	}
 
@@ -259,7 +266,7 @@
 	struct saa7146_fh  *fh  = file->private_data;
 	struct saa7146_dev *dev = fh->dev;
 
-	DEB_EE(("file:%p\n", file));
+	DEB_EE("file:%p\n", file);
 
 	if (mutex_lock_interruptible(&saa7146_devices_lock))
 		return -ERESTARTSYS;
@@ -289,12 +296,14 @@
 
 	switch (fh->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-		DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",file, vma));
+		DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",
+		       file, vma);
 		q = &fh->video_q;
 		break;
 		}
 	case V4L2_BUF_TYPE_VBI_CAPTURE: {
-		DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",file, vma));
+		DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",
+		       file, vma);
 		q = &fh->vbi_q;
 		break;
 		}
@@ -312,14 +321,14 @@
 	struct videobuf_buffer *buf = NULL;
 	struct videobuf_queue *q;
 
-	DEB_EE(("file:%p, poll:%p\n",file, wait));
+	DEB_EE("file:%p, poll:%p\n", file, wait);
 
 	if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
 		if( 0 == fh->vbi_q.streaming )
 			return videobuf_poll_stream(file, &fh->vbi_q, wait);
 		q = &fh->vbi_q;
 	} else {
-		DEB_D(("using video queue.\n"));
+		DEB_D("using video queue\n");
 		q = &fh->video_q;
 	}
 
@@ -327,17 +336,17 @@
 		buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
 
 	if (!buf) {
-		DEB_D(("buf == NULL!\n"));
+		DEB_D("buf == NULL!\n");
 		return POLLERR;
 	}
 
 	poll_wait(file, &buf->done, wait);
 	if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) {
-		DEB_D(("poll succeeded!\n"));
+		DEB_D("poll succeeded!\n");
 		return POLLIN|POLLRDNORM;
 	}
 
-	DEB_D(("nothing to poll for, buf->state:%d\n",buf->state));
+	DEB_D("nothing to poll for, buf->state:%d\n", buf->state);
 	return 0;
 }
 
@@ -346,18 +355,20 @@
 	struct saa7146_fh *fh = file->private_data;
 
 	switch (fh->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-//		DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun", file, data, (unsigned long)count));
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+/*
+		DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun",
+		       file, data, (unsigned long)count);
+*/
 		return saa7146_video_uops.read(file,data,count,ppos);
-		}
-	case V4L2_BUF_TYPE_VBI_CAPTURE: {
-//		DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count));
+	case V4L2_BUF_TYPE_VBI_CAPTURE:
+/*
+		DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n",
+		       file, data, (unsigned long)count);
+*/
 		if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
 			return saa7146_vbi_uops.read(file,data,count,ppos);
-		else
-			return -EINVAL;
-		}
-		break;
+		return -EINVAL;
 	default:
 		BUG();
 		return 0;
@@ -398,22 +409,22 @@
 {
 	u32 isr = status;
 
-	DEB_INT(("dev:%p, isr:0x%08x\n",dev,(u32)status));
+	DEB_INT("dev:%p, isr:0x%08x\n", dev, (u32)status);
 
 	if (0 != (isr & (MASK_27))) {
-		DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
+		DEB_INT("irq: RPS0 (0x%08x)\n", isr);
 		saa7146_video_uops.irq_done(dev,isr);
 	}
 
 	if (0 != (isr & (MASK_28))) {
 		u32 mc2 = saa7146_read(dev, MC2);
 		if( 0 != (mc2 & MASK_15)) {
-			DEB_INT(("irq: RPS1 vbi workaround (0x%08x).\n",isr));
+			DEB_INT("irq: RPS1 vbi workaround (0x%08x)\n", isr);
 			wake_up(&dev->vv_data->vbi_wq);
 			saa7146_write(dev,MC2, MASK_31);
 			return;
 		}
-		DEB_INT(("irq: RPS1 (0x%08x).\n",isr));
+		DEB_INT("irq: RPS1 (0x%08x)\n", isr);
 		saa7146_vbi_uops.irq_done(dev,isr);
 	}
 }
@@ -429,13 +440,13 @@
 
 	vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL);
 	if (vv == NULL) {
-		ERR(("out of memory. aborting.\n"));
+		ERR("out of memory. aborting.\n");
 		return -ENOMEM;
 	}
 	ext_vv->ops = saa7146_video_ioctl_ops;
 	ext_vv->core_ops = &saa7146_video_ioctl_ops;
 
-	DEB_EE(("dev:%p\n",dev));
+	DEB_EE("dev:%p\n", dev);
 
 	/* set default values for video parts of the saa7146 */
 	saa7146_write(dev, BCS_CTRL, 0x80400040);
@@ -450,7 +461,7 @@
 
 	vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle);
 	if( NULL == vv->d_clipping.cpu_addr ) {
-		ERR(("out of memory. aborting.\n"));
+		ERR("out of memory. aborting.\n");
 		kfree(vv);
 		return -1;
 	}
@@ -471,7 +482,7 @@
 {
 	struct saa7146_vv *vv = dev->vv_data;
 
-	DEB_EE(("dev:%p\n",dev));
+	DEB_EE("dev:%p\n", dev);
 
 	v4l2_device_unregister(&dev->v4l2_dev);
 	pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
@@ -490,7 +501,7 @@
 	int err;
 	int i;
 
-	DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type));
+	DEB_EE("dev:%p, name:'%s', type:%d\n", dev, name, type);
 
 	// released by vfd->release
 	vfd = video_device_alloc();
@@ -509,13 +520,13 @@
 
 	err = video_register_device(vfd, type, -1);
 	if (err < 0) {
-		ERR(("cannot register v4l2 device. skipping.\n"));
+		ERR("cannot register v4l2 device. skipping.\n");
 		video_device_release(vfd);
 		return err;
 	}
 
-	INFO(("%s: registered device %s [v4l2]\n",
-		dev->name, video_device_node_name(vfd)));
+	pr_info("%s: registered device %s [v4l2]\n",
+		dev->name, video_device_node_name(vfd));
 
 	*vid = vfd;
 	return 0;
@@ -524,7 +535,7 @@
 
 int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
 {
-	DEB_EE(("dev:%p\n",dev));
+	DEB_EE("dev:%p\n", dev);
 
 	video_unregister_device(*vid);
 	*vid = NULL;
diff -druN linux-libre-3.1-gnu/drivers/media/common/saa7146_hlp.c linux-libre-3.2-gnu/drivers/media/common/saa7146_hlp.c
--- linux-libre-3.1-gnu/drivers/media/common/saa7146_hlp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/saa7146_hlp.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,7 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <media/saa7146_vv.h>
 
 static void calculate_output_format_register(struct saa7146_dev* saa, u32 palette, u32* clip_format)
@@ -711,8 +714,8 @@
 
 	int depth = sfmt->depth;
 
-	DEB_CAP(("[size=%dx%d,fields=%s]\n",
-		width,height,v4l2_field_names[field]));
+	DEB_CAP("[size=%dx%d,fields=%s]\n",
+		width, height, v4l2_field_names[field]);
 
 	if( bytesperline != 0) {
 		vdma1.pitch = bytesperline*2;
@@ -837,8 +840,8 @@
 	BUG_ON(0 == buf->pt[1].dma);
 	BUG_ON(0 == buf->pt[2].dma);
 
-	DEB_CAP(("[size=%dx%d,fields=%s]\n",
-		width,height,v4l2_field_names[field]));
+	DEB_CAP("[size=%dx%d,fields=%s]\n",
+		width, height, v4l2_field_names[field]);
 
 	/* fixme: look at bytesperline! */
 
@@ -998,12 +1001,12 @@
 	struct saa7146_vv *vv = dev->vv_data;
 	u32 vdma1_prot_addr;
 
-	DEB_CAP(("buf:%p, next:%p\n",buf,next));
+	DEB_CAP("buf:%p, next:%p\n", buf, next);
 
 	vdma1_prot_addr = saa7146_read(dev, PROT_ADDR1);
 	if( 0 == vdma1_prot_addr ) {
 		/* clear out beginning of streaming bit (rps register 0)*/
-		DEB_CAP(("forcing sync to new frame\n"));
+		DEB_CAP("forcing sync to new frame\n");
 		saa7146_write(dev, MC2, MASK_27 );
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/media/common/saa7146_i2c.c linux-libre-3.2-gnu/drivers/media/common/saa7146_i2c.c
--- linux-libre-3.1-gnu/drivers/media/common/saa7146_i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/saa7146_i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,8 +1,10 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <media/saa7146_vv.h>
 
 static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
 {
-//fm	DEB_I2C(("'%s'.\n", adapter->name));
+	/* DEB_I2C("'%s'\n", adapter->name); */
 
 	return	  I2C_FUNC_I2C
 		| I2C_FUNC_SMBUS_QUICK
@@ -14,9 +16,7 @@
 static inline u32 saa7146_i2c_status(struct saa7146_dev *dev)
 {
 	u32 iicsta = saa7146_read(dev, I2C_STATUS);
-/*
-	DEB_I2C(("status: 0x%08x\n",iicsta));
-*/
+	/* DEB_I2C("status: 0x%08x\n", iicsta); */
 	return iicsta;
 }
 
@@ -39,10 +39,11 @@
 	   plus one extra byte to address the device */
 	mem = 1 + ((mem-1) / 3);
 
-	/* we assume that op points to a memory of at least SAA7146_I2C_MEM bytes
-	   size. if we exceed this limit... */
-	if ( (4*mem) > SAA7146_I2C_MEM ) {
-//fm		DEB_I2C(("cannot prepare i2c-message.\n"));
+	/* we assume that op points to a memory of at least
+	 * SAA7146_I2C_MEM bytes size. if we exceed this limit...
+	 */
+	if ((4 * mem) > SAA7146_I2C_MEM) {
+		/* DEB_I2C("cannot prepare i2c-message\n"); */
 		return -ENOMEM;
 	}
 
@@ -123,7 +124,7 @@
 	if ( 0 != ( status & SAA7146_I2C_BUSY) ) {
 
 		/* yes, kill ongoing operation */
-		DEB_I2C(("busy_state detected.\n"));
+		DEB_I2C("busy_state detected\n");
 
 		/* set "ABORT-OPERATION"-bit (bit 7)*/
 		saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
@@ -141,7 +142,7 @@
 
 	if ( dev->i2c_bitrate != status ) {
 
-		DEB_I2C(("error_state detected. status:0x%08x\n",status));
+		DEB_I2C("error_state detected. status:0x%08x\n", status);
 
 		/* Repeat the abort operation. This seems to be necessary
 		   after serious protocol errors caused by e.g. the SAA7740 */
@@ -164,7 +165,7 @@
 	/* 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));
+		DEB_I2C("fatal error. status:0x%08x\n", status);
 		return -1;
 	}
 
@@ -181,7 +182,8 @@
 	unsigned long timeout;
 
 	/* write out i2c-command */
-	DEB_I2C(("before: 0x%08x (status: 0x%08x), %d\n",*dword,saa7146_read(dev, I2C_STATUS), dev->i2c_op));
+	DEB_I2C("before: 0x%08x (status: 0x%08x), %d\n",
+		*dword, saa7146_read(dev, I2C_STATUS), dev->i2c_op);
 
 	if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
 
@@ -202,7 +204,7 @@
 				/* a signal arrived */
 				return -ERESTARTSYS;
 
-			printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
+			pr_warn("%s %s [irq]: timed out waiting for end of xfer\n",
 				dev->name, __func__);
 			return -EIO;
 		}
@@ -220,7 +222,7 @@
 				break;
 			}
 			if (time_after(jiffies,timeout)) {
-				printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
+				pr_warn("%s %s: timed out waiting for MC2\n",
 					dev->name, __func__);
 				return -EIO;
 			}
@@ -237,7 +239,7 @@
 				/* this is normal when probing the bus
 				 * (no answer from nonexisistant device...)
 				 */
-				printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
+				pr_warn("%s %s [poll]: timed out waiting for end of xfer\n",
 					dev->name, __func__);
 				return -EIO;
 			}
@@ -257,24 +259,24 @@
 		if ( 0 == (status & SAA7146_I2C_ERR) ||
 		     0 == (status & SAA7146_I2C_BUSY) ) {
 			/* it may take some time until ERR goes high - ignore */
-			DEB_I2C(("unexpected i2c status %04x\n", status));
+			DEB_I2C("unexpected i2c status %04x\n", status);
 		}
 		if( 0 != (status & SAA7146_I2C_SPERR) ) {
-			DEB_I2C(("error due to invalid start/stop condition.\n"));
+			DEB_I2C("error due to invalid start/stop condition\n");
 		}
 		if( 0 != (status & SAA7146_I2C_DTERR) ) {
-			DEB_I2C(("error in data transmission.\n"));
+			DEB_I2C("error in data transmission\n");
 		}
 		if( 0 != (status & SAA7146_I2C_DRERR) ) {
-			DEB_I2C(("error when receiving data.\n"));
+			DEB_I2C("error when receiving data\n");
 		}
 		if( 0 != (status & SAA7146_I2C_AL) ) {
-			DEB_I2C(("error because arbitration lost.\n"));
+			DEB_I2C("error because arbitration lost\n");
 		}
 
 		/* we handle address-errors here */
 		if( 0 != (status & SAA7146_I2C_APERR) ) {
-			DEB_I2C(("error in address phase.\n"));
+			DEB_I2C("error in address phase\n");
 			return -EREMOTEIO;
 		}
 
@@ -284,7 +286,7 @@
 	/* read back data, just in case we were reading ... */
 	*dword = cpu_to_le32(saa7146_read(dev, I2C_TRANSFER));
 
-	DEB_I2C(("after: 0x%08x\n",*dword));
+	DEB_I2C("after: 0x%08x\n", *dword);
 	return 0;
 }
 
@@ -299,7 +301,7 @@
 		return -ERESTARTSYS;
 
 	for(i=0;i<num;i++) {
-		DEB_I2C(("msg:%d/%d\n",i+1,num));
+		DEB_I2C("msg:%d/%d\n", i+1, num);
 	}
 
 	/* prepare the message(s), get number of u32s to transfer */
@@ -316,7 +318,7 @@
 		/* reset the i2c-device if necessary */
 		err = saa7146_i2c_reset(dev);
 		if ( 0 > err ) {
-			DEB_I2C(("could not reset i2c-device.\n"));
+			DEB_I2C("could not reset i2c-device\n");
 			goto out;
 		}
 
@@ -336,7 +338,7 @@
 				   address error and trust the saa7146 address error detection. */
 				if (-EREMOTEIO == err && 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags))
 					goto out;
-				DEB_I2C(("error while sending message(s). starting again.\n"));
+				DEB_I2C("error while sending message(s). starting again\n");
 				break;
 			}
 		}
@@ -356,13 +358,13 @@
 
 	/* if any things had to be read, get the results */
 	if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) {
-		DEB_I2C(("could not cleanup i2c-message.\n"));
+		DEB_I2C("could not cleanup i2c-message\n");
 		err = -1;
 		goto out;
 	}
 
 	/* return the number of delivered messages */
-	DEB_I2C(("transmission successful. (msg:%d).\n",err));
+	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 continuing */
@@ -370,7 +372,7 @@
 		__le32 zero = 0;
 		saa7146_i2c_reset(dev);
 		if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) {
-			INFO(("revision 0 error. this should never happen.\n"));
+			pr_info("revision 0 error. this should never happen\n");
 		}
 	}
 
@@ -400,7 +402,7 @@
 
 int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate)
 {
-	DEB_EE(("bitrate: 0x%08x\n",bitrate));
+	DEB_EE("bitrate: 0x%08x\n", bitrate);
 
 	/* enable i2c-port pins */
 	saa7146_write(dev, MC1, (MASK_08 | MASK_24));
diff -druN linux-libre-3.1-gnu/drivers/media/common/saa7146_vbi.c linux-libre-3.2-gnu/drivers/media/common/saa7146_vbi.c
--- linux-libre-3.1-gnu/drivers/media/common/saa7146_vbi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/saa7146_vbi.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
 
 	DECLARE_WAITQUEUE(wait, current);
 
-	DEB_VBI(("dev:%p\n",dev));
+	DEB_VBI("dev:%p\n", dev);
 
 	/* once again, a bug in the saa7146: the brs acquisition
 	   is buggy and especially the BXO-counter does not work
@@ -40,14 +40,14 @@
 	WRITE_RPS1(0xc000008c);
 	/* wait for vbi_a or vbi_b*/
 	if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
-		DEB_D(("...using port b\n"));
+		DEB_D("...using port b\n");
 		WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_E_FID_B);
 		WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_O_FID_B);
 /*
 		WRITE_RPS1(CMD_PAUSE | MASK_09);
 */
 	} else {
-		DEB_D(("...using port a\n"));
+		DEB_D("...using port a\n");
 		WRITE_RPS1(CMD_PAUSE | MASK_10);
 	}
 	/* upload brs */
@@ -103,7 +103,7 @@
 
 		schedule();
 
-		DEB_VBI(("brs bug workaround %d/1.\n",i));
+		DEB_VBI("brs bug workaround %d/1\n", i);
 
 		remove_wait_queue(&vv->vbi_wq, &wait);
 		current->state = TASK_RUNNING;
@@ -116,7 +116,8 @@
 
 		if(signal_pending(current)) {
 
-			DEB_VBI(("aborted (rps:0x%08x).\n",saa7146_read(dev,RPS_ADDR1)));
+			DEB_VBI("aborted (rps:0x%08x)\n",
+				saa7146_read(dev, RPS_ADDR1));
 
 			/* stop rps1 for sure */
 			saa7146_write(dev, MC1, MASK_29);
@@ -207,7 +208,7 @@
 	struct saa7146_vv *vv = dev->vv_data;
 	buf->vb.state = VIDEOBUF_ACTIVE;
 
-	DEB_VBI(("dev:%p, buf:%p, next:%p\n",dev,buf,next));
+	DEB_VBI("dev:%p, buf:%p, next:%p\n", dev, buf, next);
 	saa7146_set_vbi_capture(dev,buf,next);
 
 	mod_timer(&vv->vbi_q.timeout, jiffies+BUFFER_TIMEOUT);
@@ -228,10 +229,10 @@
 	llength = vbi_pixel_to_capture;
 	size = lines * llength;
 
-	DEB_VBI(("vb:%p\n",vb));
+	DEB_VBI("vb:%p\n", vb);
 
 	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size) {
-		DEB_VBI(("size mismatch.\n"));
+		DEB_VBI("size mismatch\n");
 		return -EINVAL;
 	}
 
@@ -263,7 +264,7 @@
 	return 0;
 
  oops:
-	DEB_VBI(("error out.\n"));
+	DEB_VBI("error out\n");
 	saa7146_dma_free(dev,q,buf);
 
 	return err;
@@ -279,7 +280,7 @@
 	*size = lines * llength;
 	*count = 2;
 
-	DEB_VBI(("count:%d, size:%d\n",*count,*size));
+	DEB_VBI("count:%d, size:%d\n", *count, *size);
 
 	return 0;
 }
@@ -292,7 +293,7 @@
 	struct saa7146_vv *vv = dev->vv_data;
 	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
 
-	DEB_VBI(("vb:%p\n",vb));
+	DEB_VBI("vb:%p\n", vb);
 	saa7146_buffer_queue(dev,&vv->vbi_q,buf);
 }
 
@@ -303,7 +304,7 @@
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
 
-	DEB_VBI(("vb:%p\n",vb));
+	DEB_VBI("vb:%p\n", vb);
 	saa7146_dma_free(dev,q,buf);
 }
 
@@ -321,7 +322,7 @@
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
 	unsigned long flags;
-	DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
+	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
 
 	spin_lock_irqsave(&dev->slock,flags);
 
@@ -354,14 +355,14 @@
 	struct saa7146_fh *fh = file->private_data;
 	struct saa7146_dev *dev = fh->dev;
 
-	DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
+	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
 
 	vbi_stop(fh, file);
 }
 
 static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
 {
-	DEB_VBI(("dev:%p\n",dev));
+	DEB_VBI("dev:%p\n", dev);
 
 	INIT_LIST_HEAD(&vv->vbi_q.queue);
 
@@ -380,11 +381,11 @@
 	u32 arbtr_ctrl	= saa7146_read(dev, PCI_BT_V1);
 	int ret = 0;
 
-	DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
 
 	ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS);
 	if (0 == ret) {
-		DEB_S(("cannot get vbi RESOURCE_DMA3_BRS resource\n"));
+		DEB_S("cannot get vbi RESOURCE_DMA3_BRS resource\n");
 		return -EBUSY;
 	}
 
@@ -425,7 +426,7 @@
 		saa7146_write(dev, BRS_CTRL, 0x00000001);
 
 		if (0 != (ret = vbi_workaround(dev))) {
-			DEB_VBI(("vbi workaround failed!\n"));
+			DEB_VBI("vbi workaround failed!\n");
 			/* return ret;*/
 		}
 	}
@@ -439,7 +440,7 @@
 {
 	struct saa7146_fh *fh = file->private_data;
 	struct saa7146_vv *vv = dev->vv_data;
-	DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
 
 	if( fh == vv->vbi_streaming ) {
 		vbi_stop(fh, file);
@@ -453,13 +454,13 @@
 	spin_lock(&dev->slock);
 
 	if (vv->vbi_q.curr) {
-		DEB_VBI(("dev:%p, curr:%p\n",dev,vv->vbi_q.curr));
+		DEB_VBI("dev:%p, curr:%p\n", dev, vv->vbi_q.curr);
 		/* this must be += 2, one count for each field */
 		vv->vbi_fieldcount+=2;
 		vv->vbi_q.curr->vb.field_count = vv->vbi_fieldcount;
 		saa7146_buffer_finish(dev,&vv->vbi_q,VIDEOBUF_DONE);
 	} else {
-		DEB_VBI(("dev:%p\n",dev));
+		DEB_VBI("dev:%p\n", dev);
 	}
 	saa7146_buffer_next(dev,&vv->vbi_q,1);
 
@@ -473,7 +474,7 @@
 	struct saa7146_vv *vv = dev->vv_data;
 	ssize_t ret = 0;
 
-	DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
 
 	if( NULL == vv->vbi_streaming ) {
 		// fixme: check if dma3 is available
@@ -482,7 +483,8 @@
 	}
 
 	if( fh != vv->vbi_streaming ) {
-		DEB_VBI(("open %p is already using vbi capture.",vv->vbi_streaming));
+		DEB_VBI("open %p is already using vbi capture\n",
+			vv->vbi_streaming);
 		return -EBUSY;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/media/common/saa7146_video.c linux-libre-3.2-gnu/drivers/media/common/saa7146_video.c
--- linux-libre-3.1-gnu/drivers/media/common/saa7146_video.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/saa7146_video.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,8 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <media/saa7146_vv.h>
 #include <media/v4l2-chip-ident.h>
+#include <linux/module.h>
 
 static int max_memory = 32;
 
@@ -94,7 +97,7 @@
 		}
 	}
 
-	DEB_D(("unknown pixelformat:'%4.4s'\n",(char *)&fourcc));
+	DEB_D("unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
 	return NULL;
 }
 
@@ -107,32 +110,32 @@
 	struct v4l2_format fmt;
 	int ret = 0, err = 0;
 
-	DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+	DEB_EE("dev:%p, fh:%p\n", dev, fh);
 
 	/* check if we have overlay informations */
 	if( NULL == fh->ov.fh ) {
-		DEB_D(("no overlay data available. try S_FMT first.\n"));
+		DEB_D("no overlay data available. try S_FMT first.\n");
 		return -EAGAIN;
 	}
 
 	/* check if streaming capture is running */
 	if (IS_CAPTURE_ACTIVE(fh) != 0) {
-		DEB_D(("streaming capture is active.\n"));
+		DEB_D("streaming capture is active\n");
 		return -EBUSY;
 	}
 
 	/* check if overlay is running */
 	if (IS_OVERLAY_ACTIVE(fh) != 0) {
 		if (vv->video_fh == fh) {
-			DEB_D(("overlay is already active.\n"));
+			DEB_D("overlay is already active\n");
 			return 0;
 		}
-		DEB_D(("overlay is already active in another open.\n"));
+		DEB_D("overlay is already active in another open\n");
 		return -EBUSY;
 	}
 
 	if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
-		DEB_D(("cannot get necessary overlay resources\n"));
+		DEB_D("cannot get necessary overlay resources\n");
 		return -EBUSY;
 	}
 
@@ -145,13 +148,13 @@
 	fh->ov.win = fmt.fmt.win;
 	vv->ov_data = &fh->ov;
 
-	DEB_D(("%dx%d+%d+%d %s field=%s\n",
-		fh->ov.win.w.width,fh->ov.win.w.height,
-		fh->ov.win.w.left,fh->ov.win.w.top,
-		vv->ov_fmt->name,v4l2_field_names[fh->ov.win.field]));
+	DEB_D("%dx%d+%d+%d %s field=%s\n",
+	      fh->ov.win.w.width, fh->ov.win.w.height,
+	      fh->ov.win.w.left, fh->ov.win.w.top,
+	      vv->ov_fmt->name, v4l2_field_names[fh->ov.win.field]);
 
 	if (0 != (ret = saa7146_enable_overlay(fh))) {
-		DEB_D(("enabling overlay failed: %d\n",ret));
+		DEB_D("enabling overlay failed: %d\n", ret);
 		saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
 		return ret;
 	}
@@ -168,22 +171,22 @@
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
 
-	DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+	DEB_EE("dev:%p, fh:%p\n", dev, fh);
 
 	/* check if streaming capture is running */
 	if (IS_CAPTURE_ACTIVE(fh) != 0) {
-		DEB_D(("streaming capture is active.\n"));
+		DEB_D("streaming capture is active\n");
 		return -EBUSY;
 	}
 
 	/* check if overlay is running at all */
 	if ((vv->video_status & STATUS_OVERLAY) == 0) {
-		DEB_D(("no active overlay.\n"));
+		DEB_D("no active overlay\n");
 		return 0;
 	}
 
 	if (vv->video_fh != fh) {
-		DEB_D(("overlay is active, but in another open.\n"));
+		DEB_D("overlay is active, but in another open\n");
 		return -EBUSY;
 	}
 
@@ -268,7 +271,7 @@
 	int length = dma->sglen;
 	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
-	DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length));
+	DEB_EE("dev:%p, buf:%p, sg_len:%d\n", dev, buf, length);
 
 	if( 0 != IS_PLANAR(sfmt->trans)) {
 		struct saa7146_pgtable *pt1 = &buf->pt[0];
@@ -288,7 +291,8 @@
 				m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
 				o1 = size%PAGE_SIZE;
 				o2 = (size+(size/4))%PAGE_SIZE;
-				DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));
+				DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
+					size, m1, m2, m3, o1, o2);
 				break;
 			}
 			case 16: {
@@ -298,7 +302,8 @@
 				m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1;
 				o1 = size%PAGE_SIZE;
 				o2 = (size+(size/2))%PAGE_SIZE;
-				DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));
+				DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
+					size, m1, m2, m3, o1, o2);
 				break;
 			}
 			default: {
@@ -387,23 +392,23 @@
 	unsigned int resource;
 	int ret = 0, err = 0;
 
-	DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+	DEB_EE("dev:%p, fh:%p\n", dev, fh);
 
 	if ((vv->video_status & STATUS_CAPTURE) != 0) {
 		if (vv->video_fh == fh) {
-			DEB_S(("already capturing.\n"));
+			DEB_S("already capturing\n");
 			return 0;
 		}
-		DEB_S(("already capturing in another open.\n"));
+		DEB_S("already capturing in another open\n");
 		return -EBUSY;
 	}
 
 	if ((vv->video_status & STATUS_OVERLAY) != 0) {
-		DEB_S(("warning: suspending overlay video for streaming capture.\n"));
+		DEB_S("warning: suspending overlay video for streaming capture\n");
 		vv->ov_suspend = vv->video_fh;
 		err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
 		if (0 != err) {
-			DEB_D(("suspending video failed. aborting\n"));
+			DEB_D("suspending video failed. aborting\n");
 			return err;
 		}
 	}
@@ -420,7 +425,7 @@
 
 	ret = saa7146_res_get(fh, resource);
 	if (0 == ret) {
-		DEB_S(("cannot get capture resource %d\n",resource));
+		DEB_S("cannot get capture resource %d\n", resource);
 		if (vv->ov_suspend != NULL) {
 			saa7146_start_preview(vv->ov_suspend);
 			vv->ov_suspend = NULL;
@@ -448,15 +453,15 @@
 	unsigned long flags;
 	unsigned int resource;
 	u32 dmas = 0;
-	DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+	DEB_EE("dev:%p, fh:%p\n", dev, fh);
 
 	if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
-		DEB_S(("not capturing.\n"));
+		DEB_S("not capturing\n");
 		return 0;
 	}
 
 	if (vv->video_fh != fh) {
-		DEB_S(("capturing, but in another open.\n"));
+		DEB_S("capturing, but in another open\n");
 		return -EBUSY;
 	}
 
@@ -530,7 +535,7 @@
 	struct saa7146_vv *vv = dev->vv_data;
 	struct saa7146_format *fmt;
 
-	DEB_EE(("VIDIOC_S_FBUF\n"));
+	DEB_EE("VIDIOC_S_FBUF\n");
 
 	if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
 		return -EPERM;
@@ -542,13 +547,13 @@
 
 	/* planar formats are not allowed for overlay video, clipping and video dma would clash */
 	if (fmt->flags & FORMAT_IS_PLANAR)
-		DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",
-					(char *)&fmt->pixelformat));
+		DEB_S("planar pixelformat '%4.4s' not allowed for overlay\n",
+		      (char *)&fmt->pixelformat);
 
 	/* check if overlay is running */
 	if (IS_OVERLAY_ACTIVE(fh) != 0) {
 		if (vv->video_fh != fh) {
-			DEB_D(("refusing to change framebuffer informations while overlay is active in another open.\n"));
+			DEB_D("refusing to change framebuffer informations while overlay is active in another open\n");
 			return -EBUSY;
 		}
 	}
@@ -559,7 +564,7 @@
 
 	if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) {
 		vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8;
-		DEB_D(("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline));
+		DEB_D("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline);
 	}
 	return 0;
 }
@@ -588,7 +593,7 @@
 	if (ctrl == NULL)
 		return -EINVAL;
 
-	DEB_EE(("VIDIOC_QUERYCTRL: id:%d\n", c->id));
+	DEB_EE("VIDIOC_QUERYCTRL: id:%d\n", c->id);
 	*c = *ctrl;
 	return 0;
 }
@@ -607,25 +612,25 @@
 	case V4L2_CID_BRIGHTNESS:
 		value = saa7146_read(dev, BCS_CTRL);
 		c->value = 0xff & (value >> 24);
-		DEB_D(("V4L2_CID_BRIGHTNESS: %d\n", c->value));
+		DEB_D("V4L2_CID_BRIGHTNESS: %d\n", c->value);
 		break;
 	case V4L2_CID_CONTRAST:
 		value = saa7146_read(dev, BCS_CTRL);
 		c->value = 0x7f & (value >> 16);
-		DEB_D(("V4L2_CID_CONTRAST: %d\n", c->value));
+		DEB_D("V4L2_CID_CONTRAST: %d\n", c->value);
 		break;
 	case V4L2_CID_SATURATION:
 		value = saa7146_read(dev, BCS_CTRL);
 		c->value = 0x7f & (value >> 0);
-		DEB_D(("V4L2_CID_SATURATION: %d\n", c->value));
+		DEB_D("V4L2_CID_SATURATION: %d\n", c->value);
 		break;
 	case V4L2_CID_VFLIP:
 		c->value = vv->vflip;
-		DEB_D(("V4L2_CID_VFLIP: %d\n", c->value));
+		DEB_D("V4L2_CID_VFLIP: %d\n", c->value);
 		break;
 	case V4L2_CID_HFLIP:
 		c->value = vv->hflip;
-		DEB_D(("V4L2_CID_HFLIP: %d\n", c->value));
+		DEB_D("V4L2_CID_HFLIP: %d\n", c->value);
 		break;
 	default:
 		return -EINVAL;
@@ -641,7 +646,7 @@
 
 	ctrl = ctrl_by_id(c->id);
 	if (NULL == ctrl) {
-		DEB_D(("unknown control %d\n", c->id));
+		DEB_D("unknown control %d\n", c->id);
 		return -EINVAL;
 	}
 
@@ -686,14 +691,14 @@
 	case V4L2_CID_HFLIP:
 		/* fixme: we can support changing VFLIP and HFLIP here... */
 		if (IS_CAPTURE_ACTIVE(fh) != 0) {
-			DEB_D(("V4L2_CID_HFLIP while active capture.\n"));
+			DEB_D("V4L2_CID_HFLIP while active capture\n");
 			return -EBUSY;
 		}
 		vv->hflip = c->value;
 		break;
 	case V4L2_CID_VFLIP:
 		if (IS_CAPTURE_ACTIVE(fh) != 0) {
-			DEB_D(("V4L2_CID_VFLIP while active capture.\n"));
+			DEB_D("V4L2_CID_VFLIP while active capture\n");
 			return -EBUSY;
 		}
 		vv->vflip = c->value;
@@ -748,7 +753,7 @@
 	int maxw, maxh;
 	int calc_bpl;
 
-	DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
+	DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
 
 	fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat);
 	if (NULL == fmt)
@@ -777,7 +782,7 @@
 		vv->last_field = V4L2_FIELD_INTERLACED;
 		break;
 	default:
-		DEB_D(("no known field mode '%d'.\n", field));
+		DEB_D("no known field mode '%d'\n", field);
 		return -EINVAL;
 	}
 
@@ -796,8 +801,9 @@
 		f->fmt.pix.bytesperline = calc_bpl;
 
 	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
-	DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n", f->fmt.pix.width,
-			f->fmt.pix.height, f->fmt.pix.bytesperline, f->fmt.pix.sizeimage));
+	DEB_D("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n",
+	      f->fmt.pix.width, f->fmt.pix.height,
+	      f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
 
 	return 0;
 }
@@ -811,22 +817,23 @@
 	enum v4l2_field field;
 	int maxw, maxh;
 
-	DEB_EE(("dev:%p\n", dev));
+	DEB_EE("dev:%p\n", dev);
 
 	if (NULL == vv->ov_fb.base) {
-		DEB_D(("no fb base set.\n"));
+		DEB_D("no fb base set\n");
 		return -EINVAL;
 	}
 	if (NULL == vv->ov_fmt) {
-		DEB_D(("no fb fmt set.\n"));
+		DEB_D("no fb fmt set\n");
 		return -EINVAL;
 	}
 	if (win->w.width < 48 || win->w.height < 32) {
-		DEB_D(("min width/height. (%d,%d)\n", win->w.width, win->w.height));
+		DEB_D("min width/height. (%d,%d)\n",
+		      win->w.width, win->w.height);
 		return -EINVAL;
 	}
 	if (win->clipcount > 16) {
-		DEB_D(("clipcount too big.\n"));
+		DEB_D("clipcount too big\n");
 		return -EINVAL;
 	}
 
@@ -848,7 +855,7 @@
 	case V4L2_FIELD_INTERLACED:
 		break;
 	default:
-		DEB_D(("no known field mode '%d'.\n", field));
+		DEB_D("no known field mode '%d'\n", field);
 		return -EINVAL;
 	}
 
@@ -868,16 +875,17 @@
 	struct saa7146_vv *vv = dev->vv_data;
 	int err;
 
-	DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
+	DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
 	if (IS_CAPTURE_ACTIVE(fh) != 0) {
-		DEB_EE(("streaming capture is active\n"));
+		DEB_EE("streaming capture is active\n");
 		return -EBUSY;
 	}
 	err = vidioc_try_fmt_vid_cap(file, fh, f);
 	if (0 != err)
 		return err;
 	fh->video_fmt = f->fmt.pix;
-	DEB_EE(("set to pixelformat '%4.4s'\n", (char *)&fh->video_fmt.pixelformat));
+	DEB_EE("set to pixelformat '%4.4s'\n",
+	       (char *)&fh->video_fmt.pixelformat);
 	return 0;
 }
 
@@ -888,7 +896,7 @@
 	struct saa7146_vv *vv = dev->vv_data;
 	int err;
 
-	DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh));
+	DEB_EE("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh);
 	err = vidioc_try_fmt_vid_overlay(file, fh, f);
 	if (0 != err)
 		return err;
@@ -931,7 +939,7 @@
 		if (e->index < 0 )
 			return -EINVAL;
 		if( e->index < dev->ext_vv_data->num_stds ) {
-			DEB_EE(("VIDIOC_ENUMSTD: index:%d\n",e->index));
+			DEB_EE("VIDIOC_ENUMSTD: index:%d\n", e->index);
 			v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);
 			return 0;
 		}
@@ -946,10 +954,10 @@
 	int found = 0;
 	int err, i;
 
-	DEB_EE(("VIDIOC_S_STD\n"));
+	DEB_EE("VIDIOC_S_STD\n");
 
 	if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
-		DEB_D(("cannot change video standard while streaming capture is active\n"));
+		DEB_D("cannot change video standard while streaming capture is active\n");
 		return -EBUSY;
 	}
 
@@ -957,7 +965,7 @@
 		vv->ov_suspend = vv->video_fh;
 		err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
 		if (0 != err) {
-			DEB_D(("suspending video failed. aborting\n"));
+			DEB_D("suspending video failed. aborting\n");
 			return err;
 		}
 	}
@@ -978,11 +986,11 @@
 	}
 
 	if (!found) {
-		DEB_EE(("VIDIOC_S_STD: standard not found.\n"));
+		DEB_EE("VIDIOC_S_STD: standard not found\n");
 		return -EINVAL;
 	}
 
-	DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name));
+	DEB_EE("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name);
 	return 0;
 }
 
@@ -990,7 +998,7 @@
 {
 	int err;
 
-	DEB_D(("VIDIOC_OVERLAY on:%d\n", on));
+	DEB_D("VIDIOC_OVERLAY on:%d\n", on);
 	if (on)
 		err = saa7146_start_preview(fh);
 	else
@@ -1047,7 +1055,7 @@
 	struct saa7146_fh *fh = __fh;
 	int err;
 
-	DEB_D(("VIDIOC_STREAMON, type:%d\n", type));
+	DEB_D("VIDIOC_STREAMON, type:%d\n", type);
 
 	err = video_begin(fh);
 	if (err)
@@ -1066,18 +1074,18 @@
 	struct saa7146_vv *vv = dev->vv_data;
 	int err;
 
-	DEB_D(("VIDIOC_STREAMOFF, type:%d\n", type));
+	DEB_D("VIDIOC_STREAMOFF, type:%d\n", type);
 
 	/* ugly: we need to copy some checks from video_end(),
 	   because videobuf_streamoff() relies on the capture running.
 	   check and fix this */
 	if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
-		DEB_S(("not capturing.\n"));
+		DEB_S("not capturing\n");
 		return 0;
 	}
 
 	if (vv->video_fh != fh) {
-		DEB_S(("capturing, but in another open.\n"));
+		DEB_S("capturing, but in another open\n");
 		return -EBUSY;
 	}
 
@@ -1087,7 +1095,7 @@
 	else if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
 		err = videobuf_streamoff(&fh->vbi_q);
 	if (0 != err) {
-		DEB_D(("warning: videobuf_streamoff() failed.\n"));
+		DEB_D("warning: videobuf_streamoff() failed\n");
 		video_end(fh, file);
 	} else {
 		err = video_end(fh, file);
@@ -1174,25 +1182,27 @@
 	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
 	int size,err = 0;
 
-	DEB_CAP(("vbuf:%p\n",vb));
+	DEB_CAP("vbuf:%p\n", vb);
 
 	/* sanity checks */
 	if (fh->video_fmt.width  < 48 ||
 	    fh->video_fmt.height < 32 ||
 	    fh->video_fmt.width  > vv->standard->h_max_out ||
 	    fh->video_fmt.height > vv->standard->v_max_out) {
-		DEB_D(("w (%d) / h (%d) out of bounds.\n",fh->video_fmt.width,fh->video_fmt.height));
+		DEB_D("w (%d) / h (%d) out of bounds\n",
+		      fh->video_fmt.width, fh->video_fmt.height);
 		return -EINVAL;
 	}
 
 	size = fh->video_fmt.sizeimage;
 	if (0 != buf->vb.baddr && buf->vb.bsize < size) {
-		DEB_D(("size mismatch.\n"));
+		DEB_D("size mismatch\n");
 		return -EINVAL;
 	}
 
-	DEB_CAP(("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
-		fh->video_fmt.width,fh->video_fmt.height,size,v4l2_field_names[fh->video_fmt.field]));
+	DEB_CAP("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
+		fh->video_fmt.width, fh->video_fmt.height,
+		size, v4l2_field_names[fh->video_fmt.field]);
 	if (buf->vb.width  != fh->video_fmt.width  ||
 	    buf->vb.bytesperline != fh->video_fmt.bytesperline ||
 	    buf->vb.height != fh->video_fmt.height ||
@@ -1238,7 +1248,7 @@
 	return 0;
 
  oops:
-	DEB_D(("error out.\n"));
+	DEB_D("error out\n");
 	saa7146_dma_free(dev,q,buf);
 
 	return err;
@@ -1259,7 +1269,7 @@
 		*count = (max_memory*1048576) / *size;
 	}
 
-	DEB_CAP(("%d buffers, %d bytes each.\n",*count,*size));
+	DEB_CAP("%d buffers, %d bytes each\n", *count, *size);
 
 	return 0;
 }
@@ -1272,7 +1282,7 @@
 	struct saa7146_vv *vv = dev->vv_data;
 	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
 
-	DEB_CAP(("vbuf:%p\n",vb));
+	DEB_CAP("vbuf:%p\n", vb);
 	saa7146_buffer_queue(fh->dev,&vv->video_q,buf);
 }
 
@@ -1283,7 +1293,7 @@
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
 
-	DEB_CAP(("vbuf:%p\n",vb));
+	DEB_CAP("vbuf:%p\n", vb);
 
 	saa7146_dma_free(dev,q,buf);
 
@@ -1347,18 +1357,14 @@
 	struct saa7146_fh *fh = file->private_data;
 	struct saa7146_vv *vv = dev->vv_data;
 	struct videobuf_queue *q = &fh->video_q;
-	int err;
 
-	if (IS_CAPTURE_ACTIVE(fh) != 0) {
-		err = video_end(fh, file);
-	} else if (IS_OVERLAY_ACTIVE(fh) != 0) {
-		err = saa7146_stop_preview(fh);
-	}
+	if (IS_CAPTURE_ACTIVE(fh) != 0)
+		video_end(fh, file);
+	else if (IS_OVERLAY_ACTIVE(fh) != 0)
+		saa7146_stop_preview(fh);
 
 	videobuf_stop(q);
-
 	/* hmm, why is this function declared void? */
-	/* return err */
 }
 
 
@@ -1368,7 +1374,7 @@
 	struct saa7146_dmaqueue *q = &vv->video_q;
 
 	spin_lock(&dev->slock);
-	DEB_CAP(("called.\n"));
+	DEB_CAP("called\n");
 
 	/* only finish the buffer if we have one... */
 	if( NULL != q->curr ) {
@@ -1386,15 +1392,15 @@
 	struct saa7146_vv *vv = dev->vv_data;
 	ssize_t ret = 0;
 
-	DEB_EE(("called.\n"));
+	DEB_EE("called\n");
 
 	if ((vv->video_status & STATUS_CAPTURE) != 0) {
 		/* fixme: should we allow read() captures while streaming capture? */
 		if (vv->video_fh == fh) {
-			DEB_S(("already capturing.\n"));
+			DEB_S("already capturing\n");
 			return -EBUSY;
 		}
-		DEB_S(("already capturing in another open.\n"));
+		DEB_S("already capturing in another open\n");
 		return -EBUSY;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/media/common/tuners/Makefile linux-libre-3.2-gnu/drivers/media/common/tuners/Makefile
--- linux-libre-3.1-gnu/drivers/media/common/tuners/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/tuners/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -28,5 +28,5 @@
 obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o
 obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff -druN linux-libre-3.1-gnu/drivers/media/common/tuners/mt20xx.c linux-libre-3.2-gnu/drivers/media/common/tuners/mt20xx.c
--- linux-libre-3.1-gnu/drivers/media/common/tuners/mt20xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/tuners/mt20xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -430,11 +430,10 @@
 {
 	struct microtune_priv *priv = fe->tuner_priv;
 	unsigned char buf[2];
-	int ret;
 
 	buf[0] = 6;
 	buf[1] = antenna ? 0x11 : 0x10;
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
+	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
 	tuner_dbg("mt2050: enabled antenna connector %d\n", antenna);
 }
 
@@ -574,21 +573,20 @@
 {
 	struct microtune_priv *priv = fe->tuner_priv;
 	unsigned char buf[2];
-	int ret;
 
-	buf[0]=6;
-	buf[1]=0x10;
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); //  power
+	buf[0] = 6;
+	buf[1] = 0x10;
+	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); /* power */
 
-	buf[0]=0x0f;
-	buf[1]=0x0f;
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // m1lo
+	buf[0] = 0x0f;
+	buf[1] = 0x0f;
+	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); /* m1lo */
 
-	buf[0]=0x0d;
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
-	tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
+	buf[0] = 0x0d;
+	tuner_i2c_xfer_send(&priv->i2c_props, buf, 1);
+	tuner_i2c_xfer_recv(&priv->i2c_props, buf, 1);
 
-	tuner_dbg("mt2050: sro is %x\n",buf[0]);
+	tuner_dbg("mt2050: sro is %x\n", buf[0]);
 
 	memcpy(&fe->ops.tuner_ops, &mt2050_tuner_ops, sizeof(struct dvb_tuner_ops));
 
diff -druN linux-libre-3.1-gnu/drivers/media/common/tuners/mxl5005s.c linux-libre-3.2-gnu/drivers/media/common/tuners/mxl5005s.c
--- linux-libre-3.1-gnu/drivers/media/common/tuners/mxl5005s.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/tuners/mxl5005s.c	2012-01-04 18:55:44.000000000 -0500
@@ -309,7 +309,6 @@
 static u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val);
 static u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum,
 	u8 *RegVal, int *count);
-static u32 MXL_GetXtalInt(u32 Xtal_Freq);
 static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq);
 static void MXL_SynthIFLO_Calc(struct dvb_frontend *fe);
 static void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe);
@@ -2307,14 +2306,6 @@
 	return status ;
 }
 
-static u32 MXL_GetXtalInt(u32 Xtal_Freq)
-{
-	if ((Xtal_Freq % 1000000) == 0)
-		return (Xtal_Freq / 10000);
-	else
-		return (((Xtal_Freq / 1000000) + 1)*100);
-}
-
 static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)
 {
 	struct mxl5005s_state *state = fe->tuner_priv;
@@ -2324,13 +2315,10 @@
 	u32 Kdbl_RF = 2;
 	u32 tg_divval;
 	u32 tg_lo;
-	u32 Xtal_Int;
 
 	u32 Fref_TG;
 	u32 Fvco;
 
-	Xtal_Int = MXL_GetXtalInt(state->Fxtal);
-
 	state->RF_IN = RF_Freq;
 
 	MXL_SynthRFTGLO_Calc(fe);
@@ -2779,6 +2767,16 @@
 	tg_lo = (((Fmax/10 - Fvco)/100)*32) / ((Fmax-Fmin)/1000)+8;
 
 	/* below equation is same as above but much harder to debug.
+	 *
+	 * static u32 MXL_GetXtalInt(u32 Xtal_Freq)
+	 * {
+	 *	if ((Xtal_Freq % 1000000) == 0)
+	 *		return (Xtal_Freq / 10000);
+	 *	else
+	 *		return (((Xtal_Freq / 1000000) + 1)*100);
+	 * }
+	 *
+	 * u32 Xtal_Int = MXL_GetXtalInt(state->Fxtal);
 	 * tg_lo = ( ((Fmax/10000 * Xtal_Int)/100) -
 	 * ((state->TG_LO/10000)*divider_val *
 	 * (state->Fxtal/10000)/100) )*32/((Fmax-Fmin)/10000 *
diff -druN linux-libre-3.1-gnu/drivers/media/common/tuners/mxl5007t.c linux-libre-3.2-gnu/drivers/media/common/tuners/mxl5007t.c
--- linux-libre-3.1-gnu/drivers/media/common/tuners/mxl5007t.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/tuners/mxl5007t.c	2012-01-04 18:55:44.000000000 -0500
@@ -488,9 +488,10 @@
 
 static int mxl5007t_read_reg(struct mxl5007t_state *state, u8 reg, u8 *val)
 {
+	u8 buf[2] = { 0xfb, reg };
 	struct i2c_msg msg[] = {
 		{ .addr = state->i2c_props.addr, .flags = 0,
-		  .buf = &reg, .len = 1 },
+		  .buf = buf, .len = 2 },
 		{ .addr = state->i2c_props.addr, .flags = I2C_M_RD,
 		  .buf = val, .len = 1 },
 	};
diff -druN linux-libre-3.1-gnu/drivers/media/common/tuners/tda18212.c linux-libre-3.2-gnu/drivers/media/common/tuners/tda18212.c
--- linux-libre-3.1-gnu/drivers/media/common/tuners/tda18212.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/tuners/tda18212.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,7 +18,20 @@
  *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include "tda18212_priv.h"
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "tda18212.h"
+
+struct tda18212_priv {
+	struct tda18212_config *cfg;
+	struct i2c_adapter *i2c;
+};
+
+#define dbg(fmt, arg...)					\
+do {								\
+	if (debug)						\
+		pr_info("%s: " fmt, __func__, ##arg);		\
+} while (0)
 
 static int debug;
 module_param(debug, int, 0644);
@@ -46,7 +59,8 @@
 	if (ret == 1) {
 		ret = 0;
 	} else {
-		warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
+		pr_warn("i2c wr failed ret:%d reg:%02x len:%d\n",
+			ret, reg, len);
 		ret = -EREMOTEIO;
 	}
 	return ret;
@@ -77,7 +91,8 @@
 		memcpy(val, buf, len);
 		ret = 0;
 	} else {
-		warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
+		pr_warn("i2c rd failed ret:%d reg:%02x len:%d\n",
+			ret, reg, len);
 		ret = -EREMOTEIO;
 	}
 
@@ -129,8 +144,8 @@
 		{ 0x92, 0x53, 0x03 }, /* DVB-C */
 	};
 
-	dbg("%s: delsys=%d RF=%d BW=%d", __func__,
-		c->delivery_system, c->frequency, c->bandwidth_hz);
+	dbg("delsys=%d RF=%d BW=%d\n",
+	    c->delivery_system, c->frequency, c->bandwidth_hz);
 
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
@@ -196,7 +211,7 @@
 	return ret;
 
 error:
-	dbg("%s: failed:%d", __func__, ret);
+	dbg("failed:%d\n", ret);
 	goto exit;
 }
 
@@ -245,13 +260,13 @@
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
 
-	dbg("%s: ret:%d chip ID:%02x", __func__, ret, val);
+	dbg("ret:%d chip ID:%02x\n", ret, val);
 	if (ret || val != 0xc7) {
 		kfree(priv);
 		return NULL;
 	}
 
-	info("NXP TDA18212HN successfully identified.");
+	pr_info("NXP TDA18212HN successfully identified\n");
 
 	memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops,
 		sizeof(struct dvb_tuner_ops));
diff -druN linux-libre-3.1-gnu/drivers/media/common/tuners/tda18212_priv.h linux-libre-3.2-gnu/drivers/media/common/tuners/tda18212_priv.h
--- linux-libre-3.1-gnu/drivers/media/common/tuners/tda18212_priv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/tuners/tda18212_priv.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/*
- * NXP TDA18212HN silicon tuner driver
- *
- * 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.
- */
-
-#ifndef TDA18212_PRIV_H
-#define TDA18212_PRIV_H
-
-#include "tda18212.h"
-
-#define LOG_PREFIX "tda18212"
-
-#undef dbg
-#define dbg(f, arg...) \
-	if (debug) \
-		printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
-struct tda18212_priv {
-	struct tda18212_config *cfg;
-	struct i2c_adapter *i2c;
-};
-
-#endif
diff -druN linux-libre-3.1-gnu/drivers/media/common/tuners/tda18218.c linux-libre-3.2-gnu/drivers/media/common/tuners/tda18218.c
--- linux-libre-3.1-gnu/drivers/media/common/tuners/tda18218.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/tuners/tda18218.c	2012-01-04 18:55:44.000000000 -0500
@@ -141,7 +141,7 @@
 	switch (params->u.ofdm.bandwidth) {
 	case BANDWIDTH_6_MHZ:
 		LP_Fc = 0;
-		LO_Frac = params->frequency + 4000000;
+		LO_Frac = params->frequency + 3000000;
 		break;
 	case BANDWIDTH_7_MHZ:
 		LP_Fc = 1;
diff -druN linux-libre-3.1-gnu/drivers/media/common/tuners/tda18271-common.c linux-libre-3.2-gnu/drivers/media/common/tuners/tda18271-common.c
--- linux-libre-3.1-gnu/drivers/media/common/tuners/tda18271-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/tuners/tda18271-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -676,10 +676,28 @@
 	return ret;
 }
 
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
+int _tda_printk(struct tda18271_priv *state, const char *level,
+		const char *func, const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+	int rtn;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	if (state)
+		rtn = printk("%s%s: [%d-%04x|%c] %pV",
+			     level, func, i2c_adapter_id(state->i2c_props.adap),
+			     state->i2c_props.addr,
+			     (state->role == TDA18271_MASTER) ? 'M' : 'S',
+			     &vaf);
+	else
+		rtn = printk("%s%s: %pV", level, func, &vaf);
+
+	va_end(args);
+
+	return rtn;
+}
diff -druN linux-libre-3.1-gnu/drivers/media/common/tuners/tda18271-fe.c linux-libre-3.2-gnu/drivers/media/common/tuners/tda18271-fe.c
--- linux-libre-3.1-gnu/drivers/media/common/tuners/tda18271-fe.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/tuners/tda18271-fe.c	2012-01-04 18:55:44.000000000 -0500
@@ -1230,7 +1230,7 @@
 	return 0;
 }
 
-static struct dvb_tuner_ops tda18271_tuner_ops = {
+static const struct dvb_tuner_ops tda18271_tuner_ops = {
 	.info = {
 		.name = "NXP TDA18271HD",
 		.frequency_min  =  45000000,
diff -druN linux-libre-3.1-gnu/drivers/media/common/tuners/tda18271-priv.h linux-libre-3.2-gnu/drivers/media/common/tuners/tda18271-priv.h
--- linux-libre-3.1-gnu/drivers/media/common/tuners/tda18271-priv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/tuners/tda18271-priv.h	2012-01-04 18:55:44.000000000 -0500
@@ -136,29 +136,26 @@
 #define DBG_ADV  8
 #define DBG_CAL  16
 
-#define tda_printk(st, kern, fmt, arg...) do {\
-	if (st) { \
-		struct tda18271_priv *state = st; \
-		printk(kern "%s: [%d-%04x|%s] " fmt, __func__, \
-			i2c_adapter_id(state->i2c_props.adap), \
-			state->i2c_props.addr, \
-			(state->role == TDA18271_MASTER) \
-			? "M" : "S", ##arg); \
-	} else \
-		printk(kern "%s: " fmt, __func__, ##arg); \
-} while (0)
+__attribute__((format(printf, 4, 5)))
+int _tda_printk(struct tda18271_priv *state, const char *level,
+		const char *func, const char *fmt, ...);
 
-#define tda_dprintk(st, lvl, fmt, arg...) do {\
-	if (tda18271_debug & lvl) \
-		tda_printk(st, KERN_DEBUG, fmt, ##arg); } while (0)
+#define tda_printk(st, lvl, fmt, arg...)			\
+	_tda_printk(st, lvl, __func__, fmt, ##arg)
 
-#define tda_info(fmt, arg...)     printk(KERN_INFO     fmt, ##arg)
-#define tda_warn(fmt, arg...) tda_printk(priv, KERN_WARNING, fmt, ##arg)
-#define tda_err(fmt, arg...)  tda_printk(priv, KERN_ERR,     fmt, ##arg)
-#define tda_dbg(fmt, arg...)  tda_dprintk(priv, DBG_INFO,    fmt, ##arg)
-#define tda_map(fmt, arg...)  tda_dprintk(priv, DBG_MAP,     fmt, ##arg)
-#define tda_reg(fmt, arg...)  tda_dprintk(priv, DBG_REG,     fmt, ##arg)
-#define tda_cal(fmt, arg...)  tda_dprintk(priv, DBG_CAL,     fmt, ##arg)
+#define tda_dprintk(st, lvl, fmt, arg...)			\
+do {								\
+	if (tda18271_debug & lvl)				\
+		tda_printk(st, KERN_DEBUG, fmt, ##arg);		\
+} while (0)
+
+#define tda_info(fmt, arg...)	pr_info(fmt, ##arg)
+#define tda_warn(fmt, arg...)	tda_printk(priv, KERN_WARNING, fmt, ##arg)
+#define tda_err(fmt, arg...)	tda_printk(priv, KERN_ERR,     fmt, ##arg)
+#define tda_dbg(fmt, arg...)	tda_dprintk(priv, DBG_INFO,    fmt, ##arg)
+#define tda_map(fmt, arg...)	tda_dprintk(priv, DBG_MAP,     fmt, ##arg)
+#define tda_reg(fmt, arg...)	tda_dprintk(priv, DBG_REG,     fmt, ##arg)
+#define tda_cal(fmt, arg...)	tda_dprintk(priv, DBG_CAL,     fmt, ##arg)
 
 #define tda_fail(ret)							     \
 ({									     \
diff -druN linux-libre-3.1-gnu/drivers/media/common/tuners/tda827x.c linux-libre-3.2-gnu/drivers/media/common/tuners/tda827x.c
--- linux-libre-3.1-gnu/drivers/media/common/tuners/tda827x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/tuners/tda827x.c	2012-01-04 18:55:44.000000000 -0500
@@ -176,7 +176,7 @@
 		if_freq = 5000000;
 		break;
 	}
-	tuner_freq = params->frequency + if_freq;
+	tuner_freq = params->frequency;
 
 	i = 0;
 	while (tda827x_table[i].lomax < tuner_freq) {
@@ -185,6 +185,8 @@
 		i++;
 	}
 
+	tuner_freq += if_freq;
+
 	N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2);
 	buf[0] = 0;
 	buf[1] = (N>>8) | 0x40;
@@ -540,7 +542,7 @@
 		if_freq = 5000000;
 		break;
 	}
-	tuner_freq = params->frequency + if_freq;
+	tuner_freq = params->frequency;
 
 	if (fe->ops.info.type == FE_QAM) {
 		dprintk("%s select tda827xa_dvbc\n", __func__);
@@ -554,6 +556,8 @@
 		i++;
 	}
 
+	tuner_freq += if_freq;
+
 	N = ((tuner_freq + 31250) / 62500) << frequency_map[i].spd;
 	buf[0] = 0;            // subaddress
 	buf[1] = N >> 8;
diff -druN linux-libre-3.1-gnu/drivers/media/common/tuners/tuner-types.c linux-libre-3.2-gnu/drivers/media/common/tuners/tuner-types.c
--- linux-libre-3.1-gnu/drivers/media/common/tuners/tuner-types.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/tuners/tuner-types.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,7 @@
  */
 
 #include <linux/i2c.h>
+#include <linux/module.h>
 #include <media/tuner.h>
 #include <media/tuner-types.h>
 
diff -druN linux-libre-3.1-gnu/drivers/media/common/tuners/tuner-xc2028.c linux-libre-3.2-gnu/drivers/media/common/tuners/tuner-xc2028.c
--- linux-libre-3.1-gnu/drivers/media/common/tuners/tuner-xc2028.c	2012-03-19 21:31:24.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/tuners/tuner-xc2028.c	2012-03-19 21:33:31.000000000 -0400
@@ -614,6 +614,13 @@
 			p += len;
 			size -= len;
 		}
+
+		/* silently fail if the frontend doesn't support I2C flush */
+		rc = do_tuner_callback(fe, XC2028_I2C_FLUSH, 0);
+		if ((rc < 0) && (rc != -EINVAL)) {
+			tuner_err("error executing flush: %d\n", rc);
+			return rc;
+		}
 	}
 	return 0;
 }
@@ -933,11 +940,16 @@
 	 * that xc2028 will be in a safe state.
 	 * Maybe this might also be needed for DTV.
 	 */
-	if (new_type == V4L2_TUNER_ANALOG_TV) {
+	switch (new_type) {
+	case V4L2_TUNER_ANALOG_TV:
 		rc = send_seq(priv, {0x00, 0x00});
 
-		/* Analog modes require offset = 0 */
-	} else {
+		/* Analog mode requires offset = 0 */
+		break;
+	case V4L2_TUNER_RADIO:
+		/* Radio mode requires offset = 0 */
+		break;
+	case V4L2_TUNER_DIGITAL_TV:
 		/*
 		 * Digital modes require an offset to adjust to the
 		 * proper frequency. The offset depends on what
diff -druN linux-libre-3.1-gnu/drivers/media/common/tuners/tuner-xc2028.h linux-libre-3.2-gnu/drivers/media/common/tuners/tuner-xc2028.h
--- linux-libre-3.1-gnu/drivers/media/common/tuners/tuner-xc2028.h	2012-03-19 21:31:22.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/common/tuners/tuner-xc2028.h	2012-03-19 21:33:29.000000000 -0400
@@ -54,6 +54,7 @@
 /* xc2028 commands for callback */
 #define XC2028_TUNER_RESET	0
 #define XC2028_RESET_CLK	1
+#define XC2028_I2C_FLUSH	2
 
 #if defined(CONFIG_MEDIA_TUNER_XC2028) || (defined(CONFIG_MEDIA_TUNER_XC2028_MODULE) && defined(MODULE))
 extern struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/b2c2/Makefile linux-libre-3.2-gnu/drivers/media/dvb/b2c2/Makefile
--- linux-libre-3.1-gnu/drivers/media/dvb/b2c2/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/b2c2/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -12,5 +12,5 @@
 b2c2-flexcop-usb-objs = flexcop-usb.o
 obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/common/tuners/
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/bt8xx/Makefile linux-libre-3.2-gnu/drivers/media/dvb/bt8xx/Makefile
--- linux-libre-3.1-gnu/drivers/media/dvb/bt8xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/bt8xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,6 +1,6 @@
 obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += -Idrivers/media/video/bt8xx
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video/bt8xx
+ccflags-y += -Idrivers/media/common/tuners
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/ddbridge/ddbridge-core.c linux-libre-3.2-gnu/drivers/media/dvb/ddbridge/ddbridge-core.c
--- linux-libre-3.1-gnu/drivers/media/dvb/ddbridge/ddbridge-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/ddbridge/ddbridge-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -507,15 +507,14 @@
 	return 0;
 }
 
-static size_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
+static ssize_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
 {
 	struct ddb *dev = input->port->dev;
 	u32 left = count;
-	u32 idx, off, free, stat = input->stat;
+	u32 idx, free, stat = input->stat;
 	int ret;
 
 	idx = (stat >> 11) & 0x1f;
-	off = (stat & 0x7ff) << 7;
 
 	while (left) {
 		if (input->cbuf == idx)
@@ -525,6 +524,8 @@
 			free = left;
 		ret = copy_to_user(buf, input->vbuf[input->cbuf] +
 				   input->coff, free);
+		if (ret)
+			return -EFAULT;
 		input->coff += free;
 		if (input->coff == input->dma_buf_size) {
 			input->coff = 0;
@@ -939,6 +940,8 @@
 				break;
 		}
 		read = ddb_input_read(input, buf, left);
+		if (read < 0)
+			return read;
 		left -= read;
 		buf += read;
 	}
@@ -1438,7 +1441,7 @@
 {
 	struct ddb *dev = file->private_data;
 	void *parg = (void *)arg;
-	int res = -EFAULT;
+	int res;
 
 	switch (cmd) {
 	case IOCTL_DDB_FLASHIO:
@@ -1447,29 +1450,29 @@
 		u8 *rbuf, *wbuf;
 
 		if (copy_from_user(&fio, parg, sizeof(fio)))
-			break;
-		if (fio.write_len + fio.read_len > 1028) {
-			printk(KERN_ERR "IOBUF too small\n");
-			return -ENOMEM;
-		}
+			return -EFAULT;
+
+		if (fio.write_len > 1028 || fio.read_len > 1028)
+			return -EINVAL;
+		if (fio.write_len + fio.read_len > 1028)
+			return -EINVAL;
+
 		wbuf = &dev->iobuf[0];
-		if (!wbuf)
-			return -ENOMEM;
 		rbuf = wbuf + fio.write_len;
-		if (copy_from_user(wbuf, fio.write_buf, fio.write_len)) {
-			vfree(wbuf);
-			break;
-		}
-		res = flashio(dev, wbuf, fio.write_len,
-			      rbuf, fio.read_len);
+
+		if (copy_from_user(wbuf, fio.write_buf, fio.write_len))
+			return -EFAULT;
+		res = flashio(dev, wbuf, fio.write_len, rbuf, fio.read_len);
+		if (res)
+			return res;
 		if (copy_to_user(fio.read_buf, rbuf, fio.read_len))
-			res = -EFAULT;
+			return -EFAULT;
 		break;
 	}
 	default:
-		break;
+		return -ENOTTY;
 	}
-	return res;
+	return 0;
 }
 
 static const struct file_operations ddb_fops = {
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/ddbridge/Makefile linux-libre-3.2-gnu/drivers/media/dvb/ddbridge/Makefile
--- linux-libre-3.1-gnu/drivers/media/dvb/ddbridge/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/ddbridge/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -6,9 +6,9 @@
 
 obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/common/tuners/
 
 # For the staging CI driver cxd2099
-EXTRA_CFLAGS += -Idrivers/staging/cxd2099/
+ccflags-y += -Idrivers/staging/media/cxd2099/
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dm1105/Makefile linux-libre-3.2-gnu/drivers/media/dvb/dm1105/Makefile
--- linux-libre-3.1-gnu/drivers/media/dvb/dm1105/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dm1105/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
 obj-$(CONFIG_DVB_DM1105) += dm1105.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-core/dvb_frontend.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-core/dvb_frontend.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-core/dvb_frontend.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-core/dvb_frontend.c	2012-01-04 18:55:44.000000000 -0500
@@ -149,30 +149,25 @@
 
 	dprintk ("%s\n", __func__);
 
-	if (mutex_lock_interruptible (&events->mtx))
-		return;
+	if ((status & FE_HAS_LOCK) && fe->ops.get_frontend)
+		fe->ops.get_frontend(fe, &fepriv->parameters_out);
 
-	wp = (events->eventw + 1) % MAX_EVENT;
+	mutex_lock(&events->mtx);
 
+	wp = (events->eventw + 1) % MAX_EVENT;
 	if (wp == events->eventr) {
 		events->overflow = 1;
 		events->eventr = (events->eventr + 1) % MAX_EVENT;
 	}
 
 	e = &events->events[events->eventw];
-
-	if (status & FE_HAS_LOCK)
-		if (fe->ops.get_frontend)
-			fe->ops.get_frontend(fe, &fepriv->parameters_out);
-
+	e->status = status;
 	e->parameters = fepriv->parameters_out;
 
 	events->eventw = wp;
 
 	mutex_unlock(&events->mtx);
 
-	e->status = status;
-
 	wake_up_interruptible (&events->wait_queue);
 }
 
@@ -207,19 +202,24 @@
 			return ret;
 	}
 
-	if (mutex_lock_interruptible (&events->mtx))
-		return -ERESTARTSYS;
-
-	memcpy (event, &events->events[events->eventr],
-		sizeof(struct dvb_frontend_event));
-
+	mutex_lock(&events->mtx);
+	*event = events->events[events->eventr];
 	events->eventr = (events->eventr + 1) % MAX_EVENT;
-
 	mutex_unlock(&events->mtx);
 
 	return 0;
 }
 
+static void dvb_frontend_clear_events(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dvb_fe_events *events = &fepriv->events;
+
+	mutex_lock(&events->mtx);
+	events->eventr = events->eventw;
+	mutex_unlock(&events->mtx);
+}
+
 static void dvb_frontend_init(struct dvb_frontend *fe)
 {
 	dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n",
@@ -537,7 +537,6 @@
 {
 	struct dvb_frontend *fe = data;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	unsigned long timeout;
 	fe_status_t s;
 	enum dvbfe_algo algo;
 
@@ -558,7 +557,7 @@
 	while (1) {
 		up(&fepriv->sem);	    /* is locked when we enter the thread... */
 restart:
-		timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
+		wait_event_interruptible_timeout(fepriv->wait_queue,
 			dvb_frontend_should_wakeup(fe) || kthread_should_stop()
 				|| freezing(current),
 			fepriv->delay);
@@ -577,12 +576,10 @@
 
 		if (fepriv->reinitialise) {
 			dvb_frontend_init(fe);
-			if (fepriv->tone != -1) {
+			if (fe->ops.set_tone && fepriv->tone != -1)
 				fe->ops.set_tone(fe, fepriv->tone);
-			}
-			if (fepriv->voltage != -1) {
+			if (fe->ops.set_voltage && fepriv->voltage != -1)
 				fe->ops.set_voltage(fe, fepriv->voltage);
-			}
 			fepriv->reinitialise = 0;
 		}
 
@@ -1019,6 +1016,29 @@
 	return 0;
 }
 
+/* Initialize the cache with some default values derived from the
+ * legacy frontend_info structure.
+ */
+static void dtv_property_cache_init(struct dvb_frontend *fe,
+				    struct dtv_frontend_properties *c)
+{
+	switch (fe->ops.info.type) {
+	case FE_QPSK:
+		c->modulation = QPSK;   /* implied for DVB-S in legacy API */
+		c->rolloff = ROLLOFF_35;/* implied for DVB-S */
+		c->delivery_system = SYS_DVBS;
+		break;
+	case FE_QAM:
+		c->delivery_system = SYS_DVBC_ANNEX_AC;
+		break;
+	case FE_OFDM:
+		c->delivery_system = SYS_DVBT;
+		break;
+	case FE_ATSC:
+		break;
+	}
+}
+
 /* Synchronise the legacy tuning parameters into the cache, so that demodulator
  * drivers can use a single set_frontend tuning function, regardless of whether
  * it's being used for the legacy or new API, reducing code and complexity.
@@ -1032,17 +1052,13 @@
 
 	switch (fe->ops.info.type) {
 	case FE_QPSK:
-		c->modulation = QPSK;   /* implied for DVB-S in legacy API */
-		c->rolloff = ROLLOFF_35;/* implied for DVB-S */
 		c->symbol_rate = p->u.qpsk.symbol_rate;
 		c->fec_inner = p->u.qpsk.fec_inner;
-		c->delivery_system = SYS_DVBS;
 		break;
 	case FE_QAM:
 		c->symbol_rate = p->u.qam.symbol_rate;
 		c->fec_inner = p->u.qam.fec_inner;
 		c->modulation = p->u.qam.modulation;
-		c->delivery_system = SYS_DVBC_ANNEX_AC;
 		break;
 	case FE_OFDM:
 		if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
@@ -1060,7 +1076,6 @@
 		c->transmission_mode = p->u.ofdm.transmission_mode;
 		c->guard_interval = p->u.ofdm.guard_interval;
 		c->hierarchy = p->u.ofdm.hierarchy_information;
-		c->delivery_system = SYS_DVBT;
 		break;
 	case FE_ATSC:
 		c->modulation = p->u.vsb.modulation;
@@ -1132,16 +1147,13 @@
 	p->frequency = c->frequency;
 	p->inversion = c->inversion;
 
-	switch(c->modulation) {
-	case PSK_8:
-	case APSK_16:
-	case APSK_32:
-	case QPSK:
+	if (c->delivery_system == SYS_DSS ||
+	    c->delivery_system == SYS_DVBS ||
+	    c->delivery_system == SYS_DVBS2 ||
+	    c->delivery_system == SYS_ISDBS ||
+	    c->delivery_system == SYS_TURBO) {
 		p->u.qpsk.symbol_rate = c->symbol_rate;
 		p->u.qpsk.fec_inner = c->fec_inner;
-		break;
-	default:
-		break;
 	}
 
 	/* Fake out a generic DVB-T request so we pass validation in the ioctl */
@@ -1824,9 +1836,17 @@
 
 			memcpy (&fepriv->parameters_in, parg,
 				sizeof (struct dvb_frontend_parameters));
+			dtv_property_cache_init(fe, c);
 			dtv_property_cache_sync(fe, c, &fepriv->parameters_in);
 		}
 
+		/*
+		 * Initialize output parameters to match the values given by
+		 * the user. FE_SET_FRONTEND triggers an initial frontend event
+		 * with status = 0, which copies output parameters to userspace.
+		 */
+		fepriv->parameters_out = fepriv->parameters_in;
+
 		memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
 		memcpy(&fetunesettings.parameters, parg,
 		       sizeof (struct dvb_frontend_parameters));
@@ -1884,8 +1904,9 @@
 		/* Request the search algorithm to search */
 		fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
 
-		dvb_frontend_wakeup(fe);
+		dvb_frontend_clear_events(fe);
 		dvb_frontend_add_event(fe, 0);
+		dvb_frontend_wakeup(fe);
 		fepriv->status = 0;
 		err = 0;
 		break;
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-core/dvb_frontend.h linux-libre-3.2-gnu/drivers/media/dvb/dvb-core/dvb_frontend.h
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-core/dvb_frontend.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-core/dvb_frontend.h	2012-01-04 18:55:44.000000000 -0500
@@ -209,6 +209,7 @@
 
 	int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
 	int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
+	int (*get_if_frequency)(struct dvb_frontend *fe, u32 *frequency);
 
 #define TUNER_STATUS_LOCKED 1
 #define TUNER_STATUS_STEREO 2
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-core/dvb_net.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-core/dvb_net.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-core/dvb_net.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-core/dvb_net.c	2012-01-04 18:55:44.000000000 -0500
@@ -1230,7 +1230,7 @@
 	.ndo_open		= dvb_net_open,
 	.ndo_stop		= dvb_net_stop,
 	.ndo_start_xmit		= dvb_net_tx,
-	.ndo_set_multicast_list = dvb_net_set_multicast_list,
+	.ndo_set_rx_mode	= dvb_net_set_multicast_list,
 	.ndo_set_mac_address    = dvb_net_set_mac,
 	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/a800.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/a800.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/a800.c	2012-03-19 21:31:52.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/a800.c	2012-03-19 21:33:56.000000000 -0400
@@ -127,6 +127,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 			.pid_filter_count = 32,
 			.streaming_ctrl   = dibusb2_0_streaming_ctrl,
@@ -147,7 +149,7 @@
 					}
 				}
 			},
-
+		}},
 			.size_of_priv     = sizeof(struct dibusb_state),
 		},
 	},
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/af9005.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/af9005.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/af9005.c	2012-03-19 21:32:00.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/af9005.c	2012-03-19 21:34:05.000000000 -0400
@@ -19,7 +19,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * see Documentation/dvb/REDME.dvb-usb for more information
+ * see Documentation/dvb/README.dvb-usb for more information
  */
 #include "af9005.h"
 
@@ -815,7 +815,7 @@
 			debug_dump(buf, 8, printk);
 		}
 	}
-	adap->fe = af9005_fe_attach(adap->dev);
+	adap->fe_adap[0].fe = af9005_fe_attach(adap->dev);
 	return 0;
 }
 
@@ -999,6 +999,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		    {
+		    .num_frontends = 1,
+		    .fe = {{
 		     .caps =
 		     DVB_USB_ADAP_HAS_PID_FILTER |
 		     DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1018,6 +1020,7 @@
 					       }
 				      }
 				},
+		     }},
 		     }
 		    },
 	.power_ctrl = af9005_power_ctrl,
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/af9005-fe.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/af9005-fe.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/af9005-fe.c	2012-03-19 21:31:45.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/af9005-fe.c	2012-03-19 21:33:49.000000000 -0400
@@ -63,11 +63,9 @@
 				 u16 reglo, u8 pos, u8 len, u16 value)
 {
 	int ret;
-	u8 temp;
 
 	if ((ret = af9005_write_ofdm_register(d, reglo, (u8) (value & 0xff))))
 		return ret;
-	temp = (u8) ((value & 0x0300) >> 8);
 	return af9005_write_register_bits(d, reghi, pos, len,
 					  (u8) ((value & 0x300) >> 8));
 }
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/af9005-remote.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/af9005-remote.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/af9005-remote.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/af9005-remote.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * see Documentation/dvb/REDME.dvb-usb for more information
+ * see Documentation/dvb/README.dvb-usb for more information
  */
 #include "af9005.h"
 /* debug */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/af9015.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/af9015.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/af9015.c	2012-03-19 21:32:09.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/af9015.c	2012-03-19 21:34:16.000000000 -0400
@@ -744,29 +744,31 @@
 };
 
 static const struct af9015_rc_setup af9015_rc_setup_usbids[] = {
-	{ (USB_VID_TERRATEC << 16) + USB_PID_TERRATEC_CINERGY_T_STICK_RC,
+	{ (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,
+	{ (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,
+	{ (USB_VID_VISIONPLUS << 16) | USB_PID_AZUREWAVE_AD_TU700,
 		RC_MAP_AZUREWAVE_AD_TU700 },
-	{ (USB_VID_VISIONPLUS << 16) + USB_PID_TINYTWIN,
+	{ (USB_VID_VISIONPLUS << 16) | USB_PID_TINYTWIN,
 		RC_MAP_AZUREWAVE_AD_TU700 },
-	{ (USB_VID_MSI_2 << 16) + USB_PID_MSI_DIGI_VOX_MINI_III,
+	{ (USB_VID_MSI_2 << 16) | USB_PID_MSI_DIGI_VOX_MINI_III,
 		RC_MAP_MSI_DIGIVOX_III },
-	{ (USB_VID_MSI_2 << 16) + USB_PID_MSI_DIGIVOX_DUO,
+	{ (USB_VID_MSI_2 << 16) | USB_PID_MSI_DIGIVOX_DUO,
 		RC_MAP_MSI_DIGIVOX_III },
-	{ (USB_VID_LEADTEK << 16) + USB_PID_WINFAST_DTV_DONGLE_GOLD,
+	{ (USB_VID_LEADTEK << 16) | USB_PID_WINFAST_DTV_DONGLE_GOLD,
 		RC_MAP_LEADTEK_Y04G0051 },
-	{ (USB_VID_AVERMEDIA << 16) + USB_PID_AVERMEDIA_VOLAR_X,
+	{ (USB_VID_LEADTEK << 16) | USB_PID_WINFAST_DTV2000DS,
+		RC_MAP_LEADTEK_Y04G0051 },
+	{ (USB_VID_AVERMEDIA << 16) | USB_PID_AVERMEDIA_VOLAR_X,
 		RC_MAP_AVERMEDIA_M135A },
-	{ (USB_VID_AFATECH << 16) + USB_PID_TREKSTOR_DVBT,
+	{ (USB_VID_AFATECH << 16) | USB_PID_TREKSTOR_DVBT,
 		RC_MAP_TREKSTOR },
-	{ (USB_VID_KWORLD_2 << 16) + USB_PID_TINYTWIN_2,
+	{ (USB_VID_KWORLD_2 << 16) | USB_PID_TINYTWIN_2,
 		RC_MAP_DIGITALNOW_TINYTWIN },
-	{ (USB_VID_GTEK << 16) + USB_PID_TINYTWIN_3,
+	{ (USB_VID_GTEK << 16) | USB_PID_TINYTWIN_3,
 		RC_MAP_DIGITALNOW_TINYTWIN },
-	{ (USB_VID_KWORLD_2 << 16) + USB_PID_SVEON_STV22,
+	{ (USB_VID_KWORLD_2 << 16) | USB_PID_SVEON_STV22,
 		RC_MAP_MSI_DIGIVOX_III },
 	{ }
 };
@@ -859,13 +861,13 @@
 	for (i = 0; i < af9015_properties_count; i++) {
 		/* USB1.1 set smaller buffersize and disable 2nd adapter */
 		if (udev->speed == USB_SPEED_FULL) {
-			af9015_properties[i].adapter[0].stream.u.bulk.buffersize
+			af9015_properties[i].adapter[0].fe[0].stream.u.bulk.buffersize
 				= TS_USB11_FRAME_SIZE;
 			/* disable 2nd adapter because we don't have
 			   PID-filters */
 			af9015_config.dual_mode = 0;
 		} else {
-			af9015_properties[i].adapter[0].stream.u.bulk.buffersize
+			af9015_properties[i].adapter[0].fe[0].stream.u.bulk.buffersize
 				= TS_USB20_FRAME_SIZE;
 		}
 	}
@@ -1111,10 +1113,10 @@
 	}
 
 	/* attach demodulator */
-	adap->fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id],
+	adap->fe_adap[0].fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id],
 		&adap->dev->i2c_adap);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static struct mt2060_config af9015_mt2060_config = {
@@ -1188,49 +1190,49 @@
 	switch (af9015_af9013_config[adap->id].tuner) {
 	case AF9013_TUNER_MT2060:
 	case AF9013_TUNER_MT2060_2:
-		ret = dvb_attach(mt2060_attach, adap->fe, &adap->dev->i2c_adap,
+		ret = dvb_attach(mt2060_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 			&af9015_mt2060_config,
 			af9015_config.mt2060_if1[adap->id])
 			== NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_QT1010:
 	case AF9013_TUNER_QT1010A:
-		ret = dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap,
+		ret = dvb_attach(qt1010_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 			&af9015_qt1010_config) == NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_TDA18271:
-		ret = dvb_attach(tda18271_attach, adap->fe, 0xc0,
+		ret = dvb_attach(tda18271_attach, adap->fe_adap[0].fe, 0xc0,
 			&adap->dev->i2c_adap,
 			&af9015_tda18271_config) == NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_TDA18218:
-		ret = dvb_attach(tda18218_attach, adap->fe,
+		ret = dvb_attach(tda18218_attach, adap->fe_adap[0].fe,
 			&adap->dev->i2c_adap,
 			&af9015_tda18218_config) == NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_MXL5003D:
-		ret = dvb_attach(mxl5005s_attach, adap->fe,
+		ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
 			&adap->dev->i2c_adap,
 			&af9015_mxl5003_config) == NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_MXL5005D:
 	case AF9013_TUNER_MXL5005R:
-		ret = dvb_attach(mxl5005s_attach, adap->fe,
+		ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
 			&adap->dev->i2c_adap,
 			&af9015_mxl5005_config) == NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_ENV77H11D5:
-		ret = dvb_attach(dvb_pll_attach, adap->fe, 0xc0,
+		ret = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0xc0,
 			&adap->dev->i2c_adap,
 			DVB_PLL_TDA665X) == NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_MC44S803:
-		ret = dvb_attach(mc44s803_attach, adap->fe,
+		ret = dvb_attach(mc44s803_attach, adap->fe_adap[0].fe,
 			&adap->dev->i2c_adap,
 			&af9015_mc44s803_config) == NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_MXL5007T:
-		ret = dvb_attach(mxl5007t_attach, adap->fe,
+		ret = dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe,
 			&adap->dev->i2c_adap,
 			0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0;
 		break;
@@ -1304,6 +1306,8 @@
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER |
 				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
@@ -1319,8 +1323,11 @@
 					.count = 6,
 					.endpoint = 0x84,
 				},
+			}},
 			},
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.frontend_attach =
 					af9015_af9013_frontend_attach,
 				.tuner_attach    = af9015_tuner_attach,
@@ -1335,6 +1342,7 @@
 						}
 					}
 				},
+			}},
 			}
 		},
 
@@ -1432,6 +1440,8 @@
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER |
 				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
@@ -1447,8 +1457,11 @@
 					.count = 6,
 					.endpoint = 0x84,
 				},
+			}},
 			},
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.frontend_attach =
 					af9015_af9013_frontend_attach,
 				.tuner_attach    = af9015_tuner_attach,
@@ -1463,6 +1476,7 @@
 						}
 					}
 				},
+			}},
 			}
 		},
 
@@ -1549,6 +1563,8 @@
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER |
 				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
@@ -1564,8 +1580,11 @@
 					.count = 6,
 					.endpoint = 0x84,
 				},
+			}},
 			},
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.frontend_attach =
 					af9015_af9013_frontend_attach,
 				.tuner_attach    = af9015_tuner_attach,
@@ -1580,6 +1599,7 @@
 						}
 					}
 				},
+			}},
 			}
 		},
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/anysee.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/anysee.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/anysee.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/anysee.c	2012-01-04 18:55:44.000000000 -0500
@@ -446,6 +446,114 @@
  * IOE[5] STV0903 1=enabled
  */
 
+static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff)
+{
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct anysee_state *state = adap->dev->priv;
+	int ret;
+
+	deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff);
+
+	/* no frontend sleep control */
+	if (onoff == 0)
+		return 0;
+
+	switch (state->hw) {
+	case ANYSEE_HW_507FA: /* 15 */
+		/* E30 Combo Plus */
+		/* E30 C Plus */
+
+		if ((fe->id ^ dvb_usb_anysee_delsys) == 0)  {
+			/* disable DVB-T demod on IOD[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
+				0x01);
+			if (ret)
+				goto error;
+
+			/* enable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+				0x20);
+			if (ret)
+				goto error;
+
+			/* enable DVB-C tuner on IOE[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
+				0x01);
+			if (ret)
+				goto error;
+		} else {
+			/* disable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
+				0x20);
+			if (ret)
+				goto error;
+
+			/* enable DVB-T demod on IOD[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
+				0x01);
+			if (ret)
+				goto error;
+
+			/* enable DVB-T tuner on IOE[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
+				0x01);
+			if (ret)
+				goto error;
+		}
+
+		break;
+	case ANYSEE_HW_508TC: /* 18 */
+	case ANYSEE_HW_508PTC: /* 21 */
+		/* E7 TC */
+		/* E7 PTC */
+
+		if ((fe->id ^ dvb_usb_anysee_delsys) == 0)  {
+			/* disable DVB-T demod on IOD[6] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
+				0x40);
+			if (ret)
+				goto error;
+
+			/* enable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+				0x20);
+			if (ret)
+				goto error;
+
+			/* enable IF route on IOE[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
+				0x01);
+			if (ret)
+				goto error;
+		} else {
+			/* disable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
+				0x20);
+			if (ret)
+				goto error;
+
+			/* enable DVB-T demod on IOD[6] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
+				0x40);
+			if (ret)
+				goto error;
+
+			/* enable IF route on IOE[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
+				0x01);
+			if (ret)
+				goto error;
+		}
+
+		break;
+	default:
+		ret = 0;
+	}
+
+error:
+	return ret;
+}
+
 static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	int ret;
@@ -466,41 +574,54 @@
 		}
 	};
 
-	/* Check which hardware we have.
-	 * We must do this call two times to get reliable values (hw bug).
-	 */
-	ret = anysee_get_hw_info(adap->dev, hw_info);
-	if (ret)
-		goto error;
+	/* detect hardware only once */
+	if (adap->fe_adap[0].fe == NULL) {
+		/* Check which hardware we have.
+		 * We must do this call two times to get reliable values (hw bug).
+		 */
+		ret = anysee_get_hw_info(adap->dev, hw_info);
+		if (ret)
+			goto error;
 
-	ret = anysee_get_hw_info(adap->dev, hw_info);
-	if (ret)
-		goto error;
+		ret = anysee_get_hw_info(adap->dev, hw_info);
+		if (ret)
+			goto error;
 
-	/* Meaning of these info bytes are guessed. */
-	info("firmware version:%d.%d hardware id:%d",
-		hw_info[1], hw_info[2], hw_info[0]);
+		/* Meaning of these info bytes are guessed. */
+		info("firmware version:%d.%d hardware id:%d",
+			hw_info[1], hw_info[2], hw_info[0]);
 
-	state->hw = hw_info[0];
+		state->hw = hw_info[0];
+	}
+
+	/* set current frondend ID for devices having two frondends */
+	if (adap->fe_adap[0].fe)
+		state->fe_id++;
 
 	switch (state->hw) {
 	case ANYSEE_HW_507T: /* 2 */
 		/* E30 */
 
+		if (state->fe_id)
+			break;
+
 		/* attach demod */
-		adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config,
+		adap->fe_adap[0].fe = dvb_attach(mt352_attach, &anysee_mt352_config,
 			&adap->dev->i2c_adap);
-		if (adap->fe)
+		if (adap->fe_adap[0].fe)
 			break;
 
 		/* attach demod */
-		adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
+		adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
 			&adap->dev->i2c_adap);
 
 		break;
 	case ANYSEE_HW_507CD: /* 6 */
 		/* E30 Plus */
 
+		if (state->fe_id)
+			break;
+
 		/* enable DVB-T demod on IOD[0] */
 		ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
 		if (ret)
@@ -512,33 +633,39 @@
 			goto error;
 
 		/* attach demod */
-		adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
-			&adap->dev->i2c_adap);
+		adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
+			&anysee_zl10353_config, &adap->dev->i2c_adap);
 
 		break;
 	case ANYSEE_HW_507DC: /* 10 */
 		/* E30 C Plus */
 
+		if (state->fe_id)
+			break;
+
 		/* enable DVB-C demod on IOD[0] */
 		ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
 		if (ret)
 			goto error;
 
 		/* attach demod */
-		adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config,
-			&adap->dev->i2c_adap, 0x48);
+		adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
+			&anysee_tda10023_config, &adap->dev->i2c_adap, 0x48);
 
 		break;
 	case ANYSEE_HW_507SI: /* 11 */
 		/* E30 S2 Plus */
 
+		if (state->fe_id)
+			break;
+
 		/* enable DVB-S/S2 demod on IOD[0] */
 		ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
 		if (ret)
 			goto error;
 
 		/* attach demod */
-		adap->fe = dvb_attach(cx24116_attach, &anysee_cx24116_config,
+		adap->fe_adap[0].fe = dvb_attach(cx24116_attach, &anysee_cx24116_config,
 			&adap->dev->i2c_adap);
 
 		break;
@@ -564,55 +691,59 @@
 		if (ret)
 			goto error;
 
-		if (dvb_usb_anysee_delsys) {
-			/* disable DVB-C demod on IOD[5] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
-				0x20);
+		if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0)  {
+			/* disable DVB-T demod on IOD[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
+				0x01);
 			if (ret)
 				goto error;
 
-			/* enable DVB-T demod on IOD[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
-				0x01);
+			/* enable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+				0x20);
 			if (ret)
 				goto error;
 
 			/* attach demod */
 			if (tmp == 0xc7) {
 				/* TDA18212 config */
-				adap->fe = dvb_attach(zl10353_attach,
-					&anysee_zl10353_tda18212_config2,
-					&adap->dev->i2c_adap);
+				adap->fe_adap[state->fe_id].fe = dvb_attach(
+					tda10023_attach,
+					&anysee_tda10023_tda18212_config,
+					&adap->dev->i2c_adap, 0x48);
 			} else {
 				/* PLL config */
-				adap->fe = dvb_attach(zl10353_attach,
-					&anysee_zl10353_config,
-					&adap->dev->i2c_adap);
+				adap->fe_adap[state->fe_id].fe = dvb_attach(
+					tda10023_attach,
+					&anysee_tda10023_config,
+					&adap->dev->i2c_adap, 0x48);
 			}
 		} else {
-			/* disable DVB-T demod on IOD[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
-				0x01);
+			/* disable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
+				0x20);
 			if (ret)
 				goto error;
 
-			/* enable DVB-C demod on IOD[5] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
-				0x20);
+			/* enable DVB-T demod on IOD[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
+				0x01);
 			if (ret)
 				goto error;
 
 			/* attach demod */
 			if (tmp == 0xc7) {
 				/* TDA18212 config */
-				adap->fe = dvb_attach(tda10023_attach,
-					&anysee_tda10023_tda18212_config,
-					&adap->dev->i2c_adap, 0x48);
+				adap->fe_adap[state->fe_id].fe = dvb_attach(
+					zl10353_attach,
+					&anysee_zl10353_tda18212_config2,
+					&adap->dev->i2c_adap);
 			} else {
 				/* PLL config */
-				adap->fe = dvb_attach(tda10023_attach,
-					&anysee_tda10023_config,
-					&adap->dev->i2c_adap, 0x48);
+				adap->fe_adap[state->fe_id].fe = dvb_attach(
+					zl10353_attach,
+					&anysee_zl10353_config,
+					&adap->dev->i2c_adap);
 			}
 		}
 
@@ -627,52 +758,40 @@
 		if (ret)
 			goto error;
 
-		if (dvb_usb_anysee_delsys) {
-			/* disable DVB-C demod on IOD[5] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
-				0x20);
-			if (ret)
-				goto error;
-
-			/* enable DVB-T demod on IOD[6] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
+		if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0)  {
+			/* disable DVB-T demod on IOD[6] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
 				0x40);
 			if (ret)
 				goto error;
 
-			/* enable IF route on IOE[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
-				0x01);
+			/* enable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+				0x20);
 			if (ret)
 				goto error;
 
 			/* attach demod */
-			adap->fe = dvb_attach(zl10353_attach,
-				&anysee_zl10353_tda18212_config,
-				&adap->dev->i2c_adap);
+			adap->fe_adap[state->fe_id].fe = dvb_attach(tda10023_attach,
+				&anysee_tda10023_tda18212_config,
+				&adap->dev->i2c_adap, 0x48);
 		} else {
-			/* disable DVB-T demod on IOD[6] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
-				0x40);
-			if (ret)
-				goto error;
-
-			/* enable DVB-C demod on IOD[5] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+			/* disable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
 				0x20);
 			if (ret)
 				goto error;
 
-			/* enable IF route on IOE[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
-				0x01);
+			/* enable DVB-T demod on IOD[6] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
+				0x40);
 			if (ret)
 				goto error;
 
 			/* attach demod */
-			adap->fe = dvb_attach(tda10023_attach,
-				&anysee_tda10023_tda18212_config,
-				&adap->dev->i2c_adap, 0x48);
+			adap->fe_adap[state->fe_id].fe = dvb_attach(zl10353_attach,
+				&anysee_zl10353_tda18212_config,
+				&adap->dev->i2c_adap);
 		}
 
 		break;
@@ -681,6 +800,9 @@
 		/* E7 S2 */
 		/* E7 PS2 */
 
+		if (state->fe_id)
+			break;
+
 		/* enable transport stream on IOA[7] */
 		ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
 		if (ret)
@@ -692,13 +814,13 @@
 			goto error;
 
 		/* attach demod */
-		adap->fe = dvb_attach(stv0900_attach, &anysee_stv0900_config,
+		adap->fe_adap[0].fe = dvb_attach(stv0900_attach, &anysee_stv0900_config,
 			&adap->dev->i2c_adap, 0);
 
 		break;
 	}
 
-	if (!adap->fe) {
+	if (!adap->fe_adap[0].fe) {
 		/* we have no frontend :-( */
 		ret = -ENODEV;
 		err("Unsupported Anysee version. " \
@@ -713,14 +835,14 @@
 	struct anysee_state *state = adap->dev->priv;
 	struct dvb_frontend *fe;
 	int ret;
-	deb_info("%s:\n", __func__);
+	deb_info("%s: fe=%d\n", __func__, state->fe_id);
 
 	switch (state->hw) {
 	case ANYSEE_HW_507T: /* 2 */
 		/* E30 */
 
 		/* attach tuner */
-		fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1),
+		fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc2 >> 1),
 			NULL, DVB_PLL_THOMSON_DTT7579);
 
 		break;
@@ -728,7 +850,7 @@
 		/* E30 Plus */
 
 		/* attach tuner */
-		fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1),
+		fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc2 >> 1),
 			&adap->dev->i2c_adap, DVB_PLL_THOMSON_DTT7579);
 
 		break;
@@ -736,7 +858,7 @@
 		/* E30 C Plus */
 
 		/* attach tuner */
-		fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1),
+		fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc0 >> 1),
 			&adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
 
 		break;
@@ -744,28 +866,14 @@
 		/* E30 S2 Plus */
 
 		/* attach LNB controller */
-		fe = dvb_attach(isl6423_attach, adap->fe, &adap->dev->i2c_adap,
-			&anysee_isl6423_config);
+		fe = dvb_attach(isl6423_attach, adap->fe_adap[0].fe,
+			&adap->dev->i2c_adap, &anysee_isl6423_config);
 
 		break;
 	case ANYSEE_HW_507FA: /* 15 */
 		/* E30 Combo Plus */
 		/* E30 C Plus */
 
-		if (dvb_usb_anysee_delsys) {
-			/* enable DVB-T tuner on IOE[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
-				0x01);
-			if (ret)
-				goto error;
-		} else {
-			/* enable DVB-C tuner on IOE[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
-				0x01);
-			if (ret)
-				goto error;
-		}
-
 		/* Try first attach TDA18212 silicon tuner on IOE[4], if that
 		 * fails attach old simple PLL. */
 
@@ -775,8 +883,8 @@
 			goto error;
 
 		/* attach tuner */
-		fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap,
-			&anysee_tda18212_config);
+		fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
+			&adap->dev->i2c_adap, &anysee_tda18212_config);
 		if (fe)
 			break;
 
@@ -786,8 +894,9 @@
 			goto error;
 
 		/* attach tuner */
-		fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1),
-			&adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
+		fe = dvb_attach(dvb_pll_attach, adap->fe_adap[state->fe_id].fe,
+			(0xc0 >> 1), &adap->dev->i2c_adap,
+			DVB_PLL_SAMSUNG_DTOS403IH102A);
 
 		break;
 	case ANYSEE_HW_508TC: /* 18 */
@@ -801,8 +910,8 @@
 			goto error;
 
 		/* attach tuner */
-		fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap,
-			&anysee_tda18212_config);
+		fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
+			&adap->dev->i2c_adap, &anysee_tda18212_config);
 
 		break;
 	case ANYSEE_HW_508S2: /* 19 */
@@ -811,12 +920,12 @@
 		/* E7 PS2 */
 
 		/* attach tuner */
-		fe = dvb_attach(stv6110_attach, adap->fe,
+		fe = dvb_attach(stv6110_attach, adap->fe_adap[0].fe,
 			&anysee_stv6110_config, &adap->dev->i2c_adap);
 
 		if (fe) {
 			/* attach LNB controller */
-			fe = dvb_attach(isl6423_attach, adap->fe,
+			fe = dvb_attach(isl6423_attach, adap->fe_adap[0].fe,
 				&adap->dev->i2c_adap, &anysee_isl6423_config);
 		}
 
@@ -918,6 +1027,9 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends    = 2,
+		.frontend_ctrl    = anysee_frontend_ctrl,
+		.fe = {{
 			.streaming_ctrl   = anysee_streaming_ctrl,
 			.frontend_attach  = anysee_frontend_attach,
 			.tuner_attach     = anysee_tuner_attach,
@@ -931,6 +1043,21 @@
 					}
 				}
 			},
+		}, {
+			.streaming_ctrl   = anysee_streaming_ctrl,
+			.frontend_attach  = anysee_frontend_attach,
+			.tuner_attach     = anysee_tuner_attach,
+			.stream = {
+				.type = USB_BULK,
+				.count = 8,
+				.endpoint = 0x82,
+				.u = {
+					.bulk = {
+						.buffersize = (16*512),
+					}
+				}
+			},
+		}},
 		}
 	},
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/anysee.h linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/anysee.h
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/anysee.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/anysee.h	2012-01-04 18:55:44.000000000 -0500
@@ -59,6 +59,7 @@
 struct anysee_state {
 	u8 hw; /* PCB ID */
 	u8 seq;
+	u8 fe_id:1; /* frondend ID */
 };
 
 #define ANYSEE_HW_507T    2 /* E30 */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/au6610.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/au6610.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/au6610.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/au6610.c	2012-01-04 18:55:44.000000000 -0500
@@ -140,9 +140,9 @@
 
 static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
+	adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
 		&adap->dev->i2c_adap);
-	if (adap->fe == NULL)
+	if (adap->fe_adap[0].fe == NULL)
 		return -ENODEV;
 
 	return 0;
@@ -155,7 +155,7 @@
 static int au6610_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	return dvb_attach(qt1010_attach,
-			  adap->fe, &adap->dev->i2c_adap,
+			  adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 			  &au6610_qt1010_config) == NULL ? -ENODEV : 0;
 }
 
@@ -204,6 +204,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach  = au6610_zl10353_frontend_attach,
 			.tuner_attach     = au6610_qt1010_tuner_attach,
 
@@ -219,6 +221,7 @@
 					}
 				}
 			},
+		}},
 		}
 	},
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/az6027.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/az6027.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/az6027.c	2012-03-19 21:32:15.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/az6027.c	2012-03-19 21:34:24.000000000 -0400
@@ -40,7 +40,6 @@
 	{ STB0899_DISRX_ST0     	, 0x04 },
 	{ STB0899_DISRX_ST1     	, 0x00 },
 	{ STB0899_DISPARITY     	, 0x00 },
-	{ STB0899_DISFIFO       	, 0x00 },
 	{ STB0899_DISSTATUS		, 0x20 },
 	{ STB0899_DISF22        	, 0x99 },
 	{ STB0899_DISF22RX      	, 0xa8 },
@@ -782,7 +781,6 @@
 {
 
 	u8 buf;
-	int ret;
 	struct dvb_usb_adapter *adap = fe->dvb->priv;
 
 	struct i2c_msg i2c_msg = {
@@ -800,17 +798,17 @@
 	switch (voltage) {
 	case SEC_VOLTAGE_13:
 		buf = 1;
-		ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
+		i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
 		break;
 
 	case SEC_VOLTAGE_18:
 		buf = 2;
-		ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
+		i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
 		break;
 
 	case SEC_VOLTAGE_OFF:
 		buf = 0;
-		ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
+		i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
 		break;
 
 	default:
@@ -910,16 +908,16 @@
 	az6027_frontend_reset(adap);
 
 	deb_info("adap = %p, dev = %p\n", adap, adap->dev);
-	adap->fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap);
+	adap->fe_adap[0].fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap);
 
-	if (adap->fe) {
+	if (adap->fe_adap[0].fe) {
 		deb_info("found STB0899 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb0899_config.demod_address);
-		if (stb6100_attach(adap->fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) {
+		if (stb6100_attach(adap->fe_adap[0].fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) {
 			deb_info("found STB6100 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb6100_config.tuner_address);
-			adap->fe->ops.set_voltage = az6027_set_voltage;
+			adap->fe_adap[0].fe->ops.set_voltage = az6027_set_voltage;
 			az6027_ci_init(adap);
 		} else {
-			adap->fe = NULL;
+			adap->fe_adap[0].fe = NULL;
 		}
 	} else
 		warn("no front-end attached\n");
@@ -954,7 +952,6 @@
 {
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
 	int i = 0, j = 0, len = 0;
-	int ret;
 	u16 index;
 	u16 value;
 	int length;
@@ -990,7 +987,7 @@
 				index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
 				value = msg[i].addr + (msg[i].len << 8);
 				length = msg[i + 1].len + 6;
-				ret = az6027_usb_in_op(d, req, value, index, data, length);
+				az6027_usb_in_op(d, req, value, index, data, length);
 				len = msg[i + 1].len;
 				for (j = 0; j < len; j++)
 					msg[i + 1].buf[j] = data[j + 5];
@@ -1017,7 +1014,7 @@
 				index = 0x0;
 				value = msg[i].addr;
 				length = msg[i].len + 6;
-				ret = az6027_usb_in_op(d, req, value, index, data, length);
+				az6027_usb_in_op(d, req, value, index, data, length);
 				len = msg[i].len;
 				for (j = 0; j < len; j++)
 					msg[i].buf[j] = data[j + 5];
@@ -1106,6 +1103,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = az6027_streaming_ctrl,
 			.frontend_attach  = az6027_frontend_attach,
 
@@ -1120,6 +1119,7 @@
 					}
 				}
 			},
+		}},
 		}
 	},
 /*
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/ce6230.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/ce6230.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/ce6230.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/ce6230.c	2012-01-04 18:55:44.000000000 -0500
@@ -186,9 +186,9 @@
 static int ce6230_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	deb_info("%s:\n", __func__);
-	adap->fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config,
+	adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config,
 		&adap->dev->i2c_adap);
-	if (adap->fe == NULL)
+	if (adap->fe_adap[0].fe == NULL)
 		return -ENODEV;
 	return 0;
 }
@@ -214,7 +214,7 @@
 {
 	int ret;
 	deb_info("%s:\n", __func__);
-	ret = dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap,
+	ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 			&ce6230_mxl5003s_config) == NULL ? -ENODEV : 0;
 	return ret;
 }
@@ -273,6 +273,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach  = ce6230_zl10353_frontend_attach,
 			.tuner_attach     = ce6230_mxl5003s_tuner_attach,
 			.stream = {
@@ -285,6 +287,7 @@
 					}
 				}
 			},
+		}},
 		}
 	},
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/cinergyT2-core.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/cinergyT2-core.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/cinergyT2-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/cinergyT2-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -69,7 +69,7 @@
 	char state[3];
 	int ret;
 
-	adap->fe = cinergyt2_fe_attach(adap->dev);
+	adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev);
 
 	ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state,
 				sizeof(state), 0);
@@ -198,6 +198,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cinergyt2_streaming_ctrl,
 			.frontend_attach  = cinergyt2_frontend_attach,
 
@@ -212,6 +214,7 @@
 					}
 				}
 			},
+		}},
 		}
 	},
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/cxusb.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/cxusb.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/cxusb.c	2012-03-19 21:32:24.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/cxusb.c	2012-03-19 21:34:34.000000000 -0400
@@ -347,7 +347,7 @@
 
 static void cxusb_d680_dmb_drain_video(struct dvb_usb_device *d)
 {
-	struct usb_data_stream_properties *p = &d->props.adapter[0].stream;
+	struct usb_data_stream_properties *p = &d->props.adapter[0].fe[0].stream;
 	const int timeout = 100;
 	const int junk_len = p->u.bulk.buffersize;
 	u8        *junk;
@@ -725,7 +725,7 @@
 /* Callbacks for DVB USB */
 static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(simple_tuner_attach, adap->fe,
+	dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
 		   &adap->dev->i2c_adap, 0x61,
 		   TUNER_PHILIPS_FMD1216ME_MK3);
 	return 0;
@@ -733,27 +733,27 @@
 
 static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(dvb_pll_attach, adap->fe, 0x61,
+	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61,
 		   NULL, DVB_PLL_THOMSON_DTT7579);
 	return 0;
 }
 
 static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, DVB_PLL_LG_Z201);
+	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, NULL, DVB_PLL_LG_Z201);
 	return 0;
 }
 
 static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
 		   NULL, DVB_PLL_THOMSON_DTT7579);
 	return 0;
 }
 
 static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(simple_tuner_attach, adap->fe,
+	dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
 		   &adap->dev->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF);
 	return 0;
 }
@@ -795,9 +795,9 @@
 	};
 
 	/* FIXME: generalize & move to common area */
-	adap->fe->callback = dvico_bluebird_xc2028_callback;
+	adap->fe_adap[0].fe->callback = dvico_bluebird_xc2028_callback;
 
-	fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
+	fe = dvb_attach(xc2028_attach, adap->fe_adap[0].fe, &cfg);
 	if (fe == NULL || fe->ops.tuner_ops.set_config == NULL)
 		return -EIO;
 
@@ -808,7 +808,7 @@
 
 static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(mxl5005s_attach, adap->fe,
+	dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
 		   &adap->dev->i2c_adap, &aver_a868r_tuner);
 	return 0;
 }
@@ -816,7 +816,7 @@
 static int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dvb_frontend *fe;
-	fe = dvb_attach(mxl5005s_attach, adap->fe,
+	fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
 			&adap->dev->i2c_adap, &d680_dmb_tuner);
 	return (fe == NULL) ? -EIO : 0;
 }
@@ -824,7 +824,7 @@
 static int cxusb_mygica_d689_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dvb_frontend *fe;
-	fe = dvb_attach(max2165_attach, adap->fe,
+	fe = dvb_attach(max2165_attach, adap->fe_adap[0].fe,
 			&adap->dev->i2c_adap, &mygica_d689_max2165_cfg);
 	return (fe == NULL) ? -EIO : 0;
 }
@@ -837,8 +837,9 @@
 
 	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1);
 
-	if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config,
-				   &adap->dev->i2c_adap)) != NULL)
+	adap->fe_adap[0].fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL)
 		return 0;
 
 	return -EIO;
@@ -851,8 +852,10 @@
 
 	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
 
-	if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config,
-				   &adap->dev->i2c_adap)) != NULL)
+	adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach,
+					 &cxusb_lgdt3303_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL)
 		return 0;
 
 	return -EIO;
@@ -860,9 +863,9 @@
 
 static int cxusb_aver_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	adap->fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config,
+	adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config,
 			      &adap->dev->i2c_adap);
-	if (adap->fe != NULL)
+	if (adap->fe_adap[0].fe != NULL)
 		return 0;
 
 	return -EIO;
@@ -876,8 +879,9 @@
 
 	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
 
-	if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config,
-				   &adap->dev->i2c_adap)) != NULL)
+	adap->fe_adap[0].fe = dvb_attach(mt352_attach, &cxusb_mt352_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL)
 		return 0;
 
 	return -EIO;
@@ -890,11 +894,15 @@
 
 	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
 
-	if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config,
-				    &adap->dev->i2c_adap)) != NULL) ||
-		((adap->fe = dvb_attach(zl10353_attach,
-					&cxusb_zl10353_dee1601_config,
-					&adap->dev->i2c_adap)) != NULL))
+	adap->fe_adap[0].fe = dvb_attach(mt352_attach, &cxusb_dee1601_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL)
+		return 0;
+
+	adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
+					 &cxusb_zl10353_dee1601_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL)
 		return 0;
 
 	return -EIO;
@@ -917,9 +925,11 @@
 	cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
 	cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
 
-	if ((adap->fe = dvb_attach(zl10353_attach,
-				   &cxusb_zl10353_xc3028_config_no_i2c_gate,
-				   &adap->dev->i2c_adap)) == NULL)
+	adap->fe_adap[0].fe =
+		dvb_attach(zl10353_attach,
+			   &cxusb_zl10353_xc3028_config_no_i2c_gate,
+			   &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) == NULL)
 		return -EIO;
 
 	/* try to determine if there is no IR decoder on the I2C bus */
@@ -1031,9 +1041,9 @@
 		return -ENODEV;
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
 			      &cxusb_dualdig4_rev2_config);
-	if (adap->fe == NULL)
+	if (adap->fe_adap[0].fe == NULL)
 		return -EIO;
 
 	return 0;
@@ -1084,15 +1094,15 @@
 {
 	struct dib0700_adapter_state *st = adap->priv;
 	struct i2c_adapter *tun_i2c =
-		dib7000p_get_i2c_master(adap->fe,
+		dib7000p_get_i2c_master(adap->fe_adap[0].fe,
 					DIBX000_I2C_INTERFACE_TUNER, 1);
 
-	if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
+	if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
 	    &dib7070p_dib0070_config) == NULL)
 		return -ENODEV;
 
-	st->set_param_save = adap->fe->ops.tuner_ops.set_params;
-	adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7070_set_param_override;
 	return 0;
 }
 
@@ -1108,14 +1118,16 @@
 	cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
 	cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
 
-	if ((adap->fe = dvb_attach(zl10353_attach,
-				   &cxusb_zl10353_xc3028_config,
-				   &adap->dev->i2c_adap)) != NULL)
+	adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
+					 &cxusb_zl10353_xc3028_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL)
 		return 0;
 
-	if ((adap->fe = dvb_attach(mt352_attach,
-				   &cxusb_mt352_xc3028_config,
-				   &adap->dev->i2c_adap)) != NULL)
+	adap->fe_adap[0].fe = dvb_attach(mt352_attach,
+					 &cxusb_mt352_xc3028_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL)
 		return 0;
 
 	return -EIO;
@@ -1150,7 +1162,7 @@
 	usb_clear_halt(d->udev,
 		usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
 	usb_clear_halt(d->udev,
-		usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint));
+		usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint));
 
 	/* Drain USB pipes to avoid hang after reboot */
 	for (n = 0;  n < 5;  n++) {
@@ -1172,8 +1184,8 @@
 	msleep(100);
 
 	/* Attach frontend */
-	adap->fe = dvb_attach(lgs8gxx_attach, &d680_lgs8gl5_cfg, &d->i2c_adap);
-	if (adap->fe == NULL)
+	adap->fe_adap[0].fe = dvb_attach(lgs8gxx_attach, &d680_lgs8gl5_cfg, &d->i2c_adap);
+	if (adap->fe_adap[0].fe == NULL)
 		return -EIO;
 
 	return 0;
@@ -1207,7 +1219,7 @@
 	usb_clear_halt(d->udev,
 		usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
 	usb_clear_halt(d->udev,
-		usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint));
+		usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint));
 
 
 	/* Reset the tuner */
@@ -1223,9 +1235,9 @@
 	msleep(100);
 
 	/* Attach frontend */
-	adap->fe = dvb_attach(atbm8830_attach, &mygica_d689_atbm8830_cfg,
+	adap->fe_adap[0].fe = dvb_attach(atbm8830_attach, &mygica_d689_atbm8830_cfg,
 		&d->i2c_adap);
-	if (adap->fe == NULL)
+	if (adap->fe_adap[0].fe == NULL)
 		return -EIO;
 
 	return 0;
@@ -1383,6 +1395,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
 			.frontend_attach  = cxusb_cx22702_frontend_attach,
 			.tuner_attach     = cxusb_fmd1216me_tuner_attach,
@@ -1397,7 +1411,7 @@
 					}
 				}
 			},
-
+		}},
 		},
 	},
 	.power_ctrl       = cxusb_power_ctrl,
@@ -1429,6 +1443,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
 			.frontend_attach  = cxusb_lgdt3303_frontend_attach,
 			.tuner_attach     = cxusb_lgh064f_tuner_attach,
@@ -1444,6 +1460,7 @@
 					}
 				}
 			},
+		}},
 		},
 	},
 
@@ -1483,6 +1500,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
 			.frontend_attach  = cxusb_dee1601_frontend_attach,
 			.tuner_attach     = cxusb_dee1601_tuner_attach,
@@ -1497,6 +1516,7 @@
 					}
 				}
 			},
+		}},
 		},
 	},
 
@@ -1544,6 +1564,8 @@
 	.num_adapters = 2,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
 			.frontend_attach  = cxusb_mt352_frontend_attach,
 			.tuner_attach     = cxusb_lgz201_tuner_attach,
@@ -1559,6 +1581,7 @@
 					}
 				}
 			},
+		}},
 		},
 	},
 	.power_ctrl       = cxusb_bluebird_power_ctrl,
@@ -1596,6 +1619,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
 			.frontend_attach  = cxusb_mt352_frontend_attach,
 			.tuner_attach     = cxusb_dtt7579_tuner_attach,
@@ -1611,6 +1636,7 @@
 					}
 				}
 			},
+		}},
 		},
 	},
 	.power_ctrl       = cxusb_bluebird_power_ctrl,
@@ -1645,6 +1671,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
 			.frontend_attach  = cxusb_dualdig4_frontend_attach,
 			.tuner_attach     = cxusb_dvico_xc3028_tuner_attach,
@@ -1659,6 +1687,7 @@
 					}
 				}
 			},
+		}},
 		},
 	},
 
@@ -1695,6 +1724,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
 			.frontend_attach  = cxusb_nano2_frontend_attach,
 			.tuner_attach     = cxusb_dvico_xc3028_tuner_attach,
@@ -1709,6 +1740,7 @@
 					}
 				}
 			},
+		}},
 		},
 	},
 
@@ -1747,6 +1779,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
 			.frontend_attach  = cxusb_nano2_frontend_attach,
 			.tuner_attach     = cxusb_dvico_xc3028_tuner_attach,
@@ -1761,6 +1795,7 @@
 					}
 				}
 			},
+		}},
 		},
 	},
 
@@ -1796,6 +1831,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_aver_streaming_ctrl,
 			.frontend_attach  = cxusb_aver_lgdt3303_frontend_attach,
 			.tuner_attach     = cxusb_mxl5003s_tuner_attach,
@@ -1810,7 +1847,7 @@
 					}
 				}
 			},
-
+		}},
 		},
 	},
 	.power_ctrl       = cxusb_aver_power_ctrl,
@@ -1839,10 +1876,12 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.size_of_priv    = sizeof(struct dib0700_adapter_state),
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl  = cxusb_streaming_ctrl,
 			.frontend_attach = cxusb_dualdig4_rev2_frontend_attach,
 			.tuner_attach    = cxusb_dualdig4_rev2_tuner_attach,
-			.size_of_priv    = sizeof(struct dib0700_adapter_state),
 			/* parameter for the MPEG2-data transfer */
 			.stream = {
 				.type = USB_BULK,
@@ -1854,6 +1893,7 @@
 					}
 				}
 			},
+		}},
 		},
 	},
 
@@ -1889,6 +1929,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_d680_dmb_streaming_ctrl,
 			.frontend_attach  = cxusb_d680_dmb_frontend_attach,
 			.tuner_attach     = cxusb_d680_dmb_tuner_attach,
@@ -1904,6 +1946,7 @@
 					}
 				}
 			},
+		}},
 		},
 	},
 
@@ -1940,6 +1983,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = cxusb_d680_dmb_streaming_ctrl,
 			.frontend_attach  = cxusb_mygica_d689_frontend_attach,
 			.tuner_attach     = cxusb_mygica_d689_tuner_attach,
@@ -1955,6 +2000,7 @@
 					}
 				}
 			},
+		}},
 		},
 	},
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dib0700_core.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dib0700_core.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dib0700_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dib0700_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,11 @@
 	struct dib0700_state *st = d->priv;
 	int ret;
 
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+		err("could not acquire lock");
+		return 0;
+	}
+
 	ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
 				  REQUEST_GET_VERSION,
 				  USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
@@ -46,6 +51,7 @@
 	if (fwtype != NULL)
 		*fwtype     = (st->buf[12] << 24) | (st->buf[13] << 16) |
 			(st->buf[14] << 8) | st->buf[15];
+	mutex_unlock(&d->usb_mutex);
 	return ret;
 }
 
@@ -108,7 +114,12 @@
 int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
 {
 	struct dib0700_state *st = d->priv;
-	s16 ret;
+	int ret;
+
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+		err("could not acquire lock");
+		return 0;
+	}
 
 	st->buf[0] = REQUEST_SET_GPIO;
 	st->buf[1] = gpio;
@@ -116,6 +127,7 @@
 
 	ret = dib0700_ctrl_wr(d, st->buf, 3);
 
+	mutex_unlock(&d->usb_mutex);
 	return ret;
 }
 
@@ -125,6 +137,11 @@
 	int ret;
 
 	if (st->fw_version >= 0x10201) {
+		if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+			err("could not acquire lock");
+			return 0;
+		}
+
 		st->buf[0] = REQUEST_SET_USB_XFER_LEN;
 		st->buf[1] = (nb_ts_packets >> 8) & 0xff;
 		st->buf[2] = nb_ts_packets & 0xff;
@@ -132,6 +149,7 @@
 		deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
 
 		ret = dib0700_ctrl_wr(d, st->buf, 3);
+		mutex_unlock(&d->usb_mutex);
 	} else {
 		deb_info("this firmware does not allow to change the USB xfer len\n");
 		ret = -EIO;
@@ -208,6 +226,10 @@
 
 		} else {
 			/* Write request */
+			if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+				err("could not acquire lock");
+				return 0;
+			}
 			st->buf[0] = REQUEST_NEW_I2C_WRITE;
 			st->buf[1] = msg[i].addr << 1;
 			st->buf[2] = (en_start << 7) | (en_stop << 6) |
@@ -227,6 +249,7 @@
 						 USB_TYPE_VENDOR | USB_DIR_OUT,
 						 0, 0, st->buf, msg[i].len + 4,
 						 USB_CTRL_GET_TIMEOUT);
+			mutex_unlock(&d->usb_mutex);
 			if (result < 0) {
 				deb_info("i2c write error (status = %d)\n", result);
 				break;
@@ -249,6 +272,10 @@
 
 	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
 		return -EAGAIN;
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+		err("could not acquire lock");
+		return 0;
+	}
 
 	for (i = 0; i < num; i++) {
 		/* fill in the address */
@@ -279,6 +306,7 @@
 				break;
 		}
 	}
+	mutex_unlock(&d->usb_mutex);
 	mutex_unlock(&d->i2c_mutex);
 
 	return i;
@@ -337,7 +365,12 @@
 	u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
 {
 	struct dib0700_state *st = d->priv;
-	s16 ret;
+	int ret;
+
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+		err("could not acquire lock");
+		return 0;
+	}
 
 	st->buf[0] = REQUEST_SET_CLOCK;
 	st->buf[1] = (en_pll << 7) | (pll_src << 6) |
@@ -352,6 +385,7 @@
 	st->buf[9] =  dsuScaler         & 0xff; /* LSB */
 
 	ret = dib0700_ctrl_wr(d, st->buf, 10);
+	mutex_unlock(&d->usb_mutex);
 
 	return ret;
 }
@@ -360,10 +394,16 @@
 {
 	struct dib0700_state *st = d->priv;
 	u16 divider;
+	int ret;
 
 	if (scl_kHz == 0)
 		return -EINVAL;
 
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+		err("could not acquire lock");
+		return 0;
+	}
+
 	st->buf[0] = REQUEST_SET_I2C_PARAM;
 	divider = (u16) (30000 / scl_kHz);
 	st->buf[1] = 0;
@@ -379,7 +419,11 @@
 	deb_info("setting I2C speed: %04x %04x %04x (%d kHz).",
 		(st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) |
 		st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz);
-	return dib0700_ctrl_wr(d, st->buf, 8);
+
+	ret = dib0700_ctrl_wr(d, st->buf, 8);
+	mutex_unlock(&d->usb_mutex);
+
+	return ret;
 }
 
 
@@ -484,13 +528,13 @@
 		for (adap_num = 0; adap_num < dib0700_devices[i].num_adapters;
 				adap_num++) {
 			if (fw_version >= 0x10201) {
-				dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
+				dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
 			} else {
 				/* for fw version older than 1.20.1,
 				 * the buffersize has to be n times 512 */
-				dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512;
-				if (dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize < 512)
-					dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 512;
+				dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512;
+				if (dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize < 512)
+					dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = 512;
 			}
 		}
 	}
@@ -515,6 +559,11 @@
 		}
 	}
 
+	if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) {
+		err("could not acquire lock");
+		return 0;
+	}
+
 	st->buf[0] = REQUEST_ENABLE_VIDEO;
 	/* this bit gives a kind of command,
 	 * rather than enabling something or not */
@@ -530,25 +579,28 @@
 	deb_info("modifying (%d) streaming state for %d\n", onoff, 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 ((adap->fe_adap[0].stream.props.endpoint != 2)
+			&& (adap->fe_adap[0].stream.props.endpoint != 3)) {
+		deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->fe_adap[0].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);
+			st->channel_state |=	1 << (adap->fe_adap[0].stream.props.endpoint-2);
 		else
-			st->channel_state |=	1 << (3-adap->stream.props.endpoint);
+			st->channel_state |=	1 << (3-adap->fe_adap[0].stream.props.endpoint);
 	}
 
 	st->buf[2] |= st->channel_state;
 
 	deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]);
 
-	return dib0700_ctrl_wr(adap->dev, st->buf, 4);
+	ret = dib0700_ctrl_wr(adap->dev, st->buf, 4);
+	mutex_unlock(&adap->dev->usb_mutex);
+
+	return ret;
 }
 
 int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
@@ -557,6 +609,11 @@
 	struct dib0700_state *st = d->priv;
 	int new_proto, ret;
 
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
+		err("could not acquire lock");
+		return 0;
+	}
+
 	st->buf[0] = REQUEST_SET_RC;
 	st->buf[1] = 0;
 	st->buf[2] = 0;
@@ -567,23 +624,29 @@
 	else if (rc_type == RC_TYPE_NEC)
 		new_proto = 0;
 	else if (rc_type == RC_TYPE_RC6) {
-		if (st->fw_version < 0x10200)
-			return -EINVAL;
+		if (st->fw_version < 0x10200) {
+			ret = -EINVAL;
+			goto out;
+		}
 
 		new_proto = 2;
-	} else
-		return -EINVAL;
+	} else {
+		ret = -EINVAL;
+		goto out;
+	}
 
 	st->buf[1] = new_proto;
 
 	ret = dib0700_ctrl_wr(d, st->buf, 3);
 	if (ret < 0) {
 		err("ir protocol setup failed");
-		return ret;
+		goto out;
 	}
 
 	d->props.rc.core.protocol = rc_type;
 
+out:
+	mutex_unlock(&d->usb_mutex);
 	return ret;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dib0700_devices.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dib0700_devices.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dib0700_devices.c	2012-03-19 21:32:35.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dib0700_devices.c	2012-03-19 21:34:47.000000000 -0400
@@ -101,7 +101,7 @@
 		}
 	}
 	st->mt2060_if1[adap->id] = 1220;
-	return (adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap,
+	return (adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap,
 		(10 + adap->id) << 1, &bristol_dib3000mc_config[adap->id])) == NULL ? -ENODEV : 0;
 }
 
@@ -118,15 +118,16 @@
 static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap;
-	struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
+	struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe_adap[0].fe, 1);
 	s8 a;
 	int if1=1220;
 	if (adap->dev->udev->descriptor.idVendor  == cpu_to_le16(USB_VID_HAUPPAUGE) &&
 		adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_500_2)) {
 		if (!eeprom_read(prim_i2c,0x59 + adap->id,&a)) if1=1220+a;
 	}
-	return dvb_attach(mt2060_attach,adap->fe, tun_i2c,&bristol_mt2060_config[adap->id],
-		if1) == NULL ? -ENODEV : 0;
+	return dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c,
+			  &bristol_mt2060_config[adap->id], if1) == NULL ?
+			  -ENODEV : 0;
 }
 
 /* STK7700D: Pinnacle/Terratec/Hauppauge Dual DVB-T Diversity */
@@ -279,10 +280,12 @@
 		}
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
-				&stk7700d_dib7000p_mt2266_config[adap->id]);
+	adap->fe_adap[0].fe =
+		dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+			   0x80 + (adap->id << 1),
+			   &stk7700d_dib7000p_mt2266_config[adap->id]);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
@@ -306,17 +309,19 @@
 		}
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
-				&stk7700d_dib7000p_mt2266_config[adap->id]);
+	adap->fe_adap[0].fe =
+		dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+			   0x80 + (adap->id << 1),
+			   &stk7700d_dib7000p_mt2266_config[adap->id]);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct i2c_adapter *tun_i2c;
-	tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
-	return dvb_attach(mt2266_attach, adap->fe, tun_i2c,
+	tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+	return dvb_attach(mt2266_attach, adap->fe_adap[0].fe, tun_i2c,
 		&stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;
 }
 
@@ -396,8 +401,8 @@
 	switch (command) {
 	case XC2028_TUNER_RESET:
 		/* Send the tuner in then out of reset */
-		dib7000p_set_gpio(adap->fe, 8, 0, 0); msleep(10);
-		dib7000p_set_gpio(adap->fe, 8, 0, 1);
+		dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0); msleep(10);
+		dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
 		break;
 	case XC2028_RESET_CLK:
 		break;
@@ -447,25 +452,25 @@
 		return -ENODEV;
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
 		&stk7700ph_dib7700_xc3028_config);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct i2c_adapter *tun_i2c;
 
-	tun_i2c = dib7000p_get_i2c_master(adap->fe,
+	tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
 		DIBX000_I2C_INTERFACE_TUNER, 1);
 
 	stk7700ph_xc3028_config.i2c_adap = tun_i2c;
 
 	/* FIXME: generalize & move to common area */
-	adap->fe->callback = stk7700ph_xc3028_callback;
+	adap->fe_adap[0].fe->callback = stk7700ph_xc3028_callback;
 
-	return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config)
+	return dvb_attach(xc2028_attach, adap->fe_adap[0].fe, &stk7700ph_xc3028_config)
 		== NULL ? -ENODEV : 0;
 }
 
@@ -685,12 +690,12 @@
 	st->mt2060_if1[0] = 1220;
 
 	if (dib7000pc_detection(&adap->dev->i2c_adap)) {
-		adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
+		adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
 		st->is_dib7000pc = 1;
 	} else
-		adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
+		adap->fe_adap[0].fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static struct mt2060_config stk7700p_mt2060_config = {
@@ -709,11 +714,11 @@
 		if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a;
 	}
 	if (st->is_dib7000pc)
-		tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+		tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
 	else
-		tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+		tun_i2c = dib7000m_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
 
-	return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config,
+	return dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c, &stk7700p_mt2060_config,
 		if1) == NULL ? -ENODEV : 0;
 }
 
@@ -843,33 +848,33 @@
 static int dib7770p_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	 struct dib0700_adapter_state *st = adap->priv;
-	 struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe,
+	 struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
 			 DIBX000_I2C_INTERFACE_TUNER, 1);
 
-	 if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
-				 &dib7770p_dib0070_config) == NULL)
+	 if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
+			&dib7770p_dib0070_config) == NULL)
 		 return -ENODEV;
 
-	 st->set_param_save = adap->fe->ops.tuner_ops.set_params;
-	 adap->fe->ops.tuner_ops.set_params = dib7770_set_param_override;
+	 st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	 adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7770_set_param_override;
 	 return 0;
 }
 
 static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+	struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
 
 	if (adap->id == 0) {
-		if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL)
+		if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL)
 			return -ENODEV;
 	} else {
-		if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[1]) == NULL)
+		if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, &dib7070p_dib0070_config[1]) == NULL)
 			return -ENODEV;
 	}
 
-	st->set_param_save = adap->fe->ops.tuner_ops.set_params;
-	adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7070_set_param_override;
 	return 0;
 }
 
@@ -878,26 +883,26 @@
 {
 	struct dib0700_state *st = adapter->dev->priv;
 	if (st->is_dib7000pc)
-		return dib7000p_pid_filter(adapter->fe, index, pid, onoff);
-	return dib7000m_pid_filter(adapter->fe, index, pid, onoff);
+		return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
+	return dib7000m_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
 }
 
 static int stk7700p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
 {
 	struct dib0700_state *st = adapter->dev->priv;
 	if (st->is_dib7000pc)
-		return dib7000p_pid_filter_ctrl(adapter->fe, onoff);
-	return dib7000m_pid_filter_ctrl(adapter->fe, onoff);
+		return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
+	return dib7000m_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
 }
 
 static int stk70x0p_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
 {
-    return dib7000p_pid_filter(adapter->fe, index, pid, onoff);
+	return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
 }
 
 static int stk70x0p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
 {
-    return dib7000p_pid_filter_ctrl(adapter->fe, onoff);
+	return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
 }
 
 static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
@@ -955,9 +960,9 @@
 		return -ENODEV;
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
 		&dib7070p_dib7000p_config);
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 /* STK7770P */
@@ -1007,9 +1012,9 @@
 		return -ENODEV;
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
 		&dib7770p_dib7000p_config);
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 /* DIB807x generic */
@@ -1225,34 +1230,34 @@
 static int dib807x_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,
+	struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe,
 			DIBX000_I2C_INTERFACE_TUNER, 1);
 
 	if (adap->id == 0) {
-		if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
+		if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
 				&dib807x_dib0070_config[0]) == NULL)
 			return -ENODEV;
 	} else {
-		if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
+		if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
 				&dib807x_dib0070_config[1]) == NULL)
 			return -ENODEV;
 	}
 
-	st->set_param_save = adap->fe->ops.tuner_ops.set_params;
-	adap->fe->ops.tuner_ops.set_params = dib807x_set_param_override;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib807x_set_param_override;
 	return 0;
 }
 
 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_adap[0].fe, index, pid, onoff);
 }
 
 static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter,
 		int onoff)
 {
-	return dib8000_pid_filter_ctrl(adapter->fe, onoff);
+	return dib8000_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
 }
 
 /* STK807x */
@@ -1276,10 +1281,10 @@
 	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
 				0x80);
 
-	adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
 			      &dib807x_dib8000_config[0]);
 
-	return adap->fe == NULL ?  -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
 }
 
 /* STK807xPVR */
@@ -1305,10 +1310,10 @@
 	/* initialize IC 0 */
 	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80);
 
-	adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
+	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
 			      &dib807x_dib8000_config[0]);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
@@ -1316,10 +1321,10 @@
 	/* initialize IC 1 */
 	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82);
 
-	adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82,
+	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82,
 			      &dib807x_dib8000_config[1]);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 /* STK8096GP */
@@ -1546,13 +1551,13 @@
 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 i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
 
-	if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL)
+	if (dvb_attach(dib0090_register, adap->fe_adap[0].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;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096_set_param_override;
 	return 0;
 }
 
@@ -1575,30 +1580,30 @@
 
 	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80);
 
-	adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
+	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
 
-	return adap->fe == NULL ?  -ENODEV : 0;
+	return adap->fe_adap[0].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);
+	struct dvb_frontend *fe_slave  = dib8000_get_slave_frontend(adap->fe_adap[0].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->dvb = adap->fe_adap[0].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)
+	tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+	if (dvb_attach(dib0090_register, adap->fe_adap[0].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;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096_set_param_override;
 
 	return 0;
 }
@@ -1626,12 +1631,12 @@
 
 	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)
+	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
+	if (adap->fe_adap[0].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);
+	dib8000_set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
 
 	return fe_slave == NULL ?  -ENODEV : 0;
 }
@@ -1639,12 +1644,12 @@
 /* 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);
+	return dib9000_fw_pid_filter(adapter->fe_adap[0].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);
+	return dib9000_fw_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
 }
 
 static int dib90x0_tuner_reset(struct dvb_frontend *fe, int onoff)
@@ -1856,15 +1861,15 @@
 	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);
+	adap->fe_adap[0].fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &stk9090m_config);
 
-	return adap->fe == NULL ?  -ENODEV : 0;
+	return adap->fe_adap[0].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);
+	struct i2c_adapter *i2c = dib9000_get_tuner_interface(adap->fe_adap[0].fe);
 	u16 data_dib190[10] = {
 		1, 0x1374,
 		2, 0x01a2,
@@ -1873,13 +1878,13 @@
 		8, 0x0486,
 	};
 
-	if (dvb_attach(dib0090_fw_register, adap->fe, i2c, &dib9090_dib0090_config) == NULL)
+	if (dvb_attach(dib0090_fw_register, adap->fe_adap[0].fe, i2c, &dib9090_dib0090_config) == NULL)
 		return -ENODEV;
-	i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
+	i2c = dib9000_get_i2c_master(adap->fe_adap[0].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)
+	if (dib9000_firmware_post_pll_init(adap->fe_adap[0].fe) < 0)
 		return -ENODEV;
 	release_firmware(state->frontend_firmware);
 	return 0;
@@ -1925,16 +1930,16 @@
 	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]);
+	adap->fe_adap[0].fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &nim9090md_config[0]);
 
-	if (adap->fe == NULL)
+	if (adap->fe_adap[0].fe == NULL)
 		return -ENODEV;
 
-	i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_3_4, 0);
+	i2c = dib9000_get_i2c_master(adap->fe_adap[0].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);
+	dib9000_set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
 
 	return fe_slave == NULL ?  -ENODEV : 0;
 }
@@ -1951,26 +1956,26 @@
 		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)
+	i2c = dib9000_get_tuner_interface(adap->fe_adap[0].fe);
+	if (dvb_attach(dib0090_fw_register, adap->fe_adap[0].fe, i2c, &nim9090md_dib0090_config[0]) == NULL)
 		return -ENODEV;
-	i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
+	i2c = dib9000_get_i2c_master(adap->fe_adap[0].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)
+	if (dib9000_firmware_post_pll_init(adap->fe_adap[0].fe) < 0)
 		return -ENODEV;
 
-	fe_slave = dib9000_get_slave_frontend(adap->fe, 1);
+	fe_slave = dib9000_get_slave_frontend(adap->fe_adap[0].fe, 1);
 	if (fe_slave != NULL) {
-		i2c = dib9000_get_component_bus_interface(adap->fe);
+		i2c = dib9000_get_component_bus_interface(adap->fe_adap[0].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);
+		fe_slave->dvb = adap->fe_adap[0].fe->dvb;
+		dib9000_fw_set_component_bus_speed(adap->fe_adap[0].fe, 2000);
 		if (dib9000_firmware_post_pll_init(fe_slave) < 0)
 			return -ENODEV;
 	}
@@ -2393,23 +2398,23 @@
 		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);
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config);
 
-	return adap->fe == NULL ?  -ENODEV : 0;
+	return adap->fe_adap[0].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);
+	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
 
-	if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &nim7090_dib0090_config) == NULL)
+	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &nim7090_dib0090_config) == NULL)
 		return -ENODEV;
 
-	dib7000p_set_gpio(adap->fe, 8, 0, 1);
+	dib7000p_set_gpio(adap->fe_adap[0].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;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
 	return 0;
 }
 
@@ -2439,11 +2444,11 @@
 	}
 
 	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)
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
+	if (adap->fe_adap[0].fe == NULL)
 		return -ENODEV;
 
-	dib7090_slave_reset(adap->fe);
+	dib7090_slave_reset(adap->fe_adap[0].fe);
 
 	return 0;
 }
@@ -2452,50 +2457,50 @@
 {
 	struct i2c_adapter *i2c;
 
-	if (adap->dev->adapter[0].fe == NULL) {
+	if (adap->dev->adapter[0].fe_adap[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);
+	i2c = dib7000p_get_i2c_master(adap->dev->adapter[0].fe_adap[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]);
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, i2c, 0x92, &tfe7090pvr_dib7000p_config[1]);
 	dib0700_set_i2c_speed(adap->dev, 200);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].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);
+	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
 
-	if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL)
+	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL)
 		return -ENODEV;
 
-	dib7000p_set_gpio(adap->fe, 8, 0, 1);
+	dib7000p_set_gpio(adap->fe_adap[0].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;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].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);
+	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
 
-	if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL)
+	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL)
 		return -ENODEV;
 
-	dib7000p_set_gpio(adap->fe, 8, 0, 1);
+	dib7000p_set_gpio(adap->fe_adap[0].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;
+	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
 	return 0;
 }
 
@@ -2555,14 +2560,14 @@
 		return -ENODEV;
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
-	return adap->fe == NULL ? -ENODEV : 0;
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
 {
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
-	return adap->fe == NULL ? -ENODEV : 0;
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 /* S5H1411 */
@@ -2617,9 +2622,9 @@
 	dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1);
 
 	/* GPIOs are initialized, do the attach */
-	adap->fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config,
+	adap->fe_adap[0].fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config,
 			      &adap->dev->i2c_adap);
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static int dib0700_xc5000_tuner_callback(void *priv, int component,
@@ -2649,9 +2654,9 @@
 static int xc5000_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	/* FIXME: generalize & move to common area */
-	adap->fe->callback = dib0700_xc5000_tuner_callback;
+	adap->fe_adap[0].fe->callback = dib0700_xc5000_tuner_callback;
 
-	return dvb_attach(xc5000_attach, adap->fe, &adap->dev->i2c_adap,
+	return dvb_attach(xc5000_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 			  &s5h1411_xc5000_tunerconfig)
 		== NULL ? -ENODEV : 0;
 }
@@ -2663,9 +2668,9 @@
 
 	if (command == XC4000_TUNER_RESET) {
 		/* Reset the tuner */
-		dib7000p_set_gpio(adap->fe, 8, 0, 0);
+		dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0);
 		msleep(10);
-		dib7000p_set_gpio(adap->fe, 8, 0, 1);
+		dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
 	} else {
 		err("xc4000: unknown tuner callback command: %d\n", command);
 		return -EINVAL;
@@ -2771,11 +2776,11 @@
 		return -ENODEV;
 	}
 
-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x12,
+	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x12,
 			      &pctv_340e_config);
 	st->is_dib7000pc = 1;
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static struct xc4000_config dib7000p_xc4000_tunerconfig = {
@@ -2791,7 +2796,7 @@
 	struct i2c_adapter *tun_i2c;
 
 	/* The xc4000 is not on the main i2c bus */
-	tun_i2c = dib7000p_get_i2c_master(adap->fe,
+	tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
 					  DIBX000_I2C_INTERFACE_TUNER, 1);
 	if (tun_i2c == NULL) {
 		printk(KERN_ERR "Could not reach tuner i2c bus\n");
@@ -2799,9 +2804,9 @@
 	}
 
 	/* Setup the reset callback */
-	adap->fe->callback = dib0700_xc4000_tuner_callback;
+	adap->fe_adap[0].fe->callback = dib0700_xc4000_tuner_callback;
 
-	return dvb_attach(xc4000_attach, adap->fe, tun_i2c,
+	return dvb_attach(xc4000_attach, adap->fe_adap[0].fe, tun_i2c,
 			  &dib7000p_xc4000_tunerconfig)
 		== NULL ? -ENODEV : 0;
 }
@@ -2857,16 +2862,16 @@
 	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
 	msleep(30);
 
-	adap->fe = dvb_attach(lgdt3305_attach,
+	adap->fe_adap[0].fe = dvb_attach(lgdt3305_attach,
 			      &hcw_lgdt3305_config,
 			      &adap->dev->i2c_adap);
 
-	return adap->fe == NULL ? -ENODEV : 0;
+	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 static int mxl5007t_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	return dvb_attach(mxl5007t_attach, adap->fe,
+	return dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe,
 			  &adap->dev->i2c_adap, 0x60,
 			  &hcw_mxl5007t_config) == NULL ? -ENODEV : 0;
 }
@@ -2989,6 +2994,8 @@
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
 				.pid_filter       = stk7700p_pid_filter,
@@ -2997,6 +3004,7 @@
 				.tuner_attach     = stk7700p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+			}},
 			},
 		},
 
@@ -3050,15 +3058,21 @@
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.frontend_attach  = bristol_frontend_attach,
 				.tuner_attach     = bristol_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+			}},
 			}, {
+			.num_frontends = 1,
+			.fe = {{
 				.frontend_attach  = bristol_frontend_attach,
 				.tuner_attach     = bristol_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+			}},
 			}
 		},
 
@@ -3084,6 +3098,8 @@
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.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,
@@ -3092,7 +3108,10 @@
 				.tuner_attach     = stk7700d_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+			}},
 			}, {
+			.num_frontends = 1,
+			.fe = {{
 				.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,
@@ -3101,6 +3120,7 @@
 				.tuner_attach     = stk7700d_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+			}},
 			}
 		},
 
@@ -3143,6 +3163,8 @@
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.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,
@@ -3151,6 +3173,7 @@
 				.tuner_attach     = stk7700d_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+			}},
 			},
 		},
 
@@ -3185,6 +3208,8 @@
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.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,
@@ -3193,7 +3218,7 @@
 				.tuner_attach     = dib7070p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv     = sizeof(struct dib0700_adapter_state),
 			},
 		},
@@ -3261,6 +3286,8 @@
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.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,
@@ -3269,7 +3296,7 @@
 				.tuner_attach     = dib7070p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv     = sizeof(struct dib0700_adapter_state),
 			},
 		},
@@ -3305,6 +3332,8 @@
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.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,
@@ -3313,9 +3342,11 @@
 				.tuner_attach     = dib7070p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv     = sizeof(struct dib0700_adapter_state),
 			}, {
+			.num_frontends = 1,
+			.fe = {{
 				.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,
@@ -3324,7 +3355,7 @@
 				.tuner_attach     = dib7070p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-
+			}},
 				.size_of_priv     = sizeof(struct dib0700_adapter_state),
 			}
 		},
@@ -3373,6 +3404,8 @@
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.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,
@@ -3381,9 +3414,11 @@
 				.tuner_attach     = dib7070p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv     = sizeof(struct dib0700_adapter_state),
 			}, {
+			.num_frontends = 1,
+			.fe = {{
 				.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,
@@ -3392,7 +3427,7 @@
 				.tuner_attach     = dib7070p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-
+			}},
 				.size_of_priv     = sizeof(struct dib0700_adapter_state),
 			}
 		},
@@ -3420,6 +3455,8 @@
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.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,
@@ -3428,7 +3465,7 @@
 				.tuner_attach     = stk7700ph_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv = sizeof(struct
 						dib0700_adapter_state),
 			},
@@ -3488,11 +3525,13 @@
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.frontend_attach  = s5h1411_frontend_attach,
 				.tuner_attach     = xc5000_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv = sizeof(struct
 						dib0700_adapter_state),
 			},
@@ -3524,11 +3563,13 @@
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.frontend_attach  = lgdt3305_frontend_attach,
 				.tuner_attach     = mxl5007t_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv = sizeof(struct
 						dib0700_adapter_state),
 			},
@@ -3550,6 +3591,8 @@
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.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,
@@ -3558,7 +3601,7 @@
 				.tuner_attach     = dib7770p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3600,6 +3643,8 @@
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.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,
@@ -3608,7 +3653,7 @@
 				.tuner_attach     = dib807x_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3644,6 +3689,8 @@
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.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,
@@ -3652,11 +3699,13 @@
 				.tuner_attach     = dib807x_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.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,
@@ -3665,7 +3714,7 @@
 				.tuner_attach     = dib807x_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3693,6 +3742,8 @@
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
 					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
@@ -3702,7 +3753,7 @@
 				.tuner_attach     = dib809x_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3730,6 +3781,8 @@
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
 					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
@@ -3739,7 +3792,7 @@
 				.tuner_attach     = dib9090_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3767,6 +3820,8 @@
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
 					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
@@ -3776,7 +3831,7 @@
 				.tuner_attach     = nim8096md_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3804,6 +3859,8 @@
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
 					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
@@ -3813,7 +3870,7 @@
 				.tuner_attach     = nim9090md_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3841,6 +3898,8 @@
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
 					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
@@ -3850,7 +3909,7 @@
 				.tuner_attach     = nim7090_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3878,6 +3937,8 @@
 		.num_adapters = 2,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
 					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
@@ -3887,11 +3948,13 @@
 				.tuner_attach     = tfe7090pvr_tuner0_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
 					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
@@ -3901,7 +3964,7 @@
 				.tuner_attach     = tfe7090pvr_tuner1_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv =
 					sizeof(struct dib0700_adapter_state),
 			},
@@ -3929,11 +3992,13 @@
 		.num_adapters = 1,
 		.adapter = {
 			{
+			.num_frontends = 1,
+			.fe = {{
 				.frontend_attach  = pctv340e_frontend_attach,
 				.tuner_attach     = xc4000_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
+			}},
 				.size_of_priv = sizeof(struct
 						dib0700_adapter_state),
 			},
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dibusb-common.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dibusb-common.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dibusb-common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dibusb-common.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,7 @@
 	if (adap->priv != NULL) {
 		struct dibusb_state *st = adap->priv;
 		if (st->ops.fifo_ctrl != NULL)
-			if (st->ops.fifo_ctrl(adap->fe,onoff)) {
+			if (st->ops.fifo_ctrl(adap->fe_adap[0].fe, onoff)) {
 				err("error while controlling the fifo of the demod.");
 				return -ENODEV;
 			}
@@ -37,7 +37,8 @@
 	if (adap->priv != NULL) {
 		struct dibusb_state *st = adap->priv;
 		if (st->ops.pid_ctrl != NULL)
-			st->ops.pid_ctrl(adap->fe,index,pid,onoff);
+			st->ops.pid_ctrl(adap->fe_adap[0].fe,
+					 index, pid, onoff);
 	}
 	return 0;
 }
@@ -48,7 +49,7 @@
 	if (adap->priv != NULL) {
 		struct dibusb_state *st = adap->priv;
 		if (st->ops.pid_parse != NULL)
-			if (st->ops.pid_parse(adap->fe,onoff) < 0)
+			if (st->ops.pid_parse(adap->fe_adap[0].fe, onoff) < 0)
 				err("could not handle pid_parser");
 	}
 	return 0;
@@ -254,8 +255,16 @@
 		msleep(1000);
 	}
 
-	if ((adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000P_I2C_ADDRESS,  &mod3000p_dib3000p_config)) != NULL ||
-		(adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000MC_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL) {
+	adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach,
+					 &adap->dev->i2c_adap,
+					 DEFAULT_DIB3000P_I2C_ADDRESS,
+					 &mod3000p_dib3000p_config);
+	if ((adap->fe_adap[0].fe) == NULL)
+		adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach,
+						 &adap->dev->i2c_adap,
+						 DEFAULT_DIB3000MC_I2C_ADDRESS,
+						 &mod3000p_dib3000p_config);
+	if ((adap->fe_adap[0].fe) != NULL) {
 		if (adap->priv != NULL) {
 			struct dibusb_state *st = adap->priv;
 			st->ops.pid_parse = dib3000mc_pid_parse;
@@ -309,15 +318,15 @@
 		}
 	}
 
-	tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
-	if (dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk3000p_mt2060_config, if1) == NULL) {
+	tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe_adap[0].fe, 1);
+	if (dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c, &stk3000p_mt2060_config, if1) == NULL) {
 		/* not found - use panasonic pll parameters */
-		if (dvb_attach(dvb_pll_attach, adap->fe, 0x60, tun_i2c, DVB_PLL_ENV57H1XD5) == NULL)
+		if (dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, tun_i2c, DVB_PLL_ENV57H1XD5) == NULL)
 			return -ENOMEM;
 	} else {
 		st->mt2060_present = 1;
 		/* set the correct parameters for the dib3000p */
-		dib3000mc_set_config(adap->fe, &stk3000p_dib3000p_config);
+		dib3000mc_set_config(adap->fe_adap[0].fe, &stk3000p_dib3000p_config);
 	}
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dibusb-mb.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dibusb-mb.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dibusb-mb.c	2012-03-19 21:32:42.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dibusb-mb.c	2012-03-19 21:34:55.000000000 -0400
@@ -31,11 +31,12 @@
 
 	demod_cfg.demod_address = 0x8;
 
-	if ((adap->fe = dvb_attach(dib3000mb_attach, &demod_cfg,
-				   &adap->dev->i2c_adap, &st->ops)) == NULL)
+	adap->fe_adap[0].fe = dvb_attach(dib3000mb_attach, &demod_cfg,
+					 &adap->dev->i2c_adap, &st->ops);
+	if ((adap->fe_adap[0].fe) == NULL)
 		return -ENODEV;
 
-	adap->fe->ops.i2c_gate_ctrl = dib3000mb_i2c_gate_ctrl;
+	adap->fe_adap[0].fe->ops.i2c_gate_ctrl = dib3000mb_i2c_gate_ctrl;
 
 	return 0;
 }
@@ -46,7 +47,7 @@
 
 	st->tuner_addr = 0x61;
 
-	dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap,
+	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, &adap->dev->i2c_adap,
 		   DVB_PLL_TUA6010XS);
 	return 0;
 }
@@ -57,7 +58,7 @@
 
 	st->tuner_addr = 0x60;
 
-	dvb_attach(dvb_pll_attach, adap->fe, 0x60, &adap->dev->i2c_adap,
+	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap,
 		   DVB_PLL_TDA665X);
 	return 0;
 }
@@ -78,16 +79,16 @@
 	/* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */
 	msg[0].addr = msg[1].addr = st->tuner_addr = 0x60;
 
-	if (adap->fe->ops.i2c_gate_ctrl)
-		adap->fe->ops.i2c_gate_ctrl(adap->fe,1);
+	if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
+		adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1);
 
 	if (i2c_transfer(&adap->dev->i2c_adap, msg, 2) != 2) {
 		err("tuner i2c write failed.");
 		ret = -EREMOTEIO;
 	}
 
-	if (adap->fe->ops.i2c_gate_ctrl)
-		adap->fe->ops.i2c_gate_ctrl(adap->fe,0);
+	if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
+		adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0);
 
 	if (b2[0] == 0xfe) {
 		info("This device has the Thomson Cable onboard. Which is default.");
@@ -185,6 +186,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 			.pid_filter_count = 16,
 
@@ -205,6 +208,7 @@
 					}
 				}
 			},
+		}},
 			.size_of_priv     = sizeof(struct dibusb_state),
 		}
 	},
@@ -272,6 +276,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER,
 			.pid_filter_count = 16,
 
@@ -292,6 +298,7 @@
 					}
 				}
 			},
+		}},
 			.size_of_priv     = sizeof(struct dibusb_state),
 		},
 	},
@@ -338,6 +345,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 			.pid_filter_count = 16,
 
@@ -358,6 +367,7 @@
 					}
 				}
 			},
+		}},
 			.size_of_priv     = sizeof(struct dibusb_state),
 		}
 	},
@@ -398,6 +408,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 			.pid_filter_count = 16,
 
@@ -417,6 +429,7 @@
 					}
 				}
 			},
+		}},
 			.size_of_priv     = sizeof(struct dibusb_state),
 		}
 	},
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dibusb-mc.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dibusb-mc.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dibusb-mc.c	2012-03-19 21:32:49.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dibusb-mc.c	2012-03-19 21:34:59.000000000 -0400
@@ -57,6 +57,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 			.pid_filter_count = 32,
 			.streaming_ctrl   = dibusb2_0_streaming_ctrl,
@@ -76,6 +78,7 @@
 					}
 				}
 			},
+		}},
 			.size_of_priv     = sizeof(struct dibusb_state),
 		}
 	},
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/digitv.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/digitv.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/digitv.c	2012-03-19 21:32:57.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/digitv.c	2012-03-19 21:35:10.000000000 -0400
@@ -137,11 +137,16 @@
 {
 	struct digitv_state *st = adap->dev->priv;
 
-	if ((adap->fe = dvb_attach(mt352_attach, &digitv_mt352_config, &adap->dev->i2c_adap)) != NULL) {
+	adap->fe_adap[0].fe = dvb_attach(mt352_attach, &digitv_mt352_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL) {
 		st->is_nxt6000 = 0;
 		return 0;
 	}
-	if ((adap->fe = dvb_attach(nxt6000_attach, &digitv_nxt6000_config, &adap->dev->i2c_adap)) != NULL) {
+	adap->fe_adap[0].fe = dvb_attach(nxt6000_attach,
+					 &digitv_nxt6000_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) != NULL) {
 		st->is_nxt6000 = 1;
 		return 0;
 	}
@@ -152,11 +157,11 @@
 {
 	struct digitv_state *st = adap->dev->priv;
 
-	if (!dvb_attach(dvb_pll_attach, adap->fe, 0x60, NULL, DVB_PLL_TDED4))
+	if (!dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, NULL, DVB_PLL_TDED4))
 		return -ENODEV;
 
 	if (st->is_nxt6000)
-		adap->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
+		adap->fe_adap[0].fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
 
 	return 0;
 }
@@ -292,6 +297,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach  = digitv_frontend_attach,
 			.tuner_attach     = digitv_tuner_attach,
 
@@ -306,6 +313,7 @@
 					}
 				}
 			},
+		}},
 		}
 	},
 	.identify_state   = digitv_identify_state,
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dtt200u.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dtt200u.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dtt200u.c	2012-03-19 21:33:00.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dtt200u.c	2012-03-19 21:35:19.000000000 -0400
@@ -90,7 +90,7 @@
 
 static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	adap->fe = dtt200u_fe_attach(adap->dev);
+	adap->fe_adap[0].fe = dtt200u_fe_attach(adap->dev);
 	return 0;
 }
 
@@ -140,6 +140,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
 			.pid_filter_count = 15,
 
@@ -157,6 +159,7 @@
 			}
 		}
 	},
+		}},
 		}
 	},
 	.power_ctrl      = dtt200u_power_ctrl,
@@ -187,6 +190,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
 			.pid_filter_count = 15,
 
@@ -204,6 +209,7 @@
 			}
 		}
 	},
+		}},
 		}
 	},
 	.power_ctrl      = dtt200u_power_ctrl,
@@ -234,6 +240,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
 			.pid_filter_count = 15,
 
@@ -251,6 +259,7 @@
 			}
 		}
 	},
+		}},
 		}
 	},
 	.power_ctrl      = dtt200u_power_ctrl,
@@ -281,6 +290,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
 			.pid_filter_count = 15,
 
@@ -298,6 +309,7 @@
 					}
 				}
 			},
+		}},
 		}
 	},
 	.power_ctrl      = dtt200u_power_ctrl,
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dtv5100.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dtv5100.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dtv5100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dtv5100.c	2012-01-04 18:55:44.000000000 -0500
@@ -115,13 +115,13 @@
 
 static int dtv5100_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	adap->fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config,
+	adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config,
 			      &adap->dev->i2c_adap);
-	if (adap->fe == NULL)
+	if (adap->fe_adap[0].fe == NULL)
 		return -EIO;
 
 	/* disable i2c gate, or it won't work... is this safe? */
-	adap->fe->ops.i2c_gate_ctrl = NULL;
+	adap->fe_adap[0].fe->ops.i2c_gate_ctrl = NULL;
 
 	return 0;
 }
@@ -133,7 +133,7 @@
 static int dtv5100_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	return dvb_attach(qt1010_attach,
-			  adap->fe, &adap->dev->i2c_adap,
+			  adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 			  &dtv5100_qt1010_config) == NULL ? -ENODEV : 0;
 }
 
@@ -180,6 +180,8 @@
 
 	.num_adapters = 1,
 	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
 		.frontend_attach = dtv5100_frontend_attach,
 		.tuner_attach    = dtv5100_tuner_attach,
 
@@ -193,6 +195,7 @@
 				}
 			}
 		},
+		}},
 	} },
 
 	.i2c_algo = &dtv5100_i2c_algo,
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,15 +17,20 @@
 	if (adap == NULL)
 		return -ENODEV;
 
+	if ((adap->active_fe < 0) ||
+	    (adap->active_fe >= adap->num_frontends_initialized)) {
+		return -EINVAL;
+	}
+
 	newfeedcount = adap->feedcount + (onoff ? 1 : -1);
 
 	/* stop feed before setting a new pid if there will be no pid anymore */
 	if (newfeedcount == 0) {
 		deb_ts("stop feeding\n");
-		usb_urb_kill(&adap->stream);
+		usb_urb_kill(&adap->fe_adap[adap->active_fe].stream);
 
-		if (adap->props.streaming_ctrl != NULL) {
-			ret = adap->props.streaming_ctrl(adap, 0);
+		if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) {
+			ret = adap->props.fe[adap->active_fe].streaming_ctrl(adap, 0);
 			if (ret < 0) {
 				err("error while stopping stream.");
 				return ret;
@@ -36,36 +41,37 @@
 	adap->feedcount = newfeedcount;
 
 	/* activate the pid on the device specific pid_filter */
-	deb_ts("setting pid (%s): %5d %04x at index %d '%s'\n",adap->pid_filtering ?
-		"yes" : "no", dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ?
-		"on" : "off");
-	if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER &&
-		adap->pid_filtering &&
-		adap->props.pid_filter != NULL)
-		adap->props.pid_filter(adap, dvbdmxfeed->index, dvbdmxfeed->pid,onoff);
+	deb_ts("setting pid (%s): %5d %04x at index %d '%s'\n",
+		adap->fe_adap[adap->active_fe].pid_filtering ?
+		"yes" : "no", dvbdmxfeed->pid, dvbdmxfeed->pid,
+		dvbdmxfeed->index, onoff ? "on" : "off");
+	if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
+		adap->fe_adap[adap->active_fe].pid_filtering &&
+		adap->props.fe[adap->active_fe].pid_filter != NULL)
+		adap->props.fe[adap->active_fe].pid_filter(adap, dvbdmxfeed->index, dvbdmxfeed->pid, onoff);
 
 	/* start the feed if this was the first feed and there is still a feed
 	 * for reception.
 	 */
 	if (adap->feedcount == onoff && adap->feedcount > 0) {
 		deb_ts("submitting all URBs\n");
-		usb_urb_submit(&adap->stream);
+		usb_urb_submit(&adap->fe_adap[adap->active_fe].stream);
 
 		deb_ts("controlling pid parser\n");
-		if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER &&
-			adap->props.caps &
+		if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
+			adap->props.fe[adap->active_fe].caps &
 			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
-			adap->props.pid_filter_ctrl != NULL) {
-			ret = adap->props.pid_filter_ctrl(adap,
-				adap->pid_filtering);
+			adap->props.fe[adap->active_fe].pid_filter_ctrl != NULL) {
+			ret = adap->props.fe[adap->active_fe].pid_filter_ctrl(adap,
+				adap->fe_adap[adap->active_fe].pid_filtering);
 			if (ret < 0) {
 				err("could not handle pid_parser");
 				return ret;
 			}
 		}
 		deb_ts("start feeding\n");
-		if (adap->props.streaming_ctrl != NULL) {
-			ret = adap->props.streaming_ctrl(adap, 1);
+		if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) {
+			ret = adap->props.fe[adap->active_fe].streaming_ctrl(adap, 1);
 			if (ret < 0) {
 				err("error while enabling fifo.");
 				return ret;
@@ -90,6 +96,7 @@
 
 int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
 {
+	int i;
 	int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
 				       adap->dev->owner, &adap->dev->udev->dev,
 				       adapter_nums);
@@ -112,7 +119,12 @@
 	adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
 	adap->demux.priv             = adap;
 
-	adap->demux.feednum          = adap->demux.filternum = adap->max_feed_count;
+	adap->demux.filternum        = 0;
+	for (i = 0; i < adap->props.num_frontends; i++) {
+		if (adap->demux.filternum < adap->fe_adap[i].max_feed_count)
+			adap->demux.filternum = adap->fe_adap[i].max_feed_count;
+	}
+	adap->demux.feednum          = adap->demux.filternum;
 	adap->demux.start_feed       = dvb_usb_start_feed;
 	adap->demux.stop_feed        = dvb_usb_stop_feed;
 	adap->demux.write_to_decoder = NULL;
@@ -156,14 +168,33 @@
 	return 0;
 }
 
+static int dvb_usb_set_active_fe(struct dvb_frontend *fe, int onoff)
+{
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+
+	int ret = (adap->props.frontend_ctrl) ?
+		adap->props.frontend_ctrl(fe, onoff) : 0;
+
+	if (ret < 0) {
+		err("frontend_ctrl request failed");
+		return ret;
+	}
+	if (onoff)
+		adap->active_fe = fe->id;
+
+	return 0;
+}
+
 static int dvb_usb_fe_wakeup(struct dvb_frontend *fe)
 {
 	struct dvb_usb_adapter *adap = fe->dvb->priv;
 
 	dvb_usb_device_power_ctrl(adap->dev, 1);
 
-	if (adap->fe_init)
-		adap->fe_init(fe);
+	dvb_usb_set_active_fe(fe, 1);
+
+	if (adap->fe_adap[fe->id].fe_init)
+		adap->fe_adap[fe->id].fe_init(fe);
 
 	return 0;
 }
@@ -172,45 +203,81 @@
 {
 	struct dvb_usb_adapter *adap = fe->dvb->priv;
 
-	if (adap->fe_sleep)
-		adap->fe_sleep(fe);
+	if (adap->fe_adap[fe->id].fe_sleep)
+		adap->fe_adap[fe->id].fe_sleep(fe);
+
+	dvb_usb_set_active_fe(fe, 0);
 
 	return dvb_usb_device_power_ctrl(adap->dev, 0);
 }
 
 int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap)
 {
-	if (adap->props.frontend_attach == NULL) {
-		err("strange: '%s' #%d doesn't want to attach a frontend.",adap->dev->desc->name, adap->id);
-		return 0;
-	}
+	int ret, i;
 
-	/* re-assign sleep and wakeup functions */
-	if (adap->props.frontend_attach(adap) == 0 && adap->fe != NULL) {
-		adap->fe_init  = adap->fe->ops.init;  adap->fe->ops.init  = dvb_usb_fe_wakeup;
-		adap->fe_sleep = adap->fe->ops.sleep; adap->fe->ops.sleep = dvb_usb_fe_sleep;
+	/* register all given adapter frontends */
+	for (i = 0; i < adap->props.num_frontends; i++) {
 
-		if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
-			err("Frontend registration failed.");
-			dvb_frontend_detach(adap->fe);
-			adap->fe = NULL;
-			return -ENODEV;
+		if (adap->props.fe[i].frontend_attach == NULL) {
+			err("strange: '%s' #%d,%d "
+			    "doesn't want to attach a frontend.",
+			    adap->dev->desc->name, adap->id, i);
+
+			return 0;
+		}
+
+		ret = adap->props.fe[i].frontend_attach(adap);
+		if (ret || adap->fe_adap[i].fe == NULL) {
+			/* only print error when there is no FE at all */
+			if (i == 0)
+				err("no frontend was attached by '%s'",
+					adap->dev->desc->name);
+
+			return 0;
+		}
+
+		adap->fe_adap[i].fe->id = i;
+
+		/* re-assign sleep and wakeup functions */
+		adap->fe_adap[i].fe_init = adap->fe_adap[i].fe->ops.init;
+		adap->fe_adap[i].fe->ops.init  = dvb_usb_fe_wakeup;
+		adap->fe_adap[i].fe_sleep = adap->fe_adap[i].fe->ops.sleep;
+		adap->fe_adap[i].fe->ops.sleep = dvb_usb_fe_sleep;
+
+		if (dvb_register_frontend(&adap->dvb_adap, adap->fe_adap[i].fe)) {
+			err("Frontend %d registration failed.", i);
+			dvb_frontend_detach(adap->fe_adap[i].fe);
+			adap->fe_adap[i].fe = NULL;
+			/* In error case, do not try register more FEs,
+			 * still leaving already registered FEs alive. */
+			if (i == 0)
+				return -ENODEV;
+			else
+				return 0;
 		}
 
 		/* only attach the tuner if the demod is there */
-		if (adap->props.tuner_attach != NULL)
-			adap->props.tuner_attach(adap);
-	} else
-		err("no frontend was attached by '%s'",adap->dev->desc->name);
+		if (adap->props.fe[i].tuner_attach != NULL)
+			adap->props.fe[i].tuner_attach(adap);
+
+		adap->num_frontends_initialized++;
+	}
 
 	return 0;
 }
 
 int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap)
 {
-	if (adap->fe != NULL) {
-		dvb_unregister_frontend(adap->fe);
-		dvb_frontend_detach(adap->fe);
+	int i = adap->num_frontends_initialized - 1;
+
+	/* unregister all given adapter frontends */
+	for (; i >= 0; i--) {
+		if (adap->fe_adap[i].fe != NULL) {
+			dvb_unregister_frontend(adap->fe_adap[i].fe);
+			dvb_frontend_detach(adap->fe_adap[i].fe);
+		}
 	}
+	adap->num_frontends_initialized = 0;
+
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dvb-usb.h linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dvb-usb.h
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dvb-usb.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dvb-usb.h	2012-01-04 18:55:44.000000000 -0500
@@ -124,6 +124,8 @@
  * @caps: capabilities of the DVB USB device.
  * @pid_filter_count: number of PID filter position in the optional hardware
  *  PID-filter.
+ * @num_frontends: number of frontends of the DVB USB adapter.
+ * @frontend_ctrl: called to power on/off active frontend.
  * @streaming_ctrl: called to start and stop the MPEG2-TS streaming of the
  *  device (not URB submitting/killing).
  * @pid_filter_ctrl: called to en/disable the PID filter, if any.
@@ -134,7 +136,7 @@
  *  pll_desc and pll_init_buf of struct dvb_usb_device).
  * @stream: configuration of the USB streaming
  */
-struct dvb_usb_adapter_properties {
+struct dvb_usb_adapter_fe_properties {
 #define DVB_USB_ADAP_HAS_PID_FILTER               0x01
 #define DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF 0x02
 #define DVB_USB_ADAP_NEED_PID_FILTERING           0x04
@@ -152,9 +154,18 @@
 	struct usb_data_stream_properties stream;
 
 	int size_of_priv;
+};
+
+#define MAX_NO_OF_FE_PER_ADAP 2
+struct dvb_usb_adapter_properties {
+	int size_of_priv;
 
+	int (*frontend_ctrl)   (struct dvb_frontend *, int);
 	int (*fe_ioctl_override) (struct dvb_frontend *,
 				  unsigned int, void *, unsigned int);
+
+	int num_frontends;
+	struct dvb_usb_adapter_fe_properties fe[MAX_NO_OF_FE_PER_ADAP];
 };
 
 /**
@@ -345,6 +356,20 @@
  *
  * @stream: the usb data stream.
  */
+struct dvb_usb_fe_adapter {
+	struct dvb_frontend *fe;
+
+	int (*fe_init)  (struct dvb_frontend *);
+	int (*fe_sleep) (struct dvb_frontend *);
+
+	struct usb_data_stream stream;
+
+	int pid_filtering;
+	int max_feed_count;
+
+	void *priv;
+};
+
 struct dvb_usb_adapter {
 	struct dvb_usb_device *dev;
 	struct dvb_usb_adapter_properties props;
@@ -356,20 +381,16 @@
 	u8  id;
 
 	int feedcount;
-	int pid_filtering;
 
 	/* dvb */
 	struct dvb_adapter   dvb_adap;
 	struct dmxdev        dmxdev;
 	struct dvb_demux     demux;
 	struct dvb_net       dvb_net;
-	struct dvb_frontend *fe;
-	int                  max_feed_count;
-
-	int (*fe_init)  (struct dvb_frontend *);
-	int (*fe_sleep) (struct dvb_frontend *);
 
-	struct usb_data_stream stream;
+	struct dvb_usb_fe_adapter fe_adap[MAX_NO_OF_FE_PER_ADAP];
+	int active_fe;
+	int num_frontends_initialized;
 
 	void *priv;
 };
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dvb-usb-ids.h linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #define USB_VID_HAUPPAUGE			0x2040
 #define USB_VID_HYPER_PALTEK			0x1025
 #define USB_VID_INTEL				0x8086
+#define USB_VID_ITETECH				0x048d
 #define USB_VID_KWORLD				0xeb2a
 #define USB_VID_KWORLD_2			0x1b80
 #define USB_VID_KYE				0x0458
@@ -126,6 +127,7 @@
 #define USB_PID_GRANDTEC_DVBT_USB_COLD			0x0fa0
 #define USB_PID_GRANDTEC_DVBT_USB_WARM			0x0fa1
 #define USB_PID_INTEL_CE9500				0x9500
+#define USB_PID_ITETECH_IT9135				0x9135
 #define USB_PID_KWORLD_399U				0xe399
 #define USB_PID_KWORLD_399U_2				0xe400
 #define USB_PID_KWORLD_395U				0xe396
@@ -136,6 +138,7 @@
 #define USB_PID_KWORLD_PC160_2T				0xc160
 #define USB_PID_KWORLD_PC160_T				0xc161
 #define USB_PID_KWORLD_UB383_T				0xe383
+#define USB_PID_KWORLD_UB499_2T_T09			0xe409
 #define USB_PID_KWORLD_VSTREAM_COLD			0x17de
 #define USB_PID_KWORLD_VSTREAM_WARM			0x17df
 #define USB_PID_TERRATEC_CINERGY_T_USB_XE		0x0055
@@ -240,6 +243,9 @@
 #define USB_PID_PCTV_200E				0x020e
 #define USB_PID_PCTV_400E				0x020f
 #define USB_PID_PCTV_450E				0x0222
+#define USB_PID_PCTV_452E				0x021f
+#define USB_PID_TECHNOTREND_CONNECT_S2_3600		0x3007
+#define USB_PID_TECHNOTREND_CONNECT_S2_3650_CI		0x300a
 #define USB_PID_NEBULA_DIGITV				0x0201
 #define USB_PID_DVICO_BLUEBIRD_LGDT			0xd820
 #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD		0xd500
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dvb-usb-init.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dvb-usb-init.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dvb-usb-init.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dvb-usb-init.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,7 @@
 static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
 {
 	struct dvb_usb_adapter *adap;
-	int ret, n;
+	int ret, n, o;
 
 	for (n = 0; n < d->props.num_adapters; n++) {
 		adap = &d->adapter[n];
@@ -38,30 +38,41 @@
 
 		memcpy(&adap->props, &d->props.adapter[n], sizeof(struct dvb_usb_adapter_properties));
 
+	for (o = 0; o < adap->props.num_frontends; o++) {
+		struct dvb_usb_adapter_fe_properties *props = &adap->props.fe[o];
 		/* speed - when running at FULL speed we need a HW PID filter */
-		if (d->udev->speed == USB_SPEED_FULL && !(adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
+		if (d->udev->speed == USB_SPEED_FULL && !(props->caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
 			err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)");
 			return -ENODEV;
 		}
 
-		if ((d->udev->speed == USB_SPEED_FULL && adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
-			(adap->props.caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
-			info("will use the device's hardware PID filter (table count: %d).", adap->props.pid_filter_count);
-			adap->pid_filtering  = 1;
-			adap->max_feed_count = adap->props.pid_filter_count;
+		if ((d->udev->speed == USB_SPEED_FULL && props->caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
+			(props->caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
+			info("will use the device's hardware PID filter (table count: %d).", props->pid_filter_count);
+			adap->fe_adap[o].pid_filtering  = 1;
+			adap->fe_adap[o].max_feed_count = props->pid_filter_count;
 		} else {
 			info("will pass the complete MPEG2 transport stream to the software demuxer.");
-			adap->pid_filtering  = 0;
-			adap->max_feed_count = 255;
+			adap->fe_adap[o].pid_filtering  = 0;
+			adap->fe_adap[o].max_feed_count = 255;
 		}
 
-		if (!adap->pid_filtering &&
+		if (!adap->fe_adap[o].pid_filtering &&
 			dvb_usb_force_pid_filter_usage &&
-			adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) {
+			props->caps & DVB_USB_ADAP_HAS_PID_FILTER) {
 			info("pid filter enabled by module option.");
-			adap->pid_filtering  = 1;
-			adap->max_feed_count = adap->props.pid_filter_count;
+			adap->fe_adap[o].pid_filtering  = 1;
+			adap->fe_adap[o].max_feed_count = props->pid_filter_count;
+		}
+
+		if (props->size_of_priv > 0) {
+			adap->fe_adap[o].priv = kzalloc(props->size_of_priv, GFP_KERNEL);
+			if (adap->fe_adap[o].priv == NULL) {
+				err("no memory for priv for adapter %d fe %d.", n, o);
+				return -ENOMEM;
+			}
 		}
+	}
 
 		if (adap->props.size_of_priv > 0) {
 			adap->priv = kzalloc(adap->props.size_of_priv, GFP_KERNEL);
@@ -77,6 +88,10 @@
 			return ret;
 		}
 
+		/* use exclusive FE lock if there is multiple shared FEs */
+		if (adap->fe_adap[1].fe)
+			adap->dvb_adap.mfe_shared = 1;
+
 		d->num_adapters_initialized++;
 		d->state |= DVB_USB_STATE_DVB;
 	}
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dvb-usb-urb.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dvb-usb-urb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dvb-usb-urb.c	2012-01-04 18:55:44.000000000 -0500
@@ -82,16 +82,28 @@
 
 int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap)
 {
-	adap->stream.udev      = adap->dev->udev;
-	if (adap->props.caps & DVB_USB_ADAP_RECEIVES_204_BYTE_TS)
-		adap->stream.complete = dvb_usb_data_complete_204;
-	else
-	adap->stream.complete  = dvb_usb_data_complete;
-	adap->stream.user_priv = adap;
-	return usb_urb_init(&adap->stream, &adap->props.stream);
+	int i, ret = 0;
+	for (i = 0; i < adap->props.num_frontends; i++) {
+
+		adap->fe_adap[i].stream.udev      = adap->dev->udev;
+		if (adap->props.fe[i].caps & DVB_USB_ADAP_RECEIVES_204_BYTE_TS)
+			adap->fe_adap[i].stream.complete =
+				dvb_usb_data_complete_204;
+		else
+		adap->fe_adap[i].stream.complete  = dvb_usb_data_complete;
+		adap->fe_adap[i].stream.user_priv = adap;
+		ret = usb_urb_init(&adap->fe_adap[i].stream,
+				   &adap->props.fe[i].stream);
+		if (ret < 0)
+			break;
+	}
+	return ret;
 }
 
 int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap)
 {
-	return usb_urb_exit(&adap->stream);
+	int i;
+	for (i = 0; i < adap->props.num_frontends; i++)
+		usb_urb_exit(&adap->fe_adap[i].stream);
+	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dw2102.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dw2102.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/dw2102.c	2012-03-19 21:33:13.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/dw2102.c	2012-03-19 21:35:29.000000000 -0400
@@ -992,18 +992,18 @@
 	struct dvb_tuner_ops *tuner_ops = NULL;
 
 	if (demod_probe & 4) {
-		d->fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
+		d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
 				&d->dev->i2c_adap, 0);
-		if (d->fe != NULL) {
-			if (dvb_attach(stb6100_attach, d->fe,
+		if (d->fe_adap[0].fe != NULL) {
+			if (dvb_attach(stb6100_attach, d->fe_adap[0].fe,
 					&dw2104a_stb6100_config,
 					&d->dev->i2c_adap)) {
-				tuner_ops = &d->fe->ops.tuner_ops;
+				tuner_ops = &d->fe_adap[0].fe->ops.tuner_ops;
 				tuner_ops->set_frequency = stb6100_set_freq;
 				tuner_ops->get_frequency = stb6100_get_freq;
 				tuner_ops->set_bandwidth = stb6100_set_bandw;
 				tuner_ops->get_bandwidth = stb6100_get_bandw;
-				d->fe->ops.set_voltage = dw210x_set_voltage;
+				d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 				info("Attached STV0900+STB6100!\n");
 				return 0;
 			}
@@ -1011,13 +1011,13 @@
 	}
 
 	if (demod_probe & 2) {
-		d->fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
+		d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
 				&d->dev->i2c_adap, 0);
-		if (d->fe != NULL) {
-			if (dvb_attach(stv6110_attach, d->fe,
+		if (d->fe_adap[0].fe != NULL) {
+			if (dvb_attach(stv6110_attach, d->fe_adap[0].fe,
 					&dw2104_stv6110_config,
 					&d->dev->i2c_adap)) {
-				d->fe->ops.set_voltage = dw210x_set_voltage;
+				d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 				info("Attached STV0900+STV6110A!\n");
 				return 0;
 			}
@@ -1025,19 +1025,19 @@
 	}
 
 	if (demod_probe & 1) {
-		d->fe = dvb_attach(cx24116_attach, &dw2104_config,
+		d->fe_adap[0].fe = dvb_attach(cx24116_attach, &dw2104_config,
 				&d->dev->i2c_adap);
-		if (d->fe != NULL) {
-			d->fe->ops.set_voltage = dw210x_set_voltage;
+		if (d->fe_adap[0].fe != NULL) {
+			d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 			info("Attached cx24116!\n");
 			return 0;
 		}
 	}
 
-	d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
+	d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
 			&d->dev->i2c_adap);
-	if (d->fe != NULL) {
-		d->fe->ops.set_voltage = dw210x_set_voltage;
+	if (d->fe_adap[0].fe != NULL) {
+		d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 		info("Attached DS3000!\n");
 		return 0;
 	}
@@ -1053,22 +1053,22 @@
 {
 	if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) {
 		/*dw2102_properties.adapter->tuner_attach = NULL;*/
-		d->fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
+		d->fe_adap[0].fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
 					&d->dev->i2c_adap);
-		if (d->fe != NULL) {
-			d->fe->ops.set_voltage = dw210x_set_voltage;
+		if (d->fe_adap[0].fe != NULL) {
+			d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 			info("Attached si21xx!\n");
 			return 0;
 		}
 	}
 
 	if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {
-		d->fe = dvb_attach(stv0288_attach, &earda_config,
+		d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
 					&d->dev->i2c_adap);
-		if (d->fe != NULL) {
-			if (dvb_attach(stb6000_attach, d->fe, 0x61,
+		if (d->fe_adap[0].fe != NULL) {
+			if (dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61,
 					&d->dev->i2c_adap)) {
-				d->fe->ops.set_voltage = dw210x_set_voltage;
+				d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 				info("Attached stv0288!\n");
 				return 0;
 			}
@@ -1077,10 +1077,10 @@
 
 	if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) {
 		/*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
-		d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
+		d->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
 					&d->dev->i2c_adap);
-		if (d->fe != NULL) {
-			d->fe->ops.set_voltage = dw210x_set_voltage;
+		if (d->fe_adap[0].fe != NULL) {
+			d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 			info("Attached stv0299!\n");
 			return 0;
 		}
@@ -1090,9 +1090,9 @@
 
 static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
 {
-	d->fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
+	d->fe_adap[0].fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
 				&d->dev->i2c_adap, 0x48);
-	if (d->fe != NULL) {
+	if (d->fe_adap[0].fe != NULL) {
 		info("Attached tda10023!\n");
 		return 0;
 	}
@@ -1101,12 +1101,12 @@
 
 static int zl100313_frontend_attach(struct dvb_usb_adapter *d)
 {
-	d->fe = dvb_attach(mt312_attach, &zl313_config,
+	d->fe_adap[0].fe = dvb_attach(mt312_attach, &zl313_config,
 			&d->dev->i2c_adap);
-	if (d->fe != NULL) {
-		if (dvb_attach(zl10039_attach, d->fe, 0x60,
+	if (d->fe_adap[0].fe != NULL) {
+		if (dvb_attach(zl10039_attach, d->fe_adap[0].fe, 0x60,
 				&d->dev->i2c_adap)) {
-			d->fe->ops.set_voltage = dw210x_set_voltage;
+			d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 			info("Attached zl100313+zl10039!\n");
 			return 0;
 		}
@@ -1119,16 +1119,16 @@
 {
 	u8 obuf[] = {7, 1};
 
-	d->fe = dvb_attach(stv0288_attach, &earda_config,
+	d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
 			&d->dev->i2c_adap);
 
-	if (d->fe == NULL)
+	if (d->fe_adap[0].fe == NULL)
 		return -EIO;
 
-	if (NULL == dvb_attach(stb6000_attach, d->fe, 0x61, &d->dev->i2c_adap))
+	if (NULL == dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61, &d->dev->i2c_adap))
 		return -EIO;
 
-	d->fe->ops.set_voltage = dw210x_set_voltage;
+	d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 
 	dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
 
@@ -1143,14 +1143,14 @@
 	struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
 	u8 obuf[] = {7, 1};
 
-	d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
+	d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
 			&d->dev->i2c_adap);
 
-	if (d->fe == NULL)
+	if (d->fe_adap[0].fe == NULL)
 		return -EIO;
 
-	st->old_set_voltage = d->fe->ops.set_voltage;
-	d->fe->ops.set_voltage = s660_set_voltage;
+	st->old_set_voltage = d->fe_adap[0].fe->ops.set_voltage;
+	d->fe_adap[0].fe->ops.set_voltage = s660_set_voltage;
 
 	dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
 
@@ -1163,12 +1163,12 @@
 {
 	u8 obuf[] = {7, 1};
 
-	d->fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
+	d->fe_adap[0].fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
 					&d->dev->i2c_adap, 0);
-	if (d->fe == NULL)
+	if (d->fe_adap[0].fe == NULL)
 		return -EIO;
 
-	d->fe->ops.set_voltage = dw210x_set_voltage;
+	d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
 
 	dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
 
@@ -1204,9 +1204,9 @@
 	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->fe_adap[0].fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
 					&d->dev->i2c_adap);
-	if (d->fe == NULL)
+	if (d->fe_adap[0].fe == NULL)
 		return -EIO;
 
 	info("Attached DS3000!\n");
@@ -1216,14 +1216,14 @@
 
 static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
 		&adap->dev->i2c_adap, DVB_PLL_OPERA1);
 	return 0;
 }
 
 static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
 		&adap->dev->i2c_adap, DVB_PLL_TUA6034);
 
 	return 0;
@@ -1535,7 +1535,7 @@
 					DW210X_READ_MSG);
 			if ((reset16[0] == 0xa1) || (reset16[0] == 0x80)) {
 				dw2102_properties.i2c_algo = &dw2102_i2c_algo;
-				dw2102_properties.adapter->tuner_attach = &dw2102_tuner_attach;
+				dw2102_properties.adapter->fe[0].tuner_attach = &dw2102_tuner_attach;
 				break;
 			} else {
 				/* check STV0288 frontend  */
@@ -1591,6 +1591,8 @@
 	.read_mac_address = dw210x_read_mac_address,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach = dw2102_frontend_attach,
 			.stream = {
 				.type = USB_BULK,
@@ -1602,6 +1604,7 @@
 					}
 				}
 			},
+		}},
 		}
 	},
 	.num_device_descs = 3,
@@ -1642,6 +1645,8 @@
 	.read_mac_address = dw210x_read_mac_address,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach = dw2104_frontend_attach,
 			.stream = {
 				.type = USB_BULK,
@@ -1653,6 +1658,7 @@
 					}
 				}
 			},
+		}},
 		}
 	},
 	.num_device_descs = 2,
@@ -1689,6 +1695,8 @@
 	.read_mac_address = dw210x_read_mac_address,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach = dw3101_frontend_attach,
 			.tuner_attach = dw3101_tuner_attach,
 			.stream = {
@@ -1701,6 +1709,7 @@
 					}
 				}
 			},
+		}},
 		}
 	},
 	.num_device_descs = 1,
@@ -1733,6 +1742,8 @@
 	.read_mac_address = s6x0_read_mac_address,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach = zl100313_frontend_attach,
 			.stream = {
 				.type = USB_BULK,
@@ -1744,6 +1755,7 @@
 					}
 				}
 			},
+		}},
 		}
 	},
 	.num_device_descs = 1,
@@ -1810,6 +1822,8 @@
 
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = su3000_streaming_ctrl,
 			.frontend_attach  = su3000_frontend_attach,
 			.stream = {
@@ -1822,6 +1836,7 @@
 					}
 				}
 			}
+		}},
 		}
 	},
 	.num_device_descs = 3,
@@ -1855,7 +1870,7 @@
 	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;
+	p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach;
 
 	s660 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
 	if (!s660) {
@@ -1869,7 +1884,7 @@
 	s660->devices[0] = d660;
 	s660->devices[1] = d480_1;
 	s660->devices[2] = d480_2;
-	s660->adapter->frontend_attach = ds3000_frontend_attach;
+	s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach;
 
 	p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
 	if (!p7500) {
@@ -1883,7 +1898,7 @@
 	p7500->devices[0] = d7500;
 	p7500->rc.legacy.rc_map_table = rc_map_tbs_table;
 	p7500->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
-	p7500->adapter->frontend_attach = prof_7500_frontend_attach;
+	p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach;
 
 	if (0 == dvb_usb_device_init(intf, &dw2102_properties,
 			THIS_MODULE, NULL, adapter_nr) ||
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/ec168.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/ec168.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/ec168.c	2012-03-19 21:33:21.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/ec168.c	2012-03-19 21:35:36.000000000 -0400
@@ -200,9 +200,9 @@
 static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	deb_info("%s:\n", __func__);
-	adap->fe = dvb_attach(ec100_attach, &ec168_ec100_config,
+	adap->fe_adap[0].fe = dvb_attach(ec100_attach, &ec168_ec100_config,
 		&adap->dev->i2c_adap);
-	if (adap->fe == NULL)
+	if (adap->fe_adap[0].fe == NULL)
 		return -ENODEV;
 
 	return 0;
@@ -228,7 +228,7 @@
 static int ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	deb_info("%s:\n", __func__);
-	return dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap,
+	return dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 		&ec168_mxl5003s_config) == NULL ? -ENODEV : 0;
 }
 
@@ -382,6 +382,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = ec168_streaming_ctrl,
 			.frontend_attach  = ec168_ec100_frontend_attach,
 			.tuner_attach     = ec168_mxl5003s_tuner_attach,
@@ -395,6 +397,7 @@
 					}
 				}
 			},
+		}},
 		}
 	},
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/friio.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/friio.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/friio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/friio.c	2012-01-04 18:55:44.000000000 -0500
@@ -403,8 +403,8 @@
 	if (friio_initialize(adap->dev) < 0)
 		return -EIO;
 
-	adap->fe = jdvbt90502_attach(adap->dev);
-	if (adap->fe == NULL)
+	adap->fe_adap[0].fe = jdvbt90502_attach(adap->dev);
+	if (adap->fe_adap[0].fe == NULL)
 		return -EIO;
 
 	return 0;
@@ -473,6 +473,8 @@
 		/* caps:0 =>  no pid filter, 188B TS packet */
 		/* GL861 has a HW pid filter, but no info available. */
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps  = 0,
 
 			.frontend_attach  = friio_frontend_attach,
@@ -490,6 +492,7 @@
 					}
 				}
 			},
+		}},
 		}
 	},
 	.i2c_algo = &gl861_i2c_algo,
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/gl861.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/gl861.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/gl861.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/gl861.c	2012-01-04 18:55:44.000000000 -0500
@@ -103,9 +103,9 @@
 static int gl861_frontend_attach(struct dvb_usb_adapter *adap)
 {
 
-	adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
+	adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
 		&adap->dev->i2c_adap);
-	if (adap->fe == NULL)
+	if (adap->fe_adap[0].fe == NULL)
 		return -EIO;
 
 	return 0;
@@ -118,7 +118,7 @@
 static int gl861_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	return dvb_attach(qt1010_attach,
-			  adap->fe, &adap->dev->i2c_adap,
+			  adap->fe_adap[0].fe, &adap->dev->i2c_adap,
 			  &gl861_qt1010_config) == NULL ? -ENODEV : 0;
 }
 
@@ -167,6 +167,8 @@
 
 	.num_adapters = 1,
 	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
 
 		.frontend_attach  = gl861_frontend_attach,
 		.tuner_attach     = gl861_tuner_attach,
@@ -181,6 +183,7 @@
 				}
 			}
 		},
+		}},
 	} },
 	.i2c_algo         = &gl861_i2c_algo,
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/gp8psk.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/gp8psk.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/gp8psk.c	2012-03-19 21:33:28.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/gp8psk.c	2012-03-19 21:35:43.000000000 -0400
@@ -230,7 +230,7 @@
 
 static int gp8psk_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	adap->fe = gp8psk_fe_attach(adap->dev);
+	adap->fe_adap[0].fe = gp8psk_fe_attach(adap->dev);
 	return 0;
 }
 
@@ -268,6 +268,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = gp8psk_streaming_ctrl,
 			.frontend_attach  = gp8psk_frontend_attach,
 			/* parameter for the MPEG2-data transfer */
@@ -281,6 +283,7 @@
 					}
 				}
 			},
+		}},
 		}
 	},
 	.power_ctrl       = gp8psk_power_ctrl,
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/gp8psk-fe.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/gp8psk-fe.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/gp8psk-fe.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/gp8psk-fe.c	2012-01-04 18:55:44.000000000 -0500
@@ -144,19 +144,25 @@
 	cmd[6] = (freq >> 16) & 0xff;
 	cmd[7] = (freq >> 24) & 0xff;
 
+	/* backwards compatibility: DVB-S + 8-PSK were used for Turbo-FEC */
+	if (c->delivery_system == SYS_DVBS && c->modulation == PSK_8)
+		c->delivery_system = SYS_TURBO;
+
 	switch (c->delivery_system) {
 	case SYS_DVBS:
-		/* Allow QPSK and 8PSK (even for DVB-S) */
-		if (c->modulation != QPSK && c->modulation != PSK_8) {
+		if (c->modulation != QPSK) {
 			deb_fe("%s: unsupported modulation selected (%d)\n",
 				__func__, c->modulation);
 			return -EOPNOTSUPP;
 		}
 		c->fec_inner = FEC_AUTO;
 		break;
-	case SYS_DVBS2:
+	case SYS_DVBS2: /* kept for backwards compatibility */
 		deb_fe("%s: DVB-S2 delivery system selected\n", __func__);
 		break;
+	case SYS_TURBO:
+		deb_fe("%s: Turbo-FEC delivery system selected\n", __func__);
+		break;
 
 	default:
 		deb_fe("%s: unsupported delivery system selected (%d)\n",
@@ -189,7 +195,10 @@
 		default:
 			cmd[9] = 5; break;
 		}
-		cmd[8] = ADV_MOD_DVB_QPSK;
+		if (c->delivery_system == SYS_TURBO)
+			cmd[8] = ADV_MOD_TURBO_QPSK;
+		else
+			cmd[8] = ADV_MOD_DVB_QPSK;
 		break;
 	case PSK_8: /* PSK_8 is for compatibility with DN */
 		cmd[8] = ADV_MOD_TURBO_8PSK;
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/it913x.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/it913x.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/it913x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/it913x.c	2012-03-19 21:35:51.000000000 -0400
@@ -0,0 +1,702 @@
+/* DVB USB compliant linux driver for IT9137
+ *
+ * Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
+ * IT9137 (C) ITE Tech 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/dvb/it9137.txt for firmware information
+ *
+ */
+#define DVB_USB_LOG_PREFIX "it913x"
+
+#include <linux/usb.h>
+#include <linux/usb/input.h>
+#include <media/rc-core.h>
+
+#include "dvb-usb.h"
+#include "it913x-fe.h"
+
+/* debug */
+static int dvb_usb_it913x_debug;
+#define l_dprintk(var, level, args...) do { \
+	if ((var >= level)) \
+		printk(KERN_DEBUG DVB_USB_LOG_PREFIX ": " args); \
+} while (0)
+
+#define deb_info(level, args...) l_dprintk(dvb_usb_it913x_debug, level, args)
+#define debug_data_snipet(level, name, p) \
+	 deb_info(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \
+		*p, *(p+1), *(p+2), *(p+3), *(p+4), \
+			*(p+5), *(p+6), *(p+7));
+
+
+module_param_named(debug, dvb_usb_it913x_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."
+			DVB_USB_DEBUG_STATUS);
+
+static int pid_filter;
+module_param_named(pid, pid_filter, int, 0644);
+MODULE_PARM_DESC(pid, "set default 0=on 1=off");
+
+int cmd_counter;
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+struct it913x_state {
+	u8 id;
+};
+
+struct ite_config {
+	u8 chip_ver;
+	u16 chip_type;
+	u32 firmware;
+	u8 tuner_id_0;
+	u8 tuner_id_1;
+	u8 dual_mode;
+};
+
+struct ite_config it913x_config;
+
+static int it913x_bulk_write(struct usb_device *dev,
+				u8 *snd, int len, u8 pipe)
+{
+	int ret, actual_l;
+
+	ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
+				snd, len , &actual_l, 100);
+	return ret;
+}
+
+static int it913x_bulk_read(struct usb_device *dev,
+				u8 *rev, int len, u8 pipe)
+{
+	int ret, actual_l;
+
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
+				 rev, len , &actual_l, 200);
+	return ret;
+}
+
+static u16 check_sum(u8 *p, u8 len)
+{
+	u16 sum = 0;
+	u8 i = 1;
+	while (i < len)
+		sum += (i++ & 1) ? (*p++) << 8 : *p++;
+	return ~sum;
+}
+
+static int it913x_io(struct usb_device *udev, u8 mode, u8 pro,
+			u8 cmd, u32 reg, u8 addr, u8 *data, u8 len)
+{
+	int ret = 0, i, buf_size = 1;
+	u8 *buff;
+	u8 rlen;
+	u16 chk_sum;
+
+	buff = kzalloc(256, GFP_KERNEL);
+	if (!buff) {
+		info("USB Buffer Failed");
+		return -ENOMEM;
+	}
+
+	buff[buf_size++] = pro;
+	buff[buf_size++] = cmd;
+	buff[buf_size++] = cmd_counter;
+
+	switch (mode) {
+	case READ_LONG:
+	case WRITE_LONG:
+		buff[buf_size++] = len;
+		buff[buf_size++] = 2;
+		buff[buf_size++] = (reg >> 24);
+		buff[buf_size++] = (reg >> 16) & 0xff;
+		buff[buf_size++] = (reg >> 8) & 0xff;
+		buff[buf_size++] = reg & 0xff;
+	break;
+	case READ_SHORT:
+		buff[buf_size++] = addr;
+		break;
+	case WRITE_SHORT:
+		buff[buf_size++] = len;
+		buff[buf_size++] = addr;
+		buff[buf_size++] = (reg >> 8) & 0xff;
+		buff[buf_size++] = reg & 0xff;
+	break;
+	case READ_DATA:
+	case WRITE_DATA:
+		break;
+	case WRITE_CMD:
+		mode = 7;
+		break;
+	default:
+		kfree(buff);
+		return -EINVAL;
+	}
+
+	if (mode & 1) {
+		for (i = 0; i < len ; i++)
+			buff[buf_size++] = data[i];
+	}
+	chk_sum = check_sum(&buff[1], buf_size);
+
+	buff[buf_size++] = chk_sum >> 8;
+	buff[0] = buf_size;
+	buff[buf_size++] = (chk_sum & 0xff);
+
+	ret = it913x_bulk_write(udev, buff, buf_size , 0x02);
+
+	ret |= it913x_bulk_read(udev, buff, (mode & 1) ?
+			5 : len + 5 , 0x01);
+
+	rlen = (mode & 0x1) ? 0x1 : len;
+
+	if (mode & 1)
+		ret |= buff[2];
+	else
+		memcpy(data, &buff[3], rlen);
+
+	cmd_counter++;
+
+	kfree(buff);
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_wr_reg(struct usb_device *udev, u8 pro, u32 reg , u8 data)
+{
+	int ret;
+	u8 b[1];
+	b[0] = data;
+	ret = it913x_io(udev, WRITE_LONG, pro,
+			CMD_DEMOD_WRITE, reg, 0, b, sizeof(b));
+
+	return ret;
+}
+
+static int it913x_read_reg(struct usb_device *udev, u32 reg)
+{
+	int ret;
+	u8 data[1];
+
+	ret = it913x_io(udev, READ_LONG, DEV_0,
+			CMD_DEMOD_READ, reg, 0, &data[0], 1);
+
+	return (ret < 0) ? ret : data[0];
+}
+
+static u32 it913x_query(struct usb_device *udev, u8 pro)
+{
+	int ret;
+	u8 data[4];
+	ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ,
+		0x1222, 0, &data[0], 3);
+
+	it913x_config.chip_ver = data[0];
+	it913x_config.chip_type = (u16)(data[2] << 8) + data[1];
+
+	info("Chip Version=%02x Chip Type=%04x", it913x_config.chip_ver,
+		it913x_config.chip_type);
+
+	ret |= it913x_io(udev, READ_SHORT, pro,
+			CMD_QUERYINFO, 0, 0x1, &data[0], 4);
+
+	it913x_config.firmware = (data[0] << 24) + (data[1] << 16) +
+			(data[2] << 8) + data[3];
+
+	return (ret < 0) ? 0 : it913x_config.firmware;
+}
+
+static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	int ret = 0;
+	u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
+
+	if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+			return -EAGAIN;
+	deb_info(1, "PID_C  (%02x)", onoff);
+
+	if (!onoff)
+		ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1);
+
+	mutex_unlock(&adap->dev->i2c_mutex);
+	return ret;
+}
+
+static int it913x_pid_filter(struct dvb_usb_adapter *adap,
+		int index, u16 pid, int onoff)
+{
+	struct usb_device *udev = adap->dev->udev;
+	int ret = 0;
+	u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
+
+	if (pid_filter > 0)
+		return 0;
+
+	if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+			return -EAGAIN;
+	deb_info(1, "PID_F  (%02x)", onoff);
+	if (onoff) {
+		ret = it913x_wr_reg(udev, pro, PID_EN, 0x1);
+
+		ret |= it913x_wr_reg(udev, pro, PID_LSB, (u8)(pid & 0xff));
+
+		ret |= it913x_wr_reg(udev, pro, PID_MSB, (u8)(pid >> 8));
+
+		ret |= it913x_wr_reg(udev, pro, PID_INX_EN, (u8)onoff);
+
+		ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f));
+
+	}
+
+	mutex_unlock(&adap->dev->i2c_mutex);
+	return 0;
+}
+
+
+static int it913x_return_status(struct usb_device *udev)
+{
+	u32 firm = 0;
+
+	firm = it913x_query(udev, DEV_0);
+	if (firm > 0)
+		info("Firmware Version %d", firm);
+
+	return (firm > 0) ? firm : 0;
+}
+
+static int it913x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+				 int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	static u8 data[256];
+	int ret;
+	u32 reg;
+	u8 pro;
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+			return -EAGAIN;
+
+	debug_data_snipet(1, "Message out", msg[0].buf);
+	deb_info(2, "num of messages %d address %02x", num, msg[0].addr);
+
+	pro = (msg[0].addr & 0x2) ?  DEV_0_DMOD : 0x0;
+	pro |= (msg[0].addr & 0x20) ? DEV_1 : DEV_0;
+	memcpy(data, msg[0].buf, msg[0].len);
+	reg = (data[0] << 24) + (data[1] << 16) +
+			(data[2] << 8) + data[3];
+	if (num == 2) {
+		ret = it913x_io(d->udev, READ_LONG, pro,
+			CMD_DEMOD_READ, reg, 0, data, msg[1].len);
+		memcpy(msg[1].buf, data, msg[1].len);
+	} else
+		ret = it913x_io(d->udev, WRITE_LONG, pro, CMD_DEMOD_WRITE,
+			reg, 0, &data[4], msg[0].len - 4);
+
+	mutex_unlock(&d->i2c_mutex);
+
+	return ret;
+}
+
+static u32 it913x_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm it913x_i2c_algo = {
+	.master_xfer   = it913x_i2c_xfer,
+	.functionality = it913x_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+#define IT913X_POLL 250
+static int it913x_rc_query(struct dvb_usb_device *d)
+{
+	u8 ibuf[4];
+	int ret;
+	u32 key;
+	/* Avoid conflict with frontends*/
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+			return -EAGAIN;
+
+	ret = it913x_io(d->udev, READ_LONG, PRO_LINK, CMD_IR_GET,
+		0, 0, &ibuf[0], sizeof(ibuf));
+
+	if ((ibuf[2] + ibuf[3]) == 0xff) {
+		key = ibuf[2];
+		key += ibuf[0] << 8;
+		deb_info(1, "INT Key =%08x", key);
+		if (d->rc_dev != NULL)
+			rc_keydown(d->rc_dev, key, 0);
+	}
+	mutex_unlock(&d->i2c_mutex);
+
+	return ret;
+}
+static int it913x_identify_state(struct usb_device *udev,
+		struct dvb_usb_device_properties *props,
+		struct dvb_usb_device_description **desc,
+		int *cold)
+{
+	int ret = 0, firm_no;
+	u8 reg, remote;
+
+	firm_no = it913x_return_status(udev);
+
+	/* checnk for dual mode */
+	it913x_config.dual_mode =  it913x_read_reg(udev, 0x49c5);
+
+	/* TODO different remotes */
+	remote = it913x_read_reg(udev, 0x49ac); /* Remote */
+	if (remote == 0)
+		props->rc.core.rc_codes = NULL;
+
+	/* TODO at the moment tuner_id is always assigned to 0x38 */
+	it913x_config.tuner_id_0 = it913x_read_reg(udev, 0x49d0);
+
+	info("Dual mode=%x Remote=%x Tuner Type=%x", it913x_config.dual_mode
+		, remote, it913x_config.tuner_id_0);
+
+	if (firm_no > 0) {
+		*cold = 0;
+		return 0;
+	}
+
+	if (it913x_config.dual_mode) {
+		it913x_config.tuner_id_1 = it913x_read_reg(udev, 0x49e0);
+		ret = it913x_wr_reg(udev, DEV_0, GPIOH1_EN, 0x1);
+		ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_ON, 0x1);
+		ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x1);
+		msleep(50);
+		ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x0);
+		msleep(50);
+		reg = it913x_read_reg(udev, GPIOH1_O);
+		if (reg == 0) {
+			ret |= it913x_wr_reg(udev, DEV_0,  GPIOH1_O, 0x1);
+			ret |= it913x_return_status(udev);
+			if (ret != 0)
+				ret = it913x_wr_reg(udev, DEV_0,
+					GPIOH1_O, 0x0);
+		}
+		props->num_adapters = 2;
+	} else
+		props->num_adapters = 1;
+
+	reg = it913x_read_reg(udev, IO_MUX_POWER_CLK);
+
+	if (it913x_config.dual_mode) {
+		ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, CHIP2_I2C_ADDR);
+		ret |= it913x_wr_reg(udev, DEV_0,  CLK_O_EN, 0x1);
+	} else {
+		ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, 0x0);
+		ret |= it913x_wr_reg(udev, DEV_0,  CLK_O_EN, 0x0);
+	}
+
+	*cold = 1;
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	int ret = 0;
+	u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
+
+	if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+			return -EAGAIN;
+	deb_info(1, "STM  (%02x)", onoff);
+
+	if (!onoff)
+		ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1);
+
+
+	mutex_unlock(&adap->dev->i2c_mutex);
+
+	return ret;
+}
+
+
+static int it913x_download_firmware(struct usb_device *udev,
+					const struct firmware *fw)
+{
+	int ret = 0, i;
+	u8 packet_size, dlen;
+	u8 *fw_data;
+
+	packet_size = 0x29;
+
+	ret = it913x_wr_reg(udev, DEV_0,  I2C_CLK, I2C_CLK_100);
+
+	info("FRM Starting Firmware Download");
+	/* This uses scatter write firmware headers follow */
+	/* 03 XX 00     XX = chip number? */ 
+
+	for (i = 0; i < fw->size; i += packet_size) {
+			if (i > 0)
+				packet_size = 0x39;
+			fw_data = (u8 *)(fw->data + i);
+			dlen = ((i + packet_size) > fw->size)
+				? (fw->size - i) : packet_size;
+			ret |= it913x_io(udev, WRITE_DATA, DEV_0,
+				CMD_SCATTER_WRITE, 0, 0, fw_data, dlen);
+			udelay(1000);
+	}
+
+	ret |= it913x_io(udev, WRITE_CMD, DEV_0,
+			CMD_BOOT, 0, 0, NULL, 0);
+
+	msleep(100);
+
+	if (ret < 0)
+		info("FRM Firmware Download Failed (%04x)" , ret);
+	else
+		info("FRM Firmware Download Completed - Resetting Device");
+
+	ret |= it913x_return_status(udev);
+
+	msleep(30);
+
+	ret |= it913x_wr_reg(udev, DEV_0,  I2C_CLK, I2C_CLK_400);
+
+	/* Tuner function */
+	if (it913x_config.dual_mode)
+		ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0xa0);
+
+	ret |= it913x_wr_reg(udev, DEV_0,  PADODPU, 0x0);
+	ret |= it913x_wr_reg(udev, DEV_0,  AGC_O_D, 0x0);
+	if (it913x_config.dual_mode) {
+		ret |= it913x_wr_reg(udev, DEV_1,  PADODPU, 0x0);
+		ret |= it913x_wr_reg(udev, DEV_1,  AGC_O_D, 0x0);
+	}
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_name(struct dvb_usb_adapter *adap)
+{
+	const char *desc = adap->dev->desc->name;
+	char *fe_name[] = {"_1", "_2", "_3", "_4"};
+	char *name = adap->fe_adap[0].fe->ops.info.name;
+
+	strlcpy(name, desc, 128);
+	strlcat(name, fe_name[adap->id], 128);
+
+	return 0;
+}
+
+static int it913x_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	struct usb_device *udev = adap->dev->udev;
+	int ret = 0;
+	u8 adf = it913x_read_reg(udev, IO_MUX_POWER_CLK);
+	u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5);
+	u16 ep_size = adap->props.fe[0].stream.u.bulk.buffersize;
+	u8 tuner_id, tuner_type;
+
+	if (adap->id == 0)
+		tuner_id = it913x_config.tuner_id_0;
+	else
+		tuner_id = it913x_config.tuner_id_1;
+
+	/* TODO we always use IT9137 possible references here*/
+	/* Documentation suggests don't care */
+	switch (tuner_id) {
+	case 0x51:
+	case 0x52:
+	case 0x60:
+	case 0x61:
+	case 0x62:
+	default:
+	case 0x38:
+		tuner_type = IT9137;
+	}
+
+	adap->fe_adap[0].fe = dvb_attach(it913x_fe_attach,
+		&adap->dev->i2c_adap, adap_addr, adf, tuner_type);
+
+	if (adap->id == 0 && adap->fe_adap[0].fe) {
+		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x1);
+		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_SW_RST, 0x1);
+		ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x0f);
+		ret = it913x_wr_reg(udev, DEV_0, EP0_TX_NAK, 0x1b);
+		ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x2f);
+		ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_LSB,
+					ep_size & 0xff);
+		ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_MSB, ep_size >> 8);
+		ret = it913x_wr_reg(udev, DEV_0, EP4_MAX_PKT, 0x80);
+	} else if (adap->id == 1 && adap->fe_adap[0].fe) {
+		ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x6f);
+		ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_LSB,
+					ep_size & 0xff);
+		ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_MSB, ep_size >> 8);
+		ret = it913x_wr_reg(udev, DEV_0, EP5_MAX_PKT, 0x80);
+		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_EN, 0x1);
+		ret = it913x_wr_reg(udev, DEV_1_DMOD, MP2IF_SERIAL, 0x1);
+		ret = it913x_wr_reg(udev, DEV_1, TOP_HOSTB_SER_MODE, 0x1);
+		ret = it913x_wr_reg(udev, DEV_0_DMOD, TSIS_ENABLE, 0x1);
+		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x0);
+		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_SW_RST, 0x0);
+		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_HALF_PSB, 0x0);
+		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF_STOP_EN, 0x1);
+		ret = it913x_wr_reg(udev, DEV_1_DMOD, MPEG_FULL_SPEED, 0x0);
+		ret = it913x_wr_reg(udev, DEV_1_DMOD, MP2IF_STOP_EN, 0x0);
+	} else
+		return -ENODEV;
+
+	ret = it913x_name(adap);
+
+	return ret;
+}
+
+/* DVB USB Driver */
+static struct dvb_usb_device_properties it913x_properties;
+
+static int it913x_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	cmd_counter = 0;
+	if (0 == dvb_usb_device_init(intf, &it913x_properties,
+				     THIS_MODULE, NULL, adapter_nr)) {
+		info("DEV registering device driver");
+		return 0;
+	}
+
+	info("DEV it913x Error");
+	return -ENODEV;
+
+}
+
+static struct usb_device_id it913x_table[] = {
+	{ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09) },
+	{ USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135) },
+	{}		/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, it913x_table);
+
+static struct dvb_usb_device_properties it913x_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+	.usb_ctrl = DEVICE_SPECIFIC,
+	.download_firmware = it913x_download_firmware,
+	.firmware = "/*(DEBLOBBED)*/",
+	.no_reconnect = 1,
+	.size_of_priv = sizeof(struct it913x_state),
+	.num_adapters = 2,
+	.adapter = {
+		{
+		.num_frontends = 1,
+		.fe = {{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER|
+				DVB_USB_ADAP_NEED_PID_FILTERING|
+				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+			.streaming_ctrl   = it913x_streaming_ctrl,
+			.pid_filter_count = 31,
+			.pid_filter = it913x_pid_filter,
+			.pid_filter_ctrl  = it913x_pid_filter_ctrl,
+			.frontend_attach  = it913x_frontend_attach,
+			/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+				.count = 10,
+				.endpoint = 0x04,
+				.u = {/* Keep Low if PID filter on */
+					.bulk = {
+						.buffersize = 3584,
+
+					}
+				}
+			}
+		}},
+		},
+			{
+		.num_frontends = 1,
+		.fe = {{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER|
+				DVB_USB_ADAP_NEED_PID_FILTERING|
+				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+			.streaming_ctrl   = it913x_streaming_ctrl,
+			.pid_filter_count = 31,
+			.pid_filter = it913x_pid_filter,
+			.pid_filter_ctrl  = it913x_pid_filter_ctrl,
+			.frontend_attach  = it913x_frontend_attach,
+			/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+				.count = 5,
+				.endpoint = 0x05,
+				.u = {
+					.bulk = {
+						.buffersize = 3584,
+
+					}
+				}
+			}
+		}},
+		}
+	},
+	.identify_state   = it913x_identify_state,
+	.rc.core = {
+		.protocol	= RC_TYPE_NEC,
+		.module_name	= "it913x",
+		.rc_query	= it913x_rc_query,
+		.rc_interval	= IT913X_POLL,
+		.allowed_protos	= RC_TYPE_NEC,
+		.rc_codes	= RC_MAP_KWORLD_315U,
+	},
+	.i2c_algo         = &it913x_i2c_algo,
+	.num_device_descs = 2,
+	.devices = {
+		{   "Kworld UB499-2T T09(IT9137)",
+			{ &it913x_table[0], NULL },
+			},
+		{   "ITE 9135 Generic",
+			{ &it913x_table[1], NULL },
+			},
+	}
+};
+
+static struct usb_driver it913x_driver = {
+	.name		= "it913x",
+	.probe		= it913x_probe,
+	.disconnect	= dvb_usb_device_exit,
+	.id_table	= it913x_table,
+};
+
+/* module stuff */
+static int __init it913x_module_init(void)
+{
+	int result = usb_register(&it913x_driver);
+	if (result) {
+		err("usb_register failed. Error number %d", result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit it913x_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&it913x_driver);
+}
+
+module_init(it913x_module_init);
+module_exit(it913x_module_exit);
+
+MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
+MODULE_DESCRIPTION("it913x USB 2 Driver");
+MODULE_VERSION("1.07");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/Kconfig linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/Kconfig
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -258,6 +258,19 @@
 	  Say Y here to support the default remote control decoding for the
 	  Afatech AF9005 based receiver.
 
+config DVB_USB_PCTV452E
+	tristate "Pinnacle PCTV HDTV Pro USB device/TT Connect S2-3600"
+	depends on DVB_USB
+	select TTPCI_EEPROM
+	select DVB_LNBP22 if !DVB_FE_CUSTOMISE
+	select DVB_STB0899 if !DVB_FE_CUSTOMISE
+	select DVB_STB6100 if !DVB_FE_CUSTOMISE
+	help
+	  Support for external USB adapter designed by Pinnacle,
+	  shipped under the brand name 'PCTV HDTV Pro USB'.
+	  Also supports TT Connect S2-3600/3650 cards.
+	  Say Y if you own such a device and want to use it.
+
 config DVB_USB_DW2102
 	tristate "DvbWorld & TeVii DVB-S/S2 USB2.0 support"
 	depends on DVB_USB
@@ -374,3 +387,18 @@
 	select DVB_STV6110x if !DVB_FE_CUSTOMISE
 	help
 	  Say Y here to support the Technisat USB2 DVB-S/S2 device
+
+config DVB_USB_IT913X
+	tristate "it913x driver"
+	depends on DVB_USB
+	select DVB_IT913X_FE
+	help
+	  Say Y here to support the it913x device
+
+config DVB_USB_MXL111SF
+	tristate "MxL111SF DTV USB2.0 support"
+	depends on DVB_USB
+	select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
+	select VIDEO_TVEEPROM
+	help
+	  Say Y here to support the MxL111SF USB2.0 DTV receiver.
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/lmedm04.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/lmedm04.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/lmedm04.c	2012-03-19 21:33:37.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/lmedm04.c	2012-03-19 21:36:00.000000000 -0400
@@ -162,7 +162,7 @@
 	int ret = 0;
 
 	if (st->usb_buffer == NULL) {
-		st->usb_buffer = kmalloc(512, GFP_KERNEL);
+		st->usb_buffer = kmalloc(64, GFP_KERNEL);
 		if (st->usb_buffer == NULL) {
 			info("MEM Error no memory");
 			return -ENOMEM;
@@ -175,8 +175,8 @@
 	if (ret < 0)
 		return -EAGAIN;
 
-	/* the read/write capped at 512 */
-	memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen);
+	/* the read/write capped at 64 */
+	memcpy(buff, wbuf, (wlen < 64) ? wlen : 64);
 
 	ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01));
 
@@ -186,8 +186,8 @@
 
 	ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01));
 
-	ret |= lme2510_bulk_read(d->udev, buff, (rlen > 512) ?
-			512 : rlen , 0x01);
+	ret |= lme2510_bulk_read(d->udev, buff, (rlen < 64) ?
+			rlen : 64 , 0x01);
 
 	if (rlen > 0)
 		memcpy(rbuf, buff, rlen);
@@ -333,7 +333,7 @@
 	if (lme_int->lme_urb == NULL)
 			return -ENOMEM;
 
-	lme_int->buffer = usb_alloc_coherent(adap->dev->udev, 5000, GFP_ATOMIC,
+	lme_int->buffer = usb_alloc_coherent(adap->dev->udev, 128, GFP_ATOMIC,
 					&lme_int->lme_urb->transfer_dma);
 
 	if (lme_int->buffer == NULL)
@@ -343,10 +343,10 @@
 				adap->dev->udev,
 				usb_rcvintpipe(adap->dev->udev, 0xa),
 				lme_int->buffer,
-				4096,
+				128,
 				lme2510_int_response,
 				adap,
-				11);
+				8);
 
 	lme_int->lme_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
@@ -580,7 +580,7 @@
 {
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
 	struct lme2510_state *st = d->priv;
-	static u8 obuf[64], ibuf[512];
+	static u8 obuf[64], ibuf[64];
 	int i, read, read_o;
 	u16 len;
 	u8 gate = st->i2c_gate;
@@ -621,7 +621,7 @@
 			len = msg[i].len+3;
 		}
 
-		if (lme2510_msg(d, obuf, len, ibuf, 512) < 0) {
+		if (lme2510_msg(d, obuf, len, ibuf, 64) < 0) {
 			deb_info(1, "i2c transfer failed.");
 			return -EAGAIN;
 		}
@@ -941,7 +941,7 @@
 	const char *desc = adap->dev->desc->name;
 	char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395",
 				" SHARP:BS2F7HZ0194"};
-	char *name = adap->fe->ops.info.name;
+	char *name = adap->fe_adap[0].fe->ops.info.name;
 
 	strlcpy(name, desc, 128);
 	strlcat(name, fe_name[st->tuner_config], 128);
@@ -958,10 +958,10 @@
 	st->i2c_talk_onoff = 1;
 
 	st->i2c_gate = 4;
-	adap->fe = dvb_attach(tda10086_attach, &tda10086_config,
+	adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config,
 		&adap->dev->i2c_adap);
 
-	if (adap->fe) {
+	if (adap->fe_adap[0].fe) {
 		info("TUN Found Frontend TDA10086");
 		st->i2c_tuner_gate_w = 4;
 		st->i2c_tuner_gate_r = 4;
@@ -975,9 +975,9 @@
 	}
 
 	st->i2c_gate = 4;
-	adap->fe = dvb_attach(stv0299_attach, &sharp_z0194_config,
+	adap->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194_config,
 			&adap->dev->i2c_adap);
-	if (adap->fe) {
+	if (adap->fe_adap[0].fe) {
 		info("FE Found Stv0299");
 		st->i2c_tuner_gate_w = 4;
 		st->i2c_tuner_gate_r = 5;
@@ -991,9 +991,9 @@
 	}
 
 	st->i2c_gate = 5;
-	adap->fe = dvb_attach(stv0288_attach, &lme_config,
+	adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config,
 			&adap->dev->i2c_adap);
-	if (adap->fe) {
+	if (adap->fe_adap[0].fe) {
 		info("FE Found Stv0288");
 		st->i2c_tuner_gate_w = 4;
 		st->i2c_tuner_gate_r = 5;
@@ -1010,15 +1010,15 @@
 
 
 end:	if (ret) {
-		if (adap->fe) {
-			dvb_frontend_detach(adap->fe);
-			adap->fe = NULL;
+		if (adap->fe_adap[0].fe) {
+			dvb_frontend_detach(adap->fe_adap[0].fe);
+			adap->fe_adap[0].fe = NULL;
 		}
 		adap->dev->props.rc.core.rc_codes = NULL;
 		return -ENODEV;
 	}
 
-	adap->fe->ops.set_voltage = dm04_lme2510_set_voltage;
+	adap->fe_adap[0].fe->ops.set_voltage = dm04_lme2510_set_voltage;
 	ret = lme_name(adap);
 	return ret;
 }
@@ -1031,17 +1031,17 @@
 
 	switch (st->tuner_config) {
 	case TUNER_LG:
-		if (dvb_attach(tda826x_attach, adap->fe, 0xc0,
+		if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0xc0,
 			&adap->dev->i2c_adap, 1))
 			ret = st->tuner_config;
 		break;
 	case TUNER_S7395:
-		if (dvb_attach(ix2505v_attach , adap->fe, &lme_tuner,
+		if (dvb_attach(ix2505v_attach , adap->fe_adap[0].fe, &lme_tuner,
 			&adap->dev->i2c_adap))
 			ret = st->tuner_config;
 		break;
 	case TUNER_S0194:
-		if (dvb_attach(dvb_pll_attach , adap->fe, 0xc0,
+		if (dvb_attach(dvb_pll_attach , adap->fe_adap[0].fe, 0xc0,
 			&adap->dev->i2c_adap, DVB_PLL_OPERA1))
 			ret = st->tuner_config;
 		break;
@@ -1145,6 +1145,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER|
 				DVB_USB_ADAP_NEED_PID_FILTERING|
 				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1166,6 +1168,7 @@
 					}
 				}
 			}
+		}},
 		}
 	},
 	.rc.core = {
@@ -1193,6 +1196,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER|
 				DVB_USB_ADAP_NEED_PID_FILTERING|
 				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
@@ -1214,6 +1219,7 @@
 					}
 				}
 			}
+		}},
 		}
 	},
 	.rc.core = {
@@ -1241,7 +1247,7 @@
 	void *buffer = NULL;
 
 	if (adap != NULL) {
-		lme2510_kill_urb(&adap->stream);
+		lme2510_kill_urb(&adap->fe_adap[0].stream);
 		adap->feedcount = 0;
 	}
 
@@ -1255,7 +1261,7 @@
 
 	if (st->lme_urb != NULL) {
 		usb_kill_urb(st->lme_urb);
-		usb_free_coherent(d->udev, 5000, st->buffer,
+		usb_free_coherent(d->udev, 128, st->buffer,
 				  st->lme_urb->transfer_dma);
 		info("Interrupt Service Stopped");
 	}
@@ -1306,5 +1312,5 @@
 
 MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
 MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
-MODULE_VERSION("1.88");
+MODULE_VERSION("1.90");
 MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/m920x.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/m920x.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/m920x.c	2012-03-19 21:33:44.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/m920x.c	2012-03-19 21:36:08.000000000 -0400
@@ -86,12 +86,12 @@
 	}
 
 	for (i = 0; i < d->props.num_adapters; i++)
-		flags |= d->adapter[i].props.caps;
+		flags |= d->adapter[i].props.fe[0].caps;
 
 	/* Some devices(Dposh) might crash if we attempt touch at all. */
 	if (flags & DVB_USB_ADAP_HAS_PID_FILTER) {
 		for (i = 0; i < d->props.num_adapters; i++) {
-			epi = d->adapter[i].props.stream.endpoint - 0x81;
+			epi = d->adapter[i].props.fe[0].stream.endpoint - 0x81;
 
 			if (epi < 0 || epi >= M9206_MAX_ADAPTERS) {
 				printk(KERN_INFO "m920x: Unexpected adapter endpoint!\n");
@@ -292,7 +292,7 @@
 	struct m920x_state *m = adap->dev->priv;
 	int enabled = m->filtering_enabled[adap->id];
 	int i, ret = 0, filter = 0;
-	int ep = adap->props.stream.endpoint;
+	int ep = adap->props.fe[0].stream.endpoint;
 
 	for (i = 0; i < M9206_MAX_FILTERS; i++)
 		if (m->filters[adap->id][i] == 8192)
@@ -501,9 +501,10 @@
 {
 	deb("%s\n",__func__);
 
-	if ((adap->fe = dvb_attach(mt352_attach,
-				   &m920x_mt352_config,
-				   &adap->dev->i2c_adap)) == NULL)
+	adap->fe_adap[0].fe = dvb_attach(mt352_attach,
+					 &m920x_mt352_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) == NULL)
 		return -EIO;
 
 	return 0;
@@ -513,9 +514,10 @@
 {
 	deb("%s\n",__func__);
 
-	if ((adap->fe = dvb_attach(tda10046_attach,
-				   &m920x_tda10046_08_config,
-				   &adap->dev->i2c_adap)) == NULL)
+	adap->fe_adap[0].fe = dvb_attach(tda10046_attach,
+					 &m920x_tda10046_08_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) == NULL)
 		return -EIO;
 
 	return 0;
@@ -525,9 +527,10 @@
 {
 	deb("%s\n",__func__);
 
-	if ((adap->fe = dvb_attach(tda10046_attach,
-				   &m920x_tda10046_0b_config,
-				   &adap->dev->i2c_adap)) == NULL)
+	adap->fe_adap[0].fe = dvb_attach(tda10046_attach,
+					 &m920x_tda10046_0b_config,
+					 &adap->dev->i2c_adap);
+	if ((adap->fe_adap[0].fe) == NULL)
 		return -EIO;
 
 	return 0;
@@ -537,7 +540,7 @@
 {
 	deb("%s\n",__func__);
 
-	if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
+	if (dvb_attach(qt1010_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
 		return -ENODEV;
 
 	return 0;
@@ -547,7 +550,7 @@
 {
 	deb("%s\n",__func__);
 
-	if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
+	if (dvb_attach(tda827x_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
 		return -ENODEV;
 
 	return 0;
@@ -557,7 +560,7 @@
 {
 	deb("%s\n",__func__);
 
-	if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
+	if (dvb_attach(tda827x_attach, adap->fe_adap[0].fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
 		return -ENODEV;
 
 	return 0;
@@ -565,7 +568,7 @@
 
 static int m920x_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	dvb_attach(simple_tuner_attach, adap->fe,
+	dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
 		   &adap->dev->i2c_adap, 0x61,
 		   TUNER_PHILIPS_FMD1216ME_MK3);
 	return 0;
@@ -807,6 +810,9 @@
 	.identify_state   = m920x_identify_state,
 	.num_adapters = 1,
 	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
+
 		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
 			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
@@ -827,6 +833,7 @@
 				}
 			}
 		},
+		}},
 	}},
 	.i2c_algo         = &m920x_i2c_algo,
 
@@ -851,6 +858,9 @@
 	.identify_state   = m920x_identify_state,
 	.num_adapters = 1,
 	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
+
 		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
 			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
@@ -871,6 +881,7 @@
 				}
 			}
 		},
+		}},
 	}},
 	.i2c_algo         = &m920x_i2c_algo,
 
@@ -910,6 +921,9 @@
 	.identify_state   = m920x_identify_state,
 	.num_adapters = 2,
 	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
+
 		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
 			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
@@ -929,7 +943,11 @@
 					 .buffersize = 512,
 				 }
 			}
+		}},
 		}},{
+		.num_frontends = 1,
+		.fe = {{
+
 		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
 			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
@@ -949,6 +967,7 @@
 					 .buffersize = 512,
 				 }
 			}
+		}},
 		},
 	}},
 	.i2c_algo         = &m920x_i2c_algo,
@@ -974,6 +993,8 @@
 	.identify_state   = m920x_identify_state,
 	.num_adapters = 1,
 	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
 		/* Hardware pid filters don't work with this device/firmware */
 
 		.frontend_attach  = m920x_mt352_frontend_attach,
@@ -989,6 +1010,7 @@
 				 }
 			}
 		},
+		}},
 	}},
 	.i2c_algo         = &m920x_i2c_algo,
 
@@ -1019,6 +1041,9 @@
 	.identify_state   = m920x_identify_state,
 	.num_adapters = 1,
 	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
+
 		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
 			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
@@ -1041,6 +1066,7 @@
 				}
 			}
 		},
+		}},
 	} },
 	.i2c_algo         = &m920x_i2c_algo,
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/Makefile linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/Makefile
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -64,6 +64,9 @@
 dvb-usb-anysee-objs = anysee.o
 obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o
 
+dvb-usb-pctv452e-objs = pctv452e.o
+obj-$(CONFIG_DVB_USB_PCTV452E) += dvb-usb-pctv452e.o
+
 dvb-usb-dw2102-objs = dw2102.o
 obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o
 
@@ -94,7 +97,16 @@
 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/
+dvb-usb-it913x-objs := it913x.o
+obj-$(CONFIG_DVB_USB_IT913X) += dvb-usb-it913x.o
+
+dvb-usb-mxl111sf-objs = mxl111sf.o mxl111sf-phy.o mxl111sf-i2c.o mxl111sf-gpio.o
+obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-usb-mxl111sf.o
+obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-demod.o
+obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o
+
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
 # due to tuner-xc3028
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/common/tuners
+EXTRA_CFLAGS += -Idrivers/media/dvb/ttpci
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1086 @@
+/*
+ * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.com)
+ *
+ *   This program is free software; you can redistribute it and/or modify it
+ *   under the terms of the GNU General Public License as published by the Free
+ *   Software Foundation, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+
+#include <linux/vmalloc.h>
+#include <linux/i2c.h>
+
+#include "mxl111sf.h"
+#include "mxl111sf-reg.h"
+#include "mxl111sf-phy.h"
+#include "mxl111sf-i2c.h"
+#include "mxl111sf-gpio.h"
+
+#include "mxl111sf-demod.h"
+#include "mxl111sf-tuner.h"
+
+#include "lgdt3305.h"
+
+int dvb_usb_mxl111sf_debug;
+module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level "
+		 "(1=info, 2=xfer, 4=i2c, 8=reg, 16=adv (or-able)).");
+
+int dvb_usb_mxl111sf_isoc;
+module_param_named(isoc, dvb_usb_mxl111sf_isoc, int, 0644);
+MODULE_PARM_DESC(isoc, "enable usb isoc xfer (0=bulk, 1=isoc).");
+
+#define ANT_PATH_AUTO 0
+#define ANT_PATH_EXTERNAL 1
+#define ANT_PATH_INTERNAL 2
+
+int dvb_usb_mxl111sf_rfswitch =
+#if 0
+		ANT_PATH_AUTO;
+#else
+		ANT_PATH_EXTERNAL;
+#endif
+
+module_param_named(rfswitch, dvb_usb_mxl111sf_rfswitch, int, 0644);
+MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int).");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define deb_info(args...)   dprintk(dvb_usb_mxl111sf_debug, 0x13, args)
+#define deb_reg(args...)    dprintk(dvb_usb_mxl111sf_debug, 0x08, args)
+#define deb_adv(args...)    dprintk(dvb_usb_mxl111sf_debug, MXL_ADV_DBG, args)
+
+int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
+		      u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+{
+	int wo = (rbuf == NULL || rlen == 0); /* write-only */
+	int ret;
+	u8 sndbuf[1+wlen];
+
+	deb_adv("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen);
+
+	memset(sndbuf, 0, 1+wlen);
+
+	sndbuf[0] = cmd;
+	memcpy(&sndbuf[1], wbuf, wlen);
+
+	ret = (wo) ? dvb_usb_generic_write(d, sndbuf, 1+wlen) :
+		dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
+	mxl_fail(ret);
+
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+#define MXL_CMD_REG_READ	0xaa
+#define MXL_CMD_REG_WRITE	0x55
+
+int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data)
+{
+	u8 buf[2];
+	int ret;
+
+	ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2);
+	if (mxl_fail(ret)) {
+		mxl_debug("error reading reg: 0x%02x", addr);
+		goto fail;
+	}
+
+	if (buf[0] == addr)
+		*data = buf[1];
+	else {
+		err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x",
+		    addr, buf[0], buf[1]);
+		ret = -EINVAL;
+	}
+
+	deb_reg("R: (0x%02x, 0x%02x)\n", addr, *data);
+fail:
+	return ret;
+}
+
+int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data)
+{
+	u8 buf[] = { addr, data };
+	int ret;
+
+	deb_reg("W: (0x%02x, 0x%02x)\n", addr, data);
+
+	ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0);
+	if (mxl_fail(ret))
+		err("error writing reg: 0x%02x, val: 0x%02x", addr, data);
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int mxl111sf_write_reg_mask(struct mxl111sf_state *state,
+				   u8 addr, u8 mask, u8 data)
+{
+	int ret;
+	u8 val;
+
+	if (mask != 0xff) {
+		ret = mxl111sf_read_reg(state, addr, &val);
+#if 1
+		/* dont know why this usually errors out on the first try */
+		if (mxl_fail(ret))
+			err("error writing addr: 0x%02x, mask: 0x%02x, "
+			    "data: 0x%02x, retrying...", addr, mask, data);
+
+		ret = mxl111sf_read_reg(state, addr, &val);
+#endif
+		if (mxl_fail(ret))
+			goto fail;
+	}
+	val &= ~mask;
+	val |= data;
+
+	ret = mxl111sf_write_reg(state, addr, val);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state,
+			       struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
+{
+	int i, ret = 0;
+
+	for (i = 0;  ctrl_reg_info[i].addr |
+		     ctrl_reg_info[i].mask |
+		     ctrl_reg_info[i].data;  i++) {
+
+		ret = mxl111sf_write_reg_mask(state,
+					      ctrl_reg_info[i].addr,
+					      ctrl_reg_info[i].mask,
+					      ctrl_reg_info[i].data);
+		if (mxl_fail(ret)) {
+			err("failed on reg #%d (0x%02x)", i,
+			    ctrl_reg_info[i].addr);
+			break;
+		}
+	}
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl1x1sf_get_chip_info(struct mxl111sf_state *state)
+{
+	int ret;
+	u8 id, ver;
+	char *mxl_chip, *mxl_rev;
+
+	if ((state->chip_id) && (state->chip_ver))
+		return 0;
+
+	ret = mxl111sf_read_reg(state, CHIP_ID_REG, &id);
+	if (mxl_fail(ret))
+		goto fail;
+	state->chip_id = id;
+
+	ret = mxl111sf_read_reg(state, TOP_CHIP_REV_ID_REG, &ver);
+	if (mxl_fail(ret))
+		goto fail;
+	state->chip_ver = ver;
+
+	switch (id) {
+	case 0x61:
+		mxl_chip = "MxL101SF";
+		break;
+	case 0x63:
+		mxl_chip = "MxL111SF";
+		break;
+	default:
+		mxl_chip = "UNKNOWN MxL1X1";
+		break;
+	}
+	switch (ver) {
+	case 0x36:
+		state->chip_rev = MXL111SF_V6;
+		mxl_rev = "v6";
+		break;
+	case 0x08:
+		state->chip_rev = MXL111SF_V8_100;
+		mxl_rev = "v8_100";
+		break;
+	case 0x18:
+		state->chip_rev = MXL111SF_V8_200;
+		mxl_rev = "v8_200";
+		break;
+	default:
+		state->chip_rev = 0;
+		mxl_rev = "UNKNOWN REVISION";
+		break;
+	}
+	info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver);
+fail:
+	return ret;
+}
+
+#define get_chip_info(state)						\
+({									\
+	int ___ret;							\
+	___ret = mxl1x1sf_get_chip_info(state);				\
+	if (mxl_fail(___ret)) {						\
+		mxl_debug("failed to get chip info"			\
+			  " on first probe attempt");			\
+		___ret = mxl1x1sf_get_chip_info(state);			\
+		if (mxl_fail(___ret))					\
+			err("failed to get chip info during probe");	\
+		else							\
+			mxl_debug("probe needed a retry "		\
+				  "in order to succeed.");		\
+	}								\
+	___ret;								\
+})
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	/* power control depends on which adapter is being woken:
+	 * save this for init, instead, via mxl111sf_adap_fe_init */
+	return 0;
+}
+
+static int mxl111sf_adap_fe_init(struct dvb_frontend *fe)
+{
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct dvb_usb_device *d = adap->dev;
+	struct mxl111sf_state *state = d->priv;
+	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe->id].priv;
+
+	int err;
+
+	/* exit if we didnt initialize the driver yet */
+	if (!state->chip_id) {
+		mxl_debug("driver not yet initialized, exit.");
+		goto fail;
+	}
+
+	deb_info("%s()\n", __func__);
+
+	mutex_lock(&state->fe_lock);
+
+	state->alt_mode = adap_state->alt_mode;
+
+	if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
+		err("set interface failed");
+
+	err = mxl1x1sf_soft_reset(state);
+	mxl_fail(err);
+	err = mxl111sf_init_tuner_demod(state);
+	mxl_fail(err);
+	err = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+
+	mxl_fail(err);
+	mxl111sf_enable_usb_output(state);
+	mxl_fail(err);
+	mxl1x1sf_top_master_ctrl(state, 1);
+	mxl_fail(err);
+
+	if ((MXL111SF_GPIO_MOD_DVBT != adap_state->gpio_mode) &&
+	    (state->chip_rev > MXL111SF_V6)) {
+		mxl111sf_config_pin_mux_modes(state,
+					      PIN_MUX_TS_SPI_IN_MODE_1);
+		mxl_fail(err);
+	}
+	err = mxl111sf_init_port_expander(state);
+	if (!mxl_fail(err)) {
+		state->gpio_mode = adap_state->gpio_mode;
+		err = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
+		mxl_fail(err);
+#if 0
+		err = fe->ops.init(fe);
+#endif
+		msleep(100); /* add short delay after enabling
+			      * the demod before touching it */
+	}
+
+	return (adap_state->fe_init) ? adap_state->fe_init(fe) : 0;
+fail:
+	return -ENODEV;
+}
+
+static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe)
+{
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct dvb_usb_device *d = adap->dev;
+	struct mxl111sf_state *state = d->priv;
+	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe->id].priv;
+	int err;
+
+	/* exit if we didnt initialize the driver yet */
+	if (!state->chip_id) {
+		mxl_debug("driver not yet initialized, exit.");
+		goto fail;
+	}
+
+	deb_info("%s()\n", __func__);
+
+	err = (adap_state->fe_sleep) ? adap_state->fe_sleep(fe) : 0;
+
+	mutex_unlock(&state->fe_lock);
+
+	return err;
+fail:
+	return -ENODEV;
+}
+
+
+static int mxl111sf_ep6_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	struct dvb_usb_device *d = adap->dev;
+	struct mxl111sf_state *state = d->priv;
+	struct mxl111sf_adap_state *adap_state = adap->fe_adap[adap->active_fe].priv;
+	int ret = 0;
+	u8 tmp;
+
+	deb_info("%s(%d)\n", __func__, onoff);
+
+	if (onoff) {
+		ret = mxl111sf_enable_usb_output(state);
+		mxl_fail(ret);
+		ret = mxl111sf_config_mpeg_in(state, 1, 1,
+					      adap_state->ep6_clockphase,
+					      0, 0);
+		mxl_fail(ret);
+	} else {
+		ret = mxl111sf_disable_656_port(state);
+		mxl_fail(ret);
+	}
+
+	mxl111sf_read_reg(state, 0x12, &tmp);
+	tmp &= ~0x04;
+	mxl111sf_write_reg(state, 0x12, tmp);
+
+	return ret;
+}
+
+static int mxl111sf_ep4_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	struct dvb_usb_device *d = adap->dev;
+	struct mxl111sf_state *state = d->priv;
+	int ret = 0;
+
+	deb_info("%s(%d)\n", __func__, onoff);
+
+	if (onoff) {
+		ret = mxl111sf_enable_usb_output(state);
+		mxl_fail(ret);
+	}
+
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static struct lgdt3305_config hauppauge_lgdt3305_config = {
+	.i2c_addr           = 0xb2 >> 1,
+	.mpeg_mode          = LGDT3305_MPEG_SERIAL,
+	.tpclk_edge         = LGDT3305_TPCLK_RISING_EDGE,
+	.tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
+	.deny_i2c_rptr      = 1,
+	.spectral_inversion = 0,
+	.qam_if_khz         = 6000,
+	.vsb_if_khz         = 6000,
+};
+
+static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	struct dvb_usb_device *d = adap->dev;
+	struct mxl111sf_state *state = d->priv;
+	int fe_id = adap->num_frontends_initialized;
+	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
+	int ret;
+
+	deb_adv("%s()\n", __func__);
+
+	/* save a pointer to the dvb_usb_device in device state */
+	state->d = d;
+	adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
+	state->alt_mode = adap_state->alt_mode;
+
+	if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
+		err("set interface failed");
+
+	state->gpio_mode = MXL111SF_GPIO_MOD_ATSC;
+	adap_state->gpio_mode = state->gpio_mode;
+	adap_state->device_mode = MXL_TUNER_MODE;
+	adap_state->ep6_clockphase = 1;
+
+	ret = mxl1x1sf_soft_reset(state);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_init_tuner_demod(state);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_enable_usb_output(state);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl1x1sf_top_master_ctrl(state, 1);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_init_port_expander(state);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
+	if (mxl_fail(ret))
+		goto fail;
+
+	adap->fe_adap[fe_id].fe = dvb_attach(lgdt3305_attach,
+				 &hauppauge_lgdt3305_config,
+				 &adap->dev->i2c_adap);
+	if (adap->fe_adap[fe_id].fe) {
+		adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
+		adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
+		adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
+		adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
+		return 0;
+	}
+	ret = -EIO;
+fail:
+	return ret;
+}
+
+static struct mxl111sf_demod_config mxl_demod_config = {
+	.read_reg        = mxl111sf_read_reg,
+	.write_reg       = mxl111sf_write_reg,
+	.program_regs    = mxl111sf_ctrl_program_regs,
+};
+
+static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap)
+{
+	struct dvb_usb_device *d = adap->dev;
+	struct mxl111sf_state *state = d->priv;
+	int fe_id = adap->num_frontends_initialized;
+	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
+	int ret;
+
+	deb_adv("%s()\n", __func__);
+
+	/* save a pointer to the dvb_usb_device in device state */
+	state->d = d;
+	adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 1 : 2;
+	state->alt_mode = adap_state->alt_mode;
+
+	if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
+		err("set interface failed");
+
+	state->gpio_mode = MXL111SF_GPIO_MOD_DVBT;
+	adap_state->gpio_mode = state->gpio_mode;
+	adap_state->device_mode = MXL_SOC_MODE;
+	adap_state->ep6_clockphase = 1;
+
+	ret = mxl1x1sf_soft_reset(state);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_init_tuner_demod(state);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_enable_usb_output(state);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl1x1sf_top_master_ctrl(state, 1);
+	if (mxl_fail(ret))
+		goto fail;
+
+	/* dont care if this fails */
+	mxl111sf_init_port_expander(state);
+
+	adap->fe_adap[fe_id].fe = dvb_attach(mxl111sf_demod_attach, state,
+			      &mxl_demod_config);
+	if (adap->fe_adap[fe_id].fe) {
+		adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
+		adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
+		adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
+		adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
+		return 0;
+	}
+	ret = -EIO;
+fail:
+	return ret;
+}
+
+static inline int mxl111sf_set_ant_path(struct mxl111sf_state *state,
+					int antpath)
+{
+	return mxl111sf_idac_config(state, 1, 1,
+				    (antpath == ANT_PATH_INTERNAL) ?
+				    0x3f : 0x00, 0);
+}
+
+#define DbgAntHunt(x, pwr0, pwr1, pwr2, pwr3) \
+	err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \
+	    __func__, __LINE__, \
+	    (ANT_PATH_EXTERNAL == x) ? "EXTERNAL" : "INTERNAL", \
+	    pwr0, pwr1, pwr2, pwr3)
+
+#define ANT_HUNT_SLEEP 90
+#define ANT_EXT_TWEAK 0
+
+static int mxl111sf_ant_hunt(struct dvb_frontend *fe)
+{
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct dvb_usb_device *d = adap->dev;
+	struct mxl111sf_state *state = d->priv;
+
+	int antctrl = dvb_usb_mxl111sf_rfswitch;
+
+	u16 rxPwrA, rxPwr0, rxPwr1, rxPwr2;
+
+	/* FIXME: must force EXTERNAL for QAM - done elsewhere */
+	mxl111sf_set_ant_path(state, antctrl == ANT_PATH_AUTO ?
+			      ANT_PATH_EXTERNAL : antctrl);
+
+	if (antctrl == ANT_PATH_AUTO) {
+#if 0
+		msleep(ANT_HUNT_SLEEP);
+#endif
+		fe->ops.tuner_ops.get_rf_strength(fe, &rxPwrA);
+
+		mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
+		msleep(ANT_HUNT_SLEEP);
+		fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr0);
+
+		mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
+		msleep(ANT_HUNT_SLEEP);
+		fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr1);
+
+		mxl111sf_set_ant_path(state, ANT_PATH_INTERNAL);
+		msleep(ANT_HUNT_SLEEP);
+		fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr2);
+
+		if (rxPwr1+ANT_EXT_TWEAK >= rxPwr2) {
+			/* return with EXTERNAL enabled */
+			mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
+			DbgAntHunt(ANT_PATH_EXTERNAL, rxPwrA,
+				   rxPwr0, rxPwr1, rxPwr2);
+		} else {
+			/* return with INTERNAL enabled */
+			DbgAntHunt(ANT_PATH_INTERNAL, rxPwrA,
+				   rxPwr0, rxPwr1, rxPwr2);
+		}
+	}
+	return 0;
+}
+
+static struct mxl111sf_tuner_config mxl_tuner_config = {
+	.if_freq         = MXL_IF_6_0, /* applies to external IF output, only */
+	.invert_spectrum = 0,
+	.read_reg        = mxl111sf_read_reg,
+	.write_reg       = mxl111sf_write_reg,
+	.program_regs    = mxl111sf_ctrl_program_regs,
+	.top_master_ctrl = mxl1x1sf_top_master_ctrl,
+	.ant_hunt        = mxl111sf_ant_hunt,
+};
+
+static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap)
+{
+	struct dvb_usb_device *d = adap->dev;
+	struct mxl111sf_state *state = d->priv;
+	int fe_id = adap->num_frontends_initialized;
+
+	deb_adv("%s()\n", __func__);
+
+	if (NULL != dvb_attach(mxl111sf_tuner_attach,
+			       adap->fe_adap[fe_id].fe, state,
+			       &mxl_tuner_config))
+		return 0;
+
+	return -EIO;
+}
+
+static int mxl111sf_fe_ioctl_override(struct dvb_frontend *fe,
+				      unsigned int cmd, void *parg,
+				      unsigned int stage)
+{
+	int err = 0;
+
+	switch (stage) {
+	case DVB_FE_IOCTL_PRE:
+
+		switch (cmd) {
+		case FE_READ_SIGNAL_STRENGTH:
+			err = fe->ops.tuner_ops.get_rf_strength(fe, parg);
+			/* If no error occurs, prevent dvb-core from handling
+			 * this IOCTL, otherwise return the error */
+			if (0 == err)
+				err = 1;
+			break;
+		}
+		break;
+
+	case DVB_FE_IOCTL_POST:
+		/* no post-ioctl handling required */
+		break;
+	}
+	return err;
+};
+
+static u32 mxl111sf_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+struct i2c_algorithm mxl111sf_i2c_algo = {
+	.master_xfer   = mxl111sf_i2c_xfer,
+	.functionality = mxl111sf_i2c_func,
+#ifdef NEED_ALGO_CONTROL
+	.algo_control = dummy_algo_control,
+#endif
+};
+
+static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties;
+static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties;
+static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties;
+static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties;
+
+static int mxl111sf_probe(struct usb_interface *intf,
+			  const struct usb_device_id *id)
+{
+	struct dvb_usb_device *d = NULL;
+
+	deb_adv("%s()\n", __func__);
+
+	if (((dvb_usb_mxl111sf_isoc) &&
+	     (0 == dvb_usb_device_init(intf,
+				       &mxl111sf_dvbt_isoc_properties,
+				       THIS_MODULE, &d, adapter_nr) ||
+	      0 == dvb_usb_device_init(intf,
+				       &mxl111sf_atsc_isoc_properties,
+				       THIS_MODULE, &d, adapter_nr))) ||
+	    0 == dvb_usb_device_init(intf,
+				     &mxl111sf_dvbt_bulk_properties,
+				     THIS_MODULE, &d, adapter_nr) ||
+	    0 == dvb_usb_device_init(intf,
+				     &mxl111sf_atsc_bulk_properties,
+				     THIS_MODULE, &d, adapter_nr) || 0) {
+
+		struct mxl111sf_state *state = d->priv;
+		static u8 eeprom[256];
+		struct i2c_client c;
+		int ret;
+
+		ret = get_chip_info(state);
+		if (mxl_fail(ret))
+			err("failed to get chip info during probe");
+
+		mutex_init(&state->fe_lock);
+
+		if (state->chip_rev > MXL111SF_V6)
+			mxl111sf_config_pin_mux_modes(state,
+						      PIN_MUX_TS_SPI_IN_MODE_1);
+
+		c.adapter = &d->i2c_adap;
+		c.addr = 0xa0 >> 1;
+
+		ret = tveeprom_read(&c, eeprom, sizeof(eeprom));
+		if (mxl_fail(ret))
+			return 0;
+		tveeprom_hauppauge_analog(&c, &state->tv,
+					  (0x84 == eeprom[0xa0]) ?
+					  eeprom + 0xa0 : eeprom + 0x80);
+#if 0
+		switch (state->tv.model) {
+		case 117001:
+		case 126001:
+		case 138001:
+			break;
+		default:
+			printk(KERN_WARNING "%s: warning: "
+			       "unknown hauppauge model #%d\n",
+			       __func__, state->tv.model);
+		}
+#endif
+		return 0;
+	}
+	err("Your device is not yet supported by this driver. "
+	    "See kernellabs.com for more info");
+	return -EINVAL;
+}
+
+static struct usb_device_id mxl111sf_table[] = {
+/* 0 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc600) }, /* ATSC+ IR     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc601) }, /* ATSC         */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc602) }, /*     +        */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc603) }, /* ATSC+        */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc604) }, /* DVBT         */
+/* 5 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc609) }, /* ATSC  IR     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60a) }, /*     + IR     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60b) }, /* ATSC+ IR     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60c) }, /* DVBT  IR     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc653) }, /* ATSC+        */
+/*10 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc65b) }, /* ATSC+ IR     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb700) }, /* ATSC+ sw     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb701) }, /* ATSC  sw     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb702) }, /*     + sw     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb703) }, /* ATSC+ sw     */
+/*15 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb704) }, /* DVBT  sw     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb753) }, /* ATSC+ sw     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb763) }, /* ATSC+ no     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb764) }, /* DVBT  no     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd853) }, /* ATSC+ sw     */
+/*20 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd854) }, /* DVBT  sw     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd863) }, /* ATSC+ no     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd864) }, /* DVBT  no     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d3) }, /* ATSC+ sw     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d4) }, /* DVBT  sw     */
+/*25 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e3) }, /* ATSC+ no     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e4) }, /* DVBT  no     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8ff) }, /* ATSC+        */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc612) }, /*     +        */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc613) }, /* ATSC+        */
+/*30 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61a) }, /*     + IR     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61b) }, /* ATSC+ IR     */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb757) }, /* ATSC+DVBT sw */
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb767) }, /* ATSC+DVBT no */
+	{}		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, mxl111sf_table);
+
+
+#define MXL111SF_EP4_BULK_STREAMING_CONFIG		\
+	.streaming_ctrl = mxl111sf_ep4_streaming_ctrl,	\
+	.stream = {					\
+		.type = USB_BULK,			\
+		.count = 5,				\
+		.endpoint = 0x04,			\
+		.u = {					\
+			.bulk = {			\
+				.buffersize = 8192,	\
+			}				\
+		}					\
+	}
+
+/* FIXME: works for v6 but not v8 silicon */
+#define MXL111SF_EP4_ISOC_STREAMING_CONFIG		\
+	.streaming_ctrl = mxl111sf_ep4_streaming_ctrl,	\
+	.stream = {					\
+		.type = USB_ISOC,			\
+		.count = 5,				\
+		.endpoint = 0x04,			\
+		.u = {					\
+			.isoc = {			\
+				.framesperurb = 96,	\
+				/* FIXME: v6 SILICON: */	\
+				.framesize = 564,	\
+				.interval = 1,		\
+			}				\
+		}					\
+	}
+
+#define MXL111SF_EP6_BULK_STREAMING_CONFIG		\
+	.streaming_ctrl = mxl111sf_ep6_streaming_ctrl,	\
+	.stream = {					\
+		.type = USB_BULK,			\
+		.count = 5,				\
+		.endpoint = 0x06,			\
+		.u = {					\
+			.bulk = {			\
+				.buffersize = 8192,	\
+			}				\
+		}					\
+	}
+
+/* FIXME */
+#define MXL111SF_EP6_ISOC_STREAMING_CONFIG		\
+	.streaming_ctrl = mxl111sf_ep6_streaming_ctrl,	\
+	.stream = {					\
+		.type = USB_ISOC,			\
+		.count = 5,				\
+		.endpoint = 0x06,			\
+		.u = {					\
+			.isoc = {			\
+				.framesperurb = 24,	\
+				.framesize = 3072,	\
+				.interval = 1,		\
+			}				\
+		}					\
+	}
+
+#define MXL111SF_DEFAULT_DEVICE_PROPERTIES			\
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,			\
+	.usb_ctrl = DEVICE_SPECIFIC,				\
+	/* use usb alt setting 1 for EP4 ISOC transfer (dvb-t),	\
+				     EP6 BULK transfer (atsc/qam), \
+	   use usb alt setting 2 for EP4 BULK transfer (dvb-t),	\
+				     EP6 ISOC transfer (atsc/qam), \
+	*/							\
+	.power_ctrl       = mxl111sf_power_ctrl,		\
+	.i2c_algo         = &mxl111sf_i2c_algo,			\
+	.generic_bulk_ctrl_endpoint          = MXL_EP2_REG_WRITE, \
+	.generic_bulk_ctrl_endpoint_response = MXL_EP1_REG_READ, \
+	.size_of_priv     = sizeof(struct mxl111sf_state)
+
+static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties = {
+	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+	.num_adapters = 1,
+	.adapter = {
+		{
+		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
+		.num_frontends = 1,
+		.fe = {{
+			.size_of_priv     = sizeof(struct mxl111sf_adap_state),
+
+			.frontend_attach  = mxl111sf_attach_demod,
+			.tuner_attach     = mxl111sf_attach_tuner,
+
+			MXL111SF_EP4_BULK_STREAMING_CONFIG,
+		} },
+		},
+	},
+	.num_device_descs = 4,
+	.devices = {
+		{   "Hauppauge 126xxx DVBT (bulk)",
+			{ NULL },
+			{ &mxl111sf_table[4], &mxl111sf_table[8],
+			  NULL },
+		},
+		{   "Hauppauge 117xxx DVBT (bulk)",
+			{ NULL },
+			{ &mxl111sf_table[15], &mxl111sf_table[18],
+			  NULL },
+		},
+		{   "Hauppauge 138xxx DVBT (bulk)",
+			{ NULL },
+			{ &mxl111sf_table[20], &mxl111sf_table[22],
+			  &mxl111sf_table[24], &mxl111sf_table[26],
+			  NULL },
+		},
+		{   "Hauppauge 126xxx (tp-bulk)",
+			{ NULL },
+			{ &mxl111sf_table[28], &mxl111sf_table[30],
+			  NULL },
+		},
+	}
+};
+
+static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties = {
+	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+	.num_adapters = 1,
+	.adapter = {
+		{
+		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
+		.num_frontends = 1,
+		.fe = {{
+			.size_of_priv     = sizeof(struct mxl111sf_adap_state),
+
+			.frontend_attach  = mxl111sf_attach_demod,
+			.tuner_attach     = mxl111sf_attach_tuner,
+
+			MXL111SF_EP4_ISOC_STREAMING_CONFIG,
+		} },
+		},
+	},
+	.num_device_descs = 4,
+	.devices = {
+		{   "Hauppauge 126xxx DVBT (isoc)",
+			{ NULL },
+			{ &mxl111sf_table[4], &mxl111sf_table[8],
+			  NULL },
+		},
+		{   "Hauppauge 117xxx DVBT (isoc)",
+			{ NULL },
+			{ &mxl111sf_table[15], &mxl111sf_table[18],
+			  NULL },
+		},
+		{   "Hauppauge 138xxx DVBT (isoc)",
+			{ NULL },
+			{ &mxl111sf_table[20], &mxl111sf_table[22],
+			  &mxl111sf_table[24], &mxl111sf_table[26],
+			  NULL },
+		},
+		{   "Hauppauge 126xxx (tp-isoc)",
+			{ NULL },
+			{ &mxl111sf_table[28], &mxl111sf_table[30],
+			  NULL },
+		},
+	}
+};
+
+static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = {
+	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+	.num_adapters = 1,
+	.adapter = {
+		{
+		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
+		.num_frontends = 2,
+		.fe = {{
+			.size_of_priv     = sizeof(struct mxl111sf_adap_state),
+
+			.frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
+			.tuner_attach     = mxl111sf_attach_tuner,
+
+			MXL111SF_EP6_BULK_STREAMING_CONFIG,
+		},
+		{
+			.size_of_priv     = sizeof(struct mxl111sf_adap_state),
+
+			.frontend_attach  = mxl111sf_attach_demod,
+			.tuner_attach     = mxl111sf_attach_tuner,
+
+			MXL111SF_EP4_BULK_STREAMING_CONFIG,
+		}},
+		},
+	},
+	.num_device_descs = 6,
+	.devices = {
+		{   "Hauppauge 126xxx ATSC (bulk)",
+			{ NULL },
+			{ &mxl111sf_table[1], &mxl111sf_table[5],
+			  NULL },
+		},
+		{   "Hauppauge 117xxx ATSC (bulk)",
+			{ NULL },
+			{ &mxl111sf_table[12],
+			  NULL },
+		},
+		{   "Hauppauge 126xxx ATSC+ (bulk)",
+			{ NULL },
+			{ &mxl111sf_table[0], &mxl111sf_table[3],
+			  &mxl111sf_table[7], &mxl111sf_table[9],
+			  &mxl111sf_table[10], NULL },
+		},
+		{   "Hauppauge 117xxx ATSC+ (bulk)",
+			{ NULL },
+			{ &mxl111sf_table[11], &mxl111sf_table[14],
+			  &mxl111sf_table[16], &mxl111sf_table[17],
+			  &mxl111sf_table[32], &mxl111sf_table[33],
+			  NULL },
+		},
+		{   "Hauppauge Mercury (tp-bulk)",
+			{ NULL },
+			{ &mxl111sf_table[19], &mxl111sf_table[21],
+			  &mxl111sf_table[23], &mxl111sf_table[25],
+			  &mxl111sf_table[27], NULL },
+		},
+		{   "Hauppauge WinTV-Aero-M",
+			{ NULL },
+			{ &mxl111sf_table[29], &mxl111sf_table[31],
+			  NULL },
+		},
+	}
+};
+
+static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = {
+	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+	.num_adapters = 1,
+	.adapter = {
+		{
+		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
+		.num_frontends = 2,
+		.fe = {{
+			.size_of_priv     = sizeof(struct mxl111sf_adap_state),
+
+			.frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
+			.tuner_attach     = mxl111sf_attach_tuner,
+
+			MXL111SF_EP6_ISOC_STREAMING_CONFIG,
+		},
+		{
+			.size_of_priv     = sizeof(struct mxl111sf_adap_state),
+
+			.frontend_attach  = mxl111sf_attach_demod,
+			.tuner_attach     = mxl111sf_attach_tuner,
+
+			MXL111SF_EP4_ISOC_STREAMING_CONFIG,
+		}},
+		},
+	},
+	.num_device_descs = 6,
+	.devices = {
+		{   "Hauppauge 126xxx ATSC (isoc)",
+			{ NULL },
+			{ &mxl111sf_table[1], &mxl111sf_table[5],
+			  NULL },
+		},
+		{   "Hauppauge 117xxx ATSC (isoc)",
+			{ NULL },
+			{ &mxl111sf_table[12],
+			  NULL },
+		},
+		{   "Hauppauge 126xxx ATSC+ (isoc)",
+			{ NULL },
+			{ &mxl111sf_table[0], &mxl111sf_table[3],
+			  &mxl111sf_table[7], &mxl111sf_table[9],
+			  &mxl111sf_table[10], NULL },
+		},
+		{   "Hauppauge 117xxx ATSC+ (isoc)",
+			{ NULL },
+			{ &mxl111sf_table[11], &mxl111sf_table[14],
+			  &mxl111sf_table[16], &mxl111sf_table[17],
+			  &mxl111sf_table[32], &mxl111sf_table[33],
+			  NULL },
+		},
+		{   "Hauppauge Mercury (tp-isoc)",
+			{ NULL },
+			{ &mxl111sf_table[19], &mxl111sf_table[21],
+			  &mxl111sf_table[23], &mxl111sf_table[25],
+			  &mxl111sf_table[27], NULL },
+		},
+		{   "Hauppauge WinTV-Aero-M (tp-isoc)",
+			{ NULL },
+			{ &mxl111sf_table[29], &mxl111sf_table[31],
+			  NULL },
+		},
+	}
+};
+
+static struct usb_driver mxl111sf_driver = {
+	.name		= "dvb_usb_mxl111sf",
+	.probe		= mxl111sf_probe,
+	.disconnect     = dvb_usb_device_exit,
+	.id_table	= mxl111sf_table,
+};
+
+static int __init mxl111sf_module_init(void)
+{
+	int result = usb_register(&mxl111sf_driver);
+	if (result) {
+		err("usb_register failed. Error number %d", result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit mxl111sf_module_exit(void)
+{
+	usb_deregister(&mxl111sf_driver);
+}
+
+module_init(mxl111sf_module_init);
+module_exit(mxl111sf_module_exit);
+
+MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
+MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-demod.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-demod.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-demod.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-demod.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,614 @@
+/*
+ *  mxl111sf-demod.c - driver for the MaxLinear MXL111SF DVB-T demodulator
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 "mxl111sf-demod.h"
+#include "mxl111sf-reg.h"
+
+/* debug */
+static int mxl111sf_demod_debug;
+module_param_named(debug, mxl111sf_demod_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
+
+#define mxl_dbg(fmt, arg...) \
+	if (mxl111sf_demod_debug) \
+		mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+/* ------------------------------------------------------------------------ */
+
+struct mxl111sf_demod_state {
+	struct mxl111sf_state *mxl_state;
+
+	struct mxl111sf_demod_config *cfg;
+
+	struct dvb_frontend fe;
+};
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_demod_read_reg(struct mxl111sf_demod_state *state,
+				   u8 addr, u8 *data)
+{
+	return (state->cfg->read_reg) ?
+		state->cfg->read_reg(state->mxl_state, addr, data) :
+		-EINVAL;
+}
+
+static int mxl111sf_demod_write_reg(struct mxl111sf_demod_state *state,
+				    u8 addr, u8 data)
+{
+	return (state->cfg->write_reg) ?
+		state->cfg->write_reg(state->mxl_state, addr, data) :
+		-EINVAL;
+}
+
+static
+int mxl111sf_demod_program_regs(struct mxl111sf_demod_state *state,
+				struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
+{
+	return (state->cfg->program_regs) ?
+		state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
+		-EINVAL;
+}
+
+/* ------------------------------------------------------------------------ */
+/* TPS */
+
+static
+int mxl1x1sf_demod_get_tps_code_rate(struct mxl111sf_demod_state *state,
+				     fe_code_rate_t *code_rate)
+{
+	u8 val;
+	int ret = mxl111sf_demod_read_reg(state, V6_CODE_RATE_TPS_REG, &val);
+	/* bit<2:0> - 000:1/2, 001:2/3, 010:3/4, 011:5/6, 100:7/8 */
+	if (mxl_fail(ret))
+		goto fail;
+
+	switch (val & V6_CODE_RATE_TPS_MASK) {
+	case 0:
+		*code_rate = FEC_1_2;
+		break;
+	case 1:
+		*code_rate = FEC_2_3;
+		break;
+	case 2:
+		*code_rate = FEC_3_4;
+		break;
+	case 3:
+		*code_rate = FEC_5_6;
+		break;
+	case 4:
+		*code_rate = FEC_7_8;
+		break;
+	}
+fail:
+	return ret;
+}
+
+static
+int mxl1x1sf_demod_get_tps_constellation(struct mxl111sf_demod_state *state,
+					 fe_modulation_t *constellation)
+{
+	u8 val;
+	int ret = mxl111sf_demod_read_reg(state, V6_MODORDER_TPS_REG, &val);
+	/* Constellation, 00 : QPSK, 01 : 16QAM, 10:64QAM */
+	if (mxl_fail(ret))
+		goto fail;
+
+	switch ((val & V6_PARAM_CONSTELLATION_MASK) >> 4) {
+	case 0:
+		*constellation = QPSK;
+		break;
+	case 1:
+		*constellation = QAM_16;
+		break;
+	case 2:
+		*constellation = QAM_64;
+		break;
+	}
+fail:
+	return ret;
+}
+
+static
+int mxl1x1sf_demod_get_tps_guard_fft_mode(struct mxl111sf_demod_state *state,
+					  fe_transmit_mode_t *fft_mode)
+{
+	u8 val;
+	int ret = mxl111sf_demod_read_reg(state, V6_MODE_TPS_REG, &val);
+	/* FFT Mode, 00:2K, 01:8K, 10:4K */
+	if (mxl_fail(ret))
+		goto fail;
+
+	switch ((val & V6_PARAM_FFT_MODE_MASK) >> 2) {
+	case 0:
+		*fft_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		*fft_mode = TRANSMISSION_MODE_8K;
+		break;
+	case 2:
+		*fft_mode = TRANSMISSION_MODE_4K;
+		break;
+	}
+fail:
+	return ret;
+}
+
+static
+int mxl1x1sf_demod_get_tps_guard_interval(struct mxl111sf_demod_state *state,
+					  fe_guard_interval_t *guard)
+{
+	u8 val;
+	int ret = mxl111sf_demod_read_reg(state, V6_CP_TPS_REG, &val);
+	/* 00:1/32, 01:1/16, 10:1/8, 11:1/4 */
+	if (mxl_fail(ret))
+		goto fail;
+
+	switch ((val & V6_PARAM_GI_MASK) >> 4) {
+	case 0:
+		*guard = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		*guard = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		*guard = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		*guard = GUARD_INTERVAL_1_4;
+		break;
+	}
+fail:
+	return ret;
+}
+
+static
+int mxl1x1sf_demod_get_tps_hierarchy(struct mxl111sf_demod_state *state,
+				     fe_hierarchy_t *hierarchy)
+{
+	u8 val;
+	int ret = mxl111sf_demod_read_reg(state, V6_TPS_HIERACHY_REG, &val);
+	/* bit<6:4> - 000:Non hierarchy, 001:1, 010:2, 011:4 */
+	if (mxl_fail(ret))
+		goto fail;
+
+	switch ((val & V6_TPS_HIERARCHY_INFO_MASK) >> 6) {
+	case 0:
+		*hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		*hierarchy = HIERARCHY_1;
+		break;
+	case 2:
+		*hierarchy = HIERARCHY_2;
+		break;
+	case 3:
+		*hierarchy = HIERARCHY_4;
+		break;
+	}
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+/* LOCKS */
+
+static
+int mxl1x1sf_demod_get_sync_lock_status(struct mxl111sf_demod_state *state,
+					int *sync_lock)
+{
+	u8 val = 0;
+	int ret = mxl111sf_demod_read_reg(state, V6_SYNC_LOCK_REG, &val);
+	if (mxl_fail(ret))
+		goto fail;
+	*sync_lock = (val & SYNC_LOCK_MASK) >> 4;
+fail:
+	return ret;
+}
+
+static
+int mxl1x1sf_demod_get_rs_lock_status(struct mxl111sf_demod_state *state,
+				      int *rs_lock)
+{
+	u8 val = 0;
+	int ret = mxl111sf_demod_read_reg(state, V6_RS_LOCK_DET_REG, &val);
+	if (mxl_fail(ret))
+		goto fail;
+	*rs_lock = (val & RS_LOCK_DET_MASK) >> 3;
+fail:
+	return ret;
+}
+
+static
+int mxl1x1sf_demod_get_tps_lock_status(struct mxl111sf_demod_state *state,
+				       int *tps_lock)
+{
+	u8 val = 0;
+	int ret = mxl111sf_demod_read_reg(state, V6_TPS_LOCK_REG, &val);
+	if (mxl_fail(ret))
+		goto fail;
+	*tps_lock = (val & V6_PARAM_TPS_LOCK_MASK) >> 6;
+fail:
+	return ret;
+}
+
+static
+int mxl1x1sf_demod_get_fec_lock_status(struct mxl111sf_demod_state *state,
+				       int *fec_lock)
+{
+	u8 val = 0;
+	int ret = mxl111sf_demod_read_reg(state, V6_IRQ_STATUS_REG, &val);
+	if (mxl_fail(ret))
+		goto fail;
+	*fec_lock = (val & IRQ_MASK_FEC_LOCK) >> 4;
+fail:
+	return ret;
+}
+
+#if 0
+static
+int mxl1x1sf_demod_get_cp_lock_status(struct mxl111sf_demod_state *state,
+				      int *cp_lock)
+{
+	u8 val = 0;
+	int ret = mxl111sf_demod_read_reg(state, V6_CP_LOCK_DET_REG, &val);
+	if (mxl_fail(ret))
+		goto fail;
+	*cp_lock = (val & V6_CP_LOCK_DET_MASK) >> 2;
+fail:
+	return ret;
+}
+#endif
+
+static int mxl1x1sf_demod_reset_irq_status(struct mxl111sf_demod_state *state)
+{
+	return mxl111sf_demod_write_reg(state, 0x0e, 0xff);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_demod_set_frontend(struct dvb_frontend *fe,
+				       struct dvb_frontend_parameters *param)
+{
+	struct mxl111sf_demod_state *state = fe->demodulator_priv;
+	int ret = 0;
+
+	struct mxl111sf_reg_ctrl_info phy_pll_patch[] = {
+		{0x00, 0xff, 0x01}, /* change page to 1 */
+		{0x40, 0xff, 0x05},
+		{0x40, 0xff, 0x01},
+		{0x41, 0xff, 0xca},
+		{0x41, 0xff, 0xc0},
+		{0x00, 0xff, 0x00}, /* change page to 0 */
+		{0,    0,    0}
+	};
+
+	mxl_dbg("()");
+
+	if (fe->ops.tuner_ops.set_params) {
+		ret = fe->ops.tuner_ops.set_params(fe, param);
+		if (mxl_fail(ret))
+			goto fail;
+		msleep(50);
+	}
+	ret = mxl111sf_demod_program_regs(state, phy_pll_patch);
+	mxl_fail(ret);
+	msleep(50);
+	ret = mxl1x1sf_demod_reset_irq_status(state);
+	mxl_fail(ret);
+	msleep(100);
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+#if 0
+/* resets TS Packet error count */
+/* After setting 7th bit of V5_PER_COUNT_RESET_REG, it should be reset to 0. */
+static
+int mxl1x1sf_demod_reset_packet_error_count(struct mxl111sf_demod_state *state)
+{
+	struct mxl111sf_reg_ctrl_info reset_per_count[] = {
+		{0x20, 0x01, 0x01},
+		{0x20, 0x01, 0x00},
+		{0,    0,    0}
+	};
+	return mxl111sf_demod_program_regs(state, reset_per_count);
+}
+#endif
+
+/* returns TS Packet error count */
+/* PER Count = FEC_PER_COUNT * (2 ** (FEC_PER_SCALE * 4)) */
+static int mxl111sf_demod_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct mxl111sf_demod_state *state = fe->demodulator_priv;
+	u32 fec_per_count, fec_per_scale;
+	u8 val;
+	int ret;
+
+	*ucblocks = 0;
+
+	/* FEC_PER_COUNT Register */
+	ret = mxl111sf_demod_read_reg(state, V6_FEC_PER_COUNT_REG, &val);
+	if (mxl_fail(ret))
+		goto fail;
+
+	fec_per_count = val;
+
+	/* FEC_PER_SCALE Register */
+	ret = mxl111sf_demod_read_reg(state, V6_FEC_PER_SCALE_REG, &val);
+	if (mxl_fail(ret))
+		goto fail;
+
+	val &= V6_FEC_PER_SCALE_MASK;
+	val *= 4;
+
+	fec_per_scale = 1 << val;
+
+	fec_per_count *= fec_per_scale;
+
+	*ucblocks = fec_per_count;
+fail:
+	return ret;
+}
+
+#ifdef MXL111SF_DEMOD_ENABLE_CALCULATIONS
+/* FIXME: leaving this enabled breaks the build on some architectures,
+ * and we shouldn't have any floating point math in the kernel, anyway.
+ *
+ * These macros need to be re-written, but it's harmless to simply
+ * return zero for now. */
+#define CALCULATE_BER(avg_errors, count) \
+	((u32)(avg_errors * 4)/(count*64*188*8))
+#define CALCULATE_SNR(data) \
+	((u32)((10 * (u32)data / 64) - 2.5))
+#else
+#define CALCULATE_BER(avg_errors, count) 0
+#define CALCULATE_SNR(data) 0
+#endif
+
+static int mxl111sf_demod_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct mxl111sf_demod_state *state = fe->demodulator_priv;
+	u8 val1, val2, val3;
+	int ret;
+
+	*ber = 0;
+
+	ret = mxl111sf_demod_read_reg(state, V6_RS_AVG_ERRORS_LSB_REG, &val1);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_demod_read_reg(state, V6_RS_AVG_ERRORS_MSB_REG, &val2);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_demod_read_reg(state, V6_N_ACCUMULATE_REG, &val3);
+	if (mxl_fail(ret))
+		goto fail;
+
+	*ber = CALCULATE_BER((val1 | (val2 << 8)), val3);
+fail:
+	return ret;
+}
+
+static int mxl111sf_demod_calc_snr(struct mxl111sf_demod_state *state,
+				   u16 *snr)
+{
+	u8 val1, val2;
+	int ret;
+
+	*snr = 0;
+
+	ret = mxl111sf_demod_read_reg(state, V6_SNR_RB_LSB_REG, &val1);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_demod_read_reg(state, V6_SNR_RB_MSB_REG, &val2);
+	if (mxl_fail(ret))
+		goto fail;
+
+	*snr = CALCULATE_SNR(val1 | ((val2 & 0x03) << 8));
+fail:
+	return ret;
+}
+
+static int mxl111sf_demod_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct mxl111sf_demod_state *state = fe->demodulator_priv;
+
+	int ret = mxl111sf_demod_calc_snr(state, snr);
+	if (mxl_fail(ret))
+		goto fail;
+
+	*snr /= 10; /* 0.1 dB */
+fail:
+	return ret;
+}
+
+static int mxl111sf_demod_read_status(struct dvb_frontend *fe,
+				      fe_status_t *status)
+{
+	struct mxl111sf_demod_state *state = fe->demodulator_priv;
+	int ret, locked, cr_lock, sync_lock, fec_lock;
+
+	*status = 0;
+
+	ret = mxl1x1sf_demod_get_rs_lock_status(state, &locked);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl1x1sf_demod_get_tps_lock_status(state, &cr_lock);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl1x1sf_demod_get_sync_lock_status(state, &sync_lock);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl1x1sf_demod_get_fec_lock_status(state, &fec_lock);
+	if (mxl_fail(ret))
+		goto fail;
+
+	if (locked)
+		*status |= FE_HAS_SIGNAL;
+	if (cr_lock)
+		*status |= FE_HAS_CARRIER;
+	if (sync_lock)
+		*status |= FE_HAS_SYNC;
+	if (fec_lock) /* false positives? */
+		*status |= FE_HAS_VITERBI;
+
+	if ((locked) && (cr_lock) && (sync_lock))
+		*status |= FE_HAS_LOCK;
+fail:
+	return ret;
+}
+
+static int mxl111sf_demod_read_signal_strength(struct dvb_frontend *fe,
+					       u16 *signal_strength)
+{
+	struct mxl111sf_demod_state *state = fe->demodulator_priv;
+	fe_modulation_t constellation;
+	u16 snr;
+
+	mxl111sf_demod_calc_snr(state, &snr);
+	mxl1x1sf_demod_get_tps_constellation(state, &constellation);
+
+	switch (constellation) {
+	case QPSK:
+		*signal_strength = (snr >= 1300) ?
+			min(65535, snr * 44) : snr * 38;
+		break;
+	case QAM_16:
+		*signal_strength = (snr >= 1500) ?
+			min(65535, snr * 38) : snr * 33;
+		break;
+	case QAM_64:
+		*signal_strength = (snr >= 2000) ?
+			min(65535, snr * 29) : snr * 25;
+		break;
+	default:
+		*signal_strength = 0;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe,
+				       struct dvb_frontend_parameters *p)
+{
+	struct mxl111sf_demod_state *state = fe->demodulator_priv;
+
+	mxl_dbg("()");
+#if 0
+	p->inversion = /* FIXME */ ? INVERSION_ON : INVERSION_OFF;
+#endif
+	if (fe->ops.tuner_ops.get_bandwidth)
+		fe->ops.tuner_ops.get_bandwidth(fe, &p->u.ofdm.bandwidth);
+	if (fe->ops.tuner_ops.get_frequency)
+		fe->ops.tuner_ops.get_frequency(fe, &p->frequency);
+	mxl1x1sf_demod_get_tps_code_rate(state, &p->u.ofdm.code_rate_HP);
+	mxl1x1sf_demod_get_tps_code_rate(state, &p->u.ofdm.code_rate_LP);
+	mxl1x1sf_demod_get_tps_constellation(state, &p->u.ofdm.constellation);
+	mxl1x1sf_demod_get_tps_guard_fft_mode(state,
+					      &p->u.ofdm.transmission_mode);
+	mxl1x1sf_demod_get_tps_guard_interval(state,
+					      &p->u.ofdm.guard_interval);
+	mxl1x1sf_demod_get_tps_hierarchy(state,
+					 &p->u.ofdm.hierarchy_information);
+
+	return 0;
+}
+
+static
+int mxl111sf_demod_get_tune_settings(struct dvb_frontend *fe,
+				     struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 1000;
+	return 0;
+}
+
+static void mxl111sf_demod_release(struct dvb_frontend *fe)
+{
+	struct mxl111sf_demod_state *state = fe->demodulator_priv;
+	mxl_dbg("()");
+	kfree(state);
+	fe->demodulator_priv = NULL;
+}
+
+static struct dvb_frontend_ops mxl111sf_demod_ops = {
+
+	.info = {
+		.name               = "MaxLinear MxL111SF DVB-T demodulator",
+		.type               = FE_OFDM,
+		.frequency_min      = 177000000,
+		.frequency_max      = 858000000,
+		.frequency_stepsize = 166666,
+		.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_AUTO |
+			FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
+	},
+	.release              = mxl111sf_demod_release,
+#if 0
+	.init                 = mxl111sf_init,
+	.i2c_gate_ctrl        = mxl111sf_i2c_gate_ctrl,
+#endif
+	.set_frontend         = mxl111sf_demod_set_frontend,
+	.get_frontend         = mxl111sf_demod_get_frontend,
+	.get_tune_settings    = mxl111sf_demod_get_tune_settings,
+	.read_status          = mxl111sf_demod_read_status,
+	.read_signal_strength = mxl111sf_demod_read_signal_strength,
+	.read_ber             = mxl111sf_demod_read_ber,
+	.read_snr             = mxl111sf_demod_read_snr,
+	.read_ucblocks        = mxl111sf_demod_read_ucblocks,
+};
+
+struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
+					   struct mxl111sf_demod_config *cfg)
+{
+	struct mxl111sf_demod_state *state = NULL;
+
+	mxl_dbg("()");
+
+	state = kzalloc(sizeof(struct mxl111sf_demod_state), GFP_KERNEL);
+	if (state == NULL)
+		return NULL;
+
+	state->mxl_state = mxl_state;
+	state->cfg = cfg;
+
+	memcpy(&state->fe.ops, &mxl111sf_demod_ops,
+	       sizeof(struct dvb_frontend_ops));
+
+	state->fe.demodulator_priv = state;
+	return &state->fe;
+}
+EXPORT_SYMBOL_GPL(mxl111sf_demod_attach);
+
+MODULE_DESCRIPTION("MaxLinear MxL111SF DVB-T demodulator driver");
+MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.1");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-demod.h linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-demod.h
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-demod.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-demod.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,55 @@
+/*
+ *  mxl111sf-demod.h - driver for the MaxLinear MXL111SF DVB-T demodulator
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 __MXL111SF_DEMOD_H__
+#define __MXL111SF_DEMOD_H__
+
+#include "dvb_frontend.h"
+#include "mxl111sf.h"
+
+struct mxl111sf_demod_config {
+	int (*read_reg)(struct mxl111sf_state *state, u8 addr, u8 *data);
+	int (*write_reg)(struct mxl111sf_state *state, u8 addr, u8 data);
+	int (*program_regs)(struct mxl111sf_state *state,
+			    struct mxl111sf_reg_ctrl_info *ctrl_reg_info);
+};
+
+#if defined(CONFIG_DVB_USB_MXL111SF) || \
+	(defined(CONFIG_DVB_USB_MXL111SF_MODULE) && defined(MODULE))
+extern
+struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
+					   struct mxl111sf_demod_config *cfg);
+#else
+static inline
+struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
+					   struct mxl111sf_demod_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_USB_MXL111SF */
+
+#endif /* __MXL111SF_DEMOD_H__ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-gpio.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-gpio.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,763 @@
+/*
+ *  mxl111sf-gpio.c - driver for the MaxLinear MXL111SF
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 "mxl111sf-gpio.h"
+#include "mxl111sf-i2c.h"
+#include "mxl111sf.h"
+
+/* ------------------------------------------------------------------------- */
+
+#define MXL_GPIO_MUX_REG_0 0x84
+#define MXL_GPIO_MUX_REG_1 0x89
+#define MXL_GPIO_MUX_REG_2 0x82
+
+#define MXL_GPIO_DIR_INPUT  0
+#define MXL_GPIO_DIR_OUTPUT 1
+
+
+static int mxl111sf_set_gpo_state(struct mxl111sf_state *state, u8 pin, u8 val)
+{
+	int ret;
+	u8 tmp;
+
+	mxl_debug_adv("(%d, %d)", pin, val);
+
+	if ((pin > 0) && (pin < 8)) {
+		ret = mxl111sf_read_reg(state, 0x19, &tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		tmp &= ~(1 << (pin - 1));
+		tmp |= (val << (pin - 1));
+		ret = mxl111sf_write_reg(state, 0x19, tmp);
+		if (mxl_fail(ret))
+			goto fail;
+	} else if (pin <= 10) {
+		if (pin == 0)
+			pin += 7;
+		ret = mxl111sf_read_reg(state, 0x30, &tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		tmp &= ~(1 << (pin - 3));
+		tmp |= (val << (pin - 3));
+		ret = mxl111sf_write_reg(state, 0x30, tmp);
+		if (mxl_fail(ret))
+			goto fail;
+	} else
+		ret = -EINVAL;
+fail:
+	return ret;
+}
+
+static int mxl111sf_get_gpi_state(struct mxl111sf_state *state, u8 pin, u8 *val)
+{
+	int ret;
+	u8 tmp;
+
+	mxl_debug("(0x%02x)", pin);
+
+	*val = 0;
+
+	switch (pin) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+		ret = mxl111sf_read_reg(state, 0x23, &tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		*val = (tmp >> (pin + 4)) & 0x01;
+		break;
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+		ret = mxl111sf_read_reg(state, 0x2f, &tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		*val = (tmp >> pin) & 0x01;
+		break;
+	case 8:
+	case 9:
+	case 10:
+		ret = mxl111sf_read_reg(state, 0x22, &tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		*val = (tmp >> (pin - 3)) & 0x01;
+		break;
+	default:
+		return -EINVAL; /* invalid pin */
+	}
+fail:
+	return ret;
+}
+
+struct mxl_gpio_cfg {
+	u8 pin;
+	u8 dir;
+	u8 val;
+};
+
+static int mxl111sf_config_gpio_pins(struct mxl111sf_state *state,
+				     struct mxl_gpio_cfg *gpio_cfg)
+{
+	int ret;
+	u8 tmp;
+
+	mxl_debug_adv("(%d, %d)", gpio_cfg->pin, gpio_cfg->dir);
+
+	switch (gpio_cfg->pin) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+		ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_0, &tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		tmp &= ~(1 << (gpio_cfg->pin + 4));
+		tmp |= (gpio_cfg->dir << (gpio_cfg->pin + 4));
+		ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_0, tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		break;
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+		ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_1, &tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		tmp &= ~(1 << gpio_cfg->pin);
+		tmp |= (gpio_cfg->dir << gpio_cfg->pin);
+		ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_1, tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		break;
+	case 8:
+	case 9:
+	case 10:
+		ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_2, &tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		tmp &= ~(1 << (gpio_cfg->pin - 3));
+		tmp |= (gpio_cfg->dir << (gpio_cfg->pin - 3));
+		ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_2, tmp);
+		if (mxl_fail(ret))
+			goto fail;
+		break;
+	default:
+		return -EINVAL; /* invalid pin */
+	}
+
+	ret = (MXL_GPIO_DIR_OUTPUT == gpio_cfg->dir) ?
+		mxl111sf_set_gpo_state(state,
+				       gpio_cfg->pin, gpio_cfg->val) :
+		mxl111sf_get_gpi_state(state,
+				       gpio_cfg->pin, &gpio_cfg->val);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+static int mxl111sf_hw_do_set_gpio(struct mxl111sf_state *state,
+				   int gpio, int direction, int val)
+{
+	struct mxl_gpio_cfg gpio_config = {
+		.pin = gpio,
+		.dir = direction,
+		.val = val,
+	};
+
+	mxl_debug("(%d, %d, %d)", gpio, direction, val);
+
+	return mxl111sf_config_gpio_pins(state, &gpio_config);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#define PIN_MUX_MPEG_MODE_MASK          0x40   /* 0x17 <6> */
+#define PIN_MUX_MPEG_PAR_EN_MASK        0x01   /* 0x18 <0> */
+#define PIN_MUX_MPEG_SER_EN_MASK        0x02   /* 0x18 <1> */
+#define PIN_MUX_MPG_IN_MUX_MASK         0x80   /* 0x3D <7> */
+#define PIN_MUX_BT656_ENABLE_MASK       0x04   /* 0x12 <2> */
+#define PIN_MUX_I2S_ENABLE_MASK         0x40   /* 0x15 <6> */
+#define PIN_MUX_SPI_MODE_MASK           0x10   /* 0x3D <4> */
+#define PIN_MUX_MCLK_EN_CTRL_MASK       0x10   /* 0x82 <4> */
+#define PIN_MUX_MPSYN_EN_CTRL_MASK      0x20   /* 0x82 <5> */
+#define PIN_MUX_MDVAL_EN_CTRL_MASK      0x40   /* 0x82 <6> */
+#define PIN_MUX_MPERR_EN_CTRL_MASK      0x80   /* 0x82 <7> */
+#define PIN_MUX_MDAT_EN_0_MASK          0x10   /* 0x84 <4> */
+#define PIN_MUX_MDAT_EN_1_MASK          0x20   /* 0x84 <5> */
+#define PIN_MUX_MDAT_EN_2_MASK          0x40   /* 0x84 <6> */
+#define PIN_MUX_MDAT_EN_3_MASK          0x80   /* 0x84 <7> */
+#define PIN_MUX_MDAT_EN_4_MASK          0x10   /* 0x89 <4> */
+#define PIN_MUX_MDAT_EN_5_MASK          0x20   /* 0x89 <5> */
+#define PIN_MUX_MDAT_EN_6_MASK          0x40   /* 0x89 <6> */
+#define PIN_MUX_MDAT_EN_7_MASK          0x80   /* 0x89 <7> */
+
+int mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state,
+				  enum mxl111sf_mux_config pin_mux_config)
+{
+	u8 r12, r15, r17, r18, r3D, r82, r84, r89;
+	int ret;
+
+	mxl_debug("(%d)", pin_mux_config);
+
+	ret = mxl111sf_read_reg(state, 0x17, &r17);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_read_reg(state, 0x18, &r18);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_read_reg(state, 0x12, &r12);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_read_reg(state, 0x15, &r15);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_read_reg(state, 0x82, &r82);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_read_reg(state, 0x84, &r84);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_read_reg(state, 0x89, &r89);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_read_reg(state, 0x3D, &r3D);
+	if (mxl_fail(ret))
+		goto fail;
+
+	switch (pin_mux_config) {
+	case PIN_MUX_TS_OUT_PARALLEL:
+		/* mpeg_mode = 1 */
+		r17 |= PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 1 */
+		r18 |= PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 0 */
+		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 0 */
+		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 0 */
+		r3D &= ~PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 1 */
+		r82 |= PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 1 */
+		r82 |= PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 1 */
+		r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 1 */
+		r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0xF */
+		r84 |= 0xF0;
+		/* mdat_en_ctrl[7:4] = 0xF */
+		r89 |= 0xF0;
+		break;
+	case PIN_MUX_TS_OUT_SERIAL:
+		/* mpeg_mode = 1 */
+		r17 |= PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 1 */
+		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 0 */
+		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 0 */
+		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 0 */
+		r3D &= ~PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 1 */
+		r82 |= PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 1 */
+		r82 |= PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 1 */
+		r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 1 */
+		r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0xF */
+		r84 |= 0xF0;
+		/* mdat_en_ctrl[7:4] = 0xF */
+		r89 |= 0xF0;
+		break;
+	case PIN_MUX_GPIO_MODE:
+		/* mpeg_mode = 0 */
+		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 0 */
+		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 0 */
+		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 0 */
+		r3D &= ~PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0x0 */
+		r84 &= 0x0F;
+		/* mdat_en_ctrl[7:4] = 0x0 */
+		r89 &= 0x0F;
+		break;
+	case PIN_MUX_TS_SERIAL_IN_MODE_0:
+		/* mpeg_mode = 0 */
+		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 1 */
+		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 0 */
+		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 0 */
+		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 0 */
+		r3D &= ~PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0x0 */
+		r84 &= 0x0F;
+		/* mdat_en_ctrl[7:4] = 0x0 */
+		r89 &= 0x0F;
+		break;
+	case PIN_MUX_TS_SERIAL_IN_MODE_1:
+		/* mpeg_mode = 0 */
+		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 1 */
+		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 1 */
+		r3D |= PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 0 */
+		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 0 */
+		r3D &= ~PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0x0 */
+		r84 &= 0x0F;
+		/* mdat_en_ctrl[7:4] = 0x0 */
+		r89 &= 0x0F;
+		break;
+	case PIN_MUX_TS_SPI_IN_MODE_1:
+		/* mpeg_mode = 0 */
+		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 1 */
+		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 1 */
+		r3D |= PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 1 */
+		r15 |= PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 1 */
+		r3D |= PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0x0 */
+		r84 &= 0x0F;
+		/* mdat_en_ctrl[7:4] = 0x0 */
+		r89 &= 0x0F;
+		break;
+	case PIN_MUX_TS_SPI_IN_MODE_0:
+		/* mpeg_mode = 0 */
+		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 1 */
+		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 0 */
+		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 1 */
+		r15 |= PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 1 */
+		r3D |= PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0x0 */
+		r84 &= 0x0F;
+		/* mdat_en_ctrl[7:4] = 0x0 */
+		r89 &= 0x0F;
+		break;
+	case PIN_MUX_TS_PARALLEL_IN:
+		/* mpeg_mode = 0 */
+		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 1 */
+		r18 |= PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 0 */
+		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 0 */
+		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 0 */
+		r3D &= ~PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0x0 */
+		r84 &= 0x0F;
+		/* mdat_en_ctrl[7:4] = 0x0 */
+		r89 &= 0x0F;
+		break;
+	case PIN_MUX_BT656_I2S_MODE:
+		/* mpeg_mode = 0 */
+		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 0 */
+		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 1 */
+		r12 |= PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 1 */
+		r15 |= PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 0 */
+		r3D &= ~PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0x0 */
+		r84 &= 0x0F;
+		/* mdat_en_ctrl[7:4] = 0x0 */
+		r89 &= 0x0F;
+		break;
+	case PIN_MUX_DEFAULT:
+	default:
+		/* mpeg_mode = 1 */
+		r17 |= PIN_MUX_MPEG_MODE_MASK;
+		/* mpeg_par_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
+		/* mpeg_ser_en = 0 */
+		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
+		/* mpg_in_mux = 0 */
+		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
+		/* bt656_enable = 0 */
+		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
+		/* i2s_enable = 0 */
+		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
+		/* spi_mode = 0 */
+		r3D &= ~PIN_MUX_SPI_MODE_MASK;
+		/* mclk_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
+		/* mperr_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
+		/* mdval_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
+		/* mpsyn_en_ctrl = 0 */
+		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
+		/* mdat_en_ctrl[3:0] = 0x0 */
+		r84 &= 0x0F;
+		/* mdat_en_ctrl[7:4] = 0x0 */
+		r89 &= 0x0F;
+		break;
+	}
+
+	ret = mxl111sf_write_reg(state, 0x17, r17);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_write_reg(state, 0x18, r18);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_write_reg(state, 0x12, r12);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_write_reg(state, 0x15, r15);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_write_reg(state, 0x82, r82);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_write_reg(state, 0x84, r84);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_write_reg(state, 0x89, r89);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_write_reg(state, 0x3D, r3D);
+	if (mxl_fail(ret))
+		goto fail;
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int mxl111sf_hw_set_gpio(struct mxl111sf_state *state, int gpio, int val)
+{
+	return mxl111sf_hw_do_set_gpio(state, gpio, MXL_GPIO_DIR_OUTPUT, val);
+}
+
+static int mxl111sf_hw_gpio_initialize(struct mxl111sf_state *state)
+{
+	u8 gpioval = 0x07; /* write protect enabled, signal LEDs off */
+	int i, ret;
+
+	mxl_debug("()");
+
+	for (i = 3; i < 8; i++) {
+		ret = mxl111sf_hw_set_gpio(state, i, (gpioval >> i) & 0x01);
+		if (mxl_fail(ret))
+			break;
+	}
+
+	return ret;
+}
+
+#define PCA9534_I2C_ADDR (0x40 >> 1)
+static int pca9534_set_gpio(struct mxl111sf_state *state, int gpio, int val)
+{
+	u8 w[2] = { 1, 0 };
+	u8 r = 0;
+	struct i2c_msg msg[] = {
+		{ .addr = PCA9534_I2C_ADDR,
+		  .flags = 0, .buf = w, .len = 1 },
+		{ .addr = PCA9534_I2C_ADDR,
+		  .flags = I2C_M_RD, .buf = &r, .len = 1 },
+	};
+
+	mxl_debug("(%d, %d)", gpio, val);
+
+	/* read current GPIO levels from flip-flop */
+	i2c_transfer(&state->d->i2c_adap, msg, 2);
+
+	/* prepare write buffer with current GPIO levels */
+	msg[0].len = 2;
+#if 0
+	w[0] = 1;
+#endif
+	w[1] = r;
+
+	/* clear the desired GPIO */
+	w[1] &= ~(1 << gpio);
+
+	/* set the desired GPIO value */
+	w[1] |= ((val ? 1 : 0) << gpio);
+
+	/* write new GPIO levels to flip-flop */
+	i2c_transfer(&state->d->i2c_adap, &msg[0], 1);
+
+	return 0;
+}
+
+static int pca9534_init_port_expander(struct mxl111sf_state *state)
+{
+	u8 w[2] = { 1, 0x07 }; /* write protect enabled, signal LEDs off */
+
+	struct i2c_msg msg = {
+		.addr = PCA9534_I2C_ADDR,
+		.flags = 0, .buf = w, .len = 2
+	};
+
+	mxl_debug("()");
+
+	i2c_transfer(&state->d->i2c_adap, &msg, 1);
+
+	/* configure all pins as outputs */
+	w[0] = 3;
+	w[1] = 0;
+
+	i2c_transfer(&state->d->i2c_adap, &msg, 1);
+
+	return 0;
+}
+
+int mxl111sf_set_gpio(struct mxl111sf_state *state, int gpio, int val)
+{
+	mxl_debug("(%d, %d)", gpio, val);
+
+	switch (state->gpio_port_expander) {
+	default:
+		mxl_printk(KERN_ERR,
+			   "gpio_port_expander undefined, assuming PCA9534");
+		/* fall-thru */
+	case mxl111sf_PCA9534:
+		return pca9534_set_gpio(state, gpio, val);
+	case mxl111sf_gpio_hw:
+		return mxl111sf_hw_set_gpio(state, gpio, val);
+	}
+}
+
+static int mxl111sf_probe_port_expander(struct mxl111sf_state *state)
+{
+	int ret;
+	u8 w = 1;
+	u8 r = 0;
+	struct i2c_msg msg[] = {
+		{ .flags = 0,        .buf = &w, .len = 1 },
+		{ .flags = I2C_M_RD, .buf = &r, .len = 1 },
+	};
+
+	mxl_debug("()");
+
+	msg[0].addr = 0x70 >> 1;
+	msg[1].addr = 0x70 >> 1;
+
+	/* read current GPIO levels from flip-flop */
+	ret = i2c_transfer(&state->d->i2c_adap, msg, 2);
+	if (ret == 2) {
+		state->port_expander_addr = msg[0].addr;
+		state->gpio_port_expander = mxl111sf_PCA9534;
+		mxl_debug("found port expander at 0x%02x",
+			  state->port_expander_addr);
+		return 0;
+	}
+
+	msg[0].addr = 0x40 >> 1;
+	msg[1].addr = 0x40 >> 1;
+
+	ret = i2c_transfer(&state->d->i2c_adap, msg, 2);
+	if (ret == 2) {
+		state->port_expander_addr = msg[0].addr;
+		state->gpio_port_expander = mxl111sf_PCA9534;
+		mxl_debug("found port expander at 0x%02x",
+			  state->port_expander_addr);
+		return 0;
+	}
+	state->port_expander_addr = 0xff;
+	state->gpio_port_expander = mxl111sf_gpio_hw;
+	mxl_debug("using hardware gpio");
+	return 0;
+}
+
+int mxl111sf_init_port_expander(struct mxl111sf_state *state)
+{
+	mxl_debug("()");
+
+	if (0x00 == state->port_expander_addr)
+		mxl111sf_probe_port_expander(state);
+
+	switch (state->gpio_port_expander) {
+	default:
+		mxl_printk(KERN_ERR,
+			   "gpio_port_expander undefined, assuming PCA9534");
+		/* fall-thru */
+	case mxl111sf_PCA9534:
+		return pca9534_init_port_expander(state);
+	case mxl111sf_gpio_hw:
+		return mxl111sf_hw_gpio_initialize(state);
+	}
+}
+
+/* ------------------------------------------------------------------------ */
+
+int mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode)
+{
+/*	GPO:
+ *	3 - ATSC/MH#   | 1 = ATSC transport, 0 = MH transport      | default 0
+ *	4 - ATSC_RST## | 1 = ATSC enable, 0 = ATSC Reset           | default 0
+ *	5 - ATSC_EN    | 1 = ATSC power enable, 0 = ATSC power off | default 0
+ *	6 - MH_RESET#  | 1 = MH enable, 0 = MH Reset               | default 0
+ *	7 - MH_EN      | 1 = MH power enable, 0 = MH power off     | default 0
+ */
+	mxl_debug("(%d)", mode);
+
+	switch (mode) {
+	case MXL111SF_GPIO_MOD_MH:
+		mxl111sf_set_gpio(state, 4, 0);
+		mxl111sf_set_gpio(state, 5, 0);
+		msleep(50);
+		mxl111sf_set_gpio(state, 7, 1);
+		msleep(50);
+		mxl111sf_set_gpio(state, 6, 1);
+		msleep(50);
+
+		mxl111sf_set_gpio(state, 3, 0);
+		break;
+	case MXL111SF_GPIO_MOD_ATSC:
+		mxl111sf_set_gpio(state, 6, 0);
+		mxl111sf_set_gpio(state, 7, 0);
+		msleep(50);
+		mxl111sf_set_gpio(state, 5, 1);
+		msleep(50);
+		mxl111sf_set_gpio(state, 4, 1);
+		msleep(50);
+		mxl111sf_set_gpio(state, 3, 1);
+		break;
+	default: /* DVBT / STANDBY */
+		mxl111sf_init_port_expander(state);
+		break;
+	}
+	return 0;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-gpio.h linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-gpio.h
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-gpio.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,56 @@
+/*
+ *  mxl111sf-gpio.h - driver for the MaxLinear MXL111SF
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 _DVB_USB_MXL111SF_GPIO_H_
+#define _DVB_USB_MXL111SF_GPIO_H_
+
+#include "mxl111sf.h"
+
+int mxl111sf_set_gpio(struct mxl111sf_state *state, int gpio, int val);
+int mxl111sf_init_port_expander(struct mxl111sf_state *state);
+
+#define MXL111SF_GPIO_MOD_DVBT	0
+#define MXL111SF_GPIO_MOD_MH	1
+#define MXL111SF_GPIO_MOD_ATSC	2
+int mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode);
+
+enum mxl111sf_mux_config {
+	PIN_MUX_DEFAULT = 0,
+	PIN_MUX_TS_OUT_PARALLEL,
+	PIN_MUX_TS_OUT_SERIAL,
+	PIN_MUX_GPIO_MODE,
+	PIN_MUX_TS_SERIAL_IN_MODE_0,
+	PIN_MUX_TS_SERIAL_IN_MODE_1,
+	PIN_MUX_TS_SPI_IN_MODE_0,
+	PIN_MUX_TS_SPI_IN_MODE_1,
+	PIN_MUX_TS_PARALLEL_IN,
+	PIN_MUX_BT656_I2S_MODE,
+};
+
+int mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state,
+				  enum mxl111sf_mux_config pin_mux_config);
+
+#endif /* _DVB_USB_MXL111SF_GPIO_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf.h linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf.h
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.com)
+ *
+ *   This program is free software; you can redistribute it and/or modify it
+ *   under the terms of the GNU General Public License as published by the Free
+ *   Software Foundation, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+
+#ifndef _DVB_USB_MXL111SF_H_
+#define _DVB_USB_MXL111SF_H_
+
+#ifdef DVB_USB_LOG_PREFIX
+#undef DVB_USB_LOG_PREFIX
+#endif
+#define DVB_USB_LOG_PREFIX "mxl111sf"
+#include "dvb-usb.h"
+#include <media/tveeprom.h>
+
+#define MXL_EP1_REG_READ     1
+#define MXL_EP2_REG_WRITE    2
+#define MXL_EP3_INTERRUPT    3
+#define MXL_EP4_MPEG2        4
+#define MXL_EP5_I2S          5
+#define MXL_EP6_656          6
+#define MXL_EP6_MPEG2        6
+
+#ifdef USING_ENUM_mxl111sf_current_mode
+enum mxl111sf_current_mode {
+	mxl_mode_dvbt = MXL_EP4_MPEG2,
+	mxl_mode_mh   = MXL_EP5_I2S,
+	mxl_mode_atsc = MXL_EP6_MPEG2,
+};
+#endif
+
+enum mxl111sf_gpio_port_expander {
+	mxl111sf_gpio_hw,
+	mxl111sf_PCA9534,
+};
+
+struct mxl111sf_state {
+	struct dvb_usb_device *d;
+
+	enum mxl111sf_gpio_port_expander gpio_port_expander;
+	u8 port_expander_addr;
+
+	u8 chip_id;
+	u8 chip_ver;
+#define MXL111SF_V6     1
+#define MXL111SF_V8_100 2
+#define MXL111SF_V8_200 3
+	u8 chip_rev;
+
+#ifdef USING_ENUM_mxl111sf_current_mode
+	enum mxl111sf_current_mode current_mode;
+#endif
+
+#define MXL_TUNER_MODE         0
+#define MXL_SOC_MODE           1
+#define MXL_DEV_MODE_MASK      0x01
+#if 1
+	int device_mode;
+#endif
+	/* use usb alt setting 1 for EP4 ISOC transfer (dvb-t),
+				     EP5 BULK transfer (atsc-mh),
+				     EP6 BULK transfer (atsc/qam),
+	   use usb alt setting 2 for EP4 BULK transfer (dvb-t),
+				     EP5 ISOC transfer (atsc-mh),
+				     EP6 ISOC transfer (atsc/qam),
+	 */
+	int alt_mode;
+	int gpio_mode;
+	struct tveeprom tv;
+
+	struct mutex fe_lock;
+};
+
+struct mxl111sf_adap_state {
+	int alt_mode;
+	int gpio_mode;
+	int device_mode;
+	int ep6_clockphase;
+	int (*fe_init)(struct dvb_frontend *);
+	int (*fe_sleep)(struct dvb_frontend *);
+};
+
+int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data);
+int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data);
+
+struct mxl111sf_reg_ctrl_info {
+	u8 addr;
+	u8 mask;
+	u8 data;
+};
+
+int mxl111sf_write_reg_mask(struct mxl111sf_state *state,
+			    u8 addr, u8 mask, u8 data);
+int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state,
+			       struct mxl111sf_reg_ctrl_info *ctrl_reg_info);
+
+/* needed for hardware i2c functions in mxl111sf-i2c.c:
+ * mxl111sf_i2c_send_data / mxl111sf_i2c_get_data */
+int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
+		      u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen);
+
+#define mxl_printk(kern, fmt, arg...) \
+	printk(kern "%s: " fmt "\n", __func__, ##arg)
+
+#define mxl_info(fmt, arg...) \
+	mxl_printk(KERN_INFO, fmt, ##arg)
+
+extern int dvb_usb_mxl111sf_debug;
+#define mxl_debug(fmt, arg...) \
+	if (dvb_usb_mxl111sf_debug) \
+		mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+#define MXL_I2C_DBG 0x04
+#define MXL_ADV_DBG 0x10
+#define mxl_debug_adv(fmt, arg...) \
+	if (dvb_usb_mxl111sf_debug & MXL_ADV_DBG) \
+		mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+#define mxl_i2c(fmt, arg...) \
+	if (dvb_usb_mxl111sf_debug & MXL_I2C_DBG) \
+		mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+#define mxl_i2c_adv(fmt, arg...) \
+	if ((dvb_usb_mxl111sf_debug & (MXL_I2C_DBG | MXL_ADV_DBG)) == \
+		(MXL_I2C_DBG | MXL_ADV_DBG)) \
+			mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+/* The following allows the mxl_fail() macro defined below to work
+ * in externel modules, such as mxl111sf-tuner.ko, even though
+ * dvb_usb_mxl111sf_debug is not defined within those modules */
+#if (defined(__MXL111SF_TUNER_H__)) || (defined(__MXL111SF_DEMOD_H__))
+#define MXL_ADV_DEBUG_ENABLED MXL_ADV_DBG
+#else
+#define MXL_ADV_DEBUG_ENABLED dvb_usb_mxl111sf_debug
+#endif
+
+#define mxl_fail(ret)							\
+({									\
+	int __ret;							\
+	__ret = (ret < 0);						\
+	if ((__ret) && (MXL_ADV_DEBUG_ENABLED & MXL_ADV_DBG))		\
+		mxl_printk(KERN_ERR, "error %d on line %d",		\
+			   ret, __LINE__);				\
+	__ret;								\
+})
+
+#endif /* _DVB_USB_MXL111SF_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,850 @@
+/*
+ *  mxl111sf-i2c.c - driver for the MaxLinear MXL111SF
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 "mxl111sf-i2c.h"
+#include "mxl111sf.h"
+
+/* SW-I2C ----------------------------------------------------------------- */
+
+#define SW_I2C_ADDR		0x1a
+#define SW_I2C_EN		0x02
+#define SW_SCL_OUT		0x04
+#define SW_SDA_OUT		0x08
+#define SW_SDA_IN		0x04
+
+#define SW_I2C_BUSY_ADDR	0x2f
+#define SW_I2C_BUSY		0x02
+
+static int mxl111sf_i2c_bitbang_sendbyte(struct mxl111sf_state *state,
+					 u8 byte)
+{
+	int i, ret;
+	u8 data = 0;
+
+	mxl_i2c("(0x%02x)", byte);
+
+	ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data);
+	if (mxl_fail(ret))
+		goto fail;
+
+	for (i = 0; i < 8; i++) {
+
+		data = (byte & (0x80 >> i)) ? SW_SDA_OUT : 0;
+
+		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+					 0x10 | SW_I2C_EN | data);
+		if (mxl_fail(ret))
+			goto fail;
+
+		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+					 0x10 | SW_I2C_EN | data | SW_SCL_OUT);
+		if (mxl_fail(ret))
+			goto fail;
+
+		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+					 0x10 | SW_I2C_EN | data);
+		if (mxl_fail(ret))
+			goto fail;
+	}
+
+	/* last bit was 0 so we need to release SDA */
+	if (!(byte & 1)) {
+		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+					 0x10 | SW_I2C_EN | SW_SDA_OUT);
+		if (mxl_fail(ret))
+			goto fail;
+	}
+
+	/* CLK high for ACK readback */
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data);
+	if (mxl_fail(ret))
+		goto fail;
+
+	/* drop the CLK after getting ACK, SDA will go high right away */
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SDA_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	if (data & SW_SDA_IN)
+		ret = -EIO;
+fail:
+	return ret;
+}
+
+static int mxl111sf_i2c_bitbang_recvbyte(struct mxl111sf_state *state,
+					 u8 *pbyte)
+{
+	int i, ret;
+	u8 byte = 0;
+	u8 data = 0;
+
+	mxl_i2c("()");
+
+	*pbyte = 0;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SDA_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	for (i = 0; i < 8; i++) {
+		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+					 0x10 | SW_I2C_EN |
+					 SW_SCL_OUT | SW_SDA_OUT);
+		if (mxl_fail(ret))
+			goto fail;
+
+		ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data);
+		if (mxl_fail(ret))
+			goto fail;
+
+		if (data & SW_SDA_IN)
+			byte |= (0x80 >> i);
+
+		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+					 0x10 | SW_I2C_EN | SW_SDA_OUT);
+		if (mxl_fail(ret))
+			goto fail;
+	}
+	*pbyte = byte;
+fail:
+	return ret;
+}
+
+static int mxl111sf_i2c_start(struct mxl111sf_state *state)
+{
+	int ret;
+
+	mxl_i2c("()");
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SCL_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN); /* start */
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+static int mxl111sf_i2c_stop(struct mxl111sf_state *state)
+{
+	int ret;
+
+	mxl_i2c("()");
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN); /* stop */
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SCL_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_SCL_OUT | SW_SDA_OUT);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+static int mxl111sf_i2c_ack(struct mxl111sf_state *state)
+{
+	int ret;
+	u8 b = 0;
+
+	mxl_i2c("()");
+
+	ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &b);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN);
+	if (mxl_fail(ret))
+		goto fail;
+
+	/* pull SDA low */
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SCL_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SDA_OUT);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+static int mxl111sf_i2c_nack(struct mxl111sf_state *state)
+{
+	int ret;
+
+	mxl_i2c("()");
+
+	/* SDA high to signal last byte read from slave */
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
+				 0x10 | SW_I2C_EN | SW_SDA_OUT);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_i2c_sw_xfer_msg(struct mxl111sf_state *state,
+				    struct i2c_msg *msg)
+{
+	int i, ret;
+
+	mxl_i2c("()");
+
+	if (msg->flags & I2C_M_RD) {
+
+		ret = mxl111sf_i2c_start(state);
+		if (mxl_fail(ret))
+			goto fail;
+
+		ret = mxl111sf_i2c_bitbang_sendbyte(state,
+						    (msg->addr << 1) | 0x01);
+		if (mxl_fail(ret)) {
+			mxl111sf_i2c_stop(state);
+			goto fail;
+		}
+
+		for (i = 0; i < msg->len; i++) {
+			ret = mxl111sf_i2c_bitbang_recvbyte(state,
+							    &msg->buf[i]);
+			if (mxl_fail(ret)) {
+				mxl111sf_i2c_stop(state);
+				goto fail;
+			}
+
+			if (i < msg->len - 1)
+				mxl111sf_i2c_ack(state);
+		}
+
+		mxl111sf_i2c_nack(state);
+
+		ret = mxl111sf_i2c_stop(state);
+		if (mxl_fail(ret))
+			goto fail;
+
+	} else {
+
+		ret = mxl111sf_i2c_start(state);
+		if (mxl_fail(ret))
+			goto fail;
+
+		ret = mxl111sf_i2c_bitbang_sendbyte(state,
+						    (msg->addr << 1) & 0xfe);
+		if (mxl_fail(ret)) {
+			mxl111sf_i2c_stop(state);
+			goto fail;
+		}
+
+		for (i = 0; i < msg->len; i++) {
+			ret = mxl111sf_i2c_bitbang_sendbyte(state,
+							    msg->buf[i]);
+			if (mxl_fail(ret)) {
+				mxl111sf_i2c_stop(state);
+				goto fail;
+			}
+		}
+
+		/* FIXME: we only want to do this on the last transaction */
+		mxl111sf_i2c_stop(state);
+	}
+fail:
+	return ret;
+}
+
+/* HW-I2C ----------------------------------------------------------------- */
+
+#define USB_WRITE_I2C_CMD     0x99
+#define USB_READ_I2C_CMD      0xdd
+#define USB_END_I2C_CMD       0xfe
+
+#define USB_WRITE_I2C_CMD_LEN   26
+#define USB_READ_I2C_CMD_LEN    24
+
+#define I2C_MUX_REG           0x30
+#define I2C_CONTROL_REG       0x00
+#define I2C_SLAVE_ADDR_REG    0x08
+#define I2C_DATA_REG          0x0c
+#define I2C_INT_STATUS_REG    0x10
+
+static int mxl111sf_i2c_send_data(struct mxl111sf_state *state,
+				  u8 index, u8 *wdata)
+{
+	int ret = mxl111sf_ctrl_msg(state->d, wdata[0],
+				    &wdata[1], 25, NULL, 0);
+	mxl_fail(ret);
+
+	return ret;
+}
+
+static int mxl111sf_i2c_get_data(struct mxl111sf_state *state,
+				 u8 index, u8 *wdata, u8 *rdata)
+{
+	int ret = mxl111sf_ctrl_msg(state->d, wdata[0],
+				    &wdata[1], 25, rdata, 24);
+	mxl_fail(ret);
+
+	return ret;
+}
+
+static u8 mxl111sf_i2c_check_status(struct mxl111sf_state *state)
+{
+	u8 status = 0;
+	u8 buf[26];
+
+	mxl_i2c_adv("()");
+
+	buf[0] = USB_READ_I2C_CMD;
+	buf[1] = 0x00;
+
+	buf[2] = I2C_INT_STATUS_REG;
+	buf[3] = 0x00;
+	buf[4] = 0x00;
+
+	buf[5] = USB_END_I2C_CMD;
+
+	mxl111sf_i2c_get_data(state, 0, buf, buf);
+
+	if (buf[1] & 0x04)
+		status = 1;
+
+	return status;
+}
+
+static u8 mxl111sf_i2c_check_fifo(struct mxl111sf_state *state)
+{
+	u8 status = 0;
+	u8 buf[26];
+
+	mxl_i2c("()");
+
+	buf[0] = USB_READ_I2C_CMD;
+	buf[1] = 0x00;
+
+	buf[2] = I2C_MUX_REG;
+	buf[3] = 0x00;
+	buf[4] = 0x00;
+
+	buf[5] = I2C_INT_STATUS_REG;
+	buf[6] = 0x00;
+	buf[7] = 0x00;
+	buf[8] = USB_END_I2C_CMD;
+
+	mxl111sf_i2c_get_data(state, 0, buf, buf);
+
+	if (0x08 == (buf[1] & 0x08))
+		status = 1;
+
+	if ((buf[5] & 0x02) == 0x02)
+		mxl_i2c("(buf[5] & 0x02) == 0x02"); /* FIXME */
+
+	return status;
+}
+
+static int mxl111sf_i2c_readagain(struct mxl111sf_state *state,
+				  u8 count, u8 *rbuf)
+{
+	u8 i2c_w_data[26];
+	u8 i2c_r_data[24];
+	u8 i = 0;
+	u8 fifo_status = 0;
+	int status = 0;
+
+	mxl_i2c("read %d bytes", count);
+
+	while ((fifo_status == 0) && (i++ < 5))
+		fifo_status = mxl111sf_i2c_check_fifo(state);
+
+	i2c_w_data[0] = 0xDD;
+	i2c_w_data[1] = 0x00;
+
+	for (i = 2; i < 26; i++)
+		i2c_w_data[i] = 0xFE;
+
+	for (i = 0; i < count; i++) {
+		i2c_w_data[2+(i*3)] = 0x0C;
+		i2c_w_data[3+(i*3)] = 0x00;
+		i2c_w_data[4+(i*3)] = 0x00;
+	}
+
+	mxl111sf_i2c_get_data(state, 0, i2c_w_data, i2c_r_data);
+
+	/* Check for I2C NACK status */
+	if (mxl111sf_i2c_check_status(state) == 1) {
+		mxl_i2c("error!");
+	} else {
+		for (i = 0; i < count; i++) {
+			rbuf[i] = i2c_r_data[(i*3)+1];
+			mxl_i2c("%02x\t %02x",
+				i2c_r_data[(i*3)+1],
+				i2c_r_data[(i*3)+2]);
+		}
+
+		status = 1;
+	}
+
+	return status;
+}
+
+#define HWI2C400 1
+static int mxl111sf_i2c_hw_xfer_msg(struct mxl111sf_state *state,
+				    struct i2c_msg *msg)
+{
+	int i, k, ret = 0;
+	u16 index = 0;
+	u8 buf[26];
+	u8 i2c_r_data[24];
+	u16 block_len;
+	u16 left_over_len;
+	u8 rd_status[8];
+	u8 ret_status;
+	u8 readbuff[26];
+
+	mxl_i2c("addr: 0x%02x, read buff len: %d, write buff len: %d",
+		msg->addr, (msg->flags & I2C_M_RD) ? msg->len : 0,
+		(!(msg->flags & I2C_M_RD)) ? msg->len : 0);
+
+	for (index = 0; index < 26; index++)
+		buf[index] = USB_END_I2C_CMD;
+
+	/* command to indicate data payload is destined for I2C interface */
+	buf[0] = USB_WRITE_I2C_CMD;
+	buf[1] = 0x00;
+
+	/* enable I2C interface */
+	buf[2] = I2C_MUX_REG;
+	buf[3] = 0x80;
+	buf[4] = 0x00;
+
+	/* enable I2C interface */
+	buf[5] = I2C_MUX_REG;
+	buf[6] = 0x81;
+	buf[7] = 0x00;
+
+	/* set Timeout register on I2C interface */
+	buf[8] = 0x14;
+	buf[9] = 0xff;
+	buf[10] = 0x00;
+#if 0
+	/* enable Interrupts on I2C interface */
+	buf[8] = 0x24;
+	buf[9] = 0xF7;
+	buf[10] = 0x00;
+#endif
+	buf[11] = 0x24;
+	buf[12] = 0xF7;
+	buf[13] = 0x00;
+
+	ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+	/* write data on I2C bus */
+	if (!(msg->flags & I2C_M_RD) && (msg->len > 0)) {
+		mxl_i2c("%d\t%02x", msg->len, msg->buf[0]);
+
+		/* control register on I2C interface to initialize I2C bus */
+		buf[2] = I2C_CONTROL_REG;
+		buf[3] = 0x5E;
+		buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+
+		/* I2C Slave device Address */
+		buf[5] = I2C_SLAVE_ADDR_REG;
+		buf[6] = (msg->addr);
+		buf[7] = 0x00;
+		buf[8] = USB_END_I2C_CMD;
+		ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+		/* check for slave device status */
+		if (mxl111sf_i2c_check_status(state) == 1) {
+			mxl_i2c("NACK writing slave address %02x",
+				msg->addr);
+			/* if NACK, stop I2C bus and exit */
+			buf[2] = I2C_CONTROL_REG;
+			buf[3] = 0x4E;
+			buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+			ret = -EIO;
+			goto exit;
+		}
+
+		/* I2C interface can do I2C operations in block of 8 bytes of
+		   I2C data. calculation to figure out number of blocks of i2c
+		   data required to program */
+		block_len = (msg->len / 8);
+		left_over_len = (msg->len % 8);
+		index = 0;
+
+		mxl_i2c("block_len %d, left_over_len %d",
+			block_len, left_over_len);
+
+		for (index = 0; index < block_len; index++) {
+			for (i = 0; i < 8; i++) {
+				/* write data on I2C interface */
+				buf[2+(i*3)] = I2C_DATA_REG;
+				buf[3+(i*3)] = msg->buf[(index*8)+i];
+				buf[4+(i*3)] = 0x00;
+			}
+
+			ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+			/* check for I2C NACK status */
+			if (mxl111sf_i2c_check_status(state) == 1) {
+				mxl_i2c("NACK writing slave address %02x",
+					msg->addr);
+
+				/* if NACK, stop I2C bus and exit */
+				buf[2] = I2C_CONTROL_REG;
+				buf[3] = 0x4E;
+				buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+				ret = -EIO;
+				goto exit;
+			}
+
+		}
+
+		if (left_over_len) {
+			for (k = 0; k < 26; k++)
+				buf[k] = USB_END_I2C_CMD;
+
+			buf[0] = 0x99;
+			buf[1] = 0x00;
+
+			for (i = 0; i < left_over_len; i++) {
+				buf[2+(i*3)] = I2C_DATA_REG;
+				buf[3+(i*3)] = msg->buf[(index*8)+i];
+				mxl_i2c("index = %d %d data %d",
+					index, i, msg->buf[(index*8)+i]);
+				buf[4+(i*3)] = 0x00;
+			}
+			ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+			/* check for I2C NACK status */
+			if (mxl111sf_i2c_check_status(state) == 1) {
+				mxl_i2c("NACK writing slave address %02x",
+					msg->addr);
+
+				/* if NACK, stop I2C bus and exit */
+				buf[2] = I2C_CONTROL_REG;
+				buf[3] = 0x4E;
+				buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+				ret = -EIO;
+				goto exit;
+			}
+
+		}
+
+		/* issue I2C STOP after write */
+		buf[2] = I2C_CONTROL_REG;
+		buf[3] = 0x4E;
+		buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+
+	}
+
+	/* read data from I2C bus */
+	if ((msg->flags & I2C_M_RD) && (msg->len > 0)) {
+		mxl_i2c("read buf len %d", msg->len);
+
+		/* command to indicate data payload is
+		   destined for I2C interface */
+		buf[2] = I2C_CONTROL_REG;
+		buf[3] = 0xDF;
+		buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+
+		/* I2C xfer length */
+		buf[5] = 0x14;
+		buf[6] = (msg->len & 0xFF);
+		buf[7] = 0;
+
+		/* I2C slave device Address */
+		buf[8] = I2C_SLAVE_ADDR_REG;
+		buf[9] = msg->addr;
+		buf[10] = 0x00;
+		buf[11] = USB_END_I2C_CMD;
+		ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+		/* check for I2C NACK status */
+		if (mxl111sf_i2c_check_status(state) == 1) {
+			mxl_i2c("NACK reading slave address %02x",
+				msg->addr);
+
+			/* if NACK, stop I2C bus and exit */
+			buf[2] = I2C_CONTROL_REG;
+			buf[3] = 0xC7;
+			buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+			ret = -EIO;
+			goto exit;
+		}
+
+		/* I2C interface can do I2C operations in block of 8 bytes of
+		   I2C data. calculation to figure out number of blocks of
+		   i2c data required to program */
+		block_len = ((msg->len) / 8);
+		left_over_len = ((msg->len) % 8);
+		index = 0;
+
+		mxl_i2c("block_len %d, left_over_len %d",
+			block_len, left_over_len);
+
+		/* command to read data from I2C interface */
+		buf[0] = USB_READ_I2C_CMD;
+		buf[1] = 0x00;
+
+		for (index = 0; index < block_len; index++) {
+			/* setup I2C read request packet on I2C interface */
+			for (i = 0; i < 8; i++) {
+				buf[2+(i*3)] = I2C_DATA_REG;
+				buf[3+(i*3)] = 0x00;
+				buf[4+(i*3)] = 0x00;
+			}
+
+			ret = mxl111sf_i2c_get_data(state, 0, buf, i2c_r_data);
+
+			/* check for I2C NACK status */
+			if (mxl111sf_i2c_check_status(state) == 1) {
+				mxl_i2c("NACK reading slave address %02x",
+					msg->addr);
+
+				/* if NACK, stop I2C bus and exit */
+				buf[2] = I2C_CONTROL_REG;
+				buf[3] = 0xC7;
+				buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+				ret = -EIO;
+				goto exit;
+			}
+
+			/* copy data from i2c data payload to read buffer */
+			for (i = 0; i < 8; i++) {
+				rd_status[i] = i2c_r_data[(i*3)+2];
+
+				if (rd_status[i] == 0x04) {
+					if (i < 7) {
+						mxl_i2c("i2c fifo empty!"
+							" @ %d", i);
+						msg->buf[(index*8)+i] =
+							i2c_r_data[(i*3)+1];
+						/* read again */
+						ret_status =
+							mxl111sf_i2c_readagain(
+								state, 8-(i+1),
+								readbuff);
+						if (ret_status == 1) {
+							for (k = 0;
+							     k < 8-(i+1);
+							     k++) {
+
+					msg->buf[(index*8)+(k+i+1)] =
+						readbuff[k];
+					mxl_i2c("read data: %02x\t %02x",
+						msg->buf[(index*8)+(k+i)],
+						(index*8)+(k+i));
+					mxl_i2c("read data: %02x\t %02x",
+						msg->buf[(index*8)+(k+i+1)],
+						readbuff[k]);
+
+							}
+							goto stop_copy;
+						} else {
+							mxl_i2c("readagain "
+								"ERROR!");
+						}
+					} else {
+						msg->buf[(index*8)+i] =
+							i2c_r_data[(i*3)+1];
+					}
+				} else {
+					msg->buf[(index*8)+i] =
+						i2c_r_data[(i*3)+1];
+				}
+			}
+stop_copy:
+			;
+
+		}
+
+		if (left_over_len) {
+			for (k = 0; k < 26; k++)
+				buf[k] = USB_END_I2C_CMD;
+
+			buf[0] = 0xDD;
+			buf[1] = 0x00;
+
+			for (i = 0; i < left_over_len; i++) {
+				buf[2+(i*3)] = I2C_DATA_REG;
+				buf[3+(i*3)] = 0x00;
+				buf[4+(i*3)] = 0x00;
+			}
+			ret = mxl111sf_i2c_get_data(state, 0, buf,
+						    i2c_r_data);
+
+			/* check for I2C NACK status */
+			if (mxl111sf_i2c_check_status(state) == 1) {
+				mxl_i2c("NACK reading slave address %02x",
+					msg->addr);
+
+				/* if NACK, stop I2C bus and exit */
+				buf[2] = I2C_CONTROL_REG;
+				buf[3] = 0xC7;
+				buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+				ret = -EIO;
+				goto exit;
+			}
+
+			for (i = 0; i < left_over_len; i++) {
+				msg->buf[(block_len*8)+i] =
+					i2c_r_data[(i*3)+1];
+				mxl_i2c("read data: %02x\t %02x",
+					i2c_r_data[(i*3)+1],
+					i2c_r_data[(i*3)+2]);
+			}
+		}
+
+		/* indicate I2C interface to issue NACK
+		   after next I2C read op */
+		buf[0] = USB_WRITE_I2C_CMD;
+		buf[1] = 0x00;
+
+		/* control register */
+		buf[2] = I2C_CONTROL_REG;
+		buf[3] = 0x17;
+		buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+
+		buf[5] = USB_END_I2C_CMD;
+		ret = mxl111sf_i2c_send_data(state, 0, buf);
+
+		/* control register */
+		buf[2] = I2C_CONTROL_REG;
+		buf[3] = 0xC7;
+		buf[4] = (HWI2C400) ? 0x03 : 0x0D;
+
+	}
+exit:
+	/* STOP and disable I2C MUX */
+	buf[0] = USB_WRITE_I2C_CMD;
+	buf[1] = 0x00;
+
+	/* de-initilize I2C BUS */
+	buf[5] = USB_END_I2C_CMD;
+	mxl111sf_i2c_send_data(state, 0, buf);
+
+	/* Control Register */
+	buf[2] = I2C_CONTROL_REG;
+	buf[3] = 0xDF;
+	buf[4] = 0x03;
+
+	/* disable I2C interface */
+	buf[5] = I2C_MUX_REG;
+	buf[6] = 0x00;
+	buf[7] = 0x00;
+
+	/* de-initilize I2C BUS */
+	buf[8] = USB_END_I2C_CMD;
+	mxl111sf_i2c_send_data(state, 0, buf);
+
+	/* disable I2C interface */
+	buf[2] = I2C_MUX_REG;
+	buf[3] = 0x81;
+	buf[4] = 0x00;
+
+	/* disable I2C interface */
+	buf[5] = I2C_MUX_REG;
+	buf[6] = 0x00;
+	buf[7] = 0x00;
+
+	/* disable I2C interface */
+	buf[8] = I2C_MUX_REG;
+	buf[9] = 0x00;
+	buf[10] = 0x00;
+
+	buf[11] = USB_END_I2C_CMD;
+	mxl111sf_i2c_send_data(state, 0, buf);
+
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int mxl111sf_i2c_xfer(struct i2c_adapter *adap,
+		      struct i2c_msg msg[], int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	struct mxl111sf_state *state = d->priv;
+	int hwi2c = (state->chip_rev > MXL111SF_V6);
+	int i, ret;
+
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+
+	for (i = 0; i < num; i++) {
+		ret = (hwi2c) ?
+			mxl111sf_i2c_hw_xfer_msg(state, &msg[i]) :
+			mxl111sf_i2c_sw_xfer_msg(state, &msg[i]);
+		if (mxl_fail(ret)) {
+			mxl_debug_adv("failed with error %d on i2c "
+				      "transaction %d of %d, %sing %d bytes "
+				      "to/from 0x%02x", ret, i+1, num,
+				      (msg[i].flags & I2C_M_RD) ?
+				      "read" : "writ",
+				      msg[i].len, msg[i].addr);
+
+			break;
+		}
+	}
+
+	mutex_unlock(&d->i2c_mutex);
+
+	return i == num ? num : -EREMOTEIO;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-i2c.h linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-i2c.h
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-i2c.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-i2c.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ *  mxl111sf-i2c.h - driver for the MaxLinear MXL111SF
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 _DVB_USB_MXL111SF_I2C_H_
+#define _DVB_USB_MXL111SF_I2C_H_
+
+#include <linux/i2c.h>
+
+int mxl111sf_i2c_xfer(struct i2c_adapter *adap,
+		      struct i2c_msg msg[], int num);
+
+#endif /* _DVB_USB_MXL111SF_I2C_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-phy.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-phy.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-phy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-phy.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,343 @@
+/*
+ *  mxl111sf-phy.c - driver for the MaxLinear MXL111SF
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 "mxl111sf-phy.h"
+#include "mxl111sf-reg.h"
+
+int mxl111sf_init_tuner_demod(struct mxl111sf_state *state)
+{
+	struct mxl111sf_reg_ctrl_info mxl_111_overwrite_default[] = {
+		{0x07, 0xff, 0x0c},
+		{0x58, 0xff, 0x9d},
+		{0x09, 0xff, 0x00},
+		{0x06, 0xff, 0x06},
+		{0xc8, 0xff, 0x40}, /* ED_LE_WIN_OLD = 0 */
+		{0x8d, 0x01, 0x01}, /* NEGATE_Q */
+		{0x32, 0xff, 0xac}, /* DIG_RFREFSELECT = 12 */
+		{0x42, 0xff, 0x43}, /* DIG_REG_AMP = 4 */
+		{0x74, 0xff, 0xc4}, /* SSPUR_FS_PRIO = 4 */
+		{0x71, 0xff, 0xe6}, /* SPUR_ROT_PRIO_VAL = 1 */
+		{0x83, 0xff, 0x64}, /* INF_FILT1_THD_SC = 100 */
+		{0x85, 0xff, 0x64}, /* INF_FILT2_THD_SC = 100 */
+		{0x88, 0xff, 0xf0}, /* INF_THD = 240 */
+		{0x6f, 0xf0, 0xb0}, /* DFE_DLY = 11 */
+		{0x00, 0xff, 0x01}, /* Change to page 1 */
+		{0x81, 0xff, 0x11}, /* DSM_FERR_BYPASS = 1 */
+		{0xf4, 0xff, 0x07}, /* DIG_FREQ_CORR = 1 */
+		{0xd4, 0x1f, 0x0f}, /* SPUR_TEST_NOISE_TH = 15 */
+		{0xd6, 0xff, 0x0c}, /* SPUR_TEST_NOISE_PAPR = 12 */
+		{0x00, 0xff, 0x00}, /* Change to page 0 */
+		{0,    0,    0}
+	};
+
+	mxl_debug("()");
+
+	return mxl111sf_ctrl_program_regs(state, mxl_111_overwrite_default);
+}
+
+int mxl1x1sf_soft_reset(struct mxl111sf_state *state)
+{
+	int ret;
+	mxl_debug("()");
+
+	ret = mxl111sf_write_reg(state, 0xff, 0x00); /* AIC */
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_write_reg(state, 0x02, 0x01); /* get out of reset */
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+int mxl1x1sf_set_device_mode(struct mxl111sf_state *state, int mode)
+{
+	int ret;
+
+	mxl_debug("(%s)", MXL_SOC_MODE == mode ?
+		"MXL_SOC_MODE" : "MXL_TUNER_MODE");
+
+	/* set device mode */
+	ret = mxl111sf_write_reg(state, 0x03,
+				 MXL_SOC_MODE == mode ? 0x01 : 0x00);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg_mask(state,
+				      0x7d, 0x40, MXL_SOC_MODE == mode ?
+				      0x00 : /* enable impulse noise filter,
+						INF_BYP = 0 */
+				      0x40); /* disable impulse noise filter,
+						INF_BYP = 1 */
+	if (mxl_fail(ret))
+		goto fail;
+
+	state->device_mode = mode;
+fail:
+	return ret;
+}
+
+/* power up tuner */
+int mxl1x1sf_top_master_ctrl(struct mxl111sf_state *state, int onoff)
+{
+	mxl_debug("(%d)", onoff);
+
+	return mxl111sf_write_reg(state, 0x01, onoff ? 0x01 : 0x00);
+}
+
+int mxl111sf_disable_656_port(struct mxl111sf_state *state)
+{
+	mxl_debug("()");
+
+	return mxl111sf_write_reg_mask(state, 0x12, 0x04, 0x00);
+}
+
+int mxl111sf_enable_usb_output(struct mxl111sf_state *state)
+{
+	mxl_debug("()");
+
+	return mxl111sf_write_reg_mask(state, 0x17, 0x40, 0x00);
+}
+
+/* initialize TSIF as input port of MxL1X1SF for MPEG2 data transfer */
+int mxl111sf_config_mpeg_in(struct mxl111sf_state *state,
+			    unsigned int parallel_serial,
+			    unsigned int msb_lsb_1st,
+			    unsigned int clock_phase,
+			    unsigned int mpeg_valid_pol,
+			    unsigned int mpeg_sync_pol)
+{
+	int ret;
+	u8 mode, tmp;
+
+	mxl_debug("(%u,%u,%u,%u,%u)", parallel_serial, msb_lsb_1st,
+		  clock_phase, mpeg_valid_pol, mpeg_sync_pol);
+
+	/* Enable PIN MUX */
+	ret = mxl111sf_write_reg(state, V6_PIN_MUX_MODE_REG, V6_ENABLE_PIN_MUX);
+	mxl_fail(ret);
+
+	/* Configure MPEG Clock phase */
+	mxl111sf_read_reg(state, V6_MPEG_IN_CLK_INV_REG, &mode);
+
+	if (clock_phase == TSIF_NORMAL)
+		mode &= ~V6_INVERTED_CLK_PHASE;
+	else
+		mode |= V6_INVERTED_CLK_PHASE;
+
+	ret = mxl111sf_write_reg(state, V6_MPEG_IN_CLK_INV_REG, mode);
+	mxl_fail(ret);
+
+	/* Configure data input mode, MPEG Valid polarity, MPEG Sync polarity
+	 * Get current configuration */
+	ret = mxl111sf_read_reg(state, V6_MPEG_IN_CTRL_REG, &mode);
+	mxl_fail(ret);
+
+	/* Data Input mode */
+	if (parallel_serial == TSIF_INPUT_PARALLEL) {
+		/* Disable serial mode */
+		mode &= ~V6_MPEG_IN_DATA_SERIAL;
+
+		/* Enable Parallel mode */
+		mode |= V6_MPEG_IN_DATA_PARALLEL;
+	} else {
+		/* Disable Parallel mode */
+		mode &= ~V6_MPEG_IN_DATA_PARALLEL;
+
+		/* Enable Serial Mode */
+		mode |= V6_MPEG_IN_DATA_SERIAL;
+
+		/* If serial interface is chosen, configure
+		   MSB or LSB order in transmission */
+		ret = mxl111sf_read_reg(state,
+					V6_MPEG_INOUT_BIT_ORDER_CTRL_REG,
+					&tmp);
+		mxl_fail(ret);
+
+		if (msb_lsb_1st == MPEG_SER_MSB_FIRST_ENABLED)
+			tmp |= V6_MPEG_SER_MSB_FIRST;
+		else
+			tmp &= ~V6_MPEG_SER_MSB_FIRST;
+
+		ret = mxl111sf_write_reg(state,
+					 V6_MPEG_INOUT_BIT_ORDER_CTRL_REG,
+					 tmp);
+		mxl_fail(ret);
+	}
+
+	/* MPEG Sync polarity */
+	if (mpeg_sync_pol == TSIF_NORMAL)
+		mode &= ~V6_INVERTED_MPEG_SYNC;
+	else
+		mode |= V6_INVERTED_MPEG_SYNC;
+
+	/* MPEG Valid polarity */
+	if (mpeg_valid_pol == 0)
+		mode &= ~V6_INVERTED_MPEG_VALID;
+	else
+		mode |= V6_INVERTED_MPEG_VALID;
+
+	ret = mxl111sf_write_reg(state, V6_MPEG_IN_CTRL_REG, mode);
+	mxl_fail(ret);
+
+	return ret;
+}
+
+int mxl111sf_init_i2s_port(struct mxl111sf_state *state, u8 sample_size)
+{
+	static struct mxl111sf_reg_ctrl_info init_i2s[] = {
+		{0x1b, 0xff, 0x1e}, /* pin mux mode, Choose 656/I2S input */
+		{0x15, 0x60, 0x60}, /* Enable I2S */
+		{0x17, 0xe0, 0x20}, /* Input, MPEG MODE USB,
+				       Inverted 656 Clock, I2S_SOFT_RESET,
+				       0 : Normal operation, 1 : Reset State */
+#if 0
+		{0x12, 0x01, 0x00}, /* AUDIO_IRQ_CLR (Overflow Indicator) */
+#endif
+		{0x00, 0xff, 0x02}, /* Change to Control Page */
+		{0x26, 0x0d, 0x0d}, /* I2S_MODE & BT656_SRC_SEL for FPGA only */
+		{0x00, 0xff, 0x00},
+		{0,    0,    0}
+	};
+	int ret;
+
+	mxl_debug("(0x%02x)", sample_size);
+
+	ret = mxl111sf_ctrl_program_regs(state, init_i2s);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, V6_I2S_NUM_SAMPLES_REG, sample_size);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+int mxl111sf_disable_i2s_port(struct mxl111sf_state *state)
+{
+	static struct mxl111sf_reg_ctrl_info disable_i2s[] = {
+		{0x15, 0x40, 0x00},
+		{0,    0,    0}
+	};
+
+	mxl_debug("()");
+
+	return mxl111sf_ctrl_program_regs(state, disable_i2s);
+}
+
+int mxl111sf_config_i2s(struct mxl111sf_state *state,
+			u8 msb_start_pos, u8 data_width)
+{
+	int ret;
+	u8 tmp;
+
+	mxl_debug("(0x%02x, 0x%02x)", msb_start_pos, data_width);
+
+	ret = mxl111sf_read_reg(state, V6_I2S_STREAM_START_BIT_REG, &tmp);
+	if (mxl_fail(ret))
+		goto fail;
+
+	tmp &= 0xe0;
+	tmp |= msb_start_pos;
+	ret = mxl111sf_write_reg(state, V6_I2S_STREAM_START_BIT_REG, tmp);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_read_reg(state, V6_I2S_STREAM_END_BIT_REG, &tmp);
+	if (mxl_fail(ret))
+		goto fail;
+
+	tmp &= 0xe0;
+	tmp |= data_width;
+	ret = mxl111sf_write_reg(state, V6_I2S_STREAM_END_BIT_REG, tmp);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+int mxl111sf_config_spi(struct mxl111sf_state *state, int onoff)
+{
+	u8 val;
+	int ret;
+
+	mxl_debug("(%d)", onoff);
+
+	ret = mxl111sf_write_reg(state, 0x00, 0x02);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_read_reg(state, V8_SPI_MODE_REG, &val);
+	if (mxl_fail(ret))
+		goto fail;
+
+	if (onoff)
+		val |= 0x04;
+	else
+		val &= ~0x04;
+
+	ret = mxl111sf_write_reg(state, V8_SPI_MODE_REG, val);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ret = mxl111sf_write_reg(state, 0x00, 0x00);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+int mxl111sf_idac_config(struct mxl111sf_state *state,
+			 u8 control_mode, u8 current_setting,
+			 u8 current_value, u8 hysteresis_value)
+{
+	int ret;
+	u8 val;
+	/* current value will be set for both automatic & manual IDAC control */
+	val = current_value;
+
+	if (control_mode == IDAC_MANUAL_CONTROL) {
+		/* enable manual control of IDAC */
+		val |= IDAC_MANUAL_CONTROL_BIT_MASK;
+
+		if (current_setting == IDAC_CURRENT_SINKING_ENABLE)
+			/* enable current sinking in manual mode */
+			val |= IDAC_CURRENT_SINKING_BIT_MASK;
+		else
+			/* disable current sinking in manual mode */
+			val &= ~IDAC_CURRENT_SINKING_BIT_MASK;
+	} else {
+		/* disable manual control of IDAC */
+		val &= ~IDAC_MANUAL_CONTROL_BIT_MASK;
+
+		/* set hysteresis value  reg: 0x0B<5:0> */
+		ret = mxl111sf_write_reg(state, V6_IDAC_HYSTERESIS_REG,
+					 (hysteresis_value & 0x3F));
+		mxl_fail(ret);
+	}
+
+	ret = mxl111sf_write_reg(state, V6_IDAC_SETTINGS_REG, val);
+	mxl_fail(ret);
+
+	return ret;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-phy.h linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-phy.h
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-phy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-phy.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,53 @@
+/*
+ *  mxl111sf-phy.h - driver for the MaxLinear MXL111SF
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 _DVB_USB_MXL111SF_PHY_H_
+#define _DVB_USB_MXL111SF_PHY_H_
+
+#include "mxl111sf.h"
+
+int mxl1x1sf_soft_reset(struct mxl111sf_state *state);
+int mxl1x1sf_set_device_mode(struct mxl111sf_state *state, int mode);
+int mxl1x1sf_top_master_ctrl(struct mxl111sf_state *state, int onoff);
+int mxl111sf_disable_656_port(struct mxl111sf_state *state);
+int mxl111sf_init_tuner_demod(struct mxl111sf_state *state);
+int mxl111sf_enable_usb_output(struct mxl111sf_state *state);
+int mxl111sf_config_mpeg_in(struct mxl111sf_state *state,
+			    unsigned int parallel_serial,
+			    unsigned int msb_lsb_1st,
+			    unsigned int clock_phase,
+			    unsigned int mpeg_valid_pol,
+			    unsigned int mpeg_sync_pol);
+int mxl111sf_config_i2s(struct mxl111sf_state *state,
+			u8 msb_start_pos, u8 data_width);
+int mxl111sf_init_i2s_port(struct mxl111sf_state *state, u8 sample_size);
+int mxl111sf_disable_i2s_port(struct mxl111sf_state *state);
+int mxl111sf_config_spi(struct mxl111sf_state *state, int onoff);
+int mxl111sf_idac_config(struct mxl111sf_state *state,
+			 u8 control_mode, u8 current_setting,
+			 u8 current_value, u8 hysteresis_value);
+
+#endif /* _DVB_USB_MXL111SF_PHY_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-reg.h linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-reg.h
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,179 @@
+/*
+ *  mxl111sf-reg.h - driver for the MaxLinear MXL111SF
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 _DVB_USB_MXL111SF_REG_H_
+#define _DVB_USB_MXL111SF_REG_H_
+
+#define CHIP_ID_REG                  0xFC
+#define TOP_CHIP_REV_ID_REG          0xFA
+
+#define V6_SNR_RB_LSB_REG            0x27
+#define V6_SNR_RB_MSB_REG            0x28
+
+#define V6_N_ACCUMULATE_REG          0x11
+#define V6_RS_AVG_ERRORS_LSB_REG     0x2C
+#define V6_RS_AVG_ERRORS_MSB_REG     0x2D
+
+#define V6_IRQ_STATUS_REG            0x24
+#define  IRQ_MASK_FEC_LOCK       0x10
+
+#define V6_SYNC_LOCK_REG             0x28
+#define SYNC_LOCK_MASK           0x10
+
+#define V6_RS_LOCK_DET_REG           0x28
+#define  RS_LOCK_DET_MASK        0x08
+
+#define V6_INITACQ_NODETECT_REG    0x20
+#define V6_FORCE_NFFT_CPSIZE_REG   0x20
+
+#define V6_CODE_RATE_TPS_REG       0x29
+#define V6_CODE_RATE_TPS_MASK      0x07
+
+
+#define V6_CP_LOCK_DET_REG        0x28
+#define V6_CP_LOCK_DET_MASK       0x04
+
+#define V6_TPS_HIERACHY_REG        0x29
+#define V6_TPS_HIERARCHY_INFO_MASK  0x40
+
+#define V6_MODORDER_TPS_REG        0x2A
+#define V6_PARAM_CONSTELLATION_MASK   0x30
+
+#define V6_MODE_TPS_REG            0x2A
+#define V6_PARAM_FFT_MODE_MASK        0x0C
+
+
+#define V6_CP_TPS_REG             0x29
+#define V6_PARAM_GI_MASK              0x30
+
+#define V6_TPS_LOCK_REG           0x2A
+#define V6_PARAM_TPS_LOCK_MASK        0x40
+
+#define V6_FEC_PER_COUNT_REG      0x2E
+#define V6_FEC_PER_SCALE_REG      0x2B
+#define V6_FEC_PER_SCALE_MASK        0x03
+#define V6_FEC_PER_CLR_REG        0x20
+#define V6_FEC_PER_CLR_MASK          0x01
+
+#define V6_PIN_MUX_MODE_REG       0x1B
+#define V6_ENABLE_PIN_MUX            0x1E
+
+#define V6_I2S_NUM_SAMPLES_REG    0x16
+
+#define V6_MPEG_IN_CLK_INV_REG    0x17
+#define V6_MPEG_IN_CTRL_REG       0x18
+
+#define V6_INVERTED_CLK_PHASE       0x20
+#define V6_MPEG_IN_DATA_PARALLEL    0x01
+#define V6_MPEG_IN_DATA_SERIAL      0x02
+
+#define V6_INVERTED_MPEG_SYNC       0x04
+#define V6_INVERTED_MPEG_VALID      0x08
+
+#define TSIF_INPUT_PARALLEL         0
+#define TSIF_INPUT_SERIAL           1
+#define TSIF_NORMAL                 0
+
+#define V6_MPEG_INOUT_BIT_ORDER_CTRL_REG  0x19
+#define V6_MPEG_SER_MSB_FIRST                0x80
+#define MPEG_SER_MSB_FIRST_ENABLED        0x01
+
+#define V6_656_I2S_BUFF_STATUS_REG   0x2F
+#define V6_656_OVERFLOW_MASK_BIT         0x08
+#define V6_I2S_OVERFLOW_MASK_BIT         0x01
+
+#define V6_I2S_STREAM_START_BIT_REG  0x14
+#define V6_I2S_STREAM_END_BIT_REG    0x15
+#define I2S_RIGHT_JUSTIFIED     0
+#define I2S_LEFT_JUSTIFIED      1
+#define I2S_DATA_FORMAT         2
+
+#define V6_TUNER_LOOP_THRU_CONTROL_REG  0x09
+#define V6_ENABLE_LOOP_THRU               0x01
+
+#define TOTAL_NUM_IF_OUTPUT_FREQ       16
+
+#define TUNER_NORMAL_IF_SPECTRUM       0x0
+#define TUNER_INVERT_IF_SPECTRUM       0x10
+
+#define V6_TUNER_IF_SEL_REG              0x06
+#define V6_TUNER_IF_FCW_REG              0x3C
+#define V6_TUNER_IF_FCW_BYP_REG          0x3D
+#define V6_RF_LOCK_STATUS_REG            0x23
+
+#define NUM_DIG_TV_CHANNEL     1000
+
+#define V6_DIG_CLK_FREQ_SEL_REG  0x07
+#define V6_REF_SYNTH_INT_REG     0x5C
+#define V6_REF_SYNTH_REMAIN_REG  0x58
+#define V6_DIG_RFREFSELECT_REG   0x32
+#define V6_XTAL_CLK_OUT_GAIN_REG   0x31
+#define V6_TUNER_LOOP_THRU_CTRL_REG      0x09
+#define V6_DIG_XTAL_ENABLE_REG  0x06
+#define V6_DIG_XTAL_BIAS_REG  0x66
+#define V6_XTAL_CAP_REG    0x08
+
+#define V6_GPO_CTRL_REG     0x18
+#define MXL_GPO_0           0x00
+#define MXL_GPO_1           0x01
+#define V6_GPO_0_MASK       0x10
+#define V6_GPO_1_MASK       0x20
+
+#define V6_111SF_GPO_CTRL_REG     0x19
+#define MXL_111SF_GPO_1               0x00
+#define MXL_111SF_GPO_2               0x01
+#define MXL_111SF_GPO_3               0x02
+#define MXL_111SF_GPO_4               0x03
+#define MXL_111SF_GPO_5               0x04
+#define MXL_111SF_GPO_6               0x05
+#define MXL_111SF_GPO_7               0x06
+
+#define MXL_111SF_GPO_0_MASK          0x01
+#define MXL_111SF_GPO_1_MASK          0x02
+#define MXL_111SF_GPO_2_MASK          0x04
+#define MXL_111SF_GPO_3_MASK          0x08
+#define MXL_111SF_GPO_4_MASK          0x10
+#define MXL_111SF_GPO_5_MASK          0x20
+#define MXL_111SF_GPO_6_MASK          0x40
+
+#define V6_ATSC_CONFIG_REG  0x0A
+
+#define MXL_MODE_REG    0x03
+#define START_TUNE_REG  0x1C
+
+#define V6_IDAC_HYSTERESIS_REG    0x0B
+#define V6_IDAC_SETTINGS_REG      0x0C
+#define IDAC_MANUAL_CONTROL             1
+#define IDAC_CURRENT_SINKING_ENABLE     1
+#define IDAC_MANUAL_CONTROL_BIT_MASK      0x80
+#define IDAC_CURRENT_SINKING_BIT_MASK     0x40
+
+#define V8_SPI_MODE_REG  0xE9
+
+#define V6_DIG_RF_PWR_LSB_REG  0x46
+#define V6_DIG_RF_PWR_MSB_REG  0x47
+
+#endif /* _DVB_USB_MXL111SF_REG_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,476 @@
+/*
+ *  mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 "mxl111sf-tuner.h"
+#include "mxl111sf-phy.h"
+#include "mxl111sf-reg.h"
+
+/* debug */
+static int mxl111sf_tuner_debug;
+module_param_named(debug, mxl111sf_tuner_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
+
+#define mxl_dbg(fmt, arg...) \
+	if (mxl111sf_tuner_debug) \
+		mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+/* ------------------------------------------------------------------------ */
+
+struct mxl111sf_tuner_state {
+	struct mxl111sf_state *mxl_state;
+
+	struct mxl111sf_tuner_config *cfg;
+
+	u32 frequency;
+	u32 bandwidth;
+};
+
+static int mxl111sf_tuner_read_reg(struct mxl111sf_tuner_state *state,
+				   u8 addr, u8 *data)
+{
+	return (state->cfg->read_reg) ?
+		state->cfg->read_reg(state->mxl_state, addr, data) :
+		-EINVAL;
+}
+
+static int mxl111sf_tuner_write_reg(struct mxl111sf_tuner_state *state,
+				    u8 addr, u8 data)
+{
+	return (state->cfg->write_reg) ?
+		state->cfg->write_reg(state->mxl_state, addr, data) :
+		-EINVAL;
+}
+
+static int mxl111sf_tuner_program_regs(struct mxl111sf_tuner_state *state,
+			       struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
+{
+	return (state->cfg->program_regs) ?
+		state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
+		-EINVAL;
+}
+
+static int mxl1x1sf_tuner_top_master_ctrl(struct mxl111sf_tuner_state *state,
+					  int onoff)
+{
+	return (state->cfg->top_master_ctrl) ?
+		state->cfg->top_master_ctrl(state->mxl_state, onoff) :
+		-EINVAL;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static struct mxl111sf_reg_ctrl_info mxl_phy_tune_rf[] = {
+	{0x1d, 0x7f, 0x00}, /* channel bandwidth section 1/2/3,
+			       DIG_MODEINDEX, _A, _CSF, */
+	{0x1e, 0xff, 0x00}, /* channel frequency (lo and fractional) */
+	{0x1f, 0xff, 0x00}, /* channel frequency (hi for integer portion) */
+	{0,    0,    0}
+};
+
+/* ------------------------------------------------------------------------ */
+
+static struct mxl111sf_reg_ctrl_info *mxl111sf_calc_phy_tune_regs(u32 freq,
+								  u8 bw)
+{
+	u8 filt_bw;
+
+	/* set channel bandwidth */
+	switch (bw) {
+	case 0: /* ATSC */
+		filt_bw = 25;
+		break;
+	case 1: /* QAM */
+		filt_bw = 69;
+		break;
+	case 6:
+		filt_bw = 21;
+		break;
+	case 7:
+		filt_bw = 42;
+		break;
+	case 8:
+		filt_bw = 63;
+		break;
+	default:
+		err("%s: invalid bandwidth setting!", __func__);
+		return NULL;
+	}
+
+	/* calculate RF channel */
+	freq /= 1000000;
+
+	freq *= 64;
+#if 0
+	/* do round */
+	freq += 0.5;
+#endif
+	/* set bandwidth */
+	mxl_phy_tune_rf[0].data = filt_bw;
+
+	/* set RF */
+	mxl_phy_tune_rf[1].data = (freq & 0xff);
+	mxl_phy_tune_rf[2].data = (freq >> 8) & 0xff;
+
+	/* start tune */
+	return mxl_phy_tune_rf;
+}
+
+static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state *state)
+{
+	int ret;
+	u8 ctrl;
+#if 0
+	u16 iffcw;
+	u32 if_freq;
+#endif
+	mxl_dbg("(IF polarity = %d, IF freq = 0x%02x)",
+		state->cfg->invert_spectrum, state->cfg->if_freq);
+
+	/* set IF polarity */
+	ctrl = state->cfg->invert_spectrum;
+
+	ctrl |= state->cfg->if_freq;
+
+	ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_SEL_REG, ctrl);
+	if (mxl_fail(ret))
+		goto fail;
+
+#if 0
+	if_freq /= 1000000;
+
+	/* do round */
+	if_freq += 0.5;
+
+	if (MXL_IF_LO == state->cfg->if_freq) {
+		ctrl = 0x08;
+		iffcw = (u16)(if_freq / (108 * 4096));
+	} else if (MXL_IF_HI == state->cfg->if_freq) {
+		ctrl = 0x08;
+		iffcw = (u16)(if_freq / (216 * 4096));
+	} else {
+		ctrl = 0;
+		iffcw = 0;
+	}
+
+	ctrl |= (iffcw >> 8);
+#endif
+	ret = mxl111sf_tuner_read_reg(state, V6_TUNER_IF_FCW_BYP_REG, &ctrl);
+	if (mxl_fail(ret))
+		goto fail;
+
+	ctrl &= 0xf0;
+	ctrl |= 0x90;
+
+	ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_BYP_REG, ctrl);
+	if (mxl_fail(ret))
+		goto fail;
+
+#if 0
+	ctrl = iffcw & 0x00ff;
+#endif
+	ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_REG, ctrl);
+	mxl_fail(ret);
+fail:
+	return ret;
+}
+
+static int mxl1x1sf_tune_rf(struct dvb_frontend *fe, u32 freq, u8 bw)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	static struct mxl111sf_reg_ctrl_info *reg_ctrl_array;
+	int ret;
+	u8 mxl_mode;
+
+	mxl_dbg("(freq = %d, bw = 0x%x)", freq, bw);
+
+	/* stop tune */
+	ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 0);
+	if (mxl_fail(ret))
+		goto fail;
+
+	/* check device mode */
+	ret = mxl111sf_tuner_read_reg(state, MXL_MODE_REG, &mxl_mode);
+	if (mxl_fail(ret))
+		goto fail;
+
+	/* Fill out registers for channel tune */
+	reg_ctrl_array = mxl111sf_calc_phy_tune_regs(freq, bw);
+	if (!reg_ctrl_array)
+		return -EINVAL;
+
+	ret = mxl111sf_tuner_program_regs(state, reg_ctrl_array);
+	if (mxl_fail(ret))
+		goto fail;
+
+	if ((mxl_mode & MXL_DEV_MODE_MASK) == MXL_TUNER_MODE) {
+		/* IF tuner mode only */
+		mxl1x1sf_tuner_top_master_ctrl(state, 0);
+		mxl1x1sf_tuner_top_master_ctrl(state, 1);
+		mxl1x1sf_tuner_set_if_output_freq(state);
+	}
+
+	ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 1);
+	if (mxl_fail(ret))
+		goto fail;
+
+	if (state->cfg->ant_hunt)
+		state->cfg->ant_hunt(fe);
+fail:
+	return ret;
+}
+
+static int mxl1x1sf_tuner_get_lock_status(struct mxl111sf_tuner_state *state,
+					  int *rf_synth_lock,
+					  int *ref_synth_lock)
+{
+	int ret;
+	u8 data;
+
+	*rf_synth_lock = 0;
+	*ref_synth_lock = 0;
+
+	ret = mxl111sf_tuner_read_reg(state, V6_RF_LOCK_STATUS_REG, &data);
+	if (mxl_fail(ret))
+		goto fail;
+
+	*ref_synth_lock = ((data & 0x03) == 0x03) ? 1 : 0;
+	*rf_synth_lock  = ((data & 0x0c) == 0x0c) ? 1 : 0;
+fail:
+	return ret;
+}
+
+#if 0
+static int mxl1x1sf_tuner_loop_thru_ctrl(struct mxl111sf_tuner_state *state,
+					 int onoff)
+{
+	return mxl111sf_tuner_write_reg(state, V6_TUNER_LOOP_THRU_CTRL_REG,
+					onoff ? 1 : 0);
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_tuner_set_params(struct dvb_frontend *fe,
+				     struct dvb_frontend_parameters *params)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	int ret;
+	u8 bw;
+
+	mxl_dbg("()");
+
+	if (fe->ops.info.type == FE_ATSC) {
+		switch (params->u.vsb.modulation) {
+		case VSB_8:
+		case VSB_16:
+			bw = 0; /* ATSC */
+			break;
+		case QAM_64:
+		case QAM_256:
+			bw = 1; /* US CABLE */
+			break;
+		default:
+			err("%s: modulation not set!", __func__);
+			return -EINVAL;
+		}
+	} else if (fe->ops.info.type == FE_OFDM) {
+		switch (params->u.ofdm.bandwidth) {
+		case BANDWIDTH_6_MHZ:
+			bw = 6;
+			break;
+		case BANDWIDTH_7_MHZ:
+			bw = 7;
+			break;
+		case BANDWIDTH_8_MHZ:
+			bw = 8;
+			break;
+		default:
+			err("%s: bandwidth not set!", __func__);
+			return -EINVAL;
+		}
+	} else {
+		err("%s: modulation type not supported!", __func__);
+		return -EINVAL;
+	}
+	ret = mxl1x1sf_tune_rf(fe, params->frequency, bw);
+	if (mxl_fail(ret))
+		goto fail;
+
+	state->frequency = params->frequency;
+	state->bandwidth = (fe->ops.info.type == FE_OFDM) ?
+		params->u.ofdm.bandwidth : 0;
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+#if 0
+static int mxl111sf_tuner_init(struct dvb_frontend *fe)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	int ret;
+
+	/* wake from standby handled by usb driver */
+
+	return ret;
+}
+
+static int mxl111sf_tuner_sleep(struct dvb_frontend *fe)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	int ret;
+
+	/* enter standby mode handled by usb driver */
+
+	return ret;
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_tuner_get_status(struct dvb_frontend *fe, u32 *status)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	int rf_locked, ref_locked, ret;
+
+	*status = 0;
+
+	ret = mxl1x1sf_tuner_get_lock_status(state, &rf_locked, &ref_locked);
+	if (mxl_fail(ret))
+		goto fail;
+	mxl_info("%s%s", rf_locked ? "rf locked " : "",
+		 ref_locked ? "ref locked" : "");
+
+	if ((rf_locked) || (ref_locked))
+		*status |= TUNER_STATUS_LOCKED;
+fail:
+	return ret;
+}
+
+static int mxl111sf_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	u8 val1, val2;
+	int ret;
+
+	*strength = 0;
+
+	ret = mxl111sf_tuner_write_reg(state, 0x00, 0x02);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_LSB_REG, &val1);
+	if (mxl_fail(ret))
+		goto fail;
+	ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_MSB_REG, &val2);
+	if (mxl_fail(ret))
+		goto fail;
+
+	*strength = val1 | ((val2 & 0x07) << 8);
+fail:
+	ret = mxl111sf_tuner_write_reg(state, 0x00, 0x00);
+	mxl_fail(ret);
+
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_tuner_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	*frequency = state->frequency;
+	return 0;
+}
+
+static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	*bandwidth = state->bandwidth;
+	return 0;
+}
+
+static int mxl111sf_tuner_release(struct dvb_frontend *fe)
+{
+	struct mxl111sf_tuner_state *state = fe->tuner_priv;
+	mxl_dbg("()");
+	kfree(state);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = {
+	.info = {
+		.name = "MaxLinear MxL111SF",
+#if 0
+		.frequency_min  = ,
+		.frequency_max  = ,
+		.frequency_step = ,
+#endif
+	},
+#if 0
+	.init              = mxl111sf_tuner_init,
+	.sleep             = mxl111sf_tuner_sleep,
+#endif
+	.set_params        = mxl111sf_tuner_set_params,
+	.get_status        = mxl111sf_tuner_get_status,
+	.get_rf_strength   = mxl111sf_get_rf_strength,
+	.get_frequency     = mxl111sf_tuner_get_frequency,
+	.get_bandwidth     = mxl111sf_tuner_get_bandwidth,
+	.release           = mxl111sf_tuner_release,
+};
+
+struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
+					   struct mxl111sf_state *mxl_state,
+					   struct mxl111sf_tuner_config *cfg)
+{
+	struct mxl111sf_tuner_state *state = NULL;
+
+	mxl_dbg("()");
+
+	state = kzalloc(sizeof(struct mxl111sf_tuner_state), GFP_KERNEL);
+	if (state == NULL)
+		return NULL;
+
+	state->mxl_state = mxl_state;
+	state->cfg = cfg;
+
+	memcpy(&fe->ops.tuner_ops, &mxl111sf_tuner_tuner_ops,
+	       sizeof(struct dvb_tuner_ops));
+
+	fe->tuner_priv = state;
+	return fe;
+}
+EXPORT_SYMBOL_GPL(mxl111sf_tuner_attach);
+
+MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver");
+MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.1");
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-tuner.h linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-tuner.h
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/mxl111sf-tuner.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/mxl111sf-tuner.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,89 @@
+/*
+ *  mxl111sf-tuner.h - driver for the MaxLinear MXL111SF CMOS tuner
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 __MXL111SF_TUNER_H__
+#define __MXL111SF_TUNER_H__
+
+#include "dvb_frontend.h"
+
+#include "mxl111sf.h"
+
+enum mxl_if_freq {
+#if 0
+	MXL_IF_LO    = 0x00, /* other IF < 9MHz */
+#endif
+	MXL_IF_4_0   = 0x01, /* 4.0   MHz */
+	MXL_IF_4_5   = 0x02, /* 4.5   MHz */
+	MXL_IF_4_57  = 0x03, /* 4.57  MHz */
+	MXL_IF_5_0   = 0x04, /* 5.0   MHz */
+	MXL_IF_5_38  = 0x05, /* 5.38  MHz */
+	MXL_IF_6_0   = 0x06, /* 6.0   MHz */
+	MXL_IF_6_28  = 0x07, /* 6.28  MHz */
+	MXL_IF_7_2   = 0x08, /* 7.2   MHz */
+	MXL_IF_35_25 = 0x09, /* 35.25 MHz */
+	MXL_IF_36    = 0x0a, /* 36    MHz */
+	MXL_IF_36_15 = 0x0b, /* 36.15 MHz */
+	MXL_IF_44    = 0x0c, /* 44    MHz */
+#if 0
+	MXL_IF_HI    = 0x0f, /* other IF > 35 MHz and < 45 MHz */
+#endif
+};
+
+struct mxl111sf_tuner_config {
+	enum mxl_if_freq if_freq;
+	unsigned int invert_spectrum:1;
+
+	int (*read_reg)(struct mxl111sf_state *state, u8 addr, u8 *data);
+	int (*write_reg)(struct mxl111sf_state *state, u8 addr, u8 data);
+	int (*program_regs)(struct mxl111sf_state *state,
+			    struct mxl111sf_reg_ctrl_info *ctrl_reg_info);
+	int (*top_master_ctrl)(struct mxl111sf_state *state, int onoff);
+	int (*ant_hunt)(struct dvb_frontend *fe);
+};
+
+/* ------------------------------------------------------------------------ */
+
+#if defined(CONFIG_DVB_USB_MXL111SF) || \
+	(defined(CONFIG_DVB_USB_MXL111SF_MODULE) && defined(MODULE))
+extern
+struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
+					   struct mxl111sf_state *mxl_state,
+					   struct mxl111sf_tuner_config *cfg);
+#else
+static inline
+struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
+					   struct mxl111sf_state *mxl_state
+					   struct mxl111sf_tuner_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* __MXL111SF_TUNER_H__ */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/nova-t-usb2.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/nova-t-usb2.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/nova-t-usb2.c	2012-03-19 21:33:50.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/nova-t-usb2.c	2012-03-19 21:36:13.000000000 -0400
@@ -166,6 +166,8 @@
 	.num_adapters     = 1,
 	.adapter          = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 			.pid_filter_count = 32,
 
@@ -186,7 +188,7 @@
 					}
 				}
 			},
-
+		}},
 			.size_of_priv     = sizeof(struct dibusb_state),
 		}
 	},
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/opera1.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/opera1.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/opera1.c	2012-03-19 21:33:59.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/opera1.c	2012-03-19 21:36:22.000000000 -0400
@@ -263,10 +263,10 @@
 
 static int opera1_frontend_attach(struct dvb_usb_adapter *d)
 {
-	if ((d->fe =
-	     dvb_attach(stv0299_attach, &opera1_stv0299_config,
-			&d->dev->i2c_adap)) != NULL) {
-		d->fe->ops.set_voltage = opera1_set_voltage;
+	d->fe_adap[0].fe = dvb_attach(stv0299_attach, &opera1_stv0299_config,
+				      &d->dev->i2c_adap);
+	if ((d->fe_adap[0].fe) != NULL) {
+		d->fe_adap[0].fe->ops.set_voltage = opera1_set_voltage;
 		return 0;
 	}
 	info("not attached stv0299");
@@ -276,7 +276,7 @@
 static int opera1_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	dvb_attach(
-		dvb_pll_attach, adap->fe, 0xc0>>1,
+		dvb_pll_attach, adap->fe_adap[0].fe, 0xc0>>1,
 		&adap->dev->i2c_adap, DVB_PLL_OPERA1
 	);
 	return 0;
@@ -516,6 +516,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach = opera1_frontend_attach,
 			.streaming_ctrl = opera1_streaming_ctrl,
 			.tuner_attach = opera1_tuner_attach,
@@ -535,6 +537,7 @@
 					}
 				}
 			},
+		}},
 		}
 	},
 	.num_device_descs = 1,
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/pctv452e.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/pctv452e.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/pctv452e.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/pctv452e.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1079 @@
+/*
+ * PCTV 452e DVB driver
+ *
+ * Copyright (c) 2006-2008 Dominik Kuhlen <dkuhlen@gmx.net>
+ *
+ * TT connect S2-3650-CI Common Interface support, MAC readout
+ * Copyright (C) 2008 Michael H. Schimek <mschimek@gmx.at>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+/* dvb usb framework */
+#define DVB_USB_LOG_PREFIX "pctv452e"
+#include "dvb-usb.h"
+
+/* Demodulator */
+#include "stb0899_drv.h"
+#include "stb0899_reg.h"
+#include "stb0899_cfg.h"
+/* Tuner */
+#include "stb6100.h"
+#include "stb6100_cfg.h"
+/* FE Power */
+#include "lnbp22.h"
+
+#include "dvb_ca_en50221.h"
+#include "ttpci-eeprom.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define ISOC_INTERFACE_ALTERNATIVE 3
+
+#define SYNC_BYTE_OUT 0xaa
+#define SYNC_BYTE_IN  0x55
+
+/* guessed: (copied from ttusb-budget) */
+#define PCTV_CMD_RESET 0x15
+/* command to poll IR receiver */
+#define PCTV_CMD_IR    0x1b
+/* command to send I2C  */
+#define PCTV_CMD_I2C   0x31
+
+#define I2C_ADDR_STB0899 (0xd0 >> 1)
+#define I2C_ADDR_STB6100 (0xc0 >> 1)
+#define I2C_ADDR_LNBP22  (0x10 >> 1)
+#define I2C_ADDR_24C16   (0xa0 >> 1)
+#define I2C_ADDR_24C64   (0xa2 >> 1)
+
+
+/* pctv452e sends us this amount of data for each issued usb-command */
+#define PCTV_ANSWER_LEN 64
+/* Wait up to 1000ms for device  */
+#define PCTV_TIMEOUT 1000
+
+
+#define PCTV_LED_GPIO   STB0899_GPIO01
+#define PCTV_LED_GREEN  0x82
+#define PCTV_LED_ORANGE 0x02
+
+#define ci_dbg(format, arg...)				\
+do {							\
+	if (0)						\
+		printk(KERN_DEBUG DVB_USB_LOG_PREFIX	\
+			": " format "\n" , ## arg);	\
+} while (0)
+
+enum {
+	TT3650_CMD_CI_TEST = 0x40,
+	TT3650_CMD_CI_RD_CTRL,
+	TT3650_CMD_CI_WR_CTRL,
+	TT3650_CMD_CI_RD_ATTR,
+	TT3650_CMD_CI_WR_ATTR,
+	TT3650_CMD_CI_RESET,
+	TT3650_CMD_CI_SET_VIDEO_PORT
+};
+
+
+static struct stb0899_postproc pctv45e_postproc[] = {
+	{ PCTV_LED_GPIO, STB0899_GPIOPULLUP },
+	{ 0, 0 }
+};
+
+/*
+ * stores all private variables for communication with the PCTV452e DVB-S2
+ */
+struct pctv452e_state {
+	struct dvb_ca_en50221 ca;
+	struct mutex ca_mutex;
+
+	u8 c;	   /* transaction counter, wraps around...  */
+	u8 initialized; /* set to 1 if 0x15 has been sent */
+	u16 last_rc_key;
+};
+
+static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
+			 unsigned int write_len, unsigned int read_len)
+{
+	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+	u8 buf[64];
+	u8 id;
+	unsigned int rlen;
+	int ret;
+
+	BUG_ON(NULL == data && 0 != (write_len | read_len));
+	BUG_ON(write_len > 64 - 4);
+	BUG_ON(read_len > 64 - 4);
+
+	id = state->c++;
+
+	buf[0] = SYNC_BYTE_OUT;
+	buf[1] = id;
+	buf[2] = cmd;
+	buf[3] = write_len;
+
+	memcpy(buf + 4, data, write_len);
+
+	rlen = (read_len > 0) ? 64 : 0;
+	ret = dvb_usb_generic_rw(d, buf, 4 + write_len,
+				  buf, rlen, /* delay_ms */ 0);
+	if (0 != ret)
+		goto failed;
+
+	ret = -EIO;
+	if (SYNC_BYTE_IN != buf[0] || id != buf[1])
+		goto failed;
+
+	memcpy(data, buf + 4, read_len);
+
+	return 0;
+
+failed:
+	err("CI error %d; %02X %02X %02X -> %02X %02X %02X.",
+	     ret, SYNC_BYTE_OUT, id, cmd, buf[0], buf[1], buf[2]);
+
+	return ret;
+}
+
+static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca,
+				u8 cmd, u8 *data, unsigned int write_len,
+				unsigned int read_len)
+{
+	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+	int ret;
+
+	mutex_lock(&state->ca_mutex);
+	ret = tt3650_ci_msg(d, cmd, data, write_len, read_len);
+	mutex_unlock(&state->ca_mutex);
+
+	return ret;
+}
+
+static int tt3650_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
+				 int slot, int address)
+{
+	u8 buf[3];
+	int ret;
+
+	if (0 != slot)
+		return -EINVAL;
+
+	buf[0] = (address >> 8) & 0x0F;
+	buf[1] = address;
+
+	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_ATTR, buf, 2, 3);
+
+	ci_dbg("%s %04x -> %d 0x%02x",
+		__func__, address, ret, buf[2]);
+
+	if (ret < 0)
+		return ret;
+
+	return buf[2];
+}
+
+static int tt3650_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
+				 int slot, int address, u8 value)
+{
+	u8 buf[3];
+
+	ci_dbg("%s %d 0x%04x 0x%02x",
+		__func__, slot, address, value);
+
+	if (0 != slot)
+		return -EINVAL;
+
+	buf[0] = (address >> 8) & 0x0F;
+	buf[1] = address;
+	buf[2] = value;
+
+	return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_ATTR, buf, 3, 3);
+}
+
+static int tt3650_ci_read_cam_control(struct dvb_ca_en50221 *ca,
+				 int			slot,
+				 u8			address)
+{
+	u8 buf[2];
+	int ret;
+
+	if (0 != slot)
+		return -EINVAL;
+
+	buf[0] = address & 3;
+
+	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_CTRL, buf, 1, 2);
+
+	ci_dbg("%s 0x%02x -> %d 0x%02x",
+		__func__, address, ret, buf[1]);
+
+	if (ret < 0)
+		return ret;
+
+	return buf[1];
+}
+
+static int tt3650_ci_write_cam_control(struct dvb_ca_en50221 *ca,
+				 int			slot,
+				 u8			address,
+				 u8			value)
+{
+	u8 buf[2];
+
+	ci_dbg("%s %d 0x%02x 0x%02x",
+		__func__, slot, address, value);
+
+	if (0 != slot)
+		return -EINVAL;
+
+	buf[0] = address;
+	buf[1] = value;
+
+	return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_CTRL, buf, 2, 2);
+}
+
+static int tt3650_ci_set_video_port(struct dvb_ca_en50221 *ca,
+				 int			slot,
+				 int			enable)
+{
+	u8 buf[1];
+	int ret;
+
+	ci_dbg("%s %d %d", __func__, slot, enable);
+
+	if (0 != slot)
+		return -EINVAL;
+
+	enable = !!enable;
+	buf[0] = enable;
+
+	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
+	if (ret < 0)
+		return ret;
+
+	if (enable != buf[0]) {
+		err("CI not %sabled.", enable ? "en" : "dis");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int tt3650_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
+{
+	return tt3650_ci_set_video_port(ca, slot, /* enable */ 0);
+}
+
+static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
+{
+	return tt3650_ci_set_video_port(ca, slot, /* enable */ 1);
+}
+
+static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
+{
+	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+	u8 buf[1];
+	int ret;
+
+	ci_dbg("%s %d", __func__, slot);
+
+	if (0 != slot)
+		return -EINVAL;
+
+	buf[0] = 0;
+
+	mutex_lock(&state->ca_mutex);
+
+	ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
+	if (0 != ret)
+		goto failed;
+
+	msleep(500);
+
+	buf[0] = 1;
+
+	ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
+	if (0 != ret)
+		goto failed;
+
+	msleep(500);
+
+	buf[0] = 0; /* FTA */
+
+	ret = tt3650_ci_msg(d, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
+
+ failed:
+	mutex_unlock(&state->ca_mutex);
+
+	return ret;
+}
+
+static int tt3650_ci_poll_slot_status(struct dvb_ca_en50221 *ca,
+				 int			slot,
+				 int			open)
+{
+	u8 buf[1];
+	int ret;
+
+	if (0 != slot)
+		return -EINVAL;
+
+	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_TEST, buf, 0, 1);
+	if (0 != ret)
+		return ret;
+
+	if (1 == buf[0])
+		return DVB_CA_EN50221_POLL_CAM_PRESENT |
+			DVB_CA_EN50221_POLL_CAM_READY;
+
+	return 0;
+
+}
+
+static void tt3650_ci_uninit(struct dvb_usb_device *d)
+{
+	struct pctv452e_state *state;
+
+	ci_dbg("%s", __func__);
+
+	if (NULL == d)
+		return;
+
+	state = (struct pctv452e_state *)d->priv;
+	if (NULL == state)
+		return;
+
+	if (NULL == state->ca.data)
+		return;
+
+	/* Error ignored. */
+	tt3650_ci_set_video_port(&state->ca, /* slot */ 0, /* enable */ 0);
+
+	dvb_ca_en50221_release(&state->ca);
+
+	memset(&state->ca, 0, sizeof(state->ca));
+}
+
+static int tt3650_ci_init(struct dvb_usb_adapter *a)
+{
+	struct dvb_usb_device *d = a->dev;
+	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+	int ret;
+
+	ci_dbg("%s", __func__);
+
+	mutex_init(&state->ca_mutex);
+
+	state->ca.owner = THIS_MODULE;
+	state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem;
+	state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem;
+	state->ca.read_cam_control = tt3650_ci_read_cam_control;
+	state->ca.write_cam_control = tt3650_ci_write_cam_control;
+	state->ca.slot_reset = tt3650_ci_slot_reset;
+	state->ca.slot_shutdown = tt3650_ci_slot_shutdown;
+	state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable;
+	state->ca.poll_slot_status = tt3650_ci_poll_slot_status;
+	state->ca.data = d;
+
+	ret = dvb_ca_en50221_init(&a->dvb_adap,
+				   &state->ca,
+				   /* flags */ 0,
+				   /* n_slots */ 1);
+	if (0 != ret) {
+		err("Cannot initialize CI: Error %d.", ret);
+		memset(&state->ca, 0, sizeof(state->ca));
+		return ret;
+	}
+
+	info("CI initialized.");
+
+	return 0;
+}
+
+#define CMD_BUFFER_SIZE 0x28
+static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr,
+				const u8 *snd_buf, u8 snd_len,
+				u8 *rcv_buf, u8 rcv_len)
+{
+	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+	u8 buf[64];
+	u8 id;
+	int ret;
+
+	id = state->c++;
+
+	ret = -EINVAL;
+	if (snd_len > 64 - 7 || rcv_len > 64 - 7)
+		goto failed;
+
+	buf[0] = SYNC_BYTE_OUT;
+	buf[1] = id;
+	buf[2] = PCTV_CMD_I2C;
+	buf[3] = snd_len + 3;
+	buf[4] = addr << 1;
+	buf[5] = snd_len;
+	buf[6] = rcv_len;
+
+	memcpy(buf + 7, snd_buf, snd_len);
+
+	ret = dvb_usb_generic_rw(d, buf, 7 + snd_len,
+				  buf, /* rcv_len */ 64,
+				  /* delay_ms */ 0);
+	if (ret < 0)
+		goto failed;
+
+	/* TT USB protocol error. */
+	ret = -EIO;
+	if (SYNC_BYTE_IN != buf[0] || id != buf[1])
+		goto failed;
+
+	/* I2C device didn't respond as expected. */
+	ret = -EREMOTEIO;
+	if (buf[5] < snd_len || buf[6] < rcv_len)
+		goto failed;
+
+	memcpy(rcv_buf, buf + 7, rcv_len);
+
+	return rcv_len;
+
+failed:
+	err("I2C error %d; %02X %02X  %02X %02X %02X -> "
+	     "%02X %02X  %02X %02X %02X.",
+	     ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len,
+	     buf[0], buf[1], buf[4], buf[5], buf[6]);
+
+	return ret;
+}
+
+static int pctv452e_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msg,
+				int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adapter);
+	int i;
+
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+
+	for (i = 0; i < num; i++) {
+		u8 addr, snd_len, rcv_len, *snd_buf, *rcv_buf;
+		int ret;
+
+		if (msg[i].flags & I2C_M_RD) {
+			addr = msg[i].addr;
+			snd_buf = NULL;
+			snd_len = 0;
+			rcv_buf = msg[i].buf;
+			rcv_len = msg[i].len;
+		} else {
+			addr = msg[i].addr;
+			snd_buf = msg[i].buf;
+			snd_len = msg[i].len;
+			rcv_buf = NULL;
+			rcv_len = 0;
+		}
+
+		ret = pctv452e_i2c_msg(d, addr, snd_buf, snd_len, rcv_buf,
+					rcv_len);
+		if (ret < rcv_len)
+			break;
+	}
+
+	mutex_unlock(&d->i2c_mutex);
+	return i;
+}
+
+static u32 pctv452e_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
+{
+	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+	u8 b0[] = { 0xaa, 0, PCTV_CMD_RESET, 1, 0 };
+	u8 rx[PCTV_ANSWER_LEN];
+	int ret;
+
+	info("%s: %d\n", __func__, i);
+
+	if (!i)
+		return 0;
+
+	if (state->initialized)
+		return 0;
+
+	/* hmm where shoud this should go? */
+	ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE);
+	if (ret != 0)
+		info("%s: Warning set interface returned: %d\n",
+			__func__, ret);
+
+	/* this is a one-time initialization, dont know where to put */
+	b0[1] = state->c++;
+	/* reset board */
+	ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0);
+	if (ret)
+		return ret;
+
+	b0[1] = state->c++;
+	b0[4] = 1;
+	/* reset board (again?) */
+	ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0);
+	if (ret)
+		return ret;
+
+	state->initialized = 1;
+
+	return 0;
+}
+
+static int pctv452e_rc_query(struct dvb_usb_device *d)
+{
+	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+	u8 b[CMD_BUFFER_SIZE];
+	u8 rx[PCTV_ANSWER_LEN];
+	int ret, i;
+	u8 id = state->c++;
+
+	/* prepare command header  */
+	b[0] = SYNC_BYTE_OUT;
+	b[1] = id;
+	b[2] = PCTV_CMD_IR;
+	b[3] = 0;
+
+	/* send ir request */
+	ret = dvb_usb_generic_rw(d, b, 4, rx, PCTV_ANSWER_LEN, 0);
+	if (ret != 0)
+		return ret;
+
+	if (debug > 3) {
+		info("%s: read: %2d: %02x %02x %02x: ", __func__,
+				ret, rx[0], rx[1], rx[2]);
+		for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++)
+			info(" %02x", rx[i+3]);
+
+		info("\n");
+	}
+
+	if ((rx[3] == 9) &&  (rx[12] & 0x01)) {
+		/* got a "press" event */
+		state->last_rc_key = (rx[7] << 8) | rx[6];
+		if (debug > 2)
+			info("%s: cmd=0x%02x sys=0x%02x\n",
+				__func__, rx[6], rx[7]);
+
+		rc_keydown(d->rc_dev, state->last_rc_key, 0);
+	} else if (state->last_rc_key) {
+		rc_keyup(d->rc_dev);
+		state->last_rc_key = 0;
+	}
+
+	return 0;
+}
+
+static int pctv452e_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
+{
+	const u8 mem_addr[] = { 0x1f, 0xcc };
+	u8 encoded_mac[20];
+	int ret;
+
+	ret = -EAGAIN;
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		goto failed;
+
+	ret = pctv452e_i2c_msg(d, I2C_ADDR_24C16,
+				mem_addr + 1, /* snd_len */ 1,
+				encoded_mac, /* rcv_len */ 20);
+	if (-EREMOTEIO == ret)
+		/* Caution! A 24C16 interprets 0xA2 0x1F 0xCC as a
+		   byte write if /WC is low. */
+		ret = pctv452e_i2c_msg(d, I2C_ADDR_24C64,
+					mem_addr, 2,
+					encoded_mac, 20);
+
+	mutex_unlock(&d->i2c_mutex);
+
+	if (20 != ret)
+		goto failed;
+
+	ret = ttpci_eeprom_decode_mac(mac, encoded_mac);
+	if (0 != ret)
+		goto failed;
+
+	return 0;
+
+failed:
+	memset(mac, 0, 6);
+
+	return ret;
+}
+
+static const struct stb0899_s1_reg pctv452e_init_dev[] = {
+	{ STB0899_DISCNTRL1,	0x26 },
+	{ STB0899_DISCNTRL2,	0x80 },
+	{ STB0899_DISRX_ST0,	0x04 },
+	{ STB0899_DISRX_ST1,	0x20 },
+	{ STB0899_DISPARITY,	0x00 },
+	{ STB0899_DISFIFO,	0x00 },
+	{ STB0899_DISF22,	0x99 },
+	{ STB0899_DISF22RX,	0x85 }, /* 0xa8 */
+	{ STB0899_ACRPRESC,	0x11 },
+	{ STB0899_ACRDIV1,	0x0a },
+	{ STB0899_ACRDIV2,	0x05 },
+	{ STB0899_DACR1	,	0x00 },
+	{ STB0899_DACR2	,	0x00 },
+	{ STB0899_OUTCFG,	0x00 },
+	{ STB0899_MODECFG,	0x00 }, /* Inversion */
+	{ STB0899_IRQMSK_3,	0xf3 },
+	{ STB0899_IRQMSK_2,	0xfc },
+	{ STB0899_IRQMSK_1,	0xff },
+	{ STB0899_IRQMSK_0,	0xff },
+	{ STB0899_I2CCFG,	0x88 },
+	{ STB0899_I2CRPT,	0x58 },
+	{ STB0899_GPIO00CFG,	0x82 },
+	{ STB0899_GPIO01CFG,	0x82 }, /* LED: 0x02 green, 0x82 orange */
+	{ STB0899_GPIO02CFG,	0x82 },
+	{ STB0899_GPIO03CFG,	0x82 },
+	{ STB0899_GPIO04CFG,	0x82 },
+	{ STB0899_GPIO05CFG,	0x82 },
+	{ STB0899_GPIO06CFG,	0x82 },
+	{ STB0899_GPIO07CFG,	0x82 },
+	{ STB0899_GPIO08CFG,	0x82 },
+	{ STB0899_GPIO09CFG,	0x82 },
+	{ STB0899_GPIO10CFG,	0x82 },
+	{ STB0899_GPIO11CFG,	0x82 },
+	{ STB0899_GPIO12CFG,	0x82 },
+	{ STB0899_GPIO13CFG,	0x82 },
+	{ STB0899_GPIO14CFG,	0x82 },
+	{ STB0899_GPIO15CFG,	0x82 },
+	{ STB0899_GPIO16CFG,	0x82 },
+	{ STB0899_GPIO17CFG,	0x82 },
+	{ STB0899_GPIO18CFG,	0x82 },
+	{ STB0899_GPIO19CFG,	0x82 },
+	{ STB0899_GPIO20CFG,	0x82 },
+	{ STB0899_SDATCFG,	0xb8 },
+	{ STB0899_SCLTCFG,	0xba },
+	{ STB0899_AGCRFCFG,	0x1c }, /* 0x11 DVB-S; 0x1c DVB-S2 (1c, rjkm) */
+	{ STB0899_GPIO22,	0x82 },
+	{ STB0899_GPIO21,	0x91 },
+	{ STB0899_DIRCLKCFG,	0x82 },
+	{ STB0899_CLKOUT27CFG,	0x7e },
+	{ STB0899_STDBYCFG,	0x82 },
+	{ STB0899_CS0CFG,	0x82 },
+	{ STB0899_CS1CFG,	0x82 },
+	{ STB0899_DISEQCOCFG,	0x20 },
+	{ STB0899_NCOARSE,	0x15 }, /* 0x15 27Mhz, F/3 198MHz, F/6 108MHz */
+	{ STB0899_SYNTCTRL,	0x00 }, /* 0x00 CLKI, 0x02 XTALI */
+	{ STB0899_FILTCTRL,	0x00 },
+	{ STB0899_SYSCTRL,	0x00 },
+	{ STB0899_STOPCLK1,	0x20 }, /* orig: 0x00 budget-ci: 0x20 */
+	{ STB0899_STOPCLK2,	0x00 },
+	{ STB0899_INTBUFCTRL,	0x0a },
+	{ STB0899_AGC2I1,	0x00 },
+	{ STB0899_AGC2I2,	0x00 },
+	{ STB0899_AGCIQIN,	0x00 },
+	{ STB0899_TSTRES,	0x40 }, /* rjkm */
+	{ 0xffff,		0xff },
+};
+
+static const struct stb0899_s1_reg pctv452e_init_s1_demod[] = {
+	{ STB0899_DEMOD,	0x00 },
+	{ STB0899_RCOMPC,	0xc9 },
+	{ STB0899_AGC1CN,	0x01 },
+	{ STB0899_AGC1REF,	0x10 },
+	{ STB0899_RTC,		0x23 },
+	{ STB0899_TMGCFG,	0x4e },
+	{ STB0899_AGC2REF,	0x34 },
+	{ STB0899_TLSR,		0x84 },
+	{ STB0899_CFD,		0xf7 },
+	{ STB0899_ACLC,		0x87 },
+	{ STB0899_BCLC,		0x94 },
+	{ STB0899_EQON,		0x41 },
+	{ STB0899_LDT,		0xf1 },
+	{ STB0899_LDT2,		0xe3 },
+	{ STB0899_EQUALREF,	0xb4 },
+	{ STB0899_TMGRAMP,	0x10 },
+	{ STB0899_TMGTHD,	0x30 },
+	{ STB0899_IDCCOMP,	0xfd },
+	{ STB0899_QDCCOMP,	0xff },
+	{ STB0899_POWERI,	0x0c },
+	{ STB0899_POWERQ,	0x0f },
+	{ STB0899_RCOMP,	0x6c },
+	{ STB0899_AGCIQIN,	0x80 },
+	{ STB0899_AGC2I1,	0x06 },
+	{ STB0899_AGC2I2,	0x00 },
+	{ STB0899_TLIR,		0x30 },
+	{ STB0899_RTF,		0x7f },
+	{ STB0899_DSTATUS,	0x00 },
+	{ STB0899_LDI,		0xbc },
+	{ STB0899_CFRM,		0xea },
+	{ STB0899_CFRL,		0x31 },
+	{ STB0899_NIRM,		0x2b },
+	{ STB0899_NIRL,		0x80 },
+	{ STB0899_ISYMB,	0x1d },
+	{ STB0899_QSYMB,	0xa6 },
+	{ STB0899_SFRH,		0x2f },
+	{ STB0899_SFRM,		0x68 },
+	{ STB0899_SFRL,		0x40 },
+	{ STB0899_SFRUPH,	0x2f },
+	{ STB0899_SFRUPM,	0x68 },
+	{ STB0899_SFRUPL,	0x40 },
+	{ STB0899_EQUAI1,	0x02 },
+	{ STB0899_EQUAQ1,	0xff },
+	{ STB0899_EQUAI2,	0x04 },
+	{ STB0899_EQUAQ2,	0x05 },
+	{ STB0899_EQUAI3,	0x02 },
+	{ STB0899_EQUAQ3,	0xfd },
+	{ STB0899_EQUAI4,	0x03 },
+	{ STB0899_EQUAQ4,	0x07 },
+	{ STB0899_EQUAI5,	0x08 },
+	{ STB0899_EQUAQ5,	0xf5 },
+	{ STB0899_DSTATUS2,	0x00 },
+	{ STB0899_VSTATUS,	0x00 },
+	{ STB0899_VERROR,	0x86 },
+	{ STB0899_IQSWAP,	0x2a },
+	{ STB0899_ECNT1M,	0x00 },
+	{ STB0899_ECNT1L,	0x00 },
+	{ STB0899_ECNT2M,	0x00 },
+	{ STB0899_ECNT2L,	0x00 },
+	{ STB0899_ECNT3M,	0x0a },
+	{ STB0899_ECNT3L,	0xad },
+	{ STB0899_FECAUTO1,	0x06 },
+	{ STB0899_FECM,		0x01 },
+	{ STB0899_VTH12,	0xb0 },
+	{ STB0899_VTH23,	0x7a },
+	{ STB0899_VTH34,	0x58 },
+	{ STB0899_VTH56,	0x38 },
+	{ STB0899_VTH67,	0x34 },
+	{ STB0899_VTH78,	0x24 },
+	{ STB0899_PRVIT,	0xff },
+	{ STB0899_VITSYNC,	0x19 },
+	{ STB0899_RSULC,	0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
+	{ STB0899_TSULC,	0x42 },
+	{ STB0899_RSLLC,	0x41 },
+	{ STB0899_TSLPL,	0x12 },
+	{ STB0899_TSCFGH,	0x0c },
+	{ STB0899_TSCFGM,	0x00 },
+	{ STB0899_TSCFGL,	0x00 },
+	{ STB0899_TSOUT,	0x69 }, /* 0x0d for CAM */
+	{ STB0899_RSSYNCDEL,	0x00 },
+	{ STB0899_TSINHDELH,	0x02 },
+	{ STB0899_TSINHDELM,	0x00 },
+	{ STB0899_TSINHDELL,	0x00 },
+	{ STB0899_TSLLSTKM,	0x1b },
+	{ STB0899_TSLLSTKL,	0xb3 },
+	{ STB0899_TSULSTKM,	0x00 },
+	{ STB0899_TSULSTKL,	0x00 },
+	{ STB0899_PCKLENUL,	0xbc },
+	{ STB0899_PCKLENLL,	0xcc },
+	{ STB0899_RSPCKLEN,	0xbd },
+	{ STB0899_TSSTATUS,	0x90 },
+	{ STB0899_ERRCTRL1,	0xb6 },
+	{ STB0899_ERRCTRL2,	0x95 },
+	{ STB0899_ERRCTRL3,	0x8d },
+	{ STB0899_DMONMSK1,	0x27 },
+	{ STB0899_DMONMSK0,	0x03 },
+	{ STB0899_DEMAPVIT,	0x5c },
+	{ STB0899_PLPARM,	0x19 },
+	{ STB0899_PDELCTRL,	0x48 },
+	{ STB0899_PDELCTRL2,	0x00 },
+	{ STB0899_BBHCTRL1,	0x00 },
+	{ STB0899_BBHCTRL2,	0x00 },
+	{ STB0899_HYSTTHRESH,	0x77 },
+	{ STB0899_MATCSTM,	0x00 },
+	{ STB0899_MATCSTL,	0x00 },
+	{ STB0899_UPLCSTM,	0x00 },
+	{ STB0899_UPLCSTL,	0x00 },
+	{ STB0899_DFLCSTM,	0x00 },
+	{ STB0899_DFLCSTL,	0x00 },
+	{ STB0899_SYNCCST,	0x00 },
+	{ STB0899_SYNCDCSTM,	0x00 },
+	{ STB0899_SYNCDCSTL,	0x00 },
+	{ STB0899_ISI_ENTRY,	0x00 },
+	{ STB0899_ISI_BIT_EN,	0x00 },
+	{ STB0899_MATSTRM,	0xf0 },
+	{ STB0899_MATSTRL,	0x02 },
+	{ STB0899_UPLSTRM,	0x45 },
+	{ STB0899_UPLSTRL,	0x60 },
+	{ STB0899_DFLSTRM,	0xe3 },
+	{ STB0899_DFLSTRL,	0x00 },
+	{ STB0899_SYNCSTR,	0x47 },
+	{ STB0899_SYNCDSTRM,	0x05 },
+	{ STB0899_SYNCDSTRL,	0x18 },
+	{ STB0899_CFGPDELSTATUS1, 0x19 },
+	{ STB0899_CFGPDELSTATUS2, 0x2b },
+	{ STB0899_BBFERRORM,	0x00 },
+	{ STB0899_BBFERRORL,	0x01 },
+	{ STB0899_UPKTERRORM,	0x00 },
+	{ STB0899_UPKTERRORL,	0x00 },
+	{ 0xffff,		0xff },
+};
+
+static struct stb0899_config stb0899_config = {
+	.init_dev	= pctv452e_init_dev,
+	.init_s2_demod	= stb0899_s2_init_2,
+	.init_s1_demod	= pctv452e_init_s1_demod,
+	.init_s2_fec	= stb0899_s2_init_4,
+	.init_tst	= stb0899_s1_init_5,
+
+	.demod_address   = I2C_ADDR_STB0899, /* I2C Address */
+	.block_sync_mode = STB0899_SYNC_FORCED, /* ? */
+
+	.xtal_freq       = 27000000,	 /* Assume Hz ? */
+	.inversion       = IQ_SWAP_ON,       /* ? */
+
+	.lo_clk	  = 76500000,
+	.hi_clk	  = 99000000,
+
+	.ts_output_mode  = 0,	/* Use parallel mode */
+	.clock_polarity  = 0,
+	.data_clk_parity = 0,
+	.fec_mode	= 0,
+
+	.esno_ave	    = STB0899_DVBS2_ESNO_AVE,
+	.esno_quant	  = STB0899_DVBS2_ESNO_QUANT,
+	.avframes_coarse     = STB0899_DVBS2_AVFRAMES_COARSE,
+	.avframes_fine       = STB0899_DVBS2_AVFRAMES_FINE,
+	.miss_threshold      = STB0899_DVBS2_MISS_THRESHOLD,
+	.uwp_threshold_acq   = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
+	.uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
+	.uwp_threshold_sof   = STB0899_DVBS2_UWP_THRESHOLD_SOF,
+	.sof_search_timeout  = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
+
+	.btr_nco_bits	  = STB0899_DVBS2_BTR_NCO_BITS,
+	.btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
+	.crl_nco_bits	  = STB0899_DVBS2_CRL_NCO_BITS,
+	.ldpc_max_iter	 = STB0899_DVBS2_LDPC_MAX_ITER,
+
+	.tuner_get_frequency	= stb6100_get_frequency,
+	.tuner_set_frequency	= stb6100_set_frequency,
+	.tuner_set_bandwidth	= stb6100_set_bandwidth,
+	.tuner_get_bandwidth	= stb6100_get_bandwidth,
+	.tuner_set_rfsiggain	= NULL,
+
+	/* helper for switching LED green/orange */
+	.postproc = pctv45e_postproc
+};
+
+static struct stb6100_config stb6100_config = {
+	.tuner_address = I2C_ADDR_STB6100,
+	.refclock      = 27000000
+};
+
+
+static struct i2c_algorithm pctv452e_i2c_algo = {
+	.master_xfer   = pctv452e_i2c_xfer,
+	.functionality = pctv452e_i2c_func
+};
+
+static int pctv452e_frontend_attach(struct dvb_usb_adapter *a)
+{
+	struct usb_device_id *id;
+
+	a->fe_adap[0].fe = dvb_attach(stb0899_attach, &stb0899_config,
+						&a->dev->i2c_adap);
+	if (!a->fe_adap[0].fe)
+		return -ENODEV;
+	if ((dvb_attach(lnbp22_attach, a->fe_adap[0].fe,
+					&a->dev->i2c_adap)) == 0)
+		err("Cannot attach lnbp22\n");
+
+	id = a->dev->desc->warm_ids[0];
+	if (USB_VID_TECHNOTREND == id->idVendor
+	    && USB_PID_TECHNOTREND_CONNECT_S2_3650_CI == id->idProduct)
+		/* Error ignored. */
+		tt3650_ci_init(a);
+
+	return 0;
+}
+
+static int pctv452e_tuner_attach(struct dvb_usb_adapter *a)
+{
+	if (!a->fe_adap[0].fe)
+		return -ENODEV;
+	if (dvb_attach(stb6100_attach, a->fe_adap[0].fe, &stb6100_config,
+					&a->dev->i2c_adap) == 0) {
+		err("%s failed\n", __func__);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static struct usb_device_id pctv452e_usb_table[] = {
+	{USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_452E)},
+	{USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_CONNECT_S2_3600)},
+	{USB_DEVICE(USB_VID_TECHNOTREND,
+				USB_PID_TECHNOTREND_CONNECT_S2_3650_CI)},
+	{}
+};
+MODULE_DEVICE_TABLE(usb, pctv452e_usb_table);
+
+static struct dvb_usb_device_properties pctv452e_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER, /* more ? */
+	.usb_ctrl = DEVICE_SPECIFIC,
+
+	.size_of_priv     = sizeof(struct pctv452e_state),
+
+	.power_ctrl       = pctv452e_power_ctrl,
+
+	.rc.core = {
+		.rc_codes	= RC_MAP_DIB0700_RC5_TABLE,
+		.allowed_protos	= RC_TYPE_UNKNOWN,
+		.rc_query	= pctv452e_rc_query,
+		.rc_interval	= 100,
+	},
+
+	.num_adapters     = 1,
+	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
+			.frontend_attach  = pctv452e_frontend_attach,
+			.tuner_attach     = pctv452e_tuner_attach,
+
+			/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type     = USB_ISOC,
+				.count    = 4,
+				.endpoint = 0x02,
+				.u = {
+					.isoc = {
+						.framesperurb = 4,
+						.framesize    = 940,
+						.interval     = 1
+					}
+				}
+			},
+		} },
+	} },
+
+	.i2c_algo = &pctv452e_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 1, /* allow generice rw function */
+
+	.num_device_descs = 1,
+	.devices = {
+		{ .name = "PCTV HDTV USB",
+		  .cold_ids = { NULL, NULL }, /* this is a warm only device */
+		  .warm_ids = { &pctv452e_usb_table[0], NULL }
+		},
+		{ 0 },
+	}
+};
+
+static struct dvb_usb_device_properties tt_connect_s2_3600_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER, /* more ? */
+	.usb_ctrl = DEVICE_SPECIFIC,
+
+	.size_of_priv		= sizeof(struct pctv452e_state),
+
+	.power_ctrl		= pctv452e_power_ctrl,
+	.read_mac_address	= pctv452e_read_mac_address,
+
+	.rc.core = {
+		.rc_codes	= RC_MAP_TT_1500,
+		.allowed_protos	= RC_TYPE_UNKNOWN,
+		.rc_query	= pctv452e_rc_query,
+		.rc_interval	= 100,
+	},
+
+	.num_adapters		= 1,
+	.adapter = {{
+		.num_frontends = 1,
+		.fe = {{
+			.frontend_attach = pctv452e_frontend_attach,
+			.tuner_attach = pctv452e_tuner_attach,
+
+			/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_ISOC,
+				.count = 7,
+				.endpoint = 0x02,
+				.u = {
+					.isoc = {
+						.framesperurb = 4,
+						.framesize = 940,
+						.interval = 1
+					}
+				}
+			},
+
+		} },
+	} },
+
+	.i2c_algo = &pctv452e_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 1, /* allow generic rw function*/
+
+	.num_device_descs = 2,
+	.devices = {
+		{ .name = "Technotrend TT Connect S2-3600",
+		  .cold_ids = { NULL, NULL }, /* this is a warm only device */
+		  .warm_ids = { &pctv452e_usb_table[1], NULL }
+		},
+		{ .name = "Technotrend TT Connect S2-3650-CI",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &pctv452e_usb_table[2], NULL }
+		},
+		{ 0 },
+	}
+};
+
+static void pctv452e_usb_disconnect(struct usb_interface *intf)
+{
+	struct dvb_usb_device *d = usb_get_intfdata(intf);
+
+	tt3650_ci_uninit(d);
+	dvb_usb_device_exit(intf);
+}
+
+static int pctv452e_usb_probe(struct usb_interface *intf,
+				const struct usb_device_id *id)
+{
+	if (0 == dvb_usb_device_init(intf, &pctv452e_properties,
+					THIS_MODULE, NULL, adapter_nr) ||
+	    0 == dvb_usb_device_init(intf, &tt_connect_s2_3600_properties,
+					THIS_MODULE, NULL, adapter_nr))
+		return 0;
+
+	return -ENODEV;
+}
+
+static struct usb_driver pctv452e_usb_driver = {
+	.name       = "pctv452e",
+	.probe      = pctv452e_usb_probe,
+	.disconnect = pctv452e_usb_disconnect,
+	.id_table   = pctv452e_usb_table,
+};
+
+static int __init pctv452e_usb_init(void)
+{
+	int ret = usb_register(&pctv452e_usb_driver);
+	if (ret)
+		err("%s: usb_register failed! Error %d", __FILE__, ret);
+
+	return ret;
+}
+
+static void __exit pctv452e_usb_exit(void)
+{
+	usb_deregister(&pctv452e_usb_driver);
+}
+
+module_init(pctv452e_usb_init);
+module_exit(pctv452e_usb_exit);
+
+MODULE_AUTHOR("Dominik Kuhlen <dkuhlen@gmx.net>");
+MODULE_AUTHOR("Andre Weidemann <Andre.Weidemann@web.de>");
+MODULE_AUTHOR("Michael H. Schimek <mschimek@gmx.at>");
+MODULE_DESCRIPTION("Pinnacle PCTV HDTV USB DVB / TT connect S2-3600 Driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/technisat-usb2.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/technisat-usb2.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/technisat-usb2.c	2012-03-19 21:34:06.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/technisat-usb2.c	2012-03-19 21:36:30.000000000 -0400
@@ -292,7 +292,7 @@
 {
 	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;
+	struct dvb_frontend *fe = state->dev->adapter[0].fe_adap[0].fe;
 
 	if (state->power_state == 0)
 		goto schedule;
@@ -505,14 +505,14 @@
 	struct usb_device *udev = a->dev->udev;
 	int ret;
 
-	a->fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config,
+	a->fe_adap[0].fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config,
 			&a->dev->i2c_adap, STV090x_DEMODULATOR_0);
 
-	if (a->fe) {
+	if (a->fe_adap[0].fe) {
 		struct stv6110x_devctl *ctl;
 
 		ctl = dvb_attach(stv6110x_attach,
-				a->fe,
+				a->fe_adap[0].fe,
 				&technisat_usb2_stv6110x_config,
 				&a->dev->i2c_adap);
 
@@ -532,8 +532,8 @@
 			/* 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 (a->fe_adap[0].fe->ops.init)
+				a->fe_adap[0].fe->ops.init(a->fe_adap[0].fe);
 
 			if (mutex_lock_interruptible(&a->dev->i2c_mutex) < 0)
 				return -EAGAIN;
@@ -548,20 +548,20 @@
 			if (ret != 0)
 				err("could not set IF_CLK to external");
 
-			a->fe->ops.set_voltage = technisat_usb2_set_voltage;
+			a->fe_adap[0].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));
+			strlcpy(a->fe_adap[0].fe->ops.info.name, a->dev->desc->name,
+					sizeof(a->fe_adap[0].fe->ops.info.name));
 		} else {
-			dvb_frontend_detach(a->fe);
-			a->fe = NULL;
+			dvb_frontend_detach(a->fe_adap[0].fe);
+			a->fe_adap[0].fe = NULL;
 		}
 	}
 
 	technisat_usb2_set_led_timer(a->dev, 1, 1);
 
-	return a->fe == NULL ? -ENODEV : 0;
+	return a->fe_adap[0].fe == NULL ? -ENODEV : 0;
 }
 
 /* Remote control */
@@ -697,6 +697,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach  = technisat_usb2_frontend_attach,
 
 			.stream = {
@@ -711,7 +713,7 @@
 					}
 				}
 			},
-
+		}},
 			.size_of_priv = 0,
 		},
 	},
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/ttusb2.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/ttusb2.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/ttusb2.c	2012-03-19 21:34:14.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/ttusb2.c	2012-03-19 21:36:37.000000000 -0400
@@ -30,18 +30,43 @@
 #include "tda826x.h"
 #include "tda10086.h"
 #include "tda1002x.h"
+#include "tda10048.h"
 #include "tda827x.h"
 #include "lnbp21.h"
+/* CA */
+#include "dvb_ca_en50221.h"
 
 /* debug */
 static int dvb_usb_ttusb2_debug;
 #define deb_info(args...)   dprintk(dvb_usb_ttusb2_debug,0x01,args)
 module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
+static int dvb_usb_ttusb2_debug_ci;
+module_param_named(debug_ci,dvb_usb_ttusb2_debug_ci, int, 0644);
+MODULE_PARM_DESC(debug_ci, "set debugging ci." DVB_USB_DEBUG_STATUS);
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
+#define ci_dbg(format, arg...)                \
+do {                                          \
+	if (dvb_usb_ttusb2_debug_ci)                                    \
+		printk(KERN_DEBUG DVB_USB_LOG_PREFIX \
+			": %s " format "\n" , __func__, ## arg);       \
+} while (0)
+
+enum {
+	TT3650_CMD_CI_TEST = 0x40,
+	TT3650_CMD_CI_RD_CTRL,
+	TT3650_CMD_CI_WR_CTRL,
+	TT3650_CMD_CI_RD_ATTR,
+	TT3650_CMD_CI_WR_ATTR,
+	TT3650_CMD_CI_RESET,
+	TT3650_CMD_CI_SET_VIDEO_PORT
+};
+
 struct ttusb2_state {
+	struct dvb_ca_en50221 ca;
+	struct mutex ca_mutex;
 	u8 id;
 	u16 last_rc_key;
 };
@@ -78,11 +103,260 @@
 	return 0;
 }
 
+/* ci */
+static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
+{
+	int ret;
+	u8 rx[60];/* (64 -4) */
+	ret = ttusb2_msg(d, cmd, data, write_len, rx, read_len);
+	if (!ret)
+		memcpy(data, rx, read_len);
+	return ret;
+}
+
+static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
+{
+	struct dvb_usb_device *d = ca->data;
+	struct ttusb2_state *state = d->priv;
+	int ret;
+
+	mutex_lock(&state->ca_mutex);
+	ret = tt3650_ci_msg(d, cmd, data, write_len, read_len);
+	mutex_unlock(&state->ca_mutex);
+
+	return ret;
+}
+
+static int tt3650_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
+{
+	u8 buf[3];
+	int ret = 0;
+
+	if (slot)
+		return -EINVAL;
+
+	buf[0] = (address >> 8) & 0x0F;
+	buf[1] = address;
+
+
+	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_ATTR, buf, 2, 3);
+
+	ci_dbg("%04x -> %d 0x%02x", address, ret, buf[2]);
+
+	if (ret < 0)
+		return ret;
+
+	return buf[2];
+}
+
+static int tt3650_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
+{
+	u8 buf[3];
+
+	ci_dbg("%d 0x%04x 0x%02x", slot, address, value);
+
+	if (slot)
+		return -EINVAL;
+
+	buf[0] = (address >> 8) & 0x0F;
+	buf[1] = address;
+	buf[2] = value;
+
+	return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_ATTR, buf, 3, 3);
+}
+
+static int tt3650_ci_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
+{
+	u8 buf[2];
+	int ret;
+
+	if (slot)
+		return -EINVAL;
+
+	buf[0] = address & 3;
+
+	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_CTRL, buf, 1, 2);
+
+	ci_dbg("0x%02x -> %d 0x%02x", address, ret, buf[1]);
+
+	if (ret < 0)
+		return ret;
+
+	return buf[1];
+}
+
+static int tt3650_ci_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
+{
+	u8 buf[2];
+
+	ci_dbg("%d 0x%02x 0x%02x", slot, address, value);
+
+	if (slot)
+		return -EINVAL;
+
+	buf[0] = address;
+	buf[1] = value;
+
+	return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_CTRL, buf, 2, 2);
+}
+
+static int tt3650_ci_set_video_port(struct dvb_ca_en50221 *ca, int slot, int enable)
+{
+	u8 buf[1];
+	int ret;
+
+	ci_dbg("%d %d", slot, enable);
+
+	if (slot)
+		return -EINVAL;
+
+	buf[0] = enable;
+
+	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
+	if (ret < 0)
+		return ret;
+
+	if (enable != buf[0]) {
+		err("CI not %sabled.", enable ? "en" : "dis");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int tt3650_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
+{
+	return tt3650_ci_set_video_port(ca, slot, 0);
+}
+
+static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
+{
+	return tt3650_ci_set_video_port(ca, slot, 1);
+}
+
+static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
+{
+	struct dvb_usb_device *d = ca->data;
+	struct ttusb2_state *state = d->priv;
+	u8 buf[1];
+	int ret;
+
+	ci_dbg("%d", slot);
+
+	if (slot)
+		return -EINVAL;
+
+	buf[0] = 0;
+
+	mutex_lock(&state->ca_mutex);
+
+	ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
+	if (ret)
+		goto failed;
+
+	msleep(500);
+
+	buf[0] = 1;
+
+	ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
+	if (ret)
+		goto failed;
+
+	msleep(500);
+
+	buf[0] = 0; /* FTA */
+
+	ret = tt3650_ci_msg(d, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
+
+	msleep(1100);
+
+ failed:
+	mutex_unlock(&state->ca_mutex);
+
+	return ret;
+}
+
+static int tt3650_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
+{
+	u8 buf[1];
+	int ret;
+
+	if (slot)
+		return -EINVAL;
+
+	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_TEST, buf, 0, 1);
+	if (ret)
+		return ret;
+
+	if (1 == buf[0]) {
+		return DVB_CA_EN50221_POLL_CAM_PRESENT |
+			DVB_CA_EN50221_POLL_CAM_READY;
+	}
+	return 0;
+}
+
+static void tt3650_ci_uninit(struct dvb_usb_device *d)
+{
+	struct ttusb2_state *state;
+
+	ci_dbg("");
+
+	if (NULL == d)
+		return;
+
+	state = d->priv;
+	if (NULL == state)
+		return;
+
+	if (NULL == state->ca.data)
+		return;
+
+	dvb_ca_en50221_release(&state->ca);
+
+	memset(&state->ca, 0, sizeof(state->ca));
+}
+
+static int tt3650_ci_init(struct dvb_usb_adapter *a)
+{
+	struct dvb_usb_device *d = a->dev;
+	struct ttusb2_state *state = d->priv;
+	int ret;
+
+	ci_dbg("");
+
+	mutex_init(&state->ca_mutex);
+
+	state->ca.owner = THIS_MODULE;
+	state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem;
+	state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem;
+	state->ca.read_cam_control = tt3650_ci_read_cam_control;
+	state->ca.write_cam_control = tt3650_ci_write_cam_control;
+	state->ca.slot_reset = tt3650_ci_slot_reset;
+	state->ca.slot_shutdown = tt3650_ci_slot_shutdown;
+	state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable;
+	state->ca.poll_slot_status = tt3650_ci_poll_slot_status;
+	state->ca.data = d;
+
+	ret = dvb_ca_en50221_init(&a->dvb_adap,
+				  &state->ca,
+				  /* flags */ 0,
+				  /* n_slots */ 1);
+	if (ret) {
+		err("Cannot initialize CI: Error %d.", ret);
+		memset(&state->ca, 0, sizeof(state->ca));
+		return ret;
+	}
+
+	info("CI initialized.");
+
+	return 0;
+}
+
 static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
 {
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
 	static u8 obuf[60], ibuf[60];
-	int i,read;
+	int i, write_read, read;
 
 	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
 		return -EAGAIN;
@@ -91,28 +365,35 @@
 		warn("more than 2 i2c messages at a time is not handled yet. TODO.");
 
 	for (i = 0; i < num; i++) {
-		read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
+		write_read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
+		read = msg[i].flags & I2C_M_RD;
 
-		obuf[0] = (msg[i].addr << 1) | read;
-		obuf[1] = msg[i].len;
+		obuf[0] = (msg[i].addr << 1) | (write_read | read);
+		if (read)
+			obuf[1] = 0;
+		else
+			obuf[1] = msg[i].len;
 
 		/* read request */
-		if (read)
+		if (write_read)
 			obuf[2] = msg[i+1].len;
+		else if (read)
+			obuf[2] = msg[i].len;
 		else
 			obuf[2] = 0;
 
-		memcpy(&obuf[3],msg[i].buf,msg[i].len);
+		memcpy(&obuf[3], msg[i].buf, msg[i].len);
 
 		if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) {
 			err("i2c transfer failed.");
 			break;
 		}
 
-		if (read) {
-			memcpy(msg[i+1].buf,&ibuf[3],msg[i+1].len);
+		if (write_read) {
+			memcpy(msg[i+1].buf, &ibuf[3], msg[i+1].len);
 			i++;
-		}
+		} else if (read)
+			memcpy(msg[i].buf, &ibuf[3], msg[i].len);
 	}
 
 	mutex_unlock(&d->i2c_mutex);
@@ -190,12 +471,31 @@
 	.deltaf = 0xa511,
 };
 
+static struct tda10048_config tda10048_config = {
+	.demod_address    = 0x10 >> 1,
+	.output_mode      = TDA10048_PARALLEL_OUTPUT,
+	.inversion        = TDA10048_INVERSION_ON,
+	.dtv6_if_freq_khz = TDA10048_IF_4000,
+	.dtv7_if_freq_khz = TDA10048_IF_4500,
+	.dtv8_if_freq_khz = TDA10048_IF_5000,
+	.clk_freq_khz     = TDA10048_CLK_16000,
+	.no_firmware      = 1,
+	.set_pll          = true ,
+	.pll_m            = 5,
+	.pll_n            = 3,
+	.pll_p            = 0,
+};
+
+static struct tda827x_config tda827x_config = {
+	.config = 0,
+};
+
 static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
 {
 	if (usb_set_interface(adap->dev->udev,0,3) < 0)
 		err("set interface to alts=3 failed");
 
-	if ((adap->fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
+	if ((adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
 		deb_info("TDA10086 attach failed\n");
 		return -ENODEV;
 	}
@@ -203,20 +503,57 @@
 	return 0;
 }
 
+static int ttusb2_ct3650_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+
+	return adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, enable);
+}
+
 static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap)
 {
 	if (usb_set_interface(adap->dev->udev, 0, 3) < 0)
 		err("set interface to alts=3 failed");
-	if ((adap->fe = dvb_attach(tda10023_attach, &tda10023_config, &adap->dev->i2c_adap, 0x48)) == NULL) {
-		deb_info("TDA10023 attach failed\n");
-		return -ENODEV;
+
+	if (adap->fe_adap[0].fe == NULL) {
+		/* FE 0 DVB-C */
+		adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
+			&tda10023_config, &adap->dev->i2c_adap, 0x48);
+
+		if (adap->fe_adap[0].fe == NULL) {
+			deb_info("TDA10023 attach failed\n");
+			return -ENODEV;
+		}
+		tt3650_ci_init(adap);
+	} else {
+		adap->fe_adap[1].fe = dvb_attach(tda10048_attach,
+			&tda10048_config, &adap->dev->i2c_adap);
+
+		if (adap->fe_adap[1].fe == NULL) {
+			deb_info("TDA10048 attach failed\n");
+			return -ENODEV;
+		}
+
+		/* tuner is behind TDA10023 I2C-gate */
+		adap->fe_adap[1].fe->ops.i2c_gate_ctrl = ttusb2_ct3650_i2c_gate_ctrl;
+
 	}
+
 	return 0;
 }
 
 static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
 {
-	if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL) {
+	struct dvb_frontend *fe;
+
+	/* MFE: select correct FE to attach tuner since that's called twice */
+	if (adap->fe_adap[1].fe == NULL)
+		fe = adap->fe_adap[0].fe;
+	else
+		fe = adap->fe_adap[1].fe;
+
+	/* attach tuner */
+	if (dvb_attach(tda827x_attach, fe, 0x61, &adap->dev->i2c_adap, &tda827x_config) == NULL) {
 		printk(KERN_ERR "%s: No tda827x found!\n", __func__);
 		return -ENODEV;
 	}
@@ -225,12 +562,12 @@
 
 static int ttusb2_tuner_tda826x_attach(struct dvb_usb_adapter *adap)
 {
-	if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
+	if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
 		deb_info("TDA8263 attach failed\n");
 		return -ENODEV;
 	}
 
-	if (dvb_attach(lnbp21_attach, adap->fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
+	if (dvb_attach(lnbp21_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
 		deb_info("LNBP21 attach failed\n");
 		return -ENODEV;
 	}
@@ -242,6 +579,14 @@
 static struct dvb_usb_device_properties ttusb2_properties_s2400;
 static struct dvb_usb_device_properties ttusb2_properties_ct3650;
 
+static void ttusb2_usb_disconnect(struct usb_interface *intf)
+{
+	struct dvb_usb_device *d = usb_get_intfdata(intf);
+
+	tt3650_ci_uninit(d);
+	dvb_usb_device_exit(intf);
+}
+
 static int ttusb2_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
 {
@@ -277,6 +622,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = NULL, // ttusb2_streaming_ctrl,
 
 			.frontend_attach  = ttusb2_frontend_tda10086_attach,
@@ -295,6 +642,7 @@
 					}
 				}
 			}
+		}},
 		}
 	},
 
@@ -329,6 +677,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = NULL,
 
 			.frontend_attach  = ttusb2_frontend_tda10086_attach,
@@ -347,6 +697,7 @@
 					}
 				}
 			}
+		}},
 		}
 	},
 
@@ -383,6 +734,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 2,
+		.fe = {{
 			.streaming_ctrl   = NULL,
 
 			.frontend_attach  = ttusb2_frontend_tda10023_attach,
@@ -401,6 +754,26 @@
 					}
 				}
 			}
+		}, {
+			.streaming_ctrl   = NULL,
+
+			.frontend_attach  = ttusb2_frontend_tda10023_attach,
+			.tuner_attach = ttusb2_tuner_tda827x_attach,
+
+			/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_ISOC,
+				.count = 5,
+				.endpoint = 0x02,
+				.u = {
+					.isoc = {
+						.framesperurb = 4,
+						.framesize = 940,
+						.interval = 1,
+					}
+				}
+			}
+		}},
 		},
 	},
 
@@ -422,7 +795,7 @@
 static struct usb_driver ttusb2_driver = {
 	.name		= "dvb_usb_ttusb2",
 	.probe		= ttusb2_probe,
-	.disconnect = dvb_usb_device_exit,
+	.disconnect	= ttusb2_usb_disconnect,
 	.id_table	= ttusb2_table,
 };
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/umt-010.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/umt-010.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/umt-010.c	2012-03-19 21:34:21.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/umt-010.c	2012-03-19 21:36:44.000000000 -0400
@@ -60,14 +60,14 @@
 	umt_config.demod_init = umt_mt352_demod_init;
 	umt_config.demod_address = 0xf;
 
-	adap->fe = dvb_attach(mt352_attach, &umt_config, &adap->dev->i2c_adap);
+	adap->fe_adap[0].fe = dvb_attach(mt352_attach, &umt_config, &adap->dev->i2c_adap);
 
 	return 0;
 }
 
 static int umt_tuner_attach (struct dvb_usb_adapter *adap)
 {
-	dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, DVB_PLL_TUA6034);
+	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, NULL, DVB_PLL_TUA6034);
 	return 0;
 }
 
@@ -100,6 +100,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.streaming_ctrl   = dibusb2_0_streaming_ctrl,
 			.frontend_attach  = umt_mt352_frontend_attach,
 			.tuner_attach     = umt_tuner_attach,
@@ -115,7 +117,7 @@
 					}
 				}
 			},
-
+		}},
 			.size_of_priv     = sizeof(struct dibusb_state),
 		}
 	},
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/usb-urb.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/usb-urb.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/usb-urb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/usb-urb.c	2012-01-04 18:55:44.000000000 -0500
@@ -148,7 +148,7 @@
 		if (!stream->urb_list[i]) {
 			deb_mem("not enough memory for urb_alloc_urb!.\n");
 			for (j = 0; j < i; j++)
-				usb_free_urb(stream->urb_list[i]);
+				usb_free_urb(stream->urb_list[j]);
 			return -ENOMEM;
 		}
 		usb_fill_bulk_urb( stream->urb_list[i], stream->udev,
@@ -181,7 +181,7 @@
 		if (!stream->urb_list[i]) {
 			deb_mem("not enough memory for urb_alloc_urb!\n");
 			for (j = 0; j < i; j++)
-				usb_free_urb(stream->urb_list[i]);
+				usb_free_urb(stream->urb_list[j]);
 			return -ENOMEM;
 		}
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/vp702x.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/vp702x.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/vp702x.c	2012-03-19 21:34:29.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/vp702x.c	2012-03-19 21:36:52.000000000 -0400
@@ -320,7 +320,7 @@
 
 	vp702x_init_pid_filter(adap);
 
-	adap->fe = vp702x_fe_attach(adap->dev);
+	adap->fe_adap[0].fe = vp702x_fe_attach(adap->dev);
 	vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 1, 7, NULL, 0);
 
 	return 0;
@@ -383,6 +383,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.caps             = DVB_USB_ADAP_RECEIVES_204_BYTE_TS,
 
 			.streaming_ctrl   = vp702x_streaming_ctrl,
@@ -399,6 +401,7 @@
 					}
 				}
 			},
+		}},
 			.size_of_priv     = sizeof(struct vp702x_adapter_state),
 		}
 	},
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/vp7045.c linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/vp7045.c
--- linux-libre-3.1-gnu/drivers/media/dvb/dvb-usb/vp7045.c	2012-03-19 21:34:36.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/dvb-usb/vp7045.c	2012-03-19 21:37:00.000000000 -0400
@@ -214,7 +214,7 @@
 /*	Dump the EEPROM */
 /*	vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */
 
-	adap->fe = vp7045_fe_attach(adap->dev);
+	adap->fe_adap[0].fe = vp7045_fe_attach(adap->dev);
 
 	return 0;
 }
@@ -245,6 +245,8 @@
 	.num_adapters = 1,
 	.adapter = {
 		{
+		.num_frontends = 1,
+		.fe = {{
 			.frontend_attach  = vp7045_frontend_attach,
 			/* parameter for the MPEG2-data transfer */
 			.stream = {
@@ -257,6 +259,7 @@
 					}
 				}
 			},
+		}},
 		}
 	},
 	.power_ctrl       = vp7045_power_ctrl,
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/a8293.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/a8293.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/a8293.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/a8293.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,184 @@
+/*
+ * Allegro A8293 SEC driver
+ *
+ * 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 "dvb_frontend.h"
+#include "a8293.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+#define LOG_PREFIX "a8293"
+
+#undef dbg
+#define dbg(f, arg...) \
+	if (debug) \
+		printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
+#undef err
+#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
+#undef info
+#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
+#undef warn
+#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
+
+
+struct a8293_priv {
+	struct i2c_adapter *i2c;
+	const struct a8293_config *cfg;
+	u8 reg[2];
+};
+
+static int a8293_i2c(struct a8293_priv *priv, u8 *val, int len, bool rd)
+{
+	int ret;
+	struct i2c_msg msg[1] = {
+		{
+			.addr = priv->cfg->i2c_addr,
+			.len = len,
+			.buf = val,
+		}
+	};
+
+	if (rd)
+		msg[0].flags = I2C_M_RD;
+	else
+		msg[0].flags = 0;
+
+	ret = i2c_transfer(priv->i2c, msg, 1);
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		warn("i2c failed=%d rd=%d", ret, rd);
+		ret = -EREMOTEIO;
+	}
+
+	return ret;
+}
+
+static int a8293_wr(struct a8293_priv *priv, u8 *val, int len)
+{
+	return a8293_i2c(priv, val, len, 0);
+}
+
+static int a8293_rd(struct a8293_priv *priv, u8 *val, int len)
+{
+	return a8293_i2c(priv, val, len, 1);
+}
+
+static int a8293_set_voltage(struct dvb_frontend *fe,
+	fe_sec_voltage_t fe_sec_voltage)
+{
+	struct a8293_priv *priv = fe->sec_priv;
+	int ret;
+
+	dbg("%s: fe_sec_voltage=%d", __func__, fe_sec_voltage);
+
+	switch (fe_sec_voltage) {
+	case SEC_VOLTAGE_OFF:
+		/* ENB=0 */
+		priv->reg[0] = 0x10;
+		break;
+	case SEC_VOLTAGE_13:
+		/* VSEL0=1, VSEL1=0, VSEL2=0, VSEL3=0, ENB=1*/
+		priv->reg[0] = 0x31;
+		break;
+	case SEC_VOLTAGE_18:
+		/* VSEL0=0, VSEL1=0, VSEL2=0, VSEL3=1, ENB=1*/
+		priv->reg[0] = 0x38;
+		break;
+	default:
+		ret = -EINVAL;
+		goto err;
+	};
+
+	ret = a8293_wr(priv, &priv->reg[0], 1);
+	if (ret)
+		goto err;
+
+	return ret;
+err:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static void a8293_release_sec(struct dvb_frontend *fe)
+{
+	dbg("%s:", __func__);
+
+	a8293_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+	kfree(fe->sec_priv);
+	fe->sec_priv = NULL;
+}
+
+struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, const struct a8293_config *cfg)
+{
+	int ret;
+	struct a8293_priv *priv = NULL;
+	u8 buf[2];
+
+	/* allocate memory for the internal priv */
+	priv = kzalloc(sizeof(struct a8293_priv), GFP_KERNEL);
+	if (priv == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* setup the priv */
+	priv->i2c = i2c;
+	priv->cfg = cfg;
+	fe->sec_priv = priv;
+
+	/* check if the SEC is there */
+	ret = a8293_rd(priv, buf, 2);
+	if (ret)
+		goto err;
+
+	/* ENB=0 */
+	priv->reg[0] = 0x10;
+	ret = a8293_wr(priv, &priv->reg[1], 1);
+	if (ret)
+		goto err;
+
+	/* TMODE=0, TGATE=1 */
+	priv->reg[1] = 0x82;
+	ret = a8293_wr(priv, &priv->reg[1], 1);
+	if (ret)
+		goto err;
+
+	info("Allegro A8293 SEC attached.");
+
+	fe->ops.release_sec = a8293_release_sec;
+
+	/* override frontend ops */
+	fe->ops.set_voltage = a8293_set_voltage;
+
+	return fe;
+err:
+	dbg("%s: failed=%d", __func__, ret);
+	kfree(priv);
+	return NULL;
+}
+EXPORT_SYMBOL(a8293_attach);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Allegro A8293 SEC driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/a8293.h linux-libre-3.2-gnu/drivers/media/dvb/frontends/a8293.h
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/a8293.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/a8293.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,41 @@
+/*
+ * Allegro A8293 SEC driver
+ *
+ * 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.
+ */
+
+#ifndef A8293_H
+#define A8293_H
+
+struct a8293_config {
+	u8 i2c_addr;
+};
+
+#if defined(CONFIG_DVB_A8293) || \
+	(defined(CONFIG_DVB_A8293_MODULE) && defined(MODULE))
+extern struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, const struct a8293_config *cfg);
+#else
+static inline struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, const struct a8293_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* A8293_H */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/cxd2820r_c.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/cxd2820r_c.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/cxd2820r_c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/cxd2820r_c.c	2012-01-04 18:55:44.000000000 -0500
@@ -335,4 +335,3 @@
 
 	return 0;
 }
-
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/cxd2820r_core.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/cxd2820r_core.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/cxd2820r_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/cxd2820r_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -727,72 +727,22 @@
 	struct cxd2820r_priv *priv = fe->demodulator_priv;
 	dbg("%s", __func__);
 
-	if (fe->ops.info.type == FE_OFDM) {
-		i2c_del_adapter(&priv->tuner_i2c_adapter);
+	if (fe->ops.info.type == FE_OFDM)
 		kfree(priv);
-	}
 
 	return;
 }
 
-static u32 cxd2820r_tuner_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static int cxd2820r_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
-	struct i2c_msg msg[], int num)
-{
-	struct cxd2820r_priv *priv = i2c_get_adapdata(i2c_adap);
-	int ret;
-	u8 *obuf = kmalloc(msg[0].len + 2, GFP_KERNEL);
-	struct i2c_msg msg2[2] = {
-		{
-			.addr = priv->cfg.i2c_address,
-			.flags = 0,
-			.len = msg[0].len + 2,
-			.buf = obuf,
-		}, {
-			.addr = priv->cfg.i2c_address,
-			.flags = I2C_M_RD,
-			.len = msg[1].len,
-			.buf = msg[1].buf,
-		}
-	};
-
-	if (!obuf)
-		return -ENOMEM;
-
-	obuf[0] = 0x09;
-	obuf[1] = (msg[0].addr << 1);
-	if (num == 2) { /* I2C read */
-		obuf[1] = (msg[0].addr << 1) | I2C_M_RD; /* I2C RD flag */
-		msg2[0].len = msg[0].len + 2 - 1; /* '-1' maybe HW bug ? */
-	}
-	memcpy(&obuf[2], msg[0].buf, msg[0].len);
-
-	ret = i2c_transfer(priv->i2c, msg2, num);
-	if (ret < 0)
-		warn("tuner i2c failed ret:%d", ret);
-
-	kfree(obuf);
-
-	return ret;
-}
-
-static struct i2c_algorithm cxd2820r_tuner_i2c_algo = {
-	.master_xfer   = cxd2820r_tuner_i2c_xfer,
-	.functionality = cxd2820r_tuner_i2c_func,
-};
-
-struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+static int cxd2820r_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
 	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	return &priv->tuner_i2c_adapter;
+	dbg("%s: %d", __func__, enable);
+
+	/* Bit 0 of reg 0xdb in bank 0x00 controls I2C repeater */
+	return cxd2820r_wr_reg_mask(priv, 0xdb, enable ? 1 : 0, 0x1);
 }
-EXPORT_SYMBOL(cxd2820r_get_tuner_i2c_adapter);
 
-static struct dvb_frontend_ops cxd2820r_ops[2];
+static const struct dvb_frontend_ops cxd2820r_ops[2];
 
 struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
 	struct i2c_adapter *i2c, struct dvb_frontend *fe)
@@ -831,18 +781,6 @@
 		priv->fe[0].demodulator_priv = priv;
 		priv->fe[1].demodulator_priv = priv;
 
-		/* create tuner i2c adapter */
-		strlcpy(priv->tuner_i2c_adapter.name,
-			"CXD2820R tuner I2C adapter",
-			sizeof(priv->tuner_i2c_adapter.name));
-		priv->tuner_i2c_adapter.algo = &cxd2820r_tuner_i2c_algo;
-		priv->tuner_i2c_adapter.algo_data = NULL;
-		i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
-		if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
-			err("tuner I2C bus could not be initialized");
-			goto error;
-		}
-
 		return &priv->fe[0];
 
 	} else {
@@ -858,7 +796,7 @@
 }
 EXPORT_SYMBOL(cxd2820r_attach);
 
-static struct dvb_frontend_ops cxd2820r_ops[2] = {
+static const struct dvb_frontend_ops cxd2820r_ops[2] = {
 	{
 		/* DVB-T/T2 */
 		.info = {
@@ -883,6 +821,7 @@
 		.sleep = cxd2820r_sleep,
 
 		.get_tune_settings = cxd2820r_get_tune_settings,
+		.i2c_gate_ctrl = cxd2820r_i2c_gate_ctrl,
 
 		.get_frontend = cxd2820r_get_frontend,
 
@@ -911,6 +850,7 @@
 		.sleep = cxd2820r_sleep,
 
 		.get_tune_settings = cxd2820r_get_tune_settings,
+		.i2c_gate_ctrl = cxd2820r_i2c_gate_ctrl,
 
 		.set_frontend = cxd2820r_set_frontend,
 		.get_frontend = cxd2820r_get_frontend,
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/cxd2820r.h linux-libre-3.2-gnu/drivers/media/dvb/frontends/cxd2820r.h
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/cxd2820r.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/cxd2820r.h	2012-01-04 18:55:44.000000000 -0500
@@ -93,9 +93,6 @@
 	struct i2c_adapter *i2c,
 	struct dvb_frontend *fe
 );
-extern struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(
-	struct dvb_frontend *fe
-);
 #else
 static inline struct dvb_frontend *cxd2820r_attach(
 	const struct cxd2820r_config *config,
@@ -106,12 +103,6 @@
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 }
-static inline struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(
-	struct dvb_frontend *fe
-)
-{
-	return NULL;
-}
 
 #endif
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/cxd2820r_priv.h linux-libre-3.2-gnu/drivers/media/dvb/frontends/cxd2820r_priv.h
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/cxd2820r_priv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/cxd2820r_priv.h	2012-01-04 18:55:44.000000000 -0500
@@ -50,7 +50,6 @@
 	struct i2c_adapter *i2c;
 	struct dvb_frontend fe[2];
 	struct cxd2820r_config cfg;
-	struct i2c_adapter tuner_i2c_adapter;
 
 	struct mutex fe_lock; /*Â FE lock */
 	int active_fe:2; /* FE lock, -1=NONE, 0=DVB-T/T2, 1=DVB-C */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/cxd2820r_t2.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/cxd2820r_t2.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/cxd2820r_t2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/cxd2820r_t2.c	2012-01-04 18:55:44.000000000 -0500
@@ -420,4 +420,3 @@
 
 	return 0;
 }
-
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/cxd2820r_t.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/cxd2820r_t.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/cxd2820r_t.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/cxd2820r_t.c	2012-01-04 18:55:44.000000000 -0500
@@ -446,4 +446,3 @@
 
 	return 0;
 }
-
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/dib0070.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/dib0070.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/dib0070.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/dib0070.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/mutex.h>
 
 #include "dvb_frontend.h"
 
@@ -78,10 +79,18 @@
 	struct i2c_msg msg[2];
 	u8 i2c_write_buffer[3];
 	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
 };
 
-static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
+static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg)
 {
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
 	state->i2c_write_buffer[0] = reg;
 
 	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
@@ -96,13 +105,23 @@
 
 	if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
 		printk(KERN_WARNING "DiB0070 I2C read failed\n");
-		return 0;
-	}
-	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+		ret = 0;
+	} else
+		ret = (state->i2c_read_buffer[0] << 8)
+			| state->i2c_read_buffer[1];
+
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 
 static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
 {
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
 	state->i2c_write_buffer[0] = reg;
 	state->i2c_write_buffer[1] = val >> 8;
 	state->i2c_write_buffer[2] = val & 0xff;
@@ -115,9 +134,12 @@
 
 	if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
 		printk(KERN_WARNING "DiB0070 I2C write failed\n");
-		return -EREMOTEIO;
-	}
-	return 0;
+		ret = -EREMOTEIO;
+	} else
+		ret = 0;
+
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 
 #define HARD_RESET(state) do { \
@@ -734,6 +756,7 @@
 	state->cfg = cfg;
 	state->i2c = i2c;
 	state->fe  = fe;
+	mutex_init(&state->i2c_buffer_lock);
 	fe->tuner_priv = state;
 
 	if (dib0070_reset(fe) != 0)
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/dib0090.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/dib0090.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/dib0090.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/dib0090.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/mutex.h>
 
 #include "dvb_frontend.h"
 
@@ -196,6 +197,7 @@
 	struct i2c_msg msg[2];
 	u8 i2c_write_buffer[3];
 	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
 };
 
 struct dib0090_fw_state {
@@ -208,10 +210,18 @@
 	struct i2c_msg msg;
 	u8 i2c_write_buffer[2];
 	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
 };
 
 static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
 {
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
 	state->i2c_write_buffer[0] = reg;
 
 	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
@@ -226,14 +236,24 @@
 
 	if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
 		printk(KERN_WARNING "DiB0090 I2C read failed\n");
-		return 0;
-	}
+		ret = 0;
+	} else
+		ret = (state->i2c_read_buffer[0] << 8)
+			| state->i2c_read_buffer[1];
 
-	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 
 static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
 {
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
 	state->i2c_write_buffer[0] = reg & 0xff;
 	state->i2c_write_buffer[1] = val >> 8;
 	state->i2c_write_buffer[2] = val & 0xff;
@@ -246,13 +266,23 @@
 
 	if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
 		printk(KERN_WARNING "DiB0090 I2C write failed\n");
-		return -EREMOTEIO;
-	}
-	return 0;
+		ret = -EREMOTEIO;
+	} else
+		ret = 0;
+
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 
 static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
 {
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
 	state->i2c_write_buffer[0] = reg;
 
 	memset(&state->msg, 0, sizeof(struct i2c_msg));
@@ -262,13 +292,24 @@
 	state->msg.len = 2;
 	if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
 		printk(KERN_WARNING "DiB0090 I2C read failed\n");
-		return 0;
-	}
-	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+		ret = 0;
+	} else
+		ret = (state->i2c_read_buffer[0] << 8)
+			| state->i2c_read_buffer[1];
+
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 
 static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
 {
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
 	state->i2c_write_buffer[0] = val >> 8;
 	state->i2c_write_buffer[1] = val & 0xff;
 
@@ -279,9 +320,12 @@
 	state->msg.len = 2;
 	if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
 		printk(KERN_WARNING "DiB0090 I2C write failed\n");
-		return -EREMOTEIO;
-	}
-	return 0;
+		ret = -EREMOTEIO;
+	} else
+		ret = 0;
+
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 
 #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)
@@ -2440,6 +2484,7 @@
 	st->config = config;
 	st->i2c = i2c;
 	st->fe = fe;
+	mutex_init(&st->i2c_buffer_lock);
 	fe->tuner_priv = st;
 
 	if (config->wbd == NULL)
@@ -2471,6 +2516,7 @@
 	st->config = config;
 	st->i2c = i2c;
 	st->fe = fe;
+	mutex_init(&st->i2c_buffer_lock);
 	fe->tuner_priv = st;
 
 	if (dib0090_fw_reset_digital(fe, st->config) != 0)
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/dib3000.h linux-libre-3.2-gnu/drivers/media/dvb/frontends/dib3000.h
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/dib3000.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/dib3000.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
  *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
  *  sources, on which this driver (and the dvb-dibusb) are based.
  *
- * see Documentation/dvb/README.dibusb for more information
+ * see Documentation/dvb/README.dvb-usb for more information
  *
  */
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/dib3000mb.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/dib3000mb.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/dib3000mb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/dib3000mb.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,7 +17,7 @@
  *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
  *  sources, on which this driver (and the dvb-dibusb) are based.
  *
- * see Documentation/dvb/README.dibusb for more information
+ * see Documentation/dvb/README.dvb-usb for more information
  *
  */
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/dib7000m.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/dib7000m.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/dib7000m.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/dib7000m.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/mutex.h>
 
 #include "dvb_frontend.h"
 
@@ -55,6 +56,7 @@
 	struct i2c_msg msg[2];
 	u8 i2c_write_buffer[4];
 	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
 };
 
 enum dib7000m_power_mode {
@@ -69,6 +71,13 @@
 
 static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
 {
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
 	state->i2c_write_buffer[0] = (reg >> 8) | 0x80;
 	state->i2c_write_buffer[1] = reg & 0xff;
 
@@ -85,11 +94,21 @@
 	if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
 		dprintk("i2c read error on %d",reg);
 
-	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	mutex_unlock(&state->i2c_buffer_lock);
+
+	return ret;
 }
 
 static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
 {
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
 	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
 	state->i2c_write_buffer[1] = reg & 0xff;
 	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
@@ -101,7 +120,10 @@
 	state->msg[0].buf = state->i2c_write_buffer;
 	state->msg[0].len = 4;
 
-	return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
+	ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
+			-EREMOTEIO : 0);
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
 {
@@ -1385,6 +1407,7 @@
 	demod                   = &st->demod;
 	demod->demodulator_priv = st;
 	memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops));
+	mutex_init(&st->i2c_buffer_lock);
 
 	st->timf_default = cfg->bw->timf;
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/dib7000p.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/dib7000p.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/dib7000p.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/dib7000p.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/mutex.h>
 
 #include "dvb_math.h"
 #include "dvb_frontend.h"
@@ -68,6 +69,7 @@
 	struct i2c_msg msg[2];
 	u8 i2c_write_buffer[4];
 	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
 };
 
 enum dib7000p_power_mode {
@@ -81,6 +83,13 @@
 
 static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
 {
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
 	state->i2c_write_buffer[0] = reg >> 8;
 	state->i2c_write_buffer[1] = reg & 0xff;
 
@@ -97,11 +106,20 @@
 	if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
 		dprintk("i2c read error on %d", reg);
 
-	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 
 static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
 {
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
 	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
 	state->i2c_write_buffer[1] = reg & 0xff;
 	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
@@ -113,7 +131,10 @@
 	state->msg[0].buf = state->i2c_write_buffer;
 	state->msg[0].len = 4;
 
-	return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
+	ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
+			-EREMOTEIO : 0);
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
 }
 
 static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
@@ -1577,8 +1598,8 @@
 		return -ENOMEM;
 	rx = kzalloc(2*sizeof(u8), GFP_KERNEL);
 	if (!rx) {
-		goto rx_memory_error;
 		ret = -ENOMEM;
+		goto rx_memory_error;
 	}
 
 	msg[0].buf = tx;
@@ -1646,6 +1667,7 @@
 		return -ENOMEM;
 
 	dpst->i2c_adap = i2c;
+	mutex_init(&dpst->i2c_buffer_lock);
 
 	for (k = no_of_demods - 1; k >= 0; k--) {
 		dpst->cfg = cfg[k];
@@ -2324,6 +2346,7 @@
 	demod = &st->demod;
 	demod->demodulator_priv = st;
 	memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
+	mutex_init(&st->i2c_buffer_lock);
 
 	dib7000p_write_word(st, 1287, 0x0003);	/* sram lead in, rdy */
 
@@ -2333,8 +2356,9 @@
 	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) */
+	   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;
 
 	/* FIXME: make sure the dev.parent field is initialized, or else
 	   request_firmware() will hit an OOPS (this should be moved somewhere
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/dib8000.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/dib8000.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/dib8000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/dib8000.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,8 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/mutex.h>
+
 #include "dvb_math.h"
 
 #include "dvb_frontend.h"
@@ -37,6 +39,7 @@
 	u8 addr;
 	u8 *i2c_write_buffer;
 	u8 *i2c_read_buffer;
+	struct mutex *i2c_buffer_lock;
 };
 
 struct dib8000_state {
@@ -77,6 +80,7 @@
 	struct i2c_msg msg[2];
 	u8 i2c_write_buffer[4];
 	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
 };
 
 enum dib8000_power_mode {
@@ -86,24 +90,39 @@
 
 static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
 {
+	u16 ret;
 	struct i2c_msg msg[2] = {
-		{.addr = i2c->addr >> 1, .flags = 0,
-			.buf = i2c->i2c_write_buffer, .len = 2},
-		{.addr = i2c->addr >> 1, .flags = I2C_M_RD,
-			.buf = i2c->i2c_read_buffer, .len = 2},
+		{.addr = i2c->addr >> 1, .flags = 0, .len = 2},
+		{.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2},
 	};
 
+	if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
+	msg[0].buf    = i2c->i2c_write_buffer;
 	msg[0].buf[0] = reg >> 8;
 	msg[0].buf[1] = reg & 0xff;
+	msg[1].buf    = i2c->i2c_read_buffer;
 
 	if (i2c_transfer(i2c->adap, msg, 2) != 2)
 		dprintk("i2c read error on %d", reg);
 
-	return (msg[1].buf[0] << 8) | msg[1].buf[1];
+	ret = (msg[1].buf[0] << 8) | msg[1].buf[1];
+	mutex_unlock(i2c->i2c_buffer_lock);
+	return ret;
 }
 
 static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
 {
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
 	state->i2c_write_buffer[0] = reg >> 8;
 	state->i2c_write_buffer[1] = reg & 0xff;
 
@@ -120,7 +139,10 @@
 	if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2)
 		dprintk("i2c read error on %d", reg);
 
-	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	mutex_unlock(&state->i2c_buffer_lock);
+
+	return ret;
 }
 
 static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
@@ -135,22 +157,35 @@
 
 static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
 {
-	struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0,
-		.buf = i2c->i2c_write_buffer, .len = 4};
+	struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4};
 	int ret = 0;
 
+	if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
+	msg.buf    = i2c->i2c_write_buffer;
 	msg.buf[0] = (reg >> 8) & 0xff;
 	msg.buf[1] = reg & 0xff;
 	msg.buf[2] = (val >> 8) & 0xff;
 	msg.buf[3] = val & 0xff;
 
 	ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+	mutex_unlock(i2c->i2c_buffer_lock);
 
 	return ret;
 }
 
 static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
 {
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
 	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
 	state->i2c_write_buffer[1] = reg & 0xff;
 	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
@@ -162,7 +197,11 @@
 	state->msg[0].buf = state->i2c_write_buffer;
 	state->msg[0].len = 4;
 
-	return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
+	ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ?
+			-EREMOTEIO : 0);
+	mutex_unlock(&state->i2c_buffer_lock);
+
+	return ret;
 }
 
 static const s16 coeff_2k_sb_1seg_dqpsk[8] = {
@@ -2434,8 +2473,15 @@
 	if (!client.i2c_read_buffer) {
 		dprintk("%s: not enough memory", __func__);
 		ret = -ENOMEM;
-		goto error_memory;
+		goto error_memory_read;
+	}
+	client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL);
+	if (!client.i2c_buffer_lock) {
+		dprintk("%s: not enough memory", __func__);
+		ret = -ENOMEM;
+		goto error_memory_lock;
 	}
+	mutex_init(client.i2c_buffer_lock);
 
 	for (k = no_of_demods - 1; k >= 0; k--) {
 		/* designated i2c address */
@@ -2476,8 +2522,10 @@
 	}
 
 error:
+	kfree(client.i2c_buffer_lock);
+error_memory_lock:
 	kfree(client.i2c_read_buffer);
-error_memory:
+error_memory_read:
 	kfree(client.i2c_write_buffer);
 
 	return ret;
@@ -2581,6 +2629,8 @@
 	state->i2c.addr = i2c_addr;
 	state->i2c.i2c_write_buffer = state->i2c_write_buffer;
 	state->i2c.i2c_read_buffer = state->i2c_read_buffer;
+	mutex_init(&state->i2c_buffer_lock);
+	state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock;
 	state->gpio_val = cfg->gpio_val;
 	state->gpio_dir = cfg->gpio_dir;
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/dib9000.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/dib9000.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/dib9000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/dib9000.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,15 @@
 #define DibInitLock(lock) mutex_init(lock)
 #define DibFreeLock(lock)
 
+struct dib9000_pid_ctrl {
+#define DIB9000_PID_FILTER_CTRL 0
+#define DIB9000_PID_FILTER      1
+	u8 cmd;
+	u8 id;
+	u16 pid;
+	u8 onoff;
+};
+
 struct dib9000_state {
 	struct i2c_device i2c;
 
@@ -99,6 +108,10 @@
 	struct i2c_msg msg[2];
 	u8 i2c_write_buffer[255];
 	u8 i2c_read_buffer[255];
+	DIB_LOCK demod_lock;
+	u8 get_frontend_internal;
+	struct dib9000_pid_ctrl pid_ctrl[10];
+	s8 pid_ctrl_index; /* -1: empty list; -2: do not use the list */
 };
 
 static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -1167,8 +1180,8 @@
 
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
 	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
-		goto error;
 		ret = -EIO;
+		goto error;
 	}
 
 	dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION,
@@ -1743,19 +1756,56 @@
 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;
+	u16 val;
+	int ret;
+
+	if ((state->pid_ctrl_index != -2) && (state->pid_ctrl_index < 9)) {
+		/* postpone the pid filtering cmd */
+		dprintk("pid filter cmd postpone");
+		state->pid_ctrl_index++;
+		state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER_CTRL;
+		state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
+		return 0;
+	}
+
+	DibAcquireLock(&state->demod_lock);
+
+	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);
+	ret = dib9000_write_word(state, 294 + 1, val);
+	DibReleaseLock(&state->demod_lock);
+	return ret;
+
 }
 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;
+	int ret;
+
+	if (state->pid_ctrl_index != -2) {
+		/* postpone the pid filtering cmd */
+		dprintk("pid filter postpone");
+		if (state->pid_ctrl_index < 9) {
+			state->pid_ctrl_index++;
+			state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER;
+			state->pid_ctrl[state->pid_ctrl_index].id = id;
+			state->pid_ctrl[state->pid_ctrl_index].pid = pid;
+			state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
+		} else
+			dprintk("can not add any more pid ctrl cmd");
+		return 0;
+	}
+
+	DibAcquireLock(&state->demod_lock);
 	dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
-	return dib9000_write_word(state, 300 + 1 + id, onoff ? (1 << 13) | pid : 0);
+	ret = dib9000_write_word(state, 300 + 1 + id,
+			onoff ? (1 << 13) | pid : 0);
+	DibReleaseLock(&state->demod_lock);
+	return ret;
 }
 EXPORT_SYMBOL(dib9000_fw_pid_filter);
 
@@ -1778,6 +1828,7 @@
 	DibFreeLock(&state->platform.risc.mbx_lock);
 	DibFreeLock(&state->platform.risc.mem_lock);
 	DibFreeLock(&state->platform.risc.mem_mbx_lock);
+	DibFreeLock(&state->demod_lock);
 	dibx000_exit_i2c_master(&st->i2c_master);
 
 	i2c_del_adapter(&st->tuner_adap);
@@ -1795,14 +1846,19 @@
 {
 	struct dib9000_state *state = fe->demodulator_priv;
 	u8 index_frontend;
-	int ret;
+	int ret = 0;
 
+	DibAcquireLock(&state->demod_lock);
 	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;
+			goto error;
 	}
-	return dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0);
+	ret = dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0);
+
+error:
+	DibReleaseLock(&state->demod_lock);
+	return ret;
 }
 
 static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
@@ -1816,7 +1872,10 @@
 	struct dib9000_state *state = fe->demodulator_priv;
 	u8 index_frontend, sub_index_frontend;
 	fe_status_t stat;
-	int ret;
+	int ret = 0;
+
+	if (state->get_frontend_internal == 0)
+		DibAcquireLock(&state->demod_lock);
 
 	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);
@@ -1846,14 +1905,15 @@
 					    state->fe[index_frontend]->dtv_property_cache.rolloff;
 				}
 			}
-			return 0;
+			ret = 0;
+			goto return_value;
 		}
 	}
 
 	/* get the channel from master chip */
 	ret = dib9000_fw_get_channel(fe, fep);
 	if (ret != 0)
-		return ret;
+		goto return_value;
 
 	/* synchronize the cache with the other frontends */
 	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
@@ -1866,8 +1926,12 @@
 		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;
 	}
+	ret = 0;
 
-	return 0;
+return_value:
+	if (state->get_frontend_internal == 0)
+		DibReleaseLock(&state->demod_lock);
+	return ret;
 }
 
 static int dib9000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
@@ -1912,6 +1976,10 @@
 		dprintk("dib9000: must specify bandwidth ");
 		return 0;
 	}
+
+	state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */
+	DibAcquireLock(&state->demod_lock);
+
 	fe->dtv_property_cache.delivery_system = SYS_DVBT;
 
 	/* set the master status */
@@ -1974,13 +2042,18 @@
 	/* check the tune result */
 	if (exit_condition == 1) {	/* tune failed */
 		dprintk("tune failed");
+		DibReleaseLock(&state->demod_lock);
+		/* tune failed; put all the pid filtering cmd to junk */
+		state->pid_ctrl_index = -1;
 		return 0;
 	}
 
 	dprintk("tune success on frontend%i", index_frontend_success);
 
 	/* synchronize all the channel cache */
+	state->get_frontend_internal = 1;
 	dib9000_get_frontend(state->fe[0], fep);
+	state->get_frontend_internal = 0;
 
 	/* retune the other frontends with the found channel */
 	channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
@@ -2025,6 +2098,28 @@
 	/* turn off the diversity for the last frontend */
 	dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0);
 
+	DibReleaseLock(&state->demod_lock);
+	if (state->pid_ctrl_index >= 0) {
+		u8 index_pid_filter_cmd;
+		u8 pid_ctrl_index = state->pid_ctrl_index;
+
+		state->pid_ctrl_index = -2;
+		for (index_pid_filter_cmd = 0;
+				index_pid_filter_cmd <= pid_ctrl_index;
+				index_pid_filter_cmd++) {
+			if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER_CTRL)
+				dib9000_fw_pid_filter_ctrl(state->fe[0],
+						state->pid_ctrl[index_pid_filter_cmd].onoff);
+			else if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER)
+				dib9000_fw_pid_filter(state->fe[0],
+						state->pid_ctrl[index_pid_filter_cmd].id,
+						state->pid_ctrl[index_pid_filter_cmd].pid,
+						state->pid_ctrl[index_pid_filter_cmd].onoff);
+		}
+	}
+	/* do not postpone any more the pid filtering */
+	state->pid_ctrl_index = -2;
+
 	return 0;
 }
 
@@ -2041,6 +2136,7 @@
 	u8 index_frontend;
 	u16 lock = 0, lock_slave = 0;
 
+	DibAcquireLock(&state->demod_lock);
 	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]);
 
@@ -2059,6 +2155,8 @@
 	if ((lock & 0x0008) || (lock_slave & 0x0008))
 		*stat |= FE_HAS_LOCK;
 
+	DibReleaseLock(&state->demod_lock);
+
 	return 0;
 }
 
@@ -2066,10 +2164,15 @@
 {
 	struct dib9000_state *state = fe->demodulator_priv;
 	u16 *c;
+	int ret = 0;
 
+	DibAcquireLock(&state->demod_lock);
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
-	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
-		return -EIO;
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
+		DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+		ret = -EIO;
+		goto error;
+	}
 	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
 			state->i2c_read_buffer, 16 * 2);
 	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
@@ -2077,7 +2180,10 @@
 	c = (u16 *)state->i2c_read_buffer;
 
 	*ber = c[10] << 16 | c[11];
-	return 0;
+
+error:
+	DibReleaseLock(&state->demod_lock);
+	return ret;
 }
 
 static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
@@ -2086,7 +2192,9 @@
 	u8 index_frontend;
 	u16 *c = (u16 *)state->i2c_read_buffer;
 	u16 val;
+	int ret = 0;
 
+	DibAcquireLock(&state->demod_lock);
 	*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);
@@ -2097,8 +2205,10 @@
 	}
 
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
-	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
-		return -EIO;
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
+		ret = -EIO;
+		goto error;
+	}
 	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
 	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
 
@@ -2107,7 +2217,10 @@
 		*strength = 65535;
 	else
 		*strength += val;
-	return 0;
+
+error:
+	DibReleaseLock(&state->demod_lock);
+	return ret;
 }
 
 static u32 dib9000_get_snr(struct dvb_frontend *fe)
@@ -2151,6 +2264,7 @@
 	u8 index_frontend;
 	u32 snr_master;
 
+	DibAcquireLock(&state->demod_lock);
 	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]);
@@ -2161,6 +2275,8 @@
 	} else
 		*snr = 0;
 
+	DibReleaseLock(&state->demod_lock);
+
 	return 0;
 }
 
@@ -2168,15 +2284,22 @@
 {
 	struct dib9000_state *state = fe->demodulator_priv;
 	u16 *c = (u16 *)state->i2c_read_buffer;
+	int ret = 0;
 
+	DibAcquireLock(&state->demod_lock);
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
-	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
-		return -EIO;
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
+		ret = -EIO;
+		goto error;
+	}
 	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
 	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
 
 	*unc = c[12];
-	return 0;
+
+error:
+	DibReleaseLock(&state->demod_lock);
+	return ret;
 }
 
 int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
@@ -2322,6 +2445,10 @@
 	DibInitLock(&st->platform.risc.mbx_lock);
 	DibInitLock(&st->platform.risc.mem_lock);
 	DibInitLock(&st->platform.risc.mem_mbx_lock);
+	DibInitLock(&st->demod_lock);
+	st->get_frontend_internal = 0;
+
+	st->pid_ctrl_index = -2;
 
 	st->fe[0] = fe;
 	fe->demodulator_priv = st;
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/dibx000_common.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/dibx000_common.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/dibx000_common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/dibx000_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,6 @@
 #include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
 
 #include "dibx000_common.h"
 
@@ -10,6 +12,13 @@
 
 static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
 {
+	int ret;
+
+	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
 	mst->i2c_write_buffer[0] = (reg >> 8) & 0xff;
 	mst->i2c_write_buffer[1] = reg & 0xff;
 	mst->i2c_write_buffer[2] = (val >> 8) & 0xff;
@@ -21,11 +30,21 @@
 	mst->msg[0].buf = mst->i2c_write_buffer;
 	mst->msg[0].len = 4;
 
-	return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
+	ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
+	mutex_unlock(&mst->i2c_buffer_lock);
+
+	return ret;
 }
 
 static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
 {
+	u16 ret;
+
+	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
 	mst->i2c_write_buffer[0] = reg >> 8;
 	mst->i2c_write_buffer[1] = reg & 0xff;
 
@@ -42,7 +61,10 @@
 	if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)
 		dprintk("i2c read error on %d", reg);
 
-	return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
+	ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
+	mutex_unlock(&mst->i2c_buffer_lock);
+
+	return ret;
 }
 
 static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
@@ -257,6 +279,7 @@
 					struct i2c_msg msg[], int num)
 {
 	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+	int ret;
 
 	if (num > 32) {
 		dprintk("%s: too much I2C message to be transmitted (%i).\
@@ -264,10 +287,15 @@
 		return -ENOMEM;
 	}
 
-	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
-
 	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
 
+	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
+	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
+
 	/* open the gate */
 	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
 	mst->msg[0].addr = mst->i2c_addr;
@@ -282,7 +310,11 @@
 	mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
 	mst->msg[num + 1].len = 4;
 
-	return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
+	ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
+			num : -EIO);
+
+	mutex_unlock(&mst->i2c_buffer_lock);
+	return ret;
 }
 
 static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
@@ -294,6 +326,7 @@
 					struct i2c_msg msg[], int num)
 {
 	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+	int ret;
 
 	if (num > 32) {
 		dprintk("%s: too much I2C message to be transmitted (%i).\
@@ -301,10 +334,14 @@
 		return -ENOMEM;
 	}
 
-	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
-
 	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
 
+	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
+
 	/* open the gate */
 	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
 	mst->msg[0].addr = mst->i2c_addr;
@@ -319,7 +356,10 @@
 	mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
 	mst->msg[num + 1].len = 4;
 
-	return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
+	ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
+			num : -EIO);
+	mutex_unlock(&mst->i2c_buffer_lock);
+	return ret;
 }
 
 static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
@@ -390,8 +430,18 @@
 int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev,
 				struct i2c_adapter *i2c_adap, u8 i2c_addr)
 {
-	u8 tx[4];
-	struct i2c_msg m = {.addr = i2c_addr >> 1,.buf = tx,.len = 4 };
+	int ret;
+
+	mutex_init(&mst->i2c_buffer_lock);
+	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+	memset(mst->msg, 0, sizeof(struct i2c_msg));
+	mst->msg[0].addr = i2c_addr >> 1;
+	mst->msg[0].flags = 0;
+	mst->msg[0].buf = mst->i2c_write_buffer;
+	mst->msg[0].len = 4;
 
 	mst->device_rev = device_rev;
 	mst->i2c_adap = i2c_adap;
@@ -431,9 +481,12 @@
 				"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);
+	dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0);
 
-	return i2c_transfer(i2c_adap, &m, 1) == 1;
+	ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1);
+	mutex_unlock(&mst->i2c_buffer_lock);
+
+	return ret;
 }
 
 EXPORT_SYMBOL(dibx000_init_i2c_master);
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/dibx000_common.h linux-libre-3.2-gnu/drivers/media/dvb/frontends/dibx000_common.h
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/dibx000_common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/dibx000_common.h	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,7 @@
 	struct i2c_msg msg[34];
 	u8 i2c_write_buffer[8];
 	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
 };
 
 extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst,
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/drxd_hard.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/drxd_hard.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/drxd_hard.c	2012-03-19 21:36:11.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/drxd_hard.c	2012-03-19 21:38:44.000000000 -0400
@@ -889,10 +889,15 @@
 			u32 R2 = state->if_agc_cfg.R2;
 			u32 R3 = state->if_agc_cfg.R3;
 
-			u32 Vmax = (3300 * R2) / (R1 + R2);
-			u32 Rpar = (R2 * R3) / (R3 + R2);
-			u32 Vmin = (3300 * Rpar) / (R1 + Rpar);
-			u32 Vout = Vmin + ((Vmax - Vmin) * Value) / 1024;
+			u32 Vmax, Rpar, Vmin, Vout;
+
+			if (R2 == 0 && (R1 == 0 || R3 == 0))
+				return 0;
+
+			Vmax = (3300 * R2) / (R1 + R2);
+			Rpar = (R2 * R3) / (R3 + R2);
+			Vmin = (3300 * Rpar) / (R1 + Rpar);
+			Vout = Vmin + ((Vmax - Vmin) * Value) / 1024;
 
 			*pValue = Vout;
 		}
@@ -926,16 +931,15 @@
 			     const u8 *pMCImage, u32 Length)
 {
 	u8 *pSrc;
-	u16 Flags;
 	u32 Address;
 	u16 nBlocks;
 	u16 BlockSize;
-	u16 BlockCRC;
 	u32 offset = 0;
 	int i, status = 0;
 
 	pSrc = (u8 *) pMCImage;
-	Flags = (pSrc[0] << 8) | pSrc[1];
+	/* We're not using Flags */
+	/* Flags = (pSrc[0] << 8) | pSrc[1]; */
 	pSrc += sizeof(u16);
 	offset += sizeof(u16);
 	nBlocks = (pSrc[0] << 8) | pSrc[1];
@@ -952,11 +956,13 @@
 		pSrc += sizeof(u16);
 		offset += sizeof(u16);
 
-		Flags = (pSrc[0] << 8) | pSrc[1];
+		/* We're not using Flags */
+		/* u16 Flags = (pSrc[0] << 8) | pSrc[1]; */
 		pSrc += sizeof(u16);
 		offset += sizeof(u16);
 
-		BlockCRC = (pSrc[0] << 8) | pSrc[1];
+		/* We're not using BlockCRC */
+		/* u16 BlockCRC = (pSrc[0] << 8) | pSrc[1]; */
 		pSrc += sizeof(u16);
 		offset += sizeof(u16);
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/drxk_hard.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/drxk_hard.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/drxk_hard.c	2012-03-19 21:36:11.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/drxk_hard.c	2012-03-19 21:38:44.000000000 -0400
@@ -6211,6 +6211,14 @@
 	u32 IF;
 
 	dprintk(1, "\n");
+
+	if (!fe->ops.tuner_ops.get_if_frequency) {
+		printk(KERN_ERR
+		       "drxk: Error: get_if_frequency() not defined at tuner. Can't work without it!\n");
+		return -EINVAL;
+	}
+
+
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (fe->ops.tuner_ops.set_params)
@@ -6218,7 +6226,7 @@
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 0);
 	state->param = *p;
-	fe->ops.tuner_ops.get_frequency(fe, &IF);
+	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
 	Start(state, 0, IF);
 
 	/* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/it913x-fe.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/it913x-fe.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/it913x-fe.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/it913x-fe.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,839 @@
+/*
+ *  Driver for it913x-fe Frontend
+ *
+ *  with support for on chip it9137 integral tuner
+ *
+ *  Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
+ *  IT9137 Copyright (C) ITE Tech Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "dvb_frontend.h"
+#include "it913x-fe.h"
+#include "it913x-fe-priv.h"
+
+static int it913x_debug;
+
+module_param_named(debug, it913x_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
+
+#define dprintk(level, args...) do { \
+	if (level & it913x_debug) \
+		printk(KERN_DEBUG "it913x-fe: " args); \
+} while (0)
+
+#define deb_info(args...)  dprintk(0x01, args)
+#define debug_data_snipet(level, name, p) \
+	  dprintk(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \
+		*p, *(p+1), *(p+2), *(p+3), *(p+4), \
+			*(p+5), *(p+6), *(p+7));
+
+struct it913x_fe_state {
+	struct dvb_frontend frontend;
+	struct i2c_adapter *i2c_adap;
+	u8 i2c_addr;
+	u32 frequency;
+	u8 adf;
+	u32 crystalFrequency;
+	u32 adcFrequency;
+	u8 tuner_type;
+	struct adctable *table;
+	fe_status_t it913x_status;
+	u16 tun_xtal;
+	u8 tun_fdiv;
+	u8 tun_clk_mode;
+	u32 tun_fn_min;
+};
+
+static int it913x_read_reg(struct it913x_fe_state *state,
+		u32 reg, u8 *data, u8 count)
+{
+	int ret;
+	u8 pro = PRO_DMOD; /* All reads from demodulator */
+	u8 b[4];
+	struct i2c_msg msg[2] = {
+		{ .addr = state->i2c_addr + (pro << 1), .flags = 0,
+			.buf = b, .len = sizeof(b) },
+		{ .addr = state->i2c_addr + (pro << 1), .flags = I2C_M_RD,
+			.buf = data, .len = count }
+	};
+	b[0] = (u8) reg >> 24;
+	b[1] = (u8)(reg >> 16) & 0xff;
+	b[2] = (u8)(reg >> 8) & 0xff;
+	b[3] = (u8) reg & 0xff;
+
+	ret = i2c_transfer(state->i2c_adap, msg, 2);
+
+	return ret;
+}
+
+static int it913x_read_reg_u8(struct it913x_fe_state *state, u32 reg)
+{
+	int ret;
+	u8 b[1];
+	ret = it913x_read_reg(state, reg, &b[0], sizeof(b));
+	return (ret < 0) ? -ENODEV : b[0];
+}
+
+static int it913x_write(struct it913x_fe_state *state,
+		u8 pro, u32 reg, u8 buf[], u8 count)
+{
+	u8 b[256];
+	struct i2c_msg msg[1] = {
+		{ .addr = state->i2c_addr + (pro << 1), .flags = 0,
+		  .buf = b, .len = count + 4 }
+	};
+	int ret;
+
+	b[0] = (u8) reg >> 24;
+	b[1] = (u8)(reg >> 16) & 0xff;
+	b[2] = (u8)(reg >> 8) & 0xff;
+	b[3] = (u8) reg & 0xff;
+	memcpy(&b[4], buf, count);
+
+	ret = i2c_transfer(state->i2c_adap, msg, 1);
+
+	if (ret < 0)
+		return -EIO;
+
+	return 0;
+}
+
+static int it913x_write_reg(struct it913x_fe_state *state,
+		u8 pro, u32 reg, u32 data)
+{
+	int ret;
+	u8 b[4];
+	u8 s;
+
+	b[0] = data >> 24;
+	b[1] = (data >> 16) & 0xff;
+	b[2] = (data >> 8) & 0xff;
+	b[3] = data & 0xff;
+	/* expand write as needed */
+	if (data < 0x100)
+		s = 3;
+	else if (data < 0x1000)
+		s = 2;
+	else if (data < 0x100000)
+		s = 1;
+	else
+		s = 0;
+
+	ret = it913x_write(state, pro, reg, &b[s], sizeof(b) - s);
+
+	return ret;
+}
+
+static int it913x_fe_script_loader(struct it913x_fe_state *state,
+		struct it913xset *loadscript)
+{
+	int ret, i;
+	if (loadscript == NULL)
+		return -EINVAL;
+
+	for (i = 0; i < 1000; ++i) {
+		if (loadscript[i].pro == 0xff)
+			break;
+		ret = it913x_write(state, loadscript[i].pro,
+			loadscript[i].address,
+			loadscript[i].reg, loadscript[i].count);
+		if (ret < 0)
+			return -ENODEV;
+	}
+	return 0;
+}
+
+static int it913x_init_tuner(struct it913x_fe_state *state)
+{
+	int ret, i, reg;
+	u8 val, nv_val;
+	u8 nv[] = {48, 32, 24, 16, 12, 8, 6, 4, 2};
+	u8 b[2];
+
+	reg = it913x_read_reg_u8(state, 0xec86);
+	switch (reg) {
+	case 0:
+		state->tun_clk_mode = reg;
+		state->tun_xtal = 2000;
+		state->tun_fdiv = 3;
+		val = 16;
+		break;
+	case -ENODEV:
+		return -ENODEV;
+	case 1:
+	default:
+		state->tun_clk_mode = reg;
+		state->tun_xtal = 640;
+		state->tun_fdiv = 1;
+		val = 6;
+		break;
+	}
+
+	reg = it913x_read_reg_u8(state, 0xed03);
+
+	if (reg < 0)
+		return -ENODEV;
+	else if (reg < sizeof(nv))
+		nv_val = nv[reg];
+	else
+		nv_val = 2;
+
+	for (i = 0; i < 50; i++) {
+		ret = it913x_read_reg(state, 0xed23, &b[0], sizeof(b));
+		reg = (b[1] << 8) + b[0];
+		if (reg > 0)
+			break;
+		if (ret < 0)
+			return -ENODEV;
+		udelay(2000);
+	}
+	state->tun_fn_min = state->tun_xtal * reg;
+	state->tun_fn_min /= (state->tun_fdiv * nv_val);
+	deb_info("Tuner fn_min %d", state->tun_fn_min);
+
+	for (i = 0; i < 50; i++) {
+		reg = it913x_read_reg_u8(state, 0xec82);
+		if (reg > 0)
+			break;
+		if (reg < 0)
+			return -ENODEV;
+		udelay(2000);
+	}
+
+	return it913x_write_reg(state, PRO_DMOD, 0xed81, val);
+}
+
+static int it9137_set_tuner(struct it913x_fe_state *state,
+		enum fe_bandwidth bandwidth, u32 frequency_m)
+{
+	struct it913xset *set_tuner = set_it9137_template;
+	int ret, reg;
+	u32 frequency = frequency_m / 1000;
+	u32 freq, temp_f, tmp;
+	u16 iqik_m_cal;
+	u16 n_div;
+	u8 n;
+	u8 l_band;
+	u8 lna_band;
+	u8 bw;
+
+	deb_info("Tuner Frequency %d Bandwidth %d", frequency, bandwidth);
+
+	if (frequency >= 51000 && frequency <= 440000) {
+		l_band = 0;
+		lna_band = 0;
+	} else if (frequency > 440000 && frequency <= 484000) {
+		l_band = 1;
+		lna_band = 1;
+	} else if (frequency > 484000 && frequency <= 533000) {
+		l_band = 1;
+		lna_band = 2;
+	} else if (frequency > 533000 && frequency <= 587000) {
+		l_band = 1;
+		lna_band = 3;
+	} else if (frequency > 587000 && frequency <= 645000) {
+		l_band = 1;
+		lna_band = 4;
+	} else if (frequency > 645000 && frequency <= 710000) {
+		l_band = 1;
+		lna_band = 5;
+	} else if (frequency > 710000 && frequency <= 782000) {
+		l_band = 1;
+		lna_band = 6;
+	} else if (frequency > 782000 && frequency <= 860000) {
+		l_band = 1;
+		lna_band = 7;
+	} else if (frequency > 1450000 && frequency <= 1492000) {
+		l_band = 1;
+		lna_band = 0;
+	} else if (frequency > 1660000 && frequency <= 1685000) {
+		l_band = 1;
+		lna_band = 1;
+	} else
+		return -EINVAL;
+	set_tuner[0].reg[0] = lna_band;
+
+	if (bandwidth == BANDWIDTH_5_MHZ)
+		bw = 0;
+	else if (bandwidth == BANDWIDTH_6_MHZ)
+		bw = 2;
+	else if (bandwidth == BANDWIDTH_7_MHZ)
+		bw = 4;
+	else if (bandwidth == BANDWIDTH_8_MHZ)
+		bw = 6;
+	else
+		bw = 6;
+
+	set_tuner[1].reg[0] = bw;
+	set_tuner[2].reg[0] = 0xa0 | (l_band << 3);
+
+	if (frequency > 53000 && frequency <= 74000) {
+		n_div = 48;
+		n = 0;
+	} else if (frequency > 74000 && frequency <= 111000) {
+		n_div = 32;
+		n = 1;
+	} else if (frequency > 111000 && frequency <= 148000) {
+		n_div = 24;
+		n = 2;
+	} else if (frequency > 148000 && frequency <= 222000) {
+		n_div = 16;
+		n = 3;
+	} else if (frequency > 222000 && frequency <= 296000) {
+		n_div = 12;
+		n = 4;
+	} else if (frequency > 296000 && frequency <= 445000) {
+		n_div = 8;
+		n = 5;
+	} else if (frequency > 445000 && frequency <= state->tun_fn_min) {
+		n_div = 6;
+		n = 6;
+	} else if (frequency > state->tun_fn_min && frequency <= 950000) {
+		n_div = 4;
+		n = 7;
+	} else if (frequency > 1450000 && frequency <= 1680000) {
+		n_div = 2;
+		n = 0;
+	} else
+		return -EINVAL;
+
+	reg = it913x_read_reg_u8(state, 0xed81);
+	iqik_m_cal = (u16)reg * n_div;
+
+	if (reg < 0x20) {
+		if (state->tun_clk_mode == 0)
+			iqik_m_cal = (iqik_m_cal * 9) >> 5;
+		else
+			iqik_m_cal >>= 1;
+	} else {
+		iqik_m_cal = 0x40 - iqik_m_cal;
+		if (state->tun_clk_mode == 0)
+			iqik_m_cal = ~((iqik_m_cal * 9) >> 5);
+		else
+			iqik_m_cal = ~(iqik_m_cal >> 1);
+	}
+
+	temp_f = frequency * (u32)n_div * (u32)state->tun_fdiv;
+	freq = temp_f / state->tun_xtal;
+	tmp = freq * state->tun_xtal;
+
+	if ((temp_f - tmp) >= (state->tun_xtal >> 1))
+		freq++;
+
+	freq += (u32) n << 13;
+	/* Frequency OMEGA_IQIK_M_CAL_MID*/
+	temp_f = freq + (u32)iqik_m_cal;
+
+	set_tuner[3].reg[0] =  temp_f & 0xff;
+	set_tuner[4].reg[0] =  (temp_f >> 8) & 0xff;
+
+	deb_info("High Frequency = %04x", temp_f);
+
+	/* Lower frequency */
+	set_tuner[5].reg[0] =  freq & 0xff;
+	set_tuner[6].reg[0] =  (freq >> 8) & 0xff;
+
+	deb_info("low Frequency = %04x", freq);
+
+	ret = it913x_fe_script_loader(state, set_tuner);
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_fe_select_bw(struct it913x_fe_state *state,
+			enum fe_bandwidth bandwidth, u32 adcFrequency)
+{
+	int ret, i;
+	u8 buffer[256];
+	u32 coeff[8];
+	u16 bfsfcw_fftinx_ratio;
+	u16 fftinx_bfsfcw_ratio;
+	u8 count;
+	u8 bw;
+	u8 adcmultiplier;
+
+	deb_info("Bandwidth %d Adc %d", bandwidth, adcFrequency);
+
+	if (bandwidth == BANDWIDTH_5_MHZ)
+		bw = 3;
+	else if (bandwidth == BANDWIDTH_6_MHZ)
+		bw = 0;
+	else if (bandwidth == BANDWIDTH_7_MHZ)
+		bw = 1;
+	else if (bandwidth == BANDWIDTH_8_MHZ)
+		bw = 2;
+	else
+		bw = 2;
+
+	ret = it913x_write_reg(state, PRO_DMOD, REG_BW, bw);
+
+	if (state->table == NULL)
+		return -EINVAL;
+
+	/* In write order */
+	coeff[0] = state->table[bw].coeff_1_2048;
+	coeff[1] = state->table[bw].coeff_2_2k;
+	coeff[2] = state->table[bw].coeff_1_8191;
+	coeff[3] = state->table[bw].coeff_1_8192;
+	coeff[4] = state->table[bw].coeff_1_8193;
+	coeff[5] = state->table[bw].coeff_2_8k;
+	coeff[6] = state->table[bw].coeff_1_4096;
+	coeff[7] = state->table[bw].coeff_2_4k;
+	bfsfcw_fftinx_ratio = state->table[bw].bfsfcw_fftinx_ratio;
+	fftinx_bfsfcw_ratio = state->table[bw].fftinx_bfsfcw_ratio;
+
+	/* ADC multiplier */
+	ret = it913x_read_reg_u8(state, ADC_X_2);
+	if (ret < 0)
+		return -EINVAL;
+
+	adcmultiplier = ret;
+
+	count = 0;
+
+	/*  Build Buffer for COEFF Registers */
+	for (i = 0; i < 8; i++) {
+		if (adcmultiplier == 1)
+			coeff[i] /= 2;
+		buffer[count++] = (coeff[i] >> 24) & 0x3;
+		buffer[count++] = (coeff[i] >> 16) & 0xff;
+		buffer[count++] = (coeff[i] >> 8) & 0xff;
+		buffer[count++] = coeff[i] & 0xff;
+	}
+
+	/* bfsfcw_fftinx_ratio register 0x21-0x22 */
+	buffer[count++] = bfsfcw_fftinx_ratio & 0xff;
+	buffer[count++] = (bfsfcw_fftinx_ratio >> 8) & 0xff;
+	/* fftinx_bfsfcw_ratio register 0x23-0x24 */
+	buffer[count++] = fftinx_bfsfcw_ratio & 0xff;
+	buffer[count++] = (fftinx_bfsfcw_ratio >> 8) & 0xff;
+	/* start at COEFF_1_2048 and write through to fftinx_bfsfcw_ratio*/
+	ret = it913x_write(state, PRO_DMOD, COEFF_1_2048, buffer, count);
+
+	for (i = 0; i < 42; i += 8)
+		debug_data_snipet(0x1, "Buffer", &buffer[i]);
+
+	return ret;
+}
+
+
+
+static int it913x_fe_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret, i;
+	fe_status_t old_status = state->it913x_status;
+	*status = 0;
+
+	if (state->it913x_status == 0) {
+		ret = it913x_read_reg_u8(state, EMPTY_CHANNEL_STATUS);
+		if (ret == 0x1) {
+			*status |= FE_HAS_SIGNAL;
+			for (i = 0; i < 40; i++) {
+				ret = it913x_read_reg_u8(state, MP2IF_SYNC_LK);
+				if (ret == 0x1)
+					break;
+				msleep(25);
+			}
+			if (ret == 0x1)
+				*status |= FE_HAS_CARRIER
+					| FE_HAS_VITERBI
+					| FE_HAS_SYNC;
+			state->it913x_status = *status;
+		}
+	}
+
+	if (state->it913x_status & FE_HAS_SYNC) {
+		ret = it913x_read_reg_u8(state, TPSD_LOCK);
+		if (ret == 0x1)
+			*status |= FE_HAS_LOCK
+				| state->it913x_status;
+		else
+			state->it913x_status = 0;
+		if (old_status != state->it913x_status)
+			ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, ret);
+	}
+
+	return 0;
+}
+
+static int it913x_fe_read_signal_strength(struct dvb_frontend *fe,
+		u16 *strength)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret = it913x_read_reg_u8(state, SIGNAL_LEVEL);
+	/*SIGNAL_LEVEL always returns 100%! so using FE_HAS_SIGNAL as switch*/
+	if (state->it913x_status & FE_HAS_SIGNAL)
+		ret = (ret * 0xff) / 0x64;
+	else
+		ret = 0x0;
+	ret |= ret << 0x8;
+	*strength = ret;
+	return 0;
+}
+
+static int it913x_fe_read_snr(struct dvb_frontend *fe, u16* snr)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret = it913x_read_reg_u8(state, SIGNAL_QUALITY);
+	ret = (ret * 0xff) / 0x64;
+	ret |= (ret << 0x8);
+	*snr = ~ret;
+	return 0;
+}
+
+static int it913x_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	*ber = 0;
+	return 0;
+}
+
+static int it913x_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	*ucblocks = 0;
+	return 0;
+}
+
+static int it913x_fe_get_frontend(struct dvb_frontend *fe,
+			struct dvb_frontend_parameters *p)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret;
+	u8 reg[8];
+
+	ret = it913x_read_reg(state, REG_TPSD_TX_MODE, reg, sizeof(reg));
+
+	if (reg[3] < 3)
+		p->u.ofdm.constellation = fe_con[reg[3]];
+
+	if (reg[0] < 3)
+		p->u.ofdm.transmission_mode = fe_mode[reg[0]];
+
+	if (reg[1] < 4)
+		p->u.ofdm.guard_interval = fe_gi[reg[1]];
+
+	if (reg[2] < 4)
+		p->u.ofdm.hierarchy_information = fe_hi[reg[2]];
+
+	p->u.ofdm.code_rate_HP = (reg[6] < 6) ? fe_code[reg[6]] : FEC_NONE;
+	p->u.ofdm.code_rate_LP = (reg[7] < 6) ? fe_code[reg[7]] : FEC_NONE;
+
+	return 0;
+}
+
+static int it913x_fe_set_frontend(struct dvb_frontend *fe,
+			struct dvb_frontend_parameters *p)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret, i;
+	u8 empty_ch, last_ch;
+
+	state->it913x_status = 0;
+
+	/* Set bw*/
+	ret = it913x_fe_select_bw(state, p->u.ofdm.bandwidth,
+		state->adcFrequency);
+
+	/* Training Mode Off */
+	ret = it913x_write_reg(state, PRO_LINK, TRAINING_MODE, 0x0);
+
+	/* Clear Empty Channel */
+	ret = it913x_write_reg(state, PRO_DMOD, EMPTY_CHANNEL_STATUS, 0x0);
+
+	/* Clear bits */
+	ret = it913x_write_reg(state, PRO_DMOD, MP2IF_SYNC_LK, 0x0);
+	/* LED on */
+	ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1);
+	/* Select Band*/
+	if ((p->frequency >= 51000000) && (p->frequency <= 230000000))
+		i = 0;
+	else if ((p->frequency >= 350000000) && (p->frequency <= 900000000))
+			i = 1;
+	else if ((p->frequency >= 1450000000) && (p->frequency <= 1680000000))
+			i = 2;
+		else
+			return -EOPNOTSUPP;
+
+	ret = it913x_write_reg(state, PRO_DMOD, FREE_BAND, i);
+
+	deb_info("Frontend Set Tuner Type %02x", state->tuner_type);
+	switch (state->tuner_type) {
+	case IT9137: /* Tuner type 0x38 */
+		ret = it9137_set_tuner(state,
+			p->u.ofdm.bandwidth, p->frequency);
+		break;
+	default:
+		if (fe->ops.tuner_ops.set_params) {
+			fe->ops.tuner_ops.set_params(fe, p);
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+		break;
+	}
+	/* LED off */
+	ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x0);
+	/* Trigger ofsm */
+	ret = it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x0);
+	last_ch = 2;
+	for (i = 0; i < 40; ++i) {
+		empty_ch = it913x_read_reg_u8(state, EMPTY_CHANNEL_STATUS);
+		if (last_ch == 1 && empty_ch == 1)
+			break;
+		if (last_ch == 2 && empty_ch == 2)
+			return 0;
+		last_ch = empty_ch;
+		msleep(25);
+	}
+	for (i = 0; i < 40; ++i) {
+		if (it913x_read_reg_u8(state, D_TPSD_LOCK) == 1)
+			break;
+		msleep(25);
+	}
+
+	state->frequency = p->frequency;
+	return 0;
+}
+
+static int it913x_fe_suspend(struct it913x_fe_state *state)
+{
+	int ret, i;
+	u8 b;
+
+	ret = it913x_write_reg(state, PRO_DMOD, SUSPEND_FLAG, 0x1);
+
+	ret |= it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x0);
+
+	for (i = 0; i < 128; i++) {
+		ret = it913x_read_reg(state, SUSPEND_FLAG, &b, 1);
+		if (ret < 0)
+			return -ENODEV;
+		if (b == 0)
+			break;
+
+	}
+
+	ret |= it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x8);
+	/* Turn LED off */
+	ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x0);
+
+	ret |= it913x_fe_script_loader(state, it9137_tuner_off);
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+/* Power sequence */
+/* Power Up	Tuner on -> Frontend suspend off -> Tuner clk on */
+/* Power Down	Frontend suspend on -> Tuner clk off -> Tuner off */
+
+static int it913x_fe_sleep(struct dvb_frontend *fe)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	return it913x_fe_suspend(state);
+}
+
+static u32 compute_div(u32 a, u32 b, u32 x)
+{
+	u32 res = 0;
+	u32 c = 0;
+	u32 i = 0;
+
+	if (a > b) {
+		c = a / b;
+		a = a - c * b;
+	}
+
+	for (i = 0; i < x; i++) {
+		if (a >= b) {
+			res += 1;
+			a -= b;
+		}
+		a <<= 1;
+		res <<= 1;
+	}
+
+	res = (c << x) + res;
+
+	return res;
+}
+
+static int it913x_fe_start(struct it913x_fe_state *state)
+{
+	struct it913xset *set_fe;
+	struct it913xset *set_mode;
+	int ret;
+	u8 adf = (state->adf & 0xf);
+	u32 adc, xtal;
+	u8 b[4];
+
+	ret = it913x_init_tuner(state);
+
+	if (adf < 12) {
+		state->crystalFrequency = fe_clockTable[adf].xtal ;
+		state->table = fe_clockTable[adf].table;
+		state->adcFrequency = state->table->adcFrequency;
+
+		adc = compute_div(state->adcFrequency, 1000000ul, 19ul);
+		xtal = compute_div(state->crystalFrequency, 1000000ul, 19ul);
+
+	} else
+		return -EINVAL;
+
+	deb_info("Xtal Freq :%d Adc Freq :%d Adc %08x Xtal %08x",
+		state->crystalFrequency, state->adcFrequency, adc, xtal);
+
+	/* Set LED indicator on GPIOH3 */
+	ret = it913x_write_reg(state, PRO_LINK, GPIOH3_EN, 0x1);
+	ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_ON, 0x1);
+	ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1);
+
+	ret |= it913x_write_reg(state, PRO_LINK, 0xf641, state->tuner_type);
+	ret |= it913x_write_reg(state, PRO_DMOD, 0xf5ca, 0x01);
+	ret |= it913x_write_reg(state, PRO_DMOD, 0xf715, 0x01);
+
+	b[0] = xtal & 0xff;
+	b[1] = (xtal >> 8) & 0xff;
+	b[2] = (xtal >> 16) & 0xff;
+	b[3] = (xtal >> 24);
+	ret |= it913x_write(state, PRO_DMOD, XTAL_CLK, b , 4);
+
+	b[0] = adc & 0xff;
+	b[1] = (adc >> 8) & 0xff;
+	b[2] = (adc >> 16) & 0xff;
+	ret |= it913x_write(state, PRO_DMOD, ADC_FREQ, b, 3);
+
+	switch (state->tuner_type) {
+	case IT9137: /* Tuner type 0x38 */
+		set_fe = it9137_set;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* set the demod */
+	ret = it913x_fe_script_loader(state, set_fe);
+	/* Always solo frontend */
+	set_mode = set_solo_fe;
+	ret |= it913x_fe_script_loader(state, set_mode);
+
+	ret |= it913x_fe_suspend(state);
+	return 0;
+}
+
+static int it913x_fe_init(struct dvb_frontend *fe)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret = 0;
+	/* Power Up Tuner - common all versions */
+	ret = it913x_write_reg(state, PRO_DMOD, 0xec40, 0x1);
+
+	ret |= it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x0);
+
+	ret |= it913x_fe_script_loader(state, init_1);
+
+	switch (state->tuner_type) {
+	case IT9137:
+		ret |= it913x_write_reg(state, PRO_DMOD, 0xfba8, 0x0);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+static void it913x_fe_release(struct dvb_frontend *fe)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops it913x_fe_ofdm_ops;
+
+struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
+		u8 i2c_addr, u8 adf, u8 type)
+{
+	struct it913x_fe_state *state = NULL;
+	int ret;
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct it913x_fe_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	state->i2c_adap = i2c_adap;
+	state->i2c_addr = i2c_addr;
+	state->adf = adf;
+	state->tuner_type = type;
+
+	ret = it913x_fe_start(state);
+	if (ret < 0)
+		goto error;
+
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &it913x_fe_ofdm_ops,
+			sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	return &state->frontend;
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(it913x_fe_attach);
+
+static struct dvb_frontend_ops it913x_fe_ofdm_ops = {
+
+	.info = {
+		.name			= "it913x-fe DVB-T",
+		.type			= FE_OFDM,
+		.frequency_min		= 51000000,
+		.frequency_max		= 1680000000,
+		.frequency_stepsize	= 62500,
+		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+			FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
+			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release = it913x_fe_release,
+
+	.init = it913x_fe_init,
+	.sleep = it913x_fe_sleep,
+
+	.set_frontend = it913x_fe_set_frontend,
+	.get_frontend = it913x_fe_get_frontend,
+
+	.read_status = it913x_fe_read_status,
+	.read_signal_strength = it913x_fe_read_signal_strength,
+	.read_snr = it913x_fe_read_snr,
+	.read_ber = it913x_fe_read_ber,
+	.read_ucblocks = it913x_fe_read_ucblocks,
+};
+
+MODULE_DESCRIPTION("it913x Frontend and it9137 tuner");
+MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
+MODULE_VERSION("1.07");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/it913x-fe.h linux-libre-3.2-gnu/drivers/media/dvb/frontends/it913x-fe.h
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/it913x-fe.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/it913x-fe.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,196 @@
+/*
+ *  Driver for it913x Frontend
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You 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 IT913X_FE_H
+#define IT913X_FE_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+#if defined(CONFIG_DVB_IT913X_FE) || (defined(CONFIG_DVB_IT913X_FE_MODULE) && \
+defined(MODULE))
+extern struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
+			u8 i2c_addr, u8 adf, u8 type);
+#else
+static inline struct dvb_frontend *it913x_fe_attach(
+		struct i2c_adapter *i2c_adap,	u8 i2c_addr, u8 adf, u8 type)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_IT913X_FE */
+#define I2C_BASE_ADDR		0x10
+#define DEV_0			0x0
+#define DEV_1			0x10
+#define PRO_LINK		0x0
+#define PRO_DMOD		0x1
+#define DEV_0_DMOD		(PRO_DMOD << 0x7)
+#define DEV_1_DMOD		(DEV_0_DMOD | DEV_1)
+#define CHIP2_I2C_ADDR		0x3a
+
+#define AFE_MEM0		0xfb24
+
+#define MP2_SW_RST		0xf99d
+#define MP2IF2_SW_RST		0xf9a4
+
+#define	PADODPU			0xd827
+#define THIRDODPU		0xd828
+#define AGC_O_D			0xd829
+
+#define EP0_TX_EN		0xdd11
+#define EP0_TX_NAK		0xdd13
+#define EP4_TX_LEN_LSB		0xdd88
+#define EP4_TX_LEN_MSB		0xdd89
+#define EP4_MAX_PKT		0xdd0c
+#define EP5_TX_LEN_LSB		0xdd8a
+#define EP5_TX_LEN_MSB		0xdd8b
+#define EP5_MAX_PKT		0xdd0d
+
+#define IO_MUX_POWER_CLK	0xd800
+#define CLK_O_EN		0xd81a
+#define I2C_CLK			0xf103
+#define I2C_CLK_100		0x7
+#define I2C_CLK_400		0x1a
+
+#define D_TPSD_LOCK		0xf5a9
+#define MP2IF2_EN		0xf9a3
+#define MP2IF_SERIAL		0xf985
+#define TSIS_ENABLE		0xf9cd
+#define MP2IF2_HALF_PSB		0xf9a5
+#define MP2IF_STOP_EN		0xf9b5
+#define MPEG_FULL_SPEED		0xf990
+#define TOP_HOSTB_SER_MODE	0xd91c
+
+#define PID_RST			0xf992
+#define PID_EN			0xf993
+#define PID_INX_EN		0xf994
+#define PID_INX			0xf995
+#define PID_LSB			0xf996
+#define PID_MSB			0xf997
+
+#define MP2IF_MPEG_PAR_MODE	0xf986
+#define DCA_UPPER_CHIP		0xf731
+#define DCA_LOWER_CHIP		0xf732
+#define DCA_PLATCH		0xf730
+#define DCA_FPGA_LATCH		0xf778
+#define DCA_STAND_ALONE		0xf73c
+#define DCA_ENABLE		0xf776
+
+#define DVBT_INTEN		0xf41f
+#define DVBT_ENABLE		0xf41a
+#define HOSTB_DCA_LOWER		0xd91f
+#define HOSTB_MPEG_PAR_MODE	0xd91b
+#define HOSTB_MPEG_SER_MODE	0xd91c
+#define HOSTB_MPEG_SER_DO7	0xd91d
+#define HOSTB_DCA_UPPER		0xd91e
+#define PADMISCDR2		0xd830
+#define PADMISCDR4		0xd831
+#define PADMISCDR8		0xd832
+#define PADMISCDRSR		0xd833
+#define LOCK3_OUT		0xd8fd
+
+#define GPIOH1_O		0xd8af
+#define GPIOH1_EN		0xd8b0
+#define GPIOH1_ON		0xd8b1
+#define GPIOH3_O		0xd8b3
+#define GPIOH3_EN		0xd8b4
+#define GPIOH3_ON		0xd8b5
+#define GPIOH5_O		0xd8bb
+#define GPIOH5_EN		0xd8bc
+#define GPIOH5_ON		0xd8bd
+
+#define AFE_MEM0		0xfb24
+
+#define REG_TPSD_TX_MODE	0xf900
+#define REG_TPSD_GI		0xf901
+#define REG_TPSD_HIER		0xf902
+#define REG_TPSD_CONST		0xf903
+#define REG_BW			0xf904
+#define REG_PRIV		0xf905
+#define REG_TPSD_HP_CODE	0xf906
+#define REG_TPSD_LP_CODE	0xf907
+
+#define MP2IF_SYNC_LK		0xf999
+#define ADC_FREQ		0xf1cd
+
+#define TRIGGER_OFSM		0x0000
+/* COEFF Registers start at 0x0001 to 0x0020 */
+#define COEFF_1_2048		0x0001
+#define XTAL_CLK		0x0025
+#define BFS_FCW			0x0029
+#define TPSD_LOCK		0x003c
+#define TRAINING_MODE		0x0040
+#define ADC_X_2			0x0045
+#define TUNER_ID		0x0046
+#define EMPTY_CHANNEL_STATUS	0x0047
+#define SIGNAL_LEVEL		0x0048
+#define SIGNAL_QUALITY		0x0049
+#define EST_SIGNAL_LEVEL	0x004a
+#define FREE_BAND		0x004b
+#define SUSPEND_FLAG		0x004c
+/* Build in tuners */
+#define IT9137 0x38
+
+enum {
+	CMD_DEMOD_READ = 0,
+	CMD_DEMOD_WRITE,
+	CMD_TUNER_READ,
+	CMD_TUNER_WRITE,
+	CMD_REG_EEPROM_READ,
+	CMD_REG_EEPROM_WRITE,
+	CMD_DATA_READ,
+	CMD_VAR_READ = 8,
+	CMD_VAR_WRITE,
+	CMD_PLATFORM_GET,
+	CMD_PLATFORM_SET,
+	CMD_IP_CACHE,
+	CMD_IP_ADD,
+	CMD_IP_REMOVE,
+	CMD_PID_ADD,
+	CMD_PID_REMOVE,
+	CMD_SIPSI_GET,
+	CMD_SIPSI_MPE_RESET,
+	CMD_H_PID_ADD = 0x15,
+	CMD_H_PID_REMOVE,
+	CMD_ABORT,
+	CMD_IR_GET,
+	CMD_IR_SET,
+	CMD_FW_DOWNLOAD = 0x21,
+	CMD_QUERYINFO,
+	CMD_BOOT,
+	CMD_FW_DOWNLOAD_BEGIN,
+	CMD_FW_DOWNLOAD_END,
+	CMD_RUN_CODE,
+	CMD_SCATTER_READ = 0x28,
+	CMD_SCATTER_WRITE,
+	CMD_GENERIC_READ,
+	CMD_GENERIC_WRITE
+};
+
+enum {
+	READ_LONG,
+	WRITE_LONG,
+	READ_SHORT,
+	WRITE_SHORT,
+	READ_DATA,
+	WRITE_DATA,
+	WRITE_CMD,
+};
+
+#endif /* IT913X_FE_H */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/it913x-fe-priv.h linux-libre-3.2-gnu/drivers/media/dvb/frontends/it913x-fe-priv.h
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/it913x-fe-priv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/it913x-fe-priv.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,336 @@
+
+struct it913xset {	u32 pro;
+			u32 address;
+			u8 reg[15];
+			u8 count;
+};
+
+struct adctable {	u32 adcFrequency;
+			u32 bandwidth;
+			u32 coeff_1_2048;
+			u32 coeff_1_4096;
+			u32 coeff_1_8191;
+			u32 coeff_1_8192;
+			u32 coeff_1_8193;
+			u32 coeff_2_2k;
+			u32 coeff_2_4k;
+			u32 coeff_2_8k;
+			u16 bfsfcw_fftinx_ratio;
+			u16 fftinx_bfsfcw_ratio;
+};
+
+/* clock and coeff tables only table 3 is used with IT9137*/
+/* TODO other tables relate AF9035 may be removed */
+static struct adctable tab1[] = {
+	{	20156250, BANDWIDTH_6_MHZ,
+		0x02b8ba6e, 0x015c5d37, 0x00ae340d, 0x00ae2e9b, 0x00ae292a,
+		0x015c5d37, 0x00ae2e9b, 0x0057174e, 0x02f1, 0x015c	},
+	{	20156250, BANDWIDTH_7_MHZ,
+		0x032cd980, 0x01966cc0, 0x00cb3cba, 0x00cb3660, 0x00cb3007,
+		0x01966cc0, 0x00cb3660, 0x00659b30, 0x0285, 0x0196	},
+	{	20156250, BANDWIDTH_8_MHZ,
+		0x03a0f893, 0x01d07c49, 0x00e84567, 0x00e83e25, 0x00e836e3,
+		0x01d07c49, 0x00e83e25, 0x00741f12, 0x0234, 0x01d0	},
+	{	20156250, BANDWIDTH_5_MHZ,
+		0x02449b5c, 0x01224dae, 0x00912b60, 0x009126d7, 0x0091224e,
+		0x01224dae, 0x009126d7, 0x0048936b, 0x0387, 0x0122	}
+};
+
+static struct adctable tab2[] = {
+	{	20187500, BANDWIDTH_6_MHZ,
+		0x02b7a654, 0x015bd32a, 0x00adef04, 0x00ade995, 0x00ade426,
+		0x015bd32a, 0x00ade995, 0x0056f4ca, 0x02f2, 0x015c	},
+	{	20187500, BANDWIDTH_7_MHZ,
+		0x032b9761, 0x0195cbb1, 0x00caec30, 0x00cae5d8, 0x00cadf81,
+		0x0195cbb1, 0x00cae5d8, 0x006572ec, 0x0286, 0x0196	},
+	{	20187500, BANDWIDTH_8_MHZ,
+		0x039f886f, 0x01cfc438, 0x00e7e95b, 0x00e7e21c, 0x00e7dadd,
+		0x01cfc438, 0x00e7e21c, 0x0073f10e, 0x0235, 0x01d0	},
+	{	20187500, BANDWIDTH_5_MHZ,
+		0x0243b546, 0x0121daa3, 0x0090f1d9, 0x0090ed51, 0x0090e8ca,
+		0x0121daa3, 0x0090ed51, 0x004876a9, 0x0388, 0x0122	}
+
+};
+
+static struct adctable tab3[] = {
+	{	20250000, BANDWIDTH_6_MHZ,
+		0x02b580ad, 0x015ac057, 0x00ad6597, 0x00ad602b, 0x00ad5ac1,
+		0x015ac057, 0x00ad602b, 0x0056b016, 0x02f4, 0x015b	},
+	{	20250000, BANDWIDTH_7_MHZ,
+		0x03291620, 0x01948b10, 0x00ca4bda, 0x00ca4588, 0x00ca3f36,
+		0x01948b10, 0x00ca4588, 0x006522c4, 0x0288, 0x0195	},
+	{	20250000, BANDWIDTH_8_MHZ,
+		0x039cab92, 0x01ce55c9, 0x00e7321e, 0x00e72ae4, 0x00e723ab,
+		0x01ce55c9, 0x00e72ae4, 0x00739572, 0x0237, 0x01ce	},
+	{	20250000, BANDWIDTH_5_MHZ,
+		0x0241eb3b, 0x0120f59e, 0x00907f53, 0x00907acf, 0x0090764b,
+		0x0120f59e, 0x00907acf, 0x00483d67, 0x038b, 0x0121	}
+
+};
+
+static struct adctable tab4[] = {
+	{	20583333, BANDWIDTH_6_MHZ,
+		0x02aa4598, 0x015522cc, 0x00aa96bb, 0x00aa9166, 0x00aa8c12,
+		0x015522cc, 0x00aa9166, 0x005548b3, 0x0300, 0x0155	},
+	{	20583333, BANDWIDTH_7_MHZ,
+		0x031bfbdc, 0x018dfdee, 0x00c7052f, 0x00c6fef7, 0x00c6f8bf,
+		0x018dfdee, 0x00c6fef7, 0x00637f7b, 0x0293, 0x018e	},
+	{	20583333, BANDWIDTH_8_MHZ,
+		0x038db21f, 0x01c6d910, 0x00e373a3, 0x00e36c88, 0x00e3656d,
+		0x01c6d910, 0x00e36c88, 0x0071b644, 0x0240, 0x01c7	},
+	{	20583333, BANDWIDTH_5_MHZ,
+		0x02388f54, 0x011c47aa, 0x008e2846, 0x008e23d5, 0x008e1f64,
+		0x011c47aa, 0x008e23d5, 0x004711ea, 0x039a, 0x011c	}
+
+};
+
+static struct adctable tab5[] = {
+	{	20416667, BANDWIDTH_6_MHZ,
+		0x02afd765, 0x0157ebb3, 0x00abfb39, 0x00abf5d9, 0x00abf07a,
+		0x0157ebb3, 0x00abf5d9, 0x0055faed, 0x02fa, 0x0158	},
+	{	20416667, BANDWIDTH_7_MHZ,
+		0x03227b4b, 0x01913da6, 0x00c8a518, 0x00c89ed3, 0x00c8988e,
+		0x01913da6, 0x00c89ed3, 0x00644f69, 0x028d, 0x0191	},
+	{	20416667, BANDWIDTH_8_MHZ,
+		0x03951f32, 0x01ca8f99, 0x00e54ef7, 0x00e547cc, 0x00e540a2,
+		0x01ca8f99, 0x00e547cc, 0x0072a3e6, 0x023c, 0x01cb	},
+	{	20416667, BANDWIDTH_5_MHZ,
+		0x023d337f, 0x011e99c0, 0x008f515a, 0x008f4ce0, 0x008f4865,
+		0x011e99c0, 0x008f4ce0, 0x0047a670, 0x0393, 0x011f	}
+
+};
+
+static struct adctable tab6[] = {
+	{	20480000, BANDWIDTH_6_MHZ,
+		0x02adb6db, 0x0156db6e, 0x00ab7312, 0x00ab6db7, 0x00ab685c,
+		0x0156db6e, 0x00ab6db7, 0x0055b6db, 0x02fd, 0x0157	},
+	{	20480000, BANDWIDTH_7_MHZ,
+		0x03200000, 0x01900000, 0x00c80640, 0x00c80000, 0x00c7f9c0,
+		0x01900000, 0x00c80000, 0x00640000, 0x028f, 0x0190	},
+	{	20480000, BANDWIDTH_8_MHZ,
+		0x03924925, 0x01c92492, 0x00e4996e, 0x00e49249, 0x00e48b25,
+		0x01c92492, 0x00e49249, 0x00724925, 0x023d, 0x01c9	},
+	{	20480000, BANDWIDTH_5_MHZ,
+		0x023b6db7, 0x011db6db, 0x008edfe5, 0x008edb6e, 0x008ed6f7,
+		0x011db6db, 0x008edb6e, 0x00476db7, 0x0396, 0x011e	}
+};
+
+static struct adctable tab7[] = {
+	{	20500000, BANDWIDTH_6_MHZ,
+		0x02ad0b99, 0x015685cc, 0x00ab4840, 0x00ab42e6, 0x00ab3d8c,
+		0x015685cc, 0x00ab42e6, 0x0055a173, 0x02fd, 0x0157	},
+	{	20500000, BANDWIDTH_7_MHZ,
+		0x031f3832, 0x018f9c19, 0x00c7d44b, 0x00c7ce0c, 0x00c7c7ce,
+		0x018f9c19, 0x00c7ce0c, 0x0063e706, 0x0290, 0x0190	},
+	{	20500000, BANDWIDTH_8_MHZ,
+		0x039164cb, 0x01c8b266, 0x00e46056, 0x00e45933, 0x00e45210,
+		0x01c8b266, 0x00e45933, 0x00722c99, 0x023e, 0x01c9	},
+	{	20500000, BANDWIDTH_5_MHZ,
+		0x023adeff, 0x011d6f80, 0x008ebc36, 0x008eb7c0, 0x008eb34a,
+		0x011d6f80, 0x008eb7c0, 0x00475be0, 0x0396, 0x011d	}
+
+};
+
+static struct adctable tab8[] = {
+	{	20625000, BANDWIDTH_6_MHZ,
+		0x02a8e4bd, 0x0154725e, 0x00aa3e81, 0x00aa392f, 0x00aa33de,
+		0x0154725e, 0x00aa392f, 0x00551c98, 0x0302, 0x0154	},
+	{	20625000, BANDWIDTH_7_MHZ,
+		0x031a6032, 0x018d3019, 0x00c69e41, 0x00c6980c, 0x00c691d8,
+		0x018d3019, 0x00c6980c, 0x00634c06, 0x0294, 0x018d	},
+	{	20625000, BANDWIDTH_8_MHZ,
+		0x038bdba6, 0x01c5edd3, 0x00e2fe02, 0x00e2f6ea, 0x00e2efd2,
+		0x01c5edd3, 0x00e2f6ea, 0x00717b75, 0x0242, 0x01c6	},
+	{	20625000, BANDWIDTH_5_MHZ,
+		0x02376948, 0x011bb4a4, 0x008ddec1, 0x008dda52, 0x008dd5e3,
+		0x011bb4a4, 0x008dda52, 0x0046ed29, 0x039c, 0x011c	}
+
+};
+
+struct table {
+		u32 xtal;
+		struct adctable *table;
+};
+
+static struct table fe_clockTable[] = {
+		{12000000, tab3},	/* FPGA     */
+		{16384000, tab6},	/* 16.38MHz */
+		{20480000, tab6},	/* 20.48MHz */
+		{36000000, tab3},	/* 36.00MHz */
+		{30000000, tab1},	/* 30.00MHz */
+		{26000000, tab4},	/* 26.00MHz */
+		{28000000, tab5},	/* 28.00MHz */
+		{32000000, tab7},	/* 32.00MHz */
+		{34000000, tab2},	/* 34.00MHz */
+		{24000000, tab1},	/* 24.00MHz */
+		{22000000, tab8},	/* 22.00MHz */
+		{12000000, tab3}	/* 12.00MHz */
+};
+
+/* fe get */
+fe_code_rate_t fe_code[] = {
+	FEC_1_2,
+	FEC_2_3,
+	FEC_3_4,
+	FEC_5_6,
+	FEC_7_8,
+	FEC_NONE,
+};
+
+fe_guard_interval_t fe_gi[] = {
+	GUARD_INTERVAL_1_32,
+	GUARD_INTERVAL_1_16,
+	GUARD_INTERVAL_1_8,
+	GUARD_INTERVAL_1_4,
+};
+
+fe_hierarchy_t fe_hi[] = {
+	HIERARCHY_NONE,
+	HIERARCHY_1,
+	HIERARCHY_2,
+	HIERARCHY_4,
+};
+
+fe_transmit_mode_t fe_mode[] = {
+	TRANSMISSION_MODE_2K,
+	TRANSMISSION_MODE_8K,
+	TRANSMISSION_MODE_4K,
+};
+
+fe_modulation_t fe_con[] = {
+	QPSK,
+	QAM_16,
+	QAM_64,
+};
+
+/* Standard demodulator functions */
+static struct it913xset set_solo_fe[] = {
+	{PRO_LINK, DVBT_INTEN, {0x04}, 0x01},
+	{PRO_LINK, DVBT_ENABLE, {0x05}, 0x01},
+	{PRO_DMOD, MP2IF_MPEG_PAR_MODE, {0x00}, 0x01},
+	{PRO_LINK, HOSTB_MPEG_SER_MODE, {0x00}, 0x01},
+	{PRO_LINK, HOSTB_MPEG_PAR_MODE, {0x00}, 0x01},
+	{PRO_DMOD, DCA_UPPER_CHIP, {0x00}, 0x01},
+	{PRO_LINK, HOSTB_DCA_UPPER, {0x00}, 0x01},
+	{PRO_DMOD, DCA_LOWER_CHIP, {0x00}, 0x01},
+	{PRO_LINK, HOSTB_DCA_LOWER, {0x00}, 0x01},
+	{PRO_DMOD, DCA_PLATCH, {0x00}, 0x01},
+	{PRO_DMOD, DCA_FPGA_LATCH, {0x00}, 0x01},
+	{PRO_DMOD, DCA_STAND_ALONE, {0x01}, 0x01},
+	{PRO_DMOD, DCA_ENABLE, {0x00}, 0x01},
+	{PRO_DMOD, MP2IF_MPEG_PAR_MODE, {0x00}, 0x01},
+	{PRO_DMOD, BFS_FCW, {0x00, 0x00, 0x00}, 0x03},
+	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
+
+static struct it913xset init_1[] = {
+	{PRO_LINK, LOCK3_OUT, {0x01}, 0x01},
+	{PRO_LINK, PADMISCDRSR, {0x01}, 0x01},
+	{PRO_LINK, PADMISCDR2, {0x00}, 0x01},
+	{PRO_LINK, PADMISCDR4, {0x00}, 0x01}, /* Power up */
+	{PRO_LINK, PADMISCDR8, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+/* ---------IT9137 0x38 tuner init---------- */
+static struct it913xset it9137_set[] = {
+	{PRO_DMOD, 0x0043, {0x00}, 0x01},
+	{PRO_DMOD, 0x0046, {0x38}, 0x01},
+	{PRO_DMOD, 0x0051, {0x01}, 0x01},
+	{PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0x0068, {0x0a}, 0x01},
+	{PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
+	{PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xc8, 0x01}, 0x05},
+	{PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02},
+	{PRO_DMOD, 0x0081, {	0x0a, 0x12, 0x02, 0x0a, 0x03, 0xc8, 0xb8,
+				0xd0, 0xc3, 0x01	}, 0x0a},
+	{PRO_DMOD, 0x008e, {0x01}, 0x01},
+	{PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+	{PRO_DMOD, 0x0099, {0x01}, 0x01},
+	{PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+	{PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+	{PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
+	{PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
+	{PRO_DMOD, 0x00b3, {0x02, 0x32}, 0x02},
+	{PRO_DMOD, 0x00b6, {0x14}, 0x01},
+	{PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05}, 0x03},
+	{PRO_DMOD, 0x00c4, {0x00}, 0x01},
+	{PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+	{PRO_DMOD, 0x00cc, {0x2e, 0x51, 0x33}, 0x03},
+	{PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03},
+	{PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+	{PRO_DMOD, 0x00fc, {	0x02, 0x02, 0x02, 0x09, 0x50, 0x7b, 0x77,
+				0x00, 0x02, 0xc8, 0x05, 0x7b	}, 0x0c},
+	{PRO_DMOD, 0x0109, {0x02}, 0x01},
+	{PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
+	{PRO_DMOD, 0x011a, {0xc8, 0x7b, 0xbc, 0xa0}, 0x04},
+	{PRO_DMOD, 0x0122, {0x02, 0x18, 0xc3}, 0x03},
+	{PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02},
+	{PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
+	{PRO_DMOD, 0x0137, {0x01, 0x00, 0x07, 0x00, 0x06}, 0x05},
+	{PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xc8}, 0x04},
+	{PRO_DMOD, 0xf130, {0x04}, 0x01},
+	{PRO_DMOD, 0xf132, {0x04}, 0x01},
+	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
+	{PRO_DMOD, 0xf146, {0x00}, 0x01},
+	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
+	{PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
+	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
+	{PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+	{PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+	{PRO_DMOD, 0xf163, {0x05}, 0x01},
+	{PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+	{PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0xf183, {0x01}, 0x01},
+	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
+	{PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+	{PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+	{PRO_DMOD, 0xf204, {0x10}, 0x01},
+	{PRO_DMOD, 0xf214, {0x00}, 0x01},
+	{PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+	{PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+	{PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+	{PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+	{PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+	{PRO_DMOD, 0xf5df, {0xfb, 0x00}, 0x02},
+	{PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+	{PRO_DMOD, 0xf5f8, {0x01}, 0x01},
+	{PRO_DMOD, 0xf5fd, {0x01}, 0x01},
+	{PRO_DMOD, 0xf600, {	0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
+				0x1f	}, 0x08},
+	{PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+	{PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
+	{PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+	{PRO_DMOD, 0xf905, {0x01}, 0x01},
+	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
+	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+	{PRO_LINK, GPIOH5_EN, {0x01}, 0x01},
+	{PRO_LINK, GPIOH5_ON, {0x01}, 0x01},
+	{PRO_LINK, GPIOH5_O, {0x00}, 0x01},
+	{PRO_LINK, GPIOH5_O, {0x01}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
+static struct it913xset it9137_tuner_off[] = {
+	{PRO_DMOD, 0xfba8, {0x01}, 0x01}, /* Tuner Clock Off  */
+	{PRO_DMOD, 0xec40, {0x00}, 0x01}, /* Power Down Tuner */
+	{PRO_DMOD, 0xec02, {0x3f, 0x1f, 0x3f, 0x3f}, 0x04},
+	{PRO_DMOD, 0xec3f, {0x01}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
+static struct it913xset set_it9137_template[] = {
+	{PRO_DMOD, 0xee06, {0x00}, 0x01},
+	{PRO_DMOD, 0xec56, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4c, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4d, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4e, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4f, {0x00}, 0x01},
+	{PRO_DMOD, 0xec50, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/Kconfig linux-libre-3.2-gnu/drivers/media/dvb/frontends/Kconfig
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -236,6 +236,13 @@
 	  A DVB-S/DSS Direct Conversion reveiver.
 	  Say Y when you want to support this frontend.
 
+config DVB_TDA10071
+	tristate "NXP TDA10071"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  Say Y when you want to support this frontend.
+
 comment "DVB-T (terrestrial) frontends"
 	depends on DVB_CORE
 
@@ -600,6 +607,16 @@
 	help
 	  An SEC control chips.
 
+config DVB_LNBP22
+	tristate "LNBP22 SEC controllers"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  LNB power supply and control voltage
+	  regulator chip with step-up converter
+	  and I2C interface.
+	  Say Y when you want to support this chip.
+
 config DVB_ISL6405
 	tristate "ISL6405 SEC controller"
 	depends on DVB_CORE && I2C
@@ -621,6 +638,11 @@
 	help
 	  A SEC controller chip from Intersil
 
+config DVB_A8293
+	tristate "Allegro A8293"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+
 config DVB_LGS8GL5
 	tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)"
 	depends on DVB_CORE && I2C
@@ -661,6 +683,14 @@
 	help
 	  A DVB-S tuner module. Say Y when you want to support this frontend.
 
+config DVB_IT913X_FE
+	tristate "it913x frontend and it9137 tuner"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  A DVB-T tuner module.
+	  Say Y when you want to support this frontend.
+
 comment "Tools to develop new frontends"
 
 config DVB_DUMMY_FE
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/lnbp22.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/lnbp22.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/lnbp22.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/lnbp22.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,148 @@
+/*
+ * lnbp22.h - driver for lnb supply and control ic lnbp22
+ *
+ * Copyright (C) 2006 Dominik Kuhlen
+ * Based on lnbp21 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "lnbp22.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+
+#define dprintk(lvl, arg...) if (debug >= (lvl)) printk(arg)
+
+struct lnbp22 {
+	u8		    config[4];
+	struct i2c_adapter *i2c;
+};
+
+static int lnbp22_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct lnbp22 *lnbp22 = (struct lnbp22 *)fe->sec_priv;
+	struct i2c_msg msg = {
+		.addr = 0x08,
+		.flags = 0,
+		.buf = (char *)&lnbp22->config,
+		.len = sizeof(lnbp22->config),
+	};
+
+	dprintk(1, "%s: %d (18V=%d 13V=%d)\n", __func__, voltage,
+	       SEC_VOLTAGE_18, SEC_VOLTAGE_13);
+
+	lnbp22->config[3] = 0x60; /* Power down */
+	switch (voltage) {
+	case SEC_VOLTAGE_OFF:
+		break;
+	case SEC_VOLTAGE_13:
+		lnbp22->config[3] |= LNBP22_EN;
+		break;
+	case SEC_VOLTAGE_18:
+		lnbp22->config[3] |= (LNBP22_EN | LNBP22_VSEL);
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	dprintk(1, "%s: 0x%02x)\n", __func__, lnbp22->config[3]);
+	return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int lnbp22_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+	struct lnbp22 *lnbp22 = (struct lnbp22 *) fe->sec_priv;
+	struct i2c_msg msg = {
+		.addr = 0x08,
+		.flags = 0,
+		.buf = (char *)&lnbp22->config,
+		.len = sizeof(lnbp22->config),
+	};
+
+	dprintk(1, "%s: %d\n", __func__, (int)arg);
+	if (arg)
+		lnbp22->config[3] |= LNBP22_LLC;
+	else
+		lnbp22->config[3] &= ~LNBP22_LLC;
+
+	return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void lnbp22_release(struct dvb_frontend *fe)
+{
+	dprintk(1, "%s\n", __func__);
+	/* LNBP power off */
+	lnbp22_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+	/* free data */
+	kfree(fe->sec_priv);
+	fe->sec_priv = NULL;
+}
+
+struct dvb_frontend *lnbp22_attach(struct dvb_frontend *fe,
+					struct i2c_adapter *i2c)
+{
+	struct lnbp22 *lnbp22 = kmalloc(sizeof(struct lnbp22), GFP_KERNEL);
+	if (!lnbp22)
+		return NULL;
+
+	/* default configuration */
+	lnbp22->config[0] = 0x00; /* ? */
+	lnbp22->config[1] = 0x28; /* ? */
+	lnbp22->config[2] = 0x48; /* ? */
+	lnbp22->config[3] = 0x60; /* Power down */
+	lnbp22->i2c = i2c;
+	fe->sec_priv = lnbp22;
+
+	/* detect if it is present or not */
+	if (lnbp22_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+		dprintk(0, "%s LNBP22 not found\n", __func__);
+		kfree(lnbp22);
+		fe->sec_priv = NULL;
+		return NULL;
+	}
+
+	/* install release callback */
+	fe->ops.release_sec = lnbp22_release;
+
+	/* override frontend ops */
+	fe->ops.set_voltage = lnbp22_set_voltage;
+	fe->ops.enable_high_lnb_voltage = lnbp22_enable_high_lnb_voltage;
+
+	return fe;
+}
+EXPORT_SYMBOL(lnbp22_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp22");
+MODULE_AUTHOR("Dominik Kuhlen");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/lnbp22.h linux-libre-3.2-gnu/drivers/media/dvb/frontends/lnbp22.h
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/lnbp22.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/lnbp22.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,57 @@
+/*
+ * lnbp22.h - driver for lnb supply and control ic lnbp22
+ *
+ * Copyright (C) 2006 Dominik Kuhlen
+ * Based on lnbp21.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef _LNBP22_H
+#define _LNBP22_H
+
+/* Enable */
+#define LNBP22_EN	  0x10
+/* Voltage selection */
+#define LNBP22_VSEL	0x02
+/* Plus 1 Volt Bit */
+#define LNBP22_LLC	0x01
+
+#include <linux/dvb/frontend.h>
+
+#if defined(CONFIG_DVB_LNBP22) || \
+		(defined(CONFIG_DVB_LNBP22_MODULE) && defined(MODULE))
+/*
+ * override_set and override_clear control which system register bits (above)
+ * to always set & clear
+ */
+extern struct dvb_frontend *lnbp22_attach(struct dvb_frontend *fe,
+						struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *lnbp22_attach(struct dvb_frontend *fe,
+						struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_LNBP22 */
+
+#endif /* _LNBP22_H */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/Makefile linux-libre-3.2-gnu/drivers/media/dvb/frontends/Makefile
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,8 +2,8 @@
 # Makefile for the kernel DVB frontend device drivers.
 #
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/common/tuners/
 
 stb0899-objs = stb0899_drv.o stb0899_algo.o
 stv0900-objs = stv0900_core.o stv0900_sw.o
@@ -52,6 +52,7 @@
 obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o
 obj-$(CONFIG_DVB_CX24123) += cx24123.o
 obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
+obj-$(CONFIG_DVB_LNBP22) += lnbp22.o
 obj-$(CONFIG_DVB_ISL6405) += isl6405.o
 obj-$(CONFIG_DVB_ISL6421) += isl6421.o
 obj-$(CONFIG_DVB_TDA10086) += tda10086.o
@@ -91,4 +92,7 @@
 obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
 obj-$(CONFIG_DVB_DRXK) += drxk.o
 obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
+obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
+obj-$(CONFIG_DVB_A8293) += a8293.o
+obj-$(CONFIG_DVB_TDA10071) += tda10071.o
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/stb0899_algo.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/stb0899_algo.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/stb0899_algo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/stb0899_algo.c	2012-01-04 18:55:44.000000000 -0500
@@ -358,6 +358,9 @@
 	else
 		dataTime = 500;
 
+	/* clear previous failed END_LOOPVIT */
+	stb0899_read_reg(state, STB0899_VSTATUS);
+
 	stb0899_write_reg(state, STB0899_DSTATUS2, 0x00); /* force search loop	*/
 	while (1) {
 		/* WARNING! VIT LOCKED has to be tested before VIT_END_LOOOP	*/
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/stb0899_drv.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/stb0899_drv.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/stb0899_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/stb0899_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -706,7 +706,7 @@
 	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
 	for (i = 0; i < cmd->msg_len; i++) {
 		/* wait for FIFO empty	*/
-		if (stb0899_wait_diseqc_fifo_empty(state, 10) < 0)
+		if (stb0899_wait_diseqc_fifo_empty(state, 100) < 0)
 			return -ETIMEDOUT;
 
 		stb0899_write_reg(state, STB0899_DISFIFO, cmd->msg[i]);
@@ -1426,9 +1426,9 @@
 	if (iter_scale > config->ldpc_max_iter)
 		iter_scale = config->ldpc_max_iter;
 
-	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, MAX_ITER);
+	reg = STB0899_READ_S2REG(STB0899_S2FEC, MAX_ITER);
 	STB0899_SETFIELD_VAL(MAX_ITERATIONS, reg, iter_scale);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_MAX_ITER, STB0899_OFF0_MAX_ITER, reg);
+	stb0899_write_s2reg(state, STB0899_S2FEC, STB0899_BASE_MAX_ITER, STB0899_OFF0_MAX_ITER, reg);
 }
 
 static enum dvbfe_search stb0899_search(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/stv0288.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/stv0288.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/stv0288.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/stv0288.c	2012-01-04 18:55:44.000000000 -0500
@@ -127,6 +127,11 @@
 	if ((srate < 1000000) || (srate > 45000000))
 		return -EINVAL;
 
+	stv0288_writeregI(state, 0x22, 0);
+	stv0288_writeregI(state, 0x23, 0);
+	stv0288_writeregI(state, 0x2b, 0xff);
+	stv0288_writeregI(state, 0x2c, 0xf7);
+
 	temp = (unsigned int)srate / 1000;
 
 		temp = temp * 32768;
@@ -461,6 +466,7 @@
 
 	char tm;
 	unsigned char tda[3];
+	u8 reg, time_out = 0;
 
 	dprintk("%s : FE_SET_FRONTEND\n", __func__);
 
@@ -488,22 +494,29 @@
 	/* Carrier lock control register */
 	stv0288_writeregI(state, 0x15, 0xc5);
 
-	tda[0] = 0x2b; /* CFRM */
 	tda[2] = 0x0; /* CFRL */
-	for (tm = -6; tm < 7;) {
+	for (tm = -9; tm < 7;) {
 		/* Viterbi status */
-		if (stv0288_readreg(state, 0x24) & 0x8)
-			break;
-
-		tda[2] += 40;
-		if (tda[2] < 40)
+		reg = stv0288_readreg(state, 0x24);
+		if (reg & 0x8)
+				break;
+		if (reg & 0x80) {
+			time_out++;
+			if (time_out > 10)
+				break;
+			tda[2] += 40;
+			if (tda[2] < 40)
+				tm++;
+		} else {
 			tm++;
+			tda[2] = 0;
+			time_out = 0;
+		}
 		tda[1] = (unsigned char)tm;
 		stv0288_writeregI(state, 0x2b, tda[1]);
 		stv0288_writeregI(state, 0x2c, tda[2]);
 		udelay(30);
 	}
-
 	state->tuner_frequency = c->frequency;
 	state->fec_inner = FEC_AUTO;
 	state->symbol_rate = c->symbol_rate;
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/stv090x.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/stv090x.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/stv090x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/stv090x.c	2012-01-04 18:55:44.000000000 -0500
@@ -3463,9 +3463,15 @@
 static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
 {
 	struct stv090x_state *state = fe->demodulator_priv;
-	u32 reg;
+	u32 reg, dstatus;
 	u8 search_state;
 
+	*status = 0;
+
+	dstatus = STV090x_READ_DEMOD(state, DSTATUS);
+	if (STV090x_GETFIELD_Px(dstatus, CAR_LOCK_FIELD))
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
 	reg = STV090x_READ_DEMOD(state, DMDSTATE);
 	search_state = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
 
@@ -3474,41 +3480,30 @@
 	case 1: /* first PLH detected */
 	default:
 		dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)");
-		*status = 0;
 		break;
 
 	case 2: /* DVB-S2 mode */
 		dprintk(FE_DEBUG, 1, "Delivery system: DVB-S2");
-		reg = STV090x_READ_DEMOD(state, DSTATUS);
-		if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) {
+		if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) {
 			reg = STV090x_READ_DEMOD(state, PDELSTATUS1);
 			if (STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD)) {
+				*status |= FE_HAS_VITERBI;
 				reg = STV090x_READ_DEMOD(state, TSSTATUS);
-				if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) {
-					*status = FE_HAS_SIGNAL |
-						  FE_HAS_CARRIER |
-						  FE_HAS_VITERBI |
-						  FE_HAS_SYNC |
-						  FE_HAS_LOCK;
-				}
+				if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD))
+					*status |= FE_HAS_SYNC | FE_HAS_LOCK;
 			}
 		}
 		break;
 
 	case 3: /* DVB-S1/legacy mode */
 		dprintk(FE_DEBUG, 1, "Delivery system: DVB-S");
-		reg = STV090x_READ_DEMOD(state, DSTATUS);
-		if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) {
+		if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) {
 			reg = STV090x_READ_DEMOD(state, VSTATUSVIT);
 			if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) {
+				*status |= FE_HAS_VITERBI;
 				reg = STV090x_READ_DEMOD(state, TSSTATUS);
-				if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) {
-					*status = FE_HAS_SIGNAL |
-						  FE_HAS_CARRIER |
-						  FE_HAS_VITERBI |
-						  FE_HAS_SYNC |
-						  FE_HAS_LOCK;
-				}
+				if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD))
+					*status |= FE_HAS_SYNC | FE_HAS_LOCK;
 			}
 		}
 		break;
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/tda10048.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/tda10048.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/tda10048.c	2012-03-19 21:35:39.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/tda10048.c	2012-03-19 21:38:03.000000000 -0400
@@ -206,15 +206,16 @@
 static struct pll_tab {
 	u32	clk_freq_khz;
 	u32	if_freq_khz;
-	u8	m, n, p;
 } pll_tab[] = {
-	{ TDA10048_CLK_4000,  TDA10048_IF_36130, 10, 0, 0 },
-	{ TDA10048_CLK_16000, TDA10048_IF_3300,  10, 3, 0 },
-	{ TDA10048_CLK_16000, TDA10048_IF_3500,  10, 3, 0 },
-	{ TDA10048_CLK_16000, TDA10048_IF_3800,  10, 3, 0 },
-	{ TDA10048_CLK_16000, TDA10048_IF_4000,  10, 3, 0 },
-	{ TDA10048_CLK_16000, TDA10048_IF_4300,  10, 3, 0 },
-	{ TDA10048_CLK_16000, TDA10048_IF_36130, 10, 3, 0 },
+	{ TDA10048_CLK_4000,  TDA10048_IF_36130 },
+	{ TDA10048_CLK_16000, TDA10048_IF_3300 },
+	{ TDA10048_CLK_16000, TDA10048_IF_3500 },
+	{ TDA10048_CLK_16000, TDA10048_IF_3800 },
+	{ TDA10048_CLK_16000, TDA10048_IF_4000 },
+	{ TDA10048_CLK_16000, TDA10048_IF_4300 },
+	{ TDA10048_CLK_16000, TDA10048_IF_4500 },
+	{ TDA10048_CLK_16000, TDA10048_IF_5000 },
+	{ TDA10048_CLK_16000, TDA10048_IF_36130 },
 };
 
 static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
@@ -460,9 +461,6 @@
 
 			state->freq_if_hz = pll_tab[i].if_freq_khz * 1000;
 			state->xtal_hz = pll_tab[i].clk_freq_khz * 1000;
-			state->pll_mfactor = pll_tab[i].m;
-			state->pll_nfactor = pll_tab[i].n;
-			state->pll_pfactor = pll_tab[i].p;
 			break;
 		}
 	}
@@ -781,6 +779,10 @@
 
 	dprintk(1, "%s()\n", __func__);
 
+	/* PLL */
+	init_tab[4].data = (u8)(state->pll_mfactor);
+	init_tab[5].data = (u8)(state->pll_nfactor) | 0x40;
+
 	/* Apply register defaults */
 	for (i = 0; i < ARRAY_SIZE(init_tab); i++)
 		tda10048_writereg(state, init_tab[i].reg, init_tab[i].data);
@@ -1123,7 +1125,7 @@
 	/* setup the state and clone the config */
 	memcpy(&state->config, config, sizeof(*config));
 	state->i2c = i2c;
-	state->fwloaded = 0;
+	state->fwloaded = config->no_firmware;
 	state->bandwidth = BANDWIDTH_8_MHZ;
 
 	/* check if the demod is present */
@@ -1135,6 +1137,17 @@
 		sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 
+	/* set pll */
+	if (config->set_pll) {
+		state->pll_mfactor = config->pll_m;
+		state->pll_nfactor = config->pll_n;
+		state->pll_pfactor = config->pll_p;
+	} else {
+		state->pll_mfactor = 10;
+		state->pll_nfactor = 3;
+		state->pll_pfactor = 0;
+	}
+
 	/* Establish any defaults the the user didn't pass */
 	tda10048_establish_defaults(&state->frontend);
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/tda10048.h linux-libre-3.2-gnu/drivers/media/dvb/frontends/tda10048.h
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/tda10048.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/tda10048.h	2012-01-04 18:55:44.000000000 -0500
@@ -51,6 +51,7 @@
 #define TDA10048_IF_4300  4300
 #define TDA10048_IF_4500  4500
 #define TDA10048_IF_4750  4750
+#define TDA10048_IF_5000  5000
 #define TDA10048_IF_36130 36130
 	u16 dtv6_if_freq_khz;
 	u16 dtv7_if_freq_khz;
@@ -62,6 +63,13 @@
 
 	/* Disable I2C gate access */
 	u8 disable_gate_access;
+
+	bool no_firmware;
+
+	bool set_pll;
+	u8 pll_m;
+	u8 pll_p;
+	u8 pll_n;
 };
 
 #if defined(CONFIG_DVB_TDA10048) || \
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/tda10071.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/tda10071.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/tda10071.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/tda10071.c	2012-03-19 21:38:13.000000000 -0400
@@ -0,0 +1,1269 @@
+/*
+ * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver
+ *
+ * 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 "tda10071_priv.h"
+
+int tda10071_debug;
+module_param_named(debug, tda10071_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+static struct dvb_frontend_ops tda10071_ops;
+
+/* write multiple registers */
+static int tda10071_wr_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
+	int len)
+{
+	int ret;
+	u8 buf[len+1];
+	struct i2c_msg msg[1] = {
+		{
+			.addr = priv->cfg.i2c_address,
+			.flags = 0,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	buf[0] = reg;
+	memcpy(&buf[1], val, len);
+
+	ret = i2c_transfer(priv->i2c, msg, 1);
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* read multiple registers */
+static int tda10071_rd_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
+	int len)
+{
+	int ret;
+	u8 buf[len];
+	struct i2c_msg msg[2] = {
+		{
+			.addr = priv->cfg.i2c_address,
+			.flags = 0,
+			.len = 1,
+			.buf = &reg,
+		}, {
+			.addr = priv->cfg.i2c_address,
+			.flags = I2C_M_RD,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	ret = i2c_transfer(priv->i2c, msg, 2);
+	if (ret == 2) {
+		memcpy(val, buf, len);
+		ret = 0;
+	} else {
+		warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* write single register */
+static int tda10071_wr_reg(struct tda10071_priv *priv, u8 reg, u8 val)
+{
+	return tda10071_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register */
+static int tda10071_rd_reg(struct tda10071_priv *priv, u8 reg, u8 *val)
+{
+	return tda10071_rd_regs(priv, reg, val, 1);
+}
+
+/* write single register with mask */
+int tda10071_wr_reg_mask(struct tda10071_priv *priv, u8 reg, u8 val, u8 mask)
+{
+	int ret;
+	u8 tmp;
+
+	/* no need for read if whole reg is written */
+	if (mask != 0xff) {
+		ret = tda10071_rd_regs(priv, reg, &tmp, 1);
+		if (ret)
+			return ret;
+
+		val &= mask;
+		tmp &= ~mask;
+		val |= tmp;
+	}
+
+	return tda10071_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register with mask */
+int tda10071_rd_reg_mask(struct tda10071_priv *priv, u8 reg, u8 *val, u8 mask)
+{
+	int ret, i;
+	u8 tmp;
+
+	ret = tda10071_rd_regs(priv, reg, &tmp, 1);
+	if (ret)
+		return ret;
+
+	tmp &= mask;
+
+	/* find position of the first bit */
+	for (i = 0; i < 8; i++) {
+		if ((mask >> i) & 0x01)
+			break;
+	}
+	*val = tmp >> i;
+
+	return 0;
+}
+
+/* execute firmware command */
+static int tda10071_cmd_execute(struct tda10071_priv *priv,
+	struct tda10071_cmd *cmd)
+{
+	int ret, i;
+	u8 tmp;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	/* write cmd and args for firmware */
+	ret = tda10071_wr_regs(priv, 0x00, cmd->args, cmd->len);
+	if (ret)
+		goto error;
+
+	/* start cmd execution */
+	ret = tda10071_wr_reg(priv, 0x1f, 1);
+	if (ret)
+		goto error;
+
+	/* wait cmd execution terminate */
+	for (i = 1000, tmp = 1; i && tmp; i--) {
+		ret = tda10071_rd_reg(priv, 0x1f, &tmp);
+		if (ret)
+			goto error;
+
+		usleep_range(200, 5000);
+	}
+
+	dbg("%s: loop=%d", __func__, i);
+
+	if (i == 0) {
+		ret = -ETIMEDOUT;
+		goto error;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_set_tone(struct dvb_frontend *fe,
+	fe_sec_tone_mode_t fe_sec_tone_mode)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret;
+	u8 tone;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	dbg("%s: tone_mode=%d", __func__, fe_sec_tone_mode);
+
+	switch (fe_sec_tone_mode) {
+	case SEC_TONE_ON:
+		tone = 1;
+		break;
+	case SEC_TONE_OFF:
+		tone = 0;
+		break;
+	default:
+		dbg("%s: invalid fe_sec_tone_mode", __func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	cmd.args[0x00] = CMD_LNB_PCB_CONFIG;
+	cmd.args[0x01] = 0;
+	cmd.args[0x02] = 0x00;
+	cmd.args[0x03] = 0x00;
+	cmd.args[0x04] = tone;
+	cmd.len = 0x05;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_set_voltage(struct dvb_frontend *fe,
+	fe_sec_voltage_t fe_sec_voltage)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret;
+	u8 voltage;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	dbg("%s: voltage=%d", __func__, fe_sec_voltage);
+
+	switch (fe_sec_voltage) {
+	case SEC_VOLTAGE_13:
+		voltage = 0;
+		break;
+	case SEC_VOLTAGE_18:
+		voltage = 1;
+		break;
+	case SEC_VOLTAGE_OFF:
+		voltage = 0;
+		break;
+	default:
+		dbg("%s: invalid fe_sec_voltage", __func__);
+		ret = -EINVAL;
+		goto error;
+	};
+
+	cmd.args[0x00] = CMD_LNB_SET_DC_LEVEL;
+	cmd.args[0x01] = 0;
+	cmd.args[0x02] = voltage;
+	cmd.len = 0x03;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe,
+	struct dvb_diseqc_master_cmd *diseqc_cmd)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i;
+	u8 tmp;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	dbg("%s: msg_len=%d", __func__, diseqc_cmd->msg_len);
+
+	if (diseqc_cmd->msg_len < 3 || diseqc_cmd->msg_len > 16) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* wait LNB TX */
+	for (i = 500, tmp = 0; i && !tmp; i--) {
+		ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x01);
+		if (ret)
+			goto error;
+
+		usleep_range(10000, 20000);
+	}
+
+	dbg("%s: loop=%d", __func__, i);
+
+	if (i == 0) {
+		ret = -ETIMEDOUT;
+		goto error;
+	}
+
+	ret = tda10071_wr_reg_mask(priv, 0x47, 0x00, 0x01);
+	if (ret)
+		goto error;
+
+	cmd.args[0x00] = CMD_LNB_SEND_DISEQC;
+	cmd.args[0x01] = 0;
+	cmd.args[0x02] = 0;
+	cmd.args[0x03] = 0;
+	cmd.args[0x04] = 2;
+	cmd.args[0x05] = 0;
+	cmd.args[0x06] = diseqc_cmd->msg_len;
+	memcpy(&cmd.args[0x07], diseqc_cmd->msg, diseqc_cmd->msg_len);
+	cmd.len = 0x07 + diseqc_cmd->msg_len;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
+	struct dvb_diseqc_slave_reply *reply)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i;
+	u8 tmp;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	dbg("%s:", __func__);
+
+	/* wait LNB RX */
+	for (i = 500, tmp = 0; i && !tmp; i--) {
+		ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x02);
+		if (ret)
+			goto error;
+
+		usleep_range(10000, 20000);
+	}
+
+	dbg("%s: loop=%d", __func__, i);
+
+	if (i == 0) {
+		ret = -ETIMEDOUT;
+		goto error;
+	}
+
+	/* reply len */
+	ret = tda10071_rd_reg(priv, 0x46, &tmp);
+	if (ret)
+		goto error;
+
+	reply->msg_len = tmp & 0x1f; /* [4:0] */;
+	if (reply->msg_len > sizeof(reply->msg))
+		reply->msg_len = sizeof(reply->msg); /* truncate API max */
+
+	/* read reply */
+	cmd.args[0x00] = CMD_LNB_UPDATE_REPLY;
+	cmd.args[0x01] = 0;
+	cmd.len = 0x02;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	ret = tda10071_rd_regs(priv, cmd.len, reply->msg, reply->msg_len);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
+	fe_sec_mini_cmd_t fe_sec_mini_cmd)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i;
+	u8 tmp, burst;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	dbg("%s: fe_sec_mini_cmd=%d", __func__, fe_sec_mini_cmd);
+
+	switch (fe_sec_mini_cmd) {
+	case SEC_MINI_A:
+		burst = 0;
+		break;
+	case SEC_MINI_B:
+		burst = 1;
+		break;
+	default:
+		dbg("%s: invalid fe_sec_mini_cmd", __func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* wait LNB TX */
+	for (i = 500, tmp = 0; i && !tmp; i--) {
+		ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x01);
+		if (ret)
+			goto error;
+
+		usleep_range(10000, 20000);
+	}
+
+	dbg("%s: loop=%d", __func__, i);
+
+	if (i == 0) {
+		ret = -ETIMEDOUT;
+		goto error;
+	}
+
+	ret = tda10071_wr_reg_mask(priv, 0x47, 0x00, 0x01);
+	if (ret)
+		goto error;
+
+	cmd.args[0x00] = CMD_LNB_SEND_TONEBURST;
+	cmd.args[0x01] = 0;
+	cmd.args[0x02] = burst;
+	cmd.len = 0x03;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 tmp;
+
+	*status = 0;
+
+	if (!priv->warm) {
+		ret = 0;
+		goto error;
+	}
+
+	ret = tda10071_rd_reg(priv, 0x39, &tmp);
+	if (ret)
+		goto error;
+
+	if (tmp & 0x01) /* tuner PLL */
+		*status |= FE_HAS_SIGNAL;
+	if (tmp & 0x02) /* demod PLL */
+		*status |= FE_HAS_CARRIER;
+	if (tmp & 0x04) /* viterbi or LDPC*/
+		*status |= FE_HAS_VITERBI;
+	if (tmp & 0x08) /* RS or BCH */
+		*status |= FE_HAS_SYNC | FE_HAS_LOCK;
+
+	priv->fe_status = *status;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+
+	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+		*snr = 0;
+		ret = 0;
+		goto error;
+	}
+
+	ret = tda10071_rd_regs(priv, 0x3a, buf, 2);
+	if (ret)
+		goto error;
+
+	/* Es/No dBx10 */
+	*snr = buf[0] << 8 | buf[1];
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret;
+	u8 tmp;
+
+	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+		*strength = 0;
+		ret = 0;
+		goto error;
+	}
+
+	cmd.args[0x00] = CMD_GET_AGCACC;
+	cmd.args[0x01] = 0;
+	cmd.len = 0x02;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	/* input power estimate dBm */
+	ret = tda10071_rd_reg(priv, 0x50, &tmp);
+	if (ret)
+		goto error;
+
+	if (tmp < 181)
+		tmp = 181; /* -75 dBm */
+	else if (tmp > 236)
+		tmp = 236; /* -20 dBm */
+
+	/* scale value to 0x0000-0xffff */
+	*strength = (tmp-181) * 0xffff / (236-181);
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i, len;
+	u8 tmp, reg, buf[8];
+
+	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+		*ber = priv->ber = 0;
+		ret = 0;
+		goto error;
+	}
+
+	switch (priv->delivery_system) {
+	case SYS_DVBS:
+		reg = 0x4c;
+		len = 8;
+		i = 1;
+		break;
+	case SYS_DVBS2:
+		reg = 0x4d;
+		len = 4;
+		i = 0;
+		break;
+	default:
+		*ber = priv->ber = 0;
+		return 0;
+	}
+
+	ret = tda10071_rd_reg(priv, reg, &tmp);
+	if (ret)
+		goto error;
+
+	if (priv->meas_count[i] == tmp) {
+		dbg("%s: meas not ready=%02x", __func__, tmp);
+		*ber = priv->ber;
+		return 0;
+	} else {
+		priv->meas_count[i] = tmp;
+	}
+
+	cmd.args[0x00] = CMD_BER_UPDATE_COUNTERS;
+	cmd.args[0x01] = 0;
+	cmd.args[0x02] = i;
+	cmd.len = 0x03;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	ret = tda10071_rd_regs(priv, cmd.len, buf, len);
+	if (ret)
+		goto error;
+
+	if (priv->delivery_system == SYS_DVBS) {
+		*ber = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+		priv->ucb += (buf[4] << 8) | buf[5];
+	} else {
+		*ber = (buf[0] << 8) | buf[1];
+	}
+	priv->ber = *ber;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	int ret = 0;
+
+	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+		*ucblocks = 0;
+		goto error;
+	}
+
+	/* UCB is updated when BER is read. Assume BER is read anyway. */
+
+	*ucblocks = priv->ucb;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_set_frontend(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *params)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i;
+	u8 mode, rolloff, pilot, inversion, div;
+
+	dbg("%s: delivery_system=%d modulation=%d frequency=%d " \
+		"symbol_rate=%d inversion=%d pilot=%d rolloff=%d", __func__,
+		c->delivery_system, c->modulation, c->frequency,
+		c->symbol_rate, c->inversion, c->pilot, c->rolloff);
+
+	priv->delivery_system = SYS_UNDEFINED;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	switch (c->inversion) {
+	case INVERSION_OFF:
+		inversion = 1;
+		break;
+	case INVERSION_ON:
+		inversion = 0;
+		break;
+	case INVERSION_AUTO:
+		/* 2 = auto; try first on then off
+		 * 3 = auto; try first off then on */
+		inversion = 3;
+		break;
+	default:
+		dbg("%s: invalid inversion", __func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	switch (c->delivery_system) {
+	case SYS_DVBS:
+		rolloff = 0;
+		pilot = 2;
+		break;
+	case SYS_DVBS2:
+		switch (c->rolloff) {
+		case ROLLOFF_20:
+			rolloff = 2;
+			break;
+		case ROLLOFF_25:
+			rolloff = 1;
+			break;
+		case ROLLOFF_35:
+			rolloff = 0;
+			break;
+		case ROLLOFF_AUTO:
+		default:
+			dbg("%s: invalid rolloff", __func__);
+			ret = -EINVAL;
+			goto error;
+		}
+
+		switch (c->pilot) {
+		case PILOT_OFF:
+			pilot = 0;
+			break;
+		case PILOT_ON:
+			pilot = 1;
+			break;
+		case PILOT_AUTO:
+			pilot = 2;
+			break;
+		default:
+			dbg("%s: invalid pilot", __func__);
+			ret = -EINVAL;
+			goto error;
+		}
+		break;
+	default:
+		dbg("%s: invalid delivery_system", __func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	for (i = 0, mode = 0xff; i < ARRAY_SIZE(TDA10071_MODCOD); i++) {
+		if (c->delivery_system == TDA10071_MODCOD[i].delivery_system &&
+			c->modulation == TDA10071_MODCOD[i].modulation &&
+			c->fec_inner == TDA10071_MODCOD[i].fec) {
+			mode = TDA10071_MODCOD[i].val;
+			dbg("%s: mode found=%02x", __func__, mode);
+			break;
+		}
+	}
+
+	if (mode == 0xff) {
+		dbg("%s: invalid parameter combination", __func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	if (c->symbol_rate <= 5000000)
+		div = 14;
+	else
+		div = 4;
+
+	ret = tda10071_wr_reg(priv, 0x81, div);
+	if (ret)
+		goto error;
+
+	ret = tda10071_wr_reg(priv, 0xe3, div);
+	if (ret)
+		goto error;
+
+	cmd.args[0x00] = CMD_CHANGE_CHANNEL;
+	cmd.args[0x01] = 0;
+	cmd.args[0x02] = mode;
+	cmd.args[0x03] = (c->frequency >> 16) & 0xff;
+	cmd.args[0x04] = (c->frequency >>  8) & 0xff;
+	cmd.args[0x05] = (c->frequency >>  0) & 0xff;
+	cmd.args[0x06] = ((c->symbol_rate / 1000) >> 8) & 0xff;
+	cmd.args[0x07] = ((c->symbol_rate / 1000) >> 0) & 0xff;
+	cmd.args[0x08] = (tda10071_ops.info.frequency_tolerance >> 8) & 0xff;
+	cmd.args[0x09] = (tda10071_ops.info.frequency_tolerance >> 0) & 0xff;
+	cmd.args[0x0a] = rolloff;
+	cmd.args[0x0b] = inversion;
+	cmd.args[0x0c] = pilot;
+	cmd.args[0x0d] = 0x00;
+	cmd.args[0x0e] = 0x00;
+	cmd.len = 0x0f;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	priv->delivery_system = c->delivery_system;
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_get_frontend(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i;
+	u8 buf[5], tmp;
+
+	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	ret = tda10071_rd_regs(priv, 0x30, buf, 5);
+	if (ret)
+		goto error;
+
+	tmp = buf[0] & 0x3f;
+	for (i = 0; i < ARRAY_SIZE(TDA10071_MODCOD); i++) {
+		if (tmp == TDA10071_MODCOD[i].val) {
+			c->modulation = TDA10071_MODCOD[i].modulation;
+			c->fec_inner = TDA10071_MODCOD[i].fec;
+			c->delivery_system = TDA10071_MODCOD[i].delivery_system;
+		}
+	}
+
+	switch ((buf[1] >> 0) & 0x01) {
+	case 0:
+		c->inversion = INVERSION_OFF;
+		break;
+	case 1:
+		c->inversion = INVERSION_ON;
+		break;
+	}
+
+	switch ((buf[1] >> 7) & 0x01) {
+	case 0:
+		c->pilot = PILOT_OFF;
+		break;
+	case 1:
+		c->pilot = PILOT_ON;
+		break;
+	}
+
+	c->frequency = (buf[2] << 16) | (buf[3] << 8) | (buf[4] << 0);
+
+	ret = tda10071_rd_regs(priv, 0x52, buf, 3);
+	if (ret)
+		goto error;
+
+	c->symbol_rate = (buf[0] << 16) | (buf[1] << 8) | (buf[2] << 0);
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_init(struct dvb_frontend *fe)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i, len, remaining, fw_size;
+	const struct firmware *fw;
+	u8 *fw_file = "/*(DEBLOBBED)*/";
+	u8 tmp, buf[4];
+	struct tda10071_reg_val_mask tab[] = {
+		{ 0xcd, 0x00, 0x07 },
+		{ 0x80, 0x00, 0x02 },
+		{ 0xcd, 0x00, 0xc0 },
+		{ 0xce, 0x00, 0x1b },
+		{ 0x9d, 0x00, 0x01 },
+		{ 0x9d, 0x00, 0x02 },
+		{ 0x9e, 0x00, 0x01 },
+		{ 0x87, 0x00, 0x80 },
+		{ 0xce, 0x00, 0x08 },
+		{ 0xce, 0x00, 0x10 },
+	};
+	struct tda10071_reg_val_mask tab2[] = {
+		{ 0xf1, 0x70, 0xff },
+		{ 0x88, priv->cfg.pll_multiplier, 0x3f },
+		{ 0x89, 0x00, 0x10 },
+		{ 0x89, 0x10, 0x10 },
+		{ 0xc0, 0x01, 0x01 },
+		{ 0xc0, 0x00, 0x01 },
+		{ 0xe0, 0xff, 0xff },
+		{ 0xe0, 0x00, 0xff },
+		{ 0x96, 0x1e, 0x7e },
+		{ 0x8b, 0x08, 0x08 },
+		{ 0x8b, 0x00, 0x08 },
+		{ 0x8f, 0x1a, 0x7e },
+		{ 0x8c, 0x68, 0xff },
+		{ 0x8d, 0x08, 0xff },
+		{ 0x8e, 0x4c, 0xff },
+		{ 0x8f, 0x01, 0x01 },
+		{ 0x8b, 0x04, 0x04 },
+		{ 0x8b, 0x00, 0x04 },
+		{ 0x87, 0x05, 0x07 },
+		{ 0x80, 0x00, 0x20 },
+		{ 0xc8, 0x01, 0xff },
+		{ 0xb4, 0x47, 0xff },
+		{ 0xb5, 0x9c, 0xff },
+		{ 0xb6, 0x7d, 0xff },
+		{ 0xba, 0x00, 0x03 },
+		{ 0xb7, 0x47, 0xff },
+		{ 0xb8, 0x9c, 0xff },
+		{ 0xb9, 0x7d, 0xff },
+		{ 0xba, 0x00, 0x0c },
+		{ 0xc8, 0x00, 0xff },
+		{ 0xcd, 0x00, 0x04 },
+		{ 0xcd, 0x00, 0x20 },
+		{ 0xe8, 0x02, 0xff },
+		{ 0xcf, 0x20, 0xff },
+		{ 0x9b, 0xd7, 0xff },
+		{ 0x9a, 0x01, 0x03 },
+		{ 0xa8, 0x05, 0x0f },
+		{ 0xa8, 0x65, 0xf0 },
+		{ 0xa6, 0xa0, 0xf0 },
+		{ 0x9d, 0x50, 0xfc },
+		{ 0x9e, 0x20, 0xe0 },
+		{ 0xa3, 0x1c, 0x7c },
+		{ 0xd5, 0x03, 0x03 },
+	};
+
+	/* firmware status */
+	ret = tda10071_rd_reg(priv, 0x51, &tmp);
+	if (ret)
+		goto error;
+
+	if (!tmp) {
+		/* warm state - wake up device from sleep */
+		priv->warm = 1;
+
+		for (i = 0; i < ARRAY_SIZE(tab); i++) {
+			ret = tda10071_wr_reg_mask(priv, tab[i].reg,
+				tab[i].val, tab[i].mask);
+			if (ret)
+				goto error;
+		}
+
+		cmd.args[0x00] = CMD_SET_SLEEP_MODE;
+		cmd.args[0x01] = 0;
+		cmd.args[0x02] = 0;
+		cmd.len = 0x03;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+	} else {
+		/* cold state - try to download firmware */
+		priv->warm = 0;
+
+		/* request the firmware, this will block and timeout */
+		ret = reject_firmware(&fw, fw_file, priv->i2c->dev.parent);
+		if (ret) {
+			err("did not find the firmware file. (%s) "
+				"Please see linux/Documentation/dvb/ for more" \
+				" details on firmware-problems. (%d)",
+				fw_file, ret);
+			goto error;
+		}
+
+		/* init */
+		for (i = 0; i < ARRAY_SIZE(tab2); i++) {
+			ret = tda10071_wr_reg_mask(priv, tab2[i].reg,
+				tab2[i].val, tab2[i].mask);
+			if (ret)
+				goto error_release_firmware;
+		}
+
+		/*  download firmware */
+		ret = tda10071_wr_reg(priv, 0xe0, 0x7f);
+		if (ret)
+			goto error_release_firmware;
+
+		ret = tda10071_wr_reg(priv, 0xf7, 0x81);
+		if (ret)
+			goto error_release_firmware;
+
+		ret = tda10071_wr_reg(priv, 0xf8, 0x00);
+		if (ret)
+			goto error_release_firmware;
+
+		ret = tda10071_wr_reg(priv, 0xf9, 0x00);
+		if (ret)
+			goto error_release_firmware;
+
+		info("found a '%s' in cold state, will try to load a firmware",
+			tda10071_ops.info.name);
+
+		info("downloading firmware from file '%s'", fw_file);
+
+		/* do not download last byte */
+		fw_size = fw->size - 1;
+
+		for (remaining = fw_size; remaining > 0;
+			remaining -= (priv->cfg.i2c_wr_max - 1)) {
+			len = remaining;
+			if (len > (priv->cfg.i2c_wr_max - 1))
+				len = (priv->cfg.i2c_wr_max - 1);
+
+			ret = tda10071_wr_regs(priv, 0xfa,
+				(u8 *) &fw->data[fw_size - remaining], len);
+			if (ret) {
+				err("firmware download failed=%d", ret);
+				if (ret)
+					goto error_release_firmware;
+			}
+		}
+		release_firmware(fw);
+
+		ret = tda10071_wr_reg(priv, 0xf7, 0x0c);
+		if (ret)
+			goto error;
+
+		ret = tda10071_wr_reg(priv, 0xe0, 0x00);
+		if (ret)
+			goto error;
+
+		/* wait firmware start */
+		msleep(250);
+
+		/* firmware status */
+		ret = tda10071_rd_reg(priv, 0x51, &tmp);
+		if (ret)
+			goto error;
+
+		if (tmp) {
+			info("firmware did not run");
+			ret = -EFAULT;
+			goto error;
+		} else {
+			priv->warm = 1;
+		}
+
+		cmd.args[0x00] = CMD_GET_FW_VERSION;
+		cmd.len = 0x01;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+
+		ret = tda10071_rd_regs(priv, cmd.len, buf, 4);
+		if (ret)
+			goto error;
+
+		info("firmware version %d.%d.%d.%d",
+			buf[0], buf[1], buf[2], buf[3]);
+		info("found a '%s' in warm state.", tda10071_ops.info.name);
+
+		ret = tda10071_rd_regs(priv, 0x81, buf, 2);
+		if (ret)
+			goto error;
+
+		cmd.args[0x00] = CMD_DEMOD_INIT;
+		cmd.args[0x01] = ((priv->cfg.xtal / 1000) >> 8) & 0xff;
+		cmd.args[0x02] = ((priv->cfg.xtal / 1000) >> 0) & 0xff;
+		cmd.args[0x03] = buf[0];
+		cmd.args[0x04] = buf[1];
+		cmd.args[0x05] = priv->cfg.pll_multiplier;
+		cmd.args[0x06] = priv->cfg.spec_inv;
+		cmd.args[0x07] = 0x00;
+		cmd.len = 0x08;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+
+		cmd.args[0x00] = CMD_TUNER_INIT;
+		cmd.args[0x01] = 0x00;
+		cmd.args[0x02] = 0x00;
+		cmd.args[0x03] = 0x00;
+		cmd.args[0x04] = 0x00;
+		cmd.args[0x05] = 0x14;
+		cmd.args[0x06] = 0x00;
+		cmd.args[0x07] = 0x03;
+		cmd.args[0x08] = 0x02;
+		cmd.args[0x09] = 0x02;
+		cmd.args[0x0a] = 0x00;
+		cmd.args[0x0b] = 0x00;
+		cmd.args[0x0c] = 0x00;
+		cmd.args[0x0d] = 0x00;
+		cmd.args[0x0e] = 0x00;
+		cmd.len = 0x0f;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+
+		cmd.args[0x00] = CMD_MPEG_CONFIG;
+		cmd.args[0x01] = 0;
+		cmd.args[0x02] = priv->cfg.ts_mode;
+		cmd.args[0x03] = 0x00;
+		cmd.args[0x04] = 0x04;
+		cmd.args[0x05] = 0x00;
+		cmd.len = 0x06;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+
+		ret = tda10071_wr_reg_mask(priv, 0xf0, 0x01, 0x01);
+		if (ret)
+			goto error;
+
+		cmd.args[0x00] = CMD_LNB_CONFIG;
+		cmd.args[0x01] = 0;
+		cmd.args[0x02] = 150;
+		cmd.args[0x03] = 3;
+		cmd.args[0x04] = 22;
+		cmd.args[0x05] = 1;
+		cmd.args[0x06] = 1;
+		cmd.args[0x07] = 30;
+		cmd.args[0x08] = 30;
+		cmd.args[0x09] = 30;
+		cmd.args[0x0a] = 30;
+		cmd.len = 0x0b;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+
+		cmd.args[0x00] = CMD_BER_CONTROL;
+		cmd.args[0x01] = 0;
+		cmd.args[0x02] = 14;
+		cmd.args[0x03] = 14;
+		cmd.len = 0x04;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+	}
+
+	return ret;
+error_release_firmware:
+	release_firmware(fw);
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_sleep(struct dvb_frontend *fe)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i;
+	struct tda10071_reg_val_mask tab[] = {
+		{ 0xcd, 0x07, 0x07 },
+		{ 0x80, 0x02, 0x02 },
+		{ 0xcd, 0xc0, 0xc0 },
+		{ 0xce, 0x1b, 0x1b },
+		{ 0x9d, 0x01, 0x01 },
+		{ 0x9d, 0x02, 0x02 },
+		{ 0x9e, 0x01, 0x01 },
+		{ 0x87, 0x80, 0x80 },
+		{ 0xce, 0x08, 0x08 },
+		{ 0xce, 0x10, 0x10 },
+	};
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	cmd.args[0x00] = CMD_SET_SLEEP_MODE;
+	cmd.args[0x01] = 0;
+	cmd.args[0x02] = 1;
+	cmd.len = 0x03;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	for (i = 0; i < ARRAY_SIZE(tab); i++) {
+		ret = tda10071_wr_reg_mask(priv, tab[i].reg, tab[i].val,
+			tab[i].mask);
+		if (ret)
+			goto error;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	return ret;
+}
+
+static int tda10071_get_tune_settings(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s)
+{
+	s->min_delay_ms = 8000;
+	s->step_size = 0;
+	s->max_drift = 0;
+
+	return 0;
+}
+
+static void tda10071_release(struct dvb_frontend *fe)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	kfree(priv);
+}
+
+struct dvb_frontend *tda10071_attach(const struct tda10071_config *config,
+	struct i2c_adapter *i2c)
+{
+	int ret;
+	struct tda10071_priv *priv = NULL;
+	u8 tmp;
+
+	/* allocate memory for the internal priv */
+	priv = kzalloc(sizeof(struct tda10071_priv), GFP_KERNEL);
+	if (priv == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	/* setup the priv */
+	priv->i2c = i2c;
+	memcpy(&priv->cfg, config, sizeof(struct tda10071_config));
+
+	/* chip ID */
+	ret = tda10071_rd_reg(priv, 0xff, &tmp);
+	if (ret || tmp != 0x0f)
+		goto error;
+
+	/* chip type */
+	ret = tda10071_rd_reg(priv, 0xdd, &tmp);
+	if (ret || tmp != 0x00)
+		goto error;
+
+	/* chip version */
+	ret = tda10071_rd_reg(priv, 0xfe, &tmp);
+	if (ret || tmp != 0x01)
+		goto error;
+
+	/* create dvb_frontend */
+	memcpy(&priv->fe.ops, &tda10071_ops, sizeof(struct dvb_frontend_ops));
+	priv->fe.demodulator_priv = priv;
+
+	return &priv->fe;
+error:
+	dbg("%s: failed=%d", __func__, ret);
+	kfree(priv);
+	return NULL;
+}
+EXPORT_SYMBOL(tda10071_attach);
+
+static struct dvb_frontend_ops tda10071_ops = {
+	.info = {
+		.name = "NXP TDA10071",
+		.type = FE_QPSK,
+		.frequency_min = 950000,
+		.frequency_max = 2150000,
+		.frequency_tolerance = 5000,
+		.symbol_rate_min = 1000000,
+		.symbol_rate_max = 45000000,
+		.caps = FE_CAN_INVERSION_AUTO |
+			FE_CAN_FEC_1_2 |
+			FE_CAN_FEC_2_3 |
+			FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_4_5 |
+			FE_CAN_FEC_5_6 |
+			FE_CAN_FEC_6_7 |
+			FE_CAN_FEC_7_8 |
+			FE_CAN_FEC_8_9 |
+			FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK |
+			FE_CAN_RECOVER |
+			FE_CAN_2G_MODULATION
+	},
+
+	.release = tda10071_release,
+
+	.get_tune_settings = tda10071_get_tune_settings,
+
+	.init = tda10071_init,
+	.sleep = tda10071_sleep,
+
+	.set_frontend = tda10071_set_frontend,
+	.get_frontend = tda10071_get_frontend,
+
+	.read_status = tda10071_read_status,
+	.read_snr = tda10071_read_snr,
+	.read_signal_strength = tda10071_read_signal_strength,
+	.read_ber = tda10071_read_ber,
+	.read_ucblocks = tda10071_read_ucblocks,
+
+	.diseqc_send_master_cmd = tda10071_diseqc_send_master_cmd,
+	.diseqc_recv_slave_reply = tda10071_diseqc_recv_slave_reply,
+	.diseqc_send_burst = tda10071_diseqc_send_burst,
+
+	.set_tone = tda10071_set_tone,
+	.set_voltage = tda10071_set_voltage,
+};
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("NXP TDA10071 DVB-S/S2 demodulator driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/tda10071.h linux-libre-3.2-gnu/drivers/media/dvb/frontends/tda10071.h
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/tda10071.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/tda10071.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,81 @@
+/*
+ * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver
+ *
+ * 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.
+ */
+
+#ifndef TDA10071_H
+#define TDA10071_H
+
+#include <linux/dvb/frontend.h>
+
+struct tda10071_config {
+	/* Demodulator I2C address.
+	 * Default: none, must set
+	 * Values: 0x55,
+	 */
+	u8 i2c_address;
+
+	/* Max bytes I2C provider can write at once.
+	 * Note: Buffer is taken from the stack currently!
+	 * Default: none, must set
+	 * Values:
+	 */
+	u16 i2c_wr_max;
+
+	/* TS output mode.
+	 * Default: TDA10071_TS_SERIAL
+	 * Values:
+	 */
+#define TDA10071_TS_SERIAL        0
+#define TDA10071_TS_PARALLEL      1
+	u8 ts_mode;
+
+	/* Input spectrum inversion.
+	 * Default: 0
+	 * Values: 0, 1
+	 */
+	bool spec_inv;
+
+	/* Xtal frequency Hz
+	 * Default: none, must set
+	 * Values:
+	 */
+	u32 xtal;
+
+	/* PLL multiplier.
+	 * Default: none, must set
+	 * Values:
+	 */
+	u8 pll_multiplier;
+};
+
+
+#if defined(CONFIG_DVB_TDA10071) || \
+	(defined(CONFIG_DVB_TDA10071_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tda10071_attach(
+	const struct tda10071_config *config, struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *tda10071_attach(
+	const struct tda10071_config *config, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* TDA10071_H */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/tda10071_priv.h linux-libre-3.2-gnu/drivers/media/dvb/frontends/tda10071_priv.h
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/tda10071_priv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/tda10071_priv.h	2012-03-19 21:38:13.000000000 -0400
@@ -0,0 +1,122 @@
+/*
+ * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver
+ *
+ * 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.
+ */
+
+#ifndef TDA10071_PRIV
+#define TDA10071_PRIV
+
+#include "dvb_frontend.h"
+#include "tda10071.h"
+#include <linux/firmware.h>
+
+#define LOG_PREFIX "tda10071"
+
+#undef dbg
+#define dbg(f, arg...) \
+	if (tda10071_debug) \
+		printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
+#undef err
+#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
+#undef info
+#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
+#undef warn
+#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
+
+struct tda10071_priv {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend fe;
+	struct tda10071_config cfg;
+
+	u8 meas_count[2];
+	u32 ber;
+	u32 ucb;
+	fe_status_t fe_status;
+	fe_delivery_system_t delivery_system;
+	bool warm; /* FW running */
+};
+
+static struct tda10071_modcod {
+	fe_delivery_system_t delivery_system;
+	fe_modulation_t modulation;
+	fe_code_rate_t fec;
+	u8 val;
+} TDA10071_MODCOD[] = {
+	/* NBC-QPSK */
+	{ SYS_DVBS2, QPSK,  FEC_AUTO, 0x00 },
+	{ SYS_DVBS2, QPSK,  FEC_1_2,  0x04 },
+	{ SYS_DVBS2, QPSK,  FEC_3_5,  0x05 },
+	{ SYS_DVBS2, QPSK,  FEC_2_3,  0x06 },
+	{ SYS_DVBS2, QPSK,  FEC_3_4,  0x07 },
+	{ SYS_DVBS2, QPSK,  FEC_4_5,  0x08 },
+	{ SYS_DVBS2, QPSK,  FEC_5_6,  0x09 },
+	{ SYS_DVBS2, QPSK,  FEC_8_9,  0x0a },
+	{ SYS_DVBS2, QPSK,  FEC_9_10, 0x0b },
+	/* 8PSK */
+	{ SYS_DVBS2, PSK_8, FEC_3_5,  0x0c },
+	{ SYS_DVBS2, PSK_8, FEC_2_3,  0x0d },
+	{ SYS_DVBS2, PSK_8, FEC_3_4,  0x0e },
+	{ SYS_DVBS2, PSK_8, FEC_5_6,  0x0f },
+	{ SYS_DVBS2, PSK_8, FEC_8_9,  0x10 },
+	{ SYS_DVBS2, PSK_8, FEC_9_10, 0x11 },
+	/* QPSK */
+	{ SYS_DVBS,  QPSK,  FEC_AUTO, 0x2d },
+	{ SYS_DVBS,  QPSK,  FEC_1_2,  0x2e },
+	{ SYS_DVBS,  QPSK,  FEC_2_3,  0x2f },
+	{ SYS_DVBS,  QPSK,  FEC_3_4,  0x30 },
+	{ SYS_DVBS,  QPSK,  FEC_5_6,  0x31 },
+	{ SYS_DVBS,  QPSK,  FEC_7_8,  0x32 },
+};
+
+struct tda10071_reg_val_mask {
+	u8 reg;
+	u8 val;
+	u8 mask;
+};
+
+/* firmware filename */
+/*(DEBLOBBED)*/
+
+/* firmware commands */
+#define CMD_DEMOD_INIT          0x10
+#define CMD_CHANGE_CHANNEL      0x11
+#define CMD_MPEG_CONFIG         0x13
+#define CMD_TUNER_INIT          0x15
+#define CMD_GET_AGCACC          0x1a
+
+#define CMD_LNB_CONFIG          0x20
+#define CMD_LNB_SEND_DISEQC     0x21
+#define CMD_LNB_SET_DC_LEVEL    0x22
+#define CMD_LNB_PCB_CONFIG      0x23
+#define CMD_LNB_SEND_TONEBURST  0x24
+#define CMD_LNB_UPDATE_REPLY    0x25
+
+#define CMD_GET_FW_VERSION      0x35
+#define CMD_SET_SLEEP_MODE      0x36
+#define CMD_BER_CONTROL         0x3e
+#define CMD_BER_UPDATE_COUNTERS 0x3f
+
+/* firmare command struct */
+#define TDA10071_ARGLEN      0x1e
+struct tda10071_cmd {
+	u8 args[TDA10071_ARGLEN];
+	u8 len;
+};
+
+
+#endif /* TDA10071_PRIV */
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/frontends/tda18271c2dd.c linux-libre-3.2-gnu/drivers/media/dvb/frontends/tda18271c2dd.c
--- linux-libre-3.1-gnu/drivers/media/dvb/frontends/tda18271c2dd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/frontends/tda18271c2dd.c	2012-01-04 18:55:44.000000000 -0500
@@ -1195,7 +1195,7 @@
 }
 #endif
 
-static int get_frequency(struct dvb_frontend *fe, u32 *frequency)
+static int get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
 	struct tda_state *state = fe->tuner_priv;
 
@@ -1222,7 +1222,7 @@
 	.sleep             = sleep,
 	.set_params        = set_params,
 	.release           = release,
-	.get_frequency     = get_frequency,
+	.get_if_frequency  = get_if_frequency,
 	.get_bandwidth     = get_bandwidth,
 };
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/mantis/hopper_cards.c linux-libre-3.2-gnu/drivers/media/dvb/mantis/hopper_cards.c
--- linux-libre-3.1-gnu/drivers/media/dvb/mantis/hopper_cards.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/mantis/hopper_cards.c	2012-01-04 18:55:44.000000000 -0500
@@ -65,7 +65,7 @@
 
 static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
 {
-	u32 stat = 0, mask = 0, lstat = 0, mstat = 0;
+	u32 stat = 0, mask = 0, lstat = 0;
 	u32 rst_stat = 0, rst_mask = 0;
 
 	struct mantis_pci *mantis;
@@ -80,7 +80,7 @@
 
 	stat = mmread(MANTIS_INT_STAT);
 	mask = mmread(MANTIS_INT_MASK);
-	mstat = lstat = stat & ~MANTIS_INT_RISCSTAT;
+	lstat = stat & ~MANTIS_INT_RISCSTAT;
 	if (!(stat & mask))
 		return IRQ_NONE;
 
@@ -126,7 +126,7 @@
 	}
 	if (stat & MANTIS_INT_RISCI) {
 		dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
-		mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
+		mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
 		tasklet_schedule(&mantis->tasklet);
 	}
 	if (stat & MANTIS_INT_I2CDONE) {
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/mantis/Makefile linux-libre-3.2-gnu/drivers/media/dvb/mantis/Makefile
--- linux-libre-3.1-gnu/drivers/media/dvb/mantis/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/mantis/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -25,4 +25,4 @@
 obj-$(CONFIG_DVB_MANTIS)	+= mantis.o
 obj-$(CONFIG_DVB_HOPPER)	+= hopper.o
 
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/mantis/mantis_cards.c linux-libre-3.2-gnu/drivers/media/dvb/mantis/mantis_cards.c
--- linux-libre-3.1-gnu/drivers/media/dvb/mantis/mantis_cards.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/mantis/mantis_cards.c	2012-01-04 18:55:44.000000000 -0500
@@ -73,7 +73,7 @@
 
 static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
 {
-	u32 stat = 0, mask = 0, lstat = 0, mstat = 0;
+	u32 stat = 0, mask = 0, lstat = 0;
 	u32 rst_stat = 0, rst_mask = 0;
 
 	struct mantis_pci *mantis;
@@ -88,7 +88,7 @@
 
 	stat = mmread(MANTIS_INT_STAT);
 	mask = mmread(MANTIS_INT_MASK);
-	mstat = lstat = stat & ~MANTIS_INT_RISCSTAT;
+	lstat = stat & ~MANTIS_INT_RISCSTAT;
 	if (!(stat & mask))
 		return IRQ_NONE;
 
@@ -134,7 +134,7 @@
 	}
 	if (stat & MANTIS_INT_RISCI) {
 		dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
-		mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
+		mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
 		tasklet_schedule(&mantis->tasklet);
 	}
 	if (stat & MANTIS_INT_I2CDONE) {
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/mantis/mantis_common.h linux-libre-3.2-gnu/drivers/media/dvb/mantis/mantis_common.h
--- linux-libre-3.1-gnu/drivers/media/dvb/mantis/mantis_common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/mantis/mantis_common.h	2012-01-04 18:55:44.000000000 -0500
@@ -123,11 +123,8 @@
 	unsigned int		num;
 
 	/*	RISC Core		*/
-	u32			finished_block;
+	u32			busy_block;
 	u32			last_block;
-	u32			line_bytes;
-	u32			line_count;
-	u32			risc_pos;
 	u8			*buf_cpu;
 	dma_addr_t		buf_dma;
 	u32			*risc_cpu;
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/mantis/mantis_dma.c linux-libre-3.2-gnu/drivers/media/dvb/mantis/mantis_dma.c
--- linux-libre-3.1-gnu/drivers/media/dvb/mantis/mantis_dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/mantis/mantis_dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,13 +43,17 @@
 #define RISC_IRQ		(0x01 << 24)
 
 #define RISC_STATUS(status)	((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16))
-#define RISC_FLUSH()		(mantis->risc_pos = 0)
-#define RISC_INSTR(opcode)	(mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode))
+#define RISC_FLUSH(risc_pos)		(risc_pos = 0)
+#define RISC_INSTR(risc_pos, opcode)	(mantis->risc_cpu[risc_pos++] = cpu_to_le32(opcode))
 
 #define MANTIS_BUF_SIZE		(64 * 1024)
-#define MANTIS_BLOCK_BYTES	(MANTIS_BUF_SIZE >> 4)
-#define MANTIS_BLOCK_COUNT	(1 << 4)
-#define MANTIS_RISC_SIZE	PAGE_SIZE
+#define MANTIS_BLOCK_BYTES      (MANTIS_BUF_SIZE / 4)
+#define MANTIS_DMA_TR_BYTES     (2 * 1024) /* upper limit: 4095 bytes. */
+#define MANTIS_BLOCK_COUNT	(MANTIS_BUF_SIZE / MANTIS_BLOCK_BYTES)
+
+#define MANTIS_DMA_TR_UNITS     (MANTIS_BLOCK_BYTES / MANTIS_DMA_TR_BYTES)
+/* MANTIS_BUF_SIZE / MANTIS_DMA_TR_UNITS must not exceed MANTIS_RISC_SIZE (4k RISC cmd buffer) */
+#define MANTIS_RISC_SIZE	PAGE_SIZE /* RISC program must fit here. */
 
 int mantis_dma_exit(struct mantis_pci *mantis)
 {
@@ -124,27 +128,6 @@
 	return -ENOMEM;
 }
 
-static inline int mantis_calc_lines(struct mantis_pci *mantis)
-{
-	mantis->line_bytes = MANTIS_BLOCK_BYTES;
-	mantis->line_count = MANTIS_BLOCK_COUNT;
-
-	while (mantis->line_bytes > 4095) {
-		mantis->line_bytes >>= 1;
-		mantis->line_count <<= 1;
-	}
-
-	dprintk(MANTIS_DEBUG, 1, "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]",
-		MANTIS_BLOCK_BYTES, mantis->line_bytes, mantis->line_count);
-
-	if (mantis->line_count > 255) {
-		dprintk(MANTIS_ERROR, 1, "Buffer size error");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 int mantis_dma_init(struct mantis_pci *mantis)
 {
 	int err = 0;
@@ -158,12 +141,6 @@
 
 		goto err;
 	}
-	err = mantis_calc_lines(mantis);
-	if (err < 0) {
-		dprintk(MANTIS_ERROR, 1, "Mantis calc lines failed");
-
-		goto err;
-	}
 
 	return 0;
 err:
@@ -174,31 +151,32 @@
 static inline void mantis_risc_program(struct mantis_pci *mantis)
 {
 	u32 buf_pos = 0;
-	u32 line;
+	u32 line, step;
+	u32 risc_pos;
 
 	dprintk(MANTIS_DEBUG, 1, "Mantis create RISC program");
-	RISC_FLUSH();
+	RISC_FLUSH(risc_pos);
 
-	dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u",
-		mantis->line_count, mantis->line_bytes);
+	dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u, bytes per DMA tr %u",
+		MANTIS_BLOCK_COUNT, MANTIS_BLOCK_BYTES, MANTIS_DMA_TR_BYTES);
 
-	for (line = 0; line < mantis->line_count; line++) {
-		dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line);
-		if (!(buf_pos % MANTIS_BLOCK_BYTES)) {
-			RISC_INSTR(RISC_WRITE	|
-				   RISC_IRQ	|
-				   RISC_STATUS(((buf_pos / MANTIS_BLOCK_BYTES) +
-				   (MANTIS_BLOCK_COUNT - 1)) %
-				    MANTIS_BLOCK_COUNT) |
-				    mantis->line_bytes);
-		} else {
-			RISC_INSTR(RISC_WRITE	| mantis->line_bytes);
-		}
-		RISC_INSTR(mantis->buf_dma + buf_pos);
-		buf_pos += mantis->line_bytes;
+	for (line = 0; line < MANTIS_BLOCK_COUNT; line++) {
+		for (step = 0; step < MANTIS_DMA_TR_UNITS; step++) {
+			dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d], step=[%d]", line, step);
+			if (step == 0) {
+				RISC_INSTR(risc_pos, RISC_WRITE	|
+					   RISC_IRQ	|
+					   RISC_STATUS(line) |
+					   MANTIS_DMA_TR_BYTES);
+			} else {
+				RISC_INSTR(risc_pos, RISC_WRITE | MANTIS_DMA_TR_BYTES);
+			}
+			RISC_INSTR(risc_pos, mantis->buf_dma + buf_pos);
+			buf_pos += MANTIS_DMA_TR_BYTES;
+		  }
 	}
-	RISC_INSTR(RISC_JUMP);
-	RISC_INSTR(mantis->risc_dma);
+	RISC_INSTR(risc_pos, RISC_JUMP);
+	RISC_INSTR(risc_pos, mantis->risc_dma);
 }
 
 void mantis_dma_start(struct mantis_pci *mantis)
@@ -210,7 +188,7 @@
 	mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
 
 	mmwrite(0, MANTIS_DMA_CTL);
-	mantis->last_block = mantis->finished_block = 0;
+	mantis->last_block = mantis->busy_block = 0;
 
 	mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK);
 
@@ -245,9 +223,9 @@
 	struct mantis_pci *mantis = (struct mantis_pci *) data;
 	struct mantis_hwconfig *config = mantis->hwconfig;
 
-	while (mantis->last_block != mantis->finished_block) {
+	while (mantis->last_block != mantis->busy_block) {
 		dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]",
-			mantis->last_block, mantis->finished_block);
+			mantis->last_block, mantis->busy_block);
 
 		(config->ts_size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter)
 		(&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES);
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/mantis/mantis_vp1041.c linux-libre-3.2-gnu/drivers/media/dvb/mantis/mantis_vp1041.c
--- linux-libre-3.1-gnu/drivers/media/dvb/mantis/mantis_vp1041.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/mantis/mantis_vp1041.c	2012-01-04 18:55:44.000000000 -0500
@@ -51,7 +51,6 @@
 	{ STB0899_DISRX_ST0     	, 0x04 },
 	{ STB0899_DISRX_ST1     	, 0x00 },
 	{ STB0899_DISPARITY     	, 0x00 },
-	{ STB0899_DISFIFO       	, 0x00 },
 	{ STB0899_DISSTATUS		, 0x20 },
 	{ STB0899_DISF22        	, 0x99 },
 	{ STB0899_DISF22RX      	, 0xa8 },
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/ngene/Makefile linux-libre-3.2-gnu/drivers/media/dvb/ngene/Makefile
--- linux-libre-3.1-gnu/drivers/media/dvb/ngene/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/ngene/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -6,9 +6,9 @@
 
 obj-$(CONFIG_DVB_NGENE) += ngene.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/common/tuners/
 
 # For the staging CI driver cxd2099
-EXTRA_CFLAGS += -Idrivers/staging/cxd2099/
+ccflags-y += -Idrivers/staging/media/cxd2099/
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/pluto2/Makefile linux-libre-3.2-gnu/drivers/media/dvb/pluto2/Makefile
--- linux-libre-3.1-gnu/drivers/media/dvb/pluto2/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/pluto2/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
 obj-$(CONFIG_DVB_PLUTO2) += pluto2.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/pt1/Makefile linux-libre-3.2-gnu/drivers/media/dvb/pt1/Makefile
--- linux-libre-3.1-gnu/drivers/media/dvb/pt1/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/pt1/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,4 +2,4 @@
 
 obj-$(CONFIG_DVB_PT1) += earth-pt1.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core -Idrivers/media/dvb/frontends
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/siano/Makefile linux-libre-3.2-gnu/drivers/media/dvb/siano/Makefile
--- linux-libre-3.1-gnu/drivers/media/dvb/siano/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/siano/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -5,7 +5,7 @@
 obj-$(CONFIG_SMS_USB_DRV) += smsusb.o
 obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/dvb-core
 
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/siano/sms-cards.c linux-libre-3.2-gnu/drivers/media/dvb/siano/sms-cards.c
--- linux-libre-3.1-gnu/drivers/media/dvb/siano/sms-cards.c	2012-03-19 21:36:36.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/siano/sms-cards.c	2012-03-19 21:39:12.000000000 -0400
@@ -19,6 +19,7 @@
 
 #include "sms-cards.h"
 #include "smsir.h"
+#include <linux/module.h>
 
 static int sms_dbg;
 module_param_named(cards_dbg, sms_dbg, int, 0644);
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/siano/smsendian.c linux-libre-3.2-gnu/drivers/media/dvb/siano/smsendian.c
--- linux-libre-3.1-gnu/drivers/media/dvb/siano/smsendian.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/siano/smsendian.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 
  ****************************************************************/
 
+#include <linux/export.h>
 #include <asm/byteorder.h>
 
 #include "smsendian.h"
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/siano/smssdio.c linux-libre-3.2-gnu/drivers/media/dvb/siano/smssdio.c
--- linux-libre-3.1-gnu/drivers/media/dvb/siano/smssdio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/siano/smssdio.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,7 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/sdio_ids.h>
+#include <linux/module.h>
 
 #include "smscoreapi.h"
 #include "sms-cards.h"
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/siano/smsusb.c linux-libre-3.2-gnu/drivers/media/dvb/siano/smsusb.c
--- linux-libre-3.1-gnu/drivers/media/dvb/siano/smsusb.c	2012-03-19 21:36:43.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/siano/smsusb.c	2012-03-19 21:39:19.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/usb.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include "smscoreapi.h"
 #include "sms-cards.h"
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/ttpci/av7110_v4l.c linux-libre-3.2-gnu/drivers/media/dvb/ttpci/av7110_v4l.c
--- linux-libre-3.1-gnu/drivers/media/dvb/ttpci/av7110_v4l.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/ttpci/av7110_v4l.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,6 +25,8 @@
  * the project's page is at http://www.linuxtv.org/ 
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/delay.h>
@@ -253,7 +255,7 @@
 
 		switch (av7110->current_input) {
 		case 1:
-			dprintk(1, "switching SAA7113 to Analog Tuner Input.\n");
+			dprintk(1, "switching SAA7113 to Analog Tuner Input\n");
 			msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
 			msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
 			msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
@@ -263,7 +265,7 @@
 
 			if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
 				if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
-					dprintk(1, "setting band in demodulator failed.\n");
+					dprintk(1, "setting band in demodulator failed\n");
 			} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
 				saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9819 pin9(STD)
 				saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9819 pin30(VIF)
@@ -272,17 +274,17 @@
 				dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
 			break;
 		case 2:
-			dprintk(1, "switching SAA7113 to Video AV CVBS Input.\n");
+			dprintk(1, "switching SAA7113 to Video AV CVBS Input\n");
 			if (i2c_writereg(av7110, 0x48, 0x02, 0xd2) != 1)
 				dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
 			break;
 		case 3:
-			dprintk(1, "switching SAA7113 to Video AV Y/C Input.\n");
+			dprintk(1, "switching SAA7113 to Video AV Y/C Input\n");
 			if (i2c_writereg(av7110, 0x48, 0x02, 0xd9) != 1)
 				dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
 			break;
 		default:
-			dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input.\n");
+			dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input\n");
 		}
 	} else {
 		adswitch = 0;
@@ -299,7 +301,7 @@
 
 		if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
 			if (ves1820_writereg(dev, 0x09, 0x0f, 0x20))
-				dprintk(1, "setting band in demodulator failed.\n");
+				dprintk(1, "setting band in demodulator failed\n");
 		} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
 			saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
 			saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
@@ -413,7 +415,7 @@
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
 
-	dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency);
+	dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x\n", f->frequency);
 
 	if (!av7110->analog_tuner_flags || av7110->current_input != 1)
 		return -EINVAL;
@@ -429,7 +431,7 @@
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
 
-	dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency);
+	dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x\n", f->frequency);
 
 	if (!av7110->analog_tuner_flags || av7110->current_input != 1)
 		return -EINVAL;
@@ -689,12 +691,12 @@
 
 	if (i2c_writereg(av7110, 0x80, 0x0, 0x80) == 1 &&
 	    i2c_writereg(av7110, 0x80, 0x0, 0) == 1) {
-		printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
+		pr_info("DVB-C analog module @ card %d detected, initializing MSP3400\n",
 			av7110->dvb_adapter.num);
 		av7110->adac_type = DVB_ADAC_MSP34x0;
 	} else if (i2c_writereg(av7110, 0x84, 0x0, 0x80) == 1 &&
 		   i2c_writereg(av7110, 0x84, 0x0, 0) == 1) {
-		printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3415\n",
+		pr_info("DVB-C analog module @ card %d detected, initializing MSP3415\n",
 			av7110->dvb_adapter.num);
 		av7110->adac_type = DVB_ADAC_MSP34x5;
 	} else
@@ -715,7 +717,7 @@
 	msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x1900); // prescale SCART
 
 	if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) {
-		INFO(("saa7113 not accessible.\n"));
+		pr_info("saa7113 not accessible\n");
 	} else {
 		u8 *i = saa7113_init_regs;
 
@@ -733,7 +735,7 @@
 		/* setup for DVB by default */
 		if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
 			if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20))
-				dprintk(1, "setting band in demodulator failed.\n");
+				dprintk(1, "setting band in demodulator failed\n");
 		} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
 			saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
 			saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
@@ -797,7 +799,7 @@
 	ret = saa7146_vv_init(dev, vv_data);
 
 	if (ret) {
-		ERR(("cannot init capture device. skipping.\n"));
+		ERR("cannot init capture device. skipping\n");
 		return -ENODEV;
 	}
 	vv_data->ops.vidioc_enum_input = vidioc_enum_input;
@@ -814,12 +816,12 @@
 	vv_data->ops.vidioc_s_fmt_sliced_vbi_out = vidioc_s_fmt_sliced_vbi_out;
 
 	if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {
-		ERR(("cannot register capture device. skipping.\n"));
+		ERR("cannot register capture device. skipping\n");
 		saa7146_vv_release(dev);
 		return -ENODEV;
 	}
 	if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI))
-		ERR(("cannot register vbi v4l2 device. skipping.\n"));
+		ERR("cannot register vbi v4l2 device. skipping\n");
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/ttpci/budget-av.c linux-libre-3.2-gnu/drivers/media/dvb/ttpci/budget-av.c
--- linux-libre-3.1-gnu/drivers/media/dvb/ttpci/budget-av.c	2012-03-19 21:36:01.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/ttpci/budget-av.c	2012-03-19 21:38:33.000000000 -0400
@@ -33,6 +33,8 @@
  * the project's page is at http://www.linuxtv.org/ 
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "budget.h"
 #include "stv0299.h"
 #include "stb0899_drv.h"
@@ -149,7 +151,7 @@
 	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
 	if (result == -ETIMEDOUT) {
 		ciintf_slot_shutdown(ca, slot);
-		printk(KERN_INFO "budget-av: cam ejected 1\n");
+		pr_info("cam ejected 1\n");
 	}
 	return result;
 }
@@ -168,7 +170,7 @@
 	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
 	if (result == -ETIMEDOUT) {
 		ciintf_slot_shutdown(ca, slot);
-		printk(KERN_INFO "budget-av: cam ejected 2\n");
+		pr_info("cam ejected 2\n");
 	}
 	return result;
 }
@@ -187,7 +189,7 @@
 	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
 	if (result == -ETIMEDOUT) {
 		ciintf_slot_shutdown(ca, slot);
-		printk(KERN_INFO "budget-av: cam ejected 3\n");
+		pr_info("cam ejected 3\n");
 		return -ETIMEDOUT;
 	}
 	return result;
@@ -207,7 +209,7 @@
 	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
 	if (result == -ETIMEDOUT) {
 		ciintf_slot_shutdown(ca, slot);
-		printk(KERN_INFO "budget-av: cam ejected 5\n");
+		pr_info("cam ejected 5\n");
 	}
 	return result;
 }
@@ -289,7 +291,7 @@
 		if (saa7146_read(saa, PSR) & MASK_06) {
 			if (budget_av->slot_status == SLOTSTATUS_NONE) {
 				budget_av->slot_status = SLOTSTATUS_PRESENT;
-				printk(KERN_INFO "budget-av: cam inserted A\n");
+				pr_info("cam inserted A\n");
 			}
 		}
 		saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
@@ -306,11 +308,11 @@
 		result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1);
 		if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) {
 			budget_av->slot_status = SLOTSTATUS_PRESENT;
-			printk(KERN_INFO "budget-av: cam inserted B\n");
+			pr_info("cam inserted B\n");
 		} else if (result < 0) {
 			if (budget_av->slot_status != SLOTSTATUS_NONE) {
 				ciintf_slot_shutdown(ca, slot);
-				printk(KERN_INFO "budget-av: cam ejected 5\n");
+				pr_info("cam ejected 5\n");
 				return 0;
 			}
 		}
@@ -365,11 +367,11 @@
 
 	if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
 					  &budget_av->ca, 0, 1)) != 0) {
-		printk(KERN_ERR "budget-av: ci initialisation failed.\n");
+		pr_err("ci initialisation failed\n");
 		goto error;
 	}
 
-	printk(KERN_INFO "budget-av: ci interface initialised.\n");
+	pr_info("ci interface initialised\n");
 	return 0;
 
 error:
@@ -896,7 +898,6 @@
 	{ STB0899_DISRX_ST0		, 0x04 },
 	{ STB0899_DISRX_ST1		, 0x00 },
 	{ STB0899_DISPARITY		, 0x00 },
-	{ STB0899_DISFIFO		, 0x00 },
 	{ STB0899_DISSTATUS		, 0x20 },
 	{ STB0899_DISF22		, 0x8c },
 	{ STB0899_DISF22RX		, 0x9a },
@@ -1197,6 +1198,7 @@
 #define SUBID_DVBC_KNC1			0x0020
 #define SUBID_DVBC_KNC1_PLUS		0x0021
 #define SUBID_DVBC_KNC1_MK3		0x0022
+#define SUBID_DVBC_KNC1_TDA10024	0x0028
 #define SUBID_DVBC_KNC1_PLUS_MK3	0x0023
 #define SUBID_DVBC_CINERGY1200		0x1156
 #define SUBID_DVBC_CINERGY1200_MK3	0x1176
@@ -1316,6 +1318,7 @@
 	case SUBID_DVBC_EASYWATCH_MK3:
 	case SUBID_DVBC_CINERGY1200_MK3:
 	case SUBID_DVBC_KNC1_MK3:
+	case SUBID_DVBC_KNC1_TDA10024:
 	case SUBID_DVBC_KNC1_PLUS_MK3:
 		budget_av->reinitialise_demod = 1;
 		budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
@@ -1343,8 +1346,7 @@
 	}
 
 	if (fe == NULL) {
-		printk(KERN_ERR "budget-av: A frontend driver was not found "
-				"for device [%04x:%04x] subsystem [%04x:%04x]\n",
+		pr_err("A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
 		       saa->pci->vendor,
 		       saa->pci->device,
 		       saa->pci->subsystem_vendor,
@@ -1356,7 +1358,7 @@
 
 	if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
 				  budget_av->budget.dvb_frontend)) {
-		printk(KERN_ERR "budget-av: Frontend registration failed!\n");
+		pr_err("Frontend registration failed!\n");
 		dvb_frontend_detach(budget_av->budget.dvb_frontend);
 		budget_av->budget.dvb_frontend = NULL;
 	}
@@ -1414,7 +1416,7 @@
 
 static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 {
-	dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
+	dprintk(1, "VIDIOC_ENUMINPUT %d\n", i->index);
 	if (i->index >= KNC1_INPUTS)
 		return -EINVAL;
 	memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
@@ -1428,7 +1430,7 @@
 
 	*i = budget_av->cur_input;
 
-	dprintk(1, "VIDIOC_G_INPUT %d.\n", *i);
+	dprintk(1, "VIDIOC_G_INPUT %d\n", *i);
 	return 0;
 }
 
@@ -1437,7 +1439,7 @@
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct budget_av *budget_av = (struct budget_av *)dev->ext_priv;
 
-	dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
+	dprintk(1, "VIDIOC_S_INPUT %d\n", input);
 	return saa7113_setinput(budget_av, input);
 }
 
@@ -1476,7 +1478,7 @@
 
 		if (0 != saa7146_vv_init(dev, &vv_data)) {
 			/* fixme: proper cleanup here */
-			ERR(("cannot init vv subsystem.\n"));
+			ERR("cannot init vv subsystem\n");
 			return err;
 		}
 		vv_data.ops.vidioc_enum_input = vidioc_enum_input;
@@ -1485,7 +1487,7 @@
 
 		if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
 			/* fixme: proper cleanup here */
-			ERR(("cannot register capture v4l2 device.\n"));
+			ERR("cannot register capture v4l2 device\n");
 			saa7146_vv_release(dev);
 			return err;
 		}
@@ -1502,13 +1504,12 @@
 
 	mac = budget_av->budget.dvb_adapter.proposed_mac;
 	if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
-		printk(KERN_ERR "KNC1-%d: Could not read MAC from KNC1 card\n",
+		pr_err("KNC1-%d: Could not read MAC from KNC1 card\n",
 		       budget_av->budget.dvb_adapter.num);
 		memset(mac, 0, 6);
 	} else {
-		printk(KERN_INFO "KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
-		       budget_av->budget.dvb_adapter.num,
-		       mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+		pr_info("KNC1-%d: MAC addr = %pM\n",
+			budget_av->budget.dvb_adapter.num, mac);
 	}
 
 	budget_av->budget.dvb_adapter.priv = budget_av;
@@ -1558,6 +1559,7 @@
 MAKE_BUDGET_INFO(knc1spx4, "KNC1 DVB-S Plus X4", BUDGET_KNC1SP);
 MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
 MAKE_BUDGET_INFO(knc1cmk3, "KNC1 DVB-C MK3", BUDGET_KNC1C_MK3);
+MAKE_BUDGET_INFO(knc1ctda10024, "KNC1 DVB-C TDA10024", BUDGET_KNC1C_TDA10024);
 MAKE_BUDGET_INFO(knc1cpmk3, "KNC1 DVB-C Plus MK3", BUDGET_KNC1CP_MK3);
 MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
 MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
@@ -1587,6 +1589,7 @@
 	MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
 	MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
 	MAKE_EXTENSION_PCI(knc1cmk3, 0x1894, 0x0022),
+	MAKE_EXTENSION_PCI(knc1ctda10024, 0x1894, 0x0028),
 	MAKE_EXTENSION_PCI(knc1cpmk3, 0x1894, 0x0023),
 	MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
 	MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/ttpci/budget-ci.c linux-libre-3.2-gnu/drivers/media/dvb/ttpci/budget-ci.c
--- linux-libre-3.1-gnu/drivers/media/dvb/ttpci/budget-ci.c	2012-03-19 21:36:01.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/ttpci/budget-ci.c	2012-03-19 21:38:33.000000000 -0400
@@ -1053,7 +1053,6 @@
 	{ STB0899_DISRX_ST0     	, 0x04 },
 	{ STB0899_DISRX_ST1     	, 0x00 },
 	{ STB0899_DISPARITY     	, 0x00 },
-	{ STB0899_DISFIFO       	, 0x00 },
 	{ STB0899_DISSTATUS		, 0x20 },
 	{ STB0899_DISF22        	, 0x8c },
 	{ STB0899_DISF22RX      	, 0x9a },
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/ttpci/budget-core.c linux-libre-3.2-gnu/drivers/media/dvb/ttpci/budget-core.c
--- linux-libre-3.1-gnu/drivers/media/dvb/ttpci/budget-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/ttpci/budget-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -110,6 +110,7 @@
 		break;
 	case BUDGET_CIN1200C_MK3:
 	case BUDGET_KNC1C_MK3:
+	case BUDGET_KNC1C_TDA10024:
 	case BUDGET_KNC1CP_MK3:
 		if (budget->video_port == BUDGET_VIDEO_PORTA) {
 			saa7146_write(dev, DD1_INIT, 0x06000200);
@@ -434,6 +435,7 @@
 	case BUDGET_KNC1CP:
 	case BUDGET_CIN1200C:
 	case BUDGET_KNC1C_MK3:
+	case BUDGET_KNC1C_TDA10024:
 	case BUDGET_KNC1CP_MK3:
 	case BUDGET_CIN1200C_MK3:
 		budget->buffer_width = TS_WIDTH_DVBC;
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/ttpci/budget.h linux-libre-3.2-gnu/drivers/media/dvb/ttpci/budget.h
--- linux-libre-3.1-gnu/drivers/media/dvb/ttpci/budget.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/ttpci/budget.h	2012-01-04 18:55:44.000000000 -0500
@@ -104,6 +104,7 @@
 #define BUDGET_KNC1C_MK3	   16
 #define BUDGET_KNC1CP_MK3	   17
 #define BUDGET_KNC1S2              18
+#define BUDGET_KNC1C_TDA10024	   19
 
 #define BUDGET_VIDEO_PORTA         0
 #define BUDGET_VIDEO_PORTB         1
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/ttpci/Makefile linux-libre-3.2-gnu/drivers/media/dvb/ttpci/Makefile
--- linux-libre-3.1-gnu/drivers/media/dvb/ttpci/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/ttpci/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -17,5 +17,5 @@
 obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o
 obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/common/tuners
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/ttpci/ttpci-eeprom.c linux-libre-3.2-gnu/drivers/media/dvb/ttpci/ttpci-eeprom.c
--- linux-libre-3.1-gnu/drivers/media/dvb/ttpci/ttpci-eeprom.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/ttpci/ttpci-eeprom.c	2012-01-04 18:55:44.000000000 -0500
@@ -85,6 +85,35 @@
 	return 0;
 }
 
+int ttpci_eeprom_decode_mac(u8 *decodedMAC, u8 *encodedMAC)
+{
+	u8 xor[20] = { 0x72, 0x23, 0x68, 0x19, 0x5c, 0xa8, 0x71, 0x2c,
+		       0x54, 0xd3, 0x7b, 0xf1, 0x9E, 0x23, 0x16, 0xf6,
+		       0x1d, 0x36, 0x64, 0x78};
+	u8 data[20];
+	int i;
+
+	memcpy(data, encodedMAC, 20);
+
+	for (i = 0; i < 20; i++)
+		data[i] ^= xor[i];
+	for (i = 0; i < 10; i++)
+		data[i] = ((data[2 * i + 1] << 8) | data[2 * i])
+			>> ((data[2 * i + 1] >> 6) & 3);
+
+	if (check_mac_tt(data))
+		return -ENODEV;
+
+	decodedMAC[0] = data[2];
+	decodedMAC[1] = data[1];
+	decodedMAC[2] = data[0];
+	decodedMAC[3] = data[6];
+	decodedMAC[4] = data[5];
+	decodedMAC[5] = data[4];
+	return 0;
+}
+EXPORT_SYMBOL(ttpci_eeprom_decode_mac);
+
 static int ttpci_eeprom_read_encodedMAC(struct i2c_adapter *adapter, u8 * encodedMAC)
 {
 	int ret;
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/ttpci/ttpci-eeprom.h linux-libre-3.2-gnu/drivers/media/dvb/ttpci/ttpci-eeprom.h
--- linux-libre-3.1-gnu/drivers/media/dvb/ttpci/ttpci-eeprom.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/ttpci/ttpci-eeprom.h	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/types.h>
 #include <linux/i2c.h>
 
+extern int ttpci_eeprom_decode_mac(u8 *decodedMAC, u8 *encodedMAC);
 extern int ttpci_eeprom_parse_mac(struct i2c_adapter *adapter, u8 *propsed_mac);
 
 #endif
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/ttusb-budget/Makefile linux-libre-3.2-gnu/drivers/media/dvb/ttusb-budget/Makefile
--- linux-libre-3.1-gnu/drivers/media/dvb/ttusb-budget/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/ttusb-budget/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
 obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
diff -druN linux-libre-3.1-gnu/drivers/media/dvb/ttusb-dec/Makefile linux-libre-3.2-gnu/drivers/media/dvb/ttusb-dec/Makefile
--- linux-libre-3.1-gnu/drivers/media/dvb/ttusb-dec/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/dvb/ttusb-dec/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,3 +1,3 @@
 obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o ttusbdecfe.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/dvb/dvb-core/
diff -druN linux-libre-3.1-gnu/drivers/media/media-device.c linux-libre-3.2-gnu/drivers/media/media-device.c
--- linux-libre-3.1-gnu/drivers/media/media-device.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/media-device.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/types.h>
 #include <linux/ioctl.h>
 #include <linux/media.h>
+#include <linux/export.h>
 
 #include <media/media-device.h>
 #include <media/media-devnode.h>
diff -druN linux-libre-3.1-gnu/drivers/media/radio/Kconfig linux-libre-3.2-gnu/drivers/media/radio/Kconfig
--- linux-libre-3.1-gnu/drivers/media/radio/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/radio/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -426,7 +426,6 @@
 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---
diff -druN linux-libre-3.1-gnu/drivers/media/radio/Makefile linux-libre-3.2-gnu/drivers/media/radio/Makefile
--- linux-libre-3.1-gnu/drivers/media/radio/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/radio/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -27,4 +27,4 @@
 obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o
 obj-$(CONFIG_RADIO_WL128X) += wl128x/
 
-EXTRA_CFLAGS += -Isound
+ccflags-y += -Isound
diff -druN linux-libre-3.1-gnu/drivers/media/radio/radio-si4713.c linux-libre-3.2-gnu/drivers/media/radio/radio-si4713.c
--- linux-libre-3.1-gnu/drivers/media/radio/radio-si4713.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/radio/radio-si4713.c	2012-01-04 18:55:44.000000000 -0500
@@ -92,10 +92,6 @@
 static int radio_si4713_querycap(struct file *file, void *priv,
 					struct v4l2_capability *capability)
 {
-	struct radio_si4713_device *rsdev;
-
-	rsdev = video_get_drvdata(video_devdata(file));
-
 	strlcpy(capability->driver, "radio-si4713", sizeof(capability->driver));
 	strlcpy(capability->card, "Silicon Labs Si4713 Modulator",
 				sizeof(capability->card));
diff -druN linux-libre-3.1-gnu/drivers/media/radio/radio-tea5764.c linux-libre-3.2-gnu/drivers/media/radio/radio-tea5764.c
--- linux-libre-3.1-gnu/drivers/media/radio/radio-tea5764.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/radio/radio-tea5764.c	2012-01-04 18:55:44.000000000 -0500
@@ -128,8 +128,10 @@
 	u16 rdsbbl;				/* PAUSEDET & RDSBBL */
 } __attribute__ ((packed));
 
-#ifndef RADIO_TEA5764_XTAL
+#ifdef CONFIG_RADIO_TEA5764_XTAL
 #define RADIO_TEA5764_XTAL 1
+#else
+#define RADIO_TEA5764_XTAL 0
 #endif
 
 static int radio_nr = -1;
diff -druN linux-libre-3.1-gnu/drivers/media/radio/radio-timb.c linux-libre-3.2-gnu/drivers/media/radio/radio-timb.c
--- linux-libre-3.1-gnu/drivers/media/radio/radio-timb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/radio/radio-timb.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/module.h>
 #include <media/timb_radio.h>
 
 #define DRIVER_NAME "timb-radio"
diff -druN linux-libre-3.1-gnu/drivers/media/radio/radio-wl1273.c linux-libre-3.2-gnu/drivers/media/radio/radio-wl1273.c
--- linux-libre-3.1-gnu/drivers/media/radio/radio-wl1273.c	2012-03-19 21:41:08.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/radio/radio-wl1273.c	2012-03-19 21:43:43.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/mfd/wl1273-core.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
@@ -2109,7 +2110,7 @@
 				 V4L2_CID_TUNE_ANTENNA_CAPACITOR,
 				 0, 255, 1, 255);
 	if (ctrl)
-		ctrl->is_volatile = 1;
+		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
 
 	if (radio->ctrl_handler.error) {
 		r = radio->ctrl_handler.error;
diff -druN linux-libre-3.1-gnu/drivers/media/radio/si470x/radio-si470x-usb.c linux-libre-3.2-gnu/drivers/media/radio/si470x/radio-si470x-usb.c
--- linux-libre-3.1-gnu/drivers/media/radio/si470x/radio-si470x-usb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/radio/si470x/radio-si470x-usb.c	2012-01-04 18:55:44.000000000 -0500
@@ -395,7 +395,6 @@
 static void si470x_int_in_callback(struct urb *urb)
 {
 	struct si470x_device *radio = urb->context;
-	unsigned char buf[RDS_REPORT_SIZE];
 	int retval;
 	unsigned char regnr;
 	unsigned char blocknum;
@@ -423,7 +422,6 @@
 
 	if (urb->actual_length > 0) {
 		/* Update RDS registers with URB data */
-		buf[0] = RDS_REPORT;
 		for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++)
 			radio->registers[STATUSRSSI + regnr] =
 			    get_unaligned_be16(&radio->int_in_buffer[
diff -druN linux-libre-3.1-gnu/drivers/media/radio/si4713-i2c.c linux-libre-3.2-gnu/drivers/media/radio/si4713-i2c.c
--- linux-libre-3.1-gnu/drivers/media/radio/si4713-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/radio/si4713-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/module.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-common.h>
diff -druN linux-libre-3.1-gnu/drivers/media/radio/wl128x/fmdrv_v4l2.c linux-libre-3.2-gnu/drivers/media/radio/wl128x/fmdrv_v4l2.c
--- linux-libre-3.1-gnu/drivers/media/radio/wl128x/fmdrv_v4l2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/radio/wl128x/fmdrv_v4l2.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,8 @@
  *
  */
 
+#include <linux/export.h>
+
 #include "fmdrv.h"
 #include "fmdrv_v4l2.h"
 #include "fmdrv_common.h"
@@ -84,12 +86,14 @@
 	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);
+	if (ret)
+		return -EFAULT;
 
 	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;
+	return sizeof(rds);
 }
 
 static u32 fm_v4l2_fops_poll(struct file *file, struct poll_table_struct *pts)
@@ -402,7 +406,7 @@
 static int fm_v4l2_vidioc_g_modulator(struct file *file, void *priv,
 		struct v4l2_modulator *mod)
 {
-	struct fmdev *fmdev = video_drvdata(file);;
+	struct fmdev *fmdev = video_drvdata(file);
 
 	if (mod->index != 0)
 		return -EINVAL;
@@ -557,7 +561,7 @@
 			255, 1, 255);
 
 	if (ctrl)
-		ctrl->is_volatile = 1;
+		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/rc/ati_remote.c linux-libre-3.2-gnu/drivers/media/rc/ati_remote.c
--- linux-libre-3.1-gnu/drivers/media/rc/ati_remote.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/rc/ati_remote.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,937 @@
+/*
+ *  USB ATI Remote support
+ *
+ *                Copyright (c) 2011 Anssi Hannula <anssi.hannula@iki.fi>
+ *  Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net>
+ *  Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev
+ *
+ *  This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including
+ *  porting to the 2.6 kernel interfaces, along with other modification
+ *  to better match the style of the existing usb/input drivers.  However, the
+ *  protocol and hardware handling is essentially unchanged from 2.1.1.
+ *
+ *  The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by
+ *  Vojtech Pavlik.
+ *
+ *  Changes:
+ *
+ *  Feb 2004: Torrey Hoffman <thoffman@arnor.net>
+ *            Version 2.2.0
+ *  Jun 2004: Torrey Hoffman <thoffman@arnor.net>
+ *            Version 2.2.1
+ *            Added key repeat support contributed by:
+ *                Vincent Vanackere <vanackere@lif.univ-mrs.fr>
+ *            Added support for the "Lola" remote contributed by:
+ *                Seth Cohn <sethcohn@yahoo.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
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Hardware & software notes
+ *
+ * These remote controls are distributed by ATI as part of their
+ * "All-In-Wonder" video card packages.  The receiver self-identifies as a
+ * "USB Receiver" with manufacturer "X10 Wireless Technology Inc".
+ *
+ * The "Lola" remote is available from X10.  See:
+ *    http://www.x10.com/products/lola_sg1.htm
+ * The Lola is similar to the ATI remote but has no mouse support, and slightly
+ * different keys.
+ *
+ * It is possible to use multiple receivers and remotes on multiple computers
+ * simultaneously by configuring them to use specific channels.
+ *
+ * The RF protocol used by the remote supports 16 distinct channels, 1 to 16.
+ * Actually, it may even support more, at least in some revisions of the
+ * hardware.
+ *
+ * Each remote can be configured to transmit on one channel as follows:
+ *   - Press and hold the "hand icon" button.
+ *   - When the red LED starts to blink, let go of the "hand icon" button.
+ *   - When it stops blinking, input the channel code as two digits, from 01
+ *     to 16, and press the hand icon again.
+ *
+ * The timing can be a little tricky.  Try loading the module with debug=1
+ * to have the kernel print out messages about the remote control number
+ * and mask.  Note: debugging prints remote numbers as zero-based hexadecimal.
+ *
+ * The driver has a "channel_mask" parameter. This bitmask specifies which
+ * channels will be ignored by the module.  To mask out channels, just add
+ * all the 2^channel_number values together.
+ *
+ * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote
+ * ignore signals coming from remote controls transmitting on channel 4, but
+ * accept all other channels.
+ *
+ * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be
+ * ignored.
+ *
+ * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this
+ * parameter are unused.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/usb/input.h>
+#include <linux/wait.h>
+#include <linux/jiffies.h>
+#include <media/rc-core.h>
+
+/*
+ * Module and Version Information, Module Parameters
+ */
+
+#define ATI_REMOTE_VENDOR_ID		0x0bc7
+#define LOLA_REMOTE_PRODUCT_ID		0x0002
+#define LOLA2_REMOTE_PRODUCT_ID		0x0003
+#define ATI_REMOTE_PRODUCT_ID		0x0004
+#define NVIDIA_REMOTE_PRODUCT_ID	0x0005
+#define MEDION_REMOTE_PRODUCT_ID	0x0006
+#define FIREFLY_REMOTE_PRODUCT_ID	0x0008
+
+#define DRIVER_VERSION		"2.2.1"
+#define DRIVER_AUTHOR           "Torrey Hoffman <thoffman@arnor.net>"
+#define DRIVER_DESC             "ATI/X10 RF USB Remote Control"
+
+#define NAME_BUFSIZE      80    /* size of product name, path buffers */
+#define DATA_BUFSIZE      63    /* size of URB data buffers */
+
+/*
+ * Duplicate event filtering time.
+ * Sequential, identical KIND_FILTERED inputs with less than
+ * FILTER_TIME milliseconds between them are considered as repeat
+ * events. The hardware generates 5 events for the first keypress
+ * and we have to take this into account for an accurate repeat
+ * behaviour.
+ */
+#define FILTER_TIME	60 /* msec */
+#define REPEAT_DELAY	500 /* msec */
+
+static unsigned long channel_mask;
+module_param(channel_mask, ulong, 0644);
+MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore");
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable extra debug messages and information");
+
+static int repeat_filter = FILTER_TIME;
+module_param(repeat_filter, int, 0644);
+MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec");
+
+static int repeat_delay = REPEAT_DELAY;
+module_param(repeat_delay, int, 0644);
+MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec");
+
+static bool mouse = true;
+module_param(mouse, bool, 0444);
+MODULE_PARM_DESC(mouse, "Enable mouse device, default = yes");
+
+#define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
+#undef err
+#define err(format, arg...) printk(KERN_ERR format , ## arg)
+
+static struct usb_device_id ati_remote_table[] = {
+	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID),	.driver_info = (unsigned long)RC_MAP_ATI_X10 },
+	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA2_REMOTE_PRODUCT_ID),	.driver_info = (unsigned long)RC_MAP_ATI_X10 },
+	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID),	.driver_info = (unsigned long)RC_MAP_ATI_X10 },
+	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, NVIDIA_REMOTE_PRODUCT_ID),	.driver_info = (unsigned long)RC_MAP_ATI_X10 },
+	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID),	.driver_info = (unsigned long)RC_MAP_MEDION_X10 },
+	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, FIREFLY_REMOTE_PRODUCT_ID),	.driver_info = (unsigned long)RC_MAP_SNAPSTREAM_FIREFLY },
+	{}	/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, ati_remote_table);
+
+/* Get hi and low bytes of a 16-bits int */
+#define HI(a)	((unsigned char)((a) >> 8))
+#define LO(a)	((unsigned char)((a) & 0xff))
+
+#define SEND_FLAG_IN_PROGRESS	1
+#define SEND_FLAG_COMPLETE	2
+
+/* Device initialization strings */
+static char init1[] = { 0x01, 0x00, 0x20, 0x14 };
+static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 };
+
+struct ati_remote {
+	struct input_dev *idev;
+	struct rc_dev *rdev;
+	struct usb_device *udev;
+	struct usb_interface *interface;
+
+	struct urb *irq_urb;
+	struct urb *out_urb;
+	struct usb_endpoint_descriptor *endpoint_in;
+	struct usb_endpoint_descriptor *endpoint_out;
+	unsigned char *inbuf;
+	unsigned char *outbuf;
+	dma_addr_t inbuf_dma;
+	dma_addr_t outbuf_dma;
+
+	unsigned char old_data;     /* Detect duplicate events */
+	unsigned long old_jiffies;
+	unsigned long acc_jiffies;  /* handle acceleration */
+	unsigned long first_jiffies;
+
+	unsigned int repeat_count;
+
+	char rc_name[NAME_BUFSIZE];
+	char rc_phys[NAME_BUFSIZE];
+	char mouse_name[NAME_BUFSIZE];
+	char mouse_phys[NAME_BUFSIZE];
+
+	wait_queue_head_t wait;
+	int send_flags;
+
+	int users; /* 0-2, users are rc and input */
+	struct mutex open_mutex;
+};
+
+/* "Kinds" of messages sent from the hardware to the driver. */
+#define KIND_END        0
+#define KIND_LITERAL    1   /* Simply pass to input system */
+#define KIND_FILTERED   2   /* Add artificial key-up events, drop keyrepeats */
+#define KIND_LU         3   /* Directional keypad diagonals - left up, */
+#define KIND_RU         4   /*   right up,  */
+#define KIND_LD         5   /*   left down, */
+#define KIND_RD         6   /*   right down */
+#define KIND_ACCEL      7   /* Directional keypad - left, right, up, down.*/
+
+/* Translation table from hardware messages to input events. */
+static const struct {
+	short kind;
+	unsigned char data;
+	int type;
+	unsigned int code;
+	int value;
+}  ati_remote_tbl[] = {
+	/* Directional control pad axes */
+	{KIND_ACCEL,   0x70, EV_REL, REL_X, -1},   /* left */
+	{KIND_ACCEL,   0x71, EV_REL, REL_X, 1},    /* right */
+	{KIND_ACCEL,   0x72, EV_REL, REL_Y, -1},   /* up */
+	{KIND_ACCEL,   0x73, EV_REL, REL_Y, 1},    /* down */
+	/* Directional control pad diagonals */
+	{KIND_LU,      0x74, EV_REL, 0, 0},        /* left up */
+	{KIND_RU,      0x75, EV_REL, 0, 0},        /* right up */
+	{KIND_LD,      0x77, EV_REL, 0, 0},        /* left down */
+	{KIND_RD,      0x76, EV_REL, 0, 0},        /* right down */
+
+	/* "Mouse button" buttons */
+	{KIND_LITERAL, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */
+	{KIND_LITERAL, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */
+	{KIND_LITERAL, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */
+	{KIND_LITERAL, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */
+
+	/* Artificial "doubleclick" events are generated by the hardware.
+	 * They are mapped to the "side" and "extra" mouse buttons here. */
+	{KIND_FILTERED, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */
+	{KIND_FILTERED, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */
+
+	/* Non-mouse events are handled by rc-core */
+	{KIND_END, 0x00, EV_MAX + 1, 0, 0}
+};
+
+/* Local function prototypes */
+static int ati_remote_sendpacket	(struct ati_remote *ati_remote, u16 cmd, unsigned char *data);
+static void ati_remote_irq_out		(struct urb *urb);
+static void ati_remote_irq_in		(struct urb *urb);
+static void ati_remote_input_report	(struct urb *urb);
+static int ati_remote_initialize	(struct ati_remote *ati_remote);
+static int ati_remote_probe		(struct usb_interface *interface, const struct usb_device_id *id);
+static void ati_remote_disconnect	(struct usb_interface *interface);
+
+/* usb specific object to register with the usb subsystem */
+static struct usb_driver ati_remote_driver = {
+	.name         = "ati_remote",
+	.probe        = ati_remote_probe,
+	.disconnect   = ati_remote_disconnect,
+	.id_table     = ati_remote_table,
+};
+
+/*
+ *	ati_remote_dump_input
+ */
+static void ati_remote_dump(struct device *dev, unsigned char *data,
+			    unsigned int len)
+{
+	if (len == 1) {
+		if (data[0] != (unsigned char)0xff && data[0] != 0x00)
+			dev_warn(dev, "Weird byte 0x%02x\n", data[0]);
+	} else if (len == 4)
+		dev_warn(dev, "Weird key %02x %02x %02x %02x\n",
+		     data[0], data[1], data[2], data[3]);
+	else
+		dev_warn(dev, "Weird data, len=%d %02x %02x %02x %02x %02x %02x ...\n",
+		     len, data[0], data[1], data[2], data[3], data[4], data[5]);
+}
+
+/*
+ *	ati_remote_open
+ */
+static int ati_remote_open(struct ati_remote *ati_remote)
+{
+	int err = 0;
+
+	mutex_lock(&ati_remote->open_mutex);
+
+	if (ati_remote->users++ != 0)
+		goto out; /* one was already active */
+
+	/* On first open, submit the read urb which was set up previously. */
+	ati_remote->irq_urb->dev = ati_remote->udev;
+	if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) {
+		dev_err(&ati_remote->interface->dev,
+			"%s: usb_submit_urb failed!\n", __func__);
+		err = -EIO;
+	}
+
+out:	mutex_unlock(&ati_remote->open_mutex);
+	return err;
+}
+
+/*
+ *	ati_remote_close
+ */
+static void ati_remote_close(struct ati_remote *ati_remote)
+{
+	mutex_lock(&ati_remote->open_mutex);
+	if (--ati_remote->users == 0)
+		usb_kill_urb(ati_remote->irq_urb);
+	mutex_unlock(&ati_remote->open_mutex);
+}
+
+static int ati_remote_input_open(struct input_dev *inputdev)
+{
+	struct ati_remote *ati_remote = input_get_drvdata(inputdev);
+	return ati_remote_open(ati_remote);
+}
+
+static void ati_remote_input_close(struct input_dev *inputdev)
+{
+	struct ati_remote *ati_remote = input_get_drvdata(inputdev);
+	ati_remote_close(ati_remote);
+}
+
+static int ati_remote_rc_open(struct rc_dev *rdev)
+{
+	struct ati_remote *ati_remote = rdev->priv;
+	return ati_remote_open(ati_remote);
+}
+
+static void ati_remote_rc_close(struct rc_dev *rdev)
+{
+	struct ati_remote *ati_remote = rdev->priv;
+	ati_remote_close(ati_remote);
+}
+
+/*
+ *		ati_remote_irq_out
+ */
+static void ati_remote_irq_out(struct urb *urb)
+{
+	struct ati_remote *ati_remote = urb->context;
+
+	if (urb->status) {
+		dev_dbg(&ati_remote->interface->dev, "%s: status %d\n",
+			__func__, urb->status);
+		return;
+	}
+
+	ati_remote->send_flags |= SEND_FLAG_COMPLETE;
+	wmb();
+	wake_up(&ati_remote->wait);
+}
+
+/*
+ *	ati_remote_sendpacket
+ *
+ *	Used to send device initialization strings
+ */
+static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data)
+{
+	int retval = 0;
+
+	/* Set up out_urb */
+	memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd));
+	((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd);
+
+	ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1;
+	ati_remote->out_urb->dev = ati_remote->udev;
+	ati_remote->send_flags = SEND_FLAG_IN_PROGRESS;
+
+	retval = usb_submit_urb(ati_remote->out_urb, GFP_ATOMIC);
+	if (retval) {
+		dev_dbg(&ati_remote->interface->dev,
+			 "sendpacket: usb_submit_urb failed: %d\n", retval);
+		return retval;
+	}
+
+	wait_event_timeout(ati_remote->wait,
+		((ati_remote->out_urb->status != -EINPROGRESS) ||
+			(ati_remote->send_flags & SEND_FLAG_COMPLETE)),
+		HZ);
+	usb_kill_urb(ati_remote->out_urb);
+
+	return retval;
+}
+
+/*
+ *	ati_remote_compute_accel
+ *
+ * Implements acceleration curve for directional control pad
+ * If elapsed time since last event is > 1/4 second, user "stopped",
+ * so reset acceleration. Otherwise, user is probably holding the control
+ * pad down, so we increase acceleration, ramping up over two seconds to
+ * a maximum speed.
+ */
+static int ati_remote_compute_accel(struct ati_remote *ati_remote)
+{
+	static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
+	unsigned long now = jiffies;
+	int acc;
+
+	if (time_after(now, ati_remote->old_jiffies + msecs_to_jiffies(250))) {
+		acc = 1;
+		ati_remote->acc_jiffies = now;
+	}
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(125)))
+		acc = accel[0];
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(250)))
+		acc = accel[1];
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(500)))
+		acc = accel[2];
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1000)))
+		acc = accel[3];
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1500)))
+		acc = accel[4];
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(2000)))
+		acc = accel[5];
+	else
+		acc = accel[6];
+
+	return acc;
+}
+
+/*
+ *	ati_remote_report_input
+ */
+static void ati_remote_input_report(struct urb *urb)
+{
+	struct ati_remote *ati_remote = urb->context;
+	unsigned char *data= ati_remote->inbuf;
+	struct input_dev *dev = ati_remote->idev;
+	int index = -1;
+	int acc;
+	int remote_num;
+	unsigned char scancode;
+	int i;
+
+	/*
+	 * data[0] = 0x14
+	 * data[1] = data[2] + data[3] + 0xd5 (a checksum byte)
+	 * data[2] = the key code (with toggle bit in MSB with some models)
+	 * data[3] = channel << 4 (the low 4 bits must be zero)
+	 */
+
+	/* Deal with strange looking inputs */
+	if ( (urb->actual_length != 4) || (data[0] != 0x14) ||
+		((data[3] & 0x0f) != 0x00) ) {
+		ati_remote_dump(&urb->dev->dev, data, urb->actual_length);
+		return;
+	}
+
+	if (data[1] != ((data[2] + data[3] + 0xd5) & 0xff)) {
+		dbginfo(&ati_remote->interface->dev,
+			"wrong checksum in input: %02x %02x %02x %02x\n",
+			data[0], data[1], data[2], data[3]);
+		return;
+	}
+
+	/* Mask unwanted remote channels.  */
+	/* note: remote_num is 0-based, channel 1 on remote == 0 here */
+	remote_num = (data[3] >> 4) & 0x0f;
+	if (channel_mask & (1 << (remote_num + 1))) {
+		dbginfo(&ati_remote->interface->dev,
+			"Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n",
+			remote_num, data[1], data[2], channel_mask);
+		return;
+	}
+
+	/*
+	 * MSB is a toggle code, though only used by some devices
+	 * (e.g. SnapStream Firefly)
+	 */
+	scancode = data[2] & 0x7f;
+
+	/* Look up event code index in the mouse translation table. */
+	for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) {
+		if (scancode == ati_remote_tbl[i].data) {
+			index = i;
+			break;
+		}
+	}
+
+	if (index >= 0) {
+		dbginfo(&ati_remote->interface->dev,
+			"channel 0x%02x; mouse data %02x; index %d; keycode %d\n",
+			remote_num, data[2], index, ati_remote_tbl[index].code);
+		if (!dev)
+			return; /* no mouse device */
+	} else
+		dbginfo(&ati_remote->interface->dev,
+			"channel 0x%02x; key data %02x, scancode %02x\n",
+			remote_num, data[2], scancode);
+
+
+	if (index >= 0 && ati_remote_tbl[index].kind == KIND_LITERAL) {
+		input_event(dev, ati_remote_tbl[index].type,
+			ati_remote_tbl[index].code,
+			ati_remote_tbl[index].value);
+		input_sync(dev);
+
+		ati_remote->old_jiffies = jiffies;
+		return;
+	}
+
+	if (index < 0 || ati_remote_tbl[index].kind == KIND_FILTERED) {
+		unsigned long now = jiffies;
+
+		/* Filter duplicate events which happen "too close" together. */
+		if (ati_remote->old_data == data[2] &&
+		    time_before(now, ati_remote->old_jiffies +
+				     msecs_to_jiffies(repeat_filter))) {
+			ati_remote->repeat_count++;
+		} else {
+			ati_remote->repeat_count = 0;
+			ati_remote->first_jiffies = now;
+		}
+
+		ati_remote->old_data = data[2];
+		ati_remote->old_jiffies = now;
+
+		/* Ensure we skip at least the 4 first duplicate events (generated
+		 * by a single keypress), and continue skipping until repeat_delay
+		 * msecs have passed
+		 */
+		if (ati_remote->repeat_count > 0 &&
+		    (ati_remote->repeat_count < 5 ||
+		     time_before(now, ati_remote->first_jiffies +
+				      msecs_to_jiffies(repeat_delay))))
+			return;
+
+		if (index < 0) {
+			/* Not a mouse event, hand it to rc-core. */
+
+			/*
+			 * We don't use the rc-core repeat handling yet as
+			 * it would cause ghost repeats which would be a
+			 * regression for this driver.
+			 */
+			rc_keydown_notimeout(ati_remote->rdev, scancode,
+					     data[2]);
+			rc_keyup(ati_remote->rdev);
+			return;
+		}
+
+		input_event(dev, ati_remote_tbl[index].type,
+			ati_remote_tbl[index].code, 1);
+		input_sync(dev);
+		input_event(dev, ati_remote_tbl[index].type,
+			ati_remote_tbl[index].code, 0);
+		input_sync(dev);
+
+	} else {
+
+		/*
+		 * Other event kinds are from the directional control pad, and have an
+		 * acceleration factor applied to them.  Without this acceleration, the
+		 * control pad is mostly unusable.
+		 */
+		acc = ati_remote_compute_accel(ati_remote);
+
+		switch (ati_remote_tbl[index].kind) {
+		case KIND_ACCEL:
+			input_event(dev, ati_remote_tbl[index].type,
+				ati_remote_tbl[index].code,
+				ati_remote_tbl[index].value * acc);
+			break;
+		case KIND_LU:
+			input_report_rel(dev, REL_X, -acc);
+			input_report_rel(dev, REL_Y, -acc);
+			break;
+		case KIND_RU:
+			input_report_rel(dev, REL_X, acc);
+			input_report_rel(dev, REL_Y, -acc);
+			break;
+		case KIND_LD:
+			input_report_rel(dev, REL_X, -acc);
+			input_report_rel(dev, REL_Y, acc);
+			break;
+		case KIND_RD:
+			input_report_rel(dev, REL_X, acc);
+			input_report_rel(dev, REL_Y, acc);
+			break;
+		default:
+			dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n",
+				ati_remote_tbl[index].kind);
+		}
+		input_sync(dev);
+
+		ati_remote->old_jiffies = jiffies;
+		ati_remote->old_data = data[2];
+	}
+}
+
+/*
+ *	ati_remote_irq_in
+ */
+static void ati_remote_irq_in(struct urb *urb)
+{
+	struct ati_remote *ati_remote = urb->context;
+	int retval;
+
+	switch (urb->status) {
+	case 0:			/* success */
+		ati_remote_input_report(urb);
+		break;
+	case -ECONNRESET:	/* unlink */
+	case -ENOENT:
+	case -ESHUTDOWN:
+		dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n",
+			__func__);
+		return;
+	default:		/* error */
+		dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n",
+			__func__, urb->status);
+	}
+
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+	if (retval)
+		dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n",
+			__func__, retval);
+}
+
+/*
+ *	ati_remote_alloc_buffers
+ */
+static int ati_remote_alloc_buffers(struct usb_device *udev,
+				    struct ati_remote *ati_remote)
+{
+	ati_remote->inbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC,
+					       &ati_remote->inbuf_dma);
+	if (!ati_remote->inbuf)
+		return -1;
+
+	ati_remote->outbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC,
+						&ati_remote->outbuf_dma);
+	if (!ati_remote->outbuf)
+		return -1;
+
+	ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ati_remote->irq_urb)
+		return -1;
+
+	ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ati_remote->out_urb)
+		return -1;
+
+	return 0;
+}
+
+/*
+ *	ati_remote_free_buffers
+ */
+static void ati_remote_free_buffers(struct ati_remote *ati_remote)
+{
+	usb_free_urb(ati_remote->irq_urb);
+	usb_free_urb(ati_remote->out_urb);
+
+	usb_free_coherent(ati_remote->udev, DATA_BUFSIZE,
+		ati_remote->inbuf, ati_remote->inbuf_dma);
+
+	usb_free_coherent(ati_remote->udev, DATA_BUFSIZE,
+		ati_remote->outbuf, ati_remote->outbuf_dma);
+}
+
+static void ati_remote_input_init(struct ati_remote *ati_remote)
+{
+	struct input_dev *idev = ati_remote->idev;
+	int i;
+
+	idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+	idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+		BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
+	idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+	for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++)
+		if (ati_remote_tbl[i].type == EV_KEY)
+			set_bit(ati_remote_tbl[i].code, idev->keybit);
+
+	input_set_drvdata(idev, ati_remote);
+
+	idev->open = ati_remote_input_open;
+	idev->close = ati_remote_input_close;
+
+	idev->name = ati_remote->mouse_name;
+	idev->phys = ati_remote->mouse_phys;
+
+	usb_to_input_id(ati_remote->udev, &idev->id);
+	idev->dev.parent = &ati_remote->interface->dev;
+}
+
+static void ati_remote_rc_init(struct ati_remote *ati_remote)
+{
+	struct rc_dev *rdev = ati_remote->rdev;
+
+	rdev->priv = ati_remote;
+	rdev->driver_type = RC_DRIVER_SCANCODE;
+	rdev->allowed_protos = RC_TYPE_OTHER;
+	rdev->driver_name = "ati_remote";
+
+	rdev->open = ati_remote_rc_open;
+	rdev->close = ati_remote_rc_close;
+
+	rdev->input_name = ati_remote->rc_name;
+	rdev->input_phys = ati_remote->rc_phys;
+
+	usb_to_input_id(ati_remote->udev, &rdev->input_id);
+	rdev->dev.parent = &ati_remote->interface->dev;
+}
+
+static int ati_remote_initialize(struct ati_remote *ati_remote)
+{
+	struct usb_device *udev = ati_remote->udev;
+	int pipe, maxp;
+
+	init_waitqueue_head(&ati_remote->wait);
+
+	/* Set up irq_urb */
+	pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress);
+	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+	maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp;
+
+	usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf,
+			 maxp, ati_remote_irq_in, ati_remote,
+			 ati_remote->endpoint_in->bInterval);
+	ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma;
+	ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	/* Set up out_urb */
+	pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress);
+	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+	maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp;
+
+	usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf,
+			 maxp, ati_remote_irq_out, ati_remote,
+			 ati_remote->endpoint_out->bInterval);
+	ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma;
+	ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	/* send initialization strings */
+	if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) ||
+	    (ati_remote_sendpacket(ati_remote, 0x8007, init2))) {
+		dev_err(&ati_remote->interface->dev,
+			 "Initializing ati_remote hardware failed.\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/*
+ *	ati_remote_probe
+ */
+static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	struct usb_host_interface *iface_host = interface->cur_altsetting;
+	struct usb_endpoint_descriptor *endpoint_in, *endpoint_out;
+	struct ati_remote *ati_remote;
+	struct input_dev *input_dev;
+	struct rc_dev *rc_dev;
+	int err = -ENOMEM;
+
+	if (iface_host->desc.bNumEndpoints != 2) {
+		err("%s: Unexpected desc.bNumEndpoints\n", __func__);
+		return -ENODEV;
+	}
+
+	endpoint_in = &iface_host->endpoint[0].desc;
+	endpoint_out = &iface_host->endpoint[1].desc;
+
+	if (!usb_endpoint_is_int_in(endpoint_in)) {
+		err("%s: Unexpected endpoint_in\n", __func__);
+		return -ENODEV;
+	}
+	if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) {
+		err("%s: endpoint_in message size==0? \n", __func__);
+		return -ENODEV;
+	}
+
+	ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL);
+	rc_dev = rc_allocate_device();
+	if (!ati_remote || !rc_dev)
+		goto fail1;
+
+	/* Allocate URB buffers, URBs */
+	if (ati_remote_alloc_buffers(udev, ati_remote))
+		goto fail2;
+
+	ati_remote->endpoint_in = endpoint_in;
+	ati_remote->endpoint_out = endpoint_out;
+	ati_remote->udev = udev;
+	ati_remote->rdev = rc_dev;
+	ati_remote->interface = interface;
+
+	usb_make_path(udev, ati_remote->rc_phys, sizeof(ati_remote->rc_phys));
+	strlcpy(ati_remote->mouse_phys, ati_remote->rc_phys,
+		sizeof(ati_remote->mouse_phys));
+
+	strlcat(ati_remote->rc_phys, "/input0", sizeof(ati_remote->rc_phys));
+	strlcat(ati_remote->mouse_phys, "/input1", sizeof(ati_remote->mouse_phys));
+
+	if (udev->manufacturer)
+		strlcpy(ati_remote->rc_name, udev->manufacturer,
+			sizeof(ati_remote->rc_name));
+
+	if (udev->product)
+		snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name),
+			 "%s %s", ati_remote->rc_name, udev->product);
+
+	if (!strlen(ati_remote->rc_name))
+		snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name),
+			DRIVER_DESC "(%04x,%04x)",
+			le16_to_cpu(ati_remote->udev->descriptor.idVendor),
+			le16_to_cpu(ati_remote->udev->descriptor.idProduct));
+
+	snprintf(ati_remote->mouse_name, sizeof(ati_remote->mouse_name),
+		 "%s mouse", ati_remote->rc_name);
+
+	if (id->driver_info)
+		rc_dev->map_name = (const char *)id->driver_info;
+	else
+		rc_dev->map_name = RC_MAP_ATI_X10;
+
+	ati_remote_rc_init(ati_remote);
+	mutex_init(&ati_remote->open_mutex);
+
+	/* Device Hardware Initialization - fills in ati_remote->idev from udev. */
+	err = ati_remote_initialize(ati_remote);
+	if (err)
+		goto fail3;
+
+	/* Set up and register rc device */
+	err = rc_register_device(ati_remote->rdev);
+	if (err)
+		goto fail3;
+
+	/* use our delay for rc_dev */
+	ati_remote->rdev->input_dev->rep[REP_DELAY] = repeat_delay;
+
+	/* Set up and register mouse input device */
+	if (mouse) {
+		input_dev = input_allocate_device();
+		if (!input_dev)
+			goto fail4;
+
+		ati_remote->idev = input_dev;
+		ati_remote_input_init(ati_remote);
+		err = input_register_device(input_dev);
+
+		if (err)
+			goto fail5;
+	}
+
+	usb_set_intfdata(interface, ati_remote);
+	return 0;
+
+ fail5:	input_free_device(input_dev);
+ fail4:	rc_unregister_device(rc_dev);
+	rc_dev = NULL;
+ fail3:	usb_kill_urb(ati_remote->irq_urb);
+	usb_kill_urb(ati_remote->out_urb);
+ fail2:	ati_remote_free_buffers(ati_remote);
+ fail1:	rc_free_device(rc_dev);
+	kfree(ati_remote);
+	return err;
+}
+
+/*
+ *	ati_remote_disconnect
+ */
+static void ati_remote_disconnect(struct usb_interface *interface)
+{
+	struct ati_remote *ati_remote;
+
+	ati_remote = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+	if (!ati_remote) {
+		dev_warn(&interface->dev, "%s - null device?\n", __func__);
+		return;
+	}
+
+	usb_kill_urb(ati_remote->irq_urb);
+	usb_kill_urb(ati_remote->out_urb);
+	if (ati_remote->idev)
+		input_unregister_device(ati_remote->idev);
+	rc_unregister_device(ati_remote->rdev);
+	ati_remote_free_buffers(ati_remote);
+	kfree(ati_remote);
+}
+
+/*
+ *	ati_remote_init
+ */
+static int __init ati_remote_init(void)
+{
+	int result;
+
+	result = usb_register(&ati_remote_driver);
+	if (result)
+		printk(KERN_ERR KBUILD_MODNAME
+		       ": usb_register error #%d\n", result);
+	else
+		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+		       DRIVER_DESC "\n");
+
+	return result;
+}
+
+/*
+ *	ati_remote_exit
+ */
+static void __exit ati_remote_exit(void)
+{
+	usb_deregister(&ati_remote_driver);
+}
+
+/*
+ *	module specification
+ */
+
+module_init(ati_remote_init);
+module_exit(ati_remote_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/media/rc/ene_ir.c linux-libre-3.2-gnu/drivers/media/rc/ene_ir.c
--- linux-libre-3.1-gnu/drivers/media/rc/ene_ir.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/ene_ir.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pnp.h>
@@ -118,31 +120,31 @@
 			dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 2 : 4;
 
 	if (hw_revision == 0xFF) {
-		ene_warn("device seems to be disabled");
-		ene_warn("send a mail to lirc-list@lists.sourceforge.net");
-		ene_warn("please attach output of acpidump and dmidecode");
+		pr_warn("device seems to be disabled\n");
+		pr_warn("send a mail to lirc-list@lists.sourceforge.net\n");
+		pr_warn("please attach output of acpidump and dmidecode\n");
 		return -ENODEV;
 	}
 
-	ene_notice("chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x",
-		chip_major, chip_minor, old_ver, hw_revision);
+	pr_notice("chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x\n",
+		  chip_major, chip_minor, old_ver, hw_revision);
 
-	ene_notice("PLL freq = %d", dev->pll_freq);
+	pr_notice("PLL freq = %d\n", dev->pll_freq);
 
 	if (chip_major == 0x33) {
-		ene_warn("chips 0x33xx aren't supported");
+		pr_warn("chips 0x33xx aren't supported\n");
 		return -ENODEV;
 	}
 
 	if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) {
 		dev->hw_revision = ENE_HW_C;
-		ene_notice("KB3926C detected");
+		pr_notice("KB3926C detected\n");
 	} else if (old_ver == 0x24 && hw_revision == 0xC0) {
 		dev->hw_revision = ENE_HW_B;
-		ene_notice("KB3926B detected");
+		pr_notice("KB3926B detected\n");
 	} else {
 		dev->hw_revision = ENE_HW_D;
-		ene_notice("KB3926D or higher detected");
+		pr_notice("KB3926D or higher detected\n");
 	}
 
 	/* detect features hardware supports */
@@ -152,7 +154,7 @@
 	fw_reg1 = ene_read_reg(dev, ENE_FW1);
 	fw_reg2 = ene_read_reg(dev, ENE_FW2);
 
-	ene_notice("Firmware regs: %02x %02x", fw_reg1, fw_reg2);
+	pr_notice("Firmware regs: %02x %02x\n", fw_reg1, fw_reg2);
 
 	dev->hw_use_gpio_0a = !!(fw_reg2 & ENE_FW2_GP0A);
 	dev->hw_learning_and_tx_capable = !!(fw_reg2 & ENE_FW2_LEARNING);
@@ -161,30 +163,29 @@
 	if (dev->hw_learning_and_tx_capable)
 		dev->hw_fan_input = !!(fw_reg2 & ENE_FW2_FAN_INPUT);
 
-	ene_notice("Hardware features:");
+	pr_notice("Hardware features:\n");
 
 	if (dev->hw_learning_and_tx_capable) {
-		ene_notice("* Supports transmitting & learning mode");
-		ene_notice("   This feature is rare and therefore,");
-		ene_notice("   you are welcome to test it,");
-		ene_notice("   and/or contact the author via:");
-		ene_notice("   lirc-list@lists.sourceforge.net");
-		ene_notice("   or maximlevitsky@gmail.com");
+		pr_notice("* Supports transmitting & learning mode\n");
+		pr_notice("   This feature is rare and therefore,\n");
+		pr_notice("   you are welcome to test it,\n");
+		pr_notice("   and/or contact the author via:\n");
+		pr_notice("   lirc-list@lists.sourceforge.net\n");
+		pr_notice("   or maximlevitsky@gmail.com\n");
 
-		ene_notice("* Uses GPIO %s for IR raw input",
-			dev->hw_use_gpio_0a ? "40" : "0A");
+		pr_notice("* Uses GPIO %s for IR raw input\n",
+			  dev->hw_use_gpio_0a ? "40" : "0A");
 
 		if (dev->hw_fan_input)
-			ene_notice("* Uses unused fan feedback input as source"
-					" of demodulated IR data");
+			pr_notice("* Uses unused fan feedback input as source of demodulated IR data\n");
 	}
 
 	if (!dev->hw_fan_input)
-		ene_notice("* Uses GPIO %s for IR demodulated input",
-			dev->hw_use_gpio_0a ? "0A" : "40");
+		pr_notice("* Uses GPIO %s for IR demodulated input\n",
+			  dev->hw_use_gpio_0a ? "0A" : "40");
 
 	if (dev->hw_extra_buffer)
-		ene_notice("* Uses new style input buffer");
+		pr_notice("* Uses new style input buffer\n");
 	return 0;
 }
 
@@ -215,13 +216,13 @@
 
 	dev->buffer_len = dev->extra_buf1_len + dev->extra_buf2_len + 8;
 
-	ene_notice("Hardware uses 2 extended buffers:");
-	ene_notice("  0x%04x - len : %d", dev->extra_buf1_address,
-						dev->extra_buf1_len);
-	ene_notice("  0x%04x - len : %d", dev->extra_buf2_address,
-						dev->extra_buf2_len);
+	pr_notice("Hardware uses 2 extended buffers:\n");
+	pr_notice("  0x%04x - len : %d\n",
+		  dev->extra_buf1_address, dev->extra_buf1_len);
+	pr_notice("  0x%04x - len : %d\n",
+		  dev->extra_buf2_address, dev->extra_buf2_len);
 
-	ene_notice("Total buffer len = %d", dev->buffer_len);
+	pr_notice("Total buffer len = %d\n", dev->buffer_len);
 
 	if (dev->buffer_len > 64 || dev->buffer_len < 16)
 		goto error;
@@ -240,7 +241,7 @@
 	ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
 	return;
 error:
-	ene_warn("Error validating extra buffers, device probably won't work");
+	pr_warn("Error validating extra buffers, device probably won't work\n");
 	dev->hw_extra_buffer = false;
 	ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
 }
@@ -588,7 +589,7 @@
 		dbg("TX: Transmitter #2 is connected");
 
 	if (!(fwreg2 & (ENE_FW2_EMMITER1_CONN | ENE_FW2_EMMITER2_CONN)))
-		ene_warn("TX: transmitter cable isn't connected!");
+		pr_warn("TX: transmitter cable isn't connected!\n");
 
 	/* disable receive on revc */
 	if (dev->hw_revision == ENE_HW_C)
@@ -615,7 +616,7 @@
 	bool pulse = dev->tx_sample_pulse;
 
 	if (!dev->tx_buffer) {
-		ene_warn("TX: BUG: attempt to transmit NULL buffer");
+		pr_warn("TX: BUG: attempt to transmit NULL buffer\n");
 		return;
 	}
 
@@ -1049,7 +1050,7 @@
 		dev->hw_learning_and_tx_capable = true;
 		setup_timer(&dev->tx_sim_timer, ene_tx_irqsim,
 						(long unsigned int)dev);
-		ene_warn("Simulation of TX activated");
+		pr_warn("Simulation of TX activated\n");
 	}
 
 	if (!dev->hw_learning_and_tx_capable)
@@ -1089,7 +1090,7 @@
 	if (error < 0)
 		goto error;
 
-	ene_notice("driver has been successfully loaded");
+	pr_notice("driver has been successfully loaded\n");
 	return 0;
 error:
 	if (dev && dev->irq >= 0)
diff -druN linux-libre-3.1-gnu/drivers/media/rc/ene_ir.h linux-libre-3.2-gnu/drivers/media/rc/ene_ir.h
--- linux-libre-3.1-gnu/drivers/media/rc/ene_ir.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/ene_ir.h	2012-01-04 18:55:44.000000000 -0500
@@ -182,20 +182,11 @@
 #define  ENE_HW_C		2	/* 3926C */
 #define  ENE_HW_D		3	/* 3926D or later */
 
-#define ene_printk(level, text, ...) \
-	printk(level ENE_DRIVER_NAME ": " text "\n", ## __VA_ARGS__)
-
-#define ene_notice(text, ...) ene_printk(KERN_NOTICE, text, ## __VA_ARGS__)
-#define ene_warn(text, ...) ene_printk(KERN_WARNING, text, ## __VA_ARGS__)
-
-
-#define __dbg(level, format, ...) \
-	do { \
-		if (debug >= level) \
-			printk(KERN_DEBUG ENE_DRIVER_NAME \
-				": " format "\n", ## __VA_ARGS__); \
-	} while (0)
-
+#define __dbg(level, format, ...)				\
+do {								\
+	if (debug >= level)					\
+		pr_debug(format "\n", ## __VA_ARGS__);		\
+} while (0)
 
 #define dbg(format, ...)		__dbg(1, format, ## __VA_ARGS__)
 #define dbg_verbose(format, ...)	__dbg(2, format, ## __VA_ARGS__)
diff -druN linux-libre-3.1-gnu/drivers/media/rc/imon.c linux-libre-3.2-gnu/drivers/media/rc/imon.c
--- linux-libre-3.1-gnu/drivers/media/rc/imon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/imon.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+#include <linux/ratelimit.h>
 
 #include <linux/input.h>
 #include <linux/usb.h>
@@ -516,19 +517,19 @@
 	if (retval) {
 		ictx->tx.busy = false;
 		smp_rmb(); /* ensure later readers know we're not busy */
-		pr_err("error submitting urb(%d)\n", retval);
+		pr_err_ratelimited("error submitting urb(%d)\n", retval);
 	} else {
 		/* Wait for transmission to complete (or abort) */
 		mutex_unlock(&ictx->lock);
 		retval = wait_for_completion_interruptible(
 				&ictx->tx.finished);
 		if (retval)
-			pr_err("task interrupted\n");
+			pr_err_ratelimited("task interrupted\n");
 		mutex_lock(&ictx->lock);
 
 		retval = ictx->tx.status;
 		if (retval)
-			pr_err("packet tx failed (%d)\n", retval);
+			pr_err_ratelimited("packet tx failed (%d)\n", retval);
 	}
 
 	kfree(control_req);
@@ -830,20 +831,20 @@
 
 	ictx = file->private_data;
 	if (!ictx) {
-		pr_err("no context for device\n");
+		pr_err_ratelimited("no context for device\n");
 		return -ENODEV;
 	}
 
 	mutex_lock(&ictx->lock);
 
 	if (!ictx->dev_present_intf0) {
-		pr_err("no iMON device present\n");
+		pr_err_ratelimited("no iMON device present\n");
 		retval = -ENODEV;
 		goto exit;
 	}
 
 	if (n_bytes <= 0 || n_bytes > 32) {
-		pr_err("invalid payload size\n");
+		pr_err_ratelimited("invalid payload size\n");
 		retval = -EINVAL;
 		goto exit;
 	}
@@ -869,7 +870,7 @@
 
 		retval = send_packet(ictx);
 		if (retval) {
-			pr_err("send packet failed for packet #%d\n", seq / 2);
+			pr_err_ratelimited("send packet #%d failed\n", seq / 2);
 			goto exit;
 		} else {
 			seq += 2;
@@ -883,7 +884,7 @@
 	ictx->usb_tx_buf[7] = (unsigned char) seq;
 	retval = send_packet(ictx);
 	if (retval)
-		pr_err("send packet failed for packet #%d\n", seq / 2);
+		pr_err_ratelimited("send packet #%d failed\n", seq / 2);
 
 exit:
 	mutex_unlock(&ictx->lock);
@@ -912,20 +913,21 @@
 
 	ictx = file->private_data;
 	if (!ictx) {
-		pr_err("no context for device\n");
+		pr_err_ratelimited("no context for device\n");
 		return -ENODEV;
 	}
 
 	mutex_lock(&ictx->lock);
 
 	if (!ictx->display_supported) {
-		pr_err("no iMON display present\n");
+		pr_err_ratelimited("no iMON display present\n");
 		retval = -ENODEV;
 		goto exit;
 	}
 
 	if (n_bytes != 8) {
-		pr_err("invalid payload size: %d (expected 8)\n", (int)n_bytes);
+		pr_err_ratelimited("invalid payload size: %d (expected 8)\n",
+				   (int)n_bytes);
 		retval = -EINVAL;
 		goto exit;
 	}
@@ -937,7 +939,7 @@
 
 	retval = send_packet(ictx);
 	if (retval) {
-		pr_err("send packet failed!\n");
+		pr_err_ratelimited("send packet failed!\n");
 		goto exit;
 	} else {
 		dev_dbg(ictx->dev, "%s: write %d bytes to LCD\n",
@@ -1656,7 +1658,7 @@
 		return;
 
 	ictx = (struct imon_context *)urb->context;
-	if (!ictx)
+	if (!ictx || !ictx->dev_present_intf0)
 		return;
 
 	switch (urb->status) {
@@ -1688,7 +1690,7 @@
 		return;
 
 	ictx = (struct imon_context *)urb->context;
-	if (!ictx)
+	if (!ictx || !ictx->dev_present_intf1)
 		return;
 
 	switch (urb->status) {
@@ -2116,7 +2118,6 @@
 
 	ictx->dev = dev;
 	ictx->usbdev_intf0 = usb_get_dev(interface_to_usbdev(intf));
-	ictx->dev_present_intf0 = true;
 	ictx->rx_urb_intf0 = rx_urb;
 	ictx->tx_urb = tx_urb;
 	ictx->rf_device = false;
@@ -2155,6 +2156,8 @@
 		goto rdev_setup_failed;
 	}
 
+	ictx->dev_present_intf0 = true;
+
 	mutex_unlock(&ictx->lock);
 	return ictx;
 
@@ -2198,7 +2201,6 @@
 	}
 
 	ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf));
-	ictx->dev_present_intf1 = true;
 	ictx->rx_urb_intf1 = rx_urb;
 
 	ret = -ENODEV;
@@ -2227,6 +2229,8 @@
 		goto urb_submit_failed;
 	}
 
+	ictx->dev_present_intf1 = true;
+
 	mutex_unlock(&ictx->lock);
 	return ictx;
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/ir-jvc-decoder.c linux-libre-3.2-gnu/drivers/media/rc/ir-jvc-decoder.c
--- linux-libre-3.1-gnu/drivers/media/rc/ir-jvc-decoder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/ir-jvc-decoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  */
 
 #include <linux/bitrev.h>
+#include <linux/module.h>
 #include "rc-core-priv.h"
 
 #define JVC_NBITS		16		/* dev(8) + func(8) */
diff -druN linux-libre-3.1-gnu/drivers/media/rc/ir-lirc-codec.c linux-libre-3.2-gnu/drivers/media/rc/ir-lirc-codec.c
--- linux-libre-3.1-gnu/drivers/media/rc/ir-lirc-codec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/ir-lirc-codec.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 
 #include <linux/sched.h>
 #include <linux/wait.h>
+#include <linux/module.h>
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
 #include <media/rc-core.h>
@@ -98,7 +99,7 @@
 	return 0;
 }
 
-static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf,
+static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
 				   size_t n, loff_t *ppos)
 {
 	struct lirc_codec *lirc;
@@ -140,10 +141,11 @@
 }
 
 static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
-			unsigned long __user arg)
+			unsigned long arg)
 {
 	struct lirc_codec *lirc;
 	struct rc_dev *dev;
+	u32 __user *argp = (u32 __user *)(arg);
 	int ret = 0;
 	__u32 val = 0, tmp;
 
@@ -156,7 +158,7 @@
 		return -EFAULT;
 
 	if (_IOC_DIR(cmd) & _IOC_WRITE) {
-		ret = get_user(val, (__u32 *)arg);
+		ret = get_user(val, argp);
 		if (ret)
 			return ret;
 	}
@@ -265,7 +267,7 @@
 	}
 
 	if (_IOC_DIR(cmd) & _IOC_READ)
-		ret = put_user(val, (__u32 *)arg);
+		ret = put_user(val, argp);
 
 	return ret;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/rc/ir-nec-decoder.c linux-libre-3.2-gnu/drivers/media/rc/ir-nec-decoder.c
--- linux-libre-3.1-gnu/drivers/media/rc/ir-nec-decoder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/ir-nec-decoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  */
 
 #include <linux/bitrev.h>
+#include <linux/module.h>
 #include "rc-core-priv.h"
 
 #define NEC_NBITS		32
diff -druN linux-libre-3.1-gnu/drivers/media/rc/ir-raw.c linux-libre-3.2-gnu/drivers/media/rc/ir-raw.c
--- linux-libre-3.1-gnu/drivers/media/rc/ir-raw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/ir-raw.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,8 +12,10 @@
  *  GNU General Public License for more details.
  */
 
+#include <linux/export.h>
 #include <linux/kthread.h>
 #include <linux/mutex.h>
+#include <linux/kmod.h>
 #include <linux/sched.h>
 #include <linux/freezer.h>
 #include "rc-core-priv.h"
diff -druN linux-libre-3.1-gnu/drivers/media/rc/ir-rc5-decoder.c linux-libre-3.2-gnu/drivers/media/rc/ir-rc5-decoder.c
--- linux-libre-3.1-gnu/drivers/media/rc/ir-rc5-decoder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/ir-rc5-decoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include "rc-core-priv.h"
+#include <linux/module.h>
 
 #define RC5_NBITS		14
 #define RC5X_NBITS		20
diff -druN linux-libre-3.1-gnu/drivers/media/rc/ir-rc5-sz-decoder.c linux-libre-3.2-gnu/drivers/media/rc/ir-rc5-sz-decoder.c
--- linux-libre-3.1-gnu/drivers/media/rc/ir-rc5-sz-decoder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/ir-rc5-sz-decoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
  */
 
 #include "rc-core-priv.h"
+#include <linux/module.h>
 
 #define RC5_SZ_NBITS		15
 #define RC5_UNIT		888888 /* ns */
diff -druN linux-libre-3.1-gnu/drivers/media/rc/ir-rc6-decoder.c linux-libre-3.2-gnu/drivers/media/rc/ir-rc6-decoder.c
--- linux-libre-3.1-gnu/drivers/media/rc/ir-rc6-decoder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/ir-rc6-decoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  */
 
 #include "rc-core-priv.h"
+#include <linux/module.h>
 
 /*
  * This decoder currently supports:
diff -druN linux-libre-3.1-gnu/drivers/media/rc/ir-sony-decoder.c linux-libre-3.2-gnu/drivers/media/rc/ir-sony-decoder.c
--- linux-libre-3.1-gnu/drivers/media/rc/ir-sony-decoder.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/ir-sony-decoder.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  */
 
 #include <linux/bitrev.h>
+#include <linux/module.h>
 #include "rc-core-priv.h"
 
 #define SONY_UNIT		600000 /* ns */
diff -druN linux-libre-3.1-gnu/drivers/media/rc/Kconfig linux-libre-3.2-gnu/drivers/media/rc/Kconfig
--- linux-libre-3.1-gnu/drivers/media/rc/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -4,8 +4,8 @@
 	default INPUT
 	---help---
 	  Enable support for Remote Controllers on Linux. This is
-	  needed in order to support several video capture adapters.
-	  Currently, all supported devices use InfraRed.
+	  needed in order to support several video capture adapters,
+	  standalone IR receivers/transmitters, and RF receivers.
 
 	  Enable this option if you have a video capture board even
 	  if you don't need IR, as otherwise, you may not be able to
@@ -108,6 +108,25 @@
 	   Enable this option to pass raw IR to and from userspace via
 	   the LIRC interface.
 
+config RC_ATI_REMOTE
+	tristate "ATI / X10 based USB RF remote controls"
+	depends on USB_ARCH_HAS_HCD
+	depends on RC_CORE
+	select USB
+	help
+	   Say Y here if you want to use an X10 based USB remote control.
+	   These are RF remotes with USB receivers.
+
+	   Such devices include the ATI remote that comes with many of ATI's
+	   All-In-Wonder video cards, the X10 "Lola" remote, NVIDIA RF remote,
+	   Medion RF remote, and SnapStream FireFly remote.
+
+	   This driver provides mouse pointer, left and right mouse buttons,
+	   and maps all the other remote buttons to keypress events.
+
+	   To compile this driver as a module, choose M here: the module will be
+	   called ati_remote.
+
 config IR_ENE
 	tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)"
 	depends on PNP
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/Makefile linux-libre-3.2-gnu/drivers/media/rc/keymaps/Makefile
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,6 +4,7 @@
 			rc-apac-viewcomp.o \
 			rc-asus-pc39.o \
 			rc-ati-tv-wonder-hd-600.o \
+			rc-ati-x10.o \
 			rc-avermedia-a16d.o \
 			rc-avermedia.o \
 			rc-avermedia-cardbus.o \
@@ -47,6 +48,7 @@
 			rc-lirc.o \
 			rc-lme2510.o \
 			rc-manli.o \
+			rc-medion-x10.o \
 			rc-msi-digivox-ii.o \
 			rc-msi-digivox-iii.o \
 			rc-msi-tvanywhere.o \
@@ -70,6 +72,7 @@
 			rc-hauppauge.o \
 			rc-rc6-mce.o \
 			rc-real-audio-220-32-keys.o \
+			rc-snapstream-firefly.o \
 			rc-streamzap.o \
 			rc-tbs-nec.o \
 			rc-technisat-usb2.o \
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* ADS Tech Instant TV DVB-T PCI Remote */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-alink-dtu-m.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-alink-dtu-m.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-alink-dtu-m.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-alink-dtu-m.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* A-Link DTU(m) slim remote, 6 rows, 3 columns. */
 static struct rc_map_table alink_dtu_m[] = {
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-anysee.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-anysee.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-anysee.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-anysee.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table anysee[] = {
 	{ 0x0800, KEY_0 },
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-apac-viewcomp.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-apac-viewcomp.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-apac-viewcomp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-apac-viewcomp.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Attila Kondoros <attila.kondoros@chello.hu> */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-asus-pc39.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-asus-pc39.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-asus-pc39.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-asus-pc39.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Marc Fargas <telenieko@telenieko.com>
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* ATI TV Wonder HD 600 USB
    Devin Heitmueller <devin.heitmueller@gmail.com>
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-ati-x10.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-ati-x10.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-ati-x10.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-ati-x10.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,104 @@
+/*
+ * ATI X10 RF remote keytable
+ *
+ * Copyright (C) 2011 Anssi Hannula <anssi.hannula@?ki.fi>
+ *
+ * This file is based on the static generic keytable previously found in
+ * ati_remote.c, which is
+ * Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net>
+ * Copyright (c) 2002 Vladimir Dergachev
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/module.h>
+#include <media/rc-map.h>
+
+static struct rc_map_table ati_x10[] = {
+	{ 0x0d, KEY_1 },
+	{ 0x0e, KEY_2 },
+	{ 0x0f, KEY_3 },
+	{ 0x10, KEY_4 },
+	{ 0x11, KEY_5 },
+	{ 0x12, KEY_6 },
+	{ 0x13, KEY_7 },
+	{ 0x14, KEY_8 },
+	{ 0x15, KEY_9 },
+	{ 0x17, KEY_0 },
+	{ 0x00, KEY_A },
+	{ 0x01, KEY_B },
+	{ 0x19, KEY_C },
+	{ 0x1b, KEY_D },
+	{ 0x21, KEY_E },
+	{ 0x23, KEY_F },
+
+	{ 0x18, KEY_KPENTER },    /* "check" */
+	{ 0x16, KEY_MENU },       /* "menu" */
+	{ 0x02, KEY_POWER },      /* Power */
+	{ 0x03, KEY_TV },         /* TV */
+	{ 0x04, KEY_DVD },        /* DVD */
+	{ 0x05, KEY_WWW },        /* WEB */
+	{ 0x06, KEY_BOOKMARKS },  /* "book" */
+	{ 0x07, KEY_EDIT },       /* "hand" */
+	{ 0x1c, KEY_COFFEE },     /* "timer" */
+	{ 0x20, KEY_FRONT },      /* "max" */
+	{ 0x1d, KEY_LEFT },       /* left */
+	{ 0x1f, KEY_RIGHT },      /* right */
+	{ 0x22, KEY_DOWN },       /* down */
+	{ 0x1a, KEY_UP },         /* up */
+	{ 0x1e, KEY_OK },         /* "OK" */
+	{ 0x09, KEY_VOLUMEDOWN }, /* VOL + */
+	{ 0x08, KEY_VOLUMEUP },   /* VOL - */
+	{ 0x0a, KEY_MUTE },       /* MUTE  */
+	{ 0x0b, KEY_CHANNELUP },  /* CH + */
+	{ 0x0c, KEY_CHANNELDOWN },/* CH - */
+	{ 0x27, KEY_RECORD },     /* ( o) red */
+	{ 0x25, KEY_PLAY },       /* ( >) */
+	{ 0x24, KEY_REWIND },     /* (<<) */
+	{ 0x26, KEY_FORWARD },    /* (>>) */
+	{ 0x28, KEY_STOP },       /* ([]) */
+	{ 0x29, KEY_PAUSE },      /* ('') */
+	{ 0x2b, KEY_PREVIOUS },   /* (<-) */
+	{ 0x2a, KEY_NEXT },       /* (>+) */
+	{ 0x2d, KEY_INFO },       /* PLAYING */
+	{ 0x2e, KEY_HOME },       /* TOP */
+	{ 0x2f, KEY_END },        /* END */
+	{ 0x30, KEY_SELECT },     /* SELECT */
+};
+
+static struct rc_map_list ati_x10_map = {
+	.map = {
+		.scan    = ati_x10,
+		.size    = ARRAY_SIZE(ati_x10),
+		.rc_type = RC_TYPE_OTHER,
+		.name    = RC_MAP_ATI_X10,
+	}
+};
+
+static int __init init_rc_map_ati_x10(void)
+{
+	return rc_map_register(&ati_x10_map);
+}
+
+static void __exit exit_rc_map_ati_x10(void)
+{
+	rc_map_unregister(&ati_x10_map);
+}
+
+module_init(init_rc_map_ati_x10)
+module_exit(exit_rc_map_ati_x10)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-avermedia-a16d.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-avermedia-a16d.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-avermedia-a16d.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-avermedia-a16d.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table avermedia_a16d[] = {
 	{ 0x20, KEY_LIST},
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-avermedia.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-avermedia.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-avermedia.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-avermedia.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Alex Hermann <gaaf@gmx.net> */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-avermedia-cardbus.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-avermedia-cardbus.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-avermedia-cardbus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-avermedia-cardbus.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Oldrich Jedlicka <oldium.pro@seznam.cz> */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-avermedia-dvbt.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-avermedia-dvbt.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-avermedia-dvbt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-avermedia-dvbt.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Matt Jesson <dvb@jesson.eclipse.co.uk */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-avermedia-m135a.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-avermedia-m135a.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-avermedia-m135a.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-avermedia-m135a.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Avermedia M135A with RM-JX and RM-K6 remote controls
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Avermedia M733A with IR model RM-K6
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Initial keytable is from Jose Alberto Reguero <jareguero@telefonica.net>
    and Felipe Morales Moreno <felipe.morales.moreno@gmail.com> */
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-avertv-303.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-avertv-303.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-avertv-303.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-avertv-303.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* AVERTV STUDIO 303 Remote */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table azurewave_ad_tu700[] = {
 	{ 0x0000, KEY_TAB },             /* Tab */
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-behold.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-behold.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-behold.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-behold.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Igor Kuznetsov <igk72@ya.ru>
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-behold-columbus.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-behold-columbus.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-behold-columbus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-behold-columbus.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Beholder Intl. Ltd. 2008
  * Dmitry Belimov d.belimov@google.com
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-budget-ci-old.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-budget-ci-old.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-budget-ci-old.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-budget-ci-old.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * From reading the following remotes:
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-cinergy-1400.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-cinergy-1400.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-cinergy-1400.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-cinergy-1400.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Cinergy 1400 DVB-T */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-cinergy.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-cinergy.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-cinergy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-cinergy.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table cinergy[] = {
 	{ 0x00, KEY_0 },
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-dib0700-nec.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-dib0700-nec.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-dib0700-nec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-dib0700-nec.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table dib0700_nec_table[] = {
 	/* Key codes for the Pixelview SBTVD remote */
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-dib0700-rc5.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-dib0700-rc5.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-dib0700-rc5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-dib0700-rc5.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table dib0700_rc5_table[] = {
 	/* Key codes for the tiny Pinnacle remote*/
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table digitalnow_tinytwin[] = {
 	{ 0x0000, KEY_MUTE },            /* [symbol speaker] */
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-digittrade.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-digittrade.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-digittrade.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-digittrade.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Digittrade DVB-T USB Stick remote controller. */
 /* Imported from af9015.h.
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-dm1105-nec.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-dm1105-nec.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-dm1105-nec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-dm1105-nec.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* DVBWorld remotes
    Igor M. Liplianin <liplianin@me.by>
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* DigitalNow DNTV Live DVB-T Remote */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* DigitalNow DNTV Live! DVB-T Pro Remote */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-em-terratec.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-em-terratec.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-em-terratec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-em-terratec.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table em_terratec[] = {
 	{ 0x01, KEY_CHANNEL },
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-encore-enltv2.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-encore-enltv2.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-encore-enltv2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-encore-enltv2.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Encore ENLTV2-FM  - silver plastic - "Wand Media" written at the botton
     Mauro Carvalho Chehab <mchehab@infradead.org> */
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-encore-enltv.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-encore-enltv.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-encore-enltv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-encore-enltv.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Encore ENLTV-FM  - black plastic, white front cover with white glowing buttons
     Juan Pablo Sormani <sorman@gmail.com> */
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Encore ENLTV-FM v5.3
    Mauro Carvalho Chehab <mchehab@infradead.org>
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-evga-indtube.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-evga-indtube.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-evga-indtube.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-evga-indtube.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* EVGA inDtube
    Devin Heitmueller <devin.heitmueller@gmail.com>
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-eztv.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-eztv.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-eztv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-eztv.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Alfons Geser <a.geser@cox.net>
  * updates from Job D. R. Borges <jobdrb@ig.com.br> */
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-flydvb.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-flydvb.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-flydvb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-flydvb.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table flydvb[] = {
 	{ 0x01, KEY_ZOOM },		/* Full Screen */
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-flyvideo.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-flyvideo.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-flyvideo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-flyvideo.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table flyvideo[] = {
 	{ 0x0f, KEY_0 },
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* DViCO FUSION HDTV MCE remote */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-gadmei-rm008z.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-gadmei-rm008z.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-gadmei-rm008z.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-gadmei-rm008z.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* GADMEI UTV330+ RM008Z remote
    Shine Liu <shinel@foxmail.com>
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Remote control for the Genius TVGO A11MCE
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-gotview7135.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-gotview7135.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-gotview7135.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-gotview7135.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Mike Baikov <mike@baikov.com> */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-hauppauge.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-hauppauge.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-hauppauge.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-hauppauge.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Hauppauge:the newer, gray remotes (seems there are multiple
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-imon-mce.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-imon-mce.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-imon-mce.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-imon-mce.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* mce-mode imon mce remote key table */
 static struct rc_map_table imon_mce[] = {
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-imon-pad.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-imon-pad.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-imon-pad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-imon-pad.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * standard imon remote key table, which isn't really entirely
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-iodata-bctv7e.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-iodata-bctv7e.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-iodata-bctv7e.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-iodata-bctv7e.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* IO-DATA BCTV7E Remote */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-kaiomy.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-kaiomy.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-kaiomy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-kaiomy.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Kaiomy TVnPC U2
    Mauro Carvalho Chehab <mchehab@infradead.org>
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-kworld-315u.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-kworld-315u.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-kworld-315u.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-kworld-315u.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Kworld 315U
  */
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Kworld Plus TV Analog Lite PCI IR
    Mauro Carvalho Chehab <mchehab@infradead.org>
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table leadtek_y04g0051[] = {
 	{ 0x0300, KEY_POWER2 },
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-lirc.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-lirc.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-lirc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-lirc.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <media/rc-core.h>
+#include <linux/module.h>
 
 static struct rc_map_table lirc[] = {
 	{ },
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-lme2510.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-lme2510.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-lme2510.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-lme2510.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 
 static struct rc_map_table lme2510_rc[] = {
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-manli.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-manli.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-manli.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-manli.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Michael Tokarev <mjt@tls.msk.ru>
    keytable is used by MANLI MTV00[0x0c] and BeholdTV 40[13] at
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-medion-x10.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-medion-x10.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-medion-x10.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-medion-x10.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,117 @@
+/*
+ * Medion X10 RF remote keytable
+ *
+ * Copyright (C) 2011 Anssi Hannula <anssi.hannula@?ki.fi>
+ *
+ * This file is based on a keytable provided by
+ * Jan Losinski <losinski@wh2.tu-dresden.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <media/rc-map.h>
+
+static struct rc_map_table medion_x10[] = {
+	{ 0x2c, KEY_TV },    /* TV */
+	{ 0x2d, KEY_VCR },   /* VCR */
+	{ 0x04, KEY_DVD },   /* DVD */
+	{ 0x06, KEY_AUDIO }, /* MUSIC */
+
+	{ 0x2e, KEY_RADIO },     /* RADIO */
+	{ 0x05, KEY_DIRECTORY }, /* PHOTO */
+	{ 0x2f, KEY_INFO },      /* TV-PREVIEW */
+	{ 0x30, KEY_LIST },      /* CHANNEL-LST */
+
+	{ 0x1b, KEY_SETUP }, /* SETUP */
+	{ 0x31, KEY_VIDEO }, /* VIDEO DESKTOP */
+
+	{ 0x08, KEY_VOLUMEDOWN },  /* VOL - */
+	{ 0x09, KEY_VOLUMEUP },    /* VOL + */
+	{ 0x0b, KEY_CHANNELUP },   /* CHAN + */
+	{ 0x0c, KEY_CHANNELDOWN }, /* CHAN - */
+	{ 0x00, KEY_MUTE },        /* MUTE */
+
+	{ 0x32, KEY_RED }, /* red */
+	{ 0x33, KEY_GREEN }, /* green */
+	{ 0x34, KEY_YELLOW }, /* yellow */
+	{ 0x35, KEY_BLUE }, /* blue */
+	{ 0x16, KEY_TEXT }, /* TXT */
+
+	{ 0x0d, KEY_1 },
+	{ 0x0e, KEY_2 },
+	{ 0x0f, KEY_3 },
+	{ 0x10, KEY_4 },
+	{ 0x11, KEY_5 },
+	{ 0x12, KEY_6 },
+	{ 0x13, KEY_7 },
+	{ 0x14, KEY_8 },
+	{ 0x15, KEY_9 },
+	{ 0x17, KEY_0 },
+	{ 0x1c, KEY_SEARCH }, /* TV/RAD, CH SRC */
+	{ 0x20, KEY_DELETE }, /* DELETE */
+
+	{ 0x36, KEY_KEYBOARD }, /* RENAME */
+	{ 0x18, KEY_SCREEN },   /* SNAPSHOT */
+
+	{ 0x1a, KEY_UP },    /* up */
+	{ 0x22, KEY_DOWN },  /* down */
+	{ 0x1d, KEY_LEFT },  /* left */
+	{ 0x1f, KEY_RIGHT }, /* right */
+	{ 0x1e, KEY_OK },    /* OK */
+
+	{ 0x37, KEY_SELECT }, /* ACQUIRE IMAGE */
+	{ 0x38, KEY_EDIT },   /* EDIT IMAGE */
+
+	{ 0x24, KEY_REWIND },   /* rewind  (<<) */
+	{ 0x25, KEY_PLAY },     /* play    ( >) */
+	{ 0x26, KEY_FORWARD },  /* forward (>>) */
+	{ 0x27, KEY_RECORD },   /* record  ( o) */
+	{ 0x28, KEY_STOP },     /* stop    ([]) */
+	{ 0x29, KEY_PAUSE },    /* pause   ('') */
+
+	{ 0x21, KEY_PREVIOUS },        /* prev */
+	{ 0x39, KEY_SWITCHVIDEOMODE }, /* F SCR */
+	{ 0x23, KEY_NEXT },            /* next */
+	{ 0x19, KEY_MENU },            /* MENU */
+	{ 0x3a, KEY_LANGUAGE },        /* AUDIO */
+
+	{ 0x02, KEY_POWER }, /* POWER */
+};
+
+static struct rc_map_list medion_x10_map = {
+	.map = {
+		.scan    = medion_x10,
+		.size    = ARRAY_SIZE(medion_x10),
+		.rc_type = RC_TYPE_OTHER,
+		.name    = RC_MAP_MEDION_X10,
+	}
+};
+
+static int __init init_rc_map_medion_x10(void)
+{
+	return rc_map_register(&medion_x10_map);
+}
+
+static void __exit exit_rc_map_medion_x10(void)
+{
+	rc_map_unregister(&medion_x10_map);
+}
+
+module_init(init_rc_map_medion_x10)
+module_exit(exit_rc_map_medion_x10)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-msi-digivox-ii.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-msi-digivox-ii.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-msi-digivox-ii.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-msi-digivox-ii.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table msi_digivox_ii[] = {
 	{ 0x0002, KEY_2 },
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-msi-digivox-iii.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-msi-digivox-iii.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-msi-digivox-iii.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-msi-digivox-iii.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* MSI DIGIVOX mini III */
 /* Uses NEC extended 0x61d6. */
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-msi-tvanywhere.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-msi-tvanywhere.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-msi-tvanywhere.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-msi-tvanywhere.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* MSI TV@nywhere MASTER remote */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
   Keycodes for remote on the MSI TV@nywhere Plus. The controller IC on the card
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-nebula.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-nebula.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-nebula.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-nebula.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table nebula[] = {
 	{ 0x00, KEY_0 },
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Terratec Cinergy Hybrid T USB XS FM
    Mauro Carvalho Chehab <mchehab@redhat.com>
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-norwood.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-norwood.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-norwood.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-norwood.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Norwood Micro (non-Pro) TV Tuner
    By Peter Naulls <peter@chocky.org>
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-npgtech.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-npgtech.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-npgtech.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-npgtech.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table npgtech[] = {
 	{ 0x1d, KEY_SWITCHVIDEOMODE },	/* switch inputs */
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pctv-sedna.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pctv-sedna.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pctv-sedna.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pctv-sedna.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Mapping for the 28 key remote control as seen at
    http://www.sednacomputer.com/photo/cardbus-tv.jpg
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pinnacle-color.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pinnacle-color.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pinnacle-color.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pinnacle-color.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table pinnacle_color[] = {
 	{ 0x59, KEY_MUTE },
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pinnacle-grey.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pinnacle-grey.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pinnacle-grey.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pinnacle-grey.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table pinnacle_grey[] = {
 	{ 0x3a, KEY_0 },
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Pinnacle PCTV HD 800i mini remote */
 
@@ -20,6 +21,7 @@
 	{ 0x0701, KEY_MENU }, /* Pinnacle logo */
 	{ 0x0739, KEY_POWER },
 	{ 0x0703, KEY_VOLUMEUP },
+	{ 0x0705, KEY_OK },
 	{ 0x0709, KEY_VOLUMEDOWN },
 	{ 0x0706, KEY_CHANNELUP },
 	{ 0x070c, KEY_CHANNELDOWN },
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pixelview-002t.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pixelview-002t.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pixelview-002t.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pixelview-002t.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Keytable for 002-T IR remote provided together with Pixelview
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pixelview.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pixelview.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pixelview.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pixelview.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table pixelview[] = {
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pixelview-mk12.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pixelview-mk12.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pixelview-mk12.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pixelview-mk12.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Keytable for MK-F12 IR remote provided together with Pixelview
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pixelview-new.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pixelview-new.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pixelview-new.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pixelview-new.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
    Mauro Carvalho Chehab <mchehab@infradead.org>
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-powercolor-real-angel.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-powercolor-real-angel.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-powercolor-real-angel.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-powercolor-real-angel.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Remote control for Powercolor Real Angel 330
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-proteus-2309.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-proteus-2309.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-proteus-2309.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-proteus-2309.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Michal Majchrowicz <mmajchrowicz@gmail.com> */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-purpletv.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-purpletv.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-purpletv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-purpletv.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table purpletv[] = {
 	{ 0x03, KEY_POWER },
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pv951.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pv951.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-pv951.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-pv951.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Mark Phalan <phalanm@o2.ie> */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-rc6-mce.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-rc6-mce.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-rc6-mce.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-rc6-mce.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table rc6_mce[] = {
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Zogis Real Audio 220 - 32 keys IR */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-snapstream-firefly.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-snapstream-firefly.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-snapstream-firefly.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-snapstream-firefly.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,107 @@
+/*
+ * SnapStream Firefly X10 RF remote keytable
+ *
+ * Copyright (C) 2011 Anssi Hannula <anssi.hannula@?ki.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 <linux/module.h>
+#include <media/rc-map.h>
+
+static struct rc_map_table snapstream_firefly[] = {
+	{ 0x2c, KEY_ZOOM },       /* Maximize */
+	{ 0x02, KEY_CLOSE },
+
+	{ 0x0d, KEY_1 },
+	{ 0x0e, KEY_2 },
+	{ 0x0f, KEY_3 },
+	{ 0x10, KEY_4 },
+	{ 0x11, KEY_5 },
+	{ 0x12, KEY_6 },
+	{ 0x13, KEY_7 },
+	{ 0x14, KEY_8 },
+	{ 0x15, KEY_9 },
+	{ 0x17, KEY_0 },
+	{ 0x16, KEY_BACK },
+	{ 0x18, KEY_KPENTER },    /* ent */
+
+	{ 0x09, KEY_VOLUMEUP },
+	{ 0x08, KEY_VOLUMEDOWN },
+	{ 0x0a, KEY_MUTE },
+	{ 0x0b, KEY_CHANNELUP },
+	{ 0x0c, KEY_CHANNELDOWN },
+	{ 0x00, KEY_VENDOR },     /* firefly */
+
+	{ 0x2e, KEY_INFO },
+	{ 0x2f, KEY_OPTION },
+
+	{ 0x1d, KEY_LEFT },
+	{ 0x1f, KEY_RIGHT },
+	{ 0x22, KEY_DOWN },
+	{ 0x1a, KEY_UP },
+	{ 0x1e, KEY_OK },
+
+	{ 0x1c, KEY_MENU },
+	{ 0x20, KEY_EXIT },
+
+	{ 0x27, KEY_RECORD },
+	{ 0x25, KEY_PLAY },
+	{ 0x28, KEY_STOP },
+	{ 0x24, KEY_REWIND },
+	{ 0x26, KEY_FORWARD },
+	{ 0x29, KEY_PAUSE },
+	{ 0x2b, KEY_PREVIOUS },
+	{ 0x2a, KEY_NEXT },
+
+	{ 0x06, KEY_AUDIO },      /* Music */
+	{ 0x05, KEY_IMAGES },     /* Photos */
+	{ 0x04, KEY_DVD },
+	{ 0x03, KEY_TV },
+	{ 0x07, KEY_VIDEO },
+
+	{ 0x01, KEY_HELP },
+	{ 0x2d, KEY_MODE },       /* Mouse */
+
+	{ 0x19, KEY_A },
+	{ 0x1b, KEY_B },
+	{ 0x21, KEY_C },
+	{ 0x23, KEY_D },
+};
+
+static struct rc_map_list snapstream_firefly_map = {
+	.map = {
+		.scan    = snapstream_firefly,
+		.size    = ARRAY_SIZE(snapstream_firefly),
+		.rc_type = RC_TYPE_OTHER,
+		.name    = RC_MAP_SNAPSTREAM_FIREFLY,
+	}
+};
+
+static int __init init_rc_map_snapstream_firefly(void)
+{
+	return rc_map_register(&snapstream_firefly_map);
+}
+
+static void __exit exit_rc_map_snapstream_firefly(void)
+{
+	rc_map_unregister(&snapstream_firefly_map);
+}
+
+module_init(init_rc_map_snapstream_firefly)
+module_exit(exit_rc_map_snapstream_firefly)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-streamzap.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-streamzap.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-streamzap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-streamzap.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table streamzap[] = {
 /*
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-tbs-nec.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-tbs-nec.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-tbs-nec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-tbs-nec.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table tbs_nec[] = {
 	{ 0x84, KEY_POWER2},		/* power */
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-technisat-usb2.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-technisat-usb2.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-technisat-usb2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-technisat-usb2.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table technisat_usb2[] = {
 	{0x0a0c, KEY_POWER},
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Terratec Cinergy Hybrid T USB XS
    Devin Heitmueller <dheitmueller@linuxtv.org>
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-terratec-slim-2.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-terratec-slim-2.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-terratec-slim-2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-terratec-slim-2.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * TerraTec slim remote, 6 rows, 3 columns.
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-terratec-slim.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-terratec-slim.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-terratec-slim.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-terratec-slim.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* TerraTec slim remote, 7 rows, 4 columns. */
 /* Uses NEC extended 0x02bd. */
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-tevii-nec.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-tevii-nec.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-tevii-nec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-tevii-nec.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table tevii_nec[] = {
 	{ 0x0a, KEY_POWER2},
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-tivo.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-tivo.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-tivo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-tivo.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /*
  * Initial mapping is for the TiVo remote included in the Nero LiquidTV bundle,
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-total-media-in-hand.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-total-media-in-hand.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-total-media-in-hand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-total-media-in-hand.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Uses NEC extended 0x02bd */
 static struct rc_map_table total_media_in_hand[] = {
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-trekstor.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-trekstor.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-trekstor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-trekstor.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* TrekStor DVB-T USB Stick remote controller. */
 /* Imported from af9015.h.
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-tt-1500.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-tt-1500.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-tt-1500.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-tt-1500.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* for the Technotrend 1500 bundled remotes (grey and black): */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-twinhan1027.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-twinhan1027.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-twinhan1027.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-twinhan1027.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,5 @@
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table twinhan_vp1027[] = {
 	{ 0x16, KEY_POWER2 },
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-videomate-m1f.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-videomate-m1f.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-videomate-m1f.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-videomate-m1f.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table videomate_m1f[] = {
 	{ 0x01, KEY_POWER },
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-videomate-s350.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-videomate-s350.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-videomate-s350.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-videomate-s350.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table videomate_s350[] = {
 	{ 0x00, KEY_TV},
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 static struct rc_map_table videomate_tv_pvr[] = {
 	{ 0x14, KEY_MUTE },
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-winfast.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-winfast.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-winfast.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-winfast.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c
--- linux-libre-3.1-gnu/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
  */
 
 #include <media/rc-map.h>
+#include <linux/module.h>
 
 /* Leadtek Winfast TV USB II Deluxe remote
    Magnus Alm <magnus.alm@gmail.com>
diff -druN linux-libre-3.1-gnu/drivers/media/rc/Makefile linux-libre-3.2-gnu/drivers/media/rc/Makefile
--- linux-libre-3.1-gnu/drivers/media/rc/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
 
 # stand-alone IR receivers/transmitters
+obj-$(CONFIG_RC_ATI_REMOTE) += ati_remote.o
 obj-$(CONFIG_IR_IMON) += imon.o
 obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o
 obj-$(CONFIG_IR_MCEUSB) += mceusb.o
diff -druN linux-libre-3.1-gnu/drivers/media/rc/mceusb.c linux-libre-3.2-gnu/drivers/media/rc/mceusb.c
--- linux-libre-3.1-gnu/drivers/media/rc/mceusb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/mceusb.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * Driver for USB Windows Media Center Ed. eHome Infrared Transceivers
  *
- * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
+ * Copyright (c) 2010-2011, Jarod Wilson <jarod@redhat.com>
  *
  * Based on the original lirc_mceusb and lirc_mceusb2 drivers, by Dan
  * Conti, Martin Blatter and Daniel Melander, the latter of which was
@@ -15,6 +15,11 @@
  * Jon Smirl, which included enhancements and simplifications to the
  * incoming IR buffer parsing routines.
  *
+ * Updated in July of 2011 with the aid of Microsoft's official
+ * remote/transceiver requirements and specification document, found at
+ * download.microsoft.com, title
+ * Windows-Media-Center-RC-IR-Collection-Green-Button-Specification-03-08-2011-V2.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
@@ -37,10 +42,11 @@
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/usb/input.h>
+#include <linux/pm_wakeup.h>
 #include <media/rc-core.h>
 
-#define DRIVER_VERSION	"1.91"
-#define DRIVER_AUTHOR	"Jarod Wilson <jarod@wilsonet.com>"
+#define DRIVER_VERSION	"1.92"
+#define DRIVER_AUTHOR	"Jarod Wilson <jarod@redhat.com>"
 #define DRIVER_DESC	"Windows Media Center Ed. eHome Infrared Transceiver " \
 			"device driver"
 #define DRIVER_NAME	"mceusb"
@@ -63,43 +69,90 @@
 #define MCE_PULSE_MASK		0x7f /* Pulse mask */
 #define MCE_MAX_PULSE_LENGTH	0x7f /* Longest transmittable pulse symbol */
 
-#define MCE_HW_CMD_HEADER	0xff	/* MCE hardware command header */
-#define MCE_COMMAND_HEADER	0x9f	/* MCE command header */
-#define MCE_COMMAND_MASK	0xe0	/* Mask out command bits */
-#define MCE_COMMAND_NULL	0x00	/* These show up various places... */
-/* if buf[i] & MCE_COMMAND_MASK == 0x80 and buf[i] != MCE_COMMAND_HEADER,
- * then we're looking at a raw IR data sample */
-#define MCE_COMMAND_IRDATA	0x80
-#define MCE_PACKET_LENGTH_MASK	0x1f /* Packet length mask */
+/*
+ * The interface between the host and the IR hardware is command-response
+ * based. All commands and responses have a consistent format, where a lead
+ * byte always identifies the type of data following it. The lead byte has
+ * a port value in the 3 highest bits and a length value in the 5 lowest
+ * bits.
+ *
+ * The length field is overloaded, with a value of 11111 indicating that the
+ * following byte is a command or response code, and the length of the entire
+ * message is determined by the code. If the length field is not 11111, then
+ * it specifies the number of bytes of port data that follow.
+ */
+#define MCE_CMD			0x1f
+#define MCE_PORT_IR		0x4	/* (0x4 << 5) | MCE_CMD = 0x9f */
+#define MCE_PORT_SYS		0x7	/* (0x7 << 5) | MCE_CMD = 0xff */
+#define MCE_PORT_SER		0x6	/* 0xc0 thru 0xdf flush & 0x1f bytes */
+#define MCE_PORT_MASK	0xe0	/* Mask out command bits */
 
-/* Sub-commands, which follow MCE_COMMAND_HEADER or MCE_HW_CMD_HEADER */
+/* Command port headers */
+#define MCE_CMD_PORT_IR		0x9f	/* IR-related cmd/rsp */
+#define MCE_CMD_PORT_SYS	0xff	/* System (non-IR) device cmd/rsp */
+
+/* Commands that set device state  (2-4 bytes in length) */
+#define MCE_CMD_RESET		0xfe	/* Reset device, 2 bytes */
+#define MCE_CMD_RESUME		0xaa	/* Resume device after error, 2 bytes */
+#define MCE_CMD_SETIRCFS	0x06	/* Set tx carrier, 4 bytes */
+#define MCE_CMD_SETIRTIMEOUT	0x0c	/* Set timeout, 4 bytes */
+#define MCE_CMD_SETIRTXPORTS	0x08	/* Set tx ports, 3 bytes */
+#define MCE_CMD_SETIRRXPORTEN	0x14	/* Set rx ports, 3 bytes */
+#define MCE_CMD_FLASHLED	0x23	/* Flash receiver LED, 2 bytes */
+
+/* Commands that query device state (all 2 bytes, unless noted) */
+#define MCE_CMD_GETIRCFS	0x07	/* Get carrier */
+#define MCE_CMD_GETIRTIMEOUT	0x0d	/* Get timeout */
+#define MCE_CMD_GETIRTXPORTS	0x13	/* Get tx ports */
+#define MCE_CMD_GETIRRXPORTEN	0x15	/* Get rx ports */
+#define MCE_CMD_GETPORTSTATUS	0x11	/* Get tx port status, 3 bytes */
+#define MCE_CMD_GETIRNUMPORTS	0x16	/* Get number of ports */
+#define MCE_CMD_GETWAKESOURCE	0x17	/* Get wake source */
+#define MCE_CMD_GETEMVER	0x22	/* Get emulator interface version */
+#define MCE_CMD_GETDEVDETAILS	0x21	/* Get device details (em ver2 only) */
+#define MCE_CMD_GETWAKESUPPORT	0x20	/* Get wake details (em ver2 only) */
+#define MCE_CMD_GETWAKEVERSION	0x18	/* Get wake pattern (em ver2 only) */
+
+/* Misc commands */
+#define MCE_CMD_NOP		0xff	/* No operation */
+
+/* Responses to commands (non-error cases) */
+#define MCE_RSP_EQIRCFS		0x06	/* tx carrier, 4 bytes */
+#define MCE_RSP_EQIRTIMEOUT	0x0c	/* rx timeout, 4 bytes */
+#define MCE_RSP_GETWAKESOURCE	0x17	/* wake source, 3 bytes */
+#define MCE_RSP_EQIRTXPORTS	0x08	/* tx port mask, 3 bytes */
+#define MCE_RSP_EQIRRXPORTEN	0x14	/* rx port mask, 3 bytes */
+#define MCE_RSP_GETPORTSTATUS	0x11	/* tx port status, 7 bytes */
+#define MCE_RSP_EQIRRXCFCNT	0x15	/* rx carrier count, 4 bytes */
+#define MCE_RSP_EQIRNUMPORTS	0x16	/* number of ports, 4 bytes */
+#define MCE_RSP_EQWAKESUPPORT	0x20	/* wake capabilities, 3 bytes */
+#define MCE_RSP_EQWAKEVERSION	0x18	/* wake pattern details, 6 bytes */
+#define MCE_RSP_EQDEVDETAILS	0x21	/* device capabilities, 3 bytes */
+#define MCE_RSP_EQEMVER		0x22	/* emulator interface ver, 3 bytes */
+#define MCE_RSP_FLASHLED	0x23	/* success flashing LED, 2 bytes */
+
+/* Responses to error cases, must send MCE_CMD_RESUME to clear them */
+#define MCE_RSP_CMD_ILLEGAL	0xfe	/* illegal command for port, 2 bytes */
+#define MCE_RSP_TX_TIMEOUT	0x81	/* tx timed out, 2 bytes */
+
+/* Misc commands/responses not defined in the MCE remote/transceiver spec */
 #define MCE_CMD_SIG_END		0x01	/* End of signal */
 #define MCE_CMD_PING		0x03	/* Ping device */
 #define MCE_CMD_UNKNOWN		0x04	/* Unknown */
 #define MCE_CMD_UNKNOWN2	0x05	/* Unknown */
-#define MCE_CMD_S_CARRIER	0x06	/* Set TX carrier frequency */
-#define MCE_CMD_G_CARRIER	0x07	/* Get TX carrier frequency */
-#define MCE_CMD_S_TXMASK	0x08	/* Set TX port bitmask */
 #define MCE_CMD_UNKNOWN3	0x09	/* Unknown */
 #define MCE_CMD_UNKNOWN4	0x0a	/* Unknown */
 #define MCE_CMD_G_REVISION	0x0b	/* Get hw/sw revision */
-#define MCE_CMD_S_TIMEOUT	0x0c	/* Set RX timeout value */
-#define MCE_CMD_G_TIMEOUT	0x0d	/* Get RX timeout value */
 #define MCE_CMD_UNKNOWN5	0x0e	/* Unknown */
 #define MCE_CMD_UNKNOWN6	0x0f	/* Unknown */
-#define MCE_CMD_G_RXPORTSTS	0x11	/* Get RX port status */
-#define MCE_CMD_G_TXMASK	0x13	/* Set TX port bitmask */
-#define MCE_CMD_S_RXSENSOR	0x14	/* Set RX sensor (std/learning) */
-#define MCE_CMD_G_RXSENSOR	0x15	/* Get RX sensor (std/learning) */
-#define MCE_RSP_PULSE_COUNT	0x15	/* RX pulse count (only if learning) */
-#define MCE_CMD_TX_PORTS	0x16	/* Get number of TX ports */
-#define MCE_CMD_G_WAKESRC	0x17	/* Get wake source */
-#define MCE_CMD_UNKNOWN7	0x18	/* Unknown */
 #define MCE_CMD_UNKNOWN8	0x19	/* Unknown */
 #define MCE_CMD_UNKNOWN9	0x1b	/* Unknown */
-#define MCE_CMD_DEVICE_RESET	0xaa	/* Reset the hardware */
-#define MCE_RSP_CMD_INVALID	0xfe	/* Invalid command issued */
+#define MCE_CMD_NULL		0x00	/* These show up various places... */
 
+/* if buf[i] & MCE_PORT_MASK == 0x80 and buf[i] != MCE_CMD_PORT_IR,
+ * then we're looking at a raw IR data sample */
+#define MCE_COMMAND_IRDATA	0x80
+#define MCE_PACKET_LENGTH_MASK	0x1f /* Packet length mask */
 
 /* module parameters */
 #ifdef CONFIG_USB_DEBUG
@@ -388,48 +441,37 @@
 	char name[128];
 	char phys[64];
 	enum mceusb_model_type model;
+
+	bool need_reset;	/* flag to issue a device resume cmd */
+	u8 emver;		/* emulator interface version */
+	u8 num_txports;		/* number of transmit ports */
+	u8 num_rxports;		/* number of receive sensors */
+	u8 txports_cabled;	/* bitmask of transmitters with cable */
+	u8 rxports_active;	/* bitmask of active receive sensors */
 };
 
-/*
- * MCE Device Command Strings
- * Device command responses vary from device to device...
- * - DEVICE_RESET resets the hardware to its default state
- * - GET_REVISION fetches the hardware/software revision, common
- *   replies are ff 0b 45 ff 1b 08 and ff 0b 50 ff 1b 42
- * - GET_CARRIER_FREQ gets the carrier mode and frequency of the
- *   device, with replies in the form of 9f 06 MM FF, where MM is 0-3,
- *   meaning clk of 10000000, 2500000, 625000 or 156250, and FF is
- *   ((clk / frequency) - 1)
- * - GET_RX_TIMEOUT fetches the receiver timeout in units of 50us,
- *   response in the form of 9f 0c msb lsb
- * - GET_TX_BITMASK fetches the transmitter bitmask, replies in
- *   the form of 9f 08 bm, where bm is the bitmask
- * - GET_RX_SENSOR fetches the RX sensor setting -- long-range
- *   general use one or short-range learning one, in the form of
- *   9f 14 ss, where ss is either 01 for long-range or 02 for short
- * - SET_CARRIER_FREQ sets a new carrier mode and frequency
- * - SET_TX_BITMASK sets the transmitter bitmask
- * - SET_RX_TIMEOUT sets the receiver timeout
- * - SET_RX_SENSOR sets which receiver sensor to use
- */
-static char DEVICE_RESET[]	= {MCE_COMMAND_NULL, MCE_HW_CMD_HEADER,
-				   MCE_CMD_DEVICE_RESET};
-static char GET_REVISION[]	= {MCE_HW_CMD_HEADER, MCE_CMD_G_REVISION};
-static char GET_UNKNOWN[]	= {MCE_HW_CMD_HEADER, MCE_CMD_UNKNOWN7};
-static char GET_UNKNOWN2[]	= {MCE_COMMAND_HEADER, MCE_CMD_UNKNOWN2};
-static char GET_CARRIER_FREQ[]	= {MCE_COMMAND_HEADER, MCE_CMD_G_CARRIER};
-static char GET_RX_TIMEOUT[]	= {MCE_COMMAND_HEADER, MCE_CMD_G_TIMEOUT};
-static char GET_TX_BITMASK[]	= {MCE_COMMAND_HEADER, MCE_CMD_G_TXMASK};
-static char GET_RX_SENSOR[]	= {MCE_COMMAND_HEADER, MCE_CMD_G_RXSENSOR};
+/* MCE Device Command Strings, generally a port and command pair */
+static char DEVICE_RESUME[]	= {MCE_CMD_NULL, MCE_CMD_PORT_SYS,
+				   MCE_CMD_RESUME};
+static char GET_REVISION[]	= {MCE_CMD_PORT_SYS, MCE_CMD_G_REVISION};
+static char GET_EMVER[]		= {MCE_CMD_PORT_SYS, MCE_CMD_GETEMVER};
+static char GET_WAKEVERSION[]	= {MCE_CMD_PORT_SYS, MCE_CMD_GETWAKEVERSION};
+static char FLASH_LED[]		= {MCE_CMD_PORT_SYS, MCE_CMD_FLASHLED};
+static char GET_UNKNOWN2[]	= {MCE_CMD_PORT_IR, MCE_CMD_UNKNOWN2};
+static char GET_CARRIER_FREQ[]	= {MCE_CMD_PORT_IR, MCE_CMD_GETIRCFS};
+static char GET_RX_TIMEOUT[]	= {MCE_CMD_PORT_IR, MCE_CMD_GETIRTIMEOUT};
+static char GET_NUM_PORTS[]	= {MCE_CMD_PORT_IR, MCE_CMD_GETIRNUMPORTS};
+static char GET_TX_BITMASK[]	= {MCE_CMD_PORT_IR, MCE_CMD_GETIRTXPORTS};
+static char GET_RX_SENSOR[]	= {MCE_CMD_PORT_IR, MCE_CMD_GETIRRXPORTEN};
 /* sub in desired values in lower byte or bytes for full command */
 /* FIXME: make use of these for transmit.
-static char SET_CARRIER_FREQ[]	= {MCE_COMMAND_HEADER,
-				   MCE_CMD_S_CARRIER, 0x00, 0x00};
-static char SET_TX_BITMASK[]	= {MCE_COMMAND_HEADER, MCE_CMD_S_TXMASK, 0x00};
-static char SET_RX_TIMEOUT[]	= {MCE_COMMAND_HEADER,
-				   MCE_CMD_S_TIMEOUT, 0x00, 0x00};
-static char SET_RX_SENSOR[]	= {MCE_COMMAND_HEADER,
-				   MCE_CMD_S_RXSENSOR, 0x00};
+static char SET_CARRIER_FREQ[]	= {MCE_CMD_PORT_IR,
+				   MCE_CMD_SETIRCFS, 0x00, 0x00};
+static char SET_TX_BITMASK[]	= {MCE_CMD_PORT_IR, MCE_CMD_SETIRTXPORTS, 0x00};
+static char SET_RX_TIMEOUT[]	= {MCE_CMD_PORT_IR,
+				   MCE_CMD_SETIRTIMEOUT, 0x00, 0x00};
+static char SET_RX_SENSOR[]	= {MCE_CMD_PORT_IR,
+				   MCE_RSP_EQIRRXPORTEN, 0x00};
 */
 
 static int mceusb_cmdsize(u8 cmd, u8 subcmd)
@@ -437,27 +479,33 @@
 	int datasize = 0;
 
 	switch (cmd) {
-	case MCE_COMMAND_NULL:
-		if (subcmd == MCE_HW_CMD_HEADER)
+	case MCE_CMD_NULL:
+		if (subcmd == MCE_CMD_PORT_SYS)
 			datasize = 1;
 		break;
-	case MCE_HW_CMD_HEADER:
+	case MCE_CMD_PORT_SYS:
 		switch (subcmd) {
+		case MCE_RSP_EQWAKEVERSION:
+			datasize = 4;
+			break;
 		case MCE_CMD_G_REVISION:
 			datasize = 2;
 			break;
+		case MCE_RSP_EQWAKESUPPORT:
+			datasize = 1;
+			break;
 		}
-	case MCE_COMMAND_HEADER:
+	case MCE_CMD_PORT_IR:
 		switch (subcmd) {
 		case MCE_CMD_UNKNOWN:
-		case MCE_CMD_S_CARRIER:
-		case MCE_CMD_S_TIMEOUT:
-		case MCE_RSP_PULSE_COUNT:
+		case MCE_RSP_EQIRCFS:
+		case MCE_RSP_EQIRTIMEOUT:
+		case MCE_RSP_EQIRRXCFCNT:
 			datasize = 2;
 			break;
 		case MCE_CMD_SIG_END:
-		case MCE_CMD_S_TXMASK:
-		case MCE_CMD_S_RXSENSOR:
+		case MCE_RSP_EQIRTXPORTS:
+		case MCE_RSP_EQIRRXPORTEN:
 			datasize = 1;
 			break;
 		}
@@ -470,9 +518,10 @@
 {
 	char codes[USB_BUFLEN * 3 + 1];
 	char inout[9];
-	u8 cmd, subcmd, data1, data2;
+	u8 cmd, subcmd, data1, data2, data3, data4, data5;
 	struct device *dev = ir->dev;
 	int i, start, skip = 0;
+	u32 carrier, period;
 
 	if (!debug)
 		return;
@@ -500,18 +549,28 @@
 	subcmd = buf[start + 1] & 0xff;
 	data1  = buf[start + 2] & 0xff;
 	data2  = buf[start + 3] & 0xff;
+	data3  = buf[start + 4] & 0xff;
+	data4  = buf[start + 5] & 0xff;
+	data5  = buf[start + 6] & 0xff;
 
 	switch (cmd) {
-	case MCE_COMMAND_NULL:
-		if ((subcmd == MCE_HW_CMD_HEADER) &&
-		    (data1 == MCE_CMD_DEVICE_RESET))
-			dev_info(dev, "Device reset requested\n");
+	case MCE_CMD_NULL:
+		if (subcmd == MCE_CMD_NULL)
+			break;
+		if ((subcmd == MCE_CMD_PORT_SYS) &&
+		    (data1 == MCE_CMD_RESUME))
+			dev_info(dev, "Device resume requested\n");
 		else
 			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
 				 cmd, subcmd);
 		break;
-	case MCE_HW_CMD_HEADER:
+	case MCE_CMD_PORT_SYS:
 		switch (subcmd) {
+		case MCE_RSP_EQEMVER:
+			if (!out)
+				dev_info(dev, "Emulator interface version %x\n",
+					 data1);
+			break;
 		case MCE_CMD_G_REVISION:
 			if (len == 2)
 				dev_info(dev, "Get hw/sw rev?\n");
@@ -520,21 +579,35 @@
 					 "0x%02x 0x%02x\n", data1, data2,
 					 buf[start + 4], buf[start + 5]);
 			break;
-		case MCE_CMD_DEVICE_RESET:
-			dev_info(dev, "Device reset requested\n");
+		case MCE_CMD_RESUME:
+			dev_info(dev, "Device resume requested\n");
 			break;
-		case MCE_RSP_CMD_INVALID:
-			dev_info(dev, "Previous command not supported\n");
+		case MCE_RSP_CMD_ILLEGAL:
+			dev_info(dev, "Illegal PORT_SYS command\n");
+			break;
+		case MCE_RSP_EQWAKEVERSION:
+			if (!out)
+				dev_info(dev, "Wake version, proto: 0x%02x, "
+					 "payload: 0x%02x, address: 0x%02x, "
+					 "version: 0x%02x\n",
+					 data1, data2, data3, data4);
+			break;
+		case MCE_RSP_GETPORTSTATUS:
+			if (!out)
+				/* We use data1 + 1 here, to match hw labels */
+				dev_info(dev, "TX port %d: blaster is%s connected\n",
+					 data1 + 1, data4 ? " not" : "");
+			break;
+		case MCE_CMD_FLASHLED:
+			dev_info(dev, "Attempting to flash LED\n");
 			break;
-		case MCE_CMD_UNKNOWN7:
-		case MCE_CMD_UNKNOWN9:
 		default:
 			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
 				 cmd, subcmd);
 			break;
 		}
 		break;
-	case MCE_COMMAND_HEADER:
+	case MCE_CMD_PORT_IR:
 		switch (subcmd) {
 		case MCE_CMD_SIG_END:
 			dev_info(dev, "End of signal\n");
@@ -546,47 +619,55 @@
 			dev_info(dev, "Resp to 9f 05 of 0x%02x 0x%02x\n",
 				 data1, data2);
 			break;
-		case MCE_CMD_S_CARRIER:
-			dev_info(dev, "%s carrier mode and freq of "
-				 "0x%02x 0x%02x\n", inout, data1, data2);
+		case MCE_RSP_EQIRCFS:
+			period = DIV_ROUND_CLOSEST(
+					(1 << data1 * 2) * (data2 + 1), 10);
+			if (!period)
+				break;
+			carrier = (1000 * 1000) / period;
+			dev_info(dev, "%s carrier of %u Hz (period %uus)\n",
+				 inout, carrier, period);
 			break;
-		case MCE_CMD_G_CARRIER:
+		case MCE_CMD_GETIRCFS:
 			dev_info(dev, "Get carrier mode and freq\n");
 			break;
-		case MCE_CMD_S_TXMASK:
+		case MCE_RSP_EQIRTXPORTS:
 			dev_info(dev, "%s transmit blaster mask of 0x%02x\n",
 				 inout, data1);
 			break;
-		case MCE_CMD_S_TIMEOUT:
+		case MCE_RSP_EQIRTIMEOUT:
 			/* value is in units of 50us, so x*50/1000 ms */
+			period = ((data1 << 8) | data2) * MCE_TIME_UNIT / 1000;
 			dev_info(dev, "%s receive timeout of %d ms\n",
-				 inout,
-				 ((data1 << 8) | data2) * MCE_TIME_UNIT / 1000);
+				 inout, period);
 			break;
-		case MCE_CMD_G_TIMEOUT:
+		case MCE_CMD_GETIRTIMEOUT:
 			dev_info(dev, "Get receive timeout\n");
 			break;
-		case MCE_CMD_G_TXMASK:
+		case MCE_CMD_GETIRTXPORTS:
 			dev_info(dev, "Get transmit blaster mask\n");
 			break;
-		case MCE_CMD_S_RXSENSOR:
+		case MCE_RSP_EQIRRXPORTEN:
 			dev_info(dev, "%s %s-range receive sensor in use\n",
 				 inout, data1 == 0x02 ? "short" : "long");
 			break;
-		case MCE_CMD_G_RXSENSOR:
-		/* aka MCE_RSP_PULSE_COUNT */
+		case MCE_CMD_GETIRRXPORTEN:
+		/* aka MCE_RSP_EQIRRXCFCNT */
 			if (out)
 				dev_info(dev, "Get receive sensor\n");
 			else if (ir->learning_enabled)
 				dev_info(dev, "RX pulse count: %d\n",
 					 ((data1 << 8) | data2));
 			break;
-		case MCE_RSP_CMD_INVALID:
-			dev_info(dev, "Error! Hardware is likely wedged...\n");
+		case MCE_RSP_EQIRNUMPORTS:
+			if (out)
+				break;
+			dev_info(dev, "Num TX ports: %x, num RX ports: %x\n",
+				 data1, data2);
+			break;
+		case MCE_RSP_CMD_ILLEGAL:
+			dev_info(dev, "Illegal PORT_IR command\n");
 			break;
-		case MCE_CMD_UNKNOWN2:
-		case MCE_CMD_UNKNOWN3:
-		case MCE_CMD_UNKNOWN5:
 		default:
 			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
 				 cmd, subcmd);
@@ -599,8 +680,8 @@
 
 	if (cmd == MCE_IRDATA_TRAILER)
 		dev_info(dev, "End of raw IR data\n");
-	else if ((cmd != MCE_COMMAND_HEADER) &&
-		 ((cmd & MCE_COMMAND_MASK) == MCE_COMMAND_IRDATA))
+	else if ((cmd != MCE_CMD_PORT_IR) &&
+		 ((cmd & MCE_PORT_MASK) == MCE_COMMAND_IRDATA))
 		dev_info(dev, "Raw IR data, %d pulse/space samples\n", ir->rem);
 }
 
@@ -616,9 +697,6 @@
 	if (ir) {
 		len = urb->actual_length;
 
-		mce_dbg(ir->dev, "callback called (status=%d len=%d)\n",
-			urb->status, len);
-
 		mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true);
 	}
 
@@ -683,7 +761,16 @@
 
 static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)
 {
+	int rsize = sizeof(DEVICE_RESUME);
+
+	if (ir->need_reset) {
+		ir->need_reset = false;
+		mce_request_packet(ir, DEVICE_RESUME, rsize, MCEUSB_TX);
+		msleep(10);
+	}
+
 	mce_request_packet(ir, data, size, MCEUSB_TX);
+	msleep(10);
 }
 
 static void mce_flush_rx_buffer(struct mceusb_dev *ir, int size)
@@ -708,8 +795,8 @@
 		return -ENOMEM;
 
 	/* MCE tx init header */
-	cmdbuf[cmdcount++] = MCE_COMMAND_HEADER;
-	cmdbuf[cmdcount++] = MCE_CMD_S_TXMASK;
+	cmdbuf[cmdcount++] = MCE_CMD_PORT_IR;
+	cmdbuf[cmdcount++] = MCE_CMD_SETIRTXPORTS;
 	cmdbuf[cmdcount++] = ir->tx_mask;
 
 	/* Generate mce packet data */
@@ -795,8 +882,8 @@
 	struct mceusb_dev *ir = dev->priv;
 	int clk = 10000000;
 	int prescaler = 0, divisor = 0;
-	unsigned char cmdbuf[4] = { MCE_COMMAND_HEADER,
-				    MCE_CMD_S_CARRIER, 0x00, 0x00 };
+	unsigned char cmdbuf[4] = { MCE_CMD_PORT_IR,
+				    MCE_CMD_SETIRCFS, 0x00, 0x00 };
 
 	/* Carrier has changed */
 	if (ir->carrier != carrier) {
@@ -844,17 +931,34 @@
 	u8 lo = ir->buf_in[index + 2] & 0xff;
 
 	switch (ir->buf_in[index]) {
+	/* the one and only 5-byte return value command */
+	case MCE_RSP_GETPORTSTATUS:
+		if ((ir->buf_in[index + 4] & 0xff) == 0x00)
+			ir->txports_cabled |= 1 << hi;
+		break;
+
 	/* 2-byte return value commands */
-	case MCE_CMD_S_TIMEOUT:
+	case MCE_RSP_EQIRTIMEOUT:
 		ir->rc->timeout = US_TO_NS((hi << 8 | lo) * MCE_TIME_UNIT);
 		break;
+	case MCE_RSP_EQIRNUMPORTS:
+		ir->num_txports = hi;
+		ir->num_rxports = lo;
+		break;
 
 	/* 1-byte return value commands */
-	case MCE_CMD_S_TXMASK:
+	case MCE_RSP_EQEMVER:
+		ir->emver = hi;
+		break;
+	case MCE_RSP_EQIRTXPORTS:
 		ir->tx_mask = hi;
 		break;
-	case MCE_CMD_S_RXSENSOR:
-		ir->learning_enabled = (hi == 0x02);
+	case MCE_RSP_EQIRRXPORTEN:
+		ir->learning_enabled = ((hi & 0x02) == 0x02);
+		ir->rxports_active = hi;
+		break;
+	case MCE_RSP_CMD_ILLEGAL:
+		ir->need_reset = true;
 		break;
 	default:
 		break;
@@ -903,8 +1007,8 @@
 			/* decode mce packets of the form (84),AA,BB,CC,DD */
 			/* IR data packets can span USB messages - rem */
 			ir->cmd = ir->buf_in[i];
-			if ((ir->cmd == MCE_COMMAND_HEADER) ||
-			    ((ir->cmd & MCE_COMMAND_MASK) !=
+			if ((ir->cmd == MCE_CMD_PORT_IR) ||
+			    ((ir->cmd & MCE_PORT_MASK) !=
 			     MCE_COMMAND_IRDATA)) {
 				ir->parser_state = SUBCMD;
 				continue;
@@ -969,6 +1073,13 @@
 	usb_submit_urb(urb, GFP_ATOMIC);
 }
 
+static void mceusb_get_emulator_version(struct mceusb_dev *ir)
+{
+	/* If we get no reply or an illegal command reply, its ver 1, says MS */
+	ir->emver = 1;
+	mce_async_out(ir, GET_EMVER, sizeof(GET_EMVER));
+}
+
 static void mceusb_gen1_init(struct mceusb_dev *ir)
 {
 	int ret;
@@ -1011,8 +1122,8 @@
 			      0x0000, 0x0100, NULL, 0, HZ * 3);
 	mce_dbg(dev, "%s - retC = %d\n", __func__, ret);
 
-	/* device reset */
-	mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
+	/* device resume */
+	mce_async_out(ir, DEVICE_RESUME, sizeof(DEVICE_RESUME));
 
 	/* get hw/sw revision? */
 	mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
@@ -1022,23 +1133,36 @@
 
 static void mceusb_gen2_init(struct mceusb_dev *ir)
 {
-	/* device reset */
-	mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
+	/* device resume */
+	mce_async_out(ir, DEVICE_RESUME, sizeof(DEVICE_RESUME));
 
 	/* get hw/sw revision? */
 	mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
 
-	/* unknown what the next two actually return... */
-	mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN));
+	/* get wake version (protocol, key, address) */
+	mce_async_out(ir, GET_WAKEVERSION, sizeof(GET_WAKEVERSION));
+
+	/* unknown what this one actually returns... */
 	mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2));
 }
 
 static void mceusb_get_parameters(struct mceusb_dev *ir)
 {
+	int i;
+	unsigned char cmdbuf[3] = { MCE_CMD_PORT_SYS,
+				    MCE_CMD_GETPORTSTATUS, 0x00 };
+
+	/* defaults, if the hardware doesn't support querying */
+	ir->num_txports = 2;
+	ir->num_rxports = 2;
+
+	/* get number of tx and rx ports */
+	mce_async_out(ir, GET_NUM_PORTS, sizeof(GET_NUM_PORTS));
+
 	/* get the carrier and frequency */
 	mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ));
 
-	if (!ir->flags.no_tx)
+	if (ir->num_txports && !ir->flags.no_tx)
 		/* get the transmitter bitmask */
 		mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK));
 
@@ -1047,6 +1171,19 @@
 
 	/* get receiver sensor setting */
 	mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR));
+
+	for (i = 0; i < ir->num_txports; i++) {
+		cmdbuf[2] = i;
+		mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
+	}
+}
+
+static void mceusb_flash_led(struct mceusb_dev *ir)
+{
+	if (ir->emver < 2)
+		return;
+
+	mce_async_out(ir, FLASH_LED, sizeof(FLASH_LED));
 }
 
 static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
@@ -1220,6 +1357,9 @@
 	mce_dbg(&intf->dev, "Flushing receive buffers\n");
 	mce_flush_rx_buffer(ir, maxp);
 
+	/* figure out which firmware/emulator version this hardware has */
+	mceusb_get_emulator_version(ir);
+
 	/* initialize device */
 	if (ir->flags.microsoft_gen1)
 		mceusb_gen1_init(ir);
@@ -1228,13 +1368,23 @@
 
 	mceusb_get_parameters(ir);
 
+	mceusb_flash_led(ir);
+
 	if (!ir->flags.no_tx)
 		mceusb_set_tx_mask(ir->rc, MCE_DEFAULT_TX_MASK);
 
 	usb_set_intfdata(intf, ir);
 
-	dev_info(&intf->dev, "Registered %s on usb%d:%d\n", name,
-		 dev->bus->busnum, dev->devnum);
+	/* enable wake via this device */
+	device_set_wakeup_capable(ir->dev, true);
+	device_set_wakeup_enable(ir->dev, true);
+
+	dev_info(&intf->dev, "Registered %s with mce emulator interface "
+		 "version %x\n", name, ir->emver);
+	dev_info(&intf->dev, "%x tx ports (0x%x cabled) and "
+		 "%x rx sensors (0x%x active)\n",
+		 ir->num_txports, ir->txports_cabled,
+		 ir->num_rxports, ir->rxports_active);
 
 	return 0;
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/rc-core-priv.h linux-libre-3.2-gnu/drivers/media/rc/rc-core-priv.h
--- linux-libre-3.1-gnu/drivers/media/rc/rc-core-priv.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/rc-core-priv.h	2012-01-04 18:55:44.000000000 -0500
@@ -162,49 +162,49 @@
 #ifdef CONFIG_IR_NEC_DECODER_MODULE
 #define load_nec_decode()	request_module("ir-nec-decoder")
 #else
-#define load_nec_decode()	0
+static inline void load_nec_decode(void) { }
 #endif
 
 /* from ir-rc5-decoder.c */
 #ifdef CONFIG_IR_RC5_DECODER_MODULE
 #define load_rc5_decode()	request_module("ir-rc5-decoder")
 #else
-#define load_rc5_decode()	0
+static inline void load_rc5_decode(void) { }
 #endif
 
 /* from ir-rc6-decoder.c */
 #ifdef CONFIG_IR_RC6_DECODER_MODULE
 #define load_rc6_decode()	request_module("ir-rc6-decoder")
 #else
-#define load_rc6_decode()	0
+static inline void load_rc6_decode(void) { }
 #endif
 
 /* from ir-jvc-decoder.c */
 #ifdef CONFIG_IR_JVC_DECODER_MODULE
 #define load_jvc_decode()	request_module("ir-jvc-decoder")
 #else
-#define load_jvc_decode()	0
+static inline void load_jvc_decode(void) { }
 #endif
 
 /* from ir-sony-decoder.c */
 #ifdef CONFIG_IR_SONY_DECODER_MODULE
 #define load_sony_decode()	request_module("ir-sony-decoder")
 #else
-#define load_sony_decode()	0
+static inline void load_sony_decode(void) { }
 #endif
 
 /* from ir-mce_kbd-decoder.c */
 #ifdef CONFIG_IR_MCE_KBD_DECODER_MODULE
 #define load_mce_kbd_decode()	request_module("ir-mce_kbd-decoder")
 #else
-#define load_mce_kbd_decode()	0
+static inline void load_mce_kbd_decode(void) { }
 #endif
 
 /* from ir-lirc-codec.c */
 #ifdef CONFIG_IR_LIRC_CODEC_MODULE
 #define load_lirc_codec()	request_module("ir-lirc-codec")
 #else
-#define load_lirc_codec()	0
+static inline void load_lirc_codec(void) { }
 #endif
 
 
diff -druN linux-libre-3.1-gnu/drivers/media/rc/rc-main.c linux-libre-3.2-gnu/drivers/media/rc/rc-main.c
--- linux-libre-3.1-gnu/drivers/media/rc/rc-main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/rc-main.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/input.h>
 #include <linux/slab.h>
 #include <linux/device.h>
+#include <linux/module.h>
 #include "rc-core-priv.h"
 
 /* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */
@@ -928,10 +929,6 @@
 
 static void rc_dev_release(struct device *device)
 {
-	struct rc_dev *dev = to_rc_dev(device);
-
-	kfree(dev);
-	module_put(THIS_MODULE);
 }
 
 #define ADD_HOTPLUG_VAR(fmt, val...)					\
@@ -945,6 +942,9 @@
 {
 	struct rc_dev *dev = to_rc_dev(device);
 
+	if (!dev || !dev->input_dev)
+		return -ENODEV;
+
 	if (dev->rc_map.name)
 		ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name);
 	if (dev->driver_name)
@@ -1013,10 +1013,16 @@
 
 void rc_free_device(struct rc_dev *dev)
 {
-	if (dev) {
+	if (!dev)
+		return;
+
+	if (dev->input_dev)
 		input_free_device(dev->input_dev);
-		put_device(&dev->dev);
-	}
+
+	put_device(&dev->dev);
+
+	kfree(dev);
+	module_put(THIS_MODULE);
 }
 EXPORT_SYMBOL_GPL(rc_free_device);
 
@@ -1143,14 +1149,18 @@
 	if (dev->driver_type == RC_DRIVER_IR_RAW)
 		ir_raw_event_unregister(dev);
 
+	/* Freeing the table should also call the stop callback */
+	ir_free_table(&dev->rc_map);
+	IR_dprintk(1, "Freed keycode table\n");
+
 	input_unregister_device(dev->input_dev);
 	dev->input_dev = NULL;
 
-	ir_free_table(&dev->rc_map);
-	IR_dprintk(1, "Freed keycode table\n");
+	device_del(&dev->dev);
 
-	device_unregister(&dev->dev);
+	rc_free_device(dev);
 }
+
 EXPORT_SYMBOL_GPL(rc_unregister_device);
 
 /*
diff -druN linux-libre-3.1-gnu/drivers/media/rc/redrat3.c linux-libre-3.2-gnu/drivers/media/rc/redrat3.c
--- linux-libre-3.1-gnu/drivers/media/rc/redrat3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/redrat3.c	2012-01-04 18:55:44.000000000 -0500
@@ -195,11 +195,6 @@
 	dma_addr_t dma_in;
 	dma_addr_t dma_out;
 
-	/* true if write urb is busy */
-	bool write_busy;
-	/* wait for the write to finish */
-	struct completion write_finished;
-
 	/* locks this structure */
 	struct mutex lock;
 
@@ -207,8 +202,6 @@
 	struct timer_list rx_timeout;
 	u32 hw_timeout;
 
-	/* Is the device currently receiving? */
-	bool recv_in_progress;
 	/* is the detector enabled*/
 	bool det_enabled;
 	/* Is the device currently transmitting?*/
diff -druN linux-libre-3.1-gnu/drivers/media/rc/winbond-cir.c linux-libre-3.2-gnu/drivers/media/rc/winbond-cir.c
--- linux-libre-3.1-gnu/drivers/media/rc/winbond-cir.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/rc/winbond-cir.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/pnp.h>
 #include <linux/interrupt.h>
@@ -1155,12 +1157,12 @@
 	case IR_PROTOCOL_RC6:
 		break;
 	default:
-		printk(KERN_ERR DRVNAME ": Invalid power-on protocol\n");
+		pr_err("Invalid power-on protocol\n");
 	}
 
 	ret = pnp_register_driver(&wbcir_driver);
 	if (ret)
-		printk(KERN_ERR DRVNAME ": Unable to register driver\n");
+		pr_err("Unable to register driver\n");
 
 	return ret;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/adp1653.c linux-libre-3.2-gnu/drivers/media/video/adp1653.c
--- linux-libre-3.1-gnu/drivers/media/video/adp1653.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/adp1653.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,7 +31,9 @@
  */
 
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <linux/i2c.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/version.h>
 #include <media/adp1653.h>
@@ -258,7 +260,7 @@
 	if (flash->ctrls.error)
 		return flash->ctrls.error;
 
-	fault->is_volatile = 1;
+	fault->flags |= V4L2_CTRL_FLAG_VOLATILE;
 
 	flash->subdev.ctrl_handler = &flash->ctrls;
 	return 0;
@@ -413,6 +415,10 @@
 	struct adp1653_flash *flash;
 	int ret;
 
+	/* we couldn't work without platform data */
+	if (client->dev.platform_data == NULL)
+		return -ENODEV;
+
 	flash = kzalloc(sizeof(*flash), GFP_KERNEL);
 	if (flash == NULL)
 		return -ENOMEM;
@@ -425,12 +431,21 @@
 	flash->subdev.internal_ops = &adp1653_internal_ops;
 	flash->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 
-	adp1653_init_controls(flash);
+	ret = adp1653_init_controls(flash);
+	if (ret)
+		goto free_and_quit;
 
 	ret = media_entity_init(&flash->subdev.entity, 0, NULL, 0);
 	if (ret < 0)
-		kfree(flash);
+		goto free_and_quit;
+
+	flash->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH;
 
+	return 0;
+
+free_and_quit:
+	v4l2_ctrl_handler_free(&flash->ctrls);
+	kfree(flash);
 	return ret;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/adv7175.c linux-libre-3.2-gnu/drivers/media/video/adv7175.c
--- linux-libre-3.1-gnu/drivers/media/video/adv7175.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/adv7175.c	2012-01-04 18:55:44.000000000 -0500
@@ -61,6 +61,11 @@
 
 static char *inputs[] = { "pass_through", "play_back", "color_bar" };
 
+static enum v4l2_mbus_pixelcode adv7175_codes[] = {
+	V4L2_MBUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_UYVY8_1X16,
+};
+
 /* ----------------------------------------------------------------------- */
 
 static inline int adv7175_write(struct v4l2_subdev *sd, u8 reg, u8 value)
@@ -296,6 +301,60 @@
 	return 0;
 }
 
+static int adv7175_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+				enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= ARRAY_SIZE(adv7175_codes))
+		return -EINVAL;
+
+	*code = adv7175_codes[index];
+	return 0;
+}
+
+static int adv7175_g_fmt(struct v4l2_subdev *sd,
+				struct v4l2_mbus_framefmt *mf)
+{
+	u8 val = adv7175_read(sd, 0x7);
+
+	if ((val & 0x40) == (1 << 6))
+		mf->code = V4L2_MBUS_FMT_UYVY8_1X16;
+	else
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+
+	mf->colorspace  = V4L2_COLORSPACE_SMPTE170M;
+	mf->width       = 0;
+	mf->height      = 0;
+	mf->field       = V4L2_FIELD_ANY;
+
+	return 0;
+}
+
+static int adv7175_s_fmt(struct v4l2_subdev *sd,
+				struct v4l2_mbus_framefmt *mf)
+{
+	u8 val = adv7175_read(sd, 0x7);
+	int ret;
+
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		val &= ~0x40;
+		break;
+
+	case V4L2_MBUS_FMT_UYVY8_1X16:
+		val |= 0x40;
+		break;
+
+	default:
+		v4l2_dbg(1, debug, sd,
+			"illegal v4l2_mbus_framefmt code: %d\n", mf->code);
+		return -EINVAL;
+	}
+
+	ret = adv7175_write(sd, 0x7, val);
+
+	return ret;
+}
+
 static int adv7175_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -324,6 +383,9 @@
 static const struct v4l2_subdev_video_ops adv7175_video_ops = {
 	.s_std_output = adv7175_s_std_output,
 	.s_routing = adv7175_s_routing,
+	.s_mbus_fmt = adv7175_s_fmt,
+	.g_mbus_fmt = adv7175_g_fmt,
+	.enum_mbus_fmt  = adv7175_enum_fmt,
 };
 
 static const struct v4l2_subdev_ops adv7175_ops = {
diff -druN linux-libre-3.1-gnu/drivers/media/video/ak881x.c linux-libre-3.2-gnu/drivers/media/video/ak881x.c
--- linux-libre-3.1-gnu/drivers/media/video/ak881x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/ak881x.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
+#include <linux/module.h>
 
 #include <media/ak881x.h>
 #include <media/v4l2-chip-ident.h>
diff -druN linux-libre-3.1-gnu/drivers/media/video/atmel-isi.c linux-libre-3.2-gnu/drivers/media/video/atmel-isi.c
--- linux-libre-3.1-gnu/drivers/media/video/atmel-isi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/atmel-isi.c	2012-01-04 18:55:44.000000000 -0500
@@ -94,6 +94,7 @@
 	unsigned int			irq;
 
 	struct isi_platform_data	*pdata;
+	u16				width_flags;	/* max 12 bits */
 
 	struct list_head		video_buffer_list;
 	struct frame_buffer		*active;
@@ -248,9 +249,9 @@
 /* ------------------------------------------------------------------
 	Videobuf operations
    ------------------------------------------------------------------*/
-static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
-				unsigned int *nplanes, unsigned long sizes[],
-				void *alloc_ctxs[])
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+				unsigned int *nbuffers, unsigned int *nplanes,
+				unsigned int sizes[], void *alloc_ctxs[])
 {
 	struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
@@ -341,7 +342,7 @@
 
 			/* Initialize the dma descriptor */
 			desc->p_fbd->fb_address =
-					vb2_dma_contig_plane_paddr(vb, 0);
+					vb2_dma_contig_plane_dma_addr(vb, 0);
 			desc->p_fbd->next_fbd_address = 0;
 			set_dma_ctrl(desc->p_fbd, ISI_DMA_CTRL_WB);
 
@@ -404,12 +405,13 @@
 
 	if (isi->active == NULL) {
 		isi->active = buf;
-		start_dma(isi, buf);
+		if (vb2_is_streaming(vb->vb2_queue))
+			start_dma(isi, buf);
 	}
 	spin_unlock_irqrestore(&isi->lock, flags);
 }
 
-static int start_streaming(struct vb2_queue *vq)
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
@@ -431,17 +433,26 @@
 	ret = wait_event_interruptible(isi->vsync_wq,
 				       isi->state != ISI_STATE_IDLE);
 	if (ret)
-		return ret;
+		goto err;
 
-	if (isi->state != ISI_STATE_READY)
-		return -EIO;
+	if (isi->state != ISI_STATE_READY) {
+		ret = -EIO;
+		goto err;
+	}
 
 	spin_lock_irq(&isi->lock);
 	isi->state = ISI_STATE_WAIT_SOF;
 	isi_writel(isi, ISI_INTDIS, ISI_SR_VSYNC);
+	if (count)
+		start_dma(isi, isi->active);
 	spin_unlock_irq(&isi->lock);
 
 	return 0;
+err:
+	isi->active = NULL;
+	isi->sequence = 0;
+	INIT_LIST_HEAD(&isi->video_buffer_list);
+	return ret;
 }
 
 /* abort streaming and wait for last buffer */
@@ -637,50 +648,42 @@
 		 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
 }
 
-static unsigned long make_bus_param(struct atmel_isi *isi)
-{
-	unsigned long flags;
-	/*
-	 * Platform specified synchronization and pixel clock polarities are
-	 * only a recommendation and are only used during probing. Atmel ISI
-	 * camera interface only works in master mode, i.e., uses HSYNC and
-	 * VSYNC signals from the sensor
-	 */
-	flags = SOCAM_MASTER |
-		SOCAM_HSYNC_ACTIVE_HIGH |
-		SOCAM_HSYNC_ACTIVE_LOW |
-		SOCAM_VSYNC_ACTIVE_HIGH |
-		SOCAM_VSYNC_ACTIVE_LOW |
-		SOCAM_PCLK_SAMPLE_RISING |
-		SOCAM_PCLK_SAMPLE_FALLING |
-		SOCAM_DATA_ACTIVE_HIGH;
-
-	if (isi->pdata->data_width_flags & ISI_DATAWIDTH_10)
-		flags |= SOCAM_DATAWIDTH_10;
-
-	if (isi->pdata->data_width_flags & ISI_DATAWIDTH_8)
-		flags |= SOCAM_DATAWIDTH_8;
-
-	if (flags & SOCAM_DATAWIDTH_MASK)
-		return flags;
-
-	return 0;
-}
+#define ISI_BUS_PARAM (V4L2_MBUS_MASTER |	\
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH |	\
+		V4L2_MBUS_HSYNC_ACTIVE_LOW |	\
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH |	\
+		V4L2_MBUS_VSYNC_ACTIVE_LOW |	\
+		V4L2_MBUS_PCLK_SAMPLE_RISING |	\
+		V4L2_MBUS_PCLK_SAMPLE_FALLING |	\
+		V4L2_MBUS_DATA_ACTIVE_HIGH)
 
 static int isi_camera_try_bus_param(struct soc_camera_device *icd,
 				    unsigned char buswidth)
 {
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct atmel_isi *isi = ici->priv;
-	unsigned long camera_flags;
+	struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+	unsigned long common_flags;
 	int ret;
 
-	camera_flags = icd->ops->query_bus_param(icd);
-	ret = soc_camera_bus_param_compatible(camera_flags,
-					make_bus_param(isi));
-	if (!ret)
-		return -EINVAL;
-	return 0;
+	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+	if (!ret) {
+		common_flags = soc_mbus_config_compatible(&cfg,
+							  ISI_BUS_PARAM);
+		if (!common_flags) {
+			dev_warn(icd->parent,
+				 "Flags incompatible: camera 0x%x, host 0x%x\n",
+				 cfg.flags, ISI_BUS_PARAM);
+			return -EINVAL;
+		}
+	} else if (ret != -ENOIOCTLCMD) {
+		return ret;
+	}
+
+	if ((1 << (buswidth - 1)) & isi->width_flags)
+		return 0;
+	return -EINVAL;
 }
 
 
@@ -802,59 +805,71 @@
 
 static int isi_camera_set_bus_param(struct soc_camera_device *icd, u32 pixfmt)
 {
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct atmel_isi *isi = ici->priv;
-	unsigned long bus_flags, camera_flags, common_flags;
+	struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+	unsigned long common_flags;
 	int ret;
 	u32 cfg1 = 0;
 
-	camera_flags = icd->ops->query_bus_param(icd);
-
-	bus_flags = make_bus_param(isi);
-	common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
-	dev_dbg(icd->parent, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n",
-		camera_flags, bus_flags, common_flags);
-	if (!common_flags)
-		return -EINVAL;
+	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+	if (!ret) {
+		common_flags = soc_mbus_config_compatible(&cfg,
+							  ISI_BUS_PARAM);
+		if (!common_flags) {
+			dev_warn(icd->parent,
+				 "Flags incompatible: camera 0x%x, host 0x%x\n",
+				 cfg.flags, ISI_BUS_PARAM);
+			return -EINVAL;
+		}
+	} else if (ret != -ENOIOCTLCMD) {
+		return ret;
+	} else {
+		common_flags = ISI_BUS_PARAM;
+	}
+	dev_dbg(icd->parent, "Flags cam: 0x%x host: 0x%x common: 0x%lx\n",
+		cfg.flags, ISI_BUS_PARAM, common_flags);
 
 	/* Make choises, based on platform preferences */
-	if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
-	    (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+	if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
+	    (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
 		if (isi->pdata->hsync_act_low)
-			common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
 		else
-			common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
 	}
 
-	if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
-	    (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
+	if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
+	    (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
 		if (isi->pdata->vsync_act_low)
-			common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
+			common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
 		else
-			common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
+			common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
 	}
 
-	if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
-	    (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+	if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
+	    (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
 		if (isi->pdata->pclk_act_falling)
-			common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+			common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
 		else
-			common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+			common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
 	}
 
-	ret = icd->ops->set_bus_param(icd, common_flags);
-	if (ret < 0) {
-		dev_dbg(icd->parent, "Camera set_bus_param(%lx) returned %d\n",
+	cfg.flags = common_flags;
+	ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+	if (ret < 0 && ret != -ENOIOCTLCMD) {
+		dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n",
 			common_flags, ret);
 		return ret;
 	}
 
 	/* set bus param for ISI */
-	if (common_flags & SOCAM_HSYNC_ACTIVE_LOW)
+	if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
 		cfg1 |= ISI_CFG1_HSYNC_POL_ACTIVE_LOW;
-	if (common_flags & SOCAM_VSYNC_ACTIVE_LOW)
+	if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
 		cfg1 |= ISI_CFG1_VSYNC_POL_ACTIVE_LOW;
-	if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
+	if (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
 		cfg1 |= ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING;
 
 	if (isi->pdata->has_emb_sync)
@@ -973,6 +988,11 @@
 		goto err_ioremap;
 	}
 
+	if (pdata->data_width_flags & ISI_DATAWIDTH_8)
+		isi->width_flags = 1 << 7;
+	if (pdata->data_width_flags & ISI_DATAWIDTH_10)
+		isi->width_flags |= 1 << 9;
+
 	isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
 
 	irq = platform_get_irq(pdev, 0);
diff -druN linux-libre-3.1-gnu/drivers/media/video/au0828/au0828-cards.c linux-libre-3.2-gnu/drivers/media/video/au0828/au0828-cards.c
--- linux-libre-3.1-gnu/drivers/media/video/au0828/au0828-cards.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/au0828/au0828-cards.c	2012-01-04 18:55:44.000000000 -0500
@@ -162,11 +162,14 @@
 	switch (tv.model) {
 	case 72000: /* WinTV-HVR950q (Retail, IR, ATSC/QAM */
 	case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
+	case 72101: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
+	case 72201: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
 	case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
 	case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
 	case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
 	case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */
 	case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
+	case 72261: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
 	case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and analog video */
 	case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */
 		break;
@@ -324,6 +327,10 @@
 		.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
 	{ USB_DEVICE(0x2040, 0x8200),
 		.driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY },
+	{ USB_DEVICE(0x2040, 0x7260),
+		.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+	{ USB_DEVICE(0x2040, 0x7213),
+		.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 	{ },
 };
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/au0828/Makefile linux-libre-3.2-gnu/drivers/media/video/au0828/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/au0828/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/au0828/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,8 +2,8 @@
 
 obj-$(CONFIG_VIDEO_AU0828) += au0828.o
 
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
 
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff -druN linux-libre-3.1-gnu/drivers/media/video/bt819.c linux-libre-3.2-gnu/drivers/media/video/bt819.c
--- linux-libre-3.1-gnu/drivers/media/video/bt819.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/bt819.c	2012-01-04 18:55:44.000000000 -0500
@@ -229,7 +229,7 @@
 	if (pstd)
 		*pstd = std;
 	if (pstatus)
-		*pstatus = status;
+		*pstatus = res;
 
 	v4l2_dbg(1, debug, sd, "get status %x\n", status);
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/media/video/bt8xx/bttv-cards.c linux-libre-3.2-gnu/drivers/media/video/bt8xx/bttv-cards.c
--- linux-libre-3.1-gnu/drivers/media/video/bt8xx/bttv-cards.c	2012-03-19 21:37:30.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/bt8xx/bttv-cards.c	2012-03-19 21:40:02.000000000 -0400
@@ -25,6 +25,8 @@
 
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/kmod.h>
@@ -2905,19 +2907,17 @@
 
 		if (type != -1) {
 			/* found it */
-			printk(KERN_INFO "bttv%d: detected: %s [card=%d], "
-			       "PCI subsystem ID is %04x:%04x\n",
-			       btv->c.nr,cards[type].name,cards[type].cardnr,
-			       btv->cardid & 0xffff,
-			       (btv->cardid >> 16) & 0xffff);
+			pr_info("%d: detected: %s [card=%d], PCI subsystem ID is %04x:%04x\n",
+				btv->c.nr, cards[type].name, cards[type].cardnr,
+				btv->cardid & 0xffff,
+				(btv->cardid >> 16) & 0xffff);
 			btv->c.type = cards[type].cardnr;
 		} else {
 			/* 404 */
-			printk(KERN_INFO "bttv%d: subsystem: %04x:%04x (UNKNOWN)\n",
-			       btv->c.nr, btv->cardid & 0xffff,
-			       (btv->cardid >> 16) & 0xffff);
-			printk(KERN_DEBUG "please mail id, board name and "
-			       "the correct card= insmod option to linux-media@vger.kernel.org\n");
+			pr_info("%d: subsystem: %04x:%04x (UNKNOWN)\n",
+				btv->c.nr, btv->cardid & 0xffff,
+				(btv->cardid >> 16) & 0xffff);
+			pr_debug("please mail id, board name and the correct card= insmod option to linux-media@vger.kernel.org\n");
 		}
 	}
 
@@ -2926,10 +2926,10 @@
 		btv->c.type=card[btv->c.nr];
 
 	/* print which card config we are using */
-	printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->c.nr,
-	       bttv_tvcards[btv->c.type].name, btv->c.type,
-	       card[btv->c.nr] < bttv_num_tvcards
-	       ? "insmod option" : "autodetected");
+	pr_info("%d: using: %s [card=%d,%s]\n",
+		btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type,
+		card[btv->c.nr] < bttv_num_tvcards
+		? "insmod option" : "autodetected");
 
 	/* overwrite gpio stuff ?? */
 	if (UNSET == audioall && UNSET == audiomux[0])
@@ -2948,12 +2948,13 @@
 		}
 	}
 	bttv_tvcards[btv->c.type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits;
-	printk(KERN_INFO "bttv%d: gpio config override: mask=0x%x, mux=",
-	       btv->c.nr,bttv_tvcards[btv->c.type].gpiomask);
+	pr_info("%d: gpio config override: mask=0x%x, mux=",
+		btv->c.nr, bttv_tvcards[btv->c.type].gpiomask);
 	for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) {
-		printk("%s0x%x", i ? "," : "", bttv_tvcards[btv->c.type].gpiomux[i]);
+		pr_cont("%s0x%x",
+			i ? "," : "", bttv_tvcards[btv->c.type].gpiomux[i]);
 	}
-	printk("\n");
+	pr_cont("\n");
 }
 
 /*
@@ -2974,8 +2975,8 @@
 
 	if (-1 != type) {
 		btv->c.type = type;
-		printk("bttv%d: detected by eeprom: %s [card=%d]\n",
-		       btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type);
+		pr_info("%d: detected by eeprom: %s [card=%d]\n",
+			btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type);
 	}
 }
 
@@ -3019,7 +3020,7 @@
 		tuner_type = 3;  /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */
 		break;
 	default:
-		printk(KERN_INFO "bttv%d: FlyVideo_gpio: unknown tuner type.\n", btv->c.nr);
+		pr_info("%d: FlyVideo_gpio: unknown tuner type\n", btv->c.nr);
 		break;
 	}
 
@@ -3036,13 +3037,13 @@
 	if (is_capture_only)
 		tuner_type = TUNER_ABSENT; /* No tuner present */
 
-	printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
-		btv->c.nr, has_radio ? "yes" : "no ",
-		has_remote ? "yes" : "no ", tuner_type, gpio);
-	printk(KERN_INFO "bttv%d: FlyVideo  LR90=%s tda9821/tda9820=%s capture_only=%s\n",
-		btv->c.nr, is_lr90 ? "yes" : "no ",
-		has_tda9820_tda9821 ? "yes" : "no ",
-		is_capture_only ? "yes" : "no ");
+	pr_info("%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
+		btv->c.nr, has_radio ? "yes" : "no",
+		has_remote ? "yes" : "no", tuner_type, gpio);
+	pr_info("%d: FlyVideo  LR90=%s tda9821/tda9820=%s capture_only=%s\n",
+		btv->c.nr, is_lr90 ? "yes" : "no",
+		has_tda9820_tda9821 ? "yes" : "no",
+		is_capture_only ? "yes" : "no");
 
 	if (tuner_type != UNSET) /* only set if known tuner autodetected, else let insmod option through */
 		btv->tuner_type = tuner_type;
@@ -3091,12 +3092,11 @@
 			if (btv->c.type == BTTV_BOARD_PINNACLE)
 				btv->c.type = BTTV_BOARD_PINNACLEPRO;
 		}
-		printk(KERN_INFO
-		       "bttv%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
-		       btv->c.nr, id+1, btv->tuner_type,
-		       !btv->has_radio ? "no" :
-		       (btv->has_matchbox ? "matchbox" : "fmtuner"),
-		       (-1 == msp) ? "no" : "yes");
+		pr_info("%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
+			btv->c.nr, id+1, btv->tuner_type,
+			!btv->has_radio ? "no" :
+			(btv->has_matchbox ? "matchbox" : "fmtuner"),
+			(-1 == msp) ? "no" : "yes");
 	} else {
 		/* new cards with microtune tuner */
 		id = 63 - id;
@@ -3138,9 +3138,8 @@
 		}
 		if (-1 != msp)
 			btv->c.type = BTTV_BOARD_PINNACLEPRO;
-		printk(KERN_INFO
-		       "bttv%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
-		       btv->c.nr, id, info, btv->has_radio ? "yes" : "no");
+		pr_info("%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
+			btv->c.nr, id, info, btv->has_radio ? "yes" : "no");
 		btv->tuner_type = TUNER_MT2032;
 	}
 }
@@ -3202,7 +3201,7 @@
 
 static void init_lmlbt4x(struct bttv *btv)
 {
-	printk(KERN_DEBUG "LMLBT4x init\n");
+	pr_debug("LMLBT4x init\n");
 	btwrite(0x000000, BT848_GPIO_REG_INP);
 	gpio_inout(0xffffff, 0x0006C0);
 	gpio_write(0x000000);
@@ -3246,7 +3245,7 @@
 		return;
 
 	if (bttv_debug)
-		printk("bttv%d: BT878A ARESET\n",btv->c.nr);
+		pr_debug("%d: BT878A ARESET\n", btv->c.nr);
 	btwrite((1<<7), 0x058);
 	udelay(10);
 	btwrite(     0, 0x058);
@@ -3349,7 +3348,8 @@
 	case BTTV_BOARD_MAGICTVIEW061:
 		if (btv->cardid == 0x3002144f) {
 			btv->has_radio=1;
-			printk("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->c.nr);
+			pr_info("%d: radio detected by subsystem id (CPH05x)\n",
+				btv->c.nr);
 		}
 		break;
 	case BTTV_BOARD_STB2:
@@ -3438,17 +3438,16 @@
 		btv->tuner_type = tuner[btv->c.nr];
 
 	if (btv->tuner_type == TUNER_ABSENT)
-		printk(KERN_INFO "bttv%d: tuner absent\n", btv->c.nr);
-	else if(btv->tuner_type == UNSET)
-		printk(KERN_WARNING "bttv%d: tuner type unset\n", btv->c.nr);
+		pr_info("%d: tuner absent\n", btv->c.nr);
+	else if (btv->tuner_type == UNSET)
+		pr_warn("%d: tuner type unset\n", btv->c.nr);
 	else
-		printk(KERN_INFO "bttv%d: tuner type=%d\n", btv->c.nr,
-		       btv->tuner_type);
+		pr_info("%d: tuner type=%d\n", btv->c.nr, btv->tuner_type);
 
 	if (autoload != UNSET) {
-		printk(KERN_WARNING "bttv%d: the autoload option is obsolete.\n", btv->c.nr);
-		printk(KERN_WARNING "bttv%d: use option msp3400, tda7432 or tvaudio to\n", btv->c.nr);
-		printk(KERN_WARNING "bttv%d: override which audio module should be used.\n", btv->c.nr);
+		pr_warn("%d: the autoload option is obsolete\n", btv->c.nr);
+		pr_warn("%d: use option msp3400, tda7432 or tvaudio to override which audio module should be used\n",
+			btv->c.nr);
 	}
 
 	if (UNSET == btv->tuner_type)
@@ -3541,8 +3540,7 @@
 	}
 
 	default:
-		printk(KERN_WARNING "bttv%d: unknown audiodev value!\n",
-			btv->c.nr);
+		pr_warn("%d: unknown audiodev value!\n", btv->c.nr);
 		return;
 	}
 
@@ -3585,8 +3583,7 @@
 		return;
 
 no_audio:
-	printk(KERN_WARNING "bttv%d: audio absent, no audio device found!\n",
-			btv->c.nr);
+	pr_warn("%d: audio absent, no audio device found!\n", btv->c.nr);
 }
 
 
@@ -3639,19 +3636,19 @@
 {
 	if( strncmp(&(eeprom_data[0x1e]),"Temic 4066 FY5",14) ==0) {
 		btv->tuner_type=TUNER_TEMIC_4066FY5_PAL_I;
-		printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n",
-		       btv->c.nr,&eeprom_data[0x1e]);
+		pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+			btv->c.nr, &eeprom_data[0x1e]);
 	} else if (strncmp(&(eeprom_data[0x1e]),"Alps TSBB5",10) ==0) {
 		btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I;
-		printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n",
-		       btv->c.nr,&eeprom_data[0x1e]);
+		pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+			btv->c.nr, &eeprom_data[0x1e]);
 	} else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) {
 		btv->tuner_type=TUNER_PHILIPS_NTSC;
-		printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n",
-		       btv->c.nr,&eeprom_data[0x1e]);
+		pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+			btv->c.nr, &eeprom_data[0x1e]);
 	} else {
-		printk("bttv%d: Modtec: Unknown TunerString: %s\n",
-		       btv->c.nr,&eeprom_data[0x1e]);
+		pr_info("%d: Modtec: Unknown TunerString: %s\n",
+			btv->c.nr, &eeprom_data[0x1e]);
 	}
 }
 
@@ -3663,7 +3660,7 @@
 	btv->tuner_type = tv.tuner_type;
 	btv->has_radio  = tv.has_radio;
 
-	printk("bttv%d: Hauppauge eeprom indicates model#%d\n",
+	pr_info("%d: Hauppauge eeprom indicates model#%d\n",
 		btv->c.nr, tv.model);
 
 	/*
@@ -3671,7 +3668,7 @@
 	 * type based on model #.
 	 */
 	if(tv.model == 64900) {
-		printk("bttv%d: Switching board type from %s to %s\n",
+		pr_info("%d: Switching board type from %s to %s\n",
 			btv->c.nr,
 			bttv_tvcards[btv->c.type].name,
 			bttv_tvcards[BTTV_BOARD_HAUPPAUGE_IMPACTVCB].name);
@@ -3698,8 +3695,7 @@
 	freq=88000/62.5;
 	tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */
 	if (0x1ed8 == tea5757_read(btv)) {
-		printk("bttv%d: Terratec Active Radio Upgrade found.\n",
-		       btv->c.nr);
+		pr_info("%d: Terratec Active Radio Upgrade found\n", btv->c.nr);
 		btv->has_radio    = 1;
 		btv->has_saa6588  = 1;
 		btv->has_matchbox = 1;
@@ -3768,13 +3764,12 @@
 
 	rc = reject_firmware(&fw_entry, "/*(DEBLOBBED)*/", &btv->c.pci->dev);
 	if (rc != 0) {
-		printk(KERN_WARNING "bttv%d: no altera firmware [via hotplug]\n",
-		       btv->c.nr);
+		pr_warn("%d: no altera firmware [via hotplug]\n", btv->c.nr);
 		return rc;
 	}
 	rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size);
-	printk(KERN_INFO "bttv%d: altera firmware upload %s\n",
-	       btv->c.nr, (rc < 0) ? "failed" : "ok");
+	pr_info("%d: altera firmware upload %s\n",
+		btv->c.nr, (rc < 0) ? "failed" : "ok");
 	release_firmware(fw_entry);
 	return rc;
 }
@@ -3870,29 +3865,27 @@
 			break;
 		default:
 			/* unknown...leave generic, but get serial # */
-			printk(KERN_INFO "bttv%d: "
-			       "osprey eeprom: unknown card type 0x%04x\n",
-			       btv->c.nr, type);
+			pr_info("%d: osprey eeprom: unknown card type 0x%04x\n",
+				btv->c.nr, type);
 			break;
 		}
 		serial = get_unaligned_be32((__be32 *)(ee+6));
 	}
 
-	printk(KERN_INFO "bttv%d: osprey eeprom: card=%d '%s' serial=%u\n",
-	       btv->c.nr, cardid,
-	       cardid>0 ? bttv_tvcards[cardid].name : "Unknown", serial);
+	pr_info("%d: osprey eeprom: card=%d '%s' serial=%u\n",
+		btv->c.nr, cardid,
+		cardid > 0 ? bttv_tvcards[cardid].name : "Unknown", serial);
 
 	if (cardid<0 || btv->c.type == cardid)
 		return;
 
 	/* card type isn't set correctly */
 	if (card[btv->c.nr] < bttv_num_tvcards) {
-		printk(KERN_WARNING "bttv%d: osprey eeprom: "
-		       "Not overriding user specified card type\n", btv->c.nr);
+		pr_warn("%d: osprey eeprom: Not overriding user specified card type\n",
+			btv->c.nr);
 	} else {
-		printk(KERN_INFO "bttv%d: osprey eeprom: "
-		       "Changing card type from %d to %d\n", btv->c.nr,
-		       btv->c.type, cardid);
+		pr_info("%d: osprey eeprom: Changing card type from %d to %d\n",
+			btv->c.nr, btv->c.type, cardid);
 		btv->c.type = cardid;
 	}
 }
@@ -3935,14 +3928,14 @@
 		if (tuner_format == 0x09)
 			tuner_type = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */
 
-	printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=",
+	pr_info("%d: Avermedia eeprom[0x%02x%02x]: tuner=",
 		btv->c.nr, eeprom_data[0x41], eeprom_data[0x42]);
 	if (tuner_type) {
 		btv->tuner_type = tuner_type;
-		printk(KERN_CONT "%d", tuner_type);
+		pr_cont("%d", tuner_type);
 	} else
-		printk(KERN_CONT "Unknown type");
-	printk(KERN_CONT " radio:%s remote control:%s\n",
+		pr_cont("Unknown type");
+	pr_cont(" radio:%s remote control:%s\n",
 	       tuner_tv_fm     ? "yes" : "no",
 	       btv->has_remote ? "yes" : "no");
 }
@@ -3990,8 +3983,8 @@
 	if (bttv_gpio)
 		bttv_gpio_tracking(btv,"msp34xx");
 	if (bttv_verbose)
-		printk(KERN_INFO "bttv%d: Hauppauge/Voodoo msp34xx: reset line "
-		       "init [%d]\n", btv->c.nr, pin);
+		pr_info("%d: Hauppauge/Voodoo msp34xx: reset line init [%d]\n",
+			btv->c.nr, pin);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -4031,7 +4024,7 @@
 	btwrite(BT848_ADC_RESERVED|BT848_ADC_AGC_EN, BT848_ADC);
 
 	/*	Initialise MAX517 DAC */
-	printk(KERN_INFO "Setting DAC reference voltage level ...\n");
+	pr_info("Setting DAC reference voltage level ...\n");
 	bttv_I2CWrite(btv,0x5E,0,0x80,1);
 
 	/*	Initialise 12C508 PIC */
@@ -4040,7 +4033,7 @@
 	 *	argument so the numbers are different */
 
 
-	printk(KERN_INFO "Initialising 12C508 PIC chip ...\n");
+	pr_info("Initialising 12C508 PIC chip ...\n");
 
 	/* First of all, enable the clock line. This is used in the PXC200-F */
 	val = btread(BT848_GPIO_DMA_CTL);
@@ -4059,13 +4052,12 @@
 	for (i = 0; i < ARRAY_SIZE(vals); i++) {
 		tmp=bttv_I2CWrite(btv,0x1E,0,vals[i],1);
 		if (tmp != -1) {
-			printk(KERN_INFO
-			       "I2C Write(%2.2x) = %i\nI2C Read () = %2.2x\n\n",
+			pr_info("I2C Write(%2.2x) = %i\nI2C Read () = %2.2x\n\n",
 			       vals[i],tmp,bttv_I2CRead(btv,0x1F,NULL));
 		}
 	}
 
-	printk(KERN_INFO "PXC200 Initialised.\n");
+	pr_info("PXC200 Initialised\n");
 }
 
 
@@ -4104,8 +4096,7 @@
 	uint32_t dataRead = 0;
 	long watchdog_value = 0x0E;
 
-	printk (KERN_INFO
-		"bttv%d: Adlink RTV-24 initialisation in progress ...\n",
+	pr_info("%d: Adlink RTV-24 initialisation in progress ...\n",
 		btv->c.nr);
 
 	btwrite (0x00c3feff, BT848_GPIO_OUT_EN);
@@ -4119,8 +4110,7 @@
 	dataRead = btread (BT848_GPIO_DATA);
 
 	if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 1)) {
-		printk (KERN_INFO
-			"bttv%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n",
+		pr_info("%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n",
 			btv->c.nr, dataRead);
 	}
 
@@ -4133,15 +4123,13 @@
 	dataRead = btread (BT848_GPIO_DATA);
 
 	if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 0)) {
-		printk (KERN_INFO
-			"bttv%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n",
+		pr_info("%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n",
 			btv->c.nr, dataRead);
 
 		return;
 	}
 
-	printk (KERN_INFO
-		"bttv%d: Adlink RTV-24 initialisation complete.\n", btv->c.nr);
+	pr_info("%d: Adlink RTV-24 initialisation complete\n", btv->c.nr);
 }
 
 
@@ -4258,22 +4246,25 @@
 	while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout))
 		schedule();
 	if (bus_in(btv,btv->mbox_data)) {
-		printk(KERN_WARNING "bttv%d: tea5757: read timeout\n",btv->c.nr);
+		pr_warn("%d: tea5757: read timeout\n", btv->c.nr);
 		return -1;
 	}
 
-	dprintk("bttv%d: tea5757:",btv->c.nr);
+	dprintk("%d: tea5757:", btv->c.nr);
 	for (i = 0; i < 24; i++) {
 		udelay(5);
 		bus_high(btv,btv->mbox_clk);
 		udelay(5);
-		dprintk("%c",(bus_in(btv,btv->mbox_most) == 0)?'T':'-');
+		dprintk_cont("%c",
+			     bus_in(btv, btv->mbox_most) == 0 ? 'T' : '-');
 		bus_low(btv,btv->mbox_clk);
 		value <<= 1;
 		value |= (bus_in(btv,btv->mbox_data) == 0)?0:1;  /* MSB first */
-		dprintk("%c", (bus_in(btv,btv->mbox_most) == 0)?'S':'M');
+		dprintk_cont("%c",
+			     bus_in(btv, btv->mbox_most) == 0 ? 'S' : 'M');
 	}
-	dprintk("\nbttv%d: tea5757: read 0x%X\n", btv->c.nr, value);
+	dprintk_cont("\n");
+	dprintk("%d: tea5757: read 0x%X\n", btv->c.nr, value);
 	return value;
 }
 
@@ -4292,7 +4283,7 @@
 	if (bttv_gpio)
 		bttv_gpio_tracking(btv,"tea5757 write");
 
-	dprintk("bttv%d: tea5757: write 0x%X\n", btv->c.nr, value);
+	dprintk("%d: tea5757: write 0x%X\n", btv->c.nr, value);
 	bus_low(btv,btv->mbox_clk);
 	bus_high(btv,btv->mbox_we);
 	for (i = 0; i < 25; i++) {
@@ -4544,7 +4535,7 @@
 static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input)
 {
 
-	dprintk (KERN_DEBUG "bttv%d : picolo_tetra_muxsel =>  input = %d\n",btv->c.nr,input);
+	dprintk("%d : picolo_tetra_muxsel =>  input = %d\n", btv->c.nr, input);
 	/*Just set the right path in the analog multiplexers : channel 1 -> 4 ==> Analog Mux ==> MUX0*/
 	/*GPIO[20]&GPIO[21] used to choose the right input*/
 	btwrite (input<<20,BT848_GPIO_DATA);
@@ -4589,7 +4580,7 @@
 	int key = input % 4;
 	int matrix = input / 4;
 
-	dprintk("bttv%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n",
+	dprintk("%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n",
 		btv->c.nr, input, matrix, key);
 
 	/* Handles the input selection on the TDA8540's */
@@ -4646,15 +4637,17 @@
 	buf[1]=0;
 	rc=bttv_I2CWrite(btv,(PX_I2C_PIC<<1),buf[0],buf[1],1);
 	if (rc) {
-	  printk(KERN_DEBUG "bttv%d: PXC200_muxsel: pic cfg write failed:%d\n", btv->c.nr,rc);
+		pr_debug("%d: PXC200_muxsel: pic cfg write failed:%d\n",
+			 btv->c.nr, rc);
 	  /* not PXC ? do nothing */
-	  return;
+		return;
 	}
 
 	rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),NULL);
 	if (!(rc & PX_CFG_PXC200F)) {
-	  printk(KERN_DEBUG "bttv%d: PXC200_muxsel: not PXC200F rc:%d \n", btv->c.nr,rc);
-	  return;
+		pr_debug("%d: PXC200_muxsel: not PXC200F rc:%d\n",
+			 btv->c.nr, rc);
+		return;
 	}
 
 
@@ -4693,7 +4686,7 @@
 	else /* older device */
 	  btand(~BT848_IFORM_MUXSEL,BT848_IFORM);
 
-	printk(KERN_DEBUG "bttv%d: setting input channel to:%d\n", btv->c.nr,(int)mux);
+	pr_debug("%d: setting input channel to:%d\n", btv->c.nr, (int)mux);
 }
 
 static void phytec_muxsel(struct bttv *btv, unsigned int input)
@@ -4844,29 +4837,27 @@
 
 	/* print warnings about any quirks found */
 	if (triton1)
-		printk(KERN_INFO "bttv: Host bridge needs ETBF enabled.\n");
+		pr_info("Host bridge needs ETBF enabled\n");
 	if (vsfx)
-		printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n");
+		pr_info("Host bridge needs VSFX enabled\n");
 	if (pcipci_fail) {
-		printk(KERN_INFO "bttv: bttv and your chipset may not work "
-							"together.\n");
+		pr_info("bttv and your chipset may not work together\n");
 		if (!no_overlay) {
-			printk(KERN_INFO "bttv: overlay will be disabled.\n");
+			pr_info("overlay will be disabled\n");
 			no_overlay = 1;
 		} else {
-			printk(KERN_INFO "bttv: overlay forced. Use this "
-						"option at your own risk.\n");
+			pr_info("overlay forced. Use this option at your own risk.\n");
 		}
 	}
 	if (UNSET != latency)
-		printk(KERN_INFO "bttv: pci latency fixup [%d]\n",latency);
+		pr_info("pci latency fixup [%d]\n", latency);
 	while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL,
 				      PCI_DEVICE_ID_INTEL_82441, dev))) {
 		unsigned char b;
 		pci_read_config_byte(dev, 0x53, &b);
 		if (bttv_debug)
-			printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, "
-			       "bufcon=0x%02x\n",b);
+			pr_info("Host bridge: 82441FX Natoma, bufcon=0x%02x\n",
+				b);
 	}
 }
 
@@ -4879,12 +4870,13 @@
 
 	if (bttv_verbose) {
 		if (triton1)
-			printk(KERN_INFO "bttv%d: enabling ETBF (430FX/VP3 compatibilty)\n",btv->c.nr);
+			pr_info("%d: enabling ETBF (430FX/VP3 compatibility)\n",
+				btv->c.nr);
 		if (vsfx && btv->id >= 878)
-			printk(KERN_INFO "bttv%d: enabling VSFX\n",btv->c.nr);
+			pr_info("%d: enabling VSFX\n", btv->c.nr);
 		if (UNSET != latency)
-			printk(KERN_INFO "bttv%d: setting pci timer to %d\n",
-			       btv->c.nr,latency);
+			pr_info("%d: setting pci timer to %d\n",
+				btv->c.nr, latency);
 	}
 
 	if (btv->id < 878) {
diff -druN linux-libre-3.1-gnu/drivers/media/video/bt8xx/bttv-driver.c linux-libre-3.2-gnu/drivers/media/video/bt8xx/bttv-driver.c
--- linux-libre-3.1-gnu/drivers/media/video/bt8xx/bttv-driver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/bt8xx/bttv-driver.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,6 +34,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/delay.h>
@@ -942,8 +944,8 @@
 void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
 {
 	if ((fh->resources & bits) != bits) {
-		/* trying to free ressources not allocated by us ... */
-		printk("bttv: BUG! (btres)\n");
+		/* trying to free resources not allocated by us ... */
+		pr_err("BUG! (btres)\n");
 	}
 	fh->resources  &= ~bits;
 	btv->resources &= ~bits;
@@ -1000,7 +1002,7 @@
 		return;
 
 	if (btv->pll.pll_ofreq == btv->pll.pll_current) {
-		dprintk("bttv%d: PLL: no change required\n",btv->c.nr);
+		dprintk("%d: PLL: no change required\n", btv->c.nr);
 		return;
 	}
 
@@ -1008,21 +1010,23 @@
 		/* no PLL needed */
 		if (btv->pll.pll_current == 0)
 			return;
-		bttv_printk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n",
-			btv->c.nr,btv->pll.pll_ifreq);
+		if (bttv_verbose)
+			pr_info("%d: PLL can sleep, using XTAL (%d)\n",
+				btv->c.nr, btv->pll.pll_ifreq);
 		btwrite(0x00,BT848_TGCTRL);
 		btwrite(0x00,BT848_PLL_XCI);
 		btv->pll.pll_current = 0;
 		return;
 	}
 
-	bttv_printk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr,
-		btv->pll.pll_ifreq, btv->pll.pll_ofreq);
+	if (bttv_verbose)
+		pr_info("%d: Setting PLL: %d => %d (needs up to 100ms)\n",
+			btv->c.nr,
+			btv->pll.pll_ifreq, btv->pll.pll_ofreq);
 	set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
 
 	for (i=0; i<10; i++) {
 		/*  Let other people run while the PLL stabilizes */
-		bttv_printk(".");
 		msleep(10);
 
 		if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
@@ -1030,12 +1034,14 @@
 		} else {
 			btwrite(0x08,BT848_TGCTRL);
 			btv->pll.pll_current = btv->pll.pll_ofreq;
-			bttv_printk(" ok\n");
+			if (bttv_verbose)
+				pr_info("PLL set ok\n");
 			return;
 		}
 	}
 	btv->pll.pll_current = -1;
-	bttv_printk("failed\n");
+	if (bttv_verbose)
+		pr_info("Setting PLL failed\n");
 	return;
 }
 
@@ -1047,7 +1053,7 @@
 	int fsc       = bttv_tvnorms[btv->tvnorm].Fsc;
 
 	if (btv->input == btv->dig) {
-		dprintk("bttv%d: load digital timing table (table_idx=%d)\n",
+		dprintk("%d: load digital timing table (table_idx=%d)\n",
 			btv->c.nr,table_idx);
 
 		/* timing change...reset timing generator address */
@@ -1076,7 +1082,7 @@
 {
 	int value;
 
-	// printk("bttv: set bright: %d\n",bright); // DEBUG
+	// printk("set bright: %d\n", bright); // DEBUG
 	btv->bright = bright;
 
 	/* We want -128 to 127 we get 0-65535 */
@@ -1150,8 +1156,7 @@
 	}
 	mux = bttv_muxsel(btv, input);
 	btaor(mux<<5, ~(3<<5), BT848_IFORM);
-	dprintk(KERN_DEBUG "bttv%d: video mux: input=%d mux=%d\n",
-		btv->c.nr,input,mux);
+	dprintk("%d: video mux: input=%d mux=%d\n", btv->c.nr, input, mux);
 
 	/* card specific hook */
 	if(bttv_tvcards[btv->c.type].muxsel_hook)
@@ -1440,7 +1445,7 @@
 	unsigned long flags;
 
 	if (bttv_verbose)
-		printk(KERN_INFO "bttv%d: reset, reinitialize\n",btv->c.nr);
+		pr_info("%d: reset, reinitialize\n", btv->c.nr);
 	spin_lock_irqsave(&btv->s_lock,flags);
 	btv->errors=0;
 	bttv_set_dma(btv,0);
@@ -1622,8 +1627,8 @@
 	unsigned int outbits, data;
 	outbits = btread(BT848_GPIO_OUT_EN);
 	data    = btread(BT848_GPIO_DATA);
-	printk(KERN_DEBUG "bttv%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
-	       btv->c.nr,outbits,data & outbits, data & ~outbits, comment);
+	pr_debug("%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
+		 btv->c.nr, outbits, data & outbits, data & ~outbits, comment);
 }
 
 static void bttv_field_count(struct bttv *btv)
@@ -1668,7 +1673,7 @@
 	unsigned long flags;
 	int retval = 0;
 
-	dprintk("switch_overlay: enter [new=%p]\n",new);
+	dprintk("switch_overlay: enter [new=%p]\n", new);
 	if (new)
 		new->vb.state = VIDEOBUF_DONE;
 	spin_lock_irqsave(&btv->s_lock,flags);
@@ -1678,7 +1683,8 @@
 	bttv_set_dma(btv, 0x03);
 	spin_unlock_irqrestore(&btv->s_lock,flags);
 	if (NULL != old) {
-		dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state);
+		dprintk("switch_overlay: old=%p state is %d\n",
+			old, old->vb.state);
 		bttv_dma_free(&fh->cap,btv, old);
 		kfree(old);
 	}
@@ -2029,11 +2035,11 @@
 	struct bttv_fh *fh  = f;
 	struct bttv *btv = fh->btv;
 
-	printk(KERN_INFO "bttv%d: ========  START STATUS CARD #%d  ========\n",
-			btv->c.nr, btv->c.nr);
+	pr_info("%d: ========  START STATUS CARD #%d  ========\n",
+		btv->c.nr, btv->c.nr);
 	bttv_call_all(btv, core, log_status);
-	printk(KERN_INFO "bttv%d: ========  END STATUS CARD   #%d  ========\n",
-			btv->c.nr, btv->c.nr);
+	pr_info("%d: ========  END STATUS CARD   #%d  ========\n",
+		btv->c.nr, btv->c.nr);
 	return 0;
 }
 
@@ -2598,7 +2604,7 @@
 	struct bttv *btv = fh->btv;
 
 	if (no_overlay > 0) {
-		printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+		pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
 		return -EINVAL;
 	}
 
@@ -2673,7 +2679,7 @@
 	int rc;
 
 	if (no_overlay > 0) {
-		printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+		pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
 		return -EINVAL;
 	}
 
@@ -2714,7 +2720,7 @@
 			return -EINVAL;
 		}
 		if (unlikely(!fh->ov.setup_ok)) {
-			dprintk("bttv%d: overlay: !setup_ok\n", btv->c.nr);
+			dprintk("%d: overlay: !setup_ok\n", btv->c.nr);
 			retval = -EINVAL;
 		}
 		if (retval)
@@ -3091,8 +3097,8 @@
 
 	if (fh->btv->errors)
 		bttv_reinit_bt848(fh->btv);
-	dprintk("bttv%d: read count=%d type=%s\n",
-		fh->btv->c.nr,(int)count,v4l2_type_names[fh->type]);
+	dprintk("%d: read count=%d type=%s\n",
+		fh->btv->c.nr, (int)count, v4l2_type_names[fh->type]);
 
 	switch (fh->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -3174,7 +3180,7 @@
 	struct bttv_fh *fh;
 	enum v4l2_buf_type type = 0;
 
-	dprintk(KERN_DEBUG "bttv: open dev=%s\n", video_device_node_name(vdev));
+	dprintk("open dev=%s\n", video_device_node_name(vdev));
 
 	if (vdev->vfl_type == VFL_TYPE_GRABBER) {
 		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -3185,8 +3191,8 @@
 		return -ENODEV;
 	}
 
-	dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n",
-		btv->c.nr,v4l2_type_names[type]);
+	dprintk("%d: open called (type=%s)\n",
+		btv->c.nr, v4l2_type_names[type]);
 
 	/* allocate per filehandle data */
 	fh = kmalloc(sizeof(*fh), GFP_KERNEL);
@@ -3288,7 +3294,7 @@
 {
 	struct bttv_fh *fh = file->private_data;
 
-	dprintk("bttv%d: mmap type=%s 0x%lx+%ld\n",
+	dprintk("%d: mmap type=%s 0x%lx+%ld\n",
 		fh->btv->c.nr, v4l2_type_names[fh->type],
 		vma->vm_start, vma->vm_end - vma->vm_start);
 	return videobuf_mmap_mapper(bttv_queue(fh),vma);
@@ -3370,9 +3376,9 @@
 	struct bttv *btv = video_drvdata(file);
 	struct bttv_fh *fh;
 
-	dprintk("bttv: open dev=%s\n", video_device_node_name(vdev));
+	dprintk("open dev=%s\n", video_device_node_name(vdev));
 
-	dprintk("bttv%d: open called (radio)\n",btv->c.nr);
+	dprintk("%d: open called (radio)\n", btv->c.nr);
 
 	/* allocate per filehandle data */
 	fh = kmalloc(sizeof(*fh), GFP_KERNEL);
@@ -3616,12 +3622,12 @@
 	};
 	int i;
 
-	printk("0x%08x [ %s", risc,
+	pr_cont("0x%08x [ %s", risc,
 	       instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
 	for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
 		if (risc & (1 << (i + 12)))
-			printk(" %s",bits[i]);
-	printk(" count=%d ]\n", risc & 0xfff);
+			pr_cont(" %s", bits[i]);
+	pr_cont(" count=%d ]\n", risc & 0xfff);
 	return incr[risc >> 28] ? incr[risc >> 28] : 1;
 }
 
@@ -3630,16 +3636,18 @@
 {
 	unsigned int i,j,n;
 
-	printk("%s: risc disasm: %p [dma=0x%08lx]\n",
-	       btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
+	pr_info("%s: risc disasm: %p [dma=0x%08lx]\n",
+		btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
 	for (i = 0; i < (risc->size >> 2); i += n) {
-		printk("%s:   0x%lx: ", btv->c.v4l2_dev.name,
-		       (unsigned long)(risc->dma + (i<<2)));
+		pr_info("%s:   0x%lx: ",
+			btv->c.v4l2_dev.name,
+			(unsigned long)(risc->dma + (i<<2)));
 		n = bttv_risc_decode(le32_to_cpu(risc->cpu[i]));
 		for (j = 1; j < n; j++)
-			printk("%s:   0x%lx: 0x%08x [ arg #%d ]\n",
-			       btv->c.v4l2_dev.name, (unsigned long)(risc->dma + ((i+j)<<2)),
-			       risc->cpu[i+j], j);
+			pr_info("%s:   0x%lx: 0x%08x [ arg #%d ]\n",
+				btv->c.v4l2_dev.name,
+				(unsigned long)(risc->dma + ((i+j)<<2)),
+				risc->cpu[i+j], j);
 		if (0 == risc->cpu[i])
 			break;
 	}
@@ -3647,17 +3655,18 @@
 
 static void bttv_print_riscaddr(struct bttv *btv)
 {
-	printk("  main: %08Lx\n",
-	       (unsigned long long)btv->main.dma);
-	printk("  vbi : o=%08Lx e=%08Lx\n",
-	       btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
-	       btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
-	printk("  cap : o=%08Lx e=%08Lx\n",
-	       btv->curr.top    ? (unsigned long long)btv->curr.top->top.dma : 0,
-	       btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
-	printk("  scr : o=%08Lx e=%08Lx\n",
-	       btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
-	       btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
+	pr_info("  main: %08llx\n", (unsigned long long)btv->main.dma);
+	pr_info("  vbi : o=%08llx e=%08llx\n",
+		btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
+		btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
+	pr_info("  cap : o=%08llx e=%08llx\n",
+		btv->curr.top
+		? (unsigned long long)btv->curr.top->top.dma : 0,
+		btv->curr.bottom
+		? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
+	pr_info("  scr : o=%08llx e=%08llx\n",
+		btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
+		btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
 	bttv_risc_disasm(btv, &btv->main);
 }
 
@@ -3690,34 +3699,34 @@
 {
 	unsigned int i;
 
-	printk("bits:");
+	pr_cont("bits:");
 	for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
 		if (print & (1 << i))
-			printk(" %s",irq_name[i]);
+			pr_cont(" %s", irq_name[i]);
 		if (mark & (1 << i))
-			printk("*");
+			pr_cont("*");
 	}
 }
 
 static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
 {
-	printk("bttv%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
-	       btv->c.nr,
-	       (unsigned long)btv->main.dma,
-	       (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
-	       (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
-	       (unsigned long)rc);
+	pr_warn("%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
+		btv->c.nr,
+		(unsigned long)btv->main.dma,
+		(unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
+		(unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
+		(unsigned long)rc);
 
 	if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
-		printk("bttv%d: Oh, there (temporarely?) is no input signal. "
-		       "Ok, then this is harmless, don't worry ;)\n",
-		       btv->c.nr);
+		pr_notice("%d: Oh, there (temporarily?) is no input signal. "
+			  "Ok, then this is harmless, don't worry ;)\n",
+			  btv->c.nr);
 		return;
 	}
-	printk("bttv%d: Uhm. Looks like we have unusual high IRQ latencies.\n",
-	       btv->c.nr);
-	printk("bttv%d: Lets try to catch the culpit red-handed ...\n",
-	       btv->c.nr);
+	pr_notice("%d: Uhm. Looks like we have unusual high IRQ latencies\n",
+		  btv->c.nr);
+	pr_notice("%d: Lets try to catch the culpit red-handed ...\n",
+		  btv->c.nr);
 	dump_stack();
 }
 
@@ -3798,9 +3807,9 @@
 		}
 	}
 
-	dprintk("bttv%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
-		btv->c.nr,set->top, set->bottom,
-		btv->screen,set->frame_irq,set->top_irq);
+	dprintk("%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
+		btv->c.nr, set->top, set->bottom,
+		btv->screen, set->frame_irq, set->top_irq);
 	return 0;
 }
 
@@ -3815,7 +3824,8 @@
 	if (wakeup->top == wakeup->bottom) {
 		if (NULL != wakeup->top && curr->top != wakeup->top) {
 			if (irq_debug > 1)
-				printk("bttv%d: wakeup: both=%p\n",btv->c.nr,wakeup->top);
+				pr_debug("%d: wakeup: both=%p\n",
+					 btv->c.nr, wakeup->top);
 			wakeup->top->vb.ts = ts;
 			wakeup->top->vb.field_count = btv->field_count;
 			wakeup->top->vb.state = state;
@@ -3824,7 +3834,8 @@
 	} else {
 		if (NULL != wakeup->top && curr->top != wakeup->top) {
 			if (irq_debug > 1)
-				printk("bttv%d: wakeup: top=%p\n",btv->c.nr,wakeup->top);
+				pr_debug("%d: wakeup: top=%p\n",
+					 btv->c.nr, wakeup->top);
 			wakeup->top->vb.ts = ts;
 			wakeup->top->vb.field_count = btv->field_count;
 			wakeup->top->vb.state = state;
@@ -3832,7 +3843,8 @@
 		}
 		if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
 			if (irq_debug > 1)
-				printk("bttv%d: wakeup: bottom=%p\n",btv->c.nr,wakeup->bottom);
+				pr_debug("%d: wakeup: bottom=%p\n",
+					 btv->c.nr, wakeup->bottom);
 			wakeup->bottom->vb.ts = ts;
 			wakeup->bottom->vb.field_count = btv->field_count;
 			wakeup->bottom->vb.state = state;
@@ -3866,11 +3878,11 @@
 	unsigned long flags;
 
 	if (bttv_verbose) {
-		printk(KERN_INFO "bttv%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
-		       btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
-		       btread(BT848_RISC_COUNT));
+		pr_info("%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
+			btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
+			btread(BT848_RISC_COUNT));
 		bttv_print_irqbits(btread(BT848_INT_STAT),0);
-		printk("\n");
+		pr_cont("\n");
 	}
 
 	spin_lock_irqsave(&btv->s_lock,flags);
@@ -4033,21 +4045,23 @@
 		dstat=btread(BT848_DSTATUS);
 
 		if (irq_debug) {
-			printk(KERN_DEBUG "bttv%d: irq loop=%d fc=%d "
-			       "riscs=%x, riscc=%08x, ",
-			       btv->c.nr, count, btv->field_count,
-			       stat>>28, btread(BT848_RISC_COUNT));
+			pr_debug("%d: irq loop=%d fc=%d riscs=%x, riscc=%08x, ",
+				 btv->c.nr, count, btv->field_count,
+				 stat>>28, btread(BT848_RISC_COUNT));
 			bttv_print_irqbits(stat,astat);
 			if (stat & BT848_INT_HLOCK)
-				printk("   HLOC => %s", (dstat & BT848_DSTATUS_HLOC)
-				       ? "yes" : "no");
+				pr_cont("   HLOC => %s",
+					dstat & BT848_DSTATUS_HLOC
+					? "yes" : "no");
 			if (stat & BT848_INT_VPRES)
-				printk("   PRES => %s", (dstat & BT848_DSTATUS_PRES)
-				       ? "yes" : "no");
+				pr_cont("   PRES => %s",
+					dstat & BT848_DSTATUS_PRES
+					? "yes" : "no");
 			if (stat & BT848_INT_FMTCHG)
-				printk("   NUML => %s", (dstat & BT848_DSTATUS_NUML)
-				       ? "625" : "525");
-			printk("\n");
+				pr_cont("   NUML => %s",
+					dstat & BT848_DSTATUS_NUML
+					? "625" : "525");
+			pr_cont("\n");
 		}
 
 		if (astat&BT848_INT_VSYNC)
@@ -4075,18 +4089,19 @@
 			audio_mute(btv, btv->mute);  /* trigger automute */
 
 		if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
-			printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr,
-			       (astat & BT848_INT_SCERR) ? "SCERR" : "",
-			       (astat & BT848_INT_OCERR) ? "OCERR" : "",
-			       btread(BT848_RISC_COUNT));
+			pr_info("%d: %s%s @ %08x,",
+				btv->c.nr,
+				(astat & BT848_INT_SCERR) ? "SCERR" : "",
+				(astat & BT848_INT_OCERR) ? "OCERR" : "",
+				btread(BT848_RISC_COUNT));
 			bttv_print_irqbits(stat,astat);
-			printk("\n");
+			pr_cont("\n");
 			if (bttv_debug)
 				bttv_print_riscaddr(btv);
 		}
 		if (fdsr && astat & BT848_INT_FDSR) {
-			printk(KERN_INFO "bttv%d: FDSR @ %08x\n",
-			       btv->c.nr,btread(BT848_RISC_COUNT));
+			pr_info("%d: FDSR @ %08x\n",
+				btv->c.nr, btread(BT848_RISC_COUNT));
 			if (bttv_debug)
 				bttv_print_riscaddr(btv);
 		}
@@ -4097,11 +4112,11 @@
 			if (count > 8 || !(astat & BT848_INT_GPINT)) {
 				btwrite(0, BT848_INT_MASK);
 
-				printk(KERN_ERR
-					   "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr);
+				pr_err("%d: IRQ lockup, cleared int mask [",
+				       btv->c.nr);
 			} else {
-				printk(KERN_ERR
-					   "bttv%d: IRQ lockup, clearing GPINT from int mask [", btv->c.nr);
+				pr_err("%d: IRQ lockup, clearing GPINT from int mask [",
+				       btv->c.nr);
 
 				btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
 						BT848_INT_MASK);
@@ -4109,7 +4124,7 @@
 
 			bttv_print_irqbits(stat,astat);
 
-			printk("]\n");
+			pr_cont("]\n");
 		}
 	}
 	btv->irq_total++;
@@ -4171,7 +4186,7 @@
 static int __devinit bttv_register_video(struct bttv *btv)
 {
 	if (no_overlay > 0)
-		printk("bttv: Overlay support disabled.\n");
+		pr_notice("Overlay support disabled\n");
 
 	/* video */
 	btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
@@ -4181,12 +4196,11 @@
 	if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
 				  video_nr[btv->c.nr]) < 0)
 		goto err;
-	printk(KERN_INFO "bttv%d: registered device %s\n",
-	       btv->c.nr, video_device_node_name(btv->video_dev));
+	pr_info("%d: registered device %s\n",
+		btv->c.nr, video_device_node_name(btv->video_dev));
 	if (device_create_file(&btv->video_dev->dev,
 				     &dev_attr_card)<0) {
-		printk(KERN_ERR "bttv%d: device_create_file 'card' "
-		       "failed\n", btv->c.nr);
+		pr_err("%d: device_create_file 'card' failed\n", btv->c.nr);
 		goto err;
 	}
 
@@ -4198,8 +4212,8 @@
 	if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
 				  vbi_nr[btv->c.nr]) < 0)
 		goto err;
-	printk(KERN_INFO "bttv%d: registered device %s\n",
-	       btv->c.nr, video_device_node_name(btv->vbi_dev));
+	pr_info("%d: registered device %s\n",
+		btv->c.nr, video_device_node_name(btv->vbi_dev));
 
 	if (!btv->has_radio)
 		return 0;
@@ -4210,8 +4224,8 @@
 	if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
 				  radio_nr[btv->c.nr]) < 0)
 		goto err;
-	printk(KERN_INFO "bttv%d: registered device %s\n",
-	       btv->c.nr, video_device_node_name(btv->radio_dev));
+	pr_info("%d: registered device %s\n",
+		btv->c.nr, video_device_node_name(btv->radio_dev));
 
 	/* all done */
 	return 0;
@@ -4244,10 +4258,10 @@
 
 	if (bttv_num == BTTV_MAX)
 		return -ENOMEM;
-	printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num);
+	pr_info("Bt8xx card found (%d)\n", bttv_num);
 	bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL);
 	if (btv == NULL) {
-		printk(KERN_ERR "bttv: out of memory.\n");
+		pr_err("out of memory\n");
 		return -ENOMEM;
 	}
 	btv->c.nr  = bttv_num;
@@ -4277,21 +4291,19 @@
 	btv->c.pci = dev;
 	btv->id  = dev->device;
 	if (pci_enable_device(dev)) {
-		printk(KERN_WARNING "bttv%d: Can't enable device.\n",
-		       btv->c.nr);
+		pr_warn("%d: Can't enable device\n", btv->c.nr);
 		return -EIO;
 	}
 	if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
-		printk(KERN_WARNING "bttv%d: No suitable DMA available.\n",
-		       btv->c.nr);
+		pr_warn("%d: No suitable DMA available\n", btv->c.nr);
 		return -EIO;
 	}
 	if (!request_mem_region(pci_resource_start(dev,0),
 				pci_resource_len(dev,0),
 				btv->c.v4l2_dev.name)) {
-		printk(KERN_WARNING "bttv%d: can't request iomem (0x%llx).\n",
-		       btv->c.nr,
-		       (unsigned long long)pci_resource_start(dev,0));
+		pr_warn("%d: can't request iomem (0x%llx)\n",
+			btv->c.nr,
+			(unsigned long long)pci_resource_start(dev, 0));
 		return -EBUSY;
 	}
 	pci_set_master(dev);
@@ -4299,22 +4311,21 @@
 
 	result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev);
 	if (result < 0) {
-		printk(KERN_WARNING "bttv%d: v4l2_device_register() failed\n", btv->c.nr);
+		pr_warn("%d: v4l2_device_register() failed\n", btv->c.nr);
 		goto fail0;
 	}
 
 	btv->revision = dev->revision;
 	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
-	printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ",
-	       bttv_num,btv->id, btv->revision, pci_name(dev));
-	printk("irq: %d, latency: %d, mmio: 0x%llx\n",
-	       btv->c.pci->irq, lat,
-	       (unsigned long long)pci_resource_start(dev,0));
+	pr_info("%d: Bt%d (rev %d) at %s, irq: %d, latency: %d, mmio: 0x%llx\n",
+		bttv_num, btv->id, btv->revision, pci_name(dev),
+		btv->c.pci->irq, lat,
+		(unsigned long long)pci_resource_start(dev, 0));
 	schedule();
 
 	btv->bt848_mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
 	if (NULL == btv->bt848_mmio) {
-		printk("bttv%d: ioremap() failed\n", btv->c.nr);
+		pr_err("%d: ioremap() failed\n", btv->c.nr);
 		result = -EIO;
 		goto fail1;
 	}
@@ -4327,8 +4338,8 @@
 	result = request_irq(btv->c.pci->irq, bttv_irq,
 	    IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv);
 	if (result < 0) {
-		printk(KERN_ERR "bttv%d: can't get IRQ %d\n",
-		       bttv_num,btv->c.pci->irq);
+		pr_err("%d: can't get IRQ %d\n",
+		       bttv_num, btv->c.pci->irq);
 		goto fail1;
 	}
 
@@ -4433,7 +4444,7 @@
 	struct bttv *btv = to_bttv(v4l2_dev);
 
 	if (bttv_verbose)
-		printk("bttv%d: unloading\n",btv->c.nr);
+		pr_info("%d: unloading\n", btv->c.nr);
 
 	if (bttv_tvcards[btv->c.type].has_dvb)
 		flush_request_modules(btv);
@@ -4481,7 +4492,7 @@
 	struct bttv_buffer_set idle;
 	unsigned long flags;
 
-	dprintk("bttv%d: suspend %d\n", btv->c.nr, state.event);
+	dprintk("%d: suspend %d\n", btv->c.nr, state.event);
 
 	/* stop dma + irqs */
 	spin_lock_irqsave(&btv->s_lock,flags);
@@ -4517,14 +4528,13 @@
 	unsigned long flags;
 	int err;
 
-	dprintk("bttv%d: resume\n", btv->c.nr);
+	dprintk("%d: resume\n", btv->c.nr);
 
 	/* restore pci state */
 	if (btv->state.disabled) {
 		err=pci_enable_device(pci_dev);
 		if (err) {
-			printk(KERN_WARNING "bttv%d: Can't enable device.\n",
-								btv->c.nr);
+			pr_warn("%d: Can't enable device\n", btv->c.nr);
 			return err;
 		}
 		btv->state.disabled = 0;
@@ -4532,8 +4542,7 @@
 	err=pci_set_power_state(pci_dev, PCI_D0);
 	if (err) {
 		pci_disable_device(pci_dev);
-		printk(KERN_WARNING "bttv%d: Can't enable device.\n",
-							btv->c.nr);
+		pr_warn("%d: Can't enable device\n", btv->c.nr);
 		btv->state.disabled = 1;
 		return err;
 	}
@@ -4585,22 +4594,21 @@
 
 	bttv_num = 0;
 
-	printk(KERN_INFO "bttv: driver version %s loaded\n",
-	       BTTV_VERSION);
+	pr_info("driver version %s loaded\n", BTTV_VERSION);
 	if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
 		gbuffers = 2;
 	if (gbufsize > BTTV_MAX_FBUF)
 		gbufsize = BTTV_MAX_FBUF;
 	gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
 	if (bttv_verbose)
-		printk(KERN_INFO "bttv: using %d buffers with %dk (%d pages) each for capture\n",
-		       gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
+		pr_info("using %d buffers with %dk (%d pages) each for capture\n",
+			gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
 
 	bttv_check_chipset();
 
 	ret = bus_register(&bttv_sub_bus_type);
 	if (ret < 0) {
-		printk(KERN_WARNING "bttv: bus_register error: %d\n", ret);
+		pr_warn("bus_register error: %d\n", ret);
 		return ret;
 	}
 	ret = pci_register_driver(&bttv_pci_driver);
diff -druN linux-libre-3.1-gnu/drivers/media/video/bt8xx/bttv-gpio.c linux-libre-3.2-gnu/drivers/media/video/bt8xx/bttv-gpio.c
--- linux-libre-3.1-gnu/drivers/media/video/bt8xx/bttv-gpio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/bt8xx/bttv-gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,8 @@
 
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -99,7 +101,7 @@
 		kfree(sub);
 		return err;
 	}
-	printk("bttv%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
+	pr_info("%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
 	list_add_tail(&sub->list,&core->subs);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/bt8xx/bttv-i2c.c linux-libre-3.2-gnu/drivers/media/video/bt8xx/bttv-i2c.c
--- linux-libre-3.1-gnu/drivers/media/video/bt8xx/bttv-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/bt8xx/bttv-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,8 @@
 
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -154,9 +156,7 @@
 	if (retval == 0)
 		goto eio;
 	if (i2c_debug) {
-		printk(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
-		if (!(xmit & BT878_I2C_NOSTOP))
-			printk(" >\n");
+		pr_cont(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
 	}
 
 	for (cnt = 1; cnt < msg->len; cnt++ ) {
@@ -170,19 +170,18 @@
 			goto err;
 		if (retval == 0)
 			goto eio;
-		if (i2c_debug) {
-			printk(" %02x", msg->buf[cnt]);
-			if (!(xmit & BT878_I2C_NOSTOP))
-				printk(" >\n");
-		}
+		if (i2c_debug)
+			pr_cont(" %02x", msg->buf[cnt]);
 	}
+	if (!(xmit & BT878_I2C_NOSTOP))
+		pr_cont(">\n");
 	return msg->len;
 
  eio:
 	retval = -EIO;
  err:
 	if (i2c_debug)
-		printk(" ERR: %d\n",retval);
+		pr_cont(" ERR: %d\n",retval);
 	return retval;
 }
 
@@ -193,7 +192,7 @@
 	u32 cnt;
 	int retval;
 
-	for(cnt = 0; cnt < msg->len; cnt++) {
+	for (cnt = 0; cnt < msg->len; cnt++) {
 		xmit = (msg->addr << 25) | (1 << 24) | I2C_HW;
 		if (cnt < msg->len-1)
 			xmit |= BT848_I2C_W3B;
@@ -201,6 +200,12 @@
 			xmit |= BT878_I2C_NOSTOP;
 		if (cnt)
 			xmit |= BT878_I2C_NOSTART;
+
+		if (i2c_debug) {
+			if (!(xmit & BT878_I2C_NOSTART))
+				pr_cont(" <R %02x", (msg->addr << 1) +1);
+		}
+
 		btwrite(xmit, BT848_I2C);
 		retval = bttv_i2c_wait_done(btv);
 		if (retval < 0)
@@ -209,20 +214,20 @@
 			goto eio;
 		msg->buf[cnt] = ((u32)btread(BT848_I2C) >> 8) & 0xff;
 		if (i2c_debug) {
-			if (!(xmit & BT878_I2C_NOSTART))
-				printk(" <R %02x", (msg->addr << 1) +1);
-			printk(" =%02x", msg->buf[cnt]);
-			if (!(xmit & BT878_I2C_NOSTOP))
-				printk(" >\n");
+			pr_cont(" =%02x", msg->buf[cnt]);
 		}
+		if (i2c_debug && !(xmit & BT878_I2C_NOSTOP))
+			pr_cont(" >\n");
 	}
+
+
 	return msg->len;
 
  eio:
 	retval = -EIO;
  err:
 	if (i2c_debug)
-		printk(" ERR: %d\n",retval);
+		pr_cont(" ERR: %d\n",retval);
 	return retval;
 }
 
@@ -234,7 +239,8 @@
 	int i;
 
 	if (i2c_debug)
-		printk("bt-i2c:");
+		pr_debug("bt-i2c:");
+
 	btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT);
 	for (i = 0 ; i < num; i++) {
 		if (msgs[i].flags & I2C_M_RD) {
@@ -271,20 +277,20 @@
 	if (0 != btv->i2c_rc)
 		return -1;
 	if (bttv_verbose && NULL != probe_for)
-		printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ",
-		       btv->c.nr,probe_for,addr);
+		pr_info("%d: i2c: checking for %s @ 0x%02x... ",
+			btv->c.nr, probe_for, addr);
 	btv->i2c_client.addr = addr >> 1;
 	if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) {
 		if (NULL != probe_for) {
 			if (bttv_verbose)
-				printk("not found\n");
+				pr_cont("not found\n");
 		} else
-			printk(KERN_WARNING "bttv%d: i2c read 0x%x: error\n",
-			       btv->c.nr,addr);
+			pr_warn("%d: i2c read 0x%x: error\n",
+				btv->c.nr, addr);
 		return -1;
 	}
 	if (bttv_verbose && NULL != probe_for)
-		printk("found\n");
+		pr_cont("found\n");
 	return buffer;
 }
 
@@ -335,8 +341,8 @@
 		rc = i2c_master_recv(c,&buf,0);
 		if (rc < 0)
 			continue;
-		printk("%s: i2c scan: found device @ 0x%x  [%s]\n",
-		       name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+		pr_info("%s: i2c scan: found device @ 0x%x  [%s]\n",
+			name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
 	}
 }
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/bt8xx/bttv-input.c linux-libre-3.2-gnu/drivers/media/video/bt8xx/bttv-input.c
--- linux-libre-3.1-gnu/drivers/media/video/bt8xx/bttv-input.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/bt8xx/bttv-input.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * 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/delay.h>
@@ -36,9 +38,10 @@
 module_param(ir_rc5_remote_gap, int, 0644);
 
 #undef dprintk
-#define dprintk(arg...) do {	\
-	if (ir_debug >= 1)	\
-		printk(arg);	\
+#define dprintk(fmt, ...)			\
+do {						\
+	if (ir_debug >= 1)			\
+		pr_info(fmt, ##__VA_ARGS__);	\
 } while (0)
 
 #define DEVNAME "bttv-input"
@@ -62,7 +65,7 @@
 
 	/* extract data */
 	data = ir_extract_bits(gpio, ir->mask_keycode);
-	dprintk(KERN_INFO DEVNAME ": irq gpio=0x%x code=%d | %s%s%s\n",
+	dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
 		gpio, data,
 		ir->polling               ? "poll"  : "irq",
 		(gpio & ir->mask_keydown) ? " down" : "",
@@ -96,7 +99,7 @@
 	keyup = (gpio & ir->mask_keyup) ? 1 << 31 : 0;
 
 	if ((ir->last_gpio & 0x7f) != data) {
-		dprintk(KERN_INFO DEVNAME ": gpio=0x%x code=%d | %s\n",
+		dprintk("gpio=0x%x code=%d | %s\n",
 			gpio, data,
 			(gpio & ir->mask_keyup) ? " up" : "up/down");
 
@@ -107,7 +110,7 @@
 		if ((ir->last_gpio & 1 << 31) == keyup)
 			return;
 
-		dprintk(KERN_INFO DEVNAME ":(cnt) gpio=0x%x code=%d | %s\n",
+		dprintk("(cnt) gpio=0x%x code=%d | %s\n",
 			gpio, data,
 			(gpio & ir->mask_keyup) ? " up" : "down");
 
@@ -177,13 +180,12 @@
 			rc5 |= 1;
 		break;
 		case 3:
-			dprintk(KERN_INFO DEVNAME ":rc5_decode(%x) bad code\n",
+			dprintk("rc5_decode(%x) bad code\n",
 				org_code);
 			return 0;
 		}
 	}
-	dprintk(KERN_INFO DEVNAME ":"
-		"code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
+	dprintk("code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
 		"instr=%x\n", rc5, org_code, RC5_START(rc5),
 		RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
 	return rc5;
@@ -212,20 +214,20 @@
 
 	/* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */
 	if (gap < 28000) {
-		dprintk(KERN_INFO DEVNAME ": spurious timer_end\n");
+		dprintk("spurious timer_end\n");
 		return;
 	}
 
 	if (ir->last_bit < 20) {
 		/* ignore spurious codes (caused by light/other remotes) */
-		dprintk(KERN_INFO DEVNAME ": short code: %x\n", ir->code);
+		dprintk("short code: %x\n", ir->code);
 	} else {
 		ir->code = (ir->code << ir->shift_by) | 1;
 		rc5 = bttv_rc5_decode(ir->code);
 
 		/* two start bits? */
 		if (RC5_START(rc5) != ir->start) {
-			printk(KERN_INFO DEVNAME ":"
+			pr_info(DEVNAME ":"
 			       " rc5 start bits invalid: %u\n", RC5_START(rc5));
 
 			/* right address? */
@@ -235,8 +237,7 @@
 
 			/* Good code */
 			rc_keydown(ir->dev, instr, toggle);
-			dprintk(KERN_INFO DEVNAME ":"
-				" instruction %x, toggle %x\n",
+			dprintk("instruction %x, toggle %x\n",
 				instr, toggle);
 		}
 	}
@@ -265,7 +266,7 @@
 		    tv.tv_usec - ir->base_time.tv_usec;
 	}
 
-	dprintk(KERN_INFO DEVNAME ": RC5 IRQ: gap %d us for %s\n",
+	dprintk("RC5 IRQ: gap %d us for %s\n",
 		gap, (gpio & 0x20) ? "mark" : "space");
 
 	/* remote IRQ? */
@@ -340,14 +341,14 @@
 
 	/* poll IR chip */
 	if (1 != i2c_master_recv(ir->c, &b, 1)) {
-		dprintk(KERN_INFO DEVNAME ": read error\n");
+		dprintk("read error\n");
 		return -EIO;
 	}
 
 	/* ignore 0xaa */
 	if (b==0xaa)
 		return 0;
-	dprintk(KERN_INFO DEVNAME ": key %02x\n", b);
+	dprintk("key %02x\n", b);
 
 	/*
 	 * NOTE:
@@ -517,7 +518,7 @@
 		break;
 	}
 	if (NULL == ir_codes) {
-		dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type);
+		dprintk("Ooops: IR config error [card=%d]\n", btv->c.type);
 		err = -ENODEV;
 		goto err_out_free;
 	}
diff -druN linux-libre-3.1-gnu/drivers/media/video/bt8xx/bttvp.h linux-libre-3.2-gnu/drivers/media/video/bt8xx/bttvp.h
--- linux-libre-3.1-gnu/drivers/media/video/bt8xx/bttvp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/bt8xx/bttvp.h	2012-01-04 18:55:44.000000000 -0500
@@ -310,9 +310,21 @@
 extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
 extern int init_bttv_i2c(struct bttv *btv);
 
-#define bttv_printk if (bttv_verbose) printk
-#define dprintk  if (bttv_debug >= 1) printk
-#define d2printk if (bttv_debug >= 2) printk
+#define dprintk(fmt, ...)			\
+do {						\
+	if (bttv_debug >= 1)			\
+		pr_debug(fmt, ##__VA_ARGS__);	\
+} while (0)
+#define dprintk_cont(fmt, ...)			\
+do {						\
+	if (bttv_debug >= 1)			\
+		pr_cont(fmt, ##__VA_ARGS__);	\
+} while (0)
+#define d2printk(fmt, ...)			\
+do {						\
+	if (bttv_debug >= 2)			\
+		printk(fmt, ##__VA_ARGS__);	\
+} while (0)
 
 #define BTTV_MAX_FBUF   0x208000
 #define BTTV_TIMEOUT    msecs_to_jiffies(500)    /* 0.5 seconds */
diff -druN linux-libre-3.1-gnu/drivers/media/video/bt8xx/bttv-risc.c linux-libre-3.2-gnu/drivers/media/video/bt8xx/bttv-risc.c
--- linux-libre-3.1-gnu/drivers/media/video/bt8xx/bttv-risc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/bt8xx/bttv-risc.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
 
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -473,8 +475,7 @@
 	capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00;  /* vbi data */
 	capctl |= override;
 
-	d2printk(KERN_DEBUG
-		 "bttv%d: capctl=%x lirq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",
+	d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
 		 btv->c.nr,capctl,btv->loop_irq,
 		 btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
 		 btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
@@ -517,8 +518,8 @@
 
 	if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
 		return rc;
-	dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n",
-		btv->c.nr,(unsigned long long)btv->main.dma);
+	dprintk("%d: risc main @ %08llx\n",
+		btv->c.nr, (unsigned long long)btv->main.dma);
 
 	btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
 				       BT848_FIFO_STATUS_VRE);
@@ -557,12 +558,12 @@
 	unsigned long next = btv->main.dma + ((slot+2) << 2);
 
 	if (NULL == risc) {
-		d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=NULL\n",
-			 btv->c.nr,risc,slot);
+		d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
 		btv->main.cpu[slot+1] = cpu_to_le32(next);
 	} else {
-		d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n",
-			 btv->c.nr,risc,slot,(unsigned long long)risc->dma,irqflags);
+		d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
+			 btv->c.nr, risc, slot,
+			 (unsigned long long)risc->dma, irqflags);
 		cmd = BT848_RISC_JUMP;
 		if (irqflags) {
 			cmd |= BT848_RISC_IRQ;
@@ -708,8 +709,7 @@
 	const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
 	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
 
-	dprintk(KERN_DEBUG
-		"bttv%d: buffer field: %s  format: %s  size: %dx%d\n",
+	dprintk("%d: buffer field: %s  format: %s  size: %dx%d\n",
 		btv->c.nr, v4l2_field_names[buf->vb.field],
 		buf->fmt->name, buf->vb.width, buf->vb.height);
 
@@ -870,10 +870,9 @@
 		  struct bttv_buffer *buf)
 {
 	/* check interleave, bottom+top fields */
-	dprintk(KERN_DEBUG
-		"bttv%d: overlay fields: %s format: %s  size: %dx%d\n",
+	dprintk("%d: overlay fields: %s format: %s  size: %dx%d\n",
 		btv->c.nr, v4l2_field_names[buf->vb.field],
-		fmt->name,ov->w.width,ov->w.height);
+		fmt->name, ov->w.width, ov->w.height);
 
 	/* calculate geometry */
 	bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
diff -druN linux-libre-3.1-gnu/drivers/media/video/bt8xx/bttv-vbi.c linux-libre-3.2-gnu/drivers/media/video/bt8xx/bttv-vbi.c
--- linux-libre-3.1-gnu/drivers/media/video/bt8xx/bttv-vbi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/bt8xx/bttv-vbi.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -65,8 +67,11 @@
 #ifdef dprintk
 # undef dprintk
 #endif
-#define dprintk(fmt, arg...)	if (vbi_debug) \
-	printk(KERN_DEBUG "bttv%d/vbi: " fmt, btv->c.nr , ## arg)
+#define dprintk(fmt, ...)						\
+do {									\
+	if (vbi_debug)							\
+		pr_debug("%d: " fmt, btv->c.nr, ##__VA_ARGS__);		\
+} while (0)
 
 #define IMAGE_SIZE(fmt) \
 	(((fmt)->count[0] + (fmt)->count[1]) * (fmt)->samples_per_line)
diff -druN linux-libre-3.1-gnu/drivers/media/video/bt8xx/Makefile linux-libre-3.2-gnu/drivers/media/video/bt8xx/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/bt8xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/bt8xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,6 @@
 
 obj-$(CONFIG_VIDEO_BT848) += bttv.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
diff -druN linux-libre-3.1-gnu/drivers/media/video/cpia2/cpia2_usb.c linux-libre-3.2-gnu/drivers/media/video/cpia2/cpia2_usb.c
--- linux-libre-3.1-gnu/drivers/media/video/cpia2/cpia2_usb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cpia2/cpia2_usb.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
+#include <linux/module.h>
 
 #include "cpia2.h"
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx18/cx18-driver.c linux-libre-3.2-gnu/drivers/media/video/cx18/cx18-driver.c
--- linux-libre-3.1-gnu/drivers/media/video/cx18/cx18-driver.c	2012-03-19 21:31:22.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx18/cx18-driver.c	2012-03-19 21:33:30.000000000 -0400
@@ -1085,6 +1085,8 @@
 		setup.addr = ADDR_UNSET;
 		setup.type = cx->options.tuner;
 		setup.mode_mask = T_ANALOG_TV;  /* matches TV tuners */
+		if (cx->options.radio > 0)
+			setup.mode_mask |= T_RADIO;
 		setup.tuner_callback = (setup.type == TUNER_XC2028) ?
 			cx18_reset_tuner_gpio : NULL;
 		cx18_call_all(cx, tuner, s_type_addr, &setup);
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx18/cx18-driver.h linux-libre-3.2-gnu/drivers/media/video/cx18/cx18-driver.h
--- linux-libre-3.1-gnu/drivers/media/video/cx18/cx18-driver.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx18/cx18-driver.h	2012-01-04 18:55:44.000000000 -0500
@@ -409,6 +409,7 @@
 
 	/* Videobuf for YUV video */
 	u32 pixelformat;
+	u32 vb_bytes_per_frame;
 	struct list_head vb_capture;    /* video capture queue */
 	spinlock_t vb_lock;
 	struct timer_list vb_timeout;
@@ -430,10 +431,6 @@
 	u32 open_id;
 	int type;
 	struct cx18 *cx;
-
-	struct videobuf_queue vbuf_q;
-	spinlock_t s_lock; /* Protect vbuf_q */
-	enum v4l2_buf_type vb_type;
 };
 
 static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh)
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx18/cx18-fileops.c linux-libre-3.2-gnu/drivers/media/video/cx18/cx18-fileops.c
--- linux-libre-3.1-gnu/drivers/media/video/cx18/cx18-fileops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx18/cx18-fileops.c	2012-01-04 18:55:44.000000000 -0500
@@ -784,8 +784,6 @@
 		cx18_release_stream(s);
 	} else {
 		cx18_stop_capture(id, 0);
-		if (id->type == CX18_ENC_STREAM_TYPE_YUV)
-			videobuf_mmap_free(&id->vbuf_q);
 	}
 	kfree(id);
 	mutex_unlock(&cx->serialize_lock);
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx18/cx18-ioctl.c linux-libre-3.2-gnu/drivers/media/video/cx18/cx18-ioctl.c
--- linux-libre-3.1-gnu/drivers/media/video/cx18/cx18-ioctl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx18/cx18-ioctl.c	2012-01-04 18:55:44.000000000 -0500
@@ -160,12 +160,7 @@
 	pixfmt->priv = 0;
 	if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
 		pixfmt->pixelformat = s->pixelformat;
-		/* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
-		   UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
-		if (s->pixelformat == V4L2_PIX_FMT_HM12)
-			pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
-		else
-			pixfmt->sizeimage = pixfmt->height * 720 * 2;
+		pixfmt->sizeimage = s->vb_bytes_per_frame;
 		pixfmt->bytesperline = 720;
 	} else {
 		pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
@@ -296,6 +291,12 @@
 		return -EBUSY;
 
 	s->pixelformat = fmt->fmt.pix.pixelformat;
+	/* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+	   UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+	if (s->pixelformat == V4L2_PIX_FMT_HM12)
+		s->vb_bytes_per_frame = h * 720 * 3 / 2;
+	else
+		s->vb_bytes_per_frame = h * 720 * 2;
 
 	mbus_fmt.width = cx->cxhdl.width = w;
 	mbus_fmt.height = cx->cxhdl.height = h;
@@ -463,13 +464,16 @@
 static int cx18_querycap(struct file *file, void *fh,
 				struct v4l2_capability *vcap)
 {
-	struct cx18 *cx = fh2id(fh)->cx;
+	struct cx18_open_id *id = fh2id(fh);
+	struct cx18 *cx = id->cx;
 
 	strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
 	strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
 	snprintf(vcap->bus_info, sizeof(vcap->bus_info),
 		 "PCI:%s", pci_name(cx->pci_dev));
 	vcap->capabilities = cx->v4l2_cap; 	    /* capabilities */
+	if (id->type == CX18_ENC_STREAM_TYPE_YUV)
+		vcap->capabilities |= V4L2_CAP_STREAMING;
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx18/cx18-mailbox.c linux-libre-3.2-gnu/drivers/media/video/cx18/cx18-mailbox.c
--- linux-libre-3.1-gnu/drivers/media/video/cx18/cx18-mailbox.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx18/cx18-mailbox.c	2012-01-04 18:55:44.000000000 -0500
@@ -196,7 +196,7 @@
 	}
 
 	/* If we've filled the buffer as per the callers res then dispatch it */
-	if (vb_buf->bytes_used >= (vb_buf->vb.width * vb_buf->vb.height * 2)) {
+	if (vb_buf->bytes_used >= s->vb_bytes_per_frame) {
 		dispatch = 1;
 		vb_buf->bytes_used = 0;
 	}
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx18/cx18-mailbox.h linux-libre-3.2-gnu/drivers/media/video/cx18/cx18-mailbox.h
--- linux-libre-3.1-gnu/drivers/media/video/cx18/cx18-mailbox.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx18/cx18-mailbox.h	2012-01-04 18:55:44.000000000 -0500
@@ -69,7 +69,7 @@
     /* Each command can have up to 6 arguments */
     u32       args[MAX_MB_ARGUMENTS];
     /* The return code can be one of the codes in the file cx23418.h. If the
-       command is completed successfuly, the error will be ERR_SYS_SUCCESS.
+       command is completed successfully, the error will be ERR_SYS_SUCCESS.
        If it is pending, the code is ERR_SYS_PENDING. If it failed, the error
        code would indicate the task from which the error originated and will
        be one of the errors in cx23418.h. In that case, the following
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx18/cx18-streams.c linux-libre-3.2-gnu/drivers/media/video/cx18/cx18-streams.c
--- linux-libre-3.1-gnu/drivers/media/video/cx18/cx18-streams.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx18/cx18-streams.c	2012-01-04 18:55:44.000000000 -0500
@@ -138,6 +138,12 @@
 		buf->tvnorm    = cx->std;
 		s->pixelformat = pixelformat;
 
+		/* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+		   UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+		if (s->pixelformat == V4L2_PIX_FMT_HM12)
+			s->vb_bytes_per_frame = height * 720 * 3 / 2;
+		else
+			s->vb_bytes_per_frame = height * 720 * 2;
 		cx18_dma_free(q, s, buf);
 	}
 
@@ -154,6 +160,12 @@
 		buf->tvnorm    = cx->std;
 		s->pixelformat = pixelformat;
 
+		/* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+		   UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+		if (s->pixelformat == V4L2_PIX_FMT_HM12)
+			s->vb_bytes_per_frame = height * 720 * 3 / 2;
+		else
+			s->vb_bytes_per_frame = height * 720 * 2;
 		rc = videobuf_iolock(q, &buf->vb, NULL);
 		if (rc != 0)
 			goto fail;
@@ -287,6 +299,7 @@
 
 		/* Assume the previous pixel default */
 		s->pixelformat = V4L2_PIX_FMT_HM12;
+		s->vb_bytes_per_frame = cx->cxhdl.height * 720 * 3 / 2;
 	}
 }
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx18/Makefile linux-libre-3.2-gnu/drivers/media/video/cx18/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/cx18/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx18/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,6 @@
 obj-$(CONFIG_VIDEO_CX18) += cx18.o
 obj-$(CONFIG_VIDEO_CX18_ALSA) += cx18-alsa.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/common/tuners
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx231xx/Makefile linux-libre-3.2-gnu/drivers/media/video/cx231xx/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/cx231xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx231xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -8,9 +8,9 @@
 obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o
 obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb/dvb-usb
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885-alsa.c linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885-alsa.c
--- linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885-alsa.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885-alsa.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,535 @@
+/*
+ *
+ *  Support for CX23885 analog audio capture
+ *
+ *    (c) 2008 Mijhail Moreyra <mijhail.moreyra@gmail.com>
+ *    Adapted from cx88-alsa.c
+ *    (c) 2009 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/device.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+
+#include <asm/delay.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+
+#include <sound/tlv.h>
+
+
+#include "cx23885.h"
+#include "cx23885-reg.h"
+
+#define AUDIO_SRAM_CHANNEL	SRAM_CH07
+
+#define dprintk(level, fmt, arg...)	if (audio_debug >= level) \
+	printk(KERN_INFO "%s: " fmt, chip->dev->name , ## arg)
+
+#define dprintk_core(level, fmt, arg...)	if (audio_debug >= level) \
+	printk(KERN_DEBUG "%s: " fmt, chip->dev->name , ## arg)
+
+/****************************************************************************
+			Module global static vars
+ ****************************************************************************/
+
+static unsigned int disable_analog_audio;
+module_param(disable_analog_audio, int, 0644);
+MODULE_PARM_DESC(disable_analog_audio, "disable analog audio ALSA driver");
+
+static unsigned int audio_debug;
+module_param(audio_debug, int, 0644);
+MODULE_PARM_DESC(audio_debug, "enable debug messages [analog audio]");
+
+/****************************************************************************
+			Board specific funtions
+ ****************************************************************************/
+
+/* Constants taken from cx88-reg.h */
+#define AUD_INT_DN_RISCI1       (1 <<  0)
+#define AUD_INT_UP_RISCI1       (1 <<  1)
+#define AUD_INT_RDS_DN_RISCI1   (1 <<  2)
+#define AUD_INT_DN_RISCI2       (1 <<  4) /* yes, 3 is skipped */
+#define AUD_INT_UP_RISCI2       (1 <<  5)
+#define AUD_INT_RDS_DN_RISCI2   (1 <<  6)
+#define AUD_INT_DN_SYNC         (1 << 12)
+#define AUD_INT_UP_SYNC         (1 << 13)
+#define AUD_INT_RDS_DN_SYNC     (1 << 14)
+#define AUD_INT_OPC_ERR         (1 << 16)
+#define AUD_INT_BER_IRQ         (1 << 20)
+#define AUD_INT_MCHG_IRQ        (1 << 21)
+#define GP_COUNT_CONTROL_RESET	0x3
+
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int cx23885_start_audio_dma(struct cx23885_audio_dev *chip)
+{
+	struct cx23885_audio_buffer *buf = chip->buf;
+	struct cx23885_dev *dev  = chip->dev;
+	struct sram_channel *audio_ch =
+		&dev->sram_channels[AUDIO_SRAM_CHANNEL];
+
+	dprintk(1, "%s()\n", __func__);
+
+	/* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
+	cx_clear(AUD_INT_DMA_CTL, 0x11);
+
+	/* setup fifo + format - out channel */
+	cx23885_sram_channel_setup(chip->dev, audio_ch, buf->bpl,
+		buf->risc.dma);
+
+	/* sets bpl size */
+	cx_write(AUD_INT_A_LNGTH, buf->bpl);
+
+	/* This is required to get good audio (1 seems to be ok) */
+	cx_write(AUD_INT_A_MODE, 1);
+
+	/* reset counter */
+	cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+	atomic_set(&chip->count, 0);
+
+	dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d "
+		"byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start+12)>>1,
+		chip->num_periods, buf->bpl * chip->num_periods);
+
+	/* Enables corresponding bits at AUD_INT_STAT */
+	cx_write(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+				    AUD_INT_DN_RISCI1);
+
+	/* Clean any pending interrupt bits already set */
+	cx_write(AUDIO_INT_INT_STAT, ~0);
+
+	/* enable audio irqs */
+	cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT);
+
+	/* start dma */
+	cx_set(DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */
+	cx_set(AUD_INT_DMA_CTL, 0x11); /* audio downstream FIFO and
+					  RISC enable */
+	if (audio_debug)
+		cx23885_sram_channel_dump(chip->dev, audio_ch);
+
+	return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+static int cx23885_stop_audio_dma(struct cx23885_audio_dev *chip)
+{
+	struct cx23885_dev *dev = chip->dev;
+	dprintk(1, "Stopping audio DMA\n");
+
+	/* stop dma */
+	cx_clear(AUD_INT_DMA_CTL, 0x11);
+
+	/* disable irqs */
+	cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT);
+	cx_clear(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+				    AUD_INT_DN_RISCI1);
+
+	if (audio_debug)
+		cx23885_sram_channel_dump(chip->dev,
+			&dev->sram_channels[AUDIO_SRAM_CHANNEL]);
+
+	return 0;
+}
+
+/*
+ * BOARD Specific: Handles audio IRQ
+ */
+int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask)
+{
+	struct cx23885_audio_dev *chip = dev->audio_dev;
+
+	if (0 == (status & mask))
+		return 0;
+
+	cx_write(AUDIO_INT_INT_STAT, status);
+
+	/* risc op code error */
+	if (status & AUD_INT_OPC_ERR) {
+		printk(KERN_WARNING "%s/1: Audio risc op code error\n",
+			dev->name);
+		cx_clear(AUD_INT_DMA_CTL, 0x11);
+		cx23885_sram_channel_dump(dev,
+			&dev->sram_channels[AUDIO_SRAM_CHANNEL]);
+	}
+	if (status & AUD_INT_DN_SYNC) {
+		dprintk(1, "Downstream sync error\n");
+		cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+		return 1;
+	}
+	/* risc1 downstream */
+	if (status & AUD_INT_DN_RISCI1) {
+		atomic_set(&chip->count, cx_read(AUD_INT_A_GPCNT));
+		snd_pcm_period_elapsed(chip->substream);
+	}
+	/* FIXME: Any other status should deserve a special handling? */
+
+	return 1;
+}
+
+static int dsp_buffer_free(struct cx23885_audio_dev *chip)
+{
+	BUG_ON(!chip->dma_size);
+
+	dprintk(2, "Freeing buffer\n");
+	videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc);
+	videobuf_dma_free(chip->dma_risc);
+	btcx_riscmem_free(chip->pci, &chip->buf->risc);
+	kfree(chip->buf);
+
+	chip->dma_risc = NULL;
+	chip->dma_size = 0;
+
+	return 0;
+}
+
+/****************************************************************************
+				ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE	4096
+
+static struct snd_pcm_hardware snd_cx23885_digital_hw = {
+	.info = SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP_VALID,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+	.rates =		SNDRV_PCM_RATE_48000,
+	.rate_min =		48000,
+	.rate_max =		48000,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* Analog audio output will be full of clicks and pops if there
+	   are not exactly four lines in the SRAM FIFO buffer.  */
+	.period_bytes_min = DEFAULT_FIFO_SIZE/4,
+	.period_bytes_max = DEFAULT_FIFO_SIZE/4,
+	.periods_min = 1,
+	.periods_max = 1024,
+	.buffer_bytes_max = (1024*1024),
+};
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_cx23885_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int err;
+
+	if (!chip) {
+		printk(KERN_ERR "BUG: cx23885 can't find device struct."
+				" Can't proceed with open\n");
+		return -ENODEV;
+	}
+
+	err = snd_pcm_hw_constraint_pow2(runtime, 0,
+		SNDRV_PCM_HW_PARAM_PERIODS);
+	if (err < 0)
+		goto _error;
+
+	chip->substream = substream;
+
+	runtime->hw = snd_cx23885_digital_hw;
+
+	if (chip->dev->sram_channels[AUDIO_SRAM_CHANNEL].fifo_size !=
+		DEFAULT_FIFO_SIZE) {
+		unsigned int bpl = chip->dev->
+			sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 4;
+		bpl &= ~7; /* must be multiple of 8 */
+		runtime->hw.period_bytes_min = bpl;
+		runtime->hw.period_bytes_max = bpl;
+	}
+
+	return 0;
+_error:
+	dprintk(1, "Error opening PCM!\n");
+	return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_cx23885_close(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_cx23885_hw_params(struct snd_pcm_substream *substream,
+			      struct snd_pcm_hw_params *hw_params)
+{
+	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct videobuf_dmabuf *dma;
+
+	struct cx23885_audio_buffer *buf;
+	int ret;
+
+	if (substream->runtime->dma_area) {
+		dsp_buffer_free(chip);
+		substream->runtime->dma_area = NULL;
+	}
+
+	chip->period_size = params_period_bytes(hw_params);
+	chip->num_periods = params_periods(hw_params);
+	chip->dma_size = chip->period_size * params_periods(hw_params);
+
+	BUG_ON(!chip->dma_size);
+	BUG_ON(chip->num_periods & (chip->num_periods-1));
+
+	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+	if (NULL == buf)
+		return -ENOMEM;
+
+	buf->bpl = chip->period_size;
+
+	dma = &buf->dma;
+	videobuf_dma_init(dma);
+	ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+			(PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
+	if (ret < 0)
+		goto error;
+
+	ret = videobuf_dma_map(&chip->pci->dev, dma);
+	if (ret < 0)
+		goto error;
+
+	ret = cx23885_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
+				   chip->period_size, chip->num_periods, 1);
+	if (ret < 0)
+		goto error;
+
+	/* Loop back to start of program */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+	buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+	chip->buf = buf;
+	chip->dma_risc = dma;
+
+	substream->runtime->dma_area = chip->dma_risc->vaddr;
+	substream->runtime->dma_bytes = chip->dma_size;
+	substream->runtime->dma_addr = 0;
+
+	return 0;
+
+error:
+	kfree(buf);
+	return ret;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_cx23885_hw_free(struct snd_pcm_substream *substream)
+{
+
+	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+
+	if (substream->runtime->dma_area) {
+		dsp_buffer_free(chip);
+		substream->runtime->dma_area = NULL;
+	}
+
+	return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_cx23885_prepare(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+/*
+ * trigger callback
+ */
+static int snd_cx23885_card_trigger(struct snd_pcm_substream *substream,
+	int cmd)
+{
+	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+	int err;
+
+	/* Local interrupts are already disabled by ALSA */
+	spin_lock(&chip->lock);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		err = cx23885_start_audio_dma(chip);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		err = cx23885_stop_audio_dma(chip);
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+
+	spin_unlock(&chip->lock);
+
+	return err;
+}
+
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_cx23885_pointer(
+	struct snd_pcm_substream *substream)
+{
+	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	u16 count;
+
+	count = atomic_read(&chip->count);
+
+	return runtime->period_size * (count & (runtime->periods-1));
+}
+
+/*
+ * page callback (needed for mmap)
+ */
+static struct page *snd_cx23885_page(struct snd_pcm_substream *substream,
+				unsigned long offset)
+{
+	void *pageptr = substream->runtime->dma_area + offset;
+	return vmalloc_to_page(pageptr);
+}
+
+/*
+ * operators
+ */
+static struct snd_pcm_ops snd_cx23885_pcm_ops = {
+	.open = snd_cx23885_pcm_open,
+	.close = snd_cx23885_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_cx23885_hw_params,
+	.hw_free = snd_cx23885_hw_free,
+	.prepare = snd_cx23885_prepare,
+	.trigger = snd_cx23885_card_trigger,
+	.pointer = snd_cx23885_pointer,
+	.page = snd_cx23885_page,
+};
+
+/*
+ * create a PCM device
+ */
+static int snd_cx23885_pcm(struct cx23885_audio_dev *chip, int device,
+	char *name)
+{
+	int err;
+	struct snd_pcm *pcm;
+
+	err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
+	if (err < 0)
+		return err;
+	pcm->private_data = chip;
+	strcpy(pcm->name, name);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx23885_pcm_ops);
+
+	return 0;
+}
+
+/****************************************************************************
+			Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * Alsa Constructor - Component probe
+ */
+
+struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev)
+{
+	struct snd_card *card;
+	struct cx23885_audio_dev *chip;
+	int err;
+
+	if (disable_analog_audio)
+		return NULL;
+
+	if (dev->sram_channels[AUDIO_SRAM_CHANNEL].cmds_start == 0) {
+		printk(KERN_WARNING "%s(): Missing SRAM channel configuration "
+			"for analog TV Audio\n", __func__);
+		return NULL;
+	}
+
+	err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			THIS_MODULE, sizeof(struct cx23885_audio_dev), &card);
+	if (err < 0)
+		goto error;
+
+	chip = (struct cx23885_audio_dev *) card->private_data;
+	chip->dev = dev;
+	chip->pci = dev->pci;
+	chip->card = card;
+	spin_lock_init(&chip->lock);
+
+	snd_card_set_dev(card, &dev->pci->dev);
+
+	err = snd_cx23885_pcm(chip, 0, "CX23885 Digital");
+	if (err < 0)
+		goto error;
+
+	strcpy(card->driver, "CX23885");
+	sprintf(card->shortname, "Conexant CX23885");
+	sprintf(card->longname, "%s at %s", card->shortname, dev->name);
+
+	err = snd_card_register(card);
+	if (err < 0)
+		goto error;
+
+	dprintk(0, "registered ALSA audio device\n");
+
+	return chip;
+
+error:
+	snd_card_free(card);
+	printk(KERN_ERR "%s(): Failed to register analog "
+			"audio adapter\n", __func__);
+
+	return NULL;
+}
+
+/*
+ * ALSA destructor
+ */
+void cx23885_audio_unregister(struct cx23885_dev *dev)
+{
+	struct cx23885_audio_dev *chip = dev->audio_dev;
+
+	snd_card_free(chip->card);
+}
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885-cards.c linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885-cards.c
--- linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885-cards.c	2012-03-19 21:38:46.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885-cards.c	2012-03-19 21:41:29.000000000 -0400
@@ -25,8 +25,8 @@
 #include <linux/delay.h>
 #include <media/cx25840.h>
 #include <linux/firmware.h>
+#include <misc/altera.h>
 
-#include "../../../staging/altera-stapl/altera.h"
 #include "cx23885.h"
 #include "tuner-xc2028.h"
 #include "netup-eeprom.h"
@@ -106,12 +106,14 @@
 			.vmux   =	CX25840_VIN7_CH3 |
 					CX25840_VIN5_CH2 |
 					CX25840_VIN2_CH1,
+			.amux   = CX25840_AUDIO8,
 			.gpio0  = 0,
 		}, {
 			.type   = CX23885_VMUX_COMPOSITE1,
 			.vmux   =	CX25840_VIN7_CH3 |
 					CX25840_VIN4_CH2 |
 					CX25840_VIN6_CH1,
+			.amux   = CX25840_AUDIO7,
 			.gpio0  = 0,
 		}, {
 			.type   = CX23885_VMUX_SVIDEO,
@@ -119,6 +121,7 @@
 					CX25840_VIN4_CH2 |
 					CX25840_VIN8_CH1 |
 					CX25840_SVIDEO_ON,
+			.amux   = CX25840_AUDIO7,
 			.gpio0  = 0,
 		} },
 	},
@@ -153,7 +156,30 @@
 	},
 	[CX23885_BOARD_HAUPPAUGE_HVR1500] = {
 		.name		= "Hauppauge WinTV-HVR1500",
+		.porta		= CX23885_ANALOG_VIDEO,
 		.portc		= CX23885_MPEG_DVB,
+		.tuner_type	= TUNER_XC2028,
+		.tuner_addr	= 0x61, /* 0xc2 >> 1 */
+		.input          = {{
+			.type   = CX23885_VMUX_TELEVISION,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN5_CH2 |
+					CX25840_VIN2_CH1,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN4_CH2 |
+					CX25840_VIN6_CH1,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_SVIDEO,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN4_CH2 |
+					CX25840_VIN8_CH1 |
+					CX25840_SVIDEO_ON,
+			.gpio0  = 0,
+		} },
 	},
 	[CX23885_BOARD_HAUPPAUGE_HVR1200] = {
 		.name		= "Hauppauge WinTV-HVR1200",
@@ -387,6 +413,31 @@
 				.vmux   = CX25840_COMPOSITE1,
 		} },
 	},
+	[CX23885_BOARD_MPX885] = {
+		.name		= "MPX-885",
+		.porta		= CX23885_ANALOG_VIDEO,
+		.input          = {{
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   = CX25840_COMPOSITE1,
+			.amux   = CX25840_AUDIO6,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE2,
+			.vmux   = CX25840_COMPOSITE2,
+			.amux   = CX25840_AUDIO6,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE3,
+			.vmux   = CX25840_COMPOSITE3,
+			.amux   = CX25840_AUDIO7,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE4,
+			.vmux   = CX25840_COMPOSITE4,
+			.amux   = CX25840_AUDIO7,
+			.gpio0  = 0,
+		} },
+	},
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
 
@@ -1415,6 +1466,8 @@
 	case CX23885_BOARD_HAUPPAUGE_HVR1290:
 	case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
 	case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
+	case CX23885_BOARD_HAUPPAUGE_HVR1500:
+	case CX23885_BOARD_MPX885:
 		dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
 				&dev->i2c_bus[2].i2c_adap,
 				"cx25840", 0x88 >> 1, NULL);
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885-core.c linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885-core.c
--- linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -54,7 +54,7 @@
 
 #define dprintk(level, fmt, arg...)\
 	do { if (debug >= level)\
-		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+		printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
 	} while (0)
 
 static unsigned int cx23885_devcount;
@@ -155,12 +155,12 @@
 		.cnt2_reg	= DMA5_CNT2,
 	},
 	[SRAM_CH07] = {
-		.name		= "ch7",
-		.cmds_start	= 0x0,
-		.ctrl_start	= 0x0,
-		.cdt		= 0x0,
-		.fifo_start	= 0x0,
-		.fifo_size	= 0x0,
+		.name		= "TV Audio",
+		.cmds_start	= 0x10190,
+		.ctrl_start	= 0x10480,
+		.cdt		= 0x10a00,
+		.fifo_start	= 0x7000,
+		.fifo_size	= 0x1000,
 		.ptr1_reg	= DMA6_PTR1,
 		.ptr2_reg	= DMA6_PTR2,
 		.cnt1_reg	= DMA6_CNT1,
@@ -1082,10 +1082,10 @@
 static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
 			       unsigned int offset, u32 sync_line,
 			       unsigned int bpl, unsigned int padding,
-			       unsigned int lines)
+			       unsigned int lines,  unsigned int lpi)
 {
 	struct scatterlist *sg;
-	unsigned int line, todo;
+	unsigned int line, todo, sol;
 
 	/* sync instruction */
 	if (sync_line != NO_SYNC_LINE)
@@ -1098,16 +1098,22 @@
 			offset -= sg_dma_len(sg);
 			sg++;
 		}
+
+		if (lpi && line > 0 && !(line % lpi))
+			sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
+		else
+			sol = RISC_SOL;
+
 		if (bpl <= sg_dma_len(sg)-offset) {
 			/* fits into current chunk */
-			*(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
+			*(rp++) = cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
 			*(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
 			*(rp++) = cpu_to_le32(0); /* bits 63-32 */
 			offset += bpl;
 		} else {
 			/* scanline needs to be split */
 			todo = bpl;
-			*(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|
+			*(rp++) = cpu_to_le32(RISC_WRITE|sol|
 					    (sg_dma_len(sg)-offset));
 			*(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
 			*(rp++) = cpu_to_le32(0); /* bits 63-32 */
@@ -1164,10 +1170,10 @@
 	rp = risc->cpu;
 	if (UNSET != top_offset)
 		rp = cx23885_risc_field(rp, sglist, top_offset, 0,
-					bpl, padding, lines);
+					bpl, padding, lines, 0);
 	if (UNSET != bottom_offset)
 		rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x200,
-					bpl, padding, lines);
+					bpl, padding, lines, 0);
 
 	/* save pointer to jmp instruction address */
 	risc->jmp = rp;
@@ -1175,11 +1181,11 @@
 	return 0;
 }
 
-static int cx23885_risc_databuffer(struct pci_dev *pci,
+int cx23885_risc_databuffer(struct pci_dev *pci,
 				   struct btcx_riscmem *risc,
 				   struct scatterlist *sglist,
 				   unsigned int bpl,
-				   unsigned int lines)
+				   unsigned int lines, unsigned int lpi)
 {
 	u32 instructions;
 	__le32 *rp;
@@ -1199,7 +1205,8 @@
 
 	/* write risc instructions */
 	rp = risc->cpu;
-	rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines);
+	rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE,
+				bpl, 0, lines, lpi);
 
 	/* save pointer to jmp instruction address */
 	risc->jmp = rp;
@@ -1207,6 +1214,54 @@
 	return 0;
 }
 
+int cx23885_risc_vbibuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+			struct scatterlist *sglist, unsigned int top_offset,
+			unsigned int bottom_offset, unsigned int bpl,
+			unsigned int padding, unsigned int lines)
+{
+	u32 instructions, fields;
+	__le32 *rp;
+	int rc;
+
+	fields = 0;
+	if (UNSET != top_offset)
+		fields++;
+	if (UNSET != bottom_offset)
+		fields++;
+
+	/* estimate risc mem: worst case is one write per page border +
+	   one write per scan line + syncs + jump (all 2 dwords).  Padding
+	   can cause next bpl to start close to a page border.  First DMA
+	   region may be smaller than PAGE_SIZE */
+	/* write and jump need and extra dword */
+	instructions  = fields * (1 + ((bpl + padding) * lines)
+		/ PAGE_SIZE + lines);
+	instructions += 2;
+	rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+	if (rc < 0)
+		return rc;
+	/* write risc instructions */
+	rp = risc->cpu;
+
+	/* Sync to line 6, so US CC line 21 will appear in line '12'
+	 * in the userland vbi payload */
+	if (UNSET != top_offset)
+		rp = cx23885_risc_field(rp, sglist, top_offset, 6,
+					bpl, padding, lines, 0);
+
+	if (UNSET != bottom_offset)
+		rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x207,
+					bpl, padding, lines, 0);
+
+
+
+	/* save pointer to jmp instruction address */
+	risc->jmp = rp;
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+	return 0;
+}
+
+
 int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
 				u32 reg, u32 mask, u32 value)
 {
@@ -1517,7 +1572,7 @@
 			goto fail;
 		cx23885_risc_databuffer(dev->pci, &buf->risc,
 					videobuf_to_dma(&buf->vb)->sglist,
-					buf->vb.width, buf->vb.height);
+					buf->vb.width, buf->vb.height, 0);
 	}
 	buf->vb.state = VIDEOBUF_PREPARED;
 	return 0;
@@ -1741,15 +1796,19 @@
 	struct cx23885_tsport *ts2 = &dev->ts2;
 	u32 pci_status, pci_mask;
 	u32 vida_status, vida_mask;
+	u32 audint_status, audint_mask;
 	u32 ts1_status, ts1_mask;
 	u32 ts2_status, ts2_mask;
 	int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0;
+	int audint_count = 0;
 	bool subdev_handled;
 
 	pci_status = cx_read(PCI_INT_STAT);
 	pci_mask = cx23885_irq_get_mask(dev);
 	vida_status = cx_read(VID_A_INT_STAT);
 	vida_mask = cx_read(VID_A_INT_MSK);
+	audint_status = cx_read(AUDIO_INT_INT_STAT);
+	audint_mask = cx_read(AUDIO_INT_INT_MSK);
 	ts1_status = cx_read(VID_B_INT_STAT);
 	ts1_mask = cx_read(VID_B_INT_MSK);
 	ts2_status = cx_read(VID_C_INT_STAT);
@@ -1759,12 +1818,15 @@
 		goto out;
 
 	vida_count = cx_read(VID_A_GPCNT);
+	audint_count = cx_read(AUD_INT_A_GPCNT);
 	ts1_count = cx_read(ts1->reg_gpcnt);
 	ts2_count = cx_read(ts2->reg_gpcnt);
 	dprintk(7, "pci_status: 0x%08x  pci_mask: 0x%08x\n",
 		pci_status, pci_mask);
 	dprintk(7, "vida_status: 0x%08x vida_mask: 0x%08x count: 0x%x\n",
 		vida_status, vida_mask, vida_count);
+	dprintk(7, "audint_status: 0x%08x audint_mask: 0x%08x count: 0x%x\n",
+		audint_status, audint_mask, audint_count);
 	dprintk(7, "ts1_status: 0x%08x  ts1_mask: 0x%08x count: 0x%x\n",
 		ts1_status, ts1_mask, ts1_count);
 	dprintk(7, "ts2_status: 0x%08x  ts2_mask: 0x%08x count: 0x%x\n",
@@ -1861,6 +1923,9 @@
 	if (vida_status)
 		handled += cx23885_video_irq(dev, vida_status);
 
+	if (audint_status)
+		handled += cx23885_audio_irq(dev, audint_status, audint_mask);
+
 	if (pci_status & PCI_MSK_IR) {
 		subdev_handled = false;
 		v4l2_subdev_call(dev->sd_ir, core, interrupt_service_routine,
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885-dvb.c linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885-dvb.c
--- linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885-dvb.c	2012-03-19 21:31:23.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885-dvb.c	2012-03-19 21:33:30.000000000 -0400
@@ -844,7 +844,7 @@
 			static struct xc2028_ctrl ctl = {
 				.fname   = "/*(DEBLOBBED)*/",
 				.max_len = 64,
-				.demod   = 5000,
+				.demod   = XC3028_FE_DIBCOM52,
 				/* This is true for all demods with
 					v36 firmware? */
 				.type    = XC2028_D2633,
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885.h linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885.h
--- linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885.h	2012-01-04 18:55:44.000000000 -0500
@@ -86,6 +86,7 @@
 #define CX23885_BOARD_GOTVIEW_X5_3D_HYBRID     29
 #define CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF 30
 #define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000 31
+#define CX23885_BOARD_MPX885                   32
 
 #define GPIO_0 0x00000001
 #define GPIO_1 0x00000002
@@ -192,6 +193,7 @@
 struct cx23885_input {
 	enum cx23885_itype type;
 	unsigned int    vmux;
+	unsigned int    amux;
 	u32             gpio0, gpio1, gpio2, gpio3;
 };
 
@@ -318,6 +320,34 @@
 	struct rc_dev		*rc;
 };
 
+struct cx23885_audio_buffer {
+	unsigned int		bpl;
+	struct btcx_riscmem	risc;
+	struct videobuf_dmabuf	dma;
+};
+
+struct cx23885_audio_dev {
+	struct cx23885_dev	*dev;
+
+	struct pci_dev		*pci;
+
+	struct snd_card		*card;
+
+	spinlock_t		lock;
+
+	atomic_t		count;
+
+	unsigned int		dma_size;
+	unsigned int		period_size;
+	unsigned int		num_periods;
+
+	struct videobuf_dmabuf	*dma_risc;
+
+	struct cx23885_audio_buffer   *buf;
+
+	struct snd_pcm_substream *substream;
+};
+
 struct cx23885_dev {
 	atomic_t                   refcount;
 	struct v4l2_device 	   v4l2_dev;
@@ -362,6 +392,7 @@
 	/* Analog video */
 	u32                        resources;
 	unsigned int               input;
+	unsigned int               audinput; /* Selectable audio input */
 	u32                        tvaudio;
 	v4l2_std_id                tvnorm;
 	unsigned int               tuner_type;
@@ -400,6 +431,9 @@
 	atomic_t                   v4l_reader_count;
 	struct cx23885_tvnorm      encodernorm;
 
+	/* Analog raw audio */
+	struct cx23885_audio_dev   *audio_dev;
+
 };
 
 static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev)
@@ -478,6 +512,11 @@
 	unsigned int top_offset, unsigned int bottom_offset,
 	unsigned int bpl, unsigned int padding, unsigned int lines);
 
+extern int cx23885_risc_vbibuffer(struct pci_dev *pci,
+	struct btcx_riscmem *risc, struct scatterlist *sglist,
+	unsigned int top_offset, unsigned int bottom_offset,
+	unsigned int bpl, unsigned int padding, unsigned int lines);
+
 void cx23885_cancel_buffers(struct cx23885_tsport *port);
 
 extern int cx23885_restart_queue(struct cx23885_tsport *port,
@@ -533,6 +572,8 @@
 extern int cx23885_video_register(struct cx23885_dev *dev);
 extern void cx23885_video_unregister(struct cx23885_dev *dev);
 extern int cx23885_video_irq(struct cx23885_dev *dev, u32 status);
+extern void cx23885_video_wakeup(struct cx23885_dev *dev,
+	struct cx23885_dmaqueue *q, u32 count);
 
 /* ----------------------------------------------------------- */
 /* cx23885-vbi.c                                               */
@@ -540,6 +581,9 @@
 	struct v4l2_format *f);
 extern void cx23885_vbi_timeout(unsigned long data);
 extern struct videobuf_queue_ops cx23885_vbi_qops;
+extern int cx23885_restart_vbi_queue(struct cx23885_dev *dev,
+	struct cx23885_dmaqueue *q);
+extern int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status);
 
 /* cx23885-i2c.c                                                */
 extern int cx23885_i2c_register(struct cx23885_i2c *bus);
@@ -563,6 +607,18 @@
 extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask);
 extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput);
 
+/* ----------------------------------------------------------- */
+/* cx23885-alsa.c                                             */
+extern struct cx23885_audio_dev *cx23885_audio_register(
+					struct cx23885_dev *dev);
+extern void cx23885_audio_unregister(struct cx23885_dev *dev);
+extern int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask);
+extern int cx23885_risc_databuffer(struct pci_dev *pci,
+				   struct btcx_riscmem *risc,
+				   struct scatterlist *sglist,
+				   unsigned int bpl,
+				   unsigned int lines,
+				   unsigned int lpi);
 
 /* ----------------------------------------------------------- */
 /* tv norms                                                    */
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885-i2c.c linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885-i2c.c
--- linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -287,6 +287,7 @@
 	[0x32 >> 1] = "cx24227",
 	[0x88 >> 1] = "cx25837",
 	[0x84 >> 1] = "tda8295",
+	[0x98 >> 1] = "flatiron",
 	[0xa0 >> 1] = "eeprom",
 	[0xc0 >> 1] = "tuner/mt2131/tda8275",
 	[0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028",
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885-reg.h linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885-reg.h
--- linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885-reg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885-reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -203,6 +203,7 @@
 #define SD2_BIAS_CTRL	0x0000000A
 #define AMP_BIAS_CTRL	0x0000000C
 #define CH_PWR_CTRL1	0x0000000E
+#define FLD_CH_SEL      (1 << 3)
 #define CH_PWR_CTRL2	0x0000000F
 #define DSM_STATUS1	0x00000010
 #define DSM_STATUS2	0x00000011
@@ -271,7 +272,9 @@
 #define VID_BC_MSK_OPC_ERR (1 << 16)
 #define VID_BC_MSK_SYNC    (1 << 12)
 #define VID_BC_MSK_OF      (1 <<  8)
+#define VID_BC_MSK_VBI_RISCI2 (1 <<  5)
 #define VID_BC_MSK_RISCI2  (1 <<  4)
+#define VID_BC_MSK_VBI_RISCI1 (1 <<  1)
 #define VID_BC_MSK_RISCI1   1
 
 #define VID_C_INT_MSK	0x00040040
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885-vbi.c linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885-vbi.c
--- linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885-vbi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885-vbi.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,12 @@
 
 /* ------------------------------------------------------------------ */
 
+#define VBI_LINE_LENGTH 1440
+#define NTSC_VBI_START_LINE 10        /* line 10 - 21 */
+#define NTSC_VBI_END_LINE   21
+#define NTSC_VBI_LINES      (NTSC_VBI_END_LINE - NTSC_VBI_START_LINE + 1)
+
+
 int cx23885_vbi_fmt(struct file *file, void *priv,
 	struct v4l2_format *f)
 {
@@ -49,43 +55,86 @@
 
 	if (dev->tvnorm & V4L2_STD_525_60) {
 		/* ntsc */
-		f->fmt.vbi.sampling_rate = 28636363;
+		f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
+		f->fmt.vbi.sampling_rate = 27000000;
+		f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+		f->fmt.vbi.offset = 0;
+		f->fmt.vbi.flags = 0;
 		f->fmt.vbi.start[0] = 10;
-		f->fmt.vbi.start[1] = 273;
-
+		f->fmt.vbi.count[0] = 17;
+		f->fmt.vbi.start[1] = 263 + 10 + 1;
+		f->fmt.vbi.count[1] = 17;
 	} else if (dev->tvnorm & V4L2_STD_625_50) {
 		/* pal */
 		f->fmt.vbi.sampling_rate = 35468950;
 		f->fmt.vbi.start[0] = 7 - 1;
 		f->fmt.vbi.start[1] = 319 - 1;
 	}
+
 	return 0;
 }
 
+/* We're given the Video Interrupt status register.
+ * The cx23885_video_irq() func has already validated
+ * the potential error bits, we just need to
+ * deal with vbi payload and return indication if
+ * we actually processed any payload.
+ */
+int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status)
+{
+	u32 count;
+	int handled = 0;
+
+	if (status & VID_BC_MSK_VBI_RISCI1) {
+		dprintk(1, "%s() VID_BC_MSK_VBI_RISCI1\n", __func__);
+		spin_lock(&dev->slock);
+		count = cx_read(VID_A_GPCNT);
+		cx23885_video_wakeup(dev, &dev->vbiq, count);
+		spin_unlock(&dev->slock);
+		handled++;
+	}
+
+	if (status & VID_BC_MSK_VBI_RISCI2) {
+		dprintk(1, "%s() VID_BC_MSK_VBI_RISCI2\n", __func__);
+		dprintk(2, "stopper vbi\n");
+		spin_lock(&dev->slock);
+		cx23885_restart_vbi_queue(dev, &dev->vbiq);
+		spin_unlock(&dev->slock);
+		handled++;
+	}
+
+	return handled;
+}
+
 static int cx23885_start_vbi_dma(struct cx23885_dev    *dev,
 			 struct cx23885_dmaqueue *q,
 			 struct cx23885_buffer   *buf)
 {
+	dprintk(1, "%s()\n", __func__);
+
 	/* setup fifo + format */
 	cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02],
 				buf->vb.width, buf->risc.dma);
 
 	/* reset counter */
+	cx_write(VID_A_GPCNT_CTL, 3);
+	cx_write(VID_A_VBI_CTRL, 3);
+	cx_write(VBI_A_GPCNT_CTL, 3);
 	q->count = 1;
 
-	/* enable irqs */
+	/* enable irq */
 	cx23885_irq_add_enable(dev, 0x01);
 	cx_set(VID_A_INT_MSK, 0x000022);
 
 	/* start dma */
 	cx_set(DEV_CNTRL2, (1<<5));
-	cx_set(VID_A_DMA_CTL, 0x00000022);
+	cx_set(VID_A_DMA_CTL, 0x22); /* FIFO and RISC enable */
 
 	return 0;
 }
 
 
-static int cx23885_restart_vbi_queue(struct cx23885_dev    *dev,
+int cx23885_restart_vbi_queue(struct cx23885_dev    *dev,
 			     struct cx23885_dmaqueue *q)
 {
 	struct cx23885_buffer *buf;
@@ -102,7 +151,7 @@
 		buf = list_entry(item, struct cx23885_buffer, vb.queue);
 		buf->count = q->count++;
 	}
-	mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+	mod_timer(&q->timeout, jiffies + (BUFFER_TIMEOUT / 30));
 	return 0;
 }
 
@@ -113,8 +162,7 @@
 	struct cx23885_buffer *buf;
 	unsigned long flags;
 
-	cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH02]);
-
+	/* Stop the VBI engine */
 	cx_clear(VID_A_DMA_CTL, 0x22);
 
 	spin_lock_irqsave(&dev->slock, flags);
@@ -132,7 +180,7 @@
 }
 
 /* ------------------------------------------------------------------ */
-#define VBI_LINE_LENGTH 2048
+#define VBI_LINE_LENGTH 1440
 #define VBI_LINE_COUNT 17
 
 static int
@@ -173,7 +221,7 @@
 		rc = videobuf_iolock(q, &buf->vb, NULL);
 		if (0 != rc)
 			goto fail;
-		cx23885_risc_buffer(dev->pci, &buf->risc,
+		cx23885_risc_vbibuffer(dev->pci, &buf->risc,
 				 dma->sglist,
 				 0, buf->vb.width * buf->vb.height,
 				 buf->vb.width, 0,
@@ -207,7 +255,7 @@
 		cx23885_start_vbi_dma(dev, q, buf);
 		buf->vb.state = VIDEOBUF_ACTIVE;
 		buf->count    = q->count++;
-		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+		mod_timer(&q->timeout, jiffies + (BUFFER_TIMEOUT / 30));
 		dprintk(2, "[%p/%d] vbi_queue - first active\n",
 			buf, buf->vb.i);
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885-video.c linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885-video.c
--- linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23885-video.c	2012-03-19 21:31:23.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23885-video.c	2012-03-19 21:33:30.000000000 -0400
@@ -37,6 +37,8 @@
 #include "cx23885-ioctl.h"
 #include "tuner-xc2028.h"
 
+#include <media/cx25840.h>
+
 MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards");
 MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
 MODULE_LICENSE("GPL");
@@ -69,14 +71,14 @@
 
 #define dprintk(level, fmt, arg...)\
 	do { if (video_debug >= level)\
-		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+		printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
 	} while (0)
 
 /* ------------------------------------------------------------------- */
 /* static data                                                         */
 
 #define FORMAT_FLAGS_PACKED       0x01
-
+#if 0
 static struct cx23885_fmt formats[] = {
 	{
 		.name     = "8 bpp, gray",
@@ -130,6 +132,23 @@
 		.flags    = FORMAT_FLAGS_PACKED,
 	},
 };
+#else
+static struct cx23885_fmt formats[] = {
+	{
+#if 0
+		.name     = "4:2:2, packed, UYVY",
+		.fourcc   = V4L2_PIX_FMT_UYVY,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	}, {
+#endif
+		.name     = "4:2:2, packed, YUYV",
+		.fourcc   = V4L2_PIX_FMT_YUYV,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	}
+};
+#endif
 
 static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc)
 {
@@ -139,7 +158,12 @@
 		if (formats[i].fourcc == fourcc)
 			return formats+i;
 
-	printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc);
+	printk(KERN_ERR "%s(%c%c%c%c) NOT FOUND\n", __func__,
+		(fourcc & 0xff),
+		((fourcc >> 8) & 0xff),
+		((fourcc >> 16) & 0xff),
+		((fourcc >> 24) & 0xff)
+		);
 	return NULL;
 }
 
@@ -171,7 +195,7 @@
 			.id            = V4L2_CID_CONTRAST,
 			.name          = "Contrast",
 			.minimum       = 0,
-			.maximum       = 0xff,
+			.maximum       = 0x7f,
 			.step          = 1,
 			.default_value = 0x3f,
 			.type          = V4L2_CTRL_TYPE_INTEGER,
@@ -184,10 +208,10 @@
 		.v = {
 			.id            = V4L2_CID_HUE,
 			.name          = "Hue",
-			.minimum       = 0,
-			.maximum       = 0xff,
+			.minimum       = -127,
+			.maximum       = 128,
 			.step          = 1,
-			.default_value = 0x7f,
+			.default_value = 0x0,
 			.type          = V4L2_CTRL_TYPE_INTEGER,
 		},
 		.off                   = 128,
@@ -202,9 +226,9 @@
 			.id            = V4L2_CID_SATURATION,
 			.name          = "Saturation",
 			.minimum       = 0,
-			.maximum       = 0xff,
+			.maximum       = 0x7f,
 			.step          = 1,
-			.default_value = 0x7f,
+			.default_value = 0x3f,
 			.type          = V4L2_CTRL_TYPE_INTEGER,
 		},
 		.off                   = 0,
@@ -258,8 +282,8 @@
 	NULL
 };
 
-static void cx23885_video_wakeup(struct cx23885_dev *dev,
-		 struct cx23885_dmaqueue *q, u32 count)
+void cx23885_video_wakeup(struct cx23885_dev *dev,
+	struct cx23885_dmaqueue *q, u32 count)
 {
 	struct cx23885_buffer *buf;
 	int bc;
@@ -393,6 +417,71 @@
 	mutex_unlock(&dev->lock);
 }
 
+static int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data)
+{
+	/* 8 bit registers, 8 bit values */
+	u8 buf[] = { reg, data };
+
+	struct i2c_msg msg = { .addr = 0x98 >> 1,
+		.flags = 0, .buf = buf, .len = 2 };
+
+	return i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg, 1);
+}
+
+static u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg)
+{
+	/* 8 bit registers, 8 bit values */
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+
+	struct i2c_msg msg[] = {
+		{ .addr = 0x98 >> 1, .flags = 0, .buf = b0, .len = 1 },
+		{ .addr = 0x98 >> 1, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+	};
+
+	ret = i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg[0], 2);
+	if (ret != 2)
+		printk(KERN_ERR "%s() error\n", __func__);
+
+	return b1[0];
+}
+
+static void cx23885_flatiron_dump(struct cx23885_dev *dev)
+{
+	int i;
+	dprintk(1, "Flatiron dump\n");
+	for (i = 0; i < 0x24; i++) {
+		dprintk(1, "FI[%02x] = %02x\n", i,
+			cx23885_flatiron_read(dev, i));
+	}
+}
+
+static int cx23885_flatiron_mux(struct cx23885_dev *dev, int input)
+{
+	u8 val;
+	dprintk(1, "%s(input = %d)\n", __func__, input);
+
+	if (input == 1)
+		val = cx23885_flatiron_read(dev, CH_PWR_CTRL1) & ~FLD_CH_SEL;
+	else if (input == 2)
+		val = cx23885_flatiron_read(dev, CH_PWR_CTRL1) | FLD_CH_SEL;
+	else
+		return -EINVAL;
+
+	val |= 0x20; /* Enable clock to delta-sigma and dec filter */
+
+	cx23885_flatiron_write(dev, CH_PWR_CTRL1, val);
+
+	/* Wake up */
+	cx23885_flatiron_write(dev, CH_PWR_CTRL2, 0);
+
+	if (video_debug)
+		cx23885_flatiron_dump(dev);
+
+	return 0;
+}
+
 static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
 {
 	dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
@@ -413,27 +502,59 @@
 	v4l2_subdev_call(dev->sd_cx25840, video, s_routing,
 			INPUT(input)->vmux, 0, 0);
 
+	if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) ||
+		(dev->board == CX23885_BOARD_MPX885)) {
+		/* Configure audio routing */
+		v4l2_subdev_call(dev->sd_cx25840, audio, s_routing,
+			INPUT(input)->amux, 0, 0);
+
+		if (INPUT(input)->amux == CX25840_AUDIO7)
+			cx23885_flatiron_mux(dev, 1);
+		else if (INPUT(input)->amux == CX25840_AUDIO6)
+			cx23885_flatiron_mux(dev, 2);
+	}
+
 	return 0;
 }
 
-/* ------------------------------------------------------------------ */
-static int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width,
-	unsigned int height, enum v4l2_field field)
+static int cx23885_audio_mux(struct cx23885_dev *dev, unsigned int input)
 {
-	dprintk(1, "%s()\n", __func__);
+	dprintk(1, "%s(input=%d)\n", __func__, input);
+
+	/* The baseband video core of the cx23885 has two audio inputs.
+	 * LR1 and LR2. In almost every single case so far only HVR1xxx
+	 * cards we've only ever supported LR1. Time to support LR2,
+	 * which is available via the optional white breakout header on
+	 * the board.
+	 * We'll use a could of existing enums in the card struct to allow
+	 * devs to specify which baseband input they need, or just default
+	 * to what we've always used.
+	 */
+	if (INPUT(input)->amux == CX25840_AUDIO7)
+		cx23885_flatiron_mux(dev, 1);
+	else if (INPUT(input)->amux == CX25840_AUDIO6)
+		cx23885_flatiron_mux(dev, 2);
+	else {
+		/* Not specifically defined, assume the default. */
+		cx23885_flatiron_mux(dev, 1);
+	}
+
 	return 0;
 }
 
+/* ------------------------------------------------------------------ */
 static int cx23885_start_video_dma(struct cx23885_dev *dev,
 			   struct cx23885_dmaqueue *q,
 			   struct cx23885_buffer *buf)
 {
 	dprintk(1, "%s()\n", __func__);
 
+	/* Stop the dma/fifo before we tamper with it's risc programs */
+	cx_clear(VID_A_DMA_CTL, 0x11);
+
 	/* setup fifo + format */
 	cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
 				buf->bpl, buf->risc.dma);
-	cx23885_set_scale(dev, buf->vb.width, buf->vb.height, buf->vb.field);
 
 	/* reset counter */
 	cx_write(VID_A_GPCNT_CTL, 3);
@@ -748,7 +869,7 @@
 	fh->type     = type;
 	fh->width    = 320;
 	fh->height   = 240;
-	fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+	fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_YUYV);
 
 	videobuf_queue_sg_init(&fh->vidq, &cx23885_video_qops,
 			    &dev->pci->dev, &dev->slock,
@@ -757,6 +878,14 @@
 			    sizeof(struct cx23885_buffer),
 			    fh, NULL);
 
+	videobuf_queue_sg_init(&fh->vbiq, &cx23885_vbi_qops,
+		&dev->pci->dev, &dev->slock,
+		V4L2_BUF_TYPE_VBI_CAPTURE,
+		V4L2_FIELD_SEQ_TB,
+		sizeof(struct cx23885_buffer),
+		fh, NULL);
+
+
 	dprintk(1, "post videobuf_queue_init()\n");
 
 	return 0;
@@ -884,8 +1013,9 @@
 static int cx23885_set_control(struct cx23885_dev *dev,
 	struct v4l2_control *ctl)
 {
-	dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)"
-		" (disabled - no action)\n", __func__);
+	dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)\n", __func__);
+	call_all(dev, core, s_ctrl, ctl);
+
 	return 0;
 }
 
@@ -1059,13 +1189,22 @@
 	struct cx23885_dev *dev = fh->dev;
 	dprintk(1, "%s()\n", __func__);
 
-	if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+	if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
 		return -EINVAL;
 	if (unlikely(i != fh->type))
 		return -EINVAL;
 
 	if (unlikely(!res_get(dev, fh, get_resource(fh))))
 		return -EBUSY;
+
+	/* Don't start VBI streaming unless vida streaming
+	 * has already started.
+	 */
+	if ((fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) &&
+		((cx_read(VID_A_DMA_CTL) & 0x11) == 0))
+		return -EINVAL;
+
 	return videobuf_streamon(get_queue(fh));
 }
 
@@ -1076,7 +1215,8 @@
 	int err, res;
 	dprintk(1, "%s()\n", __func__);
 
-	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
 		return -EINVAL;
 	if (i != fh->type)
 		return -EINVAL;
@@ -1119,7 +1259,7 @@
 	dprintk(1, "%s()\n", __func__);
 
 	n = i->index;
-	if (n >= 4)
+	if (n >= MAX_CX23885_INPUT)
 		return -EINVAL;
 
 	if (0 == INPUT(n)->type)
@@ -1133,6 +1273,11 @@
 		i->type = V4L2_INPUT_TYPE_TUNER;
 		i->std = CX23885_NORMS;
 	}
+
+	/* Two selectable audio inputs for non-tv inputs */
+	if (INPUT(n)->type != CX23885_VMUX_TELEVISION)
+		i->audioset = 0x3;
+
 	return 0;
 }
 
@@ -1159,13 +1304,20 @@
 
 	dprintk(1, "%s(%d)\n", __func__, i);
 
-	if (i >= 4) {
+	if (i >= MAX_CX23885_INPUT) {
 		dprintk(1, "%s() -EINVAL\n", __func__);
 		return -EINVAL;
 	}
 
+	if (INPUT(i)->type == 0)
+		return -EINVAL;
+
 	mutex_lock(&dev->lock);
 	cx23885_video_mux(dev, i);
+
+	/* By default establish the default audio input for the card also */
+	/* Caller is free to use VIDIOC_S_AUDIO to override afterwards */
+	cx23885_audio_mux(dev, i);
 	mutex_unlock(&dev->lock);
 	return 0;
 }
@@ -1185,6 +1337,64 @@
 	return 0;
 }
 
+static int cx23885_query_audinput(struct file *file, void *priv,
+	struct v4l2_audio *i)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+	static const char *iname[] = {
+		[0] = "Baseband L/R 1",
+		[1] = "Baseband L/R 2",
+	};
+	unsigned int n;
+	dprintk(1, "%s()\n", __func__);
+
+	n = i->index;
+	if (n >= 2)
+		return -EINVAL;
+
+	memset(i, 0, sizeof(*i));
+	i->index = n;
+	strcpy(i->name, iname[n]);
+	i->capability  = V4L2_AUDCAP_STEREO;
+	i->mode  = V4L2_AUDMODE_AVL;
+	return 0;
+
+}
+
+static int vidioc_enum_audinput(struct file *file, void *priv,
+				struct v4l2_audio *i)
+{
+	return cx23885_query_audinput(file, priv, i);
+}
+
+static int vidioc_g_audinput(struct file *file, void *priv,
+	struct v4l2_audio *i)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+	i->index = dev->audinput;
+	dprintk(1, "%s(input=%d)\n", __func__, i->index);
+
+	return cx23885_query_audinput(file, priv, i);
+}
+
+static int vidioc_s_audinput(struct file *file, void *priv,
+	struct v4l2_audio *i)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+	if (i->index >= 2)
+		return -EINVAL;
+
+	dprintk(1, "%s(%d)\n", __func__, i->index);
+
+	dev->audinput = i->index;
+
+	/* Skip the audio defaults from the cards struct, caller wants
+	 * directly touch the audio mux hardware. */
+	cx23885_flatiron_mux(dev, dev->audinput + 1);
+	return 0;
+}
+
 static int vidioc_queryctrl(struct file *file, void *priv,
 				struct v4l2_queryctrl *qctrl)
 {
@@ -1221,10 +1431,8 @@
 		return -EINVAL;
 
 	strcpy(t->name, "Television");
-	t->type       = V4L2_TUNER_ANALOG_TV;
-	t->capability = V4L2_TUNER_CAP_NORM;
-	t->rangehigh  = 0xffffffffUL;
-	t->signal = 0xffff ; /* LOCKED */
+
+	call_all(dev, tuner, g_tuner, t);
 	return 0;
 }
 
@@ -1237,6 +1445,9 @@
 		return -EINVAL;
 	if (0 != t->index)
 		return -EINVAL;
+	/* Update the A/V core */
+	call_all(dev, tuner, s_tuner, t);
+
 	return 0;
 }
 
@@ -1302,10 +1513,6 @@
 	struct cx23885_buffer *buf;
 	unsigned long flags;
 
-	cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH01]);
-
-	cx_clear(VID_A_DMA_CTL, 0x11);
-
 	spin_lock_irqsave(&dev->slock, flags);
 	while (!list_empty(&q->active)) {
 		buf = list_entry(q->active.next,
@@ -1313,7 +1520,7 @@
 		list_del(&buf->vb.queue);
 		buf->vb.state = VIDEOBUF_ERROR;
 		wake_up(&buf->vb.done);
-		printk(KERN_ERR "%s/0: [%p/%d] timeout - dma=0x%08lx\n",
+		printk(KERN_ERR "%s: [%p/%d] timeout - dma=0x%08lx\n",
 			dev->name, buf, buf->vb.i,
 			(unsigned long)buf->risc.dma);
 	}
@@ -1329,27 +1536,43 @@
 	mask   = cx_read(VID_A_INT_MSK);
 	if (0 == (status & mask))
 		return handled;
+
 	cx_write(VID_A_INT_STAT, status);
 
-	dprintk(2, "%s() status = 0x%08x\n", __func__, status);
-	/* risc op code error */
-	if (status & (1 << 16)) {
-		printk(KERN_WARNING "%s/0: video risc op code error\n",
-			dev->name);
-		cx_clear(VID_A_DMA_CTL, 0x11);
-		cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH01]);
+	/* risc op code error, fifo overflow or line sync detection error */
+	if ((status & VID_BC_MSK_OPC_ERR) ||
+		(status & VID_BC_MSK_SYNC) ||
+		(status & VID_BC_MSK_OF)) {
+
+		if (status & VID_BC_MSK_OPC_ERR) {
+			dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n",
+				VID_BC_MSK_OPC_ERR);
+			printk(KERN_WARNING "%s: video risc op code error\n",
+				dev->name);
+			cx23885_sram_channel_dump(dev,
+				&dev->sram_channels[SRAM_CH01]);
+		}
+
+		if (status & VID_BC_MSK_SYNC)
+			dprintk(7, " (VID_BC_MSK_SYNC 0x%08x) "
+				"video lines miss-match\n",
+				VID_BC_MSK_SYNC);
+
+		if (status & VID_BC_MSK_OF)
+			dprintk(7, " (VID_BC_MSK_OF 0x%08x) fifo overflow\n",
+				VID_BC_MSK_OF);
+
 	}
 
-	/* risc1 y */
-	if (status & 0x01) {
+	/* Video */
+	if (status & VID_BC_MSK_RISCI1) {
 		spin_lock(&dev->slock);
 		count = cx_read(VID_A_GPCNT);
 		cx23885_video_wakeup(dev, &dev->vidq, count);
 		spin_unlock(&dev->slock);
 		handled++;
 	}
-	/* risc2 y */
-	if (status & 0x10) {
+	if (status & VID_BC_MSK_RISCI2) {
 		dprintk(2, "stopper video\n");
 		spin_lock(&dev->slock);
 		cx23885_restart_video_queue(dev, &dev->vidq);
@@ -1357,6 +1580,9 @@
 		handled++;
 	}
 
+	/* Allow the VBI framework to process it's payload */
+	handled += cx23885_vbi_irq(dev, status);
+
 	return handled;
 }
 
@@ -1405,6 +1631,9 @@
 	.vidioc_g_register    = cx23885_g_register,
 	.vidioc_s_register    = cx23885_s_register,
 #endif
+	.vidioc_enumaudio     = vidioc_enum_audinput,
+	.vidioc_g_audio       = vidioc_g_audinput,
+	.vidioc_s_audio       = vidioc_s_audinput,
 };
 
 static struct video_device cx23885_vbi_template;
@@ -1429,6 +1658,14 @@
 	dprintk(1, "%s()\n", __func__);
 	cx23885_irq_remove(dev, 0x01);
 
+	if (dev->vbi_dev) {
+		if (video_is_registered(dev->vbi_dev))
+			video_unregister_device(dev->vbi_dev);
+		else
+			video_device_release(dev->vbi_dev);
+		dev->vbi_dev = NULL;
+		btcx_riscmem_free(dev->pci, &dev->vbiq.stopper);
+	}
 	if (dev->video_dev) {
 		if (video_is_registered(dev->video_dev))
 			video_unregister_device(dev->video_dev);
@@ -1438,6 +1675,9 @@
 
 		btcx_riscmem_free(dev->pci, &dev->vidq.stopper);
 	}
+
+	if (dev->audio_dev)
+		cx23885_audio_unregister(dev);
 }
 
 int cx23885_video_register(struct cx23885_dev *dev)
@@ -1463,7 +1703,14 @@
 	cx23885_risc_stopper(dev->pci, &dev->vidq.stopper,
 		VID_A_DMA_CTL, 0x11, 0x00);
 
-	/* Don't enable VBI yet */
+	/* init vbi dma queues */
+	INIT_LIST_HEAD(&dev->vbiq.active);
+	INIT_LIST_HEAD(&dev->vbiq.queued);
+	dev->vbiq.timeout.function = cx23885_vbi_timeout;
+	dev->vbiq.timeout.data = (unsigned long)dev;
+	init_timer(&dev->vbiq.timeout);
+	cx23885_risc_stopper(dev->pci, &dev->vbiq.stopper,
+		VID_A_DMA_CTL, 0x22, 0x00);
 
 	cx23885_irq_add_enable(dev, 0x01);
 
@@ -1504,8 +1751,7 @@
 		}
 	}
 
-
-	/* register v4l devices */
+	/* register Video device */
 	dev->video_dev = cx23885_vdev_init(dev, dev->pci,
 		&cx23885_video_template, "video");
 	err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER,
@@ -1515,13 +1761,31 @@
 			dev->name);
 		goto fail_unreg;
 	}
-	printk(KERN_INFO "%s/0: registered device %s [v4l2]\n",
+	printk(KERN_INFO "%s: registered device %s [v4l2]\n",
 	       dev->name, video_device_node_name(dev->video_dev));
+
+	/* register VBI device */
+	dev->vbi_dev = cx23885_vdev_init(dev, dev->pci,
+		&cx23885_vbi_template, "vbi");
+	err = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
+				    vbi_nr[dev->nr]);
+	if (err < 0) {
+		printk(KERN_INFO "%s: can't register vbi device\n",
+			dev->name);
+		goto fail_unreg;
+	}
+	printk(KERN_INFO "%s: registered device %s\n",
+	       dev->name, video_device_node_name(dev->vbi_dev));
+
+	/* Register ALSA audio device */
+	dev->audio_dev = cx23885_audio_register(dev);
+
 	/* initial device configuration */
 	mutex_lock(&dev->lock);
 	cx23885_set_tvnorm(dev, dev->tvnorm);
 	init_controls(dev);
 	cx23885_video_mux(dev, 0);
+	cx23885_audio_mux(dev, 0);
 	mutex_unlock(&dev->lock);
 
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23888-ir.c linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23888-ir.c
--- linux-libre-3.1-gnu/drivers/media/video/cx23885/cx23888-ir.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx23885/cx23888-ir.c	2012-01-04 18:55:44.000000000 -0500
@@ -673,7 +673,7 @@
 
 	unsigned int i, n;
 	union cx23888_ir_fifo_rec *p;
-	unsigned u, v;
+	unsigned u, v, w;
 
 	n = count / sizeof(union cx23888_ir_fifo_rec)
 		* sizeof(union cx23888_ir_fifo_rec);
@@ -692,11 +692,12 @@
 		if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
 			/* Assume RTO was because of no IR light input */
 			u = 0;
-			v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n");
+			w = 1;
 		} else {
 			u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
 			if (invert)
 				u = u ? 0 : 1;
+			w = 0;
 		}
 
 		v = (unsigned) pulse_width_count_to_ns(
@@ -707,9 +708,12 @@
 		init_ir_raw_event(&p->ir_core_data);
 		p->ir_core_data.pulse = u;
 		p->ir_core_data.duration = v;
+		p->ir_core_data.timeout = w;
 
-		v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns  %s\n",
-			 v, u ? "mark" : "space");
+		v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns  %s  %s\n",
+			 v, u ? "mark" : "space", w ? "(timed out)" : "");
+		if (w)
+			v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n");
 	}
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx23885/Kconfig linux-libre-3.2-gnu/drivers/media/video/cx23885/Kconfig
--- linux-libre-3.1-gnu/drivers/media/video/cx23885/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx23885/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -38,7 +38,7 @@
 config MEDIA_ALTERA_CI
 	tristate "Altera FPGA based CI module"
 	depends on VIDEO_CX23885 && DVB_CORE
-	select STAPL_ALTERA
+	select ALTERA_STAPL
 	---help---
 	  An Altera FPGA CI module for NetUP Dual DVB-T/C RF CI card.
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx23885/Makefile linux-libre-3.2-gnu/drivers/media/video/cx23885/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/cx23885/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx23885/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,14 +2,14 @@
 		    cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \
 		    cx23885-ioctl.o cx23885-ir.o cx23885-av.o cx23885-input.o \
 		    cx23888-ir.o netup-init.o cimax2.o netup-eeprom.o \
-		    cx23885-f300.o
+		    cx23885-f300.o cx23885-alsa.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
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
 
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-alsa.c linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-alsa.c
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-alsa.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-alsa.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,795 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *	Based on SAA713x ALSA driver and CX88 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, 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.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You 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/device.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "cx25821.h"
+#include "cx25821-reg.h"
+
+#define AUDIO_SRAM_CHANNEL	SRAM_CH08
+
+#define dprintk(level, fmt, arg...)				\
+do {								\
+	if (debug >= level)					\
+		pr_info("%s/1: " fmt, chip->dev->name, ##arg);	\
+} while (0)
+#define dprintk_core(level, fmt, arg...)				\
+do {									\
+	if (debug >= level)						\
+		printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name, ##arg); \
+} while (0)
+
+/****************************************************************************
+	Data type declarations - Can be moded to a header file later
+ ****************************************************************************/
+
+static struct snd_card *snd_cx25821_cards[SNDRV_CARDS];
+static int devno;
+
+struct cx25821_audio_buffer {
+	unsigned int bpl;
+	struct btcx_riscmem risc;
+	struct videobuf_dmabuf dma;
+};
+
+struct cx25821_audio_dev {
+	struct cx25821_dev *dev;
+	struct cx25821_dmaqueue q;
+
+	/* pci i/o */
+	struct pci_dev *pci;
+
+	/* audio controls */
+	int irq;
+
+	struct snd_card *card;
+
+	unsigned long iobase;
+	spinlock_t reg_lock;
+	atomic_t count;
+
+	unsigned int dma_size;
+	unsigned int period_size;
+	unsigned int num_periods;
+
+	struct videobuf_dmabuf *dma_risc;
+
+	struct cx25821_audio_buffer *buf;
+
+	struct snd_pcm_substream *substream;
+};
+
+
+/****************************************************************************
+			Module global static vars
+ ****************************************************************************/
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
+static int enable[SNDRV_CARDS] = { 1, [1 ... (SNDRV_CARDS - 1)] = 1 };
+
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled.");
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for cx25821 capture interface(s).");
+
+/****************************************************************************
+				Module macros
+ ****************************************************************************/
+
+MODULE_DESCRIPTION("ALSA driver module for cx25821 based capture cards");
+MODULE_AUTHOR("Hiep Huynh");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Conexant,25821}");	/* "{{Conexant,23881}," */
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+/****************************************************************************
+			Module specific funtions
+ ****************************************************************************/
+/* Constants taken from cx88-reg.h */
+#define AUD_INT_DN_RISCI1       (1 <<  0)
+#define AUD_INT_UP_RISCI1       (1 <<  1)
+#define AUD_INT_RDS_DN_RISCI1   (1 <<  2)
+#define AUD_INT_DN_RISCI2       (1 <<  4)	/* yes, 3 is skipped */
+#define AUD_INT_UP_RISCI2       (1 <<  5)
+#define AUD_INT_RDS_DN_RISCI2   (1 <<  6)
+#define AUD_INT_DN_SYNC         (1 << 12)
+#define AUD_INT_UP_SYNC         (1 << 13)
+#define AUD_INT_RDS_DN_SYNC     (1 << 14)
+#define AUD_INT_OPC_ERR         (1 << 16)
+#define AUD_INT_BER_IRQ         (1 << 20)
+#define AUD_INT_MCHG_IRQ        (1 << 21)
+#define GP_COUNT_CONTROL_RESET	0x3
+
+#define PCI_MSK_AUD_EXT   (1 <<  4)
+#define PCI_MSK_AUD_INT   (1 <<  3)
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip)
+{
+	struct cx25821_audio_buffer *buf = chip->buf;
+	struct cx25821_dev *dev = chip->dev;
+	struct sram_channel *audio_ch =
+	    &cx25821_sram_channels[AUDIO_SRAM_CHANNEL];
+	u32 tmp = 0;
+
+	/* enable output on the GPIO 0 for the MCLK ADC (Audio) */
+	cx25821_set_gpiopin_direction(chip->dev, 0, 0);
+
+	/* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
+	cx_clear(AUD_INT_DMA_CTL,
+		 FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
+
+	/* setup fifo + format - out channel */
+	cx25821_sram_channel_setup_audio(chip->dev, audio_ch, buf->bpl,
+					 buf->risc.dma);
+
+	/* sets bpl size */
+	cx_write(AUD_A_LNGTH, buf->bpl);
+
+	/* reset counter */
+	/* GP_COUNT_CONTROL_RESET = 0x3 */
+	cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+	atomic_set(&chip->count, 0);
+
+	/* Set the input mode to 16-bit */
+	tmp = cx_read(AUD_A_CFG);
+	cx_write(AUD_A_CFG,
+		 tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE |
+		 FLD_AUD_CLK_ENABLE);
+
+	/*
+	pr_info("DEBUG: Start audio DMA, %d B/line, cmds_start(0x%x)= %d lines/FIFO, %d periods, %d byte buffer\n",
+		buf->bpl, audio_ch->cmds_start,
+		cx_read(audio_ch->cmds_start + 12)>>1,
+		chip->num_periods, buf->bpl * chip->num_periods);
+	*/
+
+	/* Enables corresponding bits at AUD_INT_STAT */
+	cx_write(AUD_A_INT_MSK,
+		 FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF | FLD_AUD_DST_SYNC |
+		 FLD_AUD_DST_OPC_ERR);
+
+	/* Clean any pending interrupt bits already set */
+	cx_write(AUD_A_INT_STAT, ~0);
+
+	/* enable audio irqs */
+	cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT);
+
+	/* Turn on audio downstream fifo and risc enable 0x101 */
+	tmp = cx_read(AUD_INT_DMA_CTL);
+	cx_set(AUD_INT_DMA_CTL,
+	       tmp | (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN));
+
+	mdelay(100);
+	return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+static int _cx25821_stop_audio_dma(struct cx25821_audio_dev *chip)
+{
+	struct cx25821_dev *dev = chip->dev;
+
+	/* stop dma */
+	cx_clear(AUD_INT_DMA_CTL,
+		 FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
+
+	/* disable irqs */
+	cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT);
+	cx_clear(AUD_A_INT_MSK,
+		 AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | AUD_INT_DN_RISCI2 |
+		 AUD_INT_DN_RISCI1);
+
+	return 0;
+}
+
+#define MAX_IRQ_LOOP 50
+
+/*
+ * BOARD Specific: IRQ dma bits
+ */
+static char *cx25821_aud_irqs[32] = {
+	"dn_risci1", "up_risci1", "rds_dn_risc1",	/* 0-2 */
+	NULL,			/* reserved */
+	"dn_risci2", "up_risci2", "rds_dn_risc2",	/* 4-6 */
+	NULL,			/* reserved */
+	"dnf_of", "upf_uf", "rds_dnf_uf",	/* 8-10 */
+	NULL,			/* reserved */
+	"dn_sync", "up_sync", "rds_dn_sync",	/* 12-14 */
+	NULL,			/* reserved */
+	"opc_err", "par_err", "rip_err",	/* 16-18 */
+	"pci_abort", "ber_irq", "mchg_irq"	/* 19-21 */
+};
+
+/*
+ * BOARD Specific: Threats IRQ audio specific calls
+ */
+static void cx25821_aud_irq(struct cx25821_audio_dev *chip, u32 status,
+			    u32 mask)
+{
+	struct cx25821_dev *dev = chip->dev;
+
+	if (0 == (status & mask))
+		return;
+
+	cx_write(AUD_A_INT_STAT, status);
+	if (debug > 1 || (status & mask & ~0xff))
+		cx25821_print_irqbits(dev->name, "irq aud",
+				      cx25821_aud_irqs,
+				      ARRAY_SIZE(cx25821_aud_irqs), status,
+				      mask);
+
+	/* risc op code error */
+	if (status & AUD_INT_OPC_ERR) {
+		pr_warn("WARNING %s/1: Audio risc op code error\n", dev->name);
+
+		cx_clear(AUD_INT_DMA_CTL,
+			 FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
+		cx25821_sram_channel_dump_audio(dev,
+						&cx25821_sram_channels
+						[AUDIO_SRAM_CHANNEL]);
+	}
+	if (status & AUD_INT_DN_SYNC) {
+		pr_warn("WARNING %s: Downstream sync error!\n", dev->name);
+		cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+		return;
+	}
+
+	/* risc1 downstream */
+	if (status & AUD_INT_DN_RISCI1) {
+		atomic_set(&chip->count, cx_read(AUD_A_GPCNT));
+		snd_pcm_period_elapsed(chip->substream);
+	}
+}
+
+/*
+ * BOARD Specific: Handles IRQ calls
+ */
+static irqreturn_t cx25821_irq(int irq, void *dev_id)
+{
+	struct cx25821_audio_dev *chip = dev_id;
+	struct cx25821_dev *dev = chip->dev;
+	u32 status, pci_status;
+	u32 audint_status, audint_mask;
+	int loop, handled = 0;
+	int audint_count = 0;
+
+	audint_status = cx_read(AUD_A_INT_STAT);
+	audint_mask = cx_read(AUD_A_INT_MSK);
+	audint_count = cx_read(AUD_A_GPCNT);
+	status = cx_read(PCI_INT_STAT);
+
+	for (loop = 0; loop < 1; loop++) {
+		status = cx_read(PCI_INT_STAT);
+		if (0 == status) {
+			status = cx_read(PCI_INT_STAT);
+			audint_status = cx_read(AUD_A_INT_STAT);
+			audint_mask = cx_read(AUD_A_INT_MSK);
+
+			if (status) {
+				handled = 1;
+				cx_write(PCI_INT_STAT, status);
+
+				cx25821_aud_irq(chip, audint_status,
+						audint_mask);
+				break;
+			} else
+				goto out;
+		}
+
+		handled = 1;
+		cx_write(PCI_INT_STAT, status);
+
+		cx25821_aud_irq(chip, audint_status, audint_mask);
+	}
+
+	pci_status = cx_read(PCI_INT_STAT);
+
+	if (handled)
+		cx_write(PCI_INT_STAT, pci_status);
+
+out:
+	return IRQ_RETVAL(handled);
+}
+
+static int dsp_buffer_free(struct cx25821_audio_dev *chip)
+{
+	BUG_ON(!chip->dma_size);
+
+	dprintk(2, "Freeing buffer\n");
+	videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc);
+	videobuf_dma_free(chip->dma_risc);
+	btcx_riscmem_free(chip->pci, &chip->buf->risc);
+	kfree(chip->buf);
+
+	chip->dma_risc = NULL;
+	chip->dma_size = 0;
+
+	return 0;
+}
+
+/****************************************************************************
+				ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE	384
+static struct snd_pcm_hardware snd_cx25821_digital_hw = {
+	.info = SNDRV_PCM_INFO_MMAP |
+	    SNDRV_PCM_INFO_INTERLEAVED |
+	    SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+	.rates = SNDRV_PCM_RATE_48000,
+	.rate_min = 48000,
+	.rate_max = 48000,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* Analog audio output will be full of clicks and pops if there
+	   are not exactly four lines in the SRAM FIFO buffer.  */
+	.period_bytes_min = DEFAULT_FIFO_SIZE / 3,
+	.period_bytes_max = DEFAULT_FIFO_SIZE / 3,
+	.periods_min = 1,
+	.periods_max = AUDIO_LINE_SIZE,
+	/* 128 * 128 = 16384 = 1024 * 16 */
+	.buffer_bytes_max = (AUDIO_LINE_SIZE * AUDIO_LINE_SIZE),
+};
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int err;
+	unsigned int bpl = 0;
+
+	if (!chip) {
+		pr_err("DEBUG: cx25821 can't find device struct. Can't proceed with open\n");
+		return -ENODEV;
+	}
+
+	err =
+	    snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS);
+	if (err < 0)
+		goto _error;
+
+	chip->substream = substream;
+
+	runtime->hw = snd_cx25821_digital_hw;
+
+	if (cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size !=
+	    DEFAULT_FIFO_SIZE) {
+		/* since there are 3 audio Clusters */
+		bpl = cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 3;
+		bpl &= ~7;	/* must be multiple of 8 */
+
+		if (bpl > AUDIO_LINE_SIZE)
+			bpl = AUDIO_LINE_SIZE;
+
+		runtime->hw.period_bytes_min = bpl;
+		runtime->hw.period_bytes_max = bpl;
+	}
+
+	return 0;
+_error:
+	dprintk(1, "Error opening PCM!\n");
+	return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_cx25821_close(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_cx25821_hw_params(struct snd_pcm_substream *substream,
+				 struct snd_pcm_hw_params *hw_params)
+{
+	struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct videobuf_dmabuf *dma;
+
+	struct cx25821_audio_buffer *buf;
+	int ret;
+
+	if (substream->runtime->dma_area) {
+		dsp_buffer_free(chip);
+		substream->runtime->dma_area = NULL;
+	}
+
+	chip->period_size = params_period_bytes(hw_params);
+	chip->num_periods = params_periods(hw_params);
+	chip->dma_size = chip->period_size * params_periods(hw_params);
+
+	BUG_ON(!chip->dma_size);
+	BUG_ON(chip->num_periods & (chip->num_periods - 1));
+
+	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+	if (NULL == buf)
+		return -ENOMEM;
+
+	if (chip->period_size > AUDIO_LINE_SIZE)
+		chip->period_size = AUDIO_LINE_SIZE;
+
+	buf->bpl = chip->period_size;
+
+	dma = &buf->dma;
+	videobuf_dma_init(dma);
+	ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+				       (PAGE_ALIGN(chip->dma_size) >>
+					PAGE_SHIFT));
+	if (ret < 0)
+		goto error;
+
+	ret = videobuf_dma_map(&chip->pci->dev, dma);
+	if (ret < 0)
+		goto error;
+
+	ret =
+	    cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist,
+					  chip->period_size, chip->num_periods,
+					  1);
+	if (ret < 0) {
+		pr_info("DEBUG: ERROR after cx25821_risc_databuffer_audio()\n");
+		goto error;
+	}
+
+	/* Loop back to start of program */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+	buf->risc.jmp[2] = cpu_to_le32(0);	/* bits 63-32 */
+
+	chip->buf = buf;
+	chip->dma_risc = dma;
+
+	substream->runtime->dma_area = chip->dma_risc->vaddr;
+	substream->runtime->dma_bytes = chip->dma_size;
+	substream->runtime->dma_addr = 0;
+
+	return 0;
+
+error:
+	kfree(buf);
+	return ret;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_cx25821_hw_free(struct snd_pcm_substream *substream)
+{
+	struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+
+	if (substream->runtime->dma_area) {
+		dsp_buffer_free(chip);
+		substream->runtime->dma_area = NULL;
+	}
+
+	return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_cx25821_prepare(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+/*
+ * trigger callback
+ */
+static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream,
+				    int cmd)
+{
+	struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+	int err = 0;
+
+	/* Local interrupts are already disabled by ALSA */
+	spin_lock(&chip->reg_lock);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		err = _cx25821_start_audio_dma(chip);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		err = _cx25821_stop_audio_dma(chip);
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+
+	spin_unlock(&chip->reg_lock);
+
+	return err;
+}
+
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_cx25821_pointer(struct snd_pcm_substream
+					     *substream)
+{
+	struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	u16 count;
+
+	count = atomic_read(&chip->count);
+
+	return runtime->period_size * (count & (runtime->periods - 1));
+}
+
+/*
+ * page callback (needed for mmap)
+ */
+static struct page *snd_cx25821_page(struct snd_pcm_substream *substream,
+				     unsigned long offset)
+{
+	void *pageptr = substream->runtime->dma_area + offset;
+
+	return vmalloc_to_page(pageptr);
+}
+
+/*
+ * operators
+ */
+static struct snd_pcm_ops snd_cx25821_pcm_ops = {
+	.open = snd_cx25821_pcm_open,
+	.close = snd_cx25821_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_cx25821_hw_params,
+	.hw_free = snd_cx25821_hw_free,
+	.prepare = snd_cx25821_prepare,
+	.trigger = snd_cx25821_card_trigger,
+	.pointer = snd_cx25821_pointer,
+	.page = snd_cx25821_page,
+};
+
+/*
+ * ALSA create a PCM device:  Called when initializing the board.
+ * Sets up the name and hooks up the callbacks
+ */
+static int snd_cx25821_pcm(struct cx25821_audio_dev *chip, int device,
+			   char *name)
+{
+	struct snd_pcm *pcm;
+	int err;
+
+	err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
+	if (err < 0) {
+		pr_info("ERROR: FAILED snd_pcm_new() in %s\n", __func__);
+		return err;
+	}
+	pcm->private_data = chip;
+	pcm->info_flags = 0;
+	strcpy(pcm->name, name);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx25821_pcm_ops);
+
+	return 0;
+}
+
+/****************************************************************************
+			Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio
+ * Only boards with eeprom and byte 1 at eeprom=1 have it
+ */
+
+static DEFINE_PCI_DEVICE_TABLE(cx25821_audio_pci_tbl) = {
+	{0x14f1, 0x0920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, cx25821_audio_pci_tbl);
+
+/*
+ * Not used in the function snd_cx25821_dev_free so removing
+ * from the file.
+ */
+/*
+static int snd_cx25821_free(struct cx25821_audio_dev *chip)
+{
+	if (chip->irq >= 0)
+		free_irq(chip->irq, chip);
+
+	cx25821_dev_unregister(chip->dev);
+	pci_disable_device(chip->pci);
+
+	return 0;
+}
+*/
+
+/*
+ * Component Destructor
+ */
+static void snd_cx25821_dev_free(struct snd_card *card)
+{
+	struct cx25821_audio_dev *chip = card->private_data;
+
+	/* snd_cx25821_free(chip); */
+	snd_card_free(chip->card);
+}
+
+/*
+ * Alsa Constructor - Component probe
+ */
+static int cx25821_audio_initdev(struct cx25821_dev *dev)
+{
+	struct snd_card *card;
+	struct cx25821_audio_dev *chip;
+	int err;
+
+	if (devno >= SNDRV_CARDS) {
+		pr_info("DEBUG ERROR: devno >= SNDRV_CARDS %s\n", __func__);
+		return -ENODEV;
+	}
+
+	if (!enable[devno]) {
+		++devno;
+		pr_info("DEBUG ERROR: !enable[devno] %s\n", __func__);
+		return -ENOENT;
+	}
+
+	err = snd_card_create(index[devno], id[devno], THIS_MODULE,
+			 sizeof(struct cx25821_audio_dev), &card);
+	if (err < 0) {
+		pr_info("DEBUG ERROR: cannot create snd_card_new in %s\n",
+			__func__);
+		return err;
+	}
+
+	strcpy(card->driver, "cx25821");
+
+	/* Card "creation" */
+	card->private_free = snd_cx25821_dev_free;
+	chip = card->private_data;
+	spin_lock_init(&chip->reg_lock);
+
+	chip->dev = dev;
+	chip->card = card;
+	chip->pci = dev->pci;
+	chip->iobase = pci_resource_start(dev->pci, 0);
+
+	chip->irq = dev->pci->irq;
+
+	err = request_irq(dev->pci->irq, cx25821_irq,
+			  IRQF_SHARED, chip->dev->name, chip);
+
+	if (err < 0) {
+		pr_err("ERROR %s: can't get IRQ %d for ALSA\n",
+		       chip->dev->name, dev->pci->irq);
+		goto error;
+	}
+
+	err = snd_cx25821_pcm(chip, 0, "cx25821 Digital");
+	if (err < 0) {
+		pr_info("DEBUG ERROR: cannot create snd_cx25821_pcm %s\n",
+			__func__);
+		goto error;
+	}
+
+	snd_card_set_dev(card, &chip->pci->dev);
+
+	strcpy(card->shortname, "cx25821");
+	sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name,
+		chip->iobase, chip->irq);
+	strcpy(card->mixername, "CX25821");
+
+	pr_info("%s/%i: ALSA support for cx25821 boards\n",
+		card->driver, devno);
+
+	err = snd_card_register(card);
+	if (err < 0) {
+		pr_info("DEBUG ERROR: cannot register sound card %s\n",
+			__func__);
+		goto error;
+	}
+
+	snd_cx25821_cards[devno] = card;
+
+	devno++;
+	return 0;
+
+error:
+	snd_card_free(card);
+	return err;
+}
+
+/****************************************************************************
+				LINUX MODULE INIT
+ ****************************************************************************/
+static void cx25821_audio_fini(void)
+{
+	snd_card_free(snd_cx25821_cards[0]);
+}
+
+/*
+ * Module initializer
+ *
+ * Loops through present saa7134 cards, and assigns an ALSA device
+ * to each one
+ *
+ */
+static int cx25821_alsa_init(void)
+{
+	struct cx25821_dev *dev = NULL;
+	struct list_head *list;
+
+	mutex_lock(&cx25821_devlist_mutex);
+	list_for_each(list, &cx25821_devlist) {
+		dev = list_entry(list, struct cx25821_dev, devlist);
+		cx25821_audio_initdev(dev);
+	}
+	mutex_unlock(&cx25821_devlist_mutex);
+
+	if (dev == NULL)
+		pr_info("ERROR ALSA: no cx25821 cards found\n");
+
+	return 0;
+
+}
+
+late_initcall(cx25821_alsa_init);
+module_exit(cx25821_audio_fini);
+
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-audio.h linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-audio.h
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-audio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-audio.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,61 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 __CX25821_AUDIO_H__
+#define __CX25821_AUDIO_H__
+
+#define USE_RISC_NOOP               1
+#define LINES_PER_BUFFER            15
+#define AUDIO_LINE_SIZE             128
+
+/* Number of buffer programs to use at once. */
+#define NUMBER_OF_PROGRAMS  8
+
+/*
+ * Max size of the RISC program for a buffer. - worst case is 2 writes per line
+ * Space is also added for the 4 no-op instructions added on the end.
+ */
+#ifndef USE_RISC_NOOP
+#define MAX_BUFFER_PROGRAM_SIZE     \
+	(2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \
+	RISC_WRITECR_INSTRUCTION_SIZE * 4)
+#endif
+
+/* MAE 12 July 2005 Try to use NOOP RISC instruction instead */
+#ifdef USE_RISC_NOOP
+#define MAX_BUFFER_PROGRAM_SIZE     \
+	(2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \
+	RISC_NOOP_INSTRUCTION_SIZE * 4)
+#endif
+
+/* Sizes of various instructions in bytes.  Used when adding instructions. */
+#define RISC_WRITE_INSTRUCTION_SIZE 12
+#define RISC_JUMP_INSTRUCTION_SIZE  12
+#define RISC_SKIP_INSTRUCTION_SIZE  4
+#define RISC_SYNC_INSTRUCTION_SIZE  4
+#define RISC_WRITECR_INSTRUCTION_SIZE  16
+#define RISC_NOOP_INSTRUCTION_SIZE 4
+
+#define MAX_AUDIO_DMA_BUFFER_SIZE	\
+(MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + RISC_SYNC_INSTRUCTION_SIZE)
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-audio-upstream.c linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-audio-upstream.c
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-audio-upstream.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-audio-upstream.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,788 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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 "cx25821-video.h"
+#include "cx25821-audio-upstream.h"
+
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static int _intr_msk = FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF |
+			FLD_AUD_SRC_SYNC | FLD_AUD_SRC_OPC_ERR;
+
+int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev,
+					      struct sram_channel *ch,
+					      unsigned int bpl, u32 risc)
+{
+	unsigned int i, lines;
+	u32 cdt;
+
+	if (ch->cmds_start == 0) {
+		cx_write(ch->ptr1_reg, 0);
+		cx_write(ch->ptr2_reg, 0);
+		cx_write(ch->cnt2_reg, 0);
+		cx_write(ch->cnt1_reg, 0);
+		return 0;
+	}
+
+	bpl = (bpl + 7) & ~7;	/* alignment */
+	cdt = ch->cdt;
+	lines = ch->fifo_size / bpl;
+
+	if (lines > 3)
+		lines = 3;
+
+	BUG_ON(lines < 2);
+
+	/* write CDT */
+	for (i = 0; i < lines; i++) {
+		cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+		cx_write(cdt + 16 * i + 4, 0);
+		cx_write(cdt + 16 * i + 8, 0);
+		cx_write(cdt + 16 * i + 12, 0);
+	}
+
+	/* write CMDS */
+	cx_write(ch->cmds_start + 0, risc);
+
+	cx_write(ch->cmds_start + 4, 0);
+	cx_write(ch->cmds_start + 8, cdt);
+	cx_write(ch->cmds_start + 12, AUDIO_CDT_SIZE_QW);
+	cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+	/* IQ size */
+	cx_write(ch->cmds_start + 20, AUDIO_IQ_SIZE_DW);
+
+	for (i = 24; i < 80; i += 4)
+		cx_write(ch->cmds_start + i, 0);
+
+	/* fill registers */
+	cx_write(ch->ptr1_reg, ch->fifo_start);
+	cx_write(ch->ptr2_reg, cdt);
+	cx_write(ch->cnt2_reg, AUDIO_CDT_SIZE_QW);
+	cx_write(ch->cnt1_reg, AUDIO_CLUSTER_SIZE_QW - 1);
+
+	return 0;
+}
+
+static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev,
+						 __le32 *rp,
+						 dma_addr_t databuf_phys_addr,
+						 unsigned int bpl,
+						 int fifo_enable)
+{
+	unsigned int line;
+	struct sram_channel *sram_ch =
+	   dev->channels[dev->_audio_upstream_channel].sram_channels;
+	int offset = 0;
+
+	/* scan lines */
+	for (line = 0; line < LINES_PER_AUDIO_BUFFER; line++) {
+		*(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+		*(rp++) = cpu_to_le32(databuf_phys_addr + offset);
+		*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+
+		/* Check if we need to enable the FIFO
+		 * after the first 3 lines.
+		 * For the upstream audio channel,
+		 * the risc engine will enable the FIFO */
+		if (fifo_enable && line == 2) {
+			*(rp++) = RISC_WRITECR;
+			*(rp++) = sram_ch->dma_ctl;
+			*(rp++) = sram_ch->fld_aud_fifo_en;
+			*(rp++) = 0x00000020;
+		}
+
+		offset += AUDIO_LINE_SIZE;
+	}
+
+	return rp;
+}
+
+int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev,
+				       struct pci_dev *pci,
+				       unsigned int bpl, unsigned int lines)
+{
+	__le32 *rp;
+	int fifo_enable = 0;
+	int frame = 0, i = 0;
+	int frame_size = AUDIO_DATA_BUF_SZ;
+	int databuf_offset = 0;
+	int risc_flag = RISC_CNT_INC;
+	dma_addr_t risc_phys_jump_addr;
+
+	/* Virtual address of Risc buffer program */
+	rp = dev->_risc_virt_addr;
+
+	/* sync instruction */
+	*(rp++) = cpu_to_le32(RISC_RESYNC | AUDIO_SYNC_LINE);
+
+	for (frame = 0; frame < NUM_AUDIO_FRAMES; frame++) {
+		databuf_offset = frame_size * frame;
+
+		if (frame == 0) {
+			fifo_enable = 1;
+			risc_flag = RISC_CNT_RESET;
+		} else {
+			fifo_enable = 0;
+			risc_flag = RISC_CNT_INC;
+		}
+
+		/* Calculate physical jump address */
+		if ((frame + 1) == NUM_AUDIO_FRAMES) {
+			risc_phys_jump_addr =
+			    dev->_risc_phys_start_addr +
+			    RISC_SYNC_INSTRUCTION_SIZE;
+		} else {
+			risc_phys_jump_addr =
+			    dev->_risc_phys_start_addr +
+			    RISC_SYNC_INSTRUCTION_SIZE +
+			    AUDIO_RISC_DMA_BUF_SIZE * (frame + 1);
+		}
+
+		rp = cx25821_risc_field_upstream_audio(dev, rp,
+						       dev->
+						       _audiodata_buf_phys_addr
+						       + databuf_offset, bpl,
+						       fifo_enable);
+
+		if (USE_RISC_NOOP_AUDIO) {
+			for (i = 0; i < NUM_NO_OPS; i++)
+				*(rp++) = cpu_to_le32(RISC_NOOP);
+		}
+
+		/* Loop to (Nth)FrameRISC or to Start of Risc program &
+		 * generate IRQ */
+		*(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
+		*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+		*(rp++) = cpu_to_le32(0);
+
+		/* Recalculate virtual address based on frame index */
+		rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE / 4 +
+		    (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4);
+	}
+
+	return 0;
+}
+
+void cx25821_free_memory_audio(struct cx25821_dev *dev)
+{
+	if (dev->_risc_virt_addr) {
+		pci_free_consistent(dev->pci, dev->_audiorisc_size,
+				    dev->_risc_virt_addr, dev->_risc_phys_addr);
+		dev->_risc_virt_addr = NULL;
+	}
+
+	if (dev->_audiodata_buf_virt_addr) {
+		pci_free_consistent(dev->pci, dev->_audiodata_buf_size,
+				    dev->_audiodata_buf_virt_addr,
+				    dev->_audiodata_buf_phys_addr);
+		dev->_audiodata_buf_virt_addr = NULL;
+	}
+}
+
+void cx25821_stop_upstream_audio(struct cx25821_dev *dev)
+{
+	struct sram_channel *sram_ch =
+	   dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels;
+	u32 tmp = 0;
+
+	if (!dev->_audio_is_running) {
+		printk(KERN_DEBUG
+		       pr_fmt("No audio file is currently running so return!\n"));
+		return;
+	}
+	/* Disable RISC interrupts */
+	cx_write(sram_ch->int_msk, 0);
+
+	/* Turn OFF risc and fifo enable in AUD_DMA_CNTRL */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_write(sram_ch->dma_ctl,
+		 tmp & ~(sram_ch->fld_aud_fifo_en | sram_ch->fld_aud_risc_en));
+
+	/* Clear data buffer memory */
+	if (dev->_audiodata_buf_virt_addr)
+		memset(dev->_audiodata_buf_virt_addr, 0,
+		       dev->_audiodata_buf_size);
+
+	dev->_audio_is_running = 0;
+	dev->_is_first_audio_frame = 0;
+	dev->_audioframe_count = 0;
+	dev->_audiofile_status = END_OF_FILE;
+
+	kfree(dev->_irq_audio_queues);
+	dev->_irq_audio_queues = NULL;
+
+	kfree(dev->_audiofilename);
+}
+
+void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev)
+{
+	if (dev->_audio_is_running)
+		cx25821_stop_upstream_audio(dev);
+
+	cx25821_free_memory_audio(dev);
+}
+
+int cx25821_get_audio_data(struct cx25821_dev *dev,
+			   struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int frame_index_temp = dev->_audioframe_index;
+	int i = 0;
+	int line_size = AUDIO_LINE_SIZE;
+	int frame_size = AUDIO_DATA_BUF_SZ;
+	int frame_offset = frame_size * frame_index_temp;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t file_offset = dev->_audioframe_count * frame_size;
+	loff_t pos;
+	mm_segment_t old_fs;
+
+	if (dev->_audiofile_status == END_OF_FILE)
+		return 0;
+
+	myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
+
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_audiofilename, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (i = 0; i < dev->_audio_lines_count; i++) {
+			pos = file_offset;
+
+			vfs_read_retval =
+			    vfs_read(myfile, mybuf, line_size, &pos);
+
+			if (vfs_read_retval > 0 && vfs_read_retval == line_size
+			    && dev->_audiodata_buf_virt_addr != NULL) {
+				memcpy((void *)(dev->_audiodata_buf_virt_addr +
+						frame_offset / 4), mybuf,
+				       vfs_read_retval);
+			}
+
+			file_offset += vfs_read_retval;
+			frame_offset += vfs_read_retval;
+
+			if (vfs_read_retval < line_size) {
+				pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
+					__func__);
+				break;
+			}
+		}
+
+		if (i > 0)
+			dev->_audioframe_count++;
+
+		dev->_audiofile_status =
+		    (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+static void cx25821_audioups_handler(struct work_struct *work)
+{
+	struct cx25821_dev *dev =
+	    container_of(work, struct cx25821_dev, _audio_work_entry);
+
+	if (!dev) {
+		pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
+		       __func__);
+		return;
+	}
+
+	cx25821_get_audio_data(dev, dev->channels[dev->_audio_upstream_channel].
+			sram_channels);
+}
+
+int cx25821_openfile_audio(struct cx25821_dev *dev,
+			   struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int i = 0, j = 0;
+	int line_size = AUDIO_LINE_SIZE;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t pos;
+	loff_t offset = (unsigned long)0;
+	mm_segment_t old_fs;
+
+	myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
+
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_audiofilename, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (j = 0; j < NUM_AUDIO_FRAMES; j++) {
+			for (i = 0; i < dev->_audio_lines_count; i++) {
+				pos = offset;
+
+				vfs_read_retval =
+				    vfs_read(myfile, mybuf, line_size, &pos);
+
+				if (vfs_read_retval > 0
+				    && vfs_read_retval == line_size
+				    && dev->_audiodata_buf_virt_addr != NULL) {
+					memcpy((void *)(dev->
+							_audiodata_buf_virt_addr
+							+ offset / 4), mybuf,
+					       vfs_read_retval);
+				}
+
+				offset += vfs_read_retval;
+
+				if (vfs_read_retval < line_size) {
+					pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
+						__func__);
+					break;
+				}
+			}
+
+			if (i > 0)
+				dev->_audioframe_count++;
+
+			if (vfs_read_retval < line_size)
+				break;
+		}
+
+		dev->_audiofile_status =
+		    (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		myfile->f_pos = 0;
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev,
+						 struct sram_channel *sram_ch,
+						 int bpl)
+{
+	int ret = 0;
+	dma_addr_t dma_addr;
+	dma_addr_t data_dma_addr;
+
+	cx25821_free_memory_audio(dev);
+
+	dev->_risc_virt_addr =
+	    pci_alloc_consistent(dev->pci, dev->audio_upstream_riscbuf_size,
+				 &dma_addr);
+	dev->_risc_virt_start_addr = dev->_risc_virt_addr;
+	dev->_risc_phys_start_addr = dma_addr;
+	dev->_risc_phys_addr = dma_addr;
+	dev->_audiorisc_size = dev->audio_upstream_riscbuf_size;
+
+	if (!dev->_risc_virt_addr) {
+		printk(KERN_DEBUG
+		       pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning\n"));
+		return -ENOMEM;
+	}
+	/* Clear out memory at address */
+	memset(dev->_risc_virt_addr, 0, dev->_audiorisc_size);
+
+	/* For Audio Data buffer allocation */
+	dev->_audiodata_buf_virt_addr =
+	    pci_alloc_consistent(dev->pci, dev->audio_upstream_databuf_size,
+				 &data_dma_addr);
+	dev->_audiodata_buf_phys_addr = data_dma_addr;
+	dev->_audiodata_buf_size = dev->audio_upstream_databuf_size;
+
+	if (!dev->_audiodata_buf_virt_addr) {
+		printk(KERN_DEBUG
+		       pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning\n"));
+		return -ENOMEM;
+	}
+	/* Clear out memory at address */
+	memset(dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size);
+
+	ret = cx25821_openfile_audio(dev, sram_ch);
+	if (ret < 0)
+		return ret;
+
+	/* Creating RISC programs */
+	ret =
+	    cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl,
+					       dev->_audio_lines_count);
+	if (ret < 0) {
+		printk(KERN_DEBUG
+		       pr_fmt("ERROR creating audio upstream RISC programs!\n"));
+		goto error;
+	}
+
+	return 0;
+
+error:
+	return ret;
+}
+
+int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num,
+			       u32 status)
+{
+	int i = 0;
+	u32 int_msk_tmp;
+	struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+	dma_addr_t risc_phys_jump_addr;
+	__le32 *rp;
+
+	if (status & FLD_AUD_SRC_RISCI1) {
+		/* Get interrupt_index of the program that interrupted */
+		u32 prog_cnt = cx_read(channel->gpcnt);
+
+		/* Since we've identified our IRQ, clear our bits from the
+		 * interrupt mask and interrupt status registers */
+		cx_write(channel->int_msk, 0);
+		cx_write(channel->int_stat, cx_read(channel->int_stat));
+
+		spin_lock(&dev->slock);
+
+		while (prog_cnt != dev->_last_index_irq) {
+			/* Update _last_index_irq */
+			if (dev->_last_index_irq < (NUMBER_OF_PROGRAMS - 1))
+				dev->_last_index_irq++;
+			else
+				dev->_last_index_irq = 0;
+
+			dev->_audioframe_index = dev->_last_index_irq;
+
+			queue_work(dev->_irq_audio_queues,
+				   &dev->_audio_work_entry);
+		}
+
+		if (dev->_is_first_audio_frame) {
+			dev->_is_first_audio_frame = 0;
+
+			if (dev->_risc_virt_start_addr != NULL) {
+				risc_phys_jump_addr =
+				    dev->_risc_phys_start_addr +
+				    RISC_SYNC_INSTRUCTION_SIZE +
+				    AUDIO_RISC_DMA_BUF_SIZE;
+
+				rp = cx25821_risc_field_upstream_audio(dev,
+						dev->_risc_virt_start_addr + 1,
+						dev->_audiodata_buf_phys_addr,
+						AUDIO_LINE_SIZE, FIFO_DISABLE);
+
+				if (USE_RISC_NOOP_AUDIO) {
+					for (i = 0; i < NUM_NO_OPS; i++) {
+						*(rp++) =
+						    cpu_to_le32(RISC_NOOP);
+					}
+				}
+				/* Jump to 2nd Audio Frame */
+				*(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 |
+						RISC_CNT_RESET);
+				*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+				*(rp++) = cpu_to_le32(0);
+			}
+		}
+
+		spin_unlock(&dev->slock);
+	} else {
+		if (status & FLD_AUD_SRC_OF)
+			pr_warn("%s(): Audio Received Overflow Error Interrupt!\n",
+				__func__);
+
+		if (status & FLD_AUD_SRC_SYNC)
+			pr_warn("%s(): Audio Received Sync Error Interrupt!\n",
+				__func__);
+
+		if (status & FLD_AUD_SRC_OPC_ERR)
+			pr_warn("%s(): Audio Received OpCode Error Interrupt!\n",
+				__func__);
+
+		/* Read and write back the interrupt status register to clear
+		 * our bits */
+		cx_write(channel->int_stat, cx_read(channel->int_stat));
+	}
+
+	if (dev->_audiofile_status == END_OF_FILE) {
+		pr_warn("EOF Channel Audio Framecount = %d\n",
+			dev->_audioframe_count);
+		return -1;
+	}
+	/* ElSE, set the interrupt mask register, re-enable irq. */
+	int_msk_tmp = cx_read(channel->int_msk);
+	cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
+
+	return 0;
+}
+
+static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id)
+{
+	struct cx25821_dev *dev = dev_id;
+	u32 msk_stat, audio_status;
+	int handled = 0;
+	struct sram_channel *sram_ch;
+
+	if (!dev)
+		return -1;
+
+	sram_ch = dev->channels[dev->_audio_upstream_channel].sram_channels;
+
+	msk_stat = cx_read(sram_ch->int_mstat);
+	audio_status = cx_read(sram_ch->int_stat);
+
+	/* Only deal with our interrupt */
+	if (audio_status) {
+		handled = cx25821_audio_upstream_irq(dev,
+				dev->_audio_upstream_channel, audio_status);
+	}
+
+	if (handled < 0)
+		cx25821_stop_upstream_audio(dev);
+	else
+		handled += handled;
+
+	return IRQ_RETVAL(handled);
+}
+
+static void cx25821_wait_fifo_enable(struct cx25821_dev *dev,
+				     struct sram_channel *sram_ch)
+{
+	int count = 0;
+	u32 tmp;
+
+	do {
+		/* Wait 10 microsecond before checking to see if the FIFO is
+		 * turned ON. */
+		udelay(10);
+
+		tmp = cx_read(sram_ch->dma_ctl);
+
+		/* 10 millisecond timeout */
+		if (count++ > 1000) {
+			pr_err("ERROR: %s() fifo is NOT turned on. Timeout!\n",
+			       __func__);
+			return;
+		}
+
+	} while (!(tmp & sram_ch->fld_aud_fifo_en));
+
+}
+
+int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev,
+				     struct sram_channel *sram_ch)
+{
+	u32 tmp = 0;
+	int err = 0;
+
+	/* Set the physical start address of the RISC program in the initial
+	 * program counter(IPC) member of the CMDS. */
+	cx_write(sram_ch->cmds_start + 0, dev->_risc_phys_addr);
+	/* Risc IPC High 64 bits 63-32 */
+	cx_write(sram_ch->cmds_start + 4, 0);
+
+	/* reset counter */
+	cx_write(sram_ch->gpcnt_ctl, 3);
+
+	/* Set the line length       (It looks like we do not need to set the
+	 * line length) */
+	cx_write(sram_ch->aud_length, AUDIO_LINE_SIZE & FLD_AUD_DST_LN_LNGTH);
+
+	/* Set the input mode to 16-bit */
+	tmp = cx_read(sram_ch->aud_cfg);
+	tmp |=
+	    FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE |
+	    FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | FLD_AUD_SONY_MODE;
+	cx_write(sram_ch->aud_cfg, tmp);
+
+	/* Read and write back the interrupt status register to clear it */
+	tmp = cx_read(sram_ch->int_stat);
+	cx_write(sram_ch->int_stat, tmp);
+
+	/* Clear our bits from the interrupt status register. */
+	cx_write(sram_ch->int_stat, _intr_msk);
+
+	/* Set the interrupt mask register, enable irq. */
+	cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
+	tmp = cx_read(sram_ch->int_msk);
+	cx_write(sram_ch->int_msk, tmp |= _intr_msk);
+
+	err =
+	    request_irq(dev->pci->irq, cx25821_upstream_irq_audio,
+			IRQF_SHARED, dev->name, dev);
+	if (err < 0) {
+		pr_err("%s: can't get upstream IRQ %d\n",
+		       dev->name, dev->pci->irq);
+		goto fail_irq;
+	}
+
+	/* Start the DMA  engine */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_set(sram_ch->dma_ctl, tmp | sram_ch->fld_aud_risc_en);
+
+	dev->_audio_is_running = 1;
+	dev->_is_first_audio_frame = 1;
+
+	/* The fifo_en bit turns on by the first Risc program */
+	cx25821_wait_fifo_enable(dev, sram_ch);
+
+	return 0;
+
+fail_irq:
+	cx25821_dev_unregister(dev);
+	return err;
+}
+
+int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
+{
+	struct sram_channel *sram_ch;
+	int retval = 0;
+	int err = 0;
+	int str_length = 0;
+
+	if (dev->_audio_is_running) {
+		pr_warn("Audio Channel is still running so return!\n");
+		return 0;
+	}
+
+	dev->_audio_upstream_channel = channel_select;
+	sram_ch = dev->channels[channel_select].sram_channels;
+
+	/* Work queue */
+	INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler);
+	dev->_irq_audio_queues =
+	    create_singlethread_workqueue("cx25821_audioworkqueue");
+
+	if (!dev->_irq_audio_queues) {
+		printk(KERN_DEBUG
+		       pr_fmt("ERROR: create_singlethread_workqueue() for Audio FAILED!\n"));
+		return -ENOMEM;
+	}
+
+	dev->_last_index_irq = 0;
+	dev->_audio_is_running = 0;
+	dev->_audioframe_count = 0;
+	dev->_audiofile_status = RESET_STATUS;
+	dev->_audio_lines_count = LINES_PER_AUDIO_BUFFER;
+	_line_size = AUDIO_LINE_SIZE;
+
+	if (dev->input_audiofilename) {
+		str_length = strlen(dev->input_audiofilename);
+		dev->_audiofilename = kmalloc(str_length + 1, GFP_KERNEL);
+
+		if (!dev->_audiofilename)
+			goto error;
+
+		memcpy(dev->_audiofilename, dev->input_audiofilename,
+		       str_length + 1);
+
+		/* Default if filename is empty string */
+		if (strcmp(dev->input_audiofilename, "") == 0)
+			dev->_audiofilename = "/root/audioGOOD.wav";
+	} else {
+		str_length = strlen(_defaultAudioName);
+		dev->_audiofilename = kmalloc(str_length + 1, GFP_KERNEL);
+
+		if (!dev->_audiofilename)
+			goto error;
+
+		memcpy(dev->_audiofilename, _defaultAudioName, str_length + 1);
+	}
+
+	retval = cx25821_sram_channel_setup_upstream_audio(dev, sram_ch,
+							_line_size, 0);
+
+	dev->audio_upstream_riscbuf_size =
+	    AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS +
+	    RISC_SYNC_INSTRUCTION_SIZE;
+	dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS;
+
+	/* Allocating buffers and prepare RISC program */
+	retval = cx25821_audio_upstream_buffer_prepare(dev, sram_ch,
+							_line_size);
+	if (retval < 0) {
+		pr_err("%s: Failed to set up Audio upstream buffers!\n",
+		       dev->name);
+		goto error;
+	}
+	/* Start RISC engine */
+	cx25821_start_audio_dma_upstream(dev, sram_ch);
+
+	return 0;
+
+error:
+	cx25821_dev_unregister(dev);
+
+	return err;
+}
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-audio-upstream.h linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-audio-upstream.h
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-audio-upstream.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-audio-upstream.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,62 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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/mutex.h>
+#include <linux/workqueue.h>
+
+#define NUM_AUDIO_PROGS       8
+#define NUM_AUDIO_FRAMES      8
+#define END_OF_FILE           0
+#define IN_PROGRESS           1
+#define RESET_STATUS          -1
+#define FIFO_DISABLE          0
+#define FIFO_ENABLE           1
+#define NUM_NO_OPS            4
+
+#define RISC_READ_INSTRUCTION_SIZE      12
+#define RISC_JUMP_INSTRUCTION_SIZE      12
+#define RISC_WRITECR_INSTRUCTION_SIZE   16
+#define RISC_SYNC_INSTRUCTION_SIZE      4
+#define DWORD_SIZE                      4
+#define AUDIO_SYNC_LINE                 4
+
+#define LINES_PER_AUDIO_BUFFER      15
+#define AUDIO_LINE_SIZE             128
+#define AUDIO_DATA_BUF_SZ           (AUDIO_LINE_SIZE * LINES_PER_AUDIO_BUFFER)
+
+#define USE_RISC_NOOP_AUDIO   1
+
+#ifdef USE_RISC_NOOP_AUDIO
+#define AUDIO_RISC_DMA_BUF_SIZE						\
+	(LINES_PER_AUDIO_BUFFER * RISC_READ_INSTRUCTION_SIZE +		\
+	 RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS * DWORD_SIZE +	\
+	 RISC_JUMP_INSTRUCTION_SIZE)
+#endif
+
+#ifndef USE_RISC_NOOP_AUDIO
+#define AUDIO_RISC_DMA_BUF_SIZE						\
+	(LINES_PER_AUDIO_BUFFER * RISC_READ_INSTRUCTION_SIZE +		\
+	 RISC_WRITECR_INSTRUCTION_SIZE + RISC_JUMP_INSTRUCTION_SIZE)
+#endif
+
+static int _line_size;
+char *_defaultAudioName = "/root/audioGOOD.wav";
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-biffuncs.h linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-biffuncs.h
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-biffuncs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-biffuncs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,45 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 _BITFUNCS_H
+#define _BITFUNCS_H
+
+#define SetBit(Bit)  (1 << Bit)
+
+inline u8 getBit(u32 sample, u8 index)
+{
+	return (u8) ((sample >> index) & 1);
+}
+
+inline u32 clearBitAtPos(u32 value, u8 bit)
+{
+	return value & ~(1 << bit);
+}
+
+inline u32 setBitAtPos(u32 sample, u8 bit)
+{
+	sample |= (1 << bit);
+	return sample;
+
+}
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-cards.c linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-cards.c
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-cards.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-cards.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,72 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *	Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <media/cx25840.h>
+
+#include "cx25821.h"
+#include "tuner-xc2028.h"
+
+/* board config info */
+
+struct cx25821_board cx25821_boards[] = {
+	[UNKNOWN_BOARD] = {
+		.name = "UNKNOWN/GENERIC",
+		/* Ensure safe default for unknown boards */
+		.clk_freq = 0,
+	},
+
+	[CX25821_BOARD] = {
+		.name = "CX25821",
+		.portb = CX25821_RAW,
+		.portc = CX25821_264,
+		.input[0].type = CX25821_VMUX_COMPOSITE,
+	},
+
+};
+
+const unsigned int cx25821_bcount = ARRAY_SIZE(cx25821_boards);
+
+struct cx25821_subid cx25821_subids[] = {
+	{
+		.subvendor = 0x14f1,
+		.subdevice = 0x0920,
+		.card = CX25821_BOARD,
+	},
+};
+
+void cx25821_card_setup(struct cx25821_dev *dev)
+{
+	static u8 eeprom[256];
+
+	if (dev->i2c_bus[0].i2c_rc == 0) {
+		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
+		tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
+			      sizeof(eeprom));
+	}
+}
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-core.c linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-core.c
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1517 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include "cx25821.h"
+#include "cx25821-sram.h"
+#include "cx25821-video.h"
+
+MODULE_DESCRIPTION("Driver for Athena cards");
+MODULE_AUTHOR("Shu Lin - Hiep Huynh");
+MODULE_LICENSE("GPL");
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+static unsigned int card[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+module_param_array(card, int, NULL, 0444);
+MODULE_PARM_DESC(card, "card type");
+
+static unsigned int cx25821_devcount;
+
+DEFINE_MUTEX(cx25821_devlist_mutex);
+EXPORT_SYMBOL(cx25821_devlist_mutex);
+LIST_HEAD(cx25821_devlist);
+EXPORT_SYMBOL(cx25821_devlist);
+
+struct sram_channel cx25821_sram_channels[] = {
+	[SRAM_CH00] = {
+		.i = SRAM_CH00,
+		.name = "VID A",
+		.cmds_start = VID_A_DOWN_CMDS,
+		.ctrl_start = VID_A_IQ,
+		.cdt = VID_A_CDT,
+		.fifo_start = VID_A_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA1_PTR1,
+		.ptr2_reg = DMA1_PTR2,
+		.cnt1_reg = DMA1_CNT1,
+		.cnt2_reg = DMA1_CNT2,
+		.int_msk = VID_A_INT_MSK,
+		.int_stat = VID_A_INT_STAT,
+		.int_mstat = VID_A_INT_MSTAT,
+		.dma_ctl = VID_DST_A_DMA_CTL,
+		.gpcnt_ctl = VID_DST_A_GPCNT_CTL,
+		.gpcnt = VID_DST_A_GPCNT,
+		.vip_ctl = VID_DST_A_VIP_CTL,
+		.pix_frmt = VID_DST_A_PIX_FRMT,
+	},
+
+	[SRAM_CH01] = {
+		.i = SRAM_CH01,
+		.name = "VID B",
+		.cmds_start = VID_B_DOWN_CMDS,
+		.ctrl_start = VID_B_IQ,
+		.cdt = VID_B_CDT,
+		.fifo_start = VID_B_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA2_PTR1,
+		.ptr2_reg = DMA2_PTR2,
+		.cnt1_reg = DMA2_CNT1,
+		.cnt2_reg = DMA2_CNT2,
+		.int_msk = VID_B_INT_MSK,
+		.int_stat = VID_B_INT_STAT,
+		.int_mstat = VID_B_INT_MSTAT,
+		.dma_ctl = VID_DST_B_DMA_CTL,
+		.gpcnt_ctl = VID_DST_B_GPCNT_CTL,
+		.gpcnt = VID_DST_B_GPCNT,
+		.vip_ctl = VID_DST_B_VIP_CTL,
+		.pix_frmt = VID_DST_B_PIX_FRMT,
+	},
+
+	[SRAM_CH02] = {
+		.i = SRAM_CH02,
+		.name = "VID C",
+		.cmds_start = VID_C_DOWN_CMDS,
+		.ctrl_start = VID_C_IQ,
+		.cdt = VID_C_CDT,
+		.fifo_start = VID_C_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA3_PTR1,
+		.ptr2_reg = DMA3_PTR2,
+		.cnt1_reg = DMA3_CNT1,
+		.cnt2_reg = DMA3_CNT2,
+		.int_msk = VID_C_INT_MSK,
+		.int_stat = VID_C_INT_STAT,
+		.int_mstat = VID_C_INT_MSTAT,
+		.dma_ctl = VID_DST_C_DMA_CTL,
+		.gpcnt_ctl = VID_DST_C_GPCNT_CTL,
+		.gpcnt = VID_DST_C_GPCNT,
+		.vip_ctl = VID_DST_C_VIP_CTL,
+		.pix_frmt = VID_DST_C_PIX_FRMT,
+	},
+
+	[SRAM_CH03] = {
+		.i = SRAM_CH03,
+		.name = "VID D",
+		.cmds_start = VID_D_DOWN_CMDS,
+		.ctrl_start = VID_D_IQ,
+		.cdt = VID_D_CDT,
+		.fifo_start = VID_D_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA4_PTR1,
+		.ptr2_reg = DMA4_PTR2,
+		.cnt1_reg = DMA4_CNT1,
+		.cnt2_reg = DMA4_CNT2,
+		.int_msk = VID_D_INT_MSK,
+		.int_stat = VID_D_INT_STAT,
+		.int_mstat = VID_D_INT_MSTAT,
+		.dma_ctl = VID_DST_D_DMA_CTL,
+		.gpcnt_ctl = VID_DST_D_GPCNT_CTL,
+		.gpcnt = VID_DST_D_GPCNT,
+		.vip_ctl = VID_DST_D_VIP_CTL,
+		.pix_frmt = VID_DST_D_PIX_FRMT,
+	},
+
+	[SRAM_CH04] = {
+		.i = SRAM_CH04,
+		.name = "VID E",
+		.cmds_start = VID_E_DOWN_CMDS,
+		.ctrl_start = VID_E_IQ,
+		.cdt = VID_E_CDT,
+		.fifo_start = VID_E_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA5_PTR1,
+		.ptr2_reg = DMA5_PTR2,
+		.cnt1_reg = DMA5_CNT1,
+		.cnt2_reg = DMA5_CNT2,
+		.int_msk = VID_E_INT_MSK,
+		.int_stat = VID_E_INT_STAT,
+		.int_mstat = VID_E_INT_MSTAT,
+		.dma_ctl = VID_DST_E_DMA_CTL,
+		.gpcnt_ctl = VID_DST_E_GPCNT_CTL,
+		.gpcnt = VID_DST_E_GPCNT,
+		.vip_ctl = VID_DST_E_VIP_CTL,
+		.pix_frmt = VID_DST_E_PIX_FRMT,
+	},
+
+	[SRAM_CH05] = {
+		.i = SRAM_CH05,
+		.name = "VID F",
+		.cmds_start = VID_F_DOWN_CMDS,
+		.ctrl_start = VID_F_IQ,
+		.cdt = VID_F_CDT,
+		.fifo_start = VID_F_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA6_PTR1,
+		.ptr2_reg = DMA6_PTR2,
+		.cnt1_reg = DMA6_CNT1,
+		.cnt2_reg = DMA6_CNT2,
+		.int_msk = VID_F_INT_MSK,
+		.int_stat = VID_F_INT_STAT,
+		.int_mstat = VID_F_INT_MSTAT,
+		.dma_ctl = VID_DST_F_DMA_CTL,
+		.gpcnt_ctl = VID_DST_F_GPCNT_CTL,
+		.gpcnt = VID_DST_F_GPCNT,
+		.vip_ctl = VID_DST_F_VIP_CTL,
+		.pix_frmt = VID_DST_F_PIX_FRMT,
+	},
+
+	[SRAM_CH06] = {
+		.i = SRAM_CH06,
+		.name = "VID G",
+		.cmds_start = VID_G_DOWN_CMDS,
+		.ctrl_start = VID_G_IQ,
+		.cdt = VID_G_CDT,
+		.fifo_start = VID_G_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA7_PTR1,
+		.ptr2_reg = DMA7_PTR2,
+		.cnt1_reg = DMA7_CNT1,
+		.cnt2_reg = DMA7_CNT2,
+		.int_msk = VID_G_INT_MSK,
+		.int_stat = VID_G_INT_STAT,
+		.int_mstat = VID_G_INT_MSTAT,
+		.dma_ctl = VID_DST_G_DMA_CTL,
+		.gpcnt_ctl = VID_DST_G_GPCNT_CTL,
+		.gpcnt = VID_DST_G_GPCNT,
+		.vip_ctl = VID_DST_G_VIP_CTL,
+		.pix_frmt = VID_DST_G_PIX_FRMT,
+	},
+
+	[SRAM_CH07] = {
+		.i = SRAM_CH07,
+		.name = "VID H",
+		.cmds_start = VID_H_DOWN_CMDS,
+		.ctrl_start = VID_H_IQ,
+		.cdt = VID_H_CDT,
+		.fifo_start = VID_H_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA8_PTR1,
+		.ptr2_reg = DMA8_PTR2,
+		.cnt1_reg = DMA8_CNT1,
+		.cnt2_reg = DMA8_CNT2,
+		.int_msk = VID_H_INT_MSK,
+		.int_stat = VID_H_INT_STAT,
+		.int_mstat = VID_H_INT_MSTAT,
+		.dma_ctl = VID_DST_H_DMA_CTL,
+		.gpcnt_ctl = VID_DST_H_GPCNT_CTL,
+		.gpcnt = VID_DST_H_GPCNT,
+		.vip_ctl = VID_DST_H_VIP_CTL,
+		.pix_frmt = VID_DST_H_PIX_FRMT,
+	},
+
+	[SRAM_CH08] = {
+		.name = "audio from",
+		.cmds_start = AUD_A_DOWN_CMDS,
+		.ctrl_start = AUD_A_IQ,
+		.cdt = AUD_A_CDT,
+		.fifo_start = AUD_A_DOWN_CLUSTER_1,
+		.fifo_size = AUDIO_CLUSTER_SIZE * 3,
+		.ptr1_reg = DMA17_PTR1,
+		.ptr2_reg = DMA17_PTR2,
+		.cnt1_reg = DMA17_CNT1,
+		.cnt2_reg = DMA17_CNT2,
+	},
+
+	[SRAM_CH09] = {
+		.i = SRAM_CH09,
+		.name = "VID Upstream I",
+		.cmds_start = VID_I_UP_CMDS,
+		.ctrl_start = VID_I_IQ,
+		.cdt = VID_I_CDT,
+		.fifo_start = VID_I_UP_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA15_PTR1,
+		.ptr2_reg = DMA15_PTR2,
+		.cnt1_reg = DMA15_CNT1,
+		.cnt2_reg = DMA15_CNT2,
+		.int_msk = VID_I_INT_MSK,
+		.int_stat = VID_I_INT_STAT,
+		.int_mstat = VID_I_INT_MSTAT,
+		.dma_ctl = VID_SRC_I_DMA_CTL,
+		.gpcnt_ctl = VID_SRC_I_GPCNT_CTL,
+		.gpcnt = VID_SRC_I_GPCNT,
+
+		.vid_fmt_ctl = VID_SRC_I_FMT_CTL,
+		.vid_active_ctl1 = VID_SRC_I_ACTIVE_CTL1,
+		.vid_active_ctl2 = VID_SRC_I_ACTIVE_CTL2,
+		.vid_cdt_size = VID_SRC_I_CDT_SZ,
+		.irq_bit = 8,
+	},
+
+	[SRAM_CH10] = {
+		.i = SRAM_CH10,
+		.name = "VID Upstream J",
+		.cmds_start = VID_J_UP_CMDS,
+		.ctrl_start = VID_J_IQ,
+		.cdt = VID_J_CDT,
+		.fifo_start = VID_J_UP_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA16_PTR1,
+		.ptr2_reg = DMA16_PTR2,
+		.cnt1_reg = DMA16_CNT1,
+		.cnt2_reg = DMA16_CNT2,
+		.int_msk = VID_J_INT_MSK,
+		.int_stat = VID_J_INT_STAT,
+		.int_mstat = VID_J_INT_MSTAT,
+		.dma_ctl = VID_SRC_J_DMA_CTL,
+		.gpcnt_ctl = VID_SRC_J_GPCNT_CTL,
+		.gpcnt = VID_SRC_J_GPCNT,
+
+		.vid_fmt_ctl = VID_SRC_J_FMT_CTL,
+		.vid_active_ctl1 = VID_SRC_J_ACTIVE_CTL1,
+		.vid_active_ctl2 = VID_SRC_J_ACTIVE_CTL2,
+		.vid_cdt_size = VID_SRC_J_CDT_SZ,
+		.irq_bit = 9,
+	},
+
+	[SRAM_CH11] = {
+		.i = SRAM_CH11,
+		.name = "Audio Upstream Channel B",
+		.cmds_start = AUD_B_UP_CMDS,
+		.ctrl_start = AUD_B_IQ,
+		.cdt = AUD_B_CDT,
+		.fifo_start = AUD_B_UP_CLUSTER_1,
+		.fifo_size = (AUDIO_CLUSTER_SIZE * 3),
+		.ptr1_reg = DMA22_PTR1,
+		.ptr2_reg = DMA22_PTR2,
+		.cnt1_reg = DMA22_CNT1,
+		.cnt2_reg = DMA22_CNT2,
+		.int_msk = AUD_B_INT_MSK,
+		.int_stat = AUD_B_INT_STAT,
+		.int_mstat = AUD_B_INT_MSTAT,
+		.dma_ctl = AUD_INT_DMA_CTL,
+		.gpcnt_ctl = AUD_B_GPCNT_CTL,
+		.gpcnt = AUD_B_GPCNT,
+		.aud_length = AUD_B_LNGTH,
+		.aud_cfg = AUD_B_CFG,
+		.fld_aud_fifo_en = FLD_AUD_SRC_B_FIFO_EN,
+		.fld_aud_risc_en = FLD_AUD_SRC_B_RISC_EN,
+		.irq_bit = 11,
+	},
+};
+EXPORT_SYMBOL(cx25821_sram_channels);
+
+struct sram_channel *channel0 = &cx25821_sram_channels[SRAM_CH00];
+struct sram_channel *channel1 = &cx25821_sram_channels[SRAM_CH01];
+struct sram_channel *channel2 = &cx25821_sram_channels[SRAM_CH02];
+struct sram_channel *channel3 = &cx25821_sram_channels[SRAM_CH03];
+struct sram_channel *channel4 = &cx25821_sram_channels[SRAM_CH04];
+struct sram_channel *channel5 = &cx25821_sram_channels[SRAM_CH05];
+struct sram_channel *channel6 = &cx25821_sram_channels[SRAM_CH06];
+struct sram_channel *channel7 = &cx25821_sram_channels[SRAM_CH07];
+struct sram_channel *channel9 = &cx25821_sram_channels[SRAM_CH09];
+struct sram_channel *channel10 = &cx25821_sram_channels[SRAM_CH10];
+struct sram_channel *channel11 = &cx25821_sram_channels[SRAM_CH11];
+
+struct cx25821_dmaqueue mpegq;
+
+static int cx25821_risc_decode(u32 risc)
+{
+	static const char * const instr[16] = {
+		[RISC_SYNC >> 28] = "sync",
+		[RISC_WRITE >> 28] = "write",
+		[RISC_WRITEC >> 28] = "writec",
+		[RISC_READ >> 28] = "read",
+		[RISC_READC >> 28] = "readc",
+		[RISC_JUMP >> 28] = "jump",
+		[RISC_SKIP >> 28] = "skip",
+		[RISC_WRITERM >> 28] = "writerm",
+		[RISC_WRITECM >> 28] = "writecm",
+		[RISC_WRITECR >> 28] = "writecr",
+	};
+	static const int incr[16] = {
+		[RISC_WRITE >> 28] = 3,
+		[RISC_JUMP >> 28] = 3,
+		[RISC_SKIP >> 28] = 1,
+		[RISC_SYNC >> 28] = 1,
+		[RISC_WRITERM >> 28] = 3,
+		[RISC_WRITECM >> 28] = 3,
+		[RISC_WRITECR >> 28] = 4,
+	};
+	static const char * const bits[] = {
+		"12", "13", "14", "resync",
+		"cnt0", "cnt1", "18", "19",
+		"20", "21", "22", "23",
+		"irq1", "irq2", "eol", "sol",
+	};
+	int i;
+
+	pr_cont("0x%08x [ %s",
+		risc, instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
+	for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--) {
+		if (risc & (1 << (i + 12)))
+			pr_cont(" %s", bits[i]);
+	}
+	pr_cont(" count=%d ]\n", risc & 0xfff);
+	return incr[risc >> 28] ? incr[risc >> 28] : 1;
+}
+
+static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	return cx_read(bus->reg_stat) & 0x01;
+}
+
+void cx_i2c_read_print(struct cx25821_dev *dev, u32 reg, const char *reg_string)
+{
+	int tmp = 0;
+	u32 value = 0;
+
+	value = cx25821_i2c_read(&dev->i2c_bus[0], reg, &tmp);
+}
+
+static void cx25821_registers_init(struct cx25821_dev *dev)
+{
+	u32 tmp;
+
+	/* enable RUN_RISC in Pecos */
+	cx_write(DEV_CNTRL2, 0x20);
+
+	/* Set the master PCI interrupt masks to enable video, audio, MBIF,
+	 * and GPIO interrupts
+	 * I2C interrupt masking is handled by the I2C objects themselves. */
+	cx_write(PCI_INT_MSK, 0x2001FFFF);
+
+	tmp = cx_read(RDR_TLCTL0);
+	tmp &= ~FLD_CFG_RCB_CK_EN;	/* Clear the RCB_CK_EN bit */
+	cx_write(RDR_TLCTL0, tmp);
+
+	/* PLL-A setting for the Audio Master Clock */
+	cx_write(PLL_A_INT_FRAC, 0x9807A58B);
+
+	/* PLL_A_POST = 0x1C, PLL_A_OUT_TO_PIN = 0x1 */
+	cx_write(PLL_A_POST_STAT_BIST, 0x8000019C);
+
+	/* clear reset bit [31] */
+	tmp = cx_read(PLL_A_INT_FRAC);
+	cx_write(PLL_A_INT_FRAC, tmp & 0x7FFFFFFF);
+
+	/* PLL-B setting for Mobilygen Host Bus Interface */
+	cx_write(PLL_B_INT_FRAC, 0x9883A86F);
+
+	/* PLL_B_POST = 0xD, PLL_B_OUT_TO_PIN = 0x0 */
+	cx_write(PLL_B_POST_STAT_BIST, 0x8000018D);
+
+	/* clear reset bit [31] */
+	tmp = cx_read(PLL_B_INT_FRAC);
+	cx_write(PLL_B_INT_FRAC, tmp & 0x7FFFFFFF);
+
+	/* PLL-C setting for video upstream channel */
+	cx_write(PLL_C_INT_FRAC, 0x96A0EA3F);
+
+	/* PLL_C_POST = 0x3, PLL_C_OUT_TO_PIN = 0x0 */
+	cx_write(PLL_C_POST_STAT_BIST, 0x80000103);
+
+	/* clear reset bit [31] */
+	tmp = cx_read(PLL_C_INT_FRAC);
+	cx_write(PLL_C_INT_FRAC, tmp & 0x7FFFFFFF);
+
+	/* PLL-D setting for audio upstream channel */
+	cx_write(PLL_D_INT_FRAC, 0x98757F5B);
+
+	/* PLL_D_POST = 0x13, PLL_D_OUT_TO_PIN = 0x0 */
+	cx_write(PLL_D_POST_STAT_BIST, 0x80000113);
+
+	/* clear reset bit [31] */
+	tmp = cx_read(PLL_D_INT_FRAC);
+	cx_write(PLL_D_INT_FRAC, tmp & 0x7FFFFFFF);
+
+	/* This selects the PLL C clock source for the video upstream channel
+	 * I and J */
+	tmp = cx_read(VID_CH_CLK_SEL);
+	cx_write(VID_CH_CLK_SEL, (tmp & 0x00FFFFFF) | 0x24000000);
+
+	/* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
+	 * channel A-C
+	 * select 656/VIP DST for downstream Channel A - C */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	/* cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); */
+	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+
+	/* enables 656 port I and J as output */
+	tmp = cx_read(CLK_RST);
+	/* use external ALT_PLL_REF pin as its reference clock instead */
+	tmp |= FLD_USE_ALT_PLL_REF;
+	cx_write(CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE));
+
+	mdelay(100);
+}
+
+int cx25821_sram_channel_setup(struct cx25821_dev *dev,
+			       struct sram_channel *ch,
+			       unsigned int bpl, u32 risc)
+{
+	unsigned int i, lines;
+	u32 cdt;
+
+	if (ch->cmds_start == 0) {
+		cx_write(ch->ptr1_reg, 0);
+		cx_write(ch->ptr2_reg, 0);
+		cx_write(ch->cnt2_reg, 0);
+		cx_write(ch->cnt1_reg, 0);
+		return 0;
+	}
+
+	bpl = (bpl + 7) & ~7;	/* alignment */
+	cdt = ch->cdt;
+	lines = ch->fifo_size / bpl;
+
+	if (lines > 4)
+		lines = 4;
+
+	BUG_ON(lines < 2);
+
+	cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	cx_write(8 + 4, 8);
+	cx_write(8 + 8, 0);
+
+	/* write CDT */
+	for (i = 0; i < lines; i++) {
+		cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+		cx_write(cdt + 16 * i + 4, 0);
+		cx_write(cdt + 16 * i + 8, 0);
+		cx_write(cdt + 16 * i + 12, 0);
+	}
+
+	/* init the first cdt buffer */
+	for (i = 0; i < 128; i++)
+		cx_write(ch->fifo_start + 4 * i, i);
+
+	/* write CMDS */
+	if (ch->jumponly)
+		cx_write(ch->cmds_start + 0, 8);
+	else
+		cx_write(ch->cmds_start + 0, risc);
+
+	cx_write(ch->cmds_start + 4, 0);	/* 64 bits 63-32 */
+	cx_write(ch->cmds_start + 8, cdt);
+	cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
+	cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+	if (ch->jumponly)
+		cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
+	else
+		cx_write(ch->cmds_start + 20, 64 >> 2);
+
+	for (i = 24; i < 80; i += 4)
+		cx_write(ch->cmds_start + i, 0);
+
+	/* fill registers */
+	cx_write(ch->ptr1_reg, ch->fifo_start);
+	cx_write(ch->ptr2_reg, cdt);
+	cx_write(ch->cnt2_reg, (lines * 16) >> 3);
+	cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+	return 0;
+}
+EXPORT_SYMBOL(cx25821_sram_channel_setup);
+
+int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev,
+				     struct sram_channel *ch,
+				     unsigned int bpl, u32 risc)
+{
+	unsigned int i, lines;
+	u32 cdt;
+
+	if (ch->cmds_start == 0) {
+		cx_write(ch->ptr1_reg, 0);
+		cx_write(ch->ptr2_reg, 0);
+		cx_write(ch->cnt2_reg, 0);
+		cx_write(ch->cnt1_reg, 0);
+		return 0;
+	}
+
+	bpl = (bpl + 7) & ~7;	/* alignment */
+	cdt = ch->cdt;
+	lines = ch->fifo_size / bpl;
+
+	if (lines > 3)
+		lines = 3;	/* for AUDIO */
+
+	BUG_ON(lines < 2);
+
+	cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	cx_write(8 + 4, 8);
+	cx_write(8 + 8, 0);
+
+	/* write CDT */
+	for (i = 0; i < lines; i++) {
+		cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+		cx_write(cdt + 16 * i + 4, 0);
+		cx_write(cdt + 16 * i + 8, 0);
+		cx_write(cdt + 16 * i + 12, 0);
+	}
+
+	/* write CMDS */
+	if (ch->jumponly)
+		cx_write(ch->cmds_start + 0, 8);
+	else
+		cx_write(ch->cmds_start + 0, risc);
+
+	cx_write(ch->cmds_start + 4, 0);	/* 64 bits 63-32 */
+	cx_write(ch->cmds_start + 8, cdt);
+	cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
+	cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+	/* IQ size */
+	if (ch->jumponly)
+		cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
+	else
+		cx_write(ch->cmds_start + 20, 64 >> 2);
+
+	/* zero out */
+	for (i = 24; i < 80; i += 4)
+		cx_write(ch->cmds_start + i, 0);
+
+	/* fill registers */
+	cx_write(ch->ptr1_reg, ch->fifo_start);
+	cx_write(ch->ptr2_reg, cdt);
+	cx_write(ch->cnt2_reg, (lines * 16) >> 3);
+	cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+	return 0;
+}
+EXPORT_SYMBOL(cx25821_sram_channel_setup_audio);
+
+void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch)
+{
+	static char *name[] = {
+		"init risc lo",
+		"init risc hi",
+		"cdt base",
+		"cdt size",
+		"iq base",
+		"iq size",
+		"risc pc lo",
+		"risc pc hi",
+		"iq wr ptr",
+		"iq rd ptr",
+		"cdt current",
+		"pci target lo",
+		"pci target hi",
+		"line / byte",
+	};
+	u32 risc;
+	unsigned int i, j, n;
+
+	pr_warn("%s: %s - dma channel status dump\n", dev->name, ch->name);
+	for (i = 0; i < ARRAY_SIZE(name); i++)
+		pr_warn("cmds + 0x%2x:   %-15s: 0x%08x\n",
+			i * 4, name[i], cx_read(ch->cmds_start + 4 * i));
+
+	j = i * 4;
+	for (i = 0; i < 4;) {
+		risc = cx_read(ch->cmds_start + 4 * (i + 14));
+		pr_warn("cmds + 0x%2x:   risc%d: ", j + i * 4, i);
+		i += cx25821_risc_decode(risc);
+	}
+
+	for (i = 0; i < (64 >> 2); i += n) {
+		risc = cx_read(ch->ctrl_start + 4 * i);
+		/* No consideration for bits 63-32 */
+
+		pr_warn("ctrl + 0x%2x (0x%08x): iq %x: ",
+			i * 4, ch->ctrl_start + 4 * i, i);
+		n = cx25821_risc_decode(risc);
+		for (j = 1; j < n; j++) {
+			risc = cx_read(ch->ctrl_start + 4 * (i + j));
+			pr_warn("ctrl + 0x%2x :   iq %x: 0x%08x [ arg #%d ]\n",
+				4 * (i + j), i + j, risc, j);
+		}
+	}
+
+	pr_warn("        :   fifo: 0x%08x -> 0x%x\n",
+		ch->fifo_start, ch->fifo_start + ch->fifo_size);
+	pr_warn("        :   ctrl: 0x%08x -> 0x%x\n",
+		ch->ctrl_start, ch->ctrl_start + 6 * 16);
+	pr_warn("        :   ptr1_reg: 0x%08x\n",
+		cx_read(ch->ptr1_reg));
+	pr_warn("        :   ptr2_reg: 0x%08x\n",
+		cx_read(ch->ptr2_reg));
+	pr_warn("        :   cnt1_reg: 0x%08x\n",
+		cx_read(ch->cnt1_reg));
+	pr_warn("        :   cnt2_reg: 0x%08x\n",
+		cx_read(ch->cnt2_reg));
+}
+EXPORT_SYMBOL(cx25821_sram_channel_dump);
+
+void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
+				     struct sram_channel *ch)
+{
+	static const char * const name[] = {
+		"init risc lo",
+		"init risc hi",
+		"cdt base",
+		"cdt size",
+		"iq base",
+		"iq size",
+		"risc pc lo",
+		"risc pc hi",
+		"iq wr ptr",
+		"iq rd ptr",
+		"cdt current",
+		"pci target lo",
+		"pci target hi",
+		"line / byte",
+	};
+
+	u32 risc, value, tmp;
+	unsigned int i, j, n;
+
+	pr_info("\n%s: %s - dma Audio channel status dump\n",
+		dev->name, ch->name);
+
+	for (i = 0; i < ARRAY_SIZE(name); i++)
+		pr_info("%s: cmds + 0x%2x:   %-15s: 0x%08x\n",
+			dev->name, i * 4, name[i],
+			cx_read(ch->cmds_start + 4 * i));
+
+	j = i * 4;
+	for (i = 0; i < 4;) {
+		risc = cx_read(ch->cmds_start + 4 * (i + 14));
+		pr_warn("cmds + 0x%2x:   risc%d: ", j + i * 4, i);
+		i += cx25821_risc_decode(risc);
+	}
+
+	for (i = 0; i < (64 >> 2); i += n) {
+		risc = cx_read(ch->ctrl_start + 4 * i);
+		/* No consideration for bits 63-32 */
+
+		pr_warn("ctrl + 0x%2x (0x%08x): iq %x: ",
+			i * 4, ch->ctrl_start + 4 * i, i);
+		n = cx25821_risc_decode(risc);
+
+		for (j = 1; j < n; j++) {
+			risc = cx_read(ch->ctrl_start + 4 * (i + j));
+			pr_warn("ctrl + 0x%2x :   iq %x: 0x%08x [ arg #%d ]\n",
+				4 * (i + j), i + j, risc, j);
+		}
+	}
+
+	pr_warn("        :   fifo: 0x%08x -> 0x%x\n",
+		ch->fifo_start, ch->fifo_start + ch->fifo_size);
+	pr_warn("        :   ctrl: 0x%08x -> 0x%x\n",
+		ch->ctrl_start, ch->ctrl_start + 6 * 16);
+	pr_warn("        :   ptr1_reg: 0x%08x\n",
+		cx_read(ch->ptr1_reg));
+	pr_warn("        :   ptr2_reg: 0x%08x\n",
+		cx_read(ch->ptr2_reg));
+	pr_warn("        :   cnt1_reg: 0x%08x\n",
+		cx_read(ch->cnt1_reg));
+	pr_warn("        :   cnt2_reg: 0x%08x\n",
+		cx_read(ch->cnt2_reg));
+
+	for (i = 0; i < 4; i++) {
+		risc = cx_read(ch->cmds_start + 56 + (i * 4));
+		pr_warn("instruction %d = 0x%x\n", i, risc);
+	}
+
+	/* read data from the first cdt buffer */
+	risc = cx_read(AUD_A_CDT);
+	pr_warn("\nread cdt loc=0x%x\n", risc);
+	for (i = 0; i < 8; i++) {
+		n = cx_read(risc + i * 4);
+		pr_cont("0x%x ", n);
+	}
+	pr_cont("\n\n");
+
+	value = cx_read(CLK_RST);
+	CX25821_INFO(" CLK_RST = 0x%x\n\n", value);
+
+	value = cx_read(PLL_A_POST_STAT_BIST);
+	CX25821_INFO(" PLL_A_POST_STAT_BIST = 0x%x\n\n", value);
+	value = cx_read(PLL_A_INT_FRAC);
+	CX25821_INFO(" PLL_A_INT_FRAC = 0x%x\n\n", value);
+
+	value = cx_read(PLL_B_POST_STAT_BIST);
+	CX25821_INFO(" PLL_B_POST_STAT_BIST = 0x%x\n\n", value);
+	value = cx_read(PLL_B_INT_FRAC);
+	CX25821_INFO(" PLL_B_INT_FRAC = 0x%x\n\n", value);
+
+	value = cx_read(PLL_C_POST_STAT_BIST);
+	CX25821_INFO(" PLL_C_POST_STAT_BIST = 0x%x\n\n", value);
+	value = cx_read(PLL_C_INT_FRAC);
+	CX25821_INFO(" PLL_C_INT_FRAC = 0x%x\n\n", value);
+
+	value = cx_read(PLL_D_POST_STAT_BIST);
+	CX25821_INFO(" PLL_D_POST_STAT_BIST = 0x%x\n\n", value);
+	value = cx_read(PLL_D_INT_FRAC);
+	CX25821_INFO(" PLL_D_INT_FRAC = 0x%x\n\n", value);
+
+	value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
+	CX25821_INFO(" AFE_AB_DIAG_CTRL (0x10900090) = 0x%x\n\n", value);
+}
+EXPORT_SYMBOL(cx25821_sram_channel_dump_audio);
+
+static void cx25821_shutdown(struct cx25821_dev *dev)
+{
+	int i;
+
+	/* disable RISC controller */
+	cx_write(DEV_CNTRL2, 0);
+
+	/* Disable Video A/B activity */
+	for (i = 0; i < VID_CHANNEL_NUM; i++) {
+		cx_write(dev->channels[i].sram_channels->dma_ctl, 0);
+		cx_write(dev->channels[i].sram_channels->int_msk, 0);
+	}
+
+	for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
+		i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) {
+		cx_write(dev->channels[i].sram_channels->dma_ctl, 0);
+		cx_write(dev->channels[i].sram_channels->int_msk, 0);
+	}
+
+	/* Disable Audio activity */
+	cx_write(AUD_INT_DMA_CTL, 0);
+
+	/* Disable Serial port */
+	cx_write(UART_CTL, 0);
+
+	/* Disable Interrupts */
+	cx_write(PCI_INT_MSK, 0);
+	cx_write(AUD_A_INT_MSK, 0);
+}
+
+void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select,
+			      u32 format)
+{
+	if (channel_select <= 7 && channel_select >= 0) {
+		cx_write(dev->channels[channel_select].
+			sram_channels->pix_frmt, format);
+		dev->channels[channel_select].pixel_formats = format;
+	}
+}
+
+static void cx25821_set_vip_mode(struct cx25821_dev *dev,
+				 struct sram_channel *ch)
+{
+	cx_write(ch->pix_frmt, PIXEL_FRMT_422);
+	cx_write(ch->vip_ctl, PIXEL_ENGINE_VIP1);
+}
+
+static void cx25821_initialize(struct cx25821_dev *dev)
+{
+	int i;
+
+	dprintk(1, "%s()\n", __func__);
+
+	cx25821_shutdown(dev);
+	cx_write(PCI_INT_STAT, 0xffffffff);
+
+	for (i = 0; i < VID_CHANNEL_NUM; i++)
+		cx_write(dev->channels[i].sram_channels->int_stat, 0xffffffff);
+
+	cx_write(AUD_A_INT_STAT, 0xffffffff);
+	cx_write(AUD_B_INT_STAT, 0xffffffff);
+	cx_write(AUD_C_INT_STAT, 0xffffffff);
+	cx_write(AUD_D_INT_STAT, 0xffffffff);
+	cx_write(AUD_E_INT_STAT, 0xffffffff);
+
+	cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000);
+	cx_write(PAD_CTRL, 0x12);	/* for I2C */
+	cx25821_registers_init(dev);	/* init Pecos registers */
+	mdelay(100);
+
+	for (i = 0; i < VID_CHANNEL_NUM; i++) {
+		cx25821_set_vip_mode(dev, dev->channels[i].sram_channels);
+		cx25821_sram_channel_setup(dev, dev->channels[i].sram_channels,
+						1440, 0);
+		dev->channels[i].pixel_formats = PIXEL_FRMT_422;
+		dev->channels[i].use_cif_resolution = FALSE;
+	}
+
+	/* Probably only affect Downstream */
+	for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
+		i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) {
+		cx25821_set_vip_mode(dev, dev->channels[i].sram_channels);
+	}
+
+	cx25821_sram_channel_setup_audio(dev,
+				dev->channels[SRAM_CH08].sram_channels,
+				128, 0);
+
+	cx25821_gpio_init(dev);
+}
+
+static int cx25821_get_resources(struct cx25821_dev *dev)
+{
+	if (request_mem_region
+	    (pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0),
+	     dev->name))
+		return 0;
+
+	pr_err("%s: can't get MMIO memory @ 0x%llx\n",
+	       dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
+
+	return -EBUSY;
+}
+
+static void cx25821_dev_checkrevision(struct cx25821_dev *dev)
+{
+	dev->hwrevision = cx_read(RDR_CFG2) & 0xff;
+
+	pr_info("%s(): Hardware revision = 0x%02x\n",
+		__func__, dev->hwrevision);
+}
+
+static void cx25821_iounmap(struct cx25821_dev *dev)
+{
+	if (dev == NULL)
+		return;
+
+	/* Releasing IO memory */
+	if (dev->lmmio != NULL) {
+		CX25821_INFO("Releasing lmmio.\n");
+		iounmap(dev->lmmio);
+		dev->lmmio = NULL;
+	}
+}
+
+static int cx25821_dev_setup(struct cx25821_dev *dev)
+{
+	int io_size = 0, i;
+
+	pr_info("\n***********************************\n");
+	pr_info("cx25821 set up\n");
+	pr_info("***********************************\n\n");
+
+	mutex_init(&dev->lock);
+
+	atomic_inc(&dev->refcount);
+
+	dev->nr = ++cx25821_devcount;
+	sprintf(dev->name, "cx25821[%d]", dev->nr);
+
+	mutex_lock(&cx25821_devlist_mutex);
+	list_add_tail(&dev->devlist, &cx25821_devlist);
+	mutex_unlock(&cx25821_devlist_mutex);
+
+	strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown");
+	strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821");
+
+	if (dev->pci->device != 0x8210) {
+		pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n",
+			__func__, dev->pci->device);
+		return -1;
+	} else {
+		pr_info("Athena Hardware device = 0x%02x\n", dev->pci->device);
+	}
+
+	/* Apply a sensible clock frequency for the PCIe bridge */
+	dev->clk_freq = 28000000;
+	for (i = 0; i < MAX_VID_CHANNEL_NUM; i++)
+		dev->channels[i].sram_channels = &cx25821_sram_channels[i];
+
+	if (dev->nr > 1)
+		CX25821_INFO("dev->nr > 1!");
+
+	/* board config */
+	dev->board = 1;		/* card[dev->nr]; */
+	dev->_max_num_decoders = MAX_DECODERS;
+
+	dev->pci_bus = dev->pci->bus->number;
+	dev->pci_slot = PCI_SLOT(dev->pci->devfn);
+	dev->pci_irqmask = 0x001f00;
+
+	/* External Master 1 Bus */
+	dev->i2c_bus[0].nr = 0;
+	dev->i2c_bus[0].dev = dev;
+	dev->i2c_bus[0].reg_stat = I2C1_STAT;
+	dev->i2c_bus[0].reg_ctrl = I2C1_CTRL;
+	dev->i2c_bus[0].reg_addr = I2C1_ADDR;
+	dev->i2c_bus[0].reg_rdata = I2C1_RDATA;
+	dev->i2c_bus[0].reg_wdata = I2C1_WDATA;
+	dev->i2c_bus[0].i2c_period = (0x07 << 24);	/* 1.95MHz */
+
+	if (cx25821_get_resources(dev) < 0) {
+		pr_err("%s: No more PCIe resources for subsystem: %04x:%04x\n",
+		       dev->name, dev->pci->subsystem_vendor,
+		       dev->pci->subsystem_device);
+
+		cx25821_devcount--;
+		return -EBUSY;
+	}
+
+	/* PCIe stuff */
+	dev->base_io_addr = pci_resource_start(dev->pci, 0);
+	io_size = pci_resource_len(dev->pci, 0);
+
+	if (!dev->base_io_addr) {
+		CX25821_ERR("No PCI Memory resources, exiting!\n");
+		return -ENODEV;
+	}
+
+	dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0));
+
+	if (!dev->lmmio) {
+		CX25821_ERR
+		    ("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n");
+		cx25821_iounmap(dev);
+		return -ENOMEM;
+	}
+
+	dev->bmmio = (u8 __iomem *) dev->lmmio;
+
+	pr_info("%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+		dev->name, dev->pci->subsystem_vendor,
+		dev->pci->subsystem_device, cx25821_boards[dev->board].name,
+		dev->board, card[dev->nr] == dev->board ?
+		"insmod option" : "autodetected");
+
+	/* init hardware */
+	cx25821_initialize(dev);
+
+	cx25821_i2c_register(&dev->i2c_bus[0]);
+/*  cx25821_i2c_register(&dev->i2c_bus[1]);
+ *  cx25821_i2c_register(&dev->i2c_bus[2]); */
+
+	CX25821_INFO("i2c register! bus->i2c_rc = %d\n",
+		     dev->i2c_bus[0].i2c_rc);
+
+	cx25821_card_setup(dev);
+
+	if (medusa_video_init(dev) < 0)
+		CX25821_ERR("%s(): Failed to initialize medusa!\n", __func__);
+
+	cx25821_video_register(dev);
+
+	/* register IOCTL device */
+	dev->ioctl_dev =
+	   cx25821_vdev_init(dev, dev->pci, &cx25821_videoioctl_template,
+			      "video");
+
+	if (video_register_device
+	    (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) {
+		cx25821_videoioctl_unregister(dev);
+		pr_err("%s(): Failed to register video adapter for IOCTL, so unregistering videoioctl device\n",
+		       __func__);
+	}
+
+	cx25821_dev_checkrevision(dev);
+	CX25821_INFO("setup done!\n");
+
+	return 0;
+}
+
+void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev,
+				      struct upstream_user_struct *up_data)
+{
+	dev->_isNTSC = !strcmp(dev->vid_stdname, "NTSC") ? 1 : 0;
+
+	dev->tvnorm = !dev->_isNTSC ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;
+	medusa_set_videostandard(dev);
+
+	cx25821_vidupstream_init_ch1(dev, dev->channel_select,
+				     dev->pixel_format);
+}
+
+void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev,
+				      struct upstream_user_struct *up_data)
+{
+	dev->_isNTSC_ch2 = !strcmp(dev->vid_stdname_ch2, "NTSC") ? 1 : 0;
+
+	dev->tvnorm = !dev->_isNTSC_ch2 ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;
+	medusa_set_videostandard(dev);
+
+	cx25821_vidupstream_init_ch2(dev, dev->channel_select_ch2,
+				     dev->pixel_format_ch2);
+}
+
+void cx25821_start_upstream_audio(struct cx25821_dev *dev,
+				  struct upstream_user_struct *up_data)
+{
+	cx25821_audio_upstream_init(dev, AUDIO_UPSTREAM_SRAM_CHANNEL_B);
+}
+
+void cx25821_dev_unregister(struct cx25821_dev *dev)
+{
+	int i;
+
+	if (!dev->base_io_addr)
+		return;
+
+	cx25821_free_mem_upstream_ch1(dev);
+	cx25821_free_mem_upstream_ch2(dev);
+	cx25821_free_mem_upstream_audio(dev);
+
+	release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0));
+
+	if (!atomic_dec_and_test(&dev->refcount))
+		return;
+
+	for (i = 0; i < VID_CHANNEL_NUM; i++)
+		cx25821_video_unregister(dev, i);
+
+	for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
+	     i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) {
+		cx25821_video_unregister(dev, i);
+	}
+
+	cx25821_videoioctl_unregister(dev);
+
+	cx25821_i2c_unregister(&dev->i2c_bus[0]);
+	cx25821_iounmap(dev);
+}
+EXPORT_SYMBOL(cx25821_dev_unregister);
+
+static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist,
+				  unsigned int offset, u32 sync_line,
+				  unsigned int bpl, unsigned int padding,
+				  unsigned int lines)
+{
+	struct scatterlist *sg;
+	unsigned int line, todo;
+
+	/* sync instruction */
+	if (sync_line != NO_SYNC_LINE)
+		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	/* scan lines */
+	sg = sglist;
+	for (line = 0; line < lines; line++) {
+		while (offset && offset >= sg_dma_len(sg)) {
+			offset -= sg_dma_len(sg);
+			sg++;
+		}
+		if (bpl <= sg_dma_len(sg) - offset) {
+			/* fits into current chunk */
+			*(rp++) =
+			    cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL | bpl);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			offset += bpl;
+		} else {
+			/* scanline needs to be split */
+			todo = bpl;
+			*(rp++) =
+			    cpu_to_le32(RISC_WRITE | RISC_SOL |
+					(sg_dma_len(sg) - offset));
+			*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			todo -= (sg_dma_len(sg) - offset);
+			offset = 0;
+			sg++;
+			while (todo > sg_dma_len(sg)) {
+				*(rp++) =
+				    cpu_to_le32(RISC_WRITE | sg_dma_len(sg));
+				*(rp++) = cpu_to_le32(sg_dma_address(sg));
+				*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+				todo -= sg_dma_len(sg);
+				sg++;
+			}
+			*(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg));
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			offset += todo;
+		}
+
+		offset += padding;
+	}
+
+	return rp;
+}
+
+int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+			struct scatterlist *sglist, unsigned int top_offset,
+			unsigned int bottom_offset, unsigned int bpl,
+			unsigned int padding, unsigned int lines)
+{
+	u32 instructions;
+	u32 fields;
+	__le32 *rp;
+	int rc;
+
+	fields = 0;
+	if (UNSET != top_offset)
+		fields++;
+	if (UNSET != bottom_offset)
+		fields++;
+
+	/* estimate risc mem: worst case is one write per page border +
+	   one write per scan line + syncs + jump (all 2 dwords).  Padding
+	   can cause next bpl to start close to a page border.  First DMA
+	   region may be smaller than PAGE_SIZE */
+	/* write and jump need and extra dword */
+	instructions =
+	    fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
+	instructions += 2;
+	rc = btcx_riscmem_alloc(pci, risc, instructions * 12);
+
+	if (rc < 0)
+		return rc;
+
+	/* write risc instructions */
+	rp = risc->cpu;
+
+	if (UNSET != top_offset) {
+		rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding,
+					lines);
+	}
+
+	if (UNSET != bottom_offset) {
+		rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl,
+					padding, lines);
+	}
+
+	/* save pointer to jmp instruction address */
+	risc->jmp = rp;
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+
+	return 0;
+}
+
+static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist,
+					unsigned int offset, u32 sync_line,
+					unsigned int bpl, unsigned int padding,
+					unsigned int lines, unsigned int lpi)
+{
+	struct scatterlist *sg;
+	unsigned int line, todo, sol;
+
+	/* sync instruction */
+	if (sync_line != NO_SYNC_LINE)
+		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	/* scan lines */
+	sg = sglist;
+	for (line = 0; line < lines; line++) {
+		while (offset && offset >= sg_dma_len(sg)) {
+			offset -= sg_dma_len(sg);
+			sg++;
+		}
+
+		if (lpi && line > 0 && !(line % lpi))
+			sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
+		else
+			sol = RISC_SOL;
+
+		if (bpl <= sg_dma_len(sg) - offset) {
+			/* fits into current chunk */
+			*(rp++) =
+			    cpu_to_le32(RISC_WRITE | sol | RISC_EOL | bpl);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			offset += bpl;
+		} else {
+			/* scanline needs to be split */
+			todo = bpl;
+			*(rp++) = cpu_to_le32(RISC_WRITE | sol |
+					      (sg_dma_len(sg) - offset));
+			*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			todo -= (sg_dma_len(sg) - offset);
+			offset = 0;
+			sg++;
+			while (todo > sg_dma_len(sg)) {
+				*(rp++) = cpu_to_le32(RISC_WRITE |
+						      sg_dma_len(sg));
+				*(rp++) = cpu_to_le32(sg_dma_address(sg));
+				*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+				todo -= sg_dma_len(sg);
+				sg++;
+			}
+			*(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg));
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			offset += todo;
+		}
+		offset += padding;
+	}
+
+	return rp;
+}
+
+int cx25821_risc_databuffer_audio(struct pci_dev *pci,
+				  struct btcx_riscmem *risc,
+				  struct scatterlist *sglist,
+				  unsigned int bpl,
+				  unsigned int lines, unsigned int lpi)
+{
+	u32 instructions;
+	__le32 *rp;
+	int rc;
+
+	/* estimate risc mem: worst case is one write per page border +
+	   one write per scan line + syncs + jump (all 2 dwords).  Here
+	   there is no padding and no sync.  First DMA region may be smaller
+	   than PAGE_SIZE */
+	/* Jump and write need an extra dword */
+	instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
+	instructions += 1;
+
+	rc = btcx_riscmem_alloc(pci, risc, instructions * 12);
+	if (rc < 0)
+		return rc;
+
+	/* write risc instructions */
+	rp = risc->cpu;
+	rp = cx25821_risc_field_audio(rp, sglist, 0, NO_SYNC_LINE, bpl, 0,
+				      lines, lpi);
+
+	/* save pointer to jmp instruction address */
+	risc->jmp = rp;
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+	return 0;
+}
+EXPORT_SYMBOL(cx25821_risc_databuffer_audio);
+
+int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+			 u32 reg, u32 mask, u32 value)
+{
+	__le32 *rp;
+	int rc;
+
+	rc = btcx_riscmem_alloc(pci, risc, 4 * 16);
+
+	if (rc < 0)
+		return rc;
+
+	/* write risc instructions */
+	rp = risc->cpu;
+
+	*(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1);
+	*(rp++) = cpu_to_le32(reg);
+	*(rp++) = cpu_to_le32(value);
+	*(rp++) = cpu_to_le32(mask);
+	*(rp++) = cpu_to_le32(RISC_JUMP);
+	*(rp++) = cpu_to_le32(risc->dma);
+	*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+	return 0;
+}
+
+void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf)
+{
+	struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+
+	BUG_ON(in_interrupt());
+	videobuf_waiton(q, &buf->vb, 0, 0);
+	videobuf_dma_unmap(q->dev, dma);
+	videobuf_dma_free(dma);
+	btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
+	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static irqreturn_t cx25821_irq(int irq, void *dev_id)
+{
+	struct cx25821_dev *dev = dev_id;
+	u32 pci_status, pci_mask;
+	u32 vid_status;
+	int i, handled = 0;
+	u32 mask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
+
+	pci_status = cx_read(PCI_INT_STAT);
+	pci_mask = cx_read(PCI_INT_MSK);
+
+	if (pci_status == 0)
+		goto out;
+
+	for (i = 0; i < VID_CHANNEL_NUM; i++) {
+		if (pci_status & mask[i]) {
+			vid_status = cx_read(dev->channels[i].
+				sram_channels->int_stat);
+
+			if (vid_status)
+				handled +=
+				cx25821_video_irq(dev, i, vid_status);
+
+			cx_write(PCI_INT_STAT, mask[i]);
+		}
+	}
+
+out:
+	return IRQ_RETVAL(handled);
+}
+
+void cx25821_print_irqbits(char *name, char *tag, char **strings,
+			   int len, u32 bits, u32 mask)
+{
+	unsigned int i;
+
+	printk(KERN_DEBUG pr_fmt("%s: %s [0x%x]"), name, tag, bits);
+
+	for (i = 0; i < len; i++) {
+		if (!(bits & (1 << i)))
+			continue;
+		if (strings[i])
+			pr_cont(" %s", strings[i]);
+		else
+			pr_cont(" %d", i);
+		if (!(mask & (1 << i)))
+			continue;
+		pr_cont("*");
+	}
+	pr_cont("\n");
+}
+EXPORT_SYMBOL(cx25821_print_irqbits);
+
+struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci)
+{
+	struct cx25821_dev *dev = pci_get_drvdata(pci);
+	return dev;
+}
+EXPORT_SYMBOL(cx25821_dev_get);
+
+static int __devinit cx25821_initdev(struct pci_dev *pci_dev,
+				     const struct pci_device_id *pci_id)
+{
+	struct cx25821_dev *dev;
+	int err = 0;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (NULL == dev)
+		return -ENOMEM;
+
+	err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
+	if (err < 0)
+		goto fail_free;
+
+	/* pci init */
+	dev->pci = pci_dev;
+	if (pci_enable_device(pci_dev)) {
+		err = -EIO;
+
+		pr_info("pci enable failed!\n");
+
+		goto fail_unregister_device;
+	}
+
+	pr_info("Athena pci enable !\n");
+
+	err = cx25821_dev_setup(dev);
+	if (err) {
+		if (err == -EBUSY)
+			goto fail_unregister_device;
+		else
+			goto fail_unregister_pci;
+	}
+
+	/* print pci info */
+	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
+	pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
+	pr_info("%s/0: found at %s, rev: %d, irq: %d, latency: %d, mmio: 0x%llx\n",
+		dev->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
+		dev->pci_lat, (unsigned long long)dev->base_io_addr);
+
+	pci_set_master(pci_dev);
+	if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+		pr_err("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
+		err = -EIO;
+		goto fail_irq;
+	}
+
+	err =
+	    request_irq(pci_dev->irq, cx25821_irq, IRQF_SHARED,
+			dev->name, dev);
+
+	if (err < 0) {
+		pr_err("%s: can't get IRQ %d\n", dev->name, pci_dev->irq);
+		goto fail_irq;
+	}
+
+	return 0;
+
+fail_irq:
+	pr_info("cx25821_initdev() can't get IRQ !\n");
+	cx25821_dev_unregister(dev);
+
+fail_unregister_pci:
+	pci_disable_device(pci_dev);
+fail_unregister_device:
+	v4l2_device_unregister(&dev->v4l2_dev);
+
+fail_free:
+	kfree(dev);
+	return err;
+}
+
+static void __devexit cx25821_finidev(struct pci_dev *pci_dev)
+{
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+	struct cx25821_dev *dev = get_cx25821(v4l2_dev);
+
+	cx25821_shutdown(dev);
+	pci_disable_device(pci_dev);
+
+	/* unregister stuff */
+	if (pci_dev->irq)
+		free_irq(pci_dev->irq, dev);
+
+	mutex_lock(&cx25821_devlist_mutex);
+	list_del(&dev->devlist);
+	mutex_unlock(&cx25821_devlist_mutex);
+
+	cx25821_dev_unregister(dev);
+	v4l2_device_unregister(v4l2_dev);
+	kfree(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(cx25821_pci_tbl) = {
+	{
+		/* CX25821 Athena */
+		.vendor = 0x14f1,
+		.device = 0x8210,
+		.subvendor = 0x14f1,
+		.subdevice = 0x0920,
+	},
+	{
+		/* --- end of list --- */
+	}
+};
+
+MODULE_DEVICE_TABLE(pci, cx25821_pci_tbl);
+
+static struct pci_driver cx25821_pci_driver = {
+	.name = "cx25821",
+	.id_table = cx25821_pci_tbl,
+	.probe = cx25821_initdev,
+	.remove = __devexit_p(cx25821_finidev),
+	/* TODO */
+	.suspend = NULL,
+	.resume = NULL,
+};
+
+static int __init cx25821_init(void)
+{
+	pr_info("driver version %d.%d.%d loaded\n",
+		(CX25821_VERSION_CODE >> 16) & 0xff,
+		(CX25821_VERSION_CODE >> 8) & 0xff,
+		CX25821_VERSION_CODE & 0xff);
+	return pci_register_driver(&cx25821_pci_driver);
+}
+
+static void __exit cx25821_fini(void)
+{
+	pci_unregister_driver(&cx25821_pci_driver);
+}
+
+
+module_init(cx25821_init);
+module_exit(cx25821_fini);
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-gpio.c linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-gpio.c
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-gpio.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,98 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 "cx25821.h"
+
+/********************* GPIO stuffs *********************/
+void cx25821_set_gpiopin_direction(struct cx25821_dev *dev,
+				   int pin_number, int pin_logic_value)
+{
+	int bit = pin_number;
+	u32 gpio_oe_reg = GPIO_LO_OE;
+	u32 gpio_register = 0;
+	u32 value = 0;
+
+	/* Check for valid pinNumber */
+	if (pin_number >= 47)
+		return;
+
+	if (pin_number > 31) {
+		bit = pin_number - 31;
+		gpio_oe_reg = GPIO_HI_OE;
+	}
+	/* Here we will make sure that the GPIOs 0 and 1 are output. keep the
+	 * rest as is */
+	gpio_register = cx_read(gpio_oe_reg);
+
+	if (pin_logic_value == 1)
+		value = gpio_register | Set_GPIO_Bit(bit);
+	else
+		value = gpio_register & Clear_GPIO_Bit(bit);
+
+	cx_write(gpio_oe_reg, value);
+}
+EXPORT_SYMBOL(cx25821_set_gpiopin_direction);
+
+static void cx25821_set_gpiopin_logicvalue(struct cx25821_dev *dev,
+					   int pin_number, int pin_logic_value)
+{
+	int bit = pin_number;
+	u32 gpio_reg = GPIO_LO;
+	u32 value = 0;
+
+	/* Check for valid pinNumber */
+	if (pin_number >= 47)
+		return;
+
+	/* change to output direction */
+	cx25821_set_gpiopin_direction(dev, pin_number, 0);
+
+	if (pin_number > 31) {
+		bit = pin_number - 31;
+		gpio_reg = GPIO_HI;
+	}
+
+	value = cx_read(gpio_reg);
+
+	if (pin_logic_value == 0)
+		value &= Clear_GPIO_Bit(bit);
+	else
+		value |= Set_GPIO_Bit(bit);
+
+	cx_write(gpio_reg, value);
+}
+
+void cx25821_gpio_init(struct cx25821_dev *dev)
+{
+	if (dev == NULL)
+		return;
+
+	switch (dev->board) {
+	case CX25821_BOARD_CONEXANT_ATHENA10:
+	default:
+		/* set GPIO 5 to select the path for Medusa/Athena */
+		cx25821_set_gpiopin_logicvalue(dev, 5, 1);
+		mdelay(20);
+		break;
+	}
+
+}
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821.h linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821.h
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,617 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> cx23885 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 CX25821_H_
+#define CX25821_H_
+
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/kdev_t.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/tuner.h>
+#include <media/tveeprom.h>
+#include <media/videobuf-dma-sg.h>
+#include <media/videobuf-dvb.h>
+
+#include "btcx-risc.h"
+#include "cx25821-reg.h"
+#include "cx25821-medusa-reg.h"
+#include "cx25821-sram.h"
+#include "cx25821-audio.h"
+#include "media/cx2341x.h"
+
+#include <linux/version.h>
+#include <linux/mutex.h>
+
+#define CX25821_VERSION_CODE KERNEL_VERSION(0, 0, 106)
+
+#define UNSET (-1U)
+#define NO_SYNC_LINE (-1U)
+
+#define CX25821_MAXBOARDS 2
+
+#define TRUE    1
+#define FALSE   0
+#define LINE_SIZE_D1    1440
+
+/* Number of decoders and encoders */
+#define MAX_DECODERS            8
+#define MAX_ENCODERS            2
+#define QUAD_DECODERS           4
+#define MAX_CAMERAS             16
+
+/* Max number of inputs by card */
+#define MAX_CX25821_INPUT 8
+#define INPUT(nr) (&cx25821_boards[dev->board].input[nr])
+#define RESOURCE_VIDEO0       1
+#define RESOURCE_VIDEO1       2
+#define RESOURCE_VIDEO2       4
+#define RESOURCE_VIDEO3       8
+#define RESOURCE_VIDEO4       16
+#define RESOURCE_VIDEO5       32
+#define RESOURCE_VIDEO6       64
+#define RESOURCE_VIDEO7       128
+#define RESOURCE_VIDEO8       256
+#define RESOURCE_VIDEO9       512
+#define RESOURCE_VIDEO10      1024
+#define RESOURCE_VIDEO11      2048
+#define RESOURCE_VIDEO_IOCTL  4096
+
+#define BUFFER_TIMEOUT     (HZ)	/* 0.5 seconds */
+
+#define UNKNOWN_BOARD       0
+#define CX25821_BOARD        1
+
+/* Currently supported by the driver */
+#define CX25821_NORMS (\
+	V4L2_STD_NTSC_M |  V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_M_KR | \
+	V4L2_STD_PAL_BG |  V4L2_STD_PAL_DK    |  V4L2_STD_PAL_I    | \
+	V4L2_STD_PAL_M  |  V4L2_STD_PAL_N     |  V4L2_STD_PAL_H    | \
+	V4L2_STD_PAL_Nc)
+
+#define CX25821_BOARD_CONEXANT_ATHENA10 1
+#define MAX_VID_CHANNEL_NUM     12
+#define VID_CHANNEL_NUM 8
+#define CX25821_NR_INPUT 2
+
+struct cx25821_fmt {
+	char *name;
+	u32 fourcc;		/* v4l2 format id */
+	int depth;
+	int flags;
+	u32 cxformat;
+};
+
+struct cx25821_ctrl {
+	struct v4l2_queryctrl v;
+	u32 off;
+	u32 reg;
+	u32 mask;
+	u32 shift;
+};
+
+struct cx25821_tvnorm {
+	char *name;
+	v4l2_std_id id;
+	u32 cxiformat;
+	u32 cxoformat;
+};
+
+struct cx25821_fh {
+	struct cx25821_dev *dev;
+	enum v4l2_buf_type type;
+	int radio;
+	u32 resources;
+
+	enum v4l2_priority prio;
+
+	/* video overlay */
+	struct v4l2_window win;
+	struct v4l2_clip *clips;
+	unsigned int nclips;
+
+	/* video capture */
+	struct cx25821_fmt *fmt;
+	unsigned int width, height;
+	int channel_id;
+
+	/* vbi capture */
+	struct videobuf_queue vidq;
+	struct videobuf_queue vbiq;
+
+	/* H264 Encoder specifics ONLY */
+	struct videobuf_queue mpegq;
+	atomic_t v4l_reading;
+};
+
+enum cx25821_itype {
+	CX25821_VMUX_COMPOSITE = 1,
+	CX25821_VMUX_SVIDEO,
+	CX25821_VMUX_DEBUG,
+	CX25821_RADIO,
+};
+
+enum cx25821_src_sel_type {
+	CX25821_SRC_SEL_EXT_656_VIDEO = 0,
+	CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO
+};
+
+/* buffer for one video frame */
+struct cx25821_buffer {
+	/* common v4l buffer stuff -- must be first */
+	struct videobuf_buffer vb;
+
+	/* cx25821 specific */
+	unsigned int bpl;
+	struct btcx_riscmem risc;
+	struct cx25821_fmt *fmt;
+	u32 count;
+};
+
+struct cx25821_input {
+	enum cx25821_itype type;
+	unsigned int vmux;
+	u32 gpio0, gpio1, gpio2, gpio3;
+};
+
+enum port {
+	CX25821_UNDEFINED = 0,
+	CX25821_RAW,
+	CX25821_264
+};
+
+struct cx25821_board {
+	char *name;
+	enum port porta;
+	enum port portb;
+	enum port portc;
+	unsigned int tuner_type;
+	unsigned int radio_type;
+	unsigned char tuner_addr;
+	unsigned char radio_addr;
+
+	u32 clk_freq;
+	struct cx25821_input input[CX25821_NR_INPUT];
+};
+
+struct cx25821_subid {
+	u16 subvendor;
+	u16 subdevice;
+	u32 card;
+};
+
+struct cx25821_i2c {
+	struct cx25821_dev *dev;
+
+	int nr;
+
+	/* i2c i/o */
+	struct i2c_adapter i2c_adap;
+	struct i2c_algo_bit_data i2c_algo;
+	struct i2c_client i2c_client;
+	u32 i2c_rc;
+
+	/* cx25821 registers used for raw addess */
+	u32 i2c_period;
+	u32 reg_ctrl;
+	u32 reg_stat;
+	u32 reg_addr;
+	u32 reg_rdata;
+	u32 reg_wdata;
+};
+
+struct cx25821_dmaqueue {
+	struct list_head active;
+	struct list_head queued;
+	struct timer_list timeout;
+	struct btcx_riscmem stopper;
+	u32 count;
+};
+
+struct cx25821_data {
+	struct cx25821_dev *dev;
+	struct sram_channel *channel;
+};
+
+struct cx25821_channel {
+	struct v4l2_prio_state prio;
+
+	int ctl_bright;
+	int ctl_contrast;
+	int ctl_hue;
+	int ctl_saturation;
+	struct cx25821_data timeout_data;
+
+	struct video_device *video_dev;
+	struct cx25821_dmaqueue vidq;
+
+	struct sram_channel *sram_channels;
+
+	struct mutex lock;
+	int resources;
+
+	int pixel_formats;
+	int use_cif_resolution;
+	int cif_width;
+};
+
+struct cx25821_dev {
+	struct list_head devlist;
+	atomic_t refcount;
+	struct v4l2_device v4l2_dev;
+
+	/* pci stuff */
+	struct pci_dev *pci;
+	unsigned char pci_rev, pci_lat;
+	int pci_bus, pci_slot;
+	u32 base_io_addr;
+	u32 __iomem *lmmio;
+	u8 __iomem *bmmio;
+	int pci_irqmask;
+	int hwrevision;
+
+	u32 clk_freq;
+
+	/* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
+	struct cx25821_i2c i2c_bus[3];
+
+	int nr;
+	struct mutex lock;
+
+	struct cx25821_channel channels[MAX_VID_CHANNEL_NUM];
+
+	/* board details */
+	unsigned int board;
+	char name[32];
+
+	/* Analog video */
+	u32 resources;
+	unsigned int input;
+	u32 tvaudio;
+	v4l2_std_id tvnorm;
+	unsigned int tuner_type;
+	unsigned char tuner_addr;
+	unsigned int radio_type;
+	unsigned char radio_addr;
+	unsigned int has_radio;
+	unsigned int videc_type;
+	unsigned char videc_addr;
+	unsigned short _max_num_decoders;
+
+	/* Analog Audio Upstream */
+	int _audio_is_running;
+	int _audiopixel_format;
+	int _is_first_audio_frame;
+	int _audiofile_status;
+	int _audio_lines_count;
+	int _audioframe_count;
+	int _audio_upstream_channel;
+	int _last_index_irq;    /* The last interrupt index processed. */
+
+	__le32 *_risc_audio_jmp_addr;
+	__le32 *_risc_virt_start_addr;
+	__le32 *_risc_virt_addr;
+	dma_addr_t _risc_phys_addr;
+	dma_addr_t _risc_phys_start_addr;
+
+	unsigned int _audiorisc_size;
+	unsigned int _audiodata_buf_size;
+	__le32 *_audiodata_buf_virt_addr;
+	dma_addr_t _audiodata_buf_phys_addr;
+	char *_audiofilename;
+
+	/* V4l */
+	u32 freq;
+	struct video_device *vbi_dev;
+	struct video_device *radio_dev;
+	struct video_device *ioctl_dev;
+
+	spinlock_t slock;
+
+	/* Video Upstream */
+	int _line_size;
+	int _prog_cnt;
+	int _pixel_format;
+	int _is_first_frame;
+	int _is_running;
+	int _file_status;
+	int _lines_count;
+	int _frame_count;
+	int _channel_upstream_select;
+	unsigned int _risc_size;
+
+	__le32 *_dma_virt_start_addr;
+	__le32 *_dma_virt_addr;
+	dma_addr_t _dma_phys_addr;
+	dma_addr_t _dma_phys_start_addr;
+
+	unsigned int _data_buf_size;
+	__le32 *_data_buf_virt_addr;
+	dma_addr_t _data_buf_phys_addr;
+	char *_filename;
+	char *_defaultname;
+
+	int _line_size_ch2;
+	int _prog_cnt_ch2;
+	int _pixel_format_ch2;
+	int _is_first_frame_ch2;
+	int _is_running_ch2;
+	int _file_status_ch2;
+	int _lines_count_ch2;
+	int _frame_count_ch2;
+	int _channel2_upstream_select;
+	unsigned int _risc_size_ch2;
+
+	__le32 *_dma_virt_start_addr_ch2;
+	__le32 *_dma_virt_addr_ch2;
+	dma_addr_t _dma_phys_addr_ch2;
+	dma_addr_t _dma_phys_start_addr_ch2;
+
+	unsigned int _data_buf_size_ch2;
+	__le32 *_data_buf_virt_addr_ch2;
+	dma_addr_t _data_buf_phys_addr_ch2;
+	char *_filename_ch2;
+	char *_defaultname_ch2;
+
+	/* MPEG Encoder ONLY settings */
+	u32 cx23417_mailbox;
+	struct cx2341x_mpeg_params mpeg_params;
+	struct video_device *v4l_device;
+	atomic_t v4l_reader_count;
+	struct cx25821_tvnorm encodernorm;
+
+	u32 upstream_riscbuf_size;
+	u32 upstream_databuf_size;
+	u32 upstream_riscbuf_size_ch2;
+	u32 upstream_databuf_size_ch2;
+	u32 audio_upstream_riscbuf_size;
+	u32 audio_upstream_databuf_size;
+	int _isNTSC;
+	int _frame_index;
+	int _audioframe_index;
+	struct workqueue_struct *_irq_queues;
+	struct work_struct _irq_work_entry;
+	struct workqueue_struct *_irq_queues_ch2;
+	struct work_struct _irq_work_entry_ch2;
+	struct workqueue_struct *_irq_audio_queues;
+	struct work_struct _audio_work_entry;
+	char *input_filename;
+	char *input_filename_ch2;
+	int _frame_index_ch2;
+	int _isNTSC_ch2;
+	char *vid_stdname_ch2;
+	int pixel_format_ch2;
+	int channel_select_ch2;
+	int command_ch2;
+	char *input_audiofilename;
+	char *vid_stdname;
+	int pixel_format;
+	int channel_select;
+	int command;
+	int channel_opened;
+};
+
+struct upstream_user_struct {
+	char *input_filename;
+	char *vid_stdname;
+	int pixel_format;
+	int channel_select;
+	int command;
+};
+
+struct downstream_user_struct {
+	char *vid_stdname;
+	int pixel_format;
+	int cif_resolution_enable;
+	int cif_width;
+	int decoder_select;
+	int command;
+	int reg_address;
+	int reg_data;
+};
+
+extern struct upstream_user_struct *up_data;
+
+static inline struct cx25821_dev *get_cx25821(struct v4l2_device *v4l2_dev)
+{
+	return container_of(v4l2_dev, struct cx25821_dev, v4l2_dev);
+}
+
+#define cx25821_call_all(dev, o, f, args...) \
+	v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args)
+
+extern struct list_head cx25821_devlist;
+extern struct mutex cx25821_devlist_mutex;
+
+extern struct cx25821_board cx25821_boards[];
+extern struct cx25821_subid cx25821_subids[];
+
+#define SRAM_CH00  0		/* Video A */
+#define SRAM_CH01  1		/* Video B */
+#define SRAM_CH02  2		/* Video C */
+#define SRAM_CH03  3		/* Video D */
+#define SRAM_CH04  4		/* Video E */
+#define SRAM_CH05  5		/* Video F */
+#define SRAM_CH06  6		/* Video G */
+#define SRAM_CH07  7		/* Video H */
+
+#define SRAM_CH08  8		/* Audio A */
+#define SRAM_CH09  9		/* Video Upstream I */
+#define SRAM_CH10  10		/* Video Upstream J */
+#define SRAM_CH11  11		/* Audio Upstream AUD_CHANNEL_B */
+
+#define VID_UPSTREAM_SRAM_CHANNEL_I     SRAM_CH09
+#define VID_UPSTREAM_SRAM_CHANNEL_J     SRAM_CH10
+#define AUDIO_UPSTREAM_SRAM_CHANNEL_B   SRAM_CH11
+#define VIDEO_IOCTL_CH  11
+
+struct sram_channel {
+	char *name;
+	u32 i;
+	u32 cmds_start;
+	u32 ctrl_start;
+	u32 cdt;
+	u32 fifo_start;
+	u32 fifo_size;
+	u32 ptr1_reg;
+	u32 ptr2_reg;
+	u32 cnt1_reg;
+	u32 cnt2_reg;
+	u32 int_msk;
+	u32 int_stat;
+	u32 int_mstat;
+	u32 dma_ctl;
+	u32 gpcnt_ctl;
+	u32 gpcnt;
+	u32 aud_length;
+	u32 aud_cfg;
+	u32 fld_aud_fifo_en;
+	u32 fld_aud_risc_en;
+
+	/* For Upstream Video */
+	u32 vid_fmt_ctl;
+	u32 vid_active_ctl1;
+	u32 vid_active_ctl2;
+	u32 vid_cdt_size;
+
+	u32 vip_ctl;
+	u32 pix_frmt;
+	u32 jumponly;
+	u32 irq_bit;
+};
+extern struct sram_channel cx25821_sram_channels[];
+
+#define STATUS_SUCCESS         0
+#define STATUS_UNSUCCESSFUL    -1
+
+#define cx_read(reg)             readl(dev->lmmio + ((reg)>>2))
+#define cx_write(reg, value)     writel((value), dev->lmmio + ((reg)>>2))
+
+#define cx_andor(reg, mask, value) \
+	writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
+	((value) & (mask)), dev->lmmio+((reg)>>2))
+
+#define cx_set(reg, bit)          cx_andor((reg), (bit), (bit))
+#define cx_clear(reg, bit)        cx_andor((reg), (bit), 0)
+
+#define Set_GPIO_Bit(Bit)                       (1 << Bit)
+#define Clear_GPIO_Bit(Bit)                     (~(1 << Bit))
+
+#define CX25821_ERR(fmt, args...)			\
+	pr_err("(%d): " fmt, dev->board, ##args)
+#define CX25821_WARN(fmt, args...)			\
+	pr_warn("(%d): " fmt, dev->board, ##args)
+#define CX25821_INFO(fmt, args...)			\
+	pr_info("(%d): " fmt, dev->board, ##args)
+
+extern int cx25821_i2c_register(struct cx25821_i2c *bus);
+extern void cx25821_card_setup(struct cx25821_dev *dev);
+extern int cx25821_ir_init(struct cx25821_dev *dev);
+extern int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value);
+extern int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value);
+extern int cx25821_i2c_unregister(struct cx25821_i2c *bus);
+extern void cx25821_gpio_init(struct cx25821_dev *dev);
+extern void cx25821_set_gpiopin_direction(struct cx25821_dev *dev,
+					  int pin_number, int pin_logic_value);
+
+extern int medusa_video_init(struct cx25821_dev *dev);
+extern int medusa_set_videostandard(struct cx25821_dev *dev);
+extern void medusa_set_resolution(struct cx25821_dev *dev, int width,
+				  int decoder_select);
+extern int medusa_set_brightness(struct cx25821_dev *dev, int brightness,
+				 int decoder);
+extern int medusa_set_contrast(struct cx25821_dev *dev, int contrast,
+			       int decoder);
+extern int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder);
+extern int medusa_set_saturation(struct cx25821_dev *dev, int saturation,
+				 int decoder);
+
+extern int cx25821_sram_channel_setup(struct cx25821_dev *dev,
+				      struct sram_channel *ch, unsigned int bpl,
+				      u32 risc);
+
+extern int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+			       struct scatterlist *sglist,
+			       unsigned int top_offset,
+			       unsigned int bottom_offset,
+			       unsigned int bpl,
+			       unsigned int padding, unsigned int lines);
+extern int cx25821_risc_databuffer_audio(struct pci_dev *pci,
+					 struct btcx_riscmem *risc,
+					 struct scatterlist *sglist,
+					 unsigned int bpl,
+					 unsigned int lines, unsigned int lpi);
+extern void cx25821_free_buffer(struct videobuf_queue *q,
+				struct cx25821_buffer *buf);
+extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+				u32 reg, u32 mask, u32 value);
+extern void cx25821_sram_channel_dump(struct cx25821_dev *dev,
+				      struct sram_channel *ch);
+extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
+					    struct sram_channel *ch);
+
+extern struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci);
+extern void cx25821_print_irqbits(char *name, char *tag, char **strings,
+				  int len, u32 bits, u32 mask);
+extern void cx25821_dev_unregister(struct cx25821_dev *dev);
+extern int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev,
+					    struct sram_channel *ch,
+					    unsigned int bpl, u32 risc);
+
+extern int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev,
+					int channel_select, int pixel_format);
+extern int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev,
+					int channel_select, int pixel_format);
+extern int cx25821_audio_upstream_init(struct cx25821_dev *dev,
+				       int channel_select);
+extern void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev);
+extern void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev);
+extern void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev);
+extern void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev,
+					     struct upstream_user_struct
+					     *up_data);
+extern void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev,
+					     struct upstream_user_struct
+					     *up_data);
+extern void cx25821_start_upstream_audio(struct cx25821_dev *dev,
+					 struct upstream_user_struct *up_data);
+extern void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev);
+extern void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev);
+extern void cx25821_stop_upstream_audio(struct cx25821_dev *dev);
+extern int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev,
+					       struct sram_channel *ch,
+					       unsigned int bpl, u32 risc);
+extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel,
+				     u32 format);
+extern void cx25821_videoioctl_unregister(struct cx25821_dev *dev);
+extern struct video_device *cx25821_vdev_init(struct cx25821_dev *dev,
+					      struct pci_dev *pci,
+					      struct video_device *template,
+					      char *type);
+#endif
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-i2c.c linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-i2c.c
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,425 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *	Based on Steven Toth <stoth@linuxtv.org> cx23885 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821.h"
+#include <linux/i2c.h>
+
+static unsigned int i2c_debug;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+static unsigned int i2c_scan;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+#define dprintk(level, fmt, arg...)					\
+do {									\
+	if (i2c_debug >= level)						\
+		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg);	\
+} while (0)
+
+#define I2C_WAIT_DELAY 32
+#define I2C_WAIT_RETRY 64
+
+#define I2C_EXTEND  (1 << 3)
+#define I2C_NOSTOP  (1 << 4)
+
+static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	return cx_read(bus->reg_stat) & 0x01;
+}
+
+static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	return cx_read(bus->reg_stat) & 0x02 ? 1 : 0;
+}
+
+static int i2c_wait_done(struct i2c_adapter *i2c_adap)
+{
+	int count;
+
+	for (count = 0; count < I2C_WAIT_RETRY; count++) {
+		if (!i2c_is_busy(i2c_adap))
+			break;
+		udelay(I2C_WAIT_DELAY);
+	}
+
+	if (I2C_WAIT_RETRY == count)
+		return 0;
+
+	return 1;
+}
+
+static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+			 const struct i2c_msg *msg, int joined_rlen)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	u32 wdata, addr, ctrl;
+	int retval, cnt;
+
+	if (joined_rlen)
+		dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
+			msg->len, joined_rlen);
+	else
+		dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
+
+	/* Deal with i2c probe functions with zero payload */
+	if (msg->len == 0) {
+		cx_write(bus->reg_addr, msg->addr << 25);
+		cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2));
+
+		if (!i2c_wait_done(i2c_adap))
+			return -EIO;
+
+		if (!i2c_slave_did_ack(i2c_adap))
+			return -EIO;
+
+		dprintk(1, "%s(): returns 0\n", __func__);
+		return 0;
+	}
+
+	/* dev, reg + first byte */
+	addr = (msg->addr << 25) | msg->buf[0];
+	wdata = msg->buf[0];
+
+	ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
+
+	if (msg->len > 1)
+		ctrl |= I2C_NOSTOP | I2C_EXTEND;
+	else if (joined_rlen)
+		ctrl |= I2C_NOSTOP;
+
+	cx_write(bus->reg_addr, addr);
+	cx_write(bus->reg_wdata, wdata);
+	cx_write(bus->reg_ctrl, ctrl);
+
+	retval = i2c_wait_done(i2c_adap);
+	if (retval < 0)
+		goto err;
+
+	if (retval == 0)
+		goto eio;
+
+	if (i2c_debug) {
+		if (!(ctrl & I2C_NOSTOP))
+			printk(" >\n");
+	}
+
+	for (cnt = 1; cnt < msg->len; cnt++) {
+		/* following bytes */
+		wdata = msg->buf[cnt];
+		ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
+
+		if (cnt < msg->len - 1)
+			ctrl |= I2C_NOSTOP | I2C_EXTEND;
+		else if (joined_rlen)
+			ctrl |= I2C_NOSTOP;
+
+		cx_write(bus->reg_addr, addr);
+		cx_write(bus->reg_wdata, wdata);
+		cx_write(bus->reg_ctrl, ctrl);
+
+		retval = i2c_wait_done(i2c_adap);
+		if (retval < 0)
+			goto err;
+
+		if (retval == 0)
+			goto eio;
+
+		if (i2c_debug) {
+			dprintk(1, " %02x", msg->buf[cnt]);
+			if (!(ctrl & I2C_NOSTOP))
+				dprintk(1, " >\n");
+		}
+	}
+
+	return msg->len;
+
+eio:
+	retval = -EIO;
+err:
+	if (i2c_debug)
+		pr_err(" ERR: %d\n", retval);
+	return retval;
+}
+
+static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+			 const struct i2c_msg *msg, int joined)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	u32 ctrl, cnt;
+	int retval;
+
+	if (i2c_debug && !joined)
+		dprintk(1, "6-%s(msg->len=%d)\n", __func__, msg->len);
+
+	/* Deal with i2c probe functions with zero payload */
+	if (msg->len == 0) {
+		cx_write(bus->reg_addr, msg->addr << 25);
+		cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1);
+		if (!i2c_wait_done(i2c_adap))
+			return -EIO;
+		if (!i2c_slave_did_ack(i2c_adap))
+			return -EIO;
+
+		dprintk(1, "%s(): returns 0\n", __func__);
+		return 0;
+	}
+
+	if (i2c_debug) {
+		if (joined)
+			dprintk(1, " R");
+		else
+			dprintk(1, " <R %02x", (msg->addr << 1) + 1);
+	}
+
+	for (cnt = 0; cnt < msg->len; cnt++) {
+
+		ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
+
+		if (cnt < msg->len - 1)
+			ctrl |= I2C_NOSTOP | I2C_EXTEND;
+
+		cx_write(bus->reg_addr, msg->addr << 25);
+		cx_write(bus->reg_ctrl, ctrl);
+
+		retval = i2c_wait_done(i2c_adap);
+		if (retval < 0)
+			goto err;
+		if (retval == 0)
+			goto eio;
+		msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
+
+		if (i2c_debug) {
+			dprintk(1, " %02x", msg->buf[cnt]);
+			if (!(ctrl & I2C_NOSTOP))
+				dprintk(1, " >\n");
+		}
+	}
+
+	return msg->len;
+eio:
+	retval = -EIO;
+err:
+	if (i2c_debug)
+		pr_err(" ERR: %d\n", retval);
+	return retval;
+}
+
+static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	int i, retval = 0;
+
+	dprintk(1, "%s(num = %d)\n", __func__, num);
+
+	for (i = 0; i < num; i++) {
+		dprintk(1, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
+			__func__, num, msgs[i].addr, msgs[i].len);
+
+		if (msgs[i].flags & I2C_M_RD) {
+			/* read */
+			retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
+		} else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
+			   msgs[i].addr == msgs[i + 1].addr) {
+			/* write then read from same address */
+			retval =
+			    i2c_sendbytes(i2c_adap, &msgs[i], msgs[i + 1].len);
+
+			if (retval < 0)
+				goto err;
+			i++;
+			retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
+		} else {
+			/* write */
+			retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
+		}
+
+		if (retval < 0)
+			goto err;
+	}
+	return num;
+
+err:
+	return retval;
+}
+
+
+static u32 cx25821_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_EMUL |
+	    I2C_FUNC_I2C |
+	    I2C_FUNC_SMBUS_WORD_DATA |
+	    I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA;
+}
+
+static struct i2c_algorithm cx25821_i2c_algo_template = {
+	.master_xfer = i2c_xfer,
+	.functionality = cx25821_functionality,
+#ifdef NEED_ALGO_CONTROL
+	.algo_control = dummy_algo_control,
+#endif
+};
+
+static struct i2c_adapter cx25821_i2c_adap_template = {
+	.name = "cx25821",
+	.owner = THIS_MODULE,
+	.algo = &cx25821_i2c_algo_template,
+};
+
+static struct i2c_client cx25821_i2c_client_template = {
+	.name = "cx25821 internal",
+};
+
+/* init + register i2c algo-bit adapter */
+int cx25821_i2c_register(struct cx25821_i2c *bus)
+{
+	struct cx25821_dev *dev = bus->dev;
+
+	dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
+
+	memcpy(&bus->i2c_adap, &cx25821_i2c_adap_template,
+	       sizeof(bus->i2c_adap));
+	memcpy(&bus->i2c_algo, &cx25821_i2c_algo_template,
+	       sizeof(bus->i2c_algo));
+	memcpy(&bus->i2c_client, &cx25821_i2c_client_template,
+	       sizeof(bus->i2c_client));
+
+	bus->i2c_adap.dev.parent = &dev->pci->dev;
+
+	strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name));
+
+	bus->i2c_algo.data = bus;
+	bus->i2c_adap.algo_data = bus;
+	i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
+	i2c_add_adapter(&bus->i2c_adap);
+
+	bus->i2c_client.adapter = &bus->i2c_adap;
+
+	/* set up the I2c */
+	bus->i2c_client.addr = (0x88 >> 1);
+
+	return bus->i2c_rc;
+}
+
+int cx25821_i2c_unregister(struct cx25821_i2c *bus)
+{
+	i2c_del_adapter(&bus->i2c_adap);
+	return 0;
+}
+
+void cx25821_av_clk(struct cx25821_dev *dev, int enable)
+{
+	/* write 0 to bus 2 addr 0x144 via i2x_xfer() */
+	char buffer[3];
+	struct i2c_msg msg;
+	dprintk(1, "%s(enabled = %d)\n", __func__, enable);
+
+	/* Register 0x144 */
+	buffer[0] = 0x01;
+	buffer[1] = 0x44;
+	if (enable == 1)
+		buffer[2] = 0x05;
+	else
+		buffer[2] = 0x00;
+
+	msg.addr = 0x44;
+	msg.flags = I2C_M_TEN;
+	msg.len = 3;
+	msg.buf = buffer;
+
+	i2c_xfer(&dev->i2c_bus[0].i2c_adap, &msg, 1);
+}
+
+int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value)
+{
+	struct i2c_client *client = &bus->i2c_client;
+	int retval = 0;
+	int v = 0;
+	u8 addr[2] = { 0, 0 };
+	u8 buf[4] = { 0, 0, 0, 0 };
+
+	struct i2c_msg msgs[2] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 2,
+			.buf = addr,
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = 4,
+			.buf = buf,
+		}
+	};
+
+	addr[0] = (reg_addr >> 8);
+	addr[1] = (reg_addr & 0xff);
+	msgs[0].addr = 0x44;
+	msgs[1].addr = 0x44;
+
+	retval = i2c_xfer(client->adapter, msgs, 2);
+
+	v = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+	*value = v;
+
+	return v;
+}
+
+int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value)
+{
+	struct i2c_client *client = &bus->i2c_client;
+	int retval = 0;
+	u8 buf[6] = { 0, 0, 0, 0, 0, 0 };
+
+	struct i2c_msg msgs[1] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 6,
+			.buf = buf,
+		}
+	};
+
+	buf[0] = reg_addr >> 8;
+	buf[1] = reg_addr & 0xff;
+	buf[5] = (value >> 24) & 0xff;
+	buf[4] = (value >> 16) & 0xff;
+	buf[3] = (value >> 8) & 0xff;
+	buf[2] = value & 0xff;
+	client->flags = 0;
+	msgs[0].addr = 0x44;
+
+	retval = i2c_xfer(client->adapter, msgs, 1);
+
+	return retval;
+}
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-medusa-defines.h linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-medusa-defines.h
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-medusa-defines.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-medusa-defines.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,42 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 _MEDUSA_DEF_H_
+#define _MEDUSA_DEF_H_
+
+/* Video deocder that we supported */
+#define VDEC_A		0
+#define VDEC_B		1
+#define VDEC_C		2
+#define VDEC_D		3
+#define VDEC_E		4
+#define VDEC_F		5
+#define VDEC_G		6
+#define VDEC_H		7
+
+/* end of display sequence */
+#define END_OF_SEQ					0xF;
+
+/* registry string size */
+#define MAX_REGISTRY_SZ					40;
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-medusa-reg.h linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-medusa-reg.h
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-medusa-reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-medusa-reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,455 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 __MEDUSA_REGISTERS__
+#define __MEDUSA_REGISTERS__
+
+/* Serial Slave Registers */
+#define	HOST_REGISTER1				0x0000
+#define	HOST_REGISTER2				0x0001
+
+/* Chip Configuration Registers */
+#define	CHIP_CTRL					0x0100
+#define	AFE_AB_CTRL					0x0104
+#define	AFE_CD_CTRL					0x0108
+#define	AFE_EF_CTRL					0x010C
+#define	AFE_GH_CTRL					0x0110
+#define	DENC_AB_CTRL				0x0114
+#define	BYP_AB_CTRL					0x0118
+#define	MON_A_CTRL					0x011C
+#define	DISP_SEQ_A					0x0120
+#define	DISP_SEQ_B					0x0124
+#define	DISP_AB_CNT					0x0128
+#define	DISP_CD_CNT					0x012C
+#define	DISP_EF_CNT					0x0130
+#define	DISP_GH_CNT					0x0134
+#define	DISP_IJ_CNT					0x0138
+#define	PIN_OE_CTRL					0x013C
+#define	PIN_SPD_CTRL				0x0140
+#define	PIN_SPD_CTRL2				0x0144
+#define	IRQ_STAT_CTRL				0x0148
+#define	POWER_CTRL_AB				0x014C
+#define	POWER_CTRL_CD				0x0150
+#define	POWER_CTRL_EF				0x0154
+#define	POWER_CTRL_GH				0x0158
+#define	TUNE_CTRL					0x015C
+#define	BIAS_CTRL					0x0160
+#define	AFE_AB_DIAG_CTRL			0x0164
+#define	AFE_CD_DIAG_CTRL			0x0168
+#define	AFE_EF_DIAG_CTRL			0x016C
+#define	AFE_GH_DIAG_CTRL			0x0170
+#define	PLL_AB_DIAG_CTRL			0x0174
+#define	PLL_CD_DIAG_CTRL			0x0178
+#define	PLL_EF_DIAG_CTRL			0x017C
+#define	PLL_GH_DIAG_CTRL			0x0180
+#define	TEST_CTRL					0x0184
+#define	BIST_STAT					0x0188
+#define	BIST_STAT2					0x018C
+#define	BIST_VID_PLL_AB_STAT		0x0190
+#define	BIST_VID_PLL_CD_STAT		0x0194
+#define	BIST_VID_PLL_EF_STAT		0x0198
+#define	BIST_VID_PLL_GH_STAT		0x019C
+#define	DLL_DIAG_CTRL				0x01A0
+#define	DEV_CH_ID_CTRL				0x01A4
+#define	ABIST_CTRL_STATUS			0x01A8
+#define	ABIST_FREQ					0x01AC
+#define	ABIST_GOERT_SHIFT			0x01B0
+#define	ABIST_COEF12				0x01B4
+#define	ABIST_COEF34				0x01B8
+#define	ABIST_COEF56				0x01BC
+#define	ABIST_COEF7_SNR				0x01C0
+#define	ABIST_ADC_CAL				0x01C4
+#define	ABIST_BIN1_VGA0				0x01C8
+#define	ABIST_BIN2_VGA1				0x01CC
+#define	ABIST_BIN3_VGA2				0x01D0
+#define	ABIST_BIN4_VGA3				0x01D4
+#define	ABIST_BIN5_VGA4				0x01D8
+#define	ABIST_BIN6_VGA5				0x01DC
+#define	ABIST_BIN7_VGA6				0x0x1E0
+#define	ABIST_CLAMP_A				0x0x1E4
+#define	ABIST_CLAMP_B				0x0x1E8
+#define	ABIST_CLAMP_C				0x01EC
+#define	ABIST_CLAMP_D				0x01F0
+#define	ABIST_CLAMP_E				0x01F4
+#define	ABIST_CLAMP_F				0x01F8
+
+/*              Digital Video Encoder A Registers */
+#define	DENC_A_REG_1					0x0200
+#define	DENC_A_REG_2					0x0204
+#define	DENC_A_REG_3					0x0208
+#define	DENC_A_REG_4					0x020C
+#define	DENC_A_REG_5					0x0210
+#define	DENC_A_REG_6					0x0214
+#define	DENC_A_REG_7					0x0218
+#define	DENC_A_REG_8					0x021C
+
+/*      Digital Video Encoder B Registers */
+#define	DENC_B_REG_1					0x0300
+#define	DENC_B_REG_2					0x0304
+#define	DENC_B_REG_3					0x0308
+#define	DENC_B_REG_4					0x030C
+#define	DENC_B_REG_5					0x0310
+#define	DENC_B_REG_6					0x0314
+#define	DENC_B_REG_7					0x0318
+#define	DENC_B_REG_8					0x031C
+
+/*              Video Decoder A Registers */
+#define	MODE_CTRL						0x1000
+#define	OUT_CTRL1						0x1004
+#define	OUT_CTRL_NS						0x1008
+#define	GEN_STAT						0x100C
+#define	INT_STAT_MASK					0x1010
+#define	LUMA_CTRL						0x1014
+#define	CHROMA_CTRL						0x1018
+#define	CRUSH_CTRL						0x101C
+#define	HORIZ_TIM_CTRL					0x1020
+#define	VERT_TIM_CTRL					0x1024
+#define	MISC_TIM_CTRL					0x1028
+#define	FIELD_COUNT						0x102C
+#define	HSCALE_CTRL						0x1030
+#define	VSCALE_CTRL						0x1034
+#define	MAN_VGA_CTRL					0x1038
+#define	MAN_AGC_CTRL					0x103C
+#define	DFE_CTRL1						0x1040
+#define	DFE_CTRL2						0x1044
+#define	DFE_CTRL3						0x1048
+#define	PLL_CTRL						0x104C
+#define	PLL_CTRL_FAST					0x1050
+#define	HTL_CTRL						0x1054
+#define	SRC_CFG							0x1058
+#define	SC_STEP_SIZE					0x105C
+#define	SC_CONVERGE_CTRL				0x1060
+#define	SC_LOOP_CTRL					0x1064
+#define	COMB_2D_HFS_CFG					0x1068
+#define	COMB_2D_HFD_CFG					0x106C
+#define	COMB_2D_LF_CFG					0x1070
+#define	COMB_2D_BLEND					0x1074
+#define	COMB_MISC_CTRL					0x1078
+#define	COMB_FLAT_THRESH_CTRL			0x107C
+#define	COMB_TEST						0x1080
+#define	BP_MISC_CTRL					0x1084
+#define	VCR_DET_CTRL					0x1088
+#define	NOISE_DET_CTRL					0x108C
+#define	COMB_FLAT_NOISE_CTRL			0x1090
+#define	VERSION							0x11F8
+#define	SOFT_RST_CTRL					0x11FC
+
+/*      Video Decoder B Registers */
+#define	VDEC_B_MODE_CTRL				0x1200
+#define	VDEC_B_OUT_CTRL1				0x1204
+#define	VDEC_B_OUT_CTRL_NS				0x1208
+#define	VDEC_B_GEN_STAT					0x120C
+#define	VDEC_B_INT_STAT_MASK			0x1210
+#define	VDEC_B_LUMA_CTRL				0x1214
+#define	VDEC_B_CHROMA_CTRL				0x1218
+#define	VDEC_B_CRUSH_CTRL				0x121C
+#define	VDEC_B_HORIZ_TIM_CTRL			0x1220
+#define	VDEC_B_VERT_TIM_CTRL			0x1224
+#define	VDEC_B_MISC_TIM_CTRL			0x1228
+#define	VDEC_B_FIELD_COUNT				0x122C
+#define	VDEC_B_HSCALE_CTRL				0x1230
+#define	VDEC_B_VSCALE_CTRL				0x1234
+#define	VDEC_B_MAN_VGA_CTRL				0x1238
+#define	VDEC_B_MAN_AGC_CTRL				0x123C
+#define	VDEC_B_DFE_CTRL1				0x1240
+#define	VDEC_B_DFE_CTRL2				0x1244
+#define	VDEC_B_DFE_CTRL3				0x1248
+#define	VDEC_B_PLL_CTRL					0x124C
+#define	VDEC_B_PLL_CTRL_FAST			0x1250
+#define	VDEC_B_HTL_CTRL					0x1254
+#define	VDEC_B_SRC_CFG					0x1258
+#define	VDEC_B_SC_STEP_SIZE				0x125C
+#define	VDEC_B_SC_CONVERGE_CTRL			0x1260
+#define	VDEC_B_SC_LOOP_CTRL				0x1264
+#define	VDEC_B_COMB_2D_HFS_CFG			0x1268
+#define	VDEC_B_COMB_2D_HFD_CFG			0x126C
+#define	VDEC_B_COMB_2D_LF_CFG			0x1270
+#define	VDEC_B_COMB_2D_BLEND			0x1274
+#define	VDEC_B_COMB_MISC_CTRL			0x1278
+#define	VDEC_B_COMB_FLAT_THRESH_CTRL	0x127C
+#define	VDEC_B_COMB_TEST				0x1280
+#define	VDEC_B_BP_MISC_CTRL				0x1284
+#define	VDEC_B_VCR_DET_CTRL				0x1288
+#define	VDEC_B_NOISE_DET_CTRL			0x128C
+#define	VDEC_B_COMB_FLAT_NOISE_CTRL		0x1290
+#define	VDEC_B_VERSION					0x13F8
+#define	VDEC_B_SOFT_RST_CTRL			0x13FC
+
+/* Video Decoder C Registers */
+#define	VDEC_C_MODE_CTRL				0x1400
+#define	VDEC_C_OUT_CTRL1				0x1404
+#define	VDEC_C_OUT_CTRL_NS				0x1408
+#define	VDEC_C_GEN_STAT					0x140C
+#define	VDEC_C_INT_STAT_MASK			0x1410
+#define VDEC_C_LUMA_CTRL				0x1414
+#define VDEC_C_CHROMA_CTRL				0x1418
+#define	VDEC_C_CRUSH_CTRL				0x141C
+#define	VDEC_C_HORIZ_TIM_CTRL			0x1420
+#define	VDEC_C_VERT_TIM_CTRL			0x1424
+#define	VDEC_C_MISC_TIM_CTRL			0x1428
+#define	VDEC_C_FIELD_COUNT				0x142C
+#define	VDEC_C_HSCALE_CTRL				0x1430
+#define	VDEC_C_VSCALE_CTRL				0x1434
+#define	VDEC_C_MAN_VGA_CTRL				0x1438
+#define	VDEC_C_MAN_AGC_CTRL				0x143C
+#define	VDEC_C_DFE_CTRL1				0x1440
+#define	VDEC_C_DFE_CTRL2				0x1444
+#define	VDEC_C_DFE_CTRL3				0x1448
+#define	VDEC_C_PLL_CTRL					0x144C
+#define	VDEC_C_PLL_CTRL_FAST			0x1450
+#define	VDEC_C_HTL_CTRL					0x1454
+#define	VDEC_C_SRC_CFG					0x1458
+#define	VDEC_C_SC_STEP_SIZE				0x145C
+#define	VDEC_C_SC_CONVERGE_CTRL			0x1460
+#define	VDEC_C_SC_LOOP_CTRL				0x1464
+#define	VDEC_C_COMB_2D_HFS_CFG			0x1468
+#define	VDEC_C_COMB_2D_HFD_CFG			0x146C
+#define	VDEC_C_COMB_2D_LF_CFG			0x1470
+#define	VDEC_C_COMB_2D_BLEND			0x1474
+#define	VDEC_C_COMB_MISC_CTRL			0x1478
+#define	VDEC_C_COMB_FLAT_THRESH_CTRL	0x147C
+#define	VDEC_C_COMB_TEST				0x1480
+#define	VDEC_C_BP_MISC_CTRL				0x1484
+#define	VDEC_C_VCR_DET_CTRL				0x1488
+#define	VDEC_C_NOISE_DET_CTRL			0x148C
+#define	VDEC_C_COMB_FLAT_NOISE_CTRL		0x1490
+#define	VDEC_C_VERSION					0x15F8
+#define	VDEC_C_SOFT_RST_CTRL			0x15FC
+
+/* Video Decoder D Registers */
+#define VDEC_D_MODE_CTRL				0x1600
+#define VDEC_D_OUT_CTRL1				0x1604
+#define VDEC_D_OUT_CTRL_NS				0x1608
+#define VDEC_D_GEN_STAT					0x160C
+#define VDEC_D_INT_STAT_MASK			0x1610
+#define VDEC_D_LUMA_CTRL				0x1614
+#define VDEC_D_CHROMA_CTRL				0x1618
+#define VDEC_D_CRUSH_CTRL				0x161C
+#define VDEC_D_HORIZ_TIM_CTRL			0x1620
+#define VDEC_D_VERT_TIM_CTRL			0x1624
+#define VDEC_D_MISC_TIM_CTRL			0x1628
+#define VDEC_D_FIELD_COUNT				0x162C
+#define VDEC_D_HSCALE_CTRL				0x1630
+#define VDEC_D_VSCALE_CTRL				0x1634
+#define VDEC_D_MAN_VGA_CTRL				0x1638
+#define VDEC_D_MAN_AGC_CTRL				0x163C
+#define VDEC_D_DFE_CTRL1				0x1640
+#define VDEC_D_DFE_CTRL2				0x1644
+#define VDEC_D_DFE_CTRL3				0x1648
+#define VDEC_D_PLL_CTRL					0x164C
+#define VDEC_D_PLL_CTRL_FAST			0x1650
+#define VDEC_D_HTL_CTRL					0x1654
+#define VDEC_D_SRC_CFG					0x1658
+#define VDEC_D_SC_STEP_SIZE				0x165C
+#define VDEC_D_SC_CONVERGE_CTRL			0x1660
+#define VDEC_D_SC_LOOP_CTRL				0x1664
+#define VDEC_D_COMB_2D_HFS_CFG			0x1668
+#define VDEC_D_COMB_2D_HFD_CFG			0x166C
+#define VDEC_D_COMB_2D_LF_CFG			0x1670
+#define VDEC_D_COMB_2D_BLEND			0x1674
+#define VDEC_D_COMB_MISC_CTRL			0x1678
+#define VDEC_D_COMB_FLAT_THRESH_CTRL	0x167C
+#define VDEC_D_COMB_TEST				0x1680
+#define VDEC_D_BP_MISC_CTRL				0x1684
+#define VDEC_D_VCR_DET_CTRL				0x1688
+#define VDEC_D_NOISE_DET_CTRL			0x168C
+#define VDEC_D_COMB_FLAT_NOISE_CTRL		0x1690
+#define VDEC_D_VERSION					0x17F8
+#define VDEC_D_SOFT_RST_CTRL			0x17FC
+
+/* Video Decoder E Registers */
+#define	VDEC_E_MODE_CTRL				0x1800
+#define	VDEC_E_OUT_CTRL1				0x1804
+#define	VDEC_E_OUT_CTRL_NS				0x1808
+#define	VDEC_E_GEN_STAT					0x180C
+#define	VDEC_E_INT_STAT_MASK			0x1810
+#define	VDEC_E_LUMA_CTRL				0x1814
+#define	VDEC_E_CHROMA_CTRL				0x1818
+#define	VDEC_E_CRUSH_CTRL				0x181C
+#define	VDEC_E_HORIZ_TIM_CTRL			0x1820
+#define	VDEC_E_VERT_TIM_CTRL			0x1824
+#define	VDEC_E_MISC_TIM_CTRL			0x1828
+#define	VDEC_E_FIELD_COUNT				0x182C
+#define	VDEC_E_HSCALE_CTRL				0x1830
+#define	VDEC_E_VSCALE_CTRL				0x1834
+#define	VDEC_E_MAN_VGA_CTRL				0x1838
+#define	VDEC_E_MAN_AGC_CTRL				0x183C
+#define	VDEC_E_DFE_CTRL1				0x1840
+#define	VDEC_E_DFE_CTRL2				0x1844
+#define	VDEC_E_DFE_CTRL3				0x1848
+#define	VDEC_E_PLL_CTRL					0x184C
+#define	VDEC_E_PLL_CTRL_FAST			0x1850
+#define	VDEC_E_HTL_CTRL					0x1854
+#define	VDEC_E_SRC_CFG					0x1858
+#define	VDEC_E_SC_STEP_SIZE				0x185C
+#define	VDEC_E_SC_CONVERGE_CTRL			0x1860
+#define	VDEC_E_SC_LOOP_CTRL				0x1864
+#define	VDEC_E_COMB_2D_HFS_CFG			0x1868
+#define	VDEC_E_COMB_2D_HFD_CFG			0x186C
+#define	VDEC_E_COMB_2D_LF_CFG			0x1870
+#define	VDEC_E_COMB_2D_BLEND			0x1874
+#define	VDEC_E_COMB_MISC_CTRL			0x1878
+#define	VDEC_E_COMB_FLAT_THRESH_CTRL	0x187C
+#define	VDEC_E_COMB_TEST				0x1880
+#define	VDEC_E_BP_MISC_CTRL				0x1884
+#define	VDEC_E_VCR_DET_CTRL				0x1888
+#define	VDEC_E_NOISE_DET_CTRL			0x188C
+#define	VDEC_E_COMB_FLAT_NOISE_CTRL		0x1890
+#define	VDEC_E_VERSION					0x19F8
+#define	VDEC_E_SOFT_RST_CTRL			0x19FC
+
+/* Video Decoder F Registers */
+#define	VDEC_F_MODE_CTRL				0x1A00
+#define	VDEC_F_OUT_CTRL1				0x1A04
+#define	VDEC_F_OUT_CTRL_NS				0x1A08
+#define	VDEC_F_GEN_STAT					0x1A0C
+#define	VDEC_F_INT_STAT_MASK			0x1A10
+#define	VDEC_F_LUMA_CTRL				0x1A14
+#define	VDEC_F_CHROMA_CTRL				0x1A18
+#define	VDEC_F_CRUSH_CTRL				0x1A1C
+#define	VDEC_F_HORIZ_TIM_CTRL			0x1A20
+#define	VDEC_F_VERT_TIM_CTRL			0x1A24
+#define	VDEC_F_MISC_TIM_CTRL			0x1A28
+#define	VDEC_F_FIELD_COUNT				0x1A2C
+#define	VDEC_F_HSCALE_CTRL				0x1A30
+#define	VDEC_F_VSCALE_CTRL				0x1A34
+#define	VDEC_F_MAN_VGA_CTRL				0x1A38
+#define	VDEC_F_MAN_AGC_CTRL				0x1A3C
+#define	VDEC_F_DFE_CTRL1				0x1A40
+#define	VDEC_F_DFE_CTRL2				0x1A44
+#define	VDEC_F_DFE_CTRL3				0x1A48
+#define	VDEC_F_PLL_CTRL					0x1A4C
+#define	VDEC_F_PLL_CTRL_FAST			0x1A50
+#define	VDEC_F_HTL_CTRL					0x1A54
+#define	VDEC_F_SRC_CFG					0x1A58
+#define	VDEC_F_SC_STEP_SIZE				0x1A5C
+#define	VDEC_F_SC_CONVERGE_CTRL			0x1A60
+#define	VDEC_F_SC_LOOP_CTRL				0x1A64
+#define	VDEC_F_COMB_2D_HFS_CFG			0x1A68
+#define	VDEC_F_COMB_2D_HFD_CFG			0x1A6C
+#define	VDEC_F_COMB_2D_LF_CFG			0x1A70
+#define	VDEC_F_COMB_2D_BLEND			0x1A74
+#define	VDEC_F_COMB_MISC_CTRL			0x1A78
+#define	VDEC_F_COMB_FLAT_THRESH_CTRL	0x1A7C
+#define	VDEC_F_COMB_TEST				0x1A80
+#define	VDEC_F_BP_MISC_CTRL				0x1A84
+#define	VDEC_F_VCR_DET_CTRL				0x1A88
+#define	VDEC_F_NOISE_DET_CTRL			0x1A8C
+#define	VDEC_F_COMB_FLAT_NOISE_CTRL		0x1A90
+#define	VDEC_F_VERSION					0x1BF8
+#define	VDEC_F_SOFT_RST_CTRL			0x1BFC
+
+/* Video Decoder G Registers */
+#define	VDEC_G_MODE_CTRL				0x1C00
+#define	VDEC_G_OUT_CTRL1				0x1C04
+#define	VDEC_G_OUT_CTRL_NS				0x1C08
+#define	VDEC_G_GEN_STAT					0x1C0C
+#define	VDEC_G_INT_STAT_MASK			0x1C10
+#define	VDEC_G_LUMA_CTRL				0x1C14
+#define	VDEC_G_CHROMA_CTRL				0x1C18
+#define	VDEC_G_CRUSH_CTRL				0x1C1C
+#define	VDEC_G_HORIZ_TIM_CTRL			0x1C20
+#define	VDEC_G_VERT_TIM_CTRL			0x1C24
+#define	VDEC_G_MISC_TIM_CTRL			0x1C28
+#define	VDEC_G_FIELD_COUNT				0x1C2C
+#define	VDEC_G_HSCALE_CTRL				0x1C30
+#define	VDEC_G_VSCALE_CTRL				0x1C34
+#define	VDEC_G_MAN_VGA_CTRL				0x1C38
+#define	VDEC_G_MAN_AGC_CTRL				0x1C3C
+#define	VDEC_G_DFE_CTRL1				0x1C40
+#define	VDEC_G_DFE_CTRL2				0x1C44
+#define	VDEC_G_DFE_CTRL3				0x1C48
+#define	VDEC_G_PLL_CTRL					0x1C4C
+#define	VDEC_G_PLL_CTRL_FAST			0x1C50
+#define	VDEC_G_HTL_CTRL					0x1C54
+#define	VDEC_G_SRC_CFG					0x1C58
+#define	VDEC_G_SC_STEP_SIZE				0x1C5C
+#define	VDEC_G_SC_CONVERGE_CTRL			0x1C60
+#define	VDEC_G_SC_LOOP_CTRL				0x1C64
+#define	VDEC_G_COMB_2D_HFS_CFG			0x1C68
+#define	VDEC_G_COMB_2D_HFD_CFG			0x1C6C
+#define	VDEC_G_COMB_2D_LF_CFG			0x1C70
+#define	VDEC_G_COMB_2D_BLEND			0x1C74
+#define	VDEC_G_COMB_MISC_CTRL			0x1C78
+#define	VDEC_G_COMB_FLAT_THRESH_CTRL	0x1C7C
+#define	VDEC_G_COMB_TEST				0x1C80
+#define	VDEC_G_BP_MISC_CTRL				0x1C84
+#define	VDEC_G_VCR_DET_CTRL				0x1C88
+#define	VDEC_G_NOISE_DET_CTRL			0x1C8C
+#define	VDEC_G_COMB_FLAT_NOISE_CTRL		0x1C90
+#define	VDEC_G_VERSION					0x1DF8
+#define	VDEC_G_SOFT_RST_CTRL			0x1DFC
+
+/*              Video Decoder H Registers  */
+#define	VDEC_H_MODE_CTRL				0x1E00
+#define	VDEC_H_OUT_CTRL1				0x1E04
+#define	VDEC_H_OUT_CTRL_NS				0x1E08
+#define	VDEC_H_GEN_STAT					0x1E0C
+#define	VDEC_H_INT_STAT_MASK			0x1E1E
+#define	VDEC_H_LUMA_CTRL				0x1E14
+#define	VDEC_H_CHROMA_CTRL				0x1E18
+#define	VDEC_H_CRUSH_CTRL				0x1E1C
+#define	VDEC_H_HORIZ_TIM_CTRL			0x1E20
+#define	VDEC_H_VERT_TIM_CTRL			0x1E24
+#define	VDEC_H_MISC_TIM_CTRL			0x1E28
+#define	VDEC_H_FIELD_COUNT				0x1E2C
+#define	VDEC_H_HSCALE_CTRL				0x1E30
+#define	VDEC_H_VSCALE_CTRL				0x1E34
+#define	VDEC_H_MAN_VGA_CTRL				0x1E38
+#define	VDEC_H_MAN_AGC_CTRL				0x1E3C
+#define	VDEC_H_DFE_CTRL1				0x1E40
+#define	VDEC_H_DFE_CTRL2				0x1E44
+#define	VDEC_H_DFE_CTRL3				0x1E48
+#define	VDEC_H_PLL_CTRL					0x1E4C
+#define	VDEC_H_PLL_CTRL_FAST			0x1E50
+#define	VDEC_H_HTL_CTRL					0x1E54
+#define	VDEC_H_SRC_CFG					0x1E58
+#define	VDEC_H_SC_STEP_SIZE				0x1E5C
+#define	VDEC_H_SC_CONVERGE_CTRL			0x1E60
+#define	VDEC_H_SC_LOOP_CTRL				0x1E64
+#define	VDEC_H_COMB_2D_HFS_CFG			0x1E68
+#define	VDEC_H_COMB_2D_HFD_CFG			0x1E6C
+#define	VDEC_H_COMB_2D_LF_CFG			0x1E70
+#define	VDEC_H_COMB_2D_BLEND			0x1E74
+#define	VDEC_H_COMB_MISC_CTRL			0x1E78
+#define	VDEC_H_COMB_FLAT_THRESH_CTRL	0x1E7C
+#define	VDEC_H_COMB_TEST				0x1E80
+#define	VDEC_H_BP_MISC_CTRL				0x1E84
+#define	VDEC_H_VCR_DET_CTRL				0x1E88
+#define	VDEC_H_NOISE_DET_CTRL			0x1E8C
+#define	VDEC_H_COMB_FLAT_NOISE_CTRL		0x1E90
+#define	VDEC_H_VERSION					0x1FF8
+#define	VDEC_H_SOFT_RST_CTRL			0x1FFC
+
+/*****************************************************************************/
+/* LUMA_CTRL register fields */
+#define VDEC_A_BRITE_CTRL				0x1014
+#define VDEC_A_CNTRST_CTRL			0x1015
+#define VDEC_A_PEAK_SEL				0x1016
+
+/*****************************************************************************/
+/* CHROMA_CTRL register fields */
+#define VDEC_A_USAT_CTRL			0x1018
+#define VDEC_A_VSAT_CTRL			0x1019
+#define VDEC_A_HUE_CTRL				0x101A
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-medusa-video.c linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-medusa-video.c
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-medusa-video.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-medusa-video.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,872 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 "cx25821.h"
+#include "cx25821-medusa-video.h"
+#include "cx25821-biffuncs.h"
+
+/*
+ * medusa_enable_bluefield_output()
+ *
+ * Enable the generation of blue filed output if no video
+ *
+ */
+static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel,
+					   int enable)
+{
+	int ret_val = 1;
+	u32 value = 0;
+	u32 tmp = 0;
+	int out_ctrl = OUT_CTRL1;
+	int out_ctrl_ns = OUT_CTRL_NS;
+
+	switch (channel) {
+	default:
+	case VDEC_A:
+		break;
+	case VDEC_B:
+		out_ctrl = VDEC_B_OUT_CTRL1;
+		out_ctrl_ns = VDEC_B_OUT_CTRL_NS;
+		break;
+	case VDEC_C:
+		out_ctrl = VDEC_C_OUT_CTRL1;
+		out_ctrl_ns = VDEC_C_OUT_CTRL_NS;
+		break;
+	case VDEC_D:
+		out_ctrl = VDEC_D_OUT_CTRL1;
+		out_ctrl_ns = VDEC_D_OUT_CTRL_NS;
+		break;
+	case VDEC_E:
+		out_ctrl = VDEC_E_OUT_CTRL1;
+		out_ctrl_ns = VDEC_E_OUT_CTRL_NS;
+		return;
+	case VDEC_F:
+		out_ctrl = VDEC_F_OUT_CTRL1;
+		out_ctrl_ns = VDEC_F_OUT_CTRL_NS;
+		return;
+	case VDEC_G:
+		out_ctrl = VDEC_G_OUT_CTRL1;
+		out_ctrl_ns = VDEC_G_OUT_CTRL_NS;
+		return;
+	case VDEC_H:
+		out_ctrl = VDEC_H_OUT_CTRL1;
+		out_ctrl_ns = VDEC_H_OUT_CTRL_NS;
+		return;
+	}
+
+	value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp);
+	value &= 0xFFFFFF7F;	/* clear BLUE_FIELD_EN */
+	if (enable)
+		value |= 0x00000080;	/* set BLUE_FIELD_EN */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value);
+
+	value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp);
+	value &= 0xFFFFFF7F;
+	if (enable)
+		value |= 0x00000080;	/* set BLUE_FIELD_EN */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value);
+}
+
+static int medusa_initialize_ntsc(struct cx25821_dev *dev)
+{
+	int ret_val = 0;
+	int i = 0;
+	u32 value = 0;
+	u32 tmp = 0;
+
+	mutex_lock(&dev->lock);
+
+	for (i = 0; i < MAX_DECODERS; i++) {
+		/* set video format NTSC-M */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
+				     &tmp);
+		value &= 0xFFFFFFF0;
+		/* enable the fast locking mode bit[16] */
+		value |= 0x10001;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
+				      value);
+
+		/* resolution NTSC 720x480 */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     HORIZ_TIM_CTRL + (0x200 * i), &tmp);
+		value &= 0x00C00C00;
+		value |= 0x612D0074;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      HORIZ_TIM_CTRL + (0x200 * i), value);
+
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     VERT_TIM_CTRL + (0x200 * i), &tmp);
+		value &= 0x00C00C00;
+		value |= 0x1C1E001A;	/* vblank_cnt + 2 to get camera ID */
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      VERT_TIM_CTRL + (0x200 * i), value);
+
+		/* chroma subcarrier step size */
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      SC_STEP_SIZE + (0x200 * i), 0x43E00000);
+
+		/* enable VIP optional active */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     OUT_CTRL_NS + (0x200 * i), &tmp);
+		value &= 0xFFFBFFFF;
+		value |= 0x00040000;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      OUT_CTRL_NS + (0x200 * i), value);
+
+		/* enable VIP optional active (VIP_OPT_AL) for direct output. */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
+				     &tmp);
+		value &= 0xFFFBFFFF;
+		value |= 0x00040000;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
+				      value);
+
+		/*
+		 * clear VPRES_VERT_EN bit, fixes the chroma run away problem
+		 * when the input switching rate < 16 fields
+		*/
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     MISC_TIM_CTRL + (0x200 * i), &tmp);
+		/* disable special play detection */
+		value = setBitAtPos(value, 14);
+		value = clearBitAtPos(value, 15);
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      MISC_TIM_CTRL + (0x200 * i), value);
+
+		/* set vbi_gate_en to 0 */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
+				     &tmp);
+		value = clearBitAtPos(value, 29);
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
+				      value);
+
+		/* Enable the generation of blue field output if no video */
+		medusa_enable_bluefield_output(dev, i, 1);
+	}
+
+	for (i = 0; i < MAX_ENCODERS; i++) {
+		/* NTSC hclock */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_1 + (0x100 * i), &tmp);
+		value &= 0xF000FC00;
+		value |= 0x06B402D0;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_1 + (0x100 * i), value);
+
+		/* burst begin and burst end */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_2 + (0x100 * i), &tmp);
+		value &= 0xFF000000;
+		value |= 0x007E9054;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_2 + (0x100 * i), value);
+
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_3 + (0x100 * i), &tmp);
+		value &= 0xFC00FE00;
+		value |= 0x00EC00F0;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_3 + (0x100 * i), value);
+
+		/* set NTSC vblank, no phase alternation, 7.5 IRE pedestal */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_4 + (0x100 * i), &tmp);
+		value &= 0x00FCFFFF;
+		value |= 0x13020000;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_4 + (0x100 * i), value);
+
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_5 + (0x100 * i), &tmp);
+		value &= 0xFFFF0000;
+		value |= 0x0000E575;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_5 + (0x100 * i), value);
+
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_6 + (0x100 * i), 0x009A89C1);
+
+		/* Subcarrier Increment */
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_7 + (0x100 * i), 0x21F07C1F);
+	}
+
+	/* set picture resolutions */
+	/* 0 - 720 */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0);
+	/* 0 - 480 */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0);
+
+	/* set Bypass input format to NTSC 525 lines */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+	value |= 0x00080200;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+
+	mutex_unlock(&dev->lock);
+
+	return ret_val;
+}
+
+static int medusa_PALCombInit(struct cx25821_dev *dev, int dec)
+{
+	int ret_val = -1;
+	u32 value = 0, tmp = 0;
+
+	/* Setup for 2D threshold */
+	ret_val =
+	    cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG + (0x200 * dec),
+			      0x20002861);
+	ret_val =
+	    cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG + (0x200 * dec),
+			      0x20002861);
+	ret_val =
+	    cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG + (0x200 * dec),
+			      0x200A1023);
+
+	/* Setup flat chroma and luma thresholds */
+	value =
+	    cx25821_i2c_read(&dev->i2c_bus[0],
+			     COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp);
+	value &= 0x06230000;
+	ret_val =
+	    cx25821_i2c_write(&dev->i2c_bus[0],
+			      COMB_FLAT_THRESH_CTRL + (0x200 * dec), value);
+
+	/* set comb 2D blend */
+	ret_val =
+	    cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND + (0x200 * dec),
+			      0x210F0F0F);
+
+	/* COMB MISC CONTROL */
+	ret_val =
+	    cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL + (0x200 * dec),
+			      0x41120A7F);
+
+	return ret_val;
+}
+
+static int medusa_initialize_pal(struct cx25821_dev *dev)
+{
+	int ret_val = 0;
+	int i = 0;
+	u32 value = 0;
+	u32 tmp = 0;
+
+	mutex_lock(&dev->lock);
+
+	for (i = 0; i < MAX_DECODERS; i++) {
+		/* set video format PAL-BDGHI */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
+				     &tmp);
+		value &= 0xFFFFFFF0;
+		/* enable the fast locking mode bit[16] */
+		value |= 0x10004;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
+				      value);
+
+		/* resolution PAL 720x576 */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     HORIZ_TIM_CTRL + (0x200 * i), &tmp);
+		value &= 0x00C00C00;
+		value |= 0x632D007D;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      HORIZ_TIM_CTRL + (0x200 * i), value);
+
+		/* vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     VERT_TIM_CTRL + (0x200 * i), &tmp);
+		value &= 0x00C00C00;
+		value |= 0x28240026;	/* vblank_cnt + 2 to get camera ID */
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      VERT_TIM_CTRL + (0x200 * i), value);
+
+		/* chroma subcarrier step size */
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      SC_STEP_SIZE + (0x200 * i), 0x5411E2D0);
+
+		/* enable VIP optional active */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     OUT_CTRL_NS + (0x200 * i), &tmp);
+		value &= 0xFFFBFFFF;
+		value |= 0x00040000;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      OUT_CTRL_NS + (0x200 * i), value);
+
+		/* enable VIP optional active (VIP_OPT_AL) for direct output. */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
+				     &tmp);
+		value &= 0xFFFBFFFF;
+		value |= 0x00040000;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
+				      value);
+
+		/*
+		 * clear VPRES_VERT_EN bit, fixes the chroma run away problem
+		 * when the input switching rate < 16 fields
+		 */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     MISC_TIM_CTRL + (0x200 * i), &tmp);
+		/* disable special play detection */
+		value = setBitAtPos(value, 14);
+		value = clearBitAtPos(value, 15);
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      MISC_TIM_CTRL + (0x200 * i), value);
+
+		/* set vbi_gate_en to 0 */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
+				     &tmp);
+		value = clearBitAtPos(value, 29);
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
+				      value);
+
+		medusa_PALCombInit(dev, i);
+
+		/* Enable the generation of blue field output if no video */
+		medusa_enable_bluefield_output(dev, i, 1);
+	}
+
+	for (i = 0; i < MAX_ENCODERS; i++) {
+		/* PAL hclock */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_1 + (0x100 * i), &tmp);
+		value &= 0xF000FC00;
+		value |= 0x06C002D0;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_1 + (0x100 * i), value);
+
+		/* burst begin and burst end */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_2 + (0x100 * i), &tmp);
+		value &= 0xFF000000;
+		value |= 0x007E9754;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_2 + (0x100 * i), value);
+
+		/* hblank and vactive */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_3 + (0x100 * i), &tmp);
+		value &= 0xFC00FE00;
+		value |= 0x00FC0120;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_3 + (0x100 * i), value);
+
+		/* set PAL vblank, phase alternation, 0 IRE pedestal */
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_4 + (0x100 * i), &tmp);
+		value &= 0x00FCFFFF;
+		value |= 0x14010000;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_4 + (0x100 * i), value);
+
+		value =
+		    cx25821_i2c_read(&dev->i2c_bus[0],
+				     DENC_A_REG_5 + (0x100 * i), &tmp);
+		value &= 0xFFFF0000;
+		value |= 0x0000F078;
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_5 + (0x100 * i), value);
+
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_6 + (0x100 * i), 0x00A493CF);
+
+		/* Subcarrier Increment */
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      DENC_A_REG_7 + (0x100 * i), 0x2A098ACB);
+	}
+
+	/* set picture resolutions */
+	/* 0 - 720 */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0);
+	/* 0 - 576 */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0);
+
+	/* set Bypass input format to PAL 625 lines */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+	value &= 0xFFF7FDFF;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+
+	mutex_unlock(&dev->lock);
+
+	return ret_val;
+}
+
+int medusa_set_videostandard(struct cx25821_dev *dev)
+{
+	int status = STATUS_SUCCESS;
+	u32 value = 0, tmp = 0;
+
+	if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+		status = medusa_initialize_pal(dev);
+	else
+		status = medusa_initialize_ntsc(dev);
+
+	/* Enable DENC_A output */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp);
+	value = setBitAtPos(value, 4);
+	status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value);
+
+	/* Enable DENC_B output */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp);
+	value = setBitAtPos(value, 4);
+	status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value);
+
+	return status;
+}
+
+void medusa_set_resolution(struct cx25821_dev *dev, int width,
+			   int decoder_select)
+{
+	int decoder = 0;
+	int decoder_count = 0;
+	int ret_val = 0;
+	u32 hscale = 0x0;
+	u32 vscale = 0x0;
+	const int MAX_WIDTH = 720;
+
+	mutex_lock(&dev->lock);
+
+	/* validate the width - cannot be negative */
+	if (width > MAX_WIDTH) {
+		pr_info("%s(): width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n",
+			__func__, width, MAX_WIDTH);
+		width = MAX_WIDTH;
+	}
+
+	if (decoder_select <= 7 && decoder_select >= 0) {
+		decoder = decoder_select;
+		decoder_count = decoder_select + 1;
+	} else {
+		decoder = 0;
+		decoder_count = _num_decoders;
+	}
+
+	switch (width) {
+	case 320:
+		hscale = 0x13E34B;
+		vscale = 0x0;
+		break;
+
+	case 352:
+		hscale = 0x10A273;
+		vscale = 0x0;
+		break;
+
+	case 176:
+		hscale = 0x3115B2;
+		vscale = 0x1E00;
+		break;
+
+	case 160:
+		hscale = 0x378D84;
+		vscale = 0x1E00;
+		break;
+
+	default:		/* 720 */
+		hscale = 0x0;
+		vscale = 0x0;
+		break;
+	}
+
+	for (; decoder < decoder_count; decoder++) {
+		/* write scaling values for each decoder */
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      HSCALE_CTRL + (0x200 * decoder), hscale);
+		ret_val =
+		    cx25821_i2c_write(&dev->i2c_bus[0],
+				      VSCALE_CTRL + (0x200 * decoder), vscale);
+	}
+
+	mutex_unlock(&dev->lock);
+}
+
+static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder,
+				       int duration)
+{
+	int ret_val = 0;
+	u32 fld_cnt = 0;
+	u32 tmp = 0;
+	u32 disp_cnt_reg = DISP_AB_CNT;
+
+	mutex_lock(&dev->lock);
+
+	/* no support */
+	if (decoder < VDEC_A && decoder > VDEC_H) {
+		mutex_unlock(&dev->lock);
+		return;
+	}
+
+	switch (decoder) {
+	default:
+		break;
+	case VDEC_C:
+	case VDEC_D:
+		disp_cnt_reg = DISP_CD_CNT;
+		break;
+	case VDEC_E:
+	case VDEC_F:
+		disp_cnt_reg = DISP_EF_CNT;
+		break;
+	case VDEC_G:
+	case VDEC_H:
+		disp_cnt_reg = DISP_GH_CNT;
+		break;
+	}
+
+	_display_field_cnt[decoder] = duration;
+
+	/* update hardware */
+	fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp);
+
+	if (!(decoder % 2)) {	/* EVEN decoder */
+		fld_cnt &= 0xFFFF0000;
+		fld_cnt |= duration;
+	} else {
+		fld_cnt &= 0x0000FFFF;
+		fld_cnt |= ((u32) duration) << 16;
+	}
+
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt);
+
+	mutex_unlock(&dev->lock);
+}
+
+/* Map to Medusa register setting */
+static int mapM(int srcMin,
+		int srcMax, int srcVal, int dstMin, int dstMax, int *dstVal)
+{
+	int numerator;
+	int denominator;
+	int quotient;
+
+	if ((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax))
+		return -1;
+	/*
+	 * This is the overall expression used:
+	 * *dstVal =
+	 *   (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin;
+	 * but we need to account for rounding so below we use the modulus
+	 * operator to find the remainder and increment if necessary.
+	 */
+	numerator = (srcVal - srcMin) * (dstMax - dstMin);
+	denominator = srcMax - srcMin;
+	quotient = numerator / denominator;
+
+	if (2 * (numerator % denominator) >= denominator)
+		quotient++;
+
+	*dstVal = quotient + dstMin;
+
+	return 0;
+}
+
+static unsigned long convert_to_twos(long numeric, unsigned long bits_len)
+{
+	unsigned char temp;
+
+	if (numeric >= 0)
+		return numeric;
+	else {
+		temp = ~(abs(numeric) & 0xFF);
+		temp += 1;
+		return temp;
+	}
+}
+
+int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder)
+{
+	int ret_val = 0;
+	int value = 0;
+	u32 val = 0, tmp = 0;
+
+	mutex_lock(&dev->lock);
+	if ((brightness > VIDEO_PROCAMP_MAX)
+	    || (brightness < VIDEO_PROCAMP_MIN)) {
+		mutex_unlock(&dev->lock);
+		return -1;
+	}
+	ret_val =
+	    mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness,
+		 SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
+	value = convert_to_twos(value, 8);
+	val =
+	    cx25821_i2c_read(&dev->i2c_bus[0],
+			     VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp);
+	val &= 0xFFFFFF00;
+	ret_val |=
+	    cx25821_i2c_write(&dev->i2c_bus[0],
+			      VDEC_A_BRITE_CTRL + (0x200 * decoder),
+			      val | value);
+	mutex_unlock(&dev->lock);
+	return ret_val;
+}
+
+int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder)
+{
+	int ret_val = 0;
+	int value = 0;
+	u32 val = 0, tmp = 0;
+
+	mutex_lock(&dev->lock);
+
+	if ((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) {
+		mutex_unlock(&dev->lock);
+		return -1;
+	}
+
+	ret_val =
+	    mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast,
+		 UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
+	val =
+	    cx25821_i2c_read(&dev->i2c_bus[0],
+			     VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp);
+	val &= 0xFFFFFF00;
+	ret_val |=
+	    cx25821_i2c_write(&dev->i2c_bus[0],
+			      VDEC_A_CNTRST_CTRL + (0x200 * decoder),
+			      val | value);
+
+	mutex_unlock(&dev->lock);
+	return ret_val;
+}
+
+int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder)
+{
+	int ret_val = 0;
+	int value = 0;
+	u32 val = 0, tmp = 0;
+
+	mutex_lock(&dev->lock);
+
+	if ((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) {
+		mutex_unlock(&dev->lock);
+		return -1;
+	}
+
+	ret_val =
+	    mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, SIGNED_BYTE_MIN,
+		 SIGNED_BYTE_MAX, &value);
+
+	value = convert_to_twos(value, 8);
+	val =
+	    cx25821_i2c_read(&dev->i2c_bus[0],
+			     VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp);
+	val &= 0xFFFFFF00;
+
+	ret_val |=
+	    cx25821_i2c_write(&dev->i2c_bus[0],
+			      VDEC_A_HUE_CTRL + (0x200 * decoder), val | value);
+
+	mutex_unlock(&dev->lock);
+	return ret_val;
+}
+
+int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder)
+{
+	int ret_val = 0;
+	int value = 0;
+	u32 val = 0, tmp = 0;
+
+	mutex_lock(&dev->lock);
+
+	if ((saturation > VIDEO_PROCAMP_MAX)
+	    || (saturation < VIDEO_PROCAMP_MIN)) {
+		mutex_unlock(&dev->lock);
+		return -1;
+	}
+
+	ret_val =
+	    mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation,
+		 UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
+
+	val =
+	    cx25821_i2c_read(&dev->i2c_bus[0],
+			     VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp);
+	val &= 0xFFFFFF00;
+	ret_val |=
+	    cx25821_i2c_write(&dev->i2c_bus[0],
+			      VDEC_A_USAT_CTRL + (0x200 * decoder),
+			      val | value);
+
+	val =
+	    cx25821_i2c_read(&dev->i2c_bus[0],
+			     VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp);
+	val &= 0xFFFFFF00;
+	ret_val |=
+	    cx25821_i2c_write(&dev->i2c_bus[0],
+			      VDEC_A_VSAT_CTRL + (0x200 * decoder),
+			      val | value);
+
+	mutex_unlock(&dev->lock);
+	return ret_val;
+}
+
+/* Program the display sequence and monitor output. */
+
+int medusa_video_init(struct cx25821_dev *dev)
+{
+	u32 value = 0, tmp = 0;
+	int ret_val = 0;
+	int i = 0;
+
+	mutex_lock(&dev->lock);
+
+	_num_decoders = dev->_max_num_decoders;
+
+	/* disable Auto source selection on all video decoders */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
+	value &= 0xFFFFF0FF;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
+
+	if (ret_val < 0)
+		goto error;
+
+	/* Turn off Master source switch enable */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
+	value &= 0xFFFFFFDF;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
+
+	if (ret_val < 0)
+		goto error;
+
+	mutex_unlock(&dev->lock);
+
+	for (i = 0; i < _num_decoders; i++)
+		medusa_set_decoderduration(dev, i, _display_field_cnt[i]);
+
+	mutex_lock(&dev->lock);
+
+	/* Select monitor as DENC A input, power up the DAC */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp);
+	value &= 0xFF70FF70;
+	value |= 0x00090008;	/* set en_active */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value);
+
+	if (ret_val < 0)
+		goto error;
+
+	/* enable input is VIP/656 */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+	value |= 0x00040100;	/* enable VIP */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+
+	if (ret_val < 0)
+		goto error;
+
+	/* select AFE clock to output mode */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
+	value &= 0x83FFFFFF;
+	ret_val =
+	   cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL,
+			     value | 0x10000000);
+
+	if (ret_val < 0)
+		goto error;
+
+	/* Turn on all of the data out and control output pins. */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp);
+	value &= 0xFEF0FE00;
+	if (_num_decoders == MAX_DECODERS) {
+		/*
+		 * Note: The octal board does not support control pins(bit16-19)
+		 * These bits are ignored in the octal board.
+		 *
+		 * disable VDEC A-C port, default to Mobilygen Interface
+		 */
+		value |= 0x010001F8;
+	} else {
+		/* disable VDEC A-C port, default to Mobilygen Interface */
+		value |= 0x010F0108;
+	}
+
+	value |= 7;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value);
+
+	if (ret_val < 0)
+		goto error;
+
+
+	mutex_unlock(&dev->lock);
+
+	ret_val = medusa_set_videostandard(dev);
+
+	return ret_val;
+
+error:
+	mutex_unlock(&dev->lock);
+	return ret_val;
+}
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-medusa-video.h linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-medusa-video.h
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-medusa-video.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-medusa-video.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,49 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 _MEDUSA_VIDEO_H
+#define _MEDUSA_VIDEO_H
+
+#include "cx25821-medusa-defines.h"
+
+/* Color control constants */
+#define VIDEO_PROCAMP_MIN                 0
+#define VIDEO_PROCAMP_MAX                 10000
+#define UNSIGNED_BYTE_MIN                 0
+#define UNSIGNED_BYTE_MAX                 0xFF
+#define SIGNED_BYTE_MIN                   -128
+#define SIGNED_BYTE_MAX                   127
+
+/* Default video color settings */
+#define SHARPNESS_DEFAULT                 50
+#define SATURATION_DEFAULT              5000
+#define BRIGHTNESS_DEFAULT              6200
+#define CONTRAST_DEFAULT                5000
+#define HUE_DEFAULT                     5000
+
+unsigned short _num_decoders;
+unsigned short _num_cameras;
+
+unsigned int _video_standard;
+int _display_field_cnt[MAX_DECODERS];
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-reg.h linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-reg.h
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1592 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 __CX25821_REGISTERS__
+#define __CX25821_REGISTERS__
+
+/* Risc Instructions */
+#define RISC_CNT_INC	 0x00010000
+#define RISC_CNT_RESET	 0x00030000
+#define RISC_IRQ1		 0x01000000
+#define RISC_IRQ2		 0x02000000
+#define RISC_EOL		 0x04000000
+#define RISC_SOL		 0x08000000
+#define RISC_WRITE		 0x10000000
+#define RISC_SKIP		 0x20000000
+#define RISC_JUMP		 0x70000000
+#define RISC_SYNC		 0x80000000
+#define RISC_RESYNC		 0x80008000
+#define RISC_READ		 0x90000000
+#define RISC_WRITERM	 0xB0000000
+#define RISC_WRITECM	 0xC0000000
+#define RISC_WRITECR	 0xD0000000
+#define RISC_WRITEC		 0x50000000
+#define RISC_READC		 0xA0000000
+
+#define RISC_SYNC_ODD		 0x00000000
+#define RISC_SYNC_EVEN		 0x00000200
+#define RISC_SYNC_ODD_VBI	 0x00000006
+#define RISC_SYNC_EVEN_VBI	 0x00000207
+#define RISC_NOOP			 0xF0000000
+
+/*****************************************************************************
+* ASB SRAM
+ *****************************************************************************/
+#define  TX_SRAM                   0x000000	/* Transmit SRAM */
+
+/*****************************************************************************/
+#define  RX_RAM                    0x010000	/* Receive SRAM */
+
+/*****************************************************************************
+* Application Layer (AL)
+ *****************************************************************************/
+#define  DEV_CNTRL2                0x040000	/* Device control */
+#define  FLD_RUN_RISC              0x00000020
+
+/* ***************************************************************************** */
+#define  PCI_INT_MSK               0x040010	/* PCI interrupt mask */
+#define  PCI_INT_STAT              0x040014	/* PCI interrupt status */
+#define  PCI_INT_MSTAT             0x040018	/* PCI interrupt masked status */
+#define  FLD_HAMMERHEAD_INT        (1 << 27)
+#define  FLD_UART_INT              (1 << 26)
+#define  FLD_IRQN_INT              (1 << 25)
+#define  FLD_TM_INT                (1 << 28)
+#define  FLD_I2C_3_RACK            (1 << 27)
+#define  FLD_I2C_3_INT             (1 << 26)
+#define  FLD_I2C_2_RACK            (1 << 25)
+#define  FLD_I2C_2_INT             (1 << 24)
+#define  FLD_I2C_1_RACK            (1 << 23)
+#define  FLD_I2C_1_INT             (1 << 22)
+
+#define  FLD_APB_DMA_BERR_INT      (1 << 21)
+#define  FLD_AL_WR_BERR_INT        (1 << 20)
+#define  FLD_AL_RD_BERR_INT        (1 << 19)
+#define  FLD_RISC_WR_BERR_INT      (1 << 18)
+#define  FLD_RISC_RD_BERR_INT      (1 << 17)
+
+#define  FLD_VID_I_INT             (1 << 8)
+#define  FLD_VID_H_INT             (1 << 7)
+#define  FLD_VID_G_INT             (1 << 6)
+#define  FLD_VID_F_INT             (1 << 5)
+#define  FLD_VID_E_INT             (1 << 4)
+#define  FLD_VID_D_INT             (1 << 3)
+#define  FLD_VID_C_INT             (1 << 2)
+#define  FLD_VID_B_INT             (1 << 1)
+#define  FLD_VID_A_INT             (1 << 0)
+
+/* ***************************************************************************** */
+#define  VID_A_INT_MSK             0x040020	/* Video A interrupt mask */
+#define  VID_A_INT_STAT            0x040024	/* Video A interrupt status */
+#define  VID_A_INT_MSTAT           0x040028	/* Video A interrupt masked status */
+#define  VID_A_INT_SSTAT           0x04002C	/* Video A interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_B_INT_MSK             0x040030	/* Video B interrupt mask */
+#define  VID_B_INT_STAT            0x040034	/* Video B interrupt status */
+#define  VID_B_INT_MSTAT           0x040038	/* Video B interrupt masked status */
+#define  VID_B_INT_SSTAT           0x04003C	/* Video B interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_C_INT_MSK             0x040040	/* Video C interrupt mask */
+#define  VID_C_INT_STAT            0x040044	/* Video C interrupt status */
+#define  VID_C_INT_MSTAT           0x040048	/* Video C interrupt masked status */
+#define  VID_C_INT_SSTAT           0x04004C	/* Video C interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_D_INT_MSK             0x040050	/* Video D interrupt mask */
+#define  VID_D_INT_STAT            0x040054	/* Video D interrupt status */
+#define  VID_D_INT_MSTAT           0x040058	/* Video D interrupt masked status */
+#define  VID_D_INT_SSTAT           0x04005C	/* Video D interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_E_INT_MSK             0x040060	/* Video E interrupt mask */
+#define  VID_E_INT_STAT            0x040064	/* Video E interrupt status */
+#define  VID_E_INT_MSTAT           0x040068	/* Video E interrupt masked status */
+#define  VID_E_INT_SSTAT           0x04006C	/* Video E interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_F_INT_MSK             0x040070	/* Video F interrupt mask */
+#define  VID_F_INT_STAT            0x040074	/* Video F interrupt status */
+#define  VID_F_INT_MSTAT           0x040078	/* Video F interrupt masked status */
+#define  VID_F_INT_SSTAT           0x04007C	/* Video F interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_G_INT_MSK             0x040080	/* Video G interrupt mask */
+#define  VID_G_INT_STAT            0x040084	/* Video G interrupt status */
+#define  VID_G_INT_MSTAT           0x040088	/* Video G interrupt masked status */
+#define  VID_G_INT_SSTAT           0x04008C	/* Video G interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_H_INT_MSK             0x040090	/* Video H interrupt mask */
+#define  VID_H_INT_STAT            0x040094	/* Video H interrupt status */
+#define  VID_H_INT_MSTAT           0x040098	/* Video H interrupt masked status */
+#define  VID_H_INT_SSTAT           0x04009C	/* Video H interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_I_INT_MSK             0x0400A0	/* Video I interrupt mask */
+#define  VID_I_INT_STAT            0x0400A4	/* Video I interrupt status */
+#define  VID_I_INT_MSTAT           0x0400A8	/* Video I interrupt masked status */
+#define  VID_I_INT_SSTAT           0x0400AC	/* Video I interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_J_INT_MSK             0x0400B0	/* Video J interrupt mask */
+#define  VID_J_INT_STAT            0x0400B4	/* Video J interrupt status */
+#define  VID_J_INT_MSTAT           0x0400B8	/* Video J interrupt masked status */
+#define  VID_J_INT_SSTAT           0x0400BC	/* Video J interrupt set status */
+
+#define  FLD_VID_SRC_OPC_ERR       0x00020000
+#define  FLD_VID_DST_OPC_ERR       0x00010000
+#define  FLD_VID_SRC_SYNC          0x00002000
+#define  FLD_VID_DST_SYNC          0x00001000
+#define  FLD_VID_SRC_UF            0x00000200
+#define  FLD_VID_DST_OF            0x00000100
+#define  FLD_VID_SRC_RISC2         0x00000020
+#define  FLD_VID_DST_RISC2         0x00000010
+#define  FLD_VID_SRC_RISC1         0x00000002
+#define  FLD_VID_DST_RISC1         0x00000001
+#define  FLD_VID_SRC_ERRORS		(FLD_VID_SRC_OPC_ERR | FLD_VID_SRC_SYNC | FLD_VID_SRC_UF)
+#define  FLD_VID_DST_ERRORS		(FLD_VID_DST_OPC_ERR | FLD_VID_DST_SYNC | FLD_VID_DST_OF)
+
+/* ***************************************************************************** */
+#define  AUD_A_INT_MSK             0x0400C0	/* Audio Int interrupt mask */
+#define  AUD_A_INT_STAT            0x0400C4	/* Audio Int interrupt status */
+#define  AUD_A_INT_MSTAT           0x0400C8	/* Audio Int interrupt masked status */
+#define  AUD_A_INT_SSTAT           0x0400CC	/* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  AUD_B_INT_MSK             0x0400D0	/* Audio Int interrupt mask */
+#define  AUD_B_INT_STAT            0x0400D4	/* Audio Int interrupt status */
+#define  AUD_B_INT_MSTAT           0x0400D8	/* Audio Int interrupt masked status */
+#define  AUD_B_INT_SSTAT           0x0400DC	/* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  AUD_C_INT_MSK             0x0400E0	/* Audio Int interrupt mask */
+#define  AUD_C_INT_STAT            0x0400E4	/* Audio Int interrupt status */
+#define  AUD_C_INT_MSTAT           0x0400E8	/* Audio Int interrupt masked status */
+#define  AUD_C_INT_SSTAT           0x0400EC	/* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  AUD_D_INT_MSK             0x0400F0	/* Audio Int interrupt mask */
+#define  AUD_D_INT_STAT            0x0400F4	/* Audio Int interrupt status */
+#define  AUD_D_INT_MSTAT           0x0400F8	/* Audio Int interrupt masked status */
+#define  AUD_D_INT_SSTAT           0x0400FC	/* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  AUD_E_INT_MSK             0x040100	/* Audio Int interrupt mask */
+#define  AUD_E_INT_STAT            0x040104	/* Audio Int interrupt status */
+#define  AUD_E_INT_MSTAT           0x040108	/* Audio Int interrupt masked status */
+#define  AUD_E_INT_SSTAT           0x04010C	/* Audio Int interrupt set status */
+
+#define  FLD_AUD_SRC_OPC_ERR       0x00020000
+#define  FLD_AUD_DST_OPC_ERR       0x00010000
+#define  FLD_AUD_SRC_SYNC          0x00002000
+#define  FLD_AUD_DST_SYNC          0x00001000
+#define  FLD_AUD_SRC_OF            0x00000200
+#define  FLD_AUD_DST_OF            0x00000100
+#define  FLD_AUD_SRC_RISCI2        0x00000020
+#define  FLD_AUD_DST_RISCI2        0x00000010
+#define  FLD_AUD_SRC_RISCI1        0x00000002
+#define  FLD_AUD_DST_RISCI1        0x00000001
+
+/* ***************************************************************************** */
+#define  MBIF_A_INT_MSK             0x040110	/* MBIF Int interrupt mask */
+#define  MBIF_A_INT_STAT            0x040114	/* MBIF Int interrupt status */
+#define  MBIF_A_INT_MSTAT           0x040118	/* MBIF Int interrupt masked status */
+#define  MBIF_A_INT_SSTAT           0x04011C	/* MBIF Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  MBIF_B_INT_MSK             0x040120	/* MBIF Int interrupt mask */
+#define  MBIF_B_INT_STAT            0x040124	/* MBIF Int interrupt status */
+#define  MBIF_B_INT_MSTAT           0x040128	/* MBIF Int interrupt masked status */
+#define  MBIF_B_INT_SSTAT           0x04012C	/* MBIF Int interrupt set status */
+
+#define  FLD_MBIF_DST_OPC_ERR       0x00010000
+#define  FLD_MBIF_DST_SYNC          0x00001000
+#define  FLD_MBIF_DST_OF            0x00000100
+#define  FLD_MBIF_DST_RISCI2        0x00000010
+#define  FLD_MBIF_DST_RISCI1        0x00000001
+
+/* ***************************************************************************** */
+#define  AUD_EXT_INT_MSK           0x040060	/* Audio Ext interrupt mask */
+#define  AUD_EXT_INT_STAT          0x040064	/* Audio Ext interrupt status */
+#define  AUD_EXT_INT_MSTAT         0x040068	/* Audio Ext interrupt masked status */
+#define  AUD_EXT_INT_SSTAT         0x04006C	/* Audio Ext interrupt set status */
+#define  FLD_AUD_EXT_OPC_ERR       0x00010000
+#define  FLD_AUD_EXT_SYNC          0x00001000
+#define  FLD_AUD_EXT_OF            0x00000100
+#define  FLD_AUD_EXT_RISCI2        0x00000010
+#define  FLD_AUD_EXT_RISCI1        0x00000001
+
+/* ***************************************************************************** */
+#define  GPIO_LO                   0x110010	/* Lower  of GPIO pins [31:0] */
+#define  GPIO_HI                   0x110014	/* Upper WORD  of GPIO pins [47:31] */
+
+#define  GPIO_LO_OE                0x110018	/* Lower  of GPIO output enable [31:0] */
+#define  GPIO_HI_OE                0x11001C	/* Upper word  of GPIO output enable [47:32] */
+
+#define  GPIO_LO_INT_MSK           0x11003C	/* GPIO interrupt mask */
+#define  GPIO_LO_INT_STAT          0x110044	/* GPIO interrupt status */
+#define  GPIO_LO_INT_MSTAT         0x11004C	/* GPIO interrupt masked status */
+#define  GPIO_LO_ISM_SNS           0x110054	/* GPIO interrupt sensitivity */
+#define  GPIO_LO_ISM_POL           0x11005C	/* GPIO interrupt polarity */
+
+#define  GPIO_HI_INT_MSK           0x110040	/* GPIO interrupt mask */
+#define  GPIO_HI_INT_STAT          0x110048	/* GPIO interrupt status */
+#define  GPIO_HI_INT_MSTAT         0x110050	/* GPIO interrupt masked status */
+#define  GPIO_HI_ISM_SNS           0x110058	/* GPIO interrupt sensitivity */
+#define  GPIO_HI_ISM_POL           0x110060	/* GPIO interrupt polarity */
+
+#define  FLD_GPIO43_INT            (1 << 11)
+#define  FLD_GPIO42_INT            (1 << 10)
+#define  FLD_GPIO41_INT            (1 << 9)
+#define  FLD_GPIO40_INT            (1 << 8)
+
+#define  FLD_GPIO9_INT             (1 << 9)
+#define  FLD_GPIO8_INT             (1 << 8)
+#define  FLD_GPIO7_INT             (1 << 7)
+#define  FLD_GPIO6_INT             (1 << 6)
+#define  FLD_GPIO5_INT             (1 << 5)
+#define  FLD_GPIO4_INT             (1 << 4)
+#define  FLD_GPIO3_INT             (1 << 3)
+#define  FLD_GPIO2_INT             (1 << 2)
+#define  FLD_GPIO1_INT             (1 << 1)
+#define  FLD_GPIO0_INT             (1 << 0)
+
+/* ***************************************************************************** */
+#define  TC_REQ                    0x040090	/* Rider PCI Express traFFic class request */
+
+/* ***************************************************************************** */
+#define  TC_REQ_SET                0x040094	/* Rider PCI Express traFFic class request set */
+
+/* ***************************************************************************** */
+/* Rider */
+/* ***************************************************************************** */
+
+/* PCI Compatible Header */
+/* ***************************************************************************** */
+#define  RDR_CFG0                  0x050000
+#define  RDR_VENDOR_DEVICE_ID_CFG  0x050000
+
+/* ***************************************************************************** */
+#define  RDR_CFG1                  0x050004
+
+/* ***************************************************************************** */
+#define  RDR_CFG2                  0x050008
+
+/* ***************************************************************************** */
+#define  RDR_CFG3                  0x05000C
+
+/* ***************************************************************************** */
+#define  RDR_CFG4                  0x050010
+
+/* ***************************************************************************** */
+#define  RDR_CFG5                  0x050014
+
+/* ***************************************************************************** */
+#define  RDR_CFG6                  0x050018
+
+/* ***************************************************************************** */
+#define  RDR_CFG7                  0x05001C
+
+/* ***************************************************************************** */
+#define  RDR_CFG8                  0x050020
+
+/* ***************************************************************************** */
+#define  RDR_CFG9                  0x050024
+
+/* ***************************************************************************** */
+#define  RDR_CFGA                  0x050028
+
+/* ***************************************************************************** */
+#define  RDR_CFGB                  0x05002C
+#define  RDR_SUSSYSTEM_ID_CFG      0x05002C
+
+/* ***************************************************************************** */
+#define  RDR_CFGC                  0x050030
+
+/* ***************************************************************************** */
+#define  RDR_CFGD                  0x050034
+
+/* ***************************************************************************** */
+#define  RDR_CFGE                  0x050038
+
+/* ***************************************************************************** */
+#define  RDR_CFGF                  0x05003C
+
+/* ***************************************************************************** */
+/* PCI-Express Capabilities */
+/* ***************************************************************************** */
+#define  RDR_PECAP                 0x050040
+
+/* ***************************************************************************** */
+#define  RDR_PEDEVCAP              0x050044
+
+/* ***************************************************************************** */
+#define  RDR_PEDEVSC               0x050048
+
+/* ***************************************************************************** */
+#define  RDR_PELINKCAP             0x05004C
+
+/* ***************************************************************************** */
+#define  RDR_PELINKSC              0x050050
+
+/* ***************************************************************************** */
+#define  RDR_PMICAP                0x050080
+
+/* ***************************************************************************** */
+#define  RDR_PMCSR                 0x050084
+
+/* ***************************************************************************** */
+#define  RDR_VPDCAP                0x050090
+
+/* ***************************************************************************** */
+#define  RDR_VPDDATA               0x050094
+
+/* ***************************************************************************** */
+#define  RDR_MSICAP                0x0500A0
+
+/* ***************************************************************************** */
+#define  RDR_MSIARL                0x0500A4
+
+/* ***************************************************************************** */
+#define  RDR_MSIARU                0x0500A8
+
+/* ***************************************************************************** */
+#define  RDR_MSIDATA               0x0500AC
+
+/* ***************************************************************************** */
+/* PCI Express Extended Capabilities */
+/* ***************************************************************************** */
+#define  RDR_AERXCAP               0x050100
+
+/* ***************************************************************************** */
+#define  RDR_AERUESTA              0x050104
+
+/* ***************************************************************************** */
+#define  RDR_AERUEMSK              0x050108
+
+/* ***************************************************************************** */
+#define  RDR_AERUESEV              0x05010C
+
+/* ***************************************************************************** */
+#define  RDR_AERCESTA              0x050110
+
+/* ***************************************************************************** */
+#define  RDR_AERCEMSK              0x050114
+
+/* ***************************************************************************** */
+#define  RDR_AERCC                 0x050118
+
+/* ***************************************************************************** */
+#define  RDR_AERHL0                0x05011C
+
+/* ***************************************************************************** */
+#define  RDR_AERHL1                0x050120
+
+/* ***************************************************************************** */
+#define  RDR_AERHL2                0x050124
+
+/* ***************************************************************************** */
+#define  RDR_AERHL3                0x050128
+
+/* ***************************************************************************** */
+#define  RDR_VCXCAP                0x050200
+
+/* ***************************************************************************** */
+#define  RDR_VCCAP1                0x050204
+
+/* ***************************************************************************** */
+#define  RDR_VCCAP2                0x050208
+
+/* ***************************************************************************** */
+#define  RDR_VCSC                  0x05020C
+
+/* ***************************************************************************** */
+#define  RDR_VCR0_CAP              0x050210
+
+/* ***************************************************************************** */
+#define  RDR_VCR0_CTRL             0x050214
+
+/* ***************************************************************************** */
+#define  RDR_VCR0_STAT             0x050218
+
+/* ***************************************************************************** */
+#define  RDR_VCR1_CAP              0x05021C
+
+/* ***************************************************************************** */
+#define  RDR_VCR1_CTRL             0x050220
+
+/* ***************************************************************************** */
+#define  RDR_VCR1_STAT             0x050224
+
+/* ***************************************************************************** */
+#define  RDR_VCR2_CAP              0x050228
+
+/* ***************************************************************************** */
+#define  RDR_VCR2_CTRL             0x05022C
+
+/* ***************************************************************************** */
+#define  RDR_VCR2_STAT             0x050230
+
+/* ***************************************************************************** */
+#define  RDR_VCR3_CAP              0x050234
+
+/* ***************************************************************************** */
+#define  RDR_VCR3_CTRL             0x050238
+
+/* ***************************************************************************** */
+#define  RDR_VCR3_STAT             0x05023C
+
+/* ***************************************************************************** */
+#define  RDR_VCARB0                0x050240
+
+/* ***************************************************************************** */
+#define  RDR_VCARB1                0x050244
+
+/* ***************************************************************************** */
+#define  RDR_VCARB2                0x050248
+
+/* ***************************************************************************** */
+#define  RDR_VCARB3                0x05024C
+
+/* ***************************************************************************** */
+#define  RDR_VCARB4                0x050250
+
+/* ***************************************************************************** */
+#define  RDR_VCARB5                0x050254
+
+/* ***************************************************************************** */
+#define  RDR_VCARB6                0x050258
+
+/* ***************************************************************************** */
+#define  RDR_VCARB7                0x05025C
+
+/* ***************************************************************************** */
+#define  RDR_RDRSTAT0              0x050300
+
+/* ***************************************************************************** */
+#define  RDR_RDRSTAT1              0x050304
+
+/* ***************************************************************************** */
+#define  RDR_RDRCTL0               0x050308
+
+/* ***************************************************************************** */
+#define  RDR_RDRCTL1               0x05030C
+
+/* ***************************************************************************** */
+/* Transaction Layer Registers */
+/* ***************************************************************************** */
+#define  RDR_TLSTAT0               0x050310
+
+/* ***************************************************************************** */
+#define  RDR_TLSTAT1               0x050314
+
+/* ***************************************************************************** */
+#define  RDR_TLCTL0                0x050318
+#define  FLD_CFG_UR_CPL_MODE       0x00000040
+#define  FLD_CFG_CORR_ERR_QUITE    0x00000020
+#define  FLD_CFG_RCB_CK_EN         0x00000010
+#define  FLD_CFG_BNDRY_CK_EN       0x00000008
+#define  FLD_CFG_BYTE_EN_CK_EN     0x00000004
+#define  FLD_CFG_RELAX_ORDER_MSK   0x00000002
+#define  FLD_CFG_TAG_ORDER_EN      0x00000001
+
+/* ***************************************************************************** */
+#define  RDR_TLCTL1                0x05031C
+
+/* ***************************************************************************** */
+#define  RDR_REQRCAL               0x050320
+
+/* ***************************************************************************** */
+#define  RDR_REQRCAU               0x050324
+
+/* ***************************************************************************** */
+#define  RDR_REQEPA                0x050328
+
+/* ***************************************************************************** */
+#define  RDR_REQCTRL               0x05032C
+
+/* ***************************************************************************** */
+#define  RDR_REQSTAT               0x050330
+
+/* ***************************************************************************** */
+#define  RDR_TL_TEST               0x050334
+
+/* ***************************************************************************** */
+#define  RDR_VCR01_CTL             0x050348
+
+/* ***************************************************************************** */
+#define  RDR_VCR23_CTL             0x05034C
+
+/* ***************************************************************************** */
+#define  RDR_RX_VCR0_FC            0x050350
+
+/* ***************************************************************************** */
+#define  RDR_RX_VCR1_FC            0x050354
+
+/* ***************************************************************************** */
+#define  RDR_RX_VCR2_FC            0x050358
+
+/* ***************************************************************************** */
+#define  RDR_RX_VCR3_FC            0x05035C
+
+/* ***************************************************************************** */
+/* Data Link Layer Registers */
+/* ***************************************************************************** */
+#define  RDR_DLLSTAT               0x050360
+
+/* ***************************************************************************** */
+#define  RDR_DLLCTRL               0x050364
+
+/* ***************************************************************************** */
+#define  RDR_REPLAYTO              0x050368
+
+/* ***************************************************************************** */
+#define  RDR_ACKLATTO              0x05036C
+
+/* ***************************************************************************** */
+/* MAC Layer Registers */
+/* ***************************************************************************** */
+#define  RDR_MACSTAT0              0x050380
+
+/* ***************************************************************************** */
+#define  RDR_MACSTAT1              0x050384
+
+/* ***************************************************************************** */
+#define  RDR_MACCTRL0              0x050388
+
+/* ***************************************************************************** */
+#define  RDR_MACCTRL1              0x05038C
+
+/* ***************************************************************************** */
+#define  RDR_MACCTRL2              0x050390
+
+/* ***************************************************************************** */
+#define  RDR_MAC_LB_DATA           0x050394
+
+/* ***************************************************************************** */
+#define  RDR_L0S_EXIT_LAT          0x050398
+
+/* ***************************************************************************** */
+/* DMAC */
+/* ***************************************************************************** */
+#define  DMA1_PTR1                 0x100000	/* DMA Current Ptr : Ch#1 */
+
+/* ***************************************************************************** */
+#define  DMA2_PTR1                 0x100004	/* DMA Current Ptr : Ch#2 */
+
+/* ***************************************************************************** */
+#define  DMA3_PTR1                 0x100008	/* DMA Current Ptr : Ch#3 */
+
+/* ***************************************************************************** */
+#define  DMA4_PTR1                 0x10000C	/* DMA Current Ptr : Ch#4 */
+
+/* ***************************************************************************** */
+#define  DMA5_PTR1                 0x100010	/* DMA Current Ptr : Ch#5 */
+
+/* ***************************************************************************** */
+#define  DMA6_PTR1                 0x100014	/* DMA Current Ptr : Ch#6 */
+
+/* ***************************************************************************** */
+#define  DMA7_PTR1                 0x100018	/* DMA Current Ptr : Ch#7 */
+
+/* ***************************************************************************** */
+#define  DMA8_PTR1                 0x10001C	/* DMA Current Ptr : Ch#8 */
+
+/* ***************************************************************************** */
+#define  DMA9_PTR1                 0x100020	/* DMA Current Ptr : Ch#9 */
+
+/* ***************************************************************************** */
+#define  DMA10_PTR1                0x100024	/* DMA Current Ptr : Ch#10 */
+
+/* ***************************************************************************** */
+#define  DMA11_PTR1                0x100028	/* DMA Current Ptr : Ch#11 */
+
+/* ***************************************************************************** */
+#define  DMA12_PTR1                0x10002C	/* DMA Current Ptr : Ch#12 */
+
+/* ***************************************************************************** */
+#define  DMA13_PTR1                0x100030	/* DMA Current Ptr : Ch#13 */
+
+/* ***************************************************************************** */
+#define  DMA14_PTR1                0x100034	/* DMA Current Ptr : Ch#14 */
+
+/* ***************************************************************************** */
+#define  DMA15_PTR1                0x100038	/* DMA Current Ptr : Ch#15 */
+
+/* ***************************************************************************** */
+#define  DMA16_PTR1                0x10003C	/* DMA Current Ptr : Ch#16 */
+
+/* ***************************************************************************** */
+#define  DMA17_PTR1                0x100040	/* DMA Current Ptr : Ch#17 */
+
+/* ***************************************************************************** */
+#define  DMA18_PTR1                0x100044	/* DMA Current Ptr : Ch#18 */
+
+/* ***************************************************************************** */
+#define  DMA19_PTR1                0x100048	/* DMA Current Ptr : Ch#19 */
+
+/* ***************************************************************************** */
+#define  DMA20_PTR1                0x10004C	/* DMA Current Ptr : Ch#20 */
+
+/* ***************************************************************************** */
+#define  DMA21_PTR1                0x100050	/* DMA Current Ptr : Ch#21 */
+
+/* ***************************************************************************** */
+#define  DMA22_PTR1                0x100054	/* DMA Current Ptr : Ch#22 */
+
+/* ***************************************************************************** */
+#define  DMA23_PTR1                0x100058	/* DMA Current Ptr : Ch#23 */
+
+/* ***************************************************************************** */
+#define  DMA24_PTR1                0x10005C	/* DMA Current Ptr : Ch#24 */
+
+/* ***************************************************************************** */
+#define  DMA25_PTR1                0x100060	/* DMA Current Ptr : Ch#25 */
+
+/* ***************************************************************************** */
+#define  DMA26_PTR1                0x100064	/* DMA Current Ptr : Ch#26 */
+
+/* ***************************************************************************** */
+#define  DMA1_PTR2                 0x100080	/* DMA Tab Ptr : Ch#1 */
+
+/* ***************************************************************************** */
+#define  DMA2_PTR2                 0x100084	/* DMA Tab Ptr : Ch#2 */
+
+/* ***************************************************************************** */
+#define  DMA3_PTR2                 0x100088	/* DMA Tab Ptr : Ch#3 */
+
+/* ***************************************************************************** */
+#define  DMA4_PTR2                 0x10008C	/* DMA Tab Ptr : Ch#4 */
+
+/* ***************************************************************************** */
+#define  DMA5_PTR2                 0x100090	/* DMA Tab Ptr : Ch#5 */
+
+/* ***************************************************************************** */
+#define  DMA6_PTR2                 0x100094	/* DMA Tab Ptr : Ch#6 */
+
+/* ***************************************************************************** */
+#define  DMA7_PTR2                 0x100098	/* DMA Tab Ptr : Ch#7 */
+
+/* ***************************************************************************** */
+#define  DMA8_PTR2                 0x10009C	/* DMA Tab Ptr : Ch#8 */
+
+/* ***************************************************************************** */
+#define  DMA9_PTR2                 0x1000A0	/* DMA Tab Ptr : Ch#9 */
+
+/* ***************************************************************************** */
+#define  DMA10_PTR2                0x1000A4	/* DMA Tab Ptr : Ch#10 */
+
+/* ***************************************************************************** */
+#define  DMA11_PTR2                0x1000A8	/* DMA Tab Ptr : Ch#11 */
+
+/* ***************************************************************************** */
+#define  DMA12_PTR2                0x1000AC	/* DMA Tab Ptr : Ch#12 */
+
+/* ***************************************************************************** */
+#define  DMA13_PTR2                0x1000B0	/* DMA Tab Ptr : Ch#13 */
+
+/* ***************************************************************************** */
+#define  DMA14_PTR2                0x1000B4	/* DMA Tab Ptr : Ch#14 */
+
+/* ***************************************************************************** */
+#define  DMA15_PTR2                0x1000B8	/* DMA Tab Ptr : Ch#15 */
+
+/* ***************************************************************************** */
+#define  DMA16_PTR2                0x1000BC	/* DMA Tab Ptr : Ch#16 */
+
+/* ***************************************************************************** */
+#define  DMA17_PTR2                0x1000C0	/* DMA Tab Ptr : Ch#17 */
+
+/* ***************************************************************************** */
+#define  DMA18_PTR2                0x1000C4	/* DMA Tab Ptr : Ch#18 */
+
+/* ***************************************************************************** */
+#define  DMA19_PTR2                0x1000C8	/* DMA Tab Ptr : Ch#19 */
+
+/* ***************************************************************************** */
+#define  DMA20_PTR2                0x1000CC	/* DMA Tab Ptr : Ch#20 */
+
+/* ***************************************************************************** */
+#define  DMA21_PTR2                0x1000D0	/* DMA Tab Ptr : Ch#21 */
+
+/* ***************************************************************************** */
+#define  DMA22_PTR2                0x1000D4	/* DMA Tab Ptr : Ch#22 */
+
+/* ***************************************************************************** */
+#define  DMA23_PTR2                0x1000D8	/* DMA Tab Ptr : Ch#23 */
+
+/* ***************************************************************************** */
+#define  DMA24_PTR2                0x1000DC	/* DMA Tab Ptr : Ch#24 */
+
+/* ***************************************************************************** */
+#define  DMA25_PTR2                0x1000E0	/* DMA Tab Ptr : Ch#25 */
+
+/* ***************************************************************************** */
+#define  DMA26_PTR2                0x1000E4	/* DMA Tab Ptr : Ch#26 */
+
+/* ***************************************************************************** */
+#define  DMA1_CNT1                 0x100100	/* DMA BuFFer Size : Ch#1 */
+
+/* ***************************************************************************** */
+#define  DMA2_CNT1                 0x100104	/* DMA BuFFer Size : Ch#2 */
+
+/* ***************************************************************************** */
+#define  DMA3_CNT1                 0x100108	/* DMA BuFFer Size : Ch#3 */
+
+/* ***************************************************************************** */
+#define  DMA4_CNT1                 0x10010C	/* DMA BuFFer Size : Ch#4 */
+
+/* ***************************************************************************** */
+#define  DMA5_CNT1                 0x100110	/* DMA BuFFer Size : Ch#5 */
+
+/* ***************************************************************************** */
+#define  DMA6_CNT1                 0x100114	/* DMA BuFFer Size : Ch#6 */
+
+/* ***************************************************************************** */
+#define  DMA7_CNT1                 0x100118	/* DMA BuFFer Size : Ch#7 */
+
+/* ***************************************************************************** */
+#define  DMA8_CNT1                 0x10011C	/* DMA BuFFer Size : Ch#8 */
+
+/* ***************************************************************************** */
+#define  DMA9_CNT1                 0x100120	/* DMA BuFFer Size : Ch#9 */
+
+/* ***************************************************************************** */
+#define  DMA10_CNT1                0x100124	/* DMA BuFFer Size : Ch#10 */
+
+/* ***************************************************************************** */
+#define  DMA11_CNT1                0x100128	/* DMA BuFFer Size : Ch#11 */
+
+/* ***************************************************************************** */
+#define  DMA12_CNT1                0x10012C	/* DMA BuFFer Size : Ch#12 */
+
+/* ***************************************************************************** */
+#define  DMA13_CNT1                0x100130	/* DMA BuFFer Size : Ch#13 */
+
+/* ***************************************************************************** */
+#define  DMA14_CNT1                0x100134	/* DMA BuFFer Size : Ch#14 */
+
+/* ***************************************************************************** */
+#define  DMA15_CNT1                0x100138	/* DMA BuFFer Size : Ch#15 */
+
+/* ***************************************************************************** */
+#define  DMA16_CNT1                0x10013C	/* DMA BuFFer Size : Ch#16 */
+
+/* ***************************************************************************** */
+#define  DMA17_CNT1                0x100140	/* DMA BuFFer Size : Ch#17 */
+
+/* ***************************************************************************** */
+#define  DMA18_CNT1                0x100144	/* DMA BuFFer Size : Ch#18 */
+
+/* ***************************************************************************** */
+#define  DMA19_CNT1                0x100148	/* DMA BuFFer Size : Ch#19 */
+
+/* ***************************************************************************** */
+#define  DMA20_CNT1                0x10014C	/* DMA BuFFer Size : Ch#20 */
+
+/* ***************************************************************************** */
+#define  DMA21_CNT1                0x100150	/* DMA BuFFer Size : Ch#21 */
+
+/* ***************************************************************************** */
+#define  DMA22_CNT1                0x100154	/* DMA BuFFer Size : Ch#22 */
+
+/* ***************************************************************************** */
+#define  DMA23_CNT1                0x100158	/* DMA BuFFer Size : Ch#23 */
+
+/* ***************************************************************************** */
+#define  DMA24_CNT1                0x10015C	/* DMA BuFFer Size : Ch#24 */
+
+/* ***************************************************************************** */
+#define  DMA25_CNT1                0x100160	/* DMA BuFFer Size : Ch#25 */
+
+/* ***************************************************************************** */
+#define  DMA26_CNT1                0x100164	/* DMA BuFFer Size : Ch#26 */
+
+/* ***************************************************************************** */
+#define  DMA1_CNT2                 0x100180	/* DMA Table Size : Ch#1 */
+
+/* ***************************************************************************** */
+#define  DMA2_CNT2                 0x100184	/* DMA Table Size : Ch#2 */
+
+/* ***************************************************************************** */
+#define  DMA3_CNT2                 0x100188	/* DMA Table Size : Ch#3 */
+
+/* ***************************************************************************** */
+#define  DMA4_CNT2                 0x10018C	/* DMA Table Size : Ch#4 */
+
+/* ***************************************************************************** */
+#define  DMA5_CNT2                 0x100190	/* DMA Table Size : Ch#5 */
+
+/* ***************************************************************************** */
+#define  DMA6_CNT2                 0x100194	/* DMA Table Size : Ch#6 */
+
+/* ***************************************************************************** */
+#define  DMA7_CNT2                 0x100198	/* DMA Table Size : Ch#7 */
+
+/* ***************************************************************************** */
+#define  DMA8_CNT2                 0x10019C	/* DMA Table Size : Ch#8 */
+
+/* ***************************************************************************** */
+#define  DMA9_CNT2                 0x1001A0	/* DMA Table Size : Ch#9 */
+
+/* ***************************************************************************** */
+#define  DMA10_CNT2                0x1001A4	/* DMA Table Size : Ch#10 */
+
+/* ***************************************************************************** */
+#define  DMA11_CNT2                0x1001A8	/* DMA Table Size : Ch#11 */
+
+/* ***************************************************************************** */
+#define  DMA12_CNT2                0x1001AC	/* DMA Table Size : Ch#12 */
+
+/* ***************************************************************************** */
+#define  DMA13_CNT2                0x1001B0	/* DMA Table Size : Ch#13 */
+
+/* ***************************************************************************** */
+#define  DMA14_CNT2                0x1001B4	/* DMA Table Size : Ch#14 */
+
+/* ***************************************************************************** */
+#define  DMA15_CNT2                0x1001B8	/* DMA Table Size : Ch#15 */
+
+/* ***************************************************************************** */
+#define  DMA16_CNT2                0x1001BC	/* DMA Table Size : Ch#16 */
+
+/* ***************************************************************************** */
+#define  DMA17_CNT2                0x1001C0	/* DMA Table Size : Ch#17 */
+
+/* ***************************************************************************** */
+#define  DMA18_CNT2                0x1001C4	/* DMA Table Size : Ch#18 */
+
+/* ***************************************************************************** */
+#define  DMA19_CNT2                0x1001C8	/* DMA Table Size : Ch#19 */
+
+/* ***************************************************************************** */
+#define  DMA20_CNT2                0x1001CC	/* DMA Table Size : Ch#20 */
+
+/* ***************************************************************************** */
+#define  DMA21_CNT2                0x1001D0	/* DMA Table Size : Ch#21 */
+
+/* ***************************************************************************** */
+#define  DMA22_CNT2                0x1001D4	/* DMA Table Size : Ch#22 */
+
+/* ***************************************************************************** */
+#define  DMA23_CNT2                0x1001D8	/* DMA Table Size : Ch#23 */
+
+/* ***************************************************************************** */
+#define  DMA24_CNT2                0x1001DC	/* DMA Table Size : Ch#24 */
+
+/* ***************************************************************************** */
+#define  DMA25_CNT2                0x1001E0	/* DMA Table Size : Ch#25 */
+
+/* ***************************************************************************** */
+#define  DMA26_CNT2                0x1001E4	/* DMA Table Size : Ch#26 */
+
+/* ***************************************************************************** */
+ /* ITG */
+/* ***************************************************************************** */
+#define  TM_CNT_LDW                0x110000	/* Timer : Counter low */
+
+/* ***************************************************************************** */
+#define  TM_CNT_UW                 0x110004	/* Timer : Counter high word */
+
+/* ***************************************************************************** */
+#define  TM_LMT_LDW                0x110008	/* Timer : Limit low */
+
+/* ***************************************************************************** */
+#define  TM_LMT_UW                 0x11000C	/* Timer : Limit high word */
+
+/* ***************************************************************************** */
+#define  GP0_IO                    0x110010	/* GPIO output enables data I/O */
+#define  FLD_GP_OE                 0x00FF0000	/* GPIO: GP_OE output enable */
+#define  FLD_GP_IN                 0x0000FF00	/* GPIO: GP_IN status */
+#define  FLD_GP_OUT                0x000000FF	/* GPIO: GP_OUT control */
+
+/* ***************************************************************************** */
+#define  GPIO_ISM                  0x110014	/* GPIO interrupt sensitivity mode */
+#define  FLD_GP_ISM_SNS            0x00000070
+#define  FLD_GP_ISM_POL            0x00000007
+
+/* ***************************************************************************** */
+#define  SOFT_RESET                0x11001C	/* Output system reset reg */
+#define  FLD_PECOS_SOFT_RESET      0x00000001
+
+/* ***************************************************************************** */
+#define  MC416_RWD                 0x110020	/* MC416 GPIO[18:3] pin */
+#define  MC416_OEN                 0x110024	/* Output enable of GPIO[18:3] */
+#define  MC416_CTL                 0x110028
+
+/* ***************************************************************************** */
+#define  ALT_PIN_OUT_SEL           0x11002C	/* Alternate GPIO output select */
+
+#define  FLD_ALT_GPIO_OUT_SEL      0xF0000000
+/* 0          Disabled <-- default */
+/* 1          GPIO[0] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+/* 8          ATT_IF */
+
+#define  FLD_AUX_PLL_CLK_ALT_SEL   0x0F000000
+/* 0          AUX_PLL_CLK<-- default */
+/* 1          GPIO[2] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_IR_TX_ALT_SEL         0x00F00000
+/* 0          IR_TX <-- default */
+/* 1          GPIO[1] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_IR_RX_ALT_SEL         0x000F0000
+/* 0          IR_RX <-- default */
+/* 1          GPIO[0] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_GPIO10_ALT_SEL        0x0000F000
+/* 0          GPIO[10] <-- default */
+/* 1          GPIO[0] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_GPIO2_ALT_SEL         0x00000F00
+/* 0          GPIO[2] <-- default */
+/* 1          GPIO[1] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_GPIO1_ALT_SEL         0x000000F0
+/* 0          GPIO[1] <-- default */
+/* 1          GPIO[0] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_GPIO0_ALT_SEL         0x0000000F
+/* 0          GPIO[0] <-- default */
+/* 1          GPIO[1] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  ALT_PIN_IN_SEL            0x110030	/* Alternate GPIO input select */
+
+#define  FLD_GPIO10_ALT_IN_SEL     0x0000F000
+/* 0          GPIO[10] <-- default */
+/* 1          IR_RX */
+/* 2          IR_TX */
+/* 3          AUX_PLL_CLK */
+/* 4          IF_ATT_SEL */
+/* 5          GPIO[0] */
+/* 6          GPIO[1] */
+/* 7          GPIO[2] */
+
+#define  FLD_GPIO2_ALT_IN_SEL      0x00000F00
+/* 0          GPIO[2] <-- default */
+/* 1          IR_RX */
+/* 2          IR_TX */
+/* 3          AUX_PLL_CLK */
+/* 4          IF_ATT_SEL */
+
+#define  FLD_GPIO1_ALT_IN_SEL      0x000000F0
+/* 0          GPIO[1] <-- default */
+/* 1          IR_RX */
+/* 2          IR_TX */
+/* 3          AUX_PLL_CLK */
+/* 4          IF_ATT_SEL */
+
+#define  FLD_GPIO0_ALT_IN_SEL      0x0000000F
+/* 0          GPIO[0] <-- default */
+/* 1          IR_RX */
+/* 2          IR_TX */
+/* 3          AUX_PLL_CLK */
+/* 4          IF_ATT_SEL */
+
+/* ***************************************************************************** */
+#define  TEST_BUS_CTL1             0x110040	/* Test bus control register #1 */
+
+/* ***************************************************************************** */
+#define  TEST_BUS_CTL2             0x110044	/* Test bus control register #2 */
+
+/* ***************************************************************************** */
+#define  CLK_DELAY                 0x110048	/* Clock delay */
+#define  FLD_MOE_CLK_DIS           0x80000000	/* Disable MoE clock */
+
+/* ***************************************************************************** */
+#define  PAD_CTRL                  0x110068	/* Pad drive strength control */
+
+/* ***************************************************************************** */
+#define  MBIST_CTRL                0x110050	/* SRAM memory built-in self test control */
+
+/* ***************************************************************************** */
+#define  MBIST_STAT                0x110054	/* SRAM memory built-in self test status */
+
+/* ***************************************************************************** */
+/* PLL registers */
+/* ***************************************************************************** */
+#define  PLL_A_INT_FRAC            0x110088
+#define  PLL_A_POST_STAT_BIST      0x11008C
+#define  PLL_B_INT_FRAC            0x110090
+#define  PLL_B_POST_STAT_BIST      0x110094
+#define  PLL_C_INT_FRAC            0x110098
+#define  PLL_C_POST_STAT_BIST      0x11009C
+#define  PLL_D_INT_FRAC            0x1100A0
+#define  PLL_D_POST_STAT_BIST      0x1100A4
+
+#define  CLK_RST                   0x11002C
+#define  FLD_VID_I_CLK_NOE         0x00001000
+#define  FLD_VID_J_CLK_NOE         0x00002000
+#define  FLD_USE_ALT_PLL_REF       0x00004000
+
+#define  VID_CH_MODE_SEL           0x110078
+#define  VID_CH_CLK_SEL            0x11007C
+
+/* ***************************************************************************** */
+#define  VBI_A_DMA                 0x130008	/* VBI A DMA data port */
+
+/* ***************************************************************************** */
+#define  VID_A_VIP_CTL             0x130080	/* Video A VIP format control */
+#define  FLD_VIP_MODE              0x00000001
+
+/* ***************************************************************************** */
+#define  VID_A_PIXEL_FRMT          0x130084	/* Video A pixel format */
+#define  FLD_VID_A_GAMMA_DIS       0x00000008
+#define  FLD_VID_A_FORMAT          0x00000007
+#define  FLD_VID_A_GAMMA_FACTOR    0x00000010
+
+/* ***************************************************************************** */
+#define  VID_A_VBI_CTL             0x130088	/* Video A VBI miscellaneous control */
+#define  FLD_VID_A_VIP_EXT         0x00000003
+
+/* ***************************************************************************** */
+#define  VID_B_DMA                 0x130100	/* Video B DMA data port */
+
+/* ***************************************************************************** */
+#define  VBI_B_DMA                 0x130108	/* VBI B DMA data port */
+
+/* ***************************************************************************** */
+#define  VID_B_SRC_SEL             0x130144	/* Video B source select */
+#define  FLD_VID_B_SRC_SEL         0x00000000
+
+/* ***************************************************************************** */
+#define  VID_B_LNGTH               0x130150	/* Video B line length */
+#define  FLD_VID_B_LN_LNGTH        0x00000FFF
+
+/* ***************************************************************************** */
+#define  VID_B_VIP_CTL             0x130180	/* Video B VIP format control */
+
+/* ***************************************************************************** */
+#define  VID_B_PIXEL_FRMT          0x130184	/* Video B pixel format */
+#define  FLD_VID_B_GAMMA_DIS       0x00000008
+#define  FLD_VID_B_FORMAT          0x00000007
+#define  FLD_VID_B_GAMMA_FACTOR    0x00000010
+
+/* ***************************************************************************** */
+#define  VID_C_DMA                 0x130200	/* Video C DMA data port */
+
+/* ***************************************************************************** */
+#define  VID_C_LNGTH               0x130250	/* Video C line length */
+#define  FLD_VID_C_LN_LNGTH        0x00000FFF
+
+/* ***************************************************************************** */
+/* Video Destination Channels */
+/* ***************************************************************************** */
+
+#define  VID_DST_A_GPCNT           0x130020	/* Video A general purpose counter */
+#define  VID_DST_B_GPCNT           0x130120	/* Video B general purpose counter */
+#define  VID_DST_C_GPCNT           0x130220	/* Video C general purpose counter */
+#define  VID_DST_D_GPCNT           0x130320	/* Video D general purpose counter */
+#define  VID_DST_E_GPCNT           0x130420	/* Video E general purpose counter */
+#define  VID_DST_F_GPCNT           0x130520	/* Video F general purpose counter */
+#define  VID_DST_G_GPCNT           0x130620	/* Video G general purpose counter */
+#define  VID_DST_H_GPCNT           0x130720	/* Video H general purpose counter */
+
+/* ***************************************************************************** */
+
+#define  VID_DST_A_GPCNT_CTL       0x130030	/* Video A general purpose control */
+#define  VID_DST_B_GPCNT_CTL       0x130130	/* Video B general purpose control */
+#define  VID_DST_C_GPCNT_CTL       0x130230	/* Video C general purpose control */
+#define  VID_DST_D_GPCNT_CTL       0x130330	/* Video D general purpose control */
+#define  VID_DST_E_GPCNT_CTL       0x130430	/* Video E general purpose control */
+#define  VID_DST_F_GPCNT_CTL       0x130530	/* Video F general purpose control */
+#define  VID_DST_G_GPCNT_CTL       0x130630	/* Video G general purpose control */
+#define  VID_DST_H_GPCNT_CTL       0x130730	/* Video H general purpose control */
+
+/* ***************************************************************************** */
+
+#define  VID_DST_A_DMA_CTL         0x130040	/* Video A DMA control */
+#define  VID_DST_B_DMA_CTL         0x130140	/* Video B DMA control */
+#define  VID_DST_C_DMA_CTL         0x130240	/* Video C DMA control */
+#define  VID_DST_D_DMA_CTL         0x130340	/* Video D DMA control */
+#define  VID_DST_E_DMA_CTL         0x130440	/* Video E DMA control */
+#define  VID_DST_F_DMA_CTL         0x130540	/* Video F DMA control */
+#define  VID_DST_G_DMA_CTL         0x130640	/* Video G DMA control */
+#define  VID_DST_H_DMA_CTL         0x130740	/* Video H DMA control */
+
+#define  FLD_VID_RISC_EN           0x00000010
+#define  FLD_VID_FIFO_EN           0x00000001
+
+/* ***************************************************************************** */
+
+#define  VID_DST_A_VIP_CTL         0x130080	/* Video A VIP control */
+#define  VID_DST_B_VIP_CTL         0x130180	/* Video B VIP control */
+#define  VID_DST_C_VIP_CTL         0x130280	/* Video C VIP control */
+#define  VID_DST_D_VIP_CTL         0x130380	/* Video D VIP control */
+#define  VID_DST_E_VIP_CTL         0x130480	/* Video E VIP control */
+#define  VID_DST_F_VIP_CTL         0x130580	/* Video F VIP control */
+#define  VID_DST_G_VIP_CTL         0x130680	/* Video G VIP control */
+#define  VID_DST_H_VIP_CTL         0x130780	/* Video H VIP control */
+
+/* ***************************************************************************** */
+
+#define  VID_DST_A_PIX_FRMT        0x130084	/* Video A Pixel format */
+#define  VID_DST_B_PIX_FRMT        0x130184	/* Video B Pixel format */
+#define  VID_DST_C_PIX_FRMT        0x130284	/* Video C Pixel format */
+#define  VID_DST_D_PIX_FRMT        0x130384	/* Video D Pixel format */
+#define  VID_DST_E_PIX_FRMT        0x130484	/* Video E Pixel format */
+#define  VID_DST_F_PIX_FRMT        0x130584	/* Video F Pixel format */
+#define  VID_DST_G_PIX_FRMT        0x130684	/* Video G Pixel format */
+#define  VID_DST_H_PIX_FRMT        0x130784	/* Video H Pixel format */
+
+/* ***************************************************************************** */
+/* Video Source Channels */
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_GPCNT_CTL       0x130804	/* Video A general purpose control */
+#define  VID_SRC_B_GPCNT_CTL       0x130904	/* Video B general purpose control */
+#define  VID_SRC_C_GPCNT_CTL       0x130A04	/* Video C general purpose control */
+#define  VID_SRC_D_GPCNT_CTL       0x130B04	/* Video D general purpose control */
+#define  VID_SRC_E_GPCNT_CTL       0x130C04	/* Video E general purpose control */
+#define  VID_SRC_F_GPCNT_CTL       0x130D04	/* Video F general purpose control */
+#define  VID_SRC_I_GPCNT_CTL       0x130E04	/* Video I general purpose control */
+#define  VID_SRC_J_GPCNT_CTL       0x130F04	/* Video J general purpose control */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_GPCNT           0x130808	/* Video A general purpose counter */
+#define  VID_SRC_B_GPCNT           0x130908	/* Video B general purpose counter */
+#define  VID_SRC_C_GPCNT           0x130A08	/* Video C general purpose counter */
+#define  VID_SRC_D_GPCNT           0x130B08	/* Video D general purpose counter */
+#define  VID_SRC_E_GPCNT           0x130C08	/* Video E general purpose counter */
+#define  VID_SRC_F_GPCNT           0x130D08	/* Video F general purpose counter */
+#define  VID_SRC_I_GPCNT           0x130E08	/* Video I general purpose counter */
+#define  VID_SRC_J_GPCNT           0x130F08	/* Video J general purpose counter */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_DMA_CTL         0x13080C	/* Video A DMA control */
+#define  VID_SRC_B_DMA_CTL         0x13090C	/* Video B DMA control */
+#define  VID_SRC_C_DMA_CTL         0x130A0C	/* Video C DMA control */
+#define  VID_SRC_D_DMA_CTL         0x130B0C	/* Video D DMA control */
+#define  VID_SRC_E_DMA_CTL         0x130C0C	/* Video E DMA control */
+#define  VID_SRC_F_DMA_CTL         0x130D0C	/* Video F DMA control */
+#define  VID_SRC_I_DMA_CTL         0x130E0C	/* Video I DMA control */
+#define  VID_SRC_J_DMA_CTL         0x130F0C	/* Video J DMA control */
+
+#define  FLD_APB_RISC_EN           0x00000010
+#define  FLD_APB_FIFO_EN           0x00000001
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_FMT_CTL         0x130810	/* Video A format control */
+#define  VID_SRC_B_FMT_CTL         0x130910	/* Video B format control */
+#define  VID_SRC_C_FMT_CTL         0x130A10	/* Video C format control */
+#define  VID_SRC_D_FMT_CTL         0x130B10	/* Video D format control */
+#define  VID_SRC_E_FMT_CTL         0x130C10	/* Video E format control */
+#define  VID_SRC_F_FMT_CTL         0x130D10	/* Video F format control */
+#define  VID_SRC_I_FMT_CTL         0x130E10	/* Video I format control */
+#define  VID_SRC_J_FMT_CTL         0x130F10	/* Video J format control */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_ACTIVE_CTL1     0x130814	/* Video A active control      1 */
+#define  VID_SRC_B_ACTIVE_CTL1     0x130914	/* Video B active control      1 */
+#define  VID_SRC_C_ACTIVE_CTL1     0x130A14	/* Video C active control      1 */
+#define  VID_SRC_D_ACTIVE_CTL1     0x130B14	/* Video D active control      1 */
+#define  VID_SRC_E_ACTIVE_CTL1     0x130C14	/* Video E active control      1 */
+#define  VID_SRC_F_ACTIVE_CTL1     0x130D14	/* Video F active control      1 */
+#define  VID_SRC_I_ACTIVE_CTL1     0x130E14	/* Video I active control      1 */
+#define  VID_SRC_J_ACTIVE_CTL1     0x130F14	/* Video J active control      1 */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_ACTIVE_CTL2     0x130818	/* Video A active control      2 */
+#define  VID_SRC_B_ACTIVE_CTL2     0x130918	/* Video B active control      2 */
+#define  VID_SRC_C_ACTIVE_CTL2     0x130A18	/* Video C active control      2 */
+#define  VID_SRC_D_ACTIVE_CTL2     0x130B18	/* Video D active control      2 */
+#define  VID_SRC_E_ACTIVE_CTL2     0x130C18	/* Video E active control      2 */
+#define  VID_SRC_F_ACTIVE_CTL2     0x130D18	/* Video F active control      2 */
+#define  VID_SRC_I_ACTIVE_CTL2     0x130E18	/* Video I active control      2 */
+#define  VID_SRC_J_ACTIVE_CTL2     0x130F18	/* Video J active control      2 */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_CDT_SZ          0x13081C	/* Video A CDT size */
+#define  VID_SRC_B_CDT_SZ          0x13091C	/* Video B CDT size */
+#define  VID_SRC_C_CDT_SZ          0x130A1C	/* Video C CDT size */
+#define  VID_SRC_D_CDT_SZ          0x130B1C	/* Video D CDT size */
+#define  VID_SRC_E_CDT_SZ          0x130C1C	/* Video E CDT size */
+#define  VID_SRC_F_CDT_SZ          0x130D1C	/* Video F CDT size */
+#define  VID_SRC_I_CDT_SZ          0x130E1C	/* Video I CDT size */
+#define  VID_SRC_J_CDT_SZ          0x130F1C	/* Video J CDT size */
+
+/* ***************************************************************************** */
+/* Audio I/F */
+/* ***************************************************************************** */
+#define  AUD_DST_A_DMA             0x140000	/* Audio Int A DMA data port */
+#define  AUD_SRC_A_DMA             0x140008	/* Audio Int A DMA data port */
+
+#define  AUD_A_GPCNT               0x140010	/* Audio Int A gp counter */
+#define  FLD_AUD_A_GP_CNT          0x0000FFFF
+
+#define  AUD_A_GPCNT_CTL           0x140014	/* Audio Int A gp control */
+
+#define  AUD_A_LNGTH               0x140018	/* Audio Int A line length */
+
+#define  AUD_A_CFG                 0x14001C	/* Audio Int A configuration */
+
+/* ***************************************************************************** */
+#define  AUD_DST_B_DMA             0x140100	/* Audio Int B DMA data port */
+#define  AUD_SRC_B_DMA             0x140108	/* Audio Int B DMA data port */
+
+#define  AUD_B_GPCNT               0x140110	/* Audio Int B gp counter */
+#define  FLD_AUD_B_GP_CNT          0x0000FFFF
+
+#define  AUD_B_GPCNT_CTL           0x140114	/* Audio Int B gp control */
+
+#define  AUD_B_LNGTH               0x140118	/* Audio Int B line length */
+
+#define  AUD_B_CFG                 0x14011C	/* Audio Int B configuration */
+
+/* ***************************************************************************** */
+#define  AUD_DST_C_DMA             0x140200	/* Audio Int C DMA data port */
+#define  AUD_SRC_C_DMA             0x140208	/* Audio Int C DMA data port */
+
+#define  AUD_C_GPCNT               0x140210	/* Audio Int C gp counter */
+#define  FLD_AUD_C_GP_CNT          0x0000FFFF
+
+#define  AUD_C_GPCNT_CTL           0x140214	/* Audio Int C gp control */
+
+#define  AUD_C_LNGTH               0x140218	/* Audio Int C line length */
+
+#define  AUD_C_CFG                 0x14021C	/* Audio Int C configuration */
+
+/* ***************************************************************************** */
+#define  AUD_DST_D_DMA             0x140300	/* Audio Int D DMA data port */
+#define  AUD_SRC_D_DMA             0x140308	/* Audio Int D DMA data port */
+
+#define  AUD_D_GPCNT               0x140310	/* Audio Int D gp counter */
+#define  FLD_AUD_D_GP_CNT          0x0000FFFF
+
+#define  AUD_D_GPCNT_CTL           0x140314	/* Audio Int D gp control */
+
+#define  AUD_D_LNGTH               0x140318	/* Audio Int D line length */
+
+#define  AUD_D_CFG                 0x14031C	/* Audio Int D configuration */
+
+/* ***************************************************************************** */
+#define  AUD_SRC_E_DMA             0x140400	/* Audio Int E DMA data port */
+
+#define  AUD_E_GPCNT               0x140410	/* Audio Int E gp counter */
+#define  FLD_AUD_E_GP_CNT          0x0000FFFF
+
+#define  AUD_E_GPCNT_CTL           0x140414	/* Audio Int E gp control */
+
+#define  AUD_E_CFG                 0x14041C	/* Audio Int E configuration */
+
+/* ***************************************************************************** */
+
+#define  FLD_AUD_DST_LN_LNGTH      0x00000FFF
+
+#define  FLD_AUD_DST_PK_MODE       0x00004000
+
+#define  FLD_AUD_CLK_ENABLE        0x00000200
+
+#define  FLD_AUD_MASTER_MODE       0x00000002
+
+#define  FLD_AUD_SONY_MODE         0x00000001
+
+#define  FLD_AUD_CLK_SELECT_PLL_D  0x00001800
+
+#define  FLD_AUD_DST_ENABLE        0x00020000
+
+#define  FLD_AUD_SRC_ENABLE        0x00010000
+
+/* ***************************************************************************** */
+#define  AUD_INT_DMA_CTL           0x140500	/* Audio Int DMA control */
+
+#define  FLD_AUD_SRC_E_RISC_EN     0x00008000
+#define  FLD_AUD_SRC_C_RISC_EN     0x00004000
+#define  FLD_AUD_SRC_B_RISC_EN     0x00002000
+#define  FLD_AUD_SRC_A_RISC_EN     0x00001000
+
+#define  FLD_AUD_DST_D_RISC_EN     0x00000800
+#define  FLD_AUD_DST_C_RISC_EN     0x00000400
+#define  FLD_AUD_DST_B_RISC_EN     0x00000200
+#define  FLD_AUD_DST_A_RISC_EN     0x00000100
+
+#define  FLD_AUD_SRC_E_FIFO_EN     0x00000080
+#define  FLD_AUD_SRC_C_FIFO_EN     0x00000040
+#define  FLD_AUD_SRC_B_FIFO_EN     0x00000020
+#define  FLD_AUD_SRC_A_FIFO_EN     0x00000010
+
+#define  FLD_AUD_DST_D_FIFO_EN     0x00000008
+#define  FLD_AUD_DST_C_FIFO_EN     0x00000004
+#define  FLD_AUD_DST_B_FIFO_EN     0x00000002
+#define  FLD_AUD_DST_A_FIFO_EN     0x00000001
+
+/* ***************************************************************************** */
+/*  */
+/* Mobilygen Interface Registers */
+/*  */
+/* ***************************************************************************** */
+/* Mobilygen Interface A */
+/* ***************************************************************************** */
+#define  MB_IF_A_DMA               0x150000	/* MBIF A DMA data port */
+#define  MB_IF_A_GPCN              0x150008	/* MBIF A GP counter */
+#define  MB_IF_A_GPCN_CTRL         0x15000C
+#define  MB_IF_A_DMA_CTRL          0x150010
+#define  MB_IF_A_LENGTH            0x150014
+#define  MB_IF_A_HDMA_XFER_SZ      0x150018
+#define  MB_IF_A_HCMD              0x15001C
+#define  MB_IF_A_HCONFIG           0x150020
+#define  MB_IF_A_DATA_STRUCT_0     0x150024
+#define  MB_IF_A_DATA_STRUCT_1     0x150028
+#define  MB_IF_A_DATA_STRUCT_2     0x15002C
+#define  MB_IF_A_DATA_STRUCT_3     0x150030
+#define  MB_IF_A_DATA_STRUCT_4     0x150034
+#define  MB_IF_A_DATA_STRUCT_5     0x150038
+#define  MB_IF_A_DATA_STRUCT_6     0x15003C
+#define  MB_IF_A_DATA_STRUCT_7     0x150040
+#define  MB_IF_A_DATA_STRUCT_8     0x150044
+#define  MB_IF_A_DATA_STRUCT_9     0x150048
+#define  MB_IF_A_DATA_STRUCT_A     0x15004C
+#define  MB_IF_A_DATA_STRUCT_B     0x150050
+#define  MB_IF_A_DATA_STRUCT_C     0x150054
+#define  MB_IF_A_DATA_STRUCT_D     0x150058
+#define  MB_IF_A_DATA_STRUCT_E     0x15005C
+#define  MB_IF_A_DATA_STRUCT_F     0x150060
+/* ***************************************************************************** */
+/* Mobilygen Interface B */
+/* ***************************************************************************** */
+#define  MB_IF_B_DMA               0x160000	/* MBIF A DMA data port */
+#define  MB_IF_B_GPCN              0x160008	/* MBIF A GP counter */
+#define  MB_IF_B_GPCN_CTRL         0x16000C
+#define  MB_IF_B_DMA_CTRL          0x160010
+#define  MB_IF_B_LENGTH            0x160014
+#define  MB_IF_B_HDMA_XFER_SZ      0x160018
+#define  MB_IF_B_HCMD              0x16001C
+#define  MB_IF_B_HCONFIG           0x160020
+#define  MB_IF_B_DATA_STRUCT_0     0x160024
+#define  MB_IF_B_DATA_STRUCT_1     0x160028
+#define  MB_IF_B_DATA_STRUCT_2     0x16002C
+#define  MB_IF_B_DATA_STRUCT_3     0x160030
+#define  MB_IF_B_DATA_STRUCT_4     0x160034
+#define  MB_IF_B_DATA_STRUCT_5     0x160038
+#define  MB_IF_B_DATA_STRUCT_6     0x16003C
+#define  MB_IF_B_DATA_STRUCT_7     0x160040
+#define  MB_IF_B_DATA_STRUCT_8     0x160044
+#define  MB_IF_B_DATA_STRUCT_9     0x160048
+#define  MB_IF_B_DATA_STRUCT_A     0x16004C
+#define  MB_IF_B_DATA_STRUCT_B     0x160050
+#define  MB_IF_B_DATA_STRUCT_C     0x160054
+#define  MB_IF_B_DATA_STRUCT_D     0x160058
+#define  MB_IF_B_DATA_STRUCT_E     0x16005C
+#define  MB_IF_B_DATA_STRUCT_F     0x160060
+
+/* MB_DMA_CTRL */
+#define  FLD_MB_IF_RISC_EN         0x00000010
+#define  FLD_MB_IF_FIFO_EN         0x00000001
+
+/* MB_LENGTH */
+#define  FLD_MB_IF_LN_LNGTH        0x00000FFF
+
+/* MB_HCMD register */
+#define  FLD_MB_HCMD_H_GO          0x80000000
+#define  FLD_MB_HCMD_H_BUSY        0x40000000
+#define  FLD_MB_HCMD_H_DMA_HOLD    0x10000000
+#define  FLD_MB_HCMD_H_DMA_BUSY    0x08000000
+#define  FLD_MB_HCMD_H_DMA_TYPE    0x04000000
+#define  FLD_MB_HCMD_H_DMA_XACT    0x02000000
+#define  FLD_MB_HCMD_H_RW_N        0x01000000
+#define  FLD_MB_HCMD_H_ADDR        0x00FF0000
+#define  FLD_MB_HCMD_H_DATA        0x0000FFFF
+
+/* ***************************************************************************** */
+/* I2C #1 */
+/* ***************************************************************************** */
+#define  I2C1_ADDR                 0x180000	/* I2C #1 address */
+#define  FLD_I2C_DADDR             0xfe000000	/* RW [31:25] I2C Device Address */
+						 /* RO [24] reserved */
+/* ***************************************************************************** */
+#define  FLD_I2C_SADDR             0x00FFFFFF	/* RW [23:0]  I2C Sub-address */
+
+/* ***************************************************************************** */
+#define  I2C1_WDATA                0x180004	/* I2C #1 write data */
+#define  FLD_I2C_WDATA             0xFFFFFFFF	/* RW [31:0] */
+
+/* ***************************************************************************** */
+#define  I2C1_CTRL                 0x180008	/* I2C #1 control */
+#define  FLD_I2C_PERIOD            0xFF000000	/* RW [31:24] */
+#define  FLD_I2C_SCL_IN            0x00200000	/* RW [21] */
+#define  FLD_I2C_SDA_IN            0x00100000	/* RW [20] */
+						 /* RO [19:18] reserved */
+#define  FLD_I2C_SCL_OUT           0x00020000	/* RW [17] */
+#define  FLD_I2C_SDA_OUT           0x00010000	/* RW [16] */
+						 /* RO [15] reserved */
+#define  FLD_I2C_DATA_LEN          0x00007000	/* RW [14:12] */
+#define  FLD_I2C_SADDR_INC         0x00000800	/* RW [11] */
+						 /* RO [10:9] reserved */
+#define  FLD_I2C_SADDR_LEN         0x00000300	/* RW [9:8] */
+						 /* RO [7:6] reserved */
+#define  FLD_I2C_SOFT              0x00000020	/* RW [5] */
+#define  FLD_I2C_NOSTOP            0x00000010	/* RW [4] */
+#define  FLD_I2C_EXTEND            0x00000008	/* RW [3] */
+#define  FLD_I2C_SYNC              0x00000004	/* RW [2] */
+#define  FLD_I2C_READ_SA           0x00000002	/* RW [1] */
+#define  FLD_I2C_READ_WRN          0x00000001	/* RW [0] */
+
+/* ***************************************************************************** */
+#define  I2C1_RDATA                0x18000C	/* I2C #1 read data */
+#define  FLD_I2C_RDATA             0xFFFFFFFF	/* RO [31:0] */
+
+/* ***************************************************************************** */
+#define  I2C1_STAT                 0x180010	/* I2C #1 status */
+#define  FLD_I2C_XFER_IN_PROG      0x00000002	/* RO [1] */
+#define  FLD_I2C_RACK              0x00000001	/* RO [0] */
+
+/* ***************************************************************************** */
+/* I2C #2 */
+/* ***************************************************************************** */
+#define  I2C2_ADDR                 0x190000	/* I2C #2 address */
+
+/* ***************************************************************************** */
+#define  I2C2_WDATA                0x190004	/* I2C #2 write data */
+
+/* ***************************************************************************** */
+#define  I2C2_CTRL                 0x190008	/* I2C #2 control */
+
+/* ***************************************************************************** */
+#define  I2C2_RDATA                0x19000C	/* I2C #2 read data */
+
+/* ***************************************************************************** */
+#define  I2C2_STAT                 0x190010	/* I2C #2 status */
+
+/* ***************************************************************************** */
+/* I2C #3 */
+/* ***************************************************************************** */
+#define  I2C3_ADDR                 0x1A0000	/* I2C #3 address */
+
+/* ***************************************************************************** */
+#define  I2C3_WDATA                0x1A0004	/* I2C #3 write data */
+
+/* ***************************************************************************** */
+#define  I2C3_CTRL                 0x1A0008	/* I2C #3 control */
+
+/* ***************************************************************************** */
+#define  I2C3_RDATA                0x1A000C	/* I2C #3 read data */
+
+/* ***************************************************************************** */
+#define  I2C3_STAT                 0x1A0010	/* I2C #3 status */
+
+/* ***************************************************************************** */
+/* UART */
+/* ***************************************************************************** */
+#define  UART_CTL                  0x1B0000	/* UART Control Register */
+#define  FLD_LOOP_BACK_EN          (1 << 7)	/* RW field - default 0 */
+#define  FLD_RX_TRG_SZ             (3 << 2)	/* RW field - default 0 */
+#define  FLD_RX_EN                 (1 << 1)	/* RW field - default 0 */
+#define  FLD_TX_EN                 (1 << 0)	/* RW field - default 0 */
+
+/* ***************************************************************************** */
+#define  UART_BRD                  0x1B0004	/* UART Baud Rate Divisor */
+#define  FLD_BRD                   0x0000FFFF	/* RW field - default 0x197 */
+
+/* ***************************************************************************** */
+#define  UART_DBUF                 0x1B0008	/* UART Tx/Rx Data BuFFer */
+#define  FLD_DB                    0xFFFFFFFF	/* RW field - default 0 */
+
+/* ***************************************************************************** */
+#define  UART_ISR                  0x1B000C	/* UART Interrupt Status */
+#define  FLD_RXD_TIMEOUT_EN        (1 << 7)	/* RW field - default 0 */
+#define  FLD_FRM_ERR_EN            (1 << 6)	/* RW field - default 0 */
+#define  FLD_RXD_RDY_EN            (1 << 5)	/* RW field - default 0 */
+#define  FLD_TXD_EMPTY_EN          (1 << 4)	/* RW field - default 0 */
+#define  FLD_RXD_OVERFLOW          (1 << 3)	/* RW field - default 0 */
+#define  FLD_FRM_ERR               (1 << 2)	/* RW field - default 0 */
+#define  FLD_RXD_RDY               (1 << 1)	/* RW field - default 0 */
+#define  FLD_TXD_EMPTY             (1 << 0)	/* RW field - default 0 */
+
+/* ***************************************************************************** */
+#define  UART_CNT                  0x1B0010	/* UART Tx/Rx FIFO Byte Count */
+#define  FLD_TXD_CNT               (0x1F << 8)	/* RW field - default 0 */
+#define  FLD_RXD_CNT               (0x1F << 0)	/* RW field - default 0 */
+
+/* ***************************************************************************** */
+/* Motion Detection */
+#define  MD_CH0_GRID_BLOCK_YCNT    0x170014
+#define  MD_CH1_GRID_BLOCK_YCNT    0x170094
+#define  MD_CH2_GRID_BLOCK_YCNT    0x170114
+#define  MD_CH3_GRID_BLOCK_YCNT    0x170194
+#define  MD_CH4_GRID_BLOCK_YCNT    0x170214
+#define  MD_CH5_GRID_BLOCK_YCNT    0x170294
+#define  MD_CH6_GRID_BLOCK_YCNT    0x170314
+#define  MD_CH7_GRID_BLOCK_YCNT    0x170394
+
+#define PIXEL_FRMT_422    4
+#define PIXEL_FRMT_411    5
+#define PIXEL_FRMT_Y8     6
+
+#define PIXEL_ENGINE_VIP1 0
+#define PIXEL_ENGINE_VIP2 1
+
+#endif /* Athena_REGISTERS */
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-sram.h linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-sram.h
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-sram.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-sram.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,261 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 __ATHENA_SRAM_H__
+#define __ATHENA_SRAM_H__
+
+/* #define RX_SRAM_START_SIZE        = 0;  //  Start of reserved SRAM */
+#define VID_CMDS_SIZE             80	/* Video CMDS size in bytes */
+#define AUDIO_CMDS_SIZE           80	/* AUDIO CMDS size in bytes */
+#define MBIF_CMDS_SIZE            80	/* MBIF  CMDS size in bytes */
+
+/* #define RX_SRAM_POOL_START_SIZE   = 0;  //  Start of useable RX SRAM for buffers */
+#define VID_IQ_SIZE               64	/* VID instruction queue size in bytes */
+#define MBIF_IQ_SIZE              64
+#define AUDIO_IQ_SIZE             64	/* AUD instruction queue size in bytes */
+
+#define VID_CDT_SIZE              64	/* VID cluster descriptor table size in bytes */
+#define MBIF_CDT_SIZE             64	/* MBIF/HBI cluster descriptor table size in bytes */
+#define AUDIO_CDT_SIZE            48	/* AUD cluster descriptor table size in bytes */
+
+/* #define RX_SRAM_POOL_FREE_SIZE    = 16; //  Start of available RX SRAM */
+/* #define RX_SRAM_END_SIZE          = 0;  //  End of RX SRAM */
+
+/* #define TX_SRAM_POOL_START_SIZE   = 0;  //  Start of transmit pool SRAM */
+/* #define MSI_DATA_SIZE             = 64; //  Reserved (MSI Data, RISC working stora */
+
+#define VID_CLUSTER_SIZE          1440	/* VID cluster data line */
+#define AUDIO_CLUSTER_SIZE        128	/* AUDIO cluster data line */
+#define MBIF_CLUSTER_SIZE         1440	/* MBIF/HBI cluster data line */
+
+/* #define TX_SRAM_POOL_FREE_SIZE    = 704;    //  Start of available TX SRAM */
+/* #define TX_SRAM_END_SIZE          = 0;      //  End of TX SRAM */
+
+/* Receive SRAM */
+#define RX_SRAM_START             0x10000
+#define VID_A_DOWN_CMDS           0x10000
+#define VID_B_DOWN_CMDS           0x10050
+#define VID_C_DOWN_CMDS           0x100A0
+#define VID_D_DOWN_CMDS           0x100F0
+#define VID_E_DOWN_CMDS           0x10140
+#define VID_F_DOWN_CMDS           0x10190
+#define VID_G_DOWN_CMDS           0x101E0
+#define VID_H_DOWN_CMDS           0x10230
+#define VID_A_UP_CMDS             0x10280
+#define VID_B_UP_CMDS             0x102D0
+#define VID_C_UP_CMDS             0x10320
+#define VID_D_UP_CMDS             0x10370
+#define VID_E_UP_CMDS             0x103C0
+#define VID_F_UP_CMDS             0x10410
+#define VID_I_UP_CMDS             0x10460
+#define VID_J_UP_CMDS             0x104B0
+#define AUD_A_DOWN_CMDS           0x10500
+#define AUD_B_DOWN_CMDS           0x10550
+#define AUD_C_DOWN_CMDS           0x105A0
+#define AUD_D_DOWN_CMDS           0x105F0
+#define AUD_A_UP_CMDS             0x10640
+#define AUD_B_UP_CMDS             0x10690
+#define AUD_C_UP_CMDS             0x106E0
+#define AUD_E_UP_CMDS             0x10730
+#define MBIF_A_DOWN_CMDS          0x10780
+#define MBIF_B_DOWN_CMDS          0x107D0
+#define DMA_SCRATCH_PAD           0x10820	/* Scratch pad area from 0x10820 to 0x10B40 */
+
+/* #define RX_SRAM_POOL_START        = 0x105B0; */
+
+#define VID_A_IQ                  0x11000
+#define VID_B_IQ                  0x11040
+#define VID_C_IQ                  0x11080
+#define VID_D_IQ                  0x110C0
+#define VID_E_IQ                  0x11100
+#define VID_F_IQ                  0x11140
+#define VID_G_IQ                  0x11180
+#define VID_H_IQ                  0x111C0
+#define VID_I_IQ                  0x11200
+#define VID_J_IQ                  0x11240
+#define AUD_A_IQ                  0x11280
+#define AUD_B_IQ                  0x112C0
+#define AUD_C_IQ                  0x11300
+#define AUD_D_IQ                  0x11340
+#define AUD_E_IQ                  0x11380
+#define MBIF_A_IQ                 0x11000
+#define MBIF_B_IQ                 0x110C0
+
+#define VID_A_CDT                 0x10C00
+#define VID_B_CDT                 0x10C40
+#define VID_C_CDT                 0x10C80
+#define VID_D_CDT                 0x10CC0
+#define VID_E_CDT                 0x10D00
+#define VID_F_CDT                 0x10D40
+#define VID_G_CDT                 0x10D80
+#define VID_H_CDT                 0x10DC0
+#define VID_I_CDT                 0x10E00
+#define VID_J_CDT                 0x10E40
+#define AUD_A_CDT                 0x10E80
+#define AUD_B_CDT                 0x10EB0
+#define AUD_C_CDT                 0x10EE0
+#define AUD_D_CDT                 0x10F10
+#define AUD_E_CDT                 0x10F40
+#define MBIF_A_CDT                0x10C00
+#define MBIF_B_CDT                0x10CC0
+
+/* Cluster Buffer for RX */
+#define VID_A_UP_CLUSTER_1        0x11400
+#define VID_A_UP_CLUSTER_2        0x119A0
+#define VID_A_UP_CLUSTER_3        0x11F40
+#define VID_A_UP_CLUSTER_4        0x124E0
+
+#define VID_B_UP_CLUSTER_1        0x12A80
+#define VID_B_UP_CLUSTER_2        0x13020
+#define VID_B_UP_CLUSTER_3        0x135C0
+#define VID_B_UP_CLUSTER_4        0x13B60
+
+#define VID_C_UP_CLUSTER_1        0x14100
+#define VID_C_UP_CLUSTER_2        0x146A0
+#define VID_C_UP_CLUSTER_3        0x14C40
+#define VID_C_UP_CLUSTER_4        0x151E0
+
+#define VID_D_UP_CLUSTER_1        0x15780
+#define VID_D_UP_CLUSTER_2        0x15D20
+#define VID_D_UP_CLUSTER_3        0x162C0
+#define VID_D_UP_CLUSTER_4        0x16860
+
+#define VID_E_UP_CLUSTER_1        0x16E00
+#define VID_E_UP_CLUSTER_2        0x173A0
+#define VID_E_UP_CLUSTER_3        0x17940
+#define VID_E_UP_CLUSTER_4        0x17EE0
+
+#define VID_F_UP_CLUSTER_1        0x18480
+#define VID_F_UP_CLUSTER_2        0x18A20
+#define VID_F_UP_CLUSTER_3        0x18FC0
+#define VID_F_UP_CLUSTER_4        0x19560
+
+#define VID_I_UP_CLUSTER_1        0x19B00
+#define VID_I_UP_CLUSTER_2        0x1A0A0
+#define VID_I_UP_CLUSTER_3        0x1A640
+#define VID_I_UP_CLUSTER_4        0x1ABE0
+
+#define VID_J_UP_CLUSTER_1        0x1B180
+#define VID_J_UP_CLUSTER_2        0x1B720
+#define VID_J_UP_CLUSTER_3        0x1BCC0
+#define VID_J_UP_CLUSTER_4        0x1C260
+
+#define AUD_A_UP_CLUSTER_1        0x1C800
+#define AUD_A_UP_CLUSTER_2        0x1C880
+#define AUD_A_UP_CLUSTER_3        0x1C900
+
+#define AUD_B_UP_CLUSTER_1        0x1C980
+#define AUD_B_UP_CLUSTER_2        0x1CA00
+#define AUD_B_UP_CLUSTER_3        0x1CA80
+
+#define AUD_C_UP_CLUSTER_1        0x1CB00
+#define AUD_C_UP_CLUSTER_2        0x1CB80
+#define AUD_C_UP_CLUSTER_3        0x1CC00
+
+#define AUD_E_UP_CLUSTER_1        0x1CC80
+#define AUD_E_UP_CLUSTER_2        0x1CD00
+#define AUD_E_UP_CLUSTER_3        0x1CD80
+
+#define RX_SRAM_POOL_FREE         0x1CE00
+#define RX_SRAM_END               0x1D000
+
+/* Free Receive SRAM    144 Bytes */
+
+/* Transmit SRAM */
+#define TX_SRAM_POOL_START        0x00000
+
+#define VID_A_DOWN_CLUSTER_1      0x00040
+#define VID_A_DOWN_CLUSTER_2      0x005E0
+#define VID_A_DOWN_CLUSTER_3      0x00B80
+#define VID_A_DOWN_CLUSTER_4      0x01120
+
+#define VID_B_DOWN_CLUSTER_1      0x016C0
+#define VID_B_DOWN_CLUSTER_2      0x01C60
+#define VID_B_DOWN_CLUSTER_3      0x02200
+#define VID_B_DOWN_CLUSTER_4      0x027A0
+
+#define VID_C_DOWN_CLUSTER_1      0x02D40
+#define VID_C_DOWN_CLUSTER_2      0x032E0
+#define VID_C_DOWN_CLUSTER_3      0x03880
+#define VID_C_DOWN_CLUSTER_4      0x03E20
+
+#define VID_D_DOWN_CLUSTER_1      0x043C0
+#define VID_D_DOWN_CLUSTER_2      0x04960
+#define VID_D_DOWN_CLUSTER_3      0x04F00
+#define VID_D_DOWN_CLUSTER_4      0x054A0
+
+#define VID_E_DOWN_CLUSTER_1      0x05a40
+#define VID_E_DOWN_CLUSTER_2      0x05FE0
+#define VID_E_DOWN_CLUSTER_3      0x06580
+#define VID_E_DOWN_CLUSTER_4      0x06B20
+
+#define VID_F_DOWN_CLUSTER_1      0x070C0
+#define VID_F_DOWN_CLUSTER_2      0x07660
+#define VID_F_DOWN_CLUSTER_3      0x07C00
+#define VID_F_DOWN_CLUSTER_4      0x081A0
+
+#define VID_G_DOWN_CLUSTER_1      0x08740
+#define VID_G_DOWN_CLUSTER_2      0x08CE0
+#define VID_G_DOWN_CLUSTER_3      0x09280
+#define VID_G_DOWN_CLUSTER_4      0x09820
+
+#define VID_H_DOWN_CLUSTER_1      0x09DC0
+#define VID_H_DOWN_CLUSTER_2      0x0A360
+#define VID_H_DOWN_CLUSTER_3      0x0A900
+#define VID_H_DOWN_CLUSTER_4      0x0AEA0
+
+#define AUD_A_DOWN_CLUSTER_1      0x0B500
+#define AUD_A_DOWN_CLUSTER_2      0x0B580
+#define AUD_A_DOWN_CLUSTER_3      0x0B600
+
+#define AUD_B_DOWN_CLUSTER_1      0x0B680
+#define AUD_B_DOWN_CLUSTER_2      0x0B700
+#define AUD_B_DOWN_CLUSTER_3      0x0B780
+
+#define AUD_C_DOWN_CLUSTER_1      0x0B800
+#define AUD_C_DOWN_CLUSTER_2      0x0B880
+#define AUD_C_DOWN_CLUSTER_3      0x0B900
+
+#define AUD_D_DOWN_CLUSTER_1      0x0B980
+#define AUD_D_DOWN_CLUSTER_2      0x0BA00
+#define AUD_D_DOWN_CLUSTER_3      0x0BA80
+
+#define TX_SRAM_POOL_FREE         0x0BB00
+#define TX_SRAM_END               0x0C000
+
+#define BYTES_TO_DWORDS(bcount) ((bcount) >> 2)
+#define BYTES_TO_QWORDS(bcount) ((bcount) >> 3)
+#define BYTES_TO_OWORDS(bcount) ((bcount) >> 4)
+
+#define VID_IQ_SIZE_DW             BYTES_TO_DWORDS(VID_IQ_SIZE)
+#define VID_CDT_SIZE_QW            BYTES_TO_QWORDS(VID_CDT_SIZE)
+#define VID_CLUSTER_SIZE_OW        BYTES_TO_OWORDS(VID_CLUSTER_SIZE)
+
+#define AUDIO_IQ_SIZE_DW           BYTES_TO_DWORDS(AUDIO_IQ_SIZE)
+#define AUDIO_CDT_SIZE_QW          BYTES_TO_QWORDS(AUDIO_CDT_SIZE)
+#define AUDIO_CLUSTER_SIZE_QW      BYTES_TO_QWORDS(AUDIO_CLUSTER_SIZE)
+
+#define MBIF_IQ_SIZE_DW            BYTES_TO_DWORDS(MBIF_IQ_SIZE)
+#define MBIF_CDT_SIZE_QW           BYTES_TO_QWORDS(MBIF_CDT_SIZE)
+#define MBIF_CLUSTER_SIZE_OW       BYTES_TO_OWORDS(MBIF_CLUSTER_SIZE)
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-video.c linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-video.c
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-video.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-video.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2012 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *  Parts adapted/taken from Eduardo Moscoso Rubino
+ *  Copyright (C) 2009 Eduardo Moscoso Rubino <moscoso@TopoLogica.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 "cx25821-video.h"
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(video_nr, int, NULL, 0444);
+module_param_array(radio_nr, int, NULL, 0444);
+
+MODULE_PARM_DESC(video_nr, "video device numbers");
+MODULE_PARM_DESC(radio_nr, "radio device numbers");
+
+static unsigned int video_debug = VIDEO_DEBUG;
+module_param(video_debug, int, 0644);
+MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
+
+static unsigned int irq_debug;
+module_param(irq_debug, int, 0644);
+MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]");
+
+unsigned int vid_limit = 16;
+module_param(vid_limit, int, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
+
+static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num);
+
+static const struct v4l2_file_operations video_fops;
+static const struct v4l2_ioctl_ops video_ioctl_ops;
+
+#define FORMAT_FLAGS_PACKED       0x01
+
+struct cx25821_fmt formats[] = {
+	{
+		.name = "8 bpp, gray",
+		.fourcc = V4L2_PIX_FMT_GREY,
+		.depth = 8,
+		.flags = FORMAT_FLAGS_PACKED,
+	 }, {
+		.name = "4:1:1, packed, Y41P",
+		.fourcc = V4L2_PIX_FMT_Y41P,
+		.depth = 12,
+		.flags = FORMAT_FLAGS_PACKED,
+	}, {
+		.name = "4:2:2, packed, YUYV",
+		.fourcc = V4L2_PIX_FMT_YUYV,
+		.depth = 16,
+		.flags = FORMAT_FLAGS_PACKED,
+	}, {
+		.name = "4:2:2, packed, UYVY",
+		.fourcc = V4L2_PIX_FMT_UYVY,
+		.depth = 16,
+		.flags = FORMAT_FLAGS_PACKED,
+	}, {
+		.name = "4:2:0, YUV",
+		.fourcc = V4L2_PIX_FMT_YUV420,
+		.depth = 12,
+		.flags = FORMAT_FLAGS_PACKED,
+	},
+};
+
+int cx25821_get_format_size(void)
+{
+	return ARRAY_SIZE(formats);
+}
+
+struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc)
+{
+	unsigned int i;
+
+	if (fourcc == V4L2_PIX_FMT_Y41P || fourcc == V4L2_PIX_FMT_YUV411P)
+		return formats + 1;
+
+	for (i = 0; i < ARRAY_SIZE(formats); i++)
+		if (formats[i].fourcc == fourcc)
+			return formats + i;
+
+	pr_err("%s(0x%08x) NOT FOUND\n", __func__, fourcc);
+	return NULL;
+}
+
+void cx25821_dump_video_queue(struct cx25821_dev *dev,
+			      struct cx25821_dmaqueue *q)
+{
+	struct cx25821_buffer *buf;
+	struct list_head *item;
+	dprintk(1, "%s()\n", __func__);
+
+	if (!list_empty(&q->active)) {
+		list_for_each(item, &q->active)
+		    buf = list_entry(item, struct cx25821_buffer, vb.queue);
+	}
+
+	if (!list_empty(&q->queued)) {
+		list_for_each(item, &q->queued)
+		    buf = list_entry(item, struct cx25821_buffer, vb.queue);
+	}
+
+}
+
+void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q,
+			  u32 count)
+{
+	struct cx25821_buffer *buf;
+	int bc;
+
+	for (bc = 0;; bc++) {
+		if (list_empty(&q->active)) {
+			dprintk(1, "bc=%d (=0: active empty)\n", bc);
+			break;
+		}
+
+		buf =
+		    list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+
+		/* count comes from the hw and it is 16bit wide --
+		 * this trick handles wrap-arounds correctly for
+		 * up to 32767 buffers in flight... */
+		if ((s16) (count - buf->count) < 0)
+			break;
+
+		do_gettimeofday(&buf->vb.ts);
+		buf->vb.state = VIDEOBUF_DONE;
+		list_del(&buf->vb.queue);
+		wake_up(&buf->vb.done);
+	}
+
+	if (list_empty(&q->active))
+		del_timer(&q->timeout);
+	else
+		mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+	if (bc != 1)
+		pr_err("%s: %d buffers handled (should be 1)\n", __func__, bc);
+}
+
+#ifdef TUNER_FLAG
+int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm)
+{
+	dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
+		__func__, (unsigned int)norm, v4l2_norm_to_name(norm));
+
+	dev->tvnorm = norm;
+
+	/* Tell the internal A/V decoder */
+	cx25821_call_all(dev, core, s_std, norm);
+
+	return 0;
+}
+#endif
+
+struct video_device *cx25821_vdev_init(struct cx25821_dev *dev,
+				       struct pci_dev *pci,
+				       struct video_device *template,
+				       char *type)
+{
+	struct video_device *vfd;
+	dprintk(1, "%s()\n", __func__);
+
+	vfd = video_device_alloc();
+	if (NULL == vfd)
+		return NULL;
+	*vfd = *template;
+	vfd->v4l2_dev = &dev->v4l2_dev;
+	vfd->release = video_device_release;
+	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type,
+		 cx25821_boards[dev->board].name);
+	video_set_drvdata(vfd, dev);
+	return vfd;
+}
+
+/*
+static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl)
+{
+	int i;
+
+	if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1)
+		return -EINVAL;
+	for (i = 0; i < CX25821_CTLS; i++)
+		if (cx25821_ctls[i].v.id == qctrl->id)
+			break;
+	if (i == CX25821_CTLS) {
+		*qctrl = no_ctl;
+		return 0;
+	}
+	*qctrl = cx25821_ctls[i].v;
+	return 0;
+}
+*/
+
+/* resource management */
+int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh,
+		    unsigned int bit)
+{
+	dprintk(1, "%s()\n", __func__);
+	if (fh->resources & bit)
+		/* have it already allocated */
+		return 1;
+
+	/* is it free? */
+	mutex_lock(&dev->lock);
+	if (dev->channels[fh->channel_id].resources & bit) {
+		/* no, someone else uses it */
+		mutex_unlock(&dev->lock);
+		return 0;
+	}
+	/* it's free, grab it */
+	fh->resources |= bit;
+	dev->channels[fh->channel_id].resources |= bit;
+	dprintk(1, "res: get %d\n", bit);
+	mutex_unlock(&dev->lock);
+	return 1;
+}
+
+int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit)
+{
+	return fh->resources & bit;
+}
+
+int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit)
+{
+	return fh->dev->channels[fh->channel_id].resources & bit;
+}
+
+void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh,
+		      unsigned int bits)
+{
+	BUG_ON((fh->resources & bits) != bits);
+	dprintk(1, "%s()\n", __func__);
+
+	mutex_lock(&dev->lock);
+	fh->resources &= ~bits;
+	dev->channels[fh->channel_id].resources &= ~bits;
+	dprintk(1, "res: put %d\n", bits);
+	mutex_unlock(&dev->lock);
+}
+
+int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input)
+{
+	struct v4l2_routing route;
+	memset(&route, 0, sizeof(route));
+
+	dprintk(1, "%s(): video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
+		__func__, input, INPUT(input)->vmux, INPUT(input)->gpio0,
+		INPUT(input)->gpio1, INPUT(input)->gpio2, INPUT(input)->gpio3);
+	dev->input = input;
+
+	route.input = INPUT(input)->vmux;
+
+	/* Tell the internal A/V decoder */
+	cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0);
+
+	return 0;
+}
+
+int cx25821_start_video_dma(struct cx25821_dev *dev,
+			    struct cx25821_dmaqueue *q,
+			    struct cx25821_buffer *buf,
+			    struct sram_channel *channel)
+{
+	int tmp = 0;
+
+	/* setup fifo + format */
+	cx25821_sram_channel_setup(dev, channel, buf->bpl, buf->risc.dma);
+
+	/* reset counter */
+	cx_write(channel->gpcnt_ctl, 3);
+	q->count = 1;
+
+	/* enable irq */
+	cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << channel->i));
+	cx_set(channel->int_msk, 0x11);
+
+	/* start dma */
+	cx_write(channel->dma_ctl, 0x11);	/* FIFO and RISC enable */
+
+	/* make sure upstream setting if any is reversed */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+
+	return 0;
+}
+
+int cx25821_restart_video_queue(struct cx25821_dev *dev,
+				struct cx25821_dmaqueue *q,
+				struct sram_channel *channel)
+{
+	struct cx25821_buffer *buf, *prev;
+	struct list_head *item;
+
+	if (!list_empty(&q->active)) {
+		buf =
+		    list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+
+		cx25821_start_video_dma(dev, q, buf, channel);
+
+		list_for_each(item, &q->active) {
+			buf = list_entry(item, struct cx25821_buffer, vb.queue);
+			buf->count = q->count++;
+		}
+
+		mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+		return 0;
+	}
+
+	prev = NULL;
+	for (;;) {
+		if (list_empty(&q->queued))
+			return 0;
+
+		buf =
+		    list_entry(q->queued.next, struct cx25821_buffer, vb.queue);
+
+		if (NULL == prev) {
+			list_move_tail(&buf->vb.queue, &q->active);
+			cx25821_start_video_dma(dev, q, buf, channel);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count = q->count++;
+			mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+		} else if (prev->vb.width == buf->vb.width &&
+			   prev->vb.height == buf->vb.height &&
+			   prev->fmt == buf->fmt) {
+			list_move_tail(&buf->vb.queue, &q->active);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count = q->count++;
+			prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+			prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */
+		} else {
+			return 0;
+		}
+		prev = buf;
+	}
+}
+
+void cx25821_vid_timeout(unsigned long data)
+{
+	struct cx25821_data *timeout_data = (struct cx25821_data *)data;
+	struct cx25821_dev *dev = timeout_data->dev;
+	struct sram_channel *channel = timeout_data->channel;
+	struct cx25821_dmaqueue *q = &dev->channels[channel->i].vidq;
+	struct cx25821_buffer *buf;
+	unsigned long flags;
+
+	/* cx25821_sram_channel_dump(dev, channel); */
+	cx_clear(channel->dma_ctl, 0x11);
+
+	spin_lock_irqsave(&dev->slock, flags);
+	while (!list_empty(&q->active)) {
+		buf =
+		    list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+		list_del(&buf->vb.queue);
+
+		buf->vb.state = VIDEOBUF_ERROR;
+		wake_up(&buf->vb.done);
+	}
+
+	cx25821_restart_video_queue(dev, q, channel);
+	spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
+{
+	u32 count = 0;
+	int handled = 0;
+	u32 mask;
+	struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+
+	mask = cx_read(channel->int_msk);
+	if (0 == (status & mask))
+		return handled;
+
+	cx_write(channel->int_stat, status);
+
+	/* risc op code error */
+	if (status & (1 << 16)) {
+		pr_warn("%s, %s: video risc op code error\n",
+			dev->name, channel->name);
+		cx_clear(channel->dma_ctl, 0x11);
+		cx25821_sram_channel_dump(dev, channel);
+	}
+
+	/* risc1 y */
+	if (status & FLD_VID_DST_RISC1) {
+		spin_lock(&dev->slock);
+		count = cx_read(channel->gpcnt);
+		cx25821_video_wakeup(dev, &dev->channels[channel->i].vidq,
+				count);
+		spin_unlock(&dev->slock);
+		handled++;
+	}
+
+	/* risc2 y */
+	if (status & 0x10) {
+		dprintk(2, "stopper video\n");
+		spin_lock(&dev->slock);
+		cx25821_restart_video_queue(dev,
+				&dev->channels[channel->i].vidq, channel);
+		spin_unlock(&dev->slock);
+		handled++;
+	}
+	return handled;
+}
+
+void cx25821_videoioctl_unregister(struct cx25821_dev *dev)
+{
+	if (dev->ioctl_dev) {
+		if (video_is_registered(dev->ioctl_dev))
+			video_unregister_device(dev->ioctl_dev);
+		else
+			video_device_release(dev->ioctl_dev);
+
+		dev->ioctl_dev = NULL;
+	}
+}
+
+void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num)
+{
+	cx_clear(PCI_INT_MSK, 1);
+
+	if (dev->channels[chan_num].video_dev) {
+		if (video_is_registered(dev->channels[chan_num].video_dev))
+			video_unregister_device(
+					dev->channels[chan_num].video_dev);
+		else
+			video_device_release(
+					dev->channels[chan_num].video_dev);
+
+		dev->channels[chan_num].video_dev = NULL;
+
+		btcx_riscmem_free(dev->pci,
+				&dev->channels[chan_num].vidq.stopper);
+
+		pr_warn("device %d released!\n", chan_num);
+	}
+
+}
+
+int cx25821_video_register(struct cx25821_dev *dev)
+{
+	int err;
+	int i;
+
+	struct video_device cx25821_video_device = {
+		.name = "cx25821-video",
+		.fops = &video_fops,
+		.minor = -1,
+		.ioctl_ops = &video_ioctl_ops,
+		.tvnorms = CX25821_NORMS,
+		.current_norm = V4L2_STD_NTSC_M,
+	};
+
+	spin_lock_init(&dev->slock);
+
+	for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; ++i) {
+		cx25821_init_controls(dev, i);
+
+		cx25821_risc_stopper(dev->pci, &dev->channels[i].vidq.stopper,
+				dev->channels[i].sram_channels->dma_ctl,
+				0x11, 0);
+
+		dev->channels[i].sram_channels = &cx25821_sram_channels[i];
+		dev->channels[i].video_dev = NULL;
+		dev->channels[i].resources = 0;
+
+		cx_write(dev->channels[i].sram_channels->int_stat, 0xffffffff);
+
+		INIT_LIST_HEAD(&dev->channels[i].vidq.active);
+		INIT_LIST_HEAD(&dev->channels[i].vidq.queued);
+
+		dev->channels[i].timeout_data.dev = dev;
+		dev->channels[i].timeout_data.channel =
+			&cx25821_sram_channels[i];
+		dev->channels[i].vidq.timeout.function =
+			cx25821_vid_timeout;
+		dev->channels[i].vidq.timeout.data =
+			(unsigned long)&dev->channels[i].timeout_data;
+		init_timer(&dev->channels[i].vidq.timeout);
+
+		/* register v4l devices */
+		dev->channels[i].video_dev = cx25821_vdev_init(dev,
+				dev->pci, &cx25821_video_device, "video");
+
+		err = video_register_device(dev->channels[i].video_dev,
+				VFL_TYPE_GRABBER, video_nr[dev->nr]);
+
+		if (err < 0)
+			goto fail_unreg;
+
+	}
+
+	/* set PCI interrupt */
+	cx_set(PCI_INT_MSK, 0xff);
+
+	/* initial device configuration */
+	mutex_lock(&dev->lock);
+#ifdef TUNER_FLAG
+	dev->tvnorm = cx25821_video_device.current_norm;
+	cx25821_set_tvnorm(dev, dev->tvnorm);
+#endif
+	mutex_unlock(&dev->lock);
+
+
+	return 0;
+
+fail_unreg:
+	cx25821_video_unregister(dev, i);
+	return err;
+}
+
+int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count,
+		 unsigned int *size)
+{
+	struct cx25821_fh *fh = q->priv_data;
+
+	*size = fh->fmt->depth * fh->width * fh->height >> 3;
+
+	if (0 == *count)
+		*count = 32;
+
+	if (*size * *count > vid_limit * 1024 * 1024)
+		*count = (vid_limit * 1024 * 1024) / *size;
+
+	return 0;
+}
+
+int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+		   enum v4l2_field field)
+{
+	struct cx25821_fh *fh = q->priv_data;
+	struct cx25821_dev *dev = fh->dev;
+	struct cx25821_buffer *buf =
+	    container_of(vb, struct cx25821_buffer, vb);
+	int rc, init_buffer = 0;
+	u32 line0_offset, line1_offset;
+	struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+	int bpl_local = LINE_SIZE_D1;
+	int channel_opened = fh->channel_id;
+
+	BUG_ON(NULL == fh->fmt);
+	if (fh->width < 48 || fh->width > 720 ||
+	    fh->height < 32 || fh->height > 576)
+		return -EINVAL;
+
+	buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
+
+	if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
+		return -EINVAL;
+
+	if (buf->fmt != fh->fmt ||
+	    buf->vb.width != fh->width ||
+	    buf->vb.height != fh->height || buf->vb.field != field) {
+		buf->fmt = fh->fmt;
+		buf->vb.width = fh->width;
+		buf->vb.height = fh->height;
+		buf->vb.field = field;
+		init_buffer = 1;
+	}
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		init_buffer = 1;
+		rc = videobuf_iolock(q, &buf->vb, NULL);
+		if (0 != rc) {
+			printk(KERN_DEBUG pr_fmt("videobuf_iolock failed!\n"));
+			goto fail;
+		}
+	}
+
+	dprintk(1, "init_buffer=%d\n", init_buffer);
+
+	if (init_buffer) {
+
+		channel_opened = dev->channel_opened;
+		if (channel_opened < 0 || channel_opened > 7)
+			channel_opened = 7;
+
+		if (dev->channels[channel_opened].pixel_formats ==
+				PIXEL_FRMT_411)
+			buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3;
+		else
+			buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width);
+
+		if (dev->channels[channel_opened].pixel_formats ==
+				PIXEL_FRMT_411) {
+			bpl_local = buf->bpl;
+		} else {
+			bpl_local = buf->bpl;   /* Default */
+
+			if (channel_opened >= 0 && channel_opened <= 7) {
+				if (dev->channels[channel_opened]
+						.use_cif_resolution) {
+					if (dev->tvnorm & V4L2_STD_PAL_BG
+					    || dev->tvnorm & V4L2_STD_PAL_DK)
+						bpl_local = 352 << 1;
+					else
+						bpl_local =
+						 dev->channels[channel_opened].
+						 cif_width <<
+						 1;
+				}
+			}
+		}
+
+		switch (buf->vb.field) {
+		case V4L2_FIELD_TOP:
+			cx25821_risc_buffer(dev->pci, &buf->risc,
+					    dma->sglist, 0, UNSET,
+					    buf->bpl, 0, buf->vb.height);
+			break;
+		case V4L2_FIELD_BOTTOM:
+			cx25821_risc_buffer(dev->pci, &buf->risc,
+					    dma->sglist, UNSET, 0,
+					    buf->bpl, 0, buf->vb.height);
+			break;
+		case V4L2_FIELD_INTERLACED:
+			/* All other formats are top field first */
+			line0_offset = 0;
+			line1_offset = buf->bpl;
+			dprintk(1, "top field first\n");
+
+			cx25821_risc_buffer(dev->pci, &buf->risc,
+					    dma->sglist, line0_offset,
+					    bpl_local, bpl_local, bpl_local,
+					    buf->vb.height >> 1);
+			break;
+		case V4L2_FIELD_SEQ_TB:
+			cx25821_risc_buffer(dev->pci, &buf->risc,
+					    dma->sglist,
+					    0, buf->bpl * (buf->vb.height >> 1),
+					    buf->bpl, 0, buf->vb.height >> 1);
+			break;
+		case V4L2_FIELD_SEQ_BT:
+			cx25821_risc_buffer(dev->pci, &buf->risc,
+					    dma->sglist,
+					    buf->bpl * (buf->vb.height >> 1), 0,
+					    buf->bpl, 0, buf->vb.height >> 1);
+			break;
+		default:
+			BUG();
+		}
+	}
+
+	dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
+		buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth,
+		fh->fmt->name, (unsigned long)buf->risc.dma);
+
+	buf->vb.state = VIDEOBUF_PREPARED;
+
+	return 0;
+
+fail:
+	cx25821_free_buffer(q, buf);
+	return rc;
+}
+
+void cx25821_buffer_release(struct videobuf_queue *q,
+			    struct videobuf_buffer *vb)
+{
+	struct cx25821_buffer *buf =
+	    container_of(vb, struct cx25821_buffer, vb);
+
+	cx25821_free_buffer(q, buf);
+}
+
+struct videobuf_queue *get_queue(struct cx25821_fh *fh)
+{
+	switch (fh->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		return &fh->vidq;
+	default:
+		BUG();
+		return NULL;
+	}
+}
+
+int cx25821_get_resource(struct cx25821_fh *fh, int resource)
+{
+	switch (fh->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		return resource;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct cx25821_fh *fh = file->private_data;
+
+	return videobuf_mmap_mapper(get_queue(fh), vma);
+}
+
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+	struct cx25821_buffer *buf =
+	   container_of(vb, struct cx25821_buffer, vb);
+	struct cx25821_buffer *prev;
+	struct cx25821_fh *fh = vq->priv_data;
+	struct cx25821_dev *dev = fh->dev;
+	struct cx25821_dmaqueue *q = &dev->channels[fh->channel_id].vidq;
+
+	/* add jump to stopper */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+	buf->risc.jmp[2] = cpu_to_le32(0);      /* bits 63-32 */
+
+	dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+	if (!list_empty(&q->queued)) {
+		list_add_tail(&buf->vb.queue, &q->queued);
+		buf->vb.state = VIDEOBUF_QUEUED;
+		dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
+				buf->vb.i);
+
+	} else if (list_empty(&q->active)) {
+		list_add_tail(&buf->vb.queue, &q->active);
+		cx25821_start_video_dma(dev, q, buf,
+				dev->channels[fh->channel_id].sram_channels);
+		buf->vb.state = VIDEOBUF_ACTIVE;
+		buf->count = q->count++;
+		mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+		dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+				buf, buf->vb.i, buf->count, q->count);
+	} else {
+		prev = list_entry(q->active.prev, struct cx25821_buffer,
+				vb.queue);
+		if (prev->vb.width == buf->vb.width
+		   && prev->vb.height == buf->vb.height
+		   && prev->fmt == buf->fmt) {
+			list_add_tail(&buf->vb.queue, &q->active);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count = q->count++;
+			prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+			/* 64 bit bits 63-32 */
+			prev->risc.jmp[2] = cpu_to_le32(0);
+			dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
+					buf, buf->vb.i, buf->count);
+
+		} else {
+			list_add_tail(&buf->vb.queue, &q->queued);
+			buf->vb.state = VIDEOBUF_QUEUED;
+			dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
+					buf->vb.i);
+		}
+	}
+
+	if (list_empty(&q->active))
+		dprintk(2, "active queue empty!\n");
+}
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+	.buf_setup = cx25821_buffer_setup,
+	.buf_prepare = cx25821_buffer_prepare,
+	.buf_queue = buffer_queue,
+	.buf_release = cx25821_buffer_release,
+};
+
+static int video_open(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cx25821_dev *h, *dev = video_drvdata(file);
+	struct cx25821_fh *fh;
+	struct list_head *list;
+	int minor = video_devdata(file)->minor;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	u32 pix_format;
+	int ch_id = 0;
+	int i;
+
+	dprintk(1, "open dev=%s type=%s\n", video_device_node_name(vdev),
+			v4l2_type_names[type]);
+
+	/* allocate + initialize per filehandle data */
+	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+	if (NULL == fh)
+		return -ENOMEM;
+
+	mutex_lock(&cx25821_devlist_mutex);
+
+	list_for_each(list, &cx25821_devlist)
+	{
+		h = list_entry(list, struct cx25821_dev, devlist);
+
+		for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) {
+			if (h->channels[i].video_dev &&
+			   h->channels[i].video_dev->minor == minor) {
+				dev = h;
+				ch_id = i;
+				type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+			}
+		}
+	}
+
+	if (NULL == dev) {
+		mutex_unlock(&cx25821_devlist_mutex);
+		kfree(fh);
+		return -ENODEV;
+	}
+
+	file->private_data = fh;
+	fh->dev = dev;
+	fh->type = type;
+	fh->width = 720;
+	fh->channel_id = ch_id;
+
+	if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+		fh->height = 576;
+	else
+		fh->height = 480;
+
+	dev->channel_opened = fh->channel_id;
+	if (dev->channels[ch_id].pixel_formats == PIXEL_FRMT_411)
+		pix_format = V4L2_PIX_FMT_Y41P;
+	else
+		pix_format = V4L2_PIX_FMT_YUYV;
+	fh->fmt = cx25821_format_by_fourcc(pix_format);
+
+	v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio);
+
+	videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+			      &dev->pci->dev, &dev->slock,
+			      V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			      V4L2_FIELD_INTERLACED,
+			      sizeof(struct cx25821_buffer), fh, NULL);
+
+	dprintk(1, "post videobuf_queue_init()\n");
+	mutex_unlock(&cx25821_devlist_mutex);
+
+	return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user * data, size_t count,
+			 loff_t *ppos)
+{
+	struct cx25821_fh *fh = file->private_data;
+
+	switch (fh->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		if (cx25821_res_locked(fh, RESOURCE_VIDEO0))
+			return -EBUSY;
+
+		return videobuf_read_one(&fh->vidq, data, count, ppos,
+					file->f_flags & O_NONBLOCK);
+
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static unsigned int video_poll(struct file *file,
+			      struct poll_table_struct *wait)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_buffer *buf;
+
+	if (cx25821_res_check(fh, RESOURCE_VIDEO0)) {
+		/* streaming capture */
+		if (list_empty(&fh->vidq.stream))
+			return POLLERR;
+		buf = list_entry(fh->vidq.stream.next,
+				struct cx25821_buffer, vb.stream);
+	} else {
+		/* read() capture */
+		buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+		if (NULL == buf)
+			return POLLERR;
+	}
+
+	poll_wait(file, &buf->vb.done, wait);
+	if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) {
+		if (buf->vb.state == VIDEOBUF_DONE) {
+			struct cx25821_dev *dev = fh->dev;
+
+			if (dev && dev->channels[fh->channel_id]
+					.use_cif_resolution) {
+				u8 cam_id = *((char *)buf->vb.baddr + 3);
+				memcpy((char *)buf->vb.baddr,
+				      (char *)buf->vb.baddr + (fh->width * 2),
+				      (fh->width * 2));
+				*((char *)buf->vb.baddr + 3) = cam_id;
+			}
+		}
+
+		return POLLIN | POLLRDNORM;
+	}
+
+	return 0;
+}
+
+static int video_release(struct file *file)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_dev *dev = fh->dev;
+
+	/* stop the risc engine and fifo */
+	cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */
+
+	/* stop video capture */
+	if (cx25821_res_check(fh, RESOURCE_VIDEO0)) {
+		videobuf_queue_cancel(&fh->vidq);
+		cx25821_res_free(dev, fh, RESOURCE_VIDEO0);
+	}
+
+	if (fh->vidq.read_buf) {
+		cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf);
+		kfree(fh->vidq.read_buf);
+	}
+
+	videobuf_mmap_free(&fh->vidq);
+
+	v4l2_prio_close(&dev->channels[fh->channel_id].prio, fh->prio);
+	file->private_data = NULL;
+	kfree(fh);
+
+	return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = fh->dev;
+
+	if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+		return -EINVAL;
+
+	if (unlikely(i != fh->type))
+		return -EINVAL;
+
+	if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh,
+						RESOURCE_VIDEO0))))
+		return -EBUSY;
+
+	return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = fh->dev;
+	int err, res;
+
+	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	if (i != fh->type)
+		return -EINVAL;
+
+	res = cx25821_get_resource(fh, RESOURCE_VIDEO0);
+	err = videobuf_streamoff(get_queue(fh));
+	if (err < 0)
+		return err;
+	cx25821_res_free(dev, fh, res);
+	return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	struct v4l2_mbus_framefmt mbus_fmt;
+	int err;
+	int pix_format = PIXEL_FRMT_422;
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+
+	dprintk(2, "%s()\n", __func__);
+	err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f);
+
+	if (0 != err)
+		return err;
+
+	fh->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
+	fh->vidq.field = f->fmt.pix.field;
+
+	/* check if width and height is valid based on set standard */
+	if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm))
+		fh->width = f->fmt.pix.width;
+
+	if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm))
+		fh->height = f->fmt.pix.height;
+
+	if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+		pix_format = PIXEL_FRMT_411;
+	else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+		pix_format = PIXEL_FRMT_422;
+	else
+		return -EINVAL;
+
+	cx25821_set_pixel_format(dev, SRAM_CH00, pix_format);
+
+	/* check if cif resolution */
+	if (fh->width == 320 || fh->width == 352)
+		dev->channels[fh->channel_id].use_cif_resolution = 1;
+	else
+		dev->channels[fh->channel_id].use_cif_resolution = 0;
+
+	dev->channels[fh->channel_id].cif_width = fh->width;
+	medusa_set_resolution(dev, fh->width, SRAM_CH00);
+
+	dprintk(2, "%s(): width=%d height=%d field=%d\n", __func__, fh->width,
+		fh->height, fh->vidq.field);
+	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
+	cx25821_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+
+	return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	int ret_val = 0;
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+	ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+
+	p->sequence = dev->channels[fh->channel_id].vidq.count;
+
+	return ret_val;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	struct cx25821_fh *fh = priv;
+	char name[32 + 2];
+
+	struct sram_channel *sram_ch = dev->channels[fh->channel_id]
+								.sram_channels;
+	u32 tmp = 0;
+
+	snprintf(name, sizeof(name), "%s/2", dev->name);
+	pr_info("%s/2: ============  START LOG STATUS  ============\n",
+		dev->name);
+	cx25821_call_all(dev, core, log_status);
+	tmp = cx_read(sram_ch->dma_ctl);
+	pr_info("Video input 0 is %s\n",
+		(tmp & 0x11) ? "streaming" : "stopped");
+	pr_info("%s/2: =============  END LOG STATUS  =============\n",
+		dev->name);
+	return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+			struct v4l2_control *ctl)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	int err;
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+
+	return cx25821_set_control(dev, ctl, fh->channel_id);
+}
+
+/* VIDEO IOCTLS */
+int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+				 struct v4l2_format *f)
+{
+	struct cx25821_fh *fh = priv;
+
+	f->fmt.pix.width = fh->width;
+	f->fmt.pix.height = fh->height;
+	f->fmt.pix.field = fh->vidq.field;
+	f->fmt.pix.pixelformat = fh->fmt->fourcc;
+	f->fmt.pix.bytesperline = (f->fmt.pix.width * fh->fmt->depth) >> 3;
+	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+	return 0;
+}
+
+int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+				   struct v4l2_format *f)
+{
+	struct cx25821_fmt *fmt;
+	enum v4l2_field field;
+	unsigned int maxw, maxh;
+
+	fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
+	if (NULL == fmt)
+		return -EINVAL;
+
+	field = f->fmt.pix.field;
+	maxw = 720;
+	maxh = 576;
+
+	if (V4L2_FIELD_ANY == field) {
+		if (f->fmt.pix.height > maxh / 2)
+			field = V4L2_FIELD_INTERLACED;
+		else
+			field = V4L2_FIELD_TOP;
+	}
+
+	switch (field) {
+	case V4L2_FIELD_TOP:
+	case V4L2_FIELD_BOTTOM:
+		maxh = maxh / 2;
+		break;
+	case V4L2_FIELD_INTERLACED:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	f->fmt.pix.field = field;
+	if (f->fmt.pix.height < 32)
+		f->fmt.pix.height = 32;
+	if (f->fmt.pix.height > maxh)
+		f->fmt.pix.height = maxh;
+	if (f->fmt.pix.width < 48)
+		f->fmt.pix.width = 48;
+	if (f->fmt.pix.width > maxw)
+		f->fmt.pix.width = maxw;
+	f->fmt.pix.width &= ~0x03;
+	f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
+	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+	return 0;
+}
+
+int cx25821_vidioc_querycap(struct file *file, void *priv,
+			    struct v4l2_capability *cap)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+	strcpy(cap->driver, "cx25821");
+	strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card));
+	sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
+	cap->version = CX25821_VERSION_CODE;
+	cap->capabilities =
+	    V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+	if (UNSET != dev->tuner_type)
+		cap->capabilities |= V4L2_CAP_TUNER;
+	return 0;
+}
+
+int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+			    struct v4l2_fmtdesc *f)
+{
+	if (unlikely(f->index >= ARRAY_SIZE(formats)))
+		return -EINVAL;
+
+	strlcpy(f->description, formats[f->index].name, sizeof(f->description));
+	f->pixelformat = formats[f->index].fourcc;
+
+	return 0;
+}
+
+int cx25821_vidioc_reqbufs(struct file *file, void *priv,
+			   struct v4l2_requestbuffers *p)
+{
+	struct cx25821_fh *fh = priv;
+	return videobuf_reqbufs(get_queue(fh), p);
+}
+
+int cx25821_vidioc_querybuf(struct file *file, void *priv,
+			    struct v4l2_buffer *p)
+{
+	struct cx25821_fh *fh = priv;
+	return videobuf_querybuf(get_queue(fh), p);
+}
+
+int cx25821_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cx25821_fh *fh = priv;
+	return videobuf_qbuf(get_queue(fh), p);
+}
+
+int cx25821_vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev;
+	struct cx25821_fh *fh = f;
+
+	*p = v4l2_prio_max(&dev->channels[fh->channel_id].prio);
+
+	return 0;
+}
+
+int cx25821_vidioc_s_priority(struct file *file, void *f,
+			      enum v4l2_priority prio)
+{
+	struct cx25821_fh *fh = f;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev;
+
+	return v4l2_prio_change(&dev->channels[fh->channel_id].prio, &fh->prio,
+			prio);
+}
+
+#ifdef TUNER_FLAG
+int cx25821_vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	int err;
+
+	dprintk(1, "%s()\n", __func__);
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+
+	if (dev->tvnorm == *tvnorms)
+		return 0;
+
+	mutex_lock(&dev->lock);
+	cx25821_set_tvnorm(dev, *tvnorms);
+	mutex_unlock(&dev->lock);
+
+	medusa_set_videostandard(dev);
+
+	return 0;
+}
+#endif
+
+int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i)
+{
+	static const char * const iname[] = {
+		[CX25821_VMUX_COMPOSITE] = "Composite",
+		[CX25821_VMUX_SVIDEO] = "S-Video",
+		[CX25821_VMUX_DEBUG] = "for debug only",
+	};
+	unsigned int n;
+	dprintk(1, "%s()\n", __func__);
+
+	n = i->index;
+	if (n >= 2)
+		return -EINVAL;
+
+	if (0 == INPUT(n)->type)
+		return -EINVAL;
+
+	i->type = V4L2_INPUT_TYPE_CAMERA;
+	strcpy(i->name, iname[INPUT(n)->type]);
+
+	i->std = CX25821_NORMS;
+	return 0;
+}
+
+int cx25821_vidioc_enum_input(struct file *file, void *priv,
+			      struct v4l2_input *i)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	dprintk(1, "%s()\n", __func__);
+	return cx25821_enum_input(dev, i);
+}
+
+int cx25821_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+	*i = dev->input;
+	dprintk(1, "%s(): returns %d\n", __func__, *i);
+	return 0;
+}
+
+int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	int err;
+
+	dprintk(1, "%s(%d)\n", __func__, i);
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+
+	if (i >= CX25821_NR_INPUT) {
+		dprintk(1, "%s(): -EINVAL\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&dev->lock);
+	cx25821_video_mux(dev, i);
+	mutex_unlock(&dev->lock);
+	return 0;
+}
+
+#ifdef TUNER_FLAG
+int cx25821_vidioc_g_frequency(struct file *file, void *priv,
+			       struct v4l2_frequency *f)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = fh->dev;
+
+	f->frequency = dev->freq;
+
+	cx25821_call_all(dev, tuner, g_frequency, f);
+
+	return 0;
+}
+
+int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f)
+{
+	mutex_lock(&dev->lock);
+	dev->freq = f->frequency;
+
+	cx25821_call_all(dev, tuner, s_frequency, f);
+
+	/* When changing channels it is required to reset TVAUDIO */
+	msleep(10);
+
+	mutex_unlock(&dev->lock);
+
+	return 0;
+}
+
+int cx25821_vidioc_s_frequency(struct file *file, void *priv,
+			       struct v4l2_frequency *f)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev;
+	int err;
+
+	if (fh) {
+		dev = fh->dev;
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	} else {
+		pr_err("Invalid fh pointer!\n");
+		return -EINVAL;
+	}
+
+	return cx25821_set_freq(dev, f);
+}
+#endif
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+int cx25821_vidioc_g_register(struct file *file, void *fh,
+		      struct v4l2_dbg_register *reg)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev;
+
+	if (!v4l2_chip_match_host(&reg->match))
+		return -EINVAL;
+
+	cx25821_call_all(dev, core, g_register, reg);
+
+	return 0;
+}
+
+int cx25821_vidioc_s_register(struct file *file, void *fh,
+		      struct v4l2_dbg_register *reg)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev;
+
+	if (!v4l2_chip_match_host(&reg->match))
+		return -EINVAL;
+
+	cx25821_call_all(dev, core, s_register, reg);
+
+	return 0;
+}
+
+#endif
+
+#ifdef TUNER_FLAG
+int cx25821_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+	if (unlikely(UNSET == dev->tuner_type))
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	strcpy(t->name, "Television");
+	t->type = V4L2_TUNER_ANALOG_TV;
+	t->capability = V4L2_TUNER_CAP_NORM;
+	t->rangehigh = 0xffffffffUL;
+
+	t->signal = 0xffff;	/* LOCKED */
+	return 0;
+}
+
+int cx25821_vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	struct cx25821_fh *fh = priv;
+	int err;
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+
+	dprintk(1, "%s()\n", __func__);
+	if (UNSET == dev->tuner_type)
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	return 0;
+}
+
+#endif
+/*****************************************************************************/
+static const struct v4l2_queryctrl no_ctl = {
+	.name = "42",
+	.flags = V4L2_CTRL_FLAG_DISABLED,
+};
+
+static struct v4l2_queryctrl cx25821_ctls[] = {
+	/* --- video --- */
+	{
+	 .id = V4L2_CID_BRIGHTNESS,
+	 .name = "Brightness",
+	 .minimum = 0,
+	 .maximum = 10000,
+	 .step = 1,
+	 .default_value = 6200,
+	 .type = V4L2_CTRL_TYPE_INTEGER,
+	 }, {
+	     .id = V4L2_CID_CONTRAST,
+	     .name = "Contrast",
+	     .minimum = 0,
+	     .maximum = 10000,
+	     .step = 1,
+	     .default_value = 5000,
+	     .type = V4L2_CTRL_TYPE_INTEGER,
+	     }, {
+		 .id = V4L2_CID_SATURATION,
+		 .name = "Saturation",
+		 .minimum = 0,
+		 .maximum = 10000,
+		 .step = 1,
+		 .default_value = 5000,
+		 .type = V4L2_CTRL_TYPE_INTEGER,
+		 }, {
+		     .id = V4L2_CID_HUE,
+		     .name = "Hue",
+		     .minimum = 0,
+		     .maximum = 10000,
+		     .step = 1,
+		     .default_value = 5000,
+		     .type = V4L2_CTRL_TYPE_INTEGER,
+		     }
+};
+static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls);
+
+static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl)
+{
+	int i;
+
+	if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1)
+		return -EINVAL;
+	for (i = 0; i < CX25821_CTLS; i++)
+		if (cx25821_ctls[i].id == qctrl->id)
+			break;
+	if (i == CX25821_CTLS) {
+		*qctrl = no_ctl;
+		return 0;
+	}
+	*qctrl = cx25821_ctls[i];
+	return 0;
+}
+
+int cx25821_vidioc_queryctrl(struct file *file, void *priv,
+		     struct v4l2_queryctrl *qctrl)
+{
+	return cx25821_ctrl_query(qctrl);
+}
+
+/* ------------------------------------------------------------------ */
+/* VIDEO CTRL IOCTLS                                                  */
+
+static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id)
+{
+	unsigned int i;
+
+	for (i = 0; i < CX25821_CTLS; i++)
+		if (cx25821_ctls[i].id == id)
+			return cx25821_ctls + i;
+	return NULL;
+}
+
+int cx25821_vidioc_g_ctrl(struct file *file, void *priv,
+			  struct v4l2_control *ctl)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	struct cx25821_fh *fh = priv;
+
+	const struct v4l2_queryctrl *ctrl;
+
+	ctrl = ctrl_by_id(ctl->id);
+
+	if (NULL == ctrl)
+		return -EINVAL;
+	switch (ctl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		ctl->value = dev->channels[fh->channel_id].ctl_bright;
+		break;
+	case V4L2_CID_HUE:
+		ctl->value = dev->channels[fh->channel_id].ctl_hue;
+		break;
+	case V4L2_CID_CONTRAST:
+		ctl->value = dev->channels[fh->channel_id].ctl_contrast;
+		break;
+	case V4L2_CID_SATURATION:
+		ctl->value = dev->channels[fh->channel_id].ctl_saturation;
+		break;
+	}
+	return 0;
+}
+
+int cx25821_set_control(struct cx25821_dev *dev,
+			struct v4l2_control *ctl, int chan_num)
+{
+	int err;
+	const struct v4l2_queryctrl *ctrl;
+
+	err = -EINVAL;
+
+	ctrl = ctrl_by_id(ctl->id);
+
+	if (NULL == ctrl)
+		return err;
+
+	switch (ctrl->type) {
+	case V4L2_CTRL_TYPE_BOOLEAN:
+	case V4L2_CTRL_TYPE_MENU:
+	case V4L2_CTRL_TYPE_INTEGER:
+		if (ctl->value < ctrl->minimum)
+			ctl->value = ctrl->minimum;
+		if (ctl->value > ctrl->maximum)
+			ctl->value = ctrl->maximum;
+		break;
+	default:
+		/* nothing */ ;
+	}
+
+	switch (ctl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		dev->channels[chan_num].ctl_bright = ctl->value;
+		medusa_set_brightness(dev, ctl->value, chan_num);
+		break;
+	case V4L2_CID_HUE:
+		dev->channels[chan_num].ctl_hue = ctl->value;
+		medusa_set_hue(dev, ctl->value, chan_num);
+		break;
+	case V4L2_CID_CONTRAST:
+		dev->channels[chan_num].ctl_contrast = ctl->value;
+		medusa_set_contrast(dev, ctl->value, chan_num);
+		break;
+	case V4L2_CID_SATURATION:
+		dev->channels[chan_num].ctl_saturation = ctl->value;
+		medusa_set_saturation(dev, ctl->value, chan_num);
+		break;
+	}
+
+	err = 0;
+
+	return err;
+}
+
+static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num)
+{
+	struct v4l2_control ctrl;
+	int i;
+	for (i = 0; i < CX25821_CTLS; i++) {
+		ctrl.id = cx25821_ctls[i].id;
+		ctrl.value = cx25821_ctls[i].default_value;
+
+		cx25821_set_control(dev, &ctrl, chan_num);
+	}
+}
+
+int cx25821_vidioc_cropcap(struct file *file, void *priv,
+			   struct v4l2_cropcap *cropcap)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+	if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	cropcap->bounds.top = cropcap->bounds.left = 0;
+	cropcap->bounds.width = 720;
+	cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480;
+	cropcap->pixelaspect.numerator =
+		dev->tvnorm == V4L2_STD_PAL_BG ? 59 : 10;
+	cropcap->pixelaspect.denominator =
+		dev->tvnorm == V4L2_STD_PAL_BG ? 54 : 11;
+	cropcap->defrect = cropcap->bounds;
+	return 0;
+}
+
+int cx25821_vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	struct cx25821_fh *fh = priv;
+	int err;
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+	/* cx25821_vidioc_s_crop not supported */
+	return -EINVAL;
+}
+
+int cx25821_vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+{
+	/* cx25821_vidioc_g_crop not supported */
+	return -EINVAL;
+}
+
+int cx25821_vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm)
+{
+	/* medusa does not support video standard sensing of current input */
+	*norm = CX25821_NORMS;
+
+	return 0;
+}
+
+int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm)
+{
+	if (tvnorm == V4L2_STD_PAL_BG) {
+		if (width == 352 || width == 720)
+			return 1;
+		else
+			return 0;
+	}
+
+	if (tvnorm == V4L2_STD_NTSC_M) {
+		if (width == 320 || width == 352 || width == 720)
+			return 1;
+		else
+			return 0;
+	}
+	return 0;
+}
+
+int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm)
+{
+	if (tvnorm == V4L2_STD_PAL_BG) {
+		if (height == 576 || height == 288)
+			return 1;
+		else
+			return 0;
+	}
+
+	if (tvnorm == V4L2_STD_NTSC_M) {
+		if (height == 480 || height == 240)
+			return 1;
+		else
+			return 0;
+	}
+
+	return 0;
+}
+
+static long video_ioctl_upstream9(struct file *file, unsigned int cmd,
+				 unsigned long arg)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_dev *dev = fh->dev;
+	int command = 0;
+	struct upstream_user_struct *data_from_user;
+
+	data_from_user = (struct upstream_user_struct *)arg;
+
+	if (!data_from_user) {
+		pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
+		return 0;
+	}
+
+	command = data_from_user->command;
+
+	if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO)
+		return 0;
+
+	dev->input_filename = data_from_user->input_filename;
+	dev->input_audiofilename = data_from_user->input_filename;
+	dev->vid_stdname = data_from_user->vid_stdname;
+	dev->pixel_format = data_from_user->pixel_format;
+	dev->channel_select = data_from_user->channel_select;
+	dev->command = data_from_user->command;
+
+	switch (command) {
+	case UPSTREAM_START_VIDEO:
+		cx25821_start_upstream_video_ch1(dev, data_from_user);
+		break;
+
+	case UPSTREAM_STOP_VIDEO:
+		cx25821_stop_upstream_video_ch1(dev);
+		break;
+	}
+
+	return 0;
+}
+
+static long video_ioctl_upstream10(struct file *file, unsigned int cmd,
+				  unsigned long arg)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_dev *dev = fh->dev;
+	int command = 0;
+	struct upstream_user_struct *data_from_user;
+
+	data_from_user = (struct upstream_user_struct *)arg;
+
+	if (!data_from_user) {
+		pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
+		return 0;
+	}
+
+	command = data_from_user->command;
+
+	if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO)
+		return 0;
+
+	dev->input_filename_ch2 = data_from_user->input_filename;
+	dev->input_audiofilename = data_from_user->input_filename;
+	dev->vid_stdname_ch2 = data_from_user->vid_stdname;
+	dev->pixel_format_ch2 = data_from_user->pixel_format;
+	dev->channel_select_ch2 = data_from_user->channel_select;
+	dev->command_ch2 = data_from_user->command;
+
+	switch (command) {
+	case UPSTREAM_START_VIDEO:
+		cx25821_start_upstream_video_ch2(dev, data_from_user);
+		break;
+
+	case UPSTREAM_STOP_VIDEO:
+		cx25821_stop_upstream_video_ch2(dev);
+		break;
+	}
+
+	return 0;
+}
+
+static long video_ioctl_upstream11(struct file *file, unsigned int cmd,
+				  unsigned long arg)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_dev *dev = fh->dev;
+	int command = 0;
+	struct upstream_user_struct *data_from_user;
+
+	data_from_user = (struct upstream_user_struct *)arg;
+
+	if (!data_from_user) {
+		pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
+		return 0;
+	}
+
+	command = data_from_user->command;
+
+	if (command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO)
+		return 0;
+
+	dev->input_filename = data_from_user->input_filename;
+	dev->input_audiofilename = data_from_user->input_filename;
+	dev->vid_stdname = data_from_user->vid_stdname;
+	dev->pixel_format = data_from_user->pixel_format;
+	dev->channel_select = data_from_user->channel_select;
+	dev->command = data_from_user->command;
+
+	switch (command) {
+	case UPSTREAM_START_AUDIO:
+		cx25821_start_upstream_audio(dev, data_from_user);
+		break;
+
+	case UPSTREAM_STOP_AUDIO:
+		cx25821_stop_upstream_audio(dev);
+		break;
+	}
+
+	return 0;
+}
+
+static long video_ioctl_set(struct file *file, unsigned int cmd,
+			   unsigned long arg)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_dev *dev = fh->dev;
+	struct downstream_user_struct *data_from_user;
+	int command;
+	int width = 720;
+	int selected_channel = 0, pix_format = 0, i = 0;
+	int cif_enable = 0, cif_width = 0;
+	u32 value = 0;
+
+	data_from_user = (struct downstream_user_struct *)arg;
+
+	if (!data_from_user) {
+		pr_err("%s(): User data is INVALID. Returning\n", __func__);
+		return 0;
+	}
+
+	command = data_from_user->command;
+
+	if (command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT
+	   && command != ENABLE_CIF_RESOLUTION && command != REG_READ
+	   && command != REG_WRITE && command != MEDUSA_READ
+	   && command != MEDUSA_WRITE) {
+		return 0;
+	}
+
+	switch (command) {
+	case SET_VIDEO_STD:
+		if (!strcmp(data_from_user->vid_stdname, "PAL"))
+			dev->tvnorm = V4L2_STD_PAL_BG;
+		else
+			dev->tvnorm = V4L2_STD_NTSC_M;
+		medusa_set_videostandard(dev);
+		break;
+
+	case SET_PIXEL_FORMAT:
+		selected_channel = data_from_user->decoder_select;
+		pix_format = data_from_user->pixel_format;
+
+		if (!(selected_channel <= 7 && selected_channel >= 0)) {
+			selected_channel -= 4;
+			selected_channel = selected_channel % 8;
+		}
+
+		if (selected_channel >= 0)
+			cx25821_set_pixel_format(dev, selected_channel,
+						pix_format);
+
+		break;
+
+	case ENABLE_CIF_RESOLUTION:
+		selected_channel = data_from_user->decoder_select;
+		cif_enable = data_from_user->cif_resolution_enable;
+		cif_width = data_from_user->cif_width;
+
+		if (cif_enable) {
+			if (dev->tvnorm & V4L2_STD_PAL_BG
+			    || dev->tvnorm & V4L2_STD_PAL_DK) {
+				width = 352;
+			} else {
+				width = cif_width;
+				if (cif_width != 320 && cif_width != 352)
+					width = 320;
+			}
+		}
+
+		if (!(selected_channel <= 7 && selected_channel >= 0)) {
+			selected_channel -= 4;
+			selected_channel = selected_channel % 8;
+		}
+
+		if (selected_channel <= 7 && selected_channel >= 0) {
+			dev->channels[selected_channel].
+				use_cif_resolution = cif_enable;
+			dev->channels[selected_channel].cif_width = width;
+		} else {
+			for (i = 0; i < VID_CHANNEL_NUM; i++) {
+				dev->channels[i].use_cif_resolution =
+					cif_enable;
+				dev->channels[i].cif_width = width;
+			}
+		}
+
+		medusa_set_resolution(dev, width, selected_channel);
+		break;
+	case REG_READ:
+		data_from_user->reg_data = cx_read(data_from_user->reg_address);
+		break;
+	case REG_WRITE:
+		cx_write(data_from_user->reg_address, data_from_user->reg_data);
+		break;
+	case MEDUSA_READ:
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+					 (u16) data_from_user->reg_address,
+					 &data_from_user->reg_data);
+		break;
+	case MEDUSA_WRITE:
+		cx25821_i2c_write(&dev->i2c_bus[0],
+				  (u16) data_from_user->reg_address,
+				  data_from_user->reg_data);
+		break;
+	}
+
+	return 0;
+}
+
+static long cx25821_video_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	int  ret = 0;
+
+	struct cx25821_fh  *fh  = file->private_data;
+
+	/* check to see if it's the video upstream */
+	if (fh->channel_id == SRAM_CH09) {
+		ret = video_ioctl_upstream9(file, cmd, arg);
+		return ret;
+	} else if (fh->channel_id == SRAM_CH10) {
+		ret = video_ioctl_upstream10(file, cmd, arg);
+		return ret;
+	} else if (fh->channel_id == SRAM_CH11) {
+		ret = video_ioctl_upstream11(file, cmd, arg);
+		ret = video_ioctl_set(file, cmd, arg);
+		return ret;
+	}
+
+	return video_ioctl2(file, cmd, arg);
+}
+
+/* exported stuff */
+static const struct v4l2_file_operations video_fops = {
+	.owner = THIS_MODULE,
+	.open = video_open,
+	.release = video_release,
+	.read = video_read,
+	.poll = video_poll,
+	.mmap = cx25821_video_mmap,
+	.ioctl = cx25821_video_ioctl,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+	.vidioc_querycap = cx25821_vidioc_querycap,
+	.vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+	.vidioc_reqbufs = cx25821_vidioc_reqbufs,
+	.vidioc_querybuf = cx25821_vidioc_querybuf,
+	.vidioc_qbuf = cx25821_vidioc_qbuf,
+	.vidioc_dqbuf = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+	.vidioc_s_std = cx25821_vidioc_s_std,
+	.vidioc_querystd = cx25821_vidioc_querystd,
+#endif
+	.vidioc_cropcap = cx25821_vidioc_cropcap,
+	.vidioc_s_crop = cx25821_vidioc_s_crop,
+	.vidioc_g_crop = cx25821_vidioc_g_crop,
+	.vidioc_enum_input = cx25821_vidioc_enum_input,
+	.vidioc_g_input = cx25821_vidioc_g_input,
+	.vidioc_s_input = cx25821_vidioc_s_input,
+	.vidioc_g_ctrl = cx25821_vidioc_g_ctrl,
+	.vidioc_s_ctrl = vidioc_s_ctrl,
+	.vidioc_queryctrl = cx25821_vidioc_queryctrl,
+	.vidioc_streamon = vidioc_streamon,
+	.vidioc_streamoff = vidioc_streamoff,
+	.vidioc_log_status = vidioc_log_status,
+	.vidioc_g_priority = cx25821_vidioc_g_priority,
+	.vidioc_s_priority = cx25821_vidioc_s_priority,
+#ifdef TUNER_FLAG
+	.vidioc_g_tuner = cx25821_vidioc_g_tuner,
+	.vidioc_s_tuner = cx25821_vidioc_s_tuner,
+	.vidioc_g_frequency = cx25821_vidioc_g_frequency,
+	.vidioc_s_frequency = cx25821_vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register = cx25821_vidioc_g_register,
+	.vidioc_s_register = cx25821_vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_videoioctl_template = {
+	.name = "cx25821-videoioctl",
+	.fops = &video_fops,
+	.ioctl_ops = &video_ioctl_ops,
+	.tvnorms = CX25821_NORMS,
+	.current_norm = V4L2_STD_NTSC_M,
+};
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-video.h linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-video.h
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-video.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-video.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,188 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> cx23885 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 CX25821_VIDEO_H_
+#define CX25821_VIDEO_H_
+
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <asm/div64.h>
+
+#include "cx25821.h"
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+
+#define TUNER_FLAG
+
+#define VIDEO_DEBUG 0
+
+#define dprintk(level, fmt, arg...)					\
+do {									\
+	if (VIDEO_DEBUG >= level)					\
+		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg);	\
+} while (0)
+
+/* For IOCTL to identify running upstream */
+#define UPSTREAM_START_VIDEO        700
+#define UPSTREAM_STOP_VIDEO         701
+#define UPSTREAM_START_AUDIO        702
+#define UPSTREAM_STOP_AUDIO         703
+#define UPSTREAM_DUMP_REGISTERS     702
+#define SET_VIDEO_STD               800
+#define SET_PIXEL_FORMAT            1000
+#define ENABLE_CIF_RESOLUTION       1001
+
+#define REG_READ		    900
+#define REG_WRITE		    901
+#define MEDUSA_READ		    910
+#define MEDUSA_WRITE		    911
+
+extern struct sram_channel *channel0;
+extern struct sram_channel *channel1;
+extern struct sram_channel *channel2;
+extern struct sram_channel *channel3;
+extern struct sram_channel *channel4;
+extern struct sram_channel *channel5;
+extern struct sram_channel *channel6;
+extern struct sram_channel *channel7;
+extern struct sram_channel *channel9;
+extern struct sram_channel *channel10;
+extern struct sram_channel *channel11;
+extern struct video_device cx25821_videoioctl_template;
+/* extern const u32 *ctrl_classes[]; */
+
+extern unsigned int vid_limit;
+
+#define FORMAT_FLAGS_PACKED       0x01
+extern struct cx25821_fmt formats[];
+extern struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc);
+extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM];
+
+extern void cx25821_dump_video_queue(struct cx25821_dev *dev,
+				     struct cx25821_dmaqueue *q);
+extern void cx25821_video_wakeup(struct cx25821_dev *dev,
+				 struct cx25821_dmaqueue *q, u32 count);
+
+#ifdef TUNER_FLAG
+extern int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm);
+#endif
+
+extern int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh,
+			   unsigned int bit);
+extern int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit);
+extern int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit);
+extern void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh,
+			     unsigned int bits);
+extern int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input);
+extern int cx25821_start_video_dma(struct cx25821_dev *dev,
+				   struct cx25821_dmaqueue *q,
+				   struct cx25821_buffer *buf,
+				   struct sram_channel *channel);
+
+extern int cx25821_set_scale(struct cx25821_dev *dev, unsigned int width,
+			     unsigned int height, enum v4l2_field field);
+extern int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status);
+extern void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num);
+extern int cx25821_video_register(struct cx25821_dev *dev);
+extern int cx25821_get_format_size(void);
+
+extern int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count,
+				unsigned int *size);
+extern int cx25821_buffer_prepare(struct videobuf_queue *q,
+				  struct videobuf_buffer *vb,
+				  enum v4l2_field field);
+extern void cx25821_buffer_release(struct videobuf_queue *q,
+				   struct videobuf_buffer *vb);
+extern struct videobuf_queue *get_queue(struct cx25821_fh *fh);
+extern int cx25821_get_resource(struct cx25821_fh *fh, int resource);
+extern int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma);
+extern int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+					  struct v4l2_format *f);
+extern int cx25821_vidioc_querycap(struct file *file, void *priv,
+				   struct v4l2_capability *cap);
+extern int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+					   struct v4l2_fmtdesc *f);
+extern int cx25821_vidioc_reqbufs(struct file *file, void *priv,
+				  struct v4l2_requestbuffers *p);
+extern int cx25821_vidioc_querybuf(struct file *file, void *priv,
+				   struct v4l2_buffer *p);
+extern int cx25821_vidioc_qbuf(struct file *file, void *priv,
+			       struct v4l2_buffer *p);
+extern int cx25821_vidioc_s_std(struct file *file, void *priv,
+				v4l2_std_id *tvnorms);
+extern int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i);
+extern int cx25821_vidioc_enum_input(struct file *file, void *priv,
+				     struct v4l2_input *i);
+extern int cx25821_vidioc_g_input(struct file *file, void *priv,
+				  unsigned int *i);
+extern int cx25821_vidioc_s_input(struct file *file, void *priv,
+				  unsigned int i);
+extern int cx25821_vidioc_g_ctrl(struct file *file, void *priv,
+				 struct v4l2_control *ctl);
+extern int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+					struct v4l2_format *f);
+extern int cx25821_vidioc_g_frequency(struct file *file, void *priv,
+				      struct v4l2_frequency *f);
+extern int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f);
+extern int cx25821_vidioc_s_frequency(struct file *file, void *priv,
+				      struct v4l2_frequency *f);
+extern int cx25821_vidioc_g_register(struct file *file, void *fh,
+				     struct v4l2_dbg_register *reg);
+extern int cx25821_vidioc_s_register(struct file *file, void *fh,
+				     struct v4l2_dbg_register *reg);
+extern int cx25821_vidioc_g_tuner(struct file *file, void *priv,
+				  struct v4l2_tuner *t);
+extern int cx25821_vidioc_s_tuner(struct file *file, void *priv,
+				  struct v4l2_tuner *t);
+
+extern int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm);
+extern int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm);
+
+extern int cx25821_vidioc_g_priority(struct file *file, void *f,
+				     enum v4l2_priority *p);
+extern int cx25821_vidioc_s_priority(struct file *file, void *f,
+				     enum v4l2_priority prio);
+
+extern int cx25821_vidioc_queryctrl(struct file *file, void *priv,
+				    struct v4l2_queryctrl *qctrl);
+extern int cx25821_set_control(struct cx25821_dev *dev,
+			       struct v4l2_control *ctrl, int chan_num);
+
+extern int cx25821_vidioc_cropcap(struct file *file, void *fh,
+				  struct v4l2_cropcap *cropcap);
+extern int cx25821_vidioc_s_crop(struct file *file, void *priv,
+				 struct v4l2_crop *crop);
+extern int cx25821_vidioc_g_crop(struct file *file, void *priv,
+				 struct v4l2_crop *crop);
+
+extern int cx25821_vidioc_querystd(struct file *file, void *priv,
+				   v4l2_std_id *norm);
+#endif
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-video-upstream.c linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-video-upstream.c
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-video-upstream.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-video-upstream.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,885 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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 "cx25821-video.h"
+#include "cx25821-video-upstream.h"
+
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC |
+			FLD_VID_SRC_OPC_ERR;
+
+int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev,
+					struct sram_channel *ch,
+					unsigned int bpl, u32 risc)
+{
+	unsigned int i, lines;
+	u32 cdt;
+
+	if (ch->cmds_start == 0) {
+		cx_write(ch->ptr1_reg, 0);
+		cx_write(ch->ptr2_reg, 0);
+		cx_write(ch->cnt2_reg, 0);
+		cx_write(ch->cnt1_reg, 0);
+		return 0;
+	}
+
+	bpl = (bpl + 7) & ~7;	/* alignment */
+	cdt = ch->cdt;
+	lines = ch->fifo_size / bpl;
+
+	if (lines > 4)
+		lines = 4;
+
+	BUG_ON(lines < 2);
+
+	/* write CDT */
+	for (i = 0; i < lines; i++) {
+		cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+		cx_write(cdt + 16 * i + 4, 0);
+		cx_write(cdt + 16 * i + 8, 0);
+		cx_write(cdt + 16 * i + 12, 0);
+	}
+
+	/* write CMDS */
+	cx_write(ch->cmds_start + 0, risc);
+
+	cx_write(ch->cmds_start + 4, 0);
+	cx_write(ch->cmds_start + 8, cdt);
+	cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
+	cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+	cx_write(ch->cmds_start + 20, VID_IQ_SIZE_DW);
+
+	for (i = 24; i < 80; i += 4)
+		cx_write(ch->cmds_start + i, 0);
+
+	/* fill registers */
+	cx_write(ch->ptr1_reg, ch->fifo_start);
+	cx_write(ch->ptr2_reg, cdt);
+	cx_write(ch->cnt2_reg, (lines * 16) >> 3);
+	cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+	return 0;
+}
+
+static __le32 *cx25821_update_riscprogram(struct cx25821_dev *dev,
+					  __le32 *rp, unsigned int offset,
+					  unsigned int bpl, u32 sync_line,
+					  unsigned int lines, int fifo_enable,
+					  int field_type)
+{
+	unsigned int line, i;
+	int dist_betwn_starts = bpl * 2;
+
+	*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	if (USE_RISC_NOOP_VIDEO) {
+		for (i = 0; i < NUM_NO_OPS; i++)
+			*(rp++) = cpu_to_le32(RISC_NOOP);
+	}
+
+	/* scan lines */
+	for (line = 0; line < lines; line++) {
+		*(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+		*(rp++) = cpu_to_le32(dev->_data_buf_phys_addr + offset);
+		*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+
+		if ((lines <= NTSC_FIELD_HEIGHT)
+		    || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC)) {
+			offset += dist_betwn_starts;
+		}
+	}
+
+	return rp;
+}
+
+static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp,
+					   dma_addr_t databuf_phys_addr,
+					   unsigned int offset, u32 sync_line,
+					   unsigned int bpl, unsigned int lines,
+					   int fifo_enable, int field_type)
+{
+	unsigned int line, i;
+	struct sram_channel *sram_ch =
+	   dev->channels[dev->_channel_upstream_select].sram_channels;
+	int dist_betwn_starts = bpl * 2;
+
+	/* sync instruction */
+	if (sync_line != NO_SYNC_LINE)
+		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	if (USE_RISC_NOOP_VIDEO) {
+		for (i = 0; i < NUM_NO_OPS; i++)
+			*(rp++) = cpu_to_le32(RISC_NOOP);
+	}
+
+	/* scan lines */
+	for (line = 0; line < lines; line++) {
+		*(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+		*(rp++) = cpu_to_le32(databuf_phys_addr + offset);
+		*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+
+		if ((lines <= NTSC_FIELD_HEIGHT)
+		    || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC))
+			/* to skip the other field line */
+			offset += dist_betwn_starts;
+
+		/* check if we need to enable the FIFO after the first 4 lines
+		 * For the upstream video channel, the risc engine will enable
+		 * the FIFO. */
+		if (fifo_enable && line == 3) {
+			*(rp++) = RISC_WRITECR;
+			*(rp++) = sram_ch->dma_ctl;
+			*(rp++) = FLD_VID_FIFO_EN;
+			*(rp++) = 0x00000001;
+		}
+	}
+
+	return rp;
+}
+
+int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
+				 struct pci_dev *pci,
+				 unsigned int top_offset,
+				 unsigned int bpl, unsigned int lines)
+{
+	__le32 *rp;
+	int fifo_enable = 0;
+	/* get line count for single field */
+	int singlefield_lines = lines >> 1;
+	int odd_num_lines = singlefield_lines;
+	int frame = 0;
+	int frame_size = 0;
+	int databuf_offset = 0;
+	int risc_program_size = 0;
+	int risc_flag = RISC_CNT_RESET;
+	unsigned int bottom_offset = bpl;
+	dma_addr_t risc_phys_jump_addr;
+
+	if (dev->_isNTSC) {
+		odd_num_lines = singlefield_lines + 1;
+		risc_program_size = FRAME1_VID_PROG_SIZE;
+		frame_size =
+		    (bpl ==
+		     Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 :
+		    FRAME_SIZE_NTSC_Y422;
+	} else {
+		risc_program_size = PAL_VID_PROG_SIZE;
+		frame_size =
+		    (bpl ==
+		     Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+	}
+
+	/* Virtual address of Risc buffer program */
+	rp = dev->_dma_virt_addr;
+
+	for (frame = 0; frame < NUM_FRAMES; frame++) {
+		databuf_offset = frame_size * frame;
+
+		if (UNSET != top_offset) {
+			fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;
+			rp = cx25821_risc_field_upstream(dev, rp,
+							 dev->
+							 _data_buf_phys_addr +
+							 databuf_offset,
+							 top_offset, 0, bpl,
+							 odd_num_lines,
+							 fifo_enable,
+							 ODD_FIELD);
+		}
+
+		fifo_enable = FIFO_DISABLE;
+
+		/* Even Field */
+		rp = cx25821_risc_field_upstream(dev, rp,
+						 dev->_data_buf_phys_addr +
+						 databuf_offset, bottom_offset,
+						 0x200, bpl, singlefield_lines,
+						 fifo_enable, EVEN_FIELD);
+
+		if (frame == 0) {
+			risc_flag = RISC_CNT_RESET;
+			risc_phys_jump_addr =
+			    dev->_dma_phys_start_addr + risc_program_size;
+		} else {
+			risc_phys_jump_addr = dev->_dma_phys_start_addr;
+			risc_flag = RISC_CNT_INC;
+		}
+
+		/* Loop to 2ndFrameRISC or to Start of Risc
+		 * program & generate IRQ
+		 */
+		*(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
+		*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+		*(rp++) = cpu_to_le32(0);
+	}
+
+	return 0;
+}
+
+void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev)
+{
+	struct sram_channel *sram_ch =
+	   dev->channels[VID_UPSTREAM_SRAM_CHANNEL_I].sram_channels;
+	u32 tmp = 0;
+
+	if (!dev->_is_running) {
+		pr_info("No video file is currently running so return!\n");
+		return;
+	}
+	/* Disable RISC interrupts */
+	tmp = cx_read(sram_ch->int_msk);
+	cx_write(sram_ch->int_msk, tmp & ~_intr_msk);
+
+	/* Turn OFF risc and fifo enable */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN));
+
+	/* Clear data buffer memory */
+	if (dev->_data_buf_virt_addr)
+		memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size);
+
+	dev->_is_running = 0;
+	dev->_is_first_frame = 0;
+	dev->_frame_count = 0;
+	dev->_file_status = END_OF_FILE;
+
+	kfree(dev->_irq_queues);
+	dev->_irq_queues = NULL;
+
+	kfree(dev->_filename);
+
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+}
+
+void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev)
+{
+	if (dev->_is_running)
+		cx25821_stop_upstream_video_ch1(dev);
+
+	if (dev->_dma_virt_addr) {
+		pci_free_consistent(dev->pci, dev->_risc_size,
+				    dev->_dma_virt_addr, dev->_dma_phys_addr);
+		dev->_dma_virt_addr = NULL;
+	}
+
+	if (dev->_data_buf_virt_addr) {
+		pci_free_consistent(dev->pci, dev->_data_buf_size,
+				    dev->_data_buf_virt_addr,
+				    dev->_data_buf_phys_addr);
+		dev->_data_buf_virt_addr = NULL;
+	}
+}
+
+int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int frame_index_temp = dev->_frame_index;
+	int i = 0;
+	int line_size =
+	    (dev->_pixel_format ==
+	     PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+	int frame_size = 0;
+	int frame_offset = 0;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t file_offset;
+	loff_t pos;
+	mm_segment_t old_fs;
+
+	if (dev->_file_status == END_OF_FILE)
+		return 0;
+
+	if (dev->_isNTSC) {
+		frame_size =
+		    (line_size ==
+		     Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 :
+		    FRAME_SIZE_NTSC_Y422;
+	} else {
+		frame_size =
+		    (line_size ==
+		     Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+	}
+
+	frame_offset = (frame_index_temp > 0) ? frame_size : 0;
+	file_offset = dev->_frame_count * frame_size;
+
+	myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0);
+
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_filename, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (i = 0; i < dev->_lines_count; i++) {
+			pos = file_offset;
+
+			vfs_read_retval =
+			    vfs_read(myfile, mybuf, line_size, &pos);
+
+			if (vfs_read_retval > 0 && vfs_read_retval == line_size
+			    && dev->_data_buf_virt_addr != NULL) {
+				memcpy((void *)(dev->_data_buf_virt_addr +
+						frame_offset / 4), mybuf,
+				       vfs_read_retval);
+			}
+
+			file_offset += vfs_read_retval;
+			frame_offset += vfs_read_retval;
+
+			if (vfs_read_retval < line_size) {
+				pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+					__func__);
+				break;
+			}
+		}
+
+		if (i > 0)
+			dev->_frame_count++;
+
+		dev->_file_status =
+		    (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+static void cx25821_vidups_handler(struct work_struct *work)
+{
+	struct cx25821_dev *dev =
+	    container_of(work, struct cx25821_dev, _irq_work_entry);
+
+	if (!dev) {
+		pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
+		       __func__);
+		return;
+	}
+
+	cx25821_get_frame(dev,
+			 dev->channels[dev->_channel_upstream_select].
+					       sram_channels);
+}
+
+int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int i = 0, j = 0;
+	int line_size =
+	    (dev->_pixel_format ==
+	     PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t pos;
+	loff_t offset = (unsigned long)0;
+	mm_segment_t old_fs;
+
+	myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0);
+
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_filename, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!  Returning\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (j = 0; j < NUM_FRAMES; j++) {
+			for (i = 0; i < dev->_lines_count; i++) {
+				pos = offset;
+
+				vfs_read_retval =
+				    vfs_read(myfile, mybuf, line_size, &pos);
+
+				if (vfs_read_retval > 0
+				    && vfs_read_retval == line_size
+				    && dev->_data_buf_virt_addr != NULL) {
+					memcpy((void *)(dev->
+							_data_buf_virt_addr +
+							offset / 4), mybuf,
+					       vfs_read_retval);
+				}
+
+				offset += vfs_read_retval;
+
+				if (vfs_read_retval < line_size) {
+					pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+						__func__);
+					break;
+				}
+			}
+
+			if (i > 0)
+				dev->_frame_count++;
+
+			if (vfs_read_retval < line_size)
+				break;
+		}
+
+		dev->_file_status =
+		    (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		myfile->f_pos = 0;
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
+				    struct sram_channel *sram_ch, int bpl)
+{
+	int ret = 0;
+	dma_addr_t dma_addr;
+	dma_addr_t data_dma_addr;
+
+	if (dev->_dma_virt_addr != NULL) {
+		pci_free_consistent(dev->pci, dev->upstream_riscbuf_size,
+				    dev->_dma_virt_addr, dev->_dma_phys_addr);
+	}
+
+	dev->_dma_virt_addr =
+	    pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size,
+				 &dma_addr);
+	dev->_dma_virt_start_addr = dev->_dma_virt_addr;
+	dev->_dma_phys_start_addr = dma_addr;
+	dev->_dma_phys_addr = dma_addr;
+	dev->_risc_size = dev->upstream_riscbuf_size;
+
+	if (!dev->_dma_virt_addr) {
+		pr_err("FAILED to allocate memory for Risc buffer! Returning\n");
+		return -ENOMEM;
+	}
+
+	/* Clear memory at address */
+	memset(dev->_dma_virt_addr, 0, dev->_risc_size);
+
+	if (dev->_data_buf_virt_addr != NULL) {
+		pci_free_consistent(dev->pci, dev->upstream_databuf_size,
+				    dev->_data_buf_virt_addr,
+				    dev->_data_buf_phys_addr);
+	}
+	/* For Video Data buffer allocation */
+	dev->_data_buf_virt_addr =
+	    pci_alloc_consistent(dev->pci, dev->upstream_databuf_size,
+				 &data_dma_addr);
+	dev->_data_buf_phys_addr = data_dma_addr;
+	dev->_data_buf_size = dev->upstream_databuf_size;
+
+	if (!dev->_data_buf_virt_addr) {
+		pr_err("FAILED to allocate memory for data buffer! Returning\n");
+		return -ENOMEM;
+	}
+
+	/* Clear memory at address */
+	memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size);
+
+	ret = cx25821_openfile(dev, sram_ch);
+	if (ret < 0)
+		return ret;
+
+	/* Create RISC programs */
+	ret =
+	    cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl,
+					 dev->_lines_count);
+	if (ret < 0) {
+		pr_info("Failed creating Video Upstream Risc programs!\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	return ret;
+}
+
+int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num,
+			       u32 status)
+{
+	u32 int_msk_tmp;
+	struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+	int singlefield_lines = NTSC_FIELD_HEIGHT;
+	int line_size_in_bytes = Y422_LINE_SZ;
+	int odd_risc_prog_size = 0;
+	dma_addr_t risc_phys_jump_addr;
+	__le32 *rp;
+
+	if (status & FLD_VID_SRC_RISC1) {
+		/* We should only process one program per call */
+		u32 prog_cnt = cx_read(channel->gpcnt);
+
+		/* Since we've identified our IRQ, clear our bits from the
+		 * interrupt mask and interrupt status registers */
+		int_msk_tmp = cx_read(channel->int_msk);
+		cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk);
+		cx_write(channel->int_stat, _intr_msk);
+
+		spin_lock(&dev->slock);
+
+		dev->_frame_index = prog_cnt;
+
+		queue_work(dev->_irq_queues, &dev->_irq_work_entry);
+
+		if (dev->_is_first_frame) {
+			dev->_is_first_frame = 0;
+
+			if (dev->_isNTSC) {
+				singlefield_lines += 1;
+				odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE;
+			} else {
+				singlefield_lines = PAL_FIELD_HEIGHT;
+				odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE;
+			}
+
+			if (dev->_dma_virt_start_addr != NULL) {
+				line_size_in_bytes =
+				    (dev->_pixel_format ==
+				     PIXEL_FRMT_411) ? Y411_LINE_SZ :
+				    Y422_LINE_SZ;
+				risc_phys_jump_addr =
+				    dev->_dma_phys_start_addr +
+				    odd_risc_prog_size;
+
+				rp = cx25821_update_riscprogram(dev,
+					dev->_dma_virt_start_addr, TOP_OFFSET,
+					line_size_in_bytes, 0x0,
+					singlefield_lines, FIFO_DISABLE,
+					ODD_FIELD);
+
+				/* Jump to Even Risc program of 1st Frame */
+				*(rp++) = cpu_to_le32(RISC_JUMP);
+				*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+				*(rp++) = cpu_to_le32(0);
+			}
+		}
+
+		spin_unlock(&dev->slock);
+	} else {
+		if (status & FLD_VID_SRC_UF)
+			pr_err("%s(): Video Received Underflow Error Interrupt!\n",
+			       __func__);
+
+		if (status & FLD_VID_SRC_SYNC)
+			pr_err("%s(): Video Received Sync Error Interrupt!\n",
+			       __func__);
+
+		if (status & FLD_VID_SRC_OPC_ERR)
+			pr_err("%s(): Video Received OpCode Error Interrupt!\n",
+			       __func__);
+	}
+
+	if (dev->_file_status == END_OF_FILE) {
+		pr_err("EOF Channel 1 Framecount = %d\n", dev->_frame_count);
+		return -1;
+	}
+	/* ElSE, set the interrupt mask register, re-enable irq. */
+	int_msk_tmp = cx_read(channel->int_msk);
+	cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
+
+	return 0;
+}
+
+static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id)
+{
+	struct cx25821_dev *dev = dev_id;
+	u32 msk_stat, vid_status;
+	int handled = 0;
+	int channel_num = 0;
+	struct sram_channel *sram_ch;
+
+	if (!dev)
+		return -1;
+
+	channel_num = VID_UPSTREAM_SRAM_CHANNEL_I;
+
+	sram_ch = dev->channels[channel_num].sram_channels;
+
+	msk_stat = cx_read(sram_ch->int_mstat);
+	vid_status = cx_read(sram_ch->int_stat);
+
+	/* Only deal with our interrupt */
+	if (vid_status) {
+		handled =
+		    cx25821_video_upstream_irq(dev, channel_num, vid_status);
+	}
+
+	if (handled < 0)
+		cx25821_stop_upstream_video_ch1(dev);
+	else
+		handled += handled;
+
+	return IRQ_RETVAL(handled);
+}
+
+void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch,
+			     int pix_format)
+{
+	int width = WIDTH_D1;
+	int height = dev->_lines_count;
+	int num_lines, odd_num_lines;
+	u32 value;
+	int vip_mode = OUTPUT_FRMT_656;
+
+	value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7);
+	value &= 0xFFFFFFEF;
+	value |= dev->_isNTSC ? 0 : 0x10;
+	cx_write(ch->vid_fmt_ctl, value);
+
+	/* set number of active pixels in each line.
+	 * Default is 720 pixels in both NTSC and PAL format */
+	cx_write(ch->vid_active_ctl1, width);
+
+	num_lines = (height / 2) & 0x3FF;
+	odd_num_lines = num_lines;
+
+	if (dev->_isNTSC)
+		odd_num_lines += 1;
+
+	value = (num_lines << 16) | odd_num_lines;
+
+	/* set number of active lines in field 0 (top) and field 1 (bottom) */
+	cx_write(ch->vid_active_ctl2, value);
+
+	cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
+}
+
+int cx25821_start_video_dma_upstream(struct cx25821_dev *dev,
+				     struct sram_channel *sram_ch)
+{
+	u32 tmp = 0;
+	int err = 0;
+
+	/* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
+	 * channel A-C
+	 */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+	/* Set the physical start address of the RISC program in the initial
+	 * program counter(IPC) member of the cmds.
+	 */
+	cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr);
+	/* Risc IPC High 64 bits 63-32 */
+	cx_write(sram_ch->cmds_start + 4, 0);
+
+	/* reset counter */
+	cx_write(sram_ch->gpcnt_ctl, 3);
+
+	/* Clear our bits from the interrupt status register. */
+	cx_write(sram_ch->int_stat, _intr_msk);
+
+	/* Set the interrupt mask register, enable irq. */
+	cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
+	tmp = cx_read(sram_ch->int_msk);
+	cx_write(sram_ch->int_msk, tmp |= _intr_msk);
+
+	err =
+	    request_irq(dev->pci->irq, cx25821_upstream_irq,
+			IRQF_SHARED, dev->name, dev);
+	if (err < 0) {
+		pr_err("%s: can't get upstream IRQ %d\n",
+		       dev->name, dev->pci->irq);
+		goto fail_irq;
+	}
+
+	/* Start the DMA  engine */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN);
+
+	dev->_is_running = 1;
+	dev->_is_first_frame = 1;
+
+	return 0;
+
+fail_irq:
+	cx25821_dev_unregister(dev);
+	return err;
+}
+
+int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
+				 int pixel_format)
+{
+	struct sram_channel *sram_ch;
+	u32 tmp;
+	int retval = 0;
+	int err = 0;
+	int data_frame_size = 0;
+	int risc_buffer_size = 0;
+	int str_length = 0;
+
+	if (dev->_is_running) {
+		pr_info("Video Channel is still running so return!\n");
+		return 0;
+	}
+
+	dev->_channel_upstream_select = channel_select;
+	sram_ch = dev->channels[channel_select].sram_channels;
+
+	INIT_WORK(&dev->_irq_work_entry, cx25821_vidups_handler);
+	dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue");
+
+	if (!dev->_irq_queues) {
+		pr_err("create_singlethread_workqueue() for Video FAILED!\n");
+		return -ENOMEM;
+	}
+	/* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
+	 * channel A-C
+	 */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+	dev->_is_running = 0;
+	dev->_frame_count = 0;
+	dev->_file_status = RESET_STATUS;
+	dev->_lines_count = dev->_isNTSC ? 480 : 576;
+	dev->_pixel_format = pixel_format;
+	dev->_line_size =
+	    (dev->_pixel_format ==
+	     PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+	data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
+	risc_buffer_size =
+	    dev->_isNTSC ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
+
+	if (dev->input_filename) {
+		str_length = strlen(dev->input_filename);
+		dev->_filename = kmalloc(str_length + 1, GFP_KERNEL);
+
+		if (!dev->_filename)
+			goto error;
+
+		memcpy(dev->_filename, dev->input_filename, str_length + 1);
+	} else {
+		str_length = strlen(dev->_defaultname);
+		dev->_filename = kmalloc(str_length + 1, GFP_KERNEL);
+
+		if (!dev->_filename)
+			goto error;
+
+		memcpy(dev->_filename, dev->_defaultname, str_length + 1);
+	}
+
+	/* Default if filename is empty string */
+	if (strcmp(dev->input_filename, "") == 0) {
+		if (dev->_isNTSC) {
+			dev->_filename =
+			    (dev->_pixel_format ==
+			     PIXEL_FRMT_411) ? "/root/vid411.yuv" :
+			    "/root/vidtest.yuv";
+		} else {
+			dev->_filename =
+			    (dev->_pixel_format ==
+			     PIXEL_FRMT_411) ? "/root/pal411.yuv" :
+			    "/root/pal422.yuv";
+		}
+	}
+
+	dev->_is_running = 0;
+	dev->_frame_count = 0;
+	dev->_file_status = RESET_STATUS;
+	dev->_lines_count = dev->_isNTSC ? 480 : 576;
+	dev->_pixel_format = pixel_format;
+	dev->_line_size =
+	    (dev->_pixel_format ==
+	     PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+
+	retval =
+	    cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size,
+						0);
+
+	/* setup fifo + format */
+	cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format);
+
+	dev->upstream_riscbuf_size = risc_buffer_size * 2;
+	dev->upstream_databuf_size = data_frame_size * 2;
+
+	/* Allocating buffers and prepare RISC program */
+	retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size);
+	if (retval < 0) {
+		pr_err("%s: Failed to set up Video upstream buffers!\n",
+		       dev->name);
+		goto error;
+	}
+
+	cx25821_start_video_dma_upstream(dev, sram_ch);
+
+	return 0;
+
+error:
+	cx25821_dev_unregister(dev);
+
+	return err;
+}
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,823 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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 "cx25821-video.h"
+#include "cx25821-video-upstream-ch2.h"
+
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC |
+			FLD_VID_SRC_OPC_ERR;
+
+static __le32 *cx25821_update_riscprogram_ch2(struct cx25821_dev *dev,
+					      __le32 *rp, unsigned int offset,
+					      unsigned int bpl, u32 sync_line,
+					      unsigned int lines,
+					      int fifo_enable, int field_type)
+{
+	unsigned int line, i;
+	int dist_betwn_starts = bpl * 2;
+
+	*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	if (USE_RISC_NOOP_VIDEO) {
+		for (i = 0; i < NUM_NO_OPS; i++)
+			*(rp++) = cpu_to_le32(RISC_NOOP);
+	}
+
+	/* scan lines */
+	for (line = 0; line < lines; line++) {
+		*(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+		*(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2 + offset);
+		*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+
+		if ((lines <= NTSC_FIELD_HEIGHT)
+		    || (line < (NTSC_FIELD_HEIGHT - 1))
+		    || !(dev->_isNTSC_ch2)) {
+			offset += dist_betwn_starts;
+		}
+	}
+
+	return rp;
+}
+
+static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev,
+					       __le32 *rp,
+					       dma_addr_t databuf_phys_addr,
+					       unsigned int offset,
+					       u32 sync_line, unsigned int bpl,
+					       unsigned int lines,
+					       int fifo_enable, int field_type)
+{
+	unsigned int line, i;
+	struct sram_channel *sram_ch =
+	   dev->channels[dev->_channel2_upstream_select].sram_channels;
+	int dist_betwn_starts = bpl * 2;
+
+	/* sync instruction */
+	if (sync_line != NO_SYNC_LINE)
+		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	if (USE_RISC_NOOP_VIDEO) {
+		for (i = 0; i < NUM_NO_OPS; i++)
+			*(rp++) = cpu_to_le32(RISC_NOOP);
+	}
+
+	/* scan lines */
+	for (line = 0; line < lines; line++) {
+		*(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+		*(rp++) = cpu_to_le32(databuf_phys_addr + offset);
+		*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+
+		if ((lines <= NTSC_FIELD_HEIGHT)
+		    || (line < (NTSC_FIELD_HEIGHT - 1))
+		    || !(dev->_isNTSC_ch2)) {
+			offset += dist_betwn_starts;
+		}
+
+	       /*
+		 check if we need to enable the FIFO after the first 4 lines
+		  For the upstream video channel, the risc engine will enable
+		  the FIFO.
+	       */
+		if (fifo_enable && line == 3) {
+			*(rp++) = RISC_WRITECR;
+			*(rp++) = sram_ch->dma_ctl;
+			*(rp++) = FLD_VID_FIFO_EN;
+			*(rp++) = 0x00000001;
+		}
+	}
+
+	return rp;
+}
+
+int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev,
+				     struct pci_dev *pci,
+				     unsigned int top_offset, unsigned int bpl,
+				     unsigned int lines)
+{
+	__le32 *rp;
+	int fifo_enable = 0;
+	int singlefield_lines = lines >> 1; /*get line count for single field */
+	int odd_num_lines = singlefield_lines;
+	int frame = 0;
+	int frame_size = 0;
+	int databuf_offset = 0;
+	int risc_program_size = 0;
+	int risc_flag = RISC_CNT_RESET;
+	unsigned int bottom_offset = bpl;
+	dma_addr_t risc_phys_jump_addr;
+
+	if (dev->_isNTSC_ch2) {
+		odd_num_lines = singlefield_lines + 1;
+		risc_program_size = FRAME1_VID_PROG_SIZE;
+		if (bpl == Y411_LINE_SZ)
+			frame_size = FRAME_SIZE_NTSC_Y411;
+		else
+			frame_size = FRAME_SIZE_NTSC_Y422;
+	} else {
+		risc_program_size = PAL_VID_PROG_SIZE;
+		if (bpl == Y411_LINE_SZ)
+			frame_size = FRAME_SIZE_PAL_Y411;
+		else
+			frame_size = FRAME_SIZE_PAL_Y422;
+	}
+
+	/* Virtual address of Risc buffer program */
+	rp = dev->_dma_virt_addr_ch2;
+
+	for (frame = 0; frame < NUM_FRAMES; frame++) {
+		databuf_offset = frame_size * frame;
+
+		if (UNSET != top_offset) {
+			fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;
+			rp = cx25821_risc_field_upstream_ch2(dev, rp,
+				dev->_data_buf_phys_addr_ch2 + databuf_offset,
+				top_offset, 0, bpl, odd_num_lines, fifo_enable,
+				ODD_FIELD);
+		}
+
+		fifo_enable = FIFO_DISABLE;
+
+	       /* Even field */
+		rp = cx25821_risc_field_upstream_ch2(dev, rp,
+				dev->_data_buf_phys_addr_ch2 + databuf_offset,
+				bottom_offset, 0x200, bpl, singlefield_lines,
+				fifo_enable, EVEN_FIELD);
+
+		if (frame == 0) {
+			risc_flag = RISC_CNT_RESET;
+			risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 +
+					risc_program_size;
+		} else {
+			risc_flag = RISC_CNT_INC;
+			risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2;
+		}
+
+	       /*
+		  Loop to 2ndFrameRISC or to Start of
+		  Risc program & generate IRQ
+	       */
+		*(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
+		*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+		*(rp++) = cpu_to_le32(0);
+	}
+
+	return 0;
+}
+
+void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev)
+{
+	struct sram_channel *sram_ch =
+	   dev->channels[VID_UPSTREAM_SRAM_CHANNEL_J].sram_channels;
+	u32 tmp = 0;
+
+	if (!dev->_is_running_ch2) {
+		pr_info("No video file is currently running so return!\n");
+		return;
+	}
+	/* Disable RISC interrupts */
+	tmp = cx_read(sram_ch->int_msk);
+	cx_write(sram_ch->int_msk, tmp & ~_intr_msk);
+
+	/* Turn OFF risc and fifo */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN));
+
+	/* Clear data buffer memory */
+	if (dev->_data_buf_virt_addr_ch2)
+		memset(dev->_data_buf_virt_addr_ch2, 0,
+		       dev->_data_buf_size_ch2);
+
+	dev->_is_running_ch2 = 0;
+	dev->_is_first_frame_ch2 = 0;
+	dev->_frame_count_ch2 = 0;
+	dev->_file_status_ch2 = END_OF_FILE;
+
+	kfree(dev->_irq_queues_ch2);
+	dev->_irq_queues_ch2 = NULL;
+
+	kfree(dev->_filename_ch2);
+
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+}
+
+void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev)
+{
+	if (dev->_is_running_ch2)
+		cx25821_stop_upstream_video_ch2(dev);
+
+	if (dev->_dma_virt_addr_ch2) {
+		pci_free_consistent(dev->pci, dev->_risc_size_ch2,
+				    dev->_dma_virt_addr_ch2,
+				    dev->_dma_phys_addr_ch2);
+		dev->_dma_virt_addr_ch2 = NULL;
+	}
+
+	if (dev->_data_buf_virt_addr_ch2) {
+		pci_free_consistent(dev->pci, dev->_data_buf_size_ch2,
+				    dev->_data_buf_virt_addr_ch2,
+				    dev->_data_buf_phys_addr_ch2);
+		dev->_data_buf_virt_addr_ch2 = NULL;
+	}
+}
+
+int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int frame_index_temp = dev->_frame_index_ch2;
+	int i = 0;
+	int line_size =
+	    (dev->_pixel_format_ch2 ==
+	     PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+	int frame_size = 0;
+	int frame_offset = 0;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t file_offset;
+	loff_t pos;
+	mm_segment_t old_fs;
+
+	if (dev->_file_status_ch2 == END_OF_FILE)
+		return 0;
+
+	if (dev->_isNTSC_ch2) {
+		frame_size =
+		    (line_size ==
+		     Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 :
+		    FRAME_SIZE_NTSC_Y422;
+	} else {
+		frame_size =
+		    (line_size ==
+		     Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+	}
+
+	frame_offset = (frame_index_temp > 0) ? frame_size : 0;
+	file_offset = dev->_frame_count_ch2 * frame_size;
+
+	myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0);
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_filename_ch2, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (i = 0; i < dev->_lines_count_ch2; i++) {
+			pos = file_offset;
+
+			vfs_read_retval =
+			    vfs_read(myfile, mybuf, line_size, &pos);
+
+			if (vfs_read_retval > 0 && vfs_read_retval == line_size
+			    && dev->_data_buf_virt_addr_ch2 != NULL) {
+				memcpy((void *)(dev->_data_buf_virt_addr_ch2 +
+						frame_offset / 4), mybuf,
+				       vfs_read_retval);
+			}
+
+			file_offset += vfs_read_retval;
+			frame_offset += vfs_read_retval;
+
+			if (vfs_read_retval < line_size) {
+				pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+					__func__);
+				break;
+			}
+		}
+
+		if (i > 0)
+			dev->_frame_count_ch2++;
+
+		dev->_file_status_ch2 =
+		    (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+static void cx25821_vidups_handler_ch2(struct work_struct *work)
+{
+	struct cx25821_dev *dev =
+	    container_of(work, struct cx25821_dev, _irq_work_entry_ch2);
+
+	if (!dev) {
+		pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
+		       __func__);
+		return;
+	}
+
+	cx25821_get_frame_ch2(dev,
+			     dev->channels[dev->
+			       _channel2_upstream_select].sram_channels);
+}
+
+int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int i = 0, j = 0;
+	int line_size =
+	    (dev->_pixel_format_ch2 ==
+	     PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t pos;
+	loff_t offset = (unsigned long)0;
+	mm_segment_t old_fs;
+
+	myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0);
+
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_filename_ch2, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!  Returning\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (j = 0; j < NUM_FRAMES; j++) {
+			for (i = 0; i < dev->_lines_count_ch2; i++) {
+				pos = offset;
+
+				vfs_read_retval =
+				    vfs_read(myfile, mybuf, line_size, &pos);
+
+				if (vfs_read_retval > 0
+				    && vfs_read_retval == line_size
+				    && dev->_data_buf_virt_addr_ch2 != NULL) {
+					memcpy((void *)(dev->
+							_data_buf_virt_addr_ch2
+							+ offset / 4), mybuf,
+					       vfs_read_retval);
+				}
+
+				offset += vfs_read_retval;
+
+				if (vfs_read_retval < line_size) {
+					pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+						__func__);
+					break;
+				}
+			}
+
+			if (i > 0)
+				dev->_frame_count_ch2++;
+
+			if (vfs_read_retval < line_size)
+				break;
+		}
+
+		dev->_file_status_ch2 =
+		    (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		myfile->f_pos = 0;
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev,
+					       struct sram_channel *sram_ch,
+					       int bpl)
+{
+	int ret = 0;
+	dma_addr_t dma_addr;
+	dma_addr_t data_dma_addr;
+
+	if (dev->_dma_virt_addr_ch2 != NULL) {
+		pci_free_consistent(dev->pci, dev->upstream_riscbuf_size_ch2,
+				    dev->_dma_virt_addr_ch2,
+				    dev->_dma_phys_addr_ch2);
+	}
+
+	dev->_dma_virt_addr_ch2 =
+	    pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size_ch2,
+				 &dma_addr);
+	dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2;
+	dev->_dma_phys_start_addr_ch2 = dma_addr;
+	dev->_dma_phys_addr_ch2 = dma_addr;
+	dev->_risc_size_ch2 = dev->upstream_riscbuf_size_ch2;
+
+	if (!dev->_dma_virt_addr_ch2) {
+		pr_err("FAILED to allocate memory for Risc buffer! Returning\n");
+		return -ENOMEM;
+	}
+
+	/* Iniitize at this address until n bytes to 0 */
+	memset(dev->_dma_virt_addr_ch2, 0, dev->_risc_size_ch2);
+
+	if (dev->_data_buf_virt_addr_ch2 != NULL) {
+		pci_free_consistent(dev->pci, dev->upstream_databuf_size_ch2,
+				    dev->_data_buf_virt_addr_ch2,
+				    dev->_data_buf_phys_addr_ch2);
+	}
+	/* For Video Data buffer allocation */
+	dev->_data_buf_virt_addr_ch2 =
+	    pci_alloc_consistent(dev->pci, dev->upstream_databuf_size_ch2,
+				 &data_dma_addr);
+	dev->_data_buf_phys_addr_ch2 = data_dma_addr;
+	dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2;
+
+	if (!dev->_data_buf_virt_addr_ch2) {
+		pr_err("FAILED to allocate memory for data buffer! Returning\n");
+		return -ENOMEM;
+	}
+
+	/* Initialize at this address until n bytes to 0 */
+	memset(dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2);
+
+	ret = cx25821_openfile_ch2(dev, sram_ch);
+	if (ret < 0)
+		return ret;
+
+	/* Creating RISC programs */
+	ret = cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl,
+						dev->_lines_count_ch2);
+	if (ret < 0) {
+		pr_info("Failed creating Video Upstream Risc programs!\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	return ret;
+}
+
+int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num,
+				   u32 status)
+{
+	u32 int_msk_tmp;
+	struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+	int singlefield_lines = NTSC_FIELD_HEIGHT;
+	int line_size_in_bytes = Y422_LINE_SZ;
+	int odd_risc_prog_size = 0;
+	dma_addr_t risc_phys_jump_addr;
+	__le32 *rp;
+
+	if (status & FLD_VID_SRC_RISC1) {
+		/* We should only process one program per call */
+		u32 prog_cnt = cx_read(channel->gpcnt);
+
+		/*
+		 *  Since we've identified our IRQ, clear our bits from the
+		 *  interrupt mask and interrupt status registers
+		 */
+		int_msk_tmp = cx_read(channel->int_msk);
+		cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk);
+		cx_write(channel->int_stat, _intr_msk);
+
+		spin_lock(&dev->slock);
+
+		dev->_frame_index_ch2 = prog_cnt;
+
+		queue_work(dev->_irq_queues_ch2, &dev->_irq_work_entry_ch2);
+
+		if (dev->_is_first_frame_ch2) {
+			dev->_is_first_frame_ch2 = 0;
+
+			if (dev->_isNTSC_ch2) {
+				singlefield_lines += 1;
+				odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE;
+			} else {
+				singlefield_lines = PAL_FIELD_HEIGHT;
+				odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE;
+			}
+
+			if (dev->_dma_virt_start_addr_ch2 != NULL) {
+				if (dev->_pixel_format_ch2 == PIXEL_FRMT_411)
+					line_size_in_bytes = Y411_LINE_SZ;
+				else
+					line_size_in_bytes = Y422_LINE_SZ;
+				risc_phys_jump_addr =
+				    dev->_dma_phys_start_addr_ch2 +
+				    odd_risc_prog_size;
+
+				rp = cx25821_update_riscprogram_ch2(dev,
+						dev->_dma_virt_start_addr_ch2,
+						TOP_OFFSET, line_size_in_bytes,
+						0x0, singlefield_lines,
+						FIFO_DISABLE, ODD_FIELD);
+
+			       /* Jump to Even Risc program of 1st Frame */
+				*(rp++) = cpu_to_le32(RISC_JUMP);
+				*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+				*(rp++) = cpu_to_le32(0);
+			}
+		}
+
+		spin_unlock(&dev->slock);
+	}
+
+	if (dev->_file_status_ch2 == END_OF_FILE) {
+		pr_info("EOF Channel 2 Framecount = %d\n",
+			dev->_frame_count_ch2);
+		return -1;
+	}
+	/* ElSE, set the interrupt mask register, re-enable irq. */
+	int_msk_tmp = cx_read(channel->int_msk);
+	cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
+
+	return 0;
+}
+
+static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id)
+{
+	struct cx25821_dev *dev = dev_id;
+	u32 msk_stat, vid_status;
+	int handled = 0;
+	int channel_num = 0;
+	struct sram_channel *sram_ch;
+
+	if (!dev)
+		return -1;
+
+	channel_num = VID_UPSTREAM_SRAM_CHANNEL_J;
+	sram_ch = dev->channels[channel_num].sram_channels;
+
+	msk_stat = cx_read(sram_ch->int_mstat);
+	vid_status = cx_read(sram_ch->int_stat);
+
+	/* Only deal with our interrupt */
+	if (vid_status) {
+		handled =
+		    cx25821_video_upstream_irq_ch2(dev, channel_num,
+						   vid_status);
+	}
+
+	if (handled < 0)
+		cx25821_stop_upstream_video_ch2(dev);
+	else
+		handled += handled;
+
+	return IRQ_RETVAL(handled);
+}
+
+static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev,
+					struct sram_channel *ch, int pix_format)
+{
+	int width = WIDTH_D1;
+	int height = dev->_lines_count_ch2;
+	int num_lines, odd_num_lines;
+	u32 value;
+	int vip_mode = PIXEL_ENGINE_VIP1;
+
+	value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7);
+	value &= 0xFFFFFFEF;
+	value |= dev->_isNTSC_ch2 ? 0 : 0x10;
+	cx_write(ch->vid_fmt_ctl, value);
+
+	/*
+	 *  set number of active pixels in each line. Default is 720
+	 * pixels in both NTSC and PAL format
+	 */
+	cx_write(ch->vid_active_ctl1, width);
+
+	num_lines = (height / 2) & 0x3FF;
+	odd_num_lines = num_lines;
+
+	if (dev->_isNTSC_ch2)
+		odd_num_lines += 1;
+
+	value = (num_lines << 16) | odd_num_lines;
+
+	/* set number of active lines in field 0 (top) and field 1 (bottom) */
+	cx_write(ch->vid_active_ctl2, value);
+
+	cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
+}
+
+int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev,
+					 struct sram_channel *sram_ch)
+{
+	u32 tmp = 0;
+	int err = 0;
+
+	/*
+	 *  656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface
+	 * for channel A-C
+	 */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+	/*
+	 *  Set the physical start address of the RISC program in the initial
+	 *  program counter(IPC) member of the cmds.
+	 */
+	cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr_ch2);
+	cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */
+
+	/* reset counter */
+	cx_write(sram_ch->gpcnt_ctl, 3);
+
+	/* Clear our bits from the interrupt status register. */
+	cx_write(sram_ch->int_stat, _intr_msk);
+
+	/* Set the interrupt mask register, enable irq. */
+	cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
+	tmp = cx_read(sram_ch->int_msk);
+	cx_write(sram_ch->int_msk, tmp |= _intr_msk);
+
+	err =
+	    request_irq(dev->pci->irq, cx25821_upstream_irq_ch2,
+			IRQF_SHARED, dev->name, dev);
+	if (err < 0) {
+		pr_err("%s: can't get upstream IRQ %d\n",
+		       dev->name, dev->pci->irq);
+		goto fail_irq;
+	}
+	/* Start the DMA  engine */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN);
+
+	dev->_is_running_ch2 = 1;
+	dev->_is_first_frame_ch2 = 1;
+
+	return 0;
+
+fail_irq:
+	cx25821_dev_unregister(dev);
+	return err;
+}
+
+int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
+				 int pixel_format)
+{
+	struct sram_channel *sram_ch;
+	u32 tmp;
+	int retval = 0;
+	int err = 0;
+	int data_frame_size = 0;
+	int risc_buffer_size = 0;
+	int str_length = 0;
+
+	if (dev->_is_running_ch2) {
+		pr_info("Video Channel is still running so return!\n");
+		return 0;
+	}
+
+	dev->_channel2_upstream_select = channel_select;
+	sram_ch = dev->channels[channel_select].sram_channels;
+
+	INIT_WORK(&dev->_irq_work_entry_ch2, cx25821_vidups_handler_ch2);
+	dev->_irq_queues_ch2 =
+	    create_singlethread_workqueue("cx25821_workqueue2");
+
+	if (!dev->_irq_queues_ch2) {
+		pr_err("create_singlethread_workqueue() for Video FAILED!\n");
+		return -ENOMEM;
+	}
+	/*
+	 * 656/VIP SRC Upstream Channel I & J and 7 -
+	 * Host Bus Interface for channel A-C
+	 */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+	dev->_is_running_ch2 = 0;
+	dev->_frame_count_ch2 = 0;
+	dev->_file_status_ch2 = RESET_STATUS;
+	dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576;
+	dev->_pixel_format_ch2 = pixel_format;
+	dev->_line_size_ch2 =
+	    (dev->_pixel_format_ch2 ==
+	     PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+	data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
+	risc_buffer_size =
+	    dev->_isNTSC_ch2 ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
+
+	if (dev->input_filename_ch2) {
+		str_length = strlen(dev->input_filename_ch2);
+		dev->_filename_ch2 = kmalloc(str_length + 1, GFP_KERNEL);
+
+		if (!dev->_filename_ch2)
+			goto error;
+
+		memcpy(dev->_filename_ch2, dev->input_filename_ch2,
+		       str_length + 1);
+	} else {
+		str_length = strlen(dev->_defaultname_ch2);
+		dev->_filename_ch2 = kmalloc(str_length + 1, GFP_KERNEL);
+
+		if (!dev->_filename_ch2)
+			goto error;
+
+		memcpy(dev->_filename_ch2, dev->_defaultname_ch2,
+		       str_length + 1);
+	}
+
+	/* Default if filename is empty string */
+	if (strcmp(dev->input_filename_ch2, "") == 0) {
+		if (dev->_isNTSC_ch2) {
+			dev->_filename_ch2 =
+			    (dev->_pixel_format_ch2 ==
+			     PIXEL_FRMT_411) ? "/root/vid411.yuv" :
+			    "/root/vidtest.yuv";
+		} else {
+			dev->_filename_ch2 =
+			    (dev->_pixel_format_ch2 ==
+			     PIXEL_FRMT_411) ? "/root/pal411.yuv" :
+			    "/root/pal422.yuv";
+		}
+	}
+
+	retval = cx25821_sram_channel_setup_upstream(dev, sram_ch,
+						dev->_line_size_ch2, 0);
+
+	/* setup fifo + format */
+	cx25821_set_pixelengine_ch2(dev, sram_ch, dev->_pixel_format_ch2);
+
+	dev->upstream_riscbuf_size_ch2 = risc_buffer_size * 2;
+	dev->upstream_databuf_size_ch2 = data_frame_size * 2;
+
+	/* Allocating buffers and prepare RISC program */
+	retval = cx25821_upstream_buffer_prepare_ch2(dev, sram_ch,
+						dev->_line_size_ch2);
+	if (retval < 0) {
+		pr_err("%s: Failed to set up Video upstream buffers!\n",
+		       dev->name);
+		goto error;
+	}
+
+	cx25821_start_video_dma_upstream_ch2(dev, sram_ch);
+
+	return 0;
+
+error:
+	cx25821_dev_unregister(dev);
+
+	return err;
+}
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-video-upstream-ch2.h linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-video-upstream-ch2.h
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-video-upstream-ch2.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-video-upstream-ch2.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,138 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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/mutex.h>
+#include <linux/workqueue.h>
+
+#define OPEN_FILE_1           0
+#define NUM_PROGS             8
+#define NUM_FRAMES            2
+#define ODD_FIELD             0
+#define EVEN_FIELD            1
+#define TOP_OFFSET            0
+#define FIFO_DISABLE          0
+#define FIFO_ENABLE           1
+#define TEST_FRAMES           5
+#define END_OF_FILE           0
+#define IN_PROGRESS           1
+#define RESET_STATUS          -1
+#define NUM_NO_OPS            5
+
+/* PAL and NTSC line sizes and number of lines. */
+#define WIDTH_D1              720
+#define NTSC_LINES_PER_FRAME  480
+#define PAL_LINES_PER_FRAME   576
+#define PAL_LINE_SZ           1440
+#define Y422_LINE_SZ          1440
+#define Y411_LINE_SZ          1080
+#define NTSC_FIELD_HEIGHT     240
+#define NTSC_ODD_FLD_LINES    241
+#define PAL_FIELD_HEIGHT      288
+
+#define FRAME_SIZE_NTSC_Y422    (NTSC_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_NTSC_Y411    (NTSC_LINES_PER_FRAME * Y411_LINE_SZ)
+#define FRAME_SIZE_PAL_Y422     (PAL_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_PAL_Y411     (PAL_LINES_PER_FRAME * Y411_LINE_SZ)
+
+#define NTSC_DATA_BUF_SZ        (Y422_LINE_SZ * NTSC_LINES_PER_FRAME)
+#define PAL_DATA_BUF_SZ         (Y422_LINE_SZ * PAL_LINES_PER_FRAME)
+
+#define RISC_WRITECR_INSTRUCTION_SIZE   16
+#define RISC_SYNC_INSTRUCTION_SIZE      4
+#define JUMP_INSTRUCTION_SIZE           12
+#define MAXSIZE_NO_OPS                  36
+#define DWORD_SIZE                      4
+
+#define USE_RISC_NOOP_VIDEO   1
+
+#ifdef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define PAL_RISC_BUF_SIZE         (2 * PAL_US_VID_PROG_SIZE)
+
+#define PAL_VID_PROG_SIZE						\
+	((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +			\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +			\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define NTSC_RISC_BUF_SIZE						\
+	(2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) *			\
+	 3 * DWORD_SIZE + 2 * RISC_SYNC_INSTRUCTION_SIZE +		\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE +	\
+	 2 * NUM_NO_OPS * DWORD_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE						\
+	(NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+#endif
+
+#ifndef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE						\
+	((PAL_FIELD_HEIGHT + 1) * 3 * DWORD_SIZE +			\
+	 RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define PAL_RISC_BUF_SIZE						\
+	(2 * (RISC_SYNC_INSTRUCTION_SIZE + PAL_US_VID_PROG_SIZE))
+
+#define PAL_VID_PROG_SIZE						\
+	((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +			\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE						\
+	(NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +			\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
+
+#define NTSC_RISC_BUF_SIZE						\
+	(2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) *			\
+	 3 * DWORD_SIZE + 2 * RISC_SYNC_INSTRUCTION_SIZE +		\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-video-upstream.h linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-video-upstream.h
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/cx25821-video-upstream.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/cx25821-video-upstream.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,139 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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/mutex.h>
+#include <linux/workqueue.h>
+
+#define OUTPUT_FRMT_656       0
+#define OPEN_FILE_1           0
+#define NUM_PROGS             8
+#define NUM_FRAMES            2
+#define ODD_FIELD             0
+#define EVEN_FIELD            1
+#define TOP_OFFSET            0
+#define FIFO_DISABLE          0
+#define FIFO_ENABLE           1
+#define TEST_FRAMES           5
+#define END_OF_FILE           0
+#define IN_PROGRESS           1
+#define RESET_STATUS          -1
+#define NUM_NO_OPS            5
+
+/* PAL and NTSC line sizes and number of lines. */
+#define WIDTH_D1              720
+#define NTSC_LINES_PER_FRAME  480
+#define PAL_LINES_PER_FRAME   576
+#define PAL_LINE_SZ           1440
+#define Y422_LINE_SZ          1440
+#define Y411_LINE_SZ          1080
+#define NTSC_FIELD_HEIGHT     240
+#define NTSC_ODD_FLD_LINES    241
+#define PAL_FIELD_HEIGHT      288
+
+#define FRAME_SIZE_NTSC_Y422    (NTSC_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_NTSC_Y411    (NTSC_LINES_PER_FRAME * Y411_LINE_SZ)
+#define FRAME_SIZE_PAL_Y422     (PAL_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_PAL_Y411     (PAL_LINES_PER_FRAME * Y411_LINE_SZ)
+
+#define NTSC_DATA_BUF_SZ        (Y422_LINE_SZ * NTSC_LINES_PER_FRAME)
+#define PAL_DATA_BUF_SZ         (Y422_LINE_SZ * PAL_LINES_PER_FRAME)
+
+#define RISC_WRITECR_INSTRUCTION_SIZE   16
+#define RISC_SYNC_INSTRUCTION_SIZE      4
+#define JUMP_INSTRUCTION_SIZE           12
+#define MAXSIZE_NO_OPS                  36
+#define DWORD_SIZE                      4
+
+#define USE_RISC_NOOP_VIDEO   1
+
+#ifdef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define PAL_RISC_BUF_SIZE           (2 * PAL_US_VID_PROG_SIZE)
+
+#define PAL_VID_PROG_SIZE						\
+	((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +			\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE						\
+	(NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +			\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define NTSC_RISC_BUF_SIZE						\
+	(2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE +	\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE)
+
+#endif
+
+#ifndef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE +	\
+	 JUMP_INSTRUCTION_SIZE)
+
+#define PAL_RISC_BUF_SIZE		(2 * PAL_US_VID_PROG_SIZE)
+
+#define PAL_VID_PROG_SIZE						\
+	((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +			\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE						\
+	(NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +			\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
+
+#define NTSC_RISC_BUF_SIZE						\
+	(2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE +	\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE)
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/Kconfig linux-libre-3.2-gnu/drivers/media/video/cx25821/Kconfig
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,34 @@
+config VIDEO_CX25821
+	tristate "Conexant cx25821 support"
+	depends on DVB_CORE && VIDEO_DEV && PCI && I2C
+	select I2C_ALGOBIT
+	select VIDEO_BTCX
+	select VIDEO_TVEEPROM
+	depends on RC_CORE
+	select VIDEOBUF_DVB
+	select VIDEOBUF_DMA_SG
+	select VIDEO_CX25840
+	select VIDEO_CX2341X
+	---help---
+	  This is a video4linux driver for Conexant 25821 based
+	  TV cards.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx25821
+
+config VIDEO_CX25821_ALSA
+	tristate "Conexant 25821 DMA audio support"
+	depends on VIDEO_CX25821 && SND && EXPERIMENTAL
+	select SND_PCM
+	---help---
+	  This is a video4linux driver for direct (DMA) audio on
+	  Conexant 25821 based capture cards using ALSA.
+
+	  It only works with boards with function 01 enabled.
+	  To check if your board supports, use lspci -n.
+	  If supported, you should see 14f1:8801 or 14f1:8811
+	  PCI device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx25821-alsa.
+
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25821/Makefile linux-libre-3.2-gnu/drivers/media/video/cx25821/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/cx25821/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/cx25821/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,13 @@
+cx25821-y   := cx25821-core.o cx25821-cards.o cx25821-i2c.o \
+		       cx25821-gpio.o cx25821-medusa-video.o \
+		       cx25821-video.o cx25821-video-upstream.o \
+		       cx25821-video-upstream-ch2.o \
+		       cx25821-audio-upstream.o
+
+obj-$(CONFIG_VIDEO_CX25821) += cx25821.o
+obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o
+
+ccflags-y := -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25840/cx25840-audio.c linux-libre-3.2-gnu/drivers/media/video/cx25840/cx25840-audio.c
--- linux-libre-3.1-gnu/drivers/media/video/cx25840/cx25840-audio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx25840/cx25840-audio.c	2012-01-04 18:55:44.000000000 -0500
@@ -480,6 +480,7 @@
 
 static void set_volume(struct i2c_client *client, int volume)
 {
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
 	int vol;
 
 	/* Convert the volume to msp3400 values (0-127) */
@@ -495,7 +496,14 @@
 	}
 
 	/* PATH1_VOLUME */
-	cx25840_write(client, 0x8d4, 228 - (vol * 2));
+	if (is_cx2388x(state)) {
+		/* for cx23885 volume doesn't work,
+		 * the calculation always results in
+		 * e4 regardless.
+		 */
+		cx25840_write(client, 0x8d4, volume);
+	} else
+		cx25840_write(client, 0x8d4, 228 - (vol * 2));
 }
 
 static void set_balance(struct i2c_client *client, int balance)
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25840/cx25840-core.c linux-libre-3.2-gnu/drivers/media/video/cx25840/cx25840-core.c
--- linux-libre-3.1-gnu/drivers/media/video/cx25840/cx25840-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx25840/cx25840-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -702,6 +702,13 @@
 
 	/* start microcontroller */
 	cx25840_and_or(client, 0x803, ~0x10, 0x10);
+
+	/* CC raw enable */
+	cx25840_write(client, 0x404, 0x0b);
+
+	/* CC on */
+	cx25840_write(client, 0x42f, 0x66);
+	cx25840_write4(client, 0x474, 0x1e1e601a);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -1067,6 +1074,18 @@
 		cx25840_write(client, 0x919, 0x01);
 	}
 
+	if (is_cx2388x(state) && ((aud_input == CX25840_AUDIO7) ||
+		(aud_input == CX25840_AUDIO6))) {
+		/* Configure audio from LR1 or LR2 input */
+		cx25840_write4(client, 0x910, 0);
+		cx25840_write4(client, 0x8d0, 0x63073);
+	} else
+	if (is_cx2388x(state) && (aud_input == CX25840_AUDIO8)) {
+		/* Configure audio from tuner/sif input */
+		cx25840_write4(client, 0x910, 0x12b000c9);
+		cx25840_write4(client, 0x8d0, 0x1f063870);
+	}
+
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25840/cx25840-ir.c linux-libre-3.2-gnu/drivers/media/video/cx25840/cx25840-ir.c
--- linux-libre-3.1-gnu/drivers/media/video/cx25840/cx25840-ir.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx25840/cx25840-ir.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 
 #include <linux/slab.h>
 #include <linux/kfifo.h>
+#include <linux/module.h>
 #include <media/cx25840.h>
 #include <media/rc-core.h>
 
@@ -668,7 +669,7 @@
 	u16 divider;
 	unsigned int i, n;
 	union cx25840_ir_fifo_rec *p;
-	unsigned u, v;
+	unsigned u, v, w;
 
 	if (ir_state == NULL)
 		return -ENODEV;
@@ -694,11 +695,12 @@
 		if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
 			/* Assume RTO was because of no IR light input */
 			u = 0;
-			v4l2_dbg(2, ir_debug, sd, "rx read: end of rx\n");
+			w = 1;
 		} else {
 			u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
 			if (invert)
 				u = u ? 0 : 1;
+			w = 0;
 		}
 
 		v = (unsigned) pulse_width_count_to_ns(
@@ -709,9 +711,12 @@
 		init_ir_raw_event(&p->ir_core_data);
 		p->ir_core_data.pulse = u;
 		p->ir_core_data.duration = v;
+		p->ir_core_data.timeout = w;
 
-		v4l2_dbg(2, ir_debug, sd, "rx read: %10u ns  %s\n",
-			 v, u ? "mark" : "space");
+		v4l2_dbg(2, ir_debug, sd, "rx read: %10u ns  %s  %s\n",
+			 v, u ? "mark" : "space", w ? "(timed out)" : "");
+		if (w)
+			v4l2_dbg(2, ir_debug, sd, "rx read: end of rx\n");
 	}
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx25840/Makefile linux-libre-3.2-gnu/drivers/media/video/cx25840/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/cx25840/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx25840/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -3,4 +3,4 @@
 
 obj-$(CONFIG_VIDEO_CX25840) += cx25840.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
+ccflags-y += -Idrivers/media/video
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx88/cx88-core.c linux-libre-3.2-gnu/drivers/media/video/cx88/cx88-core.c
--- linux-libre-3.1-gnu/drivers/media/video/cx88/cx88-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx88/cx88-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -636,9 +636,6 @@
 	cx_write(MO_PCI_INTSTAT,   0xFFFFFFFF); // Clear PCI int
 	cx_write(MO_INT1_STAT,     0xFFFFFFFF); // Clear RISC int
 
-	/* set default notch filter */
-	cx_andor(MO_HTOTAL, 0x1800, (HLNotchFilter4xFsc << 11));
-
 	/* Reset on-board parts */
 	cx_write(MO_SRST_IO, 0);
 	msleep(10);
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx88/cx88-video.c linux-libre-3.2-gnu/drivers/media/video/cx88/cx88-video.c
--- linux-libre-3.1-gnu/drivers/media/video/cx88/cx88-video.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx88/cx88-video.c	2012-01-04 18:55:44.000000000 -0500
@@ -266,7 +266,7 @@
 			.id            = V4L2_CID_BAND_STOP_FILTER,
 			.name          = "Notch filter",
 			.minimum       = 0,
-			.maximum       = 3,
+			.maximum       = 1,
 			.step          = 1,
 			.default_value = 0x0,
 			.type          = V4L2_CTRL_TYPE_INTEGER,
diff -druN linux-libre-3.1-gnu/drivers/media/video/cx88/Makefile linux-libre-3.2-gnu/drivers/media/video/cx88/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/cx88/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/cx88/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
 obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
 obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff -druN linux-libre-3.1-gnu/drivers/media/video/davinci/dm355_ccdc.c linux-libre-3.2-gnu/drivers/media/video/davinci/dm355_ccdc.c
--- linux-libre-3.1-gnu/drivers/media/video/davinci/dm355_ccdc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/davinci/dm355_ccdc.c	2012-01-04 18:55:44.000000000 -0500
@@ -39,6 +39,7 @@
 #include <linux/videodev2.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/module.h>
 
 #include <media/davinci/dm355_ccdc.h>
 #include <media/davinci/vpss.h>
diff -druN linux-libre-3.1-gnu/drivers/media/video/davinci/dm644x_ccdc.c linux-libre-3.2-gnu/drivers/media/video/davinci/dm644x_ccdc.c
--- linux-libre-3.1-gnu/drivers/media/video/davinci/dm644x_ccdc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/davinci/dm644x_ccdc.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,7 @@
 #include <linux/gfp.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/module.h>
 
 #include <media/davinci/dm644x_ccdc.h>
 #include <media/davinci/vpss.h>
diff -druN linux-libre-3.1-gnu/drivers/media/video/davinci/vpbe_display.c linux-libre-3.2-gnu/drivers/media/video/davinci/vpbe_display.c
--- linux-libre-3.1-gnu/drivers/media/video/davinci/vpbe_display.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/davinci/vpbe_display.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,6 @@
 
 static int debug;
 
-#define VPBE_DISPLAY_SD_BUF_SIZE (720*576*2)
 #define VPBE_DEFAULT_NUM_BUFS 3
 
 module_param(debug, int, 0644);
diff -druN linux-libre-3.1-gnu/drivers/media/video/davinci/vpbe_osd.c linux-libre-3.2-gnu/drivers/media/video/davinci/vpbe_osd.c
--- linux-libre-3.1-gnu/drivers/media/video/davinci/vpbe_osd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/davinci/vpbe_osd.c	2012-01-04 18:55:44.000000000 -0500
@@ -1162,7 +1162,7 @@
 		goto free_mem;
 	}
 	osd->osd_base_phys = res->start;
-	osd->osd_size = res->end - res->start + 1;
+	osd->osd_size = resource_size(res);
 	if (!request_mem_region(osd->osd_base_phys, osd->osd_size,
 				MODULE_NAME)) {
 		dev_err(osd->dev, "Unable to reserve OSD MMIO region\n");
diff -druN linux-libre-3.1-gnu/drivers/media/video/em28xx/em28xx-cards.c linux-libre-3.2-gnu/drivers/media/video/em28xx/em28xx-cards.c
--- linux-libre-3.1-gnu/drivers/media/video/em28xx/em28xx-cards.c	2012-03-19 21:31:23.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/em28xx/em28xx-cards.c	2012-03-19 21:33:30.000000000 -0400
@@ -60,7 +60,7 @@
 module_param_array(card,  int, NULL, 0444);
 MODULE_PARM_DESC(card,     "card type");
 
-/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
+/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS - 1 */
 static unsigned long em28xx_devused;
 
 struct em28xx_hash_table {
@@ -317,6 +317,25 @@
 };
 #endif
 
+/* 2013:024f PCTV DVB-S2 Stick 460e
+ * GPIO_0 - POWER_ON
+ * GPIO_1 - BOOST
+ * GPIO_2 - VUV_LNB (red LED)
+ * GPIO_3 - EXT_12V
+ * GPIO_4 - INT_DEM (DEMOD GPIO_0)
+ * GPIO_5 - INT_LNB
+ * GPIO_6 - RESET_DEM
+ * GPIO_7 - LED (green LED)
+ */
+static struct em28xx_reg_seq pctv_460e[] = {
+	{EM2874_R80_GPIO, 0x01, 0xff,  50},
+	{0x0d,            0xff, 0xff,  50},
+	{EM2874_R80_GPIO, 0x41, 0xff,  50}, /* GPIO_6=1 */
+	{0x0d,            0x42, 0xff,  50},
+	{EM2874_R80_GPIO, 0x61, 0xff,  50}, /* GPIO_5=1 */
+	{             -1,   -1,   -1,  -1},
+};
+
 /*
  *  Board definitions
  */
@@ -1810,6 +1829,17 @@
 		.has_dvb       = 1,
 		.ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
 	},
+	/* 2013:024f PCTV DVB-S2 Stick 460e
+	 * Empia EM28174, NXP TDA10071, Conexant CX24118A and Allegro A8293 */
+	[EM28174_BOARD_PCTV_460E] = {
+		.i2c_speed     = EM2874_I2C_SECONDARY_BUS_SELECT |
+			EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ,
+		.name          = "PCTV DVB-S2 Stick (460e)",
+		.tuner_type    = TUNER_ABSENT,
+		.tuner_gpio    = pctv_460e,
+		.has_dvb       = 1,
+		.ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
+	},
 };
 const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
 
@@ -1893,6 +1923,8 @@
 			.driver_info = EM2860_BOARD_TERRATEC_AV350 },
 	{ USB_DEVICE(0x0ccd, 0x0096),
 			.driver_info = EM2860_BOARD_TERRATEC_GRABBY },
+	{ USB_DEVICE(0x0ccd, 0x10AF),
+			.driver_info = EM2860_BOARD_TERRATEC_GRABBY },
 	{ USB_DEVICE(0x0fd9, 0x0033),
 			.driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE},
 	{ USB_DEVICE(0x185b, 0x2870),
@@ -1941,6 +1973,8 @@
 			.driver_info = EM2870_BOARD_KWORLD_A340 },
 	{ USB_DEVICE(0x2013, 0x024f),
 			.driver_info = EM28174_BOARD_PCTV_290E },
+	{ USB_DEVICE(0x2013, 0x024c),
+			.driver_info = EM28174_BOARD_PCTV_460E },
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, em28xx_id_table);
@@ -2768,9 +2802,9 @@
 #endif /* CONFIG_MODULES */
 
 /*
- * em28xx_realease_resources()
+ * em28xx_release_resources()
  * unregisters the v4l2,i2c and usb devices
- * called when the device gets disconected or at module unload
+ * called when the device gets disconnected or at module unload
 */
 void em28xx_release_resources(struct em28xx *dev)
 {
@@ -2784,8 +2818,6 @@
 
 	em28xx_release_analog_resources(dev);
 
-	em28xx_remove_from_devlist(dev);
-
 	em28xx_i2c_unregister(dev);
 
 	v4l2_device_unregister(&dev->v4l2_dev);
@@ -2793,7 +2825,7 @@
 	usb_put_dev(dev->udev);
 
 	/* Mark device as unused */
-	em28xx_devused &= ~(1 << dev->devno);
+	clear_bit(dev->devno, &em28xx_devused);
 };
 
 /*
@@ -2806,7 +2838,6 @@
 {
 	struct em28xx *dev = *devhandle;
 	int retval;
-	int errCode;
 
 	dev->udev = udev;
 	mutex_init(&dev->ctrl_urb_lock);
@@ -2883,10 +2914,9 @@
 	}
 
 	if (dev->is_audio_only) {
-		errCode = em28xx_audio_setup(dev);
-		if (errCode)
+		retval = em28xx_audio_setup(dev);
+		if (retval)
 			return -ENODEV;
-		em28xx_add_into_devlist(dev);
 		em28xx_init_extension(dev);
 
 		return 0;
@@ -2903,7 +2933,7 @@
 		/* Resets I2C speed */
 		em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
 		if (retval < 0) {
-			em28xx_errdev("%s: em28xx_write_regs_req failed!"
+			em28xx_errdev("%s: em28xx_write_reg failed!"
 				      " retval [%d]\n",
 				      __func__, retval);
 			return retval;
@@ -2917,12 +2947,11 @@
 	}
 
 	/* register i2c bus */
-	errCode = em28xx_i2c_register(dev);
-	if (errCode < 0) {
-		v4l2_device_unregister(&dev->v4l2_dev);
-		em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n",
-			__func__, errCode);
-		return errCode;
+	retval = em28xx_i2c_register(dev);
+	if (retval < 0) {
+		em28xx_errdev("%s: em28xx_i2c_register - error [%d]!\n",
+			__func__, retval);
+		goto unregister_dev;
 	}
 
 	/*
@@ -2936,11 +2965,11 @@
 	em28xx_card_setup(dev);
 
 	/* Configure audio */
-	errCode = em28xx_audio_setup(dev);
-	if (errCode < 0) {
-		v4l2_device_unregister(&dev->v4l2_dev);
-		em28xx_errdev("%s: Error while setting audio - errCode [%d]!\n",
-			__func__, errCode);
+	retval = em28xx_audio_setup(dev);
+	if (retval < 0) {
+		em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
+			__func__, retval);
+		goto fail;
 	}
 
 	/* wake i2c devices */
@@ -2954,41 +2983,41 @@
 
 	if (dev->board.has_msp34xx) {
 		/* Send a reset to other chips via gpio */
-		errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7);
-		if (errCode < 0) {
-			em28xx_errdev("%s: em28xx_write_regs_req - "
-				      "msp34xx(1) failed! errCode [%d]\n",
-				      __func__, errCode);
-			return errCode;
+		retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7);
+		if (retval < 0) {
+			em28xx_errdev("%s: em28xx_write_reg - "
+				      "msp34xx(1) failed! error [%d]\n",
+				      __func__, retval);
+			goto fail;
 		}
 		msleep(3);
 
-		errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
-		if (errCode < 0) {
-			em28xx_errdev("%s: em28xx_write_regs_req - "
-				      "msp34xx(2) failed! errCode [%d]\n",
-				      __func__, errCode);
-			return errCode;
+		retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
+		if (retval < 0) {
+			em28xx_errdev("%s: em28xx_write_reg - "
+				      "msp34xx(2) failed! error [%d]\n",
+				      __func__, retval);
+			goto fail;
 		}
 		msleep(3);
 	}
 
-	em28xx_add_into_devlist(dev);
-
 	retval = em28xx_register_analog_devices(dev);
 	if (retval < 0) {
-		em28xx_release_resources(dev);
-		goto fail_reg_devices;
+		goto fail;
 	}
 
-	em28xx_init_extension(dev);
-
 	/* Save some power by putting tuner to sleep */
 	v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
 
 	return 0;
 
-fail_reg_devices:
+fail:
+	em28xx_i2c_unregister(dev);
+
+unregister_dev:
+	v4l2_device_unregister(&dev->v4l2_dev);
+
 	return retval;
 }
 
@@ -3015,8 +3044,16 @@
 	udev = usb_get_dev(interface_to_usbdev(interface));
 
 	/* Check to see next free device and mark as used */
-	nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
-	em28xx_devused |= 1<<nr;
+	do {
+		nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
+		if (nr >= EM28XX_MAXBOARDS) {
+			/* No free device slots */
+			printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
+					EM28XX_MAXBOARDS);
+			retval = -ENOMEM;
+			goto err_no_slot;
+		}
+	} while (test_and_set_bit(nr, &em28xx_devused));
 
 	/* Don't register audio interfaces */
 	if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
@@ -3027,7 +3064,6 @@
 			ifnum,
 			interface->altsetting[0].desc.bInterfaceClass);
 
-		em28xx_devused &= ~(1<<nr);
 		retval = -ENODEV;
 		goto err;
 	}
@@ -3076,7 +3112,6 @@
 				em28xx_err(DRIVER_NAME " This is an anciliary "
 					"interface not used by the driver\n");
 
-				em28xx_devused &= ~(1<<nr);
 				retval = -ENODEV;
 				goto err;
 			}
@@ -3132,29 +3167,19 @@
 		printk(DRIVER_NAME ": Device initialization failed.\n");
 		printk(DRIVER_NAME ": Device must be connected to a high-speed"
 		       " USB 2.0 port.\n");
-		em28xx_devused &= ~(1<<nr);
 		retval = -ENODEV;
 		goto err;
 	}
 
-	if (nr >= EM28XX_MAXBOARDS) {
-		printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
-				EM28XX_MAXBOARDS);
-		em28xx_devused &= ~(1<<nr);
-		retval = -ENOMEM;
-		goto err;
-	}
-
 	/* allocate memory for our device state and initialize it */
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL) {
 		em28xx_err(DRIVER_NAME ": out of memory!\n");
-		em28xx_devused &= ~(1<<nr);
 		retval = -ENOMEM;
 		goto err;
 	}
 
-	snprintf(dev->name, 29, "em28xx #%d", nr);
+	snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr);
 	dev->devno = nr;
 	dev->model = id->driver_info;
 	dev->alt   = -1;
@@ -3177,7 +3202,6 @@
 
 	if (dev->alt_max_pkt_size == NULL) {
 		em28xx_errdev("out of memory!\n");
-		em28xx_devused &= ~(1<<nr);
 		kfree(dev);
 		retval = -ENOMEM;
 		goto err;
@@ -3204,8 +3228,8 @@
 	mutex_lock(&dev->lock);
 	retval = em28xx_init_dev(&dev, udev, interface, nr);
 	if (retval) {
-		em28xx_devused &= ~(1<<dev->devno);
 		mutex_unlock(&dev->lock);
+		kfree(dev->alt_max_pkt_size);
 		kfree(dev);
 		goto err;
 	}
@@ -3217,15 +3241,26 @@
 	 */
 	mutex_unlock(&dev->lock);
 
+	/*
+	 * These extensions can be modules. If the modules are already
+	 * loaded then we can initialise the device now, otherwise we
+	 * will initialise it when the modules load instead.
+	 */
+	em28xx_init_extension(dev);
+
 	return 0;
 
 err:
+	clear_bit(nr, &em28xx_devused);
+
+err_no_slot:
+	usb_put_dev(udev);
 	return retval;
 }
 
 /*
  * em28xx_usb_disconnect()
- * called when the device gets diconencted
+ * called when the device gets disconnected
  * video device will be unregistered on v4l2_close in case it is still open
  */
 static void em28xx_usb_disconnect(struct usb_interface *interface)
@@ -3273,10 +3308,10 @@
 		em28xx_release_resources(dev);
 	}
 
-	em28xx_close_extension(dev);
-
 	mutex_unlock(&dev->lock);
 
+	em28xx_close_extension(dev);
+
 	if (!dev->users) {
 		kfree(dev->alt_max_pkt_size);
 		kfree(dev);
diff -druN linux-libre-3.1-gnu/drivers/media/video/em28xx/em28xx-core.c linux-libre-3.2-gnu/drivers/media/video/em28xx/em28xx-core.c
--- linux-libre-3.1-gnu/drivers/media/video/em28xx/em28xx-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/em28xx/em28xx-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -1184,25 +1184,6 @@
 static DEFINE_MUTEX(em28xx_devlist_mutex);
 
 /*
- * em28xx_realease_resources()
- * unregisters the v4l2,i2c and usb devices
- * called when the device gets disconected or at module unload
-*/
-void em28xx_remove_from_devlist(struct em28xx *dev)
-{
-	mutex_lock(&em28xx_devlist_mutex);
-	list_del(&dev->devlist);
-	mutex_unlock(&em28xx_devlist_mutex);
-};
-
-void em28xx_add_into_devlist(struct em28xx *dev)
-{
-	mutex_lock(&em28xx_devlist_mutex);
-	list_add_tail(&dev->devlist, &em28xx_devlist);
-	mutex_unlock(&em28xx_devlist_mutex);
-};
-
-/*
  * Extension interface
  */
 
@@ -1217,8 +1198,8 @@
 	list_for_each_entry(dev, &em28xx_devlist, devlist) {
 		ops->init(dev);
 	}
-	printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
 	mutex_unlock(&em28xx_devlist_mutex);
+	printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
 	return 0;
 }
 EXPORT_SYMBOL(em28xx_register_extension);
@@ -1231,36 +1212,34 @@
 	list_for_each_entry(dev, &em28xx_devlist, devlist) {
 		ops->fini(dev);
 	}
-	printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
 	list_del(&ops->next);
 	mutex_unlock(&em28xx_devlist_mutex);
+	printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
 }
 EXPORT_SYMBOL(em28xx_unregister_extension);
 
 void em28xx_init_extension(struct em28xx *dev)
 {
-	struct em28xx_ops *ops = NULL;
+	const struct em28xx_ops *ops = NULL;
 
 	mutex_lock(&em28xx_devlist_mutex);
-	if (!list_empty(&em28xx_extension_devlist)) {
-		list_for_each_entry(ops, &em28xx_extension_devlist, next) {
-			if (ops->init)
-				ops->init(dev);
-		}
+	list_add_tail(&dev->devlist, &em28xx_devlist);
+	list_for_each_entry(ops, &em28xx_extension_devlist, next) {
+		if (ops->init)
+			ops->init(dev);
 	}
 	mutex_unlock(&em28xx_devlist_mutex);
 }
 
 void em28xx_close_extension(struct em28xx *dev)
 {
-	struct em28xx_ops *ops = NULL;
+	const struct em28xx_ops *ops = NULL;
 
 	mutex_lock(&em28xx_devlist_mutex);
-	if (!list_empty(&em28xx_extension_devlist)) {
-		list_for_each_entry(ops, &em28xx_extension_devlist, next) {
-			if (ops->fini)
-				ops->fini(dev);
-		}
+	list_for_each_entry(ops, &em28xx_extension_devlist, next) {
+		if (ops->fini)
+			ops->fini(dev);
 	}
+	list_del(&dev->devlist);
 	mutex_unlock(&em28xx_devlist_mutex);
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/em28xx/em28xx-dvb.c linux-libre-3.2-gnu/drivers/media/video/em28xx/em28xx-dvb.c
--- linux-libre-3.1-gnu/drivers/media/video/em28xx/em28xx-dvb.c	2012-03-19 21:39:03.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/em28xx/em28xx-dvb.c	2012-03-19 21:41:43.000000000 -0400
@@ -42,6 +42,8 @@
 #include "cxd2820r.h"
 #include "tda18271c2dd.h"
 #include "drxk.h"
+#include "tda10071.h"
+#include "a8293.h"
 
 MODULE_DESCRIPTION("driver for em28xx based DVB cards");
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -122,7 +124,7 @@
 	}
 }
 
-static inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
+static inline int em28xx_dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
 {
 	int i;
 
@@ -155,7 +157,7 @@
 	return 0;
 }
 
-static int start_streaming(struct em28xx_dvb *dvb)
+static int em28xx_start_streaming(struct em28xx_dvb *dvb)
 {
 	int rc;
 	struct em28xx *dev = dvb->adapter.priv;
@@ -175,10 +177,10 @@
 
 	return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS,
 				EM28XX_DVB_NUM_BUFS, max_dvb_packet_size,
-				dvb_isoc_copy);
+				em28xx_dvb_isoc_copy);
 }
 
-static int stop_streaming(struct em28xx_dvb *dvb)
+static int em28xx_stop_streaming(struct em28xx_dvb *dvb)
 {
 	struct em28xx *dev = dvb->adapter.priv;
 
@@ -189,7 +191,7 @@
 	return 0;
 }
 
-static int start_feed(struct dvb_demux_feed *feed)
+static int em28xx_start_feed(struct dvb_demux_feed *feed)
 {
 	struct dvb_demux *demux  = feed->demux;
 	struct em28xx_dvb *dvb = demux->priv;
@@ -203,7 +205,7 @@
 	rc = dvb->nfeeds;
 
 	if (dvb->nfeeds == 1) {
-		ret = start_streaming(dvb);
+		ret = em28xx_start_streaming(dvb);
 		if (ret < 0)
 			rc = ret;
 	}
@@ -212,7 +214,7 @@
 	return rc;
 }
 
-static int stop_feed(struct dvb_demux_feed *feed)
+static int em28xx_stop_feed(struct dvb_demux_feed *feed)
 {
 	struct dvb_demux *demux  = feed->demux;
 	struct em28xx_dvb *dvb = demux->priv;
@@ -222,7 +224,7 @@
 	dvb->nfeeds--;
 
 	if (0 == dvb->nfeeds)
-		err = stop_streaming(dvb);
+		err = em28xx_stop_streaming(dvb);
 
 	mutex_unlock(&dvb->lock);
 	return err;
@@ -380,7 +382,7 @@
 	em28xx_gpio_set(dev, terratec_h5_end);
 };
 
-static int mt352_terratec_xs_init(struct dvb_frontend *fe)
+static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe)
 {
 	/* Values extracted from a USB trace of the Terratec Windows driver */
 	static u8 clock_config[]   = { CLOCK_CTL,  0x38, 0x2c };
@@ -412,7 +414,7 @@
 	.demod_address = (0x1e >> 1),
 	.no_tuner = 1,
 	.if2 = 45600,
-	.demod_init = mt352_terratec_xs_init,
+	.demod_init = em28xx_mt352_terratec_xs_init,
 };
 
 static struct tda10023_config em28xx_tda10023_config = {
@@ -438,11 +440,25 @@
 
 static struct tda18271_config em28xx_cxd2820r_tda18271_config = {
 	.output_opt = TDA18271_OUTPUT_LT_OFF,
+	.gate = TDA18271_GATE_DIGITAL,
+};
+
+static const struct tda10071_config em28xx_tda10071_config = {
+	.i2c_address = 0x55, /* (0xaa >> 1) */
+	.i2c_wr_max = 64,
+	.ts_mode = TDA10071_TS_SERIAL,
+	.spec_inv = 0,
+	.xtal = 40444000, /* 40.444 MHz */
+	.pll_multiplier = 20,
+};
+
+static const struct a8293_config em28xx_a8293_config = {
+	.i2c_addr = 0x08, /* (0x10 >> 1) */
 };
 
 /* ------------------------------------------------------------------ */
 
-static int attach_xc3028(u8 addr, struct em28xx *dev)
+static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
 {
 	struct dvb_frontend *fe;
 	struct xc2028_config cfg;
@@ -472,10 +488,8 @@
 
 /* ------------------------------------------------------------------ */
 
-static int register_dvb(struct em28xx_dvb *dvb,
-		 struct module *module,
-		 struct em28xx *dev,
-		 struct device *device)
+static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module,
+			       struct em28xx *dev, struct device *device)
 {
 	int result;
 
@@ -522,8 +536,8 @@
 	dvb->demux.priv       = dvb;
 	dvb->demux.filternum  = 256;
 	dvb->demux.feednum    = 256;
-	dvb->demux.start_feed = start_feed;
-	dvb->demux.stop_feed  = stop_feed;
+	dvb->demux.start_feed = em28xx_start_feed;
+	dvb->demux.stop_feed  = em28xx_stop_feed;
 
 	result = dvb_dmx_init(&dvb->demux);
 	if (result < 0) {
@@ -591,7 +605,7 @@
 	return result;
 }
 
-static void unregister_dvb(struct em28xx_dvb *dvb)
+static void em28xx_unregister_dvb(struct em28xx_dvb *dvb)
 {
 	dvb_net_release(&dvb->net);
 	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
@@ -607,9 +621,9 @@
 	dvb_unregister_adapter(&dvb->adapter);
 }
 
-static int dvb_init(struct em28xx *dev)
+static int em28xx_dvb_init(struct em28xx *dev)
 {
-	int result = 0;
+	int result = 0, mfe_shared = 0;
 	struct em28xx_dvb *dvb;
 
 	if (!dev->board.has_dvb) {
@@ -648,7 +662,7 @@
 		dvb->fe[0] = dvb_attach(lgdt330x_attach,
 					   &em2880_lgdt3303_dev,
 					   &dev->i2c_adap);
-		if (attach_xc3028(0x61, dev) < 0) {
+		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -657,7 +671,7 @@
 		dvb->fe[0] = dvb_attach(zl10353_attach,
 					   &em28xx_zl10353_with_xc3028,
 					   &dev->i2c_adap);
-		if (attach_xc3028(0x61, dev) < 0) {
+		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -668,7 +682,7 @@
 		dvb->fe[0] = dvb_attach(zl10353_attach,
 					   &em28xx_zl10353_xc3028_no_i2c_gate,
 					   &dev->i2c_adap);
-		if (attach_xc3028(0x61, dev) < 0) {
+		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -689,7 +703,7 @@
 						   &dev->i2c_adap);
 		}
 
-		if (attach_xc3028(0x61, dev) < 0) {
+		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -699,7 +713,7 @@
 		dvb->fe[0] = dvb_attach(s5h1409_attach,
 					   &em28xx_s5h1409_with_xc3028,
 					   &dev->i2c_adap);
-		if (attach_xc3028(0x61, dev) < 0) {
+		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -720,7 +734,7 @@
 	case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
 		dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL,
 					   &dev->i2c_adap, &dev->udev->dev);
-		if (attach_xc3028(0x61, dev) < 0) {
+		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -753,11 +767,9 @@
 		dvb->fe[0] = dvb_attach(cxd2820r_attach,
 			&em28xx_cxd2820r_config, &dev->i2c_adap, NULL);
 		if (dvb->fe[0]) {
-			struct i2c_adapter *i2c_tuner;
-			i2c_tuner = cxd2820r_get_tuner_i2c_adapter(dvb->fe[0]);
 			/* FE 0 attach tuner */
 			if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
-				i2c_tuner, &em28xx_cxd2820r_tda18271_config)) {
+				&dev->i2c_adap, &em28xx_cxd2820r_tda18271_config)) {
 				dvb_frontend_detach(dvb->fe[0]);
 				result = -EINVAL;
 				goto out_free;
@@ -768,10 +780,12 @@
 			dvb->fe[1]->id = 1;
 			/* FE 1 attach tuner */
 			if (!dvb_attach(tda18271_attach, dvb->fe[1], 0x60,
-				i2c_tuner, &em28xx_cxd2820r_tda18271_config)) {
+				&dev->i2c_adap, &em28xx_cxd2820r_tda18271_config)) {
 				dvb_frontend_detach(dvb->fe[1]);
 				/* leave FE 0 still active */
 			}
+
+			mfe_shared = 1;
 		}
 		break;
 	case EM2884_BOARD_TERRATEC_H5:
@@ -809,6 +823,16 @@
 		       sizeof(dvb->fe[0]->ops.tuner_ops));
 
 		break;
+	case EM28174_BOARD_PCTV_460E:
+		/* attach demod */
+		dvb->fe[0] = dvb_attach(tda10071_attach,
+			&em28xx_tda10071_config, &dev->i2c_adap);
+
+		/* attach SEC */
+		if (dvb->fe[0])
+			dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap,
+				&em28xx_a8293_config);
+		break;
 	default:
 		em28xx_errdev("/2: The frontend of your DVB/ATSC card"
 				" isn't supported yet\n");
@@ -823,11 +847,14 @@
 	dvb->fe[0]->callback = em28xx_tuner_callback;
 
 	/* register everything */
-	result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
+	result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
 
 	if (result < 0)
 		goto out_free;
 
+	/* MFE lock */
+	dvb->adapter.mfe_shared = mfe_shared;
+
 	em28xx_info("Successfully loaded em28xx-dvb\n");
 ret:
 	em28xx_set_mode(dev, EM28XX_SUSPEND);
@@ -840,7 +867,14 @@
 	goto ret;
 }
 
-static int dvb_fini(struct em28xx *dev)
+static inline void prevent_sleep(struct dvb_frontend_ops *ops)
+{
+	ops->set_voltage = NULL;
+	ops->sleep = NULL;
+	ops->tuner_ops.sleep = NULL;
+}
+
+static int em28xx_dvb_fini(struct em28xx *dev)
 {
 	if (!dev->board.has_dvb) {
 		/* This device does not support the extension */
@@ -848,8 +882,19 @@
 	}
 
 	if (dev->dvb) {
-		unregister_dvb(dev->dvb);
-		kfree(dev->dvb);
+		struct em28xx_dvb *dvb = dev->dvb;
+
+		if (dev->state & DEV_DISCONNECTED) {
+			/* We cannot tell the device to sleep
+			 * once it has been unplugged. */
+			if (dvb->fe[0])
+				prevent_sleep(&dvb->fe[0]->ops);
+			if (dvb->fe[1])
+				prevent_sleep(&dvb->fe[1]->ops);
+		}
+
+		em28xx_unregister_dvb(dvb);
+		kfree(dvb);
 		dev->dvb = NULL;
 	}
 
@@ -859,8 +904,8 @@
 static struct em28xx_ops dvb_ops = {
 	.id   = EM28XX_DVB,
 	.name = "Em28xx dvb Extension",
-	.init = dvb_init,
-	.fini = dvb_fini,
+	.init = em28xx_dvb_init,
+	.fini = em28xx_dvb_fini,
 };
 
 static int __init em28xx_dvb_register(void)
diff -druN linux-libre-3.1-gnu/drivers/media/video/em28xx/em28xx.h linux-libre-3.2-gnu/drivers/media/video/em28xx/em28xx.h
--- linux-libre-3.1-gnu/drivers/media/video/em28xx/em28xx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/em28xx/em28xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -120,6 +120,7 @@
 #define EM2874_BOARD_LEADERSHIP_ISDBT		  77
 #define EM28174_BOARD_PCTV_290E                   78
 #define EM2884_BOARD_TERRATEC_H5		  79
+#define EM28174_BOARD_PCTV_460E                   80
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
@@ -677,8 +678,6 @@
 int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
 int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
 void em28xx_wake_i2c(struct em28xx *dev);
-void em28xx_remove_from_devlist(struct em28xx *dev);
-void em28xx_add_into_devlist(struct em28xx *dev);
 int em28xx_register_extension(struct em28xx_ops *dev);
 void em28xx_unregister_extension(struct em28xx_ops *dev);
 void em28xx_init_extension(struct em28xx *dev);
diff -druN linux-libre-3.1-gnu/drivers/media/video/em28xx/em28xx-input.c linux-libre-3.2-gnu/drivers/media/video/em28xx/em28xx-input.c
--- linux-libre-3.1-gnu/drivers/media/video/em28xx/em28xx-input.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/em28xx/em28xx-input.c	2012-01-04 18:55:44.000000000 -0500
@@ -463,11 +463,11 @@
 	if (!ir)
 		return 0;
 
-	em28xx_ir_stop(ir->rc);
-	rc_unregister_device(ir->rc);
-	kfree(ir);
+	if (ir->rc)
+		rc_unregister_device(ir->rc);
 
 	/* done */
+	kfree(ir);
 	dev->ir = NULL;
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/em28xx/em28xx-video.c linux-libre-3.2-gnu/drivers/media/video/em28xx/em28xx-video.c
--- linux-libre-3.1-gnu/drivers/media/video/em28xx/em28xx-video.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/em28xx/em28xx-video.c	2012-01-04 18:55:44.000000000 -0500
@@ -1156,6 +1156,21 @@
 	return 0;
 }
 
+static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
+{
+	struct em28xx_fh   *fh  = priv;
+	struct em28xx      *dev = fh->dev;
+	int                rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm);
+
+	return 0;
+}
+
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
 {
 	struct em28xx_fh   *fh  = priv;
@@ -1787,6 +1802,45 @@
 	return 0;
 }
 
+static int vidioc_enum_framesizes(struct file *file, void *priv,
+				  struct v4l2_frmsizeenum *fsize)
+{
+	struct em28xx_fh      *fh  = priv;
+	struct em28xx         *dev = fh->dev;
+	struct em28xx_fmt     *fmt;
+	unsigned int	      maxw = norm_maxw(dev);
+	unsigned int	      maxh = norm_maxh(dev);
+
+	fmt = format_by_fourcc(fsize->pixel_format);
+	if (!fmt) {
+		em28xx_videodbg("Fourcc format (%08x) invalid.\n",
+				fsize->pixel_format);
+		return -EINVAL;
+	}
+
+	if (dev->board.is_em2800) {
+		if (fsize->index > 1)
+			return -EINVAL;
+		fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+		fsize->discrete.width = maxw / (1 + fsize->index);
+		fsize->discrete.height = maxh / (1 + fsize->index);
+		return 0;
+	}
+
+	if (fsize->index != 0)
+		return -EINVAL;
+
+	/* Report a continuous range */
+	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+	fsize->stepwise.min_width = 48;
+	fsize->stepwise.min_height = 32;
+	fsize->stepwise.max_width = maxw;
+	fsize->stepwise.max_height = maxh;
+	fsize->stepwise.step_width = 1;
+	fsize->stepwise.step_height = 1;
+	return 0;
+}
+
 /* Sliced VBI ioctls */
 static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
 					struct v4l2_format *f)
@@ -2200,6 +2254,7 @@
 		   free the remaining resources */
 		if (dev->state & DEV_DISCONNECTED) {
 			em28xx_release_resources(dev);
+			kfree(dev->alt_max_pkt_size);
 			kfree(dev);
 			return 0;
 		}
@@ -2340,10 +2395,10 @@
 	.vidioc_s_fmt_vid_cap       = vidioc_s_fmt_vid_cap,
 	.vidioc_g_fmt_vbi_cap       = vidioc_g_fmt_vbi_cap,
 	.vidioc_s_fmt_vbi_cap       = vidioc_s_fmt_vbi_cap,
+	.vidioc_enum_framesizes     = vidioc_enum_framesizes,
 	.vidioc_g_audio             = vidioc_g_audio,
 	.vidioc_s_audio             = vidioc_s_audio,
 	.vidioc_cropcap             = vidioc_cropcap,
-
 	.vidioc_g_fmt_sliced_vbi_cap   = vidioc_g_fmt_sliced_vbi_cap,
 	.vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
 	.vidioc_s_fmt_sliced_vbi_cap   = vidioc_try_set_sliced_vbi_cap,
@@ -2353,6 +2408,7 @@
 	.vidioc_qbuf                = vidioc_qbuf,
 	.vidioc_dqbuf               = vidioc_dqbuf,
 	.vidioc_g_std               = vidioc_g_std,
+	.vidioc_querystd            = vidioc_querystd,
 	.vidioc_s_std               = vidioc_s_std,
 	.vidioc_g_parm		    = vidioc_g_parm,
 	.vidioc_s_parm		    = vidioc_s_parm,
diff -druN linux-libre-3.1-gnu/drivers/media/video/em28xx/Kconfig linux-libre-3.2-gnu/drivers/media/video/em28xx/Kconfig
--- linux-libre-3.1-gnu/drivers/media/video/em28xx/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/em28xx/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -41,6 +41,8 @@
 	select DVB_CXD2820R if !DVB_FE_CUSTOMISE
 	select DVB_DRXK if !DVB_FE_CUSTOMISE
 	select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
+	select DVB_TDA10071 if !DVB_FE_CUSTOMISE
+	select DVB_A8293 if !DVB_FE_CUSTOMISE
 	select VIDEOBUF_DVB
 	---help---
 	  This adds support for DVB cards based on the
diff -druN linux-libre-3.1-gnu/drivers/media/video/em28xx/Makefile linux-libre-3.2-gnu/drivers/media/video/em28xx/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/em28xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/em28xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -9,8 +9,8 @@
 obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o
 obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/et61x251/et61x251_core.c linux-libre-3.2-gnu/drivers/media/video/et61x251/et61x251_core.c
--- linux-libre-3.1-gnu/drivers/media/video/et61x251/et61x251_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/et61x251/et61x251_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
  ***************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff -druN linux-libre-3.1-gnu/drivers/media/video/et61x251/et61x251.h linux-libre-3.2-gnu/drivers/media/video/et61x251/et61x251.h
--- linux-libre-3.1-gnu/drivers/media/video/et61x251/et61x251.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/et61x251/et61x251.h	2012-01-04 18:55:44.000000000 -0500
@@ -165,45 +165,49 @@
 #undef DBG
 #undef KDBG
 #ifdef ET61X251_DEBUG
-#	define DBG(level, fmt, args...)                                       \
-do {                                                                          \
-	if (debug >= (level)) {                                               \
-		if ((level) == 1)                                             \
-			dev_err(&cam->usbdev->dev, fmt "\n", ## args);        \
-		else if ((level) == 2)                                        \
-			dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \
-		else if ((level) >= 3)                                        \
-			dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n",   \
-				 __FILE__, __func__, __LINE__ , ## args); \
-	}                                                                     \
+#define DBG(level, fmt, ...)						\
+do {									\
+	if (debug >= (level)) {						\
+		if ((level) == 1)					\
+			dev_err(&cam->usbdev->dev, fmt "\n",		\
+				##__VA_ARGS__);				\
+		else if ((level) == 2)					\
+			dev_info(&cam->usbdev->dev, fmt "\n",		\
+				 ##__VA_ARGS__);			\
+		else if ((level) >= 3)					\
+			dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \
+				 __FILE__, __func__, __LINE__,		\
+				 ##__VA_ARGS__);			\
+	}								\
 } while (0)
-#	define KDBG(level, fmt, args...)                                      \
-do {                                                                          \
-	if (debug >= (level)) {                                               \
-		if ((level) == 1 || (level) == 2)                             \
-			pr_info("et61x251: " fmt "\n", ## args);              \
-		else if ((level) == 3)                                        \
-			pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__,   \
-				 __func__, __LINE__ , ## args);           \
-	}                                                                     \
+#define KDBG(level, fmt, ...)						\
+do {									\
+	if (debug >= (level)) {						\
+		if ((level) == 1 || (level) == 2)			\
+			pr_info(fmt "\n", ##__VA_ARGS__);		\
+		else if ((level) == 3)					\
+			pr_debug("[%s:%s:%d] " fmt "\n",		\
+				 __FILE__,  __func__, __LINE__,		\
+				 ##__VA_ARGS__);			\
+	}								\
 } while (0)
-#	define V4LDBG(level, name, cmd)                                       \
-do {                                                                          \
-	if (debug >= (level))                                                 \
-		v4l_print_ioctl(name, cmd);                                   \
+#define V4LDBG(level, name, cmd)					\
+do {									\
+	if (debug >= (level))						\
+		v4l_print_ioctl(name, cmd);				\
 } while (0)
 #else
-#	define DBG(level, fmt, args...) do {;} while(0)
-#	define KDBG(level, fmt, args...) do {;} while(0)
-#	define V4LDBG(level, name, cmd) do {;} while(0)
+#define DBG(level, fmt, ...) do {;} while(0)
+#define KDBG(level, fmt, ...) do {;} while(0)
+#define V4LDBG(level, name, cmd) do {;} while(0)
 #endif
 
 #undef PDBG
-#define PDBG(fmt, args...)                                                    \
-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__,   \
-	 __LINE__ , ## args)
+#define PDBG(fmt, ...)							\
+	dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n",		\
+		 __FILE__, __func__, __LINE__, ##__VA_ARGS__)
 
 #undef PDBGG
-#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
+#define PDBGG(fmt, args...) do {;} while (0) /* placeholder */
 
 #endif /* _ET61X251_H_ */
diff -druN linux-libre-3.1-gnu/drivers/media/video/et61x251/et61x251_tas5130d1b.c linux-libre-3.2-gnu/drivers/media/video/et61x251/et61x251_tas5130d1b.c
--- linux-libre-3.1-gnu/drivers/media/video/et61x251/et61x251_tas5130d1b.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/et61x251/et61x251_tas5130d1b.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
  ***************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "et61x251_sensor.h"
 
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/benq.c linux-libre-3.2-gnu/drivers/media/video/gspca/benq.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/benq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/benq.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "benq"
 
 #include "gspca.h"
@@ -62,7 +64,7 @@
 			0,
 			500);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -84,20 +86,6 @@
 	return 0;
 }
 
-static int sd_isoc_init(struct gspca_dev *gspca_dev)
-{
-	int ret;
-
-	ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface,
-		gspca_dev->nbalt - 1);
-	if (ret < 0) {
-		err("usb_set_interface failed");
-		return ret;
-	}
-/*	reg_w(gspca_dev, 0x0003, 0x0002); */
-	return 0;
-}
-
 /* -- start the camera -- */
 static int sd_start(struct gspca_dev *gspca_dev)
 {
@@ -113,7 +101,7 @@
 	for (n = 0; n < 4; n++) {
 		urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
 		if (!urb) {
-			err("usb_alloc_urb failed");
+			pr_err("usb_alloc_urb failed\n");
 			return -ENOMEM;
 		}
 		gspca_dev->urb[n] = urb;
@@ -123,7 +111,7 @@
 						&urb->transfer_dma);
 
 		if (urb->transfer_buffer == NULL) {
-			err("usb_alloc_coherent failed");
+			pr_err("usb_alloc_coherent failed\n");
 			return -ENOMEM;
 		}
 		urb->dev = gspca_dev->dev;
@@ -181,7 +169,7 @@
 		if (gspca_dev->frozen)
 			return;
 #endif
-		err("urb status: %d", urb->status);
+		pr_err("urb status: %d\n", urb->status);
 		return;
 	}
 
@@ -209,7 +197,7 @@
 		if (st == 0)
 			st = urb->iso_frame_desc[i].status;
 		if (st) {
-			err("ISOC data error: [%d] status=%d",
+			pr_err("ISOC data error: [%d] status=%d\n",
 				i, st);
 			gspca_dev->last_packet_type = DISCARD_PACKET;
 			continue;
@@ -256,10 +244,10 @@
 	/* resubmit the URBs */
 	st = usb_submit_urb(urb0, GFP_ATOMIC);
 	if (st < 0)
-		err("usb_submit_urb(0) ret %d", st);
+		pr_err("usb_submit_urb(0) ret %d\n", st);
 	st = usb_submit_urb(urb, GFP_ATOMIC);
 	if (st < 0)
-		err("usb_submit_urb() ret %d", st);
+		pr_err("usb_submit_urb() ret %d\n", st);
 }
 
 /* sub-driver description */
@@ -269,7 +257,6 @@
 	.nctrls = ARRAY_SIZE(sd_ctrls),
 	.config = sd_config,
 	.init = sd_init,
-	.isoc_init = sd_isoc_init,
 	.start = sd_start,
 	.stopN = sd_stopN,
 	.pkt_scan = sd_pkt_scan,
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/conex.c linux-libre-3.2-gnu/drivers/media/video/gspca/conex.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/conex.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/conex.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "conex"
 
 #include "gspca.h"
@@ -129,7 +131,7 @@
 
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		err("reg_r: buffer overflow");
+		pr_err("reg_r: buffer overflow\n");
 		return;
 	}
 #endif
@@ -169,7 +171,7 @@
 
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		err("reg_w: buffer overflow");
+		pr_err("reg_w: buffer overflow\n");
 		return;
 	}
 	PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/cpia1.c linux-libre-3.2-gnu/drivers/media/video/gspca/cpia1.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/cpia1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/cpia1.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "cpia1"
 
 #include <linux/input.h>
@@ -550,8 +552,7 @@
 			      gspca_dev->usb_buf, databytes, 1000);
 
 	if (ret < 0)
-		err("usb_control_msg %02x, error %d", command[1],
-		       ret);
+		pr_err("usb_control_msg %02x, error %d\n", command[1], ret);
 
 	if (ret == -EPIPE && retries > 0) {
 		retries--;
@@ -1279,7 +1280,7 @@
 	cmd[7] = 0;
 	ret = cpia_usb_transferCmd(gspca_dev, cmd);
 	if (ret) {
-		err("ReadVPRegs(30,4,9,8) - failed: %d", ret);
+		pr_err("ReadVPRegs(30,4,9,8) - failed: %d\n", ret);
 		return;
 	}
 	exp_acc = gspca_dev->usb_buf[0];
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/etoms.c linux-libre-3.2-gnu/drivers/media/video/gspca/etoms.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/etoms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/etoms.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "etoms"
 
 #include "gspca.h"
@@ -236,7 +238,7 @@
 
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		err("reg_r: buffer overflow");
+		pr_err("reg_r: buffer overflow\n");
 		return;
 	}
 #endif
@@ -274,7 +276,7 @@
 
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		err("reg_w: buffer overflow");
+		pr_err("reg_w: buffer overflow\n");
 		return;
 	}
 	PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/finepix.c linux-libre-3.2-gnu/drivers/media/video/gspca/finepix.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/finepix.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/finepix.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "finepix"
 
 #include "gspca.h"
@@ -182,7 +184,7 @@
 	/* Init the device */
 	ret = command(gspca_dev, 0);
 	if (ret < 0) {
-		err("init failed %d", ret);
+		pr_err("init failed %d\n", ret);
 		return ret;
 	}
 
@@ -194,14 +196,14 @@
 			FPIX_MAX_TRANSFER, &len,
 			FPIX_TIMEOUT);
 	if (ret < 0) {
-		err("usb_bulk_msg failed %d", ret);
+		pr_err("usb_bulk_msg failed %d\n", ret);
 		return ret;
 	}
 
 	/* Request a frame, but don't read it */
 	ret = command(gspca_dev, 1);
 	if (ret < 0) {
-		err("frame request failed %d", ret);
+		pr_err("frame request failed %d\n", ret);
 		return ret;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/gl860/gl860.c linux-libre-3.2-gnu/drivers/media/video/gspca/gl860/gl860.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/gl860/gl860.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/gl860/gl860.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,9 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "gspca.h"
 #include "gl860.h"
 
@@ -572,9 +575,8 @@
 	}
 
 	if (r < 0)
-		err("ctrl transfer failed %4d "
-			"[p%02x r%d v%04x i%04x len%d]",
-			r, pref, req, val, index, len);
+		pr_err("ctrl transfer failed %4d [p%02x r%d v%04x i%04x len%d]\n",
+		       r, pref, req, val, index, len);
 	else if (len > 1 && r < len)
 		PDEBUG(D_ERR, "short ctrl transfer %d/%d", r, len);
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/gl860/Makefile linux-libre-3.2-gnu/drivers/media/video/gspca/gl860/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/gspca/gl860/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/gl860/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -6,5 +6,5 @@
 		    gl860-ov9655.o \
 		    gl860-mi2020.o
 
-EXTRA_CFLAGS += -Idrivers/media/video/gspca
+ccflags-y += -Idrivers/media/video/gspca
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/gspca.c linux-libre-3.2-gnu/drivers/media/video/gspca/gspca.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/gspca.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/gspca.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,9 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define MODULE_NAME "gspca"
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define GSPCA_VERSION	"2.14.0"
 
 #include <linux/init.h>
 #include <linux/fs.h>
@@ -50,12 +52,10 @@
 #error "DEF_NURBS too big"
 #endif
 
-#define DRIVER_VERSION_NUMBER	"2.13.0"
-
 MODULE_AUTHOR("Jean-FranÃ§ois Moine <http://moinejf.free.fr>");
 MODULE_DESCRIPTION("GSPCA USB Camera Driver");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(DRIVER_VERSION_NUMBER);
+MODULE_VERSION(GSPCA_VERSION);
 
 #ifdef GSPCA_DEBUG
 int gspca_debug = D_ERR | D_PROBE;
@@ -148,7 +148,7 @@
 	if (ret == 0) {
 		ret = usb_submit_urb(urb, GFP_ATOMIC);
 		if (ret < 0)
-			err("Resubmit URB failed with error %i", ret);
+			pr_err("Resubmit URB failed with error %i\n", ret);
 	}
 }
 
@@ -177,8 +177,8 @@
 
 		err = input_register_device(input_dev);
 		if (err) {
-			err("Input device registration failed with error %i",
-				err);
+			pr_err("Input device registration failed with error %i\n",
+			       err);
 			input_dev->dev.parent = NULL;
 			input_free_device(input_dev);
 		} else {
@@ -323,8 +323,8 @@
 		/* check the packet status and length */
 		st = urb->iso_frame_desc[i].status;
 		if (st) {
-			err("ISOC data error: [%d] len=%d, status=%d",
-				i, len, st);
+			pr_err("ISOC data error: [%d] len=%d, status=%d\n",
+			       i, len, st);
 			gspca_dev->last_packet_type = DISCARD_PACKET;
 			continue;
 		}
@@ -346,7 +346,7 @@
 	/* resubmit the URB */
 	st = usb_submit_urb(urb, GFP_ATOMIC);
 	if (st < 0)
-		err("usb_submit_urb() ret %d", st);
+		pr_err("usb_submit_urb() ret %d\n", st);
 }
 
 /*
@@ -400,7 +400,7 @@
 	if (gspca_dev->cam.bulk_nurbs != 0) {
 		st = usb_submit_urb(urb, GFP_ATOMIC);
 		if (st < 0)
-			err("usb_submit_urb() ret %d", st);
+			pr_err("usb_submit_urb() ret %d\n", st);
 	}
 }
 
@@ -464,7 +464,7 @@
 		} else {
 /* !! image is NULL only when last pkt is LAST or DISCARD
 			if (gspca_dev->image == NULL) {
-				err("gspca_frame_add() image == NULL");
+				pr_err("gspca_frame_add() image == NULL\n");
 				return;
 			}
  */
@@ -497,19 +497,6 @@
 }
 EXPORT_SYMBOL(gspca_frame_add);
 
-static int gspca_is_compressed(__u32 format)
-{
-	switch (format) {
-	case V4L2_PIX_FMT_MJPEG:
-	case V4L2_PIX_FMT_JPEG:
-	case V4L2_PIX_FMT_SPCA561:
-	case V4L2_PIX_FMT_PAC207:
-	case V4L2_PIX_FMT_MR97310A:
-		return 1;
-	}
-	return 0;
-}
-
 static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file,
 			enum v4l2_memory memory, unsigned int count)
 {
@@ -525,7 +512,7 @@
 		count = GSPCA_MAX_FRAMES - 1;
 	gspca_dev->frbuf = vmalloc_32(frsz * count);
 	if (!gspca_dev->frbuf) {
-		err("frame alloc failed");
+		pr_err("frame alloc failed\n");
 		return -ENOMEM;
 	}
 	gspca_dev->capt_file = file;
@@ -597,7 +584,7 @@
 		return 0;
 	ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
 	if (ret < 0)
-		err("set alt 0 err %d", ret);
+		pr_err("set alt 0 err %d\n", ret);
 	return ret;
 }
 
@@ -640,53 +627,104 @@
 	return NULL;
 }
 
+/* compute the minimum bandwidth for the current transfer */
+static u32 which_bandwidth(struct gspca_dev *gspca_dev)
+{
+	u32 bandwidth;
+	int i;
+
+	i = gspca_dev->curr_mode;
+	bandwidth = gspca_dev->cam.cam_mode[i].sizeimage;
+
+	/* if the image is compressed, estimate the mean image size */
+	if (bandwidth < gspca_dev->cam.cam_mode[i].width *
+				gspca_dev->cam.cam_mode[i].height)
+		bandwidth /= 3;
+
+	/* estimate the frame rate */
+	if (gspca_dev->sd_desc->get_streamparm) {
+		struct v4l2_streamparm parm;
+
+		parm.parm.capture.timeperframe.denominator = 15;
+		gspca_dev->sd_desc->get_streamparm(gspca_dev, &parm);
+		bandwidth *= parm.parm.capture.timeperframe.denominator;
+	} else {
+		bandwidth *= 15;		/* 15 fps */
+	}
+
+	PDEBUG(D_STREAM, "min bandwidth: %d", bandwidth);
+	return bandwidth;
+}
+
+/* endpoint table */
+#define MAX_ALT 16
+struct ep_tb_s {
+	u32 alt;
+	u32 bandwidth;
+};
+
 /*
- * look for an input (isoc or bulk) endpoint
- *
- * The endpoint is defined by the subdriver.
- * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep).
- * This routine may be called many times when the bandwidth is too small
- * (the bandwidth is checked on urb submit).
+ * build the table of the endpoints
+ * and compute the minimum bandwidth for the image transfer
  */
-static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev)
+static int build_ep_tb(struct gspca_dev *gspca_dev,
+			struct usb_interface *intf,
+			int xfer,
+			struct ep_tb_s *ep_tb)
 {
-	struct usb_interface *intf;
 	struct usb_host_endpoint *ep;
-	int xfer, i, ret;
+	int i, j, nbalt, psize, found;
+	u32 bandwidth, last_bw;
 
-	intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
-	ep = NULL;
-	xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
-				   : USB_ENDPOINT_XFER_ISOC;
-	i = gspca_dev->alt;			/* previous alt setting */
-	if (gspca_dev->cam.reverse_alts) {
-		while (++i < gspca_dev->nbalt) {
-			ep = alt_xfer(&intf->altsetting[i], xfer);
-			if (ep)
-				break;
-		}
-	} else {
-		while (--i >= 0) {
-			ep = alt_xfer(&intf->altsetting[i], xfer);
-			if (ep)
-				break;
+	nbalt = intf->num_altsetting;
+	if (nbalt > MAX_ALT)
+		nbalt = MAX_ALT;	/* fixme: should warn */
+
+	/* build the endpoint table */
+	i = 0;
+	last_bw = 0;
+	for (;;) {
+		ep_tb->bandwidth = 2000 * 2000 * 120;
+		found = 0;
+		for (j = 0; j < nbalt; j++) {
+			ep = alt_xfer(&intf->altsetting[j], xfer);
+			if (ep == NULL)
+				continue;
+			psize = le16_to_cpu(ep->desc.wMaxPacketSize);
+			if (!gspca_dev->cam.bulk)		/* isoc */
+				psize = (psize & 0x07ff) *
+						(1 + ((psize >> 11) & 3));
+			bandwidth = psize * ep->desc.bInterval * 1000;
+			if (gspca_dev->dev->speed == USB_SPEED_HIGH
+			 || gspca_dev->dev->speed == USB_SPEED_SUPER)
+				bandwidth *= 8;
+			if (bandwidth <= last_bw)
+				continue;
+			if (bandwidth < ep_tb->bandwidth) {
+				ep_tb->bandwidth = bandwidth;
+				ep_tb->alt = j;
+				found = 1;
+			}
 		}
+		if (!found)
+			break;
+		PDEBUG(D_STREAM, "alt %d bandwidth %d",
+				ep_tb->alt, ep_tb->bandwidth);
+		last_bw = ep_tb->bandwidth;
+		i++;
+		ep_tb++;
 	}
-	if (ep == NULL) {
-		err("no transfer endpoint found");
-		return NULL;
-	}
-	PDEBUG(D_STREAM, "use alt %d ep 0x%02x",
-			i, ep->desc.bEndpointAddress);
-	gspca_dev->alt = i;		/* memorize the current alt setting */
-	if (gspca_dev->nbalt > 1) {
-		ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
-		if (ret < 0) {
-			err("set alt %d err %d", i, ret);
-			ep = NULL;
-		}
+
+	/* get the requested bandwidth and start at the highest atlsetting */
+	bandwidth = which_bandwidth(gspca_dev);
+	ep_tb--;
+	while (i > 1) {
+		ep_tb--;
+		if (ep_tb->bandwidth < bandwidth)
+			break;
+		i--;
 	}
-	return ep;
+	return i;
 }
 
 /*
@@ -731,7 +769,7 @@
 	for (n = 0; n < nurbs; n++) {
 		urb = usb_alloc_urb(npkt, GFP_KERNEL);
 		if (!urb) {
-			err("usb_alloc_urb failed");
+			pr_err("usb_alloc_urb failed\n");
 			return -ENOMEM;
 		}
 		gspca_dev->urb[n] = urb;
@@ -741,7 +779,7 @@
 						&urb->transfer_dma);
 
 		if (urb->transfer_buffer == NULL) {
-			err("usb_alloc_coherent failed");
+			pr_err("usb_alloc_coherent failed\n");
 			return -ENOMEM;
 		}
 		urb->dev = gspca_dev->dev;
@@ -752,7 +790,10 @@
 						    ep->desc.bEndpointAddress);
 			urb->transfer_flags = URB_ISO_ASAP
 					| URB_NO_TRANSFER_DMA_MAP;
-			urb->interval = ep->desc.bInterval;
+			if (gspca_dev->dev->speed == USB_SPEED_LOW)
+				urb->interval = ep->desc.bInterval;
+			else
+				urb->interval = 1 << (ep->desc.bInterval - 1);
 			urb->complete = isoc_irq;
 			urb->number_of_packets = npkt;
 			for (i = 0; i < npkt; i++) {
@@ -774,9 +815,11 @@
  */
 static int gspca_init_transfer(struct gspca_dev *gspca_dev)
 {
+	struct usb_interface *intf;
 	struct usb_host_endpoint *ep;
 	struct urb *urb;
-	int n, ret;
+	struct ep_tb_s ep_tb[MAX_ALT];
+	int n, ret, xfer, alt, alt_idx;
 
 	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 		return -ERESTARTSYS;
@@ -794,30 +837,65 @@
 
 	gspca_dev->usb_err = 0;
 
-	/* set the higher alternate setting and
-	 * loop until urb submit succeeds */
-	if (gspca_dev->cam.reverse_alts)
-		gspca_dev->alt = 0;
-	else
-		gspca_dev->alt = gspca_dev->nbalt;
-
+	/* do the specific subdriver stuff before endpoint selection */
+	intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
+	gspca_dev->alt = gspca_dev->cam.bulk ? intf->num_altsetting : 0;
 	if (gspca_dev->sd_desc->isoc_init) {
 		ret = gspca_dev->sd_desc->isoc_init(gspca_dev);
 		if (ret < 0)
 			goto unlock;
 	}
+	xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
+				   : USB_ENDPOINT_XFER_ISOC;
 
-	gspca_input_destroy_urb(gspca_dev);
-	ep = get_ep(gspca_dev);
-	if (ep == NULL) {
-		ret = -EIO;
-		goto out;
+	/* if the subdriver forced an altsetting, get the endpoint */
+	if (gspca_dev->alt != 0) {
+		gspca_dev->alt--;	/* (previous version compatibility) */
+		ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer);
+		if (ep == NULL) {
+			pr_err("bad altsetting %d\n", gspca_dev->alt);
+			ret = -EIO;
+			goto out;
+		}
+		ep_tb[0].alt = gspca_dev->alt;
+		alt_idx = 1;
+	} else {
+
+	/* else, compute the minimum bandwidth
+	 * and build the endpoint table */
+		alt_idx = build_ep_tb(gspca_dev, intf, xfer, ep_tb);
+		if (alt_idx <= 0) {
+			pr_err("no transfer endpoint found\n");
+			ret = -EIO;
+			goto unlock;
+		}
 	}
+
+	/* set the highest alternate setting and
+	 * loop until urb submit succeeds */
+	gspca_input_destroy_urb(gspca_dev);
+
+	gspca_dev->alt = ep_tb[--alt_idx].alt;
+	alt = -1;
 	for (;;) {
+		if (alt != gspca_dev->alt) {
+			alt = gspca_dev->alt;
+			if (gspca_dev->nbalt > 1) {
+				ret = usb_set_interface(gspca_dev->dev,
+							gspca_dev->iface,
+							alt);
+				if (ret < 0) {
+					if (ret == -ENOSPC)
+						goto retry; /*fixme: ugly*/
+					pr_err("set alt %d err %d\n", alt, ret);
+					goto out;
+				}
+			}
+		}
 		if (!gspca_dev->cam.no_urb_create) {
-			PDEBUG(D_STREAM, "init transfer alt %d",
-				gspca_dev->alt);
-			ret = create_urbs(gspca_dev, ep);
+			PDEBUG(D_STREAM, "init transfer alt %d", alt);
+			ret = create_urbs(gspca_dev,
+				alt_xfer(&intf->altsetting[alt], xfer));
 			if (ret < 0) {
 				destroy_urbs(gspca_dev);
 				goto out;
@@ -851,29 +929,35 @@
 				break;
 		}
 		if (ret >= 0)
-			break;
+			break;			/* transfer is started */
+
+		/* something when wrong
+		 * stop the webcam and free the transfer resources */
 		gspca_stream_off(gspca_dev);
 		if (ret != -ENOSPC) {
-			err("usb_submit_urb alt %d err %d",
-				gspca_dev->alt, ret);
+			pr_err("usb_submit_urb alt %d err %d\n",
+			       gspca_dev->alt, ret);
 			goto out;
 		}
 
 		/* the bandwidth is not wide enough
 		 * negotiate or try a lower alternate setting */
+retry:
 		PDEBUG(D_ERR|D_STREAM,
-			"bandwidth not wide enough - trying again");
+			"alt %d - bandwidth not wide enough - trying again",
+			alt);
 		msleep(20);	/* wait for kill complete */
 		if (gspca_dev->sd_desc->isoc_nego) {
 			ret = gspca_dev->sd_desc->isoc_nego(gspca_dev);
 			if (ret < 0)
 				goto out;
 		} else {
-			ep = get_ep(gspca_dev);
-			if (ep == NULL) {
+			if (alt_idx <= 0) {
+				pr_err("no transfer endpoint found\n");
 				ret = -EIO;
 				goto out;
 			}
+			gspca_dev->alt = ep_tb[--alt_idx].alt;
 		}
 	}
 out:
@@ -1044,7 +1128,9 @@
 		return -EINVAL;		/* no more format */
 
 	fmtdesc->pixelformat = fmt_tb[index];
-	if (gspca_is_compressed(fmt_tb[index]))
+	if (gspca_dev->cam.cam_mode[i].sizeimage <
+			gspca_dev->cam.cam_mode[i].width *
+				gspca_dev->cam.cam_mode[i].height)
 		fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
 	fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
 	fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
@@ -2195,19 +2281,20 @@
 	struct usb_device *dev = interface_to_usbdev(intf);
 	int ret;
 
-	PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct);
+	pr_info("%s-" GSPCA_VERSION " probing %04x:%04x\n",
+		sd_desc->name, id->idVendor, id->idProduct);
 
 	/* create the device */
 	if (dev_size < sizeof *gspca_dev)
 		dev_size = sizeof *gspca_dev;
 	gspca_dev = kzalloc(dev_size, GFP_KERNEL);
 	if (!gspca_dev) {
-		err("couldn't kzalloc gspca struct");
+		pr_err("couldn't kzalloc gspca struct\n");
 		return -ENOMEM;
 	}
 	gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL);
 	if (!gspca_dev->usb_buf) {
-		err("out of memory");
+		pr_err("out of memory\n");
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -2264,7 +2351,7 @@
 				  VFL_TYPE_GRABBER,
 				  -1);
 	if (ret < 0) {
-		err("video_register_device err %d", ret);
+		pr_err("video_register_device err %d\n", ret);
 		goto out;
 	}
 
@@ -2296,8 +2383,8 @@
 
 	/* we don't handle multi-config cameras */
 	if (dev->descriptor.bNumConfigurations != 1) {
-		err("%04x:%04x too many config",
-				id->idVendor, id->idProduct);
+		pr_err("%04x:%04x too many config\n",
+		       id->idVendor, id->idProduct);
 		return -ENODEV;
 	}
 
@@ -2480,7 +2567,7 @@
 /* -- module insert / remove -- */
 static int __init gspca_init(void)
 {
-	info("v" DRIVER_VERSION_NUMBER " registered");
+	pr_info("v" GSPCA_VERSION " registered\n");
 	return 0;
 }
 static void __exit gspca_exit(void)
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/gspca.h linux-libre-3.2-gnu/drivers/media/video/gspca/gspca.h
--- linux-libre-3.1-gnu/drivers/media/video/gspca/gspca.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/gspca.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,11 +14,12 @@
 #ifdef GSPCA_DEBUG
 /* GSPCA our debug messages */
 extern int gspca_debug;
-#define PDEBUG(level, fmt, args...) \
-	do {\
-		if (gspca_debug & (level)) \
-			printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args); \
-	} while (0)
+#define PDEBUG(level, fmt, ...)					\
+do {								\
+	if (gspca_debug & (level))				\
+		pr_info(fmt, ##__VA_ARGS__);			\
+} while (0)
+
 #define D_ERR  0x01
 #define D_PROBE 0x02
 #define D_CONF 0x04
@@ -29,17 +30,8 @@
 #define D_USBO 0x00
 #define D_V4L2 0x0100
 #else
-#define PDEBUG(level, fmt, args...)
+#define PDEBUG(level, fmt, ...)
 #endif
-#undef err
-#define err(fmt, args...) \
-	printk(KERN_ERR MODULE_NAME ": " fmt "\n", ## args)
-#undef info
-#define info(fmt, args...) \
-	printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args)
-#undef warn
-#define warn(fmt, args...) \
-	printk(KERN_WARNING MODULE_NAME ": " fmt "\n", ## args)
 
 #define GSPCA_MAX_FRAMES 16	/* maximum number of video frame buffers */
 /* image transfers */
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/jeilinj.c linux-libre-3.2-gnu/drivers/media/video/gspca/jeilinj.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/jeilinj.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/jeilinj.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "jeilinj"
 
 #include <linux/slab.h>
@@ -113,8 +115,8 @@
 			usb_sndbulkpipe(gspca_dev->dev, 3),
 			gspca_dev->usb_buf, 2, NULL, 500);
 	if (retval < 0) {
-		err("command write [%02x] error %d",
-				gspca_dev->usb_buf[0], retval);
+		pr_err("command write [%02x] error %d\n",
+		       gspca_dev->usb_buf[0], retval);
 		gspca_dev->usb_err = retval;
 	}
 }
@@ -131,8 +133,8 @@
 				gspca_dev->usb_buf, 1, NULL, 500);
 	response = gspca_dev->usb_buf[0];
 	if (retval < 0) {
-		err("read command [%02x] error %d",
-				gspca_dev->usb_buf[0], retval);
+		pr_err("read command [%02x] error %d\n",
+		       gspca_dev->usb_buf[0], retval);
 		gspca_dev->usb_err = retval;
 	}
 }
@@ -403,13 +405,7 @@
 	dev->type = id->driver_info;
 	gspca_dev->cam.ctrls = dev->ctrls;
 	dev->quality = QUALITY_DEF;
-	dev->ctrls[LIGHTFREQ].def = V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
-	dev->ctrls[RED].def = RED_BALANCE_DEF;
-	dev->ctrls[GREEN].def = GREEN_BALANCE_DEF;
-	dev->ctrls[BLUE].def = BLUE_BALANCE_DEF;
-	PDEBUG(D_PROBE,
-		"JEILINJ camera detected"
-		" (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+
 	cam->cam_mode = jlj_mode;
 	cam->nmodes = ARRAY_SIZE(jlj_mode);
 	cam->bulk = 1;
@@ -422,7 +418,7 @@
 {
 	int i;
 	u8 *buf;
-	u8 stop_commands[][2] = {
+	static u8 stop_commands[][2] = {
 		{0x71, 0x00},
 		{0x70, 0x09},
 		{0x71, 0x80},
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/Kconfig linux-libre-3.2-gnu/drivers/media/video/gspca/Kconfig
--- linux-libre-3.1-gnu/drivers/media/video/gspca/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -356,6 +356,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called gspca_t613.
 
+config USB_GSPCA_TOPRO
+	tristate "TOPRO USB Camera Driver"
+	depends on VIDEO_V4L2 && USB_GSPCA
+	help
+	  Say Y here if you want support for cameras based on the
+	  TP6800 and TP6810 Topro chips.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gspca_topro.
+
 config USB_GSPCA_TV8532
 	tristate "TV8532 USB Camera Driver"
 	depends on VIDEO_V4L2 && USB_GSPCA
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/kinect.c linux-libre-3.2-gnu/drivers/media/video/gspca/kinect.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/kinect.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/kinect.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "kinect"
 
 #include "gspca.h"
@@ -34,11 +36,6 @@
 MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver");
 MODULE_LICENSE("GPL");
 
-#ifdef GSPCA_DEBUG
-int gspca_debug = D_ERR | D_PROBE | D_CONF | D_STREAM | D_FRAM | D_PACK |
-	D_USBI | D_USBO | D_V4L2;
-#endif
-
 struct pkt_hdr {
 	uint8_t magic[2];
 	uint8_t pad;
@@ -141,7 +138,7 @@
 	struct cam_hdr *rhdr = (void *)ibuf;
 
 	if (cmd_len & 1 || cmd_len > (0x400 - sizeof(*chdr))) {
-		err("send_cmd: Invalid command length (0x%x)", cmd_len);
+		pr_err("send_cmd: Invalid command length (0x%x)\n", cmd_len);
 		return -1;
 	}
 
@@ -157,7 +154,7 @@
 	PDEBUG(D_USBO, "Control cmd=%04x tag=%04x len=%04x: %d", cmd,
 		sd->cam_tag, cmd_len, res);
 	if (res < 0) {
-		err("send_cmd: Output control transfer failed (%d)", res);
+		pr_err("send_cmd: Output control transfer failed (%d)\n", res);
 		return res;
 	}
 
@@ -166,33 +163,35 @@
 	} while (actual_len == 0);
 	PDEBUG(D_USBO, "Control reply: %d", res);
 	if (actual_len < sizeof(*rhdr)) {
-		err("send_cmd: Input control transfer failed (%d)", res);
+		pr_err("send_cmd: Input control transfer failed (%d)\n", res);
 		return res;
 	}
 	actual_len -= sizeof(*rhdr);
 
 	if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) {
-		err("send_cmd: Bad magic %02x %02x", rhdr->magic[0],
-			rhdr->magic[1]);
+		pr_err("send_cmd: Bad magic %02x %02x\n",
+		       rhdr->magic[0], rhdr->magic[1]);
 		return -1;
 	}
 	if (rhdr->cmd != chdr->cmd) {
-		err("send_cmd: Bad cmd %02x != %02x", rhdr->cmd, chdr->cmd);
+		pr_err("send_cmd: Bad cmd %02x != %02x\n",
+		       rhdr->cmd, chdr->cmd);
 		return -1;
 	}
 	if (rhdr->tag != chdr->tag) {
-		err("send_cmd: Bad tag %04x != %04x", rhdr->tag, chdr->tag);
+		pr_err("send_cmd: Bad tag %04x != %04x\n",
+		       rhdr->tag, chdr->tag);
 		return -1;
 	}
 	if (cpu_to_le16(rhdr->len) != (actual_len/2)) {
-		err("send_cmd: Bad len %04x != %04x",
-				cpu_to_le16(rhdr->len), (int)(actual_len/2));
+		pr_err("send_cmd: Bad len %04x != %04x\n",
+		       cpu_to_le16(rhdr->len), (int)(actual_len/2));
 		return -1;
 	}
 
 	if (actual_len > reply_len) {
-		warn("send_cmd: Data buffer is %d bytes long, but got %d bytes",
-				reply_len, actual_len);
+		pr_warn("send_cmd: Data buffer is %d bytes long, but got %d bytes\n",
+			reply_len, actual_len);
 		memcpy(replybuf, ibuf+sizeof(*rhdr), reply_len);
 	} else {
 		memcpy(replybuf, ibuf+sizeof(*rhdr), actual_len);
@@ -218,8 +217,8 @@
 	if (res < 0)
 		return res;
 	if (res != 2) {
-		warn("send_cmd returned %d [%04x %04x], 0000 expected",
-				res, reply[0], reply[1]);
+		pr_warn("send_cmd returned %d [%04x %04x], 0000 expected\n",
+			res, reply[0], reply[1]);
 	}
 	return 0;
 }
@@ -353,8 +352,8 @@
 		return;
 
 	if (hdr->magic[0] != 'R' || hdr->magic[1] != 'B') {
-		warn("[Stream %02x] Invalid magic %02x%02x", sd->stream_flag,
-				hdr->magic[0], hdr->magic[1]);
+		pr_warn("[Stream %02x] Invalid magic %02x%02x\n",
+			sd->stream_flag, hdr->magic[0], hdr->magic[1]);
 		return;
 	}
 
@@ -368,7 +367,7 @@
 		gspca_frame_add(gspca_dev, LAST_PACKET, data, datalen);
 
 	else
-		warn("Packet type not recognized...");
+		pr_warn("Packet type not recognized...\n");
 }
 
 /* sub-driver description */
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/konica.c linux-libre-3.2-gnu/drivers/media/video/gspca/konica.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/konica.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/konica.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "konica"
 
 #include <linux/input.h>
@@ -200,7 +202,7 @@
 			0,
 			1000);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -221,7 +223,7 @@
 			2,
 			1000);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -284,7 +286,7 @@
 	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
 	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
 	if (!alt) {
-		err("Couldn't get altsetting");
+		pr_err("Couldn't get altsetting\n");
 		return -EIO;
 	}
 
@@ -315,7 +317,7 @@
 			le16_to_cpu(alt->endpoint[i].desc.wMaxPacketSize);
 		urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
 		if (!urb) {
-			err("usb_alloc_urb failed");
+			pr_err("usb_alloc_urb failed\n");
 			return -ENOMEM;
 		}
 		gspca_dev->urb[n] = urb;
@@ -324,7 +326,7 @@
 						GFP_KERNEL,
 						&urb->transfer_dma);
 		if (urb->transfer_buffer == NULL) {
-			err("usb_buffer_alloc failed");
+			pr_err("usb_buffer_alloc failed\n");
 			return -ENOMEM;
 		}
 
@@ -386,7 +388,7 @@
 		PDEBUG(D_ERR, "urb status: %d", urb->status);
 		st = usb_submit_urb(urb, GFP_ATOMIC);
 		if (st < 0)
-			err("resubmit urb error %d", st);
+			pr_err("resubmit urb error %d\n", st);
 		return;
 	}
 
@@ -477,7 +479,7 @@
 	}
 	st = usb_submit_urb(status_urb, GFP_ATOMIC);
 	if (st < 0)
-		err("usb_submit_urb(status_urb) ret %d", st);
+		pr_err("usb_submit_urb(status_urb) ret %d\n", st);
 }
 
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/m5602/m5602_core.c linux-libre-3.2-gnu/drivers/media/video/gspca/m5602/m5602_core.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/m5602/m5602_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/m5602/m5602_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "m5602_ov9650.h"
 #include "m5602_ov7660.h"
 #include "m5602_mt9m111.h"
@@ -192,10 +194,9 @@
 	for (i = 0; i < 0x80; i++) {
 		unsigned char val = 0;
 		m5602_read_bridge(sd, i, &val);
-		info("ALi m5602 address 0x%x contains 0x%x", i, val);
+		pr_info("ALi m5602 address 0x%x contains 0x%x\n", i, val);
 	}
-	info("Warning: The ALi m5602 webcam probably won't work "
-		"until it's power cycled");
+	pr_info("Warning: The ALi m5602 webcam probably won't work until it's power cycled\n");
 }
 
 static int m5602_probe_sensor(struct sd *sd)
@@ -231,7 +232,7 @@
 		return 0;
 
 	/* More sensor probe function goes here */
-	info("Failed to find a sensor");
+	pr_info("Failed to find a sensor\n");
 	sd->sensor = NULL;
 	return -ENODEV;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/m5602/m5602_mt9m111.c linux-libre-3.2-gnu/drivers/media/video/gspca/m5602/m5602_mt9m111.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/m5602/m5602_mt9m111.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/m5602/m5602_mt9m111.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "m5602_mt9m111.h"
 
 static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
@@ -163,7 +165,7 @@
 
 	if (force_sensor) {
 		if (force_sensor == MT9M111_SENSOR) {
-			info("Forcing a %s sensor", mt9m111.name);
+			pr_info("Forcing a %s sensor\n", mt9m111.name);
 			goto sensor_found;
 		}
 		/* If we want to force another sensor, don't try to probe this
@@ -191,7 +193,7 @@
 		return -ENODEV;
 
 	if ((data[0] == 0x14) && (data[1] == 0x3a)) {
-		info("Detected a mt9m111 sensor");
+		pr_info("Detected a mt9m111 sensor\n");
 		goto sensor_found;
 	}
 
@@ -612,34 +614,34 @@
 {
 	u8 address, value[2] = {0x00, 0x00};
 
-	info("Dumping the mt9m111 register state");
+	pr_info("Dumping the mt9m111 register state\n");
 
-	info("Dumping the mt9m111 sensor core registers");
+	pr_info("Dumping the mt9m111 sensor core registers\n");
 	value[1] = MT9M111_SENSOR_CORE;
 	m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
 	for (address = 0; address < 0xff; address++) {
 		m5602_read_sensor(sd, address, value, 2);
-		info("register 0x%x contains 0x%x%x",
-		     address, value[0], value[1]);
+		pr_info("register 0x%x contains 0x%x%x\n",
+			address, value[0], value[1]);
 	}
 
-	info("Dumping the mt9m111 color pipeline registers");
+	pr_info("Dumping the mt9m111 color pipeline registers\n");
 	value[1] = MT9M111_COLORPIPE;
 	m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
 	for (address = 0; address < 0xff; address++) {
 		m5602_read_sensor(sd, address, value, 2);
-		info("register 0x%x contains 0x%x%x",
-		     address, value[0], value[1]);
+		pr_info("register 0x%x contains 0x%x%x\n",
+			address, value[0], value[1]);
 	}
 
-	info("Dumping the mt9m111 camera control registers");
+	pr_info("Dumping the mt9m111 camera control registers\n");
 	value[1] = MT9M111_CAMERA_CONTROL;
 	m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
 	for (address = 0; address < 0xff; address++) {
 		m5602_read_sensor(sd, address, value, 2);
-		info("register 0x%x contains 0x%x%x",
-		     address, value[0], value[1]);
+		pr_info("register 0x%x contains 0x%x%x\n",
+			address, value[0], value[1]);
 	}
 
-	info("mt9m111 register state dump complete");
+	pr_info("mt9m111 register state dump complete\n");
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/m5602/m5602_ov7660.c linux-libre-3.2-gnu/drivers/media/video/gspca/m5602/m5602_ov7660.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/m5602/m5602_ov7660.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/m5602/m5602_ov7660.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "m5602_ov7660.h"
 
 static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
@@ -149,7 +151,7 @@
 
 	if (force_sensor) {
 		if (force_sensor == OV7660_SENSOR) {
-			info("Forcing an %s sensor", ov7660.name);
+			pr_info("Forcing an %s sensor\n", ov7660.name);
 			goto sensor_found;
 		}
 		/* If we want to force another sensor,
@@ -180,10 +182,10 @@
 	if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1))
 		return -ENODEV;
 
-	info("Sensor reported 0x%x%x", prod_id, ver_id);
+	pr_info("Sensor reported 0x%x%x\n", prod_id, ver_id);
 
 	if ((prod_id == 0x76) && (ver_id == 0x60)) {
-		info("Detected a ov7660 sensor");
+		pr_info("Detected a ov7660 sensor\n");
 		goto sensor_found;
 	}
 	return -ENODEV;
@@ -457,17 +459,16 @@
 static void ov7660_dump_registers(struct sd *sd)
 {
 	int address;
-	info("Dumping the ov7660 register state");
+	pr_info("Dumping the ov7660 register state\n");
 	for (address = 0; address < 0xa9; address++) {
 		u8 value;
 		m5602_read_sensor(sd, address, &value, 1);
-		info("register 0x%x contains 0x%x",
-		     address, value);
+		pr_info("register 0x%x contains 0x%x\n", address, value);
 	}
 
-	info("ov7660 register state dump complete");
+	pr_info("ov7660 register state dump complete\n");
 
-	info("Probing for which registers that are read/write");
+	pr_info("Probing for which registers that are read/write\n");
 	for (address = 0; address < 0xff; address++) {
 		u8 old_value, ctrl_value;
 		u8 test_value[2] = {0xff, 0xff};
@@ -477,9 +478,9 @@
 		m5602_read_sensor(sd, address, &ctrl_value, 1);
 
 		if (ctrl_value == test_value[0])
-			info("register 0x%x is writeable", address);
+			pr_info("register 0x%x is writeable\n", address);
 		else
-			info("register 0x%x is read only", address);
+			pr_info("register 0x%x is read only\n", address);
 
 		/* Restore original value */
 		m5602_write_sensor(sd, address, &old_value, 1);
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/m5602/m5602_ov9650.c linux-libre-3.2-gnu/drivers/media/video/gspca/m5602/m5602_ov9650.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/m5602/m5602_ov9650.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/m5602/m5602_ov9650.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "m5602_ov9650.h"
 
 static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
@@ -299,7 +301,7 @@
 
 	if (force_sensor) {
 		if (force_sensor == OV9650_SENSOR) {
-			info("Forcing an %s sensor", ov9650.name);
+			pr_info("Forcing an %s sensor\n", ov9650.name);
 			goto sensor_found;
 		}
 		/* If we want to force another sensor,
@@ -330,7 +332,7 @@
 		return -ENODEV;
 
 	if ((prod_id == 0x96) && (ver_id == 0x52)) {
-		info("Detected an ov9650 sensor");
+		pr_info("Detected an ov9650 sensor\n");
 		goto sensor_found;
 	}
 	return -ENODEV;
@@ -850,17 +852,16 @@
 static void ov9650_dump_registers(struct sd *sd)
 {
 	int address;
-	info("Dumping the ov9650 register state");
+	pr_info("Dumping the ov9650 register state\n");
 	for (address = 0; address < 0xa9; address++) {
 		u8 value;
 		m5602_read_sensor(sd, address, &value, 1);
-		info("register 0x%x contains 0x%x",
-		     address, value);
+		pr_info("register 0x%x contains 0x%x\n", address, value);
 	}
 
-	info("ov9650 register state dump complete");
+	pr_info("ov9650 register state dump complete\n");
 
-	info("Probing for which registers that are read/write");
+	pr_info("Probing for which registers that are read/write\n");
 	for (address = 0; address < 0xff; address++) {
 		u8 old_value, ctrl_value;
 		u8 test_value[2] = {0xff, 0xff};
@@ -870,9 +871,9 @@
 		m5602_read_sensor(sd, address, &ctrl_value, 1);
 
 		if (ctrl_value == test_value[0])
-			info("register 0x%x is writeable", address);
+			pr_info("register 0x%x is writeable\n", address);
 		else
-			info("register 0x%x is read only", address);
+			pr_info("register 0x%x is read only\n", address);
 
 		/* Restore original value */
 		m5602_write_sensor(sd, address, &old_value, 1);
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/m5602/m5602_po1030.c linux-libre-3.2-gnu/drivers/media/video/gspca/m5602/m5602_po1030.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/m5602/m5602_po1030.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/m5602/m5602_po1030.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "m5602_po1030.h"
 
 static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
@@ -197,7 +199,7 @@
 
 	if (force_sensor) {
 		if (force_sensor == PO1030_SENSOR) {
-			info("Forcing a %s sensor", po1030.name);
+			pr_info("Forcing a %s sensor\n", po1030.name);
 			goto sensor_found;
 		}
 		/* If we want to force another sensor, don't try to probe this
@@ -221,7 +223,7 @@
 		return -ENODEV;
 
 	if (dev_id_h == 0x30) {
-		info("Detected a po1030 sensor");
+		pr_info("Detected a po1030 sensor\n");
 		goto sensor_found;
 	}
 	return -ENODEV;
@@ -267,7 +269,7 @@
 			break;
 
 		default:
-			info("Invalid stream command, exiting init");
+			pr_info("Invalid stream command, exiting init\n");
 			return -EINVAL;
 		}
 	}
@@ -733,16 +735,15 @@
 	int address;
 	u8 value = 0;
 
-	info("Dumping the po1030 sensor core registers");
+	pr_info("Dumping the po1030 sensor core registers\n");
 	for (address = 0; address < 0x7f; address++) {
 		m5602_read_sensor(sd, address, &value, 1);
-		info("register 0x%x contains 0x%x",
-		     address, value);
+		pr_info("register 0x%x contains 0x%x\n", address, value);
 	}
 
-	info("po1030 register state dump complete");
+	pr_info("po1030 register state dump complete\n");
 
-	info("Probing for which registers that are read/write");
+	pr_info("Probing for which registers that are read/write\n");
 	for (address = 0; address < 0xff; address++) {
 		u8 old_value, ctrl_value;
 		u8 test_value[2] = {0xff, 0xff};
@@ -752,9 +753,9 @@
 		m5602_read_sensor(sd, address, &ctrl_value, 1);
 
 		if (ctrl_value == test_value[0])
-			info("register 0x%x is writeable", address);
+			pr_info("register 0x%x is writeable\n", address);
 		else
-			info("register 0x%x is read only", address);
+			pr_info("register 0x%x is read only\n", address);
 
 		/* Restore original value */
 		m5602_write_sensor(sd, address, &old_value, 1);
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/m5602/m5602_s5k4aa.c linux-libre-3.2-gnu/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/m5602/m5602_s5k4aa.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/m5602/m5602_s5k4aa.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "m5602_s5k4aa.h"
 
 static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
@@ -240,7 +242,7 @@
 
 	if (force_sensor) {
 		if (force_sensor == S5K4AA_SENSOR) {
-			info("Forcing a %s sensor", s5k4aa.name);
+			pr_info("Forcing a %s sensor\n", s5k4aa.name);
 			goto sensor_found;
 		}
 		/* If we want to force another sensor, don't try to probe this
@@ -276,7 +278,7 @@
 						  data, 2);
 			break;
 		default:
-			info("Invalid stream command, exiting init");
+			pr_info("Invalid stream command, exiting init\n");
 			return -EINVAL;
 		}
 	}
@@ -292,7 +294,7 @@
 	if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
 		return -ENODEV;
 	else
-		info("Detected a s5k4aa sensor");
+		pr_info("Detected a s5k4aa sensor\n");
 
 sensor_found:
 	sensor_settings = kmalloc(
@@ -347,7 +349,7 @@
 			break;
 
 			default:
-				err("Invalid stream command, exiting init");
+				pr_err("Invalid stream command, exiting init\n");
 				return -EINVAL;
 			}
 		}
@@ -383,7 +385,7 @@
 			break;
 
 			default:
-				err("Invalid stream command, exiting init");
+				pr_err("Invalid stream command, exiting init\n");
 				return -EINVAL;
 			}
 		}
@@ -447,7 +449,7 @@
 				init_s5k4aa[i][1], data, 2);
 			break;
 		default:
-			info("Invalid stream command, exiting init");
+			pr_info("Invalid stream command, exiting init\n");
 			return -EINVAL;
 		}
 	}
@@ -686,20 +688,21 @@
 	m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
 	for (page = 0; page < 16; page++) {
 		m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
-		info("Dumping the s5k4aa register state for page 0x%x", page);
+		pr_info("Dumping the s5k4aa register state for page 0x%x\n",
+			page);
 		for (address = 0; address <= 0xff; address++) {
 			u8 value = 0;
 			m5602_read_sensor(sd, address, &value, 1);
-			info("register 0x%x contains 0x%x",
-			     address, value);
+			pr_info("register 0x%x contains 0x%x\n",
+				address, value);
 		}
 	}
-	info("s5k4aa register state dump complete");
+	pr_info("s5k4aa register state dump complete\n");
 
 	for (page = 0; page < 16; page++) {
 		m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
-		info("Probing for which registers that are "
-		     "read/write for page 0x%x", page);
+		pr_info("Probing for which registers that are read/write for page 0x%x\n",
+			page);
 		for (address = 0; address <= 0xff; address++) {
 			u8 old_value, ctrl_value, test_value = 0xff;
 
@@ -708,14 +711,16 @@
 			m5602_read_sensor(sd, address, &ctrl_value, 1);
 
 			if (ctrl_value == test_value)
-				info("register 0x%x is writeable", address);
+				pr_info("register 0x%x is writeable\n",
+					address);
 			else
-				info("register 0x%x is read only", address);
+				pr_info("register 0x%x is read only\n",
+					address);
 
 			/* Restore original value */
 			m5602_write_sensor(sd, address, &old_value, 1);
 		}
 	}
-	info("Read/write register probing complete");
+	pr_info("Read/write register probing complete\n");
 	m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/m5602/m5602_s5k83a.c linux-libre-3.2-gnu/drivers/media/video/gspca/m5602/m5602_s5k83a.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/m5602/m5602_s5k83a.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/m5602/m5602_s5k83a.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kthread.h>
 #include "m5602_s5k83a.h"
 
@@ -135,7 +137,7 @@
 
 	if (force_sensor) {
 		if (force_sensor == S5K83A_SENSOR) {
-			info("Forcing a %s sensor", s5k83a.name);
+			pr_info("Forcing a %s sensor\n", s5k83a.name);
 			goto sensor_found;
 		}
 		/* If we want to force another sensor, don't try to probe this
@@ -168,7 +170,7 @@
 	if ((prod_id == 0xff) || (ver_id == 0xff))
 		return -ENODEV;
 	else
-		info("Detected a s5k83a sensor");
+		pr_info("Detected a s5k83a sensor\n");
 
 sensor_found:
 	sens_priv = kmalloc(
@@ -227,7 +229,7 @@
 				init_s5k83a[i][1], data, 2);
 			break;
 		default:
-			info("Invalid stream command, exiting init");
+			pr_info("Invalid stream command, exiting init\n");
 			return -EINVAL;
 		}
 	}
@@ -273,7 +275,7 @@
 		s5k83a_get_rotation(sd, &reg);
 		if (previous_rotation != reg) {
 			previous_rotation = reg;
-			info("Camera was flipped");
+			pr_info("Camera was flipped\n");
 
 			s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
 			s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
@@ -566,20 +568,20 @@
 
 	for (page = 0; page < 16; page++) {
 		m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
-		info("Dumping the s5k83a register state for page 0x%x", page);
+		pr_info("Dumping the s5k83a register state for page 0x%x\n",
+			page);
 		for (address = 0; address <= 0xff; address++) {
 			u8 val = 0;
 			m5602_read_sensor(sd, address, &val, 1);
-			info("register 0x%x contains 0x%x",
-			     address, val);
+			pr_info("register 0x%x contains 0x%x\n", address, val);
 		}
 	}
-	info("s5k83a register state dump complete");
+	pr_info("s5k83a register state dump complete\n");
 
 	for (page = 0; page < 16; page++) {
 		m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
-		info("Probing for which registers that are read/write "
-				"for page 0x%x", page);
+		pr_info("Probing for which registers that are read/write for page 0x%x\n",
+			page);
 		for (address = 0; address <= 0xff; address++) {
 			u8 old_val, ctrl_val, test_val = 0xff;
 
@@ -588,14 +590,16 @@
 			m5602_read_sensor(sd, address, &ctrl_val, 1);
 
 			if (ctrl_val == test_val)
-				info("register 0x%x is writeable", address);
+				pr_info("register 0x%x is writeable\n",
+					address);
 			else
-				info("register 0x%x is read only", address);
+				pr_info("register 0x%x is read only\n",
+					address);
 
 			/* Restore original val */
 			m5602_write_sensor(sd, address, &old_val, 1);
 		}
 	}
-	info("Read/write register probing complete");
+	pr_info("Read/write register probing complete\n");
 	m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/m5602/Makefile linux-libre-3.2-gnu/drivers/media/video/gspca/m5602/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/gspca/m5602/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/m5602/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -8,4 +8,4 @@
 		    m5602_s5k83a.o \
 		    m5602_s5k4aa.o
 
-EXTRA_CFLAGS += -Idrivers/media/video/gspca
+ccflags-y += -Idrivers/media/video/gspca
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/Makefile linux-libre-3.2-gnu/drivers/media/video/gspca/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/gspca/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -35,6 +35,7 @@
 obj-$(CONFIG_USB_GSPCA_STK014)   += gspca_stk014.o
 obj-$(CONFIG_USB_GSPCA_STV0680)  += gspca_stv0680.o
 obj-$(CONFIG_USB_GSPCA_T613)     += gspca_t613.o
+obj-$(CONFIG_USB_GSPCA_TOPRO)    += gspca_topro.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
@@ -78,6 +79,7 @@
 gspca_stv0680-objs  := stv0680.o
 gspca_sunplus-objs  := sunplus.o
 gspca_t613-objs     := t613.o
+gspca_topro-objs    := topro.o
 gspca_tv8532-objs   := tv8532.o
 gspca_vc032x-objs   := vc032x.o
 gspca_vicam-objs    := vicam.o
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/mars.c linux-libre-3.2-gnu/drivers/media/video/gspca/mars.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/mars.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/mars.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "mars"
 
 #include "gspca.h"
@@ -178,8 +180,8 @@
 			&alen,
 			500);	/* timeout in milliseconds */
 	if (ret < 0) {
-		err("reg write [%02x] error %d",
-			gspca_dev->usb_buf[0], ret);
+		pr_err("reg write [%02x] error %d\n",
+		       gspca_dev->usb_buf[0], ret);
 		gspca_dev->usb_err = ret;
 	}
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/mr97310a.c linux-libre-3.2-gnu/drivers/media/video/gspca/mr97310a.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/mr97310a.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/mr97310a.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "mr97310a"
 
 #include "gspca.h"
@@ -267,7 +269,7 @@
 			  usb_sndbulkpipe(gspca_dev->dev, 4),
 			  gspca_dev->usb_buf, len, NULL, 500);
 	if (rc < 0)
-		err("reg write [%02x] error %d",
+		pr_err("reg write [%02x] error %d\n",
 		       gspca_dev->usb_buf[0], rc);
 	return rc;
 }
@@ -281,7 +283,7 @@
 			  usb_rcvbulkpipe(gspca_dev->dev, 3),
 			  gspca_dev->usb_buf, len, NULL, 500);
 	if (rc < 0)
-		err("reg read [%02x] error %d",
+		pr_err("reg read [%02x] error %d\n",
 		       gspca_dev->usb_buf[0], rc);
 	return rc;
 }
@@ -540,7 +542,7 @@
 			sd->sensor_type = 1;
 			break;
 		default:
-			err("Unknown CIF Sensor id : %02x",
+			pr_err("Unknown CIF Sensor id : %02x\n",
 			       gspca_dev->usb_buf[1]);
 			return -ENODEV;
 		}
@@ -575,10 +577,10 @@
 			sd->sensor_type = 2;
 		} else if ((gspca_dev->usb_buf[0] != 0x03) &&
 					(gspca_dev->usb_buf[0] != 0x04)) {
-			err("Unknown VGA Sensor id Byte 0: %02x",
-					gspca_dev->usb_buf[0]);
-			err("Defaults assumed, may not work");
-			err("Please report this");
+			pr_err("Unknown VGA Sensor id Byte 0: %02x\n",
+			       gspca_dev->usb_buf[0]);
+			pr_err("Defaults assumed, may not work\n");
+			pr_err("Please report this\n");
 		}
 		/* Sakar Digital color needs to be adjusted. */
 		if ((gspca_dev->usb_buf[0] == 0x03) &&
@@ -595,10 +597,10 @@
 				/* Nothing to do here. */
 				break;
 			default:
-				err("Unknown VGA Sensor id Byte 1: %02x",
-					gspca_dev->usb_buf[1]);
-				err("Defaults assumed, may not work");
-				err("Please report this");
+				pr_err("Unknown VGA Sensor id Byte 1: %02x\n",
+				       gspca_dev->usb_buf[1]);
+				pr_err("Defaults assumed, may not work\n");
+				pr_err("Please report this\n");
 			}
 		}
 		PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d",
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/nw80x.c linux-libre-3.2-gnu/drivers/media/video/gspca/nw80x.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/nw80x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/nw80x.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "nw80x"
 
 #include "gspca.h"
@@ -1571,7 +1573,7 @@
 			len,
 			500);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -1592,7 +1594,7 @@
 			0x00, index,
 			gspca_dev->usb_buf, len, 500);
 	if (ret < 0) {
-		err("reg_r err %d", ret);
+		pr_err("reg_r err %d\n", ret);
 		gspca_dev->usb_err = ret;
 		return;
 	}
@@ -1802,7 +1804,8 @@
 		}
 	}
 	if (webcam_chip[sd->webcam] != sd->bridge) {
-		err("Bad webcam type %d for NW80%d", sd->webcam, sd->bridge);
+		pr_err("Bad webcam type %d for NW80%d\n",
+		       sd->webcam, sd->bridge);
 		gspca_dev->usb_err = -ENODEV;
 		return gspca_dev->usb_err;
 	}
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/ov519.c linux-libre-3.2-gnu/drivers/media/video/gspca/ov519.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/ov519.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/ov519.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,9 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "ov519"
 
 #include <linux/input.h>
@@ -2171,7 +2174,7 @@
 			sd->gspca_dev.usb_buf, 1, 500);
 leave:
 	if (ret < 0) {
-		err("reg_w %02x failed %d", index, ret);
+		pr_err("reg_w %02x failed %d\n", index, ret);
 		sd->gspca_dev.usb_err = ret;
 		return;
 	}
@@ -2210,7 +2213,7 @@
 		PDEBUG(D_USBI, "GET %02x 0000 %04x %02x",
 			req, index, ret);
 	} else {
-		err("reg_r %02x failed %d", index, ret);
+		pr_err("reg_r %02x failed %d\n", index, ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 
@@ -2235,7 +2238,7 @@
 	if (ret >= 0) {
 		ret = sd->gspca_dev.usb_buf[0];
 	} else {
-		err("reg_r8 %02x failed %d", index, ret);
+		pr_err("reg_r8 %02x failed %d\n", index, ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 
@@ -2288,7 +2291,7 @@
 			0, index,
 			sd->gspca_dev.usb_buf, n, 500);
 	if (ret < 0) {
-		err("reg_w32 %02x failed %d", index, ret);
+		pr_err("reg_w32 %02x failed %d\n", index, ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 }
@@ -2457,7 +2460,7 @@
 			(u16) value, (u16) reg, NULL, 0, 500);
 
 	if (ret < 0) {
-		err("ovfx2_i2c_w %02x failed %d", reg, ret);
+		pr_err("ovfx2_i2c_w %02x failed %d\n", reg, ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 
@@ -2481,7 +2484,7 @@
 		ret = sd->gspca_dev.usb_buf[0];
 		PDEBUG(D_USBI, "ovfx2_i2c_r %02x %02x", reg, ret);
 	} else {
-		err("ovfx2_i2c_r %02x failed %d", reg, ret);
+		pr_err("ovfx2_i2c_r %02x failed %d\n", reg, ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 
@@ -2727,7 +2730,7 @@
 	int high, low;
 
 	if (sd->bridge != BRIDGE_OVFX2) {
-		err("error hires sensors only supported with ovfx2");
+		pr_err("error hires sensors only supported with ovfx2\n");
 		return;
 	}
 
@@ -2762,7 +2765,7 @@
 		}
 		break;
 	}
-	err("Error unknown sensor type: %02x%02x", high, low);
+	pr_err("Error unknown sensor type: %02x%02x\n", high, low);
 }
 
 /* This initializes the OV8110, OV8610 sensor. The OV8110 uses
@@ -2783,7 +2786,7 @@
 	if ((rc & 3) == 1)
 		sd->sensor = SEN_OV8610;
 	else
-		err("Unknown image sensor version: %d", rc & 3);
+		pr_err("Unknown image sensor version: %d\n", rc & 3);
 }
 
 /* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
@@ -2840,8 +2843,8 @@
 		if (high == 0x76) {
 			switch (low) {
 			case 0x30:
-				err("Sensor is an OV7630/OV7635");
-				err("7630 is not supported by this driver");
+				pr_err("Sensor is an OV7630/OV7635\n");
+				pr_err("7630 is not supported by this driver\n");
 				return;
 			case 0x40:
 				PDEBUG(D_PROBE, "Sensor is an OV7645");
@@ -2868,7 +2871,7 @@
 			sd->sensor = SEN_OV7620;
 		}
 	} else {
-		err("Unknown image sensor version: %d", rc & 3);
+		pr_err("Unknown image sensor version: %d\n", rc & 3);
 	}
 }
 
@@ -2891,8 +2894,7 @@
 	switch (rc) {
 	case 0x00:
 		sd->sensor = SEN_OV6630;
-		warn("WARNING: Sensor is an OV66308. Your camera may have");
-		warn("been misdetected in previous driver versions.");
+		pr_warn("WARNING: Sensor is an OV66308. Your camera may have been misdetected in previous driver versions.\n");
 		break;
 	case 0x01:
 		sd->sensor = SEN_OV6620;
@@ -2908,11 +2910,10 @@
 		break;
 	case 0x90:
 		sd->sensor = SEN_OV6630;
-		warn("WARNING: Sensor is an OV66307. Your camera may have");
-		warn("been misdetected in previous driver versions.");
+		pr_warn("WARNING: Sensor is an OV66307. Your camera may have been misdetected in previous driver versions.\n");
 		break;
 	default:
-		err("FATAL: Unknown sensor version: 0x%02x", rc);
+		pr_err("FATAL: Unknown sensor version: 0x%02x\n", rc);
 		return;
 	}
 
@@ -3405,7 +3406,7 @@
 	} else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) {
 		ov_hires_configure(sd);
 	} else {
-		err("Can't determine sensor slave IDs");
+		pr_err("Can't determine sensor slave IDs\n");
 		goto error;
 	}
 
@@ -3590,7 +3591,7 @@
 	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
 	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
 	if (!alt) {
-		err("Couldn't get altsetting");
+		pr_err("Couldn't get altsetting\n");
 		sd->gspca_dev.usb_err = -EIO;
 		return;
 	}
@@ -3713,7 +3714,7 @@
 	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
 	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
 	if (!alt) {
-		err("Couldn't get altsetting");
+		pr_err("Couldn't get altsetting\n");
 		sd->gspca_dev.usb_err = -EIO;
 		return;
 	}
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/ov534_9.c linux-libre-3.2-gnu/drivers/media/video/gspca/ov534_9.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/ov534_9.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/ov534_9.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
- * ov534-ov965x gspca driver
+ * ov534-ov9xxx gspca driver
  *
- * Copyright (C) 2009-2010 Jean-Francois Moine http://moinejf.free.fr
+ * Copyright (C) 2009-2011 Jean-Francois Moine http://moinejf.free.fr
  * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
  * Copyright (C) 2008 Jim Paris <jim@jtan.com>
  *
@@ -24,6 +24,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "ov534_9"
 
 #include "gspca.h"
@@ -45,39 +47,44 @@
 MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver");
 MODULE_LICENSE("GPL");
 
+/* controls */
+enum e_ctrl {
+	BRIGHTNESS,
+	CONTRAST,
+	AUTOGAIN,
+	EXPOSURE,
+	SHARPNESS,
+	SATUR,
+	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;
 	u8 last_fid;
 
-	u8 brightness;
-	u8 contrast;
-	u8 autogain;
-	u8 exposure;
-	s8 sharpness;
-	u8 satur;
-	u8 freq;
+	u8 sensor;
+};
+enum sensors {
+	SENSOR_OV965x,		/* ov9657 */
+	SENSOR_OV971x,		/* ov9712 */
+	NSENSORS
 };
 
 /* 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_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
-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_setexposure(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getexposure(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_setsatur(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
+static void setbrightness(struct gspca_dev *gspca_dev);
+static void setcontrast(struct gspca_dev *gspca_dev);
+static void setautogain(struct gspca_dev *gspca_dev);
+static void setexposure(struct gspca_dev *gspca_dev);
+static void setsharpness(struct gspca_dev *gspca_dev);
+static void setsatur(struct gspca_dev *gspca_dev);
+static void setlightfreq(struct gspca_dev *gspca_dev);
 
-static const struct ctrl sd_ctrls[] = {
-    {							/* 0 */
+static const struct ctrl sd_ctrls[NCTRLS] = {
+[BRIGHTNESS] = {
 	{
 		.id      = V4L2_CID_BRIGHTNESS,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -85,13 +92,11 @@
 		.minimum = 0,
 		.maximum = 15,
 		.step    = 1,
-#define BRIGHTNESS_DEF 7
-		.default_value = BRIGHTNESS_DEF,
+		.default_value = 7
 	},
-	.set = sd_setbrightness,
-	.get = sd_getbrightness,
+	.set_control = setbrightness
     },
-    {							/* 1 */
+[CONTRAST] = {
 	{
 		.id      = V4L2_CID_CONTRAST,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -99,13 +104,11 @@
 		.minimum = 0,
 		.maximum = 15,
 		.step    = 1,
-#define CONTRAST_DEF 3
-		.default_value = CONTRAST_DEF,
+		.default_value = 3
 	},
-	.set = sd_setcontrast,
-	.get = sd_getcontrast,
+	.set_control = setcontrast
     },
-    {							/* 2 */
+[AUTOGAIN] = {
 	{
 		.id      = V4L2_CID_AUTOGAIN,
 		.type    = V4L2_CTRL_TYPE_BOOLEAN,
@@ -116,11 +119,9 @@
 #define AUTOGAIN_DEF 1
 		.default_value = AUTOGAIN_DEF,
 	},
-	.set = sd_setautogain,
-	.get = sd_getautogain,
+	.set_control = setautogain
     },
-#define EXPO_IDX 3
-    {							/* 3 */
+[EXPOSURE] = {
 	{
 		.id      = V4L2_CID_EXPOSURE,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -128,13 +129,11 @@
 		.minimum = 0,
 		.maximum = 3,
 		.step    = 1,
-#define EXPO_DEF 0
-		.default_value = EXPO_DEF,
+		.default_value = 0
 	},
-	.set = sd_setexposure,
-	.get = sd_getexposure,
+	.set_control = setexposure
     },
-    {							/* 4 */
+[SHARPNESS] = {
 	{
 		.id      = V4L2_CID_SHARPNESS,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -142,13 +141,11 @@
 		.minimum = -1,		/* -1 = auto */
 		.maximum = 4,
 		.step    = 1,
-#define SHARPNESS_DEF -1
-		.default_value = SHARPNESS_DEF,
+		.default_value = -1
 	},
-	.set = sd_setsharpness,
-	.get = sd_getsharpness,
+	.set_control = setsharpness
     },
-    {							/* 5 */
+[SATUR] = {
 	{
 		.id      = V4L2_CID_SATURATION,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -156,13 +153,11 @@
 		.minimum = 0,
 		.maximum = 4,
 		.step    = 1,
-#define SATUR_DEF 2
-		.default_value = SATUR_DEF,
+		.default_value = 2
 	},
-	.set = sd_setsatur,
-	.get = sd_getsatur,
+	.set_control = setsatur
     },
-    {
+[LIGHTFREQ] = {
 	{
 		.id	 = V4L2_CID_POWER_LINE_FREQUENCY,
 		.type    = V4L2_CTRL_TYPE_MENU,
@@ -170,11 +165,9 @@
 		.minimum = 0,
 		.maximum = 2,	/* 0: 0, 1: 50Hz, 2:60Hz */
 		.step    = 1,
-#define FREQ_DEF 0
-		.default_value = FREQ_DEF,
+		.default_value = 0
 	},
-	.set = sd_setfreq,
-	.get = sd_getfreq,
+	.set_control = setlightfreq
     },
 };
 
@@ -206,6 +199,14 @@
 		.colorspace = V4L2_COLORSPACE_JPEG},
 };
 
+static const struct v4l2_pix_format ov971x_mode[] = {
+	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+		.bytesperline = 640,
+		.sizeimage = 640 * 480,
+		.colorspace = V4L2_COLORSPACE_SRGB
+	}
+};
+
 static const u8 bridge_init[][2] = {
 	{0x88, 0xf8},
 	{0x89, 0xff},
@@ -240,7 +241,7 @@
 	{0x94, 0x11},
 };
 
-static const u8 sensor_init[][2] = {
+static const u8 ov965x_init[][2] = {
 	{0x12, 0x80},	/* com7 - SSCB reset */
 	{0x00, 0x00},	/* gain */
 	{0x01, 0x80},	/* blue */
@@ -450,7 +451,7 @@
 	{0x94, 0x11},
 };
 
-static const u8 sensor_init_2[][2] = {
+static const u8 ov965x_init_2[][2] = {
 	{0x3b, 0xc4},
 	{0x1e, 0x04},	/* mvfp */
 	{0x13, 0xe0},	/* com8 */
@@ -492,7 +493,65 @@
 	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
 };
 
-static const u8 sensor_start_1_vga[][2] = {	/* same for qvga */
+static const u8 ov971x_init[][2] = {
+	{0x12, 0x80},
+	{0x09, 0x10},
+	{0x1e, 0x07},
+	{0x5f, 0x18},
+	{0x69, 0x04},
+	{0x65, 0x2a},
+	{0x68, 0x0a},
+	{0x39, 0x28},
+	{0x4d, 0x90},
+	{0xc1, 0x80},
+	{0x0c, 0x30},
+	{0x6d, 0x02},
+	{0x96, 0xf1},
+	{0xbc, 0x68},
+	{0x12, 0x00},
+	{0x3b, 0x00},
+	{0x97, 0x80},
+	{0x17, 0x25},
+	{0x18, 0xa2},
+	{0x19, 0x01},
+	{0x1a, 0xca},
+	{0x03, 0x0a},
+	{0x32, 0x07},
+	{0x98, 0x40},	/*{0x98, 0x00},*/
+	{0x99, 0xA0},	/*{0x99, 0x00},*/
+	{0x9a, 0x01},	/*{0x9a, 0x00},*/
+	{0x57, 0x00},
+	{0x58, 0x78},	/*{0x58, 0xc8},*/
+	{0x59, 0x50},	/*{0x59, 0xa0},*/
+	{0x4c, 0x13},
+	{0x4b, 0x36},
+	{0x3d, 0x3c},
+	{0x3e, 0x03},
+	{0xbd, 0x50},	/*{0xbd, 0xa0},*/
+	{0xbe, 0x78},	/*{0xbe, 0xc8},*/
+	{0x4e, 0x55},
+	{0x4f, 0x55},
+	{0x50, 0x55},
+	{0x51, 0x55},
+	{0x24, 0x55},
+	{0x25, 0x40},
+	{0x26, 0xa1},
+	{0x5c, 0x59},
+	{0x5d, 0x00},
+	{0x11, 0x00},
+	{0x2a, 0x98},
+	{0x2b, 0x06},
+	{0x2d, 0x00},
+	{0x2e, 0x00},
+	{0x13, 0xa5},
+	{0x14, 0x40},
+	{0x4a, 0x00},
+	{0x49, 0xce},
+	{0x22, 0x03},
+	{0x09, 0x00}
+};
+
+static const u8 ov965x_start_1_vga[][2] = {	/* same for qvga */
 	{0x12, 0x62},	/* com7 - 30fps VGA YUV */
 	{0x36, 0xfa},	/* aref3 */
 	{0x69, 0x0a},	/* hv */
@@ -515,7 +574,7 @@
 	{0xc0, 0xaa},
 };
 
-static const u8 sensor_start_1_svga[][2] = {
+static const u8 ov965x_start_1_svga[][2] = {
 	{0x12, 0x02},	/* com7 - YUYV - VGA 15 full resolution */
 	{0x36, 0xf8},	/* aref3 */
 	{0x69, 0x02},	/* hv */
@@ -537,7 +596,7 @@
 	{0xc0, 0xe2},
 };
 
-static const u8 sensor_start_1_xga[][2] = {
+static const u8 ov965x_start_1_xga[][2] = {
 	{0x12, 0x02},	/* com7 */
 	{0x36, 0xf8},	/* aref3 */
 	{0x69, 0x02},	/* hv */
@@ -560,7 +619,7 @@
 	{0xc0, 0xe2},
 };
 
-static const u8 sensor_start_1_sxga[][2] = {
+static const u8 ov965x_start_1_sxga[][2] = {
 	{0x12, 0x02},	/* com7 */
 	{0x36, 0xf8},	/* aref3 */
 	{0x69, 0x02},	/* hv */
@@ -709,7 +768,7 @@
 	{0x94, 0x11},
 };
 
-static const u8 sensor_start_2_qvga[][2] = {
+static const u8 ov965x_start_2_qvga[][2] = {
 	{0x3b, 0xe4},	/* com11 - night mode 1/4 frame rate */
 	{0x1e, 0x04},	/* mvfp */
 	{0x13, 0xe0},	/* com8 */
@@ -727,7 +786,7 @@
 	{0x3a, 0x80},	/* tslb - yuyv */
 };
 
-static const u8 sensor_start_2_vga[][2] = {
+static const u8 ov965x_start_2_vga[][2] = {
 	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */
 	{0x1e, 0x04},	/* mvfp */
 	{0x13, 0xe0},	/* com8 */
@@ -743,7 +802,7 @@
 	{0x2d, 0x00},	/* advfl */
 };
 
-static const u8 sensor_start_2_svga[][2] = {	/* same for xga */
+static const u8 ov965x_start_2_svga[][2] = {	/* same for xga */
 	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */
 	{0x1e, 0x04},	/* mvfp */
 	{0x13, 0xe0},	/* com8 */
@@ -757,7 +816,7 @@
 	{0xa3, 0x41},	/* bd60 */
 };
 
-static const u8 sensor_start_2_sxga[][2] = {
+static const u8 ov965x_start_2_sxga[][2] = {
 	{0x13, 0xe0},	/* com8 */
 	{0x00, 0x00},
 	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
@@ -785,7 +844,7 @@
 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
 	if (ret < 0) {
-		err("reg_w failed %d", ret);
+		pr_err("reg_w failed %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -810,7 +869,7 @@
 			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
 	PDEBUG(D_USBI, "reg_r [%04x] -> %02x", reg, gspca_dev->usb_buf[0]);
 	if (ret < 0) {
-		err("reg_r err %d", ret);
+		pr_err("reg_r err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 	return gspca_dev->usb_buf[0];
@@ -848,7 +907,7 @@
 	reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
 
 	if (!sccb_check_status(gspca_dev))
-		err("sccb_write failed");
+		pr_err("sccb_write failed\n");
 }
 
 static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)
@@ -856,11 +915,11 @@
 	reg_w(gspca_dev, OV534_REG_SUBADDR, reg);
 	reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
 	if (!sccb_check_status(gspca_dev))
-		err("sccb_read failed 1");
+		pr_err("sccb_read failed 1\n");
 
 	reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
 	if (!sccb_check_status(gspca_dev))
-		err("sccb_read failed 2");
+		pr_err("sccb_read failed 2\n");
 
 	return reg_r(gspca_dev, OV534_REG_READ);
 }
@@ -922,7 +981,9 @@
 	struct sd *sd = (struct sd *) gspca_dev;
 	u8 val;
 
-	val = sd->brightness;
+	if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS))
+		return;
+	val = sd->ctrls[BRIGHTNESS].val;
 	if (val < 8)
 		val = 15 - val;		/* f .. 8 */
 	else
@@ -935,8 +996,10 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
+	if (gspca_dev->ctrl_dis & (1 << CONTRAST))
+		return;
 	sccb_write(gspca_dev, 0x56,	/* cnst1 - contrast 1 ctrl coeff */
-			sd->contrast << 4);
+			sd->ctrls[CONTRAST].val << 4);
 }
 
 static void setautogain(struct gspca_dev *gspca_dev)
@@ -944,10 +1007,12 @@
 	struct sd *sd = (struct sd *) gspca_dev;
 	u8 val;
 
+	if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
+		return;
 /*fixme: should adjust agc/awb/aec by different controls */
 	val = sccb_read(gspca_dev, 0x13);		/* com8 */
 	sccb_write(gspca_dev, 0xff, 0x00);
-	if (sd->autogain)
+	if (sd->ctrls[AUTOGAIN].val)
 		val |= 0x05;		/* agc & aec */
 	else
 		val &= 0xfa;
@@ -960,8 +1025,10 @@
 	u8 val;
 	static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};
 
+	if (gspca_dev->ctrl_dis & (1 << EXPOSURE))
+		return;
 	sccb_write(gspca_dev, 0x10,			/* aec[9:2] */
-			expo[sd->exposure]);
+			expo[sd->ctrls[EXPOSURE].val]);
 
 	val = sccb_read(gspca_dev, 0x13);		/* com8 */
 	sccb_write(gspca_dev, 0xff, 0x00);
@@ -977,7 +1044,9 @@
 	struct sd *sd = (struct sd *) gspca_dev;
 	s8 val;
 
-	val = sd->sharpness;
+	if (gspca_dev->ctrl_dis & (1 << SHARPNESS))
+		return;
+	val = sd->ctrls[SHARPNESS].val;
 	if (val < 0) {				/* auto */
 		val = sccb_read(gspca_dev, 0x42);	/* com17 */
 		sccb_write(gspca_dev, 0xff, 0x00);
@@ -1006,8 +1075,10 @@
 		{0x48, 0x90}
 	};
 
-	val1 = matrix[sd->satur][0];
-	val2 = matrix[sd->satur][1];
+	if (gspca_dev->ctrl_dis & (1 << SATUR))
+		return;
+	val1 = matrix[sd->ctrls[SATUR].val][0];
+	val2 = matrix[sd->ctrls[SATUR].val][1];
 	val3 = val1 + val2;
 	sccb_write(gspca_dev, 0x4f, val3);	/* matrix coeff */
 	sccb_write(gspca_dev, 0x50, val3);
@@ -1022,14 +1093,16 @@
 	sccb_write(gspca_dev, 0x41, val1);
 }
 
-static void setfreq(struct gspca_dev *gspca_dev)
+static void setlightfreq(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	u8 val;
 
+	if (gspca_dev->ctrl_dis & (1 << LIGHTFREQ))
+		return;
 	val = sccb_read(gspca_dev, 0x13);		/* com8 */
 	sccb_write(gspca_dev, 0xff, 0x00);
-	if (sd->freq == 0) {
+	if (sd->ctrls[LIGHTFREQ].val == 0) {
 		sccb_write(gspca_dev, 0x13, val & 0xdf);
 		return;
 	}
@@ -1037,7 +1110,7 @@
 
 	val = sccb_read(gspca_dev, 0x42);		/* com17 */
 	sccb_write(gspca_dev, 0xff, 0x00);
-	if (sd->freq == 1)
+	if (sd->ctrls[LIGHTFREQ].val == 1)
 		val |= 0x01;
 	else
 		val &= 0xfe;
@@ -1049,34 +1122,19 @@
 		     const struct usb_device_id *id)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct cam *cam;
-
-	cam = &gspca_dev->cam;
 
-	cam->cam_mode = ov965x_mode;
-	cam->nmodes = ARRAY_SIZE(ov965x_mode);
+	gspca_dev->cam.ctrls = sd->ctrls;
 
-	sd->brightness = BRIGHTNESS_DEF;
-	sd->contrast = CONTRAST_DEF;
 #if AUTOGAIN_DEF != 0
-	sd->autogain = AUTOGAIN_DEF;
-	gspca_dev->ctrl_inac |= (1 << EXPO_IDX);
-#endif
-#if EXPO_DEF != 0
-	sd->exposure = EXPO_DEF;
-#endif
-#if SHARPNESS_DEF != 0
-	sd->sharpness = SHARPNESS_DEF;
+	gspca_dev->ctrl_inac |= (1 << EXPOSURE);
 #endif
-	sd->satur = SATUR_DEF;
-	sd->freq = FREQ_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;
 
 	/* reset bridge */
@@ -1099,68 +1157,117 @@
 	PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
 
 	/* initialize */
-	reg_w_array(gspca_dev, bridge_init,
-			ARRAY_SIZE(bridge_init));
-	sccb_w_array(gspca_dev, sensor_init,
-			ARRAY_SIZE(sensor_init));
-	reg_w_array(gspca_dev, bridge_init_2,
-			ARRAY_SIZE(bridge_init_2));
-	sccb_w_array(gspca_dev, sensor_init_2,
-			ARRAY_SIZE(sensor_init_2));
-	reg_w(gspca_dev, 0xe0, 0x00);
-	reg_w(gspca_dev, 0xe0, 0x01);
-	set_led(gspca_dev, 0);
-	reg_w(gspca_dev, 0xe0, 0x00);
+	if ((sensor_id & 0xfff0) == 0x9650) {
+		sd->sensor = SENSOR_OV965x;
+
+		gspca_dev->cam.cam_mode = ov965x_mode;
+		gspca_dev->cam.nmodes = ARRAY_SIZE(ov965x_mode);
+
+		reg_w_array(gspca_dev, bridge_init,
+				ARRAY_SIZE(bridge_init));
+		sccb_w_array(gspca_dev, ov965x_init,
+				ARRAY_SIZE(ov965x_init));
+		reg_w_array(gspca_dev, bridge_init_2,
+				ARRAY_SIZE(bridge_init_2));
+		sccb_w_array(gspca_dev, ov965x_init_2,
+				ARRAY_SIZE(ov965x_init_2));
+		reg_w(gspca_dev, 0xe0, 0x00);
+		reg_w(gspca_dev, 0xe0, 0x01);
+		set_led(gspca_dev, 0);
+		reg_w(gspca_dev, 0xe0, 0x00);
+	} else if ((sensor_id & 0xfff0) == 0x9710) {
+		const char *p;
+		int l;
+
+		sd->sensor = SENSOR_OV971x;
+
+		gspca_dev->cam.cam_mode = ov971x_mode;
+		gspca_dev->cam.nmodes = ARRAY_SIZE(ov971x_mode);
+
+		/* no control yet */
+		gspca_dev->ctrl_dis = (1 << NCTRLS) - 1;
+
+		gspca_dev->cam.bulk = 1;
+		gspca_dev->cam.bulk_size = 16384;
+		gspca_dev->cam.bulk_nurbs = 2;
+
+		sccb_w_array(gspca_dev, ov971x_init,
+				ARRAY_SIZE(ov971x_init));
+
+		/* set video format on bridge processor */
+		/* access bridge processor's video format registers at: 0x00 */
+		reg_w(gspca_dev, 0x1c, 0x00);
+		/*set register: 0x00 is 'RAW8', 0x40 is 'YUV422' (YUYV?)*/
+		reg_w(gspca_dev, 0x1d, 0x00);
+
+		/* Will W. specific stuff
+		 * set VSYNC to
+		 *	output (0x1f) if first webcam
+		 *	input (0x17) if 2nd or 3rd webcam */
+		p = video_device_node_name(&gspca_dev->vdev);
+		l = strlen(p) - 1;
+		if (p[l] == '0')
+			reg_w(gspca_dev, 0x56, 0x1f);
+		else
+			reg_w(gspca_dev, 0x56, 0x17);
+	} else {
+		err("Unknown sensor %04x", sensor_id);
+		return -EINVAL;
+	}
 
 	return gspca_dev->usb_err;
 }
 
 static int sd_start(struct gspca_dev *gspca_dev)
 {
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (sd->sensor == SENSOR_OV971x)
+		return gspca_dev->usb_err;
 	switch (gspca_dev->curr_mode) {
 	case QVGA_MODE:			/* 320x240 */
-		sccb_w_array(gspca_dev, sensor_start_1_vga,
-				ARRAY_SIZE(sensor_start_1_vga));
+		sccb_w_array(gspca_dev, ov965x_start_1_vga,
+				ARRAY_SIZE(ov965x_start_1_vga));
 		reg_w_array(gspca_dev, bridge_start_qvga,
 				ARRAY_SIZE(bridge_start_qvga));
-		sccb_w_array(gspca_dev, sensor_start_2_qvga,
-				ARRAY_SIZE(sensor_start_2_qvga));
+		sccb_w_array(gspca_dev, ov965x_start_2_qvga,
+				ARRAY_SIZE(ov965x_start_2_qvga));
 		break;
 	case VGA_MODE:			/* 640x480 */
-		sccb_w_array(gspca_dev, sensor_start_1_vga,
-				ARRAY_SIZE(sensor_start_1_vga));
+		sccb_w_array(gspca_dev, ov965x_start_1_vga,
+				ARRAY_SIZE(ov965x_start_1_vga));
 		reg_w_array(gspca_dev, bridge_start_vga,
 				ARRAY_SIZE(bridge_start_vga));
-		sccb_w_array(gspca_dev, sensor_start_2_vga,
-				ARRAY_SIZE(sensor_start_2_vga));
+		sccb_w_array(gspca_dev, ov965x_start_2_vga,
+				ARRAY_SIZE(ov965x_start_2_vga));
 		break;
 	case SVGA_MODE:			/* 800x600 */
-		sccb_w_array(gspca_dev, sensor_start_1_svga,
-				ARRAY_SIZE(sensor_start_1_svga));
+		sccb_w_array(gspca_dev, ov965x_start_1_svga,
+				ARRAY_SIZE(ov965x_start_1_svga));
 		reg_w_array(gspca_dev, bridge_start_svga,
 				ARRAY_SIZE(bridge_start_svga));
-		sccb_w_array(gspca_dev, sensor_start_2_svga,
-				ARRAY_SIZE(sensor_start_2_svga));
+		sccb_w_array(gspca_dev, ov965x_start_2_svga,
+				ARRAY_SIZE(ov965x_start_2_svga));
 		break;
 	case XGA_MODE:			/* 1024x768 */
-		sccb_w_array(gspca_dev, sensor_start_1_xga,
-				ARRAY_SIZE(sensor_start_1_xga));
+		sccb_w_array(gspca_dev, ov965x_start_1_xga,
+				ARRAY_SIZE(ov965x_start_1_xga));
 		reg_w_array(gspca_dev, bridge_start_xga,
 				ARRAY_SIZE(bridge_start_xga));
-		sccb_w_array(gspca_dev, sensor_start_2_svga,
-				ARRAY_SIZE(sensor_start_2_svga));
+		sccb_w_array(gspca_dev, ov965x_start_2_svga,
+				ARRAY_SIZE(ov965x_start_2_svga));
 		break;
 	default:
 /*	case SXGA_MODE:			 * 1280x1024 */
-		sccb_w_array(gspca_dev, sensor_start_1_sxga,
-				ARRAY_SIZE(sensor_start_1_sxga));
+		sccb_w_array(gspca_dev, ov965x_start_1_sxga,
+				ARRAY_SIZE(ov965x_start_1_sxga));
 		reg_w_array(gspca_dev, bridge_start_sxga,
 				ARRAY_SIZE(bridge_start_sxga));
-		sccb_w_array(gspca_dev, sensor_start_2_sxga,
-				ARRAY_SIZE(sensor_start_2_sxga));
+		sccb_w_array(gspca_dev, ov965x_start_2_sxga,
+				ARRAY_SIZE(ov965x_start_2_sxga));
 		break;
 	}
-	setfreq(gspca_dev);
+	setlightfreq(gspca_dev);
 	setautogain(gspca_dev);
 	setbrightness(gspca_dev);
 	setcontrast(gspca_dev);
@@ -1198,9 +1305,11 @@
 	__u32 this_pts;
 	u8 this_fid;
 	int remaining_len = len;
+	int payload_len;
 
+	payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
 	do {
-		len = min(remaining_len, 2040);
+		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
@@ -1262,138 +1371,6 @@
 	} while (remaining_len > 0);
 }
 
-/* controls */
-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 gspca_dev->usb_err;
-}
-
-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 gspca_dev->usb_err;
-}
-
-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_setautogain(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->autogain = val;
-
-	if (gspca_dev->streaming) {
-		if (val)
-			gspca_dev->ctrl_inac |= (1 << EXPO_IDX);
-		else
-			gspca_dev->ctrl_inac &= ~(1 << EXPO_IDX);
-		setautogain(gspca_dev);
-	}
-	return gspca_dev->usb_err;
-}
-
-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_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 gspca_dev->usb_err;
-}
-
-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_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 gspca_dev->usb_err;
-}
-
-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_setsatur(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->satur = val;
-	if (gspca_dev->streaming)
-		setsatur(gspca_dev);
-	return gspca_dev->usb_err;
-}
-
-static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->satur;
-	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 gspca_dev->usb_err;
-}
-
-static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->freq;
-	return 0;
-}
-
 static int sd_querymenu(struct gspca_dev *gspca_dev,
 			struct v4l2_querymenu *menu)
 {
@@ -1419,7 +1396,7 @@
 static const struct sd_desc sd_desc = {
 	.name     = MODULE_NAME,
 	.ctrls    = sd_ctrls,
-	.nctrls   = ARRAY_SIZE(sd_ctrls),
+	.nctrls   = NCTRLS,
 	.config   = sd_config,
 	.init     = sd_init,
 	.start    = sd_start,
@@ -1430,6 +1407,7 @@
 
 /* -- module initialisation -- */
 static const struct usb_device_id device_table[] = {
+	{USB_DEVICE(0x05a9, 0x8065)},
 	{USB_DEVICE(0x06f8, 0x3003)},
 	{}
 };
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/ov534.c linux-libre-3.2-gnu/drivers/media/video/gspca/ov534.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/ov534.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/ov534.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "ov534"
 
 #include "gspca.h"
@@ -775,7 +777,7 @@
 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
 	if (ret < 0) {
-		err("write failed %d", ret);
+		pr_err("write failed %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -794,7 +796,7 @@
 			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
 	PDEBUG(D_USBI, "GET 01 0000 %04x %02x", reg, gspca_dev->usb_buf[0]);
 	if (ret < 0) {
-		err("read failed %d", ret);
+		pr_err("read failed %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 	return gspca_dev->usb_buf[0];
@@ -858,7 +860,7 @@
 	ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
 
 	if (!sccb_check_status(gspca_dev)) {
-		err("sccb_reg_write failed");
+		pr_err("sccb_reg_write failed\n");
 		gspca_dev->usb_err = -EIO;
 	}
 }
@@ -868,11 +870,11 @@
 	ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
 	ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
 	if (!sccb_check_status(gspca_dev))
-		err("sccb_reg_read failed 1");
+		pr_err("sccb_reg_read failed 1\n");
 
 	ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
 	if (!sccb_check_status(gspca_dev))
-		err("sccb_reg_read failed 2");
+		pr_err("sccb_reg_read failed 2\n");
 
 	return ov534_reg_read(gspca_dev, OV534_REG_READ);
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/pac207.c linux-libre-3.2-gnu/drivers/media/video/gspca/pac207.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/pac207.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/pac207.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "pac207"
 
 #include <linux/input.h>
@@ -178,8 +180,8 @@
 			0x00, index,
 			gspca_dev->usb_buf, length, PAC207_CTRL_TIMEOUT);
 	if (err < 0)
-		err("Failed to write registers to index 0x%04X, error %d)",
-			index, err);
+		pr_err("Failed to write registers to index 0x%04X, error %d\n",
+		       index, err);
 
 	return err;
 }
@@ -194,8 +196,8 @@
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
 			value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
 	if (err)
-		err("Failed to write a register (index 0x%04X,"
-			" value 0x%02X, error %d)", index, value, err);
+		pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n",
+		       index, value, err);
 
 	return err;
 }
@@ -210,8 +212,8 @@
 			0x00, index,
 			gspca_dev->usb_buf, 1, PAC207_CTRL_TIMEOUT);
 	if (res < 0) {
-		err("Failed to read a register (index 0x%04X, error %d)",
-			index, res);
+		pr_err("Failed to read a register (index 0x%04X, error %d)\n",
+		       index, res);
 		return res;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/pac7302.c linux-libre-3.2-gnu/drivers/media/video/gspca/pac7302.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/pac7302.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/pac7302.c	2012-01-04 18:55:44.000000000 -0500
@@ -61,6 +61,8 @@
     3   | 0x21       | sethvflip()
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "pac7302"
 
 #include <linux/input.h>
@@ -408,8 +410,8 @@
 			index, gspca_dev->usb_buf, len,
 			500);
 	if (ret < 0) {
-		err("reg_w_buf failed index 0x%02x, error %d",
-			index, ret);
+		pr_err("reg_w_buf failed index 0x%02x, error %d\n",
+		       index, ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -431,8 +433,8 @@
 			0, index, gspca_dev->usb_buf, 1,
 			500);
 	if (ret < 0) {
-		err("reg_w() failed index 0x%02x, value 0x%02x, error %d",
-			index, value, ret);
+		pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
+		       index, value, ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -466,9 +468,8 @@
 				0, index, gspca_dev->usb_buf, 1,
 				500);
 		if (ret < 0) {
-			err("reg_w_page() failed index 0x%02x, "
-			"value 0x%02x, error %d",
-				index, page[index], ret);
+			pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
+			       index, page[index], ret);
 			gspca_dev->usb_err = ret;
 			break;
 		}
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/pac7311.c linux-libre-3.2-gnu/drivers/media/video/gspca/pac7311.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/pac7311.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/pac7311.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,6 +49,8 @@
 		for max gain, 0x14 for minimal gain.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "pac7311"
 
 #include <linux/input.h>
@@ -276,8 +278,8 @@
 			index, gspca_dev->usb_buf, len,
 			500);
 	if (ret < 0) {
-		err("reg_w_buf() failed index 0x%02x, error %d",
-			index, ret);
+		pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
+		       index, ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -299,8 +301,8 @@
 			0, index, gspca_dev->usb_buf, 1,
 			500);
 	if (ret < 0) {
-		err("reg_w() failed index 0x%02x, value 0x%02x, error %d",
-			index, value, ret);
+		pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
+		       index, value, ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -334,9 +336,8 @@
 				0, index, gspca_dev->usb_buf, 1,
 				500);
 		if (ret < 0) {
-			err("reg_w_page() failed index 0x%02x, "
-			"value 0x%02x, error %d",
-				index, page[index], ret);
+			pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
+			       index, page[index], ret);
 			gspca_dev->usb_err = ret;
 			break;
 		}
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/se401.c linux-libre-3.2-gnu/drivers/media/video/gspca/se401.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/se401.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/se401.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "se401"
 
 #define BULK_SIZE 4096
@@ -144,8 +146,8 @@
 			      value, 0, NULL, 0, 1000);
 	if (err < 0) {
 		if (!silent)
-			err("write req failed req %#04x val %#04x error %d",
-			    req, value, err);
+			pr_err("write req failed req %#04x val %#04x error %d\n",
+			       req, value, err);
 		gspca_dev->usb_err = err;
 	}
 }
@@ -158,7 +160,7 @@
 		return;
 
 	if (USB_BUF_SZ < READ_REQ_SIZE) {
-		err("USB_BUF_SZ too small!!");
+		pr_err("USB_BUF_SZ too small!!\n");
 		gspca_dev->usb_err = -ENOBUFS;
 		return;
 	}
@@ -169,7 +171,8 @@
 			      0, 0, gspca_dev->usb_buf, READ_REQ_SIZE, 1000);
 	if (err < 0) {
 		if (!silent)
-			err("read req failed req %#04x error %d", req, err);
+			pr_err("read req failed req %#04x error %d\n",
+			       req, err);
 		gspca_dev->usb_err = err;
 	}
 }
@@ -188,8 +191,8 @@
 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			      param, selector, NULL, 0, 1000);
 	if (err < 0) {
-		err("set feature failed sel %#04x param %#04x error %d",
-		    selector, param, err);
+		pr_err("set feature failed sel %#04x param %#04x error %d\n",
+		       selector, param, err);
 		gspca_dev->usb_err = err;
 	}
 }
@@ -202,7 +205,7 @@
 		return gspca_dev->usb_err;
 
 	if (USB_BUF_SZ < 2) {
-		err("USB_BUF_SZ too small!!");
+		pr_err("USB_BUF_SZ too small!!\n");
 		gspca_dev->usb_err = -ENOBUFS;
 		return gspca_dev->usb_err;
 	}
@@ -213,7 +216,8 @@
 			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			      0, selector, gspca_dev->usb_buf, 2, 1000);
 	if (err < 0) {
-		err("get feature failed sel %#04x error %d", selector, err);
+		pr_err("get feature failed sel %#04x error %d\n",
+		       selector, err);
 		gspca_dev->usb_err = err;
 		return err;
 	}
@@ -300,21 +304,21 @@
 		return gspca_dev->usb_err;
 
 	if (cd[1] != 0x41) {
-		err("Wrong descriptor type");
+		pr_err("Wrong descriptor type\n");
 		return -ENODEV;
 	}
 
 	if (!(cd[2] & SE401_FORMAT_BAYER)) {
-		err("Bayer format not supported!");
+		pr_err("Bayer format not supported!\n");
 		return -ENODEV;
 	}
 
 	if (cd[3])
-		info("ExtraFeatures: %d", cd[3]);
+		pr_info("ExtraFeatures: %d\n", cd[3]);
 
 	n = cd[4] | (cd[5] << 8);
 	if (n > MAX_MODES) {
-		err("Too many frame sizes");
+		pr_err("Too many frame sizes\n");
 		return -ENODEV;
 	}
 
@@ -353,15 +357,16 @@
 			sd->fmts[i].pixelformat = V4L2_PIX_FMT_SBGGR8;
 			sd->fmts[i].bytesperline = widths[i];
 			sd->fmts[i].sizeimage = widths[i] * heights[i];
-			info("Frame size: %dx%d bayer", widths[i], heights[i]);
+			pr_info("Frame size: %dx%d bayer\n",
+				widths[i], heights[i]);
 		} else {
 			/* Found a match use janggu compression */
 			sd->fmts[i].pixelformat = V4L2_PIX_FMT_SE401;
 			sd->fmts[i].bytesperline = 0;
 			sd->fmts[i].sizeimage = widths[i] * heights[i] * 3;
-			info("Frame size: %dx%d 1/%dth janggu",
-			     widths[i], heights[i],
-			     sd->fmts[i].priv * sd->fmts[i].priv);
+			pr_info("Frame size: %dx%d 1/%dth janggu\n",
+				widths[i], heights[i],
+				sd->fmts[i].priv * sd->fmts[i].priv);
 		}
 	}
 
@@ -571,11 +576,12 @@
 		plen   = ((bits + 47) >> 4) << 1;
 		/* Sanity checks */
 		if (plen > 1024) {
-			err("invalid packet len %d restarting stream", plen);
+			pr_err("invalid packet len %d restarting stream\n",
+			       plen);
 			goto error;
 		}
 		if (info == 3) {
-			err("unknown frame info value restarting stream");
+			pr_err("unknown frame info value restarting stream\n");
 			goto error;
 		}
 
@@ -599,8 +605,8 @@
 			break;
 		case 1: /* EOF */
 			if (sd->pixels_read != imagesize) {
-				err("frame size %d expected %d",
-				    sd->pixels_read, imagesize);
+				pr_err("frame size %d expected %d\n",
+				       sd->pixels_read, imagesize);
 				goto error;
 			}
 			sd_complete_frame(gspca_dev, sd->packet, plen);
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/sn9c2028.c linux-libre-3.2-gnu/drivers/media/video/gspca/sn9c2028.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/sn9c2028.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/sn9c2028.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "sn9c2028"
 
 #include "gspca.h"
@@ -75,8 +77,8 @@
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
 			2, 0, gspca_dev->usb_buf, 6, 500);
 	if (rc < 0) {
-		err("command write [%02x] error %d",
-				gspca_dev->usb_buf[0], rc);
+		pr_err("command write [%02x] error %d\n",
+		       gspca_dev->usb_buf[0], rc);
 		return rc;
 	}
 
@@ -93,7 +95,7 @@
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
 			1, 0, gspca_dev->usb_buf, 1, 500);
 	if (rc != 1) {
-		err("read1 error %d", rc);
+		pr_err("read1 error %d\n", rc);
 		return (rc < 0) ? rc : -EIO;
 	}
 	PDEBUG(D_USBI, "read1 response %02x", gspca_dev->usb_buf[0]);
@@ -109,7 +111,7 @@
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
 			4, 0, gspca_dev->usb_buf, 4, 500);
 	if (rc != 4) {
-		err("read4 error %d", rc);
+		pr_err("read4 error %d\n", rc);
 		return (rc < 0) ? rc : -EIO;
 	}
 	memcpy(reading, gspca_dev->usb_buf, 4);
@@ -131,7 +133,7 @@
 	for (i = 0; i < 256 && status < 2; i++)
 		status = sn9c2028_read1(gspca_dev);
 	if (status != 2) {
-		err("long command status read error %d", status);
+		pr_err("long command status read error %d\n", status);
 		return (status < 0) ? status : -EIO;
 	}
 
@@ -638,7 +640,7 @@
 		err_code = start_vivitar_cam(gspca_dev);
 		break;
 	default:
-		err("Starting unknown camera, please report this");
+		pr_err("Starting unknown camera, please report this\n");
 		return -ENXIO;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/sn9c20x.c linux-libre-3.2-gnu/drivers/media/video/gspca/sn9c20x.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/sn9c20x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/sn9c20x.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/input.h>
 
 #include "gspca.h"
@@ -1123,7 +1125,7 @@
 			length,
 			500);
 	if (unlikely(result < 0 || result != length)) {
-		err("Read register failed 0x%02X", reg);
+		pr_err("Read register failed 0x%02X\n", reg);
 		return -EIO;
 	}
 	return 0;
@@ -1144,7 +1146,7 @@
 			length,
 			500);
 	if (unlikely(result < 0 || result != length)) {
-		err("Write register failed index 0x%02X", reg);
+		pr_err("Write register failed index 0x%02X\n", reg);
 		return -EIO;
 	}
 	return 0;
@@ -1275,14 +1277,14 @@
 		return -EINVAL;
 
 	if (id != 0x7fa2) {
-		err("sensor id for ov9650 doesn't match (0x%04x)", id);
+		pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id);
 		return -ENODEV;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
 		if (i2c_w1(gspca_dev, ov9650_init[i].reg,
 				ov9650_init[i].val) < 0) {
-			err("OV9650 sensor initialization failed");
+			pr_err("OV9650 sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -1299,7 +1301,7 @@
 	for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
 		if (i2c_w1(gspca_dev, ov9655_init[i].reg,
 				ov9655_init[i].val) < 0) {
-			err("OV9655 sensor initialization failed");
+			pr_err("OV9655 sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -1318,7 +1320,7 @@
 	for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
 		if (i2c_w1(gspca_dev, soi968_init[i].reg,
 				soi968_init[i].val) < 0) {
-			err("SOI968 sensor initialization failed");
+			pr_err("SOI968 sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -1338,7 +1340,7 @@
 	for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
 		if (i2c_w1(gspca_dev, ov7660_init[i].reg,
 				ov7660_init[i].val) < 0) {
-			err("OV7660 sensor initialization failed");
+			pr_err("OV7660 sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -1355,7 +1357,7 @@
 	for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
 		if (i2c_w1(gspca_dev, ov7670_init[i].reg,
 				ov7670_init[i].val) < 0) {
-			err("OV7670 sensor initialization failed");
+			pr_err("OV7670 sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -1379,14 +1381,14 @@
 		for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
 			if (i2c_w2(gspca_dev, mt9v011_init[i].reg,
 					mt9v011_init[i].val) < 0) {
-				err("MT9V011 sensor initialization failed");
+				pr_err("MT9V011 sensor initialization failed\n");
 				return -ENODEV;
 			}
 		}
 		sd->hstart = 2;
 		sd->vstart = 2;
 		sd->sensor = SENSOR_MT9V011;
-		info("MT9V011 sensor detected");
+		pr_info("MT9V011 sensor detected\n");
 		return 0;
 	}
 
@@ -1397,7 +1399,7 @@
 		for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
 			if (i2c_w2(gspca_dev, mt9v111_init[i].reg,
 					mt9v111_init[i].val) < 0) {
-				err("MT9V111 sensor initialization failed");
+				pr_err("MT9V111 sensor initialization failed\n");
 				return -ENODEV;
 			}
 		}
@@ -1407,7 +1409,7 @@
 		sd->hstart = 2;
 		sd->vstart = 2;
 		sd->sensor = SENSOR_MT9V111;
-		info("MT9V111 sensor detected");
+		pr_info("MT9V111 sensor detected\n");
 		return 0;
 	}
 
@@ -1422,14 +1424,14 @@
 		for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
 			if (i2c_w2(gspca_dev, mt9v112_init[i].reg,
 					mt9v112_init[i].val) < 0) {
-				err("MT9V112 sensor initialization failed");
+				pr_err("MT9V112 sensor initialization failed\n");
 				return -ENODEV;
 			}
 		}
 		sd->hstart = 6;
 		sd->vstart = 2;
 		sd->sensor = SENSOR_MT9V112;
-		info("MT9V112 sensor detected");
+		pr_info("MT9V112 sensor detected\n");
 		return 0;
 	}
 
@@ -1443,7 +1445,7 @@
 	for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) {
 		if (i2c_w2(gspca_dev, mt9m112_init[i].reg,
 				mt9m112_init[i].val) < 0) {
-			err("MT9M112 sensor initialization failed");
+			pr_err("MT9M112 sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -1461,7 +1463,7 @@
 	for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
 		if (i2c_w2(gspca_dev, mt9m111_init[i].reg,
 				mt9m111_init[i].val) < 0) {
-			err("MT9M111 sensor initialization failed");
+			pr_err("MT9M111 sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -1485,20 +1487,20 @@
 	switch (id) {
 	case 0x8411:
 	case 0x8421:
-		info("MT9M001 color sensor detected");
+		pr_info("MT9M001 color sensor detected\n");
 		break;
 	case 0x8431:
-		info("MT9M001 mono sensor detected");
+		pr_info("MT9M001 mono sensor detected\n");
 		break;
 	default:
-		err("No MT9M001 chip detected, ID = %x\n", id);
+		pr_err("No MT9M001 chip detected, ID = %x\n\n", id);
 		return -ENODEV;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
 		if (i2c_w2(gspca_dev, mt9m001_init[i].reg,
 				mt9m001_init[i].val) < 0) {
-			err("MT9M001 sensor initialization failed");
+			pr_err("MT9M001 sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -1517,7 +1519,7 @@
 	for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
 		if (i2c_w1(gspca_dev, hv7131r_init[i].reg,
 				hv7131r_init[i].val) < 0) {
-			err("HV7131R Sensor initialization failed");
+			pr_err("HV7131R Sensor initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -2103,7 +2105,7 @@
 	for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
 		value = bridge_init[i][1];
 		if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) {
-			err("Device initialization failed");
+			pr_err("Device initialization failed\n");
 			return -ENODEV;
 		}
 	}
@@ -2114,7 +2116,7 @@
 		reg_w1(gspca_dev, 0x1006, 0x20);
 
 	if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) {
-		err("Device initialization failed");
+		pr_err("Device initialization failed\n");
 		return -ENODEV;
 	}
 
@@ -2122,27 +2124,27 @@
 	case SENSOR_OV9650:
 		if (ov9650_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("OV9650 sensor detected");
+		pr_info("OV9650 sensor detected\n");
 		break;
 	case SENSOR_OV9655:
 		if (ov9655_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("OV9655 sensor detected");
+		pr_info("OV9655 sensor detected\n");
 		break;
 	case SENSOR_SOI968:
 		if (soi968_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("SOI968 sensor detected");
+		pr_info("SOI968 sensor detected\n");
 		break;
 	case SENSOR_OV7660:
 		if (ov7660_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("OV7660 sensor detected");
+		pr_info("OV7660 sensor detected\n");
 		break;
 	case SENSOR_OV7670:
 		if (ov7670_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("OV7670 sensor detected");
+		pr_info("OV7670 sensor detected\n");
 		break;
 	case SENSOR_MT9VPRB:
 		if (mt9v_init_sensor(gspca_dev) < 0)
@@ -2151,12 +2153,12 @@
 	case SENSOR_MT9M111:
 		if (mt9m111_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("MT9M111 sensor detected");
+		pr_info("MT9M111 sensor detected\n");
 		break;
 	case SENSOR_MT9M112:
 		if (mt9m112_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("MT9M112 sensor detected");
+		pr_info("MT9M112 sensor detected\n");
 		break;
 	case SENSOR_MT9M001:
 		if (mt9m001_init_sensor(gspca_dev) < 0)
@@ -2165,10 +2167,10 @@
 	case SENSOR_HV7131R:
 		if (hv7131r_init_sensor(gspca_dev) < 0)
 			return -ENODEV;
-		info("HV7131R sensor detected");
+		pr_info("HV7131R sensor detected\n");
 		break;
 	default:
-		info("Unsupported Sensor");
+		pr_info("Unsupported Sensor\n");
 		return -ENODEV;
 	}
 
@@ -2263,19 +2265,19 @@
 	switch (mode & SCALE_MASK) {
 	case SCALE_1280x1024:
 		scale = 0xc0;
-		info("Set 1280x1024");
+		pr_info("Set 1280x1024\n");
 		break;
 	case SCALE_640x480:
 		scale = 0x80;
-		info("Set 640x480");
+		pr_info("Set 640x480\n");
 		break;
 	case SCALE_320x240:
 		scale = 0x90;
-		info("Set 320x240");
+		pr_info("Set 320x240\n");
 		break;
 	case SCALE_160x120:
 		scale = 0xa0;
-		info("Set 160x120");
+		pr_info("Set 160x120\n");
 		break;
 	}
 
@@ -2513,7 +2515,7 @@
 	{USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
 	{USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
 	{USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
-	{USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)},
+	{USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
 	{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)},
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/sonixj.c linux-libre-3.2-gnu/drivers/media/video/gspca/sonixj.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/sonixj.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/sonixj.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver
  *
- * Copyright (C) 2009-2010 Jean-FranÃ§ois Moine <http://moinejf.free.fr>
+ * Copyright (C) 2009-2011 Jean-FranÃ§ois Moine <http://moinejf.free.fr>
  * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
  *
  * This program is free software; you can redistribute it and/or modify
@@ -19,6 +19,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "sonixj"
 
 #include <linux/input.h>
@@ -136,7 +138,7 @@
 static void setfreq(struct gspca_dev *gspca_dev);
 
 static const struct ctrl sd_ctrls[NCTRLS] = {
-[BRIGHTNESS] =  {
+[BRIGHTNESS] = {
 	    {
 		.id      = V4L2_CID_BRIGHTNESS,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -157,7 +159,7 @@
 #define CONTRAST_MAX 127
 		.maximum = CONTRAST_MAX,
 		.step    = 1,
-		.default_value = 63,
+		.default_value = 20,
 	    },
 	    .set_control = setcontrast
 	},
@@ -737,7 +739,7 @@
 	{0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
 	{0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
 	{0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
-	{0xd1, 0x5d, 0x2f, 0xf7, 0xB0, 0x00, 0x04, 0x10},
+	{0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},
 	{0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
 	{0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
 	{0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
@@ -1277,7 +1279,7 @@
 			/* global gain ? : 07 - change with 0x15 at the end */
 	{0xa1, 0x21, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x10}, /* ???? : 063f */
 	{0xa1, 0x21, 0x04, 0x06, 0x00, 0x00, 0x00, 0x10},
-	{0xb1, 0x21, 0x2d, 0x00, 0x02, 0x00, 0x00, 0x10},
+	{0xb1, 0x21, 0x2d, 0x63, 0x03, 0x00, 0x00, 0x10},
 			/* exposure ? : 0200 - change with 0x1e at the end */
 	{}
 };
@@ -1395,7 +1397,7 @@
 		return;
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		err("reg_r: buffer overflow");
+		pr_err("reg_r: buffer overflow\n");
 		return;
 	}
 #endif
@@ -1408,7 +1410,7 @@
 			500);
 	PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
 	if (ret < 0) {
-		err("reg_r err %d", ret);
+		pr_err("reg_r err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -1432,7 +1434,7 @@
 			gspca_dev->usb_buf, 1,
 			500);
 	if (ret < 0) {
-		err("reg_w1 err %d", ret);
+		pr_err("reg_w1 err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -1449,7 +1451,7 @@
 		value, buffer[0], buffer[1]);
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		err("reg_w: buffer overflow");
+		pr_err("reg_w: buffer overflow\n");
 		return;
 	}
 #endif
@@ -1462,7 +1464,7 @@
 			gspca_dev->usb_buf, len,
 			500);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -1502,7 +1504,7 @@
 			gspca_dev->usb_buf, 8,
 			500);
 	if (ret < 0) {
-		err("i2c_w1 err %d", ret);
+		pr_err("i2c_w1 err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -1527,7 +1529,7 @@
 			500);
 	msleep(2);
 	if (ret < 0) {
-		err("i2c_w8 err %d", ret);
+		pr_err("i2c_w8 err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -1591,7 +1593,7 @@
 		PDEBUG(D_PROBE, "Sensor HV7131R found");
 		return;
 	}
-	warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x",
+	pr_warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x\n",
 		gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
 		gspca_dev->usb_buf[2]);
 }
@@ -1710,7 +1712,7 @@
 		sd->sensor = SENSOR_PO1030;
 		return;
 	}
-	err("Unknown sensor %04x", val);
+	pr_err("Unknown sensor %04x\n", val);
 }
 
 /* 0c45:6142 sensor may be po2030n, gc0305 or gc0307 */
@@ -1748,7 +1750,7 @@
 		PDEBUG(D_PROBE, "Sensor po2030n");
 /*		sd->sensor = SENSOR_PO2030N; */
 	} else {
-		err("Unknown sensor ID %04x", val);
+		pr_err("Unknown sensor ID %04x\n", val);
 	}
 }
 
@@ -2006,8 +2008,7 @@
 	case SENSOR_OM6802:
 		expo = brightness << 2;
 		sd->exposure = setexposure(gspca_dev, expo);
-		k2 = brightness >> 3;
-		break;
+		return;			/* Y offset already set */
 	}
 
 	reg_w1(gspca_dev, 0x96, k2);	/* color matrix Y offset */
@@ -2019,13 +2020,13 @@
 	u8 k2;
 	u8 contrast[6];
 
-	k2 = sd->ctrls[CONTRAST].val * 0x30 / (CONTRAST_MAX + 1)
-				+ 0x10;		/* 10..40 */
+	k2 = sd->ctrls[CONTRAST].val * 37 / (CONTRAST_MAX + 1)
+				+ 37;		/* 37..73 */
 	contrast[0] = (k2 + 1) / 2;		/* red */
 	contrast[1] = 0;
 	contrast[2] = k2;			/* green */
 	contrast[3] = 0;
-	contrast[4] = (k2 + 1) / 5;		/* blue */
+	contrast[4] = k2 / 5;			/* blue */
 	contrast[5] = 0;
 	reg_w(gspca_dev, 0x84, contrast, sizeof contrast);
 }
@@ -2507,9 +2508,7 @@
 		break;
 	case SENSOR_HV7131R:
 	case SENSOR_MI0360:
-		if (mode)
-			reg01 |= SYS_SEL_48M;	/* 320x240: clk 48Mhz */
-		else
+		if (!mode)
 			reg01 &= ~SYS_SEL_48M;	/* 640x480: clk 24Mhz */
 		reg17 &= ~MCK_SIZE_MASK;
 		reg17 |= 0x01;			/* clock / 1 */
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/spca1528.c linux-libre-3.2-gnu/drivers/media/video/gspca/spca1528.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/spca1528.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/spca1528.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * spca1528 subdriver
  *
- * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
+ * Copyright (C) 2010-2011 Jean-Francois Moine (http://moinejf.free.fr)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "spca1528"
 
 #include "gspca.h"
@@ -171,7 +173,7 @@
 	PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", req, index,
 			 gspca_dev->usb_buf[0]);
 	if (ret < 0) {
-		err("reg_r err %d", ret);
+		pr_err("reg_r err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -193,7 +195,7 @@
 			value, index,
 			NULL, 0, 500);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -217,21 +219,23 @@
 			value, index,
 			gspca_dev->usb_buf, 1, 500);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
 
 static void wait_status_0(struct gspca_dev *gspca_dev)
 {
-	int i;
+	int i, w;
 
-	i = 20;
+	i = 16;
+	w = 0;
 	do {
 		reg_r(gspca_dev, 0x21, 0x0000, 1);
 		if (gspca_dev->usb_buf[0] == 0)
 			return;
-		msleep(30);
+		w += 15;
+		msleep(w);
 	} while (--i > 0);
 	PDEBUG(D_ERR, "wait_status_0 timeout");
 	gspca_dev->usb_err = -ETIME;
@@ -307,8 +311,6 @@
 	sd->color = COLOR_DEF;
 	sd->sharpness = SHARPNESS_DEF;
 
-	gspca_dev->nbalt = 4;		/* use alternate setting 3 */
-
 	return 0;
 }
 
@@ -347,8 +349,12 @@
 	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
 	reg_wb(gspca_dev, 0x25, 0x0000, 0x0004, mode);
 	reg_r(gspca_dev, 0x25, 0x0004, 1);
-	reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06);
+	reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06);	/* 420 */
 	reg_r(gspca_dev, 0x27, 0x0000, 1);
+
+/* not useful..
+	gspca_dev->alt = 4;		* use alternate setting 3 */
+
 	return gspca_dev->usb_err;
 }
 
@@ -361,8 +367,8 @@
 	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
 			0x22);		/* JPEG 411 */
 
-	/* the JPEG quality seems to be 82% */
-	jpeg_set_qual(sd->jpeg_hdr, 82);
+	/* the JPEG quality shall be 85% */
+	jpeg_set_qual(sd->jpeg_hdr, 85);
 
 	/* set the controls */
 	setbrightness(gspca_dev);
@@ -377,7 +383,7 @@
 
 	/* start the capture */
 	wait_status_0(gspca_dev);
-	reg_w(gspca_dev, 0x31, 0x0000, 0x0004);
+	reg_w(gspca_dev, 0x31, 0x0000, 0x0004);	/* start request */
 	wait_status_1(gspca_dev);
 	wait_status_0(gspca_dev);
 	msleep(200);
@@ -390,7 +396,7 @@
 {
 	/* stop the capture */
 	wait_status_0(gspca_dev);
-	reg_w(gspca_dev, 0x31, 0x0000, 0x0000);
+	reg_w(gspca_dev, 0x31, 0x0000, 0x0000);	/* stop request */
 	wait_status_1(gspca_dev);
 	wait_status_0(gspca_dev);
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/spca500.c linux-libre-3.2-gnu/drivers/media/video/gspca/spca500.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/spca500.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/spca500.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "spca500"
 
 #include "gspca.h"
@@ -396,7 +398,7 @@
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			value, index, NULL, 0, 500);
 	if (ret < 0)
-		err("reg write: error %d", ret);
+		pr_err("reg write: error %d\n", ret);
 	return ret;
 }
 
@@ -418,7 +420,7 @@
 			gspca_dev->usb_buf, length,
 			500);		/* timeout */
 	if (ret < 0) {
-		err("reg_r_12 err %d", ret);
+		pr_err("reg_r_12 err %d\n", ret);
 		return ret;
 	}
 	return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/spca501.c linux-libre-3.2-gnu/drivers/media/video/gspca/spca501.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/spca501.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/spca501.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "spca501"
 
 #include "gspca.h"
@@ -1852,7 +1854,7 @@
 	PDEBUG(D_USBO, "reg write: 0x%02x 0x%02x 0x%02x",
 		req, index, value);
 	if (ret < 0)
-		err("reg write: error %d", ret);
+		pr_err("reg write: error %d\n", ret);
 	return ret;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/spca505.c linux-libre-3.2-gnu/drivers/media/video/gspca/spca505.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/spca505.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/spca505.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "spca505"
 
 #include "gspca.h"
@@ -578,7 +580,7 @@
 	PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
 		req, index, value, ret);
 	if (ret < 0)
-		err("reg write: error %d", ret);
+		pr_err("reg write: error %d\n", ret);
 	return ret;
 }
 
@@ -685,8 +687,8 @@
 		return ret;
 	}
 	if (ret != 0x0101) {
-		err("After vector read returns 0x%04x should be 0x0101",
-			ret);
+		pr_err("After vector read returns 0x%04x should be 0x0101\n",
+		       ret);
 	}
 
 	ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a);
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/spca508.c linux-libre-3.2-gnu/drivers/media/video/gspca/spca508.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/spca508.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/spca508.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "spca508"
 
 #include "gspca.h"
@@ -1275,7 +1277,7 @@
 	PDEBUG(D_USBO, "reg write i:0x%04x = 0x%02x",
 		index, value);
 	if (ret < 0)
-		err("reg write: error %d", ret);
+		pr_err("reg write: error %d\n", ret);
 	return ret;
 }
 
@@ -1297,7 +1299,7 @@
 	PDEBUG(D_USBI, "reg read i:%04x --> %02x",
 		index, gspca_dev->usb_buf[0]);
 	if (ret < 0) {
-		err("reg_read err %d", ret);
+		pr_err("reg_read err %d\n", ret);
 		return ret;
 	}
 	return gspca_dev->usb_buf[0];
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/spca561.c linux-libre-3.2-gnu/drivers/media/video/gspca/spca561.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/spca561.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/spca561.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "spca561"
 
 #include <linux/input.h>
@@ -315,7 +317,7 @@
 			      value, index, NULL, 0, 500);
 	PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
 	if (ret < 0)
-		err("reg write: error %d", ret);
+		pr_err("reg write: error %d\n", ret);
 }
 
 static void write_vector(struct gspca_dev *gspca_dev,
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/sq905.c linux-libre-3.2-gnu/drivers/media/video/gspca/sq905.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/sq905.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/sq905.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,6 +33,8 @@
  * drivers.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "sq905"
 
 #include <linux/workqueue.h>
@@ -123,8 +125,7 @@
 			      SQ905_COMMAND, index, gspca_dev->usb_buf, 1,
 			      SQ905_CMD_TIMEOUT);
 	if (ret < 0) {
-		err("%s: usb_control_msg failed (%d)",
-			__func__, ret);
+		pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
 		return ret;
 	}
 
@@ -135,8 +136,7 @@
 			      SQ905_PING, 0, gspca_dev->usb_buf, 1,
 			      SQ905_CMD_TIMEOUT);
 	if (ret < 0) {
-		err("%s: usb_control_msg failed 2 (%d)",
-			__func__, ret);
+		pr_err("%s: usb_control_msg failed 2 (%d)\n", __func__, ret);
 		return ret;
 	}
 
@@ -158,7 +158,7 @@
 			      SQ905_READ_DONE, 0, gspca_dev->usb_buf, 1,
 			      SQ905_CMD_TIMEOUT);
 	if (ret < 0) {
-		err("%s: usb_control_msg failed (%d)", __func__, ret);
+		pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
 		return ret;
 	}
 
@@ -186,7 +186,7 @@
 	if (need_lock)
 		mutex_unlock(&gspca_dev->usb_lock);
 	if (ret < 0) {
-		err("%s: usb_control_msg failed (%d)", __func__, ret);
+		pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
 		return ret;
 	}
 	ret = usb_bulk_msg(gspca_dev->dev,
@@ -195,8 +195,7 @@
 
 	/* successful, it returns 0, otherwise  negative */
 	if (ret < 0 || act_len != size) {
-		err("bulk read fail (%d) len %d/%d",
-			ret, act_len, size);
+		pr_err("bulk read fail (%d) len %d/%d\n", ret, act_len, size);
 		return -EIO;
 	}
 	return 0;
@@ -226,7 +225,7 @@
 
 	buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
 	if (!buffer) {
-		err("Couldn't allocate USB buffer");
+		pr_err("Couldn't allocate USB buffer\n");
 		goto quit_stream;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/sq905c.c linux-libre-3.2-gnu/drivers/media/video/gspca/sq905c.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/sq905c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/sq905c.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,8 @@
  * and may contain code fragments from it.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "sq905c"
 
 #include <linux/workqueue.h>
@@ -95,8 +97,7 @@
 			      command, index, NULL, 0,
 			      SQ905C_CMD_TIMEOUT);
 	if (ret < 0) {
-		err("%s: usb_control_msg failed (%d)",
-			__func__, ret);
+		pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
 		return ret;
 	}
 
@@ -115,8 +116,7 @@
 			      command, index, gspca_dev->usb_buf, size,
 			      SQ905C_CMD_TIMEOUT);
 	if (ret < 0) {
-		err("%s: usb_control_msg failed (%d)",
-		       __func__, ret);
+		pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
 		return ret;
 	}
 
@@ -146,7 +146,7 @@
 
 	buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
 	if (!buffer) {
-		err("Couldn't allocate USB buffer");
+		pr_err("Couldn't allocate USB buffer\n");
 		goto quit_stream;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/sq930x.c linux-libre-3.2-gnu/drivers/media/video/gspca/sq930x.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/sq930x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/sq930x.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "sq930x"
 
 #include "gspca.h"
@@ -468,7 +470,7 @@
 			value, 0, gspca_dev->usb_buf, len,
 			500);
 	if (ret < 0) {
-		err("reg_r %04x failed %d", value, ret);
+		pr_err("reg_r %04x failed %d\n", value, ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -488,7 +490,7 @@
 			500);
 	msleep(30);
 	if (ret < 0) {
-		err("reg_w %04x %04x failed %d", value, index, ret);
+		pr_err("reg_w %04x %04x failed %d\n", value, index, ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -511,7 +513,7 @@
 			1000);
 	msleep(30);
 	if (ret < 0) {
-		err("reg_wb %04x %04x failed %d", value, index, ret);
+		pr_err("reg_wb %04x %04x failed %d\n", value, index, ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -556,7 +558,7 @@
 			gspca_dev->usb_buf, buf - gspca_dev->usb_buf,
 			500);
 	if (ret < 0) {
-		err("i2c_write failed %d", ret);
+		pr_err("i2c_write failed %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -575,7 +577,7 @@
 
 #ifdef GSPCA_DEBUG
 	if ((batchsize - 1) * 3 > USB_BUF_SZ) {
-		err("Bug: usb_buf overflow");
+		pr_err("Bug: usb_buf overflow\n");
 		gspca_dev->usb_err = -ENOMEM;
 		return;
 	}
@@ -612,7 +614,7 @@
 				gspca_dev->usb_buf, buf - gspca_dev->usb_buf,
 				500);
 		if (ret < 0) {
-			err("ucbus_write failed %d", ret);
+			pr_err("ucbus_write failed %d\n", ret);
 			gspca_dev->usb_err = ret;
 			return;
 		}
@@ -688,7 +690,7 @@
 			break;
 	}
 	if (i >= ARRAY_SIZE(probe_order)) {
-		err("Unknown sensor");
+		pr_err("Unknown sensor\n");
 		gspca_dev->usb_err = -EINVAL;
 		return;
 	}
@@ -696,7 +698,8 @@
 	switch (sd->sensor) {
 	case SENSOR_OV7660:
 	case SENSOR_OV9630:
-		err("Sensor %s not yet treated", sensor_tb[sd->sensor].name);
+		pr_err("Sensor %s not yet treated\n",
+		       sensor_tb[sd->sensor].name);
 		gspca_dev->usb_err = -EINVAL;
 		break;
 	}
@@ -1091,7 +1094,7 @@
 	gspca_dev->cam.bulk_nurbs = 1;
 	ret = usb_submit_urb(gspca_dev->urb[0], GFP_ATOMIC);
 	if (ret < 0)
-		err("sd_dq_callback() err %d", ret);
+		pr_err("sd_dq_callback() err %d\n", ret);
 
 	/* wait a little time, otherwise the webcam crashes */
 	msleep(100);
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/stk014.c linux-libre-3.2-gnu/drivers/media/video/gspca/stk014.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/stk014.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/stk014.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "stk014"
 
 #include "gspca.h"
@@ -137,7 +139,7 @@
 			gspca_dev->usb_buf, 1,
 			500);
 	if (ret < 0) {
-		err("reg_r err %d", ret);
+		pr_err("reg_r err %d\n", ret);
 		gspca_dev->usb_err = ret;
 		return 0;
 	}
@@ -162,7 +164,7 @@
 			0,
 			500);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -192,7 +194,7 @@
 			&alen,
 			500);		/* timeout in milliseconds */
 	if (ret < 0) {
-		err("rcv_val err %d", ret);
+		pr_err("rcv_val err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -235,7 +237,7 @@
 			&alen,
 			500);	/* timeout in milliseconds */
 	if (ret < 0) {
-		err("snd_val err %d", ret);
+		pr_err("snd_val err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	} else {
 		if (ads == 0x003f08) {
@@ -315,7 +317,7 @@
 	ret = reg_r(gspca_dev, 0x0740);
 	if (gspca_dev->usb_err >= 0) {
 		if (ret != 0xff) {
-			err("init reg: 0x%02x", ret);
+			pr_err("init reg: 0x%02x\n", ret);
 			gspca_dev->usb_err = -EIO;
 		}
 	}
@@ -349,8 +351,8 @@
 					gspca_dev->iface,
 					gspca_dev->alt);
 	if (ret < 0) {
-		err("set intf %d %d failed",
-			gspca_dev->iface, gspca_dev->alt);
+		pr_err("set intf %d %d failed\n",
+		       gspca_dev->iface, gspca_dev->alt);
 		gspca_dev->usb_err = ret;
 		goto out;
 	}
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/stv0680.c linux-libre-3.2-gnu/drivers/media/video/gspca/stv0680.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/stv0680.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/stv0680.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "stv0680"
 
 #include "gspca.h"
@@ -79,7 +81,7 @@
 			      val, 0, gspca_dev->usb_buf, size, 500);
 
 	if ((ret < 0) && (req != 0x0a))
-		err("usb_control_msg error %i, request = 0x%x, error = %i",
+		pr_err("usb_control_msg error %i, request = 0x%x, error = %i\n",
 		       set, req, ret);
 
 	return ret;
@@ -236,7 +238,7 @@
 
 	if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0100, 0x12) != 0x12 ||
 	    gspca_dev->usb_buf[8] != 0x53 || gspca_dev->usb_buf[9] != 0x05) {
-		err("Could not get descriptor 0100.");
+		pr_err("Could not get descriptor 0100\n");
 		return stv0680_handle_error(gspca_dev, -EIO);
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/stv06xx/Makefile linux-libre-3.2-gnu/drivers/media/video/gspca/stv06xx/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/gspca/stv06xx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/stv06xx/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -6,5 +6,5 @@
 		      stv06xx_pb0100.o \
 		      stv06xx_st6422.o
 
-EXTRA_CFLAGS += -Idrivers/media/video/gspca
+ccflags-y += -Idrivers/media/video/gspca
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/stv06xx/stv06xx.c linux-libre-3.2-gnu/drivers/media/video/gspca/stv06xx/stv06xx.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/stv06xx/stv06xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/stv06xx/stv06xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,8 @@
  * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/input.h>
 #include "stv06xx_sensor.h"
 
@@ -189,7 +191,7 @@
 			      0x04, 0x40, 0x1400, 0, buf, I2C_BUFFER_LENGTH,
 			      STV06XX_URB_MSG_TIMEOUT);
 	if (err < 0) {
-		err("I2C: Read error writing address: %d", err);
+		pr_err("I2C: Read error writing address: %d\n", err);
 		return err;
 	}
 
@@ -213,14 +215,14 @@
 	int i;
 	u8 data, buf;
 
-	info("Dumping all stv06xx bridge registers");
+	pr_info("Dumping all stv06xx bridge registers\n");
 	for (i = 0x1400; i < 0x160f; i++) {
 		stv06xx_read_bridge(sd, i, &data);
 
-		info("Read 0x%x from address 0x%x", data, i);
+		pr_info("Read 0x%x from address 0x%x\n", data, i);
 	}
 
-	info("Testing stv06xx bridge registers for writability");
+	pr_info("Testing stv06xx bridge registers for writability\n");
 	for (i = 0x1400; i < 0x160f; i++) {
 		stv06xx_read_bridge(sd, i, &data);
 		buf = data;
@@ -228,12 +230,12 @@
 		stv06xx_write_bridge(sd, i, 0xff);
 		stv06xx_read_bridge(sd, i, &data);
 		if (data == 0xff)
-			info("Register 0x%x is read/write", i);
+			pr_info("Register 0x%x is read/write\n", i);
 		else if (data != buf)
-			info("Register 0x%x is read/write,"
-			     " but only partially", i);
+			pr_info("Register 0x%x is read/write, but only partially\n",
+				i);
 		else
-			info("Register 0x%x is read-only", i);
+			pr_info("Register 0x%x is read-only\n", i);
 
 		stv06xx_write_bridge(sd, i, buf);
 	}
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/stv06xx/stv06xx.h linux-libre-3.2-gnu/drivers/media/video/gspca/stv06xx/stv06xx.h
--- linux-libre-3.1-gnu/drivers/media/video/gspca/stv06xx/stv06xx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/stv06xx/stv06xx.h	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,8 @@
 
 #define STV_ISOC_ENDPOINT_ADDR		0x81
 
+#define STV_R                           0x0509
+
 #define STV_REG23			0x0423
 
 /* Control registers of the STV0600 ASIC */
@@ -61,7 +63,9 @@
 
 /* Refers to the CIF 352x288 and QCIF 176x144 */
 /* 1: 288 lines, 2: 144 lines */
-#define STV_Y_CTRL			0x15c3
+#define STV_Y_CTRL		        0x15c3
+
+#define STV_RESET                       0x1620
 
 /* 0xa: 352 columns, 0x6: 176 columns */
 #define STV_X_CTRL			0x1680
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c linux-libre-3.2-gnu/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,8 @@
  * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "stv06xx_hdcs.h"
 
 static const struct ctrl hdcs1x00_ctrl[] = {
@@ -428,7 +430,7 @@
 	if (ret < 0 || sensor != 0x08)
 		return -ENODEV;
 
-	info("HDCS-1000/1100 sensor detected");
+	pr_info("HDCS-1000/1100 sensor detected\n");
 
 	sd->gspca_dev.cam.cam_mode = hdcs1x00_mode;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1x00_mode);
@@ -487,7 +489,7 @@
 	if (ret < 0 || sensor != 0x10)
 		return -ENODEV;
 
-	info("HDCS-1020 sensor detected");
+	pr_info("HDCS-1020 sensor detected\n");
 
 	sd->gspca_dev.cam.cam_mode = hdcs1020_mode;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1020_mode);
@@ -601,11 +603,11 @@
 {
 	u16 reg, val;
 
-	info("Dumping sensor registers:");
+	pr_info("Dumping sensor registers:\n");
 
 	for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH; reg++) {
 		stv06xx_read_sensor(sd, reg, &val);
-		info("reg 0x%02x = 0x%02x", reg, val);
+		pr_info("reg 0x%02x = 0x%02x\n", reg, val);
 	}
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c linux-libre-3.2-gnu/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,6 +44,8 @@
  * PB_CFILLIN       = R5  = 0x0E (14 dec)     : Sets the frame rate
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "stv06xx_pb0100.h"
 
 static const struct ctrl pb0100_ctrl[] = {
@@ -190,7 +192,7 @@
 		if (!sensor_settings)
 			return -ENOMEM;
 
-		info("Photobit pb0100 sensor detected");
+		pr_info("Photobit pb0100 sensor detected\n");
 
 		sd->gspca_dev.cam.cam_mode = pb0100_mode;
 		sd->gspca_dev.cam.nmodes = ARRAY_SIZE(pb0100_mode);
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c linux-libre-3.2-gnu/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "stv06xx_st6422.h"
 
 /* controls */
@@ -136,7 +138,7 @@
 	if (sd->bridge != BRIDGE_ST6422)
 		return -ENODEV;
 
-	info("st6422 sensor detected");
+	pr_info("st6422 sensor detected\n");
 
 	sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL);
 	if (!sensor_settings)
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c linux-libre-3.2-gnu/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,8 @@
  * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "stv06xx_vv6410.h"
 
 static struct v4l2_pix_format vv6410_mode[] = {
@@ -112,7 +114,7 @@
 		return -ENODEV;
 
 	if (data == 0x19) {
-		info("vv6410 sensor detected");
+		pr_info("vv6410 sensor detected\n");
 
 		sensor_settings = kmalloc(ARRAY_SIZE(vv6410_ctrl) * sizeof(s32),
 					  GFP_KERNEL);
@@ -138,18 +140,7 @@
 	s32 *sensor_settings = sd->sensor_priv;
 
 	for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++) {
-		/* if NULL then len contains single value */
-		if (stv_bridge_init[i].data == NULL) {
-			err = stv06xx_write_bridge(sd,
-				stv_bridge_init[i].start,
-				stv_bridge_init[i].len);
-		} else {
-			int j;
-			for (j = 0; j < stv_bridge_init[i].len; j++)
-				err = stv06xx_write_bridge(sd,
-					stv_bridge_init[i].start + j,
-					stv_bridge_init[i].data[j]);
-		}
+		stv06xx_write_bridge(sd, stv_bridge_init[i].addr, stv_bridge_init[i].data);
 	}
 
 	if (err < 0)
@@ -183,15 +174,6 @@
 	struct cam *cam = &sd->gspca_dev.cam;
 	u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
 
-	if (priv & VV6410_CROP_TO_QVGA) {
-		PDEBUG(D_CONF, "Cropping to QVGA");
-		stv06xx_write_sensor(sd, VV6410_XENDH, 320 - 1);
-		stv06xx_write_sensor(sd, VV6410_YENDH, 240 - 1);
-	} else {
-		stv06xx_write_sensor(sd, VV6410_XENDH, 360 - 1);
-		stv06xx_write_sensor(sd, VV6410_YENDH, 294 - 1);
-	}
-
 	if (priv & VV6410_SUBSAMPLE) {
 		PDEBUG(D_CONF, "Enabling subsampling");
 		stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02);
@@ -201,8 +183,8 @@
 	} else {
 		stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
 		stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
+		stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x00);
 
-		stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20);
 	}
 
 	/* Turn on LED */
@@ -242,11 +224,11 @@
 	u8 i;
 	int err = 0;
 
-	info("Dumping all vv6410 sensor registers");
+	pr_info("Dumping all vv6410 sensor registers\n");
 	for (i = 0; i < 0xff && !err; i++) {
 		u16 data;
 		err = stv06xx_read_sensor(sd, i, &data);
-		info("Register 0x%x contained 0x%x", i, data);
+		pr_info("Register 0x%x contained 0x%x\n", i, data);
 	}
 	return (err < 0) ? err : 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h linux-libre-3.2-gnu/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
--- linux-libre-3.1-gnu/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h	2012-01-04 18:55:44.000000000 -0500
@@ -211,49 +211,49 @@
 
 /* If NULL, only single value to write, stored in len */
 struct stv_init {
-	const u8 *data;
-	u16 start;
-	u8 len;
-};
-
-static const u8 x1500[] = {	/* 0x1500 - 0x150f */
-	0x0b, 0xa7, 0xb7, 0x00, 0x00
-};
-
-static const u8 x1536[] = {	/* 0x1536 - 0x153b */
-	0x02, 0x00, 0x60, 0x01, 0x20, 0x01
+	u16 addr;
+	u8 data;
 };
 
 static const struct stv_init stv_bridge_init[] = {
 	/* This reg is written twice. Some kind of reset? */
-	{NULL,  0x1620, 0x80},
-	{NULL,  0x1620, 0x00},
-	{NULL,  0x1443, 0x00},
-	{NULL,  0x1423, 0x04},
-	{x1500, 0x1500, ARRAY_SIZE(x1500)},
-	{x1536, 0x1536, ARRAY_SIZE(x1536)},
+	{STV_RESET, 0x80},
+	{STV_RESET, 0x00},
+	{STV_SCAN_RATE, 0x00},
+	{STV_I2C_FLUSH, 0x04},
+	{STV_REG00, 0x0b},
+	{STV_REG01, 0xa7},
+	{STV_REG02, 0xb7},
+	{STV_REG03, 0x00},
+	{STV_REG04, 0x00},
+	{0x1536, 0x02},
+	{0x1537, 0x00},
+	{0x1538, 0x60},
+	{0x1539, 0x01},
+	{0x153a, 0x20},
+	{0x153b, 0x01},
 };
 
 static const u8 vv6410_sensor_init[][2] = {
 	/* Setup registers */
-	{VV6410_SETUP0,		VV6410_SOFT_RESET},
-	{VV6410_SETUP0,		VV6410_LOW_POWER_MODE},
+	{VV6410_SETUP0,	VV6410_SOFT_RESET},
+	{VV6410_SETUP0,	VV6410_LOW_POWER_MODE},
 	/* Use shuffled read-out mode */
-	{VV6410_SETUP1,		BIT(6)},
-	/* All modes to 1 */
-	{VV6410_FGMODES,	BIT(6) | BIT(4) | BIT(2) | BIT(0)},
-	{VV6410_PINMAPPING,	0x00},
+	{VV6410_SETUP1,	BIT(6)},
+	/* All modes to 1, FST, Fast QCK, Free running QCK, Free running LST, FST will qualify visible pixels */
+	{VV6410_FGMODES, BIT(6) | BIT(4) | BIT(2) | BIT(0)},
+	{VV6410_PINMAPPING, 0x00},
 	/* Pre-clock generator divide off */
-	{VV6410_DATAFORMAT,	BIT(7) | BIT(0)},
+	{VV6410_DATAFORMAT, BIT(7) | BIT(0)},
 
-	{VV6410_CLKDIV,		VV6410_CLK_DIV_2},
+	{VV6410_CLKDIV,	VV6410_CLK_DIV_2},
 
 	/* System registers */
 	/* Enable voltage doubler */
-	{VV6410_AS0,		BIT(6) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
-	{VV6410_AT0,		0x00},
+	{VV6410_AS0, BIT(6) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
+	{VV6410_AT0, 0x00},
 	/* Power up audio, differential */
-	{VV6410_AT1,		BIT(4)|BIT(0)},
+	{VV6410_AT1, BIT(4) | BIT(0)},
 };
 
 #endif
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/sunplus.c linux-libre-3.2-gnu/drivers/media/video/gspca/sunplus.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/sunplus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/sunplus.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "sunplus"
 
 #include "gspca.h"
@@ -325,7 +327,7 @@
 
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
-		err("reg_r: buffer overflow");
+		pr_err("reg_r: buffer overflow\n");
 		return;
 	}
 #endif
@@ -340,7 +342,7 @@
 			len ? gspca_dev->usb_buf : NULL, len,
 			500);
 	if (ret < 0) {
-		err("reg_r err %d", ret);
+		pr_err("reg_r err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -365,7 +367,7 @@
 			gspca_dev->usb_buf, 1,
 			500);
 	if (ret < 0) {
-		err("reg_w_1 err %d", ret);
+		pr_err("reg_w_1 err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -385,7 +387,7 @@
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			value, index, NULL, 0, 500);
 	if (ret < 0) {
-		err("reg_w_riv err %d", ret);
+		pr_err("reg_w_riv err %d\n", ret);
 		gspca_dev->usb_err = ret;
 		return;
 	}
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/t613.c linux-libre-3.2-gnu/drivers/media/video/gspca/t613.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/t613.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/t613.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,8 @@
  *			Costantino Leandro
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "t613"
 
 #include <linux/slab.h>
@@ -572,7 +574,7 @@
 
 		tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
 		if (!tmpbuf) {
-			err("Out of memory");
+			pr_err("Out of memory\n");
 			return;
 		}
 		usb_control_msg(gspca_dev->dev,
@@ -598,7 +600,7 @@
 	} else {
 		p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
 		if (!tmpbuf) {
-			err("Out of memory");
+			pr_err("Out of memory\n");
 			return;
 		}
 	}
@@ -652,7 +654,7 @@
 	}
 	byte = reg_r(gspca_dev, 0x0063);
 	if (byte != 0x17) {
-		err("Bad sensor reset %02x", byte);
+		pr_err("Bad sensor reset %02x\n", byte);
 		/* continue? */
 	}
 
@@ -890,7 +892,7 @@
 		sd->sensor = SENSOR_OM6802;
 		break;
 	default:
-		err("unknown sensor %04x", sensor_id);
+		pr_err("unknown sensor %04x\n", sensor_id);
 		return -EINVAL;
 	}
 
@@ -905,7 +907,7 @@
 				break;		/* OK */
 		}
 		if (i < 0) {
-			err("Bad sensor reset %02x", test_byte);
+			pr_err("Bad sensor reset %02x\n", test_byte);
 			return -EIO;
 		}
 		reg_w_buf(gspca_dev, n2, sizeof n2);
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/topro.c linux-libre-3.2-gnu/drivers/media/video/gspca/topro.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/topro.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/topro.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,4989 @@
+/*
+ * Topro TP6800/6810 webcam driver.
+ *
+ * Copyright (C) 2011 Jean-FranÃ§ois Moine (http://moinejf.free.fr)
+ * Copyright (C) 2009 Anders Blomdell (anders.blomdell@control.lth.se)
+ * Copyright (C) 2008 Thomas Champagne (lafeuil@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, see <http://www.gnu.org/licenses/>.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "gspca.h"
+
+MODULE_DESCRIPTION("Topro TP6800/6810 gspca webcam driver");
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
+		"Anders Blomdell <anders.blomdell@control.lth.se>");
+MODULE_LICENSE("GPL");
+
+static int force_sensor = -1;
+
+/* JPEG header */
+static const u8 jpeg_head[] = {
+	0xff, 0xd8,			/* jpeg */
+
+/* quantization table quality 50% */
+	0xff, 0xdb, 0x00, 0x84,		/* DQT */
+0,
+#define JPEG_QT0_OFFSET 7
+	0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
+	0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
+	0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
+	0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
+	0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
+	0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
+	0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
+	0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
+1,
+#define JPEG_QT1_OFFSET 72
+	0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+	0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+
+	/* Define Huffman table (thanks to Thomas Kaiser) */
+	0xff, 0xc4, 0x01, 0x5e,
+	0x00, 0x00, 0x02, 0x03,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
+	0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
+	0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
+	0x07, 0x05, 0x04, 0x06, 0x01, 0x00, 0x00, 0x57,
+	0x01, 0x02, 0x03, 0x00, 0x11, 0x04, 0x12, 0x21,
+	0x31, 0x13, 0x41, 0x51, 0x61, 0x05, 0x22, 0x32,
+	0x14, 0x71, 0x81, 0x91, 0x15, 0x23, 0x42, 0x52,
+	0x62, 0xa1, 0xb1, 0x06, 0x33, 0x72, 0xc1, 0xd1,
+	0x24, 0x43, 0x53, 0x82, 0x16, 0x34, 0x92, 0xa2,
+	0xe1, 0xf1, 0xf0, 0x07, 0x08, 0x17, 0x18, 0x25,
+	0x26, 0x27, 0x28, 0x35, 0x36, 0x37, 0x38, 0x44,
+	0x45, 0x46, 0x47, 0x48, 0x54, 0x55, 0x56, 0x57,
+	0x58, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x73,
+	0x74, 0x75, 0x76, 0x77, 0x78, 0x83, 0x84, 0x85,
+	0x86, 0x87, 0x88, 0x93, 0x94, 0x95, 0x96, 0x97,
+	0x98, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xb2,
+	0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xc2, 0xc3,
+	0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xd2, 0xd3, 0xd4,
+	0xd5, 0xd6, 0xd7, 0xd8, 0xe2, 0xe3, 0xe4, 0xe5,
+	0xe6, 0xe7, 0xe8, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
+	0xf7, 0xf8, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
+	0x05, 0x06, 0x07, 0x08, 0x09, 0x11, 0x00, 0x02,
+	0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
+	0x04, 0x06, 0x01, 0x00, 0x00, 0x57, 0x00, 0x01,
+	0x11, 0x02, 0x21, 0x03, 0x12, 0x31, 0x41, 0x13,
+	0x22, 0x51, 0x61, 0x04, 0x32, 0x71, 0x05, 0x14,
+	0x23, 0x42, 0x33, 0x52, 0x81, 0x91, 0xa1, 0xb1,
+	0xf0, 0x06, 0x15, 0xc1, 0xd1, 0xe1, 0x24, 0x43,
+	0x62, 0xf1, 0x16, 0x25, 0x34, 0x53, 0x72, 0x82,
+	0x92, 0x07, 0x08, 0x17, 0x18, 0x26, 0x27, 0x28,
+	0x35, 0x36, 0x37, 0x38, 0x44, 0x45, 0x46, 0x47,
+	0x48, 0x54, 0x55, 0x56, 0x57, 0x58, 0x63, 0x64,
+	0x65, 0x66, 0x67, 0x68, 0x73, 0x74, 0x75, 0x76,
+	0x77, 0x78, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+	0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0xa2, 0xa3,
+	0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xb2, 0xb3, 0xb4,
+	0xb5, 0xb6, 0xb7, 0xb8, 0xc2, 0xc3, 0xc4, 0xc5,
+	0xc6, 0xc7, 0xc8, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+	0xd7, 0xd8, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+	0xe8, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+	0xff, 0xc0, 0x00, 0x11,		/* SOF0 (start of frame 0 */
+	0x08,				/* data precision */
+#define JPEG_HEIGHT_OFFSET 493
+	0x01, 0xe0,			/* height */
+	0x02, 0x80,			/* width */
+	0x03,				/* component number */
+		0x01,
+			0x21,		/* samples Y = jpeg 422 */
+			0x00,		/* quant Y */
+		0x02, 0x11, 0x01,	/* samples CbCr - quant CbCr */
+		0x03, 0x11, 0x01,
+
+	0xff, 0xda, 0x00, 0x0c,		/* SOS (start of scan) */
+	0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
+#define JPEG_HDR_SZ 521
+};
+
+enum e_ctrl {
+	EXPOSURE,
+	QUALITY,
+	SHARPNESS,
+	RGAIN,
+	GAIN,
+	BGAIN,
+	GAMMA,
+	AUTOGAIN,
+	NCTRLS		/* number of controls */
+};
+
+#define AUTOGAIN_DEF 1
+
+struct sd {
+	struct gspca_dev gspca_dev;	/* !! must be the first item */
+
+	struct gspca_ctrl ctrls[NCTRLS];
+
+	u8 framerate;
+	u8 quality;		/* webcam current JPEG quality (0..16) */
+	s8 ag_cnt;		/* autogain / start counter for tp6810 */
+#define AG_CNT_START 13		/* check gain every N frames */
+
+	u8 bridge;
+	u8 sensor;
+
+	u8 jpeg_hdr[JPEG_HDR_SZ];
+};
+
+enum bridges {
+	BRIDGE_TP6800,
+	BRIDGE_TP6810,
+};
+
+enum sensors {
+	SENSOR_CX0342,
+	SENSOR_SOI763A,		/* ~= ov7630 / ov7648 */
+	NSENSORS
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240 * 4 / 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}
+};
+
+/*
+ * JPEG quality
+ * index: webcam compression
+ * value: JPEG quality in %
+ */
+static const u8 jpeg_q[17] = {
+	88, 77, 67, 57, 55, 55, 45, 45, 36, 36, 30, 30, 26, 26, 22, 22, 94
+};
+
+#define BULK_OUT_SIZE		0x20
+#if BULK_OUT_SIZE > USB_BUF_SZ
+#error "USB buffer too small"
+#endif
+
+static const u8 rates[] = {30, 20, 15, 10, 7, 5};
+static const struct framerates framerates[] = {
+	{
+		.rates = rates,
+		.nrates = ARRAY_SIZE(rates)
+	},
+	{
+		.rates = rates,
+		.nrates = ARRAY_SIZE(rates)
+	}
+};
+static const u8 rates_6810[] = {30, 15, 10, 7, 5};
+static const struct framerates framerates_6810[] = {
+	{
+		.rates = rates_6810,
+		.nrates = ARRAY_SIZE(rates_6810)
+	},
+	{
+		.rates = rates_6810,
+		.nrates = ARRAY_SIZE(rates_6810)
+	}
+};
+
+/*
+ * webcam quality in %
+ * the last value is the ultra fine quality
+ */
+
+/* TP6800 register offsets */
+#define TP6800_R10_SIF_TYPE		0x10
+#define TP6800_R11_SIF_CONTROL		0x11
+#define TP6800_R12_SIF_ADDR_S		0x12
+#define TP6800_R13_SIF_TX_DATA		0x13
+#define TP6800_R14_SIF_RX_DATA		0x14
+#define TP6800_R15_GPIO_PU		0x15
+#define TP6800_R16_GPIO_PD		0x16
+#define TP6800_R17_GPIO_IO		0x17
+#define TP6800_R18_GPIO_DATA		0x18
+#define TP6800_R19_SIF_ADDR_S2		0x19
+#define TP6800_R1A_SIF_TX_DATA2		0x1a
+#define TP6800_R1B_SIF_RX_DATA2		0x1b
+#define TP6800_R21_ENDP_1_CTL		0x21
+#define TP6800_R2F_TIMING_CFG		0x2f
+#define TP6800_R30_SENSOR_CFG		0x30
+#define TP6800_R31_PIXEL_START		0x31
+#define TP6800_R32_PIXEL_END_L		0x32
+#define TP6800_R33_PIXEL_END_H		0x33
+#define TP6800_R34_LINE_START		0x34
+#define TP6800_R35_LINE_END_L		0x35
+#define TP6800_R36_LINE_END_H		0x36
+#define TP6800_R37_FRONT_DARK_ST	0x37
+#define TP6800_R38_FRONT_DARK_END	0x38
+#define TP6800_R39_REAR_DARK_ST_L	0x39
+#define TP6800_R3A_REAR_DARK_ST_H	0x3a
+#define TP6800_R3B_REAR_DARK_END_L	0x3b
+#define TP6800_R3C_REAR_DARK_END_H	0x3c
+#define TP6800_R3D_HORIZ_DARK_LINE_L	0x3d
+#define TP6800_R3E_HORIZ_DARK_LINE_H	0x3e
+#define TP6800_R3F_FRAME_RATE		0x3f
+#define TP6800_R50			0x50
+#define TP6800_R51			0x51
+#define TP6800_R52			0x52
+#define TP6800_R53			0x53
+#define TP6800_R54_DARK_CFG		0x54
+#define TP6800_R55_GAMMA_R		0x55
+#define TP6800_R56_GAMMA_G		0x56
+#define TP6800_R57_GAMMA_B		0x57
+#define TP6800_R5C_EDGE_THRLD		0x5c
+#define TP6800_R5D_DEMOSAIC_CFG		0x5d
+#define TP6800_R78_FORMAT		0x78
+#define TP6800_R79_QUALITY		0x79
+#define TP6800_R7A_BLK_THRLD		0x7a
+
+/* CX0342 register offsets */
+
+#define CX0342_SENSOR_ID		0x00
+#define CX0342_VERSION_NO		0x01
+#define CX0342_ORG_X_L			0x02
+#define CX0342_ORG_X_H			0x03
+#define CX0342_ORG_Y_L			0x04
+#define CX0342_ORG_Y_H			0x05
+#define CX0342_STOP_X_L			0x06
+#define CX0342_STOP_X_H			0x07
+#define CX0342_STOP_Y_L			0x08
+#define CX0342_STOP_Y_H			0x09
+#define CX0342_FRAME_WIDTH_L		0x0a
+#define CX0342_FRAME_WIDTH_H		0x0b
+#define CX0342_FRAME_HEIGH_L		0x0c
+#define CX0342_FRAME_HEIGH_H		0x0d
+#define CX0342_EXPO_LINE_L		0x10
+#define CX0342_EXPO_LINE_H		0x11
+#define CX0342_EXPO_CLK_L		0x12
+#define CX0342_EXPO_CLK_H		0x13
+#define CX0342_RAW_GRGAIN_L		0x14
+#define CX0342_RAW_GRGAIN_H		0x15
+#define CX0342_RAW_GBGAIN_L		0x16
+#define CX0342_RAW_GBGAIN_H		0x17
+#define CX0342_RAW_RGAIN_L		0x18
+#define CX0342_RAW_RGAIN_H		0x19
+#define CX0342_RAW_BGAIN_L		0x1a
+#define CX0342_RAW_BGAIN_H		0x1b
+#define CX0342_GLOBAL_GAIN		0x1c
+#define CX0342_SYS_CTRL_0		0x20
+#define CX0342_SYS_CTRL_1		0x21
+#define CX0342_SYS_CTRL_2		0x22
+#define CX0342_BYPASS_MODE		0x23
+#define CX0342_SYS_CTRL_3		0x24
+#define CX0342_TIMING_EN		0x25
+#define CX0342_OUTPUT_CTRL		0x26
+#define CX0342_AUTO_ADC_CALIB		0x27
+#define CX0342_SYS_CTRL_4		0x28
+#define CX0342_ADCGN			0x30
+#define CX0342_SLPCR			0x31
+#define CX0342_SLPFN_LO			0x32
+#define CX0342_ADC_CTL			0x33
+#define CX0342_LVRST_BLBIAS		0x34
+#define CX0342_VTHSEL			0x35
+#define CX0342_RAMP_RIV			0x36
+#define CX0342_LDOSEL			0x37
+#define CX0342_CLOCK_GEN		0x40
+#define CX0342_SOFT_RESET		0x41
+#define CX0342_PLL			0x42
+#define CX0342_DR_ENH_PULSE_OFFSET_L	0x43
+#define CX0342_DR_ENH_PULSE_OFFSET_H	0x44
+#define CX0342_DR_ENH_PULSE_POS_L	0x45
+#define CX0342_DR_ENH_PULSE_POS_H	0x46
+#define CX0342_DR_ENH_PULSE_WIDTH	0x47
+#define CX0342_AS_CURRENT_CNT_L		0x48
+#define CX0342_AS_CURRENT_CNT_H		0x49
+#define CX0342_AS_PREVIOUS_CNT_L	0x4a
+#define CX0342_AS_PREVIOUS_CNT_H	0x4b
+#define CX0342_SPV_VALUE_L		0x4c
+#define CX0342_SPV_VALUE_H		0x4d
+#define CX0342_GPXLTHD_L		0x50
+#define CX0342_GPXLTHD_H		0x51
+#define CX0342_RBPXLTHD_L		0x52
+#define CX0342_RBPXLTHD_H		0x53
+#define CX0342_PLANETHD_L		0x54
+#define CX0342_PLANETHD_H		0x55
+#define CX0342_ROWDARK_TH		0x56
+#define CX0342_ROWDARK_TOL		0x57
+#define CX0342_RB_GAP_L			0x58
+#define CX0342_RB_GAP_H			0x59
+#define CX0342_G_GAP_L			0x5a
+#define CX0342_G_GAP_H			0x5b
+#define CX0342_AUTO_ROW_DARK		0x60
+#define CX0342_MANUAL_DARK_VALUE	0x61
+#define CX0342_GB_DARK_OFFSET		0x62
+#define CX0342_GR_DARK_OFFSET		0x63
+#define CX0342_RED_DARK_OFFSET		0x64
+#define CX0342_BLUE_DARK_OFFSET		0x65
+#define CX0342_DATA_SCALING_MULTI	0x66
+#define CX0342_AUTOD_Q_FRAME		0x67
+#define CX0342_AUTOD_ALLOW_VARI		0x68
+#define CX0342_AUTO_DARK_VALUE_L	0x69
+#define CX0342_AUTO_DARK_VALUE_H	0x6a
+#define CX0342_IO_CTRL_0		0x70
+#define CX0342_IO_CTRL_1		0x71
+#define CX0342_IO_CTRL_2		0x72
+#define CX0342_IDLE_CTRL		0x73
+#define CX0342_TEST_MODE		0x74
+#define CX0342_FRAME_FIX_DATA_TEST	0x75
+#define CX0342_FRAME_CNT_TEST		0x76
+#define CX0342_RST_OVERFLOW_L		0x80
+#define CX0342_RST_OVERFLOW_H		0x81
+#define CX0342_RST_UNDERFLOW_L		0x82
+#define CX0342_RST_UNDERFLOW_H		0x83
+#define CX0342_DATA_OVERFLOW_L		0x84
+#define CX0342_DATA_OVERFLOW_H		0x85
+#define CX0342_DATA_UNDERFLOW_L		0x86
+#define CX0342_DATA_UNDERFLOW_H		0x87
+#define CX0342_CHANNEL_0_0_L_irst	0x90
+#define CX0342_CHANNEL_0_0_H_irst	0x91
+#define CX0342_CHANNEL_0_1_L_irst	0x92
+#define CX0342_CHANNEL_0_1_H_irst	0x93
+#define CX0342_CHANNEL_0_2_L_irst	0x94
+#define CX0342_CHANNEL_0_2_H_irst	0x95
+#define CX0342_CHANNEL_0_3_L_irst	0x96
+#define CX0342_CHANNEL_0_3_H_irst	0x97
+#define CX0342_CHANNEL_0_4_L_irst	0x98
+#define CX0342_CHANNEL_0_4_H_irst	0x99
+#define CX0342_CHANNEL_0_5_L_irst	0x9a
+#define CX0342_CHANNEL_0_5_H_irst	0x9b
+#define CX0342_CHANNEL_0_6_L_irst	0x9c
+#define CX0342_CHANNEL_0_6_H_irst	0x9d
+#define CX0342_CHANNEL_0_7_L_irst	0x9e
+#define CX0342_CHANNEL_0_7_H_irst	0x9f
+#define CX0342_CHANNEL_1_0_L_itx	0xa0
+#define CX0342_CHANNEL_1_0_H_itx	0xa1
+#define CX0342_CHANNEL_1_1_L_itx	0xa2
+#define CX0342_CHANNEL_1_1_H_itx	0xa3
+#define CX0342_CHANNEL_1_2_L_itx	0xa4
+#define CX0342_CHANNEL_1_2_H_itx	0xa5
+#define CX0342_CHANNEL_1_3_L_itx	0xa6
+#define CX0342_CHANNEL_1_3_H_itx	0xa7
+#define CX0342_CHANNEL_1_4_L_itx	0xa8
+#define CX0342_CHANNEL_1_4_H_itx	0xa9
+#define CX0342_CHANNEL_1_5_L_itx	0xaa
+#define CX0342_CHANNEL_1_5_H_itx	0xab
+#define CX0342_CHANNEL_1_6_L_itx	0xac
+#define CX0342_CHANNEL_1_6_H_itx	0xad
+#define CX0342_CHANNEL_1_7_L_itx	0xae
+#define CX0342_CHANNEL_1_7_H_itx	0xaf
+#define CX0342_CHANNEL_2_0_L_iwl	0xb0
+#define CX0342_CHANNEL_2_0_H_iwl	0xb1
+#define CX0342_CHANNEL_2_1_L_iwl	0xb2
+#define CX0342_CHANNEL_2_1_H_iwl	0xb3
+#define CX0342_CHANNEL_2_2_L_iwl	0xb4
+#define CX0342_CHANNEL_2_2_H_iwl	0xb5
+#define CX0342_CHANNEL_2_3_L_iwl	0xb6
+#define CX0342_CHANNEL_2_3_H_iwl	0xb7
+#define CX0342_CHANNEL_2_4_L_iwl	0xb8
+#define CX0342_CHANNEL_2_4_H_iwl	0xb9
+#define CX0342_CHANNEL_2_5_L_iwl	0xba
+#define CX0342_CHANNEL_2_5_H_iwl	0xbb
+#define CX0342_CHANNEL_2_6_L_iwl	0xbc
+#define CX0342_CHANNEL_2_6_H_iwl	0xbd
+#define CX0342_CHANNEL_2_7_L_iwl	0xbe
+#define CX0342_CHANNEL_2_7_H_iwl	0xbf
+#define CX0342_CHANNEL_3_0_L_ensp	0xc0
+#define CX0342_CHANNEL_3_0_H_ensp	0xc1
+#define CX0342_CHANNEL_3_1_L_ensp	0xc2
+#define CX0342_CHANNEL_3_1_H_ensp	0xc3
+#define CX0342_CHANNEL_3_2_L_ensp	0xc4
+#define CX0342_CHANNEL_3_2_H_ensp	0xc5
+#define CX0342_CHANNEL_3_3_L_ensp	0xc6
+#define CX0342_CHANNEL_3_3_H_ensp	0xc7
+#define CX0342_CHANNEL_3_4_L_ensp	0xc8
+#define CX0342_CHANNEL_3_4_H_ensp	0xc9
+#define CX0342_CHANNEL_3_5_L_ensp	0xca
+#define CX0342_CHANNEL_3_5_H_ensp	0xcb
+#define CX0342_CHANNEL_3_6_L_ensp	0xcc
+#define CX0342_CHANNEL_3_6_H_ensp	0xcd
+#define CX0342_CHANNEL_3_7_L_ensp	0xce
+#define CX0342_CHANNEL_3_7_H_ensp	0xcf
+#define CX0342_CHANNEL_4_0_L_sela	0xd0
+#define CX0342_CHANNEL_4_0_H_sela	0xd1
+#define CX0342_CHANNEL_4_1_L_sela	0xd2
+#define CX0342_CHANNEL_4_1_H_sela	0xd3
+#define CX0342_CHANNEL_5_0_L_intla	0xe0
+#define CX0342_CHANNEL_5_0_H_intla	0xe1
+#define CX0342_CHANNEL_5_1_L_intla	0xe2
+#define CX0342_CHANNEL_5_1_H_intla	0xe3
+#define CX0342_CHANNEL_5_2_L_intla	0xe4
+#define CX0342_CHANNEL_5_2_H_intla	0xe5
+#define CX0342_CHANNEL_5_3_L_intla	0xe6
+#define CX0342_CHANNEL_5_3_H_intla	0xe7
+#define CX0342_CHANNEL_6_0_L_xa_sel_pos 0xf0
+#define CX0342_CHANNEL_6_0_H_xa_sel_pos 0xf1
+#define CX0342_CHANNEL_7_1_L_cds_pos	0xf2
+#define CX0342_CHANNEL_7_1_H_cds_pos	0xf3
+#define CX0342_SENSOR_HEIGHT_L		0xfb
+#define CX0342_SENSOR_HEIGHT_H		0xfc
+#define CX0342_SENSOR_WIDTH_L		0xfd
+#define CX0342_SENSOR_WIDTH_H		0xfe
+#define CX0342_VSYNC_HSYNC_READ		0xff
+
+struct cmd {
+	u8 reg;
+	u8 val;
+};
+
+static const u8 DQT[17][130] = {
+	/* Define quantization table (thanks to Thomas Kaiser) */
+	{			/* Quality 0 */
+	 0x00,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x01,
+	 0x04, 0x04, 0x04, 0x06, 0x05, 0x06, 0x0b, 0x06,
+	 0x06, 0x0b, 0x18, 0x10, 0x0e, 0x10, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 },
+	{			/* Quality 1 */
+	 0x00,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x09, 0x09, 0x09, 0x09, 0x09,
+	 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+	 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+	 0x01,
+	 0x08, 0x09, 0x09, 0x0c, 0x0a, 0x0c, 0x17, 0x0d,
+	 0x0d, 0x17, 0x31, 0x21, 0x1c, 0x21, 0x31, 0x31,
+	 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+	 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+	 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+	 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+	 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+	 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+	 },
+	{			/* Quality 2 */
+	 0x00,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x06, 0x06, 0x06, 0x04, 0x04, 0x04,
+	 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+	 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+	 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+	 0x06, 0x06, 0x06, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+	 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+	 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+	 0x01,
+	 0x0c, 0x0d, 0x0d, 0x12, 0x0f, 0x12, 0x23, 0x13,
+	 0x13, 0x23, 0x4a, 0x31, 0x2a, 0x31, 0x4a, 0x4a,
+	 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+	 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+	 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+	 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+	 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+	 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+	 },
+	{			/* Quality 3 */
+	 0x00,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04,
+	 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+	 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+	 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+	 0x08, 0x08, 0x08, 0x13, 0x13, 0x13, 0x13, 0x13,
+	 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
+	 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
+	 0x01,
+	 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+	 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+	 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	 },
+	{			/* Quality 4 */
+	 0x00,
+	 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+	 0x05, 0x05, 0x0a, 0x0a, 0x0a, 0x05, 0x05, 0x05,
+	 0x05, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+	 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+	 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+	 0x0a, 0x0a, 0x0a, 0x17, 0x17, 0x17, 0x17, 0x17,
+	 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
+	 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
+	 0x01,
+	 0x11, 0x16, 0x16, 0x1e, 0x1a, 0x1e, 0x3a, 0x20,
+	 0x20, 0x3a, 0x7b, 0x52, 0x46, 0x52, 0x7b, 0x7b,
+	 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+	 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+	 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+	 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+	 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+	 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+	 },
+	{			/* Quality 5 */
+	 0x00,
+	 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+	 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x06, 0x06, 0x06,
+	 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+	 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+	 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+	 0x0c, 0x0c, 0x0c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+	 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+	 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+	 0x01,
+	 0x11, 0x1b, 0x1b, 0x24, 0x1f, 0x24, 0x46, 0x27,
+	 0x27, 0x46, 0x94, 0x63, 0x54, 0x63, 0x94, 0x94,
+	 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+	 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+	 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+	 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+	 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+	 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+	 },
+	{			/* Quality 6 */
+	 0x00,
+	 0x05, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+	 0x07, 0x07, 0x0e, 0x0e, 0x0e, 0x07, 0x07, 0x07,
+	 0x07, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+	 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+	 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+	 0x0e, 0x0e, 0x0e, 0x21, 0x21, 0x21, 0x21, 0x21,
+	 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
+	 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
+	 0x01,
+	 0x15, 0x1f, 0x1f, 0x2a, 0x24, 0x2a, 0x52, 0x2d,
+	 0x2d, 0x52, 0xad, 0x73, 0x62, 0x73, 0xad, 0xad,
+	 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+	 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+	 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+	 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+	 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+	 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+	 },
+	{			/* Quality 7 */
+	 0x00,
+	 0x05, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+	 0x08, 0x08, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08,
+	 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	 0x10, 0x10, 0x10, 0x26, 0x26, 0x26, 0x26, 0x26,
+	 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
+	 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
+	 0x01,
+	 0x15, 0x24, 0x24, 0x30, 0x2a, 0x30, 0x5e, 0x34,
+	 0x34, 0x5e, 0xc6, 0x84, 0x70, 0x84, 0xc6, 0xc6,
+	 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+	 },
+	{			/* Quality 8 */
+	 0x00,
+	 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+	 0x0a, 0x0a, 0x14, 0x14, 0x14, 0x0a, 0x0a, 0x0a,
+	 0x0a, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+	 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+	 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+	 0x14, 0x14, 0x14, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
+	 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
+	 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
+	 0x01,
+	 0x19, 0x2d, 0x2d, 0x3c, 0x34, 0x3c, 0x75, 0x41,
+	 0x41, 0x75, 0xf7, 0xa5, 0x8c, 0xa5, 0xf7, 0xf7,
+	 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+	 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+	 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+	 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+	 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+	 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+	 },
+	{			/* Quality 9 */
+	 0x00,
+	 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+	 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x0c,
+	 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x18, 0x39, 0x39, 0x39, 0x39, 0x39,
+	 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
+	 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
+	 0x01,
+	 0x19, 0x36, 0x36, 0x48, 0x3f, 0x48, 0x8d, 0x4e,
+	 0x4e, 0x8d, 0xff, 0xc6, 0xa8, 0xc6, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 },
+	{			/* Quality 10 */
+	 0x00,
+	 0x07, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+	 0x0e, 0x0e, 0x1c, 0x1c, 0x1c, 0x0e, 0x0e, 0x0e,
+	 0x0e, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+	 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+	 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+	 0x1c, 0x1c, 0x1c, 0x42, 0x42, 0x42, 0x42, 0x42,
+	 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
+	 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
+	 0x01,
+	 0x1d, 0x3f, 0x3f, 0x54, 0x49, 0x54, 0xa4, 0x5b,
+	 0x5b, 0xa4, 0xff, 0xe7, 0xc4, 0xe7, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 },
+	{			/* Quality 11 */
+	 0x00,
+	 0x07, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	 0x10, 0x10, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10,
+	 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	 0x20, 0x20, 0x20, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
+	 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
+	 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
+	 0x01,
+	 0x1d, 0x48, 0x48, 0x60, 0x54, 0x60, 0xbc, 0x68,
+	 0x68, 0xbc, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 },
+	{			/* Quality 12 */
+	 0x00,
+	 0x08, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+	 0x14, 0x14, 0x28, 0x28, 0x28, 0x14, 0x14, 0x14,
+	 0x14, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+	 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+	 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+	 0x28, 0x28, 0x28, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+	 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+	 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+	 0x01,
+	 0x22, 0x5a, 0x5a, 0x78, 0x69, 0x78, 0xeb, 0x82,
+	 0x82, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 },
+	{			/* Quality 13 */
+	 0x00,
+	 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+	 0x18, 0x18, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18,
+	 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+	 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+	 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+	 0x30, 0x30, 0x30, 0x72, 0x72, 0x72, 0x72, 0x72,
+	 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
+	 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
+	 0x01,
+	 0x22, 0x6c, 0x6c, 0x90, 0x7e, 0x90, 0xff, 0x9c,
+	 0x9c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 },
+	{			/* Quality 14 */
+	 0x00,
+	 0x0a, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+	 0x1c, 0x1c, 0x38, 0x38, 0x38, 0x1c, 0x1c, 0x1c,
+	 0x1c, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+	 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+	 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+	 0x38, 0x38, 0x38, 0x85, 0x85, 0x85, 0x85, 0x85,
+	 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+	 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+	 0x01,
+	 0x2a, 0x7e, 0x7e, 0xa8, 0x93, 0xa8, 0xff, 0xb6,
+	 0xb6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 },
+	{			/* Quality 15 */
+	 0x00,
+	 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	 0x20, 0x20, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20,
+	 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+	 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+	 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+	 0x40, 0x40, 0x40, 0x98, 0x98, 0x98, 0x98, 0x98,
+	 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+	 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+	 0x01,
+	 0x2a, 0x90, 0x90, 0xc0, 0xa8, 0xc0, 0xff, 0xd0,
+	 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 },
+	{			/* Quality 16-31 */
+	 0x00,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x01,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	 }
+};
+
+static const struct cmd tp6810_cx_init_common[] = {
+	{0x1c, 0x00},
+	{TP6800_R10_SIF_TYPE, 0x00},
+	{0x4e, 0x00},
+	{0x4f, 0x00},
+	{TP6800_R50, 0xff},
+	{TP6800_R51, 0x03},
+	{0x00, 0x07},
+	{TP6800_R79_QUALITY, 0x03},
+	{TP6800_R2F_TIMING_CFG, 0x37},
+	{TP6800_R30_SENSOR_CFG, 0x10},
+	{TP6800_R21_ENDP_1_CTL, 0x00},
+	{TP6800_R52, 0x40},
+	{TP6800_R53, 0x40},
+	{TP6800_R54_DARK_CFG, 0x40},
+	{TP6800_R30_SENSOR_CFG, 0x18},
+	{0x4b, 0x00},
+	{TP6800_R3F_FRAME_RATE, 0x83},
+	{TP6800_R79_QUALITY, 0x05},
+	{TP6800_R21_ENDP_1_CTL, 0x00},
+	{0x7c, 0x04},
+	{0x25, 0x14},
+	{0x26, 0x0f},
+	{0x7b, 0x10},
+};
+
+static const struct cmd tp6810_ov_init_common[] = {
+	{0x1c, 0x00},
+	{TP6800_R10_SIF_TYPE, 0x00},
+	{0x4e, 0x00},
+	{0x4f, 0x00},
+	{TP6800_R50, 0xff},
+	{TP6800_R51, 0x03},
+	{0x00, 0x07},
+	{TP6800_R52, 0x40},
+	{TP6800_R53, 0x40},
+	{TP6800_R54_DARK_CFG, 0x40},
+	{TP6800_R79_QUALITY, 0x03},
+	{TP6800_R2F_TIMING_CFG, 0x17},
+	{TP6800_R30_SENSOR_CFG, 0x18},
+	{TP6800_R21_ENDP_1_CTL, 0x00},
+	{TP6800_R3F_FRAME_RATE, 0x86},
+	{0x25, 0x18},
+	{0x26, 0x0f},
+	{0x7b, 0x90},
+};
+
+static const struct cmd tp6810_bridge_start[] = {
+	{0x59, 0x88},
+	{0x5a, 0x0f},
+	{0x5b, 0x4e},
+	{TP6800_R5C_EDGE_THRLD, 0x63},
+	{TP6800_R5D_DEMOSAIC_CFG, 0x00},
+	{0x03, 0x7f},
+	{0x04, 0x80},
+	{0x06, 0x00},
+	{0x00, 0x00},
+};
+
+static const struct cmd tp6810_late_start[] = {
+	{0x7d, 0x01},
+	{0xb0, 0x04},
+	{0xb1, 0x04},
+	{0xb2, 0x04},
+	{0xb3, 0x04},
+	{0xb4, 0x04},
+	{0xb5, 0x04},
+	{0xb6, 0x08},
+	{0xb7, 0x08},
+	{0xb8, 0x04},
+	{0xb9, 0x04},
+	{0xba, 0x04},
+	{0xbb, 0x04},
+	{0xbc, 0x04},
+	{0xbd, 0x08},
+	{0xbe, 0x08},
+	{0xbf, 0x08},
+	{0xc0, 0x04},
+	{0xc1, 0x04},
+	{0xc2, 0x08},
+	{0xc3, 0x08},
+	{0xc4, 0x08},
+	{0xc5, 0x08},
+	{0xc6, 0x08},
+	{0xc7, 0x13},
+	{0xc8, 0x04},
+	{0xc9, 0x08},
+	{0xca, 0x08},
+	{0xcb, 0x08},
+	{0xcc, 0x08},
+	{0xcd, 0x08},
+	{0xce, 0x13},
+	{0xcf, 0x13},
+	{0xd0, 0x08},
+	{0xd1, 0x08},
+	{0xd2, 0x08},
+	{0xd3, 0x08},
+	{0xd4, 0x08},
+	{0xd5, 0x13},
+	{0xd6, 0x13},
+	{0xd7, 0x13},
+	{0xd8, 0x08},
+	{0xd9, 0x08},
+	{0xda, 0x08},
+	{0xdb, 0x08},
+	{0xdc, 0x13},
+	{0xdd, 0x13},
+	{0xde, 0x13},
+	{0xdf, 0x13},
+	{0xe0, 0x08},
+	{0xe1, 0x08},
+	{0xe2, 0x08},
+	{0xe3, 0x13},
+	{0xe4, 0x13},
+	{0xe5, 0x13},
+	{0xe6, 0x13},
+	{0xe7, 0x13},
+	{0xe8, 0x08},
+	{0xe9, 0x08},
+	{0xea, 0x13},
+	{0xeb, 0x13},
+	{0xec, 0x13},
+	{0xed, 0x13},
+	{0xee, 0x13},
+	{0xef, 0x13},
+	{0x7d, 0x02},
+
+	/* later after isoc start */
+	{0x7d, 0x08},
+	{0x7d, 0x00},
+};
+
+static const struct cmd cx0342_timing_seq[] = {
+	{CX0342_CHANNEL_0_1_L_irst, 0x20},
+	{CX0342_CHANNEL_0_2_L_irst, 0x24},
+	{CX0342_CHANNEL_0_2_H_irst, 0x00},
+	{CX0342_CHANNEL_0_3_L_irst, 0x2f},
+	{CX0342_CHANNEL_0_3_H_irst, 0x00},
+	{CX0342_CHANNEL_1_0_L_itx, 0x02},
+	{CX0342_CHANNEL_1_0_H_itx, 0x00},
+	{CX0342_CHANNEL_1_1_L_itx, 0x20},
+	{CX0342_CHANNEL_1_1_H_itx, 0x00},
+	{CX0342_CHANNEL_1_2_L_itx, 0xe4},
+	{CX0342_CHANNEL_1_2_H_itx, 0x00},
+	{CX0342_CHANNEL_1_3_L_itx, 0xee},
+	{CX0342_CHANNEL_1_3_H_itx, 0x00},
+	{CX0342_CHANNEL_2_0_L_iwl, 0x30},
+	{CX0342_CHANNEL_2_0_H_iwl, 0x00},
+	{CX0342_CHANNEL_3_0_L_ensp, 0x34},
+	{CX0342_CHANNEL_3_1_L_ensp, 0xe2},
+	{CX0342_CHANNEL_3_1_H_ensp, 0x00},
+	{CX0342_CHANNEL_3_2_L_ensp, 0xf6},
+	{CX0342_CHANNEL_3_2_H_ensp, 0x00},
+	{CX0342_CHANNEL_3_3_L_ensp, 0xf4},
+	{CX0342_CHANNEL_3_3_H_ensp, 0x02},
+	{CX0342_CHANNEL_4_0_L_sela, 0x26},
+	{CX0342_CHANNEL_4_0_H_sela, 0x00},
+	{CX0342_CHANNEL_4_1_L_sela, 0xe2},
+	{CX0342_CHANNEL_4_1_H_sela, 0x00},
+	{CX0342_CHANNEL_5_0_L_intla, 0x26},
+	{CX0342_CHANNEL_5_1_L_intla, 0x29},
+	{CX0342_CHANNEL_5_2_L_intla, 0xf0},
+	{CX0342_CHANNEL_5_2_H_intla, 0x00},
+	{CX0342_CHANNEL_5_3_L_intla, 0xf3},
+	{CX0342_CHANNEL_5_3_H_intla, 0x00},
+	{CX0342_CHANNEL_6_0_L_xa_sel_pos, 0x24},
+	{CX0342_CHANNEL_7_1_L_cds_pos, 0x02},
+	{CX0342_TIMING_EN, 0x01},
+};
+
+/* define the JPEG header */
+static void jpeg_define(u8 *jpeg_hdr,
+			int height,
+			int width)
+{
+	memcpy(jpeg_hdr, jpeg_head, sizeof jpeg_head);
+	jpeg_hdr[JPEG_HEIGHT_OFFSET + 0] = height >> 8;
+	jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height;
+	jpeg_hdr[JPEG_HEIGHT_OFFSET + 2] = width >> 8;
+	jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width;
+}
+
+/* set the JPEG quality for sensor soi763a */
+static void jpeg_set_qual(u8 *jpeg_hdr,
+			  int quality)
+{
+	int i, sc;
+
+	if (quality < 50)
+		sc = 5000 / quality;
+	else
+		sc = 200 - quality * 2;
+	for (i = 0; i < 64; i++) {
+		jpeg_hdr[JPEG_QT0_OFFSET + i] =
+			(jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100;
+		jpeg_hdr[JPEG_QT1_OFFSET + i] =
+			(jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100;
+	}
+}
+
+static void reg_w(struct gspca_dev *gspca_dev, u8 index, u8 value)
+{
+	struct usb_device *dev = gspca_dev->dev;
+	int ret;
+
+	if (gspca_dev->usb_err < 0)
+		return;
+	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+			0x0e,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			value, index, NULL, 0, 500);
+	if (ret < 0) {
+		pr_err("reg_w err %d\n", ret);
+		gspca_dev->usb_err = ret;
+	}
+}
+
+/* the returned value is in gspca_dev->usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev, u8 index)
+{
+	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),
+			0x0d,
+			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			0, index, gspca_dev->usb_buf, 1, 500);
+	if (ret < 0) {
+		pr_err("reg_r err %d\n", ret);
+		gspca_dev->usb_err = ret;
+	}
+}
+
+static void reg_w_buf(struct gspca_dev *gspca_dev,
+			const struct cmd *p, int l)
+{
+	do {
+		reg_w(gspca_dev, p->reg, p->val);
+		p++;
+	} while (--l > 0);
+}
+
+static int i2c_w(struct gspca_dev *gspca_dev, u8 index, u8 value)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
+	reg_w(gspca_dev, TP6800_R19_SIF_ADDR_S2, index);
+	reg_w(gspca_dev, TP6800_R13_SIF_TX_DATA, value);
+	reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x01);
+	if (sd->bridge == BRIDGE_TP6800)
+		return 0;
+	msleep(5);
+	reg_r(gspca_dev, TP6800_R11_SIF_CONTROL);
+	if (gspca_dev->usb_buf[0] == 0)
+		return 0;
+	reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
+	return -1;				/* error */
+}
+
+static void i2c_w_buf(struct gspca_dev *gspca_dev,
+			const struct cmd *p, int l)
+{
+	do {
+		i2c_w(gspca_dev, p->reg, p->val);
+		p++;
+	} while (--l > 0);
+}
+
+static int i2c_r(struct gspca_dev *gspca_dev, u8 index, int len)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int v;
+
+	reg_w(gspca_dev, TP6800_R19_SIF_ADDR_S2, index);
+	reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x02);
+	msleep(5);
+	reg_r(gspca_dev, TP6800_R14_SIF_RX_DATA);
+	v = gspca_dev->usb_buf[0];
+	if (sd->bridge == BRIDGE_TP6800)
+		return v;
+	if (len > 1) {
+		reg_r(gspca_dev, TP6800_R1B_SIF_RX_DATA2);
+		v |= (gspca_dev->usb_buf[0] << 8);
+	}
+	reg_r(gspca_dev, TP6800_R11_SIF_CONTROL);
+	if (gspca_dev->usb_buf[0] == 0)
+		return v;
+	reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
+	return -1;
+}
+
+static void bulk_w(struct gspca_dev *gspca_dev,
+		  u8 tag,
+		  const u8 *data,
+		  int length)
+{
+	struct usb_device *dev = gspca_dev->dev;
+	int count, actual_count, ret;
+
+	if (gspca_dev->usb_err < 0)
+		return;
+	for (;;) {
+		count = length > BULK_OUT_SIZE - 1
+				? BULK_OUT_SIZE - 1 : length;
+		gspca_dev->usb_buf[0] = tag;
+		memcpy(&gspca_dev->usb_buf[1], data, count);
+		ret = usb_bulk_msg(dev,
+				   usb_sndbulkpipe(dev, 3),
+				   gspca_dev->usb_buf, count + 1,
+				   &actual_count, 500);
+		if (ret < 0) {
+			pr_err("bulk write error %d tag=%02x\n",
+				ret, tag);
+			gspca_dev->usb_err = ret;
+			return;
+		}
+		length -= count;
+		if (length <= 0)
+			break;
+		data += count;
+	}
+}
+
+static int probe_6810(struct gspca_dev *gspca_dev)
+{
+	u8 gpio;
+	int ret;
+
+	reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
+	gpio = gspca_dev->usb_buf[0];
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x04);	/* i2c 16 bits */
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x21);	/* ov??? */
+	reg_w(gspca_dev, TP6800_R1A_SIF_TX_DATA2, 0x00);
+	if (i2c_w(gspca_dev, 0x00, 0x00) >= 0)
+		return SENSOR_SOI763A;
+
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00);	/* i2c 8 bits */
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x7f);	/* (unknown i2c) */
+	if (i2c_w(gspca_dev, 0x00, 0x00) >= 0)
+		return -2;
+
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00);	/* i2c 8 bits */
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x11);	/* tas??? / hv??? */
+	ret = i2c_r(gspca_dev, 0x00, 1);
+	if (ret > 0)
+		return -3;
+
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x6e);	/* po??? */
+	ret = i2c_r(gspca_dev, 0x00, 1);
+	if (ret > 0)
+		return -4;
+
+	ret = i2c_r(gspca_dev, 0x01, 1);
+	if (ret > 0)
+		return -5;
+
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x04);	/* i2c 16 bits */
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x5d);	/* mi/mt??? */
+	ret = i2c_r(gspca_dev, 0x00, 2);
+	if (ret > 0)
+		return -6;
+
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x5c);	/* mi/mt??? */
+	ret = i2c_r(gspca_dev, 0x36, 2);
+	if (ret > 0)
+		return -7;
+
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x61);	/* (unknown i2c) */
+	reg_w(gspca_dev, TP6800_R1A_SIF_TX_DATA2, 0x10);
+	if (i2c_w(gspca_dev, 0xff, 0x00) >= 0)
+		return -8;
+
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+	reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00);	/* i2c 8 bits */
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20);	/* cx0342 */
+	ret = i2c_r(gspca_dev, 0x00, 1);
+	if (ret > 0)
+		return SENSOR_CX0342;
+	return -9;
+}
+
+static void cx0342_6810_init(struct gspca_dev *gspca_dev)
+{
+	static const struct cmd reg_init_1[] = {
+		{TP6800_R2F_TIMING_CFG, 0x2f},
+		{0x25, 0x02},
+		{TP6800_R21_ENDP_1_CTL, 0x00},
+		{TP6800_R3F_FRAME_RATE, 0x80},
+		{TP6800_R2F_TIMING_CFG, 0x2f},
+		{TP6800_R18_GPIO_DATA, 0xe1},
+		{TP6800_R18_GPIO_DATA, 0xc1},
+		{TP6800_R18_GPIO_DATA, 0xe1},
+		{TP6800_R11_SIF_CONTROL, 0x00},
+	};
+	static const struct cmd reg_init_2[] = {
+		{TP6800_R78_FORMAT, 0x48},
+		{TP6800_R11_SIF_CONTROL, 0x00},
+	};
+	static const struct cmd sensor_init[] = {
+		{CX0342_OUTPUT_CTRL, 0x07},
+		{CX0342_BYPASS_MODE, 0x58},
+		{CX0342_GPXLTHD_L, 0x28},
+		{CX0342_RBPXLTHD_L, 0x28},
+		{CX0342_PLANETHD_L, 0x50},
+		{CX0342_PLANETHD_H, 0x03},
+		{CX0342_RB_GAP_L, 0xff},
+		{CX0342_RB_GAP_H, 0x07},
+		{CX0342_G_GAP_L, 0xff},
+		{CX0342_G_GAP_H, 0x07},
+		{CX0342_RST_OVERFLOW_L, 0x5c},
+		{CX0342_RST_OVERFLOW_H, 0x01},
+		{CX0342_DATA_OVERFLOW_L, 0xfc},
+		{CX0342_DATA_OVERFLOW_H, 0x03},
+		{CX0342_DATA_UNDERFLOW_L, 0x00},
+		{CX0342_DATA_UNDERFLOW_H, 0x00},
+		{CX0342_SYS_CTRL_0, 0x40},
+		{CX0342_GLOBAL_GAIN, 0x01},
+		{CX0342_CLOCK_GEN, 0x00},
+		{CX0342_SYS_CTRL_0, 0x02},
+		{CX0342_IDLE_CTRL, 0x05},
+		{CX0342_ADCGN, 0x00},
+		{CX0342_ADC_CTL, 0x00},
+		{CX0342_LVRST_BLBIAS, 0x01},
+		{CX0342_VTHSEL, 0x0b},
+		{CX0342_RAMP_RIV, 0x0b},
+		{CX0342_LDOSEL, 0x07},
+		{CX0342_SPV_VALUE_L, 0x40},
+		{CX0342_SPV_VALUE_H, 0x02},
+
+		{CX0342_AUTO_ADC_CALIB, 0x81},
+		{CX0342_TIMING_EN, 0x01},
+	};
+
+	reg_w_buf(gspca_dev, reg_init_1, ARRAY_SIZE(reg_init_1));
+	reg_w_buf(gspca_dev, tp6810_cx_init_common,
+			ARRAY_SIZE(tp6810_cx_init_common));
+	reg_w_buf(gspca_dev, reg_init_2, ARRAY_SIZE(reg_init_2));
+
+	reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20);	/* cx0342 I2C addr */
+	i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
+	i2c_w_buf(gspca_dev, cx0342_timing_seq, ARRAY_SIZE(cx0342_timing_seq));
+}
+
+static void soi763a_6810_init(struct gspca_dev *gspca_dev)
+{
+	static const struct cmd reg_init_1[] = {
+		{TP6800_R2F_TIMING_CFG, 0x2f},
+		{TP6800_R18_GPIO_DATA, 0xe1},
+		{0x25, 0x02},
+		{TP6800_R21_ENDP_1_CTL, 0x00},
+		{TP6800_R3F_FRAME_RATE, 0x80},
+		{TP6800_R2F_TIMING_CFG, 0x2f},
+		{TP6800_R18_GPIO_DATA, 0xc1},
+	};
+	static const struct cmd reg_init_2[] = {
+		{TP6800_R78_FORMAT, 0x54},
+	};
+	static const struct cmd sensor_init[] = {
+		{0x00, 0x00},
+		{0x01, 0x80},
+		{0x02, 0x80},
+		{0x03, 0x90},
+		{0x04, 0x20},
+		{0x05, 0x20},
+		{0x06, 0x80},
+		{0x07, 0x00},
+		{0x08, 0xff},
+		{0x09, 0xff},
+		{0x0a, 0x76},		/* 7630 = soi673a */
+		{0x0b, 0x30},
+		{0x0c, 0x20},
+		{0x0d, 0x20},
+		{0x0e, 0xff},
+		{0x0f, 0xff},
+		{0x10, 0x41},
+		{0x15, 0x14},
+		{0x11, 0x40},
+		{0x12, 0x48},
+		{0x13, 0x80},
+		{0x14, 0x80},
+		{0x16, 0x03},
+		{0x28, 0xb0},
+		{0x71, 0x20},
+		{0x75, 0x8e},
+		{0x17, 0x1b},
+		{0x18, 0xbd},
+		{0x19, 0x05},
+		{0x1a, 0xf6},
+		{0x1b, 0x04},
+		{0x1c, 0x7f},		/* omnivision */
+		{0x1d, 0xa2},
+		{0x1e, 0x00},
+		{0x1f, 0x00},
+		{0x20, 0x45},
+		{0x21, 0x80},
+		{0x22, 0x80},
+		{0x23, 0xee},
+		{0x24, 0x50},
+		{0x25, 0x7a},
+		{0x26, 0xa0},
+		{0x27, 0x9a},
+		{0x29, 0x30},
+		{0x2a, 0x80},
+		{0x2b, 0x00},
+		{0x2c, 0xac},
+		{0x2d, 0x05},
+		{0x2e, 0x80},
+		{0x2f, 0x3c},
+		{0x30, 0x22},
+		{0x31, 0x00},
+		{0x32, 0x86},
+		{0x33, 0x08},
+		{0x34, 0xff},
+		{0x35, 0xff},
+		{0x36, 0xff},
+		{0x37, 0xff},
+		{0x38, 0xff},
+		{0x39, 0xff},
+		{0x3a, 0xfe},
+		{0x3b, 0xfe},
+		{0x3c, 0xfe},
+		{0x3d, 0xfe},
+		{0x3e, 0xfe},
+		{0x3f, 0x71},
+		{0x40, 0xff},
+		{0x41, 0xff},
+		{0x42, 0xff},
+		{0x43, 0xff},
+		{0x44, 0xff},
+		{0x45, 0xff},
+		{0x46, 0xff},
+		{0x47, 0xff},
+		{0x48, 0xff},
+		{0x49, 0xff},
+		{0x4a, 0xfe},
+		{0x4b, 0xff},
+		{0x4c, 0x00},
+		{0x4d, 0x00},
+		{0x4e, 0xff},
+		{0x4f, 0xff},
+		{0x50, 0xff},
+		{0x51, 0xff},
+		{0x52, 0xff},
+		{0x53, 0xff},
+		{0x54, 0xff},
+		{0x55, 0xff},
+		{0x56, 0xff},
+		{0x57, 0xff},
+		{0x58, 0xff},
+		{0x59, 0xff},
+		{0x5a, 0xff},
+		{0x5b, 0xfe},
+		{0x5c, 0xff},
+		{0x5d, 0x8f},
+		{0x5e, 0xff},
+		{0x5f, 0x8f},
+		{0x60, 0xa2},
+		{0x61, 0x4a},
+		{0x62, 0xf3},
+		{0x63, 0x75},
+		{0x64, 0xf0},
+		{0x65, 0x00},
+		{0x66, 0x55},
+		{0x67, 0x92},
+		{0x68, 0xa0},
+		{0x69, 0x4a},
+		{0x6a, 0x22},
+		{0x6b, 0x00},
+		{0x6c, 0x33},
+		{0x6d, 0x44},
+		{0x6e, 0x22},
+		{0x6f, 0x84},
+		{0x70, 0x0b},
+		{0x72, 0x10},
+		{0x73, 0x50},
+		{0x74, 0x21},
+		{0x76, 0x00},
+		{0x77, 0xa5},
+		{0x78, 0x80},
+		{0x79, 0x80},
+		{0x7a, 0x80},
+		{0x7b, 0xe2},
+		{0x7c, 0x00},
+		{0x7d, 0xf7},
+		{0x7e, 0x00},
+		{0x7f, 0x00},
+	};
+
+	reg_w_buf(gspca_dev, reg_init_1, ARRAY_SIZE(reg_init_1));
+	reg_w_buf(gspca_dev, tp6810_ov_init_common,
+			ARRAY_SIZE(tp6810_ov_init_common));
+	reg_w_buf(gspca_dev, reg_init_2, ARRAY_SIZE(reg_init_2));
+
+	i2c_w(gspca_dev, 0x12, 0x80);		/* sensor reset */
+	msleep(10);
+	i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
+}
+
+/* set the gain and exposure */
+static void setexposure(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (sd->sensor == SENSOR_CX0342) {
+		int expo;
+
+		expo = (sd->ctrls[EXPOSURE].val << 2) - 1;
+		i2c_w(gspca_dev, CX0342_EXPO_LINE_L, expo);
+		i2c_w(gspca_dev, CX0342_EXPO_LINE_H, expo >> 8);
+		if (sd->bridge == BRIDGE_TP6800)
+			i2c_w(gspca_dev, CX0342_RAW_GBGAIN_H,
+						sd->ctrls[GAIN].val >> 8);
+		i2c_w(gspca_dev, CX0342_RAW_GBGAIN_L, sd->ctrls[GAIN].val);
+		if (sd->bridge == BRIDGE_TP6800)
+			i2c_w(gspca_dev, CX0342_RAW_GRGAIN_H,
+						sd->ctrls[GAIN].val >> 8);
+		i2c_w(gspca_dev, CX0342_RAW_GRGAIN_L, sd->ctrls[GAIN].val);
+		if (sd->bridge == BRIDGE_TP6800)
+			i2c_w(gspca_dev, CX0342_RAW_BGAIN_H,
+						sd->ctrls[BGAIN].val >> 8);
+		i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, sd->ctrls[BGAIN].val);
+		if (sd->bridge == BRIDGE_TP6800)
+			i2c_w(gspca_dev, CX0342_RAW_RGAIN_H,
+						sd->ctrls[RGAIN].val >> 8);
+		i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, sd->ctrls[RGAIN].val);
+		i2c_w(gspca_dev, CX0342_SYS_CTRL_0,
+				sd->bridge == BRIDGE_TP6800 ? 0x80 : 0x81);
+		return;
+	}
+
+	/* soi763a */
+	i2c_w(gspca_dev, 0x10,		/* AEC_H (exposure time) */
+			 sd->ctrls[EXPOSURE].val);
+/*	i2c_w(gspca_dev, 0x76, 0x02);	 * AEC_L ([1:0] */
+	i2c_w(gspca_dev, 0x00,		/* gain */
+			 sd->ctrls[GAIN].val);
+}
+
+/* set the JPEG quantization tables */
+static void set_dqt(struct gspca_dev *gspca_dev, u8 q)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	/* update the jpeg quantization tables */
+	PDEBUG(D_STREAM, "q %d -> %d", sd->quality, q);
+	sd->quality = q;
+	if (q > 16)
+		q = 16;
+	if (sd->sensor == SENSOR_SOI763A)
+		jpeg_set_qual(sd->jpeg_hdr, jpeg_q[q]);
+	else
+		memcpy(&sd->jpeg_hdr[JPEG_QT0_OFFSET - 1],
+			DQT[q], sizeof DQT[0]);
+}
+
+/* set the JPEG compression quality factor */
+static void setquality(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u16 q;
+
+	q = sd->ctrls[QUALITY].val;
+	if (q != 16)
+		q = 15 - q;
+
+	reg_w(gspca_dev, TP6800_R7A_BLK_THRLD, 0x00);
+	reg_w(gspca_dev, TP6800_R79_QUALITY, 0x04);
+	reg_w(gspca_dev, TP6800_R79_QUALITY, q);
+
+	/* auto quality */
+	if (q == 15 && sd->bridge == BRIDGE_TP6810) {
+		msleep(4);
+		reg_w(gspca_dev, TP6800_R7A_BLK_THRLD, 0x19);
+	}
+}
+
+static const u8 color_null[18] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+static const u8 color_gain[NSENSORS][18] = {
+[SENSOR_CX0342] =
+	{0x4c, 0x00, 0xa9, 0x00, 0x31, 0x00,	/* Y R/G/B (LE values) */
+	 0xb6, 0x03, 0x6c, 0x03, 0xe0, 0x00,	/* U R/G/B */
+	 0xdf, 0x00, 0x46, 0x03, 0xdc, 0x03},	/* V R/G/B */
+[SENSOR_SOI763A] =
+	{0x4c, 0x00, 0x95, 0x00, 0x1d, 0x00,	/* Y R/G/B (LE values) */
+	 0xb6, 0x03, 0x6c, 0x03, 0xd7, 0x00,	/* U R/G/B */
+	 0xd5, 0x00, 0x46, 0x03, 0xdc, 0x03},	/* V R/G/B */
+};
+
+static void setgamma(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int gamma;
+#define NGAMMA 6
+	static const u8 gamma_tb[NGAMMA][3][1024] = {
+	    {				/* gamma 0 - from tp6800 + soi763a */
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+		 0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
+		 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
+		 0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
+		 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
+		 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
+		 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
+		 0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
+		 0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
+		 0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
+		 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
+		 0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
+		 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
+		 0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
+		 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
+		 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
+		 0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
+		 0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
+		 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
+		 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
+		 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
+		 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
+		 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
+		 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
+		 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
+		 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
+		 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
+		 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
+		 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
+		 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
+		 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
+		 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
+		 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
+		 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
+		 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
+		 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
+		 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
+		 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
+		 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+		 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
+		 0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
+		 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+		 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+		 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
+		 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
+		 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
+		 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+		 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
+		 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+		 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
+		 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+		 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
+		 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+		 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+		 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+		 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
+		 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
+		 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+		 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
+		 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+		 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+		 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
+		 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
+		 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+		 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+		 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
+		 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
+		 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
+		 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+		 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+		 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
+		 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+		 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
+		 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+		 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+		 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+		 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
+		 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+		 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+		 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
+		 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+		 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
+		 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
+		 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+		 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
+		 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+		 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
+		 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+		 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+		 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+		 0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
+		 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
+		 0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
+		 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
+		 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
+		 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
+		 0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
+		 0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
+		 0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
+		 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
+		 0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
+		 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
+		 0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
+		 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
+		 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
+		 0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
+		 0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
+		 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
+		 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
+		 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
+		 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
+		 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
+		 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
+		 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
+		 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
+		 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
+		 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
+		 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
+		 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
+		 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
+		 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
+		 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
+		 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
+		 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
+		 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
+		 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
+		 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
+		 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+		 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
+		 0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
+		 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+		 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+		 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
+		 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
+		 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
+		 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+		 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
+		 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+		 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
+		 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+		 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
+		 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+		 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+		 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+		 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
+		 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
+		 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+		 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
+		 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+		 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+		 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
+		 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
+		 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+		 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+		 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
+		 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
+		 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
+		 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+		 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+		 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
+		 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+		 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
+		 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+		 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+		 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+		 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
+		 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+		 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+		 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
+		 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+		 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
+		 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
+		 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+		 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
+		 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+		 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
+		 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+		 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+		 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+		 0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
+		 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
+		 0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
+		 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
+		 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
+		 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
+		 0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
+		 0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
+		 0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
+		 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
+		 0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
+		 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
+		 0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
+		 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
+		 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
+		 0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
+		 0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
+		 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
+		 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
+		 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
+		 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
+		 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
+		 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
+		 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
+		 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
+		 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
+		 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x76,
+		 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
+		 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
+		 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
+		 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
+		 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
+		 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
+		 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
+		 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
+		 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
+		 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
+		 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+		 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
+		 0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
+		 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+		 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+		 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
+		 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
+		 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
+		 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+		 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
+		 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+		 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
+		 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+		 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
+		 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+		 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+		 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+		 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
+		 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
+		 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+		 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
+		 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+		 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+		 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
+		 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
+		 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+		 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+		 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
+		 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
+		 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
+		 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+		 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+		 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
+		 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+		 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
+		 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+		 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+		 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+		 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
+		 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+		 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+		 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
+		 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+		 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
+		 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
+		 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+		 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
+		 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+		 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
+		 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+		 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+		 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
+	    },
+	    {				/* gamma 1 - from tp6810 + soi763a */
+		{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, 0x02, 0x03, 0x05, 0x07, 0x08, 0x09, 0x0a,
+		 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x15,
+		 0x16, 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1c, 0x1e,
+		 0x1f, 0x20, 0x22, 0x22, 0x23, 0x25, 0x26, 0x27,
+		 0x27, 0x28, 0x29, 0x2b, 0x2b, 0x2c, 0x2d, 0x2f,
+		 0x2f, 0x30, 0x31, 0x33, 0x33, 0x34, 0x35, 0x35,
+		 0x37, 0x38, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c,
+		 0x3c, 0x3d, 0x3f, 0x3f, 0x40, 0x42, 0x42, 0x43,
+		 0x43, 0x44, 0x45, 0x45, 0x47, 0x47, 0x48, 0x49,
+		 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d,
+		 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
+		 0x54, 0x54, 0x55, 0x56, 0x56, 0x58, 0x58, 0x59,
+		 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5e,
+		 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61, 0x61,
+		 0x62, 0x62, 0x63, 0x63, 0x65, 0x65, 0x65, 0x66,
+		 0x66, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69, 0x69,
+		 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
+		 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71,
+		 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75,
+		 0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79,
+		 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c,
+		 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x80,
+		 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x84, 0x84,
+		 0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x88,
+		 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a,
+		 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e,
+		 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x91,
+		 0x91, 0x91, 0x92, 0x92, 0x92, 0x92, 0x93, 0x93,
+		 0x93, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x97,
+		 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
+		 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b,
+		 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9e,
+		 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
+		 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3,
+		 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5,
+		 0xa5, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+		 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xab,
+		 0xac, 0xac, 0xac, 0xad, 0xad, 0xad, 0xad, 0xae,
+		 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0,
+		 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+		 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4,
+		 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
+		 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
+		 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
+		 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
+		 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+		 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
+		 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4,
+		 0xc4, 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6,
+		 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7,
+		 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
+		 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
+		 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+		 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+		 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
+		 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4,
+		 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+		 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
+		 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda,
+		 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb,
+		 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+		 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
+		 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
+		 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
+		 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+		 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+		 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8,
+		 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9,
+		 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec,
+		 0xec, 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed,
+		 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
+		 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+		 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3,
+		 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
+		 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
+		 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
+		 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+		 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe,
+		 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 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, 0x01, 0x02, 0x03,
+		 0x05, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0c, 0x0d,
+		 0x0e, 0x10, 0x10, 0x11, 0x12, 0x14, 0x15, 0x15,
+		 0x16, 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1c, 0x1e,
+		 0x1e, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x25, 0x25,
+		 0x26, 0x27, 0x27, 0x28, 0x29, 0x29, 0x2b, 0x2c,
+		 0x2c, 0x2d, 0x2d, 0x2f, 0x30, 0x30, 0x31, 0x31,
+		 0x33, 0x34, 0x34, 0x35, 0x35, 0x37, 0x38, 0x38,
+		 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d,
+		 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x42, 0x43,
+		 0x43, 0x44, 0x44, 0x45, 0x45, 0x47, 0x47, 0x48,
+		 0x48, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4c,
+		 0x4c, 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50,
+		 0x52, 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x55,
+		 0x55, 0x56, 0x56, 0x56, 0x58, 0x58, 0x59, 0x59,
+		 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c,
+		 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x60,
+		 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, 0x65,
+		 0x65, 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67,
+		 0x68, 0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a,
+		 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e,
+		 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
+		 0x71, 0x71, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74,
+		 0x75, 0x75, 0x75, 0x77, 0x77, 0x77, 0x78, 0x78,
+		 0x78, 0x79, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a,
+		 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d,
+		 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80,
+		 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
+		 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
+		 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89, 0x89,
+		 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b,
+		 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e,
+		 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
+		 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
+		 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
+		 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97,
+		 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99,
+		 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b,
+		 0x9b, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
+		 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0,
+		 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
+		 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
+		 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
+		 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
+		 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab,
+		 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+		 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
+		 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+		 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+		 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+		 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
+		 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
+		 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+		 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
+		 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+		 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf,
+		 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+		 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
+		 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
+		 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
+		 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9,
+		 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
+		 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
+		 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd,
+		 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce, 0xcf,
+		 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
+		 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
+		 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4,
+		 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+		 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8,
+		 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb,
+		 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+		 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
+		 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+		 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2,
+		 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3,
+		 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+		 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+		 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+		 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
+		 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+		 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
+		 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+		 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+		 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1,
+		 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4,
+		 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5,
+		 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7,
+		 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc,
+		 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+		 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe,
+		 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 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, 0x01, 0x02, 0x03, 0x05, 0x05, 0x07,
+		 0x08, 0x09, 0x0a, 0x0a, 0x0c, 0x0d, 0x0e, 0x0e,
+		 0x10, 0x11, 0x12, 0x12, 0x14, 0x15, 0x16, 0x16,
+		 0x17, 0x18, 0x18, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
+		 0x1e, 0x1f, 0x1f, 0x20, 0x22, 0x22, 0x23, 0x23,
+		 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x29, 0x29,
+		 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f, 0x30,
+		 0x30, 0x31, 0x31, 0x33, 0x33, 0x34, 0x34, 0x35,
+		 0x35, 0x37, 0x37, 0x38, 0x38, 0x39, 0x39, 0x3a,
+		 0x3a, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d,
+		 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x42, 0x42, 0x43,
+		 0x43, 0x44, 0x44, 0x45, 0x45, 0x47, 0x47, 0x47,
+		 0x48, 0x48, 0x49, 0x49, 0x49, 0x4a, 0x4a, 0x4b,
+		 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4f,
+		 0x4f, 0x50, 0x50, 0x50, 0x52, 0x52, 0x52, 0x53,
+		 0x53, 0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x56,
+		 0x56, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x5a,
+		 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c,
+		 0x5e, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60,
+		 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63,
+		 0x63, 0x63, 0x65, 0x65, 0x65, 0x66, 0x66, 0x66,
+		 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x69,
+		 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
+		 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e,
+		 0x6f, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
+		 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x74, 0x74,
+		 0x74, 0x74, 0x75, 0x75, 0x75, 0x75, 0x77, 0x77,
+		 0x77, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79,
+		 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b,
+		 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
+		 0x7d, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80,
+		 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82,
+		 0x82, 0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85,
+		 0x85, 0x86, 0x86, 0x86, 0x86, 0x88, 0x88, 0x88,
+		 0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x8a, 0x8a,
+		 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d,
+		 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
+		 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
+		 0x90, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92,
+		 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94, 0x94,
+		 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96, 0x96,
+		 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+		 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
+		 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
+		 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0,
+		 0xa0, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1,
+		 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3,
+		 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
+		 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6,
+		 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
+		 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab,
+		 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac,
+		 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xae, 0xae,
+		 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+		 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
+		 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2,
+		 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4,
+		 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6,
+		 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
+		 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
+		 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba,
+		 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
+		 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
+		 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
+		 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
+		 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3,
+		 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
+		 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
+		 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
+		 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+		 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb,
+		 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
+		 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce,
+		 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+		 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0,
+		 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
+		 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
+		 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7,
+		 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
+		 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+		 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+		 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
+		 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0,
+		 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
+		 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3,
+		 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4,
+		 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
+		 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7,
+		 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
+		 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb,
+		 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+		 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xee,
+		 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef, 0xef,
+		 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1,
+		 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3,
+		 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5,
+		 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+		 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc,
+		 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd,
+		 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+	    },
+	    {							/* gamma 2 */
+		{0x00, 0x01, 0x02, 0x05, 0x07, 0x08, 0x0a, 0x0c,
+		 0x0d, 0x0e, 0x10, 0x12, 0x14, 0x15, 0x16, 0x17,
+		 0x18, 0x1a, 0x1b, 0x1c, 0x1e, 0x1f, 0x20, 0x22,
+		 0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2c,
+		 0x2d, 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34, 0x34,
+		 0x35, 0x37, 0x38, 0x38, 0x39, 0x3a, 0x3b, 0x3b,
+		 0x3c, 0x3d, 0x3f, 0x3f, 0x40, 0x42, 0x42, 0x43,
+		 0x44, 0x44, 0x45, 0x47, 0x47, 0x48, 0x49, 0x49,
+		 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4f, 0x4f,
+		 0x50, 0x50, 0x52, 0x53, 0x53, 0x54, 0x54, 0x55,
+		 0x55, 0x56, 0x56, 0x58, 0x58, 0x59, 0x5a, 0x5a,
+		 0x5b, 0x5b, 0x5c, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f,
+		 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x63, 0x63,
+		 0x65, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
+		 0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
+		 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x70,
+		 0x70, 0x70, 0x71, 0x71, 0x73, 0x73, 0x73, 0x74,
+		 0x74, 0x75, 0x75, 0x75, 0x77, 0x77, 0x78, 0x78,
+		 0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b,
+		 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f,
+		 0x7f, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82,
+		 0x82, 0x82, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85,
+		 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x89, 0x89,
+		 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8d,
+		 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f,
+		 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+		 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94,
+		 0x94, 0x94, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
+		 0x97, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99,
+		 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b,
+		 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
+		 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, 0xa1,
+		 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3,
+		 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5,
+		 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8,
+		 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
+		 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xad,
+		 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
+		 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0,
+		 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2,
+		 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, 0xb4,
+		 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
+		 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
+		 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba,
+		 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
+		 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
+		 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0,
+		 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3,
+		 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4,
+		 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6,
+		 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7,
+		 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+		 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb,
+		 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
+		 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce,
+		 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0,
+		 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1,
+		 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4,
+		 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
+		 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
+		 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda,
+		 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd,
+		 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde,
+		 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
+		 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1,
+		 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
+		 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4,
+		 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5,
+		 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6,
+		 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8,
+		 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9,
+		 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+		 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed,
+		 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
+		 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+		 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1,
+		 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3,
+		 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
+		 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+		 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9,
+		 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+		{0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x05,
+		 0x07, 0x08, 0x09, 0x0a, 0x0d, 0x0e, 0x10, 0x11,
+		 0x12, 0x14, 0x15, 0x16, 0x16, 0x17, 0x18, 0x1a,
+		 0x1b, 0x1c, 0x1e, 0x1f, 0x20, 0x20, 0x22, 0x23,
+		 0x25, 0x26, 0x26, 0x27, 0x28, 0x29, 0x29, 0x2b,
+		 0x2c, 0x2d, 0x2d, 0x2f, 0x30, 0x30, 0x31, 0x33,
+		 0x33, 0x34, 0x35, 0x35, 0x37, 0x38, 0x38, 0x39,
+		 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3d, 0x3f,
+		 0x3f, 0x40, 0x42, 0x42, 0x43, 0x43, 0x44, 0x44,
+		 0x45, 0x45, 0x47, 0x47, 0x48, 0x48, 0x49, 0x4a,
+		 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d,
+		 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
+		 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x58,
+		 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
+		 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f,
+		 0x60, 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x63,
+		 0x63, 0x63, 0x65, 0x65, 0x65, 0x66, 0x66, 0x67,
+		 0x67, 0x67, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69,
+		 0x6a, 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d,
+		 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
+		 0x70, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x73,
+		 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77, 0x77,
+		 0x77, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x79,
+		 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7b, 0x7c,
+		 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7f, 0x7f,
+		 0x7f, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81,
+		 0x82, 0x82, 0x82, 0x82, 0x84, 0x84, 0x84, 0x84,
+		 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x88,
+		 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x8a,
+		 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d,
+		 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f,
+		 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x91,
+		 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
+		 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
+		 0x94, 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
+		 0x97, 0x98, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99,
+		 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b,
+		 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9c,
+		 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e,
+		 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa1,
+		 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2,
+		 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+		 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+		 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
+		 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
+		 0xab, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac,
+		 0xac, 0xac, 0xad, 0xad, 0xad, 0xad, 0xad, 0xae,
+		 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf,
+		 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1,
+		 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2,
+		 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
+		 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6,
+		 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
+		 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9,
+		 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
+		 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
+		 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe,
+		 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf,
+		 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+		 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
+		 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4,
+		 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5,
+		 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7,
+		 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
+		 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
+		 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
+		 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
+		 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
+		 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
+		 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1,
+		 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
+		 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
+		 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+		 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
+		 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
+		 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
+		 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
+		 0xdb, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+		 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf,
+		 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0,
+		 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1,
+		 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
+		 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
+		 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+		 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6,
+		 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+		 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
+		 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+		 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+		 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
+		 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xef,
+		 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
+		 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
+		 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4,
+		 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5,
+		 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+		 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9,
+		 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+		{0x00, 0x00, 0x00, 0x01, 0x02, 0x05, 0x07, 0x08,
+		 0x09, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x12, 0x14,
+		 0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1e,
+		 0x1f, 0x20, 0x20, 0x22, 0x23, 0x25, 0x26, 0x27,
+		 0x28, 0x28, 0x29, 0x2b, 0x2c, 0x2d, 0x2d, 0x2f,
+		 0x30, 0x31, 0x31, 0x33, 0x34, 0x35, 0x35, 0x37,
+		 0x38, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, 0x3c,
+		 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x43, 0x43,
+		 0x44, 0x44, 0x45, 0x47, 0x47, 0x48, 0x48, 0x49,
+		 0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d,
+		 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
+		 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58,
+		 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c,
+		 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
+		 0x61, 0x61, 0x62, 0x62, 0x63, 0x63, 0x65, 0x65,
+		 0x65, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68,
+		 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
+		 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f,
+		 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x73, 0x73,
+		 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
+		 0x77, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x7a,
+		 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c,
+		 0x7c, 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80,
+		 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82,
+		 0x82, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85,
+		 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
+		 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b,
+		 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e,
+		 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90,
+		 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
+		 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
+		 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97,
+		 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99,
+		 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b,
+		 0x9b, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
+		 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0,
+		 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
+		 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
+		 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
+		 0xa5, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
+		 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
+		 0xab, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac,
+		 0xad, 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
+		 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0,
+		 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1,
+		 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3,
+		 0xb3, 0xb3, 0xb3, 0xb4, 0xb3, 0xb4, 0xb4, 0xb4,
+		 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+		 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
+		 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
+		 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
+		 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe,
+		 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
+		 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
+		 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
+		 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
+		 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
+		 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
+		 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+		 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb,
+		 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
+		 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce,
+		 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+		 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0,
+		 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
+		 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
+		 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+		 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8,
+		 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda,
+		 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
+		 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+		 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
+		 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,
+		 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+		 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3,
+		 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+		 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6,
+		 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
+		 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
+		 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9,
+		 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec,
+		 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed,
+		 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
+		 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+		 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1,
+		 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3,
+		 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
+		 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7,
+		 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+		 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
+	    },
+	    {				/* gamma 3 - from tp6810 + cx0342 */
+		{0x08, 0x09, 0x0c, 0x0d, 0x10, 0x11, 0x14, 0x15,
+		 0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x1f, 0x20, 0x23,
+		 0x25, 0x26, 0x27, 0x28, 0x2b, 0x2c, 0x2d, 0x2f,
+		 0x30, 0x31, 0x33, 0x34, 0x35, 0x37, 0x38, 0x39,
+		 0x3a, 0x3b, 0x3c, 0x3d, 0x3f, 0x40, 0x42, 0x43,
+		 0x44, 0x45, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b,
+		 0x4c, 0x4d, 0x4d, 0x4f, 0x50, 0x52, 0x53, 0x53,
+		 0x54, 0x55, 0x56, 0x56, 0x58, 0x59, 0x5a, 0x5a,
+		 0x5b, 0x5c, 0x5c, 0x5e, 0x5f, 0x5f, 0x60, 0x61,
+		 0x61, 0x62, 0x63, 0x63, 0x65, 0x66, 0x66, 0x67,
+		 0x68, 0x68, 0x69, 0x69, 0x6a, 0x6c, 0x6c, 0x6d,
+		 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x73,
+		 0x73, 0x74, 0x74, 0x75, 0x75, 0x77, 0x77, 0x78,
+		 0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c,
+		 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81,
+		 0x82, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
+		 0x86, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b,
+		 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f,
+		 0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92, 0x93,
+		 0x93, 0x93, 0x94, 0x94, 0x96, 0x96, 0x97, 0x97,
+		 0x97, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d,
+		 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
+		 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+		 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa8, 0xa8,
+		 0xa8, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac,
+		 0xac, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
+		 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
+		 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3,
+		 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+		 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
+		 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
+		 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf,
+		 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2,
+		 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5,
+		 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
+		 0xc7, 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+		 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
+		 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce,
+		 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
+		 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3,
+		 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6,
+		 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
+		 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda,
+		 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd,
+		 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf,
+		 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1,
+		 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
+		 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4,
+		 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+		 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8,
+		 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb,
+		 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+		 0xed, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
+		 0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
+		 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
+		 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
+		 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+		 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9,
+		 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+		 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd,
+		 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		{0x03, 0x05, 0x07, 0x09, 0x0a, 0x0c, 0x0d, 0x10,
+		 0x11, 0x12, 0x14, 0x15, 0x17, 0x18, 0x1a, 0x1b,
+		 0x1c, 0x1e, 0x1f, 0x20, 0x22, 0x23, 0x25, 0x26,
+		 0x27, 0x28, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2f,
+		 0x30, 0x31, 0x33, 0x33, 0x34, 0x35, 0x37, 0x38,
+		 0x38, 0x39, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3f,
+		 0x3f, 0x40, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45,
+		 0x47, 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b, 0x4b,
+		 0x4c, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x52, 0x52,
+		 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, 0x58,
+		 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c,
+		 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
+		 0x61, 0x62, 0x62, 0x63, 0x63, 0x65, 0x65, 0x66,
+		 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69,
+		 0x6a, 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e,
+		 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71,
+		 0x71, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75,
+		 0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79,
+		 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c,
+		 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80,
+		 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x84,
+		 0x84, 0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86,
+		 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a,
+		 0x8a, 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e,
+		 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90,
+		 0x90, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92,
+		 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x96,
+		 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x98, 0x98,
+		 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a,
+		 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c,
+		 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e,
+		 0xa0, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1,
+		 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3,
+		 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
+		 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+		 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
+		 0xab, 0xac, 0xac, 0xac, 0xac, 0xad, 0xad, 0xad,
+		 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf,
+		 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1,
+		 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
+		 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4,
+		 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+		 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9,
+		 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
+		 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
+		 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+		 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0,
+		 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3,
+		 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4,
+		 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
+		 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
+		 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+		 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb,
+		 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
+		 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
+		 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0,
+		 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1,
+		 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4,
+		 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6,
+		 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+		 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
+		 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
+		 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
+		 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+		 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
+		 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1,
+		 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2,
+		 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
+		 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
+		 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+		 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+		 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
+		 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+		 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec,
+		 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xee,
+		 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
+		 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+		 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+		 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
+		 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
+		 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+		 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
+		 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc,
+		 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+		 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe,
+		 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		{0x07, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14,
+		 0x16, 0x17, 0x18, 0x1b, 0x1c, 0x1e, 0x1f, 0x20,
+		 0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2d,
+		 0x2f, 0x30, 0x31, 0x33, 0x34, 0x35, 0x37, 0x38,
+		 0x39, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3f, 0x40,
+		 0x42, 0x43, 0x44, 0x44, 0x45, 0x47, 0x48, 0x49,
+		 0x4a, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4f, 0x50,
+		 0x52, 0x52, 0x53, 0x54, 0x55, 0x55, 0x56, 0x58,
+		 0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5e,
+		 0x5f, 0x5f, 0x60, 0x61, 0x61, 0x62, 0x63, 0x63,
+		 0x65, 0x65, 0x66, 0x67, 0x67, 0x68, 0x68, 0x69,
+		 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e,
+		 0x6f, 0x70, 0x70, 0x71, 0x71, 0x73, 0x73, 0x74,
+		 0x74, 0x75, 0x75, 0x77, 0x77, 0x78, 0x78, 0x79,
+		 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7d,
+		 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81,
+		 0x82, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
+		 0x88, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b,
+		 0x8b, 0x8b, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f,
+		 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92,
+		 0x92, 0x93, 0x93, 0x94, 0x94, 0x94, 0x96, 0x96,
+		 0x96, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
+		 0x99, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+		 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0xa0,
+		 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3,
+		 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5,
+		 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, 0xa9,
+		 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac,
+		 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xaf, 0xaf,
+		 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1,
+		 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb4,
+		 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+		 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
+		 0xb9, 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc,
+		 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf,
+		 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
+		 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4,
+		 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
+		 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9,
+		 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb,
+		 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
+		 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xcf,
+		 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1,
+		 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3,
+		 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
+		 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
+		 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda,
+		 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
+		 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde,
+		 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+		 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+		 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
+		 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5,
+		 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
+		 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
+		 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb,
+		 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
+		 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
+		 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
+		 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+		 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+		 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+		 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9,
+		 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+		 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd,
+		 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+	    },
+	    {				/* gamma 4 - from tp6800 + soi763a */
+		{0x11, 0x14, 0x15, 0x17, 0x1a, 0x1b, 0x1e, 0x1f,
+		 0x22, 0x23, 0x25, 0x27, 0x28, 0x2b, 0x2c, 0x2d,
+		 0x2f, 0x31, 0x33, 0x34, 0x35, 0x38, 0x39, 0x3a,
+		 0x3b, 0x3c, 0x3d, 0x40, 0x42, 0x43, 0x44, 0x45,
+		 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4f,
+		 0x50, 0x52, 0x53, 0x53, 0x54, 0x55, 0x56, 0x58,
+		 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5f, 0x60,
+		 0x61, 0x61, 0x62, 0x63, 0x65, 0x65, 0x66, 0x67,
+		 0x68, 0x68, 0x69, 0x6a, 0x6c, 0x6c, 0x6d, 0x6e,
+		 0x6f, 0x6f, 0x70, 0x71, 0x71, 0x73, 0x74, 0x74,
+		 0x75, 0x77, 0x77, 0x78, 0x79, 0x79, 0x7a, 0x7a,
+		 0x7b, 0x7c, 0x7c, 0x7d, 0x7f, 0x7f, 0x80, 0x80,
+		 0x81, 0x81, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86,
+		 0x86, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b, 0x8b,
+		 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x90, 0x90, 0x91,
+		 0x91, 0x92, 0x92, 0x93, 0x93, 0x94, 0x94, 0x96,
+		 0x96, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
+		 0x9a, 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d,
+		 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2,
+		 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5,
+		 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9, 0xab,
+		 0xab, 0xab, 0xac, 0xac, 0xad, 0xad, 0xad, 0xae,
+		 0xae, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1,
+		 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4,
+		 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8,
+		 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xbc,
+		 0xbc, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf,
+		 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2,
+		 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+		 0xc5, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc9,
+		 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
+		 0xcb, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xce,
+		 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0,
+		 0xd0, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+		 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
+		 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb,
+		 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf,
+		 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1,
+		 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
+		 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+		 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
+		 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9,
+		 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec,
+		 0xec, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
+		 0xee, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
+		 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3,
+		 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5,
+		 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
+		 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9,
+		 0xf9, 0xf9, 0xfa, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+		{0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x14, 0x15,
+		 0x16, 0x17, 0x1a, 0x1b, 0x1c, 0x1e, 0x1f, 0x20,
+		 0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2c,
+		 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34, 0x34, 0x35,
+		 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d,
+		 0x3f, 0x40, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45,
+		 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b, 0x4b, 0x4c,
+		 0x4d, 0x4f, 0x4f, 0x50, 0x52, 0x52, 0x53, 0x54,
+		 0x54, 0x55, 0x55, 0x56, 0x58, 0x58, 0x59, 0x5a,
+		 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f,
+		 0x60, 0x60, 0x61, 0x61, 0x62, 0x63, 0x63, 0x65,
+		 0x65, 0x66, 0x66, 0x67, 0x67, 0x68, 0x68, 0x69,
+		 0x69, 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e,
+		 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71, 0x73,
+		 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x77, 0x77,
+		 0x78, 0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b,
+		 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f,
+		 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82,
+		 0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86, 0x86,
+		 0x88, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8a,
+		 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e,
+		 0x8e, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91,
+		 0x91, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x94,
+		 0x94, 0x94, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
+		 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a,
+		 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c,
+		 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0xa0,
+		 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
+		 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4,
+		 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa6,
+		 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
+		 0xaa, 0xab, 0xab, 0xac, 0xac, 0xac, 0xad, 0xad,
+		 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf,
+		 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
+		 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3,
+		 0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6,
+		 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8,
+		 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
+		 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
+		 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+		 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0,
+		 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
+		 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+		 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
+		 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9, 0xc9,
+		 0xca, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
+		 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd,
+		 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
+		 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
+		 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3,
+		 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
+		 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
+		 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+		 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda,
+		 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
+		 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+		 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
+		 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1,
+		 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
+		 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4,
+		 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
+		 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7,
+		 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
+		 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb,
+		 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+		 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
+		 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
+		 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+		 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+		 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+		 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
+		 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
+		 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+		 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+		{0x0d, 0x10, 0x11, 0x14, 0x15, 0x17, 0x18, 0x1b,
+		 0x1c, 0x1e, 0x20, 0x22, 0x23, 0x26, 0x27, 0x28,
+		 0x29, 0x2b, 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34,
+		 0x35, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d,
+		 0x3f, 0x40, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48,
+		 0x49, 0x4a, 0x4b, 0x4b, 0x4c, 0x4d, 0x4f, 0x50,
+		 0x52, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58,
+		 0x59, 0x5a, 0x5a, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f,
+		 0x60, 0x60, 0x61, 0x62, 0x62, 0x63, 0x65, 0x65,
+		 0x66, 0x67, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6c,
+		 0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
+		 0x71, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x77,
+		 0x78, 0x78, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b,
+		 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80,
+		 0x81, 0x81, 0x82, 0x82, 0x84, 0x84, 0x85, 0x85,
+		 0x86, 0x86, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a,
+		 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f,
+		 0x8f, 0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92,
+		 0x93, 0x93, 0x94, 0x94, 0x94, 0x96, 0x96, 0x97,
+		 0x97, 0x98, 0x98, 0x98, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d,
+		 0x9d, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
+		 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+		 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa8, 0xa8,
+		 0xa8, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac,
+		 0xac, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
+		 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
+		 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb4,
+		 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+		 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba,
+		 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
+		 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+		 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc3,
+		 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+		 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7,
+		 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
+		 0xca, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc,
+		 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
+		 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0,
+		 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+		 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
+		 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8,
+		 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
+		 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+		 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf,
+		 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1,
+		 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
+		 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
+		 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6,
+		 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8,
+		 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb,
+		 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
+		 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+		 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
+		 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+		 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
+		 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+		 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8,
+		 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
+		 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
+	    },
+	    {							/* gamma 5 */
+		{0x16, 0x18, 0x19, 0x1b, 0x1d, 0x1e, 0x20, 0x21,
+		 0x23, 0x24, 0x25, 0x27, 0x28, 0x2a, 0x2b, 0x2c,
+		 0x2d, 0x2f, 0x30, 0x31, 0x32, 0x34, 0x35, 0x36,
+		 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+		 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+		 0x48, 0x49, 0x4a, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e,
+		 0x4f, 0x50, 0x51, 0x51, 0x52, 0x53, 0x54, 0x55,
+		 0x56, 0x56, 0x57, 0x58, 0x59, 0x59, 0x5a, 0x5b,
+		 0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 0x5f, 0x60, 0x61,
+		 0x62, 0x62, 0x63, 0x64, 0x64, 0x65, 0x66, 0x66,
+		 0x67, 0x68, 0x68, 0x69, 0x6a, 0x6a, 0x6b, 0x6b,
+		 0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
+		 0x71, 0x71, 0x72, 0x73, 0x73, 0x74, 0x74, 0x75,
+		 0x75, 0x76, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79,
+		 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7d, 0x7d, 0x7e,
+		 0x7e, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x82,
+		 0x82, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85, 0x85,
+		 0x86, 0x86, 0x87, 0x87, 0x88, 0x88, 0x89, 0x89,
+		 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8d,
+		 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x90, 0x90,
+		 0x91, 0x91, 0x91, 0x92, 0x92, 0x93, 0x93, 0x94,
+		 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x96, 0x97,
+		 0x97, 0x98, 0x98, 0x98, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d,
+		 0x9d, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f, 0xa0, 0xa0,
+		 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3,
+		 0xa3, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6,
+		 0xa6, 0xa6, 0xa7, 0xa7, 0xa7, 0xa8, 0xa8, 0xa8,
+		 0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
+		 0xab, 0xac, 0xac, 0xac, 0xad, 0xad, 0xad, 0xae,
+		 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+		 0xb0, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3,
+		 0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5,
+		 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7,
+		 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
+		 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc,
+		 0xbc, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
+		 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
+		 0xc1, 0xc1, 0xc1, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
+		 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+		 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7,
+		 0xc7, 0xc8, 0xc8, 0xc8, 0xc8, 0xc9, 0xc9, 0xc9,
+		 0xc9, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
+		 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd,
+		 0xcd, 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf,
+		 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
+		 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3,
+		 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd5, 0xd5, 0xd5,
+		 0xd5, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
+		 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
+		 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+		 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdd,
+		 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde,
+		 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0,
+		 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+		 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
+		 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
+		 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7,
+		 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
+		 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea, 0xea, 0xeb,
+		 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+		 0xed, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
+		 0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+		 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
+		 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3,
+		 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
+		 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
+		 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd,
+		 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		{0x0f, 0x11, 0x12, 0x14, 0x15, 0x16, 0x18, 0x19,
+		 0x1a, 0x1b, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
+		 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
+		 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x31, 0x32,
+		 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x38, 0x39,
+		 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3e, 0x3f, 0x3f,
+		 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x44, 0x45,
+		 0x46, 0x47, 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b,
+		 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0x4e, 0x4f, 0x50,
+		 0x50, 0x51, 0x51, 0x52, 0x53, 0x53, 0x54, 0x54,
+		 0x55, 0x55, 0x56, 0x56, 0x57, 0x58, 0x58, 0x59,
+		 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5d,
+		 0x5d, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
+		 0x61, 0x62, 0x62, 0x63, 0x63, 0x64, 0x64, 0x65,
+		 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x68, 0x68,
+		 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c,
+		 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f,
+		 0x6f, 0x70, 0x70, 0x71, 0x71, 0x71, 0x72, 0x72,
+		 0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x75,
+		 0x76, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78, 0x78,
+		 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
+		 0x7b, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e,
+		 0x7e, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x81,
+		 0x81, 0x81, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83,
+		 0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x86,
+		 0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88,
+		 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b,
+		 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d,
+		 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f,
+		 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+		 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94,
+		 0x94, 0x94, 0x94, 0x95, 0x95, 0x95, 0x96, 0x96,
+		 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98,
+		 0x98, 0x98, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+		 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e,
+		 0x9e, 0x9e, 0x9f, 0x9f, 0x9f, 0x9f, 0xa0, 0xa0,
+		 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
+		 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
+		 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+		 0xa6, 0xa6, 0xa6, 0xa6, 0xa7, 0xa7, 0xa7, 0xa7,
+		 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9,
+		 0xa9, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
+		 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+		 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
+		 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+		 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+		 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+		 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5,
+		 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
+		 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
+		 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
+		 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+		 0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
+		 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+		 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0,
+		 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
+		 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
+		 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
+		 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
+		 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
+		 0xc7, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc9, 0xc9,
+		 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca,
+		 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
+		 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd,
+		 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce,
+		 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
+		 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
+		 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3,
+		 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
+		 0xd4, 0xd4, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5,
+		 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
+		 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+		 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda,
+		 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb,
+		 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
+		 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde,
+		 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf,
+		 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,
+		 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+		 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3,
+		 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
+		 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+		 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+		 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
+		 0xe9, 0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea,
+		 0xea, 0xea, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+		 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
+		 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
+		 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+		 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1,
+		 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+		 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
+		 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
+		 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
+		 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+		 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd,
+		 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+		 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		{0x13, 0x15, 0x16, 0x18, 0x19, 0x1b, 0x1c, 0x1e,
+		 0x1f, 0x20, 0x22, 0x23, 0x24, 0x26, 0x27, 0x28,
+		 0x29, 0x2a, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
+		 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+		 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41,
+		 0x42, 0x43, 0x44, 0x44, 0x45, 0x46, 0x47, 0x48,
+		 0x49, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e,
+		 0x4f, 0x50, 0x50, 0x51, 0x52, 0x53, 0x53, 0x54,
+		 0x55, 0x55, 0x56, 0x57, 0x57, 0x58, 0x59, 0x59,
+		 0x5a, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5f,
+		 0x5f, 0x60, 0x60, 0x61, 0x62, 0x62, 0x63, 0x63,
+		 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
+		 0x69, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c,
+		 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
+		 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x74, 0x74,
+		 0x75, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78,
+		 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c,
+		 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f,
+		 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x83,
+		 0x83, 0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
+		 0x86, 0x87, 0x87, 0x88, 0x88, 0x88, 0x89, 0x89,
+		 0x89, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c,
+		 0x8c, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f,
+		 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92,
+		 0x92, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x95,
+		 0x95, 0x95, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
+		 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+		 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d,
+		 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f,
+		 0x9f, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2,
+		 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+		 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6,
+		 0xa7, 0xa7, 0xa7, 0xa7, 0xa8, 0xa8, 0xa8, 0xa9,
+		 0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
+		 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xad, 0xad,
+		 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf,
+		 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1,
+		 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+		 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5,
+		 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7,
+		 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+		 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb,
+		 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
+		 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf,
+		 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1,
+		 0xc1, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
+		 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+		 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
+		 0xc7, 0xc7, 0xc7, 0xc7, 0xc8, 0xc8, 0xc8, 0xc8,
+		 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
+		 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
+		 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+		 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+		 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
+		 0xd1, 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3,
+		 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
+		 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd6, 0xd6, 0xd6,
+		 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
+		 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9,
+		 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb,
+		 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
+		 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+		 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
+		 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
+		 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
+		 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+		 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6,
+		 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+		 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9,
+		 0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea, 0xea,
+		 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec,
+		 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
+		 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
+		 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+		 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2,
+		 0xf2, 0xf2, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3,
+		 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5,
+		 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+		 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
+		 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+		 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb,
+		 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+		 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe,
+		 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	    },
+	};
+
+	reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
+	if (sd->bridge == BRIDGE_TP6810)
+		reg_w(gspca_dev, 0x02, 0x28);
+/*	msleep(50); */
+	gamma = sd->ctrls[GAMMA].val;
+	bulk_w(gspca_dev, 0x00, gamma_tb[gamma][0], 1024);
+	bulk_w(gspca_dev, 0x01, gamma_tb[gamma][1], 1024);
+	bulk_w(gspca_dev, 0x02, gamma_tb[gamma][2], 1024);
+	if (sd->bridge == BRIDGE_TP6810) {
+		int i;
+
+		reg_w(gspca_dev, 0x02, 0x2b);
+		reg_w(gspca_dev, 0x02, 0x28);
+		for (i = 0; i < 6; i++)
+			reg_w(gspca_dev, TP6800_R55_GAMMA_R,
+				gamma_tb[gamma][0][i]);
+		reg_w(gspca_dev, 0x02, 0x2b);
+		reg_w(gspca_dev, 0x02, 0x28);
+		for (i = 0; i < 6; i++)
+			reg_w(gspca_dev, TP6800_R56_GAMMA_G,
+				gamma_tb[gamma][1][i]);
+		reg_w(gspca_dev, 0x02, 0x2b);
+		reg_w(gspca_dev, 0x02, 0x28);
+		for (i = 0; i < 6; i++)
+			reg_w(gspca_dev, TP6800_R57_GAMMA_B,
+				gamma_tb[gamma][2][i]);
+		reg_w(gspca_dev, 0x02, 0x28);
+	}
+	reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
+/*	msleep(50); */
+}
+
+static void setsharpness(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 val;
+
+	if (sd->bridge == BRIDGE_TP6800) {
+		val = sd->ctrls[SHARPNESS].val
+				| 0x08;		/* grid compensation enable */
+		if (gspca_dev->width == 640)
+			reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */
+		else
+			val |= 0x04;		/* scaling down enable */
+		reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, val);
+	} else {
+		val = (sd->ctrls[SHARPNESS].val << 5) | 0x08;
+		reg_w(gspca_dev, 0x59, val);
+	}
+}
+
+static void setautogain(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
+		return;
+	if (sd->ctrls[AUTOGAIN].val) {
+		sd->ag_cnt = AG_CNT_START;
+		gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN);
+	} else {
+		sd->ag_cnt = -1;
+		gspca_dev->ctrl_inac &= ~((1 << EXPOSURE) | (1 << GAIN));
+	}
+}
+
+/* set the resolution for sensor cx0342 */
+static void set_resolution(struct gspca_dev *gspca_dev)
+{
+	reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
+	if (gspca_dev->width == 320) {
+		reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x06);
+		msleep(100);
+		i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
+		msleep(100);
+		reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
+		reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01);	/* qvga */
+		reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, 0x0d);
+		i2c_w(gspca_dev, CX0342_EXPO_LINE_L, 0x37);
+		i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x01);
+	} else {
+		reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x05);
+		msleep(100);
+		i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
+		msleep(100);
+		reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
+		reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00);	/* vga */
+		reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, 0x09);
+		i2c_w(gspca_dev, CX0342_EXPO_LINE_L, 0xcf);
+		i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00);
+	}
+	i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01);
+	bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342],
+				ARRAY_SIZE(color_gain[0]));
+	setgamma(gspca_dev);
+	setquality(gspca_dev);
+}
+
+/* convert the frame rate to a tp68x0 value */
+static int get_fr_idx(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int i;
+
+	if (sd->bridge == BRIDGE_TP6800) {
+		for (i = 0; i < ARRAY_SIZE(rates) - 1; i++) {
+			if (sd->framerate >= rates[i])
+				break;
+		}
+		i = 6 - i;		/* 1 = 5fps .. 6 = 30fps */
+
+		/* 640x480 * 30 fps does not work */
+		if (i == 6			/* if 30 fps */
+		 && gspca_dev->width == 640)
+			i = 0x86;		/* 15 fps */
+	} else {
+		for (i = 0; i < ARRAY_SIZE(rates_6810) - 1; i++) {
+			if (sd->framerate >= rates_6810[i])
+				break;
+		}
+		i = 7 - i;		/* 3 = 5fps .. 7 = 30fps */
+
+		/* 640x480 * 30 fps does not work */
+		if (i == 7			/* if 30 fps */
+		 && gspca_dev->width == 640)
+			i = 6;			/* 15 fps */
+		i |= 0x80;			/* clock * 1 */
+	}
+	return i;
+}
+
+static void setframerate(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 fr_idx;
+
+	fr_idx = get_fr_idx(gspca_dev);
+
+	if (sd->bridge == BRIDGE_TP6810) {
+		reg_r(gspca_dev, 0x7b);
+		reg_w(gspca_dev, 0x7b,
+			sd->sensor == SENSOR_CX0342 ? 0x10 : 0x90);
+		if (sd->ctrls[EXPOSURE].val >= 128)
+			fr_idx = 0xf0;		/* lower frame rate */
+	}
+
+	reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, fr_idx);
+
+	if (sd->sensor == SENSOR_CX0342)
+		i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
+}
+
+static void setrgain(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int rgain;
+
+	rgain = sd->ctrls[RGAIN].val;
+	i2c_w(gspca_dev, CX0342_RAW_RGAIN_H, rgain >> 8);
+	i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, rgain);
+	i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80);
+}
+
+static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (sd->sensor == SENSOR_CX0342) {
+		sd->ctrls[BGAIN].val = sd->ctrls[BGAIN].val
+					* val / sd->ctrls[GAIN].val;
+		if (sd->ctrls[BGAIN].val > 4095)
+			sd->ctrls[BGAIN].val = 4095;
+		sd->ctrls[RGAIN].val = sd->ctrls[RGAIN].val
+					* val / sd->ctrls[GAIN].val;
+		if (sd->ctrls[RGAIN].val > 4095)
+			sd->ctrls[RGAIN].val = 4095;
+	}
+	sd->ctrls[GAIN].val = val;
+	if (gspca_dev->streaming)
+		setexposure(gspca_dev);
+	return gspca_dev->usb_err;
+}
+
+static void setbgain(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int bgain;
+
+	bgain = sd->ctrls[BGAIN].val;
+	i2c_w(gspca_dev, CX0342_RAW_BGAIN_H, bgain >> 8);
+	i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, bgain);
+	i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80);
+}
+
+/* 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;
+
+	sd->bridge = id->driver_info;
+
+	gspca_dev->cam.cam_mode = vga_mode;
+	gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
+	gspca_dev->cam.mode_framerates = sd->bridge == BRIDGE_TP6800 ?
+			framerates : framerates_6810;
+
+	sd->framerate = 30;		/* default: 30 fps */
+	gspca_dev->cam.ctrls = sd->ctrls;
+	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;
+	static const struct cmd tp6800_preinit[] = {
+		{TP6800_R10_SIF_TYPE, 0x01},	/* sif */
+		{TP6800_R11_SIF_CONTROL, 0x01},
+		{TP6800_R15_GPIO_PU, 0x9f},
+		{TP6800_R16_GPIO_PD, 0x9f},
+		{TP6800_R17_GPIO_IO, 0x80},
+		{TP6800_R18_GPIO_DATA, 0x40},	/* LED off */
+	};
+	static const struct cmd tp6810_preinit[] = {
+		{TP6800_R2F_TIMING_CFG, 0x2f},
+		{TP6800_R15_GPIO_PU, 0x6f},
+		{TP6800_R16_GPIO_PD, 0x40},
+		{TP6800_R17_GPIO_IO, 0x9f},
+		{TP6800_R18_GPIO_DATA, 0xc1},	/* LED off */
+	};
+
+	if (sd->bridge == BRIDGE_TP6800)
+		reg_w_buf(gspca_dev, tp6800_preinit,
+				ARRAY_SIZE(tp6800_preinit));
+	else
+		reg_w_buf(gspca_dev, tp6810_preinit,
+				ARRAY_SIZE(tp6810_preinit));
+	msleep(15);
+	reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
+	PDEBUG(D_PROBE, "gpio: %02x", gspca_dev->usb_buf[0]);
+/* values:
+ *	0x80: snapshot button
+ *	0x40: LED
+ *	0x20: (bridge / sensor) reset for tp6810 ?
+ *	0x07: sensor type ?
+ */
+
+	/* guess the sensor type */
+	if (force_sensor >= 0) {
+		sd->sensor = force_sensor;
+	} else {
+		if (sd->bridge == BRIDGE_TP6800) {
+/*fixme: not sure this is working*/
+			switch (gspca_dev->usb_buf[0] & 0x07) {
+			case 0:
+				sd->sensor = SENSOR_SOI763A;
+				break;
+			case 1:
+				sd->sensor = SENSOR_CX0342;
+				break;
+			}
+		} else {
+			int sensor;
+
+			sensor = probe_6810(gspca_dev);
+			if (sensor < 0) {
+				pr_warn("Unknown sensor %d - forced to soi763a\n",
+					-sensor);
+				sensor = SENSOR_SOI763A;
+			}
+			sd->sensor = sensor;
+		}
+	}
+	if (sd->sensor == SENSOR_SOI763A) {
+		pr_info("Sensor soi763a\n");
+		sd->ctrls[GAMMA].def = sd->bridge == BRIDGE_TP6800 ? 0 : 1;
+		sd->ctrls[GAIN].max = 15;
+		sd->ctrls[GAIN].def = 3;
+		gspca_dev->ctrl_dis = (1 << RGAIN) | (1 << BGAIN);
+		if (sd->bridge == BRIDGE_TP6810) {
+			soi763a_6810_init(gspca_dev);
+#if AUTOGAIN_DEF
+			gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN);
+#endif
+		} else {
+			gspca_dev->ctrl_dis |= (1 << AUTOGAIN);
+		}
+	} else {
+		pr_info("Sensor cx0342\n");
+		if (sd->bridge == BRIDGE_TP6810) {
+			cx0342_6810_init(gspca_dev);
+#if AUTOGAIN_DEF
+			gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN);
+#endif
+		} else {
+			gspca_dev->ctrl_dis |= (1 << AUTOGAIN);
+		}
+	}
+
+	if (sd->bridge == BRIDGE_TP6810)
+		sd->ctrls[QUALITY].def = 0;	/* auto quality */
+	set_dqt(gspca_dev, 0);
+	return 0;
+}
+
+/* This function is called before choosing the alt setting */
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	static const struct cmd cx_sensor_init[] = {
+		{CX0342_AUTO_ADC_CALIB, 0x81},
+		{CX0342_EXPO_LINE_L, 0x37},
+		{CX0342_EXPO_LINE_H, 0x01},
+		{CX0342_RAW_GRGAIN_L, 0x00},
+		{CX0342_RAW_GBGAIN_L, 0x00},
+		{CX0342_RAW_RGAIN_L, 0x00},
+		{CX0342_RAW_BGAIN_L, 0x00},
+		{CX0342_SYS_CTRL_0, 0x81},
+	};
+	static const struct cmd cx_bridge_init[] = {
+		{0x4d, 0x00},
+		{0x4c, 0xff},
+		{0x4e, 0xff},
+		{0x4f, 0x00},
+	};
+	static const struct cmd ov_sensor_init[] = {
+		{0x10, 0x75},		/* exposure */
+		{0x76, 0x03},
+		{0x00, 0x00},		/* gain */
+	};
+	static const struct cmd ov_bridge_init[] = {
+		{0x7b, 0x90},
+		{TP6800_R3F_FRAME_RATE, 0x87},
+	};
+
+	if (sd->bridge == BRIDGE_TP6800)
+		return 0;
+	if (sd->sensor == SENSOR_CX0342) {
+		reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20);
+		reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87);
+		i2c_w_buf(gspca_dev, cx_sensor_init,
+				ARRAY_SIZE(cx_sensor_init));
+		reg_w_buf(gspca_dev, cx_bridge_init,
+				ARRAY_SIZE(cx_bridge_init));
+		bulk_w(gspca_dev, 0x03, color_null, sizeof color_null);
+		reg_w(gspca_dev, 0x59, 0x40);
+	} else {
+		reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x21);
+		i2c_w_buf(gspca_dev, ov_sensor_init,
+				ARRAY_SIZE(ov_sensor_init));
+		reg_r(gspca_dev, 0x7b);
+		reg_w_buf(gspca_dev, ov_bridge_init,
+				ARRAY_SIZE(ov_bridge_init));
+	}
+	reg_w(gspca_dev, TP6800_R78_FORMAT,
+			gspca_dev->curr_mode ? 0x00 : 0x01);
+	return gspca_dev->usb_err;
+}
+
+static void set_led(struct gspca_dev *gspca_dev, int on)
+{
+	u8 data;
+
+	reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
+	data = gspca_dev->usb_buf[0];
+	if (on)
+		data &= ~0x40;
+	else
+		data |= 0x40;
+	reg_w(gspca_dev, TP6800_R18_GPIO_DATA, data);
+}
+
+static void cx0342_6800_start(struct gspca_dev *gspca_dev)
+{
+	static const struct cmd reg_init[] = {
+/*fixme: is this usefull?*/
+		{TP6800_R17_GPIO_IO, 0x9f},
+		{TP6800_R16_GPIO_PD, 0x40},
+		{TP6800_R10_SIF_TYPE, 0x00},	/* i2c 8 bits */
+		{TP6800_R50, 0x00},
+		{TP6800_R51, 0x00},
+		{TP6800_R52, 0xff},
+		{TP6800_R53, 0x03},
+		{TP6800_R54_DARK_CFG, 0x07},
+		{TP6800_R5C_EDGE_THRLD, 0x40},
+		{TP6800_R7A_BLK_THRLD, 0x40},
+		{TP6800_R2F_TIMING_CFG, 0x17},
+		{TP6800_R30_SENSOR_CFG, 0x18},	/* G1B..RG0 */
+		{TP6800_R37_FRONT_DARK_ST, 0x00},
+		{TP6800_R38_FRONT_DARK_END, 0x00},
+		{TP6800_R39_REAR_DARK_ST_L, 0x00},
+		{TP6800_R3A_REAR_DARK_ST_H, 0x00},
+		{TP6800_R3B_REAR_DARK_END_L, 0x00},
+		{TP6800_R3C_REAR_DARK_END_H, 0x00},
+		{TP6800_R3D_HORIZ_DARK_LINE_L, 0x00},
+		{TP6800_R3E_HORIZ_DARK_LINE_H, 0x00},
+		{TP6800_R21_ENDP_1_CTL, 0x03},
+
+		{TP6800_R31_PIXEL_START, 0x0b},
+		{TP6800_R32_PIXEL_END_L, 0x8a},
+		{TP6800_R33_PIXEL_END_H, 0x02},
+		{TP6800_R34_LINE_START, 0x0e},
+		{TP6800_R35_LINE_END_L, 0xf4},
+		{TP6800_R36_LINE_END_H, 0x01},
+		{TP6800_R78_FORMAT, 0x00},
+		{TP6800_R12_SIF_ADDR_S, 0x20},	/* cx0342 i2c addr */
+	};
+	static const struct cmd sensor_init[] = {
+		{CX0342_OUTPUT_CTRL, 0x07},
+		{CX0342_BYPASS_MODE, 0x58},
+		{CX0342_GPXLTHD_L, 0x16},
+		{CX0342_RBPXLTHD_L, 0x16},
+		{CX0342_PLANETHD_L, 0xc0},
+		{CX0342_PLANETHD_H, 0x03},
+		{CX0342_RB_GAP_L, 0xff},
+		{CX0342_RB_GAP_H, 0x07},
+		{CX0342_G_GAP_L, 0xff},
+		{CX0342_G_GAP_H, 0x07},
+		{CX0342_RST_OVERFLOW_L, 0x5c},
+		{CX0342_RST_OVERFLOW_H, 0x01},
+		{CX0342_DATA_OVERFLOW_L, 0xfc},
+		{CX0342_DATA_OVERFLOW_H, 0x03},
+		{CX0342_DATA_UNDERFLOW_L, 0x00},
+		{CX0342_DATA_UNDERFLOW_H, 0x00},
+		{CX0342_SYS_CTRL_0, 0x40},
+		{CX0342_GLOBAL_GAIN, 0x01},
+		{CX0342_CLOCK_GEN, 0x00},
+		{CX0342_SYS_CTRL_0, 0x02},
+		{CX0342_IDLE_CTRL, 0x05},
+		{CX0342_ADCGN, 0x00},
+		{CX0342_ADC_CTL, 0x00},
+		{CX0342_LVRST_BLBIAS, 0x01},
+		{CX0342_VTHSEL, 0x0b},
+		{CX0342_RAMP_RIV, 0x0b},
+		{CX0342_LDOSEL, 0x07},
+		{CX0342_SPV_VALUE_L, 0x40},
+		{CX0342_SPV_VALUE_H, 0x02},
+	};
+
+	reg_w_buf(gspca_dev, reg_init, ARRAY_SIZE(reg_init));
+	i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
+	i2c_w_buf(gspca_dev, cx0342_timing_seq, ARRAY_SIZE(cx0342_timing_seq));
+	reg_w(gspca_dev, TP6800_R5C_EDGE_THRLD, 0x10);
+	reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00);
+	i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00);
+	i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01);
+	setexposure(gspca_dev);
+	set_led(gspca_dev, 1);
+	set_resolution(gspca_dev);
+}
+
+static void cx0342_6810_start(struct gspca_dev *gspca_dev)
+{
+	static const struct cmd sensor_init_2[] = {
+		{CX0342_EXPO_LINE_L, 0x6f},
+		{CX0342_EXPO_LINE_H, 0x02},
+		{CX0342_RAW_GRGAIN_L, 0x00},
+		{CX0342_RAW_GBGAIN_L, 0x00},
+		{CX0342_RAW_RGAIN_L, 0x00},
+		{CX0342_RAW_BGAIN_L, 0x00},
+		{CX0342_SYS_CTRL_0, 0x81},
+	};
+	static const struct cmd bridge_init_2[] = {
+		{0x4d, 0x00},
+		{0x4c, 0xff},
+		{0x4e, 0xff},
+		{0x4f, 0x00},
+		{TP6800_R7A_BLK_THRLD, 0x00},
+		{TP6800_R79_QUALITY, 0x04},
+		{TP6800_R79_QUALITY, 0x01},
+	};
+	static const struct cmd bridge_init_3[] = {
+		{TP6800_R31_PIXEL_START, 0x08},
+		{TP6800_R32_PIXEL_END_L, 0x87},
+		{TP6800_R33_PIXEL_END_H, 0x02},
+		{TP6800_R34_LINE_START, 0x0e},
+		{TP6800_R35_LINE_END_L, 0xf4},
+		{TP6800_R36_LINE_END_H, 0x01},
+	};
+	static const struct cmd sensor_init_3[] = {
+		{CX0342_AUTO_ADC_CALIB, 0x81},
+		{CX0342_EXPO_LINE_L, 0x6f},
+		{CX0342_EXPO_LINE_H, 0x02},
+		{CX0342_RAW_GRGAIN_L, 0x00},
+		{CX0342_RAW_GBGAIN_L, 0x00},
+		{CX0342_RAW_RGAIN_L, 0x00},
+		{CX0342_RAW_BGAIN_L, 0x00},
+		{CX0342_SYS_CTRL_0, 0x81},
+	};
+	static const struct cmd bridge_init_5[] = {
+		{0x4d, 0x00},
+		{0x4c, 0xff},
+		{0x4e, 0xff},
+		{0x4f, 0x00},
+	};
+	static const struct cmd sensor_init_4[] = {
+		{CX0342_EXPO_LINE_L, 0xd3},
+		{CX0342_EXPO_LINE_H, 0x01},
+/*fixme: gains, but 00..80 only*/
+		{CX0342_RAW_GRGAIN_L, 0x40},
+		{CX0342_RAW_GBGAIN_L, 0x40},
+		{CX0342_RAW_RGAIN_L, 0x40},
+		{CX0342_RAW_BGAIN_L, 0x40},
+		{CX0342_SYS_CTRL_0, 0x81},
+	};
+	static const struct cmd sensor_init_5[] = {
+		{CX0342_IDLE_CTRL, 0x05},
+		{CX0342_ADCGN, 0x00},
+		{CX0342_ADC_CTL, 0x00},
+		{CX0342_LVRST_BLBIAS, 0x01},
+		{CX0342_VTHSEL, 0x0b},
+		{CX0342_RAMP_RIV, 0x0b},
+		{CX0342_LDOSEL, 0x07},
+		{CX0342_SPV_VALUE_L, 0x40},
+		{CX0342_SPV_VALUE_H, 0x02},
+		{CX0342_AUTO_ADC_CALIB, 0x81},
+	};
+
+	reg_w(gspca_dev, 0x22, gspca_dev->alt);
+	i2c_w_buf(gspca_dev, sensor_init_2, ARRAY_SIZE(sensor_init_2));
+	reg_w_buf(gspca_dev, bridge_init_2, ARRAY_SIZE(bridge_init_2));
+	reg_w_buf(gspca_dev, tp6810_cx_init_common,
+			ARRAY_SIZE(tp6810_cx_init_common));
+	reg_w_buf(gspca_dev, bridge_init_3, ARRAY_SIZE(bridge_init_3));
+	if (gspca_dev->curr_mode) {
+		reg_w(gspca_dev, 0x4a, 0x7f);
+		reg_w(gspca_dev, 0x07, 0x05);
+		reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00);	/* vga */
+	} else {
+		reg_w(gspca_dev, 0x4a, 0xff);
+		reg_w(gspca_dev, 0x07, 0x85);
+		reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01);	/* qvga */
+	}
+	setgamma(gspca_dev);
+	reg_w_buf(gspca_dev, tp6810_bridge_start,
+			ARRAY_SIZE(tp6810_bridge_start));
+	setsharpness(gspca_dev);
+	bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342],
+				ARRAY_SIZE(color_gain[0]));
+	reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87);
+	i2c_w_buf(gspca_dev, sensor_init_3, ARRAY_SIZE(sensor_init_3));
+	reg_w_buf(gspca_dev, bridge_init_5, ARRAY_SIZE(bridge_init_5));
+	i2c_w_buf(gspca_dev, sensor_init_4, ARRAY_SIZE(sensor_init_4));
+	reg_w_buf(gspca_dev, bridge_init_5, ARRAY_SIZE(bridge_init_5));
+	i2c_w_buf(gspca_dev, sensor_init_5, ARRAY_SIZE(sensor_init_5));
+
+	set_led(gspca_dev, 1);
+/*	setquality(gspca_dev); */
+}
+
+static void soi763a_6800_start(struct gspca_dev *gspca_dev)
+{
+	static const struct cmd reg_init[] = {
+		{TP6800_R79_QUALITY, 0x04},
+		{TP6800_R79_QUALITY, 0x01},
+		{TP6800_R10_SIF_TYPE, 0x00},	/* i2c 8 bits */
+
+		{TP6800_R50, 0x00},
+		{TP6800_R51, 0x00},
+		{TP6800_R52, 0xff},
+		{TP6800_R53, 0x03},
+		{TP6800_R54_DARK_CFG, 0x07},
+		{TP6800_R5C_EDGE_THRLD, 0x40},
+
+		{TP6800_R79_QUALITY, 0x03},
+		{TP6800_R7A_BLK_THRLD, 0x40},
+
+		{TP6800_R2F_TIMING_CFG, 0x46},
+		{TP6800_R30_SENSOR_CFG, 0x10},	/* BG1..G0R */
+		{TP6800_R37_FRONT_DARK_ST, 0x00},
+		{TP6800_R38_FRONT_DARK_END, 0x00},
+		{TP6800_R39_REAR_DARK_ST_L, 0x00},
+		{TP6800_R3A_REAR_DARK_ST_H, 0x00},
+		{TP6800_R3B_REAR_DARK_END_L, 0x00},
+		{TP6800_R3C_REAR_DARK_END_H, 0x00},
+		{TP6800_R3D_HORIZ_DARK_LINE_L, 0x00},
+		{TP6800_R3E_HORIZ_DARK_LINE_H, 0x00},
+		{TP6800_R21_ENDP_1_CTL, 0x03},
+
+		{TP6800_R3F_FRAME_RATE, 0x04},	/* 15 fps */
+		{TP6800_R5D_DEMOSAIC_CFG, 0x0e}, /* scale down - medium edge */
+
+		{TP6800_R31_PIXEL_START, 0x1b},
+		{TP6800_R32_PIXEL_END_L, 0x9a},
+		{TP6800_R33_PIXEL_END_H, 0x02},
+		{TP6800_R34_LINE_START, 0x0f},
+		{TP6800_R35_LINE_END_L, 0xf4},
+		{TP6800_R36_LINE_END_H, 0x01},
+		{TP6800_R78_FORMAT, 0x01},	/* qvga */
+		{TP6800_R12_SIF_ADDR_S, 0x21},	/* soi763a i2c addr */
+		{TP6800_R1A_SIF_TX_DATA2, 0x00},
+	};
+	static const struct cmd sensor_init[] = {
+		{0x12, 0x48},		/* mirror - RGB */
+		{0x13, 0xa0},		/* clock - no AGC nor AEC */
+		{0x03, 0xa4},		/* saturation */
+		{0x04, 0x30},		/* hue */
+		{0x05, 0x88},		/* contrast */
+		{0x06, 0x60},		/* brightness */
+		{0x10, 0x41},		/* AEC */
+		{0x11, 0x40},		/* clock rate */
+		{0x13, 0xa0},
+		{0x14, 0x00},		/* 640x480 */
+		{0x15, 0x14},
+		{0x1f, 0x41},
+		{0x20, 0x80},
+		{0x23, 0xee},
+		{0x24, 0x50},
+		{0x25, 0x7a},
+		{0x26, 0x00},
+		{0x27, 0xe2},
+		{0x28, 0xb0},
+		{0x2a, 0x00},
+		{0x2b, 0x00},
+		{0x2d, 0x81},
+		{0x2f, 0x9d},
+		{0x60, 0x80},
+		{0x61, 0x00},
+		{0x62, 0x88},
+		{0x63, 0x11},
+		{0x64, 0x89},
+		{0x65, 0x00},
+		{0x67, 0x94},
+		{0x68, 0x7a},
+		{0x69, 0x0f},
+		{0x6c, 0x80},
+		{0x6d, 0x80},
+		{0x6e, 0x80},
+		{0x6f, 0xff},
+		{0x71, 0x20},
+		{0x74, 0x20},
+		{0x75, 0x86},
+		{0x77, 0xb5},
+		{0x17, 0x18},		/* H href start */
+		{0x18, 0xbf},		/* H href end */
+		{0x19, 0x03},		/* V start */
+		{0x1a, 0xf8},		/* V end */
+		{0x01, 0x80},		/* blue gain */
+		{0x02, 0x80},		/* red gain */
+	};
+
+	reg_w_buf(gspca_dev, reg_init, ARRAY_SIZE(reg_init));
+
+	i2c_w(gspca_dev, 0x12, 0x80);		/* sensor reset */
+	msleep(10);
+
+	i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
+
+	reg_w(gspca_dev, TP6800_R5C_EDGE_THRLD, 0x10);
+	reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00);
+
+	setsharpness(gspca_dev);
+
+	bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A],
+				ARRAY_SIZE(color_gain[0]));
+
+	set_led(gspca_dev, 1);
+	setexposure(gspca_dev);
+	setquality(gspca_dev);
+	setgamma(gspca_dev);
+}
+
+static void soi763a_6810_start(struct gspca_dev *gspca_dev)
+{
+	static const struct cmd bridge_init_2[] = {
+		{TP6800_R7A_BLK_THRLD, 0x00},
+		{TP6800_R79_QUALITY, 0x04},
+		{TP6800_R79_QUALITY, 0x01},
+	};
+	static const struct cmd bridge_init_3[] = {
+		{TP6800_R31_PIXEL_START, 0x20},
+		{TP6800_R32_PIXEL_END_L, 0x9f},
+		{TP6800_R33_PIXEL_END_H, 0x02},
+		{TP6800_R34_LINE_START, 0x13},
+		{TP6800_R35_LINE_END_L, 0xf8},
+		{TP6800_R36_LINE_END_H, 0x01},
+	};
+	static const struct cmd bridge_init_6[] = {
+		{0x08, 0xff},
+		{0x09, 0xff},
+		{0x0a, 0x5f},
+		{0x0b, 0x80},
+	};
+
+	reg_w(gspca_dev, 0x22, gspca_dev->alt);
+	bulk_w(gspca_dev, 0x03, color_null, sizeof color_null);
+	reg_w(gspca_dev, 0x59, 0x40);
+	setexposure(gspca_dev);
+	reg_w_buf(gspca_dev, bridge_init_2, ARRAY_SIZE(bridge_init_2));
+	reg_w_buf(gspca_dev, tp6810_ov_init_common,
+			ARRAY_SIZE(tp6810_ov_init_common));
+	reg_w_buf(gspca_dev, bridge_init_3, ARRAY_SIZE(bridge_init_3));
+	if (gspca_dev->curr_mode) {
+		reg_w(gspca_dev, 0x4a, 0x7f);
+		reg_w(gspca_dev, 0x07, 0x05);
+		reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00);	/* vga */
+	} else {
+		reg_w(gspca_dev, 0x4a, 0xff);
+		reg_w(gspca_dev, 0x07, 0x85);
+		reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01);	/* qvga */
+	}
+	setgamma(gspca_dev);
+	reg_w_buf(gspca_dev, tp6810_bridge_start,
+			ARRAY_SIZE(tp6810_bridge_start));
+
+	if (gspca_dev->curr_mode) {
+		reg_w(gspca_dev, 0x4f, 0x00);
+		reg_w(gspca_dev, 0x4e, 0x7c);
+	}
+
+	reg_w(gspca_dev, 0x00, 0x00);
+
+	setsharpness(gspca_dev);
+	bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A],
+				ARRAY_SIZE(color_gain[0]));
+	set_led(gspca_dev, 1);
+	reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0xf0);
+	setexposure(gspca_dev);
+	reg_w_buf(gspca_dev, bridge_init_6, ARRAY_SIZE(bridge_init_6));
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width);
+	set_dqt(gspca_dev, sd->quality);
+	if (sd->bridge == BRIDGE_TP6800) {
+		if (sd->sensor == SENSOR_CX0342)
+			cx0342_6800_start(gspca_dev);
+		else
+			soi763a_6800_start(gspca_dev);
+	} else {
+		if (sd->sensor == SENSOR_CX0342)
+			cx0342_6810_start(gspca_dev);
+		else
+			soi763a_6810_start(gspca_dev);
+		reg_w_buf(gspca_dev, tp6810_late_start,
+				ARRAY_SIZE(tp6810_late_start));
+		reg_w(gspca_dev, 0x80, 0x03);
+		reg_w(gspca_dev, 0x82, gspca_dev->curr_mode ? 0x0a : 0x0e);
+
+		setexposure(gspca_dev);
+		setquality(gspca_dev);
+		setautogain(gspca_dev);
+	}
+
+	setframerate(gspca_dev);
+
+	return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (sd->bridge == BRIDGE_TP6800)
+		reg_w(gspca_dev, TP6800_R2F_TIMING_CFG, 0x03);
+	set_led(gspca_dev, 0);
+	reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+			u8 *data,
+			int len)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	/* the start of frame contains:
+	 *	ff d8
+	 *	ff fe
+	 *	width / 16
+	 *	height / 8
+	 *	quality
+	 */
+	if (sd->bridge == BRIDGE_TP6810) {
+		if (*data != 0x5a) {
+/*fixme: don't discard the whole frame..*/
+			if (*data == 0xaa || *data == 0x00)
+				return;
+			if (*data > 0xc0) {
+				PDEBUG(D_FRAM, "bad frame");
+				gspca_dev->last_packet_type = DISCARD_PACKET;
+				return;
+			}
+		}
+		data++;
+		len--;
+		if (*data == 0xff && data[1] == 0xd8) {
+/*fixme: there may be information in the 4 high bits*/
+			if ((data[6] & 0x0f) != sd->quality)
+				set_dqt(gspca_dev, data[6] & 0x0f);
+			gspca_frame_add(gspca_dev, FIRST_PACKET,
+					sd->jpeg_hdr, JPEG_HDR_SZ);
+			gspca_frame_add(gspca_dev, INTER_PACKET,
+					data + 7, len - 7);
+		} else if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
+			gspca_frame_add(gspca_dev, LAST_PACKET,
+					data, len);
+		} else {
+			gspca_frame_add(gspca_dev, INTER_PACKET,
+					data, len);
+		}
+		return;
+	}
+
+	switch (*data) {
+	case 0x55:
+		gspca_frame_add(gspca_dev, LAST_PACKET, data, 0);
+
+		if (len < 8
+		 || data[1] != 0xff || data[2] != 0xd8
+		 || data[3] != 0xff || data[4] != 0xfe) {
+
+			/* Have only seen this with corrupt frames */
+			gspca_dev->last_packet_type = DISCARD_PACKET;
+			return;
+		}
+		if (data[7] != sd->quality)
+			set_dqt(gspca_dev, data[7]);
+		gspca_frame_add(gspca_dev, FIRST_PACKET,
+				sd->jpeg_hdr, JPEG_HDR_SZ);
+		gspca_frame_add(gspca_dev, INTER_PACKET,
+				data + 8, len - 8);
+		break;
+	case 0xaa:
+		gspca_dev->last_packet_type = DISCARD_PACKET;
+		break;
+	case 0xcc:
+		if (data[1] != 0xff || data[2] != 0xd8)
+			gspca_frame_add(gspca_dev, INTER_PACKET,
+					data + 1, len - 1);
+		else
+			gspca_dev->last_packet_type = DISCARD_PACKET;
+		break;
+	}
+}
+
+/* -- do autogain -- */
+/* gain setting is done in setexposure() for tp6810 */
+static void setgain(struct gspca_dev *gspca_dev) {}
+/* !! coarse_grained_expo_autogain is not used !! */
+#define exp_too_low_cnt bridge
+#define exp_too_high_cnt sensor
+
+#include "autogain_functions.h"
+static void sd_dq_callback(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int ret, alen;
+	int luma, expo;
+
+	if (sd->ag_cnt < 0)
+		return;
+	if (--sd->ag_cnt > 5)
+		return;
+	switch (sd->ag_cnt) {
+/*	case 5: */
+	default:
+		reg_w(gspca_dev, 0x7d, 0x00);
+		break;
+	case 4:
+		reg_w(gspca_dev, 0x27, 0xb0);
+		break;
+	case 3:
+		reg_w(gspca_dev, 0x0c, 0x01);
+		break;
+	case 2:
+		ret = usb_bulk_msg(gspca_dev->dev,
+				usb_rcvbulkpipe(gspca_dev->dev, 0x02),
+				gspca_dev->usb_buf,
+				32,
+				&alen,
+				500);
+		if (ret < 0) {
+			pr_err("bulk err %d\n", ret);
+			break;
+		}
+		/* values not used (unknown) */
+		break;
+	case 1:
+		reg_w(gspca_dev, 0x27, 0xd0);
+		break;
+	case 0:
+		ret = usb_bulk_msg(gspca_dev->dev,
+				usb_rcvbulkpipe(gspca_dev->dev, 0x02),
+				gspca_dev->usb_buf,
+				32,
+				&alen,
+				500);
+		if (ret < 0) {
+			pr_err("bulk err %d\n", ret);
+			break;
+		}
+		luma = ((gspca_dev->usb_buf[8] << 8) + gspca_dev->usb_buf[7] +
+			(gspca_dev->usb_buf[11] << 8) + gspca_dev->usb_buf[10] +
+			(gspca_dev->usb_buf[14] << 8) + gspca_dev->usb_buf[13] +
+			(gspca_dev->usb_buf[17] << 8) + gspca_dev->usb_buf[16] +
+			(gspca_dev->usb_buf[20] << 8) + gspca_dev->usb_buf[19] +
+			(gspca_dev->usb_buf[23] << 8) + gspca_dev->usb_buf[22] +
+			(gspca_dev->usb_buf[26] << 8) + gspca_dev->usb_buf[25] +
+			(gspca_dev->usb_buf[29] << 8) + gspca_dev->usb_buf[28])
+				/ 8;
+		if (gspca_dev->width == 640)
+			luma /= 4;
+		reg_w(gspca_dev, 0x7d, 0x00);
+
+		expo = sd->ctrls[EXPOSURE].val;
+		ret = auto_gain_n_exposure(gspca_dev, luma,
+				60,	/* desired luma */
+				6,	/* dead zone */
+				2,	/* gain knee */
+				70);	/* expo knee */
+		sd->ag_cnt = AG_CNT_START;
+		if (sd->bridge == BRIDGE_TP6810) {
+			if ((expo >= 128 && sd->ctrls[EXPOSURE].val < 128)
+			 || (expo < 128 && sd->ctrls[EXPOSURE].val >= 128))
+				setframerate(gspca_dev);
+		}
+		break;
+	}
+}
+
+/* get stream parameters (framerate) */
+static void sd_get_streamparm(struct gspca_dev *gspca_dev,
+			     struct v4l2_streamparm *parm)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	struct v4l2_captureparm *cp = &parm->parm.capture;
+	struct v4l2_fract *tpf = &cp->timeperframe;
+	int fr, i;
+
+	cp->capability |= V4L2_CAP_TIMEPERFRAME;
+	tpf->numerator = 1;
+	i = get_fr_idx(gspca_dev);
+	if (i & 0x80) {
+		if (sd->bridge == BRIDGE_TP6800)
+			fr = rates[6 - (i & 0x07)];
+		else
+			fr = rates_6810[7 - (i & 0x07)];
+	} else {
+		fr = rates[6 - i];
+	}
+	tpf->denominator = fr;
+}
+
+/* set stream parameters (framerate) */
+static void sd_set_streamparm(struct gspca_dev *gspca_dev,
+			     struct v4l2_streamparm *parm)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	struct v4l2_captureparm *cp = &parm->parm.capture;
+	struct v4l2_fract *tpf = &cp->timeperframe;
+	int fr, i;
+
+	sd->framerate = tpf->denominator / tpf->numerator;
+	if (gspca_dev->streaming)
+		setframerate(gspca_dev);
+
+	/* Return the actual framerate */
+	i = get_fr_idx(gspca_dev);
+	if (i & 0x80)
+		fr = rates_6810[7 - (i & 0x07)];
+	else
+		fr = rates[6 - i];
+	tpf->numerator = 1;
+	tpf->denominator = fr;
+}
+
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (sd->sensor == SENSOR_SOI763A)
+		jpeg_set_qual(sd->jpeg_hdr, jcomp->quality);
+/*	else
+		fixme: TODO
+*/
+	return gspca_dev->usb_err;
+}
+
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	memset(jcomp, 0, sizeof *jcomp);
+	jcomp->quality = jpeg_q[sd->quality];
+	jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
+			| V4L2_JPEG_MARKER_DQT;
+	return 0;
+}
+
+static struct ctrl sd_ctrls[NCTRLS] = {
+[EXPOSURE] = {
+	    {
+		.id = V4L2_CID_EXPOSURE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Exposure",
+		.minimum = 0x01,
+		.maximum = 0xdc,
+		.step = 1,
+		.default_value = 0x4e,
+	    },
+	    .set_control = setexposure
+	},
+[QUALITY] = {
+	    {
+		.id = V4L2_CID_PRIVATE_BASE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Compression quality",
+		.minimum = 0,
+		.maximum = 15,
+		.step = 1,
+		.default_value = 13,
+	    },
+	    .set_control = setquality
+	},
+[RGAIN] = {
+	    {
+		.id = V4L2_CID_RED_BALANCE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Red balance",
+		.minimum = 0,
+		.maximum = 4095,
+		.step = 1,
+		.default_value = 256,
+	    },
+	    .set_control = setrgain
+	},
+[GAIN] = {
+	    {
+		.id = V4L2_CID_GAIN,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Gain",
+		.minimum = 0,
+		.maximum = 4095,
+		.step = 1,
+		.default_value = 256,
+	    },
+	    .set = sd_setgain
+	},
+[BGAIN] = {
+	    {
+		.id = V4L2_CID_BLUE_BALANCE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Blue balance",
+		.minimum = 0,
+		.maximum = 4095,
+		.step = 1,
+		.default_value = 256,
+	    },
+	    .set_control = setbgain
+	},
+[SHARPNESS] = {
+	    {
+		.id	 = V4L2_CID_SHARPNESS,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Sharpness",
+		.minimum = 0,
+		.maximum = 3,
+		.step    = 1,
+		.default_value = 2,
+	    },
+	    .set_control = setsharpness
+	},
+[GAMMA] = {
+	    {
+		.id      = V4L2_CID_GAMMA,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Gamma",
+		.minimum = 0,
+		.maximum = NGAMMA - 1,
+		.step    = 1,
+		.default_value = 1,
+	    },
+	    .set_control = setgamma
+	},
+[AUTOGAIN] = {
+	    {
+		.id      = V4L2_CID_AUTOGAIN,
+		.type    = V4L2_CTRL_TYPE_BOOLEAN,
+		.name    = "Auto Gain",
+		.minimum = 0,
+		.maximum = 1,
+		.step    = 1,
+		.default_value = AUTOGAIN_DEF
+	    },
+	    .set_control = setautogain
+	},
+};
+
+static const struct sd_desc sd_desc = {
+	.name = KBUILD_MODNAME,
+	.ctrls = sd_ctrls,
+	.nctrls = NCTRLS,
+	.config = sd_config,
+	.init = sd_init,
+	.isoc_init = sd_isoc_init,
+	.start = sd_start,
+	.stopN = sd_stopN,
+	.pkt_scan = sd_pkt_scan,
+	.dq_callback = sd_dq_callback,
+	.get_streamparm = sd_get_streamparm,
+	.set_streamparm = sd_set_streamparm,
+	.get_jcomp = sd_get_jcomp,
+	.set_jcomp = sd_set_jcomp,
+};
+
+static const struct usb_device_id device_table[] = {
+	{USB_DEVICE(0x06a2, 0x0003), .driver_info = BRIDGE_TP6800},
+	{USB_DEVICE(0x06a2, 0x6810), .driver_info = BRIDGE_TP6810},
+	{}			/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+static int sd_probe(struct usb_interface *interface,
+		    const struct usb_device_id *id)
+{
+	return gspca_dev_probe(interface, id, &sd_desc, sizeof(struct sd),
+			       THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+	.name = KBUILD_MODNAME,
+	.id_table = device_table,
+	.probe = sd_probe,
+	.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+	.suspend = gspca_suspend,
+	.resume = gspca_resume,
+	.reset_resume = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+	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(force_sensor, int, 0644);
+MODULE_PARM_DESC(force_sensor,
+	"Force sensor. 0: cx0342, 1: soi763a");
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/vc032x.c linux-libre-3.2-gnu/drivers/media/video/gspca/vc032x.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/vc032x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/vc032x.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "vc032x"
 
 #include "gspca.h"
@@ -3169,7 +3171,7 @@
 			index, gspca_dev->usb_buf, len,
 			500);
 	if (ret < 0) {
-		err("reg_r err %d", ret);
+		pr_err("reg_r err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -3210,7 +3212,7 @@
 			value, index, NULL, 0,
 			500);
 	if (ret < 0) {
-		err("reg_w err %d", ret);
+		pr_err("reg_w err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -3235,8 +3237,7 @@
 
 	reg_r(gspca_dev, 0xa1, 0xb33f, 1);
 	if (!(gspca_dev->usb_buf[0] & 0x02)) {
-		err("I2c Bus Busy Wait %02x",
-			gspca_dev->usb_buf[0]);
+		pr_err("I2c Bus Busy Wait %02x\n", gspca_dev->usb_buf[0]);
 		return 0;
 	}
 	reg_w(gspca_dev, 0xa0, address, 0xb33a);
@@ -3349,7 +3350,7 @@
 		msleep(20);
 	} while (--retry > 0);
 	if (retry <= 0)
-		err("i2c_write timeout");
+		pr_err("i2c_write timeout\n");
 }
 
 static void put_tab_to_reg(struct gspca_dev *gspca_dev,
@@ -3446,7 +3447,7 @@
 
 	switch (sensor) {
 	case -1:
-		err("Unknown sensor...");
+		pr_err("Unknown sensor...\n");
 		return -EINVAL;
 	case SENSOR_HV7131R:
 		PDEBUG(D_PROBE, "Find Sensor HV7131R");
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/vicam.c linux-libre-3.2-gnu/drivers/media/video/gspca/vicam.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/vicam.c	2012-03-19 21:40:58.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/vicam.c	2012-03-19 21:43:32.000000000 -0400
@@ -26,6 +26,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "vicam"
 #define HEADER_SIZE 64
 
@@ -117,7 +119,7 @@
 			      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);
+		pr_err("control msg req %02X error %d\n", request, ret);
 
 	return ret;
 }
@@ -189,8 +191,8 @@
 			   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);
+		pr_err("bulk read fail (%d) len %d/%d\n",
+		       ret, act_len, size);
 		return -EIO;
 	}
 	return 0;
@@ -216,7 +218,7 @@
 		   HEADER_SIZE;
 	buffer = kmalloc(frame_sz, GFP_KERNEL | GFP_DMA);
 	if (!buffer) {
-		err("Couldn't allocate USB buffer");
+		pr_err("Couldn't allocate USB buffer\n");
 		goto exit;
 	}
 
@@ -269,7 +271,7 @@
 	ret = reject_firmware(&fw, "/*(DEBLOBBED)*/",
 				    &gspca_dev->dev->dev);
 	if (ret) {
-		err("Failed to load \"/*(DEBLOBBED)*/\": %d\n", ret);
+		pr_err("Failed to load \"/*(DEBLOBBED)*/\": %d\n", ret);
 		return ret;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/w996Xcf.c linux-libre-3.2-gnu/drivers/media/video/gspca/w996Xcf.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/w996Xcf.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/w996Xcf.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,8 @@
    the sensor drivers to v4l2 sub drivers, and properly split of this
    driver from ov519.c */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define W9968CF_I2C_BUS_DELAY    4 /* delay in us for I2C bit r/w operations */
 
 #define Y_QUANTABLE (&sd->jpeg_hdr[JPEG_QT0_OFFSET])
@@ -81,7 +83,7 @@
 			      USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
 			      value, 0x06, sd->gspca_dev.usb_buf, 6, 500);
 	if (ret < 0) {
-		err("Write FSB registers failed (%d)", ret);
+		pr_err("Write FSB registers failed (%d)\n", ret);
 		sd->gspca_dev.usb_err = ret;
 	}
 }
@@ -108,7 +110,7 @@
 	udelay(W9968CF_I2C_BUS_DELAY);
 
 	if (ret < 0) {
-		err("Write SB reg [01] %04x failed", value);
+		pr_err("Write SB reg [01] %04x failed\n", value);
 		sd->gspca_dev.usb_err = ret;
 	}
 }
@@ -135,7 +137,7 @@
 		ret = sd->gspca_dev.usb_buf[0] |
 		      (sd->gspca_dev.usb_buf[1] << 8);
 	} else {
-		err("Read SB reg [01] failed");
+		pr_err("Read SB reg [01] failed\n");
 		sd->gspca_dev.usb_err = ret;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/xirlink_cit.c linux-libre-3.2-gnu/drivers/media/video/gspca/xirlink_cit.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/xirlink_cit.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/xirlink_cit.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "xirlink-cit"
 
 #include <linux/input.h>
@@ -800,8 +802,8 @@
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
 			value, index, NULL, 0, 1000);
 	if (err < 0)
-		err("Failed to write a register (index 0x%04X,"
-			" value 0x%02X, error %d)", index, value, err);
+		pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n",
+		       index, value, err);
 
 	return 0;
 }
@@ -816,8 +818,8 @@
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
 			0x00, index, buf, 8, 1000);
 	if (res < 0) {
-		err("Failed to read a register (index 0x%04X, error %d)",
-			index, res);
+		pr_err("Failed to read a register (index 0x%04X, error %d)\n",
+		       index, res);
 		return res;
 	}
 
@@ -1587,7 +1589,7 @@
 	intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
 	alt = usb_altnum_to_altsetting(intf, gspca_dev->alt);
 	if (!alt) {
-		err("Couldn't get altsetting");
+		pr_err("Couldn't get altsetting\n");
 		return -EIO;
 	}
 
@@ -2824,7 +2826,7 @@
 
 	ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
 	if (ret < 0)
-		err("set alt 1 err %d", ret);
+		pr_err("set alt 1 err %d\n", ret);
 
 	return ret;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/gspca/zc3xx.c linux-libre-3.2-gnu/drivers/media/video/gspca/zc3xx.c
--- linux-libre-3.1-gnu/drivers/media/video/gspca/zc3xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/gspca/zc3xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define MODULE_NAME "zc3xx"
 
 #include <linux/input.h>
@@ -5666,7 +5668,7 @@
 			index, gspca_dev->usb_buf, 1,
 			500);
 	if (ret < 0) {
-		err("reg_r_i err %d", ret);
+		pr_err("reg_r_i err %d\n", ret);
 		gspca_dev->usb_err = ret;
 		return 0;
 	}
@@ -5698,7 +5700,7 @@
 			value, index, NULL, 0,
 			500);
 	if (ret < 0) {
-		err("reg_w_i err %d", ret);
+		pr_err("reg_w_i err %d\n", ret);
 		gspca_dev->usb_err = ret;
 	}
 }
@@ -5724,7 +5726,7 @@
 	msleep(20);
 	retbyte = reg_r_i(gspca_dev, 0x0091);		/* read status */
 	if (retbyte != 0x00)
-		err("i2c_r status error %02x", retbyte);
+		pr_err("i2c_r status error %02x\n", retbyte);
 	retval = reg_r_i(gspca_dev, 0x0095);		/* read Lowbyte */
 	retval |= reg_r_i(gspca_dev, 0x0096) << 8;	/* read Hightbyte */
 	PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)",
@@ -5748,7 +5750,7 @@
 	msleep(1);
 	retbyte = reg_r_i(gspca_dev, 0x0091);		/* read status */
 	if (retbyte != 0x00)
-		err("i2c_w status error %02x", retbyte);
+		pr_err("i2c_w status error %02x\n", retbyte);
 	PDEBUG(D_USBO, "i2c w [%02x] = %02x%02x (%02x)",
 			reg, valH, valL, retbyte);
 	return retbyte;
@@ -6497,7 +6499,7 @@
 				PDEBUG(D_PROBE, "Sensor GC0303");
 				break;
 			default:
-				warn("Unknown sensor - set to TAS5130C");
+				pr_warn("Unknown sensor - set to TAS5130C\n");
 				sd->sensor = SENSOR_TAS5130C;
 			}
 			break;
@@ -6603,7 +6605,7 @@
 			sd->sensor = SENSOR_OV7620;	/* same sensor (?) */
 			break;
 		default:
-			err("Unknown sensor %04x", sensor);
+			pr_err("Unknown sensor %04x\n", sensor);
 			return -EINVAL;
 		}
 	}
@@ -6970,6 +6972,7 @@
 };
 
 static const struct usb_device_id device_table[] = {
+	{USB_DEVICE(0x03f0, 0x1b07)},
 	{USB_DEVICE(0x041e, 0x041e)},
 	{USB_DEVICE(0x041e, 0x4017)},
 	{USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106},
diff -druN linux-libre-3.1-gnu/drivers/media/video/hdpvr/hdpvr-i2c.c linux-libre-3.2-gnu/drivers/media/video/hdpvr/hdpvr-i2c.c
--- linux-libre-3.1-gnu/drivers/media/video/hdpvr/hdpvr-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/hdpvr/hdpvr-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 
 #include <linux/i2c.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 
 #include "hdpvr.h"
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/hdpvr/Makefile linux-libre-3.2-gnu/drivers/media/video/hdpvr/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/hdpvr/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/hdpvr/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,6 +2,6 @@
 
 obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
+ccflags-y += -Idrivers/media/video
 
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff -druN linux-libre-3.1-gnu/drivers/media/video/hexium_gemini.c linux-libre-3.2-gnu/drivers/media/video/hexium_gemini.c
--- linux-libre-3.1-gnu/drivers/media/video/hexium_gemini.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/hexium_gemini.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,9 +21,12 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define DEBUG_VARIABLE debug
 
 #include <media/saa7146_vv.h>
+#include <linux/module.h>
 
 static int debug;
 module_param(debug, int, 0);
@@ -175,13 +178,14 @@
 	union i2c_smbus_data data;
 	int i = 0;
 
-	DEB_D(("hexium_init_done called.\n"));
+	DEB_D("hexium_init_done called\n");
 
 	/* initialize the helper ics to useful values */
 	for (i = 0; i < sizeof(hexium_ks0127b); i++) {
 		data.byte = hexium_ks0127b[i];
 		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
-			printk("hexium_gemini: hexium_init_done() failed for address 0x%02x\n", i);
+			pr_err("hexium_init_done() failed for address 0x%02x\n",
+			       i);
 		}
 	}
 
@@ -192,7 +196,7 @@
 {
 	union i2c_smbus_data data;
 
-	DEB_D((".\n"));
+	DEB_D("\n");
 
 	data.byte = hexium_input_select[input].byte;
 	if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, hexium_input_select[input].adr, I2C_SMBUS_BYTE_DATA, &data)) {
@@ -207,12 +211,13 @@
 	union i2c_smbus_data data;
 	int i = 0;
 
-	DEB_D((".\n"));
+	DEB_D("\n");
 
 	while (vdec[i].adr != -1) {
 		data.byte = vdec[i].byte;
 		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, vdec[i].adr, I2C_SMBUS_BYTE_DATA, &data)) {
-			printk("hexium_init_done: hexium_set_standard() failed for address 0x%02x\n", i);
+			pr_err("hexium_init_done: hexium_set_standard() failed for address 0x%02x\n",
+			       i);
 			return -1;
 		}
 		i++;
@@ -222,14 +227,14 @@
 
 static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 {
-	DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
+	DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
 
 	if (i->index >= HEXIUM_INPUTS)
 		return -EINVAL;
 
 	memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
 
-	DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
+	DEB_D("v4l2_ioctl: VIDIOC_ENUMINPUT %d\n", i->index);
 	return 0;
 }
 
@@ -240,7 +245,7 @@
 
 	*input = hexium->cur_input;
 
-	DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
+	DEB_D("VIDIOC_G_INPUT: %d\n", *input);
 	return 0;
 }
 
@@ -249,7 +254,7 @@
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct hexium *hexium = (struct hexium *) dev->ext_priv;
 
-	DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
+	DEB_EE("VIDIOC_S_INPUT %d\n", input);
 
 	if (input >= HEXIUM_INPUTS)
 		return -EINVAL;
@@ -270,7 +275,7 @@
 	for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
 		if (hexium_controls[i].id == qc->id) {
 			*qc = hexium_controls[i];
-			DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
+			DEB_D("VIDIOC_QUERYCTRL %d\n", qc->id);
 			return 0;
 		}
 	}
@@ -293,7 +298,7 @@
 
 	if (vc->id == V4L2_CID_PRIVATE_BASE) {
 		vc->value = hexium->cur_bw;
-		DEB_D(("VIDIOC_G_CTRL BW:%d.\n", vc->value));
+		DEB_D("VIDIOC_G_CTRL BW:%d\n", vc->value);
 		return 0;
 	}
 	return -EINVAL;
@@ -316,7 +321,7 @@
 	if (vc->id == V4L2_CID_PRIVATE_BASE)
 		hexium->cur_bw = vc->value;
 
-	DEB_D(("VIDIOC_S_CTRL BW:%d.\n", hexium->cur_bw));
+	DEB_D("VIDIOC_S_CTRL BW:%d\n", hexium->cur_bw);
 
 	if (0 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
 		hexium_set_standard(hexium, hexium_pal);
@@ -351,14 +356,14 @@
 /* this function only gets called when the probing was successful */
 static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
 {
-	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+	struct hexium *hexium;
 	int ret;
 
-	DEB_EE((".\n"));
+	DEB_EE("\n");
 
 	hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL);
 	if (NULL == hexium) {
-		printk("hexium_gemini: not enough kernel memory in hexium_attach().\n");
+		pr_err("not enough kernel memory in hexium_attach()\n");
 		return -ENOMEM;
 	}
 	dev->ext_priv = hexium;
@@ -371,7 +376,7 @@
 	};
 	saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
 	if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
-		DEB_S(("cannot register i2c-device. skipping.\n"));
+		DEB_S("cannot register i2c-device. skipping.\n");
 		kfree(hexium);
 		return -EFAULT;
 	}
@@ -402,11 +407,11 @@
 	vv_data.ops.vidioc_s_input = vidioc_s_input;
 	ret = saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER);
 	if (ret < 0) {
-		printk("hexium_gemini: cannot register capture v4l2 device. skipping.\n");
+		pr_err("cannot register capture v4l2 device. skipping.\n");
 		return ret;
 	}
 
-	printk("hexium_gemini: found 'hexium gemini' frame grabber-%d.\n", hexium_num);
+	pr_info("found 'hexium gemini' frame grabber-%d\n", hexium_num);
 	hexium_num++;
 
 	return 0;
@@ -416,7 +421,7 @@
 {
 	struct hexium *hexium = (struct hexium *) dev->ext_priv;
 
-	DEB_EE(("dev:%p\n", dev));
+	DEB_EE("dev:%p\n", dev);
 
 	saa7146_unregister_device(&hexium->video_dev, dev);
 	saa7146_vv_release(dev);
@@ -508,7 +513,7 @@
 static int __init hexium_init_module(void)
 {
 	if (0 != saa7146_register_extension(&hexium_extension)) {
-		DEB_S(("failed to register extension.\n"));
+		DEB_S("failed to register extension\n");
 		return -ENODEV;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/hexium_orion.c linux-libre-3.2-gnu/drivers/media/video/hexium_orion.c
--- linux-libre-3.1-gnu/drivers/media/video/hexium_orion.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/hexium_orion.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,9 +21,12 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define DEBUG_VARIABLE debug
 
 #include <media/saa7146_vv.h>
+#include <linux/module.h>
 
 static int debug;
 module_param(debug, int, 0);
@@ -209,7 +212,7 @@
 	union i2c_smbus_data data;
 	int err = 0;
 
-	DEB_EE((".\n"));
+	DEB_EE("\n");
 
 	/* there are no hexium orion cards with revision 0 saa7146s */
 	if (0 == dev->revision) {
@@ -218,7 +221,7 @@
 
 	hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL);
 	if (NULL == hexium) {
-		printk("hexium_orion: hexium_probe: not enough kernel memory.\n");
+		pr_err("hexium_probe: not enough kernel memory\n");
 		return -ENOMEM;
 	}
 
@@ -234,7 +237,7 @@
 	};
 	saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
 	if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
-		DEB_S(("cannot register i2c-device. skipping.\n"));
+		DEB_S("cannot register i2c-device. skipping.\n");
 		kfree(hexium);
 		return -EFAULT;
 	}
@@ -248,7 +251,7 @@
 
 	/* detect newer Hexium Orion cards by subsystem ids */
 	if (0x17c8 == dev->pci->subsystem_vendor && 0x0101 == dev->pci->subsystem_device) {
-		printk("hexium_orion: device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs.\n");
+		pr_info("device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs\n");
 		/* we store the pointer in our private data field */
 		dev->ext_priv = hexium;
 		hexium->type = HEXIUM_ORION_1SVHS_3BNC;
@@ -256,7 +259,7 @@
 	}
 
 	if (0x17c8 == dev->pci->subsystem_vendor && 0x2101 == dev->pci->subsystem_device) {
-		printk("hexium_orion: device is a Hexium Orion w/ 4 BNC inputs.\n");
+		pr_info("device is a Hexium Orion w/ 4 BNC inputs\n");
 		/* we store the pointer in our private data field */
 		dev->ext_priv = hexium;
 		hexium->type = HEXIUM_ORION_4BNC;
@@ -266,7 +269,7 @@
 	/* check if this is an old hexium Orion card by looking at
 	   a saa7110 at address 0x4e */
 	if (0 == (err = i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, &data))) {
-		printk("hexium_orion: device is a Hexium HV-PCI6/Orion (old).\n");
+		pr_info("device is a Hexium HV-PCI6/Orion (old)\n");
 		/* we store the pointer in our private data field */
 		dev->ext_priv = hexium;
 		hexium->type = HEXIUM_HV_PCI6_ORION;
@@ -288,13 +291,13 @@
 	union i2c_smbus_data data;
 	int i = 0;
 
-	DEB_D(("hexium_init_done called.\n"));
+	DEB_D("hexium_init_done called\n");
 
 	/* initialize the helper ics to useful values */
 	for (i = 0; i < sizeof(hexium_saa7110); i++) {
 		data.byte = hexium_saa7110[i];
 		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
-			printk("hexium_orion: failed for address 0x%02x\n", i);
+			pr_err("failed for address 0x%02x\n", i);
 		}
 	}
 
@@ -306,7 +309,7 @@
 	union i2c_smbus_data data;
 	int i = 0;
 
-	DEB_D((".\n"));
+	DEB_D("\n");
 
 	for (i = 0; i < 8; i++) {
 		int adr = hexium_input_select[input].data[i].adr;
@@ -314,7 +317,7 @@
 		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, adr, I2C_SMBUS_BYTE_DATA, &data)) {
 			return -1;
 		}
-		printk("%d: 0x%02x => 0x%02x\n",input, adr,data.byte);
+		pr_debug("%d: 0x%02x => 0x%02x\n", input, adr, data.byte);
 	}
 
 	return 0;
@@ -322,14 +325,14 @@
 
 static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 {
-	DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
+	DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
 
 	if (i->index >= HEXIUM_INPUTS)
 		return -EINVAL;
 
 	memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
 
-	DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
+	DEB_D("v4l2_ioctl: VIDIOC_ENUMINPUT %d\n", i->index);
 	return 0;
 }
 
@@ -340,7 +343,7 @@
 
 	*input = hexium->cur_input;
 
-	DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
+	DEB_D("VIDIOC_G_INPUT: %d\n", *input);
 	return 0;
 }
 
@@ -365,18 +368,18 @@
 {
 	struct hexium *hexium = (struct hexium *) dev->ext_priv;
 
-	DEB_EE((".\n"));
+	DEB_EE("\n");
 
 	saa7146_vv_init(dev, &vv_data);
 	vv_data.ops.vidioc_enum_input = vidioc_enum_input;
 	vv_data.ops.vidioc_g_input = vidioc_g_input;
 	vv_data.ops.vidioc_s_input = vidioc_s_input;
 	if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_GRABBER)) {
-		printk("hexium_orion: cannot register capture v4l2 device. skipping.\n");
+		pr_err("cannot register capture v4l2 device. skipping.\n");
 		return -1;
 	}
 
-	printk("hexium_orion: found 'hexium orion' frame grabber-%d.\n", hexium_num);
+	pr_err("found 'hexium orion' frame grabber-%d\n", hexium_num);
 	hexium_num++;
 
 	/* the rest */
@@ -390,7 +393,7 @@
 {
 	struct hexium *hexium = (struct hexium *) dev->ext_priv;
 
-	DEB_EE(("dev:%p\n", dev));
+	DEB_EE("dev:%p\n", dev);
 
 	saa7146_unregister_device(&hexium->video_dev, dev);
 	saa7146_vv_release(dev);
@@ -479,7 +482,7 @@
 static int __init hexium_init_module(void)
 {
 	if (0 != saa7146_register_extension(&extension)) {
-		DEB_S(("failed to register extension.\n"));
+		DEB_S("failed to register extension\n");
 		return -ENODEV;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/imx074.c linux-libre-3.2-gnu/drivers/media/video/imx074.c
--- linux-libre-3.1-gnu/drivers/media/video/imx074.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/imx074.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,11 +12,12 @@
 
 #include <linux/delay.h>
 #include <linux/i2c.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
+#include <linux/module.h>
 
 #include <media/soc_camera.h>
-#include <media/soc_mediabus.h>
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-chip-ident.h>
 
@@ -267,6 +268,17 @@
 	return 0;
 }
 
+static int imx074_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	cfg->type = V4L2_MBUS_CSI2;
+	cfg->flags = V4L2_MBUS_CSI2_2_LANE |
+		V4L2_MBUS_CSI2_CHANNEL_0 |
+		V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
+
+	return 0;
+}
+
 static struct v4l2_subdev_video_ops imx074_subdev_video_ops = {
 	.s_stream	= imx074_s_stream,
 	.s_mbus_fmt	= imx074_s_fmt,
@@ -275,6 +287,7 @@
 	.enum_mbus_fmt	= imx074_enum_fmt,
 	.g_crop		= imx074_g_crop,
 	.cropcap	= imx074_cropcap,
+	.g_mbus_config	= imx074_g_mbus_config,
 };
 
 static struct v4l2_subdev_core_ops imx074_subdev_core_ops = {
@@ -286,28 +299,7 @@
 	.video	= &imx074_subdev_video_ops,
 };
 
-/*
- * We have to provide soc-camera operations, but we don't have anything to say
- * there. The MIPI CSI2 driver will provide .query_bus_param and .set_bus_param
- */
-static unsigned long imx074_query_bus_param(struct soc_camera_device *icd)
-{
-	return 0;
-}
-
-static int imx074_set_bus_param(struct soc_camera_device *icd,
-				 unsigned long flags)
-{
-	return -EINVAL;
-}
-
-static struct soc_camera_ops imx074_ops = {
-	.query_bus_param	= imx074_query_bus_param,
-	.set_bus_param		= imx074_set_bus_param,
-};
-
-static int imx074_video_probe(struct soc_camera_device *icd,
-			      struct i2c_client *client)
+static int imx074_video_probe(struct i2c_client *client)
 {
 	int ret;
 	u16 id;
@@ -417,17 +409,10 @@
 			const struct i2c_device_id *did)
 {
 	struct imx074 *priv;
-	struct soc_camera_device *icd = client->dev.platform_data;
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-	struct soc_camera_link *icl;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 	int ret;
 
-	if (!icd) {
-		dev_err(&client->dev, "IMX074: missing soc-camera data!\n");
-		return -EINVAL;
-	}
-
-	icl = to_soc_camera_link(icd);
 	if (!icl) {
 		dev_err(&client->dev, "IMX074: missing platform data!\n");
 		return -EINVAL;
@@ -445,12 +430,10 @@
 
 	v4l2_i2c_subdev_init(&priv->subdev, client, &imx074_subdev_ops);
 
-	icd->ops	= &imx074_ops;
 	priv->fmt	= &imx074_colour_fmts[0];
 
-	ret = imx074_video_probe(icd, client);
+	ret = imx074_video_probe(client);
 	if (ret < 0) {
-		icd->ops = NULL;
 		kfree(priv);
 		return ret;
 	}
@@ -461,10 +444,8 @@
 static int imx074_remove(struct i2c_client *client)
 {
 	struct imx074 *priv = to_imx074(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 
-	icd->ops = NULL;
 	if (icl->free_bus)
 		icl->free_bus(icl);
 	kfree(priv);
diff -druN linux-libre-3.1-gnu/drivers/media/video/ivtv/ivtv-driver.c linux-libre-3.2-gnu/drivers/media/video/ivtv/ivtv-driver.c
--- linux-libre-3.1-gnu/drivers/media/video/ivtv/ivtv-driver.c	2012-03-19 21:31:22.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/ivtv/ivtv-driver.c	2012-03-19 21:33:30.000000000 -0400
@@ -1180,6 +1180,8 @@
 		setup.addr = ADDR_UNSET;
 		setup.type = itv->options.tuner;
 		setup.mode_mask = T_ANALOG_TV;  /* matches TV tuners */
+		if (itv->options.radio > 0)
+			setup.mode_mask |= T_RADIO;
 		setup.tuner_callback = (setup.type == TUNER_XC2028) ?
 			ivtv_reset_tuner_gpio : NULL;
 		ivtv_call_all(itv, tuner, s_type_addr, &setup);
diff -druN linux-libre-3.1-gnu/drivers/media/video/ivtv/ivtv-ioctl.c linux-libre-3.2-gnu/drivers/media/video/ivtv/ivtv-ioctl.c
--- linux-libre-3.1-gnu/drivers/media/video/ivtv/ivtv-ioctl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/ivtv/ivtv-ioctl.c	2012-01-04 18:55:44.000000000 -0500
@@ -1203,9 +1203,7 @@
 					cap->service_lines[f][l] = set;
 			}
 		}
-		return 0;
-	}
-	if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
+	} else if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
 		if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
 			return -EINVAL;
 		if (itv->is_60hz) {
@@ -1215,9 +1213,16 @@
 			cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
 			cap->service_lines[0][16] = V4L2_SLICED_VPS;
 		}
-		return 0;
+	} else {
+		return -EINVAL;
 	}
-	return -EINVAL;
+
+	set = 0;
+	for (f = 0; f < 2; f++)
+		for (l = 0; l < 24; l++)
+			set |= cap->service_lines[f][l];
+	cap->service_set = set;
+	return 0;
 }
 
 static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
diff -druN linux-libre-3.1-gnu/drivers/media/video/ivtv/Makefile linux-libre-3.2-gnu/drivers/media/video/ivtv/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/ivtv/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/ivtv/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -7,8 +7,8 @@
 obj-$(CONFIG_VIDEO_IVTV) += ivtv.o
 obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/Kconfig linux-libre-3.2-gnu/drivers/media/video/Kconfig
--- linux-libre-3.1-gnu/drivers/media/video/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -467,6 +467,20 @@
 	  OV7670 VGA camera.  It currently only works with the M88ALP01
 	  controller.
 
+config VIDEO_MT9P031
+	tristate "Aptina MT9P031 support"
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	---help---
+	  This is a Video4Linux2 sensor-level driver for the Aptina
+	  (Micron) mt9p031 5 Mpixel camera.
+
+config VIDEO_MT9T001
+	tristate "Aptina MT9T001 support"
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	---help---
+	  This is a Video4Linux2 sensor-level driver for the Aptina
+	  (Micron) mt0t001 3 Mpixel camera.
+
 config VIDEO_MT9V011
 	tristate "Micron mt9v011 sensor support"
 	depends on I2C && VIDEO_V4L2
@@ -489,6 +503,27 @@
 	  This is a driver for the Toshiba TCM825x VGA camera sensor.
 	  It is used for example in Nokia N800.
 
+config VIDEO_SR030PC30
+	tristate "Siliconfile SR030PC30 sensor support"
+	depends on I2C && VIDEO_V4L2
+	---help---
+	  This driver supports SR030PC30 VGA camera from Siliconfile
+
+config VIDEO_NOON010PC30
+	tristate "Siliconfile NOON010PC30 sensor support"
+	depends on I2C && VIDEO_V4L2 && EXPERIMENTAL && VIDEO_V4L2_SUBDEV_API
+	---help---
+	  This driver supports NOON010PC30 CIF camera from Siliconfile
+
+source "drivers/media/video/m5mols/Kconfig"
+
+config VIDEO_S5K6AA
+	tristate "Samsung S5K6AAFX sensor support"
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	---help---
+	  This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M
+	  camera sensor with an embedded SoC image signal processor.
+
 comment "Flash devices"
 
 config VIDEO_ADP1653
@@ -708,6 +743,8 @@
 
 source "drivers/media/video/cx23885/Kconfig"
 
+source "drivers/media/video/cx25821/Kconfig"
+
 source "drivers/media/video/au0828/Kconfig"
 
 source "drivers/media/video/ivtv/Kconfig"
@@ -737,12 +774,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called arv.
 
-config VIDEO_SR030PC30
-	tristate "SR030PC30 VGA camera sensor support"
-	depends on I2C && VIDEO_V4L2
-	---help---
-	  This driver supports SR030PC30 VGA camera from Siliconfile
-
 config VIDEO_VIA_CAMERA
 	tristate "VIAFB camera controller support"
 	depends on FB_VIA
@@ -753,18 +784,9 @@
 	   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
-
-source "drivers/media/video/m5mols/Kconfig"
-
 config VIDEO_OMAP3
 	tristate "OMAP 3 Camera support (EXPERIMENTAL)"
-	select OMAP_IOMMU
-	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL
+	depends on OMAP_IOVMM && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL
 	---help---
 	  Driver for an OMAP 3 camera controller.
 
@@ -949,8 +971,9 @@
 	  Interface
 
 config  VIDEO_SAMSUNG_S5P_FIMC
-	tristate "Samsung S5P and EXYNOS4 camera host interface driver"
-	depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
+	tristate "Samsung S5P and EXYNOS4 camera interface driver (EXPERIMENTAL)"
+	depends on VIDEO_V4L2 && I2C && PLAT_S5P && PM_RUNTIME && \
+		VIDEO_V4L2_SUBDEV_API && EXPERIMENTAL
 	select VIDEOBUF2_DMA_CONTIG
 	select V4L2_MEM2MEM_DEV
 	---help---
@@ -1004,6 +1027,8 @@
 
 source "drivers/media/video/cx231xx/Kconfig"
 
+source "drivers/media/video/tm6000/Kconfig"
+
 source "drivers/media/video/usbvision/Kconfig"
 
 source "drivers/media/video/et61x251/Kconfig"
diff -druN linux-libre-3.1-gnu/drivers/media/video/m5mols/m5mols_core.c linux-libre-3.2-gnu/drivers/media/video/m5mols/m5mols_core.c
--- linux-libre-3.1-gnu/drivers/media/video/m5mols/m5mols_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/m5mols/m5mols_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/videodev2.h>
+#include <linux/module.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-subdev.h>
@@ -333,7 +334,7 @@
 	int ret = -EINVAL;
 	u8 reg;
 
-	if (mode < REG_PARAMETER && mode > REG_CAPTURE)
+	if (mode < REG_PARAMETER || mode > REG_CAPTURE)
 		return ret;
 
 	ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, &reg);
@@ -510,9 +511,6 @@
 	struct m5mols_info *info = to_m5mols(sd);
 	struct v4l2_mbus_framefmt *format;
 
-	if (fmt->pad != 0)
-		return -EINVAL;
-
 	format = __find_format(info, fh, fmt->which, info->res_type);
 	if (!format)
 		return -EINVAL;
@@ -531,9 +529,6 @@
 	u32 resolution = 0;
 	int ret;
 
-	if (fmt->pad != 0)
-		return -EINVAL;
-
 	ret = __find_resolution(sd, format, &type, &resolution);
 	if (ret < 0)
 		return ret;
@@ -542,13 +537,14 @@
 	if (!sfmt)
 		return 0;
 
-	*sfmt		= m5mols_default_ffmt[type];
-	sfmt->width	= format->width;
-	sfmt->height	= format->height;
+
+	format->code = m5mols_default_ffmt[type].code;
+	format->colorspace = V4L2_COLORSPACE_JPEG;
+	format->field = V4L2_FIELD_NONE;
 
 	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		*sfmt = *format;
 		info->resolution = resolution;
-		info->code = format->code;
 		info->res_type = type;
 	}
 
@@ -625,13 +621,14 @@
 static int m5mols_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct m5mols_info *info = to_m5mols(sd);
+	u32 code = info->ffmt[info->res_type].code;
 
 	if (enable) {
 		int ret = -EINVAL;
 
-		if (is_code(info->code, M5MOLS_RESTYPE_MONITOR))
+		if (is_code(code, M5MOLS_RESTYPE_MONITOR))
 			ret = m5mols_start_monitor(info);
-		if (is_code(info->code, M5MOLS_RESTYPE_CAPTURE))
+		if (is_code(code, M5MOLS_RESTYPE_CAPTURE))
 			ret = m5mols_start_capture(info);
 
 		return ret;
@@ -936,7 +933,7 @@
 		return -EINVAL;
 	}
 
-	if (!pdata->irq) {
+	if (!client->irq) {
 		dev_err(&client->dev, "Interrupt not assigned\n");
 		return -EINVAL;
 	}
@@ -973,7 +970,7 @@
 
 	init_waitqueue_head(&info->irq_waitq);
 	INIT_WORK(&info->work_irq, m5mols_irq_work);
-	ret = request_irq(pdata->irq, m5mols_irq_handler,
+	ret = request_irq(client->irq, m5mols_irq_handler,
 			  IRQF_TRIGGER_RISING, MODULE_NAME, sd);
 	if (ret) {
 		dev_err(&client->dev, "Interrupt request failed: %d\n", ret);
@@ -998,7 +995,7 @@
 	struct m5mols_info *info = to_m5mols(sd);
 
 	v4l2_device_unregister_subdev(sd);
-	free_irq(info->pdata->irq, sd);
+	free_irq(client->irq, sd);
 
 	regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
 	gpio_free(info->pdata->gpio_reset);
diff -druN linux-libre-3.1-gnu/drivers/media/video/m5mols/m5mols.h linux-libre-3.2-gnu/drivers/media/video/m5mols/m5mols.h
--- linux-libre-3.1-gnu/drivers/media/video/m5mols/m5mols.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/m5mols/m5mols.h	2012-01-04 18:55:44.000000000 -0500
@@ -162,7 +162,6 @@
  * @pad: media pad
  * @ffmt: current fmt according to resolution type
  * @res_type: current resolution type
- * @code: current code
  * @irq_waitq: waitqueue for the capture
  * @work_irq: workqueue for the IRQ
  * @flags: state variable for the interrupt handler
@@ -192,7 +191,6 @@
 	struct media_pad pad;
 	struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX];
 	int res_type;
-	enum v4l2_mbus_pixelcode code;
 	wait_queue_head_t irq_waitq;
 	struct work_struct work_irq;
 	unsigned long flags;
diff -druN linux-libre-3.1-gnu/drivers/media/video/Makefile linux-libre-3.2-gnu/drivers/media/video/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -65,11 +65,14 @@
 obj-$(CONFIG_VIDEO_OV7670) 	+= ov7670.o
 obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
 obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
+obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
+obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o
 obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
 obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
 obj-$(CONFIG_VIDEO_SR030PC30)	+= sr030pc30.o
 obj-$(CONFIG_VIDEO_NOON010PC30)	+= noon010pc30.o
 obj-$(CONFIG_VIDEO_M5MOLS)	+= m5mols/
+obj-$(CONFIG_VIDEO_S5K6AA)	+= s5k6aa.o
 obj-$(CONFIG_VIDEO_ADP1653)	+= adp1653.o
 
 obj-$(CONFIG_SOC_CAMERA_IMX074)		+= imx074.o
@@ -102,9 +105,11 @@
 obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
 obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/
 obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
+obj-$(CONFIG_VIDEO_CX25821) += cx25821/
 obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
 obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
 obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
+obj-$(CONFIG_VIDEO_TM6000) += tm6000/
 obj-$(CONFIG_VIDEO_MXB) += mxb.o
 obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
 obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
@@ -190,6 +195,6 @@
 
 obj-$(CONFIG_ARCH_OMAP)	+= omap/
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/common/tuners
diff -druN linux-libre-3.1-gnu/drivers/media/video/marvell-ccic/mcam-core.c linux-libre-3.2-gnu/drivers/media/video/marvell-ccic/mcam-core.c
--- linux-libre-3.1-gnu/drivers/media/video/marvell-ccic/mcam-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/marvell-ccic/mcam-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -450,7 +450,7 @@
 		buf = cam->vb_bufs[frame ^ 0x1];
 		cam->vb_bufs[frame] = buf;
 		mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
-				vb2_dma_contig_plane_paddr(&buf->vb_buf, 0));
+				vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
 		set_bit(CF_SINGLE_BUFFER, &cam->flags);
 		singles++;
 		return;
@@ -461,7 +461,7 @@
 	buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue);
 	list_del_init(&buf->queue);
 	mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
-			vb2_dma_contig_plane_paddr(&buf->vb_buf, 0));
+			vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
 	cam->vb_bufs[frame] = buf;
 	clear_bit(CF_SINGLE_BUFFER, &cam->flags);
 }
@@ -883,8 +883,9 @@
  * Videobuf2 interface code.
  */
 
-static int mcam_vb_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
-		unsigned int *num_planes, unsigned long sizes[],
+static int mcam_vb_queue_setup(struct vb2_queue *vq,
+		const struct v4l2_format *fmt, unsigned int *nbufs,
+		unsigned int *num_planes, unsigned int sizes[],
 		void *alloc_ctxs[])
 {
 	struct mcam_camera *cam = vb2_get_drv_priv(vq);
@@ -940,12 +941,14 @@
 /*
  * These need to be called with the mutex held from vb2
  */
-static int mcam_vb_start_streaming(struct vb2_queue *vq)
+static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct mcam_camera *cam = vb2_get_drv_priv(vq);
 
-	if (cam->state != S_IDLE)
+	if (cam->state != S_IDLE) {
+		INIT_LIST_HEAD(&cam->buffers);
 		return -EINVAL;
+	}
 	cam->sequence = 0;
 	/*
 	 * Videobuf2 sneakily hoards all the buffers and won't
diff -druN linux-libre-3.1-gnu/drivers/media/video/marvell-ccic/mmp-driver.c linux-libre-3.2-gnu/drivers/media/video/marvell-ccic/mmp-driver.c
--- linux-libre-3.1-gnu/drivers/media/video/marvell-ccic/mmp-driver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/marvell-ccic/mmp-driver.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 
 #include "mcam-core.h"
 
+MODULE_ALIAS("platform:mmp-camera");
 MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
 MODULE_LICENSE("GPL");
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/mem2mem_testdev.c linux-libre-3.2-gnu/drivers/media/video/mem2mem_testdev.c
--- linux-libre-3.1-gnu/drivers/media/video/mem2mem_testdev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/mem2mem_testdev.c	2012-01-04 18:55:44.000000000 -0500
@@ -738,9 +738,10 @@
  * Queue operations
  */
 
-static int m2mtest_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
-				unsigned int *nplanes, unsigned long sizes[],
-				void *alloc_ctxs[])
+static int m2mtest_queue_setup(struct vb2_queue *vq,
+				const struct v4l2_format *fmt,
+				unsigned int *nbuffers, unsigned int *nplanes,
+				unsigned int sizes[], void *alloc_ctxs[])
 {
 	struct m2mtest_ctx *ctx = vb2_get_drv_priv(vq);
 	struct m2mtest_q_data *q_data;
@@ -793,10 +794,24 @@
 	v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
 }
 
+static void m2mtest_wait_prepare(struct vb2_queue *q)
+{
+	struct m2mtest_ctx *ctx = vb2_get_drv_priv(q);
+	m2mtest_unlock(ctx);
+}
+
+static void m2mtest_wait_finish(struct vb2_queue *q)
+{
+	struct m2mtest_ctx *ctx = vb2_get_drv_priv(q);
+	m2mtest_lock(ctx);
+}
+
 static struct vb2_ops m2mtest_qops = {
 	.queue_setup	 = m2mtest_queue_setup,
 	.buf_prepare	 = m2mtest_buf_prepare,
 	.buf_queue	 = m2mtest_buf_queue,
+	.wait_prepare	 = m2mtest_wait_prepare,
+	.wait_finish	 = m2mtest_wait_finish,
 };
 
 static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
diff -druN linux-libre-3.1-gnu/drivers/media/video/msp3400-driver.c linux-libre-3.2-gnu/drivers/media/video/msp3400-driver.c
--- linux-libre-3.1-gnu/drivers/media/video/msp3400-driver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/msp3400-driver.c	2012-01-04 18:55:44.000000000 -0500
@@ -426,6 +426,20 @@
 	return 0;
 }
 
+static int msp_querystd(struct v4l2_subdev *sd, v4l2_std_id *id)
+{
+	struct msp_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	*id &= state->detected_std;
+
+	v4l_dbg(2, msp_debug, client,
+		"detected standard: %s(0x%08Lx)\n",
+		msp_standard_std_name(state->std), state->detected_std);
+
+	return 0;
+}
+
 static int msp_s_std(struct v4l2_subdev *sd, v4l2_std_id id)
 {
 	struct msp_state *state = to_state(sd);
@@ -616,6 +630,10 @@
 	.s_std = msp_s_std,
 };
 
+static const struct v4l2_subdev_video_ops msp_video_ops = {
+	.querystd = msp_querystd,
+};
+
 static const struct v4l2_subdev_tuner_ops msp_tuner_ops = {
 	.s_frequency = msp_s_frequency,
 	.g_tuner = msp_g_tuner,
@@ -630,6 +648,7 @@
 
 static const struct v4l2_subdev_ops msp_ops = {
 	.core = &msp_core_ops,
+	.video = &msp_video_ops,
 	.tuner = &msp_tuner_ops,
 	.audio = &msp_audio_ops,
 };
@@ -664,6 +683,7 @@
 	v4l2_i2c_subdev_init(sd, client, &msp_ops);
 
 	state->v4l2_std = V4L2_STD_NTSC;
+	state->detected_std = V4L2_STD_ALL;
 	state->audmode = V4L2_TUNER_MODE_STEREO;
 	state->input = -1;
 	state->i2s_mode = 0;
diff -druN linux-libre-3.1-gnu/drivers/media/video/msp3400-driver.h linux-libre-3.2-gnu/drivers/media/video/msp3400-driver.h
--- linux-libre-3.1-gnu/drivers/media/video/msp3400-driver.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/msp3400-driver.h	2012-01-04 18:55:44.000000000 -0500
@@ -75,7 +75,7 @@
 	int opmode;
 	int std;
 	int mode;
-	v4l2_std_id v4l2_std;
+	v4l2_std_id v4l2_std, detected_std;
 	int nicam_on;
 	int acb;
 	int in_scart;
diff -druN linux-libre-3.1-gnu/drivers/media/video/msp3400-kthreads.c linux-libre-3.2-gnu/drivers/media/video/msp3400-kthreads.c
--- linux-libre-3.1-gnu/drivers/media/video/msp3400-kthreads.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/msp3400-kthreads.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,29 +37,49 @@
 	int retval;
 	int main, second;
 	char *name;
+	v4l2_std_id std;
 } msp_stdlist[] = {
-	{ 0x0000, 0, 0, "could not detect sound standard" },
-	{ 0x0001, 0, 0, "autodetect start" },
-	{ 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), "4.5/4.72  M Dual FM-Stereo" },
-	{ 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), "5.5/5.74  B/G Dual FM-Stereo" },
-	{ 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25  D/K1 Dual FM-Stereo" },
-	{ 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74  D/K2 Dual FM-Stereo" },
-	{ 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5  D/K FM-Mono (HDEV3)" },
-	{ 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875), "6.5/5.74  D/K3 Dual FM-Stereo" },
-	{ 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85  B/G NICAM FM" },
-	{ 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85  L NICAM AM" },
-	{ 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55  I NICAM FM" },
-	{ 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85  D/K NICAM FM" },
-	{ 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85  D/K NICAM FM (HDEV2)" },
-	{ 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85  D/K NICAM FM (HDEV3)" },
-	{ 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5  M BTSC-Stereo" },
-	{ 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5  M BTSC-Mono + SAP" },
-	{ 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5  M EIA-J Japan Stereo" },
-	{ 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), "10.7  FM-Stereo Radio" },
-	{ 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5  SAT-Mono" },
-	{ 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), "7.02/7.20  SAT-Stereo" },
-	{ 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2  SAT ADR" },
-	{     -1, 0, 0, NULL }, /* EOF */
+	{ 0x0000, 0, 0, "could not detect sound standard", V4L2_STD_ALL },
+	{ 0x0001, 0, 0, "autodetect start", V4L2_STD_ALL },
+	{ 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72),
+	  "4.5/4.72  M Dual FM-Stereo", V4L2_STD_MN },
+	{ 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875),
+	  "5.5/5.74  B/G Dual FM-Stereo", V4L2_STD_BG },
+	{ 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125),
+	  "6.5/6.25  D/K1 Dual FM-Stereo", V4L2_STD_DK },
+	{ 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875),
+	  "6.5/6.74  D/K2 Dual FM-Stereo", V4L2_STD_DK },
+	{ 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5),
+	  "6.5  D/K FM-Mono (HDEV3)", V4L2_STD_DK },
+	{ 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875),
+	  "6.5/5.74  D/K3 Dual FM-Stereo", V4L2_STD_DK },
+	{ 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85),
+	  "5.5/5.85  B/G NICAM FM", V4L2_STD_BG },
+	{ 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
+	  "6.5/5.85  L NICAM AM", V4L2_STD_L },
+	{ 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55),
+	  "6.0/6.55  I NICAM FM", V4L2_STD_PAL_I },
+	{ 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
+	  "6.5/5.85  D/K NICAM FM", V4L2_STD_DK },
+	{ 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
+	  "6.5/5.85  D/K NICAM FM (HDEV2)", V4L2_STD_DK },
+	{ 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
+	  "6.5/5.85  D/K NICAM FM (HDEV3)", V4L2_STD_DK },
+	{ 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
+	  "4.5  M BTSC-Stereo", V4L2_STD_MTS },
+	{ 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
+	  "4.5  M BTSC-Mono + SAP", V4L2_STD_MTS },
+	{ 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
+	  "4.5  M EIA-J Japan Stereo", V4L2_STD_NTSC_M_JP },
+	{ 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7),
+	  "10.7  FM-Stereo Radio", V4L2_STD_ALL },
+	{ 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5),
+	  "6.5  SAT-Mono", V4L2_STD_ALL },
+	{ 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20),
+	  "7.02/7.20  SAT-Stereo", V4L2_STD_ALL },
+	{ 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2),
+	  "7.2  SAT ADR", V4L2_STD_ALL },
+	{     -1, 0, 0, NULL, 0 }, /* EOF */
 };
 
 static struct msp3400c_init_data_dem {
@@ -156,6 +176,16 @@
 	return "unknown";
 }
 
+static v4l2_std_id msp_standard_std(int std)
+{
+	int i;
+
+	for (i = 0; msp_stdlist[i].name != NULL; i++)
+		if (msp_stdlist[i].retval == std)
+			return msp_stdlist[i].std;
+	return V4L2_STD_ALL;
+}
+
 static void msp_set_source(struct i2c_client *client, u16 src)
 {
 	struct msp_state *state = to_state(i2c_get_clientdata(client));
@@ -479,6 +509,7 @@
 	int count, max1, max2, val1, val2, val, i;
 
 	v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n");
+	state->detected_std = V4L2_STD_ALL;
 	set_freezable();
 	for (;;) {
 		v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n");
@@ -579,6 +610,7 @@
 		state->main = msp3400c_carrier_detect_main[max1].cdo;
 		switch (max1) {
 		case 1: /* 5.5 */
+			state->detected_std = V4L2_STD_BG | V4L2_STD_PAL_H;
 			if (max2 == 0) {
 				/* B/G FM-stereo */
 				state->second = msp3400c_carrier_detect_55[max2].cdo;
@@ -596,6 +628,7 @@
 			break;
 		case 2: /* 6.0 */
 			/* PAL I NICAM */
+			state->detected_std = V4L2_STD_PAL_I;
 			state->second = MSP_CARRIER(6.552);
 			msp3400c_set_mode(client, MSP_MODE_FM_NICAM2);
 			state->nicam_on = 1;
@@ -607,22 +640,26 @@
 				state->second = msp3400c_carrier_detect_65[max2].cdo;
 				msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
 				state->watch_stereo = 1;
+				state->detected_std = V4L2_STD_DK;
 			} else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) {
 				/* L NICAM or AM-mono */
 				state->second = msp3400c_carrier_detect_65[max2].cdo;
 				msp3400c_set_mode(client, MSP_MODE_AM_NICAM);
 				state->watch_stereo = 1;
+				state->detected_std = V4L2_STD_L;
 			} else if (max2 == 0 && state->has_nicam) {
 				/* D/K NICAM */
 				state->second = msp3400c_carrier_detect_65[max2].cdo;
 				msp3400c_set_mode(client, MSP_MODE_FM_NICAM1);
 				state->nicam_on = 1;
 				state->watch_stereo = 1;
+				state->detected_std = V4L2_STD_DK;
 			} else {
 				goto no_second;
 			}
 			break;
 		case 0: /* 4.5 */
+			state->detected_std = V4L2_STD_MN;
 		default:
 no_second:
 			state->second = msp3400c_carrier_detect_main[max1].cdo;
@@ -662,6 +699,7 @@
 	int val, i, std, count;
 
 	v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
+	state->detected_std = V4L2_STD_ALL;
 	set_freezable();
 	for (;;) {
 		v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n");
@@ -743,6 +781,8 @@
 					msp_stdlist[8].name : "unknown", val);
 			state->std = val = 0x0009;
 			msp_write_dem(client, 0x20, val);
+		} else {
+			state->detected_std = msp_standard_std(state->std);
 		}
 
 		/* set stereo */
@@ -957,6 +997,7 @@
 	int val, i;
 
 	v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
+	state->detected_std = V4L2_STD_ALL;
 	set_freezable();
 	for (;;) {
 		v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
@@ -1013,6 +1054,7 @@
 		v4l_dbg(1, msp_debug, client,
 			"detected standard: %s (0x%04x)\n",
 			msp_standard_std_name(state->std), state->std);
+		state->detected_std = msp_standard_std(state->std);
 
 		if (state->std == 9) {
 			/* AM NICAM mode */
diff -druN linux-libre-3.1-gnu/drivers/media/video/mt9m001.c linux-libre-3.2-gnu/drivers/media/video/mt9m001.c
--- linux-libre-3.1-gnu/drivers/media/video/mt9m001.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/mt9m001.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,10 +12,13 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/log2.h>
+#include <linux/module.h>
 
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-chip-ident.h>
-#include <media/soc_camera.h>
+#include <media/v4l2-ctrls.h>
 
 /*
  * mt9m001 i2c address 0x5d
@@ -84,15 +87,19 @@
 
 struct mt9m001 {
 	struct v4l2_subdev subdev;
+	struct v4l2_ctrl_handler hdl;
+	struct {
+		/* exposure/auto-exposure cluster */
+		struct v4l2_ctrl *autoexposure;
+		struct v4l2_ctrl *exposure;
+	};
 	struct v4l2_rect rect;	/* Sensor window */
 	const struct mt9m001_datafmt *fmt;
 	const struct mt9m001_datafmt *fmts;
 	int num_fmts;
 	int model;	/* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
-	unsigned int gain;
-	unsigned int exposure;
+	unsigned int total_h;
 	unsigned short y_skip_top;	/* Lines to skip at the top */
-	unsigned char autoexposure;
 };
 
 static struct mt9m001 *to_mt9m001(const struct i2c_client *client)
@@ -165,54 +172,13 @@
 	return 0;
 }
 
-static int mt9m001_set_bus_param(struct soc_camera_device *icd,
-				 unsigned long flags)
-{
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-	unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK;
-
-	/* Only one width bit may be set */
-	if (!is_power_of_2(width_flag))
-		return -EINVAL;
-
-	if (icl->set_bus_param)
-		return icl->set_bus_param(icl, width_flag);
-
-	/*
-	 * Without board specific bus width settings we only support the
-	 * sensors native bus width
-	 */
-	if (width_flag == SOCAM_DATAWIDTH_10)
-		return 0;
-
-	return -EINVAL;
-}
-
-static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
-{
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-	/* MT9M001 has all capture_format parameters fixed */
-	unsigned long flags = SOCAM_PCLK_SAMPLE_FALLING |
-		SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
-		SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER;
-
-	if (icl->query_bus_param)
-		flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK;
-	else
-		flags |= SOCAM_DATAWIDTH_10;
-
-	return soc_camera_apply_sensor_flags(icl, flags);
-}
-
 static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct mt9m001 *mt9m001 = to_mt9m001(client);
 	struct v4l2_rect rect = a->c;
-	struct soc_camera_device *icd = client->dev.platform_data;
 	int ret;
 	const u16 hblank = 9, vblank = 25;
-	unsigned int total_h;
 
 	if (mt9m001->fmts == mt9m001_colour_fmts)
 		/*
@@ -231,7 +197,7 @@
 	soc_camera_limit_side(&rect.top, &rect.height,
 		     MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT);
 
-	total_h = rect.height + mt9m001->y_skip_top + vblank;
+	mt9m001->total_h = rect.height + mt9m001->y_skip_top + vblank;
 
 	/* Blanking and start values - default... */
 	ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank);
@@ -240,7 +206,7 @@
 
 	/*
 	 * The caller provides a supported format, as verified per
-	 * call to icd->try_fmt()
+	 * call to .try_mbus_fmt()
 	 */
 	if (!ret)
 		ret = reg_write(client, MT9M001_COLUMN_START, rect.left);
@@ -251,17 +217,8 @@
 	if (!ret)
 		ret = reg_write(client, MT9M001_WINDOW_HEIGHT,
 				rect.height + mt9m001->y_skip_top - 1);
-	if (!ret && mt9m001->autoexposure) {
-		ret = reg_write(client, MT9M001_SHUTTER_WIDTH, total_h);
-		if (!ret) {
-			const struct v4l2_queryctrl *qctrl =
-				soc_camera_find_qctrl(icd->ops,
-						      V4L2_CID_EXPOSURE);
-			mt9m001->exposure = (524 + (total_h - 1) *
-				 (qctrl->maximum - qctrl->minimum)) /
-				1048 + qctrl->minimum;
-		}
-	}
+	if (!ret && v4l2_ctrl_g_ctrl(mt9m001->autoexposure) == V4L2_EXPOSURE_AUTO)
+		ret = reg_write(client, MT9M001_SHUTTER_WIDTH, mt9m001->total_h);
 
 	if (!ret)
 		mt9m001->rect = rect;
@@ -421,107 +378,48 @@
 }
 #endif
 
-static const struct v4l2_queryctrl mt9m001_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_GAIN,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Gain",
-		.minimum	= 0,
-		.maximum	= 127,
-		.step		= 1,
-		.default_value	= 64,
-		.flags		= V4L2_CTRL_FLAG_SLIDER,
-	}, {
-		.id		= V4L2_CID_EXPOSURE,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Exposure",
-		.minimum	= 1,
-		.maximum	= 255,
-		.step		= 1,
-		.default_value	= 255,
-		.flags		= V4L2_CTRL_FLAG_SLIDER,
-	}, {
-		.id		= V4L2_CID_EXPOSURE_AUTO,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Automatic Exposure",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 1,
-	}
-};
-
-static struct soc_camera_ops mt9m001_ops = {
-	.set_bus_param		= mt9m001_set_bus_param,
-	.query_bus_param	= mt9m001_query_bus_param,
-	.controls		= mt9m001_controls,
-	.num_controls		= ARRAY_SIZE(mt9m001_controls),
-};
-
-static int mt9m001_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9m001_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct mt9m001 *mt9m001 = to_mt9m001(client);
-	int data;
+	struct mt9m001 *mt9m001 = container_of(ctrl->handler,
+					       struct mt9m001, hdl);
+	s32 min, max;
 
 	switch (ctrl->id) {
-	case V4L2_CID_VFLIP:
-		data = reg_read(client, MT9M001_READ_OPTIONS2);
-		if (data < 0)
-			return -EIO;
-		ctrl->value = !!(data & 0x8000);
-		break;
 	case V4L2_CID_EXPOSURE_AUTO:
-		ctrl->value = mt9m001->autoexposure;
-		break;
-	case V4L2_CID_GAIN:
-		ctrl->value = mt9m001->gain;
-		break;
-	case V4L2_CID_EXPOSURE:
-		ctrl->value = mt9m001->exposure;
+		min = mt9m001->exposure->minimum;
+		max = mt9m001->exposure->maximum;
+		mt9m001->exposure->val =
+			(524 + (mt9m001->total_h - 1) * (max - min)) / 1048 + min;
 		break;
 	}
 	return 0;
 }
 
-static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct mt9m001 *mt9m001 = container_of(ctrl->handler,
+					       struct mt9m001, hdl);
+	struct v4l2_subdev *sd = &mt9m001->subdev;
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct mt9m001 *mt9m001 = to_mt9m001(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
-	const struct v4l2_queryctrl *qctrl;
+	struct v4l2_ctrl *exp = mt9m001->exposure;
 	int data;
 
-	qctrl = soc_camera_find_qctrl(&mt9m001_ops, ctrl->id);
-
-	if (!qctrl)
-		return -EINVAL;
-
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
-		if (ctrl->value)
+		if (ctrl->val)
 			data = reg_set(client, MT9M001_READ_OPTIONS2, 0x8000);
 		else
 			data = reg_clear(client, MT9M001_READ_OPTIONS2, 0x8000);
 		if (data < 0)
 			return -EIO;
-		break;
+		return 0;
+
 	case V4L2_CID_GAIN:
-		if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
-			return -EINVAL;
 		/* See Datasheet Table 7, Gain settings. */
-		if (ctrl->value <= qctrl->default_value) {
+		if (ctrl->val <= ctrl->default_value) {
 			/* Pack it into 0..1 step 0.125, register values 0..8 */
-			unsigned long range = qctrl->default_value - qctrl->minimum;
-			data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range;
+			unsigned long range = ctrl->default_value - ctrl->minimum;
+			data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
 
 			dev_dbg(&client->dev, "Setting gain %d\n", data);
 			data = reg_write(client, MT9M001_GLOBAL_GAIN, data);
@@ -530,8 +428,8 @@
 		} else {
 			/* Pack it into 1.125..15 variable step, register values 9..67 */
 			/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
-			unsigned long range = qctrl->maximum - qctrl->default_value - 1;
-			unsigned long gain = ((ctrl->value - qctrl->default_value - 1) *
+			unsigned long range = ctrl->maximum - ctrl->default_value - 1;
+			unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
 					       111 + range / 2) / range + 9;
 
 			if (gain <= 32)
@@ -547,66 +445,44 @@
 			if (data < 0)
 				return -EIO;
 		}
+		return 0;
 
-		/* Success */
-		mt9m001->gain = ctrl->value;
-		break;
-	case V4L2_CID_EXPOSURE:
-		/* mt9m001 has maximum == default */
-		if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
-			return -EINVAL;
-		else {
-			unsigned long range = qctrl->maximum - qctrl->minimum;
-			unsigned long shutter = ((ctrl->value - qctrl->minimum) * 1048 +
+	case V4L2_CID_EXPOSURE_AUTO:
+		if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
+			unsigned long range = exp->maximum - exp->minimum;
+			unsigned long shutter = ((exp->val - exp->minimum) * 1048 +
 						 range / 2) / range + 1;
 
 			dev_dbg(&client->dev,
 				"Setting shutter width from %d to %lu\n",
-				reg_read(client, MT9M001_SHUTTER_WIDTH),
-				shutter);
+				reg_read(client, MT9M001_SHUTTER_WIDTH), shutter);
 			if (reg_write(client, MT9M001_SHUTTER_WIDTH, shutter) < 0)
 				return -EIO;
-			mt9m001->exposure = ctrl->value;
-			mt9m001->autoexposure = 0;
-		}
-		break;
-	case V4L2_CID_EXPOSURE_AUTO:
-		if (ctrl->value) {
+		} else {
 			const u16 vblank = 25;
-			unsigned int total_h = mt9m001->rect.height +
+
+			mt9m001->total_h = mt9m001->rect.height +
 				mt9m001->y_skip_top + vblank;
-			if (reg_write(client, MT9M001_SHUTTER_WIDTH,
-				      total_h) < 0)
+			if (reg_write(client, MT9M001_SHUTTER_WIDTH, mt9m001->total_h) < 0)
 				return -EIO;
-			qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
-			mt9m001->exposure = (524 + (total_h - 1) *
-				 (qctrl->maximum - qctrl->minimum)) /
-				1048 + qctrl->minimum;
-			mt9m001->autoexposure = 1;
-		} else
-			mt9m001->autoexposure = 0;
-		break;
+		}
+		return 0;
 	}
-	return 0;
+	return -EINVAL;
 }
 
 /*
  * Interface active, can use i2c. If it fails, it can indeed mean, that
  * this wasn't our capture interface, so, we wait for the right one
  */
-static int mt9m001_video_probe(struct soc_camera_device *icd,
+static int mt9m001_video_probe(struct soc_camera_link *icl,
 			       struct i2c_client *client)
 {
 	struct mt9m001 *mt9m001 = to_mt9m001(client);
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
 	s32 data;
 	unsigned long flags;
 	int ret;
 
-	/* We must have a parent by now. And it cannot be a wrong one. */
-	BUG_ON(!icd->parent ||
-	       to_soc_camera_host(icd->parent)->nr != icd->iface);
-
 	/* Enable the chip */
 	data = reg_write(client, MT9M001_CHIP_ENABLE, 1);
 	dev_dbg(&client->dev, "write: %d\n", data);
@@ -661,18 +537,11 @@
 		dev_err(&client->dev, "Failed to initialise the camera\n");
 
 	/* mt9m001_init() has reset the chip, returning registers to defaults */
-	mt9m001->gain = 64;
-	mt9m001->exposure = 255;
-
-	return ret;
+	return v4l2_ctrl_handler_setup(&mt9m001->hdl);
 }
 
-static void mt9m001_video_remove(struct soc_camera_device *icd)
+static void mt9m001_video_remove(struct soc_camera_link *icl)
 {
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-
-	dev_dbg(icd->pdev, "Video removed: %p, %p\n",
-		icd->parent, icd->vdev);
 	if (icl->free_bus)
 		icl->free_bus(icl);
 }
@@ -687,9 +556,12 @@
 	return 0;
 }
 
+static const struct v4l2_ctrl_ops mt9m001_ctrl_ops = {
+	.g_volatile_ctrl = mt9m001_g_volatile_ctrl,
+	.s_ctrl = mt9m001_s_ctrl,
+};
+
 static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
-	.g_ctrl		= mt9m001_g_ctrl,
-	.s_ctrl		= mt9m001_s_ctrl,
 	.g_chip_ident	= mt9m001_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register	= mt9m001_g_register,
@@ -710,6 +582,40 @@
 	return 0;
 }
 
+static int mt9m001_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	/* MT9M001 has all capture_format parameters fixed */
+	cfg->flags = V4L2_MBUS_PCLK_SAMPLE_FALLING |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_DATA_ACTIVE_HIGH | V4L2_MBUS_MASTER;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static int mt9m001_s_mbus_config(struct v4l2_subdev *sd,
+				const struct v4l2_mbus_config *cfg)
+{
+	const struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	struct mt9m001 *mt9m001 = to_mt9m001(client);
+	unsigned int bps = soc_mbus_get_fmtdesc(mt9m001->fmt->code)->bits_per_sample;
+
+	if (icl->set_bus_param)
+		return icl->set_bus_param(icl, 1 << (bps - 1));
+
+	/*
+	 * Without board specific bus width settings we only support the
+	 * sensors native bus width
+	 */
+	return bps == 10 ? 0 : -EINVAL;
+}
+
 static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
 	.s_stream	= mt9m001_s_stream,
 	.s_mbus_fmt	= mt9m001_s_fmt,
@@ -719,6 +625,8 @@
 	.g_crop		= mt9m001_g_crop,
 	.cropcap	= mt9m001_cropcap,
 	.enum_mbus_fmt	= mt9m001_enum_fmt,
+	.g_mbus_config	= mt9m001_g_mbus_config,
+	.s_mbus_config	= mt9m001_s_mbus_config,
 };
 
 static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = {
@@ -735,17 +643,10 @@
 			 const struct i2c_device_id *did)
 {
 	struct mt9m001 *mt9m001;
-	struct soc_camera_device *icd = client->dev.platform_data;
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-	struct soc_camera_link *icl;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 	int ret;
 
-	if (!icd) {
-		dev_err(&client->dev, "MT9M001: missing soc-camera data!\n");
-		return -EINVAL;
-	}
-
-	icl = to_soc_camera_link(icd);
 	if (!icl) {
 		dev_err(&client->dev, "MT9M001 driver needs platform data\n");
 		return -EINVAL;
@@ -762,25 +663,40 @@
 		return -ENOMEM;
 
 	v4l2_i2c_subdev_init(&mt9m001->subdev, client, &mt9m001_subdev_ops);
+	v4l2_ctrl_handler_init(&mt9m001->hdl, 4);
+	v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops,
+			V4L2_CID_GAIN, 0, 127, 1, 64);
+	mt9m001->exposure = v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops,
+			V4L2_CID_EXPOSURE, 1, 255, 1, 255);
+	/*
+	 * Simulated autoexposure. If enabled, we calculate shutter width
+	 * ourselves in the driver based on vertical blanking and frame width
+	 */
+	mt9m001->autoexposure = v4l2_ctrl_new_std_menu(&mt9m001->hdl,
+			&mt9m001_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
+			V4L2_EXPOSURE_AUTO);
+	mt9m001->subdev.ctrl_handler = &mt9m001->hdl;
+	if (mt9m001->hdl.error) {
+		int err = mt9m001->hdl.error;
 
-	/* Second stage probe - when a capture adapter is there */
-	icd->ops		= &mt9m001_ops;
+		kfree(mt9m001);
+		return err;
+	}
+	v4l2_ctrl_auto_cluster(2, &mt9m001->autoexposure,
+					V4L2_EXPOSURE_MANUAL, true);
 
+	/* Second stage probe - when a capture adapter is there */
 	mt9m001->y_skip_top	= 0;
 	mt9m001->rect.left	= MT9M001_COLUMN_SKIP;
 	mt9m001->rect.top	= MT9M001_ROW_SKIP;
 	mt9m001->rect.width	= MT9M001_MAX_WIDTH;
 	mt9m001->rect.height	= MT9M001_MAX_HEIGHT;
 
-	/*
-	 * Simulated autoexposure. If enabled, we calculate shutter width
-	 * ourselves in the driver based on vertical blanking and frame width
-	 */
-	mt9m001->autoexposure = 1;
-
-	ret = mt9m001_video_probe(icd, client);
+	ret = mt9m001_video_probe(icl, client);
 	if (ret) {
-		icd->ops = NULL;
+		v4l2_ctrl_handler_free(&mt9m001->hdl);
 		kfree(mt9m001);
 	}
 
@@ -790,10 +706,11 @@
 static int mt9m001_remove(struct i2c_client *client)
 {
 	struct mt9m001 *mt9m001 = to_mt9m001(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 
-	icd->ops = NULL;
-	mt9m001_video_remove(icd);
+	v4l2_device_unregister_subdev(&mt9m001->subdev);
+	v4l2_ctrl_handler_free(&mt9m001->hdl);
+	mt9m001_video_remove(icl);
 	kfree(mt9m001);
 
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/media/video/mt9m111.c linux-libre-3.2-gnu/drivers/media/video/mt9m111.c
--- linux-libre-3.1-gnu/drivers/media/video/mt9m111.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/mt9m111.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,10 +13,13 @@
 #include <linux/log2.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/module.h>
 
+#include <media/soc_camera.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
 #include <media/v4l2-chip-ident.h>
-#include <media/soc_camera.h>
 
 /*
  * MT9M111, MT9M112 and MT9M131:
@@ -177,6 +180,8 @@
 
 struct mt9m111 {
 	struct v4l2_subdev subdev;
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *gain;
 	int model;	/* V4L2_IDENT_MT9M111 or V4L2_IDENT_MT9M112 code
 			 * from v4l2-chip-ident.h */
 	enum mt9m111_context context;
@@ -184,13 +189,9 @@
 	struct mutex power_lock; /* lock to protect power_count */
 	int power_count;
 	const struct mt9m111_datafmt *fmt;
-	unsigned int gain;
-	unsigned char autoexposure;
+	int lastpage;	/* PageMap cache value */
 	unsigned char datawidth;
 	unsigned int powered:1;
-	unsigned int hflip:1;
-	unsigned int vflip:1;
-	unsigned int autowhitebalance:1;
 };
 
 static struct mt9m111 *to_mt9m111(const struct i2c_client *client)
@@ -202,17 +203,17 @@
 {
 	int ret;
 	u16 page;
-	static int lastpage = -1;	/* PageMap cache value */
+	struct mt9m111 *mt9m111 = to_mt9m111(client);
 
 	page = (reg >> 8);
-	if (page == lastpage)
+	if (page == mt9m111->lastpage)
 		return 0;
 	if (page > 2)
 		return -EINVAL;
 
 	ret = i2c_smbus_write_word_data(client, MT9M111_PAGE_MAP, swab16(page));
 	if (!ret)
-		lastpage = page;
+		mt9m111->lastpage = page;
 	return ret;
 }
 
@@ -362,21 +363,6 @@
 	return ret;
 }
 
-static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd)
-{
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-	unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |
-		SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
-		SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
-
-	return soc_camera_apply_sensor_flags(icl, flags);
-}
-
-static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
-{
-	return 0;
-}
-
 static int mt9m111_make_rect(struct mt9m111 *mt9m111,
 			     struct v4l2_rect *rect)
 {
@@ -659,50 +645,6 @@
 }
 #endif
 
-static const struct v4l2_queryctrl mt9m111_controls[] = {
-	{
-		.id		= V4L2_CID_VFLIP,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Flip Verticaly",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 0,
-	}, {
-		.id		= V4L2_CID_HFLIP,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Flip Horizontaly",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 0,
-	}, {	/* gain = 1/32*val (=>gain=1 if val==32) */
-		.id		= V4L2_CID_GAIN,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Gain",
-		.minimum	= 0,
-		.maximum	= 63 * 2 * 2,
-		.step		= 1,
-		.default_value	= 32,
-		.flags		= V4L2_CTRL_FLAG_SLIDER,
-	}, {
-		.id		= V4L2_CID_EXPOSURE_AUTO,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Auto Exposure",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 1,
-	}
-};
-
-static struct soc_camera_ops mt9m111_ops = {
-	.query_bus_param	= mt9m111_query_bus_param,
-	.set_bus_param		= mt9m111_set_bus_param,
-	.controls		= mt9m111_controls,
-	.num_controls		= ARRAY_SIZE(mt9m111_controls),
-};
-
 static int mt9m111_set_flip(struct mt9m111 *mt9m111, int flip, int mask)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
@@ -743,7 +685,6 @@
 	if (gain > 63 * 2 * 2)
 		return -EINVAL;
 
-	mt9m111->gain = gain;
 	if ((gain >= 64 * 2) && (gain < 63 * 2 * 2))
 		val = (1 << 10) | (1 << 9) | (gain / 4);
 	else if ((gain >= 64) && (gain < 64 * 2))
@@ -757,118 +698,47 @@
 static int mt9m111_set_autoexposure(struct mt9m111 *mt9m111, int on)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
-	int ret;
 
 	if (on)
-		ret = reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
-	else
-		ret = reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
-
-	if (!ret)
-		mt9m111->autoexposure = on;
-
-	return ret;
+		return reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
+	return reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
 }
 
 static int mt9m111_set_autowhitebalance(struct mt9m111 *mt9m111, int on)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
-	int ret;
 
 	if (on)
-		ret = reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);
-	else
-		ret = reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);
-
-	if (!ret)
-		mt9m111->autowhitebalance = on;
-
-	return ret;
-}
-
-static int mt9m111_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
-	int data;
-
-	switch (ctrl->id) {
-	case V4L2_CID_VFLIP:
-		if (mt9m111->context == HIGHPOWER)
-			data = reg_read(READ_MODE_B);
-		else
-			data = reg_read(READ_MODE_A);
-
-		if (data < 0)
-			return -EIO;
-		ctrl->value = !!(data & MT9M111_RMB_MIRROR_ROWS);
-		break;
-	case V4L2_CID_HFLIP:
-		if (mt9m111->context == HIGHPOWER)
-			data = reg_read(READ_MODE_B);
-		else
-			data = reg_read(READ_MODE_A);
-
-		if (data < 0)
-			return -EIO;
-		ctrl->value = !!(data & MT9M111_RMB_MIRROR_COLS);
-		break;
-	case V4L2_CID_GAIN:
-		data = mt9m111_get_global_gain(mt9m111);
-		if (data < 0)
-			return data;
-		ctrl->value = data;
-		break;
-	case V4L2_CID_EXPOSURE_AUTO:
-		ctrl->value = mt9m111->autoexposure;
-		break;
-	case V4L2_CID_AUTO_WHITE_BALANCE:
-		ctrl->value = mt9m111->autowhitebalance;
-		break;
-	}
-	return 0;
+		return reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);
+	return reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);
 }
 
-static int mt9m111_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
-	const struct v4l2_queryctrl *qctrl;
-	int ret;
-
-	qctrl = soc_camera_find_qctrl(&mt9m111_ops, ctrl->id);
-	if (!qctrl)
-		return -EINVAL;
+	struct mt9m111 *mt9m111 = container_of(ctrl->handler,
+					       struct mt9m111, hdl);
 
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
-		mt9m111->vflip = ctrl->value;
-		ret = mt9m111_set_flip(mt9m111, ctrl->value,
+		return mt9m111_set_flip(mt9m111, ctrl->val,
 					MT9M111_RMB_MIRROR_ROWS);
-		break;
 	case V4L2_CID_HFLIP:
-		mt9m111->hflip = ctrl->value;
-		ret = mt9m111_set_flip(mt9m111, ctrl->value,
+		return mt9m111_set_flip(mt9m111, ctrl->val,
 					MT9M111_RMB_MIRROR_COLS);
-		break;
 	case V4L2_CID_GAIN:
-		ret = mt9m111_set_global_gain(mt9m111, ctrl->value);
-		break;
+		return mt9m111_set_global_gain(mt9m111, ctrl->val);
 	case V4L2_CID_EXPOSURE_AUTO:
-		ret =  mt9m111_set_autoexposure(mt9m111, ctrl->value);
-		break;
+		return mt9m111_set_autoexposure(mt9m111, ctrl->val);
 	case V4L2_CID_AUTO_WHITE_BALANCE:
-		ret =  mt9m111_set_autowhitebalance(mt9m111, ctrl->value);
-		break;
-	default:
-		ret = -EINVAL;
+		return mt9m111_set_autowhitebalance(mt9m111, ctrl->val);
 	}
 
-	return ret;
+	return -EINVAL;
 }
 
 static int mt9m111_suspend(struct mt9m111 *mt9m111)
 {
-	mt9m111->gain = mt9m111_get_global_gain(mt9m111);
+	v4l2_ctrl_s_ctrl(mt9m111->gain, mt9m111_get_global_gain(mt9m111));
 
 	return 0;
 }
@@ -878,11 +748,7 @@
 	mt9m111_set_context(mt9m111, mt9m111->context);
 	mt9m111_set_pixfmt(mt9m111, mt9m111->fmt->code);
 	mt9m111_setup_rect(mt9m111, &mt9m111->rect);
-	mt9m111_set_flip(mt9m111, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS);
-	mt9m111_set_flip(mt9m111, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS);
-	mt9m111_set_global_gain(mt9m111, mt9m111->gain);
-	mt9m111_set_autoexposure(mt9m111, mt9m111->autoexposure);
-	mt9m111_set_autowhitebalance(mt9m111, mt9m111->autowhitebalance);
+	v4l2_ctrl_handler_setup(&mt9m111->hdl);
 }
 
 static int mt9m111_resume(struct mt9m111 *mt9m111)
@@ -910,8 +776,6 @@
 		ret = mt9m111_reset(mt9m111);
 	if (!ret)
 		ret = mt9m111_set_context(mt9m111, mt9m111->context);
-	if (!ret)
-		ret = mt9m111_set_autoexposure(mt9m111, mt9m111->autoexposure);
 	if (ret)
 		dev_err(&client->dev, "mt9m111 init failed: %d\n", ret);
 	return ret;
@@ -921,20 +785,12 @@
  * Interface active, can use i2c. If it fails, it can indeed mean, that
  * this wasn't our capture interface, so, we wait for the right one
  */
-static int mt9m111_video_probe(struct soc_camera_device *icd,
-			       struct i2c_client *client)
+static int mt9m111_video_probe(struct i2c_client *client)
 {
 	struct mt9m111 *mt9m111 = to_mt9m111(client);
 	s32 data;
 	int ret;
 
-	/* We must have a parent by now. And it cannot be a wrong one. */
-	BUG_ON(!icd->parent ||
-	       to_soc_camera_host(icd->parent)->nr != icd->iface);
-
-	mt9m111->autoexposure = 1;
-	mt9m111->autowhitebalance = 1;
-
 	data = reg_read(CHIP_VERSION);
 
 	switch (data) {
@@ -948,17 +804,16 @@
 		dev_info(&client->dev, "Detected a MT9M112 chip ID %x\n", data);
 		break;
 	default:
-		ret = -ENODEV;
 		dev_err(&client->dev,
 			"No MT9M111/MT9M112/MT9M131 chip detected register read %x\n",
 			data);
-		goto ei2c;
+		return -ENODEV;
 	}
 
 	ret = mt9m111_init(mt9m111);
-
-ei2c:
-	return ret;
+	if (ret)
+		return ret;
+	return v4l2_ctrl_handler_setup(&mt9m111->hdl);
 }
 
 static int mt9m111_s_power(struct v4l2_subdev *sd, int on)
@@ -995,9 +850,11 @@
 	return ret;
 }
 
+static const struct v4l2_ctrl_ops mt9m111_ctrl_ops = {
+	.s_ctrl = mt9m111_s_ctrl,
+};
+
 static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = {
-	.g_ctrl		= mt9m111_g_ctrl,
-	.s_ctrl		= mt9m111_s_ctrl,
 	.g_chip_ident	= mt9m111_g_chip_ident,
 	.s_power	= mt9m111_s_power,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -1016,6 +873,21 @@
 	return 0;
 }
 
+static int mt9m111_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
 static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
 	.s_mbus_fmt	= mt9m111_s_fmt,
 	.g_mbus_fmt	= mt9m111_g_fmt,
@@ -1024,6 +896,7 @@
 	.g_crop		= mt9m111_g_crop,
 	.cropcap	= mt9m111_cropcap,
 	.enum_mbus_fmt	= mt9m111_enum_fmt,
+	.g_mbus_config	= mt9m111_g_mbus_config,
 };
 
 static struct v4l2_subdev_ops mt9m111_subdev_ops = {
@@ -1035,17 +908,10 @@
 			 const struct i2c_device_id *did)
 {
 	struct mt9m111 *mt9m111;
-	struct soc_camera_device *icd = client->dev.platform_data;
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-	struct soc_camera_link *icl;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 	int ret;
 
-	if (!icd) {
-		dev_err(&client->dev, "mt9m111: soc-camera data missing!\n");
-		return -EINVAL;
-	}
-
-	icl = to_soc_camera_link(icd);
 	if (!icl) {
 		dev_err(&client->dev, "mt9m111: driver needs platform data\n");
 		return -EINVAL;
@@ -1062,19 +928,38 @@
 		return -ENOMEM;
 
 	v4l2_i2c_subdev_init(&mt9m111->subdev, client, &mt9m111_subdev_ops);
+	v4l2_ctrl_handler_init(&mt9m111->hdl, 5);
+	v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
+			V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
+	mt9m111->gain = v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
+			V4L2_CID_GAIN, 0, 63 * 2 * 2, 1, 32);
+	v4l2_ctrl_new_std_menu(&mt9m111->hdl,
+			&mt9m111_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
+			V4L2_EXPOSURE_AUTO);
+	mt9m111->subdev.ctrl_handler = &mt9m111->hdl;
+	if (mt9m111->hdl.error) {
+		int err = mt9m111->hdl.error;
 
-	/* Second stage probe - when a capture adapter is there */
-	icd->ops		= &mt9m111_ops;
+		kfree(mt9m111);
+		return err;
+	}
 
+	/* Second stage probe - when a capture adapter is there */
 	mt9m111->rect.left	= MT9M111_MIN_DARK_COLS;
 	mt9m111->rect.top	= MT9M111_MIN_DARK_ROWS;
 	mt9m111->rect.width	= MT9M111_MAX_WIDTH;
 	mt9m111->rect.height	= MT9M111_MAX_HEIGHT;
 	mt9m111->fmt		= &mt9m111_colour_fmts[0];
+	mt9m111->lastpage	= -1;
+	mutex_init(&mt9m111->power_lock);
 
-	ret = mt9m111_video_probe(icd, client);
+	ret = mt9m111_video_probe(client);
 	if (ret) {
-		icd->ops = NULL;
+		v4l2_ctrl_handler_free(&mt9m111->hdl);
 		kfree(mt9m111);
 	}
 
@@ -1084,9 +969,9 @@
 static int mt9m111_remove(struct i2c_client *client)
 {
 	struct mt9m111 *mt9m111 = to_mt9m111(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
 
-	icd->ops = NULL;
+	v4l2_device_unregister_subdev(&mt9m111->subdev);
+	v4l2_ctrl_handler_free(&mt9m111->hdl);
 	kfree(mt9m111);
 
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/media/video/mt9p031.c linux-libre-3.2-gnu/drivers/media/video/mt9p031.c
--- linux-libre-3.1-gnu/drivers/media/video/mt9p031.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/mt9p031.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,964 @@
+/*
+ * Driver for MT9P031 CMOS Image Sensor from Aptina
+ *
+ * Copyright (C) 2011, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ * Copyright (C) 2011, Javier Martin <javier.martin@vista-silicon.com>
+ * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * Based on the MT9V032 driver and Bastian Hecht's code.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <media/v4l2-subdev.h>
+#include <linux/videodev2.h>
+
+#include <media/mt9p031.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#define MT9P031_PIXEL_ARRAY_WIDTH			2752
+#define MT9P031_PIXEL_ARRAY_HEIGHT			2004
+
+#define MT9P031_CHIP_VERSION				0x00
+#define		MT9P031_CHIP_VERSION_VALUE		0x1801
+#define MT9P031_ROW_START				0x01
+#define		MT9P031_ROW_START_MIN			0
+#define		MT9P031_ROW_START_MAX			2004
+#define		MT9P031_ROW_START_DEF			54
+#define MT9P031_COLUMN_START				0x02
+#define		MT9P031_COLUMN_START_MIN		0
+#define		MT9P031_COLUMN_START_MAX		2750
+#define		MT9P031_COLUMN_START_DEF		16
+#define MT9P031_WINDOW_HEIGHT				0x03
+#define		MT9P031_WINDOW_HEIGHT_MIN		2
+#define		MT9P031_WINDOW_HEIGHT_MAX		2006
+#define		MT9P031_WINDOW_HEIGHT_DEF		1944
+#define MT9P031_WINDOW_WIDTH				0x04
+#define		MT9P031_WINDOW_WIDTH_MIN		2
+#define		MT9P031_WINDOW_WIDTH_MAX		2752
+#define		MT9P031_WINDOW_WIDTH_DEF		2592
+#define MT9P031_HORIZONTAL_BLANK			0x05
+#define		MT9P031_HORIZONTAL_BLANK_MIN		0
+#define		MT9P031_HORIZONTAL_BLANK_MAX		4095
+#define MT9P031_VERTICAL_BLANK				0x06
+#define		MT9P031_VERTICAL_BLANK_MIN		0
+#define		MT9P031_VERTICAL_BLANK_MAX		4095
+#define		MT9P031_VERTICAL_BLANK_DEF		25
+#define MT9P031_OUTPUT_CONTROL				0x07
+#define		MT9P031_OUTPUT_CONTROL_CEN		2
+#define		MT9P031_OUTPUT_CONTROL_SYN		1
+#define		MT9P031_OUTPUT_CONTROL_DEF		0x1f82
+#define MT9P031_SHUTTER_WIDTH_UPPER			0x08
+#define MT9P031_SHUTTER_WIDTH_LOWER			0x09
+#define		MT9P031_SHUTTER_WIDTH_MIN		1
+#define		MT9P031_SHUTTER_WIDTH_MAX		1048575
+#define		MT9P031_SHUTTER_WIDTH_DEF		1943
+#define	MT9P031_PLL_CONTROL				0x10
+#define		MT9P031_PLL_CONTROL_PWROFF		0x0050
+#define		MT9P031_PLL_CONTROL_PWRON		0x0051
+#define		MT9P031_PLL_CONTROL_USEPLL		0x0052
+#define	MT9P031_PLL_CONFIG_1				0x11
+#define	MT9P031_PLL_CONFIG_2				0x12
+#define MT9P031_PIXEL_CLOCK_CONTROL			0x0a
+#define MT9P031_FRAME_RESTART				0x0b
+#define MT9P031_SHUTTER_DELAY				0x0c
+#define MT9P031_RST					0x0d
+#define		MT9P031_RST_ENABLE			1
+#define		MT9P031_RST_DISABLE			0
+#define MT9P031_READ_MODE_1				0x1e
+#define MT9P031_READ_MODE_2				0x20
+#define		MT9P031_READ_MODE_2_ROW_MIR		(1 << 15)
+#define		MT9P031_READ_MODE_2_COL_MIR		(1 << 14)
+#define		MT9P031_READ_MODE_2_ROW_BLC		(1 << 6)
+#define MT9P031_ROW_ADDRESS_MODE			0x22
+#define MT9P031_COLUMN_ADDRESS_MODE			0x23
+#define MT9P031_GLOBAL_GAIN				0x35
+#define		MT9P031_GLOBAL_GAIN_MIN			8
+#define		MT9P031_GLOBAL_GAIN_MAX			1024
+#define		MT9P031_GLOBAL_GAIN_DEF			8
+#define		MT9P031_GLOBAL_GAIN_MULT		(1 << 6)
+#define MT9P031_ROW_BLACK_DEF_OFFSET			0x4b
+#define MT9P031_TEST_PATTERN				0xa0
+#define		MT9P031_TEST_PATTERN_SHIFT		3
+#define		MT9P031_TEST_PATTERN_ENABLE		(1 << 0)
+#define		MT9P031_TEST_PATTERN_DISABLE		(0 << 0)
+#define MT9P031_TEST_PATTERN_GREEN			0xa1
+#define MT9P031_TEST_PATTERN_RED			0xa2
+#define MT9P031_TEST_PATTERN_BLUE			0xa3
+
+struct mt9p031_pll_divs {
+	u32 ext_freq;
+	u32 target_freq;
+	u8 m;
+	u8 n;
+	u8 p1;
+};
+
+struct mt9p031 {
+	struct v4l2_subdev subdev;
+	struct media_pad pad;
+	struct v4l2_rect crop;  /* Sensor window */
+	struct v4l2_mbus_framefmt format;
+	struct v4l2_ctrl_handler ctrls;
+	struct mt9p031_platform_data *pdata;
+	struct mutex power_lock; /* lock to protect power_count */
+	int power_count;
+	u16 xskip;
+	u16 yskip;
+
+	const struct mt9p031_pll_divs *pll;
+
+	/* Registers cache */
+	u16 output_control;
+	u16 mode2;
+};
+
+static struct mt9p031 *to_mt9p031(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct mt9p031, subdev);
+}
+
+static int mt9p031_read(struct i2c_client *client, u8 reg)
+{
+	s32 data = i2c_smbus_read_word_data(client, reg);
+	return data < 0 ? data : be16_to_cpu(data);
+}
+
+static int mt9p031_write(struct i2c_client *client, u8 reg, u16 data)
+{
+	return i2c_smbus_write_word_data(client, reg, cpu_to_be16(data));
+}
+
+static int mt9p031_set_output_control(struct mt9p031 *mt9p031, u16 clear,
+				      u16 set)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	u16 value = (mt9p031->output_control & ~clear) | set;
+	int ret;
+
+	ret = mt9p031_write(client, MT9P031_OUTPUT_CONTROL, value);
+	if (ret < 0)
+		return ret;
+
+	mt9p031->output_control = value;
+	return 0;
+}
+
+static int mt9p031_set_mode2(struct mt9p031 *mt9p031, u16 clear, u16 set)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	u16 value = (mt9p031->mode2 & ~clear) | set;
+	int ret;
+
+	ret = mt9p031_write(client, MT9P031_READ_MODE_2, value);
+	if (ret < 0)
+		return ret;
+
+	mt9p031->mode2 = value;
+	return 0;
+}
+
+static int mt9p031_reset(struct mt9p031 *mt9p031)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	int ret;
+
+	/* Disable chip output, synchronous option update */
+	ret = mt9p031_write(client, MT9P031_RST, MT9P031_RST_ENABLE);
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_RST, MT9P031_RST_DISABLE);
+	if (ret < 0)
+		return ret;
+
+	return mt9p031_set_output_control(mt9p031, MT9P031_OUTPUT_CONTROL_CEN,
+					  0);
+}
+
+/*
+ * This static table uses ext_freq and vdd_io values to select suitable
+ * PLL dividers m, n and p1 which have been calculated as specifiec in p36
+ * of Aptina's mt9p031 datasheet. New values should be added here.
+ */
+static const struct mt9p031_pll_divs mt9p031_divs[] = {
+	/* ext_freq	target_freq	m	n	p1 */
+	{21000000,	48000000,	26,	2,	6}
+};
+
+static int mt9p031_pll_get_divs(struct mt9p031 *mt9p031)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mt9p031_divs); i++) {
+		if (mt9p031_divs[i].ext_freq == mt9p031->pdata->ext_freq &&
+		  mt9p031_divs[i].target_freq == mt9p031->pdata->target_freq) {
+			mt9p031->pll = &mt9p031_divs[i];
+			return 0;
+		}
+	}
+
+	dev_err(&client->dev, "Couldn't find PLL dividers for ext_freq = %d, "
+		"target_freq = %d\n", mt9p031->pdata->ext_freq,
+		mt9p031->pdata->target_freq);
+	return -EINVAL;
+}
+
+static int mt9p031_pll_enable(struct mt9p031 *mt9p031)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	int ret;
+
+	ret = mt9p031_write(client, MT9P031_PLL_CONTROL,
+			    MT9P031_PLL_CONTROL_PWRON);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9p031_write(client, MT9P031_PLL_CONFIG_1,
+			    (mt9p031->pll->m << 8) | (mt9p031->pll->n - 1));
+	if (ret < 0)
+		return ret;
+
+	ret = mt9p031_write(client, MT9P031_PLL_CONFIG_2, mt9p031->pll->p1 - 1);
+	if (ret < 0)
+		return ret;
+
+	usleep_range(1000, 2000);
+	ret = mt9p031_write(client, MT9P031_PLL_CONTROL,
+			    MT9P031_PLL_CONTROL_PWRON |
+			    MT9P031_PLL_CONTROL_USEPLL);
+	return ret;
+}
+
+static inline int mt9p031_pll_disable(struct mt9p031 *mt9p031)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+
+	return mt9p031_write(client, MT9P031_PLL_CONTROL,
+			     MT9P031_PLL_CONTROL_PWROFF);
+}
+
+static int mt9p031_power_on(struct mt9p031 *mt9p031)
+{
+	/* Ensure RESET_BAR is low */
+	if (mt9p031->pdata->reset) {
+		mt9p031->pdata->reset(&mt9p031->subdev, 1);
+		usleep_range(1000, 2000);
+	}
+
+	/* Emable clock */
+	if (mt9p031->pdata->set_xclk)
+		mt9p031->pdata->set_xclk(&mt9p031->subdev,
+					 mt9p031->pdata->ext_freq);
+
+	/* Now RESET_BAR must be high */
+	if (mt9p031->pdata->reset) {
+		mt9p031->pdata->reset(&mt9p031->subdev, 0);
+		usleep_range(1000, 2000);
+	}
+
+	return 0;
+}
+
+static void mt9p031_power_off(struct mt9p031 *mt9p031)
+{
+	if (mt9p031->pdata->reset) {
+		mt9p031->pdata->reset(&mt9p031->subdev, 1);
+		usleep_range(1000, 2000);
+	}
+
+	if (mt9p031->pdata->set_xclk)
+		mt9p031->pdata->set_xclk(&mt9p031->subdev, 0);
+}
+
+static int __mt9p031_set_power(struct mt9p031 *mt9p031, bool on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	int ret;
+
+	if (!on) {
+		mt9p031_power_off(mt9p031);
+		return 0;
+	}
+
+	ret = mt9p031_power_on(mt9p031);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9p031_reset(mt9p031);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to reset the camera\n");
+		return ret;
+	}
+
+	return v4l2_ctrl_handler_setup(&mt9p031->ctrls);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev video operations
+ */
+
+static int mt9p031_set_params(struct mt9p031 *mt9p031)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	struct v4l2_mbus_framefmt *format = &mt9p031->format;
+	const struct v4l2_rect *crop = &mt9p031->crop;
+	unsigned int hblank;
+	unsigned int vblank;
+	unsigned int xskip;
+	unsigned int yskip;
+	unsigned int xbin;
+	unsigned int ybin;
+	int ret;
+
+	/* Windows position and size.
+	 *
+	 * TODO: Make sure the start coordinates and window size match the
+	 * skipping, binning and mirroring (see description of registers 2 and 4
+	 * in table 13, and Binning section on page 41).
+	 */
+	ret = mt9p031_write(client, MT9P031_COLUMN_START, crop->left);
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_ROW_START, crop->top);
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_WINDOW_WIDTH, crop->width - 1);
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_WINDOW_HEIGHT, crop->height - 1);
+	if (ret < 0)
+		return ret;
+
+	/* Row and column binning and skipping. Use the maximum binning value
+	 * compatible with the skipping settings.
+	 */
+	xskip = DIV_ROUND_CLOSEST(crop->width, format->width);
+	yskip = DIV_ROUND_CLOSEST(crop->height, format->height);
+	xbin = 1 << (ffs(xskip) - 1);
+	ybin = 1 << (ffs(yskip) - 1);
+
+	ret = mt9p031_write(client, MT9P031_COLUMN_ADDRESS_MODE,
+			    ((xbin - 1) << 4) | (xskip - 1));
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_ROW_ADDRESS_MODE,
+			    ((ybin - 1) << 4) | (yskip - 1));
+	if (ret < 0)
+		return ret;
+
+	/* Blanking - use minimum value for horizontal blanking and default
+	 * value for vertical blanking.
+	 */
+	hblank = 346 * ybin + 64 + (80 >> max_t(unsigned int, xbin, 3));
+	vblank = MT9P031_VERTICAL_BLANK_DEF;
+
+	ret = mt9p031_write(client, MT9P031_HORIZONTAL_BLANK, hblank);
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_VERTICAL_BLANK, vblank);
+	if (ret < 0)
+		return ret;
+
+	return ret;
+}
+
+static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	int ret;
+
+	if (!enable) {
+		/* Stop sensor readout */
+		ret = mt9p031_set_output_control(mt9p031,
+						 MT9P031_OUTPUT_CONTROL_CEN, 0);
+		if (ret < 0)
+			return ret;
+
+		return mt9p031_pll_disable(mt9p031);
+	}
+
+	ret = mt9p031_set_params(mt9p031);
+	if (ret < 0)
+		return ret;
+
+	/* Switch to master "normal" mode */
+	ret = mt9p031_set_output_control(mt9p031, 0,
+					 MT9P031_OUTPUT_CONTROL_CEN);
+	if (ret < 0)
+		return ret;
+
+	return mt9p031_pll_enable(mt9p031);
+}
+
+static int mt9p031_enum_mbus_code(struct v4l2_subdev *subdev,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+	if (code->pad || code->index)
+		return -EINVAL;
+
+	code->code = mt9p031->format.code;
+	return 0;
+}
+
+static int mt9p031_enum_frame_size(struct v4l2_subdev *subdev,
+				   struct v4l2_subdev_fh *fh,
+				   struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+	if (fse->index >= 8 || fse->code != mt9p031->format.code)
+		return -EINVAL;
+
+	fse->min_width = MT9P031_WINDOW_WIDTH_DEF
+		       / min_t(unsigned int, 7, fse->index + 1);
+	fse->max_width = fse->min_width;
+	fse->min_height = MT9P031_WINDOW_HEIGHT_DEF / (fse->index + 1);
+	fse->max_height = fse->min_height;
+
+	return 0;
+}
+
+static struct v4l2_mbus_framefmt *
+__mt9p031_get_pad_format(struct mt9p031 *mt9p031, struct v4l2_subdev_fh *fh,
+			 unsigned int pad, u32 which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_format(fh, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &mt9p031->format;
+	default:
+		return NULL;
+	}
+}
+
+static struct v4l2_rect *
+__mt9p031_get_pad_crop(struct mt9p031 *mt9p031, struct v4l2_subdev_fh *fh,
+		     unsigned int pad, u32 which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_crop(fh, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &mt9p031->crop;
+	default:
+		return NULL;
+	}
+}
+
+static int mt9p031_get_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *fmt)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+	fmt->format = *__mt9p031_get_pad_format(mt9p031, fh, fmt->pad,
+						fmt->which);
+	return 0;
+}
+
+static int mt9p031_set_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *format)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	struct v4l2_mbus_framefmt *__format;
+	struct v4l2_rect *__crop;
+	unsigned int width;
+	unsigned int height;
+	unsigned int hratio;
+	unsigned int vratio;
+
+	__crop = __mt9p031_get_pad_crop(mt9p031, fh, format->pad,
+					format->which);
+
+	/* Clamp the width and height to avoid dividing by zero. */
+	width = clamp_t(unsigned int, ALIGN(format->format.width, 2),
+			max(__crop->width / 7, MT9P031_WINDOW_WIDTH_MIN),
+			__crop->width);
+	height = clamp_t(unsigned int, ALIGN(format->format.height, 2),
+			max(__crop->height / 8, MT9P031_WINDOW_HEIGHT_MIN),
+			__crop->height);
+
+	hratio = DIV_ROUND_CLOSEST(__crop->width, width);
+	vratio = DIV_ROUND_CLOSEST(__crop->height, height);
+
+	__format = __mt9p031_get_pad_format(mt9p031, fh, format->pad,
+					    format->which);
+	__format->width = __crop->width / hratio;
+	__format->height = __crop->height / vratio;
+
+	format->format = *__format;
+
+	return 0;
+}
+
+static int mt9p031_get_crop(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_fh *fh,
+			    struct v4l2_subdev_crop *crop)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+	crop->rect = *__mt9p031_get_pad_crop(mt9p031, fh, crop->pad,
+					     crop->which);
+	return 0;
+}
+
+static int mt9p031_set_crop(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_fh *fh,
+			    struct v4l2_subdev_crop *crop)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	struct v4l2_mbus_framefmt *__format;
+	struct v4l2_rect *__crop;
+	struct v4l2_rect rect;
+
+	/* Clamp the crop rectangle boundaries and align them to a multiple of 2
+	 * pixels to ensure a GRBG Bayer pattern.
+	 */
+	rect.left = clamp(ALIGN(crop->rect.left, 2), MT9P031_COLUMN_START_MIN,
+			  MT9P031_COLUMN_START_MAX);
+	rect.top = clamp(ALIGN(crop->rect.top, 2), MT9P031_ROW_START_MIN,
+			 MT9P031_ROW_START_MAX);
+	rect.width = clamp(ALIGN(crop->rect.width, 2),
+			   MT9P031_WINDOW_WIDTH_MIN,
+			   MT9P031_WINDOW_WIDTH_MAX);
+	rect.height = clamp(ALIGN(crop->rect.height, 2),
+			    MT9P031_WINDOW_HEIGHT_MIN,
+			    MT9P031_WINDOW_HEIGHT_MAX);
+
+	rect.width = min(rect.width, MT9P031_PIXEL_ARRAY_WIDTH - rect.left);
+	rect.height = min(rect.height, MT9P031_PIXEL_ARRAY_HEIGHT - rect.top);
+
+	__crop = __mt9p031_get_pad_crop(mt9p031, fh, crop->pad, crop->which);
+
+	if (rect.width != __crop->width || rect.height != __crop->height) {
+		/* Reset the output image size if the crop rectangle size has
+		 * been modified.
+		 */
+		__format = __mt9p031_get_pad_format(mt9p031, fh, crop->pad,
+						    crop->which);
+		__format->width = rect.width;
+		__format->height = rect.height;
+	}
+
+	*__crop = rect;
+	crop->rect = rect;
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev control operations
+ */
+
+#define V4L2_CID_TEST_PATTERN		(V4L2_CID_USER_BASE | 0x1001)
+
+static int mt9p031_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mt9p031 *mt9p031 =
+			container_of(ctrl->handler, struct mt9p031, ctrls);
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	u16 data;
+	int ret;
+
+	switch (ctrl->id) {
+	case V4L2_CID_EXPOSURE:
+		ret = mt9p031_write(client, MT9P031_SHUTTER_WIDTH_UPPER,
+				    (ctrl->val >> 16) & 0xffff);
+		if (ret < 0)
+			return ret;
+
+		return mt9p031_write(client, MT9P031_SHUTTER_WIDTH_LOWER,
+				     ctrl->val & 0xffff);
+
+	case V4L2_CID_GAIN:
+		/* Gain is controlled by 2 analog stages and a digital stage.
+		 * Valid values for the 3 stages are
+		 *
+		 * Stage                Min     Max     Step
+		 * ------------------------------------------
+		 * First analog stage   x1      x2      1
+		 * Second analog stage  x1      x4      0.125
+		 * Digital stage        x1      x16     0.125
+		 *
+		 * To minimize noise, the gain stages should be used in the
+		 * second analog stage, first analog stage, digital stage order.
+		 * Gain from a previous stage should be pushed to its maximum
+		 * value before the next stage is used.
+		 */
+		if (ctrl->val <= 32) {
+			data = ctrl->val;
+		} else if (ctrl->val <= 64) {
+			ctrl->val &= ~1;
+			data = (1 << 6) | (ctrl->val >> 1);
+		} else {
+			ctrl->val &= ~7;
+			data = ((ctrl->val - 64) << 5) | (1 << 6) | 32;
+		}
+
+		return mt9p031_write(client, MT9P031_GLOBAL_GAIN, data);
+
+	case V4L2_CID_HFLIP:
+		if (ctrl->val)
+			return mt9p031_set_mode2(mt9p031,
+					0, MT9P031_READ_MODE_2_COL_MIR);
+		else
+			return mt9p031_set_mode2(mt9p031,
+					MT9P031_READ_MODE_2_COL_MIR, 0);
+
+	case V4L2_CID_VFLIP:
+		if (ctrl->val)
+			return mt9p031_set_mode2(mt9p031,
+					0, MT9P031_READ_MODE_2_ROW_MIR);
+		else
+			return mt9p031_set_mode2(mt9p031,
+					MT9P031_READ_MODE_2_ROW_MIR, 0);
+
+	case V4L2_CID_TEST_PATTERN:
+		if (!ctrl->val) {
+			ret = mt9p031_set_mode2(mt9p031,
+					0, MT9P031_READ_MODE_2_ROW_BLC);
+			if (ret < 0)
+				return ret;
+
+			return mt9p031_write(client, MT9P031_TEST_PATTERN,
+					     MT9P031_TEST_PATTERN_DISABLE);
+		}
+
+		ret = mt9p031_write(client, MT9P031_TEST_PATTERN_GREEN, 0x05a0);
+		if (ret < 0)
+			return ret;
+		ret = mt9p031_write(client, MT9P031_TEST_PATTERN_RED, 0x0a50);
+		if (ret < 0)
+			return ret;
+		ret = mt9p031_write(client, MT9P031_TEST_PATTERN_BLUE, 0x0aa0);
+		if (ret < 0)
+			return ret;
+
+		ret = mt9p031_set_mode2(mt9p031, MT9P031_READ_MODE_2_ROW_BLC,
+					0);
+		if (ret < 0)
+			return ret;
+		ret = mt9p031_write(client, MT9P031_ROW_BLACK_DEF_OFFSET, 0);
+		if (ret < 0)
+			return ret;
+
+		return mt9p031_write(client, MT9P031_TEST_PATTERN,
+				((ctrl->val - 1) << MT9P031_TEST_PATTERN_SHIFT)
+				| MT9P031_TEST_PATTERN_ENABLE);
+	}
+	return 0;
+}
+
+static struct v4l2_ctrl_ops mt9p031_ctrl_ops = {
+	.s_ctrl = mt9p031_s_ctrl,
+};
+
+static const char * const mt9p031_test_pattern_menu[] = {
+	"Disabled",
+	"Color Field",
+	"Horizontal Gradient",
+	"Vertical Gradient",
+	"Diagonal Gradient",
+	"Classic Test Pattern",
+	"Walking 1s",
+	"Monochrome Horizontal Bars",
+	"Monochrome Vertical Bars",
+	"Vertical Color Bars",
+};
+
+static const struct v4l2_ctrl_config mt9p031_ctrls[] = {
+	{
+		.ops		= &mt9p031_ctrl_ops,
+		.id		= V4L2_CID_TEST_PATTERN,
+		.type		= V4L2_CTRL_TYPE_MENU,
+		.name		= "Test Pattern",
+		.min		= 0,
+		.max		= ARRAY_SIZE(mt9p031_test_pattern_menu) - 1,
+		.step		= 0,
+		.def		= 0,
+		.flags		= 0,
+		.menu_skip_mask	= 0,
+		.qmenu		= mt9p031_test_pattern_menu,
+	}
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev core operations
+ */
+
+static int mt9p031_set_power(struct v4l2_subdev *subdev, int on)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	int ret = 0;
+
+	mutex_lock(&mt9p031->power_lock);
+
+	/* If the power count is modified from 0 to != 0 or from != 0 to 0,
+	 * update the power state.
+	 */
+	if (mt9p031->power_count == !on) {
+		ret = __mt9p031_set_power(mt9p031, !!on);
+		if (ret < 0)
+			goto out;
+	}
+
+	/* Update the power count. */
+	mt9p031->power_count += on ? 1 : -1;
+	WARN_ON(mt9p031->power_count < 0);
+
+out:
+	mutex_unlock(&mt9p031->power_lock);
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev internal operations
+ */
+
+static int mt9p031_registered(struct v4l2_subdev *subdev)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	s32 data;
+	int ret;
+
+	ret = mt9p031_power_on(mt9p031);
+	if (ret < 0) {
+		dev_err(&client->dev, "MT9P031 power up failed\n");
+		return ret;
+	}
+
+	/* Read out the chip version register */
+	data = mt9p031_read(client, MT9P031_CHIP_VERSION);
+	if (data != MT9P031_CHIP_VERSION_VALUE) {
+		dev_err(&client->dev, "MT9P031 not detected, wrong version "
+			"0x%04x\n", data);
+		return -ENODEV;
+	}
+
+	mt9p031_power_off(mt9p031);
+
+	dev_info(&client->dev, "MT9P031 detected at address 0x%02x\n",
+		 client->addr);
+
+	return ret;
+}
+
+static int mt9p031_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *crop;
+
+	crop = v4l2_subdev_get_try_crop(fh, 0);
+	crop->left = MT9P031_COLUMN_START_DEF;
+	crop->top = MT9P031_ROW_START_DEF;
+	crop->width = MT9P031_WINDOW_WIDTH_DEF;
+	crop->height = MT9P031_WINDOW_HEIGHT_DEF;
+
+	format = v4l2_subdev_get_try_format(fh, 0);
+
+	if (mt9p031->pdata->version == MT9P031_MONOCHROME_VERSION)
+		format->code = V4L2_MBUS_FMT_Y12_1X12;
+	else
+		format->code = V4L2_MBUS_FMT_SGRBG12_1X12;
+
+	format->width = MT9P031_WINDOW_WIDTH_DEF;
+	format->height = MT9P031_WINDOW_HEIGHT_DEF;
+	format->field = V4L2_FIELD_NONE;
+	format->colorspace = V4L2_COLORSPACE_SRGB;
+
+	mt9p031->xskip = 1;
+	mt9p031->yskip = 1;
+	return mt9p031_set_power(subdev, 1);
+}
+
+static int mt9p031_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return mt9p031_set_power(subdev, 0);
+}
+
+static struct v4l2_subdev_core_ops mt9p031_subdev_core_ops = {
+	.s_power        = mt9p031_set_power,
+};
+
+static struct v4l2_subdev_video_ops mt9p031_subdev_video_ops = {
+	.s_stream       = mt9p031_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops mt9p031_subdev_pad_ops = {
+	.enum_mbus_code = mt9p031_enum_mbus_code,
+	.enum_frame_size = mt9p031_enum_frame_size,
+	.get_fmt = mt9p031_get_format,
+	.set_fmt = mt9p031_set_format,
+	.get_crop = mt9p031_get_crop,
+	.set_crop = mt9p031_set_crop,
+};
+
+static struct v4l2_subdev_ops mt9p031_subdev_ops = {
+	.core   = &mt9p031_subdev_core_ops,
+	.video  = &mt9p031_subdev_video_ops,
+	.pad    = &mt9p031_subdev_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops mt9p031_subdev_internal_ops = {
+	.registered = mt9p031_registered,
+	.open = mt9p031_open,
+	.close = mt9p031_close,
+};
+
+/* -----------------------------------------------------------------------------
+ * Driver initialization and probing
+ */
+
+static int mt9p031_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
+{
+	struct mt9p031_platform_data *pdata = client->dev.platform_data;
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	struct mt9p031 *mt9p031;
+	unsigned int i;
+	int ret;
+
+	if (pdata == NULL) {
+		dev_err(&client->dev, "No platform data\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
+		dev_warn(&client->dev,
+			"I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+		return -EIO;
+	}
+
+	mt9p031 = kzalloc(sizeof(*mt9p031), GFP_KERNEL);
+	if (mt9p031 == NULL)
+		return -ENOMEM;
+
+	mt9p031->pdata = pdata;
+	mt9p031->output_control	= MT9P031_OUTPUT_CONTROL_DEF;
+	mt9p031->mode2 = MT9P031_READ_MODE_2_ROW_BLC;
+
+	v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 4);
+
+	v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+			  V4L2_CID_EXPOSURE, MT9P031_SHUTTER_WIDTH_MIN,
+			  MT9P031_SHUTTER_WIDTH_MAX, 1,
+			  MT9P031_SHUTTER_WIDTH_DEF);
+	v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+			  V4L2_CID_GAIN, MT9P031_GLOBAL_GAIN_MIN,
+			  MT9P031_GLOBAL_GAIN_MAX, 1, MT9P031_GLOBAL_GAIN_DEF);
+	v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+			  V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+			  V4L2_CID_VFLIP, 0, 1, 1, 0);
+
+	for (i = 0; i < ARRAY_SIZE(mt9p031_ctrls); ++i)
+		v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL);
+
+	mt9p031->subdev.ctrl_handler = &mt9p031->ctrls;
+
+	if (mt9p031->ctrls.error)
+		printk(KERN_INFO "%s: control initialization error %d\n",
+		       __func__, mt9p031->ctrls.error);
+
+	mutex_init(&mt9p031->power_lock);
+	v4l2_i2c_subdev_init(&mt9p031->subdev, client, &mt9p031_subdev_ops);
+	mt9p031->subdev.internal_ops = &mt9p031_subdev_internal_ops;
+
+	mt9p031->pad.flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_init(&mt9p031->subdev.entity, 1, &mt9p031->pad, 0);
+	if (ret < 0)
+		goto done;
+
+	mt9p031->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	mt9p031->crop.width = MT9P031_WINDOW_WIDTH_DEF;
+	mt9p031->crop.height = MT9P031_WINDOW_HEIGHT_DEF;
+	mt9p031->crop.left = MT9P031_COLUMN_START_DEF;
+	mt9p031->crop.top = MT9P031_ROW_START_DEF;
+
+	if (mt9p031->pdata->version == MT9P031_MONOCHROME_VERSION)
+		mt9p031->format.code = V4L2_MBUS_FMT_Y12_1X12;
+	else
+		mt9p031->format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
+
+	mt9p031->format.width = MT9P031_WINDOW_WIDTH_DEF;
+	mt9p031->format.height = MT9P031_WINDOW_HEIGHT_DEF;
+	mt9p031->format.field = V4L2_FIELD_NONE;
+	mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB;
+
+	ret = mt9p031_pll_get_divs(mt9p031);
+
+done:
+	if (ret < 0) {
+		v4l2_ctrl_handler_free(&mt9p031->ctrls);
+		media_entity_cleanup(&mt9p031->subdev.entity);
+		kfree(mt9p031);
+	}
+
+	return ret;
+}
+
+static int mt9p031_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+	v4l2_ctrl_handler_free(&mt9p031->ctrls);
+	v4l2_device_unregister_subdev(subdev);
+	media_entity_cleanup(&subdev->entity);
+	kfree(mt9p031);
+
+	return 0;
+}
+
+static const struct i2c_device_id mt9p031_id[] = {
+	{ "mt9p031", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mt9p031_id);
+
+static struct i2c_driver mt9p031_i2c_driver = {
+	.driver = {
+		.name = "mt9p031",
+	},
+	.probe          = mt9p031_probe,
+	.remove         = mt9p031_remove,
+	.id_table       = mt9p031_id,
+};
+
+static int __init mt9p031_mod_init(void)
+{
+	return i2c_add_driver(&mt9p031_i2c_driver);
+}
+
+static void __exit mt9p031_mod_exit(void)
+{
+	i2c_del_driver(&mt9p031_i2c_driver);
+}
+
+module_init(mt9p031_mod_init);
+module_exit(mt9p031_mod_exit);
+
+MODULE_DESCRIPTION("Aptina MT9P031 Camera driver");
+MODULE_AUTHOR("Bastian Hecht <hechtb@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-3.1-gnu/drivers/media/video/mt9t001.c linux-libre-3.2-gnu/drivers/media/video/mt9t001.c
--- linux-libre-3.1-gnu/drivers/media/video/mt9t001.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/mt9t001.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,836 @@
+/*
+ * Driver for MT9T001 CMOS Image Sensor from Aptina (Micron)
+ *
+ * Copyright (C) 2010-2011, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on the MT9M001 driver,
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <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 <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/log2.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/v4l2-mediabus.h>
+
+#include <media/mt9t001.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#define MT9T001_PIXEL_ARRAY_HEIGHT			1568
+#define MT9T001_PIXEL_ARRAY_WIDTH			2112
+
+#define MT9T001_CHIP_VERSION				0x00
+#define		MT9T001_CHIP_ID				0x1621
+#define MT9T001_ROW_START				0x01
+#define		MT9T001_ROW_START_MIN			0
+#define		MT9T001_ROW_START_DEF			20
+#define		MT9T001_ROW_START_MAX			1534
+#define MT9T001_COLUMN_START				0x02
+#define		MT9T001_COLUMN_START_MIN		0
+#define		MT9T001_COLUMN_START_DEF		32
+#define		MT9T001_COLUMN_START_MAX		2046
+#define MT9T001_WINDOW_HEIGHT				0x03
+#define		MT9T001_WINDOW_HEIGHT_MIN		1
+#define		MT9T001_WINDOW_HEIGHT_DEF		1535
+#define		MT9T001_WINDOW_HEIGHT_MAX		1567
+#define MT9T001_WINDOW_WIDTH				0x04
+#define		MT9T001_WINDOW_WIDTH_MIN		1
+#define		MT9T001_WINDOW_WIDTH_DEF		2047
+#define		MT9T001_WINDOW_WIDTH_MAX		2111
+#define MT9T001_HORIZONTAL_BLANKING			0x05
+#define		MT9T001_HORIZONTAL_BLANKING_MIN		21
+#define		MT9T001_HORIZONTAL_BLANKING_MAX		1023
+#define MT9T001_VERTICAL_BLANKING			0x06
+#define		MT9T001_VERTICAL_BLANKING_MIN		3
+#define		MT9T001_VERTICAL_BLANKING_MAX		1023
+#define MT9T001_OUTPUT_CONTROL				0x07
+#define		MT9T001_OUTPUT_CONTROL_SYNC		(1 << 0)
+#define		MT9T001_OUTPUT_CONTROL_CHIP_ENABLE	(1 << 1)
+#define		MT9T001_OUTPUT_CONTROL_TEST_DATA	(1 << 6)
+#define MT9T001_SHUTTER_WIDTH_HIGH			0x08
+#define MT9T001_SHUTTER_WIDTH_LOW			0x09
+#define		MT9T001_SHUTTER_WIDTH_MIN		1
+#define		MT9T001_SHUTTER_WIDTH_DEF		1561
+#define		MT9T001_SHUTTER_WIDTH_MAX		(1024 * 1024)
+#define MT9T001_PIXEL_CLOCK				0x0a
+#define		MT9T001_PIXEL_CLOCK_INVERT		(1 << 15)
+#define		MT9T001_PIXEL_CLOCK_SHIFT_MASK		(7 << 8)
+#define		MT9T001_PIXEL_CLOCK_SHIFT_SHIFT		8
+#define		MT9T001_PIXEL_CLOCK_DIVIDE_MASK		(0x7f << 0)
+#define MT9T001_FRAME_RESTART				0x0b
+#define MT9T001_SHUTTER_DELAY				0x0c
+#define		MT9T001_SHUTTER_DELAY_MAX		2047
+#define MT9T001_RESET					0x0d
+#define MT9T001_READ_MODE1				0x1e
+#define		MT9T001_READ_MODE_SNAPSHOT		(1 << 8)
+#define		MT9T001_READ_MODE_STROBE_ENABLE		(1 << 9)
+#define		MT9T001_READ_MODE_STROBE_WIDTH		(1 << 10)
+#define		MT9T001_READ_MODE_STROBE_OVERRIDE	(1 << 11)
+#define MT9T001_READ_MODE2				0x20
+#define		MT9T001_READ_MODE_BAD_FRAMES		(1 << 0)
+#define		MT9T001_READ_MODE_LINE_VALID_CONTINUOUS	(1 << 9)
+#define		MT9T001_READ_MODE_LINE_VALID_FRAME	(1 << 10)
+#define MT9T001_READ_MODE3				0x21
+#define		MT9T001_READ_MODE_GLOBAL_RESET		(1 << 0)
+#define		MT9T001_READ_MODE_GHST_CTL		(1 << 1)
+#define MT9T001_ROW_ADDRESS_MODE			0x22
+#define		MT9T001_ROW_SKIP_MASK			(7 << 0)
+#define		MT9T001_ROW_BIN_MASK			(3 << 3)
+#define		MT9T001_ROW_BIN_SHIFT			3
+#define MT9T001_COLUMN_ADDRESS_MODE			0x23
+#define		MT9T001_COLUMN_SKIP_MASK		(7 << 0)
+#define		MT9T001_COLUMN_BIN_MASK			(3 << 3)
+#define		MT9T001_COLUMN_BIN_SHIFT		3
+#define MT9T001_GREEN1_GAIN				0x2b
+#define MT9T001_BLUE_GAIN				0x2c
+#define MT9T001_RED_GAIN				0x2d
+#define MT9T001_GREEN2_GAIN				0x2e
+#define MT9T001_TEST_DATA				0x32
+#define MT9T001_GLOBAL_GAIN				0x35
+#define		MT9T001_GLOBAL_GAIN_MIN			8
+#define		MT9T001_GLOBAL_GAIN_MAX			1024
+#define MT9T001_BLACK_LEVEL				0x49
+#define MT9T001_ROW_BLACK_DEFAULT_OFFSET		0x4b
+#define MT9T001_BLC_DELTA_THRESHOLDS			0x5d
+#define MT9T001_CAL_THRESHOLDS				0x5f
+#define MT9T001_GREEN1_OFFSET				0x60
+#define MT9T001_GREEN2_OFFSET				0x61
+#define MT9T001_BLACK_LEVEL_CALIBRATION			0x62
+#define		MT9T001_BLACK_LEVEL_OVERRIDE		(1 << 0)
+#define		MT9T001_BLACK_LEVEL_DISABLE_OFFSET	(1 << 1)
+#define		MT9T001_BLACK_LEVEL_RECALCULATE		(1 << 12)
+#define		MT9T001_BLACK_LEVEL_LOCK_RED_BLUE	(1 << 13)
+#define		MT9T001_BLACK_LEVEL_LOCK_GREEN		(1 << 14)
+#define MT9T001_RED_OFFSET				0x63
+#define MT9T001_BLUE_OFFSET				0x64
+
+struct mt9t001 {
+	struct v4l2_subdev subdev;
+	struct media_pad pad;
+
+	struct v4l2_mbus_framefmt format;
+	struct v4l2_rect crop;
+
+	struct v4l2_ctrl_handler ctrls;
+	struct v4l2_ctrl *gains[4];
+
+	u16 output_control;
+	u16 black_level;
+};
+
+static inline struct mt9t001 *to_mt9t001(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct mt9t001, subdev);
+}
+
+static int mt9t001_read(struct i2c_client *client, u8 reg)
+{
+	s32 data = i2c_smbus_read_word_data(client, reg);
+	return data < 0 ? data : be16_to_cpu(data);
+}
+
+static int mt9t001_write(struct i2c_client *client, u8 reg, u16 data)
+{
+	return i2c_smbus_write_word_data(client, reg, cpu_to_be16(data));
+}
+
+static int mt9t001_set_output_control(struct mt9t001 *mt9t001, u16 clear,
+				      u16 set)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
+	u16 value = (mt9t001->output_control & ~clear) | set;
+	int ret;
+
+	if (value == mt9t001->output_control)
+		return 0;
+
+	ret = mt9t001_write(client, MT9T001_OUTPUT_CONTROL, value);
+	if (ret < 0)
+		return ret;
+
+	mt9t001->output_control = value;
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev video operations
+ */
+
+static struct v4l2_mbus_framefmt *
+__mt9t001_get_pad_format(struct mt9t001 *mt9t001, struct v4l2_subdev_fh *fh,
+			 unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_format(fh, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &mt9t001->format;
+	default:
+		return NULL;
+	}
+}
+
+static struct v4l2_rect *
+__mt9t001_get_pad_crop(struct mt9t001 *mt9t001, struct v4l2_subdev_fh *fh,
+		       unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_crop(fh, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &mt9t001->crop;
+	default:
+		return NULL;
+	}
+}
+
+static int mt9t001_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	const u16 mode = MT9T001_OUTPUT_CONTROL_CHIP_ENABLE;
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+	struct v4l2_mbus_framefmt *format = &mt9t001->format;
+	struct v4l2_rect *crop = &mt9t001->crop;
+	unsigned int hratio;
+	unsigned int vratio;
+	int ret;
+
+	if (!enable)
+		return mt9t001_set_output_control(mt9t001, mode, 0);
+
+	/* Configure the window size and row/column bin */
+	hratio = DIV_ROUND_CLOSEST(crop->width, format->width);
+	vratio = DIV_ROUND_CLOSEST(crop->height, format->height);
+
+	ret = mt9t001_write(client, MT9T001_ROW_ADDRESS_MODE, hratio - 1);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_COLUMN_ADDRESS_MODE, vratio - 1);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_COLUMN_START, crop->left);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_ROW_START, crop->top);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_WINDOW_WIDTH, crop->width - 1);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_WINDOW_HEIGHT, crop->height - 1);
+	if (ret < 0)
+		return ret;
+
+	/* Switch to master "normal" mode */
+	return mt9t001_set_output_control(mt9t001, 0, mode);
+}
+
+static int mt9t001_enum_mbus_code(struct v4l2_subdev *subdev,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	if (code->index > 0)
+		return -EINVAL;
+
+	code->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+	return 0;
+}
+
+static int mt9t001_enum_frame_size(struct v4l2_subdev *subdev,
+				   struct v4l2_subdev_fh *fh,
+				   struct v4l2_subdev_frame_size_enum *fse)
+{
+	if (fse->index >= 8 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10)
+		return -EINVAL;
+
+	fse->min_width = (MT9T001_WINDOW_WIDTH_DEF + 1) / fse->index;
+	fse->max_width = fse->min_width;
+	fse->min_height = (MT9T001_WINDOW_HEIGHT_DEF + 1) / fse->index;
+	fse->max_height = fse->min_height;
+
+	return 0;
+}
+
+static int mt9t001_get_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *format)
+{
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+
+	format->format = *__mt9t001_get_pad_format(mt9t001, fh, format->pad,
+						   format->which);
+	return 0;
+}
+
+static int mt9t001_set_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *format)
+{
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+	struct v4l2_mbus_framefmt *__format;
+	struct v4l2_rect *__crop;
+	unsigned int width;
+	unsigned int height;
+	unsigned int hratio;
+	unsigned int vratio;
+
+	__crop = __mt9t001_get_pad_crop(mt9t001, fh, format->pad,
+					format->which);
+
+	/* Clamp the width and height to avoid dividing by zero. */
+	width = clamp_t(unsigned int, ALIGN(format->format.width, 2),
+			max(__crop->width / 8, MT9T001_WINDOW_HEIGHT_MIN + 1),
+			__crop->width);
+	height = clamp_t(unsigned int, ALIGN(format->format.height, 2),
+			 max(__crop->height / 8, MT9T001_WINDOW_HEIGHT_MIN + 1),
+			 __crop->height);
+
+	hratio = DIV_ROUND_CLOSEST(__crop->width, width);
+	vratio = DIV_ROUND_CLOSEST(__crop->height, height);
+
+	__format = __mt9t001_get_pad_format(mt9t001, fh, format->pad,
+					    format->which);
+	__format->width = __crop->width / hratio;
+	__format->height = __crop->height / vratio;
+
+	format->format = *__format;
+
+	return 0;
+}
+
+static int mt9t001_get_crop(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_fh *fh,
+			    struct v4l2_subdev_crop *crop)
+{
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+
+	crop->rect = *__mt9t001_get_pad_crop(mt9t001, fh, crop->pad,
+					     crop->which);
+	return 0;
+}
+
+static int mt9t001_set_crop(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_fh *fh,
+			    struct v4l2_subdev_crop *crop)
+{
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+	struct v4l2_mbus_framefmt *__format;
+	struct v4l2_rect *__crop;
+	struct v4l2_rect rect;
+
+	/* Clamp the crop rectangle boundaries and align them to a multiple of 2
+	 * pixels.
+	 */
+	rect.left = clamp(ALIGN(crop->rect.left, 2),
+			  MT9T001_COLUMN_START_MIN,
+			  MT9T001_COLUMN_START_MAX);
+	rect.top = clamp(ALIGN(crop->rect.top, 2),
+			 MT9T001_ROW_START_MIN,
+			 MT9T001_ROW_START_MAX);
+	rect.width = clamp(ALIGN(crop->rect.width, 2),
+			   MT9T001_WINDOW_WIDTH_MIN + 1,
+			   MT9T001_WINDOW_WIDTH_MAX + 1);
+	rect.height = clamp(ALIGN(crop->rect.height, 2),
+			    MT9T001_WINDOW_HEIGHT_MIN + 1,
+			    MT9T001_WINDOW_HEIGHT_MAX + 1);
+
+	rect.width = min(rect.width, MT9T001_PIXEL_ARRAY_WIDTH - rect.left);
+	rect.height = min(rect.height, MT9T001_PIXEL_ARRAY_HEIGHT - rect.top);
+
+	__crop = __mt9t001_get_pad_crop(mt9t001, fh, crop->pad, crop->which);
+
+	if (rect.width != __crop->width || rect.height != __crop->height) {
+		/* Reset the output image size if the crop rectangle size has
+		 * been modified.
+		 */
+		__format = __mt9t001_get_pad_format(mt9t001, fh, crop->pad,
+						    crop->which);
+		__format->width = rect.width;
+		__format->height = rect.height;
+	}
+
+	*__crop = rect;
+	crop->rect = rect;
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev control operations
+ */
+
+#define V4L2_CID_TEST_PATTERN		(V4L2_CID_USER_BASE | 0x1001)
+#define V4L2_CID_BLACK_LEVEL_AUTO	(V4L2_CID_USER_BASE | 0x1002)
+#define V4L2_CID_BLACK_LEVEL_OFFSET	(V4L2_CID_USER_BASE | 0x1003)
+#define V4L2_CID_BLACK_LEVEL_CALIBRATE	(V4L2_CID_USER_BASE | 0x1004)
+
+#define V4L2_CID_GAIN_RED		(V4L2_CTRL_CLASS_CAMERA | 0x1001)
+#define V4L2_CID_GAIN_GREEN_RED		(V4L2_CTRL_CLASS_CAMERA | 0x1002)
+#define V4L2_CID_GAIN_GREEN_BLUE	(V4L2_CTRL_CLASS_CAMERA | 0x1003)
+#define V4L2_CID_GAIN_BLUE		(V4L2_CTRL_CLASS_CAMERA | 0x1004)
+
+static u16 mt9t001_gain_value(s32 *gain)
+{
+	/* Gain is controlled by 2 analog stages and a digital stage. Valid
+	 * values for the 3 stages are
+	 *
+	 * Stage		Min	Max	Step
+	 * ------------------------------------------
+	 * First analog stage	x1	x2	1
+	 * Second analog stage	x1	x4	0.125
+	 * Digital stage	x1	x16	0.125
+	 *
+	 * To minimize noise, the gain stages should be used in the second
+	 * analog stage, first analog stage, digital stage order. Gain from a
+	 * previous stage should be pushed to its maximum value before the next
+	 * stage is used.
+	 */
+	if (*gain <= 32)
+		return *gain;
+
+	if (*gain <= 64) {
+		*gain &= ~1;
+		return (1 << 6) | (*gain >> 1);
+	}
+
+	*gain &= ~7;
+	return ((*gain - 64) << 5) | (1 << 6) | 32;
+}
+
+static int mt9t001_ctrl_freeze(struct mt9t001 *mt9t001, bool freeze)
+{
+	return mt9t001_set_output_control(mt9t001,
+		freeze ? 0 : MT9T001_OUTPUT_CONTROL_SYNC,
+		freeze ? MT9T001_OUTPUT_CONTROL_SYNC : 0);
+}
+
+static int mt9t001_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	static const u8 gains[4] = {
+		MT9T001_RED_GAIN, MT9T001_GREEN1_GAIN,
+		MT9T001_GREEN2_GAIN, MT9T001_BLUE_GAIN
+	};
+
+	struct mt9t001 *mt9t001 =
+			container_of(ctrl->handler, struct mt9t001, ctrls);
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
+	unsigned int count;
+	unsigned int i;
+	u16 value;
+	int ret;
+
+	switch (ctrl->id) {
+	case V4L2_CID_GAIN_RED:
+	case V4L2_CID_GAIN_GREEN_RED:
+	case V4L2_CID_GAIN_GREEN_BLUE:
+	case V4L2_CID_GAIN_BLUE:
+
+		/* Disable control updates if more than one control has changed
+		 * in the cluster.
+		 */
+		for (i = 0, count = 0; i < 4; ++i) {
+			struct v4l2_ctrl *gain = mt9t001->gains[i];
+
+			if (gain->val != gain->cur.val)
+				count++;
+		}
+
+		if (count > 1) {
+			ret = mt9t001_ctrl_freeze(mt9t001, true);
+			if (ret < 0)
+				return ret;
+		}
+
+		/* Update the gain controls. */
+		for (i = 0; i < 4; ++i) {
+			struct v4l2_ctrl *gain = mt9t001->gains[i];
+
+			if (gain->val == gain->cur.val)
+				continue;
+
+			value = mt9t001_gain_value(&gain->val);
+			ret = mt9t001_write(client, gains[i], value);
+			if (ret < 0) {
+				mt9t001_ctrl_freeze(mt9t001, false);
+				return ret;
+			}
+		}
+
+		/* Enable control updates. */
+		if (count > 1) {
+			ret = mt9t001_ctrl_freeze(mt9t001, false);
+			if (ret < 0)
+				return ret;
+		}
+
+		break;
+
+	case V4L2_CID_EXPOSURE:
+		ret = mt9t001_write(client, MT9T001_SHUTTER_WIDTH_LOW,
+				    ctrl->val & 0xffff);
+		if (ret < 0)
+			return ret;
+
+		return mt9t001_write(client, MT9T001_SHUTTER_WIDTH_HIGH,
+				     ctrl->val >> 16);
+
+	case V4L2_CID_TEST_PATTERN:
+		ret = mt9t001_set_output_control(mt9t001,
+			ctrl->val ? 0 : MT9T001_OUTPUT_CONTROL_TEST_DATA,
+			ctrl->val ? MT9T001_OUTPUT_CONTROL_TEST_DATA : 0);
+		if (ret < 0)
+			return ret;
+
+		return mt9t001_write(client, MT9T001_TEST_DATA, ctrl->val << 2);
+
+	case V4L2_CID_BLACK_LEVEL_AUTO:
+		value = ctrl->val ? 0 : MT9T001_BLACK_LEVEL_OVERRIDE;
+		ret = mt9t001_write(client, MT9T001_BLACK_LEVEL_CALIBRATION,
+				    value);
+		if (ret < 0)
+			return ret;
+
+		mt9t001->black_level = value;
+		break;
+
+	case V4L2_CID_BLACK_LEVEL_OFFSET:
+		ret = mt9t001_write(client, MT9T001_GREEN1_OFFSET, ctrl->val);
+		if (ret < 0)
+			return ret;
+
+		ret = mt9t001_write(client, MT9T001_GREEN2_OFFSET, ctrl->val);
+		if (ret < 0)
+			return ret;
+
+		ret = mt9t001_write(client, MT9T001_RED_OFFSET, ctrl->val);
+		if (ret < 0)
+			return ret;
+
+		return mt9t001_write(client, MT9T001_BLUE_OFFSET, ctrl->val);
+
+	case V4L2_CID_BLACK_LEVEL_CALIBRATE:
+		return mt9t001_write(client, MT9T001_BLACK_LEVEL_CALIBRATION,
+				     MT9T001_BLACK_LEVEL_RECALCULATE |
+				     mt9t001->black_level);
+	}
+
+	return 0;
+}
+
+static struct v4l2_ctrl_ops mt9t001_ctrl_ops = {
+	.s_ctrl = mt9t001_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config mt9t001_ctrls[] = {
+	{
+		.ops		= &mt9t001_ctrl_ops,
+		.id		= V4L2_CID_TEST_PATTERN,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Test pattern",
+		.min		= 0,
+		.max		= 1023,
+		.step		= 1,
+		.def		= 0,
+		.flags		= 0,
+	}, {
+		.ops		= &mt9t001_ctrl_ops,
+		.id		= V4L2_CID_BLACK_LEVEL_AUTO,
+		.type		= V4L2_CTRL_TYPE_BOOLEAN,
+		.name		= "Black Level, Auto",
+		.min		= 0,
+		.max		= 1,
+		.step		= 1,
+		.def		= 1,
+		.flags		= 0,
+	}, {
+		.ops		= &mt9t001_ctrl_ops,
+		.id		= V4L2_CID_BLACK_LEVEL_OFFSET,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Black Level, Offset",
+		.min		= -256,
+		.max		= 255,
+		.step		= 1,
+		.def		= 32,
+		.flags		= 0,
+	}, {
+		.ops		= &mt9t001_ctrl_ops,
+		.id		= V4L2_CID_BLACK_LEVEL_CALIBRATE,
+		.type		= V4L2_CTRL_TYPE_BUTTON,
+		.name		= "Black Level, Calibrate",
+		.min		= 0,
+		.max		= 0,
+		.step		= 0,
+		.def		= 0,
+		.flags		= V4L2_CTRL_FLAG_WRITE_ONLY,
+	},
+};
+
+static const struct v4l2_ctrl_config mt9t001_gains[] = {
+	{
+		.ops		= &mt9t001_ctrl_ops,
+		.id		= V4L2_CID_GAIN_RED,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Gain, Red",
+		.min		= MT9T001_GLOBAL_GAIN_MIN,
+		.max		= MT9T001_GLOBAL_GAIN_MAX,
+		.step		= 1,
+		.def		= MT9T001_GLOBAL_GAIN_MIN,
+		.flags		= 0,
+	}, {
+		.ops		= &mt9t001_ctrl_ops,
+		.id		= V4L2_CID_GAIN_GREEN_RED,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Gain, Green (R)",
+		.min		= MT9T001_GLOBAL_GAIN_MIN,
+		.max		= MT9T001_GLOBAL_GAIN_MAX,
+		.step		= 1,
+		.def		= MT9T001_GLOBAL_GAIN_MIN,
+		.flags		= 0,
+	}, {
+		.ops		= &mt9t001_ctrl_ops,
+		.id		= V4L2_CID_GAIN_GREEN_BLUE,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Gain, Green (B)",
+		.min		= MT9T001_GLOBAL_GAIN_MIN,
+		.max		= MT9T001_GLOBAL_GAIN_MAX,
+		.step		= 1,
+		.def		= MT9T001_GLOBAL_GAIN_MIN,
+		.flags		= 0,
+	}, {
+		.ops		= &mt9t001_ctrl_ops,
+		.id		= V4L2_CID_GAIN_BLUE,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Gain, Blue",
+		.min		= MT9T001_GLOBAL_GAIN_MIN,
+		.max		= MT9T001_GLOBAL_GAIN_MAX,
+		.step		= 1,
+		.def		= MT9T001_GLOBAL_GAIN_MIN,
+		.flags		= 0,
+	},
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev internal operations
+ */
+
+static int mt9t001_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *crop;
+
+	crop = v4l2_subdev_get_try_crop(fh, 0);
+	crop->left = MT9T001_COLUMN_START_DEF;
+	crop->top = MT9T001_ROW_START_DEF;
+	crop->width = MT9T001_WINDOW_WIDTH_DEF + 1;
+	crop->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
+
+	format = v4l2_subdev_get_try_format(fh, 0);
+	format->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+	format->width = MT9T001_WINDOW_WIDTH_DEF + 1;
+	format->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
+	format->field = V4L2_FIELD_NONE;
+	format->colorspace = V4L2_COLORSPACE_SRGB;
+
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops mt9t001_subdev_video_ops = {
+	.s_stream = mt9t001_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops mt9t001_subdev_pad_ops = {
+	.enum_mbus_code = mt9t001_enum_mbus_code,
+	.enum_frame_size = mt9t001_enum_frame_size,
+	.get_fmt = mt9t001_get_format,
+	.set_fmt = mt9t001_set_format,
+	.get_crop = mt9t001_get_crop,
+	.set_crop = mt9t001_set_crop,
+};
+
+static struct v4l2_subdev_ops mt9t001_subdev_ops = {
+	.video = &mt9t001_subdev_video_ops,
+	.pad = &mt9t001_subdev_pad_ops,
+};
+
+static struct v4l2_subdev_internal_ops mt9t001_subdev_internal_ops = {
+	.open = mt9t001_open,
+};
+
+static int mt9t001_video_probe(struct i2c_client *client)
+{
+	struct mt9t001_platform_data *pdata = client->dev.platform_data;
+	s32 data;
+	int ret;
+
+	dev_info(&client->dev, "Probing MT9T001 at address 0x%02x\n",
+		 client->addr);
+
+	/* Reset the chip and stop data read out */
+	ret = mt9t001_write(client, MT9T001_RESET, 1);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_RESET, 0);
+	if (ret < 0)
+		return ret;
+
+	ret  = mt9t001_write(client, MT9T001_OUTPUT_CONTROL, 0);
+	if (ret < 0)
+		return ret;
+
+	/* Configure the pixel clock polarity */
+	if (pdata && pdata->clk_pol) {
+		ret  = mt9t001_write(client, MT9T001_PIXEL_CLOCK,
+				     MT9T001_PIXEL_CLOCK_INVERT);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Read and check the sensor version */
+	data = mt9t001_read(client, MT9T001_CHIP_VERSION);
+	if (data != MT9T001_CHIP_ID) {
+		dev_err(&client->dev, "MT9T001 not detected, wrong version "
+			"0x%04x\n", data);
+		return -ENODEV;
+	}
+
+	dev_info(&client->dev, "MT9T001 detected at address 0x%02x\n",
+		 client->addr);
+
+	return ret;
+}
+
+static int mt9t001_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
+{
+	struct mt9t001 *mt9t001;
+	unsigned int i;
+	int ret;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_WORD_DATA)) {
+		dev_warn(&client->adapter->dev,
+			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+		return -EIO;
+	}
+
+	ret = mt9t001_video_probe(client);
+	if (ret < 0)
+		return ret;
+
+	mt9t001 = kzalloc(sizeof(*mt9t001), GFP_KERNEL);
+	if (!mt9t001)
+		return -ENOMEM;
+
+	v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) +
+						ARRAY_SIZE(mt9t001_gains) + 2);
+
+	v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
+			  V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN,
+			  MT9T001_SHUTTER_WIDTH_MAX, 1,
+			  MT9T001_SHUTTER_WIDTH_DEF);
+	v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
+			  V4L2_CID_BLACK_LEVEL, 1, 1, 1, 1);
+
+	for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i)
+		v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL);
+
+	for (i = 0; i < ARRAY_SIZE(mt9t001_gains); ++i)
+		mt9t001->gains[i] = v4l2_ctrl_new_custom(&mt9t001->ctrls,
+			&mt9t001_gains[i], NULL);
+
+	v4l2_ctrl_cluster(ARRAY_SIZE(mt9t001_gains), mt9t001->gains);
+
+	mt9t001->subdev.ctrl_handler = &mt9t001->ctrls;
+
+	if (mt9t001->ctrls.error) {
+		printk(KERN_INFO "%s: control initialization error %d\n",
+		       __func__, mt9t001->ctrls.error);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	mt9t001->crop.left = MT9T001_COLUMN_START_DEF;
+	mt9t001->crop.top = MT9T001_ROW_START_DEF;
+	mt9t001->crop.width = MT9T001_WINDOW_WIDTH_DEF + 1;
+	mt9t001->crop.height = MT9T001_WINDOW_HEIGHT_DEF + 1;
+
+	mt9t001->format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
+	mt9t001->format.width = MT9T001_WINDOW_WIDTH_DEF + 1;
+	mt9t001->format.height = MT9T001_WINDOW_HEIGHT_DEF + 1;
+	mt9t001->format.field = V4L2_FIELD_NONE;
+	mt9t001->format.colorspace = V4L2_COLORSPACE_SRGB;
+
+	v4l2_i2c_subdev_init(&mt9t001->subdev, client, &mt9t001_subdev_ops);
+	mt9t001->subdev.internal_ops = &mt9t001_subdev_internal_ops;
+	mt9t001->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	mt9t001->pad.flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_init(&mt9t001->subdev.entity, 1, &mt9t001->pad, 0);
+
+done:
+	if (ret < 0) {
+		v4l2_ctrl_handler_free(&mt9t001->ctrls);
+		media_entity_cleanup(&mt9t001->subdev.entity);
+		kfree(mt9t001);
+	}
+
+	return ret;
+}
+
+static int mt9t001_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+
+	v4l2_ctrl_handler_free(&mt9t001->ctrls);
+	v4l2_device_unregister_subdev(subdev);
+	media_entity_cleanup(&subdev->entity);
+	kfree(mt9t001);
+	return 0;
+}
+
+static const struct i2c_device_id mt9t001_id[] = {
+	{ "mt9t001", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mt9t001_id);
+
+static struct i2c_driver mt9t001_driver = {
+	.driver = {
+		.name = "mt9t001",
+	},
+	.probe		= mt9t001_probe,
+	.remove		= mt9t001_remove,
+	.id_table	= mt9t001_id,
+};
+
+static int __init mt9t001_init(void)
+{
+	return i2c_add_driver(&mt9t001_driver);
+}
+
+static void __exit mt9t001_exit(void)
+{
+	i2c_del_driver(&mt9t001_driver);
+}
+
+module_init(mt9t001_init);
+module_exit(mt9t001_exit);
+
+MODULE_DESCRIPTION("Aptina (Micron) MT9T001 Camera driver");
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/media/video/mt9t031.c linux-libre-3.2-gnu/drivers/media/video/mt9t031.c
--- linux-libre-3.1-gnu/drivers/media/video/mt9t031.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/mt9t031.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,11 +13,21 @@
 #include <linux/log2.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/videodev2.h>
+#include <linux/module.h>
 
 #include <media/soc_camera.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-subdev.h>
+#include <media/v4l2-ctrls.h>
+
+/*
+ * ATTENTION: this driver still cannot be used outside of the soc-camera
+ * framework because of its PM implementation, using the video_device node.
+ * If hardware becomes available for testing, alternative PM approaches shall
+ * be considered and tested.
+ */
 
 /*
  * mt9t031 i2c address 0x5d
@@ -57,21 +67,20 @@
 #define MT9T031_COLUMN_SKIP		32
 #define MT9T031_ROW_SKIP		20
 
-#define MT9T031_BUS_PARAM	(SOCAM_PCLK_SAMPLE_RISING |	\
-	SOCAM_PCLK_SAMPLE_FALLING | SOCAM_HSYNC_ACTIVE_HIGH |	\
-	SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH |	\
-	SOCAM_MASTER | SOCAM_DATAWIDTH_10)
-
 struct mt9t031 {
 	struct v4l2_subdev subdev;
+	struct v4l2_ctrl_handler hdl;
+	struct {
+		/* exposure/auto-exposure cluster */
+		struct v4l2_ctrl *autoexposure;
+		struct v4l2_ctrl *exposure;
+	};
 	struct v4l2_rect rect;	/* Sensor window */
 	int model;	/* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */
 	u16 xskip;
 	u16 yskip;
-	unsigned int gain;
+	unsigned int total_h;
 	unsigned short y_skip_top;	/* Lines to skip at the top */
-	unsigned int exposure;
-	unsigned char autoexposure;
 };
 
 static struct mt9t031 *to_mt9t031(const struct i2c_client *client)
@@ -179,95 +188,6 @@
 	return 0;
 }
 
-static int mt9t031_set_bus_param(struct soc_camera_device *icd,
-				 unsigned long flags)
-{
-	struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
-
-	/* The caller should have queried our parameters, check anyway */
-	if (flags & ~MT9T031_BUS_PARAM)
-		return -EINVAL;
-
-	if (flags & SOCAM_PCLK_SAMPLE_FALLING)
-		reg_clear(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
-	else
-		reg_set(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
-
-	return 0;
-}
-
-static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd)
-{
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-
-	return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM);
-}
-
-enum {
-	MT9T031_CTRL_VFLIP,
-	MT9T031_CTRL_HFLIP,
-	MT9T031_CTRL_GAIN,
-	MT9T031_CTRL_EXPOSURE,
-	MT9T031_CTRL_EXPOSURE_AUTO,
-};
-
-static const struct v4l2_queryctrl mt9t031_controls[] = {
-	[MT9T031_CTRL_VFLIP] = {
-		.id		= V4L2_CID_VFLIP,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Flip Vertically",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 0,
-	},
-	[MT9T031_CTRL_HFLIP] = {
-		.id		= V4L2_CID_HFLIP,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Flip Horizontally",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 0,
-	},
-	[MT9T031_CTRL_GAIN] = {
-		.id		= V4L2_CID_GAIN,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Gain",
-		.minimum	= 0,
-		.maximum	= 127,
-		.step		= 1,
-		.default_value	= 64,
-		.flags		= V4L2_CTRL_FLAG_SLIDER,
-	},
-	[MT9T031_CTRL_EXPOSURE] = {
-		.id		= V4L2_CID_EXPOSURE,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Exposure",
-		.minimum	= 1,
-		.maximum	= 255,
-		.step		= 1,
-		.default_value	= 255,
-		.flags		= V4L2_CTRL_FLAG_SLIDER,
-	},
-	[MT9T031_CTRL_EXPOSURE_AUTO] = {
-		.id		= V4L2_CID_EXPOSURE_AUTO,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Automatic Exposure",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 1,
-	}
-};
-
-static struct soc_camera_ops mt9t031_ops = {
-	.set_bus_param		= mt9t031_set_bus_param,
-	.query_bus_param	= mt9t031_query_bus_param,
-	.controls		= mt9t031_controls,
-	.num_controls		= ARRAY_SIZE(mt9t031_controls),
-};
-
 /* target must be _even_ */
 static u16 mt9t031_skip(s32 *source, s32 target, s32 max)
 {
@@ -353,7 +273,7 @@
 
 	/*
 	 * The caller provides a supported format, as guaranteed by
-	 * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap()
+	 * .try_mbus_fmt(), soc_camera_s_crop() and soc_camera_cropcap()
 	 */
 	if (ret >= 0)
 		ret = reg_write(client, MT9T031_COLUMN_START, rect->left);
@@ -364,17 +284,10 @@
 	if (ret >= 0)
 		ret = reg_write(client, MT9T031_WINDOW_HEIGHT,
 				rect->height + mt9t031->y_skip_top - 1);
-	if (ret >= 0 && mt9t031->autoexposure) {
-		unsigned int total_h = rect->height + mt9t031->y_skip_top + vblank;
-		ret = set_shutter(client, total_h);
-		if (ret >= 0) {
-			const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
-			const struct v4l2_queryctrl *qctrl =
-				&mt9t031_controls[MT9T031_CTRL_EXPOSURE];
-			mt9t031->exposure = (shutter_max / 2 + (total_h - 1) *
-				 (qctrl->maximum - qctrl->minimum)) /
-				shutter_max + qctrl->minimum;
-		}
+	if (ret >= 0 && v4l2_ctrl_g_ctrl(mt9t031->autoexposure) == V4L2_EXPOSURE_AUTO) {
+		mt9t031->total_h = rect->height + mt9t031->y_skip_top + vblank;
+
+		ret = set_shutter(client, mt9t031->total_h);
 	}
 
 	/* Re-enable register update, commit all changes */
@@ -543,71 +456,57 @@
 }
 #endif
 
-static int mt9t031_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9t031_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct mt9t031 *mt9t031 = to_mt9t031(client);
-	int data;
+	struct mt9t031 *mt9t031 = container_of(ctrl->handler,
+					       struct mt9t031, hdl);
+	const u32 shutter_max = MT9T031_MAX_HEIGHT + MT9T031_VERTICAL_BLANK;
+	s32 min, max;
 
 	switch (ctrl->id) {
-	case V4L2_CID_VFLIP:
-		data = reg_read(client, MT9T031_READ_MODE_2);
-		if (data < 0)
-			return -EIO;
-		ctrl->value = !!(data & 0x8000);
-		break;
-	case V4L2_CID_HFLIP:
-		data = reg_read(client, MT9T031_READ_MODE_2);
-		if (data < 0)
-			return -EIO;
-		ctrl->value = !!(data & 0x4000);
-		break;
 	case V4L2_CID_EXPOSURE_AUTO:
-		ctrl->value = mt9t031->autoexposure;
-		break;
-	case V4L2_CID_GAIN:
-		ctrl->value = mt9t031->gain;
-		break;
-	case V4L2_CID_EXPOSURE:
-		ctrl->value = mt9t031->exposure;
+		min = mt9t031->exposure->minimum;
+		max = mt9t031->exposure->maximum;
+		mt9t031->exposure->val =
+			(shutter_max / 2 + (mt9t031->total_h - 1) * (max - min))
+				/ shutter_max + min;
 		break;
 	}
 	return 0;
 }
 
-static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9t031_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct mt9t031 *mt9t031 = container_of(ctrl->handler,
+					       struct mt9t031, hdl);
+	struct v4l2_subdev *sd = &mt9t031->subdev;
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct mt9t031 *mt9t031 = to_mt9t031(client);
-	const struct v4l2_queryctrl *qctrl;
+	struct v4l2_ctrl *exp = mt9t031->exposure;
 	int data;
 
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
-		if (ctrl->value)
+		if (ctrl->val)
 			data = reg_set(client, MT9T031_READ_MODE_2, 0x8000);
 		else
 			data = reg_clear(client, MT9T031_READ_MODE_2, 0x8000);
 		if (data < 0)
 			return -EIO;
-		break;
+		return 0;
 	case V4L2_CID_HFLIP:
-		if (ctrl->value)
+		if (ctrl->val)
 			data = reg_set(client, MT9T031_READ_MODE_2, 0x4000);
 		else
 			data = reg_clear(client, MT9T031_READ_MODE_2, 0x4000);
 		if (data < 0)
 			return -EIO;
-		break;
+		return 0;
 	case V4L2_CID_GAIN:
-		qctrl = &mt9t031_controls[MT9T031_CTRL_GAIN];
-		if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
-			return -EINVAL;
 		/* See Datasheet Table 7, Gain settings. */
-		if (ctrl->value <= qctrl->default_value) {
+		if (ctrl->val <= ctrl->default_value) {
 			/* Pack it into 0..1 step 0.125, register values 0..8 */
-			unsigned long range = qctrl->default_value - qctrl->minimum;
-			data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range;
+			unsigned long range = ctrl->default_value - ctrl->minimum;
+			data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
 
 			dev_dbg(&client->dev, "Setting gain %d\n", data);
 			data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
@@ -616,9 +515,9 @@
 		} else {
 			/* Pack it into 1.125..128 variable step, register values 9..0x7860 */
 			/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
-			unsigned long range = qctrl->maximum - qctrl->default_value - 1;
+			unsigned long range = ctrl->maximum - ctrl->default_value - 1;
 			/* calculated gain: map 65..127 to 9..1024 step 0.125 */
-			unsigned long gain = ((ctrl->value - qctrl->default_value - 1) *
+			unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
 					       1015 + range / 2) / range + 9;
 
 			if (gain <= 32)		/* calculated gain 9..32 -> 9..32 */
@@ -635,19 +534,13 @@
 			if (data < 0)
 				return -EIO;
 		}
+		return 0;
 
-		/* Success */
-		mt9t031->gain = ctrl->value;
-		break;
-	case V4L2_CID_EXPOSURE:
-		qctrl = &mt9t031_controls[MT9T031_CTRL_EXPOSURE];
-		/* mt9t031 has maximum == default */
-		if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
-			return -EINVAL;
-		else {
-			const unsigned long range = qctrl->maximum - qctrl->minimum;
-			const u32 shutter = ((ctrl->value - qctrl->minimum) * 1048 +
-					     range / 2) / range + 1;
+	case V4L2_CID_EXPOSURE_AUTO:
+		if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
+			unsigned int range = exp->maximum - exp->minimum;
+			unsigned int shutter = ((exp->val - exp->minimum) * 1048 +
+						 range / 2) / range + 1;
 			u32 old;
 
 			get_shutter(client, &old);
@@ -655,27 +548,15 @@
 				old, shutter);
 			if (set_shutter(client, shutter) < 0)
 				return -EIO;
-			mt9t031->exposure = ctrl->value;
-			mt9t031->autoexposure = 0;
-		}
-		break;
-	case V4L2_CID_EXPOSURE_AUTO:
-		if (ctrl->value) {
+		} else {
 			const u16 vblank = MT9T031_VERTICAL_BLANK;
-			const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
-			unsigned int total_h = mt9t031->rect.height +
+			mt9t031->total_h = mt9t031->rect.height +
 				mt9t031->y_skip_top + vblank;
 
-			if (set_shutter(client, total_h) < 0)
+			if (set_shutter(client, mt9t031->total_h) < 0)
 				return -EIO;
-			qctrl = &mt9t031_controls[MT9T031_CTRL_EXPOSURE];
-			mt9t031->exposure = (shutter_max / 2 + (total_h - 1) *
-				 (qctrl->maximum - qctrl->minimum)) /
-				shutter_max + qctrl->minimum;
-			mt9t031->autoexposure = 1;
-		} else
-			mt9t031->autoexposure = 0;
-		break;
+		}
+		return 0;
 	default:
 		return -EINVAL;
 	}
@@ -700,8 +581,7 @@
 static int mt9t031_runtime_resume(struct device *dev)
 {
 	struct video_device *vdev = to_video_device(dev);
-	struct soc_camera_device *icd = dev_get_drvdata(vdev->parent);
-	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+	struct v4l2_subdev *sd = soc_camera_vdev_to_subdev(vdev);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct mt9t031 *mt9t031 = to_mt9t031(client);
 
@@ -734,6 +614,19 @@
 	.pm	= &mt9t031_dev_pm_ops,
 };
 
+static int mt9t031_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct video_device *vdev = soc_camera_i2c_to_vdev(client);
+
+	if (on)
+		vdev->dev.type = &mt9t031_dev_type;
+	else
+		vdev->dev.type = NULL;
+
+	return 0;
+}
+
 /*
  * Interface active, can use i2c. If it fails, it can indeed mean, that
  * this wasn't our capture interface, so, we wait for the right one
@@ -741,7 +634,6 @@
 static int mt9t031_video_probe(struct i2c_client *client)
 {
 	struct mt9t031 *mt9t031 = to_mt9t031(client);
-	struct video_device *vdev = soc_camera_i2c_to_vdev(client);
 	s32 data;
 	int ret;
 
@@ -768,11 +660,7 @@
 	if (ret < 0)
 		dev_err(&client->dev, "Failed to initialise the camera\n");
 	else
-		vdev->dev.type = &mt9t031_dev_type;
-
-	/* mt9t031_idle() has reset the chip to default. */
-	mt9t031->exposure = 255;
-	mt9t031->gain = 64;
+		v4l2_ctrl_handler_setup(&mt9t031->hdl);
 
 	return ret;
 }
@@ -787,10 +675,14 @@
 	return 0;
 }
 
+static const struct v4l2_ctrl_ops mt9t031_ctrl_ops = {
+	.g_volatile_ctrl = mt9t031_g_volatile_ctrl,
+	.s_ctrl = mt9t031_s_ctrl,
+};
+
 static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = {
-	.g_ctrl		= mt9t031_g_ctrl,
-	.s_ctrl		= mt9t031_s_ctrl,
 	.g_chip_ident	= mt9t031_g_chip_ident,
+	.s_power	= mt9t031_s_power,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register	= mt9t031_g_register,
 	.s_register	= mt9t031_s_register,
@@ -807,6 +699,34 @@
 	return 0;
 }
 
+static int mt9t031_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |
+		V4L2_MBUS_PCLK_SAMPLE_FALLING | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static int mt9t031_s_mbus_config(struct v4l2_subdev *sd,
+				const struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	if (soc_camera_apply_board_flags(icl, cfg) &
+	    V4L2_MBUS_PCLK_SAMPLE_FALLING)
+		return reg_clear(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
+	else
+		return reg_set(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
+}
+
 static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = {
 	.s_stream	= mt9t031_s_stream,
 	.s_mbus_fmt	= mt9t031_s_fmt,
@@ -816,6 +736,8 @@
 	.g_crop		= mt9t031_g_crop,
 	.cropcap	= mt9t031_cropcap,
 	.enum_mbus_fmt	= mt9t031_enum_fmt,
+	.g_mbus_config	= mt9t031_g_mbus_config,
+	.s_mbus_config	= mt9t031_s_mbus_config,
 };
 
 static struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = {
@@ -832,18 +754,13 @@
 			 const struct i2c_device_id *did)
 {
 	struct mt9t031 *mt9t031;
-	struct soc_camera_device *icd = client->dev.platform_data;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
 	int ret;
 
-	if (icd) {
-		struct soc_camera_link *icl = to_soc_camera_link(icd);
-		if (!icl) {
-			dev_err(&client->dev, "MT9T031 driver needs platform data\n");
-			return -EINVAL;
-		}
-
-		icd->ops = &mt9t031_ops;
+	if (!icl) {
+		dev_err(&client->dev, "MT9T031 driver needs platform data\n");
+		return -EINVAL;
 	}
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
@@ -857,6 +774,33 @@
 		return -ENOMEM;
 
 	v4l2_i2c_subdev_init(&mt9t031->subdev, client, &mt9t031_subdev_ops);
+	v4l2_ctrl_handler_init(&mt9t031->hdl, 5);
+	v4l2_ctrl_new_std(&mt9t031->hdl, &mt9t031_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9t031->hdl, &mt9t031_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9t031->hdl, &mt9t031_ctrl_ops,
+			V4L2_CID_GAIN, 0, 127, 1, 64);
+
+	/*
+	 * Simulated autoexposure. If enabled, we calculate shutter width
+	 * ourselves in the driver based on vertical blanking and frame width
+	 */
+	mt9t031->autoexposure = v4l2_ctrl_new_std_menu(&mt9t031->hdl,
+			&mt9t031_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
+			V4L2_EXPOSURE_AUTO);
+	mt9t031->exposure = v4l2_ctrl_new_std(&mt9t031->hdl, &mt9t031_ctrl_ops,
+			V4L2_CID_EXPOSURE, 1, 255, 1, 255);
+
+	mt9t031->subdev.ctrl_handler = &mt9t031->hdl;
+	if (mt9t031->hdl.error) {
+		int err = mt9t031->hdl.error;
+
+		kfree(mt9t031);
+		return err;
+	}
+	v4l2_ctrl_auto_cluster(2, &mt9t031->autoexposure,
+				V4L2_EXPOSURE_MANUAL, true);
 
 	mt9t031->y_skip_top	= 0;
 	mt9t031->rect.left	= MT9T031_COLUMN_SKIP;
@@ -864,12 +808,6 @@
 	mt9t031->rect.width	= MT9T031_MAX_WIDTH;
 	mt9t031->rect.height	= MT9T031_MAX_HEIGHT;
 
-	/*
-	 * Simulated autoexposure. If enabled, we calculate shutter width
-	 * ourselves in the driver based on vertical blanking and frame width
-	 */
-	mt9t031->autoexposure = 1;
-
 	mt9t031->xskip = 1;
 	mt9t031->yskip = 1;
 
@@ -880,8 +818,7 @@
 	mt9t031_disable(client);
 
 	if (ret) {
-		if (icd)
-			icd->ops = NULL;
+		v4l2_ctrl_handler_free(&mt9t031->hdl);
 		kfree(mt9t031);
 	}
 
@@ -891,10 +828,9 @@
 static int mt9t031_remove(struct i2c_client *client)
 {
 	struct mt9t031 *mt9t031 = to_mt9t031(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
 
-	if (icd)
-		icd->ops = NULL;
+	v4l2_device_unregister_subdev(&mt9t031->subdev);
+	v4l2_ctrl_handler_free(&mt9t031->hdl);
 	kfree(mt9t031);
 
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/media/video/mt9t112.c linux-libre-3.2-gnu/drivers/media/video/mt9t112.c
--- linux-libre-3.1-gnu/drivers/media/video/mt9t112.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/mt9t112.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,11 +22,11 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/videodev2.h>
 
 #include <media/mt9t112.h>
 #include <media/soc_camera.h>
-#include <media/soc_mediabus.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-common.h>
 
@@ -34,11 +34,7 @@
 /* #define EXT_CLOCK 24000000 */
 
 /************************************************************************
-
-
 			macro
-
-
 ************************************************************************/
 /*
  * frame size
@@ -80,17 +76,8 @@
 #define VAR8(id, offset) _VAR(id, offset, 0x8000)
 
 /************************************************************************
-
-
 			struct
-
-
 ************************************************************************/
-struct mt9t112_frame_size {
-	u16 width;
-	u16 height;
-};
-
 struct mt9t112_format {
 	enum v4l2_mbus_pixelcode code;
 	enum v4l2_colorspace colorspace;
@@ -102,21 +89,17 @@
 	struct v4l2_subdev		 subdev;
 	struct mt9t112_camera_info	*info;
 	struct i2c_client		*client;
-	struct soc_camera_device	 icd;
-	struct mt9t112_frame_size	 frame;
+	struct v4l2_rect		 frame;
 	const struct mt9t112_format	*format;
 	int				 model;
 	u32				 flags;
 /* for flags */
-#define INIT_DONE  (1<<0)
+#define INIT_DONE	(1 << 0)
+#define PCLK_RISING	(1 << 1)
 };
 
 /************************************************************************
-
-
 			supported format
-
-
 ************************************************************************/
 
 static const struct mt9t112_format mt9t112_cfmts[] = {
@@ -154,11 +137,7 @@
 };
 
 /************************************************************************
-
-
 			general function
-
-
 ************************************************************************/
 static struct mt9t112_priv *to_mt9t112(const struct i2c_client *client)
 {
@@ -326,50 +305,47 @@
 	n = (n >> 8) & 0x003f;
 
 	enable = ((6000 > ext) || (54000 < ext)) ? "X" : "";
-	dev_info(&client->dev, "EXTCLK          : %10u K %s\n", ext, enable);
+	dev_dbg(&client->dev, "EXTCLK          : %10u K %s\n", ext, enable);
 
 	vco = 2 * m * ext / (n+1);
 	enable = ((384000 > vco) || (768000 < vco)) ? "X" : "";
-	dev_info(&client->dev, "VCO             : %10u K %s\n", vco, enable);
+	dev_dbg(&client->dev, "VCO             : %10u K %s\n", vco, enable);
 
 	clk = vco / (p1+1) / (p2+1);
 	enable = (96000 < clk) ? "X" : "";
-	dev_info(&client->dev, "PIXCLK          : %10u K %s\n", clk, enable);
+	dev_dbg(&client->dev, "PIXCLK          : %10u K %s\n", clk, enable);
 
 	clk = vco / (p3+1);
 	enable = (768000 < clk) ? "X" : "";
-	dev_info(&client->dev, "MIPICLK         : %10u K %s\n", clk, enable);
+	dev_dbg(&client->dev, "MIPICLK         : %10u K %s\n", clk, enable);
 
 	clk = vco / (p6+1);
 	enable = (96000 < clk) ? "X" : "";
-	dev_info(&client->dev, "MCU CLK         : %10u K %s\n", clk, enable);
+	dev_dbg(&client->dev, "MCU CLK         : %10u K %s\n", clk, enable);
 
 	clk = vco / (p5+1);
 	enable = (54000 < clk) ? "X" : "";
-	dev_info(&client->dev, "SOC CLK         : %10u K %s\n", clk, enable);
+	dev_dbg(&client->dev, "SOC CLK         : %10u K %s\n", clk, enable);
 
 	clk = vco / (p4+1);
 	enable = (70000 < clk) ? "X" : "";
-	dev_info(&client->dev, "Sensor CLK      : %10u K %s\n", clk, enable);
+	dev_dbg(&client->dev, "Sensor CLK      : %10u K %s\n", clk, enable);
 
 	clk = vco / (p7+1);
-	dev_info(&client->dev, "External sensor : %10u K\n", clk);
+	dev_dbg(&client->dev, "External sensor : %10u K\n", clk);
 
 	clk = ext / (n+1);
 	enable = ((2000 > clk) || (24000 < clk)) ? "X" : "";
-	dev_info(&client->dev, "PFD             : %10u K %s\n", clk, enable);
+	dev_dbg(&client->dev, "PFD             : %10u K %s\n", clk, enable);
 
 	return 0;
 }
 #endif
 
-static void mt9t112_frame_check(u32 *width, u32 *height)
+static void mt9t112_frame_check(u32 *width, u32 *height, u32 *left, u32 *top)
 {
-	if (*width > MAX_WIDTH)
-		*width = MAX_WIDTH;
-
-	if (*height > MAX_HEIGHT)
-		*height = MAX_HEIGHT;
+	soc_camera_limit_side(left, width, 0, 0, MAX_WIDTH);
+	soc_camera_limit_side(top, height, 0, 0, MAX_HEIGHT);
 }
 
 static int mt9t112_set_a_frame_size(const struct i2c_client *client,
@@ -758,48 +734,7 @@
 }
 
 /************************************************************************
-
-
-			soc_camera_ops
-
-
-************************************************************************/
-static int mt9t112_set_bus_param(struct soc_camera_device *icd,
-				 unsigned long	flags)
-{
-	return 0;
-}
-
-static unsigned long mt9t112_query_bus_param(struct soc_camera_device *icd)
-{
-	struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
-	struct mt9t112_priv *priv = to_mt9t112(client);
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-	unsigned long flags = SOCAM_MASTER | SOCAM_VSYNC_ACTIVE_HIGH |
-		SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH;
-
-	flags |= (priv->info->flags & MT9T112_FLAG_PCLK_RISING_EDGE) ?
-		SOCAM_PCLK_SAMPLE_RISING : SOCAM_PCLK_SAMPLE_FALLING;
-
-	if (priv->info->flags & MT9T112_FLAG_DATAWIDTH_8)
-		flags |= SOCAM_DATAWIDTH_8;
-	else
-		flags |= SOCAM_DATAWIDTH_10;
-
-	return soc_camera_apply_sensor_flags(icl, flags);
-}
-
-static struct soc_camera_ops mt9t112_ops = {
-	.set_bus_param		= mt9t112_set_bus_param,
-	.query_bus_param	= mt9t112_query_bus_param,
-};
-
-/************************************************************************
-
-
 			v4l2_subdev_core_ops
-
-
 ************************************************************************/
 static int mt9t112_g_chip_ident(struct v4l2_subdev *sd,
 				struct v4l2_dbg_chip_ident *id)
@@ -850,11 +785,7 @@
 
 
 /************************************************************************
-
-
 			v4l2_subdev_video_ops
-
-
 ************************************************************************/
 static int mt9t112_s_stream(struct v4l2_subdev *sd, int enable)
 {
@@ -877,8 +808,7 @@
 	}
 
 	if (!(priv->flags & INIT_DONE)) {
-		u16 param = (MT9T112_FLAG_PCLK_RISING_EDGE &
-			     priv->info->flags) ? 0x0001 : 0x0000;
+		u16 param = PCLK_RISING & priv->flags ? 0x0001 : 0x0000;
 
 		ECHECKER(ret, mt9t112_init_camera(client));
 
@@ -910,19 +840,12 @@
 	return ret;
 }
 
-static int mt9t112_set_params(struct i2c_client *client, u32 width, u32 height,
+static int mt9t112_set_params(struct mt9t112_priv *priv,
+			      const struct v4l2_rect *rect,
 			      enum v4l2_mbus_pixelcode code)
 {
-	struct mt9t112_priv *priv = to_mt9t112(client);
 	int i;
 
-	priv->format = NULL;
-
-	/*
-	 * frame size check
-	 */
-	mt9t112_frame_check(&width, &height);
-
 	/*
 	 * get color format
 	 */
@@ -933,8 +856,13 @@
 	if (i == ARRAY_SIZE(mt9t112_cfmts))
 		return -EINVAL;
 
-	priv->frame.width  = (u16)width;
-	priv->frame.height = (u16)height;
+	priv->frame  = *rect;
+
+	/*
+	 * frame size check
+	 */
+	mt9t112_frame_check(&priv->frame.width, &priv->frame.height,
+			    &priv->frame.left, &priv->frame.top);
 
 	priv->format = mt9t112_cfmts + i;
 
@@ -945,9 +873,12 @@
 {
 	a->bounds.left			= 0;
 	a->bounds.top			= 0;
-	a->bounds.width			= VGA_WIDTH;
-	a->bounds.height		= VGA_HEIGHT;
-	a->defrect			= a->bounds;
+	a->bounds.width			= MAX_WIDTH;
+	a->bounds.height		= MAX_HEIGHT;
+	a->defrect.left			= 0;
+	a->defrect.top			= 0;
+	a->defrect.width		= VGA_WIDTH;
+	a->defrect.height		= VGA_HEIGHT;
 	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	a->pixelaspect.numerator	= 1;
 	a->pixelaspect.denominator	= 1;
@@ -957,11 +888,11 @@
 
 static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
-	a->c.left	= 0;
-	a->c.top	= 0;
-	a->c.width	= VGA_WIDTH;
-	a->c.height	= VGA_HEIGHT;
-	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9t112_priv *priv = to_mt9t112(client);
+
+	a->c	= priv->frame;
+	a->type	= V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
 	return 0;
 }
@@ -969,10 +900,10 @@
 static int mt9t112_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9t112_priv *priv = to_mt9t112(client);
 	struct v4l2_rect *rect = &a->c;
 
-	return mt9t112_set_params(client, rect->width, rect->height,
-				 V4L2_MBUS_FMT_UYVY8_2X8);
+	return mt9t112_set_params(priv, rect, priv->format->code);
 }
 
 static int mt9t112_g_fmt(struct v4l2_subdev *sd,
@@ -981,16 +912,9 @@
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct mt9t112_priv *priv = to_mt9t112(client);
 
-	if (!priv->format) {
-		int ret = mt9t112_set_params(client, VGA_WIDTH, VGA_HEIGHT,
-					     V4L2_MBUS_FMT_UYVY8_2X8);
-		if (ret < 0)
-			return ret;
-	}
-
 	mf->width	= priv->frame.width;
 	mf->height	= priv->frame.height;
-	/* TODO: set colorspace */
+	mf->colorspace	= priv->format->colorspace;
 	mf->code	= priv->format->code;
 	mf->field	= V4L2_FIELD_NONE;
 
@@ -1001,17 +925,42 @@
 			 struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9t112_priv *priv = to_mt9t112(client);
+	struct v4l2_rect rect = {
+		.width = mf->width,
+		.height = mf->height,
+		.left = priv->frame.left,
+		.top = priv->frame.top,
+	};
+	int ret;
 
-	/* TODO: set colorspace */
-	return mt9t112_set_params(client, mf->width, mf->height, mf->code);
+	ret = mt9t112_set_params(priv, &rect, mf->code);
+
+	if (!ret)
+		mf->colorspace = priv->format->colorspace;
+
+	return ret;
 }
 
 static int mt9t112_try_fmt(struct v4l2_subdev *sd,
 			   struct v4l2_mbus_framefmt *mf)
 {
-	mt9t112_frame_check(&mf->width, &mf->height);
+	unsigned int top, left;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mt9t112_cfmts); i++)
+		if (mt9t112_cfmts[i].code == mf->code)
+			break;
+
+	if (i == ARRAY_SIZE(mt9t112_cfmts)) {
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+		mf->colorspace = V4L2_COLORSPACE_JPEG;
+	} else {
+		mf->colorspace	= mt9t112_cfmts[i].colorspace;
+	}
+
+	mt9t112_frame_check(&mf->width, &mf->height, &left, &top);
 
-	/* TODO: set colorspace */
 	mf->field = V4L2_FIELD_NONE;
 
 	return 0;
@@ -1024,6 +973,35 @@
 		return -EINVAL;
 
 	*code = mt9t112_cfmts[index].code;
+
+	return 0;
+}
+
+static int mt9t112_g_mbus_config(struct v4l2_subdev *sd,
+				 struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_DATA_ACTIVE_HIGH |
+		V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static int mt9t112_s_mbus_config(struct v4l2_subdev *sd,
+				 const struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	struct mt9t112_priv *priv = to_mt9t112(client);
+
+	if (soc_camera_apply_board_flags(icl, cfg) & V4L2_MBUS_PCLK_SAMPLE_RISING)
+		priv->flags |= PCLK_RISING;
+
 	return 0;
 }
 
@@ -1036,31 +1014,24 @@
 	.g_crop		= mt9t112_g_crop,
 	.s_crop		= mt9t112_s_crop,
 	.enum_mbus_fmt	= mt9t112_enum_fmt,
+	.g_mbus_config	= mt9t112_g_mbus_config,
+	.s_mbus_config	= mt9t112_s_mbus_config,
 };
 
 /************************************************************************
-
-
 			i2c driver
-
-
 ************************************************************************/
 static struct v4l2_subdev_ops mt9t112_subdev_ops = {
 	.core	= &mt9t112_subdev_core_ops,
 	.video	= &mt9t112_subdev_video_ops,
 };
 
-static int mt9t112_camera_probe(struct soc_camera_device *icd,
-				struct i2c_client *client)
+static int mt9t112_camera_probe(struct i2c_client *client)
 {
 	struct mt9t112_priv *priv = to_mt9t112(client);
 	const char          *devname;
 	int                  chipid;
 
-	/* We must have a parent by now. And it cannot be a wrong one. */
-	BUG_ON(!icd->parent ||
-	       to_soc_camera_host(icd->parent)->nr != icd->iface);
-
 	/*
 	 * check and show chip ID
 	 */
@@ -1088,20 +1059,21 @@
 static int mt9t112_probe(struct i2c_client *client,
 			 const struct i2c_device_id *did)
 {
-	struct mt9t112_priv        *priv;
-	struct soc_camera_device   *icd = client->dev.platform_data;
-	struct soc_camera_link     *icl;
-	int                         ret;
+	struct mt9t112_priv *priv;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	struct v4l2_rect rect = {
+		.width = VGA_WIDTH,
+		.height = VGA_HEIGHT,
+		.left = (MAX_WIDTH - VGA_WIDTH) / 2,
+		.top = (MAX_HEIGHT - VGA_HEIGHT) / 2,
+	};
+	int ret;
 
-	if (!icd) {
-		dev_err(&client->dev, "mt9t112: missing soc-camera data!\n");
+	if (!icl || !icl->priv) {
+		dev_err(&client->dev, "mt9t112: missing platform data!\n");
 		return -EINVAL;
 	}
 
-	icl = to_soc_camera_link(icd);
-	if (!icl || !icl->priv)
-		return -EINVAL;
-
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
@@ -1110,23 +1082,22 @@
 
 	v4l2_i2c_subdev_init(&priv->subdev, client, &mt9t112_subdev_ops);
 
-	icd->ops = &mt9t112_ops;
-
-	ret = mt9t112_camera_probe(icd, client);
+	ret = mt9t112_camera_probe(client);
 	if (ret) {
-		icd->ops = NULL;
 		kfree(priv);
+		return ret;
 	}
 
+	/* Cannot fail: using the default supported pixel code */
+	mt9t112_set_params(priv, &rect, V4L2_MBUS_FMT_UYVY8_2X8);
+
 	return ret;
 }
 
 static int mt9t112_remove(struct i2c_client *client)
 {
 	struct mt9t112_priv *priv = to_mt9t112(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
 
-	icd->ops = NULL;
 	kfree(priv);
 	return 0;
 }
@@ -1147,11 +1118,7 @@
 };
 
 /************************************************************************
-
-
 			module function
-
-
 ************************************************************************/
 static int __init mt9t112_module_init(void)
 {
diff -druN linux-libre-3.1-gnu/drivers/media/video/mt9v011.c linux-libre-3.2-gnu/drivers/media/video/mt9v011.c
--- linux-libre-3.1-gnu/drivers/media/video/mt9v011.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/mt9v011.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <asm/div64.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
diff -druN linux-libre-3.1-gnu/drivers/media/video/mt9v022.c linux-libre-3.2-gnu/drivers/media/video/mt9v022.c
--- linux-libre-3.1-gnu/drivers/media/video/mt9v022.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/mt9v022.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,10 +13,13 @@
 #include <linux/i2c.h>
 #include <linux/delay.h>
 #include <linux/log2.h>
+#include <linux/module.h>
 
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-chip-ident.h>
-#include <media/soc_camera.h>
+#include <media/v4l2-ctrls.h>
 
 /*
  * mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c
@@ -100,6 +103,17 @@
 
 struct mt9v022 {
 	struct v4l2_subdev subdev;
+	struct v4l2_ctrl_handler hdl;
+	struct {
+		/* exposure/auto-exposure cluster */
+		struct v4l2_ctrl *autoexposure;
+		struct v4l2_ctrl *exposure;
+	};
+	struct {
+		/* gain/auto-gain cluster */
+		struct v4l2_ctrl *autogain;
+		struct v4l2_ctrl *gain;
+	};
 	struct v4l2_rect rect;	/* Sensor window */
 	const struct mt9v022_datafmt *fmt;
 	const struct mt9v022_datafmt *fmts;
@@ -178,6 +192,8 @@
 		ret = reg_clear(client, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
 	if (!ret)
 		ret = reg_write(client, MT9V022_DIGITAL_TEST_PATTERN, 0);
+	if (!ret)
+		return v4l2_ctrl_handler_setup(&mt9v022->hdl);
 
 	return ret;
 }
@@ -199,78 +215,6 @@
 	return 0;
 }
 
-static int mt9v022_set_bus_param(struct soc_camera_device *icd,
-				 unsigned long flags)
-{
-	struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
-	struct mt9v022 *mt9v022 = to_mt9v022(client);
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-	unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
-	int ret;
-	u16 pixclk = 0;
-
-	/* Only one width bit may be set */
-	if (!is_power_of_2(width_flag))
-		return -EINVAL;
-
-	if (icl->set_bus_param) {
-		ret = icl->set_bus_param(icl, width_flag);
-		if (ret)
-			return ret;
-	} else {
-		/*
-		 * Without board specific bus width settings we only support the
-		 * sensors native bus width
-		 */
-		if (width_flag != SOCAM_DATAWIDTH_10)
-			return -EINVAL;
-	}
-
-	flags = soc_camera_apply_sensor_flags(icl, flags);
-
-	if (flags & SOCAM_PCLK_SAMPLE_FALLING)
-		pixclk |= 0x10;
-
-	if (!(flags & SOCAM_HSYNC_ACTIVE_HIGH))
-		pixclk |= 0x1;
-
-	if (!(flags & SOCAM_VSYNC_ACTIVE_HIGH))
-		pixclk |= 0x2;
-
-	ret = reg_write(client, MT9V022_PIXCLK_FV_LV, pixclk);
-	if (ret < 0)
-		return ret;
-
-	if (!(flags & SOCAM_MASTER))
-		mt9v022->chip_control &= ~0x8;
-
-	ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
-	if (ret < 0)
-		return ret;
-
-	dev_dbg(&client->dev, "Calculated pixclk 0x%x, chip control 0x%x\n",
-		pixclk, mt9v022->chip_control);
-
-	return 0;
-}
-
-static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
-{
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-	unsigned int flags = SOCAM_MASTER | SOCAM_SLAVE |
-		SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING |
-		SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW |
-		SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |
-		SOCAM_DATA_ACTIVE_HIGH;
-
-	if (icl->query_bus_param)
-		flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK;
-	else
-		flags |= SOCAM_DATAWIDTH_10;
-
-	return soc_camera_apply_sensor_flags(icl, flags);
-}
-
 static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -389,7 +333,7 @@
 
 	/*
 	 * The caller provides a supported format, as verified per call to
-	 * icd->try_fmt(), datawidth is from our supported format list
+	 * .try_mbus_fmt(), datawidth is from our supported format list
 	 */
 	switch (mf->code) {
 	case V4L2_MBUS_FMT_Y8_1X8:
@@ -502,236 +446,131 @@
 }
 #endif
 
-static const struct v4l2_queryctrl mt9v022_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,
-	}, {
-		.id		= V4L2_CID_GAIN,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Analog Gain",
-		.minimum	= 64,
-		.maximum	= 127,
-		.step		= 1,
-		.default_value	= 64,
-		.flags		= V4L2_CTRL_FLAG_SLIDER,
-	}, {
-		.id		= V4L2_CID_EXPOSURE,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Exposure",
-		.minimum	= 1,
-		.maximum	= 255,
-		.step		= 1,
-		.default_value	= 255,
-		.flags		= V4L2_CTRL_FLAG_SLIDER,
-	}, {
-		.id		= V4L2_CID_AUTOGAIN,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Automatic Gain",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 1,
-	}, {
-		.id		= V4L2_CID_EXPOSURE_AUTO,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Automatic Exposure",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 1,
-	}
-};
-
-static struct soc_camera_ops mt9v022_ops = {
-	.set_bus_param		= mt9v022_set_bus_param,
-	.query_bus_param	= mt9v022_query_bus_param,
-	.controls		= mt9v022_controls,
-	.num_controls		= ARRAY_SIZE(mt9v022_controls),
-};
-
-static int mt9v022_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct mt9v022 *mt9v022 = container_of(ctrl->handler,
+					       struct mt9v022, hdl);
+	struct v4l2_subdev *sd = &mt9v022->subdev;
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	const struct v4l2_queryctrl *qctrl;
+	struct v4l2_ctrl *gain = mt9v022->gain;
+	struct v4l2_ctrl *exp = mt9v022->exposure;
 	unsigned long range;
 	int data;
 
-	qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
-
 	switch (ctrl->id) {
-	case V4L2_CID_VFLIP:
-		data = reg_read(client, MT9V022_READ_MODE);
-		if (data < 0)
-			return -EIO;
-		ctrl->value = !!(data & 0x10);
-		break;
-	case V4L2_CID_HFLIP:
-		data = reg_read(client, MT9V022_READ_MODE);
-		if (data < 0)
-			return -EIO;
-		ctrl->value = !!(data & 0x20);
-		break;
-	case V4L2_CID_EXPOSURE_AUTO:
-		data = reg_read(client, MT9V022_AEC_AGC_ENABLE);
-		if (data < 0)
-			return -EIO;
-		ctrl->value = !!(data & 0x1);
-		break;
 	case V4L2_CID_AUTOGAIN:
-		data = reg_read(client, MT9V022_AEC_AGC_ENABLE);
-		if (data < 0)
-			return -EIO;
-		ctrl->value = !!(data & 0x2);
-		break;
-	case V4L2_CID_GAIN:
 		data = reg_read(client, MT9V022_ANALOG_GAIN);
 		if (data < 0)
 			return -EIO;
 
-		range = qctrl->maximum - qctrl->minimum;
-		ctrl->value = ((data - 16) * range + 24) / 48 + qctrl->minimum;
-
-		break;
-	case V4L2_CID_EXPOSURE:
+		range = gain->maximum - gain->minimum;
+		gain->val = ((data - 16) * range + 24) / 48 + gain->minimum;
+		return 0;
+	case V4L2_CID_EXPOSURE_AUTO:
 		data = reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH);
 		if (data < 0)
 			return -EIO;
 
-		range = qctrl->maximum - qctrl->minimum;
-		ctrl->value = ((data - 1) * range + 239) / 479 + qctrl->minimum;
-
-		break;
+		range = exp->maximum - exp->minimum;
+		exp->val = ((data - 1) * range + 239) / 479 + exp->minimum;
+		return 0;
 	}
-	return 0;
+	return -EINVAL;
 }
 
-static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	int data;
+	struct mt9v022 *mt9v022 = container_of(ctrl->handler,
+					       struct mt9v022, hdl);
+	struct v4l2_subdev *sd = &mt9v022->subdev;
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	const struct v4l2_queryctrl *qctrl;
-
-	qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
-	if (!qctrl)
-		return -EINVAL;
+	int data;
 
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
-		if (ctrl->value)
+		if (ctrl->val)
 			data = reg_set(client, MT9V022_READ_MODE, 0x10);
 		else
 			data = reg_clear(client, MT9V022_READ_MODE, 0x10);
 		if (data < 0)
 			return -EIO;
-		break;
+		return 0;
 	case V4L2_CID_HFLIP:
-		if (ctrl->value)
+		if (ctrl->val)
 			data = reg_set(client, MT9V022_READ_MODE, 0x20);
 		else
 			data = reg_clear(client, MT9V022_READ_MODE, 0x20);
 		if (data < 0)
 			return -EIO;
-		break;
-	case V4L2_CID_GAIN:
-		/* mt9v022 has minimum == default */
-		if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
-			return -EINVAL;
-		else {
-			unsigned long range = qctrl->maximum - qctrl->minimum;
+		return 0;
+	case V4L2_CID_AUTOGAIN:
+		if (ctrl->val) {
+			if (reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
+				return -EIO;
+		} else {
+			struct v4l2_ctrl *gain = mt9v022->gain;
+			/* mt9v022 has minimum == default */
+			unsigned long range = gain->maximum - gain->minimum;
 			/* Valid values 16 to 64, 32 to 64 must be even. */
-			unsigned long gain = ((ctrl->value - qctrl->minimum) *
+			unsigned long gain_val = ((gain->val - gain->minimum) *
 					      48 + range / 2) / range + 16;
-			if (gain >= 32)
-				gain &= ~1;
+
+			if (gain_val >= 32)
+				gain_val &= ~1;
+
 			/*
 			 * The user wants to set gain manually, hope, she
 			 * knows, what she's doing... Switch AGC off.
 			 */
-
 			if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
 				return -EIO;
 
 			dev_dbg(&client->dev, "Setting gain from %d to %lu\n",
-				reg_read(client, MT9V022_ANALOG_GAIN), gain);
-			if (reg_write(client, MT9V022_ANALOG_GAIN, gain) < 0)
+				reg_read(client, MT9V022_ANALOG_GAIN), gain_val);
+			if (reg_write(client, MT9V022_ANALOG_GAIN, gain_val) < 0)
 				return -EIO;
 		}
-		break;
-	case V4L2_CID_EXPOSURE:
-		/* mt9v022 has maximum == default */
-		if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
-			return -EINVAL;
-		else {
-			unsigned long range = qctrl->maximum - qctrl->minimum;
-			unsigned long shutter = ((ctrl->value - qctrl->minimum) *
-						 479 + range / 2) / range + 1;
+		return 0;
+	case V4L2_CID_EXPOSURE_AUTO:
+		if (ctrl->val == V4L2_EXPOSURE_AUTO) {
+			data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x1);
+		} else {
+			struct v4l2_ctrl *exp = mt9v022->exposure;
+			unsigned long range = exp->maximum - exp->minimum;
+			unsigned long shutter = ((exp->val - exp->minimum) *
+					479 + range / 2) / range + 1;
+
 			/*
 			 * The user wants to set shutter width manually, hope,
 			 * she knows, what she's doing... Switch AEC off.
 			 */
-
-			if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1) < 0)
+			data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1);
+			if (data < 0)
 				return -EIO;
-
 			dev_dbg(&client->dev, "Shutter width from %d to %lu\n",
-				reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH),
-				shutter);
+					reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH),
+					shutter);
 			if (reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
-				      shutter) < 0)
+						shutter) < 0)
 				return -EIO;
 		}
-		break;
-	case V4L2_CID_AUTOGAIN:
-		if (ctrl->value)
-			data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x2);
-		else
-			data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2);
-		if (data < 0)
-			return -EIO;
-		break;
-	case V4L2_CID_EXPOSURE_AUTO:
-		if (ctrl->value)
-			data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x1);
-		else
-			data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1);
-		if (data < 0)
-			return -EIO;
-		break;
+		return 0;
 	}
-	return 0;
+	return -EINVAL;
 }
 
 /*
  * Interface active, can use i2c. If it fails, it can indeed mean, that
  * this wasn't our capture interface, so, we wait for the right one
  */
-static int mt9v022_video_probe(struct soc_camera_device *icd,
-			       struct i2c_client *client)
+static int mt9v022_video_probe(struct i2c_client *client)
 {
 	struct mt9v022 *mt9v022 = to_mt9v022(client);
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 	s32 data;
 	int ret;
 	unsigned long flags;
 
-	/* We must have a parent by now. And it cannot be a wrong one. */
-	BUG_ON(!icd->parent ||
-	       to_soc_camera_host(icd->parent)->nr != icd->iface);
-
 	/* Read out the chip version register */
 	data = reg_read(client, MT9V022_CHIP_VERSION);
 
@@ -805,16 +644,6 @@
 	return ret;
 }
 
-static void mt9v022_video_remove(struct soc_camera_device *icd)
-{
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-
-	dev_dbg(icd->pdev, "Video removed: %p, %p\n",
-		icd->parent, icd->vdev);
-	if (icl->free_bus)
-		icl->free_bus(icl);
-}
-
 static int mt9v022_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -825,9 +654,12 @@
 	return 0;
 }
 
+static const struct v4l2_ctrl_ops mt9v022_ctrl_ops = {
+	.g_volatile_ctrl = mt9v022_g_volatile_ctrl,
+	.s_ctrl = mt9v022_s_ctrl,
+};
+
 static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = {
-	.g_ctrl		= mt9v022_g_ctrl,
-	.s_ctrl		= mt9v022_s_ctrl,
 	.g_chip_ident	= mt9v022_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register	= mt9v022_g_register,
@@ -848,6 +680,72 @@
 	return 0;
 }
 
+static int mt9v022_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE |
+		V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static int mt9v022_s_mbus_config(struct v4l2_subdev *sd,
+				 const struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+	unsigned long flags = soc_camera_apply_board_flags(icl, cfg);
+	unsigned int bps = soc_mbus_get_fmtdesc(mt9v022->fmt->code)->bits_per_sample;
+	int ret;
+	u16 pixclk = 0;
+
+	if (icl->set_bus_param) {
+		ret = icl->set_bus_param(icl, 1 << (bps - 1));
+		if (ret)
+			return ret;
+	} else if (bps != 10) {
+		/*
+		 * Without board specific bus width settings we only support the
+		 * sensors native bus width
+		 */
+		return -EINVAL;
+	}
+
+	if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
+		pixclk |= 0x10;
+
+	if (!(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH))
+		pixclk |= 0x1;
+
+	if (!(flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH))
+		pixclk |= 0x2;
+
+	ret = reg_write(client, MT9V022_PIXCLK_FV_LV, pixclk);
+	if (ret < 0)
+		return ret;
+
+	if (!(flags & V4L2_MBUS_MASTER))
+		mt9v022->chip_control &= ~0x8;
+
+	ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(&client->dev, "Calculated pixclk 0x%x, chip control 0x%x\n",
+		pixclk, mt9v022->chip_control);
+
+	return 0;
+}
+
 static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = {
 	.s_stream	= mt9v022_s_stream,
 	.s_mbus_fmt	= mt9v022_s_fmt,
@@ -857,6 +755,8 @@
 	.g_crop		= mt9v022_g_crop,
 	.cropcap	= mt9v022_cropcap,
 	.enum_mbus_fmt	= mt9v022_enum_fmt,
+	.g_mbus_config	= mt9v022_g_mbus_config,
+	.s_mbus_config	= mt9v022_s_mbus_config,
 };
 
 static struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = {
@@ -873,17 +773,10 @@
 			 const struct i2c_device_id *did)
 {
 	struct mt9v022 *mt9v022;
-	struct soc_camera_device *icd = client->dev.platform_data;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-	struct soc_camera_link *icl;
 	int ret;
 
-	if (!icd) {
-		dev_err(&client->dev, "MT9V022: missing soc-camera data!\n");
-		return -EINVAL;
-	}
-
-	icl = to_soc_camera_link(icd);
 	if (!icl) {
 		dev_err(&client->dev, "MT9V022 driver needs platform data\n");
 		return -EINVAL;
@@ -900,10 +793,39 @@
 		return -ENOMEM;
 
 	v4l2_i2c_subdev_init(&mt9v022->subdev, client, &mt9v022_subdev_ops);
+	v4l2_ctrl_handler_init(&mt9v022->hdl, 6);
+	v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	mt9v022->autogain = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+	mt9v022->gain = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+			V4L2_CID_GAIN, 0, 127, 1, 64);
+
+	/*
+	 * Simulated autoexposure. If enabled, we calculate shutter width
+	 * ourselves in the driver based on vertical blanking and frame width
+	 */
+	mt9v022->autoexposure = v4l2_ctrl_new_std_menu(&mt9v022->hdl,
+			&mt9v022_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
+			V4L2_EXPOSURE_AUTO);
+	mt9v022->exposure = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+			V4L2_CID_EXPOSURE, 1, 255, 1, 255);
+
+	mt9v022->subdev.ctrl_handler = &mt9v022->hdl;
+	if (mt9v022->hdl.error) {
+		int err = mt9v022->hdl.error;
+
+		kfree(mt9v022);
+		return err;
+	}
+	v4l2_ctrl_auto_cluster(2, &mt9v022->autoexposure,
+				V4L2_EXPOSURE_MANUAL, true);
+	v4l2_ctrl_auto_cluster(2, &mt9v022->autogain, 0, true);
 
 	mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
 
-	icd->ops		= &mt9v022_ops;
 	/*
 	 * MT9V022 _really_ corrupts the first read out line.
 	 * TODO: verify on i.MX31
@@ -914,9 +836,9 @@
 	mt9v022->rect.width	= MT9V022_MAX_WIDTH;
 	mt9v022->rect.height	= MT9V022_MAX_HEIGHT;
 
-	ret = mt9v022_video_probe(icd, client);
+	ret = mt9v022_video_probe(client);
 	if (ret) {
-		icd->ops = NULL;
+		v4l2_ctrl_handler_free(&mt9v022->hdl);
 		kfree(mt9v022);
 	}
 
@@ -926,10 +848,12 @@
 static int mt9v022_remove(struct i2c_client *client)
 {
 	struct mt9v022 *mt9v022 = to_mt9v022(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 
-	icd->ops = NULL;
-	mt9v022_video_remove(icd);
+	v4l2_device_unregister_subdev(&mt9v022->subdev);
+	if (icl->free_bus)
+		icl->free_bus(icl);
+	v4l2_ctrl_handler_free(&mt9v022->hdl);
 	kfree(mt9v022);
 
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/media/video/mt9v032.c linux-libre-3.2-gnu/drivers/media/video/mt9v032.c
--- linux-libre-3.1-gnu/drivers/media/video/mt9v032.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/mt9v032.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 #include <linux/v4l2-mediabus.h>
+#include <linux/module.h>
 
 #include <media/mt9v032.h>
 #include <media/v4l2-ctrls.h>
diff -druN linux-libre-3.1-gnu/drivers/media/video/mx1_camera.c linux-libre-3.2-gnu/drivers/media/video/mx1_camera.c
--- linux-libre-3.1-gnu/drivers/media/video/mx1_camera.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/mx1_camera.c	2012-01-04 18:55:44.000000000 -0500
@@ -78,11 +78,10 @@
 #define CSI_IRQ_MASK	(CSISR_SFF_OR_INT | CSISR_RFF_OR_INT | \
 			CSISR_STATFF_INT | CSISR_RXFF_INT | CSISR_SOF_INT)
 
-#define CSI_BUS_FLAGS	(SOCAM_MASTER | SOCAM_HSYNC_ACTIVE_HIGH | \
-			SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW | \
-			SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | \
-			SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_LOW | \
-			SOCAM_DATAWIDTH_8)
+#define CSI_BUS_FLAGS	(V4L2_MBUS_MASTER | V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
+			V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW | \
+			V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING | \
+			V4L2_MBUS_DATA_ACTIVE_HIGH | V4L2_MBUS_DATA_ACTIVE_LOW)
 
 #define MAX_VIDEO_MEM 16	/* Video memory limit in megabytes */
 
@@ -490,59 +489,73 @@
 
 static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
 {
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct mx1_camera_dev *pcdev = ici->priv;
-	unsigned long camera_flags, common_flags;
+	struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+	unsigned long common_flags;
 	unsigned int csicr1;
 	int ret;
 
-	camera_flags = icd->ops->query_bus_param(icd);
-
 	/* MX1 supports only 8bit buswidth */
-	common_flags = soc_camera_bus_param_compatible(camera_flags,
-						       CSI_BUS_FLAGS);
-	if (!common_flags)
-		return -EINVAL;
+	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+	if (!ret) {
+		common_flags = soc_mbus_config_compatible(&cfg, CSI_BUS_FLAGS);
+		if (!common_flags) {
+			dev_warn(icd->parent,
+				 "Flags incompatible: camera 0x%x, host 0x%x\n",
+				 cfg.flags, CSI_BUS_FLAGS);
+			return -EINVAL;
+		}
+	} else if (ret != -ENOIOCTLCMD) {
+		return ret;
+	} else {
+		common_flags = CSI_BUS_FLAGS;
+	}
 
 	/* Make choises, based on platform choice */
-	if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
-		(common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
+	if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
+		(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
 			if (!pcdev->pdata ||
 			     pcdev->pdata->flags & MX1_CAMERA_VSYNC_HIGH)
-				common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
+				common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
 			else
-				common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
+				common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
 	}
 
-	if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
-		(common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+	if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
+		(common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
 			if (!pcdev->pdata ||
 			     pcdev->pdata->flags & MX1_CAMERA_PCLK_RISING)
-				common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+				common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
 			else
-				common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+				common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
 	}
 
-	if ((common_flags & SOCAM_DATA_ACTIVE_HIGH) &&
-		(common_flags & SOCAM_DATA_ACTIVE_LOW)) {
+	if ((common_flags & V4L2_MBUS_DATA_ACTIVE_HIGH) &&
+		(common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)) {
 			if (!pcdev->pdata ||
 			     pcdev->pdata->flags & MX1_CAMERA_DATA_HIGH)
-				common_flags &= ~SOCAM_DATA_ACTIVE_LOW;
+				common_flags &= ~V4L2_MBUS_DATA_ACTIVE_LOW;
 			else
-				common_flags &= ~SOCAM_DATA_ACTIVE_HIGH;
+				common_flags &= ~V4L2_MBUS_DATA_ACTIVE_HIGH;
 	}
 
-	ret = icd->ops->set_bus_param(icd, common_flags);
-	if (ret < 0)
+	cfg.flags = common_flags;
+	ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+	if (ret < 0 && ret != -ENOIOCTLCMD) {
+		dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n",
+			common_flags, ret);
 		return ret;
+	}
 
 	csicr1 = __raw_readl(pcdev->base + CSICR1);
 
-	if (common_flags & SOCAM_PCLK_SAMPLE_RISING)
+	if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
 		csicr1 |= CSICR1_REDGE;
-	if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH)
+	if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
 		csicr1 |= CSICR1_SOF_POL;
-	if (common_flags & SOCAM_DATA_ACTIVE_LOW)
+	if (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)
 		csicr1 |= CSICR1_DATA_POL;
 
 	__raw_writel(csicr1, pcdev->base + CSICR1);
diff -druN linux-libre-3.1-gnu/drivers/media/video/mx2_camera.c linux-libre-3.2-gnu/drivers/media/video/mx2_camera.c
--- linux-libre-3.1-gnu/drivers/media/video/mx2_camera.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/mx2_camera.c	2012-01-04 18:55:44.000000000 -0500
@@ -686,16 +686,15 @@
 			icd, &icd->video_lock);
 }
 
-#define MX2_BUS_FLAGS	(SOCAM_DATAWIDTH_8 | \
-			SOCAM_MASTER | \
-			SOCAM_VSYNC_ACTIVE_HIGH | \
-			SOCAM_VSYNC_ACTIVE_LOW | \
-			SOCAM_HSYNC_ACTIVE_HIGH | \
-			SOCAM_HSYNC_ACTIVE_LOW | \
-			SOCAM_PCLK_SAMPLE_RISING | \
-			SOCAM_PCLK_SAMPLE_FALLING | \
-			SOCAM_DATA_ACTIVE_HIGH | \
-			SOCAM_DATA_ACTIVE_LOW)
+#define MX2_BUS_FLAGS	(V4L2_MBUS_MASTER | \
+			V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
+			V4L2_MBUS_VSYNC_ACTIVE_LOW | \
+			V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
+			V4L2_MBUS_HSYNC_ACTIVE_LOW | \
+			V4L2_MBUS_PCLK_SAMPLE_RISING | \
+			V4L2_MBUS_PCLK_SAMPLE_FALLING | \
+			V4L2_MBUS_DATA_ACTIVE_HIGH | \
+			V4L2_MBUS_DATA_ACTIVE_LOW)
 
 static int mx27_camera_emma_prp_reset(struct mx2_camera_dev *pcdev)
 {
@@ -770,46 +769,59 @@
 static int mx2_camera_set_bus_param(struct soc_camera_device *icd,
 		__u32 pixfmt)
 {
-	struct soc_camera_host *ici =
-		to_soc_camera_host(icd->parent);
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct mx2_camera_dev *pcdev = ici->priv;
-	unsigned long camera_flags, common_flags;
-	int ret = 0;
+	struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+	unsigned long common_flags;
+	int ret;
 	int bytesperline;
 	u32 csicr1 = pcdev->csicr1;
 
-	camera_flags = icd->ops->query_bus_param(icd);
-
-	common_flags = soc_camera_bus_param_compatible(camera_flags,
-				MX2_BUS_FLAGS);
-	if (!common_flags)
-		return -EINVAL;
+	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+	if (!ret) {
+		common_flags = soc_mbus_config_compatible(&cfg, MX2_BUS_FLAGS);
+		if (!common_flags) {
+			dev_warn(icd->parent,
+				 "Flags incompatible: camera 0x%x, host 0x%x\n",
+				 cfg.flags, MX2_BUS_FLAGS);
+			return -EINVAL;
+		}
+	} else if (ret != -ENOIOCTLCMD) {
+		return ret;
+	} else {
+		common_flags = MX2_BUS_FLAGS;
+	}
 
-	if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
-	    (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+	if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
+	    (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
 		if (pcdev->platform_flags & MX2_CAMERA_HSYNC_HIGH)
-			common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
 		else
-			common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
 	}
 
-	if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
-	    (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+	if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
+	    (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
 		if (pcdev->platform_flags & MX2_CAMERA_PCLK_SAMPLE_RISING)
-			common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+			common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
 		else
-			common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+			common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
 	}
 
-	ret = icd->ops->set_bus_param(icd, common_flags);
-	if (ret < 0)
+	cfg.flags = common_flags;
+	ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+	if (ret < 0 && ret != -ENOIOCTLCMD) {
+		dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n",
+			common_flags, ret);
 		return ret;
+	}
 
-	if (common_flags & SOCAM_PCLK_SAMPLE_RISING)
+	if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
 		csicr1 |= CSICR1_REDGE;
-	if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH)
+	if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
 		csicr1 |= CSICR1_SOF_POL;
-	if (common_flags & SOCAM_HSYNC_ACTIVE_HIGH)
+	if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
 		csicr1 |= CSICR1_HSYNC_POL;
 	if (pcdev->platform_flags & MX2_CAMERA_SWAP16)
 		csicr1 |= CSICR1_SWAP16_EN;
diff -druN linux-libre-3.1-gnu/drivers/media/video/mx3_camera.c linux-libre-3.2-gnu/drivers/media/video/mx3_camera.c
--- linux-libre-3.1-gnu/drivers/media/video/mx3_camera.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/mx3_camera.c	2012-01-04 18:55:44.000000000 -0500
@@ -109,10 +109,12 @@
 
 	unsigned long		platform_flags;
 	unsigned long		mclk;
+	u16			width_flags;	/* max 15 bits */
 
 	struct list_head	capture;
 	spinlock_t		lock;		/* Protects video buffer lists */
 	struct mx3_camera_buffer *active;
+	size_t			buf_total;
 	struct vb2_alloc_ctx	*alloc_ctx;
 	enum v4l2_field		field;
 	int			sequence;
@@ -190,79 +192,53 @@
  * Calculate the __buffer__ (not data) size and number of buffers.
  */
 static int mx3_videobuf_setup(struct vb2_queue *vq,
+			const struct v4l2_format *fmt,
 			unsigned int *count, unsigned int *num_planes,
-			unsigned long sizes[], void *alloc_ctxs[])
+			unsigned int sizes[], void *alloc_ctxs[])
 {
 	struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct mx3_camera_dev *mx3_cam = ici->priv;
-	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;
+	int bytes_per_line;
+	unsigned int height;
 
 	if (!mx3_cam->idmac_channel[0])
 		return -EINVAL;
 
-	*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 (sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024)
-		*count = MAX_VIDEO_MEM * 1024 * 1024 / sizes[0];
-
-	return 0;
-}
-
-static int mx3_videobuf_prepare(struct vb2_buffer *vb)
-{
-	struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
-	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-	struct mx3_camera_dev *mx3_cam = ici->priv;
-	struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
-	struct scatterlist *sg;
-	struct mx3_camera_buffer *buf;
-	size_t new_size;
-	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+	if (fmt) {
+		const struct soc_camera_format_xlate *xlate = soc_camera_xlate_by_fourcc(icd,
+								fmt->fmt.pix.pixelformat);
+		if (!xlate)
+			return -EINVAL;
+		bytes_per_line = soc_mbus_bytes_per_line(fmt->fmt.pix.width,
+							 xlate->host_fmt);
+		height = fmt->fmt.pix.height;
+	} else {
+		/* Called from VIDIOC_REQBUFS or in compatibility mode */
+		bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
 						icd->current_fmt->host_fmt);
-
+		height = icd->user_height;
+	}
 	if (bytes_per_line < 0)
 		return bytes_per_line;
 
-	buf = to_mx3_vb(vb);
-	sg = &buf->sg;
-
-	new_size = bytes_per_line * icd->user_height;
-
-	if (vb2_plane_size(vb, 0) < new_size) {
-		dev_err(icd->parent, "Buffer too small (%lu < %zu)\n",
-			vb2_plane_size(vb, 0), new_size);
-		return -ENOBUFS;
-	}
+	sizes[0] = bytes_per_line * height;
 
-	if (buf->state == CSI_BUF_NEEDS_INIT) {
-		sg_dma_address(sg)	= vb2_dma_contig_plane_paddr(vb, 0);
-		sg_dma_len(sg)		= new_size;
+	alloc_ctxs[0] = mx3_cam->alloc_ctx;
 
-		buf->txd = ichan->dma_chan.device->device_prep_slave_sg(
-			&ichan->dma_chan, sg, 1, DMA_FROM_DEVICE,
-			DMA_PREP_INTERRUPT);
-		if (!buf->txd)
-			return -EIO;
+	if (!vq->num_buffers)
+		mx3_cam->sequence = 0;
 
-		buf->txd->callback_param	= buf->txd;
-		buf->txd->callback		= mx3_cam_dma_done;
+	if (!*count)
+		*count = 2;
 
-		buf->state = CSI_BUF_PREPARED;
-	}
+	/* If *num_planes != 0, we have already verified *count. */
+	if (!*num_planes &&
+	    sizes[0] * *count + mx3_cam->buf_total > MAX_VIDEO_MEM * 1024 * 1024)
+		*count = (MAX_VIDEO_MEM * 1024 * 1024 - mx3_cam->buf_total) /
+			sizes[0];
 
-	vb2_set_plane_payload(vb, 0, new_size);
+	*num_planes = 1;
 
 	return 0;
 }
@@ -286,28 +262,58 @@
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct mx3_camera_dev *mx3_cam = ici->priv;
 	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 scatterlist *sg = &buf->sg;
+	struct dma_async_tx_descriptor *txd;
+	struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
 	struct idmac_video_param *video = &ichan->params.video;
-	dma_cookie_t cookie;
-	u32 fourcc = icd->current_fmt->host_fmt->fourcc;
+	const struct soc_mbus_pixelfmt *host_fmt = icd->current_fmt->host_fmt;
+	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, host_fmt);
 	unsigned long flags;
+	dma_cookie_t cookie;
+	size_t new_size;
+
+	BUG_ON(bytes_per_line <= 0);
+
+	new_size = bytes_per_line * icd->user_height;
+
+	if (vb2_plane_size(vb, 0) < new_size) {
+		dev_err(icd->parent, "Buffer #%d too small (%lu < %zu)\n",
+			vb->v4l2_buf.index, vb2_plane_size(vb, 0), new_size);
+		goto error;
+	}
+
+	if (buf->state == CSI_BUF_NEEDS_INIT) {
+		sg_dma_address(sg)	= vb2_dma_contig_plane_dma_addr(vb, 0);
+		sg_dma_len(sg)		= new_size;
+
+		txd = ichan->dma_chan.device->device_prep_slave_sg(
+			&ichan->dma_chan, sg, 1, DMA_FROM_DEVICE,
+			DMA_PREP_INTERRUPT);
+		if (!txd)
+			goto error;
+
+		txd->callback_param	= txd;
+		txd->callback		= mx3_cam_dma_done;
+
+		buf->state		= CSI_BUF_PREPARED;
+		buf->txd		= txd;
+	} else {
+		txd = buf->txd;
+	}
+
+	vb2_set_plane_payload(vb, 0, new_size);
 
 	/* This is the configuration of one sg-element */
-	video->out_pixel_fmt	= fourcc_to_ipu_pix(fourcc);
+	video->out_pixel_fmt = fourcc_to_ipu_pix(host_fmt->fourcc);
 
 	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.
+		 * If the IPU DMA channel is configured to transfer generic
+		 * 8-bit data, we have to set up the geometry parameters
+		 * correctly, according to the current pixel format. The DMA
+		 * horizontal parameters in this case are expressed in bytes,
+		 * not in pixels.
 		 */
-		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;
@@ -351,6 +357,7 @@
 		mx3_cam->active = NULL;
 
 	spin_unlock_irqrestore(&mx3_cam->lock, flags);
+error:
 	vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 }
 
@@ -384,17 +391,24 @@
 	}
 
 	spin_unlock_irqrestore(&mx3_cam->lock, flags);
+
+	mx3_cam->buf_total -= vb2_plane_size(vb, 0);
 }
 
 static int mx3_videobuf_init(struct vb2_buffer *vb)
 {
+	struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mx3_camera_dev *mx3_cam = ici->priv;
 	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;
+
+	mx3_cam->buf_total += vb2_plane_size(vb, 0);
 
 	return 0;
 }
@@ -405,13 +419,12 @@
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct mx3_camera_dev *mx3_cam = ici->priv;
 	struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
-	struct dma_chan *chan;
 	struct mx3_camera_buffer *buf, *tmp;
 	unsigned long flags;
 
 	if (ichan) {
-		chan = &ichan->dma_chan;
-		chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
+		struct dma_chan *chan = &ichan->dma_chan;
+		chan->device->device_control(chan, DMA_PAUSE, 0);
 	}
 
 	spin_lock_irqsave(&mx3_cam->lock, flags);
@@ -419,8 +432,8 @@
 	mx3_cam->active = NULL;
 
 	list_for_each_entry_safe(buf, tmp, &mx3_cam->capture, queue) {
-		buf->state = CSI_BUF_NEEDS_INIT;
 		list_del_init(&buf->queue);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
 	}
 
 	spin_unlock_irqrestore(&mx3_cam->lock, flags);
@@ -430,7 +443,6 @@
 
 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,
@@ -514,6 +526,7 @@
 
 	mx3_camera_activate(mx3_cam, icd);
 
+	mx3_cam->buf_total = 0;
 	mx3_cam->icd = icd;
 
 	dev_info(icd->parent, "MX3 Camera driver attached to camera %d\n",
@@ -548,58 +561,27 @@
 			       unsigned char buswidth, unsigned long *flags)
 {
 	/*
+	 * If requested data width is supported by the platform, use it or any
+	 * possible lower value - i.MX31 is smart enough to shift bits
+	 */
+	if (buswidth > fls(mx3_cam->width_flags))
+		return -EINVAL;
+
+	/*
 	 * Platform specified synchronization and pixel clock polarities are
 	 * only a recommendation and are only used during probing. MX3x
 	 * camera interface only works in master mode, i.e., uses HSYNC and
 	 * VSYNC signals from the sensor
 	 */
-	*flags = SOCAM_MASTER |
-		SOCAM_HSYNC_ACTIVE_HIGH |
-		SOCAM_HSYNC_ACTIVE_LOW |
-		SOCAM_VSYNC_ACTIVE_HIGH |
-		SOCAM_VSYNC_ACTIVE_LOW |
-		SOCAM_PCLK_SAMPLE_RISING |
-		SOCAM_PCLK_SAMPLE_FALLING |
-		SOCAM_DATA_ACTIVE_HIGH |
-		SOCAM_DATA_ACTIVE_LOW;
-
-	/*
-	 * If requested data width is supported by the platform, use it or any
-	 * possible lower value - i.MX31 is smart enough to schift bits
-	 */
-	if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15)
-		*flags |= SOCAM_DATAWIDTH_15 | SOCAM_DATAWIDTH_10 |
-			SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4;
-	else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10)
-		*flags |= SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8 |
-			SOCAM_DATAWIDTH_4;
-	else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8)
-		*flags |= SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4;
-	else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)
-		*flags |= SOCAM_DATAWIDTH_4;
-
-	switch (buswidth) {
-	case 15:
-		if (!(*flags & SOCAM_DATAWIDTH_15))
-			return -EINVAL;
-		break;
-	case 10:
-		if (!(*flags & SOCAM_DATAWIDTH_10))
-			return -EINVAL;
-		break;
-	case 8:
-		if (!(*flags & SOCAM_DATAWIDTH_8))
-			return -EINVAL;
-		break;
-	case 4:
-		if (!(*flags & SOCAM_DATAWIDTH_4))
-			return -EINVAL;
-		break;
-	default:
-		dev_warn(mx3_cam->soc_host.v4l2_dev.dev,
-			 "Unsupported bus width %d\n", buswidth);
-		return -EINVAL;
-	}
+	*flags = V4L2_MBUS_MASTER |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_HSYNC_ACTIVE_LOW |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_VSYNC_ACTIVE_LOW |
+		V4L2_MBUS_PCLK_SAMPLE_RISING |
+		V4L2_MBUS_PCLK_SAMPLE_FALLING |
+		V4L2_MBUS_DATA_ACTIVE_HIGH |
+		V4L2_MBUS_DATA_ACTIVE_LOW;
 
 	return 0;
 }
@@ -607,9 +589,11 @@
 static int mx3_camera_try_bus_param(struct soc_camera_device *icd,
 				    const unsigned int depth)
 {
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct mx3_camera_dev *mx3_cam = ici->priv;
-	unsigned long bus_flags, camera_flags;
+	struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+	unsigned long bus_flags, common_flags;
 	int ret = test_platform_param(mx3_cam, depth, &bus_flags);
 
 	dev_dbg(icd->parent, "request bus width %d bit: %d\n", depth, ret);
@@ -617,15 +601,21 @@
 	if (ret < 0)
 		return ret;
 
-	camera_flags = icd->ops->query_bus_param(icd);
-
-	ret = soc_camera_bus_param_compatible(camera_flags, bus_flags);
-	if (ret < 0)
-		dev_warn(icd->parent,
-			 "Flags incompatible: camera %lx, host %lx\n",
-			 camera_flags, bus_flags);
+	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+	if (!ret) {
+		common_flags = soc_mbus_config_compatible(&cfg,
+							  bus_flags);
+		if (!common_flags) {
+			dev_warn(icd->parent,
+				 "Flags incompatible: camera 0x%x, host 0x%lx\n",
+				 cfg.flags, bus_flags);
+			return -EINVAL;
+		}
+	} else if (ret != -ENOIOCTLCMD) {
+		return ret;
+	}
 
-	return ret;
+	return 0;
 }
 
 static bool chan_filter(struct dma_chan *chan, void *arg)
@@ -994,9 +984,11 @@
 
 static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
 {
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct mx3_camera_dev *mx3_cam = ici->priv;
-	unsigned long bus_flags, camera_flags, common_flags;
+	struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+	unsigned long bus_flags, common_flags;
 	u32 dw, sens_conf;
 	const struct soc_mbus_pixelfmt *fmt;
 	int buswidth;
@@ -1008,83 +1000,76 @@
 	if (!fmt)
 		return -EINVAL;
 
-	buswidth = fmt->bits_per_sample;
-	ret = test_platform_param(mx3_cam, buswidth, &bus_flags);
-
 	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
 	if (!xlate) {
 		dev_warn(dev, "Format %x not found\n", pixfmt);
 		return -EINVAL;
 	}
 
+	buswidth = fmt->bits_per_sample;
+	ret = test_platform_param(mx3_cam, buswidth, &bus_flags);
+
 	dev_dbg(dev, "requested bus width %d bit: %d\n", buswidth, ret);
 
 	if (ret < 0)
 		return ret;
 
-	camera_flags = icd->ops->query_bus_param(icd);
-
-	common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
-	dev_dbg(dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n",
-		camera_flags, bus_flags, common_flags);
-	if (!common_flags) {
-		dev_dbg(dev, "no common flags");
-		return -EINVAL;
+	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+	if (!ret) {
+		common_flags = soc_mbus_config_compatible(&cfg,
+							  bus_flags);
+		if (!common_flags) {
+			dev_warn(icd->parent,
+				 "Flags incompatible: camera 0x%x, host 0x%lx\n",
+				 cfg.flags, bus_flags);
+			return -EINVAL;
+		}
+	} else if (ret != -ENOIOCTLCMD) {
+		return ret;
+	} else {
+		common_flags = bus_flags;
 	}
 
+	dev_dbg(dev, "Flags cam: 0x%x host: 0x%lx common: 0x%lx\n",
+		cfg.flags, bus_flags, common_flags);
+
 	/* Make choices, based on platform preferences */
-	if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
-	    (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+	if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
+	    (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
 		if (mx3_cam->platform_flags & MX3_CAMERA_HSP)
-			common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
 		else
-			common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
 	}
 
-	if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
-	    (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
+	if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
+	    (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
 		if (mx3_cam->platform_flags & MX3_CAMERA_VSP)
-			common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
+			common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
 		else
-			common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
+			common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
 	}
 
-	if ((common_flags & SOCAM_DATA_ACTIVE_HIGH) &&
-	    (common_flags & SOCAM_DATA_ACTIVE_LOW)) {
+	if ((common_flags & V4L2_MBUS_DATA_ACTIVE_HIGH) &&
+	    (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)) {
 		if (mx3_cam->platform_flags & MX3_CAMERA_DP)
-			common_flags &= ~SOCAM_DATA_ACTIVE_HIGH;
+			common_flags &= ~V4L2_MBUS_DATA_ACTIVE_HIGH;
 		else
-			common_flags &= ~SOCAM_DATA_ACTIVE_LOW;
+			common_flags &= ~V4L2_MBUS_DATA_ACTIVE_LOW;
 	}
 
-	if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
-	    (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+	if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
+	    (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
 		if (mx3_cam->platform_flags & MX3_CAMERA_PCP)
-			common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+			common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
 		else
-			common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+			common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
 	}
 
-	/*
-	 * Make the camera work in widest common mode, we'll take care of
-	 * the rest
-	 */
-	if (common_flags & SOCAM_DATAWIDTH_15)
-		common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
-			SOCAM_DATAWIDTH_15;
-	else if (common_flags & SOCAM_DATAWIDTH_10)
-		common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
-			SOCAM_DATAWIDTH_10;
-	else if (common_flags & SOCAM_DATAWIDTH_8)
-		common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
-			SOCAM_DATAWIDTH_8;
-	else
-		common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
-			SOCAM_DATAWIDTH_4;
-
-	ret = icd->ops->set_bus_param(icd, common_flags);
-	if (ret < 0) {
-		dev_dbg(dev, "camera set_bus_param(%lx) returned %d\n",
+	cfg.flags = common_flags;
+	ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+	if (ret < 0 && ret != -ENOIOCTLCMD) {
+		dev_dbg(dev, "camera s_mbus_config(0x%lx) returned %d\n",
 			common_flags, ret);
 		return ret;
 	}
@@ -1108,13 +1093,13 @@
 	/* This has been set in mx3_camera_activate(), but we clear it above */
 	sens_conf |= CSI_SENS_CONF_DATA_FMT_BAYER;
 
-	if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
+	if (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
 		sens_conf |= 1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT;
-	if (common_flags & SOCAM_HSYNC_ACTIVE_LOW)
+	if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
 		sens_conf |= 1 << CSI_SENS_CONF_HSYNC_POL_SHIFT;
-	if (common_flags & SOCAM_VSYNC_ACTIVE_LOW)
+	if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
 		sens_conf |= 1 << CSI_SENS_CONF_VSYNC_POL_SHIFT;
-	if (common_flags & SOCAM_DATA_ACTIVE_LOW)
+	if (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)
 		sens_conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT;
 
 	/* Just do what we're asked to do */
@@ -1199,6 +1184,14 @@
 			 "data widths, using default 8 bit\n");
 		mx3_cam->platform_flags |= MX3_CAMERA_DATAWIDTH_8;
 	}
+	if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)
+		mx3_cam->width_flags = 1 << 3;
+	if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8)
+		mx3_cam->width_flags |= 1 << 7;
+	if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10)
+		mx3_cam->width_flags |= 1 << 9;
+	if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15)
+		mx3_cam->width_flags |= 1 << 14;
 
 	mx3_cam->mclk = mx3_cam->pdata->mclk_10khz * 10000;
 	if (!mx3_cam->mclk) {
@@ -1281,8 +1274,6 @@
 
 	dmaengine_put();
 
-	dev_info(&pdev->dev, "i.MX3x Camera driver unloaded\n");
-
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/mxb.c linux-libre-3.2-gnu/drivers/media/video/mxb.c
--- linux-libre-3.1-gnu/drivers/media/video/mxb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/mxb.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,12 +21,15 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define DEBUG_VARIABLE debug
 
 #include <media/saa7146_vv.h>
 #include <media/tuner.h>
 #include <media/v4l2-common.h>
 #include <media/saa7115.h>
+#include <linux/module.h>
 
 #include "mxb.h"
 #include "tea6415c.h"
@@ -171,7 +174,7 @@
 
 	mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
 	if (mxb == NULL) {
-		DEB_D(("not enough kernel memory.\n"));
+		DEB_D("not enough kernel memory\n");
 		return -ENOMEM;
 	}
 
@@ -179,7 +182,7 @@
 
 	saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
 	if (i2c_add_adapter(&mxb->i2c_adapter) < 0) {
-		DEB_S(("cannot register i2c-device. skipping.\n"));
+		DEB_S("cannot register i2c-device. skipping.\n");
 		kfree(mxb);
 		return -EFAULT;
 	}
@@ -200,7 +203,7 @@
 	/* check if all devices are present */
 	if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
 	    !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
-		printk("mxb: did not find all i2c devices. aborting\n");
+		pr_err("did not find all i2c devices. aborting\n");
 		i2c_del_adapter(&mxb->i2c_adapter);
 		kfree(mxb);
 		return -ENODEV;
@@ -346,11 +349,11 @@
 			msg.buf = &mxb_saa7740_init[i].data[0];
 			err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
 			if (err != 1) {
-				DEB_D(("failed to initialize 'sound arena module'.\n"));
+				DEB_D("failed to initialize 'sound arena module'\n");
 				goto err;
 			}
 		}
-		INFO(("'sound arena module' detected.\n"));
+		pr_info("'sound arena module' detected\n");
 	}
 err:
 	/* the rest for saa7146: you should definitely set some basic values
@@ -390,7 +393,7 @@
 	for (i = MAXCONTROLS - 1; i >= 0; i--) {
 		if (mxb_controls[i].id == qc->id) {
 			*qc = mxb_controls[i];
-			DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
+			DEB_D("VIDIOC_QUERYCTRL %d\n", qc->id);
 			return 0;
 		}
 	}
@@ -413,11 +416,11 @@
 
 	if (vc->id == V4L2_CID_AUDIO_MUTE) {
 		vc->value = mxb->cur_mute;
-		DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
+		DEB_D("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d\n", vc->value);
 		return 0;
 	}
 
-	DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
+	DEB_EE("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d\n", vc->value);
 	return 0;
 }
 
@@ -440,14 +443,14 @@
 		/* switch the audio-source */
 		tea6420_route_line(mxb, vc->value ? 6 :
 				video_audio_connect[mxb->cur_input]);
-		DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value));
+		DEB_EE("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d\n", vc->value);
 	}
 	return 0;
 }
 
 static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 {
-	DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
+	DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
 	if (i->index >= MXB_INPUTS)
 		return -EINVAL;
 	memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
@@ -460,7 +463,7 @@
 	struct mxb *mxb = (struct mxb *)dev->ext_priv;
 	*i = mxb->cur_input;
 
-	DEB_EE(("VIDIOC_G_INPUT %d.\n", *i));
+	DEB_EE("VIDIOC_G_INPUT %d\n", *i);
 	return 0;
 }
 
@@ -471,7 +474,7 @@
 	int err = 0;
 	int i = 0;
 
-	DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
+	DEB_EE("VIDIOC_S_INPUT %d\n", input);
 
 	if (input >= MXB_INPUTS)
 		return -EINVAL;
@@ -514,7 +517,7 @@
 
 	/* switch video in saa7111a */
 	if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0))
-		printk(KERN_ERR "VIDIOC_S_INPUT: could not address saa7111a.\n");
+		pr_err("VIDIOC_S_INPUT: could not address saa7111a\n");
 
 	/* switch the audio-source only if necessary */
 	if (0 == mxb->cur_mute)
@@ -529,11 +532,12 @@
 	struct mxb *mxb = (struct mxb *)dev->ext_priv;
 
 	if (t->index) {
-		DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index));
+		DEB_D("VIDIOC_G_TUNER: channel %d does not have a tuner attached\n",
+		      t->index);
 		return -EINVAL;
 	}
 
-	DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
+	DEB_EE("VIDIOC_G_TUNER: %d\n", t->index);
 
 	memset(t, 0, sizeof(*t));
 	strlcpy(t->name, "TV Tuner", sizeof(t->name));
@@ -550,7 +554,8 @@
 	struct mxb *mxb = (struct mxb *)dev->ext_priv;
 
 	if (t->index) {
-		DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n", t->index));
+		DEB_D("VIDIOC_S_TUNER: channel %d does not have a tuner attached\n",
+		      t->index);
 		return -EINVAL;
 	}
 
@@ -564,14 +569,14 @@
 	struct mxb *mxb = (struct mxb *)dev->ext_priv;
 
 	if (mxb->cur_input) {
-		DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",
-					mxb->cur_input));
+		DEB_D("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",
+		      mxb->cur_input);
 		return -EINVAL;
 	}
 
 	*f = mxb->cur_freq;
 
-	DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq.frequency));
+	DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency);
 	return 0;
 }
 
@@ -588,12 +593,13 @@
 		return -EINVAL;
 
 	if (mxb->cur_input) {
-		DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input));
+		DEB_D("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",
+		      mxb->cur_input);
 		return -EINVAL;
 	}
 
 	mxb->cur_freq = *f;
-	DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency));
+	DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency);
 
 	/* tune in desired frequency */
 	tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
@@ -612,18 +618,18 @@
 	struct mxb *mxb = (struct mxb *)dev->ext_priv;
 
 	if (a->index > MXB_INPUTS) {
-		DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index));
+		DEB_D("VIDIOC_G_AUDIO %d out of range\n", a->index);
 		return -EINVAL;
 	}
 
-	DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index));
+	DEB_EE("VIDIOC_G_AUDIO %d\n", a->index);
 	memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
 	return 0;
 }
 
 static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
 {
-	DEB_D(("VIDIOC_S_AUDIO %d.\n", a->index));
+	DEB_D("VIDIOC_S_AUDIO %d\n", a->index);
 	return 0;
 }
 
@@ -655,11 +661,11 @@
 		int i = *(int *)arg;
 
 		if (i < 0 || i >= MXB_AUDIOS) {
-			DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n", i));
+			DEB_D("invalid argument to MXB_S_AUDIO_CD: i:%d\n", i);
 			return -EINVAL;
 		}
 
-		DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n", i));
+		DEB_EE("MXB_S_AUDIO_CD: i:%d\n", i);
 
 		tea6420_route_cd(mxb, i);
 		return 0;
@@ -669,17 +675,18 @@
 		int i = *(int *)arg;
 
 		if (i < 0 || i >= MXB_AUDIOS) {
-			DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n", i));
+			DEB_D("invalid argument to MXB_S_AUDIO_LINE: i:%d\n",
+			      i);
 			return -EINVAL;
 		}
 
-		DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n", i));
+		DEB_EE("MXB_S_AUDIO_LINE: i:%d\n", i);
 		tea6420_route_line(mxb, i);
 		return 0;
 	}
 	default:
 /*
-		DEB2(printk("does not handle this ioctl.\n"));
+		DEB2(pr_err("does not handle this ioctl\n"));
 */
 		return -ENOIOCTLCMD;
 	}
@@ -693,7 +700,7 @@
 {
 	struct mxb *mxb;
 
-	DEB_EE(("dev:%p\n", dev));
+	DEB_EE("dev:%p\n", dev);
 
 	saa7146_vv_init(dev, &vv_data);
 	if (mxb_probe(dev)) {
@@ -720,7 +727,7 @@
 #endif
 	vv_data.ops.vidioc_default = vidioc_default;
 	if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
-		ERR(("cannot register capture v4l2 device. skipping.\n"));
+		ERR("cannot register capture v4l2 device. skipping.\n");
 		saa7146_vv_release(dev);
 		return -1;
 	}
@@ -728,11 +735,11 @@
 	/* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
 	if (MXB_BOARD_CAN_DO_VBI(dev)) {
 		if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
-			ERR(("cannot register vbi v4l2 device. skipping.\n"));
+			ERR("cannot register vbi v4l2 device. skipping.\n");
 		}
 	}
 
-	printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num);
+	pr_info("found Multimedia eXtension Board #%d\n", mxb_num);
 
 	mxb_num++;
 	mxb_init_done(dev);
@@ -743,7 +750,7 @@
 {
 	struct mxb *mxb = (struct mxb *)dev->ext_priv;
 
-	DEB_EE(("dev:%p\n", dev));
+	DEB_EE("dev:%p\n", dev);
 
 	saa7146_unregister_device(&mxb->video_dev,dev);
 	if (MXB_BOARD_CAN_DO_VBI(dev))
@@ -765,7 +772,7 @@
 	if (V4L2_STD_PAL_I == standard->id) {
 		v4l2_std_id std = V4L2_STD_PAL_I;
 
-		DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n"));
+		DEB_D("VIDIOC_S_STD: setting mxb for PAL_I\n");
 		/* set the 7146 gpio register -- I don't know what this does exactly */
 		saa7146_write(dev, GPIO_CTRL, 0x00404050);
 		/* unset the 7111 gpio register -- I don't know what this does exactly */
@@ -774,7 +781,7 @@
 	} else {
 		v4l2_std_id std = V4L2_STD_PAL_BG;
 
-		DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n"));
+		DEB_D("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM\n");
 		/* set the 7146 gpio register -- I don't know what this does exactly */
 		saa7146_write(dev, GPIO_CTRL, 0x00404050);
 		/* set the 7111 gpio register -- I don't know what this does exactly */
@@ -852,7 +859,7 @@
 static int __init mxb_init_module(void)
 {
 	if (saa7146_register_extension(&extension)) {
-		DEB_S(("failed to register extension.\n"));
+		DEB_S("failed to register extension\n");
 		return -ENODEV;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/noon010pc30.c linux-libre-3.2-gnu/drivers/media/video/noon010pc30.c
--- linux-libre-3.1-gnu/drivers/media/video/noon010pc30.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/noon010pc30.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * Driver for SiliconFile NOON010PC30 CIF (1/11") Image Sensor with ISP
  *
- * Copyright (C) 2010 Samsung Electronics
+ * Copyright (C) 2010 - 2011 Samsung Electronics Co., Ltd.
  * Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com>
  *
  * Initial register configuration based on a driver authored by
@@ -10,7 +10,7 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later vergsion.
+ * (at your option) any later version.
  */
 
 #include <linux/delay.h>
@@ -21,6 +21,7 @@
 #include <media/noon010pc30.h>
 #include <media/v4l2-chip-ident.h>
 #include <linux/videodev2.h>
+#include <linux/module.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-mediabus.h>
@@ -131,17 +132,23 @@
 
 struct noon010_info {
 	struct v4l2_subdev sd;
+	struct media_pad pad;
 	struct v4l2_ctrl_handler hdl;
-	const struct noon010pc30_platform_data *pdata;
+	struct regulator_bulk_data supply[NOON010_NUM_SUPPLIES];
+	u32 gpio_nreset;
+	u32 gpio_nstby;
+
+	/* Protects the struct members below */
+	struct mutex lock;
+
 	const struct noon010_format *curr_fmt;
 	const struct noon010_frmsize *curr_win;
+	unsigned int apply_new_cfg:1;
+	unsigned int streaming:1;
 	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 {
@@ -292,8 +299,10 @@
 	u8 reg = sleep ? 0xF1 : 0xF0;
 	int ret = 0;
 
-	if (reset)
+	if (reset) {
 		ret = cam_i2c_write(sd, POWER_CTRL_REG, reg | 0x02);
+		udelay(20);
+	}
 	if (!ret) {
 		ret = cam_i2c_write(sd, POWER_CTRL_REG, reg);
 		if (reset && !ret)
@@ -313,6 +322,7 @@
 	return ret;
 }
 
+/* Called with struct noon010_info.lock mutex held */
 static int noon010_set_flip(struct v4l2_subdev *sd, int hflip, int vflip)
 {
 	struct noon010_info *info = to_noon010(sd);
@@ -340,21 +350,18 @@
 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;
+	int ret = cam_i2c_write(sd, VDO_CTL_REG(0),
+				info->curr_win->vid_ctl1);
+	if (ret)
+		return ret;
+	return cam_i2c_write(sd, ISP_CTL_REG(0),
+			     info->curr_fmt->ispctl1_reg);
 }
 
 /* Find nearest matching image pixel size. */
-static int noon010_try_frame_size(struct v4l2_mbus_framefmt *mf)
+static int noon010_try_frame_size(struct v4l2_mbus_framefmt *mf,
+				  const struct noon010_frmsize **size)
 {
 	unsigned int min_err = ~0;
 	int i = ARRAY_SIZE(noon010_sizes);
@@ -374,11 +381,14 @@
 	if (match) {
 		mf->width  = match->width;
 		mf->height = match->height;
+		if (size)
+			*size = match;
 		return 0;
 	}
 	return -EINVAL;
 }
 
+/* Called with info.lock mutex held */
 static int power_enable(struct noon010_info *info)
 {
 	int ret;
@@ -419,6 +429,7 @@
 	return 0;
 }
 
+/* Called with info.lock mutex held */
 static int power_disable(struct noon010_info *info)
 {
 	int ret;
@@ -448,147 +459,175 @@
 static int noon010_s_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct noon010_info *info = to_noon010(sd);
+	int ret = 0;
 
 	v4l2_dbg(1, debug, sd, "%s: ctrl_id: %d, value: %d\n",
 		 __func__, ctrl->id, ctrl->val);
 
+	mutex_lock(&info->lock);
+	/*
+	 * If the device is not powered up by the host driver do
+	 * not apply any controls to H/W at this time. Instead
+	 * the controls will be restored right after power-up.
+	 */
+	if (!info->power)
+		goto unlock;
+
 	switch (ctrl->id) {
 	case V4L2_CID_AUTO_WHITE_BALANCE:
-		return noon010_enable_autowhitebalance(sd, ctrl->val);
+		ret = noon010_enable_autowhitebalance(sd, ctrl->val);
+		break;
 	case V4L2_CID_BLUE_BALANCE:
-		return cam_i2c_write(sd, MWB_BGAIN_REG, ctrl->val);
+		ret = cam_i2c_write(sd, MWB_BGAIN_REG, ctrl->val);
+		break;
 	case V4L2_CID_RED_BALANCE:
-		return cam_i2c_write(sd, MWB_RGAIN_REG, ctrl->val);
+		ret =  cam_i2c_write(sd, MWB_RGAIN_REG, ctrl->val);
+		break;
 	default:
-		return -EINVAL;
+		ret = -EINVAL;
 	}
+unlock:
+	mutex_unlock(&info->lock);
+	return ret;
 }
 
-static int noon010_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-			    enum v4l2_mbus_pixelcode *code)
+static int noon010_enum_mbus_code(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
 {
-	if (!code || index >= ARRAY_SIZE(noon010_formats))
+	if (code->index >= ARRAY_SIZE(noon010_formats))
 		return -EINVAL;
 
-	*code = noon010_formats[index].code;
+	code->code = noon010_formats[code->index].code;
 	return 0;
 }
 
-static int noon010_g_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
+static int noon010_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_format *fmt)
 {
 	struct noon010_info *info = to_noon010(sd);
-	int ret;
-
-	if (!mf)
-		return -EINVAL;
+	struct v4l2_mbus_framefmt *mf;
 
-	if (!info->curr_win || !info->curr_fmt) {
-		ret = noon010_set_params(sd);
-		if (ret)
-			return ret;
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+		if (fh) {
+			mf = v4l2_subdev_get_try_format(fh, 0);
+			fmt->format = *mf;
+		}
+		return 0;
 	}
+	mf = &fmt->format;
 
-	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;
+	mutex_lock(&info->lock);
+	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;
 
+	mutex_unlock(&info->lock);
 	return 0;
 }
 
 /* Return nearest media bus frame format. */
-static const struct noon010_format *try_fmt(struct v4l2_subdev *sd,
+static const struct noon010_format *noon010_try_fmt(struct v4l2_subdev *sd,
 					    struct v4l2_mbus_framefmt *mf)
 {
 	int i = ARRAY_SIZE(noon010_formats);
 
-	noon010_try_frame_size(mf);
-
-	while (i--)
+	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)
+static int noon010_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_format *fmt)
 {
 	struct noon010_info *info = to_noon010(sd);
+	const struct noon010_frmsize *size = NULL;
+	const struct noon010_format *nf;
+	struct v4l2_mbus_framefmt *mf;
+	int ret = 0;
 
-	if (!sd || !mf)
-		return -EINVAL;
-
-	info->curr_fmt = try_fmt(sd, mf);
+	nf = noon010_try_fmt(sd, &fmt->format);
+	noon010_try_frame_size(&fmt->format, &size);
+	fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
 
-	return noon010_set_params(sd);
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+		if (fh) {
+			mf = v4l2_subdev_get_try_format(fh, 0);
+			*mf = fmt->format;
+		}
+		return 0;
+	}
+	mutex_lock(&info->lock);
+	if (!info->streaming) {
+		info->apply_new_cfg = 1;
+		info->curr_fmt = nf;
+		info->curr_win = size;
+	} else {
+		ret = -EBUSY;
+	}
+	mutex_unlock(&info->lock);
+	return ret;
 }
 
+/* Called with struct noon010_info.lock mutex held */
 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];
+	int ret = noon010_bulk_write_reg(sd, noon010_base_regs);
+	if (!ret)
 		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;
+	int ret;
 
+	mutex_lock(&info->lock);
 	if (on) {
 		ret = power_enable(info);
-		if (ret)
-			return ret;
-		ret = noon010_base_config(sd);
+		if (!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;
 	}
+	mutex_unlock(&info->lock);
+
+	/* Restore the controls state */
+	if (!ret && on)
+		ret = v4l2_ctrl_handler_setup(&info->hdl);
 
 	return ret;
 }
 
-static int noon010_g_chip_ident(struct v4l2_subdev *sd,
-				struct v4l2_dbg_chip_ident *chip)
+static int noon010_s_stream(struct v4l2_subdev *sd, int on)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct noon010_info *info = to_noon010(sd);
+	int ret = 0;
 
-	return v4l2_chip_ident_i2c_client(client, chip,
-					  V4L2_IDENT_NOON010PC30, 0);
+	mutex_lock(&info->lock);
+	if (!info->streaming != !on) {
+		ret = noon010_power_ctrl(sd, false, !on);
+		if (!ret)
+			info->streaming = on;
+	}
+	if (!ret && on && info->apply_new_cfg) {
+		ret = noon010_set_params(sd);
+		if (!ret)
+			info->apply_new_cfg = 0;
+	}
+	mutex_unlock(&info->lock);
+	return ret;
 }
 
 static int noon010_log_status(struct v4l2_subdev *sd)
@@ -599,12 +638,27 @@
 	return 0;
 }
 
+static int noon010_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(fh, 0);
+
+	mf->width = noon010_sizes[0].width;
+	mf->height = noon010_sizes[0].height;
+	mf->code = noon010_formats[0].code;
+	mf->colorspace = V4L2_COLORSPACE_JPEG;
+	mf->field = V4L2_FIELD_NONE;
+	return 0;
+}
+
+static const struct v4l2_subdev_internal_ops noon010_subdev_internal_ops = {
+	.open = noon010_open,
+};
+
 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,
@@ -616,15 +670,19 @@
 	.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 struct v4l2_subdev_pad_ops noon010_pad_ops = {
+	.enum_mbus_code	= noon010_enum_mbus_code,
+	.get_fmt	= noon010_get_fmt,
+	.set_fmt	= noon010_set_fmt,
+};
+
+static struct v4l2_subdev_video_ops noon010_video_ops = {
+	.s_stream	= noon010_s_stream,
 };
 
 static const struct v4l2_subdev_ops noon010_ops = {
 	.core	= &noon010_core_ops,
+	.pad	= &noon010_pad_ops,
 	.video	= &noon010_video_ops,
 };
 
@@ -665,10 +723,14 @@
 	if (!info)
 		return -ENOMEM;
 
+	mutex_init(&info->lock);
 	sd = &info->sd;
 	strlcpy(sd->name, MODULE_NAME, sizeof(sd->name));
 	v4l2_i2c_subdev_init(sd, client, &noon010_ops);
 
+	sd->internal_ops = &noon010_subdev_internal_ops;
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
 	v4l2_ctrl_handler_init(&info->hdl, 3);
 
 	v4l2_ctrl_new_std(&info->hdl, &noon010_ctrl_ops,
@@ -684,10 +746,11 @@
 	if (ret)
 		goto np_err;
 
-	info->pdata		= client->dev.platform_data;
 	info->i2c_reg_page	= -1;
 	info->gpio_nreset	= -EINVAL;
 	info->gpio_nstby	= -EINVAL;
+	info->curr_fmt		= &noon010_formats[0];
+	info->curr_win		= &noon010_sizes[0];
 
 	if (gpio_is_valid(pdata->gpio_nreset)) {
 		ret = gpio_request(pdata->gpio_nreset, "NOON010PC30 NRST");
@@ -719,11 +782,17 @@
 	if (ret)
 		goto np_reg_err;
 
+	info->pad.flags = MEDIA_PAD_FL_SOURCE;
+	sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
+	ret = media_entity_init(&sd->entity, 1, &info->pad, 0);
+	if (ret < 0)
+		goto np_me_err;
+
 	ret = noon010_detect(client, info);
 	if (!ret)
 		return 0;
 
-	/* the sensor detection failed */
+np_me_err:
 	regulator_bulk_free(NOON010_NUM_SUPPLIES, info->supply);
 np_reg_err:
 	if (gpio_is_valid(info->gpio_nstby))
@@ -754,6 +823,7 @@
 	if (gpio_is_valid(info->gpio_nstby))
 		gpio_free(info->gpio_nstby);
 
+	media_entity_cleanup(&sd->entity);
 	kfree(info);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap/omap_vout.c linux-libre-3.2-gnu/drivers/media/video/omap/omap_vout.c
--- linux-libre-3.1-gnu/drivers/media/video/omap/omap_vout.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap/omap_vout.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,6 +38,7 @@
 #include <linux/irq.h>
 #include <linux/videodev2.h>
 #include <linux/dma-mapping.h>
+#include <linux/slab.h>
 
 #include <media/videobuf-dma-contig.h>
 #include <media/v4l2-device.h>
@@ -400,7 +401,6 @@
 
 	ovl->get_overlay_info(ovl, &info);
 	info.paddr = addr;
-	info.vaddr = NULL;
 	info.width = cropwidth;
 	info.height = cropheight;
 	info.color_mode = vout->dss_mode;
@@ -834,6 +834,15 @@
 /*
  *  File operations
  */
+static unsigned int omap_vout_poll(struct file *file,
+				   struct poll_table_struct *wait)
+{
+	struct omap_vout_device *vout = file->private_data;
+	struct videobuf_queue *q = &vout->vbq;
+
+	return videobuf_poll_stream(file, q, wait);
+}
+
 static void omap_vout_vm_open(struct vm_area_struct *vma)
 {
 	struct omap_vout_device *vout = vma->vm_private_data;
@@ -1165,12 +1174,17 @@
 {
 	int ret = 0;
 	struct omap_vout_device *vout = fh;
+	struct omap_overlay *ovl;
+	struct omapvideo_info *ovid;
 	struct v4l2_window *win = &f->fmt.win;
 
+	ovid = &vout->vid_info;
+	ovl = ovid->overlays[0];
+
 	ret = omap_vout_try_window(&vout->fbuf, win);
 
 	if (!ret) {
-		if (vout->vid == OMAP_VIDEO1)
+		if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
 			win->global_alpha = 255;
 		else
 			win->global_alpha = f->fmt.win.global_alpha;
@@ -1194,8 +1208,8 @@
 
 	ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win);
 	if (!ret) {
-		/* Video1 plane does not support global alpha */
-		if (ovl->id == OMAP_DSS_VIDEO1)
+		/* Video1 plane does not support global alpha on OMAP3 */
+		if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
 			vout->win.global_alpha = 255;
 		else
 			vout->win.global_alpha = f->fmt.win.global_alpha;
@@ -1788,7 +1802,9 @@
 	if (ovl->manager && ovl->manager->get_manager_info &&
 			ovl->manager->set_manager_info) {
 		ovl->manager->get_manager_info(ovl->manager, &info);
-		info.alpha_enabled = enable;
+		/* enable this only if there is no zorder cap */
+		if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
+			info.partial_alpha_enabled = enable;
 		if (ovl->manager->set_manager_info(ovl->manager, &info))
 			return -EINVAL;
 	}
@@ -1820,7 +1836,7 @@
 	}
 	if (ovl->manager && ovl->manager->get_manager_info) {
 		ovl->manager->get_manager_info(ovl->manager, &info);
-		if (info.alpha_enabled)
+		if (info.partial_alpha_enabled)
 			a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
 	}
 
@@ -1855,6 +1871,7 @@
 
 static const struct v4l2_file_operations omap_vout_fops = {
 	.owner 		= THIS_MODULE,
+	.poll		= omap_vout_poll,
 	.unlocked_ioctl	= video_ioctl2,
 	.mmap 		= omap_vout_mmap,
 	.open 		= omap_vout_open,
@@ -2153,6 +2170,14 @@
 	vid_dev->num_displays = 0;
 	for_each_dss_dev(dssdev) {
 		omap_dss_get_device(dssdev);
+
+		if (!dssdev->driver) {
+			dev_warn(&pdev->dev, "no driver for display: %s\n",
+					dssdev->name);
+			omap_dss_put_device(dssdev);
+			continue;
+		}
+
 		vid_dev->displays[vid_dev->num_displays++] = dssdev;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap1_camera.c linux-libre-3.2-gnu/drivers/media/video/omap1_camera.c
--- linux-libre-3.1-gnu/drivers/media/video/omap1_camera.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap1_camera.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
@@ -102,10 +103,10 @@
 /* end of OMAP1 Camera Interface registers */
 
 
-#define SOCAM_BUS_FLAGS	(SOCAM_MASTER | \
-			SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | \
-			SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | \
-			SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8)
+#define SOCAM_BUS_FLAGS	(V4L2_MBUS_MASTER | \
+			V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
+			V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING | \
+			V4L2_MBUS_DATA_ACTIVE_HIGH)
 
 
 #define FIFO_SIZE		((THRESHOLD_MASK >> THRESHOLD_SHIFT) + 1)
@@ -1438,41 +1439,55 @@
 static int omap1_cam_set_bus_param(struct soc_camera_device *icd,
 		__u32 pixfmt)
 {
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct device *dev = icd->parent;
 	struct soc_camera_host *ici = to_soc_camera_host(dev);
 	struct omap1_cam_dev *pcdev = ici->priv;
 	const struct soc_camera_format_xlate *xlate;
 	const struct soc_mbus_pixelfmt *fmt;
-	unsigned long camera_flags, common_flags;
+	struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+	unsigned long common_flags;
 	u32 ctrlclock, mode;
 	int ret;
 
-	camera_flags = icd->ops->query_bus_param(icd);
-
-	common_flags = soc_camera_bus_param_compatible(camera_flags,
-			SOCAM_BUS_FLAGS);
-	if (!common_flags)
-		return -EINVAL;
+	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+	if (!ret) {
+		common_flags = soc_mbus_config_compatible(&cfg, SOCAM_BUS_FLAGS);
+		if (!common_flags) {
+			dev_warn(dev,
+				 "Flags incompatible: camera 0x%x, host 0x%x\n",
+				 cfg.flags, SOCAM_BUS_FLAGS);
+			return -EINVAL;
+		}
+	} else if (ret != -ENOIOCTLCMD) {
+		return ret;
+	} else {
+		common_flags = SOCAM_BUS_FLAGS;
+	}
 
 	/* Make choices, possibly based on platform configuration */
-	if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
-			(common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+	if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
+			(common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
 		if (!pcdev->pdata ||
 				pcdev->pdata->flags & OMAP1_CAMERA_LCLK_RISING)
-			common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+			common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
 		else
-			common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+			common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
 	}
 
-	ret = icd->ops->set_bus_param(icd, common_flags);
-	if (ret < 0)
+	cfg.flags = common_flags;
+	ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+	if (ret < 0 && ret != -ENOIOCTLCMD) {
+		dev_dbg(dev, "camera s_mbus_config(0x%lx) returned %d\n",
+			common_flags, ret);
 		return ret;
+	}
 
 	ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK);
 	if (ctrlclock & LCLK_EN)
 		CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN);
 
-	if (common_flags & SOCAM_PCLK_SAMPLE_RISING) {
+	if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) {
 		dev_dbg(dev, "CTRLCLOCK_REG |= POLCLK\n");
 		ctrlclock |= POLCLK;
 	} else {
@@ -1565,10 +1580,10 @@
 	pcdev->clk = clk;
 
 	pcdev->pdata = pdev->dev.platform_data;
-	pcdev->pflags = pcdev->pdata->flags;
-
-	if (pcdev->pdata)
+	if (pcdev->pdata) {
+		pcdev->pflags = pcdev->pdata->flags;
 		pcdev->camexclk = pcdev->pdata->camexclk_khz * 1000;
+	}
 
 	switch (pcdev->camexclk) {
 	case 6000000:
@@ -1578,6 +1593,7 @@
 	case 24000000:
 		break;
 	default:
+		/* pcdev->camexclk != 0 => pcdev->pdata != NULL */
 		dev_warn(&pdev->dev,
 				"Incorrect sensor clock frequency %ld kHz, "
 				"should be one of 0, 6, 8, 9.6, 12 or 24 MHz, "
@@ -1585,8 +1601,7 @@
 				pcdev->pdata->camexclk_khz);
 		pcdev->camexclk = 0;
 	case 0:
-		dev_info(&pdev->dev,
-				"Not providing sensor clock\n");
+		dev_info(&pdev->dev, "Not providing sensor clock\n");
 	}
 
 	INIT_LIST_HEAD(&pcdev->capture);
@@ -1716,5 +1731,5 @@
 MODULE_DESCRIPTION("OMAP1 Camera Interface driver");
 MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>");
 MODULE_LICENSE("GPL v2");
-MODULE_LICENSE(DRIVER_VERSION);
+MODULE_VERSION(DRIVER_VERSION);
 MODULE_ALIAS("platform:" DRIVER_NAME);
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap24xxcam.c linux-libre-3.2-gnu/drivers/media/video/omap24xxcam.c
--- linux-libre-3.1-gnu/drivers/media/video/omap24xxcam.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap24xxcam.c	2012-01-04 18:55:44.000000000 -0500
@@ -36,6 +36,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/module.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap24xxcam-dma.c linux-libre-3.2-gnu/drivers/media/video/omap24xxcam-dma.c
--- linux-libre-3.1-gnu/drivers/media/video/omap24xxcam-dma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap24xxcam-dma.c	2012-01-04 18:55:44.000000000 -0500
@@ -506,7 +506,7 @@
 	unsigned long flags;
 	struct sgdma_state *sg_state;
 
-	if ((sglen < 0) || ((sglen > 0) & !sglist))
+	if ((sglen < 0) || ((sglen > 0) && !sglist))
 		return -EINVAL;
 
 	spin_lock_irqsave(&sgdma->lock, flags);
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/isp.c linux-libre-3.2-gnu/drivers/media/video/omap3isp/isp.c
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/isp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/isp.c	2012-01-04 18:55:44.000000000 -0500
@@ -80,6 +80,13 @@
 #include "isph3a.h"
 #include "isphist.h"
 
+/*
+ * this is provided as an interim solution until omap3isp doesn't need
+ * any omap-specific iommu API
+ */
+#define to_iommu(dev)							\
+	(struct omap_iommu *)platform_get_drvdata(to_platform_device(dev))
+
 static unsigned int autoidle;
 module_param(autoidle, int, 0444);
 MODULE_PARM_DESC(autoidle, "Enable OMAP3ISP AUTOIDLE support");
@@ -732,7 +739,7 @@
 	struct media_pad *pad;
 	struct v4l2_subdev *subdev;
 	unsigned long flags;
-	int ret = 0;
+	int ret;
 
 	spin_lock_irqsave(&pipe->lock, flags);
 	pipe->state &= ~(ISP_PIPELINE_IDLE_INPUT | ISP_PIPELINE_IDLE_OUTPUT);
@@ -756,7 +763,7 @@
 
 		ret = v4l2_subdev_call(subdev, video, s_stream, mode);
 		if (ret < 0 && ret != -ENOIOCTLCMD)
-			break;
+			return ret;
 
 		if (subdev == &isp->isp_ccdc.subdev) {
 			v4l2_subdev_call(&isp->isp_aewb.subdev, video,
@@ -777,7 +784,7 @@
 	if (pipe->do_propagation && mode == ISP_PIPELINE_STREAM_SINGLESHOT)
 		atomic_inc(&pipe->frame_number);
 
-	return ret;
+	return 0;
 }
 
 static int isp_pipeline_wait_resizer(struct isp_device *isp)
@@ -1108,7 +1115,7 @@
 {
 	isp_save_context(isp, isp_reg_list);
 	if (isp->iommu)
-		iommu_save_ctx(isp->iommu);
+		omap_iommu_save_ctx(isp->iommu);
 }
 
 /*
@@ -1122,7 +1129,7 @@
 {
 	isp_restore_context(isp, isp_reg_list);
 	if (isp->iommu)
-		iommu_restore_ctx(isp->iommu);
+		omap_iommu_restore_ctx(isp->iommu);
 	omap3isp_ccdc_restore_context(isp);
 	omap3isp_preview_restore_context(isp);
 }
@@ -1697,6 +1704,7 @@
 	isp->media_dev.dev = isp->dev;
 	strlcpy(isp->media_dev.model, "TI OMAP3 ISP",
 		sizeof(isp->media_dev.model));
+	isp->media_dev.hw_revision = isp->revision;
 	isp->media_dev.link_notify = isp_pipeline_link_notify;
 	ret = media_device_register(&isp->media_dev);
 	if (ret < 0) {
@@ -1975,7 +1983,8 @@
 	isp_cleanup_modules(isp);
 
 	omap3isp_get(isp);
-	iommu_put(isp->iommu);
+	iommu_detach_device(isp->domain, isp->iommu_dev);
+	iommu_domain_free(isp->domain);
 	omap3isp_put(isp);
 
 	free_irq(isp->irq_num, isp);
@@ -2123,25 +2132,41 @@
 	}
 
 	/* IOMMU */
-	isp->iommu = iommu_get("isp");
-	if (IS_ERR_OR_NULL(isp->iommu)) {
-		isp->iommu = NULL;
+	isp->iommu_dev = omap_find_iommu_device("isp");
+	if (!isp->iommu_dev) {
+		dev_err(isp->dev, "omap_find_iommu_device failed\n");
 		ret = -ENODEV;
 		goto error_isp;
 	}
 
+	/* to be removed once iommu migration is complete */
+	isp->iommu = to_iommu(isp->iommu_dev);
+
+	isp->domain = iommu_domain_alloc(pdev->dev.bus);
+	if (!isp->domain) {
+		dev_err(isp->dev, "can't alloc iommu domain\n");
+		ret = -ENOMEM;
+		goto error_isp;
+	}
+
+	ret = iommu_attach_device(isp->domain, isp->iommu_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "can't attach iommu device: %d\n", ret);
+		goto free_domain;
+	}
+
 	/* 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;
+		goto detach_dev;
 	}
 
 	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;
+		goto detach_dev;
 	}
 
 	/* Entities */
@@ -2162,8 +2187,11 @@
 	isp_cleanup_modules(isp);
 error_irq:
 	free_irq(isp->irq_num, isp);
+detach_dev:
+	iommu_detach_device(isp->domain, isp->iommu_dev);
+free_domain:
+	iommu_domain_free(isp->domain);
 error_isp:
-	iommu_put(isp->iommu);
 	omap3isp_put(isp);
 error:
 	isp_put_clocks(isp);
@@ -2183,6 +2211,8 @@
 	regulator_put(isp->isp_csiphy2.vdd);
 	regulator_put(isp->isp_csiphy1.vdd);
 	platform_set_drvdata(pdev, NULL);
+
+	mutex_destroy(&isp->isp_mutex);
 	kfree(isp);
 
 	return ret;
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispccdc.c linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispccdc.c
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispccdc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispccdc.c	2012-01-04 18:55:44.000000000 -0500
@@ -366,7 +366,7 @@
 		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);
+		omap_iommu_vfree(isp->domain, isp->iommu, req->table);
 	kfree(req);
 }
 
@@ -438,15 +438,15 @@
 
 		req->enable = 1;
 
-		req->table = iommu_vmalloc(isp->iommu, 0, req->config.size,
-					   IOMMU_FLAG);
+		req->table = omap_iommu_vmalloc(isp->domain, 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);
+		req->iovm = omap_find_iovm_area(isp->iommu, req->table);
 		if (req->iovm == NULL) {
 			ret = -ENOMEM;
 			goto done;
@@ -462,7 +462,7 @@
 		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);
+		table = omap_da_to_va(isp->iommu, req->table);
 		if (copy_from_user(table, config->lsc, req->config.size)) {
 			ret = -EFAULT;
 			goto done;
@@ -731,18 +731,19 @@
 
 			/*
 			 * table_new must be 64-bytes aligned, but it's
-			 * already done by iommu_vmalloc().
+			 * already done by omap_iommu_vmalloc().
 			 */
 			size = ccdc->fpc.fpnum * 4;
-			table_new = iommu_vmalloc(isp->iommu, 0, size,
-						  IOMMU_FLAG);
+			table_new = omap_iommu_vmalloc(isp->domain, 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),
+			if (copy_from_user(omap_da_to_va(isp->iommu, table_new),
 					   (__force void __user *)
 					   ccdc->fpc.fpcaddr, size)) {
-				iommu_vfree(isp->iommu, table_new);
+				omap_iommu_vfree(isp->domain, isp->iommu,
+								table_new);
 				return -EFAULT;
 			}
 
@@ -752,7 +753,7 @@
 
 		ccdc_configure_fpc(ccdc);
 		if (table_old != 0)
-			iommu_vfree(isp->iommu, table_old);
+			omap_iommu_vfree(isp->domain, isp->iommu, table_old);
 	}
 
 	return ccdc_lsc_config(ccdc, ccdc_struct);
@@ -1405,11 +1406,14 @@
 
 static void ccdc_hs_vs_isr(struct isp_ccdc_device *ccdc)
 {
-	struct video_device *vdev = &ccdc->subdev.devnode;
+	struct isp_pipeline *pipe =
+		to_isp_pipeline(&ccdc->video_out.video.entity);
+	struct video_device *vdev = ccdc->subdev.devnode;
 	struct v4l2_event event;
 
 	memset(&event, 0, sizeof(event));
-	event.type = V4L2_EVENT_OMAP3ISP_HS_VS;
+	event.type = V4L2_EVENT_FRAME_SYNC;
+	event.u.frame_sync.frame_sequence = atomic_read(&pipe->frame_number);
 
 	v4l2_event_queue(vdev, &event);
 }
@@ -1691,7 +1695,11 @@
 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)
+	if (sub->type != V4L2_EVENT_FRAME_SYNC)
+		return -EINVAL;
+
+	/* line number is zero at frame start */
+	if (sub->id != 0)
 		return -EINVAL;
 
 	return v4l2_event_subscribe(fh, sub, OMAP3ISP_CCDC_NEVENTS);
@@ -1828,7 +1836,7 @@
 		 * 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 = clamp_t(u32, width, 32, fmt->width + 15);
 		fmt->width &= ~15;
 		fmt->height = clamp_t(u32, height, 32, fmt->height);
 		break;
@@ -2144,6 +2152,37 @@
 	.link_setup = ccdc_link_setup,
 };
 
+void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc)
+{
+	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
+ */
+
 /*
  * ccdc_init_entities - Initialize V4L2 subdev and media entity
  * @ccdc: ISP CCDC module
@@ -2185,50 +2224,23 @@
 
 	ret = omap3isp_video_init(&ccdc->video_out, "CCDC");
 	if (ret < 0)
-		return ret;
+		goto error_video;
 
 	/* 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;
+		goto error_link;
 
 	return 0;
 
-error:
-	omap3isp_ccdc_unregister_entities(ccdc);
+error_link:
+	omap3isp_video_cleanup(&ccdc->video_out);
+error_video:
+	media_entity_cleanup(me);
 	return ret;
 }
 
-/* -----------------------------------------------------------------------------
- * ISP CCDC initialisation and cleanup
- */
-
 /*
  * omap3isp_ccdc_init - CCDC module initialization.
  * @dev: Device pointer specific to the OMAP3 ISP.
@@ -2240,6 +2252,7 @@
 int omap3isp_ccdc_init(struct isp_device *isp)
 {
 	struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
+	int ret;
 
 	spin_lock_init(&ccdc->lock);
 	init_waitqueue_head(&ccdc->wait);
@@ -2268,7 +2281,13 @@
 	ccdc->update = OMAP3ISP_CCDC_BLCLAMP;
 	ccdc_apply_controls(ccdc);
 
-	return ccdc_init_entities(ccdc);
+	ret = ccdc_init_entities(ccdc);
+	if (ret < 0) {
+		mutex_destroy(&ccdc->ioctl_lock);
+		return ret;
+	}
+
+	return 0;
 }
 
 /*
@@ -2279,6 +2298,9 @@
 {
 	struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
 
+	omap3isp_video_cleanup(&ccdc->video_out);
+	media_entity_cleanup(&ccdc->subdev.entity);
+
 	/* 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.
 	 */
@@ -2287,5 +2309,7 @@
 	ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
 
 	if (ccdc->fpc.fpcaddr != 0)
-		iommu_vfree(isp->iommu, ccdc->fpc.fpcaddr);
+		omap_iommu_vfree(isp->domain, isp->iommu, ccdc->fpc.fpcaddr);
+
+	mutex_destroy(&ccdc->ioctl_lock);
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispccp2.c linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispccp2.c
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispccp2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispccp2.c	2012-01-04 18:55:44.000000000 -0500
@@ -243,9 +243,9 @@
 
 	val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
 	if (!(val & ISPCCP2_CTRL_MODE)) {
-		if (pdata->ccp2_mode)
+		if (pdata->ccp2_mode == ISP_CCP2_MODE_CCP2)
 			dev_warn(isp->dev, "OMAP3 CCP2 bus not available\n");
-		if (pdata->phy_layer == ISPCCP2_CTRL_PHY_SEL_STROBE)
+		if (pdata->phy_layer == ISP_CCP2_PHY_DATA_STROBE)
 			/* Strobe mode requires CCP2 */
 			return -EIO;
 	}
@@ -1032,6 +1032,48 @@
 };
 
 /*
+ * omap3isp_ccp2_unregister_entities - Unregister media entities: subdev
+ * @ccp2: Pointer to ISP CCP2 device
+ */
+void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2)
+{
+	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
+ */
+
+/*
  * ccp2_init_entities - Initialize ccp2 subdev and media entity.
  * @ccp2: Pointer to ISP CCP2 device
  * return negative error code or zero on success
@@ -1083,72 +1125,23 @@
 
 	ret = omap3isp_video_init(&ccp2->video_in, "CCP2");
 	if (ret < 0)
-		return ret;
+		goto error_video;
 
 	/* 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;
+		goto error_link;
 
 	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)
-{
+error_link:
+	omap3isp_video_cleanup(&ccp2->video_in);
+error_video:
 	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)
-{
-	struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;
-
-	regulator_put(ccp2->vdds_csib);
-}
-
 /*
  * omap3isp_ccp2_init - CCP2 initialization.
  * @isp : Pointer to ISP device
@@ -1184,13 +1177,25 @@
 	}
 
 	ret = ccp2_init_entities(ccp2);
-	if (ret < 0)
-		goto out;
+	if (ret < 0) {
+		regulator_put(ccp2->vdds_csib);
+		return ret;
+	}
 
 	ccp2_reset(ccp2);
-out:
-	if (ret)
-		omap3isp_ccp2_cleanup(isp);
+	return 0;
+}
 
-	return ret;
+/*
+ * omap3isp_ccp2_cleanup - CCP2 un-initialization
+ * @isp : Pointer to ISP device
+ */
+void omap3isp_ccp2_cleanup(struct isp_device *isp)
+{
+	struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;
+
+	omap3isp_video_cleanup(&ccp2->video_in);
+	media_entity_cleanup(&ccp2->subdev.entity);
+
+	regulator_put(ccp2->vdds_csib);
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispcsi2.c linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispcsi2.c
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispcsi2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispcsi2.c	2012-01-04 18:55:44.000000000 -0500
@@ -1187,6 +1187,37 @@
 	.link_setup = csi2_link_setup,
 };
 
+void omap3isp_csi2_unregister_entities(struct isp_csi2_device *csi2)
+{
+	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
+ */
+
 /*
  * csi2_init_entities - Initialize subdev and media entity.
  * @csi2: Pointer to csi2 structure.
@@ -1228,57 +1259,23 @@
 
 	ret = omap3isp_video_init(&csi2->video_out, "CSI2a");
 	if (ret < 0)
-		return ret;
+		goto error_video;
 
 	/* 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;
+		goto error_link;
 
 	return 0;
-}
 
-void omap3isp_csi2_unregister_entities(struct isp_csi2_device *csi2)
-{
+error_link:
+	omap3isp_video_cleanup(&csi2->video_out);
+error_video:
 	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
  */
@@ -1298,7 +1295,7 @@
 
 	ret = csi2_init_entities(csi2a);
 	if (ret < 0)
-		goto fail;
+		return ret;
 
 	if (isp->revision == ISP_REVISION_15_0) {
 		csi2c->isp = isp;
@@ -1311,7 +1308,15 @@
 	}
 
 	return 0;
-fail:
-	omap3isp_csi2_cleanup(isp);
-	return ret;
+}
+
+/*
+ * omap3isp_csi2_cleanup - Routine for module driver cleanup
+ */
+void omap3isp_csi2_cleanup(struct isp_device *isp)
+{
+	struct isp_csi2_device *csi2a = &isp->isp_csi2a;
+
+	omap3isp_video_cleanup(&csi2a->video_out);
+	media_entity_cleanup(&csi2a->subdev.entity);
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/isp.h linux-libre-3.2-gnu/drivers/media/video/omap3isp/isp.h
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/isp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/isp.h	2012-01-04 18:55:44.000000000 -0500
@@ -27,11 +27,13 @@
 #ifndef OMAP3_ISP_CORE_H
 #define OMAP3_ISP_CORE_H
 
+#include <media/omap3isp.h>
 #include <media/v4l2-device.h>
 #include <linux/device.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/wait.h>
+#include <linux/iommu.h>
 #include <plat/iommu.h>
 #include <plat/iovmm.h>
 
@@ -94,14 +96,6 @@
 	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 */
@@ -130,82 +124,6 @@
 	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
- * @hs_pol: Horizontal synchronization polarity
- *		0 - Active high, 1 - Active low
- * @vs_pol: Vertical synchronization polarity
- *		0 - Active high, 1 - Active low
- * @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 hs_pol:1;
-	unsigned int vs_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,
@@ -294,7 +212,9 @@
 	unsigned int sbl_resources;
 	unsigned int subclk_resources;
 
-	struct iommu *iommu;
+	struct omap_iommu *iommu;
+	struct iommu_domain *domain;
+	struct device *iommu_dev;
 
 	struct isp_platform_callback platform_cb;
 };
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/isph3a_aewb.c linux-libre-3.2-gnu/drivers/media/video/omap3isp/isph3a_aewb.c
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/isph3a_aewb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/isph3a_aewb.c	2012-01-04 18:55:44.000000000 -0500
@@ -370,5 +370,5 @@
 {
 	kfree(isp->isp_aewb.priv);
 	kfree(isp->isp_aewb.recover_priv);
-	omap3isp_stat_free(&isp->isp_aewb);
+	omap3isp_stat_cleanup(&isp->isp_aewb);
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/isph3a_af.c linux-libre-3.2-gnu/drivers/media/video/omap3isp/isph3a_af.c
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/isph3a_af.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/isph3a_af.c	2012-01-04 18:55:44.000000000 -0500
@@ -425,5 +425,5 @@
 {
 	kfree(isp->isp_af.priv);
 	kfree(isp->isp_af.recover_priv);
-	omap3isp_stat_free(&isp->isp_af);
+	omap3isp_stat_cleanup(&isp->isp_af);
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/isphist.c linux-libre-3.2-gnu/drivers/media/video/omap3isp/isphist.c
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/isphist.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/isphist.c	2012-01-04 18:55:44.000000000 -0500
@@ -516,5 +516,5 @@
 	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);
+	omap3isp_stat_cleanup(&isp->isp_hist);
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/isppreview.c linux-libre-3.2-gnu/drivers/media/video/omap3isp/isppreview.c
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/isppreview.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/isppreview.c	2012-01-04 18:55:44.000000000 -0500
@@ -76,9 +76,51 @@
 
 #define DEF_DETECT_CORRECT_VAL	0xe
 
-#define PREV_MIN_WIDTH		64
-#define PREV_MIN_HEIGHT		8
-#define PREV_MAX_HEIGHT		16384
+/*
+ * Margins and image size limits.
+ *
+ * The preview engine crops several rows and columns internally depending on
+ * which filters are enabled. To avoid format changes when the filters are
+ * enabled or disabled (which would prevent them from being turned on or off
+ * during streaming), the driver assumes all the filters are enabled when
+ * computing sink crop and source format limits.
+ *
+ * If a filter is disabled, additional cropping is automatically added at the
+ * preview engine input by the driver to avoid overflow at line and frame end.
+ * This is completely transparent for applications.
+ *
+ * Median filter		4 pixels
+ * Noise filter,
+ * Faulty pixels correction	4 pixels, 4 lines
+ * 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
+ *
+ * The color suppression and luma enhancement filters are applied after bayer to
+ * YUV conversion. They thus can crop one pixel on the left and one pixel on the
+ * right side of the image without changing the color pattern. When both those
+ * filters are disabled, the driver must crop the two pixels on the same side of
+ * the image to avoid changing the bayer pattern. The left margin is thus set to
+ * 8 pixels and the right margin to 6 pixels.
+ */
+
+#define PREV_MARGIN_LEFT	8
+#define PREV_MARGIN_RIGHT	6
+#define PREV_MARGIN_TOP		4
+#define PREV_MARGIN_BOTTOM	4
+
+#define PREV_MIN_IN_WIDTH	64
+#define PREV_MIN_IN_HEIGHT	8
+#define PREV_MAX_IN_HEIGHT	16384
+
+#define PREV_MIN_OUT_WIDTH	0
+#define PREV_MIN_OUT_HEIGHT	0
+#define PREV_MAX_OUT_WIDTH	1280
+#define PREV_MAX_OUT_WIDTH_ES2	3300
+#define PREV_MAX_OUT_WIDTH_3630	4096
 
 /*
  * Coeficient Tables for the submodules in Preview.
@@ -979,52 +1021,36 @@
  * 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.
+ *
+ * See the explanation at the PREV_MARGIN_* definitions for more details.
  */
 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
-	 */
+	unsigned int sph = prev->crop.left;
+	unsigned int eph = prev->crop.left + prev->crop.width - 1;
+	unsigned int slv = prev->crop.top;
+	unsigned int elv = prev->crop.top + prev->crop.height - 1;
 
-	if (!(params->features & PREV_CFA)) {
-		sph += 2;
-		eph -= 2;
-		slv += 2;
-		elv -= 2;
+	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_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_HORZ_MEDIAN_FILTER) {
+		sph -= 2;
+		eph += 2;
 	}
-	if (!(params->features & (PREV_CHROMA_SUPPRESS | PREV_LUMA_ENHANCE)))
-		sph += 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);
@@ -1228,7 +1254,6 @@
 	/* 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));
@@ -1281,14 +1306,14 @@
 
 	switch (isp->revision) {
 	case ISP_REVISION_1_0:
-		return ISPPRV_MAXOUTPUT_WIDTH;
+		return PREV_MAX_OUT_WIDTH;
 
 	case ISP_REVISION_2_0:
 	default:
-		return ISPPRV_MAXOUTPUT_WIDTH_ES2;
+		return PREV_MAX_OUT_WIDTH_ES2;
 
 	case ISP_REVISION_15_0:
-		return ISPPRV_MAXOUTPUT_WIDTH_3630;
+		return PREV_MAX_OUT_WIDTH_3630;
 	}
 }
 
@@ -1296,8 +1321,6 @@
 {
 	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);
 
@@ -1335,10 +1358,7 @@
 		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_averager(prev, 0);
 	preview_config_ycpos(prev, format->code);
 }
 
@@ -1597,6 +1617,16 @@
 		return &prev->formats[pad];
 }
 
+static struct v4l2_rect *
+__preview_get_crop(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
+		   enum v4l2_subdev_format_whence which)
+{
+	if (which == V4L2_SUBDEV_FORMAT_TRY)
+		return v4l2_subdev_get_try_crop(fh, PREV_PAD_SINK);
+	else
+		return &prev->crop;
+}
+
 /* previewer format descriptions */
 static const unsigned int preview_input_fmts[] = {
 	V4L2_MBUS_FMT_SGRBG10_1X10,
@@ -1611,24 +1641,25 @@
 };
 
 /*
- * 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
+ * preview_try_format - Validate a format
+ * @prev: ISP preview engine
+ * @fh: V4L2 subdev file handle
+ * @pad: pad number
+ * @fmt: format to be validated
+ * @which: try/active format selector
+ *
+ * Validate and adjust the given format for the given pad based on the preview
+ * engine limits and the format and crop rectangles on other pads.
  */
 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;
+	struct v4l2_rect *crop;
 	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
@@ -1641,10 +1672,11 @@
 		 * 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->width = clamp_t(u32, fmt->width, PREV_MIN_IN_WIDTH,
+					     preview_max_out_width(prev));
+			fmt->height = clamp_t(u32, fmt->height,
+					      PREV_MIN_IN_HEIGHT,
+					      PREV_MAX_IN_HEIGHT);
 		}
 
 		fmt->colorspace = V4L2_COLORSPACE_SRGB;
@@ -1661,15 +1693,8 @@
 
 	case PREV_PAD_SOURCE:
 		pixelcode = fmt->code;
-		format = __preview_get_format(prev, fh, PREV_PAD_SINK, which);
-		memcpy(fmt, format, sizeof(*fmt));
+		*fmt = *__preview_get_format(prev, fh, PREV_PAD_SINK, which);
 
-		/* 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:
@@ -1681,31 +1706,14 @@
 			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.
+		/* The preview module output size is configurable through the
+		 * averager (horizontal scaling by 1/1, 1/2, 1/4 or 1/8). This
+		 * is not supported yet, hardcode the output size to the crop
+		 * rectangle size.
 		 */
-		fmt->width -= 14;
-		fmt->height -= 8;
+		crop = __preview_get_crop(prev, fh, which);
+		fmt->width = crop->width;
+		fmt->height = crop->height;
 
 		fmt->colorspace = V4L2_COLORSPACE_JPEG;
 		break;
@@ -1715,6 +1723,49 @@
 }
 
 /*
+ * preview_try_crop - Validate a crop rectangle
+ * @prev: ISP preview engine
+ * @sink: format on the sink pad
+ * @crop: crop rectangle to be validated
+ *
+ * The preview engine crops lines and columns for its internal operation,
+ * depending on which filters are enabled. Enforce minimum crop margins to
+ * handle that transparently for userspace.
+ *
+ * See the explanation at the PREV_MARGIN_* definitions for more details.
+ */
+static void preview_try_crop(struct isp_prev_device *prev,
+			     const struct v4l2_mbus_framefmt *sink,
+			     struct v4l2_rect *crop)
+{
+	unsigned int left = PREV_MARGIN_LEFT;
+	unsigned int right = sink->width - PREV_MARGIN_RIGHT;
+	unsigned int top = PREV_MARGIN_TOP;
+	unsigned int bottom = sink->height - PREV_MARGIN_BOTTOM;
+
+	/* When processing data on-the-fly from the CCDC, at least 2 pixels must
+	 * be cropped from the left and right sides of the image. As we don't
+	 * know which filters will be enabled, increase the left and right
+	 * margins by two.
+	 */
+	if (prev->input == PREVIEW_INPUT_CCDC) {
+		left += 2;
+		right -= 2;
+	}
+
+	/* Restrict left/top to even values to keep the Bayer pattern. */
+	crop->left &= ~1;
+	crop->top &= ~1;
+
+	crop->left = clamp_t(u32, crop->left, left, right - PREV_MIN_OUT_WIDTH);
+	crop->top = clamp_t(u32, crop->top, top, bottom - PREV_MIN_OUT_HEIGHT);
+	crop->width = clamp_t(u32, crop->width, PREV_MIN_OUT_WIDTH,
+			      right - crop->left);
+	crop->height = clamp_t(u32, crop->height, PREV_MIN_OUT_HEIGHT,
+			       bottom - crop->top);
+}
+
+/*
  * preview_enum_mbus_code - Handle pixel format enumeration
  * @sd     : pointer to v4l2 subdev structure
  * @fh     : V4L2 subdev file handle
@@ -1776,6 +1827,60 @@
 }
 
 /*
+ * preview_get_crop - Retrieve the crop rectangle on a pad
+ * @sd: ISP preview V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @crop: crop rectangle
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+static int preview_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			    struct v4l2_subdev_crop *crop)
+{
+	struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
+
+	/* Cropping is only supported on the sink pad. */
+	if (crop->pad != PREV_PAD_SINK)
+		return -EINVAL;
+
+	crop->rect = *__preview_get_crop(prev, fh, crop->which);
+	return 0;
+}
+
+/*
+ * preview_set_crop - Retrieve the crop rectangle on a pad
+ * @sd: ISP preview V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @crop: crop rectangle
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+static int preview_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			    struct v4l2_subdev_crop *crop)
+{
+	struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	/* Cropping is only supported on the sink pad. */
+	if (crop->pad != PREV_PAD_SINK)
+		return -EINVAL;
+
+	/* The crop rectangle can't be changed while streaming. */
+	if (prev->state != ISP_PIPELINE_STREAM_STOPPED)
+		return -EBUSY;
+
+	format = __preview_get_format(prev, fh, PREV_PAD_SINK, crop->which);
+	preview_try_crop(prev, format, &crop->rect);
+	*__preview_get_crop(prev, fh, crop->which) = crop->rect;
+
+	/* Update the source format. */
+	format = __preview_get_format(prev, fh, PREV_PAD_SOURCE, crop->which);
+	preview_try_format(prev, fh, PREV_PAD_SOURCE, format, crop->which);
+
+	return 0;
+}
+
+/*
  * preview_get_format - Handle get format by pads subdev method
  * @sd : pointer to v4l2 subdev structure
  * @fh : V4L2 subdev file handle
@@ -1808,6 +1913,7 @@
 {
 	struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
 	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *crop;
 
 	format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
 	if (format == NULL)
@@ -1818,9 +1924,18 @@
 
 	/* Propagate the format from sink to source */
 	if (fmt->pad == PREV_PAD_SINK) {
+		/* Reset the crop rectangle. */
+		crop = __preview_get_crop(prev, fh, fmt->which);
+		crop->left = 0;
+		crop->top = 0;
+		crop->width = fmt->format.width;
+		crop->height = fmt->format.height;
+
+		preview_try_crop(prev, &fmt->format, crop);
+
+		/* Update the source format. */
 		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);
 	}
@@ -1869,6 +1984,8 @@
 	.enum_frame_size = preview_enum_frame_size,
 	.get_fmt = preview_get_format,
 	.set_fmt = preview_set_format,
+	.get_crop = preview_get_crop,
+	.set_crop = preview_set_crop,
 };
 
 /* subdev operations */
@@ -1966,8 +2083,44 @@
 	.link_setup = preview_link_setup,
 };
 
+void omap3isp_preview_unregister_entities(struct isp_prev_device *prev)
+{
+	v4l2_device_unregister_subdev(&prev->subdev);
+	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
+ */
+
 /*
- * review_init_entities - Initialize subdev and media entity.
+ * preview_init_entities - Initialize subdev and media entity.
  * @prev : Pointer to preview structure
  * return -ENOMEM or zero on success
  */
@@ -2024,69 +2177,34 @@
 
 	ret = omap3isp_video_init(&prev->video_in, "preview");
 	if (ret < 0)
-		return ret;
+		goto error_video_in;
 
 	ret = omap3isp_video_init(&prev->video_out, "preview");
 	if (ret < 0)
-		return ret;
+		goto error_video_out;
 
 	/* 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;
+		goto error_link;
 
 	ret = media_entity_create_link(&prev->subdev.entity, PREV_PAD_SOURCE,
 			&prev->video_out.video.entity, 0, 0);
 	if (ret < 0)
-		return ret;
+		goto error_link;
 
 	return 0;
-}
 
-void omap3isp_preview_unregister_entities(struct isp_prev_device *prev)
-{
+error_link:
+	omap3isp_video_cleanup(&prev->video_out);
+error_video_out:
+	omap3isp_video_cleanup(&prev->video_in);
+error_video_in:
 	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
@@ -2095,19 +2213,20 @@
 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;
+	return preview_init_entities(prev);
+}
 
-out:
-	if (ret)
-		omap3isp_preview_cleanup(isp);
+void omap3isp_preview_cleanup(struct isp_device *isp)
+{
+	struct isp_prev_device *prev = &isp->isp_prev;
 
-	return ret;
+	v4l2_ctrl_handler_free(&prev->ctrls);
+	omap3isp_video_cleanup(&prev->video_in);
+	omap3isp_video_cleanup(&prev->video_out);
+	media_entity_cleanup(&prev->subdev.entity);
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/isppreview.h linux-libre-3.2-gnu/drivers/media/video/omap3isp/isppreview.h
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/isppreview.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/isppreview.h	2012-01-04 18:55:44.000000000 -0500
@@ -45,11 +45,6 @@
 #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
@@ -106,7 +101,6 @@
  * @rgb2ycbcr: RGB to ycbcr parameters.
  * @hmed: Horizontal median filter.
  * @yclimit: YC limits parameters.
- * @average: Downsampling rate for averager.
  * @contrast: Contrast.
  * @brightness: Brightness.
  */
@@ -124,7 +118,6 @@
 	struct omap3isp_prev_csc rgb2ycbcr;
 	struct omap3isp_prev_hmed hmed;
 	struct omap3isp_prev_yclimit yclimit;
-	u8 average;
 	u8 contrast;
 	u8 brightness;
 };
@@ -159,6 +152,7 @@
  * @subdev: V4L2 subdevice
  * @pads: Media entity pads
  * @formats: Active formats at the subdev pad
+ * @crop: Active crop rectangle
  * @input: Module currently connected to the input pad
  * @output: Bitmask of the active output
  * @video_in: Input video entity
@@ -177,6 +171,7 @@
 	struct v4l2_subdev subdev;
 	struct media_pad pads[PREV_PADS_NUM];
 	struct v4l2_mbus_framefmt formats[PREV_PADS_NUM];
+	struct v4l2_rect crop;
 
 	struct v4l2_ctrl_handler ctrls;
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispqueue.c linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispqueue.c
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispqueue.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispqueue.c	2012-01-04 18:55:44.000000000 -0500
@@ -868,6 +868,10 @@
 		goto done;
 
 	if (vbuf->memory == V4L2_MEMORY_USERPTR &&
+	    vbuf->length < buf->vbuf.length)
+		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;
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispreg.h linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispreg.h
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispreg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispreg.h	2012-01-04 18:55:44.000000000 -0500
@@ -402,9 +402,6 @@
 #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
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispresizer.c linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispresizer.c
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispresizer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispresizer.c	2012-01-04 18:55:44.000000000 -0500
@@ -1608,6 +1608,42 @@
 	.link_setup = resizer_link_setup,
 };
 
+void omap3isp_resizer_unregister_entities(struct isp_res_device *res)
+{
+	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
+ */
+
 /*
  * resizer_init_entities - Initialize resizer subdev and media entity.
  * @res : Pointer to resizer device structure
@@ -1652,68 +1688,34 @@
 
 	ret = omap3isp_video_init(&res->video_in, "resizer");
 	if (ret < 0)
-		return ret;
+		goto error_video_in;
 
 	ret = omap3isp_video_init(&res->video_out, "resizer");
 	if (ret < 0)
-		return ret;
+		goto error_video_out;
 
 	/* 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;
+		goto error_link;
 
 	ret = media_entity_create_link(&res->subdev.entity, RESZ_PAD_SOURCE,
 			&res->video_out.video.entity, 0, 0);
 	if (ret < 0)
-		return ret;
+		goto error_link;
 
 	return 0;
-}
 
-void omap3isp_resizer_unregister_entities(struct isp_res_device *res)
-{
+error_link:
+	omap3isp_video_cleanup(&res->video_out);
+error_video_out:
+	omap3isp_video_cleanup(&res->video_in);
+error_video_in:
 	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
@@ -1722,17 +1724,17 @@
 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;
+	return resizer_init_entities(res);
+}
 
-out:
-	if (ret)
-		omap3isp_resizer_cleanup(isp);
+void omap3isp_resizer_cleanup(struct isp_device *isp)
+{
+	struct isp_res_device *res = &isp->isp_res;
 
-	return ret;
+	omap3isp_video_cleanup(&res->video_in);
+	omap3isp_video_cleanup(&res->video_out);
+	media_entity_cleanup(&res->subdev.entity);
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispstat.c linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispstat.c
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispstat.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispstat.c	2012-01-04 18:55:44.000000000 -0500
@@ -366,7 +366,8 @@
 				dma_unmap_sg(isp->dev, buf->iovm->sgt->sgl,
 					     buf->iovm->sgt->nents,
 					     DMA_FROM_DEVICE);
-			iommu_vfree(isp->iommu, buf->iommu_addr);
+			omap_iommu_vfree(isp->domain, isp->iommu,
+							buf->iommu_addr);
 		} else {
 			if (!buf->virt_addr)
 				continue;
@@ -399,8 +400,8 @@
 		struct iovm_struct *iovm;
 
 		WARN_ON(buf->dma_addr);
-		buf->iommu_addr = iommu_vmalloc(isp->iommu, 0, size,
-						IOMMU_FLAG);
+		buf->iommu_addr = omap_iommu_vmalloc(isp->domain, isp->iommu, 0,
+							size, IOMMU_FLAG);
 		if (IS_ERR((void *)buf->iommu_addr)) {
 			dev_err(stat->isp->dev,
 				 "%s: Can't acquire memory for "
@@ -409,7 +410,7 @@
 			return -ENOMEM;
 		}
 
-		iovm = find_iovm_area(isp->iommu, buf->iommu_addr);
+		iovm = omap_find_iovm_area(isp->iommu, buf->iommu_addr);
 		if (!iovm ||
 		    !dma_map_sg(isp->dev, iovm->sgt->sgl, iovm->sgt->nents,
 				DMA_FROM_DEVICE)) {
@@ -418,7 +419,7 @@
 		}
 		buf->iovm = iovm;
 
-		buf->virt_addr = da_to_va(stat->isp->iommu,
+		buf->virt_addr = omap_da_to_va(stat->isp->iommu,
 					  (u32)buf->iommu_addr);
 		buf->empty = 1;
 		dev_dbg(stat->isp->dev, "%s: buffer[%d] allocated."
@@ -495,7 +496,7 @@
 
 static void isp_stat_queue_event(struct ispstat *stat, int err)
 {
-	struct video_device *vdev = &stat->subdev.devnode;
+	struct video_device *vdev = stat->subdev.devnode;
 	struct v4l2_event event;
 	struct omap3isp_stat_event_status *status = (void *)event.u.data;
 
@@ -1022,24 +1023,6 @@
 	__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;
-	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)
@@ -1061,7 +1044,6 @@
 
 void omap3isp_stat_unregister_entities(struct ispstat *stat)
 {
-	media_entity_cleanup(&stat->subdev.entity);
 	v4l2_device_unregister_subdev(&stat->subdev);
 }
 
@@ -1071,21 +1053,50 @@
 	return v4l2_device_register_subdev(vdev, &stat->subdev);
 }
 
+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;
+	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_init(struct ispstat *stat, const char *name,
 		       const struct v4l2_subdev_ops *sd_ops)
 {
+	int ret;
+
 	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);
+	ret = isp_stat_init_entities(stat, name, sd_ops);
+	if (ret < 0) {
+		mutex_destroy(&stat->ioctl_lock);
+		kfree(stat->buf);
+	}
+
+	return ret;
 }
 
-void omap3isp_stat_free(struct ispstat *stat)
+void omap3isp_stat_cleanup(struct ispstat *stat)
 {
+	media_entity_cleanup(&stat->subdev.entity);
+	mutex_destroy(&stat->ioctl_lock);
 	isp_stat_bufs_free(stat);
 	kfree(stat->buf);
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispstat.h linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispstat.h
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispstat.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispstat.h	2012-01-04 18:55:44.000000000 -0500
@@ -144,7 +144,7 @@
 				     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);
+void omap3isp_stat_cleanup(struct ispstat *stat);
 int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
 				  struct v4l2_fh *fh,
 				  struct v4l2_event_subscription *sub);
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispvideo.c linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispvideo.c
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispvideo.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispvideo.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <asm/cacheflush.h>
 #include <linux/clk.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/pagemap.h>
 #include <linux/scatterlist.h>
 #include <linux/sched.h>
@@ -278,7 +279,8 @@
  * 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.
+ * different formats on its two ends or if the pipeline doesn't start with a
+ * video source (either a subdev with no input pad, or a non-subdev entity).
  */
 static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
 {
@@ -329,10 +331,15 @@
 		 * in the middle of it. */
 		shifter_link = subdev == &isp->isp_ccdc.subdev;
 
-		/* Retrieve the source format */
+		/* Retrieve the source format. Return an error if no source
+		 * entity can be found, and stop checking the pipeline if the
+		 * source entity isn't a subdev.
+		 */
 		pad = media_entity_remote_source(pad);
-		if (pad == NULL ||
-		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		if (pad == NULL)
+			return -EPIPE;
+
+		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
 			break;
 
 		subdev = media_entity_to_v4l2_subdev(pad->entity);
@@ -446,7 +453,7 @@
 	sgt->nents = sglen;
 	sgt->orig_nents = sglen;
 
-	da = iommu_vmap(isp->iommu, 0, sgt, IOMMU_FLAG);
+	da = omap_iommu_vmap(isp->domain, isp->iommu, 0, sgt, IOMMU_FLAG);
 	if (IS_ERR_VALUE(da))
 		kfree(sgt);
 
@@ -462,7 +469,7 @@
 {
 	struct sg_table *sgt;
 
-	sgt = iommu_vunmap(isp->iommu, (u32)da);
+	sgt = omap_iommu_vunmap(isp->domain, isp->iommu, (u32)da);
 	kfree(sgt);
 }
 
@@ -1050,6 +1057,14 @@
 		if (video->isp->pdata->set_constraints)
 			video->isp->pdata->set_constraints(video->isp, false);
 		media_entity_pipeline_stop(&video->video.entity);
+		/* The DMA queue must be emptied here, otherwise CCDC interrupts
+		 * that will get triggered the next time the CCDC is powered up
+		 * will try to access buffers that might have been freed but
+		 * still present in the DMA queue. This can easily get triggered
+		 * if the above omap3isp_pipeline_set_stream() call fails on a
+		 * system with a free-running sensor.
+		 */
+		INIT_LIST_HEAD(&video->dmaqueue);
 		video->queue = NULL;
 	}
 
@@ -1311,6 +1326,13 @@
 	return 0;
 }
 
+void omap3isp_video_cleanup(struct isp_video *video)
+{
+	media_entity_cleanup(&video->video.entity);
+	mutex_destroy(&video->stream_lock);
+	mutex_destroy(&video->mutex);
+}
+
 int omap3isp_video_register(struct isp_video *video, struct v4l2_device *vdev)
 {
 	int ret;
@@ -1327,8 +1349,6 @@
 
 void omap3isp_video_unregister(struct isp_video *video)
 {
-	if (video_is_registered(&video->video)) {
-		media_entity_cleanup(&video->video.entity);
+	if (video_is_registered(&video->video))
 		video_unregister_device(&video->video);
-	}
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispvideo.h linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispvideo.h
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/ispvideo.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/ispvideo.h	2012-01-04 18:55:44.000000000 -0500
@@ -190,6 +190,7 @@
 				container_of(q, struct isp_video_fh, queue)
 
 int omap3isp_video_init(struct isp_video *video, const char *name);
+void omap3isp_video_cleanup(struct isp_video *video);
 int omap3isp_video_register(struct isp_video *video,
 			    struct v4l2_device *vdev);
 void omap3isp_video_unregister(struct isp_video *video);
diff -druN linux-libre-3.1-gnu/drivers/media/video/omap3isp/Makefile linux-libre-3.2-gnu/drivers/media/video/omap3isp/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/omap3isp/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/omap3isp/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,8 +1,6 @@
 # Makefile for OMAP3 ISP driver
 
-ifdef CONFIG_VIDEO_OMAP3_DEBUG
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_VIDEO_OMAP3_DEBUG) += -DDEBUG
 
 omap3-isp-objs += \
 	isp.o ispqueue.o ispvideo.o \
diff -druN linux-libre-3.1-gnu/drivers/media/video/ov2640.c linux-libre-3.2-gnu/drivers/media/video/ov2640.c
--- linux-libre-3.1-gnu/drivers/media/video/ov2640.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/ov2640.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,11 +18,13 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/videodev2.h>
+
+#include <media/soc_camera.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-subdev.h>
-#include <media/soc_camera.h>
-#include <media/soc_mediabus.h>
+#include <media/v4l2-ctrls.h>
 
 #define VAL_SET(x, mask, rshift, lshift)  \
 		((((x) >> rshift) & mask) << lshift)
@@ -299,12 +301,10 @@
 
 struct ov2640_priv {
 	struct v4l2_subdev		subdev;
-	struct ov2640_camera_info	*info;
+	struct v4l2_ctrl_handler	hdl;
 	enum v4l2_mbus_pixelcode	cfmt_code;
 	const struct ov2640_win_size	*win;
 	int				model;
-	u16				flag_vflip:1;
-	u16				flag_hflip:1;
 };
 
 /*
@@ -610,29 +610,6 @@
 };
 
 /*
- * Supported controls
- */
-static const struct v4l2_queryctrl ov2640_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,
-	},
-};
-
-/*
  * General functions
  */
 static struct ov2640_priv *to_ov2640(const struct i2c_client *client)
@@ -701,81 +678,23 @@
 	return 0;
 }
 
-static int ov2640_set_bus_param(struct soc_camera_device *icd,
-				unsigned long flags)
-{
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-	unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK;
-
-	/* Only one width bit may be set */
-	if (!is_power_of_2(width_flag))
-		return -EINVAL;
-
-	if (icl->set_bus_param)
-		return icl->set_bus_param(icl, width_flag);
-
-	/*
-	 * Without board specific bus width settings we support only the
-	 * sensors native bus width witch are tested working
-	 */
-	if (width_flag & (SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8))
-		return 0;
-
-	return 0;
-}
-
-static unsigned long ov2640_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;
-
-	if (icl->query_bus_param)
-		flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK;
-	else
-		flags |= SOCAM_DATAWIDTH_10;
-
-	return soc_camera_apply_sensor_flags(icl, flags);
-}
-
-static int ov2640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct i2c_client  *client = v4l2_get_subdevdata(sd);
-	struct ov2640_priv *priv = to_ov2640(client);
-
-	switch (ctrl->id) {
-	case V4L2_CID_VFLIP:
-		ctrl->value = priv->flag_vflip;
-		break;
-	case V4L2_CID_HFLIP:
-		ctrl->value = priv->flag_hflip;
-		break;
-	}
-	return 0;
-}
-
-static int ov2640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int ov2640_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct v4l2_subdev *sd =
+		&container_of(ctrl->handler, struct ov2640_priv, hdl)->subdev;
 	struct i2c_client  *client = v4l2_get_subdevdata(sd);
-	struct ov2640_priv *priv = to_ov2640(client);
-	int ret = 0;
 	u8 val;
 
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
-		val = ctrl->value ? REG04_VFLIP_IMG : 0x00;
-		priv->flag_vflip = ctrl->value ? 1 : 0;
-		ret = ov2640_mask_set(client, REG04, REG04_VFLIP_IMG, val);
-		break;
+		val = ctrl->val ? REG04_VFLIP_IMG : 0x00;
+		return ov2640_mask_set(client, REG04, REG04_VFLIP_IMG, val);
 	case V4L2_CID_HFLIP:
-		val = ctrl->value ? REG04_HFLIP_IMG : 0x00;
-		priv->flag_hflip = ctrl->value ? 1 : 0;
-		ret = ov2640_mask_set(client, REG04, REG04_HFLIP_IMG, val);
-		break;
+		val = ctrl->val ? REG04_HFLIP_IMG : 0x00;
+		return ov2640_mask_set(client, REG04, REG04_HFLIP_IMG, val);
 	}
 
-	return ret;
+	return -EINVAL;
 }
 
 static int ov2640_g_chip_ident(struct v4l2_subdev *sd,
@@ -1023,18 +942,13 @@
 	return 0;
 }
 
-static int ov2640_video_probe(struct soc_camera_device *icd,
-			      struct i2c_client *client)
+static int ov2640_video_probe(struct i2c_client *client)
 {
 	struct ov2640_priv *priv = to_ov2640(client);
 	u8 pid, ver, midh, midl;
 	const char *devname;
 	int ret;
 
-	/* We must have a parent by now. And it cannot be a wrong one. */
-	BUG_ON(!icd->parent ||
-	       to_soc_camera_host(icd->parent)->nr != icd->iface);
-
 	/*
 	 * check and show product ID and manufacturer ID
 	 */
@@ -1060,22 +974,17 @@
 		 "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
 		 devname, pid, ver, midh, midl);
 
-	return 0;
+	return v4l2_ctrl_handler_setup(&priv->hdl);
 
 err:
 	return ret;
 }
 
-static struct soc_camera_ops ov2640_ops = {
-	.set_bus_param		= ov2640_set_bus_param,
-	.query_bus_param	= ov2640_query_bus_param,
-	.controls		= ov2640_controls,
-	.num_controls		= ARRAY_SIZE(ov2640_controls),
+static const struct v4l2_ctrl_ops ov2640_ctrl_ops = {
+	.s_ctrl = ov2640_s_ctrl,
 };
 
 static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {
-	.g_ctrl		= ov2640_g_ctrl,
-	.s_ctrl		= ov2640_s_ctrl,
 	.g_chip_ident	= ov2640_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register	= ov2640_g_register,
@@ -1083,6 +992,21 @@
 #endif
 };
 
+static int ov2640_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
 static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = {
 	.s_stream	= ov2640_s_stream,
 	.g_mbus_fmt	= ov2640_g_fmt,
@@ -1091,6 +1015,7 @@
 	.cropcap	= ov2640_cropcap,
 	.g_crop		= ov2640_g_crop,
 	.enum_mbus_fmt	= ov2640_enum_fmt,
+	.g_mbus_config	= ov2640_g_mbus_config,
 };
 
 static struct v4l2_subdev_ops ov2640_subdev_ops = {
@@ -1104,18 +1029,11 @@
 static int ov2640_probe(struct i2c_client *client,
 			const struct i2c_device_id *did)
 {
-	struct ov2640_priv        *priv;
-	struct soc_camera_device  *icd = client->dev.platform_data;
-	struct i2c_adapter        *adapter = to_i2c_adapter(client->dev.parent);
-	struct soc_camera_link    *icl;
-	int                        ret;
-
-	if (!icd) {
-		dev_err(&adapter->dev, "OV2640: missing soc-camera data!\n");
-		return -EINVAL;
-	}
+	struct ov2640_priv	*priv;
+	struct soc_camera_link	*icl = soc_camera_i2c_to_link(client);
+	struct i2c_adapter	*adapter = to_i2c_adapter(client->dev.parent);
+	int			ret;
 
-	icl = to_soc_camera_link(icd);
 	if (!icl) {
 		dev_err(&adapter->dev,
 			"OV2640: Missing platform_data for driver\n");
@@ -1135,15 +1053,23 @@
 		return -ENOMEM;
 	}
 
-	priv->info = icl->priv;
-
 	v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops);
+	v4l2_ctrl_handler_init(&priv->hdl, 2);
+	v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	priv->subdev.ctrl_handler = &priv->hdl;
+	if (priv->hdl.error) {
+		int err = priv->hdl.error;
 
-	icd->ops = &ov2640_ops;
+		kfree(priv);
+		return err;
+	}
 
-	ret = ov2640_video_probe(icd, client);
+	ret = ov2640_video_probe(client);
 	if (ret) {
-		icd->ops = NULL;
+		v4l2_ctrl_handler_free(&priv->hdl);
 		kfree(priv);
 	} else {
 		dev_info(&adapter->dev, "OV2640 Probed\n");
@@ -1155,9 +1081,9 @@
 static int ov2640_remove(struct i2c_client *client)
 {
 	struct ov2640_priv       *priv = to_ov2640(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
 
-	icd->ops = NULL;
+	v4l2_device_unregister_subdev(&priv->subdev);
+	v4l2_ctrl_handler_free(&priv->hdl);
 	kfree(priv);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/ov5642.c linux-libre-3.2-gnu/drivers/media/video/ov5642.c
--- linux-libre-3.1-gnu/drivers/media/video/ov5642.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/ov5642.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,14 +14,16 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
+#include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 #include <linux/module.h>
+#include <linux/v4l2-mediabus.h>
 
 #include <media/soc_camera.h>
-#include <media/soc_mediabus.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-subdev.h>
 
@@ -35,7 +37,7 @@
 #define REG_WINDOW_START_Y_LOW		0x3803
 #define REG_WINDOW_WIDTH_HIGH		0x3804
 #define REG_WINDOW_WIDTH_LOW		0x3805
-#define REG_WINDOW_HEIGHT_HIGH 		0x3806
+#define REG_WINDOW_HEIGHT_HIGH		0x3806
 #define REG_WINDOW_HEIGHT_LOW		0x3807
 #define REG_OUT_WIDTH_HIGH		0x3808
 #define REG_OUT_WIDTH_LOW		0x3809
@@ -45,19 +47,44 @@
 #define REG_OUT_TOTAL_WIDTH_LOW		0x380d
 #define REG_OUT_TOTAL_HEIGHT_HIGH	0x380e
 #define REG_OUT_TOTAL_HEIGHT_LOW	0x380f
+#define REG_OUTPUT_FORMAT		0x4300
+#define REG_ISP_CTRL_01			0x5001
+#define REG_AVG_WINDOW_END_X_HIGH	0x5682
+#define REG_AVG_WINDOW_END_X_LOW	0x5683
+#define REG_AVG_WINDOW_END_Y_HIGH	0x5686
+#define REG_AVG_WINDOW_END_Y_LOW	0x5687
+
+/* active pixel array size */
+#define OV5642_SENSOR_SIZE_X	2592
+#define OV5642_SENSOR_SIZE_Y	1944
 
 /*
- * define standard resolution.
- * Works currently only for up to 720 lines
- * eg. 320x240, 640x480, 800x600, 1280x720, 2048x720
+ * About OV5642 resolution, cropping and binning:
+ * This sensor supports it all, at least in the feature description.
+ * Unfortunately, no combination of appropriate registers settings could make
+ * the chip work the intended way. As it works with predefined register lists,
+ * some undocumented registers are presumably changed there to achieve their
+ * goals.
+ * This driver currently only works for resolutions up to 720 lines with a
+ * 1:1 scale. Hopefully these restrictions will be removed in the future.
  */
+#define OV5642_MAX_WIDTH	OV5642_SENSOR_SIZE_X
+#define OV5642_MAX_HEIGHT	720
 
-#define OV5642_WIDTH		1280
-#define OV5642_HEIGHT		720
-#define OV5642_TOTAL_WIDTH	3200
-#define OV5642_TOTAL_HEIGHT	2000
-#define OV5642_SENSOR_SIZE_X	2592
-#define OV5642_SENSOR_SIZE_Y	1944
+/* default sizes */
+#define OV5642_DEFAULT_WIDTH	1280
+#define OV5642_DEFAULT_HEIGHT	OV5642_MAX_HEIGHT
+
+/* minimum extra blanking */
+#define BLANKING_EXTRA_WIDTH		500
+#define BLANKING_EXTRA_HEIGHT		20
+
+/*
+ * the sensor's autoexposure is buggy when setting total_height low.
+ * It tries to expose longer than 1 frame period without taking care of it
+ * and this leads to weird output. So we set 1000 lines as minimum.
+ */
+#define BLANKING_MIN_HEIGHT		1000
 
 struct regval_list {
 	u16 reg_num;
@@ -582,6 +609,11 @@
 struct ov5642 {
 	struct v4l2_subdev		subdev;
 	const struct ov5642_datafmt	*fmt;
+	struct v4l2_rect                crop_rect;
+
+	/* blanking information */
+	int total_width;
+	int total_height;
 };
 
 static const struct ov5642_datafmt ov5642_colour_fmts[] = {
@@ -642,6 +674,21 @@
 
 	return 0;
 }
+
+/*
+ * convenience function to write 16 bit register values that are split up
+ * into two consecutive high and low parts
+ */
+static int reg_write16(struct i2c_client *client, u16 reg, u16 val16)
+{
+	int ret;
+
+	ret = reg_write(client, reg, val16 >> 8);
+	if (ret)
+		return ret;
+	return reg_write(client, reg + 1, val16 & 0x00ff);
+}
+
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int ov5642_get_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
@@ -685,58 +732,55 @@
 	return 0;
 }
 
-static int ov5642_set_resolution(struct i2c_client *client)
+static int ov5642_set_resolution(struct v4l2_subdev *sd)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov5642 *priv = to_ov5642(client);
+	int width = priv->crop_rect.width;
+	int height = priv->crop_rect.height;
+	int total_width = priv->total_width;
+	int total_height = priv->total_height;
+	int start_x = (OV5642_SENSOR_SIZE_X - width) / 2;
+	int start_y = (OV5642_SENSOR_SIZE_Y - height) / 2;
 	int ret;
-	u8 start_x_high = ((OV5642_SENSOR_SIZE_X - OV5642_WIDTH) / 2) >> 8;
-	u8 start_x_low  = ((OV5642_SENSOR_SIZE_X - OV5642_WIDTH) / 2) & 0xff;
-	u8 start_y_high = ((OV5642_SENSOR_SIZE_Y - OV5642_HEIGHT) / 2) >> 8;
-	u8 start_y_low  = ((OV5642_SENSOR_SIZE_Y - OV5642_HEIGHT) / 2) & 0xff;
-
-	u8 width_high	= OV5642_WIDTH  >> 8;
-	u8 width_low	= OV5642_WIDTH  & 0xff;
-	u8 height_high	= OV5642_HEIGHT >> 8;
-	u8 height_low	= OV5642_HEIGHT & 0xff;
-
-	u8 total_width_high  = OV5642_TOTAL_WIDTH  >> 8;
-	u8 total_width_low   = OV5642_TOTAL_WIDTH  & 0xff;
-	u8 total_height_high = OV5642_TOTAL_HEIGHT >> 8;
-	u8 total_height_low  = OV5642_TOTAL_HEIGHT & 0xff;
 
-	ret = reg_write(client, REG_WINDOW_START_X_HIGH, start_x_high);
-	if (!ret)
-		ret = reg_write(client, REG_WINDOW_START_X_LOW, start_x_low);
-	if (!ret)
-		ret = reg_write(client, REG_WINDOW_START_Y_HIGH, start_y_high);
+	/*
+	 * This should set the starting point for cropping.
+	 * Doesn't work so far.
+	 */
+	ret = reg_write16(client, REG_WINDOW_START_X_HIGH, start_x);
 	if (!ret)
-		ret = reg_write(client, REG_WINDOW_START_Y_LOW, start_y_low);
+		ret = reg_write16(client, REG_WINDOW_START_Y_HIGH, start_y);
+	if (!ret) {
+		priv->crop_rect.left = start_x;
+		priv->crop_rect.top = start_y;
+	}
 
 	if (!ret)
-		ret = reg_write(client, REG_WINDOW_WIDTH_HIGH, width_high);
-	if (!ret)
-		ret = reg_write(client, REG_WINDOW_WIDTH_LOW , width_low);
-	if (!ret)
-		ret = reg_write(client, REG_WINDOW_HEIGHT_HIGH, height_high);
+		ret = reg_write16(client, REG_WINDOW_WIDTH_HIGH, width);
 	if (!ret)
-		ret = reg_write(client, REG_WINDOW_HEIGHT_LOW,  height_low);
+		ret = reg_write16(client, REG_WINDOW_HEIGHT_HIGH, height);
+	if (ret)
+		return ret;
+	priv->crop_rect.width = width;
+	priv->crop_rect.height = height;
 
+	/* Set the output window size. Only 1:1 scale is supported so far. */
+	ret = reg_write16(client, REG_OUT_WIDTH_HIGH, width);
 	if (!ret)
-		ret = reg_write(client, REG_OUT_WIDTH_HIGH, width_high);
-	if (!ret)
-		ret = reg_write(client, REG_OUT_WIDTH_LOW , width_low);
-	if (!ret)
-		ret = reg_write(client, REG_OUT_HEIGHT_HIGH, height_high);
-	if (!ret)
-		ret = reg_write(client, REG_OUT_HEIGHT_LOW,  height_low);
+		ret = reg_write16(client, REG_OUT_HEIGHT_HIGH, height);
 
+	/* Total width = output size + blanking */
 	if (!ret)
-		ret = reg_write(client, REG_OUT_TOTAL_WIDTH_HIGH, total_width_high);
+		ret = reg_write16(client, REG_OUT_TOTAL_WIDTH_HIGH, total_width);
 	if (!ret)
-		ret = reg_write(client, REG_OUT_TOTAL_WIDTH_LOW, total_width_low);
+		ret = reg_write16(client, REG_OUT_TOTAL_HEIGHT_HIGH, total_height);
+
+	/* Sets the window for AWB calculations */
 	if (!ret)
-		ret = reg_write(client, REG_OUT_TOTAL_HEIGHT_HIGH, total_height_high);
+		ret = reg_write16(client, REG_AVG_WINDOW_END_X_HIGH, width);
 	if (!ret)
-		ret = reg_write(client, REG_OUT_TOTAL_HEIGHT_LOW,  total_height_low);
+		ret = reg_write16(client, REG_AVG_WINDOW_END_Y_HIGH, height);
 
 	return ret;
 }
@@ -744,18 +788,18 @@
 static int ov5642_try_fmt(struct v4l2_subdev *sd,
 			  struct v4l2_mbus_framefmt *mf)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov5642 *priv = to_ov5642(client);
 	const struct ov5642_datafmt *fmt = ov5642_find_datafmt(mf->code);
 
-	dev_dbg(sd->v4l2_dev->dev, "%s(%u) width: %u heigth: %u\n",
-			__func__, mf->code, mf->width, mf->height);
+	mf->width = priv->crop_rect.width;
+	mf->height = priv->crop_rect.height;
 
 	if (!fmt) {
 		mf->code	= ov5642_colour_fmts[0].code;
 		mf->colorspace	= ov5642_colour_fmts[0].colorspace;
 	}
 
-	mf->width	= OV5642_WIDTH;
-	mf->height	= OV5642_HEIGHT;
 	mf->field	= V4L2_FIELD_NONE;
 
 	return 0;
@@ -767,20 +811,13 @@
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct ov5642 *priv = to_ov5642(client);
 
-	dev_dbg(sd->v4l2_dev->dev, "%s(%u)\n", __func__, mf->code);
-
 	/* MIPI CSI could have changed the format, double-check */
 	if (!ov5642_find_datafmt(mf->code))
 		return -EINVAL;
 
 	ov5642_try_fmt(sd, mf);
-
 	priv->fmt = ov5642_find_datafmt(mf->code);
 
-	ov5642_write_array(client, ov5642_default_regs_init);
-	ov5642_set_resolution(client);
-	ov5642_write_array(client, ov5642_default_regs_finalise);
-
 	return 0;
 }
 
@@ -794,8 +831,8 @@
 
 	mf->code	= fmt->code;
 	mf->colorspace	= fmt->colorspace;
-	mf->width	= OV5642_WIDTH;
-	mf->height	= OV5642_HEIGHT;
+	mf->width	= priv->crop_rect.width;
+	mf->height	= priv->crop_rect.height;
 	mf->field	= V4L2_FIELD_NONE;
 
 	return 0;
@@ -828,15 +865,44 @@
 	return 0;
 }
 
+static int ov5642_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov5642 *priv = to_ov5642(client);
+	struct v4l2_rect *rect = &a->c;
+	int ret;
+
+	v4l_bound_align_image(&rect->width, 48, OV5642_MAX_WIDTH, 1,
+			      &rect->height, 32, OV5642_MAX_HEIGHT, 1, 0);
+
+	priv->crop_rect.width	= rect->width;
+	priv->crop_rect.height	= rect->height;
+	priv->total_width	= rect->width + BLANKING_EXTRA_WIDTH;
+	priv->total_height	= max_t(int, rect->height +
+							BLANKING_EXTRA_HEIGHT,
+							BLANKING_MIN_HEIGHT);
+	priv->crop_rect.width		= rect->width;
+	priv->crop_rect.height		= rect->height;
+
+	ret = ov5642_write_array(client, ov5642_default_regs_init);
+	if (!ret)
+		ret = ov5642_set_resolution(sd);
+	if (!ret)
+		ret = ov5642_write_array(client, ov5642_default_regs_finalise);
+
+	return ret;
+}
+
 static int ov5642_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov5642 *priv = to_ov5642(client);
 	struct v4l2_rect *rect = &a->c;
 
-	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	rect->top	= 0;
-	rect->left	= 0;
-	rect->width	= OV5642_WIDTH;
-	rect->height	= OV5642_HEIGHT;
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	*rect = priv->crop_rect;
 
 	return 0;
 }
@@ -845,8 +911,8 @@
 {
 	a->bounds.left			= 0;
 	a->bounds.top			= 0;
-	a->bounds.width			= OV5642_WIDTH;
-	a->bounds.height		= OV5642_HEIGHT;
+	a->bounds.width			= OV5642_MAX_WIDTH;
+	a->bounds.height		= OV5642_MAX_HEIGHT;
 	a->defrect			= a->bounds;
 	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	a->pixelaspect.numerator	= 1;
@@ -855,16 +921,47 @@
 	return 0;
 }
 
+static int ov5642_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	cfg->type = V4L2_MBUS_CSI2;
+	cfg->flags = V4L2_MBUS_CSI2_2_LANE | V4L2_MBUS_CSI2_CHANNEL_0 |
+					V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
+
+	return 0;
+}
+
+static int ov5642_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct i2c_client *client;
+	int ret;
+
+	if (!on)
+		return 0;
+
+	client = v4l2_get_subdevdata(sd);
+	ret = ov5642_write_array(client, ov5642_default_regs_init);
+	if (!ret)
+		ret = ov5642_set_resolution(sd);
+	if (!ret)
+		ret = ov5642_write_array(client, ov5642_default_regs_finalise);
+
+	return ret;
+}
+
 static struct v4l2_subdev_video_ops ov5642_subdev_video_ops = {
 	.s_mbus_fmt	= ov5642_s_fmt,
 	.g_mbus_fmt	= ov5642_g_fmt,
 	.try_mbus_fmt	= ov5642_try_fmt,
 	.enum_mbus_fmt	= ov5642_enum_fmt,
+	.s_crop		= ov5642_s_crop,
 	.g_crop		= ov5642_g_crop,
 	.cropcap	= ov5642_cropcap,
+	.g_mbus_config	= ov5642_g_mbus_config,
 };
 
 static struct v4l2_subdev_core_ops ov5642_subdev_core_ops = {
+	.s_power	= ov5642_s_power,
 	.g_chip_ident	= ov5642_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register	= ov5642_get_register,
@@ -877,28 +974,7 @@
 	.video	= &ov5642_subdev_video_ops,
 };
 
-/*
- * We have to provide soc-camera operations, but we don't have anything to say
- * there. The MIPI CSI2 driver will provide .query_bus_param and .set_bus_param
- */
-static unsigned long soc_ov5642_query_bus_param(struct soc_camera_device *icd)
-{
-	return 0;
-}
-
-static int soc_ov5642_set_bus_param(struct soc_camera_device *icd,
-				 unsigned long flags)
-{
-	return -EINVAL;
-}
-
-static struct soc_camera_ops soc_ov5642_ops = {
-	.query_bus_param	= soc_ov5642_query_bus_param,
-	.set_bus_param		= soc_ov5642_set_bus_param,
-};
-
-static int ov5642_video_probe(struct soc_camera_device *icd,
-			      struct i2c_client *client)
+static int ov5642_video_probe(struct i2c_client *client)
 {
 	int ret;
 	u8 id_high, id_low;
@@ -929,16 +1005,9 @@
 			const struct i2c_device_id *did)
 {
 	struct ov5642 *priv;
-	struct soc_camera_device *icd = client->dev.platform_data;
-	struct soc_camera_link *icl;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 	int ret;
 
-	if (!icd) {
-		dev_err(&client->dev, "OV5642: missing soc-camera data!\n");
-		return -EINVAL;
-	}
-
-	icl = to_soc_camera_link(icd);
 	if (!icl) {
 		dev_err(&client->dev, "OV5642: missing platform data!\n");
 		return -EINVAL;
@@ -950,17 +1019,24 @@
 
 	v4l2_i2c_subdev_init(&priv->subdev, client, &ov5642_subdev_ops);
 
-	icd->ops	= &soc_ov5642_ops;
-	priv->fmt	= &ov5642_colour_fmts[0];
+	priv->fmt		= &ov5642_colour_fmts[0];
 
-	ret = ov5642_video_probe(icd, client);
+	priv->crop_rect.width	= OV5642_DEFAULT_WIDTH;
+	priv->crop_rect.height	= OV5642_DEFAULT_HEIGHT;
+	priv->crop_rect.left	= (OV5642_MAX_WIDTH - OV5642_DEFAULT_WIDTH) / 2;
+	priv->crop_rect.top	= (OV5642_MAX_HEIGHT - OV5642_DEFAULT_HEIGHT) / 2;
+	priv->crop_rect.width	= OV5642_DEFAULT_WIDTH;
+	priv->crop_rect.height	= OV5642_DEFAULT_HEIGHT;
+	priv->total_width = OV5642_DEFAULT_WIDTH + BLANKING_EXTRA_WIDTH;
+	priv->total_height = BLANKING_MIN_HEIGHT;
+
+	ret = ov5642_video_probe(client);
 	if (ret < 0)
 		goto error;
 
 	return 0;
 
 error:
-	icd->ops = NULL;
 	kfree(priv);
 	return ret;
 }
@@ -968,10 +1044,8 @@
 static int ov5642_remove(struct i2c_client *client)
 {
 	struct ov5642 *priv = to_ov5642(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 
-	icd->ops = NULL;
 	if (icl->free_bus)
 		icl->free_bus(icl);
 	kfree(priv);
diff -druN linux-libre-3.1-gnu/drivers/media/video/ov6650.c linux-libre-3.2-gnu/drivers/media/video/ov6650.c
--- linux-libre-3.1-gnu/drivers/media/video/ov6650.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/ov6650.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,10 +28,12 @@
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/module.h>
 
 #include <media/soc_camera.h>
 #include <media/v4l2-chip-ident.h>
-
+#include <media/v4l2-ctrls.h>
 
 /* Register definitions */
 #define REG_GAIN		0x00	/* range 00 - 3F */
@@ -177,20 +179,23 @@
 
 struct ov6650 {
 	struct v4l2_subdev	subdev;
-
-	int			gain;
-	int			blue;
-	int			red;
-	int			saturation;
-	int			hue;
-	int			brightness;
-	int			exposure;
-	int			gamma;
-	int			aec;
-	bool			vflip;
-	bool			hflip;
-	bool			awb;
-	bool			agc;
+	struct v4l2_ctrl_handler hdl;
+	struct {
+		/* exposure/autoexposure cluster */
+		struct v4l2_ctrl *autoexposure;
+		struct v4l2_ctrl *exposure;
+	};
+	struct {
+		/* gain/autogain cluster */
+		struct v4l2_ctrl *autogain;
+		struct v4l2_ctrl *gain;
+	};
+	struct {
+		/* blue/red/autowhitebalance cluster */
+		struct v4l2_ctrl *autowb;
+		struct v4l2_ctrl *blue;
+		struct v4l2_ctrl *red;
+	};
 	bool			half_scale;	/* scale down output by 2 */
 	struct v4l2_rect	rect;		/* sensor cropping window */
 	unsigned long		pclk_limit;	/* from host */
@@ -210,126 +215,6 @@
 	V4L2_MBUS_FMT_Y8_1X8,
 };
 
-static const struct v4l2_queryctrl ov6650_controls[] = {
-	{
-		.id		= V4L2_CID_AUTOGAIN,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "AGC",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 1,
-	},
-	{
-		.id		= V4L2_CID_GAIN,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Gain",
-		.minimum	= 0,
-		.maximum	= 0x3f,
-		.step		= 1,
-		.default_value	= DEF_GAIN,
-	},
-	{
-		.id		= V4L2_CID_AUTO_WHITE_BALANCE,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "AWB",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 1,
-	},
-	{
-		.id		= V4L2_CID_BLUE_BALANCE,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Blue",
-		.minimum	= 0,
-		.maximum	= 0xff,
-		.step		= 1,
-		.default_value	= DEF_BLUE,
-	},
-	{
-		.id		= V4L2_CID_RED_BALANCE,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Red",
-		.minimum	= 0,
-		.maximum	= 0xff,
-		.step		= 1,
-		.default_value	= DEF_RED,
-	},
-	{
-		.id		= V4L2_CID_SATURATION,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Saturation",
-		.minimum	= 0,
-		.maximum	= 0xf,
-		.step		= 1,
-		.default_value	= 0x8,
-	},
-	{
-		.id		= V4L2_CID_HUE,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Hue",
-		.minimum	= 0,
-		.maximum	= HUE_MASK,
-		.step		= 1,
-		.default_value	= DEF_HUE,
-	},
-	{
-		.id		= V4L2_CID_BRIGHTNESS,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Brightness",
-		.minimum	= 0,
-		.maximum	= 0xff,
-		.step		= 1,
-		.default_value	= 0x80,
-	},
-	{
-		.id		= V4L2_CID_EXPOSURE_AUTO,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "AEC",
-		.minimum	= 0,
-		.maximum	= 3,
-		.step		= 1,
-		.default_value	= 0,
-	},
-	{
-		.id		= V4L2_CID_EXPOSURE,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Exposure",
-		.minimum	= 0,
-		.maximum	= 0xff,
-		.step		= 1,
-		.default_value	= DEF_AECH,
-	},
-	{
-		.id		= V4L2_CID_GAMMA,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Gamma",
-		.minimum	= 0,
-		.maximum	= 0xff,
-		.step		= 1,
-		.default_value	= 0x12,
-	},
-	{
-		.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 ov6650_reg_read(struct i2c_client *client, u8 reg, u8 *val)
 {
@@ -419,213 +304,90 @@
 	return 0;
 }
 
-/* Alter bus settings on camera side */
-static int ov6650_set_bus_param(struct soc_camera_device *icd,
-				unsigned long flags)
-{
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-	struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
-	int ret;
-
-	flags = soc_camera_apply_sensor_flags(icl, flags);
-
-	if (flags & SOCAM_PCLK_SAMPLE_RISING)
-		ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_PCLK_RISING, 0);
-	else
-		ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_PCLK_RISING);
-	if (ret)
-		return ret;
-
-	if (flags & SOCAM_HSYNC_ACTIVE_LOW)
-		ret = ov6650_reg_rmw(client, REG_COMF, COMF_HREF_LOW, 0);
-	else
-		ret = ov6650_reg_rmw(client, REG_COMF, 0, COMF_HREF_LOW);
-	if (ret)
-		return ret;
-
-	if (flags & SOCAM_VSYNC_ACTIVE_HIGH)
-		ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_VSYNC_HIGH, 0);
-	else
-		ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_VSYNC_HIGH);
-
-	return ret;
-}
-
-/* Request bus settings on camera side */
-static unsigned long ov6650_query_bus_param(struct soc_camera_device *icd)
-{
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-
-	unsigned long flags = SOCAM_MASTER |
-		SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING |
-		SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW |
-		SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |
-		SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
-
-	return soc_camera_apply_sensor_flags(icl, flags);
-}
-
 /* Get status of additional camera capabilities */
-static int ov6650_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int ov6550_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct ov6650 *priv = container_of(ctrl->handler, struct ov6650, hdl);
+	struct v4l2_subdev *sd = &priv->subdev;
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct ov6650 *priv = to_ov6650(client);
-	uint8_t reg;
-	int ret = 0;
+	uint8_t reg, reg2;
+	int ret;
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUTOGAIN:
-		ctrl->value = priv->agc;
-		break;
-	case V4L2_CID_GAIN:
-		if (priv->agc) {
-			ret = ov6650_reg_read(client, REG_GAIN, &reg);
-			ctrl->value = reg;
-		} else {
-			ctrl->value = priv->gain;
-		}
-		break;
+		ret = ov6650_reg_read(client, REG_GAIN, &reg);
+		if (!ret)
+			priv->gain->val = reg;
+		return ret;
 	case V4L2_CID_AUTO_WHITE_BALANCE:
-		ctrl->value = priv->awb;
-		break;
-	case V4L2_CID_BLUE_BALANCE:
-		if (priv->awb) {
-			ret = ov6650_reg_read(client, REG_BLUE, &reg);
-			ctrl->value = reg;
-		} else {
-			ctrl->value = priv->blue;
-		}
-		break;
-	case V4L2_CID_RED_BALANCE:
-		if (priv->awb) {
-			ret = ov6650_reg_read(client, REG_RED, &reg);
-			ctrl->value = reg;
-		} else {
-			ctrl->value = priv->red;
+		ret = ov6650_reg_read(client, REG_BLUE, &reg);
+		if (!ret)
+			ret = ov6650_reg_read(client, REG_RED, &reg2);
+		if (!ret) {
+			priv->blue->val = reg;
+			priv->red->val = reg2;
 		}
-		break;
-	case V4L2_CID_SATURATION:
-		ctrl->value = priv->saturation;
-		break;
-	case V4L2_CID_HUE:
-		ctrl->value = priv->hue;
-		break;
-	case V4L2_CID_BRIGHTNESS:
-		ctrl->value = priv->brightness;
-		break;
+		return ret;
 	case V4L2_CID_EXPOSURE_AUTO:
-		ctrl->value = priv->aec;
-		break;
-	case V4L2_CID_EXPOSURE:
-		if (priv->aec) {
-			ret = ov6650_reg_read(client, REG_AECH, &reg);
-			ctrl->value = reg;
-		} else {
-			ctrl->value = priv->exposure;
-		}
-		break;
-	case V4L2_CID_GAMMA:
-		ctrl->value = priv->gamma;
-		break;
-	case V4L2_CID_VFLIP:
-		ctrl->value = priv->vflip;
-		break;
-	case V4L2_CID_HFLIP:
-		ctrl->value = priv->hflip;
-		break;
+		ret = ov6650_reg_read(client, REG_AECH, &reg);
+		if (!ret)
+			priv->exposure->val = reg;
+		return ret;
 	}
-	return ret;
+	return -EINVAL;
 }
 
 /* Set status of additional camera capabilities */
-static int ov6650_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int ov6550_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct ov6650 *priv = container_of(ctrl->handler, struct ov6650, hdl);
+	struct v4l2_subdev *sd = &priv->subdev;
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct ov6650 *priv = to_ov6650(client);
-	int ret = 0;
+	int ret;
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUTOGAIN:
 		ret = ov6650_reg_rmw(client, REG_COMB,
-				ctrl->value ? COMB_AGC : 0, COMB_AGC);
-		if (!ret)
-			priv->agc = ctrl->value;
-		break;
-	case V4L2_CID_GAIN:
-		ret = ov6650_reg_write(client, REG_GAIN, ctrl->value);
-		if (!ret)
-			priv->gain = ctrl->value;
-		break;
+				ctrl->val ? COMB_AGC : 0, COMB_AGC);
+		if (!ret && !ctrl->val)
+			ret = ov6650_reg_write(client, REG_GAIN, priv->gain->val);
+		return ret;
 	case V4L2_CID_AUTO_WHITE_BALANCE:
 		ret = ov6650_reg_rmw(client, REG_COMB,
-				ctrl->value ? COMB_AWB : 0, COMB_AWB);
-		if (!ret)
-			priv->awb = ctrl->value;
-		break;
-	case V4L2_CID_BLUE_BALANCE:
-		ret = ov6650_reg_write(client, REG_BLUE, ctrl->value);
-		if (!ret)
-			priv->blue = ctrl->value;
-		break;
-	case V4L2_CID_RED_BALANCE:
-		ret = ov6650_reg_write(client, REG_RED, ctrl->value);
-		if (!ret)
-			priv->red = ctrl->value;
-		break;
+				ctrl->val ? COMB_AWB : 0, COMB_AWB);
+		if (!ret && !ctrl->val) {
+			ret = ov6650_reg_write(client, REG_BLUE, priv->blue->val);
+			if (!ret)
+				ret = ov6650_reg_write(client, REG_RED,
+							priv->red->val);
+		}
+		return ret;
 	case V4L2_CID_SATURATION:
-		ret = ov6650_reg_rmw(client, REG_SAT, SET_SAT(ctrl->value),
+		return ov6650_reg_rmw(client, REG_SAT, SET_SAT(ctrl->val),
 				SAT_MASK);
-		if (!ret)
-			priv->saturation = ctrl->value;
-		break;
 	case V4L2_CID_HUE:
-		ret = ov6650_reg_rmw(client, REG_HUE, SET_HUE(ctrl->value),
+		return ov6650_reg_rmw(client, REG_HUE, SET_HUE(ctrl->val),
 				HUE_MASK);
-		if (!ret)
-			priv->hue = ctrl->value;
-		break;
 	case V4L2_CID_BRIGHTNESS:
-		ret = ov6650_reg_write(client, REG_BRT, ctrl->value);
-		if (!ret)
-			priv->brightness = ctrl->value;
-		break;
+		return ov6650_reg_write(client, REG_BRT, ctrl->val);
 	case V4L2_CID_EXPOSURE_AUTO:
-		switch (ctrl->value) {
-		case V4L2_EXPOSURE_AUTO:
-			ret = ov6650_reg_rmw(client, REG_COMB, COMB_AEC, 0);
-			break;
-		default:
-			ret = ov6650_reg_rmw(client, REG_COMB, 0, COMB_AEC);
-			break;
-		}
-		if (!ret)
-			priv->aec = ctrl->value;
-		break;
-	case V4L2_CID_EXPOSURE:
-		ret = ov6650_reg_write(client, REG_AECH, ctrl->value);
-		if (!ret)
-			priv->exposure = ctrl->value;
-		break;
+		ret = ov6650_reg_rmw(client, REG_COMB, ctrl->val ==
+				V4L2_EXPOSURE_AUTO ? COMB_AEC : 0, COMB_AEC);
+		if (!ret && ctrl->val == V4L2_EXPOSURE_MANUAL)
+			ret = ov6650_reg_write(client, REG_AECH,
+						priv->exposure->val);
+		return ret;
 	case V4L2_CID_GAMMA:
-		ret = ov6650_reg_write(client, REG_GAM1, ctrl->value);
-		if (!ret)
-			priv->gamma = ctrl->value;
-		break;
+		return ov6650_reg_write(client, REG_GAM1, ctrl->val);
 	case V4L2_CID_VFLIP:
-		ret = ov6650_reg_rmw(client, REG_COMB,
-				ctrl->value ? COMB_FLIP_V : 0, COMB_FLIP_V);
-		if (!ret)
-			priv->vflip = ctrl->value;
-		break;
+		return ov6650_reg_rmw(client, REG_COMB,
+				ctrl->val ? COMB_FLIP_V : 0, COMB_FLIP_V);
 	case V4L2_CID_HFLIP:
-		ret = ov6650_reg_rmw(client, REG_COMB,
-				ctrl->value ? COMB_FLIP_H : 0, COMB_FLIP_H);
-		if (!ret)
-			priv->hflip = ctrl->value;
-		break;
+		return ov6650_reg_rmw(client, REG_COMB,
+				ctrl->val ? COMB_FLIP_H : 0, COMB_FLIP_H);
 	}
 
-	return ret;
+	return -EINVAL;
 }
 
 /* Get chip identification */
@@ -778,7 +540,7 @@
 static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct soc_camera_device *icd = client->dev.platform_data;
+	struct soc_camera_device *icd = v4l2_get_subdev_hostdata(sd);
 	struct soc_camera_sense *sense = icd->sense;
 	struct ov6650 *priv = to_ov6650(client);
 	bool half_scale = !is_unscaled_ok(mf->width, mf->height, &priv->rect);
@@ -1057,8 +819,7 @@
 	return ret;
 }
 
-static int ov6650_video_probe(struct soc_camera_device *icd,
-				struct i2c_client *client)
+static int ov6650_video_probe(struct i2c_client *client)
 {
 	u8		pidh, pidl, midh, midl;
 	int		ret = 0;
@@ -1094,16 +855,12 @@
 	return ret;
 }
 
-static struct soc_camera_ops ov6650_ops = {
-	.set_bus_param		= ov6650_set_bus_param,
-	.query_bus_param	= ov6650_query_bus_param,
-	.controls		= ov6650_controls,
-	.num_controls		= ARRAY_SIZE(ov6650_controls),
+static const struct v4l2_ctrl_ops ov6550_ctrl_ops = {
+	.g_volatile_ctrl = ov6550_g_volatile_ctrl,
+	.s_ctrl = ov6550_s_ctrl,
 };
 
 static struct v4l2_subdev_core_ops ov6650_core_ops = {
-	.g_ctrl			= ov6650_g_ctrl,
-	.s_ctrl			= ov6650_s_ctrl,
 	.g_chip_ident		= ov6650_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register		= ov6650_get_register,
@@ -1111,6 +868,55 @@
 #endif
 };
 
+/* Request bus settings on camera side */
+static int ov6650_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_MASTER |
+		V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+/* Alter bus settings on camera side */
+static int ov6650_s_mbus_config(struct v4l2_subdev *sd,
+				const struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	unsigned long flags = soc_camera_apply_board_flags(icl, cfg);
+	int ret;
+
+	if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
+		ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_PCLK_RISING, 0);
+	else
+		ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_PCLK_RISING);
+	if (ret)
+		return ret;
+
+	if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
+		ret = ov6650_reg_rmw(client, REG_COMF, COMF_HREF_LOW, 0);
+	else
+		ret = ov6650_reg_rmw(client, REG_COMF, 0, COMF_HREF_LOW);
+	if (ret)
+		return ret;
+
+	if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
+		ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_VSYNC_HIGH, 0);
+	else
+		ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_VSYNC_HIGH);
+
+	return ret;
+}
+
 static struct v4l2_subdev_video_ops ov6650_video_ops = {
 	.s_stream	= ov6650_s_stream,
 	.g_mbus_fmt	= ov6650_g_fmt,
@@ -1122,6 +928,8 @@
 	.s_crop		= ov6650_s_crop,
 	.g_parm		= ov6650_g_parm,
 	.s_parm		= ov6650_s_parm,
+	.g_mbus_config	= ov6650_g_mbus_config,
+	.s_mbus_config	= ov6650_s_mbus_config,
 };
 
 static struct v4l2_subdev_ops ov6650_subdev_ops = {
@@ -1136,16 +944,9 @@
 			const struct i2c_device_id *did)
 {
 	struct ov6650 *priv;
-	struct soc_camera_device *icd = client->dev.platform_data;
-	struct soc_camera_link *icl;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 	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;
@@ -1159,8 +960,46 @@
 	}
 
 	v4l2_i2c_subdev_init(&priv->subdev, client, &ov6650_subdev_ops);
+	v4l2_ctrl_handler_init(&priv->hdl, 13);
+	v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	priv->autogain = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+	priv->gain = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_GAIN, 0, 0x3f, 1, DEF_GAIN);
+	priv->autowb = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
+	priv->blue = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_BLUE_BALANCE, 0, 0xff, 1, DEF_BLUE);
+	priv->red = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_RED_BALANCE, 0, 0xff, 1, DEF_RED);
+	v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 0xf, 1, 0x8);
+	v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_HUE, 0, HUE_MASK, 1, DEF_HUE);
+	v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 0xff, 1, 0x80);
+	priv->autoexposure = v4l2_ctrl_new_std_menu(&priv->hdl,
+			&ov6550_ctrl_ops, V4L2_CID_EXPOSURE_AUTO,
+			V4L2_EXPOSURE_MANUAL, 0, V4L2_EXPOSURE_AUTO);
+	priv->exposure = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_EXPOSURE, 0, 0xff, 1, DEF_AECH);
+	v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_GAMMA, 0, 0xff, 1, 0x12);
 
-	icd->ops = &ov6650_ops;
+	priv->subdev.ctrl_handler = &priv->hdl;
+	if (priv->hdl.error) {
+		int err = priv->hdl.error;
+
+		kfree(priv);
+		return err;
+	}
+	v4l2_ctrl_auto_cluster(2, &priv->autogain, 0, true);
+	v4l2_ctrl_auto_cluster(3, &priv->autowb, 0, true);
+	v4l2_ctrl_auto_cluster(2, &priv->autoexposure,
+				V4L2_EXPOSURE_MANUAL, true);
 
 	priv->rect.left	  = DEF_HSTRT << 1;
 	priv->rect.top	  = DEF_VSTRT << 1;
@@ -1170,10 +1009,12 @@
 	priv->code	  = V4L2_MBUS_FMT_YUYV8_2X8;
 	priv->colorspace  = V4L2_COLORSPACE_JPEG;
 
-	ret = ov6650_video_probe(icd, client);
+	ret = ov6650_video_probe(client);
+	if (!ret)
+		ret = v4l2_ctrl_handler_setup(&priv->hdl);
 
 	if (ret) {
-		icd->ops = NULL;
+		v4l2_ctrl_handler_free(&priv->hdl);
 		kfree(priv);
 	}
 
@@ -1184,6 +1025,8 @@
 {
 	struct ov6650 *priv = to_ov6650(client);
 
+	v4l2_device_unregister_subdev(&priv->subdev);
+	v4l2_ctrl_handler_free(&priv->hdl);
 	kfree(priv);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/ov772x.c linux-libre-3.2-gnu/drivers/media/video/ov772x.c
--- linux-libre-3.1-gnu/drivers/media/video/ov772x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/ov772x.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,12 +20,14 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/videodev2.h>
+
+#include <media/ov772x.h>
+#include <media/soc_camera.h>
+#include <media/v4l2-ctrls.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-subdev.h>
-#include <media/soc_camera.h>
-#include <media/soc_mediabus.h>
-#include <media/ov772x.h>
 
 /*
  * register offset
@@ -400,6 +402,7 @@
 
 struct ov772x_priv {
 	struct v4l2_subdev                subdev;
+	struct v4l2_ctrl_handler	  hdl;
 	struct ov772x_camera_info        *info;
 	const struct ov772x_color_format *cfmt;
 	const struct ov772x_win_size     *win;
@@ -517,36 +520,6 @@
 	.regs     = ov772x_qvga_regs,
 };
 
-static const struct v4l2_queryctrl ov772x_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,
-	},
-	{
-		.id		= V4L2_CID_BAND_STOP_FILTER,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Band-stop filter",
-		.minimum	= 0,
-		.maximum	= 256,
-		.step		= 1,
-		.default_value	= 0,
-	},
-};
-
 /*
  * general function
  */
@@ -620,75 +593,30 @@
 	return 0;
 }
 
-static int ov772x_set_bus_param(struct soc_camera_device *icd,
-				unsigned long		  flags)
-{
-	return 0;
-}
-
-static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
-{
-	struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
-	struct ov772x_priv *priv = i2c_get_clientdata(client);
-	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;
-
-	if (priv->info->flags & OV772X_FLAG_8BIT)
-		flags |= SOCAM_DATAWIDTH_8;
-	else
-		flags |= SOCAM_DATAWIDTH_10;
-
-	return soc_camera_apply_sensor_flags(icl, flags);
-}
-
-static int ov772x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev);
-
-	switch (ctrl->id) {
-	case V4L2_CID_VFLIP:
-		ctrl->value = priv->flag_vflip;
-		break;
-	case V4L2_CID_HFLIP:
-		ctrl->value = priv->flag_hflip;
-		break;
-	case V4L2_CID_BAND_STOP_FILTER:
-		ctrl->value = priv->band_filter;
-		break;
-	}
-	return 0;
-}
-
-static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct ov772x_priv *priv = container_of(ctrl->handler,
+						struct ov772x_priv, hdl);
+	struct v4l2_subdev *sd = &priv->subdev;
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev);
 	int ret = 0;
 	u8 val;
 
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
-		val = ctrl->value ? VFLIP_IMG : 0x00;
-		priv->flag_vflip = ctrl->value;
+		val = ctrl->val ? VFLIP_IMG : 0x00;
+		priv->flag_vflip = ctrl->val;
 		if (priv->info->flags & OV772X_FLAG_VFLIP)
 			val ^= VFLIP_IMG;
-		ret = ov772x_mask_set(client, COM3, VFLIP_IMG, val);
-		break;
+		return ov772x_mask_set(client, COM3, VFLIP_IMG, val);
 	case V4L2_CID_HFLIP:
-		val = ctrl->value ? HFLIP_IMG : 0x00;
-		priv->flag_hflip = ctrl->value;
+		val = ctrl->val ? HFLIP_IMG : 0x00;
+		priv->flag_hflip = ctrl->val;
 		if (priv->info->flags & OV772X_FLAG_HFLIP)
 			val ^= HFLIP_IMG;
-		ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val);
-		break;
+		return ov772x_mask_set(client, COM3, HFLIP_IMG, val);
 	case V4L2_CID_BAND_STOP_FILTER:
-		if ((unsigned)ctrl->value > 256)
-			ctrl->value = 256;
-		if (ctrl->value == priv->band_filter)
-			break;
-		if (!ctrl->value) {
+		if (!ctrl->val) {
 			/* Switch the filter off, it is on now */
 			ret = ov772x_mask_set(client, BDBASE, 0xff, 0xff);
 			if (!ret)
@@ -696,7 +624,7 @@
 						      BNDF_ON_OFF, 0);
 		} else {
 			/* Switch the filter on, set AEC low limit */
-			val = 256 - ctrl->value;
+			val = 256 - ctrl->val;
 			ret = ov772x_mask_set(client, COM8,
 					      BNDF_ON_OFF, BNDF_ON_OFF);
 			if (!ret)
@@ -704,11 +632,11 @@
 						      0xff, val);
 		}
 		if (!ret)
-			priv->band_filter = ctrl->value;
-		break;
+			priv->band_filter = ctrl->val;
+		return ret;
 	}
 
-	return ret;
+	return -EINVAL;
 }
 
 static int ov772x_g_chip_ident(struct v4l2_subdev *sd,
@@ -822,13 +750,13 @@
 			goto ov772x_set_fmt_error;
 
 		ret = ov772x_mask_set(client,
-				      EDGE_TRSHLD, EDGE_THRESHOLD_MASK,
+				      EDGE_TRSHLD, OV772X_EDGE_THRESHOLD_MASK,
 				      priv->info->edgectrl.threshold);
 		if (ret < 0)
 			goto ov772x_set_fmt_error;
 
 		ret = ov772x_mask_set(client,
-				      EDGE_STRNGT, EDGE_STRENGTH_MASK,
+				      EDGE_STRNGT, OV772X_EDGE_STRENGTH_MASK,
 				      priv->info->edgectrl.strength);
 		if (ret < 0)
 			goto ov772x_set_fmt_error;
@@ -840,13 +768,13 @@
 		 * set upper and lower limit
 		 */
 		ret = ov772x_mask_set(client,
-				      EDGE_UPPER, EDGE_UPPER_MASK,
+				      EDGE_UPPER, OV772X_EDGE_UPPER_MASK,
 				      priv->info->edgectrl.upper);
 		if (ret < 0)
 			goto ov772x_set_fmt_error;
 
 		ret = ov772x_mask_set(client,
-				      EDGE_LOWER, EDGE_LOWER_MASK,
+				      EDGE_LOWER, OV772X_EDGE_LOWER_MASK,
 				      priv->info->edgectrl.lower);
 		if (ret < 0)
 			goto ov772x_set_fmt_error;
@@ -1025,17 +953,12 @@
 	return 0;
 }
 
-static int ov772x_video_probe(struct soc_camera_device *icd,
-			      struct i2c_client *client)
+static int ov772x_video_probe(struct i2c_client *client)
 {
 	struct ov772x_priv *priv = to_ov772x(client);
 	u8                  pid, ver;
 	const char         *devname;
 
-	/* We must have a parent by now. And it cannot be a wrong one. */
-	BUG_ON(!icd->parent ||
-	       to_soc_camera_host(icd->parent)->nr != icd->iface);
-
 	/*
 	 * check and show product ID and manufacturer ID
 	 */
@@ -1064,20 +987,14 @@
 		 ver,
 		 i2c_smbus_read_byte_data(client, MIDH),
 		 i2c_smbus_read_byte_data(client, MIDL));
-
-	return 0;
+	return v4l2_ctrl_handler_setup(&priv->hdl);
 }
 
-static struct soc_camera_ops ov772x_ops = {
-	.set_bus_param		= ov772x_set_bus_param,
-	.query_bus_param	= ov772x_query_bus_param,
-	.controls		= ov772x_controls,
-	.num_controls		= ARRAY_SIZE(ov772x_controls),
+static const struct v4l2_ctrl_ops ov772x_ctrl_ops = {
+	.s_ctrl = ov772x_s_ctrl,
 };
 
 static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = {
-	.g_ctrl		= ov772x_g_ctrl,
-	.s_ctrl		= ov772x_s_ctrl,
 	.g_chip_ident	= ov772x_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register	= ov772x_g_register,
@@ -1095,6 +1012,21 @@
 	return 0;
 }
 
+static int ov772x_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
 static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = {
 	.s_stream	= ov772x_s_stream,
 	.g_mbus_fmt	= ov772x_g_fmt,
@@ -1103,6 +1035,7 @@
 	.cropcap	= ov772x_cropcap,
 	.g_crop		= ov772x_g_crop,
 	.enum_mbus_fmt	= ov772x_enum_fmt,
+	.g_mbus_config	= ov772x_g_mbus_config,
 };
 
 static struct v4l2_subdev_ops ov772x_subdev_ops = {
@@ -1117,21 +1050,16 @@
 static int ov772x_probe(struct i2c_client *client,
 			const struct i2c_device_id *did)
 {
-	struct ov772x_priv        *priv;
-	struct soc_camera_device  *icd = client->dev.platform_data;
-	struct i2c_adapter        *adapter = to_i2c_adapter(client->dev.parent);
-	struct soc_camera_link    *icl;
-	int                        ret;
+	struct ov772x_priv	*priv;
+	struct soc_camera_link	*icl = soc_camera_i2c_to_link(client);
+	struct i2c_adapter	*adapter = to_i2c_adapter(client->dev.parent);
+	int			ret;
 
-	if (!icd) {
-		dev_err(&client->dev, "OV772X: missing soc-camera data!\n");
+	if (!icl || !icl->priv) {
+		dev_err(&client->dev, "OV772X: missing platform data!\n");
 		return -EINVAL;
 	}
 
-	icl = to_soc_camera_link(icd);
-	if (!icl || !icl->priv)
-		return -EINVAL;
-
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
 		dev_err(&adapter->dev,
 			"I2C-Adapter doesn't support "
@@ -1146,12 +1074,24 @@
 	priv->info = icl->priv;
 
 	v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops);
+	v4l2_ctrl_handler_init(&priv->hdl, 3);
+	v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops,
+			V4L2_CID_BAND_STOP_FILTER, 0, 256, 1, 0);
+	priv->subdev.ctrl_handler = &priv->hdl;
+	if (priv->hdl.error) {
+		int err = priv->hdl.error;
 
-	icd->ops		= &ov772x_ops;
+		kfree(priv);
+		return err;
+	}
 
-	ret = ov772x_video_probe(icd, client);
+	ret = ov772x_video_probe(client);
 	if (ret) {
-		icd->ops = NULL;
+		v4l2_ctrl_handler_free(&priv->hdl);
 		kfree(priv);
 	}
 
@@ -1161,9 +1101,9 @@
 static int ov772x_remove(struct i2c_client *client)
 {
 	struct ov772x_priv *priv = to_ov772x(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
 
-	icd->ops = NULL;
+	v4l2_device_unregister_subdev(&priv->subdev);
+	v4l2_ctrl_handler_free(&priv->hdl);
 	kfree(priv);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/ov9640.c linux-libre-3.2-gnu/drivers/media/video/ov9640.c
--- linux-libre-3.1-gnu/drivers/media/video/ov9640.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/ov9640.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,10 +24,13 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/videodev2.h>
+
+#include <media/soc_camera.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-common.h>
-#include <media/soc_camera.h>
+#include <media/v4l2-ctrls.h>
 
 #include "ov9640.h"
 
@@ -162,27 +165,6 @@
 	V4L2_MBUS_FMT_RGB565_2X8_LE,
 };
 
-static const struct v4l2_queryctrl ov9640_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 ov9640_reg_read(struct i2c_client *client, u8 reg, u8 *val)
 {
@@ -284,75 +266,25 @@
 	return 0;
 }
 
-/* Alter bus settings on camera side */
-static int ov9640_set_bus_param(struct soc_camera_device *icd,
-				unsigned long flags)
-{
-	return 0;
-}
-
-/* Request bus settings on camera side */
-static unsigned long ov9640_query_bus_param(struct soc_camera_device *icd)
-{
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-
-	/*
-	 * REVISIT: the camera probably can do 10 bit transfers, but I don't
-	 *          have those pins connected on my hardware.
-	 */
-	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 ov9640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct ov9640_priv *priv = to_ov9640_sensor(sd);
-
-	switch (ctrl->id) {
-	case V4L2_CID_VFLIP:
-		ctrl->value = priv->flag_vflip;
-		break;
-	case V4L2_CID_HFLIP:
-		ctrl->value = priv->flag_hflip;
-		break;
-	}
-	return 0;
-}
-
 /* Set status of additional camera capabilities */
-static int ov9640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int ov9640_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct ov9640_priv *priv = to_ov9640_sensor(sd);
-
-	int ret = 0;
+	struct ov9640_priv *priv = container_of(ctrl->handler, struct ov9640_priv, hdl);
+	struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev);
 
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
-		priv->flag_vflip = ctrl->value;
-		if (ctrl->value)
-			ret = ov9640_reg_rmw(client, OV9640_MVFP,
+		if (ctrl->val)
+			return ov9640_reg_rmw(client, OV9640_MVFP,
 							OV9640_MVFP_V, 0);
-		else
-			ret = ov9640_reg_rmw(client, OV9640_MVFP,
-							0, OV9640_MVFP_V);
-		break;
+		return ov9640_reg_rmw(client, OV9640_MVFP, 0, OV9640_MVFP_V);
 	case V4L2_CID_HFLIP:
-		priv->flag_hflip = ctrl->value;
-		if (ctrl->value)
-			ret = ov9640_reg_rmw(client, OV9640_MVFP,
+		if (ctrl->val)
+			return ov9640_reg_rmw(client, OV9640_MVFP,
 							OV9640_MVFP_H, 0);
-		else
-			ret = ov9640_reg_rmw(client, OV9640_MVFP,
-							0, OV9640_MVFP_H);
-		break;
+		return ov9640_reg_rmw(client, OV9640_MVFP, 0, OV9640_MVFP_H);
 	}
-
-	return ret;
+	return -EINVAL;
 }
 
 /* Get chip identification */
@@ -646,10 +578,7 @@
 	return 0;
 }
 
-
-
-static int ov9640_video_probe(struct soc_camera_device *icd,
-				struct i2c_client *client)
+static int ov9640_video_probe(struct i2c_client *client)
 {
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
 	struct ov9640_priv *priv = to_ov9640_sensor(sd);
@@ -657,29 +586,19 @@
 	const char	*devname;
 	int		ret = 0;
 
-	/* We must have a parent by now. And it cannot be a wrong one. */
-	BUG_ON(!icd->parent ||
-	       to_soc_camera_host(icd->parent)->nr != icd->iface);
-
 	/*
 	 * check and show product ID and manufacturer ID
 	 */
 
 	ret = ov9640_reg_read(client, OV9640_PID, &pid);
+	if (!ret)
+		ret = ov9640_reg_read(client, OV9640_VER, &ver);
+	if (!ret)
+		ret = ov9640_reg_read(client, OV9640_MIDH, &midh);
+	if (!ret)
+		ret = ov9640_reg_read(client, OV9640_MIDL, &midl);
 	if (ret)
-		goto err;
-
-	ret = ov9640_reg_read(client, OV9640_VER, &ver);
-	if (ret)
-		goto err;
-
-	ret = ov9640_reg_read(client, OV9640_MIDH, &midh);
-	if (ret)
-		goto err;
-
-	ret = ov9640_reg_read(client, OV9640_MIDL, &midl);
-	if (ret)
-		goto err;
+		return ret;
 
 	switch (VERSION(pid, ver)) {
 	case OV9640_V2:
@@ -693,27 +612,20 @@
 		break;
 	default:
 		dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver);
-		ret = -ENODEV;
-		goto err;
+		return -ENODEV;
 	}
 
 	dev_info(&client->dev, "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
 		 devname, pid, ver, midh, midl);
 
-err:
-	return ret;
+	return v4l2_ctrl_handler_setup(&priv->hdl);
 }
 
-static struct soc_camera_ops ov9640_ops = {
-	.set_bus_param		= ov9640_set_bus_param,
-	.query_bus_param	= ov9640_query_bus_param,
-	.controls		= ov9640_controls,
-	.num_controls		= ARRAY_SIZE(ov9640_controls),
+static const struct v4l2_ctrl_ops ov9640_ctrl_ops = {
+	.s_ctrl = ov9640_s_ctrl,
 };
 
 static struct v4l2_subdev_core_ops ov9640_core_ops = {
-	.g_ctrl			= ov9640_g_ctrl,
-	.s_ctrl			= ov9640_s_ctrl,
 	.g_chip_ident		= ov9640_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register		= ov9640_get_register,
@@ -722,6 +634,22 @@
 
 };
 
+/* Request bus settings on camera side */
+static int ov9640_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
 static struct v4l2_subdev_video_ops ov9640_video_ops = {
 	.s_stream	= ov9640_s_stream,
 	.s_mbus_fmt	= ov9640_s_fmt,
@@ -729,7 +657,7 @@
 	.enum_mbus_fmt	= ov9640_enum_fmt,
 	.cropcap	= ov9640_cropcap,
 	.g_crop		= ov9640_g_crop,
-
+	.g_mbus_config	= ov9640_g_mbus_config,
 };
 
 static struct v4l2_subdev_ops ov9640_subdev_ops = {
@@ -744,16 +672,9 @@
 			const struct i2c_device_id *did)
 {
 	struct ov9640_priv *priv;
-	struct soc_camera_device *icd	= client->dev.platform_data;
-	struct soc_camera_link *icl;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 	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;
@@ -768,12 +689,23 @@
 
 	v4l2_i2c_subdev_init(&priv->subdev, client, &ov9640_subdev_ops);
 
-	icd->ops	= &ov9640_ops;
+	v4l2_ctrl_handler_init(&priv->hdl, 2);
+	v4l2_ctrl_new_std(&priv->hdl, &ov9640_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ov9640_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	priv->subdev.ctrl_handler = &priv->hdl;
+	if (priv->hdl.error) {
+		int err = priv->hdl.error;
 
-	ret = ov9640_video_probe(icd, client);
+		kfree(priv);
+		return err;
+	}
+
+	ret = ov9640_video_probe(client);
 
 	if (ret) {
-		icd->ops = NULL;
+		v4l2_ctrl_handler_free(&priv->hdl);
 		kfree(priv);
 	}
 
@@ -785,6 +717,8 @@
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
 	struct ov9640_priv *priv = to_ov9640_sensor(sd);
 
+	v4l2_device_unregister_subdev(&priv->subdev);
+	v4l2_ctrl_handler_free(&priv->hdl);
 	kfree(priv);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/ov9640.h linux-libre-3.2-gnu/drivers/media/video/ov9640.h
--- linux-libre-3.1-gnu/drivers/media/video/ov9640.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/ov9640.h	2012-01-04 18:55:44.000000000 -0500
@@ -198,12 +198,10 @@
 
 struct ov9640_priv {
 	struct v4l2_subdev		subdev;
+	struct v4l2_ctrl_handler	hdl;
 
 	int				model;
 	int				revision;
-
-	bool				flag_vflip;
-	bool				flag_hflip;
 };
 
 #endif	/* __DRIVERS_MEDIA_VIDEO_OV9640_H__ */
diff -druN linux-libre-3.1-gnu/drivers/media/video/ov9740.c linux-libre-3.2-gnu/drivers/media/video/ov9740.c
--- linux-libre-3.1-gnu/drivers/media/video/ov9740.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/ov9740.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,8 +14,11 @@
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
-#include <media/v4l2-chip-ident.h>
+#include <linux/v4l2-mediabus.h>
+
 #include <media/soc_camera.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
 
 #define to_ov9740(sd)		container_of(sd, struct ov9740_priv, subdev)
 
@@ -192,6 +195,7 @@
 
 struct ov9740_priv {
 	struct v4l2_subdev		subdev;
+	struct v4l2_ctrl_handler	hdl;
 
 	int				ident;
 	u16				model;
@@ -392,27 +396,6 @@
 	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)
 {
@@ -560,25 +543,6 @@
 	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);
-}
-
 /* select nearest higher resolution for capture */
 static void ov9740_res_roundup(u32 *width, u32 *height)
 {
@@ -788,36 +752,18 @@
 	return 0;
 }
 
-/* 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)
+static int ov9740_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct ov9740_priv *priv = to_ov9740(sd);
+	struct ov9740_priv *priv =
+		container_of(ctrl->handler, struct ov9740_priv, hdl);
 
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
-		priv->flag_vflip = ctrl->value;
+		priv->flag_vflip = ctrl->val;
 		break;
 	case V4L2_CID_HFLIP:
-		priv->flag_hflip = ctrl->value;
+		priv->flag_hflip = ctrl->val;
 		break;
 	default:
 		return -EINVAL;
@@ -890,18 +836,13 @@
 }
 #endif
 
-static int ov9740_video_probe(struct soc_camera_device *icd,
-			      struct i2c_client *client)
+static int ov9740_video_probe(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. */
-	BUG_ON(!icd->parent ||
-	       to_soc_camera_host(icd->parent)->nr != icd->iface);
-
 	/*
 	 * check and show product ID and manufacturer ID
 	 */
@@ -942,25 +883,33 @@
 	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),
-};
+/* Request bus settings on camera side */
+static int ov9740_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
 
 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,
+	.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,
+	.g_mbus_config	= ov9740_g_mbus_config,
 };
 
 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,
 	.s_power		= ov9740_s_power,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -974,6 +923,10 @@
 	.video			= &ov9740_video_ops,
 };
 
+static const struct v4l2_ctrl_ops ov9740_ctrl_ops = {
+	.s_ctrl = ov9740_s_ctrl,
+};
+
 /*
  * i2c_driver function
  */
@@ -981,16 +934,9 @@
 			const struct i2c_device_id *did)
 {
 	struct ov9740_priv *priv;
-	struct soc_camera_device *icd	= client->dev.platform_data;
-	struct soc_camera_link *icl;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 	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;
@@ -1003,12 +949,24 @@
 	}
 
 	v4l2_i2c_subdev_init(&priv->subdev, client, &ov9740_subdev_ops);
+	v4l2_ctrl_handler_init(&priv->hdl, 13);
+	v4l2_ctrl_new_std(&priv->hdl, &ov9740_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ov9740_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	priv->subdev.ctrl_handler = &priv->hdl;
+	if (priv->hdl.error) {
+		int err = priv->hdl.error;
 
-	icd->ops = &ov9740_ops;
+		kfree(priv);
+		return err;
+	}
 
-	ret = ov9740_video_probe(icd, client);
+	ret = ov9740_video_probe(client);
+	if (!ret)
+		ret = v4l2_ctrl_handler_setup(&priv->hdl);
 	if (ret < 0) {
-		icd->ops = NULL;
+		v4l2_ctrl_handler_free(&priv->hdl);
 		kfree(priv);
 	}
 
@@ -1019,8 +977,9 @@
 {
 	struct ov9740_priv *priv = i2c_get_clientdata(client);
 
+	v4l2_device_unregister_subdev(&priv->subdev);
+	v4l2_ctrl_handler_free(&priv->hdl);
 	kfree(priv);
-
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/pvrusb2/Makefile linux-libre-3.2-gnu/drivers/media/video/pvrusb2/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/pvrusb2/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/pvrusb2/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -16,7 +16,7 @@
 
 obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff -druN linux-libre-3.1-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.c linux-libre-3.2-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.c
--- linux-libre-3.1-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.c	2012-03-19 21:39:18.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.c	2012-03-19 21:41:57.000000000 -0400
@@ -28,6 +28,7 @@
 
 #include "pvrusb2-devattr.h"
 #include <linux/usb.h>
+#include <linux/module.h>
 /* This is needed in order to pull in tuner type ids... */
 #include <linux/i2c.h>
 #include <media/tuner.h>
diff -druN linux-libre-3.1-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.c linux-libre-3.2-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.c
--- linux-libre-3.1-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.c	2012-03-19 21:39:11.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.c	2012-03-19 21:41:50.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
@@ -2993,6 +2994,13 @@
 		pvr2_subdev_set_control(hdw, id, #lab, (hdw)->lab##_val); \
 	}
 
+int pvr2_hdw_get_detected_std(struct pvr2_hdw *hdw, v4l2_std_id *std)
+{
+	v4l2_device_call_all(&hdw->v4l2_dev, 0,
+			     video, querystd, std);
+	return 0;
+}
+
 /* Execute whatever commands are required to update the state of all the
    sub-devices so that they match our current control values. */
 static void pvr2_subdev_update(struct pvr2_hdw *hdw)
diff -druN linux-libre-3.1-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.h linux-libre-3.2-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.h
--- linux-libre-3.1-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.h	2012-01-04 18:55:44.000000000 -0500
@@ -214,6 +214,9 @@
 int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw,struct v4l2_standard *std,
 			       unsigned int idx);
 
+/* Get the detected video standard */
+int pvr2_hdw_get_detected_std(struct pvr2_hdw *hdw, v4l2_std_id *std);
+
 /* Enable / disable retrieval of CPU firmware or prom contents.  This must
    be enabled before pvr2_hdw_cpufw_get() will function.  Note that doing
    this may prevent the device from running (and leaving this mode may
diff -druN linux-libre-3.1-gnu/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c linux-libre-3.2-gnu/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
--- linux-libre-3.1-gnu/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <linux/i2c.h>
+#include <linux/module.h>
 #include <media/ir-kbd-i2c.h>
 #include "pvrusb2-i2c-core.h"
 #include "pvrusb2-hdw-internal.h"
diff -druN linux-libre-3.1-gnu/drivers/media/video/pvrusb2/pvrusb2-v4l2.c linux-libre-3.2-gnu/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
--- linux-libre-3.1-gnu/drivers/media/video/pvrusb2/pvrusb2-v4l2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/pvrusb2/pvrusb2-v4l2.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include "pvrusb2-v4l2.h"
 #include "pvrusb2-ioread.h"
 #include <linux/videodev2.h>
+#include <linux/module.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
@@ -227,6 +228,14 @@
 		break;
 	}
 
+	case VIDIOC_QUERYSTD:
+	{
+		v4l2_std_id *std = arg;
+		*std = V4L2_STD_ALL;
+		ret = pvr2_hdw_get_detected_std(hdw, std);
+		break;
+	}
+
 	case VIDIOC_G_STD:
 	{
 		int val = 0;
diff -druN linux-libre-3.1-gnu/drivers/media/video/pwc/pwc-if.c linux-libre-3.2-gnu/drivers/media/video/pwc/pwc-if.c
--- linux-libre-3.1-gnu/drivers/media/video/pwc/pwc-if.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/pwc/pwc-if.c	2012-01-04 18:55:44.000000000 -0500
@@ -744,9 +744,9 @@
 /***************************************************************************/
 /* Videobuf2 operations */
 
-static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
-				unsigned int *nplanes, unsigned long sizes[],
-				void *alloc_ctxs[])
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+				unsigned int *nbuffers, unsigned int *nplanes,
+				unsigned int sizes[], void *alloc_ctxs[])
 {
 	struct pwc_device *pdev = vb2_get_drv_priv(vq);
 
@@ -816,7 +816,7 @@
 	spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
 }
 
-static int start_streaming(struct vb2_queue *vq)
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct pwc_device *pdev = vb2_get_drv_priv(vq);
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/pwc/pwc-v4l.c linux-libre-3.2-gnu/drivers/media/video/pwc/pwc-v4l.c
--- linux-libre-3.1-gnu/drivers/media/video/pwc/pwc-v4l.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/pwc/pwc-v4l.c	2012-01-04 18:55:44.000000000 -0500
@@ -83,6 +83,7 @@
 	.id	= PWC_CID_CUSTOM(contour),
 	.type	= V4L2_CTRL_TYPE_INTEGER,
 	.name	= "Contour",
+	.flags  = V4L2_CTRL_FLAG_SLIDER,
 	.min	= 0,
 	.max	= 63,
 	.step	= 1,
@@ -206,8 +207,7 @@
 	pdev->blue_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
 				V4L2_CID_BLUE_BALANCE, 0, 255, 1, def);
 
-	v4l2_ctrl_auto_cluster(3, &pdev->auto_white_balance, awb_manual,
-			       pdev->auto_white_balance->cur.val == awb_auto);
+	v4l2_ctrl_auto_cluster(3, &pdev->auto_white_balance, awb_manual, true);
 
 	/* autogain, gain */
 	r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, AGC_MODE_FORMATTER, &def);
@@ -331,12 +331,12 @@
 	pdev->restore_user = v4l2_ctrl_new_custom(hdl, &pwc_restore_user_cfg,
 						  NULL);
 	if (pdev->restore_user)
-		pdev->restore_user->flags = V4L2_CTRL_FLAG_UPDATE;
+		pdev->restore_user->flags |= V4L2_CTRL_FLAG_UPDATE;
 	pdev->restore_factory = v4l2_ctrl_new_custom(hdl,
 						     &pwc_restore_factory_cfg,
 						     NULL);
 	if (pdev->restore_factory)
-		pdev->restore_factory->flags = V4L2_CTRL_FLAG_UPDATE;
+		pdev->restore_factory->flags |= V4L2_CTRL_FLAG_UPDATE;
 
 	if (!(pdev->features & FEATURE_MOTOR_PANTILT))
 		return hdl->error;
@@ -563,8 +563,10 @@
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUTO_WHITE_BALANCE:
-		if (pdev->color_bal_valid && time_before(jiffies,
-				pdev->last_color_bal_update + HZ / 4)) {
+		if (pdev->color_bal_valid &&
+			(pdev->auto_white_balance->val != awb_auto ||
+			 time_before(jiffies,
+				pdev->last_color_bal_update + HZ / 4))) {
 			pdev->red_balance->val  = pdev->last_red_balance;
 			pdev->blue_balance->val = pdev->last_blue_balance;
 			break;
@@ -630,7 +632,7 @@
 
 static int pwc_set_awb(struct pwc_device *pdev)
 {
-	int ret = 0;
+	int ret;
 
 	if (pdev->auto_white_balance->is_new) {
 		ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
@@ -639,52 +641,34 @@
 		if (ret)
 			return ret;
 
-		/* Update val when coming from auto or going to a preset */
-		if (pdev->red_balance->is_volatile ||
-		    pdev->auto_white_balance->val == awb_indoor ||
-		    pdev->auto_white_balance->val == awb_outdoor ||
-		    pdev->auto_white_balance->val == awb_fl) {
-			if (!pdev->red_balance->is_new)
-				pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
-					READ_RED_GAIN_FORMATTER,
-					&pdev->red_balance->val);
-			if (!pdev->blue_balance->is_new)
-				pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
-					READ_BLUE_GAIN_FORMATTER,
-					&pdev->blue_balance->val);
-		}
-		if (pdev->auto_white_balance->val == awb_auto) {
-			pdev->red_balance->is_volatile = true;
-			pdev->blue_balance->is_volatile = true;
+		if (pdev->auto_white_balance->val != awb_manual)
 			pdev->color_bal_valid = false; /* Force cache update */
-		} else {
-			pdev->red_balance->is_volatile = false;
-			pdev->blue_balance->is_volatile = false;
-		}
 	}
+	if (pdev->auto_white_balance->val != awb_manual)
+		return 0;
 
-	if (ret == 0 && pdev->red_balance->is_new) {
-		if (pdev->auto_white_balance->val != awb_manual)
-			return -EBUSY;
+	if (pdev->red_balance->is_new) {
 		ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
 				      PRESET_MANUAL_RED_GAIN_FORMATTER,
 				      pdev->red_balance->val);
+		if (ret)
+			return ret;
 	}
 
-	if (ret == 0 && pdev->blue_balance->is_new) {
-		if (pdev->auto_white_balance->val != awb_manual)
-			return -EBUSY;
+	if (pdev->blue_balance->is_new) {
 		ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
 				      PRESET_MANUAL_BLUE_GAIN_FORMATTER,
 				      pdev->blue_balance->val);
+		if (ret)
+			return ret;
 	}
-	return ret;
+	return 0;
 }
 
 /* For CODEC2 models which have separate autogain and auto exposure */
 static int pwc_set_autogain(struct pwc_device *pdev)
 {
-	int ret = 0;
+	int ret;
 
 	if (pdev->autogain->is_new) {
 		ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
@@ -692,27 +676,28 @@
 				      pdev->autogain->val ? 0 : 0xff);
 		if (ret)
 			return ret;
+
 		if (pdev->autogain->val)
 			pdev->gain_valid = false; /* Force cache update */
-		else if (!pdev->gain->is_new)
-			pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
-					READ_AGC_FORMATTER,
-					&pdev->gain->val);
 	}
-	if (ret == 0 && pdev->gain->is_new) {
-		if (pdev->autogain->val)
-			return -EBUSY;
+
+	if (pdev->autogain->val)
+		return 0;
+
+	if (pdev->gain->is_new) {
 		ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
 				      PRESET_AGC_FORMATTER,
 				      pdev->gain->val);
+		if (ret)
+			return ret;
 	}
-	return ret;
+	return 0;
 }
 
 /* For CODEC2 models which have separate autogain and auto exposure */
 static int pwc_set_exposure_auto(struct pwc_device *pdev)
 {
-	int ret = 0;
+	int ret;
 	int is_auto = pdev->exposure_auto->val == V4L2_EXPOSURE_AUTO;
 
 	if (pdev->exposure_auto->is_new) {
@@ -721,27 +706,28 @@
 				      is_auto ? 0 : 0xff);
 		if (ret)
 			return ret;
+
 		if (is_auto)
 			pdev->exposure_valid = false; /* Force cache update */
-		else if (!pdev->exposure->is_new)
-			pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
-					 READ_SHUTTER_FORMATTER,
-					 &pdev->exposure->val);
 	}
-	if (ret == 0 && pdev->exposure->is_new) {
-		if (is_auto)
-			return -EBUSY;
+
+	if (is_auto)
+		return 0;
+
+	if (pdev->exposure->is_new) {
 		ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
 				       PRESET_SHUTTER_FORMATTER,
 				       pdev->exposure->val);
+		if (ret)
+			return ret;
 	}
-	return ret;
+	return 0;
 }
 
 /* For CODEC3 models which have autogain controlling both gain and exposure */
 static int pwc_set_autogain_expo(struct pwc_device *pdev)
 {
-	int ret = 0;
+	int ret;
 
 	if (pdev->autogain->is_new) {
 		ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
@@ -749,35 +735,32 @@
 				      pdev->autogain->val ? 0 : 0xff);
 		if (ret)
 			return ret;
+
 		if (pdev->autogain->val) {
 			pdev->gain_valid     = false; /* Force cache update */
 			pdev->exposure_valid = false; /* Force cache update */
-		} else {
-			if (!pdev->gain->is_new)
-				pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
-						READ_AGC_FORMATTER,
-						&pdev->gain->val);
-			if (!pdev->exposure->is_new)
-				pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
-						 READ_SHUTTER_FORMATTER,
-						 &pdev->exposure->val);
 		}
 	}
-	if (ret == 0 && pdev->gain->is_new) {
-		if (pdev->autogain->val)
-			return -EBUSY;
+
+	if (pdev->autogain->val)
+		return 0;
+
+	if (pdev->gain->is_new) {
 		ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
 				      PRESET_AGC_FORMATTER,
 				      pdev->gain->val);
+		if (ret)
+			return ret;
 	}
-	if (ret == 0 && pdev->exposure->is_new) {
-		if (pdev->autogain->val)
-			return -EBUSY;
+
+	if (pdev->exposure->is_new) {
 		ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
 				       PRESET_SHUTTER_FORMATTER,
 				       pdev->exposure->val);
+		if (ret)
+			return ret;
 	}
-	return ret;
+	return 0;
 }
 
 static int pwc_set_motor(struct pwc_device *pdev)
@@ -878,10 +861,6 @@
 					pdev->autocontour->val ? 0 : 0xff);
 		}
 		if (ret == 0 && pdev->contour->is_new) {
-			if (pdev->autocontour->val) {
-				ret = -EBUSY;
-				break;
-			}
 			ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
 					      PRESET_CONTOUR_FORMATTER,
 					      pdev->contour->val);
@@ -1099,6 +1078,14 @@
 	return 0;
 }
 
+static int pwc_log_status(struct file *file, void *priv)
+{
+	struct pwc_device *pdev = video_drvdata(file);
+
+	v4l2_ctrl_handler_log_status(&pdev->ctrl_handler, PWC_NAME);
+	return 0;
+}
+
 static long pwc_default(struct file *file, void *fh, bool valid_prio,
 			int cmd, void *arg)
 {
@@ -1122,6 +1109,7 @@
 	.vidioc_dqbuf			    = pwc_dqbuf,
 	.vidioc_streamon		    = pwc_streamon,
 	.vidioc_streamoff		    = pwc_streamoff,
+	.vidioc_log_status		    = pwc_log_status,
 	.vidioc_enum_framesizes		    = pwc_enum_framesizes,
 	.vidioc_enum_frameintervals	    = pwc_enum_frameintervals,
 	.vidioc_default		    = pwc_default,
diff -druN linux-libre-3.1-gnu/drivers/media/video/pxa_camera.c linux-libre-3.2-gnu/drivers/media/video/pxa_camera.c
--- linux-libre-3.1-gnu/drivers/media/video/pxa_camera.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/pxa_camera.c	2012-01-04 18:55:44.000000000 -0500
@@ -214,6 +214,7 @@
 	unsigned long		ciclk;
 	unsigned long		mclk;
 	u32			mclk_divisor;
+	u16			width_flags;	/* max 10 bits */
 
 	struct list_head	capture;
 
@@ -1020,37 +1021,20 @@
 	 * quick capture interface supports both.
 	 */
 	*flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ?
-		  SOCAM_MASTER : SOCAM_SLAVE) |
-		SOCAM_HSYNC_ACTIVE_HIGH |
-		SOCAM_HSYNC_ACTIVE_LOW |
-		SOCAM_VSYNC_ACTIVE_HIGH |
-		SOCAM_VSYNC_ACTIVE_LOW |
-		SOCAM_DATA_ACTIVE_HIGH |
-		SOCAM_PCLK_SAMPLE_RISING |
-		SOCAM_PCLK_SAMPLE_FALLING;
+		  V4L2_MBUS_MASTER : V4L2_MBUS_SLAVE) |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_HSYNC_ACTIVE_LOW |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_VSYNC_ACTIVE_LOW |
+		V4L2_MBUS_DATA_ACTIVE_HIGH |
+		V4L2_MBUS_PCLK_SAMPLE_RISING |
+		V4L2_MBUS_PCLK_SAMPLE_FALLING;
 
 	/* If requested data width is supported by the platform, use it */
-	switch (buswidth) {
-	case 10:
-		if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10))
-			return -EINVAL;
-		*flags |= SOCAM_DATAWIDTH_10;
-		break;
-	case 9:
-		if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9))
-			return -EINVAL;
-		*flags |= SOCAM_DATAWIDTH_9;
-		break;
-	case 8:
-		if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8))
-			return -EINVAL;
-		*flags |= SOCAM_DATAWIDTH_8;
-		break;
-	default:
-		return -EINVAL;
-	}
+	if ((1 << (buswidth - 1)) & pcdev->width_flags)
+		return 0;
 
-	return 0;
+	return -EINVAL;
 }
 
 static void pxa_camera_setup_cicr(struct soc_camera_device *icd,
@@ -1070,12 +1054,12 @@
 	 * Datawidth is now guaranteed to be equal to one of the three values.
 	 * We fix bit-per-pixel equal to data-width...
 	 */
-	switch (flags & SOCAM_DATAWIDTH_MASK) {
-	case SOCAM_DATAWIDTH_10:
+	switch (icd->current_fmt->host_fmt->bits_per_sample) {
+	case 10:
 		dw = 4;
 		bpp = 0x40;
 		break;
-	case SOCAM_DATAWIDTH_9:
+	case 9:
 		dw = 3;
 		bpp = 0x20;
 		break;
@@ -1084,7 +1068,7 @@
 		 * Actually it can only be 8 now,
 		 * default is just to silence compiler warnings
 		 */
-	case SOCAM_DATAWIDTH_8:
+	case 8:
 		dw = 2;
 		bpp = 0;
 	}
@@ -1093,11 +1077,11 @@
 		cicr4 |= CICR4_PCLK_EN;
 	if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
 		cicr4 |= CICR4_MCLK_EN;
-	if (flags & SOCAM_PCLK_SAMPLE_FALLING)
+	if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
 		cicr4 |= CICR4_PCP;
-	if (flags & SOCAM_HSYNC_ACTIVE_LOW)
+	if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
 		cicr4 |= CICR4_HSP;
-	if (flags & SOCAM_VSYNC_ACTIVE_LOW)
+	if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
 		cicr4 |= CICR4_VSP;
 
 	cicr0 = __raw_readl(pcdev->base + CICR0);
@@ -1151,9 +1135,11 @@
 
 static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
 {
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct pxa_camera_dev *pcdev = ici->priv;
-	unsigned long bus_flags, camera_flags, common_flags;
+	struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+	unsigned long bus_flags, common_flags;
 	int ret;
 	struct pxa_cam *cam = icd->host_priv;
 
@@ -1162,44 +1148,58 @@
 	if (ret < 0)
 		return ret;
 
-	camera_flags = icd->ops->query_bus_param(icd);
-
-	common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
-	if (!common_flags)
-		return -EINVAL;
+	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+	if (!ret) {
+		common_flags = soc_mbus_config_compatible(&cfg,
+							  bus_flags);
+		if (!common_flags) {
+			dev_warn(icd->parent,
+				 "Flags incompatible: camera 0x%x, host 0x%lx\n",
+				 cfg.flags, bus_flags);
+			return -EINVAL;
+		}
+	} else if (ret != -ENOIOCTLCMD) {
+		return ret;
+	} else {
+		common_flags = bus_flags;
+	}
 
 	pcdev->channels = 1;
 
 	/* Make choises, based on platform preferences */
-	if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
-	    (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+	if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
+	    (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
 		if (pcdev->platform_flags & PXA_CAMERA_HSP)
-			common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
 		else
-			common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
 	}
 
-	if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
-	    (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
+	if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
+	    (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
 		if (pcdev->platform_flags & PXA_CAMERA_VSP)
-			common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
+			common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
 		else
-			common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
+			common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
 	}
 
-	if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
-	    (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+	if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
+	    (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
 		if (pcdev->platform_flags & PXA_CAMERA_PCP)
-			common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+			common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
 		else
-			common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+			common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
 	}
 
-	cam->flags = common_flags;
-
-	ret = icd->ops->set_bus_param(icd, common_flags);
-	if (ret < 0)
+	cfg.flags = common_flags;
+	ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+	if (ret < 0 && ret != -ENOIOCTLCMD) {
+		dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n",
+			common_flags, ret);
 		return ret;
+	}
+
+	cam->flags = common_flags;
 
 	pxa_camera_setup_cicr(icd, common_flags, pixfmt);
 
@@ -1209,17 +1209,31 @@
 static int pxa_camera_try_bus_param(struct soc_camera_device *icd,
 				    unsigned char buswidth)
 {
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct pxa_camera_dev *pcdev = ici->priv;
-	unsigned long bus_flags, camera_flags;
+	struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+	unsigned long bus_flags, common_flags;
 	int ret = test_platform_param(pcdev, buswidth, &bus_flags);
 
 	if (ret < 0)
 		return ret;
 
-	camera_flags = icd->ops->query_bus_param(icd);
+	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+	if (!ret) {
+		common_flags = soc_mbus_config_compatible(&cfg,
+							  bus_flags);
+		if (!common_flags) {
+			dev_warn(icd->parent,
+				 "Flags incompatible: camera 0x%x, host 0x%lx\n",
+				 cfg.flags, bus_flags);
+			return -EINVAL;
+		}
+	} else if (ret == -ENOIOCTLCMD) {
+		ret = 0;
+	}
 
-	return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL;
+	return ret;
 }
 
 static const struct soc_mbus_pixelfmt pxa_camera_formats[] = {
@@ -1687,6 +1701,12 @@
 			 "data widths, using default 10 bit\n");
 		pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10;
 	}
+	if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8)
+		pcdev->width_flags = 1 << 7;
+	if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9)
+		pcdev->width_flags |= 1 << 8;
+	if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10)
+		pcdev->width_flags |= 1 << 9;
 	pcdev->mclk = pcdev->pdata->mclk_10khz * 10000;
 	if (!pcdev->mclk) {
 		dev_warn(&pdev->dev,
diff -druN linux-libre-3.1-gnu/drivers/media/video/rj54n1cb0c.c linux-libre-3.2-gnu/drivers/media/video/rj54n1cb0c.c
--- linux-libre-3.1-gnu/drivers/media/video/rj54n1cb0c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/rj54n1cb0c.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,13 +11,15 @@
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/videodev2.h>
+#include <linux/module.h>
 
 #include <media/rj54n1cb0c.h>
 #include <media/soc_camera.h>
-#include <media/soc_mediabus.h>
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
 
 #define RJ54N1_DEV_CODE			0x0400
 #define RJ54N1_DEV_CODE2		0x0401
@@ -148,6 +150,7 @@
 
 struct rj54n1 {
 	struct v4l2_subdev subdev;
+	struct v4l2_ctrl_handler hdl;
 	struct rj54n1_clock_div clk_div;
 	const struct rj54n1_datafmt *fmt;
 	struct v4l2_rect rect;	/* Sensor window */
@@ -499,31 +502,6 @@
 	return reg_set(client, RJ54N1_STILL_CONTROL, (!enable) << 7, 0x80);
 }
 
-static int rj54n1_set_bus_param(struct soc_camera_device *icd,
-				unsigned long flags)
-{
-	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	/* Figures 2.5-1 to 2.5-3 - default falling pixclk edge */
-
-	if (flags & SOCAM_PCLK_SAMPLE_RISING)
-		return reg_write(client, RJ54N1_OUT_SIGPO, 1 << 4);
-	else
-		return reg_write(client, RJ54N1_OUT_SIGPO, 0);
-}
-
-static unsigned long rj54n1_query_bus_param(struct soc_camera_device *icd)
-{
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-	const unsigned long flags =
-		SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING |
-		SOCAM_MASTER | SOCAM_DATAWIDTH_8 |
-		SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
-		SOCAM_DATA_ACTIVE_HIGH;
-
-	return soc_camera_apply_sensor_flags(icl, flags);
-}
-
 static int rj54n1_set_rect(struct i2c_client *client,
 			   u16 reg_x, u16 reg_y, u16 reg_xy,
 			   u32 width, u32 height)
@@ -1202,134 +1180,51 @@
 }
 #endif
 
-static const struct v4l2_queryctrl rj54n1_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,
-	}, {
-		.id		= V4L2_CID_GAIN,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Gain",
-		.minimum	= 0,
-		.maximum	= 127,
-		.step		= 1,
-		.default_value	= 66,
-		.flags		= V4L2_CTRL_FLAG_SLIDER,
-	}, {
-		.id		= V4L2_CID_AUTO_WHITE_BALANCE,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Auto white balance",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 1,
-	},
-};
-
-static struct soc_camera_ops rj54n1_ops = {
-	.set_bus_param		= rj54n1_set_bus_param,
-	.query_bus_param	= rj54n1_query_bus_param,
-	.controls		= rj54n1_controls,
-	.num_controls		= ARRAY_SIZE(rj54n1_controls),
-};
-
-static int rj54n1_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int rj54n1_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct rj54n1 *rj54n1 = container_of(ctrl->handler, struct rj54n1, hdl);
+	struct v4l2_subdev *sd = &rj54n1->subdev;
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct rj54n1 *rj54n1 = to_rj54n1(client);
-	int data;
-
-	switch (ctrl->id) {
-	case V4L2_CID_VFLIP:
-		data = reg_read(client, RJ54N1_MIRROR_STILL_MODE);
-		if (data < 0)
-			return -EIO;
-		ctrl->value = !(data & 1);
-		break;
-	case V4L2_CID_HFLIP:
-		data = reg_read(client, RJ54N1_MIRROR_STILL_MODE);
-		if (data < 0)
-			return -EIO;
-		ctrl->value = !(data & 2);
-		break;
-	case V4L2_CID_GAIN:
-		data = reg_read(client, RJ54N1_Y_GAIN);
-		if (data < 0)
-			return -EIO;
-
-		ctrl->value = data / 2;
-		break;
-	case V4L2_CID_AUTO_WHITE_BALANCE:
-		ctrl->value = rj54n1->auto_wb;
-		break;
-	}
-
-	return 0;
-}
-
-static int rj54n1_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
 	int data;
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct rj54n1 *rj54n1 = to_rj54n1(client);
-	const struct v4l2_queryctrl *qctrl;
-
-	qctrl = soc_camera_find_qctrl(&rj54n1_ops, ctrl->id);
-	if (!qctrl)
-		return -EINVAL;
 
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
-		if (ctrl->value)
+		if (ctrl->val)
 			data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 0, 1);
 		else
 			data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 1, 1);
 		if (data < 0)
 			return -EIO;
-		break;
+		return 0;
 	case V4L2_CID_HFLIP:
-		if (ctrl->value)
+		if (ctrl->val)
 			data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 0, 2);
 		else
 			data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 2, 2);
 		if (data < 0)
 			return -EIO;
-		break;
+		return 0;
 	case V4L2_CID_GAIN:
-		if (ctrl->value > qctrl->maximum ||
-		    ctrl->value < qctrl->minimum)
-			return -EINVAL;
-		else if (reg_write(client, RJ54N1_Y_GAIN, ctrl->value * 2) < 0)
+		if (reg_write(client, RJ54N1_Y_GAIN, ctrl->val * 2) < 0)
 			return -EIO;
-		break;
+		return 0;
 	case V4L2_CID_AUTO_WHITE_BALANCE:
 		/* Auto WB area - whole image */
-		if (reg_set(client, RJ54N1_WB_SEL_WEIGHT_I, ctrl->value << 7,
+		if (reg_set(client, RJ54N1_WB_SEL_WEIGHT_I, ctrl->val << 7,
 			    0x80) < 0)
 			return -EIO;
-		rj54n1->auto_wb = ctrl->value;
-		break;
+		rj54n1->auto_wb = ctrl->val;
+		return 0;
 	}
 
-	return 0;
+	return -EINVAL;
 }
 
+static const struct v4l2_ctrl_ops rj54n1_ctrl_ops = {
+	.s_ctrl = rj54n1_s_ctrl,
+};
+
 static struct v4l2_subdev_core_ops rj54n1_subdev_core_ops = {
-	.g_ctrl		= rj54n1_g_ctrl,
-	.s_ctrl		= rj54n1_s_ctrl,
 	.g_chip_ident	= rj54n1_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register	= rj54n1_g_register,
@@ -1337,6 +1232,36 @@
 #endif
 };
 
+static int rj54n1_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags =
+		V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING |
+		V4L2_MBUS_MASTER | V4L2_MBUS_DATA_ACTIVE_HIGH |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static int rj54n1_s_mbus_config(struct v4l2_subdev *sd,
+				const struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	/* Figures 2.5-1 to 2.5-3 - default falling pixclk edge */
+	if (soc_camera_apply_board_flags(icl, cfg) &
+	    V4L2_MBUS_PCLK_SAMPLE_RISING)
+		return reg_write(client, RJ54N1_OUT_SIGPO, 1 << 4);
+	else
+		return reg_write(client, RJ54N1_OUT_SIGPO, 0);
+}
+
 static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = {
 	.s_stream	= rj54n1_s_stream,
 	.s_mbus_fmt	= rj54n1_s_fmt,
@@ -1346,6 +1271,8 @@
 	.g_crop		= rj54n1_g_crop,
 	.s_crop		= rj54n1_s_crop,
 	.cropcap	= rj54n1_cropcap,
+	.g_mbus_config	= rj54n1_g_mbus_config,
+	.s_mbus_config	= rj54n1_s_mbus_config,
 };
 
 static struct v4l2_subdev_ops rj54n1_subdev_ops = {
@@ -1357,17 +1284,12 @@
  * Interface active, can use i2c. If it fails, it can indeed mean, that
  * this wasn't our capture interface, so, we wait for the right one
  */
-static int rj54n1_video_probe(struct soc_camera_device *icd,
-			      struct i2c_client *client,
+static int rj54n1_video_probe(struct i2c_client *client,
 			      struct rj54n1_pdata *priv)
 {
 	int data1, data2;
 	int ret;
 
-	/* We must have a parent by now. And it cannot be a wrong one. */
-	BUG_ON(!icd->parent ||
-	       to_soc_camera_host(icd->parent)->nr != icd->iface);
-
 	/* Read out the chip version register */
 	data1 = reg_read(client, RJ54N1_DEV_CODE);
 	data2 = reg_read(client, RJ54N1_DEV_CODE2);
@@ -1395,18 +1317,11 @@
 			const struct i2c_device_id *did)
 {
 	struct rj54n1 *rj54n1;
-	struct soc_camera_device *icd = client->dev.platform_data;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-	struct soc_camera_link *icl;
 	struct rj54n1_pdata *rj54n1_priv;
 	int ret;
 
-	if (!icd) {
-		dev_err(&client->dev, "RJ54N1CB0C: missing soc-camera data!\n");
-		return -EINVAL;
-	}
-
-	icl = to_soc_camera_link(icd);
 	if (!icl || !icl->priv) {
 		dev_err(&client->dev, "RJ54N1CB0C: missing platform data!\n");
 		return -EINVAL;
@@ -1425,8 +1340,22 @@
 		return -ENOMEM;
 
 	v4l2_i2c_subdev_init(&rj54n1->subdev, client, &rj54n1_subdev_ops);
+	v4l2_ctrl_handler_init(&rj54n1->hdl, 4);
+	v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops,
+			V4L2_CID_GAIN, 0, 127, 1, 66);
+	v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops,
+			V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
+	rj54n1->subdev.ctrl_handler = &rj54n1->hdl;
+	if (rj54n1->hdl.error) {
+		int err = rj54n1->hdl.error;
 
-	icd->ops		= &rj54n1_ops;
+		kfree(rj54n1);
+		return err;
+	}
 
 	rj54n1->clk_div		= clk_div;
 	rj54n1->rect.left	= RJ54N1_COLUMN_SKIP;
@@ -1440,25 +1369,24 @@
 	rj54n1->tgclk_mhz	= (rj54n1_priv->mclk_freq / PLL_L * PLL_N) /
 		(clk_div.ratio_tg + 1) / (clk_div.ratio_t + 1);
 
-	ret = rj54n1_video_probe(icd, client, rj54n1_priv);
+	ret = rj54n1_video_probe(client, rj54n1_priv);
 	if (ret < 0) {
-		icd->ops = NULL;
+		v4l2_ctrl_handler_free(&rj54n1->hdl);
 		kfree(rj54n1);
 		return ret;
 	}
-
-	return ret;
+	return v4l2_ctrl_handler_setup(&rj54n1->hdl);
 }
 
 static int rj54n1_remove(struct i2c_client *client)
 {
 	struct rj54n1 *rj54n1 = to_rj54n1(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 
-	icd->ops = NULL;
+	v4l2_device_unregister_subdev(&rj54n1->subdev);
 	if (icl->free_bus)
 		icl->free_bus(icl);
+	v4l2_ctrl_handler_free(&rj54n1->hdl);
 	kfree(rj54n1);
 
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5k6aa.c linux-libre-3.2-gnu/drivers/media/video/s5k6aa.c
--- linux-libre-3.1-gnu/drivers/media/video/s5k6aa.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/s5k6aa.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1681 @@
+/*
+ * Driver for Samsung S5K6AAFX SXGA 1/6" 1.3M CMOS Image Sensor
+ * with embedded SoC ISP.
+ *
+ * Copyright (C) 2011, Samsung Electronics Co., Ltd.
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * Based on a driver authored by Dongsoo Nathaniel Kim.
+ * Copyright (C) 2009, Dongsoo Nathaniel Kim <dongsoo45.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 version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/media.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-mediabus.h>
+#include <media/s5k6aa.h>
+
+static int debug;
+module_param(debug, int, 0644);
+
+#define DRIVER_NAME			"S5K6AA"
+
+/* The token to indicate array termination */
+#define S5K6AA_TERM			0xffff
+#define S5K6AA_OUT_WIDTH_DEF		640
+#define S5K6AA_OUT_HEIGHT_DEF		480
+#define S5K6AA_WIN_WIDTH_MAX		1280
+#define S5K6AA_WIN_HEIGHT_MAX		1024
+#define S5K6AA_WIN_WIDTH_MIN		8
+#define S5K6AA_WIN_HEIGHT_MIN		8
+
+/*
+ * H/W register Interface (0xD0000000 - 0xD0000FFF)
+ */
+#define AHB_MSB_ADDR_PTR		0xfcfc
+#define GEN_REG_OFFSH			0xd000
+#define REG_CMDWR_ADDRH			0x0028
+#define REG_CMDWR_ADDRL			0x002a
+#define REG_CMDRD_ADDRH			0x002c
+#define REG_CMDRD_ADDRL			0x002e
+#define REG_CMDBUF0_ADDR		0x0f12
+#define REG_CMDBUF1_ADDR		0x0f10
+
+/*
+ * Host S/W Register interface (0x70000000 - 0x70002000)
+ * The value of the two most significant address bytes is 0x7000,
+ * (HOST_SWIF_OFFS_H). The register addresses below specify 2 LSBs.
+ */
+#define HOST_SWIF_OFFSH			0x7000
+
+/* Initialization parameters */
+/* Master clock frequency in KHz */
+#define REG_I_INCLK_FREQ_L		0x01b8
+#define REG_I_INCLK_FREQ_H		0x01ba
+#define  MIN_MCLK_FREQ_KHZ		6000U
+#define  MAX_MCLK_FREQ_KHZ		27000U
+#define REG_I_USE_NPVI_CLOCKS		0x01c6
+#define REG_I_USE_NMIPI_CLOCKS		0x01c8
+
+/* Clock configurations, n = 0..2. REG_I_* frequency unit is 4 kHz. */
+#define REG_I_OPCLK_4KHZ(n)		((n) * 6 + 0x01cc)
+#define REG_I_MIN_OUTRATE_4KHZ(n)	((n) * 6 + 0x01ce)
+#define REG_I_MAX_OUTRATE_4KHZ(n)	((n) * 6 + 0x01d0)
+#define  SYS_PLL_OUT_FREQ		(48000000 / 4000)
+#define  PCLK_FREQ_MIN			(24000000 / 4000)
+#define  PCLK_FREQ_MAX			(48000000 / 4000)
+#define REG_I_INIT_PARAMS_UPDATED	0x01e0
+#define REG_I_ERROR_INFO		0x01e2
+
+/* General purpose parameters */
+#define REG_USER_BRIGHTNESS		0x01e4
+#define REG_USER_CONTRAST		0x01e6
+#define REG_USER_SATURATION		0x01e8
+#define REG_USER_SHARPBLUR		0x01ea
+
+#define REG_G_SPEC_EFFECTS		0x01ee
+#define REG_G_ENABLE_PREV		0x01f0
+#define REG_G_ENABLE_PREV_CHG		0x01f2
+#define REG_G_NEW_CFG_SYNC		0x01f8
+#define REG_G_PREVZOOM_IN_WIDTH		0x020a
+#define REG_G_PREVZOOM_IN_HEIGHT	0x020c
+#define REG_G_PREVZOOM_IN_XOFFS		0x020e
+#define REG_G_PREVZOOM_IN_YOFFS		0x0210
+#define REG_G_INPUTS_CHANGE_REQ		0x021a
+#define REG_G_ACTIVE_PREV_CFG		0x021c
+#define REG_G_PREV_CFG_CHG		0x021e
+#define REG_G_PREV_OPEN_AFTER_CH	0x0220
+#define REG_G_PREV_CFG_ERROR		0x0222
+
+/* Preview control section. n = 0...4. */
+#define PREG(n, x)			((n) * 0x26 + x)
+#define REG_P_OUT_WIDTH(n)		PREG(n, 0x0242)
+#define REG_P_OUT_HEIGHT(n)		PREG(n, 0x0244)
+#define REG_P_FMT(n)			PREG(n, 0x0246)
+#define REG_P_MAX_OUT_RATE(n)		PREG(n, 0x0248)
+#define REG_P_MIN_OUT_RATE(n)		PREG(n, 0x024a)
+#define REG_P_PVI_MASK(n)		PREG(n, 0x024c)
+#define REG_P_CLK_INDEX(n)		PREG(n, 0x024e)
+#define REG_P_FR_RATE_TYPE(n)		PREG(n, 0x0250)
+#define  FR_RATE_DYNAMIC		0
+#define  FR_RATE_FIXED			1
+#define  FR_RATE_FIXED_ACCURATE		2
+#define REG_P_FR_RATE_Q_TYPE(n)		PREG(n, 0x0252)
+#define  FR_RATE_Q_BEST_FRRATE		1 /* Binning enabled */
+#define  FR_RATE_Q_BEST_QUALITY		2 /* Binning disabled */
+/* Frame period in 0.1 ms units */
+#define REG_P_MAX_FR_TIME(n)		PREG(n, 0x0254)
+#define REG_P_MIN_FR_TIME(n)		PREG(n, 0x0256)
+/* Conversion to REG_P_[MAX/MIN]_FR_TIME value; __t: time in us */
+#define  US_TO_FR_TIME(__t)		((__t) / 100)
+#define  S5K6AA_MIN_FR_TIME		33300  /* us */
+#define  S5K6AA_MAX_FR_TIME		650000 /* us */
+#define  S5K6AA_MAX_HIGHRES_FR_TIME	666    /* x100 us */
+/* The below 5 registers are for "device correction" values */
+#define REG_P_COLORTEMP(n)		PREG(n, 0x025e)
+#define REG_P_PREV_MIRROR(n)		PREG(n, 0x0262)
+
+/* Extended image property controls */
+/* Exposure time in 10 us units */
+#define REG_SF_USR_EXPOSURE_L		0x03c6
+#define REG_SF_USR_EXPOSURE_H		0x03c8
+#define REG_SF_USR_EXPOSURE_CHG		0x03ca
+#define REG_SF_USR_TOT_GAIN		0x03cc
+#define REG_SF_USR_TOT_GAIN_CHG		0x03ce
+#define REG_SF_RGAIN			0x03d0
+#define REG_SF_RGAIN_CHG		0x03d2
+#define REG_SF_GGAIN			0x03d4
+#define REG_SF_GGAIN_CHG		0x03d6
+#define REG_SF_BGAIN			0x03d8
+#define REG_SF_BGAIN_CHG		0x03da
+#define REG_SF_FLICKER_QUANT		0x03dc
+#define REG_SF_FLICKER_QUANT_CHG	0x03de
+
+/* Output interface (parallel/MIPI) setup */
+#define REG_OIF_EN_MIPI_LANES		0x03fa
+#define REG_OIF_EN_PACKETS		0x03fc
+#define REG_OIF_CFG_CHG			0x03fe
+
+/* Auto-algorithms enable mask */
+#define REG_DBG_AUTOALG_EN		0x0400
+#define  AALG_ALL_EN_MASK		(1 << 0)
+#define  AALG_AE_EN_MASK		(1 << 1)
+#define  AALG_DIVLEI_EN_MASK		(1 << 2)
+#define  AALG_WB_EN_MASK		(1 << 3)
+#define  AALG_FLICKER_EN_MASK		(1 << 5)
+#define  AALG_FIT_EN_MASK		(1 << 6)
+#define  AALG_WRHW_EN_MASK		(1 << 7)
+
+/* Firmware revision information */
+#define REG_FW_APIVER			0x012e
+#define  S5K6AAFX_FW_APIVER		0x0001
+#define REG_FW_REVISION			0x0130
+
+/* For now we use only one user configuration register set */
+#define S5K6AA_MAX_PRESETS		1
+
+static const char * const s5k6aa_supply_names[] = {
+	"vdd_core",	/* Digital core supply 1.5V (1.4V to 1.6V) */
+	"vdda",		/* Analog power supply 2.8V (2.6V to 3.0V) */
+	"vdd_reg",	/* Regulator input power 1.8V (1.7V to 1.9V)
+			   or 2.8V (2.6V to 3.0) */
+	"vddio",	/* I/O supply 1.8V (1.65V to 1.95V)
+			   or 2.8V (2.5V to 3.1V) */
+};
+#define S5K6AA_NUM_SUPPLIES ARRAY_SIZE(s5k6aa_supply_names)
+
+enum s5k6aa_gpio_id {
+	STBY,
+	RST,
+	GPIO_NUM,
+};
+
+struct s5k6aa_regval {
+	u16 addr;
+	u16 val;
+};
+
+struct s5k6aa_pixfmt {
+	enum v4l2_mbus_pixelcode code;
+	u32 colorspace;
+	/* REG_P_FMT(x) register value */
+	u16 reg_p_fmt;
+};
+
+struct s5k6aa_preset {
+	/* output pixel format and resolution */
+	struct v4l2_mbus_framefmt mbus_fmt;
+	u8 clk_id;
+	u8 index;
+};
+
+struct s5k6aa_ctrls {
+	struct v4l2_ctrl_handler handler;
+	/* Auto / manual white balance cluster */
+	struct v4l2_ctrl *awb;
+	struct v4l2_ctrl *gain_red;
+	struct v4l2_ctrl *gain_blue;
+	struct v4l2_ctrl *gain_green;
+	/* Mirror cluster */
+	struct v4l2_ctrl *hflip;
+	struct v4l2_ctrl *vflip;
+	/* Auto exposure / manual exposure and gain cluster */
+	struct v4l2_ctrl *auto_exp;
+	struct v4l2_ctrl *exposure;
+	struct v4l2_ctrl *gain;
+};
+
+struct s5k6aa_interval {
+	u16 reg_fr_time;
+	struct v4l2_fract interval;
+	/* Maximum rectangle for the interval */
+	struct v4l2_frmsize_discrete size;
+};
+
+struct s5k6aa {
+	struct v4l2_subdev sd;
+	struct media_pad pad;
+
+	enum v4l2_mbus_type bus_type;
+	u8 mipi_lanes;
+
+	int (*s_power)(int enable);
+	struct regulator_bulk_data supplies[S5K6AA_NUM_SUPPLIES];
+	struct s5k6aa_gpio gpio[GPIO_NUM];
+
+	/* external master clock frequency */
+	unsigned long mclk_frequency;
+	/* ISP internal master clock frequency */
+	u16 clk_fop;
+	/* output pixel clock frequency range */
+	u16 pclk_fmin;
+	u16 pclk_fmax;
+
+	unsigned int inv_hflip:1;
+	unsigned int inv_vflip:1;
+
+	/* protects the struct members below */
+	struct mutex lock;
+
+	/* sensor matrix scan window */
+	struct v4l2_rect ccd_rect;
+
+	struct s5k6aa_ctrls ctrls;
+	struct s5k6aa_preset presets[S5K6AA_MAX_PRESETS];
+	struct s5k6aa_preset *preset;
+	const struct s5k6aa_interval *fiv;
+
+	unsigned int streaming:1;
+	unsigned int apply_cfg:1;
+	unsigned int apply_crop:1;
+	unsigned int power;
+};
+
+static struct s5k6aa_regval s5k6aa_analog_config[] = {
+	/* Analog settings */
+	{ 0x112a, 0x0000 }, { 0x1132, 0x0000 },
+	{ 0x113e, 0x0000 }, { 0x115c, 0x0000 },
+	{ 0x1164, 0x0000 }, { 0x1174, 0x0000 },
+	{ 0x1178, 0x0000 }, { 0x077a, 0x0000 },
+	{ 0x077c, 0x0000 }, { 0x077e, 0x0000 },
+	{ 0x0780, 0x0000 }, { 0x0782, 0x0000 },
+	{ 0x0784, 0x0000 }, { 0x0786, 0x0000 },
+	{ 0x0788, 0x0000 }, { 0x07a2, 0x0000 },
+	{ 0x07a4, 0x0000 }, { 0x07a6, 0x0000 },
+	{ 0x07a8, 0x0000 }, { 0x07b6, 0x0000 },
+	{ 0x07b8, 0x0002 }, { 0x07ba, 0x0004 },
+	{ 0x07bc, 0x0004 }, { 0x07be, 0x0005 },
+	{ 0x07c0, 0x0005 }, { S5K6AA_TERM, 0 },
+};
+
+/* TODO: Add RGB888 and Bayer format */
+static const struct s5k6aa_pixfmt s5k6aa_formats[] = {
+	{ V4L2_MBUS_FMT_YUYV8_2X8,	V4L2_COLORSPACE_JPEG,	5 },
+	/* range 16-240 */
+	{ V4L2_MBUS_FMT_YUYV8_2X8,	V4L2_COLORSPACE_REC709,	6 },
+	{ V4L2_MBUS_FMT_RGB565_2X8_BE,	V4L2_COLORSPACE_JPEG,	0 },
+};
+
+static const struct s5k6aa_interval s5k6aa_intervals[] = {
+	{ 1000, {10000, 1000000}, {1280, 1024} }, /* 10 fps */
+	{ 666,  {15000, 1000000}, {1280, 1024} }, /* 15 fps */
+	{ 500,  {20000, 1000000}, {1280, 720} },  /* 20 fps */
+	{ 400,  {25000, 1000000}, {640, 480} },   /* 25 fps */
+	{ 333,  {33300, 1000000}, {640, 480} },   /* 30 fps */
+};
+
+#define S5K6AA_INTERVAL_DEF_INDEX 1 /* 15 fps */
+
+static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct s5k6aa, ctrls.handler)->sd;
+}
+
+static inline struct s5k6aa *to_s5k6aa(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct s5k6aa, sd);
+}
+
+/* Set initial values for all preview presets */
+static void s5k6aa_presets_data_init(struct s5k6aa *s5k6aa)
+{
+	struct s5k6aa_preset *preset = &s5k6aa->presets[0];
+	int i;
+
+	for (i = 0; i < S5K6AA_MAX_PRESETS; i++) {
+		preset->mbus_fmt.width	= S5K6AA_OUT_WIDTH_DEF;
+		preset->mbus_fmt.height	= S5K6AA_OUT_HEIGHT_DEF;
+		preset->mbus_fmt.code	= s5k6aa_formats[0].code;
+		preset->index		= i;
+		preset->clk_id		= 0;
+		preset++;
+	}
+
+	s5k6aa->fiv = &s5k6aa_intervals[S5K6AA_INTERVAL_DEF_INDEX];
+	s5k6aa->preset = &s5k6aa->presets[0];
+}
+
+static int s5k6aa_i2c_read(struct i2c_client *client, u16 addr, u16 *val)
+{
+	u8 wbuf[2] = {addr >> 8, addr & 0xFF};
+	struct i2c_msg msg[2];
+	u8 rbuf[2];
+	int ret;
+
+	msg[0].addr = client->addr;
+	msg[0].flags = 0;
+	msg[0].len = 2;
+	msg[0].buf = wbuf;
+
+	msg[1].addr = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].len = 2;
+	msg[1].buf = rbuf;
+
+	ret = i2c_transfer(client->adapter, msg, 2);
+	*val = be16_to_cpu(*((u16 *)rbuf));
+
+	v4l2_dbg(3, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val);
+
+	return ret == 2 ? 0 : ret;
+}
+
+static int s5k6aa_i2c_write(struct i2c_client *client, u16 addr, u16 val)
+{
+	u8 buf[4] = {addr >> 8, addr & 0xFF, val >> 8, val & 0xFF};
+
+	int ret = i2c_master_send(client, buf, 4);
+	v4l2_dbg(3, debug, client, "i2c_write: 0x%04X : 0x%04x\n", addr, val);
+
+	return ret == 4 ? 0 : ret;
+}
+
+/* The command register write, assumes Command_Wr_addH = 0x7000. */
+static int s5k6aa_write(struct i2c_client *c, u16 addr, u16 val)
+{
+	int ret = s5k6aa_i2c_write(c, REG_CMDWR_ADDRL, addr);
+	if (ret)
+		return ret;
+	return s5k6aa_i2c_write(c, REG_CMDBUF0_ADDR, val);
+}
+
+/* The command register read, assumes Command_Rd_addH = 0x7000. */
+static int s5k6aa_read(struct i2c_client *client, u16 addr, u16 *val)
+{
+	int ret = s5k6aa_i2c_write(client, REG_CMDRD_ADDRL, addr);
+	if (ret)
+		return ret;
+	return s5k6aa_i2c_read(client, REG_CMDBUF0_ADDR, val);
+}
+
+static int s5k6aa_write_array(struct v4l2_subdev *sd,
+			      const struct s5k6aa_regval *msg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u16 addr_incr = 0;
+	int ret = 0;
+
+	while (msg->addr != S5K6AA_TERM) {
+		if (addr_incr != 2)
+			ret = s5k6aa_i2c_write(client, REG_CMDWR_ADDRL,
+					       msg->addr);
+		if (ret)
+			break;
+		ret = s5k6aa_i2c_write(client, REG_CMDBUF0_ADDR, msg->val);
+		if (ret)
+			break;
+		/* Assume that msg->addr is always less than 0xfffc */
+		addr_incr = (msg + 1)->addr - msg->addr;
+		msg++;
+	}
+
+	return ret;
+}
+
+/* Configure the AHB high address bytes for GTG registers access */
+static int s5k6aa_set_ahb_address(struct i2c_client *client)
+{
+	int ret = s5k6aa_i2c_write(client, AHB_MSB_ADDR_PTR, GEN_REG_OFFSH);
+	if (ret)
+		return ret;
+	ret = s5k6aa_i2c_write(client, REG_CMDRD_ADDRH, HOST_SWIF_OFFSH);
+	if (ret)
+		return ret;
+	return s5k6aa_i2c_write(client, REG_CMDWR_ADDRH, HOST_SWIF_OFFSH);
+}
+
+/**
+ * s5k6aa_configure_pixel_clock - apply ISP main clock/PLL configuration
+ *
+ * Configure the internal ISP PLL for the required output frequency.
+ * Locking: called with s5k6aa.lock mutex held.
+ */
+static int s5k6aa_configure_pixel_clocks(struct s5k6aa *s5k6aa)
+{
+	struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
+	unsigned long fmclk = s5k6aa->mclk_frequency / 1000;
+	u16 status;
+	int ret;
+
+	if (WARN(fmclk < MIN_MCLK_FREQ_KHZ || fmclk > MAX_MCLK_FREQ_KHZ,
+		 "Invalid clock frequency: %ld\n", fmclk))
+		return -EINVAL;
+
+	s5k6aa->pclk_fmin = PCLK_FREQ_MIN;
+	s5k6aa->pclk_fmax = PCLK_FREQ_MAX;
+	s5k6aa->clk_fop = SYS_PLL_OUT_FREQ;
+
+	/* External input clock frequency in kHz */
+	ret = s5k6aa_write(c, REG_I_INCLK_FREQ_H, fmclk >> 16);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_I_INCLK_FREQ_L, fmclk & 0xFFFF);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_I_USE_NPVI_CLOCKS, 1);
+	/* Internal PLL frequency */
+	if (!ret)
+		ret = s5k6aa_write(c, REG_I_OPCLK_4KHZ(0), s5k6aa->clk_fop);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_I_MIN_OUTRATE_4KHZ(0),
+				   s5k6aa->pclk_fmin);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_I_MAX_OUTRATE_4KHZ(0),
+				   s5k6aa->pclk_fmax);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_I_INIT_PARAMS_UPDATED, 1);
+	if (!ret)
+		ret = s5k6aa_read(c, REG_I_ERROR_INFO, &status);
+
+	return ret ? ret : (status ? -EINVAL : 0);
+}
+
+/* Set horizontal and vertical image flipping */
+static int s5k6aa_set_mirror(struct s5k6aa *s5k6aa, int horiz_flip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+	int index = s5k6aa->preset->index;
+
+	unsigned int vflip = s5k6aa->ctrls.vflip->val ^ s5k6aa->inv_vflip;
+	unsigned int flip = (horiz_flip ^ s5k6aa->inv_hflip) | (vflip << 1);
+
+	return s5k6aa_write(client, REG_P_PREV_MIRROR(index), flip);
+}
+
+/* Configure auto/manual white balance and R/G/B gains */
+static int s5k6aa_set_awb(struct s5k6aa *s5k6aa, int awb)
+{
+	struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
+	struct s5k6aa_ctrls *ctrls = &s5k6aa->ctrls;
+	u16 reg;
+
+	int ret = s5k6aa_read(c, REG_DBG_AUTOALG_EN, &reg);
+
+	if (!ret && !awb) {
+		ret = s5k6aa_write(c, REG_SF_RGAIN, ctrls->gain_red->val);
+		if (!ret)
+			ret = s5k6aa_write(c, REG_SF_RGAIN_CHG, 1);
+		if (ret)
+			return ret;
+
+		ret = s5k6aa_write(c, REG_SF_GGAIN, ctrls->gain_green->val);
+		if (!ret)
+			ret = s5k6aa_write(c, REG_SF_GGAIN_CHG, 1);
+		if (ret)
+			return ret;
+
+		ret = s5k6aa_write(c, REG_SF_BGAIN, ctrls->gain_blue->val);
+		if (!ret)
+			ret = s5k6aa_write(c, REG_SF_BGAIN_CHG, 1);
+	}
+	if (!ret) {
+		reg = awb ? reg | AALG_WB_EN_MASK : reg & ~AALG_WB_EN_MASK;
+		ret = s5k6aa_write(c, REG_DBG_AUTOALG_EN, reg);
+	}
+
+	return ret;
+}
+
+/* Program FW with exposure time, 'exposure' in us units */
+static int s5k6aa_set_user_exposure(struct i2c_client *client, int exposure)
+{
+	unsigned int time = exposure / 10;
+
+	int ret = s5k6aa_write(client, REG_SF_USR_EXPOSURE_L, time & 0xffff);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_SF_USR_EXPOSURE_H, time >> 16);
+	if (ret)
+		return ret;
+	return s5k6aa_write(client, REG_SF_USR_EXPOSURE_CHG, 1);
+}
+
+static int s5k6aa_set_user_gain(struct i2c_client *client, int gain)
+{
+	int ret = s5k6aa_write(client, REG_SF_USR_TOT_GAIN, gain);
+	if (ret)
+		return ret;
+	return s5k6aa_write(client, REG_SF_USR_TOT_GAIN_CHG, 1);
+}
+
+/* Set auto/manual exposure and total gain */
+static int s5k6aa_set_auto_exposure(struct s5k6aa *s5k6aa, int value)
+{
+	struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
+	unsigned int exp_time = s5k6aa->ctrls.exposure->val;
+	u16 auto_alg;
+
+	int ret = s5k6aa_read(c, REG_DBG_AUTOALG_EN, &auto_alg);
+	if (ret)
+		return ret;
+
+	v4l2_dbg(1, debug, c, "man_exp: %d, auto_exp: %d, a_alg: 0x%x\n",
+		 exp_time, value, auto_alg);
+
+	if (value == V4L2_EXPOSURE_AUTO) {
+		auto_alg |= AALG_AE_EN_MASK | AALG_DIVLEI_EN_MASK;
+	} else {
+		ret = s5k6aa_set_user_exposure(c, exp_time);
+		if (ret)
+			return ret;
+		ret = s5k6aa_set_user_gain(c, s5k6aa->ctrls.gain->val);
+		if (ret)
+			return ret;
+		auto_alg &= ~(AALG_AE_EN_MASK | AALG_DIVLEI_EN_MASK);
+	}
+
+	return s5k6aa_write(c, REG_DBG_AUTOALG_EN, auto_alg);
+}
+
+static int s5k6aa_set_anti_flicker(struct s5k6aa *s5k6aa, int value)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+	u16 auto_alg;
+	int ret;
+
+	ret = s5k6aa_read(client, REG_DBG_AUTOALG_EN, &auto_alg);
+	if (ret)
+		return ret;
+
+	if (value == V4L2_CID_POWER_LINE_FREQUENCY_AUTO) {
+		auto_alg |= AALG_FLICKER_EN_MASK;
+	} else {
+		auto_alg &= ~AALG_FLICKER_EN_MASK;
+		/* The V4L2_CID_LINE_FREQUENCY control values match
+		 * the register values */
+		ret = s5k6aa_write(client, REG_SF_FLICKER_QUANT, value);
+		if (ret)
+			return ret;
+		ret = s5k6aa_write(client, REG_SF_FLICKER_QUANT_CHG, 1);
+		if (ret)
+			return ret;
+	}
+
+	return s5k6aa_write(client, REG_DBG_AUTOALG_EN, auto_alg);
+}
+
+static int s5k6aa_set_colorfx(struct s5k6aa *s5k6aa, int val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+	static const struct v4l2_control colorfx[] = {
+		{ V4L2_COLORFX_NONE,	 0 },
+		{ V4L2_COLORFX_BW,	 1 },
+		{ V4L2_COLORFX_NEGATIVE, 2 },
+		{ V4L2_COLORFX_SEPIA,	 3 },
+		{ V4L2_COLORFX_SKY_BLUE, 4 },
+		{ V4L2_COLORFX_SKETCH,	 5 },
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(colorfx); i++) {
+		if (colorfx[i].id == val)
+			return s5k6aa_write(client, REG_G_SPEC_EFFECTS,
+					    colorfx[i].value);
+	}
+	return -EINVAL;
+}
+
+static int s5k6aa_preview_config_status(struct i2c_client *client)
+{
+	u16 error = 0;
+	int ret = s5k6aa_read(client, REG_G_PREV_CFG_ERROR, &error);
+
+	v4l2_dbg(1, debug, client, "error: 0x%x (%d)\n", error, ret);
+	return ret ? ret : (error ? -EINVAL : 0);
+}
+
+static int s5k6aa_get_pixfmt_index(struct s5k6aa *s5k6aa,
+				   struct v4l2_mbus_framefmt *mf)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(s5k6aa_formats); i++)
+		if (mf->colorspace == s5k6aa_formats[i].colorspace &&
+		    mf->code == s5k6aa_formats[i].code)
+			return i;
+	return 0;
+}
+
+static int s5k6aa_set_output_framefmt(struct s5k6aa *s5k6aa,
+				      struct s5k6aa_preset *preset)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+	int fmt_index = s5k6aa_get_pixfmt_index(s5k6aa, &preset->mbus_fmt);
+	int ret;
+
+	ret = s5k6aa_write(client, REG_P_OUT_WIDTH(preset->index),
+			   preset->mbus_fmt.width);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_OUT_HEIGHT(preset->index),
+				   preset->mbus_fmt.height);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_FMT(preset->index),
+				   s5k6aa_formats[fmt_index].reg_p_fmt);
+	return ret;
+}
+
+static int s5k6aa_set_input_params(struct s5k6aa *s5k6aa)
+{
+	struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
+	struct v4l2_rect *r = &s5k6aa->ccd_rect;
+	int ret;
+
+	ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_WIDTH, r->width);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_HEIGHT, r->height);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_XOFFS, r->left);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_YOFFS, r->top);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_G_INPUTS_CHANGE_REQ, 1);
+	if (!ret)
+		s5k6aa->apply_crop = 0;
+
+	return ret;
+}
+
+/**
+ * s5k6aa_configure_video_bus - configure the video output interface
+ * @bus_type: video bus type: parallel or MIPI-CSI
+ * @nlanes: number of MIPI lanes to be used (MIPI-CSI only)
+ *
+ * Note: Only parallel bus operation has been tested.
+ */
+static int s5k6aa_configure_video_bus(struct s5k6aa *s5k6aa,
+				      enum v4l2_mbus_type bus_type, int nlanes)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+	u16 cfg = 0;
+	int ret;
+
+	/*
+	 * TODO: The sensor is supposed to support BT.601 and BT.656
+	 * but there is nothing indicating how to switch between both
+	 * in the datasheet. For now default BT.601 interface is assumed.
+	 */
+	if (bus_type == V4L2_MBUS_CSI2)
+		cfg = nlanes;
+	else if (bus_type != V4L2_MBUS_PARALLEL)
+		return -EINVAL;
+
+	ret = s5k6aa_write(client, REG_OIF_EN_MIPI_LANES, cfg);
+	if (ret)
+		return ret;
+	return s5k6aa_write(client, REG_OIF_CFG_CHG, 1);
+}
+
+/* This function should be called when switching to new user configuration set*/
+static int s5k6aa_new_config_sync(struct i2c_client *client, int timeout,
+				  int cid)
+{
+	unsigned long end = jiffies + msecs_to_jiffies(timeout);
+	u16 reg = 1;
+	int ret;
+
+	ret = s5k6aa_write(client, REG_G_ACTIVE_PREV_CFG, cid);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_G_NEW_CFG_SYNC, 1);
+	if (timeout == 0)
+		return ret;
+
+	while (ret >= 0 && time_is_after_jiffies(end)) {
+		ret = s5k6aa_read(client, REG_G_NEW_CFG_SYNC, &reg);
+		if (!reg)
+			return 0;
+		usleep_range(1000, 5000);
+	}
+	return ret ? ret : -ETIMEDOUT;
+}
+
+/**
+ * s5k6aa_set_prev_config - write user preview register set
+ *
+ * Configure output resolution and color fromat, pixel clock
+ * frequency range, device frame rate type and frame period range.
+ */
+static int s5k6aa_set_prev_config(struct s5k6aa *s5k6aa,
+				  struct s5k6aa_preset *preset)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+	int idx = preset->index;
+	u16 frame_rate_q;
+	int ret;
+
+	if (s5k6aa->fiv->reg_fr_time >= S5K6AA_MAX_HIGHRES_FR_TIME)
+		frame_rate_q = FR_RATE_Q_BEST_FRRATE;
+	else
+		frame_rate_q = FR_RATE_Q_BEST_QUALITY;
+
+	ret = s5k6aa_set_output_framefmt(s5k6aa, preset);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_MAX_OUT_RATE(idx),
+				   s5k6aa->pclk_fmax);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_MIN_OUT_RATE(idx),
+				   s5k6aa->pclk_fmin);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_CLK_INDEX(idx),
+				   preset->clk_id);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_FR_RATE_TYPE(idx),
+				   FR_RATE_DYNAMIC);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_FR_RATE_Q_TYPE(idx),
+				   frame_rate_q);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_MAX_FR_TIME(idx),
+				   s5k6aa->fiv->reg_fr_time + 33);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_MIN_FR_TIME(idx),
+				   s5k6aa->fiv->reg_fr_time - 33);
+	if (!ret)
+		ret = s5k6aa_new_config_sync(client, 250, idx);
+	if (!ret)
+		ret = s5k6aa_preview_config_status(client);
+	if (!ret)
+		s5k6aa->apply_cfg = 0;
+
+	v4l2_dbg(1, debug, client, "Frame interval: %d +/- 3.3ms. (%d)\n",
+		 s5k6aa->fiv->reg_fr_time, ret);
+	return ret;
+}
+
+/**
+ * s5k6aa_initialize_isp - basic ISP MCU initialization
+ *
+ * Configure AHB addresses for registers read/write; configure PLLs for
+ * required output pixel clock. The ISP power supply needs to be already
+ * enabled, with an optional H/W reset.
+ * Locking: called with s5k6aa.lock mutex held.
+ */
+static int s5k6aa_initialize_isp(struct v4l2_subdev *sd)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	int ret;
+
+	s5k6aa->apply_crop = 1;
+	s5k6aa->apply_cfg = 1;
+	msleep(100);
+
+	ret = s5k6aa_set_ahb_address(client);
+	if (ret)
+		return ret;
+	ret = s5k6aa_configure_video_bus(s5k6aa, s5k6aa->bus_type,
+					 s5k6aa->mipi_lanes);
+	if (ret)
+		return ret;
+	ret = s5k6aa_write_array(sd, s5k6aa_analog_config);
+	if (ret)
+		return ret;
+	msleep(20);
+
+	return s5k6aa_configure_pixel_clocks(s5k6aa);
+}
+
+static int s5k6aa_gpio_set_value(struct s5k6aa *priv, int id, u32 val)
+{
+	if (!gpio_is_valid(priv->gpio[id].gpio))
+		return 0;
+	gpio_set_value(priv->gpio[id].gpio, !!val);
+	return 1;
+}
+
+static int s5k6aa_gpio_assert(struct s5k6aa *priv, int id)
+{
+	return s5k6aa_gpio_set_value(priv, id, priv->gpio[id].level);
+}
+
+static int s5k6aa_gpio_deassert(struct s5k6aa *priv, int id)
+{
+	return s5k6aa_gpio_set_value(priv, id, !priv->gpio[id].level);
+}
+
+static int __s5k6aa_power_on(struct s5k6aa *s5k6aa)
+{
+	int ret;
+
+	ret = regulator_bulk_enable(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
+	if (ret)
+		return ret;
+	if (s5k6aa_gpio_deassert(s5k6aa, STBY))
+		usleep_range(150, 200);
+
+	if (s5k6aa->s_power)
+		ret = s5k6aa->s_power(1);
+	usleep_range(4000, 4000);
+
+	if (s5k6aa_gpio_deassert(s5k6aa, RST))
+		msleep(20);
+
+	return ret;
+}
+
+static int __s5k6aa_power_off(struct s5k6aa *s5k6aa)
+{
+	int ret;
+
+	if (s5k6aa_gpio_assert(s5k6aa, RST))
+		usleep_range(100, 150);
+
+	if (s5k6aa->s_power) {
+		ret = s5k6aa->s_power(0);
+		if (ret)
+			return ret;
+	}
+	if (s5k6aa_gpio_assert(s5k6aa, STBY))
+		usleep_range(50, 100);
+	s5k6aa->streaming = 0;
+
+	return regulator_bulk_disable(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
+}
+
+/*
+ * V4L2 subdev core and video operations
+ */
+static int s5k6aa_set_power(struct v4l2_subdev *sd, int on)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	int ret = 0;
+
+	mutex_lock(&s5k6aa->lock);
+
+	if (!on == s5k6aa->power) {
+		if (on) {
+			ret = __s5k6aa_power_on(s5k6aa);
+			if (!ret)
+				ret = s5k6aa_initialize_isp(sd);
+		} else {
+			ret = __s5k6aa_power_off(s5k6aa);
+		}
+
+		if (!ret)
+			s5k6aa->power += on ? 1 : -1;
+	}
+
+	mutex_unlock(&s5k6aa->lock);
+
+	if (!on || ret || s5k6aa->power != 1)
+		return ret;
+
+	return v4l2_ctrl_handler_setup(sd->ctrl_handler);
+}
+
+static int __s5k6aa_stream(struct s5k6aa *s5k6aa, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+	int ret = 0;
+
+	ret = s5k6aa_write(client, REG_G_ENABLE_PREV, enable);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_G_ENABLE_PREV_CHG, 1);
+	if (!ret)
+		s5k6aa->streaming = enable;
+
+	return ret;
+}
+
+static int s5k6aa_s_stream(struct v4l2_subdev *sd, int on)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	int ret = 0;
+
+	mutex_lock(&s5k6aa->lock);
+
+	if (s5k6aa->streaming == !on) {
+		if (!ret && s5k6aa->apply_cfg)
+			ret = s5k6aa_set_prev_config(s5k6aa, s5k6aa->preset);
+		if (s5k6aa->apply_crop)
+			ret = s5k6aa_set_input_params(s5k6aa);
+		if (!ret)
+			ret = __s5k6aa_stream(s5k6aa, !!on);
+	}
+	mutex_unlock(&s5k6aa->lock);
+
+	return ret;
+}
+
+static int s5k6aa_g_frame_interval(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_frame_interval *fi)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+
+	mutex_lock(&s5k6aa->lock);
+	fi->interval = s5k6aa->fiv->interval;
+	mutex_unlock(&s5k6aa->lock);
+
+	return 0;
+}
+
+static int __s5k6aa_set_frame_interval(struct s5k6aa *s5k6aa,
+				       struct v4l2_subdev_frame_interval *fi)
+{
+	struct v4l2_mbus_framefmt *mbus_fmt = &s5k6aa->preset->mbus_fmt;
+	const struct s5k6aa_interval *fiv = &s5k6aa_intervals[0];
+	unsigned int err, min_err = UINT_MAX;
+	unsigned int i, fr_time;
+
+	if (fi->interval.denominator == 0)
+		return -EINVAL;
+
+	fr_time = fi->interval.numerator * 10000 / fi->interval.denominator;
+
+	for (i = 0; i < ARRAY_SIZE(s5k6aa_intervals); i++) {
+		const struct s5k6aa_interval *iv = &s5k6aa_intervals[i];
+
+		if (mbus_fmt->width > iv->size.width ||
+		    mbus_fmt->height > iv->size.height)
+			continue;
+
+		err = abs(iv->reg_fr_time - fr_time);
+		if (err < min_err) {
+			fiv = iv;
+			min_err = err;
+		}
+	}
+	s5k6aa->fiv = fiv;
+
+	v4l2_dbg(1, debug, &s5k6aa->sd, "Changed frame interval to %d us\n",
+		 fiv->reg_fr_time * 100);
+	return 0;
+}
+
+static int s5k6aa_s_frame_interval(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_frame_interval *fi)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	int ret;
+
+	v4l2_dbg(1, debug, sd, "Setting %d/%d frame interval\n",
+		 fi->interval.numerator, fi->interval.denominator);
+
+	mutex_lock(&s5k6aa->lock);
+	ret = __s5k6aa_set_frame_interval(s5k6aa, fi);
+	s5k6aa->apply_cfg = 1;
+
+	mutex_unlock(&s5k6aa->lock);
+	return ret;
+}
+
+/*
+ * V4L2 subdev pad level and video operations
+ */
+static int s5k6aa_enum_frame_interval(struct v4l2_subdev *sd,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_frame_interval_enum *fie)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	const struct s5k6aa_interval *fi;
+	int ret = 0;
+
+	if (fie->index > ARRAY_SIZE(s5k6aa_intervals))
+		return -EINVAL;
+
+	v4l_bound_align_image(&fie->width, S5K6AA_WIN_WIDTH_MIN,
+			      S5K6AA_WIN_WIDTH_MAX, 1,
+			      &fie->height, S5K6AA_WIN_HEIGHT_MIN,
+			      S5K6AA_WIN_HEIGHT_MAX, 1, 0);
+
+	mutex_lock(&s5k6aa->lock);
+	fi = &s5k6aa_intervals[fie->index];
+	if (fie->width > fi->size.width || fie->height > fi->size.height)
+		ret = -EINVAL;
+	else
+		fie->interval = fi->interval;
+	mutex_unlock(&s5k6aa->lock);
+
+	return ret;
+}
+
+static int s5k6aa_enum_mbus_code(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_fh *fh,
+				 struct v4l2_subdev_mbus_code_enum *code)
+{
+	if (code->index >= ARRAY_SIZE(s5k6aa_formats))
+		return -EINVAL;
+
+	code->code = s5k6aa_formats[code->index].code;
+	return 0;
+}
+
+static int s5k6aa_enum_frame_size(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_frame_size_enum *fse)
+{
+	int i = ARRAY_SIZE(s5k6aa_formats);
+
+	if (fse->index > 0)
+		return -EINVAL;
+
+	while (--i)
+		if (fse->code == s5k6aa_formats[i].code)
+			break;
+
+	fse->code = s5k6aa_formats[i].code;
+	fse->min_width  = S5K6AA_WIN_WIDTH_MIN;
+	fse->max_width  = S5K6AA_WIN_WIDTH_MAX;
+	fse->max_height = S5K6AA_WIN_HEIGHT_MIN;
+	fse->min_height = S5K6AA_WIN_HEIGHT_MAX;
+
+	return 0;
+}
+
+static struct v4l2_rect *
+__s5k6aa_get_crop_rect(struct s5k6aa *s5k6aa, struct v4l2_subdev_fh *fh,
+		       enum v4l2_subdev_format_whence which)
+{
+	if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
+		return &s5k6aa->ccd_rect;
+	if (which == V4L2_SUBDEV_FORMAT_TRY)
+		return v4l2_subdev_get_try_crop(fh, 0);
+
+	return NULL;
+}
+
+static void s5k6aa_try_format(struct s5k6aa *s5k6aa,
+			      struct v4l2_mbus_framefmt *mf)
+{
+	unsigned int index;
+
+	v4l_bound_align_image(&mf->width, S5K6AA_WIN_WIDTH_MIN,
+			      S5K6AA_WIN_WIDTH_MAX, 1,
+			      &mf->height, S5K6AA_WIN_HEIGHT_MIN,
+			      S5K6AA_WIN_HEIGHT_MAX, 1, 0);
+
+	if (mf->colorspace != V4L2_COLORSPACE_JPEG &&
+	    mf->colorspace != V4L2_COLORSPACE_REC709)
+		mf->colorspace = V4L2_COLORSPACE_JPEG;
+
+	index = s5k6aa_get_pixfmt_index(s5k6aa, mf);
+
+	mf->colorspace	= s5k6aa_formats[index].colorspace;
+	mf->code	= s5k6aa_formats[index].code;
+	mf->field	= V4L2_FIELD_NONE;
+}
+
+static int s5k6aa_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			  struct v4l2_subdev_format *fmt)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	struct v4l2_mbus_framefmt *mf;
+
+	memset(fmt->reserved, 0, sizeof(fmt->reserved));
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+		mf = v4l2_subdev_get_try_format(fh, 0);
+		fmt->format = *mf;
+		return 0;
+	}
+
+	mutex_lock(&s5k6aa->lock);
+	fmt->format = s5k6aa->preset->mbus_fmt;
+	mutex_unlock(&s5k6aa->lock);
+
+	return 0;
+}
+
+static int s5k6aa_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			  struct v4l2_subdev_format *fmt)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	struct s5k6aa_preset *preset = s5k6aa->preset;
+	struct v4l2_mbus_framefmt *mf;
+	struct v4l2_rect *crop;
+	int ret = 0;
+
+	mutex_lock(&s5k6aa->lock);
+	s5k6aa_try_format(s5k6aa, &fmt->format);
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+		mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+		crop = v4l2_subdev_get_try_crop(fh, 0);
+	} else {
+		if (s5k6aa->streaming) {
+			ret = -EBUSY;
+		} else {
+			mf = &preset->mbus_fmt;
+			crop = &s5k6aa->ccd_rect;
+			s5k6aa->apply_cfg = 1;
+		}
+	}
+
+	if (ret == 0) {
+		struct v4l2_subdev_frame_interval fiv = {
+			.interval = {0, 1}
+		};
+
+		*mf = fmt->format;
+		/*
+		 * Make sure the crop window is valid, i.e. its size is
+		 * greater than the output window, as the ISP supports
+		 * only down-scaling.
+		 */
+		crop->width = clamp_t(unsigned int, crop->width, mf->width,
+				      S5K6AA_WIN_WIDTH_MAX);
+		crop->height = clamp_t(unsigned int, crop->height, mf->height,
+				       S5K6AA_WIN_HEIGHT_MAX);
+		crop->left = clamp_t(unsigned int, crop->left, 0,
+				     S5K6AA_WIN_WIDTH_MAX - crop->width);
+		crop->top  = clamp_t(unsigned int, crop->top, 0,
+				     S5K6AA_WIN_HEIGHT_MAX - crop->height);
+
+		/* Reset to minimum possible frame interval */
+		ret = __s5k6aa_set_frame_interval(s5k6aa, &fiv);
+	}
+	mutex_unlock(&s5k6aa->lock);
+
+	return ret;
+}
+
+static int s5k6aa_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_crop *crop)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	struct v4l2_rect *rect;
+
+	memset(crop->reserved, 0, sizeof(crop->reserved));
+	mutex_lock(&s5k6aa->lock);
+
+	rect = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->which);
+	if (rect)
+		crop->rect = *rect;
+
+	mutex_unlock(&s5k6aa->lock);
+
+	v4l2_dbg(1, debug, sd, "Current crop rectangle: (%d,%d)/%dx%d\n",
+		 rect->left, rect->top, rect->width, rect->height);
+
+	return 0;
+}
+
+static int s5k6aa_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_crop *crop)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	struct v4l2_mbus_framefmt *mf;
+	unsigned int max_x, max_y;
+	struct v4l2_rect *crop_r;
+
+	mutex_lock(&s5k6aa->lock);
+	crop_r = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->which);
+
+	if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		mf = &s5k6aa->preset->mbus_fmt;
+		s5k6aa->apply_crop = 1;
+	} else {
+		mf = v4l2_subdev_get_try_format(fh, 0);
+	}
+	v4l_bound_align_image(&crop->rect.width, mf->width,
+			      S5K6AA_WIN_WIDTH_MAX, 1,
+			      &crop->rect.height, mf->height,
+			      S5K6AA_WIN_HEIGHT_MAX, 1, 0);
+
+	max_x = (S5K6AA_WIN_WIDTH_MAX - crop->rect.width) & ~1;
+	max_y = (S5K6AA_WIN_HEIGHT_MAX - crop->rect.height) & ~1;
+
+	crop->rect.left = clamp_t(unsigned int, crop->rect.left, 0, max_x);
+	crop->rect.top  = clamp_t(unsigned int, crop->rect.top, 0, max_y);
+
+	*crop_r = crop->rect;
+
+	mutex_unlock(&s5k6aa->lock);
+
+	v4l2_dbg(1, debug, sd, "Set crop rectangle: (%d,%d)/%dx%d\n",
+		 crop_r->left, crop_r->top, crop_r->width, crop_r->height);
+
+	return 0;
+}
+
+static const struct v4l2_subdev_pad_ops s5k6aa_pad_ops = {
+	.enum_mbus_code		= s5k6aa_enum_mbus_code,
+	.enum_frame_size	= s5k6aa_enum_frame_size,
+	.enum_frame_interval	= s5k6aa_enum_frame_interval,
+	.get_fmt		= s5k6aa_get_fmt,
+	.set_fmt		= s5k6aa_set_fmt,
+	.get_crop		= s5k6aa_get_crop,
+	.set_crop		= s5k6aa_set_crop,
+};
+
+static const struct v4l2_subdev_video_ops s5k6aa_video_ops = {
+	.g_frame_interval	= s5k6aa_g_frame_interval,
+	.s_frame_interval	= s5k6aa_s_frame_interval,
+	.s_stream		= s5k6aa_s_stream,
+};
+
+/*
+ * V4L2 subdev controls
+ */
+
+static int s5k6aa_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	int idx, err = 0;
+
+	v4l2_dbg(1, debug, sd, "ctrl: 0x%x, value: %d\n", ctrl->id, ctrl->val);
+
+	mutex_lock(&s5k6aa->lock);
+	/*
+	 * If the device is not powered up by the host driver do
+	 * not apply any controls to H/W at this time. Instead
+	 * the controls will be restored right after power-up.
+	 */
+	if (s5k6aa->power == 0)
+		goto unlock;
+	idx = s5k6aa->preset->index;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		err = s5k6aa_set_awb(s5k6aa, ctrl->val);
+		break;
+
+	case V4L2_CID_BRIGHTNESS:
+		err = s5k6aa_write(client, REG_USER_BRIGHTNESS, ctrl->val);
+		break;
+
+	case V4L2_CID_COLORFX:
+		err = s5k6aa_set_colorfx(s5k6aa, ctrl->val);
+		break;
+
+	case V4L2_CID_CONTRAST:
+		err = s5k6aa_write(client, REG_USER_CONTRAST, ctrl->val);
+		break;
+
+	case V4L2_CID_EXPOSURE_AUTO:
+		err = s5k6aa_set_auto_exposure(s5k6aa, ctrl->val);
+		break;
+
+	case V4L2_CID_HFLIP:
+		err = s5k6aa_set_mirror(s5k6aa, ctrl->val);
+		if (err)
+			break;
+		err = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
+		break;
+
+	case V4L2_CID_POWER_LINE_FREQUENCY:
+		err = s5k6aa_set_anti_flicker(s5k6aa, ctrl->val);
+		break;
+
+	case V4L2_CID_SATURATION:
+		err = s5k6aa_write(client, REG_USER_SATURATION, ctrl->val);
+		break;
+
+	case V4L2_CID_SHARPNESS:
+		err = s5k6aa_write(client, REG_USER_SHARPBLUR, ctrl->val);
+		break;
+
+	case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
+		err = s5k6aa_write(client, REG_P_COLORTEMP(idx), ctrl->val);
+		if (err)
+			break;
+		err = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
+		break;
+	}
+unlock:
+	mutex_unlock(&s5k6aa->lock);
+	return err;
+}
+
+static const struct v4l2_ctrl_ops s5k6aa_ctrl_ops = {
+	.s_ctrl	= s5k6aa_s_ctrl,
+};
+
+static int s5k6aa_log_status(struct v4l2_subdev *sd)
+{
+	v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name);
+	return 0;
+}
+
+#define V4L2_CID_RED_GAIN	(V4L2_CTRL_CLASS_CAMERA | 0x1001)
+#define V4L2_CID_GREEN_GAIN	(V4L2_CTRL_CLASS_CAMERA | 0x1002)
+#define V4L2_CID_BLUE_GAIN	(V4L2_CTRL_CLASS_CAMERA | 0x1003)
+
+static const struct v4l2_ctrl_config s5k6aa_ctrls[] = {
+	{
+		.ops	= &s5k6aa_ctrl_ops,
+		.id	= V4L2_CID_RED_GAIN,
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.name	= "Gain, Red",
+		.min	= 0,
+		.max	= 256,
+		.def	= 127,
+		.step	= 1,
+	}, {
+		.ops	= &s5k6aa_ctrl_ops,
+		.id	= V4L2_CID_GREEN_GAIN,
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.name	= "Gain, Green",
+		.min	= 0,
+		.max	= 256,
+		.def	= 127,
+		.step	= 1,
+	}, {
+		.ops	= &s5k6aa_ctrl_ops,
+		.id	= V4L2_CID_BLUE_GAIN,
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.name	= "Gain, Blue",
+		.min	= 0,
+		.max	= 256,
+		.def	= 127,
+		.step	= 1,
+	},
+};
+
+static int s5k6aa_initialize_ctrls(struct s5k6aa *s5k6aa)
+{
+	const struct v4l2_ctrl_ops *ops = &s5k6aa_ctrl_ops;
+	struct s5k6aa_ctrls *ctrls = &s5k6aa->ctrls;
+	struct v4l2_ctrl_handler *hdl = &ctrls->handler;
+
+	int ret = v4l2_ctrl_handler_init(hdl, 16);
+	if (ret)
+		return ret;
+	/* Auto white balance cluster */
+	ctrls->awb = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_WHITE_BALANCE,
+				       0, 1, 1, 1);
+	ctrls->gain_red = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[0], NULL);
+	ctrls->gain_green = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[1], NULL);
+	ctrls->gain_blue = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[2], NULL);
+	v4l2_ctrl_auto_cluster(4, &ctrls->awb, 0, false);
+
+	ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
+	ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_cluster(2, &ctrls->hflip);
+
+	ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops,
+				V4L2_CID_EXPOSURE_AUTO,
+				V4L2_EXPOSURE_MANUAL, 0, V4L2_EXPOSURE_AUTO);
+	/* Exposure time: x 1 us */
+	ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE,
+					    0, 6000000U, 1, 100000U);
+	/* Total gain: 256 <=> 1x */
+	ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
+					0, 256, 1, 256);
+	v4l2_ctrl_auto_cluster(3, &ctrls->auto_exp, 0, false);
+
+	v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_POWER_LINE_FREQUENCY,
+			       V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
+			       V4L2_CID_POWER_LINE_FREQUENCY_AUTO);
+
+	v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_COLORFX,
+			       V4L2_COLORFX_SKY_BLUE, ~0x6f, V4L2_COLORFX_NONE);
+
+	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_WHITE_BALANCE_TEMPERATURE,
+			  0, 256, 1, 0);
+
+	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION, -127, 127, 1, 0);
+	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -127, 127, 1, 0);
+	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -127, 127, 1, 0);
+	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SHARPNESS, -127, 127, 1, 0);
+
+	if (hdl->error) {
+		ret = hdl->error;
+		v4l2_ctrl_handler_free(hdl);
+		return ret;
+	}
+
+	s5k6aa->sd.ctrl_handler = hdl;
+	return 0;
+}
+
+/*
+ * V4L2 subdev internal operations
+ */
+static int s5k6aa_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
+	struct v4l2_rect *crop = v4l2_subdev_get_try_crop(fh, 0);
+
+	format->colorspace = s5k6aa_formats[0].colorspace;
+	format->code = s5k6aa_formats[0].code;
+	format->width = S5K6AA_OUT_WIDTH_DEF;
+	format->height = S5K6AA_OUT_HEIGHT_DEF;
+	format->field = V4L2_FIELD_NONE;
+
+	crop->width = S5K6AA_WIN_WIDTH_MAX;
+	crop->height = S5K6AA_WIN_HEIGHT_MAX;
+	crop->left = 0;
+	crop->top = 0;
+
+	return 0;
+}
+
+int s5k6aa_check_fw_revision(struct s5k6aa *s5k6aa)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+	u16 api_ver = 0, fw_rev = 0;
+
+	int ret = s5k6aa_set_ahb_address(client);
+
+	if (!ret)
+		ret = s5k6aa_read(client, REG_FW_APIVER, &api_ver);
+	if (!ret)
+		ret = s5k6aa_read(client, REG_FW_REVISION, &fw_rev);
+	if (ret) {
+		v4l2_err(&s5k6aa->sd, "FW revision check failed!\n");
+		return ret;
+	}
+
+	v4l2_info(&s5k6aa->sd, "FW API ver.: 0x%X, FW rev.: 0x%X\n",
+		  api_ver, fw_rev);
+
+	return api_ver == S5K6AAFX_FW_APIVER ? 0 : -ENODEV;
+}
+
+static int s5k6aa_registered(struct v4l2_subdev *sd)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	int ret;
+
+	mutex_lock(&s5k6aa->lock);
+	ret = __s5k6aa_power_on(s5k6aa);
+	if (!ret) {
+		msleep(100);
+		ret = s5k6aa_check_fw_revision(s5k6aa);
+		__s5k6aa_power_off(s5k6aa);
+	}
+	mutex_unlock(&s5k6aa->lock);
+
+	return ret;
+}
+
+static const struct v4l2_subdev_internal_ops s5k6aa_subdev_internal_ops = {
+	.registered = s5k6aa_registered,
+	.open = s5k6aa_open,
+};
+
+static const struct v4l2_subdev_core_ops s5k6aa_core_ops = {
+	.s_power = s5k6aa_set_power,
+	.log_status = s5k6aa_log_status,
+};
+
+static const struct v4l2_subdev_ops s5k6aa_subdev_ops = {
+	.core = &s5k6aa_core_ops,
+	.pad = &s5k6aa_pad_ops,
+	.video = &s5k6aa_video_ops,
+};
+
+/*
+ * GPIO setup
+ */
+static int s5k6aa_configure_gpio(int nr, int val, const char *name)
+{
+	unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+	int ret;
+
+	if (!gpio_is_valid(nr))
+		return 0;
+	ret = gpio_request_one(nr, flags, name);
+	if (!ret)
+		gpio_export(nr, 0);
+	return ret;
+}
+
+static void s5k6aa_free_gpios(struct s5k6aa *s5k6aa)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(s5k6aa->gpio); i++) {
+		if (!gpio_is_valid(s5k6aa->gpio[i].gpio))
+			continue;
+		gpio_free(s5k6aa->gpio[i].gpio);
+		s5k6aa->gpio[i].gpio = -EINVAL;
+	}
+}
+
+static int s5k6aa_configure_gpios(struct s5k6aa *s5k6aa,
+				  const struct s5k6aa_platform_data *pdata)
+{
+	const struct s5k6aa_gpio *gpio = &pdata->gpio_stby;
+	int ret;
+
+	s5k6aa->gpio[STBY].gpio = -EINVAL;
+	s5k6aa->gpio[RST].gpio  = -EINVAL;
+
+	ret = s5k6aa_configure_gpio(gpio->gpio, gpio->level, "S5K6AA_STBY");
+	if (ret) {
+		s5k6aa_free_gpios(s5k6aa);
+		return ret;
+	}
+	s5k6aa->gpio[STBY] = *gpio;
+	if (gpio_is_valid(gpio->gpio))
+		gpio_set_value(gpio->gpio, 0);
+
+	gpio = &pdata->gpio_reset;
+	ret = s5k6aa_configure_gpio(gpio->gpio, gpio->level, "S5K6AA_RST");
+	if (ret) {
+		s5k6aa_free_gpios(s5k6aa);
+		return ret;
+	}
+	s5k6aa->gpio[RST] = *gpio;
+	if (gpio_is_valid(gpio->gpio))
+		gpio_set_value(gpio->gpio, 0);
+
+	return 0;
+}
+
+static int s5k6aa_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	const struct s5k6aa_platform_data *pdata = client->dev.platform_data;
+	struct v4l2_subdev *sd;
+	struct s5k6aa *s5k6aa;
+	int i, ret;
+
+	if (pdata == NULL) {
+		dev_err(&client->dev, "Platform data not specified\n");
+		return -EINVAL;
+	}
+
+	if (pdata->mclk_frequency == 0) {
+		dev_err(&client->dev, "MCLK frequency not specified\n");
+		return -EINVAL;
+	}
+
+	s5k6aa = kzalloc(sizeof(*s5k6aa), GFP_KERNEL);
+	if (!s5k6aa)
+		return -ENOMEM;
+
+	mutex_init(&s5k6aa->lock);
+
+	s5k6aa->mclk_frequency = pdata->mclk_frequency;
+	s5k6aa->bus_type = pdata->bus_type;
+	s5k6aa->mipi_lanes = pdata->nlanes;
+	s5k6aa->s_power	= pdata->set_power;
+	s5k6aa->inv_hflip = pdata->horiz_flip;
+	s5k6aa->inv_vflip = pdata->vert_flip;
+
+	sd = &s5k6aa->sd;
+	strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name));
+	v4l2_i2c_subdev_init(sd, client, &s5k6aa_subdev_ops);
+
+	sd->internal_ops = &s5k6aa_subdev_internal_ops;
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	s5k6aa->pad.flags = MEDIA_PAD_FL_SOURCE;
+	sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
+	ret = media_entity_init(&sd->entity, 1, &s5k6aa->pad, 0);
+	if (ret)
+		goto out_err1;
+
+	ret = s5k6aa_configure_gpios(s5k6aa, pdata);
+	if (ret)
+		goto out_err2;
+
+	for (i = 0; i < S5K6AA_NUM_SUPPLIES; i++)
+		s5k6aa->supplies[i].supply = s5k6aa_supply_names[i];
+
+	ret = regulator_bulk_get(&client->dev, S5K6AA_NUM_SUPPLIES,
+				 s5k6aa->supplies);
+	if (ret) {
+		dev_err(&client->dev, "Failed to get regulators\n");
+		goto out_err3;
+	}
+
+	ret = s5k6aa_initialize_ctrls(s5k6aa);
+	if (ret)
+		goto out_err4;
+
+	s5k6aa_presets_data_init(s5k6aa);
+
+	s5k6aa->ccd_rect.width = S5K6AA_WIN_WIDTH_MAX;
+	s5k6aa->ccd_rect.height	= S5K6AA_WIN_HEIGHT_MAX;
+	s5k6aa->ccd_rect.left = 0;
+	s5k6aa->ccd_rect.top = 0;
+
+	return 0;
+
+out_err4:
+	regulator_bulk_free(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
+out_err3:
+	s5k6aa_free_gpios(s5k6aa);
+out_err2:
+	media_entity_cleanup(&s5k6aa->sd.entity);
+out_err1:
+	kfree(s5k6aa);
+	return ret;
+}
+
+static int s5k6aa_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(sd->ctrl_handler);
+	media_entity_cleanup(&sd->entity);
+	regulator_bulk_free(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
+	s5k6aa_free_gpios(s5k6aa);
+	kfree(s5k6aa);
+
+	return 0;
+}
+
+static const struct i2c_device_id s5k6aa_id[] = {
+	{ DRIVER_NAME, 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, s5k6aa_id);
+
+
+static struct i2c_driver s5k6aa_i2c_driver = {
+	.driver = {
+		.name = DRIVER_NAME
+	},
+	.probe		= s5k6aa_probe,
+	.remove		= s5k6aa_remove,
+	.id_table	= s5k6aa_id,
+};
+
+static int __init s5k6aa_init(void)
+{
+	return i2c_add_driver(&s5k6aa_i2c_driver);
+}
+
+static void __exit s5k6aa_exit(void)
+{
+	i2c_del_driver(&s5k6aa_i2c_driver);
+}
+
+module_init(s5k6aa_init);
+module_exit(s5k6aa_exit);
+
+MODULE_DESCRIPTION("Samsung S5K6AA(FX) SXGA camera driver");
+MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/fimc-capture.c linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/fimc-capture.c
--- linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/fimc-capture.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/fimc-capture.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,11 +16,9 @@
 #include <linux/bug.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
-#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/list.h>
 #include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/i2c.h>
 
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
@@ -29,135 +27,92 @@
 #include <media/videobuf2-core.h>
 #include <media/videobuf2-dma-contig.h>
 
+#include "fimc-mdevice.h"
 #include "fimc-core.h"
 
-static struct v4l2_subdev *fimc_subdev_register(struct fimc_dev *fimc,
-					    struct s5p_fimc_isp_info *isp_info)
+static int fimc_init_capture(struct fimc_dev *fimc)
 {
-	struct i2c_adapter *i2c_adap;
-	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
-	struct v4l2_subdev *sd = NULL;
-
-	i2c_adap = i2c_get_adapter(isp_info->i2c_bus_num);
-	if (!i2c_adap)
-		return ERR_PTR(-ENOMEM);
-
-	sd = v4l2_i2c_new_subdev_board(&vid_cap->v4l2_dev, i2c_adap,
-				       isp_info->board_info, NULL);
-	if (!sd) {
-		v4l2_err(&vid_cap->v4l2_dev, "failed to acquire subdev\n");
-		return NULL;
-	}
+	struct fimc_ctx *ctx = fimc->vid_cap.ctx;
+	struct fimc_sensor_info *sensor;
+	unsigned long flags;
+	int ret = 0;
 
-	v4l2_info(&vid_cap->v4l2_dev, "subdevice %s registered successfuly\n",
-		isp_info->board_info->type);
+	if (fimc->pipeline.sensor == NULL || ctx == NULL)
+		return -ENXIO;
+	if (ctx->s_frame.fmt == NULL)
+		return -EINVAL;
 
-	return sd;
-}
+	sensor = v4l2_get_subdev_hostdata(fimc->pipeline.sensor);
 
-static void fimc_subdev_unregister(struct fimc_dev *fimc)
-{
-	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
-	struct i2c_client *client;
+	spin_lock_irqsave(&fimc->slock, flags);
+	fimc_prepare_dma_offset(ctx, &ctx->d_frame);
+	fimc_set_yuv_order(ctx);
 
-	if (vid_cap->input_index < 0)
-		return;	/* Subdevice already released or not registered. */
+	fimc_hw_set_camera_polarity(fimc, sensor->pdata);
+	fimc_hw_set_camera_type(fimc, sensor->pdata);
+	fimc_hw_set_camera_source(fimc, sensor->pdata);
+	fimc_hw_set_camera_offset(fimc, &ctx->s_frame);
 
-	if (vid_cap->sd) {
-		v4l2_device_unregister_subdev(vid_cap->sd);
-		client = v4l2_get_subdevdata(vid_cap->sd);
-		i2c_unregister_device(client);
-		i2c_put_adapter(client->adapter);
-		vid_cap->sd = NULL;
+	ret = fimc_set_scaler_info(ctx);
+	if (!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, false);
+		fimc_hw_set_output_path(ctx);
+		fimc_hw_set_out_dma(ctx);
+		clear_bit(ST_CAPT_APPLY_CFG, &fimc->state);
 	}
-
-	vid_cap->input_index = -1;
+	spin_unlock_irqrestore(&fimc->slock, flags);
+	return ret;
 }
 
-/**
- * fimc_subdev_attach - attach v4l2_subdev to camera host interface
- *
- * @fimc: FIMC device information
- * @index: index to the array of available subdevices,
- *	   -1 for full array search or non negative value
- *	   to select specific subdevice
- */
-static int fimc_subdev_attach(struct fimc_dev *fimc, int index)
+static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend)
 {
-	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
-	struct s5p_platform_fimc *pdata = fimc->pdata;
-	struct s5p_fimc_isp_info *isp_info;
-	struct v4l2_subdev *sd;
-	int i;
-
-	for (i = 0; i < pdata->num_clients; ++i) {
-		isp_info = &pdata->isp_info[i];
+	struct fimc_vid_cap *cap = &fimc->vid_cap;
+	struct fimc_vid_buffer *buf;
+	unsigned long flags;
+	bool streaming;
 
-		if (index >= 0 && i != index)
-			continue;
+	spin_lock_irqsave(&fimc->slock, flags);
+	streaming = fimc->state & (1 << ST_CAPT_ISP_STREAM);
 
-		sd = fimc_subdev_register(fimc, isp_info);
-		if (!IS_ERR_OR_NULL(sd)) {
-			vid_cap->sd = sd;
-			vid_cap->input_index = i;
+	fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_SHUT |
+			 1 << ST_CAPT_STREAM | 1 << ST_CAPT_ISP_STREAM);
+	if (!suspend)
+		fimc->state &= ~(1 << ST_CAPT_PEND | 1 << ST_CAPT_SUSPENDED);
 
-			return 0;
-		}
+	/* Release unused buffers */
+	while (!suspend && !list_empty(&cap->pending_buf_q)) {
+		buf = fimc_pending_queue_pop(cap);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
 	}
+	/* If suspending put unused buffers onto pending queue */
+	while (!list_empty(&cap->active_buf_q)) {
+		buf = fimc_active_queue_pop(cap);
+		if (suspend)
+			fimc_pending_queue_add(cap, buf);
+		else
+			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+	}
+	set_bit(ST_CAPT_SUSPENDED, &fimc->state);
 
-	vid_cap->input_index = -1;
-	vid_cap->sd = NULL;
-	v4l2_err(&vid_cap->v4l2_dev, "fimc%d: sensor attach failed\n",
-		 fimc->id);
-	return -ENODEV;
-}
-
-static int fimc_isp_subdev_init(struct fimc_dev *fimc, unsigned int index)
-{
-	struct s5p_fimc_isp_info *isp_info;
-	struct s5p_platform_fimc *pdata = fimc->pdata;
-	int ret;
-
-	if (index >= pdata->num_clients)
-		return -EINVAL;
-
-	isp_info = &pdata->isp_info[index];
-
-	if (isp_info->clk_frequency)
-		clk_set_rate(fimc->clock[CLK_CAM], isp_info->clk_frequency);
-
-	ret = clk_enable(fimc->clock[CLK_CAM]);
-	if (ret)
-		return ret;
-
-	ret = fimc_subdev_attach(fimc, index);
-	if (ret)
-		return ret;
-
-	ret = fimc_hw_set_camera_polarity(fimc, isp_info);
-	if (ret)
-		return ret;
-
-	ret = v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 1);
-	if (!ret)
-		return ret;
-
-	/* enabling power failed so unregister subdev */
-	fimc_subdev_unregister(fimc);
+	fimc_hw_reset(fimc);
+	cap->buf_index = 0;
 
-	v4l2_err(&fimc->vid_cap.v4l2_dev, "ISP initialization failed: %d\n",
-		 ret);
+	spin_unlock_irqrestore(&fimc->slock, flags);
 
-	return ret;
+	if (streaming)
+		return fimc_pipeline_s_stream(fimc, 0);
+	else
+		return 0;
 }
 
-static int fimc_stop_capture(struct fimc_dev *fimc)
+static int fimc_stop_capture(struct fimc_dev *fimc, bool suspend)
 {
 	unsigned long flags;
-	struct fimc_vid_cap *cap;
-	struct fimc_vid_buffer *buf;
-
-	cap = &fimc->vid_cap;
 
 	if (!fimc_capture_active(fimc))
 		return 0;
@@ -169,81 +124,72 @@
 
 	wait_event_timeout(fimc->irq_queue,
 			   !test_bit(ST_CAPT_SHUT, &fimc->state),
-			   FIMC_SHUTDOWN_TIMEOUT);
-
-	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_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);
+			   (2*HZ/10)); /* 200 ms */
 
-	dbg("state: 0x%lx", fimc->state);
-	return 0;
+	return fimc_capture_state_cleanup(fimc, suspend);
 }
 
-static int start_streaming(struct vb2_queue *q)
+/**
+ * fimc_capture_config_update - apply the camera interface configuration
+ *
+ * To be called from within the interrupt handler with fimc.slock
+ * spinlock held. It updates the camera pixel crop, rotation and
+ * image flip in H/W.
+ */
+int fimc_capture_config_update(struct fimc_ctx *ctx)
 {
-	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;
+	if (!test_bit(ST_CAPT_APPLY_CFG, &fimc->state))
+		return 0;
 
-	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);
+	spin_lock(&ctx->slock);
 	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);
+	ret = fimc_set_scaler_info(ctx);
+	if (ret == 0) {
 		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_prepare_dma_offset(ctx, &ctx->d_frame);
+		fimc_hw_set_out_dma(ctx);
+		clear_bit(ST_CAPT_APPLY_CFG, &fimc->state);
 	}
+	spin_unlock(&ctx->slock);
+	return ret;
+}
 
-	fimc_hw_set_output_path(ctx);
-	fimc_hw_set_out_dma(ctx);
+static int start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct fimc_ctx *ctx = q->drv_priv;
+	struct fimc_dev *fimc = ctx->fimc_dev;
+	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
+	int min_bufs;
+	int ret;
 
-	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;
+	vid_cap->frame_count = 0;
+
+	ret = fimc_init_capture(fimc);
+	if (ret)
+		goto error;
 
 	set_bit(ST_CAPT_PEND, &fimc->state);
 
+	min_bufs = fimc->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);
+
+		if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
+			fimc_pipeline_s_stream(fimc, 1);
+	}
+
 	return 0;
+error:
+	fimc_capture_state_cleanup(fimc, false);
+	return ret;
 }
 
 static int stop_streaming(struct vb2_queue *q)
@@ -254,7 +200,46 @@
 	if (!fimc_capture_active(fimc))
 		return -EINVAL;
 
-	return fimc_stop_capture(fimc);
+	return fimc_stop_capture(fimc, false);
+}
+
+int fimc_capture_suspend(struct fimc_dev *fimc)
+{
+	bool suspend = fimc_capture_busy(fimc);
+
+	int ret = fimc_stop_capture(fimc, suspend);
+	if (ret)
+		return ret;
+	return fimc_pipeline_shutdown(fimc);
+}
+
+static void buffer_queue(struct vb2_buffer *vb);
+
+int fimc_capture_resume(struct fimc_dev *fimc)
+{
+	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
+	struct fimc_vid_buffer *buf;
+	int i;
+
+	if (!test_and_clear_bit(ST_CAPT_SUSPENDED, &fimc->state))
+		return 0;
+
+	INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
+	vid_cap->buf_index = 0;
+	fimc_pipeline_initialize(fimc, &fimc->vid_cap.vfd->entity,
+				 false);
+	fimc_init_capture(fimc);
+
+	clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
+
+	for (i = 0; i < vid_cap->reqbufs_count; i++) {
+		if (list_empty(&vid_cap->pending_buf_q))
+			break;
+		buf = fimc_pending_queue_pop(vid_cap);
+		buffer_queue(&buf->vb);
+	}
+	return 0;
+
 }
 
 static unsigned int get_plane_size(struct fimc_frame *fr, unsigned int plane)
@@ -264,9 +249,9 @@
 	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[])
+static int queue_setup(struct vb2_queue *vq,  const struct v4l2_format *pfmt,
+		       unsigned int *num_buffers, unsigned int *num_planes,
+		       unsigned int sizes[], void *allocators[])
 {
 	struct fimc_ctx *ctx = vq->drv_priv;
 	struct fimc_fmt *fmt = ctx->d_frame.fmt;
@@ -289,21 +274,20 @@
 {
 	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)
+	if (ctx->d_frame.fmt == NULL)
 		return -EINVAL;
 
 	for (i = 0; i < ctx->d_frame.fmt->memplanes; i++) {
-		unsigned long size = get_plane_size(&ctx->d_frame, i);
+		unsigned long size = ctx->d_frame.payload[i];
 
 		if (vb2_plane_size(vb, i) < size) {
-			v4l2_err(v4l2_dev, "User buffer too small (%ld < %ld)\n",
+			v4l2_err(ctx->fimc_dev->vid_cap.vfd,
+				 "User buffer too small (%ld < %ld)\n",
 				 vb2_plane_size(vb, i), size);
 			return -EINVAL;
 		}
-
 		vb2_set_plane_payload(vb, i, size);
 	}
 
@@ -312,10 +296,10 @@
 
 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_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct fimc_dev *fimc = ctx->fimc_dev;
 	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
 	unsigned long flags;
 	int min_bufs;
@@ -323,15 +307,16 @@
 	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) {
+	if (!test_bit(ST_CAPT_SUSPENDED, &fimc->state) &&
+	    !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);
+		fimc_active_queue_add(vid_cap, buf);
 
 		if (++vid_cap->buf_index >= FIMC_MAX_OUT_BUFS)
 			vid_cap->buf_index = 0;
@@ -341,10 +326,17 @@
 
 	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))
+
+	if (vb2_is_streaming(&vid_cap->vbq) &&
+	    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);
 
+		if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
+			fimc_pipeline_s_stream(fimc, 1);
+		return;
+	}
 	spin_unlock_irqrestore(&fimc->slock, flags);
 }
 
@@ -370,10 +362,40 @@
 	.stop_streaming		= stop_streaming,
 };
 
+/**
+ * fimc_capture_ctrls_create - initialize the control handler
+ * Initialize the capture video node control handler and fill it
+ * with the FIMC controls. Inherit any sensor's controls if the
+ * 'user_subdev_api' flag is false (default behaviour).
+ * This function need to be called with the graph mutex held.
+ */
+int fimc_capture_ctrls_create(struct fimc_dev *fimc)
+{
+	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
+	int ret;
+
+	if (WARN_ON(vid_cap->ctx == NULL))
+		return -ENXIO;
+	if (vid_cap->ctx->ctrls_rdy)
+		return 0;
+
+	ret = fimc_ctrls_create(vid_cap->ctx);
+	if (ret || vid_cap->user_subdev_api)
+		return ret;
+
+	return v4l2_ctrl_add_handler(&vid_cap->ctx->ctrl_handler,
+				    fimc->pipeline.sensor->ctrl_handler);
+}
+
+static int fimc_capture_set_default_format(struct fimc_dev *fimc);
+
 static int fimc_capture_open(struct file *file)
 {
 	struct fimc_dev *fimc = video_drvdata(file);
-	int ret = 0;
+	int ret = v4l2_fh_open(file);
+
+	if (ret)
+		return ret;
 
 	dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
 
@@ -381,17 +403,27 @@
 	if (fimc_m2m_active(fimc))
 		return -EBUSY;
 
+	set_bit(ST_CAPT_BUSY, &fimc->state);
+	pm_runtime_get_sync(&fimc->pdev->dev);
+
 	if (++fimc->vid_cap.refcnt == 1) {
-		ret = fimc_isp_subdev_init(fimc, 0);
-		if (ret) {
+		ret = fimc_pipeline_initialize(fimc,
+			       &fimc->vid_cap.vfd->entity, true);
+		if (ret < 0) {
+			dev_err(&fimc->pdev->dev,
+				"Video pipeline initialization failed\n");
+			pm_runtime_put_sync(&fimc->pdev->dev);
 			fimc->vid_cap.refcnt--;
-			return -EIO;
+			v4l2_fh_release(file);
+			clear_bit(ST_CAPT_BUSY, &fimc->state);
+			return ret;
 		}
-	}
-
-	file->private_data = fimc->vid_cap.ctx;
+		ret = fimc_capture_ctrls_create(fimc);
 
-	return 0;
+		if (!ret && !fimc->vid_cap.user_subdev_api)
+			ret = fimc_capture_set_default_format(fimc);
+	}
+	return ret;
 }
 
 static int fimc_capture_close(struct file *file)
@@ -401,37 +433,36 @@
 	dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
 
 	if (--fimc->vid_cap.refcnt == 0) {
-		fimc_stop_capture(fimc);
-		vb2_queue_release(&fimc->vid_cap.vbq);
+		clear_bit(ST_CAPT_BUSY, &fimc->state);
+		fimc_stop_capture(fimc, false);
+		fimc_pipeline_shutdown(fimc);
+		clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
+	}
 
-		v4l2_err(&fimc->vid_cap.v4l2_dev, "releasing ISP\n");
+	pm_runtime_put(&fimc->pdev->dev);
 
-		v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0);
-		clk_disable(fimc->clock[CLK_CAM]);
-		fimc_subdev_unregister(fimc);
+	if (fimc->vid_cap.refcnt == 0) {
+		vb2_queue_release(&fimc->vid_cap.vbq);
+		fimc_ctrls_delete(fimc->vid_cap.ctx);
 	}
-
-	return 0;
+	return v4l2_fh_release(file);
 }
 
 static unsigned int fimc_capture_poll(struct file *file,
 				      struct poll_table_struct *wait)
 {
-	struct fimc_ctx *ctx = file->private_data;
-	struct fimc_dev *fimc = ctx->fimc_dev;
+	struct fimc_dev *fimc = video_drvdata(file);
 
 	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_dev *fimc = video_drvdata(file);
 
 	return vb2_mmap(&fimc->vid_cap.vbq, vma);
 }
 
-/* video device file operations */
 static const struct v4l2_file_operations fimc_capture_fops = {
 	.owner		= THIS_MODULE,
 	.open		= fimc_capture_open,
@@ -441,263 +472,553 @@
 	.mmap		= fimc_capture_mmap,
 };
 
+/*
+ * Format and crop negotiation helpers
+ */
+
+static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx,
+						u32 *width, u32 *height,
+						u32 *code, u32 *fourcc, int pad)
+{
+	bool rotation = ctx->rotation == 90 || ctx->rotation == 270;
+	struct fimc_dev *fimc = ctx->fimc_dev;
+	struct samsung_fimc_variant *var = fimc->variant;
+	struct fimc_pix_limit *pl = var->pix_limit;
+	struct fimc_frame *dst = &ctx->d_frame;
+	u32 depth, min_w, max_w, min_h, align_h = 3;
+	u32 mask = FMT_FLAGS_CAM;
+	struct fimc_fmt *ffmt;
+
+	/* Color conversion from/to JPEG is not supported */
+	if (code && ctx->s_frame.fmt && pad == FIMC_SD_PAD_SOURCE &&
+	    fimc_fmt_is_jpeg(ctx->s_frame.fmt->color))
+		*code = V4L2_MBUS_FMT_JPEG_1X8;
+
+	if (fourcc && *fourcc != V4L2_PIX_FMT_JPEG && pad != FIMC_SD_PAD_SINK)
+		mask |= FMT_FLAGS_M2M;
+
+	ffmt = fimc_find_format(fourcc, code, mask, 0);
+	if (WARN_ON(!ffmt))
+		return NULL;
+	if (code)
+		*code = ffmt->mbus_code;
+	if (fourcc)
+		*fourcc = ffmt->fourcc;
+
+	if (pad == FIMC_SD_PAD_SINK) {
+		max_w = fimc_fmt_is_jpeg(ffmt->color) ?
+			pl->scaler_dis_w : pl->scaler_en_w;
+		/* Apply the camera input interface pixel constraints */
+		v4l_bound_align_image(width, max_t(u32, *width, 32), max_w, 4,
+				      height, max_t(u32, *height, 32),
+				      FIMC_CAMIF_MAX_HEIGHT,
+				      fimc_fmt_is_jpeg(ffmt->color) ? 3 : 1,
+				      0);
+		return ffmt;
+	}
+	/* Can't scale or crop in transparent (JPEG) transfer mode */
+	if (fimc_fmt_is_jpeg(ffmt->color)) {
+		*width  = ctx->s_frame.f_width;
+		*height = ctx->s_frame.f_height;
+		return ffmt;
+	}
+	/* Apply the scaler and the output DMA constraints */
+	max_w = rotation ? pl->out_rot_en_w : pl->out_rot_dis_w;
+	min_w = ctx->state & FIMC_DST_CROP ? dst->width : var->min_out_pixsize;
+	min_h = ctx->state & FIMC_DST_CROP ? dst->height : var->min_out_pixsize;
+	if (var->min_vsize_align == 1 && !rotation)
+		align_h = fimc_fmt_is_rgb(ffmt->color) ? 0 : 1;
+
+	depth = fimc_get_format_depth(ffmt);
+	v4l_bound_align_image(width, min_w, max_w,
+			      ffs(var->min_out_pixsize) - 1,
+			      height, min_h, FIMC_CAMIF_MAX_HEIGHT,
+			      align_h,
+			      64/(ALIGN(depth, 8)));
+
+	dbg("pad%d: code: 0x%x, %dx%d. dst fmt: %dx%d",
+	    pad, code ? *code : 0, *width, *height,
+	    dst->f_width, dst->f_height);
+
+	return ffmt;
+}
+
+static void fimc_capture_try_crop(struct fimc_ctx *ctx, struct v4l2_rect *r,
+				  int pad)
+{
+	bool rotate = ctx->rotation == 90 || ctx->rotation == 270;
+	struct fimc_dev *fimc = ctx->fimc_dev;
+	struct samsung_fimc_variant *var = fimc->variant;
+	struct fimc_pix_limit *pl = var->pix_limit;
+	struct fimc_frame *sink = &ctx->s_frame;
+	u32 max_w, max_h, min_w = 0, min_h = 0, min_sz;
+	u32 align_sz = 0, align_h = 4;
+	u32 max_sc_h, max_sc_v;
+
+	/* In JPEG transparent transfer mode cropping is not supported */
+	if (fimc_fmt_is_jpeg(ctx->d_frame.fmt->color)) {
+		r->width  = sink->f_width;
+		r->height = sink->f_height;
+		r->left   = r->top = 0;
+		return;
+	}
+	if (pad == FIMC_SD_PAD_SOURCE) {
+		if (ctx->rotation != 90 && ctx->rotation != 270)
+			align_h = 1;
+		max_sc_h = min(SCALER_MAX_HRATIO, 1 << (ffs(sink->width) - 3));
+		max_sc_v = min(SCALER_MAX_VRATIO, 1 << (ffs(sink->height) - 1));
+		min_sz = var->min_out_pixsize;
+	} else {
+		u32 depth = fimc_get_format_depth(sink->fmt);
+		align_sz = 64/ALIGN(depth, 8);
+		min_sz = var->min_inp_pixsize;
+		min_w = min_h = min_sz;
+		max_sc_h = max_sc_v = 1;
+	}
+	/*
+	 * For the crop rectangle at source pad the following constraints
+	 * must be met:
+	 * - it must fit in the sink pad format rectangle (f_width/f_height);
+	 * - maximum downscaling ratio is 64;
+	 * - maximum crop size depends if the rotator is used or not;
+	 * - the sink pad format width/height must be 4 multiple of the
+	 *   prescaler ratios determined by sink pad size and source pad crop,
+	 *   the prescaler ratio is returned by fimc_get_scaler_factor().
+	 */
+	max_w = min_t(u32,
+		      rotate ? pl->out_rot_en_w : pl->out_rot_dis_w,
+		      rotate ? sink->f_height : sink->f_width);
+	max_h = min_t(u32, FIMC_CAMIF_MAX_HEIGHT, sink->f_height);
+	if (pad == FIMC_SD_PAD_SOURCE) {
+		min_w = min_t(u32, max_w, sink->f_width / max_sc_h);
+		min_h = min_t(u32, max_h, sink->f_height / max_sc_v);
+		if (rotate) {
+			swap(max_sc_h, max_sc_v);
+			swap(min_w, min_h);
+		}
+	}
+	v4l_bound_align_image(&r->width, min_w, max_w, ffs(min_sz) - 1,
+			      &r->height, min_h, max_h, align_h,
+			      align_sz);
+	/* Adjust left/top if cropping rectangle is out of bounds */
+	r->left = clamp_t(u32, r->left, 0, sink->f_width - r->width);
+	r->top  = clamp_t(u32, r->top, 0, sink->f_height - r->height);
+	r->left = round_down(r->left, var->hor_offs_align);
+
+	dbg("pad%d: (%d,%d)/%dx%d, sink fmt: %dx%d",
+	    pad, r->left, r->top, r->width, r->height,
+	    sink->f_width, sink->f_height);
+}
+
+/*
+ * The video node ioctl operations
+ */
 static int fimc_vidioc_querycap_capture(struct file *file, void *priv,
 					struct v4l2_capability *cap)
 {
-	struct fimc_ctx *ctx = file->private_data;
-	struct fimc_dev *fimc = ctx->fimc_dev;
+	struct fimc_dev *fimc = video_drvdata(file);
 
 	strncpy(cap->driver, fimc->pdev->name, sizeof(cap->driver) - 1);
 	strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1);
 	cap->bus_info[0] = 0;
-	cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |
-			    V4L2_CAP_VIDEO_CAPTURE_MPLANE;
+	cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE_MPLANE;
 
 	return 0;
 }
 
-/* Synchronize formats of the camera interface input and attached  sensor. */
-static int sync_capture_fmt(struct fimc_ctx *ctx)
+static int fimc_cap_enum_fmt_mplane(struct file *file, void *priv,
+				    struct v4l2_fmtdesc *f)
 {
-	struct fimc_frame *frame = &ctx->s_frame;
-	struct fimc_dev *fimc = ctx->fimc_dev;
-	struct v4l2_mbus_framefmt *fmt = &fimc->vid_cap.fmt;
-	int ret;
+	struct fimc_fmt *fmt;
 
-	fmt->width  = ctx->d_frame.o_width;
-	fmt->height = ctx->d_frame.o_height;
+	fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM | FMT_FLAGS_M2M,
+			       f->index);
+	if (!fmt)
+		return -EINVAL;
+	strncpy(f->description, fmt->name, sizeof(f->description) - 1);
+	f->pixelformat = fmt->fourcc;
+	if (fmt->fourcc == V4L2_MBUS_FMT_JPEG_1X8)
+		f->flags |= V4L2_FMT_FLAG_COMPRESSED;
+	return 0;
+}
 
-	ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_mbus_fmt, fmt);
-	if (ret == -ENOIOCTLCMD) {
-		err("s_mbus_fmt failed");
-		return ret;
-	}
-	dbg("w: %d, h: %d, code= %d", fmt->width, fmt->height, fmt->code);
+/**
+ * fimc_pipeline_try_format - negotiate and/or set formats at pipeline
+ *                            elements
+ * @ctx: FIMC capture context
+ * @tfmt: media bus format to try/set on subdevs
+ * @fmt_id: fimc pixel format id corresponding to returned @tfmt (output)
+ * @set: true to set format on subdevs, false to try only
+ */
+static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
+				    struct v4l2_mbus_framefmt *tfmt,
+				    struct fimc_fmt **fmt_id,
+				    bool set)
+{
+	struct fimc_dev *fimc = ctx->fimc_dev;
+	struct v4l2_subdev *sd = fimc->pipeline.sensor;
+	struct v4l2_subdev *csis = fimc->pipeline.csis;
+	struct v4l2_subdev_format sfmt;
+	struct v4l2_mbus_framefmt *mf = &sfmt.format;
+	struct fimc_fmt *ffmt = NULL;
+	int ret, i = 0;
 
-	frame->fmt = find_mbus_format(fmt, FMT_FLAGS_CAM);
-	if (!frame->fmt) {
-		err("fimc source format not found\n");
+	if (WARN_ON(!sd || !tfmt))
 		return -EINVAL;
+
+	memset(&sfmt, 0, sizeof(sfmt));
+	sfmt.format = *tfmt;
+
+	sfmt.which = set ? V4L2_SUBDEV_FORMAT_ACTIVE : V4L2_SUBDEV_FORMAT_TRY;
+	while (1) {
+		ffmt = fimc_find_format(NULL, mf->code != 0 ? &mf->code : NULL,
+					FMT_FLAGS_CAM, i++);
+		if (ffmt == NULL) {
+			/*
+			 * Notify user-space if common pixel code for
+			 * host and sensor does not exist.
+			 */
+			return -EINVAL;
+		}
+		mf->code = tfmt->code = ffmt->mbus_code;
+
+		ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &sfmt);
+		if (ret)
+			return ret;
+		if (mf->code != tfmt->code) {
+			mf->code = 0;
+			continue;
+		}
+		if (mf->width != tfmt->width || mf->width != tfmt->width) {
+			u32 fcc = ffmt->fourcc;
+			tfmt->width  = mf->width;
+			tfmt->height = mf->height;
+			ffmt = fimc_capture_try_format(ctx,
+					       &tfmt->width, &tfmt->height,
+					       NULL, &fcc, FIMC_SD_PAD_SOURCE);
+			if (ffmt && ffmt->mbus_code)
+				mf->code = ffmt->mbus_code;
+			if (mf->width != tfmt->width || mf->width != tfmt->width)
+				continue;
+			tfmt->code = mf->code;
+		}
+		if (csis)
+			ret = v4l2_subdev_call(csis, pad, set_fmt, NULL, &sfmt);
+
+		if (mf->code == tfmt->code &&
+		    mf->width == tfmt->width && mf->width == tfmt->width)
+			break;
 	}
 
-	frame->f_width	= fmt->width;
-	frame->f_height = fmt->height;
-	frame->width	= fmt->width;
-	frame->height	= fmt->height;
-	frame->o_width	= fmt->width;
-	frame->o_height = fmt->height;
-	frame->offs_h	= 0;
-	frame->offs_v	= 0;
+	if (fmt_id && ffmt)
+		*fmt_id = ffmt;
+	*tfmt = *mf;
 
+	dbg("code: 0x%x, %dx%d, %p", mf->code, mf->width, mf->height, ffmt);
 	return 0;
 }
 
-static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
+static int fimc_cap_g_fmt_mplane(struct file *file, void *fh,
 				 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 *pix;
-	int ret;
-	int i;
+	struct fimc_dev *fimc = video_drvdata(file);
+	struct fimc_ctx *ctx = fimc->vid_cap.ctx;
 
 	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 		return -EINVAL;
 
-	ret = fimc_vidioc_try_fmt_mplane(file, priv, f);
-	if (ret)
-		return ret;
-
-	if (vb2_is_busy(&fimc->vid_cap.vbq) || fimc_capture_active(fimc))
-		return -EBUSY;
+	return fimc_fill_format(&ctx->d_frame, f);
+}
 
-	frame = &ctx->d_frame;
+static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
+				   struct v4l2_format *f)
+{
+	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
+	struct fimc_dev *fimc = video_drvdata(file);
+	struct fimc_ctx *ctx = fimc->vid_cap.ctx;
+	struct v4l2_mbus_framefmt mf;
+	struct fimc_fmt *ffmt = NULL;
 
-	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");
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 		return -EINVAL;
-	}
 
-	for (i = 0; i < frame->fmt->colplanes; i++) {
-		frame->payload[i] =
-			(pix->width * pix->height * frame->fmt->depth[i]) >> 3;
+	if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+		fimc_capture_try_format(ctx, &pix->width, &pix->height,
+					NULL, &pix->pixelformat,
+					FIMC_SD_PAD_SINK);
+		ctx->s_frame.f_width  = pix->width;
+		ctx->s_frame.f_height = pix->height;
 	}
+	ffmt = fimc_capture_try_format(ctx, &pix->width, &pix->height,
+				       NULL, &pix->pixelformat,
+				       FIMC_SD_PAD_SOURCE);
+	if (!ffmt)
+		return -EINVAL;
 
-	/* Output DMA frame pixel size and offsets. */
-	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->offs_h	= 0;
-	frame->offs_v	= 0;
+	if (!fimc->vid_cap.user_subdev_api) {
+		mf.width  = pix->width;
+		mf.height = pix->height;
+		mf.code   = ffmt->mbus_code;
+		fimc_md_graph_lock(fimc);
+		fimc_pipeline_try_format(ctx, &mf, &ffmt, false);
+		fimc_md_graph_unlock(fimc);
 
-	ctx->state |= (FIMC_PARAMS | FIMC_DST_FMT);
+		pix->width	 = mf.width;
+		pix->height	 = mf.height;
+		if (ffmt)
+			pix->pixelformat = ffmt->fourcc;
+	}
 
-	ret = sync_capture_fmt(ctx);
-	return ret;
+	fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix);
+	return 0;
 }
 
-static int fimc_cap_enum_input(struct file *file, void *priv,
-				     struct v4l2_input *i)
+static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, bool jpeg)
 {
-	struct fimc_ctx *ctx = priv;
-	struct s5p_platform_fimc *pldata = ctx->fimc_dev->pdata;
-	struct s5p_fimc_isp_info *isp_info;
-
-	if (i->index >= pldata->num_clients)
-		return -EINVAL;
-
-	isp_info = &pldata->isp_info[i->index];
+	ctx->scaler.enabled = !jpeg;
+	fimc_ctrls_activate(ctx, !jpeg);
 
-	i->type = V4L2_INPUT_TYPE_CAMERA;
-	strncpy(i->name, isp_info->board_info->type, 32);
-	return 0;
+	if (jpeg)
+		set_bit(ST_CAPT_JPEG, &ctx->fimc_dev->state);
+	else
+		clear_bit(ST_CAPT_JPEG, &ctx->fimc_dev->state);
 }
 
-static int fimc_cap_s_input(struct file *file, void *priv,
-				  unsigned int i)
+static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
 {
-	struct fimc_ctx *ctx = priv;
-	struct fimc_dev *fimc = ctx->fimc_dev;
-	struct s5p_platform_fimc *pdata = fimc->pdata;
+	struct fimc_ctx *ctx = fimc->vid_cap.ctx;
+	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
+	struct v4l2_mbus_framefmt *mf = &fimc->vid_cap.mf;
+	struct fimc_frame *ff = &ctx->d_frame;
+	struct fimc_fmt *s_fmt = NULL;
+	int ret, i;
 
-	if (fimc_capture_active(ctx->fimc_dev))
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		return -EINVAL;
+	if (vb2_is_busy(&fimc->vid_cap.vbq))
 		return -EBUSY;
 
-	if (i >= pdata->num_clients)
+	/* Pre-configure format at camera interface input, for JPEG only */
+	if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+		fimc_capture_try_format(ctx, &pix->width, &pix->height,
+					NULL, &pix->pixelformat,
+					FIMC_SD_PAD_SINK);
+		ctx->s_frame.f_width  = pix->width;
+		ctx->s_frame.f_height = pix->height;
+	}
+	/* Try the format at the scaler and the DMA output */
+	ff->fmt = fimc_capture_try_format(ctx, &pix->width, &pix->height,
+					  NULL, &pix->pixelformat,
+					  FIMC_SD_PAD_SOURCE);
+	if (!ff->fmt)
 		return -EINVAL;
+	/* Try to match format at the host and the sensor */
+	if (!fimc->vid_cap.user_subdev_api) {
+		mf->code   = ff->fmt->mbus_code;
+		mf->width  = pix->width;
+		mf->height = pix->height;
 
-
-	if (fimc->vid_cap.sd) {
-		int ret = v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0);
+		fimc_md_graph_lock(fimc);
+		ret = fimc_pipeline_try_format(ctx, mf, &s_fmt, true);
+		fimc_md_graph_unlock(fimc);
 		if (ret)
-			err("s_power failed: %d", ret);
+			return ret;
+		pix->width  = mf->width;
+		pix->height = mf->height;
+	}
+	fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix);
+	for (i = 0; i < ff->fmt->colplanes; i++)
+		ff->payload[i] =
+			(pix->width * pix->height * ff->fmt->depth[i]) / 8;
 
-		clk_disable(fimc->clock[CLK_CAM]);
+	set_frame_bounds(ff, pix->width, pix->height);
+	/* Reset the composition rectangle if not yet configured */
+	if (!(ctx->state & FIMC_DST_CROP))
+		set_frame_crop(ff, 0, 0, pix->width, pix->height);
+
+	fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ff->fmt->color));
+
+	/* Reset cropping and set format at the camera interface input */
+	if (!fimc->vid_cap.user_subdev_api) {
+		ctx->s_frame.fmt = s_fmt;
+		set_frame_bounds(&ctx->s_frame, pix->width, pix->height);
+		set_frame_crop(&ctx->s_frame, 0, 0, pix->width, pix->height);
 	}
 
-	/* Release the attached sensor subdevice. */
-	fimc_subdev_unregister(fimc);
+	return ret;
+}
 
-	return fimc_isp_subdev_init(fimc, i);
+static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
+				 struct v4l2_format *f)
+{
+	struct fimc_dev *fimc = video_drvdata(file);
+
+	return fimc_capture_set_format(fimc, f);
 }
 
-static int fimc_cap_g_input(struct file *file, void *priv,
-				       unsigned int *i)
+static int fimc_cap_enum_input(struct file *file, void *priv,
+			       struct v4l2_input *i)
 {
-	struct fimc_ctx *ctx = priv;
-	struct fimc_vid_cap *cap = &ctx->fimc_dev->vid_cap;
+	struct fimc_dev *fimc = video_drvdata(file);
+	struct v4l2_subdev *sd = fimc->pipeline.sensor;
 
-	*i = cap->input_index;
+	if (i->index != 0)
+		return -EINVAL;
+
+	i->type = V4L2_INPUT_TYPE_CAMERA;
+	if (sd)
+		strlcpy(i->name, sd->name, sizeof(i->name));
+	return 0;
+}
+
+static int fimc_cap_s_input(struct file *file, void *priv, unsigned int i)
+{
+	return i == 0 ? i : -EINVAL;
+}
+
+static int fimc_cap_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	*i = 0;
+	return 0;
+}
+
+/**
+ * fimc_pipeline_validate - check for formats inconsistencies
+ *                          between source and sink pad of each link
+ *
+ * Return 0 if all formats match or -EPIPE otherwise.
+ */
+static int fimc_pipeline_validate(struct fimc_dev *fimc)
+{
+	struct v4l2_subdev_format sink_fmt, src_fmt;
+	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
+	struct v4l2_subdev *sd;
+	struct media_pad *pad;
+	int ret;
+
+	/* Start with the video capture node pad */
+	pad = media_entity_remote_source(&vid_cap->vd_pad);
+	if (pad == NULL)
+		return -EPIPE;
+	/* FIMC.{N} subdevice */
+	sd = media_entity_to_v4l2_subdev(pad->entity);
+
+	while (1) {
+		/* Retrieve format at the sink pad */
+		pad = &sd->entity.pads[0];
+		if (!(pad->flags & MEDIA_PAD_FL_SINK))
+			break;
+		/* Don't call FIMC subdev operation to avoid nested locking */
+		if (sd == fimc->vid_cap.subdev) {
+			struct fimc_frame *ff = &vid_cap->ctx->s_frame;
+			sink_fmt.format.width = ff->f_width;
+			sink_fmt.format.height = ff->f_height;
+			sink_fmt.format.code = ff->fmt ? ff->fmt->mbus_code : 0;
+		} else {
+			sink_fmt.pad = pad->index;
+			sink_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+			ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sink_fmt);
+			if (ret < 0 && ret != -ENOIOCTLCMD)
+				return -EPIPE;
+		}
+		/* Retrieve format at the source pad */
+		pad = media_entity_remote_source(pad);
+		if (pad == NULL ||
+		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+			break;
+
+		sd = media_entity_to_v4l2_subdev(pad->entity);
+		src_fmt.pad = pad->index;
+		src_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+		ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &src_fmt);
+		if (ret < 0 && ret != -ENOIOCTLCMD)
+			return -EPIPE;
+
+		if (src_fmt.format.width != sink_fmt.format.width ||
+		    src_fmt.format.height != sink_fmt.format.height ||
+		    src_fmt.format.code != sink_fmt.format.code)
+			return -EPIPE;
+	}
 	return 0;
 }
 
 static int fimc_cap_streamon(struct file *file, void *priv,
 			     enum v4l2_buf_type type)
 {
-	struct fimc_ctx *ctx = priv;
-	struct fimc_dev *fimc = ctx->fimc_dev;
+	struct fimc_dev *fimc = video_drvdata(file);
+	struct fimc_pipeline *p = &fimc->pipeline;
+	int ret;
 
-	if (fimc_capture_active(fimc) || !fimc->vid_cap.sd)
+	if (fimc_capture_active(fimc))
 		return -EBUSY;
 
-	if (!(ctx->state & FIMC_DST_FMT)) {
-		v4l2_err(&fimc->vid_cap.v4l2_dev, "Format is not set\n");
-		return -EINVAL;
-	}
+	media_entity_pipeline_start(&p->sensor->entity, p->pipe);
 
+	if (fimc->vid_cap.user_subdev_api) {
+		ret = fimc_pipeline_validate(fimc);
+		if (ret)
+			return ret;
+	}
 	return vb2_streamon(&fimc->vid_cap.vbq, type);
 }
 
 static int fimc_cap_streamoff(struct file *file, void *priv,
 			    enum v4l2_buf_type type)
 {
-	struct fimc_ctx *ctx = priv;
-	struct fimc_dev *fimc = ctx->fimc_dev;
+	struct fimc_dev *fimc = video_drvdata(file);
+	struct v4l2_subdev *sd = fimc->pipeline.sensor;
+	int ret;
 
-	return vb2_streamoff(&fimc->vid_cap.vbq, type);
+	ret = vb2_streamoff(&fimc->vid_cap.vbq, type);
+	if (ret == 0)
+		media_entity_pipeline_stop(&sd->entity);
+	return ret;
 }
 
 static int fimc_cap_reqbufs(struct file *file, void *priv,
 			    struct v4l2_requestbuffers *reqbufs)
 {
-	struct fimc_ctx *ctx = priv;
-	struct fimc_vid_cap *cap = &ctx->fimc_dev->vid_cap;
-	int ret;
-
+	struct fimc_dev *fimc = video_drvdata(file);
+	int ret = vb2_reqbufs(&fimc->vid_cap.vbq, reqbufs);
 
-	ret = vb2_reqbufs(&cap->vbq, reqbufs);
 	if (!ret)
-		cap->reqbufs_count = reqbufs->count;
-
+		fimc->vid_cap.reqbufs_count = reqbufs->count;
 	return ret;
 }
 
 static int fimc_cap_querybuf(struct file *file, void *priv,
 			   struct v4l2_buffer *buf)
 {
-	struct fimc_ctx *ctx = priv;
-	struct fimc_vid_cap *cap = &ctx->fimc_dev->vid_cap;
+	struct fimc_dev *fimc = video_drvdata(file);
 
-	return vb2_querybuf(&cap->vbq, buf);
+	return vb2_querybuf(&fimc->vid_cap.vbq, buf);
 }
 
 static int fimc_cap_qbuf(struct file *file, void *priv,
 			  struct v4l2_buffer *buf)
 {
-	struct fimc_ctx *ctx = priv;
-	struct fimc_vid_cap *cap = &ctx->fimc_dev->vid_cap;
-	return vb2_qbuf(&cap->vbq, buf);
+	struct fimc_dev *fimc = video_drvdata(file);
+
+	return vb2_qbuf(&fimc->vid_cap.vbq, buf);
 }
 
 static int fimc_cap_dqbuf(struct file *file, void *priv,
 			   struct v4l2_buffer *buf)
 {
-	struct fimc_ctx *ctx = priv;
-	return vb2_dqbuf(&ctx->fimc_dev->vid_cap.vbq, buf,
-		file->f_flags & O_NONBLOCK);
-}
-
-static int fimc_cap_s_ctrl(struct file *file, void *priv,
-			 struct v4l2_control *ctrl)
-{
-	struct fimc_ctx *ctx = priv;
-	int ret = -EINVAL;
+	struct fimc_dev *fimc = video_drvdata(file);
 
-	/* Allow any controls but 90/270 rotation while streaming */
-	if (!fimc_capture_active(ctx->fimc_dev) ||
-	    ctrl->id != V4L2_CID_ROTATE ||
-	    (ctrl->value != 90 && ctrl->value != 270)) {
-		ret = check_ctrl_val(ctx, ctrl);
-		if (!ret) {
-			ret = fimc_s_ctrl(ctx, ctrl);
-			if (!ret)
-				ctx->state |= FIMC_PARAMS;
-		}
-	}
-	if (ret == -EINVAL)
-		ret = v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,
-				       core, s_ctrl, ctrl);
-	return ret;
+	return vb2_dqbuf(&fimc->vid_cap.vbq, buf, file->f_flags & O_NONBLOCK);
 }
 
 static int fimc_cap_cropcap(struct file *file, void *fh,
 			    struct v4l2_cropcap *cr)
 {
-	struct fimc_frame *f;
-	struct fimc_ctx *ctx = fh;
+	struct fimc_dev *fimc = video_drvdata(file);
+	struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame;
 
 	if (cr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 		return -EINVAL;
 
-	f = &ctx->s_frame;
-
 	cr->bounds.left		= 0;
 	cr->bounds.top		= 0;
 	cr->bounds.width	= f->o_width;
@@ -709,10 +1030,8 @@
 
 static int fimc_cap_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
 {
-	struct fimc_frame *f;
-	struct fimc_ctx *ctx = file->private_data;
-
-	f = &ctx->s_frame;
+	struct fimc_dev *fimc = video_drvdata(file);
+	struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame;
 
 	cr->c.left	= f->offs_h;
 	cr->c.top	= f->offs_v;
@@ -722,53 +1041,31 @@
 	return 0;
 }
 
-static int fimc_cap_s_crop(struct file *file, void *fh,
-			       struct v4l2_crop *cr)
+static int fimc_cap_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
 {
-	struct fimc_frame *f;
-	struct fimc_ctx *ctx = file->private_data;
-	struct fimc_dev *fimc = ctx->fimc_dev;
-	int ret = -EINVAL;
-
-	if (fimc_capture_active(fimc))
-		return -EBUSY;
-
-	ret = fimc_try_crop(ctx, cr);
-	if (ret)
-		return ret;
-
-	if (!(ctx->state & FIMC_DST_FMT)) {
-		v4l2_err(&fimc->vid_cap.v4l2_dev,
-			 "Capture color format not set\n");
-		return -EINVAL; /* TODO: make sure this is the right value */
-	}
+	struct fimc_dev *fimc = video_drvdata(file);
+	struct fimc_ctx *ctx = fimc->vid_cap.ctx;
+	struct fimc_frame *ff;
+	unsigned long flags;
 
-	f = &ctx->s_frame;
-	/* Check for the pixel scaling ratio when cropping input image. */
-	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\n");
-		return ret;
-	}
+	fimc_capture_try_crop(ctx, &cr->c, FIMC_SD_PAD_SINK);
+	ff = &ctx->s_frame;
 
-	f->offs_h = cr->c.left;
-	f->offs_v = cr->c.top;
-	f->width  = cr->c.width;
-	f->height = cr->c.height;
+	spin_lock_irqsave(&fimc->slock, flags);
+	set_frame_crop(ff, cr->c.left, cr->c.top, cr->c.width, cr->c.height);
+	set_bit(ST_CAPT_APPLY_CFG, &fimc->state);
+	spin_unlock_irqrestore(&fimc->slock, flags);
 
 	return 0;
 }
 
-
 static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
 	.vidioc_querycap		= fimc_vidioc_querycap_capture,
 
-	.vidioc_enum_fmt_vid_cap_mplane	= fimc_vidioc_enum_fmt_mplane,
-	.vidioc_try_fmt_vid_cap_mplane	= fimc_vidioc_try_fmt_mplane,
+	.vidioc_enum_fmt_vid_cap_mplane	= fimc_cap_enum_fmt_mplane,
+	.vidioc_try_fmt_vid_cap_mplane	= fimc_cap_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_g_fmt_vid_cap_mplane	= fimc_cap_g_fmt_mplane,
 
 	.vidioc_reqbufs			= fimc_cap_reqbufs,
 	.vidioc_querybuf		= fimc_cap_querybuf,
@@ -779,10 +1076,6 @@
 	.vidioc_streamon		= fimc_cap_streamon,
 	.vidioc_streamoff		= fimc_cap_streamoff,
 
-	.vidioc_queryctrl		= fimc_vidioc_queryctrl,
-	.vidioc_g_ctrl			= fimc_vidioc_g_ctrl,
-	.vidioc_s_ctrl			= fimc_cap_s_ctrl,
-
 	.vidioc_g_crop			= fimc_cap_g_crop,
 	.vidioc_s_crop			= fimc_cap_s_crop,
 	.vidioc_cropcap			= fimc_cap_cropcap,
@@ -792,17 +1085,329 @@
 	.vidioc_g_input			= fimc_cap_g_input,
 };
 
+/* Capture subdev media entity operations */
+static int fimc_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 fimc_dev *fimc = v4l2_get_subdevdata(sd);
+
+	if (media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		return -EINVAL;
+
+	if (WARN_ON(fimc == NULL))
+		return 0;
+
+	dbg("%s --> %s, flags: 0x%x. input: 0x%x",
+	    local->entity->name, remote->entity->name, flags,
+	    fimc->vid_cap.input);
+
+	if (flags & MEDIA_LNK_FL_ENABLED) {
+		if (fimc->vid_cap.input != 0)
+			return -EBUSY;
+		fimc->vid_cap.input = sd->grp_id;
+		return 0;
+	}
+
+	fimc->vid_cap.input = 0;
+	return 0;
+}
+
+static const struct media_entity_operations fimc_sd_media_ops = {
+	.link_setup = fimc_link_setup,
+};
+
+/**
+ * fimc_sensor_notify - v4l2_device notification from a sensor subdev
+ * @sd: pointer to a subdev generating the notification
+ * @notification: the notification type, must be S5P_FIMC_TX_END_NOTIFY
+ * @arg: pointer to an u32 type integer that stores the frame payload value
+ *
+ * The End Of Frame notification sent by sensor subdev in its still capture
+ * mode. If there is only a single VSYNC generated by the sensor at the
+ * beginning of a frame transmission, FIMC does not issue the LastIrq
+ * (end of frame) interrupt. And this notification is used to complete the
+ * frame capture and returning a buffer to user-space. Subdev drivers should
+ * call this notification from their last 'End of frame capture' interrupt.
+ */
+void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification,
+			void *arg)
+{
+	struct fimc_sensor_info	*sensor;
+	struct fimc_vid_buffer *buf;
+	struct fimc_md *fmd;
+	struct fimc_dev *fimc;
+	unsigned long flags;
+
+	if (sd == NULL)
+		return;
+
+	sensor = v4l2_get_subdev_hostdata(sd);
+	fmd = entity_to_fimc_mdev(&sd->entity);
+
+	spin_lock_irqsave(&fmd->slock, flags);
+	fimc = sensor ? sensor->host : NULL;
+
+	if (fimc && arg && notification == S5P_FIMC_TX_END_NOTIFY &&
+	    test_bit(ST_CAPT_PEND, &fimc->state)) {
+		unsigned long irq_flags;
+		spin_lock_irqsave(&fimc->slock, irq_flags);
+		if (!list_empty(&fimc->vid_cap.active_buf_q)) {
+			buf = list_entry(fimc->vid_cap.active_buf_q.next,
+					 struct fimc_vid_buffer, list);
+			vb2_set_plane_payload(&buf->vb, 0, *((u32 *)arg));
+		}
+		fimc_capture_irq_handler(fimc, true);
+		fimc_deactivate_capture(fimc);
+		spin_unlock_irqrestore(&fimc->slock, irq_flags);
+	}
+	spin_unlock_irqrestore(&fmd->slock, flags);
+}
+
+static int fimc_subdev_enum_mbus_code(struct v4l2_subdev *sd,
+				      struct v4l2_subdev_fh *fh,
+				      struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct fimc_fmt *fmt;
+
+	fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, code->index);
+	if (!fmt)
+		return -EINVAL;
+	code->code = fmt->mbus_code;
+	return 0;
+}
+
+static int fimc_subdev_get_fmt(struct v4l2_subdev *sd,
+			       struct v4l2_subdev_fh *fh,
+			       struct v4l2_subdev_format *fmt)
+{
+	struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
+	struct fimc_ctx *ctx = fimc->vid_cap.ctx;
+	struct v4l2_mbus_framefmt *mf;
+	struct fimc_frame *ff;
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+		mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+		fmt->format = *mf;
+		return 0;
+	}
+	mf = &fmt->format;
+	mf->colorspace = V4L2_COLORSPACE_JPEG;
+	ff = fmt->pad == FIMC_SD_PAD_SINK ? &ctx->s_frame : &ctx->d_frame;
+
+	mutex_lock(&fimc->lock);
+	/* The pixel code is same on both input and output pad */
+	if (!WARN_ON(ctx->s_frame.fmt == NULL))
+		mf->code = ctx->s_frame.fmt->mbus_code;
+	mf->width  = ff->f_width;
+	mf->height = ff->f_height;
+	mutex_unlock(&fimc->lock);
+
+	return 0;
+}
+
+static int fimc_subdev_set_fmt(struct v4l2_subdev *sd,
+			       struct v4l2_subdev_fh *fh,
+			       struct v4l2_subdev_format *fmt)
+{
+	struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *mf = &fmt->format;
+	struct fimc_ctx *ctx = fimc->vid_cap.ctx;
+	struct fimc_frame *ff;
+	struct fimc_fmt *ffmt;
+
+	dbg("pad%d: code: 0x%x, %dx%d",
+	    fmt->pad, mf->code, mf->width, mf->height);
+
+	if (fmt->pad == FIMC_SD_PAD_SOURCE &&
+	    vb2_is_busy(&fimc->vid_cap.vbq))
+		return -EBUSY;
+
+	mutex_lock(&fimc->lock);
+	ffmt = fimc_capture_try_format(ctx, &mf->width, &mf->height,
+				       &mf->code, NULL, fmt->pad);
+	mutex_unlock(&fimc->lock);
+	mf->colorspace = V4L2_COLORSPACE_JPEG;
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+		mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+		*mf = fmt->format;
+		return 0;
+	}
+	fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ffmt->color));
+
+	ff = fmt->pad == FIMC_SD_PAD_SINK ?
+		&ctx->s_frame : &ctx->d_frame;
+
+	mutex_lock(&fimc->lock);
+	set_frame_bounds(ff, mf->width, mf->height);
+	fimc->vid_cap.mf = *mf;
+	ff->fmt = ffmt;
+
+	/* Reset the crop rectangle if required. */
+	if (!(fmt->pad == FIMC_SD_PAD_SOURCE && (ctx->state & FIMC_DST_CROP)))
+		set_frame_crop(ff, 0, 0, mf->width, mf->height);
+
+	if (fmt->pad == FIMC_SD_PAD_SINK)
+		ctx->state &= ~FIMC_DST_CROP;
+	mutex_unlock(&fimc->lock);
+	return 0;
+}
+
+static int fimc_subdev_get_crop(struct v4l2_subdev *sd,
+				struct v4l2_subdev_fh *fh,
+				struct v4l2_subdev_crop *crop)
+{
+	struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
+	struct fimc_ctx *ctx = fimc->vid_cap.ctx;
+	struct v4l2_rect *r = &crop->rect;
+	struct fimc_frame *ff;
+
+	if (crop->which == V4L2_SUBDEV_FORMAT_TRY) {
+		crop->rect = *v4l2_subdev_get_try_crop(fh, crop->pad);
+		return 0;
+	}
+	ff = crop->pad == FIMC_SD_PAD_SINK ?
+		&ctx->s_frame : &ctx->d_frame;
+
+	mutex_lock(&fimc->lock);
+	r->left	  = ff->offs_h;
+	r->top	  = ff->offs_v;
+	r->width  = ff->width;
+	r->height = ff->height;
+	mutex_unlock(&fimc->lock);
+
+	dbg("ff:%p, pad%d: l:%d, t:%d, %dx%d, f_w: %d, f_h: %d",
+	    ff, crop->pad, r->left, r->top, r->width, r->height,
+	    ff->f_width, ff->f_height);
+
+	return 0;
+}
+
+static int fimc_subdev_set_crop(struct v4l2_subdev *sd,
+				struct v4l2_subdev_fh *fh,
+				struct v4l2_subdev_crop *crop)
+{
+	struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
+	struct fimc_ctx *ctx = fimc->vid_cap.ctx;
+	struct v4l2_rect *r = &crop->rect;
+	struct fimc_frame *ff;
+	unsigned long flags;
+
+	dbg("(%d,%d)/%dx%d", r->left, r->top, r->width, r->height);
+
+	ff = crop->pad == FIMC_SD_PAD_SOURCE ?
+		&ctx->d_frame : &ctx->s_frame;
+
+	mutex_lock(&fimc->lock);
+	fimc_capture_try_crop(ctx, r, crop->pad);
+
+	if (crop->which == V4L2_SUBDEV_FORMAT_TRY) {
+		mutex_lock(&fimc->lock);
+		*v4l2_subdev_get_try_crop(fh, crop->pad) = *r;
+		return 0;
+	}
+	spin_lock_irqsave(&fimc->slock, flags);
+	set_frame_crop(ff, r->left, r->top, r->width, r->height);
+	if (crop->pad == FIMC_SD_PAD_SOURCE)
+		ctx->state |= FIMC_DST_CROP;
+
+	set_bit(ST_CAPT_APPLY_CFG, &fimc->state);
+	spin_unlock_irqrestore(&fimc->slock, flags);
+
+	dbg("pad%d: (%d,%d)/%dx%d", crop->pad, r->left, r->top,
+	    r->width, r->height);
+
+	mutex_unlock(&fimc->lock);
+	return 0;
+}
+
+static struct v4l2_subdev_pad_ops fimc_subdev_pad_ops = {
+	.enum_mbus_code = fimc_subdev_enum_mbus_code,
+	.get_fmt = fimc_subdev_get_fmt,
+	.set_fmt = fimc_subdev_set_fmt,
+	.get_crop = fimc_subdev_get_crop,
+	.set_crop = fimc_subdev_set_crop,
+};
+
+static struct v4l2_subdev_ops fimc_subdev_ops = {
+	.pad = &fimc_subdev_pad_ops,
+};
+
+static int fimc_create_capture_subdev(struct fimc_dev *fimc,
+				      struct v4l2_device *v4l2_dev)
+{
+	struct v4l2_subdev *sd;
+	int ret;
+
+	sd = kzalloc(sizeof(*sd), GFP_KERNEL);
+	if (!sd)
+		return -ENOMEM;
+
+	v4l2_subdev_init(sd, &fimc_subdev_ops);
+	sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(sd->name, sizeof(sd->name), "FIMC.%d", fimc->pdev->id);
+
+	fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	fimc->vid_cap.sd_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_init(&sd->entity, FIMC_SD_PADS_NUM,
+				fimc->vid_cap.sd_pads, 0);
+	if (ret)
+		goto me_err;
+	ret = v4l2_device_register_subdev(v4l2_dev, sd);
+	if (ret)
+		goto sd_err;
+
+	fimc->vid_cap.subdev = sd;
+	v4l2_set_subdevdata(sd, fimc);
+	sd->entity.ops = &fimc_sd_media_ops;
+	return 0;
+sd_err:
+	media_entity_cleanup(&sd->entity);
+me_err:
+	kfree(sd);
+	return ret;
+}
+
+static void fimc_destroy_capture_subdev(struct fimc_dev *fimc)
+{
+	struct v4l2_subdev *sd = fimc->vid_cap.subdev;
+
+	if (!sd)
+		return;
+	media_entity_cleanup(&sd->entity);
+	v4l2_device_unregister_subdev(sd);
+	kfree(sd);
+	fimc->vid_cap.subdev = NULL;
+}
+
+/* Set default format at the sensor and host interface */
+static int fimc_capture_set_default_format(struct fimc_dev *fimc)
+{
+	struct v4l2_format fmt = {
+		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.fmt.pix_mp = {
+			.width		= 640,
+			.height		= 480,
+			.pixelformat	= V4L2_PIX_FMT_YUYV,
+			.field		= V4L2_FIELD_NONE,
+			.colorspace	= V4L2_COLORSPACE_JPEG,
+		},
+	};
+
+	return fimc_capture_set_format(fimc, &fmt);
+}
+
 /* fimc->lock must be already initialized */
-int fimc_register_capture_device(struct fimc_dev *fimc)
+int fimc_register_capture_device(struct fimc_dev *fimc,
+				 struct v4l2_device *v4l2_dev)
 {
-	struct v4l2_device *v4l2_dev = &fimc->vid_cap.v4l2_dev;
 	struct video_device *vfd;
 	struct fimc_vid_cap *vid_cap;
 	struct fimc_ctx *ctx;
-	struct v4l2_format f;
-	struct fimc_frame *fr;
 	struct vb2_queue *q;
-	int ret;
+	int ret = -ENOMEM;
 
 	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
 	if (!ctx)
@@ -812,33 +1417,21 @@
 	ctx->in_path	 = FIMC_CAMERA;
 	ctx->out_path	 = FIMC_DMA;
 	ctx->state	 = FIMC_CTX_CAP;
-
-	/* 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),
-			 "%s.capture", dev_name(&fimc->pdev->dev));
-
-	ret = v4l2_device_register(NULL, v4l2_dev);
-	if (ret)
-		goto err_info;
+	ctx->s_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0);
+	ctx->d_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0);
 
 	vfd = video_device_alloc();
 	if (!vfd) {
 		v4l2_err(v4l2_dev, "Failed to allocate video device\n");
-		goto err_v4l2_reg;
+		goto err_vd_alloc;
 	}
 
-	snprintf(vfd->name, sizeof(vfd->name), "%s:cap",
+	snprintf(vfd->name, sizeof(vfd->name), "%s.capture",
 		 dev_name(&fimc->pdev->dev));
 
 	vfd->fops	= &fimc_capture_fops;
 	vfd->ioctl_ops	= &fimc_capture_ioctl_ops;
+	vfd->v4l2_dev	= v4l2_dev;
 	vfd->minor	= -1;
 	vfd->release	= video_device_release;
 	vfd->lock	= &fimc->lock;
@@ -849,8 +1442,6 @@
 	vid_cap->active_buf_cnt = 0;
 	vid_cap->reqbufs_count  = 0;
 	vid_cap->refcnt = 0;
-	/* Default color format for image sensor */
-	vid_cap->fmt.code = V4L2_MBUS_FMT_YUYV8_2X8;
 
 	INIT_LIST_HEAD(&vid_cap->pending_buf_q);
 	INIT_LIST_HEAD(&vid_cap->active_buf_q);
@@ -868,34 +1459,37 @@
 
 	vb2_queue_init(q);
 
-	ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
-	if (ret) {
-		v4l2_err(v4l2_dev, "Failed to register video device\n");
-		goto err_vd_reg;
-	}
-
-	v4l2_info(v4l2_dev,
-		  "FIMC capture driver registered as /dev/video%d\n",
-		  vfd->num);
+	fimc->vid_cap.vd_pad.flags = MEDIA_PAD_FL_SINK;
+	ret = media_entity_init(&vfd->entity, 1, &fimc->vid_cap.vd_pad, 0);
+	if (ret)
+		goto err_ent;
+	ret = fimc_create_capture_subdev(fimc, v4l2_dev);
+	if (ret)
+		goto err_sd_reg;
 
+	vfd->ctrl_handler = &ctx->ctrl_handler;
 	return 0;
 
-err_vd_reg:
+err_sd_reg:
+	media_entity_cleanup(&vfd->entity);
+err_ent:
 	video_device_release(vfd);
-err_v4l2_reg:
-	v4l2_device_unregister(v4l2_dev);
-err_info:
+err_vd_alloc:
 	kfree(ctx);
-	dev_err(&fimc->pdev->dev, "failed to install\n");
 	return ret;
 }
 
 void fimc_unregister_capture_device(struct fimc_dev *fimc)
 {
-	struct fimc_vid_cap *capture = &fimc->vid_cap;
-
-	if (capture->vfd)
-		video_unregister_device(capture->vfd);
+	struct video_device *vfd = fimc->vid_cap.vfd;
 
-	kfree(capture->ctx);
+	if (vfd) {
+		media_entity_cleanup(&vfd->entity);
+		/* Can also be called if video device was
+		   not registered */
+		video_unregister_device(vfd);
+	}
+	fimc_destroy_capture_subdev(fimc);
+	kfree(fimc->vid_cap.ctx);
+	fimc->vid_cap.ctx = NULL;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/fimc-core.c linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/fimc-core.c
--- linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/fimc-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/fimc-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/list.h>
 #include <linux/io.h>
 #include <linux/slab.h>
@@ -27,15 +28,16 @@
 #include <media/videobuf2-dma-contig.h>
 
 #include "fimc-core.h"
+#include "fimc-mdevice.h"
 
 static char *fimc_clocks[MAX_FIMC_CLOCKS] = {
-	"sclk_fimc", "fimc", "sclk_cam"
+	"sclk_fimc", "fimc"
 };
 
 static struct fimc_fmt fimc_formats[] = {
 	{
 		.name		= "RGB565",
-		.fourcc		= V4L2_PIX_FMT_RGB565X,
+		.fourcc		= V4L2_PIX_FMT_RGB565,
 		.depth		= { 16 },
 		.color		= S5P_FIMC_RGB565,
 		.memplanes	= 1,
@@ -157,59 +159,28 @@
 		.memplanes	= 2,
 		.colplanes	= 2,
 		.flags		= FMT_FLAGS_M2M,
-	},
-};
-
-static struct v4l2_queryctrl fimc_ctrls[] = {
-	{
-		.id		= V4L2_CID_HFLIP,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Horizontal flip",
-		.minimum	= 0,
-		.maximum	= 1,
-		.default_value	= 0,
-	}, {
-		.id		= V4L2_CID_VFLIP,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Vertical flip",
-		.minimum	= 0,
-		.maximum	= 1,
-		.default_value	= 0,
 	}, {
-		.id		= V4L2_CID_ROTATE,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Rotation (CCW)",
-		.minimum	= 0,
-		.maximum	= 270,
-		.step		= 90,
-		.default_value	= 0,
+		.name		= "JPEG encoded data",
+		.fourcc		= V4L2_PIX_FMT_JPEG,
+		.color		= S5P_FIMC_JPEG,
+		.depth		= { 8 },
+		.memplanes	= 1,
+		.colplanes	= 1,
+		.mbus_code	= V4L2_MBUS_FMT_JPEG_1X8,
+		.flags		= FMT_FLAGS_CAM,
 	},
 };
 
-
-static struct v4l2_queryctrl *get_ctrl(int id)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(fimc_ctrls); ++i)
-		if (id == fimc_ctrls[i].id)
-			return &fimc_ctrls[i];
-	return NULL;
-}
-
-int fimc_check_scaler_ratio(int sw, int sh, int dw, int dh, int rot)
+int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh,
+			    int dw, int dh, int rotation)
 {
-	int tx, ty;
+	if (rotation == 90 || rotation == 270)
+		swap(dw, dh);
 
-	if (rot == 90 || rot == 270) {
-		ty = dw;
-		tx = dh;
-	} else {
-		tx = dw;
-		ty = dh;
-	}
+	if (!ctx->scaler.enabled)
+		return (sw == dw && sh == dh) ? 0 : -EINVAL;
 
-	if ((sw >= SCALER_MAX_HRATIO * tx) || (sh >= SCALER_MAX_VRATIO * ty))
+	if ((sw >= SCALER_MAX_HRATIO * dw) || (sh >= SCALER_MAX_VRATIO * dh))
 		return -EINVAL;
 
 	return 0;
@@ -235,10 +206,11 @@
 
 int fimc_set_scaler_info(struct fimc_ctx *ctx)
 {
+	struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
+	struct device *dev = &ctx->fimc_dev->pdev->dev;
 	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;
 
@@ -250,15 +222,14 @@
 		ty = d_frame->height;
 	}
 	if (tx <= 0 || ty <= 0) {
-		v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
-			"invalid target size: %d x %d", tx, ty);
+		dev_err(dev, "Invalid target size: %dx%d", tx, ty);
 		return -EINVAL;
 	}
 
 	sx = s_frame->width;
 	sy = s_frame->height;
 	if (sx <= 0 || sy <= 0) {
-		err("invalid source size: %d x %d", sx, sy);
+		dev_err(dev, "Invalid source size: %dx%d", sx, sy);
 		return -EINVAL;
 	}
 	sc->real_width = sx;
@@ -301,7 +272,6 @@
 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;
@@ -312,54 +282,68 @@
 	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);
+		v4l2_m2m_job_finish(ctx->fimc_dev->m2m.m2m_dev,
+				    ctx->m2m_ctx);
 	}
 }
 
 /* Complete the transaction which has been scheduled for execution. */
-static void fimc_m2m_shutdown(struct fimc_ctx *ctx)
+static int fimc_m2m_shutdown(struct fimc_ctx *ctx)
 {
 	struct fimc_dev *fimc = ctx->fimc_dev;
 	int ret;
 
 	if (!fimc_m2m_pending(fimc))
-		return;
+		return 0;
 
 	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);
+
+	return ret == 0 ? -ETIMEDOUT : ret;
+}
+
+static int start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct fimc_ctx *ctx = q->drv_priv;
+	int ret;
+
+	ret = pm_runtime_get_sync(&ctx->fimc_dev->pdev->dev);
+	return ret > 0 ? 0 : ret;
 }
 
 static int stop_streaming(struct vb2_queue *q)
 {
 	struct fimc_ctx *ctx = q->drv_priv;
+	int ret;
 
-	fimc_m2m_shutdown(ctx);
+	ret = fimc_m2m_shutdown(ctx);
+	if (ret == -ETIMEDOUT)
+		fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
 
+	pm_runtime_put(&ctx->fimc_dev->pdev->dev);
 	return 0;
 }
 
-static void fimc_capture_irq_handler(struct fimc_dev *fimc)
+void fimc_capture_irq_handler(struct fimc_dev *fimc, bool final)
 {
 	struct fimc_vid_cap *cap = &fimc->vid_cap;
 	struct fimc_vid_buffer *v_buf;
 	struct timeval *tv;
 	struct timespec ts;
 
+	if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) {
+		wake_up(&fimc->irq_queue);
+		return;
+	}
+
 	if (!list_empty(&cap->active_buf_q) &&
-	    test_bit(ST_CAPT_RUN, &fimc->state)) {
+	    test_bit(ST_CAPT_RUN, &fimc->state) && final) {
 		ktime_get_real_ts(&ts);
 
-		v_buf = active_queue_pop(cap);
+		v_buf = fimc_active_queue_pop(cap);
 
 		tv = &v_buf->vb.v4l2_buf.timestamp;
 		tv->tv_sec = ts.tv_sec;
@@ -369,19 +353,14 @@
 		vb2_buffer_done(&v_buf->vb, VB2_BUF_STATE_DONE);
 	}
 
-	if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) {
-		wake_up(&fimc->irq_queue);
-		return;
-	}
-
 	if (!list_empty(&cap->pending_buf_q)) {
 
-		v_buf = pending_queue_pop(cap);
+		v_buf = fimc_pending_queue_pop(cap);
 		fimc_hw_set_output_addr(fimc, &v_buf->paddr, cap->buf_index);
 		v_buf->index = cap->buf_index;
 
 		/* Move the buffer to the capture active queue */
-		active_queue_add(cap, v_buf);
+		fimc_active_queue_add(cap, v_buf);
 
 		dbg("next frame: %d, done frame: %d",
 		    fimc_hw_get_frame_index(fimc), v_buf->index);
@@ -391,7 +370,8 @@
 	}
 
 	if (cap->active_buf_cnt == 0) {
-		clear_bit(ST_CAPT_RUN, &fimc->state);
+		if (final)
+			clear_bit(ST_CAPT_RUN, &fimc->state);
 
 		if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
 			cap->buf_index = 0;
@@ -399,11 +379,13 @@
 		set_bit(ST_CAPT_RUN, &fimc->state);
 	}
 
+	fimc_capture_config_update(cap->ctx);
+
 	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)
+static irqreturn_t fimc_irq_handler(int irq, void *priv)
 {
 	struct fimc_dev *fimc = priv;
 	struct fimc_vid_cap *cap = &fimc->vid_cap;
@@ -411,9 +393,17 @@
 
 	fimc_hw_clear_irq(fimc);
 
+	spin_lock(&fimc->slock);
+
 	if (test_and_clear_bit(ST_M2M_PEND, &fimc->state)) {
+		if (test_and_clear_bit(ST_M2M_SUSPENDING, &fimc->state)) {
+			set_bit(ST_M2M_SUSPENDED, &fimc->state);
+			wake_up(&fimc->irq_queue);
+			goto out;
+		}
 		ctx = v4l2_m2m_get_curr_priv(fimc->m2m.m2m_dev);
 		if (ctx != NULL) {
+			spin_unlock(&fimc->slock);
 			fimc_m2m_job_finish(ctx, VB2_BUF_STATE_DONE);
 
 			spin_lock(&ctx->slock);
@@ -423,21 +413,16 @@
 			}
 			spin_unlock(&ctx->slock);
 		}
-
 		return IRQ_HANDLED;
-	}
-
-	spin_lock(&fimc->slock);
-
-	if (test_bit(ST_CAPT_PEND, &fimc->state)) {
-		fimc_capture_irq_handler(fimc);
-
+	} else if (test_bit(ST_CAPT_PEND, &fimc->state)) {
+		fimc_capture_irq_handler(fimc,
+				 !test_bit(ST_CAPT_JPEG, &fimc->state));
 		if (cap->active_buf_cnt == 1) {
 			fimc_deactivate_capture(fimc);
 			clear_bit(ST_CAPT_STREAM, &fimc->state);
 		}
 	}
-
+out:
 	spin_unlock(&fimc->slock);
 	return IRQ_HANDLED;
 }
@@ -457,7 +442,7 @@
 	dbg("memplanes= %d, colplanes= %d, pix_size= %d",
 		frame->fmt->memplanes, frame->fmt->colplanes, pix_size);
 
-	paddr->y = vb2_dma_contig_plane_paddr(vb, 0);
+	paddr->y = vb2_dma_contig_plane_dma_addr(vb, 0);
 
 	if (frame->fmt->memplanes == 1) {
 		switch (frame->fmt->colplanes) {
@@ -485,10 +470,10 @@
 		}
 	} else {
 		if (frame->fmt->memplanes >= 2)
-			paddr->cb = vb2_dma_contig_plane_paddr(vb, 1);
+			paddr->cb = vb2_dma_contig_plane_dma_addr(vb, 1);
 
 		if (frame->fmt->memplanes == 3)
-			paddr->cr = vb2_dma_contig_plane_paddr(vb, 2);
+			paddr->cr = vb2_dma_contig_plane_dma_addr(vb, 2);
 	}
 
 	dbg("PHYS_ADDR: y= 0x%X  cb= 0x%X cr= 0x%X ret= %d",
@@ -498,7 +483,7 @@
 }
 
 /* Set order for 1 and 2 plane YCBCR 4:2:2 formats. */
-static void fimc_set_yuv_order(struct fimc_ctx *ctx)
+void fimc_set_yuv_order(struct fimc_ctx *ctx)
 {
 	/* The one only mode supported in SoC. */
 	ctx->in_order_2p = S5P_FIMC_LSB_CRCB;
@@ -540,7 +525,7 @@
 	dbg("ctx->out_order_1p= %d", ctx->out_order_1p);
 }
 
-static void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
+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;
@@ -606,9 +591,6 @@
 		fimc_set_yuv_order(ctx);
 	}
 
-	/* Input DMA mode is not allowed when the scaler is disabled. */
-	ctx->scaler.enabled = 1;
-
 	if (flags & FIMC_SRC_ADDR) {
 		vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
 		ret = fimc_prepare_addr(ctx, vb, s_frame, &s_frame->paddr);
@@ -635,10 +617,10 @@
 		return;
 
 	fimc = ctx->fimc_dev;
-
-	spin_lock_irqsave(&ctx->slock, flags);
+	spin_lock_irqsave(&fimc->slock, flags);
 	set_bit(ST_M2M_PEND, &fimc->state);
 
+	spin_lock(&ctx->slock);
 	ctx->state |= (FIMC_SRC_ADDR | FIMC_DST_ADDR);
 	ret = fimc_prepare_config(ctx, ctx->state);
 	if (ret)
@@ -649,8 +631,6 @@
 		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) {
@@ -665,7 +645,7 @@
 		fimc_hw_set_mainscaler(ctx);
 		fimc_hw_set_target_format(ctx);
 		fimc_hw_set_rotation(ctx);
-		fimc_hw_set_effect(ctx);
+		fimc_hw_set_effect(ctx, false);
 	}
 
 	fimc_hw_set_output_path(ctx);
@@ -680,10 +660,9 @@
 	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);
+	spin_unlock(&ctx->slock);
+	spin_unlock_irqrestore(&fimc->slock, flags);
 }
 
 static void fimc_job_abort(void *priv)
@@ -691,9 +670,9 @@
 	fimc_m2m_shutdown(priv);
 }
 
-static int fimc_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
-			    unsigned int *num_planes, unsigned long sizes[],
-			    void *allocators[])
+static int fimc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+			    unsigned int *num_buffers, unsigned int *num_planes,
+			    unsigned int sizes[], void *allocators[])
 {
 	struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
 	struct fimc_frame *f;
@@ -762,146 +741,296 @@
 	.wait_prepare	 = fimc_unlock,
 	.wait_finish	 = fimc_lock,
 	.stop_streaming	 = stop_streaming,
+	.start_streaming = start_streaming,
 };
 
-static int fimc_m2m_querycap(struct file *file, void *priv,
-			   struct v4l2_capability *cap)
+/*
+ * V4L2 controls handling
+ */
+#define ctrl_to_ctx(__ctrl) \
+	container_of((__ctrl)->handler, struct fimc_ctx, ctrl_handler)
+
+static int fimc_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct fimc_ctx *ctx = file->private_data;
+	struct fimc_ctx *ctx = ctrl_to_ctx(ctrl);
+	struct fimc_dev *fimc = ctx->fimc_dev;
+	struct samsung_fimc_variant *variant = fimc->variant;
+	unsigned long flags;
+	int ret = 0;
+
+	if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
+		return 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_HFLIP:
+		spin_lock_irqsave(&ctx->slock, flags);
+		ctx->hflip = ctrl->val;
+		break;
+
+	case V4L2_CID_VFLIP:
+		spin_lock_irqsave(&ctx->slock, flags);
+		ctx->vflip = ctrl->val;
+		break;
+
+	case V4L2_CID_ROTATE:
+		if (fimc_capture_pending(fimc) ||
+		    fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
+			ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width,
+					ctx->s_frame.height, ctx->d_frame.width,
+					ctx->d_frame.height, ctrl->val);
+		}
+		if (ret) {
+			v4l2_err(fimc->m2m.vfd, "Out of scaler range\n");
+			return -EINVAL;
+		}
+		if ((ctrl->val == 90 || ctrl->val == 270) &&
+		    !variant->has_out_rot)
+			return -EINVAL;
+		spin_lock_irqsave(&ctx->slock, flags);
+		ctx->rotation = ctrl->val;
+		break;
+
+	default:
+		v4l2_err(fimc->v4l2_dev, "Invalid control: 0x%X\n", ctrl->id);
+		return -EINVAL;
+	}
+	ctx->state |= FIMC_PARAMS;
+	set_bit(ST_CAPT_APPLY_CFG, &fimc->state);
+	spin_unlock_irqrestore(&ctx->slock, flags);
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops fimc_ctrl_ops = {
+	.s_ctrl = fimc_s_ctrl,
+};
+
+int fimc_ctrls_create(struct fimc_ctx *ctx)
+{
+	if (ctx->ctrls_rdy)
+		return 0;
+	v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3);
+
+	ctx->ctrl_rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
+				     V4L2_CID_HFLIP, 0, 1, 1, 0);
+	ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
+				    V4L2_CID_VFLIP, 0, 1, 1, 0);
+	ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
+				    V4L2_CID_ROTATE, 0, 270, 90, 0);
+	ctx->ctrls_rdy = ctx->ctrl_handler.error == 0;
+
+	return ctx->ctrl_handler.error;
+}
+
+void fimc_ctrls_delete(struct fimc_ctx *ctx)
+{
+	if (ctx->ctrls_rdy) {
+		v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+		ctx->ctrls_rdy = false;
+	}
+}
+
+void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
+{
+	if (!ctx->ctrls_rdy)
+		return;
+
+	mutex_lock(&ctx->ctrl_handler.lock);
+	v4l2_ctrl_activate(ctx->ctrl_rotate, active);
+	v4l2_ctrl_activate(ctx->ctrl_hflip, active);
+	v4l2_ctrl_activate(ctx->ctrl_vflip, active);
+
+	if (active) {
+		ctx->rotation = ctx->ctrl_rotate->val;
+		ctx->hflip    = ctx->ctrl_hflip->val;
+		ctx->vflip    = ctx->ctrl_vflip->val;
+	} else {
+		ctx->rotation = 0;
+		ctx->hflip    = 0;
+		ctx->vflip    = 0;
+	}
+	mutex_unlock(&ctx->ctrl_handler.lock);
+}
+
+/*
+ * V4L2 ioctl handlers
+ */
+static int fimc_m2m_querycap(struct file *file, void *fh,
+			     struct v4l2_capability *cap)
+{
+	struct fimc_ctx *ctx = fh_to_ctx(fh);
 	struct fimc_dev *fimc = ctx->fimc_dev;
 
 	strncpy(cap->driver, fimc->pdev->name, sizeof(cap->driver) - 1);
 	strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1);
 	cap->bus_info[0] = 0;
 	cap->capabilities = V4L2_CAP_STREAMING |
-		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_mplane(struct file *file, void *priv,
-				struct v4l2_fmtdesc *f)
+static int fimc_m2m_enum_fmt_mplane(struct file *file, void *priv,
+				    struct v4l2_fmtdesc *f)
 {
 	struct fimc_fmt *fmt;
 
-	if (f->index >= ARRAY_SIZE(fimc_formats))
+	fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_M2M, f->index);
+	if (!fmt)
 		return -EINVAL;
 
-	fmt = &fimc_formats[f->index];
 	strncpy(f->description, fmt->name, sizeof(f->description) - 1);
 	f->pixelformat = fmt->fourcc;
-
 	return 0;
 }
 
-int fimc_vidioc_g_fmt_mplane(struct file *file, void *priv,
-			     struct v4l2_format *f)
+int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f)
 {
-	struct fimc_ctx *ctx = priv;
-	struct fimc_frame *frame;
-	struct v4l2_pix_format_mplane *pixm;
+	struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
 	int i;
 
-	frame = ctx_get_frame(ctx, f->type);
-	if (IS_ERR(frame))
-		return PTR_ERR(frame);
-
-	pixm = &f->fmt.pix_mp;
-
-	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;
+	pixm->width = frame->o_width;
+	pixm->height = frame->o_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;
-
+		int bpl = frame->f_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;
 	}
-
 	return 0;
 }
 
-struct fimc_fmt *find_format(struct v4l2_format *f, unsigned int mask)
+void fimc_fill_frame(struct fimc_frame *frame, struct v4l2_format *f)
 {
-	struct fimc_fmt *fmt;
-	unsigned int i;
+	struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
 
-	for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) {
-		fmt = &fimc_formats[i];
-		if (fmt->fourcc == f->fmt.pix_mp.pixelformat &&
-		   (fmt->flags & mask))
-			break;
+	frame->f_width  = pixm->plane_fmt[0].bytesperline;
+	if (frame->fmt->colplanes == 1)
+		frame->f_width = (frame->f_width * 8) / frame->fmt->depth[0];
+	frame->f_height	= pixm->height;
+	frame->width    = pixm->width;
+	frame->height   = pixm->height;
+	frame->o_width  = pixm->width;
+	frame->o_height = pixm->height;
+	frame->offs_h   = 0;
+	frame->offs_v   = 0;
+}
+
+/**
+ * fimc_adjust_mplane_format - adjust bytesperline/sizeimage for each plane
+ * @fmt: fimc pixel format description (input)
+ * @width: requested pixel width
+ * @height: requested pixel height
+ * @pix: multi-plane format to adjust
+ */
+void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height,
+			       struct v4l2_pix_format_mplane *pix)
+{
+	u32 bytesperline = 0;
+	int i;
+
+	pix->colorspace	= V4L2_COLORSPACE_JPEG;
+	pix->field = V4L2_FIELD_NONE;
+	pix->num_planes = fmt->memplanes;
+	pix->height = height;
+	pix->width = width;
+
+	for (i = 0; i < pix->num_planes; ++i) {
+		u32 bpl = pix->plane_fmt[i].bytesperline;
+		u32 *sizeimage = &pix->plane_fmt[i].sizeimage;
+
+		if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width))
+			bpl = pix->width; /* Planar */
+
+		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. */
+			bytesperline = bpl;
+
+		pix->plane_fmt[i].bytesperline = bytesperline;
+		*sizeimage = (pix->width * pix->height * fmt->depth[i]) / 8;
 	}
+}
 
-	return (i == ARRAY_SIZE(fimc_formats)) ? NULL : fmt;
+static int fimc_m2m_g_fmt_mplane(struct file *file, void *fh,
+				 struct v4l2_format *f)
+{
+	struct fimc_ctx *ctx = fh_to_ctx(fh);
+	struct fimc_frame *frame = ctx_get_frame(ctx, f->type);
+
+	if (IS_ERR(frame))
+		return PTR_ERR(frame);
+
+	return fimc_fill_format(frame, f);
 }
 
-struct fimc_fmt *find_mbus_format(struct v4l2_mbus_framefmt *f,
-				  unsigned int mask)
+/**
+ * fimc_find_format - lookup fimc color format by fourcc or media bus format
+ * @pixelformat: fourcc to match, ignored if null
+ * @mbus_code: media bus code to match, ignored if null
+ * @mask: the color flags to match
+ * @index: offset in the fimc_formats array, ignored if negative
+ */
+struct fimc_fmt *fimc_find_format(u32 *pixelformat, u32 *mbus_code,
+				  unsigned int mask, int index)
 {
-	struct fimc_fmt *fmt;
+	struct fimc_fmt *fmt, *def_fmt = NULL;
 	unsigned int i;
+	int id = 0;
+
+	if (index >= ARRAY_SIZE(fimc_formats))
+		return NULL;
 
 	for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) {
 		fmt = &fimc_formats[i];
-		if (fmt->mbus_code == f->code && (fmt->flags & mask))
-			break;
+		if (!(fmt->flags & mask))
+			continue;
+		if (pixelformat && fmt->fourcc == *pixelformat)
+			return fmt;
+		if (mbus_code && fmt->mbus_code == *mbus_code)
+			return fmt;
+		if (index == id)
+			def_fmt = fmt;
+		id++;
 	}
-
-	return (i == ARRAY_SIZE(fimc_formats)) ? NULL : fmt;
+	return def_fmt;
 }
 
-
-int fimc_vidioc_try_fmt_mplane(struct file *file, void *priv,
-			       struct v4l2_format *f)
+static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, 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_mplane *pix = &f->fmt.pix_mp;
 	struct fimc_fmt *fmt;
-	u32 max_width, mod_x, mod_y, mask;
-	int i, is_output = 0;
-
+	u32 max_w, mod_x, mod_y;
 
-	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_MPLANE) {
+	if (!IS_M2M(f->type))
 		return -EINVAL;
-	}
 
 	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);
+	fmt = fimc_find_format(&pix->pixelformat, NULL, FMT_FLAGS_M2M, 0);
+	if (WARN(fmt == NULL, "Pixel format lookup failed"))
 		return -EINVAL;
-	}
 
 	if (pix->field == V4L2_FIELD_ANY)
 		pix->field = V4L2_FIELD_NONE;
-	else if (V4L2_FIELD_NONE != pix->field)
+	else if (pix->field != V4L2_FIELD_NONE)
 		return -EINVAL;
 
-	if (is_output) {
-		max_width = variant->pix_limit->scaler_dis_w;
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		max_w = variant->pix_limit->scaler_dis_w;
 		mod_x = ffs(variant->min_inp_pixsize) - 1;
 	} else {
-		max_width = variant->pix_limit->out_rot_dis_w;
+		max_w = variant->pix_limit->out_rot_dis_w;
 		mod_x = ffs(variant->min_out_pixsize) - 1;
 	}
 
@@ -909,75 +1038,56 @@
 		mod_x = 6; /* 64 x 32 pixels tile */
 		mod_y = 5;
 	} else {
-		if (fimc->id == 1 && variant->pix_hoff)
+		if (variant->min_vsize_align == 1)
 			mod_y = fimc_fmt_is_rgb(fmt->color) ? 0 : 1;
 		else
-			mod_y = mod_x;
+			mod_y = ffs(variant->min_vsize_align) - 1;
 	}
 
-	dbg("mod_x: %d, mod_y: %d, max_w: %d", mod_x, mod_y, max_width);
-
-	v4l_bound_align_image(&pix->width, 16, max_width, mod_x,
+	v4l_bound_align_image(&pix->width, 16, max_w, mod_x,
 		&pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0);
 
-	pix->num_planes = fmt->memplanes;
-	pix->colorspace	= V4L2_COLORSPACE_JPEG;
-
-
-	for (i = 0; i < pix->num_planes; ++i) {
-		u32 bpl = pix->plane_fmt[i].bytesperline;
-		u32 *sizeimage = &pix->plane_fmt[i].sizeimage;
-
-		if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width))
-			bpl = pix->width; /* Planar */
-
-		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;
+	fimc_adjust_mplane_format(fmt, pix->width, pix->height, &f->fmt.pix_mp);
+	return 0;
+}
 
-		pix->plane_fmt[i].bytesperline = mod_x;
-		*sizeimage = (pix->width * pix->height * fmt->depth[i]) / 8;
-	}
+static int fimc_m2m_try_fmt_mplane(struct file *file, void *fh,
+				   struct v4l2_format *f)
+{
+	struct fimc_ctx *ctx = fh_to_ctx(fh);
 
-	return 0;
+	return fimc_try_fmt_mplane(ctx, f);
 }
 
-static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
+static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh,
 				 struct v4l2_format *f)
 {
-	struct fimc_ctx *ctx = priv;
+	struct fimc_ctx *ctx = fh_to_ctx(fh);
 	struct fimc_dev *fimc = ctx->fimc_dev;
 	struct vb2_queue *vq;
 	struct fimc_frame *frame;
 	struct v4l2_pix_format_mplane *pix;
 	int i, ret = 0;
 
-	ret = fimc_vidioc_try_fmt_mplane(file, priv, f);
+	ret = fimc_try_fmt_mplane(ctx, f);
 	if (ret)
 		return ret;
 
 	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
 
 	if (vb2_is_busy(vq)) {
-		v4l2_err(&fimc->m2m.v4l2_dev, "queue (%d) busy\n", f->type);
+		v4l2_err(fimc->m2m.vfd, "queue (%d) busy\n", f->type);
 		return -EBUSY;
 	}
 
-	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 		frame = &ctx->s_frame;
-	} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+	else
 		frame = &ctx->d_frame;
-	} else {
-		v4l2_err(&fimc->m2m.v4l2_dev,
-			 "Wrong buffer/video queue type (%d)\n", f->type);
-		return -EINVAL;
-	}
 
 	pix = &f->fmt.pix_mp;
-	frame->fmt = find_format(f, FMT_FLAGS_M2M);
+	frame->fmt = fimc_find_format(&pix->pixelformat, NULL,
+				      FMT_FLAGS_M2M, 0);
 	if (!frame->fmt)
 		return -EINVAL;
 
@@ -986,15 +1096,9 @@
 			(pix->width * pix->height * frame->fmt->depth[i]) / 8;
 	}
 
-	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->offs_h	= 0;
-	frame->offs_v	= 0;
+	fimc_fill_frame(frame, f);
+
+	ctx->scaler.enabled = 1;
 
 	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 		fimc_ctx_state_lock_set(FIMC_PARAMS | FIMC_DST_FMT, ctx);
@@ -1006,39 +1110,42 @@
 	return 0;
 }
 
-static int fimc_m2m_reqbufs(struct file *file, void *priv,
-			  struct v4l2_requestbuffers *reqbufs)
+static int fimc_m2m_reqbufs(struct file *file, void *fh,
+			    struct v4l2_requestbuffers *reqbufs)
 {
-	struct fimc_ctx *ctx = priv;
+	struct fimc_ctx *ctx = fh_to_ctx(fh);
+
 	return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
 }
 
-static int fimc_m2m_querybuf(struct file *file, void *priv,
-			   struct v4l2_buffer *buf)
+static int fimc_m2m_querybuf(struct file *file, void *fh,
+			     struct v4l2_buffer *buf)
 {
-	struct fimc_ctx *ctx = priv;
+	struct fimc_ctx *ctx = fh_to_ctx(fh);
+
 	return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
 }
 
-static int fimc_m2m_qbuf(struct file *file, void *priv,
-			  struct v4l2_buffer *buf)
+static int fimc_m2m_qbuf(struct file *file, void *fh,
+			 struct v4l2_buffer *buf)
 {
-	struct fimc_ctx *ctx = priv;
+	struct fimc_ctx *ctx = fh_to_ctx(fh);
 
 	return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
 }
 
-static int fimc_m2m_dqbuf(struct file *file, void *priv,
-			   struct v4l2_buffer *buf)
+static int fimc_m2m_dqbuf(struct file *file, void *fh,
+			  struct v4l2_buffer *buf)
 {
-	struct fimc_ctx *ctx = priv;
+	struct fimc_ctx *ctx = fh_to_ctx(fh);
+
 	return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
 }
 
-static int fimc_m2m_streamon(struct file *file, void *priv,
-			   enum v4l2_buf_type type)
+static int fimc_m2m_streamon(struct file *file, void *fh,
+			     enum v4l2_buf_type type)
 {
-	struct fimc_ctx *ctx = priv;
+	struct fimc_ctx *ctx = fh_to_ctx(fh);
 
 	/* The source and target color format need to be set */
 	if (V4L2_TYPE_IS_OUTPUT(type)) {
@@ -1051,149 +1158,19 @@
 	return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
 }
 
-static int fimc_m2m_streamoff(struct file *file, void *priv,
+static int fimc_m2m_streamoff(struct file *file, void *fh,
 			    enum v4l2_buf_type type)
 {
-	struct fimc_ctx *ctx = priv;
-	return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
-}
-
-int fimc_vidioc_queryctrl(struct file *file, void *priv,
-			    struct v4l2_queryctrl *qc)
-{
-	struct fimc_ctx *ctx = priv;
-	struct v4l2_queryctrl *c;
-	int ret = -EINVAL;
-
-	c = get_ctrl(qc->id);
-	if (c) {
-		*qc = *c;
-		return 0;
-	}
-
-	if (fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx)) {
-		return v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,
-					core, queryctrl, qc);
-	}
-	return ret;
-}
-
-int fimc_vidioc_g_ctrl(struct file *file, void *priv,
-			 struct v4l2_control *ctrl)
-{
-	struct fimc_ctx *ctx = priv;
-	struct fimc_dev *fimc = ctx->fimc_dev;
-
-	switch (ctrl->id) {
-	case V4L2_CID_HFLIP:
-		ctrl->value = (FLIP_X_AXIS & ctx->flip) ? 1 : 0;
-		break;
-	case V4L2_CID_VFLIP:
-		ctrl->value = (FLIP_Y_AXIS & ctx->flip) ? 1 : 0;
-		break;
-	case V4L2_CID_ROTATE:
-		ctrl->value = ctx->rotation;
-		break;
-	default:
-		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");
-			return -EINVAL;
-		}
-	}
-	dbg("ctrl->value= %d", ctrl->value);
-
-	return 0;
-}
-
-int check_ctrl_val(struct fimc_ctx *ctx,  struct v4l2_control *ctrl)
-{
-	struct v4l2_queryctrl *c;
-	c = get_ctrl(ctrl->id);
-	if (!c)
-		return -EINVAL;
-
-	if (ctrl->value < c->minimum || ctrl->value > c->maximum
-		|| (c->step != 0 && ctrl->value % c->step != 0)) {
-		v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
-		"Invalid control value\n");
-		return -ERANGE;
-	}
-
-	return 0;
-}
-
-int fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_control *ctrl)
-{
-	struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
-	struct fimc_dev *fimc = ctx->fimc_dev;
-	int ret = 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_HFLIP:
-		if (ctrl->value)
-			ctx->flip |= FLIP_X_AXIS;
-		else
-			ctx->flip &= ~FLIP_X_AXIS;
-		break;
-
-	case V4L2_CID_VFLIP:
-		if (ctrl->value)
-			ctx->flip |= FLIP_Y_AXIS;
-		else
-			ctx->flip &= ~FLIP_Y_AXIS;
-		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))
-			return -EINVAL;
-		ctx->rotation = ctrl->value;
-		break;
-
-	default:
-		v4l2_err(&fimc->m2m.v4l2_dev, "Invalid control\n");
-		return -EINVAL;
-	}
-
-	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 fimc_ctx *ctx = priv;
-	int ret = 0;
-
-	ret = check_ctrl_val(ctx, ctrl);
-	if (ret)
-		return ret;
+	struct fimc_ctx *ctx = fh_to_ctx(fh);
 
-	ret = fimc_s_ctrl(ctx, ctrl);
-	return 0;
+	return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
 }
 
 static int fimc_m2m_cropcap(struct file *file, void *fh,
-			struct v4l2_cropcap *cr)
+			    struct v4l2_cropcap *cr)
 {
+	struct fimc_ctx *ctx = fh_to_ctx(fh);
 	struct fimc_frame *frame;
-	struct fimc_ctx *ctx = fh;
 
 	frame = ctx_get_frame(ctx, cr->type);
 	if (IS_ERR(frame))
@@ -1201,8 +1178,8 @@
 
 	cr->bounds.left		= 0;
 	cr->bounds.top		= 0;
-	cr->bounds.width	= frame->f_width;
-	cr->bounds.height	= frame->f_height;
+	cr->bounds.width	= frame->o_width;
+	cr->bounds.height	= frame->o_height;
 	cr->defrect		= cr->bounds;
 
 	return 0;
@@ -1210,8 +1187,8 @@
 
 static int fimc_m2m_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
 {
+	struct fimc_ctx *ctx = fh_to_ctx(fh);
 	struct fimc_frame *frame;
-	struct fimc_ctx *ctx = file->private_data;
 
 	frame = ctx_get_frame(ctx, cr->type);
 	if (IS_ERR(frame))
@@ -1225,26 +1202,21 @@
 	return 0;
 }
 
-int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
+static int fimc_m2m_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
 {
 	struct fimc_dev *fimc = ctx->fimc_dev;
 	struct fimc_frame *f;
 	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,
+		v4l2_err(fimc->m2m.vfd,
 			"doesn't support negative values for top & left\n");
 		return -EINVAL;
 	}
-
-	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->d_frame;
+	else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 		f = &ctx->s_frame;
 	else
 		return -EINVAL;
@@ -1253,15 +1225,10 @@
 		fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize;
 
 	/* 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;
-	}
+	if (fimc->variant->min_vsize_align == 1)
+		halign = fimc_fmt_is_rgb(f->fmt->color) ? 0 : 1;
+	else
+		halign = ffs(fimc->variant->min_vsize_align) - 1;
 
 	for (i = 0; i < f->fmt->colplanes; i++)
 		depth += f->fmt->depth[i];
@@ -1278,7 +1245,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, is_capture_ctx ? 16 : 8);
+	cr->c.top  = round_down(cr->c.top, fimc->variant->hor_offs_align);
 
 	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,
@@ -1289,12 +1256,12 @@
 
 static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
 {
-	struct fimc_ctx *ctx = file->private_data;
+	struct fimc_ctx *ctx = fh_to_ctx(fh);
 	struct fimc_dev *fimc = ctx->fimc_dev;
 	struct fimc_frame *f;
 	int ret;
 
-	ret = fimc_try_crop(ctx, cr);
+	ret = fimc_m2m_try_crop(ctx, cr);
 	if (ret)
 		return ret;
 
@@ -1304,18 +1271,16 @@
 	/* 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);
+			ret = fimc_check_scaler_ratio(ctx, 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);
+			ret = fimc_check_scaler_ratio(ctx, 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\n");
+			v4l2_err(fimc->m2m.vfd, "Out of scaler range\n");
 			return -EINVAL;
 		}
 	}
@@ -1333,14 +1298,14 @@
 static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
 	.vidioc_querycap		= fimc_m2m_querycap,
 
-	.vidioc_enum_fmt_vid_cap_mplane	= fimc_vidioc_enum_fmt_mplane,
-	.vidioc_enum_fmt_vid_out_mplane	= fimc_vidioc_enum_fmt_mplane,
+	.vidioc_enum_fmt_vid_cap_mplane	= fimc_m2m_enum_fmt_mplane,
+	.vidioc_enum_fmt_vid_out_mplane	= fimc_m2m_enum_fmt_mplane,
 
-	.vidioc_g_fmt_vid_cap_mplane	= fimc_vidioc_g_fmt_mplane,
-	.vidioc_g_fmt_vid_out_mplane	= fimc_vidioc_g_fmt_mplane,
+	.vidioc_g_fmt_vid_cap_mplane	= fimc_m2m_g_fmt_mplane,
+	.vidioc_g_fmt_vid_out_mplane	= fimc_m2m_g_fmt_mplane,
 
-	.vidioc_try_fmt_vid_cap_mplane	= fimc_vidioc_try_fmt_mplane,
-	.vidioc_try_fmt_vid_out_mplane	= fimc_vidioc_try_fmt_mplane,
+	.vidioc_try_fmt_vid_cap_mplane	= fimc_m2m_try_fmt_mplane,
+	.vidioc_try_fmt_vid_out_mplane	= fimc_m2m_try_fmt_mplane,
 
 	.vidioc_s_fmt_vid_cap_mplane	= fimc_m2m_s_fmt_mplane,
 	.vidioc_s_fmt_vid_out_mplane	= fimc_m2m_s_fmt_mplane,
@@ -1354,10 +1319,6 @@
 	.vidioc_streamon		= fimc_m2m_streamon,
 	.vidioc_streamoff		= fimc_m2m_streamoff,
 
-	.vidioc_queryctrl		= fimc_vidioc_queryctrl,
-	.vidioc_g_ctrl			= fimc_vidioc_g_ctrl,
-	.vidioc_s_ctrl			= fimc_m2m_s_ctrl,
-
 	.vidioc_g_crop			= fimc_m2m_g_crop,
 	.vidioc_s_crop			= fimc_m2m_s_crop,
 	.vidioc_cropcap			= fimc_m2m_cropcap
@@ -1396,7 +1357,8 @@
 static int fimc_m2m_open(struct file *file)
 {
 	struct fimc_dev *fimc = video_drvdata(file);
-	struct fimc_ctx *ctx = NULL;
+	struct fimc_ctx *ctx;
+	int ret;
 
 	dbg("pid: %d, state: 0x%lx, refcnt: %d",
 		task_pid_nr(current), fimc->state, fimc->vid_cap.refcnt);
@@ -1408,19 +1370,24 @@
 	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)
 		return -ENOMEM;
+	v4l2_fh_init(&ctx->fh, fimc->m2m.vfd);
+	ret = fimc_ctrls_create(ctx);
+	if (ret)
+		goto error_fh;
+
+	/* Use separate control handler per file handle */
+	ctx->fh.ctrl_handler = &ctx->ctrl_handler;
+	file->private_data = &ctx->fh;
+	v4l2_fh_add(&ctx->fh);
 
-	file->private_data = ctx;
 	ctx->fimc_dev = fimc;
 	/* Default color format */
 	ctx->s_frame.fmt = &fimc_formats[0];
 	ctx->d_frame.fmt = &fimc_formats[0];
-	/* Setup the device context for mem2mem mode. */
+	/* Setup the device context for memory-to-memory mode */
 	ctx->state = FIMC_CTX_M2M;
 	ctx->flags = 0;
 	ctx->in_path = FIMC_DMA;
@@ -1429,34 +1396,46 @@
 
 	ctx->m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init);
 	if (IS_ERR(ctx->m2m_ctx)) {
-		int err = PTR_ERR(ctx->m2m_ctx);
-		kfree(ctx);
-		return err;
+		ret = PTR_ERR(ctx->m2m_ctx);
+		goto error_c;
 	}
 
+	if (fimc->m2m.refcnt++ == 0)
+		set_bit(ST_M2M_RUN, &fimc->state);
 	return 0;
+
+error_c:
+	fimc_ctrls_delete(ctx);
+error_fh:
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	kfree(ctx);
+	return ret;
 }
 
 static int fimc_m2m_release(struct file *file)
 {
-	struct fimc_ctx *ctx = file->private_data;
+	struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
 	struct fimc_dev *fimc = ctx->fimc_dev;
 
 	dbg("pid: %d, state: 0x%lx, refcnt= %d",
 		task_pid_nr(current), fimc->state, fimc->m2m.refcnt);
 
 	v4l2_m2m_ctx_release(ctx->m2m_ctx);
-	kfree(ctx);
-	if (--fimc->m2m.refcnt <= 0)
-		clear_bit(ST_OUTDMA_RUN, &fimc->state);
+	fimc_ctrls_delete(ctx);
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
 
+	if (--fimc->m2m.refcnt <= 0)
+		clear_bit(ST_M2M_RUN, &fimc->state);
+	kfree(ctx);
 	return 0;
 }
 
 static unsigned int fimc_m2m_poll(struct file *file,
-				     struct poll_table_struct *wait)
+				  struct poll_table_struct *wait)
 {
-	struct fimc_ctx *ctx = file->private_data;
+	struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
 
 	return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
 }
@@ -1464,7 +1443,7 @@
 
 static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	struct fimc_ctx *ctx = file->private_data;
+	struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
 
 	return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
 }
@@ -1483,92 +1462,73 @@
 	.job_abort	= fimc_job_abort,
 };
 
-static int fimc_register_m2m_device(struct fimc_dev *fimc)
+int fimc_register_m2m_device(struct fimc_dev *fimc,
+			     struct v4l2_device *v4l2_dev)
 {
 	struct video_device *vfd;
 	struct platform_device *pdev;
-	struct v4l2_device *v4l2_dev;
 	int ret = 0;
 
 	if (!fimc)
 		return -ENODEV;
 
 	pdev = fimc->pdev;
-	v4l2_dev = &fimc->m2m.v4l2_dev;
-
-	/* set name if it is empty */
-	if (!v4l2_dev->name[0])
-		snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
-			 "%s.m2m", dev_name(&pdev->dev));
-
-	ret = v4l2_device_register(&pdev->dev, v4l2_dev);
-	if (ret)
-		goto err_m2m_r1;
+	fimc->v4l2_dev = v4l2_dev;
 
 	vfd = video_device_alloc();
 	if (!vfd) {
 		v4l2_err(v4l2_dev, "Failed to allocate video device\n");
-		goto err_m2m_r1;
+		return -ENOMEM;
 	}
 
 	vfd->fops	= &fimc_m2m_fops;
 	vfd->ioctl_ops	= &fimc_m2m_ioctl_ops;
+	vfd->v4l2_dev	= v4l2_dev;
 	vfd->minor	= -1;
 	vfd->release	= video_device_release;
 	vfd->lock	= &fimc->lock;
 
-	snprintf(vfd->name, sizeof(vfd->name), "%s:m2m", dev_name(&pdev->dev));
-
+	snprintf(vfd->name, sizeof(vfd->name), "%s.m2m", dev_name(&pdev->dev));
 	video_set_drvdata(vfd, fimc);
-	platform_set_drvdata(pdev, fimc);
 
 	fimc->m2m.vfd = vfd;
 	fimc->m2m.m2m_dev = v4l2_m2m_init(&m2m_ops);
 	if (IS_ERR(fimc->m2m.m2m_dev)) {
 		v4l2_err(v4l2_dev, "failed to initialize v4l2-m2m device\n");
 		ret = PTR_ERR(fimc->m2m.m2m_dev);
-		goto err_m2m_r2;
-	}
-
-	ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
-	if (ret) {
-		v4l2_err(v4l2_dev,
-			 "%s(): failed to register video device\n", __func__);
-		goto err_m2m_r3;
+		goto err_init;
 	}
-	v4l2_info(v4l2_dev,
-		  "FIMC m2m driver registered as /dev/video%d\n", vfd->num);
 
-	return 0;
+	ret = media_entity_init(&vfd->entity, 0, NULL, 0);
+	if (!ret)
+		return 0;
 
-err_m2m_r3:
 	v4l2_m2m_release(fimc->m2m.m2m_dev);
-err_m2m_r2:
+err_init:
 	video_device_release(fimc->m2m.vfd);
-err_m2m_r1:
-	v4l2_device_unregister(v4l2_dev);
-
 	return ret;
 }
 
-static void fimc_unregister_m2m_device(struct fimc_dev *fimc)
+void fimc_unregister_m2m_device(struct fimc_dev *fimc)
 {
-	if (fimc) {
+	if (!fimc)
+		return;
+
+	if (fimc->m2m.m2m_dev)
 		v4l2_m2m_release(fimc->m2m.m2m_dev);
+	if (fimc->m2m.vfd) {
+		media_entity_cleanup(&fimc->m2m.vfd->entity);
+		/* Can also be called if video device wasn't registered */
 		video_unregister_device(fimc->m2m.vfd);
-
-		v4l2_device_unregister(&fimc->m2m.v4l2_dev);
 	}
 }
 
-static void fimc_clk_release(struct fimc_dev *fimc)
+static void fimc_clk_put(struct fimc_dev *fimc)
 {
 	int i;
 	for (i = 0; i < fimc->num_clocks; i++) {
-		if (fimc->clock[i]) {
-			clk_disable(fimc->clock[i]);
+		if (fimc->clock[i])
 			clk_put(fimc->clock[i]);
-		}
 	}
 }
 
@@ -1577,15 +1537,50 @@
 	int i;
 	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]);
+		if (!IS_ERR_OR_NULL(fimc->clock[i]))
 			continue;
-		}
 		dev_err(&fimc->pdev->dev, "failed to get fimc clock: %s\n",
 			fimc_clocks[i]);
 		return -ENXIO;
 	}
+
+	return 0;
+}
+
+static int fimc_m2m_suspend(struct fimc_dev *fimc)
+{
+	unsigned long flags;
+	int timeout;
+
+	spin_lock_irqsave(&fimc->slock, flags);
+	if (!fimc_m2m_pending(fimc)) {
+		spin_unlock_irqrestore(&fimc->slock, flags);
+		return 0;
+	}
+	clear_bit(ST_M2M_SUSPENDED, &fimc->state);
+	set_bit(ST_M2M_SUSPENDING, &fimc->state);
+	spin_unlock_irqrestore(&fimc->slock, flags);
+
+	timeout = wait_event_timeout(fimc->irq_queue,
+			     test_bit(ST_M2M_SUSPENDED, &fimc->state),
+			     FIMC_SHUTDOWN_TIMEOUT);
+
+	clear_bit(ST_M2M_SUSPENDING, &fimc->state);
+	return timeout == 0 ? -EAGAIN : 0;
+}
+
+static int fimc_m2m_resume(struct fimc_dev *fimc)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&fimc->slock, flags);
+	/* Clear for full H/W setup in first run after resume */
+	fimc->m2m.ctx = NULL;
+	spin_unlock_irqrestore(&fimc->slock, flags);
+
+	if (test_and_clear_bit(ST_M2M_SUSPENDED, &fimc->state))
+		fimc_m2m_job_finish(fimc->m2m.ctx,
+				    VB2_BUF_STATE_ERROR);
 	return 0;
 }
 
@@ -1596,7 +1591,6 @@
 	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__);
 
@@ -1614,15 +1608,15 @@
 		return -ENOMEM;
 
 	fimc->id = pdev->id;
+
 	fimc->variant = drv_data->variant[fimc->id];
 	fimc->pdev = pdev;
 	pdata = pdev->dev.platform_data;
 	fimc->pdata = pdata;
-	fimc->state = ST_IDLE;
+
 
 	init_waitqueue_head(&fimc->irq_queue);
 	spin_lock_init(&fimc->slock);
-
 	mutex_init(&fimc->lock);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1647,71 +1641,51 @@
 		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[CLK_BUS], drv_data->lclk_frequency);
-
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!res) {
 		dev_err(&pdev->dev, "failed to get IRQ resource\n");
 		ret = -ENXIO;
-		goto err_clk;
+		goto err_regs_unmap;
 	}
 	fimc->irq = res->start;
 
-	fimc_hw_reset(fimc);
+	fimc->num_clocks = MAX_FIMC_CLOCKS;
+	ret = fimc_clk_get(fimc);
+	if (ret)
+		goto err_regs_unmap;
+	clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency);
+	clk_enable(fimc->clock[CLK_BUS]);
 
-	ret = request_irq(fimc->irq, fimc_isr, 0, pdev->name, fimc);
+	platform_set_drvdata(pdev, fimc);
+
+	ret = request_irq(fimc->irq, fimc_irq_handler, 0, pdev->name, fimc);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to install irq (%d)\n", ret);
 		goto err_clk;
 	}
 
+	pm_runtime_enable(&pdev->dev);
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (ret < 0)
+		goto err_irq;
 	/* Initialize contiguous memory allocator */
-	fimc->alloc_ctx = vb2_dma_contig_init_ctx(&fimc->pdev->dev);
+	fimc->alloc_ctx = vb2_dma_contig_init_ctx(&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 (cap_input_index >= 0) {
-		ret = fimc_register_capture_device(fimc);
-		if (ret)
-			goto err_m2m;
-		clk_disable(fimc->clock[CLK_CAM]);
+		goto err_pm;
 	}
-	/*
-	 * Exclude the additional output DMA address registers by masking
-	 * them out on HW revisions that provide extended capabilites.
-	 */
-	if (fimc->variant->out_buf_count > 4)
-		fimc_hw_set_dma_seq(fimc, 0xF);
 
-	dev_dbg(&pdev->dev, "%s(): fimc-%d registered successfully\n",
-		__func__, fimc->id);
+	dev_dbg(&pdev->dev, "FIMC.%d registered successfully\n", fimc->id);
 
+	pm_runtime_put(&pdev->dev);
 	return 0;
 
-err_m2m:
-	fimc_unregister_m2m_device(fimc);
+err_pm:
+	pm_runtime_put(&pdev->dev);
 err_irq:
 	free_irq(fimc->irq, fimc);
 err_clk:
-	fimc_clk_release(fimc);
+	fimc_clk_put(fimc);
 err_regs_unmap:
 	iounmap(fimc->regs);
 err_req_region:
@@ -1719,31 +1693,100 @@
 	kfree(fimc->regs_res);
 err_info:
 	kfree(fimc);
+	return ret;
+}
+
+static int fimc_runtime_resume(struct device *dev)
+{
+	struct fimc_dev *fimc =	dev_get_drvdata(dev);
+
+	dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
+
+	/* Enable clocks and perform basic initalization */
+	clk_enable(fimc->clock[CLK_GATE]);
+	fimc_hw_reset(fimc);
+
+	/* Resume the capture or mem-to-mem device */
+	if (fimc_capture_busy(fimc))
+		return fimc_capture_resume(fimc);
+	else if (fimc_m2m_pending(fimc))
+		return fimc_m2m_resume(fimc);
+	return 0;
+}
+
+static int fimc_runtime_suspend(struct device *dev)
+{
+	struct fimc_dev *fimc =	dev_get_drvdata(dev);
+	int ret = 0;
+
+	if (fimc_capture_busy(fimc))
+		ret = fimc_capture_suspend(fimc);
+	else
+		ret = fimc_m2m_suspend(fimc);
+	if (!ret)
+		clk_disable(fimc->clock[CLK_GATE]);
 
+	dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
 	return ret;
 }
 
-static int __devexit fimc_remove(struct platform_device *pdev)
+#ifdef CONFIG_PM_SLEEP
+static int fimc_resume(struct device *dev)
 {
-	struct fimc_dev *fimc =
-		(struct fimc_dev *)platform_get_drvdata(pdev);
+	struct fimc_dev *fimc =	dev_get_drvdata(dev);
+	unsigned long flags;
 
-	free_irq(fimc->irq, fimc);
+	dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
+
+	/* Do not resume if the device was idle before system suspend */
+	spin_lock_irqsave(&fimc->slock, flags);
+	if (!test_and_clear_bit(ST_LPM, &fimc->state) ||
+	    (!fimc_m2m_active(fimc) && !fimc_capture_busy(fimc))) {
+		spin_unlock_irqrestore(&fimc->slock, flags);
+		return 0;
+	}
 	fimc_hw_reset(fimc);
+	spin_unlock_irqrestore(&fimc->slock, flags);
 
-	fimc_unregister_m2m_device(fimc);
-	fimc_unregister_capture_device(fimc);
+	if (fimc_capture_busy(fimc))
+		return fimc_capture_resume(fimc);
 
-	fimc_clk_release(fimc);
+	return fimc_m2m_resume(fimc);
+}
+
+static int fimc_suspend(struct device *dev)
+{
+	struct fimc_dev *fimc =	dev_get_drvdata(dev);
+
+	dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
+
+	if (test_and_set_bit(ST_LPM, &fimc->state))
+		return 0;
+	if (fimc_capture_busy(fimc))
+		return fimc_capture_suspend(fimc);
+
+	return fimc_m2m_suspend(fimc);
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static int __devexit fimc_remove(struct platform_device *pdev)
+{
+	struct fimc_dev *fimc = platform_get_drvdata(pdev);
+
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
 
 	vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
 
+	clk_disable(fimc->clock[CLK_BUS]);
+	fimc_clk_put(fimc);
+	free_irq(fimc->irq, fimc);
 	iounmap(fimc->regs);
 	release_resource(fimc->regs_res);
 	kfree(fimc->regs_res);
 	kfree(fimc);
 
-	dev_info(&pdev->dev, "%s driver unloaded\n", pdev->name);
+	dev_info(&pdev->dev, "driver unloaded\n");
 	return 0;
 }
 
@@ -1786,17 +1829,21 @@
 static struct samsung_fimc_variant fimc0_variant_s5p = {
 	.has_inp_rot	 = 1,
 	.has_out_rot	 = 1,
+	.has_cam_if	 = 1,
 	.min_inp_pixsize = 16,
 	.min_out_pixsize = 16,
 	.hor_offs_align	 = 8,
+	.min_vsize_align = 16,
 	.out_buf_count	 = 4,
 	.pix_limit	 = &s5p_pix_limit[0],
 };
 
 static struct samsung_fimc_variant fimc2_variant_s5p = {
+	.has_cam_if	 = 1,
 	.min_inp_pixsize = 16,
 	.min_out_pixsize = 16,
 	.hor_offs_align	 = 8,
+	.min_vsize_align = 16,
 	.out_buf_count	 = 4,
 	.pix_limit = &s5p_pix_limit[1],
 };
@@ -1805,9 +1852,11 @@
 	.pix_hoff	 = 1,
 	.has_inp_rot	 = 1,
 	.has_out_rot	 = 1,
+	.has_cam_if	 = 1,
 	.min_inp_pixsize = 16,
 	.min_out_pixsize = 16,
 	.hor_offs_align	 = 8,
+	.min_vsize_align = 16,
 	.out_buf_count	 = 4,
 	.pix_limit	 = &s5p_pix_limit[1],
 };
@@ -1816,19 +1865,23 @@
 	.pix_hoff	 = 1,
 	.has_inp_rot	 = 1,
 	.has_out_rot	 = 1,
+	.has_cam_if	 = 1,
 	.has_mainscaler_ext = 1,
 	.min_inp_pixsize = 16,
 	.min_out_pixsize = 16,
 	.hor_offs_align	 = 1,
+	.min_vsize_align = 1,
 	.out_buf_count	 = 4,
 	.pix_limit	 = &s5p_pix_limit[2],
 };
 
 static struct samsung_fimc_variant fimc2_variant_s5pv210 = {
+	.has_cam_if	 = 1,
 	.pix_hoff	 = 1,
 	.min_inp_pixsize = 16,
 	.min_out_pixsize = 16,
 	.hor_offs_align	 = 8,
+	.min_vsize_align = 16,
 	.out_buf_count	 = 4,
 	.pix_limit	 = &s5p_pix_limit[2],
 };
@@ -1837,22 +1890,26 @@
 	.pix_hoff	 = 1,
 	.has_inp_rot	 = 1,
 	.has_out_rot	 = 1,
+	.has_cam_if	 = 1,
 	.has_cistatus2	 = 1,
 	.has_mainscaler_ext = 1,
 	.min_inp_pixsize = 16,
 	.min_out_pixsize = 16,
-	.hor_offs_align	 = 1,
+	.hor_offs_align	 = 2,
+	.min_vsize_align = 1,
 	.out_buf_count	 = 32,
 	.pix_limit	 = &s5p_pix_limit[1],
 };
 
-static struct samsung_fimc_variant fimc2_variant_exynos4 = {
+static struct samsung_fimc_variant fimc3_variant_exynos4 = {
 	.pix_hoff	 = 1,
+	.has_cam_if	 = 1,
 	.has_cistatus2	 = 1,
 	.has_mainscaler_ext = 1,
 	.min_inp_pixsize = 16,
 	.min_out_pixsize = 16,
-	.hor_offs_align	 = 1,
+	.hor_offs_align	 = 2,
+	.min_vsize_align = 1,
 	.out_buf_count	 = 32,
 	.pix_limit	 = &s5p_pix_limit[3],
 };
@@ -1885,7 +1942,7 @@
 		[0] = &fimc0_variant_exynos4,
 		[1] = &fimc0_variant_exynos4,
 		[2] = &fimc0_variant_exynos4,
-		[3] = &fimc2_variant_exynos4,
+		[3] = &fimc3_variant_exynos4,
 	},
 	.num_entities = 4,
 	.lclk_frequency = 166000000UL,
@@ -1906,33 +1963,28 @@
 };
 MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
 
+static const struct dev_pm_ops fimc_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume)
+	SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL)
+};
+
 static struct platform_driver fimc_driver = {
 	.probe		= fimc_probe,
-	.remove	= __devexit_p(fimc_remove),
+	.remove		= __devexit_p(fimc_remove),
 	.id_table	= fimc_driver_ids,
 	.driver = {
-		.name	= MODULE_NAME,
+		.name	= FIMC_MODULE_NAME,
 		.owner	= THIS_MODULE,
+		.pm     = &fimc_pm_ops,
 	}
 };
 
-static int __init fimc_init(void)
+int __init fimc_register_driver(void)
 {
-	int ret = platform_driver_register(&fimc_driver);
-	if (ret)
-		err("platform_driver_register failed: %d\n", ret);
-	return ret;
+	return platform_driver_probe(&fimc_driver, fimc_probe);
 }
 
-static void __exit fimc_exit(void)
+void __exit fimc_unregister_driver(void)
 {
 	platform_driver_unregister(&fimc_driver);
 }
-
-module_init(fimc_init);
-module_exit(fimc_exit);
-
-MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
-MODULE_DESCRIPTION("S5P FIMC camera host interface/video postprocessor driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0.1");
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/fimc-core.h linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/fimc-core.h
--- linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/fimc-core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/fimc-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -11,12 +11,16 @@
 
 /*#define DEBUG*/
 
+#include <linux/platform_device.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/videodev2.h>
 #include <linux/io.h>
+
+#include <media/media-entity.h>
 #include <media/videobuf2-core.h>
+#include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-mem2mem.h>
 #include <media/v4l2-mediabus.h>
@@ -32,38 +36,46 @@
 
 /* Time to wait for next frame VSYNC interrupt while stopping operation. */
 #define FIMC_SHUTDOWN_TIMEOUT	((100*HZ)/1000)
-#define MAX_FIMC_CLOCKS		3
-#define MODULE_NAME		"s5p-fimc"
+#define MAX_FIMC_CLOCKS		2
+#define FIMC_MODULE_NAME	"s5p-fimc"
 #define FIMC_MAX_DEVS		4
 #define FIMC_MAX_OUT_BUFS	4
 #define SCALER_MAX_HRATIO	64
 #define SCALER_MAX_VRATIO	64
 #define DMA_MIN_SIZE		8
+#define FIMC_CAMIF_MAX_HEIGHT	0x2000
 
 /* indices to the clocks array */
 enum {
 	CLK_BUS,
 	CLK_GATE,
-	CLK_CAM,
 };
 
 enum fimc_dev_flags {
-	/* for m2m node */
-	ST_IDLE,
-	ST_OUTDMA_RUN,
+	ST_LPM,
+	/* m2m node */
+	ST_M2M_RUN,
 	ST_M2M_PEND,
-	/* for capture node */
+	ST_M2M_SUSPENDING,
+	ST_M2M_SUSPENDED,
+	/* capture node */
 	ST_CAPT_PEND,
 	ST_CAPT_RUN,
 	ST_CAPT_STREAM,
+	ST_CAPT_ISP_STREAM,
+	ST_CAPT_SUSPENDED,
 	ST_CAPT_SHUT,
+	ST_CAPT_BUSY,
+	ST_CAPT_APPLY_CFG,
+	ST_CAPT_JPEG,
 };
 
-#define fimc_m2m_active(dev) test_bit(ST_OUTDMA_RUN, &(dev)->state)
+#define fimc_m2m_active(dev) test_bit(ST_M2M_RUN, &(dev)->state)
 #define fimc_m2m_pending(dev) test_bit(ST_M2M_PEND, &(dev)->state)
 
 #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_busy(dev) test_bit(ST_CAPT_BUSY, &(dev)->state)
 
 enum fimc_datapath {
 	FIMC_CAMERA,
@@ -83,9 +95,14 @@
 	S5P_FIMC_CBYCRY422,
 	S5P_FIMC_CRYCBY422,
 	S5P_FIMC_YCBCR444_LOCAL,
+	S5P_FIMC_JPEG = 0x40,
 };
 
-#define fimc_fmt_is_rgb(x) ((x) & 0x10)
+#define fimc_fmt_is_rgb(x) (!!((x) & 0x10))
+#define fimc_fmt_is_jpeg(x) (!!((x) & 0x40))
+
+#define IS_M2M(__strt) ((__strt) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || \
+			__strt == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 
 /* 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
@@ -104,9 +121,10 @@
 #define	FIMC_DST_ADDR		(1 << 2)
 #define	FIMC_SRC_FMT		(1 << 3)
 #define	FIMC_DST_FMT		(1 << 4)
-#define	FIMC_CTX_M2M		(1 << 5)
-#define	FIMC_CTX_CAP		(1 << 6)
-#define	FIMC_CTX_SHUT		(1 << 7)
+#define	FIMC_DST_CROP		(1 << 5)
+#define	FIMC_CTX_M2M		(1 << 16)
+#define	FIMC_CTX_CAP		(1 << 17)
+#define	FIMC_CTX_SHUT		(1 << 18)
 
 /* Image conversion flags */
 #define	FIMC_IN_DMA_ACCESS_TILED	(1 << 0)
@@ -122,11 +140,6 @@
 /* Y (16 ~ 235), Cb/Cr (16 ~ 240) */
 #define	FIMC_COLOR_RANGE_NARROW		(1 << 3)
 
-#define	FLIP_NONE			0
-#define	FLIP_X_AXIS			1
-#define	FLIP_Y_AXIS			2
-#define	FLIP_XY_AXIS			(FLIP_X_AXIS | FLIP_Y_AXIS)
-
 /**
  * struct fimc_fmt - the driver's internal color format data
  * @mbus_code: Media Bus pixel code, -1 if not applicable
@@ -275,26 +288,29 @@
 /**
  * struct fimc_m2m_device - v4l2 memory-to-memory device data
  * @vfd: the video device node for v4l2 m2m mode
- * @v4l2_dev: v4l2 device for m2m mode
  * @m2m_dev: v4l2 memory-to-memory device data
  * @ctx: hardware context data
  * @refcnt: the reference counter
  */
 struct fimc_m2m_device {
 	struct video_device	*vfd;
-	struct v4l2_device	v4l2_dev;
 	struct v4l2_m2m_dev	*m2m_dev;
 	struct fimc_ctx		*ctx;
 	int			refcnt;
 };
 
+#define FIMC_SD_PAD_SINK	0
+#define FIMC_SD_PAD_SOURCE	1
+#define FIMC_SD_PADS_NUM	2
+
 /**
  * struct fimc_vid_cap - camera capture device information
  * @ctx: hardware context data
  * @vfd: video device node for camera capture mode
- * @v4l2_dev: v4l2_device struct to manage subdevs
- * @sd: pointer to camera sensor subdevice currently in use
- * @fmt: Media Bus format configured at selected image sensor
+ * @subdev: subdev exposing the FIMC processing block
+ * @vd_pad: fimc video capture node pad
+ * @sd_pads: fimc video processing block pads
+ * @mf: media bus format at the FIMC camera input (and the scaler output) pad
  * @pending_buf_q: the pending buffer queue head
  * @active_buf_q: the queue head of buffers scheduled in hardware
  * @vbq: the capture am video buffer queue
@@ -304,14 +320,17 @@
  * @reqbufs_count: the number of buffers requested in REQBUFS ioctl
  * @input_index: input (camera sensor) index
  * @refcnt: driver's private reference counter
+ * @input: capture input type, grp_id of the attached subdev
+ * @user_subdev_api: true if subdevs are not configured by the host driver
  */
 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_mbus_framefmt	fmt;
+	struct v4l2_subdev		*subdev;
+	struct media_pad		vd_pad;
+	struct v4l2_mbus_framefmt	mf;
+	struct media_pad		sd_pads[FIMC_SD_PADS_NUM];
 	struct list_head		pending_buf_q;
 	struct list_head		active_buf_q;
 	struct vb2_queue		vbq;
@@ -321,6 +340,8 @@
 	unsigned int			reqbufs_count;
 	int				input_index;
 	int				refcnt;
+	u32				input;
+	bool				user_subdev_api;
 };
 
 /**
@@ -351,10 +372,12 @@
  * @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
+ * @has_cam_if: set if this instance has a camera input interface
  * @pix_limit: pixel size constraints for the scaler
  * @min_inp_pixsize: minimum input pixel size
  * @min_out_pixsize: minimum output pixel size
  * @hor_offs_align: horizontal pixel offset aligment
+ * @min_vsize_align: minimum vertical pixel size alignment
  * @out_buf_count: the number of buffers in output DMA sequence
  */
 struct samsung_fimc_variant {
@@ -363,10 +386,12 @@
 	unsigned int	has_out_rot:1;
 	unsigned int	has_cistatus2:1;
 	unsigned int	has_mainscaler_ext:1;
+	unsigned int	has_cam_if:1;
 	struct fimc_pix_limit *pix_limit;
 	u16		min_inp_pixsize;
 	u16		min_out_pixsize;
 	u16		hor_offs_align;
+	u16		min_vsize_align;
 	u16		out_buf_count;
 };
 
@@ -383,6 +408,12 @@
 	int		num_entities;
 };
 
+struct fimc_pipeline {
+	struct media_pipeline *pipe;
+	struct v4l2_subdev *sensor;
+	struct v4l2_subdev *csis;
+};
+
 struct fimc_ctx;
 
 /**
@@ -399,10 +430,12 @@
  * @regs_res:	the resource claimed for IO registers
  * @irq:	FIMC interrupt number
  * @irq_queue:	interrupt handler waitqueue
+ * @v4l2_dev:	root v4l2_device
  * @m2m:	memory-to-memory V4L2 device information
  * @vid_cap:	camera capture device information
  * @state:	flags used to synchronize m2m and capture mode operation
  * @alloc_ctx:	videobuf2 memory allocator context
+ * @pipeline:	fimc video capture pipeline data structure
  */
 struct fimc_dev {
 	spinlock_t			slock;
@@ -417,10 +450,12 @@
 	struct resource			*regs_res;
 	int				irq;
 	wait_queue_head_t		irq_queue;
+	struct v4l2_device		*v4l2_dev;
 	struct fimc_m2m_device		m2m;
 	struct fimc_vid_cap		vid_cap;
 	unsigned long			state;
 	struct vb2_alloc_ctx		*alloc_ctx;
+	struct fimc_pipeline		pipeline;
 };
 
 /**
@@ -437,11 +472,18 @@
  * @scaler:		image scaler properties
  * @effect:		image effect
  * @rotation:		image clockwise rotation in degrees
- * @flip:		image flip mode
+ * @hflip:		indicates image horizontal flip if set
+ * @vflip:		indicates image vertical flip if set
  * @flags:		additional flags for image conversion
  * @state:		flags to keep track of user configuration
  * @fimc_dev:		the FIMC device this context applies to
  * @m2m_ctx:		memory-to-memory device context
+ * @fh:			v4l2 file handle
+ * @ctrl_handler:	v4l2 controls handler
+ * @ctrl_rotate		image rotation control
+ * @ctrl_hflip		horizontal flip control
+ * @ctrl_vflip		vartical flip control
+ * @ctrls_rdy:		true if the control handler is initialized
  */
 struct fimc_ctx {
 	spinlock_t		slock;
@@ -456,13 +498,49 @@
 	struct fimc_scaler	scaler;
 	struct fimc_effect	effect;
 	int			rotation;
-	u32			flip;
+	unsigned int		hflip:1;
+	unsigned int		vflip:1;
 	u32			flags;
 	u32			state;
 	struct fimc_dev		*fimc_dev;
 	struct v4l2_m2m_ctx	*m2m_ctx;
+	struct v4l2_fh		fh;
+	struct v4l2_ctrl_handler ctrl_handler;
+	struct v4l2_ctrl	*ctrl_rotate;
+	struct v4l2_ctrl	*ctrl_hflip;
+	struct v4l2_ctrl	*ctrl_vflip;
+	bool			ctrls_rdy;
 };
 
+#define fh_to_ctx(__fh) container_of(__fh, struct fimc_ctx, fh)
+
+static inline void set_frame_bounds(struct fimc_frame *f, u32 width, u32 height)
+{
+	f->o_width  = width;
+	f->o_height = height;
+	f->f_width  = width;
+	f->f_height = height;
+}
+
+static inline void set_frame_crop(struct fimc_frame *f,
+				  u32 left, u32 top, u32 width, u32 height)
+{
+	f->offs_h = left;
+	f->offs_v = top;
+	f->width  = width;
+	f->height = height;
+}
+
+static inline u32 fimc_get_format_depth(struct fimc_fmt *ff)
+{
+	u32 i, depth = 0;
+
+	if (ff != NULL)
+		for (i = 0; i < ff->colplanes; i++)
+			depth += ff->depth[i];
+	return depth;
+}
+
 static inline bool fimc_capture_active(struct fimc_dev *fimc)
 {
 	unsigned long flags;
@@ -561,7 +639,7 @@
 	} else if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == type) {
 		frame = &ctx->d_frame;
 	} else {
-		v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
+		v4l2_err(ctx->fimc_dev->v4l2_dev,
 			"Wrong buffer/video queue type (%d)\n", type);
 		return ERR_PTR(-EINVAL);
 	}
@@ -595,7 +673,7 @@
 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_effect(struct fimc_ctx *ctx, bool active);
 void fimc_hw_set_in_dma(struct fimc_ctx *ctx);
 void fimc_hw_set_input_path(struct fimc_ctx *ctx);
 void fimc_hw_set_output_path(struct fimc_ctx *ctx);
@@ -614,36 +692,45 @@
 /* fimc-core.c */
 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,
-		       struct v4l2_control *ctrl);
-
-int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr);
-int check_ctrl_val(struct fimc_ctx *ctx,  struct v4l2_control *ctrl);
-int fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_control *ctrl);
-
-struct fimc_fmt *find_format(struct v4l2_format *f, unsigned int mask);
-struct fimc_fmt *find_mbus_format(struct v4l2_mbus_framefmt *f,
-				  unsigned int mask);
+int fimc_ctrls_create(struct fimc_ctx *ctx);
+void fimc_ctrls_delete(struct fimc_ctx *ctx);
+void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active);
+int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f);
+void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height,
+			       struct v4l2_pix_format_mplane *pix);
+struct fimc_fmt *fimc_find_format(u32 *pixelformat, u32 *mbus_code,
+				  unsigned int mask, int index);
 
-int fimc_check_scaler_ratio(int sw, int sh, int dw, int dh, int rot);
+int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh,
+			    int dw, int dh, int rotation);
 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 vb2_buffer *vb,
 		      struct fimc_frame *frame, struct fimc_addr *paddr);
+void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f);
+void fimc_set_yuv_order(struct fimc_ctx *ctx);
+void fimc_fill_frame(struct fimc_frame *frame, struct v4l2_format *f);
+void fimc_capture_irq_handler(struct fimc_dev *fimc, bool done);
+
+int fimc_register_m2m_device(struct fimc_dev *fimc,
+			     struct v4l2_device *v4l2_dev);
+void fimc_unregister_m2m_device(struct fimc_dev *fimc);
+int fimc_register_driver(void);
+void fimc_unregister_driver(void);
 
 /* -----------------------------------------------------*/
 /* fimc-capture.c					*/
-int fimc_register_capture_device(struct fimc_dev *fimc);
+int fimc_register_capture_device(struct fimc_dev *fimc,
+				 struct v4l2_device *v4l2_dev);
 void fimc_unregister_capture_device(struct fimc_dev *fimc);
-int fimc_sensor_sd_init(struct fimc_dev *fimc, int index);
+int fimc_capture_ctrls_create(struct fimc_dev *fimc);
 int fimc_vid_cap_buf_queue(struct fimc_dev *fimc,
 			     struct fimc_vid_buffer *fimc_vb);
+void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification,
+			void *arg);
+int fimc_capture_suspend(struct fimc_dev *fimc);
+int fimc_capture_resume(struct fimc_dev *fimc);
+int fimc_capture_config_update(struct fimc_ctx *ctx);
 
 /* Locking: the caller holds fimc->slock */
 static inline void fimc_activate_capture(struct fimc_ctx *ctx)
@@ -661,22 +748,27 @@
 }
 
 /*
- * Add buf to the capture active buffers queue.
- * Locking: Need to be called with fimc_dev::slock held.
+ * Buffer list manipulation functions. Must be called with fimc.slock held.
  */
-static inline void active_queue_add(struct fimc_vid_cap *vid_cap,
-				    struct fimc_vid_buffer *buf)
+
+/**
+ * fimc_active_queue_add - add buffer to the capture active buffers queue
+ * @buf: buffer to add to the active buffers list
+ */
+static inline void fimc_active_queue_add(struct fimc_vid_cap *vid_cap,
+					 struct fimc_vid_buffer *buf)
 {
 	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 fimc_dev::slock held.
+/**
+ * fimc_active_queue_pop - pop buffer from the capture active buffers queue
+ *
+ * The caller must assure the active_buf_q list is not empty.
  */
-static inline struct fimc_vid_buffer *
-active_queue_pop(struct fimc_vid_cap *vid_cap)
+static inline struct fimc_vid_buffer *fimc_active_queue_pop(
+				    struct fimc_vid_cap *vid_cap)
 {
 	struct fimc_vid_buffer *buf;
 	buf = list_entry(vid_cap->active_buf_q.next,
@@ -686,16 +778,23 @@
 	return buf;
 }
 
-/* Add video buffer to the capture pending buffers queue */
+/**
+ * fimc_pending_queue_add - add buffer to the capture pending buffers queue
+ * @buf: buffer to add to the pending buffers list
+ */
 static inline void fimc_pending_queue_add(struct fimc_vid_cap *vid_cap,
 					  struct fimc_vid_buffer *buf)
 {
 	list_add_tail(&buf->list, &vid_cap->pending_buf_q);
 }
 
-/* Add video buffer to the capture pending buffers queue */
-static inline struct fimc_vid_buffer *
-pending_queue_pop(struct fimc_vid_cap *vid_cap)
+/**
+ * fimc_pending_queue_pop - pop buffer from the capture pending buffers queue
+ *
+ * The caller must assure the pending_buf_q list is not empty.
+ */
+static inline struct fimc_vid_buffer *fimc_pending_queue_pop(
+				     struct fimc_vid_cap *vid_cap)
 {
 	struct fimc_vid_buffer *buf;
 	buf = list_entry(vid_cap->pending_buf_q.next,
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/fimc-mdevice.c linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/fimc-mdevice.c
--- linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/fimc-mdevice.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/fimc-mdevice.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,869 @@
+/*
+ * S5P/EXYNOS4 SoC series camera host interface media device driver
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * Contact: Sylwester Nawrocki, <s.nawrocki@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/bug.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <media/v4l2-ctrls.h>
+#include <media/media-device.h>
+
+#include "fimc-core.h"
+#include "fimc-mdevice.h"
+#include "mipi-csis.h"
+
+static int __fimc_md_set_camclk(struct fimc_md *fmd,
+				struct fimc_sensor_info *s_info,
+				bool on);
+/**
+ * fimc_pipeline_prepare - update pipeline information with subdevice pointers
+ * @fimc: fimc device terminating the pipeline
+ *
+ * Caller holds the graph mutex.
+ */
+void fimc_pipeline_prepare(struct fimc_dev *fimc, struct media_entity *me)
+{
+	struct media_entity_graph graph;
+	struct v4l2_subdev *sd;
+
+	media_entity_graph_walk_start(&graph, me);
+
+	while ((me = media_entity_graph_walk_next(&graph))) {
+		if (media_entity_type(me) != MEDIA_ENT_T_V4L2_SUBDEV)
+			continue;
+		sd = media_entity_to_v4l2_subdev(me);
+
+		if (sd->grp_id == SENSOR_GROUP_ID)
+			fimc->pipeline.sensor = sd;
+		else if (sd->grp_id == CSIS_GROUP_ID)
+			fimc->pipeline.csis = sd;
+	}
+}
+
+/**
+ * __subdev_set_power - change power state of a single subdev
+ * @sd: subdevice to change power state for
+ * @on: 1 to enable power or 0 to disable
+ *
+ * Return result of s_power subdev operation or -ENXIO if sd argument
+ * is NULL. Return 0 if the subdevice does not implement s_power.
+ */
+static int __subdev_set_power(struct v4l2_subdev *sd, int on)
+{
+	int *use_count;
+	int ret;
+
+	if (sd == NULL)
+		return -ENXIO;
+
+	use_count = &sd->entity.use_count;
+	if (on && (*use_count)++ > 0)
+		return 0;
+	else if (!on && (*use_count == 0 || --(*use_count) > 0))
+		return 0;
+	ret = v4l2_subdev_call(sd, core, s_power, on);
+
+	return ret != -ENOIOCTLCMD ? ret : 0;
+}
+
+/**
+ * fimc_pipeline_s_power - change power state of all pipeline subdevs
+ * @fimc: fimc device terminating the pipeline
+ * @state: 1 to enable power or 0 for power down
+ *
+ * Need to be called with the graph mutex held.
+ */
+int fimc_pipeline_s_power(struct fimc_dev *fimc, int state)
+{
+	int ret = 0;
+
+	if (fimc->pipeline.sensor == NULL)
+		return -ENXIO;
+
+	if (state) {
+		ret = __subdev_set_power(fimc->pipeline.csis, 1);
+		if (ret && ret != -ENXIO)
+			return ret;
+		return __subdev_set_power(fimc->pipeline.sensor, 1);
+	}
+
+	ret = __subdev_set_power(fimc->pipeline.sensor, 0);
+	if (ret)
+		return ret;
+	ret = __subdev_set_power(fimc->pipeline.csis, 0);
+
+	return ret == -ENXIO ? 0 : ret;
+}
+
+/**
+ * __fimc_pipeline_initialize - update the pipeline information, enable power
+ *                              of all pipeline subdevs and the sensor clock
+ * @me: media entity to start graph walk with
+ * @prep: true to acquire sensor (and csis) subdevs
+ *
+ * This function must be called with the graph mutex held.
+ */
+static int __fimc_pipeline_initialize(struct fimc_dev *fimc,
+				      struct media_entity *me, bool prep)
+{
+	int ret;
+
+	if (prep)
+		fimc_pipeline_prepare(fimc, me);
+	if (fimc->pipeline.sensor == NULL)
+		return -EINVAL;
+	ret = fimc_md_set_camclk(fimc->pipeline.sensor, true);
+	if (ret)
+		return ret;
+	return fimc_pipeline_s_power(fimc, 1);
+}
+
+int fimc_pipeline_initialize(struct fimc_dev *fimc, struct media_entity *me,
+			     bool prep)
+{
+	int ret;
+
+	mutex_lock(&me->parent->graph_mutex);
+	ret =  __fimc_pipeline_initialize(fimc, me, prep);
+	mutex_unlock(&me->parent->graph_mutex);
+
+	return ret;
+}
+
+/**
+ * __fimc_pipeline_shutdown - disable the sensor clock and pipeline power
+ * @fimc: fimc device terminating the pipeline
+ *
+ * Disable power of all subdevs in the pipeline and turn off the external
+ * sensor clock.
+ * Called with the graph mutex held.
+ */
+int __fimc_pipeline_shutdown(struct fimc_dev *fimc)
+{
+	int ret = 0;
+
+	if (fimc->pipeline.sensor) {
+		ret = fimc_pipeline_s_power(fimc, 0);
+		fimc_md_set_camclk(fimc->pipeline.sensor, false);
+	}
+	return ret == -ENXIO ? 0 : ret;
+}
+
+int fimc_pipeline_shutdown(struct fimc_dev *fimc)
+{
+	struct media_entity *me = &fimc->vid_cap.vfd->entity;
+	int ret;
+
+	mutex_lock(&me->parent->graph_mutex);
+	ret = __fimc_pipeline_shutdown(fimc);
+	mutex_unlock(&me->parent->graph_mutex);
+
+	return ret;
+}
+
+/**
+ * fimc_pipeline_s_stream - invoke s_stream on pipeline subdevs
+ * @fimc: fimc device terminating the pipeline
+ * @on: passed as the s_stream call argument
+ */
+int fimc_pipeline_s_stream(struct fimc_dev *fimc, int on)
+{
+	struct fimc_pipeline *p = &fimc->pipeline;
+	int ret = 0;
+
+	if (p->sensor == NULL)
+		return -ENODEV;
+
+	if ((on && p->csis) || !on)
+		ret = v4l2_subdev_call(on ? p->csis : p->sensor,
+				       video, s_stream, on);
+	if (ret < 0 && ret != -ENOIOCTLCMD)
+		return ret;
+	if ((!on && p->csis) || on)
+		ret = v4l2_subdev_call(on ? p->sensor : p->csis,
+				       video, s_stream, on);
+	return ret == -ENOIOCTLCMD ? 0 : ret;
+}
+
+/*
+ * Sensor subdevice helper functions
+ */
+static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd,
+				   struct fimc_sensor_info *s_info)
+{
+	struct i2c_adapter *adapter;
+	struct v4l2_subdev *sd = NULL;
+
+	if (!s_info || !fmd)
+		return NULL;
+
+	adapter = i2c_get_adapter(s_info->pdata->i2c_bus_num);
+	if (!adapter)
+		return NULL;
+	sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter,
+				       s_info->pdata->board_info, NULL);
+	if (IS_ERR_OR_NULL(sd)) {
+		i2c_put_adapter(adapter);
+		v4l2_err(&fmd->v4l2_dev, "Failed to acquire subdev\n");
+		return NULL;
+	}
+	v4l2_set_subdev_hostdata(sd, s_info);
+	sd->grp_id = SENSOR_GROUP_ID;
+
+	v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n",
+		  s_info->pdata->board_info->type);
+	return sd;
+}
+
+static void fimc_md_unregister_sensor(struct v4l2_subdev *sd)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct i2c_adapter *adapter;
+
+	if (!client)
+		return;
+	v4l2_device_unregister_subdev(sd);
+	adapter = client->adapter;
+	i2c_unregister_device(client);
+	if (adapter)
+		i2c_put_adapter(adapter);
+}
+
+static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
+{
+	struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data;
+	struct fimc_dev *fd = NULL;
+	int num_clients, ret, i;
+
+	/*
+	 * Runtime resume one of the FIMC entities to make sure
+	 * the sclk_cam clocks are not globally disabled.
+	 */
+	for (i = 0; !fd && i < ARRAY_SIZE(fmd->fimc); i++)
+		if (fmd->fimc[i])
+			fd = fmd->fimc[i];
+	if (!fd)
+		return -ENXIO;
+	ret = pm_runtime_get_sync(&fd->pdev->dev);
+	if (ret < 0)
+		return ret;
+
+	WARN_ON(pdata->num_clients > ARRAY_SIZE(fmd->sensor));
+	num_clients = min_t(u32, pdata->num_clients, ARRAY_SIZE(fmd->sensor));
+
+	fmd->num_sensors = num_clients;
+	for (i = 0; i < num_clients; i++) {
+		fmd->sensor[i].pdata = &pdata->isp_info[i];
+		ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], true);
+		if (ret)
+			break;
+		fmd->sensor[i].subdev =
+			fimc_md_register_sensor(fmd, &fmd->sensor[i]);
+		ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], false);
+		if (ret)
+			break;
+	}
+	pm_runtime_put(&fd->pdev->dev);
+	return ret;
+}
+
+/*
+ * MIPI CSIS and FIMC platform devices registration.
+ */
+static int fimc_register_callback(struct device *dev, void *p)
+{
+	struct fimc_dev *fimc = dev_get_drvdata(dev);
+	struct fimc_md *fmd = p;
+	int ret;
+
+	if (!fimc || !fimc->pdev)
+		return 0;
+	if (fimc->pdev->id < 0 || fimc->pdev->id >= FIMC_MAX_DEVS)
+		return 0;
+
+	fmd->fimc[fimc->pdev->id] = fimc;
+	ret = fimc_register_m2m_device(fimc, &fmd->v4l2_dev);
+	if (ret)
+		return ret;
+	ret = fimc_register_capture_device(fimc, &fmd->v4l2_dev);
+	if (!ret)
+		fimc->vid_cap.user_subdev_api = fmd->user_subdev_api;
+	return ret;
+}
+
+static int csis_register_callback(struct device *dev, void *p)
+{
+	struct v4l2_subdev *sd = dev_get_drvdata(dev);
+	struct platform_device *pdev;
+	struct fimc_md *fmd = p;
+	int id, ret;
+
+	if (!sd)
+		return 0;
+	pdev = v4l2_get_subdevdata(sd);
+	if (!pdev || pdev->id < 0 || pdev->id >= CSIS_MAX_ENTITIES)
+		return 0;
+	v4l2_info(sd, "csis%d sd: %s\n", pdev->id, sd->name);
+
+	id = pdev->id < 0 ? 0 : pdev->id;
+	fmd->csis[id].sd = sd;
+	sd->grp_id = CSIS_GROUP_ID;
+	ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
+	if (ret)
+		v4l2_err(&fmd->v4l2_dev,
+			 "Failed to register CSIS subdevice: %d\n", ret);
+	return ret;
+}
+
+/**
+ * fimc_md_register_platform_entities - register FIMC and CSIS media entities
+ */
+static int fimc_md_register_platform_entities(struct fimc_md *fmd)
+{
+	struct device_driver *driver;
+	int ret;
+
+	driver = driver_find(FIMC_MODULE_NAME, &platform_bus_type);
+	if (!driver)
+		return -ENODEV;
+	ret = driver_for_each_device(driver, NULL, fmd,
+				     fimc_register_callback);
+	put_driver(driver);
+	if (ret)
+		return ret;
+
+	driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type);
+	if (driver) {
+		ret = driver_for_each_device(driver, NULL, fmd,
+					     csis_register_callback);
+		put_driver(driver);
+	}
+	return ret;
+}
+
+static void fimc_md_unregister_entities(struct fimc_md *fmd)
+{
+	int i;
+
+	for (i = 0; i < FIMC_MAX_DEVS; i++) {
+		if (fmd->fimc[i] == NULL)
+			continue;
+		fimc_unregister_m2m_device(fmd->fimc[i]);
+		fimc_unregister_capture_device(fmd->fimc[i]);
+		fmd->fimc[i] = NULL;
+	}
+	for (i = 0; i < CSIS_MAX_ENTITIES; i++) {
+		if (fmd->csis[i].sd == NULL)
+			continue;
+		v4l2_device_unregister_subdev(fmd->csis[i].sd);
+		fmd->csis[i].sd = NULL;
+	}
+	for (i = 0; i < fmd->num_sensors; i++) {
+		if (fmd->sensor[i].subdev == NULL)
+			continue;
+		fimc_md_unregister_sensor(fmd->sensor[i].subdev);
+		fmd->sensor[i].subdev = NULL;
+	}
+}
+
+static int fimc_md_register_video_nodes(struct fimc_md *fmd)
+{
+	struct video_device *vdev;
+	int i, ret = 0;
+
+	for (i = 0; i < FIMC_MAX_DEVS && !ret; i++) {
+		if (!fmd->fimc[i])
+			continue;
+
+		vdev = fmd->fimc[i]->m2m.vfd;
+		if (vdev) {
+			ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+			if (ret)
+				break;
+			v4l2_info(&fmd->v4l2_dev, "Registered %s as /dev/%s\n",
+				  vdev->name, video_device_node_name(vdev));
+		}
+
+		vdev = fmd->fimc[i]->vid_cap.vfd;
+		if (vdev == NULL)
+			continue;
+		ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+		v4l2_info(&fmd->v4l2_dev, "Registered %s as /dev/%s\n",
+			  vdev->name, video_device_node_name(vdev));
+	}
+
+	return ret;
+}
+
+/**
+ * __fimc_md_create_fimc_links - create links to all FIMC entities
+ * @fmd: fimc media device
+ * @source: the source entity to create links to all fimc entities from
+ * @sensor: sensor subdev linked to FIMC[fimc_id] entity, may be null
+ * @pad: the source entity pad index
+ * @fimc_id: index of the fimc device for which link should be enabled
+ */
+static int __fimc_md_create_fimc_links(struct fimc_md *fmd,
+				       struct media_entity *source,
+				       struct v4l2_subdev *sensor,
+				       int pad, int fimc_id)
+{
+	struct fimc_sensor_info *s_info;
+	struct media_entity *sink;
+	unsigned int flags;
+	int ret, i;
+
+	for (i = 0; i < FIMC_MAX_DEVS; i++) {
+		if (!fmd->fimc[i])
+			break;
+		/*
+		 * Some FIMC variants are not fitted with camera capture
+		 * interface. Skip creating a link from sensor for those.
+		 */
+		if (sensor->grp_id == SENSOR_GROUP_ID &&
+		    !fmd->fimc[i]->variant->has_cam_if)
+			continue;
+
+		flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0;
+		sink = &fmd->fimc[i]->vid_cap.subdev->entity;
+		ret = media_entity_create_link(source, pad, sink,
+					      FIMC_SD_PAD_SINK, flags);
+		if (ret)
+			return ret;
+
+		/* Notify FIMC capture subdev entity */
+		ret = media_entity_call(sink, link_setup, &sink->pads[0],
+					&source->pads[pad], flags);
+		if (ret)
+			break;
+
+		v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]",
+			  source->name, flags ? '=' : '-', sink->name);
+
+		if (flags == 0)
+			continue;
+		s_info = v4l2_get_subdev_hostdata(sensor);
+		if (!WARN_ON(s_info == NULL)) {
+			unsigned long irq_flags;
+			spin_lock_irqsave(&fmd->slock, irq_flags);
+			s_info->host = fmd->fimc[i];
+			spin_unlock_irqrestore(&fmd->slock, irq_flags);
+		}
+	}
+	return 0;
+}
+
+/**
+ * fimc_md_create_links - create default links between registered entities
+ *
+ * Parallel interface sensor entities are connected directly to FIMC capture
+ * entities. The sensors using MIPI CSIS bus are connected through immutable
+ * link with CSI receiver entity specified by mux_id. Any registered CSIS
+ * entity has a link to each registered FIMC capture entity. Enabled links
+ * are created by default between each subsequent registered sensor and
+ * subsequent FIMC capture entity. The number of default active links is
+ * determined by the number of available sensors or FIMC entities,
+ * whichever is less.
+ */
+static int fimc_md_create_links(struct fimc_md *fmd)
+{
+	struct v4l2_subdev *sensor, *csis;
+	struct s5p_fimc_isp_info *pdata;
+	struct fimc_sensor_info *s_info;
+	struct media_entity *source, *sink;
+	int i, pad, fimc_id = 0;
+	int ret = 0;
+	u32 flags;
+
+	for (i = 0; i < fmd->num_sensors; i++) {
+		if (fmd->sensor[i].subdev == NULL)
+			continue;
+
+		sensor = fmd->sensor[i].subdev;
+		s_info = v4l2_get_subdev_hostdata(sensor);
+		if (!s_info || !s_info->pdata)
+			continue;
+
+		source = NULL;
+		pdata = s_info->pdata;
+
+		switch (pdata->bus_type) {
+		case FIMC_MIPI_CSI2:
+			if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES,
+				"Wrong CSI channel id: %d\n", pdata->mux_id))
+				return -EINVAL;
+
+			csis = fmd->csis[pdata->mux_id].sd;
+			if (WARN(csis == NULL,
+				 "MIPI-CSI interface specified "
+				 "but s5p-csis module is not loaded!\n"))
+				return -EINVAL;
+
+			ret = media_entity_create_link(&sensor->entity, 0,
+					      &csis->entity, CSIS_PAD_SINK,
+					      MEDIA_LNK_FL_IMMUTABLE |
+					      MEDIA_LNK_FL_ENABLED);
+			if (ret)
+				return ret;
+
+			v4l2_info(&fmd->v4l2_dev, "created link [%s] => [%s]",
+				  sensor->entity.name, csis->entity.name);
+
+			source = &csis->entity;
+			pad = CSIS_PAD_SOURCE;
+			break;
+
+		case FIMC_ITU_601...FIMC_ITU_656:
+			source = &sensor->entity;
+			pad = 0;
+			break;
+
+		default:
+			v4l2_err(&fmd->v4l2_dev, "Wrong bus_type: %x\n",
+				 pdata->bus_type);
+			return -EINVAL;
+		}
+		if (source == NULL)
+			continue;
+
+		ret = __fimc_md_create_fimc_links(fmd, source, sensor, pad,
+						  fimc_id++);
+	}
+	/* Create immutable links between each FIMC's subdev and video node */
+	flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
+	for (i = 0; i < FIMC_MAX_DEVS; i++) {
+		if (!fmd->fimc[i])
+			continue;
+		source = &fmd->fimc[i]->vid_cap.subdev->entity;
+		sink = &fmd->fimc[i]->vid_cap.vfd->entity;
+		ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE,
+					      sink, 0, flags);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+/*
+ * The peripheral sensor clock management.
+ */
+static int fimc_md_get_clocks(struct fimc_md *fmd)
+{
+	char clk_name[32];
+	struct clk *clock;
+	int i;
+
+	for (i = 0; i < FIMC_MAX_CAMCLKS; i++) {
+		snprintf(clk_name, sizeof(clk_name), "sclk_cam%u", i);
+		clock = clk_get(NULL, clk_name);
+		if (IS_ERR_OR_NULL(clock)) {
+			v4l2_err(&fmd->v4l2_dev, "Failed to get clock: %s",
+				  clk_name);
+			return -ENXIO;
+		}
+		fmd->camclk[i].clock = clock;
+	}
+	return 0;
+}
+
+static void fimc_md_put_clocks(struct fimc_md *fmd)
+{
+	int i = FIMC_MAX_CAMCLKS;
+
+	while (--i >= 0) {
+		if (IS_ERR_OR_NULL(fmd->camclk[i].clock))
+			continue;
+		clk_put(fmd->camclk[i].clock);
+		fmd->camclk[i].clock = NULL;
+	}
+}
+
+static int __fimc_md_set_camclk(struct fimc_md *fmd,
+					 struct fimc_sensor_info *s_info,
+					 bool on)
+{
+	struct s5p_fimc_isp_info *pdata = s_info->pdata;
+	struct fimc_camclk_info *camclk;
+	int ret = 0;
+
+	if (WARN_ON(pdata->clk_id >= FIMC_MAX_CAMCLKS) || fmd == NULL)
+		return -EINVAL;
+
+	if (s_info->clk_on == on)
+		return 0;
+	camclk = &fmd->camclk[pdata->clk_id];
+
+	dbg("camclk %d, f: %lu, clk: %p, on: %d",
+	    pdata->clk_id, pdata->clk_frequency, camclk, on);
+
+	if (on) {
+		if (camclk->use_count > 0 &&
+		    camclk->frequency != pdata->clk_frequency)
+			return -EINVAL;
+
+		if (camclk->use_count++ == 0) {
+			clk_set_rate(camclk->clock, pdata->clk_frequency);
+			camclk->frequency = pdata->clk_frequency;
+			ret = clk_enable(camclk->clock);
+		}
+		s_info->clk_on = 1;
+		dbg("Enabled camclk %d: f: %lu", pdata->clk_id,
+		    clk_get_rate(camclk->clock));
+
+		return ret;
+	}
+
+	if (WARN_ON(camclk->use_count == 0))
+		return 0;
+
+	if (--camclk->use_count == 0) {
+		clk_disable(camclk->clock);
+		s_info->clk_on = 0;
+		dbg("Disabled camclk %d", pdata->clk_id);
+	}
+	return ret;
+}
+
+/**
+ * fimc_md_set_camclk - peripheral sensor clock setup
+ * @sd: sensor subdev to configure sclk_cam clock for
+ * @on: 1 to enable or 0 to disable the clock
+ *
+ * There are 2 separate clock outputs available in the SoC for external
+ * image processors. These clocks are shared between all registered FIMC
+ * devices to which sensors can be attached, either directly or through
+ * the MIPI CSI receiver. The clock is allowed here to be used by
+ * multiple sensors concurrently if they use same frequency.
+ * The per sensor subdev clk_on attribute helps to synchronize accesses
+ * to the sclk_cam clocks from the video and media device nodes.
+ * This function should only be called when the graph mutex is held.
+ */
+int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on)
+{
+	struct fimc_sensor_info *s_info = v4l2_get_subdev_hostdata(sd);
+	struct fimc_md *fmd = entity_to_fimc_mdev(&sd->entity);
+
+	return __fimc_md_set_camclk(fmd, s_info, on);
+}
+
+static int fimc_md_link_notify(struct media_pad *source,
+			       struct media_pad *sink, u32 flags)
+{
+	struct v4l2_subdev *sd;
+	struct fimc_dev *fimc;
+	int ret = 0;
+
+	if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		return 0;
+
+	sd = media_entity_to_v4l2_subdev(sink->entity);
+	fimc = v4l2_get_subdevdata(sd);
+
+	if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+		ret = __fimc_pipeline_shutdown(fimc);
+		fimc->pipeline.sensor = NULL;
+		fimc->pipeline.csis = NULL;
+
+		mutex_lock(&fimc->lock);
+		fimc_ctrls_delete(fimc->vid_cap.ctx);
+		mutex_unlock(&fimc->lock);
+		return ret;
+	}
+	/*
+	 * Link activation. Enable power of pipeline elements only if the
+	 * pipeline is already in use, i.e. its video node is opened.
+	 * Recreate the controls destroyed during the link deactivation.
+	 */
+	mutex_lock(&fimc->lock);
+	if (fimc->vid_cap.refcnt > 0) {
+		ret = __fimc_pipeline_initialize(fimc, source->entity, true);
+		if (!ret)
+			ret = fimc_capture_ctrls_create(fimc);
+	}
+	mutex_unlock(&fimc->lock);
+
+	return ret ? -EPIPE : ret;
+}
+
+static ssize_t fimc_md_sysfs_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct fimc_md *fmd = platform_get_drvdata(pdev);
+
+	if (fmd->user_subdev_api)
+		return strlcpy(buf, "Sub-device API (sub-dev)\n", PAGE_SIZE);
+
+	return strlcpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE);
+}
+
+static ssize_t fimc_md_sysfs_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct fimc_md *fmd = platform_get_drvdata(pdev);
+	bool subdev_api;
+	int i;
+
+	if (!strcmp(buf, "vid-dev\n"))
+		subdev_api = false;
+	else if (!strcmp(buf, "sub-dev\n"))
+		subdev_api = true;
+	else
+		return count;
+
+	fmd->user_subdev_api = subdev_api;
+	for (i = 0; i < FIMC_MAX_DEVS; i++)
+		if (fmd->fimc[i])
+			fmd->fimc[i]->vid_cap.user_subdev_api = subdev_api;
+	return count;
+}
+/*
+ * This device attribute is to select video pipeline configuration method.
+ * There are following valid values:
+ *  vid-dev - for V4L2 video node API only, subdevice will be configured
+ *  by the host driver.
+ *  sub-dev - for media controller API, subdevs must be configured in user
+ *  space before starting streaming.
+ */
+static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO,
+		   fimc_md_sysfs_show, fimc_md_sysfs_store);
+
+static int __devinit fimc_md_probe(struct platform_device *pdev)
+{
+	struct v4l2_device *v4l2_dev;
+	struct fimc_md *fmd;
+	int ret;
+
+	fmd = kzalloc(sizeof(struct fimc_md), GFP_KERNEL);
+	if (!fmd)
+		return -ENOMEM;
+
+	spin_lock_init(&fmd->slock);
+	fmd->pdev = pdev;
+
+	strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC",
+		sizeof(fmd->media_dev.model));
+	fmd->media_dev.link_notify = fimc_md_link_notify;
+	fmd->media_dev.dev = &pdev->dev;
+
+	v4l2_dev = &fmd->v4l2_dev;
+	v4l2_dev->mdev = &fmd->media_dev;
+	v4l2_dev->notify = fimc_sensor_notify;
+	snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s",
+		 dev_name(&pdev->dev));
+
+	ret = v4l2_device_register(&pdev->dev, &fmd->v4l2_dev);
+	if (ret < 0) {
+		v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret);
+		goto err1;
+	}
+	ret = media_device_register(&fmd->media_dev);
+	if (ret < 0) {
+		v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret);
+		goto err2;
+	}
+	ret = fimc_md_get_clocks(fmd);
+	if (ret)
+		goto err3;
+
+	fmd->user_subdev_api = false;
+	ret = fimc_md_register_platform_entities(fmd);
+	if (ret)
+		goto err3;
+
+	if (pdev->dev.platform_data) {
+		ret = fimc_md_register_sensor_entities(fmd);
+		if (ret)
+			goto err3;
+	}
+	ret = fimc_md_create_links(fmd);
+	if (ret)
+		goto err3;
+	ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
+	if (ret)
+		goto err3;
+	ret = fimc_md_register_video_nodes(fmd);
+	if (ret)
+		goto err3;
+
+	ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode);
+	if (!ret) {
+		platform_set_drvdata(pdev, fmd);
+		return 0;
+	}
+err3:
+	media_device_unregister(&fmd->media_dev);
+	fimc_md_put_clocks(fmd);
+	fimc_md_unregister_entities(fmd);
+err2:
+	v4l2_device_unregister(&fmd->v4l2_dev);
+err1:
+	kfree(fmd);
+	return ret;
+}
+
+static int __devexit fimc_md_remove(struct platform_device *pdev)
+{
+	struct fimc_md *fmd = platform_get_drvdata(pdev);
+
+	if (!fmd)
+		return 0;
+	device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
+	fimc_md_unregister_entities(fmd);
+	media_device_unregister(&fmd->media_dev);
+	fimc_md_put_clocks(fmd);
+	kfree(fmd);
+	return 0;
+}
+
+static struct platform_driver fimc_md_driver = {
+	.probe		= fimc_md_probe,
+	.remove		= __devexit_p(fimc_md_remove),
+	.driver = {
+		.name	= "s5p-fimc-md",
+		.owner	= THIS_MODULE,
+	}
+};
+
+int __init fimc_md_init(void)
+{
+	int ret;
+	request_module("s5p-csis");
+	ret = fimc_register_driver();
+	if (ret)
+		return ret;
+	return platform_driver_register(&fimc_md_driver);
+}
+void __exit fimc_md_exit(void)
+{
+	platform_driver_unregister(&fimc_md_driver);
+	fimc_unregister_driver();
+}
+
+module_init(fimc_md_init);
+module_exit(fimc_md_exit);
+
+MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
+MODULE_DESCRIPTION("S5P FIMC camera host interface/video postprocessor driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("2.0.1");
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/fimc-mdevice.h linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/fimc-mdevice.h
--- linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/fimc-mdevice.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/fimc-mdevice.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+#ifndef FIMC_MDEVICE_H_
+#define FIMC_MDEVICE_H_
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <media/media-device.h>
+#include <media/media-entity.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#include "fimc-core.h"
+#include "mipi-csis.h"
+
+/* Group IDs of sensor, MIPI CSIS and the writeback subdevs. */
+#define SENSOR_GROUP_ID		(1 << 8)
+#define CSIS_GROUP_ID		(1 << 9)
+#define WRITEBACK_GROUP_ID	(1 << 10)
+
+#define FIMC_MAX_SENSORS	8
+#define FIMC_MAX_CAMCLKS	2
+
+struct fimc_csis_info {
+	struct v4l2_subdev *sd;
+	int id;
+};
+
+struct fimc_camclk_info {
+	struct clk *clock;
+	int use_count;
+	unsigned long frequency;
+};
+
+/**
+ * struct fimc_sensor_info - image data source subdev information
+ * @pdata: sensor's atrributes passed as media device's platform data
+ * @subdev: image sensor v4l2 subdev
+ * @host: fimc device the sensor is currently linked to
+ * @clk_on: sclk_cam clock's state associated with this subdev
+ *
+ * This data structure applies to image sensor and the writeback subdevs.
+ */
+struct fimc_sensor_info {
+	struct s5p_fimc_isp_info *pdata;
+	struct v4l2_subdev *subdev;
+	struct fimc_dev *host;
+	bool clk_on;
+};
+
+/**
+ * struct fimc_md - fimc media device information
+ * @csis: MIPI CSIS subdevs data
+ * @sensor: array of registered sensor subdevs
+ * @num_sensors: actual number of registered sensors
+ * @camclk: external sensor clock information
+ * @fimc: array of registered fimc devices
+ * @media_dev: top level media device
+ * @v4l2_dev: top level v4l2_device holding up the subdevs
+ * @pdev: platform device this media device is hooked up into
+ * @user_subdev_api: true if subdevs are not configured by the host driver
+ * @slock: spinlock protecting @sensor array
+ */
+struct fimc_md {
+	struct fimc_csis_info csis[CSIS_MAX_ENTITIES];
+	struct fimc_sensor_info sensor[FIMC_MAX_SENSORS];
+	int num_sensors;
+	struct fimc_camclk_info camclk[FIMC_MAX_CAMCLKS];
+	struct fimc_dev *fimc[FIMC_MAX_DEVS];
+	struct media_device media_dev;
+	struct v4l2_device v4l2_dev;
+	struct platform_device *pdev;
+	bool user_subdev_api;
+	spinlock_t slock;
+};
+
+#define is_subdev_pad(pad) (pad == NULL || \
+	media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV)
+
+#define me_subtype(me) \
+	((me->type) & (MEDIA_ENT_TYPE_MASK | MEDIA_ENT_SUBTYPE_MASK))
+
+#define subdev_has_devnode(__sd) (__sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)
+
+static inline struct fimc_md *entity_to_fimc_mdev(struct media_entity *me)
+{
+	return me->parent == NULL ? NULL :
+		container_of(me->parent, struct fimc_md, media_dev);
+}
+
+static inline void fimc_md_graph_lock(struct fimc_dev *fimc)
+{
+	BUG_ON(fimc->vid_cap.vfd == NULL);
+	mutex_lock(&fimc->vid_cap.vfd->entity.parent->graph_mutex);
+}
+
+static inline void fimc_md_graph_unlock(struct fimc_dev *fimc)
+{
+	BUG_ON(fimc->vid_cap.vfd == NULL);
+	mutex_unlock(&fimc->vid_cap.vfd->entity.parent->graph_mutex);
+}
+
+int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on);
+void fimc_pipeline_prepare(struct fimc_dev *fimc, struct media_entity *me);
+int fimc_pipeline_initialize(struct fimc_dev *fimc, struct media_entity *me,
+			     bool resume);
+int fimc_pipeline_shutdown(struct fimc_dev *fimc);
+int fimc_pipeline_s_power(struct fimc_dev *fimc, int state);
+int fimc_pipeline_s_stream(struct fimc_dev *fimc, int state);
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/fimc-reg.c linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/fimc-reg.c
--- linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/fimc-reg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/fimc-reg.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,30 +30,25 @@
 	cfg = readl(dev->regs + S5P_CIGCTRL);
 	cfg |= (S5P_CIGCTRL_SWRST | S5P_CIGCTRL_IRQ_LEVEL);
 	writel(cfg, dev->regs + S5P_CIGCTRL);
-	udelay(1000);
+	udelay(10);
 
 	cfg = readl(dev->regs + S5P_CIGCTRL);
 	cfg &= ~S5P_CIGCTRL_SWRST;
 	writel(cfg, dev->regs + S5P_CIGCTRL);
+
+	if (dev->variant->out_buf_count > 4)
+		fimc_hw_set_dma_seq(dev, 0xF);
 }
 
 static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx)
 {
 	u32 flip = S5P_MSCTRL_FLIP_NORMAL;
 
-	switch (ctx->flip) {
-	case FLIP_X_AXIS:
+	if (ctx->hflip)
 		flip = S5P_MSCTRL_FLIP_X_MIRROR;
-		break;
-	case FLIP_Y_AXIS:
+	if (ctx->vflip)
 		flip = S5P_MSCTRL_FLIP_Y_MIRROR;
-		break;
-	case FLIP_XY_AXIS:
-		flip = S5P_MSCTRL_FLIP_180;
-		break;
-	default:
-		break;
-	}
+
 	if (ctx->rotation <= 90)
 		return flip;
 
@@ -64,19 +59,11 @@
 {
 	u32 flip = S5P_CITRGFMT_FLIP_NORMAL;
 
-	switch (ctx->flip) {
-	case FLIP_X_AXIS:
-		flip = S5P_CITRGFMT_FLIP_X_MIRROR;
-		break;
-	case FLIP_Y_AXIS:
-		flip = S5P_CITRGFMT_FLIP_Y_MIRROR;
-		break;
-	case FLIP_XY_AXIS:
-		flip = S5P_CITRGFMT_FLIP_180;
-		break;
-	default:
-		break;
-	}
+	if (ctx->hflip)
+		flip |= S5P_CITRGFMT_FLIP_X_MIRROR;
+	if (ctx->vflip)
+		flip |= S5P_CITRGFMT_FLIP_Y_MIRROR;
+
 	if (ctx->rotation <= 90)
 		return flip;
 
@@ -267,7 +254,14 @@
 	struct fimc_scaler *sc = &ctx->scaler;
 	struct fimc_frame *src_frame = &ctx->s_frame;
 	struct fimc_frame *dst_frame = &ctx->d_frame;
-	u32 cfg = 0;
+
+	u32 cfg = readl(dev->regs + S5P_CISCCTRL);
+
+	cfg &= ~(S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE |
+		 S5P_CISCCTRL_SCALEUP_H | S5P_CISCCTRL_SCALEUP_V |
+		 S5P_CISCCTRL_SCALERBYPASS | S5P_CISCCTRL_ONE2ONE |
+		 S5P_CISCCTRL_INRGB_FMT_MASK | S5P_CISCCTRL_OUTRGB_FMT_MASK |
+		 S5P_CISCCTRL_INTERLACE | S5P_CISCCTRL_RGB_EXT);
 
 	if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
 		cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE);
@@ -324,9 +318,9 @@
 	fimc_hw_set_scaler(ctx);
 
 	cfg = readl(dev->regs + S5P_CISCCTRL);
+	cfg &= ~(S5P_CISCCTRL_MHRATIO_MASK | S5P_CISCCTRL_MVRATIO_MASK);
 
 	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);
@@ -339,7 +333,6 @@
 		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);
@@ -368,17 +361,19 @@
 	writel(cfg | S5P_CIIMGCPT_IMGCPTEN, dev->regs + S5P_CIIMGCPT);
 }
 
-void fimc_hw_set_effect(struct fimc_ctx *ctx)
+void fimc_hw_set_effect(struct fimc_ctx *ctx, bool active)
 {
 	struct fimc_dev *dev = ctx->fimc_dev;
 	struct fimc_effect *effect = &ctx->effect;
-	u32 cfg = (S5P_CIIMGEFF_IE_ENABLE | S5P_CIIMGEFF_IE_SC_AFTER);
-
-	cfg |= effect->type;
+	u32 cfg = 0;
 
-	if (effect->type == S5P_FIMC_EFFECT_ARBITRARY) {
-		cfg |= S5P_CIIMGEFF_PAT_CB(effect->pat_cb);
-		cfg |= S5P_CIIMGEFF_PAT_CR(effect->pat_cr);
+	if (active) {
+		cfg |= S5P_CIIMGEFF_IE_SC_AFTER | S5P_CIIMGEFF_IE_ENABLE;
+		cfg |= effect->type;
+		if (effect->type == S5P_FIMC_EFFECT_ARBITRARY) {
+			cfg |= S5P_CIIMGEFF_PAT_CB(effect->pat_cb);
+			cfg |= S5P_CIIMGEFF_PAT_CR(effect->pat_cr);
+		}
 	}
 
 	writel(cfg, dev->regs + S5P_CIIMGEFF);
@@ -547,20 +542,24 @@
 	u32 cfg = readl(fimc->regs + S5P_CIGCTRL);
 
 	cfg &= ~(S5P_CIGCTRL_INVPOLPCLK | S5P_CIGCTRL_INVPOLVSYNC |
-		 S5P_CIGCTRL_INVPOLHREF | S5P_CIGCTRL_INVPOLHSYNC);
+		 S5P_CIGCTRL_INVPOLHREF | S5P_CIGCTRL_INVPOLHSYNC |
+		 S5P_CIGCTRL_INVPOLFIELD);
 
-	if (cam->flags & FIMC_CLK_INV_PCLK)
+	if (cam->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
 		cfg |= S5P_CIGCTRL_INVPOLPCLK;
 
-	if (cam->flags & FIMC_CLK_INV_VSYNC)
+	if (cam->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
 		cfg |= S5P_CIGCTRL_INVPOLVSYNC;
 
-	if (cam->flags & FIMC_CLK_INV_HREF)
+	if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
 		cfg |= S5P_CIGCTRL_INVPOLHREF;
 
-	if (cam->flags & FIMC_CLK_INV_HSYNC)
+	if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
 		cfg |= S5P_CIGCTRL_INVPOLHSYNC;
 
+	if (cam->flags & V4L2_MBUS_FIELD_EVEN_LOW)
+		cfg |= S5P_CIGCTRL_INVPOLFIELD;
+
 	writel(cfg, fimc->regs + S5P_CIGCTRL);
 
 	return 0;
@@ -588,7 +587,7 @@
 
 	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) {
+			if (fimc->vid_cap.mf.code == pix_desc[i].pixelcode) {
 				cfg = pix_desc[i].cisrcfmt;
 				bus_width = pix_desc[i].bus_width;
 				break;
@@ -596,9 +595,9 @@
 		}
 
 		if (i == ARRAY_SIZE(pix_desc)) {
-			v4l2_err(&fimc->vid_cap.v4l2_dev,
+			v4l2_err(fimc->vid_cap.vfd,
 				 "Camera color format not supported: %d\n",
-				 fimc->vid_cap.fmt.code);
+				 fimc->vid_cap.mf.code);
 			return -EINVAL;
 		}
 
@@ -608,6 +607,9 @@
 			else if (bus_width == 16)
 				cfg |= S5P_CISRCFMT_ITU601_16BIT;
 		} /* else defaults to ITU-R BT.656 8-bit */
+	} else if (cam->bus_type == FIMC_MIPI_CSI2) {
+		if (fimc_fmt_is_jpeg(f->fmt->color))
+			cfg |= S5P_CISRCFMT_ITU601_8BIT;
 	}
 
 	cfg |= S5P_CISRCFMT_HSIZE(f->o_width) | S5P_CISRCFMT_VSIZE(f->o_height);
@@ -649,7 +651,7 @@
 	/* Select ITU B interface, disable Writeback path and test pattern. */
 	cfg &= ~(S5P_CIGCTRL_TESTPAT_MASK | S5P_CIGCTRL_SELCAM_ITU_A |
 		S5P_CIGCTRL_SELCAM_MIPI | S5P_CIGCTRL_CAMIF_SELWB |
-		S5P_CIGCTRL_SELCAM_MIPI_A);
+		S5P_CIGCTRL_SELCAM_MIPI_A | S5P_CIGCTRL_CAM_JPEG);
 
 	if (cam->bus_type == FIMC_MIPI_CSI2) {
 		cfg |= S5P_CIGCTRL_SELCAM_MIPI;
@@ -658,11 +660,18 @@
 			cfg |= S5P_CIGCTRL_SELCAM_MIPI_A;
 
 		/* TODO: add remaining supported formats. */
-		if (vid_cap->fmt.code == V4L2_MBUS_FMT_VYUY8_2X8) {
+		switch (vid_cap->mf.code) {
+		case V4L2_MBUS_FMT_VYUY8_2X8:
 			tmp = S5P_CSIIMGFMT_YCBCR422_8BIT;
-		} else {
-			err("camera image format not supported: %d",
-			    vid_cap->fmt.code);
+			break;
+		case V4L2_MBUS_FMT_JPEG_1X8:
+			tmp = S5P_CSIIMGFMT_USER(1);
+			cfg |= S5P_CIGCTRL_CAM_JPEG;
+			break;
+		default:
+			v4l2_err(fimc->vid_cap.vfd,
+				 "Not supported camera pixel format: %d",
+				 vid_cap->mf.code);
 			return -EINVAL;
 		}
 		tmp |= (cam->csi_data_align == 32) << 8;
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/Makefile linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,4 @@
-s5p-fimc-objs := fimc-core.o fimc-reg.o fimc-capture.o
+s5p-fimc-objs := fimc-core.o fimc-reg.o fimc-capture.o fimc-mdevice.o
 s5p-csis-objs := mipi-csis.o
 
 obj-$(CONFIG_VIDEO_S5P_MIPI_CSIS)	+= s5p-csis.o
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/mipi-csis.c linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/mipi-csis.c
--- linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/mipi-csis.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/mipi-csis.c	2012-01-04 18:55:44.000000000 -0500
@@ -81,6 +81,12 @@
 };
 #define NUM_CSIS_CLOCKS	ARRAY_SIZE(csi_clock_name)
 
+static const char * const csis_supply_name[] = {
+	"vdd11", /* 1.1V or 1.2V (s5pc100) MIPI CSI suppply */
+	"vdd18", /* VDD 1.8V and MIPI CSI PLL supply */
+};
+#define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name)
+
 enum {
 	ST_POWERED	= 1,
 	ST_STREAMING	= 2,
@@ -109,9 +115,9 @@
 	struct platform_device *pdev;
 	struct resource *regs_res;
 	void __iomem *regs;
+	struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
 	struct clk *clock[NUM_CSIS_CLOCKS];
 	int irq;
-	struct regulator *supply;
 	u32 flags;
 	const struct csis_pix_format *csis_fmt;
 	struct v4l2_mbus_framefmt format;
@@ -460,6 +466,7 @@
 	struct resource *regs_res;
 	struct csis_state *state;
 	int ret = -ENOMEM;
+	int i;
 
 	state = kzalloc(sizeof(*state), GFP_KERNEL);
 	if (!state)
@@ -519,14 +526,13 @@
 		goto e_clkput;
 	}
 
-	if (!pdata->fixed_phy_vdd) {
-		state->supply = regulator_get(&pdev->dev, "vdd");
-		if (IS_ERR(state->supply)) {
-			ret = PTR_ERR(state->supply);
-			state->supply = NULL;
-			goto e_clkput;
-		}
-	}
+	for (i = 0; i < CSIS_NUM_SUPPLIES; i++)
+		state->supplies[i].supply = csis_supply_name[i];
+
+	ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES,
+				 state->supplies);
+	if (ret)
+		goto e_clkput;
 
 	ret = request_irq(state->irq, s5pcsis_irq_handler, 0,
 			  dev_name(&pdev->dev), state);
@@ -553,7 +559,6 @@
 	/* .. and a pointer to the subdev. */
 	platform_set_drvdata(pdev, &state->sd);
 
-	state->flags = ST_SUSPENDED;
 	pm_runtime_enable(&pdev->dev);
 
 	return 0;
@@ -561,8 +566,7 @@
 e_irqfree:
 	free_irq(state->irq, state);
 e_regput:
-	if (state->supply)
-		regulator_put(state->supply);
+	regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies);
 e_clkput:
 	clk_disable(state->clock[CSIS_CLK_MUX]);
 	s5pcsis_clk_put(state);
@@ -575,7 +579,7 @@
 	return ret;
 }
 
-static int s5pcsis_suspend(struct device *dev)
+static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
 {
 	struct s5p_platform_mipi_csis *pdata = dev->platform_data;
 	struct platform_device *pdev = to_platform_device(dev);
@@ -592,21 +596,21 @@
 		ret = pdata->phy_enable(state->pdev, false);
 		if (ret)
 			goto unlock;
-		if (state->supply) {
-			ret = regulator_disable(state->supply);
-			if (ret)
-				goto unlock;
-		}
+		ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES,
+					     state->supplies);
+		if (ret)
+			goto unlock;
 		clk_disable(state->clock[CSIS_CLK_GATE]);
 		state->flags &= ~ST_POWERED;
+		if (!runtime)
+			state->flags |= ST_SUSPENDED;
 	}
-	state->flags |= ST_SUSPENDED;
  unlock:
 	mutex_unlock(&state->lock);
 	return ret ? -EAGAIN : 0;
 }
 
-static int s5pcsis_resume(struct device *dev)
+static int s5pcsis_pm_resume(struct device *dev, bool runtime)
 {
 	struct s5p_platform_mipi_csis *pdata = dev->platform_data;
 	struct platform_device *pdev = to_platform_device(dev);
@@ -618,20 +622,20 @@
 		 __func__, state->flags);
 
 	mutex_lock(&state->lock);
-	if (!(state->flags & ST_SUSPENDED))
+	if (!runtime && !(state->flags & ST_SUSPENDED))
 		goto unlock;
 
 	if (!(state->flags & ST_POWERED)) {
-		if (state->supply)
-			ret = regulator_enable(state->supply);
+		ret = regulator_bulk_enable(CSIS_NUM_SUPPLIES,
+					    state->supplies);
 		if (ret)
 			goto unlock;
-
 		ret = pdata->phy_enable(state->pdev, true);
 		if (!ret) {
 			state->flags |= ST_POWERED;
-		} else if (state->supply) {
-			regulator_disable(state->supply);
+		} else {
+			regulator_bulk_disable(CSIS_NUM_SUPPLIES,
+					       state->supplies);
 			goto unlock;
 		}
 		clk_enable(state->clock[CSIS_CLK_GATE]);
@@ -646,24 +650,26 @@
 }
 
 #ifdef CONFIG_PM_SLEEP
-static int s5pcsis_pm_suspend(struct device *dev)
+static int s5pcsis_suspend(struct device *dev)
 {
-	return s5pcsis_suspend(dev);
+	return s5pcsis_pm_suspend(dev, false);
 }
 
-static int s5pcsis_pm_resume(struct device *dev)
+static int s5pcsis_resume(struct device *dev)
 {
-	int ret;
-
-	ret = s5pcsis_resume(dev);
+	return s5pcsis_pm_resume(dev, false);
+}
+#endif
 
-	if (!ret) {
-		pm_runtime_disable(dev);
-		ret = pm_runtime_set_active(dev);
-		pm_runtime_enable(dev);
-	}
+#ifdef CONFIG_PM_RUNTIME
+static int s5pcsis_runtime_suspend(struct device *dev)
+{
+	return s5pcsis_pm_suspend(dev, true);
+}
 
-	return ret;
+static int s5pcsis_runtime_resume(struct device *dev)
+{
+	return s5pcsis_pm_resume(dev, true);
 }
 #endif
 
@@ -679,8 +685,7 @@
 	pm_runtime_set_suspended(&pdev->dev);
 
 	s5pcsis_clk_put(state);
-	if (state->supply)
-		regulator_put(state->supply);
+	regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies);
 
 	media_entity_cleanup(&state->sd.entity);
 	free_irq(state->irq, state);
@@ -692,8 +697,9 @@
 }
 
 static const struct dev_pm_ops s5pcsis_pm_ops = {
-	SET_RUNTIME_PM_OPS(s5pcsis_suspend, s5pcsis_resume, NULL)
-	SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_pm_suspend, s5pcsis_pm_resume)
+	SET_RUNTIME_PM_OPS(s5pcsis_runtime_suspend, s5pcsis_runtime_resume,
+			   NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume)
 };
 
 static struct platform_driver s5pcsis_driver = {
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/regs-fimc.h linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/regs-fimc.h
--- linux-libre-3.1-gnu/drivers/media/video/s5p-fimc/regs-fimc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-fimc/regs-fimc.h	2012-01-04 18:55:44.000000000 -0500
@@ -54,12 +54,14 @@
 #define S5P_CIGCTRL_IRQ_CLR		(1 << 19)
 #define S5P_CIGCTRL_IRQ_ENABLE		(1 << 16)
 #define S5P_CIGCTRL_SHDW_DISABLE	(1 << 12)
+#define S5P_CIGCTRL_CAM_JPEG		(1 << 8)
 #define S5P_CIGCTRL_SELCAM_MIPI_A	(1 << 7)
 #define S5P_CIGCTRL_CAMIF_SELWB		(1 << 6)
 /* 0 - ITU601; 1 - ITU709 */
 #define S5P_CIGCTRL_CSC_ITU601_709	(1 << 5)
 #define S5P_CIGCTRL_INVPOLHSYNC		(1 << 4)
 #define S5P_CIGCTRL_SELCAM_MIPI		(1 << 3)
+#define S5P_CIGCTRL_INVPOLFIELD		(1 << 1)
 #define S5P_CIGCTRL_INTERLACE		(1 << 0)
 
 /* Window offset 2 */
@@ -184,7 +186,6 @@
 
 /* Image effect */
 #define S5P_CIIMGEFF			0xd0
-#define S5P_CIIMGEFF_IE_DISABLE		(0 << 30)
 #define S5P_CIIMGEFF_IE_ENABLE		(1 << 30)
 #define S5P_CIIMGEFF_IE_SC_BEFORE	(0 << 29)
 #define S5P_CIIMGEFF_IE_SC_AFTER	(1 << 29)
@@ -286,10 +287,8 @@
 #define S5P_CSIIMGFMT_RAW8		0x2a
 #define S5P_CSIIMGFMT_RAW10		0x2b
 #define S5P_CSIIMGFMT_RAW12		0x2c
-#define S5P_CSIIMGFMT_USER1		0x30
-#define S5P_CSIIMGFMT_USER2		0x31
-#define S5P_CSIIMGFMT_USER3		0x32
-#define S5P_CSIIMGFMT_USER4		0x33
+/* User defined formats. x = 0...16. */
+#define S5P_CSIIMGFMT_USER(x)		(0x30 + x - 1)
 
 /* Output frame buffer sequence mask */
 #define S5P_CIFCNTSEQ			0x1FC
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-mfc/s5p_mfc.c linux-libre-3.2-gnu/drivers/media/video/s5p-mfc/s5p_mfc.c
--- linux-libre-3.1-gnu/drivers/media/video/s5p-mfc/s5p_mfc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-mfc/s5p_mfc.c	2012-01-04 18:55:44.000000000 -0500
@@ -202,7 +202,7 @@
 	   appropraite flags */
 	src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
 	list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
-		if (vb2_dma_contig_plane_paddr(dst_buf->b, 0) == dec_y_addr) {
+		if (vb2_dma_contig_plane_dma_addr(dst_buf->b, 0) == dec_y_addr) {
 			memcpy(&dst_buf->b->v4l2_buf.timecode,
 				&src_buf->b->v4l2_buf.timecode,
 				sizeof(struct v4l2_timecode));
@@ -248,7 +248,7 @@
 	 * check which videobuf does it correspond to */
 	list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
 		/* Check if this is the buffer we're looking for */
-		if (vb2_dma_contig_plane_paddr(dst_buf->b, 0) == dspl_y_addr) {
+		if (vb2_dma_contig_plane_dma_addr(dst_buf->b, 0) == dspl_y_addr) {
 			list_del(&dst_buf->list);
 			ctx->dst_queue_cnt--;
 			dst_buf->b->v4l2_buf.sequence = ctx->sequence;
@@ -940,9 +940,8 @@
 	return !strcmp(dev_name(dev), (char *)data);
 }
 
-
 /* MFC probe function */
-static int __devinit s5p_mfc_probe(struct platform_device *pdev)
+static int s5p_mfc_probe(struct platform_device *pdev)
 {
 	struct s5p_mfc_dev *dev;
 	struct video_device *vfd;
@@ -1236,7 +1235,7 @@
 			   NULL)
 };
 
-static struct platform_driver s5p_mfc_pdrv = {
+static struct platform_driver s5p_mfc_driver = {
 	.probe	= s5p_mfc_probe,
 	.remove	= __devexit_p(s5p_mfc_remove),
 	.driver	= {
@@ -1254,15 +1253,15 @@
 	int ret;
 
 	pr_info("%s", banner);
-	ret = platform_driver_register(&s5p_mfc_pdrv);
+	ret = platform_driver_register(&s5p_mfc_driver);
 	if (ret)
 		pr_err("Platform device registration failed.\n");
 	return ret;
 }
 
-static void __devexit s5p_mfc_exit(void)
+static void __exit s5p_mfc_exit(void)
 {
-	platform_driver_unregister(&s5p_mfc_pdrv);
+	platform_driver_unregister(&s5p_mfc_driver);
 }
 
 module_init(s5p_mfc_init);
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-mfc/s5p_mfc_dec.c linux-libre-3.2-gnu/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
--- linux-libre-3.1-gnu/drivers/media/video/s5p-mfc/s5p_mfc_dec.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-mfc/s5p_mfc_dec.c	2012-01-04 18:55:44.000000000 -0500
@@ -165,7 +165,7 @@
 		.maximum = 32,
 		.step = 1,
 		.default_value = 1,
-		.is_volatile = 1,
+		.flags = V4L2_CTRL_FLAG_VOLATILE,
 	},
 };
 
@@ -220,8 +220,8 @@
 	strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1);
 	cap->bus_info[0] = 0;
 	cap->version = KERNEL_VERSION(1, 0, 0);
-	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
-						    | V4L2_CAP_STREAMING;
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+			V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING;
 	return 0;
 }
 
@@ -744,9 +744,10 @@
 	.vidioc_g_crop = vidioc_g_crop,
 };
 
-static int s5p_mfc_queue_setup(struct vb2_queue *vq, unsigned int *buf_count,
-			       unsigned int *plane_count, unsigned long psize[],
-			       void *allocators[])
+static int s5p_mfc_queue_setup(struct vb2_queue *vq,
+			const struct v4l2_format *fmt, unsigned int *buf_count,
+			unsigned int *plane_count, unsigned int psize[],
+			void *allocators[])
 {
 	struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
 
@@ -824,7 +825,7 @@
 			return 0;
 		for (i = 0; i <= ctx->src_fmt->num_planes ; i++) {
 			if (IS_ERR_OR_NULL(ERR_PTR(
-					vb2_dma_contig_plane_paddr(vb, i)))) {
+					vb2_dma_contig_plane_dma_addr(vb, i)))) {
 				mfc_err("Plane mem not allocated\n");
 				return -EINVAL;
 			}
@@ -837,13 +838,13 @@
 		i = vb->v4l2_buf.index;
 		ctx->dst_bufs[i].b = vb;
 		ctx->dst_bufs[i].cookie.raw.luma =
-					vb2_dma_contig_plane_paddr(vb, 0);
+					vb2_dma_contig_plane_dma_addr(vb, 0);
 		ctx->dst_bufs[i].cookie.raw.chroma =
-					vb2_dma_contig_plane_paddr(vb, 1);
+					vb2_dma_contig_plane_dma_addr(vb, 1);
 		ctx->dst_bufs_cnt++;
 	} else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 		if (IS_ERR_OR_NULL(ERR_PTR(
-					vb2_dma_contig_plane_paddr(vb, 0)))) {
+					vb2_dma_contig_plane_dma_addr(vb, 0)))) {
 			mfc_err("Plane memory not allocated\n");
 			return -EINVAL;
 		}
@@ -855,7 +856,7 @@
 		i = vb->v4l2_buf.index;
 		ctx->src_bufs[i].b = vb;
 		ctx->src_bufs[i].cookie.stream =
-					vb2_dma_contig_plane_paddr(vb, 0);
+					vb2_dma_contig_plane_dma_addr(vb, 0);
 		ctx->src_bufs_cnt++;
 	} else {
 		mfc_err("s5p_mfc_buf_init: unknown queue type\n");
@@ -864,7 +865,7 @@
 	return 0;
 }
 
-static int s5p_mfc_start_streaming(struct vb2_queue *q)
+static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
 {
 	struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
 	struct s5p_mfc_dev *dev = ctx->dev;
@@ -1020,7 +1021,7 @@
 			return ctx->ctrl_handler.error;
 		}
 		if (controls[i].is_volatile && ctx->ctrls[i])
-			ctx->ctrls[i]->is_volatile = 1;
+			ctx->ctrls[i]->flags |= V4L2_CTRL_FLAG_VOLATILE;
 	}
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-mfc/s5p_mfc_enc.c linux-libre-3.2-gnu/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
--- linux-libre-3.1-gnu/drivers/media/video/s5p-mfc/s5p_mfc_enc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-mfc/s5p_mfc_enc.c	2012-01-04 18:55:44.000000000 -0500
@@ -61,7 +61,7 @@
 		.num_planes = 1,
 	},
 	{
-		.name = "H264 Encoded Stream",
+		.name = "H263 Encoded Stream",
 		.fourcc = V4L2_PIX_FMT_H263,
 		.codec_mode = S5P_FIMV_CODEC_H263_ENC,
 		.type = MFC_FMT_ENC,
@@ -599,8 +599,8 @@
 	while (!list_empty(&ctx->ref_queue)) {
 		mb_entry = list_entry((&ctx->ref_queue)->next,
 						struct s5p_mfc_buf, list);
-		mb_y_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 0);
-		mb_c_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 1);
+		mb_y_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 0);
+		mb_c_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 1);
 		list_del(&mb_entry->list);
 		ctx->ref_queue_cnt--;
 		list_add_tail(&mb_entry->list, &ctx->src_queue);
@@ -622,7 +622,7 @@
 
 	spin_lock_irqsave(&dev->irqlock, flags);
 	dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
-	dst_addr = vb2_dma_contig_plane_paddr(dst_mb->b, 0);
+	dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
 	dst_size = vb2_plane_size(dst_mb->b, 0);
 	s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
 	spin_unlock_irqrestore(&dev->irqlock, flags);
@@ -668,14 +668,14 @@
 
 	spin_lock_irqsave(&dev->irqlock, flags);
 	src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-	src_y_addr = vb2_dma_contig_plane_paddr(src_mb->b, 0);
-	src_c_addr = vb2_dma_contig_plane_paddr(src_mb->b, 1);
+	src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
+	src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
 	s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
 	spin_unlock_irqrestore(&dev->irqlock, flags);
 
 	spin_lock_irqsave(&dev->irqlock, flags);
 	dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
-	dst_addr = vb2_dma_contig_plane_paddr(dst_mb->b, 0);
+	dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
 	dst_size = vb2_plane_size(dst_mb->b, 0);
 	s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
 	spin_unlock_irqrestore(&dev->irqlock, flags);
@@ -703,8 +703,8 @@
 	if (slice_type >= 0) {
 		s5p_mfc_get_enc_frame_buffer(ctx, &enc_y_addr, &enc_c_addr);
 		list_for_each_entry(mb_entry, &ctx->src_queue, list) {
-			mb_y_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 0);
-			mb_c_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 1);
+			mb_y_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 0);
+			mb_c_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 1);
 			if ((enc_y_addr == mb_y_addr) &&
 						(enc_c_addr == mb_c_addr)) {
 				list_del(&mb_entry->list);
@@ -715,8 +715,8 @@
 			}
 		}
 		list_for_each_entry(mb_entry, &ctx->ref_queue, list) {
-			mb_y_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 0);
-			mb_c_addr = vb2_dma_contig_plane_paddr(mb_entry->b, 1);
+			mb_y_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 0);
+			mb_c_addr = vb2_dma_contig_plane_dma_addr(mb_entry->b, 1);
 			if ((enc_y_addr == mb_y_addr) &&
 						(enc_c_addr == mb_c_addr)) {
 				list_del(&mb_entry->list);
@@ -785,8 +785,8 @@
 	strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1);
 	cap->bus_info[0] = 0;
 	cap->version = KERNEL_VERSION(1, 0, 0);
-	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
-			  | V4L2_CAP_VIDEO_OUTPUT
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE
+			  | V4L2_CAP_VIDEO_OUTPUT_MPLANE
 			  | V4L2_CAP_STREAMING;
 	return 0;
 }
@@ -1501,20 +1501,21 @@
 		return -EINVAL;
 	}
 	for (i = 0; i < fmt->num_planes; i++) {
-		if (!vb2_dma_contig_plane_paddr(vb, i)) {
+		if (!vb2_dma_contig_plane_dma_addr(vb, i)) {
 			mfc_err("failed to get plane cookie\n");
 			return -EINVAL;
 		}
 		mfc_debug(2, "index: %d, plane[%d] cookie: 0x%08zx",
 				vb->v4l2_buf.index, i,
-				vb2_dma_contig_plane_paddr(vb, i));
+				vb2_dma_contig_plane_dma_addr(vb, i));
 	}
 	return 0;
 }
 
 static int s5p_mfc_queue_setup(struct vb2_queue *vq,
-		       unsigned int *buf_count, unsigned int *plane_count,
-		       unsigned long psize[], void *allocators[])
+			const struct v4l2_format *fmt,
+			unsigned int *buf_count, unsigned int *plane_count,
+			unsigned int psize[], void *allocators[])
 {
 	struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
 
@@ -1584,7 +1585,7 @@
 		i = vb->v4l2_buf.index;
 		ctx->dst_bufs[i].b = vb;
 		ctx->dst_bufs[i].cookie.stream =
-					vb2_dma_contig_plane_paddr(vb, 0);
+					vb2_dma_contig_plane_dma_addr(vb, 0);
 		ctx->dst_bufs_cnt++;
 	} else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 		ret = check_vb_with_fmt(ctx->src_fmt, vb);
@@ -1593,9 +1594,9 @@
 		i = vb->v4l2_buf.index;
 		ctx->src_bufs[i].b = vb;
 		ctx->src_bufs[i].cookie.raw.luma =
-					vb2_dma_contig_plane_paddr(vb, 0);
+					vb2_dma_contig_plane_dma_addr(vb, 0);
 		ctx->src_bufs[i].cookie.raw.chroma =
-					vb2_dma_contig_plane_paddr(vb, 1);
+					vb2_dma_contig_plane_dma_addr(vb, 1);
 		ctx->src_bufs_cnt++;
 	} else {
 		mfc_err("inavlid queue type: %d\n", vq->type);
@@ -1640,7 +1641,7 @@
 	return 0;
 }
 
-static int s5p_mfc_start_streaming(struct vb2_queue *q)
+static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
 {
 	struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
 	struct s5p_mfc_dev *dev = ctx->dev;
@@ -1814,7 +1815,7 @@
 			return ctx->ctrl_handler.error;
 		}
 		if (controls[i].is_volatile && ctx->ctrls[i])
-			ctx->ctrls[i]->is_volatile = 1;
+			ctx->ctrls[i]->flags |= V4L2_CTRL_FLAG_VOLATILE;
 	}
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-mfc/s5p_mfc_opr.c linux-libre-3.2-gnu/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
--- linux-libre-3.1-gnu/drivers/media/video/s5p-mfc/s5p_mfc_opr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-mfc/s5p_mfc_opr.c	2012-01-04 18:55:44.000000000 -0500
@@ -1135,7 +1135,7 @@
 	temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
 	temp_vb->used = 1;
 	s5p_mfc_set_dec_stream_buffer(ctx,
-		vb2_dma_contig_plane_paddr(temp_vb->b, 0), ctx->consumed_stream,
+		vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), ctx->consumed_stream,
 					temp_vb->b->v4l2_planes[0].bytesused);
 	spin_unlock_irqrestore(&dev->irqlock, flags);
 	index = temp_vb->b->v4l2_buf.index;
@@ -1172,12 +1172,12 @@
 	}
 	src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
 	src_mb->used = 1;
-	src_y_addr = vb2_dma_contig_plane_paddr(src_mb->b, 0);
-	src_c_addr = vb2_dma_contig_plane_paddr(src_mb->b, 1);
+	src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
+	src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
 	s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
 	dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
 	dst_mb->used = 1;
-	dst_addr = vb2_dma_contig_plane_paddr(dst_mb->b, 0);
+	dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
 	dst_size = vb2_plane_size(dst_mb->b, 0);
 	s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
 	spin_unlock_irqrestore(&dev->irqlock, flags);
@@ -1200,7 +1200,7 @@
 	s5p_mfc_set_dec_desc_buffer(ctx);
 	mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
 	s5p_mfc_set_dec_stream_buffer(ctx,
-				vb2_dma_contig_plane_paddr(temp_vb->b, 0),
+				vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
 				0, temp_vb->b->v4l2_planes[0].bytesused);
 	spin_unlock_irqrestore(&dev->irqlock, flags);
 	dev->curr_ctx = ctx->num;
@@ -1219,7 +1219,7 @@
 	s5p_mfc_set_enc_ref_buffer(ctx);
 	spin_lock_irqsave(&dev->irqlock, flags);
 	dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
-	dst_addr = vb2_dma_contig_plane_paddr(dst_mb->b, 0);
+	dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
 	dst_size = vb2_plane_size(dst_mb->b, 0);
 	s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
 	spin_unlock_irqrestore(&dev->irqlock, flags);
@@ -1255,7 +1255,7 @@
 	temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
 	mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
 	s5p_mfc_set_dec_stream_buffer(ctx,
-				vb2_dma_contig_plane_paddr(temp_vb->b, 0),
+				vb2_dma_contig_plane_dma_addr(temp_vb->b, 0),
 				0, temp_vb->b->v4l2_planes[0].bytesused);
 	spin_unlock_irqrestore(&dev->irqlock, flags);
 	dev->curr_ctx = ctx->num;
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-tv/hdmi_drv.c linux-libre-3.2-gnu/drivers/media/video/s5p-tv/hdmi_drv.c
--- linux-libre-3.1-gnu/drivers/media/video/s5p-tv/hdmi_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-tv/hdmi_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -210,20 +210,17 @@
 	/* enable HPD interrupts */
 	hdmi_write_mask(hdev, HDMI_INTC_CON, ~0, HDMI_INTC_EN_GLOBAL |
 		HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
-	/* choose HDMI mode */
+	/* choose DVI mode */
 	hdmi_write_mask(hdev, HDMI_MODE_SEL,
-		HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
+		HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
+	hdmi_write_mask(hdev, HDMI_CON_2, ~0,
+		HDMI_DVI_PERAMBLE_EN | HDMI_DVI_BAND_EN);
 	/* disable bluescreen */
 	hdmi_write_mask(hdev, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
 	/* choose bluescreen (fecal) color */
 	hdmi_writeb(hdev, HDMI_BLUE_SCREEN_0, 0x12);
 	hdmi_writeb(hdev, HDMI_BLUE_SCREEN_1, 0x34);
 	hdmi_writeb(hdev, HDMI_BLUE_SCREEN_2, 0x56);
-	/* enable AVI packet every vsync, fixes purple line problem */
-	hdmi_writeb(hdev, HDMI_AVI_CON, 0x02);
-	/* force YUV444, look to CEA-861-D, table 7 for more detail */
-	hdmi_writeb(hdev, HDMI_AVI_BYTE(0), 2 << 5);
-	hdmi_write_mask(hdev, HDMI_CON_1, 2, 3 << 5);
 }
 
 static void hdmi_timing_apply(struct hdmi_device *hdev,
@@ -443,6 +440,7 @@
 		.height = 480,
 		.code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
 		.field = V4L2_FIELD_NONE,
+		.colorspace = V4L2_COLORSPACE_SRGB,
 	},
 };
 
@@ -475,6 +473,7 @@
 		.height = 720,
 		.code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
 		.field = V4L2_FIELD_NONE,
+		.colorspace = V4L2_COLORSPACE_SRGB,
 	},
 };
 
@@ -507,6 +506,7 @@
 		.height = 1080,
 		.code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
 		.field = V4L2_FIELD_NONE,
+		.colorspace = V4L2_COLORSPACE_SRGB,
 	},
 };
 
@@ -539,6 +539,7 @@
 		.height = 1080,
 		.code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
 		.field = V4L2_FIELD_NONE,
+		.colorspace = V4L2_COLORSPACE_SRGB,
 	},
 };
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-tv/Kconfig linux-libre-3.2-gnu/drivers/media/video/s5p-tv/Kconfig
--- linux-libre-3.1-gnu/drivers/media/video/s5p-tv/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-tv/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -8,7 +8,7 @@
 
 config VIDEO_SAMSUNG_S5P_TV
 	bool "Samsung TV driver for S5P platform (experimental)"
-	depends on PLAT_S5P
+	depends on PLAT_S5P && PM_RUNTIME
 	depends on EXPERIMENTAL
 	default n
 	---help---
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-tv/mixer_grp_layer.c linux-libre-3.2-gnu/drivers/media/video/s5p-tv/mixer_grp_layer.c
--- linux-libre-3.1-gnu/drivers/media/video/s5p-tv/mixer_grp_layer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-tv/mixer_grp_layer.c	2012-01-04 18:55:44.000000000 -0500
@@ -86,7 +86,7 @@
 	dma_addr_t addr = 0;
 
 	if (buf)
-		addr = vb2_dma_contig_plane_paddr(&buf->vb, 0);
+		addr = vb2_dma_contig_plane_dma_addr(&buf->vb, 0);
 	mxr_reg_graph_buffer(layer->mdev, layer->idx, addr);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-tv/mixer.h linux-libre-3.2-gnu/drivers/media/video/s5p-tv/mixer.h
--- linux-libre-3.1-gnu/drivers/media/video/s5p-tv/mixer.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-tv/mixer.h	2012-01-04 18:55:44.000000000 -0500
@@ -111,8 +111,6 @@
 enum mxr_layer_state {
 	/** layers is not shown */
 	MXR_LAYER_IDLE = 0,
-	/** state between STREAMON and hardware start */
-	MXR_LAYER_STREAMING_START,
 	/** layer is shown */
 	MXR_LAYER_STREAMING,
 	/** state before STREAMOFF is finished */
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-tv/mixer_reg.c linux-libre-3.2-gnu/drivers/media/video/s5p-tv/mixer_reg.c
--- linux-libre-3.1-gnu/drivers/media/video/s5p-tv/mixer_reg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-tv/mixer_reg.c	2012-01-04 18:55:44.000000000 -0500
@@ -90,7 +90,7 @@
 	mxr_vsync_set_update(mdev, MXR_DISABLE);
 
 	/* set output in RGB888 mode */
-	mxr_write(mdev, MXR_CFG, MXR_CFG_OUT_YUV444);
+	mxr_write(mdev, MXR_CFG, MXR_CFG_OUT_RGB888);
 
 	/* 16 beat burst in DMA */
 	mxr_write_mask(mdev, MXR_STATUS, MXR_STATUS_16_BURST,
@@ -376,6 +376,12 @@
 	spin_lock_irqsave(&mdev->reg_slock, flags);
 	mxr_vsync_set_update(mdev, MXR_DISABLE);
 
+	/* selecting colorspace accepted by output */
+	if (fmt->colorspace == V4L2_COLORSPACE_JPEG)
+		val |= MXR_CFG_OUT_YUV444;
+	else
+		val |= MXR_CFG_OUT_RGB888;
+
 	/* choosing between interlace and progressive mode */
 	if (fmt->field == V4L2_FIELD_INTERLACED)
 		val |= MXR_CFG_SCAN_INTERLACE;
@@ -394,7 +400,8 @@
 	else
 		WARN(1, "unrecognized mbus height %u!\n", fmt->height);
 
-	mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_SCAN_MASK);
+	mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_SCAN_MASK |
+		MXR_CFG_OUT_MASK);
 
 	val = (fmt->field == V4L2_FIELD_INTERLACED) ? ~0 : 0;
 	vp_write_mask(mdev, VP_MODE, val,
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-tv/mixer_video.c linux-libre-3.2-gnu/drivers/media/video/s5p-tv/mixer_video.c
--- linux-libre-3.1-gnu/drivers/media/video/s5p-tv/mixer_video.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-tv/mixer_video.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <media/v4l2-ioctl.h>
 #include <linux/videodev2.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/version.h>
 #include <linux/timer.h>
 #include <media/videobuf2-dma-contig.h>
@@ -727,8 +728,8 @@
 	.unlocked_ioctl = video_ioctl2,
 };
 
-static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
-	unsigned int *nplanes, unsigned long sizes[],
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
+	unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[],
 	void *alloc_ctxs[])
 {
 	struct mxr_layer *layer = vb2_get_drv_priv(vq);
@@ -764,19 +765,10 @@
 	struct mxr_layer *layer = vb2_get_drv_priv(vb->vb2_queue);
 	struct mxr_device *mdev = layer->mdev;
 	unsigned long flags;
-	int must_start = 0;
 
 	spin_lock_irqsave(&layer->enq_slock, flags);
-	if (layer->state == MXR_LAYER_STREAMING_START) {
-		layer->state = MXR_LAYER_STREAMING;
-		must_start = 1;
-	}
 	list_add_tail(&buffer->list, &layer->enq_list);
 	spin_unlock_irqrestore(&layer->enq_slock, flags);
-	if (must_start) {
-		layer->ops.stream_set(layer, MXR_ENABLE);
-		mxr_streamer_get(mdev);
-	}
 
 	mxr_dbg(mdev, "queuing buffer\n");
 }
@@ -797,13 +789,19 @@
 	mutex_unlock(&layer->mutex);
 }
 
-static int start_streaming(struct vb2_queue *vq)
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct mxr_layer *layer = vb2_get_drv_priv(vq);
 	struct mxr_device *mdev = layer->mdev;
 	unsigned long flags;
 
 	mxr_dbg(mdev, "%s\n", __func__);
+
+	if (count == 0) {
+		mxr_dbg(mdev, "no output buffers queued\n");
+		return -EINVAL;
+	}
+
 	/* block any changes in output configuration */
 	mxr_output_get(mdev);
 
@@ -814,9 +812,12 @@
 	layer->ops.format_set(layer);
 	/* enabling layer in hardware */
 	spin_lock_irqsave(&layer->enq_slock, flags);
-	layer->state = MXR_LAYER_STREAMING_START;
+	layer->state = MXR_LAYER_STREAMING;
 	spin_unlock_irqrestore(&layer->enq_slock, flags);
 
+	layer->ops.stream_set(layer, MXR_ENABLE);
+	mxr_streamer_get(mdev);
+
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-tv/mixer_vp_layer.c linux-libre-3.2-gnu/drivers/media/video/s5p-tv/mixer_vp_layer.c
--- linux-libre-3.1-gnu/drivers/media/video/s5p-tv/mixer_vp_layer.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-tv/mixer_vp_layer.c	2012-01-04 18:55:44.000000000 -0500
@@ -97,9 +97,9 @@
 		mxr_reg_vp_buffer(layer->mdev, luma_addr, chroma_addr);
 		return;
 	}
-	luma_addr[0] = vb2_dma_contig_plane_paddr(&buf->vb, 0);
+	luma_addr[0] = vb2_dma_contig_plane_dma_addr(&buf->vb, 0);
 	if (layer->fmt->num_subframes == 2) {
-		chroma_addr[0] = vb2_dma_contig_plane_paddr(&buf->vb, 1);
+		chroma_addr[0] = vb2_dma_contig_plane_dma_addr(&buf->vb, 1);
 	} else {
 		/* FIXME: mxr_get_plane_size compute integer division,
 		 * which is slow and should not be performed in interrupt */
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-tv/regs-hdmi.h linux-libre-3.2-gnu/drivers/media/video/s5p-tv/regs-hdmi.h
--- linux-libre-3.1-gnu/drivers/media/video/s5p-tv/regs-hdmi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-tv/regs-hdmi.h	2012-01-04 18:55:44.000000000 -0500
@@ -127,6 +127,10 @@
 #define HDMI_BLUE_SCR_EN		(1 << 5)
 #define HDMI_EN				(1 << 0)
 
+/* HDMI_CON_2 */
+#define HDMI_DVI_PERAMBLE_EN		(1 << 5)
+#define HDMI_DVI_BAND_EN		(1 << 1)
+
 /* HDMI_PHY_STATUS */
 #define HDMI_PHY_STATUS_READY		(1 << 0)
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-tv/regs-mixer.h linux-libre-3.2-gnu/drivers/media/video/s5p-tv/regs-mixer.h
--- linux-libre-3.1-gnu/drivers/media/video/s5p-tv/regs-mixer.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-tv/regs-mixer.h	2012-01-04 18:55:44.000000000 -0500
@@ -67,6 +67,7 @@
 /* bits for MXR_CFG */
 #define MXR_CFG_OUT_YUV444		(0 << 8)
 #define MXR_CFG_OUT_RGB888		(1 << 8)
+#define MXR_CFG_OUT_MASK		(1 << 8)
 #define MXR_CFG_DST_SDO			(0 << 7)
 #define MXR_CFG_DST_HDMI		(1 << 7)
 #define MXR_CFG_DST_MASK		(1 << 7)
diff -druN linux-libre-3.1-gnu/drivers/media/video/s5p-tv/sdo_drv.c linux-libre-3.2-gnu/drivers/media/video/s5p-tv/sdo_drv.c
--- linux-libre-3.1-gnu/drivers/media/video/s5p-tv/sdo_drv.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/s5p-tv/sdo_drv.c	2012-01-04 18:55:44.000000000 -0500
@@ -170,6 +170,7 @@
 	fmt->height = sdev->fmt->height;
 	fmt->code = V4L2_MBUS_FMT_FIXED;
 	fmt->field = V4L2_FIELD_INTERLACED;
+	fmt->colorspace = V4L2_COLORSPACE_JPEG;
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/saa7115.c linux-libre-3.2-gnu/drivers/media/video/saa7115.c
--- linux-libre-3.1-gnu/drivers/media/video/saa7115.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/saa7115.c	2012-01-04 18:55:44.000000000 -0500
@@ -793,7 +793,6 @@
 			saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val);
 		else
 			saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val | 0x80);
-		v4l2_ctrl_activate(state->gain, !state->agc->val);
 		break;
 
 	default:
@@ -1345,35 +1344,57 @@
 static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
 {
 	struct saa711x_state *state = to_state(sd);
-	int reg1e;
+	int reg1f, reg1e;
 
-	*std = V4L2_STD_ALL;
-	if (state->ident != V4L2_IDENT_SAA7115) {
-		int reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
+	/*
+	 * The V4L2 core already initializes std with all supported
+	 * Standards. All driver needs to do is to mask it, to remove
+	 * standards that don't apply from the mask
+	 */
 
-		if (reg1f & 0x20)
-			*std = V4L2_STD_525_60;
-		else
-			*std = V4L2_STD_625_50;
+	reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
+	v4l2_dbg(1, debug, sd, "Status byte 2 (0x1f)=0x%02x\n", reg1f);
 
-		return 0;
-	}
+	/* horizontal/vertical not locked */
+	if (reg1f & 0x40)
+		goto ret;
+
+	if (reg1f & 0x20)
+		*std &= V4L2_STD_525_60;
+	else
+		*std &= V4L2_STD_625_50;
+
+	if (state->ident != V4L2_IDENT_SAA7115)
+		goto ret;
 
 	reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
 
 	switch (reg1e & 0x03) {
 	case 1:
-		*std = V4L2_STD_NTSC;
+		*std &= V4L2_STD_NTSC;
 		break;
 	case 2:
-		*std = V4L2_STD_PAL;
+		/*
+		 * V4L2_STD_PAL just cover the european PAL standards.
+		 * This is wrong, as the device could also be using an
+		 * other PAL standard.
+		 */
+		*std &= V4L2_STD_PAL   | V4L2_STD_PAL_N  | V4L2_STD_PAL_Nc |
+			V4L2_STD_PAL_M | V4L2_STD_PAL_60;
 		break;
 	case 3:
-		*std = V4L2_STD_SECAM;
+		*std &= V4L2_STD_SECAM;
 		break;
 	default:
+		/* Can't detect anything */
 		break;
 	}
+
+	v4l2_dbg(1, debug, sd, "Status byte 1 (0x1e)=0x%02x\n", reg1e);
+
+ret:
+	v4l2_dbg(1, debug, sd, "detected std mask = %08Lx\n", *std);
+
 	return 0;
 }
 
@@ -1601,7 +1622,6 @@
 			V4L2_CID_CHROMA_AGC, 0, 1, 1, 1);
 	state->gain = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
 			V4L2_CID_CHROMA_GAIN, 0, 127, 1, 40);
-	state->gain->is_volatile = 1;
 	sd->ctrl_handler = hdl;
 	if (hdl->error) {
 		int err = hdl->error;
@@ -1610,8 +1630,7 @@
 		kfree(state);
 		return err;
 	}
-	state->agc->flags |= V4L2_CTRL_FLAG_UPDATE;
-	v4l2_ctrl_cluster(2, &state->agc);
+	v4l2_ctrl_auto_cluster(2, &state->agc, 0, true);
 
 	state->input = -1;
 	state->output = SAA7115_IPORT_ON;
diff -druN linux-libre-3.1-gnu/drivers/media/video/saa7134/Makefile linux-libre-3.2-gnu/drivers/media/video/saa7134/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/saa7134/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/saa7134/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -10,7 +10,7 @@
 
 obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff -druN linux-libre-3.1-gnu/drivers/media/video/saa7134/saa7134.h linux-libre-3.2-gnu/drivers/media/video/saa7134/saa7134.h
--- linux-libre-3.1-gnu/drivers/media/video/saa7134/saa7134.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/saa7134/saa7134.h	2012-01-04 18:55:44.000000000 -0500
@@ -843,10 +843,10 @@
 int saa7134_ir_start(struct saa7134_dev *dev);
 void saa7134_ir_stop(struct saa7134_dev *dev);
 #else
-#define saa7134_input_init1(dev)	(0)
-#define saa7134_input_fini(dev)		(0)
-#define saa7134_input_irq(dev)		(0)
-#define saa7134_probe_i2c_ir(dev)	(0)
-#define saa7134_ir_start(dev)		(0)
-#define saa7134_ir_stop(dev)		(0)
+#define saa7134_input_init1(dev)	((void)0)
+#define saa7134_input_fini(dev)		((void)0)
+#define saa7134_input_irq(dev)		((void)0)
+#define saa7134_probe_i2c_ir(dev)	((void)0)
+#define saa7134_ir_start(dev)		((void)0)
+#define saa7134_ir_stop(dev)		((void)0)
 #endif
diff -druN linux-libre-3.1-gnu/drivers/media/video/saa7164/Makefile linux-libre-3.2-gnu/drivers/media/video/saa7164/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/saa7164/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/saa7164/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -4,9 +4,9 @@
 
 obj-$(CONFIG_VIDEO_SAA7164) += saa7164.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
 
-EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff -druN linux-libre-3.1-gnu/drivers/media/video/saa7164/saa7164-cards.c linux-libre-3.2-gnu/drivers/media/video/saa7164/saa7164-cards.c
--- linux-libre-3.1-gnu/drivers/media/video/saa7164/saa7164-cards.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/saa7164/saa7164-cards.c	2012-01-04 18:55:44.000000000 -0500
@@ -203,6 +203,66 @@
 			.i2c_reg_len	= REGLEN_8bit,
 		} },
 	},
+	[SAA7164_BOARD_HAUPPAUGE_HVR2200_4] = {
+		.name		= "Hauppauge WinTV-HVR2200",
+		.porta		= SAA7164_MPEG_DVB,
+		.portb		= SAA7164_MPEG_DVB,
+		.portc		= SAA7164_MPEG_ENCODER,
+		.portd		= SAA7164_MPEG_ENCODER,
+		.porte		= SAA7164_MPEG_VBI,
+		.portf		= SAA7164_MPEG_VBI,
+		.chiprev	= SAA7164_CHIP_REV3,
+		.unit		= {{
+			.id		= 0x1d,
+			.type		= SAA7164_UNIT_EEPROM,
+			.name		= "4K EEPROM",
+			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
+			.i2c_bus_addr	= 0xa0 >> 1,
+			.i2c_reg_len	= REGLEN_8bit,
+		}, {
+			.id		= 0x04,
+			.type		= SAA7164_UNIT_TUNER,
+			.name		= "TDA18271-1",
+			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
+			.i2c_bus_addr	= 0xc0 >> 1,
+			.i2c_reg_len	= REGLEN_8bit,
+		}, {
+			.id		= 0x05,
+			.type		= SAA7164_UNIT_ANALOG_DEMODULATOR,
+			.name		= "TDA8290-1",
+			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
+			.i2c_bus_addr	= 0x84 >> 1,
+			.i2c_reg_len	= REGLEN_8bit,
+		}, {
+			.id		= 0x1b,
+			.type		= SAA7164_UNIT_TUNER,
+			.name		= "TDA18271-2",
+			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
+			.i2c_bus_addr	= 0xc0 >> 1,
+			.i2c_reg_len	= REGLEN_8bit,
+		}, {
+			.id		= 0x1c,
+			.type		= SAA7164_UNIT_ANALOG_DEMODULATOR,
+			.name		= "TDA8290-2",
+			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
+			.i2c_bus_addr	= 0x84 >> 1,
+			.i2c_reg_len	= REGLEN_8bit,
+		}, {
+			.id		= 0x1e,
+			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
+			.name		= "TDA10048-1",
+			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
+			.i2c_bus_addr	= 0x10 >> 1,
+			.i2c_reg_len	= REGLEN_8bit,
+		}, {
+			.id		= 0x1f,
+			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
+			.name		= "TDA10048-2",
+			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
+			.i2c_bus_addr	= 0x12 >> 1,
+			.i2c_reg_len	= REGLEN_8bit,
+		} },
+	},
 	[SAA7164_BOARD_HAUPPAUGE_HVR2250] = {
 		.name		= "Hauppauge WinTV-HVR2250",
 		.porta		= SAA7164_MPEG_DVB,
@@ -387,6 +447,62 @@
 			.i2c_reg_len	= REGLEN_8bit,
 		} },
 	},
+	[SAA7164_BOARD_HAUPPAUGE_HVR2200_5] = {
+		.name		= "Hauppauge WinTV-HVR2200",
+		.porta		= SAA7164_MPEG_DVB,
+		.portb		= SAA7164_MPEG_DVB,
+		.chiprev	= SAA7164_CHIP_REV3,
+		.unit		= {{
+			.id		= 0x23,
+			.type		= SAA7164_UNIT_EEPROM,
+			.name		= "4K EEPROM",
+			.i2c_bus_nr	= SAA7164_I2C_BUS_0,
+			.i2c_bus_addr	= 0xa0 >> 1,
+			.i2c_reg_len	= REGLEN_8bit,
+		}, {
+			.id		= 0x04,
+			.type		= SAA7164_UNIT_TUNER,
+			.name		= "TDA18271-1",
+			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
+			.i2c_bus_addr	= 0xc0 >> 1,
+			.i2c_reg_len	= REGLEN_8bit,
+		}, {
+			.id		= 0x05,
+			.type		= SAA7164_UNIT_ANALOG_DEMODULATOR,
+			.name		= "TDA8290-1",
+			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
+			.i2c_bus_addr	= 0x84 >> 1,
+			.i2c_reg_len	= REGLEN_8bit,
+		}, {
+			.id		= 0x21,
+			.type		= SAA7164_UNIT_TUNER,
+			.name		= "TDA18271-2",
+			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
+			.i2c_bus_addr	= 0xc0 >> 1,
+			.i2c_reg_len	= REGLEN_8bit,
+		}, {
+			.id		= 0x22,
+			.type		= SAA7164_UNIT_ANALOG_DEMODULATOR,
+			.name		= "TDA8290-2",
+			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
+			.i2c_bus_addr	= 0x84 >> 1,
+			.i2c_reg_len	= REGLEN_8bit,
+		}, {
+			.id		= 0x24,
+			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
+			.name		= "TDA10048-1",
+			.i2c_bus_nr	= SAA7164_I2C_BUS_1,
+			.i2c_bus_addr	= 0x10 >> 1,
+			.i2c_reg_len	= REGLEN_8bit,
+		}, {
+			.id		= 0x25,
+			.type		= SAA7164_UNIT_DIGITAL_DEMODULATOR,
+			.name		= "TDA10048-2",
+			.i2c_bus_nr	= SAA7164_I2C_BUS_2,
+			.i2c_bus_addr	= 0x12 >> 1,
+			.i2c_reg_len	= REGLEN_8bit,
+		} },
+	},
 };
 const unsigned int saa7164_bcount = ARRAY_SIZE(saa7164_boards);
 
@@ -426,6 +542,14 @@
 		.subvendor = 0x0070,
 		.subdevice = 0x8851,
 		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2250_2,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x8940,
+		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_4,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x8953,
+		.card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_5,
 	},
 };
 const unsigned int saa7164_idcount = ARRAY_SIZE(saa7164_subids);
@@ -469,6 +593,8 @@
 	case SAA7164_BOARD_HAUPPAUGE_HVR2200:
 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
+	case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
+	case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
 	case SAA7164_BOARD_HAUPPAUGE_HVR2250:
 	case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
 	case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
@@ -549,6 +675,8 @@
 	case SAA7164_BOARD_HAUPPAUGE_HVR2200:
 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
+	case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
+	case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
 	case SAA7164_BOARD_HAUPPAUGE_HVR2250:
 	case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
 	case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
diff -druN linux-libre-3.1-gnu/drivers/media/video/saa7164/saa7164-dvb.c linux-libre-3.2-gnu/drivers/media/video/saa7164/saa7164-dvb.c
--- linux-libre-3.1-gnu/drivers/media/video/saa7164/saa7164-dvb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/saa7164/saa7164-dvb.c	2012-01-04 18:55:44.000000000 -0500
@@ -475,6 +475,8 @@
 	case SAA7164_BOARD_HAUPPAUGE_HVR2200:
 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
 	case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
+	case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
+	case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
 		i2c_bus = &dev->i2c_bus[port->nr + 1];
 		switch (port->nr) {
 		case 0:
diff -druN linux-libre-3.1-gnu/drivers/media/video/saa7164/saa7164.h linux-libre-3.2-gnu/drivers/media/video/saa7164/saa7164.h
--- linux-libre-3.1-gnu/drivers/media/video/saa7164/saa7164.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/saa7164/saa7164.h	2012-01-04 18:55:44.000000000 -0500
@@ -82,6 +82,8 @@
 #define SAA7164_BOARD_HAUPPAUGE_HVR2200_3	6
 #define SAA7164_BOARD_HAUPPAUGE_HVR2250_2	7
 #define SAA7164_BOARD_HAUPPAUGE_HVR2250_3	8
+#define SAA7164_BOARD_HAUPPAUGE_HVR2200_4	9
+#define SAA7164_BOARD_HAUPPAUGE_HVR2200_5	10
 
 #define SAA7164_MAX_UNITS		8
 #define SAA7164_TS_NUMBER_OF_LINES	312
diff -druN linux-libre-3.1-gnu/drivers/media/video/sh_mobile_ceu_camera.c linux-libre-3.2-gnu/drivers/media/video/sh_mobile_ceu_camera.c
--- linux-libre-3.1-gnu/drivers/media/video/sh_mobile_ceu_camera.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/sh_mobile_ceu_camera.c	2012-01-04 18:55:44.000000000 -0500
@@ -90,7 +90,6 @@
 struct sh_mobile_ceu_buffer {
 	struct vb2_buffer vb; /* v4l buffer must be first */
 	struct list_head queue;
-	enum v4l2_mbus_pixelcode code;
 };
 
 struct sh_mobile_ceu_dev {
@@ -100,7 +99,8 @@
 
 	unsigned int irq;
 	void __iomem *base;
-	unsigned long video_limit;
+	size_t video_limit;
+	size_t buf_total;
 
 	spinlock_t lock;		/* Protects video buffer lists */
 	struct list_head capture;
@@ -121,7 +121,7 @@
 };
 
 struct sh_mobile_ceu_cam {
-	/* CEU offsets within scaled by the CEU camera output */
+	/* CEU offsets within the camera output, before the CEU scaler */
 	unsigned int ceu_left;
 	unsigned int ceu_top;
 	/* Client output, as seen by the CEU */
@@ -144,30 +144,6 @@
 	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;
-
-	flags = SOCAM_MASTER |
-		SOCAM_PCLK_SAMPLE_RISING |
-		SOCAM_HSYNC_ACTIVE_HIGH |
-		SOCAM_HSYNC_ACTIVE_LOW |
-		SOCAM_VSYNC_ACTIVE_HIGH |
-		SOCAM_VSYNC_ACTIVE_LOW |
-		SOCAM_DATA_ACTIVE_HIGH;
-
-	if (pcdev->pdata->flags & SH_CEU_FLAG_USE_8BIT_BUS)
-		flags |= SOCAM_DATAWIDTH_8;
-
-	if (pcdev->pdata->flags & SH_CEU_FLAG_USE_16BIT_BUS)
-		flags |= SOCAM_DATAWIDTH_16;
-
-	if (flags & SOCAM_DATAWIDTH_MASK)
-		return flags;
-
-	return 0;
-}
-
 static void ceu_write(struct sh_mobile_ceu_dev *priv,
 		      unsigned long reg_offs, u32 data)
 {
@@ -216,34 +192,62 @@
 /*
  *  Videobuf operations
  */
+
+/*
+ * .queue_setup() is called to check, whether the driver can accept the
+ *		  requested number of buffers and to fill in plane sizes
+ *		  for the current frame format if required
+ */
 static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq,
+			const struct v4l2_format *fmt,
 			unsigned int *count, unsigned int *num_planes,
-			unsigned long sizes[], void *alloc_ctxs[])
+			unsigned int sizes[], void *alloc_ctxs[])
 {
 	struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
-	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
-						icd->current_fmt->host_fmt);
+	int bytes_per_line;
+	unsigned int height;
 
+	if (fmt) {
+		const struct soc_camera_format_xlate *xlate = soc_camera_xlate_by_fourcc(icd,
+								fmt->fmt.pix.pixelformat);
+		if (!xlate)
+			return -EINVAL;
+		bytes_per_line = soc_mbus_bytes_per_line(fmt->fmt.pix.width,
+							 xlate->host_fmt);
+		height = fmt->fmt.pix.height;
+	} else {
+		/* Called from VIDIOC_REQBUFS or in compatibility mode */
+		bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+						icd->current_fmt->host_fmt);
+		height = icd->user_height;
+	}
 	if (bytes_per_line < 0)
 		return bytes_per_line;
 
-	*num_planes = 1;
+	sizes[0] = bytes_per_line * height;
 
-	pcdev->sequence = 0;
-	sizes[0] = bytes_per_line * icd->user_height;
 	alloc_ctxs[0] = pcdev->alloc_ctx;
 
+	if (!vq->num_buffers)
+		pcdev->sequence = 0;
+
 	if (!*count)
 		*count = 2;
 
-	if (pcdev->video_limit) {
-		if (PAGE_ALIGN(sizes[0]) * *count > pcdev->video_limit)
-			*count = pcdev->video_limit / PAGE_ALIGN(sizes[0]);
+	/* If *num_planes != 0, we have already verified *count. */
+	if (pcdev->video_limit && !*num_planes) {
+		size_t size = PAGE_ALIGN(sizes[0]) * *count;
+
+		if (size + pcdev->buf_total > pcdev->video_limit)
+			*count = (pcdev->video_limit - pcdev->buf_total) /
+				PAGE_ALIGN(sizes[0]);
 	}
 
-	dev_dbg(icd->parent, "count=%d, size=%lu\n", *count, sizes[0]);
+	*num_planes = 1;
+
+	dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]);
 
 	return 0;
 }
@@ -267,6 +271,7 @@
 	unsigned long top1, top2;
 	unsigned long bottom1, bottom2;
 	u32 status;
+	bool planar;
 	int ret = 0;
 
 	/*
@@ -312,19 +317,31 @@
 		bottom2	= CDBCR;
 	}
 
-	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;
-		ceu_write(pcdev, bottom1, phys_addr_bottom);
-	}
+	phys_addr_top = vb2_dma_contig_plane_dma_addr(pcdev->active, 0);
 
 	switch (icd->current_fmt->host_fmt->fourcc) {
 	case V4L2_PIX_FMT_NV12:
 	case V4L2_PIX_FMT_NV21:
 	case V4L2_PIX_FMT_NV16:
 	case V4L2_PIX_FMT_NV61:
+		planar = true;
+		break;
+	default:
+		planar = false;
+	}
+
+	ceu_write(pcdev, top1, phys_addr_top);
+	if (V4L2_FIELD_NONE != pcdev->field) {
+		if (planar)
+			phys_addr_bottom = phys_addr_top + icd->user_width;
+		else
+			phys_addr_bottom = phys_addr_top +
+				soc_mbus_bytes_per_line(icd->user_width,
+							icd->current_fmt->host_fmt);
+		ceu_write(pcdev, bottom1, phys_addr_bottom);
+	}
+
+	if (planar) {
 		phys_addr_top += icd->user_width *
 			icd->user_height;
 		ceu_write(pcdev, top2, phys_addr_top);
@@ -341,23 +358,40 @@
 
 static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb)
 {
+	struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
+
+	/* Added list head initialization on alloc */
+	WARN(!list_empty(&buf->queue), "Buffer %p on queue!\n", vb);
+
+	return 0;
+}
+
+static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb)
+{
 	struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq);
-	struct sh_mobile_ceu_buffer *buf;
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct sh_mobile_ceu_dev *pcdev = ici->priv;
+	struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
+	unsigned long size;
 	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
 						icd->current_fmt->host_fmt);
-	unsigned long size;
 
 	if (bytes_per_line < 0)
-		return bytes_per_line;
+		goto error;
 
-	buf = to_ceu_vb(vb);
+	size = icd->user_height * bytes_per_line;
+
+	if (vb2_plane_size(vb, 0) < size) {
+		dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n",
+			vb->v4l2_buf.index, vb2_plane_size(vb, 0), size);
+		goto error;
+	}
+
+	vb2_set_plane_payload(vb, 0, size);
 
 	dev_dbg(icd->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(!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
@@ -367,31 +401,6 @@
 		memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0));
 #endif
 
-	BUG_ON(NULL == icd->current_fmt);
-
-	size = icd->user_height * bytes_per_line;
-
-	if (vb2_plane_size(vb, 0) < size) {
-		dev_err(icd->parent, "Buffer too small (%lu < %lu)\n",
-			vb2_plane_size(vb, 0), size);
-		return -ENOBUFS;
-	}
-
-	vb2_set_plane_payload(vb, 0, size);
-
-	return 0;
-}
-
-static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb)
-{
-	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->parent);
-	struct sh_mobile_ceu_dev *pcdev = ici->priv;
-	struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
-
-	dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
-		vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
-
 	spin_lock_irq(&pcdev->lock);
 	list_add_tail(&buf->queue, &pcdev->capture);
 
@@ -405,6 +414,11 @@
 		sh_mobile_ceu_capture(pcdev);
 	}
 	spin_unlock_irq(&pcdev->lock);
+
+	return;
+
+error:
+	vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 }
 
 static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb)
@@ -429,11 +443,23 @@
 	if (buf->queue.next)
 		list_del_init(&buf->queue);
 
+	pcdev->buf_total -= PAGE_ALIGN(vb2_plane_size(vb, 0));
+	dev_dbg(icd->parent, "%s() %zu bytes buffers\n", __func__,
+		pcdev->buf_total);
+
 	spin_unlock_irq(&pcdev->lock);
 }
 
 static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb)
 {
+	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->parent);
+	struct sh_mobile_ceu_dev *pcdev = ici->priv;
+
+	pcdev->buf_total += PAGE_ALIGN(vb2_plane_size(vb, 0));
+	dev_dbg(icd->parent, "%s() %zu bytes buffers\n", __func__,
+		pcdev->buf_total);
+
 	/* This is for locking debugging only */
 	INIT_LIST_HEAD(&to_ceu_vb(vb)->queue);
 	return 0;
@@ -535,19 +561,31 @@
 
 	pm_runtime_get_sync(ici->v4l2_dev.dev);
 
+	pcdev->buf_total = 0;
+
 	ret = sh_mobile_ceu_soft_reset(pcdev);
 
 	csi2_sd = find_csi2(pcdev);
+	if (csi2_sd) {
+		csi2_sd->grp_id = soc_camera_grp_id(icd);
+		v4l2_set_subdev_hostdata(csi2_sd, icd);
+	}
 
 	ret = v4l2_subdev_call(csi2_sd, core, s_power, 1);
-	if (ret != -ENODEV && ret != -ENOIOCTLCMD && ret < 0) {
+	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
 		pm_runtime_put_sync(ici->v4l2_dev.dev);
-	} else {
-		pcdev->icd = icd;
-		ret = 0;
+		return ret;
 	}
 
-	return ret;
+	/*
+	 * -ENODEV is special: either csi2_sd == NULL or the CSI-2 driver
+	 * has not found this soc-camera device among its clients
+	 */
+	if (ret == -ENODEV && csi2_sd)
+		csi2_sd->grp_id = 0;
+	pcdev->icd = icd;
+
+	return 0;
 }
 
 /* Called with .video_lock held */
@@ -560,6 +598,8 @@
 	BUG_ON(icd != pcdev->icd);
 
 	v4l2_subdev_call(csi2_sd, core, s_power, 0);
+	if (csi2_sd)
+		csi2_sd->grp_id = 0;
 	/* disable capture, disable interrupts */
 	ceu_write(pcdev, CEIER, 0);
 	sh_mobile_ceu_soft_reset(pcdev);
@@ -628,22 +668,22 @@
 	left_offset	= cam->ceu_left;
 	top_offset	= cam->ceu_top;
 
-	/* CEU cropping (CFSZR) is applied _after_ the scaling filter (CFLCR) */
+	WARN_ON(icd->user_width & 3 || icd->user_height & 3);
+
+	width = icd->user_width;
+
 	if (pcdev->image_mode) {
 		in_width = cam->width;
 		if (!pcdev->is_16bit) {
 			in_width *= 2;
 			left_offset *= 2;
 		}
-		width = icd->user_width;
-		cdwdr_width = icd->user_width;
+		cdwdr_width = width;
 	} else {
-		int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+		int bytes_per_line = soc_mbus_bytes_per_line(width,
 						icd->current_fmt->host_fmt);
 		unsigned int w_factor;
 
-		width = icd->user_width;
-
 		switch (icd->current_fmt->host_fmt->packing) {
 		case SOC_MBUS_PACKING_2X8_PADHI:
 			w_factor = 2;
@@ -653,10 +693,10 @@
 		}
 
 		in_width = cam->width * w_factor;
-		left_offset = left_offset * w_factor;
+		left_offset *= w_factor;
 
 		if (bytes_per_line < 0)
-			cdwdr_width = icd->user_width;
+			cdwdr_width = width;
 		else
 			cdwdr_width = bytes_per_line;
 	}
@@ -664,7 +704,7 @@
 	height = icd->user_height;
 	in_height = cam->height;
 	if (V4L2_FIELD_NONE != pcdev->field) {
-		height /= 2;
+		height = (height / 2) & ~3;
 		in_height /= 2;
 		top_offset /= 2;
 		cdwdr_width *= 2;
@@ -686,6 +726,7 @@
 
 	ceu_write(pcdev, CAMOR, camor);
 	ceu_write(pcdev, CAPWR, (in_height << 16) | in_width);
+	/* CFSZR clipping is applied _after_ the scaling filter (CFLCR) */
 	ceu_write(pcdev, CFSZR, (height << 16) | width);
 	ceu_write(pcdev, CDWDR, cdwdr_width);
 }
@@ -723,66 +764,93 @@
 		ceu_write(pcdev, CAPSR, capsr);
 }
 
+/* Find the bus subdevice driver, e.g., CSI2 */
+static struct v4l2_subdev *find_bus_subdev(struct sh_mobile_ceu_dev *pcdev,
+					   struct soc_camera_device *icd)
+{
+	if (pcdev->csi2_pdev) {
+		struct v4l2_subdev *csi2_sd = find_csi2(pcdev);
+		if (csi2_sd && csi2_sd->grp_id == soc_camera_grp_id(icd))
+			return csi2_sd;
+	}
+
+	return soc_camera_to_subdev(icd);
+}
+
+#define CEU_BUS_FLAGS (V4L2_MBUS_MASTER |	\
+		V4L2_MBUS_PCLK_SAMPLE_RISING |	\
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH |	\
+		V4L2_MBUS_HSYNC_ACTIVE_LOW |	\
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH |	\
+		V4L2_MBUS_VSYNC_ACTIVE_LOW |	\
+		V4L2_MBUS_DATA_ACTIVE_HIGH)
+
 /* Capture is not running, no interrupts, no locking needed */
 static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
 				       __u32 pixfmt)
 {
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
-	int ret;
-	unsigned long camera_flags, common_flags, value;
-	int yuv_lineskip;
+	struct v4l2_subdev *sd = find_bus_subdev(pcdev, icd);
 	struct sh_mobile_ceu_cam *cam = icd->host_priv;
+	struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+	unsigned long value, common_flags = CEU_BUS_FLAGS;
 	u32 capsr = capture_save_reset(pcdev);
+	unsigned int yuv_lineskip;
+	int ret;
 
-	camera_flags = icd->ops->query_bus_param(icd);
-	common_flags = soc_camera_bus_param_compatible(camera_flags,
-						       make_bus_param(pcdev));
-	if (!common_flags)
-		return -EINVAL;
+	/*
+	 * If the client doesn't implement g_mbus_config, we just use our
+	 * platform data
+	 */
+	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+	if (!ret) {
+		common_flags = soc_mbus_config_compatible(&cfg,
+							  common_flags);
+		if (!common_flags)
+			return -EINVAL;
+	} else if (ret != -ENOIOCTLCMD) {
+		return ret;
+	}
 
 	/* Make choises, based on platform preferences */
-	if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
-	    (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+	if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
+	    (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
 		if (pcdev->pdata->flags & SH_CEU_FLAG_HSYNC_LOW)
-			common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
 		else
-			common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
 	}
 
-	if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
-	    (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
+	if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
+	    (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
 		if (pcdev->pdata->flags & SH_CEU_FLAG_VSYNC_LOW)
-			common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
+			common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
 		else
-			common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
+			common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
 	}
 
-	ret = icd->ops->set_bus_param(icd, common_flags);
-	if (ret < 0)
+	cfg.flags = common_flags;
+	ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+	if (ret < 0 && ret != -ENOIOCTLCMD)
 		return ret;
 
-	switch (common_flags & SOCAM_DATAWIDTH_MASK) {
-	case SOCAM_DATAWIDTH_8:
-		pcdev->is_16bit = 0;
-		break;
-	case SOCAM_DATAWIDTH_16:
+	if (icd->current_fmt->host_fmt->bits_per_sample > 8)
 		pcdev->is_16bit = 1;
-		break;
-	default:
-		return -EINVAL;
-	}
+	else
+		pcdev->is_16bit = 0;
 
 	ceu_write(pcdev, CRCNTR, 0);
 	ceu_write(pcdev, CRCMPR, 0);
 
 	value = 0x00000010; /* data fetch by default */
-	yuv_lineskip = 0;
+	yuv_lineskip = 0x10;
 
 	switch (icd->current_fmt->host_fmt->fourcc) {
 	case V4L2_PIX_FMT_NV12:
 	case V4L2_PIX_FMT_NV21:
-		yuv_lineskip = 1; /* skip for NV12/21, no skip for NV16/61 */
+		/* convert 4:2:2 -> 4:2:0 */
+		yuv_lineskip = 0; /* skip for NV12/21, no skip for NV16/61 */
 		/* fall-through */
 	case V4L2_PIX_FMT_NV16:
 	case V4L2_PIX_FMT_NV61:
@@ -808,8 +876,8 @@
 	    icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV61)
 		value ^= 0x00000100; /* swap U, V to change from NV1x->NVx1 */
 
-	value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0;
-	value |= common_flags & SOCAM_HSYNC_ACTIVE_LOW ? 1 << 0 : 0;
+	value |= common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW ? 1 << 1 : 0;
+	value |= common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW ? 1 << 0 : 0;
 	value |= pcdev->is_16bit ? 1 << 12 : 0;
 
 	/* CSI2 mode */
@@ -852,9 +920,7 @@
 	 * using 7 we swap the data bytes to match the incoming order:
 	 * D0, D1, D2, D3, D4, D5, D6, D7
 	 */
-	value = 0x00000017;
-	if (yuv_lineskip)
-		value &= ~0x00000010; /* convert 4:2:2 -> 4:2:0 */
+	value = 0x00000007 | yuv_lineskip;
 
 	ceu_write(pcdev, CDOCR, value);
 	ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */
@@ -875,13 +941,19 @@
 {
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
-	unsigned long camera_flags, common_flags;
+	struct v4l2_subdev *sd = find_bus_subdev(pcdev, icd);
+	unsigned long common_flags = CEU_BUS_FLAGS;
+	struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+	int ret;
 
-	camera_flags = icd->ops->query_bus_param(icd);
-	common_flags = soc_camera_bus_param_compatible(camera_flags,
-						       make_bus_param(pcdev));
-	if (!common_flags || buswidth > 16 ||
-	    (buswidth > 8 && !(common_flags & SOCAM_DATAWIDTH_16)))
+	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+	if (!ret)
+		common_flags = soc_mbus_config_compatible(&cfg,
+							  common_flags);
+	else if (ret != -ENOIOCTLCMD)
+		return ret;
+
+	if (!common_flags || buswidth > 16)
 		return -EINVAL;
 
 	return 0;
@@ -891,26 +963,26 @@
 	{
 		.fourcc			= V4L2_PIX_FMT_NV12,
 		.name			= "NV12",
-		.bits_per_sample	= 12,
-		.packing		= SOC_MBUS_PACKING_NONE,
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_1_5X8,
 		.order			= SOC_MBUS_ORDER_LE,
 	}, {
 		.fourcc			= V4L2_PIX_FMT_NV21,
 		.name			= "NV21",
-		.bits_per_sample	= 12,
-		.packing		= SOC_MBUS_PACKING_NONE,
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_1_5X8,
 		.order			= SOC_MBUS_ORDER_LE,
 	}, {
 		.fourcc			= V4L2_PIX_FMT_NV16,
 		.name			= "NV16",
-		.bits_per_sample	= 16,
-		.packing		= SOC_MBUS_PACKING_NONE,
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_2X8_PADHI,
 		.order			= SOC_MBUS_ORDER_LE,
 	}, {
 		.fourcc			= V4L2_PIX_FMT_NV61,
 		.name			= "NV61",
-		.bits_per_sample	= 16,
-		.packing		= SOC_MBUS_PACKING_NONE,
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_2X8_PADHI,
 		.order			= SOC_MBUS_ORDER_LE,
 	},
 };
@@ -920,6 +992,8 @@
 {
 	return	fmt->packing == SOC_MBUS_PACKING_NONE ||
 		(fmt->bits_per_sample == 8 &&
+		 fmt->packing == SOC_MBUS_PACKING_1_5X8) ||
+		(fmt->bits_per_sample == 8 &&
 		 fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) ||
 		(fmt->bits_per_sample > 8 &&
 		 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
@@ -927,6 +1001,38 @@
 
 static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect);
 
+static struct soc_camera_device *ctrl_to_icd(struct v4l2_ctrl *ctrl)
+{
+	return container_of(ctrl->handler, struct soc_camera_device,
+							ctrl_handler);
+}
+
+static int sh_mobile_ceu_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct soc_camera_device *icd = ctrl_to_icd(ctrl);
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct sh_mobile_ceu_dev *pcdev = ici->priv;
+
+	switch (ctrl->id) {
+	case V4L2_CID_SHARPNESS:
+		switch (icd->current_fmt->host_fmt->fourcc) {
+		case V4L2_PIX_FMT_NV12:
+		case V4L2_PIX_FMT_NV21:
+		case V4L2_PIX_FMT_NV16:
+		case V4L2_PIX_FMT_NV61:
+			ceu_write(pcdev, CLFCR, !ctrl->val);
+			return 0;
+		}
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static const struct v4l2_ctrl_ops sh_mobile_ceu_ctrl_ops = {
+	.s_ctrl = sh_mobile_ceu_s_ctrl,
+};
+
 static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int idx,
 				     struct soc_camera_format_xlate *xlate)
 {
@@ -952,6 +1058,7 @@
 	}
 
 	if (!pcdev->pdata->csi2) {
+		/* Are there any restrictions in the CSI-2 case? */
 		ret = sh_mobile_ceu_try_bus_param(icd, fmt->bits_per_sample);
 		if (ret < 0)
 			return 0;
@@ -962,6 +1069,12 @@
 		struct v4l2_rect rect;
 		int shift = 0;
 
+		/* Add our control */
+		v4l2_ctrl_new_std(&icd->ctrl_handler, &sh_mobile_ceu_ctrl_ops,
+				  V4L2_CID_SHARPNESS, 0, 1, 1, 0);
+		if (icd->ctrl_handler.error)
+			return icd->ctrl_handler.error;
+
 		/* FIXME: subwindow is lost between close / open */
 
 		/* Cache current client geometry */
@@ -978,8 +1091,9 @@
 			/* Try 2560x1920, 1280x960, 640x480, 320x240 */
 			mf.width	= 2560 >> shift;
 			mf.height	= 1920 >> shift;
-			ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
-							 s_mbus_fmt, &mf);
+			ret = v4l2_device_call_until_err(sd->v4l2_dev,
+					soc_camera_grp_id(icd), video,
+					s_mbus_fmt, &mf);
 			if (ret < 0)
 				return ret;
 			shift++;
@@ -1004,9 +1118,6 @@
 		cam->width	= mf.width;
 		cam->height	= mf.height;
 
-		cam->width	= mf.width;
-		cam->height	= mf.height;
-
 		icd->host_priv = cam;
 	} else {
 		cam = icd->host_priv;
@@ -1278,16 +1389,25 @@
 	unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h;
 	unsigned int max_width, max_height;
 	struct v4l2_cropcap cap;
+	bool ceu_1to1;
 	int ret;
 
-	ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
+	ret = v4l2_device_call_until_err(sd->v4l2_dev,
+					 soc_camera_grp_id(icd), video,
 					 s_mbus_fmt, mf);
 	if (ret < 0)
 		return ret;
 
 	dev_geo(dev, "camera scaled to %ux%u\n", mf->width, mf->height);
 
-	if ((width == mf->width && height == mf->height) || !ceu_can_scale)
+	if (width == mf->width && height == mf->height) {
+		/* Perfect! The client has done it all. */
+		ceu_1to1 = true;
+		goto update_cache;
+	}
+
+	ceu_1to1 = false;
+	if (!ceu_can_scale)
 		goto update_cache;
 
 	cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -1310,8 +1430,9 @@
 		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, (long)icd, video,
-						 s_mbus_fmt, mf);
+		ret = v4l2_device_call_until_err(sd->v4l2_dev,
+					soc_camera_grp_id(icd), video,
+					s_mbus_fmt, mf);
 		dev_geo(dev, "Camera scaled to %ux%u\n",
 			mf->width, mf->height);
 		if (ret < 0) {
@@ -1327,7 +1448,10 @@
 	if (ret < 0)
 		return ret;
 
-	update_subrect(cam);
+	if (ceu_1to1)
+		cam->subrect = cam->rect;
+	else
+		update_subrect(cam);
 
 	return 0;
 }
@@ -1414,7 +1538,10 @@
 	capsr = capture_save_reset(pcdev);
 	dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr);
 
-	/* 1. - 2. Apply iterative camera S_CROP for new input window. */
+	/*
+	 * 1. - 2. Apply iterative camera S_CROP for new input window, read back
+	 * actual camera rectangle.
+	 */
 	ret = client_s_crop(icd, a, &cam_crop);
 	if (ret < 0)
 		return ret;
@@ -1458,8 +1585,9 @@
 	}
 
 	if (interm_width < icd->user_width || interm_height < icd->user_height) {
-		ret = v4l2_device_call_until_err(sd->v4l2_dev, (int)icd, video,
-						 s_mbus_fmt, &mf);
+		ret = v4l2_device_call_until_err(sd->v4l2_dev,
+					soc_camera_grp_id(icd), video,
+					s_mbus_fmt, &mf);
 		if (ret < 0)
 			return ret;
 
@@ -1498,8 +1626,9 @@
 		ceu_write(pcdev, CFLCR, cflcr);
 	}
 
-	icd->user_width	 = out_width;
-	icd->user_height = out_height;
+	icd->user_width	 = out_width & ~3;
+	icd->user_height = out_height & ~3;
+	/* Offsets are applied at the CEU scaling filter input */
 	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;
 
@@ -1538,7 +1667,7 @@
  * CEU crop, mapped backed onto the client input (subrect).
  */
 static void calculate_client_output(struct soc_camera_device *icd,
-		struct v4l2_pix_format *pix, struct v4l2_mbus_framefmt *mf)
+		const struct v4l2_pix_format *pix, struct v4l2_mbus_framefmt *mf)
 {
 	struct sh_mobile_ceu_cam *cam = icd->host_priv;
 	struct device *dev = icd->parent;
@@ -1574,8 +1703,8 @@
 	dev_geo(dev, "3: scales %u:%u\n", scale_h, scale_v);
 
 	/*
-	 * 4. Calculate client output window by applying combined scales to real
-	 *    input window.
+	 * 4. Calculate desired client output window by applying combined scales
+	 *    to client (real) input window.
 	 */
 	mf->width	= scale_down(cam->rect.width, scale_h);
 	mf->height	= scale_down(cam->rect.height, scale_v);
@@ -1600,8 +1729,6 @@
 	bool image_mode;
 	enum v4l2_field field;
 
-	dev_geo(dev, "S_FMT(pix=0x%x, %ux%u)\n", pixfmt, pix->width, pix->height);
-
 	switch (pix->field) {
 	default:
 		pix->field = V4L2_FIELD_NONE;
@@ -1622,8 +1749,8 @@
 		return -EINVAL;
 	}
 
-	/* 1.-4. Calculate client output geometry */
-	calculate_client_output(icd, &f->fmt.pix, &mf);
+	/* 1.-4. Calculate desired client output geometry */
+	calculate_client_output(icd, pix, &mf);
 	mf.field	= pix->field;
 	mf.colorspace	= pix->colorspace;
 	mf.code		= xlate->code;
@@ -1639,6 +1766,9 @@
 		image_mode = false;
 	}
 
+	dev_geo(dev, "S_FMT(pix=0x%x, fld 0x%x, code 0x%x, %ux%u)\n", pixfmt, mf.field, mf.code,
+		pix->width, pix->height);
+
 	dev_geo(dev, "4: request camera output %ux%u\n", mf.width, mf.height);
 
 	/* 5. - 9. */
@@ -1700,6 +1830,10 @@
 	pcdev->field = field;
 	pcdev->image_mode = image_mode;
 
+	/* CFSZR requirement */
+	pix->width	&= ~3;
+	pix->height	&= ~3;
+
 	return 0;
 }
 
@@ -1725,7 +1859,8 @@
 
 	/* FIXME: calculate using depth and bus width */
 
-	v4l_bound_align_image(&pix->width, 2, 2560, 1,
+	/* CFSZR requires height and width to be 4-pixel aligned */
+	v4l_bound_align_image(&pix->width, 2, 2560, 2,
 			      &pix->height, 4, 1920, 2, 0);
 
 	width = pix->width;
@@ -1738,7 +1873,8 @@
 	mf.code		= xlate->code;
 	mf.colorspace	= pix->colorspace;
 
-	ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video, try_mbus_fmt, &mf);
+	ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd),
+					 video, try_mbus_fmt, &mf);
 	if (ret < 0)
 		return ret;
 
@@ -1762,8 +1898,9 @@
 			 */
 			mf.width = 2560;
 			mf.height = 1920;
-			ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
-							 try_mbus_fmt, &mf);
+			ret = v4l2_device_call_until_err(sd->v4l2_dev,
+					soc_camera_grp_id(icd), video,
+					try_mbus_fmt, &mf);
 			if (ret < 0) {
 				/* Shouldn't actually happen... */
 				dev_err(icd->parent,
@@ -1778,6 +1915,9 @@
 			pix->height = height;
 	}
 
+	pix->width	&= ~3;
+	pix->height	&= ~3;
+
 	dev_geo(icd->parent, "%s(): return %d, fmt 0x%x, %ux%u\n",
 		__func__, ret, pix->pixelformat, pix->width, pix->height);
 
@@ -1824,8 +1964,8 @@
 			     out_height != f.fmt.pix.height))
 			ret = -EINVAL;
 		if (!ret) {
-			icd->user_width		= out_width;
-			icd->user_height	= out_height;
+			icd->user_width		= out_width & ~3;
+			icd->user_height	= out_height & ~3;
 			ret = sh_mobile_ceu_set_bus_param(icd,
 					icd->current_fmt->host_fmt->fourcc);
 		}
@@ -1869,55 +2009,6 @@
 	return vb2_queue_init(q);
 }
 
-static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd,
-				  struct v4l2_control *ctrl)
-{
-	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-	struct sh_mobile_ceu_dev *pcdev = ici->priv;
-	u32 val;
-
-	switch (ctrl->id) {
-	case V4L2_CID_SHARPNESS:
-		val = ceu_read(pcdev, CLFCR);
-		ctrl->value = val ^ 1;
-		return 0;
-	}
-	return -ENOIOCTLCMD;
-}
-
-static int sh_mobile_ceu_set_ctrl(struct soc_camera_device *icd,
-				  struct v4l2_control *ctrl)
-{
-	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-	struct sh_mobile_ceu_dev *pcdev = ici->priv;
-
-	switch (ctrl->id) {
-	case V4L2_CID_SHARPNESS:
-		switch (icd->current_fmt->host_fmt->fourcc) {
-		case V4L2_PIX_FMT_NV12:
-		case V4L2_PIX_FMT_NV21:
-		case V4L2_PIX_FMT_NV16:
-		case V4L2_PIX_FMT_NV61:
-			ceu_write(pcdev, CLFCR, !ctrl->value);
-			return 0;
-		}
-		return -EINVAL;
-	}
-	return -ENOIOCTLCMD;
-}
-
-static const struct v4l2_queryctrl sh_mobile_ceu_controls[] = {
-	{
-		.id		= V4L2_CID_SHARPNESS,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Low-pass filter",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 0,
-	},
-};
-
 static struct soc_camera_host_ops sh_mobile_ceu_host_ops = {
 	.owner		= THIS_MODULE,
 	.add		= sh_mobile_ceu_add_device,
@@ -1929,14 +2020,10 @@
 	.set_livecrop	= sh_mobile_ceu_set_livecrop,
 	.set_fmt	= sh_mobile_ceu_set_fmt,
 	.try_fmt	= sh_mobile_ceu_try_fmt,
-	.set_ctrl	= sh_mobile_ceu_set_ctrl,
-	.get_ctrl	= sh_mobile_ceu_get_ctrl,
 	.poll		= sh_mobile_ceu_poll,
 	.querycap	= sh_mobile_ceu_querycap,
 	.set_bus_param	= sh_mobile_ceu_set_bus_param,
 	.init_videobuf2	= sh_mobile_ceu_init_videobuf,
-	.controls	= sh_mobile_ceu_controls,
-	.num_controls	= ARRAY_SIZE(sh_mobile_ceu_controls),
 };
 
 struct bus_wait {
diff -druN linux-libre-3.1-gnu/drivers/media/video/sh_mobile_csi2.c linux-libre-3.2-gnu/drivers/media/video/sh_mobile_csi2.c
--- linux-libre-3.1-gnu/drivers/media/video/sh_mobile_csi2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/sh_mobile_csi2.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,10 +15,12 @@
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
+#include <linux/module.h>
 
 #include <media/sh_mobile_ceu.h>
 #include <media/sh_mobile_csi2.h>
 #include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-device.h>
@@ -35,11 +37,10 @@
 	struct v4l2_subdev		subdev;
 	struct list_head		list;
 	unsigned int			irq;
+	unsigned long			mipi_flags;
 	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,
@@ -127,9 +128,34 @@
 	return 0;
 }
 
+static int sh_csi2_g_mbus_config(struct v4l2_subdev *sd,
+				 struct v4l2_mbus_config *cfg)
+{
+	cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_MASTER | V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+
+	return 0;
+}
+
+static int sh_csi2_s_mbus_config(struct v4l2_subdev *sd,
+				 const struct v4l2_mbus_config *cfg)
+{
+	struct sh_csi2 *priv = container_of(sd, struct sh_csi2, subdev);
+	struct soc_camera_device *icd = v4l2_get_subdev_hostdata(sd);
+	struct v4l2_subdev *client_sd = soc_camera_to_subdev(icd);
+	struct v4l2_mbus_config client_cfg = {.type = V4L2_MBUS_CSI2,
+					      .flags = priv->mipi_flags};
+
+	return v4l2_subdev_call(client_sd, video, s_mbus_config, &client_cfg);
+}
+
 static struct v4l2_subdev_video_ops sh_csi2_subdev_video_ops = {
 	.s_mbus_fmt	= sh_csi2_s_fmt,
 	.try_mbus_fmt	= sh_csi2_try_fmt,
+	.g_mbus_config	= sh_csi2_g_mbus_config,
+	.s_mbus_config	= sh_csi2_s_mbus_config,
 };
 
 static void sh_csi2_hwinit(struct sh_csi2 *priv)
@@ -144,11 +170,21 @@
 	udelay(5);
 	iowrite32(0x00000000, priv->base + SH_CSI2_SRST);
 
-	if (priv->client->lanes & 3)
-		tmp |= priv->client->lanes & 3;
-	else
-		/* Default - both lanes */
-		tmp |= 3;
+	switch (pdata->type) {
+	case SH_CSI2C:
+		if (priv->client->lanes == 1)
+			tmp |= 1;
+		else
+			/* Default - both lanes */
+			tmp |= 3;
+		break;
+	case SH_CSI2I:
+		if (!priv->client->lanes || priv->client->lanes > 4)
+			/* Default - all 4 lanes */
+			tmp |= 0xf;
+		else
+			tmp |= (1 << priv->client->lanes) - 1;
+	}
 
 	if (priv->client->phy == SH_CSI2_PHY_MAIN)
 		tmp |= 0x8000;
@@ -163,38 +199,18 @@
 	iowrite32(tmp, priv->base + SH_CSI2_CHKSUM);
 }
 
-static int sh_csi2_set_bus_param(struct soc_camera_device *icd,
-				 unsigned long flags)
-{
-	return 0;
-}
-
-static unsigned long sh_csi2_query_bus_param(struct soc_camera_device *icd)
-{
-	struct soc_camera_link *icl = to_soc_camera_link(icd);
-	const unsigned long flags = SOCAM_PCLK_SAMPLE_RISING |
-		SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
-		SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_DATA_ACTIVE_HIGH;
-
-	return soc_camera_apply_sensor_flags(icl, flags);
-}
-
 static int sh_csi2_client_connect(struct sh_csi2 *priv)
 {
 	struct sh_csi2_pdata *pdata = priv->pdev->dev.platform_data;
-	struct v4l2_subdev *sd, *csi2_sd = &priv->subdev;
-	struct soc_camera_device *icd = NULL;
+	struct soc_camera_device *icd = v4l2_get_subdev_hostdata(&priv->subdev);
+	struct v4l2_subdev *client_sd = soc_camera_to_subdev(icd);
 	struct device *dev = v4l2_get_subdevdata(&priv->subdev);
-	int i;
-
-	v4l2_device_for_each_subdev(sd, csi2_sd->v4l2_dev)
-		if (sd->grp_id) {
-			icd = (struct soc_camera_device *)sd->grp_id;
-			break;
-		}
+	struct v4l2_mbus_config cfg;
+	unsigned long common_flags, csi2_flags;
+	int i, ret;
 
-	if (!icd)
-		return -EINVAL;
+	if (priv->client)
+		return -EBUSY;
 
 	for (i = 0; i < pdata->num_clients; i++)
 		if (&pdata->clients[i].pdev->dev == icd->pdev)
@@ -205,14 +221,41 @@
 	if (i == pdata->num_clients)
 		return -ENODEV;
 
-	priv->client = pdata->clients + i;
+	/* Check if we can support this camera */
+	csi2_flags = V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | V4L2_MBUS_CSI2_1_LANE;
 
-	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;
+	switch (pdata->type) {
+	case SH_CSI2C:
+		if (pdata->clients[i].lanes != 1)
+			csi2_flags |= V4L2_MBUS_CSI2_2_LANE;
+		break;
+	case SH_CSI2I:
+		switch (pdata->clients[i].lanes) {
+		default:
+			csi2_flags |= V4L2_MBUS_CSI2_4_LANE;
+		case 3:
+			csi2_flags |= V4L2_MBUS_CSI2_3_LANE;
+		case 2:
+			csi2_flags |= V4L2_MBUS_CSI2_2_LANE;
+		}
+	}
 
-	csi2_sd->grp_id = (long)icd;
+	cfg.type = V4L2_MBUS_CSI2;
+	ret = v4l2_subdev_call(client_sd, video, g_mbus_config, &cfg);
+	if (ret == -ENOIOCTLCMD)
+		common_flags = csi2_flags;
+	else if (!ret)
+		common_flags = soc_mbus_config_compatible(&cfg,
+							  csi2_flags);
+	else
+		common_flags = 0;
+
+	if (!common_flags)
+		return -EINVAL;
+
+	/* All good: camera MIPI configuration supported */
+	priv->mipi_flags = common_flags;
+	priv->client = pdata->clients + i;
 
 	pm_runtime_get_sync(dev);
 
@@ -223,16 +266,10 @@
 
 static void sh_csi2_client_disconnect(struct sh_csi2 *priv)
 {
-	struct soc_camera_device *icd = (struct soc_camera_device *)priv->subdev.grp_id;
+	if (!priv->client)
+		return;
 
 	priv->client = NULL;
-	priv->subdev.grp_id = 0;
-
-	/* Driver is about to be unbound */
-	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;
 
 	pm_runtime_put(v4l2_get_subdevdata(&priv->subdev));
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/sh_vou.c linux-libre-3.2-gnu/drivers/media/video/sh_vou.c
--- linux-libre-3.1-gnu/drivers/media/video/sh_vou.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/sh_vou.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
+#include <linux/module.h>
 
 #include <media/sh_vou.h>
 #include <media/v4l2-common.h>
diff -druN linux-libre-3.1-gnu/drivers/media/video/soc_camera.c linux-libre-3.2-gnu/drivers/media/video/soc_camera.c
--- linux-libre-3.1-gnu/drivers/media/video/soc_camera.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/soc_camera.c	2012-01-04 18:55:44.000000000 -0500
@@ -50,49 +50,65 @@
 static LIST_HEAD(devices);
 static DEFINE_MUTEX(list_lock);		/* Protects the list of hosts */
 
-static int soc_camera_power_set(struct soc_camera_device *icd,
-				struct soc_camera_link *icl,
-				int power_on)
+static int soc_camera_power_on(struct soc_camera_device *icd,
+			       struct soc_camera_link *icl)
 {
-	int ret;
-
-	if (power_on) {
-		ret = regulator_bulk_enable(icl->num_regulators,
-					    icl->regulators);
-		if (ret < 0) {
-			dev_err(icd->pdev, "Cannot enable regulators\n");
-			return ret;
-		}
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+	int ret = regulator_bulk_enable(icl->num_regulators,
+					icl->regulators);
+	if (ret < 0) {
+		dev_err(icd->pdev, "Cannot enable regulators\n");
+		return ret;
+	}
 
-		if (icl->power)
-			ret = icl->power(icd->pdev, power_on);
+	if (icl->power) {
+		ret = icl->power(icd->pdev, 1);
 		if (ret < 0) {
 			dev_err(icd->pdev,
 				"Platform failed to power-on the camera.\n");
-
-			regulator_bulk_disable(icl->num_regulators,
-					       icl->regulators);
-			return ret;
+			goto elinkpwr;
 		}
-	} else {
-		ret = 0;
-		if (icl->power)
-			ret = icl->power(icd->pdev, 0);
+	}
+
+	ret = v4l2_subdev_call(sd, core, s_power, 1);
+	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
+		goto esdpwr;
+
+	return 0;
+
+esdpwr:
+	if (icl->power)
+		icl->power(icd->pdev, 0);
+elinkpwr:
+	regulator_bulk_disable(icl->num_regulators,
+			       icl->regulators);
+	return ret;
+}
+
+static int soc_camera_power_off(struct soc_camera_device *icd,
+				struct soc_camera_link *icl)
+{
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+	int ret = v4l2_subdev_call(sd, core, s_power, 0);
+
+	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
+		return ret;
+
+	if (icl->power) {
+		ret = icl->power(icd->pdev, 0);
 		if (ret < 0) {
 			dev_err(icd->pdev,
 				"Platform failed to power-off the camera.\n");
 			return ret;
 		}
-
-		ret = regulator_bulk_disable(icl->num_regulators,
-					     icl->regulators);
-		if (ret < 0) {
-			dev_err(icd->pdev, "Cannot disable regulators\n");
-			return ret;
-		}
 	}
 
-	return 0;
+	ret = regulator_bulk_disable(icl->num_regulators,
+				     icl->regulators);
+	if (ret < 0)
+		dev_err(icd->pdev, "Cannot disable regulators\n");
+
+	return ret;
 }
 
 const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
@@ -108,38 +124,38 @@
 EXPORT_SYMBOL(soc_camera_xlate_by_fourcc);
 
 /**
- * soc_camera_apply_sensor_flags() - apply platform SOCAM_SENSOR_INVERT_* flags
+ * soc_camera_apply_board_flags() - apply platform SOCAM_SENSOR_INVERT_* flags
  * @icl:	camera platform parameters
- * @flags:	flags to be inverted according to platform configuration
+ * @cfg:	media bus configuration
  * @return:	resulting flags
  */
-unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl,
-					    unsigned long flags)
+unsigned long soc_camera_apply_board_flags(struct soc_camera_link *icl,
+					   const struct v4l2_mbus_config *cfg)
 {
-	unsigned long f;
+	unsigned long f, flags = cfg->flags;
 
 	/* If only one of the two polarities is supported, switch to the opposite */
 	if (icl->flags & SOCAM_SENSOR_INVERT_HSYNC) {
-		f = flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW);
-		if (f == SOCAM_HSYNC_ACTIVE_HIGH || f == SOCAM_HSYNC_ACTIVE_LOW)
-			flags ^= SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW;
+		f = flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW);
+		if (f == V4L2_MBUS_HSYNC_ACTIVE_HIGH || f == V4L2_MBUS_HSYNC_ACTIVE_LOW)
+			flags ^= V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW;
 	}
 
 	if (icl->flags & SOCAM_SENSOR_INVERT_VSYNC) {
-		f = flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW);
-		if (f == SOCAM_VSYNC_ACTIVE_HIGH || f == SOCAM_VSYNC_ACTIVE_LOW)
-			flags ^= SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW;
+		f = flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW);
+		if (f == V4L2_MBUS_VSYNC_ACTIVE_HIGH || f == V4L2_MBUS_VSYNC_ACTIVE_LOW)
+			flags ^= V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW;
 	}
 
 	if (icl->flags & SOCAM_SENSOR_INVERT_PCLK) {
-		f = flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING);
-		if (f == SOCAM_PCLK_SAMPLE_RISING || f == SOCAM_PCLK_SAMPLE_FALLING)
-			flags ^= SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING;
+		f = flags & (V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING);
+		if (f == V4L2_MBUS_PCLK_SAMPLE_RISING || f == V4L2_MBUS_PCLK_SAMPLE_FALLING)
+			flags ^= V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING;
 	}
 
 	return flags;
 }
-EXPORT_SYMBOL(soc_camera_apply_sensor_flags);
+EXPORT_SYMBOL(soc_camera_apply_board_flags);
 
 #define pixfmtstr(x) (x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, \
 	((x) >> 24) & 0xff
@@ -233,6 +249,14 @@
 	return v4l2_subdev_call(sd, core, s_std, *a);
 }
 
+static int soc_camera_g_std(struct file *file, void *priv, v4l2_std_id *a)
+{
+	struct soc_camera_device *icd = file->private_data;
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+
+	return v4l2_subdev_call(sd, core, g_std, a);
+}
+
 static int soc_camera_enum_fsizes(struct file *file, void *fh,
 					 struct v4l2_frmsizeenum *fsize)
 {
@@ -318,6 +342,32 @@
 		return vb2_dqbuf(&icd->vb2_vidq, p, file->f_flags & O_NONBLOCK);
 }
 
+static int soc_camera_create_bufs(struct file *file, void *priv,
+			    struct v4l2_create_buffers *create)
+{
+	struct soc_camera_device *icd = file->private_data;
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+
+	/* videobuf2 only */
+	if (ici->ops->init_videobuf)
+		return -EINVAL;
+	else
+		return vb2_create_bufs(&icd->vb2_vidq, create);
+}
+
+static int soc_camera_prepare_buf(struct file *file, void *priv,
+				  struct v4l2_buffer *b)
+{
+	struct soc_camera_device *icd = file->private_data;
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+
+	/* videobuf2 only */
+	if (ici->ops->init_videobuf)
+		return -EINVAL;
+	else
+		return vb2_prepare_buf(&icd->vb2_vidq, b);
+}
+
 /* Always entered with .video_lock held */
 static int soc_camera_init_user_formats(struct soc_camera_device *icd)
 {
@@ -448,7 +498,7 @@
 	struct soc_camera_host *ici;
 	int ret;
 
-	if (!icd->ops)
+	if (!to_soc_camera_control(icd))
 		/* No device driver attached */
 		return -ENODEV;
 
@@ -476,7 +526,7 @@
 			},
 		};
 
-		ret = soc_camera_power_set(icd, icl, 1);
+		ret = soc_camera_power_on(icd, icl);
 		if (ret < 0)
 			goto epower;
 
@@ -512,6 +562,7 @@
 			if (ret < 0)
 				goto einitvb;
 		}
+		v4l2_ctrl_handler_setup(&icd->ctrl_handler);
 	}
 
 	file->private_data = icd;
@@ -529,7 +580,7 @@
 eresume:
 	ici->ops->remove(icd);
 eiciadd:
-	soc_camera_power_set(icd, icl, 0);
+	soc_camera_power_off(icd, icl);
 epower:
 	icd->use_count--;
 	module_put(ici->ops->owner);
@@ -553,7 +604,7 @@
 		if (ici->ops->init_videobuf2)
 			vb2_queue_release(&icd->vb2_vidq);
 
-		soc_camera_power_set(icd, icl, 0);
+		soc_camera_power_off(icd, icl);
 	}
 
 	if (icd->streamer == file)
@@ -781,75 +832,6 @@
 	return 0;
 }
 
-static int soc_camera_queryctrl(struct file *file, void *priv,
-				struct v4l2_queryctrl *qc)
-{
-	struct soc_camera_device *icd = file->private_data;
-	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-	int i;
-
-	WARN_ON(priv != file->private_data);
-
-	if (!qc->id)
-		return -EINVAL;
-
-	/* First check host controls */
-	for (i = 0; i < ici->ops->num_controls; i++)
-		if (qc->id == ici->ops->controls[i].id) {
-			memcpy(qc, &(ici->ops->controls[i]),
-				sizeof(*qc));
-			return 0;
-		}
-
-	/* Then device controls */
-	for (i = 0; i < icd->ops->num_controls; i++)
-		if (qc->id == icd->ops->controls[i].id) {
-			memcpy(qc, &(icd->ops->controls[i]),
-				sizeof(*qc));
-			return 0;
-		}
-
-	return -EINVAL;
-}
-
-static int soc_camera_g_ctrl(struct file *file, void *priv,
-			     struct v4l2_control *ctrl)
-{
-	struct soc_camera_device *icd = file->private_data;
-	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-	int ret;
-
-	WARN_ON(priv != file->private_data);
-
-	if (ici->ops->get_ctrl) {
-		ret = ici->ops->get_ctrl(icd, ctrl);
-		if (ret != -ENOIOCTLCMD)
-			return ret;
-	}
-
-	return v4l2_subdev_call(sd, core, g_ctrl, ctrl);
-}
-
-static int soc_camera_s_ctrl(struct file *file, void *priv,
-			     struct v4l2_control *ctrl)
-{
-	struct soc_camera_device *icd = file->private_data;
-	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-	int ret;
-
-	WARN_ON(priv != file->private_data);
-
-	if (ici->ops->set_ctrl) {
-		ret = ici->ops->set_ctrl(icd, ctrl);
-		if (ret != -ENOIOCTLCMD)
-			return ret;
-	}
-
-	return v4l2_subdev_call(sd, core, s_ctrl, ctrl);
-}
-
 static int soc_camera_cropcap(struct file *file, void *fh,
 			      struct v4l2_cropcap *a)
 {
@@ -1003,7 +985,7 @@
 		goto ei2cga;
 	}
 
-	icl->board_info->platform_data = icd;
+	icl->board_info->platform_data = icl;
 
 	subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap,
 				icl->board_info, NULL);
@@ -1052,12 +1034,29 @@
 
 	dev_info(icd->pdev, "Probing %s\n", dev_name(icd->pdev));
 
+	/*
+	 * Currently the subdev with the largest number of controls (13) is
+	 * ov6550. So let's pick 16 as a hint for the control handler. Note
+	 * that this is a hint only: too large and you waste some memory, too
+	 * small and there is a (very) small performance hit when looking up
+	 * controls in the internal hash.
+	 */
+	ret = v4l2_ctrl_handler_init(&icd->ctrl_handler, 16);
+	if (ret < 0)
+		return ret;
+
 	ret = regulator_bulk_get(icd->pdev, icl->num_regulators,
 				 icl->regulators);
 	if (ret < 0)
 		goto ereg;
 
-	ret = soc_camera_power_set(icd, icl, 1);
+	/*
+	 * This will not yet call v4l2_subdev_core_ops::s_power(1), because the
+	 * subdevice has not been initialised yet. We'll have to call it once
+	 * again after initialisation, even though it shouldn't be needed, we
+	 * don't do any IO here.
+	 */
+	ret = soc_camera_power_on(icd, icl);
 	if (ret < 0)
 		goto epower;
 
@@ -1098,12 +1097,17 @@
 		if (!control || !control->driver || !dev_get_drvdata(control) ||
 		    !try_module_get(control->driver->owner)) {
 			icl->del_device(icd);
+			ret = -ENODEV;
 			goto enodrv;
 		}
 	}
 
 	sd = soc_camera_to_subdev(icd);
-	sd->grp_id = (long)icd;
+	sd->grp_id = soc_camera_grp_id(icd);
+	v4l2_set_subdev_hostdata(sd, icd);
+
+	if (v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler))
+		goto ectrl;
 
 	/* At this point client .probe() should have run already */
 	ret = soc_camera_init_user_formats(icd);
@@ -1123,6 +1127,10 @@
 	if (ret < 0)
 		goto evidstart;
 
+	ret = v4l2_subdev_call(sd, core, s_power, 1);
+	if (ret < 0 && ret != -ENOIOCTLCMD)
+		goto esdpwr;
+
 	/* Try to improve our guess of a reasonable window format */
 	if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) {
 		icd->user_width		= mf.width;
@@ -1133,16 +1141,19 @@
 
 	ici->ops->remove(icd);
 
-	soc_camera_power_set(icd, icl, 0);
+	soc_camera_power_off(icd, icl);
 
 	mutex_unlock(&icd->video_lock);
 
 	return 0;
 
+esdpwr:
+	video_unregister_device(icd->vdev);
 evidstart:
 	mutex_unlock(&icd->video_lock);
 	soc_camera_free_user_formats(icd);
 eiufmt:
+ectrl:
 	if (icl->board_info) {
 		soc_camera_free_i2c(icd);
 	} else {
@@ -1152,13 +1163,15 @@
 enodrv:
 eadddev:
 	video_device_release(icd->vdev);
+	icd->vdev = NULL;
 evdc:
 	ici->ops->remove(icd);
 eadd:
-	soc_camera_power_set(icd, icl, 0);
+	soc_camera_power_off(icd, icl);
 epower:
 	regulator_bulk_free(icl->num_regulators, icl->regulators);
 ereg:
+	v4l2_ctrl_handler_free(&icd->ctrl_handler);
 	return ret;
 }
 
@@ -1173,6 +1186,7 @@
 
 	BUG_ON(!icd->parent);
 
+	v4l2_ctrl_handler_free(&icd->ctrl_handler);
 	if (vdev) {
 		video_unregister_device(vdev);
 		icd->vdev = NULL;
@@ -1363,24 +1377,24 @@
 
 static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
 	.vidioc_querycap	 = soc_camera_querycap,
+	.vidioc_try_fmt_vid_cap  = soc_camera_try_fmt_vid_cap,
 	.vidioc_g_fmt_vid_cap    = soc_camera_g_fmt_vid_cap,
-	.vidioc_enum_fmt_vid_cap = soc_camera_enum_fmt_vid_cap,
 	.vidioc_s_fmt_vid_cap    = soc_camera_s_fmt_vid_cap,
+	.vidioc_enum_fmt_vid_cap = soc_camera_enum_fmt_vid_cap,
 	.vidioc_enum_input	 = soc_camera_enum_input,
 	.vidioc_g_input		 = soc_camera_g_input,
 	.vidioc_s_input		 = soc_camera_s_input,
 	.vidioc_s_std		 = soc_camera_s_std,
+	.vidioc_g_std		 = soc_camera_g_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,
 	.vidioc_qbuf		 = soc_camera_qbuf,
 	.vidioc_dqbuf		 = soc_camera_dqbuf,
+	.vidioc_create_bufs	 = soc_camera_create_bufs,
+	.vidioc_prepare_buf	 = soc_camera_prepare_buf,
 	.vidioc_streamon	 = soc_camera_streamon,
 	.vidioc_streamoff	 = soc_camera_streamoff,
-	.vidioc_queryctrl	 = soc_camera_queryctrl,
-	.vidioc_g_ctrl		 = soc_camera_g_ctrl,
-	.vidioc_s_ctrl		 = soc_camera_s_ctrl,
 	.vidioc_cropcap		 = soc_camera_cropcap,
 	.vidioc_g_crop		 = soc_camera_g_crop,
 	.vidioc_s_crop		 = soc_camera_s_crop,
@@ -1409,6 +1423,7 @@
 	vdev->ioctl_ops		= &soc_camera_ioctl_ops;
 	vdev->release		= video_device_release;
 	vdev->tvnorms		= V4L2_STD_UNKNOWN;
+	vdev->ctrl_handler	= &icd->ctrl_handler;
 	vdev->lock		= &icd->video_lock;
 
 	icd->vdev = vdev;
@@ -1427,11 +1442,6 @@
 	if (!icd->parent)
 		return -ENODEV;
 
-	if (!icd->ops ||
-	    !icd->ops->query_bus_param ||
-	    !icd->ops->set_bus_param)
-		return -EINVAL;
-
 	ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, -1);
 	if (ret < 0) {
 		dev_err(icd->pdev, "video_register_device failed: %d\n", ret);
diff -druN linux-libre-3.1-gnu/drivers/media/video/soc_camera_platform.c linux-libre-3.2-gnu/drivers/media/video/soc_camera_platform.c
--- linux-libre-3.1-gnu/drivers/media/video/soc_camera_platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/soc_camera_platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,32 +30,12 @@
 	return container_of(subdev, struct soc_camera_platform_priv, subdev);
 }
 
-static struct soc_camera_platform_info *get_info(struct soc_camera_device *icd)
-{
-	struct platform_device *pdev =
-		to_platform_device(to_soc_camera_control(icd));
-	return pdev->dev.platform_data;
-}
-
 static int soc_camera_platform_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
 	return p->set_capture(p, enable);
 }
 
-static int soc_camera_platform_set_bus_param(struct soc_camera_device *icd,
-					     unsigned long flags)
-{
-	return 0;
-}
-
-static unsigned long
-soc_camera_platform_query_bus_param(struct soc_camera_device *icd)
-{
-	struct soc_camera_platform_info *p = get_info(icd);
-	return p->bus_param;
-}
-
 static int soc_camera_platform_fill_fmt(struct v4l2_subdev *sd,
 					struct v4l2_mbus_framefmt *mf)
 {
@@ -115,6 +95,17 @@
 	return 0;
 }
 
+static int soc_camera_platform_g_mbus_config(struct v4l2_subdev *sd,
+					     struct v4l2_mbus_config *cfg)
+{
+	struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
+
+	cfg->flags = p->mbus_param;
+	cfg->type = p->mbus_type;
+
+	return 0;
+}
+
 static struct v4l2_subdev_video_ops platform_subdev_video_ops = {
 	.s_stream	= soc_camera_platform_s_stream,
 	.enum_mbus_fmt	= soc_camera_platform_enum_fmt,
@@ -123,6 +114,7 @@
 	.try_mbus_fmt	= soc_camera_platform_fill_fmt,
 	.g_mbus_fmt	= soc_camera_platform_fill_fmt,
 	.s_mbus_fmt	= soc_camera_platform_fill_fmt,
+	.g_mbus_config	= soc_camera_platform_g_mbus_config,
 };
 
 static struct v4l2_subdev_ops platform_subdev_ops = {
@@ -130,11 +122,6 @@
 	.video	= &platform_subdev_video_ops,
 };
 
-static struct soc_camera_ops soc_camera_platform_ops = {
-	.set_bus_param		= soc_camera_platform_set_bus_param,
-	.query_bus_param	= soc_camera_platform_query_bus_param,
-};
-
 static int soc_camera_platform_probe(struct platform_device *pdev)
 {
 	struct soc_camera_host *ici;
@@ -163,8 +150,6 @@
 	/* Set the control device reference */
 	icd->control = &pdev->dev;
 
-	icd->ops = &soc_camera_platform_ops;
-
 	ici = to_soc_camera_host(icd->parent);
 
 	v4l2_subdev_init(&priv->subdev, &platform_subdev_ops);
@@ -178,7 +163,6 @@
 	return ret;
 
 evdrs:
-	icd->ops = NULL;
 	platform_set_drvdata(pdev, NULL);
 	kfree(priv);
 	return ret;
@@ -187,11 +171,10 @@
 static int soc_camera_platform_remove(struct platform_device *pdev)
 {
 	struct soc_camera_platform_priv *priv = get_priv(pdev);
-	struct soc_camera_platform_info *p = pdev->dev.platform_data;
-	struct soc_camera_device *icd = p->icd;
+	struct soc_camera_platform_info *p = v4l2_get_subdevdata(&priv->subdev);
 
+	p->icd->control = NULL;
 	v4l2_device_unregister_subdev(&priv->subdev);
-	icd->ops = NULL;
 	platform_set_drvdata(pdev, NULL);
 	kfree(priv);
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/media/video/soc_mediabus.c linux-libre-3.2-gnu/drivers/media/video/soc_mediabus.c
--- linux-libre-3.1-gnu/drivers/media/video/soc_mediabus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/soc_mediabus.c	2012-01-04 18:55:44.000000000 -0500
@@ -383,6 +383,39 @@
 }
 EXPORT_SYMBOL(soc_mbus_get_fmtdesc);
 
+unsigned int soc_mbus_config_compatible(const struct v4l2_mbus_config *cfg,
+					unsigned int flags)
+{
+	unsigned long common_flags;
+	bool hsync = true, vsync = true, pclk, data, mode;
+	bool mipi_lanes, mipi_clock;
+
+	common_flags = cfg->flags & flags;
+
+	switch (cfg->type) {
+	case V4L2_MBUS_PARALLEL:
+		hsync = common_flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+					V4L2_MBUS_HSYNC_ACTIVE_LOW);
+		vsync = common_flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+					V4L2_MBUS_VSYNC_ACTIVE_LOW);
+	case V4L2_MBUS_BT656:
+		pclk = common_flags & (V4L2_MBUS_PCLK_SAMPLE_RISING |
+				       V4L2_MBUS_PCLK_SAMPLE_FALLING);
+		data = common_flags & (V4L2_MBUS_DATA_ACTIVE_HIGH |
+				       V4L2_MBUS_DATA_ACTIVE_LOW);
+		mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE);
+		return (!hsync || !vsync || !pclk || !data || !mode) ?
+			0 : common_flags;
+	case V4L2_MBUS_CSI2:
+		mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES;
+		mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK |
+					     V4L2_MBUS_CSI2_CONTINUOUS_CLOCK);
+		return (!mipi_lanes || !mipi_clock) ? 0 : common_flags;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(soc_mbus_config_compatible);
+
 static int __init soc_mbus_init(void)
 {
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/media/video/sr030pc30.c linux-libre-3.2-gnu/drivers/media/video/sr030pc30.c
--- linux-libre-3.1-gnu/drivers/media/video/sr030pc30.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/sr030pc30.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/i2c.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-mediabus.h>
@@ -714,11 +715,6 @@
 	return ret;
 }
 
-static int sr030pc30_s_stream(struct v4l2_subdev *sd, int enable)
-{
-	return 0;
-}
-
 static int sr030pc30_s_power(struct v4l2_subdev *sd, int on)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -764,7 +760,6 @@
 };
 
 static const struct v4l2_subdev_video_ops sr030pc30_video_ops = {
-	.s_stream	= sr030pc30_s_stream,
 	.g_mbus_fmt	= sr030pc30_g_fmt,
 	.s_mbus_fmt	= sr030pc30_s_fmt,
 	.try_mbus_fmt	= sr030pc30_try_fmt,
diff -druN linux-libre-3.1-gnu/drivers/media/video/stk-webcam.c linux-libre-3.2-gnu/drivers/media/video/stk-webcam.c
--- linux-libre-3.1-gnu/drivers/media/video/stk-webcam.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/stk-webcam.c	2012-01-04 18:55:44.000000000 -0500
@@ -55,6 +55,8 @@
 MODULE_DESCRIPTION("Syntek DC1125 webcam driver");
 
 
+/* bool for webcam LED management */
+int first_init = 1;
 
 /* Some cameras have audio interfaces, we aren't interested in those */
 static struct usb_device_id stkwebcam_table[] = {
@@ -518,7 +520,7 @@
 			return -ENOMEM;
 		for (i = 0; i < n_sbufs; i++) {
 			if (stk_setup_siobuf(dev, i))
-				return (dev->n_sbufs > 1)? 0 : -ENOMEM;
+				return (dev->n_sbufs > 1 ? 0 : -ENOMEM);
 			dev->n_sbufs = i+1;
 		}
 	}
@@ -558,9 +560,14 @@
 	vdev = video_devdata(fp);
 	dev = vdev_to_camera(vdev);
 
-	if (dev == NULL || !is_present(dev)) {
+	if (dev == NULL || !is_present(dev))
 		return -ENXIO;
-	}
+
+	if (!first_init)
+		stk_camera_write_reg(dev, 0x0, 0x24);
+	else
+		first_init = 0;
+
 	fp->private_data = dev;
 	usb_autopm_get_interface(dev->interface);
 
@@ -574,10 +581,12 @@
 	if (dev->owner == fp) {
 		stk_stop_stream(dev);
 		stk_free_buffers(dev);
+		stk_camera_write_reg(dev, 0x0, 0x49); /* turn off the LED */
+		unset_initialised(dev);
 		dev->owner = NULL;
 	}
 
-	if(is_present(dev))
+	if (is_present(dev))
 		usb_autopm_put_interface(dev->interface);
 
 	return 0;
@@ -654,7 +663,7 @@
 		return POLLERR;
 
 	if (!list_empty(&dev->sio_full))
-		return (POLLIN | POLLRDNORM);
+		return POLLIN | POLLRDNORM;
 
 	return 0;
 }
@@ -891,9 +900,9 @@
 	struct stk_camera *dev = priv;
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(stk_sizes)
-			&& stk_sizes[i].m != dev->vsettings.mode;
-		i++);
+	for (i = 0; i < ARRAY_SIZE(stk_sizes) &&
+			stk_sizes[i].m != dev->vsettings.mode; i++)
+		;
 	if (i == ARRAY_SIZE(stk_sizes)) {
 		STK_ERROR("ERROR: mode invalid\n");
 		return -EINVAL;
@@ -1305,9 +1314,8 @@
 	usb_set_intfdata(interface, dev);
 
 	err = stk_register_video_device(dev);
-	if (err) {
+	if (err)
 		goto error;
-	}
 
 	return 0;
 
@@ -1350,6 +1358,7 @@
 		return 0;
 	unset_initialised(dev);
 	stk_initialise(dev);
+	stk_camera_write_reg(dev, 0x0, 0x49);
 	stk_setup_format(dev);
 	if (is_streaming(dev))
 		stk_start_stream(dev);
diff -druN linux-libre-3.1-gnu/drivers/media/video/tcm825x.c linux-libre-3.2-gnu/drivers/media/video/tcm825x.c
--- linux-libre-3.1-gnu/drivers/media/video/tcm825x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/tcm825x.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
  */
 
 #include <linux/i2c.h>
+#include <linux/module.h>
 #include <media/v4l2-int-device.h>
 
 #include "tcm825x.h"
diff -druN linux-libre-3.1-gnu/drivers/media/video/timblogiw.c linux-libre-3.2-gnu/drivers/media/video/timblogiw.c
--- linux-libre-3.1-gnu/drivers/media/video/timblogiw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/timblogiw.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/i2c.h>
+#include <linux/module.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 #include <media/videobuf-dma-contig.h>
diff -druN linux-libre-3.1-gnu/drivers/media/video/tlg2300/Makefile linux-libre-3.2-gnu/drivers/media/video/tlg2300/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/tlg2300/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/tlg2300/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,8 +2,8 @@
 
 obj-$(CONFIG_VIDEO_TLG2300) += poseidon.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/tm6000/Kconfig linux-libre-3.2-gnu/drivers/media/video/tm6000/Kconfig
--- linux-libre-3.1-gnu/drivers/media/video/tm6000/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/tm6000/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,33 @@
+config VIDEO_TM6000
+	tristate "TV Master TM5600/6000/6010 driver"
+	depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB && EXPERIMENTAL
+	select VIDEO_TUNER
+	select MEDIA_TUNER_XC2028
+	select MEDIA_TUNER_XC5000
+	select VIDEOBUF_VMALLOC
+	help
+	  Support for TM5600/TM6000/TM6010 USB Device
+
+	  Since these cards have no MPEG decoder onboard, they transmit
+	  only compressed MPEG data over the usb bus, so you need
+	  an external software decoder to watch TV on your computer.
+
+	  Say Y if you own such a device and want to use it.
+
+config VIDEO_TM6000_ALSA
+	tristate "TV Master TM5600/6000/6010 audio support"
+	depends on VIDEO_TM6000 && SND && EXPERIMENTAL
+	select SND_PCM
+	---help---
+	  This is a video4linux driver for direct (DMA) audio for
+	  TM5600/TM6000/TM6010 USB Devices.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tm6000-alsa.
+
+config VIDEO_TM6000_DVB
+	tristate "DVB Support for tm6000 based TV cards"
+	depends on VIDEO_TM6000 && DVB_CORE && USB && EXPERIMENTAL
+	select DVB_ZL10353
+	---help---
+	  This adds support for DVB cards based on the tm5600/tm6000 chip.
diff -druN linux-libre-3.1-gnu/drivers/media/video/tm6000/Makefile linux-libre-3.2-gnu/drivers/media/video/tm6000/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/tm6000/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/tm6000/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,15 @@
+tm6000-y := tm6000-cards.o \
+		   tm6000-core.o  \
+		   tm6000-i2c.o   \
+		   tm6000-video.o \
+		   tm6000-stds.o \
+		   tm6000-input.o
+
+obj-$(CONFIG_VIDEO_TM6000) += tm6000.o
+obj-$(CONFIG_VIDEO_TM6000_ALSA) += tm6000-alsa.o
+obj-$(CONFIG_VIDEO_TM6000_DVB) += tm6000-dvb.o
+
+ccflags-y := -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff -druN linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-alsa.c linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-alsa.c
--- linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-alsa.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-alsa.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,513 @@
+/*
+ *
+ *  Support for audio capture for tm5600/6000/6010
+ *    (c) 2007-2008 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ *  Based on cx88-alsa.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/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+
+
+#include "tm6000.h"
+#include "tm6000-regs.h"
+
+#undef dprintk
+
+#define dprintk(level, fmt, arg...) do {				   \
+	if (debug >= level)						   \
+		printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg); \
+	} while (0)
+
+/****************************************************************************
+			Module global static vars
+ ****************************************************************************/
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
+
+static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
+
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable tm6000x soundcard. default enabled.");
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for tm6000x capture interface(s).");
+
+
+/****************************************************************************
+				Module macros
+ ****************************************************************************/
+
+MODULE_DESCRIPTION("ALSA driver module for tm5600/tm6000/tm6010 based TV cards");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Trident,tm5600},"
+			"{{Trident,tm6000},"
+			"{{Trident,tm6010}");
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+/****************************************************************************
+			Module specific funtions
+ ****************************************************************************/
+
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int _tm6000_start_audio_dma(struct snd_tm6000_card *chip)
+{
+	struct tm6000_core *core = chip->core;
+
+	dprintk(1, "Starting audio DMA\n");
+
+	/* Enables audio */
+	tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_IF, 0x40, 0x40);
+
+	tm6000_set_audio_bitrate(core, 48000);
+
+	return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+static int _tm6000_stop_audio_dma(struct snd_tm6000_card *chip)
+{
+	struct tm6000_core *core = chip->core;
+
+	dprintk(1, "Stopping audio DMA\n");
+
+	/* Disables audio */
+	tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_IF, 0x00, 0x40);
+
+	return 0;
+}
+
+static void dsp_buffer_free(struct snd_pcm_substream *substream)
+{
+	struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+
+	dprintk(2, "Freeing buffer\n");
+
+	vfree(substream->runtime->dma_area);
+	substream->runtime->dma_area = NULL;
+	substream->runtime->dma_bytes = 0;
+}
+
+static int dsp_buffer_alloc(struct snd_pcm_substream *substream, int size)
+{
+	struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+
+	dprintk(2, "Allocating buffer\n");
+
+	if (substream->runtime->dma_area) {
+		if (substream->runtime->dma_bytes > size)
+			return 0;
+
+		dsp_buffer_free(substream);
+	}
+
+	substream->runtime->dma_area = vmalloc(size);
+	if (!substream->runtime->dma_area)
+		return -ENOMEM;
+
+	substream->runtime->dma_bytes = size;
+
+	return 0;
+}
+
+
+/****************************************************************************
+				ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE	4096
+
+static struct snd_pcm_hardware snd_tm6000_digital_hw = {
+	.info = SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP_VALID,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+	.rates = SNDRV_PCM_RATE_CONTINUOUS,
+	.rate_min = 48000,
+	.rate_max = 48000,
+	.channels_min = 2,
+	.channels_max = 2,
+	.period_bytes_min = 64,
+	.period_bytes_max = 12544,
+	.periods_min = 1,
+	.periods_max = 98,
+	.buffer_bytes_max = 62720 * 8,
+};
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_tm6000_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int err;
+
+	err = snd_pcm_hw_constraint_pow2(runtime, 0,
+					 SNDRV_PCM_HW_PARAM_PERIODS);
+	if (err < 0)
+		goto _error;
+
+	chip->substream = substream;
+
+	runtime->hw = snd_tm6000_digital_hw;
+
+	return 0;
+_error:
+	dprintk(1, "Error opening PCM!\n");
+	return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_tm6000_close(struct snd_pcm_substream *substream)
+{
+	struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+	struct tm6000_core *core = chip->core;
+
+	if (atomic_read(&core->stream_started) > 0) {
+		atomic_set(&core->stream_started, 0);
+		schedule_work(&core->wq_trigger);
+	}
+
+	return 0;
+}
+
+static int tm6000_fillbuf(struct tm6000_core *core, char *buf, int size)
+{
+	struct snd_tm6000_card *chip = core->adev;
+	struct snd_pcm_substream *substream = chip->substream;
+	struct snd_pcm_runtime *runtime;
+	int period_elapsed = 0;
+	unsigned int stride, buf_pos;
+	int length;
+
+	if (atomic_read(&core->stream_started) == 0)
+		return 0;
+
+	if (!size || !substream) {
+		dprintk(1, "substream was NULL\n");
+		return -EINVAL;
+	}
+
+	runtime = substream->runtime;
+	if (!runtime || !runtime->dma_area) {
+		dprintk(1, "runtime was NULL\n");
+		return -EINVAL;
+	}
+
+	buf_pos = chip->buf_pos;
+	stride = runtime->frame_bits >> 3;
+
+	if (stride == 0) {
+		dprintk(1, "stride is zero\n");
+		return -EINVAL;
+	}
+
+	length = size / stride;
+	if (length == 0) {
+		dprintk(1, "%s: length was zero\n", __func__);
+		return -EINVAL;
+	}
+
+	dprintk(1, "Copying %d bytes at %p[%d] - buf size=%d x %d\n", size,
+		runtime->dma_area, buf_pos,
+		(unsigned int)runtime->buffer_size, stride);
+
+	if (buf_pos + length >= runtime->buffer_size) {
+		unsigned int cnt = runtime->buffer_size - buf_pos;
+		memcpy(runtime->dma_area + buf_pos * stride, buf, cnt * stride);
+		memcpy(runtime->dma_area, buf + cnt * stride,
+			length * stride - cnt * stride);
+	} else
+		memcpy(runtime->dma_area + buf_pos * stride, buf,
+			length * stride);
+
+	snd_pcm_stream_lock(substream);
+
+	chip->buf_pos += length;
+	if (chip->buf_pos >= runtime->buffer_size)
+		chip->buf_pos -= runtime->buffer_size;
+
+	chip->period_pos += length;
+	if (chip->period_pos >= runtime->period_size) {
+		chip->period_pos -= runtime->period_size;
+		period_elapsed = 1;
+	}
+
+	snd_pcm_stream_unlock(substream);
+
+	if (period_elapsed)
+		snd_pcm_period_elapsed(substream);
+
+	return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_tm6000_hw_params(struct snd_pcm_substream *substream,
+			      struct snd_pcm_hw_params *hw_params)
+{
+	int size, rc;
+
+	size = params_period_bytes(hw_params) * params_periods(hw_params);
+
+	rc = dsp_buffer_alloc(substream, size);
+	if (rc < 0)
+		return rc;
+
+	return 0;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_tm6000_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+	struct tm6000_core *core = chip->core;
+
+	if (atomic_read(&core->stream_started) > 0) {
+		atomic_set(&core->stream_started, 0);
+		schedule_work(&core->wq_trigger);
+	}
+
+	dsp_buffer_free(substream);
+	return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_tm6000_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+
+	chip->buf_pos = 0;
+	chip->period_pos = 0;
+
+	return 0;
+}
+
+
+/*
+ * trigger callback
+ */
+static void audio_trigger(struct work_struct *work)
+{
+	struct tm6000_core *core = container_of(work, struct tm6000_core,
+						wq_trigger);
+	struct snd_tm6000_card *chip = core->adev;
+
+	if (atomic_read(&core->stream_started)) {
+		dprintk(1, "starting capture");
+		_tm6000_start_audio_dma(chip);
+	} else {
+		dprintk(1, "stopping capture");
+		_tm6000_stop_audio_dma(chip);
+	}
+}
+
+static int snd_tm6000_card_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+	struct tm6000_core *core = chip->core;
+	int err = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		atomic_set(&core->stream_started, 1);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		atomic_set(&core->stream_started, 0);
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+	schedule_work(&core->wq_trigger);
+
+	return err;
+}
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_tm6000_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+
+	return chip->buf_pos;
+}
+
+/*
+ * operators
+ */
+static struct snd_pcm_ops snd_tm6000_pcm_ops = {
+	.open = snd_tm6000_pcm_open,
+	.close = snd_tm6000_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_tm6000_hw_params,
+	.hw_free = snd_tm6000_hw_free,
+	.prepare = snd_tm6000_prepare,
+	.trigger = snd_tm6000_card_trigger,
+	.pointer = snd_tm6000_pointer,
+};
+
+/*
+ * create a PCM device
+ */
+
+/* FIXME: Control interface - How to control volume/mute? */
+
+/****************************************************************************
+			Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * Alsa Constructor - Component probe
+ */
+static int tm6000_audio_init(struct tm6000_core *dev)
+{
+	struct snd_card		*card;
+	struct snd_tm6000_card	*chip;
+	int			rc;
+	static int		devnr;
+	char			component[14];
+	struct snd_pcm		*pcm;
+
+	if (!dev)
+		return 0;
+
+	if (devnr >= SNDRV_CARDS)
+		return -ENODEV;
+
+	if (!enable[devnr])
+		return -ENOENT;
+
+	rc = snd_card_create(index[devnr], "tm6000", THIS_MODULE, 0, &card);
+	if (rc < 0) {
+		snd_printk(KERN_ERR "cannot create card instance %d\n", devnr);
+		return rc;
+	}
+	strcpy(card->driver, "tm6000-alsa");
+	strcpy(card->shortname, "TM5600/60x0");
+	sprintf(card->longname, "TM5600/60x0 Audio at bus %d device %d",
+		dev->udev->bus->busnum, dev->udev->devnum);
+
+	sprintf(component, "USB%04x:%04x",
+		le16_to_cpu(dev->udev->descriptor.idVendor),
+		le16_to_cpu(dev->udev->descriptor.idProduct));
+	snd_component_add(card, component);
+	snd_card_set_dev(card, &dev->udev->dev);
+
+	chip = kzalloc(sizeof(struct snd_tm6000_card), GFP_KERNEL);
+	if (!chip) {
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	chip->core = dev;
+	chip->card = card;
+	dev->adev = chip;
+	spin_lock_init(&chip->reg_lock);
+
+	rc = snd_pcm_new(card, "TM6000 Audio", 0, 0, 1, &pcm);
+	if (rc < 0)
+		goto error_chip;
+
+	pcm->info_flags = 0;
+	pcm->private_data = chip;
+	strcpy(pcm->name, "Trident TM5600/60x0");
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_tm6000_pcm_ops);
+
+	INIT_WORK(&dev->wq_trigger, audio_trigger);
+	rc = snd_card_register(card);
+	if (rc < 0)
+		goto error_chip;
+
+	dprintk(1, "Registered audio driver for %s\n", card->longname);
+
+	return 0;
+
+error_chip:
+	kfree(chip);
+	dev->adev = NULL;
+error:
+	snd_card_free(card);
+	return rc;
+}
+
+static int tm6000_audio_fini(struct tm6000_core *dev)
+{
+	struct snd_tm6000_card	*chip = dev->adev;
+
+	if (!dev)
+		return 0;
+
+	if (!chip)
+		return 0;
+
+	if (!chip->card)
+		return 0;
+
+	snd_card_free(chip->card);
+	chip->card = NULL;
+	kfree(chip);
+	dev->adev = NULL;
+
+	return 0;
+}
+
+static struct tm6000_ops audio_ops = {
+	.type	= TM6000_AUDIO,
+	.name	= "TM6000 Audio Extension",
+	.init	= tm6000_audio_init,
+	.fini	= tm6000_audio_fini,
+	.fillbuf = tm6000_fillbuf,
+};
+
+static int __init tm6000_alsa_register(void)
+{
+	return tm6000_register_extension(&audio_ops);
+}
+
+static void __exit tm6000_alsa_unregister(void)
+{
+	tm6000_unregister_extension(&audio_ops);
+}
+
+module_init(tm6000_alsa_register);
+module_exit(tm6000_alsa_unregister);
diff -druN linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-cards.c linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-cards.c
--- linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-cards.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-cards.c	2012-03-19 21:33:40.000000000 -0400
@@ -0,0 +1,1402 @@
+/*
+ *  tm6000-cards.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+#include <media/tvaudio.h>
+#include <media/i2c-addr.h>
+#include <media/rc-map.h>
+
+#include "tm6000.h"
+#include "tm6000-regs.h"
+#include "tuner-xc2028.h"
+#include "xc5000.h"
+
+#define TM6000_BOARD_UNKNOWN			0
+#define TM5600_BOARD_GENERIC			1
+#define TM6000_BOARD_GENERIC			2
+#define TM6010_BOARD_GENERIC			3
+#define TM5600_BOARD_10MOONS_UT821		4
+#define TM5600_BOARD_10MOONS_UT330		5
+#define TM6000_BOARD_ADSTECH_DUAL_TV		6
+#define TM6000_BOARD_FREECOM_AND_SIMILAR	7
+#define TM6000_BOARD_ADSTECH_MINI_DUAL_TV	8
+#define TM6010_BOARD_HAUPPAUGE_900H		9
+#define TM6010_BOARD_BEHOLD_WANDER		10
+#define TM6010_BOARD_BEHOLD_VOYAGER		11
+#define TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE	12
+#define TM6010_BOARD_TWINHAN_TU501		13
+#define TM6010_BOARD_BEHOLD_WANDER_LITE		14
+#define TM6010_BOARD_BEHOLD_VOYAGER_LITE	15
+#define TM5600_BOARD_TERRATEC_GRABSTER		16
+
+#define is_generic(model) ((model == TM6000_BOARD_UNKNOWN) || \
+			   (model == TM5600_BOARD_GENERIC) || \
+			   (model == TM6000_BOARD_GENERIC) || \
+			   (model == TM6010_BOARD_GENERIC))
+
+#define TM6000_MAXBOARDS        16
+static unsigned int card[]     = {[0 ... (TM6000_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(card,  int, NULL, 0444);
+
+static unsigned long tm6000_devused;
+
+
+struct tm6000_board {
+	char            *name;
+	char		eename[16];		/* EEPROM name */
+	unsigned	eename_size;		/* size of EEPROM name */
+	unsigned	eename_pos;		/* Position where it appears at ROM */
+
+	struct tm6000_capabilities caps;
+
+	enum		tm6000_devtype type;	/* variant of the chipset */
+	int             tuner_type;     /* type of the tuner */
+	int             tuner_addr;     /* tuner address */
+	int             demod_addr;     /* demodulator address */
+
+	struct tm6000_gpio gpio;
+
+	struct tm6000_input	vinput[3];
+	struct tm6000_input	rinput;
+
+	char		*ir_codes;
+};
+
+static struct tm6000_board tm6000_boards[] = {
+	[TM6000_BOARD_UNKNOWN] = {
+		.name         = "Unknown tm6000 video grabber",
+		.caps = {
+			.has_tuner	= 1,
+			.has_eeprom	= 1,
+		},
+		.gpio = {
+			.tuner_reset	= TM6000_GPIO_1,
+		},
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_ADC1,
+			}, {
+			.type	= TM6000_INPUT_COMPOSITE1,
+			.vmux	= TM6000_VMUX_VIDEO_A,
+			.amux	= TM6000_AMUX_ADC2,
+			}, {
+			.type	= TM6000_INPUT_SVIDEO,
+			.vmux	= TM6000_VMUX_VIDEO_AB,
+			.amux	= TM6000_AMUX_ADC2,
+			},
+		},
+	},
+	[TM5600_BOARD_GENERIC] = {
+		.name         = "Generic tm5600 board",
+		.type         = TM5600,
+		.tuner_type   = TUNER_XC2028,
+		.tuner_addr   = 0xc2 >> 1,
+		.caps = {
+			.has_tuner	= 1,
+			.has_eeprom	= 1,
+		},
+		.gpio = {
+			.tuner_reset	= TM6000_GPIO_1,
+		},
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_ADC1,
+			}, {
+			.type	= TM6000_INPUT_COMPOSITE1,
+			.vmux	= TM6000_VMUX_VIDEO_A,
+			.amux	= TM6000_AMUX_ADC2,
+			}, {
+			.type	= TM6000_INPUT_SVIDEO,
+			.vmux	= TM6000_VMUX_VIDEO_AB,
+			.amux	= TM6000_AMUX_ADC2,
+			},
+		},
+	},
+	[TM6000_BOARD_GENERIC] = {
+		.name         = "Generic tm6000 board",
+		.tuner_type   = TUNER_XC2028,
+		.tuner_addr   = 0xc2 >> 1,
+		.caps = {
+			.has_tuner	= 1,
+			.has_eeprom	= 1,
+		},
+		.gpio = {
+			.tuner_reset	= TM6000_GPIO_1,
+		},
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_ADC1,
+			}, {
+			.type	= TM6000_INPUT_COMPOSITE1,
+			.vmux	= TM6000_VMUX_VIDEO_A,
+			.amux	= TM6000_AMUX_ADC2,
+			}, {
+			.type	= TM6000_INPUT_SVIDEO,
+			.vmux	= TM6000_VMUX_VIDEO_AB,
+			.amux	= TM6000_AMUX_ADC2,
+			},
+		},
+	},
+	[TM6010_BOARD_GENERIC] = {
+		.name         = "Generic tm6010 board",
+		.type         = TM6010,
+		.tuner_type   = TUNER_XC2028,
+		.tuner_addr   = 0xc2 >> 1,
+		.demod_addr   = 0x1e >> 1,
+		.caps = {
+			.has_tuner	= 1,
+			.has_dvb	= 1,
+			.has_zl10353	= 1,
+			.has_eeprom	= 1,
+			.has_remote	= 1,
+		},
+		.gpio = {
+			.tuner_reset	= TM6010_GPIO_2,
+			.tuner_on	= TM6010_GPIO_3,
+			.demod_reset	= TM6010_GPIO_1,
+			.demod_on	= TM6010_GPIO_4,
+			.power_led	= TM6010_GPIO_7,
+			.dvb_led	= TM6010_GPIO_5,
+			.ir		= TM6010_GPIO_0,
+		},
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_SIF1,
+			}, {
+			.type	= TM6000_INPUT_COMPOSITE1,
+			.vmux	= TM6000_VMUX_VIDEO_A,
+			.amux	= TM6000_AMUX_ADC2,
+			}, {
+			.type	= TM6000_INPUT_SVIDEO,
+			.vmux	= TM6000_VMUX_VIDEO_AB,
+			.amux	= TM6000_AMUX_ADC2,
+			},
+		},
+	},
+	[TM5600_BOARD_10MOONS_UT821] = {
+		.name         = "10Moons UT 821",
+		.tuner_type   = TUNER_XC2028,
+		.eename       = { '1', '0', 'M', 'O', 'O', 'N', 'S', '5', '6', '0', '0', 0xff, 0x45, 0x5b},
+		.eename_size  = 14,
+		.eename_pos   = 0x14,
+		.type         = TM5600,
+		.tuner_addr   = 0xc2 >> 1,
+		.caps = {
+			.has_tuner    = 1,
+			.has_eeprom   = 1,
+		},
+		.gpio = {
+			.tuner_reset	= TM6000_GPIO_1,
+		},
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_ADC1,
+			}, {
+			.type	= TM6000_INPUT_COMPOSITE1,
+			.vmux	= TM6000_VMUX_VIDEO_A,
+			.amux	= TM6000_AMUX_ADC2,
+			}, {
+			.type	= TM6000_INPUT_SVIDEO,
+			.vmux	= TM6000_VMUX_VIDEO_AB,
+			.amux	= TM6000_AMUX_ADC2,
+			},
+		},
+	},
+	[TM5600_BOARD_10MOONS_UT330] = {
+		.name         = "10Moons UT 330",
+		.tuner_type   = TUNER_PHILIPS_FQ1216AME_MK4,
+		.tuner_addr   = 0xc8 >> 1,
+		.caps = {
+			.has_tuner    = 1,
+			.has_dvb      = 0,
+			.has_zl10353  = 0,
+			.has_eeprom   = 1,
+		},
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_ADC1,
+			}, {
+			.type	= TM6000_INPUT_COMPOSITE1,
+			.vmux	= TM6000_VMUX_VIDEO_A,
+			.amux	= TM6000_AMUX_ADC2,
+			}, {
+			.type	= TM6000_INPUT_SVIDEO,
+			.vmux	= TM6000_VMUX_VIDEO_AB,
+			.amux	= TM6000_AMUX_ADC2,
+			},
+		},
+	},
+	[TM6000_BOARD_ADSTECH_DUAL_TV] = {
+		.name         = "ADSTECH Dual TV USB",
+		.tuner_type   = TUNER_XC2028,
+		.tuner_addr   = 0xc8 >> 1,
+		.caps = {
+			.has_tuner    = 1,
+			.has_tda9874  = 1,
+			.has_dvb      = 1,
+			.has_zl10353  = 1,
+			.has_eeprom   = 1,
+		},
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_ADC1,
+			}, {
+			.type	= TM6000_INPUT_COMPOSITE1,
+			.vmux	= TM6000_VMUX_VIDEO_A,
+			.amux	= TM6000_AMUX_ADC2,
+			}, {
+			.type	= TM6000_INPUT_SVIDEO,
+			.vmux	= TM6000_VMUX_VIDEO_AB,
+			.amux	= TM6000_AMUX_ADC2,
+			},
+		},
+	},
+	[TM6000_BOARD_FREECOM_AND_SIMILAR] = {
+		.name         = "Freecom Hybrid Stick / Moka DVB-T Receiver Dual",
+		.tuner_type   = TUNER_XC2028, /* has a XC3028 */
+		.tuner_addr   = 0xc2 >> 1,
+		.demod_addr   = 0x1e >> 1,
+		.caps = {
+			.has_tuner    = 1,
+			.has_dvb      = 1,
+			.has_zl10353  = 1,
+			.has_eeprom   = 0,
+			.has_remote   = 1,
+		},
+		.gpio = {
+			.tuner_reset	= TM6000_GPIO_4,
+		},
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_ADC1,
+			}, {
+			.type	= TM6000_INPUT_COMPOSITE1,
+			.vmux	= TM6000_VMUX_VIDEO_A,
+			.amux	= TM6000_AMUX_ADC2,
+			}, {
+			.type	= TM6000_INPUT_SVIDEO,
+			.vmux	= TM6000_VMUX_VIDEO_AB,
+			.amux	= TM6000_AMUX_ADC2,
+			},
+		},
+	},
+	[TM6000_BOARD_ADSTECH_MINI_DUAL_TV] = {
+		.name         = "ADSTECH Mini Dual TV USB",
+		.tuner_type   = TUNER_XC2028, /* has a XC3028 */
+		.tuner_addr   = 0xc8 >> 1,
+		.demod_addr   = 0x1e >> 1,
+		.caps = {
+			.has_tuner    = 1,
+			.has_dvb      = 1,
+			.has_zl10353  = 1,
+			.has_eeprom   = 0,
+		},
+		.gpio = {
+			.tuner_reset	= TM6000_GPIO_4,
+		},
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_ADC1,
+			}, {
+			.type	= TM6000_INPUT_COMPOSITE1,
+			.vmux	= TM6000_VMUX_VIDEO_A,
+			.amux	= TM6000_AMUX_ADC2,
+			}, {
+			.type	= TM6000_INPUT_SVIDEO,
+			.vmux	= TM6000_VMUX_VIDEO_AB,
+			.amux	= TM6000_AMUX_ADC2,
+			},
+		},
+	},
+	[TM6010_BOARD_HAUPPAUGE_900H] = {
+		.name         = "Hauppauge WinTV HVR-900H / WinTV USB2-Stick",
+		.eename       = { 'H', 0, 'V', 0, 'R', 0, '9', 0, '0', 0, '0', 0, 'H', 0 },
+		.eename_size  = 14,
+		.eename_pos   = 0x42,
+		.tuner_type   = TUNER_XC2028, /* has a XC3028 */
+		.tuner_addr   = 0xc2 >> 1,
+		.demod_addr   = 0x1e >> 1,
+		.type         = TM6010,
+		.caps = {
+			.has_tuner    = 1,
+			.has_dvb      = 1,
+			.has_zl10353  = 1,
+			.has_eeprom   = 1,
+			.has_remote   = 1,
+		},
+		.gpio = {
+			.tuner_reset	= TM6010_GPIO_2,
+			.tuner_on	= TM6010_GPIO_3,
+			.demod_reset	= TM6010_GPIO_1,
+			.demod_on	= TM6010_GPIO_4,
+			.power_led	= TM6010_GPIO_7,
+			.dvb_led	= TM6010_GPIO_5,
+			.ir		= TM6010_GPIO_0,
+		},
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_SIF1,
+			}, {
+			.type	= TM6000_INPUT_COMPOSITE1,
+			.vmux	= TM6000_VMUX_VIDEO_A,
+			.amux	= TM6000_AMUX_ADC2,
+			}, {
+			.type	= TM6000_INPUT_SVIDEO,
+			.vmux	= TM6000_VMUX_VIDEO_AB,
+			.amux	= TM6000_AMUX_ADC2,
+			},
+		},
+	},
+	[TM6010_BOARD_BEHOLD_WANDER] = {
+		.name         = "Beholder Wander DVB-T/TV/FM USB2.0",
+		.tuner_type   = TUNER_XC5000,
+		.tuner_addr   = 0xc2 >> 1,
+		.demod_addr   = 0x1e >> 1,
+		.type         = TM6010,
+		.caps = {
+			.has_tuner      = 1,
+			.has_dvb        = 1,
+			.has_zl10353    = 1,
+			.has_eeprom     = 1,
+			.has_remote     = 1,
+			.has_radio	= 1,
+		},
+		.gpio = {
+			.tuner_reset	= TM6010_GPIO_0,
+			.demod_reset	= TM6010_GPIO_1,
+			.power_led	= TM6010_GPIO_6,
+		},
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_SIF1,
+			}, {
+			.type	= TM6000_INPUT_COMPOSITE1,
+			.vmux	= TM6000_VMUX_VIDEO_A,
+			.amux	= TM6000_AMUX_ADC2,
+			}, {
+			.type	= TM6000_INPUT_SVIDEO,
+			.vmux	= TM6000_VMUX_VIDEO_AB,
+			.amux	= TM6000_AMUX_ADC2,
+			},
+		},
+		.rinput = {
+			.type	= TM6000_INPUT_RADIO,
+			.amux	= TM6000_AMUX_ADC1,
+		},
+	},
+	[TM6010_BOARD_BEHOLD_VOYAGER] = {
+		.name         = "Beholder Voyager TV/FM USB2.0",
+		.tuner_type   = TUNER_XC5000,
+		.tuner_addr   = 0xc2 >> 1,
+		.type         = TM6010,
+		.caps = {
+			.has_tuner      = 1,
+			.has_dvb        = 0,
+			.has_zl10353    = 0,
+			.has_eeprom     = 1,
+			.has_remote     = 1,
+			.has_radio	= 1,
+		},
+		.gpio = {
+			.tuner_reset	= TM6010_GPIO_0,
+			.power_led	= TM6010_GPIO_6,
+		},
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_SIF1,
+			}, {
+			.type	= TM6000_INPUT_COMPOSITE1,
+			.vmux	= TM6000_VMUX_VIDEO_A,
+			.amux	= TM6000_AMUX_ADC2,
+			}, {
+			.type	= TM6000_INPUT_SVIDEO,
+			.vmux	= TM6000_VMUX_VIDEO_AB,
+			.amux	= TM6000_AMUX_ADC2,
+			},
+		},
+		.rinput = {
+			.type	= TM6000_INPUT_RADIO,
+			.amux	= TM6000_AMUX_ADC1,
+		},
+	},
+	[TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE] = {
+		.name         = "Terratec Cinergy Hybrid XE / Cinergy Hybrid-Stick",
+		.tuner_type   = TUNER_XC2028, /* has a XC3028 */
+		.tuner_addr   = 0xc2 >> 1,
+		.demod_addr   = 0x1e >> 1,
+		.type         = TM6010,
+		.caps = {
+			.has_tuner    = 1,
+			.has_dvb      = 1,
+			.has_zl10353  = 1,
+			.has_eeprom   = 1,
+			.has_remote   = 1,
+			.has_radio    = 1,
+		},
+		.gpio = {
+			.tuner_reset	= TM6010_GPIO_2,
+			.tuner_on	= TM6010_GPIO_3,
+			.demod_reset	= TM6010_GPIO_1,
+			.demod_on	= TM6010_GPIO_4,
+			.power_led	= TM6010_GPIO_7,
+			.dvb_led	= TM6010_GPIO_5,
+			.ir		= TM6010_GPIO_0,
+		},
+		.ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS,
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_SIF1,
+			}, {
+			.type	= TM6000_INPUT_COMPOSITE1,
+			.vmux	= TM6000_VMUX_VIDEO_A,
+			.amux	= TM6000_AMUX_ADC2,
+			}, {
+			.type	= TM6000_INPUT_SVIDEO,
+			.vmux	= TM6000_VMUX_VIDEO_AB,
+			.amux	= TM6000_AMUX_ADC2,
+			},
+		},
+		.rinput = {
+			.type = TM6000_INPUT_RADIO,
+			.amux = TM6000_AMUX_SIF1,
+		},
+	},
+	[TM5600_BOARD_TERRATEC_GRABSTER] = {
+		.name         = "Terratec Grabster AV 150/250 MX",
+		.type         = TM5600,
+		.tuner_type   = TUNER_ABSENT,
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_ADC1,
+			}, {
+			.type	= TM6000_INPUT_COMPOSITE1,
+			.vmux	= TM6000_VMUX_VIDEO_A,
+			.amux	= TM6000_AMUX_ADC2,
+			}, {
+			.type	= TM6000_INPUT_SVIDEO,
+			.vmux	= TM6000_VMUX_VIDEO_AB,
+			.amux	= TM6000_AMUX_ADC2,
+			},
+		},
+	},
+	[TM6010_BOARD_TWINHAN_TU501] = {
+		.name         = "Twinhan TU501(704D1)",
+		.tuner_type   = TUNER_XC2028, /* has a XC3028 */
+		.tuner_addr   = 0xc2 >> 1,
+		.demod_addr   = 0x1e >> 1,
+		.type         = TM6010,
+		.caps = {
+			.has_tuner    = 1,
+			.has_dvb      = 1,
+			.has_zl10353  = 1,
+			.has_eeprom   = 1,
+			.has_remote   = 1,
+		},
+		.gpio = {
+			.tuner_reset	= TM6010_GPIO_2,
+			.tuner_on	= TM6010_GPIO_3,
+			.demod_reset	= TM6010_GPIO_1,
+			.demod_on	= TM6010_GPIO_4,
+			.power_led	= TM6010_GPIO_7,
+			.dvb_led	= TM6010_GPIO_5,
+			.ir		= TM6010_GPIO_0,
+		},
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_SIF1,
+			}, {
+			.type	= TM6000_INPUT_COMPOSITE1,
+			.vmux	= TM6000_VMUX_VIDEO_A,
+			.amux	= TM6000_AMUX_ADC2,
+			}, {
+			.type	= TM6000_INPUT_SVIDEO,
+			.vmux	= TM6000_VMUX_VIDEO_AB,
+			.amux	= TM6000_AMUX_ADC2,
+			},
+		},
+	},
+	[TM6010_BOARD_BEHOLD_WANDER_LITE] = {
+		.name         = "Beholder Wander Lite DVB-T/TV/FM USB2.0",
+		.tuner_type   = TUNER_XC5000,
+		.tuner_addr   = 0xc2 >> 1,
+		.demod_addr   = 0x1e >> 1,
+		.type         = TM6010,
+		.caps = {
+			.has_tuner      = 1,
+			.has_dvb        = 1,
+			.has_zl10353    = 1,
+			.has_eeprom     = 1,
+			.has_remote     = 0,
+			.has_radio	= 1,
+		},
+		.gpio = {
+			.tuner_reset	= TM6010_GPIO_0,
+			.demod_reset	= TM6010_GPIO_1,
+			.power_led	= TM6010_GPIO_6,
+		},
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_SIF1,
+			},
+		},
+		.rinput = {
+			.type	= TM6000_INPUT_RADIO,
+			.amux	= TM6000_AMUX_ADC1,
+		},
+	},
+	[TM6010_BOARD_BEHOLD_VOYAGER_LITE] = {
+		.name         = "Beholder Voyager Lite TV/FM USB2.0",
+		.tuner_type   = TUNER_XC5000,
+		.tuner_addr   = 0xc2 >> 1,
+		.type         = TM6010,
+		.caps = {
+			.has_tuner      = 1,
+			.has_dvb        = 0,
+			.has_zl10353    = 0,
+			.has_eeprom     = 1,
+			.has_remote     = 0,
+			.has_radio	= 1,
+		},
+		.gpio = {
+			.tuner_reset	= TM6010_GPIO_0,
+			.power_led	= TM6010_GPIO_6,
+		},
+		.vinput = { {
+			.type	= TM6000_INPUT_TV,
+			.vmux	= TM6000_VMUX_VIDEO_B,
+			.amux	= TM6000_AMUX_SIF1,
+			},
+		},
+		.rinput = {
+			.type	= TM6000_INPUT_RADIO,
+			.amux	= TM6000_AMUX_ADC1,
+		},
+	},
+};
+
+/* table of devices that work with this driver */
+static struct usb_device_id tm6000_id_table[] = {
+	{ USB_DEVICE(0x6000, 0x0001), .driver_info = TM5600_BOARD_GENERIC },
+	{ USB_DEVICE(0x6000, 0x0002), .driver_info = TM6010_BOARD_GENERIC },
+	{ USB_DEVICE(0x06e1, 0xf332), .driver_info = TM6000_BOARD_ADSTECH_DUAL_TV },
+	{ USB_DEVICE(0x14aa, 0x0620), .driver_info = TM6000_BOARD_FREECOM_AND_SIMILAR },
+	{ USB_DEVICE(0x06e1, 0xb339), .driver_info = TM6000_BOARD_ADSTECH_MINI_DUAL_TV },
+	{ USB_DEVICE(0x2040, 0x6600), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
+	{ USB_DEVICE(0x2040, 0x6601), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
+	{ USB_DEVICE(0x2040, 0x6610), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
+	{ USB_DEVICE(0x2040, 0x6611), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
+	{ USB_DEVICE(0x6000, 0xdec0), .driver_info = TM6010_BOARD_BEHOLD_WANDER },
+	{ USB_DEVICE(0x6000, 0xdec1), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER },
+	{ USB_DEVICE(0x0ccd, 0x0086), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE },
+	{ USB_DEVICE(0x0ccd, 0x00A5), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE },
+	{ USB_DEVICE(0x0ccd, 0x0079), .driver_info = TM5600_BOARD_TERRATEC_GRABSTER },
+	{ USB_DEVICE(0x13d3, 0x3240), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
+	{ USB_DEVICE(0x13d3, 0x3241), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
+	{ USB_DEVICE(0x13d3, 0x3243), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
+	{ USB_DEVICE(0x13d3, 0x3264), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
+	{ USB_DEVICE(0x6000, 0xdec2), .driver_info = TM6010_BOARD_BEHOLD_WANDER_LITE },
+	{ USB_DEVICE(0x6000, 0xdec3), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER_LITE },
+	{ }
+};
+
+/* Control power led for show some activity */
+void tm6000_flash_led(struct tm6000_core *dev, u8 state)
+{
+	/* Power LED unconfigured */
+	if (!dev->gpio.power_led)
+		return;
+
+	/* ON Power LED */
+	if (state) {
+		switch (dev->model) {
+		case TM6010_BOARD_HAUPPAUGE_900H:
+		case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+		case TM6010_BOARD_TWINHAN_TU501:
+			tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+				dev->gpio.power_led, 0x00);
+			break;
+		case TM6010_BOARD_BEHOLD_WANDER:
+		case TM6010_BOARD_BEHOLD_VOYAGER:
+		case TM6010_BOARD_BEHOLD_WANDER_LITE:
+		case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
+			tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+				dev->gpio.power_led, 0x01);
+			break;
+		}
+	}
+	/* OFF Power LED */
+	else {
+		switch (dev->model) {
+		case TM6010_BOARD_HAUPPAUGE_900H:
+		case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+		case TM6010_BOARD_TWINHAN_TU501:
+			tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+				dev->gpio.power_led, 0x01);
+			break;
+		case TM6010_BOARD_BEHOLD_WANDER:
+		case TM6010_BOARD_BEHOLD_VOYAGER:
+		case TM6010_BOARD_BEHOLD_WANDER_LITE:
+		case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
+			tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+				dev->gpio.power_led, 0x00);
+			break;
+		}
+	}
+}
+
+/* Tuner callback to provide the proper gpio changes needed for xc5000 */
+int tm6000_xc5000_callback(void *ptr, int component, int command, int arg)
+{
+	int rc = 0;
+	struct tm6000_core *dev = ptr;
+
+	if (dev->tuner_type != TUNER_XC5000)
+		return 0;
+
+	switch (command) {
+	case XC5000_TUNER_RESET:
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+			       dev->gpio.tuner_reset, 0x01);
+		msleep(15);
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+			       dev->gpio.tuner_reset, 0x00);
+		msleep(15);
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+			       dev->gpio.tuner_reset, 0x01);
+		break;
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(tm6000_xc5000_callback);
+
+/* Tuner callback to provide the proper gpio changes needed for xc2028 */
+
+int tm6000_tuner_callback(void *ptr, int component, int command, int arg)
+{
+	int rc = 0;
+	struct tm6000_core *dev = ptr;
+
+	if (dev->tuner_type != TUNER_XC2028)
+		return 0;
+
+	switch (command) {
+	case XC2028_RESET_CLK:
+		tm6000_ir_wait(dev, 0);
+
+		tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT,
+					0x02, arg);
+		msleep(10);
+		rc = tm6000_i2c_reset(dev, 10);
+		break;
+	case XC2028_TUNER_RESET:
+		/* Reset codes during load firmware */
+		switch (arg) {
+		case 0:
+			/* newer tuner can faster reset */
+			switch (dev->model) {
+			case TM5600_BOARD_10MOONS_UT821:
+				tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+					       dev->gpio.tuner_reset, 0x01);
+				tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+					       0x300, 0x01);
+				msleep(10);
+				tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+					       dev->gpio.tuner_reset, 0x00);
+				tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+					       0x300, 0x00);
+				msleep(10);
+				tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+					       dev->gpio.tuner_reset, 0x01);
+				tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+					       0x300, 0x01);
+				break;
+			case TM6010_BOARD_HAUPPAUGE_900H:
+			case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+			case TM6010_BOARD_TWINHAN_TU501:
+				tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+					       dev->gpio.tuner_reset, 0x01);
+				msleep(60);
+				tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+					       dev->gpio.tuner_reset, 0x00);
+				msleep(75);
+				tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+					       dev->gpio.tuner_reset, 0x01);
+				msleep(60);
+				break;
+			default:
+				tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+					       dev->gpio.tuner_reset, 0x00);
+				msleep(130);
+				tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+					       dev->gpio.tuner_reset, 0x01);
+				msleep(130);
+				break;
+			}
+
+			tm6000_ir_wait(dev, 1);
+			break;
+		case 1:
+			tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT,
+						0x02, 0x01);
+			msleep(10);
+			break;
+		case 2:
+			rc = tm6000_i2c_reset(dev, 100);
+			break;
+		}
+		break;
+	case XC2028_I2C_FLUSH:
+		tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
+		tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
+		break;
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(tm6000_tuner_callback);
+
+int tm6000_cards_setup(struct tm6000_core *dev)
+{
+	/*
+	 * Board-specific initialization sequence. Handles all GPIO
+	 * initialization sequences that are board-specific.
+	 * Up to now, all found devices use GPIO1 and GPIO4 at the same way.
+	 * Probably, they're all based on some reference device. Due to that,
+	 * there's a common routine at the end to handle those GPIO's. Devices
+	 * that use different pinups or init sequences can just return at
+	 * the board-specific session.
+	 */
+	switch (dev->model) {
+	case TM6010_BOARD_HAUPPAUGE_900H:
+	case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+	case TM6010_BOARD_TWINHAN_TU501:
+	case TM6010_BOARD_GENERIC:
+		/* Turn xceive 3028 on */
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.tuner_on, 0x01);
+		msleep(15);
+		/* Turn zarlink zl10353 on */
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x00);
+		msleep(15);
+		/* Reset zarlink zl10353 */
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x00);
+		msleep(50);
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x01);
+		msleep(15);
+		/* Turn zarlink zl10353 off */
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x01);
+		msleep(15);
+		/* ir ? */
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.ir, 0x01);
+		msleep(15);
+		/* Power led on (blue) */
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x00);
+		msleep(15);
+		/* DVB led off (orange) */
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.dvb_led, 0x01);
+		msleep(15);
+		/* Turn zarlink zl10353 on */
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x00);
+		msleep(15);
+		break;
+	case TM6010_BOARD_BEHOLD_WANDER:
+	case TM6010_BOARD_BEHOLD_WANDER_LITE:
+		/* Power led on (blue) */
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x01);
+		msleep(15);
+		/* Reset zarlink zl10353 */
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x00);
+		msleep(50);
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x01);
+		msleep(15);
+		break;
+	case TM6010_BOARD_BEHOLD_VOYAGER:
+	case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
+		/* Power led on (blue) */
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x01);
+		msleep(15);
+		break;
+	default:
+		break;
+	}
+
+	/*
+	 * Default initialization. Most of the devices seem to use GPIO1
+	 * and GPIO4.on the same way, so, this handles the common sequence
+	 * used by most devices.
+	 * If a device uses a different sequence or different GPIO pins for
+	 * reset, just add the code at the board-specific part
+	 */
+
+	if (dev->gpio.tuner_reset) {
+		int rc;
+		int i;
+
+		for (i = 0; i < 2; i++) {
+			rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+						dev->gpio.tuner_reset, 0x00);
+			if (rc < 0) {
+				printk(KERN_ERR "Error %i doing tuner reset\n", rc);
+				return rc;
+			}
+
+			msleep(10); /* Just to be conservative */
+			rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+						dev->gpio.tuner_reset, 0x01);
+			if (rc < 0) {
+				printk(KERN_ERR "Error %i doing tuner reset\n", rc);
+				return rc;
+			}
+		}
+	} else {
+		printk(KERN_ERR "Tuner reset is not configured\n");
+		return -1;
+	}
+
+	msleep(50);
+
+	return 0;
+};
+
+static void tm6000_config_tuner(struct tm6000_core *dev)
+{
+	struct tuner_setup tun_setup;
+
+	/* Load tuner module */
+	v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+		"tuner", dev->tuner_addr, NULL);
+
+	memset(&tun_setup, 0, sizeof(tun_setup));
+	tun_setup.type = dev->tuner_type;
+	tun_setup.addr = dev->tuner_addr;
+
+	tun_setup.mode_mask = 0;
+	if (dev->caps.has_tuner)
+		tun_setup.mode_mask |= (T_ANALOG_TV | T_RADIO);
+
+	switch (dev->tuner_type) {
+	case TUNER_XC2028:
+		tun_setup.tuner_callback = tm6000_tuner_callback;
+		break;
+	case TUNER_XC5000:
+		tun_setup.tuner_callback = tm6000_xc5000_callback;
+		break;
+	}
+
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
+
+	switch (dev->tuner_type) {
+	case TUNER_XC2028: {
+		struct v4l2_priv_tun_config xc2028_cfg;
+		struct xc2028_ctrl ctl;
+
+		memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
+		memset(&ctl, 0, sizeof(ctl));
+
+		ctl.demod = XC3028_FE_ZARLINK456;
+
+		xc2028_cfg.tuner = TUNER_XC2028;
+		xc2028_cfg.priv  = &ctl;
+
+		switch (dev->model) {
+		case TM6010_BOARD_HAUPPAUGE_900H:
+		case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+		case TM6010_BOARD_TWINHAN_TU501:
+			ctl.fname = "/*(DEBLOBBED)*/";
+			break;
+		default:
+			if (dev->dev_type == TM6010)
+				ctl.fname = "/*(DEBLOBBED)*/";
+			else
+				ctl.fname = "/*(DEBLOBBED)*/";
+		}
+
+		printk(KERN_INFO "Setting firmware parameters for xc2028\n");
+		v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config,
+				     &xc2028_cfg);
+
+		}
+		break;
+	case TUNER_XC5000:
+		{
+		struct v4l2_priv_tun_config  xc5000_cfg;
+		struct xc5000_config ctl = {
+			.i2c_address = dev->tuner_addr,
+			.if_khz      = 4570,
+			.radio_input = XC5000_RADIO_FM1_MONO,
+			};
+
+		xc5000_cfg.tuner = TUNER_XC5000;
+		xc5000_cfg.priv  = &ctl;
+
+		v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config,
+				     &xc5000_cfg);
+		}
+		break;
+	default:
+		printk(KERN_INFO "Unknown tuner type. Tuner is not configured.\n");
+		break;
+	}
+}
+
+static int fill_board_specific_data(struct tm6000_core *dev)
+{
+	int rc;
+
+	dev->dev_type   = tm6000_boards[dev->model].type;
+	dev->tuner_type = tm6000_boards[dev->model].tuner_type;
+	dev->tuner_addr = tm6000_boards[dev->model].tuner_addr;
+
+	dev->gpio = tm6000_boards[dev->model].gpio;
+
+	dev->ir_codes = tm6000_boards[dev->model].ir_codes;
+
+	dev->demod_addr = tm6000_boards[dev->model].demod_addr;
+
+	dev->caps = tm6000_boards[dev->model].caps;
+
+	dev->vinput[0] = tm6000_boards[dev->model].vinput[0];
+	dev->vinput[1] = tm6000_boards[dev->model].vinput[1];
+	dev->vinput[2] = tm6000_boards[dev->model].vinput[2];
+	dev->rinput = tm6000_boards[dev->model].rinput;
+
+	/* setup per-model quirks */
+	switch (dev->model) {
+	case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+		dev->quirks |= TM6000_QUIRK_NO_USB_DELAY;
+		break;
+
+	default:
+		break;
+	}
+
+	/* initialize hardware */
+	rc = tm6000_init(dev);
+	if (rc < 0)
+		return rc;
+
+	return v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev);
+}
+
+
+static void use_alternative_detection_method(struct tm6000_core *dev)
+{
+	int i, model = -1;
+
+	if (!dev->eedata_size)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(tm6000_boards); i++) {
+		if (!tm6000_boards[i].eename_size)
+			continue;
+		if (dev->eedata_size < tm6000_boards[i].eename_pos +
+				       tm6000_boards[i].eename_size)
+			continue;
+
+		if (!memcmp(&dev->eedata[tm6000_boards[i].eename_pos],
+			    tm6000_boards[i].eename,
+			    tm6000_boards[i].eename_size)) {
+			model = i;
+			break;
+		}
+	}
+	if (model < 0) {
+		printk(KERN_INFO "Device has eeprom but is currently unknown\n");
+		return;
+	}
+
+	dev->model = model;
+
+	printk(KERN_INFO "Device identified via eeprom as %s (type = %d)\n",
+	       tm6000_boards[model].name, model);
+}
+
+static int tm6000_init_dev(struct tm6000_core *dev)
+{
+	struct v4l2_frequency f;
+	int rc = 0;
+
+	mutex_init(&dev->lock);
+	mutex_lock(&dev->lock);
+
+	if (!is_generic(dev->model)) {
+		rc = fill_board_specific_data(dev);
+		if (rc < 0)
+			goto err;
+
+		/* register i2c bus */
+		rc = tm6000_i2c_register(dev);
+		if (rc < 0)
+			goto err;
+	} else {
+		/* register i2c bus */
+		rc = tm6000_i2c_register(dev);
+		if (rc < 0)
+			goto err;
+
+		use_alternative_detection_method(dev);
+
+		rc = fill_board_specific_data(dev);
+		if (rc < 0)
+			goto err;
+	}
+
+	/* Default values for STD and resolutions */
+	dev->width = 720;
+	dev->height = 480;
+	dev->norm = V4L2_STD_PAL_M;
+
+	/* Configure tuner */
+	tm6000_config_tuner(dev);
+
+	/* Set video standard */
+	v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
+
+	/* Set tuner frequency - also loads firmware on xc2028/xc3028 */
+	f.tuner = 0;
+	f.type = V4L2_TUNER_ANALOG_TV;
+	f.frequency = 3092;	/* 193.25 MHz */
+	dev->freq = f.frequency;
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
+
+	if (dev->caps.has_tda9874)
+		v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+			"tvaudio", I2C_ADDR_TDA9874, NULL);
+
+	/* register and initialize V4L2 */
+	rc = tm6000_v4l2_register(dev);
+	if (rc < 0)
+		goto err;
+
+	tm6000_add_into_devlist(dev);
+	tm6000_init_extension(dev);
+
+	tm6000_ir_init(dev);
+
+	mutex_unlock(&dev->lock);
+	return 0;
+
+err:
+	mutex_unlock(&dev->lock);
+	return rc;
+}
+
+/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
+#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
+
+static void get_max_endpoint(struct usb_device *udev,
+			     struct usb_host_interface *alt,
+			     char *msgtype,
+			     struct usb_host_endpoint *curr_e,
+			     struct tm6000_endpoint *tm_ep)
+{
+	u16 tmp = le16_to_cpu(curr_e->desc.wMaxPacketSize);
+	unsigned int size = tmp & 0x7ff;
+
+	if (udev->speed == USB_SPEED_HIGH)
+		size = size * hb_mult(tmp);
+
+	if (size > tm_ep->maxsize) {
+		tm_ep->endp = curr_e;
+		tm_ep->maxsize = size;
+		tm_ep->bInterfaceNumber = alt->desc.bInterfaceNumber;
+		tm_ep->bAlternateSetting = alt->desc.bAlternateSetting;
+
+		printk(KERN_INFO "tm6000: %s endpoint: 0x%02x (max size=%u bytes)\n",
+					msgtype, curr_e->desc.bEndpointAddress,
+					size);
+	}
+}
+
+/*
+ * tm6000_usb_probe()
+ * checks for supported devices
+ */
+static int tm6000_usb_probe(struct usb_interface *interface,
+			    const struct usb_device_id *id)
+{
+	struct usb_device *usbdev;
+	struct tm6000_core *dev = NULL;
+	int i, rc = 0;
+	int nr = 0;
+	char *speed;
+
+	usbdev = usb_get_dev(interface_to_usbdev(interface));
+
+	/* Selects the proper interface */
+	rc = usb_set_interface(usbdev, 0, 1);
+	if (rc < 0)
+		goto err;
+
+	/* Check to see next free device and mark as used */
+	nr = find_first_zero_bit(&tm6000_devused, TM6000_MAXBOARDS);
+	if (nr >= TM6000_MAXBOARDS) {
+		printk(KERN_ERR "tm6000: Supports only %i tm60xx boards.\n", TM6000_MAXBOARDS);
+		usb_put_dev(usbdev);
+		return -ENOMEM;
+	}
+
+	/* Create and initialize dev struct */
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		printk(KERN_ERR "tm6000" ": out of memory!\n");
+		usb_put_dev(usbdev);
+		return -ENOMEM;
+	}
+	spin_lock_init(&dev->slock);
+	mutex_init(&dev->usb_lock);
+
+	/* Increment usage count */
+	set_bit(nr, &tm6000_devused);
+	snprintf(dev->name, 29, "tm6000 #%d", nr);
+
+	dev->model = id->driver_info;
+	if (card[nr] < ARRAY_SIZE(tm6000_boards))
+		dev->model = card[nr];
+
+	dev->udev = usbdev;
+	dev->devno = nr;
+
+	switch (usbdev->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";
+	}
+
+	/* Get endpoints */
+	for (i = 0; i < interface->num_altsetting; i++) {
+		int ep;
+
+		for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) {
+			struct usb_host_endpoint	*e;
+			int dir_out;
+
+			e = &interface->altsetting[i].endpoint[ep];
+
+			dir_out = ((e->desc.bEndpointAddress &
+					USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
+
+			printk(KERN_INFO "tm6000: alt %d, interface %i, class %i\n",
+			       i,
+			       interface->altsetting[i].desc.bInterfaceNumber,
+			       interface->altsetting[i].desc.bInterfaceClass);
+
+			switch (e->desc.bmAttributes) {
+			case USB_ENDPOINT_XFER_BULK:
+				if (!dir_out) {
+					get_max_endpoint(usbdev,
+							 &interface->altsetting[i],
+							 "Bulk IN", e,
+							 &dev->bulk_in);
+				} else {
+					get_max_endpoint(usbdev,
+							 &interface->altsetting[i],
+							 "Bulk OUT", e,
+							 &dev->bulk_out);
+				}
+				break;
+			case USB_ENDPOINT_XFER_ISOC:
+				if (!dir_out) {
+					get_max_endpoint(usbdev,
+							 &interface->altsetting[i],
+							 "ISOC IN", e,
+							 &dev->isoc_in);
+				} else {
+					get_max_endpoint(usbdev,
+							 &interface->altsetting[i],
+							 "ISOC OUT", e,
+							 &dev->isoc_out);
+				}
+				break;
+			case USB_ENDPOINT_XFER_INT:
+				if (!dir_out) {
+					get_max_endpoint(usbdev,
+							&interface->altsetting[i],
+							"INT IN", e,
+							&dev->int_in);
+				} else {
+					get_max_endpoint(usbdev,
+							&interface->altsetting[i],
+							"INT OUT", e,
+							&dev->int_out);
+				}
+				break;
+			}
+		}
+	}
+
+
+	printk(KERN_INFO "tm6000: New video device @ %s Mbps (%04x:%04x, ifnum %d)\n",
+		speed,
+		le16_to_cpu(dev->udev->descriptor.idVendor),
+		le16_to_cpu(dev->udev->descriptor.idProduct),
+		interface->altsetting->desc.bInterfaceNumber);
+
+/* check if the the device has the iso in endpoint at the correct place */
+	if (!dev->isoc_in.endp) {
+		printk(KERN_ERR "tm6000: probing error: no IN ISOC endpoint!\n");
+		rc = -ENODEV;
+
+		goto err;
+	}
+
+	/* save our data pointer in this interface device */
+	usb_set_intfdata(interface, dev);
+
+	printk(KERN_INFO "tm6000: Found %s\n", tm6000_boards[dev->model].name);
+
+	rc = tm6000_init_dev(dev);
+	if (rc < 0)
+		goto err;
+
+	return 0;
+
+err:
+	printk(KERN_ERR "tm6000: Error %d while registering\n", rc);
+
+	clear_bit(nr, &tm6000_devused);
+	usb_put_dev(usbdev);
+
+	kfree(dev);
+	return rc;
+}
+
+/*
+ * tm6000_usb_disconnect()
+ * called when the device gets diconencted
+ * video device will be unregistered on v4l2_close in case it is still open
+ */
+static void tm6000_usb_disconnect(struct usb_interface *interface)
+{
+	struct tm6000_core *dev = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+
+	if (!dev)
+		return;
+
+	printk(KERN_INFO "tm6000: disconnecting %s\n", dev->name);
+
+	tm6000_ir_fini(dev);
+
+	if (dev->gpio.power_led) {
+		switch (dev->model) {
+		case TM6010_BOARD_HAUPPAUGE_900H:
+		case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+		case TM6010_BOARD_TWINHAN_TU501:
+			/* Power led off */
+			tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+				dev->gpio.power_led, 0x01);
+			msleep(15);
+			break;
+		case TM6010_BOARD_BEHOLD_WANDER:
+		case TM6010_BOARD_BEHOLD_VOYAGER:
+		case TM6010_BOARD_BEHOLD_WANDER_LITE:
+		case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
+			/* Power led off */
+			tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+				dev->gpio.power_led, 0x00);
+			msleep(15);
+			break;
+		}
+	}
+	tm6000_v4l2_unregister(dev);
+
+	tm6000_i2c_unregister(dev);
+
+	v4l2_device_unregister(&dev->v4l2_dev);
+
+	dev->state |= DEV_DISCONNECTED;
+
+	usb_put_dev(dev->udev);
+
+	tm6000_close_extension(dev);
+	tm6000_remove_from_devlist(dev);
+
+	clear_bit(dev->devno, &tm6000_devused);
+	kfree(dev);
+}
+
+static struct usb_driver tm6000_usb_driver = {
+		.name = "tm6000",
+		.probe = tm6000_usb_probe,
+		.disconnect = tm6000_usb_disconnect,
+		.id_table = tm6000_id_table,
+};
+
+static int __init tm6000_module_init(void)
+{
+	int result;
+
+	printk(KERN_INFO "tm6000" " v4l2 driver version %d.%d.%d loaded\n",
+	       (TM6000_VERSION  >> 16) & 0xff,
+	       (TM6000_VERSION  >> 8) & 0xff, TM6000_VERSION  & 0xff);
+
+	/* register this driver with the USB subsystem */
+	result = usb_register(&tm6000_usb_driver);
+	if (result)
+		printk(KERN_ERR "tm6000"
+			   " usb_register failed. Error number %d.\n", result);
+
+	return result;
+}
+
+static void __exit tm6000_module_exit(void)
+{
+	/* deregister at USB subsystem */
+	usb_deregister(&tm6000_usb_driver);
+}
+
+module_init(tm6000_module_init);
+module_exit(tm6000_module_exit);
+
+MODULE_DESCRIPTION("Trident TVMaster TM5600/TM6000/TM6010 USB2 adapter");
+MODULE_AUTHOR("Mauro Carvalho Chehab");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-core.c linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-core.c
--- linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,965 @@
+/*
+ *  tm6000-core.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ *      - DVB-T support
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation 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.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/kernel.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include "tm6000.h"
+#include "tm6000-regs.h"
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+
+#define USB_TIMEOUT	(5 * HZ) /* ms */
+
+int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req,
+			  u16 value, u16 index, u8 *buf, u16 len)
+{
+	int          ret, i;
+	unsigned int pipe;
+	u8	     *data = NULL;
+
+	mutex_lock(&dev->usb_lock);
+
+	if (len)
+		data = kzalloc(len, GFP_KERNEL);
+
+	if (req_type & USB_DIR_IN)
+		pipe = usb_rcvctrlpipe(dev->udev, 0);
+	else {
+		pipe = usb_sndctrlpipe(dev->udev, 0);
+		memcpy(data, buf, len);
+	}
+
+	if (tm6000_debug & V4L2_DEBUG_I2C) {
+		printk(KERN_DEBUG "(dev %p, pipe %08x): ", dev->udev, pipe);
+
+		printk(KERN_CONT "%s: %02x %02x %02x %02x %02x %02x %02x %02x ",
+			(req_type & USB_DIR_IN) ? " IN" : "OUT",
+			req_type, req, value&0xff, value>>8, index&0xff,
+			index>>8, len&0xff, len>>8);
+
+		if (!(req_type & USB_DIR_IN)) {
+			printk(KERN_CONT ">>> ");
+			for (i = 0; i < len; i++)
+				printk(KERN_CONT " %02x", buf[i]);
+			printk(KERN_CONT "\n");
+		}
+	}
+
+	ret = usb_control_msg(dev->udev, pipe, req, req_type, value, index,
+			      data, len, USB_TIMEOUT);
+
+	if (req_type &  USB_DIR_IN)
+		memcpy(buf, data, len);
+
+	if (tm6000_debug & V4L2_DEBUG_I2C) {
+		if (ret < 0) {
+			if (req_type &  USB_DIR_IN)
+				printk(KERN_DEBUG "<<< (len=%d)\n", len);
+
+			printk(KERN_CONT "%s: Error #%d\n", __func__, ret);
+		} else if (req_type &  USB_DIR_IN) {
+			printk(KERN_CONT "<<< ");
+			for (i = 0; i < len; i++)
+				printk(KERN_CONT " %02x", buf[i]);
+			printk(KERN_CONT "\n");
+		}
+	}
+
+	kfree(data);
+	msleep(5);
+
+	mutex_unlock(&dev->usb_lock);
+	return ret;
+}
+
+int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index)
+{
+	return
+		tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
+				      req, value, index, NULL, 0);
+}
+EXPORT_SYMBOL_GPL(tm6000_set_reg);
+
+int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index)
+{
+	int rc;
+	u8 buf[1];
+
+	rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
+					value, index, buf, 1);
+
+	if (rc < 0)
+		return rc;
+
+	return *buf;
+}
+EXPORT_SYMBOL_GPL(tm6000_get_reg);
+
+int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value,
+						u16 index, u16 mask)
+{
+	int rc;
+	u8 buf[1];
+	u8 new_index;
+
+	rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
+					value, index, buf, 1);
+
+	if (rc < 0)
+		return rc;
+
+	new_index = (buf[0] & ~mask) | (index & mask);
+
+	if (new_index == index)
+		return 0;
+
+	return tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
+				      req, value, new_index, NULL, 0);
+}
+EXPORT_SYMBOL_GPL(tm6000_set_reg_mask);
+
+int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index)
+{
+	int rc;
+	u8 buf[2];
+
+	rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
+					value, index, buf, 2);
+
+	if (rc < 0)
+		return rc;
+
+	return buf[1]|buf[0]<<8;
+}
+
+int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index)
+{
+	int rc;
+	u8 buf[4];
+
+	rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
+					value, index, buf, 4);
+
+	if (rc < 0)
+		return rc;
+
+	return buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24;
+}
+
+int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep)
+{
+	int rc;
+
+	rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0);
+	if (rc < 0)
+		return rc;
+
+	msleep(tsleep);
+
+	rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
+	msleep(tsleep);
+
+	return rc;
+}
+
+void tm6000_set_fourcc_format(struct tm6000_core *dev)
+{
+	if (dev->dev_type == TM6010) {
+		int val;
+
+		val = tm6000_get_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, 0) & 0xfc;
+		if (dev->fourcc == V4L2_PIX_FMT_UYVY)
+			tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val);
+		else
+			tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val | 1);
+	} else {
+		if (dev->fourcc == V4L2_PIX_FMT_UYVY)
+			tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0);
+		else
+			tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0x90);
+	}
+}
+
+static void tm6000_set_vbi(struct tm6000_core *dev)
+{
+	/*
+	 * FIXME:
+	 * VBI lines and start/end are different between 60Hz and 50Hz
+	 * So, it is very likely that we need to change the config to
+	 * something that takes it into account, doing something different
+	 * if (dev->norm & V4L2_STD_525_60)
+	 */
+
+	if (dev->dev_type == TM6010) {
+		tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
+		tm6000_set_reg(dev, TM6010_REQ07_R41_TELETEXT_VBI_CODE1, 0x27);
+		tm6000_set_reg(dev, TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55);
+		tm6000_set_reg(dev, TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7, 0x66);
+		tm6000_set_reg(dev, TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8, 0x66);
+		tm6000_set_reg(dev, TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9, 0x66);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10, 0x66);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11, 0x66);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12, 0x66);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13, 0x66);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14, 0x66);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15, 0x66);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16, 0x66);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17, 0x66);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18, 0x66);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19, 0x66);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20, 0x66);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x66);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22, 0x66);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23, 0x00);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES, 0x00);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN, 0x00);
+		tm6000_set_reg(dev,
+			TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02);
+		tm6000_set_reg(dev, TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35);
+		tm6000_set_reg(dev, TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0);
+		tm6000_set_reg(dev, TM6010_REQ07_R5A_VBI_TELETEXT_DTO1, 0x11);
+		tm6000_set_reg(dev, TM6010_REQ07_R5B_VBI_TELETEXT_DTO0, 0x4c);
+		tm6000_set_reg(dev, TM6010_REQ07_R40_TELETEXT_VBI_CODE0, 0x01);
+		tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00);
+	}
+}
+
+int tm6000_init_analog_mode(struct tm6000_core *dev)
+{
+	struct v4l2_frequency f;
+
+	if (dev->dev_type == TM6010) {
+		u8 active = TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE;
+
+		if (!dev->radio)
+			active |= TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE;
+
+		/* Enable video and audio */
+		tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF,
+							active, 0x60);
+		/* Disable TS input */
+		tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE,
+							0x00, 0x40);
+	} else {
+		/* Enables soft reset */
+		tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
+
+		if (dev->scaler)
+			/* Disable Hfilter and Enable TS Drop err */
+			tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x20);
+		else	/* Enable Hfilter and disable TS Drop err */
+			tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x80);
+
+		tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x88);
+		tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x23);
+		tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xc0);
+		tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xd8);
+		tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x06);
+		tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f);
+
+		/* AP Software reset */
+		tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08);
+		tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00);
+
+		tm6000_set_fourcc_format(dev);
+
+		/* Disables soft reset */
+		tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00);
+	}
+	msleep(20);
+
+	/* Tuner firmware can now be loaded */
+
+	/*
+	 * FIXME: This is a hack! xc3028 "sleeps" when no channel is detected
+	 * for more than a few seconds. Not sure why, as this behavior does
+	 * not happen on other devices with xc3028. So, I suspect that it
+	 * is yet another bug at tm6000. After start sleeping, decoding
+	 * doesn't start automatically. Instead, it requires some
+	 * I2C commands to wake it up. As we want to have image at the
+	 * beginning, we needed to add this hack. The better would be to
+	 * discover some way to make tm6000 to wake up without this hack.
+	 */
+	f.frequency = dev->freq;
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
+
+	msleep(100);
+	tm6000_set_standard(dev);
+	tm6000_set_vbi(dev);
+	tm6000_set_audio_bitrate(dev, 48000);
+
+	/* switch dvb led off */
+	if (dev->gpio.dvb_led) {
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+			dev->gpio.dvb_led, 0x01);
+	}
+
+	return 0;
+}
+
+int tm6000_init_digital_mode(struct tm6000_core *dev)
+{
+	if (dev->dev_type == TM6010) {
+		/* Disable video and audio */
+		tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF,
+				0x00, 0x60);
+		/* Enable TS input */
+		tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE,
+				0x40, 0x40);
+		/* all power down, but not the digital data port */
+		tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0x28);
+		tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xfc);
+		tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0xff);
+	} else  {
+		tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08);
+		tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00);
+		tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
+		tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x08);
+		tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c);
+		tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff);
+		tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0xd8);
+		tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x40);
+		tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0);
+		tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x09);
+		tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x37);
+		tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xd8);
+		tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xc0);
+		tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x60);
+
+		tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c);
+		tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff);
+		tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0x08);
+		msleep(50);
+
+		tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
+		msleep(50);
+		tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x01);
+		msleep(50);
+		tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
+		msleep(100);
+	}
+
+	/* switch dvb led on */
+	if (dev->gpio.dvb_led) {
+		tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+			dev->gpio.dvb_led, 0x00);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(tm6000_init_digital_mode);
+
+struct reg_init {
+	u8 req;
+	u8 reg;
+	u8 val;
+};
+
+/* The meaning of those initializations are unknown */
+static struct reg_init tm6000_init_tab[] = {
+	/* REG  VALUE */
+	{ TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f },
+	{ TM6010_REQ07_RFF_SOFT_RESET, 0x08 },
+	{ TM6010_REQ07_RFF_SOFT_RESET, 0x00 },
+	{ TM6010_REQ07_RD5_POWERSAVE, 0x4f },
+	{ TM6000_REQ07_RDA_CLK_SEL, 0x23 },
+	{ TM6000_REQ07_RDB_OUT_SEL, 0x08 },
+	{ TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x00 },
+	{ TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10 },
+	{ TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00 },
+	{ TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00 },
+	{ TM6000_REQ07_REB_VADC_AADC_MODE, 0x64 },	/* 48000 bits/sample, external input */
+	{ TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL, 0xc2 },
+
+	{ TM6010_REQ07_R3F_RESET, 0x01 },		/* Start of soft reset */
+	{ TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
+	{ TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 },
+	{ TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+	{ TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
+	{ TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 },
+	{ TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 },
+	{ TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 },
+	{ TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 },
+	{ TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 },
+	{ TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a },
+	{ TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 },
+	{ TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 },
+	{ TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b },
+	{ TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 },
+	{ TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f },
+	{ TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd },
+	{ TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+	{ TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
+	{ TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
+	{ TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
+	{ TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+	{ TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+	{ TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+	{ TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+	{ TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c },
+	{ TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c },
+	{ TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 },
+	{ TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+	{ TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+	{ TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+	{ TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 },
+	{ TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
+	{ TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 },
+	{ TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+	{ TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a },
+	{ TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 },
+	{ TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 },
+	{ TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a },
+	{ TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 },
+	{ TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 },
+	{ TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 },
+	{ TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 },
+	{ TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 },
+	{ TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 },
+	{ TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 },
+	{ TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+	{ TM6010_REQ07_RC1_TRESHOLD, 0xd0 },
+	{ TM6010_REQ07_RC3_HSTART1, 0x88 },
+	{ TM6010_REQ07_R3F_RESET, 0x00 },		/* End of the soft reset */
+	{ TM6010_REQ05_R18_IMASK7, 0x00 },
+};
+
+static struct reg_init tm6010_init_tab[] = {
+	{ TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x00 },
+	{ TM6010_REQ07_RC4_HSTART0, 0xa0 },
+	{ TM6010_REQ07_RC6_HEND0, 0x40 },
+	{ TM6010_REQ07_RCA_VEND0, 0x31 },
+	{ TM6010_REQ07_RCC_ACTIVE_IF, 0xe1 },
+	{ TM6010_REQ07_RE0_DVIDEO_SOURCE, 0x03 },
+	{ TM6010_REQ07_RFE_POWER_DOWN, 0x7f },
+
+	{ TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0 },
+	{ TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4 },
+	{ TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8 },
+	{ TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x00 },
+	{ TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2 },
+	{ TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0 },
+	{ TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2 },
+	{ TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x60 },
+	{ TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc },
+
+	{ TM6010_REQ07_R3F_RESET, 0x01 },
+	{ TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
+	{ TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 },
+	{ TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+	{ TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
+	{ TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 },
+	{ TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 },
+	{ TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 },
+	{ TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 },
+	{ TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 },
+	{ TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a },
+	{ TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 },
+	{ TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 },
+	{ TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b },
+	{ TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 },
+	{ TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f },
+	{ TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd },
+	{ TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+	{ TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
+	{ TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
+	{ TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
+	{ TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+	{ TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+	{ TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+	{ TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+	{ TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c },
+	{ TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c },
+	{ TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 },
+	{ TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+	{ TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+	{ TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+	{ TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 },
+	{ TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
+	{ TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 },
+	{ TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+	{ TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a },
+	{ TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 },
+	{ TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 },
+	{ TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a },
+	{ TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 },
+	{ TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 },
+	{ TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 },
+	{ TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 },
+	{ TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 },
+	{ TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 },
+	{ TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 },
+	{ TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+	{ TM6010_REQ07_RC1_TRESHOLD, 0xd0 },
+	{ TM6010_REQ07_RC3_HSTART1, 0x88 },
+	{ TM6010_REQ07_R3F_RESET, 0x00 },
+
+	{ TM6010_REQ05_R18_IMASK7, 0x00 },
+
+	{ TM6010_REQ07_RD8_IR_LEADER1, 0xaa },
+	{ TM6010_REQ07_RD8_IR_LEADER0, 0x30 },
+	{ TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20 },
+	{ TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0 },
+	{ REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 },
+	{ TM6010_REQ07_RD8_IR, 0x2f },
+
+	/* set remote wakeup key:any key wakeup */
+	{ TM6010_REQ07_RE5_REMOTE_WAKEUP,  0xfe },
+	{ TM6010_REQ07_RD8_IR_WAKEUP_SEL,  0xff },
+};
+
+int tm6000_init(struct tm6000_core *dev)
+{
+	int board, rc = 0, i, size;
+	struct reg_init *tab;
+
+	/* Check board revision */
+	board = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0);
+	if (board >= 0) {
+		switch (board & 0xff) {
+		case 0xf3:
+			printk(KERN_INFO "Found tm6000\n");
+			if (dev->dev_type != TM6000)
+				dev->dev_type = TM6000;
+			break;
+		case 0xf4:
+			printk(KERN_INFO "Found tm6010\n");
+			if (dev->dev_type != TM6010)
+				dev->dev_type = TM6010;
+			break;
+		default:
+			printk(KERN_INFO "Unknown board version = 0x%08x\n", board);
+		}
+	} else
+		printk(KERN_ERR "Error %i while retrieving board version\n", board);
+
+	if (dev->dev_type == TM6010) {
+		tab = tm6010_init_tab;
+		size = ARRAY_SIZE(tm6010_init_tab);
+	} else {
+		tab = tm6000_init_tab;
+		size = ARRAY_SIZE(tm6000_init_tab);
+	}
+
+	/* Load board's initialization table */
+	for (i = 0; i < size; i++) {
+		rc = tm6000_set_reg(dev, tab[i].req, tab[i].reg, tab[i].val);
+		if (rc < 0) {
+			printk(KERN_ERR "Error %i while setting req %d, "
+					"reg %d to value %d\n", rc,
+					tab[i].req, tab[i].reg, tab[i].val);
+			return rc;
+		}
+	}
+
+	msleep(5); /* Just to be conservative */
+
+	rc = tm6000_cards_setup(dev);
+
+	return rc;
+}
+
+int tm6000_reset(struct tm6000_core *dev)
+{
+	int pipe;
+	int err;
+
+	msleep(500);
+
+	err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 0);
+	if (err < 0) {
+		tm6000_err("failed to select interface %d, alt. setting 0\n",
+				dev->isoc_in.bInterfaceNumber);
+		return err;
+	}
+
+	err = usb_reset_configuration(dev->udev);
+	if (err < 0) {
+		tm6000_err("failed to reset configuration\n");
+		return err;
+	}
+
+	if ((dev->quirks & TM6000_QUIRK_NO_USB_DELAY) == 0)
+		msleep(5);
+
+	/*
+	 * Not all devices have int_in defined
+	 */
+	if (!dev->int_in.endp)
+		return 0;
+
+	err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 2);
+	if (err < 0) {
+		tm6000_err("failed to select interface %d, alt. setting 2\n",
+				dev->isoc_in.bInterfaceNumber);
+		return err;
+	}
+
+	msleep(5);
+
+	pipe = usb_rcvintpipe(dev->udev,
+			dev->int_in.endp->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+
+	err = usb_clear_halt(dev->udev, pipe);
+	if (err < 0) {
+		tm6000_err("usb_clear_halt failed: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate)
+{
+	int val = 0;
+	u8 areg_f0 = 0x60; /* ADC MCLK = 250 Fs */
+	u8 areg_0a = 0x91; /* SIF 48KHz */
+
+	switch (bitrate) {
+	case 48000:
+		areg_f0 = 0x60; /* ADC MCLK = 250 Fs */
+		areg_0a = 0x91; /* SIF 48KHz */
+		dev->audio_bitrate = bitrate;
+		break;
+	case 32000:
+		areg_f0 = 0x00; /* ADC MCLK = 375 Fs */
+		areg_0a = 0x90; /* SIF 32KHz */
+		dev->audio_bitrate = bitrate;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+
+	/* enable I2S, if we use sif or external I2S device */
+	if (dev->dev_type == TM6010) {
+		val = tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, areg_0a);
+		if (val < 0)
+			return val;
+
+		val = tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+							areg_f0, 0xf0);
+		if (val < 0)
+			return val;
+	} else {
+		val = tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE,
+							areg_f0, 0xf0);
+		if (val < 0)
+			return val;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(tm6000_set_audio_bitrate);
+
+int tm6000_set_audio_rinput(struct tm6000_core *dev)
+{
+	if (dev->dev_type == TM6010) {
+		/* Audio crossbar setting, default SIF1 */
+		u8 areg_f0;
+
+		switch (dev->rinput.amux) {
+		case TM6000_AMUX_SIF1:
+		case TM6000_AMUX_SIF2:
+			areg_f0 = 0x03;
+			break;
+		case TM6000_AMUX_ADC1:
+			areg_f0 = 0x00;
+			break;
+		case TM6000_AMUX_ADC2:
+			areg_f0 = 0x08;
+			break;
+		case TM6000_AMUX_I2S:
+			areg_f0 = 0x04;
+			break;
+		default:
+			printk(KERN_INFO "%s: audio input dosn't support\n",
+				dev->name);
+			return 0;
+			break;
+		}
+		/* Set audio input crossbar */
+		tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+							areg_f0, 0x0f);
+	} else {
+		u8 areg_eb;
+		/* Audio setting, default LINE1 */
+		switch (dev->rinput.amux) {
+		case TM6000_AMUX_ADC1:
+			areg_eb = 0x00;
+			break;
+		case TM6000_AMUX_ADC2:
+			areg_eb = 0x04;
+			break;
+		default:
+			printk(KERN_INFO "%s: audio input dosn't support\n",
+				dev->name);
+			return 0;
+			break;
+		}
+		/* Set audio input */
+		tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE,
+							areg_eb, 0x0f);
+	}
+	return 0;
+}
+
+static void tm6010_set_mute_sif(struct tm6000_core *dev, u8 mute)
+{
+	u8 mute_reg = 0;
+
+	if (mute)
+		mute_reg = 0x08;
+
+	tm6000_set_reg_mask(dev, TM6010_REQ08_R0A_A_I2S_MOD, mute_reg, 0x08);
+}
+
+static void tm6010_set_mute_adc(struct tm6000_core *dev, u8 mute)
+{
+	u8 mute_reg = 0;
+
+	if (mute)
+		mute_reg = 0x20;
+
+	if (dev->dev_type == TM6010) {
+		tm6000_set_reg_mask(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL,
+							mute_reg, 0x20);
+		tm6000_set_reg_mask(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL,
+							mute_reg, 0x20);
+	} else {
+		tm6000_set_reg_mask(dev, TM6000_REQ07_REC_VADC_AADC_LVOL,
+							mute_reg, 0x20);
+		tm6000_set_reg_mask(dev, TM6000_REQ07_RED_VADC_AADC_RVOL,
+							mute_reg, 0x20);
+	}
+}
+
+int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute)
+{
+	enum tm6000_mux mux;
+
+	if (dev->radio)
+		mux = dev->rinput.amux;
+	else
+		mux = dev->vinput[dev->input].amux;
+
+	switch (mux) {
+	case TM6000_AMUX_SIF1:
+	case TM6000_AMUX_SIF2:
+		if (dev->dev_type == TM6010)
+			tm6010_set_mute_sif(dev, mute);
+		else {
+			printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has"
+					" SIF audio inputs. Please check the %s"
+					" configuration.\n", dev->name);
+			return -EINVAL;
+		}
+		break;
+	case TM6000_AMUX_ADC1:
+	case TM6000_AMUX_ADC2:
+		tm6010_set_mute_adc(dev, mute);
+		break;
+	default:
+		return -EINVAL;
+		break;
+	}
+	return 0;
+}
+
+static void tm6010_set_volume_sif(struct tm6000_core *dev, int vol)
+{
+	u8 vol_reg;
+
+	vol_reg = vol & 0x0F;
+
+	if (vol < 0)
+		vol_reg |= 0x40;
+
+	tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, vol_reg);
+	tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, vol_reg);
+}
+
+static void tm6010_set_volume_adc(struct tm6000_core *dev, int vol)
+{
+	u8 vol_reg;
+
+	vol_reg = (vol + 0x10) & 0x1f;
+
+	if (dev->dev_type == TM6010) {
+		tm6000_set_reg(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL, vol_reg);
+		tm6000_set_reg(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL, vol_reg);
+	} else {
+		tm6000_set_reg(dev, TM6000_REQ07_REC_VADC_AADC_LVOL, vol_reg);
+		tm6000_set_reg(dev, TM6000_REQ07_RED_VADC_AADC_RVOL, vol_reg);
+	}
+}
+
+void tm6000_set_volume(struct tm6000_core *dev, int vol)
+{
+	enum tm6000_mux mux;
+
+	if (dev->radio) {
+		mux = dev->rinput.amux;
+		vol += 8; /* Offset to 0 dB */
+	} else
+		mux = dev->vinput[dev->input].amux;
+
+	switch (mux) {
+	case TM6000_AMUX_SIF1:
+	case TM6000_AMUX_SIF2:
+		if (dev->dev_type == TM6010)
+			tm6010_set_volume_sif(dev, vol);
+		else
+			printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has"
+					" SIF audio inputs. Please check the %s"
+					" configuration.\n", dev->name);
+		break;
+	case TM6000_AMUX_ADC1:
+	case TM6000_AMUX_ADC2:
+		tm6010_set_volume_adc(dev, vol);
+		break;
+	default:
+		break;
+	}
+}
+
+static LIST_HEAD(tm6000_devlist);
+static DEFINE_MUTEX(tm6000_devlist_mutex);
+
+/*
+ * tm6000_realease_resource()
+ */
+
+void tm6000_remove_from_devlist(struct tm6000_core *dev)
+{
+	mutex_lock(&tm6000_devlist_mutex);
+	list_del(&dev->devlist);
+	mutex_unlock(&tm6000_devlist_mutex);
+};
+
+void tm6000_add_into_devlist(struct tm6000_core *dev)
+{
+	mutex_lock(&tm6000_devlist_mutex);
+	list_add_tail(&dev->devlist, &tm6000_devlist);
+	mutex_unlock(&tm6000_devlist_mutex);
+};
+
+/*
+ * Extension interface
+ */
+
+static LIST_HEAD(tm6000_extension_devlist);
+
+int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type,
+			char *buf, int size)
+{
+	struct tm6000_ops *ops = NULL;
+
+	/* FIXME: tm6000_extension_devlist_lock should be a spinlock */
+
+	if (!list_empty(&tm6000_extension_devlist)) {
+		list_for_each_entry(ops, &tm6000_extension_devlist, next) {
+			if (ops->fillbuf && ops->type == type)
+				ops->fillbuf(dev, buf, size);
+		}
+	}
+
+	return 0;
+}
+
+int tm6000_register_extension(struct tm6000_ops *ops)
+{
+	struct tm6000_core *dev = NULL;
+
+	mutex_lock(&tm6000_devlist_mutex);
+	list_add_tail(&ops->next, &tm6000_extension_devlist);
+	list_for_each_entry(dev, &tm6000_devlist, devlist) {
+		ops->init(dev);
+		printk(KERN_INFO "%s: Initialized (%s) extension\n",
+		       dev->name, ops->name);
+	}
+	mutex_unlock(&tm6000_devlist_mutex);
+	return 0;
+}
+EXPORT_SYMBOL(tm6000_register_extension);
+
+void tm6000_unregister_extension(struct tm6000_ops *ops)
+{
+	struct tm6000_core *dev = NULL;
+
+	mutex_lock(&tm6000_devlist_mutex);
+	list_for_each_entry(dev, &tm6000_devlist, devlist)
+		ops->fini(dev);
+
+	printk(KERN_INFO "tm6000: Remove (%s) extension\n", ops->name);
+	list_del(&ops->next);
+	mutex_unlock(&tm6000_devlist_mutex);
+}
+EXPORT_SYMBOL(tm6000_unregister_extension);
+
+void tm6000_init_extension(struct tm6000_core *dev)
+{
+	struct tm6000_ops *ops = NULL;
+
+	mutex_lock(&tm6000_devlist_mutex);
+	if (!list_empty(&tm6000_extension_devlist)) {
+		list_for_each_entry(ops, &tm6000_extension_devlist, next) {
+			if (ops->init)
+				ops->init(dev);
+		}
+	}
+	mutex_unlock(&tm6000_devlist_mutex);
+}
+
+void tm6000_close_extension(struct tm6000_core *dev)
+{
+	struct tm6000_ops *ops = NULL;
+
+	mutex_lock(&tm6000_devlist_mutex);
+	if (!list_empty(&tm6000_extension_devlist)) {
+		list_for_each_entry(ops, &tm6000_extension_devlist, next) {
+			if (ops->fini)
+				ops->fini(dev);
+		}
+	}
+	mutex_unlock(&tm6000_devlist_mutex);
+}
diff -druN linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-dvb.c linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-dvb.c
--- linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-dvb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-dvb.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,452 @@
+/*
+ *  tm6000-dvb.c - dvb-t support for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation version 2
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/slab.h>
+#include <linux/usb.h>
+
+#include "tm6000.h"
+#include "tm6000-regs.h"
+
+#include "zl10353.h"
+
+#include <media/tuner.h>
+
+#include "tuner-xc2028.h"
+#include "xc5000.h"
+
+MODULE_DESCRIPTION("DVB driver extension module for tm5600/6000/6010 based TV cards");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_LICENSE("GPL");
+
+MODULE_SUPPORTED_DEVICE("{{Trident, tm5600},"
+			"{{Trident, tm6000},"
+			"{{Trident, tm6010}");
+
+static int debug;
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug message");
+
+static inline void print_err_status(struct tm6000_core *dev,
+				    int packet, int status)
+{
+	char *errmsg = "Unknown";
+
+	switch (status) {
+	case -ENOENT:
+		errmsg = "unlinked synchronuously";
+		break;
+	case -ECONNRESET:
+		errmsg = "unlinked asynchronuously";
+		break;
+	case -ENOSR:
+		errmsg = "Buffer error (overrun)";
+		break;
+	case -EPIPE:
+		errmsg = "Stalled (device not responding)";
+		break;
+	case -EOVERFLOW:
+		errmsg = "Babble (bad cable?)";
+		break;
+	case -EPROTO:
+		errmsg = "Bit-stuff error (bad cable?)";
+		break;
+	case -EILSEQ:
+		errmsg = "CRC/Timeout (could be anything)";
+		break;
+	case -ETIME:
+		errmsg = "Device does not respond";
+		break;
+	}
+	if (packet < 0) {
+		dprintk(dev, 1, "URB status %d [%s].\n",
+			status, errmsg);
+	} else {
+		dprintk(dev, 1, "URB packet %d, status %d [%s].\n",
+			packet, status, errmsg);
+	}
+}
+
+static void tm6000_urb_received(struct urb *urb)
+{
+	int ret;
+	struct tm6000_core *dev = urb->context;
+
+	if (urb->status != 0)
+		print_err_status(dev, 0, urb->status);
+	else if (urb->actual_length > 0)
+		dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
+						   urb->actual_length);
+
+	if (dev->dvb->streams > 0) {
+		ret = usb_submit_urb(urb, GFP_ATOMIC);
+		if (ret < 0) {
+			printk(KERN_ERR "tm6000:  error %s\n", __func__);
+			kfree(urb->transfer_buffer);
+			usb_free_urb(urb);
+		}
+	}
+}
+
+static int tm6000_start_stream(struct tm6000_core *dev)
+{
+	int ret;
+	unsigned int pipe, size;
+	struct tm6000_dvb *dvb = dev->dvb;
+
+	printk(KERN_INFO "tm6000: got start stream request %s\n", __func__);
+
+	if (dev->mode != TM6000_MODE_DIGITAL) {
+		tm6000_init_digital_mode(dev);
+		dev->mode = TM6000_MODE_DIGITAL;
+	}
+
+	dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (dvb->bulk_urb == NULL) {
+		printk(KERN_ERR "tm6000: couldn't allocate urb\n");
+		return -ENOMEM;
+	}
+
+	pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress
+							  & USB_ENDPOINT_NUMBER_MASK);
+
+	size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
+	size = size * 15; /* 512 x 8 or 12 or 15 */
+
+	dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
+	if (dvb->bulk_urb->transfer_buffer == NULL) {
+		usb_free_urb(dvb->bulk_urb);
+		printk(KERN_ERR "tm6000: couldn't allocate transfer buffer!\n");
+		return -ENOMEM;
+	}
+
+	usb_fill_bulk_urb(dvb->bulk_urb, dev->udev, pipe,
+						 dvb->bulk_urb->transfer_buffer,
+						 size,
+						 tm6000_urb_received, dev);
+
+	ret = usb_clear_halt(dev->udev, pipe);
+	if (ret < 0) {
+		printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",
+							ret, __func__);
+		return ret;
+	} else
+		printk(KERN_ERR "tm6000: pipe resetted\n");
+
+/*	mutex_lock(&tm6000_driver.open_close_mutex); */
+	ret = usb_submit_urb(dvb->bulk_urb, GFP_KERNEL);
+
+/*	mutex_unlock(&tm6000_driver.open_close_mutex); */
+	if (ret) {
+		printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n",
+									ret);
+
+		kfree(dvb->bulk_urb->transfer_buffer);
+		usb_free_urb(dvb->bulk_urb);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void tm6000_stop_stream(struct tm6000_core *dev)
+{
+	struct tm6000_dvb *dvb = dev->dvb;
+
+	if (dvb->bulk_urb) {
+		printk(KERN_INFO "urb killing\n");
+		usb_kill_urb(dvb->bulk_urb);
+		printk(KERN_INFO "urb buffer free\n");
+		kfree(dvb->bulk_urb->transfer_buffer);
+		usb_free_urb(dvb->bulk_urb);
+		dvb->bulk_urb = NULL;
+	}
+}
+
+static int tm6000_start_feed(struct dvb_demux_feed *feed)
+{
+	struct dvb_demux *demux = feed->demux;
+	struct tm6000_core *dev = demux->priv;
+	struct tm6000_dvb *dvb = dev->dvb;
+	printk(KERN_INFO "tm6000: got start feed request %s\n", __func__);
+
+	mutex_lock(&dvb->mutex);
+	if (dvb->streams == 0) {
+		dvb->streams = 1;
+/*		mutex_init(&tm6000_dev->streming_mutex); */
+		tm6000_start_stream(dev);
+	} else
+		++(dvb->streams);
+	mutex_unlock(&dvb->mutex);
+
+	return 0;
+}
+
+static int tm6000_stop_feed(struct dvb_demux_feed *feed)
+{
+	struct dvb_demux *demux = feed->demux;
+	struct tm6000_core *dev = demux->priv;
+	struct tm6000_dvb *dvb = dev->dvb;
+
+	printk(KERN_INFO "tm6000: got stop feed request %s\n", __func__);
+
+	mutex_lock(&dvb->mutex);
+
+	printk(KERN_INFO "stream %#x\n", dvb->streams);
+	--(dvb->streams);
+	if (dvb->streams == 0) {
+		printk(KERN_INFO "stop stream\n");
+		tm6000_stop_stream(dev);
+/*		mutex_destroy(&tm6000_dev->streaming_mutex); */
+	}
+	mutex_unlock(&dvb->mutex);
+/*	mutex_destroy(&tm6000_dev->streaming_mutex); */
+
+	return 0;
+}
+
+static int tm6000_dvb_attach_frontend(struct tm6000_core *dev)
+{
+	struct tm6000_dvb *dvb = dev->dvb;
+
+	if (dev->caps.has_zl10353) {
+		struct zl10353_config config = {
+				     .demod_address = dev->demod_addr,
+				     .no_tuner = 1,
+				     .parallel_ts = 1,
+				     .if2 = 45700,
+				     .disable_i2c_gate_ctrl = 1,
+				    };
+
+		dvb->frontend = dvb_attach(zl10353_attach, &config,
+							   &dev->i2c_adap);
+	} else {
+		printk(KERN_ERR "tm6000: no frontend defined for the device!\n");
+		return -1;
+	}
+
+	return (!dvb->frontend) ? -1 : 0;
+}
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static int register_dvb(struct tm6000_core *dev)
+{
+	int ret = -1;
+	struct tm6000_dvb *dvb = dev->dvb;
+
+	mutex_init(&dvb->mutex);
+
+	dvb->streams = 0;
+
+	/* attach the frontend */
+	ret = tm6000_dvb_attach_frontend(dev);
+	if (ret < 0) {
+		printk(KERN_ERR "tm6000: couldn't attach the frontend!\n");
+		goto err;
+	}
+
+	ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T",
+					THIS_MODULE, &dev->udev->dev, adapter_nr);
+	dvb->adapter.priv = dev;
+
+	if (dvb->frontend) {
+		switch (dev->tuner_type) {
+		case TUNER_XC2028: {
+			struct xc2028_config cfg = {
+				.i2c_adap = &dev->i2c_adap,
+				.i2c_addr = dev->tuner_addr,
+			};
+
+			dvb->frontend->callback = tm6000_tuner_callback;
+			ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+			if (ret < 0) {
+				printk(KERN_ERR
+					"tm6000: couldn't register frontend\n");
+				goto adapter_err;
+			}
+
+			if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
+				printk(KERN_ERR "tm6000: couldn't register "
+						"frontend (xc3028)\n");
+				ret = -EINVAL;
+				goto frontend_err;
+			}
+			printk(KERN_INFO "tm6000: XC2028/3028 asked to be "
+					 "attached to frontend!\n");
+			break;
+			}
+		case TUNER_XC5000: {
+			struct xc5000_config cfg = {
+				.i2c_address = dev->tuner_addr,
+			};
+
+			dvb->frontend->callback = tm6000_xc5000_callback;
+			ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+			if (ret < 0) {
+				printk(KERN_ERR
+					"tm6000: couldn't register frontend\n");
+				goto adapter_err;
+			}
+
+			if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) {
+				printk(KERN_ERR "tm6000: couldn't register "
+						"frontend (xc5000)\n");
+				ret = -EINVAL;
+				goto frontend_err;
+			}
+			printk(KERN_INFO "tm6000: XC5000 asked to be "
+					 "attached to frontend!\n");
+			break;
+			}
+		}
+	} else
+		printk(KERN_ERR "tm6000: no frontend found\n");
+
+	dvb->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING
+							    | DMX_MEMORY_BASED_FILTERING;
+	dvb->demux.priv = dev;
+	dvb->demux.filternum = 8;
+	dvb->demux.feednum = 8;
+	dvb->demux.start_feed = tm6000_start_feed;
+	dvb->demux.stop_feed = tm6000_stop_feed;
+	dvb->demux.write_to_decoder = NULL;
+	ret = dvb_dmx_init(&dvb->demux);
+	if (ret < 0) {
+		printk(KERN_ERR "tm6000: dvb_dmx_init failed (errno = %d)\n", ret);
+		goto frontend_err;
+	}
+
+	dvb->dmxdev.filternum = dev->dvb->demux.filternum;
+	dvb->dmxdev.demux = &dev->dvb->demux.dmx;
+	dvb->dmxdev.capabilities = 0;
+
+	ret =  dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
+	if (ret < 0) {
+		printk(KERN_ERR "tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret);
+		goto dvb_dmx_err;
+	}
+
+	return 0;
+
+dvb_dmx_err:
+	dvb_dmx_release(&dvb->demux);
+frontend_err:
+	if (dvb->frontend) {
+		dvb_frontend_detach(dvb->frontend);
+		dvb_unregister_frontend(dvb->frontend);
+	}
+adapter_err:
+	dvb_unregister_adapter(&dvb->adapter);
+err:
+	return ret;
+}
+
+static void unregister_dvb(struct tm6000_core *dev)
+{
+	struct tm6000_dvb *dvb = dev->dvb;
+
+	if (dvb->bulk_urb != NULL) {
+		struct urb *bulk_urb = dvb->bulk_urb;
+
+		kfree(bulk_urb->transfer_buffer);
+		bulk_urb->transfer_buffer = NULL;
+		usb_unlink_urb(bulk_urb);
+		usb_free_urb(bulk_urb);
+	}
+
+/*	mutex_lock(&tm6000_driver.open_close_mutex); */
+	if (dvb->frontend) {
+		dvb_frontend_detach(dvb->frontend);
+		dvb_unregister_frontend(dvb->frontend);
+	}
+
+	dvb_dmxdev_release(&dvb->dmxdev);
+	dvb_dmx_release(&dvb->demux);
+	dvb_unregister_adapter(&dvb->adapter);
+	mutex_destroy(&dvb->mutex);
+/*	mutex_unlock(&tm6000_driver.open_close_mutex); */
+}
+
+static int dvb_init(struct tm6000_core *dev)
+{
+	struct tm6000_dvb *dvb;
+	int rc;
+
+	if (!dev)
+		return 0;
+
+	if (!dev->caps.has_dvb)
+		return 0;
+
+	dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL);
+	if (!dvb) {
+		printk(KERN_INFO "Cannot allocate memory\n");
+		return -ENOMEM;
+	}
+
+	dev->dvb = dvb;
+
+	rc = register_dvb(dev);
+	if (rc < 0) {
+		kfree(dvb);
+		dev->dvb = NULL;
+		return 0;
+	}
+
+	return 0;
+}
+
+static int dvb_fini(struct tm6000_core *dev)
+{
+	if (!dev)
+		return 0;
+
+	if (!dev->caps.has_dvb)
+		return 0;
+
+	if (dev->dvb) {
+		unregister_dvb(dev);
+		kfree(dev->dvb);
+		dev->dvb = NULL;
+	}
+
+	return 0;
+}
+
+static struct tm6000_ops dvb_ops = {
+	.type	= TM6000_DVB,
+	.name	= "TM6000 dvb Extension",
+	.init	= dvb_init,
+	.fini	= dvb_fini,
+};
+
+static int __init tm6000_dvb_register(void)
+{
+	return tm6000_register_extension(&dvb_ops);
+}
+
+static void __exit tm6000_dvb_unregister(void)
+{
+	tm6000_unregister_extension(&dvb_ops);
+}
+
+module_init(tm6000_dvb_register);
+module_exit(tm6000_dvb_unregister);
diff -druN linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000.h linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000.h
--- linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,398 @@
+/*
+ *  tm6000.h - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ *	- DVB-T support
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation 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.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/videobuf-vmalloc.h>
+#include "tm6000-usb-isoc.h"
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <media/v4l2-device.h>
+
+#include <linux/dvb/frontend.h>
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dmxdev.h"
+
+#define TM6000_VERSION KERNEL_VERSION(0, 0, 2)
+
+/* Inputs */
+enum tm6000_itype {
+	TM6000_INPUT_TV	= 1,
+	TM6000_INPUT_COMPOSITE1,
+	TM6000_INPUT_COMPOSITE2,
+	TM6000_INPUT_SVIDEO,
+	TM6000_INPUT_DVB,
+	TM6000_INPUT_RADIO,
+};
+
+enum tm6000_mux {
+	TM6000_VMUX_VIDEO_A = 1,
+	TM6000_VMUX_VIDEO_B,
+	TM6000_VMUX_VIDEO_AB,
+	TM6000_AMUX_ADC1,
+	TM6000_AMUX_ADC2,
+	TM6000_AMUX_SIF1,
+	TM6000_AMUX_SIF2,
+	TM6000_AMUX_I2S,
+};
+
+enum tm6000_devtype {
+	TM6000 = 0,
+	TM5600,
+	TM6010,
+};
+
+struct tm6000_input {
+	enum tm6000_itype	type;
+	enum tm6000_mux		vmux;
+	enum tm6000_mux		amux;
+	unsigned int		v_gpio;
+	unsigned int		a_gpio;
+};
+
+/* ------------------------------------------------------------------
+ *	Basic structures
+ * ------------------------------------------------------------------
+ */
+
+struct tm6000_fmt {
+	char  *name;
+	u32   fourcc;          /* v4l2 format id */
+	int   depth;
+};
+
+/* buffer for one video frame */
+struct tm6000_buffer {
+	/* common v4l buffer stuff -- must be first */
+	struct videobuf_buffer vb;
+
+	struct tm6000_fmt      *fmt;
+};
+
+struct tm6000_dmaqueue {
+	struct list_head       active;
+	struct list_head       queued;
+
+	/* thread for generating video stream*/
+	struct task_struct         *kthread;
+	wait_queue_head_t          wq;
+	/* Counters to control fps rate */
+	int                        frame;
+	int                        ini_jiffies;
+};
+
+/* device states */
+enum tm6000_core_state {
+	DEV_INITIALIZED   = 0x01,
+	DEV_DISCONNECTED  = 0x02,
+	DEV_MISCONFIGURED = 0x04,
+};
+
+/* io methods */
+enum tm6000_io_method {
+	IO_NONE,
+	IO_READ,
+	IO_MMAP,
+};
+
+enum tm6000_mode {
+	TM6000_MODE_UNKNOWN = 0,
+	TM6000_MODE_ANALOG,
+	TM6000_MODE_DIGITAL,
+};
+
+struct tm6000_gpio {
+	int		tuner_reset;
+	int		tuner_on;
+	int		demod_reset;
+	int		demod_on;
+	int		power_led;
+	int		dvb_led;
+	int		ir;
+};
+
+struct tm6000_capabilities {
+	unsigned int    has_tuner:1;
+	unsigned int    has_tda9874:1;
+	unsigned int    has_dvb:1;
+	unsigned int    has_zl10353:1;
+	unsigned int    has_eeprom:1;
+	unsigned int    has_remote:1;
+	unsigned int    has_radio:1;
+};
+
+struct tm6000_dvb {
+	struct dvb_adapter	adapter;
+	struct dvb_demux	demux;
+	struct dvb_frontend	*frontend;
+	struct dmxdev		dmxdev;
+	unsigned int		streams;
+	struct urb		*bulk_urb;
+	struct mutex		mutex;
+};
+
+struct snd_tm6000_card {
+	struct snd_card			*card;
+	spinlock_t			reg_lock;
+	struct tm6000_core		*core;
+	struct snd_pcm_substream	*substream;
+
+	/* temporary data for buffer fill processing */
+	unsigned			buf_pos;
+	unsigned			period_pos;
+};
+
+struct tm6000_endpoint {
+	struct usb_host_endpoint	*endp;
+	__u8				bInterfaceNumber;
+	__u8				bAlternateSetting;
+	unsigned			maxsize;
+};
+
+#define TM6000_QUIRK_NO_USB_DELAY (1 << 0)
+
+struct tm6000_core {
+	/* generic device properties */
+	char				name[30];	/* name (including minor) of the device */
+	int				model;		/* index in the device_data struct */
+	int				devno;		/* marks the number of this device */
+	enum tm6000_devtype		dev_type;	/* type of device */
+	unsigned char			eedata[256];	/* Eeprom data */
+	unsigned			eedata_size;	/* Size of the eeprom info */
+
+	v4l2_std_id                     norm;           /* Current norm */
+	int				width, height;	/* Selected resolution */
+
+	enum tm6000_core_state		state;
+
+	/* Device Capabilities*/
+	struct tm6000_capabilities	caps;
+
+	/* Tuner configuration */
+	int				tuner_type;		/* type of the tuner */
+	int				tuner_addr;		/* tuner address */
+
+	struct tm6000_gpio		gpio;
+
+	char				*ir_codes;
+
+	__u8				radio;
+
+	/* Demodulator configuration */
+	int				demod_addr;	/* demodulator address */
+
+	int				audio_bitrate;
+	/* i2c i/o */
+	struct i2c_adapter		i2c_adap;
+	struct i2c_client		i2c_client;
+
+
+	/* extension */
+	struct list_head		devlist;
+
+	/* video for linux */
+	int				users;
+
+	/* various device info */
+	struct tm6000_fh		*resources;	/* Points to fh that is streaming */
+	bool				is_res_read;
+
+	struct video_device		*vfd;
+	struct video_device		*radio_dev;
+	struct tm6000_dmaqueue		vidq;
+	struct v4l2_device		v4l2_dev;
+
+	int				input;
+	struct tm6000_input		vinput[3];	/* video input */
+	struct tm6000_input		rinput;		/* radio input */
+
+	int				freq;
+	unsigned int			fourcc;
+
+	enum tm6000_mode		mode;
+
+	int				ctl_mute;             /* audio */
+	int				ctl_volume;
+	int				amode;
+
+	/* DVB-T support */
+	struct tm6000_dvb		*dvb;
+
+	/* audio support */
+	struct snd_tm6000_card		*adev;
+	struct work_struct		wq_trigger;   /* Trigger to start/stop audio for alsa module */
+	atomic_t			stream_started;  /* stream should be running if true */
+
+	struct tm6000_IR		*ir;
+
+	/* locks */
+	struct mutex			lock;
+	struct mutex			usb_lock;
+
+	/* usb transfer */
+	struct usb_device		*udev;		/* the usb device */
+
+	struct tm6000_endpoint		bulk_in, bulk_out, isoc_in, isoc_out;
+	struct tm6000_endpoint		int_in, int_out;
+
+	/* scaler!=0 if scaler is active*/
+	int				scaler;
+
+		/* Isoc control struct */
+	struct usb_isoc_ctl          isoc_ctl;
+
+	spinlock_t                   slock;
+
+	unsigned long quirks;
+};
+
+enum tm6000_ops_type {
+	TM6000_AUDIO = 0x10,
+	TM6000_DVB = 0x20,
+};
+
+struct tm6000_ops {
+	struct list_head	next;
+	char			*name;
+	enum tm6000_ops_type	type;
+	int (*init)(struct tm6000_core *);
+	int (*fini)(struct tm6000_core *);
+	int (*fillbuf)(struct tm6000_core *, char *buf, int size);
+};
+
+struct tm6000_fh {
+	struct tm6000_core           *dev;
+	unsigned int                 radio;
+
+	/* video capture */
+	struct tm6000_fmt            *fmt;
+	unsigned int                 width, height;
+	struct videobuf_queue        vb_vidq;
+
+	enum v4l2_buf_type           type;
+};
+
+#define TM6000_STD	(V4L2_STD_PAL|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|    \
+			V4L2_STD_PAL_M|V4L2_STD_PAL_60|V4L2_STD_NTSC_M| \
+			V4L2_STD_NTSC_M_JP|V4L2_STD_SECAM)
+
+/* In tm6000-cards.c */
+
+int tm6000_tuner_callback(void *ptr, int component, int command, int arg);
+int tm6000_xc5000_callback(void *ptr, int component, int command, int arg);
+int tm6000_cards_setup(struct tm6000_core *dev);
+void tm6000_flash_led(struct tm6000_core *dev, u8 state);
+
+/* In tm6000-core.c */
+
+int tm6000_read_write_usb(struct tm6000_core *dev, u8 reqtype, u8 req,
+			   u16 value, u16 index, u8 *buf, u16 len);
+int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index);
+int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index);
+int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index);
+int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index);
+int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value,
+						u16 index, u16 mask);
+int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep);
+int tm6000_init(struct tm6000_core *dev);
+int tm6000_reset(struct tm6000_core *dev);
+
+int tm6000_init_analog_mode(struct tm6000_core *dev);
+int tm6000_init_digital_mode(struct tm6000_core *dev);
+int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate);
+int tm6000_set_audio_rinput(struct tm6000_core *dev);
+int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute);
+void tm6000_set_volume(struct tm6000_core *dev, int vol);
+
+int tm6000_v4l2_register(struct tm6000_core *dev);
+int tm6000_v4l2_unregister(struct tm6000_core *dev);
+int tm6000_v4l2_exit(void);
+void tm6000_set_fourcc_format(struct tm6000_core *dev);
+
+void tm6000_remove_from_devlist(struct tm6000_core *dev);
+void tm6000_add_into_devlist(struct tm6000_core *dev);
+int tm6000_register_extension(struct tm6000_ops *ops);
+void tm6000_unregister_extension(struct tm6000_ops *ops);
+void tm6000_init_extension(struct tm6000_core *dev);
+void tm6000_close_extension(struct tm6000_core *dev);
+int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type,
+			char *buf, int size);
+
+
+/* In tm6000-stds.c */
+void tm6000_get_std_res(struct tm6000_core *dev);
+int tm6000_set_standard(struct tm6000_core *dev);
+
+/* In tm6000-i2c.c */
+int tm6000_i2c_register(struct tm6000_core *dev);
+int tm6000_i2c_unregister(struct tm6000_core *dev);
+
+/* In tm6000-queue.c */
+
+int tm6000_v4l2_mmap(struct file *filp, struct vm_area_struct *vma);
+
+int tm6000_vidioc_streamon(struct file *file, void *priv,
+			   enum v4l2_buf_type i);
+int tm6000_vidioc_streamoff(struct file *file, void *priv,
+			    enum v4l2_buf_type i);
+int tm6000_vidioc_reqbufs(struct file *file, void *priv,
+			  struct v4l2_requestbuffers *rb);
+int tm6000_vidioc_querybuf(struct file *file, void *priv,
+			   struct v4l2_buffer *b);
+int tm6000_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b);
+int tm6000_vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b);
+ssize_t tm6000_v4l2_read(struct file *filp, char __user * buf, size_t count,
+			 loff_t *f_pos);
+unsigned int tm6000_v4l2_poll(struct file *file,
+			      struct poll_table_struct *wait);
+int tm6000_queue_init(struct tm6000_core *dev);
+
+/* In tm6000-alsa.c */
+/*int tm6000_audio_init(struct tm6000_core *dev, int idx);*/
+
+/* In tm6000-input.c */
+int tm6000_ir_init(struct tm6000_core *dev);
+int tm6000_ir_fini(struct tm6000_core *dev);
+void tm6000_ir_wait(struct tm6000_core *dev, u8 state);
+int tm6000_ir_int_start(struct tm6000_core *dev);
+void tm6000_ir_int_stop(struct tm6000_core *dev);
+
+/* Debug stuff */
+
+extern int tm6000_debug;
+
+#define dprintk(dev, level, fmt, arg...) do {\
+	if (tm6000_debug & level) \
+		printk(KERN_INFO "(%lu) %s %s :"fmt, jiffies, \
+			 dev->name, __func__ , ##arg); } while (0)
+
+#define V4L2_DEBUG_REG		0x0004
+#define V4L2_DEBUG_I2C		0x0008
+#define V4L2_DEBUG_QUEUE	0x0010
+#define V4L2_DEBUG_ISOC		0x0020
+#define V4L2_DEBUG_RES_LOCK	0x0040	/* Resource locking */
+#define V4L2_DEBUG_OPEN		0x0080	/* video open/close debug */
+
+#define tm6000_err(fmt, arg...) do {\
+	printk(KERN_ERR "tm6000 %s :"fmt, \
+		__func__ , ##arg); } while (0)
diff -druN linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-i2c.c linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-i2c.c
--- linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,340 @@
+/*
+ *  tm6000-i2c.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ *	- Fix SMBus Read Byte command
+ *
+ *  This program is free software; 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.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/kernel.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+
+#include "tm6000.h"
+#include "tm6000-regs.h"
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+#include "tuner-xc2028.h"
+
+
+/* ----------------------------------------------------------- */
+
+static unsigned int i2c_debug;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+#define i2c_dprintk(lvl, fmt, args...) if (i2c_debug >= lvl) do { \
+			printk(KERN_DEBUG "%s at %s: " fmt, \
+			dev->name, __func__, ##args); } while (0)
+
+static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr,
+				__u8 reg, char *buf, int len)
+{
+	int rc;
+	unsigned int tsleep;
+	unsigned int i2c_packet_limit = 16;
+
+	if (dev->dev_type == TM6010)
+		i2c_packet_limit = 64;
+
+	if (!buf)
+		return -1;
+
+	if (len < 1 || len > i2c_packet_limit) {
+		printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
+			len, i2c_packet_limit);
+		return -1;
+	}
+
+	/* capture mutex */
+	rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
+		USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+		addr | reg << 8, 0, buf, len);
+
+	if (rc < 0) {
+		/* release mutex */
+		return rc;
+	}
+
+	/* Calculate delay time, 14000us for 64 bytes */
+	tsleep = ((len * 200) + 200 + 1000) / 1000;
+	msleep(tsleep);
+
+	/* release mutex */
+	return rc;
+}
+
+/* Generic read - doesn't work fine with 16bit registers */
+static int tm6000_i2c_recv_regs(struct tm6000_core *dev, unsigned char addr,
+				__u8 reg, char *buf, int len)
+{
+	int rc;
+	u8 b[2];
+	unsigned int i2c_packet_limit = 16;
+
+	if (dev->dev_type == TM6010)
+		i2c_packet_limit = 64;
+
+	if (!buf)
+		return -1;
+
+	if (len < 1 || len > i2c_packet_limit) {
+		printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
+			len, i2c_packet_limit);
+		return -1;
+	}
+
+	/* capture mutex */
+	if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) {
+		/*
+		 * Workaround an I2C bug when reading from zl10353
+		 */
+		reg -= 1;
+		len += 1;
+
+		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len);
+
+		*buf = b[1];
+	} else {
+		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
+	}
+
+	/* release mutex */
+	return rc;
+}
+
+/*
+ * read from a 16bit register
+ * for example xc2028, xc3028 or xc3028L
+ */
+static int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr,
+				  __u16 reg, char *buf, int len)
+{
+	int rc;
+	unsigned char ureg;
+
+	if (!buf || len != 2)
+		return -1;
+
+	/* capture mutex */
+	if (dev->dev_type == TM6010) {
+		ureg = reg & 0xFF;
+		rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
+			USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+			addr | (reg & 0xFF00), 0, &ureg, 1);
+
+		if (rc < 0) {
+			/* release mutex */
+			return rc;
+		}
+
+		msleep(1400 / 1000);
+		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+			USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
+			reg, 0, buf, len);
+	} else {
+		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+			USB_RECIP_DEVICE, REQ_14_SET_GET_I2C_WR2_RDN,
+			addr, reg, buf, len);
+	}
+
+	/* release mutex */
+	return rc;
+}
+
+static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
+			   struct i2c_msg msgs[], int num)
+{
+	struct tm6000_core *dev = i2c_adap->algo_data;
+	int addr, rc, i, byte;
+
+	if (num <= 0)
+		return 0;
+	for (i = 0; i < num; i++) {
+		addr = (msgs[i].addr << 1) & 0xff;
+		i2c_dprintk(2, "%s %s addr=0x%x len=%d:",
+			 (msgs[i].flags & I2C_M_RD) ? "read" : "write",
+			 i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
+		if (msgs[i].flags & I2C_M_RD) {
+			/* read request without preceding register selection */
+			/*
+			 * The TM6000 only supports a read transaction
+			 * immediately after a 1 or 2 byte write to select
+			 * a register.  We cannot fulfil this request.
+			 */
+			i2c_dprintk(2, " read without preceding write not"
+				       " supported");
+			rc = -EOPNOTSUPP;
+			goto err;
+		} else if (i + 1 < num && msgs[i].len <= 2 &&
+			   (msgs[i + 1].flags & I2C_M_RD) &&
+			   msgs[i].addr == msgs[i + 1].addr) {
+			/* 1 or 2 byte write followed by a read */
+			if (i2c_debug >= 2)
+				for (byte = 0; byte < msgs[i].len; byte++)
+					printk(KERN_CONT " %02x", msgs[i].buf[byte]);
+			i2c_dprintk(2, "; joined to read %s len=%d:",
+				    i == num - 2 ? "stop" : "nonstop",
+				    msgs[i + 1].len);
+
+			if (msgs[i].len == 2) {
+				rc = tm6000_i2c_recv_regs16(dev, addr,
+					msgs[i].buf[0] << 8 | msgs[i].buf[1],
+					msgs[i + 1].buf, msgs[i + 1].len);
+			} else {
+				rc = tm6000_i2c_recv_regs(dev, addr, msgs[i].buf[0],
+					msgs[i + 1].buf, msgs[i + 1].len);
+			}
+
+			i++;
+
+			if (addr == dev->tuner_addr << 1) {
+				tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
+				tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
+			}
+			if (i2c_debug >= 2)
+				for (byte = 0; byte < msgs[i].len; byte++)
+					printk(KERN_CONT " %02x", msgs[i].buf[byte]);
+		} else {
+			/* write bytes */
+			if (i2c_debug >= 2)
+				for (byte = 0; byte < msgs[i].len; byte++)
+					printk(KERN_CONT " %02x", msgs[i].buf[byte]);
+			rc = tm6000_i2c_send_regs(dev, addr, msgs[i].buf[0],
+				msgs[i].buf + 1, msgs[i].len - 1);
+		}
+		if (i2c_debug >= 2)
+			printk(KERN_CONT "\n");
+		if (rc < 0)
+			goto err;
+	}
+
+	return num;
+err:
+	i2c_dprintk(2, " ERROR: %i\n", rc);
+	return rc;
+}
+
+static int tm6000_i2c_eeprom(struct tm6000_core *dev)
+{
+	int i, rc;
+	unsigned char *p = dev->eedata;
+	unsigned char bytes[17];
+
+	dev->i2c_client.addr = 0xa0 >> 1;
+	dev->eedata_size = 0;
+
+	bytes[16] = '\0';
+	for (i = 0; i < sizeof(dev->eedata); ) {
+		*p = i;
+		rc = tm6000_i2c_recv_regs(dev, 0xa0, i, p, 1);
+		if (rc < 1) {
+			if (p == dev->eedata)
+				goto noeeprom;
+			else {
+				printk(KERN_WARNING
+				"%s: i2c eeprom read error (err=%d)\n",
+				dev->name, rc);
+			}
+			return -EINVAL;
+		}
+		dev->eedata_size++;
+		p++;
+		if (0 == (i % 16))
+			printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
+		printk(KERN_CONT " %02x", dev->eedata[i]);
+		if ((dev->eedata[i] >= ' ') && (dev->eedata[i] <= 'z'))
+			bytes[i%16] = dev->eedata[i];
+		else
+			bytes[i%16] = '.';
+
+		i++;
+
+		if (0 == (i % 16)) {
+			bytes[16] = '\0';
+			printk(KERN_CONT "  %s\n", bytes);
+		}
+	}
+	if (0 != (i%16)) {
+		bytes[i%16] = '\0';
+		for (i %= 16; i < 16; i++)
+			printk(KERN_CONT "   ");
+		printk(KERN_CONT "  %s\n", bytes);
+	}
+
+	return 0;
+
+noeeprom:
+	printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
+	       dev->name, rc);
+	return -EINVAL;
+}
+
+/* ----------------------------------------------------------- */
+
+/*
+ * functionality()
+ */
+static u32 functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm tm6000_algo = {
+	.master_xfer   = tm6000_i2c_xfer,
+	.functionality = functionality,
+};
+
+/* ----------------------------------------------------------- */
+
+/*
+ * tm6000_i2c_register()
+ * register i2c bus
+ */
+int tm6000_i2c_register(struct tm6000_core *dev)
+{
+	int rc;
+
+	dev->i2c_adap.owner = THIS_MODULE;
+	dev->i2c_adap.algo = &tm6000_algo;
+	dev->i2c_adap.dev.parent = &dev->udev->dev;
+	strlcpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name));
+	dev->i2c_adap.algo_data = dev;
+	i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
+	rc = i2c_add_adapter(&dev->i2c_adap);
+	if (rc)
+		return rc;
+
+	dev->i2c_client.adapter = &dev->i2c_adap;
+	strlcpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE);
+	tm6000_i2c_eeprom(dev);
+
+	return 0;
+}
+
+/*
+ * tm6000_i2c_unregister()
+ * unregister i2c_bus
+ */
+int tm6000_i2c_unregister(struct tm6000_core *dev)
+{
+	i2c_del_adapter(&dev->i2c_adap);
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-input.c linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-input.c
--- linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-input.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-input.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,459 @@
+/*
+ *  tm6000-input.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2010 Stefan Ringel <stefan.ringel@arcor.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 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.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/delay.h>
+
+#include <linux/input.h>
+#include <linux/usb.h>
+
+#include <media/rc-core.h>
+
+#include "tm6000.h"
+#include "tm6000-regs.h"
+
+static unsigned int ir_debug;
+module_param(ir_debug, int, 0644);
+MODULE_PARM_DESC(ir_debug, "enable debug message [IR]");
+
+static unsigned int enable_ir = 1;
+module_param(enable_ir, int, 0644);
+MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)");
+
+/* number of 50ms for ON-OFF-ON power led */
+/* show IR activity */
+#define PWLED_OFF 2
+
+#undef dprintk
+
+#define dprintk(fmt, arg...) \
+	if (ir_debug) { \
+		printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
+	}
+
+struct tm6000_ir_poll_result {
+	u16 rc_data;
+};
+
+struct tm6000_IR {
+	struct tm6000_core	*dev;
+	struct rc_dev		*rc;
+	char			name[32];
+	char			phys[32];
+
+	/* poll expernal decoder */
+	int			polling;
+	struct delayed_work	work;
+	u8			wait:1;
+	u8			key:1;
+	u8			pwled:1;
+	u8			pwledcnt;
+	u16			key_addr;
+	struct urb		*int_urb;
+	u8			*urb_data;
+
+	int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *);
+
+	/* IR device properties */
+	u64			rc_type;
+};
+
+
+void tm6000_ir_wait(struct tm6000_core *dev, u8 state)
+{
+	struct tm6000_IR *ir = dev->ir;
+
+	if (!dev->ir)
+		return;
+
+	if (state)
+		ir->wait = 1;
+	else
+		ir->wait = 0;
+}
+
+
+static int tm6000_ir_config(struct tm6000_IR *ir)
+{
+	struct tm6000_core *dev = ir->dev;
+	u8 buf[10];
+	int rc;
+
+	switch (ir->rc_type) {
+	case RC_TYPE_NEC:
+		/* Setup IR decoder for NEC standard 12MHz system clock */
+		/* IR_LEADER_CNT = 0.9ms             */
+		tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER1, 0xaa);
+		tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER0, 0x30);
+		/* IR_PULSE_CNT = 0.7ms              */
+		tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20);
+		tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0);
+		/* Remote WAKEUP = enable */
+		tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe);
+		/* IR_WKUP_SEL = Low byte in decoded IR data */
+		tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff);
+		/* IR_WKU_ADD code */
+		tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_ADD, 0xff);
+		tm6000_flash_led(dev, 0);
+		msleep(100);
+		tm6000_flash_led(dev, 1);
+		break;
+	default:
+		/* hack */
+		buf[0] = 0xff;
+		buf[1] = 0xff;
+		buf[2] = 0xf2;
+		buf[3] = 0x2b;
+		buf[4] = 0x20;
+		buf[5] = 0x35;
+		buf[6] = 0x60;
+		buf[7] = 0x04;
+		buf[8] = 0xc0;
+		buf[9] = 0x08;
+
+		rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
+			USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a);
+		msleep(100);
+
+		if (rc < 0) {
+			printk(KERN_INFO "IR configuration failed");
+			return rc;
+		}
+		break;
+	}
+
+	return 0;
+}
+
+static void tm6000_ir_urb_received(struct urb *urb)
+{
+	struct tm6000_core *dev = urb->context;
+	struct tm6000_IR *ir = dev->ir;
+	int rc;
+
+	if (urb->status != 0)
+		printk(KERN_INFO "not ready\n");
+	else if (urb->actual_length > 0) {
+		memcpy(ir->urb_data, urb->transfer_buffer, urb->actual_length);
+
+		dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0],
+			ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]);
+
+		ir->key = 1;
+	}
+
+	rc = usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static int default_polling_getkey(struct tm6000_IR *ir,
+				struct tm6000_ir_poll_result *poll_result)
+{
+	struct tm6000_core *dev = ir->dev;
+	int rc;
+	u8 buf[2];
+
+	if (ir->wait && !&dev->int_in)
+		return 0;
+
+	if (&dev->int_in) {
+		switch (ir->rc_type) {
+		case RC_TYPE_RC5:
+			poll_result->rc_data = ir->urb_data[0];
+			break;
+		case RC_TYPE_NEC:
+			if (ir->urb_data[1] == ((ir->key_addr >> 8) & 0xff)) {
+				poll_result->rc_data = ir->urb_data[0]
+							| ir->urb_data[1] << 8;
+			}
+			break;
+		default:
+			poll_result->rc_data = ir->urb_data[0]
+					| ir->urb_data[1] << 8;
+			break;
+		}
+	} else {
+		tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
+		msleep(10);
+		tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1);
+		msleep(10);
+
+		if (ir->rc_type == RC_TYPE_RC5) {
+			rc = tm6000_read_write_usb(dev, USB_DIR_IN |
+				USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+				REQ_02_GET_IR_CODE, 0, 0, buf, 1);
+
+			msleep(10);
+
+			dprintk("read data=%02x\n", buf[0]);
+			if (rc < 0)
+				return rc;
+
+			poll_result->rc_data = buf[0];
+		} else {
+			rc = tm6000_read_write_usb(dev, USB_DIR_IN |
+				USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+				REQ_02_GET_IR_CODE, 0, 0, buf, 2);
+
+			msleep(10);
+
+			dprintk("read data=%04x\n", buf[0] | buf[1] << 8);
+			if (rc < 0)
+				return rc;
+
+			poll_result->rc_data = buf[0] | buf[1] << 8;
+		}
+		if ((poll_result->rc_data & 0x00ff) != 0xff)
+			ir->key = 1;
+	}
+	return 0;
+}
+
+static void tm6000_ir_handle_key(struct tm6000_IR *ir)
+{
+	struct tm6000_core *dev = ir->dev;
+	int result;
+	struct tm6000_ir_poll_result poll_result;
+
+	/* read the registers containing the IR status */
+	result = ir->get_key(ir, &poll_result);
+	if (result < 0) {
+		printk(KERN_INFO "ir->get_key() failed %d\n", result);
+		return;
+	}
+
+	dprintk("ir->get_key result data=%04x\n", poll_result.rc_data);
+
+	if (ir->pwled) {
+		if (ir->pwledcnt >= PWLED_OFF) {
+			ir->pwled = 0;
+			ir->pwledcnt = 0;
+			tm6000_flash_led(dev, 1);
+		} else
+			ir->pwledcnt += 1;
+	}
+
+	if (ir->key) {
+		rc_keydown(ir->rc, poll_result.rc_data, 0);
+		ir->key = 0;
+		ir->pwled = 1;
+		ir->pwledcnt = 0;
+		tm6000_flash_led(dev, 0);
+	}
+	return;
+}
+
+static void tm6000_ir_work(struct work_struct *work)
+{
+	struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
+
+	tm6000_ir_handle_key(ir);
+	schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
+}
+
+static int tm6000_ir_start(struct rc_dev *rc)
+{
+	struct tm6000_IR *ir = rc->priv;
+
+	INIT_DELAYED_WORK(&ir->work, tm6000_ir_work);
+	schedule_delayed_work(&ir->work, 0);
+
+	return 0;
+}
+
+static void tm6000_ir_stop(struct rc_dev *rc)
+{
+	struct tm6000_IR *ir = rc->priv;
+
+	cancel_delayed_work_sync(&ir->work);
+}
+
+static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
+{
+	struct tm6000_IR *ir = rc->priv;
+
+	if (!ir)
+		return 0;
+
+	if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC))
+		ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff);
+
+	ir->get_key = default_polling_getkey;
+	ir->rc_type = rc_type;
+
+	tm6000_ir_config(ir);
+	/* TODO */
+	return 0;
+}
+
+int tm6000_ir_int_start(struct tm6000_core *dev)
+{
+	struct tm6000_IR *ir = dev->ir;
+	int pipe, size;
+	int err = -ENOMEM;
+
+
+	if (!ir)
+		return -ENODEV;
+
+	ir->int_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ir->int_urb)
+		return -ENOMEM;
+
+	pipe = usb_rcvintpipe(dev->udev,
+		dev->int_in.endp->desc.bEndpointAddress
+		& USB_ENDPOINT_NUMBER_MASK);
+
+	size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
+	dprintk("IR max size: %d\n", size);
+
+	ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
+	if (ir->int_urb->transfer_buffer == NULL) {
+		usb_free_urb(ir->int_urb);
+		return err;
+	}
+	dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval);
+	usb_fill_int_urb(ir->int_urb, dev->udev, pipe,
+		ir->int_urb->transfer_buffer, size,
+		tm6000_ir_urb_received, dev,
+		dev->int_in.endp->desc.bInterval);
+	err = usb_submit_urb(ir->int_urb, GFP_KERNEL);
+	if (err) {
+		kfree(ir->int_urb->transfer_buffer);
+		usb_free_urb(ir->int_urb);
+		return err;
+	}
+	ir->urb_data = kzalloc(size, GFP_KERNEL);
+
+	return 0;
+}
+
+void tm6000_ir_int_stop(struct tm6000_core *dev)
+{
+	struct tm6000_IR *ir = dev->ir;
+
+	if (!ir)
+		return;
+
+	usb_kill_urb(ir->int_urb);
+	kfree(ir->int_urb->transfer_buffer);
+	usb_free_urb(ir->int_urb);
+	ir->int_urb = NULL;
+	kfree(ir->urb_data);
+	ir->urb_data = NULL;
+}
+
+int tm6000_ir_init(struct tm6000_core *dev)
+{
+	struct tm6000_IR *ir;
+	struct rc_dev *rc;
+	int err = -ENOMEM;
+
+	if (!enable_ir)
+		return -ENODEV;
+
+	if (!dev->caps.has_remote)
+		return 0;
+
+	if (!dev->ir_codes)
+		return 0;
+
+	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+	rc = rc_allocate_device();
+	if (!ir || !rc)
+		goto out;
+
+	/* record handles to ourself */
+	ir->dev = dev;
+	dev->ir = ir;
+	ir->rc = rc;
+
+	/* input einrichten */
+	rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
+	rc->priv = ir;
+	rc->change_protocol = tm6000_ir_change_protocol;
+	rc->open = tm6000_ir_start;
+	rc->close = tm6000_ir_stop;
+	rc->driver_type = RC_DRIVER_SCANCODE;
+
+	ir->polling = 50;
+	ir->pwled = 0;
+	ir->pwledcnt = 0;
+
+
+	snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)",
+						dev->name);
+
+	usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
+	strlcat(ir->phys, "/input0", sizeof(ir->phys));
+
+	tm6000_ir_change_protocol(rc, RC_TYPE_UNKNOWN);
+
+	rc->input_name = ir->name;
+	rc->input_phys = ir->phys;
+	rc->input_id.bustype = BUS_USB;
+	rc->input_id.version = 1;
+	rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
+	rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
+	rc->map_name = dev->ir_codes;
+	rc->driver_name = "tm6000";
+	rc->dev.parent = &dev->udev->dev;
+
+	if (&dev->int_in) {
+		dprintk("IR over int\n");
+
+		err = tm6000_ir_int_start(dev);
+
+		if (err)
+			goto out;
+	}
+
+	/* ir register */
+	err = rc_register_device(rc);
+	if (err)
+		goto out;
+
+	return 0;
+
+out:
+	dev->ir = NULL;
+	rc_free_device(rc);
+	kfree(ir);
+	return err;
+}
+
+int tm6000_ir_fini(struct tm6000_core *dev)
+{
+	struct tm6000_IR *ir = dev->ir;
+
+	/* skip detach on non attached board */
+
+	if (!ir)
+		return 0;
+
+	rc_unregister_device(ir->rc);
+
+	if (ir->int_urb)
+		tm6000_ir_int_stop(dev);
+
+	kfree(ir);
+	dev->ir = NULL;
+
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-regs.h linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-regs.h
--- linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,600 @@
+/*
+ *  tm6000-regs.h - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 TV Master TM5600/TM6000/TM6010 Request codes
+ */
+#define REQ_00_SET_IR_VALUE		0
+#define REQ_01_SET_WAKEUP_IRCODE	1
+#define REQ_02_GET_IR_CODE		2
+#define REQ_03_SET_GET_MCU_PIN		3
+#define REQ_04_EN_DISABLE_MCU_INT	4
+#define REQ_05_SET_GET_USBREG		5
+	/* Write: RegNum, Value, 0 */
+	/* Read : RegNum, Value, 1, RegStatus */
+#define REQ_06_SET_GET_USBREG_BIT	6
+#define REQ_07_SET_GET_AVREG		7
+	/* Write: RegNum, Value, 0 */
+	/* Read : RegNum, Value, 1, RegStatus */
+#define REQ_08_SET_GET_AVREG_BIT	8
+#define REQ_09_SET_GET_TUNER_FQ		9
+#define REQ_10_SET_TUNER_SYSTEM		10
+#define REQ_11_SET_EEPROM_ADDR		11
+#define REQ_12_SET_GET_EEPROMBYTE	12
+#define REQ_13_GET_EEPROM_SEQREAD	13
+#define REQ_14_SET_GET_I2C_WR2_RDN	14
+#define REQ_15_SET_GET_I2CBYTE		15
+	/* Write: Subaddr, Slave Addr, value, 0 */
+	/* Read : Subaddr, Slave Addr, value, 1 */
+#define REQ_16_SET_GET_I2C_WR1_RDN	16
+	/* Subaddr, Slave Addr, 0, length */
+#define REQ_17_SET_GET_I2CFP		17
+	/* Write: Slave Addr, register, value */
+	/* Read : Slave Addr, register, 2, data */
+#define REQ_20_DATA_TRANSFER		20
+#define REQ_30_I2C_WRITE		30
+#define REQ_31_I2C_READ			31
+#define REQ_35_AFTEK_TUNER_READ		35
+#define REQ_40_GET_VERSION		40
+#define REQ_50_SET_START		50
+#define REQ_51_SET_STOP			51
+#define REQ_52_TRANSMIT_DATA		52
+#define REQ_53_SPI_INITIAL		53
+#define REQ_54_SPI_SETSTART		54
+#define REQ_55_SPI_INOUTDATA		55
+#define REQ_56_SPI_SETSTOP		56
+
+/*
+ * Define TV Master TM5600/TM6000/TM6010 GPIO lines
+ */
+
+#define TM6000_GPIO_CLK		0x101
+#define TM6000_GPIO_DATA	0x100
+
+#define TM6000_GPIO_1		0x102
+#define TM6000_GPIO_2		0x103
+#define TM6000_GPIO_3		0x104
+#define TM6000_GPIO_4		0x300
+#define TM6000_GPIO_5		0x301
+#define TM6000_GPIO_6		0x304
+#define TM6000_GPIO_7		0x305
+
+/* tm6010 defines GPIO with different values */
+#define TM6010_GPIO_0      0x0102
+#define TM6010_GPIO_1      0x0103
+#define TM6010_GPIO_2      0x0104
+#define TM6010_GPIO_3      0x0105
+#define TM6010_GPIO_4      0x0106
+#define TM6010_GPIO_5      0x0107
+#define TM6010_GPIO_6      0x0300
+#define TM6010_GPIO_7      0x0301
+#define TM6010_GPIO_9      0x0305
+/*
+ * Define TV Master TM5600/TM6000/TM6010 URB message codes and length
+ */
+
+enum {
+	TM6000_URB_MSG_VIDEO = 1,
+	TM6000_URB_MSG_AUDIO,
+	TM6000_URB_MSG_VBI,
+	TM6000_URB_MSG_PTS,
+	TM6000_URB_MSG_ERR,
+};
+
+/* Define specific TM6000 Video decoder registers */
+#define TM6000_REQ07_RD8_TEST_SEL			0x07, 0xd8
+#define TM6000_REQ07_RD9_A_SIM_SEL			0x07, 0xd9
+#define TM6000_REQ07_RDA_CLK_SEL			0x07, 0xda
+#define TM6000_REQ07_RDB_OUT_SEL			0x07, 0xdb
+#define TM6000_REQ07_RDC_NSEL_I2S			0x07, 0xdc
+#define TM6000_REQ07_RDD_GPIO2_MDRV			0x07, 0xdd
+#define TM6000_REQ07_RDE_GPIO1_MDRV			0x07, 0xde
+#define TM6000_REQ07_RDF_PWDOWN_ACLK			0x07, 0xdf
+#define TM6000_REQ07_RE0_VADC_REF_CTL			0x07, 0xe0
+#define TM6000_REQ07_RE1_VADC_DACLIMP			0x07, 0xe1
+#define TM6000_REQ07_RE2_VADC_STATUS_CTL		0x07, 0xe2
+#define TM6000_REQ07_RE3_VADC_INP_LPF_SEL1		0x07, 0xe3
+#define TM6000_REQ07_RE4_VADC_TARGET1			0x07, 0xe4
+#define TM6000_REQ07_RE5_VADC_INP_LPF_SEL2		0x07, 0xe5
+#define TM6000_REQ07_RE6_VADC_TARGET2			0x07, 0xe6
+#define TM6000_REQ07_RE7_VADC_AGAIN_CTL			0x07, 0xe7
+#define TM6000_REQ07_RE8_VADC_PWDOWN_CTL		0x07, 0xe8
+#define TM6000_REQ07_RE9_VADC_INPUT_CTL1		0x07, 0xe9
+#define TM6000_REQ07_REA_VADC_INPUT_CTL2		0x07, 0xea
+#define TM6000_REQ07_REB_VADC_AADC_MODE			0x07, 0xeb
+#define TM6000_REQ07_REC_VADC_AADC_LVOL			0x07, 0xec
+#define TM6000_REQ07_RED_VADC_AADC_RVOL			0x07, 0xed
+#define TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL		0x07, 0xee
+#define TM6000_REQ07_REF_VADC_GAIN_MAP_CTL		0x07, 0xef
+#define TM6000_REQ07_RFD_BIST_ERR_VST_LOW		0x07, 0xfd
+#define TM6000_REQ07_RFE_BIST_ERR_VST_HIGH		0x07, 0xfe
+
+/* Define TM6000/TM6010 Video decoder registers */
+#define TM6010_REQ07_R00_VIDEO_CONTROL0			0x07, 0x00
+#define TM6010_REQ07_R01_VIDEO_CONTROL1			0x07, 0x01
+#define TM6010_REQ07_R02_VIDEO_CONTROL2			0x07, 0x02
+#define TM6010_REQ07_R03_YC_SEP_CONTROL			0x07, 0x03
+#define TM6010_REQ07_R04_LUMA_HAGC_CONTROL		0x07, 0x04
+#define TM6010_REQ07_R05_NOISE_THRESHOLD		0x07, 0x05
+#define TM6010_REQ07_R06_AGC_GATE_THRESHOLD		0x07, 0x06
+#define TM6010_REQ07_R07_OUTPUT_CONTROL			0x07, 0x07
+#define TM6010_REQ07_R08_LUMA_CONTRAST_ADJ		0x07, 0x08
+#define TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ		0x07, 0x09
+#define TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ		0x07, 0x0a
+#define TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ		0x07, 0x0b
+#define TM6010_REQ07_R0C_CHROMA_AGC_CONTROL		0x07, 0x0c
+#define TM6010_REQ07_R0D_CHROMA_KILL_LEVEL		0x07, 0x0d
+#define TM6010_REQ07_R0F_CHROMA_AUTO_POSITION		0x07, 0x0f
+#define TM6010_REQ07_R10_AGC_PEAK_NOMINAL		0x07, 0x10
+#define TM6010_REQ07_R11_AGC_PEAK_CONTROL		0x07, 0x11
+#define TM6010_REQ07_R12_AGC_GATE_STARTH		0x07, 0x12
+#define TM6010_REQ07_R13_AGC_GATE_STARTL		0x07, 0x13
+#define TM6010_REQ07_R14_AGC_GATE_WIDTH			0x07, 0x14
+#define TM6010_REQ07_R15_AGC_BP_DELAY			0x07, 0x15
+#define TM6010_REQ07_R16_LOCK_COUNT			0x07, 0x16
+#define TM6010_REQ07_R17_HLOOP_MAXSTATE			0x07, 0x17
+#define TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3		0x07, 0x18
+#define TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2		0x07, 0x19
+#define TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1		0x07, 0x1a
+#define TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0		0x07, 0x1b
+#define TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3		0x07, 0x1c
+#define TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2		0x07, 0x1d
+#define TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1		0x07, 0x1e
+#define TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0		0x07, 0x1f
+#define TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME		0x07, 0x20
+#define TM6010_REQ07_R21_HSYNC_PHASE_OFFSET		0x07, 0x21
+#define TM6010_REQ07_R22_HSYNC_PLL_START_TIME		0x07, 0x22
+#define TM6010_REQ07_R23_HSYNC_PLL_END_TIME		0x07, 0x23
+#define TM6010_REQ07_R24_HSYNC_TIP_START_TIME		0x07, 0x24
+#define TM6010_REQ07_R25_HSYNC_TIP_END_TIME		0x07, 0x25
+#define TM6010_REQ07_R26_HSYNC_RISING_EDGE_START	0x07, 0x26
+#define TM6010_REQ07_R27_HSYNC_RISING_EDGE_END		0x07, 0x27
+#define TM6010_REQ07_R28_BACKPORCH_START		0x07, 0x28
+#define TM6010_REQ07_R29_BACKPORCH_END			0x07, 0x29
+#define TM6010_REQ07_R2A_HSYNC_FILTER_START		0x07, 0x2a
+#define TM6010_REQ07_R2B_HSYNC_FILTER_END		0x07, 0x2b
+#define TM6010_REQ07_R2C_CHROMA_BURST_START		0x07, 0x2c
+#define TM6010_REQ07_R2D_CHROMA_BURST_END		0x07, 0x2d
+#define TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART		0x07, 0x2e
+#define TM6010_REQ07_R2F_ACTIVE_VIDEO_HWIDTH		0x07, 0x2f
+#define TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART		0x07, 0x30
+#define TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT		0x07, 0x31
+#define TM6010_REQ07_R32_VSYNC_HLOCK_MIN		0x07, 0x32
+#define TM6010_REQ07_R33_VSYNC_HLOCK_MAX		0x07, 0x33
+#define TM6010_REQ07_R34_VSYNC_AGC_MIN			0x07, 0x34
+#define TM6010_REQ07_R35_VSYNC_AGC_MAX			0x07, 0x35
+#define TM6010_REQ07_R36_VSYNC_VBI_MIN			0x07, 0x36
+#define TM6010_REQ07_R37_VSYNC_VBI_MAX			0x07, 0x37
+#define TM6010_REQ07_R38_VSYNC_THRESHOLD		0x07, 0x38
+#define TM6010_REQ07_R39_VSYNC_TIME_CONSTANT		0x07, 0x39
+#define TM6010_REQ07_R3A_STATUS1			0x07, 0x3a
+#define TM6010_REQ07_R3B_STATUS2			0x07, 0x3b
+#define TM6010_REQ07_R3C_STATUS3			0x07, 0x3c
+#define TM6010_REQ07_R3F_RESET				0x07, 0x3f
+#define TM6010_REQ07_R40_TELETEXT_VBI_CODE0		0x07, 0x40
+#define TM6010_REQ07_R41_TELETEXT_VBI_CODE1		0x07, 0x41
+#define TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL		0x07, 0x42
+#define TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7		0x07, 0x43
+#define TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8		0x07, 0x44
+#define TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9		0x07, 0x45
+#define TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10		0x07, 0x46
+#define TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11		0x07, 0x47
+#define TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12		0x07, 0x48
+#define TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13		0x07, 0x49
+#define TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14		0x07, 0x4a
+#define TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15		0x07, 0x4b
+#define TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16		0x07, 0x4c
+#define TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17		0x07, 0x4d
+#define TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18		0x07, 0x4e
+#define TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19		0x07, 0x4f
+#define TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20		0x07, 0x50
+#define TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21		0x07, 0x51
+#define TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22		0x07, 0x52
+#define TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23		0x07, 0x53
+#define TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES		0x07, 0x54
+#define TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN		0x07, 0x55
+#define TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN		0x07, 0x56
+#define TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN		0x07, 0x57
+#define TM6010_REQ07_R58_VBI_CAPTION_DTO1		0x07, 0x58
+#define TM6010_REQ07_R59_VBI_CAPTION_DTO0		0x07, 0x59
+#define TM6010_REQ07_R5A_VBI_TELETEXT_DTO1		0x07, 0x5a
+#define TM6010_REQ07_R5B_VBI_TELETEXT_DTO0		0x07, 0x5b
+#define TM6010_REQ07_R5C_VBI_WSS625_DTO1		0x07, 0x5c
+#define TM6010_REQ07_R5D_VBI_WSS625_DTO0		0x07, 0x5d
+#define TM6010_REQ07_R5E_VBI_CAPTION_FRAME_START	0x07, 0x5e
+#define TM6010_REQ07_R5F_VBI_WSS625_FRAME_START		0x07, 0x5f
+#define TM6010_REQ07_R60_TELETEXT_FRAME_START		0x07, 0x60
+#define TM6010_REQ07_R61_VBI_CCDATA1			0x07, 0x61
+#define TM6010_REQ07_R62_VBI_CCDATA2			0x07, 0x62
+#define TM6010_REQ07_R63_VBI_WSS625_DATA1		0x07, 0x63
+#define TM6010_REQ07_R64_VBI_WSS625_DATA2		0x07, 0x64
+#define TM6010_REQ07_R65_VBI_DATA_STATUS		0x07, 0x65
+#define TM6010_REQ07_R66_VBI_CAPTION_START		0x07, 0x66
+#define TM6010_REQ07_R67_VBI_WSS625_START		0x07, 0x67
+#define TM6010_REQ07_R68_VBI_TELETEXT_START		0x07, 0x68
+#define TM6010_REQ07_R70_HSYNC_DTO_INC_STATUS3		0x07, 0x70
+#define TM6010_REQ07_R71_HSYNC_DTO_INC_STATUS2		0x07, 0x71
+#define TM6010_REQ07_R72_HSYNC_DTO_INC_STATUS1		0x07, 0x72
+#define TM6010_REQ07_R73_HSYNC_DTO_INC_STATUS0		0x07, 0x73
+#define TM6010_REQ07_R74_CHROMA_DTO_INC_STATUS3		0x07, 0x74
+#define TM6010_REQ07_R75_CHROMA_DTO_INC_STATUS2		0x07, 0x75
+#define TM6010_REQ07_R76_CHROMA_DTO_INC_STATUS1		0x07, 0x76
+#define TM6010_REQ07_R77_CHROMA_DTO_INC_STATUS0		0x07, 0x77
+#define TM6010_REQ07_R78_AGC_AGAIN_STATUS		0x07, 0x78
+#define TM6010_REQ07_R79_AGC_DGAIN_STATUS		0x07, 0x79
+#define TM6010_REQ07_R7A_CHROMA_MAG_STATUS		0x07, 0x7a
+#define TM6010_REQ07_R7B_CHROMA_GAIN_STATUS1		0x07, 0x7b
+#define TM6010_REQ07_R7C_CHROMA_GAIN_STATUS0		0x07, 0x7c
+#define TM6010_REQ07_R7D_CORDIC_FREQ_STATUS		0x07, 0x7d
+#define TM6010_REQ07_R7F_STATUS_NOISE			0x07, 0x7f
+#define TM6010_REQ07_R80_COMB_FILTER_TRESHOLD		0x07, 0x80
+#define TM6010_REQ07_R82_COMB_FILTER_CONFIG		0x07, 0x82
+#define TM6010_REQ07_R83_CHROMA_LOCK_CONFIG		0x07, 0x83
+#define TM6010_REQ07_R84_NOISE_NTSC_C			0x07, 0x84
+#define TM6010_REQ07_R85_NOISE_PAL_C			0x07, 0x85
+#define TM6010_REQ07_R86_NOISE_PHASE_C			0x07, 0x86
+#define TM6010_REQ07_R87_NOISE_PHASE_Y			0x07, 0x87
+#define TM6010_REQ07_R8A_CHROMA_LOOPFILTER_STATE	0x07, 0x8a
+#define TM6010_REQ07_R8B_CHROMA_HRESAMPLER		0x07, 0x8b
+#define TM6010_REQ07_R8D_CPUMP_DELAY_ADJ		0x07, 0x8d
+#define TM6010_REQ07_R8E_CPUMP_ADJ			0x07, 0x8e
+#define TM6010_REQ07_R8F_CPUMP_DELAY			0x07, 0x8f
+
+/* Define TM6000/TM6010 Miscellaneous registers */
+#define TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE		0x07, 0xc0
+#define TM6010_REQ07_RC1_TRESHOLD			0x07, 0xc1
+#define TM6010_REQ07_RC2_HSYNC_WIDTH			0x07, 0xc2
+#define TM6010_REQ07_RC3_HSTART1			0x07, 0xc3
+#define TM6010_REQ07_RC4_HSTART0			0x07, 0xc4
+#define TM6010_REQ07_RC5_HEND1				0x07, 0xc5
+#define TM6010_REQ07_RC6_HEND0				0x07, 0xc6
+#define TM6010_REQ07_RC7_VSTART1			0x07, 0xc7
+#define TM6010_REQ07_RC8_VSTART0			0x07, 0xc8
+#define TM6010_REQ07_RC9_VEND1				0x07, 0xc9
+#define TM6010_REQ07_RCA_VEND0				0x07, 0xca
+#define TM6010_REQ07_RCB_DELAY				0x07, 0xcb
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RCC_ACTIVE_IF			0x07, 0xcc
+#define TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE (1 << 5)
+#define TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE (1 << 6)
+#define TM6010_REQ07_RD0_USB_PERIPHERY_CONTROL		0x07, 0xd0
+#define TM6010_REQ07_RD1_ADDR_FOR_REQ1			0x07, 0xd1
+#define TM6010_REQ07_RD2_ADDR_FOR_REQ2			0x07, 0xd2
+#define TM6010_REQ07_RD3_ADDR_FOR_REQ3			0x07, 0xd3
+#define TM6010_REQ07_RD4_ADDR_FOR_REQ4			0x07, 0xd4
+#define TM6010_REQ07_RD5_POWERSAVE			0x07, 0xd5
+#define TM6010_REQ07_RD6_ENDP_REQ1_REQ2			0x07, 0xd6
+#define TM6010_REQ07_RD7_ENDP_REQ3_REQ4			0x07, 0xd7
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR				0x07, 0xd8
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR_BSIZE			0x07, 0xd9
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR_WAKEUP_SEL			0x07, 0xda
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR_WAKEUP_ADD			0x07, 0xdb
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR_LEADER1			0x07, 0xdc
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR_LEADER0			0x07, 0xdd
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR_PULSE_CNT1			0x07, 0xde
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR_PULSE_CNT0			0x07, 0xdf
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE0_DVIDEO_SOURCE			0x07, 0xe0
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE0_DVIDEO_SOURCE_IF		0x07, 0xe1
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE2_OUT_SEL2			0x07, 0xe2
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE3_OUT_SEL1			0x07, 0xe3
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE4_OUT_SEL0			0x07, 0xe4
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE5_REMOTE_WAKEUP			0x07, 0xe5
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE7_PUB_GPIO			0x07, 0xe7
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE8_TYPESEL_MOS_I2S		0x07, 0xe8
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE9_TYPESEL_MOS_TS			0x07, 0xe9
+/* ONLY for TM6010 */
+#define TM6010_REQ07_REA_TYPESEL_MOS_CCIR		0x07, 0xea
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF0_BIST_CRC_RESULT0		0x07, 0xf0
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF1_BIST_CRC_RESULT1		0x07, 0xf1
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF2_BIST_CRC_RESULT2		0x07, 0xf2
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF3_BIST_CRC_RESULT3		0x07, 0xf3
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF4_BIST_ERR_VST2			0x07, 0xf4
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF5_BIST_ERR_VST1			0x07, 0xf5
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF6_BIST_ERR_VST0			0x07, 0xf6
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF7_BIST				0x07, 0xf7
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RFE_POWER_DOWN			0x07, 0xfe
+#define TM6010_REQ07_RFF_SOFT_RESET			0x07, 0xff
+
+/* Define TM6000/TM6010 USB registers */
+#define TM6010_REQ05_R00_MAIN_CTRL		0x05, 0x00
+#define TM6010_REQ05_R01_DEVADDR		0x05, 0x01
+#define TM6010_REQ05_R02_TEST			0x05, 0x02
+#define TM6010_REQ05_R04_SOFN0			0x05, 0x04
+#define TM6010_REQ05_R05_SOFN1			0x05, 0x05
+#define TM6010_REQ05_R06_SOFTM0			0x05, 0x06
+#define TM6010_REQ05_R07_SOFTM1			0x05, 0x07
+#define TM6010_REQ05_R08_PHY_TEST		0x05, 0x08
+#define TM6010_REQ05_R09_VCTL			0x05, 0x09
+#define TM6010_REQ05_R0A_VSTA			0x05, 0x0a
+#define TM6010_REQ05_R0B_CX_CFG			0x05, 0x0b
+#define TM6010_REQ05_R0C_ENDP0_REG0		0x05, 0x0c
+#define TM6010_REQ05_R10_GMASK			0x05, 0x10
+#define TM6010_REQ05_R11_IMASK0			0x05, 0x11
+#define TM6010_REQ05_R12_IMASK1			0x05, 0x12
+#define TM6010_REQ05_R13_IMASK2			0x05, 0x13
+#define TM6010_REQ05_R14_IMASK3			0x05, 0x14
+#define TM6010_REQ05_R15_IMASK4			0x05, 0x15
+#define TM6010_REQ05_R16_IMASK5			0x05, 0x16
+#define TM6010_REQ05_R17_IMASK6			0x05, 0x17
+#define TM6010_REQ05_R18_IMASK7			0x05, 0x18
+#define TM6010_REQ05_R19_ZEROP0			0x05, 0x19
+#define TM6010_REQ05_R1A_ZEROP1			0x05, 0x1a
+#define TM6010_REQ05_R1C_FIFO_EMP0		0x05, 0x1c
+#define TM6010_REQ05_R1D_FIFO_EMP1		0x05, 0x1d
+#define TM6010_REQ05_R20_IRQ_GROUP		0x05, 0x20
+#define TM6010_REQ05_R21_IRQ_SOURCE0		0x05, 0x21
+#define TM6010_REQ05_R22_IRQ_SOURCE1		0x05, 0x22
+#define TM6010_REQ05_R23_IRQ_SOURCE2		0x05, 0x23
+#define TM6010_REQ05_R24_IRQ_SOURCE3		0x05, 0x24
+#define TM6010_REQ05_R25_IRQ_SOURCE4		0x05, 0x25
+#define TM6010_REQ05_R26_IRQ_SOURCE5		0x05, 0x26
+#define TM6010_REQ05_R27_IRQ_SOURCE6		0x05, 0x27
+#define TM6010_REQ05_R28_IRQ_SOURCE7		0x05, 0x28
+#define TM6010_REQ05_R29_SEQ_ERR0		0x05, 0x29
+#define TM6010_REQ05_R2A_SEQ_ERR1		0x05, 0x2a
+#define TM6010_REQ05_R2B_SEQ_ABORT0		0x05, 0x2b
+#define TM6010_REQ05_R2C_SEQ_ABORT1		0x05, 0x2c
+#define TM6010_REQ05_R2D_TX_ZERO0		0x05, 0x2d
+#define TM6010_REQ05_R2E_TX_ZERO1		0x05, 0x2e
+#define TM6010_REQ05_R2F_IDLE_CNT		0x05, 0x2f
+#define TM6010_REQ05_R30_FNO_P1			0x05, 0x30
+#define TM6010_REQ05_R31_FNO_P2			0x05, 0x31
+#define TM6010_REQ05_R32_FNO_P3			0x05, 0x32
+#define TM6010_REQ05_R33_FNO_P4			0x05, 0x33
+#define TM6010_REQ05_R34_FNO_P5			0x05, 0x34
+#define TM6010_REQ05_R35_FNO_P6			0x05, 0x35
+#define TM6010_REQ05_R36_FNO_P7			0x05, 0x36
+#define TM6010_REQ05_R37_FNO_P8			0x05, 0x37
+#define TM6010_REQ05_R38_FNO_P9			0x05, 0x38
+#define TM6010_REQ05_R30_FNO_P10		0x05, 0x39
+#define TM6010_REQ05_R30_FNO_P11		0x05, 0x3a
+#define TM6010_REQ05_R30_FNO_P12		0x05, 0x3b
+#define TM6010_REQ05_R30_FNO_P13		0x05, 0x3c
+#define TM6010_REQ05_R30_FNO_P14		0x05, 0x3d
+#define TM6010_REQ05_R30_FNO_P15		0x05, 0x3e
+#define TM6010_REQ05_R40_IN_MAXPS_LOW1		0x05, 0x40
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH1		0x05, 0x41
+#define TM6010_REQ05_R42_IN_MAXPS_LOW2		0x05, 0x42
+#define TM6010_REQ05_R43_IN_MAXPS_HIGH2		0x05, 0x43
+#define TM6010_REQ05_R44_IN_MAXPS_LOW3		0x05, 0x44
+#define TM6010_REQ05_R45_IN_MAXPS_HIGH3		0x05, 0x45
+#define TM6010_REQ05_R46_IN_MAXPS_LOW4		0x05, 0x46
+#define TM6010_REQ05_R47_IN_MAXPS_HIGH4		0x05, 0x47
+#define TM6010_REQ05_R48_IN_MAXPS_LOW5		0x05, 0x48
+#define TM6010_REQ05_R49_IN_MAXPS_HIGH5		0x05, 0x49
+#define TM6010_REQ05_R4A_IN_MAXPS_LOW6		0x05, 0x4a
+#define TM6010_REQ05_R4B_IN_MAXPS_HIGH6		0x05, 0x4b
+#define TM6010_REQ05_R4C_IN_MAXPS_LOW7		0x05, 0x4c
+#define TM6010_REQ05_R4D_IN_MAXPS_HIGH7		0x05, 0x4d
+#define TM6010_REQ05_R4E_IN_MAXPS_LOW8		0x05, 0x4e
+#define TM6010_REQ05_R4F_IN_MAXPS_HIGH8		0x05, 0x4f
+#define TM6010_REQ05_R50_IN_MAXPS_LOW9		0x05, 0x50
+#define TM6010_REQ05_R51_IN_MAXPS_HIGH9		0x05, 0x51
+#define TM6010_REQ05_R40_IN_MAXPS_LOW10		0x05, 0x52
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH10	0x05, 0x53
+#define TM6010_REQ05_R40_IN_MAXPS_LOW11		0x05, 0x54
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH11	0x05, 0x55
+#define TM6010_REQ05_R40_IN_MAXPS_LOW12		0x05, 0x56
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH12	0x05, 0x57
+#define TM6010_REQ05_R40_IN_MAXPS_LOW13		0x05, 0x58
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH13	0x05, 0x59
+#define TM6010_REQ05_R40_IN_MAXPS_LOW14		0x05, 0x5a
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH14	0x05, 0x5b
+#define TM6010_REQ05_R40_IN_MAXPS_LOW15		0x05, 0x5c
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH15	0x05, 0x5d
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW1		0x05, 0x60
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH1	0x05, 0x61
+#define TM6010_REQ05_R62_OUT_MAXPS_LOW2		0x05, 0x62
+#define TM6010_REQ05_R63_OUT_MAXPS_HIGH2	0x05, 0x63
+#define TM6010_REQ05_R64_OUT_MAXPS_LOW3		0x05, 0x64
+#define TM6010_REQ05_R65_OUT_MAXPS_HIGH3	0x05, 0x65
+#define TM6010_REQ05_R66_OUT_MAXPS_LOW4		0x05, 0x66
+#define TM6010_REQ05_R67_OUT_MAXPS_HIGH4	0x05, 0x67
+#define TM6010_REQ05_R68_OUT_MAXPS_LOW5		0x05, 0x68
+#define TM6010_REQ05_R69_OUT_MAXPS_HIGH5	0x05, 0x69
+#define TM6010_REQ05_R6A_OUT_MAXPS_LOW6		0x05, 0x6a
+#define TM6010_REQ05_R6B_OUT_MAXPS_HIGH6	0x05, 0x6b
+#define TM6010_REQ05_R6C_OUT_MAXPS_LOW7		0x05, 0x6c
+#define TM6010_REQ05_R6D_OUT_MAXPS_HIGH7	0x05, 0x6d
+#define TM6010_REQ05_R6E_OUT_MAXPS_LOW8		0x05, 0x6e
+#define TM6010_REQ05_R6F_OUT_MAXPS_HIGH8	0x05, 0x6f
+#define TM6010_REQ05_R70_OUT_MAXPS_LOW9		0x05, 0x70
+#define TM6010_REQ05_R71_OUT_MAXPS_HIGH9	0x05, 0x71
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW10	0x05, 0x72
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH10	0x05, 0x73
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW11	0x05, 0x74
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH11	0x05, 0x75
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW12	0x05, 0x76
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH12	0x05, 0x77
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW13	0x05, 0x78
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH13	0x05, 0x79
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW14	0x05, 0x7a
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH14	0x05, 0x7b
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW15	0x05, 0x7c
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH15	0x05, 0x7d
+#define TM6010_REQ05_R80_FIFO0			0x05, 0x80
+#define TM6010_REQ05_R81_FIFO1			0x05, 0x81
+#define TM6010_REQ05_R82_FIFO2			0x05, 0x82
+#define TM6010_REQ05_R83_FIFO3			0x05, 0x83
+#define TM6010_REQ05_R84_FIFO4			0x05, 0x84
+#define TM6010_REQ05_R85_FIFO5			0x05, 0x85
+#define TM6010_REQ05_R86_FIFO6			0x05, 0x86
+#define TM6010_REQ05_R87_FIFO7			0x05, 0x87
+#define TM6010_REQ05_R88_FIFO8			0x05, 0x88
+#define TM6010_REQ05_R89_FIFO9			0x05, 0x89
+#define TM6010_REQ05_R81_FIFO10			0x05, 0x8a
+#define TM6010_REQ05_R81_FIFO11			0x05, 0x8b
+#define TM6010_REQ05_R81_FIFO12			0x05, 0x8c
+#define TM6010_REQ05_R81_FIFO13			0x05, 0x8d
+#define TM6010_REQ05_R81_FIFO14			0x05, 0x8e
+#define TM6010_REQ05_R81_FIFO15			0x05, 0x8f
+#define TM6010_REQ05_R90_CFG_FIFO0		0x05, 0x90
+#define TM6010_REQ05_R91_CFG_FIFO1		0x05, 0x91
+#define TM6010_REQ05_R92_CFG_FIFO2		0x05, 0x92
+#define TM6010_REQ05_R93_CFG_FIFO3		0x05, 0x93
+#define TM6010_REQ05_R94_CFG_FIFO4		0x05, 0x94
+#define TM6010_REQ05_R95_CFG_FIFO5		0x05, 0x95
+#define TM6010_REQ05_R96_CFG_FIFO6		0x05, 0x96
+#define TM6010_REQ05_R97_CFG_FIFO7		0x05, 0x97
+#define TM6010_REQ05_R98_CFG_FIFO8		0x05, 0x98
+#define TM6010_REQ05_R99_CFG_FIFO9		0x05, 0x99
+#define TM6010_REQ05_R91_CFG_FIFO10		0x05, 0x9a
+#define TM6010_REQ05_R91_CFG_FIFO11		0x05, 0x9b
+#define TM6010_REQ05_R91_CFG_FIFO12		0x05, 0x9c
+#define TM6010_REQ05_R91_CFG_FIFO13		0x05, 0x9d
+#define TM6010_REQ05_R91_CFG_FIFO14		0x05, 0x9e
+#define TM6010_REQ05_R91_CFG_FIFO15		0x05, 0x9f
+#define TM6010_REQ05_RA0_CTL_FIFO0		0x05, 0xa0
+#define TM6010_REQ05_RA1_CTL_FIFO1		0x05, 0xa1
+#define TM6010_REQ05_RA2_CTL_FIFO2		0x05, 0xa2
+#define TM6010_REQ05_RA3_CTL_FIFO3		0x05, 0xa3
+#define TM6010_REQ05_RA4_CTL_FIFO4		0x05, 0xa4
+#define TM6010_REQ05_RA5_CTL_FIFO5		0x05, 0xa5
+#define TM6010_REQ05_RA6_CTL_FIFO6		0x05, 0xa6
+#define TM6010_REQ05_RA7_CTL_FIFO7		0x05, 0xa7
+#define TM6010_REQ05_RA8_CTL_FIFO8		0x05, 0xa8
+#define TM6010_REQ05_RA9_CTL_FIFO9		0x05, 0xa9
+#define TM6010_REQ05_RA1_CTL_FIFO10		0x05, 0xaa
+#define TM6010_REQ05_RA1_CTL_FIFO11		0x05, 0xab
+#define TM6010_REQ05_RA1_CTL_FIFO12		0x05, 0xac
+#define TM6010_REQ05_RA1_CTL_FIFO13		0x05, 0xad
+#define TM6010_REQ05_RA1_CTL_FIFO14		0x05, 0xae
+#define TM6010_REQ05_RA1_CTL_FIFO15		0x05, 0xaf
+#define TM6010_REQ05_RB0_BC_LOW_FIFO0		0x05, 0xb0
+#define TM6010_REQ05_RB1_BC_LOW_FIFO1		0x05, 0xb1
+#define TM6010_REQ05_RB2_BC_LOW_FIFO2		0x05, 0xb2
+#define TM6010_REQ05_RB3_BC_LOW_FIFO3		0x05, 0xb3
+#define TM6010_REQ05_RB4_BC_LOW_FIFO4		0x05, 0xb4
+#define TM6010_REQ05_RB5_BC_LOW_FIFO5		0x05, 0xb5
+#define TM6010_REQ05_RB6_BC_LOW_FIFO6		0x05, 0xb6
+#define TM6010_REQ05_RB7_BC_LOW_FIFO7		0x05, 0xb7
+#define TM6010_REQ05_RB8_BC_LOW_FIFO8		0x05, 0xb8
+#define TM6010_REQ05_RB9_BC_LOW_FIFO9		0x05, 0xb9
+#define TM6010_REQ05_RB1_BC_LOW_FIFO10		0x05, 0xba
+#define TM6010_REQ05_RB1_BC_LOW_FIFO11		0x05, 0xbb
+#define TM6010_REQ05_RB1_BC_LOW_FIFO12		0x05, 0xbc
+#define TM6010_REQ05_RB1_BC_LOW_FIFO13		0x05, 0xbd
+#define TM6010_REQ05_RB1_BC_LOW_FIFO14		0x05, 0xbe
+#define TM6010_REQ05_RB1_BC_LOW_FIFO15		0x05, 0xbf
+#define TM6010_REQ05_RC0_DATA_FIFO0		0x05, 0xc0
+#define TM6010_REQ05_RC4_DATA_FIFO1		0x05, 0xc4
+#define TM6010_REQ05_RC8_DATA_FIFO2		0x05, 0xc8
+#define TM6010_REQ05_RCC_DATA_FIFO3		0x05, 0xcc
+#define TM6010_REQ05_RD0_DATA_FIFO4		0x05, 0xd0
+#define TM6010_REQ05_RD4_DATA_FIFO5		0x05, 0xd4
+#define TM6010_REQ05_RD8_DATA_FIFO6		0x05, 0xd8
+#define TM6010_REQ05_RDC_DATA_FIFO7		0x05, 0xdc
+#define TM6010_REQ05_RE0_DATA_FIFO8		0x05, 0xe0
+#define TM6010_REQ05_RE4_DATA_FIFO9		0x05, 0xe4
+#define TM6010_REQ05_RC4_DATA_FIFO10		0x05, 0xe8
+#define TM6010_REQ05_RC4_DATA_FIFO11		0x05, 0xec
+#define TM6010_REQ05_RC4_DATA_FIFO12		0x05, 0xf0
+#define TM6010_REQ05_RC4_DATA_FIFO13		0x05, 0xf4
+#define TM6010_REQ05_RC4_DATA_FIFO14		0x05, 0xf8
+#define TM6010_REQ05_RC4_DATA_FIFO15		0x05, 0xfc
+
+/* Define TM6010 Audio decoder registers */
+/* This core available only in TM6010 */
+#define TM6010_REQ08_R00_A_VERSION		0x08, 0x00
+#define TM6010_REQ08_R01_A_INIT			0x08, 0x01
+#define TM6010_REQ08_R02_A_FIX_GAIN_CTRL	0x08, 0x02
+#define TM6010_REQ08_R03_A_AUTO_GAIN_CTRL	0x08, 0x03
+#define TM6010_REQ08_R04_A_SIF_AMP_CTRL		0x08, 0x04
+#define TM6010_REQ08_R05_A_STANDARD_MOD		0x08, 0x05
+#define TM6010_REQ08_R06_A_SOUND_MOD		0x08, 0x06
+#define TM6010_REQ08_R07_A_LEFT_VOL		0x08, 0x07
+#define TM6010_REQ08_R08_A_RIGHT_VOL		0x08, 0x08
+#define TM6010_REQ08_R09_A_MAIN_VOL		0x08, 0x09
+#define TM6010_REQ08_R0A_A_I2S_MOD		0x08, 0x0a
+#define TM6010_REQ08_R0B_A_ASD_THRES1		0x08, 0x0b
+#define TM6010_REQ08_R0C_A_ASD_THRES2		0x08, 0x0c
+#define TM6010_REQ08_R0D_A_AMD_THRES		0x08, 0x0d
+#define TM6010_REQ08_R0E_A_MONO_THRES1		0x08, 0x0e
+#define TM6010_REQ08_R0F_A_MONO_THRES2		0x08, 0x0f
+#define TM6010_REQ08_R10_A_MUTE_THRES1		0x08, 0x10
+#define TM6010_REQ08_R11_A_MUTE_THRES2		0x08, 0x11
+#define TM6010_REQ08_R12_A_AGC_U		0x08, 0x12
+#define TM6010_REQ08_R13_A_AGC_ERR_T		0x08, 0x13
+#define TM6010_REQ08_R14_A_AGC_GAIN_INIT	0x08, 0x14
+#define TM6010_REQ08_R15_A_AGC_STEP_THR		0x08, 0x15
+#define TM6010_REQ08_R16_A_AGC_GAIN_MAX		0x08, 0x16
+#define TM6010_REQ08_R17_A_AGC_GAIN_MIN		0x08, 0x17
+#define TM6010_REQ08_R18_A_TR_CTRL		0x08, 0x18
+#define TM6010_REQ08_R19_A_FH_2FH_GAIN		0x08, 0x19
+#define TM6010_REQ08_R1A_A_NICAM_SER_MAX	0x08, 0x1a
+#define TM6010_REQ08_R1B_A_NICAM_SER_MIN	0x08, 0x1b
+#define TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT	0x08, 0x1e
+#define TM6010_REQ08_R1F_A_TEST_INTF_SEL	0x08, 0x1f
+#define TM6010_REQ08_R20_A_TEST_PIN_SEL		0x08, 0x20
+#define TM6010_REQ08_R21_A_AGC_ERR		0x08, 0x21
+#define TM6010_REQ08_R22_A_AGC_GAIN		0x08, 0x22
+#define TM6010_REQ08_R23_A_NICAM_INFO		0x08, 0x23
+#define TM6010_REQ08_R24_A_SER			0x08, 0x24
+#define TM6010_REQ08_R25_A_C1_AMP		0x08, 0x25
+#define TM6010_REQ08_R26_A_C2_AMP		0x08, 0x26
+#define TM6010_REQ08_R27_A_NOISE_AMP		0x08, 0x27
+#define TM6010_REQ08_R28_A_AUDIO_MODE_RES	0x08, 0x28
+
+/* Define TM6010 Video ADC registers */
+#define TM6010_REQ08_RE0_ADC_REF		0x08, 0xe0
+#define TM6010_REQ08_RE1_DAC_CLMP		0x08, 0xe1
+#define TM6010_REQ08_RE2_POWER_DOWN_CTRL1	0x08, 0xe2
+#define TM6010_REQ08_RE3_ADC_IN1_SEL		0x08, 0xe3
+#define TM6010_REQ08_RE4_ADC_IN2_SEL		0x08, 0xe4
+#define TM6010_REQ08_RE5_GAIN_PARAM		0x08, 0xe5
+#define TM6010_REQ08_RE6_POWER_DOWN_CTRL2	0x08, 0xe6
+#define TM6010_REQ08_RE7_REG_GAIN_Y		0x08, 0xe7
+#define TM6010_REQ08_RE8_REG_GAIN_C		0x08, 0xe8
+#define TM6010_REQ08_RE9_BIAS_CTRL		0x08, 0xe9
+#define TM6010_REQ08_REA_BUFF_DRV_CTRL		0x08, 0xea
+#define TM6010_REQ08_REB_SIF_GAIN_CTRL		0x08, 0xeb
+#define TM6010_REQ08_REC_REVERSE_YC_CTRL	0x08, 0xec
+#define TM6010_REQ08_RED_GAIN_SEL		0x08, 0xed
+
+/* Define TM6010 Audio ADC registers */
+#define TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG	0x08, 0xf0
+#define TM6010_REQ08_RF1_AADC_POWER_DOWN	0x08, 0xf1
+#define TM6010_REQ08_RF2_LEFT_CHANNEL_VOL	0x08, 0xf2
+#define TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL	0x08, 0xf3
diff -druN linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-stds.c linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-stds.c
--- linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-stds.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-stds.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,659 @@
+/*
+ *  tm6000-stds.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2007 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 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.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/kernel.h>
+#include "tm6000.h"
+#include "tm6000-regs.h"
+
+static unsigned int tm6010_a_mode;
+module_param(tm6010_a_mode, int, 0644);
+MODULE_PARM_DESC(tm6010_a_mode, "set tm6010 sif audio mode");
+
+struct tm6000_reg_settings {
+	unsigned char req;
+	unsigned char reg;
+	unsigned char value;
+};
+
+
+struct tm6000_std_settings {
+	v4l2_std_id id;
+	struct tm6000_reg_settings *common;
+};
+
+static struct tm6000_reg_settings composite_pal_m[] = {
+	{ TM6010_REQ07_R3F_RESET, 0x01 },
+	{ TM6010_REQ07_R00_VIDEO_CONTROL0, 0x04 },
+	{ TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+	{ TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+	{ TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
+	{ TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+	{ TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+	{ TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83 },
+	{ TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a },
+	{ TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0 },
+	{ TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+	{ TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+	{ TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+	{ TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+	{ TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+	{ TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x20 },
+	{ TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+	{ TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+	{ TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+	{ TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+	{ TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+	{ TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+	{ TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+	{ TM6010_REQ07_R3F_RESET, 0x00 },
+	{ 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings composite_pal_nc[] = {
+	{ TM6010_REQ07_R3F_RESET, 0x01 },
+	{ TM6010_REQ07_R00_VIDEO_CONTROL0, 0x36 },
+	{ TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+	{ TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+	{ TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
+	{ TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+	{ TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+	{ TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91 },
+	{ TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f },
+	{ TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c },
+	{ TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+	{ TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+	{ TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+	{ TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+	{ TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+	{ TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
+	{ TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+	{ TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+	{ TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+	{ TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+	{ TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+	{ TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+	{ TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+	{ TM6010_REQ07_R3F_RESET, 0x00 },
+	{ 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings composite_pal[] = {
+	{ TM6010_REQ07_R3F_RESET, 0x01 },
+	{ TM6010_REQ07_R00_VIDEO_CONTROL0, 0x32 },
+	{ TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+	{ TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+	{ TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
+	{ TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+	{ TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25 },
+	{ TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5 },
+	{ TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63 },
+	{ TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50 },
+	{ TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+	{ TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+	{ TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+	{ TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+	{ TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+	{ TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
+	{ TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+	{ TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+	{ TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+	{ TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+	{ TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+	{ TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+	{ TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+	{ TM6010_REQ07_R3F_RESET, 0x00 },
+	{ 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings composite_secam[] = {
+	{ TM6010_REQ07_R3F_RESET, 0x01 },
+	{ TM6010_REQ07_R00_VIDEO_CONTROL0, 0x38 },
+	{ TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+	{ TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+	{ TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
+	{ TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+	{ TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24 },
+	{ TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92 },
+	{ TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8 },
+	{ TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed },
+	{ TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+	{ TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+	{ TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+	{ TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+	{ TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+	{ TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
+	{ TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+	{ TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c },
+	{ TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18 },
+	{ TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+	{ TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xff },
+	{ TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+	{ TM6010_REQ07_R3F_RESET, 0x00 },
+	{ 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings composite_ntsc[] = {
+	{ TM6010_REQ07_R3F_RESET, 0x01 },
+	{ TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
+	{ TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f },
+	{ TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+	{ TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
+	{ TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+	{ TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+	{ TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
+	{ TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
+	{ TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
+	{ TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+	{ TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+	{ TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+	{ TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+	{ TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+	{ TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+	{ TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+	{ TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
+	{ TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+	{ TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+	{ TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+	{ TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd },
+	{ TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+	{ TM6010_REQ07_R3F_RESET, 0x00 },
+	{ 0, 0, 0 }
+};
+
+static struct tm6000_std_settings composite_stds[] = {
+	{ .id = V4L2_STD_PAL_M, .common = composite_pal_m, },
+	{ .id = V4L2_STD_PAL_Nc, .common = composite_pal_nc, },
+	{ .id = V4L2_STD_PAL, .common = composite_pal, },
+	{ .id = V4L2_STD_SECAM, .common = composite_secam, },
+	{ .id = V4L2_STD_NTSC, .common = composite_ntsc, },
+};
+
+static struct tm6000_reg_settings svideo_pal_m[] = {
+	{ TM6010_REQ07_R3F_RESET, 0x01 },
+	{ TM6010_REQ07_R00_VIDEO_CONTROL0, 0x05 },
+	{ TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+	{ TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+	{ TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
+	{ TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+	{ TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+	{ TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83 },
+	{ TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a },
+	{ TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0 },
+	{ TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+	{ TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+	{ TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+	{ TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+	{ TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+	{ TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+	{ TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+	{ TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+	{ TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+	{ TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+	{ TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+	{ TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+	{ TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+	{ TM6010_REQ07_R3F_RESET, 0x00 },
+	{ 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings svideo_pal_nc[] = {
+	{ TM6010_REQ07_R3F_RESET, 0x01 },
+	{ TM6010_REQ07_R00_VIDEO_CONTROL0, 0x37 },
+	{ TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+	{ TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+	{ TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
+	{ TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+	{ TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+	{ TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91 },
+	{ TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f },
+	{ TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c },
+	{ TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+	{ TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+	{ TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+	{ TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+	{ TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+	{ TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+	{ TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+	{ TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+	{ TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+	{ TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+	{ TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+	{ TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+	{ TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+	{ TM6010_REQ07_R3F_RESET, 0x00 },
+	{ 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings svideo_pal[] = {
+	{ TM6010_REQ07_R3F_RESET, 0x01 },
+	{ TM6010_REQ07_R00_VIDEO_CONTROL0, 0x33 },
+	{ TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+	{ TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+	{ TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
+	{ TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30 },
+	{ TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25 },
+	{ TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5 },
+	{ TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63 },
+	{ TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50 },
+	{ TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+	{ TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+	{ TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+	{ TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+	{ TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+	{ TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a },
+	{ TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+	{ TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+	{ TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+	{ TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+	{ TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+	{ TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+	{ TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+	{ TM6010_REQ07_R3F_RESET, 0x00 },
+	{ 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings svideo_secam[] = {
+	{ TM6010_REQ07_R3F_RESET, 0x01 },
+	{ TM6010_REQ07_R00_VIDEO_CONTROL0, 0x39 },
+	{ TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+	{ TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+	{ TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03 },
+	{ TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+	{ TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24 },
+	{ TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92 },
+	{ TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8 },
+	{ TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed },
+	{ TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+	{ TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+	{ TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+	{ TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+	{ TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+	{ TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a },
+	{ TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+	{ TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c },
+	{ TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18 },
+	{ TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+	{ TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xff },
+	{ TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+	{ TM6010_REQ07_R3F_RESET, 0x00 },
+	{ 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings svideo_ntsc[] = {
+	{ TM6010_REQ07_R3F_RESET, 0x01 },
+	{ TM6010_REQ07_R00_VIDEO_CONTROL0, 0x01 },
+	{ TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f },
+	{ TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+	{ TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03 },
+	{ TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30 },
+	{ TM6010_REQ07_R17_HLOOP_MAXSTATE, 0x8b },
+	{ TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+	{ TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
+	{ TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
+	{ TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
+	{ TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+	{ TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+	{ TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+	{ TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+	{ TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+	{ TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+	{ TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+	{ TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
+	{ TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+	{ TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+	{ TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+	{ TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd },
+	{ TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+	{ TM6010_REQ07_R3F_RESET, 0x00 },
+	{ 0, 0, 0 }
+};
+
+static struct tm6000_std_settings svideo_stds[] = {
+	{ .id = V4L2_STD_PAL_M, .common = svideo_pal_m, },
+	{ .id = V4L2_STD_PAL_Nc, .common = svideo_pal_nc, },
+	{ .id = V4L2_STD_PAL, .common = svideo_pal, },
+	{ .id = V4L2_STD_SECAM, .common = svideo_secam, },
+	{ .id = V4L2_STD_NTSC, .common = svideo_ntsc, },
+};
+
+static int tm6000_set_audio_std(struct tm6000_core *dev)
+{
+	uint8_t areg_02 = 0x04; /* GC1 Fixed gain 0dB */
+	uint8_t areg_05 = 0x01; /* Auto 4.5 = M Japan, Auto 6.5 = DK */
+	uint8_t areg_06 = 0x02; /* Auto de-emphasis, mannual channel mode */
+	uint8_t nicam_flag = 0; /* No NICAM */
+
+	if (dev->radio) {
+		tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00);
+		tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, 0x04);
+		tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00);
+		tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0x80);
+		tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, 0x0c);
+		/* set mono or stereo */
+		if (dev->amode == V4L2_TUNER_MODE_MONO)
+			tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x00);
+		else if (dev->amode == V4L2_TUNER_MODE_STEREO)
+			tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x02);
+		tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x18);
+		tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x0a);
+		tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x40);
+		tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe);
+		tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13);
+		tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80);
+		tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0xff);
+		return 0;
+	}
+
+	switch (tm6010_a_mode) {
+	/* auto */
+	case 0:
+		switch (dev->norm) {
+		case V4L2_STD_NTSC_M_KR:
+			areg_05 |= 0x00;
+			break;
+		case V4L2_STD_NTSC_M_JP:
+			areg_05 |= 0x40;
+			break;
+		case V4L2_STD_NTSC_M:
+		case V4L2_STD_PAL_M:
+		case V4L2_STD_PAL_N:
+			areg_05 |= 0x20;
+			break;
+		case V4L2_STD_PAL_Nc:
+			areg_05 |= 0x60;
+			break;
+		case V4L2_STD_SECAM_L:
+			areg_05 |= 0x00;
+			break;
+		case V4L2_STD_DK:
+			areg_05 |= 0x10;
+			break;
+		}
+		break;
+	/* A2 */
+	case 1:
+		switch (dev->norm) {
+		case V4L2_STD_B:
+		case V4L2_STD_GH:
+			areg_05 = 0x05;
+			break;
+		case V4L2_STD_DK:
+			areg_05 = 0x09;
+			break;
+		}
+		break;
+	/* NICAM */
+	case 2:
+		switch (dev->norm) {
+		case V4L2_STD_B:
+		case V4L2_STD_GH:
+			areg_05 = 0x07;
+			break;
+		case V4L2_STD_DK:
+			areg_05 = 0x06;
+			break;
+		case V4L2_STD_PAL_I:
+			areg_05 = 0x08;
+			break;
+		case V4L2_STD_SECAM_L:
+			areg_05 = 0x0a;
+			areg_02 = 0x02;
+			break;
+		}
+		nicam_flag = 1;
+		break;
+	/* other */
+	case 3:
+		switch (dev->norm) {
+		/* DK3_A2 */
+		case V4L2_STD_DK:
+			areg_05 = 0x0b;
+			break;
+		/* Korea */
+		case V4L2_STD_NTSC_M_KR:
+			areg_05 = 0x04;
+			break;
+		/* EIAJ */
+		case V4L2_STD_NTSC_M_JP:
+			areg_05 = 0x03;
+			break;
+		default:
+			areg_05 = 0x02;
+			break;
+		}
+		break;
+	}
+
+	tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00);
+	tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, areg_02);
+	tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00);
+	tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0xa0);
+	tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, areg_05);
+	tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, areg_06);
+	tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, 0x00);
+	tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, 0x00);
+	tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x08);
+	tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, 0x91);
+	tm6000_set_reg(dev, TM6010_REQ08_R0B_A_ASD_THRES1, 0x20);
+	tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x12);
+	tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x20);
+	tm6000_set_reg(dev, TM6010_REQ08_R0E_A_MONO_THRES1, 0xf0);
+	tm6000_set_reg(dev, TM6010_REQ08_R0F_A_MONO_THRES2, 0x80);
+	tm6000_set_reg(dev, TM6010_REQ08_R10_A_MUTE_THRES1, 0xc0);
+	tm6000_set_reg(dev, TM6010_REQ08_R11_A_MUTE_THRES2, 0x80);
+	tm6000_set_reg(dev, TM6010_REQ08_R12_A_AGC_U, 0x12);
+	tm6000_set_reg(dev, TM6010_REQ08_R13_A_AGC_ERR_T, 0xfe);
+	tm6000_set_reg(dev, TM6010_REQ08_R14_A_AGC_GAIN_INIT, 0x20);
+	tm6000_set_reg(dev, TM6010_REQ08_R15_A_AGC_STEP_THR, 0x14);
+	tm6000_set_reg(dev, TM6010_REQ08_R16_A_AGC_GAIN_MAX, 0xfe);
+	tm6000_set_reg(dev, TM6010_REQ08_R17_A_AGC_GAIN_MIN, 0x01);
+	tm6000_set_reg(dev, TM6010_REQ08_R18_A_TR_CTRL, 0xa0);
+	tm6000_set_reg(dev, TM6010_REQ08_R19_A_FH_2FH_GAIN, 0x32);
+	tm6000_set_reg(dev, TM6010_REQ08_R1A_A_NICAM_SER_MAX, 0x64);
+	tm6000_set_reg(dev, TM6010_REQ08_R1B_A_NICAM_SER_MIN, 0x20);
+	tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1c, 0x00);
+	tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1d, 0x00);
+	tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13);
+	tm6000_set_reg(dev, TM6010_REQ08_R1F_A_TEST_INTF_SEL, 0x00);
+	tm6000_set_reg(dev, TM6010_REQ08_R20_A_TEST_PIN_SEL, 0x00);
+	tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80);
+
+	return 0;
+}
+
+void tm6000_get_std_res(struct tm6000_core *dev)
+{
+	/* Currently, those are the only supported resoltions */
+	if (dev->norm & V4L2_STD_525_60)
+		dev->height = 480;
+	else
+		dev->height = 576;
+
+	dev->width = 720;
+}
+
+static int tm6000_load_std(struct tm6000_core *dev, struct tm6000_reg_settings *set)
+{
+	int i, rc;
+
+	/* Load board's initialization table */
+	for (i = 0; set[i].req; i++) {
+		rc = tm6000_set_reg(dev, set[i].req, set[i].reg, set[i].value);
+		if (rc < 0) {
+			printk(KERN_ERR "Error %i while setting "
+			       "req %d, reg %d to value %d\n",
+			       rc, set[i].req, set[i].reg, set[i].value);
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+int tm6000_set_standard(struct tm6000_core *dev)
+{
+	struct tm6000_input *input;
+	int i, rc = 0;
+	u8 reg_07_fe = 0x8a;
+	u8 reg_08_f1 = 0xfc;
+	u8 reg_08_e2 = 0xf0;
+	u8 reg_08_e6 = 0x0f;
+
+	tm6000_get_std_res(dev);
+
+	if (!dev->radio)
+		input = &dev->vinput[dev->input];
+	else
+		input = &dev->rinput;
+
+	if (dev->dev_type == TM6010) {
+		switch (input->vmux) {
+		case TM6000_VMUX_VIDEO_A:
+			tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4);
+			tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1);
+			tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0);
+			tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
+			tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe8);
+			reg_07_fe |= 0x01;
+			break;
+		case TM6000_VMUX_VIDEO_B:
+			tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8);
+			tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1);
+			tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0);
+			tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
+			tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe8);
+			reg_07_fe |= 0x01;
+			break;
+		case TM6000_VMUX_VIDEO_AB:
+			tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc);
+			tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8);
+			reg_08_e6 = 0x00;
+			tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2);
+			tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0);
+			tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
+			tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe0);
+			break;
+		default:
+			break;
+		}
+		switch (input->amux) {
+		case TM6000_AMUX_ADC1:
+			tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+				0x00, 0x0f);
+			break;
+		case TM6000_AMUX_ADC2:
+			tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+				0x08, 0x0f);
+			break;
+		case TM6000_AMUX_SIF1:
+			reg_08_e2 |= 0x02;
+			reg_08_e6 = 0x08;
+			reg_07_fe |= 0x40;
+			reg_08_f1 |= 0x02;
+			tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3);
+			tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+				0x02, 0x0f);
+			break;
+		case TM6000_AMUX_SIF2:
+			reg_08_e2 |= 0x02;
+			reg_08_e6 = 0x08;
+			reg_07_fe |= 0x40;
+			reg_08_f1 |= 0x02;
+			tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf7);
+			tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+				0x02, 0x0f);
+			break;
+		default:
+			break;
+		}
+		tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, reg_08_e2);
+		tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, reg_08_e6);
+		tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, reg_08_f1);
+		tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, reg_07_fe);
+	} else {
+		switch (input->vmux) {
+		case TM6000_VMUX_VIDEO_A:
+			tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10);
+			tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00);
+			tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x0f);
+			tm6000_set_reg(dev,
+			    REQ_03_SET_GET_MCU_PIN, input->v_gpio, 0);
+			break;
+		case TM6000_VMUX_VIDEO_B:
+			tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x00);
+			tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00);
+			tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x0f);
+			tm6000_set_reg(dev,
+			    REQ_03_SET_GET_MCU_PIN, input->v_gpio, 0);
+			break;
+		case TM6000_VMUX_VIDEO_AB:
+			tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10);
+			tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x10);
+			tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00);
+			tm6000_set_reg(dev,
+			    REQ_03_SET_GET_MCU_PIN, input->v_gpio, 1);
+			break;
+		default:
+			break;
+		}
+		switch (input->amux) {
+		case TM6000_AMUX_ADC1:
+			tm6000_set_reg_mask(dev,
+				TM6000_REQ07_REB_VADC_AADC_MODE, 0x00, 0x0f);
+			break;
+		case TM6000_AMUX_ADC2:
+			tm6000_set_reg_mask(dev,
+				TM6000_REQ07_REB_VADC_AADC_MODE, 0x04, 0x0f);
+			break;
+		default:
+			break;
+		}
+	}
+	if (input->type == TM6000_INPUT_SVIDEO) {
+		for (i = 0; i < ARRAY_SIZE(svideo_stds); i++) {
+			if (dev->norm & svideo_stds[i].id) {
+				rc = tm6000_load_std(dev, svideo_stds[i].common);
+				goto ret;
+			}
+		}
+		return -EINVAL;
+	} else {
+		for (i = 0; i < ARRAY_SIZE(composite_stds); i++) {
+			if (dev->norm & composite_stds[i].id) {
+				rc = tm6000_load_std(dev, composite_stds[i].common);
+				goto ret;
+			}
+		}
+		return -EINVAL;
+	}
+
+ret:
+	if (rc < 0)
+		return rc;
+
+	if ((dev->dev_type == TM6010) &&
+	    ((input->amux == TM6000_AMUX_SIF1) ||
+	    (input->amux == TM6000_AMUX_SIF2)))
+		tm6000_set_audio_std(dev);
+
+	msleep(40);
+
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-usb-isoc.h linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-usb-isoc.h
--- linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-usb-isoc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-usb-isoc.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,50 @@
+/*
+ *  tm6000-buf.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/videodev2.h>
+
+#define TM6000_URB_MSG_LEN 180
+
+struct usb_isoc_ctl {
+		/* max packet size of isoc transaction */
+	int				max_pkt_size;
+
+		/* number of allocated urbs */
+	int				num_bufs;
+
+		/* urb for isoc transfers */
+	struct urb			**urb;
+
+		/* transfer buffers for isoc transfer */
+	char				**transfer_buffer;
+
+		/* Last buffer command and region */
+	u8				cmd;
+	int				pos, size, pktsize;
+
+		/* Last field: ODD or EVEN? */
+	int				vfield, field;
+
+		/* Stores incomplete commands */
+	u32				tmp_buf;
+	int				tmp_buf_len;
+
+		/* Stores already requested buffers */
+	struct tm6000_buffer		*buf;
+};
diff -druN linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-video.c linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-video.c
--- linux-libre-3.1-gnu/drivers/media/video/tm6000/tm6000-video.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/media/video/tm6000/tm6000-video.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1813 @@
+/*
+ *   tm6000-video.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ *	- Fixed module load/unload
+ *
+ *  This program is free software; 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.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/random.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-ioctl.h>
+#include <media/tuner.h>
+#include <linux/interrupt.h>
+#include <linux/kthread.h>
+#include <linux/highmem.h>
+#include <linux/freezer.h>
+
+#include "tm6000-regs.h"
+#include "tm6000.h"
+
+#define BUFFER_TIMEOUT     msecs_to_jiffies(2000)  /* 2 seconds */
+
+/* Limits minimum and default number of buffers */
+#define TM6000_MIN_BUF 4
+#define TM6000_DEF_BUF 8
+
+#define TM6000_MAX_ISO_PACKETS	46	/* Max number of ISO packets */
+
+/* Declare static vars that will be used as parameters */
+static unsigned int vid_limit = 16;	/* Video memory limit, in Mb */
+static int video_nr = -1;		/* /dev/videoN, -1 for autodetect */
+static int radio_nr = -1;		/* /dev/radioN, -1 for autodetect */
+
+/* Debug level */
+int tm6000_debug;
+EXPORT_SYMBOL_GPL(tm6000_debug);
+
+static const struct v4l2_queryctrl no_ctrl = {
+	.name  = "42",
+	.flags = V4L2_CTRL_FLAG_DISABLED,
+};
+
+/* supported controls */
+static struct v4l2_queryctrl tm6000_qctrl[] = {
+	{
+		.id            = V4L2_CID_BRIGHTNESS,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+		.name          = "Brightness",
+		.minimum       = 0,
+		.maximum       = 255,
+		.step          = 1,
+		.default_value = 54,
+		.flags         = 0,
+	}, {
+		.id            = V4L2_CID_CONTRAST,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+		.name          = "Contrast",
+		.minimum       = 0,
+		.maximum       = 255,
+		.step          = 0x1,
+		.default_value = 119,
+		.flags         = 0,
+	}, {
+		.id            = V4L2_CID_SATURATION,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+		.name          = "Saturation",
+		.minimum       = 0,
+		.maximum       = 255,
+		.step          = 0x1,
+		.default_value = 112,
+		.flags         = 0,
+	}, {
+		.id            = V4L2_CID_HUE,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+		.name          = "Hue",
+		.minimum       = -128,
+		.maximum       = 127,
+		.step          = 0x1,
+		.default_value = 0,
+		.flags         = 0,
+	},
+		/* --- audio --- */
+	{
+		.id            = V4L2_CID_AUDIO_MUTE,
+		.name          = "Mute",
+		.minimum       = 0,
+		.maximum       = 1,
+		.type          = V4L2_CTRL_TYPE_BOOLEAN,
+	}, {
+		.id            = V4L2_CID_AUDIO_VOLUME,
+		.name          = "Volume",
+		.minimum       = -15,
+		.maximum       = 15,
+		.step          = 1,
+		.default_value = 0,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+	}
+};
+
+static const unsigned int CTRLS = ARRAY_SIZE(tm6000_qctrl);
+static int qctl_regs[ARRAY_SIZE(tm6000_qctrl)];
+
+static struct tm6000_fmt format[] = {
+	{
+		.name     = "4:2:2, packed, YVY2",
+		.fourcc   = V4L2_PIX_FMT_YUYV,
+		.depth    = 16,
+	}, {
+		.name     = "4:2:2, packed, UYVY",
+		.fourcc   = V4L2_PIX_FMT_UYVY,
+		.depth    = 16,
+	}, {
+		.name     = "A/V + VBI mux packet",
+		.fourcc   = V4L2_PIX_FMT_TM6000,
+		.depth    = 16,
+	}
+};
+
+static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id)
+{
+	unsigned int i;
+
+	for (i = 0; i < CTRLS; i++)
+		if (tm6000_qctrl[i].id == id)
+			return tm6000_qctrl+i;
+	return NULL;
+}
+
+/* ------------------------------------------------------------------
+ *	DMA and thread functions
+ * ------------------------------------------------------------------
+ */
+
+#define norm_maxw(a) 720
+#define norm_maxh(a) 576
+
+#define norm_minw(a) norm_maxw(a)
+#define norm_minh(a) norm_maxh(a)
+
+/*
+ * video-buf generic routine to get the next available buffer
+ */
+static inline void get_next_buf(struct tm6000_dmaqueue *dma_q,
+			       struct tm6000_buffer   **buf)
+{
+	struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+	char *outp;
+
+	if (list_empty(&dma_q->active)) {
+		dprintk(dev, V4L2_DEBUG_QUEUE, "No active queue to serve\n");
+		*buf = NULL;
+		return;
+	}
+
+	*buf = list_entry(dma_q->active.next,
+			struct tm6000_buffer, vb.queue);
+
+	/* Cleans up buffer - Useful for testing for frame/URB loss */
+	outp = videobuf_to_vmalloc(&(*buf)->vb);
+
+	return;
+}
+
+/*
+ * Announces that a buffer were filled and request the next
+ */
+static inline void buffer_filled(struct tm6000_core *dev,
+				 struct tm6000_dmaqueue *dma_q,
+				 struct tm6000_buffer *buf)
+{
+	/* Advice that buffer was filled */
+	dprintk(dev, V4L2_DEBUG_ISOC, "[%p/%d] wakeup\n", buf, buf->vb.i);
+	buf->vb.state = VIDEOBUF_DONE;
+	buf->vb.field_count++;
+	do_gettimeofday(&buf->vb.ts);
+
+	list_del(&buf->vb.queue);
+	wake_up(&buf->vb.done);
+}
+
+/*
+ * Identify the tm5600/6000 buffer header type and properly handles
+ */
+static int copy_streams(u8 *data, unsigned long len,
+			struct urb *urb)
+{
+	struct tm6000_dmaqueue  *dma_q = urb->context;
+	struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+	u8 *ptr = data, *endp = data+len, c;
+	unsigned long header = 0;
+	int rc = 0;
+	unsigned int cmd, cpysize, pktsize, size, field, block, line, pos = 0;
+	struct tm6000_buffer *vbuf = NULL;
+	char *voutp = NULL;
+	unsigned int linewidth;
+
+	if (!dev->radio) {
+		/* get video buffer */
+		get_next_buf(dma_q, &vbuf);
+
+		if (!vbuf)
+			return rc;
+		voutp = videobuf_to_vmalloc(&vbuf->vb);
+
+		if (!voutp)
+			return 0;
+	}
+
+	for (ptr = data; ptr < endp;) {
+		if (!dev->isoc_ctl.cmd) {
+			/* Header */
+			if (dev->isoc_ctl.tmp_buf_len > 0) {
+				/* from last urb or packet */
+				header = dev->isoc_ctl.tmp_buf;
+				if (4 - dev->isoc_ctl.tmp_buf_len > 0) {
+					memcpy((u8 *)&header +
+						dev->isoc_ctl.tmp_buf_len,
+						ptr,
+						4 - dev->isoc_ctl.tmp_buf_len);
+					ptr += 4 - dev->isoc_ctl.tmp_buf_len;
+				}
+				dev->isoc_ctl.tmp_buf_len = 0;
+			} else {
+				if (ptr + 3 >= endp) {
+					/* have incomplete header */
+					dev->isoc_ctl.tmp_buf_len = endp - ptr;
+					memcpy(&dev->isoc_ctl.tmp_buf, ptr,
+						dev->isoc_ctl.tmp_buf_len);
+					return rc;
+				}
+				/* Seek for sync */
+				for (; ptr < endp - 3; ptr++) {
+					if (*(ptr + 3) == 0x47)
+						break;
+				}
+				/* Get message header */
+				header = *(unsigned long *)ptr;
+				ptr += 4;
+			}
+
+			/* split the header fields */
+			c = (header >> 24) & 0xff;
+			size = ((header & 0x7e) << 1);
+			if (size > 0)
+				size -= 4;
+			block = (header >> 7) & 0xf;
+			field = (header >> 11) & 0x1;
+			line  = (header >> 12) & 0x1ff;
+			cmd   = (header >> 21) & 0x7;
+			/* Validates haeder fields */
+			if (size > TM6000_URB_MSG_LEN)
+				size = TM6000_URB_MSG_LEN;
+			pktsize = TM6000_URB_MSG_LEN;
+			/*
+			 * calculate position in buffer and change the buffer
+			 */
+			switch (cmd) {
+			case TM6000_URB_MSG_VIDEO:
+				if (!dev->radio) {
+					if ((dev->isoc_ctl.vfield != field) &&
+						(field == 1)) {
+						/*
+						 * Announces that a new buffer
+						 * were filled
+						 */
+						buffer_filled(dev, dma_q, vbuf);
+						dprintk(dev, V4L2_DEBUG_ISOC,
+							"new buffer filled\n");
+						get_next_buf(dma_q, &vbuf);
+						if (!vbuf)
+							return rc;
+						voutp = videobuf_to_vmalloc(&vbuf->vb);
+						if (!voutp)
+							return rc;
+						memset(voutp, 0, vbuf->vb.size);
+					}
+					linewidth = vbuf->vb.width << 1;
+					pos = ((line << 1) - field - 1) *
+					linewidth + block * TM6000_URB_MSG_LEN;
+					/* Don't allow to write out of the buffer */
+					if (pos + size > vbuf->vb.size)
+						cmd = TM6000_URB_MSG_ERR;
+					dev->isoc_ctl.vfield = field;
+				}
+				break;
+			case TM6000_URB_MSG_VBI:
+				break;
+			case TM6000_URB_MSG_AUDIO:
+			case TM6000_URB_MSG_PTS:
+				size = pktsize; /* Size is always 180 bytes */
+				break;
+			}
+		} else {
+			/* Continue the last copy */
+			cmd = dev->isoc_ctl.cmd;
+			size = dev->isoc_ctl.size;
+			pos = dev->isoc_ctl.pos;
+			pktsize = dev->isoc_ctl.pktsize;
+			field = dev->isoc_ctl.field;
+		}
+		cpysize = (endp - ptr > size) ? size : endp - ptr;
+		if (cpysize) {
+			/* copy data in different buffers */
+			switch (cmd) {
+			case TM6000_URB_MSG_VIDEO:
+				/* Fills video buffer */
+				if (vbuf)
+					memcpy(&voutp[pos], ptr, cpysize);
+				break;
+			case TM6000_URB_MSG_AUDIO: {
+				int i;
+				for (i = 0; i < cpysize; i += 2)
+					swab16s((u16 *)(ptr + i));
+
+				tm6000_call_fillbuf(dev, TM6000_AUDIO, ptr, cpysize);
+				break;
+			}
+			case TM6000_URB_MSG_VBI:
+				/* Need some code to copy vbi buffer */
+				break;
+			case TM6000_URB_MSG_PTS: {
+				/* Need some code to copy pts */
+				u32 pts;
+				pts = *(u32 *)ptr;
+				dprintk(dev, V4L2_DEBUG_ISOC, "field %d, PTS %x",
+					field, pts);
+				break;
+			}
+			}
+		}
+		if (ptr + pktsize > endp) {
+			/*
+			 * End of URB packet, but cmd processing is not
+			 * complete. Preserve the state for a next packet
+			 */
+			dev->isoc_ctl.pos = pos + cpysize;
+			dev->isoc_ctl.size = size - cpysize;
+			dev->isoc_ctl.cmd = cmd;
+			dev->isoc_ctl.field = field;
+			dev->isoc_ctl.pktsize = pktsize - (endp - ptr);
+			ptr += endp - ptr;
+		} else {
+			dev->isoc_ctl.cmd = 0;
+			ptr += pktsize;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Identify the tm5600/6000 buffer header type and properly handles
+ */
+static int copy_multiplexed(u8 *ptr, unsigned long len,
+			struct urb *urb)
+{
+	struct tm6000_dmaqueue  *dma_q = urb->context;
+	struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+	unsigned int pos = dev->isoc_ctl.pos, cpysize;
+	int rc = 1;
+	struct tm6000_buffer *buf;
+	char *outp = NULL;
+
+	get_next_buf(dma_q, &buf);
+	if (buf)
+		outp = videobuf_to_vmalloc(&buf->vb);
+
+	if (!outp)
+		return 0;
+
+	while (len > 0) {
+		cpysize = min(len, buf->vb.size-pos);
+		memcpy(&outp[pos], ptr, cpysize);
+		pos += cpysize;
+		ptr += cpysize;
+		len -= cpysize;
+		if (pos >= buf->vb.size) {
+			pos = 0;
+			/* Announces that a new buffer were filled */
+			buffer_filled(dev, dma_q, buf);
+			dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n");
+			get_next_buf(dma_q, &buf);
+			if (!buf)
+				break;
+			outp = videobuf_to_vmalloc(&(buf->vb));
+			if (!outp)
+				return rc;
+			pos = 0;
+		}
+	}
+
+	dev->isoc_ctl.pos = pos;
+	return rc;
+}
+
+static inline void print_err_status(struct tm6000_core *dev,
+				     int packet, int status)
+{
+	char *errmsg = "Unknown";
+
+	switch (status) {
+	case -ENOENT:
+		errmsg = "unlinked synchronuously";
+		break;
+	case -ECONNRESET:
+		errmsg = "unlinked asynchronuously";
+		break;
+	case -ENOSR:
+		errmsg = "Buffer error (overrun)";
+		break;
+	case -EPIPE:
+		errmsg = "Stalled (device not responding)";
+		break;
+	case -EOVERFLOW:
+		errmsg = "Babble (bad cable?)";
+		break;
+	case -EPROTO:
+		errmsg = "Bit-stuff error (bad cable?)";
+		break;
+	case -EILSEQ:
+		errmsg = "CRC/Timeout (could be anything)";
+		break;
+	case -ETIME:
+		errmsg = "Device does not respond";
+		break;
+	}
+	if (packet < 0) {
+		dprintk(dev, V4L2_DEBUG_QUEUE, "URB status %d [%s].\n",
+			status, errmsg);
+	} else {
+		dprintk(dev, V4L2_DEBUG_QUEUE, "URB packet %d, status %d [%s].\n",
+			packet, status, errmsg);
+	}
+}
+
+
+/*
+ * Controls the isoc copy of each urb packet
+ */
+static inline int tm6000_isoc_copy(struct urb *urb)
+{
+	struct tm6000_dmaqueue  *dma_q = urb->context;
+	struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+	int i, len = 0, rc = 1, status;
+	char *p;
+
+	if (urb->status < 0) {
+		print_err_status(dev, -1, urb->status);
+		return 0;
+	}
+
+	for (i = 0; i < urb->number_of_packets; i++) {
+		status = urb->iso_frame_desc[i].status;
+
+		if (status < 0) {
+			print_err_status(dev, i, status);
+			continue;
+		}
+
+		len = urb->iso_frame_desc[i].actual_length;
+
+		if (len > 0) {
+			p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+			if (!urb->iso_frame_desc[i].status) {
+				if ((dev->fourcc) == V4L2_PIX_FMT_TM6000) {
+					rc = copy_multiplexed(p, len, urb);
+					if (rc <= 0)
+						return rc;
+				} else {
+					copy_streams(p, len, urb);
+				}
+			}
+		}
+	}
+	return rc;
+}
+
+/* ------------------------------------------------------------------
+ *	URB control
+ * ------------------------------------------------------------------
+ */
+
+/*
+ * IRQ callback, called by URB callback
+ */
+static void tm6000_irq_callback(struct urb *urb)
+{
+	struct tm6000_dmaqueue  *dma_q = urb->context;
+	struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+	int i;
+
+	switch (urb->status) {
+	case 0:
+	case -ETIMEDOUT:
+		break;
+
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+
+	default:
+		tm6000_err("urb completion error %d.\n", urb->status);
+		break;
+	}
+
+	spin_lock(&dev->slock);
+	tm6000_isoc_copy(urb);
+	spin_unlock(&dev->slock);
+
+	/* Reset urb buffers */
+	for (i = 0; i < urb->number_of_packets; i++) {
+		urb->iso_frame_desc[i].status = 0;
+		urb->iso_frame_desc[i].actual_length = 0;
+	}
+
+	urb->status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (urb->status)
+		tm6000_err("urb resubmit failed (error=%i)\n",
+			urb->status);
+}
+
+/*
+ * Stop and Deallocate URBs
+ */
+static void tm6000_uninit_isoc(struct tm6000_core *dev)
+{
+	struct urb *urb;
+	int i;
+
+	dev->isoc_ctl.buf = NULL;
+	for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+		urb = dev->isoc_ctl.urb[i];
+		if (urb) {
+			usb_kill_urb(urb);
+			usb_unlink_urb(urb);
+			if (dev->isoc_ctl.transfer_buffer[i]) {
+				usb_free_coherent(dev->udev,
+						urb->transfer_buffer_length,
+						dev->isoc_ctl.transfer_buffer[i],
+						urb->transfer_dma);
+			}
+			usb_free_urb(urb);
+			dev->isoc_ctl.urb[i] = NULL;
+		}
+		dev->isoc_ctl.transfer_buffer[i] = NULL;
+	}
+
+	kfree(dev->isoc_ctl.urb);
+	kfree(dev->isoc_ctl.transfer_buffer);
+
+	dev->isoc_ctl.urb = NULL;
+	dev->isoc_ctl.transfer_buffer = NULL;
+	dev->isoc_ctl.num_bufs = 0;
+}
+
+/*
+ * Allocate URBs and start IRQ
+ */
+static int tm6000_prepare_isoc(struct tm6000_core *dev)
+{
+	struct tm6000_dmaqueue *dma_q = &dev->vidq;
+	int i, j, sb_size, pipe, size, max_packets, num_bufs = 8;
+	struct urb *urb;
+
+	/* De-allocates all pending stuff */
+	tm6000_uninit_isoc(dev);
+	/* Stop interrupt USB pipe */
+	tm6000_ir_int_stop(dev);
+
+	usb_set_interface(dev->udev,
+			  dev->isoc_in.bInterfaceNumber,
+			  dev->isoc_in.bAlternateSetting);
+
+	/* Start interrupt USB pipe */
+	tm6000_ir_int_start(dev);
+
+	pipe = usb_rcvisocpipe(dev->udev,
+			       dev->isoc_in.endp->desc.bEndpointAddress &
+			       USB_ENDPOINT_NUMBER_MASK);
+
+	size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
+
+	if (size > dev->isoc_in.maxsize)
+		size = dev->isoc_in.maxsize;
+
+	dev->isoc_ctl.max_pkt_size = size;
+
+	max_packets = TM6000_MAX_ISO_PACKETS;
+	sb_size = max_packets * size;
+
+	dev->isoc_ctl.num_bufs = num_bufs;
+
+	dev->isoc_ctl.urb = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
+	if (!dev->isoc_ctl.urb) {
+		tm6000_err("cannot alloc memory for usb buffers\n");
+		return -ENOMEM;
+	}
+
+	dev->isoc_ctl.transfer_buffer = kmalloc(sizeof(void *)*num_bufs,
+				   GFP_KERNEL);
+	if (!dev->isoc_ctl.transfer_buffer) {
+		tm6000_err("cannot allocate memory for usbtransfer\n");
+		kfree(dev->isoc_ctl.urb);
+		return -ENOMEM;
+	}
+
+	dprintk(dev, V4L2_DEBUG_QUEUE, "Allocating %d x %d packets"
+		    " (%d bytes) of %d bytes each to handle %u size\n",
+		    max_packets, num_bufs, sb_size,
+		    dev->isoc_in.maxsize, size);
+
+	/* allocate urbs and transfer buffers */
+	for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+		urb = usb_alloc_urb(max_packets, GFP_KERNEL);
+		if (!urb) {
+			tm6000_err("cannot alloc isoc_ctl.urb %i\n", i);
+			tm6000_uninit_isoc(dev);
+			usb_free_urb(urb);
+			return -ENOMEM;
+		}
+		dev->isoc_ctl.urb[i] = urb;
+
+		dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev,
+			sb_size, GFP_KERNEL, &urb->transfer_dma);
+		if (!dev->isoc_ctl.transfer_buffer[i]) {
+			tm6000_err("unable to allocate %i bytes for transfer"
+					" buffer %i%s\n",
+					sb_size, i,
+					in_interrupt() ? " while in int" : "");
+			tm6000_uninit_isoc(dev);
+			return -ENOMEM;
+		}
+		memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
+
+		usb_fill_bulk_urb(urb, dev->udev, pipe,
+				  dev->isoc_ctl.transfer_buffer[i], sb_size,
+				  tm6000_irq_callback, dma_q);
+		urb->interval = dev->isoc_in.endp->desc.bInterval;
+		urb->number_of_packets = max_packets;
+		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+
+		for (j = 0; j < max_packets; j++) {
+			urb->iso_frame_desc[j].offset = size * j;
+			urb->iso_frame_desc[j].length = size;
+		}
+	}
+
+	return 0;
+}
+
+static int tm6000_start_thread(struct tm6000_core *dev)
+{
+	struct tm6000_dmaqueue *dma_q = &dev->vidq;
+	int i;
+
+	dma_q->frame = 0;
+	dma_q->ini_jiffies = jiffies;
+
+	init_waitqueue_head(&dma_q->wq);
+
+	/* submit urbs and enables IRQ */
+	for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+		int rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
+		if (rc) {
+			tm6000_err("submit of urb %i failed (error=%i)\n", i,
+				   rc);
+			tm6000_uninit_isoc(dev);
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------
+ *	Videobuf operations
+ * ------------------------------------------------------------------
+ */
+
+static int
+buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
+{
+	struct tm6000_fh *fh = vq->priv_data;
+
+	*size = fh->fmt->depth * fh->width * fh->height >> 3;
+	if (0 == *count)
+		*count = TM6000_DEF_BUF;
+
+	if (*count < TM6000_MIN_BUF)
+		*count = TM6000_MIN_BUF;
+
+	while (*size * *count > vid_limit * 1024 * 1024)
+		(*count)--;
+
+	return 0;
+}
+
+static void free_buffer(struct videobuf_queue *vq, struct tm6000_buffer *buf)
+{
+	struct tm6000_fh *fh = vq->priv_data;
+	struct tm6000_core   *dev = fh->dev;
+	unsigned long flags;
+
+	if (in_interrupt())
+		BUG();
+
+	/* We used to wait for the buffer to finish here, but this didn't work
+	   because, as we were keeping the state as VIDEOBUF_QUEUED,
+	   videobuf_queue_cancel marked it as finished for us.
+	   (Also, it could wedge forever if the hardware was misconfigured.)
+
+	   This should be safe; by the time we get here, the buffer isn't
+	   queued anymore. If we ever start marking the buffers as
+	   VIDEOBUF_ACTIVE, it won't be, though.
+	*/
+	spin_lock_irqsave(&dev->slock, flags);
+	if (dev->isoc_ctl.buf == buf)
+		dev->isoc_ctl.buf = NULL;
+	spin_unlock_irqrestore(&dev->slock, flags);
+
+	videobuf_vmalloc_free(&buf->vb);
+	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int
+buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+						enum v4l2_field field)
+{
+	struct tm6000_fh     *fh  = vq->priv_data;
+	struct tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb);
+	struct tm6000_core   *dev = fh->dev;
+	int rc = 0;
+
+	BUG_ON(NULL == fh->fmt);
+
+
+	/* FIXME: It assumes depth=2 */
+	/* The only currently supported format is 16 bits/pixel */
+	buf->vb.size = fh->fmt->depth*fh->width*fh->height >> 3;
+	if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+		return -EINVAL;
+
+	if (buf->fmt       != fh->fmt    ||
+	    buf->vb.width  != fh->width  ||
+	    buf->vb.height != fh->height ||
+	    buf->vb.field  != field) {
+		buf->fmt       = fh->fmt;
+		buf->vb.width  = fh->width;
+		buf->vb.height = fh->height;
+		buf->vb.field  = field;
+		buf->vb.state = VIDEOBUF_NEEDS_INIT;
+	}
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		rc = videobuf_iolock(vq, &buf->vb, NULL);
+		if (rc != 0)
+			goto fail;
+	}
+
+	if (!dev->isoc_ctl.num_bufs) {
+		rc = tm6000_prepare_isoc(dev);
+		if (rc < 0)
+			goto fail;
+
+		rc = tm6000_start_thread(dev);
+		if (rc < 0)
+			goto fail;
+
+	}
+
+	buf->vb.state = VIDEOBUF_PREPARED;
+	return 0;
+
+fail:
+	free_buffer(vq, buf);
+	return rc;
+}
+
+static void
+buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+	struct tm6000_buffer    *buf     = container_of(vb, struct tm6000_buffer, vb);
+	struct tm6000_fh        *fh      = vq->priv_data;
+	struct tm6000_core      *dev     = fh->dev;
+	struct tm6000_dmaqueue  *vidq    = &dev->vidq;
+
+	buf->vb.state = VIDEOBUF_QUEUED;
+	list_add_tail(&buf->vb.queue, &vidq->active);
+}
+
+static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+	struct tm6000_buffer   *buf  = container_of(vb, struct tm6000_buffer, vb);
+
+	free_buffer(vq, buf);
+}
+
+static struct videobuf_queue_ops tm6000_video_qops = {
+	.buf_setup      = buffer_setup,
+	.buf_prepare    = buffer_prepare,
+	.buf_queue      = buffer_queue,
+	.buf_release    = buffer_release,
+};
+
+/* ------------------------------------------------------------------
+ *	IOCTL handling
+ * ------------------------------------------------------------------
+ */
+
+static bool is_res_read(struct tm6000_core *dev, struct tm6000_fh *fh)
+{
+	/* Is the current fh handling it? if so, that's OK */
+	if (dev->resources == fh && dev->is_res_read)
+		return true;
+
+	return false;
+}
+
+static bool is_res_streaming(struct tm6000_core *dev, struct tm6000_fh *fh)
+{
+	/* Is the current fh handling it? if so, that's OK */
+	if (dev->resources == fh)
+		return true;
+
+	return false;
+}
+
+static bool res_get(struct tm6000_core *dev, struct tm6000_fh *fh,
+		   bool is_res_read)
+{
+	/* Is the current fh handling it? if so, that's OK */
+	if (dev->resources == fh && dev->is_res_read == is_res_read)
+		return true;
+
+	/* is it free? */
+	if (dev->resources)
+		return false;
+
+	/* grab it */
+	dev->resources = fh;
+	dev->is_res_read = is_res_read;
+	dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: get\n");
+	return true;
+}
+
+static void res_free(struct tm6000_core *dev, struct tm6000_fh *fh)
+{
+	/* Is the current fh handling it? if so, that's OK */
+	if (dev->resources != fh)
+		return;
+
+	dev->resources = NULL;
+	dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: put\n");
+}
+
+/* ------------------------------------------------------------------
+ *	IOCTL vidioc handling
+ * ------------------------------------------------------------------
+ */
+static int vidioc_querycap(struct file *file, void  *priv,
+					struct v4l2_capability *cap)
+{
+	struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
+
+	strlcpy(cap->driver, "tm6000", sizeof(cap->driver));
+	strlcpy(cap->card, "Trident TVMaster TM5600/6000/6010", sizeof(cap->card));
+	cap->version = TM6000_VERSION;
+	cap->capabilities =	V4L2_CAP_VIDEO_CAPTURE |
+				V4L2_CAP_STREAMING     |
+				V4L2_CAP_AUDIO         |
+				V4L2_CAP_READWRITE;
+
+	if (dev->tuner_type != TUNER_ABSENT)
+		cap->capabilities |= V4L2_CAP_TUNER;
+
+	return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+					struct v4l2_fmtdesc *f)
+{
+	if (unlikely(f->index >= ARRAY_SIZE(format)))
+		return -EINVAL;
+
+	strlcpy(f->description, format[f->index].name, sizeof(f->description));
+	f->pixelformat = format[f->index].fourcc;
+	return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct tm6000_fh  *fh = priv;
+
+	f->fmt.pix.width        = fh->width;
+	f->fmt.pix.height       = fh->height;
+	f->fmt.pix.field        = fh->vb_vidq.field;
+	f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+	f->fmt.pix.bytesperline =
+		(f->fmt.pix.width * fh->fmt->depth) >> 3;
+	f->fmt.pix.sizeimage =
+		f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+	return 0;
+}
+
+static struct tm6000_fmt *format_by_fourcc(unsigned int fourcc)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(format); i++)
+		if (format[i].fourcc == fourcc)
+			return format+i;
+	return NULL;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+			struct v4l2_format *f)
+{
+	struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
+	struct tm6000_fmt *fmt;
+	enum v4l2_field field;
+
+	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+	if (NULL == fmt) {
+		dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Fourcc format (0x%08x)"
+				" invalid.\n", f->fmt.pix.pixelformat);
+		return -EINVAL;
+	}
+
+	field = f->fmt.pix.field;
+
+	if (field == V4L2_FIELD_ANY)
+		field = V4L2_FIELD_SEQ_TB;
+	else if (V4L2_FIELD_INTERLACED != field) {
+		dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Field type invalid.\n");
+		return -EINVAL;
+	}
+
+	tm6000_get_std_res(dev);
+
+	f->fmt.pix.width  = dev->width;
+	f->fmt.pix.height = dev->height;
+
+	f->fmt.pix.width &= ~0x01;
+
+	f->fmt.pix.field = field;
+
+	f->fmt.pix.bytesperline =
+		(f->fmt.pix.width * fmt->depth) >> 3;
+	f->fmt.pix.sizeimage =
+		f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+	return 0;
+}
+
+/*FIXME: This seems to be generic enough to be at videodev2 */
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct tm6000_fh  *fh = priv;
+	struct tm6000_core *dev = fh->dev;
+	int ret = vidioc_try_fmt_vid_cap(file, fh, f);
+	if (ret < 0)
+		return ret;
+
+	fh->fmt           = format_by_fourcc(f->fmt.pix.pixelformat);
+	fh->width         = f->fmt.pix.width;
+	fh->height        = f->fmt.pix.height;
+	fh->vb_vidq.field = f->fmt.pix.field;
+	fh->type          = f->type;
+
+	dev->fourcc       = f->fmt.pix.pixelformat;
+
+	tm6000_set_fourcc_format(dev);
+
+	return 0;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+			   struct v4l2_requestbuffers *p)
+{
+	struct tm6000_fh  *fh = priv;
+
+	return videobuf_reqbufs(&fh->vb_vidq, p);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+			    struct v4l2_buffer *p)
+{
+	struct tm6000_fh  *fh = priv;
+
+	return videobuf_querybuf(&fh->vb_vidq, p);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct tm6000_fh  *fh = priv;
+
+	return videobuf_qbuf(&fh->vb_vidq, p);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct tm6000_fh  *fh = priv;
+
+	return videobuf_dqbuf(&fh->vb_vidq, p,
+				file->f_flags & O_NONBLOCK);
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct tm6000_fh *fh = priv;
+	struct tm6000_core *dev = fh->dev;
+
+	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	if (i != fh->type)
+		return -EINVAL;
+
+	if (!res_get(dev, fh, false))
+		return -EBUSY;
+	return videobuf_streamon(&fh->vb_vidq);
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct tm6000_fh *fh = priv;
+	struct tm6000_core *dev = fh->dev;
+
+	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if (i != fh->type)
+		return -EINVAL;
+
+	videobuf_streamoff(&fh->vb_vidq);
+	res_free(dev, fh);
+
+	return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+	int rc = 0;
+	struct tm6000_fh *fh = priv;
+	struct tm6000_core *dev = fh->dev;
+
+	dev->norm = *norm;
+	rc = tm6000_init_analog_mode(dev);
+
+	fh->width  = dev->width;
+	fh->height = dev->height;
+
+	if (rc < 0)
+		return rc;
+
+	v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
+
+	return 0;
+}
+
+static const char *iname[] = {
+	[TM6000_INPUT_TV] = "Television",
+	[TM6000_INPUT_COMPOSITE1] = "Composite 1",
+	[TM6000_INPUT_COMPOSITE2] = "Composite 2",
+	[TM6000_INPUT_SVIDEO] = "S-Video",
+};
+
+static int vidioc_enum_input(struct file *file, void *priv,
+				struct v4l2_input *i)
+{
+	struct tm6000_fh   *fh = priv;
+	struct tm6000_core *dev = fh->dev;
+	unsigned int n;
+
+	n = i->index;
+	if (n >= 3)
+		return -EINVAL;
+
+	if (!dev->vinput[n].type)
+		return -EINVAL;
+
+	i->index = n;
+
+	if (dev->vinput[n].type == TM6000_INPUT_TV)
+		i->type = V4L2_INPUT_TYPE_TUNER;
+	else
+		i->type = V4L2_INPUT_TYPE_CAMERA;
+
+	strcpy(i->name, iname[dev->vinput[n].type]);
+
+	i->std = TM6000_STD;
+
+	return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	struct tm6000_fh   *fh = priv;
+	struct tm6000_core *dev = fh->dev;
+
+	*i = dev->input;
+
+	return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+	struct tm6000_fh   *fh = priv;
+	struct tm6000_core *dev = fh->dev;
+	int rc = 0;
+
+	if (i >= 3)
+		return -EINVAL;
+	if (!dev->vinput[i].type)
+		return -EINVAL;
+
+	dev->input = i;
+
+	rc = vidioc_s_std(file, priv, &dev->vfd->current_norm);
+
+	return rc;
+}
+
+/* --- controls ---------------------------------------------- */
+static int vidioc_queryctrl(struct file *file, void *priv,
+				struct v4l2_queryctrl *qc)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++)
+		if (qc->id && qc->id == tm6000_qctrl[i].id) {
+			memcpy(qc, &(tm6000_qctrl[i]),
+				sizeof(*qc));
+			return 0;
+		}
+
+	return -EINVAL;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+				struct v4l2_control *ctrl)
+{
+	struct tm6000_fh  *fh = priv;
+	struct tm6000_core *dev    = fh->dev;
+	int  val;
+
+	/* FIXME: Probably, those won't work! Maybe we need shadow regs */
+	switch (ctrl->id) {
+	case V4L2_CID_CONTRAST:
+		val = tm6000_get_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0);
+		break;
+	case V4L2_CID_BRIGHTNESS:
+		val = tm6000_get_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0);
+		return 0;
+	case V4L2_CID_SATURATION:
+		val = tm6000_get_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0);
+		return 0;
+	case V4L2_CID_HUE:
+		val = tm6000_get_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, 0);
+		return 0;
+	case V4L2_CID_AUDIO_MUTE:
+		val = dev->ctl_mute;
+		return 0;
+	case V4L2_CID_AUDIO_VOLUME:
+		val = dev->ctl_volume;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+
+	if (val < 0)
+		return val;
+
+	ctrl->value = val;
+
+	return 0;
+}
+static int vidioc_s_ctrl(struct file *file, void *priv,
+				struct v4l2_control *ctrl)
+{
+	struct tm6000_fh   *fh  = priv;
+	struct tm6000_core *dev = fh->dev;
+	u8  val = ctrl->value;
+
+	switch (ctrl->id) {
+	case V4L2_CID_CONTRAST:
+		tm6000_set_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, val);
+		return 0;
+	case V4L2_CID_BRIGHTNESS:
+		tm6000_set_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, val);
+		return 0;
+	case V4L2_CID_SATURATION:
+		tm6000_set_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, val);
+		return 0;
+	case V4L2_CID_HUE:
+		tm6000_set_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, val);
+		return 0;
+	case V4L2_CID_AUDIO_MUTE:
+		dev->ctl_mute = val;
+		tm6000_tvaudio_set_mute(dev, val);
+		return 0;
+	case V4L2_CID_AUDIO_VOLUME:
+		dev->ctl_volume = val;
+		tm6000_set_volume(dev, val);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct tm6000_fh   *fh  = priv;
+	struct tm6000_core *dev = fh->dev;
+
+	if (unlikely(UNSET == dev->tuner_type))
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	strcpy(t->name, "Television");
+	t->type       = V4L2_TUNER_ANALOG_TV;
+	t->capability = V4L2_TUNER_CAP_NORM;
+	t->rangehigh  = 0xffffffffUL;
+	t->rxsubchans = V4L2_TUNER_SUB_STEREO;
+
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
+
+	t->audmode = dev->amode;
+
+	return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct tm6000_fh   *fh  = priv;
+	struct tm6000_core *dev = fh->dev;
+
+	if (UNSET == dev->tuner_type)
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	dev->amode = t->audmode;
+	dprintk(dev, 3, "audio mode: %x\n", t->audmode);
+
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
+
+	return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct tm6000_fh   *fh  = priv;
+	struct tm6000_core *dev = fh->dev;
+
+	if (unlikely(UNSET == dev->tuner_type))
+		return -EINVAL;
+
+	f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+	f->frequency = dev->freq;
+
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, f);
+
+	return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct tm6000_fh   *fh  = priv;
+	struct tm6000_core *dev = fh->dev;
+
+	if (unlikely(UNSET == dev->tuner_type))
+		return -EINVAL;
+	if (unlikely(f->tuner != 0))
+		return -EINVAL;
+	if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type)
+		return -EINVAL;
+	if (1 == fh->radio && V4L2_TUNER_RADIO != f->type)
+		return -EINVAL;
+
+	dev->freq = f->frequency;
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f);
+
+	return 0;
+}
+
+static int radio_querycap(struct file *file, void *priv,
+					struct v4l2_capability *cap)
+{
+	struct tm6000_fh *fh = file->private_data;
+	struct tm6000_core *dev = fh->dev;
+
+	strcpy(cap->driver, "tm6000");
+	strlcpy(cap->card, dev->name, sizeof(dev->name));
+	sprintf(cap->bus_info, "USB%04x:%04x",
+		le16_to_cpu(dev->udev->descriptor.idVendor),
+		le16_to_cpu(dev->udev->descriptor.idProduct));
+	cap->version = dev->dev_type;
+	cap->capabilities = V4L2_CAP_TUNER |
+			V4L2_CAP_AUDIO     |
+			V4L2_CAP_RADIO     |
+			V4L2_CAP_READWRITE |
+			V4L2_CAP_STREAMING;
+
+	return 0;
+}
+
+static int radio_g_tuner(struct file *file, void *priv,
+					struct v4l2_tuner *t)
+{
+	struct tm6000_fh *fh = file->private_data;
+	struct tm6000_core *dev = fh->dev;
+
+	if (0 != t->index)
+		return -EINVAL;
+
+	memset(t, 0, sizeof(*t));
+	strcpy(t->name, "Radio");
+	t->type = V4L2_TUNER_RADIO;
+	t->rxsubchans = V4L2_TUNER_SUB_STEREO;
+
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
+
+	return 0;
+}
+
+static int radio_s_tuner(struct file *file, void *priv,
+					struct v4l2_tuner *t)
+{
+	struct tm6000_fh *fh = file->private_data;
+	struct tm6000_core *dev = fh->dev;
+
+	if (0 != t->index)
+		return -EINVAL;
+
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
+
+	return 0;
+}
+
+static int radio_enum_input(struct file *file, void *priv,
+					struct v4l2_input *i)
+{
+	struct tm6000_fh *fh = priv;
+	struct tm6000_core *dev = fh->dev;
+
+	if (i->index != 0)
+		return -EINVAL;
+
+	if (!dev->rinput.type)
+		return -EINVAL;
+
+	strcpy(i->name, "Radio");
+	i->type = V4L2_INPUT_TYPE_TUNER;
+
+	return 0;
+}
+
+static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+	struct tm6000_fh *fh = priv;
+	struct tm6000_core *dev = fh->dev;
+
+	if (dev->input != 5)
+		return -EINVAL;
+
+	*i = dev->input - 5;
+
+	return 0;
+}
+
+static int radio_g_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	memset(a, 0, sizeof(*a));
+	strcpy(a->name, "Radio");
+	return 0;
+}
+
+static int radio_s_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	return 0;
+}
+
+static int radio_s_input(struct file *filp, void *priv, unsigned int i)
+{
+	struct tm6000_fh *fh = priv;
+	struct tm6000_core *dev = fh->dev;
+
+	if (i)
+		return -EINVAL;
+
+	if (!dev->rinput.type)
+		return -EINVAL;
+
+	dev->input = i + 5;
+
+	return 0;
+}
+
+static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
+{
+	return 0;
+}
+
+static int radio_queryctrl(struct file *file, void *priv,
+					struct v4l2_queryctrl *c)
+{
+	const struct v4l2_queryctrl *ctrl;
+
+	if (c->id <  V4L2_CID_BASE ||
+	    c->id >= V4L2_CID_LASTP1)
+		return -EINVAL;
+	if (c->id == V4L2_CID_AUDIO_MUTE) {
+		ctrl = ctrl_by_id(c->id);
+		*c = *ctrl;
+	} else
+		*c = no_ctrl;
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------
+	File operations for the device
+   ------------------------------------------------------------------*/
+
+static int tm6000_open(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct tm6000_core *dev = video_drvdata(file);
+	struct tm6000_fh *fh;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	int i, rc;
+	int radio = 0;
+
+	dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: open called (dev=%s)\n",
+		video_device_node_name(vdev));
+
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		break;
+	case VFL_TYPE_VBI:
+		type = V4L2_BUF_TYPE_VBI_CAPTURE;
+		break;
+	case VFL_TYPE_RADIO:
+		radio = 1;
+		break;
+	}
+
+	/* If more than one user, mutex should be added */
+	dev->users++;
+
+	dprintk(dev, V4L2_DEBUG_OPEN, "open dev=%s type=%s users=%d\n",
+		video_device_node_name(vdev), v4l2_type_names[type],
+		dev->users);
+
+	/* allocate + initialize per filehandle data */
+	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+	if (NULL == fh) {
+		dev->users--;
+		return -ENOMEM;
+	}
+
+	file->private_data = fh;
+	fh->dev      = dev;
+	fh->radio    = radio;
+	dev->radio   = radio;
+	fh->type     = type;
+	dev->fourcc  = format[0].fourcc;
+
+	fh->fmt      = format_by_fourcc(dev->fourcc);
+
+	tm6000_get_std_res(dev);
+
+	fh->width = dev->width;
+	fh->height = dev->height;
+
+	dprintk(dev, V4L2_DEBUG_OPEN, "Open: fh=0x%08lx, dev=0x%08lx, "
+						"dev->vidq=0x%08lx\n",
+			(unsigned long)fh, (unsigned long)dev,
+			(unsigned long)&dev->vidq);
+	dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty "
+				"queued=%d\n", list_empty(&dev->vidq.queued));
+	dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty "
+				"active=%d\n", list_empty(&dev->vidq.active));
+
+	/* initialize hardware on analog mode */
+	rc = tm6000_init_analog_mode(dev);
+	if (rc < 0)
+		return rc;
+
+	if (dev->mode != TM6000_MODE_ANALOG) {
+		/* Put all controls at a sane state */
+		for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++)
+			qctl_regs[i] = tm6000_qctrl[i].default_value;
+
+		dev->mode = TM6000_MODE_ANALOG;
+	}
+
+	if (!fh->radio) {
+		videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops,
+				NULL, &dev->slock,
+				fh->type,
+				V4L2_FIELD_INTERLACED,
+				sizeof(struct tm6000_buffer), fh, &dev->lock);
+	} else {
+		dprintk(dev, V4L2_DEBUG_OPEN, "video_open: setting radio device\n");
+		dev->input = 5;
+		tm6000_set_audio_rinput(dev);
+		v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio);
+		tm6000_prepare_isoc(dev);
+		tm6000_start_thread(dev);
+	}
+
+	return 0;
+}
+
+static ssize_t
+tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos)
+{
+	struct tm6000_fh        *fh = file->private_data;
+
+	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		if (!res_get(fh->dev, fh, true))
+			return -EBUSY;
+
+		return videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0,
+					file->f_flags & O_NONBLOCK);
+	}
+	return 0;
+}
+
+static unsigned int
+tm6000_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct tm6000_fh        *fh = file->private_data;
+	struct tm6000_buffer    *buf;
+
+	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
+		return POLLERR;
+
+	if (!!is_res_streaming(fh->dev, fh))
+		return POLLERR;
+
+	if (!is_res_read(fh->dev, fh)) {
+		/* streaming capture */
+		if (list_empty(&fh->vb_vidq.stream))
+			return POLLERR;
+		buf = list_entry(fh->vb_vidq.stream.next, struct tm6000_buffer, vb.stream);
+	} else {
+		/* read() capture */
+		return videobuf_poll_stream(file, &fh->vb_vidq, wait);
+	}
+	poll_wait(file, &buf->vb.done, wait);
+	if (buf->vb.state == VIDEOBUF_DONE ||
+	    buf->vb.state == VIDEOBUF_ERROR)
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+static int tm6000_release(struct file *file)
+{
+	struct tm6000_fh         *fh = file->private_data;
+	struct tm6000_core      *dev = fh->dev;
+	struct video_device    *vdev = video_devdata(file);
+
+	dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: close called (dev=%s, users=%d)\n",
+		video_device_node_name(vdev), dev->users);
+
+	dev->users--;
+
+	res_free(dev, fh);
+
+	if (!dev->users) {
+		int err;
+
+		tm6000_uninit_isoc(dev);
+
+		if (!fh->radio)
+			videobuf_mmap_free(&fh->vb_vidq);
+
+		err = tm6000_reset(dev);
+		if (err < 0)
+			dev_err(&vdev->dev, "reset failed: %d\n", err);
+	}
+
+	kfree(fh);
+
+	return 0;
+}
+
+static int tm6000_mmap(struct file *file, struct vm_area_struct * vma)
+{
+	struct tm6000_fh *fh = file->private_data;
+
+	return videobuf_mmap_mapper(&fh->vb_vidq, vma);
+}
+
+static struct v4l2_file_operations tm6000_fops = {
+	.owner = THIS_MODULE,
+	.open = tm6000_open,
+	.release = tm6000_release,
+	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
+	.read = tm6000_read,
+	.poll = tm6000_poll,
+	.mmap = tm6000_mmap,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+	.vidioc_querycap          = vidioc_querycap,
+	.vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
+	.vidioc_s_std             = vidioc_s_std,
+	.vidioc_enum_input        = vidioc_enum_input,
+	.vidioc_g_input           = vidioc_g_input,
+	.vidioc_s_input           = vidioc_s_input,
+	.vidioc_queryctrl         = vidioc_queryctrl,
+	.vidioc_g_ctrl            = vidioc_g_ctrl,
+	.vidioc_s_ctrl            = vidioc_s_ctrl,
+	.vidioc_g_tuner           = vidioc_g_tuner,
+	.vidioc_s_tuner           = vidioc_s_tuner,
+	.vidioc_g_frequency       = vidioc_g_frequency,
+	.vidioc_s_frequency       = vidioc_s_frequency,
+	.vidioc_streamon          = vidioc_streamon,
+	.vidioc_streamoff         = vidioc_streamoff,
+	.vidioc_reqbufs           = vidioc_reqbufs,
+	.vidioc_querybuf          = vidioc_querybuf,
+	.vidioc_qbuf              = vidioc_qbuf,
+	.vidioc_dqbuf             = vidioc_dqbuf,
+};
+
+static struct video_device tm6000_template = {
+	.name		= "tm6000",
+	.fops           = &tm6000_fops,
+	.ioctl_ops      = &video_ioctl_ops,
+	.release	= video_device_release,
+	.tvnorms        = TM6000_STD,
+	.current_norm   = V4L2_STD_NTSC_M,
+};
+
+static const struct v4l2_file_operations radio_fops = {
+	.owner		= THIS_MODULE,
+	.open		= tm6000_open,
+	.release	= tm6000_release,
+	.unlocked_ioctl	= video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
+	.vidioc_querycap	= radio_querycap,
+	.vidioc_g_tuner		= radio_g_tuner,
+	.vidioc_enum_input	= radio_enum_input,
+	.vidioc_g_audio		= radio_g_audio,
+	.vidioc_s_tuner		= radio_s_tuner,
+	.vidioc_s_audio		= radio_s_audio,
+	.vidioc_s_input		= radio_s_input,
+	.vidioc_s_std		= radio_s_std,
+	.vidioc_queryctrl	= radio_queryctrl,
+	.vidioc_g_input		= radio_g_input,
+	.vidioc_g_ctrl		= vidioc_g_ctrl,
+	.vidioc_s_ctrl		= vidioc_s_ctrl,
+	.vidioc_g_frequency	= vidioc_g_frequency,
+	.vidioc_s_frequency	= vidioc_s_frequency,
+};
+
+static struct video_device tm6000_radio_template = {
+	.name			= "tm6000",
+	.fops			= &radio_fops,
+	.ioctl_ops		= &radio_ioctl_ops,
+};
+
+/* -----------------------------------------------------------------
+ *	Initialization and module stuff
+ * ------------------------------------------------------------------
+ */
+
+static struct video_device *vdev_init(struct tm6000_core *dev,
+		const struct video_device
+		*template, const char *type_name)
+{
+	struct video_device *vfd;
+
+	vfd = video_device_alloc();
+	if (NULL == vfd)
+		return NULL;
+
+	*vfd = *template;
+	vfd->v4l2_dev = &dev->v4l2_dev;
+	vfd->release = video_device_release;
+	vfd->debug = tm6000_debug;
+	vfd->lock = &dev->lock;
+
+	snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
+
+	video_set_drvdata(vfd, dev);
+	return vfd;
+}
+
+int tm6000_v4l2_register(struct tm6000_core *dev)
+{
+	int ret = -1;
+
+	dev->vfd = vdev_init(dev, &tm6000_template, "video");
+
+	if (!dev->vfd) {
+		printk(KERN_INFO "%s: can't register video device\n",
+		       dev->name);
+		return -ENOMEM;
+	}
+
+	/* init video dma queues */
+	INIT_LIST_HEAD(&dev->vidq.active);
+	INIT_LIST_HEAD(&dev->vidq.queued);
+
+	ret = video_register_device(dev->vfd, VFL_TYPE_GRABBER, video_nr);
+
+	if (ret < 0) {
+		printk(KERN_INFO "%s: can't register video device\n",
+		       dev->name);
+		return ret;
+	}
+
+	printk(KERN_INFO "%s: registered device %s\n",
+	       dev->name, video_device_node_name(dev->vfd));
+
+	if (dev->caps.has_radio) {
+		dev->radio_dev = vdev_init(dev, &tm6000_radio_template,
+							   "radio");
+		if (!dev->radio_dev) {
+			printk(KERN_INFO "%s: can't register radio device\n",
+			       dev->name);
+			return ret; /* FIXME release resource */
+		}
+
+		ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
+					    radio_nr);
+		if (ret < 0) {
+			printk(KERN_INFO "%s: can't register radio device\n",
+			       dev->name);
+			return ret; /* FIXME release resource */
+		}
+
+		printk(KERN_INFO "%s: registered device %s\n",
+		       dev->name, video_device_node_name(dev->radio_dev));
+	}
+
+	printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret);
+	return ret;
+}
+
+int tm6000_v4l2_unregister(struct tm6000_core *dev)
+{
+	video_unregister_device(dev->vfd);
+
+	if (dev->radio_dev) {
+		if (video_is_registered(dev->radio_dev))
+			video_unregister_device(dev->radio_dev);
+		else
+			video_device_release(dev->radio_dev);
+		dev->radio_dev = NULL;
+	}
+
+	return 0;
+}
+
+int tm6000_v4l2_exit(void)
+{
+	return 0;
+}
+
+module_param(video_nr, int, 0);
+MODULE_PARM_DESC(video_nr, "Allow changing video device number");
+
+module_param_named(debug, tm6000_debug, int, 0444);
+MODULE_PARM_DESC(debug, "activates debug info");
+
+module_param(vid_limit, int, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
+
diff -druN linux-libre-3.1-gnu/drivers/media/video/tvaudio.c linux-libre-3.2-gnu/drivers/media/video/tvaudio.c
--- linux-libre-3.1-gnu/drivers/media/video/tvaudio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/tvaudio.c	2012-01-04 18:55:44.000000000 -0500
@@ -1695,14 +1695,17 @@
 	case V4L2_CID_AUDIO_BALANCE:
 	{
 		int volume, balance;
+
 		if (!(desc->flags & CHIP_HAS_VOLUME))
 			break;
 
-		volume = max(chip->left,chip->right);
+		volume = max(chip->left, chip->right);
 		balance = ctrl->value;
+		chip->left = (min(65536 - balance, 32768) * volume) / 32768;
+		chip->right = (min(balance, volume * (__u16)32768)) / 32768;
 
-		chip_write(chip,desc->leftreg,desc->volfunc(chip->left));
-		chip_write(chip,desc->rightreg,desc->volfunc(chip->right));
+		chip_write(chip, desc->leftreg, desc->volfunc(chip->left));
+		chip_write(chip, desc->rightreg, desc->volfunc(chip->right));
 
 		return 0;
 	}
diff -druN linux-libre-3.1-gnu/drivers/media/video/tvp514x.c linux-libre-3.2-gnu/drivers/media/video/tvp514x.c
--- linux-libre-3.1-gnu/drivers/media/video/tvp514x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/tvp514x.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/videodev2.h>
+#include <linux/module.h>
 
 #include <media/v4l2-device.h>
 #include <media/v4l2-common.h>
diff -druN linux-libre-3.1-gnu/drivers/media/video/tvp5150.c linux-libre-3.2-gnu/drivers/media/video/tvp5150.c
--- linux-libre-3.1-gnu/drivers/media/video/tvp5150.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/tvp5150.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <media/v4l2-device.h>
 #include <media/tvp5150.h>
 #include <media/v4l2-chip-ident.h>
diff -druN linux-libre-3.1-gnu/drivers/media/video/tvp5150_reg.h linux-libre-3.2-gnu/drivers/media/video/tvp5150_reg.h
--- linux-libre-3.1-gnu/drivers/media/video/tvp5150_reg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/tvp5150_reg.h	2012-01-04 18:55:44.000000000 -0500
@@ -45,7 +45,22 @@
 
 /* Reserved 1Fh-27h */
 
-#define TVP5150_VIDEO_STD           0x28 /* Video standard */
+#define VIDEO_STD_MASK			 (0x07 >> 1)
+#define TVP5150_VIDEO_STD                0x28 /* Video standard */
+#define VIDEO_STD_AUTO_SWITCH_BIT	 0x00
+#define VIDEO_STD_NTSC_MJ_BIT		 0x02
+#define VIDEO_STD_PAL_BDGHIN_BIT	 0x04
+#define VIDEO_STD_PAL_M_BIT		 0x06
+#define VIDEO_STD_PAL_COMBINATION_N_BIT	 0x08
+#define VIDEO_STD_NTSC_4_43_BIT		 0x0a
+#define VIDEO_STD_SECAM_BIT		 0x0c
+
+#define VIDEO_STD_NTSC_MJ_BIT_AS                 0x01
+#define VIDEO_STD_PAL_BDGHIN_BIT_AS              0x03
+#define VIDEO_STD_PAL_M_BIT_AS		         0x05
+#define VIDEO_STD_PAL_COMBINATION_N_BIT_AS	 0x07
+#define VIDEO_STD_NTSC_4_43_BIT_AS		 0x09
+#define VIDEO_STD_SECAM_BIT_AS		         0x0b
 
 /* Reserved 29h-2bh */
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/tvp7002.c linux-libre-3.2-gnu/drivers/media/video/tvp7002.c
--- linux-libre-3.1-gnu/drivers/media/video/tvp7002.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/tvp7002.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
+#include <linux/module.h>
 #include <media/tvp7002.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
@@ -128,7 +129,7 @@
 	{ TVP7002_ADC_SETUP, 0x50, TVP7002_WRITE },
 	{ TVP7002_COARSE_CLAMP_CTL, 0x00, TVP7002_WRITE },
 	{ TVP7002_SOG_CLAMP, 0x80, TVP7002_WRITE },
-	{ TVP7002_RGB_COARSE_CLAMP_CTL, 0x00, TVP7002_WRITE },
+	{ TVP7002_RGB_COARSE_CLAMP_CTL, 0x8c, TVP7002_WRITE },
 	{ TVP7002_SOG_COARSE_CLAMP_CTL, 0x04, TVP7002_WRITE },
 	{ TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE },
 	{ 0x32, 0x18, TVP7002_RESERVED },
@@ -182,7 +183,6 @@
 	{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x35, TVP7002_WRITE },
 	{ TVP7002_HPLL_FDBK_DIV_LSBS, 0xa0, TVP7002_WRITE },
 	{ TVP7002_HPLL_CRTL, 0x02, TVP7002_WRITE },
-	{ TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE },
 	{ TVP7002_AVID_START_PIXEL_LSBS, 0x91, TVP7002_WRITE },
 	{ TVP7002_AVID_START_PIXEL_MSBS, 0x00, TVP7002_WRITE },
 	{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x0B, TVP7002_WRITE },
@@ -204,7 +204,6 @@
 	{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x36, TVP7002_WRITE },
 	{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x00, TVP7002_WRITE },
 	{ TVP7002_HPLL_CRTL, 0x18, TVP7002_WRITE },
-	{ TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE },
 	{ TVP7002_AVID_START_PIXEL_LSBS, 0x9B, TVP7002_WRITE },
 	{ TVP7002_AVID_START_PIXEL_MSBS, 0x00, TVP7002_WRITE },
 	{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x0F, TVP7002_WRITE },
@@ -226,7 +225,6 @@
 	{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x89, TVP7002_WRITE },
 	{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x80, TVP7002_WRITE },
 	{ TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE },
-	{ TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE },
 	{ TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE },
 	{ TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE },
 	{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x8a, TVP7002_WRITE },
@@ -248,7 +246,6 @@
 	{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x89, TVP7002_WRITE },
 	{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x80, TVP7002_WRITE },
 	{ TVP7002_HPLL_CRTL, 0xE0, TVP7002_WRITE },
-	{ TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE },
 	{ TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE },
 	{ TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE },
 	{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x8a, TVP7002_WRITE },
@@ -270,7 +267,6 @@
 	{ TVP7002_HPLL_FDBK_DIV_MSBS, 0xa5, TVP7002_WRITE },
 	{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x00, TVP7002_WRITE },
 	{ TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE },
-	{ TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE },
 	{ TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE },
 	{ TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE },
 	{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x8a, TVP7002_WRITE },
@@ -292,7 +288,6 @@
 	{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x67, TVP7002_WRITE },
 	{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x20, TVP7002_WRITE },
 	{ TVP7002_HPLL_CRTL, 0xa0, TVP7002_WRITE },
-	{ TVP7002_HPLL_PHASE_SEL, 0x16, TVP7002_WRITE },
 	{ TVP7002_AVID_START_PIXEL_LSBS, 0x47, TVP7002_WRITE },
 	{ TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE },
 	{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x4B, TVP7002_WRITE },
@@ -314,7 +309,6 @@
 	{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x7b, TVP7002_WRITE },
 	{ TVP7002_HPLL_FDBK_DIV_LSBS, 0xc0, TVP7002_WRITE },
 	{ TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE },
-	{ TVP7002_HPLL_PHASE_SEL, 0x16, TVP7002_WRITE },
 	{ TVP7002_AVID_START_PIXEL_LSBS, 0x47, TVP7002_WRITE },
 	{ TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE },
 	{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x4B, TVP7002_WRITE },
@@ -687,6 +681,9 @@
 	u8 cpl_msb;
 	int index;
 
+	/* Return invalid preset if no active input is detected */
+	qpreset->preset = V4L2_DV_INVALID;
+
 	device = to_tvp7002(sd);
 
 	/* Read standards from device registers */
@@ -720,8 +717,6 @@
 	if (index == NUM_PRESETS) {
 		v4l2_dbg(1, debug, sd, "detection failed: lpf = %x, cpl = %x\n",
 								lpfr, cpln);
-		/* Could not detect a signal, so return the 'invalid' preset */
-		qpreset->preset = V4L2_DV_INVALID;
 		return 0;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/tw9910.c linux-libre-3.2-gnu/drivers/media/video/tw9910.c
--- linux-libre-3.1-gnu/drivers/media/video/tw9910.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/tw9910.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,11 +22,13 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/videodev2.h>
-#include <media/v4l2-chip-ident.h>
-#include <media/v4l2-subdev.h>
+
 #include <media/soc_camera.h>
 #include <media/tw9910.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-subdev.h>
 
 #define GET_ID(val)  ((val & 0xF8) >> 3)
 #define GET_REV(val) (val & 0x07)
@@ -203,6 +205,10 @@
 #define RTSEL_FIELD 0x06 /* 0110 = FIELD */
 #define RTSEL_RTCO  0x07 /* 0111 = RTCO ( Real Time Control ) */
 
+/* HSYNC start and end are constant for now */
+#define HSYNC_START	0x0260
+#define HSYNC_END	0x0300
+
 /*
  * structure
  */
@@ -220,22 +226,11 @@
 	u16             vscale;
 };
 
-struct tw9910_cropping_ctrl {
-	u16 vdelay;
-	u16 vactive;
-	u16 hdelay;
-	u16 hactive;
-};
-
-struct tw9910_hsync_ctrl {
-	u16 start;
-	u16 end;
-};
-
 struct tw9910_priv {
 	struct v4l2_subdev		subdev;
 	struct tw9910_video_info	*info;
 	const struct tw9910_scale_ctrl	*scale;
+	v4l2_std_id			norm;
 	u32				revision;
 };
 
@@ -329,11 +324,6 @@
 	},
 };
 
-static const struct tw9910_hsync_ctrl tw9910_hsync_ctrl = {
-	.start = 0x0260,
-	.end   = 0x0300,
-};
-
 /*
  * general function
  */
@@ -378,21 +368,20 @@
 	return ret;
 }
 
-static int tw9910_set_hsync(struct i2c_client *client,
-			    const struct tw9910_hsync_ctrl *hsync)
+static int tw9910_set_hsync(struct i2c_client *client)
 {
 	struct tw9910_priv *priv = to_tw9910(client);
 	int ret;
 
 	/* bit 10 - 3 */
 	ret = i2c_smbus_write_byte_data(client, HSBEGIN,
-					(hsync->start & 0x07F8) >> 3);
+					(HSYNC_START & 0x07F8) >> 3);
 	if (ret < 0)
 		return ret;
 
 	/* bit 10 - 3 */
 	ret = i2c_smbus_write_byte_data(client, HSEND,
-					(hsync->end & 0x07F8) >> 3);
+					(HSYNC_END & 0x07F8) >> 3);
 	if (ret < 0)
 		return ret;
 
@@ -400,8 +389,8 @@
 	/* bit 2 - 0 */
 	if (1 == priv->revision)
 		ret = tw9910_mask_set(client, HSLOWCTL, 0x77,
-				      (hsync->start & 0x0007) << 4 |
-				      (hsync->end   & 0x0007));
+				      (HSYNC_START & 0x0007) << 4 |
+				      (HSYNC_END   & 0x0007));
 
 	return ret;
 }
@@ -433,12 +422,11 @@
 	return tw9910_mask_set(client, ACNTL2, ACNTL2_PDN_MASK, acntl2);
 }
 
-static const struct tw9910_scale_ctrl*
-tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height)
+static const struct tw9910_scale_ctrl *tw9910_select_norm(v4l2_std_id norm,
+							  u32 width, u32 height)
 {
 	const struct tw9910_scale_ctrl *scale;
 	const struct tw9910_scale_ctrl *ret = NULL;
-	v4l2_std_id norm = icd->vdev->current_norm;
 	__u32 diff = 0xffffffff, tmp;
 	int size, i;
 
@@ -465,7 +453,7 @@
 }
 
 /*
- * soc_camera_ops function
+ * subdevice operations
  */
 static int tw9910_s_stream(struct v4l2_subdev *sd, int enable)
 {
@@ -507,49 +495,27 @@
 	return tw9910_power(client, enable);
 }
 
-static int tw9910_set_bus_param(struct soc_camera_device *icd,
-				unsigned long flags)
+static int tw9910_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm)
 {
-	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	u8 val = VSSL_VVALID | HSSL_DVALID;
-
-	/*
-	 * set OUTCTR1
-	 *
-	 * We use VVALID and DVALID signals to control VSYNC and HSYNC
-	 * outputs, in this mode their polarity is inverted.
-	 */
-	if (flags & SOCAM_HSYNC_ACTIVE_LOW)
-		val |= HSP_HI;
+	struct tw9910_priv *priv = to_tw9910(client);
 
-	if (flags & SOCAM_VSYNC_ACTIVE_LOW)
-		val |= VSP_HI;
+	*norm = priv->norm;
 
-	return i2c_smbus_write_byte_data(client, OUTCTR1, val);
+	return 0;
 }
 
-static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd)
+static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
 {
-	struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct tw9910_priv *priv = to_tw9910(client);
-	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_VSYNC_ACTIVE_LOW  | SOCAM_HSYNC_ACTIVE_LOW  |
-		SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth;
 
-	return soc_camera_apply_sensor_flags(icl, flags);
-}
-
-static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
-{
-	int ret = -EINVAL;
+	if (!(norm & (V4L2_STD_NTSC | V4L2_STD_PAL)))
+		return -EINVAL;
 
-	if (norm & (V4L2_STD_NTSC | V4L2_STD_PAL))
-		ret = 0;
+	priv->norm = norm;
 
-	return ret;
+	return 0;
 }
 
 static int tw9910_g_chip_ident(struct v4l2_subdev *sd,
@@ -600,19 +566,17 @@
 }
 #endif
 
-static int tw9910_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height)
 {
-	struct v4l2_rect *rect = &a->c;
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct tw9910_priv *priv = to_tw9910(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
-	int                 ret  = -EINVAL;
-	u8                  val;
+	int ret = -EINVAL;
+	u8 val;
 
 	/*
 	 * select suitable norm
 	 */
-	priv->scale = tw9910_select_norm(icd, rect->width, rect->height);
+	priv->scale = tw9910_select_norm(priv->norm, *width, *height);
 	if (!priv->scale)
 		goto tw9910_set_fmt_error;
 
@@ -670,14 +634,12 @@
 	/*
 	 * set hsync
 	 */
-	ret = tw9910_set_hsync(client, &tw9910_hsync_ctrl);
+	ret = tw9910_set_hsync(client);
 	if (ret < 0)
 		goto tw9910_set_fmt_error;
 
-	rect->width = priv->scale->width;
-	rect->height = priv->scale->height;
-	rect->left = 0;
-	rect->top = 0;
+	*width = priv->scale->width;
+	*height = priv->scale->height;
 
 	return ret;
 
@@ -694,25 +656,15 @@
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct tw9910_priv *priv = to_tw9910(client);
 
-	if (!priv->scale) {
-		int ret;
-		struct v4l2_crop crop = {
-			.c = {
-				.left	= 0,
-				.top	= 0,
-				.width	= 640,
-				.height	= 480,
-			},
-		};
-		ret = tw9910_s_crop(sd, &crop);
-		if (ret < 0)
-			return ret;
-	}
-
 	a->c.left	= 0;
 	a->c.top	= 0;
-	a->c.width	= priv->scale->width;
-	a->c.height	= priv->scale->height;
+	if (priv->norm & V4L2_STD_NTSC) {
+		a->c.width	= 640;
+		a->c.height	= 480;
+	} else {
+		a->c.width	= 768;
+		a->c.height	= 576;
+	}
 	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
 	return 0;
@@ -720,14 +672,19 @@
 
 static int tw9910_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct tw9910_priv *priv = to_tw9910(client);
+
 	a->bounds.left			= 0;
 	a->bounds.top			= 0;
-	a->bounds.width			= 768;
-	a->bounds.height		= 576;
-	a->defrect.left			= 0;
-	a->defrect.top			= 0;
-	a->defrect.width		= 640;
-	a->defrect.height		= 480;
+	if (priv->norm & V4L2_STD_NTSC) {
+		a->bounds.width		= 640;
+		a->bounds.height	= 480;
+	} else {
+		a->bounds.width		= 768;
+		a->bounds.height	= 576;
+	}
+	a->defrect			= a->bounds;
 	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	a->pixelaspect.numerator	= 1;
 	a->pixelaspect.denominator	= 1;
@@ -743,15 +700,8 @@
 
 	if (!priv->scale) {
 		int ret;
-		struct v4l2_crop crop = {
-			.c = {
-				.left	= 0,
-				.top	= 0,
-				.width	= 640,
-				.height	= 480,
-			},
-		};
-		ret = tw9910_s_crop(sd, &crop);
+		u32 width = 640, height = 480;
+		ret = tw9910_set_frame(sd, &width, &height);
 		if (ret < 0)
 			return ret;
 	}
@@ -768,17 +718,7 @@
 static int tw9910_s_fmt(struct v4l2_subdev *sd,
 			struct v4l2_mbus_framefmt *mf)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct tw9910_priv *priv = to_tw9910(client);
-	/* See tw9910_s_crop() - no proper cropping support */
-	struct v4l2_crop a = {
-		.c = {
-			.left	= 0,
-			.top	= 0,
-			.width	= mf->width,
-			.height	= mf->height,
-		},
-	};
+	u32 width = mf->width, height = mf->height;
 	int ret;
 
 	WARN_ON(mf->field != V4L2_FIELD_ANY &&
@@ -792,10 +732,10 @@
 
 	mf->colorspace = V4L2_COLORSPACE_JPEG;
 
-	ret = tw9910_s_crop(sd, &a);
+	ret = tw9910_set_frame(sd, &width, &height);
 	if (!ret) {
-		mf->width	= priv->scale->width;
-		mf->height	= priv->scale->height;
+		mf->width	= width;
+		mf->height	= height;
 	}
 	return ret;
 }
@@ -804,7 +744,7 @@
 			  struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct soc_camera_device *icd = client->dev.platform_data;
+	struct tw9910_priv *priv = to_tw9910(client);
 	const struct tw9910_scale_ctrl *scale;
 
 	if (V4L2_FIELD_ANY == mf->field) {
@@ -820,7 +760,7 @@
 	/*
 	 * select suitable norm
 	 */
-	scale = tw9910_select_norm(icd, mf->width, mf->height);
+	scale = tw9910_select_norm(priv->norm, mf->width, mf->height);
 	if (!scale)
 		return -EINVAL;
 
@@ -830,16 +770,11 @@
 	return 0;
 }
 
-static int tw9910_video_probe(struct soc_camera_device *icd,
-			      struct i2c_client *client)
+static int tw9910_video_probe(struct i2c_client *client)
 {
 	struct tw9910_priv *priv = to_tw9910(client);
 	s32 id;
 
-	/* We must have a parent by now. And it cannot be a wrong one. */
-	BUG_ON(!icd->parent ||
-	       to_soc_camera_host(icd->parent)->nr != icd->iface);
-
 	/*
 	 * tw9910 only use 8 or 16 bit bus width
 	 */
@@ -868,20 +803,15 @@
 	dev_info(&client->dev,
 		 "tw9910 Product ID %0x:%0x\n", id, priv->revision);
 
-	icd->vdev->tvnorms      = V4L2_STD_NTSC | V4L2_STD_PAL;
-	icd->vdev->current_norm = V4L2_STD_NTSC;
+	priv->norm = V4L2_STD_NTSC;
 
 	return 0;
 }
 
-static struct soc_camera_ops tw9910_ops = {
-	.set_bus_param		= tw9910_set_bus_param,
-	.query_bus_param	= tw9910_query_bus_param,
-};
-
 static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
 	.g_chip_ident	= tw9910_g_chip_ident,
 	.s_std		= tw9910_s_std,
+	.g_std		= tw9910_g_std,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register	= tw9910_g_register,
 	.s_register	= tw9910_s_register,
@@ -898,6 +828,45 @@
 	return 0;
 }
 
+static int tw9910_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static int tw9910_s_mbus_config(struct v4l2_subdev *sd,
+				const struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	u8 val = VSSL_VVALID | HSSL_DVALID;
+	unsigned long flags = soc_camera_apply_board_flags(icl, cfg);
+
+	/*
+	 * set OUTCTR1
+	 *
+	 * We use VVALID and DVALID signals to control VSYNC and HSYNC
+	 * outputs, in this mode their polarity is inverted.
+	 */
+	if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
+		val |= HSP_HI;
+
+	if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
+		val |= VSP_HI;
+
+	return i2c_smbus_write_byte_data(client, OUTCTR1, val);
+}
+
 static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {
 	.s_stream	= tw9910_s_stream,
 	.g_mbus_fmt	= tw9910_g_fmt,
@@ -905,8 +874,9 @@
 	.try_mbus_fmt	= tw9910_try_fmt,
 	.cropcap	= tw9910_cropcap,
 	.g_crop		= tw9910_g_crop,
-	.s_crop		= tw9910_s_crop,
 	.enum_mbus_fmt	= tw9910_enum_fmt,
+	.g_mbus_config	= tw9910_g_mbus_config,
+	.s_mbus_config	= tw9910_s_mbus_config,
 };
 
 static struct v4l2_subdev_ops tw9910_subdev_ops = {
@@ -922,23 +892,18 @@
 			const struct i2c_device_id *did)
 
 {
-	struct tw9910_priv             *priv;
-	struct tw9910_video_info       *info;
-	struct soc_camera_device       *icd = client->dev.platform_data;
-	struct i2c_adapter             *adapter =
+	struct tw9910_priv		*priv;
+	struct tw9910_video_info	*info;
+	struct i2c_adapter		*adapter =
 		to_i2c_adapter(client->dev.parent);
-	struct soc_camera_link         *icl;
-	int                             ret;
+	struct soc_camera_link		*icl = soc_camera_i2c_to_link(client);
+	int				ret;
 
-	if (!icd) {
-		dev_err(&client->dev, "TW9910: missing soc-camera data!\n");
+	if (!icl || !icl->priv) {
+		dev_err(&client->dev, "TW9910: missing platform data!\n");
 		return -EINVAL;
 	}
 
-	icl = to_soc_camera_link(icd);
-	if (!icl || !icl->priv)
-		return -EINVAL;
-
 	info = icl->priv;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -956,14 +921,9 @@
 
 	v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops);
 
-	icd->ops     = &tw9910_ops;
-	icd->iface   = icl->bus_id;
-
-	ret = tw9910_video_probe(icd, client);
-	if (ret) {
-		icd->ops = NULL;
+	ret = tw9910_video_probe(client);
+	if (ret)
 		kfree(priv);
-	}
 
 	return ret;
 }
@@ -971,9 +931,7 @@
 static int tw9910_remove(struct i2c_client *client)
 {
 	struct tw9910_priv *priv = to_tw9910(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
 
-	icd->ops = NULL;
 	kfree(priv);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/media/video/usbvision/Makefile linux-libre-3.2-gnu/drivers/media/video/usbvision/Makefile
--- linux-libre-3.1-gnu/drivers/media/video/usbvision/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/usbvision/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -2,5 +2,5 @@
 
 obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
-EXTRA_CFLAGS += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
diff -druN linux-libre-3.1-gnu/drivers/media/video/usbvision/usbvision-cards.c linux-libre-3.2-gnu/drivers/media/video/usbvision/usbvision-cards.c
--- linux-libre-3.1-gnu/drivers/media/video/usbvision/usbvision-cards.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/usbvision/usbvision-cards.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 
 
 #include <linux/list.h>
+#include <linux/module.h>
 #include <media/v4l2-dev.h>
 #include <media/tuner.h>
 #include "usbvision.h"
diff -druN linux-libre-3.1-gnu/drivers/media/video/uvc/uvc_ctrl.c linux-libre-3.2-gnu/drivers/media/video/uvc/uvc_ctrl.c
--- linux-libre-3.1-gnu/drivers/media/video/uvc/uvc_ctrl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/uvc/uvc_ctrl.c	2012-01-04 18:55:44.000000000 -0500
@@ -1016,7 +1016,8 @@
 
 	menu_info = &mapping->menu_info[query_menu->index];
 
-	if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) {
+	if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK &&
+	    (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) {
 		s32 bitmap;
 
 		if (!ctrl->cached) {
@@ -1225,7 +1226,8 @@
 		/* Valid menu indices are reported by the GET_RES request for
 		 * UVC controls that support it.
 		 */
-		if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) {
+		if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK &&
+		    (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) {
 			if (!ctrl->cached) {
 				ret = uvc_ctrl_populate_cache(chain, ctrl);
 				if (ret < 0)
diff -druN linux-libre-3.1-gnu/drivers/media/video/uvc/uvc_driver.c linux-libre-3.2-gnu/drivers/media/video/uvc/uvc_driver.c
--- linux-libre-3.1-gnu/drivers/media/video/uvc/uvc_driver.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/uvc/uvc_driver.c	2012-01-04 18:55:44.000000000 -0500
@@ -114,6 +114,11 @@
 		.guid		= UVC_GUID_FORMAT_RGBP,
 		.fcc		= V4L2_PIX_FMT_RGB565,
 	},
+	{
+		.name		= "H.264",
+		.guid		= UVC_GUID_FORMAT_H264,
+		.fcc		= V4L2_PIX_FMT_H264,
+	},
 };
 
 /* ------------------------------------------------------------------------
@@ -2331,6 +2336,14 @@
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_QUIRK_PROBE_DEF },
+	/* The Imaging Source USB CCD cameras */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x199e,
+	  .idProduct		= 0x8102,
+	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0 },
 	/* Bodelin ProScopeHR */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_DEV_HI
diff -druN linux-libre-3.1-gnu/drivers/media/video/uvc/uvc_v4l2.c linux-libre-3.2-gnu/drivers/media/video/uvc/uvc_v4l2.c
--- linux-libre-3.1-gnu/drivers/media/video/uvc/uvc_v4l2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/uvc/uvc_v4l2.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,7 @@
  * UVC ioctls
  */
 static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain,
-	struct uvc_xu_control_mapping *xmap, int old)
+	struct uvc_xu_control_mapping *xmap)
 {
 	struct uvc_control_mapping *map;
 	unsigned int size;
@@ -58,13 +58,6 @@
 		break;
 
 	case V4L2_CTRL_TYPE_MENU:
-		if (old) {
-			uvc_trace(UVC_TRACE_CONTROL, "V4L2_CTRL_TYPE_MENU not "
-				  "supported for UVCIOC_CTRL_MAP_OLD.\n");
-			ret = -EINVAL;
-			goto done;
-		}
-
 		size = xmap->menu_count * sizeof(*map->menu_info);
 		map->menu_info = kmalloc(size, GFP_KERNEL);
 		if (map->menu_info == NULL) {
@@ -538,20 +531,6 @@
 	return 0;
 }
 
-static void uvc_v4l2_ioctl_warn(void)
-{
-	static int warned;
-
-	if (warned)
-		return;
-
-	uvc_printk(KERN_INFO, "Deprecated UVCIOC_CTRL_{ADD,MAP_OLD,GET,SET} "
-		   "ioctls will be removed in 2.6.42.\n");
-	uvc_printk(KERN_INFO, "See http://www.ideasonboard.org/uvc/upgrade/ "
-		   "for upgrade instructions.\n");
-	warned = 1;
-}
-
 static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
 	struct video_device *vdev = video_devdata(file);
@@ -1032,37 +1011,8 @@
 		uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd);
 		return -EINVAL;
 
-	/* Dynamic controls. UVCIOC_CTRL_ADD, UVCIOC_CTRL_MAP_OLD,
-	 * UVCIOC_CTRL_GET and UVCIOC_CTRL_SET are deprecated and scheduled for
-	 * removal in 2.6.42.
-	 */
-	case __UVCIOC_CTRL_ADD:
-		uvc_v4l2_ioctl_warn();
-		return -EEXIST;
-
-	case __UVCIOC_CTRL_MAP_OLD:
-		uvc_v4l2_ioctl_warn();
-	case __UVCIOC_CTRL_MAP:
 	case UVCIOC_CTRL_MAP:
-		return uvc_ioctl_ctrl_map(chain, arg,
-					  cmd == __UVCIOC_CTRL_MAP_OLD);
-
-	case __UVCIOC_CTRL_GET:
-	case __UVCIOC_CTRL_SET:
-	{
-		struct uvc_xu_control *xctrl = arg;
-		struct uvc_xu_control_query xqry = {
-			.unit		= xctrl->unit,
-			.selector	= xctrl->selector,
-			.query		= cmd == __UVCIOC_CTRL_GET
-					? UVC_GET_CUR : UVC_SET_CUR,
-			.size		= xctrl->size,
-			.data		= xctrl->data,
-		};
-
-		uvc_v4l2_ioctl_warn();
-		return uvc_xu_ctrl_query(chain, &xqry);
-	}
+		return uvc_ioctl_ctrl_map(chain, arg);
 
 	case UVCIOC_CTRL_QUERY:
 		return uvc_xu_ctrl_query(chain, arg);
diff -druN linux-libre-3.1-gnu/drivers/media/video/uvc/uvc_video.c linux-libre-3.2-gnu/drivers/media/video/uvc/uvc_video.c
--- linux-libre-3.1-gnu/drivers/media/video/uvc/uvc_video.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/uvc/uvc_video.c	2012-01-04 18:55:44.000000000 -0500
@@ -790,8 +790,12 @@
 
 	for (i = 0; i < UVC_URBS; ++i) {
 		if (stream->urb_buffer[i]) {
+#ifndef CONFIG_DMA_NONCOHERENT
 			usb_free_coherent(stream->dev->udev, stream->urb_size,
 				stream->urb_buffer[i], stream->urb_dma[i]);
+#else
+			kfree(stream->urb_buffer[i]);
+#endif
 			stream->urb_buffer[i] = NULL;
 		}
 	}
@@ -831,9 +835,14 @@
 	for (; npackets > 1; npackets /= 2) {
 		for (i = 0; i < UVC_URBS; ++i) {
 			stream->urb_size = psize * npackets;
+#ifndef CONFIG_DMA_NONCOHERENT
 			stream->urb_buffer[i] = usb_alloc_coherent(
 				stream->dev->udev, stream->urb_size,
 				gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]);
+#else
+			stream->urb_buffer[i] =
+			    kmalloc(stream->urb_size, gfp_flags | __GFP_NOWARN);
+#endif
 			if (!stream->urb_buffer[i]) {
 				uvc_free_urb_buffers(stream);
 				break;
@@ -908,10 +917,14 @@
 		urb->context = stream;
 		urb->pipe = usb_rcvisocpipe(stream->dev->udev,
 				ep->desc.bEndpointAddress);
+#ifndef CONFIG_DMA_NONCOHERENT
 		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+		urb->transfer_dma = stream->urb_dma[i];
+#else
+		urb->transfer_flags = URB_ISO_ASAP;
+#endif
 		urb->interval = ep->desc.bInterval;
 		urb->transfer_buffer = stream->urb_buffer[i];
-		urb->transfer_dma = stream->urb_dma[i];
 		urb->complete = uvc_video_complete;
 		urb->number_of_packets = npackets;
 		urb->transfer_buffer_length = size;
@@ -969,8 +982,10 @@
 		usb_fill_bulk_urb(urb, stream->dev->udev, pipe,
 			stream->urb_buffer[i], size, uvc_video_complete,
 			stream);
+#ifndef CONFIG_DMA_NONCOHERENT
 		urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
 		urb->transfer_dma = stream->urb_dma[i];
+#endif
 
 		stream->urb[i] = urb;
 	}
diff -druN linux-libre-3.1-gnu/drivers/media/video/uvc/uvcvideo.h linux-libre-3.2-gnu/drivers/media/video/uvc/uvcvideo.h
--- linux-libre-3.1-gnu/drivers/media/video/uvc/uvcvideo.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/uvc/uvcvideo.h	2012-01-04 18:55:44.000000000 -0500
@@ -1,106 +1,16 @@
 #ifndef _USB_VIDEO_H_
 #define _USB_VIDEO_H_
 
-#include <linux/kernel.h>
-#include <linux/videodev2.h>
-
-#ifndef __KERNEL__
-/*
- * This header provides binary compatibility with applications using the private
- * uvcvideo API. This API is deprecated and will be removed in 2.6.42.
- * Applications should be recompiled against the public linux/uvcvideo.h header.
- */
-#warn "The uvcvideo.h header is deprecated, use linux/uvcvideo.h instead."
-
-/*
- * Dynamic controls
- */
-
-/* Data types for UVC control data */
-#define UVC_CTRL_DATA_TYPE_RAW		0
-#define UVC_CTRL_DATA_TYPE_SIGNED	1
-#define UVC_CTRL_DATA_TYPE_UNSIGNED	2
-#define UVC_CTRL_DATA_TYPE_BOOLEAN	3
-#define UVC_CTRL_DATA_TYPE_ENUM		4
-#define UVC_CTRL_DATA_TYPE_BITMASK	5
-
-/* Control flags */
-#define UVC_CONTROL_SET_CUR	(1 << 0)
-#define UVC_CONTROL_GET_CUR	(1 << 1)
-#define UVC_CONTROL_GET_MIN	(1 << 2)
-#define UVC_CONTROL_GET_MAX	(1 << 3)
-#define UVC_CONTROL_GET_RES	(1 << 4)
-#define UVC_CONTROL_GET_DEF	(1 << 5)
-#define UVC_CONTROL_RESTORE	(1 << 6)
-#define UVC_CONTROL_AUTO_UPDATE	(1 << 7)
-
-#define UVC_CONTROL_GET_RANGE	(UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | \
-				 UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | \
-				 UVC_CONTROL_GET_DEF)
-
-struct uvc_menu_info {
-	__u32 value;
-	__u8 name[32];
-};
-
-struct uvc_xu_control_mapping {
-	__u32 id;
-	__u8 name[32];
-	__u8 entity[16];
-	__u8 selector;
-
-	__u8 size;
-	__u8 offset;
-	__u32 v4l2_type;
-	__u32 data_type;
-
-	struct uvc_menu_info __user *menu_info;
-	__u32 menu_count;
-
-	__u32 reserved[4];
-};
-
-#endif
-
-struct uvc_xu_control_info {
-	__u8 entity[16];
-	__u8 index;
-	__u8 selector;
-	__u16 size;
-	__u32 flags;
-};
-
-struct uvc_xu_control_mapping_old {
-	__u8 reserved[64];
-};
-
-struct uvc_xu_control {
-	__u8 unit;
-	__u8 selector;
-	__u16 size;
-	__u8 __user *data;
-};
-
 #ifndef __KERNEL__
-#define UVCIOC_CTRL_ADD		_IOW('U', 1, struct uvc_xu_control_info)
-#define UVCIOC_CTRL_MAP_OLD	_IOWR('U', 2, struct uvc_xu_control_mapping_old)
-#define UVCIOC_CTRL_MAP		_IOWR('U', 2, struct uvc_xu_control_mapping)
-#define UVCIOC_CTRL_GET		_IOWR('U', 3, struct uvc_xu_control)
-#define UVCIOC_CTRL_SET		_IOW('U', 4, struct uvc_xu_control)
-#else
-#define __UVCIOC_CTRL_ADD	_IOW('U', 1, struct uvc_xu_control_info)
-#define __UVCIOC_CTRL_MAP_OLD	_IOWR('U', 2, struct uvc_xu_control_mapping_old)
-#define __UVCIOC_CTRL_MAP	_IOWR('U', 2, struct uvc_xu_control_mapping)
-#define __UVCIOC_CTRL_GET	_IOWR('U', 3, struct uvc_xu_control)
-#define __UVCIOC_CTRL_SET	_IOW('U', 4, struct uvc_xu_control)
-#endif
-
-#ifdef __KERNEL__
+#error "The uvcvideo.h header is deprecated, use linux/uvcvideo.h instead."
+#endif /* __KERNEL__ */
 
+#include <linux/kernel.h>
 #include <linux/poll.h>
 #include <linux/usb.h>
 #include <linux/usb/video.h>
 #include <linux/uvcvideo.h>
+#include <linux/videodev2.h>
 #include <media/media-device.h>
 #include <media/v4l2-device.h>
 
@@ -179,6 +89,10 @@
 	{ 'M',  '4',  '2',  '0', 0x00, 0x00, 0x10, 0x00, \
 	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
 
+#define UVC_GUID_FORMAT_H264 \
+	{ 'H',  '2',  '6',  '4', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+
 /* ------------------------------------------------------------------------
  * Driver specific constants.
  */
@@ -698,6 +612,4 @@
 void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream,
 		struct uvc_buffer *buf);
 
-#endif /* __KERNEL__ */
-
 #endif
diff -druN linux-libre-3.1-gnu/drivers/media/video/v4l2-compat-ioctl32.c linux-libre-3.2-gnu/drivers/media/video/v4l2-compat-ioctl32.c
--- linux-libre-3.1-gnu/drivers/media/video/v4l2-compat-ioctl32.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/v4l2-compat-ioctl32.c	2012-01-04 18:55:44.000000000 -0500
@@ -159,11 +159,25 @@
 	} fmt;
 };
 
-static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+/**
+ * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
+ * @index:	on return, index of the first created buffer
+ * @count:	entry: number of requested buffers,
+ *		return: number of created buffers
+ * @memory:	buffer memory type
+ * @format:	frame format, for which buffers are requested
+ * @reserved:	future extensions
+ */
+struct v4l2_create_buffers32 {
+	__u32			index;
+	__u32			count;
+	enum v4l2_memory        memory;
+	struct v4l2_format32	format;
+	__u32			reserved[8];
+};
+
+static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
 {
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
-			get_user(kp->type, &up->type))
-			return -EFAULT;
 	switch (kp->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
@@ -192,11 +206,24 @@
 	}
 }
 
-static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+{
+	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
+			get_user(kp->type, &up->type))
+			return -EFAULT;
+	return __get_v4l2_format32(kp, up);
+}
+
+static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
+{
+	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
+	    copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format.fmt)))
+			return -EFAULT;
+	return __get_v4l2_format32(&kp->format, &up->format);
+}
+
+static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
 {
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
-		put_user(kp->type, &up->type))
-		return -EFAULT;
 	switch (kp->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
@@ -225,6 +252,22 @@
 	}
 }
 
+static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+{
+	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
+		put_user(kp->type, &up->type))
+		return -EFAULT;
+	return __put_v4l2_format32(kp, up);
+}
+
+static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
+{
+	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
+	    copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format.fmt)))
+			return -EFAULT;
+	return __put_v4l2_format32(&kp->format, &up->format);
+}
+
 struct v4l2_standard32 {
 	__u32		     index;
 	__u32		     id[2]; /* __u64 would get the alignment wrong */
@@ -702,6 +745,8 @@
 #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
 #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
 #define	VIDIOC_DQEVENT32	_IOR ('V', 89, struct v4l2_event32)
+#define VIDIOC_CREATE_BUFS32	_IOWR('V', 92, struct v4l2_create_buffers32)
+#define VIDIOC_PREPARE_BUF32	_IOWR('V', 93, struct v4l2_buffer32)
 
 #define VIDIOC_OVERLAY32	_IOW ('V', 14, s32)
 #define VIDIOC_STREAMON32	_IOW ('V', 18, s32)
@@ -721,6 +766,7 @@
 		struct v4l2_standard v2s;
 		struct v4l2_ext_controls v2ecs;
 		struct v4l2_event v2ev;
+		struct v4l2_create_buffers v2crt;
 		unsigned long vx;
 		int vi;
 	} karg;
@@ -751,6 +797,8 @@
 	case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
 	case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
 	case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
+	case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
+	case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
 	}
 
 	switch (cmd) {
@@ -775,6 +823,12 @@
 		compatible_arg = 0;
 		break;
 
+	case VIDIOC_CREATE_BUFS:
+		err = get_v4l2_create32(&karg.v2crt, up);
+		compatible_arg = 0;
+		break;
+
+	case VIDIOC_PREPARE_BUF:
 	case VIDIOC_QUERYBUF:
 	case VIDIOC_QBUF:
 	case VIDIOC_DQBUF:
@@ -860,6 +914,10 @@
 		err = put_v4l2_format32(&karg.v2f, up);
 		break;
 
+	case VIDIOC_CREATE_BUFS:
+		err = put_v4l2_create32(&karg.v2crt, up);
+		break;
+
 	case VIDIOC_QUERYBUF:
 	case VIDIOC_QBUF:
 	case VIDIOC_DQBUF:
@@ -959,6 +1017,8 @@
 	case VIDIOC_DQEVENT32:
 	case VIDIOC_SUBSCRIBE_EVENT:
 	case VIDIOC_UNSUBSCRIBE_EVENT:
+	case VIDIOC_CREATE_BUFS32:
+	case VIDIOC_PREPARE_BUF32:
 		ret = do_video_ioctl(file, cmd, arg);
 		break;
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/v4l2-ctrls.c linux-libre-3.2-gnu/drivers/media/video/v4l2-ctrls.c
--- linux-libre-3.1-gnu/drivers/media/video/v4l2-ctrls.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/v4l2-ctrls.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 
 #include <linux/ctype.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
@@ -43,7 +44,7 @@
 };
 
 /* Small helper function to determine if the autocluster is set to manual
-   mode. In that case the is_volatile flag should be ignored. */
+   mode. */
 static bool is_cur_manual(const struct v4l2_ctrl *master)
 {
 	return master->is_auto && master->cur.val == master->manual_mode_value;
@@ -210,6 +211,7 @@
 		"Disabled",
 		"50 Hz",
 		"60 Hz",
+		"Auto",
 		NULL
 	};
 	static const char * const camera_exposure_auto[] = {
@@ -819,8 +821,8 @@
 	fill_event(&ev, ctrl, changes);
 
 	list_for_each_entry(sev, &ctrl->ev_subs, node)
-		if (sev->fh && (sev->fh != fh ||
-				(sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK)))
+		if (sev->fh != fh ||
+		    (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK))
 			v4l2_event_queue_fh(sev->fh, &ev);
 }
 
@@ -937,9 +939,15 @@
 		break;
 	}
 	if (update_inactive) {
-		ctrl->flags &= ~V4L2_CTRL_FLAG_INACTIVE;
-		if (!is_cur_manual(ctrl->cluster[0]))
+		/* Note: update_inactive can only be true for auto clusters. */
+		ctrl->flags &=
+			~(V4L2_CTRL_FLAG_INACTIVE | V4L2_CTRL_FLAG_VOLATILE);
+		if (!is_cur_manual(ctrl->cluster[0])) {
 			ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+			if (ctrl->cluster[0]->has_volatiles)
+				ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+		}
+		fh = NULL;
 	}
 	if (changed || update_inactive) {
 		/* If a control was changed that was not one of the controls
@@ -1394,10 +1402,8 @@
 			type, min, max,
 			is_menu ? cfg->menu_skip_mask : step,
 			def, flags, qmenu, priv);
-	if (ctrl) {
+	if (ctrl)
 		ctrl->is_private = cfg->is_private;
-		ctrl->is_volatile = cfg->is_volatile;
-	}
 	return ctrl;
 }
 EXPORT_SYMBOL(v4l2_ctrl_new_custom);
@@ -1491,6 +1497,7 @@
 /* Cluster controls */
 void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls)
 {
+	bool has_volatiles = false;
 	int i;
 
 	/* The first control is the master control and it must not be NULL */
@@ -1500,8 +1507,11 @@
 		if (controls[i]) {
 			controls[i]->cluster = controls;
 			controls[i]->ncontrols = ncontrols;
+			if (controls[i]->flags & V4L2_CTRL_FLAG_VOLATILE)
+				has_volatiles = true;
 		}
 	}
+	controls[0]->has_volatiles = has_volatiles;
 }
 EXPORT_SYMBOL(v4l2_ctrl_cluster);
 
@@ -1509,22 +1519,25 @@
 			    u8 manual_val, bool set_volatile)
 {
 	struct v4l2_ctrl *master = controls[0];
-	u32 flag;
+	u32 flag = 0;
 	int i;
 
 	v4l2_ctrl_cluster(ncontrols, controls);
 	WARN_ON(ncontrols <= 1);
 	WARN_ON(manual_val < master->minimum || manual_val > master->maximum);
+	WARN_ON(set_volatile && !has_op(master, g_volatile_ctrl));
 	master->is_auto = true;
+	master->has_volatiles = set_volatile;
 	master->manual_mode_value = manual_val;
 	master->flags |= V4L2_CTRL_FLAG_UPDATE;
-	flag = is_cur_manual(master) ? 0 : V4L2_CTRL_FLAG_INACTIVE;
+
+	if (!is_cur_manual(master))
+		flag = V4L2_CTRL_FLAG_INACTIVE |
+			(set_volatile ? V4L2_CTRL_FLAG_VOLATILE : 0);
 
 	for (i = 1; i < ncontrols; i++)
-		if (controls[i]) {
-			controls[i]->is_volatile = set_volatile;
+		if (controls[i])
 			controls[i]->flags |= flag;
-		}
 }
 EXPORT_SYMBOL(v4l2_ctrl_auto_cluster);
 
@@ -1579,9 +1592,6 @@
 static void log_ctrl(const struct v4l2_ctrl *ctrl,
 		     const char *prefix, const char *colon)
 {
-	int fl_inact = ctrl->flags & V4L2_CTRL_FLAG_INACTIVE;
-	int fl_grabbed = ctrl->flags & V4L2_CTRL_FLAG_GRABBED;
-
 	if (ctrl->flags & (V4L2_CTRL_FLAG_DISABLED | V4L2_CTRL_FLAG_WRITE_ONLY))
 		return;
 	if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
@@ -1612,14 +1622,17 @@
 		printk(KERN_CONT "unknown type %d", ctrl->type);
 		break;
 	}
-	if (fl_inact && fl_grabbed)
-		printk(KERN_CONT " (inactive, grabbed)\n");
-	else if (fl_inact)
-		printk(KERN_CONT " (inactive)\n");
-	else if (fl_grabbed)
-		printk(KERN_CONT " (grabbed)\n");
-	else
-		printk(KERN_CONT "\n");
+	if (ctrl->flags & (V4L2_CTRL_FLAG_INACTIVE |
+			   V4L2_CTRL_FLAG_GRABBED |
+			   V4L2_CTRL_FLAG_VOLATILE)) {
+		if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
+			printk(KERN_CONT " inactive");
+		if (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)
+			printk(KERN_CONT " grabbed");
+		if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE)
+			printk(KERN_CONT " volatile");
+	}
+	printk(KERN_CONT "\n");
 }
 
 /* Log all controls owned by the handler */
@@ -1959,7 +1972,8 @@
 		v4l2_ctrl_lock(master);
 
 		/* g_volatile_ctrl will update the new control values */
-		if (has_op(master, g_volatile_ctrl) && !is_cur_manual(master)) {
+		if ((master->flags & V4L2_CTRL_FLAG_VOLATILE) ||
+			(master->has_volatiles && !is_cur_manual(master))) {
 			for (j = 0; j < master->ncontrols; j++)
 				cur_to_new(master->cluster[j]);
 			ret = call_op(master, g_volatile_ctrl);
@@ -2004,7 +2018,7 @@
 
 	v4l2_ctrl_lock(master);
 	/* g_volatile_ctrl will update the current control values */
-	if (ctrl->is_volatile && !is_cur_manual(master)) {
+	if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) {
 		for (i = 0; i < master->ncontrols; i++)
 			cur_to_new(master->cluster[i]);
 		ret = call_op(master, g_volatile_ctrl);
@@ -2120,6 +2134,20 @@
 	return 0;
 }
 
+/* Obtain the current volatile values of an autocluster and mark them
+   as new. */
+static void update_from_auto_cluster(struct v4l2_ctrl *master)
+{
+	int i;
+
+	for (i = 0; i < master->ncontrols; i++)
+		cur_to_new(master->cluster[i]);
+	if (!call_op(master, g_volatile_ctrl))
+		for (i = 1; i < master->ncontrols; i++)
+			if (master->cluster[i])
+				master->cluster[i]->is_new = 1;
+}
+
 /* Try or try-and-set controls */
 static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
 			     struct v4l2_ext_controls *cs,
@@ -2165,6 +2193,31 @@
 			if (master->cluster[j])
 				master->cluster[j]->is_new = 0;
 
+		/* For volatile autoclusters that are currently in auto mode
+		   we need to discover if it will be set to manual mode.
+		   If so, then we have to copy the current volatile values
+		   first since those will become the new manual values (which
+		   may be overwritten by explicit new values from this set
+		   of controls). */
+		if (master->is_auto && master->has_volatiles &&
+						!is_cur_manual(master)) {
+			/* Pick an initial non-manual value */
+			s32 new_auto_val = master->manual_mode_value + 1;
+			u32 tmp_idx = idx;
+
+			do {
+				/* Check if the auto control is part of the
+				   list, and remember the new value. */
+				if (helpers[tmp_idx].ctrl == master)
+					new_auto_val = cs->controls[tmp_idx].value;
+				tmp_idx = helpers[tmp_idx].next;
+			} while (tmp_idx);
+			/* If the new value == the manual value, then copy
+			   the current volatile values. */
+			if (new_auto_val == master->manual_mode_value)
+				update_from_auto_cluster(master);
+		}
+
 		/* Copy the new caller-supplied control values.
 		   user_to_new() sets 'is_new' to 1. */
 		do {
@@ -2235,6 +2288,12 @@
 		if (master->cluster[i])
 			master->cluster[i]->is_new = 0;
 
+	/* For autoclusters with volatiles that are switched from auto to
+	   manual mode we have to update the current volatile values since
+	   those will become the initial manual values after such a switch. */
+	if (master->is_auto && master->has_volatiles && ctrl == master &&
+	    !is_cur_manual(master) && *val == master->manual_mode_value)
+		update_from_auto_cluster(master);
 	ctrl->val = *val;
 	ctrl->is_new = 1;
 	ret = try_or_set_cluster(fh, master, true);
diff -druN linux-libre-3.1-gnu/drivers/media/video/v4l2-device.c linux-libre-3.2-gnu/drivers/media/video/v4l2-device.c
--- linux-libre-3.1-gnu/drivers/media/video/v4l2-device.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/v4l2-device.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,9 @@
 
 #include <linux/types.h>
 #include <linux/ioctl.h>
+#include <linux/module.h>
 #include <linux/i2c.h>
+#include <linux/slab.h>
 #if defined(CONFIG_SPI)
 #include <linux/spi/spi.h>
 #endif
@@ -193,6 +195,13 @@
 }
 EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
 
+static void v4l2_device_release_subdev_node(struct video_device *vdev)
+{
+	struct v4l2_subdev *sd = video_get_drvdata(vdev);
+	sd->devnode = NULL;
+	kfree(vdev);
+}
+
 int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
 {
 	struct video_device *vdev;
@@ -206,22 +215,40 @@
 		if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
 			continue;
 
-		vdev = &sd->devnode;
+		vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+		if (!vdev) {
+			err = -ENOMEM;
+			goto clean_up;
+		}
+
+		video_set_drvdata(vdev, sd);
 		strlcpy(vdev->name, sd->name, sizeof(vdev->name));
 		vdev->v4l2_dev = v4l2_dev;
 		vdev->fops = &v4l2_subdev_fops;
-		vdev->release = video_device_release_empty;
+		vdev->release = v4l2_device_release_subdev_node;
 		vdev->ctrl_handler = sd->ctrl_handler;
 		err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
 					      sd->owner);
-		if (err < 0)
-			return err;
+		if (err < 0) {
+			kfree(vdev);
+			goto clean_up;
+		}
 #if defined(CONFIG_MEDIA_CONTROLLER)
 		sd->entity.v4l.major = VIDEO_MAJOR;
 		sd->entity.v4l.minor = vdev->minor;
 #endif
+		sd->devnode = vdev;
 	}
 	return 0;
+
+clean_up:
+	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
+		if (!sd->devnode)
+			break;
+		video_unregister_device(sd->devnode);
+	}
+
+	return err;
 }
 EXPORT_SYMBOL_GPL(v4l2_device_register_subdev_nodes);
 
@@ -247,7 +274,7 @@
 	if (v4l2_dev->mdev)
 		media_device_unregister_entity(&sd->entity);
 #endif
-	video_unregister_device(&sd->devnode);
+	video_unregister_device(sd->devnode);
 	module_put(sd->owner);
 }
 EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
diff -druN linux-libre-3.1-gnu/drivers/media/video/v4l2-event.c linux-libre-3.2-gnu/drivers/media/video/v4l2-event.c
--- linux-libre-3.1-gnu/drivers/media/video/v4l2-event.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/v4l2-event.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 
 static unsigned sev_pos(const struct v4l2_subscribed_event *sev, unsigned idx)
 {
@@ -215,6 +216,9 @@
 	unsigned long flags;
 	unsigned i;
 
+	if (sub->type == V4L2_EVENT_ALL)
+		return -EINVAL;
+
 	if (elems < 1)
 		elems = 1;
 	if (sub->type == V4L2_EVENT_CTRL) {
@@ -282,6 +286,7 @@
 {
 	struct v4l2_subscribed_event *sev;
 	unsigned long flags;
+	int i;
 
 	if (sub->type == V4L2_EVENT_ALL) {
 		v4l2_event_unsubscribe_all(fh);
@@ -292,8 +297,12 @@
 
 	sev = v4l2_event_subscribed(fh, sub->type, sub->id);
 	if (sev != NULL) {
+		/* Remove any pending events for this subscription */
+		for (i = 0; i < sev->in_use; i++) {
+			list_del(&sev->events[sev_pos(sev, i)].list);
+			fh->navailable--;
+		}
 		list_del(&sev->list);
-		sev->fh = NULL;
 	}
 
 	spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
diff -druN linux-libre-3.1-gnu/drivers/media/video/v4l2-fh.c linux-libre-3.2-gnu/drivers/media/video/v4l2-fh.c
--- linux-libre-3.1-gnu/drivers/media/video/v4l2-fh.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/v4l2-fh.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 
 #include <linux/bitops.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-fh.h>
 #include <media/v4l2-event.h>
diff -druN linux-libre-3.1-gnu/drivers/media/video/v4l2-int-device.c linux-libre-3.2-gnu/drivers/media/video/v4l2-int-device.c
--- linux-libre-3.1-gnu/drivers/media/video/v4l2-int-device.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/v4l2-int-device.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/list.h>
 #include <linux/sort.h>
 #include <linux/string.h>
+#include <linux/module.h>
 
 #include <media/v4l2-int-device.h>
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/v4l2-ioctl.c linux-libre-3.2-gnu/drivers/media/video/v4l2-ioctl.c
--- linux-libre-3.1-gnu/drivers/media/video/v4l2-ioctl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/v4l2-ioctl.c	2012-01-04 18:55:44.000000000 -0500
@@ -55,6 +55,19 @@
 	memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
 	0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
 
+#define have_fmt_ops(foo) (						\
+	ops->vidioc_##foo##_fmt_vid_cap ||				\
+	ops->vidioc_##foo##_fmt_vid_out ||				\
+	ops->vidioc_##foo##_fmt_vid_cap_mplane ||			\
+	ops->vidioc_##foo##_fmt_vid_out_mplane ||			\
+	ops->vidioc_##foo##_fmt_vid_overlay ||				\
+	ops->vidioc_##foo##_fmt_vbi_cap ||				\
+	ops->vidioc_##foo##_fmt_vid_out_overlay ||			\
+	ops->vidioc_##foo##_fmt_vbi_out ||				\
+	ops->vidioc_##foo##_fmt_sliced_vbi_cap ||			\
+	ops->vidioc_##foo##_fmt_sliced_vbi_out ||			\
+	ops->vidioc_##foo##_fmt_type_private)
+
 struct std_descr {
 	v4l2_std_id std;
 	const char *descr;
@@ -260,6 +273,8 @@
 	[_IOC_NR(VIDIOC_DQEVENT)]	   = "VIDIOC_DQEVENT",
 	[_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)]  = "VIDIOC_SUBSCRIBE_EVENT",
 	[_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_EVENT",
+	[_IOC_NR(VIDIOC_CREATE_BUFS)]      = "VIDIOC_CREATE_BUFS",
+	[_IOC_NR(VIDIOC_PREPARE_BUF)]      = "VIDIOC_PREPARE_BUF",
 };
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
@@ -477,63 +492,6 @@
 	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)
 {
@@ -541,8 +499,8 @@
 	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_prio = 0;
 	long ret = -ENOTTY;
 
 	if (ops == NULL) {
@@ -562,39 +520,8 @@
 		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;
-		}
-	}
+	if (use_fh_prio)
+		ret_prio = v4l2_prio_check(vfd->prio, vfh->prio);
 
 	switch (cmd) {
 
@@ -638,12 +565,14 @@
 		enum v4l2_priority *p = arg;
 
 		if (!ops->vidioc_s_priority && !use_fh_prio)
-				break;
+			break;
 		dbgarg(cmd, "setting priority to %d\n", *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);
+			ret = ret_prio ? ret_prio :
+				v4l2_prio_change(&vfd->v4l2_dev->prio,
+							&vfh->prio, *p);
 		break;
 	}
 
@@ -654,37 +583,37 @@
 
 		switch (f->type) {
 		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-			if (ops->vidioc_enum_fmt_vid_cap)
+			if (likely(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)
+			if (likely(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)
+			if (likely(ops->vidioc_enum_fmt_vid_overlay))
 				ret = ops->vidioc_enum_fmt_vid_overlay(file,
 					fh, f);
 			break;
 		case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-			if (ops->vidioc_enum_fmt_vid_out)
+			if (likely(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)
+			if (likely(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)
+			if (likely(ops->vidioc_enum_fmt_type_private))
 				ret = ops->vidioc_enum_fmt_type_private(file,
 								fh, f);
 			break;
 		default:
 			break;
 		}
-		if (!ret)
+		if (likely (!ret))
 			dbgarg(cmd, "index=%d, type=%d, flags=%d, "
 				"pixelformat=%c%c%c%c, description='%s'\n",
 				f->index, f->type, f->flags,
@@ -693,6 +622,14 @@
 				(f->pixelformat >> 16) & 0xff,
 				(f->pixelformat >> 24) & 0xff,
 				f->description);
+		else if (ret == -ENOTTY &&
+			 (ops->vidioc_enum_fmt_vid_cap ||
+			  ops->vidioc_enum_fmt_vid_out ||
+			  ops->vidioc_enum_fmt_vid_cap_mplane ||
+			  ops->vidioc_enum_fmt_vid_out_mplane ||
+			  ops->vidioc_enum_fmt_vid_overlay ||
+			  ops->vidioc_enum_fmt_type_private))
+			ret = -EINVAL;
 		break;
 	}
 	case VIDIOC_G_FMT:
@@ -704,119 +641,67 @@
 
 		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) {
+			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)
+			if (likely(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) {
+			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)
+			if (likely(ops->vidioc_g_fmt_vid_out_overlay))
 				ret = ops->vidioc_g_fmt_vid_out_overlay(file,
 				       fh, f);
 			break;
 		case V4L2_BUF_TYPE_VBI_CAPTURE:
-			if (ops->vidioc_g_fmt_vbi_cap)
+			if (likely(ops->vidioc_g_fmt_vbi_cap))
 				ret = ops->vidioc_g_fmt_vbi_cap(file, fh, f);
 			break;
 		case V4L2_BUF_TYPE_VBI_OUTPUT:
-			if (ops->vidioc_g_fmt_vbi_out)
+			if (likely(ops->vidioc_g_fmt_vbi_out))
 				ret = ops->vidioc_g_fmt_vbi_out(file, fh, f);
 			break;
 		case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-			if (ops->vidioc_g_fmt_sliced_vbi_cap)
+			if (likely(ops->vidioc_g_fmt_sliced_vbi_cap))
 				ret = ops->vidioc_g_fmt_sliced_vbi_cap(file,
 									fh, f);
 			break;
 		case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-			if (ops->vidioc_g_fmt_sliced_vbi_out)
+			if (likely(ops->vidioc_g_fmt_sliced_vbi_out))
 				ret = ops->vidioc_g_fmt_sliced_vbi_out(file,
 									fh, f);
 			break;
 		case V4L2_BUF_TYPE_PRIVATE:
-			if (ops->vidioc_g_fmt_type_private)
+			if (likely(ops->vidioc_g_fmt_type_private))
 				ret = ops->vidioc_g_fmt_type_private(file,
 								fh, f);
 			break;
 		}
+		if (unlikely(ret == -ENOTTY && have_fmt_ops(g)))
+			ret = -EINVAL;
 
 		break;
 	}
@@ -824,6 +709,14 @@
 	{
 		struct v4l2_format *f = (struct v4l2_format *)arg;
 
+		if (!have_fmt_ops(s))
+			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
+		ret = -EINVAL;
+
 		/* FIXME: Should be one dump per type */
 		dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
 
@@ -831,44 +724,15 @@
 		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) {
+			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);
@@ -879,44 +743,15 @@
 		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) {
+			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);
@@ -926,29 +761,30 @@
 			break;
 		case V4L2_BUF_TYPE_VBI_CAPTURE:
 			CLEAR_AFTER_FIELD(f, fmt.vbi);
-			if (ops->vidioc_s_fmt_vbi_cap)
+			if (likely(ops->vidioc_s_fmt_vbi_cap))
 				ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f);
 			break;
 		case V4L2_BUF_TYPE_VBI_OUTPUT:
 			CLEAR_AFTER_FIELD(f, fmt.vbi);
-			if (ops->vidioc_s_fmt_vbi_out)
+			if (likely(ops->vidioc_s_fmt_vbi_out))
 				ret = ops->vidioc_s_fmt_vbi_out(file, fh, f);
 			break;
 		case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
 			CLEAR_AFTER_FIELD(f, fmt.sliced);
-			if (ops->vidioc_s_fmt_sliced_vbi_cap)
+			if (likely(ops->vidioc_s_fmt_sliced_vbi_cap))
 				ret = ops->vidioc_s_fmt_sliced_vbi_cap(file,
 									fh, f);
 			break;
 		case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
 			CLEAR_AFTER_FIELD(f, fmt.sliced);
-			if (ops->vidioc_s_fmt_sliced_vbi_out)
+			if (likely(ops->vidioc_s_fmt_sliced_vbi_out))
 				ret = ops->vidioc_s_fmt_sliced_vbi_out(file,
 									fh, f);
+
 			break;
 		case V4L2_BUF_TYPE_PRIVATE:
 			/* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
-			if (ops->vidioc_s_fmt_type_private)
+			if (likely(ops->vidioc_s_fmt_type_private))
 				ret = ops->vidioc_s_fmt_type_private(file,
 								fh, f);
 			break;
@@ -965,132 +801,77 @@
 		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) {
+			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)
+			if (likely(ops->vidioc_try_fmt_vid_overlay))
 				ret = ops->vidioc_try_fmt_vid_overlay(file,
 					fh, f);
 			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) {
+			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)
+			if (likely(ops->vidioc_try_fmt_vid_out_overlay))
 				ret = ops->vidioc_try_fmt_vid_out_overlay(file,
 				       fh, f);
 			break;
 		case V4L2_BUF_TYPE_VBI_CAPTURE:
 			CLEAR_AFTER_FIELD(f, fmt.vbi);
-			if (ops->vidioc_try_fmt_vbi_cap)
+			if (likely(ops->vidioc_try_fmt_vbi_cap))
 				ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f);
 			break;
 		case V4L2_BUF_TYPE_VBI_OUTPUT:
 			CLEAR_AFTER_FIELD(f, fmt.vbi);
-			if (ops->vidioc_try_fmt_vbi_out)
+			if (likely(ops->vidioc_try_fmt_vbi_out))
 				ret = ops->vidioc_try_fmt_vbi_out(file, fh, f);
 			break;
 		case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
 			CLEAR_AFTER_FIELD(f, fmt.sliced);
-			if (ops->vidioc_try_fmt_sliced_vbi_cap)
+			if (likely(ops->vidioc_try_fmt_sliced_vbi_cap))
 				ret = ops->vidioc_try_fmt_sliced_vbi_cap(file,
 								fh, f);
 			break;
 		case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
 			CLEAR_AFTER_FIELD(f, fmt.sliced);
-			if (ops->vidioc_try_fmt_sliced_vbi_out)
+			if (likely(ops->vidioc_try_fmt_sliced_vbi_out))
 				ret = ops->vidioc_try_fmt_sliced_vbi_out(file,
 								fh, f);
 			break;
 		case V4L2_BUF_TYPE_PRIVATE:
 			/* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
-			if (ops->vidioc_try_fmt_type_private)
+			if (likely(ops->vidioc_try_fmt_type_private))
 				ret = ops->vidioc_try_fmt_type_private(file,
 								fh, f);
 			break;
 		}
-
+		if (unlikely(ret == -ENOTTY && have_fmt_ops(try)))
+			ret = -EINVAL;
 		break;
 	}
 	/* FIXME: Those buf reqs could be handled here,
@@ -1103,6 +884,10 @@
 
 		if (!ops->vidioc_reqbufs)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		ret = check_fmt(ops, p->type);
 		if (ret)
 			break;
@@ -1168,6 +953,10 @@
 
 		if (!ops->vidioc_overlay)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		dbgarg(cmd, "value=%d\n", *i);
 		ret = ops->vidioc_overlay(file, fh, *i);
 		break;
@@ -1193,6 +982,10 @@
 
 		if (!ops->vidioc_s_fbuf)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
 			p->capability, p->flags, (unsigned long)p->base);
 		v4l_print_pix_fmt(vfd, &p->fmt);
@@ -1205,6 +998,10 @@
 
 		if (!ops->vidioc_streamon)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
 		ret = ops->vidioc_streamon(file, fh, i);
 		break;
@@ -1215,6 +1012,10 @@
 
 		if (!ops->vidioc_streamoff)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
 		ret = ops->vidioc_streamoff(file, fh, i);
 		break;
@@ -1227,6 +1028,10 @@
 		unsigned int index = p->index, i, j = 0;
 		const char *descr = "";
 
+		if (id == 0)
+			break;
+		ret = -EINVAL;
+
 		/* Return norm array in a canonical way */
 		for (i = 0; i <= index && id; i++) {
 			/* last std value in the standards array is 0, so this
@@ -1262,16 +1067,15 @@
 	{
 		v4l2_std_id *id = arg;
 
-		ret = 0;
 		/* Calls the specific handler */
 		if (ops->vidioc_g_std)
 			ret = ops->vidioc_g_std(file, fh, id);
-		else if (vfd->current_norm)
+		else if (vfd->current_norm) {
+			ret = 0;
 			*id = vfd->current_norm;
-		else
-			ret = -EINVAL;
+		}
 
-		if (!ret)
+		if (likely(!ret))
 			dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id);
 		break;
 	}
@@ -1281,15 +1085,20 @@
 
 		dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
 
+		if (!ops->vidioc_s_std)
+			break;
+
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
+		ret = -EINVAL;
 		norm = (*id) & vfd->tvnorms;
 		if (vfd->tvnorms && !norm)	/* Check if std is supported */
 			break;
 
 		/* Calls the specific handler */
-		if (ops->vidioc_s_std)
-			ret = ops->vidioc_s_std(file, fh, &norm);
-		else
-			ret = -EINVAL;
+		ret = ops->vidioc_s_std(file, fh, &norm);
 
 		/* Updates standard information */
 		if (ret >= 0)
@@ -1302,6 +1111,14 @@
 
 		if (!ops->vidioc_querystd)
 			break;
+		/*
+		 * If nothing detected, it should return all supported
+		 * Drivers just need to mask the std argument, in order
+		 * to remove the standards that don't apply from the mask.
+		 * This means that tuners, audio and video decoders can join
+		 * their efforts to improve the standards detection
+		 */
+		*p = vfd->tvnorms;
 		ret = ops->vidioc_querystd(file, fh, arg);
 		if (!ret)
 			dbgarg(cmd, "detected std=%08Lx\n",
@@ -1358,6 +1175,10 @@
 
 		if (!ops->vidioc_s_input)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		dbgarg(cmd, "value=%d\n", *i);
 		ret = ops->vidioc_s_input(file, fh, *i);
 		break;
@@ -1410,6 +1231,10 @@
 
 		if (!ops->vidioc_s_output)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		dbgarg(cmd, "value=%d\n", *i);
 		ret = ops->vidioc_s_output(file, fh, *i);
 		break;
@@ -1479,6 +1304,10 @@
 		if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
 			!ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 
 		dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
 
@@ -1504,6 +1333,8 @@
 		ctrl.value = p->value;
 		if (check_ext_ctrls(&ctrls, 1))
 			ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls);
+		else
+			ret = -EINVAL;
 		break;
 	}
 	case VIDIOC_G_EXT_CTRLS:
@@ -1515,8 +1346,10 @@
 			ret = v4l2_g_ext_ctrls(vfh->ctrl_handler, p);
 		else if (vfd->ctrl_handler)
 			ret = v4l2_g_ext_ctrls(vfd->ctrl_handler, p);
-		else if (ops->vidioc_g_ext_ctrls && check_ext_ctrls(p, 0))
-			ret = ops->vidioc_g_ext_ctrls(file, fh, p);
+		else if (ops->vidioc_g_ext_ctrls)
+			ret = check_ext_ctrls(p, 0) ?
+				ops->vidioc_g_ext_ctrls(file, fh, p) :
+				-EINVAL;
 		else
 			break;
 		v4l_print_ext_ctrls(cmd, vfd, p, !ret);
@@ -1530,6 +1363,10 @@
 		if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
 				!ops->vidioc_s_ext_ctrls)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		v4l_print_ext_ctrls(cmd, vfd, p, 1);
 		if (vfh && vfh->ctrl_handler)
 			ret = v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p);
@@ -1537,6 +1374,8 @@
 			ret = v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p);
 		else if (check_ext_ctrls(p, 0))
 			ret = ops->vidioc_s_ext_ctrls(file, fh, p);
+		else
+			ret = -EINVAL;
 		break;
 	}
 	case VIDIOC_TRY_EXT_CTRLS:
@@ -1554,6 +1393,8 @@
 			ret = v4l2_try_ext_ctrls(vfd->ctrl_handler, p);
 		else if (check_ext_ctrls(p, 0))
 			ret = ops->vidioc_try_ext_ctrls(file, fh, p);
+		else
+			ret = -EINVAL;
 		break;
 	}
 	case VIDIOC_QUERYMENU:
@@ -1614,6 +1455,10 @@
 
 		if (!ops->vidioc_s_audio)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
 					"mode=0x%x\n", p->index, p->name,
 					p->capability, p->mode);
@@ -1654,6 +1499,10 @@
 
 		if (!ops->vidioc_s_audout)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		dbgarg(cmd, "index=%d, name=%s, capability=%d, "
 					"mode=%d\n", p->index, p->name,
 					p->capability, p->mode);
@@ -1683,6 +1532,10 @@
 
 		if (!ops->vidioc_s_modulator)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		dbgarg(cmd, "index=%d, name=%s, capability=%d, "
 				"rangelow=%d, rangehigh=%d, txsubchans=%d\n",
 				p->index, p->name, p->capability, p->rangelow,
@@ -1709,6 +1562,10 @@
 
 		if (!ops->vidioc_s_crop)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
 		dbgrect(vfd, "", &p->c);
 		ret = ops->vidioc_s_crop(file, fh, p);
@@ -1752,11 +1609,15 @@
 
 		if (!ops->vidioc_g_jpegcomp)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		dbgarg(cmd, "quality=%d, APPn=%d, APP_len=%d, "
 					"COM_len=%d, jpeg_markers=%d\n",
 					p->quality, p->APPn, p->APP_len,
 					p->COM_len, p->jpeg_markers);
-			ret = ops->vidioc_s_jpegcomp(file, fh, p);
+		ret = ops->vidioc_s_jpegcomp(file, fh, p);
 		break;
 	}
 	case VIDIOC_G_ENC_INDEX:
@@ -1777,6 +1638,10 @@
 
 		if (!ops->vidioc_encoder_cmd)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		ret = ops->vidioc_encoder_cmd(file, fh, p);
 		if (!ret)
 			dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
@@ -1797,6 +1662,8 @@
 	{
 		struct v4l2_streamparm *p = arg;
 
+		if (!ops->vidioc_g_parm && !vfd->current_norm)
+			break;
 		if (ops->vidioc_g_parm) {
 			ret = check_fmt(ops, p->type);
 			if (ret)
@@ -1805,14 +1672,13 @@
 		} else {
 			v4l2_std_id std = vfd->current_norm;
 
+			ret = -EINVAL;
 			if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 				break;
 
 			ret = 0;
 			if (ops->vidioc_g_std)
 				ret = ops->vidioc_g_std(file, fh, &std);
-			else if (std == 0)
-				ret = -EINVAL;
 			if (ret == 0)
 				v4l2_video_std_frame_period(std,
 						    &p->parm.capture.timeperframe);
@@ -1827,6 +1693,10 @@
 
 		if (!ops->vidioc_s_parm)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		ret = check_fmt(ops, p->type);
 		if (ret)
 			break;
@@ -1862,6 +1732,10 @@
 
 		if (!ops->vidioc_s_tuner)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
 			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
 		dbgarg(cmd, "index=%d, name=%s, type=%d, "
@@ -1896,6 +1770,10 @@
 
 		if (!ops->vidioc_s_frequency)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
 				p->tuner, p->type, p->frequency);
 		ret = ops->vidioc_s_frequency(file, fh, p);
@@ -1970,6 +1848,10 @@
 
 		if (!ops->vidioc_s_hw_freq_seek)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 		type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
 			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
 		dbgarg(cmd,
@@ -2074,6 +1956,10 @@
 
 		if (!ops->vidioc_s_dv_preset)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 
 		dbgarg(cmd, "preset=%d\n", p->preset);
 		ret = ops->vidioc_s_dv_preset(file, fh, p);
@@ -2109,6 +1995,10 @@
 
 		if (!ops->vidioc_s_dv_timings)
 			break;
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
 
 		switch (p->type) {
 		case V4L2_DV_BT_656_1120:
@@ -2216,20 +2106,47 @@
 		dbgarg(cmd, "type=0x%8.8x", sub->type);
 		break;
 	}
-	default:
+	case VIDIOC_CREATE_BUFS:
 	{
-		bool valid_prio = true;
+		struct v4l2_create_buffers *create = arg;
 
-		if (!ops->vidioc_default)
+		if (!ops->vidioc_create_bufs)
 			break;
-		if (use_fh_prio)
-			valid_prio = v4l2_prio_check(vfd->prio, vfh->prio) >= 0;
-		ret = ops->vidioc_default(file, fh, valid_prio, cmd, arg);
+		if (ret_prio) {
+			ret = ret_prio;
+			break;
+		}
+		ret = check_fmt(ops, create->format.type);
+		if (ret)
+			break;
+
+		ret = ops->vidioc_create_bufs(file, fh, create);
+
+		dbgarg(cmd, "count=%d @ %d\n", create->count, create->index);
+		break;
+	}
+	case VIDIOC_PREPARE_BUF:
+	{
+		struct v4l2_buffer *b = arg;
+
+		if (!ops->vidioc_prepare_buf)
+			break;
+		ret = check_fmt(ops, b->type);
+		if (ret)
+			break;
+
+		ret = ops->vidioc_prepare_buf(file, fh, b);
+
+		dbgarg(cmd, "index=%d", b->index);
 		break;
 	}
+	default:
+		if (!ops->vidioc_default)
+			break;
+		ret = ops->vidioc_default(file, fh, ret_prio >= 0, cmd, arg);
+		break;
 	} /* switch */
 
-exit_prio:
 	if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
 		if (ret < 0) {
 			v4l_print_ioctl(vfd->name, cmd);
diff -druN linux-libre-3.1-gnu/drivers/media/video/v4l2-mem2mem.c linux-libre-3.2-gnu/drivers/media/video/v4l2-mem2mem.c
--- linux-libre-3.1-gnu/drivers/media/video/v4l2-mem2mem.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/v4l2-mem2mem.c	2012-01-04 18:55:44.000000000 -0500
@@ -97,11 +97,12 @@
 
 	spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
 
-	if (list_empty(&q_ctx->rdy_queue))
-		goto end;
+	if (list_empty(&q_ctx->rdy_queue)) {
+		spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
+		return NULL;
+	}
 
 	b = list_entry(q_ctx->rdy_queue.next, struct v4l2_m2m_buffer, list);
-end:
 	spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
 	return &b->vb;
 }
@@ -117,12 +118,13 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
-	if (!list_empty(&q_ctx->rdy_queue)) {
-		b = list_entry(q_ctx->rdy_queue.next, struct v4l2_m2m_buffer,
-				list);
-		list_del(&b->list);
-		q_ctx->num_rdy--;
+	if (list_empty(&q_ctx->rdy_queue)) {
+		spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
+		return NULL;
 	}
+	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->rdy_spinlock, flags);
 
 	return &b->vb;
diff -druN linux-libre-3.1-gnu/drivers/media/video/v4l2-subdev.c linux-libre-3.2-gnu/drivers/media/video/v4l2-subdev.c
--- linux-libre-3.1-gnu/drivers/media/video/v4l2-subdev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/v4l2-subdev.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/videodev2.h>
+#include <linux/export.h>
 
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
@@ -173,6 +174,25 @@
 
 	case VIDIOC_UNSUBSCRIBE_EVENT:
 		return v4l2_subdev_call(sd, core, unsubscribe_event, vfh, arg);
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	case VIDIOC_DBG_G_REGISTER:
+	{
+		struct v4l2_dbg_register *p = arg;
+
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		return v4l2_subdev_call(sd, core, g_register, p);
+	}
+	case VIDIOC_DBG_S_REGISTER:
+	{
+		struct v4l2_dbg_register *p = arg;
+
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		return v4l2_subdev_call(sd, core, s_register, p);
+	}
+#endif
 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
 	case VIDIOC_SUBDEV_G_FMT: {
 		struct v4l2_subdev_format *format = arg;
diff -druN linux-libre-3.1-gnu/drivers/media/video/via-camera.c linux-libre-3.2-gnu/drivers/media/video/via-camera.c
--- linux-libre-3.1-gnu/drivers/media/video/via-camera.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/via-camera.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
 #include <media/videobuf-dma-sg.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
 #include <linux/via-core.h>
 #include <linux/via-gpio.h>
 #include <linux/via_i2c.h>
@@ -69,7 +69,7 @@
 	struct mutex lock;
 	enum viacam_opstate opstate;
 	unsigned long flags;
-	struct pm_qos_request_list qos_request;
+	struct pm_qos_request qos_request;
 	/*
 	 * GPIO info for power/reset management
 	 */
diff -druN linux-libre-3.1-gnu/drivers/media/video/videobuf2-core.c linux-libre-3.2-gnu/drivers/media/video/videobuf2-core.c
--- linux-libre-3.1-gnu/drivers/media/video/videobuf2-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/videobuf2-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,13 +38,13 @@
 	(((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)
+				 V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \
+				 V4L2_BUF_FLAG_PREPARED)
 
 /**
  * __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)
+static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
 	struct vb2_queue *q = vb->vb2_queue;
 	void *mem_priv;
@@ -53,13 +53,13 @@
 	/* 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]);
+				      q->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];
+		vb->v4l2_planes[plane].length = q->plane_sizes[plane];
 	}
 
 	return 0;
@@ -110,18 +110,28 @@
  * __setup_offsets() - setup unique offsets ("cookies") for every plane in
  * every buffer on the queue
  */
-static void __setup_offsets(struct vb2_queue *q)
+static void __setup_offsets(struct vb2_queue *q, unsigned int n)
 {
 	unsigned int buffer, plane;
 	struct vb2_buffer *vb;
-	unsigned long off = 0;
+	unsigned long off;
 
-	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+	if (q->num_buffers) {
+		struct v4l2_plane *p;
+		vb = q->bufs[q->num_buffers - 1];
+		p = &vb->v4l2_planes[vb->num_planes - 1];
+		off = PAGE_ALIGN(p->m.mem_offset + p->length);
+	} else {
+		off = 0;
+	}
+
+	for (buffer = q->num_buffers; buffer < q->num_buffers + n; ++buffer) {
 		vb = q->bufs[buffer];
 		if (!vb)
 			continue;
 
 		for (plane = 0; plane < vb->num_planes; ++plane) {
+			vb->v4l2_planes[plane].length = q->plane_sizes[plane];
 			vb->v4l2_planes[plane].m.mem_offset = off;
 
 			dprintk(3, "Buffer %d, plane %d offset 0x%08lx\n",
@@ -141,8 +151,7 @@
  * 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 num_buffers, unsigned int num_planes)
 {
 	unsigned int buffer;
 	struct vb2_buffer *vb;
@@ -163,13 +172,13 @@
 		vb->state = VB2_BUF_STATE_DEQUEUED;
 		vb->vb2_queue = q;
 		vb->num_planes = num_planes;
-		vb->v4l2_buf.index = buffer;
+		vb->v4l2_buf.index = q->num_buffers + 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);
+			ret = __vb2_buf_mem_alloc(vb);
 			if (ret) {
 				dprintk(1, "Failed allocating memory for "
 						"buffer %d\n", buffer);
@@ -191,15 +200,13 @@
 			}
 		}
 
-		q->bufs[buffer] = vb;
+		q->bufs[q->num_buffers + buffer] = vb;
 	}
 
-	q->num_buffers = buffer;
-
-	__setup_offsets(q);
+	__setup_offsets(q, buffer);
 
 	dprintk(1, "Allocated %d buffers, %d plane(s) each\n",
-			q->num_buffers, num_planes);
+			buffer, num_planes);
 
 	return buffer;
 }
@@ -207,12 +214,13 @@
 /**
  * __vb2_free_mem() - release all video buffer memory for a given queue
  */
-static void __vb2_free_mem(struct vb2_queue *q)
+static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
 {
 	unsigned int buffer;
 	struct vb2_buffer *vb;
 
-	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
+	     ++buffer) {
 		vb = q->bufs[buffer];
 		if (!vb)
 			continue;
@@ -226,17 +234,18 @@
 }
 
 /**
- * __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.
+ * __vb2_queue_free() - free buffers at the end of the queue - video memory and
+ * related information, if no buffers are left 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)
+static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 {
 	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) {
+		for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
+		     ++buffer) {
 			if (NULL == q->bufs[buffer])
 				continue;
 			q->ops->buf_cleanup(q->bufs[buffer]);
@@ -244,23 +253,26 @@
 	}
 
 	/* Release video buffer memory */
-	__vb2_free_mem(q);
+	__vb2_free_mem(q, buffers);
 
 	/* Free videobuf buffers */
-	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
+	     ++buffer) {
 		kfree(q->bufs[buffer]);
 		q->bufs[buffer] = NULL;
 	}
 
-	q->num_buffers = 0;
-	q->memory = 0;
+	q->num_buffers -= buffers;
+	if (!q->num_buffers)
+		q->memory = 0;
+	INIT_LIST_HEAD(&q->queued_list);
 }
 
 /**
  * __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)
+static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
 	/* Is memory for copying plane information present? */
 	if (NULL == b->m.planes) {
@@ -279,13 +291,48 @@
 }
 
 /**
+ * __buffer_in_use() - return true if the buffer is in use and
+ * the queue cannot be freed (by the means of REQBUFS(0)) call
+ */
+static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
+{
+	unsigned int plane;
+	for (plane = 0; plane < vb->num_planes; ++plane) {
+		void *mem_priv = vb->planes[plane].mem_priv;
+		/*
+		 * 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 (mem_priv && call_memop(q, plane, num_users, mem_priv) > 1)
+			return true;
+	}
+	return false;
+}
+
+/**
+ * __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;
+	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+		if (__buffer_in_use(q, q->bufs[buffer]))
+			return true;
+	}
+	return false;
+}
+
+/**
  * __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;
+	int ret;
 
 	/* Copy back data such as timestamp, flags, input, etc. */
 	memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
@@ -332,15 +379,18 @@
 	case VB2_BUF_STATE_DONE:
 		b->flags |= V4L2_BUF_FLAG_DONE;
 		break;
+	case VB2_BUF_STATE_PREPARED:
+		b->flags |= V4L2_BUF_FLAG_PREPARED;
+		break;
 	case VB2_BUF_STATE_DEQUEUED:
 		/* nothing */
 		break;
 	}
 
-	if (vb->num_planes_mapped == vb->num_planes)
+	if (__buffer_in_use(q, vb))
 		b->flags |= V4L2_BUF_FLAG_MAPPED;
 
-	return ret;
+	return 0;
 }
 
 /**
@@ -402,33 +452,6 @@
 }
 
 /**
- * __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
@@ -453,8 +476,7 @@
  */
 int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
 {
-	unsigned int num_buffers, num_planes;
-	unsigned long plane_sizes[VIDEO_MAX_PLANES];
+	unsigned int num_buffers, allocated_buffers, num_planes = 0;
 	int ret = 0;
 
 	if (q->fileio) {
@@ -502,7 +524,7 @@
 			return -EBUSY;
 		}
 
-		__vb2_queue_free(q);
+		__vb2_queue_free(q, q->num_buffers);
 
 		/*
 		 * In case of REQBUFS(0) return immediately without calling
@@ -516,7 +538,7 @@
 	 * 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->plane_sizes, 0, sizeof(q->plane_sizes));
 	memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
 	q->memory = req->memory;
 
@@ -524,57 +546,180 @@
 	 * 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);
+	ret = call_qop(q, queue_setup, q, NULL, &num_buffers, &num_planes,
+		       q->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);
+	ret = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes);
 	if (ret == 0) {
 		dprintk(1, "Memory allocation failed\n");
 		return -ENOMEM;
 	}
 
+	allocated_buffers = ret;
+
 	/*
 	 * Check if driver can handle the allocated number of buffers.
 	 */
-	if (ret < num_buffers) {
-		unsigned int orig_num_buffers;
+	if (allocated_buffers < num_buffers) {
+		num_buffers = allocated_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;
+		ret = call_qop(q, queue_setup, q, NULL, &num_buffers,
+			       &num_planes, q->plane_sizes, q->alloc_ctx);
 
-		if (orig_num_buffers < num_buffers) {
+		if (!ret && allocated_buffers < num_buffers)
 			ret = -ENOMEM;
-			goto free_mem;
-		}
 
 		/*
-		 * Ok, driver accepted smaller number of buffers.
+		 * Either the driver has accepted a smaller number of buffers,
+		 * or .queue_setup() returned an error
 		 */
-		ret = num_buffers;
+	}
+
+	q->num_buffers = allocated_buffers;
+
+	if (ret < 0) {
+		__vb2_queue_free(q, allocated_buffers);
+		return ret;
 	}
 
 	/*
 	 * Return the number of successfully allocated buffers
 	 * to the userspace.
 	 */
-	req->count = ret;
+	req->count = allocated_buffers;
 
 	return 0;
-
-free_mem:
-	__vb2_queue_free(q);
-	return ret;
 }
 EXPORT_SYMBOL_GPL(vb2_reqbufs);
 
 /**
+ * vb2_create_bufs() - Allocate buffers and any required auxiliary structs
+ * @q:		videobuf2 queue
+ * @create:	creation parameters, passed from userspace to vidioc_create_bufs
+ *		handler in driver
+ *
+ * Should be called from vidioc_create_bufs ioctl handler of a driver.
+ * This function:
+ * 1) verifies parameter sanity
+ * 2) calls the .queue_setup() queue operation
+ * 3) performs any necessary memory allocations
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_create_bufs handler in driver.
+ */
+int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
+{
+	unsigned int num_planes = 0, num_buffers, allocated_buffers;
+	int ret = 0;
+
+	if (q->fileio) {
+		dprintk(1, "%s(): file io in progress\n", __func__);
+		return -EBUSY;
+	}
+
+	if (create->memory != V4L2_MEMORY_MMAP
+			&& create->memory != V4L2_MEMORY_USERPTR) {
+		dprintk(1, "%s(): unsupported memory type\n", __func__);
+		return -EINVAL;
+	}
+
+	if (create->format.type != q->type) {
+		dprintk(1, "%s(): requested type is incorrect\n", __func__);
+		return -EINVAL;
+	}
+
+	/*
+	 * Make sure all the required memory ops for given memory type
+	 * are available.
+	 */
+	if (create->memory == V4L2_MEMORY_MMAP && __verify_mmap_ops(q)) {
+		dprintk(1, "%s(): MMAP for current setup unsupported\n", __func__);
+		return -EINVAL;
+	}
+
+	if (create->memory == V4L2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
+		dprintk(1, "%s(): USERPTR for current setup unsupported\n", __func__);
+		return -EINVAL;
+	}
+
+	if (q->num_buffers == VIDEO_MAX_FRAME) {
+		dprintk(1, "%s(): maximum number of buffers already allocated\n",
+			__func__);
+		return -ENOBUFS;
+	}
+
+	create->index = q->num_buffers;
+
+	if (!q->num_buffers) {
+		memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
+		memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
+		q->memory = create->memory;
+	}
+
+	num_buffers = min(create->count, VIDEO_MAX_FRAME - q->num_buffers);
+
+	/*
+	 * Ask the driver, whether the requested number of buffers, planes per
+	 * buffer and their sizes are acceptable
+	 */
+	ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
+		       &num_planes, q->plane_sizes, q->alloc_ctx);
+	if (ret)
+		return ret;
+
+	/* Finally, allocate buffers and video memory */
+	ret = __vb2_queue_alloc(q, create->memory, num_buffers,
+				num_planes);
+	if (ret < 0) {
+		dprintk(1, "Memory allocation failed with error: %d\n", ret);
+		return ret;
+	}
+
+	allocated_buffers = ret;
+
+	/*
+	 * Check if driver can handle the so far allocated number of buffers.
+	 */
+	if (ret < num_buffers) {
+		num_buffers = ret;
+
+		/*
+		 * q->num_buffers contains the total number of buffers, that the
+		 * queue driver has set up
+		 */
+		ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
+			       &num_planes, q->plane_sizes, q->alloc_ctx);
+
+		if (!ret && allocated_buffers < num_buffers)
+			ret = -ENOMEM;
+
+		/*
+		 * Either the driver has accepted a smaller number of buffers,
+		 * or .queue_setup() returned an error
+		 */
+	}
+
+	q->num_buffers += allocated_buffers;
+
+	if (ret < 0) {
+		__vb2_queue_free(q, allocated_buffers);
+		return ret;
+	}
+
+	/*
+	 * Return the number of successfully allocated buffers
+	 * to the userspace.
+	 */
+	create->count = allocated_buffers;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_create_bufs);
+
+/**
  * 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
@@ -658,7 +803,7 @@
  * __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,
+static int __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
 				struct v4l2_plane *v4l2_planes)
 {
 	unsigned int plane;
@@ -722,7 +867,7 @@
 /**
  * __qbuf_userptr() - handle qbuf of a USERPTR buffer
  */
-static int __qbuf_userptr(struct vb2_buffer *vb, struct v4l2_buffer *b)
+static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
 	struct v4l2_plane planes[VIDEO_MAX_PLANES];
 	struct vb2_queue *q = vb->vb2_queue;
@@ -745,12 +890,20 @@
 		dprintk(3, "qbuf: userspace address for plane %d changed, "
 				"reacquiring memory\n", plane);
 
+		/* Check if the provided plane buffer is large enough */
+		if (planes[plane].length < q->plane_sizes[plane]) {
+			ret = -EINVAL;
+			goto err;
+		}
+
 		/* 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;
+		vb->v4l2_planes[plane].m.userptr = 0;
+		vb->v4l2_planes[plane].length = 0;
 
 		/* Acquire each plane's memory */
 		if (q->mem_ops->get_userptr) {
@@ -788,10 +941,13 @@
 	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;
+	for (plane = 0; plane < vb->num_planes; ++plane) {
+		if (vb->planes[plane].mem_priv)
+			call_memop(q, plane, put_userptr,
+				   vb->planes[plane].mem_priv);
+		vb->planes[plane].mem_priv = NULL;
+		vb->v4l2_planes[plane].m.userptr = 0;
+		vb->v4l2_planes[plane].length = 0;
 	}
 
 	return ret;
@@ -800,7 +956,7 @@
 /**
  * __qbuf_mmap() - handle qbuf of an MMAP buffer
  */
-static int __qbuf_mmap(struct vb2_buffer *vb, struct v4l2_buffer *b)
+static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
 	return __fill_vb2_buffer(vb, b, vb->v4l2_planes);
 }
@@ -817,6 +973,95 @@
 	q->ops->buf_queue(vb);
 }
 
+static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+{
+	struct vb2_queue *q = vb->vb2_queue;
+	int ret;
+
+	switch (q->memory) {
+	case V4L2_MEMORY_MMAP:
+		ret = __qbuf_mmap(vb, b);
+		break;
+	case V4L2_MEMORY_USERPTR:
+		ret = __qbuf_userptr(vb, b);
+		break;
+	default:
+		WARN(1, "Invalid queue type\n");
+		ret = -EINVAL;
+	}
+
+	if (!ret)
+		ret = call_qop(q, buf_prepare, vb);
+	if (ret)
+		dprintk(1, "qbuf: buffer preparation failed: %d\n", ret);
+	else
+		vb->state = VB2_BUF_STATE_PREPARED;
+
+	return ret;
+}
+
+/**
+ * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
+ * @q:		videobuf2 queue
+ * @b:		buffer structure passed from userspace to vidioc_prepare_buf
+ *		handler in driver
+ *
+ * Should be called from vidioc_prepare_buf 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,
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_prepare_buf handler in driver.
+ */
+int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+	struct vb2_buffer *vb;
+	int ret;
+
+	if (q->fileio) {
+		dprintk(1, "%s(): file io in progress\n", __func__);
+		return -EBUSY;
+	}
+
+	if (b->type != q->type) {
+		dprintk(1, "%s(): invalid buffer type\n", __func__);
+		return -EINVAL;
+	}
+
+	if (b->index >= q->num_buffers) {
+		dprintk(1, "%s(): buffer index out of range\n", __func__);
+		return -EINVAL;
+	}
+
+	vb = q->bufs[b->index];
+	if (NULL == vb) {
+		/* Should never happen */
+		dprintk(1, "%s(): buffer is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (b->memory != q->memory) {
+		dprintk(1, "%s(): invalid memory type\n", __func__);
+		return -EINVAL;
+	}
+
+	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
+		dprintk(1, "%s(): invalid buffer state %d\n", __func__, vb->state);
+		return -EINVAL;
+	}
+
+	ret = __buf_prepare(vb, b);
+	if (ret < 0)
+		return ret;
+
+	__fill_v4l2_buffer(vb, b);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_prepare_buf);
+
 /**
  * vb2_qbuf() - Queue a buffer from userspace
  * @q:		videobuf2 queue
@@ -826,8 +1071,8 @@
  * 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,
+ * 2) if necessary, 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.
  *
@@ -837,7 +1082,7 @@
 int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
 {
 	struct vb2_buffer *vb;
-	int ret = 0;
+	int ret;
 
 	if (q->fileio) {
 		dprintk(1, "qbuf: file io in progress\n");
@@ -866,29 +1111,18 @@
 		return -EINVAL;
 	}
 
-	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
+	switch (vb->state) {
+	case VB2_BUF_STATE_DEQUEUED:
+		ret = __buf_prepare(vb, b);
+		if (ret)
+			return ret;
+	case VB2_BUF_STATE_PREPARED:
+		break;
+	default:
 		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.
@@ -903,6 +1137,9 @@
 	if (q->streaming)
 		__enqueue_in_driver(vb);
 
+	/* Fill buffer information for the userspace */
+	__fill_v4l2_buffer(vb, b);
+
 	dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index);
 	return 0;
 }
@@ -1096,6 +1333,43 @@
 EXPORT_SYMBOL_GPL(vb2_dqbuf);
 
 /**
+ * __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);
+	atomic_set(&q->queued_count, 0);
+	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_streamon - start streaming
  * @q:		videobuf2 queue
  * @type:	type argument passed from userspace to vidioc_streamon handler
@@ -1103,7 +1377,7 @@
  * 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
+ * 2) passes any previously queued buffers to the driver and starts streaming
  *
  * The return values from this function are intended to be directly returned
  * from vidioc_streamon handler in the driver.
@@ -1129,75 +1403,29 @@
 	}
 
 	/*
-	 * Cannot start streaming on an OUTPUT device if no buffers have
-	 * been queued yet.
+	 * If any buffers were queued before streamon,
+	 * we can now pass them to driver for processing.
 	 */
-	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
-		if (list_empty(&q->queued_list)) {
-			dprintk(1, "streamon: no output buffers queued\n");
-			return -EINVAL;
-		}
-	}
+	list_for_each_entry(vb, &q->queued_list, queued_entry)
+		__enqueue_in_driver(vb);
 
 	/*
 	 * Let driver notice that streaming state has been enabled.
 	 */
-	ret = call_qop(q, start_streaming, q);
+	ret = call_qop(q, start_streaming, q, atomic_read(&q->queued_count));
 	if (ret) {
 		dprintk(1, "streamon: driver refused to start streaming\n");
+		__vb2_queue_cancel(q);
 		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);
-	atomic_set(&q->queued_count, 0);
-	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
@@ -1336,14 +1564,42 @@
 	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);
 
+#ifndef CONFIG_MMU
+unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
+				    unsigned long addr,
+				    unsigned long len,
+				    unsigned long pgoff,
+				    unsigned long flags)
+{
+	unsigned long off = pgoff << PAGE_SHIFT;
+	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;
+	}
+
+	/*
+	 * 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];
+
+	return (unsigned long)vb2_plane_vaddr(vb, plane);
+}
+EXPORT_SYMBOL_GPL(vb2_get_unmapped_area);
+#endif
+
 static int __vb2_init_fileio(struct vb2_queue *q, int read);
 static int __vb2_cleanup_fileio(struct vb2_queue *q);
 
@@ -1461,7 +1717,7 @@
 {
 	__vb2_cleanup_fileio(q);
 	__vb2_queue_cancel(q);
-	__vb2_queue_free(q);
+	__vb2_queue_free(q, q->num_buffers);
 }
 EXPORT_SYMBOL_GPL(vb2_queue_release);
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/videobuf2-dma-contig.c linux-libre-3.2-gnu/drivers/media/video/videobuf2-dma-contig.c
--- linux-libre-3.1-gnu/drivers/media/video/videobuf2-dma-contig.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/videobuf2-dma-contig.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,7 +24,7 @@
 struct vb2_dc_buf {
 	struct vb2_dc_conf		*conf;
 	void				*vaddr;
-	dma_addr_t			paddr;
+	dma_addr_t			dma_addr;
 	unsigned long			size;
 	struct vm_area_struct		*vma;
 	atomic_t			refcount;
@@ -42,7 +42,7 @@
 	if (!buf)
 		return ERR_PTR(-ENOMEM);
 
-	buf->vaddr = dma_alloc_coherent(conf->dev, size, &buf->paddr,
+	buf->vaddr = dma_alloc_coherent(conf->dev, size, &buf->dma_addr,
 					GFP_KERNEL);
 	if (!buf->vaddr) {
 		dev_err(conf->dev, "dma_alloc_coherent of size %ld failed\n",
@@ -69,7 +69,7 @@
 
 	if (atomic_dec_and_test(&buf->refcount)) {
 		dma_free_coherent(buf->conf->dev, buf->size, buf->vaddr,
-				  buf->paddr);
+				  buf->dma_addr);
 		kfree(buf);
 	}
 }
@@ -78,7 +78,7 @@
 {
 	struct vb2_dc_buf *buf = buf_priv;
 
-	return &buf->paddr;
+	return &buf->dma_addr;
 }
 
 static void *vb2_dma_contig_vaddr(void *buf_priv)
@@ -106,7 +106,7 @@
 		return -EINVAL;
 	}
 
-	return vb2_mmap_pfn_range(vma, buf->paddr, buf->size,
+	return vb2_mmap_pfn_range(vma, buf->dma_addr, buf->size,
 				  &vb2_common_vm_ops, &buf->handler);
 }
 
@@ -115,14 +115,14 @@
 {
 	struct vb2_dc_buf *buf;
 	struct vm_area_struct *vma;
-	dma_addr_t paddr = 0;
+	dma_addr_t dma_addr = 0;
 	int ret;
 
 	buf = kzalloc(sizeof *buf, GFP_KERNEL);
 	if (!buf)
 		return ERR_PTR(-ENOMEM);
 
-	ret = vb2_get_contig_userptr(vaddr, size, &vma, &paddr);
+	ret = vb2_get_contig_userptr(vaddr, size, &vma, &dma_addr);
 	if (ret) {
 		printk(KERN_ERR "Failed acquiring VMA for vaddr 0x%08lx\n",
 				vaddr);
@@ -131,7 +131,7 @@
 	}
 
 	buf->size = size;
-	buf->paddr = paddr;
+	buf->dma_addr = dma_addr;
 	buf->vma = vma;
 
 	return buf;
diff -druN linux-libre-3.1-gnu/drivers/media/video/videobuf2-dma-sg.c linux-libre-3.2-gnu/drivers/media/video/videobuf2-dma-sg.c
--- linux-libre-3.1-gnu/drivers/media/video/videobuf2-dma-sg.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/videobuf2-dma-sg.c	2012-01-04 18:55:44.000000000 -0500
@@ -75,12 +75,6 @@
 
 	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:
diff -druN linux-libre-3.1-gnu/drivers/media/video/videobuf2-memops.c linux-libre-3.2-gnu/drivers/media/video/videobuf2-memops.c
--- linux-libre-3.1-gnu/drivers/media/video/videobuf2-memops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/videobuf2-memops.c	2012-01-04 18:55:44.000000000 -0500
@@ -68,12 +68,12 @@
 	if (!vma)
 		return;
 
-	if (vma->vm_file)
-		fput(vma->vm_file);
-
 	if (vma->vm_ops && vma->vm_ops->close)
 		vma->vm_ops->close(vma);
 
+	if (vma->vm_file)
+		fput(vma->vm_file);
+
 	kfree(vma);
 }
 EXPORT_SYMBOL_GPL(vb2_put_vma);
diff -druN linux-libre-3.1-gnu/drivers/media/video/vivi.c linux-libre-3.2-gnu/drivers/media/video/vivi.c
--- linux-libre-3.1-gnu/drivers/media/video/vivi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/vivi.c	2012-01-04 18:55:44.000000000 -0500
@@ -650,9 +650,9 @@
 /* ------------------------------------------------------------------
 	Videobuf operations
    ------------------------------------------------------------------*/
-static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
-				unsigned int *nplanes, unsigned long sizes[],
-				void *alloc_ctxs[])
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+				unsigned int *nbuffers, unsigned int *nplanes,
+				unsigned int sizes[], void *alloc_ctxs[])
 {
 	struct vivi_dev *dev = vb2_get_drv_priv(vq);
 	unsigned long size;
@@ -766,7 +766,7 @@
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
 
-static int start_streaming(struct vb2_queue *vq)
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct vivi_dev *dev = vb2_get_drv_priv(vq);
 	dprintk(dev, 1, "%s\n", __func__);
@@ -852,6 +852,11 @@
 		(f->fmt.pix.width * dev->fmt->depth) >> 3;
 	f->fmt.pix.sizeimage =
 		f->fmt.pix.height * f->fmt.pix.bytesperline;
+	if (dev->fmt->fourcc == V4L2_PIX_FMT_YUYV ||
+	    dev->fmt->fourcc == V4L2_PIX_FMT_UYVY)
+		f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+	else
+		f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
 	return 0;
 }
 
@@ -885,6 +890,11 @@
 		(f->fmt.pix.width * fmt->depth) >> 3;
 	f->fmt.pix.sizeimage =
 		f->fmt.pix.height * f->fmt.pix.bytesperline;
+	if (fmt->fourcc == V4L2_PIX_FMT_YUYV ||
+	    fmt->fourcc == V4L2_PIX_FMT_UYVY)
+		f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+	else
+		f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
 	return 0;
 }
 
@@ -948,6 +958,14 @@
 	return vb2_streamoff(&dev->vb_vidq, i);
 }
 
+static int vidioc_log_status(struct file *file, void *priv)
+{
+	struct vivi_dev *dev = video_drvdata(file);
+
+	v4l2_ctrl_handler_log_status(&dev->ctrl_handler, dev->v4l2_dev.name);
+	return 0;
+}
+
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
 {
 	return 0;
@@ -1191,6 +1209,7 @@
 	.vidioc_s_input       = vidioc_s_input,
 	.vidioc_streamon      = vidioc_streamon,
 	.vidioc_streamoff     = vidioc_streamoff,
+	.vidioc_log_status    = vidioc_log_status,
 	.vidioc_subscribe_event = vidioc_subscribe_event,
 	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
diff -druN linux-libre-3.1-gnu/drivers/media/video/vpx3220.c linux-libre-3.2-gnu/drivers/media/video/vpx3220.c
--- linux-libre-3.1-gnu/drivers/media/video/vpx3220.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/vpx3220.c	2012-01-04 18:55:44.000000000 -0500
@@ -331,7 +331,7 @@
 	if (pstd)
 		*pstd = std;
 	if (pstatus)
-		*pstatus = status;
+		*pstatus = res;
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/media/video/zr364xx.c linux-libre-3.2-gnu/drivers/media/video/zr364xx.c
--- linux-libre-3.1-gnu/drivers/media/video/zr364xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/media/video/zr364xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -1638,6 +1638,9 @@
 
 	if (!cam->read_endpoint) {
 		dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
+		video_device_release(cam->vdev);
+		kfree(cam);
+		cam = NULL;
 		return -ENOMEM;
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/memstick/core/memstick.c linux-libre-3.2-gnu/drivers/memstick/core/memstick.c
--- linux-libre-3.1-gnu/drivers/memstick/core/memstick.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/memstick/core/memstick.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/fs.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define DRIVER_NAME "memstick"
 
diff -druN linux-libre-3.1-gnu/drivers/memstick/core/mspro_block.c linux-libre-3.2-gnu/drivers/memstick/core/mspro_block.c
--- linux-libre-3.1-gnu/drivers/memstick/core/mspro_block.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/memstick/core/mspro_block.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/memstick.h>
+#include <linux/module.h>
 
 #define DRIVER_NAME "mspro_block"
 
diff -druN linux-libre-3.1-gnu/drivers/memstick/host/jmb38x_ms.c linux-libre-3.2-gnu/drivers/memstick/host/jmb38x_ms.c
--- linux-libre-3.1-gnu/drivers/memstick/host/jmb38x_ms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/memstick/host/jmb38x_ms.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/highmem.h>
 #include <linux/memstick.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define DRIVER_NAME "jmb38x_ms"
 
diff -druN linux-libre-3.1-gnu/drivers/memstick/host/tifm_ms.c linux-libre-3.2-gnu/drivers/memstick/host/tifm_ms.c
--- linux-libre-3.1-gnu/drivers/memstick/host/tifm_ms.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/memstick/host/tifm_ms.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/highmem.h>
 #include <linux/scatterlist.h>
 #include <linux/log2.h>
+#include <linux/module.h>
 #include <asm/io.h>
 
 #define DRIVER_NAME "tifm_ms"
diff -druN linux-libre-3.1-gnu/drivers/message/fusion/mptbase.c linux-libre-3.2-gnu/drivers/message/fusion/mptbase.c
--- linux-libre-3.1-gnu/drivers/message/fusion/mptbase.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/message/fusion/mptbase.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,6 +63,8 @@
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
 #endif
+#include <linux/kthread.h>
+#include <scsi/scsi_host.h>
 
 #include "mptbase.h"
 #include "lsi/mpi_log_fc.h"
@@ -323,6 +325,32 @@
 	return rc;
 }
 
+
+/**
+ *  mpt_remove_dead_ioc_func - kthread context to remove dead ioc
+ * @arg: input argument, used to derive ioc
+ *
+ * Return 0 if controller is removed from pci subsystem.
+ * Return -1 for other case.
+ */
+static int mpt_remove_dead_ioc_func(void *arg)
+{
+	MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
+	struct pci_dev *pdev;
+
+	if ((ioc == NULL))
+		return -1;
+
+	pdev = ioc->pcidev;
+	if ((pdev == NULL))
+		return -1;
+
+	pci_remove_bus_device(pdev);
+	return 0;
+}
+
+
+
 /**
  *	mpt_fault_reset_work - work performed on workq after ioc fault
  *	@work: input argument, used to derive ioc
@@ -336,12 +364,45 @@
 	u32		 ioc_raw_state;
 	int		 rc;
 	unsigned long	 flags;
+	MPT_SCSI_HOST	*hd;
+	struct task_struct *p;
 
 	if (ioc->ioc_reset_in_progress || !ioc->active)
 		goto out;
 
+
 	ioc_raw_state = mpt_GetIocState(ioc, 0);
-	if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
+	if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_MASK) {
+		printk(MYIOC_s_INFO_FMT "%s: IOC is non-operational !!!!\n",
+		    ioc->name, __func__);
+
+		/*
+		 * Call mptscsih_flush_pending_cmds callback so that we
+		 * flush all pending commands back to OS.
+		 * This call is required to aovid deadlock at block layer.
+		 * Dead IOC will fail to do diag reset,and this call is safe
+		 * since dead ioc will never return any command back from HW.
+		 */
+		hd = shost_priv(ioc->sh);
+		ioc->schedule_dead_ioc_flush_running_cmds(hd);
+
+		/*Remove the Dead Host */
+		p = kthread_run(mpt_remove_dead_ioc_func, ioc,
+				"mpt_dead_ioc_%d", ioc->id);
+		if (IS_ERR(p))	{
+			printk(MYIOC_s_ERR_FMT
+				"%s: Running mpt_dead_ioc thread failed !\n",
+				ioc->name, __func__);
+		} else {
+			printk(MYIOC_s_WARN_FMT
+				"%s: Running mpt_dead_ioc thread success !\n",
+				ioc->name, __func__);
+		}
+		return; /* don't rearm timer */
+	}
+
+	if ((ioc_raw_state & MPI_IOC_STATE_MASK)
+			== MPI_IOC_STATE_FAULT) {
 		printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n",
 		       ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
 		printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
@@ -6413,8 +6474,19 @@
 			pReq->Action, ioc->mptbase_cmds.status, timeleft));
 		if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
 			goto out;
-		if (!timeleft)
+		if (!timeleft) {
+			spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+			if (ioc->ioc_reset_in_progress) {
+				spin_unlock_irqrestore(&ioc->taskmgmt_lock,
+					flags);
+				printk(MYIOC_s_INFO_FMT "%s: host reset in"
+					" progress mpt_config timed out.!!\n",
+					__func__, ioc->name);
+				return -EFAULT;
+			}
+			spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
 			issue_hard_reset = 1;
+		}
 		goto out;
 	}
 
@@ -7128,7 +7200,18 @@
 	spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
 	if (ioc->ioc_reset_in_progress) {
 		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
-		return 0;
+		ioc->wait_on_reset_completion = 1;
+		do {
+			ssleep(1);
+		} while (ioc->ioc_reset_in_progress == 1);
+		ioc->wait_on_reset_completion = 0;
+		return ioc->reset_status;
+	}
+	if (ioc->wait_on_reset_completion) {
+		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+		rc = 0;
+		time_count = jiffies;
+		goto exit;
 	}
 	ioc->ioc_reset_in_progress = 1;
 	if (ioc->alt_ioc)
@@ -7165,6 +7248,7 @@
 	ioc->ioc_reset_in_progress = 0;
 	ioc->taskmgmt_quiesce_io = 0;
 	ioc->taskmgmt_in_progress = 0;
+	ioc->reset_status = rc;
 	if (ioc->alt_ioc) {
 		ioc->alt_ioc->ioc_reset_in_progress = 0;
 		ioc->alt_ioc->taskmgmt_quiesce_io = 0;
@@ -7180,7 +7264,7 @@
 					ioc->alt_ioc, MPT_IOC_POST_RESET);
 		}
 	}
-
+exit:
 	dtmprintk(ioc,
 	    printk(MYIOC_s_DEBUG_FMT
 		"HardResetHandler: completed (%d seconds): %s\n", ioc->name,
diff -druN linux-libre-3.1-gnu/drivers/message/fusion/mptbase.h linux-libre-3.2-gnu/drivers/message/fusion/mptbase.h
--- linux-libre-3.1-gnu/drivers/message/fusion/mptbase.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/message/fusion/mptbase.h	2012-01-04 18:55:44.000000000 -0500
@@ -76,8 +76,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2008 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.04.19"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.19"
+#define MPT_LINUX_VERSION_COMMON	"3.04.20"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.20"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -554,10 +554,47 @@
 	u8		flags;
 };
 
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
+/*
+ * MPT_SCSI_HOST defines - Used by the IOCTL and the SCSI drivers
+ * Private to the driver.
+ */
+
+#define MPT_HOST_BUS_UNKNOWN		(0xFF)
+#define MPT_HOST_TOO_MANY_TM		(0x05)
+#define MPT_HOST_NVRAM_INVALID		(0xFFFFFFFF)
+#define MPT_HOST_NO_CHAIN		(0xFFFFFFFF)
+#define MPT_NVRAM_MASK_TIMEOUT		(0x000000FF)
+#define MPT_NVRAM_SYNC_MASK		(0x0000FF00)
+#define MPT_NVRAM_SYNC_SHIFT		(8)
+#define MPT_NVRAM_DISCONNECT_ENABLE	(0x00010000)
+#define MPT_NVRAM_ID_SCAN_ENABLE	(0x00020000)
+#define MPT_NVRAM_LUN_SCAN_ENABLE	(0x00040000)
+#define MPT_NVRAM_TAG_QUEUE_ENABLE	(0x00080000)
+#define MPT_NVRAM_WIDE_DISABLE		(0x00100000)
+#define MPT_NVRAM_BOOT_CHOICE		(0x00200000)
+
+typedef enum {
+	FC,
+	SPI,
+	SAS
+} BUS_TYPE;
+
+typedef struct _MPT_SCSI_HOST {
+	struct _MPT_ADAPTER		 *ioc;
+	ushort			  sel_timeout[MPT_MAX_FC_DEVICES];
+	char			  *info_kbuf;
+	long			  last_queue_full;
+	u16			  spi_pending;
+	struct list_head	  target_reset_list;
+} MPT_SCSI_HOST;
+
 typedef void (*MPT_ADD_SGE)(void *pAddr, u32 flagslength, dma_addr_t dma_addr);
 typedef void (*MPT_ADD_CHAIN)(void *pAddr, u8 next, u16 length,
 		dma_addr_t dma_addr);
 typedef void (*MPT_SCHEDULE_TARGET_RESET)(void *ioc);
+typedef void (*MPT_FLUSH_RUNNING_CMDS)(MPT_SCSI_HOST *hd);
 
 /*
  *  Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
@@ -716,7 +753,10 @@
 	int			 taskmgmt_in_progress;
 	u8			 taskmgmt_quiesce_io;
 	u8			 ioc_reset_in_progress;
+	u8			 reset_status;
+	u8			 wait_on_reset_completion;
 	MPT_SCHEDULE_TARGET_RESET schedule_target_reset;
+	MPT_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;
 	struct work_struct	 sas_persist_task;
 
 	struct work_struct	 fc_setup_reset_work;
@@ -830,19 +870,6 @@
 	u32	pad;
 } MPT_LOCAL_REPLY;
 
-#define MPT_HOST_BUS_UNKNOWN		(0xFF)
-#define MPT_HOST_TOO_MANY_TM		(0x05)
-#define MPT_HOST_NVRAM_INVALID		(0xFFFFFFFF)
-#define MPT_HOST_NO_CHAIN		(0xFFFFFFFF)
-#define MPT_NVRAM_MASK_TIMEOUT		(0x000000FF)
-#define MPT_NVRAM_SYNC_MASK		(0x0000FF00)
-#define MPT_NVRAM_SYNC_SHIFT		(8)
-#define MPT_NVRAM_DISCONNECT_ENABLE	(0x00010000)
-#define MPT_NVRAM_ID_SCAN_ENABLE	(0x00020000)
-#define MPT_NVRAM_LUN_SCAN_ENABLE	(0x00040000)
-#define MPT_NVRAM_TAG_QUEUE_ENABLE	(0x00080000)
-#define MPT_NVRAM_WIDE_DISABLE		(0x00100000)
-#define MPT_NVRAM_BOOT_CHOICE		(0x00200000)
 
 /* The TM_STATE variable is used to provide strict single threading of TM
  * requests as well as communicate TM error conditions.
@@ -851,21 +878,6 @@
 #define	TM_STATE_IN_PROGRESS   (1)
 #define	TM_STATE_ERROR	       (2)
 
-typedef enum {
-	FC,
-	SPI,
-	SAS
-} BUS_TYPE;
-
-typedef struct _MPT_SCSI_HOST {
-	MPT_ADAPTER		 *ioc;
-	ushort			  sel_timeout[MPT_MAX_FC_DEVICES];
-	char 			  *info_kbuf;
-	long			  last_queue_full;
-	u16			  spi_pending;
-	struct list_head	  target_reset_list;
-} MPT_SCSI_HOST;
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *	More Dynamic Multi-Pathing stuff...
diff -druN linux-libre-3.1-gnu/drivers/message/fusion/mptsas.c linux-libre-3.2-gnu/drivers/message/fusion/mptsas.c
--- linux-libre-3.1-gnu/drivers/message/fusion/mptsas.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/message/fusion/mptsas.c	2012-01-04 18:55:44.000000000 -0500
@@ -92,6 +92,11 @@
 module_param(max_lun, int, 0);
 MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
 
+static int mpt_loadtime_max_sectors = 8192;
+module_param(mpt_loadtime_max_sectors, int, 0);
+MODULE_PARM_DESC(mpt_loadtime_max_sectors,
+		" Maximum sector define for Host Bus Adaptor.Range 64 to 8192 default=8192");
+
 static u8	mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
 static u8	mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
 static u8	mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
@@ -285,10 +290,11 @@
 	spin_lock_irqsave(&ioc->fw_event_lock, flags);
 	list_add_tail(&fw_event->list, &ioc->fw_event_list);
 	INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work);
-	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)\n",
-	    ioc->name, __func__, fw_event));
-	queue_delayed_work(ioc->fw_event_q, &fw_event->work,
-	    delay);
+	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)"
+		"on cpuid %d\n", ioc->name, __func__,
+		fw_event, smp_processor_id()));
+	queue_delayed_work_on(smp_processor_id(), ioc->fw_event_q,
+	    &fw_event->work, delay);
 	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 }
 
@@ -300,10 +306,11 @@
 	unsigned long flags;
 	spin_lock_irqsave(&ioc->fw_event_lock, flags);
 	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: reschedule task "
-	    "(fw_event=0x%p)\n", ioc->name, __func__, fw_event));
+	    "(fw_event=0x%p)on cpuid %d\n", ioc->name, __func__,
+		fw_event, smp_processor_id()));
 	fw_event->retries++;
-	queue_delayed_work(ioc->fw_event_q, &fw_event->work,
-	    msecs_to_jiffies(delay));
+	queue_delayed_work_on(smp_processor_id(), ioc->fw_event_q,
+	    &fw_event->work, msecs_to_jiffies(delay));
 	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 }
 
@@ -1943,6 +1950,15 @@
 		goto done;
 	}
 
+	/* In case if IOC is in reset from internal context.
+	*  Do not execute EEH for the same IOC. SML should to reset timer.
+	*/
+	if (ioc->ioc_reset_in_progress) {
+		dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: ioc is in reset,"
+		    "SML need to reset the timer (sc=%p)\n",
+		    ioc->name, __func__, sc));
+		rc = BLK_EH_RESET_TIMER;
+	}
 	vdevice = sc->device->hostdata;
 	if (vdevice && vdevice->vtarget && (vdevice->vtarget->inDMD
 		|| vdevice->vtarget->deleted)) {
@@ -5142,6 +5158,8 @@
 	ioc->TaskCtx = mptsasTaskCtx;
 	ioc->InternalCtx = mptsasInternalCtx;
 	ioc->schedule_target_reset = &mptsas_schedule_target_reset;
+	ioc->schedule_dead_ioc_flush_running_cmds =
+				&mptscsih_flush_running_cmds;
 	/*  Added sanity check on readiness of the MPT adapter.
 	 */
 	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
@@ -5239,6 +5257,21 @@
 		sh->sg_tablesize = numSGE;
 	}
 
+	if (mpt_loadtime_max_sectors) {
+		if (mpt_loadtime_max_sectors < 64 ||
+			mpt_loadtime_max_sectors > 8192) {
+			printk(MYIOC_s_INFO_FMT "Invalid value passed for"
+				"mpt_loadtime_max_sectors %d."
+				"Range from 64 to 8192\n", ioc->name,
+				mpt_loadtime_max_sectors);
+		}
+		mpt_loadtime_max_sectors &=  0xFFFFFFFE;
+		dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+			"Resetting max sector to %d from %d\n",
+		  ioc->name, mpt_loadtime_max_sectors, sh->max_sectors));
+		sh->max_sectors = mpt_loadtime_max_sectors;
+	}
+
 	hd = shost_priv(sh);
 	hd->ioc = ioc;
 
diff -druN linux-libre-3.1-gnu/drivers/message/fusion/mptscsih.c linux-libre-3.2-gnu/drivers/message/fusion/mptscsih.c
--- linux-libre-3.1-gnu/drivers/message/fusion/mptscsih.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/message/fusion/mptscsih.c	2012-01-04 18:55:44.000000000 -0500
@@ -830,7 +830,8 @@
 					if ((pScsiReq->CDB[0] == READ_6  && ((pScsiReq->CDB[1] & 0x02) == 0)) ||
 					    pScsiReq->CDB[0] == READ_10 ||
 					    pScsiReq->CDB[0] == READ_12 ||
-					    pScsiReq->CDB[0] == READ_16 ||
+						(pScsiReq->CDB[0] == READ_16 &&
+						((pScsiReq->CDB[1] & 0x02) == 0)) ||
 					    pScsiReq->CDB[0] == VERIFY  ||
 					    pScsiReq->CDB[0] == VERIFY_16) {
 						if (scsi_bufflen(sc) !=
@@ -1024,7 +1025,7 @@
  *
  *	Must be called while new I/Os are being queued.
  */
-static void
+void
 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
 {
 	MPT_ADAPTER *ioc = hd->ioc;
@@ -1055,6 +1056,7 @@
 		sc->scsi_done(sc);
 	}
 }
+EXPORT_SYMBOL(mptscsih_flush_running_cmds);
 
 /*
  *	mptscsih_search_running_cmds - Delete any commands associated
@@ -1629,7 +1631,13 @@
 		return 0;
 	}
 
-	if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
+	/* DOORBELL ACTIVE check is not required if
+	*  MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q is supported.
+	*/
+
+	if (!((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q)
+		 && (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) &&
+		(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
 		printk(MYIOC_s_WARN_FMT
 			"TaskMgmt type=%x: ioc_state: "
 			"DOORBELL_ACTIVE (0x%x)!\n",
@@ -1728,7 +1736,9 @@
 		printk(MYIOC_s_WARN_FMT
 		       "Issuing Reset from %s!! doorbell=0x%08x\n",
 		       ioc->name, __func__, mpt_GetIocState(ioc, 0));
-		retval = mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
+		retval = (ioc->bus_type == SAS) ?
+			mpt_HardResetHandler(ioc, CAN_SLEEP) :
+			mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
 		mpt_free_msg_frame(ioc, mf);
 	}
 
diff -druN linux-libre-3.1-gnu/drivers/message/fusion/mptscsih.h linux-libre-3.2-gnu/drivers/message/fusion/mptscsih.h
--- linux-libre-3.1-gnu/drivers/message/fusion/mptscsih.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/message/fusion/mptscsih.h	2012-01-04 18:55:44.000000000 -0500
@@ -135,3 +135,4 @@
 extern struct device_attribute *mptscsih_host_attrs[];
 extern struct scsi_cmnd	*mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
 extern void mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code);
+extern void mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd);
diff -druN linux-libre-3.1-gnu/drivers/message/i2o/pci.c linux-libre-3.2-gnu/drivers/message/i2o/pci.c
--- linux-libre-3.1-gnu/drivers/message/i2o/pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/message/i2o/pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/i2o.h>
+#include <linux/module.h>
 #include "core.h"
 
 #define OSM_DESCRIPTION	"I2O-subsystem"
diff -druN linux-libre-3.1-gnu/drivers/mfd/aat2870-core.c linux-libre-3.2-gnu/drivers/mfd/aat2870-core.c
--- linux-libre-3.1-gnu/drivers/mfd/aat2870-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/aat2870-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -295,7 +295,7 @@
 {
 	struct aat2870_data *aat2870 = file->private_data;
 	char buf[32];
-	int buf_size;
+	ssize_t buf_size;
 	char *start = buf;
 	unsigned long addr, val;
 	int ret;
diff -druN linux-libre-3.1-gnu/drivers/mfd/ab3100-core.c linux-libre-3.2-gnu/drivers/mfd/ab3100-core.c
--- linux-libre-3.1-gnu/drivers/mfd/ab3100-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/ab3100-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/notifier.h>
 #include <linux/slab.h>
 #include <linux/err.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
@@ -809,7 +810,7 @@
 	char	*name;
 };
 
-static const struct ab_family_id ids[] __devinitdata = {
+static const struct ab_family_id ids[] __devinitconst = {
 	/* AB3100 */
 	{
 		.id = 0xc0,
diff -druN linux-libre-3.1-gnu/drivers/mfd/ab3550-core.c linux-libre-3.2-gnu/drivers/mfd/ab3550-core.c
--- linux-libre-3.1-gnu/drivers/mfd/ab3550-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/ab3550-core.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1380 +0,0 @@
-/*
- * Copyright (C) 2007-2010 ST-Ericsson
- * License terms: GNU General Public License (GPL) version 2
- * Low-level core for exclusive access to the AB3550 IC on the I2C bus
- * and some basic chip-configuration.
- * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
- * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
- * Author: Mattias Wallin <mattias.wallin@stericsson.com>
- * Author: Rickard Andersson <rickard.andersson@stericsson.com>
- */
-
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/random.h>
-#include <linux/workqueue.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>
-#include <linux/mfd/abx500.h>
-#include <linux/list.h>
-#include <linux/bitops.h>
-#include <linux/spinlock.h>
-#include <linux/mfd/core.h>
-
-#define AB3550_NAME_STRING "ab3550"
-#define AB3550_ID_FORMAT_STRING "AB3550 %s"
-#define AB3550_NUM_BANKS 2
-#define AB3550_NUM_EVENT_REG 5
-
-/* These are the only registers inside AB3550 used in this main file */
-
-/* Chip ID register */
-#define AB3550_CID_REG           0x20
-
-/* Interrupt event registers */
-#define AB3550_EVENT_BANK        0
-#define AB3550_EVENT_REG         0x22
-
-/* Read/write operation values. */
-#define AB3550_PERM_RD (0x01)
-#define AB3550_PERM_WR (0x02)
-
-/* Read/write permissions. */
-#define AB3550_PERM_RO (AB3550_PERM_RD)
-#define AB3550_PERM_RW (AB3550_PERM_RD | AB3550_PERM_WR)
-
-/**
- * struct ab3550
- * @access_mutex: lock out concurrent accesses to the AB registers
- * @i2c_client: I2C client for this chip
- * @chip_name: name of this chip variant
- * @chip_id: 8 bit chip ID for this chip variant
- * @mask_work: a worker for writing to mask registers
- * @event_lock: a lock to protect the event_mask
- * @event_mask: a local copy of the mask event registers
- * @startup_events: a copy of the first reading of the event registers
- * @startup_events_read: whether the first events have been read
- */
-struct ab3550 {
-	struct mutex access_mutex;
-	struct i2c_client *i2c_client[AB3550_NUM_BANKS];
-	char chip_name[32];
-	u8 chip_id;
-	struct work_struct mask_work;
-	spinlock_t event_lock;
-	u8 event_mask[AB3550_NUM_EVENT_REG];
-	u8 startup_events[AB3550_NUM_EVENT_REG];
-	bool startup_events_read;
-#ifdef CONFIG_DEBUG_FS
-	unsigned int debug_bank;
-	unsigned int debug_address;
-#endif
-};
-
-/**
- * struct ab3550_reg_range
- * @first: the first address of the range
- * @last: the last address of the range
- * @perm: access permissions for the range
- */
-struct ab3550_reg_range {
-	u8 first;
-	u8 last;
-	u8 perm;
-};
-
-/**
- * struct ab3550_reg_ranges
- * @count: the number of ranges in the list
- * @range: the list of register ranges
- */
-struct ab3550_reg_ranges {
-	u8 count;
-	const struct ab3550_reg_range *range;
-};
-
-/*
- * Permissible register ranges for reading and writing per device and bank.
- *
- * The ranges must be listed in increasing address order, and no overlaps are
- * allowed. It is assumed that write permission implies read permission
- * (i.e. only RO and RW permissions should be used).  Ranges with write
- * permission must not be split up.
- */
-
-#define NO_RANGE {.count = 0, .range = NULL,}
-
-static struct
-ab3550_reg_ranges ab3550_reg_ranges[AB3550_NUM_DEVICES][AB3550_NUM_BANKS] = {
-	[AB3550_DEVID_DAC] = {
-		NO_RANGE,
-		{
-			.count = 2,
-			.range = (struct ab3550_reg_range[]) {
-				{
-					.first = 0xb0,
-					.last = 0xba,
-					.perm = AB3550_PERM_RW,
-				},
-				{
-					.first = 0xbc,
-					.last = 0xc3,
-					.perm = AB3550_PERM_RW,
-				},
-			},
-		},
-	},
-	[AB3550_DEVID_LEDS] = {
-		NO_RANGE,
-		{
-			.count = 2,
-			.range = (struct ab3550_reg_range[]) {
-				{
-					.first = 0x5a,
-					.last = 0x88,
-					.perm = AB3550_PERM_RW,
-				},
-				{
-					.first = 0x8a,
-					.last = 0xad,
-					.perm = AB3550_PERM_RW,
-				},
-			}
-		},
-	},
-	[AB3550_DEVID_POWER] = {
-		{
-			.count = 1,
-			.range = (struct ab3550_reg_range[]) {
-				{
-					.first = 0x21,
-					.last = 0x21,
-					.perm = AB3550_PERM_RO,
-				},
-			}
-		},
-		NO_RANGE,
-	},
-	[AB3550_DEVID_REGULATORS] = {
-		{
-			.count = 1,
-			.range = (struct ab3550_reg_range[]) {
-				{
-					.first = 0x69,
-					.last = 0xa3,
-					.perm = AB3550_PERM_RW,
-				},
-			}
-		},
-		{
-			.count = 1,
-			.range = (struct ab3550_reg_range[]) {
-				{
-					.first = 0x14,
-					.last = 0x16,
-					.perm = AB3550_PERM_RW,
-				},
-			}
-		},
-	},
-	[AB3550_DEVID_SIM] = {
-		{
-			.count = 1,
-			.range = (struct ab3550_reg_range[]) {
-				{
-					.first = 0x21,
-					.last = 0x21,
-					.perm = AB3550_PERM_RO,
-				},
-			}
-		},
-		{
-			.count = 1,
-			.range = (struct ab3550_reg_range[]) {
-				{
-					.first = 0x14,
-					.last = 0x17,
-					.perm = AB3550_PERM_RW,
-				},
-			}
-
-		},
-	},
-	[AB3550_DEVID_UART] = {
-		NO_RANGE,
-		NO_RANGE,
-	},
-	[AB3550_DEVID_RTC] = {
-		{
-			.count = 1,
-			.range = (struct ab3550_reg_range[]) {
-				{
-					.first = 0x00,
-					.last = 0x0c,
-					.perm = AB3550_PERM_RW,
-				},
-			}
-		},
-		NO_RANGE,
-	},
-	[AB3550_DEVID_CHARGER] = {
-		{
-			.count = 2,
-			.range = (struct ab3550_reg_range[]) {
-				{
-					.first = 0x10,
-					.last = 0x1a,
-					.perm = AB3550_PERM_RW,
-				},
-				{
-					.first = 0x21,
-					.last = 0x21,
-					.perm = AB3550_PERM_RO,
-				},
-			}
-		},
-		NO_RANGE,
-	},
-	[AB3550_DEVID_ADC] = {
-		NO_RANGE,
-		{
-			.count = 1,
-			.range = (struct ab3550_reg_range[]) {
-				{
-					.first = 0x20,
-					.last = 0x56,
-					.perm = AB3550_PERM_RW,
-				},
-
-			}
-		},
-	},
-	[AB3550_DEVID_FUELGAUGE] = {
-		{
-			.count = 1,
-			.range = (struct ab3550_reg_range[]) {
-				{
-					.first = 0x21,
-					.last = 0x21,
-					.perm = AB3550_PERM_RO,
-				},
-			}
-		},
-		{
-			.count = 1,
-			.range = (struct ab3550_reg_range[]) {
-				{
-					.first = 0x00,
-					.last = 0x0e,
-					.perm = AB3550_PERM_RW,
-				},
-			}
-		},
-	},
-	[AB3550_DEVID_VIBRATOR] = {
-		NO_RANGE,
-		{
-			.count = 1,
-			.range = (struct ab3550_reg_range[]) {
-				{
-					.first = 0x10,
-					.last = 0x13,
-					.perm = AB3550_PERM_RW,
-				},
-
-			}
-		},
-	},
-	[AB3550_DEVID_CODEC] = {
-		{
-			.count = 2,
-			.range = (struct ab3550_reg_range[]) {
-				{
-					.first = 0x31,
-					.last = 0x63,
-					.perm = AB3550_PERM_RW,
-				},
-				{
-					.first = 0x65,
-					.last = 0x68,
-					.perm = AB3550_PERM_RW,
-				},
-			}
-		},
-		NO_RANGE,
-	},
-};
-
-static struct mfd_cell ab3550_devs[AB3550_NUM_DEVICES] = {
-	[AB3550_DEVID_DAC] = {
-		.name = "ab3550-dac",
-		.id = AB3550_DEVID_DAC,
-		.num_resources = 0,
-	},
-	[AB3550_DEVID_LEDS] = {
-		.name = "ab3550-leds",
-		.id = AB3550_DEVID_LEDS,
-	},
-	[AB3550_DEVID_POWER] = {
-		.name = "ab3550-power",
-		.id = AB3550_DEVID_POWER,
-	},
-	[AB3550_DEVID_REGULATORS] = {
-		.name = "ab3550-regulators",
-		.id = AB3550_DEVID_REGULATORS,
-	},
-	[AB3550_DEVID_SIM] = {
-		.name = "ab3550-sim",
-		.id = AB3550_DEVID_SIM,
-	},
-	[AB3550_DEVID_UART] = {
-		.name = "ab3550-uart",
-		.id = AB3550_DEVID_UART,
-	},
-	[AB3550_DEVID_RTC] = {
-		.name = "ab3550-rtc",
-		.id = AB3550_DEVID_RTC,
-	},
-	[AB3550_DEVID_CHARGER] = {
-		.name = "ab3550-charger",
-		.id = AB3550_DEVID_CHARGER,
-	},
-	[AB3550_DEVID_ADC] = {
-		.name = "ab3550-adc",
-		.id = AB3550_DEVID_ADC,
-		.num_resources = 10,
-		.resources = (struct resource[]) {
-			{
-				.name = "TRIGGER-0",
-				.flags = IORESOURCE_IRQ,
-				.start = 16,
-				.end = 16,
-			},
-			{
-				.name = "TRIGGER-1",
-				.flags = IORESOURCE_IRQ,
-				.start = 17,
-				.end = 17,
-			},
-			{
-				.name = "TRIGGER-2",
-				.flags = IORESOURCE_IRQ,
-				.start = 18,
-				.end = 18,
-			},
-			{
-				.name = "TRIGGER-3",
-				.flags = IORESOURCE_IRQ,
-				.start = 19,
-				.end = 19,
-			},
-			{
-				.name = "TRIGGER-4",
-				.flags = IORESOURCE_IRQ,
-				.start = 20,
-				.end = 20,
-			},
-			{
-				.name = "TRIGGER-5",
-				.flags = IORESOURCE_IRQ,
-				.start = 21,
-				.end = 21,
-			},
-			{
-				.name = "TRIGGER-6",
-				.flags = IORESOURCE_IRQ,
-				.start = 22,
-				.end = 22,
-			},
-			{
-				.name = "TRIGGER-7",
-				.flags = IORESOURCE_IRQ,
-				.start = 23,
-				.end = 23,
-			},
-			{
-				.name = "TRIGGER-VBAT-TXON",
-				.flags = IORESOURCE_IRQ,
-				.start = 13,
-				.end = 13,
-			},
-			{
-				.name = "TRIGGER-VBAT",
-				.flags = IORESOURCE_IRQ,
-				.start = 12,
-				.end = 12,
-			},
-		},
-	},
-	[AB3550_DEVID_FUELGAUGE] = {
-		.name = "ab3550-fuelgauge",
-		.id = AB3550_DEVID_FUELGAUGE,
-	},
-	[AB3550_DEVID_VIBRATOR] = {
-		.name = "ab3550-vibrator",
-		.id = AB3550_DEVID_VIBRATOR,
-	},
-	[AB3550_DEVID_CODEC] = {
-		.name = "ab3550-codec",
-		.id = AB3550_DEVID_CODEC,
-	},
-};
-
-/*
- * I2C transactions with error messages.
- */
-static int ab3550_i2c_master_send(struct ab3550 *ab, u8 bank, u8 *data,
-	u8 count)
-{
-	int err;
-
-	err = i2c_master_send(ab->i2c_client[bank], data, count);
-	if (err < 0) {
-		dev_err(&ab->i2c_client[0]->dev, "send error: %d\n", err);
-		return err;
-	}
-	return 0;
-}
-
-static int ab3550_i2c_master_recv(struct ab3550 *ab, u8 bank, u8 *data,
-	u8 count)
-{
-	int err;
-
-	err = i2c_master_recv(ab->i2c_client[bank], data, count);
-	if (err < 0) {
-		dev_err(&ab->i2c_client[0]->dev, "receive error: %d\n", err);
-		return err;
-	}
-	return 0;
-}
-
-/*
- * Functionality for getting/setting register values.
- */
-static int get_register_interruptible(struct ab3550 *ab, u8 bank, u8 reg,
-	u8 *value)
-{
-	int err;
-
-	err = mutex_lock_interruptible(&ab->access_mutex);
-	if (err)
-		return err;
-
-	err = ab3550_i2c_master_send(ab, bank, &reg, 1);
-	if (!err)
-		err = ab3550_i2c_master_recv(ab, bank, value, 1);
-
-	mutex_unlock(&ab->access_mutex);
-	return err;
-}
-
-static int get_register_page_interruptible(struct ab3550 *ab, u8 bank,
-	u8 first_reg, u8 *regvals, u8 numregs)
-{
-	int err;
-
-	err = mutex_lock_interruptible(&ab->access_mutex);
-	if (err)
-		return err;
-
-	err = ab3550_i2c_master_send(ab, bank, &first_reg, 1);
-	if (!err)
-		err = ab3550_i2c_master_recv(ab, bank, regvals, numregs);
-
-	mutex_unlock(&ab->access_mutex);
-	return err;
-}
-
-static int mask_and_set_register_interruptible(struct ab3550 *ab, u8 bank,
-	u8 reg, u8 bitmask, u8 bitvalues)
-{
-	int err = 0;
-
-	if (likely(bitmask)) {
-		u8 reg_bits[2] = {reg, 0};
-
-		err = mutex_lock_interruptible(&ab->access_mutex);
-		if (err)
-			return err;
-
-		if (bitmask == 0xFF) /* No need to read in this case. */
-			reg_bits[1] = bitvalues;
-		else { /* Read and modify the register value. */
-			u8 bits;
-
-			err = ab3550_i2c_master_send(ab, bank, &reg, 1);
-			if (err)
-				goto unlock_and_return;
-			err = ab3550_i2c_master_recv(ab, bank, &bits, 1);
-			if (err)
-				goto unlock_and_return;
-			reg_bits[1] = ((~bitmask & bits) |
-				(bitmask & bitvalues));
-		}
-		/* Write the new value. */
-		err = ab3550_i2c_master_send(ab, bank, reg_bits, 2);
-unlock_and_return:
-		mutex_unlock(&ab->access_mutex);
-	}
-	return err;
-}
-
-/*
- * Read/write permission checking functions.
- */
-static bool page_write_allowed(const struct ab3550_reg_ranges *ranges,
-	u8 first_reg, u8 last_reg)
-{
-	u8 i;
-
-	if (last_reg < first_reg)
-		return false;
-
-	for (i = 0; i < ranges->count; i++) {
-		if (first_reg < ranges->range[i].first)
-			break;
-		if ((last_reg <= ranges->range[i].last) &&
-			(ranges->range[i].perm & AB3550_PERM_WR))
-			return true;
-	}
-	return false;
-}
-
-static bool reg_write_allowed(const struct ab3550_reg_ranges *ranges, u8 reg)
-{
-	return page_write_allowed(ranges, reg, reg);
-}
-
-static bool page_read_allowed(const struct ab3550_reg_ranges *ranges,
-	u8 first_reg, u8 last_reg)
-{
-	u8 i;
-
-	if (last_reg < first_reg)
-		return false;
-	/* Find the range (if it exists in the list) that includes first_reg. */
-	for (i = 0; i < ranges->count; i++) {
-		if (first_reg < ranges->range[i].first)
-			return false;
-		if (first_reg <= ranges->range[i].last)
-			break;
-	}
-	/* Make sure that the entire range up to and including last_reg is
-	 * readable. This may span several of the ranges in the list.
-	 */
-	while ((i < ranges->count) &&
-		(ranges->range[i].perm & AB3550_PERM_RD)) {
-		if (last_reg <= ranges->range[i].last)
-			return true;
-		if ((++i >= ranges->count) ||
-			(ranges->range[i].first !=
-			 (ranges->range[i - 1].last + 1))) {
-			break;
-		}
-	}
-	return false;
-}
-
-static bool reg_read_allowed(const struct ab3550_reg_ranges *ranges, u8 reg)
-{
-	return page_read_allowed(ranges, reg, reg);
-}
-
-/*
- * The register access functionality.
- */
-static int ab3550_get_chip_id(struct device *dev)
-{
-	struct ab3550 *ab = dev_get_drvdata(dev->parent);
-	return (int)ab->chip_id;
-}
-
-static int ab3550_mask_and_set_register_interruptible(struct device *dev,
-	u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
-{
-	struct ab3550 *ab;
-	struct platform_device *pdev = to_platform_device(dev);
-
-	if ((AB3550_NUM_BANKS <= bank) ||
-		!reg_write_allowed(&ab3550_reg_ranges[pdev->id][bank], reg))
-		return -EINVAL;
-
-	ab = dev_get_drvdata(dev->parent);
-	return mask_and_set_register_interruptible(ab, bank, reg,
-		bitmask, bitvalues);
-}
-
-static int ab3550_set_register_interruptible(struct device *dev, u8 bank,
-	u8 reg, u8 value)
-{
-	return ab3550_mask_and_set_register_interruptible(dev, bank, reg, 0xFF,
-		value);
-}
-
-static int ab3550_get_register_interruptible(struct device *dev, u8 bank,
-	u8 reg, u8 *value)
-{
-	struct ab3550 *ab;
-	struct platform_device *pdev = to_platform_device(dev);
-
-	if ((AB3550_NUM_BANKS <= bank) ||
-		!reg_read_allowed(&ab3550_reg_ranges[pdev->id][bank], reg))
-		return -EINVAL;
-
-	ab = dev_get_drvdata(dev->parent);
-	return get_register_interruptible(ab, bank, reg, value);
-}
-
-static int ab3550_get_register_page_interruptible(struct device *dev, u8 bank,
-	u8 first_reg, u8 *regvals, u8 numregs)
-{
-	struct ab3550 *ab;
-	struct platform_device *pdev = to_platform_device(dev);
-
-	if ((AB3550_NUM_BANKS <= bank) ||
-		!page_read_allowed(&ab3550_reg_ranges[pdev->id][bank],
-			first_reg, (first_reg + numregs - 1)))
-		return -EINVAL;
-
-	ab = dev_get_drvdata(dev->parent);
-	return get_register_page_interruptible(ab, bank, first_reg, regvals,
-		numregs);
-}
-
-static int ab3550_event_registers_startup_state_get(struct device *dev,
-	u8 *event)
-{
-	struct ab3550 *ab;
-
-	ab = dev_get_drvdata(dev->parent);
-	if (!ab->startup_events_read)
-		return -EAGAIN; /* Try again later */
-
-	memcpy(event, ab->startup_events, AB3550_NUM_EVENT_REG);
-	return 0;
-}
-
-static int ab3550_startup_irq_enabled(struct device *dev, unsigned int irq)
-{
-	struct ab3550 *ab;
-	struct ab3550_platform_data *plf_data;
-	bool val;
-
-	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);
-
-	return val;
-}
-
-static struct abx500_ops ab3550_ops = {
-	.get_chip_id = ab3550_get_chip_id,
-	.get_register = ab3550_get_register_interruptible,
-	.set_register = ab3550_set_register_interruptible,
-	.get_register_page = ab3550_get_register_page_interruptible,
-	.set_register_page = NULL,
-	.mask_and_set_register = ab3550_mask_and_set_register_interruptible,
-	.event_registers_startup_state_get =
-		ab3550_event_registers_startup_state_get,
-	.startup_irq_enabled = ab3550_startup_irq_enabled,
-};
-
-static irqreturn_t ab3550_irq_handler(int irq, void *data)
-{
-	struct ab3550 *ab = data;
-	int err;
-	unsigned int i;
-	u8 e[AB3550_NUM_EVENT_REG];
-	u8 *events;
-	unsigned long flags;
-
-	events = (ab->startup_events_read ? e : ab->startup_events);
-
-	err = get_register_page_interruptible(ab, AB3550_EVENT_BANK,
-		AB3550_EVENT_REG, events, AB3550_NUM_EVENT_REG);
-	if (err)
-		goto err_event_rd;
-
-	if (!ab->startup_events_read) {
-		dev_info(&ab->i2c_client[0]->dev,
-			"startup events 0x%x,0x%x,0x%x,0x%x,0x%x\n",
-			ab->startup_events[0], ab->startup_events[1],
-			ab->startup_events[2], ab->startup_events[3],
-			ab->startup_events[4]);
-		ab->startup_events_read = true;
-		goto out;
-	}
-
-	/* The two highest bits in event[4] are not used. */
-	events[4] &= 0x3f;
-
-	spin_lock_irqsave(&ab->event_lock, flags);
-	for (i = 0; i < AB3550_NUM_EVENT_REG; i++)
-		events[i] &= ~ab->event_mask[i];
-	spin_unlock_irqrestore(&ab->event_lock, flags);
-
-	for (i = 0; i < AB3550_NUM_EVENT_REG; i++) {
-		u8 bit;
-		u8 event_reg;
-
-		dev_dbg(&ab->i2c_client[0]->dev, "IRQ Event[%d]: 0x%2x\n",
-			i, events[i]);
-
-		event_reg = events[i];
-		for (bit = 0; event_reg; bit++, event_reg /= 2) {
-			if (event_reg % 2) {
-				unsigned int irq;
-				struct ab3550_platform_data *plf_data;
-
-				plf_data = ab->i2c_client[0]->dev.platform_data;
-				irq = plf_data->irq.base + (i * 8) + bit;
-				handle_nested_irq(irq);
-			}
-		}
-	}
-out:
-	return IRQ_HANDLED;
-
-err_event_rd:
-	dev_dbg(&ab->i2c_client[0]->dev, "error reading event registers\n");
-	return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static struct ab3550_reg_ranges debug_ranges[AB3550_NUM_BANKS] = {
-	{
-		.count = 6,
-		.range = (struct ab3550_reg_range[]) {
-			{
-				.first = 0x00,
-				.last = 0x0e,
-			},
-			{
-				.first = 0x10,
-				.last = 0x1a,
-			},
-			{
-				.first = 0x1e,
-				.last = 0x4f,
-			},
-			{
-				.first = 0x51,
-				.last = 0x63,
-			},
-			{
-				.first = 0x65,
-				.last = 0xa3,
-			},
-			{
-				.first = 0xa5,
-				.last = 0xa8,
-			},
-		}
-	},
-	{
-		.count = 8,
-		.range = (struct ab3550_reg_range[]) {
-			{
-				.first = 0x00,
-				.last = 0x0e,
-			},
-			{
-				.first = 0x10,
-				.last = 0x17,
-			},
-			{
-				.first = 0x1a,
-				.last = 0x1c,
-			},
-			{
-				.first = 0x20,
-				.last = 0x56,
-			},
-			{
-				.first = 0x5a,
-				.last = 0x88,
-			},
-			{
-				.first = 0x8a,
-				.last = 0xad,
-			},
-			{
-				.first = 0xb0,
-				.last = 0xba,
-			},
-			{
-				.first = 0xbc,
-				.last = 0xc3,
-			},
-		}
-	},
-};
-
-static int ab3550_registers_print(struct seq_file *s, void *p)
-{
-	struct ab3550 *ab = s->private;
-	int bank;
-
-	seq_printf(s, AB3550_NAME_STRING " register values:\n");
-
-	for (bank = 0; bank < AB3550_NUM_BANKS; bank++) {
-		unsigned int i;
-
-		seq_printf(s, " bank %d:\n", bank);
-		for (i = 0; i < debug_ranges[bank].count; i++) {
-			u8 reg;
-
-			for (reg = debug_ranges[bank].range[i].first;
-				reg <= debug_ranges[bank].range[i].last;
-				reg++) {
-				u8 value;
-
-				get_register_interruptible(ab, bank, reg,
-					&value);
-				seq_printf(s, "  [%d/0x%02X]: 0x%02X\n", bank,
-					reg, value);
-			}
-		}
-	}
-	return 0;
-}
-
-static int ab3550_registers_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ab3550_registers_print, inode->i_private);
-}
-
-static const struct file_operations ab3550_registers_fops = {
-	.open = ab3550_registers_open,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-	.owner = THIS_MODULE,
-};
-
-static int ab3550_bank_print(struct seq_file *s, void *p)
-{
-	struct ab3550 *ab = s->private;
-
-	seq_printf(s, "%d\n", ab->debug_bank);
-	return 0;
-}
-
-static int ab3550_bank_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ab3550_bank_print, inode->i_private);
-}
-
-static ssize_t ab3550_bank_write(struct file *file,
-	const char __user *user_buf,
-	size_t count, loff_t *ppos)
-{
-	struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private;
-	unsigned long user_bank;
-	int err;
-
-	/* Get userspace string and assure termination */
-	err = kstrtoul_from_user(user_buf, count, 0, &user_bank);
-	if (err)
-		return err;
-
-	if (user_bank >= AB3550_NUM_BANKS) {
-		dev_err(&ab->i2c_client[0]->dev,
-			"debugfs error input > number of banks\n");
-		return -EINVAL;
-	}
-
-	ab->debug_bank = user_bank;
-
-	return count;
-}
-
-static int ab3550_address_print(struct seq_file *s, void *p)
-{
-	struct ab3550 *ab = s->private;
-
-	seq_printf(s, "0x%02X\n", ab->debug_address);
-	return 0;
-}
-
-static int ab3550_address_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ab3550_address_print, inode->i_private);
-}
-
-static ssize_t ab3550_address_write(struct file *file,
-	const char __user *user_buf,
-	size_t count, loff_t *ppos)
-{
-	struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private;
-	unsigned long user_address;
-	int err;
-
-	/* Get userspace string and assure termination */
-	err = kstrtoul_from_user(user_buf, count, 0, &user_address);
-	if (err)
-		return err;
-
-	if (user_address > 0xff) {
-		dev_err(&ab->i2c_client[0]->dev,
-			"debugfs error input > 0xff\n");
-		return -EINVAL;
-	}
-	ab->debug_address = user_address;
-	return count;
-}
-
-static int ab3550_val_print(struct seq_file *s, void *p)
-{
-	struct ab3550 *ab = s->private;
-	int err;
-	u8 regvalue;
-
-	err = get_register_interruptible(ab, (u8)ab->debug_bank,
-		(u8)ab->debug_address, &regvalue);
-	if (err)
-		return -EINVAL;
-	seq_printf(s, "0x%02X\n", regvalue);
-
-	return 0;
-}
-
-static int ab3550_val_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ab3550_val_print, inode->i_private);
-}
-
-static ssize_t ab3550_val_write(struct file *file,
-	const char __user *user_buf,
-	size_t count, loff_t *ppos)
-{
-	struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private;
-	unsigned long user_val;
-	int err;
-	u8 regvalue;
-
-	/* Get userspace string and assure termination */
-	err = kstrtoul_from_user(user_buf, count, 0, &user_val);
-	if (err)
-		return err;
-
-	if (user_val > 0xff) {
-		dev_err(&ab->i2c_client[0]->dev,
-			"debugfs error input > 0xff\n");
-		return -EINVAL;
-	}
-	err = mask_and_set_register_interruptible(
-		ab, (u8)ab->debug_bank,
-		(u8)ab->debug_address, 0xFF, (u8)user_val);
-	if (err)
-		return -EINVAL;
-
-	get_register_interruptible(ab, (u8)ab->debug_bank,
-		(u8)ab->debug_address, &regvalue);
-	if (err)
-		return -EINVAL;
-
-	return count;
-}
-
-static const struct file_operations ab3550_bank_fops = {
-	.open = ab3550_bank_open,
-	.write = ab3550_bank_write,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-	.owner = THIS_MODULE,
-};
-
-static const struct file_operations ab3550_address_fops = {
-	.open = ab3550_address_open,
-	.write = ab3550_address_write,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-	.owner = THIS_MODULE,
-};
-
-static const struct file_operations ab3550_val_fops = {
-	.open = ab3550_val_open,
-	.write = ab3550_val_write,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-	.owner = THIS_MODULE,
-};
-
-static struct dentry *ab3550_dir;
-static struct dentry *ab3550_reg_file;
-static struct dentry *ab3550_bank_file;
-static struct dentry *ab3550_address_file;
-static struct dentry *ab3550_val_file;
-
-static inline void ab3550_setup_debugfs(struct ab3550 *ab)
-{
-	ab->debug_bank = 0;
-	ab->debug_address = 0x00;
-
-	ab3550_dir = debugfs_create_dir(AB3550_NAME_STRING, NULL);
-	if (!ab3550_dir)
-		goto exit_no_debugfs;
-
-	ab3550_reg_file = debugfs_create_file("all-registers",
-		S_IRUGO, ab3550_dir, ab, &ab3550_registers_fops);
-	if (!ab3550_reg_file)
-		goto exit_destroy_dir;
-
-	ab3550_bank_file = debugfs_create_file("register-bank",
-		(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_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_IWUSR), ab3550_dir, ab, &ab3550_val_fops);
-	if (!ab3550_val_file)
-		goto exit_destroy_address;
-
-	return;
-
-exit_destroy_address:
-	debugfs_remove(ab3550_address_file);
-exit_destroy_bank:
-	debugfs_remove(ab3550_bank_file);
-exit_destroy_reg:
-	debugfs_remove(ab3550_reg_file);
-exit_destroy_dir:
-	debugfs_remove(ab3550_dir);
-exit_no_debugfs:
-	dev_err(&ab->i2c_client[0]->dev, "failed to create debugfs entries.\n");
-	return;
-}
-
-static inline void ab3550_remove_debugfs(void)
-{
-	debugfs_remove(ab3550_val_file);
-	debugfs_remove(ab3550_address_file);
-	debugfs_remove(ab3550_bank_file);
-	debugfs_remove(ab3550_reg_file);
-	debugfs_remove(ab3550_dir);
-}
-
-#else /* !CONFIG_DEBUG_FS */
-static inline void ab3550_setup_debugfs(struct ab3550 *ab)
-{
-}
-static inline void ab3550_remove_debugfs(void)
-{
-}
-#endif
-
-/*
- * Basic set-up, datastructure creation/destruction and I2C interface.
- * This sets up a default config in the AB3550 chip so that it
- * will work as expected.
- */
-static int __init ab3550_setup(struct ab3550 *ab)
-{
-	int err = 0;
-	int i;
-	struct ab3550_platform_data *plf_data;
-	struct abx500_init_settings *settings;
-
-	plf_data = ab->i2c_client[0]->dev.platform_data;
-	settings = plf_data->init_settings;
-
-	for (i = 0; i < plf_data->init_settings_sz; i++) {
-		err = mask_and_set_register_interruptible(ab,
-			settings[i].bank,
-			settings[i].reg,
-			0xFF, settings[i].setting);
-		if (err)
-			goto exit_no_setup;
-
-		/* If event mask register update the event mask in ab3550 */
-		if ((settings[i].bank == 0) &&
-			(AB3550_IMR1 <= settings[i].reg) &&
-			(settings[i].reg <= AB3550_IMR5)) {
-			ab->event_mask[settings[i].reg - AB3550_IMR1] =
-				settings[i].setting;
-		}
-	}
-exit_no_setup:
-	return err;
-}
-
-static void ab3550_mask_work(struct work_struct *work)
-{
-	struct ab3550 *ab = container_of(work, struct ab3550, mask_work);
-	int i;
-	unsigned long flags;
-	u8 mask[AB3550_NUM_EVENT_REG];
-
-	spin_lock_irqsave(&ab->event_lock, flags);
-	for (i = 0; i < AB3550_NUM_EVENT_REG; i++)
-		mask[i] = ab->event_mask[i];
-	spin_unlock_irqrestore(&ab->event_lock, flags);
-
-	for (i = 0; i < AB3550_NUM_EVENT_REG; i++) {
-		int err;
-
-		err = mask_and_set_register_interruptible(ab, 0,
-			(AB3550_IMR1 + i), ~0, mask[i]);
-		if (err)
-			dev_err(&ab->i2c_client[0]->dev,
-				"ab3550_mask_work failed 0x%x,0x%x\n",
-				(AB3550_IMR1 + i), mask[i]);
-	}
-}
-
-static void ab3550_mask(struct irq_data *data)
-{
-	unsigned long flags;
-	struct ab3550 *ab;
-	struct ab3550_platform_data *plf_data;
-	int irq;
-
-	ab = irq_data_get_irq_chip_data(data);
-	plf_data = ab->i2c_client[0]->dev.platform_data;
-	irq = data->irq - plf_data->irq.base;
-
-	spin_lock_irqsave(&ab->event_lock, flags);
-	ab->event_mask[irq / 8] |= BIT(irq % 8);
-	spin_unlock_irqrestore(&ab->event_lock, flags);
-
-	schedule_work(&ab->mask_work);
-}
-
-static void ab3550_unmask(struct irq_data *data)
-{
-	unsigned long flags;
-	struct ab3550 *ab;
-	struct ab3550_platform_data *plf_data;
-	int irq;
-
-	ab = irq_data_get_irq_chip_data(data);
-	plf_data = ab->i2c_client[0]->dev.platform_data;
-	irq = data->irq - plf_data->irq.base;
-
-	spin_lock_irqsave(&ab->event_lock, flags);
-	ab->event_mask[irq / 8] &= ~BIT(irq % 8);
-	spin_unlock_irqrestore(&ab->event_lock, flags);
-
-	schedule_work(&ab->mask_work);
-}
-
-static void noop(struct irq_data *data)
-{
-}
-
-static struct irq_chip ab3550_irq_chip = {
-	.name		= "ab3550-core", /* Keep the same name as the request */
-	.irq_disable	= ab3550_mask, /* No default to mask in chip.c */
-	.irq_ack	= noop,
-	.irq_mask	= ab3550_mask,
-	.irq_unmask	= ab3550_unmask,
-};
-
-struct ab_family_id {
-	u8	id;
-	char	*name;
-};
-
-static const struct ab_family_id ids[] __initdata = {
-	/* AB3550 */
-	{
-		.id = AB3550_P1A,
-		.name = "P1A"
-	},
-	/* Terminator */
-	{
-		.id = 0x00,
-	}
-};
-
-static int __init ab3550_probe(struct i2c_client *client,
-	const struct i2c_device_id *id)
-{
-	struct ab3550 *ab;
-	struct ab3550_platform_data *ab3550_plf_data =
-		client->dev.platform_data;
-	int err;
-	int i;
-	int num_i2c_clients = 0;
-
-	ab = kzalloc(sizeof(struct ab3550), GFP_KERNEL);
-	if (!ab) {
-		dev_err(&client->dev,
-			"could not allocate " AB3550_NAME_STRING " device\n");
-		return -ENOMEM;
-	}
-
-	/* Initialize data structure */
-	mutex_init(&ab->access_mutex);
-	spin_lock_init(&ab->event_lock);
-	ab->i2c_client[0] = client;
-
-	i2c_set_clientdata(client, ab);
-
-	/* Read chip ID register */
-	err = get_register_interruptible(ab, 0, AB3550_CID_REG, &ab->chip_id);
-	if (err) {
-		dev_err(&client->dev, "could not communicate with the analog "
-			"baseband chip\n");
-		goto exit_no_detect;
-	}
-
-	for (i = 0; ids[i].id != 0x0; i++) {
-		if (ids[i].id == ab->chip_id) {
-			snprintf(&ab->chip_name[0], sizeof(ab->chip_name) - 1,
-				AB3550_ID_FORMAT_STRING, ids[i].name);
-			break;
-		}
-	}
-
-	if (ids[i].id == 0x0) {
-		dev_err(&client->dev, "unknown analog baseband chip id: 0x%x\n",
-			ab->chip_id);
-		dev_err(&client->dev, "driver not started!\n");
-		goto exit_no_detect;
-	}
-
-	dev_info(&client->dev, "detected AB chip: %s\n", &ab->chip_name[0]);
-
-	/* Attach other dummy I2C clients. */
-	while (++num_i2c_clients < AB3550_NUM_BANKS) {
-		ab->i2c_client[num_i2c_clients] =
-			i2c_new_dummy(client->adapter,
-				(client->addr + num_i2c_clients));
-		if (!ab->i2c_client[num_i2c_clients]) {
-			err = -ENOMEM;
-			goto exit_no_dummy_client;
-		}
-		strlcpy(ab->i2c_client[num_i2c_clients]->name, id->name,
-			sizeof(ab->i2c_client[num_i2c_clients]->name));
-	}
-
-	err = ab3550_setup(ab);
-	if (err)
-		goto exit_no_setup;
-
-	INIT_WORK(&ab->mask_work, ab3550_mask_work);
-
-	for (i = 0; i < ab3550_plf_data->irq.count; i++) {
-		unsigned int irq;
-
-		irq = ab3550_plf_data->irq.base + i;
-		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
-		irq_set_noprobe(irq);
-#endif
-	}
-
-	err = request_threaded_irq(client->irq, NULL, ab3550_irq_handler,
-		IRQF_ONESHOT, "ab3550-core", ab);
-	/* This real unpredictable IRQ is of course sampled for entropy */
-	rand_initialize_irq(client->irq);
-
-	if (err)
-		goto exit_no_irq;
-
-	err = abx500_register_ops(&client->dev, &ab3550_ops);
-	if (err)
-		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].pdata_size = ab3550_plf_data->dev_data_sz[i];
-	}
-
-	err = mfd_add_devices(&client->dev, 0, ab3550_devs,
-		ARRAY_SIZE(ab3550_devs), NULL,
-		ab3550_plf_data->irq.base);
-
-	ab3550_setup_debugfs(ab);
-
-	return 0;
-
-exit_no_ops:
-exit_no_irq:
-exit_no_setup:
-exit_no_dummy_client:
-	/* Unregister the dummy i2c clients. */
-	while (--num_i2c_clients)
-		i2c_unregister_device(ab->i2c_client[num_i2c_clients]);
-exit_no_detect:
-	kfree(ab);
-	return err;
-}
-
-static int __exit ab3550_remove(struct i2c_client *client)
-{
-	struct ab3550 *ab = i2c_get_clientdata(client);
-	int num_i2c_clients = AB3550_NUM_BANKS;
-
-	mfd_remove_devices(&client->dev);
-	ab3550_remove_debugfs();
-
-	while (--num_i2c_clients)
-		i2c_unregister_device(ab->i2c_client[num_i2c_clients]);
-
-	/*
-	 * At this point, all subscribers should have unregistered
-	 * their notifiers so deactivate IRQ
-	 */
-	free_irq(client->irq, ab);
-	kfree(ab);
-	return 0;
-}
-
-static const struct i2c_device_id ab3550_id[] = {
-	{AB3550_NAME_STRING, 0},
-	{}
-};
-MODULE_DEVICE_TABLE(i2c, ab3550_id);
-
-static struct i2c_driver ab3550_driver = {
-	.driver = {
-		.name	= AB3550_NAME_STRING,
-		.owner	= THIS_MODULE,
-	},
-	.id_table	= ab3550_id,
-	.probe		= ab3550_probe,
-	.remove		= __exit_p(ab3550_remove),
-};
-
-static int __init ab3550_i2c_init(void)
-{
-	return i2c_add_driver(&ab3550_driver);
-}
-
-static void __exit ab3550_i2c_exit(void)
-{
-	i2c_del_driver(&ab3550_driver);
-}
-
-subsys_initcall(ab3550_i2c_init);
-module_exit(ab3550_i2c_exit);
-
-MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>");
-MODULE_DESCRIPTION("AB3550 core driver");
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/mfd/ab5500-core.c linux-libre-3.2-gnu/drivers/mfd/ab5500-core.c
--- linux-libre-3.1-gnu/drivers/mfd/ab5500-core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/mfd/ab5500-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1440 @@
+/*
+ * Copyright (C) 2007-2011 ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ * Low-level core for exclusive access to the AB5500 IC on the I2C bus
+ * and some basic chip-configuration.
+ * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
+ * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
+ * Author: Mattias Wallin <mattias.wallin@stericsson.com>
+ * Author: Rickard Andersson <rickard.andersson@stericsson.com>
+ * Author: Karl Komierowski  <karl.komierowski@stericsson.com>
+ * Author: Bibek Basu <bibek.basu@stericsson.com>
+ *
+ * TODO: Event handling with irq_chip. Waiting for PRCMU fw support.
+ */
+
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/random.h>
+#include <linux/mfd/ab5500/ab5500.h>
+#include <linux/mfd/abx500.h>
+#include <linux/list.h>
+#include <linux/bitops.h>
+#include <linux/spinlock.h>
+#include <linux/mfd/core.h>
+#include <linux/version.h>
+#include <linux/mfd/db5500-prcmu.h>
+
+#include "ab5500-core.h"
+#include "ab5500-debugfs.h"
+
+#define AB5500_NUM_EVENT_REG 23
+#define AB5500_IT_LATCH0_REG 0x40
+#define AB5500_IT_MASK0_REG 0x60
+
+/*
+ * Permissible register ranges for reading and writing per device and bank.
+ *
+ * The ranges must be listed in increasing address order, and no overlaps are
+ * allowed. It is assumed that write permission implies read permission
+ * (i.e. only RO and RW permissions should be used).  Ranges with write
+ * permission must not be split up.
+ */
+
+#define NO_RANGE {.count = 0, .range = NULL,}
+static struct ab5500_i2c_banks ab5500_bank_ranges[AB5500_NUM_DEVICES] = {
+	[AB5500_DEVID_USB] =  {
+		.nbanks = 1,
+		.bank = (struct ab5500_i2c_ranges []) {
+			{
+				.bankid = AB5500_BANK_USB,
+				.nranges = 12,
+				.range = (struct ab5500_reg_range[]) {
+					{
+						.first = 0x01,
+						.last = 0x01,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x80,
+						.last = 0x83,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x87,
+						.last = 0x8A,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x8B,
+						.last = 0x8B,
+						.perm = AB5500_PERM_RO,
+					},
+					{
+						.first = 0x91,
+						.last = 0x92,
+						.perm = AB5500_PERM_RO,
+					},
+					{
+						.first = 0x93,
+						.last = 0x93,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x94,
+						.last = 0x94,
+						.perm = AB5500_PERM_RO,
+					},
+					{
+						.first = 0xA8,
+						.last = 0xB0,
+						.perm = AB5500_PERM_RO,
+					},
+					{
+						.first = 0xB2,
+						.last = 0xB2,
+						.perm = AB5500_PERM_RO,
+					},
+					{
+						.first = 0xB4,
+						.last = 0xBC,
+						.perm = AB5500_PERM_RO,
+					},
+					{
+						.first = 0xBF,
+						.last = 0xBF,
+						.perm = AB5500_PERM_RO,
+					},
+					{
+						.first = 0xC1,
+						.last = 0xC5,
+						.perm = AB5500_PERM_RO,
+					},
+				},
+			},
+		},
+	},
+	[AB5500_DEVID_ADC] =  {
+		.nbanks = 1,
+		.bank = (struct ab5500_i2c_ranges []) {
+			{
+				.bankid = AB5500_BANK_ADC,
+				.nranges = 6,
+				.range = (struct ab5500_reg_range[]) {
+					{
+						.first = 0x1F,
+						.last = 0x22,
+						.perm = AB5500_PERM_RO,
+					},
+					{
+						.first = 0x23,
+						.last = 0x24,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x26,
+						.last = 0x2D,
+						.perm = AB5500_PERM_RO,
+					},
+					{
+						.first = 0x2F,
+						.last = 0x34,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x37,
+						.last = 0x57,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x58,
+						.last = 0x58,
+						.perm = AB5500_PERM_RO,
+					},
+				},
+			},
+		},
+	},
+	[AB5500_DEVID_LEDS] =  {
+		.nbanks = 1,
+		.bank = (struct ab5500_i2c_ranges []) {
+			{
+				.bankid = AB5500_BANK_LED,
+				.nranges = 1,
+				.range = (struct ab5500_reg_range[]) {
+					{
+						.first = 0x00,
+						.last = 0x0C,
+						.perm = AB5500_PERM_RW,
+					},
+				},
+			},
+		},
+	},
+	[AB5500_DEVID_VIDEO] =   {
+		.nbanks = 1,
+		.bank = (struct ab5500_i2c_ranges []) {
+			{
+				.bankid = AB5500_BANK_VDENC,
+				.nranges = 12,
+				.range = (struct ab5500_reg_range[]) {
+					{
+						.first = 0x00,
+						.last = 0x08,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x09,
+						.last = 0x09,
+						.perm = AB5500_PERM_RO,
+					},
+					{
+						.first = 0x0A,
+						.last = 0x12,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x15,
+						.last = 0x19,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x1B,
+						.last = 0x21,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x27,
+						.last = 0x2C,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x41,
+						.last = 0x41,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x45,
+						.last = 0x5B,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x5D,
+						.last = 0x5D,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x69,
+						.last = 0x69,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x6C,
+						.last = 0x6D,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x80,
+						.last = 0x81,
+						.perm = AB5500_PERM_RW,
+					},
+				},
+			},
+		},
+	},
+	[AB5500_DEVID_REGULATORS] =   {
+		.nbanks = 2,
+		.bank =  (struct ab5500_i2c_ranges []) {
+			{
+				.bankid = AB5500_BANK_STARTUP,
+				.nranges = 12,
+				.range = (struct ab5500_reg_range[]) {
+					{
+						.first = 0x00,
+						.last = 0x01,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x1F,
+						.last = 0x1F,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x2E,
+						.last = 0x2E,
+						.perm = AB5500_PERM_RO,
+					},
+					{
+						.first = 0x2F,
+						.last = 0x30,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x50,
+						.last = 0x51,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x60,
+						.last = 0x61,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x66,
+						.last = 0x8A,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x8C,
+						.last = 0x96,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0xAA,
+						.last = 0xB4,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0xB7,
+						.last = 0xBF,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0xC1,
+						.last = 0xCA,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0xD3,
+						.last = 0xE0,
+						.perm = AB5500_PERM_RW,
+					},
+				},
+			},
+			{
+				.bankid = AB5500_BANK_SIM_USBSIM,
+				.nranges = 1,
+				.range = (struct ab5500_reg_range[]) {
+					{
+						.first = 0x13,
+						.last = 0x19,
+						.perm = AB5500_PERM_RW,
+					},
+				},
+			},
+		},
+	},
+	[AB5500_DEVID_SIM] =   {
+		.nbanks = 1,
+		.bank = (struct ab5500_i2c_ranges []) {
+			{
+				.bankid = AB5500_BANK_SIM_USBSIM,
+				.nranges = 1,
+				.range = (struct ab5500_reg_range[]) {
+					{
+						.first = 0x13,
+						.last = 0x19,
+						.perm = AB5500_PERM_RW,
+					},
+				},
+			},
+		},
+	},
+	[AB5500_DEVID_RTC] =   {
+		.nbanks = 1,
+		.bank = (struct ab5500_i2c_ranges []) {
+			{
+				.bankid = AB5500_BANK_RTC,
+				.nranges = 2,
+				.range = (struct ab5500_reg_range[]) {
+					{
+						.first = 0x00,
+						.last = 0x04,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0x06,
+						.last = 0x0C,
+						.perm = AB5500_PERM_RW,
+					},
+				},
+			},
+		},
+	},
+	[AB5500_DEVID_CHARGER] =   {
+		.nbanks = 1,
+		.bank = (struct ab5500_i2c_ranges []) {
+			{
+				.bankid = AB5500_BANK_CHG,
+				.nranges = 2,
+				.range = (struct ab5500_reg_range[]) {
+					{
+						.first = 0x11,
+						.last = 0x11,
+						.perm = AB5500_PERM_RO,
+					},
+					{
+						.first = 0x12,
+						.last = 0x1B,
+						.perm = AB5500_PERM_RW,
+					},
+				},
+			},
+		},
+	},
+	[AB5500_DEVID_FUELGAUGE] =   {
+		.nbanks = 1,
+		.bank = (struct ab5500_i2c_ranges []) {
+			{
+				.bankid = AB5500_BANK_FG_BATTCOM_ACC,
+				.nranges = 2,
+				.range = (struct ab5500_reg_range[]) {
+					{
+						.first = 0x00,
+						.last = 0x0B,
+						.perm = AB5500_PERM_RO,
+					},
+					{
+						.first = 0x0C,
+						.last = 0x10,
+						.perm = AB5500_PERM_RW,
+					},
+				},
+			},
+		},
+	},
+	[AB5500_DEVID_VIBRATOR] =   {
+		.nbanks = 1,
+		.bank = (struct ab5500_i2c_ranges []) {
+			{
+				.bankid = AB5500_BANK_VIBRA,
+				.nranges = 2,
+				.range = (struct ab5500_reg_range[]) {
+					{
+						.first = 0x10,
+						.last = 0x13,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0xFE,
+						.last = 0xFE,
+						.perm = AB5500_PERM_RW,
+					},
+				},
+			},
+		},
+	},
+	[AB5500_DEVID_CODEC] =   {
+		.nbanks = 1,
+		.bank = (struct ab5500_i2c_ranges []) {
+			{
+				.bankid = AB5500_BANK_AUDIO_HEADSETUSB,
+				.nranges = 2,
+				.range = (struct ab5500_reg_range[]) {
+					{
+						.first = 0x00,
+						.last = 0x48,
+						.perm = AB5500_PERM_RW,
+					},
+					{
+						.first = 0xEB,
+						.last = 0xFB,
+						.perm = AB5500_PERM_RW,
+					},
+				},
+			},
+		},
+	},
+	[AB5500_DEVID_POWER] = {
+		.nbanks	= 2,
+		.bank	= (struct ab5500_i2c_ranges []) {
+			{
+				.bankid = AB5500_BANK_STARTUP,
+				.nranges = 1,
+				.range = (struct ab5500_reg_range[]) {
+					{
+						.first = 0x30,
+						.last = 0x30,
+						.perm = AB5500_PERM_RW,
+					},
+				},
+			},
+			{
+				.bankid = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP,
+				.nranges = 1,
+				.range = (struct ab5500_reg_range[]) {
+					{
+						.first = 0x01,
+						.last = 0x01,
+						.perm = AB5500_PERM_RW,
+					},
+				},
+			},
+		},
+	},
+};
+
+#define AB5500_IRQ(bank, bit)	((bank) * 8 + (bit))
+
+/* I appologize for the resource names beeing a mix of upper case
+ * and lower case but I want them to be exact as the documentation */
+static struct mfd_cell ab5500_devs[AB5500_NUM_DEVICES] = {
+	[AB5500_DEVID_LEDS] = {
+		.name = "ab5500-leds",
+		.id = AB5500_DEVID_LEDS,
+	},
+	[AB5500_DEVID_POWER] = {
+		.name = "ab5500-power",
+		.id = AB5500_DEVID_POWER,
+	},
+	[AB5500_DEVID_REGULATORS] = {
+		.name = "ab5500-regulator",
+		.id = AB5500_DEVID_REGULATORS,
+	},
+	[AB5500_DEVID_SIM] = {
+		.name = "ab5500-sim",
+		.id = AB5500_DEVID_SIM,
+		.num_resources = 1,
+		.resources = (struct resource[]) {
+			{
+				.name = "SIMOFF",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(2, 0), /*rising*/
+				.end = AB5500_IRQ(2, 1), /*falling*/
+			},
+		},
+	},
+	[AB5500_DEVID_RTC] = {
+		.name = "ab5500-rtc",
+		.id = AB5500_DEVID_RTC,
+		.num_resources = 1,
+		.resources = (struct resource[]) {
+			{
+				.name	= "RTC_Alarm",
+				.flags	= IORESOURCE_IRQ,
+				.start	= AB5500_IRQ(1, 7),
+				.end	= AB5500_IRQ(1, 7),
+			}
+		},
+	},
+	[AB5500_DEVID_CHARGER] = {
+		.name = "ab5500-charger",
+		.id = AB5500_DEVID_CHARGER,
+	},
+	[AB5500_DEVID_ADC] = {
+		.name = "ab5500-adc",
+		.id = AB5500_DEVID_ADC,
+		.num_resources = 10,
+		.resources = (struct resource[]) {
+			{
+				.name = "TRIGGER-0",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(0, 0),
+				.end = AB5500_IRQ(0, 0),
+			},
+			{
+				.name = "TRIGGER-1",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(0, 1),
+				.end = AB5500_IRQ(0, 1),
+			},
+			{
+				.name = "TRIGGER-2",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(0, 2),
+				.end = AB5500_IRQ(0, 2),
+			},
+			{
+				.name = "TRIGGER-3",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(0, 3),
+				.end = AB5500_IRQ(0, 3),
+			},
+			{
+				.name = "TRIGGER-4",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(0, 4),
+				.end = AB5500_IRQ(0, 4),
+			},
+			{
+				.name = "TRIGGER-5",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(0, 5),
+				.end = AB5500_IRQ(0, 5),
+			},
+			{
+				.name = "TRIGGER-6",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(0, 6),
+				.end = AB5500_IRQ(0, 6),
+			},
+			{
+				.name = "TRIGGER-7",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(0, 7),
+				.end = AB5500_IRQ(0, 7),
+			},
+			{
+				.name = "TRIGGER-VBAT",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(0, 8),
+				.end = AB5500_IRQ(0, 8),
+			},
+			{
+				.name = "TRIGGER-VBAT-TXON",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(0, 9),
+				.end = AB5500_IRQ(0, 9),
+			},
+		},
+	},
+	[AB5500_DEVID_FUELGAUGE] = {
+		.name = "ab5500-fuelgauge",
+		.id = AB5500_DEVID_FUELGAUGE,
+		.num_resources = 6,
+		.resources = (struct resource[]) {
+			{
+				.name = "Batt_attach",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(7, 5),
+				.end = AB5500_IRQ(7, 5),
+			},
+			{
+				.name = "Batt_removal",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(7, 6),
+				.end = AB5500_IRQ(7, 6),
+			},
+			{
+				.name = "UART_framing",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(7, 7),
+				.end = AB5500_IRQ(7, 7),
+			},
+			{
+				.name = "UART_overrun",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(8, 0),
+				.end = AB5500_IRQ(8, 0),
+			},
+			{
+				.name = "UART_Rdy_RX",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(8, 1),
+				.end = AB5500_IRQ(8, 1),
+			},
+			{
+				.name = "UART_Rdy_TX",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(8, 2),
+				.end = AB5500_IRQ(8, 2),
+			},
+		},
+	},
+	[AB5500_DEVID_VIBRATOR] = {
+		.name = "ab5500-vibrator",
+		.id = AB5500_DEVID_VIBRATOR,
+	},
+	[AB5500_DEVID_CODEC] = {
+		.name = "ab5500-codec",
+		.id = AB5500_DEVID_CODEC,
+		.num_resources = 3,
+		.resources = (struct resource[]) {
+			{
+				.name = "audio_spkr1_ovc",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(9, 5),
+				.end = AB5500_IRQ(9, 5),
+			},
+			{
+				.name = "audio_plllocked",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(9, 6),
+				.end = AB5500_IRQ(9, 6),
+			},
+			{
+				.name = "audio_spkr2_ovc",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(17, 4),
+				.end = AB5500_IRQ(17, 4),
+			},
+		},
+	},
+	[AB5500_DEVID_USB] = {
+		.name = "ab5500-usb",
+		.id = AB5500_DEVID_USB,
+		.num_resources = 36,
+		.resources = (struct resource[]) {
+			{
+				.name = "Link_Update",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(22, 1),
+				.end = AB5500_IRQ(22, 1),
+			},
+			{
+				.name = "DCIO",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(8, 3),
+				.end = AB5500_IRQ(8, 4),
+			},
+			{
+				.name = "VBUS_R",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(8, 5),
+				.end = AB5500_IRQ(8, 5),
+			},
+			{
+				.name = "VBUS_F",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(8, 6),
+				.end = AB5500_IRQ(8, 6),
+			},
+			{
+				.name = "CHGstate_10_PCVBUSchg",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(8, 7),
+				.end = AB5500_IRQ(8, 7),
+			},
+			{
+				.name = "DCIOreverse_ovc",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(9, 0),
+				.end = AB5500_IRQ(9, 0),
+			},
+			{
+				.name = "USBCharDetDone",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(9, 1),
+				.end = AB5500_IRQ(9, 1),
+			},
+			{
+				.name = "DCIO_no_limit",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(9, 2),
+				.end = AB5500_IRQ(9, 2),
+			},
+			{
+				.name = "USB_suspend",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(9, 3),
+				.end = AB5500_IRQ(9, 3),
+			},
+			{
+				.name = "DCIOreverse_fwdcurrent",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(9, 4),
+				.end = AB5500_IRQ(9, 4),
+			},
+			{
+				.name = "Vbus_Imeasmax_change",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(9, 5),
+				.end = AB5500_IRQ(9, 6),
+			},
+			{
+				.name = "OVV",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(14, 5),
+				.end = AB5500_IRQ(14, 5),
+			},
+			{
+				.name = "USBcharging_NOTok",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(15, 3),
+				.end = AB5500_IRQ(15, 3),
+			},
+			{
+				.name = "usb_adp_sensoroff",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(15, 6),
+				.end = AB5500_IRQ(15, 6),
+			},
+			{
+				.name = "usb_adp_probeplug",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(15, 7),
+				.end = AB5500_IRQ(15, 7),
+			},
+			{
+				.name = "usb_adp_sinkerror",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(16, 0),
+				.end = AB5500_IRQ(16, 6),
+			},
+			{
+				.name = "usb_adp_sourceerror",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(16, 1),
+				.end = AB5500_IRQ(16, 1),
+			},
+			{
+				.name = "usb_idgnd_r",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(16, 2),
+				.end = AB5500_IRQ(16, 2),
+			},
+			{
+				.name = "usb_idgnd_f",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(16, 3),
+				.end = AB5500_IRQ(16, 3),
+			},
+			{
+				.name = "usb_iddetR1",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(16, 4),
+				.end = AB5500_IRQ(16, 5),
+			},
+			{
+				.name = "usb_iddetR2",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(16, 6),
+				.end = AB5500_IRQ(16, 7),
+			},
+			{
+				.name = "usb_iddetR3",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(17, 0),
+				.end = AB5500_IRQ(17, 1),
+			},
+			{
+				.name = "usb_iddetR4",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(17, 2),
+				.end = AB5500_IRQ(17, 3),
+			},
+			{
+				.name = "CharTempWindowOk",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(17, 7),
+				.end = AB5500_IRQ(18, 0),
+			},
+			{
+				.name = "USB_SprDetect",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(18, 1),
+				.end = AB5500_IRQ(18, 1),
+			},
+			{
+				.name = "usb_adp_probe_unplug",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(18, 2),
+				.end = AB5500_IRQ(18, 2),
+			},
+			{
+				.name = "VBUSChDrop",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(18, 3),
+				.end = AB5500_IRQ(18, 4),
+			},
+			{
+				.name = "dcio_char_rec_done",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(18, 5),
+				.end = AB5500_IRQ(18, 5),
+			},
+			{
+				.name = "Charging_stopped_by_temp",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(18, 6),
+				.end = AB5500_IRQ(18, 6),
+			},
+			{
+				.name = "CHGstate_11_SafeModeVBUS",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(21, 1),
+				.end = AB5500_IRQ(21, 2),
+			},
+			{
+				.name = "CHGstate_12_comletedVBUS",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(21, 2),
+				.end = AB5500_IRQ(21, 2),
+			},
+			{
+				.name = "CHGstate_13_completedVBUS",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(21, 3),
+				.end = AB5500_IRQ(21, 3),
+			},
+			{
+				.name = "CHGstate_14_FullChgDCIO",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(21, 4),
+				.end = AB5500_IRQ(21, 4),
+			},
+			{
+				.name = "CHGstate_15_SafeModeDCIO",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(21, 5),
+				.end = AB5500_IRQ(21, 5),
+			},
+			{
+				.name = "CHGstate_16_OFFsuspendDCIO",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(21, 6),
+				.end = AB5500_IRQ(21, 6),
+			},
+			{
+				.name = "CHGstate_17_completedDCIO",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(21, 7),
+				.end = AB5500_IRQ(21, 7),
+			},
+		},
+	},
+	[AB5500_DEVID_OTP] = {
+		.name = "ab5500-otp",
+		.id = AB5500_DEVID_OTP,
+	},
+	[AB5500_DEVID_VIDEO] = {
+		.name = "ab5500-video",
+		.id = AB5500_DEVID_VIDEO,
+		.num_resources = 1,
+		.resources = (struct resource[]) {
+			{
+				.name = "plugTVdet",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(22, 2),
+				.end = AB5500_IRQ(22, 2),
+			},
+		},
+	},
+	[AB5500_DEVID_DBIECI] = {
+		.name = "ab5500-dbieci",
+		.id = AB5500_DEVID_DBIECI,
+		.num_resources = 10,
+		.resources = (struct resource[]) {
+			{
+				.name = "COLL",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(14, 0),
+				.end = AB5500_IRQ(14, 0),
+			},
+			{
+				.name = "RESERR",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(14, 1),
+				.end = AB5500_IRQ(14, 1),
+			},
+			{
+				.name = "FRAERR",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(14, 2),
+				.end = AB5500_IRQ(14, 2),
+			},
+			{
+				.name = "COMERR",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(14, 3),
+				.end = AB5500_IRQ(14, 3),
+			},
+			{
+				.name = "BSI_indicator",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(14, 4),
+				.end = AB5500_IRQ(14, 4),
+			},
+			{
+				.name = "SPDSET",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(14, 6),
+				.end = AB5500_IRQ(14, 6),
+			},
+			{
+				.name = "DSENT",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(14, 7),
+				.end = AB5500_IRQ(14, 7),
+			},
+			{
+				.name = "DREC",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(15, 0),
+				.end = AB5500_IRQ(15, 0),
+			},
+			{
+				.name = "ACCINT",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(15, 1),
+				.end = AB5500_IRQ(15, 1),
+			},
+			{
+				.name = "NOPINT",
+				.flags = IORESOURCE_IRQ,
+				.start = AB5500_IRQ(15, 2),
+				.end = AB5500_IRQ(15, 2),
+			},
+		},
+	},
+	[AB5500_DEVID_ONSWA] = {
+		.name = "ab5500-onswa",
+		.id = AB5500_DEVID_ONSWA,
+		.num_resources = 2,
+		.resources = (struct resource[]) {
+			{
+				.name	= "ONSWAn_rising",
+				.flags	= IORESOURCE_IRQ,
+				.start	= AB5500_IRQ(1, 3),
+				.end	= AB5500_IRQ(1, 3),
+			},
+			{
+				.name	= "ONSWAn_falling",
+				.flags	= IORESOURCE_IRQ,
+				.start	= AB5500_IRQ(1, 4),
+				.end	= AB5500_IRQ(1, 4),
+			},
+		},
+	},
+};
+
+/*
+ * Functionality for getting/setting register values.
+ */
+int ab5500_get_register_interruptible_raw(struct ab5500 *ab,
+					  u8 bank, u8 reg,
+					  u8 *value)
+{
+	int err;
+
+	if (bank >= AB5500_NUM_BANKS)
+		return -EINVAL;
+
+	err = mutex_lock_interruptible(&ab->access_mutex);
+	if (err)
+		return err;
+	err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr, reg, value, 1);
+
+	mutex_unlock(&ab->access_mutex);
+	return err;
+}
+
+static int get_register_page_interruptible(struct ab5500 *ab, u8 bank,
+	u8 first_reg, u8 *regvals, u8 numregs)
+{
+	int err;
+
+	if (bank >= AB5500_NUM_BANKS)
+		return -EINVAL;
+
+	err = mutex_lock_interruptible(&ab->access_mutex);
+	if (err)
+		return err;
+
+	while (numregs) {
+		/* The hardware limit for get page is 4 */
+		u8 curnum = min_t(u8, numregs, 4u);
+
+		err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr,
+					    first_reg, regvals, curnum);
+		if (err)
+			goto out;
+
+		numregs -= curnum;
+		first_reg += curnum;
+		regvals += curnum;
+	}
+
+out:
+	mutex_unlock(&ab->access_mutex);
+	return err;
+}
+
+int ab5500_mask_and_set_register_interruptible_raw(struct ab5500 *ab, u8 bank,
+	u8 reg, u8 bitmask, u8 bitvalues)
+{
+	int err = 0;
+
+	if (bank >= AB5500_NUM_BANKS)
+		return -EINVAL;
+
+	if (bitmask) {
+		u8 buf;
+
+		err = mutex_lock_interruptible(&ab->access_mutex);
+		if (err)
+			return err;
+
+		if (bitmask == 0xFF) /* No need to read in this case. */
+			buf = bitvalues;
+		else { /* Read and modify the register value. */
+			err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr,
+				reg, &buf, 1);
+			if (err)
+				return err;
+
+			buf = ((~bitmask & buf) | (bitmask & bitvalues));
+		}
+		/* Write the new value. */
+		err = db5500_prcmu_abb_write(bankinfo[bank].slave_addr, reg,
+					     &buf, 1);
+
+		mutex_unlock(&ab->access_mutex);
+	}
+	return err;
+}
+
+static int
+set_register_interruptible(struct ab5500 *ab, u8 bank, u8 reg, u8 value)
+{
+	return ab5500_mask_and_set_register_interruptible_raw(ab, bank, reg,
+							      0xff, value);
+}
+
+/*
+ * Read/write permission checking functions.
+ */
+static const struct ab5500_i2c_ranges *get_bankref(u8 devid, u8 bank)
+{
+	u8 i;
+
+	if (devid < AB5500_NUM_DEVICES) {
+		for (i = 0; i < ab5500_bank_ranges[devid].nbanks; i++) {
+			if (ab5500_bank_ranges[devid].bank[i].bankid == bank)
+				return &ab5500_bank_ranges[devid].bank[i];
+		}
+	}
+	return NULL;
+}
+
+static bool page_write_allowed(u8 devid, u8 bank, u8 first_reg, u8 last_reg)
+{
+	u8 i; /* range loop index */
+	const struct ab5500_i2c_ranges *bankref;
+
+	bankref = get_bankref(devid, bank);
+	if (bankref == NULL || last_reg < first_reg)
+		return false;
+
+	for (i = 0; i < bankref->nranges; i++) {
+		if (first_reg < bankref->range[i].first)
+			break;
+		if ((last_reg <= bankref->range[i].last) &&
+			(bankref->range[i].perm & AB5500_PERM_WR))
+			return true;
+	}
+	return false;
+}
+
+static bool reg_write_allowed(u8 devid, u8 bank, u8 reg)
+{
+	return page_write_allowed(devid, bank, reg, reg);
+}
+
+static bool page_read_allowed(u8 devid, u8 bank, u8 first_reg, u8 last_reg)
+{
+	u8 i;
+	const struct ab5500_i2c_ranges *bankref;
+
+	bankref = get_bankref(devid, bank);
+	if (bankref == NULL || last_reg < first_reg)
+		return false;
+
+
+	/* Find the range (if it exists in the list) that includes first_reg. */
+	for (i = 0; i < bankref->nranges; i++) {
+		if (first_reg < bankref->range[i].first)
+			return false;
+		if (first_reg <= bankref->range[i].last)
+			break;
+	}
+	/* Make sure that the entire range up to and including last_reg is
+	 * readable. This may span several of the ranges in the list.
+	 */
+	while ((i < bankref->nranges) &&
+		(bankref->range[i].perm & AB5500_PERM_RD)) {
+		if (last_reg <= bankref->range[i].last)
+			return true;
+		if ((++i >= bankref->nranges) ||
+			(bankref->range[i].first !=
+				(bankref->range[i - 1].last + 1))) {
+			break;
+		}
+	}
+	return false;
+}
+
+static bool reg_read_allowed(u8 devid, u8 bank, u8 reg)
+{
+	return page_read_allowed(devid, bank, reg, reg);
+}
+
+
+/*
+ * The exported register access functionality.
+ */
+static int ab5500_get_chip_id(struct device *dev)
+{
+	struct ab5500 *ab = dev_get_drvdata(dev->parent);
+
+	return (int)ab->chip_id;
+}
+
+static int ab5500_mask_and_set_register_interruptible(struct device *dev,
+		u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
+{
+	struct ab5500 *ab;
+	struct platform_device *pdev = to_platform_device(dev);
+
+	if ((AB5500_NUM_BANKS <= bank) ||
+		!reg_write_allowed(pdev->id, bank, reg))
+		return -EINVAL;
+
+	ab = dev_get_drvdata(dev->parent);
+	return ab5500_mask_and_set_register_interruptible_raw(ab, bank, reg,
+		bitmask, bitvalues);
+}
+
+static int ab5500_set_register_interruptible(struct device *dev, u8 bank,
+	u8 reg, u8 value)
+{
+	return ab5500_mask_and_set_register_interruptible(dev, bank, reg, 0xFF,
+		value);
+}
+
+static int ab5500_get_register_interruptible(struct device *dev, u8 bank,
+		u8 reg, u8 *value)
+{
+	struct ab5500 *ab;
+	struct platform_device *pdev = to_platform_device(dev);
+
+	if ((AB5500_NUM_BANKS <= bank) ||
+		!reg_read_allowed(pdev->id, bank, reg))
+		return -EINVAL;
+
+	ab = dev_get_drvdata(dev->parent);
+	return ab5500_get_register_interruptible_raw(ab, bank, reg, value);
+}
+
+static int ab5500_get_register_page_interruptible(struct device *dev, u8 bank,
+		u8 first_reg, u8 *regvals, u8 numregs)
+{
+	struct ab5500 *ab;
+	struct platform_device *pdev = to_platform_device(dev);
+
+	if ((AB5500_NUM_BANKS <= bank) ||
+		!page_read_allowed(pdev->id, bank,
+			first_reg, (first_reg + numregs - 1)))
+		return -EINVAL;
+
+	ab = dev_get_drvdata(dev->parent);
+	return get_register_page_interruptible(ab, bank, first_reg, regvals,
+		numregs);
+}
+
+static int
+ab5500_event_registers_startup_state_get(struct device *dev, u8 *event)
+{
+	struct ab5500 *ab;
+
+	ab = dev_get_drvdata(dev->parent);
+	if (!ab->startup_events_read)
+		return -EAGAIN; /* Try again later */
+
+	memcpy(event, ab->startup_events, AB5500_NUM_EVENT_REG);
+	return 0;
+}
+
+static struct abx500_ops ab5500_ops = {
+	.get_chip_id = ab5500_get_chip_id,
+	.get_register = ab5500_get_register_interruptible,
+	.set_register = ab5500_set_register_interruptible,
+	.get_register_page = ab5500_get_register_page_interruptible,
+	.set_register_page = NULL,
+	.mask_and_set_register = ab5500_mask_and_set_register_interruptible,
+	.event_registers_startup_state_get =
+		ab5500_event_registers_startup_state_get,
+	.startup_irq_enabled = NULL,
+};
+
+/*
+ * ab5500_setup : Basic set-up, datastructure creation/destruction
+ *		  and I2C interface.This sets up a default config
+ *		  in the AB5500 chip so that it will work as expected.
+ * @ab :	  Pointer to ab5500 structure
+ * @settings :    Pointer to struct abx500_init_settings
+ * @size :        Size of init data
+ */
+static int __init ab5500_setup(struct ab5500 *ab,
+	struct abx500_init_settings *settings, unsigned int size)
+{
+	int err = 0;
+	int i;
+
+	for (i = 0; i < size; i++) {
+		err = ab5500_mask_and_set_register_interruptible_raw(ab,
+			settings[i].bank,
+			settings[i].reg,
+			0xFF, settings[i].setting);
+		if (err)
+			goto exit_no_setup;
+
+		/* If event mask register update the event mask in ab5500 */
+		if ((settings[i].bank == AB5500_BANK_IT) &&
+			(AB5500_MASK_BASE <= settings[i].reg) &&
+			(settings[i].reg <= AB5500_MASK_END)) {
+			ab->mask[settings[i].reg - AB5500_MASK_BASE] =
+				settings[i].setting;
+		}
+	}
+exit_no_setup:
+	return err;
+}
+
+struct ab_family_id {
+	u8	id;
+	char	*name;
+};
+
+static const struct ab_family_id ids[] __initdata = {
+	/* AB5500 */
+	{
+		.id = AB5500_1_0,
+		.name = "1.0"
+	},
+	{
+		.id = AB5500_1_1,
+		.name = "1.1"
+	},
+	/* Terminator */
+	{
+		.id = 0x00,
+	}
+};
+
+static int __init ab5500_probe(struct platform_device *pdev)
+{
+	struct ab5500 *ab;
+	struct ab5500_platform_data *ab5500_plf_data =
+		pdev->dev.platform_data;
+	int err;
+	int i;
+
+	ab = kzalloc(sizeof(struct ab5500), GFP_KERNEL);
+	if (!ab) {
+		dev_err(&pdev->dev,
+			"could not allocate ab5500 device\n");
+		return -ENOMEM;
+	}
+
+	/* Initialize data structure */
+	mutex_init(&ab->access_mutex);
+	mutex_init(&ab->irq_lock);
+	ab->dev = &pdev->dev;
+
+	platform_set_drvdata(pdev, ab);
+
+	/* Read chip ID register */
+	err = ab5500_get_register_interruptible_raw(ab,
+					AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP,
+					AB5500_CHIP_ID, &ab->chip_id);
+	if (err) {
+		dev_err(&pdev->dev, "could not communicate with the analog "
+			"baseband chip\n");
+		goto exit_no_detect;
+	}
+
+	for (i = 0; ids[i].id != 0x0; i++) {
+		if (ids[i].id == ab->chip_id) {
+			snprintf(&ab->chip_name[0], sizeof(ab->chip_name) - 1,
+				"AB5500 %s", ids[i].name);
+			break;
+		}
+	}
+	if (ids[i].id == 0x0) {
+		dev_err(&pdev->dev, "unknown analog baseband chip id: 0x%x\n",
+			ab->chip_id);
+		dev_err(&pdev->dev, "driver not started!\n");
+		goto exit_no_detect;
+	}
+
+	/* Clear and mask all interrupts */
+	for (i = 0; i < AB5500_NUM_IRQ_REGS; i++) {
+		u8 latchreg = AB5500_IT_LATCH0_REG + i;
+		u8 maskreg = AB5500_IT_MASK0_REG + i;
+		u8 val;
+
+		ab5500_get_register_interruptible_raw(ab, AB5500_BANK_IT,
+						      latchreg, &val);
+		set_register_interruptible(ab, AB5500_BANK_IT, maskreg, 0xff);
+		ab->mask[i] = ab->oldmask[i] = 0xff;
+	}
+
+	err = abx500_register_ops(&pdev->dev, &ab5500_ops);
+	if (err) {
+		dev_err(&pdev->dev, "ab5500_register ops error\n");
+		goto exit_no_detect;
+	}
+
+	/* Set up and register the platform devices. */
+	for (i = 0; i < AB5500_NUM_DEVICES; i++) {
+		ab5500_devs[i].platform_data = ab5500_plf_data->dev_data[i];
+		ab5500_devs[i].pdata_size =
+			sizeof(ab5500_plf_data->dev_data[i]);
+	}
+
+	err = mfd_add_devices(&pdev->dev, 0, ab5500_devs,
+		ARRAY_SIZE(ab5500_devs), NULL,
+		ab5500_plf_data->irq.base);
+	if (err) {
+		dev_err(&pdev->dev, "ab5500_mfd_add_device error\n");
+		goto exit_no_detect;
+	}
+
+	err = ab5500_setup(ab, ab5500_plf_data->init_settings,
+		ab5500_plf_data->init_settings_sz);
+	if (err) {
+		dev_err(&pdev->dev, "ab5500_setup error\n");
+		goto exit_no_detect;
+	}
+
+	ab5500_setup_debugfs(ab);
+
+	dev_info(&pdev->dev, "detected AB chip: %s\n", &ab->chip_name[0]);
+	return 0;
+
+exit_no_detect:
+	kfree(ab);
+	return err;
+}
+
+static int __exit ab5500_remove(struct platform_device *pdev)
+{
+	struct ab5500 *ab = platform_get_drvdata(pdev);
+
+	ab5500_remove_debugfs();
+	mfd_remove_devices(&pdev->dev);
+	kfree(ab);
+	return 0;
+}
+
+static struct platform_driver ab5500_driver = {
+	.driver = {
+		.name = "ab5500-core",
+		.owner = THIS_MODULE,
+	},
+	.remove  = __exit_p(ab5500_remove),
+};
+
+static int __init ab5500_core_init(void)
+{
+	return platform_driver_probe(&ab5500_driver, ab5500_probe);
+}
+
+static void __exit ab5500_core_exit(void)
+{
+	platform_driver_unregister(&ab5500_driver);
+}
+
+subsys_initcall(ab5500_core_init);
+module_exit(ab5500_core_exit);
+
+MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>");
+MODULE_DESCRIPTION("AB5500 core driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/mfd/ab5500-core.h linux-libre-3.2-gnu/drivers/mfd/ab5500-core.h
--- linux-libre-3.1-gnu/drivers/mfd/ab5500-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/mfd/ab5500-core.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ * Shared definitions and data structures for the AB5500 MFD driver
+ */
+
+/* Read/write operation values. */
+#define AB5500_PERM_RD (0x01)
+#define AB5500_PERM_WR (0x02)
+
+/* Read/write permissions. */
+#define AB5500_PERM_RO (AB5500_PERM_RD)
+#define AB5500_PERM_RW (AB5500_PERM_RD | AB5500_PERM_WR)
+
+#define AB5500_MASK_BASE (0x60)
+#define AB5500_MASK_END (0x79)
+#define AB5500_CHIP_ID (0x20)
+
+/**
+ * struct ab5500_reg_range
+ * @first: the first address of the range
+ * @last: the last address of the range
+ * @perm: access permissions for the range
+ */
+struct ab5500_reg_range {
+	u8 first;
+	u8 last;
+	u8 perm;
+};
+
+/**
+ * struct ab5500_i2c_ranges
+ * @count: the number of ranges in the list
+ * @range: the list of register ranges
+ */
+struct ab5500_i2c_ranges {
+	u8 nranges;
+	u8 bankid;
+	const struct ab5500_reg_range *range;
+};
+
+/**
+ * struct ab5500_i2c_banks
+ * @count: the number of ranges in the list
+ * @range: the list of register ranges
+ */
+struct ab5500_i2c_banks {
+	u8 nbanks;
+	const struct ab5500_i2c_ranges *bank;
+};
+
+/**
+ * struct ab5500_bank
+ * @slave_addr: I2C slave_addr found in AB5500 specification
+ * @name: Documentation name of the bank. For reference
+ */
+struct ab5500_bank {
+	u8 slave_addr;
+	const char *name;
+};
+
+static const struct ab5500_bank bankinfo[AB5500_NUM_BANKS] = {
+	[AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = {
+		AB5500_ADDR_VIT_IO_I2C_CLK_TST_OTP, "VIT_IO_I2C_CLK_TST_OTP"},
+	[AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = {
+		AB5500_ADDR_VDDDIG_IO_I2C_CLK_TST, "VDDDIG_IO_I2C_CLK_TST"},
+	[AB5500_BANK_VDENC] = {AB5500_ADDR_VDENC, "VDENC"},
+	[AB5500_BANK_SIM_USBSIM] = {AB5500_ADDR_SIM_USBSIM, "SIM_USBSIM"},
+	[AB5500_BANK_LED] = {AB5500_ADDR_LED, "LED"},
+	[AB5500_BANK_ADC] = {AB5500_ADDR_ADC, "ADC"},
+	[AB5500_BANK_RTC] = {AB5500_ADDR_RTC, "RTC"},
+	[AB5500_BANK_STARTUP] = {AB5500_ADDR_STARTUP, "STARTUP"},
+	[AB5500_BANK_DBI_ECI] = {AB5500_ADDR_DBI_ECI, "DBI-ECI"},
+	[AB5500_BANK_CHG] = {AB5500_ADDR_CHG, "CHG"},
+	[AB5500_BANK_FG_BATTCOM_ACC] = {
+		AB5500_ADDR_FG_BATTCOM_ACC, "FG_BATCOM_ACC"},
+	[AB5500_BANK_USB] = {AB5500_ADDR_USB, "USB"},
+	[AB5500_BANK_IT] = {AB5500_ADDR_IT, "IT"},
+	[AB5500_BANK_VIBRA] = {AB5500_ADDR_VIBRA, "VIBRA"},
+	[AB5500_BANK_AUDIO_HEADSETUSB] = {
+		AB5500_ADDR_AUDIO_HEADSETUSB, "AUDIO_HEADSETUSB"},
+};
+
+int ab5500_get_register_interruptible_raw(struct ab5500 *ab, u8 bank, u8 reg,
+	u8 *value);
+int ab5500_mask_and_set_register_interruptible_raw(struct ab5500 *ab, u8 bank,
+	u8 reg, u8 bitmask, u8 bitvalues);
diff -druN linux-libre-3.1-gnu/drivers/mfd/ab5500-debugfs.c linux-libre-3.2-gnu/drivers/mfd/ab5500-debugfs.c
--- linux-libre-3.1-gnu/drivers/mfd/ab5500-debugfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/mfd/ab5500-debugfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,807 @@
+/*
+ * Copyright (C) 2011 ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ * Debugfs support for the AB5500 MFD driver
+ */
+
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/mfd/ab5500/ab5500.h>
+#include <linux/mfd/abx500.h>
+#include <linux/uaccess.h>
+
+#include "ab5500-core.h"
+#include "ab5500-debugfs.h"
+
+static struct ab5500_i2c_ranges ab5500_reg_ranges[AB5500_NUM_BANKS] = {
+	[AB5500_BANK_LED] = {
+		.bankid = AB5500_BANK_LED,
+		.nranges = 1,
+		.range = (struct ab5500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x0C,
+				.perm = AB5500_PERM_RW,
+			},
+		},
+	},
+	[AB5500_BANK_ADC] = {
+		.bankid = AB5500_BANK_ADC,
+		.nranges = 6,
+		.range = (struct ab5500_reg_range[]) {
+			{
+				.first = 0x1F,
+				.last = 0x22,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0x23,
+				.last = 0x24,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x26,
+				.last = 0x2D,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0x2F,
+				.last = 0x34,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x37,
+				.last = 0x57,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x58,
+				.last = 0x58,
+				.perm = AB5500_PERM_RO,
+			},
+		},
+	},
+	[AB5500_BANK_RTC] = {
+		.bankid = AB5500_BANK_RTC,
+		.nranges = 2,
+		.range = (struct ab5500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x04,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x06,
+				.last = 0x0C,
+				.perm = AB5500_PERM_RW,
+			},
+		},
+	},
+	[AB5500_BANK_STARTUP] = {
+		.bankid = AB5500_BANK_STARTUP,
+		.nranges = 12,
+		.range = (struct ab5500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x01,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x1F,
+				.last = 0x1F,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x2E,
+				.last = 0x2E,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0x2F,
+				.last = 0x30,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x50,
+				.last = 0x51,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x60,
+				.last = 0x61,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x66,
+				.last = 0x8A,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x8C,
+				.last = 0x96,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0xAA,
+				.last = 0xB4,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0xB7,
+				.last = 0xBF,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0xC1,
+				.last = 0xCA,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0xD3,
+				.last = 0xE0,
+				.perm = AB5500_PERM_RW,
+			},
+		},
+	},
+	[AB5500_BANK_DBI_ECI] = {
+		.bankid = AB5500_BANK_DBI_ECI,
+		.nranges = 3,
+		.range = (struct ab5500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x07,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x10,
+				.last = 0x10,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x13,
+				.last = 0x13,
+				.perm = AB5500_PERM_RW,
+			},
+		},
+	},
+	[AB5500_BANK_CHG] = {
+		.bankid = AB5500_BANK_CHG,
+		.nranges = 2,
+		.range = (struct ab5500_reg_range[]) {
+			{
+				.first = 0x11,
+				.last = 0x11,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0x12,
+				.last = 0x1B,
+				.perm = AB5500_PERM_RW,
+			},
+		},
+	},
+	[AB5500_BANK_FG_BATTCOM_ACC] = {
+		.bankid = AB5500_BANK_FG_BATTCOM_ACC,
+		.nranges = 2,
+		.range = (struct ab5500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x0B,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0x0C,
+				.last = 0x10,
+				.perm = AB5500_PERM_RW,
+			},
+		},
+	},
+	[AB5500_BANK_USB] = {
+		.bankid = AB5500_BANK_USB,
+		.nranges = 12,
+		.range = (struct ab5500_reg_range[]) {
+			{
+				.first = 0x01,
+				.last = 0x01,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x80,
+				.last = 0x83,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x87,
+				.last = 0x8A,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x8B,
+				.last = 0x8B,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0x91,
+				.last = 0x92,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0x93,
+				.last = 0x93,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x94,
+				.last = 0x94,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0xA8,
+				.last = 0xB0,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0xB2,
+				.last = 0xB2,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0xB4,
+				.last = 0xBC,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0xBF,
+				.last = 0xBF,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0xC1,
+				.last = 0xC5,
+				.perm = AB5500_PERM_RO,
+			},
+		},
+	},
+	[AB5500_BANK_IT] = {
+		.bankid = AB5500_BANK_IT,
+		.nranges = 4,
+		.range = (struct ab5500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x02,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0x20,
+				.last = 0x36,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0x40,
+				.last = 0x56,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0x60,
+				.last = 0x76,
+				.perm = AB5500_PERM_RO,
+			},
+		},
+	},
+	[AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = {
+		.bankid = AB5500_BANK_VDDDIG_IO_I2C_CLK_TST,
+		.nranges = 7,
+		.range = (struct ab5500_reg_range[]) {
+			{
+				.first = 0x02,
+				.last = 0x02,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x12,
+				.last = 0x12,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x30,
+				.last = 0x34,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x40,
+				.last = 0x44,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x50,
+				.last = 0x54,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x60,
+				.last = 0x64,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x70,
+				.last = 0x74,
+				.perm = AB5500_PERM_RW,
+			},
+		},
+	},
+	[AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = {
+		.bankid = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP,
+		.nranges = 13,
+		.range = (struct ab5500_reg_range[]) {
+			{
+				.first = 0x01,
+				.last = 0x01,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x02,
+				.last = 0x02,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0x0D,
+				.last = 0x0F,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x1C,
+				.last = 0x1C,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x1E,
+				.last = 0x1E,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x20,
+				.last = 0x21,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x25,
+				.last = 0x25,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x28,
+				.last = 0x2A,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x30,
+				.last = 0x33,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x40,
+				.last = 0x43,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x50,
+				.last = 0x53,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x60,
+				.last = 0x63,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x70,
+				.last = 0x73,
+				.perm = AB5500_PERM_RW,
+			},
+		},
+	},
+	[AB5500_BANK_VIBRA] = {
+		.bankid = AB5500_BANK_VIBRA,
+		.nranges = 2,
+		.range = (struct ab5500_reg_range[]) {
+			{
+				.first = 0x10,
+				.last = 0x13,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0xFE,
+				.last = 0xFE,
+				.perm = AB5500_PERM_RW,
+			},
+		},
+	},
+	[AB5500_BANK_AUDIO_HEADSETUSB] = {
+		.bankid = AB5500_BANK_AUDIO_HEADSETUSB,
+		.nranges = 2,
+		.range = (struct ab5500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x48,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0xEB,
+				.last = 0xFB,
+				.perm = AB5500_PERM_RW,
+			},
+		},
+	},
+	[AB5500_BANK_SIM_USBSIM] = {
+		.bankid = AB5500_BANK_SIM_USBSIM,
+		.nranges = 1,
+		.range = (struct ab5500_reg_range[]) {
+			{
+				.first = 0x13,
+				.last = 0x19,
+				.perm = AB5500_PERM_RW,
+			},
+		},
+	},
+	[AB5500_BANK_VDENC] = {
+		.bankid = AB5500_BANK_VDENC,
+		.nranges = 12,
+		.range = (struct ab5500_reg_range[]) {
+			{
+				.first = 0x00,
+				.last = 0x08,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x09,
+				.last = 0x09,
+				.perm = AB5500_PERM_RO,
+			},
+			{
+				.first = 0x0A,
+				.last = 0x12,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x15,
+				.last = 0x19,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x1B,
+				.last = 0x21,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x27,
+				.last = 0x2C,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x41,
+				.last = 0x41,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x45,
+				.last = 0x5B,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x5D,
+				.last = 0x5D,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x69,
+				.last = 0x69,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x6C,
+				.last = 0x6D,
+				.perm = AB5500_PERM_RW,
+			},
+			{
+				.first = 0x80,
+				.last = 0x81,
+				.perm = AB5500_PERM_RW,
+			},
+		},
+	},
+};
+
+static int ab5500_registers_print(struct seq_file *s, void *p)
+{
+	struct ab5500 *ab = s->private;
+	unsigned int i;
+	u8 bank = (u8)ab->debug_bank;
+
+	seq_printf(s, "ab5500 register values:\n");
+	for (bank = 0; bank < AB5500_NUM_BANKS; bank++) {
+		seq_printf(s, " bank %u, %s (0x%x):\n", bank,
+				bankinfo[bank].name,
+				bankinfo[bank].slave_addr);
+		for (i = 0; i < ab5500_reg_ranges[bank].nranges; i++) {
+			u8 reg;
+			int err;
+
+			for (reg = ab5500_reg_ranges[bank].range[i].first;
+				reg <= ab5500_reg_ranges[bank].range[i].last;
+				reg++) {
+				u8 value;
+
+				err = ab5500_get_register_interruptible_raw(ab,
+								bank, reg,
+								&value);
+				if (err < 0) {
+					dev_err(ab->dev, "get_reg failed %d"
+						"bank 0x%x reg 0x%x\n",
+						err, bank, reg);
+					return err;
+				}
+
+				err = seq_printf(s, "[%d/0x%02X]: 0x%02X\n",
+						bank, reg, value);
+				if (err < 0) {
+					dev_err(ab->dev,
+						"seq_printf overflow\n");
+					/*
+					 * Error is not returned here since
+					 * the output is wanted in any case
+					 */
+					return 0;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+static int ab5500_registers_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab5500_registers_print, inode->i_private);
+}
+
+static const struct file_operations ab5500_registers_fops = {
+	.open = ab5500_registers_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static int ab5500_bank_print(struct seq_file *s, void *p)
+{
+	struct ab5500 *ab = s->private;
+
+	seq_printf(s, "%d\n", ab->debug_bank);
+	return 0;
+}
+
+static int ab5500_bank_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab5500_bank_print, inode->i_private);
+}
+
+static ssize_t ab5500_bank_write(struct file *file,
+	const char __user *user_buf,
+	size_t count, loff_t *ppos)
+{
+	struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
+	char buf[32];
+	int buf_size;
+	unsigned long user_bank;
+	int err;
+
+	/* Get userspace string and assure termination */
+	buf_size = min(count, (sizeof(buf) - 1));
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	buf[buf_size] = 0;
+
+	err = strict_strtoul(buf, 0, &user_bank);
+	if (err)
+		return -EINVAL;
+
+	if (user_bank >= AB5500_NUM_BANKS) {
+		dev_err(ab->dev,
+			"debugfs error input > number of banks\n");
+		return -EINVAL;
+	}
+
+	ab->debug_bank = user_bank;
+
+	return buf_size;
+}
+
+static int ab5500_address_print(struct seq_file *s, void *p)
+{
+	struct ab5500 *ab = s->private;
+
+	seq_printf(s, "0x%02X\n", ab->debug_address);
+	return 0;
+}
+
+static int ab5500_address_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab5500_address_print, inode->i_private);
+}
+
+static ssize_t ab5500_address_write(struct file *file,
+	const char __user *user_buf,
+	size_t count, loff_t *ppos)
+{
+	struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
+	char buf[32];
+	int buf_size;
+	unsigned long user_address;
+	int err;
+
+	/* Get userspace string and assure termination */
+	buf_size = min(count, (sizeof(buf) - 1));
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	buf[buf_size] = 0;
+
+	err = strict_strtoul(buf, 0, &user_address);
+	if (err)
+		return -EINVAL;
+	if (user_address > 0xff) {
+		dev_err(ab->dev,
+			"debugfs error input > 0xff\n");
+		return -EINVAL;
+	}
+	ab->debug_address = user_address;
+	return buf_size;
+}
+
+static int ab5500_val_print(struct seq_file *s, void *p)
+{
+	struct ab5500 *ab = s->private;
+	int err;
+	u8 regvalue;
+
+	err = ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank,
+		(u8)ab->debug_address, &regvalue);
+	if (err) {
+		dev_err(ab->dev, "get_reg failed %d, bank 0x%x"
+			", reg 0x%x\n", err, ab->debug_bank,
+			ab->debug_address);
+		return -EINVAL;
+	}
+	seq_printf(s, "0x%02X\n", regvalue);
+
+	return 0;
+}
+
+static int ab5500_val_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab5500_val_print, inode->i_private);
+}
+
+static ssize_t ab5500_val_write(struct file *file,
+	const char __user *user_buf,
+	size_t count, loff_t *ppos)
+{
+	struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
+	char buf[32];
+	int buf_size;
+	unsigned long user_val;
+	int err;
+	u8 regvalue;
+
+	/* Get userspace string and assure termination */
+	buf_size = min(count, (sizeof(buf)-1));
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	buf[buf_size] = 0;
+
+	err = strict_strtoul(buf, 0, &user_val);
+	if (err)
+		return -EINVAL;
+	if (user_val > 0xff) {
+		dev_err(ab->dev,
+			"debugfs error input > 0xff\n");
+		return -EINVAL;
+	}
+	err = ab5500_mask_and_set_register_interruptible_raw(
+		ab, (u8)ab->debug_bank,
+		(u8)ab->debug_address, 0xFF, (u8)user_val);
+	if (err)
+		return -EINVAL;
+
+	ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank,
+		(u8)ab->debug_address, &regvalue);
+	if (err)
+		return -EINVAL;
+
+	return buf_size;
+}
+
+static const struct file_operations ab5500_bank_fops = {
+	.open = ab5500_bank_open,
+	.write = ab5500_bank_write,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static const struct file_operations ab5500_address_fops = {
+	.open = ab5500_address_open,
+	.write = ab5500_address_write,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static const struct file_operations ab5500_val_fops = {
+	.open = ab5500_val_open,
+	.write = ab5500_val_write,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+static struct dentry *ab5500_dir;
+static struct dentry *ab5500_reg_file;
+static struct dentry *ab5500_bank_file;
+static struct dentry *ab5500_address_file;
+static struct dentry *ab5500_val_file;
+
+void __init ab5500_setup_debugfs(struct ab5500 *ab)
+{
+	ab->debug_bank = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP;
+	ab->debug_address = AB5500_CHIP_ID;
+
+	ab5500_dir = debugfs_create_dir("ab5500", NULL);
+	if (!ab5500_dir)
+		goto exit_no_debugfs;
+
+	ab5500_reg_file = debugfs_create_file("all-bank-registers",
+		S_IRUGO, ab5500_dir, ab, &ab5500_registers_fops);
+	if (!ab5500_reg_file)
+		goto exit_destroy_dir;
+
+	ab5500_bank_file = debugfs_create_file("register-bank",
+		(S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_bank_fops);
+	if (!ab5500_bank_file)
+		goto exit_destroy_reg;
+
+	ab5500_address_file = debugfs_create_file("register-address",
+		(S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_address_fops);
+	if (!ab5500_address_file)
+		goto exit_destroy_bank;
+
+	ab5500_val_file = debugfs_create_file("register-value",
+		(S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_val_fops);
+	if (!ab5500_val_file)
+		goto exit_destroy_address;
+
+	return;
+
+exit_destroy_address:
+	debugfs_remove(ab5500_address_file);
+exit_destroy_bank:
+	debugfs_remove(ab5500_bank_file);
+exit_destroy_reg:
+	debugfs_remove(ab5500_reg_file);
+exit_destroy_dir:
+	debugfs_remove(ab5500_dir);
+exit_no_debugfs:
+	dev_err(ab->dev, "failed to create debugfs entries.\n");
+	return;
+}
+
+void __exit ab5500_remove_debugfs(void)
+{
+	debugfs_remove(ab5500_val_file);
+	debugfs_remove(ab5500_address_file);
+	debugfs_remove(ab5500_bank_file);
+	debugfs_remove(ab5500_reg_file);
+	debugfs_remove(ab5500_dir);
+}
diff -druN linux-libre-3.1-gnu/drivers/mfd/ab5500-debugfs.h linux-libre-3.2-gnu/drivers/mfd/ab5500-debugfs.h
--- linux-libre-3.1-gnu/drivers/mfd/ab5500-debugfs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/mfd/ab5500-debugfs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2011 ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ * Debugfs interface to the AB5500 core driver
+ */
+
+#ifdef CONFIG_DEBUG_FS
+
+void ab5500_setup_debugfs(struct ab5500 *ab);
+void ab5500_remove_debugfs(void);
+
+#else /* !CONFIG_DEBUG_FS */
+
+static inline void ab5500_setup_debugfs(struct ab5500 *ab)
+{
+}
+
+static inline void ab5500_remove_debugfs(void)
+{
+}
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/mfd/ab8500-core.c linux-libre-3.2-gnu/drivers/mfd/ab8500-core.c
--- linux-libre-3.1-gnu/drivers/mfd/ab8500-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/ab8500-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -92,6 +92,8 @@
 #define AB8500_REV_REG			0x80
 #define AB8500_SWITCH_OFF_STATUS	0x00
 
+#define AB8500_TURN_ON_STATUS		0x00
+
 /*
  * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
  * numbers are indexed into this array with (num / 8).
@@ -293,6 +295,7 @@
 	.irq_bus_lock		= ab8500_irq_lock,
 	.irq_bus_sync_unlock	= ab8500_irq_sync_unlock,
 	.irq_mask		= ab8500_irq_mask,
+	.irq_disable		= ab8500_irq_mask,
 	.irq_unmask		= ab8500_irq_unmask,
 };
 
@@ -617,6 +620,7 @@
 
 static struct resource __devinitdata ab8500_chargalg_resources[] = {};
 
+#ifdef CONFIG_DEBUG_FS
 static struct resource __devinitdata ab8500_debug_resources[] = {
 	{
 		.name	= "IRQ_FIRST",
@@ -631,6 +635,7 @@
 		.flags	= IORESOURCE_IRQ,
 	},
 };
+#endif
 
 static struct resource __devinitdata ab8500_usb_resources[] = {
 	{
@@ -811,12 +816,40 @@
 	return sprintf(buf, "%#x\n", value);
 }
 
+/*
+ * ab8500 has turned on due to (TURN_ON_STATUS):
+ * 0x01 PORnVbat
+ * 0x02 PonKey1dbF
+ * 0x04 PonKey2dbF
+ * 0x08 RTCAlarm
+ * 0x10 MainChDet
+ * 0x20 VbusDet
+ * 0x40 UsbIDDetect
+ * 0x80 Reserved
+ */
+static ssize_t show_turn_on_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_SYS_CTRL1_BLOCK,
+		AB8500_TURN_ON_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 DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
 
 static struct attribute *ab8500_sysfs_entries[] = {
 	&dev_attr_chip_id.attr,
 	&dev_attr_switch_off_status.attr,
+	&dev_attr_turn_on_status.attr,
 	NULL,
 };
 
@@ -843,11 +876,11 @@
 		return ret;
 
 	switch (value) {
-	case AB8500_CUTEARLY:
 	case AB8500_CUT1P0:
 	case AB8500_CUT1P1:
 	case AB8500_CUT2P0:
 	case AB8500_CUT3P0:
+	case AB8500_CUT3P3:
 		dev_info(ab8500->dev, "detected chip, revision: %#x\n", value);
 		break;
 	default:
diff -druN linux-libre-3.1-gnu/drivers/mfd/ab8500-debugfs.c linux-libre-3.2-gnu/drivers/mfd/ab8500-debugfs.c
--- linux-libre-3.1-gnu/drivers/mfd/ab8500-debugfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/ab8500-debugfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
 #include <linux/fs.h>
+#include <linux/module.h>
 #include <linux/debugfs.h>
 #include <linux/platform_device.h>
 
diff -druN linux-libre-3.1-gnu/drivers/mfd/ab8500-gpadc.c linux-libre-3.2-gnu/drivers/mfd/ab8500-gpadc.c
--- linux-libre-3.1-gnu/drivers/mfd/ab8500-gpadc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/ab8500-gpadc.c	2012-01-04 18:55:44.000000000 -0500
@@ -143,12 +143,15 @@
 }
 EXPORT_SYMBOL(ab8500_gpadc_get);
 
-static int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 input,
+/**
+ * ab8500_gpadc_ad_to_voltage() - Convert a raw ADC value to a voltage
+ */
+int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel,
 	int ad_value)
 {
 	int res;
 
-	switch (input) {
+	switch (channel) {
 	case MAIN_CHARGER_V:
 		/* For some reason we don't have calibrated data */
 		if (!gpadc->cal_data[ADC_INPUT_VMAIN].gain) {
@@ -232,18 +235,46 @@
 	}
 	return res;
 }
+EXPORT_SYMBOL(ab8500_gpadc_ad_to_voltage);
 
 /**
  * ab8500_gpadc_convert() - gpadc conversion
- * @input:	analog input to be converted to digital data
+ * @channel:	analog channel 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 ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 channel)
+{
+	int ad_value;
+	int voltage;
+
+	ad_value = ab8500_gpadc_read_raw(gpadc, channel);
+	if (ad_value < 0) {
+		dev_err(gpadc->dev, "GPADC raw value failed ch: %d\n", channel);
+		return ad_value;
+	}
+
+	voltage = ab8500_gpadc_ad_to_voltage(gpadc, channel, ad_value);
+
+	if (voltage < 0)
+		dev_err(gpadc->dev, "GPADC to voltage conversion failed ch:"
+			" %d AD: 0x%x\n", channel, ad_value);
+
+	return voltage;
+}
+EXPORT_SYMBOL(ab8500_gpadc_convert);
+
+/**
+ * ab8500_gpadc_read_raw() - gpadc read
+ * @channel:	analog channel to be read
+ *
+ * This function obtains the raw ADC value, this then needs
+ * to be converted by calling ab8500_gpadc_ad_to_voltage()
+ */
+int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel)
 {
 	int ret;
-	u16 data = 0;
 	int looplimit = 0;
 	u8 val, low_data, high_data;
 
@@ -278,9 +309,9 @@
 		goto out;
 	}
 
-	/* Select the input source and set average samples to 16 */
+	/* Select the channel source and set average samples to 16 */
 	ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
-		AB8500_GPADC_CTRL2_REG, (input | SW_AVG_16));
+		AB8500_GPADC_CTRL2_REG, (channel | SW_AVG_16));
 	if (ret < 0) {
 		dev_err(gpadc->dev,
 			"gpadc_conversion: set avg samples failed\n");
@@ -292,7 +323,7 @@
 	 * charging current sense if it needed, ABB 3.0 needs some special
 	 * treatment too.
 	 */
-	switch (input) {
+	switch (channel) {
 	case MAIN_CHARGER_C:
 	case USB_CHARGER_C:
 		ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
@@ -359,7 +390,6 @@
 		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);
@@ -370,8 +400,8 @@
 	/* 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;
+
+	return (high_data << 8) | low_data;
 
 out:
 	/*
@@ -385,10 +415,10 @@
 	regulator_disable(gpadc->regu);
 	mutex_unlock(&gpadc->ab8500_gpadc_lock);
 	dev_err(gpadc->dev,
-		"gpadc_conversion: Failed to AD convert channel %d\n", input);
+		"gpadc_conversion: Failed to AD convert channel %d\n", channel);
 	return ret;
 }
-EXPORT_SYMBOL(ab8500_gpadc_convert);
+EXPORT_SYMBOL(ab8500_gpadc_read_raw);
 
 /**
  * ab8500_bm_gpswadcconvend_handler() - isr for s/w gpadc conversion completion
diff -druN linux-libre-3.1-gnu/drivers/mfd/ab8500-sysctrl.c linux-libre-3.2-gnu/drivers/mfd/ab8500-sysctrl.c
--- linux-libre-3.1-gnu/drivers/mfd/ab8500-sysctrl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/ab8500-sysctrl.c	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,7 @@
  */
 
 #include <linux/err.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/ab8500.h>
 #include <linux/mfd/abx500.h>
diff -druN linux-libre-3.1-gnu/drivers/mfd/abx500-core.c linux-libre-3.2-gnu/drivers/mfd/abx500-core.c
--- linux-libre-3.1-gnu/drivers/mfd/abx500-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/abx500-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/err.h>
+#include <linux/module.h>
 #include <linux/mfd/abx500.h>
 
 static LIST_HEAD(abx500_list);
diff -druN linux-libre-3.1-gnu/drivers/mfd/adp5520.c linux-libre-3.2-gnu/drivers/mfd/adp5520.c
--- linux-libre-3.1-gnu/drivers/mfd/adp5520.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/adp5520.c	2012-01-04 18:55:44.000000000 -0500
@@ -109,7 +109,7 @@
 
 	ret = __adp5520_read(chip->client, reg, &reg_val);
 
-	if (!ret && ((reg_val & bit_mask) == 0)) {
+	if (!ret && ((reg_val & bit_mask) != bit_mask)) {
 		reg_val |= bit_mask;
 		ret = __adp5520_write(chip->client, reg, reg_val);
 	}
diff -druN linux-libre-3.1-gnu/drivers/mfd/asic3.c linux-libre-3.2-gnu/drivers/mfd/asic3.c
--- linux-libre-3.1-gnu/drivers/mfd/asic3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/asic3.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
+#include <linux/export.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
@@ -584,7 +585,7 @@
 	return gpiochip_remove(&asic->gpio);
 }
 
-static int asic3_clk_enable(struct asic3 *asic, struct asic3_clk *clk)
+static void asic3_clk_enable(struct asic3 *asic, struct asic3_clk *clk)
 {
 	unsigned long flags;
 	u32 cdex;
@@ -596,8 +597,6 @@
 		asic3_write_register(asic, ASIC3_OFFSET(CLOCK, CDEX), cdex);
 	}
 	spin_unlock_irqrestore(&asic->lock, flags);
-
-	return 0;
 }
 
 static void asic3_clk_disable(struct asic3 *asic, struct asic3_clk *clk)
@@ -779,6 +778,8 @@
 	.name          = "tmio-mmc",
 	.enable        = asic3_mmc_enable,
 	.disable       = asic3_mmc_disable,
+	.suspend       = asic3_mmc_disable,
+	.resume        = asic3_mmc_enable,
 	.platform_data = &asic3_mmc_data,
 	.pdata_size    = sizeof(asic3_mmc_data),
 	.num_resources = ARRAY_SIZE(asic3_mmc_resources),
@@ -811,24 +812,43 @@
 	return 0;
 }
 
+static int asic3_leds_suspend(struct platform_device *pdev)
+{
+	const struct mfd_cell *cell = mfd_get_cell(pdev);
+	struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
+
+	while (asic3_gpio_get(&asic->gpio, ASIC3_GPIO(C, cell->id)) != 0)
+		msleep(1);
+
+	asic3_clk_disable(asic, &asic->clocks[clock_ledn[cell->id]]);
+
+	return 0;
+}
+
 static struct mfd_cell asic3_cell_leds[ASIC3_NUM_LEDS] = {
 	[0] = {
 		.name          = "leds-asic3",
 		.id            = 0,
 		.enable        = asic3_leds_enable,
 		.disable       = asic3_leds_disable,
+		.suspend       = asic3_leds_suspend,
+		.resume        = asic3_leds_enable,
 	},
 	[1] = {
 		.name          = "leds-asic3",
 		.id            = 1,
 		.enable        = asic3_leds_enable,
 		.disable       = asic3_leds_disable,
+		.suspend       = asic3_leds_suspend,
+		.resume        = asic3_leds_enable,
 	},
 	[2] = {
 		.name          = "leds-asic3",
 		.id            = 2,
 		.enable        = asic3_leds_enable,
 		.disable       = asic3_leds_disable,
+		.suspend       = asic3_leds_suspend,
+		.resume        = asic3_leds_enable,
 	},
 };
 
@@ -949,6 +969,7 @@
 		goto out_unmap;
 	}
 
+	asic->gpio.label = "asic3";
 	asic->gpio.base = pdata->gpio_base;
 	asic->gpio.ngpio = ASIC3_NUM_GPIOS;
 	asic->gpio.get = asic3_gpio_get;
diff -druN linux-libre-3.1-gnu/drivers/mfd/da903x.c linux-libre-3.2-gnu/drivers/mfd/da903x.c
--- linux-libre-3.1-gnu/drivers/mfd/da903x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/da903x.c	2012-01-04 18:55:44.000000000 -0500
@@ -182,7 +182,7 @@
 	if (ret)
 		goto out;
 
-	if ((reg_val & bit_mask) == 0) {
+	if ((reg_val & bit_mask) != bit_mask) {
 		reg_val |= bit_mask;
 		ret = __da903x_write(chip->client, reg, reg_val);
 	}
@@ -523,7 +523,7 @@
 	chip->ops->read_events(chip, &tmp);
 
 	ret = request_irq(client->irq, da903x_irq_handler,
-			IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+			IRQF_TRIGGER_FALLING,
 			"da903x", chip);
 	if (ret) {
 		dev_err(&client->dev, "failed to request irq %d\n",
@@ -549,6 +549,7 @@
 	struct da903x_chip *chip = i2c_get_clientdata(client);
 
 	da903x_remove_subdevs(chip);
+	free_irq(client->irq, chip);
 	kfree(chip);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/mfd/db5500-prcmu.c linux-libre-3.2-gnu/drivers/mfd/db5500-prcmu.c
--- linux-libre-3.1-gnu/drivers/mfd/db5500-prcmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/db5500-prcmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,11 +20,11 @@
 #include <linux/jiffies.h>
 #include <linux/bitops.h>
 #include <linux/interrupt.h>
-#include <linux/mfd/db5500-prcmu.h>
+#include <linux/mfd/dbx500-prcmu.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/db5500-regs.h>
-#include "db5500-prcmu-regs.h"
+#include "dbx500-prcmu-regs.h"
 
 #define _PRCM_MB_HEADER (tcdm_base + 0xFE8)
 #define PRCM_REQ_MB0_HEADER (_PRCM_MB_HEADER + 0x0)
@@ -109,15 +109,18 @@
 #define PRCMU_DSI_CLOCK_SETTING			0x00000128
 /* TVCLK_MGT PLLSW=001 (PLLSOC0) PLLDIV=0x13, = 19.05 MHZ */
 #define PRCMU_DSI_LP_CLOCK_SETTING		0x00000135
-#define PRCMU_PLLDSI_FREQ_SETTING		0x0004013C
+#define PRCMU_PLLDSI_FREQ_SETTING		0x00020121
 #define PRCMU_DSI_PLLOUT_SEL_SETTING		0x00000002
-#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV		0x03000101
+#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV		0x03000201
 #define PRCMU_DISABLE_ESCAPE_CLOCK_DIV		0x00000101
 
 #define PRCMU_ENABLE_PLLDSI			0x00000001
 #define PRCMU_DISABLE_PLLDSI			0x00000000
 
 #define PRCMU_DSI_RESET_SW			0x00000003
+#define PRCMU_RESOUTN0_PIN			0x00000001
+#define PRCMU_RESOUTN1_PIN			0x00000002
+#define PRCMU_RESOUTN2_PIN			0x00000004
 
 #define PRCMU_PLLDSI_LOCKP_LOCKED		0x3
 
@@ -315,31 +318,31 @@
 		r = false;
 		break;
 	}
-	writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR);
+	writel(MBOX_BIT(0), PRCM_ARM_IT1_CLR);
 	return r;
 }
 
 static bool read_mailbox_1(void)
 {
-	writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR);
+	writel(MBOX_BIT(1), PRCM_ARM_IT1_CLR);
 	return false;
 }
 
 static bool read_mailbox_2(void)
 {
-	writel(MBOX_BIT(2), PRCM_ARM_IT1_CLEAR);
+	writel(MBOX_BIT(2), PRCM_ARM_IT1_CLR);
 	return false;
 }
 
 static bool read_mailbox_3(void)
 {
-	writel(MBOX_BIT(3), PRCM_ARM_IT1_CLEAR);
+	writel(MBOX_BIT(3), PRCM_ARM_IT1_CLR);
 	return false;
 }
 
 static bool read_mailbox_4(void)
 {
-	writel(MBOX_BIT(4), PRCM_ARM_IT1_CLEAR);
+	writel(MBOX_BIT(4), PRCM_ARM_IT1_CLR);
 	return false;
 }
 
@@ -360,19 +363,19 @@
 		print_unknown_header_warning(5, header);
 		break;
 	}
-	writel(MBOX_BIT(5), PRCM_ARM_IT1_CLEAR);
+	writel(MBOX_BIT(5), PRCM_ARM_IT1_CLR);
 	return false;
 }
 
 static bool read_mailbox_6(void)
 {
-	writel(MBOX_BIT(6), PRCM_ARM_IT1_CLEAR);
+	writel(MBOX_BIT(6), PRCM_ARM_IT1_CLR);
 	return false;
 }
 
 static bool read_mailbox_7(void)
 {
-	writel(MBOX_BIT(7), PRCM_ARM_IT1_CLEAR);
+	writel(MBOX_BIT(7), PRCM_ARM_IT1_CLR);
 	return false;
 }
 
@@ -434,7 +437,7 @@
 		return -ENODEV;
 
 	/* Clean up the mailbox interrupts after pre-kernel code. */
-	writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLEAR);
+	writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
 
 	r = request_threaded_irq(IRQ_DB5500_PRCMU1, prcmu_irq_handler,
 		prcmu_irq_thread_fn, 0, "prcmu", NULL);
diff -druN linux-libre-3.1-gnu/drivers/mfd/db5500-prcmu-regs.h linux-libre-3.2-gnu/drivers/mfd/db5500-prcmu-regs.h
--- linux-libre-3.1-gnu/drivers/mfd/db5500-prcmu-regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/db5500-prcmu-regs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics 2009
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
- * Author: Sundar Iyer <sundar.iyer@stericsson.com>
- *
- * License Terms: GNU General Public License v2
- *
- * PRCM Unit registers
- */
-
-#ifndef __MACH_PRCMU_REGS_H
-#define __MACH_PRCMU_REGS_H
-
-#include <mach/hardware.h>
-
-#define PRCM_ARM_PLLDIVPS	(_PRCMU_BASE + 0x118)
-#define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE		0x3f
-#define PRCM_ARM_PLLDIVPS_MAX_MASK		0xf
-
-#define PRCM_PLLARM_LOCKP       (_PRCMU_BASE + 0x0a8)
-#define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3	0x2
-
-#define PRCM_ARM_CHGCLKREQ	(_PRCMU_BASE + 0x114)
-#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ	0x1
-
-#define PRCM_PLLARM_ENABLE	(_PRCMU_BASE + 0x98)
-#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE	0x1
-#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON	0x100
-
-#define PRCM_ARMCLKFIX_MGT	(_PRCMU_BASE + 0x0)
-#define PRCM_A9_RESETN_CLR	(_PRCMU_BASE + 0x1f4)
-#define PRCM_A9_RESETN_SET	(_PRCMU_BASE + 0x1f0)
-#define PRCM_ARM_LS_CLAMP	(_PRCMU_BASE + 0x30c)
-#define PRCM_SRAM_A9		(_PRCMU_BASE + 0x308)
-
-/* ARM WFI Standby signal register */
-#define PRCM_ARM_WFI_STANDBY    (_PRCMU_BASE + 0x130)
-#define PRCM_IOCR		(_PRCMU_BASE + 0x310)
-#define PRCM_IOCR_IOFORCE			0x1
-
-/* CPU mailbox registers */
-#define PRCM_MBOX_CPU_VAL	(_PRCMU_BASE + 0x0fc)
-#define PRCM_MBOX_CPU_SET	(_PRCMU_BASE + 0x100)
-#define PRCM_MBOX_CPU_CLR	(_PRCMU_BASE + 0x104)
-
-/* Dual A9 core interrupt management unit registers */
-#define PRCM_A9_MASK_REQ	(_PRCMU_BASE + 0x328)
-#define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ	0x1
-
-#define PRCM_A9_MASK_ACK	(_PRCMU_BASE + 0x32c)
-#define PRCM_ARMITMSK31TO0	(_PRCMU_BASE + 0x11c)
-#define PRCM_ARMITMSK63TO32	(_PRCMU_BASE + 0x120)
-#define PRCM_ARMITMSK95TO64	(_PRCMU_BASE + 0x124)
-#define PRCM_ARMITMSK127TO96	(_PRCMU_BASE + 0x128)
-#define PRCM_POWER_STATE_VAL	(_PRCMU_BASE + 0x25C)
-#define PRCM_ARMITVAL31TO0	(_PRCMU_BASE + 0x260)
-#define PRCM_ARMITVAL63TO32	(_PRCMU_BASE + 0x264)
-#define PRCM_ARMITVAL95TO64	(_PRCMU_BASE + 0x268)
-#define PRCM_ARMITVAL127TO96	(_PRCMU_BASE + 0x26C)
-
-#define PRCM_HOSTACCESS_REQ	(_PRCMU_BASE + 0x334)
-#define ARM_WAKEUP_MODEM	0x1
-
-#define PRCM_ARM_IT1_CLEAR	(_PRCMU_BASE + 0x48C)
-#define PRCM_ARM_IT1_VAL	(_PRCMU_BASE + 0x494)
-#define PRCM_HOLD_EVT		(_PRCMU_BASE + 0x174)
-
-#define PRCM_ITSTATUS0		(_PRCMU_BASE + 0x148)
-#define PRCM_ITSTATUS1		(_PRCMU_BASE + 0x150)
-#define PRCM_ITSTATUS2		(_PRCMU_BASE + 0x158)
-#define PRCM_ITSTATUS3		(_PRCMU_BASE + 0x160)
-#define PRCM_ITSTATUS4		(_PRCMU_BASE + 0x168)
-#define PRCM_ITSTATUS5		(_PRCMU_BASE + 0x484)
-#define PRCM_ITCLEAR5		(_PRCMU_BASE + 0x488)
-#define PRCM_ARMIT_MASKXP70_IT	(_PRCMU_BASE + 0x1018)
-
-/* System reset register */
-#define PRCM_APE_SOFTRST	(_PRCMU_BASE + 0x228)
-
-/* Level shifter and clamp control registers */
-#define PRCM_MMIP_LS_CLAMP_SET     (_PRCMU_BASE + 0x420)
-#define PRCM_MMIP_LS_CLAMP_CLR     (_PRCMU_BASE + 0x424)
-
-/* PRCMU clock/PLL/reset registers */
-#define PRCM_PLLDSI_FREQ           (_PRCMU_BASE + 0x500)
-#define PRCM_PLLDSI_ENABLE         (_PRCMU_BASE + 0x504)
-#define PRCM_PLLDSI_LOCKP          (_PRCMU_BASE + 0x508)
-#define PRCM_LCDCLK_MGT            (_PRCMU_BASE + 0x044)
-#define PRCM_MCDECLK_MGT           (_PRCMU_BASE + 0x064)
-#define PRCM_HDMICLK_MGT           (_PRCMU_BASE + 0x058)
-#define PRCM_TVCLK_MGT             (_PRCMU_BASE + 0x07c)
-#define PRCM_DSI_PLLOUT_SEL        (_PRCMU_BASE + 0x530)
-#define PRCM_DSITVCLK_DIV          (_PRCMU_BASE + 0x52C)
-#define PRCM_PLLDSI_LOCKP          (_PRCMU_BASE + 0x508)
-#define PRCM_APE_RESETN_SET        (_PRCMU_BASE + 0x1E4)
-#define PRCM_APE_RESETN_CLR        (_PRCMU_BASE + 0x1E8)
-#define PRCM_CLKOCR		   (_PRCMU_BASE + 0x1CC)
-
-/* ePOD and memory power signal control registers */
-#define PRCM_EPOD_C_SET            (_PRCMU_BASE + 0x410)
-#define PRCM_SRAM_LS_SLEEP         (_PRCMU_BASE + 0x304)
-
-/* Debug power control unit registers */
-#define PRCM_POWER_STATE_SET       (_PRCMU_BASE + 0x254)
-
-/* Miscellaneous unit registers */
-#define PRCM_DSI_SW_RESET          (_PRCMU_BASE + 0x324)
-#define PRCM_GPIOCR                (_PRCMU_BASE + 0x138)
-#define PRCM_GPIOCR_DBG_STM_MOD_CMD1            0x800
-#define PRCM_GPIOCR_DBG_UARTMOD_CMD0            0x1
-
-
-#endif /* __MACH_PRCMU__REGS_H */
diff -druN linux-libre-3.1-gnu/drivers/mfd/db8500-prcmu.c linux-libre-3.2-gnu/drivers/mfd/db8500-prcmu.c
--- linux-libre-3.1-gnu/drivers/mfd/db8500-prcmu.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/db8500-prcmu.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,14 +27,14 @@
 #include <linux/platform_device.h>
 #include <linux/uaccess.h>
 #include <linux/mfd/core.h>
-#include <linux/mfd/db8500-prcmu.h>
+#include <linux/mfd/dbx500-prcmu.h>
 #include <linux/regulator/db8500-prcmu.h>
 #include <linux/regulator/machine.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/db8500-regs.h>
 #include <mach/id.h>
-#include "db8500-prcmu-regs.h"
+#include "dbx500-prcmu-regs.h"
 
 /* Offset for the firmware version within the TCPM */
 #define PRCMU_FW_VERSION_OFFSET 0xA4
@@ -131,12 +131,14 @@
 #define MB1H_REQUEST_APE_OPP_100_VOLT 0x3
 #define MB1H_RELEASE_APE_OPP_100_VOLT 0x4
 #define MB1H_RELEASE_USB_WAKEUP 0x5
+#define MB1H_PLL_ON_OFF 0x6
 
 /* Mailbox 1 Requests */
 #define PRCM_REQ_MB1_ARM_OPP			(PRCM_REQ_MB1 + 0x0)
 #define PRCM_REQ_MB1_APE_OPP			(PRCM_REQ_MB1 + 0x1)
-#define PRCM_REQ_MB1_APE_OPP_100_RESTORE	(PRCM_REQ_MB1 + 0x4)
-#define PRCM_REQ_MB1_ARM_OPP_100_RESTORE	(PRCM_REQ_MB1 + 0x8)
+#define PRCM_REQ_MB1_PLL_ON_OFF			(PRCM_REQ_MB1 + 0x4)
+#define PLL_SOC1_OFF	0x4
+#define PLL_SOC1_ON	0x8
 
 /* Mailbox 1 ACKs */
 #define PRCM_ACK_MB1_CURRENT_ARM_OPP	(PRCM_ACK_MB1 + 0x0)
@@ -184,6 +186,11 @@
 #define MB4H_HOTDOG	0x12
 #define MB4H_HOTMON	0x13
 #define MB4H_HOT_PERIOD	0x14
+#define MB4H_A9WDOG_CONF 0x16
+#define MB4H_A9WDOG_EN   0x17
+#define MB4H_A9WDOG_DIS  0x18
+#define MB4H_A9WDOG_LOAD 0x19
+#define MB4H_A9WDOG_KICK 0x20
 
 /* Mailbox 4 Requests */
 #define PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE	(PRCM_REQ_MB4 + 0x0)
@@ -196,6 +203,13 @@
 #define PRCM_REQ_MB4_HOT_PERIOD			(PRCM_REQ_MB4 + 0x0)
 #define HOTMON_CONFIG_LOW			BIT(0)
 #define HOTMON_CONFIG_HIGH			BIT(1)
+#define PRCM_REQ_MB4_A9WDOG_0			(PRCM_REQ_MB4 + 0x0)
+#define PRCM_REQ_MB4_A9WDOG_1			(PRCM_REQ_MB4 + 0x1)
+#define PRCM_REQ_MB4_A9WDOG_2			(PRCM_REQ_MB4 + 0x2)
+#define PRCM_REQ_MB4_A9WDOG_3			(PRCM_REQ_MB4 + 0x3)
+#define A9WDOG_AUTO_OFF_EN			BIT(7)
+#define A9WDOG_AUTO_OFF_DIS			0
+#define A9WDOG_ID_MASK				0xf
 
 /* Mailbox 5 Requests */
 #define PRCM_REQ_MB5_I2C_SLAVE_OP	(PRCM_REQ_MB5 + 0x0)
@@ -412,7 +426,7 @@
 
 static DEFINE_SPINLOCK(clk_mgt_lock);
 
-#define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT), 0 }
+#define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT_OFF), 0 }
 struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = {
 	CLK_MGT_ENTRY(SGACLK),
 	CLK_MGT_ENTRY(UARTCLK),
@@ -445,6 +459,35 @@
 	CLK_MGT_ENTRY(UICCCLK),
 };
 
+static struct regulator *hwacc_regulator[NUM_HW_ACC];
+static struct regulator *hwacc_ret_regulator[NUM_HW_ACC];
+
+static bool hwacc_enabled[NUM_HW_ACC];
+static bool hwacc_ret_enabled[NUM_HW_ACC];
+
+static const char *hwacc_regulator_name[NUM_HW_ACC] = {
+	[HW_ACC_SVAMMDSP]	= "hwacc-sva-mmdsp",
+	[HW_ACC_SVAPIPE]	= "hwacc-sva-pipe",
+	[HW_ACC_SIAMMDSP]	= "hwacc-sia-mmdsp",
+	[HW_ACC_SIAPIPE]	= "hwacc-sia-pipe",
+	[HW_ACC_SGA]		= "hwacc-sga",
+	[HW_ACC_B2R2]		= "hwacc-b2r2",
+	[HW_ACC_MCDE]		= "hwacc-mcde",
+	[HW_ACC_ESRAM1]		= "hwacc-esram1",
+	[HW_ACC_ESRAM2]		= "hwacc-esram2",
+	[HW_ACC_ESRAM3]		= "hwacc-esram3",
+	[HW_ACC_ESRAM4]		= "hwacc-esram4",
+};
+
+static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = {
+	[HW_ACC_SVAMMDSP]	= "hwacc-sva-mmdsp-ret",
+	[HW_ACC_SIAMMDSP]	= "hwacc-sia-mmdsp-ret",
+	[HW_ACC_ESRAM1]		= "hwacc-esram1-ret",
+	[HW_ACC_ESRAM2]		= "hwacc-esram2-ret",
+	[HW_ACC_ESRAM3]		= "hwacc-esram3-ret",
+	[HW_ACC_ESRAM4]		= "hwacc-esram4-ret",
+};
+
 /*
 * Used by MCDE to setup all necessary PRCMU registers
 */
@@ -493,55 +536,51 @@
 } prcmu_version;
 
 
-int prcmu_enable_dsipll(void)
+int db8500_prcmu_enable_dsipll(void)
 {
 	int i;
 	unsigned int plldsifreq;
 
 	/* Clear DSIPLL_RESETN */
-	writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_CLR));
+	writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR);
 	/* Unclamp DSIPLL in/out */
-	writel(PRCMU_UNCLAMP_DSIPLL, (_PRCMU_BASE + PRCM_MMIP_LS_CLAMP_CLR));
+	writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR);
 
 	if (prcmu_is_u8400())
 		plldsifreq = PRCMU_PLLDSI_FREQ_SETTING_U8400;
 	else
 		plldsifreq = PRCMU_PLLDSI_FREQ_SETTING;
 	/* Set DSI PLL FREQ */
-	writel(plldsifreq, (_PRCMU_BASE + PRCM_PLLDSI_FREQ));
-	writel(PRCMU_DSI_PLLOUT_SEL_SETTING,
-		(_PRCMU_BASE + PRCM_DSI_PLLOUT_SEL));
+	writel(plldsifreq, PRCM_PLLDSI_FREQ);
+	writel(PRCMU_DSI_PLLOUT_SEL_SETTING, PRCM_DSI_PLLOUT_SEL);
 	/* Enable Escape clocks */
-	writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV,
-					(_PRCMU_BASE + PRCM_DSITVCLK_DIV));
+	writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV);
 
 	/* Start DSI PLL */
-	writel(PRCMU_ENABLE_PLLDSI, (_PRCMU_BASE + PRCM_PLLDSI_ENABLE));
+	writel(PRCMU_ENABLE_PLLDSI, PRCM_PLLDSI_ENABLE);
 	/* Reset DSI PLL */
-	writel(PRCMU_DSI_RESET_SW, (_PRCMU_BASE + PRCM_DSI_SW_RESET));
+	writel(PRCMU_DSI_RESET_SW, PRCM_DSI_SW_RESET);
 	for (i = 0; i < 10; i++) {
-		if ((readl(_PRCMU_BASE + PRCM_PLLDSI_LOCKP) &
-			PRCMU_PLLDSI_LOCKP_LOCKED)
+		if ((readl(PRCM_PLLDSI_LOCKP) & PRCMU_PLLDSI_LOCKP_LOCKED)
 					== PRCMU_PLLDSI_LOCKP_LOCKED)
 			break;
 		udelay(100);
 	}
 	/* Set DSIPLL_RESETN */
-	writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_SET));
+	writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_SET);
 	return 0;
 }
 
-int prcmu_disable_dsipll(void)
+int db8500_prcmu_disable_dsipll(void)
 {
 	/* Disable dsi pll */
-	writel(PRCMU_DISABLE_PLLDSI, (_PRCMU_BASE + PRCM_PLLDSI_ENABLE));
+	writel(PRCMU_DISABLE_PLLDSI, PRCM_PLLDSI_ENABLE);
 	/* Disable  escapeclock */
-	writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV,
-					(_PRCMU_BASE + PRCM_DSITVCLK_DIV));
+	writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV);
 	return 0;
 }
 
-int prcmu_set_display_clocks(void)
+int db8500_prcmu_set_display_clocks(void)
 {
 	unsigned long flags;
 	unsigned int dsiclk;
@@ -554,15 +593,15 @@
 	spin_lock_irqsave(&clk_mgt_lock, flags);
 
 	/* Grab the HW semaphore. */
-	while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+	while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
 		cpu_relax();
 
-	writel(dsiclk, (_PRCMU_BASE + PRCM_HDMICLK_MGT));
-	writel(PRCMU_DSI_LP_CLOCK_SETTING, (_PRCMU_BASE + PRCM_TVCLK_MGT));
-	writel(PRCMU_DPI_CLOCK_SETTING, (_PRCMU_BASE + PRCM_LCDCLK_MGT));
+	writel(dsiclk, PRCM_HDMICLK_MGT);
+	writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT);
+	writel(PRCMU_DPI_CLOCK_SETTING, PRCM_LCDCLK_MGT);
 
 	/* Release the HW semaphore. */
-	writel(0, (_PRCMU_BASE + PRCM_SEM));
+	writel(0, PRCM_SEM);
 
 	spin_unlock_irqrestore(&clk_mgt_lock, flags);
 
@@ -578,8 +617,8 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&gpiocr_lock, flags);
-	reg = readl(_PRCMU_BASE + PRCM_GPIOCR);
-	writel(reg | PRCM_GPIOCR_SPI2_SELECT, _PRCMU_BASE + PRCM_GPIOCR);
+	reg = readl(PRCM_GPIOCR);
+	writel(reg | PRCM_GPIOCR_SPI2_SELECT, PRCM_GPIOCR);
 	spin_unlock_irqrestore(&gpiocr_lock, flags);
 }
 
@@ -592,8 +631,8 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&gpiocr_lock, flags);
-	reg = readl(_PRCMU_BASE + PRCM_GPIOCR);
-	writel(reg & ~PRCM_GPIOCR_SPI2_SELECT, _PRCMU_BASE + PRCM_GPIOCR);
+	reg = readl(PRCM_GPIOCR);
+	writel(reg & ~PRCM_GPIOCR_SPI2_SELECT, PRCM_GPIOCR);
 	spin_unlock_irqrestore(&gpiocr_lock, flags);
 }
 
@@ -701,7 +740,7 @@
 
 	spin_lock_irqsave(&clkout_lock, flags);
 
-	val = readl(_PRCMU_BASE + PRCM_CLKOCR);
+	val = readl(PRCM_CLKOCR);
 	if (val & div_mask) {
 		if (div) {
 			if ((val & mask) != bits) {
@@ -715,7 +754,7 @@
 			}
 		}
 	}
-	writel((bits | (val & ~mask)), (_PRCMU_BASE + PRCM_CLKOCR));
+	writel((bits | (val & ~mask)), PRCM_CLKOCR);
 	requests[clkout] += (div ? 1 : -1);
 
 unlock_and_return:
@@ -724,7 +763,7 @@
 	return r;
 }
 
-int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
+int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
 {
 	unsigned long flags;
 
@@ -732,7 +771,7 @@
 
 	spin_lock_irqsave(&mb0_transfer.lock, flags);
 
-	while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
 		cpu_relax();
 
 	writeb(MB0H_POWER_STATE_TRANS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0));
@@ -741,7 +780,7 @@
 	writeb((keep_ulp_clk ? 1 : 0),
 		(tcdm_base + PRCM_REQ_MB0_ULP_CLOCK_STATE));
 	writeb(0, (tcdm_base + PRCM_REQ_MB0_DO_NOT_WFI));
-	writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+	writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
 
 	spin_unlock_irqrestore(&mb0_transfer.lock, flags);
 
@@ -770,18 +809,18 @@
 		return;
 
 	for (i = 0; i < 2; i++) {
-		while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
+		while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
 			cpu_relax();
 		writel(dbb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_8500));
 		writel(abb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_4500));
 		writeb(header[i], (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0));
-		writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+		writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
 	}
 	last_dbb_events = dbb_events;
 	last_abb_events = abb_events;
 }
 
-void prcmu_enable_wakeups(u32 wakeups)
+void db8500_prcmu_enable_wakeups(u32 wakeups)
 {
 	unsigned long flags;
 	u32 bits;
@@ -802,7 +841,7 @@
 	spin_unlock_irqrestore(&mb0_transfer.lock, flags);
 }
 
-void prcmu_config_abb_event_readout(u32 abb_events)
+void db8500_prcmu_config_abb_event_readout(u32 abb_events)
 {
 	unsigned long flags;
 
@@ -814,7 +853,7 @@
 	spin_unlock_irqrestore(&mb0_transfer.lock, flags);
 }
 
-void prcmu_get_abb_event_buffer(void __iomem **buf)
+void db8500_prcmu_get_abb_event_buffer(void __iomem **buf)
 {
 	if (readb(tcdm_base + PRCM_ACK_MB0_READ_POINTER) & 1)
 		*buf = (tcdm_base + PRCM_ACK_MB0_WAKEUP_1_4500);
@@ -823,13 +862,13 @@
 }
 
 /**
- * prcmu_set_arm_opp - set the appropriate ARM OPP
+ * db8500_prcmu_set_arm_opp - set the appropriate ARM OPP
  * @opp: The new ARM operating point to which transition is to be made
  * Returns: 0 on success, non-zero on failure
  *
  * This function sets the the operating point of the ARM.
  */
-int prcmu_set_arm_opp(u8 opp)
+int db8500_prcmu_set_arm_opp(u8 opp)
 {
 	int r;
 
@@ -840,14 +879,14 @@
 
 	mutex_lock(&mb1_transfer.lock);
 
-	while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
 
 	writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
 	writeb(opp, (tcdm_base + PRCM_REQ_MB1_ARM_OPP));
 	writeb(APE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_APE_OPP));
 
-	writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb1_transfer.work);
 
 	if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) ||
@@ -860,11 +899,11 @@
 }
 
 /**
- * prcmu_get_arm_opp - get the current ARM OPP
+ * db8500_prcmu_get_arm_opp - get the current ARM OPP
  *
  * Returns: the current ARM OPP
  */
-int prcmu_get_arm_opp(void)
+int db8500_prcmu_get_arm_opp(void)
 {
 	return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_ARM_OPP);
 }
@@ -876,7 +915,7 @@
  */
 int prcmu_get_ddr_opp(void)
 {
-	return readb(_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW);
+	return readb(PRCM_DDR_SUBSYS_APE_MINBW);
 }
 
 /**
@@ -892,7 +931,7 @@
 		return -EINVAL;
 	/* Changing the DDR OPP can hang the hardware pre-v21 */
 	if (cpu_is_u8500v20_or_later() && !cpu_is_u8500v20())
-		writeb(opp, (_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW));
+		writeb(opp, PRCM_DDR_SUBSYS_APE_MINBW);
 
 	return 0;
 }
@@ -909,14 +948,14 @@
 
 	mutex_lock(&mb1_transfer.lock);
 
-	while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
 
 	writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
 	writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP));
 	writeb(opp, (tcdm_base + PRCM_REQ_MB1_APE_OPP));
 
-	writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb1_transfer.work);
 
 	if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) ||
@@ -966,12 +1005,12 @@
 		header = MB1H_RELEASE_APE_OPP_100_VOLT;
 	}
 
-	while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
 
 	writeb(header, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
 
-	writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb1_transfer.work);
 
 	if ((mb1_transfer.ack.header != header) ||
@@ -995,13 +1034,13 @@
 
 	mutex_lock(&mb1_transfer.lock);
 
-	while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
 
 	writeb(MB1H_RELEASE_USB_WAKEUP,
 		(tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
 
-	writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb1_transfer.work);
 
 	if ((mb1_transfer.ack.header != MB1H_RELEASE_USB_WAKEUP) ||
@@ -1013,15 +1052,169 @@
 	return r;
 }
 
+static int request_pll(u8 clock, bool enable)
+{
+	int r = 0;
+
+	if (clock == PRCMU_PLLSOC1)
+		clock = (enable ? PLL_SOC1_ON : PLL_SOC1_OFF);
+	else
+		return -EINVAL;
+
+	mutex_lock(&mb1_transfer.lock);
+
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+		cpu_relax();
+
+	writeb(MB1H_PLL_ON_OFF, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
+	writeb(clock, (tcdm_base + PRCM_REQ_MB1_PLL_ON_OFF));
+
+	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
+	wait_for_completion(&mb1_transfer.work);
+
+	if (mb1_transfer.ack.header != MB1H_PLL_ON_OFF)
+		r = -EIO;
+
+	mutex_unlock(&mb1_transfer.lock);
+
+	return r;
+}
+
 /**
- * prcmu_set_epod - set the state of a EPOD (power domain)
+ * prcmu_set_hwacc - set the power state of a h/w accelerator
+ * @hwacc_dev: The hardware accelerator (enum hw_acc_dev).
+ * @state: The new power state (enum hw_acc_state).
+ *
+ * This function sets the power state of a hardware accelerator.
+ * This function should not be called from interrupt context.
+ *
+ * NOTE! Deprecated, to be removed when all users switched over to use the
+ * regulator framework API.
+ */
+int prcmu_set_hwacc(u16 hwacc_dev, u8 state)
+{
+	int r = 0;
+	bool ram_retention = false;
+	bool enable, enable_ret;
+
+	/* check argument */
+	BUG_ON(hwacc_dev >= NUM_HW_ACC);
+
+	/* get state of switches */
+	enable = hwacc_enabled[hwacc_dev];
+	enable_ret = hwacc_ret_enabled[hwacc_dev];
+
+	/* set flag if retention is possible */
+	switch (hwacc_dev) {
+	case HW_ACC_SVAMMDSP:
+	case HW_ACC_SIAMMDSP:
+	case HW_ACC_ESRAM1:
+	case HW_ACC_ESRAM2:
+	case HW_ACC_ESRAM3:
+	case HW_ACC_ESRAM4:
+		ram_retention = true;
+		break;
+	}
+
+	/* check argument */
+	BUG_ON(state > HW_ON);
+	BUG_ON(state == HW_OFF_RAMRET && !ram_retention);
+
+	/* modify enable flags */
+	switch (state) {
+	case HW_OFF:
+		enable_ret = false;
+		enable = false;
+		break;
+	case HW_ON:
+		enable = true;
+		break;
+	case HW_OFF_RAMRET:
+		enable_ret = true;
+		enable = false;
+		break;
+	}
+
+	/* get regulator (lazy) */
+	if (hwacc_regulator[hwacc_dev] == NULL) {
+		hwacc_regulator[hwacc_dev] = regulator_get(NULL,
+			hwacc_regulator_name[hwacc_dev]);
+		if (IS_ERR(hwacc_regulator[hwacc_dev])) {
+			pr_err("prcmu: failed to get supply %s\n",
+				hwacc_regulator_name[hwacc_dev]);
+			r = PTR_ERR(hwacc_regulator[hwacc_dev]);
+			goto out;
+		}
+	}
+
+	if (ram_retention) {
+		if (hwacc_ret_regulator[hwacc_dev] == NULL) {
+			hwacc_ret_regulator[hwacc_dev] = regulator_get(NULL,
+				hwacc_ret_regulator_name[hwacc_dev]);
+			if (IS_ERR(hwacc_ret_regulator[hwacc_dev])) {
+				pr_err("prcmu: failed to get supply %s\n",
+					hwacc_ret_regulator_name[hwacc_dev]);
+				r = PTR_ERR(hwacc_ret_regulator[hwacc_dev]);
+				goto out;
+			}
+		}
+	}
+
+	/* set regulators */
+	if (ram_retention) {
+		if (enable_ret && !hwacc_ret_enabled[hwacc_dev]) {
+			r = regulator_enable(hwacc_ret_regulator[hwacc_dev]);
+			if (r < 0) {
+				pr_err("prcmu_set_hwacc: ret enable failed\n");
+				goto out;
+			}
+			hwacc_ret_enabled[hwacc_dev] = true;
+		}
+	}
+
+	if (enable && !hwacc_enabled[hwacc_dev]) {
+		r = regulator_enable(hwacc_regulator[hwacc_dev]);
+		if (r < 0) {
+			pr_err("prcmu_set_hwacc: enable failed\n");
+			goto out;
+		}
+		hwacc_enabled[hwacc_dev] = true;
+	}
+
+	if (!enable && hwacc_enabled[hwacc_dev]) {
+		r = regulator_disable(hwacc_regulator[hwacc_dev]);
+		if (r < 0) {
+			pr_err("prcmu_set_hwacc: disable failed\n");
+			goto out;
+		}
+		hwacc_enabled[hwacc_dev] = false;
+	}
+
+	if (ram_retention) {
+		if (!enable_ret && hwacc_ret_enabled[hwacc_dev]) {
+			r = regulator_disable(hwacc_ret_regulator[hwacc_dev]);
+			if (r < 0) {
+				pr_err("prcmu_set_hwacc: ret disable failed\n");
+				goto out;
+			}
+			hwacc_ret_enabled[hwacc_dev] = false;
+		}
+	}
+
+out:
+	return r;
+}
+EXPORT_SYMBOL(prcmu_set_hwacc);
+
+/**
+ * db8500_prcmu_set_epod - set the state of a EPOD (power domain)
  * @epod_id: The EPOD to set
  * @epod_state: The new EPOD state
  *
  * This function sets the state of a EPOD (power domain). It may not be called
  * from interrupt context.
  */
-int prcmu_set_epod(u16 epod_id, u8 epod_state)
+int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
 {
 	int r = 0;
 	bool ram_retention = false;
@@ -1048,7 +1241,7 @@
 	mutex_lock(&mb2_transfer.lock);
 
 	/* wait for mailbox */
-	while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(2))
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(2))
 		cpu_relax();
 
 	/* fill in mailbox */
@@ -1058,7 +1251,7 @@
 
 	writeb(MB2H_DPS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB2));
 
-	writel(MBOX_BIT(2), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+	writel(MBOX_BIT(2), PRCM_MBOX_CPU_SET);
 
 	/*
 	 * The current firmware version does not handle errors correctly,
@@ -1145,13 +1338,13 @@
 
 	spin_lock_irqsave(&mb3_transfer.lock, flags);
 
-	while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(3))
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(3))
 		cpu_relax();
 
 	writeb((enable ? ON : OFF), (tcdm_base + PRCM_REQ_MB3_SYSCLK_MGT));
 
 	writeb(MB3H_SYSCLK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB3));
-	writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+	writel(MBOX_BIT(3), PRCM_MBOX_CPU_SET);
 
 	spin_unlock_irqrestore(&mb3_transfer.lock, flags);
 
@@ -1177,7 +1370,7 @@
 
 	if (!enable)
 		val |= PRCM_TCR_STOP_TIMERS;
-	writel(val, (_PRCMU_BASE + PRCM_TCR));
+	writel(val, PRCM_TCR);
 
 	return 0;
 }
@@ -1190,7 +1383,7 @@
 	spin_lock_irqsave(&clk_mgt_lock, flags);
 
 	/* Grab the HW semaphore. */
-	while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+	while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
 		cpu_relax();
 
 	val = readl(_PRCMU_BASE + clk_mgt[clock].offset);
@@ -1203,34 +1396,61 @@
 	writel(val, (_PRCMU_BASE + clk_mgt[clock].offset));
 
 	/* Release the HW semaphore. */
-	writel(0, (_PRCMU_BASE + PRCM_SEM));
+	writel(0, PRCM_SEM);
 
 	spin_unlock_irqrestore(&clk_mgt_lock, flags);
 
 	return 0;
 }
 
+static int request_sga_clock(u8 clock, bool enable)
+{
+	u32 val;
+	int ret;
+
+	if (enable) {
+		val = readl(PRCM_CGATING_BYPASS);
+		writel(val | PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS);
+	}
+
+	ret = request_reg_clock(clock, enable);
+
+	if (!ret && !enable) {
+		val = readl(PRCM_CGATING_BYPASS);
+		writel(val & ~PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS);
+	}
+
+	return ret;
+}
+
 /**
- * prcmu_request_clock() - Request for a clock to be enabled or disabled.
+ * db8500_prcmu_request_clock() - Request for a clock to be enabled or disabled.
  * @clock:      The clock for which the request is made.
  * @enable:     Whether the clock should be enabled (true) or disabled (false).
  *
  * This function should only be used by the clock implementation.
  * Do not use it from any other place!
  */
-int prcmu_request_clock(u8 clock, bool enable)
+int db8500_prcmu_request_clock(u8 clock, bool enable)
 {
-	if (clock < PRCMU_NUM_REG_CLOCKS)
-		return request_reg_clock(clock, enable);
-	else if (clock == PRCMU_TIMCLK)
+	switch(clock) {
+	case PRCMU_SGACLK:
+		return request_sga_clock(clock, enable);
+	case PRCMU_TIMCLK:
 		return request_timclk(enable);
-	else if (clock == PRCMU_SYSCLK)
+	case PRCMU_SYSCLK:
 		return request_sysclk(enable);
-	else
-		return -EINVAL;
+	case PRCMU_PLLSOC1:
+		return request_pll(clock, enable);
+	default:
+		break;
+	}
+	if (clock < PRCMU_NUM_REG_CLOCKS)
+		return request_reg_clock(clock, enable);
+	return -EINVAL;
 }
 
-int prcmu_config_esram0_deep_sleep(u8 state)
+int db8500_prcmu_config_esram0_deep_sleep(u8 state)
 {
 	if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) ||
 	    (state < ESRAM0_DEEP_SLEEP_STATE_OFF))
@@ -1238,7 +1458,7 @@
 
 	mutex_lock(&mb4_transfer.lock);
 
-	while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
 
 	writeb(MB4H_MEM_ST, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
@@ -1248,7 +1468,7 @@
 	       (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE));
 	writeb(state, (tcdm_base + PRCM_REQ_MB4_ESRAM0_ST));
 
-	writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb4_transfer.work);
 
 	mutex_unlock(&mb4_transfer.lock);
@@ -1260,13 +1480,13 @@
 {
 	mutex_lock(&mb4_transfer.lock);
 
-	while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
 
 	writeb(threshold, (tcdm_base + PRCM_REQ_MB4_HOTDOG_THRESHOLD));
 	writeb(MB4H_HOTDOG, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
 
-	writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb4_transfer.work);
 
 	mutex_unlock(&mb4_transfer.lock);
@@ -1278,7 +1498,7 @@
 {
 	mutex_lock(&mb4_transfer.lock);
 
-	while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
 
 	writeb(low, (tcdm_base + PRCM_REQ_MB4_HOTMON_LOW));
@@ -1287,7 +1507,7 @@
 		(tcdm_base + PRCM_REQ_MB4_HOTMON_CONFIG));
 	writeb(MB4H_HOTMON, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
 
-	writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb4_transfer.work);
 
 	mutex_unlock(&mb4_transfer.lock);
@@ -1299,13 +1519,13 @@
 {
 	mutex_lock(&mb4_transfer.lock);
 
-	while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
 
 	writew(val, (tcdm_base + PRCM_REQ_MB4_HOT_PERIOD));
 	writeb(MB4H_HOT_PERIOD, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
 
-	writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb4_transfer.work);
 
 	mutex_unlock(&mb4_transfer.lock);
@@ -1326,6 +1546,78 @@
 	return config_hot_period(0xFFFF);
 }
 
+static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3)
+{
+
+	mutex_lock(&mb4_transfer.lock);
+
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
+		cpu_relax();
+
+	writeb(d0, (tcdm_base + PRCM_REQ_MB4_A9WDOG_0));
+	writeb(d1, (tcdm_base + PRCM_REQ_MB4_A9WDOG_1));
+	writeb(d2, (tcdm_base + PRCM_REQ_MB4_A9WDOG_2));
+	writeb(d3, (tcdm_base + PRCM_REQ_MB4_A9WDOG_3));
+
+	writeb(cmd, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
+
+	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
+	wait_for_completion(&mb4_transfer.work);
+
+	mutex_unlock(&mb4_transfer.lock);
+
+	return 0;
+
+}
+
+int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
+{
+	BUG_ON(num == 0 || num > 0xf);
+	return prcmu_a9wdog(MB4H_A9WDOG_CONF, num, 0, 0,
+			    sleep_auto_off ? A9WDOG_AUTO_OFF_EN :
+			    A9WDOG_AUTO_OFF_DIS);
+}
+
+int prcmu_enable_a9wdog(u8 id)
+{
+	return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0);
+}
+
+int prcmu_disable_a9wdog(u8 id)
+{
+	return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0);
+}
+
+int prcmu_kick_a9wdog(u8 id)
+{
+	return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0);
+}
+
+/*
+ * timeout is 28 bit, in ms.
+ */
+#define MAX_WATCHDOG_TIMEOUT 131000
+int prcmu_load_a9wdog(u8 id, u32 timeout)
+{
+	if (timeout > MAX_WATCHDOG_TIMEOUT)
+		/*
+		 * Due to calculation bug in prcmu fw, timeouts
+		 * can't be bigger than 131 seconds.
+		 */
+		return -EINVAL;
+
+	return prcmu_a9wdog(MB4H_A9WDOG_LOAD,
+			    (id & A9WDOG_ID_MASK) |
+			    /*
+			     * Put the lowest 28 bits of timeout at
+			     * offset 4. Four first bits are used for id.
+			     */
+			    (u8)((timeout << 4) & 0xf0),
+			    (u8)((timeout >> 4) & 0xff),
+			    (u8)((timeout >> 12) & 0xff),
+			    (u8)((timeout >> 20) & 0xff));
+}
+
 /**
  * prcmu_set_clock_divider() - Configure the clock divider.
  * @clock:	The clock for which the request is made.
@@ -1345,7 +1637,7 @@
 	spin_lock_irqsave(&clk_mgt_lock, flags);
 
 	/* Grab the HW semaphore. */
-	while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+	while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
 		cpu_relax();
 
 	val = readl(_PRCMU_BASE + clk_mgt[clock].offset);
@@ -1354,7 +1646,7 @@
 	writel(val, (_PRCMU_BASE + clk_mgt[clock].offset));
 
 	/* Release the HW semaphore. */
-	writel(0, (_PRCMU_BASE + PRCM_SEM));
+	writel(0, PRCM_SEM);
 
 	spin_unlock_irqrestore(&clk_mgt_lock, flags);
 
@@ -1380,7 +1672,7 @@
 
 	mutex_lock(&mb5_transfer.lock);
 
-	while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
 		cpu_relax();
 
 	writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP));
@@ -1388,7 +1680,7 @@
 	writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG));
 	writeb(0, (tcdm_base + PRCM_REQ_MB5_I2C_VAL));
 
-	writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+	writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
 
 	if (!wait_for_completion_timeout(&mb5_transfer.work,
 				msecs_to_jiffies(20000))) {
@@ -1426,7 +1718,7 @@
 
 	mutex_lock(&mb5_transfer.lock);
 
-	while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
 		cpu_relax();
 
 	writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP));
@@ -1434,7 +1726,7 @@
 	writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG));
 	writeb(*value, (tcdm_base + PRCM_REQ_MB5_I2C_VAL));
 
-	writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+	writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
 
 	if (!wait_for_completion_timeout(&mb5_transfer.work,
 				msecs_to_jiffies(20000))) {
@@ -1456,21 +1748,44 @@
 void prcmu_ac_wake_req(void)
 {
 	u32 val;
+	u32 status;
 
 	mutex_lock(&mb0_transfer.ac_wake_lock);
 
-	val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ);
+	val = readl(PRCM_HOSTACCESS_REQ);
 	if (val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ)
 		goto unlock_and_return;
 
 	atomic_set(&ac_wake_req_state, 1);
 
-	writel((val | PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ),
-		(_PRCMU_BASE + PRCM_HOSTACCESS_REQ));
+retry:
+	writel((val | PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), PRCM_HOSTACCESS_REQ);
 
 	if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
-			msecs_to_jiffies(20000))) {
-		pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
+			msecs_to_jiffies(5000))) {
+		pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n",
+			__func__);
+		goto unlock_and_return;
+	}
+
+	/*
+	 * The modem can generate an AC_WAKE_ACK, and then still go to sleep.
+	 * As a workaround, we wait, and then check that the modem is indeed
+	 * awake (in terms of the value of the PRCM_MOD_AWAKE_STATUS
+	 * register, which may not be the whole truth).
+	 */
+	udelay(400);
+	status = (readl(PRCM_MOD_AWAKE_STATUS) & BITS(0, 2));
+	if (status != (PRCM_MOD_AWAKE_STATUS_PRCM_MOD_AAPD_AWAKE |
+			PRCM_MOD_AWAKE_STATUS_PRCM_MOD_COREPD_AWAKE)) {
+		pr_err("prcmu: %s received ack, but modem not awake (0x%X).\n",
+			__func__, status);
+		udelay(1200);
+		writel(val, PRCM_HOSTACCESS_REQ);
+		if (wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
+				msecs_to_jiffies(5000)))
+			goto retry;
+		pr_crit("prcmu: %s timed out (5 s) waiting for AC_SLEEP_ACK.\n",
 			__func__);
 	}
 
@@ -1487,16 +1802,16 @@
 
 	mutex_lock(&mb0_transfer.ac_wake_lock);
 
-	val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ);
+	val = readl(PRCM_HOSTACCESS_REQ);
 	if (!(val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ))
 		goto unlock_and_return;
 
 	writel((val & ~PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ),
-		(_PRCMU_BASE + PRCM_HOSTACCESS_REQ));
+		PRCM_HOSTACCESS_REQ);
 
 	if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
-			msecs_to_jiffies(20000))) {
-		pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
+			msecs_to_jiffies(5000))) {
+		pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n",
 			__func__);
 	}
 
@@ -1506,21 +1821,32 @@
 	mutex_unlock(&mb0_transfer.ac_wake_lock);
 }
 
-bool prcmu_is_ac_wake_requested(void)
+bool db8500_prcmu_is_ac_wake_requested(void)
 {
 	return (atomic_read(&ac_wake_req_state) != 0);
 }
 
 /**
- * prcmu_system_reset - System reset
+ * db8500_prcmu_system_reset - System reset
  *
- * Saves the reset reason code and then sets the APE_SOFRST register which
+ * Saves the reset reason code and then sets the APE_SOFTRST register which
  * fires interrupt to fw
  */
-void prcmu_system_reset(u16 reset_code)
+void db8500_prcmu_system_reset(u16 reset_code)
 {
 	writew(reset_code, (tcdm_base + PRCM_SW_RST_REASON));
-	writel(1, (_PRCMU_BASE + PRCM_APE_SOFTRST));
+	writel(1, PRCM_APE_SOFTRST);
+}
+
+/**
+ * db8500_prcmu_get_reset_code - Retrieve SW reset reason code
+ *
+ * Retrieves the reset reason code stored by prcmu_system_reset() before
+ * last restart.
+ */
+u16 db8500_prcmu_get_reset_code(void)
+{
+	return readw(tcdm_base + PRCM_SW_RST_REASON);
 }
 
 /**
@@ -1530,11 +1856,11 @@
 {
 	mutex_lock(&mb1_transfer.lock);
 
-	while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
 
 	writeb(MB1H_RESET_MODEM, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
-	writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb1_transfer.work);
 
 	/*
@@ -1551,11 +1877,11 @@
 
 	spin_lock_irqsave(&mb0_transfer.lock, flags);
 
-	while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
 		cpu_relax();
 
 	writeb(MB0H_READ_WAKEUP_ACK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0));
-	writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+	writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
 
 	spin_unlock_irqrestore(&mb0_transfer.lock, flags);
 }
@@ -1600,7 +1926,7 @@
 		r = false;
 		break;
 	}
-	writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+	writel(MBOX_BIT(0), PRCM_ARM_IT1_CLR);
 	return r;
 }
 
@@ -1613,7 +1939,7 @@
 		PRCM_ACK_MB1_CURRENT_APE_OPP);
 	mb1_transfer.ack.ape_voltage_status = readb(tcdm_base +
 		PRCM_ACK_MB1_APE_VOLTAGE_STATUS);
-	writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+	writel(MBOX_BIT(1), PRCM_ARM_IT1_CLR);
 	complete(&mb1_transfer.work);
 	return false;
 }
@@ -1621,14 +1947,14 @@
 static bool read_mailbox_2(void)
 {
 	mb2_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB2_DPS_STATUS);
-	writel(MBOX_BIT(2), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+	writel(MBOX_BIT(2), PRCM_ARM_IT1_CLR);
 	complete(&mb2_transfer.work);
 	return false;
 }
 
 static bool read_mailbox_3(void)
 {
-	writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+	writel(MBOX_BIT(3), PRCM_ARM_IT1_CLR);
 	return false;
 }
 
@@ -1643,6 +1969,11 @@
 	case MB4H_HOTDOG:
 	case MB4H_HOTMON:
 	case MB4H_HOT_PERIOD:
+	case MB4H_A9WDOG_CONF:
+	case MB4H_A9WDOG_EN:
+	case MB4H_A9WDOG_DIS:
+	case MB4H_A9WDOG_LOAD:
+	case MB4H_A9WDOG_KICK:
 		break;
 	default:
 		print_unknown_header_warning(4, header);
@@ -1650,7 +1981,7 @@
 		break;
 	}
 
-	writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+	writel(MBOX_BIT(4), PRCM_ARM_IT1_CLR);
 
 	if (do_complete)
 		complete(&mb4_transfer.work);
@@ -1662,20 +1993,20 @@
 {
 	mb5_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB5_I2C_STATUS);
 	mb5_transfer.ack.value = readb(tcdm_base + PRCM_ACK_MB5_I2C_VAL);
-	writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+	writel(MBOX_BIT(5), PRCM_ARM_IT1_CLR);
 	complete(&mb5_transfer.work);
 	return false;
 }
 
 static bool read_mailbox_6(void)
 {
-	writel(MBOX_BIT(6), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+	writel(MBOX_BIT(6), PRCM_ARM_IT1_CLR);
 	return false;
 }
 
 static bool read_mailbox_7(void)
 {
-	writel(MBOX_BIT(7), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+	writel(MBOX_BIT(7), PRCM_ARM_IT1_CLR);
 	return false;
 }
 
@@ -1696,7 +2027,7 @@
 	u8 n;
 	irqreturn_t r;
 
-	bits = (readl(_PRCMU_BASE + PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS);
+	bits = (readl(PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS);
 	if (unlikely(!bits))
 		return IRQ_NONE;
 
@@ -1768,7 +2099,7 @@
 	.irq_unmask	= prcmu_irq_unmask,
 };
 
-void __init prcmu_early_init(void)
+void __init db8500_prcmu_early_init(void)
 {
 	unsigned int i;
 
@@ -1826,6 +2157,16 @@
 	}
 }
 
+static void __init db8500_prcmu_init_clkforce(void)
+{
+	u32 val;
+
+	val = readl(PRCM_A9PL_FORCE_CLKEN);
+	val &= ~(PRCM_A9PL_FORCE_CLKEN_PRCM_A9PL_FORCE_CLKEN |
+		PRCM_A9PL_FORCE_CLKEN_PRCM_A9AXI_FORCE_CLKEN);
+	writel(val, (PRCM_A9PL_FORCE_CLKEN));
+}
+
 /*
  * Power domain switches (ePODs) modeled as regulators for the DB8500 SoC
  */
@@ -1861,7 +2202,42 @@
 
 static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = {
 	REGULATOR_SUPPLY("vsupply", "b2r2.0"),
-	REGULATOR_SUPPLY("vsupply", "mcde.0"),
+	REGULATOR_SUPPLY("vsupply", "mcde"),
+};
+
+/* SVA MMDSP regulator switch */
+static struct regulator_consumer_supply db8500_svammdsp_consumers[] = {
+	REGULATOR_SUPPLY("sva-mmdsp", "cm_control"),
+};
+
+/* SVA pipe regulator switch */
+static struct regulator_consumer_supply db8500_svapipe_consumers[] = {
+	REGULATOR_SUPPLY("sva-pipe", "cm_control"),
+};
+
+/* SIA MMDSP regulator switch */
+static struct regulator_consumer_supply db8500_siammdsp_consumers[] = {
+	REGULATOR_SUPPLY("sia-mmdsp", "cm_control"),
+};
+
+/* SIA pipe regulator switch */
+static struct regulator_consumer_supply db8500_siapipe_consumers[] = {
+	REGULATOR_SUPPLY("sia-pipe", "cm_control"),
+};
+
+static struct regulator_consumer_supply db8500_sga_consumers[] = {
+	REGULATOR_SUPPLY("v-mali", NULL),
+};
+
+/* ESRAM1 and 2 regulator switch */
+static struct regulator_consumer_supply db8500_esram12_consumers[] = {
+	REGULATOR_SUPPLY("esram12", "cm_control"),
+};
+
+/* ESRAM3 and 4 regulator switch */
+static struct regulator_consumer_supply db8500_esram34_consumers[] = {
+	REGULATOR_SUPPLY("v-esram34", "mcde"),
+	REGULATOR_SUPPLY("esram34", "cm_control"),
 };
 
 static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
@@ -1923,6 +2299,8 @@
 			.name = "db8500-sva-mmdsp",
 			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 		},
+		.consumer_supplies = db8500_svammdsp_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_svammdsp_consumers),
 	},
 	[DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = {
 		.constraints = {
@@ -1937,6 +2315,8 @@
 			.name = "db8500-sva-pipe",
 			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 		},
+		.consumer_supplies = db8500_svapipe_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_svapipe_consumers),
 	},
 	[DB8500_REGULATOR_SWITCH_SIAMMDSP] = {
 		.supply_regulator = "db8500-vape",
@@ -1944,6 +2324,8 @@
 			.name = "db8500-sia-mmdsp",
 			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 		},
+		.consumer_supplies = db8500_siammdsp_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_siammdsp_consumers),
 	},
 	[DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = {
 		.constraints = {
@@ -1957,6 +2339,8 @@
 			.name = "db8500-sia-pipe",
 			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 		},
+		.consumer_supplies = db8500_siapipe_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_siapipe_consumers),
 	},
 	[DB8500_REGULATOR_SWITCH_SGA] = {
 		.supply_regulator = "db8500-vape",
@@ -1964,6 +2348,9 @@
 			.name = "db8500-sga",
 			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 		},
+		.consumer_supplies = db8500_sga_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_sga_consumers),
+
 	},
 	[DB8500_REGULATOR_SWITCH_B2R2_MCDE] = {
 		.supply_regulator = "db8500-vape",
@@ -1980,6 +2367,8 @@
 			.name = "db8500-esram12",
 			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 		},
+		.consumer_supplies = db8500_esram12_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_esram12_consumers),
 	},
 	[DB8500_REGULATOR_SWITCH_ESRAM12RET] = {
 		.constraints = {
@@ -1993,6 +2382,8 @@
 			.name = "db8500-esram34",
 			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 		},
+		.consumer_supplies = db8500_esram34_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_esram34_consumers),
 	},
 	[DB8500_REGULATOR_SWITCH_ESRAM34RET] = {
 		.constraints = {
@@ -2024,8 +2415,10 @@
 	if (ux500_is_svp())
 		return -ENODEV;
 
+	db8500_prcmu_init_clkforce();
+
 	/* Clean up the mailbox interrupts after pre-kernel code. */
-	writel(ALL_MBOX_BITS, (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+	writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
 
 	err = request_threaded_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler,
 		prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL);
diff -druN linux-libre-3.1-gnu/drivers/mfd/db8500-prcmu-regs.h linux-libre-3.2-gnu/drivers/mfd/db8500-prcmu-regs.h
--- linux-libre-3.1-gnu/drivers/mfd/db8500-prcmu-regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/db8500-prcmu-regs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics 2009
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
- * Author: Sundar Iyer <sundar.iyer@stericsson.com>
- *
- * License Terms: GNU General Public License v2
- *
- * PRCM Unit registers
- */
-#ifndef __DB8500_PRCMU_REGS_H
-#define __DB8500_PRCMU_REGS_H
-
-#include <linux/bitops.h>
-#include <mach/hardware.h>
-
-#define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end))
-
-#define PRCM_ARM_PLLDIVPS 0x118
-#define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE	BITS(0, 5)
-#define PRCM_ARM_PLLDIVPS_MAX_MASK	0xF
-
-#define PRCM_PLLARM_LOCKP 0x0A8
-#define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3 BIT(1)
-
-#define PRCM_ARM_CHGCLKREQ 0x114
-#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ BIT(0)
-
-#define PRCM_PLLARM_ENABLE 0x98
-#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE	BIT(0)
-#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON	BIT(8)
-
-#define PRCM_ARMCLKFIX_MGT	0x0
-#define PRCM_A9_RESETN_CLR	0x1f4
-#define PRCM_A9_RESETN_SET	0x1f0
-#define PRCM_ARM_LS_CLAMP	0x30C
-#define PRCM_SRAM_A9		0x308
-
-/* ARM WFI Standby signal register */
-#define PRCM_ARM_WFI_STANDBY	0x130
-#define PRCM_IOCR		0x310
-#define PRCM_IOCR_IOFORCE BIT(0)
-
-/* CPU mailbox registers */
-#define PRCM_MBOX_CPU_VAL 0x0FC
-#define PRCM_MBOX_CPU_SET 0x100
-
-/* Dual A9 core interrupt management unit registers */
-#define PRCM_A9_MASK_REQ 0x328
-#define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ BIT(0)
-
-#define PRCM_A9_MASK_ACK	0x32C
-#define PRCM_ARMITMSK31TO0	0x11C
-#define PRCM_ARMITMSK63TO32	0x120
-#define PRCM_ARMITMSK95TO64	0x124
-#define PRCM_ARMITMSK127TO96	0x128
-#define PRCM_POWER_STATE_VAL	0x25C
-#define PRCM_ARMITVAL31TO0	0x260
-#define PRCM_ARMITVAL63TO32	0x264
-#define PRCM_ARMITVAL95TO64	0x268
-#define PRCM_ARMITVAL127TO96	0x26C
-
-#define PRCM_HOSTACCESS_REQ 0x334
-#define PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ BIT(0)
-
-#define PRCM_ARM_IT1_CLR 0x48C
-#define PRCM_ARM_IT1_VAL 0x494
-
-#define PRCM_ITSTATUS0		0x148
-#define PRCM_ITSTATUS1		0x150
-#define PRCM_ITSTATUS2		0x158
-#define PRCM_ITSTATUS3		0x160
-#define PRCM_ITSTATUS4		0x168
-#define PRCM_ITSTATUS5		0x484
-#define PRCM_ITCLEAR5		0x488
-#define PRCM_ARMIT_MASKXP70_IT	0x1018
-
-/* System reset register */
-#define PRCM_APE_SOFTRST 0x228
-
-/* Level shifter and clamp control registers */
-#define PRCM_MMIP_LS_CLAMP_SET 0x420
-#define PRCM_MMIP_LS_CLAMP_CLR 0x424
-
-/* PRCMU HW semaphore */
-#define PRCM_SEM 0x400
-#define PRCM_SEM_PRCM_SEM BIT(0)
-
-/* PRCMU clock/PLL/reset registers */
-#define PRCM_PLLDSI_FREQ	0x500
-#define PRCM_PLLDSI_ENABLE	0x504
-#define PRCM_PLLDSI_LOCKP	0x508
-#define PRCM_DSI_PLLOUT_SEL	0x530
-#define PRCM_DSITVCLK_DIV	0x52C
-#define PRCM_APE_RESETN_SET	0x1E4
-#define PRCM_APE_RESETN_CLR	0x1E8
-
-#define PRCM_TCR		0x1C8
-#define PRCM_TCR_TENSEL_MASK	BITS(0, 7)
-#define PRCM_TCR_STOP_TIMERS	BIT(16)
-#define PRCM_TCR_DOZE_MODE	BIT(17)
-
-#define PRCM_CLKOCR			0x1CC
-#define PRCM_CLKOCR_CLKODIV0_SHIFT	0
-#define PRCM_CLKOCR_CLKODIV0_MASK	BITS(0, 5)
-#define PRCM_CLKOCR_CLKOSEL0_SHIFT	6
-#define PRCM_CLKOCR_CLKOSEL0_MASK	BITS(6, 8)
-#define PRCM_CLKOCR_CLKODIV1_SHIFT	16
-#define PRCM_CLKOCR_CLKODIV1_MASK	BITS(16, 21)
-#define PRCM_CLKOCR_CLKOSEL1_SHIFT	22
-#define PRCM_CLKOCR_CLKOSEL1_MASK	BITS(22, 24)
-#define PRCM_CLKOCR_CLK1TYPE		BIT(28)
-
-#define PRCM_SGACLK_MGT		0x014
-#define PRCM_UARTCLK_MGT	0x018
-#define PRCM_MSP02CLK_MGT	0x01C
-#define PRCM_MSP1CLK_MGT	0x288
-#define PRCM_I2CCLK_MGT		0x020
-#define PRCM_SDMMCCLK_MGT	0x024
-#define PRCM_SLIMCLK_MGT	0x028
-#define PRCM_PER1CLK_MGT	0x02C
-#define PRCM_PER2CLK_MGT	0x030
-#define PRCM_PER3CLK_MGT	0x034
-#define PRCM_PER5CLK_MGT	0x038
-#define PRCM_PER6CLK_MGT	0x03C
-#define PRCM_PER7CLK_MGT	0x040
-#define PRCM_LCDCLK_MGT		0x044
-#define PRCM_BMLCLK_MGT		0x04C
-#define PRCM_HSITXCLK_MGT	0x050
-#define PRCM_HSIRXCLK_MGT	0x054
-#define PRCM_HDMICLK_MGT	0x058
-#define PRCM_APEATCLK_MGT	0x05C
-#define PRCM_APETRACECLK_MGT	0x060
-#define PRCM_MCDECLK_MGT	0x064
-#define PRCM_IPI2CCLK_MGT	0x068
-#define PRCM_DSIALTCLK_MGT	0x06C
-#define PRCM_DMACLK_MGT		0x074
-#define PRCM_B2R2CLK_MGT	0x078
-#define PRCM_TVCLK_MGT		0x07C
-#define PRCM_UNIPROCLK_MGT	0x278
-#define PRCM_SSPCLK_MGT		0x280
-#define PRCM_RNGCLK_MGT		0x284
-#define PRCM_UICCCLK_MGT	0x27C
-
-#define PRCM_CLK_MGT_CLKPLLDIV_MASK	BITS(0, 4)
-#define PRCM_CLK_MGT_CLKPLLSW_MASK	BITS(5, 7)
-#define PRCM_CLK_MGT_CLKEN		BIT(8)
-
-/* ePOD and memory power signal control registers */
-#define PRCM_EPOD_C_SET		0x410
-#define PRCM_SRAM_LS_SLEEP	0x304
-
-/* Debug power control unit registers */
-#define PRCM_POWER_STATE_SET 0x254
-
-/* Miscellaneous unit registers */
-#define PRCM_DSI_SW_RESET 0x324
-#define PRCM_GPIOCR		0x138
-
-/* GPIOCR register */
-#define PRCM_GPIOCR_SPI2_SELECT BIT(23)
-
-#define PRCM_DDR_SUBSYS_APE_MINBW  0x438
-
-#endif /* __DB8500_PRCMU_REGS_H */
diff -druN linux-libre-3.1-gnu/drivers/mfd/dbx500-prcmu-regs.h linux-libre-3.2-gnu/drivers/mfd/dbx500-prcmu-regs.h
--- linux-libre-3.1-gnu/drivers/mfd/dbx500-prcmu-regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/mfd/dbx500-prcmu-regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * PRCM Unit registers
+ */
+
+#ifndef __DB8500_PRCMU_REGS_H
+#define __DB8500_PRCMU_REGS_H
+
+#include <mach/hardware.h>
+
+#define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end))
+
+#define PRCM_SVACLK_MGT_OFF		0x008
+#define PRCM_SIACLK_MGT_OFF		0x00C
+#define PRCM_SGACLK_MGT_OFF		0x014
+#define PRCM_UARTCLK_MGT_OFF		0x018
+#define PRCM_MSP02CLK_MGT_OFF		0x01C
+#define PRCM_I2CCLK_MGT_OFF		0x020
+#define PRCM_SDMMCCLK_MGT_OFF		0x024
+#define PRCM_SLIMCLK_MGT_OFF		0x028
+#define PRCM_PER1CLK_MGT_OFF		0x02C
+#define PRCM_PER2CLK_MGT_OFF		0x030
+#define PRCM_PER3CLK_MGT_OFF		0x034
+#define PRCM_PER5CLK_MGT_OFF		0x038
+#define PRCM_PER6CLK_MGT_OFF		0x03C
+#define PRCM_PER7CLK_MGT_OFF		0x040
+#define PRCM_PWMCLK_MGT_OFF		0x044 /* for DB5500 */
+#define PRCM_IRDACLK_MGT_OFF		0x048 /* for DB5500 */
+#define PRCM_IRRCCLK_MGT_OFF		0x04C /* for DB5500 */
+#define PRCM_LCDCLK_MGT_OFF		0x044
+#define PRCM_BMLCLK_MGT_OFF		0x04C
+#define PRCM_HSITXCLK_MGT_OFF		0x050
+#define PRCM_HSIRXCLK_MGT_OFF		0x054
+#define PRCM_HDMICLK_MGT_OFF		0x058
+#define PRCM_APEATCLK_MGT_OFF		0x05C
+#define PRCM_APETRACECLK_MGT_OFF	0x060
+#define PRCM_MCDECLK_MGT_OFF		0x064
+#define PRCM_IPI2CCLK_MGT_OFF		0x068
+#define PRCM_DSIALTCLK_MGT_OFF		0x06C
+#define PRCM_DMACLK_MGT_OFF		0x074
+#define PRCM_B2R2CLK_MGT_OFF		0x078
+#define PRCM_TVCLK_MGT_OFF		0x07C
+#define PRCM_UNIPROCLK_MGT_OFF		0x278
+#define PRCM_SSPCLK_MGT_OFF		0x280
+#define PRCM_RNGCLK_MGT_OFF		0x284
+#define PRCM_UICCCLK_MGT_OFF		0x27C
+#define PRCM_MSP1CLK_MGT_OFF		0x288
+
+#define PRCM_ARM_PLLDIVPS	(_PRCMU_BASE + 0x118)
+#define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE		0x3f
+#define PRCM_ARM_PLLDIVPS_MAX_MASK		0xf
+
+#define PRCM_PLLARM_LOCKP       (_PRCMU_BASE + 0x0a8)
+#define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3	0x2
+
+#define PRCM_ARM_CHGCLKREQ	(_PRCMU_BASE + 0x114)
+#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ	0x1
+
+#define PRCM_PLLARM_ENABLE	(_PRCMU_BASE + 0x98)
+#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE	0x1
+#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON	0x100
+
+#define PRCM_ARMCLKFIX_MGT	(_PRCMU_BASE + 0x0)
+#define PRCM_A9PL_FORCE_CLKEN	(_PRCMU_BASE + 0x19C)
+#define PRCM_A9_RESETN_CLR	(_PRCMU_BASE + 0x1f4)
+#define PRCM_A9_RESETN_SET	(_PRCMU_BASE + 0x1f0)
+#define PRCM_ARM_LS_CLAMP	(_PRCMU_BASE + 0x30c)
+#define PRCM_SRAM_A9		(_PRCMU_BASE + 0x308)
+
+#define PRCM_A9PL_FORCE_CLKEN_PRCM_A9PL_FORCE_CLKEN BIT(0)
+#define PRCM_A9PL_FORCE_CLKEN_PRCM_A9AXI_FORCE_CLKEN BIT(1)
+
+/* ARM WFI Standby signal register */
+#define PRCM_ARM_WFI_STANDBY    (_PRCMU_BASE + 0x130)
+#define PRCM_IOCR		(_PRCMU_BASE + 0x310)
+#define PRCM_IOCR_IOFORCE			0x1
+
+/* CPU mailbox registers */
+#define PRCM_MBOX_CPU_VAL	(_PRCMU_BASE + 0x0fc)
+#define PRCM_MBOX_CPU_SET	(_PRCMU_BASE + 0x100)
+#define PRCM_MBOX_CPU_CLR	(_PRCMU_BASE + 0x104)
+
+/* Dual A9 core interrupt management unit registers */
+#define PRCM_A9_MASK_REQ	(_PRCMU_BASE + 0x328)
+#define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ	0x1
+
+#define PRCM_A9_MASK_ACK	(_PRCMU_BASE + 0x32c)
+#define PRCM_ARMITMSK31TO0	(_PRCMU_BASE + 0x11c)
+#define PRCM_ARMITMSK63TO32	(_PRCMU_BASE + 0x120)
+#define PRCM_ARMITMSK95TO64	(_PRCMU_BASE + 0x124)
+#define PRCM_ARMITMSK127TO96	(_PRCMU_BASE + 0x128)
+#define PRCM_POWER_STATE_VAL	(_PRCMU_BASE + 0x25C)
+#define PRCM_ARMITVAL31TO0	(_PRCMU_BASE + 0x260)
+#define PRCM_ARMITVAL63TO32	(_PRCMU_BASE + 0x264)
+#define PRCM_ARMITVAL95TO64	(_PRCMU_BASE + 0x268)
+#define PRCM_ARMITVAL127TO96	(_PRCMU_BASE + 0x26C)
+
+#define PRCM_HOSTACCESS_REQ	(_PRCMU_BASE + 0x334)
+#define PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ 0x1
+#define ARM_WAKEUP_MODEM	0x1
+
+#define PRCM_ARM_IT1_CLR	(_PRCMU_BASE + 0x48C)
+#define PRCM_ARM_IT1_VAL	(_PRCMU_BASE + 0x494)
+#define PRCM_HOLD_EVT		(_PRCMU_BASE + 0x174)
+
+#define PRCM_MOD_AWAKE_STATUS	(_PRCMU_BASE + 0x4A0)
+#define PRCM_MOD_AWAKE_STATUS_PRCM_MOD_COREPD_AWAKE	BIT(0)
+#define PRCM_MOD_AWAKE_STATUS_PRCM_MOD_AAPD_AWAKE	BIT(1)
+#define PRCM_MOD_AWAKE_STATUS_PRCM_MOD_VMODEM_OFF_ISO	BIT(2)
+
+#define PRCM_ITSTATUS0		(_PRCMU_BASE + 0x148)
+#define PRCM_ITSTATUS1		(_PRCMU_BASE + 0x150)
+#define PRCM_ITSTATUS2		(_PRCMU_BASE + 0x158)
+#define PRCM_ITSTATUS3		(_PRCMU_BASE + 0x160)
+#define PRCM_ITSTATUS4		(_PRCMU_BASE + 0x168)
+#define PRCM_ITSTATUS5		(_PRCMU_BASE + 0x484)
+#define PRCM_ITCLEAR5		(_PRCMU_BASE + 0x488)
+#define PRCM_ARMIT_MASKXP70_IT	(_PRCMU_BASE + 0x1018)
+
+/* System reset register */
+#define PRCM_APE_SOFTRST	(_PRCMU_BASE + 0x228)
+
+/* Level shifter and clamp control registers */
+#define PRCM_MMIP_LS_CLAMP_SET     (_PRCMU_BASE + 0x420)
+#define PRCM_MMIP_LS_CLAMP_CLR     (_PRCMU_BASE + 0x424)
+
+/* PRCMU clock/PLL/reset registers */
+#define PRCM_PLLDSI_FREQ           (_PRCMU_BASE + 0x500)
+#define PRCM_PLLDSI_ENABLE         (_PRCMU_BASE + 0x504)
+#define PRCM_PLLDSI_LOCKP          (_PRCMU_BASE + 0x508)
+#define PRCM_LCDCLK_MGT            (_PRCMU_BASE + PRCM_LCDCLK_MGT_OFF)
+#define PRCM_MCDECLK_MGT           (_PRCMU_BASE + PRCM_MCDECLK_MGT_OFF)
+#define PRCM_HDMICLK_MGT           (_PRCMU_BASE + PRCM_HDMICLK_MGT_OFF)
+#define PRCM_TVCLK_MGT             (_PRCMU_BASE + PRCM_TVCLK_MGT_OFF)
+#define PRCM_DSI_PLLOUT_SEL        (_PRCMU_BASE + 0x530)
+#define PRCM_DSITVCLK_DIV          (_PRCMU_BASE + 0x52C)
+#define PRCM_PLLDSI_LOCKP          (_PRCMU_BASE + 0x508)
+#define PRCM_APE_RESETN_SET        (_PRCMU_BASE + 0x1E4)
+#define PRCM_APE_RESETN_CLR        (_PRCMU_BASE + 0x1E8)
+
+#define PRCM_CLKOCR		   (_PRCMU_BASE + 0x1CC)
+#define PRCM_CLKOCR_CLKOUT0_REF_CLK	(1 << 0)
+#define PRCM_CLKOCR_CLKOUT0_MASK	BITS(0, 13)
+#define PRCM_CLKOCR_CLKOUT1_REF_CLK	(1 << 16)
+#define PRCM_CLKOCR_CLKOUT1_MASK	BITS(16, 29)
+
+/* ePOD and memory power signal control registers */
+#define PRCM_EPOD_C_SET            (_PRCMU_BASE + 0x410)
+#define PRCM_SRAM_LS_SLEEP         (_PRCMU_BASE + 0x304)
+
+/* Debug power control unit registers */
+#define PRCM_POWER_STATE_SET       (_PRCMU_BASE + 0x254)
+
+/* Miscellaneous unit registers */
+#define PRCM_DSI_SW_RESET          (_PRCMU_BASE + 0x324)
+#define PRCM_GPIOCR                (_PRCMU_BASE + 0x138)
+#define PRCM_GPIOCR_DBG_STM_MOD_CMD1            0x800
+#define PRCM_GPIOCR_DBG_UARTMOD_CMD0            0x1
+
+/* PRCMU HW semaphore */
+#define PRCM_SEM                   (_PRCMU_BASE + 0x400)
+#define PRCM_SEM_PRCM_SEM BIT(0)
+
+#define PRCM_TCR                   (_PRCMU_BASE + 0x1C8)
+#define PRCM_TCR_TENSEL_MASK       BITS(0, 7)
+#define PRCM_TCR_STOP_TIMERS       BIT(16)
+#define PRCM_TCR_DOZE_MODE         BIT(17)
+
+#define PRCM_CLKOCR_CLKODIV0_SHIFT	0
+#define PRCM_CLKOCR_CLKODIV0_MASK	BITS(0, 5)
+#define PRCM_CLKOCR_CLKOSEL0_SHIFT	6
+#define PRCM_CLKOCR_CLKOSEL0_MASK	BITS(6, 8)
+#define PRCM_CLKOCR_CLKODIV1_SHIFT	16
+#define PRCM_CLKOCR_CLKODIV1_MASK	BITS(16, 21)
+#define PRCM_CLKOCR_CLKOSEL1_SHIFT	22
+#define PRCM_CLKOCR_CLKOSEL1_MASK	BITS(22, 24)
+#define PRCM_CLKOCR_CLK1TYPE		BIT(28)
+
+#define PRCM_CLK_MGT_CLKPLLDIV_MASK	BITS(0, 4)
+#define PRCM_CLK_MGT_CLKPLLSW_MASK	BITS(5, 7)
+#define PRCM_CLK_MGT_CLKEN		BIT(8)
+
+/* GPIOCR register */
+#define PRCM_GPIOCR_SPI2_SELECT BIT(23)
+
+#define PRCM_DDR_SUBSYS_APE_MINBW	(_PRCMU_BASE + 0x438)
+#define PRCM_CGATING_BYPASS		(_PRCMU_BASE + 0x134)
+#define PRCM_CGATING_BYPASS_ICN2	BIT(6)
+
+/* Miscellaneous unit registers */
+#define PRCM_RESOUTN_SET		(_PRCMU_BASE + 0x214)
+#define PRCM_RESOUTN_CLR		(_PRCMU_BASE + 0x218)
+
+/* System reset register */
+#define PRCM_APE_SOFTRST		(_PRCMU_BASE + 0x228)
+
+#endif /* __DB8500_PRCMU_REGS_H */
diff -druN linux-libre-3.1-gnu/drivers/mfd/dm355evm_msp.c linux-libre-3.2-gnu/drivers/mfd/dm355evm_msp.c
--- linux-libre-3.1-gnu/drivers/mfd/dm355evm_msp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/dm355evm_msp.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/module.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
diff -druN linux-libre-3.1-gnu/drivers/mfd/intel_msic.c linux-libre-3.2-gnu/drivers/mfd/intel_msic.c
--- linux-libre-3.1-gnu/drivers/mfd/intel_msic.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/mfd/intel_msic.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,502 @@
+/*
+ * Driver for Intel MSIC
+ *
+ * Copyright (C) 2011, Intel Corporation
+ * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/intel_msic.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <asm/intel_scu_ipc.h>
+
+#define MSIC_VENDOR(id)		((id >> 6) & 3)
+#define MSIC_VERSION(id)	(id & 0x3f)
+#define MSIC_MAJOR(id)		('A' + ((id >> 3) & 7))
+#define MSIC_MINOR(id)		(id & 7)
+
+/*
+ * MSIC interrupt tree is readable from SRAM at INTEL_MSIC_IRQ_PHYS_BASE.
+ * Since IRQ block starts from address 0x002 we need to substract that from
+ * the actual IRQ status register address.
+ */
+#define MSIC_IRQ_STATUS(x)	(INTEL_MSIC_IRQ_PHYS_BASE + ((x) - 2))
+#define MSIC_IRQ_STATUS_ACCDET	MSIC_IRQ_STATUS(INTEL_MSIC_ACCDET)
+
+/*
+ * The SCU hardware has limitation of 16 bytes per read/write buffer on
+ * Medfield.
+ */
+#define SCU_IPC_RWBUF_LIMIT	16
+
+/**
+ * struct intel_msic - an MSIC MFD instance
+ * @pdev: pointer to the platform device
+ * @vendor: vendor ID
+ * @version: chip version
+ * @irq_base: base address of the mapped MSIC SRAM interrupt tree
+ */
+struct intel_msic {
+	struct platform_device		*pdev;
+	unsigned			vendor;
+	unsigned			version;
+	void __iomem			*irq_base;
+};
+
+static struct resource msic_touch_resources[] = {
+	{
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msic_adc_resources[] = {
+	{
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msic_battery_resources[] = {
+	{
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msic_gpio_resources[] = {
+	{
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msic_audio_resources[] = {
+	{
+		.name		= "IRQ",
+		.flags		= IORESOURCE_IRQ,
+	},
+	/*
+	 * We will pass IRQ_BASE to the driver now but this can be removed
+	 * when/if the driver starts to use intel_msic_irq_read().
+	 */
+	{
+		.name		= "IRQ_BASE",
+		.flags		= IORESOURCE_MEM,
+		.start		= MSIC_IRQ_STATUS_ACCDET,
+		.end		= MSIC_IRQ_STATUS_ACCDET,
+	},
+};
+
+static struct resource msic_hdmi_resources[] = {
+	{
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msic_thermal_resources[] = {
+	{
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msic_power_btn_resources[] = {
+	{
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msic_ocd_resources[] = {
+	{
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+/*
+ * Devices that are part of the MSIC and are available via firmware
+ * populated SFI DEVS table.
+ */
+static struct mfd_cell msic_devs[] = {
+	[INTEL_MSIC_BLOCK_TOUCH]	= {
+		.name			= "msic_touch",
+		.num_resources		= ARRAY_SIZE(msic_touch_resources),
+		.resources		= msic_touch_resources,
+	},
+	[INTEL_MSIC_BLOCK_ADC]		= {
+		.name			= "msic_adc",
+		.num_resources		= ARRAY_SIZE(msic_adc_resources),
+		.resources		= msic_adc_resources,
+	},
+	[INTEL_MSIC_BLOCK_BATTERY]	= {
+		.name			= "msic_battery",
+		.num_resources		= ARRAY_SIZE(msic_battery_resources),
+		.resources		= msic_battery_resources,
+	},
+	[INTEL_MSIC_BLOCK_GPIO]		= {
+		.name			= "msic_gpio",
+		.num_resources		= ARRAY_SIZE(msic_gpio_resources),
+		.resources		= msic_gpio_resources,
+	},
+	[INTEL_MSIC_BLOCK_AUDIO]	= {
+		.name			= "msic_audio",
+		.num_resources		= ARRAY_SIZE(msic_audio_resources),
+		.resources		= msic_audio_resources,
+	},
+	[INTEL_MSIC_BLOCK_HDMI]		= {
+		.name			= "msic_hdmi",
+		.num_resources		= ARRAY_SIZE(msic_hdmi_resources),
+		.resources		= msic_hdmi_resources,
+	},
+	[INTEL_MSIC_BLOCK_THERMAL]	= {
+		.name			= "msic_thermal",
+		.num_resources		= ARRAY_SIZE(msic_thermal_resources),
+		.resources		= msic_thermal_resources,
+	},
+	[INTEL_MSIC_BLOCK_POWER_BTN]	= {
+		.name			= "msic_power_btn",
+		.num_resources		= ARRAY_SIZE(msic_power_btn_resources),
+		.resources		= msic_power_btn_resources,
+	},
+	[INTEL_MSIC_BLOCK_OCD]		= {
+		.name			= "msic_ocd",
+		.num_resources		= ARRAY_SIZE(msic_ocd_resources),
+		.resources		= msic_ocd_resources,
+	},
+};
+
+/*
+ * Other MSIC related devices which are not directly available via SFI DEVS
+ * table. These can be pseudo devices, regulators etc. which are needed for
+ * different purposes.
+ *
+ * These devices appear only after the MSIC driver itself is initialized so
+ * we can guarantee that the SCU IPC interface is ready.
+ */
+static struct mfd_cell msic_other_devs[] = {
+	/* Audio codec in the MSIC */
+	{
+		.id			= -1,
+		.name			= "sn95031",
+	},
+};
+
+/**
+ * intel_msic_reg_read - read a single MSIC register
+ * @reg: register to read
+ * @val: register value is placed here
+ *
+ * Read a single register from MSIC. Returns %0 on success and negative
+ * errno in case of failure.
+ *
+ * Function may sleep.
+ */
+int intel_msic_reg_read(unsigned short reg, u8 *val)
+{
+	return intel_scu_ipc_ioread8(reg, val);
+}
+EXPORT_SYMBOL_GPL(intel_msic_reg_read);
+
+/**
+ * intel_msic_reg_write - write a single MSIC register
+ * @reg: register to write
+ * @val: value to write to that register
+ *
+ * Write a single MSIC register. Returns 0 on success and negative
+ * errno in case of failure.
+ *
+ * Function may sleep.
+ */
+int intel_msic_reg_write(unsigned short reg, u8 val)
+{
+	return intel_scu_ipc_iowrite8(reg, val);
+}
+EXPORT_SYMBOL_GPL(intel_msic_reg_write);
+
+/**
+ * intel_msic_reg_update - update a single MSIC register
+ * @reg: register to update
+ * @val: value to write to the register
+ * @mask: specifies which of the bits are updated (%0 = don't update,
+ *        %1 = update)
+ *
+ * Perform an update to a register @reg. @mask is used to specify which
+ * bits are updated. Returns %0 in case of success and negative errno in
+ * case of failure.
+ *
+ * Function may sleep.
+ */
+int intel_msic_reg_update(unsigned short reg, u8 val, u8 mask)
+{
+	return intel_scu_ipc_update_register(reg, val, mask);
+}
+EXPORT_SYMBOL_GPL(intel_msic_reg_update);
+
+/**
+ * intel_msic_bulk_read - read an array of registers
+ * @reg: array of register addresses to read
+ * @buf: array where the read values are placed
+ * @count: number of registers to read
+ *
+ * Function reads @count registers from the MSIC using addresses passed in
+ * @reg. Read values are placed in @buf. Reads are performed atomically
+ * wrt. MSIC.
+ *
+ * Returns %0 in case of success and negative errno in case of failure.
+ *
+ * Function may sleep.
+ */
+int intel_msic_bulk_read(unsigned short *reg, u8 *buf, size_t count)
+{
+	if (WARN_ON(count > SCU_IPC_RWBUF_LIMIT))
+		return -EINVAL;
+
+	return intel_scu_ipc_readv(reg, buf, count);
+}
+EXPORT_SYMBOL_GPL(intel_msic_bulk_read);
+
+/**
+ * intel_msic_bulk_write - write an array of values to the MSIC registers
+ * @reg: array of registers to write
+ * @buf: values to write to each register
+ * @count: number of registers to write
+ *
+ * Function writes @count registers in @buf to MSIC. Writes are performed
+ * atomically wrt MSIC. Returns %0 in case of success and negative errno in
+ * case of failure.
+ *
+ * Function may sleep.
+ */
+int intel_msic_bulk_write(unsigned short *reg, u8 *buf, size_t count)
+{
+	if (WARN_ON(count > SCU_IPC_RWBUF_LIMIT))
+		return -EINVAL;
+
+	return intel_scu_ipc_writev(reg, buf, count);
+}
+EXPORT_SYMBOL_GPL(intel_msic_bulk_write);
+
+/**
+ * intel_msic_irq_read - read a register from an MSIC interrupt tree
+ * @msic: MSIC instance
+ * @reg: interrupt register (between %INTEL_MSIC_IRQLVL1 and
+ *	 %INTEL_MSIC_RESETIRQ2)
+ * @val: value of the register is placed here
+ *
+ * This function can be used by an MSIC subdevice interrupt handler to read
+ * a register value from the MSIC interrupt tree. In this way subdevice
+ * drivers don't have to map in the interrupt tree themselves but can just
+ * call this function instead.
+ *
+ * Function doesn't sleep and is callable from interrupt context.
+ *
+ * Returns %-EINVAL if @reg is outside of the allowed register region.
+ */
+int intel_msic_irq_read(struct intel_msic *msic, unsigned short reg, u8 *val)
+{
+	if (WARN_ON(reg < INTEL_MSIC_IRQLVL1 || reg > INTEL_MSIC_RESETIRQ2))
+		return -EINVAL;
+
+	*val = readb(msic->irq_base + (reg - INTEL_MSIC_IRQLVL1));
+	return 0;
+}
+EXPORT_SYMBOL_GPL(intel_msic_irq_read);
+
+static int __devinit intel_msic_init_devices(struct intel_msic *msic)
+{
+	struct platform_device *pdev = msic->pdev;
+	struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
+	int ret, i;
+
+	if (pdata->gpio) {
+		struct mfd_cell *cell = &msic_devs[INTEL_MSIC_BLOCK_GPIO];
+
+		cell->platform_data = pdata->gpio;
+		cell->pdata_size = sizeof(*pdata->gpio);
+	}
+
+	if (pdata->ocd) {
+		unsigned gpio = pdata->ocd->gpio;
+
+		ret = gpio_request_one(gpio, GPIOF_IN, "ocd_gpio");
+		if (ret) {
+			dev_err(&pdev->dev, "failed to register OCD GPIO\n");
+			return ret;
+		}
+
+		ret = gpio_to_irq(gpio);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "no IRQ number for OCD GPIO\n");
+			gpio_free(gpio);
+			return ret;
+		}
+
+		/* Update the IRQ number for the OCD */
+		pdata->irq[INTEL_MSIC_BLOCK_OCD] = ret;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(msic_devs); i++) {
+		if (!pdata->irq[i])
+			continue;
+
+		ret = mfd_add_devices(&pdev->dev, -1, &msic_devs[i], 1, NULL,
+				      pdata->irq[i]);
+		if (ret)
+			goto fail;
+	}
+
+	ret = mfd_add_devices(&pdev->dev, 0, msic_other_devs,
+			      ARRAY_SIZE(msic_other_devs), NULL, 0);
+	if (ret)
+		goto fail;
+
+	return 0;
+
+fail:
+	mfd_remove_devices(&pdev->dev);
+	if (pdata->ocd)
+		gpio_free(pdata->ocd->gpio);
+
+	return ret;
+}
+
+static void __devexit intel_msic_remove_devices(struct intel_msic *msic)
+{
+	struct platform_device *pdev = msic->pdev;
+	struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
+
+	mfd_remove_devices(&pdev->dev);
+
+	if (pdata->ocd)
+		gpio_free(pdata->ocd->gpio);
+}
+
+static int __devinit intel_msic_probe(struct platform_device *pdev)
+{
+	struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
+	struct intel_msic *msic;
+	struct resource *res;
+	u8 id0, id1;
+	int ret;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "no platform data passed\n");
+		return -EINVAL;
+	}
+
+	/* First validate that we have an MSIC in place */
+	ret = intel_scu_ipc_ioread8(INTEL_MSIC_ID0, &id0);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to identify the MSIC chip (ID0)\n");
+		return -ENXIO;
+	}
+
+	ret = intel_scu_ipc_ioread8(INTEL_MSIC_ID1, &id1);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to identify the MSIC chip (ID1)\n");
+		return -ENXIO;
+	}
+
+	if (MSIC_VENDOR(id0) != MSIC_VENDOR(id1)) {
+		dev_err(&pdev->dev, "invalid vendor ID: %x, %x\n", id0, id1);
+		return -ENXIO;
+	}
+
+	msic = kzalloc(sizeof(*msic), GFP_KERNEL);
+	if (!msic)
+		return -ENOMEM;
+
+	msic->vendor = MSIC_VENDOR(id0);
+	msic->version = MSIC_VERSION(id0);
+	msic->pdev = pdev;
+
+	/*
+	 * Map in the MSIC interrupt tree area in SRAM. This is exposed to
+	 * the clients via intel_msic_irq_read().
+	 */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get SRAM iomem resource\n");
+		ret = -ENODEV;
+		goto fail_free_msic;
+	}
+
+	res = request_mem_region(res->start, resource_size(res), pdev->name);
+	if (!res) {
+		ret = -EBUSY;
+		goto fail_free_msic;
+	}
+
+	msic->irq_base = ioremap_nocache(res->start, resource_size(res));
+	if (!msic->irq_base) {
+		dev_err(&pdev->dev, "failed to map SRAM memory\n");
+		ret = -ENOMEM;
+		goto fail_release_region;
+	}
+
+	platform_set_drvdata(pdev, msic);
+
+	ret = intel_msic_init_devices(msic);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize MSIC devices\n");
+		goto fail_unmap_mem;
+	}
+
+	dev_info(&pdev->dev, "Intel MSIC version %c%d (vendor %#x)\n",
+		 MSIC_MAJOR(msic->version), MSIC_MINOR(msic->version),
+		 msic->vendor);
+
+	return 0;
+
+fail_unmap_mem:
+	iounmap(msic->irq_base);
+fail_release_region:
+	release_mem_region(res->start, resource_size(res));
+fail_free_msic:
+	kfree(msic);
+
+	return ret;
+}
+
+static int __devexit intel_msic_remove(struct platform_device *pdev)
+{
+	struct intel_msic *msic = platform_get_drvdata(pdev);
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	intel_msic_remove_devices(msic);
+	platform_set_drvdata(pdev, NULL);
+	iounmap(msic->irq_base);
+	release_mem_region(res->start, resource_size(res));
+	kfree(msic);
+
+	return 0;
+}
+
+static struct platform_driver intel_msic_driver = {
+	.probe		= intel_msic_probe,
+	.remove		= __devexit_p(intel_msic_remove),
+	.driver		= {
+		.name	= "intel_msic",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init intel_msic_init(void)
+{
+	return platform_driver_register(&intel_msic_driver);
+}
+module_init(intel_msic_init);
+
+static void __exit intel_msic_exit(void)
+{
+	platform_driver_unregister(&intel_msic_driver);
+}
+module_exit(intel_msic_exit);
+
+MODULE_DESCRIPTION("Driver for Intel MSIC");
+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/mfd/jz4740-adc.c linux-libre-3.2-gnu/drivers/mfd/jz4740-adc.c
--- linux-libre-3.1-gnu/drivers/mfd/jz4740-adc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/jz4740-adc.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
  */
 
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
@@ -328,7 +329,7 @@
 	return 0;
 }
 
-struct platform_driver jz4740_adc_driver = {
+static struct platform_driver jz4740_adc_driver = {
 	.probe	= jz4740_adc_probe,
 	.remove = __devexit_p(jz4740_adc_remove),
 	.driver = {
diff -druN linux-libre-3.1-gnu/drivers/mfd/Kconfig linux-libre-3.2-gnu/drivers/mfd/Kconfig
--- linux-libre-3.1-gnu/drivers/mfd/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -2,23 +2,8 @@
 # Multifunction miscellaneous devices
 #
 
-menuconfig MFD_SUPPORT
-	bool "Multifunction device drivers"
-	depends on HAS_IOMEM
-	default y
-	help
-	  Multifunction devices embed several functions (e.g. GPIOs,
-	  touchscreens, keyboards, current regulators, power management chips,
-	  etc...) in one single integrated circuit. They usually talk to the
-	  main CPU through one or more IRQ lines and low speed data busses (SPI,
-	  I2C, etc..). They appear as one single device to the main system
-	  through the data bus and the MFD framework allows for sub devices
-	  (a.k.a. functions) to appear as discrete platform devices.
-	  MFDs are typically found on embedded platforms.
-
-	  This option alone does not add any kernel code.
-
-if MFD_SUPPORT
+if HAS_IOMEM
+menu "Multifunction device drivers"
 
 config MFD_CORE
 	tristate
@@ -390,6 +375,7 @@
 	tristate "Support Wolfson Microelectronics WM8400"
 	select MFD_CORE
 	depends on I2C
+	select REGMAP_I2C
 	help
 	  Support for the Wolfson Microelecronics WM8400 PMIC and audio
 	  CODEC.  This driver provides common support for accessing
@@ -404,6 +390,7 @@
 	bool "Support Wolfson Microelectronics WM831x/2x PMICs with I2C"
 	select MFD_CORE
 	select MFD_WM831X
+	select REGMAP_I2C
 	depends on I2C=y && GENERIC_HARDIRQS
 	help
 	  Support for the Wolfson Microelecronics WM831x and WM832x PMICs
@@ -415,6 +402,7 @@
 	bool "Support Wolfson Microelectronics WM831x/2x PMICs with SPI"
 	select MFD_CORE
 	select MFD_WM831X
+	select REGMAP_SPI
 	depends on SPI_MASTER && GENERIC_HARDIRQS
 	help
 	  Support for the Wolfson Microelecronics WM831x and WM832x PMICs
@@ -488,6 +476,7 @@
 config MFD_WM8994
 	bool "Support Wolfson Microelectronics WM8994"
 	select MFD_CORE
+	select REGMAP_I2C
 	depends on I2C=y && GENERIC_HARDIRQS
 	help
 	  The WM8994 is a highly integrated hi-fi CODEC designed for
@@ -500,6 +489,7 @@
 config MFD_PCF50633
 	tristate "Support for NXP PCF50633"
 	depends on I2C
+	select REGMAP_I2C
 	help
 	  Say yes here if you have NXP PCF50633 chip on your board.
 	  This core driver provides register access and IRQ handling
@@ -576,6 +566,23 @@
 	  This enables the PCAP ASIC present on EZX Phones. This is
 	  needed for MMC, TouchScreen, Sound, USB, etc..
 
+config AB5500_CORE
+	bool "ST-Ericsson AB5500 Mixed Signal Power Management chip"
+	depends on ABX500_CORE && MFD_DB5500_PRCMU
+	select MFD_CORE
+	help
+	  Select this option to enable access to AB5500 power management
+	  chip. This connects to the db5500 chip via the I2C bus via PRCMU.
+	  This chip embeds various other multimedia funtionalities as well.
+
+config AB5500_DEBUG
+	bool "Enable debug info via debugfs"
+	depends on AB5500_CORE && DEBUG_FS
+	default y if DEBUG_FS
+	help
+	  Select this option if you want debug information from the AB5500
+	  using the debug filesystem, debugfs.
+
 config AB8500_CORE
 	bool "ST-Ericsson AB8500 Mixed Signal Power Management chip"
 	depends on GENERIC_HARDIRQS && ABX500_CORE
@@ -612,20 +619,6 @@
 	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
-	depends on I2C=y && GENERIC_HARDIRQS && ABX500_CORE
-	help
-	  Select this to enable the AB3550 Mixed Signal IC core
-	  functionality. This connects to a AB3550 on the I2C bus
-	  and expose a number of symbols needed for dependent devices
-	  to read and write registers and subscribe to events from
-	  this multi-functional IC. This is needed to use other features
-	  of the AB3550 such as battery-backed RTC, charging control,
-	  LEDs, vibrator, system power and temperature, power management
-	  and ALSA sound.
-
 config MFD_DB8500_PRCMU
 	bool "ST-Ericsson DB8500 Power Reset Control Management Unit"
 	depends on UX500_SOC_DB8500
@@ -770,7 +763,17 @@
 	  additional drivers must be enabled in order to use the
 	  functionality of the device.
 
-endif # MFD_SUPPORT
+config MFD_INTEL_MSIC
+	bool "Support for Intel MSIC"
+	depends on INTEL_SCU_IPC
+	select MFD_CORE
+	help
+	  Select this option to enable access to Intel MSIC (Avatele
+	  Passage) chip. This chip embeds audio, battery, GPIO, etc.
+	  devices used in Intel Medfield platforms.
+
+endmenu
+endif
 
 menu "Multimedia Capabilities Port drivers"
 	depends on ARCH_SA1100
diff -druN linux-libre-3.1-gnu/drivers/mfd/Makefile linux-libre-3.2-gnu/drivers/mfd/Makefile
--- linux-libre-3.1-gnu/drivers/mfd/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -79,7 +79,8 @@
 obj-$(CONFIG_ABX500_CORE)	+= abx500-core.o
 obj-$(CONFIG_AB3100_CORE)	+= ab3100-core.o
 obj-$(CONFIG_AB3100_OTP)	+= ab3100-otp.o
-obj-$(CONFIG_AB3550_CORE)	+= ab3550-core.o
+obj-$(CONFIG_AB5500_CORE)	+= ab5500-core.o
+obj-$(CONFIG_AB5500_DEBUG)	+= ab5500-debugfs.o
 obj-$(CONFIG_AB8500_CORE)	+= ab8500-core.o ab8500-sysctrl.o
 obj-$(CONFIG_AB8500_DEBUG)	+= ab8500-debugfs.o
 obj-$(CONFIG_AB8500_GPADC)	+= ab8500-gpadc.o
@@ -102,3 +103,4 @@
 obj-$(CONFIG_MFD_PM8XXX_IRQ) 	+= pm8xxx-irq.o
 obj-$(CONFIG_TPS65911_COMPARATOR)	+= tps65911-comparator.o
 obj-$(CONFIG_MFD_AAT2870_CORE)	+= aat2870-core.o
+obj-$(CONFIG_MFD_INTEL_MSIC)	+= intel_msic.o
diff -druN linux-libre-3.1-gnu/drivers/mfd/max8997.c linux-libre-3.2-gnu/drivers/mfd/max8997.c
--- linux-libre-3.1-gnu/drivers/mfd/max8997.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/max8997.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,7 +23,9 @@
 
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/interrupt.h>
 #include <linux/pm_runtime.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/max8997.h>
@@ -142,7 +144,6 @@
 
 	max8997->irq_base = pdata->irq_base;
 	max8997->ono = pdata->ono;
-	max8997->wakeup = pdata->wakeup;
 
 	mutex_init(&max8997->iolock);
 
@@ -169,6 +170,9 @@
 	if (ret < 0)
 		goto err_mfd;
 
+	/* MAX8997 has a power button input. */
+	device_init_wakeup(max8997->dev, pdata->wakeup);
+
 	return ret;
 
 err_mfd:
@@ -398,7 +402,29 @@
 	return 0;
 }
 
+static int max8997_suspend(struct device *dev)
+{
+	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
+
+	if (device_may_wakeup(dev))
+		irq_set_irq_wake(max8997->irq, 1);
+	return 0;
+}
+
+static int max8997_resume(struct device *dev)
+{
+	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
+
+	if (device_may_wakeup(dev))
+		irq_set_irq_wake(max8997->irq, 0);
+	return max8997_irq_resume(max8997);
+}
+
 const struct dev_pm_ops max8997_pm = {
+	.suspend = max8997_suspend,
+	.resume = max8997_resume,
 	.freeze = max8997_freeze,
 	.restore = max8997_restore,
 };
diff -druN linux-libre-3.1-gnu/drivers/mfd/mc13xxx-core.c linux-libre-3.2-gnu/drivers/mfd/mc13xxx-core.c
--- linux-libre-3.1-gnu/drivers/mfd/mc13xxx-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/mc13xxx-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,20 +26,10 @@
 
 	irq_handler_t irqhandler[MC13XXX_NUM_IRQ];
 	void *irqdata[MC13XXX_NUM_IRQ];
-};
-
-struct mc13783 {
-	struct mc13xxx mc13xxx;
 
 	int adcflags;
 };
 
-struct mc13xxx *mc13783_to_mc13xxx(struct mc13783 *mc13783)
-{
-	return &mc13783->mc13xxx;
-}
-EXPORT_SYMBOL(mc13783_to_mc13xxx);
-
 #define MC13XXX_IRQSTAT0	0
 #define MC13XXX_IRQSTAT0_ADCDONEI	(1 << 0)
 #define MC13XXX_IRQSTAT0_ADCBISDONEI	(1 << 1)
@@ -136,14 +126,14 @@
 #define MC13XXX_REVISION_FAB		(0x03 << 11)
 #define MC13XXX_REVISION_ICIDCODE	(0x3f << 13)
 
-#define MC13783_ADC1		44
-#define MC13783_ADC1_ADEN		(1 << 0)
-#define MC13783_ADC1_RAND		(1 << 1)
-#define MC13783_ADC1_ADSEL		(1 << 3)
-#define MC13783_ADC1_ASC		(1 << 20)
-#define MC13783_ADC1_ADTRIGIGN		(1 << 21)
+#define MC13XXX_ADC1		44
+#define MC13XXX_ADC1_ADEN		(1 << 0)
+#define MC13XXX_ADC1_RAND		(1 << 1)
+#define MC13XXX_ADC1_ADSEL		(1 << 3)
+#define MC13XXX_ADC1_ASC		(1 << 20)
+#define MC13XXX_ADC1_ADTRIGIGN		(1 << 21)
 
-#define MC13783_ADC2		45
+#define MC13XXX_ADC2		45
 
 #define MC13XXX_NUMREGS 0x3f
 
@@ -487,7 +477,7 @@
 	MC13XXX_ID_INVALID,
 };
 
-const char *mc13xxx_chipname[] = {
+static const char *mc13xxx_chipname[] = {
 	[MC13XXX_ID_MC13783] = "mc13783",
 	[MC13XXX_ID_MC13892] = "mc13892",
 };
@@ -558,8 +548,6 @@
 	return mc13xxx_chipname[devid->driver_data];
 }
 
-#include <linux/mfd/mc13783.h>
-
 int mc13xxx_get_flags(struct mc13xxx *mc13xxx)
 {
 	struct mc13xxx_platform_data *pdata =
@@ -569,15 +557,15 @@
 }
 EXPORT_SYMBOL(mc13xxx_get_flags);
 
-#define MC13783_ADC1_CHAN0_SHIFT	5
-#define MC13783_ADC1_CHAN1_SHIFT	8
+#define MC13XXX_ADC1_CHAN0_SHIFT	5
+#define MC13XXX_ADC1_CHAN1_SHIFT	8
 
 struct mc13xxx_adcdone_data {
 	struct mc13xxx *mc13xxx;
 	struct completion done;
 };
 
-static irqreturn_t mc13783_handler_adcdone(int irq, void *data)
+static irqreturn_t mc13xxx_handler_adcdone(int irq, void *data)
 {
 	struct mc13xxx_adcdone_data *adcdone_data = data;
 
@@ -588,12 +576,11 @@
 	return IRQ_HANDLED;
 }
 
-#define MC13783_ADC_WORKING (1 << 0)
+#define MC13XXX_ADC_WORKING (1 << 0)
 
-int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode,
+int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
 		unsigned int channel, unsigned int *sample)
 {
-	struct mc13xxx *mc13xxx = &mc13783->mc13xxx;
 	u32 adc0, adc1, old_adc0;
 	int i, ret;
 	struct mc13xxx_adcdone_data adcdone_data = {
@@ -605,51 +592,51 @@
 
 	mc13xxx_lock(mc13xxx);
 
-	if (mc13783->adcflags & MC13783_ADC_WORKING) {
+	if (mc13xxx->adcflags & MC13XXX_ADC_WORKING) {
 		ret = -EBUSY;
 		goto out;
 	}
 
-	mc13783->adcflags |= MC13783_ADC_WORKING;
+	mc13xxx->adcflags |= MC13XXX_ADC_WORKING;
 
-	mc13xxx_reg_read(mc13xxx, MC13783_ADC0, &old_adc0);
+	mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0);
 
-	adc0 = MC13783_ADC0_ADINC1 | MC13783_ADC0_ADINC2;
-	adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN | MC13783_ADC1_ASC;
+	adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2;
+	adc1 = MC13XXX_ADC1_ADEN | MC13XXX_ADC1_ADTRIGIGN | MC13XXX_ADC1_ASC;
 
 	if (channel > 7)
-		adc1 |= MC13783_ADC1_ADSEL;
+		adc1 |= MC13XXX_ADC1_ADSEL;
 
 	switch (mode) {
-	case MC13783_ADC_MODE_TS:
-		adc0 |= MC13783_ADC0_ADREFEN | MC13783_ADC0_TSMOD0 |
-			MC13783_ADC0_TSMOD1;
-		adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT;
+	case MC13XXX_ADC_MODE_TS:
+		adc0 |= MC13XXX_ADC0_ADREFEN | MC13XXX_ADC0_TSMOD0 |
+			MC13XXX_ADC0_TSMOD1;
+		adc1 |= 4 << MC13XXX_ADC1_CHAN1_SHIFT;
 		break;
 
-	case MC13783_ADC_MODE_SINGLE_CHAN:
-		adc0 |= old_adc0 & MC13783_ADC0_TSMOD_MASK;
-		adc1 |= (channel & 0x7) << MC13783_ADC1_CHAN0_SHIFT;
-		adc1 |= MC13783_ADC1_RAND;
+	case MC13XXX_ADC_MODE_SINGLE_CHAN:
+		adc0 |= old_adc0 & MC13XXX_ADC0_TSMOD_MASK;
+		adc1 |= (channel & 0x7) << MC13XXX_ADC1_CHAN0_SHIFT;
+		adc1 |= MC13XXX_ADC1_RAND;
 		break;
 
-	case MC13783_ADC_MODE_MULT_CHAN:
-		adc0 |= old_adc0 & MC13783_ADC0_TSMOD_MASK;
-		adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT;
+	case MC13XXX_ADC_MODE_MULT_CHAN:
+		adc0 |= old_adc0 & MC13XXX_ADC0_TSMOD_MASK;
+		adc1 |= 4 << MC13XXX_ADC1_CHAN1_SHIFT;
 		break;
 
 	default:
-		mc13783_unlock(mc13783);
+		mc13xxx_unlock(mc13xxx);
 		return -EINVAL;
 	}
 
-	dev_dbg(&mc13783->mc13xxx.spidev->dev, "%s: request irq\n", __func__);
-	mc13xxx_irq_request(mc13xxx, MC13783_IRQ_ADCDONE,
-			mc13783_handler_adcdone, __func__, &adcdone_data);
-	mc13xxx_irq_ack(mc13xxx, MC13783_IRQ_ADCDONE);
+	dev_dbg(&mc13xxx->spidev->dev, "%s: request irq\n", __func__);
+	mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_ADCDONE,
+			mc13xxx_handler_adcdone, __func__, &adcdone_data);
+	mc13xxx_irq_ack(mc13xxx, MC13XXX_IRQ_ADCDONE);
 
-	mc13xxx_reg_write(mc13xxx, MC13783_ADC0, adc0);
-	mc13xxx_reg_write(mc13xxx, MC13783_ADC1, adc1);
+	mc13xxx_reg_write(mc13xxx, MC13XXX_ADC0, adc0);
+	mc13xxx_reg_write(mc13xxx, MC13XXX_ADC1, adc1);
 
 	mc13xxx_unlock(mc13xxx);
 
@@ -660,27 +647,27 @@
 
 	mc13xxx_lock(mc13xxx);
 
-	mc13xxx_irq_free(mc13xxx, MC13783_IRQ_ADCDONE, &adcdone_data);
+	mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_ADCDONE, &adcdone_data);
 
 	if (ret > 0)
 		for (i = 0; i < 4; ++i) {
 			ret = mc13xxx_reg_read(mc13xxx,
-					MC13783_ADC2, &sample[i]);
+					MC13XXX_ADC2, &sample[i]);
 			if (ret)
 				break;
 		}
 
-	if (mode == MC13783_ADC_MODE_TS)
+	if (mode == MC13XXX_ADC_MODE_TS)
 		/* restore TSMOD */
-		mc13xxx_reg_write(mc13xxx, MC13783_ADC0, old_adc0);
+		mc13xxx_reg_write(mc13xxx, MC13XXX_ADC0, old_adc0);
 
-	mc13783->adcflags &= ~MC13783_ADC_WORKING;
+	mc13xxx->adcflags &= ~MC13XXX_ADC_WORKING;
 out:
 	mc13xxx_unlock(mc13xxx);
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion);
+EXPORT_SYMBOL_GPL(mc13xxx_adc_do_conversion);
 
 static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx,
 		const char *format, void *pdata, size_t pdata_size)
@@ -716,6 +703,11 @@
 	enum mc13xxx_id id;
 	int ret;
 
+	if (!pdata) {
+		dev_err(&spi->dev, "invalid platform data\n");
+		return -EINVAL;
+	}
+
 	mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL);
 	if (!mc13xxx)
 		return -ENOMEM;
@@ -763,10 +755,8 @@
 	if (pdata->flags & MC13XXX_USE_CODEC)
 		mc13xxx_add_subdevice(mc13xxx, "%s-codec");
 
-	if (pdata->flags & MC13XXX_USE_REGULATOR) {
-		mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
-				&pdata->regulators, sizeof(pdata->regulators));
-	}
+	mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
+		&pdata->regulators, sizeof(pdata->regulators));
 
 	if (pdata->flags & MC13XXX_USE_RTC)
 		mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
@@ -774,10 +764,14 @@
 	if (pdata->flags & MC13XXX_USE_TOUCHSCREEN)
 		mc13xxx_add_subdevice(mc13xxx, "%s-ts");
 
-	if (pdata->flags & MC13XXX_USE_LED)
+	if (pdata->leds)
 		mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led",
 				pdata->leds, sizeof(*pdata->leds));
 
+	if (pdata->buttons)
+		mc13xxx_add_subdevice_pdata(mc13xxx, "%s-pwrbutton",
+				pdata->buttons, sizeof(*pdata->buttons));
+
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/mfd/menelaus.c linux-libre-3.2-gnu/drivers/mfd/menelaus.c
--- linux-libre-3.1-gnu/drivers/mfd/menelaus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/menelaus.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,7 +44,7 @@
 
 #include <asm/mach/irq.h>
 
-#include <mach/gpio.h>
+#include <asm/gpio.h>
 #include <plat/menelaus.h>
 
 #define DRIVER_NAME			"menelaus"
@@ -1226,7 +1226,7 @@
 	menelaus_write_reg(MENELAUS_MCT_CTRL1, 0x73);
 
 	if (client->irq > 0) {
-		err = request_irq(client->irq, menelaus_irq, IRQF_DISABLED,
+		err = request_irq(client->irq, menelaus_irq, 0,
 				  DRIVER_NAME, menelaus);
 		if (err) {
 			dev_dbg(&client->dev,  "can't get IRQ %d, err %d\n",
diff -druN linux-libre-3.1-gnu/drivers/mfd/mfd-core.c linux-libre-3.2-gnu/drivers/mfd/mfd-core.c
--- linux-libre-3.1-gnu/drivers/mfd/mfd-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/mfd-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/mfd/core.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 int mfd_cell_enable(struct platform_device *pdev)
 {
diff -druN linux-libre-3.1-gnu/drivers/mfd/pcf50633-core.c linux-libre-3.2-gnu/drivers/mfd/pcf50633-core.c
--- linux-libre-3.1-gnu/drivers/mfd/pcf50633-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/pcf50633-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,45 +23,22 @@
 #include <linux/i2c.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
 
 #include <linux/mfd/pcf50633/core.h>
 
-static int __pcf50633_read(struct pcf50633 *pcf, u8 reg, int num, u8 *data)
-{
-	int ret;
-
-	ret = i2c_smbus_read_i2c_block_data(pcf->i2c_client, reg,
-				num, data);
-	if (ret < 0)
-		dev_err(pcf->dev, "Error reading %d regs at %d\n", num, reg);
-
-	return ret;
-}
-
-static int __pcf50633_write(struct pcf50633 *pcf, u8 reg, int num, u8 *data)
-{
-	int ret;
-
-	ret = i2c_smbus_write_i2c_block_data(pcf->i2c_client, reg,
-				num, data);
-	if (ret < 0)
-		dev_err(pcf->dev, "Error writing %d regs at %d\n", num, reg);
-
-	return ret;
-
-}
-
 /* Read a block of up to 32 regs  */
 int pcf50633_read_block(struct pcf50633 *pcf, u8 reg,
 					int nr_regs, u8 *data)
 {
 	int ret;
 
-	mutex_lock(&pcf->lock);
-	ret = __pcf50633_read(pcf, reg, nr_regs, data);
-	mutex_unlock(&pcf->lock);
+	ret = regmap_raw_read(pcf->regmap, reg, data, nr_regs);
+	if (ret != 0)
+		return ret;
 
-	return ret;
+	return nr_regs;
 }
 EXPORT_SYMBOL_GPL(pcf50633_read_block);
 
@@ -71,21 +48,22 @@
 {
 	int ret;
 
-	mutex_lock(&pcf->lock);
-	ret = __pcf50633_write(pcf, reg, nr_regs, data);
-	mutex_unlock(&pcf->lock);
+	ret = regmap_raw_write(pcf->regmap, reg, data, nr_regs);
+	if (ret != 0)
+		return ret;
 
-	return ret;
+	return nr_regs;
 }
 EXPORT_SYMBOL_GPL(pcf50633_write_block);
 
 u8 pcf50633_reg_read(struct pcf50633 *pcf, u8 reg)
 {
-	u8 val;
+	unsigned int val;
+	int ret;
 
-	mutex_lock(&pcf->lock);
-	__pcf50633_read(pcf, reg, 1, &val);
-	mutex_unlock(&pcf->lock);
+	ret = regmap_read(pcf->regmap, reg, &val);
+	if (ret < 0)
+		return -1;
 
 	return val;
 }
@@ -93,56 +71,19 @@
 
 int pcf50633_reg_write(struct pcf50633 *pcf, u8 reg, u8 val)
 {
-	int ret;
-
-	mutex_lock(&pcf->lock);
-	ret = __pcf50633_write(pcf, reg, 1, &val);
-	mutex_unlock(&pcf->lock);
-
-	return ret;
+	return regmap_write(pcf->regmap, reg, val);
 }
 EXPORT_SYMBOL_GPL(pcf50633_reg_write);
 
 int pcf50633_reg_set_bit_mask(struct pcf50633 *pcf, u8 reg, u8 mask, u8 val)
 {
-	int ret;
-	u8 tmp;
-
-	val &= mask;
-
-	mutex_lock(&pcf->lock);
-	ret = __pcf50633_read(pcf, reg, 1, &tmp);
-	if (ret < 0)
-		goto out;
-
-	tmp &= ~mask;
-	tmp |= val;
-	ret = __pcf50633_write(pcf, reg, 1, &tmp);
-
-out:
-	mutex_unlock(&pcf->lock);
-
-	return ret;
+	return regmap_update_bits(pcf->regmap, reg, mask, val);
 }
 EXPORT_SYMBOL_GPL(pcf50633_reg_set_bit_mask);
 
 int pcf50633_reg_clear_bits(struct pcf50633 *pcf, u8 reg, u8 val)
 {
-	int ret;
-	u8 tmp;
-
-	mutex_lock(&pcf->lock);
-	ret = __pcf50633_read(pcf, reg, 1, &tmp);
-	if (ret < 0)
-		goto out;
-
-	tmp &= ~val;
-	ret = __pcf50633_write(pcf, reg, 1, &tmp);
-
-out:
-	mutex_unlock(&pcf->lock);
-
-	return ret;
+	return regmap_update_bits(pcf->regmap, reg, val, 0);
 }
 EXPORT_SYMBOL_GPL(pcf50633_reg_clear_bits);
 
@@ -251,6 +192,11 @@
 
 static SIMPLE_DEV_PM_OPS(pcf50633_pm, pcf50633_suspend, pcf50633_resume);
 
+static struct regmap_config pcf50633_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
 static int __devinit pcf50633_probe(struct i2c_client *client,
 				const struct i2c_device_id *ids)
 {
@@ -272,16 +218,23 @@
 
 	mutex_init(&pcf->lock);
 
+	pcf->regmap = regmap_init_i2c(client, &pcf50633_regmap_config);
+	if (IS_ERR(pcf->regmap)) {
+		ret = PTR_ERR(pcf->regmap);
+		dev_err(pcf->dev, "Failed to allocate register map: %d\n",
+			ret);
+		goto err_free;
+	}
+
 	i2c_set_clientdata(client, pcf);
 	pcf->dev = &client->dev;
-	pcf->i2c_client = client;
 
 	version = pcf50633_reg_read(pcf, 0);
 	variant = pcf50633_reg_read(pcf, 1);
 	if (version < 0 || variant < 0) {
 		dev_err(pcf->dev, "Unable to probe pcf50633\n");
 		ret = -ENODEV;
-		goto err_free;
+		goto err_regmap;
 	}
 
 	dev_info(pcf->dev, "Probed device version %d variant %d\n",
@@ -328,6 +281,8 @@
 
 	return 0;
 
+err_regmap:
+	regmap_exit(pcf->regmap);
 err_free:
 	kfree(pcf);
 
@@ -351,6 +306,7 @@
 	for (i = 0; i < PCF50633_NUM_REGULATORS; i++)
 		platform_device_unregister(pcf->regulator_pdev[i]);
 
+	regmap_exit(pcf->regmap);
 	kfree(pcf);
 
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/mfd/pcf50633-irq.c linux-libre-3.2-gnu/drivers/mfd/pcf50633-irq.c
--- linux-libre-3.1-gnu/drivers/mfd/pcf50633-irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/pcf50633-irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/mutex.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 
 #include <linux/mfd/pcf50633/core.h>
diff -druN linux-libre-3.1-gnu/drivers/mfd/tc3589x.c linux-libre-3.2-gnu/drivers/mfd/tc3589x.c
--- linux-libre-3.1-gnu/drivers/mfd/tc3589x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/tc3589x.c	2012-01-04 18:55:44.000000000 -0500
@@ -357,6 +357,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
 static int tc3589x_suspend(struct device *dev)
 {
 	struct tc3589x *tc3589x = dev_get_drvdata(dev);
@@ -387,6 +388,7 @@
 
 static const SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend,
 						tc3589x_resume);
+#endif
 
 static const struct i2c_device_id tc3589x_id[] = {
 	{ "tc3589x", 24 },
diff -druN linux-libre-3.1-gnu/drivers/mfd/timberdale.c linux-libre-3.2-gnu/drivers/mfd/timberdale.c
--- linux-libre-3.1-gnu/drivers/mfd/timberdale.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/timberdale.c	2012-01-04 18:55:44.000000000 -0500
@@ -697,7 +697,7 @@
 		dev_err(&dev->dev, "The driver supports an older "
 			"version of the FPGA, please update the driver to "
 			"support %d.%d\n", priv->fw.major, priv->fw.minor);
-		goto err_ioremap;
+		goto err_config;
 	}
 	if (priv->fw.major < TIMB_SUPPORTED_MAJOR ||
 		priv->fw.minor < TIMB_REQUIRED_MINOR) {
@@ -705,13 +705,13 @@
 			"please upgrade the FPGA to at least: %d.%d\n",
 			priv->fw.major, priv->fw.minor,
 			TIMB_SUPPORTED_MAJOR, TIMB_REQUIRED_MINOR);
-		goto err_ioremap;
+		goto err_config;
 	}
 
 	msix_entries = kzalloc(TIMBERDALE_NR_IRQS * sizeof(*msix_entries),
 		GFP_KERNEL);
 	if (!msix_entries)
-		goto err_ioremap;
+		goto err_config;
 
 	for (i = 0; i < TIMBERDALE_NR_IRQS; i++)
 		msix_entries[i].entry = i;
@@ -825,6 +825,8 @@
 err_create_file:
 	pci_disable_msix(dev);
 err_msix:
+	kfree(msix_entries);
+err_config:
 	iounmap(priv->ctl_membase);
 err_ioremap:
 	release_mem_region(priv->ctl_mapbase, CHIPCTLSIZE);
@@ -833,7 +835,6 @@
 err_start:
 	pci_disable_device(dev);
 err_enable:
-	kfree(msix_entries);
 	kfree(priv);
 	pci_set_drvdata(dev, NULL);
 	return -ENODEV;
diff -druN linux-libre-3.1-gnu/drivers/mfd/tmio_core.c linux-libre-3.2-gnu/drivers/mfd/tmio_core.c
--- linux-libre-3.1-gnu/drivers/mfd/tmio_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/tmio_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -6,6 +6,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/export.h>
 #include <linux/mfd/tmio.h>
 
 int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base)
diff -druN linux-libre-3.1-gnu/drivers/mfd/tps6586x.c linux-libre-3.2-gnu/drivers/mfd/tps6586x.c
--- linux-libre-3.1-gnu/drivers/mfd/tps6586x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/tps6586x.c	2012-01-04 18:55:44.000000000 -0500
@@ -197,7 +197,7 @@
 	if (ret)
 		goto out;
 
-	if ((reg_val & bit_mask) == 0) {
+	if ((reg_val & bit_mask) != bit_mask) {
 		reg_val |= bit_mask;
 		ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val);
 	}
diff -druN linux-libre-3.1-gnu/drivers/mfd/tps65910.c linux-libre-3.2-gnu/drivers/mfd/tps65910.c
--- linux-libre-3.1-gnu/drivers/mfd/tps65910.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/tps65910.c	2012-01-04 18:55:44.000000000 -0500
@@ -120,7 +120,7 @@
 		goto out;
 	}
 
-	data &= mask;
+	data &= ~mask;
 	err = tps65910_i2c_write(tps65910, reg, 1, &data);
 	if (err)
 		dev_err(tps65910->dev, "write to reg %x failed\n", reg);
diff -druN linux-libre-3.1-gnu/drivers/mfd/tps65912-core.c linux-libre-3.2-gnu/drivers/mfd/tps65912-core.c
--- linux-libre-3.1-gnu/drivers/mfd/tps65912-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/tps65912-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -131,9 +131,6 @@
 	if (init_data == NULL)
 		return -ENOMEM;
 
-	init_data->irq = pmic_plat_data->irq;
-	init_data->irq_base = pmic_plat_data->irq;
-
 	mutex_init(&tps65912->io_mutex);
 	dev_set_drvdata(tps65912->dev, tps65912);
 
@@ -153,10 +150,13 @@
 	if (ret < 0)
 		goto err;
 
+	init_data->irq = pmic_plat_data->irq;
+	init_data->irq_base = pmic_plat_data->irq;
 	ret = tps65912_irq_init(tps65912, init_data->irq, init_data);
 	if (ret < 0)
 		goto err;
 
+	kfree(init_data);
 	return ret;
 
 err:
diff -druN linux-libre-3.1-gnu/drivers/mfd/twl4030-irq.c linux-libre-3.2-gnu/drivers/mfd/twl4030-irq.c
--- linux-libre-3.1-gnu/drivers/mfd/twl4030-irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/twl4030-irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,6 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/kthread.h>
 #include <linux/slab.h>
 
 #include <linux/i2c/twl.h>
@@ -278,59 +277,6 @@
 
 static unsigned twl4030_irq_base;
 
-static struct completion irq_event;
-
-/*
- * This thread processes interrupts reported by the Primary Interrupt Handler.
- */
-static int twl4030_irq_thread(void *data)
-{
-	long irq = (long)data;
-	static unsigned i2c_errors;
-	static const unsigned max_i2c_errors = 100;
-
-
-	current->flags |= PF_NOFREEZE;
-
-	while (!kthread_should_stop()) {
-		int ret;
-		int module_irq;
-		u8 pih_isr;
-
-		/* Wait for IRQ, then read PIH irq status (also blocking) */
-		wait_for_completion_interruptible(&irq_event);
-
-		ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
-					  REG_PIH_ISR_P1);
-		if (ret) {
-			pr_warning("twl4030: I2C error %d reading PIH ISR\n",
-					ret);
-			if (++i2c_errors >= max_i2c_errors) {
-				printk(KERN_ERR "Maximum I2C error count"
-						" exceeded.  Terminating %s.\n",
-						__func__);
-				break;
-			}
-			complete(&irq_event);
-			continue;
-		}
-
-		/* these handlers deal with the relevant SIH irq status */
-		local_irq_disable();
-		for (module_irq = twl4030_irq_base;
-				pih_isr;
-				pih_isr >>= 1, module_irq++) {
-			if (pih_isr & 0x1)
-				generic_handle_irq(module_irq);
-		}
-		local_irq_enable();
-
-		enable_irq(irq);
-	}
-
-	return 0;
-}
-
 /*
  * handle_twl4030_pih() is the desc->handle method for the twl4030 interrupt.
  * This is a chained interrupt, so there is no desc->action method for it.
@@ -342,9 +288,25 @@
  */
 static irqreturn_t handle_twl4030_pih(int irq, void *devid)
 {
-	/* Acknowledge, clear *AND* mask the interrupt... */
-	disable_irq_nosync(irq);
-	complete(devid);
+	int		module_irq;
+	irqreturn_t	ret;
+	u8		pih_isr;
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
+			REG_PIH_ISR_P1);
+	if (ret) {
+		pr_warning("twl4030: I2C error %d reading PIH ISR\n", ret);
+		return IRQ_NONE;
+	}
+
+	/* these handlers deal with the relevant SIH irq status */
+	for (module_irq = twl4030_irq_base;
+			pih_isr;
+			pih_isr >>= 1, module_irq++) {
+		if (pih_isr & 0x1)
+			handle_nested_irq(module_irq);
+	}
+
 	return IRQ_HANDLED;
 }
 /*----------------------------------------------------------------------*/
@@ -460,113 +422,18 @@
 
 /*----------------------------------------------------------------------*/
 
-static DEFINE_SPINLOCK(sih_agent_lock);
-
-static struct workqueue_struct *wq;
-
 struct sih_agent {
 	int			irq_base;
 	const struct sih	*sih;
 
 	u32			imr;
 	bool			imr_change_pending;
-	struct work_struct	mask_work;
-
-	u32			edge_change;
-	struct work_struct	edge_work;
-};
-
-static void twl4030_sih_do_mask(struct work_struct *work)
-{
-	struct sih_agent	*agent;
-	const struct sih	*sih;
-	union {
-		u8	bytes[4];
-		u32	word;
-	}			imr;
-	int			status;
-
-	agent = container_of(work, struct sih_agent, mask_work);
-
-	/* see what work we have */
-	spin_lock_irq(&sih_agent_lock);
-	if (agent->imr_change_pending) {
-		sih = agent->sih;
-		/* byte[0] gets overwritten as we write ... */
-		imr.word = cpu_to_le32(agent->imr << 8);
-		agent->imr_change_pending = false;
-	} else
-		sih = NULL;
-	spin_unlock_irq(&sih_agent_lock);
-	if (!sih)
-		return;
 
-	/* write the whole mask ... simpler than subsetting it */
-	status = twl_i2c_write(sih->module, imr.bytes,
-			sih->mask[irq_line].imr_offset, sih->bytes_ixr);
-	if (status)
-		pr_err("twl4030: %s, %s --> %d\n", __func__,
-				"write", status);
-}
-
-static void twl4030_sih_do_edge(struct work_struct *work)
-{
-	struct sih_agent	*agent;
-	const struct sih	*sih;
-	u8			bytes[6];
 	u32			edge_change;
-	int			status;
-
-	agent = container_of(work, struct sih_agent, edge_work);
-
-	/* see what work we have */
-	spin_lock_irq(&sih_agent_lock);
-	edge_change = agent->edge_change;
-	agent->edge_change = 0;
-	sih = edge_change ? agent->sih : NULL;
-	spin_unlock_irq(&sih_agent_lock);
-	if (!sih)
-		return;
-
-	/* Read, reserving first byte for write scratch.  Yes, this
-	 * could be cached for some speedup ... but be careful about
-	 * any processor on the other IRQ line, EDR registers are
-	 * shared.
-	 */
-	status = twl_i2c_read(sih->module, bytes + 1,
-			sih->edr_offset, sih->bytes_edr);
-	if (status) {
-		pr_err("twl4030: %s, %s --> %d\n", __func__,
-				"read", status);
-		return;
-	}
-
-	/* Modify only the bits we know must change */
-	while (edge_change) {
-		int		i = fls(edge_change) - 1;
-		struct irq_data	*idata = irq_get_irq_data(i + agent->irq_base);
-		int		byte = 1 + (i >> 2);
-		int		off = (i & 0x3) * 2;
-		unsigned int	type;
-
-		bytes[byte] &= ~(0x03 << off);
-
-		type = irqd_get_trigger_type(idata);
-		if (type & IRQ_TYPE_EDGE_RISING)
-			bytes[byte] |= BIT(off + 1);
-		if (type & IRQ_TYPE_EDGE_FALLING)
-			bytes[byte] |= BIT(off + 0);
-
-		edge_change &= ~BIT(i);
-	}
 
-	/* Write */
-	status = twl_i2c_write(sih->module, bytes,
-			sih->edr_offset, sih->bytes_edr);
-	if (status)
-		pr_err("twl4030: %s, %s --> %d\n", __func__,
-				"write", status);
-}
+	struct mutex		irq_lock;
+	char			*irq_name;
+};
 
 /*----------------------------------------------------------------------*/
 
@@ -579,50 +446,125 @@
 
 static void twl4030_sih_mask(struct irq_data *data)
 {
-	struct sih_agent *sih = irq_data_get_irq_chip_data(data);
-	unsigned long flags;
+	struct sih_agent *agent = irq_data_get_irq_chip_data(data);
 
-	spin_lock_irqsave(&sih_agent_lock, flags);
-	sih->imr |= BIT(data->irq - sih->irq_base);
-	sih->imr_change_pending = true;
-	queue_work(wq, &sih->mask_work);
-	spin_unlock_irqrestore(&sih_agent_lock, flags);
+	agent->imr |= BIT(data->irq - agent->irq_base);
+	agent->imr_change_pending = true;
 }
 
 static void twl4030_sih_unmask(struct irq_data *data)
 {
-	struct sih_agent *sih = irq_data_get_irq_chip_data(data);
-	unsigned long flags;
+	struct sih_agent *agent = irq_data_get_irq_chip_data(data);
 
-	spin_lock_irqsave(&sih_agent_lock, flags);
-	sih->imr &= ~BIT(data->irq - sih->irq_base);
-	sih->imr_change_pending = true;
-	queue_work(wq, &sih->mask_work);
-	spin_unlock_irqrestore(&sih_agent_lock, flags);
+	agent->imr &= ~BIT(data->irq - agent->irq_base);
+	agent->imr_change_pending = true;
 }
 
 static int twl4030_sih_set_type(struct irq_data *data, unsigned trigger)
 {
-	struct sih_agent *sih = irq_data_get_irq_chip_data(data);
-	unsigned long flags;
+	struct sih_agent *agent = irq_data_get_irq_chip_data(data);
 
 	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
 		return -EINVAL;
 
-	spin_lock_irqsave(&sih_agent_lock, flags);
-	if (irqd_get_trigger_type(data) != trigger) {
-		sih->edge_change |= BIT(data->irq - sih->irq_base);
-		queue_work(wq, &sih->edge_work);
-	}
-	spin_unlock_irqrestore(&sih_agent_lock, flags);
+	if (irqd_get_trigger_type(data) != trigger)
+		agent->edge_change |= BIT(data->irq - agent->irq_base);
+
 	return 0;
 }
 
+static void twl4030_sih_bus_lock(struct irq_data *data)
+{
+	struct sih_agent	*agent = irq_data_get_irq_chip_data(data);
+
+	mutex_lock(&agent->irq_lock);
+}
+
+static void twl4030_sih_bus_sync_unlock(struct irq_data *data)
+{
+	struct sih_agent	*agent = irq_data_get_irq_chip_data(data);
+	const struct sih	*sih = agent->sih;
+	int			status;
+
+	if (agent->imr_change_pending) {
+		union {
+			u32	word;
+			u8	bytes[4];
+		} imr;
+
+		/* byte[0] gets overwriten as we write ... */
+		imr.word = cpu_to_le32(agent->imr << 8);
+		agent->imr_change_pending = false;
+
+		/* write the whole mask ... simpler than subsetting it */
+		status = twl_i2c_write(sih->module, imr.bytes,
+				sih->mask[irq_line].imr_offset,
+				sih->bytes_ixr);
+		if (status)
+			pr_err("twl4030: %s, %s --> %d\n", __func__,
+					"write", status);
+	}
+
+	if (agent->edge_change) {
+		u32		edge_change;
+		u8		bytes[6];
+
+		edge_change = agent->edge_change;
+		agent->edge_change = 0;
+
+		/*
+		 * Read, reserving first byte for write scratch.  Yes, this
+		 * could be cached for some speedup ... but be careful about
+		 * any processor on the other IRQ line, EDR registers are
+		 * shared.
+		 */
+		status = twl_i2c_read(sih->module, bytes + 1,
+				sih->edr_offset, sih->bytes_edr);
+		if (status) {
+			pr_err("twl4030: %s, %s --> %d\n", __func__,
+					"read", status);
+			return;
+		}
+
+		/* Modify only the bits we know must change */
+		while (edge_change) {
+			int		i = fls(edge_change) - 1;
+			struct irq_data	*idata;
+			int		byte = 1 + (i >> 2);
+			int		off = (i & 0x3) * 2;
+			unsigned int	type;
+
+			idata = irq_get_irq_data(i + agent->irq_base);
+
+			bytes[byte] &= ~(0x03 << off);
+
+			type = irqd_get_trigger_type(idata);
+			if (type & IRQ_TYPE_EDGE_RISING)
+				bytes[byte] |= BIT(off + 1);
+			if (type & IRQ_TYPE_EDGE_FALLING)
+				bytes[byte] |= BIT(off + 0);
+
+			edge_change &= ~BIT(i);
+		}
+
+		/* Write */
+		status = twl_i2c_write(sih->module, bytes,
+				sih->edr_offset, sih->bytes_edr);
+		if (status)
+			pr_err("twl4030: %s, %s --> %d\n", __func__,
+					"write", status);
+	}
+
+	mutex_unlock(&agent->irq_lock);
+}
+
 static struct irq_chip twl4030_sih_irq_chip = {
 	.name		= "twl4030",
-	.irq_mask      	= twl4030_sih_mask,
+	.irq_mask	= twl4030_sih_mask,
 	.irq_unmask	= twl4030_sih_unmask,
 	.irq_set_type	= twl4030_sih_set_type,
+	.irq_bus_lock	= twl4030_sih_bus_lock,
+	.irq_bus_sync_unlock = twl4030_sih_bus_sync_unlock,
 };
 
 /*----------------------------------------------------------------------*/
@@ -648,22 +590,20 @@
  * Generic handler for SIH interrupts ... we "know" this is called
  * in task context, with IRQs enabled.
  */
-static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc)
+static irqreturn_t handle_twl4030_sih(int irq, void *data)
 {
 	struct sih_agent *agent = irq_get_handler_data(irq);
 	const struct sih *sih = agent->sih;
 	int isr;
 
 	/* reading ISR acks the IRQs, using clear-on-read mode */
-	local_irq_enable();
 	isr = sih_read_isr(sih);
-	local_irq_disable();
 
 	if (isr < 0) {
 		pr_err("twl4030: %s SIH, read ISR error %d\n",
 			sih->name, isr);
 		/* REVISIT:  recover; eventually mask it all, etc */
-		return;
+		return IRQ_HANDLED;
 	}
 
 	while (isr) {
@@ -672,11 +612,12 @@
 		isr &= ~BIT(irq);
 
 		if (irq < sih->bits)
-			generic_handle_irq(agent->irq_base + irq);
+			handle_nested_irq(agent->irq_base + irq);
 		else
 			pr_err("twl4030: %s SIH, invalid ISR bit %d\n",
 				sih->name, irq);
 	}
+	return IRQ_HANDLED;
 }
 
 static unsigned twl4030_irq_next;
@@ -718,30 +659,30 @@
 	agent->irq_base = irq_base;
 	agent->sih = sih;
 	agent->imr = ~0;
-	INIT_WORK(&agent->mask_work, twl4030_sih_do_mask);
-	INIT_WORK(&agent->edge_work, twl4030_sih_do_edge);
+	mutex_init(&agent->irq_lock);
 
 	for (i = 0; i < sih->bits; i++) {
 		irq = irq_base + i;
 
+		irq_set_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);
 	}
 
-	status = irq_base;
 	twl4030_irq_next += i;
 
 	/* replace generic PIH handler (handle_simple_irq) */
 	irq = sih_mod + twl4030_irq_base;
 	irq_set_handler_data(irq, agent);
-	irq_set_chained_handler(irq, handle_twl4030_sih);
+	agent->irq_name = kasprintf(GFP_KERNEL, "twl4030_%s", sih->name);
+	status = request_threaded_irq(irq, NULL, handle_twl4030_sih, 0,
+				      agent->irq_name ?: sih->name, NULL);
 
 	pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name,
 			irq, irq_base, twl4030_irq_next - 1);
 
-	return status;
+	return status < 0 ? status : irq_base;
 }
 
 /* FIXME need a call to reverse twl4030_sih_setup() ... */
@@ -758,7 +699,6 @@
 
 	int			status;
 	int			i;
-	struct task_struct	*task;
 
 	/*
 	 * Mask and clear all TWL4030 interrupts since initially we do
@@ -768,12 +708,6 @@
 	if (status < 0)
 		return status;
 
-	wq = create_singlethread_workqueue("twl4030-irqchip");
-	if (!wq) {
-		pr_err("twl4030: workqueue FAIL\n");
-		return -ESRCH;
-	}
-
 	twl4030_irq_base = irq_base;
 
 	/* install an irq handler for each of the SIH modules;
@@ -787,6 +721,7 @@
 	for (i = irq_base; i < irq_end; i++) {
 		irq_set_chip_and_handler(i, &twl4030_irq_chip,
 					 handle_simple_irq);
+		irq_set_nested_thread(i, 1);
 		activate_irq(i);
 	}
 	twl4030_irq_next = i;
@@ -801,34 +736,23 @@
 	}
 
 	/* install an irq handler to demultiplex the TWL4030 interrupt */
-
-
-	init_completion(&irq_event);
-
-	status = request_irq(irq_num, handle_twl4030_pih, IRQF_DISABLED,
-				"TWL4030-PIH", &irq_event);
+	status = request_threaded_irq(irq_num, NULL, handle_twl4030_pih,
+				      IRQF_ONESHOT,
+				      "TWL4030-PIH", NULL);
 	if (status < 0) {
 		pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status);
 		goto fail_rqirq;
 	}
 
-	task = kthread_run(twl4030_irq_thread, (void *)(long)irq_num,
-								"twl4030-irq");
-	if (IS_ERR(task)) {
-		pr_err("twl4030: could not create irq %d thread!\n", irq_num);
-		status = PTR_ERR(task);
-		goto fail_kthread;
-	}
 	return status;
-fail_kthread:
-	free_irq(irq_num, &irq_event);
 fail_rqirq:
 	/* clean up twl4030_sih_setup */
 fail:
-	for (i = irq_base; i < irq_end; i++)
+	for (i = irq_base; i < irq_end; i++) {
+		irq_set_nested_thread(i, 0);
 		irq_set_chip_and_handler(i, NULL, NULL);
-	destroy_workqueue(wq);
-	wq = NULL;
+	}
+
 	return status;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/mfd/twl4030-madc.c linux-libre-3.2-gnu/drivers/mfd/twl4030-madc.c
--- linux-libre-3.1-gnu/drivers/mfd/twl4030-madc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/twl4030-madc.c	2012-01-04 18:55:44.000000000 -0500
@@ -740,6 +740,28 @@
 			TWL4030_BCI_BCICTL1);
 		goto err_i2c;
 	}
+
+	/* Check that MADC clock is on */
+	ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &regval, TWL4030_REG_GPBR1);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to read reg GPBR1 0x%X\n",
+				TWL4030_REG_GPBR1);
+		goto err_i2c;
+	}
+
+	/* If MADC clk is not on, turn it on */
+	if (!(regval & TWL4030_GPBR1_MADC_HFCLK_EN)) {
+		dev_info(&pdev->dev, "clk disabled, enabling\n");
+		regval |= TWL4030_GPBR1_MADC_HFCLK_EN;
+		ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, regval,
+				       TWL4030_REG_GPBR1);
+		if (ret) {
+			dev_err(&pdev->dev, "unable to write reg GPBR1 0x%X\n",
+					TWL4030_REG_GPBR1);
+			goto err_i2c;
+		}
+	}
+
 	platform_set_drvdata(pdev, madc);
 	mutex_init(&madc->lock);
 	ret = request_threaded_irq(platform_get_irq(pdev, 0), NULL,
diff -druN linux-libre-3.1-gnu/drivers/mfd/twl6030-irq.c linux-libre-3.2-gnu/drivers/mfd/twl6030-irq.c
--- linux-libre-3.1-gnu/drivers/mfd/twl6030-irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/twl6030-irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,11 +32,13 @@
  */
 
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/kthread.h>
 #include <linux/i2c/twl.h>
 #include <linux/platform_device.h>
+#include <linux/suspend.h>
 
 #include "twl-core.h"
 
@@ -83,8 +85,48 @@
 /*----------------------------------------------------------------------*/
 
 static unsigned twl6030_irq_base;
+static int twl_irq;
+static bool twl_irq_wake_enabled;
 
 static struct completion irq_event;
+static atomic_t twl6030_wakeirqs = ATOMIC_INIT(0);
+
+static int twl6030_irq_pm_notifier(struct notifier_block *notifier,
+				   unsigned long pm_event, void *unused)
+{
+	int chained_wakeups;
+
+	switch (pm_event) {
+	case PM_SUSPEND_PREPARE:
+		chained_wakeups = atomic_read(&twl6030_wakeirqs);
+
+		if (chained_wakeups && !twl_irq_wake_enabled) {
+			if (enable_irq_wake(twl_irq))
+				pr_err("twl6030 IRQ wake enable failed\n");
+			else
+				twl_irq_wake_enabled = true;
+		} else if (!chained_wakeups && twl_irq_wake_enabled) {
+			disable_irq_wake(twl_irq);
+			twl_irq_wake_enabled = false;
+		}
+
+		disable_irq(twl_irq);
+		break;
+
+	case PM_POST_SUSPEND:
+		enable_irq(twl_irq);
+		break;
+
+	default:
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block twl6030_irq_pm_notifier_block = {
+	.notifier_call = twl6030_irq_pm_notifier,
+};
 
 /*
  * This thread processes interrupts reported by the Primary Interrupt Handler.
@@ -187,6 +229,16 @@
 #endif
 }
 
+int twl6030_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+	if (on)
+		atomic_inc(&twl6030_wakeirqs);
+	else
+		atomic_dec(&twl6030_wakeirqs);
+
+	return 0;
+}
+
 /*----------------------------------------------------------------------*/
 
 static unsigned twl6030_irq_next;
@@ -318,10 +370,12 @@
 	twl6030_irq_chip = dummy_irq_chip;
 	twl6030_irq_chip.name = "twl6030";
 	twl6030_irq_chip.irq_set_type = NULL;
+	twl6030_irq_chip.irq_set_wake = twl6030_irq_set_wake;
 
 	for (i = irq_base; i < irq_end; i++) {
 		irq_set_chip_and_handler(i, &twl6030_irq_chip,
 					 handle_simple_irq);
+		irq_set_chip_data(i, (void *)irq_num);
 		activate_irq(i);
 	}
 
@@ -331,6 +385,14 @@
 
 	/* install an irq handler to demultiplex the TWL6030 interrupt */
 	init_completion(&irq_event);
+
+	status = request_irq(irq_num, handle_twl6030_pih, 0,
+				"TWL6030-PIH", &irq_event);
+	if (status < 0) {
+		pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status);
+		goto fail_irq;
+	}
+
 	task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq");
 	if (IS_ERR(task)) {
 		pr_err("twl6030: could not create irq %d thread!\n", irq_num);
@@ -338,17 +400,14 @@
 		goto fail_kthread;
 	}
 
-	status = request_irq(irq_num, handle_twl6030_pih, IRQF_DISABLED,
-				"TWL6030-PIH", &irq_event);
-	if (status < 0) {
-		pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status);
-		goto fail_irq;
-	}
+	twl_irq = irq_num;
+	register_pm_notifier(&twl6030_irq_pm_notifier_block);
 	return status;
-fail_irq:
-	free_irq(irq_num, &irq_event);
 
 fail_kthread:
+	free_irq(irq_num, &irq_event);
+
+fail_irq:
 	for (i = irq_base; i < irq_end; i++)
 		irq_set_chip_and_handler(i, NULL, NULL);
 	return status;
@@ -356,6 +415,7 @@
 
 int twl6030_exit_irq(void)
 {
+	unregister_pm_notifier(&twl6030_irq_pm_notifier_block);
 
 	if (twl6030_irq_base) {
 		pr_err("twl6030: can't yet clean up IRQs?\n");
diff -druN linux-libre-3.1-gnu/drivers/mfd/twl6040-core.c linux-libre-3.2-gnu/drivers/mfd/twl6040-core.c
--- linux-libre-3.1-gnu/drivers/mfd/twl6040-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/twl6040-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,7 +34,7 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/twl6040.h>
 
-static struct platform_device *twl6040_dev;
+#define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1)
 
 int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
 {
@@ -42,10 +42,16 @@
 	u8 val = 0;
 
 	mutex_lock(&twl6040->io_mutex);
-	ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
-	if (ret < 0) {
-		mutex_unlock(&twl6040->io_mutex);
-		return ret;
+	/* Vibra control registers from cache */
+	if (unlikely(reg == TWL6040_REG_VIBCTLL ||
+		     reg == TWL6040_REG_VIBCTLR)) {
+		val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)];
+	} else {
+		ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
+		if (ret < 0) {
+			mutex_unlock(&twl6040->io_mutex);
+			return ret;
+		}
 	}
 	mutex_unlock(&twl6040->io_mutex);
 
@@ -59,6 +65,9 @@
 
 	mutex_lock(&twl6040->io_mutex);
 	ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
+	/* Cache the vibra control registers */
+	if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR)
+		twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val;
 	mutex_unlock(&twl6040->io_mutex);
 
 	return ret;
@@ -203,11 +212,11 @@
 	if (intid & TWL6040_THINT) {
 		status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS);
 		if (status & TWL6040_TSHUTDET) {
-			dev_warn(&twl6040_dev->dev,
+			dev_warn(twl6040->dev,
 				 "Thermal shutdown, powering-off");
 			twl6040_power(twl6040, 0);
 		} else {
-			dev_warn(&twl6040_dev->dev,
+			dev_warn(twl6040->dev,
 				 "Leaving thermal shutdown, powering-on");
 			twl6040_power(twl6040, 1);
 		}
@@ -227,7 +236,7 @@
 	if (!time_left) {
 		intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
 		if (!(intid & TWL6040_READYINT)) {
-			dev_err(&twl6040_dev->dev,
+			dev_err(twl6040->dev,
 				"timeout waiting for READYINT\n");
 			return -ETIMEDOUT;
 		}
@@ -255,7 +264,7 @@
 			/* wait for power-up completion */
 			ret = twl6040_power_up_completion(twl6040, naudint);
 			if (ret) {
-				dev_err(&twl6040_dev->dev,
+				dev_err(twl6040->dev,
 					"automatic power-down failed\n");
 				twl6040->power_count = 0;
 				goto out;
@@ -264,7 +273,7 @@
 			/* use manual power-up sequence */
 			ret = twl6040_power_up(twl6040);
 			if (ret) {
-				dev_err(&twl6040_dev->dev,
+				dev_err(twl6040->dev,
 					"manual power-up failed\n");
 				twl6040->power_count = 0;
 				goto out;
@@ -276,7 +285,7 @@
 	} else {
 		/* already powered-down */
 		if (!twl6040->power_count) {
-			dev_err(&twl6040_dev->dev,
+			dev_err(twl6040->dev,
 				"device is already powered-off\n");
 			ret = -EPERM;
 			goto out;
@@ -326,7 +335,7 @@
 			lppllctl &= ~TWL6040_LPLLFIN;
 			break;
 		default:
-			dev_err(&twl6040_dev->dev,
+			dev_err(twl6040->dev,
 				"freq_out %d not supported\n", freq_out);
 			ret = -EINVAL;
 			goto pll_out;
@@ -347,7 +356,7 @@
 					  hppllctl);
 			break;
 		default:
-			dev_err(&twl6040_dev->dev,
+			dev_err(twl6040->dev,
 				"freq_in %d not supported\n", freq_in);
 			ret = -EINVAL;
 			goto pll_out;
@@ -356,7 +365,7 @@
 	case TWL6040_SYSCLK_SEL_HPPLL:
 		/* high-performance PLL can provide only 19.2 MHz */
 		if (freq_out != 19200000) {
-			dev_err(&twl6040_dev->dev,
+			dev_err(twl6040->dev,
 				"freq_out %d not supported\n", freq_out);
 			ret = -EINVAL;
 			goto pll_out;
@@ -389,7 +398,7 @@
 				    TWL6040_HPLLENA;
 			break;
 		default:
-			dev_err(&twl6040_dev->dev,
+			dev_err(twl6040->dev,
 				"freq_in %d not supported\n", freq_in);
 			ret = -EINVAL;
 			goto pll_out;
@@ -406,7 +415,7 @@
 		twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
 		break;
 	default:
-		dev_err(&twl6040_dev->dev, "unknown pll id %d\n", pll_id);
+		dev_err(twl6040->dev, "unknown pll id %d\n", pll_id);
 		ret = -EINVAL;
 		goto pll_out;
 	}
@@ -435,6 +444,18 @@
 }
 EXPORT_SYMBOL(twl6040_get_sysclk);
 
+/* Get the combined status of the vibra control register */
+int twl6040_get_vibralr_status(struct twl6040 *twl6040)
+{
+	u8 status;
+
+	status = twl6040->vibra_ctrl_cache[0] | twl6040->vibra_ctrl_cache[1];
+	status &= (TWL6040_VIBENA | TWL6040_VIBSEL);
+
+	return status;
+}
+EXPORT_SYMBOL(twl6040_get_vibralr_status);
+
 static struct resource twl6040_vibra_rsrc[] = {
 	{
 		.flags = IORESOURCE_IRQ,
@@ -471,9 +492,7 @@
 
 	platform_set_drvdata(pdev, twl6040);
 
-	twl6040_dev = pdev;
 	twl6040->dev = &pdev->dev;
-	twl6040->audpwron = pdata->audpwron_gpio;
 	twl6040->irq = pdata->naudint_irq;
 	twl6040->irq_base = pdata->irq_base;
 
@@ -483,6 +502,12 @@
 
 	twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
 
+	/* ERRATA: Automatic power-up is not possible in ES1.0 */
+	if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0)
+		twl6040->audpwron = pdata->audpwron_gpio;
+	else
+		twl6040->audpwron = -EINVAL;
+
 	if (gpio_is_valid(twl6040->audpwron)) {
 		ret = gpio_request(twl6040->audpwron, "audpwron");
 		if (ret)
@@ -493,10 +518,6 @@
 			goto gpio2_err;
 	}
 
-	/* ERRATA: Automatic power-up is not possible in ES1.0 */
-	if (twl6040->rev == TWL6040_REV_ES1_0)
-		twl6040->audpwron = -EINVAL;
-
 	/* codec interrupt */
 	ret = twl6040_irq_init(twl6040);
 	if (ret)
@@ -566,7 +587,6 @@
 gpio1_err:
 	platform_set_drvdata(pdev, NULL);
 	kfree(twl6040);
-	twl6040_dev = NULL;
 	return ret;
 }
 
@@ -586,7 +606,6 @@
 	mfd_remove_devices(&pdev->dev);
 	platform_set_drvdata(pdev, NULL);
 	kfree(twl6040);
-	twl6040_dev = NULL;
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/mfd/twl-core.c linux-libre-3.2-gnu/drivers/mfd/twl-core.c
--- linux-libre-3.1-gnu/drivers/mfd/twl-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/twl-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 
 #include <linux/init.h>
 #include <linux/mutex.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/err.h>
@@ -109,7 +110,7 @@
 #define twl_has_watchdog()        false
 #endif
 
-#if defined(CONFIG_TWL4030_CODEC) || defined(CONFIG_TWL4030_CODEC_MODULE) ||\
+#if defined(CONFIG_MFD_TWL4030_AUDIO) || defined(CONFIG_MFD_TWL4030_AUDIO_MODULE) ||\
 	defined(CONFIG_TWL6040_CORE) || defined(CONFIG_TWL6040_CORE_MODULE)
 #define twl_has_codec()	true
 #else
@@ -362,13 +363,13 @@
 		pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
 		return -EPERM;
 	}
-	sid = twl_map[mod_no].sid;
-	twl = &twl_modules[sid];
-
 	if (unlikely(!inuse)) {
-		pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid);
+		pr_err("%s: not initialized\n", DRIVER_NAME);
 		return -EPERM;
 	}
+	sid = twl_map[mod_no].sid;
+	twl = &twl_modules[sid];
+
 	mutex_lock(&twl->xfer_lock);
 	/*
 	 * [MSG1]: fill the register address data
@@ -419,13 +420,13 @@
 		pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
 		return -EPERM;
 	}
-	sid = twl_map[mod_no].sid;
-	twl = &twl_modules[sid];
-
 	if (unlikely(!inuse)) {
-		pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid);
+		pr_err("%s: not initialized\n", DRIVER_NAME);
 		return -EPERM;
 	}
+	sid = twl_map[mod_no].sid;
+	twl = &twl_modules[sid];
+
 	mutex_lock(&twl->xfer_lock);
 	/* [MSG1] fill the register address data */
 	msg = &twl->xfer_msg[0];
diff -druN linux-libre-3.1-gnu/drivers/mfd/wl1273-core.c linux-libre-3.2-gnu/drivers/mfd/wl1273-core.c
--- linux-libre-3.1-gnu/drivers/mfd/wl1273-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/wl1273-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 
 #include <linux/mfd/wl1273-core.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #define DRIVER_DESC "WL1273 FM Radio Core"
 
diff -druN linux-libre-3.1-gnu/drivers/mfd/wm831x-core.c linux-libre-3.2-gnu/drivers/mfd/wm831x-core.c
--- linux-libre-3.1-gnu/drivers/mfd/wm831x-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/wm831x-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,12 +18,14 @@
 #include <linux/delay.h>
 #include <linux/mfd/core.h>
 #include <linux/slab.h>
+#include <linux/err.h>
 
 #include <linux/mfd/wm831x/core.h>
 #include <linux/mfd/wm831x/pdata.h>
 #include <linux/mfd/wm831x/irq.h>
 #include <linux/mfd/wm831x/auxadc.h>
 #include <linux/mfd/wm831x/otp.h>
+#include <linux/mfd/wm831x/pmu.h>
 #include <linux/mfd/wm831x/regulator.h>
 
 /* Current settings - values are 2*2^(reg_val/4) microamps.  These are
@@ -160,27 +162,350 @@
 }
 EXPORT_SYMBOL_GPL(wm831x_reg_unlock);
 
-static int wm831x_read(struct wm831x *wm831x, unsigned short reg,
-		       int bytes, void *dest)
+static bool wm831x_reg_readable(struct device *dev, unsigned int reg)
 {
-	int ret, i;
-	u16 *buf = dest;
-
-	BUG_ON(bytes % 2);
-	BUG_ON(bytes <= 0);
+	switch (reg) {
+	case WM831X_RESET_ID:
+	case WM831X_REVISION:
+	case WM831X_PARENT_ID:
+	case WM831X_SYSVDD_CONTROL:
+	case WM831X_THERMAL_MONITORING:
+	case WM831X_POWER_STATE:
+	case WM831X_WATCHDOG:
+	case WM831X_ON_PIN_CONTROL:
+	case WM831X_RESET_CONTROL:
+	case WM831X_CONTROL_INTERFACE:
+	case WM831X_SECURITY_KEY:
+	case WM831X_SOFTWARE_SCRATCH:
+	case WM831X_OTP_CONTROL:
+	case WM831X_GPIO_LEVEL:
+	case WM831X_SYSTEM_STATUS:
+	case WM831X_ON_SOURCE:
+	case WM831X_OFF_SOURCE:
+	case WM831X_SYSTEM_INTERRUPTS:
+	case WM831X_INTERRUPT_STATUS_1:
+	case WM831X_INTERRUPT_STATUS_2:
+	case WM831X_INTERRUPT_STATUS_3:
+	case WM831X_INTERRUPT_STATUS_4:
+	case WM831X_INTERRUPT_STATUS_5:
+	case WM831X_IRQ_CONFIG:
+	case WM831X_SYSTEM_INTERRUPTS_MASK:
+	case WM831X_INTERRUPT_STATUS_1_MASK:
+	case WM831X_INTERRUPT_STATUS_2_MASK:
+	case WM831X_INTERRUPT_STATUS_3_MASK:
+	case WM831X_INTERRUPT_STATUS_4_MASK:
+	case WM831X_INTERRUPT_STATUS_5_MASK:
+	case WM831X_RTC_WRITE_COUNTER:
+	case WM831X_RTC_TIME_1:
+	case WM831X_RTC_TIME_2:
+	case WM831X_RTC_ALARM_1:
+	case WM831X_RTC_ALARM_2:
+	case WM831X_RTC_CONTROL:
+	case WM831X_RTC_TRIM:
+	case WM831X_TOUCH_CONTROL_1:
+	case WM831X_TOUCH_CONTROL_2:
+	case WM831X_TOUCH_DATA_X:
+	case WM831X_TOUCH_DATA_Y:
+	case WM831X_TOUCH_DATA_Z:
+	case WM831X_AUXADC_DATA:
+	case WM831X_AUXADC_CONTROL:
+	case WM831X_AUXADC_SOURCE:
+	case WM831X_COMPARATOR_CONTROL:
+	case WM831X_COMPARATOR_1:
+	case WM831X_COMPARATOR_2:
+	case WM831X_COMPARATOR_3:
+	case WM831X_COMPARATOR_4:
+	case WM831X_GPIO1_CONTROL:
+	case WM831X_GPIO2_CONTROL:
+	case WM831X_GPIO3_CONTROL:
+	case WM831X_GPIO4_CONTROL:
+	case WM831X_GPIO5_CONTROL:
+	case WM831X_GPIO6_CONTROL:
+	case WM831X_GPIO7_CONTROL:
+	case WM831X_GPIO8_CONTROL:
+	case WM831X_GPIO9_CONTROL:
+	case WM831X_GPIO10_CONTROL:
+	case WM831X_GPIO11_CONTROL:
+	case WM831X_GPIO12_CONTROL:
+	case WM831X_GPIO13_CONTROL:
+	case WM831X_GPIO14_CONTROL:
+	case WM831X_GPIO15_CONTROL:
+	case WM831X_GPIO16_CONTROL:
+	case WM831X_CHARGER_CONTROL_1:
+	case WM831X_CHARGER_CONTROL_2:
+	case WM831X_CHARGER_STATUS:
+	case WM831X_BACKUP_CHARGER_CONTROL:
+	case WM831X_STATUS_LED_1:
+	case WM831X_STATUS_LED_2:
+	case WM831X_CURRENT_SINK_1:
+	case WM831X_CURRENT_SINK_2:
+	case WM831X_DCDC_ENABLE:
+	case WM831X_LDO_ENABLE:
+	case WM831X_DCDC_STATUS:
+	case WM831X_LDO_STATUS:
+	case WM831X_DCDC_UV_STATUS:
+	case WM831X_LDO_UV_STATUS:
+	case WM831X_DC1_CONTROL_1:
+	case WM831X_DC1_CONTROL_2:
+	case WM831X_DC1_ON_CONFIG:
+	case WM831X_DC1_SLEEP_CONTROL:
+	case WM831X_DC1_DVS_CONTROL:
+	case WM831X_DC2_CONTROL_1:
+	case WM831X_DC2_CONTROL_2:
+	case WM831X_DC2_ON_CONFIG:
+	case WM831X_DC2_SLEEP_CONTROL:
+	case WM831X_DC2_DVS_CONTROL:
+	case WM831X_DC3_CONTROL_1:
+	case WM831X_DC3_CONTROL_2:
+	case WM831X_DC3_ON_CONFIG:
+	case WM831X_DC3_SLEEP_CONTROL:
+	case WM831X_DC4_CONTROL:
+	case WM831X_DC4_SLEEP_CONTROL:
+	case WM831X_EPE1_CONTROL:
+	case WM831X_EPE2_CONTROL:
+	case WM831X_LDO1_CONTROL:
+	case WM831X_LDO1_ON_CONTROL:
+	case WM831X_LDO1_SLEEP_CONTROL:
+	case WM831X_LDO2_CONTROL:
+	case WM831X_LDO2_ON_CONTROL:
+	case WM831X_LDO2_SLEEP_CONTROL:
+	case WM831X_LDO3_CONTROL:
+	case WM831X_LDO3_ON_CONTROL:
+	case WM831X_LDO3_SLEEP_CONTROL:
+	case WM831X_LDO4_CONTROL:
+	case WM831X_LDO4_ON_CONTROL:
+	case WM831X_LDO4_SLEEP_CONTROL:
+	case WM831X_LDO5_CONTROL:
+	case WM831X_LDO5_ON_CONTROL:
+	case WM831X_LDO5_SLEEP_CONTROL:
+	case WM831X_LDO6_CONTROL:
+	case WM831X_LDO6_ON_CONTROL:
+	case WM831X_LDO6_SLEEP_CONTROL:
+	case WM831X_LDO7_CONTROL:
+	case WM831X_LDO7_ON_CONTROL:
+	case WM831X_LDO7_SLEEP_CONTROL:
+	case WM831X_LDO8_CONTROL:
+	case WM831X_LDO8_ON_CONTROL:
+	case WM831X_LDO8_SLEEP_CONTROL:
+	case WM831X_LDO9_CONTROL:
+	case WM831X_LDO9_ON_CONTROL:
+	case WM831X_LDO9_SLEEP_CONTROL:
+	case WM831X_LDO10_CONTROL:
+	case WM831X_LDO10_ON_CONTROL:
+	case WM831X_LDO10_SLEEP_CONTROL:
+	case WM831X_LDO11_ON_CONTROL:
+	case WM831X_LDO11_SLEEP_CONTROL:
+	case WM831X_POWER_GOOD_SOURCE_1:
+	case WM831X_POWER_GOOD_SOURCE_2:
+	case WM831X_CLOCK_CONTROL_1:
+	case WM831X_CLOCK_CONTROL_2:
+	case WM831X_FLL_CONTROL_1:
+	case WM831X_FLL_CONTROL_2:
+	case WM831X_FLL_CONTROL_3:
+	case WM831X_FLL_CONTROL_4:
+	case WM831X_FLL_CONTROL_5:
+	case WM831X_UNIQUE_ID_1:
+	case WM831X_UNIQUE_ID_2:
+	case WM831X_UNIQUE_ID_3:
+	case WM831X_UNIQUE_ID_4:
+	case WM831X_UNIQUE_ID_5:
+	case WM831X_UNIQUE_ID_6:
+	case WM831X_UNIQUE_ID_7:
+	case WM831X_UNIQUE_ID_8:
+	case WM831X_FACTORY_OTP_ID:
+	case WM831X_FACTORY_OTP_1:
+	case WM831X_FACTORY_OTP_2:
+	case WM831X_FACTORY_OTP_3:
+	case WM831X_FACTORY_OTP_4:
+	case WM831X_FACTORY_OTP_5:
+	case WM831X_CUSTOMER_OTP_ID:
+	case WM831X_DC1_OTP_CONTROL:
+	case WM831X_DC2_OTP_CONTROL:
+	case WM831X_DC3_OTP_CONTROL:
+	case WM831X_LDO1_2_OTP_CONTROL:
+	case WM831X_LDO3_4_OTP_CONTROL:
+	case WM831X_LDO5_6_OTP_CONTROL:
+	case WM831X_LDO7_8_OTP_CONTROL:
+	case WM831X_LDO9_10_OTP_CONTROL:
+	case WM831X_LDO11_EPE_CONTROL:
+	case WM831X_GPIO1_OTP_CONTROL:
+	case WM831X_GPIO2_OTP_CONTROL:
+	case WM831X_GPIO3_OTP_CONTROL:
+	case WM831X_GPIO4_OTP_CONTROL:
+	case WM831X_GPIO5_OTP_CONTROL:
+	case WM831X_GPIO6_OTP_CONTROL:
+	case WM831X_DBE_CHECK_DATA:
+		return true;
+	default:
+		return false;
+	}
+}
 
-	ret = wm831x->read_dev(wm831x, reg, bytes, dest);
-	if (ret < 0)
-		return ret;
+static bool wm831x_reg_writeable(struct device *dev, unsigned int reg)
+{
+	struct wm831x *wm831x = dev_get_drvdata(dev);
 
-	for (i = 0; i < bytes / 2; i++) {
-		buf[i] = be16_to_cpu(buf[i]);
+	if (wm831x_reg_locked(wm831x, reg))
+		return false;
 
-		dev_vdbg(wm831x->dev, "Read %04x from R%d(0x%x)\n",
-			 buf[i], reg + i, reg + i);
+	switch (reg) {
+	case WM831X_SYSVDD_CONTROL:
+	case WM831X_THERMAL_MONITORING:
+	case WM831X_POWER_STATE:
+	case WM831X_WATCHDOG:
+	case WM831X_ON_PIN_CONTROL:
+	case WM831X_RESET_CONTROL:
+	case WM831X_CONTROL_INTERFACE:
+	case WM831X_SECURITY_KEY:
+	case WM831X_SOFTWARE_SCRATCH:
+	case WM831X_OTP_CONTROL:
+	case WM831X_GPIO_LEVEL:
+	case WM831X_INTERRUPT_STATUS_1:
+	case WM831X_INTERRUPT_STATUS_2:
+	case WM831X_INTERRUPT_STATUS_3:
+	case WM831X_INTERRUPT_STATUS_4:
+	case WM831X_INTERRUPT_STATUS_5:
+	case WM831X_IRQ_CONFIG:
+	case WM831X_SYSTEM_INTERRUPTS_MASK:
+	case WM831X_INTERRUPT_STATUS_1_MASK:
+	case WM831X_INTERRUPT_STATUS_2_MASK:
+	case WM831X_INTERRUPT_STATUS_3_MASK:
+	case WM831X_INTERRUPT_STATUS_4_MASK:
+	case WM831X_INTERRUPT_STATUS_5_MASK:
+	case WM831X_RTC_TIME_1:
+	case WM831X_RTC_TIME_2:
+	case WM831X_RTC_ALARM_1:
+	case WM831X_RTC_ALARM_2:
+	case WM831X_RTC_CONTROL:
+	case WM831X_RTC_TRIM:
+	case WM831X_TOUCH_CONTROL_1:
+	case WM831X_TOUCH_CONTROL_2:
+	case WM831X_AUXADC_CONTROL:
+	case WM831X_AUXADC_SOURCE:
+	case WM831X_COMPARATOR_CONTROL:
+	case WM831X_COMPARATOR_1:
+	case WM831X_COMPARATOR_2:
+	case WM831X_COMPARATOR_3:
+	case WM831X_COMPARATOR_4:
+	case WM831X_GPIO1_CONTROL:
+	case WM831X_GPIO2_CONTROL:
+	case WM831X_GPIO3_CONTROL:
+	case WM831X_GPIO4_CONTROL:
+	case WM831X_GPIO5_CONTROL:
+	case WM831X_GPIO6_CONTROL:
+	case WM831X_GPIO7_CONTROL:
+	case WM831X_GPIO8_CONTROL:
+	case WM831X_GPIO9_CONTROL:
+	case WM831X_GPIO10_CONTROL:
+	case WM831X_GPIO11_CONTROL:
+	case WM831X_GPIO12_CONTROL:
+	case WM831X_GPIO13_CONTROL:
+	case WM831X_GPIO14_CONTROL:
+	case WM831X_GPIO15_CONTROL:
+	case WM831X_GPIO16_CONTROL:
+	case WM831X_CHARGER_CONTROL_1:
+	case WM831X_CHARGER_CONTROL_2:
+	case WM831X_CHARGER_STATUS:
+	case WM831X_BACKUP_CHARGER_CONTROL:
+	case WM831X_STATUS_LED_1:
+	case WM831X_STATUS_LED_2:
+	case WM831X_CURRENT_SINK_1:
+	case WM831X_CURRENT_SINK_2:
+	case WM831X_DCDC_ENABLE:
+	case WM831X_LDO_ENABLE:
+	case WM831X_DC1_CONTROL_1:
+	case WM831X_DC1_CONTROL_2:
+	case WM831X_DC1_ON_CONFIG:
+	case WM831X_DC1_SLEEP_CONTROL:
+	case WM831X_DC1_DVS_CONTROL:
+	case WM831X_DC2_CONTROL_1:
+	case WM831X_DC2_CONTROL_2:
+	case WM831X_DC2_ON_CONFIG:
+	case WM831X_DC2_SLEEP_CONTROL:
+	case WM831X_DC2_DVS_CONTROL:
+	case WM831X_DC3_CONTROL_1:
+	case WM831X_DC3_CONTROL_2:
+	case WM831X_DC3_ON_CONFIG:
+	case WM831X_DC3_SLEEP_CONTROL:
+	case WM831X_DC4_CONTROL:
+	case WM831X_DC4_SLEEP_CONTROL:
+	case WM831X_EPE1_CONTROL:
+	case WM831X_EPE2_CONTROL:
+	case WM831X_LDO1_CONTROL:
+	case WM831X_LDO1_ON_CONTROL:
+	case WM831X_LDO1_SLEEP_CONTROL:
+	case WM831X_LDO2_CONTROL:
+	case WM831X_LDO2_ON_CONTROL:
+	case WM831X_LDO2_SLEEP_CONTROL:
+	case WM831X_LDO3_CONTROL:
+	case WM831X_LDO3_ON_CONTROL:
+	case WM831X_LDO3_SLEEP_CONTROL:
+	case WM831X_LDO4_CONTROL:
+	case WM831X_LDO4_ON_CONTROL:
+	case WM831X_LDO4_SLEEP_CONTROL:
+	case WM831X_LDO5_CONTROL:
+	case WM831X_LDO5_ON_CONTROL:
+	case WM831X_LDO5_SLEEP_CONTROL:
+	case WM831X_LDO6_CONTROL:
+	case WM831X_LDO6_ON_CONTROL:
+	case WM831X_LDO6_SLEEP_CONTROL:
+	case WM831X_LDO7_CONTROL:
+	case WM831X_LDO7_ON_CONTROL:
+	case WM831X_LDO7_SLEEP_CONTROL:
+	case WM831X_LDO8_CONTROL:
+	case WM831X_LDO8_ON_CONTROL:
+	case WM831X_LDO8_SLEEP_CONTROL:
+	case WM831X_LDO9_CONTROL:
+	case WM831X_LDO9_ON_CONTROL:
+	case WM831X_LDO9_SLEEP_CONTROL:
+	case WM831X_LDO10_CONTROL:
+	case WM831X_LDO10_ON_CONTROL:
+	case WM831X_LDO10_SLEEP_CONTROL:
+	case WM831X_LDO11_ON_CONTROL:
+	case WM831X_LDO11_SLEEP_CONTROL:
+	case WM831X_POWER_GOOD_SOURCE_1:
+	case WM831X_POWER_GOOD_SOURCE_2:
+	case WM831X_CLOCK_CONTROL_1:
+	case WM831X_CLOCK_CONTROL_2:
+	case WM831X_FLL_CONTROL_1:
+	case WM831X_FLL_CONTROL_2:
+	case WM831X_FLL_CONTROL_3:
+	case WM831X_FLL_CONTROL_4:
+	case WM831X_FLL_CONTROL_5:
+		return true;
+	default:
+		return false;
 	}
+}
 
-	return 0;
+static bool wm831x_reg_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case WM831X_SYSTEM_STATUS:
+	case WM831X_ON_SOURCE:
+	case WM831X_OFF_SOURCE:
+	case WM831X_GPIO_LEVEL:
+	case WM831X_SYSTEM_INTERRUPTS:
+	case WM831X_INTERRUPT_STATUS_1:
+	case WM831X_INTERRUPT_STATUS_2:
+	case WM831X_INTERRUPT_STATUS_3:
+	case WM831X_INTERRUPT_STATUS_4:
+	case WM831X_INTERRUPT_STATUS_5:
+	case WM831X_RTC_TIME_1:
+	case WM831X_RTC_TIME_2:
+	case WM831X_TOUCH_DATA_X:
+	case WM831X_TOUCH_DATA_Y:
+	case WM831X_TOUCH_DATA_Z:
+	case WM831X_AUXADC_DATA:
+	case WM831X_CHARGER_STATUS:
+	case WM831X_DCDC_STATUS:
+	case WM831X_LDO_STATUS:
+	case WM831X_DCDC_UV_STATUS:
+	case WM831X_LDO_UV_STATUS:
+		return true;
+	default:
+		return false;
+	}
 }
 
 /**
@@ -191,14 +516,10 @@
  */
 int wm831x_reg_read(struct wm831x *wm831x, unsigned short reg)
 {
-	unsigned short val;
+	unsigned int val;
 	int ret;
 
-	mutex_lock(&wm831x->io_lock);
-
-	ret = wm831x_read(wm831x, reg, 2, &val);
-
-	mutex_unlock(&wm831x->io_lock);
+	ret = regmap_read(wm831x->regmap, reg, &val);
 
 	if (ret < 0)
 		return ret;
@@ -218,15 +539,7 @@
 int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
 		     int count, u16 *buf)
 {
-	int ret;
-
-	mutex_lock(&wm831x->io_lock);
-
-	ret = wm831x_read(wm831x, reg, count * 2, buf);
-
-	mutex_unlock(&wm831x->io_lock);
-
-	return ret;
+	return regmap_bulk_read(wm831x->regmap, reg, buf, count);
 }
 EXPORT_SYMBOL_GPL(wm831x_bulk_read);
 
@@ -234,7 +547,7 @@
 			int bytes, void *src)
 {
 	u16 *buf = src;
-	int i;
+	int i, ret;
 
 	BUG_ON(bytes % 2);
 	BUG_ON(bytes <= 0);
@@ -245,11 +558,10 @@
 
 		dev_vdbg(wm831x->dev, "Write %04x to R%d(0x%x)\n",
 			 buf[i], reg + i, reg + i);
-
-		buf[i] = cpu_to_be16(buf[i]);
+		ret = regmap_write(wm831x->regmap, reg + i, buf[i]);
 	}
 
-	return wm831x->write_dev(wm831x, reg, bytes, src);
+	return 0;
 }
 
 /**
@@ -286,20 +598,14 @@
 		    unsigned short mask, unsigned short val)
 {
 	int ret;
-	u16 r;
 
 	mutex_lock(&wm831x->io_lock);
 
-	ret = wm831x_read(wm831x, reg, 2, &r);
-	if (ret < 0)
-		goto out;
-
-	r &= ~mask;
-	r |= val & mask;
-
-	ret = wm831x_write(wm831x, reg, 2, &r);
+	if (!wm831x_reg_locked(wm831x, reg))
+		ret = regmap_update_bits(wm831x->regmap, reg, mask, val);
+	else
+		ret = -EPERM;
 
-out:
 	mutex_unlock(&wm831x->io_lock);
 
 	return ret;
@@ -1292,6 +1598,19 @@
 	},
 };
 
+struct regmap_config wm831x_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 16,
+
+	.cache_type = REGCACHE_RBTREE,
+
+	.max_register = WM831X_DBE_CHECK_DATA,
+	.readable_reg = wm831x_reg_readable,
+	.writeable_reg = wm831x_reg_writeable,
+	.volatile_reg = wm831x_reg_volatile,
+};
+EXPORT_SYMBOL_GPL(wm831x_regmap_config);
+
 /*
  * Instantiate the generic non-control parts of the device.
  */
@@ -1305,11 +1624,12 @@
 	mutex_init(&wm831x->io_lock);
 	mutex_init(&wm831x->key_lock);
 	dev_set_drvdata(wm831x->dev, wm831x);
+	wm831x->soft_shutdown = pdata->soft_shutdown;
 
 	ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
 	if (ret < 0) {
 		dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret);
-		goto err;
+		goto err_regmap;
 	}
 	switch (ret) {
 	case 0x6204:
@@ -1318,20 +1638,20 @@
 	default:
 		dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret);
 		ret = -EINVAL;
-		goto err;
+		goto err_regmap;
 	}
 
 	ret = wm831x_reg_read(wm831x, WM831X_REVISION);
 	if (ret < 0) {
 		dev_err(wm831x->dev, "Failed to read revision: %d\n", ret);
-		goto err;
+		goto err_regmap;
 	}
 	rev = (ret & WM831X_PARENT_REV_MASK) >> WM831X_PARENT_REV_SHIFT;
 
 	ret = wm831x_reg_read(wm831x, WM831X_RESET_ID);
 	if (ret < 0) {
 		dev_err(wm831x->dev, "Failed to read device ID: %d\n", ret);
-		goto err;
+		goto err_regmap;
 	}
 
 	/* Some engineering samples do not have the ID set, rely on
@@ -1406,7 +1726,7 @@
 	default:
 		dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret);
 		ret = -EINVAL;
-		goto err;
+		goto err_regmap;
 	}
 
 	/* This will need revisiting in future but is OK for all
@@ -1420,7 +1740,7 @@
 	ret = wm831x_reg_read(wm831x, WM831X_SECURITY_KEY);
 	if (ret < 0) {
 		dev_err(wm831x->dev, "Failed to read security key: %d\n", ret);
-		goto err;
+		goto err_regmap;
 	}
 	if (ret != 0) {
 		dev_warn(wm831x->dev, "Security key had non-zero value %x\n",
@@ -1433,7 +1753,7 @@
 		ret = pdata->pre_init(wm831x);
 		if (ret != 0) {
 			dev_err(wm831x->dev, "pre_init() failed: %d\n", ret);
-			goto err;
+			goto err_regmap;
 		}
 	}
 
@@ -1456,7 +1776,7 @@
 
 	ret = wm831x_irq_init(wm831x, irq);
 	if (ret != 0)
-		goto err;
+		goto err_regmap;
 
 	wm831x_auxadc_init(wm831x);
 
@@ -1552,8 +1872,9 @@
 
 err_irq:
 	wm831x_irq_exit(wm831x);
-err:
+err_regmap:
 	mfd_remove_devices(wm831x->dev);
+	regmap_exit(wm831x->regmap);
 	kfree(wm831x);
 	return ret;
 }
@@ -1565,6 +1886,7 @@
 	if (wm831x->irq_base)
 		free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x);
 	wm831x_irq_exit(wm831x);
+	regmap_exit(wm831x->regmap);
 	kfree(wm831x);
 }
 
@@ -1604,6 +1926,15 @@
 	return 0;
 }
 
+void wm831x_device_shutdown(struct wm831x *wm831x)
+{
+	if (wm831x->soft_shutdown) {
+		dev_info(wm831x->dev, "Initiating shutdown...\n");
+		wm831x_set_bits(wm831x, WM831X_POWER_STATE, WM831X_CHIP_ON, 0);
+	}
+}
+EXPORT_SYMBOL_GPL(wm831x_device_shutdown);
+
 MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Mark Brown");
diff -druN linux-libre-3.1-gnu/drivers/mfd/wm831x-i2c.c linux-libre-3.2-gnu/drivers/mfd/wm831x-i2c.c
--- linux-libre-3.1-gnu/drivers/mfd/wm831x-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/wm831x-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,67 +18,17 @@
 #include <linux/delay.h>
 #include <linux/mfd/core.h>
 #include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/regmap.h>
 
 #include <linux/mfd/wm831x/core.h>
 #include <linux/mfd/wm831x/pdata.h>
 
-static int wm831x_i2c_read_device(struct wm831x *wm831x, unsigned short reg,
-				  int bytes, void *dest)
-{
-	struct i2c_client *i2c = wm831x->control_data;
-	int ret;
-	u16 r = cpu_to_be16(reg);
-
-	ret = i2c_master_send(i2c, (unsigned char *)&r, 2);
-	if (ret < 0)
-		return ret;
-	if (ret != 2)
-		return -EIO;
-
-	ret = i2c_master_recv(i2c, dest, bytes);
-	if (ret < 0)
-		return ret;
-	if (ret != bytes)
-		return -EIO;
-	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 wm831x_i2c_write_device(struct wm831x *wm831x, unsigned short reg,
-				   int bytes, void *src)
-{
-	struct i2c_client *i2c = wm831x->control_data;
-	struct i2c_msg xfer[2];
-	int ret;
-
-	reg = cpu_to_be16(reg);
-
-	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 != 2)
-		return -EIO;
-
-	return 0;
-}
-
 static int wm831x_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
 	struct wm831x *wm831x;
+	int ret;
 
 	wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
 	if (wm831x == NULL)
@@ -86,9 +36,15 @@
 
 	i2c_set_clientdata(i2c, wm831x);
 	wm831x->dev = &i2c->dev;
-	wm831x->control_data = i2c;
-	wm831x->read_dev = wm831x_i2c_read_device;
-	wm831x->write_dev = wm831x_i2c_write_device;
+
+	wm831x->regmap = regmap_init_i2c(i2c, &wm831x_regmap_config);
+	if (IS_ERR(wm831x->regmap)) {
+		ret = PTR_ERR(wm831x->regmap);
+		dev_err(wm831x->dev, "Failed to allocate register map: %d\n",
+			ret);
+		kfree(wm831x);
+		return ret;
+	}
 
 	return wm831x_device_init(wm831x, id->driver_data, i2c->irq);
 }
@@ -109,6 +65,13 @@
 	return wm831x_device_suspend(wm831x);
 }
 
+static void wm831x_i2c_shutdown(struct i2c_client *i2c)
+{
+	struct wm831x *wm831x = i2c_get_clientdata(i2c);
+
+	wm831x_device_shutdown(wm831x);
+}
+
 static const struct i2c_device_id wm831x_i2c_id[] = {
 	{ "wm8310", WM8310 },
 	{ "wm8311", WM8311 },
@@ -133,6 +96,7 @@
 	},
 	.probe = wm831x_i2c_probe,
 	.remove = wm831x_i2c_remove,
+	.shutdown = wm831x_i2c_shutdown,
 	.id_table = wm831x_i2c_id,
 };
 
diff -druN linux-libre-3.1-gnu/drivers/mfd/wm831x-irq.c linux-libre-3.2-gnu/drivers/mfd/wm831x-irq.c
--- linux-libre-3.1-gnu/drivers/mfd/wm831x-irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/wm831x-irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -420,12 +420,19 @@
 	switch (type) {
 	case IRQ_TYPE_EDGE_BOTH:
 		wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_INT_MODE;
+		wm831x->gpio_level[irq] = false;
 		break;
 	case IRQ_TYPE_EDGE_RISING:
 		wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL;
+		wm831x->gpio_level[irq] = false;
 		break;
 	case IRQ_TYPE_EDGE_FALLING:
 		wm831x->gpio_update[irq] = 0x10000;
+		wm831x->gpio_level[irq] = false;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL;
+		wm831x->gpio_level[irq] = true;
 		break;
 	default:
 		return -EINVAL;
@@ -449,7 +456,7 @@
 {
 	struct wm831x *wm831x = data;
 	unsigned int i;
-	int primary, status_addr;
+	int primary, status_addr, ret;
 	int status_regs[WM831X_NUM_IRQ_REGS] = { 0 };
 	int read[WM831X_NUM_IRQ_REGS] = { 0 };
 	int *status;
@@ -507,6 +514,19 @@
 
 		if (*status & wm831x_irqs[i].mask)
 			handle_nested_irq(wm831x->irq_base + i);
+
+		/* Simulate an edge triggered IRQ by polling the input
+		 * status.  This is sucky but improves interoperability.
+		 */
+		if (primary == WM831X_GP_INT &&
+		    wm831x->gpio_level[i - WM831X_IRQ_GPIO_1]) {
+			ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL);
+			while (ret & 1 << (i - WM831X_IRQ_GPIO_1)) {
+				handle_nested_irq(wm831x->irq_base + i);
+				ret = wm831x_reg_read(wm831x,
+						      WM831X_GPIO_LEVEL);
+			}
+		}
 	}
 
 out:
@@ -596,8 +616,6 @@
 			 "No interrupt specified - functionality limited\n");
 	}
 
-
-
 	/* Enable top level interrupts, we mask at secondary level */
 	wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0);
 
diff -druN linux-libre-3.1-gnu/drivers/mfd/wm831x-spi.c linux-libre-3.2-gnu/drivers/mfd/wm831x-spi.c
--- linux-libre-3.1-gnu/drivers/mfd/wm831x-spi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/wm831x-spi.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,78 +16,19 @@
 #include <linux/module.h>
 #include <linux/pm.h>
 #include <linux/spi/spi.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
 
 #include <linux/mfd/wm831x/core.h>
 
-static int wm831x_spi_read_device(struct wm831x *wm831x, unsigned short reg,
-				  int bytes, void *dest)
-{
-	u16 tx_val;
-	u16 *d = dest;
-	int r, ret;
-
-	/* Go register at a time */
-	for (r = reg; r < reg + (bytes / 2); r++) {
-		tx_val = r | 0x8000;
-
-		ret = spi_write_then_read(wm831x->control_data,
-					  (u8 *)&tx_val, 2, (u8 *)d, 2);
-		if (ret != 0)
-			return ret;
-
-		*d = be16_to_cpu(*d);
-
-		d++;
-	}
-
-	return 0;
-}
-
-static int wm831x_spi_write_device(struct wm831x *wm831x, unsigned short reg,
-				   int bytes, void *src)
-{
-	struct spi_device *spi = wm831x->control_data;
-	u16 *s = src;
-	u16 data[2];
-	int ret, r;
-
-	/* Go register at a time */
-	for (r = reg; r < reg + (bytes / 2); r++) {
-		data[0] = r;
-		data[1] = *s++;
-
-		ret = spi_write(spi, (char *)&data, sizeof(data));
-		if (ret != 0)
-			return ret;
-	}
-
-	return 0;
-}
-
 static int __devinit wm831x_spi_probe(struct spi_device *spi)
 {
+	const struct spi_device_id *id = spi_get_device_id(spi);
 	struct wm831x *wm831x;
 	enum wm831x_parent type;
+	int ret;
 
-	/* Currently SPI support for ID tables is unmerged, we're faking it */
-	if (strcmp(spi->modalias, "wm8310") == 0)
-		type = WM8310;
-	else if (strcmp(spi->modalias, "wm8311") == 0)
-		type = WM8311;
-	else if (strcmp(spi->modalias, "wm8312") == 0)
-		type = WM8312;
-	else if (strcmp(spi->modalias, "wm8320") == 0)
-		type = WM8320;
-	else if (strcmp(spi->modalias, "wm8321") == 0)
-		type = WM8321;
-	else if (strcmp(spi->modalias, "wm8325") == 0)
-		type = WM8325;
-	else if (strcmp(spi->modalias, "wm8326") == 0)
-		type = WM8326;
-	else {
-		dev_err(&spi->dev, "Unknown device type\n");
-		return -EINVAL;
-	}
+	type = (enum wm831x_parent)id->driver_data;
 
 	wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
 	if (wm831x == NULL)
@@ -98,9 +39,15 @@
 
 	dev_set_drvdata(&spi->dev, wm831x);
 	wm831x->dev = &spi->dev;
-	wm831x->control_data = spi;
-	wm831x->read_dev = wm831x_spi_read_device;
-	wm831x->write_dev = wm831x_spi_write_device;
+
+	wm831x->regmap = regmap_init_spi(spi, &wm831x_regmap_config);
+	if (IS_ERR(wm831x->regmap)) {
+		ret = PTR_ERR(wm831x->regmap);
+		dev_err(wm831x->dev, "Failed to allocate register map: %d\n",
+			ret);
+		kfree(wm831x);
+		return ret;
+	}
 
 	return wm831x_device_init(wm831x, type, spi->irq);
 }
@@ -121,119 +68,50 @@
 	return wm831x_device_suspend(wm831x);
 }
 
+static void wm831x_spi_shutdown(struct spi_device *spi)
+{
+	struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
+
+	wm831x_device_shutdown(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),
-};
-
-static struct spi_driver wm8311_spi_driver = {
-	.driver = {
-		.name	= "wm8311",
-		.bus	= &spi_bus_type,
-		.owner	= THIS_MODULE,
-		.pm	= &wm831x_spi_pm,
-	},
-	.probe		= wm831x_spi_probe,
-	.remove		= __devexit_p(wm831x_spi_remove),
-};
-
-static struct spi_driver wm8312_spi_driver = {
-	.driver = {
-		.name	= "wm8312",
-		.bus	= &spi_bus_type,
-		.owner	= THIS_MODULE,
-		.pm	= &wm831x_spi_pm,
-	},
-	.probe		= wm831x_spi_probe,
-	.remove		= __devexit_p(wm831x_spi_remove),
-};
-
-static struct spi_driver wm8320_spi_driver = {
-	.driver = {
-		.name	= "wm8320",
-		.bus	= &spi_bus_type,
-		.owner	= THIS_MODULE,
-		.pm	= &wm831x_spi_pm,
-	},
-	.probe		= wm831x_spi_probe,
-	.remove		= __devexit_p(wm831x_spi_remove),
-};
-
-static struct spi_driver wm8321_spi_driver = {
-	.driver = {
-		.name	= "wm8321",
-		.bus	= &spi_bus_type,
-		.owner	= THIS_MODULE,
-		.pm	= &wm831x_spi_pm,
-	},
-	.probe		= wm831x_spi_probe,
-	.remove		= __devexit_p(wm831x_spi_remove),
-};
-
-static struct spi_driver wm8325_spi_driver = {
-	.driver = {
-		.name	= "wm8325",
-		.bus	= &spi_bus_type,
-		.owner	= THIS_MODULE,
-		.pm	= &wm831x_spi_pm,
-	},
-	.probe		= wm831x_spi_probe,
-	.remove		= __devexit_p(wm831x_spi_remove),
+static const struct spi_device_id wm831x_spi_ids[] = {
+	{ "wm8310", WM8310 },
+	{ "wm8311", WM8311 },
+	{ "wm8312", WM8312 },
+	{ "wm8320", WM8320 },
+	{ "wm8321", WM8321 },
+	{ "wm8325", WM8325 },
+	{ "wm8326", WM8326 },
+	{ },
 };
+MODULE_DEVICE_TABLE(spi, wm831x_spi_id);
 
-static struct spi_driver wm8326_spi_driver = {
+static struct spi_driver wm831x_spi_driver = {
 	.driver = {
-		.name	= "wm8326",
+		.name	= "wm831x",
 		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
 		.pm	= &wm831x_spi_pm,
 	},
+	.id_table	= wm831x_spi_ids,
 	.probe		= wm831x_spi_probe,
 	.remove		= __devexit_p(wm831x_spi_remove),
+	.shutdown	= wm831x_spi_shutdown,
 };
 
 static int __init wm831x_spi_init(void)
 {
 	int ret;
 
-	ret = spi_register_driver(&wm8310_spi_driver);
-	if (ret != 0)
-		pr_err("Failed to register WM8310 SPI driver: %d\n", ret);
-
-	ret = spi_register_driver(&wm8311_spi_driver);
-	if (ret != 0)
-		pr_err("Failed to register WM8311 SPI driver: %d\n", ret);
-
-	ret = spi_register_driver(&wm8312_spi_driver);
-	if (ret != 0)
-		pr_err("Failed to register WM8312 SPI driver: %d\n", ret);
-
-	ret = spi_register_driver(&wm8320_spi_driver);
-	if (ret != 0)
-		pr_err("Failed to register WM8320 SPI driver: %d\n", ret);
-
-	ret = spi_register_driver(&wm8321_spi_driver);
-	if (ret != 0)
-		pr_err("Failed to register WM8321 SPI driver: %d\n", ret);
-
-	ret = spi_register_driver(&wm8325_spi_driver);
-	if (ret != 0)
-		pr_err("Failed to register WM8325 SPI driver: %d\n", ret);
-
-	ret = spi_register_driver(&wm8326_spi_driver);
+	ret = spi_register_driver(&wm831x_spi_driver);
 	if (ret != 0)
-		pr_err("Failed to register WM8326 SPI driver: %d\n", ret);
+		pr_err("Failed to register WM831x SPI driver: %d\n", ret);
 
 	return 0;
 }
@@ -241,13 +119,7 @@
 
 static void __exit wm831x_spi_exit(void)
 {
-	spi_unregister_driver(&wm8326_spi_driver);
-	spi_unregister_driver(&wm8325_spi_driver);
-	spi_unregister_driver(&wm8321_spi_driver);
-	spi_unregister_driver(&wm8320_spi_driver);
-	spi_unregister_driver(&wm8312_spi_driver);
-	spi_unregister_driver(&wm8311_spi_driver);
-	spi_unregister_driver(&wm8310_spi_driver);
+	spi_unregister_driver(&wm831x_spi_driver);
 }
 module_exit(wm831x_spi_exit);
 
diff -druN linux-libre-3.1-gnu/drivers/mfd/wm8400-core.c linux-libre-3.2-gnu/drivers/mfd/wm8400-core.c
--- linux-libre-3.1-gnu/drivers/mfd/wm8400-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/wm8400-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,12 +12,15 @@
  *
  */
 
+#include <linux/module.h>
 #include <linux/bug.h>
+#include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/kernel.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/wm8400-private.h>
 #include <linux/mfd/wm8400-audio.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 
 static struct {
@@ -123,14 +126,9 @@
 	/* If there are any volatile reads then read back the entire block */
 	for (i = reg; i < reg + num_regs; i++)
 		if (reg_data[i].vol) {
-			ret = wm8400->read_dev(wm8400->io_data, reg,
-					       num_regs, dest);
-			if (ret != 0)
-				return ret;
-			for (i = 0; i < num_regs; i++)
-				dest[i] = be16_to_cpu(dest[i]);
-
-			return 0;
+			ret = regmap_bulk_read(wm8400->regmap, reg, dest,
+					       num_regs);
+			return ret;
 		}
 
 	/* Otherwise use the cache */
@@ -149,14 +147,11 @@
 	for (i = 0; i < num_regs; i++) {
 		BUG_ON(!reg_data[reg + i].writable);
 		wm8400->reg_cache[reg + i] = src[i];
-		src[i] = cpu_to_be16(src[i]);
+		ret = regmap_write(wm8400->regmap, reg, src[i]);
+		if (ret != 0)
+			return ret;
 	}
 
-	/* Do the actual I/O */
-	ret = wm8400->write_dev(wm8400->io_data, reg, num_regs, src);
-	if (ret != 0)
-		return -EIO;
-
 	return 0;
 }
 
@@ -270,14 +265,14 @@
 	dev_set_drvdata(wm8400->dev, wm8400);
 
 	/* Check that this is actually a WM8400 */
-	ret = wm8400->read_dev(wm8400->io_data, WM8400_RESET_ID, 1, &reg);
+	ret = regmap_read(wm8400->regmap, WM8400_RESET_ID, &i);
 	if (ret != 0) {
 		dev_err(wm8400->dev, "Chip ID register read failed\n");
 		return -EIO;
 	}
-	if (be16_to_cpu(reg) != reg_data[WM8400_RESET_ID].default_val) {
+	if (i != reg_data[WM8400_RESET_ID].default_val) {
 		dev_err(wm8400->dev, "Device is not a WM8400, ID is %x\n",
-			be16_to_cpu(reg));
+			reg);
 		return -ENODEV;
 	}
 
@@ -285,9 +280,8 @@
 	 * is a PMIC we can't reset it safely so initialise the register
 	 * cache from the hardware.
 	 */
-	ret = wm8400->read_dev(wm8400->io_data, 0,
-			       ARRAY_SIZE(wm8400->reg_cache),
-			       wm8400->reg_cache);
+	ret = regmap_raw_read(wm8400->regmap, 0, wm8400->reg_cache,
+			      ARRAY_SIZE(wm8400->reg_cache));
 	if (ret != 0) {
 		dev_err(wm8400->dev, "Register cache read failed\n");
 		return -EIO;
@@ -337,60 +331,13 @@
 	mfd_remove_devices(wm8400->dev);
 }
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static int wm8400_i2c_read(void *io_data, char reg, int count, u16 *dest)
-{
-	struct i2c_client *i2c = io_data;
-	struct i2c_msg xfer[2];
-	int ret;
-
-	/* Write register */
-	xfer[0].addr = i2c->addr;
-	xfer[0].flags = 0;
-	xfer[0].len = 1;
-	xfer[0].buf = &reg;
-
-	/* Read data */
-	xfer[1].addr = i2c->addr;
-	xfer[1].flags = I2C_M_RD;
-	xfer[1].len = count * sizeof(u16);
-	xfer[1].buf = (u8 *)dest;
-
-	ret = i2c_transfer(i2c->adapter, xfer, 2);
-	if (ret == 2)
-		ret = 0;
-	else if (ret >= 0)
-		ret = -EIO;
-
-	return ret;
-}
-
-static int wm8400_i2c_write(void *io_data, char reg, int count, const u16 *src)
-{
-	struct i2c_client *i2c = io_data;
-	u8 *msg;
-	int ret;
-
-	/* We add 1 byte for device register - ideally I2C would gather. */
-	msg = kmalloc((count * sizeof(u16)) + 1, GFP_KERNEL);
-	if (msg == NULL)
-		return -ENOMEM;
-
-	msg[0] = reg;
-	memcpy(&msg[1], src, count * sizeof(u16));
-
-	ret = i2c_master_send(i2c, msg, (count * sizeof(u16)) + 1);
-
-	if (ret == (count * 2) + 1)
-		ret = 0;
-	else if (ret >= 0)
-		ret = -EIO;
-
-	kfree(msg);
-
-	return ret;
-}
+static const struct regmap_config wm8400_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 16,
+	.max_register = WM8400_REGISTER_COUNT - 1,
+};
 
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static int wm8400_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
@@ -403,18 +350,23 @@
 		goto err;
 	}
 
-	wm8400->io_data = i2c;
-	wm8400->read_dev = wm8400_i2c_read;
-	wm8400->write_dev = wm8400_i2c_write;
+	wm8400->regmap = regmap_init_i2c(i2c, &wm8400_regmap_config);
+	if (IS_ERR(wm8400->regmap)) {
+		ret = PTR_ERR(wm8400->regmap);
+		goto struct_err;
+	}
+
 	wm8400->dev = &i2c->dev;
 	i2c_set_clientdata(i2c, wm8400);
 
 	ret = wm8400_init(wm8400, i2c->dev.platform_data);
 	if (ret != 0)
-		goto struct_err;
+		goto map_err;
 
 	return 0;
 
+map_err:
+	regmap_exit(wm8400->regmap);
 struct_err:
 	kfree(wm8400);
 err:
@@ -426,6 +378,7 @@
 	struct wm8400 *wm8400 = i2c_get_clientdata(i2c);
 
 	wm8400_release(wm8400);
+	regmap_exit(wm8400->regmap);
 	kfree(wm8400);
 
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/mfd/wm8994-core.c linux-libre-3.2-gnu/drivers/mfd/wm8994-core.c
--- linux-libre-3.1-gnu/drivers/mfd/wm8994-core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mfd/wm8994-core.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,9 +16,11 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/mfd/core.h>
 #include <linux/pm_runtime.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/machine.h>
 
@@ -29,22 +31,7 @@
 static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
 		       int bytes, void *dest)
 {
-	int ret, i;
-	u16 *buf = dest;
-
-	BUG_ON(bytes % 2);
-	BUG_ON(bytes <= 0);
-
-	ret = wm8994->read_dev(wm8994, reg, bytes, dest);
-	if (ret < 0)
-		return ret;
-
-	for (i = 0; i < bytes / 2; i++) {
-		dev_vdbg(wm8994->dev, "Read %04x from R%d(0x%x)\n",
-			 be16_to_cpu(buf[i]), reg + i, reg + i);
-	}
-
-	return 0;
+	return regmap_raw_read(wm8994->regmap, reg, dest, bytes);
 }
 
 /**
@@ -55,19 +42,15 @@
  */
 int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg)
 {
-	unsigned short val;
+	unsigned int val;
 	int ret;
 
-	mutex_lock(&wm8994->io_lock);
-
-	ret = wm8994_read(wm8994, reg, 2, &val);
-
-	mutex_unlock(&wm8994->io_lock);
+	ret = regmap_read(wm8994->regmap, reg, &val);
 
 	if (ret < 0)
 		return ret;
 	else
-		return be16_to_cpu(val);
+		return val;
 }
 EXPORT_SYMBOL_GPL(wm8994_reg_read);
 
@@ -82,33 +65,13 @@
 int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
 		     int count, u16 *buf)
 {
-	int ret;
-
-	mutex_lock(&wm8994->io_lock);
-
-	ret = wm8994_read(wm8994, reg, count * 2, buf);
-
-	mutex_unlock(&wm8994->io_lock);
-
-	return ret;
+	return regmap_bulk_read(wm8994->regmap, reg, buf, count);
 }
-EXPORT_SYMBOL_GPL(wm8994_bulk_read);
 
 static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
 			int bytes, const void *src)
 {
-	const u16 *buf = src;
-	int i;
-
-	BUG_ON(bytes % 2);
-	BUG_ON(bytes <= 0);
-
-	for (i = 0; i < bytes / 2; i++) {
-		dev_vdbg(wm8994->dev, "Write %04x to R%d(0x%x)\n",
-			 be16_to_cpu(buf[i]), reg + i, reg + i);
-	}
-
-	return wm8994->write_dev(wm8994, reg, bytes, src);
+	return regmap_raw_write(wm8994->regmap, reg, src, bytes);
 }
 
 /**
@@ -121,17 +84,7 @@
 int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
 		     unsigned short val)
 {
-	int ret;
-
-	val = cpu_to_be16(val);
-
-	mutex_lock(&wm8994->io_lock);
-
-	ret = wm8994_write(wm8994, reg, 2, &val);
-
-	mutex_unlock(&wm8994->io_lock);
-
-	return ret;
+	return regmap_write(wm8994->regmap, reg, val);
 }
 EXPORT_SYMBOL_GPL(wm8994_reg_write);
 
@@ -146,15 +99,7 @@
 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;
+	return regmap_raw_write(wm8994->regmap, reg, buf, count * sizeof(u16));
 }
 EXPORT_SYMBOL_GPL(wm8994_bulk_write);
 
@@ -169,28 +114,7 @@
 int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
 		    unsigned short mask, unsigned short val)
 {
-	int ret;
-	u16 r;
-
-	mutex_lock(&wm8994->io_lock);
-
-	ret = wm8994_read(wm8994, reg, 2, &r);
-	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:
-	mutex_unlock(&wm8994->io_lock);
-
-	return ret;
+	return regmap_update_bits(wm8994->regmap, reg, mask, val);
 }
 EXPORT_SYMBOL_GPL(wm8994_set_bits);
 
@@ -243,6 +167,18 @@
  * and should be handled via the standard regulator API supply
  * management.
  */
+static const char *wm1811_main_supplies[] = {
+	"DBVDD1",
+	"DBVDD2",
+	"DBVDD3",
+	"DCVDD",
+	"AVDD1",
+	"AVDD2",
+	"CPVDD",
+	"SPKVDD1",
+	"SPKVDD2",
+};
+
 static const char *wm8994_main_supplies[] = {
 	"DBVDD",
 	"DCVDD",
@@ -281,6 +217,48 @@
 		return 0;
 	}
 
+	ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_4);
+	if (ret < 0) {
+		dev_err(dev, "Failed to read power status: %d\n", ret);
+	} else if (ret & (WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA |
+			  WM8994_AIF1ADC2L_ENA | WM8994_AIF1ADC2R_ENA |
+			  WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC1R_ENA)) {
+		dev_dbg(dev, "CODEC still active, ignoring suspend\n");
+		return 0;
+	}
+
+	ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_5);
+	if (ret < 0) {
+		dev_err(dev, "Failed to read power status: %d\n", ret);
+	} else if (ret & (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA |
+			  WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA |
+			  WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA)) {
+		dev_dbg(dev, "CODEC still active, ignoring suspend\n");
+		return 0;
+	}
+
+	switch (wm8994->type) {
+	case WM8958:
+	case WM1811:
+		ret = wm8994_reg_read(wm8994, WM8958_MIC_DETECT_1);
+		if (ret < 0) {
+			dev_err(dev, "Failed to read power status: %d\n", ret);
+		} else if (ret & WM8958_MICD_ENA) {
+			dev_dbg(dev, "CODEC still active, ignoring suspend\n");
+			return 0;
+		}
+		break;
+	default:
+		break;
+	}
+
+	/* Disable LDO pulldowns while the device is suspended if we
+	 * don't know that something will be driving them. */
+	if (!wm8994->ldo_ena_always_driven)
+		wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
+				WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
+				WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD);
+
 	/* GPIO configuration state is saved here since we may be configuring
 	 * the GPIO alternate functions even if we're not using the gpiolib
 	 * driver for them.
@@ -350,6 +328,11 @@
 	if (ret < 0)
 		dev_err(dev, "Failed to restore GPIO registers: %d\n", ret);
 
+	/* Disable LDO pulldowns while the device is active */
+	wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
+			WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
+			0);
+
 	wm8994->suspended = false;
 
 	return 0;
@@ -378,6 +361,11 @@
 }
 #endif
 
+static struct regmap_config wm8994_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 16,
+};
+
 /*
  * Instantiate the generic non-control parts of the device.
  */
@@ -387,7 +375,6 @@
 	const char *devname;
 	int ret, i;
 
-	mutex_init(&wm8994->io_lock);
 	dev_set_drvdata(wm8994->dev, wm8994);
 
 	/* Add the on-chip regulators first for bootstrapping */
@@ -397,10 +384,13 @@
 			      NULL, 0);
 	if (ret != 0) {
 		dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
-		goto err;
+		goto err_regmap;
 	}
 
 	switch (wm8994->type) {
+	case WM1811:
+		wm8994->num_supplies = ARRAY_SIZE(wm1811_main_supplies);
+		break;
 	case WM8994:
 		wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies);
 		break;
@@ -409,7 +399,7 @@
 		break;
 	default:
 		BUG();
-		goto err;
+		goto err_regmap;
 	}
 
 	wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
@@ -417,10 +407,14 @@
 				   GFP_KERNEL);
 	if (!wm8994->supplies) {
 		ret = -ENOMEM;
-		goto err;
+		goto err_regmap;
 	}
 
 	switch (wm8994->type) {
+	case WM1811:
+		for (i = 0; i < ARRAY_SIZE(wm1811_main_supplies); i++)
+			wm8994->supplies[i].supply = wm1811_main_supplies[i];
+		break;
 	case WM8994:
 		for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++)
 			wm8994->supplies[i].supply = wm8994_main_supplies[i];
@@ -431,7 +425,7 @@
 		break;
 	default:
 		BUG();
-		goto err;
+		goto err_regmap;
 	}
 		
 	ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies,
@@ -454,6 +448,13 @@
 		goto err_enable;
 	}
 	switch (ret) {
+	case 0x1811:
+		devname = "WM1811";
+		if (wm8994->type != WM1811)
+			dev_warn(wm8994->dev, "Device registered as type %d\n",
+				 wm8994->type);
+		wm8994->type = WM1811;
+		break;
 	case 0x8994:
 		devname = "WM8994";
 		if (wm8994->type != WM8994)
@@ -513,8 +514,15 @@
 						pdata->gpio_defaults[i]);
 			}
 		}
+
+		wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven;
 	}
 
+	/* Disable LDO pulldowns while the device is active */
+	wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
+			WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
+			0);
+
 	/* In some system designs where the regulators are not in use,
 	 * we can achieve a small reduction in leakage currents by
 	 * floating LDO outputs.  This bit makes no difference if the
@@ -554,7 +562,8 @@
 	regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
 err_supplies:
 	kfree(wm8994->supplies);
-err:
+err_regmap:
+	regmap_exit(wm8994->regmap);
 	mfd_remove_devices(wm8994->dev);
 	kfree(wm8994);
 	return ret;
@@ -569,62 +578,15 @@
 			       wm8994->supplies);
 	regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
 	kfree(wm8994->supplies);
+	regmap_exit(wm8994->regmap);
 	kfree(wm8994);
 }
 
-static int wm8994_i2c_read_device(struct wm8994 *wm8994, unsigned short reg,
-				  int bytes, void *dest)
-{
-	struct i2c_client *i2c = wm8994->control_data;
-	int ret;
-	u16 r = cpu_to_be16(reg);
-
-	ret = i2c_master_send(i2c, (unsigned char *)&r, 2);
-	if (ret < 0)
-		return ret;
-	if (ret != 2)
-		return -EIO;
-
-	ret = i2c_master_recv(i2c, dest, bytes);
-	if (ret < 0)
-		return ret;
-	if (ret != bytes)
-		return -EIO;
-	return 0;
-}
-
-static int wm8994_i2c_write_device(struct wm8994 *wm8994, unsigned short reg,
-				   int bytes, const void *src)
-{
-	struct i2c_client *i2c = wm8994->control_data;
-	struct i2c_msg xfer[2];
-	int ret;
-
-	reg = cpu_to_be16(reg);
-
-	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 != 2)
-		return -EIO;
-
-	return 0;
-}
-
 static int wm8994_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
 	struct wm8994 *wm8994;
+	int ret;
 
 	wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL);
 	if (wm8994 == NULL)
@@ -632,12 +594,18 @@
 
 	i2c_set_clientdata(i2c, wm8994);
 	wm8994->dev = &i2c->dev;
-	wm8994->control_data = i2c;
-	wm8994->read_dev = wm8994_i2c_read_device;
-	wm8994->write_dev = wm8994_i2c_write_device;
 	wm8994->irq = i2c->irq;
 	wm8994->type = id->driver_data;
 
+	wm8994->regmap = regmap_init_i2c(i2c, &wm8994_regmap_config);
+	if (IS_ERR(wm8994->regmap)) {
+		ret = PTR_ERR(wm8994->regmap);
+		dev_err(wm8994->dev, "Failed to allocate register map: %d\n",
+			ret);
+		kfree(wm8994);
+		return ret;
+	}
+
 	return wm8994_device_init(wm8994, i2c->irq);
 }
 
@@ -651,6 +619,7 @@
 }
 
 static const struct i2c_device_id wm8994_i2c_id[] = {
+	{ "wm1811", WM1811 },
 	{ "wm8994", WM8994 },
 	{ "wm8958", WM8958 },
 	{ }
diff -druN linux-libre-3.1-gnu/drivers/misc/ab8500-pwm.c linux-libre-3.2-gnu/drivers/misc/ab8500-pwm.c
--- linux-libre-3.1-gnu/drivers/misc/ab8500-pwm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/ab8500-pwm.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/pwm.h>
 #include <linux/mfd/ab8500.h>
 #include <linux/mfd/abx500.h>
+#include <linux/module.h>
 
 /*
  * PWM Out generators
diff -druN linux-libre-3.1-gnu/drivers/misc/ad525x_dpot.h linux-libre-3.2-gnu/drivers/misc/ad525x_dpot.h
--- linux-libre-3.1-gnu/drivers/misc/ad525x_dpot.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/ad525x_dpot.h	2012-01-04 18:55:44.000000000 -0500
@@ -100,7 +100,7 @@
 	AD5293_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 27),
 	AD7376_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
 			BRDAC0, 7, 28),
-	AD8400_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
+	AD8400_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
 			BRDAC0, 8, 29),
 	AD8402_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
 			BRDAC0 | BRDAC1, 8, 30),
diff -druN linux-libre-3.1-gnu/drivers/misc/ad525x_dpot-i2c.c linux-libre-3.2-gnu/drivers/misc/ad525x_dpot-i2c.c
--- linux-libre-3.1-gnu/drivers/misc/ad525x_dpot-i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/ad525x_dpot-i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -98,6 +98,7 @@
 	{"ad5282", AD5282_ID},
 	{"adn2860", ADN2860_ID},
 	{"ad5273", AD5273_ID},
+	{"ad5161", AD5161_ID},
 	{"ad5171", AD5171_ID},
 	{"ad5170", AD5170_ID},
 	{"ad5172", AD5172_ID},
diff -druN linux-libre-3.1-gnu/drivers/misc/altera-stapl/altera.c linux-libre-3.2-gnu/drivers/misc/altera-stapl/altera.c
--- linux-libre-3.1-gnu/drivers/misc/altera-stapl/altera.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/misc/altera-stapl/altera.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2537 @@
+/*
+ * 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 <linux/module.h>
+#include <misc/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 =
+				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;
+	int retval = 0;
+
+	key = kzalloc(33, GFP_KERNEL);
+	if (!key) {
+		retval = -ENOMEM;
+		goto out;
+	}
+	value = kzalloc(257, GFP_KERNEL);
+	if (!value) {
+		retval = -ENOMEM;
+		goto free_key;
+	}
+	astate = kzalloc(sizeof(struct altera_state), GFP_KERNEL);
+	if (!astate) {
+		retval = -ENOMEM;
+		goto free_value;
+	}
+
+	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(astate);
+free_value:
+	kfree(value);
+free_key:
+	kfree(key);
+out:
+	return retval;
+}
+EXPORT_SYMBOL(altera_init);
diff -druN linux-libre-3.1-gnu/drivers/misc/altera-stapl/altera-comp.c linux-libre-3.2-gnu/drivers/misc/altera-stapl/altera-comp.c
--- linux-libre-3.1-gnu/drivers/misc/altera-stapl/altera-comp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/misc/altera-stapl/altera-comp.c	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/drivers/misc/altera-stapl/altera-exprt.h linux-libre-3.2-gnu/drivers/misc/altera-stapl/altera-exprt.h
--- linux-libre-3.1-gnu/drivers/misc/altera-stapl/altera-exprt.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/misc/altera-stapl/altera-exprt.h	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/drivers/misc/altera-stapl/altera-jtag.c linux-libre-3.2-gnu/drivers/misc/altera-stapl/altera-jtag.c
--- linux-libre-3.1-gnu/drivers/misc/altera-stapl/altera-jtag.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/misc/altera-stapl/altera-jtag.c	2012-01-04 18:55:44.000000000 -0500
@@ -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 <misc/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-3.1-gnu/drivers/misc/altera-stapl/altera-jtag.h linux-libre-3.2-gnu/drivers/misc/altera-stapl/altera-jtag.h
--- linux-libre-3.1-gnu/drivers/misc/altera-stapl/altera-jtag.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/misc/altera-stapl/altera-jtag.h	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/drivers/misc/altera-stapl/altera-lpt.c linux-libre-3.2-gnu/drivers/misc/altera-stapl/altera-lpt.c
--- linux-libre-3.1-gnu/drivers/misc/altera-stapl/altera-lpt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/misc/altera-stapl/altera-lpt.c	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/drivers/misc/altera-stapl/Kconfig linux-libre-3.2-gnu/drivers/misc/altera-stapl/Kconfig
--- linux-libre-3.1-gnu/drivers/misc/altera-stapl/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/misc/altera-stapl/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/drivers/misc/altera-stapl/Makefile linux-libre-3.2-gnu/drivers/misc/altera-stapl/Makefile
--- linux-libre-3.1-gnu/drivers/misc/altera-stapl/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/misc/altera-stapl/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -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-3.1-gnu/drivers/misc/atmel-ssc.c linux-libre-3.2-gnu/drivers/misc/atmel-ssc.c
--- linux-libre-3.1-gnu/drivers/misc/atmel-ssc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/atmel-ssc.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/spinlock.h>
 #include <linux/atmel-ssc.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 /* Serialize access to ssc_list and user count */
 static DEFINE_SPINLOCK(user_lock);
diff -druN linux-libre-3.1-gnu/drivers/misc/atmel_tclib.c linux-libre-3.2-gnu/drivers/misc/atmel_tclib.c
--- linux-libre-3.1-gnu/drivers/misc/atmel_tclib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/atmel_tclib.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,6 +7,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 
 /* Number of bytes to reserve for the iomem resource */
 #define ATMEL_TC_IOMEM_SIZE	256
diff -druN linux-libre-3.1-gnu/drivers/misc/bh1780gli.c linux-libre-3.2-gnu/drivers/misc/bh1780gli.c
--- linux-libre-3.1-gnu/drivers/misc/bh1780gli.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/bh1780gli.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 
 #define BH1780_REG_CONTROL	0x80
 #define BH1780_REG_PARTID	0x8A
diff -druN linux-libre-3.1-gnu/drivers/misc/carma/carma-fpga.c linux-libre-3.2-gnu/drivers/misc/carma/carma-fpga.c
--- linux-libre-3.1-gnu/drivers/misc/carma/carma-fpga.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/carma/carma-fpga.c	2012-01-04 18:55:44.000000000 -0500
@@ -1249,8 +1249,7 @@
 	return true;
 }
 
-static int data_of_probe(struct platform_device *op,
-			 const struct of_device_id *match)
+static int data_of_probe(struct platform_device *op)
 {
 	struct device_node *of_node = op->dev.of_node;
 	struct device *this_device;
@@ -1401,7 +1400,7 @@
 	{},
 };
 
-static struct of_platform_driver data_of_driver = {
+static struct platform_driver data_of_driver = {
 	.probe		= data_of_probe,
 	.remove		= data_of_remove,
 	.driver		= {
@@ -1417,12 +1416,12 @@
 
 static int __init data_init(void)
 {
-	return of_register_platform_driver(&data_of_driver);
+	return platform_driver_register(&data_of_driver);
 }
 
 static void __exit data_exit(void)
 {
-	of_unregister_platform_driver(&data_of_driver);
+	platform_driver_unregister(&data_of_driver);
 }
 
 MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
diff -druN linux-libre-3.1-gnu/drivers/misc/carma/carma-fpga-program.c linux-libre-3.2-gnu/drivers/misc/carma/carma-fpga-program.c
--- linux-libre-3.1-gnu/drivers/misc/carma/carma-fpga-program.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/carma/carma-fpga-program.c	2012-01-04 18:55:44.000000000 -0500
@@ -945,8 +945,7 @@
 /* CTL-CPLD Version Register */
 #define CTL_CPLD_VERSION	0x2000
 
-static int fpga_of_probe(struct platform_device *op,
-			 const struct of_device_id *match)
+static int fpga_of_probe(struct platform_device *op)
 {
 	struct device_node *of_node = op->dev.of_node;
 	struct device *this_device;
@@ -1107,7 +1106,7 @@
 	{},
 };
 
-static struct of_platform_driver fpga_of_driver = {
+static struct platform_driver fpga_of_driver = {
 	.probe		= fpga_of_probe,
 	.remove		= fpga_of_remove,
 	.driver		= {
@@ -1124,12 +1123,12 @@
 static int __init fpga_init(void)
 {
 	led_trigger_register_simple("fpga", &ledtrig_fpga);
-	return of_register_platform_driver(&fpga_of_driver);
+	return platform_driver_register(&fpga_of_driver);
 }
 
 static void __exit fpga_exit(void)
 {
-	of_unregister_platform_driver(&fpga_of_driver);
+	platform_driver_unregister(&fpga_of_driver);
 	led_trigger_unregister_simple(ledtrig_fpga);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/misc/eeprom/Kconfig linux-libre-3.2-gnu/drivers/misc/eeprom/Kconfig
--- linux-libre-3.1-gnu/drivers/misc/eeprom/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/eeprom/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -85,7 +85,7 @@
 
 config EEPROM_DIGSY_MTC_CFG
 	bool "DigsyMTC display configuration EEPROMs device"
-	depends on PPC_MPC5200_GPIO && GPIOLIB && SPI_GPIO
+	depends on GPIO_MPC5200 && SPI_GPIO
 	help
 	  This option enables access to display configuration EEPROMs
 	  on digsy_mtc board. You have to additionally select Microwire
diff -druN linux-libre-3.1-gnu/drivers/misc/fsa9480.c linux-libre-3.2-gnu/drivers/misc/fsa9480.c
--- linux-libre-3.1-gnu/drivers/misc/fsa9480.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/fsa9480.c	2012-01-04 18:55:44.000000000 -0500
@@ -400,7 +400,8 @@
 			return ret;
 		}
 
-		device_init_wakeup(&client->dev, pdata->wakeup);
+		if (pdata)
+			device_init_wakeup(&client->dev, pdata->wakeup);
 	}
 
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/misc/Kconfig linux-libre-3.2-gnu/drivers/misc/Kconfig
--- linux-libre-3.1-gnu/drivers/misc/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -63,7 +63,7 @@
 
 config ATMEL_PWM
 	tristate "Atmel AT32/AT91 PWM support"
-	depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9
+	depends on HAVE_CLK
 	help
 	  This option enables device driver support for the PWM channels
 	  on certain Atmel processors.  Pulse Width Modulation is used for
@@ -472,7 +472,7 @@
 	  module will be called bmp085.
 
 config PCH_PHUB
-	tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB"
+	tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) PHUB"
 	depends on PCI
 	help
 	  This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of
@@ -480,12 +480,13 @@
 	  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 IOH(Input/
-	  Output Hub), ML7213 and ML7223.
-	  ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is
-	  for MP(Media Phone) use.
-	  ML7213/ML7223 is companion chip for Intel Atom E6xx series.
-	  ML7213/ML7223 is completely compatible for Intel EG20T PCH.
+	  This driver also can be used for LAPIS Semiconductor's IOH,
+	  ML7213/ML7223/ML7831.
+	  ML7213 which is for IVI(In-Vehicle Infotainment) use.
+	  ML7223 IOH is for MP(Media Phone) use.
+	  ML7831 IOH is for general purpose use.
+	  ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series.
+	  ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH.
 
 	  To compile this driver as a module, choose M here: the module will
 	  be called pch_phub.
@@ -506,5 +507,6 @@
 source "drivers/misc/ti-st/Kconfig"
 source "drivers/misc/lis3lv02d/Kconfig"
 source "drivers/misc/carma/Kconfig"
+source "drivers/misc/altera-stapl/Kconfig"
 
 endif # MISC_DEVICES
diff -druN linux-libre-3.1-gnu/drivers/misc/kgdbts.c linux-libre-3.2-gnu/drivers/misc/kgdbts.c
--- linux-libre-3.1-gnu/drivers/misc/kgdbts.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/kgdbts.c	2012-01-04 18:55:44.000000000 -0500
@@ -102,6 +102,7 @@
 #include <linux/nmi.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
+#include <linux/module.h>
 
 #define v1printk(a...) do { \
 	if (verbose) \
diff -druN linux-libre-3.1-gnu/drivers/misc/lis3lv02d/lis3lv02d.c linux-libre-3.2-gnu/drivers/misc/lis3lv02d/lis3lv02d.c
--- linux-libre-3.1-gnu/drivers/misc/lis3lv02d/lis3lv02d.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/lis3lv02d/lis3lv02d.c	2012-01-04 18:55:44.000000000 -0500
@@ -163,7 +163,7 @@
 	int i;
 
 	if (lis3->blkread) {
-		if (lis3_dev.whoami == WAI_12B) {
+		if (lis3->whoami == WAI_12B) {
 			u16 data[3];
 			lis3->blkread(lis3, OUTX_L, 6, (u8 *)data);
 			for (i = 0; i < 3; i++)
@@ -195,18 +195,30 @@
 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)
+static int lis3lv02d_get_odr(struct lis3lv02d *lis3)
 {
 	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)];
+	lis3->read(lis3, CTRL_REG1, &ctrl);
+	ctrl &= lis3->odr_mask;
+	shift = ffs(lis3->odr_mask) - 1;
+	return lis3->odrs[(ctrl >> shift)];
 }
 
-static int lis3lv02d_set_odr(int rate)
+static int lis3lv02d_get_pwron_wait(struct lis3lv02d *lis3)
+{
+	int div = lis3lv02d_get_odr(lis3);
+
+	if (WARN_ONCE(div == 0, "device returned spurious data"))
+		return -ENXIO;
+
+	/* LIS3 power on delay is quite long */
+	msleep(lis3->pwron_delay / div);
+	return 0;
+}
+
+static int lis3lv02d_set_odr(struct lis3lv02d *lis3, int rate)
 {
 	u8 ctrl;
 	int i, len, shift;
@@ -214,14 +226,14 @@
 	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;
+	lis3->read(lis3, CTRL_REG1, &ctrl);
+	ctrl &= ~lis3->odr_mask;
+	len = 1 << hweight_long(lis3->odr_mask); /* # of possible values */
+	shift = ffs(lis3->odr_mask) - 1;
 
 	for (i = 0; i < len; i++)
-		if (lis3_dev.odrs[i] == rate) {
-			lis3_dev.write(&lis3_dev, CTRL_REG1,
+		if (lis3->odrs[i] == rate) {
+			lis3->write(lis3, CTRL_REG1,
 					ctrl | (i << shift));
 			return 0;
 		}
@@ -240,12 +252,12 @@
 	mutex_lock(&lis3->mutex);
 
 	irq_cfg = lis3->irq_cfg;
-	if (lis3_dev.whoami == WAI_8B) {
+	if (lis3->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);
+		atomic_inc(&lis3->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 &
@@ -253,12 +265,12 @@
 				(LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
 	}
 
-	if (lis3_dev.whoami == WAI_3DC) {
+	if (lis3->whoami == WAI_3DC) {
 		ctlreg = CTRL_REG4;
 		selftest = CTRL4_ST0;
 	} else {
 		ctlreg = CTRL_REG1;
-		if (lis3_dev.whoami == WAI_12B)
+		if (lis3->whoami == WAI_12B)
 			selftest = CTRL1_ST;
 		else
 			selftest = CTRL1_STP;
@@ -266,7 +278,9 @@
 
 	lis3->read(lis3, ctlreg, &reg);
 	lis3->write(lis3, ctlreg, (reg | selftest));
-	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+	ret = lis3lv02d_get_pwron_wait(lis3);
+	if (ret)
+		goto fail;
 
 	/* Read directly to avoid axis remap */
 	x = lis3->read_data(lis3, OUTX);
@@ -275,7 +289,9 @@
 
 	/* back to normal settings */
 	lis3->write(lis3, ctlreg, reg);
-	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+	ret = lis3lv02d_get_pwron_wait(lis3);
+	if (ret)
+		goto fail;
 
 	results[0] = x - lis3->read_data(lis3, OUTX);
 	results[1] = y - lis3->read_data(lis3, OUTY);
@@ -283,9 +299,9 @@
 
 	ret = 0;
 
-	if (lis3_dev.whoami == WAI_8B) {
+	if (lis3->whoami == WAI_8B) {
 		/* Restore original interrupt configuration */
-		atomic_dec(&lis3_dev.wake_thread);
+		atomic_dec(&lis3->wake_thread);
 		lis3->write(lis3, CTRL_REG3, ctrl_reg_data);
 		lis3->irq_cfg = irq_cfg;
 
@@ -363,8 +379,9 @@
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
 
-void lis3lv02d_poweron(struct lis3lv02d *lis3)
+int lis3lv02d_poweron(struct lis3lv02d *lis3)
 {
+	int err;
 	u8 reg;
 
 	lis3->init(lis3);
@@ -384,35 +401,41 @@
 		lis3->write(lis3, CTRL_REG2, reg);
 	}
 
-	/* LIS3 power on delay is quite long */
-	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+	err = lis3lv02d_get_pwron_wait(lis3);
+	if (err)
+		return err;
 
 	if (lis3->reg_ctrl)
 		lis3_context_restore(lis3);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
 
 
 static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
 {
+	struct lis3lv02d *lis3 = pidev->private;
 	int x, y, z;
 
-	mutex_lock(&lis3_dev.mutex);
-	lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
+	mutex_lock(&lis3->mutex);
+	lis3lv02d_get_xyz(lis3, &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);
+	mutex_unlock(&lis3->mutex);
 }
 
 static void lis3lv02d_joystick_open(struct input_polled_dev *pidev)
 {
-	if (lis3_dev.pm_dev)
-		pm_runtime_get_sync(lis3_dev.pm_dev);
+	struct lis3lv02d *lis3 = pidev->private;
 
-	if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev)
-		atomic_set(&lis3_dev.wake_thread, 1);
+	if (lis3->pm_dev)
+		pm_runtime_get_sync(lis3->pm_dev);
+
+	if (lis3->pdata && lis3->whoami == WAI_8B && lis3->idev)
+		atomic_set(&lis3->wake_thread, 1);
 	/*
 	 * Update coordinates for the case where poll interval is 0 and
 	 * the chip in running purely under interrupt control
@@ -422,14 +445,18 @@
 
 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);
+	struct lis3lv02d *lis3 = pidev->private;
+
+	atomic_set(&lis3->wake_thread, 0);
+	if (lis3->pm_dev)
+		pm_runtime_put(lis3->pm_dev);
 }
 
-static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
+static irqreturn_t lis302dl_interrupt(int irq, void *data)
 {
-	if (!test_bit(0, &lis3_dev.misc_opened))
+	struct lis3lv02d *lis3 = data;
+
+	if (!test_bit(0, &lis3->misc_opened))
 		goto out;
 
 	/*
@@ -437,12 +464,12 @@
 	 * the lid is closed. This leads to interrupts as soon as a little move
 	 * is done.
 	 */
-	atomic_inc(&lis3_dev.count);
+	atomic_inc(&lis3->count);
 
-	wake_up_interruptible(&lis3_dev.misc_wait);
-	kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
+	wake_up_interruptible(&lis3->misc_wait);
+	kill_fasync(&lis3->async_queue, SIGIO, POLL_IN);
 out:
-	if (atomic_read(&lis3_dev.wake_thread))
+	if (atomic_read(&lis3->wake_thread))
 		return IRQ_WAKE_THREAD;
 	return IRQ_HANDLED;
 }
@@ -514,28 +541,37 @@
 
 static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
 {
-	if (test_and_set_bit(0, &lis3_dev.misc_opened))
+	struct lis3lv02d *lis3 = container_of(file->private_data,
+					      struct lis3lv02d, miscdev);
+
+	if (test_and_set_bit(0, &lis3->misc_opened))
 		return -EBUSY; /* already open */
 
-	if (lis3_dev.pm_dev)
-		pm_runtime_get_sync(lis3_dev.pm_dev);
+	if (lis3->pm_dev)
+		pm_runtime_get_sync(lis3->pm_dev);
 
-	atomic_set(&lis3_dev.count, 0);
+	atomic_set(&lis3->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);
+	struct lis3lv02d *lis3 = container_of(file->private_data,
+					      struct lis3lv02d, miscdev);
+
+	fasync_helper(-1, file, 0, &lis3->async_queue);
+	clear_bit(0, &lis3->misc_opened); /* release the device */
+	if (lis3->pm_dev)
+		pm_runtime_put(lis3->pm_dev);
 	return 0;
 }
 
 static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
 				size_t count, loff_t *pos)
 {
+	struct lis3lv02d *lis3 = container_of(file->private_data,
+					      struct lis3lv02d, miscdev);
+
 	DECLARE_WAITQUEUE(wait, current);
 	u32 data;
 	unsigned char byte_data;
@@ -544,10 +580,10 @@
 	if (count < 1)
 		return -EINVAL;
 
-	add_wait_queue(&lis3_dev.misc_wait, &wait);
+	add_wait_queue(&lis3->misc_wait, &wait);
 	while (true) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		data = atomic_xchg(&lis3_dev.count, 0);
+		data = atomic_xchg(&lis3->count, 0);
 		if (data)
 			break;
 
@@ -577,22 +613,28 @@
 
 out:
 	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&lis3_dev.misc_wait, &wait);
+	remove_wait_queue(&lis3->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))
+	struct lis3lv02d *lis3 = container_of(file->private_data,
+					      struct lis3lv02d, miscdev);
+
+	poll_wait(file, &lis3->misc_wait, wait);
+	if (atomic_read(&lis3->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);
+	struct lis3lv02d *lis3 = container_of(file->private_data,
+					      struct lis3lv02d, miscdev);
+
+	return fasync_helper(fd, file, on, &lis3->async_queue);
 }
 
 static const struct file_operations lis3lv02d_misc_fops = {
@@ -605,85 +647,80 @@
 	.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)
+int lis3lv02d_joystick_enable(struct lis3lv02d *lis3)
 {
 	struct input_dev *input_dev;
 	int err;
 	int max_val, fuzz, flat;
 	int btns[] = {BTN_X, BTN_Y, BTN_Z};
 
-	if (lis3_dev.idev)
+	if (lis3->idev)
 		return -EINVAL;
 
-	lis3_dev.idev = input_allocate_polled_device();
-	if (!lis3_dev.idev)
+	lis3->idev = input_allocate_polled_device();
+	if (!lis3->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;
+	lis3->idev->poll = lis3lv02d_joystick_poll;
+	lis3->idev->open = lis3lv02d_joystick_open;
+	lis3->idev->close = lis3lv02d_joystick_close;
+	lis3->idev->poll_interval = MDPS_POLL_INTERVAL;
+	lis3->idev->poll_interval_min = MDPS_POLL_MIN;
+	lis3->idev->poll_interval_max = MDPS_POLL_MAX;
+	lis3->idev->private = lis3;
+	input_dev = lis3->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;
+	input_dev->dev.parent = &lis3->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) {
+	max_val = (lis3->mdps_max_val * lis3->scale) / LIS3_ACCURACY;
+	if (lis3->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;
+	fuzz = (fuzz * lis3->scale) / LIS3_ACCURACY;
+	flat = (flat * lis3->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);
+	lis3->mapped_btns[0] = lis3lv02d_get_axis(abs(lis3->ac.x), btns);
+	lis3->mapped_btns[1] = lis3lv02d_get_axis(abs(lis3->ac.y), btns);
+	lis3->mapped_btns[2] = lis3lv02d_get_axis(abs(lis3->ac.z), btns);
 
-	err = input_register_polled_device(lis3_dev.idev);
+	err = input_register_polled_device(lis3->idev);
 	if (err) {
-		input_free_polled_device(lis3_dev.idev);
-		lis3_dev.idev = NULL;
+		input_free_polled_device(lis3->idev);
+		lis3->idev = NULL;
 	}
 
 	return err;
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable);
 
-void lis3lv02d_joystick_disable(void)
+void lis3lv02d_joystick_disable(struct lis3lv02d *lis3)
 {
-	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->irq)
+		free_irq(lis3->irq, lis3);
+	if (lis3->pdata && lis3->pdata->irq2)
+		free_irq(lis3->pdata->irq2, lis3);
 
-	if (!lis3_dev.idev)
+	if (!lis3->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;
+	if (lis3->irq)
+		misc_deregister(&lis3->miscdev);
+	input_unregister_polled_device(lis3->idev);
+	input_free_polled_device(lis3->idev);
+	lis3->idev = NULL;
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
 
@@ -708,6 +745,7 @@
 static ssize_t lis3lv02d_selftest_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
+	struct lis3lv02d *lis3 = dev_get_drvdata(dev);
 	s16 values[3];
 
 	static const char ok[] = "OK";
@@ -715,8 +753,8 @@
 	static const char irq[] = "FAIL_IRQ";
 	const char *res;
 
-	lis3lv02d_sysfs_poweron(&lis3_dev);
-	switch (lis3lv02d_selftest(&lis3_dev, values)) {
+	lis3lv02d_sysfs_poweron(lis3);
+	switch (lis3lv02d_selftest(lis3, values)) {
 	case SELFTEST_FAIL:
 		res = fail;
 		break;
@@ -735,33 +773,37 @@
 static ssize_t lis3lv02d_position_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
+	struct lis3lv02d *lis3 = dev_get_drvdata(dev);
 	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);
+	lis3lv02d_sysfs_poweron(lis3);
+	mutex_lock(&lis3->mutex);
+	lis3lv02d_get_xyz(lis3, &x, &y, &z);
+	mutex_unlock(&lis3->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());
+	struct lis3lv02d *lis3 = dev_get_drvdata(dev);
+
+	lis3lv02d_sysfs_poweron(lis3);
+	return sprintf(buf, "%d\n", lis3lv02d_get_odr(lis3));
 }
 
 static ssize_t lis3lv02d_rate_set(struct device *dev,
 				struct device_attribute *attr, const char *buf,
 				size_t count)
 {
+	struct lis3lv02d *lis3 = dev_get_drvdata(dev);
 	unsigned long rate;
 
 	if (strict_strtoul(buf, 0, &rate))
 		return -EINVAL;
 
-	lis3lv02d_sysfs_poweron(&lis3_dev);
-	if (lis3lv02d_set_odr(rate))
+	lis3lv02d_sysfs_poweron(lis3);
+	if (lis3lv02d_set_odr(lis3, rate))
 		return -EINVAL;
 
 	return count;
@@ -790,6 +832,7 @@
 	if (IS_ERR(lis3->pdev))
 		return PTR_ERR(lis3->pdev);
 
+	platform_set_drvdata(lis3->pdev, lis3);
 	return sysfs_create_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
 }
 
@@ -803,7 +846,7 @@
 
 		/* SYSFS may have left chip running. Turn off if necessary */
 		if (!pm_runtime_suspended(lis3->pm_dev))
-			lis3lv02d_poweroff(&lis3_dev);
+			lis3lv02d_poweroff(lis3);
 
 		pm_runtime_disable(lis3->pm_dev);
 		pm_runtime_set_suspended(lis3->pm_dev);
@@ -813,24 +856,24 @@
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
 
-static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
+static void lis3lv02d_8b_configure(struct lis3lv02d *lis3,
 				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,
+		lis3->write(lis3, CLICK_CFG, p->click_flags);
+		lis3->write(lis3, CLICK_TIMELIMIT, p->click_time_limit);
+		lis3->write(lis3, CLICK_LATENCY, p->click_latency);
+		lis3->write(lis3, CLICK_WINDOW, p->click_window);
+		lis3->write(lis3, CLICK_THSZ, p->click_thresh_z & 0xf);
+		lis3->write(lis3, 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;
+		if (lis3->idev) {
+			struct input_dev *input_dev = lis3->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);
@@ -838,22 +881,22 @@
 	}
 
 	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);
+		lis3->write(lis3, FF_WU_CFG_1, p->wakeup_flags);
+		lis3->write(lis3, 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);
+		lis3->write(lis3, 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);
+		lis3->write(lis3, FF_WU_CFG_2, p->wakeup_flags2);
+		lis3->write(lis3, 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);
+		lis3->write(lis3, 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);
+	lis3->write(lis3, CTRL_REG2, ctrl2);
 
 	if (p->irq2) {
 		err = request_threaded_irq(p->irq2,
@@ -861,7 +904,7 @@
 					lis302dl_interrupt_thread2_8b,
 					IRQF_TRIGGER_RISING | IRQF_ONESHOT |
 					(p->irq_flags2 & IRQF_TRIGGER_MASK),
-					DRIVER_NAME, &lis3_dev);
+					DRIVER_NAME, lis3);
 		if (err < 0)
 			pr_err("No second IRQ. Limited functionality\n");
 	}
@@ -871,93 +914,97 @@
  * Initialise the accelerometer and the various subsystems.
  * Should be rather independent of the bus system.
  */
-int lis3lv02d_init_device(struct lis3lv02d *dev)
+int lis3lv02d_init_device(struct lis3lv02d *lis3)
 {
 	int err;
 	irq_handler_t thread_fn;
 	int irq_flags = 0;
 
-	dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I);
+	lis3->whoami = lis3lv02d_read_8(lis3, WHO_AM_I);
 
-	switch (dev->whoami) {
+	switch (lis3->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);
+		lis3->read_data = lis3lv02d_read_12;
+		lis3->mdps_max_val = 2048;
+		lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_12B;
+		lis3->odrs = lis3_12_rates;
+		lis3->odr_mask = CTRL1_DF0 | CTRL1_DF1;
+		lis3->scale = LIS3_SENSITIVITY_12B;
+		lis3->regs = lis3_wai12_regs;
+		lis3->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);
+		lis3->read_data = lis3lv02d_read_8;
+		lis3->mdps_max_val = 128;
+		lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
+		lis3->odrs = lis3_8_rates;
+		lis3->odr_mask = CTRL1_DR;
+		lis3->scale = LIS3_SENSITIVITY_8B;
+		lis3->regs = lis3_wai8_regs;
+		lis3->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;
+		lis3->read_data = lis3lv02d_read_8;
+		lis3->mdps_max_val = 128;
+		lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
+		lis3->odrs = lis3_3dc_rates;
+		lis3->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
+		lis3->scale = LIS3_SENSITIVITY_8B;
 		break;
 	default:
-		pr_err("unknown sensor type 0x%X\n", dev->whoami);
+		pr_err("unknown sensor type 0x%X\n", lis3->whoami);
 		return -EINVAL;
 	}
 
-	dev->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs),
+	lis3->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs),
 				     sizeof(lis3_wai12_regs)), GFP_KERNEL);
 
-	if (dev->reg_cache == NULL) {
+	if (lis3->reg_cache == NULL) {
 		printk(KERN_ERR DRIVER_NAME "out of memory\n");
 		return -ENOMEM;
 	}
 
-	mutex_init(&dev->mutex);
-	atomic_set(&dev->wake_thread, 0);
+	mutex_init(&lis3->mutex);
+	atomic_set(&lis3->wake_thread, 0);
 
-	lis3lv02d_add_fs(dev);
-	lis3lv02d_poweron(dev);
+	lis3lv02d_add_fs(lis3);
+	err = lis3lv02d_poweron(lis3);
+	if (err) {
+		lis3lv02d_remove_fs(lis3);
+		return err;
+	}
 
-	if (dev->pm_dev) {
-		pm_runtime_set_active(dev->pm_dev);
-		pm_runtime_enable(dev->pm_dev);
+	if (lis3->pm_dev) {
+		pm_runtime_set_active(lis3->pm_dev);
+		pm_runtime_enable(lis3->pm_dev);
 	}
 
-	if (lis3lv02d_joystick_enable())
+	if (lis3lv02d_joystick_enable(lis3))
 		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 (lis3->pdata) {
+		struct lis3lv02d_platform_data *p = lis3->pdata;
 
-		if (dev->whoami == WAI_8B)
-			lis3lv02d_8b_configure(dev, p);
+		if (lis3->whoami == WAI_8B)
+			lis3lv02d_8b_configure(lis3, p);
 
 		irq_flags = p->irq_flags1 & IRQF_TRIGGER_MASK;
 
-		dev->irq_cfg = p->irq_cfg;
+		lis3->irq_cfg = p->irq_cfg;
 		if (p->irq_cfg)
-			dev->write(dev, CTRL_REG3, p->irq_cfg);
+			lis3->write(lis3, CTRL_REG3, p->irq_cfg);
 
 		if (p->default_rate)
-			lis3lv02d_set_odr(p->default_rate);
+			lis3lv02d_set_odr(lis3, p->default_rate);
 	}
 
 	/* bail if we did not get an IRQ from the bus layer */
-	if (!dev->irq) {
+	if (!lis3->irq) {
 		pr_debug("No IRQ. Disabling /dev/freefall\n");
 		goto out;
 	}
@@ -973,23 +1020,27 @@
 	 * 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)
+	if (lis3->pdata && lis3->whoami == WAI_8B)
 		thread_fn = lis302dl_interrupt_thread1_8b;
 	else
 		thread_fn = NULL;
 
-	err = request_threaded_irq(dev->irq, lis302dl_interrupt,
+	err = request_threaded_irq(lis3->irq, lis302dl_interrupt,
 				thread_fn,
 				IRQF_TRIGGER_RISING | IRQF_ONESHOT |
 				irq_flags,
-				DRIVER_NAME, &lis3_dev);
+				DRIVER_NAME, lis3);
 
 	if (err < 0) {
 		pr_err("Cannot get IRQ\n");
 		goto out;
 	}
 
-	if (misc_register(&lis3lv02d_misc_device))
+	lis3->miscdev.minor	= MISC_DYNAMIC_MINOR;
+	lis3->miscdev.name	= "freefall";
+	lis3->miscdev.fops	= &lis3lv02d_misc_fops;
+
+	if (misc_register(&lis3->miscdev))
 		pr_err("misc_register failed\n");
 out:
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/misc/lis3lv02d/lis3lv02d.h linux-libre-3.2-gnu/drivers/misc/lis3lv02d/lis3lv02d.h
--- linux-libre-3.1-gnu/drivers/misc/lis3lv02d/lis3lv02d.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/lis3lv02d/lis3lv02d.h	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/input-polldev.h>
 #include <linux/regulator/consumer.h>
+#include <linux/miscdevice.h>
 
 /*
  * This driver tries to support the "digital" accelerometer chips from
@@ -273,6 +274,8 @@
 	struct fasync_struct	*async_queue; /* queue for the misc device */
 	wait_queue_head_t	misc_wait; /* Wait queue for the misc device */
 	unsigned long		misc_opened; /* bit0: whether the device is open */
+	struct miscdevice	miscdev;
+
 	int                     data_ready_count[2];
 	atomic_t		wake_thread;
 	unsigned char           irq_cfg;
@@ -282,10 +285,10 @@
 };
 
 int lis3lv02d_init_device(struct lis3lv02d *lis3);
-int lis3lv02d_joystick_enable(void);
-void lis3lv02d_joystick_disable(void);
+int lis3lv02d_joystick_enable(struct lis3lv02d *lis3);
+void lis3lv02d_joystick_disable(struct lis3lv02d *lis3);
 void lis3lv02d_poweroff(struct lis3lv02d *lis3);
-void lis3lv02d_poweron(struct lis3lv02d *lis3);
+int lis3lv02d_poweron(struct lis3lv02d *lis3);
 int lis3lv02d_remove_fs(struct lis3lv02d *lis3);
 
 extern struct lis3lv02d lis3_dev;
diff -druN linux-libre-3.1-gnu/drivers/misc/lis3lv02d/lis3lv02d_i2c.c linux-libre-3.2-gnu/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
--- linux-libre-3.1-gnu/drivers/misc/lis3lv02d/lis3lv02d_i2c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/lis3lv02d/lis3lv02d_i2c.c	2012-01-04 18:55:44.000000000 -0500
@@ -79,8 +79,7 @@
 	u8 reg;
 	int ret;
 
-	if (lis3->reg_ctrl)
-		lis3_reg_ctrl(lis3, LIS3_REG_ON);
+	lis3_reg_ctrl(lis3, LIS3_REG_ON);
 
 	lis3->read(lis3, WHO_AM_I, &reg);
 	if (reg != lis3->whoami)
@@ -106,10 +105,6 @@
 	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)))
@@ -131,15 +126,13 @@
 			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.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;
@@ -153,16 +146,19 @@
 	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);
+	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);
+	lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
 
-	if (ret == 0)
-		return 0;
+	if (ret)
+		goto fail2;
+	return 0;
+
+fail2:
+	regulator_bulk_free(ARRAY_SIZE(lis3_dev.regulators),
+				lis3_dev.regulators);
 fail:
 	if (pdata && pdata->release_resources)
 		pdata->release_resources();
@@ -177,12 +173,11 @@
 	if (pdata && pdata->release_resources)
 		pdata->release_resources();
 
-	lis3lv02d_joystick_disable();
+	lis3lv02d_joystick_disable(lis3);
 	lis3lv02d_remove_fs(&lis3_dev);
 
-	if (lis3_dev.reg_ctrl)
-		regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
-				lis3_dev.regulators);
+	regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
+			    lis3_dev.regulators);
 	return 0;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/misc/lis3lv02d/lis3lv02d_spi.c linux-libre-3.2-gnu/drivers/misc/lis3lv02d/lis3lv02d_spi.c
--- linux-libre-3.1-gnu/drivers/misc/lis3lv02d/lis3lv02d_spi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/lis3lv02d/lis3lv02d_spi.c	2012-01-04 18:55:44.000000000 -0500
@@ -83,7 +83,7 @@
 static int __devexit lis302dl_spi_remove(struct spi_device *spi)
 {
 	struct lis3lv02d *lis3 = spi_get_drvdata(spi);
-	lis3lv02d_joystick_disable();
+	lis3lv02d_joystick_disable(lis3);
 	lis3lv02d_poweroff(lis3);
 
 	return lis3lv02d_remove_fs(&lis3_dev);
diff -druN linux-libre-3.1-gnu/drivers/misc/Makefile linux-libre-3.2-gnu/drivers/misc/Makefile
--- linux-libre-3.1-gnu/drivers/misc/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -47,3 +47,4 @@
 obj-y				+= lis3lv02d/
 obj-y				+= carma/
 obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
+obj-$(CONFIG_ALTERA_STAPL)	+=altera-stapl/
diff -druN linux-libre-3.1-gnu/drivers/misc/pch_phub.c linux-libre-3.2-gnu/drivers/misc/pch_phub.c
--- linux-libre-3.1-gnu/drivers/misc/pch_phub.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/pch_phub.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
+ * Copyright (C) 2011 LAPIS 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
@@ -41,10 +41,10 @@
 #define PCH_PHUB_ROM_START_ADDR_EG20T 0x80 /* 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)
+						offset(LAPIS Semicon ML7213)
 					      */
 #define PCH_PHUB_ROM_START_ADDR_ML7223 0x400 /* ROM data area start address
-						offset(OKI SEMICONDUCTOR ML7223)
+						offset(LAPIS Semicon ML7223)
 					      */
 
 /* MAX number of INT_REDUCE_CONTROL registers */
@@ -73,6 +73,9 @@
 #define PCI_DEVICE_ID_ROHM_ML7223_mPHUB	0x8012 /* for Bus-m */
 #define PCI_DEVICE_ID_ROHM_ML7223_nPHUB	0x8002 /* for Bus-n */
 
+/* Macros for ML7831 */
+#define PCI_DEVICE_ID_ROHM_ML7831_PHUB 0x8801
+
 /* SROM ACCESS Macro */
 #define PCH_WORD_ADDR_MASK (~((1 << 2) - 1))
 
@@ -90,6 +93,7 @@
 #define PCH_PHUB_INTPIN_REG_WPERMIT_REG3	0x002C
 #define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE	0x0040
 #define CLKCFG_REG_OFFSET			0x500
+#define FUNCSEL_REG_OFFSET			0x508
 
 #define PCH_PHUB_OROM_SIZE 15360
 
@@ -108,11 +112,13 @@
  * @intpin_reg_wpermit_reg3:		INTPIN_REG_WPERMIT register 3 val
  * @int_reduce_control_reg:		INT_REDUCE_CONTROL registers val
  * @clkcfg_reg:				CLK CFG register val
+ * @funcsel_reg:			Function select register value
  * @pch_phub_base_address:		Register base address
  * @pch_phub_extrom_base_address:	external rom base address
  * @pch_mac_start_address:		MAC address area start address
  * @pch_opt_rom_start_address:		Option ROM start address
  * @ioh_type:				Save IOH type
+ * @pdev:				pointer to pci device struct
  */
 struct pch_phub_reg {
 	u32 phub_id_reg;
@@ -128,11 +134,13 @@
 	u32 intpin_reg_wpermit_reg3;
 	u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
 	u32 clkcfg_reg;
+	u32 funcsel_reg;
 	void __iomem *pch_phub_base_address;
 	void __iomem *pch_phub_extrom_base_address;
 	u32 pch_mac_start_address;
 	u32 pch_opt_rom_start_address;
 	int ioh_type;
+	struct pci_dev *pdev;
 };
 
 /* SROM SPEC for MAC address assignment offset */
@@ -211,6 +219,8 @@
 			__func__, i, chip->int_reduce_control_reg[i]);
 	}
 	chip->clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET);
+	if ((chip->ioh_type == 2) || (chip->ioh_type == 4))
+		chip->funcsel_reg = ioread32(p + FUNCSEL_REG_OFFSET);
 }
 
 /* pch_phub_restore_reg_conf - restore register configuration */
@@ -271,6 +281,8 @@
 	}
 
 	iowrite32(chip->clkcfg_reg, p + CLKCFG_REG_OFFSET);
+	if ((chip->ioh_type == 2) || (chip->ioh_type == 4))
+		iowrite32(chip->funcsel_reg, p + FUNCSEL_REG_OFFSET);
 }
 
 /**
@@ -464,7 +476,7 @@
 	int retval;
 	int i;
 
-	if (chip->ioh_type == 1) /* EG20T */
+	if ((chip->ioh_type == 1) || (chip->ioh_type == 5)) /* EG20T or ML7831*/
 		retval = pch_phub_gbe_serial_rom_conf(chip);
 	else	/* ML7223 */
 		retval = pch_phub_gbe_serial_rom_conf_mp(chip);
@@ -491,6 +503,7 @@
 	unsigned int orom_size;
 	int ret;
 	int err;
+	ssize_t rom_size;
 
 	struct pch_phub_reg *chip =
 		dev_get_drvdata(container_of(kobj, struct device, kobj));
@@ -502,6 +515,10 @@
 	}
 
 	/* Get Rom signature */
+	chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
+	if (!chip->pch_phub_extrom_base_address)
+		goto exrom_map_err;
+
 	pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address,
 				(unsigned char *)&rom_signature);
 	rom_signature &= 0xff;
@@ -532,10 +549,13 @@
 		goto return_err;
 	}
 return_ok:
+	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
 	mutex_unlock(&pch_phub_mutex);
 	return addr_offset;
 
 return_err:
+	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
+exrom_map_err:
 	mutex_unlock(&pch_phub_mutex);
 return_err_nomutex:
 	return err;
@@ -548,6 +568,7 @@
 	int err;
 	unsigned int addr_offset;
 	int ret;
+	ssize_t rom_size;
 	struct pch_phub_reg *chip =
 		dev_get_drvdata(container_of(kobj, struct device, kobj));
 
@@ -564,6 +585,12 @@
 		goto return_ok;
 	}
 
+	chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
+	if (!chip->pch_phub_extrom_base_address) {
+		err = -ENOMEM;
+		goto exrom_map_err;
+	}
+
 	for (addr_offset = 0; addr_offset < count; addr_offset++) {
 		if (PCH_PHUB_OROM_SIZE < off + addr_offset)
 			goto return_ok;
@@ -578,10 +605,14 @@
 	}
 
 return_ok:
+	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
 	mutex_unlock(&pch_phub_mutex);
 	return addr_offset;
 
 return_err:
+	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
+
+exrom_map_err:
 	mutex_unlock(&pch_phub_mutex);
 	return err;
 }
@@ -591,17 +622,23 @@
 {
 	u8 mac[8];
 	struct pch_phub_reg *chip = dev_get_drvdata(dev);
+	ssize_t rom_size;
+
+	chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
+	if (!chip->pch_phub_extrom_base_address)
+		return -ENOMEM;
 
 	pch_phub_read_gbe_mac_addr(chip, mac);
+	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
 
-	return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
-				mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+	return sprintf(buf, "%pM\n", mac);
 }
 
 static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
 			     const char *buf, size_t count)
 {
 	u8 mac[6];
+	ssize_t rom_size;
 	struct pch_phub_reg *chip = dev_get_drvdata(dev);
 
 	if (count != 18)
@@ -611,7 +648,12 @@
 		(u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2], (u32 *)&mac[3],
 		(u32 *)&mac[4], (u32 *)&mac[5]);
 
+	chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
+	if (!chip->pch_phub_extrom_base_address)
+		return -ENOMEM;
+
 	pch_phub_write_gbe_mac_addr(chip, mac);
+	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
 
 	return count;
 }
@@ -634,7 +676,6 @@
 	int retval;
 
 	int ret;
-	ssize_t rom_size;
 	struct pch_phub_reg *chip;
 
 	chip = kzalloc(sizeof(struct pch_phub_reg), GFP_KERNEL);
@@ -671,19 +712,7 @@
 		"in pch_phub_base_address variable is %p\n", __func__,
 		chip->pch_phub_base_address);
 
-	if (id->driver_data != 3) {
-		chip->pch_phub_extrom_base_address =\
-						   pci_map_rom(pdev, &rom_size);
-		if (chip->pch_phub_extrom_base_address == 0) {
-			dev_err(&pdev->dev, "%s: pci_map_rom FAILED", __func__);
-			ret = -ENOMEM;
-			goto err_pci_map;
-		}
-		dev_dbg(&pdev->dev, "%s : "
-			"pci_map_rom SUCCESS and value in "
-			"pch_phub_extrom_base_address variable is %p\n",
-			__func__, chip->pch_phub_extrom_base_address);
-	}
+	chip->pdev = pdev; /* Save pci device struct */
 
 	if (id->driver_data == 1) { /* EG20T PCH */
 		const char *board_name;
@@ -757,6 +786,22 @@
 		chip->pch_opt_rom_start_address =\
 						 PCH_PHUB_ROM_START_ADDR_ML7223;
 		chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;
+	} else if (id->driver_data == 5) { /* ML7831 */
+		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;
+
+		/* 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);
+		chip->pch_opt_rom_start_address = PCH_PHUB_ROM_START_ADDR_EG20T;
+		chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_EG20T;
 	}
 
 	chip->ioh_type = id->driver_data;
@@ -767,8 +812,6 @@
 	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
 
 err_sysfs_create:
-	pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
-err_pci_map:
 	pci_iounmap(pdev, chip->pch_phub_base_address);
 err_pci_iomap:
 	pci_release_regions(pdev);
@@ -786,7 +829,6 @@
 
 	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
 	sysfs_remove_bin_file(&pdev->dev.kobj, &pch_bin_attr);
-	pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
 	pci_iounmap(pdev, chip->pch_phub_base_address);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
@@ -841,6 +883,7 @@
 	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2,  },
 	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_mPHUB), 3,  },
 	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_nPHUB), 4,  },
+	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7831_PHUB), 5,  },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, pch_phub_pcidev_id);
@@ -867,5 +910,5 @@
 module_init(pch_phub_pci_init);
 module_exit(pch_phub_pci_exit);
 
-MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB");
+MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7223) PHUB");
 MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/misc/sgi-gru/grukservices.c linux-libre-3.2-gnu/drivers/misc/sgi-gru/grukservices.c
--- linux-libre-3.1-gnu/drivers/misc/sgi-gru/grukservices.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/sgi-gru/grukservices.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/interrupt.h>
 #include <linux/uaccess.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 #include <asm/io_apic.h>
 #include "gru.h"
 #include "grulib.h"
diff -druN linux-libre-3.1-gnu/drivers/misc/spear13xx_pcie_gadget.c linux-libre-3.2-gnu/drivers/misc/spear13xx_pcie_gadget.c
--- linux-libre-3.1-gnu/drivers/misc/spear13xx_pcie_gadget.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/spear13xx_pcie_gadget.c	2012-01-04 18:55:44.000000000 -0500
@@ -903,6 +903,6 @@
 }
 module_exit(spear_pcie_gadget_exit);
 
-MODULE_ALIAS("pcie-gadget-spear");
+MODULE_ALIAS("platform:pcie-gadget-spear");
 MODULE_AUTHOR("Pratyush Anand");
 MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/misc/tifm_7xx1.c linux-libre-3.2-gnu/drivers/misc/tifm_7xx1.c
--- linux-libre-3.1-gnu/drivers/misc/tifm_7xx1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/tifm_7xx1.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 
 #include <linux/tifm.h>
 #include <linux/dma-mapping.h>
+#include <linux/module.h>
 
 #define DRIVER_NAME "tifm_7xx1"
 #define DRIVER_VERSION "0.8"
diff -druN linux-libre-3.1-gnu/drivers/misc/tifm_core.c linux-libre-3.2-gnu/drivers/misc/tifm_core.c
--- linux-libre-3.1-gnu/drivers/misc/tifm_core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/tifm_core.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/idr.h>
+#include <linux/module.h>
 
 #define DRIVER_NAME "tifm_core"
 #define DRIVER_VERSION "0.8"
diff -druN linux-libre-3.1-gnu/drivers/misc/ti-st/st_kim.c linux-libre-3.2-gnu/drivers/misc/ti-st/st_kim.c
--- linux-libre-3.1-gnu/drivers/misc/ti-st/st_kim.c	2012-03-19 22:00:38.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/ti-st/st_kim.c	2012-03-19 22:04:22.000000000 -0400
@@ -35,6 +35,7 @@
 
 #include <linux/skbuff.h>
 #include <linux/ti_wilink_st.h>
+#include <linux/module.h>
 
 
 #define MAX_ST_DEVICES	3	/* Imagine 1 on each UART for now */
diff -druN linux-libre-3.1-gnu/drivers/misc/vmw_balloon.c linux-libre-3.2-gnu/drivers/misc/vmw_balloon.c
--- linux-libre-3.1-gnu/drivers/misc/vmw_balloon.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/misc/vmw_balloon.c	2012-01-04 18:55:44.000000000 -0500
@@ -151,7 +151,7 @@
 struct vmballoon_stats {
 	unsigned int timer;
 
-	/* allocation statustics */
+	/* allocation statistics */
 	unsigned int alloc;
 	unsigned int alloc_fail;
 	unsigned int sleep_alloc;
@@ -412,6 +412,7 @@
 	gfp_t flags;
 	unsigned int hv_status;
 	bool locked = false;
+	flags = can_sleep ? VMW_PAGE_ALLOC_CANSLEEP : VMW_PAGE_ALLOC_NOSLEEP;
 
 	do {
 		if (!can_sleep)
@@ -419,7 +420,6 @@
 		else
 			STATS_INC(b->stats.sleep_alloc);
 
-		flags = can_sleep ? VMW_PAGE_ALLOC_CANSLEEP : VMW_PAGE_ALLOC_NOSLEEP;
 		page = alloc_page(flags);
 		if (!page) {
 			if (!can_sleep)
diff -druN linux-libre-3.1-gnu/drivers/mmc/card/block.c linux-libre-3.2-gnu/drivers/mmc/card/block.c
--- linux-libre-3.1-gnu/drivers/mmc/card/block.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/card/block.c	2012-01-04 18:55:44.000000000 -0500
@@ -94,6 +94,11 @@
 	unsigned int	read_only;
 	unsigned int	part_type;
 	unsigned int	name_idx;
+	unsigned int	reset_done;
+#define MMC_BLK_READ		BIT(0)
+#define MMC_BLK_WRITE		BIT(1)
+#define MMC_BLK_DISCARD		BIT(2)
+#define MMC_BLK_SECDISCARD	BIT(3)
 
 	/*
 	 * Only set in main mmc_blk_data associated
@@ -109,11 +114,11 @@
 enum mmc_blk_status {
 	MMC_BLK_SUCCESS = 0,
 	MMC_BLK_PARTIAL,
-	MMC_BLK_RETRY,
-	MMC_BLK_RETRY_SINGLE,
-	MMC_BLK_DATA_ERR,
 	MMC_BLK_CMD_ERR,
+	MMC_BLK_RETRY,
 	MMC_BLK_ABORT,
+	MMC_BLK_DATA_ERR,
+	MMC_BLK_ECC_ERR,
 };
 
 module_param(perdev_minors, int, 0444);
@@ -291,7 +296,7 @@
 	struct mmc_card *card;
 	struct mmc_command cmd = {0};
 	struct mmc_data data = {0};
-	struct mmc_request mrq = {0};
+	struct mmc_request mrq = {NULL};
 	struct scatterlist sg;
 	int err;
 
@@ -442,19 +447,24 @@
 {
 	int ret;
 	struct mmc_blk_data *main_md = mmc_get_drvdata(card);
+
 	if (main_md->part_curr == md->part_type)
 		return 0;
 
 	if (mmc_card_mmc(card)) {
-		card->ext_csd.part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
-		card->ext_csd.part_config |= md->part_type;
+		u8 part_config = card->ext_csd.part_config;
+
+		part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
+		part_config |= md->part_type;
 
 		ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-				 EXT_CSD_PART_CONFIG, card->ext_csd.part_config,
+				 EXT_CSD_PART_CONFIG, part_config,
 				 card->ext_csd.part_time);
 		if (ret)
 			return ret;
-}
+
+		card->ext_csd.part_config = part_config;
+	}
 
 	main_md->part_curr = md->part_type;
 	return 0;
@@ -466,7 +476,7 @@
 	u32 result;
 	__be32 *blocks;
 
-	struct mmc_request mrq = {0};
+	struct mmc_request mrq = {NULL};
 	struct mmc_command cmd = {0};
 	struct mmc_data data = {0};
 	unsigned int timeout_us;
@@ -616,7 +626,7 @@
  * Otherwise we don't understand what happened, so abort.
  */
 static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
-	struct mmc_blk_request *brq)
+	struct mmc_blk_request *brq, int *ecc_err)
 {
 	bool prev_cmd_status_valid = true;
 	u32 status, stop_status = 0;
@@ -641,6 +651,12 @@
 	if (err)
 		return ERR_ABORT;
 
+	/* Flag ECC errors */
+	if ((status & R1_CARD_ECC_FAILED) ||
+	    (brq->stop.resp[0] & R1_CARD_ECC_FAILED) ||
+	    (brq->cmd.resp[0] & R1_CARD_ECC_FAILED))
+		*ecc_err = 1;
+
 	/*
 	 * Check the current card state.  If it is in some data transfer
 	 * mode, tell it to stop (and hopefully transition back to TRAN.)
@@ -658,6 +674,8 @@
 		 */
 		if (err)
 			return ERR_ABORT;
+		if (stop_status & R1_CARD_ECC_FAILED)
+			*ecc_err = 1;
 	}
 
 	/* Check for set block count errors */
@@ -670,6 +688,10 @@
 		return mmc_blk_cmd_error(req, "r/w cmd", brq->cmd.error,
 				prev_cmd_status_valid, status);
 
+	/* Data errors */
+	if (!brq->stop.error)
+		return ERR_CONTINUE;
+
 	/* Now for stop errors.  These aren't fatal to the transfer. */
 	pr_err("%s: error %d sending stop command, original cmd response %#x, card status %#x\n",
 	       req->rq_disk->disk_name, brq->stop.error,
@@ -686,12 +708,45 @@
 	return ERR_CONTINUE;
 }
 
+static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
+			 int type)
+{
+	int err;
+
+	if (md->reset_done & type)
+		return -EEXIST;
+
+	md->reset_done |= type;
+	err = mmc_hw_reset(host);
+	/* Ensure we switch back to the correct partition */
+	if (err != -EOPNOTSUPP) {
+		struct mmc_blk_data *main_md = mmc_get_drvdata(host->card);
+		int part_err;
+
+		main_md->part_curr = main_md->part_type;
+		part_err = mmc_blk_part_switch(host->card, md);
+		if (part_err) {
+			/*
+			 * We have failed to get back into the correct
+			 * partition, so we need to abort the whole request.
+			 */
+			return -ENODEV;
+		}
+	}
+	return err;
+}
+
+static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
+{
+	md->reset_done &= ~type;
+}
+
 static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
 {
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
 	unsigned int from, nr, arg;
-	int err = 0;
+	int err = 0, type = MMC_BLK_DISCARD;
 
 	if (!mmc_can_erase(card)) {
 		err = -EOPNOTSUPP;
@@ -701,11 +756,13 @@
 	from = blk_rq_pos(req);
 	nr = blk_rq_sectors(req);
 
-	if (mmc_can_trim(card))
+	if (mmc_can_discard(card))
+		arg = MMC_DISCARD_ARG;
+	else if (mmc_can_trim(card))
 		arg = MMC_TRIM_ARG;
 	else
 		arg = MMC_ERASE_ARG;
-
+retry:
 	if (card->quirks & MMC_QUIRK_INAND_CMD38) {
 		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 				 INAND_CMD38_ARG_EXT_CSD,
@@ -718,6 +775,10 @@
 	}
 	err = mmc_erase(card, from, nr, arg);
 out:
+	if (err == -EIO && !mmc_blk_reset(md, card->host, type))
+		goto retry;
+	if (!err)
+		mmc_blk_reset_success(md, type);
 	spin_lock_irq(&md->lock);
 	__blk_end_request(req, err, blk_rq_bytes(req));
 	spin_unlock_irq(&md->lock);
@@ -731,13 +792,20 @@
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
 	unsigned int from, nr, arg;
-	int err = 0;
+	int err = 0, type = MMC_BLK_SECDISCARD;
 
-	if (!mmc_can_secure_erase_trim(card)) {
+	if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) {
 		err = -EOPNOTSUPP;
 		goto out;
 	}
 
+	/* The sanitize operation is supported at v4.5 only */
+	if (mmc_can_sanitize(card)) {
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+				EXT_CSD_SANITIZE_START, 1, 0);
+		goto out;
+	}
+
 	from = blk_rq_pos(req);
 	nr = blk_rq_sectors(req);
 
@@ -745,7 +813,7 @@
 		arg = MMC_SECURE_TRIM1_ARG;
 	else
 		arg = MMC_SECURE_ERASE_ARG;
-
+retry:
 	if (card->quirks & MMC_QUIRK_INAND_CMD38) {
 		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 				 INAND_CMD38_ARG_EXT_CSD,
@@ -769,6 +837,10 @@
 		err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
 	}
 out:
+	if (err == -EIO && !mmc_blk_reset(md, card->host, type))
+		goto retry;
+	if (!err)
+		mmc_blk_reset_success(md, type);
 	spin_lock_irq(&md->lock);
 	__blk_end_request(req, err, blk_rq_bytes(req));
 	spin_unlock_irq(&md->lock);
@@ -779,16 +851,18 @@
 static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
 {
 	struct mmc_blk_data *md = mq->data;
+	struct mmc_card *card = md->queue.card;
+	int ret = 0;
+
+	ret = mmc_flush_cache(card);
+	if (ret)
+		ret = -EIO;
 
-	/*
-	 * No-op, only service this because we need REQ_FUA for reliable
-	 * writes.
-	 */
 	spin_lock_irq(&md->lock);
-	__blk_end_request_all(req, 0);
+	__blk_end_request_all(req, ret);
 	spin_unlock_irq(&md->lock);
 
-	return 1;
+	return ret ? 0 : 1;
 }
 
 /*
@@ -825,11 +899,11 @@
 static int mmc_blk_err_check(struct mmc_card *card,
 			     struct mmc_async_req *areq)
 {
-	enum mmc_blk_status ret = MMC_BLK_SUCCESS;
 	struct mmc_queue_req *mq_mrq = container_of(areq, struct mmc_queue_req,
 						    mmc_active);
 	struct mmc_blk_request *brq = &mq_mrq->brq;
 	struct request *req = mq_mrq->req;
+	int ecc_err = 0;
 
 	/*
 	 * sbc.error indicates a problem with the set block count
@@ -841,8 +915,9 @@
 	 * stop.error indicates a problem with the stop command.  Data
 	 * may have been transferred, or may still be transferring.
 	 */
-	if (brq->sbc.error || brq->cmd.error || brq->stop.error) {
-		switch (mmc_blk_cmd_recovery(card, req, brq)) {
+	if (brq->sbc.error || brq->cmd.error || brq->stop.error ||
+	    brq->data.error) {
+		switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err)) {
 		case ERR_RETRY:
 			return MMC_BLK_RETRY;
 		case ERR_ABORT:
@@ -873,7 +948,7 @@
 		do {
 			int err = get_card_status(card, &status, 5);
 			if (err) {
-				printk(KERN_ERR "%s: error %d requesting status\n",
+				pr_err("%s: error %d requesting status\n",
 				       req->rq_disk->disk_name, err);
 				return MMC_BLK_CMD_ERR;
 			}
@@ -894,23 +969,21 @@
 		       brq->cmd.resp[0], brq->stop.resp[0]);
 
 		if (rq_data_dir(req) == READ) {
-			if (brq->data.blocks > 1) {
-				/* Redo read one sector at a time */
-				pr_warning("%s: retrying using single block read\n",
-					   req->rq_disk->disk_name);
-				return MMC_BLK_RETRY_SINGLE;
-			}
+			if (ecc_err)
+				return MMC_BLK_ECC_ERR;
 			return MMC_BLK_DATA_ERR;
 		} else {
 			return MMC_BLK_CMD_ERR;
 		}
 	}
 
-	if (ret == MMC_BLK_SUCCESS &&
-	    blk_rq_bytes(req) != brq->data.bytes_xfered)
-		ret = MMC_BLK_PARTIAL;
+	if (!brq->data.bytes_xfered)
+		return MMC_BLK_RETRY;
 
-	return ret;
+	if (blk_rq_bytes(req) != brq->data.bytes_xfered)
+		return MMC_BLK_PARTIAL;
+
+	return MMC_BLK_SUCCESS;
 }
 
 static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
@@ -957,13 +1030,20 @@
 	if (brq->data.blocks > card->host->max_blk_count)
 		brq->data.blocks = card->host->max_blk_count;
 
-	/*
-	 * After a read error, we redo the request one sector at a time
-	 * in order to accurately determine which sectors can be read
-	 * successfully.
-	 */
-	if (disable_multi && brq->data.blocks > 1)
-		brq->data.blocks = 1;
+	if (brq->data.blocks > 1) {
+		/*
+		 * After a read error, we redo the request one sector
+		 * at a time in order to accurately determine which
+		 * sectors can be read successfully.
+		 */
+		if (disable_multi)
+			brq->data.blocks = 1;
+
+		/* Some controllers can't do multiblock reads due to hw bugs */
+		if (card->host->caps2 & MMC_CAP2_NO_MULTI_READ &&
+		    rq_data_dir(req) == READ)
+			brq->data.blocks = 1;
+	}
 
 	if (brq->data.blocks > 1 || do_rel_wr) {
 		/* SPI multiblock writes terminate using a special
@@ -1049,12 +1129,41 @@
 	mmc_queue_bounce_pre(mqrq);
 }
 
+static int mmc_blk_cmd_err(struct mmc_blk_data *md, struct mmc_card *card,
+			   struct mmc_blk_request *brq, struct request *req,
+			   int ret)
+{
+	/*
+	 * If this is an SD card and we're writing, we can first
+	 * mark the known good sectors as ok.
+	 *
+	 * If the card is not SD, we can still ok written sectors
+	 * as reported by the controller (which might be less than
+	 * the real number of written sectors, but never more).
+	 */
+	if (mmc_card_sd(card)) {
+		u32 blocks;
+
+		blocks = mmc_sd_num_wr_blocks(card);
+		if (blocks != (u32)-1) {
+			spin_lock_irq(&md->lock);
+			ret = __blk_end_request(req, 0, blocks << 9);
+			spin_unlock_irq(&md->lock);
+		}
+	} else {
+		spin_lock_irq(&md->lock);
+		ret = __blk_end_request(req, 0, brq->data.bytes_xfered);
+		spin_unlock_irq(&md->lock);
+	}
+	return ret;
+}
+
 static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
 {
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
 	struct mmc_blk_request *brq = &mq->mqrq_cur->brq;
-	int ret = 1, disable_multi = 0, retry = 0;
+	int ret = 1, disable_multi = 0, retry = 0, type;
 	enum mmc_blk_status status;
 	struct mmc_queue_req *mq_rq;
 	struct request *req;
@@ -1076,6 +1185,7 @@
 		mq_rq = container_of(areq, struct mmc_queue_req, mmc_active);
 		brq = &mq_rq->brq;
 		req = mq_rq->req;
+		type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE;
 		mmc_queue_bounce_post(mq_rq);
 
 		switch (status) {
@@ -1084,18 +1194,18 @@
 			/*
 			 * A block was successfully transferred.
 			 */
+			mmc_blk_reset_success(md, type);
 			spin_lock_irq(&md->lock);
 			ret = __blk_end_request(req, 0,
 						brq->data.bytes_xfered);
 			spin_unlock_irq(&md->lock);
+			/*
+			 * If the blk_end_request function returns non-zero even
+			 * though all data has been transferred and no errors
+			 * were returned by the host controller, it's a bug.
+			 */
 			if (status == MMC_BLK_SUCCESS && ret) {
-				/*
-				 * The blk_end_request has returned non zero
-				 * even though all data is transfered and no
-				 * erros returned by host.
-				 * If this happen it's a bug.
-				 */
-				printk(KERN_ERR "%s BUG rq_tot %d d_xfer %d\n",
+				pr_err("%s BUG rq_tot %d d_xfer %d\n",
 				       __func__, blk_rq_bytes(req),
 				       brq->data.bytes_xfered);
 				rqc = NULL;
@@ -1103,16 +1213,36 @@
 			}
 			break;
 		case MMC_BLK_CMD_ERR:
-			goto cmd_err;
-		case MMC_BLK_RETRY_SINGLE:
-			disable_multi = 1;
-			break;
+			ret = mmc_blk_cmd_err(md, card, brq, req, ret);
+			if (!mmc_blk_reset(md, card->host, type))
+				break;
+			goto cmd_abort;
 		case MMC_BLK_RETRY:
 			if (retry++ < 5)
 				break;
+			/* Fall through */
 		case MMC_BLK_ABORT:
+			if (!mmc_blk_reset(md, card->host, type))
+				break;
 			goto cmd_abort;
-		case MMC_BLK_DATA_ERR:
+		case MMC_BLK_DATA_ERR: {
+			int err;
+
+			err = mmc_blk_reset(md, card->host, type);
+			if (!err)
+				break;
+			if (err == -ENODEV)
+				goto cmd_abort;
+			/* Fall through */
+		}
+		case MMC_BLK_ECC_ERR:
+			if (brq->data.blocks > 1) {
+				/* Redo read one sector at a time */
+				pr_warning("%s: retrying using single block read\n",
+					   req->rq_disk->disk_name);
+				disable_multi = 1;
+				break;
+			}
 			/*
 			 * After an error, we redo I/O one sector at a
 			 * time, so we only reach here after trying to
@@ -1129,7 +1259,7 @@
 
 		if (ret) {
 			/*
-			 * In case of a none complete request
+			 * In case of a incomplete request
 			 * prepare it again and resend.
 			 */
 			mmc_blk_rw_rq_prep(mq_rq, card, disable_multi, mq);
@@ -1139,30 +1269,6 @@
 
 	return 1;
 
- cmd_err:
- 	/*
- 	 * If this is an SD card and we're writing, we can first
- 	 * mark the known good sectors as ok.
- 	 *
-	 * If the card is not SD, we can still ok written sectors
-	 * as reported by the controller (which might be less than
-	 * the real number of written sectors, but never more).
-	 */
-	if (mmc_card_sd(card)) {
-		u32 blocks;
-
-		blocks = mmc_sd_num_wr_blocks(card);
-		if (blocks != (u32)-1) {
-			spin_lock_irq(&md->lock);
-			ret = __blk_end_request(req, 0, blocks << 9);
-			spin_unlock_irq(&md->lock);
-		}
-	} else {
-		spin_lock_irq(&md->lock);
-		ret = __blk_end_request(req, 0, brq->data.bytes_xfered);
-		spin_unlock_irq(&md->lock);
-	}
-
  cmd_abort:
 	spin_lock_irq(&md->lock);
 	while (ret)
@@ -1190,6 +1296,11 @@
 
 	ret = mmc_blk_part_switch(card, md);
 	if (ret) {
+		if (req) {
+			spin_lock_irq(&md->lock);
+			__blk_end_request_all(req, -EIO);
+			spin_unlock_irq(&md->lock);
+		}
 		ret = 0;
 		goto out;
 	}
@@ -1374,32 +1485,35 @@
 
 	string_get_size((u64)get_capacity(part_md->disk) << 9, STRING_UNITS_2,
 			cap_str, sizeof(cap_str));
-	printk(KERN_INFO "%s: %s %s partition %u %s\n",
+	pr_info("%s: %s %s partition %u %s\n",
 	       part_md->disk->disk_name, mmc_card_id(card),
 	       mmc_card_name(card), part_md->part_type, cap_str);
 	return 0;
 }
 
+/* MMC Physical partitions consist of two boot partitions and
+ * up to four general purpose partitions.
+ * For each partition enabled in EXT_CSD a block device will be allocatedi
+ * to provide access to the partition.
+ */
+
 static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
 {
-	int ret = 0;
+	int idx, ret = 0;
 
 	if (!mmc_card_mmc(card))
 		return 0;
 
-	if (card->ext_csd.boot_size) {
-		ret = mmc_blk_alloc_part(card, md, EXT_CSD_PART_CONFIG_ACC_BOOT0,
-					 card->ext_csd.boot_size >> 9,
-					 true,
-					 "boot0");
-		if (ret)
-			return ret;
-		ret = mmc_blk_alloc_part(card, md, EXT_CSD_PART_CONFIG_ACC_BOOT1,
-					 card->ext_csd.boot_size >> 9,
-					 true,
-					 "boot1");
-		if (ret)
-			return ret;
+	for (idx = 0; idx < card->nr_parts; idx++) {
+		if (card->part[idx].size) {
+			ret = mmc_blk_alloc_part(card, md,
+				card->part[idx].part_cfg,
+				card->part[idx].size >> 9,
+				card->part[idx].force_ro,
+				card->part[idx].name);
+			if (ret)
+				return ret;
+		}
 	}
 
 	return ret;
@@ -1415,7 +1529,7 @@
 	mmc_release_host(card->host);
 
 	if (err) {
-		printk(KERN_ERR "%s: unable to set block size to 512: %d\n",
+		pr_err("%s: unable to set block size to 512: %d\n",
 			md->disk->disk_name, err);
 		return -EINVAL;
 	}
@@ -1492,6 +1606,14 @@
 		  MMC_QUIRK_BLK_NO_CMD23),
 	MMC_FIXUP("MMC32G", 0x11, CID_OEMID_ANY, add_quirk_mmc,
 		  MMC_QUIRK_BLK_NO_CMD23),
+
+	/*
+	 * Some Micron MMC cards needs longer data read timeout than
+	 * indicated in CSD.
+	 */
+	MMC_FIXUP(CID_NAME_ANY, 0x13, 0x200, add_quirk_mmc,
+		  MMC_QUIRK_LONG_READ_TIME),
+
 	END_FIXUP
 };
 
@@ -1517,7 +1639,7 @@
 
 	string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,
 			cap_str, sizeof(cap_str));
-	printk(KERN_INFO "%s: %s %s %s %s\n",
+	pr_info("%s: %s %s %s %s\n",
 		md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
 		cap_str, md->read_only ? "(ro)" : "");
 
diff -druN linux-libre-3.1-gnu/drivers/mmc/card/mmc_test.c linux-libre-3.2-gnu/drivers/mmc/card/mmc_test.c
--- linux-libre-3.1-gnu/drivers/mmc/card/mmc_test.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/card/mmc_test.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
 #include <linux/seq_file.h>
+#include <linux/module.h>
 
 #define RESULT_OK		0
 #define RESULT_FAIL		1
@@ -250,7 +251,7 @@
 		if (!busy && mmc_test_busy(&cmd)) {
 			busy = 1;
 			if (test->card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
-				printk(KERN_INFO "%s: Warning: Host did not "
+				pr_info("%s: Warning: Host did not "
 					"wait for busy state to end.\n",
 					mmc_hostname(test->card->host));
 		}
@@ -552,7 +553,7 @@
 	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 "
+	pr_info("%s: Transfer of %u sectors (%u%s KiB) took %lu.%09lu "
 			 "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,
@@ -578,7 +579,7 @@
 	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 "
+	pr_info("%s: Transfer of %u x %u sectors (%u x %u%s KiB) took "
 			 "%lu.%09lu seconds (%u kB/s, %u KiB/s, "
 			 "%u.%02u IOPS, sg_len %d)\n",
 			 mmc_hostname(test->card->host), count, sectors, count,
@@ -1408,7 +1409,7 @@
 
 static int mmc_test_no_highmem(struct mmc_test_card *test)
 {
-	printk(KERN_INFO "%s: Highmem not configured - test skipped\n",
+	pr_info("%s: Highmem not configured - test skipped\n",
 	       mmc_hostname(test->card->host));
 	return 0;
 }
@@ -1435,7 +1436,7 @@
 				      t->max_seg_sz, &t->sg_len, min_sg_len);
 	}
 	if (err)
-		printk(KERN_INFO "%s: Failed to map sg list\n",
+		pr_info("%s: Failed to map sg list\n",
 		       mmc_hostname(test->card->host));
 	return err;
 }
@@ -2135,7 +2136,7 @@
 
 	return ret;
  err:
-	printk(KERN_INFO "[%s] error\n", __func__);
+	pr_info("[%s] error\n", __func__);
 	return ret;
 }
 
@@ -2149,7 +2150,7 @@
 
 	if (rw->do_nonblock_req &&
 	    ((!pre_req && post_req) || (pre_req && !post_req))) {
-		printk(KERN_INFO "error: only one of pre/post is defined\n");
+		pr_info("error: only one of pre/post is defined\n");
 		return -EINVAL;
 	}
 
@@ -2328,6 +2329,31 @@
 	return mmc_test_rw_multiple_sg_len(test, &test_data);
 }
 
+/*
+ * eMMC hardware reset.
+ */
+static int mmc_test_hw_reset(struct mmc_test_card *test)
+{
+	struct mmc_card *card = test->card;
+	struct mmc_host *host = card->host;
+	int err;
+
+	err = mmc_hw_reset_check(host);
+	if (!err)
+		return RESULT_OK;
+
+	if (err == -ENOSYS)
+		return RESULT_FAIL;
+
+	if (err != -EOPNOTSUPP)
+		return err;
+
+	if (!mmc_can_reset(card))
+		return RESULT_UNSUP_CARD;
+
+	return RESULT_UNSUP_HOST;
+}
+
 static const struct mmc_test_case mmc_test_cases[] = {
 	{
 		.name = "Basic write (no data verification)",
@@ -2650,6 +2676,11 @@
 		.run = mmc_test_profile_sglen_r_nonblock_perf,
 		.cleanup = mmc_test_area_cleanup,
 	},
+
+	{
+		.name = "eMMC hardware reset",
+		.run = mmc_test_hw_reset,
+	},
 };
 
 static DEFINE_MUTEX(mmc_test_lock);
@@ -2660,7 +2691,7 @@
 {
 	int i, ret;
 
-	printk(KERN_INFO "%s: Starting tests of card %s...\n",
+	pr_info("%s: Starting tests of card %s...\n",
 		mmc_hostname(test->card->host), mmc_card_id(test->card));
 
 	mmc_claim_host(test->card->host);
@@ -2671,14 +2702,14 @@
 		if (testcase && ((i + 1) != testcase))
 			continue;
 
-		printk(KERN_INFO "%s: Test case %d. %s...\n",
+		pr_info("%s: Test case %d. %s...\n",
 			mmc_hostname(test->card->host), i + 1,
 			mmc_test_cases[i].name);
 
 		if (mmc_test_cases[i].prepare) {
 			ret = mmc_test_cases[i].prepare(test);
 			if (ret) {
-				printk(KERN_INFO "%s: Result: Prepare "
+				pr_info("%s: Result: Prepare "
 					"stage failed! (%d)\n",
 					mmc_hostname(test->card->host),
 					ret);
@@ -2708,25 +2739,25 @@
 		ret = mmc_test_cases[i].run(test);
 		switch (ret) {
 		case RESULT_OK:
-			printk(KERN_INFO "%s: Result: OK\n",
+			pr_info("%s: Result: OK\n",
 				mmc_hostname(test->card->host));
 			break;
 		case RESULT_FAIL:
-			printk(KERN_INFO "%s: Result: FAILED\n",
+			pr_info("%s: Result: FAILED\n",
 				mmc_hostname(test->card->host));
 			break;
 		case RESULT_UNSUP_HOST:
-			printk(KERN_INFO "%s: Result: UNSUPPORTED "
+			pr_info("%s: Result: UNSUPPORTED "
 				"(by host)\n",
 				mmc_hostname(test->card->host));
 			break;
 		case RESULT_UNSUP_CARD:
-			printk(KERN_INFO "%s: Result: UNSUPPORTED "
+			pr_info("%s: Result: UNSUPPORTED "
 				"(by card)\n",
 				mmc_hostname(test->card->host));
 			break;
 		default:
-			printk(KERN_INFO "%s: Result: ERROR (%d)\n",
+			pr_info("%s: Result: ERROR (%d)\n",
 				mmc_hostname(test->card->host), ret);
 		}
 
@@ -2737,7 +2768,7 @@
 		if (mmc_test_cases[i].cleanup) {
 			ret = mmc_test_cases[i].cleanup(test);
 			if (ret) {
-				printk(KERN_INFO "%s: Warning: Cleanup "
+				pr_info("%s: Warning: Cleanup "
 					"stage failed! (%d)\n",
 					mmc_hostname(test->card->host),
 					ret);
@@ -2747,7 +2778,7 @@
 
 	mmc_release_host(test->card->host);
 
-	printk(KERN_INFO "%s: Tests completed.\n",
+	pr_info("%s: Tests completed.\n",
 		mmc_hostname(test->card->host));
 }
 
diff -druN linux-libre-3.1-gnu/drivers/mmc/card/queue.c linux-libre-3.2-gnu/drivers/mmc/card/queue.c
--- linux-libre-3.1-gnu/drivers/mmc/card/queue.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/card/queue.c	2012-01-04 18:55:44.000000000 -0500
@@ -108,7 +108,7 @@
 		wake_up_process(mq->thread);
 }
 
-struct scatterlist *mmc_alloc_sg(int sg_len, int *err)
+static struct scatterlist *mmc_alloc_sg(int sg_len, int *err)
 {
 	struct scatterlist *sg;
 
@@ -140,7 +140,7 @@
 	/* granularity must not be greater than max. discard */
 	if (card->pref_erase > max_discard)
 		q->limits.discard_granularity = 0;
-	if (mmc_can_secure_erase_trim(card))
+	if (mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))
 		queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, q);
 }
 
@@ -197,13 +197,13 @@
 		if (bouncesz > 512) {
 			mqrq_cur->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
 			if (!mqrq_cur->bounce_buf) {
-				printk(KERN_WARNING "%s: unable to "
+				pr_warning("%s: unable to "
 					"allocate bounce cur buffer\n",
 					mmc_card_name(card));
 			}
 			mqrq_prev->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
 			if (!mqrq_prev->bounce_buf) {
-				printk(KERN_WARNING "%s: unable to "
+				pr_warning("%s: unable to "
 					"allocate bounce prev buffer\n",
 					mmc_card_name(card));
 				kfree(mqrq_cur->bounce_buf);
diff -druN linux-libre-3.1-gnu/drivers/mmc/card/sdio_uart.c linux-libre-3.2-gnu/drivers/mmc/card/sdio_uart.c
--- linux-libre-3.1-gnu/drivers/mmc/card/sdio_uart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/card/sdio_uart.c	2012-01-04 18:55:44.000000000 -0500
@@ -1082,7 +1082,7 @@
 		return -ENOMEM;
 
 	if (func->class == SDIO_CLASS_UART) {
-		printk(KERN_WARNING "%s: need info on UART class basic setup\n",
+		pr_warning("%s: need info on UART class basic setup\n",
 		       sdio_func_id(func));
 		kfree(port);
 		return -ENOSYS;
@@ -1101,23 +1101,23 @@
 				break;
 		}
 		if (!tpl) {
-			printk(KERN_WARNING
+			pr_warning(
        "%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n",
 			       sdio_func_id(func));
 			kfree(port);
 			return -EINVAL;
 		}
-		printk(KERN_DEBUG "%s: Register ID = 0x%02x, Exp ID = 0x%02x\n",
+		pr_debug("%s: Register ID = 0x%02x, Exp ID = 0x%02x\n",
 		       sdio_func_id(func), tpl->data[2], tpl->data[3]);
 		port->regs_offset = (tpl->data[4] << 0) |
 				    (tpl->data[5] << 8) |
 				    (tpl->data[6] << 16);
-		printk(KERN_DEBUG "%s: regs offset = 0x%x\n",
+		pr_debug("%s: regs offset = 0x%x\n",
 		       sdio_func_id(func), port->regs_offset);
 		port->uartclk = tpl->data[7] * 115200;
 		if (port->uartclk == 0)
 			port->uartclk = 115200;
-		printk(KERN_DEBUG "%s: clk %d baudcode %u 4800-div %u\n",
+		pr_debug("%s: clk %d baudcode %u 4800-div %u\n",
 		       sdio_func_id(func), port->uartclk,
 		       tpl->data[7], tpl->data[8] | (tpl->data[9] << 8));
 	} else {
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/bus.c linux-libre-3.2-gnu/drivers/mmc/core/bus.c
--- linux-libre-3.1-gnu/drivers/mmc/core/bus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/bus.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,9 +11,11 @@
  *  MMC card bus driver model
  */
 
+#include <linux/export.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <linux/stat.h>
 #include <linux/pm_runtime.h>
 
 #include <linux/mmc/card.h>
@@ -295,7 +297,7 @@
 	}
 
 	if (mmc_host_is_spi(card->host)) {
-		printk(KERN_INFO "%s: new %s%s%s card on SPI\n",
+		pr_info("%s: new %s%s%s card on SPI\n",
 			mmc_hostname(card->host),
 			mmc_card_highspeed(card) ? "high speed " : "",
 			mmc_card_ddr_mode(card) ? "DDR " : "",
@@ -334,10 +336,10 @@
 
 	if (mmc_card_present(card)) {
 		if (mmc_host_is_spi(card->host)) {
-			printk(KERN_INFO "%s: SPI card removed\n",
+			pr_info("%s: SPI card removed\n",
 				mmc_hostname(card->host));
 		} else {
-			printk(KERN_INFO "%s: card %04x removed\n",
+			pr_info("%s: card %04x removed\n",
 				mmc_hostname(card->host), card->rca);
 		}
 		device_del(&card->dev);
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/core.c linux-libre-3.2-gnu/drivers/mmc/core/core.c
--- linux-libre-3.1-gnu/drivers/mmc/core/core.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/core.c	2012-01-04 18:55:44.000000000 -0500
@@ -24,6 +24,8 @@
 #include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
 #include <linux/suspend.h>
+#include <linux/fault-inject.h>
+#include <linux/random.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -83,6 +85,43 @@
 	flush_workqueue(workqueue);
 }
 
+#ifdef CONFIG_FAIL_MMC_REQUEST
+
+/*
+ * Internal function. Inject random data errors.
+ * If mmc_data is NULL no errors are injected.
+ */
+static void mmc_should_fail_request(struct mmc_host *host,
+				    struct mmc_request *mrq)
+{
+	struct mmc_command *cmd = mrq->cmd;
+	struct mmc_data *data = mrq->data;
+	static const int data_errors[] = {
+		-ETIMEDOUT,
+		-EILSEQ,
+		-EIO,
+	};
+
+	if (!data)
+		return;
+
+	if (cmd->error || data->error ||
+	    !should_fail(&host->fail_mmc_request, data->blksz * data->blocks))
+		return;
+
+	data->error = data_errors[random32() % ARRAY_SIZE(data_errors)];
+	data->bytes_xfered = (random32() % (data->bytes_xfered >> 9)) << 9;
+}
+
+#else /* CONFIG_FAIL_MMC_REQUEST */
+
+static inline void mmc_should_fail_request(struct mmc_host *host,
+					   struct mmc_request *mrq)
+{
+}
+
+#endif /* CONFIG_FAIL_MMC_REQUEST */
+
 /**
  *	mmc_request_done - finish processing an MMC request
  *	@host: MMC host which completed request
@@ -102,13 +141,15 @@
 	}
 
 	if (err && cmd->retries) {
-		pr_debug("%s: req failed (CMD%u): %d, retrying...\n",
-			mmc_hostname(host), cmd->opcode, err);
-
-		cmd->retries--;
-		cmd->error = 0;
-		host->ops->request(host, mrq);
+		/*
+		 * Request starter must handle retries - see
+		 * mmc_wait_for_req_done().
+		 */
+		if (mrq->done)
+			mrq->done(mrq);
 	} else {
+		mmc_should_fail_request(host, mrq);
+
 		led_trigger_event(host->led, LED_OFF);
 
 		pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n",
@@ -212,7 +253,21 @@
 static void mmc_wait_for_req_done(struct mmc_host *host,
 				  struct mmc_request *mrq)
 {
-	wait_for_completion(&mrq->completion);
+	struct mmc_command *cmd;
+
+	while (1) {
+		wait_for_completion(&mrq->completion);
+
+		cmd = mrq->cmd;
+		if (!cmd->error || !cmd->retries)
+			break;
+
+		pr_debug("%s: req failed (CMD%u): %d, retrying...\n",
+			 mmc_hostname(host), cmd->opcode, cmd->error);
+		cmd->retries--;
+		cmd->error = 0;
+		host->ops->request(host, mrq);
+	}
 }
 
 /**
@@ -279,8 +334,14 @@
 		mmc_wait_for_req_done(host, host->areq->mrq);
 		err = host->areq->err_check(host->card, host->areq);
 		if (err) {
+			/* post process the completed failed request */
 			mmc_post_req(host, host->areq->mrq, 0);
 			if (areq)
+				/*
+				 * Cancel the new prepared request, because
+				 * it can't run until the failed
+				 * request has been properly handled.
+				 */
 				mmc_post_req(host, areq->mrq, -EINVAL);
 
 			host->areq = NULL;
@@ -319,6 +380,63 @@
 EXPORT_SYMBOL(mmc_wait_for_req);
 
 /**
+ *	mmc_interrupt_hpi - Issue for High priority Interrupt
+ *	@card: the MMC card associated with the HPI transfer
+ *
+ *	Issued High Priority Interrupt, and check for card status
+ *	util out-of prg-state.
+ */
+int mmc_interrupt_hpi(struct mmc_card *card)
+{
+	int err;
+	u32 status;
+
+	BUG_ON(!card);
+
+	if (!card->ext_csd.hpi_en) {
+		pr_info("%s: HPI enable bit unset\n", mmc_hostname(card->host));
+		return 1;
+	}
+
+	mmc_claim_host(card->host);
+	err = mmc_send_status(card, &status);
+	if (err) {
+		pr_err("%s: Get card status fail\n", mmc_hostname(card->host));
+		goto out;
+	}
+
+	/*
+	 * If the card status is in PRG-state, we can send the HPI command.
+	 */
+	if (R1_CURRENT_STATE(status) == R1_STATE_PRG) {
+		do {
+			/*
+			 * We don't know when the HPI command will finish
+			 * processing, so we need to resend HPI until out
+			 * of prg-state, and keep checking the card status
+			 * with SEND_STATUS.  If a timeout error occurs when
+			 * sending the HPI command, we are already out of
+			 * prg-state.
+			 */
+			err = mmc_send_hpi_cmd(card, &status);
+			if (err)
+				pr_debug("%s: abort HPI (%d error)\n",
+					 mmc_hostname(card->host), err);
+
+			err = mmc_send_status(card, &status);
+			if (err)
+				break;
+		} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
+	} else
+		pr_debug("%s: Left prg-state\n", mmc_hostname(card->host));
+
+out:
+	mmc_release_host(card->host);
+	return err;
+}
+EXPORT_SYMBOL(mmc_interrupt_hpi);
+
+/**
  *	mmc_wait_for_cmd - start a command and wait for completion
  *	@host: MMC host to start command
  *	@cmd: MMC command to start
@@ -330,7 +448,7 @@
  */
 int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries)
 {
-	struct mmc_request mrq = {0};
+	struct mmc_request mrq = {NULL};
 
 	WARN_ON(!host->claimed);
 
@@ -411,6 +529,18 @@
 			data->timeout_clks = 0;
 		}
 	}
+
+	/*
+	 * Some cards require longer data read timeout than indicated in CSD.
+	 * Address this by setting the read timeout to a "reasonably high"
+	 * value. For the cards tested, 300ms has proven enough. If necessary,
+	 * this value can be increased if other problematic cards require this.
+	 */
+	if (mmc_card_long_read_time(card) && data->flags & MMC_DATA_READ) {
+		data->timeout_ns = 300000000;
+		data->timeout_clks = 0;
+	}
+
 	/*
 	 * Some cards need very high timeouts if driven in SPI mode.
 	 * The worst observed timeout was 900ms after writing a
@@ -1095,6 +1225,46 @@
 	mmc_host_clk_release(host);
 }
 
+static void mmc_poweroff_notify(struct mmc_host *host)
+{
+	struct mmc_card *card;
+	unsigned int timeout;
+	unsigned int notify_type = EXT_CSD_NO_POWER_NOTIFICATION;
+	int err = 0;
+
+	card = host->card;
+
+	/*
+	 * Send power notify command only if card
+	 * is mmc and notify state is powered ON
+	 */
+	if (card && mmc_card_mmc(card) &&
+	    (card->poweroff_notify_state == MMC_POWERED_ON)) {
+
+		if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) {
+			notify_type = EXT_CSD_POWER_OFF_SHORT;
+			timeout = card->ext_csd.generic_cmd6_time;
+			card->poweroff_notify_state = MMC_POWEROFF_SHORT;
+		} else {
+			notify_type = EXT_CSD_POWER_OFF_LONG;
+			timeout = card->ext_csd.power_off_longtime;
+			card->poweroff_notify_state = MMC_POWEROFF_LONG;
+		}
+
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+				 EXT_CSD_POWER_OFF_NOTIFICATION,
+				 notify_type, timeout);
+
+		if (err && err != -EBADMSG)
+			pr_err("Device failed to respond within %d poweroff "
+			       "time. Forcefully powering down the device\n",
+			       timeout);
+
+		/* Set the card state to no notification after the poweroff */
+		card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION;
+	}
+}
+
 /*
  * Apply power to the MMC stack.  This is a two-stage process.
  * First, we enable power to the card without the clock running.
@@ -1119,13 +1289,11 @@
 		bit = fls(host->ocr_avail) - 1;
 
 	host->ios.vdd = bit;
-	if (mmc_host_is_spi(host)) {
+	if (mmc_host_is_spi(host))
 		host->ios.chip_select = MMC_CS_HIGH;
-		host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
-	} else {
+	else
 		host->ios.chip_select = MMC_CS_DONTCARE;
-		host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-	}
+	host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
 	host->ios.power_mode = MMC_POWER_UP;
 	host->ios.bus_width = MMC_BUS_WIDTH_1;
 	host->ios.timing = MMC_TIMING_LEGACY;
@@ -1151,13 +1319,15 @@
 	mmc_host_clk_release(host);
 }
 
-static void mmc_power_off(struct mmc_host *host)
+void mmc_power_off(struct mmc_host *host)
 {
 	mmc_host_clk_hold(host);
 
 	host->ios.clock = 0;
 	host->ios.vdd = 0;
 
+	mmc_poweroff_notify(host);
+
 	/*
 	 * Reset ocr mask to be the highest possible voltage supported for
 	 * this mmc host. This value will be used at next power up.
@@ -1173,6 +1343,13 @@
 	host->ios.timing = MMC_TIMING_LEGACY;
 	mmc_set_ios(host);
 
+	/*
+	 * Some configurations, such as the 802.11 SDIO card in the OLPC
+	 * XO-1.5, require a short delay after poweroff before the card
+	 * can be successfully turned on again.
+	 */
+	mmc_delay(1);
+
 	mmc_host_clk_release(host);
 }
 
@@ -1241,8 +1418,7 @@
 }
 
 /*
- * Remove the current bus handler from a host. Assumes that there are
- * no interesting cards left, so the bus is powered down.
+ * Remove the current bus handler from a host.
  */
 void mmc_detach_bus(struct mmc_host *host)
 {
@@ -1259,8 +1435,6 @@
 
 	spin_unlock_irqrestore(&host->lock, flags);
 
-	mmc_power_off(host);
-
 	mmc_bus_put(host);
 }
 
@@ -1478,9 +1652,9 @@
 	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
 	err = mmc_wait_for_cmd(card->host, &cmd, 0);
 	if (err) {
-		printk(KERN_ERR "mmc_erase: group start error %d, "
+		pr_err("mmc_erase: group start error %d, "
 		       "status %#x\n", err, cmd.resp[0]);
-		err = -EINVAL;
+		err = -EIO;
 		goto out;
 	}
 
@@ -1493,9 +1667,9 @@
 	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
 	err = mmc_wait_for_cmd(card->host, &cmd, 0);
 	if (err) {
-		printk(KERN_ERR "mmc_erase: group end error %d, status %#x\n",
+		pr_err("mmc_erase: group end error %d, status %#x\n",
 		       err, cmd.resp[0]);
-		err = -EINVAL;
+		err = -EIO;
 		goto out;
 	}
 
@@ -1506,7 +1680,7 @@
 	cmd.cmd_timeout_ms = mmc_erase_timeout(card, arg, qty);
 	err = mmc_wait_for_cmd(card->host, &cmd, 0);
 	if (err) {
-		printk(KERN_ERR "mmc_erase: erase error %d, status %#x\n",
+		pr_err("mmc_erase: erase error %d, status %#x\n",
 		       err, cmd.resp[0]);
 		err = -EIO;
 		goto out;
@@ -1523,7 +1697,7 @@
 		/* Do not retry else we can't see errors */
 		err = mmc_wait_for_cmd(card->host, &cmd, 0);
 		if (err || (cmd.resp[0] & 0xFDF92000)) {
-			printk(KERN_ERR "error %d requesting status %#x\n",
+			pr_err("error %d requesting status %#x\n",
 				err, cmd.resp[0]);
 			err = -EIO;
 			goto out;
@@ -1614,10 +1788,32 @@
 {
 	if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN)
 		return 1;
+	if (mmc_can_discard(card))
+		return 1;
 	return 0;
 }
 EXPORT_SYMBOL(mmc_can_trim);
 
+int mmc_can_discard(struct mmc_card *card)
+{
+	/*
+	 * As there's no way to detect the discard support bit at v4.5
+	 * use the s/w feature support filed.
+	 */
+	if (card->ext_csd.feature_support & MMC_DISCARD_FEATURE)
+		return 1;
+	return 0;
+}
+EXPORT_SYMBOL(mmc_can_discard);
+
+int mmc_can_sanitize(struct mmc_card *card)
+{
+	if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_SANITIZE)
+		return 1;
+	return 0;
+}
+EXPORT_SYMBOL(mmc_can_sanitize);
+
 int mmc_can_secure_erase_trim(struct mmc_card *card)
 {
 	if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN)
@@ -1727,6 +1923,94 @@
 }
 EXPORT_SYMBOL(mmc_set_blocklen);
 
+static void mmc_hw_reset_for_init(struct mmc_host *host)
+{
+	if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
+		return;
+	mmc_host_clk_hold(host);
+	host->ops->hw_reset(host);
+	mmc_host_clk_release(host);
+}
+
+int mmc_can_reset(struct mmc_card *card)
+{
+	u8 rst_n_function;
+
+	if (!mmc_card_mmc(card))
+		return 0;
+	rst_n_function = card->ext_csd.rst_n_function;
+	if ((rst_n_function & EXT_CSD_RST_N_EN_MASK) != EXT_CSD_RST_N_ENABLED)
+		return 0;
+	return 1;
+}
+EXPORT_SYMBOL(mmc_can_reset);
+
+static int mmc_do_hw_reset(struct mmc_host *host, int check)
+{
+	struct mmc_card *card = host->card;
+
+	if (!host->bus_ops->power_restore)
+		return -EOPNOTSUPP;
+
+	if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
+		return -EOPNOTSUPP;
+
+	if (!card)
+		return -EINVAL;
+
+	if (!mmc_can_reset(card))
+		return -EOPNOTSUPP;
+
+	mmc_host_clk_hold(host);
+	mmc_set_clock(host, host->f_init);
+
+	host->ops->hw_reset(host);
+
+	/* If the reset has happened, then a status command will fail */
+	if (check) {
+		struct mmc_command cmd = {0};
+		int err;
+
+		cmd.opcode = MMC_SEND_STATUS;
+		if (!mmc_host_is_spi(card->host))
+			cmd.arg = card->rca << 16;
+		cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
+		err = mmc_wait_for_cmd(card->host, &cmd, 0);
+		if (!err) {
+			mmc_host_clk_release(host);
+			return -ENOSYS;
+		}
+	}
+
+	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_DDR);
+	if (mmc_host_is_spi(host)) {
+		host->ios.chip_select = MMC_CS_HIGH;
+		host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
+	} else {
+		host->ios.chip_select = MMC_CS_DONTCARE;
+		host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+	}
+	host->ios.bus_width = MMC_BUS_WIDTH_1;
+	host->ios.timing = MMC_TIMING_LEGACY;
+	mmc_set_ios(host);
+
+	mmc_host_clk_release(host);
+
+	return host->bus_ops->power_restore(host);
+}
+
+int mmc_hw_reset(struct mmc_host *host)
+{
+	return mmc_do_hw_reset(host, 0);
+}
+EXPORT_SYMBOL(mmc_hw_reset);
+
+int mmc_hw_reset_check(struct mmc_host *host)
+{
+	return mmc_do_hw_reset(host, 1);
+}
+EXPORT_SYMBOL(mmc_hw_reset_check);
+
 static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
 {
 	host->f_init = freq;
@@ -1738,6 +2022,12 @@
 	mmc_power_up(host);
 
 	/*
+	 * Some eMMCs (with VCCQ always on) may not be reset after power up, so
+	 * do a hardware reset if possible.
+	 */
+	mmc_hw_reset_for_init(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.
@@ -1845,6 +2135,7 @@
 
 		mmc_claim_host(host);
 		mmc_detach_bus(host);
+		mmc_power_off(host);
 		mmc_release_host(host);
 		mmc_bus_put(host);
 		return;
@@ -1927,7 +2218,7 @@
 
 	mmc_bus_get(host);
 
-	if (host->bus_ops && !host->bus_dead && host->bus_ops->awake)
+	if (host->bus_ops && !host->bus_dead && host->bus_ops->sleep)
 		err = host->bus_ops->sleep(host);
 
 	mmc_bus_put(host);
@@ -1946,6 +2237,65 @@
 }
 EXPORT_SYMBOL(mmc_card_can_sleep);
 
+/*
+ * Flush the cache to the non-volatile storage.
+ */
+int mmc_flush_cache(struct mmc_card *card)
+{
+	struct mmc_host *host = card->host;
+	int err = 0;
+
+	if (!(host->caps2 & MMC_CAP2_CACHE_CTRL))
+		return err;
+
+	if (mmc_card_mmc(card) &&
+			(card->ext_csd.cache_size > 0) &&
+			(card->ext_csd.cache_ctrl & 1)) {
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+				EXT_CSD_FLUSH_CACHE, 1, 0);
+		if (err)
+			pr_err("%s: cache flush error %d\n",
+					mmc_hostname(card->host), err);
+	}
+
+	return err;
+}
+EXPORT_SYMBOL(mmc_flush_cache);
+
+/*
+ * Turn the cache ON/OFF.
+ * Turning the cache OFF shall trigger flushing of the data
+ * to the non-volatile storage.
+ */
+int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
+{
+	struct mmc_card *card = host->card;
+	int err = 0;
+
+	if (!(host->caps2 & MMC_CAP2_CACHE_CTRL) ||
+			mmc_card_is_removable(host))
+		return err;
+
+	if (card && mmc_card_mmc(card) &&
+			(card->ext_csd.cache_size > 0)) {
+		enable = !!enable;
+
+		if (card->ext_csd.cache_ctrl ^ enable)
+			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+					EXT_CSD_CACHE_CTRL, enable, 0);
+		if (err)
+			pr_err("%s: cache %s error %d\n",
+					mmc_hostname(card->host),
+					enable ? "on" : "off",
+					err);
+		else
+			card->ext_csd.cache_ctrl = enable;
+	}
+
+	return err;
+}
+EXPORT_SYMBOL(mmc_cache_ctrl);
+
 #ifdef CONFIG_PM
 
 /**
@@ -1960,23 +2310,47 @@
 		cancel_delayed_work(&host->disable);
 	cancel_delayed_work(&host->detect);
 	mmc_flush_scheduled_work();
+	err = mmc_cache_ctrl(host, 0);
+	if (err)
+		goto out;
 
 	mmc_bus_get(host);
 	if (host->bus_ops && !host->bus_dead) {
-		if (host->bus_ops->suspend)
-			err = host->bus_ops->suspend(host);
-		if (err == -ENOSYS || !host->bus_ops->resume) {
-			/*
-			 * We simply "remove" the card in this case.
-			 * It will be redetected on resume.
-			 */
-			if (host->bus_ops->remove)
-				host->bus_ops->remove(host);
-			mmc_claim_host(host);
-			mmc_detach_bus(host);
-			mmc_release_host(host);
-			host->pm_flags = 0;
-			err = 0;
+
+		/*
+		 * A long response time is not acceptable for device drivers
+		 * when doing suspend. Prevent mmc_claim_host in the suspend
+		 * sequence, to potentially wait "forever" by trying to
+		 * pre-claim the host.
+		 */
+		if (mmc_try_claim_host(host)) {
+			if (host->bus_ops->suspend) {
+				/*
+				 * For eMMC 4.5 device send notify command
+				 * before sleep, because in sleep state eMMC 4.5
+				 * devices respond to only RESET and AWAKE cmd
+				 */
+				mmc_poweroff_notify(host);
+				err = host->bus_ops->suspend(host);
+			}
+			mmc_do_release_host(host);
+
+			if (err == -ENOSYS || !host->bus_ops->resume) {
+				/*
+				 * We simply "remove" the card in this case.
+				 * It will be redetected on resume.
+				 */
+				if (host->bus_ops->remove)
+					host->bus_ops->remove(host);
+				mmc_claim_host(host);
+				mmc_detach_bus(host);
+				mmc_power_off(host);
+				mmc_release_host(host);
+				host->pm_flags = 0;
+				err = 0;
+			}
+		} else {
+			err = -EBUSY;
 		}
 	}
 	mmc_bus_put(host);
@@ -1984,6 +2358,7 @@
 	if (!err && !mmc_card_keep_power(host))
 		mmc_power_off(host);
 
+out:
 	return err;
 }
 
@@ -2018,7 +2393,7 @@
 		BUG_ON(!host->bus_ops->resume);
 		err = host->bus_ops->resume(host);
 		if (err) {
-			printk(KERN_WARNING "%s: error %d during resume "
+			pr_warning("%s: error %d during resume "
 					    "(card was removed?)\n",
 					    mmc_hostname(host), err);
 			err = 0;
@@ -2049,6 +2424,7 @@
 
 		spin_lock_irqsave(&host->lock, flags);
 		host->rescan_disable = 1;
+		host->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
 		spin_unlock_irqrestore(&host->lock, flags);
 		cancel_delayed_work_sync(&host->detect);
 
@@ -2061,6 +2437,7 @@
 			host->bus_ops->remove(host);
 
 		mmc_detach_bus(host);
+		mmc_power_off(host);
 		mmc_release_host(host);
 		host->pm_flags = 0;
 		break;
@@ -2071,6 +2448,7 @@
 
 		spin_lock_irqsave(&host->lock, flags);
 		host->rescan_disable = 0;
+		host->power_notify_type = MMC_HOST_PW_NOTIFY_LONG;
 		spin_unlock_irqrestore(&host->lock, flags);
 		mmc_detect_change(host, 0);
 
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/core.h linux-libre-3.2-gnu/drivers/mmc/core/core.h
--- linux-libre-3.1-gnu/drivers/mmc/core/core.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/core.h	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@
 			   bool cmd11);
 void mmc_set_timing(struct mmc_host *host, unsigned int timing);
 void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type);
+void mmc_power_off(struct mmc_host *host);
 
 static inline void mmc_delay(unsigned int ms)
 {
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/debugfs.c linux-libre-3.2-gnu/drivers/mmc/core/debugfs.c
--- linux-libre-3.1-gnu/drivers/mmc/core/debugfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/debugfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -7,11 +7,14 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/moduleparam.h>
+#include <linux/export.h>
 #include <linux/debugfs.h>
 #include <linux/fs.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/stat.h>
+#include <linux/fault-inject.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -19,6 +22,14 @@
 #include "core.h"
 #include "mmc_ops.h"
 
+#ifdef CONFIG_FAIL_MMC_REQUEST
+
+static DECLARE_FAULT_ATTR(fail_default_attr);
+static char *fail_request;
+module_param(fail_request, charp, 0);
+
+#endif /* CONFIG_FAIL_MMC_REQUEST */
+
 /* The debugfs functions are optimized away when CONFIG_DEBUG_FS isn't set. */
 static int mmc_ios_show(struct seq_file *s, void *data)
 {
@@ -113,6 +124,15 @@
 	case MMC_TIMING_SD_HS:
 		str = "sd high-speed";
 		break;
+	case MMC_TIMING_UHS_SDR50:
+		str = "sd uhs SDR50";
+		break;
+	case MMC_TIMING_UHS_SDR104:
+		str = "sd uhs SDR104";
+		break;
+	case MMC_TIMING_UHS_DDR50:
+		str = "sd uhs DDR50";
+		break;
 	default:
 		str = "invalid";
 		break;
@@ -188,6 +208,15 @@
 				root, &host->clk_delay))
 		goto err_node;
 #endif
+#ifdef CONFIG_FAIL_MMC_REQUEST
+	if (fail_request)
+		setup_fault_attr(&fail_default_attr, fail_request);
+	host->fail_mmc_request = fail_default_attr;
+	if (IS_ERR(fault_create_debugfs_attr("fail_mmc_request",
+					     root,
+					     &host->fail_mmc_request)))
+		goto err_node;
+#endif
 	return;
 
 err_node:
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/host.c linux-libre-3.2-gnu/drivers/mmc/core/host.c
--- linux-libre-3.1-gnu/drivers/mmc/core/host.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/host.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/err.h>
 #include <linux/idr.h>
 #include <linux/pagemap.h>
+#include <linux/export.h>
 #include <linux/leds.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/mmc.c linux-libre-3.2-gnu/drivers/mmc/core/mmc.c
--- linux-libre-3.1-gnu/drivers/mmc/core/mmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/mmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <linux/stat.h>
 
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
@@ -101,7 +102,7 @@
 		break;
 
 	default:
-		printk(KERN_ERR "%s: card has unknown MMCA version %d\n",
+		pr_err("%s: card has unknown MMCA version %d\n",
 			mmc_hostname(card->host), card->csd.mmca_vsn);
 		return -EINVAL;
 	}
@@ -135,7 +136,7 @@
 	 */
 	csd->structure = UNSTUFF_BITS(resp, 126, 2);
 	if (csd->structure == 0) {
-		printk(KERN_ERR "%s: unrecognised CSD structure version %d\n",
+		pr_err("%s: unrecognised CSD structure version %d\n",
 			mmc_hostname(card->host), csd->structure);
 		return -EINVAL;
 	}
@@ -195,7 +196,7 @@
 	 */
 	ext_csd = kmalloc(512, GFP_KERNEL);
 	if (!ext_csd) {
-		printk(KERN_ERR "%s: could not allocate a buffer to "
+		pr_err("%s: could not allocate a buffer to "
 			"receive the ext_csd.\n", mmc_hostname(card->host));
 		return -ENOMEM;
 	}
@@ -217,12 +218,12 @@
 		 * stored in their CSD.
 		 */
 		if (card->csd.capacity == (4096 * 512)) {
-			printk(KERN_ERR "%s: unable to read EXT_CSD "
+			pr_err("%s: unable to read EXT_CSD "
 				"on a possible high capacity card. "
 				"Card will be ignored.\n",
 				mmc_hostname(card->host));
 		} else {
-			printk(KERN_WARNING "%s: unable to read "
+			pr_warning("%s: unable to read "
 				"EXT_CSD, performance might "
 				"suffer.\n",
 				mmc_hostname(card->host));
@@ -239,7 +240,9 @@
  */
 static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
 {
-	int err = 0;
+	int err = 0, idx;
+	unsigned int part_size;
+	u8 hc_erase_grp_sz = 0, hc_wp_grp_sz = 0;
 
 	BUG_ON(!card);
 
@@ -250,7 +253,7 @@
 	card->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE];
 	if (card->csd.structure == 3) {
 		if (card->ext_csd.raw_ext_csd_structure > 2) {
-			printk(KERN_ERR "%s: unrecognised EXT_CSD structure "
+			pr_err("%s: unrecognised EXT_CSD structure "
 				"version %d\n", mmc_hostname(card->host),
 					card->ext_csd.raw_ext_csd_structure);
 			err = -EINVAL;
@@ -260,7 +263,7 @@
 
 	card->ext_csd.rev = ext_csd[EXT_CSD_REV];
 	if (card->ext_csd.rev > 6) {
-		printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n",
+		pr_err("%s: unrecognised EXT_CSD revision %d\n",
 			mmc_hostname(card->host), card->ext_csd.rev);
 		err = -EINVAL;
 		goto out;
@@ -306,7 +309,7 @@
 		break;
 	default:
 		/* MMC v4 spec says this cannot happen */
-		printk(KERN_WARNING "%s: card is mmc v4 but doesn't "
+		pr_warning("%s: card is mmc v4 but doesn't "
 			"support any high-speed modes.\n",
 			mmc_hostname(card->host));
 	}
@@ -340,7 +343,14 @@
 		 * There are two boot regions of equal size, defined in
 		 * multiples of 128K.
 		 */
-		card->ext_csd.boot_size = ext_csd[EXT_CSD_BOOT_MULT] << 17;
+		if (ext_csd[EXT_CSD_BOOT_MULT] && mmc_boot_partition_access(card->host)) {
+			for (idx = 0; idx < MMC_NUM_BOOT_PARTITION; idx++) {
+				part_size = ext_csd[EXT_CSD_BOOT_MULT] << 17;
+				mmc_part_add(card, part_size,
+					EXT_CSD_PART_CONFIG_ACC_BOOT0 + idx,
+					"boot%d", idx, true);
+			}
+		}
 	}
 
 	card->ext_csd.raw_hc_erase_gap_size =
@@ -359,11 +369,12 @@
 		 * card has the Enhanced area enabled.  If so, export enhanced
 		 * area offset and size to user by adding sysfs interface.
 		 */
+		card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT];
 		if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
 		    (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
-			u8 hc_erase_grp_sz =
+			hc_erase_grp_sz =
 				ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
-			u8 hc_wp_grp_sz =
+			hc_wp_grp_sz =
 				ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
 
 			card->ext_csd.enhanced_area_en = 1;
@@ -392,6 +403,41 @@
 			card->ext_csd.enhanced_area_offset = -EINVAL;
 			card->ext_csd.enhanced_area_size = -EINVAL;
 		}
+
+		/*
+		 * General purpose partition feature support --
+		 * If ext_csd has the size of general purpose partitions,
+		 * set size, part_cfg, partition name in mmc_part.
+		 */
+		if (ext_csd[EXT_CSD_PARTITION_SUPPORT] &
+			EXT_CSD_PART_SUPPORT_PART_EN) {
+			if (card->ext_csd.enhanced_area_en != 1) {
+				hc_erase_grp_sz =
+					ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
+				hc_wp_grp_sz =
+					ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
+
+				card->ext_csd.enhanced_area_en = 1;
+			}
+
+			for (idx = 0; idx < MMC_NUM_GP_PARTITION; idx++) {
+				if (!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3] &&
+				!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1] &&
+				!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2])
+					continue;
+				part_size =
+				(ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2]
+					<< 16) +
+				(ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1]
+					<< 8) +
+				ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3];
+				part_size *= (size_t)(hc_erase_grp_sz *
+					hc_wp_grp_sz);
+				mmc_part_add(card, part_size << 19,
+					EXT_CSD_PART_CONFIG_ACC_GP0 + idx,
+					"gp%d", idx, false);
+			}
+		}
 		card->ext_csd.sec_trim_mult =
 			ext_csd[EXT_CSD_SEC_TRIM_MULT];
 		card->ext_csd.sec_erase_mult =
@@ -402,14 +448,48 @@
 			ext_csd[EXT_CSD_TRIM_MULT];
 	}
 
-	if (card->ext_csd.rev >= 5)
+	if (card->ext_csd.rev >= 5) {
+		/* check whether the eMMC card supports HPI */
+		if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) {
+			card->ext_csd.hpi = 1;
+			if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2)
+				card->ext_csd.hpi_cmd =	MMC_STOP_TRANSMISSION;
+			else
+				card->ext_csd.hpi_cmd = MMC_SEND_STATUS;
+			/*
+			 * Indicate the maximum timeout to close
+			 * a command interrupted by HPI
+			 */
+			card->ext_csd.out_of_int_time =
+				ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME] * 10;
+		}
+
 		card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM];
+		card->ext_csd.rst_n_function = ext_csd[EXT_CSD_RST_N_FUNCTION];
+	}
 
+	card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT];
 	if (ext_csd[EXT_CSD_ERASED_MEM_CONT])
 		card->erased_byte = 0xFF;
 	else
 		card->erased_byte = 0x0;
 
+	/* eMMC v4.5 or later */
+	if (card->ext_csd.rev >= 6) {
+		card->ext_csd.feature_support |= MMC_DISCARD_FEATURE;
+
+		card->ext_csd.generic_cmd6_time = 10 *
+			ext_csd[EXT_CSD_GENERIC_CMD6_TIME];
+		card->ext_csd.power_off_longtime = 10 *
+			ext_csd[EXT_CSD_POWER_OFF_LONG_TIME];
+
+		card->ext_csd.cache_size =
+			ext_csd[EXT_CSD_CACHE_SIZE + 0] << 0 |
+			ext_csd[EXT_CSD_CACHE_SIZE + 1] << 8 |
+			ext_csd[EXT_CSD_CACHE_SIZE + 2] << 16 |
+			ext_csd[EXT_CSD_CACHE_SIZE + 3] << 24;
+	}
+
 out:
 	return err;
 }
@@ -530,6 +610,86 @@
 };
 
 /*
+ * Select the PowerClass for the current bus width
+ * If power class is defined for 4/8 bit bus in the
+ * extended CSD register, select it by executing the
+ * mmc_switch command.
+ */
+static int mmc_select_powerclass(struct mmc_card *card,
+		unsigned int bus_width, u8 *ext_csd)
+{
+	int err = 0;
+	unsigned int pwrclass_val;
+	unsigned int index = 0;
+	struct mmc_host *host;
+
+	BUG_ON(!card);
+
+	host = card->host;
+	BUG_ON(!host);
+
+	if (ext_csd == NULL)
+		return 0;
+
+	/* Power class selection is supported for versions >= 4.0 */
+	if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+		return 0;
+
+	/* Power class values are defined only for 4/8 bit bus */
+	if (bus_width == EXT_CSD_BUS_WIDTH_1)
+		return 0;
+
+	switch (1 << host->ios.vdd) {
+	case MMC_VDD_165_195:
+		if (host->ios.clock <= 26000000)
+			index = EXT_CSD_PWR_CL_26_195;
+		else if	(host->ios.clock <= 52000000)
+			index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
+				EXT_CSD_PWR_CL_52_195 :
+				EXT_CSD_PWR_CL_DDR_52_195;
+		else if (host->ios.clock <= 200000000)
+			index = EXT_CSD_PWR_CL_200_195;
+		break;
+	case MMC_VDD_32_33:
+	case MMC_VDD_33_34:
+	case MMC_VDD_34_35:
+	case MMC_VDD_35_36:
+		if (host->ios.clock <= 26000000)
+			index = EXT_CSD_PWR_CL_26_360;
+		else if	(host->ios.clock <= 52000000)
+			index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
+				EXT_CSD_PWR_CL_52_360 :
+				EXT_CSD_PWR_CL_DDR_52_360;
+		else if (host->ios.clock <= 200000000)
+			index = EXT_CSD_PWR_CL_200_360;
+		break;
+	default:
+		pr_warning("%s: Voltage range not supported "
+			   "for power class.\n", mmc_hostname(host));
+		return -EINVAL;
+	}
+
+	pwrclass_val = ext_csd[index];
+
+	if (bus_width & (EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_BUS_WIDTH_8))
+		pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_8BIT_MASK) >>
+				EXT_CSD_PWR_CL_8BIT_SHIFT;
+	else
+		pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_4BIT_MASK) >>
+				EXT_CSD_PWR_CL_4BIT_SHIFT;
+
+	/* If the power class is different from the default value */
+	if (pwrclass_val > 0) {
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+				 EXT_CSD_POWER_CLASS,
+				 pwrclass_val,
+				 card->ext_csd.generic_cmd6_time);
+	}
+
+	return err;
+}
+
+/*
  * Handle the detection and initialisation of a card.
  *
  * In the case of a resume, "oldcard" will contain the card
@@ -548,11 +708,16 @@
 	BUG_ON(!host);
 	WARN_ON(!host->claimed);
 
+	/* Set correct bus mode for MMC before attempting init */
+	if (!mmc_host_is_spi(host))
+		mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN);
+
 	/*
 	 * Since we're changing the OCR value, we seem to
 	 * need to tell some cards to go back to the idle
 	 * state.  We wait 1ms to give cards time to
 	 * respond.
+	 * mmc_go_idle is needed for eMMC that are asleep
 	 */
 	mmc_go_idle(host);
 
@@ -668,7 +833,8 @@
 	 */
 	if (card->ext_csd.enhanced_area_en) {
 		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-				 EXT_CSD_ERASE_GROUP_DEF, 1, 0);
+				 EXT_CSD_ERASE_GROUP_DEF, 1,
+				 card->ext_csd.generic_cmd6_time);
 
 		if (err && err != -EBADMSG)
 			goto free_card;
@@ -706,17 +872,39 @@
 	}
 
 	/*
+	 * If the host supports the power_off_notify capability then
+	 * set the notification byte in the ext_csd register of device
+	 */
+	if ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) &&
+	    (card->ext_csd.rev >= 6)) {
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+				 EXT_CSD_POWER_OFF_NOTIFICATION,
+				 EXT_CSD_POWER_ON,
+				 card->ext_csd.generic_cmd6_time);
+		if (err && err != -EBADMSG)
+			goto free_card;
+
+		/*
+		 * The err can be -EBADMSG or 0,
+		 * so check for success and update the flag
+		 */
+		if (!err)
+			card->poweroff_notify_state = MMC_POWERED_ON;
+	}
+
+	/*
 	 * Activate high speed (if supported)
 	 */
 	if ((card->ext_csd.hs_max_dtr != 0) &&
 		(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
 		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-				 EXT_CSD_HS_TIMING, 1, 0);
+				 EXT_CSD_HS_TIMING, 1,
+				 card->ext_csd.generic_cmd6_time);
 		if (err && err != -EBADMSG)
 			goto free_card;
 
 		if (err) {
-			printk(KERN_WARNING "%s: switch to highspeed failed\n",
+			pr_warning("%s: switch to highspeed failed\n",
 			       mmc_hostname(card->host));
 			err = 0;
 		} else {
@@ -726,6 +914,22 @@
 	}
 
 	/*
+	 * Enable HPI feature (if supported)
+	 */
+	if (card->ext_csd.hpi) {
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+			EXT_CSD_HPI_MGMT, 1, 0);
+		if (err && err != -EBADMSG)
+			goto free_card;
+		if (err) {
+			pr_warning("%s: Enabling HPI failed\n",
+				   mmc_hostname(card->host));
+			err = 0;
+		} else
+			card->ext_csd.hpi_en = 1;
+	}
+
+	/*
 	 * Compute bus speed.
 	 */
 	max_dtr = (unsigned int)-1;
@@ -780,10 +984,18 @@
 			bus_width = bus_widths[idx];
 			if (bus_width == MMC_BUS_WIDTH_1)
 				ddr = 0; /* no DDR for 1-bit width */
+			err = mmc_select_powerclass(card, ext_csd_bits[idx][0],
+						    ext_csd);
+			if (err)
+				pr_err("%s: power class selection to "
+				       "bus width %d failed\n",
+				       mmc_hostname(card->host),
+				       1 << bus_width);
+
 			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 					 EXT_CSD_BUS_WIDTH,
 					 ext_csd_bits[idx][0],
-					 0);
+					 card->ext_csd.generic_cmd6_time);
 			if (!err) {
 				mmc_set_bus_width(card->host, bus_width);
 
@@ -803,13 +1015,21 @@
 		}
 
 		if (!err && ddr) {
+			err = mmc_select_powerclass(card, ext_csd_bits[idx][1],
+						    ext_csd);
+			if (err)
+				pr_err("%s: power class selection to "
+				       "bus width %d ddr %d failed\n",
+				       mmc_hostname(card->host),
+				       1 << bus_width, ddr);
+
 			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 					 EXT_CSD_BUS_WIDTH,
 					 ext_csd_bits[idx][1],
-					 0);
+					 card->ext_csd.generic_cmd6_time);
 		}
 		if (err) {
-			printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
+			pr_warning("%s: switch to bus width %d ddr %d "
 				"failed\n", mmc_hostname(card->host),
 				1 << bus_width, ddr);
 			goto free_card;
@@ -840,6 +1060,23 @@
 		}
 	}
 
+	/*
+	 * If cache size is higher than 0, this indicates
+	 * the existence of cache and it can be turned on.
+	 */
+	if ((host->caps2 & MMC_CAP2_CACHE_CTRL) &&
+			card->ext_csd.cache_size > 0) {
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+				EXT_CSD_CACHE_CTRL, 1, 0);
+		if (err && err != -EBADMSG)
+			goto free_card;
+
+		/*
+		 * Only if no error, cache is turned on successfully.
+		 */
+		card->ext_csd.cache_ctrl = err ? 0 : 1;
+	}
+
 	if (!oldcard)
 		host->card = card;
 
@@ -891,6 +1128,7 @@
 
 		mmc_claim_host(host);
 		mmc_detach_bus(host);
+		mmc_power_off(host);
 		mmc_release_host(host);
 	}
 }
@@ -900,16 +1138,20 @@
  */
 static int mmc_suspend(struct mmc_host *host)
 {
+	int err = 0;
+
 	BUG_ON(!host);
 	BUG_ON(!host->card);
 
 	mmc_claim_host(host);
-	if (!mmc_host_is_spi(host))
+	if (mmc_card_can_sleep(host))
+		err = mmc_card_sleep(host);
+	else if (!mmc_host_is_spi(host))
 		mmc_deselect_cards(host);
 	host->card->state &= ~MMC_STATE_HIGHSPEED;
 	mmc_release_host(host);
 
-	return 0;
+	return err;
 }
 
 /*
@@ -1016,6 +1258,10 @@
 	BUG_ON(!host);
 	WARN_ON(!host->claimed);
 
+	/* Set correct bus mode for MMC before attempting attach */
+	if (!mmc_host_is_spi(host))
+		mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN);
+
 	err = mmc_send_op_cond(host, 0, &ocr);
 	if (err)
 		return err;
@@ -1038,7 +1284,7 @@
 	 * support.
 	 */
 	if (ocr & 0x7F) {
-		printk(KERN_WARNING "%s: card claims to support voltages "
+		pr_warning("%s: card claims to support voltages "
 		       "below the defined range. These will be ignored.\n",
 		       mmc_hostname(host));
 		ocr &= ~0x7F;
@@ -1077,7 +1323,7 @@
 err:
 	mmc_detach_bus(host);
 
-	printk(KERN_ERR "%s: error %d whilst initialising MMC card\n",
+	pr_err("%s: error %d whilst initialising MMC card\n",
 		mmc_hostname(host), err);
 
 	return err;
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/mmc_ops.c linux-libre-3.2-gnu/drivers/mmc/core/mmc_ops.c
--- linux-libre-3.1-gnu/drivers/mmc/core/mmc_ops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/mmc_ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/scatterlist.h>
 
@@ -233,7 +234,7 @@
 mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
 		u32 opcode, void *buf, unsigned len)
 {
-	struct mmc_request mrq = {0};
+	struct mmc_request mrq = {NULL};
 	struct mmc_command cmd = {0};
 	struct mmc_data data = {0};
 	struct scatterlist sg;
@@ -414,7 +415,7 @@
 			return -EBADMSG;
 	} else {
 		if (status & 0xFDFFA000)
-			printk(KERN_WARNING "%s: unexpected status %#x after "
+			pr_warning("%s: unexpected status %#x after "
 			       "switch", mmc_hostname(card->host), status);
 		if (status & R1_SWITCH_ERROR)
 			return -EBADMSG;
@@ -454,7 +455,7 @@
 mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
 		  u8 len)
 {
-	struct mmc_request mrq = {0};
+	struct mmc_request mrq = {NULL};
 	struct mmc_command cmd = {0};
 	struct mmc_data data = {0};
 	struct scatterlist sg;
@@ -476,7 +477,7 @@
 	else if (len == 4)
 		test_buf = testdata_4bit;
 	else {
-		printk(KERN_ERR "%s: Invalid bus_width %d\n",
+		pr_err("%s: Invalid bus_width %d\n",
 		       mmc_hostname(host), len);
 		kfree(data_buf);
 		return -EINVAL;
@@ -547,3 +548,34 @@
 	err = mmc_send_bus_test(card, card->host, MMC_BUS_TEST_R, width);
 	return err;
 }
+
+int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status)
+{
+	struct mmc_command cmd = {0};
+	unsigned int opcode;
+	unsigned int flags;
+	int err;
+
+	opcode = card->ext_csd.hpi_cmd;
+	if (opcode == MMC_STOP_TRANSMISSION)
+		flags = MMC_RSP_R1 | MMC_CMD_AC;
+	else if (opcode == MMC_SEND_STATUS)
+		flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+	cmd.opcode = opcode;
+	cmd.arg = card->rca << 16 | 1;
+	cmd.flags = flags;
+	cmd.cmd_timeout_ms = card->ext_csd.out_of_int_time;
+
+	err = mmc_wait_for_cmd(card->host, &cmd, 0);
+	if (err) {
+		pr_warn("%s: error %d interrupting operation. "
+			"HPI command response %#x\n", mmc_hostname(card->host),
+			err, cmd.resp[0]);
+		return err;
+	}
+	if (status)
+		*status = cmd.resp[0];
+
+	return 0;
+}
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/mmc_ops.h linux-libre-3.2-gnu/drivers/mmc/core/mmc_ops.h
--- linux-libre-3.1-gnu/drivers/mmc/core/mmc_ops.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/mmc_ops.h	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
 int mmc_card_sleepawake(struct mmc_host *host, int sleep);
 int mmc_bus_test(struct mmc_card *card, u8 bus_width);
+int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status);
 
 #endif
 
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/quirks.c linux-libre-3.2-gnu/drivers/mmc/core/quirks.c
--- linux-libre-3.1-gnu/drivers/mmc/core/quirks.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/quirks.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/mmc/card.h>
 
 #ifndef SDIO_VENDOR_ID_TI
@@ -21,6 +22,14 @@
 #define SDIO_DEVICE_ID_TI_WL1271	0x4076
 #endif
 
+#ifndef SDIO_VENDOR_ID_STE
+#define SDIO_VENDOR_ID_STE		0x0020
+#endif
+
+#ifndef SDIO_DEVICE_ID_STE_CW1200
+#define SDIO_DEVICE_ID_STE_CW1200	0x2280
+#endif
+
 /*
  * This hook just adds a quirk for all sdio devices
  */
@@ -46,6 +55,9 @@
 	SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
 		   add_quirk, MMC_QUIRK_DISABLE_CD),
 
+	SDIO_FIXUP(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200,
+		   add_quirk, MMC_QUIRK_BROKEN_BYTE_MODE_512),
+
 	END_FIXUP
 };
 
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/sd.c linux-libre-3.2-gnu/drivers/mmc/core/sd.c
--- linux-libre-3.1-gnu/drivers/mmc/core/sd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/sd.c	2012-01-04 18:55:44.000000000 -0500
@@ -12,6 +12,7 @@
 
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <linux/stat.h>
 
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
@@ -163,7 +164,7 @@
 		csd->erase_size = 1;
 		break;
 	default:
-		printk(KERN_ERR "%s: unrecognised CSD structure version %d\n",
+		pr_err("%s: unrecognised CSD structure version %d\n",
 			mmc_hostname(card->host), csd_struct);
 		return -EINVAL;
 	}
@@ -187,7 +188,7 @@
 
 	scr_struct = UNSTUFF_BITS(resp, 60, 4);
 	if (scr_struct != 0) {
-		printk(KERN_ERR "%s: unrecognised SCR structure version %d\n",
+		pr_err("%s: unrecognised SCR structure version %d\n",
 			mmc_hostname(card->host), scr_struct);
 		return -EINVAL;
 	}
@@ -218,7 +219,7 @@
 	u32 *ssr;
 
 	if (!(card->csd.cmdclass & CCC_APP_SPEC)) {
-		printk(KERN_WARNING "%s: card lacks mandatory SD Status "
+		pr_warning("%s: card lacks mandatory SD Status "
 			"function.\n", mmc_hostname(card->host));
 		return 0;
 	}
@@ -229,7 +230,7 @@
 
 	err = mmc_app_sd_status(card, ssr);
 	if (err) {
-		printk(KERN_WARNING "%s: problem reading SD Status "
+		pr_warning("%s: problem reading SD Status "
 			"register.\n", mmc_hostname(card->host));
 		err = 0;
 		goto out;
@@ -253,7 +254,7 @@
 			card->ssr.erase_offset = eo * 1000;
 		}
 	} else {
-		printk(KERN_WARNING "%s: SD Status: Invalid Allocation Unit "
+		pr_warning("%s: SD Status: Invalid Allocation Unit "
 			"size.\n", mmc_hostname(card->host));
 	}
 out:
@@ -273,7 +274,7 @@
 		return 0;
 
 	if (!(card->csd.cmdclass & CCC_SWITCH)) {
-		printk(KERN_WARNING "%s: card lacks mandatory switch "
+		pr_warning("%s: card lacks mandatory switch "
 			"function, performance might suffer.\n",
 			mmc_hostname(card->host));
 		return 0;
@@ -283,7 +284,7 @@
 
 	status = kmalloc(64, GFP_KERNEL);
 	if (!status) {
-		printk(KERN_ERR "%s: could not allocate a buffer for "
+		pr_err("%s: could not allocate a buffer for "
 			"switch capabilities.\n",
 			mmc_hostname(card->host));
 		return -ENOMEM;
@@ -299,13 +300,16 @@
 		if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
 			goto out;
 
-		printk(KERN_WARNING "%s: problem reading Bus Speed modes.\n",
+		pr_warning("%s: problem reading Bus Speed modes.\n",
 			mmc_hostname(card->host));
 		err = 0;
 
 		goto out;
 	}
 
+	if (status[13] & UHS_SDR50_BUS_SPEED)
+		card->sw_caps.hs_max_dtr = 50000000;
+
 	if (card->scr.sda_spec3) {
 		card->sw_caps.sd3_bus_mode = status[13];
 
@@ -319,7 +323,7 @@
 			if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
 				goto out;
 
-			printk(KERN_WARNING "%s: problem reading "
+			pr_warning("%s: problem reading "
 				"Driver Strength.\n",
 				mmc_hostname(card->host));
 			err = 0;
@@ -339,7 +343,7 @@
 			if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
 				goto out;
 
-			printk(KERN_WARNING "%s: problem reading "
+			pr_warning("%s: problem reading "
 				"Current Limit.\n",
 				mmc_hostname(card->host));
 			err = 0;
@@ -348,9 +352,6 @@
 		}
 
 		card->sw_caps.sd3_curr_limit = status[7];
-	} else {
-		if (status[13] & 0x02)
-			card->sw_caps.hs_max_dtr = 50000000;
 	}
 
 out:
@@ -383,7 +384,7 @@
 
 	status = kmalloc(64, GFP_KERNEL);
 	if (!status) {
-		printk(KERN_ERR "%s: could not allocate a buffer for "
+		pr_err("%s: could not allocate a buffer for "
 			"switch capabilities.\n", mmc_hostname(card->host));
 		return -ENOMEM;
 	}
@@ -393,7 +394,7 @@
 		goto out;
 
 	if ((status[16] & 0xF) != 1) {
-		printk(KERN_WARNING "%s: Problem switching card "
+		pr_warning("%s: Problem switching card "
 			"into high-speed mode!\n",
 			mmc_hostname(card->host));
 		err = 0;
@@ -459,7 +460,7 @@
 		return err;
 
 	if ((status[15] & 0xF) != drive_strength) {
-		printk(KERN_WARNING "%s: Problem setting drive strength!\n",
+		pr_warning("%s: Problem setting drive strength!\n",
 			mmc_hostname(card->host));
 		return 0;
 	}
@@ -538,7 +539,7 @@
 		return err;
 
 	if ((status[16] & 0xF) != card->sd_bus_speed)
-		printk(KERN_WARNING "%s: Problem setting bus speed mode!\n",
+		pr_warning("%s: Problem setting bus speed mode!\n",
 			mmc_hostname(card->host));
 	else {
 		mmc_set_timing(card->host, timing);
@@ -600,7 +601,7 @@
 		return err;
 
 	if (((status[15] >> 4) & 0x0F) != current_limit)
-		printk(KERN_WARNING "%s: Problem setting current limit!\n",
+		pr_warning("%s: Problem setting current limit!\n",
 			mmc_hostname(card->host));
 
 	return 0;
@@ -622,7 +623,7 @@
 
 	status = kmalloc(64, GFP_KERNEL);
 	if (!status) {
-		printk(KERN_ERR "%s: could not allocate a buffer for "
+		pr_err("%s: could not allocate a buffer for "
 			"switch capabilities.\n", mmc_hostname(card->host));
 		return -ENOMEM;
 	}
@@ -852,7 +853,7 @@
 			ro = host->ops->get_ro(host);
 
 		if (ro < 0) {
-			printk(KERN_WARNING "%s: host does not "
+			pr_warning("%s: host does not "
 				"support reading read-only "
 				"switch. assuming write-enable.\n",
 				mmc_hostname(host));
@@ -929,8 +930,6 @@
 		err = mmc_send_relative_addr(host, &card->rca);
 		if (err)
 			return err;
-
-		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
 	}
 
 	if (!oldcard) {
@@ -1043,6 +1042,7 @@
 
 		mmc_claim_host(host);
 		mmc_detach_bus(host);
+		mmc_power_off(host);
 		mmc_release_host(host);
 	}
 }
@@ -1167,7 +1167,7 @@
 	 * support.
 	 */
 	if (ocr & 0x7F) {
-		printk(KERN_WARNING "%s: card claims to support voltages "
+		pr_warning("%s: card claims to support voltages "
 		       "below the defined range. These will be ignored.\n",
 		       mmc_hostname(host));
 		ocr &= ~0x7F;
@@ -1175,7 +1175,7 @@
 
 	if ((ocr & MMC_VDD_165_195) &&
 	    !(host->ocr_avail_sd & MMC_VDD_165_195)) {
-		printk(KERN_WARNING "%s: SD card claims to support the "
+		pr_warning("%s: SD card claims to support the "
 		       "incompletely defined 'low voltage range'. This "
 		       "will be ignored.\n", mmc_hostname(host));
 		ocr &= ~MMC_VDD_165_195;
@@ -1214,7 +1214,7 @@
 err:
 	mmc_detach_bus(host);
 
-	printk(KERN_ERR "%s: error %d whilst initialising SD card\n",
+	pr_err("%s: error %d whilst initialising SD card\n",
 		mmc_hostname(host), err);
 
 	return err;
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/sdio_bus.c linux-libre-3.2-gnu/drivers/mmc/core/sdio_bus.c
--- linux-libre-3.1-gnu/drivers/mmc/core/sdio_bus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/sdio_bus.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,6 +13,7 @@
 
 #include <linux/device.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 
@@ -173,7 +174,7 @@
 	drv->remove(func);
 
 	if (func->irq_handler) {
-		printk(KERN_WARNING "WARNING: driver %s did not remove "
+		pr_warning("WARNING: driver %s did not remove "
 			"its interrupt handler!\n", drv->name);
 		sdio_claim_host(func);
 		sdio_release_irq(func);
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/sdio.c linux-libre-3.2-gnu/drivers/mmc/core/sdio.c
--- linux-libre-3.1-gnu/drivers/mmc/core/sdio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/sdio.c	2012-01-04 18:55:44.000000000 -0500
@@ -111,8 +111,8 @@
 
 	cccr_vsn = data & 0x0f;
 
-	if (cccr_vsn > SDIO_CCCR_REV_1_20) {
-		printk(KERN_ERR "%s: unrecognised CCCR structure version %d\n",
+	if (cccr_vsn > SDIO_CCCR_REV_3_00) {
+		pr_err("%s: unrecognised CCCR structure version %d\n",
 			mmc_hostname(card->host), cccr_vsn);
 		return -EINVAL;
 	}
@@ -408,8 +408,6 @@
 		 */
 		if (oldcard)
 			oldcard->rca = card->rca;
-
-		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
 	}
 
 	/*
@@ -597,6 +595,7 @@
 
 		mmc_claim_host(host);
 		mmc_detach_bus(host);
+		mmc_power_off(host);
 		mmc_release_host(host);
 	}
 }
@@ -778,7 +777,7 @@
 	 * support.
 	 */
 	if (ocr & 0x7F) {
-		printk(KERN_WARNING "%s: card claims to support voltages "
+		pr_warning("%s: card claims to support voltages "
 		       "below the defined range. These will be ignored.\n",
 		       mmc_hostname(host));
 		ocr &= ~0x7F;
@@ -875,7 +874,7 @@
 err:
 	mmc_detach_bus(host);
 
-	printk(KERN_ERR "%s: error %d whilst initialising SDIO card\n",
+	pr_err("%s: error %d whilst initialising SDIO card\n",
 		mmc_hostname(host), err);
 
 	return err;
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/sdio_cis.c linux-libre-3.2-gnu/drivers/mmc/core/sdio_cis.c
--- linux-libre-3.1-gnu/drivers/mmc/core/sdio_cis.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/sdio_cis.c	2012-01-04 18:55:44.000000000 -0500
@@ -132,7 +132,7 @@
 			ret = -EINVAL;
 		}
 		if (ret && ret != -EILSEQ && ret != -ENOENT) {
-			printk(KERN_ERR "%s: bad %s tuple 0x%02x (%u bytes)\n",
+			pr_err("%s: bad %s tuple 0x%02x (%u bytes)\n",
 			       mmc_hostname(card->host), tpl_descr, code, size);
 		}
 	} else {
@@ -313,7 +313,7 @@
 
 			if (ret == -ENOENT) {
 				/* warn about unknown tuples */
-				printk(KERN_WARNING "%s: queuing unknown"
+				pr_warning("%s: queuing unknown"
 				       " CIS tuple 0x%02x (%u bytes)\n",
 				       mmc_hostname(card->host),
 				       tpl_code, tpl_link);
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/sdio_io.c linux-libre-3.2-gnu/drivers/mmc/core/sdio_io.c
--- linux-libre-3.1-gnu/drivers/mmc/core/sdio_io.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/sdio_io.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  * your option) any later version.
  */
 
+#include <linux/export.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/sdio.h>
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/sdio_irq.c linux-libre-3.2-gnu/drivers/mmc/core/sdio_irq.c
--- linux-libre-3.1-gnu/drivers/mmc/core/sdio_irq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/sdio_irq.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/kthread.h>
+#include <linux/export.h>
 #include <linux/wait.h>
 #include <linux/delay.h>
 
@@ -45,7 +46,7 @@
 
 	ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0, &pending);
 	if (ret) {
-		printk(KERN_DEBUG "%s: error %d reading SDIO_CCCR_INTx\n",
+		pr_debug("%s: error %d reading SDIO_CCCR_INTx\n",
 		       mmc_card_id(card), ret);
 		return ret;
 	}
@@ -55,7 +56,7 @@
 		if (pending & (1 << i)) {
 			func = card->sdio_func[i - 1];
 			if (!func) {
-				printk(KERN_WARNING "%s: pending IRQ for "
+				pr_warning("%s: pending IRQ for "
 					"non-existent function\n",
 					mmc_card_id(card));
 				ret = -EINVAL;
@@ -63,7 +64,7 @@
 				func->irq_handler(func);
 				count++;
 			} else {
-				printk(KERN_WARNING "%s: pending IRQ with no handler\n",
+				pr_warning("%s: pending IRQ with no handler\n",
 				       sdio_func_id(func));
 				ret = -EINVAL;
 			}
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/sdio_ops.c linux-libre-3.2-gnu/drivers/mmc/core/sdio_ops.c
--- linux-libre-3.1-gnu/drivers/mmc/core/sdio_ops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/sdio_ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -121,7 +121,7 @@
 int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
 	unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz)
 {
-	struct mmc_request mrq = {0};
+	struct mmc_request mrq = {NULL};
 	struct mmc_command cmd = {0};
 	struct mmc_data data = {0};
 	struct scatterlist sg;
@@ -144,8 +144,11 @@
 	cmd.arg |= fn << 28;
 	cmd.arg |= incr_addr ? 0x04000000 : 0x00000000;
 	cmd.arg |= addr << 9;
-	if (blocks == 1 && blksz <= 512)
-		cmd.arg |= (blksz == 512) ? 0 : blksz;	/* byte mode */
+	if (blocks == 1 && blksz < 512)
+		cmd.arg |= blksz;			/* byte mode */
+	else if (blocks == 1 && blksz == 512 &&
+		 !(mmc_card_broken_byte_mode_512(card)))
+		cmd.arg |= 0;				/* byte mode, 0==512 */
 	else
 		cmd.arg |= 0x08000000 | blocks;		/* block mode */
 	cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
diff -druN linux-libre-3.1-gnu/drivers/mmc/core/sd_ops.c linux-libre-3.2-gnu/drivers/mmc/core/sd_ops.c
--- linux-libre-3.1-gnu/drivers/mmc/core/sd_ops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/core/sd_ops.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 
 #include <linux/slab.h>
 #include <linux/types.h>
+#include <linux/export.h>
 #include <linux/scatterlist.h>
 
 #include <linux/mmc/host.h>
@@ -67,7 +68,7 @@
 int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
 	struct mmc_command *cmd, int retries)
 {
-	struct mmc_request mrq = {0};
+	struct mmc_request mrq = {NULL};
 
 	int i, err;
 
@@ -244,7 +245,7 @@
 int mmc_app_send_scr(struct mmc_card *card, u32 *scr)
 {
 	int err;
-	struct mmc_request mrq = {0};
+	struct mmc_request mrq = {NULL};
 	struct mmc_command cmd = {0};
 	struct mmc_data data = {0};
 	struct scatterlist sg;
@@ -303,7 +304,7 @@
 int mmc_sd_switch(struct mmc_card *card, int mode, int group,
 	u8 value, u8 *resp)
 {
-	struct mmc_request mrq = {0};
+	struct mmc_request mrq = {NULL};
 	struct mmc_command cmd = {0};
 	struct mmc_data data = {0};
 	struct scatterlist sg;
@@ -348,7 +349,7 @@
 int mmc_app_sd_status(struct mmc_card *card, void *ssr)
 {
 	int err;
-	struct mmc_request mrq = {0};
+	struct mmc_request mrq = {NULL};
 	struct mmc_command cmd = {0};
 	struct mmc_data data = {0};
 	struct scatterlist sg;
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/at91_mci.c linux-libre-3.2-gnu/drivers/mmc/host/at91_mci.c
--- linux-libre-3.1-gnu/drivers/mmc/host/at91_mci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/at91_mci.c	2012-01-04 18:55:44.000000000 -0500
@@ -869,7 +869,11 @@
 static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
 {
 	struct at91mci_host *host = _host;
-	int present = !gpio_get_value(irq_to_gpio(irq));
+	int present;
+
+	/* entering this ISR means that we have configured det_pin:
+	 * we can use its value in board structure */
+	present = !gpio_get_value(host->board->det_pin);
 
 	/*
 	 * we expect this irq on both insert and remove,
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/atmel-mci.c linux-libre-3.2-gnu/drivers/mmc/host/atmel-mci.c
--- linux-libre-3.1-gnu/drivers/mmc/host/atmel-mci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/atmel-mci.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 
 #include <mach/atmel-mci.h>
 #include <linux/atmel-mci.h>
+#include <linux/atmel_pdc.h>
 
 #include <asm/io.h>
 #include <asm/unaligned.h>
@@ -39,7 +40,7 @@
 
 #include "atmel-mci-regs.h"
 
-#define ATMCI_DATA_ERROR_FLAGS	(MCI_DCRCE | MCI_DTOE | MCI_OVRE | MCI_UNRE)
+#define ATMCI_DATA_ERROR_FLAGS	(ATMCI_DCRCE | ATMCI_DTOE | ATMCI_OVRE | ATMCI_UNRE)
 #define ATMCI_DMA_THRESHOLD	16
 
 enum {
@@ -58,18 +59,35 @@
 	STATE_DATA_ERROR,
 };
 
+enum atmci_xfer_dir {
+	XFER_RECEIVE = 0,
+	XFER_TRANSMIT,
+};
+
+enum atmci_pdc_buf {
+	PDC_FIRST_BUF = 0,
+	PDC_SECOND_BUF,
+};
+
+struct atmel_mci_caps {
+	bool    has_dma;
+	bool    has_pdc;
+	bool    has_cfg_reg;
+	bool    has_cstor_reg;
+	bool    has_highspeed;
+	bool    has_rwproof;
+};
+
 struct atmel_mci_dma {
-#ifdef CONFIG_MMC_ATMELMCI_DMA
 	struct dma_chan			*chan;
 	struct dma_async_tx_descriptor	*data_desc;
-#endif
 };
 
 /**
  * struct atmel_mci - MMC controller state shared between all slots
  * @lock: Spinlock protecting the queue and associated data.
  * @regs: Pointer to MMIO registers.
- * @sg: Scatterlist entry currently being processed by PIO code, if any.
+ * @sg: Scatterlist entry currently being processed by PIO or PDC code.
  * @pio_offset: Offset into the current scatterlist entry.
  * @cur_slot: The slot which is currently using the controller.
  * @mrq: The request currently being processed on @cur_slot,
@@ -77,6 +95,7 @@
  * @cmd: The command currently being sent to the card, or NULL.
  * @data: The data currently being transferred, or NULL if no data
  *	transfer is in progress.
+ * @data_size: just data->blocks * data->blksz.
  * @dma: DMA client state.
  * @data_chan: DMA channel being used for the current data transfer.
  * @cmd_status: Snapshot of SR taken upon completion of the current
@@ -103,6 +122,13 @@
  * @mck: The peripheral bus clock hooked up to the MMC controller.
  * @pdev: Platform device associated with the MMC controller.
  * @slot: Slots sharing this MMC controller.
+ * @caps: MCI capabilities depending on MCI version.
+ * @prepare_data: function to setup MCI before data transfer which
+ * depends on MCI capabilities.
+ * @submit_data: function to start data transfer which depends on MCI
+ * capabilities.
+ * @stop_transfer: function to stop data transfer which depends on MCI
+ * capabilities.
  *
  * Locking
  * =======
@@ -143,6 +169,7 @@
 	struct mmc_request	*mrq;
 	struct mmc_command	*cmd;
 	struct mmc_data		*data;
+	unsigned int		data_size;
 
 	struct atmel_mci_dma	dma;
 	struct dma_chan		*data_chan;
@@ -166,7 +193,13 @@
 	struct clk		*mck;
 	struct platform_device	*pdev;
 
-	struct atmel_mci_slot	*slot[ATMEL_MCI_MAX_NR_SLOTS];
+	struct atmel_mci_slot	*slot[ATMCI_MAX_NR_SLOTS];
+
+	struct atmel_mci_caps   caps;
+
+	u32 (*prepare_data)(struct atmel_mci *host, struct mmc_data *data);
+	void (*submit_data)(struct atmel_mci *host, struct mmc_data *data);
+	void (*stop_transfer)(struct atmel_mci *host);
 };
 
 /**
@@ -220,31 +253,6 @@
 	set_bit(event, &host->pending_events)
 
 /*
- * Enable or disable features/registers based on
- * whether the processor supports them
- */
-static bool mci_has_rwproof(void)
-{
-	if (cpu_is_at91sam9261() || cpu_is_at91rm9200())
-		return false;
-	else
-		return true;
-}
-
-/*
- * The new MCI2 module isn't 100% compatible with the old MCI module,
- * and it has a few nice features which we want to use...
- */
-static inline bool atmci_is_mci2(void)
-{
-	if (cpu_is_at91sam9g45())
-		return true;
-
-	return false;
-}
-
-
-/*
  * The debugfs stuff below is mostly optimized away when
  * CONFIG_DEBUG_FS is not set.
  */
@@ -352,7 +360,7 @@
 	struct atmel_mci	*host = s->private;
 	u32			*buf;
 
-	buf = kmalloc(MCI_REGS_SIZE, GFP_KERNEL);
+	buf = kmalloc(ATMCI_REGS_SIZE, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 
@@ -363,47 +371,50 @@
 	 */
 	spin_lock_bh(&host->lock);
 	clk_enable(host->mck);
-	memcpy_fromio(buf, host->regs, MCI_REGS_SIZE);
+	memcpy_fromio(buf, host->regs, ATMCI_REGS_SIZE);
 	clk_disable(host->mck);
 	spin_unlock_bh(&host->lock);
 
 	seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n",
-			buf[MCI_MR / 4],
-			buf[MCI_MR / 4] & MCI_MR_RDPROOF ? " RDPROOF" : "",
-			buf[MCI_MR / 4] & MCI_MR_WRPROOF ? " WRPROOF" : "",
-			buf[MCI_MR / 4] & 0xff);
-	seq_printf(s, "DTOR:\t0x%08x\n", buf[MCI_DTOR / 4]);
-	seq_printf(s, "SDCR:\t0x%08x\n", buf[MCI_SDCR / 4]);
-	seq_printf(s, "ARGR:\t0x%08x\n", buf[MCI_ARGR / 4]);
+			buf[ATMCI_MR / 4],
+			buf[ATMCI_MR / 4] & ATMCI_MR_RDPROOF ? " RDPROOF" : "",
+			buf[ATMCI_MR / 4] & ATMCI_MR_WRPROOF ? " WRPROOF" : "",
+			buf[ATMCI_MR / 4] & 0xff);
+	seq_printf(s, "DTOR:\t0x%08x\n", buf[ATMCI_DTOR / 4]);
+	seq_printf(s, "SDCR:\t0x%08x\n", buf[ATMCI_SDCR / 4]);
+	seq_printf(s, "ARGR:\t0x%08x\n", buf[ATMCI_ARGR / 4]);
 	seq_printf(s, "BLKR:\t0x%08x BCNT=%u BLKLEN=%u\n",
-			buf[MCI_BLKR / 4],
-			buf[MCI_BLKR / 4] & 0xffff,
-			(buf[MCI_BLKR / 4] >> 16) & 0xffff);
-	if (atmci_is_mci2())
-		seq_printf(s, "CSTOR:\t0x%08x\n", buf[MCI_CSTOR / 4]);
+			buf[ATMCI_BLKR / 4],
+			buf[ATMCI_BLKR / 4] & 0xffff,
+			(buf[ATMCI_BLKR / 4] >> 16) & 0xffff);
+	if (host->caps.has_cstor_reg)
+		seq_printf(s, "CSTOR:\t0x%08x\n", buf[ATMCI_CSTOR / 4]);
 
 	/* Don't read RSPR and RDR; it will consume the data there */
 
-	atmci_show_status_reg(s, "SR", buf[MCI_SR / 4]);
-	atmci_show_status_reg(s, "IMR", buf[MCI_IMR / 4]);
+	atmci_show_status_reg(s, "SR", buf[ATMCI_SR / 4]);
+	atmci_show_status_reg(s, "IMR", buf[ATMCI_IMR / 4]);
 
-	if (atmci_is_mci2()) {
+	if (host->caps.has_dma) {
 		u32 val;
 
-		val = buf[MCI_DMA / 4];
+		val = buf[ATMCI_DMA / 4];
 		seq_printf(s, "DMA:\t0x%08x OFFSET=%u CHKSIZE=%u%s\n",
 				val, val & 3,
 				((val >> 4) & 3) ?
 					1 << (((val >> 4) & 3) + 1) : 1,
-				val & MCI_DMAEN ? " DMAEN" : "");
+				val & ATMCI_DMAEN ? " DMAEN" : "");
+	}
+	if (host->caps.has_cfg_reg) {
+		u32 val;
 
-		val = buf[MCI_CFG / 4];
+		val = buf[ATMCI_CFG / 4];
 		seq_printf(s, "CFG:\t0x%08x%s%s%s%s\n",
 				val,
-				val & MCI_CFG_FIFOMODE_1DATA ? " FIFOMODE_ONE_DATA" : "",
-				val & MCI_CFG_FERRCTRL_COR ? " FERRCTRL_CLEAR_ON_READ" : "",
-				val & MCI_CFG_HSMODE ? " HSMODE" : "",
-				val & MCI_CFG_LSYNC ? " LSYNC" : "");
+				val & ATMCI_CFG_FIFOMODE_1DATA ? " FIFOMODE_ONE_DATA" : "",
+				val & ATMCI_CFG_FERRCTRL_COR ? " FERRCTRL_CLEAR_ON_READ" : "",
+				val & ATMCI_CFG_HSMODE ? " HSMODE" : "",
+				val & ATMCI_CFG_LSYNC ? " LSYNC" : "");
 	}
 
 	kfree(buf);
@@ -466,7 +477,7 @@
 	dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n");
 }
 
-static inline unsigned int ns_to_clocks(struct atmel_mci *host,
+static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host,
 					unsigned int ns)
 {
 	return (ns * (host->bus_hz / 1000000) + 999) / 1000;
@@ -482,7 +493,8 @@
 	unsigned	dtocyc;
 	unsigned	dtomul;
 
-	timeout = ns_to_clocks(host, data->timeout_ns) + data->timeout_clks;
+	timeout = atmci_ns_to_clocks(host, data->timeout_ns)
+		+ data->timeout_clks;
 
 	for (dtomul = 0; dtomul < 8; dtomul++) {
 		unsigned shift = dtomul_to_shift[dtomul];
@@ -498,7 +510,7 @@
 
 	dev_vdbg(&slot->mmc->class_dev, "setting timeout to %u cycles\n",
 			dtocyc << dtomul_to_shift[dtomul]);
-	mci_writel(host, DTOR, (MCI_DTOMUL(dtomul) | MCI_DTOCYC(dtocyc)));
+	atmci_writel(host, ATMCI_DTOR, (ATMCI_DTOMUL(dtomul) | ATMCI_DTOCYC(dtocyc)));
 }
 
 /*
@@ -512,13 +524,13 @@
 
 	cmd->error = -EINPROGRESS;
 
-	cmdr = MCI_CMDR_CMDNB(cmd->opcode);
+	cmdr = ATMCI_CMDR_CMDNB(cmd->opcode);
 
 	if (cmd->flags & MMC_RSP_PRESENT) {
 		if (cmd->flags & MMC_RSP_136)
-			cmdr |= MCI_CMDR_RSPTYP_136BIT;
+			cmdr |= ATMCI_CMDR_RSPTYP_136BIT;
 		else
-			cmdr |= MCI_CMDR_RSPTYP_48BIT;
+			cmdr |= ATMCI_CMDR_RSPTYP_48BIT;
 	}
 
 	/*
@@ -526,34 +538,34 @@
 	 * it's too difficult to determine whether this is an ACMD or
 	 * not. Better make it 64.
 	 */
-	cmdr |= MCI_CMDR_MAXLAT_64CYC;
+	cmdr |= ATMCI_CMDR_MAXLAT_64CYC;
 
 	if (mmc->ios.bus_mode == MMC_BUSMODE_OPENDRAIN)
-		cmdr |= MCI_CMDR_OPDCMD;
+		cmdr |= ATMCI_CMDR_OPDCMD;
 
 	data = cmd->data;
 	if (data) {
-		cmdr |= MCI_CMDR_START_XFER;
+		cmdr |= ATMCI_CMDR_START_XFER;
 
 		if (cmd->opcode == SD_IO_RW_EXTENDED) {
-			cmdr |= MCI_CMDR_SDIO_BLOCK;
+			cmdr |= ATMCI_CMDR_SDIO_BLOCK;
 		} else {
 			if (data->flags & MMC_DATA_STREAM)
-				cmdr |= MCI_CMDR_STREAM;
+				cmdr |= ATMCI_CMDR_STREAM;
 			else if (data->blocks > 1)
-				cmdr |= MCI_CMDR_MULTI_BLOCK;
+				cmdr |= ATMCI_CMDR_MULTI_BLOCK;
 			else
-				cmdr |= MCI_CMDR_BLOCK;
+				cmdr |= ATMCI_CMDR_BLOCK;
 		}
 
 		if (data->flags & MMC_DATA_READ)
-			cmdr |= MCI_CMDR_TRDIR_READ;
+			cmdr |= ATMCI_CMDR_TRDIR_READ;
 	}
 
 	return cmdr;
 }
 
-static void atmci_start_command(struct atmel_mci *host,
+static void atmci_send_command(struct atmel_mci *host,
 		struct mmc_command *cmd, u32 cmd_flags)
 {
 	WARN_ON(host->cmd);
@@ -563,43 +575,119 @@
 			"start command: ARGR=0x%08x CMDR=0x%08x\n",
 			cmd->arg, cmd_flags);
 
-	mci_writel(host, ARGR, cmd->arg);
-	mci_writel(host, CMDR, cmd_flags);
+	atmci_writel(host, ATMCI_ARGR, cmd->arg);
+	atmci_writel(host, ATMCI_CMDR, cmd_flags);
 }
 
-static void send_stop_cmd(struct atmel_mci *host, struct mmc_data *data)
+static void atmci_send_stop_cmd(struct atmel_mci *host, struct mmc_data *data)
 {
-	atmci_start_command(host, data->stop, host->stop_cmdr);
-	mci_writel(host, IER, MCI_CMDRDY);
+	atmci_send_command(host, data->stop, host->stop_cmdr);
+	atmci_writel(host, ATMCI_IER, ATMCI_CMDRDY);
 }
 
-#ifdef CONFIG_MMC_ATMELMCI_DMA
-static void atmci_dma_cleanup(struct atmel_mci *host)
+/*
+ * Configure given PDC buffer taking care of alignement issues.
+ * Update host->data_size and host->sg.
+ */
+static void atmci_pdc_set_single_buf(struct atmel_mci *host,
+	enum atmci_xfer_dir dir, enum atmci_pdc_buf buf_nb)
 {
-	struct mmc_data			*data = host->data;
+	u32 pointer_reg, counter_reg;
+
+	if (dir == XFER_RECEIVE) {
+		pointer_reg = ATMEL_PDC_RPR;
+		counter_reg = ATMEL_PDC_RCR;
+	} else {
+		pointer_reg = ATMEL_PDC_TPR;
+		counter_reg = ATMEL_PDC_TCR;
+	}
+
+	if (buf_nb == PDC_SECOND_BUF) {
+		pointer_reg += ATMEL_PDC_SCND_BUF_OFF;
+		counter_reg += ATMEL_PDC_SCND_BUF_OFF;
+	}
+
+	atmci_writel(host, pointer_reg, sg_dma_address(host->sg));
+	if (host->data_size <= sg_dma_len(host->sg)) {
+		if (host->data_size & 0x3) {
+			/* If size is different from modulo 4, transfer bytes */
+			atmci_writel(host, counter_reg, host->data_size);
+			atmci_writel(host, ATMCI_MR, host->mode_reg | ATMCI_MR_PDCFBYTE);
+		} else {
+			/* Else transfer 32-bits words */
+			atmci_writel(host, counter_reg, host->data_size / 4);
+		}
+		host->data_size = 0;
+	} else {
+		/* We assume the size of a page is 32-bits aligned */
+		atmci_writel(host, counter_reg, sg_dma_len(host->sg) / 4);
+		host->data_size -= sg_dma_len(host->sg);
+		if (host->data_size)
+			host->sg = sg_next(host->sg);
+	}
+}
+
+/*
+ * Configure PDC buffer according to the data size ie configuring one or two
+ * buffers. Don't use this function if you want to configure only the second
+ * buffer. In this case, use atmci_pdc_set_single_buf.
+ */
+static void atmci_pdc_set_both_buf(struct atmel_mci *host, int dir)
+{
+	atmci_pdc_set_single_buf(host, dir, PDC_FIRST_BUF);
+	if (host->data_size)
+		atmci_pdc_set_single_buf(host, dir, PDC_SECOND_BUF);
+}
+
+/*
+ * Unmap sg lists, called when transfer is finished.
+ */
+static void atmci_pdc_cleanup(struct atmel_mci *host)
+{
+	struct mmc_data         *data = host->data;
 
 	if (data)
-		dma_unmap_sg(host->dma.chan->device->dev,
-			     data->sg, data->sg_len,
-			     ((data->flags & MMC_DATA_WRITE)
-			      ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
+		dma_unmap_sg(&host->pdev->dev,
+				data->sg, data->sg_len,
+				((data->flags & MMC_DATA_WRITE)
+				 ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
 }
 
-static void atmci_stop_dma(struct atmel_mci *host)
+/*
+ * Disable PDC transfers. Update pending flags to EVENT_XFER_COMPLETE after
+ * having received ATMCI_TXBUFE or ATMCI_RXBUFF interrupt. Enable ATMCI_NOTBUSY
+ * interrupt needed for both transfer directions.
+ */
+static void atmci_pdc_complete(struct atmel_mci *host)
 {
-	struct dma_chan *chan = host->data_chan;
+	atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
+	atmci_pdc_cleanup(host);
 
-	if (chan) {
-		dmaengine_terminate_all(chan);
-		atmci_dma_cleanup(host);
-	} else {
-		/* Data transfer was stopped by the interrupt handler */
+	/*
+	 * If the card was removed, data will be NULL. No point trying
+	 * to send the stop command or waiting for NBUSY in this case.
+	 */
+	if (host->data) {
 		atmci_set_pending(host, EVENT_XFER_COMPLETE);
-		mci_writel(host, IER, MCI_NOTBUSY);
+		tasklet_schedule(&host->tasklet);
+		atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
 	}
 }
 
-/* This function is called by the DMA driver from tasklet context. */
+static void atmci_dma_cleanup(struct atmel_mci *host)
+{
+	struct mmc_data                 *data = host->data;
+
+	if (data)
+		dma_unmap_sg(host->dma.chan->device->dev,
+				data->sg, data->sg_len,
+				((data->flags & MMC_DATA_WRITE)
+				 ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
+}
+
+/*
+ * This function is called by the DMA driver from tasklet context.
+ */
 static void atmci_dma_complete(void *arg)
 {
 	struct atmel_mci	*host = arg;
@@ -607,9 +695,9 @@
 
 	dev_vdbg(&host->pdev->dev, "DMA complete\n");
 
-	if (atmci_is_mci2())
+	if (host->caps.has_dma)
 		/* Disable DMA hardware handshaking on MCI */
-		mci_writel(host, DMA, mci_readl(host, DMA) & ~MCI_DMAEN);
+		atmci_writel(host, ATMCI_DMA, atmci_readl(host, ATMCI_DMA) & ~ATMCI_DMAEN);
 
 	atmci_dma_cleanup(host);
 
@@ -641,11 +729,93 @@
 		 * completion callback" rule of the dma engine
 		 * framework.
 		 */
-		mci_writel(host, IER, MCI_NOTBUSY);
+		atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
 	}
 }
 
-static int
+/*
+ * Returns a mask of interrupt flags to be enabled after the whole
+ * request has been prepared.
+ */
+static u32 atmci_prepare_data(struct atmel_mci *host, struct mmc_data *data)
+{
+	u32 iflags;
+
+	data->error = -EINPROGRESS;
+
+	host->sg = data->sg;
+	host->data = data;
+	host->data_chan = NULL;
+
+	iflags = ATMCI_DATA_ERROR_FLAGS;
+
+	/*
+	 * Errata: MMC data write operation with less than 12
+	 * bytes is impossible.
+	 *
+	 * Errata: MCI Transmit Data Register (TDR) FIFO
+	 * corruption when length is not multiple of 4.
+	 */
+	if (data->blocks * data->blksz < 12
+			|| (data->blocks * data->blksz) & 3)
+		host->need_reset = true;
+
+	host->pio_offset = 0;
+	if (data->flags & MMC_DATA_READ)
+		iflags |= ATMCI_RXRDY;
+	else
+		iflags |= ATMCI_TXRDY;
+
+	return iflags;
+}
+
+/*
+ * Set interrupt flags and set block length into the MCI mode register even
+ * if this value is also accessible in the MCI block register. It seems to be
+ * necessary before the High Speed MCI version. It also map sg and configure
+ * PDC registers.
+ */
+static u32
+atmci_prepare_data_pdc(struct atmel_mci *host, struct mmc_data *data)
+{
+	u32 iflags, tmp;
+	unsigned int sg_len;
+	enum dma_data_direction dir;
+
+	data->error = -EINPROGRESS;
+
+	host->data = data;
+	host->sg = data->sg;
+	iflags = ATMCI_DATA_ERROR_FLAGS;
+
+	/* Enable pdc mode */
+	atmci_writel(host, ATMCI_MR, host->mode_reg | ATMCI_MR_PDCMODE);
+
+	if (data->flags & MMC_DATA_READ) {
+		dir = DMA_FROM_DEVICE;
+		iflags |= ATMCI_ENDRX | ATMCI_RXBUFF;
+	} else {
+		dir = DMA_TO_DEVICE;
+		iflags |= ATMCI_ENDTX | ATMCI_TXBUFE;
+	}
+
+	/* Set BLKLEN */
+	tmp = atmci_readl(host, ATMCI_MR);
+	tmp &= 0x0000ffff;
+	tmp |= ATMCI_BLKLEN(data->blksz);
+	atmci_writel(host, ATMCI_MR, tmp);
+
+	/* Configure PDC */
+	host->data_size = data->blocks * data->blksz;
+	sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, dir);
+	if (host->data_size)
+		atmci_pdc_set_both_buf(host,
+			((dir == DMA_FROM_DEVICE) ? XFER_RECEIVE : XFER_TRANSMIT));
+
+	return iflags;
+}
+
+static u32
 atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
 {
 	struct dma_chan			*chan;
@@ -654,6 +824,15 @@
 	unsigned int			i;
 	enum dma_data_direction		direction;
 	unsigned int			sglen;
+	u32 iflags;
+
+	data->error = -EINPROGRESS;
+
+	WARN_ON(host->data);
+	host->sg = NULL;
+	host->data = data;
+
+	iflags = ATMCI_DATA_ERROR_FLAGS;
 
 	/*
 	 * We don't do DMA on "complex" transfers, i.e. with
@@ -661,13 +840,13 @@
 	 * with all the DMA setup overhead for short transfers.
 	 */
 	if (data->blocks * data->blksz < ATMCI_DMA_THRESHOLD)
-		return -EINVAL;
+		return atmci_prepare_data(host, data);
 	if (data->blksz & 3)
-		return -EINVAL;
+		return atmci_prepare_data(host, data);
 
 	for_each_sg(data->sg, sg, data->sg_len, i) {
 		if (sg->offset & 3 || sg->length & 3)
-			return -EINVAL;
+			return atmci_prepare_data(host, data);
 	}
 
 	/* If we don't have a channel, we can't do DMA */
@@ -678,8 +857,8 @@
 	if (!chan)
 		return -ENODEV;
 
-	if (atmci_is_mci2())
-		mci_writel(host, DMA, MCI_DMA_CHKSIZE(3) | MCI_DMAEN);
+	if (host->caps.has_dma)
+		atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(3) | ATMCI_DMAEN);
 
 	if (data->flags & MMC_DATA_READ)
 		direction = DMA_FROM_DEVICE;
@@ -687,7 +866,7 @@
 		direction = DMA_TO_DEVICE;
 
 	sglen = dma_map_sg(chan->device->dev, data->sg,
-			   data->sg_len, direction);
+			data->sg_len, direction);
 
 	desc = chan->device->device_prep_slave_sg(chan,
 			data->sg, sglen, direction,
@@ -699,13 +878,32 @@
 	desc->callback = atmci_dma_complete;
 	desc->callback_param = host;
 
-	return 0;
+	return iflags;
 unmap_exit:
 	dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, direction);
 	return -ENOMEM;
 }
 
-static void atmci_submit_data(struct atmel_mci *host)
+static void
+atmci_submit_data(struct atmel_mci *host, struct mmc_data *data)
+{
+	return;
+}
+
+/*
+ * Start PDC according to transfer direction.
+ */
+static void
+atmci_submit_data_pdc(struct atmel_mci *host, struct mmc_data *data)
+{
+	if (data->flags & MMC_DATA_READ)
+		atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
+	else
+		atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
+}
+
+static void
+atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data)
 {
 	struct dma_chan			*chan = host->data_chan;
 	struct dma_async_tx_descriptor	*desc = host->dma.data_desc;
@@ -716,64 +914,39 @@
 	}
 }
 
-#else /* CONFIG_MMC_ATMELMCI_DMA */
-
-static int atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
-{
-	return -ENOSYS;
-}
-
-static void atmci_submit_data(struct atmel_mci *host) {}
-
-static void atmci_stop_dma(struct atmel_mci *host)
+static void atmci_stop_transfer(struct atmel_mci *host)
 {
-	/* Data transfer was stopped by the interrupt handler */
 	atmci_set_pending(host, EVENT_XFER_COMPLETE);
-	mci_writel(host, IER, MCI_NOTBUSY);
+	atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
 }
 
-#endif /* CONFIG_MMC_ATMELMCI_DMA */
-
 /*
- * Returns a mask of interrupt flags to be enabled after the whole
- * request has been prepared.
+ * Stop data transfer because error(s) occured.
  */
-static u32 atmci_prepare_data(struct atmel_mci *host, struct mmc_data *data)
+static void atmci_stop_transfer_pdc(struct atmel_mci *host)
 {
-	u32 iflags;
-
-	data->error = -EINPROGRESS;
-
-	WARN_ON(host->data);
-	host->sg = NULL;
-	host->data = data;
-
-	iflags = ATMCI_DATA_ERROR_FLAGS;
-	if (atmci_prepare_data_dma(host, data)) {
-		host->data_chan = NULL;
+	atmci_set_pending(host, EVENT_XFER_COMPLETE);
+	atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
+}
 
-		/*
-		 * Errata: MMC data write operation with less than 12
-		 * bytes is impossible.
-		 *
-		 * Errata: MCI Transmit Data Register (TDR) FIFO
-		 * corruption when length is not multiple of 4.
-		 */
-		if (data->blocks * data->blksz < 12
-				|| (data->blocks * data->blksz) & 3)
-			host->need_reset = true;
+static void atmci_stop_transfer_dma(struct atmel_mci *host)
+{
+	struct dma_chan *chan = host->data_chan;
 
-		host->sg = data->sg;
-		host->pio_offset = 0;
-		if (data->flags & MMC_DATA_READ)
-			iflags |= MCI_RXRDY;
-		else
-			iflags |= MCI_TXRDY;
+	if (chan) {
+		dmaengine_terminate_all(chan);
+		atmci_dma_cleanup(host);
+	} else {
+		/* Data transfer was stopped by the interrupt handler */
+		atmci_set_pending(host, EVENT_XFER_COMPLETE);
+		atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
 	}
-
-	return iflags;
 }
 
+/*
+ * Start a request: prepare data if needed, prepare the command and activate
+ * interrupts.
+ */
 static void atmci_start_request(struct atmel_mci *host,
 		struct atmel_mci_slot *slot)
 {
@@ -792,24 +965,24 @@
 	host->data_status = 0;
 
 	if (host->need_reset) {
-		mci_writel(host, CR, MCI_CR_SWRST);
-		mci_writel(host, CR, MCI_CR_MCIEN);
-		mci_writel(host, MR, host->mode_reg);
-		if (atmci_is_mci2())
-			mci_writel(host, CFG, host->cfg_reg);
+		atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
+		atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN);
+		atmci_writel(host, ATMCI_MR, host->mode_reg);
+		if (host->caps.has_cfg_reg)
+			atmci_writel(host, ATMCI_CFG, host->cfg_reg);
 		host->need_reset = false;
 	}
-	mci_writel(host, SDCR, slot->sdc_reg);
+	atmci_writel(host, ATMCI_SDCR, slot->sdc_reg);
 
-	iflags = mci_readl(host, IMR);
-	if (iflags & ~(MCI_SDIOIRQA | MCI_SDIOIRQB))
+	iflags = atmci_readl(host, ATMCI_IMR);
+	if (iflags & ~(ATMCI_SDIOIRQA | ATMCI_SDIOIRQB))
 		dev_warn(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n",
 				iflags);
 
 	if (unlikely(test_and_clear_bit(ATMCI_CARD_NEED_INIT, &slot->flags))) {
 		/* Send init sequence (74 clock cycles) */
-		mci_writel(host, CMDR, MCI_CMDR_SPCMD_INIT);
-		while (!(mci_readl(host, SR) & MCI_CMDRDY))
+		atmci_writel(host, ATMCI_CMDR, ATMCI_CMDR_SPCMD_INIT);
+		while (!(atmci_readl(host, ATMCI_SR) & ATMCI_CMDRDY))
 			cpu_relax();
 	}
 	iflags = 0;
@@ -818,31 +991,31 @@
 		atmci_set_timeout(host, slot, data);
 
 		/* Must set block count/size before sending command */
-		mci_writel(host, BLKR, MCI_BCNT(data->blocks)
-				| MCI_BLKLEN(data->blksz));
+		atmci_writel(host, ATMCI_BLKR, ATMCI_BCNT(data->blocks)
+				| ATMCI_BLKLEN(data->blksz));
 		dev_vdbg(&slot->mmc->class_dev, "BLKR=0x%08x\n",
-			MCI_BCNT(data->blocks) | MCI_BLKLEN(data->blksz));
+			ATMCI_BCNT(data->blocks) | ATMCI_BLKLEN(data->blksz));
 
-		iflags |= atmci_prepare_data(host, data);
+		iflags |= host->prepare_data(host, data);
 	}
 
-	iflags |= MCI_CMDRDY;
+	iflags |= ATMCI_CMDRDY;
 	cmd = mrq->cmd;
 	cmdflags = atmci_prepare_command(slot->mmc, cmd);
-	atmci_start_command(host, cmd, cmdflags);
+	atmci_send_command(host, cmd, cmdflags);
 
 	if (data)
-		atmci_submit_data(host);
+		host->submit_data(host, data);
 
 	if (mrq->stop) {
 		host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop);
-		host->stop_cmdr |= MCI_CMDR_STOP_XFER;
+		host->stop_cmdr |= ATMCI_CMDR_STOP_XFER;
 		if (!(data->flags & MMC_DATA_WRITE))
-			host->stop_cmdr |= MCI_CMDR_TRDIR_READ;
+			host->stop_cmdr |= ATMCI_CMDR_TRDIR_READ;
 		if (data->flags & MMC_DATA_STREAM)
-			host->stop_cmdr |= MCI_CMDR_STREAM;
+			host->stop_cmdr |= ATMCI_CMDR_STREAM;
 		else
-			host->stop_cmdr |= MCI_CMDR_MULTI_BLOCK;
+			host->stop_cmdr |= ATMCI_CMDR_MULTI_BLOCK;
 	}
 
 	/*
@@ -851,7 +1024,7 @@
 	 * conditions (e.g. command and data complete, but stop not
 	 * prepared yet.)
 	 */
-	mci_writel(host, IER, iflags);
+	atmci_writel(host, ATMCI_IER, iflags);
 }
 
 static void atmci_queue_request(struct atmel_mci *host,
@@ -909,13 +1082,13 @@
 	struct atmel_mci	*host = slot->host;
 	unsigned int		i;
 
-	slot->sdc_reg &= ~MCI_SDCBUS_MASK;
+	slot->sdc_reg &= ~ATMCI_SDCBUS_MASK;
 	switch (ios->bus_width) {
 	case MMC_BUS_WIDTH_1:
-		slot->sdc_reg |= MCI_SDCBUS_1BIT;
+		slot->sdc_reg |= ATMCI_SDCBUS_1BIT;
 		break;
 	case MMC_BUS_WIDTH_4:
-		slot->sdc_reg |= MCI_SDCBUS_4BIT;
+		slot->sdc_reg |= ATMCI_SDCBUS_4BIT;
 		break;
 	}
 
@@ -926,10 +1099,10 @@
 		spin_lock_bh(&host->lock);
 		if (!host->mode_reg) {
 			clk_enable(host->mck);
-			mci_writel(host, CR, MCI_CR_SWRST);
-			mci_writel(host, CR, MCI_CR_MCIEN);
-			if (atmci_is_mci2())
-				mci_writel(host, CFG, host->cfg_reg);
+			atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
+			atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN);
+			if (host->caps.has_cfg_reg)
+				atmci_writel(host, ATMCI_CFG, host->cfg_reg);
 		}
 
 		/*
@@ -937,7 +1110,7 @@
 		 * core ios update when finding the minimum.
 		 */
 		slot->clock = ios->clock;
-		for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+		for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
 			if (host->slot[i] && host->slot[i]->clock
 					&& host->slot[i]->clock < clock_min)
 				clock_min = host->slot[i]->clock;
@@ -952,28 +1125,28 @@
 			clkdiv = 255;
 		}
 
-		host->mode_reg = MCI_MR_CLKDIV(clkdiv);
+		host->mode_reg = ATMCI_MR_CLKDIV(clkdiv);
 
 		/*
 		 * WRPROOF and RDPROOF prevent overruns/underruns by
 		 * stopping the clock when the FIFO is full/empty.
 		 * This state is not expected to last for long.
 		 */
-		if (mci_has_rwproof())
-			host->mode_reg |= (MCI_MR_WRPROOF | MCI_MR_RDPROOF);
+		if (host->caps.has_rwproof)
+			host->mode_reg |= (ATMCI_MR_WRPROOF | ATMCI_MR_RDPROOF);
 
-		if (atmci_is_mci2()) {
+		if (host->caps.has_cfg_reg) {
 			/* setup High Speed mode in relation with card capacity */
 			if (ios->timing == MMC_TIMING_SD_HS)
-				host->cfg_reg |= MCI_CFG_HSMODE;
+				host->cfg_reg |= ATMCI_CFG_HSMODE;
 			else
-				host->cfg_reg &= ~MCI_CFG_HSMODE;
+				host->cfg_reg &= ~ATMCI_CFG_HSMODE;
 		}
 
 		if (list_empty(&host->queue)) {
-			mci_writel(host, MR, host->mode_reg);
-			if (atmci_is_mci2())
-				mci_writel(host, CFG, host->cfg_reg);
+			atmci_writel(host, ATMCI_MR, host->mode_reg);
+			if (host->caps.has_cfg_reg)
+				atmci_writel(host, ATMCI_CFG, host->cfg_reg);
 		} else {
 			host->need_clock_update = true;
 		}
@@ -984,16 +1157,16 @@
 
 		spin_lock_bh(&host->lock);
 		slot->clock = 0;
-		for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+		for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
 			if (host->slot[i] && host->slot[i]->clock) {
 				any_slot_active = true;
 				break;
 			}
 		}
 		if (!any_slot_active) {
-			mci_writel(host, CR, MCI_CR_MCIDIS);
+			atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS);
 			if (host->mode_reg) {
-				mci_readl(host, MR);
+				atmci_readl(host, ATMCI_MR);
 				clk_disable(host->mck);
 			}
 			host->mode_reg = 0;
@@ -1057,9 +1230,9 @@
 	struct atmel_mci	*host = slot->host;
 
 	if (enable)
-		mci_writel(host, IER, slot->sdio_irq);
+		atmci_writel(host, ATMCI_IER, slot->sdio_irq);
 	else
-		mci_writel(host, IDR, slot->sdio_irq);
+		atmci_writel(host, ATMCI_IDR, slot->sdio_irq);
 }
 
 static const struct mmc_host_ops atmci_ops = {
@@ -1086,9 +1259,9 @@
 	 * busy transferring data.
 	 */
 	if (host->need_clock_update) {
-		mci_writel(host, MR, host->mode_reg);
-		if (atmci_is_mci2())
-			mci_writel(host, CFG, host->cfg_reg);
+		atmci_writel(host, ATMCI_MR, host->mode_reg);
+		if (host->caps.has_cfg_reg)
+			atmci_writel(host, ATMCI_CFG, host->cfg_reg);
 	}
 
 	host->cur_slot->mrq = NULL;
@@ -1117,16 +1290,16 @@
 	u32		status = host->cmd_status;
 
 	/* Read the response from the card (up to 16 bytes) */
-	cmd->resp[0] = mci_readl(host, RSPR);
-	cmd->resp[1] = mci_readl(host, RSPR);
-	cmd->resp[2] = mci_readl(host, RSPR);
-	cmd->resp[3] = mci_readl(host, RSPR);
+	cmd->resp[0] = atmci_readl(host, ATMCI_RSPR);
+	cmd->resp[1] = atmci_readl(host, ATMCI_RSPR);
+	cmd->resp[2] = atmci_readl(host, ATMCI_RSPR);
+	cmd->resp[3] = atmci_readl(host, ATMCI_RSPR);
 
-	if (status & MCI_RTOE)
+	if (status & ATMCI_RTOE)
 		cmd->error = -ETIMEDOUT;
-	else if ((cmd->flags & MMC_RSP_CRC) && (status & MCI_RCRCE))
+	else if ((cmd->flags & MMC_RSP_CRC) && (status & ATMCI_RCRCE))
 		cmd->error = -EILSEQ;
-	else if (status & (MCI_RINDE | MCI_RDIRE | MCI_RENDE))
+	else if (status & (ATMCI_RINDE | ATMCI_RDIRE | ATMCI_RENDE))
 		cmd->error = -EIO;
 	else
 		cmd->error = 0;
@@ -1136,10 +1309,10 @@
 			"command error: status=0x%08x\n", status);
 
 		if (cmd->data) {
-			atmci_stop_dma(host);
+			host->stop_transfer(host);
 			host->data = NULL;
-			mci_writel(host, IDR, MCI_NOTBUSY
-					| MCI_TXRDY | MCI_RXRDY
+			atmci_writel(host, ATMCI_IDR, ATMCI_NOTBUSY
+					| ATMCI_TXRDY | ATMCI_RXRDY
 					| ATMCI_DATA_ERROR_FLAGS);
 		}
 	}
@@ -1191,11 +1364,11 @@
 				 * Reset controller to terminate any ongoing
 				 * commands or data transfers.
 				 */
-				mci_writel(host, CR, MCI_CR_SWRST);
-				mci_writel(host, CR, MCI_CR_MCIEN);
-				mci_writel(host, MR, host->mode_reg);
-				if (atmci_is_mci2())
-					mci_writel(host, CFG, host->cfg_reg);
+				atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
+				atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN);
+				atmci_writel(host, ATMCI_MR, host->mode_reg);
+				if (host->caps.has_cfg_reg)
+					atmci_writel(host, ATMCI_CFG, host->cfg_reg);
 
 				host->data = NULL;
 				host->cmd = NULL;
@@ -1210,7 +1383,7 @@
 					/* fall through */
 				case STATE_SENDING_DATA:
 					mrq->data->error = -ENOMEDIUM;
-					atmci_stop_dma(host);
+					host->stop_transfer(host);
 					break;
 				case STATE_DATA_BUSY:
 				case STATE_DATA_ERROR:
@@ -1261,7 +1434,7 @@
 	dev_vdbg(&host->pdev->dev,
 		"tasklet: state %u pending/completed/mask %lx/%lx/%x\n",
 		state, host->pending_events, host->completed_events,
-		mci_readl(host, IMR));
+		atmci_readl(host, ATMCI_IMR));
 
 	do {
 		prev_state = state;
@@ -1289,9 +1462,9 @@
 		case STATE_SENDING_DATA:
 			if (atmci_test_and_clear_pending(host,
 						EVENT_DATA_ERROR)) {
-				atmci_stop_dma(host);
+				host->stop_transfer(host);
 				if (data->stop)
-					send_stop_cmd(host, data);
+					atmci_send_stop_cmd(host, data);
 				state = STATE_DATA_ERROR;
 				break;
 			}
@@ -1313,11 +1486,11 @@
 			atmci_set_completed(host, EVENT_DATA_COMPLETE);
 			status = host->data_status;
 			if (unlikely(status & ATMCI_DATA_ERROR_FLAGS)) {
-				if (status & MCI_DTOE) {
+				if (status & ATMCI_DTOE) {
 					dev_dbg(&host->pdev->dev,
 							"data timeout error\n");
 					data->error = -ETIMEDOUT;
-				} else if (status & MCI_DCRCE) {
+				} else if (status & ATMCI_DCRCE) {
 					dev_dbg(&host->pdev->dev,
 							"data CRC error\n");
 					data->error = -EILSEQ;
@@ -1330,7 +1503,7 @@
 			} else {
 				data->bytes_xfered = data->blocks * data->blksz;
 				data->error = 0;
-				mci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS);
+				atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS);
 			}
 
 			if (!data->stop) {
@@ -1340,7 +1513,7 @@
 
 			prev_state = state = STATE_SENDING_STOP;
 			if (!data->error)
-				send_stop_cmd(host, data);
+				atmci_send_stop_cmd(host, data);
 			/* fall through */
 
 		case STATE_SENDING_STOP:
@@ -1380,7 +1553,7 @@
 	unsigned int		nbytes = 0;
 
 	do {
-		value = mci_readl(host, RDR);
+		value = atmci_readl(host, ATMCI_RDR);
 		if (likely(offset + 4 <= sg->length)) {
 			put_unaligned(value, (u32 *)(buf + offset));
 
@@ -1412,9 +1585,9 @@
 			nbytes += offset;
 		}
 
-		status = mci_readl(host, SR);
+		status = atmci_readl(host, ATMCI_SR);
 		if (status & ATMCI_DATA_ERROR_FLAGS) {
-			mci_writel(host, IDR, (MCI_NOTBUSY | MCI_RXRDY
+			atmci_writel(host, ATMCI_IDR, (ATMCI_NOTBUSY | ATMCI_RXRDY
 						| ATMCI_DATA_ERROR_FLAGS));
 			host->data_status = status;
 			data->bytes_xfered += nbytes;
@@ -1423,7 +1596,7 @@
 			tasklet_schedule(&host->tasklet);
 			return;
 		}
-	} while (status & MCI_RXRDY);
+	} while (status & ATMCI_RXRDY);
 
 	host->pio_offset = offset;
 	data->bytes_xfered += nbytes;
@@ -1431,8 +1604,8 @@
 	return;
 
 done:
-	mci_writel(host, IDR, MCI_RXRDY);
-	mci_writel(host, IER, MCI_NOTBUSY);
+	atmci_writel(host, ATMCI_IDR, ATMCI_RXRDY);
+	atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
 	data->bytes_xfered += nbytes;
 	smp_wmb();
 	atmci_set_pending(host, EVENT_XFER_COMPLETE);
@@ -1451,7 +1624,7 @@
 	do {
 		if (likely(offset + 4 <= sg->length)) {
 			value = get_unaligned((u32 *)(buf + offset));
-			mci_writel(host, TDR, value);
+			atmci_writel(host, ATMCI_TDR, value);
 
 			offset += 4;
 			nbytes += 4;
@@ -1472,20 +1645,20 @@
 
 			host->sg = sg = sg_next(sg);
 			if (!sg) {
-				mci_writel(host, TDR, value);
+				atmci_writel(host, ATMCI_TDR, value);
 				goto done;
 			}
 
 			offset = 4 - remaining;
 			buf = sg_virt(sg);
 			memcpy((u8 *)&value + remaining, buf, offset);
-			mci_writel(host, TDR, value);
+			atmci_writel(host, ATMCI_TDR, value);
 			nbytes += offset;
 		}
 
-		status = mci_readl(host, SR);
+		status = atmci_readl(host, ATMCI_SR);
 		if (status & ATMCI_DATA_ERROR_FLAGS) {
-			mci_writel(host, IDR, (MCI_NOTBUSY | MCI_TXRDY
+			atmci_writel(host, ATMCI_IDR, (ATMCI_NOTBUSY | ATMCI_TXRDY
 						| ATMCI_DATA_ERROR_FLAGS));
 			host->data_status = status;
 			data->bytes_xfered += nbytes;
@@ -1494,7 +1667,7 @@
 			tasklet_schedule(&host->tasklet);
 			return;
 		}
-	} while (status & MCI_TXRDY);
+	} while (status & ATMCI_TXRDY);
 
 	host->pio_offset = offset;
 	data->bytes_xfered += nbytes;
@@ -1502,8 +1675,8 @@
 	return;
 
 done:
-	mci_writel(host, IDR, MCI_TXRDY);
-	mci_writel(host, IER, MCI_NOTBUSY);
+	atmci_writel(host, ATMCI_IDR, ATMCI_TXRDY);
+	atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
 	data->bytes_xfered += nbytes;
 	smp_wmb();
 	atmci_set_pending(host, EVENT_XFER_COMPLETE);
@@ -1511,7 +1684,7 @@
 
 static void atmci_cmd_interrupt(struct atmel_mci *host, u32 status)
 {
-	mci_writel(host, IDR, MCI_CMDRDY);
+	atmci_writel(host, ATMCI_IDR, ATMCI_CMDRDY);
 
 	host->cmd_status = status;
 	smp_wmb();
@@ -1523,7 +1696,7 @@
 {
 	int	i;
 
-	for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+	for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
 		struct atmel_mci_slot *slot = host->slot[i];
 		if (slot && (status & slot->sdio_irq)) {
 			mmc_signal_sdio_irq(slot->mmc);
@@ -1539,40 +1712,92 @@
 	unsigned int		pass_count = 0;
 
 	do {
-		status = mci_readl(host, SR);
-		mask = mci_readl(host, IMR);
+		status = atmci_readl(host, ATMCI_SR);
+		mask = atmci_readl(host, ATMCI_IMR);
 		pending = status & mask;
 		if (!pending)
 			break;
 
 		if (pending & ATMCI_DATA_ERROR_FLAGS) {
-			mci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS
-					| MCI_RXRDY | MCI_TXRDY);
-			pending &= mci_readl(host, IMR);
+			atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS
+					| ATMCI_RXRDY | ATMCI_TXRDY);
+			pending &= atmci_readl(host, ATMCI_IMR);
 
 			host->data_status = status;
 			smp_wmb();
 			atmci_set_pending(host, EVENT_DATA_ERROR);
 			tasklet_schedule(&host->tasklet);
 		}
-		if (pending & MCI_NOTBUSY) {
-			mci_writel(host, IDR,
-					ATMCI_DATA_ERROR_FLAGS | MCI_NOTBUSY);
+
+		if (pending & ATMCI_TXBUFE) {
+			atmci_writel(host, ATMCI_IDR, ATMCI_TXBUFE);
+			atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX);
+			/*
+			 * We can receive this interruption before having configured
+			 * the second pdc buffer, so we need to reconfigure first and
+			 * second buffers again
+			 */
+			if (host->data_size) {
+				atmci_pdc_set_both_buf(host, XFER_TRANSMIT);
+				atmci_writel(host, ATMCI_IER, ATMCI_ENDTX);
+				atmci_writel(host, ATMCI_IER, ATMCI_TXBUFE);
+			} else {
+				atmci_pdc_complete(host);
+			}
+		} else if (pending & ATMCI_ENDTX) {
+			atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX);
+
+			if (host->data_size) {
+				atmci_pdc_set_single_buf(host,
+						XFER_TRANSMIT, PDC_SECOND_BUF);
+				atmci_writel(host, ATMCI_IER, ATMCI_ENDTX);
+			}
+		}
+
+		if (pending & ATMCI_RXBUFF) {
+			atmci_writel(host, ATMCI_IDR, ATMCI_RXBUFF);
+			atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX);
+			/*
+			 * We can receive this interruption before having configured
+			 * the second pdc buffer, so we need to reconfigure first and
+			 * second buffers again
+			 */
+			if (host->data_size) {
+				atmci_pdc_set_both_buf(host, XFER_RECEIVE);
+				atmci_writel(host, ATMCI_IER, ATMCI_ENDRX);
+				atmci_writel(host, ATMCI_IER, ATMCI_RXBUFF);
+			} else {
+				atmci_pdc_complete(host);
+			}
+		} else if (pending & ATMCI_ENDRX) {
+			atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX);
+
+			if (host->data_size) {
+				atmci_pdc_set_single_buf(host,
+						XFER_RECEIVE, PDC_SECOND_BUF);
+				atmci_writel(host, ATMCI_IER, ATMCI_ENDRX);
+			}
+		}
+
+
+		if (pending & ATMCI_NOTBUSY) {
+			atmci_writel(host, ATMCI_IDR,
+					ATMCI_DATA_ERROR_FLAGS | ATMCI_NOTBUSY);
 			if (!host->data_status)
 				host->data_status = status;
 			smp_wmb();
 			atmci_set_pending(host, EVENT_DATA_COMPLETE);
 			tasklet_schedule(&host->tasklet);
 		}
-		if (pending & MCI_RXRDY)
+		if (pending & ATMCI_RXRDY)
 			atmci_read_data_pio(host);
-		if (pending & MCI_TXRDY)
+		if (pending & ATMCI_TXRDY)
 			atmci_write_data_pio(host);
 
-		if (pending & MCI_CMDRDY)
+		if (pending & ATMCI_CMDRDY)
 			atmci_cmd_interrupt(host, status);
 
-		if (pending & (MCI_SDIOIRQA | MCI_SDIOIRQB))
+		if (pending & (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB))
 			atmci_sdio_interrupt(host, status);
 
 	} while (pass_count++ < 5);
@@ -1621,7 +1846,7 @@
 	mmc->ocr_avail	= MMC_VDD_32_33 | MMC_VDD_33_34;
 	if (sdio_irq)
 		mmc->caps |= MMC_CAP_SDIO_IRQ;
-	if (atmci_is_mci2())
+	if (host->caps.has_highspeed)
 		mmc->caps |= MMC_CAP_SD_HIGHSPEED;
 	if (slot_data->bus_width >= 4)
 		mmc->caps |= MMC_CAP_4_BIT_DATA;
@@ -1704,8 +1929,7 @@
 	mmc_free_host(slot->mmc);
 }
 
-#ifdef CONFIG_MMC_ATMELMCI_DMA
-static bool filter(struct dma_chan *chan, void *slave)
+static bool atmci_filter(struct dma_chan *chan, void *slave)
 {
 	struct mci_dma_data	*sl = slave;
 
@@ -1730,14 +1954,14 @@
 		dma_cap_mask_t mask;
 
 		setup_dma_addr(pdata->dma_slave,
-			       host->mapbase + MCI_TDR,
-			       host->mapbase + MCI_RDR);
+			       host->mapbase + ATMCI_TDR,
+			       host->mapbase + ATMCI_RDR);
 
 		/* Try to grab a DMA channel */
 		dma_cap_zero(mask);
 		dma_cap_set(DMA_SLAVE, mask);
 		host->dma.chan =
-			dma_request_channel(mask, filter, pdata->dma_slave);
+			dma_request_channel(mask, atmci_filter, pdata->dma_slave);
 	}
 	if (!host->dma.chan)
 		dev_notice(&host->pdev->dev, "DMA not available, using PIO\n");
@@ -1746,9 +1970,60 @@
 					"Using %s for DMA transfers\n",
 					dma_chan_name(host->dma.chan));
 }
+
+static inline unsigned int atmci_get_version(struct atmel_mci *host)
+{
+	return atmci_readl(host, ATMCI_VERSION) & 0x00000fff;
+}
+
+/*
+ * HSMCI (High Speed MCI) module is not fully compatible with MCI module.
+ * HSMCI provides DMA support and a new config register but no more supports
+ * PDC.
+ */
+static void __init atmci_get_cap(struct atmel_mci *host)
+{
+	unsigned int version;
+
+	version = atmci_get_version(host);
+	dev_info(&host->pdev->dev,
+			"version: 0x%x\n", version);
+
+	host->caps.has_dma = 0;
+	host->caps.has_pdc = 0;
+	host->caps.has_cfg_reg = 0;
+	host->caps.has_cstor_reg = 0;
+	host->caps.has_highspeed = 0;
+	host->caps.has_rwproof = 0;
+
+	/* keep only major version number */
+	switch (version & 0xf00) {
+	case 0x100:
+	case 0x200:
+		host->caps.has_pdc = 1;
+		host->caps.has_rwproof = 1;
+		break;
+	case 0x300:
+	case 0x400:
+	case 0x500:
+#ifdef CONFIG_AT_HDMAC
+		host->caps.has_dma = 1;
 #else
-static void atmci_configure_dma(struct atmel_mci *host) {}
+		host->caps.has_dma = 0;
+		dev_info(&host->pdev->dev,
+			"has dma capability but dma engine is not selected, then use pio\n");
 #endif
+		host->caps.has_cfg_reg = 1;
+		host->caps.has_cstor_reg = 1;
+		host->caps.has_highspeed = 1;
+		host->caps.has_rwproof = 1;
+		break;
+	default:
+		dev_warn(&host->pdev->dev,
+				"Unmanaged mci version, set minimum capabilities\n");
+		break;
+	}
+}
 
 static int __init atmci_probe(struct platform_device *pdev)
 {
@@ -1789,7 +2064,7 @@
 		goto err_ioremap;
 
 	clk_enable(host->mck);
-	mci_writel(host, CR, MCI_CR_SWRST);
+	atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
 	host->bus_hz = clk_get_rate(host->mck);
 	clk_disable(host->mck);
 
@@ -1801,7 +2076,27 @@
 	if (ret)
 		goto err_request_irq;
 
-	atmci_configure_dma(host);
+	/* Get MCI capabilities and set operations according to it */
+	atmci_get_cap(host);
+	if (host->caps.has_dma) {
+		dev_info(&pdev->dev, "using DMA\n");
+		host->prepare_data = &atmci_prepare_data_dma;
+		host->submit_data = &atmci_submit_data_dma;
+		host->stop_transfer = &atmci_stop_transfer_dma;
+	} else if (host->caps.has_pdc) {
+		dev_info(&pdev->dev, "using PDC\n");
+		host->prepare_data = &atmci_prepare_data_pdc;
+		host->submit_data = &atmci_submit_data_pdc;
+		host->stop_transfer = &atmci_stop_transfer_pdc;
+	} else {
+		dev_info(&pdev->dev, "no DMA, no PDC\n");
+		host->prepare_data = &atmci_prepare_data;
+		host->submit_data = &atmci_submit_data;
+		host->stop_transfer = &atmci_stop_transfer;
+	}
+
+	if (host->caps.has_dma)
+		atmci_configure_dma(host);
 
 	platform_set_drvdata(pdev, host);
 
@@ -1810,13 +2105,13 @@
 	ret = -ENODEV;
 	if (pdata->slot[0].bus_width) {
 		ret = atmci_init_slot(host, &pdata->slot[0],
-				0, MCI_SDCSEL_SLOT_A, MCI_SDIOIRQA);
+				0, ATMCI_SDCSEL_SLOT_A, ATMCI_SDIOIRQA);
 		if (!ret)
 			nr_slots++;
 	}
 	if (pdata->slot[1].bus_width) {
 		ret = atmci_init_slot(host, &pdata->slot[1],
-				1, MCI_SDCSEL_SLOT_B, MCI_SDIOIRQB);
+				1, ATMCI_SDCSEL_SLOT_B, ATMCI_SDIOIRQB);
 		if (!ret)
 			nr_slots++;
 	}
@@ -1833,10 +2128,8 @@
 	return 0;
 
 err_init_slot:
-#ifdef CONFIG_MMC_ATMELMCI_DMA
 	if (host->dma.chan)
 		dma_release_channel(host->dma.chan);
-#endif
 	free_irq(irq, host);
 err_request_irq:
 	iounmap(host->regs);
@@ -1854,15 +2147,15 @@
 
 	platform_set_drvdata(pdev, NULL);
 
-	for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+	for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
 		if (host->slot[i])
 			atmci_cleanup_slot(host->slot[i], i);
 	}
 
 	clk_enable(host->mck);
-	mci_writel(host, IDR, ~0UL);
-	mci_writel(host, CR, MCI_CR_MCIDIS);
-	mci_readl(host, SR);
+	atmci_writel(host, ATMCI_IDR, ~0UL);
+	atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS);
+	atmci_readl(host, ATMCI_SR);
 	clk_disable(host->mck);
 
 #ifdef CONFIG_MMC_ATMELMCI_DMA
@@ -1885,7 +2178,7 @@
 	struct atmel_mci *host = dev_get_drvdata(dev);
 	int i;
 
-	 for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+	 for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
 		struct atmel_mci_slot *slot = host->slot[i];
 		int ret;
 
@@ -1916,7 +2209,7 @@
 	int i;
 	int ret = 0;
 
-	for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+	for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
 		struct atmel_mci_slot *slot = host->slot[i];
 		int err;
 
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/atmel-mci-regs.h linux-libre-3.2-gnu/drivers/mmc/host/atmel-mci-regs.h
--- linux-libre-3.1-gnu/drivers/mmc/host/atmel-mci-regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/atmel-mci-regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -17,112 +17,126 @@
 #define __DRIVERS_MMC_ATMEL_MCI_H__
 
 /* MCI Register Definitions */
-#define MCI_CR			0x0000	/* Control */
-# define MCI_CR_MCIEN		(  1 <<  0)	/* MCI Enable */
-# define MCI_CR_MCIDIS		(  1 <<  1)	/* MCI Disable */
-# define MCI_CR_PWSEN		(  1 <<  2)	/* Power Save Enable */
-# define MCI_CR_PWSDIS		(  1 <<  3)	/* Power Save Disable */
-# define MCI_CR_SWRST		(  1 <<  7)	/* Software Reset */
-#define MCI_MR			0x0004	/* Mode */
-# define MCI_MR_CLKDIV(x)	((x) <<  0)	/* Clock Divider */
-# define MCI_MR_PWSDIV(x)	((x) <<  8)	/* Power Saving Divider */
-# define MCI_MR_RDPROOF		(  1 << 11)	/* Read Proof */
-# define MCI_MR_WRPROOF		(  1 << 12)	/* Write Proof */
-# define MCI_MR_PDCFBYTE	(  1 << 13)	/* Force Byte Transfer */
-# define MCI_MR_PDCPADV		(  1 << 14)	/* Padding Value */
-# define MCI_MR_PDCMODE		(  1 << 15)	/* PDC-oriented Mode */
-#define MCI_DTOR		0x0008	/* Data Timeout */
-# define MCI_DTOCYC(x)		((x) <<  0)	/* Data Timeout Cycles */
-# define MCI_DTOMUL(x)		((x) <<  4)	/* Data Timeout Multiplier */
-#define MCI_SDCR		0x000c	/* SD Card / SDIO */
-# define MCI_SDCSEL_SLOT_A	(  0 <<  0)	/* Select SD slot A */
-# define MCI_SDCSEL_SLOT_B	(  1 <<  0)	/* Select SD slot A */
-# define MCI_SDCSEL_MASK	(  3 <<  0)
-# define MCI_SDCBUS_1BIT	(  0 <<  6)	/* 1-bit data bus */
-# define MCI_SDCBUS_4BIT	(  2 <<  6)	/* 4-bit data bus */
-# define MCI_SDCBUS_8BIT	(  3 <<  6)	/* 8-bit data bus[2] */
-# define MCI_SDCBUS_MASK	(  3 <<  6)
-#define MCI_ARGR		0x0010	/* Command Argument */
-#define MCI_CMDR		0x0014	/* Command */
-# define MCI_CMDR_CMDNB(x)	((x) <<  0)	/* Command Opcode */
-# define MCI_CMDR_RSPTYP_NONE	(  0 <<  6)	/* No response */
-# define MCI_CMDR_RSPTYP_48BIT	(  1 <<  6)	/* 48-bit response */
-# define MCI_CMDR_RSPTYP_136BIT	(  2 <<  6)	/* 136-bit response */
-# define MCI_CMDR_SPCMD_INIT	(  1 <<  8)	/* Initialization command */
-# define MCI_CMDR_SPCMD_SYNC	(  2 <<  8)	/* Synchronized command */
-# define MCI_CMDR_SPCMD_INT	(  4 <<  8)	/* Interrupt command */
-# define MCI_CMDR_SPCMD_INTRESP	(  5 <<  8)	/* Interrupt response */
-# define MCI_CMDR_OPDCMD	(  1 << 11)	/* Open Drain */
-# define MCI_CMDR_MAXLAT_5CYC	(  0 << 12)	/* Max latency 5 cycles */
-# define MCI_CMDR_MAXLAT_64CYC	(  1 << 12)	/* Max latency 64 cycles */
-# define MCI_CMDR_START_XFER	(  1 << 16)	/* Start data transfer */
-# define MCI_CMDR_STOP_XFER	(  2 << 16)	/* Stop data transfer */
-# define MCI_CMDR_TRDIR_WRITE	(  0 << 18)	/* Write data */
-# define MCI_CMDR_TRDIR_READ	(  1 << 18)	/* Read data */
-# define MCI_CMDR_BLOCK		(  0 << 19)	/* Single-block transfer */
-# define MCI_CMDR_MULTI_BLOCK	(  1 << 19)	/* Multi-block transfer */
-# define MCI_CMDR_STREAM	(  2 << 19)	/* MMC Stream transfer */
-# define MCI_CMDR_SDIO_BYTE	(  4 << 19)	/* SDIO Byte transfer */
-# define MCI_CMDR_SDIO_BLOCK	(  5 << 19)	/* SDIO Block transfer */
-# define MCI_CMDR_SDIO_SUSPEND	(  1 << 24)	/* SDIO Suspend Command */
-# define MCI_CMDR_SDIO_RESUME	(  2 << 24)	/* SDIO Resume Command */
-#define MCI_BLKR		0x0018	/* Block */
-# define MCI_BCNT(x)		((x) <<  0)	/* Data Block Count */
-# define MCI_BLKLEN(x)		((x) << 16)	/* Data Block Length */
-#define MCI_CSTOR		0x001c	/* Completion Signal Timeout[2] */
-# define MCI_CSTOCYC(x)		((x) <<  0)	/* CST cycles */
-# define MCI_CSTOMUL(x)		((x) <<  4)	/* CST multiplier */
-#define MCI_RSPR		0x0020	/* Response 0 */
-#define MCI_RSPR1		0x0024	/* Response 1 */
-#define MCI_RSPR2		0x0028	/* Response 2 */
-#define MCI_RSPR3		0x002c	/* Response 3 */
-#define MCI_RDR			0x0030	/* Receive Data */
-#define MCI_TDR			0x0034	/* Transmit Data */
-#define MCI_SR			0x0040	/* Status */
-#define MCI_IER			0x0044	/* Interrupt Enable */
-#define MCI_IDR			0x0048	/* Interrupt Disable */
-#define MCI_IMR			0x004c	/* Interrupt Mask */
-# define MCI_CMDRDY		(  1 <<   0)	/* Command Ready */
-# define MCI_RXRDY		(  1 <<   1)	/* Receiver Ready */
-# define MCI_TXRDY		(  1 <<   2)	/* Transmitter Ready */
-# define MCI_BLKE		(  1 <<   3)	/* Data Block Ended */
-# define MCI_DTIP		(  1 <<   4)	/* Data Transfer In Progress */
-# define MCI_NOTBUSY		(  1 <<   5)	/* Data Not Busy */
-# define MCI_SDIOIRQA		(  1 <<   8)	/* SDIO IRQ in slot A */
-# define MCI_SDIOIRQB		(  1 <<   9)	/* SDIO IRQ in slot B */
-# define MCI_RINDE		(  1 <<  16)	/* Response Index Error */
-# define MCI_RDIRE		(  1 <<  17)	/* Response Direction Error */
-# define MCI_RCRCE		(  1 <<  18)	/* Response CRC Error */
-# define MCI_RENDE		(  1 <<  19)	/* Response End Bit Error */
-# define MCI_RTOE		(  1 <<  20)	/* Response Time-Out Error */
-# define MCI_DCRCE		(  1 <<  21)	/* Data CRC Error */
-# define MCI_DTOE		(  1 <<  22)	/* Data Time-Out Error */
-# define MCI_OVRE		(  1 <<  30)	/* RX Overrun Error */
-# define MCI_UNRE		(  1 <<  31)	/* TX Underrun Error */
-#define MCI_DMA			0x0050	/* DMA Configuration[2] */
-# define MCI_DMA_OFFSET(x)	((x) <<  0)	/* DMA Write Buffer Offset */
-# define MCI_DMA_CHKSIZE(x)	((x) <<  4)	/* DMA Channel Read and Write Chunk Size */
-# define MCI_DMAEN		(  1 <<  8)	/* DMA Hardware Handshaking Enable */
-#define MCI_CFG			0x0054	/* Configuration[2] */
-# define MCI_CFG_FIFOMODE_1DATA	(  1 <<  0)	/* MCI Internal FIFO control mode */
-# define MCI_CFG_FERRCTRL_COR	(  1 <<  4)	/* Flow Error flag reset control mode */
-# define MCI_CFG_HSMODE		(  1 <<  8)	/* High Speed Mode */
-# define MCI_CFG_LSYNC		(  1 << 12)	/* Synchronize on the last block */
-#define MCI_WPMR		0x00e4	/* Write Protection Mode[2] */
-# define MCI_WP_EN		(  1 <<  0)	/* WP Enable */
-# define MCI_WP_KEY		(0x4d4349 << 8)	/* WP Key */
-#define MCI_WPSR		0x00e8	/* Write Protection Status[2] */
-# define MCI_GET_WP_VS(x)	((x) & 0x0f)
-# define MCI_GET_WP_VSRC(x)	(((x) >> 8) & 0xffff)
-#define MCI_FIFO_APERTURE	0x0200	/* FIFO Aperture[2] */
+#define ATMCI_CR			0x0000	/* Control */
+# define ATMCI_CR_MCIEN			(  1 <<  0)	/* MCI Enable */
+# define ATMCI_CR_MCIDIS		(  1 <<  1)	/* MCI Disable */
+# define ATMCI_CR_PWSEN			(  1 <<  2)	/* Power Save Enable */
+# define ATMCI_CR_PWSDIS		(  1 <<  3)	/* Power Save Disable */
+# define ATMCI_CR_SWRST			(  1 <<  7)	/* Software Reset */
+#define ATMCI_MR			0x0004	/* Mode */
+# define ATMCI_MR_CLKDIV(x)		((x) <<  0)	/* Clock Divider */
+# define ATMCI_MR_PWSDIV(x)		((x) <<  8)	/* Power Saving Divider */
+# define ATMCI_MR_RDPROOF		(  1 << 11)	/* Read Proof */
+# define ATMCI_MR_WRPROOF		(  1 << 12)	/* Write Proof */
+# define ATMCI_MR_PDCFBYTE		(  1 << 13)	/* Force Byte Transfer */
+# define ATMCI_MR_PDCPADV		(  1 << 14)	/* Padding Value */
+# define ATMCI_MR_PDCMODE		(  1 << 15)	/* PDC-oriented Mode */
+#define ATMCI_DTOR			0x0008	/* Data Timeout */
+# define ATMCI_DTOCYC(x)		((x) <<  0)	/* Data Timeout Cycles */
+# define ATMCI_DTOMUL(x)		((x) <<  4)	/* Data Timeout Multiplier */
+#define ATMCI_SDCR			0x000c	/* SD Card / SDIO */
+# define ATMCI_SDCSEL_SLOT_A		(  0 <<  0)	/* Select SD slot A */
+# define ATMCI_SDCSEL_SLOT_B		(  1 <<  0)	/* Select SD slot A */
+# define ATMCI_SDCSEL_MASK		(  3 <<  0)
+# define ATMCI_SDCBUS_1BIT		(  0 <<  6)	/* 1-bit data bus */
+# define ATMCI_SDCBUS_4BIT		(  2 <<  6)	/* 4-bit data bus */
+# define ATMCI_SDCBUS_8BIT		(  3 <<  6)	/* 8-bit data bus[2] */
+# define ATMCI_SDCBUS_MASK		(  3 <<  6)
+#define ATMCI_ARGR			0x0010	/* Command Argument */
+#define ATMCI_CMDR			0x0014	/* Command */
+# define ATMCI_CMDR_CMDNB(x)		((x) <<  0)	/* Command Opcode */
+# define ATMCI_CMDR_RSPTYP_NONE		(  0 <<  6)	/* No response */
+# define ATMCI_CMDR_RSPTYP_48BIT	(  1 <<  6)	/* 48-bit response */
+# define ATMCI_CMDR_RSPTYP_136BIT	(  2 <<  6)	/* 136-bit response */
+# define ATMCI_CMDR_SPCMD_INIT		(  1 <<  8)	/* Initialization command */
+# define ATMCI_CMDR_SPCMD_SYNC		(  2 <<  8)	/* Synchronized command */
+# define ATMCI_CMDR_SPCMD_INT		(  4 <<  8)	/* Interrupt command */
+# define ATMCI_CMDR_SPCMD_INTRESP	(  5 <<  8)	/* Interrupt response */
+# define ATMCI_CMDR_OPDCMD		(  1 << 11)	/* Open Drain */
+# define ATMCI_CMDR_MAXLAT_5CYC		(  0 << 12)	/* Max latency 5 cycles */
+# define ATMCI_CMDR_MAXLAT_64CYC	(  1 << 12)	/* Max latency 64 cycles */
+# define ATMCI_CMDR_START_XFER		(  1 << 16)	/* Start data transfer */
+# define ATMCI_CMDR_STOP_XFER		(  2 << 16)	/* Stop data transfer */
+# define ATMCI_CMDR_TRDIR_WRITE		(  0 << 18)	/* Write data */
+# define ATMCI_CMDR_TRDIR_READ		(  1 << 18)	/* Read data */
+# define ATMCI_CMDR_BLOCK		(  0 << 19)	/* Single-block transfer */
+# define ATMCI_CMDR_MULTI_BLOCK		(  1 << 19)	/* Multi-block transfer */
+# define ATMCI_CMDR_STREAM		(  2 << 19)	/* MMC Stream transfer */
+# define ATMCI_CMDR_SDIO_BYTE		(  4 << 19)	/* SDIO Byte transfer */
+# define ATMCI_CMDR_SDIO_BLOCK		(  5 << 19)	/* SDIO Block transfer */
+# define ATMCI_CMDR_SDIO_SUSPEND	(  1 << 24)	/* SDIO Suspend Command */
+# define ATMCI_CMDR_SDIO_RESUME		(  2 << 24)	/* SDIO Resume Command */
+#define ATMCI_BLKR			0x0018	/* Block */
+# define ATMCI_BCNT(x)			((x) <<  0)	/* Data Block Count */
+# define ATMCI_BLKLEN(x)		((x) << 16)	/* Data Block Length */
+#define ATMCI_CSTOR			0x001c	/* Completion Signal Timeout[2] */
+# define ATMCI_CSTOCYC(x)		((x) <<  0)	/* CST cycles */
+# define ATMCI_CSTOMUL(x)		((x) <<  4)	/* CST multiplier */
+#define ATMCI_RSPR			0x0020	/* Response 0 */
+#define ATMCI_RSPR1			0x0024	/* Response 1 */
+#define ATMCI_RSPR2			0x0028	/* Response 2 */
+#define ATMCI_RSPR3			0x002c	/* Response 3 */
+#define ATMCI_RDR			0x0030	/* Receive Data */
+#define ATMCI_TDR			0x0034	/* Transmit Data */
+#define ATMCI_SR			0x0040	/* Status */
+#define ATMCI_IER			0x0044	/* Interrupt Enable */
+#define ATMCI_IDR			0x0048	/* Interrupt Disable */
+#define ATMCI_IMR			0x004c	/* Interrupt Mask */
+# define ATMCI_CMDRDY			(  1 <<   0)	/* Command Ready */
+# define ATMCI_RXRDY			(  1 <<   1)	/* Receiver Ready */
+# define ATMCI_TXRDY			(  1 <<   2)	/* Transmitter Ready */
+# define ATMCI_BLKE			(  1 <<   3)	/* Data Block Ended */
+# define ATMCI_DTIP			(  1 <<   4)	/* Data Transfer In Progress */
+# define ATMCI_NOTBUSY			(  1 <<   5)	/* Data Not Busy */
+# define ATMCI_ENDRX			(  1 <<   6)    /* End of RX Buffer */
+# define ATMCI_ENDTX			(  1 <<   7)    /* End of TX Buffer */
+# define ATMCI_SDIOIRQA			(  1 <<   8)	/* SDIO IRQ in slot A */
+# define ATMCI_SDIOIRQB			(  1 <<   9)	/* SDIO IRQ in slot B */
+# define ATMCI_SDIOWAIT			(  1 <<  12)    /* SDIO Read Wait Operation Status */
+# define ATMCI_CSRCV			(  1 <<  13)    /* CE-ATA Completion Signal Received */
+# define ATMCI_RXBUFF			(  1 <<  14)    /* RX Buffer Full */
+# define ATMCI_TXBUFE			(  1 <<  15)    /* TX Buffer Empty */
+# define ATMCI_RINDE			(  1 <<  16)	/* Response Index Error */
+# define ATMCI_RDIRE			(  1 <<  17)	/* Response Direction Error */
+# define ATMCI_RCRCE			(  1 <<  18)	/* Response CRC Error */
+# define ATMCI_RENDE			(  1 <<  19)	/* Response End Bit Error */
+# define ATMCI_RTOE			(  1 <<  20)	/* Response Time-Out Error */
+# define ATMCI_DCRCE			(  1 <<  21)	/* Data CRC Error */
+# define ATMCI_DTOE			(  1 <<  22)	/* Data Time-Out Error */
+# define ATMCI_CSTOE			(  1 <<  23)    /* Completion Signal Time-out Error */
+# define ATMCI_BLKOVRE			(  1 <<  24)    /* DMA Block Overrun Error */
+# define ATMCI_DMADONE			(  1 <<  25)    /* DMA Transfer Done */
+# define ATMCI_FIFOEMPTY		(  1 <<  26)    /* FIFO Empty Flag */
+# define ATMCI_XFRDONE			(  1 <<  27)    /* Transfer Done Flag */
+# define ATMCI_ACKRCV			(  1 <<  28)    /* Boot Operation Acknowledge Received */
+# define ATMCI_ACKRCVE			(  1 <<  29)    /* Boot Operation Acknowledge Error */
+# define ATMCI_OVRE			(  1 <<  30)	/* RX Overrun Error */
+# define ATMCI_UNRE			(  1 <<  31)	/* TX Underrun Error */
+#define ATMCI_DMA			0x0050	/* DMA Configuration[2] */
+# define ATMCI_DMA_OFFSET(x)		((x) <<  0)	/* DMA Write Buffer Offset */
+# define ATMCI_DMA_CHKSIZE(x)		((x) <<  4)	/* DMA Channel Read and Write Chunk Size */
+# define ATMCI_DMAEN			(  1 <<  8)	/* DMA Hardware Handshaking Enable */
+#define ATMCI_CFG			0x0054	/* Configuration[2] */
+# define ATMCI_CFG_FIFOMODE_1DATA	(  1 <<  0)	/* MCI Internal FIFO control mode */
+# define ATMCI_CFG_FERRCTRL_COR		(  1 <<  4)	/* Flow Error flag reset control mode */
+# define ATMCI_CFG_HSMODE		(  1 <<  8)	/* High Speed Mode */
+# define ATMCI_CFG_LSYNC		(  1 << 12)	/* Synchronize on the last block */
+#define ATMCI_WPMR			0x00e4	/* Write Protection Mode[2] */
+# define ATMCI_WP_EN			(  1 <<  0)	/* WP Enable */
+# define ATMCI_WP_KEY			(0x4d4349 << 8)	/* WP Key */
+#define ATMCI_WPSR			0x00e8	/* Write Protection Status[2] */
+# define ATMCI_GET_WP_VS(x)		((x) & 0x0f)
+# define ATMCI_GET_WP_VSRC(x)		(((x) >> 8) & 0xffff)
+#define ATMCI_VERSION			0x00FC  /* Version */
+#define ATMCI_FIFO_APERTURE		0x0200	/* FIFO Aperture[2] */
 
 /* This is not including the FIFO Aperture on MCI2 */
-#define MCI_REGS_SIZE		0x100
+#define ATMCI_REGS_SIZE		0x100
 
 /* Register access macros */
-#define mci_readl(port,reg)				\
-	__raw_readl((port)->regs + MCI_##reg)
-#define mci_writel(port,reg,value)			\
-	__raw_writel((value), (port)->regs + MCI_##reg)
+#define atmci_readl(port,reg)				\
+	__raw_readl((port)->regs + reg)
+#define atmci_writel(port,reg,value)			\
+	__raw_writel((value), (port)->regs + reg)
 
 #endif /* __DRIVERS_MMC_ATMEL_MCI_H__ */
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/au1xmmc.c linux-libre-3.2-gnu/drivers/mmc/host/au1xmmc.c
--- linux-libre-3.1-gnu/drivers/mmc/host/au1xmmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/au1xmmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -55,7 +55,7 @@
 
 #ifdef DEBUG
 #define DBG(fmt, idx, args...)	\
-	printk(KERN_DEBUG "au1xmmc(%d): DEBUG: " fmt, idx, ##args)
+	pr_debug("au1xmmc(%d): DEBUG: " fmt, idx, ##args)
 #else
 #define DBG(fmt, idx, args...) do {} while (0)
 #endif
@@ -64,11 +64,8 @@
 #define AU1XMMC_DESCRIPTOR_COUNT 1
 
 /* max DMA seg size: 64KB on Au1100, 4MB on Au1200 */
-#ifdef CONFIG_SOC_AU1100
-#define AU1XMMC_DESCRIPTOR_SIZE 0x0000ffff
-#else	/* Au1200 */
-#define AU1XMMC_DESCRIPTOR_SIZE 0x003fffff
-#endif
+#define AU1100_MMC_DESCRIPTOR_SIZE 0x0000ffff
+#define AU1200_MMC_DESCRIPTOR_SIZE 0x003fffff
 
 #define AU1XMMC_OCR (MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 | \
 		     MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33 | \
@@ -127,6 +124,7 @@
 #define HOST_F_XMIT	0x0001
 #define HOST_F_RECV	0x0002
 #define HOST_F_DMA	0x0010
+#define HOST_F_DBDMA	0x0020
 #define HOST_F_ACTIVE	0x0100
 #define HOST_F_STOP	0x1000
 
@@ -151,6 +149,16 @@
 #define DMA_CHANNEL(h)	\
 	(((h)->flags & HOST_F_XMIT) ? (h)->tx_chan : (h)->rx_chan)
 
+static inline int has_dbdma(void)
+{
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1200:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
 static inline void IRQ_ON(struct au1xmmc_host *host, u32 mask)
 {
 	u32 val = au_readl(HOST_CONFIG(host));
@@ -268,7 +276,7 @@
 		mmccmd |= SD_CMD_RT_3;
 		break;
 	default:
-		printk(KERN_INFO "au1xmmc: unhandled response type %02x\n",
+		pr_info("au1xmmc: unhandled response type %02x\n",
 			mmc_resp_type(cmd));
 		return -EINVAL;
 	}
@@ -353,14 +361,12 @@
 	data->bytes_xfered = 0;
 
 	if (!data->error) {
-		if (host->flags & HOST_F_DMA) {
-#ifdef CONFIG_SOC_AU1200	/* DBDMA */
+		if (host->flags & (HOST_F_DMA | HOST_F_DBDMA)) {
 			u32 chan = DMA_CHANNEL(host);
 
 			chan_tab_t *c = *((chan_tab_t **)chan);
 			au1x_dma_chan_t *cp = c->chan_ptr;
 			data->bytes_xfered = cp->ddma_bytecnt;
-#endif
 		} else
 			data->bytes_xfered =
 				(data->blocks * data->blksz) - host->pio.len;
@@ -570,11 +576,10 @@
 
 	host->status = HOST_S_DATA;
 
-	if (host->flags & HOST_F_DMA) {
-#ifdef CONFIG_SOC_AU1200	/* DBDMA */
+	if ((host->flags & (HOST_F_DMA | HOST_F_DBDMA))) {
 		u32 channel = DMA_CHANNEL(host);
 
-		/* Start the DMA as soon as the buffer gets something in it */
+		/* Start the DBDMA as soon as the buffer gets something in it */
 
 		if (host->flags & HOST_F_RECV) {
 			u32 mask = SD_STATUS_DB | SD_STATUS_NE;
@@ -584,7 +589,6 @@
 		}
 
 		au1xxx_dbdma_start(channel);
-#endif
 	}
 }
 
@@ -633,8 +637,7 @@
 
 	au_writel(data->blksz - 1, HOST_BLKSIZE(host));
 
-	if (host->flags & HOST_F_DMA) {
-#ifdef CONFIG_SOC_AU1200	/* DBDMA */
+	if (host->flags & (HOST_F_DMA | HOST_F_DBDMA)) {
 		int i;
 		u32 channel = DMA_CHANNEL(host);
 
@@ -663,7 +666,6 @@
 
 			datalen -= len;
 		}
-#endif
 	} else {
 		host->pio.index = 0;
 		host->pio.offset = 0;
@@ -838,7 +840,6 @@
 	return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_SOC_AU1200
 /* 8bit memory DMA device */
 static dbdev_tab_t au1xmmc_mem_dbdev = {
 	.dev_id		= DSCR_CMD0_ALWAYS,
@@ -905,7 +906,7 @@
 	au1xxx_dbdma_ring_alloc(host->rx_chan, AU1XMMC_DESCRIPTOR_COUNT);
 
 	/* DBDMA is good to go */
-	host->flags |= HOST_F_DMA;
+	host->flags |= HOST_F_DMA | HOST_F_DBDMA;
 
 	return 0;
 }
@@ -918,7 +919,6 @@
 		au1xxx_dbdma_chan_free(host->rx_chan);
 	}
 }
-#endif
 
 static void au1xmmc_enable_sdio_irq(struct mmc_host *mmc, int en)
 {
@@ -997,8 +997,16 @@
 	mmc->f_min =   450000;
 	mmc->f_max = 24000000;
 
-	mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE;
-	mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT;
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1100:
+		mmc->max_seg_size = AU1100_MMC_DESCRIPTOR_SIZE;
+		mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT;
+		break;
+	case ALCHEMY_CPU_AU1200:
+		mmc->max_seg_size = AU1200_MMC_DESCRIPTOR_SIZE;
+		mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT;
+		break;
+	}
 
 	mmc->max_blk_size = 2048;
 	mmc->max_blk_count = 512;
@@ -1028,11 +1036,11 @@
 	tasklet_init(&host->finish_task, au1xmmc_tasklet_finish,
 			(unsigned long)host);
 
-#ifdef CONFIG_SOC_AU1200
-	ret = au1xmmc_dbdma_init(host);
-	if (ret)
-		printk(KERN_INFO DRIVER_NAME ": DBDMA init failed; using PIO\n");
-#endif
+	if (has_dbdma()) {
+		ret = au1xmmc_dbdma_init(host);
+		if (ret)
+			pr_info(DRIVER_NAME ": DBDMA init failed; using PIO\n");
+	}
 
 #ifdef CONFIG_LEDS_CLASS
 	if (host->platdata && host->platdata->led) {
@@ -1056,7 +1064,7 @@
 
 	platform_set_drvdata(pdev, host);
 
-	printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X"
+	pr_info(DRIVER_NAME ": MMC Controller %d set up at %8.8X"
 		" (mode=%s)\n", pdev->id, host->iobase,
 		host->flags & HOST_F_DMA ? "dma" : "pio");
 
@@ -1073,9 +1081,8 @@
 	au_writel(0, HOST_CONFIG2(host));
 	au_sync();
 
-#ifdef CONFIG_SOC_AU1200
-	au1xmmc_dbdma_shutdown(host);
-#endif
+	if (host->flags & HOST_F_DBDMA)
+		au1xmmc_dbdma_shutdown(host);
 
 	tasklet_kill(&host->data_task);
 	tasklet_kill(&host->finish_task);
@@ -1120,9 +1127,9 @@
 		tasklet_kill(&host->data_task);
 		tasklet_kill(&host->finish_task);
 
-#ifdef CONFIG_SOC_AU1200
-		au1xmmc_dbdma_shutdown(host);
-#endif
+		if (host->flags & HOST_F_DBDMA)
+			au1xmmc_dbdma_shutdown(host);
+
 		au1xmmc_set_power(host, 0);
 
 		free_irq(host->irq, host);
@@ -1181,24 +1188,23 @@
 
 static int __init au1xmmc_init(void)
 {
-#ifdef CONFIG_SOC_AU1200
-	/* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride
-	 * of 8 bits.  And since devices are shared, we need to create
-	 * our own to avoid freaking out other devices.
-	 */
-	memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev);
-	if (!memid)
-		printk(KERN_ERR "au1xmmc: cannot add memory dbdma dev\n");
-#endif
+	if (has_dbdma()) {
+		/* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride
+		* of 8 bits.  And since devices are shared, we need to create
+		* our own to avoid freaking out other devices.
+		*/
+		memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev);
+		if (!memid)
+			pr_err("au1xmmc: cannot add memory dbdma\n");
+	}
 	return platform_driver_register(&au1xmmc_driver);
 }
 
 static void __exit au1xmmc_exit(void)
 {
-#ifdef CONFIG_SOC_AU1200
-	if (memid)
+	if (has_dbdma() && memid)
 		au1xxx_ddma_del_device(memid);
-#endif
+
 	platform_driver_unregister(&au1xmmc_driver);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/davinci_mmc.c linux-libre-3.2-gnu/drivers/mmc/host/davinci_mmc.c
--- linux-libre-3.1-gnu/drivers/mmc/host/davinci_mmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/davinci_mmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -807,12 +807,25 @@
 static void mmc_davinci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct mmc_davinci_host *host = mmc_priv(mmc);
+	struct platform_device *pdev = to_platform_device(mmc->parent);
+	struct davinci_mmc_config *config = pdev->dev.platform_data;
 
 	dev_dbg(mmc_dev(host->mmc),
 		"clock %dHz busmode %d powermode %d Vdd %04x\n",
 		ios->clock, ios->bus_mode, ios->power_mode,
 		ios->vdd);
 
+	switch (ios->power_mode) {
+	case MMC_POWER_OFF:
+		if (config && config->set_power)
+			config->set_power(pdev->id, false);
+		break;
+	case MMC_POWER_UP:
+		if (config && config->set_power)
+			config->set_power(pdev->id, true);
+		break;
+	}
+
 	switch (ios->bus_width) {
 	case MMC_BUS_WIDTH_8:
 		dev_dbg(mmc_dev(host->mmc), "Enabling 8 bit mode\n");
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/dw_mmc.c linux-libre-3.2-gnu/drivers/mmc/host/dw_mmc.c
--- linux-libre-3.1-gnu/drivers/mmc/host/dw_mmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/dw_mmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -764,11 +764,29 @@
 	return present;
 }
 
+static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
+{
+	struct dw_mci_slot *slot = mmc_priv(mmc);
+	struct dw_mci *host = slot->host;
+	u32 int_mask;
+
+	/* Enable/disable Slot Specific SDIO interrupt */
+	int_mask = mci_readl(host, INTMASK);
+	if (enb) {
+		mci_writel(host, INTMASK,
+			   (int_mask | (1 << SDMMC_INT_SDIO(slot->id))));
+	} else {
+		mci_writel(host, INTMASK,
+			   (int_mask & ~(1 << SDMMC_INT_SDIO(slot->id))));
+	}
+}
+
 static const struct mmc_host_ops dw_mci_ops = {
-	.request	= dw_mci_request,
-	.set_ios	= dw_mci_set_ios,
-	.get_ro		= dw_mci_get_ro,
-	.get_cd		= dw_mci_get_cd,
+	.request		= dw_mci_request,
+	.set_ios		= dw_mci_set_ios,
+	.get_ro			= dw_mci_get_ro,
+	.get_cd			= dw_mci_get_cd,
+	.enable_sdio_irq	= dw_mci_enable_sdio_irq,
 };
 
 static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
@@ -1025,7 +1043,8 @@
 		buf += len;
 		cnt -= len;
 		if (!sg_next(host->sg) || host->part_buf_count == 2) {
-			mci_writew(host, DATA, host->part_buf16);
+			mci_writew(host, DATA(host->data_offset),
+					host->part_buf16);
 			host->part_buf_count = 0;
 		}
 	}
@@ -1042,21 +1061,23 @@
 			cnt -= len;
 			/* push data from aligned buffer into fifo */
 			for (i = 0; i < items; ++i)
-				mci_writew(host, DATA, aligned_buf[i]);
+				mci_writew(host, DATA(host->data_offset),
+						aligned_buf[i]);
 		}
 	} else
 #endif
 	{
 		u16 *pdata = buf;
 		for (; cnt >= 2; cnt -= 2)
-			mci_writew(host, DATA, *pdata++);
+			mci_writew(host, DATA(host->data_offset), *pdata++);
 		buf = pdata;
 	}
 	/* put anything remaining in the part_buf */
 	if (cnt) {
 		dw_mci_set_part_bytes(host, buf, cnt);
 		if (!sg_next(host->sg))
-			mci_writew(host, DATA, host->part_buf16);
+			mci_writew(host, DATA(host->data_offset),
+					host->part_buf16);
 	}
 }
 
@@ -1071,7 +1092,8 @@
 			int items = len >> 1;
 			int i;
 			for (i = 0; i < items; ++i)
-				aligned_buf[i] = mci_readw(host, DATA);
+				aligned_buf[i] = mci_readw(host,
+						DATA(host->data_offset));
 			/* memcpy from aligned buffer into output buffer */
 			memcpy(buf, aligned_buf, len);
 			buf += len;
@@ -1082,11 +1104,11 @@
 	{
 		u16 *pdata = buf;
 		for (; cnt >= 2; cnt -= 2)
-			*pdata++ = mci_readw(host, DATA);
+			*pdata++ = mci_readw(host, DATA(host->data_offset));
 		buf = pdata;
 	}
 	if (cnt) {
-		host->part_buf16 = mci_readw(host, DATA);
+		host->part_buf16 = mci_readw(host, DATA(host->data_offset));
 		dw_mci_pull_final_bytes(host, buf, cnt);
 	}
 }
@@ -1099,7 +1121,8 @@
 		buf += len;
 		cnt -= len;
 		if (!sg_next(host->sg) || host->part_buf_count == 4) {
-			mci_writel(host, DATA, host->part_buf32);
+			mci_writel(host, DATA(host->data_offset),
+					host->part_buf32);
 			host->part_buf_count = 0;
 		}
 	}
@@ -1116,21 +1139,23 @@
 			cnt -= len;
 			/* push data from aligned buffer into fifo */
 			for (i = 0; i < items; ++i)
-				mci_writel(host, DATA, aligned_buf[i]);
+				mci_writel(host, DATA(host->data_offset),
+						aligned_buf[i]);
 		}
 	} else
 #endif
 	{
 		u32 *pdata = buf;
 		for (; cnt >= 4; cnt -= 4)
-			mci_writel(host, DATA, *pdata++);
+			mci_writel(host, DATA(host->data_offset), *pdata++);
 		buf = pdata;
 	}
 	/* put anything remaining in the part_buf */
 	if (cnt) {
 		dw_mci_set_part_bytes(host, buf, cnt);
 		if (!sg_next(host->sg))
-			mci_writel(host, DATA, host->part_buf32);
+			mci_writel(host, DATA(host->data_offset),
+						host->part_buf32);
 	}
 }
 
@@ -1145,7 +1170,8 @@
 			int items = len >> 2;
 			int i;
 			for (i = 0; i < items; ++i)
-				aligned_buf[i] = mci_readl(host, DATA);
+				aligned_buf[i] = mci_readl(host,
+						DATA(host->data_offset));
 			/* memcpy from aligned buffer into output buffer */
 			memcpy(buf, aligned_buf, len);
 			buf += len;
@@ -1156,11 +1182,11 @@
 	{
 		u32 *pdata = buf;
 		for (; cnt >= 4; cnt -= 4)
-			*pdata++ = mci_readl(host, DATA);
+			*pdata++ = mci_readl(host, DATA(host->data_offset));
 		buf = pdata;
 	}
 	if (cnt) {
-		host->part_buf32 = mci_readl(host, DATA);
+		host->part_buf32 = mci_readl(host, DATA(host->data_offset));
 		dw_mci_pull_final_bytes(host, buf, cnt);
 	}
 }
@@ -1173,7 +1199,8 @@
 		buf += len;
 		cnt -= len;
 		if (!sg_next(host->sg) || host->part_buf_count == 8) {
-			mci_writew(host, DATA, host->part_buf);
+			mci_writew(host, DATA(host->data_offset),
+					host->part_buf);
 			host->part_buf_count = 0;
 		}
 	}
@@ -1190,21 +1217,23 @@
 			cnt -= len;
 			/* push data from aligned buffer into fifo */
 			for (i = 0; i < items; ++i)
-				mci_writeq(host, DATA, aligned_buf[i]);
+				mci_writeq(host, DATA(host->data_offset),
+						aligned_buf[i]);
 		}
 	} else
 #endif
 	{
 		u64 *pdata = buf;
 		for (; cnt >= 8; cnt -= 8)
-			mci_writeq(host, DATA, *pdata++);
+			mci_writeq(host, DATA(host->data_offset), *pdata++);
 		buf = pdata;
 	}
 	/* put anything remaining in the part_buf */
 	if (cnt) {
 		dw_mci_set_part_bytes(host, buf, cnt);
 		if (!sg_next(host->sg))
-			mci_writeq(host, DATA, host->part_buf);
+			mci_writeq(host, DATA(host->data_offset),
+					host->part_buf);
 	}
 }
 
@@ -1219,7 +1248,8 @@
 			int items = len >> 3;
 			int i;
 			for (i = 0; i < items; ++i)
-				aligned_buf[i] = mci_readq(host, DATA);
+				aligned_buf[i] = mci_readq(host,
+						DATA(host->data_offset));
 			/* memcpy from aligned buffer into output buffer */
 			memcpy(buf, aligned_buf, len);
 			buf += len;
@@ -1230,11 +1260,11 @@
 	{
 		u64 *pdata = buf;
 		for (; cnt >= 8; cnt -= 8)
-			*pdata++ = mci_readq(host, DATA);
+			*pdata++ = mci_readq(host, DATA(host->data_offset));
 		buf = pdata;
 	}
 	if (cnt) {
-		host->part_buf = mci_readq(host, DATA);
+		host->part_buf = mci_readq(host, DATA(host->data_offset));
 		dw_mci_pull_final_bytes(host, buf, cnt);
 	}
 }
@@ -1406,6 +1436,7 @@
 	struct dw_mci *host = dev_id;
 	u32 status, pending;
 	unsigned int pass_count = 0;
+	int i;
 
 	do {
 		status = mci_readl(host, RINTSTS);
@@ -1477,6 +1508,15 @@
 			queue_work(dw_mci_card_workqueue, &host->card_work);
 		}
 
+		/* Handle SDIO Interrupts */
+		for (i = 0; i < host->num_slots; i++) {
+			struct dw_mci_slot *slot = host->slot[i];
+			if (pending & SDMMC_INT_SDIO(i)) {
+				mci_writel(host, RINTSTS, SDMMC_INT_SDIO(i));
+				mmc_signal_sdio_irq(slot->mmc);
+			}
+		}
+
 	} while (pass_count++ < 5);
 
 #ifdef CONFIG_MMC_DW_IDMAC
@@ -1673,7 +1713,7 @@
 
 	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));
+		pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
 		host->vmmc = NULL;
 	} else
 		regulator_enable(host->vmmc);
@@ -1924,6 +1964,18 @@
 	}
 
 	/*
+	 * In 2.40a spec, Data offset is changed.
+	 * Need to check the version-id and set data-offset for DATA register.
+	 */
+	host->verid = SDMMC_GET_VERID(mci_readl(host, VERID));
+	dev_info(&pdev->dev, "Version ID is %04x\n", host->verid);
+
+	if (host->verid < DW_MMC_240A)
+		host->data_offset = DATA_OFFSET;
+	else
+		host->data_offset = DATA_240A_OFFSET;
+
+	/*
 	 * Enable interrupts for command done, data over, data empty, card det,
 	 * receive ready and error such as transmit, receive timeout, crc error
 	 */
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/dw_mmc.h linux-libre-3.2-gnu/drivers/mmc/host/dw_mmc.h
--- linux-libre-3.1-gnu/drivers/mmc/host/dw_mmc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/dw_mmc.h	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,8 @@
 #ifndef _DW_MMC_H_
 #define _DW_MMC_H_
 
+#define DW_MMC_240A		0x240a
+
 #define SDMMC_CTRL		0x000
 #define SDMMC_PWREN		0x004
 #define SDMMC_CLKDIV		0x008
@@ -51,7 +53,14 @@
 #define SDMMC_IDINTEN		0x090
 #define SDMMC_DSCADDR		0x094
 #define SDMMC_BUFADDR		0x098
-#define SDMMC_DATA		0x100
+#define SDMMC_DATA(x)		(x)
+
+/*
+ * Data offset is difference according to Version
+ * Lower than 2.40a : data register offest is 0x100
+ */
+#define DATA_OFFSET		0x100
+#define DATA_240A_OFFSET	0x200
 
 /* shift bit field */
 #define _SBF(f, v)		((v) << (f))
@@ -82,7 +91,7 @@
 #define SDMMC_CTYPE_4BIT		BIT(0)
 #define SDMMC_CTYPE_1BIT		0
 /* Interrupt status & mask register defines */
-#define SDMMC_INT_SDIO			BIT(16)
+#define SDMMC_INT_SDIO(n)		BIT(16 + (n))
 #define SDMMC_INT_EBE			BIT(15)
 #define SDMMC_INT_ACD			BIT(14)
 #define SDMMC_INT_SBE			BIT(13)
@@ -130,6 +139,8 @@
 #define SDMMC_IDMAC_ENABLE		BIT(7)
 #define SDMMC_IDMAC_FB			BIT(1)
 #define SDMMC_IDMAC_SWRESET		BIT(0)
+/* Version ID register define */
+#define SDMMC_GET_VERID(x)		((x) & 0xFFFF)
 
 /* Register access macros */
 #define mci_readl(dev, reg)			\
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/imxmmc.c linux-libre-3.2-gnu/drivers/mmc/host/imxmmc.c
--- linux-libre-3.1-gnu/drivers/mmc/host/imxmmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/imxmmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -942,7 +942,7 @@
 	int ret = 0, irq;
 	u16 rev_no;
 
-	printk(KERN_INFO "i.MX mmc driver\n");
+	pr_info("i.MX mmc driver\n");
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq = platform_get_irq(pdev, 0);
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/Kconfig linux-libre-3.2-gnu/drivers/mmc/host/Kconfig
--- linux-libre-3.1-gnu/drivers/mmc/host/Kconfig	2012-03-19 22:03:14.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/Kconfig	2012-03-19 22:06:24.000000000 -0400
@@ -130,13 +130,13 @@
 	  If unsure, say N.
 
 config MMC_SDHCI_ESDHC_IMX
-	tristate "SDHCI platform support for the Freescale eSDHC i.MX controller"
-	depends on ARCH_MX25 || ARCH_MX35 || ARCH_MX5
+	tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller"
+	depends on ARCH_MXC
 	depends on MMC_SDHCI_PLTFM
 	select MMC_SDHCI_IO_ACCESSORS
 	help
-	  This selects the Freescale eSDHC controller support on the platform
-	  bus, found on platforms like mx35/51.
+	  This selects the Freescale eSDHC/uSDHC controller support
+	  found on i.MX25, i.MX35 i.MX5x and i.MX6x.
 
 	  If you have a controller with this interface, say Y or M here.
 
@@ -263,7 +263,7 @@
 
 config MMC_AU1X
 	tristate "Alchemy AU1XX0 MMC Card Interface support"
-	depends on SOC_AU1200
+	depends on MIPS_ALCHEMY
 	help
 	  This selects the AMD Alchemy(R) Multimedia card interface.
 	  If you have a Alchemy platform with a MMC slot, say Y or M here.
@@ -326,11 +326,11 @@
 	  support for SDIO devices.
 
 config MMC_MXC
-	tristate "Freescale i.MX2/3 Multimedia Card Interface support"
-	depends on MACH_MX21 || MACH_MX27 || ARCH_MX31
+	tristate "Freescale i.MX21/27/31 Multimedia Card Interface support"
+	depends on ARCH_MXC
 	help
-	  This selects the Freescale i.MX2/3 Multimedia card Interface.
-	  If you have a i.MX platform with a Multimedia Card slot,
+	  This selects the Freescale i.MX21, i.MX27 and i.MX31 Multimedia card
+	  Interface. If you have a i.MX platform with a Multimedia Card slot,
 	  say Y or M here.
 
 	  If unsure, say N.
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/mmci.c linux-libre-3.2-gnu/drivers/mmc/host/mmci.c
--- linux-libre-3.1-gnu/drivers/mmc/host/mmci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/mmci.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/amba/mmci.h>
+#include <linux/pm_runtime.h>
 
 #include <asm/div64.h>
 #include <asm/io.h>
@@ -170,6 +171,7 @@
 	 * back into the driver...
 	 */
 	spin_unlock(&host->lock);
+	pm_runtime_put(mmc_dev(host->mmc));
 	mmc_request_done(host->mmc, mrq);
 	spin_lock(&host->lock);
 }
@@ -464,7 +466,7 @@
 	struct mmci_host_next *next = &host->next_data;
 
 	if (data->host_cookie && data->host_cookie != next->cookie) {
-		printk(KERN_WARNING "[%s] invalid cookie: data->host_cookie %d"
+		pr_warning("[%s] invalid cookie: data->host_cookie %d"
 		       " host->next_data.cookie %d\n",
 		       __func__, data->host_cookie, host->next_data.cookie);
 		data->host_cookie = 0;
@@ -529,7 +531,7 @@
 	if (chan) {
 		if (err)
 			dmaengine_terminate_all(chan);
-		if (err || data->host_cookie)
+		if (data->host_cookie)
 			dma_unmap_sg(mmc_dev(host->mmc), data->sg,
 				     data->sg_len, dir);
 		mrq->data->host_cookie = 0;
@@ -673,7 +675,8 @@
 	      unsigned int status)
 {
 	/* First check for errors */
-	if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
+	if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR|
+		      MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
 		u32 remain, success;
 
 		/* Terminate the DMA transfer */
@@ -752,8 +755,12 @@
 	}
 
 	if (!cmd->data || cmd->error) {
-		if (host->data)
+		if (host->data) {
+			/* Terminate the DMA transfer */
+			if (dma_inprogress(host))
+				mmci_dma_data_error(host);
 			mmci_stop_data(host);
+		}
 		mmci_request_end(host, cmd->mrq);
 	} else if (!(cmd->data->flags & MMC_DATA_READ)) {
 		mmci_start_data(host, cmd->data);
@@ -953,8 +960,9 @@
 		dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);
 
 		data = host->data;
-		if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|
-			      MCI_RXOVERRUN|MCI_DATAEND|MCI_DATABLOCKEND) && data)
+		if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR|
+			      MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_DATAEND|
+			      MCI_DATABLOCKEND) && data)
 			mmci_data_irq(host, data, status);
 
 		cmd = host->cmd;
@@ -984,6 +992,8 @@
 		return;
 	}
 
+	pm_runtime_get_sync(mmc_dev(mmc));
+
 	spin_lock_irqsave(&host->lock, flags);
 
 	host->mrq = mrq;
@@ -1156,10 +1166,14 @@
 		goto host_free;
 	}
 
-	ret = clk_enable(host->clk);
+	ret = clk_prepare(host->clk);
 	if (ret)
 		goto clk_free;
 
+	ret = clk_enable(host->clk);
+	if (ret)
+		goto clk_unprep;
+
 	host->plat = plat;
 	host->variant = variant;
 	host->mclk = clk_get_rate(host->clk);
@@ -1327,6 +1341,8 @@
 
 	mmci_dma_setup(host);
 
+	pm_runtime_put(&dev->dev);
+
 	mmc_add_host(mmc);
 
 	return 0;
@@ -1345,6 +1361,8 @@
 	iounmap(host->base);
  clk_disable:
 	clk_disable(host->clk);
+ clk_unprep:
+	clk_unprepare(host->clk);
  clk_free:
 	clk_put(host->clk);
  host_free:
@@ -1364,6 +1382,12 @@
 	if (mmc) {
 		struct mmci_host *host = mmc_priv(mmc);
 
+		/*
+		 * Undo pm_runtime_put() in probe.  We use the _sync
+		 * version here so that we can access the primecell.
+		 */
+		pm_runtime_get_sync(&dev->dev);
+
 		mmc_remove_host(mmc);
 
 		writel(0, host->base + MMCIMASK0);
@@ -1386,6 +1410,7 @@
 
 		iounmap(host->base);
 		clk_disable(host->clk);
+		clk_unprepare(host->clk);
 		clk_put(host->clk);
 
 		if (host->vcc)
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/mmc_spi.c linux-libre-3.2-gnu/drivers/mmc/host/mmc_spi.c
--- linux-libre-3.1-gnu/drivers/mmc/host/mmc_spi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/mmc_spi.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <linux/bio.h>
 #include <linux/dma-mapping.h>
 #include <linux/crc7.h>
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/msm_sdcc.c linux-libre-3.2-gnu/drivers/mmc/host/msm_sdcc.c
--- linux-libre-3.1-gnu/drivers/mmc/host/msm_sdcc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/msm_sdcc.c	2012-01-04 18:55:44.000000000 -0500
@@ -213,7 +213,8 @@
 	msmsdcc_writel(host, host->cmd_timeout, MMCIDATATIMER);
 	msmsdcc_writel(host, (unsigned int)host->curr.xfer_size,
 		       MMCIDATALENGTH);
-	msmsdcc_writel(host, host->cmd_pio_irqmask, MMCIMASK1);
+	msmsdcc_writel(host, (msmsdcc_readl(host, MMCIMASK0) &
+			(~MCI_IRQ_PIO)) | host->cmd_pio_irqmask, MMCIMASK0);
 	msmsdcc_writel(host, host->cmd_datactrl, MMCIDATACTRL);
 
 	if (host->cmd_cmd) {
@@ -388,7 +389,7 @@
 	n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
 			host->dma.num_ents, host->dma.dir);
 	if (n == 0) {
-		printk(KERN_ERR "%s: Unable to map in all sg elements\n",
+		pr_err("%s: Unable to map in all sg elements\n",
 			mmc_hostname(host->mmc));
 		host->dma.sg = NULL;
 		host->dma.num_ents = 0;
@@ -474,7 +475,7 @@
 		*c |= MCI_CSPM_MCIABORT;
 
 	if (host->curr.cmd != NULL) {
-		printk(KERN_ERR "%s: Overlapping command requests\n",
+		pr_err("%s: Overlapping command requests\n",
 			mmc_hostname(host->mmc));
 	}
 	host->curr.cmd = cmd;
@@ -543,7 +544,9 @@
 
 		msmsdcc_writel(host, host->curr.xfer_size, MMCIDATALENGTH);
 
-		msmsdcc_writel(host, pio_irqmask, MMCIMASK1);
+		msmsdcc_writel(host, (msmsdcc_readl(host, MMCIMASK0) &
+				(~MCI_IRQ_PIO)) | pio_irqmask, MMCIMASK0);
+
 		msmsdcc_writel(host, datactrl, MMCIDATACTRL);
 
 		if (cmd) {
@@ -659,8 +662,13 @@
 {
 	struct msmsdcc_host	*host = dev_id;
 	uint32_t		status;
+	u32 mci_mask0;
 
 	status = msmsdcc_readl(host, MMCISTATUS);
+	mci_mask0 = msmsdcc_readl(host, MMCIMASK0);
+
+	if (((mci_mask0 & status) & MCI_IRQ_PIO) == 0)
+		return IRQ_NONE;
 
 	do {
 		unsigned long flags;
@@ -719,10 +727,12 @@
 	} while (1);
 
 	if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE)
-		msmsdcc_writel(host, MCI_RXDATAAVLBLMASK, MMCIMASK1);
+		msmsdcc_writel(host, (mci_mask0 & (~MCI_IRQ_PIO)) |
+					MCI_RXDATAAVLBLMASK, MMCIMASK0);
 
 	if (!host->curr.xfer_remain)
-		msmsdcc_writel(host, 0, MMCIMASK1);
+		msmsdcc_writel(host, (mci_mask0 & (~MCI_IRQ_PIO)) | 0,
+					MMCIMASK0);
 
 	return IRQ_HANDLED;
 }
@@ -854,6 +864,8 @@
 	do {
 		status = msmsdcc_readl(host, MMCISTATUS);
 		status &= msmsdcc_readl(host, MMCIMASK0);
+		if ((status & (~MCI_IRQ_PIO)) == 0)
+			break;
 		msmsdcc_writel(host, status, MMCICLEAR);
 
 		if (status & MCI_SDIOINTR)
@@ -939,7 +951,7 @@
 	struct msm_mmc_gpio_data *curr;
 	int i, rc = 0;
 
-	if (!host->plat->gpio_data && host->gpio_config_status == enable)
+	if (!host->plat->gpio_data || host->gpio_config_status == enable)
 		return;
 
 	curr = host->plat->gpio_data;
@@ -1052,10 +1064,19 @@
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
+static void msmsdcc_init_card(struct mmc_host *mmc, struct mmc_card *card)
+{
+	struct msmsdcc_host *host = mmc_priv(mmc);
+
+	if (host->plat->init_card)
+		host->plat->init_card(card);
+}
+
 static const struct mmc_host_ops msmsdcc_ops = {
 	.request	= msmsdcc_request,
 	.set_ios	= msmsdcc_set_ios,
 	.enable_sdio_irq = msmsdcc_enable_sdio_irq,
+	.init_card	= msmsdcc_init_card,
 };
 
 static void
@@ -1092,7 +1113,7 @@
 {
 	struct msmsdcc_host *host = dev_id;
 
-	printk(KERN_DEBUG "%s: %d\n", __func__, irq);
+	pr_debug("%s: %d\n", __func__, irq);
 	msmsdcc_check_status((unsigned long) host);
 	return IRQ_HANDLED;
 }
@@ -1102,7 +1123,7 @@
 {
 	struct msmsdcc_host *host = dev_id;
 
-	printk(KERN_DEBUG "%s: card_present %d\n", mmc_hostname(host->mmc),
+	pr_debug("%s: card_present %d\n", mmc_hostname(host->mmc),
 	       card_present);
 	msmsdcc_check_status((unsigned long) host);
 }
@@ -1150,7 +1171,6 @@
 	struct msmsdcc_host *host;
 	struct mmc_host *mmc;
 	struct resource *cmd_irqres = NULL;
-	struct resource *pio_irqres = NULL;
 	struct resource *stat_irqres = NULL;
 	struct resource *memres = NULL;
 	struct resource *dmares = NULL;
@@ -1175,12 +1195,10 @@
 	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
 	cmd_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
 						  "cmd_irq");
-	pio_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-						  "pio_irq");
 	stat_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
 						   "status_irq");
 
-	if (!cmd_irqres || !pio_irqres || !memres) {
+	if (!cmd_irqres || !memres) {
 		pr_err("%s: Invalid resource\n", __func__);
 		return -ENXIO;
 	}
@@ -1200,17 +1218,20 @@
 	host->plat = plat;
 	host->mmc = mmc;
 	host->curr.cmd = NULL;
+	init_timer(&host->busclk_timer);
+	host->busclk_timer.data = (unsigned long) host;
+	host->busclk_timer.function = msmsdcc_busclk_expired;
+
 
 	host->cmdpoll = 1;
 
 	host->base = ioremap(memres->start, PAGE_SIZE);
 	if (!host->base) {
 		ret = -ENOMEM;
-		goto out;
+		goto host_free;
 	}
 
 	host->cmd_irqres = cmd_irqres;
-	host->pio_irqres = pio_irqres;
 	host->memres = memres;
 	host->dmares = dmares;
 	spin_lock_init(&host->lock);
@@ -1221,13 +1242,19 @@
 	/*
 	 * Setup DMA
 	 */
-	msmsdcc_init_dma(host);
+	if (host->dmares) {
+		ret = msmsdcc_init_dma(host);
+		if (ret)
+			goto ioremap_free;
+	} else {
+		host->dma.channel = -1;
+	}
 
 	/* Get our clocks */
 	host->pclk = clk_get(&pdev->dev, "sdc_pclk");
 	if (IS_ERR(host->pclk)) {
 		ret = PTR_ERR(host->pclk);
-		goto host_free;
+		goto dma_free;
 	}
 
 	host->clk = clk_get(&pdev->dev, "sdc_clk");
@@ -1236,17 +1263,17 @@
 		goto pclk_put;
 	}
 
-	/* Enable clocks */
-	ret = msmsdcc_enable_clocks(host);
-	if (ret)
-		goto clk_put;
-
 	ret = clk_set_rate(host->clk, msmsdcc_fmin);
 	if (ret) {
 		pr_err("%s: Clock rate set failed (%d)\n", __func__, ret);
-		goto clk_disable;
+		goto clk_put;
 	}
 
+	/* Enable clocks */
+	ret = msmsdcc_enable_clocks(host);
+	if (ret)
+		goto clk_put;
+
 	host->pclk_rate = clk_get_rate(host->pclk);
 	host->clk_rate = clk_get_rate(host->clk);
 
@@ -1316,16 +1343,12 @@
 		host->eject = !host->oldstat;
 	}
 
-	init_timer(&host->busclk_timer);
-	host->busclk_timer.data = (unsigned long) host;
-	host->busclk_timer.function = msmsdcc_busclk_expired;
-
 	ret = request_irq(cmd_irqres->start, msmsdcc_irq, IRQF_SHARED,
 			  DRIVER_NAME " (cmd)", host);
 	if (ret)
 		goto stat_irq_free;
 
-	ret = request_irq(pio_irqres->start, msmsdcc_pio_irq, IRQF_SHARED,
+	ret = request_irq(cmd_irqres->start, msmsdcc_pio_irq, IRQF_SHARED,
 			  DRIVER_NAME " (pio)", host);
 	if (ret)
 		goto cmd_irq_free;
@@ -1368,6 +1391,13 @@
 	clk_put(host->clk);
  pclk_put:
 	clk_put(host->pclk);
+dma_free:
+	if (host->dmares)
+		dma_free_coherent(NULL, sizeof(struct msmsdcc_nc_dmadata),
+					host->dma.nc, host->dma.nc_busaddr);
+ioremap_free:
+	tasklet_kill(&host->dma_tlet);
+	iounmap(host->base);
  host_free:
 	mmc_free_host(mmc);
  out:
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/msm_sdcc.h linux-libre-3.2-gnu/drivers/mmc/host/msm_sdcc.h
--- linux-libre-3.1-gnu/drivers/mmc/host/msm_sdcc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/msm_sdcc.h	2012-01-04 18:55:44.000000000 -0500
@@ -140,6 +140,11 @@
 	MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK|	\
 	MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATAENDMASK|MCI_PROGDONEMASK)
 
+#define MCI_IRQ_PIO \
+	(MCI_RXDATAAVLBLMASK | MCI_TXDATAAVLBLMASK | MCI_RXFIFOEMPTYMASK | \
+	 MCI_TXFIFOEMPTYMASK | MCI_RXFIFOFULLMASK | MCI_TXFIFOFULLMASK | \
+	 MCI_RXFIFOHALFFULLMASK | MCI_TXFIFOHALFEMPTYMASK | \
+	 MCI_RXACTIVEMASK | MCI_TXACTIVEMASK)
 /*
  * The size of the FIFO in bytes.
  */
@@ -202,7 +207,6 @@
 
 struct msmsdcc_host {
 	struct resource		*cmd_irqres;
-	struct resource		*pio_irqres;
 	struct resource		*memres;
 	struct resource		*dmares;
 	void __iomem		*base;
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/mvsdio.c linux-libre-3.2-gnu/drivers/mmc/host/mvsdio.c
--- linux-libre-3.1-gnu/drivers/mmc/host/mvsdio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/mvsdio.c	2012-01-04 18:55:44.000000000 -0500
@@ -117,7 +117,7 @@
 		host->pio_size = data->blocks * data->blksz;
 		host->pio_ptr = sg_virt(data->sg);
 		if (!nodma)
-			printk(KERN_DEBUG "%s: fallback to PIO for data "
+			pr_debug("%s: fallback to PIO for data "
 					  "at 0x%p size %d\n",
 					  mmc_hostname(host->mmc),
 					  host->pio_ptr, host->pio_size);
@@ -471,7 +471,7 @@
 		if (mrq->data)
 			err_status = mvsd_finish_data(host, mrq->data, err_status);
 		if (err_status) {
-			printk(KERN_ERR "%s: unhandled error status %#04x\n",
+			pr_err("%s: unhandled error status %#04x\n",
 					mmc_hostname(host->mmc), err_status);
 			cmd->error = -ENOMSG;
 		}
@@ -489,7 +489,7 @@
 	if (irq_handled)
 		return IRQ_HANDLED;
 
-	printk(KERN_ERR "%s: unhandled interrupt status=0x%04x en=0x%04x "
+	pr_err("%s: unhandled interrupt status=0x%04x en=0x%04x "
 			"pio=%d\n", mmc_hostname(host->mmc), intr_status,
 			host->intr_en, host->pio_size);
 	return IRQ_NONE;
@@ -505,9 +505,9 @@
 	spin_lock_irqsave(&host->lock, flags);
 	mrq = host->mrq;
 	if (mrq) {
-		printk(KERN_ERR "%s: Timeout waiting for hardware interrupt.\n",
+		pr_err("%s: Timeout waiting for hardware interrupt.\n",
 				mmc_hostname(host->mmc));
-		printk(KERN_ERR "%s: hw_state=0x%04x, intr_status=0x%04x "
+		pr_err("%s: hw_state=0x%04x, intr_status=0x%04x "
 				"intr_en=0x%04x\n", mmc_hostname(host->mmc),
 				mvsd_read(MVSD_HW_STATE),
 				mvsd_read(MVSD_NOR_INTR_STATUS),
@@ -762,7 +762,7 @@
 
 	ret = request_irq(irq, mvsd_irq, 0, DRIVER_NAME, host);
 	if (ret) {
-		printk(KERN_ERR "%s: cannot assign irq %d\n", DRIVER_NAME, irq);
+		pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq);
 		goto out;
 	} else
 		host->irq = irq;
@@ -802,7 +802,7 @@
 	if (ret)
 		goto out;
 
-	printk(KERN_NOTICE "%s: %s driver initialized, ",
+	pr_notice("%s: %s driver initialized, ",
 			   mmc_hostname(mmc), DRIVER_NAME);
 	if (host->gpio_card_detect)
 		printk("using GPIO %d for card detection\n",
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/mxcmmc.c linux-libre-3.2-gnu/drivers/mmc/host/mxcmmc.c
--- linux-libre-3.1-gnu/drivers/mmc/host/mxcmmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/mxcmmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,6 +40,7 @@
 #include <mach/mmc.h>
 
 #include <mach/dma.h>
+#include <mach/hardware.h>
 
 #define DRIVER_NAME "mxc-mmc"
 
@@ -731,6 +732,7 @@
 				"failed to config DMA channel. Falling back to PIO\n");
 			dma_release_channel(host->dma);
 			host->do_dma = 0;
+			host->dma = NULL;
 		}
 	}
 
@@ -842,7 +844,7 @@
 	int ret = 0, irq;
 	dma_cap_mask_t mask;
 
-	printk(KERN_INFO "i.MX SDHC driver\n");
+	pr_info("i.MX SDHC driver\n");
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq = platform_get_irq(pdev, 0);
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/mxs-mmc.c linux-libre-3.2-gnu/drivers/mmc/host/mxs-mmc.c
--- linux-libre-3.1-gnu/drivers/mmc/host/mxs-mmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/mxs-mmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/mmc/sdio.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/module.h>
 
 #include <mach/mxs.h>
 #include <mach/common.h>
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/omap.c linux-libre-3.2-gnu/drivers/mmc/host/omap.c
--- linux-libre-3.1-gnu/drivers/mmc/host/omap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/omap.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,7 +33,7 @@
 
 #include <plat/board.h>
 #include <plat/mmc.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
 #include <plat/dma.h>
 #include <plat/mux.h>
 #include <plat/fpga.h>
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/omap_hsmmc.c linux-libre-3.2-gnu/drivers/mmc/host/omap_hsmmc.c
--- linux-libre-3.1-gnu/drivers/mmc/host/omap_hsmmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/omap_hsmmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -450,15 +450,14 @@
 		* framework is fixed, we need a workaround like this
 		* (which is safe for MMC, but not in general).
 		*/
-		if (regulator_is_enabled(host->vcc) > 0) {
-			regulator_enable(host->vcc);
-			regulator_disable(host->vcc);
-		}
-		if (host->vcc_aux) {
-			if (regulator_is_enabled(reg) > 0) {
-				regulator_enable(reg);
-				regulator_disable(reg);
-			}
+		if (regulator_is_enabled(host->vcc) > 0 ||
+		    (host->vcc_aux && regulator_is_enabled(host->vcc_aux))) {
+			int vdd = ffs(mmc_slot(host).ocr_mask) - 1;
+
+			mmc_slot(host).set_power(host->dev, host->slot_id,
+						 1, vdd);
+			mmc_slot(host).set_power(host->dev, host->slot_id,
+						 0, 0);
 		}
 	}
 
@@ -1011,6 +1010,7 @@
 			host->data->sg_len,
 			omap_hsmmc_get_dma_dir(host, host->data));
 		omap_free_dma(dma_ch);
+		host->data->host_cookie = 0;
 	}
 	host->data = NULL;
 }
@@ -1264,14 +1264,14 @@
 	host->reqs_blocked = 0;
 	if (mmc_slot(host).get_cover_state(host->dev, host->slot_id)) {
 		if (host->protect_card) {
-			printk(KERN_INFO "%s: cover is closed, "
+			pr_info("%s: cover is closed, "
 					 "card is now accessible\n",
 					 mmc_hostname(host->mmc));
 			host->protect_card = 0;
 		}
 	} else {
 		if (!host->protect_card) {
-			printk(KERN_INFO "%s: cover is open, "
+			pr_info("%s: cover is open, "
 					 "card is now inaccessible\n",
 					 mmc_hostname(host->mmc));
 			host->protect_card = 1;
@@ -1422,7 +1422,7 @@
 
 	if (!next && data->host_cookie &&
 	    data->host_cookie != host->next_data.cookie) {
-		printk(KERN_WARNING "[%s] invalid cookie: data->host_cookie %d"
+		pr_warning("[%s] invalid cookie: data->host_cookie %d"
 		       " host->next_data.cookie %d\n",
 		       __func__, data->host_cookie, host->next_data.cookie);
 		data->host_cookie = 0;
@@ -1576,8 +1576,10 @@
 	struct mmc_data *data = mrq->data;
 
 	if (host->use_dma) {
-		dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
-			     omap_hsmmc_get_dma_dir(host, data));
+		if (data->host_cookie)
+			dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+				     data->sg_len,
+				     omap_hsmmc_get_dma_dir(host, data));
 		data->host_cookie = 0;
 	}
 }
@@ -1943,6 +1945,10 @@
 	omap_hsmmc_context_save(host);
 
 	mmc->caps |= MMC_CAP_DISABLE;
+	if (host->pdata->controller_flags & OMAP_HSMMC_BROKEN_MULTIBLOCK_READ) {
+		dev_info(&pdev->dev, "multiblock reads disabled due to 35xx erratum 2.1.1.128; MMC read performance may suffer\n");
+		mmc->caps2 |= MMC_CAP2_NO_MULTI_READ;
+	}
 
 	pm_runtime_enable(host->dev);
 	pm_runtime_get_sync(host->dev);
@@ -2015,7 +2021,7 @@
 	}
 
 	/* Request IRQ for MMC operations */
-	ret = request_irq(host->irq, omap_hsmmc_irq, IRQF_DISABLED,
+	ret = request_irq(host->irq, omap_hsmmc_irq, 0,
 			mmc_hostname(mmc), host);
 	if (ret) {
 		dev_dbg(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
@@ -2043,8 +2049,7 @@
 	if ((mmc_slot(host).card_detect_irq)) {
 		ret = request_irq(mmc_slot(host).card_detect_irq,
 				  omap_hsmmc_cd_handler,
-				  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
-					  | IRQF_DISABLED,
+				  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 				  mmc_hostname(mmc), host);
 		if (ret) {
 			dev_dbg(mmc_dev(host->mmc),
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/pxamci.c linux-libre-3.2-gnu/drivers/mmc/host/pxamci.c
--- linux-libre-3.1-gnu/drivers/mmc/host/pxamci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/pxamci.c	2012-01-04 18:55:44.000000000 -0500
@@ -558,7 +558,7 @@
 	if (dcsr & DCSR_ENDINTR) {
 		writel(BUF_PART_FULL, host->base + MMC_PRTBUF);
 	} else {
-		printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
+		pr_err("%s: DMA error on channel %d (DCSR=%#x)\n",
 		       mmc_hostname(host->mmc), dma, dcsr);
 		host->data->error = -EIO;
 		pxamci_data_done(host, 0);
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/s3cmci.c linux-libre-3.2-gnu/drivers/mmc/host/s3cmci.c
--- linux-libre-3.1-gnu/drivers/mmc/host/s3cmci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/s3cmci.c	2012-01-04 18:55:44.000000000 -0500
@@ -247,7 +247,7 @@
 {
 	if (host->sdio_irqen) {
 		if (gpio_get_value(S3C2410_GPE(8)) == 0) {
-			printk(KERN_DEBUG "%s: signalling irq\n", __func__);
+			pr_debug("%s: signalling irq\n", __func__);
 			mmc_signal_sdio_irq(host->mmc);
 		}
 	}
@@ -344,7 +344,7 @@
 
 	local_irq_save(flags);
 
-	//printk(KERN_DEBUG "%s: transfer %d\n", __func__, transfer);
+	/* pr_debug("%s: transfer %d\n", __func__, transfer); */
 
 	host->irq_disabled = transfer;
 
@@ -913,9 +913,9 @@
 }
 
 static void s3cmci_dma_setup(struct s3cmci_host *host,
-			     enum s3c2410_dmasrc source)
+			     enum dma_data_direction source)
 {
-	static enum s3c2410_dmasrc last_source = -1;
+	static enum dma_data_direction last_source = -1;
 	static int setup_ok;
 
 	if (last_source == source)
@@ -1087,7 +1087,7 @@
 
 	BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
 
-	s3cmci_dma_setup(host, rw ? S3C2410_DMASRC_MEM : S3C2410_DMASRC_HW);
+	s3cmci_dma_setup(host, rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 	s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
 
 	dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sdhci.c linux-libre-3.2-gnu/drivers/mmc/host/sdhci.c
--- linux-libre-3.1-gnu/drivers/mmc/host/sdhci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sdhci.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,10 +16,12 @@
 #include <linux/delay.h>
 #include <linux/highmem.h>
 #include <linux/io.h>
+#include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/scatterlist.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
 
 #include <linux/leds.h>
 
@@ -41,6 +43,7 @@
 #define MAX_TUNING_LOOP 40
 
 static unsigned int debug_quirks = 0;
+static unsigned int debug_quirks2;
 
 static void sdhci_finish_data(struct sdhci_host *);
 
@@ -49,53 +52,67 @@
 static int sdhci_execute_tuning(struct mmc_host *mmc);
 static void sdhci_tuning_timer(unsigned long data);
 
+#ifdef CONFIG_PM_RUNTIME
+static int sdhci_runtime_pm_get(struct sdhci_host *host);
+static int sdhci_runtime_pm_put(struct sdhci_host *host);
+#else
+static inline int sdhci_runtime_pm_get(struct sdhci_host *host)
+{
+	return 0;
+}
+static inline int sdhci_runtime_pm_put(struct sdhci_host *host)
+{
+	return 0;
+}
+#endif
+
 static void sdhci_dumpregs(struct sdhci_host *host)
 {
-	printk(KERN_DEBUG DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n",
+	pr_debug(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n",
 		mmc_hostname(host->mmc));
 
-	printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version:  0x%08x\n",
+	pr_debug(DRIVER_NAME ": Sys addr: 0x%08x | Version:  0x%08x\n",
 		sdhci_readl(host, SDHCI_DMA_ADDRESS),
 		sdhci_readw(host, SDHCI_HOST_VERSION));
-	printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt:  0x%08x\n",
+	pr_debug(DRIVER_NAME ": Blk size: 0x%08x | Blk cnt:  0x%08x\n",
 		sdhci_readw(host, SDHCI_BLOCK_SIZE),
 		sdhci_readw(host, SDHCI_BLOCK_COUNT));
-	printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
+	pr_debug(DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
 		sdhci_readl(host, SDHCI_ARGUMENT),
 		sdhci_readw(host, SDHCI_TRANSFER_MODE));
-	printk(KERN_DEBUG DRIVER_NAME ": Present:  0x%08x | Host ctl: 0x%08x\n",
+	pr_debug(DRIVER_NAME ": Present:  0x%08x | Host ctl: 0x%08x\n",
 		sdhci_readl(host, SDHCI_PRESENT_STATE),
 		sdhci_readb(host, SDHCI_HOST_CONTROL));
-	printk(KERN_DEBUG DRIVER_NAME ": Power:    0x%08x | Blk gap:  0x%08x\n",
+	pr_debug(DRIVER_NAME ": Power:    0x%08x | Blk gap:  0x%08x\n",
 		sdhci_readb(host, SDHCI_POWER_CONTROL),
 		sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL));
-	printk(KERN_DEBUG DRIVER_NAME ": Wake-up:  0x%08x | Clock:    0x%08x\n",
+	pr_debug(DRIVER_NAME ": Wake-up:  0x%08x | Clock:    0x%08x\n",
 		sdhci_readb(host, SDHCI_WAKE_UP_CONTROL),
 		sdhci_readw(host, SDHCI_CLOCK_CONTROL));
-	printk(KERN_DEBUG DRIVER_NAME ": Timeout:  0x%08x | Int stat: 0x%08x\n",
+	pr_debug(DRIVER_NAME ": Timeout:  0x%08x | Int stat: 0x%08x\n",
 		sdhci_readb(host, SDHCI_TIMEOUT_CONTROL),
 		sdhci_readl(host, SDHCI_INT_STATUS));
-	printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
+	pr_debug(DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
 		sdhci_readl(host, SDHCI_INT_ENABLE),
 		sdhci_readl(host, SDHCI_SIGNAL_ENABLE));
-	printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
+	pr_debug(DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
 		sdhci_readw(host, SDHCI_ACMD12_ERR),
 		sdhci_readw(host, SDHCI_SLOT_INT_STATUS));
-	printk(KERN_DEBUG DRIVER_NAME ": Caps:     0x%08x | Caps_1:   0x%08x\n",
+	pr_debug(DRIVER_NAME ": Caps:     0x%08x | Caps_1:   0x%08x\n",
 		sdhci_readl(host, SDHCI_CAPABILITIES),
 		sdhci_readl(host, SDHCI_CAPABILITIES_1));
-	printk(KERN_DEBUG DRIVER_NAME ": Cmd:      0x%08x | Max curr: 0x%08x\n",
+	pr_debug(DRIVER_NAME ": Cmd:      0x%08x | Max curr: 0x%08x\n",
 		sdhci_readw(host, SDHCI_COMMAND),
 		sdhci_readl(host, SDHCI_MAX_CURRENT));
-	printk(KERN_DEBUG DRIVER_NAME ": Host ctl2: 0x%08x\n",
+	pr_debug(DRIVER_NAME ": Host ctl2: 0x%08x\n",
 		sdhci_readw(host, SDHCI_HOST_CONTROL2));
 
 	if (host->flags & SDHCI_USE_ADMA)
-		printk(KERN_DEBUG DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
+		pr_debug(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
 		       readl(host->ioaddr + SDHCI_ADMA_ERROR),
 		       readl(host->ioaddr + SDHCI_ADMA_ADDRESS));
 
-	printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n");
+	pr_debug(DRIVER_NAME ": ===========================================\n");
 }
 
 /*****************************************************************************\
@@ -132,6 +149,9 @@
 	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
 		return;
 
+	if (host->quirks2 & SDHCI_QUIRK2_OWN_CARD_DETECTION)
+		return;
+
 	present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
 			      SDHCI_CARD_PRESENT;
 	irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
@@ -180,7 +200,7 @@
 	/* hw clears the bit when it's done */
 	while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
 		if (timeout == 0) {
-			printk(KERN_ERR "%s: Reset 0x%x never completed.\n",
+			pr_err("%s: Reset 0x%x never completed.\n",
 				mmc_hostname(host->mmc), (int)mask);
 			sdhci_dumpregs(host);
 			return;
@@ -251,11 +271,14 @@
 
 	spin_lock_irqsave(&host->lock, flags);
 
+	if (host->runtime_suspended)
+		goto out;
+
 	if (brightness == LED_OFF)
 		sdhci_deactivate_led(host);
 	else
 		sdhci_activate_led(host);
-
+out:
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 #endif
@@ -654,7 +677,7 @@
 	}
 
 	if (count >= 0xF) {
-		printk(KERN_WARNING "%s: Too large timeout requested for CMD%d!\n",
+		pr_warning("%s: Too large timeout requested for CMD%d!\n",
 		       mmc_hostname(host->mmc), cmd->opcode);
 		count = 0xE;
 	}
@@ -949,7 +972,7 @@
 
 	while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
 		if (timeout == 0) {
-			printk(KERN_ERR "%s: Controller never released "
+			pr_err("%s: Controller never released "
 				"inhibit bit(s).\n", mmc_hostname(host->mmc));
 			sdhci_dumpregs(host);
 			cmd->error = -EIO;
@@ -971,7 +994,7 @@
 	sdhci_set_transfer_mode(host, cmd);
 
 	if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
-		printk(KERN_ERR "%s: Unsupported response type!\n",
+		pr_err("%s: Unsupported response type!\n",
 			mmc_hostname(host->mmc));
 		cmd->error = -EINVAL;
 		tasklet_schedule(&host->finish_tasklet);
@@ -1121,7 +1144,7 @@
 	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
 		& SDHCI_CLOCK_INT_STABLE)) {
 		if (timeout == 0) {
-			printk(KERN_ERR "%s: Internal clock never "
+			pr_err("%s: Internal clock never "
 				"stabilised.\n", mmc_hostname(host->mmc));
 			sdhci_dumpregs(host);
 			return;
@@ -1209,6 +1232,8 @@
 
 	host = mmc_priv(mmc);
 
+	sdhci_runtime_pm_get(host);
+
 	spin_lock_irqsave(&host->lock, flags);
 
 	WARN_ON(host->mrq != NULL);
@@ -1269,14 +1294,11 @@
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 {
-	struct sdhci_host *host;
 	unsigned long flags;
 	u8 ctrl;
 
-	host = mmc_priv(mmc);
-
 	spin_lock_irqsave(&host->lock, flags);
 
 	if (host->flags & SDHCI_DEVICE_DEAD)
@@ -1426,7 +1448,16 @@
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static int check_ro(struct sdhci_host *host)
+static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+
+	sdhci_runtime_pm_get(host);
+	sdhci_do_set_ios(host, ios);
+	sdhci_runtime_pm_put(host);
+}
+
+static int sdhci_check_ro(struct sdhci_host *host)
 {
 	unsigned long flags;
 	int is_readonly;
@@ -1450,19 +1481,16 @@
 
 #define SAMPLE_COUNT	5
 
-static int sdhci_get_ro(struct mmc_host *mmc)
+static int sdhci_do_get_ro(struct sdhci_host *host)
 {
-	struct sdhci_host *host;
 	int i, ro_count;
 
-	host = mmc_priv(mmc);
-
 	if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT))
-		return check_ro(host);
+		return sdhci_check_ro(host);
 
 	ro_count = 0;
 	for (i = 0; i < SAMPLE_COUNT; i++) {
-		if (check_ro(host)) {
+		if (sdhci_check_ro(host)) {
 			if (++ro_count > SAMPLE_COUNT / 2)
 				return 1;
 		}
@@ -1471,38 +1499,64 @@
 	return 0;
 }
 
-static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
+static void sdhci_hw_reset(struct mmc_host *mmc)
 {
-	struct sdhci_host *host;
-	unsigned long flags;
+	struct sdhci_host *host = mmc_priv(mmc);
 
-	host = mmc_priv(mmc);
+	if (host->ops && host->ops->hw_reset)
+		host->ops->hw_reset(host);
+}
 
-	spin_lock_irqsave(&host->lock, flags);
+static int sdhci_get_ro(struct mmc_host *mmc)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	int ret;
 
+	sdhci_runtime_pm_get(host);
+	ret = sdhci_do_get_ro(host);
+	sdhci_runtime_pm_put(host);
+	return ret;
+}
+
+static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
+{
 	if (host->flags & SDHCI_DEVICE_DEAD)
 		goto out;
 
 	if (enable)
+		host->flags |= SDHCI_SDIO_IRQ_ENABLED;
+	else
+		host->flags &= ~SDHCI_SDIO_IRQ_ENABLED;
+
+	/* SDIO IRQ will be enabled as appropriate in runtime resume */
+	if (host->runtime_suspended)
+		goto out;
+
+	if (enable)
 		sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT);
 	else
 		sdhci_mask_irqs(host, SDHCI_INT_CARD_INT);
 out:
 	mmiowb();
+}
 
+static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	sdhci_enable_sdio_irq_nolock(host, enable);
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
-	struct mmc_ios *ios)
+static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
+						struct mmc_ios *ios)
 {
-	struct sdhci_host *host;
 	u8 pwr;
 	u16 clk, ctrl;
 	u32 present_state;
 
-	host = mmc_priv(mmc);
-
 	/*
 	 * Signal Voltage Switching is only applicable for Host Controllers
 	 * v3.00 and above.
@@ -1528,7 +1582,7 @@
 		if (!(ctrl & SDHCI_CTRL_VDD_180))
 			return 0;
 		else {
-			printk(KERN_INFO DRIVER_NAME ": Switching to 3.3V "
+			pr_info(DRIVER_NAME ": Switching to 3.3V "
 				"signalling voltage failed\n");
 			return -EIO;
 		}
@@ -1587,7 +1641,7 @@
 		pwr |= SDHCI_POWER_ON;
 		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
 
-		printk(KERN_INFO DRIVER_NAME ": Switching to 1.8V signalling "
+		pr_info(DRIVER_NAME ": Switching to 1.8V signalling "
 			"voltage failed, retrying with S18R set to 0\n");
 		return -EAGAIN;
 	} else
@@ -1595,6 +1649,20 @@
 		return 0;
 }
 
+static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
+	struct mmc_ios *ios)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	int err;
+
+	if (host->version < SDHCI_SPEC_300)
+		return 0;
+	sdhci_runtime_pm_get(host);
+	err = sdhci_do_start_signal_voltage_switch(host, ios);
+	sdhci_runtime_pm_put(host);
+	return err;
+}
+
 static int sdhci_execute_tuning(struct mmc_host *mmc)
 {
 	struct sdhci_host *host;
@@ -1606,6 +1674,7 @@
 
 	host = mmc_priv(mmc);
 
+	sdhci_runtime_pm_get(host);
 	disable_irq(host->irq);
 	spin_lock(&host->lock);
 
@@ -1623,6 +1692,7 @@
 	else {
 		spin_unlock(&host->lock);
 		enable_irq(host->irq);
+		sdhci_runtime_pm_put(host);
 		return 0;
 	}
 
@@ -1648,7 +1718,7 @@
 	timeout = 150;
 	do {
 		struct mmc_command cmd = {0};
-		struct mmc_request mrq = {0};
+		struct mmc_request mrq = {NULL};
 
 		if (!tuning_loop_counter && !timeout)
 			break;
@@ -1694,7 +1764,7 @@
 		spin_lock(&host->lock);
 
 		if (!host->tuning_done) {
-			printk(KERN_INFO DRIVER_NAME ": Timeout waiting for "
+			pr_info(DRIVER_NAME ": Timeout waiting for "
 				"Buffer Read Ready interrupt during tuning "
 				"procedure, falling back to fixed sampling "
 				"clock\n");
@@ -1724,7 +1794,7 @@
 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 	} else {
 		if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
-			printk(KERN_INFO DRIVER_NAME ": Tuning procedure"
+			pr_info(DRIVER_NAME ": Tuning procedure"
 				" failed, falling back to fixed sampling"
 				" clock\n");
 			err = -EIO;
@@ -1766,18 +1836,16 @@
 	sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier);
 	spin_unlock(&host->lock);
 	enable_irq(host->irq);
+	sdhci_runtime_pm_put(host);
 
 	return err;
 }
 
-static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable)
+static void sdhci_do_enable_preset_value(struct sdhci_host *host, bool enable)
 {
-	struct sdhci_host *host;
 	u16 ctrl;
 	unsigned long flags;
 
-	host = mmc_priv(mmc);
-
 	/* Host Controller v3.00 defines preset value registers */
 	if (host->version < SDHCI_SPEC_300)
 		return;
@@ -1793,18 +1861,30 @@
 	if (enable && !(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
 		ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+		host->flags |= SDHCI_PV_ENABLED;
 	} else if (!enable && (ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
 		ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+		host->flags &= ~SDHCI_PV_ENABLED;
 	}
 
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
+static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+
+	sdhci_runtime_pm_get(host);
+	sdhci_do_enable_preset_value(host, enable);
+	sdhci_runtime_pm_put(host);
+}
+
 static const struct mmc_host_ops sdhci_ops = {
 	.request	= sdhci_request,
 	.set_ios	= sdhci_set_ios,
 	.get_ro		= sdhci_get_ro,
+	.hw_reset	= sdhci_hw_reset,
 	.enable_sdio_irq = sdhci_enable_sdio_irq,
 	.start_signal_voltage_switch	= sdhci_start_signal_voltage_switch,
 	.execute_tuning			= sdhci_execute_tuning,
@@ -1826,19 +1906,19 @@
 
 	spin_lock_irqsave(&host->lock, flags);
 
-	if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
-		if (host->mrq) {
-			printk(KERN_ERR "%s: Card removed during transfer!\n",
-				mmc_hostname(host->mmc));
-			printk(KERN_ERR "%s: Resetting controller.\n",
-				mmc_hostname(host->mmc));
+	/* Check host->mrq first in case we are runtime suspended */
+	if (host->mrq &&
+	    !(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
+		pr_err("%s: Card removed during transfer!\n",
+			mmc_hostname(host->mmc));
+		pr_err("%s: Resetting controller.\n",
+			mmc_hostname(host->mmc));
 
-			sdhci_reset(host, SDHCI_RESET_CMD);
-			sdhci_reset(host, SDHCI_RESET_DATA);
+		sdhci_reset(host, SDHCI_RESET_CMD);
+		sdhci_reset(host, SDHCI_RESET_DATA);
 
-			host->mrq->cmd->error = -ENOMEDIUM;
-			tasklet_schedule(&host->finish_tasklet);
-		}
+		host->mrq->cmd->error = -ENOMEDIUM;
+		tasklet_schedule(&host->finish_tasklet);
 	}
 
 	spin_unlock_irqrestore(&host->lock, flags);
@@ -1854,14 +1934,16 @@
 
 	host = (struct sdhci_host*)param;
 
+	spin_lock_irqsave(&host->lock, flags);
+
         /*
          * If this tasklet gets rescheduled while running, it will
          * be run again afterwards but without any active request.
          */
-	if (!host->mrq)
+	if (!host->mrq) {
+		spin_unlock_irqrestore(&host->lock, flags);
 		return;
-
-	spin_lock_irqsave(&host->lock, flags);
+	}
 
 	del_timer(&host->timer);
 
@@ -1905,6 +1987,7 @@
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	mmc_request_done(host->mmc, mrq);
+	sdhci_runtime_pm_put(host);
 }
 
 static void sdhci_timeout_timer(unsigned long data)
@@ -1917,7 +2000,7 @@
 	spin_lock_irqsave(&host->lock, flags);
 
 	if (host->mrq) {
-		printk(KERN_ERR "%s: Timeout waiting for hardware "
+		pr_err("%s: Timeout waiting for hardware "
 			"interrupt.\n", mmc_hostname(host->mmc));
 		sdhci_dumpregs(host);
 
@@ -1963,7 +2046,7 @@
 	BUG_ON(intmask == 0);
 
 	if (!host->cmd) {
-		printk(KERN_ERR "%s: Got command interrupt 0x%08x even "
+		pr_err("%s: Got command interrupt 0x%08x even "
 			"though no command operation was in progress.\n",
 			mmc_hostname(host->mmc), (unsigned)intmask);
 		sdhci_dumpregs(host);
@@ -2063,7 +2146,7 @@
 			}
 		}
 
-		printk(KERN_ERR "%s: Got data interrupt 0x%08x even "
+		pr_err("%s: Got data interrupt 0x%08x even "
 			"though no data operation was in progress.\n",
 			mmc_hostname(host->mmc), (unsigned)intmask);
 		sdhci_dumpregs(host);
@@ -2080,7 +2163,7 @@
 			!= MMC_BUS_TEST_R)
 		host->data->error = -EILSEQ;
 	else if (intmask & SDHCI_INT_ADMA_ERROR) {
-		printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc));
+		pr_err("%s: ADMA error\n", mmc_hostname(host->mmc));
 		sdhci_show_adma_error(host);
 		host->data->error = -EIO;
 	}
@@ -2136,12 +2219,19 @@
 static irqreturn_t sdhci_irq(int irq, void *dev_id)
 {
 	irqreturn_t result;
-	struct sdhci_host* host = dev_id;
+	struct sdhci_host *host = dev_id;
 	u32 intmask;
 	int cardint = 0;
 
 	spin_lock(&host->lock);
 
+	if (host->runtime_suspended) {
+		spin_unlock(&host->lock);
+		pr_warning("%s: got irq while runtime suspended\n",
+		       mmc_hostname(host->mmc));
+		return IRQ_HANDLED;
+	}
+
 	intmask = sdhci_readl(host, SDHCI_INT_STATUS);
 
 	if (!intmask || intmask == 0xffffffff) {
@@ -2194,7 +2284,7 @@
 	intmask &= ~SDHCI_INT_ERROR;
 
 	if (intmask & SDHCI_INT_BUS_POWER) {
-		printk(KERN_ERR "%s: Card is consuming too much power!\n",
+		pr_err("%s: Card is consuming too much power!\n",
 			mmc_hostname(host->mmc));
 		sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS);
 	}
@@ -2207,7 +2297,7 @@
 	intmask &= ~SDHCI_INT_CARD_INT;
 
 	if (intmask) {
-		printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n",
+		pr_err("%s: Unexpected interrupt 0x%08x.\n",
 			mmc_hostname(host->mmc), intmask);
 		sdhci_dumpregs(host);
 
@@ -2237,7 +2327,7 @@
 
 #ifdef CONFIG_PM
 
-int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state)
+int sdhci_suspend_host(struct sdhci_host *host)
 {
 	int ret;
 
@@ -2275,7 +2365,6 @@
 			return ret;
 	}
 
-
 	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
 		if (host->ops->enable_dma)
 			host->ops->enable_dma(host);
@@ -2314,6 +2403,90 @@
 
 #endif /* CONFIG_PM */
 
+#ifdef CONFIG_PM_RUNTIME
+
+static int sdhci_runtime_pm_get(struct sdhci_host *host)
+{
+	return pm_runtime_get_sync(host->mmc->parent);
+}
+
+static int sdhci_runtime_pm_put(struct sdhci_host *host)
+{
+	pm_runtime_mark_last_busy(host->mmc->parent);
+	return pm_runtime_put_autosuspend(host->mmc->parent);
+}
+
+int sdhci_runtime_suspend_host(struct sdhci_host *host)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	/* Disable tuning since we are suspending */
+	if (host->version >= SDHCI_SPEC_300 &&
+	    host->tuning_mode == SDHCI_TUNING_MODE_1) {
+		del_timer_sync(&host->tuning_timer);
+		host->flags &= ~SDHCI_NEEDS_RETUNING;
+	}
+
+	spin_lock_irqsave(&host->lock, flags);
+	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	synchronize_irq(host->irq);
+
+	spin_lock_irqsave(&host->lock, flags);
+	host->runtime_suspended = true;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host);
+
+int sdhci_runtime_resume_host(struct sdhci_host *host)
+{
+	unsigned long flags;
+	int ret = 0, host_flags = host->flags;
+
+	if (host_flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
+		if (host->ops->enable_dma)
+			host->ops->enable_dma(host);
+	}
+
+	sdhci_init(host, 0);
+
+	/* Force clock and power re-program */
+	host->pwr = 0;
+	host->clock = 0;
+	sdhci_do_set_ios(host, &host->mmc->ios);
+
+	sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios);
+	if (host_flags & SDHCI_PV_ENABLED)
+		sdhci_do_enable_preset_value(host, true);
+
+	/* Set the re-tuning expiration flag */
+	if ((host->version >= SDHCI_SPEC_300) && host->tuning_count &&
+	    (host->tuning_mode == SDHCI_TUNING_MODE_1))
+		host->flags |= SDHCI_NEEDS_RETUNING;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	host->runtime_suspended = false;
+
+	/* Enable SDIO IRQ */
+	if ((host->flags & SDHCI_SDIO_IRQ_ENABLED))
+		sdhci_enable_sdio_irq_nolock(host, true);
+
+	/* Enable Card Detection */
+	sdhci_enable_card_detection(host);
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(sdhci_runtime_resume_host);
+
+#endif
+
 /*****************************************************************************\
  *                                                                           *
  * Device allocation/registration                                            *
@@ -2356,6 +2529,8 @@
 
 	if (debug_quirks)
 		host->quirks = debug_quirks;
+	if (debug_quirks2)
+		host->quirks2 = debug_quirks2;
 
 	sdhci_reset(host, SDHCI_RESET_ALL);
 
@@ -2363,7 +2538,7 @@
 	host->version = (host->version & SDHCI_SPEC_VER_MASK)
 				>> SDHCI_SPEC_VER_SHIFT;
 	if (host->version > SDHCI_SPEC_300) {
-		printk(KERN_ERR "%s: Unknown controller version (%d). "
+		pr_err("%s: Unknown controller version (%d). "
 			"You may experience problems.\n", mmc_hostname(mmc),
 			host->version);
 	}
@@ -2400,7 +2575,7 @@
 	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
 		if (host->ops->enable_dma) {
 			if (host->ops->enable_dma(host)) {
-				printk(KERN_WARNING "%s: No suitable DMA "
+				pr_warning("%s: No suitable DMA "
 					"available. Falling back to PIO.\n",
 					mmc_hostname(mmc));
 				host->flags &=
@@ -2420,7 +2595,7 @@
 		if (!host->adma_desc || !host->align_buffer) {
 			kfree(host->adma_desc);
 			kfree(host->align_buffer);
-			printk(KERN_WARNING "%s: Unable to allocate ADMA "
+			pr_warning("%s: Unable to allocate ADMA "
 				"buffers. Falling back to standard DMA.\n",
 				mmc_hostname(mmc));
 			host->flags &= ~SDHCI_USE_ADMA;
@@ -2448,8 +2623,7 @@
 	if (host->max_clk == 0 || host->quirks &
 			SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) {
 		if (!host->ops->get_max_clock) {
-			printk(KERN_ERR
-			       "%s: Hardware doesn't specify base clock "
+			pr_err("%s: Hardware doesn't specify base clock "
 			       "frequency.\n", mmc_hostname(mmc));
 			return -ENODEV;
 		}
@@ -2495,8 +2669,7 @@
 			host->timeout_clk = host->ops->get_timeout_clock(host);
 		} else if (!(host->quirks &
 				SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) {
-			printk(KERN_ERR
-			       "%s: Hardware doesn't specify timeout clock "
+			pr_err("%s: Hardware doesn't specify timeout clock "
 			       "frequency.\n", mmc_hostname(mmc));
 			return -ENODEV;
 		}
@@ -2566,6 +2739,15 @@
 	if (caps[1] & SDHCI_DRIVER_TYPE_D)
 		mmc->caps |= MMC_CAP_DRIVER_TYPE_D;
 
+	/*
+	 * If Power Off Notify capability is enabled by the host,
+	 * set notify to short power off notify timeout value.
+	 */
+	if (mmc->caps2 & MMC_CAP2_POWEROFF_NOTIFY)
+		mmc->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
+	else
+		mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE;
+
 	/* Initial value for re-tuning timer count */
 	host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >>
 			      SDHCI_RETUNING_TIMER_COUNT_SHIFT;
@@ -2655,7 +2837,7 @@
 		mmc->ocr_avail_mmc &= host->ocr_avail_mmc;
 
 	if (mmc->ocr_avail == 0) {
-		printk(KERN_ERR "%s: Hardware doesn't report any "
+		pr_err("%s: Hardware doesn't report any "
 			"support voltages.\n", mmc_hostname(mmc));
 		return -ENODEV;
 	}
@@ -2703,7 +2885,7 @@
 		mmc->max_blk_size = (caps[0] & SDHCI_MAX_BLOCK_MASK) >>
 				SDHCI_MAX_BLOCK_SHIFT;
 		if (mmc->max_blk_size >= 3) {
-			printk(KERN_WARNING "%s: Invalid maximum block size, "
+			pr_warning("%s: Invalid maximum block size, "
 				"assuming 512 bytes\n", mmc_hostname(mmc));
 			mmc->max_blk_size = 0;
 		}
@@ -2742,7 +2924,7 @@
 
 	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));
+		pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
 		host->vmmc = NULL;
 	} else {
 		regulator_enable(host->vmmc);
@@ -2771,7 +2953,7 @@
 
 	mmc_add_host(mmc);
 
-	printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s\n",
+	pr_info("%s: SDHCI controller on %s [%s] using %s\n",
 		mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)),
 		(host->flags & SDHCI_USE_ADMA) ? "ADMA" :
 		(host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO");
@@ -2804,7 +2986,7 @@
 		host->flags |= SDHCI_DEVICE_DEAD;
 
 		if (host->mrq) {
-			printk(KERN_ERR "%s: Controller removed during "
+			pr_err("%s: Controller removed during "
 				" transfer!\n", mmc_hostname(host->mmc));
 
 			host->mrq->cmd->error = -ENOMEDIUM;
@@ -2863,9 +3045,9 @@
 
 static int __init sdhci_drv_init(void)
 {
-	printk(KERN_INFO DRIVER_NAME
+	pr_info(DRIVER_NAME
 		": Secure Digital Host Controller Interface driver\n");
-	printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
+	pr_info(DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
 
 	return 0;
 }
@@ -2878,9 +3060,11 @@
 module_exit(sdhci_drv_exit);
 
 module_param(debug_quirks, uint, 0444);
+module_param(debug_quirks2, uint, 0444);
 
 MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>");
 MODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver");
 MODULE_LICENSE("GPL");
 
 MODULE_PARM_DESC(debug_quirks, "Force certain quirks.");
+MODULE_PARM_DESC(debug_quirks2, "Force certain other quirks.");
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sdhci-cns3xxx.c linux-libre-3.2-gnu/drivers/mmc/host/sdhci-cns3xxx.c
--- linux-libre-3.1-gnu/drivers/mmc/host/sdhci-cns3xxx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sdhci-cns3xxx.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/mmc/host.h>
+#include <linux/module.h>
 #include <mach/cns3xxx.h>
 #include "sdhci-pltfm.h"
 
@@ -108,13 +109,10 @@
 	.driver		= {
 		.name	= "sdhci-cns3xxx",
 		.owner	= THIS_MODULE,
+		.pm	= SDHCI_PLTFM_PMOPS,
 	},
 	.probe		= sdhci_cns3xxx_probe,
 	.remove		= __devexit_p(sdhci_cns3xxx_remove),
-#ifdef CONFIG_PM
-	.suspend	= sdhci_pltfm_suspend,
-	.resume		= sdhci_pltfm_resume,
-#endif
 };
 
 static int __init sdhci_cns3xxx_init(void)
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sdhci-dove.c linux-libre-3.2-gnu/drivers/mmc/host/sdhci-dove.c
--- linux-libre-3.1-gnu/drivers/mmc/host/sdhci-dove.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sdhci-dove.c	2012-01-04 18:55:44.000000000 -0500
@@ -82,13 +82,10 @@
 	.driver		= {
 		.name	= "sdhci-dove",
 		.owner	= THIS_MODULE,
+		.pm	= SDHCI_PLTFM_PMOPS,
 	},
 	.probe		= sdhci_dove_probe,
 	.remove		= __devexit_p(sdhci_dove_remove),
-#ifdef CONFIG_PM
-	.suspend	= sdhci_pltfm_suspend,
-	.resume		= sdhci_pltfm_resume,
-#endif
 };
 
 static int __init sdhci_dove_init(void)
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sdhci-esdhc-imx.c linux-libre-3.2-gnu/drivers/mmc/host/sdhci-esdhc-imx.c
--- linux-libre-3.1-gnu/drivers/mmc/host/sdhci-esdhc-imx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sdhci-esdhc-imx.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,6 +32,16 @@
 /* VENDOR SPEC register */
 #define SDHCI_VENDOR_SPEC		0xC0
 #define  SDHCI_VENDOR_SPEC_SDIO_QUIRK	0x00000002
+#define SDHCI_WTMK_LVL			0x44
+#define SDHCI_MIX_CTRL			0x48
+
+/*
+ * There is an INT DMA ERR mis-match between eSDHC and STD SDHC SPEC:
+ * Bit25 is used in STD SPEC, and is reserved in fsl eSDHC design,
+ * but bit28 is used as the INT DMA ERR in fsl eSDHC design.
+ * Define this macro DMA error INT for fsl eSDHC
+ */
+#define SDHCI_INT_VENDOR_SPEC_DMA_ERR	0x10000000
 
 /*
  * The CMDTYPE of the CMD register (offset 0xE) should be set to
@@ -51,6 +61,7 @@
 	IMX35_ESDHC,
 	IMX51_ESDHC,
 	IMX53_ESDHC,
+	IMX6Q_USDHC,
 };
 
 struct pltfm_imx_data {
@@ -74,6 +85,9 @@
 		.name = "sdhci-esdhc-imx53",
 		.driver_data = IMX53_ESDHC,
 	}, {
+		.name = "sdhci-usdhc-imx6q",
+		.driver_data = IMX6Q_USDHC,
+	}, {
 		/* sentinel */
 	}
 };
@@ -84,6 +98,7 @@
 	{ .compatible = "fsl,imx35-esdhc", .data = &imx_esdhc_devtype[IMX35_ESDHC], },
 	{ .compatible = "fsl,imx51-esdhc", .data = &imx_esdhc_devtype[IMX51_ESDHC], },
 	{ .compatible = "fsl,imx53-esdhc", .data = &imx_esdhc_devtype[IMX53_ESDHC], },
+	{ .compatible = "fsl,imx6q-usdhc", .data = &imx_esdhc_devtype[IMX6Q_USDHC], },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids);
@@ -108,6 +123,11 @@
 	return data->devtype == IMX53_ESDHC;
 }
 
+static inline int is_imx6q_usdhc(struct pltfm_imx_data *data)
+{
+	return data->devtype == IMX6Q_USDHC;
+}
+
 static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg)
 {
 	void __iomem *base = host->ioaddr + (reg & ~0x3);
@@ -135,6 +155,27 @@
 			val |= SDHCI_CARD_PRESENT;
 	}
 
+	if (unlikely(reg == SDHCI_CAPABILITIES)) {
+		/* In FSL esdhc IC module, only bit20 is used to indicate the
+		 * ADMA2 capability of esdhc, but this bit is messed up on
+		 * some SOCs (e.g. on MX25, MX35 this bit is set, but they
+		 * don't actually support ADMA2). So set the BROKEN_ADMA
+		 * uirk on MX25/35 platforms.
+		 */
+
+		if (val & SDHCI_CAN_DO_ADMA1) {
+			val &= ~SDHCI_CAN_DO_ADMA1;
+			val |= SDHCI_CAN_DO_ADMA2;
+		}
+	}
+
+	if (unlikely(reg == SDHCI_INT_STATUS)) {
+		if (val & SDHCI_INT_VENDOR_SPEC_DMA_ERR) {
+			val &= ~SDHCI_INT_VENDOR_SPEC_DMA_ERR;
+			val |= SDHCI_INT_ADMA_ERROR;
+		}
+	}
+
 	return val;
 }
 
@@ -179,13 +220,28 @@
 			writel(v, host->ioaddr + SDHCI_VENDOR_SPEC);
 	}
 
+	if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) {
+		if (val & SDHCI_INT_ADMA_ERROR) {
+			val &= ~SDHCI_INT_ADMA_ERROR;
+			val |= SDHCI_INT_VENDOR_SPEC_DMA_ERR;
+		}
+	}
+
 	writel(val, host->ioaddr + reg);
 }
 
 static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
 {
-	if (unlikely(reg == SDHCI_HOST_VERSION))
-		reg ^= 2;
+	if (unlikely(reg == SDHCI_HOST_VERSION)) {
+		u16 val = readw(host->ioaddr + (reg ^ 2));
+		/*
+		 * uSDHC supports SDHCI v3.0, but it's encoded as value
+		 * 0x3 in host controller version register, which violates
+		 * SDHCI_SPEC_300 definition.  Work it around here.
+		 */
+		if ((val & SDHCI_SPEC_VER_MASK) == 3)
+			return --val;
+	}
 
 	return readw(host->ioaddr + reg);
 }
@@ -216,8 +272,17 @@
 		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);
+
+		if (is_imx6q_usdhc(imx_data)) {
+			u32 m = readl(host->ioaddr + SDHCI_MIX_CTRL);
+			m = imx_data->scratchpad | (m & 0xffff0000);
+			writel(m, host->ioaddr + SDHCI_MIX_CTRL);
+			writel(val << 16,
+			       host->ioaddr + SDHCI_TRANSFER_MODE);
+		} else {
+			writel(val << 16 | imx_data->scratchpad,
+			       host->ioaddr + SDHCI_TRANSFER_MODE);
+		}
 		return;
 	case SDHCI_BLOCK_SIZE:
 		val &= ~SDHCI_MAKE_BLKSZ(0x7, 0);
@@ -311,9 +376,10 @@
 };
 
 static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
-	.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
+	.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_NO_HISPD_BIT
+			| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
+			| SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC
 			| SDHCI_QUIRK_BROKEN_CARD_DETECTION,
-	/* ADMA has issues. Might be fixable */
 	.ops = &sdhci_esdhc_ops,
 };
 
@@ -405,11 +471,19 @@
 
 	if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data))
 		/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
-		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
+		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
+			| SDHCI_QUIRK_BROKEN_ADMA;
 
 	if (is_imx53_esdhc(imx_data))
 		imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
 
+	/*
+	 * The imx6q ROM code will change the default watermark level setting
+	 * to something insane.  Change it back here.
+	 */
+	if (is_imx6q_usdhc(imx_data))
+		writel(0x08100810, host->ioaddr + SDHCI_WTMK_LVL);
+
 	boarddata = &imx_data->boarddata;
 	if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) {
 		if (!host->mmc->parent->platform_data) {
@@ -525,14 +599,11 @@
 		.name	= "sdhci-esdhc-imx",
 		.owner	= THIS_MODULE,
 		.of_match_table = imx_esdhc_dt_ids,
+		.pm	= SDHCI_PLTFM_PMOPS,
 	},
 	.id_table	= imx_esdhc_devtype,
 	.probe		= sdhci_esdhc_imx_probe,
 	.remove		= __devexit_p(sdhci_esdhc_imx_remove),
-#ifdef CONFIG_PM
-	.suspend	= sdhci_pltfm_suspend,
-	.resume		= sdhci_pltfm_resume,
-#endif
 };
 
 static int __init sdhci_esdhc_imx_init(void)
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sdhci.h linux-libre-3.2-gnu/drivers/mmc/host/sdhci.h
--- linux-libre-3.1-gnu/drivers/mmc/host/sdhci.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sdhci.h	2012-01-04 18:55:44.000000000 -0500
@@ -273,7 +273,7 @@
 	void	(*platform_reset_enter)(struct sdhci_host *host, u8 mask);
 	void	(*platform_reset_exit)(struct sdhci_host *host, u8 mask);
 	int	(*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
-
+	void	(*hw_reset)(struct sdhci_host *host);
 };
 
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
@@ -374,9 +374,14 @@
 extern void sdhci_remove_host(struct sdhci_host *host, int dead);
 
 #ifdef CONFIG_PM
-extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state);
+extern int sdhci_suspend_host(struct sdhci_host *host);
 extern int sdhci_resume_host(struct sdhci_host *host);
 extern void sdhci_enable_irq_wakeups(struct sdhci_host *host);
 #endif
 
+#ifdef CONFIG_PM_RUNTIME
+extern int sdhci_runtime_suspend_host(struct sdhci_host *host);
+extern int sdhci_runtime_resume_host(struct sdhci_host *host);
+#endif
+
 #endif /* __SDHCI_HW_H */
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sdhci-of-esdhc.c linux-libre-3.2-gnu/drivers/mmc/host/sdhci-of-esdhc.c
--- linux-libre-3.1-gnu/drivers/mmc/host/sdhci-of-esdhc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sdhci-of-esdhc.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * Freescale eSDHC controller driver.
  *
- * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ * Copyright (c) 2007, 2010 Freescale Semiconductor, Inc.
  * Copyright (c) 2009 MontaVista Software, Inc.
  *
  * Authors: Xiaobo Xie <X.Xie@freescale.com>
@@ -15,6 +15,7 @@
 
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <linux/mmc/host.h>
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
@@ -22,11 +23,21 @@
 static u16 esdhc_readw(struct sdhci_host *host, int reg)
 {
 	u16 ret;
+	int base = reg & ~0x3;
+	int shift = (reg & 0x2) * 8;
 
 	if (unlikely(reg == SDHCI_HOST_VERSION))
-		ret = in_be16(host->ioaddr + reg);
+		ret = in_be32(host->ioaddr + base) & 0xffff;
 	else
-		ret = sdhci_be32bs_readw(host, reg);
+		ret = (in_be32(host->ioaddr + base) >> shift) & 0xffff;
+	return ret;
+}
+
+static u8 esdhc_readb(struct sdhci_host *host, int reg)
+{
+	int base = reg & ~0x3;
+	int shift = (reg & 0x3) * 8;
+	u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff;
 	return ret;
 }
 
@@ -74,7 +85,7 @@
 static struct sdhci_ops sdhci_esdhc_ops = {
 	.read_l = sdhci_be32bs_readl,
 	.read_w = esdhc_readw,
-	.read_b = sdhci_be32bs_readb,
+	.read_b = esdhc_readb,
 	.write_l = sdhci_be32bs_writel,
 	.write_w = esdhc_writew,
 	.write_b = esdhc_writeb,
@@ -114,13 +125,10 @@
 		.name = "sdhci-esdhc",
 		.owner = THIS_MODULE,
 		.of_match_table = sdhci_esdhc_of_match,
+		.pm = SDHCI_PLTFM_PMOPS,
 	},
 	.probe = sdhci_esdhc_probe,
 	.remove = __devexit_p(sdhci_esdhc_remove),
-#ifdef CONFIG_PM
-	.suspend = sdhci_pltfm_suspend,
-	.resume = sdhci_pltfm_resume,
-#endif
 };
 
 static int __init sdhci_esdhc_init(void)
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sdhci-of-hlwd.c linux-libre-3.2-gnu/drivers/mmc/host/sdhci-of-hlwd.c
--- linux-libre-3.1-gnu/drivers/mmc/host/sdhci-of-hlwd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sdhci-of-hlwd.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,6 +20,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <linux/mmc/host.h>
 #include "sdhci-pltfm.h"
 
@@ -86,13 +87,10 @@
 		.name = "sdhci-hlwd",
 		.owner = THIS_MODULE,
 		.of_match_table = sdhci_hlwd_of_match,
+		.pm = SDHCI_PLTFM_PMOPS,
 	},
 	.probe = sdhci_hlwd_probe,
 	.remove = __devexit_p(sdhci_hlwd_remove),
-#ifdef CONFIG_PM
-	.suspend = sdhci_pltfm_suspend,
-	.resume = sdhci_pltfm_resume,
-#endif
 };
 
 static int __init sdhci_hlwd_init(void)
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sdhci-pci.c linux-libre-3.2-gnu/drivers/mmc/host/sdhci-pci.c
--- linux-libre-3.1-gnu/drivers/mmc/host/sdhci-pci.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sdhci-pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 
 #include <linux/delay.h>
 #include <linux/highmem.h>
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
@@ -21,6 +22,9 @@
 #include <linux/mmc/host.h>
 #include <linux/scatterlist.h>
 #include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/sfi.h>
+#include <linux/pm_runtime.h>
 
 #include "sdhci.h"
 
@@ -43,14 +47,14 @@
 
 struct sdhci_pci_fixes {
 	unsigned int		quirks;
+	bool			allow_runtime_pm;
 
 	int			(*probe) (struct sdhci_pci_chip *);
 
 	int			(*probe_slot) (struct sdhci_pci_slot *);
 	void			(*remove_slot) (struct sdhci_pci_slot *, int);
 
-	int			(*suspend) (struct sdhci_pci_chip *,
-					pm_message_t);
+	int			(*suspend) (struct sdhci_pci_chip *);
 	int			(*resume) (struct sdhci_pci_chip *);
 };
 
@@ -59,12 +63,16 @@
 	struct sdhci_host	*host;
 
 	int			pci_bar;
+	int			rst_n_gpio;
+	int			cd_gpio;
+	int			cd_irq;
 };
 
 struct sdhci_pci_chip {
 	struct pci_dev		*pdev;
 
 	unsigned int		quirks;
+	bool			allow_runtime_pm;
 	const struct sdhci_pci_fixes *fixes;
 
 	int			num_slots;	/* Slots on controller */
@@ -163,12 +171,129 @@
 	return 0;
 }
 
+/* Medfield eMMC hardware reset GPIOs */
+static int mfd_emmc0_rst_gpio = -EINVAL;
+static int mfd_emmc1_rst_gpio = -EINVAL;
+
+static int mfd_emmc_gpio_parse(struct sfi_table_header *table)
+{
+	struct sfi_table_simple *sb = (struct sfi_table_simple *)table;
+	struct sfi_gpio_table_entry *entry;
+	int i, num;
+
+	num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry);
+	entry = (struct sfi_gpio_table_entry *)sb->pentry;
+
+	for (i = 0; i < num; i++, entry++) {
+		if (!strncmp(entry->pin_name, "emmc0_rst", SFI_NAME_LEN))
+			mfd_emmc0_rst_gpio = entry->pin_no;
+		else if (!strncmp(entry->pin_name, "emmc1_rst", SFI_NAME_LEN))
+			mfd_emmc1_rst_gpio = entry->pin_no;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+
+static irqreturn_t mfd_sd_cd(int irq, void *dev_id)
+{
+	struct sdhci_pci_slot *slot = dev_id;
+	struct sdhci_host *host = slot->host;
+
+	mmc_detect_change(host->mmc, msecs_to_jiffies(200));
+	return IRQ_HANDLED;
+}
+
+#define MFLD_SD_CD_PIN 69
+
+static int mfd_sd_probe_slot(struct sdhci_pci_slot *slot)
+{
+	int err, irq, gpio = MFLD_SD_CD_PIN;
+
+	slot->cd_gpio = -EINVAL;
+	slot->cd_irq = -EINVAL;
+
+	err = gpio_request(gpio, "sd_cd");
+	if (err < 0)
+		goto out;
+
+	err = gpio_direction_input(gpio);
+	if (err < 0)
+		goto out_free;
+
+	irq = gpio_to_irq(gpio);
+	if (irq < 0)
+		goto out_free;
+
+	err = request_irq(irq, mfd_sd_cd, IRQF_TRIGGER_RISING |
+			  IRQF_TRIGGER_FALLING, "sd_cd", slot);
+	if (err)
+		goto out_free;
+
+	slot->cd_gpio = gpio;
+	slot->cd_irq = irq;
+	slot->host->quirks2 |= SDHCI_QUIRK2_OWN_CARD_DETECTION;
+
+	return 0;
+
+out_free:
+	gpio_free(gpio);
+out:
+	dev_warn(&slot->chip->pdev->dev, "failed to setup card detect wake up\n");
+	return 0;
+}
+
+static void mfd_sd_remove_slot(struct sdhci_pci_slot *slot, int dead)
+{
+	if (slot->cd_irq >= 0)
+		free_irq(slot->cd_irq, slot);
+	gpio_free(slot->cd_gpio);
+}
+
+#else
+
+#define mfd_sd_probe_slot	NULL
+#define mfd_sd_remove_slot	NULL
+
+#endif
+
 static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot)
 {
-	slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+	const char *name = NULL;
+	int gpio = -EINVAL;
+
+	sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, mfd_emmc_gpio_parse);
+
+	switch (slot->chip->pdev->device) {
+	case PCI_DEVICE_ID_INTEL_MFD_EMMC0:
+		gpio = mfd_emmc0_rst_gpio;
+		name = "eMMC0_reset";
+		break;
+	case PCI_DEVICE_ID_INTEL_MFD_EMMC1:
+		gpio = mfd_emmc1_rst_gpio;
+		name = "eMMC1_reset";
+		break;
+	}
+
+	if (!gpio_request(gpio, name)) {
+		gpio_direction_output(gpio, 1);
+		slot->rst_n_gpio = gpio;
+		slot->host->mmc->caps |= MMC_CAP_HW_RESET;
+	}
+
+	slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE;
+
+	slot->host->mmc->caps2 = MMC_CAP2_BOOTPART_NOACC;
+
 	return 0;
 }
 
+static void mfd_emmc_remove_slot(struct sdhci_pci_slot *slot, int dead)
+{
+	gpio_free(slot->rst_n_gpio);
+}
+
 static const struct sdhci_pci_fixes sdhci_intel_mrst_hc0 = {
 	.quirks		= SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_NO_HISPD_BIT,
 	.probe_slot	= mrst_hc_probe_slot,
@@ -181,15 +306,21 @@
 
 static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = {
 	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+	.allow_runtime_pm = true,
+	.probe_slot	= mfd_sd_probe_slot,
+	.remove_slot	= mfd_sd_remove_slot,
 };
 
 static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = {
 	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+	.allow_runtime_pm = true,
 };
 
 static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc = {
 	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+	.allow_runtime_pm = true,
 	.probe_slot	= mfd_emmc_probe_slot,
+	.remove_slot	= mfd_emmc_remove_slot,
 };
 
 /* O2Micro extra registers */
@@ -417,7 +548,7 @@
 		jmicron_enable_mmc(slot->host, 0);
 }
 
-static int jmicron_suspend(struct sdhci_pci_chip *chip, pm_message_t state)
+static int jmicron_suspend(struct sdhci_pci_chip *chip)
 {
 	int i;
 
@@ -832,9 +963,25 @@
 	return 0;
 }
 
+static void sdhci_pci_hw_reset(struct sdhci_host *host)
+{
+	struct sdhci_pci_slot *slot = sdhci_priv(host);
+	int rst_n_gpio = slot->rst_n_gpio;
+
+	if (!gpio_is_valid(rst_n_gpio))
+		return;
+	gpio_set_value_cansleep(rst_n_gpio, 0);
+	/* For eMMC, minimum is 1us but give it 10us for good measure */
+	udelay(10);
+	gpio_set_value_cansleep(rst_n_gpio, 1);
+	/* For eMMC, minimum is 200us but give it 300us for good measure */
+	usleep_range(300, 1000);
+}
+
 static struct sdhci_ops sdhci_pci_ops = {
 	.enable_dma	= sdhci_pci_enable_dma,
 	.platform_8bit_width	= sdhci_pci_8bit_width,
+	.hw_reset		= sdhci_pci_hw_reset,
 };
 
 /*****************************************************************************\
@@ -845,8 +992,9 @@
 
 #ifdef CONFIG_PM
 
-static int sdhci_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+static int sdhci_pci_suspend(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct sdhci_pci_chip *chip;
 	struct sdhci_pci_slot *slot;
 	mmc_pm_flag_t slot_pm_flags;
@@ -862,7 +1010,7 @@
 		if (!slot)
 			continue;
 
-		ret = sdhci_suspend_host(slot->host, state);
+		ret = sdhci_suspend_host(slot->host);
 
 		if (ret) {
 			for (i--; i >= 0; i--)
@@ -878,7 +1026,7 @@
 	}
 
 	if (chip->fixes && chip->fixes->suspend) {
-		ret = chip->fixes->suspend(chip, state);
+		ret = chip->fixes->suspend(chip);
 		if (ret) {
 			for (i = chip->num_slots - 1; i >= 0; i--)
 				sdhci_resume_host(chip->slots[i]->host);
@@ -894,16 +1042,17 @@
 		}
 		pci_set_power_state(pdev, PCI_D3hot);
 	} else {
-		pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+		pci_enable_wake(pdev, PCI_D3hot, 0);
 		pci_disable_device(pdev);
-		pci_set_power_state(pdev, pci_choose_state(pdev, state));
+		pci_set_power_state(pdev, PCI_D3hot);
 	}
 
 	return 0;
 }
 
-static int sdhci_pci_resume(struct pci_dev *pdev)
+static int sdhci_pci_resume(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct sdhci_pci_chip *chip;
 	struct sdhci_pci_slot *slot;
 	int i, ret;
@@ -944,6 +1093,96 @@
 
 #endif /* CONFIG_PM */
 
+#ifdef CONFIG_PM_RUNTIME
+
+static int sdhci_pci_runtime_suspend(struct device *dev)
+{
+	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+	struct sdhci_pci_chip *chip;
+	struct sdhci_pci_slot *slot;
+	int i, ret;
+
+	chip = pci_get_drvdata(pdev);
+	if (!chip)
+		return 0;
+
+	for (i = 0; i < chip->num_slots; i++) {
+		slot = chip->slots[i];
+		if (!slot)
+			continue;
+
+		ret = sdhci_runtime_suspend_host(slot->host);
+
+		if (ret) {
+			for (i--; i >= 0; i--)
+				sdhci_runtime_resume_host(chip->slots[i]->host);
+			return ret;
+		}
+	}
+
+	if (chip->fixes && chip->fixes->suspend) {
+		ret = chip->fixes->suspend(chip);
+		if (ret) {
+			for (i = chip->num_slots - 1; i >= 0; i--)
+				sdhci_runtime_resume_host(chip->slots[i]->host);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int sdhci_pci_runtime_resume(struct device *dev)
+{
+	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+	struct sdhci_pci_chip *chip;
+	struct sdhci_pci_slot *slot;
+	int i, ret;
+
+	chip = pci_get_drvdata(pdev);
+	if (!chip)
+		return 0;
+
+	if (chip->fixes && chip->fixes->resume) {
+		ret = chip->fixes->resume(chip);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < chip->num_slots; i++) {
+		slot = chip->slots[i];
+		if (!slot)
+			continue;
+
+		ret = sdhci_runtime_resume_host(slot->host);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int sdhci_pci_runtime_idle(struct device *dev)
+{
+	return 0;
+}
+
+#else
+
+#define sdhci_pci_runtime_suspend	NULL
+#define sdhci_pci_runtime_resume	NULL
+#define sdhci_pci_runtime_idle		NULL
+
+#endif
+
+static const struct dev_pm_ops sdhci_pci_pm_ops = {
+	.suspend = sdhci_pci_suspend,
+	.resume = sdhci_pci_resume,
+	.runtime_suspend = sdhci_pci_runtime_suspend,
+	.runtime_resume = sdhci_pci_runtime_resume,
+	.runtime_idle = sdhci_pci_runtime_idle,
+};
+
 /*****************************************************************************\
  *                                                                           *
  * Device probing/removal                                                    *
@@ -988,6 +1227,7 @@
 	slot->chip = chip;
 	slot->host = host;
 	slot->pci_bar = bar;
+	slot->rst_n_gpio = -EINVAL;
 
 	host->hw_name = "PCI";
 	host->ops = &sdhci_pci_ops;
@@ -1058,6 +1298,21 @@
 	sdhci_free_host(slot->host);
 }
 
+static void __devinit sdhci_pci_runtime_pm_allow(struct device *dev)
+{
+	pm_runtime_put_noidle(dev);
+	pm_runtime_allow(dev);
+	pm_runtime_set_autosuspend_delay(dev, 50);
+	pm_runtime_use_autosuspend(dev);
+	pm_suspend_ignore_children(dev, 1);
+}
+
+static void __devexit sdhci_pci_runtime_pm_forbid(struct device *dev)
+{
+	pm_runtime_forbid(dev);
+	pm_runtime_get_noresume(dev);
+}
+
 static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
 				     const struct pci_device_id *ent)
 {
@@ -1107,8 +1362,10 @@
 
 	chip->pdev = pdev;
 	chip->fixes = (const struct sdhci_pci_fixes *)ent->driver_data;
-	if (chip->fixes)
+	if (chip->fixes) {
 		chip->quirks = chip->fixes->quirks;
+		chip->allow_runtime_pm = chip->fixes->allow_runtime_pm;
+	}
 	chip->num_slots = slots;
 
 	pci_set_drvdata(pdev, chip);
@@ -1133,6 +1390,9 @@
 		chip->slots[i] = slot;
 	}
 
+	if (chip->allow_runtime_pm)
+		sdhci_pci_runtime_pm_allow(&pdev->dev);
+
 	return 0;
 
 free:
@@ -1152,6 +1412,9 @@
 	chip = pci_get_drvdata(pdev);
 
 	if (chip) {
+		if (chip->allow_runtime_pm)
+			sdhci_pci_runtime_pm_forbid(&pdev->dev);
+
 		for (i = 0; i < chip->num_slots; i++)
 			sdhci_pci_remove_slot(chip->slots[i]);
 
@@ -1167,8 +1430,9 @@
 	.id_table =	pci_ids,
 	.probe =	sdhci_pci_probe,
 	.remove =	__devexit_p(sdhci_pci_remove),
-	.suspend =	sdhci_pci_suspend,
-	.resume	=	sdhci_pci_resume,
+	.driver =	{
+		.pm =   &sdhci_pci_pm_ops
+	},
 };
 
 /*****************************************************************************\
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sdhci-pltfm.c linux-libre-3.2-gnu/drivers/mmc/host/sdhci-pltfm.c
--- linux-libre-3.1-gnu/drivers/mmc/host/sdhci-pltfm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sdhci-pltfm.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,7 @@
  */
 
 #include <linux/err.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #ifdef CONFIG_PPC
 #include <asm/machdep.h>
@@ -193,21 +194,25 @@
 EXPORT_SYMBOL_GPL(sdhci_pltfm_unregister);
 
 #ifdef CONFIG_PM
-int sdhci_pltfm_suspend(struct platform_device *dev, pm_message_t state)
+static int sdhci_pltfm_suspend(struct device *dev)
 {
-	struct sdhci_host *host = platform_get_drvdata(dev);
+	struct sdhci_host *host = dev_get_drvdata(dev);
 
-	return sdhci_suspend_host(host, state);
+	return sdhci_suspend_host(host);
 }
-EXPORT_SYMBOL_GPL(sdhci_pltfm_suspend);
 
-int sdhci_pltfm_resume(struct platform_device *dev)
+static int sdhci_pltfm_resume(struct device *dev)
 {
-	struct sdhci_host *host = platform_get_drvdata(dev);
+	struct sdhci_host *host = dev_get_drvdata(dev);
 
 	return sdhci_resume_host(host);
 }
-EXPORT_SYMBOL_GPL(sdhci_pltfm_resume);
+
+const struct dev_pm_ops sdhci_pltfm_pmops = {
+	.suspend	= sdhci_pltfm_suspend,
+	.resume		= sdhci_pltfm_resume,
+};
+EXPORT_SYMBOL_GPL(sdhci_pltfm_pmops);
 #endif	/* CONFIG_PM */
 
 static int __init sdhci_pltfm_drv_init(void)
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sdhci-pltfm.h linux-libre-3.2-gnu/drivers/mmc/host/sdhci-pltfm.h
--- linux-libre-3.1-gnu/drivers/mmc/host/sdhci-pltfm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sdhci-pltfm.h	2012-01-04 18:55:44.000000000 -0500
@@ -99,8 +99,10 @@
 extern int sdhci_pltfm_unregister(struct platform_device *pdev);
 
 #ifdef CONFIG_PM
-extern int sdhci_pltfm_suspend(struct platform_device *dev, pm_message_t state);
-extern int sdhci_pltfm_resume(struct platform_device *dev);
+extern const struct dev_pm_ops sdhci_pltfm_pmops;
+#define SDHCI_PLTFM_PMOPS (&sdhci_pltfm_pmops)
+#else
+#define SDHCI_PLTFM_PMOPS NULL
 #endif
 
 #endif /* _DRIVERS_MMC_SDHCI_PLTFM_H */
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sdhci-pxav2.c linux-libre-3.2-gnu/drivers/mmc/host/sdhci-pxav2.c
--- linux-libre-3.1-gnu/drivers/mmc/host/sdhci-pxav2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sdhci-pxav2.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/module.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/mmc/card.h>
@@ -59,7 +60,7 @@
 		 * tune timing of read data/command when crc error happen
 		 * no performance impact
 		 */
-		if (pdata->clk_delay_sel == 1) {
+		if (pdata && pdata->clk_delay_sel == 1) {
 			tmp = readw(host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
 
 			tmp &= ~(SDCLK_DELAY_MASK << SDCLK_DELAY_SHIFT);
@@ -71,7 +72,7 @@
 			writew(tmp, host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
 		}
 
-		if (pdata->flags & PXA_FLAG_ENABLE_CLOCK_GATING) {
+		if (pdata && (pdata->flags & PXA_FLAG_ENABLE_CLOCK_GATING)) {
 			tmp = readw(host->ioaddr + SD_FIFO_PARAM);
 			tmp &= ~CLK_GATE_SETTING_BITS;
 			writew(tmp, host->ioaddr + SD_FIFO_PARAM);
@@ -217,13 +218,10 @@
 	.driver		= {
 		.name	= "sdhci-pxav2",
 		.owner	= THIS_MODULE,
+		.pm	= SDHCI_PLTFM_PMOPS,
 	},
 	.probe		= sdhci_pxav2_probe,
 	.remove		= __devexit_p(sdhci_pxav2_remove),
-#ifdef CONFIG_PM
-	.suspend	= sdhci_pltfm_suspend,
-	.resume		= sdhci_pltfm_resume,
-#endif
 };
 static int __init sdhci_pxav2_init(void)
 {
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sdhci-pxav3.c linux-libre-3.2-gnu/drivers/mmc/host/sdhci-pxav3.c
--- linux-libre-3.1-gnu/drivers/mmc/host/sdhci-pxav3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sdhci-pxav3.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/platform_data/pxa_sdhci.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include "sdhci.h"
 #include "sdhci-pltfm.h"
 
@@ -263,13 +264,10 @@
 	.driver		= {
 		.name	= "sdhci-pxav3",
 		.owner	= THIS_MODULE,
+		.pm	= SDHCI_PLTFM_PMOPS,
 	},
 	.probe		= sdhci_pxav3_probe,
 	.remove		= __devexit_p(sdhci_pxav3_remove),
-#ifdef CONFIG_PM
-	.suspend	= sdhci_pltfm_suspend,
-	.resume		= sdhci_pltfm_resume,
-#endif
 };
 static int __init sdhci_pxav3_init(void)
 {
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sdhci-s3c.c linux-libre-3.2-gnu/drivers/mmc/host/sdhci-s3c.c
--- linux-libre-3.1-gnu/drivers/mmc/host/sdhci-s3c.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sdhci-s3c.c	2012-01-04 18:55:44.000000000 -0500
@@ -203,17 +203,23 @@
 		writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2);
 	}
 
-	/* reconfigure the hardware for new clock rate */
-
-	{
-		struct mmc_ios ios;
+	/* reprogram default hardware configuration */
+	writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA,
+		host->ioaddr + S3C64XX_SDHCI_CONTROL4);
 
-		ios.clock = clock;
+	ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
+	ctrl |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
+		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
+		  S3C_SDHCI_CTRL2_ENFBCLKRX |
+		  S3C_SDHCI_CTRL2_DFCNT_NONE |
+		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
+	writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2);
 
-		if (ourhost->pdata->cfg_card)
-			(ourhost->pdata->cfg_card)(ourhost->pdev, host->ioaddr,
-						   &ios, NULL);
-	}
+	/* reconfigure the controller for new clock rate */
+	ctrl = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
+	if (clock < 25 * 1000000)
+		ctrl |= (S3C_SDHCI_CTRL3_FCSEL3 | S3C_SDHCI_CTRL3_FCSEL2);
+	writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL3);
 }
 
 /**
@@ -561,8 +567,10 @@
 
  err_req_regs:
 	for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
-		clk_disable(sc->clk_bus[ptr]);
-		clk_put(sc->clk_bus[ptr]);
+		if (sc->clk_bus[ptr]) {
+			clk_disable(sc->clk_bus[ptr]);
+			clk_put(sc->clk_bus[ptr]);
+		}
 	}
 
  err_no_busclks:
@@ -614,33 +622,38 @@
 
 #ifdef CONFIG_PM
 
-static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm)
+static int sdhci_s3c_suspend(struct device *dev)
 {
-	struct sdhci_host *host = platform_get_drvdata(dev);
+	struct sdhci_host *host = dev_get_drvdata(dev);
 
-	return sdhci_suspend_host(host, pm);
+	return sdhci_suspend_host(host);
 }
 
-static int sdhci_s3c_resume(struct platform_device *dev)
+static int sdhci_s3c_resume(struct device *dev)
 {
-	struct sdhci_host *host = platform_get_drvdata(dev);
+	struct sdhci_host *host = dev_get_drvdata(dev);
 
 	return sdhci_resume_host(host);
 }
 
+static const struct dev_pm_ops sdhci_s3c_pmops = {
+	.suspend	= sdhci_s3c_suspend,
+	.resume		= sdhci_s3c_resume,
+};
+
+#define SDHCI_S3C_PMOPS (&sdhci_s3c_pmops)
+
 #else
-#define sdhci_s3c_suspend NULL
-#define sdhci_s3c_resume NULL
+#define SDHCI_S3C_PMOPS NULL
 #endif
 
 static struct platform_driver sdhci_s3c_driver = {
 	.probe		= sdhci_s3c_probe,
 	.remove		= __devexit_p(sdhci_s3c_remove),
-	.suspend	= sdhci_s3c_suspend,
-	.resume	        = sdhci_s3c_resume,
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= "s3c-sdhci",
+		.pm	= SDHCI_S3C_PMOPS,
 	},
 };
 
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sdhci-spear.c linux-libre-3.2-gnu/drivers/mmc/host/sdhci-spear.c
--- linux-libre-3.1-gnu/drivers/mmc/host/sdhci-spear.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sdhci-spear.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/highmem.h>
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/platform_device.h>
@@ -177,8 +178,6 @@
 					sdhci->data->card_power_gpio);
 			goto err_pgpio_direction;
 		}
-
-		gpio_set_value(sdhci->data->card_power_gpio, 1);
 	}
 
 	if (sdhci->data->card_int_gpio >= 0) {
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sdhci-tegra.c linux-libre-3.2-gnu/drivers/mmc/host/sdhci-tegra.c
--- linux-libre-3.1-gnu/drivers/mmc/host/sdhci-tegra.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sdhci-tegra.c	2012-01-04 18:55:44.000000000 -0500
@@ -13,15 +13,21 @@
  */
 
 #include <linux/err.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 #include <linux/gpio.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
+#include <linux/module.h>
 
-#include <mach/gpio.h>
+#include <asm/gpio.h>
+
+#include <mach/gpio-tegra.h>
 #include <mach/sdhci.h>
 
 #include "sdhci-pltfm.h"
@@ -73,10 +79,8 @@
 
 static unsigned int tegra_sdhci_get_ro(struct sdhci_host *sdhci)
 {
-	struct platform_device *pdev = to_platform_device(mmc_dev(sdhci->mmc));
-	struct tegra_sdhci_platform_data *plat;
-
-	plat = pdev->dev.platform_data;
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
+	struct tegra_sdhci_platform_data *plat = pltfm_host->priv;
 
 	if (!gpio_is_valid(plat->wp_gpio))
 		return -1;
@@ -94,12 +98,10 @@
 
 static int tegra_sdhci_8bit(struct sdhci_host *host, int bus_width)
 {
-	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
-	struct tegra_sdhci_platform_data *plat;
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct tegra_sdhci_platform_data *plat = pltfm_host->priv;
 	u32 ctrl;
 
-	plat = pdev->dev.platform_data;
-
 	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
 	if (plat->is_8bit && bus_width == MMC_BUS_WIDTH_8) {
 		ctrl &= ~SDHCI_CTRL_4BITBUS;
@@ -131,6 +133,36 @@
 	.ops  = &tegra_sdhci_ops,
 };
 
+static const struct of_device_id sdhci_tegra_dt_match[] __devinitdata = {
+	{ .compatible = "nvidia,tegra20-sdhci", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, sdhci_dt_ids);
+
+static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata(
+						struct platform_device *pdev)
+{
+	struct tegra_sdhci_platform_data *plat;
+	struct device_node *np = pdev->dev.of_node;
+
+	if (!np)
+		return NULL;
+
+	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
+	if (!plat) {
+		dev_err(&pdev->dev, "Can't allocate platform data\n");
+		return NULL;
+	}
+
+	plat->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
+	plat->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
+	plat->power_gpio = of_get_named_gpio(np, "power-gpios", 0);
+	if (of_find_property(np, "support-8bit", NULL))
+		plat->is_8bit = 1;
+
+	return plat;
+}
+
 static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
 {
 	struct sdhci_pltfm_host *pltfm_host;
@@ -147,12 +179,17 @@
 
 	plat = pdev->dev.platform_data;
 
+	if (plat == NULL)
+		plat = sdhci_tegra_dt_parse_pdata(pdev);
+
 	if (plat == NULL) {
 		dev_err(mmc_dev(host->mmc), "missing platform data\n");
 		rc = -ENXIO;
 		goto err_no_plat;
 	}
 
+	pltfm_host->priv = plat;
+
 	if (gpio_is_valid(plat->power_gpio)) {
 		rc = gpio_request(plat->power_gpio, "sdhci_power");
 		if (rc) {
@@ -247,13 +284,11 @@
 {
 	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-	struct tegra_sdhci_platform_data *plat;
+	struct tegra_sdhci_platform_data *plat = pltfm_host->priv;
 	int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
 
 	sdhci_remove_host(host, dead);
 
-	plat = pdev->dev.platform_data;
-
 	if (gpio_is_valid(plat->wp_gpio)) {
 		tegra_gpio_disable(plat->wp_gpio);
 		gpio_free(plat->wp_gpio);
@@ -282,13 +317,11 @@
 	.driver		= {
 		.name	= "sdhci-tegra",
 		.owner	= THIS_MODULE,
+		.of_match_table = sdhci_tegra_dt_match,
+		.pm	= SDHCI_PLTFM_PMOPS,
 	},
 	.probe		= sdhci_tegra_probe,
 	.remove		= __devexit_p(sdhci_tegra_remove),
-#ifdef CONFIG_PM
-	.suspend	= sdhci_pltfm_suspend,
-	.resume		= sdhci_pltfm_resume,
-#endif
 };
 
 static int __init sdhci_tegra_init(void)
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sdricoh_cs.c linux-libre-3.2-gnu/drivers/mmc/host/sdricoh_cs.c
--- linux-libre-3.1-gnu/drivers/mmc/host/sdricoh_cs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sdricoh_cs.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 */
 #include <linux/delay.h>
 #include <linux/highmem.h>
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/scatterlist.h>
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sh_mmcif.c linux-libre-3.2-gnu/drivers/mmc/host/sh_mmcif.c
--- linux-libre-3.1-gnu/drivers/mmc/host/sh_mmcif.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sh_mmcif.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/spinlock.h>
+#include <linux/module.h>
 
 #define DRIVER_NAME	"sh_mmcif"
 #define DRIVER_VERSION	"2010-04-28"
@@ -165,6 +166,8 @@
 	struct mmc_host *mmc;
 	struct mmc_data *data;
 	struct platform_device *pd;
+	struct sh_dmae_slave dma_slave_tx;
+	struct sh_dmae_slave dma_slave_rx;
 	struct clk *hclk;
 	unsigned int clk;
 	int bus_width;
@@ -323,25 +326,35 @@
 static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
 				 struct sh_mmcif_plat_data *pdata)
 {
+	struct sh_dmae_slave *tx, *rx;
 	host->dma_active = false;
 
 	/* We can only either use DMA for both Tx and Rx or not use it at all */
 	if (pdata->dma) {
+		dev_warn(&host->pd->dev,
+			 "Update your platform to use embedded DMA slave IDs\n");
+		tx = &pdata->dma->chan_priv_tx;
+		rx = &pdata->dma->chan_priv_rx;
+	} else {
+		tx = &host->dma_slave_tx;
+		tx->slave_id = pdata->slave_id_tx;
+		rx = &host->dma_slave_rx;
+		rx->slave_id = pdata->slave_id_rx;
+	}
+	if (tx->slave_id > 0 && rx->slave_id > 0) {
 		dma_cap_mask_t mask;
 
 		dma_cap_zero(mask);
 		dma_cap_set(DMA_SLAVE, mask);
 
-		host->chan_tx = dma_request_channel(mask, sh_mmcif_filter,
-						    &pdata->dma->chan_priv_tx);
+		host->chan_tx = dma_request_channel(mask, sh_mmcif_filter, tx);
 		dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
 			host->chan_tx);
 
 		if (!host->chan_tx)
 			return;
 
-		host->chan_rx = dma_request_channel(mask, sh_mmcif_filter,
-						    &pdata->dma->chan_priv_rx);
+		host->chan_rx = dma_request_channel(mask, sh_mmcif_filter, rx);
 		dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
 			host->chan_rx);
 
@@ -895,7 +908,7 @@
 		if (host->power) {
 			pm_runtime_put(&host->pd->dev);
 			host->power = false;
-			if (p->down_pwr)
+			if (p->down_pwr && ios->power_mode == MMC_POWER_OFF)
 				p->down_pwr(host->pd);
 		}
 		host->state = STATE_IDLE;
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/sh_mobile_sdhi.c linux-libre-3.2-gnu/drivers/mmc/host/sh_mobile_sdhi.c
--- linux-libre-3.1-gnu/drivers/mmc/host/sh_mobile_sdhi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/sh_mobile_sdhi.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
@@ -96,7 +97,8 @@
 	struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
 	struct tmio_mmc_host *host;
 	char clk_name[8];
-	int i, irq, ret;
+	int irq, ret, i = 0;
+	bool multiplexed_isr = true;
 
 	priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL);
 	if (priv == NULL) {
@@ -153,27 +155,60 @@
 	if (ret < 0)
 		goto eprobe;
 
-	for (i = 0; i < 3; i++) {
-		irq = platform_get_irq(pdev, i);
-		if (irq < 0) {
-			if (i) {
-				continue;
-			} else {
-				ret = irq;
-				goto eirq;
-			}
-		}
-		ret = request_irq(irq, tmio_mmc_irq, 0,
+	/*
+	 * Allow one or more specific (named) ISRs or
+	 * one or more multiplexed (un-named) ISRs.
+	 */
+
+	irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_CARD_DETECT);
+	if (irq >= 0) {
+		multiplexed_isr = false;
+		ret = request_irq(irq, tmio_mmc_card_detect_irq, 0,
 				  dev_name(&pdev->dev), host);
-		if (ret) {
-			while (i--) {
-				irq = platform_get_irq(pdev, i);
-				if (irq >= 0)
-					free_irq(irq, host);
-			}
-			goto eirq;
+		if (ret)
+			goto eirq_card_detect;
+	}
+
+	irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDIO);
+	if (irq >= 0) {
+		multiplexed_isr = false;
+		ret = request_irq(irq, tmio_mmc_sdio_irq, 0,
+				  dev_name(&pdev->dev), host);
+		if (ret)
+			goto eirq_sdio;
+	}
+
+	irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDCARD);
+	if (irq >= 0) {
+		multiplexed_isr = false;
+		ret = request_irq(irq, tmio_mmc_sdcard_irq, 0,
+				  dev_name(&pdev->dev), host);
+		if (ret)
+			goto eirq_sdcard;
+	} else if (!multiplexed_isr) {
+		dev_err(&pdev->dev,
+			"Principal SD-card IRQ is missing among named interrupts\n");
+		ret = irq;
+		goto eirq_sdcard;
+	}
+
+	if (multiplexed_isr) {
+		while (1) {
+			irq = platform_get_irq(pdev, i);
+			if (irq < 0)
+				break;
+			i++;
+			ret = request_irq(irq, tmio_mmc_irq, 0,
+					  dev_name(&pdev->dev), host);
+			if (ret)
+				goto eirq_multiplexed;
 		}
+
+		/* There must be at least one IRQ source */
+		if (!i)
+			goto eirq_multiplexed;
 	}
+
 	dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n",
 		 mmc_hostname(host->mmc), (unsigned long)
 		 (platform_get_resource(pdev,IORESOURCE_MEM, 0)->start),
@@ -181,7 +216,20 @@
 
 	return ret;
 
-eirq:
+eirq_multiplexed:
+	while (i--) {
+		irq = platform_get_irq(pdev, i);
+		free_irq(irq, host);
+	}
+eirq_sdcard:
+	irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDIO);
+	if (irq >= 0)
+		free_irq(irq, host);
+eirq_sdio:
+	irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_CARD_DETECT);
+	if (irq >= 0)
+		free_irq(irq, host);
+eirq_card_detect:
 	tmio_mmc_host_remove(host);
 eprobe:
 	clk_disable(priv->clk);
@@ -197,16 +245,17 @@
 	struct tmio_mmc_host *host = mmc_priv(mmc);
 	struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data);
 	struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
-	int i, irq;
+	int i = 0, irq;
 
 	p->pdata = NULL;
 
 	tmio_mmc_host_remove(host);
 
-	for (i = 0; i < 3; i++) {
-		irq = platform_get_irq(pdev, i);
-		if (irq >= 0)
-			free_irq(irq, host);
+	while (1) {
+		irq = platform_get_irq(pdev, i++);
+		if (irq < 0)
+			break;
+		free_irq(irq, host);
 	}
 
 	clk_disable(priv->clk);
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/tifm_sd.c linux-libre-3.2-gnu/drivers/mmc/host/tifm_sd.c
--- linux-libre-3.1-gnu/drivers/mmc/host/tifm_sd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/tifm_sd.c	2012-01-04 18:55:44.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/mmc/host.h>
 #include <linux/highmem.h>
 #include <linux/scatterlist.h>
+#include <linux/module.h>
 #include <asm/io.h>
 
 #define DRIVER_NAME "tifm_sd"
@@ -631,7 +632,7 @@
 	}
 
 	if (host->req) {
-		printk(KERN_ERR "%s : unfinished request detected\n",
+		pr_err("%s : unfinished request detected\n",
 		       dev_name(&sock->dev));
 		mrq->cmd->error = -ETIMEDOUT;
 		goto err_out;
@@ -671,7 +672,7 @@
 					    r_data->flags & MMC_DATA_WRITE
 					    ? PCI_DMA_TODEVICE
 					    : PCI_DMA_FROMDEVICE)) {
-				printk(KERN_ERR "%s : scatterlist map failed\n",
+				pr_err("%s : scatterlist map failed\n",
 				       dev_name(&sock->dev));
 				mrq->cmd->error = -ENOMEM;
 				goto err_out;
@@ -683,7 +684,7 @@
 						   ? PCI_DMA_TODEVICE
 						   : PCI_DMA_FROMDEVICE);
 			if (host->sg_len < 1) {
-				printk(KERN_ERR "%s : scatterlist map failed\n",
+				pr_err("%s : scatterlist map failed\n",
 				       dev_name(&sock->dev));
 				tifm_unmap_sg(sock, &host->bounce_buf, 1,
 					      r_data->flags & MMC_DATA_WRITE
@@ -747,7 +748,7 @@
 	host->req = NULL;
 
 	if (!mrq) {
-		printk(KERN_ERR " %s : no request to complete?\n",
+		pr_err(" %s : no request to complete?\n",
 		       dev_name(&sock->dev));
 		spin_unlock_irqrestore(&sock->lock, flags);
 		return;
@@ -786,8 +787,7 @@
 {
 	struct tifm_sd *host = (struct tifm_sd*)data;
 
-	printk(KERN_ERR
-	       "%s : card failed to respond for a long period of time "
+	pr_err("%s : card failed to respond for a long period of time "
 	       "(%x, %x)\n",
 	       dev_name(&host->dev->dev), host->req->cmd->opcode, host->cmd_flags);
 
@@ -905,7 +905,7 @@
 	}
 
 	if (rc) {
-		printk(KERN_ERR "%s : controller failed to reset\n",
+		pr_err("%s : controller failed to reset\n",
 		       dev_name(&sock->dev));
 		return -ENODEV;
 	}
@@ -931,8 +931,7 @@
 	}
 
 	if (rc) {
-		printk(KERN_ERR
-		       "%s : card not ready - probe failed on initialization\n",
+		pr_err("%s : card not ready - probe failed on initialization\n",
 		       dev_name(&sock->dev));
 		return -ENODEV;
 	}
@@ -953,7 +952,7 @@
 
 	if (!(TIFM_SOCK_STATE_OCCUPIED
 	      & readl(sock->addr + SOCK_PRESENT_STATE))) {
-		printk(KERN_WARNING "%s : card gone, unexpectedly\n",
+		pr_warning("%s : card gone, unexpectedly\n",
 		       dev_name(&sock->dev));
 		return rc;
 	}
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/tmio_mmc.c linux-libre-3.2-gnu/drivers/mmc/host/tmio_mmc.c
--- linux-libre-3.1-gnu/drivers/mmc/host/tmio_mmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/tmio_mmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -88,8 +88,8 @@
 	if (ret)
 		goto cell_disable;
 
-	ret = request_irq(irq, tmio_mmc_irq, IRQF_DISABLED |
-			  IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), host);
+	ret = request_irq(irq, tmio_mmc_irq, IRQF_TRIGGER_FALLING,
+				dev_name(&pdev->dev), host);
 	if (ret)
 		goto host_remove;
 
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/tmio_mmc.h linux-libre-3.2-gnu/drivers/mmc/host/tmio_mmc.h
--- linux-libre-3.1-gnu/drivers/mmc/host/tmio_mmc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/tmio_mmc.h	2012-01-04 18:55:44.000000000 -0500
@@ -79,6 +79,10 @@
 	struct delayed_work	delayed_reset_work;
 	struct work_struct	done;
 
+	/* Cache IRQ mask */
+	u32			sdcard_irq_mask;
+	u32			sdio_irq_mask;
+
 	spinlock_t		lock;		/* protect host private data */
 	unsigned long		last_req_ts;
 	struct mutex		ios_lock;	/* protect set_ios() context */
@@ -93,6 +97,9 @@
 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);
 irqreturn_t tmio_mmc_irq(int irq, void *devid);
+irqreturn_t tmio_mmc_sdcard_irq(int irq, void *devid);
+irqreturn_t tmio_mmc_card_detect_irq(int irq, void *devid);
+irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid);
 
 static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg,
 					 unsigned long *flags)
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/tmio_mmc_pio.c linux-libre-3.2-gnu/drivers/mmc/host/tmio_mmc_pio.c
--- linux-libre-3.1-gnu/drivers/mmc/host/tmio_mmc_pio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/tmio_mmc_pio.c	2012-01-04 18:55:44.000000000 -0500
@@ -48,14 +48,14 @@
 
 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);
+	host->sdcard_irq_mask &= ~(i & TMIO_MASK_IRQ);
+	sd_ctrl_write32(host, CTL_IRQ_MASK, host->sdcard_irq_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);
+	host->sdcard_irq_mask |= (i & TMIO_MASK_IRQ);
+	sd_ctrl_write32(host, CTL_IRQ_MASK, host->sdcard_irq_mask);
 }
 
 static void tmio_mmc_ack_mmc_irqs(struct tmio_mmc_host *host, u32 i)
@@ -92,7 +92,7 @@
 static void pr_debug_status(u32 status)
 {
 	int i = 0;
-	printk(KERN_DEBUG "status: %08x = ", status);
+	pr_debug("status: %08x = ", status);
 	STATUS_TO_TEXT(CARD_REMOVE, status, i);
 	STATUS_TO_TEXT(CARD_INSERT, status, i);
 	STATUS_TO_TEXT(SIGSTATE, status, i);
@@ -127,11 +127,13 @@
 
 	if (enable) {
 		host->sdio_irq_enabled = 1;
+		host->sdio_irq_mask = TMIO_SDIO_MASK_ALL &
+					~TMIO_SDIO_STAT_IOIRQ;
 		sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001);
-		sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK,
-			(TMIO_SDIO_MASK_ALL & ~TMIO_SDIO_STAT_IOIRQ));
+		sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask);
 	} else {
-		sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, TMIO_SDIO_MASK_ALL);
+		host->sdio_irq_mask = TMIO_SDIO_MASK_ALL;
+		sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask);
 		sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000);
 		host->sdio_irq_enabled = 0;
 	}
@@ -543,45 +545,20 @@
 	spin_unlock(&host->lock);
 }
 
-irqreturn_t tmio_mmc_irq(int irq, void *devid)
+static void tmio_mmc_card_irq_status(struct tmio_mmc_host *host,
+				       int *ireg, int *status)
 {
-	struct tmio_mmc_host *host = devid;
-	struct mmc_host *mmc = host->mmc;
-	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(mmc, 0);
-			goto out;
-		}
-
-		if (mmc->caps & MMC_CAP_SDIO_IRQ &&
-			sdio_ireg & TMIO_SDIO_STAT_IOIRQ)
-			mmc_signal_sdio_irq(mmc);
+	*status = sd_ctrl_read32(host, CTL_STATUS);
+	*ireg = *status & TMIO_MASK_IRQ & ~host->sdcard_irq_mask;
 
-		if (sdio_ireg)
-			goto out;
-	}
+	pr_debug_status(*status);
+	pr_debug_status(*ireg);
+}
 
-	pr_debug_status(status);
-	pr_debug_status(ireg);
+static bool __tmio_mmc_card_detect_irq(struct tmio_mmc_host *host,
+				      int ireg, int status)
+{
+	struct mmc_host *mmc = host->mmc;
 
 	/* Card insert / remove attempts */
 	if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
@@ -591,43 +568,102 @@
 		     ((ireg & TMIO_STAT_CARD_INSERT) && !mmc->card)) &&
 		    !work_pending(&mmc->detect.work))
 			mmc_detect_change(host->mmc, msecs_to_jiffies(100));
-		goto out;
+		return true;
 	}
 
-	/* CRC and other errors */
-/*	if (ireg & TMIO_STAT_ERR_IRQ)
- *		handled |= tmio_error_irq(host, irq, stat);
- */
+	return false;
+}
 
+irqreturn_t tmio_mmc_card_detect_irq(int irq, void *devid)
+{
+	unsigned int ireg, status;
+	struct tmio_mmc_host *host = devid;
+
+	tmio_mmc_card_irq_status(host, &ireg, &status);
+	__tmio_mmc_card_detect_irq(host, ireg, status);
+
+	return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(tmio_mmc_card_detect_irq);
+
+static bool __tmio_mmc_sdcard_irq(struct tmio_mmc_host *host,
+				 int ireg, int status)
+{
 	/* 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);
-		goto out;
+		return true;
 	}
 
 	/* 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);
-		goto out;
+		return true;
 	}
 
 	/* Data transfer completion */
 	if (ireg & TMIO_STAT_DATAEND) {
 		tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND);
 		tmio_mmc_data_irq(host);
-		goto out;
+		return true;
 	}
 
-	pr_warning("tmio_mmc: Spurious irq, disabling! "
-		"0x%08x 0x%08x 0x%08x\n", status, irq_mask, ireg);
-	pr_debug_status(status);
-	tmio_mmc_disable_mmc_irqs(host, status & ~irq_mask);
+	return false;
+}
+
+irqreturn_t tmio_mmc_sdcard_irq(int irq, void *devid)
+{
+	unsigned int ireg, status;
+	struct tmio_mmc_host *host = devid;
+
+	tmio_mmc_card_irq_status(host, &ireg, &status);
+	__tmio_mmc_sdcard_irq(host, ireg, status);
+
+	return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(tmio_mmc_sdcard_irq);
+
+irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid)
+{
+	struct tmio_mmc_host *host = devid;
+	struct mmc_host *mmc = host->mmc;
+	struct tmio_mmc_data *pdata = host->pdata;
+	unsigned int ireg, status;
+
+	if (!(pdata->flags & TMIO_MMC_SDIO_IRQ))
+		return IRQ_HANDLED;
+
+	status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
+	ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdcard_irq_mask;
+
+	sd_ctrl_write16(host, CTL_SDIO_STATUS, status & ~TMIO_SDIO_MASK_ALL);
+
+	if (mmc->caps & MMC_CAP_SDIO_IRQ && ireg & TMIO_SDIO_STAT_IOIRQ)
+		mmc_signal_sdio_irq(mmc);
+
+	return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(tmio_mmc_sdio_irq);
+
+irqreturn_t tmio_mmc_irq(int irq, void *devid)
+{
+	struct tmio_mmc_host *host = devid;
+	unsigned int ireg, status;
+
+	pr_debug("MMC IRQ begin\n");
+
+	tmio_mmc_card_irq_status(host, &ireg, &status);
+	if (__tmio_mmc_card_detect_irq(host, ireg, status))
+		return IRQ_HANDLED;
+	if (__tmio_mmc_sdcard_irq(host, ireg, status))
+		return IRQ_HANDLED;
+
+	tmio_mmc_sdio_irq(irq, devid);
 
-out:
 	return IRQ_HANDLED;
 }
 EXPORT_SYMBOL(tmio_mmc_irq);
@@ -762,7 +798,7 @@
 		/* start bus clock */
 		tmio_mmc_clk_start(host);
 	} else if (ios->power_mode != MMC_POWER_UP) {
-		if (host->set_pwr)
+		if (host->set_pwr && ios->power_mode == MMC_POWER_OFF)
 			host->set_pwr(host->pdev, 0);
 		if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) &&
 		    pdata->power) {
@@ -882,6 +918,7 @@
 	tmio_mmc_clk_stop(_host);
 	tmio_mmc_reset(_host);
 
+	_host->sdcard_irq_mask = sd_ctrl_read32(_host, CTL_IRQ_MASK);
 	tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL);
 	if (pdata->flags & TMIO_MMC_SDIO_IRQ)
 		tmio_mmc_enable_sdio_irq(mmc, 0);
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/via-sdmmc.c linux-libre-3.2-gnu/drivers/mmc/host/via-sdmmc.c
--- linux-libre-3.1-gnu/drivers/mmc/host/via-sdmmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/via-sdmmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include <linux/pci.h>
+#include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/highmem.h>
 #include <linux/delay.h>
@@ -1191,7 +1192,7 @@
 	mmiowb();
 
 	if (sdhost->mrq) {
-		printk(KERN_ERR "%s: Controller removed during "
+		pr_err("%s: Controller removed during "
 			"transfer\n", mmc_hostname(sdhost->mmc));
 
 		/* make sure all DMA is stopped */
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/vub300.c linux-libre-3.2-gnu/drivers/mmc/host/vub300.c
--- linux-libre-3.1-gnu/drivers/mmc/host/vub300.c	2012-03-19 22:03:25.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/vub300.c	2012-03-19 22:06:32.000000000 -0400
@@ -259,7 +259,7 @@
 static int firmware_rom_wait_states = 0x1C;
 #endif
 
-module_param(firmware_rom_wait_states, bool, 0644);
+module_param(firmware_rom_wait_states, int, 0644);
 MODULE_PARM_DESC(firmware_rom_wait_states,
 		 "ROM wait states byte=RRRIIEEE (Reserved Internal External)");
 
diff -druN linux-libre-3.1-gnu/drivers/mmc/host/wbsd.c linux-libre-3.2-gnu/drivers/mmc/host/wbsd.c
--- linux-libre-3.1-gnu/drivers/mmc/host/wbsd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mmc/host/wbsd.c	2012-01-04 18:55:44.000000000 -0500
@@ -194,7 +194,7 @@
 {
 	u8 setup;
 
-	printk(KERN_ERR "%s: Resetting chip\n", mmc_hostname(host->mmc));
+	pr_err("%s: Resetting chip\n", mmc_hostname(host->mmc));
 
 	/*
 	 * Soft reset of chip (SD/MMC part).
@@ -721,7 +721,7 @@
 		 * Any leftover data?
 		 */
 		if (count) {
-			printk(KERN_ERR "%s: Incomplete DMA transfer. "
+			pr_err("%s: Incomplete DMA transfer. "
 				"%d bytes left.\n",
 				mmc_hostname(host->mmc), count);
 
@@ -803,7 +803,7 @@
 
 		default:
 #ifdef CONFIG_MMC_DEBUG
-			printk(KERN_WARNING "%s: Data command %d is not "
+			pr_warning("%s: Data command %d is not "
 				"supported by this controller.\n",
 				mmc_hostname(host->mmc), cmd->opcode);
 #endif
@@ -1029,7 +1029,7 @@
 		host->flags &= ~WBSD_FCARD_PRESENT;
 
 		if (host->mrq) {
-			printk(KERN_ERR "%s: Card removed during transfer!\n",
+			pr_err("%s: Card removed during transfer!\n",
 				mmc_hostname(host->mmc));
 			wbsd_reset(host);
 
@@ -1429,7 +1429,7 @@
 	free_dma(dma);
 
 err:
-	printk(KERN_WARNING DRIVER_NAME ": Unable to allocate DMA %d. "
+	pr_warning(DRIVER_NAME ": Unable to allocate DMA %d. "
 		"Falling back on FIFO.\n", dma);
 }
 
@@ -1664,7 +1664,7 @@
 	ret = wbsd_scan(host);
 	if (ret) {
 		if (pnp && (ret == -ENODEV)) {
-			printk(KERN_WARNING DRIVER_NAME
+			pr_warning(DRIVER_NAME
 				": Unable to confirm device presence. You may "
 				"experience lock-ups.\n");
 		} else {
@@ -1688,7 +1688,7 @@
 	 */
 	if (pnp) {
 		if ((host->config != 0) && !wbsd_chip_validate(host)) {
-			printk(KERN_WARNING DRIVER_NAME
+			pr_warning(DRIVER_NAME
 				": PnP active but chip not configured! "
 				"You probably have a buggy BIOS. "
 				"Configuring chip manually.\n");
@@ -1720,7 +1720,7 @@
 
 	mmc_add_host(mmc);
 
-	printk(KERN_INFO "%s: W83L51xD", mmc_hostname(mmc));
+	pr_info("%s: W83L51xD", mmc_hostname(mmc));
 	if (host->chip_id != 0)
 		printk(" id %x", (int)host->chip_id);
 	printk(" at 0x%x irq %d", (int)host->base, (int)host->irq);
@@ -1909,7 +1909,7 @@
 	 */
 	if (host->config != 0) {
 		if (!wbsd_chip_validate(host)) {
-			printk(KERN_WARNING DRIVER_NAME
+			pr_warning(DRIVER_NAME
 				": PnP active but chip not configured! "
 				"You probably have a buggy BIOS. "
 				"Configuring chip manually.\n");
@@ -1973,9 +1973,9 @@
 {
 	int result;
 
-	printk(KERN_INFO DRIVER_NAME
+	pr_info(DRIVER_NAME
 		": Winbond W83L51xD SD/MMC card interface driver\n");
-	printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
+	pr_info(DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
 
 #ifdef CONFIG_PNP
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/afs.c linux-libre-3.2-gnu/drivers/mtd/afs.c
--- linux-libre-3.1-gnu/drivers/mtd/afs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/afs.c	2012-01-04 18:55:44.000000000 -0500
@@ -162,8 +162,8 @@
 }
 
 static int parse_afs_partitions(struct mtd_info *mtd,
-                         struct mtd_partition **pparts,
-                         unsigned long origin)
+				struct mtd_partition **pparts,
+				struct mtd_part_parser_data *data)
 {
 	struct mtd_partition *parts;
 	u_int mask, off, idx, sz;
diff -druN linux-libre-3.1-gnu/drivers/mtd/ar7part.c linux-libre-3.2-gnu/drivers/mtd/ar7part.c
--- linux-libre-3.1-gnu/drivers/mtd/ar7part.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/ar7part.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/bootmem.h>
 #include <linux/magic.h>
+#include <linux/module.h>
 
 #define AR7_PARTS	4
 #define ROOT_OFFSET	0xe0000
@@ -46,7 +47,7 @@
 
 static int create_mtd_partitions(struct mtd_info *master,
 				 struct mtd_partition **pparts,
-				 unsigned long origin)
+				 struct mtd_part_parser_data *data)
 {
 	struct ar7_bin_rec header;
 	unsigned int offset;
diff -druN linux-libre-3.1-gnu/drivers/mtd/chips/cfi_cmdset_0002.c linux-libre-3.2-gnu/drivers/mtd/chips/cfi_cmdset_0002.c
--- linux-libre-3.1-gnu/drivers/mtd/chips/cfi_cmdset_0002.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/chips/cfi_cmdset_0002.c	2012-01-04 18:55:44.000000000 -0500
@@ -145,8 +145,7 @@
 	if (((major << 8) | minor) < 0x3131) {
 		/* CFI version 1.0 => don't trust bootloc */
 
-		DEBUG(MTD_DEBUG_LEVEL1,
-			"%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n",
+		pr_debug("%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n",
 			map->name, cfi->mfr, cfi->id);
 
 		/* AFAICS all 29LV400 with a bottom boot block have a device ID
@@ -166,8 +165,7 @@
 			 * the 8-bit device ID.
 			 */
 			(cfi->mfr == CFI_MFR_MACRONIX)) {
-			DEBUG(MTD_DEBUG_LEVEL1,
-				"%s: Macronix MX29LV400C with bottom boot block"
+			pr_debug("%s: Macronix MX29LV400C with bottom boot block"
 				" detected\n", map->name);
 			extp->TopBottom = 2;	/* bottom boot */
 		} else
@@ -178,8 +176,7 @@
 			extp->TopBottom = 2;	/* bottom boot */
 		}
 
-		DEBUG(MTD_DEBUG_LEVEL1,
-			"%s: AMD CFI PRI V%c.%c has no boot block field;"
+		pr_debug("%s: AMD CFI PRI V%c.%c has no boot block field;"
 			" deduced %s from Device ID\n", map->name, major, minor,
 			extp->TopBottom == 2 ? "bottom" : "top");
 	}
@@ -191,7 +188,7 @@
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
 	if (cfi->cfiq->BufWriteTimeoutTyp) {
-		DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" );
+		pr_debug("Using buffer write method\n" );
 		mtd->write = cfi_amdstd_write_buffers;
 	}
 }
@@ -443,8 +440,8 @@
 	mtd->writesize = 1;
 	mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): write buffer size %d\n",
-		__func__, mtd->writebufsize);
+	pr_debug("MTD %s(): write buffer size %d\n", __func__,
+			mtd->writebufsize);
 
 	mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot;
 
@@ -1163,7 +1160,7 @@
 		return ret;
 	}
 
-	DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
+	pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
 	       __func__, adr, datum.x[0] );
 
 	/*
@@ -1174,7 +1171,7 @@
 	 */
 	oldd = map_read(map, adr);
 	if (map_word_equal(map, oldd, datum)) {
-		DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): NOP\n",
+		pr_debug("MTD %s(): NOP\n",
 		       __func__);
 		goto op_done;
 	}
@@ -1400,7 +1397,7 @@
 
 	datum = map_word_load(map, buf);
 
-	DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
+	pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
 	       __func__, adr, datum.x[0] );
 
 	XIP_INVAL_CACHED_RANGE(map, adr, len);
@@ -1587,7 +1584,7 @@
 		return ret;
 	}
 
-	DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
+	pr_debug("MTD %s(): ERASE 0x%.8lx\n",
 	       __func__, chip->start );
 
 	XIP_INVAL_CACHED_RANGE(map, adr, map->size);
@@ -1675,7 +1672,7 @@
 		return ret;
 	}
 
-	DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
+	pr_debug("MTD %s(): ERASE 0x%.8lx\n",
 	       __func__, adr );
 
 	XIP_INVAL_CACHED_RANGE(map, adr, len);
@@ -1801,8 +1798,7 @@
 		goto out_unlock;
 	chip->state = FL_LOCKING;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n",
-	      __func__, adr, len);
+	pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", __func__, adr, len);
 
 	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
 			 cfi->device_type, NULL);
@@ -1837,8 +1833,7 @@
 		goto out_unlock;
 	chip->state = FL_UNLOCKING;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n",
-	      __func__, adr, len);
+	pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", __func__, adr, len);
 
 	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
 			 cfi->device_type, NULL);
diff -druN linux-libre-3.1-gnu/drivers/mtd/chips/fwh_lock.h linux-libre-3.2-gnu/drivers/mtd/chips/fwh_lock.h
--- linux-libre-3.1-gnu/drivers/mtd/chips/fwh_lock.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/chips/fwh_lock.h	2012-01-04 18:55:44.000000000 -0500
@@ -34,8 +34,7 @@
 
 	/* Refuse the operation if the we cannot look behind the chip */
 	if (chip->start < 0x400000) {
-		DEBUG( MTD_DEBUG_LEVEL3,
-			"MTD %s(): chip->start: %lx wanted >= 0x400000\n",
+		pr_debug( "MTD %s(): chip->start: %lx wanted >= 0x400000\n",
 			__func__, chip->start );
 		return -EIO;
 	}
diff -druN linux-libre-3.1-gnu/drivers/mtd/chips/jedec_probe.c linux-libre-3.2-gnu/drivers/mtd/chips/jedec_probe.c
--- linux-libre-3.1-gnu/drivers/mtd/chips/jedec_probe.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/chips/jedec_probe.c	2012-01-04 18:55:44.000000000 -0500
@@ -1914,11 +1914,10 @@
 	 * (oh and incidentaly the jedec spec - 3.5.3.3) the reset
 	 * sequence is *supposed* to be 0xaa at 0x5555, 0x55 at
 	 * 0x2aaa, 0xF0 at 0x5555 this will not affect the AMD chips
-	 * as they will ignore the writes and dont care what address
+	 * as they will ignore the writes and don't care what address
 	 * the F0 is written to */
 	if (cfi->addr_unlock1) {
-		DEBUG( MTD_DEBUG_LEVEL3,
-		       "reset unlock called %x %x \n",
+		pr_debug( "reset unlock called %x %x \n",
 		       cfi->addr_unlock1,cfi->addr_unlock2);
 		cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
 		cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
@@ -1941,7 +1940,7 @@
 	uint8_t uaddr;
 
 	if (!(jedec_table[index].devtypes & cfi->device_type)) {
-		DEBUG(MTD_DEBUG_LEVEL1, "Rejecting potential %s with incompatible %d-bit device type\n",
+		pr_debug("Rejecting potential %s with incompatible %d-bit device type\n",
 		      jedec_table[index].name, 4 * (1<<cfi->device_type));
 		return 0;
 	}
@@ -2021,7 +2020,7 @@
 		 * there aren't.
 		 */
 		if (finfo->dev_id > 0xff) {
-			DEBUG( MTD_DEBUG_LEVEL3, "%s(): ID is not 8bit\n",
+			pr_debug("%s(): ID is not 8bit\n",
 			       __func__);
 			goto match_done;
 		}
@@ -2045,12 +2044,10 @@
 	}
 
 	/* the part size must fit in the memory window */
-	DEBUG( MTD_DEBUG_LEVEL3,
-	       "MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n",
+	pr_debug("MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n",
 	       __func__, base, 1 << finfo->dev_size, base + (1 << finfo->dev_size) );
 	if ( base + cfi_interleave(cfi) * ( 1 << finfo->dev_size ) > map->size ) {
-		DEBUG( MTD_DEBUG_LEVEL3,
-		       "MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n",
+		pr_debug("MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n",
 		       __func__, finfo->mfr_id, finfo->dev_id,
 		       1 << finfo->dev_size );
 		goto match_done;
@@ -2061,13 +2058,12 @@
 
 	uaddr = finfo->uaddr;
 
-	DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n",
+	pr_debug("MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n",
 	       __func__, cfi->addr_unlock1, cfi->addr_unlock2 );
 	if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr
 	     && ( unlock_addrs[uaddr].addr1 / cfi->device_type != cfi->addr_unlock1 ||
 		  unlock_addrs[uaddr].addr2 / cfi->device_type != cfi->addr_unlock2 ) ) {
-		DEBUG( MTD_DEBUG_LEVEL3,
-			"MTD %s(): 0x%.4x 0x%.4x did not match\n",
+		pr_debug("MTD %s(): 0x%.4x 0x%.4x did not match\n",
 			__func__,
 			unlock_addrs[uaddr].addr1,
 			unlock_addrs[uaddr].addr2);
@@ -2083,15 +2079,13 @@
 	 * FIXME - write a driver that takes all of the chip info as
 	 * module parameters, doesn't probe but forces a load.
 	 */
-	DEBUG( MTD_DEBUG_LEVEL3,
-	       "MTD %s(): check ID's disappear when not in ID mode\n",
+	pr_debug("MTD %s(): check ID's disappear when not in ID mode\n",
 	       __func__ );
 	jedec_reset( base, map, cfi );
 	mfr = jedec_read_mfr( map, base, cfi );
 	id = jedec_read_id( map, base, cfi );
 	if ( mfr == cfi->mfr && id == cfi->id ) {
-		DEBUG( MTD_DEBUG_LEVEL3,
-		       "MTD %s(): ID 0x%.2x:0x%.2x did not change after reset:\n"
+		pr_debug("MTD %s(): ID 0x%.2x:0x%.2x did not change after reset:\n"
 		       "You might need to manually specify JEDEC parameters.\n",
 			__func__, cfi->mfr, cfi->id );
 		goto match_done;
@@ -2104,7 +2098,7 @@
 	 * Put the device back in ID mode - only need to do this if we
 	 * were truly frobbing a real device.
 	 */
-	DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): return to ID mode\n", __func__ );
+	pr_debug("MTD %s(): return to ID mode\n", __func__ );
 	if (cfi->addr_unlock1) {
 		cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
 		cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
@@ -2167,13 +2161,11 @@
 
 		cfi->mfr = jedec_read_mfr(map, base, cfi);
 		cfi->id = jedec_read_id(map, base, cfi);
-		DEBUG(MTD_DEBUG_LEVEL3,
-		      "Search for id:(%02x %02x) interleave(%d) type(%d)\n",
+		pr_debug("Search for id:(%02x %02x) interleave(%d) type(%d)\n",
 			cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type);
 		for (i = 0; i < ARRAY_SIZE(jedec_table); i++) {
 			if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) {
-				DEBUG( MTD_DEBUG_LEVEL3,
-				       "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n",
+				pr_debug("MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n",
 				       __func__, cfi->mfr, cfi->id,
 				       cfi->addr_unlock1, cfi->addr_unlock2 );
 				if (!cfi_jedec_setup(map, cfi, i))
diff -druN linux-libre-3.1-gnu/drivers/mtd/cmdlinepart.c linux-libre-3.2-gnu/drivers/mtd/cmdlinepart.c
--- linux-libre-3.1-gnu/drivers/mtd/cmdlinepart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/cmdlinepart.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,6 +43,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/bootmem.h>
+#include <linux/module.h>
 
 /* error message prefix */
 #define ERRP "mtd: "
@@ -188,10 +189,7 @@
 			     extra_mem_size;
 		parts = kzalloc(alloc_size, GFP_KERNEL);
 		if (!parts)
-		{
-			printk(KERN_ERR ERRP "out of memory\n");
 			return NULL;
-		}
 		extra_mem = (unsigned char *)(parts + *num_parts);
 	}
 	/* enter this partition (offset will be calculated later if it is zero at this point) */
@@ -316,8 +314,8 @@
  * the first one in the chain if a NULL mtd_id is passed in.
  */
 static int parse_cmdline_partitions(struct mtd_info *master,
-                             struct mtd_partition **pparts,
-                             unsigned long origin)
+				    struct mtd_partition **pparts,
+				    struct mtd_part_parser_data *data)
 {
 	unsigned long offset;
 	int i;
diff -druN linux-libre-3.1-gnu/drivers/mtd/devices/doc2000.c linux-libre-3.2-gnu/drivers/mtd/devices/doc2000.c
--- linux-libre-3.1-gnu/drivers/mtd/devices/doc2000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/devices/doc2000.c	2012-01-04 18:55:44.000000000 -0500
@@ -82,8 +82,7 @@
 	void __iomem *docptr = doc->virtadr;
 	unsigned long timeo = jiffies + (HZ * 10);
 
-	DEBUG(MTD_DEBUG_LEVEL3,
-	      "_DoC_WaitReady called for out-of-line wait\n");
+	pr_debug("_DoC_WaitReady called for out-of-line wait\n");
 
 	/* Out-of-line routine to wait for chip response */
 	while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
@@ -92,7 +91,7 @@
 		DoC_Delay(doc, 2);
 
 		if (time_after(jiffies, timeo)) {
-			DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
+			pr_debug("_DoC_WaitReady timed out.\n");
 			return -EIO;
 		}
 		udelay(1);
@@ -323,8 +322,7 @@
 
 	/* Reset the chip */
 	if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) {
-		DEBUG(MTD_DEBUG_LEVEL2,
-		      "DoC_Command (reset) for %d,%d returned true\n",
+		pr_debug("DoC_Command (reset) for %d,%d returned true\n",
 		      floor, chip);
 		return 0;
 	}
@@ -332,8 +330,7 @@
 
 	/* Read the NAND chip ID: 1. Send ReadID command */
 	if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) {
-		DEBUG(MTD_DEBUG_LEVEL2,
-		      "DoC_Command (ReadID) for %d,%d returned true\n",
+		pr_debug("DoC_Command (ReadID) for %d,%d returned true\n",
 		      floor, chip);
 		return 0;
 	}
@@ -699,7 +696,7 @@
 #ifdef ECC_DEBUG
 			printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from);
 #endif
-			/* Read the ECC syndrom through the DiskOnChip ECC
+			/* Read the ECC syndrome through the DiskOnChip ECC
 			   logic.  These syndrome will be all ZERO when there
 			   is no error */
 			for (i = 0; i < 6; i++) {
@@ -930,7 +927,7 @@
 	uint8_t *buf = ops->oobbuf;
 	size_t len = ops->len;
 
-	BUG_ON(ops->mode != MTD_OOB_PLACE);
+	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
 	ofs += ops->ooboffs;
 
@@ -1094,7 +1091,7 @@
 	struct DiskOnChip *this = mtd->priv;
 	int ret;
 
-	BUG_ON(ops->mode != MTD_OOB_PLACE);
+	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
 	mutex_lock(&this->lock);
 	ret = doc_write_oob_nolock(mtd, ofs + ops->ooboffs, ops->len,
diff -druN linux-libre-3.1-gnu/drivers/mtd/devices/doc2001.c linux-libre-3.2-gnu/drivers/mtd/devices/doc2001.c
--- linux-libre-3.1-gnu/drivers/mtd/devices/doc2001.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/devices/doc2001.c	2012-01-04 18:55:44.000000000 -0500
@@ -55,15 +55,14 @@
 {
 	unsigned short c = 0xffff;
 
-	DEBUG(MTD_DEBUG_LEVEL3,
-	      "_DoC_WaitReady called for out-of-line wait\n");
+	pr_debug("_DoC_WaitReady called for out-of-line wait\n");
 
 	/* Out-of-line routine to wait for chip response */
 	while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c)
 		;
 
 	if (c == 0)
-		DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
+		pr_debug("_DoC_WaitReady timed out.\n");
 
 	return (c == 0);
 }
@@ -464,7 +463,7 @@
 #ifdef ECC_DEBUG
 		printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
 #endif
-		/* Read the ECC syndrom through the DiskOnChip ECC logic.
+		/* Read the ECC syndrome through the DiskOnChip ECC logic.
 		   These syndrome will be all ZERO when there is no error */
 		for (i = 0; i < 6; i++) {
 			syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i);
@@ -632,7 +631,7 @@
 	uint8_t *buf = ops->oobbuf;
 	size_t len = ops->len;
 
-	BUG_ON(ops->mode != MTD_OOB_PLACE);
+	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
 	ofs += ops->ooboffs;
 
@@ -690,7 +689,7 @@
 	uint8_t *buf = ops->oobbuf;
 	size_t len = ops->len;
 
-	BUG_ON(ops->mode != MTD_OOB_PLACE);
+	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
 	ofs += ops->ooboffs;
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/devices/doc2001plus.c linux-libre-3.2-gnu/drivers/mtd/devices/doc2001plus.c
--- linux-libre-3.1-gnu/drivers/mtd/devices/doc2001plus.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/devices/doc2001plus.c	2012-01-04 18:55:44.000000000 -0500
@@ -61,15 +61,14 @@
 {
 	unsigned int c = 0xffff;
 
-	DEBUG(MTD_DEBUG_LEVEL3,
-	      "_DoC_WaitReady called for out-of-line wait\n");
+	pr_debug("_DoC_WaitReady called for out-of-line wait\n");
 
 	/* Out-of-line routine to wait for chip response */
 	while (((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) && --c)
 		;
 
 	if (c == 0)
-		DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
+		pr_debug("_DoC_WaitReady timed out.\n");
 
 	return (c == 0);
 }
@@ -655,7 +654,7 @@
 #ifdef ECC_DEBUG
 		printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
 #endif
-		/* Read the ECC syndrom through the DiskOnChip ECC logic.
+		/* Read the ECC syndrome through the DiskOnChip ECC logic.
 		   These syndrome will be all ZERO when there is no error */
 		for (i = 0; i < 6; i++)
 			syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
@@ -835,7 +834,7 @@
 	uint8_t *buf = ops->oobbuf;
 	size_t len = ops->len;
 
-	BUG_ON(ops->mode != MTD_OOB_PLACE);
+	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
 	ofs += ops->ooboffs;
 
@@ -920,7 +919,7 @@
 	uint8_t *buf = ops->oobbuf;
 	size_t len = ops->len;
 
-	BUG_ON(ops->mode != MTD_OOB_PLACE);
+	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
 	ofs += ops->ooboffs;
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/devices/docecc.c linux-libre-3.2-gnu/drivers/mtd/devices/docecc.c
--- linux-libre-3.1-gnu/drivers/mtd/devices/docecc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/devices/docecc.c	2012-01-04 18:55:44.000000000 -0500
@@ -2,7 +2,7 @@
  * ECC algorithm for M-systems disk on chip. We use the excellent Reed
  * Solmon code of Phil Karn (karn@ka9q.ampr.org) available under the
  * GNU GPL License. The rest is simply to convert the disk on chip
- * syndrom into a standard syndom.
+ * syndrome into a standard syndome.
  *
  * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
  * Copyright (C) 2000 Netgem S.A.
diff -druN linux-libre-3.1-gnu/drivers/mtd/devices/docg3.c linux-libre-3.2-gnu/drivers/mtd/devices/docg3.c
--- linux-libre-3.1-gnu/drivers/mtd/devices/docg3.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/mtd/devices/docg3.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1114 @@
+/*
+ * Handles the M-Systems DiskOnChip G3 chip
+ *
+ * Copyright (C) 2011 Robert Jarzmik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/errno.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#define CREATE_TRACE_POINTS
+#include "docg3.h"
+
+/*
+ * This driver handles the DiskOnChip G3 flash memory.
+ *
+ * As no specification is available from M-Systems/Sandisk, this drivers lacks
+ * several functions available on the chip, as :
+ *  - block erase
+ *  - page write
+ *  - IPL write
+ *  - ECC fixing (lack of BCH algorith understanding)
+ *  - powerdown / powerup
+ *
+ * The bus data width (8bits versus 16bits) is not handled (if_cfg flag), and
+ * the driver assumes a 16bits data bus.
+ *
+ * DocG3 relies on 2 ECC algorithms, which are handled in hardware :
+ *  - a 1 byte Hamming code stored in the OOB for each page
+ *  - a 7 bytes BCH code stored in the OOB for each page
+ * The BCH part is only used for check purpose, no correction is available as
+ * some information is missing. What is known is that :
+ *  - BCH is in GF(2^14)
+ *  - BCH is over data of 520 bytes (512 page + 7 page_info bytes
+ *                                   + 1 hamming byte)
+ *  - BCH can correct up to 4 bits (t = 4)
+ *  - BCH syndroms are calculated in hardware, and checked in hardware as well
+ *
+ */
+
+static inline u8 doc_readb(struct docg3 *docg3, u16 reg)
+{
+	u8 val = readb(docg3->base + reg);
+
+	trace_docg3_io(0, 8, reg, (int)val);
+	return val;
+}
+
+static inline u16 doc_readw(struct docg3 *docg3, u16 reg)
+{
+	u16 val = readw(docg3->base + reg);
+
+	trace_docg3_io(0, 16, reg, (int)val);
+	return val;
+}
+
+static inline void doc_writeb(struct docg3 *docg3, u8 val, u16 reg)
+{
+	writeb(val, docg3->base + reg);
+	trace_docg3_io(1, 16, reg, val);
+}
+
+static inline void doc_writew(struct docg3 *docg3, u16 val, u16 reg)
+{
+	writew(val, docg3->base + reg);
+	trace_docg3_io(1, 16, reg, val);
+}
+
+static inline void doc_flash_command(struct docg3 *docg3, u8 cmd)
+{
+	doc_writeb(docg3, cmd, DOC_FLASHCOMMAND);
+}
+
+static inline void doc_flash_sequence(struct docg3 *docg3, u8 seq)
+{
+	doc_writeb(docg3, seq, DOC_FLASHSEQUENCE);
+}
+
+static inline void doc_flash_address(struct docg3 *docg3, u8 addr)
+{
+	doc_writeb(docg3, addr, DOC_FLASHADDRESS);
+}
+
+static char const *part_probes[] = { "cmdlinepart", "saftlpart", NULL };
+
+static int doc_register_readb(struct docg3 *docg3, int reg)
+{
+	u8 val;
+
+	doc_writew(docg3, reg, DOC_READADDRESS);
+	val = doc_readb(docg3, reg);
+	doc_vdbg("Read register %04x : %02x\n", reg, val);
+	return val;
+}
+
+static int doc_register_readw(struct docg3 *docg3, int reg)
+{
+	u16 val;
+
+	doc_writew(docg3, reg, DOC_READADDRESS);
+	val = doc_readw(docg3, reg);
+	doc_vdbg("Read register %04x : %04x\n", reg, val);
+	return val;
+}
+
+/**
+ * doc_delay - delay docg3 operations
+ * @docg3: the device
+ * @nbNOPs: the number of NOPs to issue
+ *
+ * As no specification is available, the right timings between chip commands are
+ * unknown. The only available piece of information are the observed nops on a
+ * working docg3 chip.
+ * Therefore, doc_delay relies on a busy loop of NOPs, instead of scheduler
+ * friendlier msleep() functions or blocking mdelay().
+ */
+static void doc_delay(struct docg3 *docg3, int nbNOPs)
+{
+	int i;
+
+	doc_dbg("NOP x %d\n", nbNOPs);
+	for (i = 0; i < nbNOPs; i++)
+		doc_writeb(docg3, 0, DOC_NOP);
+}
+
+static int is_prot_seq_error(struct docg3 *docg3)
+{
+	int ctrl;
+
+	ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+	return ctrl & (DOC_CTRL_PROTECTION_ERROR | DOC_CTRL_SEQUENCE_ERROR);
+}
+
+static int doc_is_ready(struct docg3 *docg3)
+{
+	int ctrl;
+
+	ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+	return ctrl & DOC_CTRL_FLASHREADY;
+}
+
+static int doc_wait_ready(struct docg3 *docg3)
+{
+	int maxWaitCycles = 100;
+
+	do {
+		doc_delay(docg3, 4);
+		cpu_relax();
+	} while (!doc_is_ready(docg3) && maxWaitCycles--);
+	doc_delay(docg3, 2);
+	if (maxWaitCycles > 0)
+		return 0;
+	else
+		return -EIO;
+}
+
+static int doc_reset_seq(struct docg3 *docg3)
+{
+	int ret;
+
+	doc_writeb(docg3, 0x10, DOC_FLASHCONTROL);
+	doc_flash_sequence(docg3, DOC_SEQ_RESET);
+	doc_flash_command(docg3, DOC_CMD_RESET);
+	doc_delay(docg3, 2);
+	ret = doc_wait_ready(docg3);
+
+	doc_dbg("doc_reset_seq() -> isReady=%s\n", ret ? "false" : "true");
+	return ret;
+}
+
+/**
+ * doc_read_data_area - Read data from data area
+ * @docg3: the device
+ * @buf: the buffer to fill in
+ * @len: the lenght to read
+ * @first: first time read, DOC_READADDRESS should be set
+ *
+ * Reads bytes from flash data. Handles the single byte / even bytes reads.
+ */
+static void doc_read_data_area(struct docg3 *docg3, void *buf, int len,
+			       int first)
+{
+	int i, cdr, len4;
+	u16 data16, *dst16;
+	u8 data8, *dst8;
+
+	doc_dbg("doc_read_data_area(buf=%p, len=%d)\n", buf, len);
+	cdr = len & 0x3;
+	len4 = len - cdr;
+
+	if (first)
+		doc_writew(docg3, DOC_IOSPACE_DATA, DOC_READADDRESS);
+	dst16 = buf;
+	for (i = 0; i < len4; i += 2) {
+		data16 = doc_readw(docg3, DOC_IOSPACE_DATA);
+		*dst16 = data16;
+		dst16++;
+	}
+
+	if (cdr) {
+		doc_writew(docg3, DOC_IOSPACE_DATA | DOC_READADDR_ONE_BYTE,
+			   DOC_READADDRESS);
+		doc_delay(docg3, 1);
+		dst8 = (u8 *)dst16;
+		for (i = 0; i < cdr; i++) {
+			data8 = doc_readb(docg3, DOC_IOSPACE_DATA);
+			*dst8 = data8;
+			dst8++;
+		}
+	}
+}
+
+/**
+ * doc_set_data_mode - Sets the flash to reliable data mode
+ * @docg3: the device
+ *
+ * The reliable data mode is a bit slower than the fast mode, but less errors
+ * occur.  Entering the reliable mode cannot be done without entering the fast
+ * mode first.
+ */
+static void doc_set_reliable_mode(struct docg3 *docg3)
+{
+	doc_dbg("doc_set_reliable_mode()\n");
+	doc_flash_sequence(docg3, DOC_SEQ_SET_MODE);
+	doc_flash_command(docg3, DOC_CMD_FAST_MODE);
+	doc_flash_command(docg3, DOC_CMD_RELIABLE_MODE);
+	doc_delay(docg3, 2);
+}
+
+/**
+ * doc_set_asic_mode - Set the ASIC mode
+ * @docg3: the device
+ * @mode: the mode
+ *
+ * The ASIC can work in 3 modes :
+ *  - RESET: all registers are zeroed
+ *  - NORMAL: receives and handles commands
+ *  - POWERDOWN: minimal poweruse, flash parts shut off
+ */
+static void doc_set_asic_mode(struct docg3 *docg3, u8 mode)
+{
+	int i;
+
+	for (i = 0; i < 12; i++)
+		doc_readb(docg3, DOC_IOSPACE_IPL);
+
+	mode |= DOC_ASICMODE_MDWREN;
+	doc_dbg("doc_set_asic_mode(%02x)\n", mode);
+	doc_writeb(docg3, mode, DOC_ASICMODE);
+	doc_writeb(docg3, ~mode, DOC_ASICMODECONFIRM);
+	doc_delay(docg3, 1);
+}
+
+/**
+ * doc_set_device_id - Sets the devices id for cascaded G3 chips
+ * @docg3: the device
+ * @id: the chip to select (amongst 0, 1, 2, 3)
+ *
+ * There can be 4 cascaded G3 chips. This function selects the one which will
+ * should be the active one.
+ */
+static void doc_set_device_id(struct docg3 *docg3, int id)
+{
+	u8 ctrl;
+
+	doc_dbg("doc_set_device_id(%d)\n", id);
+	doc_writeb(docg3, id, DOC_DEVICESELECT);
+	ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+
+	ctrl &= ~DOC_CTRL_VIOLATION;
+	ctrl |= DOC_CTRL_CE;
+	doc_writeb(docg3, ctrl, DOC_FLASHCONTROL);
+}
+
+/**
+ * doc_set_extra_page_mode - Change flash page layout
+ * @docg3: the device
+ *
+ * Normally, the flash page is split into the data (512 bytes) and the out of
+ * band data (16 bytes). For each, 4 more bytes can be accessed, where the wear
+ * leveling counters are stored.  To access this last area of 4 bytes, a special
+ * mode must be input to the flash ASIC.
+ *
+ * Returns 0 if no error occured, -EIO else.
+ */
+static int doc_set_extra_page_mode(struct docg3 *docg3)
+{
+	int fctrl;
+
+	doc_dbg("doc_set_extra_page_mode()\n");
+	doc_flash_sequence(docg3, DOC_SEQ_PAGE_SIZE_532);
+	doc_flash_command(docg3, DOC_CMD_PAGE_SIZE_532);
+	doc_delay(docg3, 2);
+
+	fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+	if (fctrl & (DOC_CTRL_PROTECTION_ERROR | DOC_CTRL_SEQUENCE_ERROR))
+		return -EIO;
+	else
+		return 0;
+}
+
+/**
+ * doc_seek - Set both flash planes to the specified block, page for reading
+ * @docg3: the device
+ * @block0: the first plane block index
+ * @block1: the second plane block index
+ * @page: the page index within the block
+ * @wear: if true, read will occur on the 4 extra bytes of the wear area
+ * @ofs: offset in page to read
+ *
+ * Programs the flash even and odd planes to the specific block and page.
+ * Alternatively, programs the flash to the wear area of the specified page.
+ */
+static int doc_read_seek(struct docg3 *docg3, int block0, int block1, int page,
+			 int wear, int ofs)
+{
+	int sector, ret = 0;
+
+	doc_dbg("doc_seek(blocks=(%d,%d), page=%d, ofs=%d, wear=%d)\n",
+		block0, block1, page, ofs, wear);
+
+	if (!wear && (ofs < 2 * DOC_LAYOUT_PAGE_SIZE)) {
+		doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE1);
+		doc_flash_command(docg3, DOC_CMD_READ_PLANE1);
+		doc_delay(docg3, 2);
+	} else {
+		doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE2);
+		doc_flash_command(docg3, DOC_CMD_READ_PLANE2);
+		doc_delay(docg3, 2);
+	}
+
+	doc_set_reliable_mode(docg3);
+	if (wear)
+		ret = doc_set_extra_page_mode(docg3);
+	if (ret)
+		goto out;
+
+	sector = (block0 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
+	doc_flash_sequence(docg3, DOC_SEQ_READ);
+	doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR);
+	doc_delay(docg3, 1);
+	doc_flash_address(docg3, sector & 0xff);
+	doc_flash_address(docg3, (sector >> 8) & 0xff);
+	doc_flash_address(docg3, (sector >> 16) & 0xff);
+	doc_delay(docg3, 1);
+
+	sector = (block1 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
+	doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR);
+	doc_delay(docg3, 1);
+	doc_flash_address(docg3, sector & 0xff);
+	doc_flash_address(docg3, (sector >> 8) & 0xff);
+	doc_flash_address(docg3, (sector >> 16) & 0xff);
+	doc_delay(docg3, 2);
+
+out:
+	return ret;
+}
+
+/**
+ * doc_read_page_ecc_init - Initialize hardware ECC engine
+ * @docg3: the device
+ * @len: the number of bytes covered by the ECC (BCH covered)
+ *
+ * The function does initialize the hardware ECC engine to compute the Hamming
+ * ECC (on 1 byte) and the BCH Syndroms (on 7 bytes).
+ *
+ * Return 0 if succeeded, -EIO on error
+ */
+static int doc_read_page_ecc_init(struct docg3 *docg3, int len)
+{
+	doc_writew(docg3, DOC_ECCCONF0_READ_MODE
+		   | DOC_ECCCONF0_BCH_ENABLE | DOC_ECCCONF0_HAMMING_ENABLE
+		   | (len & DOC_ECCCONF0_DATA_BYTES_MASK),
+		   DOC_ECCCONF0);
+	doc_delay(docg3, 4);
+	doc_register_readb(docg3, DOC_FLASHCONTROL);
+	return doc_wait_ready(docg3);
+}
+
+/**
+ * doc_read_page_prepare - Prepares reading data from a flash page
+ * @docg3: the device
+ * @block0: the first plane block index on flash memory
+ * @block1: the second plane block index on flash memory
+ * @page: the page index in the block
+ * @offset: the offset in the page (must be a multiple of 4)
+ *
+ * Prepares the page to be read in the flash memory :
+ *   - tell ASIC to map the flash pages
+ *   - tell ASIC to be in read mode
+ *
+ * After a call to this method, a call to doc_read_page_finish is mandatory,
+ * to end the read cycle of the flash.
+ *
+ * Read data from a flash page. The length to be read must be between 0 and
+ * (page_size + oob_size + wear_size), ie. 532, and a multiple of 4 (because
+ * the extra bytes reading is not implemented).
+ *
+ * As pages are grouped by 2 (in 2 planes), reading from a page must be done
+ * in two steps:
+ *  - one read of 512 bytes at offset 0
+ *  - one read of 512 bytes at offset 512 + 16
+ *
+ * Returns 0 if successful, -EIO if a read error occured.
+ */
+static int doc_read_page_prepare(struct docg3 *docg3, int block0, int block1,
+				 int page, int offset)
+{
+	int wear_area = 0, ret = 0;
+
+	doc_dbg("doc_read_page_prepare(blocks=(%d,%d), page=%d, ofsInPage=%d)\n",
+		block0, block1, page, offset);
+	if (offset >= DOC_LAYOUT_WEAR_OFFSET)
+		wear_area = 1;
+	if (!wear_area && offset > (DOC_LAYOUT_PAGE_OOB_SIZE * 2))
+		return -EINVAL;
+
+	doc_set_device_id(docg3, docg3->device_id);
+	ret = doc_reset_seq(docg3);
+	if (ret)
+		goto err;
+
+	/* Program the flash address block and page */
+	ret = doc_read_seek(docg3, block0, block1, page, wear_area, offset);
+	if (ret)
+		goto err;
+
+	doc_flash_command(docg3, DOC_CMD_READ_ALL_PLANES);
+	doc_delay(docg3, 2);
+	doc_wait_ready(docg3);
+
+	doc_flash_command(docg3, DOC_CMD_SET_ADDR_READ);
+	doc_delay(docg3, 1);
+	if (offset >= DOC_LAYOUT_PAGE_SIZE * 2)
+		offset -= 2 * DOC_LAYOUT_PAGE_SIZE;
+	doc_flash_address(docg3, offset >> 2);
+	doc_delay(docg3, 1);
+	doc_wait_ready(docg3);
+
+	doc_flash_command(docg3, DOC_CMD_READ_FLASH);
+
+	return 0;
+err:
+	doc_writeb(docg3, 0, DOC_DATAEND);
+	doc_delay(docg3, 2);
+	return -EIO;
+}
+
+/**
+ * doc_read_page_getbytes - Reads bytes from a prepared page
+ * @docg3: the device
+ * @len: the number of bytes to be read (must be a multiple of 4)
+ * @buf: the buffer to be filled in
+ * @first: 1 if first time read, DOC_READADDRESS should be set
+ *
+ */
+static int doc_read_page_getbytes(struct docg3 *docg3, int len, u_char *buf,
+				  int first)
+{
+	doc_read_data_area(docg3, buf, len, first);
+	doc_delay(docg3, 2);
+	return len;
+}
+
+/**
+ * doc_get_hw_bch_syndroms - Get hardware calculated BCH syndroms
+ * @docg3: the device
+ * @syns:  the array of 7 integers where the syndroms will be stored
+ */
+static void doc_get_hw_bch_syndroms(struct docg3 *docg3, int *syns)
+{
+	int i;
+
+	for (i = 0; i < DOC_ECC_BCH_SIZE; i++)
+		syns[i] = doc_register_readb(docg3, DOC_BCH_SYNDROM(i));
+}
+
+/**
+ * doc_read_page_finish - Ends reading of a flash page
+ * @docg3: the device
+ *
+ * As a side effect, resets the chip selector to 0. This ensures that after each
+ * read operation, the floor 0 is selected. Therefore, if the systems halts, the
+ * reboot will boot on floor 0, where the IPL is.
+ */
+static void doc_read_page_finish(struct docg3 *docg3)
+{
+	doc_writeb(docg3, 0, DOC_DATAEND);
+	doc_delay(docg3, 2);
+	doc_set_device_id(docg3, 0);
+}
+
+/**
+ * calc_block_sector - Calculate blocks, pages and ofs.
+
+ * @from: offset in flash
+ * @block0: first plane block index calculated
+ * @block1: second plane block index calculated
+ * @page: page calculated
+ * @ofs: offset in page
+ */
+static void calc_block_sector(loff_t from, int *block0, int *block1, int *page,
+			      int *ofs)
+{
+	uint sector;
+
+	sector = from / DOC_LAYOUT_PAGE_SIZE;
+	*block0 = sector / (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES)
+		* DOC_LAYOUT_NBPLANES;
+	*block1 = *block0 + 1;
+	*page = sector % (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES);
+	*page /= DOC_LAYOUT_NBPLANES;
+	if (sector % 2)
+		*ofs = DOC_LAYOUT_PAGE_OOB_SIZE;
+	else
+		*ofs = 0;
+}
+
+/**
+ * doc_read - Read bytes from flash
+ * @mtd: the device
+ * @from: the offset from first block and first page, in bytes, aligned on page
+ *        size
+ * @len: the number of bytes to read (must be a multiple of 4)
+ * @retlen: the number of bytes actually read
+ * @buf: the filled in buffer
+ *
+ * Reads flash memory pages. This function does not read the OOB chunk, but only
+ * the page data.
+ *
+ * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured
+ */
+static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
+	     size_t *retlen, u_char *buf)
+{
+	struct docg3 *docg3 = mtd->priv;
+	int block0, block1, page, readlen, ret, ofs = 0;
+	int syn[DOC_ECC_BCH_SIZE], eccconf1;
+	u8 oob[DOC_LAYOUT_OOB_SIZE];
+
+	ret = -EINVAL;
+	doc_dbg("doc_read(from=%lld, len=%zu, buf=%p)\n", from, len, buf);
+	if (from % DOC_LAYOUT_PAGE_SIZE)
+		goto err;
+	if (len % 4)
+		goto err;
+	calc_block_sector(from, &block0, &block1, &page, &ofs);
+	if (block1 > docg3->max_block)
+		goto err;
+
+	*retlen = 0;
+	ret = 0;
+	readlen = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE);
+	while (!ret && len > 0) {
+		readlen = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE);
+		ret = doc_read_page_prepare(docg3, block0, block1, page, ofs);
+		if (ret < 0)
+			goto err;
+		ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_COVERED_BYTES);
+		if (ret < 0)
+			goto err_in_read;
+		ret = doc_read_page_getbytes(docg3, readlen, buf, 1);
+		if (ret < readlen)
+			goto err_in_read;
+		ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE,
+					     oob, 0);
+		if (ret < DOC_LAYOUT_OOB_SIZE)
+			goto err_in_read;
+
+		*retlen += readlen;
+		buf += readlen;
+		len -= readlen;
+
+		ofs ^= DOC_LAYOUT_PAGE_OOB_SIZE;
+		if (ofs == 0)
+			page += 2;
+		if (page > DOC_ADDR_PAGE_MASK) {
+			page = 0;
+			block0 += 2;
+			block1 += 2;
+		}
+
+		/*
+		 * There should be a BCH bitstream fixing algorithm here ...
+		 * By now, a page read failure is triggered by BCH error
+		 */
+		doc_get_hw_bch_syndroms(docg3, syn);
+		eccconf1 = doc_register_readb(docg3, DOC_ECCCONF1);
+
+		doc_dbg("OOB - INFO: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+			 oob[0], oob[1], oob[2], oob[3], oob[4],
+			 oob[5], oob[6]);
+		doc_dbg("OOB - HAMMING: %02x\n", oob[7]);
+		doc_dbg("OOB - BCH_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+			 oob[8], oob[9], oob[10], oob[11], oob[12],
+			 oob[13], oob[14]);
+		doc_dbg("OOB - UNUSED: %02x\n", oob[15]);
+		doc_dbg("ECC checks: ECCConf1=%x\n", eccconf1);
+		doc_dbg("ECC BCH syndrom: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+			syn[0], syn[1], syn[2], syn[3], syn[4], syn[5], syn[6]);
+
+		ret = -EBADMSG;
+		if (block0 >= DOC_LAYOUT_BLOCK_FIRST_DATA) {
+			if (eccconf1 & DOC_ECCCONF1_BCH_SYNDROM_ERR)
+				goto err_in_read;
+			if (is_prot_seq_error(docg3))
+				goto err_in_read;
+		}
+		doc_read_page_finish(docg3);
+	}
+
+	return 0;
+err_in_read:
+	doc_read_page_finish(docg3);
+err:
+	return ret;
+}
+
+/**
+ * doc_read_oob - Read out of band bytes from flash
+ * @mtd: the device
+ * @from: the offset from first block and first page, in bytes, aligned on page
+ *        size
+ * @ops: the mtd oob structure
+ *
+ * Reads flash memory OOB area of pages.
+ *
+ * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured
+ */
+static int doc_read_oob(struct mtd_info *mtd, loff_t from,
+			struct mtd_oob_ops *ops)
+{
+	struct docg3 *docg3 = mtd->priv;
+	int block0, block1, page, ofs, ret;
+	u8 *buf = ops->oobbuf;
+	size_t len = ops->ooblen;
+
+	doc_dbg("doc_read_oob(from=%lld, buf=%p, len=%zu)\n", from, buf, len);
+	if (len != DOC_LAYOUT_OOB_SIZE)
+		return -EINVAL;
+
+	switch (ops->mode) {
+	case MTD_OPS_PLACE_OOB:
+		buf += ops->ooboffs;
+		break;
+	default:
+		break;
+	}
+
+	calc_block_sector(from, &block0, &block1, &page, &ofs);
+	if (block1 > docg3->max_block)
+		return -EINVAL;
+
+	ret = doc_read_page_prepare(docg3, block0, block1, page,
+				    ofs + DOC_LAYOUT_PAGE_SIZE);
+	if (!ret)
+		ret = doc_read_page_ecc_init(docg3, DOC_LAYOUT_OOB_SIZE);
+	if (!ret)
+		ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE,
+					     buf, 1);
+	doc_read_page_finish(docg3);
+
+	if (ret > 0)
+		ops->oobretlen = ret;
+	else
+		ops->oobretlen = 0;
+	return (ret > 0) ? 0 : ret;
+}
+
+static int doc_reload_bbt(struct docg3 *docg3)
+{
+	int block = DOC_LAYOUT_BLOCK_BBT;
+	int ret = 0, nbpages, page;
+	u_char *buf = docg3->bbt;
+
+	nbpages = DIV_ROUND_UP(docg3->max_block + 1, 8 * DOC_LAYOUT_PAGE_SIZE);
+	for (page = 0; !ret && (page < nbpages); page++) {
+		ret = doc_read_page_prepare(docg3, block, block + 1,
+					    page + DOC_LAYOUT_PAGE_BBT, 0);
+		if (!ret)
+			ret = doc_read_page_ecc_init(docg3,
+						     DOC_LAYOUT_PAGE_SIZE);
+		if (!ret)
+			doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE,
+					       buf, 1);
+		buf += DOC_LAYOUT_PAGE_SIZE;
+	}
+	doc_read_page_finish(docg3);
+	return ret;
+}
+
+/**
+ * doc_block_isbad - Checks whether a block is good or not
+ * @mtd: the device
+ * @from: the offset to find the correct block
+ *
+ * Returns 1 if block is bad, 0 if block is good
+ */
+static int doc_block_isbad(struct mtd_info *mtd, loff_t from)
+{
+	struct docg3 *docg3 = mtd->priv;
+	int block0, block1, page, ofs, is_good;
+
+	calc_block_sector(from, &block0, &block1, &page, &ofs);
+	doc_dbg("doc_block_isbad(from=%lld) => block=(%d,%d), page=%d, ofs=%d\n",
+		from, block0, block1, page, ofs);
+
+	if (block0 < DOC_LAYOUT_BLOCK_FIRST_DATA)
+		return 0;
+	if (block1 > docg3->max_block)
+		return -EINVAL;
+
+	is_good = docg3->bbt[block0 >> 3] & (1 << (block0 & 0x7));
+	return !is_good;
+}
+
+/**
+ * doc_get_erase_count - Get block erase count
+ * @docg3: the device
+ * @from: the offset in which the block is.
+ *
+ * Get the number of times a block was erased. The number is the maximum of
+ * erase times between first and second plane (which should be equal normally).
+ *
+ * Returns The number of erases, or -EINVAL or -EIO on error.
+ */
+static int doc_get_erase_count(struct docg3 *docg3, loff_t from)
+{
+	u8 buf[DOC_LAYOUT_WEAR_SIZE];
+	int ret, plane1_erase_count, plane2_erase_count;
+	int block0, block1, page, ofs;
+
+	doc_dbg("doc_get_erase_count(from=%lld, buf=%p)\n", from, buf);
+	if (from % DOC_LAYOUT_PAGE_SIZE)
+		return -EINVAL;
+	calc_block_sector(from, &block0, &block1, &page, &ofs);
+	if (block1 > docg3->max_block)
+		return -EINVAL;
+
+	ret = doc_reset_seq(docg3);
+	if (!ret)
+		ret = doc_read_page_prepare(docg3, block0, block1, page,
+					    ofs + DOC_LAYOUT_WEAR_OFFSET);
+	if (!ret)
+		ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_WEAR_SIZE,
+					     buf, 1);
+	doc_read_page_finish(docg3);
+
+	if (ret || (buf[0] != DOC_ERASE_MARK) || (buf[2] != DOC_ERASE_MARK))
+		return -EIO;
+	plane1_erase_count = (u8)(~buf[1]) | ((u8)(~buf[4]) << 8)
+		| ((u8)(~buf[5]) << 16);
+	plane2_erase_count = (u8)(~buf[3]) | ((u8)(~buf[6]) << 8)
+		| ((u8)(~buf[7]) << 16);
+
+	return max(plane1_erase_count, plane2_erase_count);
+}
+
+/*
+ * Debug sysfs entries
+ */
+static int dbg_flashctrl_show(struct seq_file *s, void *p)
+{
+	struct docg3 *docg3 = (struct docg3 *)s->private;
+
+	int pos = 0;
+	u8 fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+
+	pos += seq_printf(s,
+		 "FlashControl : 0x%02x (%s,CE# %s,%s,%s,flash %s)\n",
+		 fctrl,
+		 fctrl & DOC_CTRL_VIOLATION ? "protocol violation" : "-",
+		 fctrl & DOC_CTRL_CE ? "active" : "inactive",
+		 fctrl & DOC_CTRL_PROTECTION_ERROR ? "protection error" : "-",
+		 fctrl & DOC_CTRL_SEQUENCE_ERROR ? "sequence error" : "-",
+		 fctrl & DOC_CTRL_FLASHREADY ? "ready" : "not ready");
+	return pos;
+}
+DEBUGFS_RO_ATTR(flashcontrol, dbg_flashctrl_show);
+
+static int dbg_asicmode_show(struct seq_file *s, void *p)
+{
+	struct docg3 *docg3 = (struct docg3 *)s->private;
+
+	int pos = 0;
+	int pctrl = doc_register_readb(docg3, DOC_ASICMODE);
+	int mode = pctrl & 0x03;
+
+	pos += seq_printf(s,
+			 "%04x : RAM_WE=%d,RSTIN_RESET=%d,BDETCT_RESET=%d,WRITE_ENABLE=%d,POWERDOWN=%d,MODE=%d%d (",
+			 pctrl,
+			 pctrl & DOC_ASICMODE_RAM_WE ? 1 : 0,
+			 pctrl & DOC_ASICMODE_RSTIN_RESET ? 1 : 0,
+			 pctrl & DOC_ASICMODE_BDETCT_RESET ? 1 : 0,
+			 pctrl & DOC_ASICMODE_MDWREN ? 1 : 0,
+			 pctrl & DOC_ASICMODE_POWERDOWN ? 1 : 0,
+			 mode >> 1, mode & 0x1);
+
+	switch (mode) {
+	case DOC_ASICMODE_RESET:
+		pos += seq_printf(s, "reset");
+		break;
+	case DOC_ASICMODE_NORMAL:
+		pos += seq_printf(s, "normal");
+		break;
+	case DOC_ASICMODE_POWERDOWN:
+		pos += seq_printf(s, "powerdown");
+		break;
+	}
+	pos += seq_printf(s, ")\n");
+	return pos;
+}
+DEBUGFS_RO_ATTR(asic_mode, dbg_asicmode_show);
+
+static int dbg_device_id_show(struct seq_file *s, void *p)
+{
+	struct docg3 *docg3 = (struct docg3 *)s->private;
+	int pos = 0;
+	int id = doc_register_readb(docg3, DOC_DEVICESELECT);
+
+	pos += seq_printf(s, "DeviceId = %d\n", id);
+	return pos;
+}
+DEBUGFS_RO_ATTR(device_id, dbg_device_id_show);
+
+static int dbg_protection_show(struct seq_file *s, void *p)
+{
+	struct docg3 *docg3 = (struct docg3 *)s->private;
+	int pos = 0;
+	int protect = doc_register_readb(docg3, DOC_PROTECTION);
+	int dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS);
+	int dps0_low = doc_register_readb(docg3, DOC_DPS0_ADDRLOW);
+	int dps0_high = doc_register_readb(docg3, DOC_DPS0_ADDRHIGH);
+	int dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS);
+	int dps1_low = doc_register_readb(docg3, DOC_DPS1_ADDRLOW);
+	int dps1_high = doc_register_readb(docg3, DOC_DPS1_ADDRHIGH);
+
+	pos += seq_printf(s, "Protection = 0x%02x (",
+			 protect);
+	if (protect & DOC_PROTECT_FOUNDRY_OTP_LOCK)
+		pos += seq_printf(s, "FOUNDRY_OTP_LOCK,");
+	if (protect & DOC_PROTECT_CUSTOMER_OTP_LOCK)
+		pos += seq_printf(s, "CUSTOMER_OTP_LOCK,");
+	if (protect & DOC_PROTECT_LOCK_INPUT)
+		pos += seq_printf(s, "LOCK_INPUT,");
+	if (protect & DOC_PROTECT_STICKY_LOCK)
+		pos += seq_printf(s, "STICKY_LOCK,");
+	if (protect & DOC_PROTECT_PROTECTION_ENABLED)
+		pos += seq_printf(s, "PROTECTION ON,");
+	if (protect & DOC_PROTECT_IPL_DOWNLOAD_LOCK)
+		pos += seq_printf(s, "IPL_DOWNLOAD_LOCK,");
+	if (protect & DOC_PROTECT_PROTECTION_ERROR)
+		pos += seq_printf(s, "PROTECT_ERR,");
+	else
+		pos += seq_printf(s, "NO_PROTECT_ERR");
+	pos += seq_printf(s, ")\n");
+
+	pos += seq_printf(s, "DPS0 = 0x%02x : "
+			 "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, "
+			 "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n",
+			 dps0, dps0_low, dps0_high,
+			 !!(dps0 & DOC_DPS_OTP_PROTECTED),
+			 !!(dps0 & DOC_DPS_READ_PROTECTED),
+			 !!(dps0 & DOC_DPS_WRITE_PROTECTED),
+			 !!(dps0 & DOC_DPS_HW_LOCK_ENABLED),
+			 !!(dps0 & DOC_DPS_KEY_OK));
+	pos += seq_printf(s, "DPS1 = 0x%02x : "
+			 "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, "
+			 "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n",
+			 dps1, dps1_low, dps1_high,
+			 !!(dps1 & DOC_DPS_OTP_PROTECTED),
+			 !!(dps1 & DOC_DPS_READ_PROTECTED),
+			 !!(dps1 & DOC_DPS_WRITE_PROTECTED),
+			 !!(dps1 & DOC_DPS_HW_LOCK_ENABLED),
+			 !!(dps1 & DOC_DPS_KEY_OK));
+	return pos;
+}
+DEBUGFS_RO_ATTR(protection, dbg_protection_show);
+
+static int __init doc_dbg_register(struct docg3 *docg3)
+{
+	struct dentry *root, *entry;
+
+	root = debugfs_create_dir("docg3", NULL);
+	if (!root)
+		return -ENOMEM;
+
+	entry = debugfs_create_file("flashcontrol", S_IRUSR, root, docg3,
+				  &flashcontrol_fops);
+	if (entry)
+		entry = debugfs_create_file("asic_mode", S_IRUSR, root,
+					    docg3, &asic_mode_fops);
+	if (entry)
+		entry = debugfs_create_file("device_id", S_IRUSR, root,
+					    docg3, &device_id_fops);
+	if (entry)
+		entry = debugfs_create_file("protection", S_IRUSR, root,
+					    docg3, &protection_fops);
+	if (entry) {
+		docg3->debugfs_root = root;
+		return 0;
+	} else {
+		debugfs_remove_recursive(root);
+		return -ENOMEM;
+	}
+}
+
+static void __exit doc_dbg_unregister(struct docg3 *docg3)
+{
+	debugfs_remove_recursive(docg3->debugfs_root);
+}
+
+/**
+ * doc_set_driver_info - Fill the mtd_info structure and docg3 structure
+ * @chip_id: The chip ID of the supported chip
+ * @mtd: The structure to fill
+ */
+static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd)
+{
+	struct docg3 *docg3 = mtd->priv;
+	int cfg;
+
+	cfg = doc_register_readb(docg3, DOC_CONFIGURATION);
+	docg3->if_cfg = (cfg & DOC_CONF_IF_CFG ? 1 : 0);
+
+	switch (chip_id) {
+	case DOC_CHIPID_G3:
+		mtd->name = "DiskOnChip G3";
+		docg3->max_block = 2047;
+		break;
+	}
+	mtd->type = MTD_NANDFLASH;
+	/*
+	 * Once write methods are added, the correct flags will be set.
+	 * mtd->flags = MTD_CAP_NANDFLASH;
+	 */
+	mtd->flags = MTD_CAP_ROM;
+	mtd->size = (docg3->max_block + 1) * DOC_LAYOUT_BLOCK_SIZE;
+	mtd->erasesize = DOC_LAYOUT_BLOCK_SIZE * DOC_LAYOUT_NBPLANES;
+	mtd->writesize = DOC_LAYOUT_PAGE_SIZE;
+	mtd->oobsize = DOC_LAYOUT_OOB_SIZE;
+	mtd->owner = THIS_MODULE;
+	mtd->erase = NULL;
+	mtd->point = NULL;
+	mtd->unpoint = NULL;
+	mtd->read = doc_read;
+	mtd->write = NULL;
+	mtd->read_oob = doc_read_oob;
+	mtd->write_oob = NULL;
+	mtd->sync = NULL;
+	mtd->block_isbad = doc_block_isbad;
+}
+
+/**
+ * doc_probe - Probe the IO space for a DiskOnChip G3 chip
+ * @pdev: platform device
+ *
+ * Probes for a G3 chip at the specified IO space in the platform data
+ * ressources.
+ *
+ * Returns 0 on success, -ENOMEM, -ENXIO on error
+ */
+static int __init docg3_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct docg3 *docg3;
+	struct mtd_info *mtd;
+	struct resource *ress;
+	int ret, bbt_nbpages;
+	u16 chip_id, chip_id_inv;
+
+	ret = -ENOMEM;
+	docg3 = kzalloc(sizeof(struct docg3), GFP_KERNEL);
+	if (!docg3)
+		goto nomem1;
+	mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
+	if (!mtd)
+		goto nomem2;
+	mtd->priv = docg3;
+
+	ret = -ENXIO;
+	ress = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!ress) {
+		dev_err(dev, "No I/O memory resource defined\n");
+		goto noress;
+	}
+	docg3->base = ioremap(ress->start, DOC_IOSPACE_SIZE);
+
+	docg3->dev = &pdev->dev;
+	docg3->device_id = 0;
+	doc_set_device_id(docg3, docg3->device_id);
+	doc_set_asic_mode(docg3, DOC_ASICMODE_RESET);
+	doc_set_asic_mode(docg3, DOC_ASICMODE_NORMAL);
+
+	chip_id = doc_register_readw(docg3, DOC_CHIPID);
+	chip_id_inv = doc_register_readw(docg3, DOC_CHIPID_INV);
+
+	ret = -ENODEV;
+	if (chip_id != (u16)(~chip_id_inv)) {
+		doc_info("No device found at IO addr %p\n",
+			 (void *)ress->start);
+		goto nochipfound;
+	}
+
+	switch (chip_id) {
+	case DOC_CHIPID_G3:
+		doc_info("Found a G3 DiskOnChip at addr %p\n",
+			 (void *)ress->start);
+		break;
+	default:
+		doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id);
+		goto nochipfound;
+	}
+
+	doc_set_driver_info(chip_id, mtd);
+	platform_set_drvdata(pdev, mtd);
+
+	ret = -ENOMEM;
+	bbt_nbpages = DIV_ROUND_UP(docg3->max_block + 1,
+				   8 * DOC_LAYOUT_PAGE_SIZE);
+	docg3->bbt = kzalloc(bbt_nbpages * DOC_LAYOUT_PAGE_SIZE, GFP_KERNEL);
+	if (!docg3->bbt)
+		goto nochipfound;
+	doc_reload_bbt(docg3);
+
+	ret = mtd_device_parse_register(mtd, part_probes,
+					NULL, NULL, 0);
+	if (ret)
+		goto register_error;
+
+	doc_dbg_register(docg3);
+	return 0;
+
+register_error:
+	kfree(docg3->bbt);
+nochipfound:
+	iounmap(docg3->base);
+noress:
+	kfree(mtd);
+nomem2:
+	kfree(docg3);
+nomem1:
+	return ret;
+}
+
+/**
+ * docg3_release - Release the driver
+ * @pdev: the platform device
+ *
+ * Returns 0
+ */
+static int __exit docg3_release(struct platform_device *pdev)
+{
+	struct mtd_info *mtd = platform_get_drvdata(pdev);
+	struct docg3 *docg3 = mtd->priv;
+
+	doc_dbg_unregister(docg3);
+	mtd_device_unregister(mtd);
+	iounmap(docg3->base);
+	kfree(docg3->bbt);
+	kfree(docg3);
+	kfree(mtd);
+	return 0;
+}
+
+static struct platform_driver g3_driver = {
+	.driver		= {
+		.name	= "docg3",
+		.owner	= THIS_MODULE,
+	},
+	.remove		= __exit_p(docg3_release),
+};
+
+static int __init docg3_init(void)
+{
+	return platform_driver_probe(&g3_driver, docg3_probe);
+}
+module_init(docg3_init);
+
+
+static void __exit docg3_exit(void)
+{
+	platform_driver_unregister(&g3_driver);
+}
+module_exit(docg3_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>");
+MODULE_DESCRIPTION("MTD driver for DiskOnChip G3");
diff -druN linux-libre-3.1-gnu/drivers/mtd/devices/docg3.h linux-libre-3.2-gnu/drivers/mtd/devices/docg3.h
--- linux-libre-3.1-gnu/drivers/mtd/devices/docg3.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/mtd/devices/docg3.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,297 @@
+/*
+ * Handles the M-Systems DiskOnChip G3 chip
+ *
+ * Copyright (C) 2011 Robert Jarzmik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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 _MTD_DOCG3_H
+#define _MTD_DOCG3_H
+
+/*
+ * Flash memory areas :
+ *   - 0x0000 .. 0x07ff : IPL
+ *   - 0x0800 .. 0x0fff : Data area
+ *   - 0x1000 .. 0x17ff : Registers
+ *   - 0x1800 .. 0x1fff : Unknown
+ */
+#define DOC_IOSPACE_IPL			0x0000
+#define DOC_IOSPACE_DATA		0x0800
+#define DOC_IOSPACE_SIZE		0x2000
+
+/*
+ * DOC G3 layout and adressing scheme
+ *   A page address for the block "b", plane "P" and page "p":
+ *   address = [bbbb bPpp pppp]
+ */
+
+#define DOC_ADDR_PAGE_MASK		0x3f
+#define DOC_ADDR_BLOCK_SHIFT		6
+#define DOC_LAYOUT_NBPLANES		2
+#define DOC_LAYOUT_PAGES_PER_BLOCK	64
+#define DOC_LAYOUT_PAGE_SIZE		512
+#define DOC_LAYOUT_OOB_SIZE		16
+#define DOC_LAYOUT_WEAR_SIZE		8
+#define DOC_LAYOUT_PAGE_OOB_SIZE				\
+	(DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_SIZE)
+#define DOC_LAYOUT_WEAR_OFFSET		(DOC_LAYOUT_PAGE_OOB_SIZE * 2)
+#define DOC_LAYOUT_BLOCK_SIZE					\
+	(DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_PAGE_SIZE)
+#define DOC_ECC_BCH_SIZE		7
+#define DOC_ECC_BCH_COVERED_BYTES				\
+	(DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_PAGEINFO_SZ +	\
+	 DOC_LAYOUT_OOB_HAMMING_SZ + DOC_LAYOUT_OOB_BCH_SZ)
+
+/*
+ * Blocks distribution
+ */
+#define DOC_LAYOUT_BLOCK_BBT		0
+#define DOC_LAYOUT_BLOCK_OTP		0
+#define DOC_LAYOUT_BLOCK_FIRST_DATA	6
+
+#define DOC_LAYOUT_PAGE_BBT		4
+
+/*
+ * Extra page OOB (16 bytes wide) layout
+ */
+#define DOC_LAYOUT_OOB_PAGEINFO_OFS	0
+#define DOC_LAYOUT_OOB_HAMMING_OFS	7
+#define DOC_LAYOUT_OOB_BCH_OFS		8
+#define DOC_LAYOUT_OOB_UNUSED_OFS	15
+#define DOC_LAYOUT_OOB_PAGEINFO_SZ	7
+#define DOC_LAYOUT_OOB_HAMMING_SZ	1
+#define DOC_LAYOUT_OOB_BCH_SZ		7
+#define DOC_LAYOUT_OOB_UNUSED_SZ	1
+
+
+#define DOC_CHIPID_G3			0x200
+#define DOC_ERASE_MARK			0xaa
+/*
+ * Flash registers
+ */
+#define DOC_CHIPID			0x1000
+#define DOC_TEST			0x1004
+#define DOC_BUSLOCK			0x1006
+#define DOC_ENDIANCONTROL		0x1008
+#define DOC_DEVICESELECT		0x100a
+#define DOC_ASICMODE			0x100c
+#define DOC_CONFIGURATION		0x100e
+#define DOC_INTERRUPTCONTROL		0x1010
+#define DOC_READADDRESS			0x101a
+#define DOC_DATAEND			0x101e
+#define DOC_INTERRUPTSTATUS		0x1020
+
+#define DOC_FLASHSEQUENCE		0x1032
+#define DOC_FLASHCOMMAND		0x1034
+#define DOC_FLASHADDRESS		0x1036
+#define DOC_FLASHCONTROL		0x1038
+#define DOC_NOP				0x103e
+
+#define DOC_ECCCONF0			0x1040
+#define DOC_ECCCONF1			0x1042
+#define DOC_ECCPRESET			0x1044
+#define DOC_HAMMINGPARITY		0x1046
+#define DOC_BCH_SYNDROM(idx)		(0x1048 + (idx << 1))
+
+#define DOC_PROTECTION			0x1056
+#define DOC_DPS0_ADDRLOW		0x1060
+#define DOC_DPS0_ADDRHIGH		0x1062
+#define DOC_DPS1_ADDRLOW		0x1064
+#define DOC_DPS1_ADDRHIGH		0x1066
+#define DOC_DPS0_STATUS			0x106c
+#define DOC_DPS1_STATUS			0x106e
+
+#define DOC_ASICMODECONFIRM		0x1072
+#define DOC_CHIPID_INV			0x1074
+
+/*
+ * Flash sequences
+ * A sequence is preset before one or more commands are input to the chip.
+ */
+#define DOC_SEQ_RESET			0x00
+#define DOC_SEQ_PAGE_SIZE_532		0x03
+#define DOC_SEQ_SET_MODE		0x09
+#define DOC_SEQ_READ			0x12
+#define DOC_SEQ_SET_PLANE1		0x0e
+#define DOC_SEQ_SET_PLANE2		0x10
+#define DOC_SEQ_PAGE_SETUP		0x1d
+
+/*
+ * Flash commands
+ */
+#define DOC_CMD_READ_PLANE1		0x00
+#define DOC_CMD_SET_ADDR_READ		0x05
+#define DOC_CMD_READ_ALL_PLANES		0x30
+#define DOC_CMD_READ_PLANE2		0x50
+#define DOC_CMD_READ_FLASH		0xe0
+#define DOC_CMD_PAGE_SIZE_532		0x3c
+
+#define DOC_CMD_PROG_BLOCK_ADDR		0x60
+#define DOC_CMD_PROG_CYCLE1		0x80
+#define DOC_CMD_PROG_CYCLE2		0x10
+#define DOC_CMD_ERASECYCLE2		0xd0
+
+#define DOC_CMD_RELIABLE_MODE		0x22
+#define DOC_CMD_FAST_MODE		0xa2
+
+#define DOC_CMD_RESET			0xff
+
+/*
+ * Flash register : DOC_FLASHCONTROL
+ */
+#define DOC_CTRL_VIOLATION		0x20
+#define DOC_CTRL_CE			0x10
+#define DOC_CTRL_UNKNOWN_BITS		0x08
+#define DOC_CTRL_PROTECTION_ERROR	0x04
+#define DOC_CTRL_SEQUENCE_ERROR		0x02
+#define DOC_CTRL_FLASHREADY		0x01
+
+/*
+ * Flash register : DOC_ASICMODE
+ */
+#define DOC_ASICMODE_RESET		0x00
+#define DOC_ASICMODE_NORMAL		0x01
+#define DOC_ASICMODE_POWERDOWN		0x02
+#define DOC_ASICMODE_MDWREN		0x04
+#define DOC_ASICMODE_BDETCT_RESET	0x08
+#define DOC_ASICMODE_RSTIN_RESET	0x10
+#define DOC_ASICMODE_RAM_WE		0x20
+
+/*
+ * Flash register : DOC_ECCCONF0
+ */
+#define DOC_ECCCONF0_READ_MODE		0x8000
+#define DOC_ECCCONF0_AUTO_ECC_ENABLE	0x4000
+#define DOC_ECCCONF0_HAMMING_ENABLE	0x1000
+#define DOC_ECCCONF0_BCH_ENABLE		0x0800
+#define DOC_ECCCONF0_DATA_BYTES_MASK	0x07ff
+
+/*
+ * Flash register : DOC_ECCCONF1
+ */
+#define DOC_ECCCONF1_BCH_SYNDROM_ERR	0x80
+#define DOC_ECCCONF1_UNKOWN1		0x40
+#define DOC_ECCCONF1_UNKOWN2		0x20
+#define DOC_ECCCONF1_UNKOWN3		0x10
+#define DOC_ECCCONF1_HAMMING_BITS_MASK	0x0f
+
+/*
+ * Flash register : DOC_PROTECTION
+ */
+#define DOC_PROTECT_FOUNDRY_OTP_LOCK	0x01
+#define DOC_PROTECT_CUSTOMER_OTP_LOCK	0x02
+#define DOC_PROTECT_LOCK_INPUT		0x04
+#define DOC_PROTECT_STICKY_LOCK		0x08
+#define DOC_PROTECT_PROTECTION_ENABLED	0x10
+#define DOC_PROTECT_IPL_DOWNLOAD_LOCK	0x20
+#define DOC_PROTECT_PROTECTION_ERROR	0x80
+
+/*
+ * Flash register : DOC_DPS0_STATUS and DOC_DPS1_STATUS
+ */
+#define DOC_DPS_OTP_PROTECTED		0x01
+#define DOC_DPS_READ_PROTECTED		0x02
+#define DOC_DPS_WRITE_PROTECTED		0x04
+#define DOC_DPS_HW_LOCK_ENABLED		0x08
+#define DOC_DPS_KEY_OK			0x80
+
+/*
+ * Flash register : DOC_CONFIGURATION
+ */
+#define DOC_CONF_IF_CFG			0x80
+#define DOC_CONF_MAX_ID_MASK		0x30
+#define DOC_CONF_VCCQ_3V		0x01
+
+/*
+ * Flash register : DOC_READADDRESS
+ */
+#define DOC_READADDR_INC		0x8000
+#define DOC_READADDR_ONE_BYTE		0x4000
+#define DOC_READADDR_ADDR_MASK		0x1fff
+
+/**
+ * struct docg3 - DiskOnChip driver private data
+ * @dev: the device currently under control
+ * @base: mapped IO space
+ * @device_id: number of the cascaded DoCG3 device (0, 1, 2 or 3)
+ * @if_cfg: if true, reads are on 16bits, else reads are on 8bits
+ * @bbt: bad block table cache
+ * @debugfs_root: debugfs root node
+ */
+struct docg3 {
+	struct device *dev;
+	void __iomem *base;
+	unsigned int device_id:4;
+	unsigned int if_cfg:1;
+	int max_block;
+	u8 *bbt;
+	struct dentry *debugfs_root;
+};
+
+#define doc_err(fmt, arg...) dev_err(docg3->dev, (fmt), ## arg)
+#define doc_info(fmt, arg...) dev_info(docg3->dev, (fmt), ## arg)
+#define doc_dbg(fmt, arg...) dev_dbg(docg3->dev, (fmt), ## arg)
+#define doc_vdbg(fmt, arg...) dev_vdbg(docg3->dev, (fmt), ## arg)
+
+#define DEBUGFS_RO_ATTR(name, show_fct) \
+	static int name##_open(struct inode *inode, struct file *file) \
+	{ return single_open(file, show_fct, inode->i_private); }      \
+	static const struct file_operations name##_fops = { \
+		.owner = THIS_MODULE, \
+		.open = name##_open, \
+		.llseek = seq_lseek, \
+		.read = seq_read, \
+		.release = single_release \
+	};
+#endif
+
+/*
+ * Trace events part
+ */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM docg3
+
+#if !defined(_MTD_DOCG3_TRACE) || defined(TRACE_HEADER_MULTI_READ)
+#define _MTD_DOCG3_TRACE
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(docg3_io,
+	    TP_PROTO(int op, int width, u16 reg, int val),
+	    TP_ARGS(op, width, reg, val),
+	    TP_STRUCT__entry(
+		    __field(int, op)
+		    __field(unsigned char, width)
+		    __field(u16, reg)
+		    __field(int, val)),
+	    TP_fast_assign(
+		    __entry->op = op;
+		    __entry->width = width;
+		    __entry->reg = reg;
+		    __entry->val = val;),
+	    TP_printk("docg3: %s%02d reg=%04x, val=%04x",
+		      __entry->op ? "write" : "read", __entry->width,
+		      __entry->reg, __entry->val)
+	);
+#endif
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE docg3
+#include <trace/define_trace.h>
diff -druN linux-libre-3.1-gnu/drivers/mtd/devices/docprobe.c linux-libre-3.2-gnu/drivers/mtd/devices/docprobe.c
--- linux-libre-3.1-gnu/drivers/mtd/devices/docprobe.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/devices/docprobe.c	2012-01-04 18:55:44.000000000 -0500
@@ -50,11 +50,6 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/doc2000.h>
 
-/* Where to look for the devices? */
-#ifndef CONFIG_MTD_DOCPROBE_ADDRESS
-#define CONFIG_MTD_DOCPROBE_ADDRESS 0
-#endif
-
 
 static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS;
 module_param(doc_config_location, ulong, 0);
diff -druN linux-libre-3.1-gnu/drivers/mtd/devices/Kconfig linux-libre-3.2-gnu/drivers/mtd/devices/Kconfig
--- linux-libre-3.1-gnu/drivers/mtd/devices/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/devices/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -249,6 +249,16 @@
 	  under "NAND Flash Device Drivers" (currently that driver does not
 	  support all Millennium Plus devices).
 
+config MTD_DOCG3
+	tristate "M-Systems Disk-On-Chip G3"
+	---help---
+	  This provides an MTD device driver for the M-Systems DiskOnChip
+	  G3 devices.
+
+	  The driver provides access to G3 DiskOnChip, distributed by
+	  M-Systems and now Sandisk. The support is very experimental,
+	  and doesn't give access to any write operations.
+
 config MTD_DOCPROBE
 	tristate
 	select MTD_DOCECC
@@ -268,8 +278,7 @@
 config MTD_DOCPROBE_ADDRESS
 	hex "Physical address of DiskOnChip" if MTD_DOCPROBE_ADVANCED
 	depends on MTD_DOCPROBE
-	default "0x0000" if MTD_DOCPROBE_ADVANCED
-	default "0" if !MTD_DOCPROBE_ADVANCED
+	default "0x0"
 	---help---
 	  By default, the probe for DiskOnChip devices will look for a
 	  DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
diff -druN linux-libre-3.1-gnu/drivers/mtd/devices/lart.c linux-libre-3.2-gnu/drivers/mtd/devices/lart.c
--- linux-libre-3.1-gnu/drivers/mtd/devices/lart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/devices/lart.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,9 +34,6 @@
 /* debugging */
 //#define LART_DEBUG
 
-/* partition support */
-#define HAVE_PARTITIONS
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -44,9 +41,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mtd/mtd.h>
-#ifdef HAVE_PARTITIONS
 #include <linux/mtd/partitions.h>
-#endif
 
 #ifndef CONFIG_SA1100_LART
 #error This is for LART architecture only
@@ -598,7 +593,6 @@
 	}
 };
 
-#ifdef HAVE_PARTITIONS
 static struct mtd_partition lart_partitions[] = {
 	/* blob */
 	{
@@ -619,7 +613,7 @@
 		.size	= INITRD_LEN,		/* MTDPART_SIZ_FULL */
 	}
 };
-#endif
+#define NUM_PARTITIONS ARRAY_SIZE(lart_partitions)
 
 static int __init lart_flash_init (void)
 {
@@ -668,7 +662,6 @@
 			   result,mtd.eraseregions[result].erasesize,mtd.eraseregions[result].erasesize / 1024,
 			   result,mtd.eraseregions[result].numblocks);
 
-#ifdef HAVE_PARTITIONS
    printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions));
 
    for (result = 0; result < ARRAY_SIZE(lart_partitions); result++)
@@ -681,25 +674,16 @@
 			 result,lart_partitions[result].offset,
 			 result,lart_partitions[result].size,lart_partitions[result].size / 1024);
 #endif
-#endif
 
-#ifndef HAVE_PARTITIONS
-   result = mtd_device_register(&mtd, NULL, 0);
-#else
    result = mtd_device_register(&mtd, lart_partitions,
                                 ARRAY_SIZE(lart_partitions));
-#endif
 
    return (result);
 }
 
 static void __exit lart_flash_exit (void)
 {
-#ifndef HAVE_PARTITIONS
-   mtd_device_unregister(&mtd);
-#else
    mtd_device_unregister(&mtd);
-#endif
 }
 
 module_init (lart_flash_init);
diff -druN linux-libre-3.1-gnu/drivers/mtd/devices/m25p80.c linux-libre-3.2-gnu/drivers/mtd/devices/m25p80.c
--- linux-libre-3.1-gnu/drivers/mtd/devices/m25p80.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/devices/m25p80.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/mtd/cfi.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/of_platform.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
@@ -88,7 +89,6 @@
 	struct spi_device	*spi;
 	struct mutex		lock;
 	struct mtd_info		mtd;
-	unsigned		partitioned:1;
 	u16			page_size;
 	u16			addr_width;
 	u8			erase_opcode;
@@ -209,9 +209,8 @@
  */
 static int erase_chip(struct m25p *flash)
 {
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %lldKiB\n",
-	      dev_name(&flash->spi->dev), __func__,
-	      (long long)(flash->mtd.size >> 10));
+	pr_debug("%s: %s %lldKiB\n", dev_name(&flash->spi->dev), __func__,
+			(long long)(flash->mtd.size >> 10));
 
 	/* Wait until finished previous write command. */
 	if (wait_till_ready(flash))
@@ -250,9 +249,8 @@
  */
 static int erase_sector(struct m25p *flash, u32 offset)
 {
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n",
-			dev_name(&flash->spi->dev), __func__,
-			flash->mtd.erasesize / 1024, offset);
+	pr_debug("%s: %s %dKiB at 0x%08x\n", dev_name(&flash->spi->dev),
+			__func__, flash->mtd.erasesize / 1024, offset);
 
 	/* Wait until finished previous write command. */
 	if (wait_till_ready(flash))
@@ -286,9 +284,9 @@
 	u32 addr,len;
 	uint32_t rem;
 
-	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%llx, len %lld\n",
-	      dev_name(&flash->spi->dev), __func__, "at",
-	      (long long)instr->addr, (long long)instr->len);
+	pr_debug("%s: %s at 0x%llx, len %lld\n", dev_name(&flash->spi->dev),
+			__func__, (long long)instr->addr,
+			(long long)instr->len);
 
 	/* sanity checks */
 	if (instr->addr + instr->len > flash->mtd.size)
@@ -348,9 +346,8 @@
 	struct spi_transfer t[2];
 	struct spi_message m;
 
-	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
-			dev_name(&flash->spi->dev), __func__, "from",
-			(u32)from, len);
+	pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
+			__func__, (u32)from, len);
 
 	/* sanity checks */
 	if (!len)
@@ -417,9 +414,8 @@
 	struct spi_transfer t[2];
 	struct spi_message m;
 
-	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
-			dev_name(&flash->spi->dev), __func__, "to",
-			(u32)to, len);
+	pr_debug("%s: %s to 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
+			__func__, (u32)to, len);
 
 	*retlen = 0;
 
@@ -510,9 +506,8 @@
 	size_t actual;
 	int cmd_sz, ret;
 
-	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
-			dev_name(&flash->spi->dev), __func__, "to",
-			(u32)to, len);
+	pr_debug("%s: %s to 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
+			__func__, (u32)to, len);
 
 	*retlen = 0;
 
@@ -661,6 +656,7 @@
 	{ "at25fs040",  INFO(0x1f6604, 0, 64 * 1024,   8, SECT_4K) },
 
 	{ "at25df041a", INFO(0x1f4401, 0, 64 * 1024,   8, SECT_4K) },
+	{ "at25df321a", INFO(0x1f4701, 0, 64 * 1024,  64, SECT_4K) },
 	{ "at25df641",  INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) },
 
 	{ "at26f004",   INFO(0x1f0400, 0, 64 * 1024,  8, SECT_4K) },
@@ -671,6 +667,7 @@
 	/* EON -- en25xxx */
 	{ "en25f32", INFO(0x1c3116, 0, 64 * 1024,  64, SECT_4K) },
 	{ "en25p32", INFO(0x1c2016, 0, 64 * 1024,  64, 0) },
+	{ "en25q32b", INFO(0x1c3016, 0, 64 * 1024,  64, 0) },
 	{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
 
 	/* Intel/Numonyx -- xxxs33b */
@@ -788,8 +785,8 @@
 	 */
 	tmp = spi_write_then_read(spi, &code, 1, id, 5);
 	if (tmp < 0) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
-			dev_name(&spi->dev), tmp);
+		pr_debug("%s: error %d reading JEDEC ID\n",
+				dev_name(&spi->dev), tmp);
 		return ERR_PTR(tmp);
 	}
 	jedec = id[0];
@@ -825,8 +822,12 @@
 	struct m25p			*flash;
 	struct flash_info		*info;
 	unsigned			i;
-	struct mtd_partition		*parts = NULL;
-	int				nr_parts = 0;
+	struct mtd_part_parser_data	ppdata;
+
+#ifdef CONFIG_MTD_OF_PARTS
+	if (!of_device_is_available(spi->dev.of_node))
+		return -ENODEV;
+#endif
 
 	/* Platform data helps sort out which chip type we have, as
 	 * well as how this board partitions it.  If we don't have
@@ -928,6 +929,7 @@
 	if (info->flags & M25P_NO_ERASE)
 		flash->mtd.flags |= MTD_NO_ERASE;
 
+	ppdata.of_node = spi->dev.of_node;
 	flash->mtd.dev.parent = &spi->dev;
 	flash->page_size = info->page_size;
 
@@ -945,8 +947,7 @@
 	dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name,
 			(long long)flash->mtd.size >> 10);
 
-	DEBUG(MTD_DEBUG_LEVEL2,
-		"mtd .name = %s, .size = 0x%llx (%lldMiB) "
+	pr_debug("mtd .name = %s, .size = 0x%llx (%lldMiB) "
 			".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
 		flash->mtd.name,
 		(long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
@@ -955,8 +956,7 @@
 
 	if (flash->mtd.numeraseregions)
 		for (i = 0; i < flash->mtd.numeraseregions; i++)
-			DEBUG(MTD_DEBUG_LEVEL2,
-				"mtd.eraseregions[%d] = { .offset = 0x%llx, "
+			pr_debug("mtd.eraseregions[%d] = { .offset = 0x%llx, "
 				".erasesize = 0x%.8x (%uKiB), "
 				".numblocks = %d }\n",
 				i, (long long)flash->mtd.eraseregions[i].offset,
@@ -968,41 +968,9 @@
 	/* partitions should match sector boundaries; and it may be good to
 	 * use readonly partitions for writeprotected sectors (BP2..BP0).
 	 */
-	if (mtd_has_cmdlinepart()) {
-		static const char *part_probes[]
-			= { "cmdlinepart", NULL, };
-
-		nr_parts = parse_mtd_partitions(&flash->mtd,
-						part_probes, &parts, 0);
-	}
-
-	if (nr_parts <= 0 && data && data->parts) {
-		parts = data->parts;
-		nr_parts = data->nr_parts;
-	}
-
-#ifdef CONFIG_MTD_OF_PARTS
-	if (nr_parts <= 0 && spi->dev.of_node) {
-		nr_parts = of_mtd_parse_partitions(&spi->dev,
-						   spi->dev.of_node, &parts);
-	}
-#endif
-
-	if (nr_parts > 0) {
-		for (i = 0; i < nr_parts; i++) {
-			DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-			      "{.name = %s, .offset = 0x%llx, "
-			      ".size = 0x%llx (%lldKiB) }\n",
-			      i, parts[i].name,
-			      (long long)parts[i].offset,
-			      (long long)parts[i].size,
-			      (long long)(parts[i].size >> 10));
-		}
-		flash->partitioned = 1;
-	}
-
-	return mtd_device_register(&flash->mtd, parts, nr_parts) == 1 ?
-		-ENODEV : 0;
+	return mtd_device_parse_register(&flash->mtd, NULL, &ppdata,
+			data ? data->parts : NULL,
+			data ? data->nr_parts : 0);
 }
 
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/devices/Makefile linux-libre-3.2-gnu/drivers/mtd/devices/Makefile
--- linux-libre-3.1-gnu/drivers/mtd/devices/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/devices/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -5,6 +5,7 @@
 obj-$(CONFIG_MTD_DOC2000)	+= doc2000.o
 obj-$(CONFIG_MTD_DOC2001)	+= doc2001.o
 obj-$(CONFIG_MTD_DOC2001PLUS)	+= doc2001plus.o
+obj-$(CONFIG_MTD_DOCG3)		+= docg3.o
 obj-$(CONFIG_MTD_DOCPROBE)	+= docprobe.o
 obj-$(CONFIG_MTD_DOCECC)	+= docecc.o
 obj-$(CONFIG_MTD_SLRAM)		+= slram.o
@@ -17,3 +18,5 @@
 obj-$(CONFIG_MTD_DATAFLASH)	+= mtd_dataflash.o
 obj-$(CONFIG_MTD_M25P80)	+= m25p80.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
+
+CFLAGS_docg3.o			+= -I$(src)
\ No newline at end of file
diff -druN linux-libre-3.1-gnu/drivers/mtd/devices/mtd_dataflash.c linux-libre-3.2-gnu/drivers/mtd/devices/mtd_dataflash.c
--- linux-libre-3.1-gnu/drivers/mtd/devices/mtd_dataflash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/devices/mtd_dataflash.c	2012-01-04 18:55:44.000000000 -0500
@@ -17,6 +17,8 @@
 #include <linux/mutex.h>
 #include <linux/err.h>
 #include <linux/math64.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
@@ -24,7 +26,6 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
-
 /*
  * DataFlash is a kind of SPI flash.  Most AT45 chips have two buffers in
  * each chip, which may be used for double buffered I/O; but this driver
@@ -98,6 +99,16 @@
 	struct mtd_info		mtd;
 };
 
+#ifdef CONFIG_OF
+static const struct of_device_id dataflash_dt_ids[] = {
+	{ .compatible = "atmel,at45", },
+	{ .compatible = "atmel,dataflash", },
+	{ /* sentinel */ }
+};
+#else
+#define dataflash_dt_ids NULL
+#endif
+
 /* ......................................................................... */
 
 /*
@@ -122,7 +133,7 @@
 	for (;;) {
 		status = dataflash_status(spi);
 		if (status < 0) {
-			DEBUG(MTD_DEBUG_LEVEL1, "%s: status %d?\n",
+			pr_debug("%s: status %d?\n",
 					dev_name(&spi->dev), status);
 			status = 0;
 		}
@@ -149,7 +160,7 @@
 	uint8_t			*command;
 	uint32_t		rem;
 
-	DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%llx len 0x%llx\n",
+	pr_debug("%s: erase addr=0x%llx len 0x%llx\n",
 	      dev_name(&spi->dev), (long long)instr->addr,
 	      (long long)instr->len);
 
@@ -187,7 +198,7 @@
 		command[2] = (uint8_t)(pageaddr >> 8);
 		command[3] = 0;
 
-		DEBUG(MTD_DEBUG_LEVEL3, "ERASE %s: (%x) %x %x %x [%i]\n",
+		pr_debug("ERASE %s: (%x) %x %x %x [%i]\n",
 			do_block ? "block" : "page",
 			command[0], command[1], command[2], command[3],
 			pageaddr);
@@ -238,8 +249,8 @@
 	uint8_t			*command;
 	int			status;
 
-	DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n",
-		dev_name(&priv->spi->dev), (unsigned)from, (unsigned)(from + len));
+	pr_debug("%s: read 0x%x..0x%x\n", dev_name(&priv->spi->dev),
+			(unsigned)from, (unsigned)(from + len));
 
 	*retlen = 0;
 
@@ -255,7 +266,7 @@
 
 	command = priv->command;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n",
+	pr_debug("READ: (%x) %x %x %x\n",
 		command[0], command[1], command[2], command[3]);
 
 	spi_message_init(&msg);
@@ -287,7 +298,7 @@
 		*retlen = msg.actual_length - 8;
 		status = 0;
 	} else
-		DEBUG(MTD_DEBUG_LEVEL1, "%s: read %x..%x --> %d\n",
+		pr_debug("%s: read %x..%x --> %d\n",
 			dev_name(&priv->spi->dev),
 			(unsigned)from, (unsigned)(from + len),
 			status);
@@ -314,7 +325,7 @@
 	int			status = -EINVAL;
 	uint8_t			*command;
 
-	DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n",
+	pr_debug("%s: write 0x%x..0x%x\n",
 		dev_name(&spi->dev), (unsigned)to, (unsigned)(to + len));
 
 	*retlen = 0;
@@ -340,7 +351,7 @@
 
 	mutex_lock(&priv->lock);
 	while (remaining > 0) {
-		DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n",
+		pr_debug("write @ %i:%i len=%i\n",
 			pageaddr, offset, writelen);
 
 		/* REVISIT:
@@ -368,12 +379,12 @@
 			command[2] = (addr & 0x0000FF00) >> 8;
 			command[3] = 0;
 
-			DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n",
+			pr_debug("TRANSFER: (%x) %x %x %x\n",
 				command[0], command[1], command[2], command[3]);
 
 			status = spi_sync(spi, &msg);
 			if (status < 0)
-				DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n",
+				pr_debug("%s: xfer %u -> %d\n",
 					dev_name(&spi->dev), addr, status);
 
 			(void) dataflash_waitready(priv->spi);
@@ -386,7 +397,7 @@
 		command[2] = (addr & 0x0000FF00) >> 8;
 		command[3] = (addr & 0x000000FF);
 
-		DEBUG(MTD_DEBUG_LEVEL3, "PROGRAM: (%x) %x %x %x\n",
+		pr_debug("PROGRAM: (%x) %x %x %x\n",
 			command[0], command[1], command[2], command[3]);
 
 		x[1].tx_buf = writebuf;
@@ -395,7 +406,7 @@
 		status = spi_sync(spi, &msg);
 		spi_transfer_del(x + 1);
 		if (status < 0)
-			DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n",
+			pr_debug("%s: pgm %u/%u -> %d\n",
 				dev_name(&spi->dev), addr, writelen, status);
 
 		(void) dataflash_waitready(priv->spi);
@@ -410,12 +421,12 @@
 		command[2] = (addr & 0x0000FF00) >> 8;
 		command[3] = 0;
 
-		DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n",
+		pr_debug("COMPARE: (%x) %x %x %x\n",
 			command[0], command[1], command[2], command[3]);
 
 		status = spi_sync(spi, &msg);
 		if (status < 0)
-			DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n",
+			pr_debug("%s: compare %u -> %d\n",
 				dev_name(&spi->dev), addr, status);
 
 		status = dataflash_waitready(priv->spi);
@@ -634,11 +645,10 @@
 {
 	struct dataflash		*priv;
 	struct mtd_info			*device;
+	struct mtd_part_parser_data	ppdata;
 	struct flash_platform_data	*pdata = spi->dev.platform_data;
 	char				*otp_tag = "";
 	int				err = 0;
-	struct mtd_partition		*parts;
-	int				nr_parts = 0;
 
 	priv = kzalloc(sizeof *priv, GFP_KERNEL);
 	if (!priv)
@@ -677,28 +687,11 @@
 			pagesize, otp_tag);
 	dev_set_drvdata(&spi->dev, priv);
 
-	if (mtd_has_cmdlinepart()) {
-		static const char *part_probes[] = { "cmdlinepart", NULL, };
-
-		nr_parts = parse_mtd_partitions(device, part_probes, &parts,
-						0);
-	}
-
-	if (nr_parts <= 0 && pdata && pdata->parts) {
-		parts = pdata->parts;
-		nr_parts = pdata->nr_parts;
-	}
-
-	if (nr_parts > 0) {
-		priv->partitioned = 1;
-		err = mtd_device_register(device, parts, nr_parts);
-		goto out;
-	}
-
-	if (mtd_device_register(device, NULL, 0) == 1)
-		err = -ENODEV;
+	ppdata.of_node = spi->dev.of_node;
+	err = mtd_device_parse_register(device, NULL, &ppdata,
+			pdata ? pdata->parts : NULL,
+			pdata ? pdata->nr_parts : 0);
 
-out:
 	if (!err)
 		return 0;
 
@@ -787,7 +780,7 @@
 	 */
 	tmp = spi_write_then_read(spi, &code, 1, id, 3);
 	if (tmp < 0) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
+		pr_debug("%s: error %d reading JEDEC ID\n",
 			dev_name(&spi->dev), tmp);
 		return ERR_PTR(tmp);
 	}
@@ -804,7 +797,7 @@
 			tmp < ARRAY_SIZE(dataflash_data);
 			tmp++, info++) {
 		if (info->jedec_id == jedec) {
-			DEBUG(MTD_DEBUG_LEVEL1, "%s: OTP, sector protect%s\n",
+			pr_debug("%s: OTP, sector protect%s\n",
 				dev_name(&spi->dev),
 				(info->flags & SUP_POW2PS)
 					? ", binary pagesize" : ""
@@ -812,8 +805,7 @@
 			if (info->flags & SUP_POW2PS) {
 				status = dataflash_status(spi);
 				if (status < 0) {
-					DEBUG(MTD_DEBUG_LEVEL1,
-						"%s: status error %d\n",
+					pr_debug("%s: status error %d\n",
 						dev_name(&spi->dev), status);
 					return ERR_PTR(status);
 				}
@@ -878,7 +870,7 @@
 	 */
 	status = dataflash_status(spi);
 	if (status <= 0 || status == 0xff) {
-		DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n",
+		pr_debug("%s: status error %d\n",
 				dev_name(&spi->dev), status);
 		if (status == 0 || status == 0xff)
 			status = -ENODEV;
@@ -914,14 +906,14 @@
 		break;
 	/* obsolete AT45DB1282 not (yet?) supported */
 	default:
-		DEBUG(MTD_DEBUG_LEVEL1, "%s: unsupported device (%x)\n",
-				dev_name(&spi->dev), status & 0x3c);
+		pr_debug("%s: unsupported device (%x)\n", dev_name(&spi->dev),
+				status & 0x3c);
 		status = -ENODEV;
 	}
 
 	if (status < 0)
-		DEBUG(MTD_DEBUG_LEVEL1, "%s: add_dataflash --> %d\n",
-				dev_name(&spi->dev), status);
+		pr_debug("%s: add_dataflash --> %d\n", dev_name(&spi->dev),
+				status);
 
 	return status;
 }
@@ -931,7 +923,7 @@
 	struct dataflash	*flash = dev_get_drvdata(&spi->dev);
 	int			status;
 
-	DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", dev_name(&spi->dev));
+	pr_debug("%s: remove\n", dev_name(&spi->dev));
 
 	status = mtd_device_unregister(&flash->mtd);
 	if (status == 0) {
@@ -946,6 +938,7 @@
 		.name		= "mtd_dataflash",
 		.bus		= &spi_bus_type,
 		.owner		= THIS_MODULE,
+		.of_match_table = dataflash_dt_ids,
 	},
 
 	.probe		= dataflash_probe,
diff -druN linux-libre-3.1-gnu/drivers/mtd/devices/sst25l.c linux-libre-3.2-gnu/drivers/mtd/devices/sst25l.c
--- linux-libre-3.1-gnu/drivers/mtd/devices/sst25l.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/devices/sst25l.c	2012-01-04 18:55:44.000000000 -0500
@@ -52,8 +52,6 @@
 	struct spi_device	*spi;
 	struct mutex		lock;
 	struct mtd_info		mtd;
-
-	int 			partitioned;
 };
 
 struct flash_info {
@@ -381,8 +379,6 @@
 	struct sst25l_flash *flash;
 	struct flash_platform_data *data;
 	int ret, i;
-	struct mtd_partition *parts = NULL;
-	int nr_parts = 0;
 
 	flash_info = sst25l_match_device(spi);
 	if (!flash_info)
@@ -414,8 +410,7 @@
 	dev_info(&spi->dev, "%s (%lld KiB)\n", flash_info->name,
 		 (long long)flash->mtd.size >> 10);
 
-	DEBUG(MTD_DEBUG_LEVEL2,
-	      "mtd .name = %s, .size = 0x%llx (%lldMiB) "
+	pr_debug("mtd .name = %s, .size = 0x%llx (%lldMiB) "
 	      ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
 	      flash->mtd.name,
 	      (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
@@ -423,37 +418,10 @@
 	      flash->mtd.numeraseregions);
 
 
-	if (mtd_has_cmdlinepart()) {
-		static const char *part_probes[] = {"cmdlinepart", NULL};
-
-		nr_parts = parse_mtd_partitions(&flash->mtd,
-						part_probes,
-						&parts, 0);
-	}
-
-	if (nr_parts <= 0 && data && data->parts) {
-		parts = data->parts;
-		nr_parts = data->nr_parts;
-	}
-
-	if (nr_parts > 0) {
-		for (i = 0; i < nr_parts; i++) {
-			DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-			      "{.name = %s, .offset = 0x%llx, "
-			      ".size = 0x%llx (%lldKiB) }\n",
-			      i, parts[i].name,
-			      (long long)parts[i].offset,
-			      (long long)parts[i].size,
-			      (long long)(parts[i].size >> 10));
-		}
-
-		flash->partitioned = 1;
-		return mtd_device_register(&flash->mtd, parts,
-					   nr_parts);
-	}
-
-	ret = mtd_device_register(&flash->mtd, NULL, 0);
-	if (ret == 1) {
+	ret = mtd_device_parse_register(&flash->mtd, NULL, 0,
+			data ? data->parts : NULL,
+			data ? data->nr_parts : 0);
+	if (ret) {
 		kfree(flash);
 		dev_set_drvdata(&spi->dev, NULL);
 		return -ENODEV;
diff -druN linux-libre-3.1-gnu/drivers/mtd/ftl.c linux-libre-3.2-gnu/drivers/mtd/ftl.c
--- linux-libre-3.1-gnu/drivers/mtd/ftl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/ftl.c	2012-01-04 18:55:44.000000000 -0500
@@ -339,7 +339,7 @@
     struct erase_info *erase;
 
     xfer = &part->XferInfo[xfernum];
-    DEBUG(1, "ftl_cs: erasing xfer unit at 0x%x\n", xfer->Offset);
+    pr_debug("ftl_cs: erasing xfer unit at 0x%x\n", xfer->Offset);
     xfer->state = XFER_ERASING;
 
     /* Is there a free erase slot? Always in MTD. */
@@ -415,7 +415,7 @@
     xfer = &part->XferInfo[i];
     xfer->state = XFER_FAILED;
 
-    DEBUG(1, "ftl_cs: preparing xfer unit at 0x%x\n", xfer->Offset);
+    pr_debug("ftl_cs: preparing xfer unit at 0x%x\n", xfer->Offset);
 
     /* Write the transfer unit header */
     header = part->header;
@@ -476,7 +476,7 @@
 
     eun = &part->EUNInfo[srcunit];
     xfer = &part->XferInfo[xferunit];
-    DEBUG(2, "ftl_cs: copying block 0x%x to 0x%x\n",
+    pr_debug("ftl_cs: copying block 0x%x to 0x%x\n",
 	  eun->Offset, xfer->Offset);
 
 
@@ -598,7 +598,7 @@
     unit with the fewest erases, and usually pick the data unit with
     the most deleted blocks.  But with a small probability, pick the
     oldest data unit instead.  This means that we generally postpone
-    the next reclaimation as long as possible, but shuffle static
+    the next reclamation as long as possible, but shuffle static
     stuff around a bit for wear leveling.
 
 ======================================================================*/
@@ -609,8 +609,8 @@
     uint32_t best;
     int queued, ret;
 
-    DEBUG(0, "ftl_cs: reclaiming space...\n");
-    DEBUG(3, "NumTransferUnits == %x\n", part->header.NumTransferUnits);
+    pr_debug("ftl_cs: reclaiming space...\n");
+    pr_debug("NumTransferUnits == %x\n", part->header.NumTransferUnits);
     /* Pick the least erased transfer unit */
     best = 0xffffffff; xfer = 0xffff;
     do {
@@ -618,22 +618,22 @@
 	for (i = 0; i < part->header.NumTransferUnits; i++) {
 	    int n=0;
 	    if (part->XferInfo[i].state == XFER_UNKNOWN) {
-		DEBUG(3,"XferInfo[%d].state == XFER_UNKNOWN\n",i);
+		pr_debug("XferInfo[%d].state == XFER_UNKNOWN\n",i);
 		n=1;
 		erase_xfer(part, i);
 	    }
 	    if (part->XferInfo[i].state == XFER_ERASING) {
-		DEBUG(3,"XferInfo[%d].state == XFER_ERASING\n",i);
+		pr_debug("XferInfo[%d].state == XFER_ERASING\n",i);
 		n=1;
 		queued = 1;
 	    }
 	    else if (part->XferInfo[i].state == XFER_ERASED) {
-		DEBUG(3,"XferInfo[%d].state == XFER_ERASED\n",i);
+		pr_debug("XferInfo[%d].state == XFER_ERASED\n",i);
 		n=1;
 		prepare_xfer(part, i);
 	    }
 	    if (part->XferInfo[i].state == XFER_PREPARED) {
-		DEBUG(3,"XferInfo[%d].state == XFER_PREPARED\n",i);
+		pr_debug("XferInfo[%d].state == XFER_PREPARED\n",i);
 		n=1;
 		if (part->XferInfo[i].EraseCount <= best) {
 		    best = part->XferInfo[i].EraseCount;
@@ -641,12 +641,12 @@
 		}
 	    }
 		if (!n)
-		    DEBUG(3,"XferInfo[%d].state == %x\n",i, part->XferInfo[i].state);
+		    pr_debug("XferInfo[%d].state == %x\n",i, part->XferInfo[i].state);
 
 	}
 	if (xfer == 0xffff) {
 	    if (queued) {
-		DEBUG(1, "ftl_cs: waiting for transfer "
+		pr_debug("ftl_cs: waiting for transfer "
 		      "unit to be prepared...\n");
 		if (part->mbd.mtd->sync)
 			part->mbd.mtd->sync(part->mbd.mtd);
@@ -656,7 +656,7 @@
 		    printk(KERN_NOTICE "ftl_cs: reclaim failed: no "
 			   "suitable transfer units!\n");
 		else
-		    DEBUG(1, "ftl_cs: reclaim failed: no "
+		    pr_debug("ftl_cs: reclaim failed: no "
 			  "suitable transfer units!\n");
 
 		return -EIO;
@@ -666,7 +666,7 @@
 
     eun = 0;
     if ((jiffies % shuffle_freq) == 0) {
-	DEBUG(1, "ftl_cs: recycling freshest block...\n");
+	pr_debug("ftl_cs: recycling freshest block...\n");
 	best = 0xffffffff;
 	for (i = 0; i < part->DataUnits; i++)
 	    if (part->EUNInfo[i].EraseCount <= best) {
@@ -686,7 +686,7 @@
 		printk(KERN_NOTICE "ftl_cs: reclaim failed: "
 		       "no free blocks!\n");
 	    else
-		DEBUG(1,"ftl_cs: reclaim failed: "
+		pr_debug("ftl_cs: reclaim failed: "
 		       "no free blocks!\n");
 
 	    return -EIO;
@@ -771,7 +771,7 @@
 	printk(KERN_NOTICE "ftl_cs: bad free list!\n");
 	return 0;
     }
-    DEBUG(2, "ftl_cs: found free block at %d in %d\n", blk, eun);
+    pr_debug("ftl_cs: found free block at %d in %d\n", blk, eun);
     return blk;
 
 } /* find_free */
@@ -791,7 +791,7 @@
     int ret;
     size_t offset, retlen;
 
-    DEBUG(2, "ftl_cs: ftl_read(0x%p, 0x%lx, %ld)\n",
+    pr_debug("ftl_cs: ftl_read(0x%p, 0x%lx, %ld)\n",
 	  part, sector, nblocks);
     if (!(part->state & FTL_FORMATTED)) {
 	printk(KERN_NOTICE "ftl_cs: bad partition\n");
@@ -840,7 +840,7 @@
     int ret;
     size_t retlen, offset;
 
-    DEBUG(2, "ftl_cs: set_bam_entry(0x%p, 0x%x, 0x%x)\n",
+    pr_debug("ftl_cs: set_bam_entry(0x%p, 0x%x, 0x%x)\n",
 	  part, log_addr, virt_addr);
     bsize = 1 << part->header.EraseUnitSize;
     eun = log_addr / bsize;
@@ -905,7 +905,7 @@
     int ret;
     size_t retlen, offset;
 
-    DEBUG(2, "ftl_cs: ftl_write(0x%p, %ld, %ld)\n",
+    pr_debug("ftl_cs: ftl_write(0x%p, %ld, %ld)\n",
 	  part, sector, nblocks);
     if (!(part->state & FTL_FORMATTED)) {
 	printk(KERN_NOTICE "ftl_cs: bad partition\n");
@@ -1011,7 +1011,7 @@
 	partition_t *part = (void *)dev;
 	uint32_t bsize = 1 << part->header.EraseUnitSize;
 
-	DEBUG(1, "FTL erase sector %ld for %d sectors\n",
+	pr_debug("FTL erase sector %ld for %d sectors\n",
 	      sector, nr_sects);
 
 	while (nr_sects) {
diff -druN linux-libre-3.1-gnu/drivers/mtd/inftlcore.c linux-libre-3.2-gnu/drivers/mtd/inftlcore.c
--- linux-libre-3.1-gnu/drivers/mtd/inftlcore.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/inftlcore.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,14 +63,12 @@
 		return;
 	}
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: add_mtd for %s\n", mtd->name);
+	pr_debug("INFTL: add_mtd for %s\n", mtd->name);
 
 	inftl = kzalloc(sizeof(*inftl), GFP_KERNEL);
 
-	if (!inftl) {
-		printk(KERN_WARNING "INFTL: Out of memory for data structures\n");
+	if (!inftl)
 		return;
-	}
 
 	inftl->mbd.mtd = mtd;
 	inftl->mbd.devnum = -1;
@@ -133,7 +131,7 @@
 {
 	struct INFTLrecord *inftl = (void *)dev;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: remove_dev (i=%d)\n", dev->devnum);
+	pr_debug("INFTL: remove_dev (i=%d)\n", dev->devnum);
 
 	del_mtd_blktrans_dev(dev);
 
@@ -154,7 +152,7 @@
 	struct mtd_oob_ops ops;
 	int res;
 
-	ops.mode = MTD_OOB_PLACE;
+	ops.mode = MTD_OPS_PLACE_OOB;
 	ops.ooboffs = offs & (mtd->writesize - 1);
 	ops.ooblen = len;
 	ops.oobbuf = buf;
@@ -174,7 +172,7 @@
 	struct mtd_oob_ops ops;
 	int res;
 
-	ops.mode = MTD_OOB_PLACE;
+	ops.mode = MTD_OPS_PLACE_OOB;
 	ops.ooboffs = offs & (mtd->writesize - 1);
 	ops.ooblen = len;
 	ops.oobbuf = buf;
@@ -194,7 +192,7 @@
 	struct mtd_oob_ops ops;
 	int res;
 
-	ops.mode = MTD_OOB_PLACE;
+	ops.mode = MTD_OPS_PLACE_OOB;
 	ops.ooboffs = offs;
 	ops.ooblen = mtd->oobsize;
 	ops.oobbuf = oob;
@@ -215,16 +213,16 @@
 	u16 pot = inftl->LastFreeEUN;
 	int silly = inftl->nb_blocks;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findfreeblock(inftl=%p,"
-		"desperate=%d)\n", inftl, desperate);
+	pr_debug("INFTL: INFTL_findfreeblock(inftl=%p,desperate=%d)\n",
+			inftl, desperate);
 
 	/*
 	 * Normally, we force a fold to happen before we run out of free
 	 * blocks completely.
 	 */
 	if (!desperate && inftl->numfreeEUNs < 2) {
-		DEBUG(MTD_DEBUG_LEVEL1, "INFTL: there are too few free "
-			"EUNs (%d)\n", inftl->numfreeEUNs);
+		pr_debug("INFTL: there are too few free EUNs (%d)\n",
+				inftl->numfreeEUNs);
 		return BLOCK_NIL;
 	}
 
@@ -259,8 +257,8 @@
 	struct inftl_oob oob;
 	size_t retlen;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_foldchain(inftl=%p,thisVUC=%d,"
-		"pending=%d)\n", inftl, thisVUC, pendingblock);
+	pr_debug("INFTL: INFTL_foldchain(inftl=%p,thisVUC=%d,pending=%d)\n",
+			inftl, thisVUC, pendingblock);
 
 	memset(BlockMap, 0xff, sizeof(BlockMap));
 	memset(BlockDeleted, 0, sizeof(BlockDeleted));
@@ -323,8 +321,7 @@
 	 * Chain, and the Erase Unit into which we are supposed to be copying.
 	 * Go for it.
 	 */
-	DEBUG(MTD_DEBUG_LEVEL1, "INFTL: folding chain %d into unit %d\n",
-		thisVUC, targetEUN);
+	pr_debug("INFTL: folding chain %d into unit %d\n", thisVUC, targetEUN);
 
 	for (block = 0; block < inftl->EraseSize/SECTORSIZE ; block++) {
 		unsigned char movebuf[SECTORSIZE];
@@ -349,14 +346,13 @@
 		ret = mtd->read(mtd, (inftl->EraseSize * BlockMap[block]) +
 				(block * SECTORSIZE), SECTORSIZE, &retlen,
 				movebuf);
-		if (ret < 0 && ret != -EUCLEAN) {
+		if (ret < 0 && !mtd_is_bitflip(ret)) {
 			ret = mtd->read(mtd,
 					(inftl->EraseSize * BlockMap[block]) +
 					(block * SECTORSIZE), SECTORSIZE,
 					&retlen, movebuf);
 			if (ret != -EIO)
-				DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went "
-				      "away on retry?\n");
+				pr_debug("INFTL: error went away on retry?\n");
 		}
 		memset(&oob, 0xff, sizeof(struct inftl_oob));
 		oob.b.Status = oob.b.Status1 = SECTOR_USED;
@@ -372,8 +368,7 @@
 	 * is important, by doing oldest first if we crash/reboot then it
 	 * it is relatively simple to clean up the mess).
 	 */
-	DEBUG(MTD_DEBUG_LEVEL1, "INFTL: want to erase virtual chain %d\n",
-		thisVUC);
+	pr_debug("INFTL: want to erase virtual chain %d\n", thisVUC);
 
 	for (;;) {
 		/* Find oldest unit in chain. */
@@ -421,7 +416,7 @@
 	u16 ChainLength = 0, thislen;
 	u16 chain, EUN;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_makefreeblock(inftl=%p,"
+	pr_debug("INFTL: INFTL_makefreeblock(inftl=%p,"
 		"pending=%d)\n", inftl, pendingblock);
 
 	for (chain = 0; chain < inftl->nb_blocks; chain++) {
@@ -484,8 +479,8 @@
 	size_t retlen;
 	int silly, silly2 = 3;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findwriteunit(inftl=%p,"
-		"block=%d)\n", inftl, block);
+	pr_debug("INFTL: INFTL_findwriteunit(inftl=%p,block=%d)\n",
+			inftl, block);
 
 	do {
 		/*
@@ -501,8 +496,8 @@
 				       blockofs, 8, &retlen, (char *)&bci);
 
 			status = bci.Status | bci.Status1;
-			DEBUG(MTD_DEBUG_LEVEL3, "INFTL: status of block %d in "
-				"EUN %d is %x\n", block , writeEUN, status);
+			pr_debug("INFTL: status of block %d in EUN %d is %x\n",
+					block , writeEUN, status);
 
 			switch(status) {
 			case SECTOR_FREE:
@@ -555,9 +550,9 @@
 			 * Hopefully we free something, lets try again.
 			 * This time we are desperate...
 			 */
-			DEBUG(MTD_DEBUG_LEVEL1, "INFTL: using desperate==1 "
-				"to find free EUN to accommodate write to "
-				"VUC %d\n", thisVUC);
+			pr_debug("INFTL: using desperate==1 to find free EUN "
+					"to accommodate write to VUC %d\n",
+					thisVUC);
 			writeEUN = INFTL_findfreeblock(inftl, 1);
 			if (writeEUN == BLOCK_NIL) {
 				/*
@@ -647,7 +642,7 @@
 	struct inftl_bci bci;
 	size_t retlen;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_trydeletechain(inftl=%p,"
+	pr_debug("INFTL: INFTL_trydeletechain(inftl=%p,"
 		"thisVUC=%d)\n", inftl, thisVUC);
 
 	memset(BlockUsed, 0, sizeof(BlockUsed));
@@ -711,7 +706,7 @@
 	 * For each block in the chain free it and make it available
 	 * for future use. Erase from the oldest unit first.
 	 */
-	DEBUG(MTD_DEBUG_LEVEL1, "INFTL: deleting empty VUC %d\n", thisVUC);
+	pr_debug("INFTL: deleting empty VUC %d\n", thisVUC);
 
 	for (;;) {
 		u16 *prevEUN = &inftl->VUtable[thisVUC];
@@ -719,7 +714,7 @@
 
 		/* If the chain is all gone already, we're done */
 		if (thisEUN == BLOCK_NIL) {
-			DEBUG(MTD_DEBUG_LEVEL2, "INFTL: Empty VUC %d for deletion was already absent\n", thisEUN);
+			pr_debug("INFTL: Empty VUC %d for deletion was already absent\n", thisEUN);
 			return;
 		}
 
@@ -731,7 +726,7 @@
 			thisEUN = *prevEUN;
 		}
 
-		DEBUG(MTD_DEBUG_LEVEL3, "Deleting EUN %d from VUC %d\n",
+		pr_debug("Deleting EUN %d from VUC %d\n",
 		      thisEUN, thisVUC);
 
 		if (INFTL_formatblock(inftl, thisEUN) < 0) {
@@ -767,7 +762,7 @@
 	size_t retlen;
 	struct inftl_bci bci;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_deleteblock(inftl=%p,"
+	pr_debug("INFTL: INFTL_deleteblock(inftl=%p,"
 		"block=%d)\n", inftl, block);
 
 	while (thisEUN < inftl->nb_blocks) {
@@ -826,7 +821,7 @@
 	struct inftl_oob oob;
 	char *p, *pend;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_writeblock(inftl=%p,block=%ld,"
+	pr_debug("INFTL: inftl_writeblock(inftl=%p,block=%ld,"
 		"buffer=%p)\n", inftl, block, buffer);
 
 	/* Is block all zero? */
@@ -876,7 +871,7 @@
 	struct inftl_bci bci;
 	size_t retlen;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_readblock(inftl=%p,block=%ld,"
+	pr_debug("INFTL: inftl_readblock(inftl=%p,block=%ld,"
 		"buffer=%p)\n", inftl, block, buffer);
 
 	while (thisEUN < inftl->nb_blocks) {
@@ -922,7 +917,7 @@
 		int ret = mtd->read(mtd, ptr, SECTORSIZE, &retlen, buffer);
 
 		/* Handle corrected bit flips gracefully */
-		if (ret < 0 && ret != -EUCLEAN)
+		if (ret < 0 && !mtd_is_bitflip(ret))
 			return -EIO;
 	}
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/mtd/inftlmount.c linux-libre-3.2-gnu/drivers/mtd/inftlmount.c
--- linux-libre-3.1-gnu/drivers/mtd/inftlmount.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/inftlmount.c	2012-01-04 18:55:44.000000000 -0500
@@ -53,7 +53,7 @@
 	struct INFTLPartition *ip;
 	size_t retlen;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: find_boot_record(inftl=%p)\n", inftl);
+	pr_debug("INFTL: find_boot_record(inftl=%p)\n", inftl);
 
         /*
 	 * Assume logical EraseSize == physical erasesize for starting the
@@ -139,24 +139,20 @@
 		mh->FormatFlags = le32_to_cpu(mh->FormatFlags);
 		mh->PercentUsed = le32_to_cpu(mh->PercentUsed);
 
-#ifdef CONFIG_MTD_DEBUG_VERBOSE
-		if (CONFIG_MTD_DEBUG_VERBOSE >= 2) {
-			printk("INFTL: Media Header ->\n"
-				"    bootRecordID          = %s\n"
-				"    NoOfBootImageBlocks   = %d\n"
-				"    NoOfBinaryPartitions  = %d\n"
-				"    NoOfBDTLPartitions    = %d\n"
-				"    BlockMultiplerBits    = %d\n"
-				"    FormatFlgs            = %d\n"
-				"    OsakVersion           = 0x%x\n"
-				"    PercentUsed           = %d\n",
-				mh->bootRecordID, mh->NoOfBootImageBlocks,
-				mh->NoOfBinaryPartitions,
-				mh->NoOfBDTLPartitions,
-				mh->BlockMultiplierBits, mh->FormatFlags,
-				mh->OsakVersion, mh->PercentUsed);
-		}
-#endif
+		pr_debug("INFTL: Media Header ->\n"
+			 "    bootRecordID          = %s\n"
+			 "    NoOfBootImageBlocks   = %d\n"
+			 "    NoOfBinaryPartitions  = %d\n"
+			 "    NoOfBDTLPartitions    = %d\n"
+			 "    BlockMultiplerBits    = %d\n"
+			 "    FormatFlgs            = %d\n"
+			 "    OsakVersion           = 0x%x\n"
+			 "    PercentUsed           = %d\n",
+			 mh->bootRecordID, mh->NoOfBootImageBlocks,
+			 mh->NoOfBinaryPartitions,
+			 mh->NoOfBDTLPartitions,
+			 mh->BlockMultiplierBits, mh->FormatFlags,
+			 mh->OsakVersion, mh->PercentUsed);
 
 		if (mh->NoOfBDTLPartitions == 0) {
 			printk(KERN_WARNING "INFTL: Media Header sanity check "
@@ -200,19 +196,15 @@
 			ip->spareUnits = le32_to_cpu(ip->spareUnits);
 			ip->Reserved0 = le32_to_cpu(ip->Reserved0);
 
-#ifdef CONFIG_MTD_DEBUG_VERBOSE
-			if (CONFIG_MTD_DEBUG_VERBOSE >= 2) {
-				printk("    PARTITION[%d] ->\n"
-					"        virtualUnits    = %d\n"
-					"        firstUnit       = %d\n"
-					"        lastUnit        = %d\n"
-					"        flags           = 0x%x\n"
-					"        spareUnits      = %d\n",
-					i, ip->virtualUnits, ip->firstUnit,
-					ip->lastUnit, ip->flags,
-					ip->spareUnits);
-			}
-#endif
+			pr_debug("    PARTITION[%d] ->\n"
+				 "        virtualUnits    = %d\n"
+				 "        firstUnit       = %d\n"
+				 "        lastUnit        = %d\n"
+				 "        flags           = 0x%x\n"
+				 "        spareUnits      = %d\n",
+				 i, ip->virtualUnits, ip->firstUnit,
+				 ip->lastUnit, ip->flags,
+				 ip->spareUnits);
 
 			if (ip->Reserved0 != ip->firstUnit) {
 				struct erase_info *instr = &inftl->instr;
@@ -375,7 +367,7 @@
  *
  * Return: 0 when succeed, -1 on error.
  *
- * ToDo: 1. Is it neceressary to check_free_sector after erasing ??
+ * ToDo: 1. Is it necessary to check_free_sector after erasing ??
  */
 int INFTL_formatblock(struct INFTLrecord *inftl, int block)
 {
@@ -385,8 +377,7 @@
 	struct mtd_info *mtd = inftl->mbd.mtd;
 	int physblock;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_formatblock(inftl=%p,"
-		"block=%d)\n", inftl, block);
+	pr_debug("INFTL: INFTL_formatblock(inftl=%p,block=%d)\n", inftl, block);
 
 	memset(instr, 0, sizeof(struct erase_info));
 
@@ -476,30 +467,30 @@
 {
 	int i;
 
-	printk("-------------------------------------------"
+	pr_debug("-------------------------------------------"
 		"----------------------------------\n");
 
-	printk("VUtable[%d] ->", s->nb_blocks);
+	pr_debug("VUtable[%d] ->", s->nb_blocks);
 	for (i = 0; i < s->nb_blocks; i++) {
 		if ((i % 8) == 0)
-			printk("\n%04x: ", i);
-		printk("%04x ", s->VUtable[i]);
+			pr_debug("\n%04x: ", i);
+		pr_debug("%04x ", s->VUtable[i]);
 	}
 
-	printk("\n-------------------------------------------"
+	pr_debug("\n-------------------------------------------"
 		"----------------------------------\n");
 
-	printk("PUtable[%d-%d=%d] ->", s->firstEUN, s->lastEUN, s->nb_blocks);
+	pr_debug("PUtable[%d-%d=%d] ->", s->firstEUN, s->lastEUN, s->nb_blocks);
 	for (i = 0; i <= s->lastEUN; i++) {
 		if ((i % 8) == 0)
-			printk("\n%04x: ", i);
-		printk("%04x ", s->PUtable[i]);
+			pr_debug("\n%04x: ", i);
+		pr_debug("%04x ", s->PUtable[i]);
 	}
 
-	printk("\n-------------------------------------------"
+	pr_debug("\n-------------------------------------------"
 		"----------------------------------\n");
 
-	printk("INFTL ->\n"
+	pr_debug("INFTL ->\n"
 		"  EraseSize       = %d\n"
 		"  h/s/c           = %d/%d/%d\n"
 		"  numvunits       = %d\n"
@@ -513,7 +504,7 @@
 		s->numvunits, s->firstEUN, s->lastEUN, s->numfreeEUNs,
 		s->LastFreeEUN, s->nb_blocks, s->nb_boot_blocks);
 
-	printk("\n-------------------------------------------"
+	pr_debug("\n-------------------------------------------"
 		"----------------------------------\n");
 }
 
@@ -521,25 +512,25 @@
 {
 	int logical, block, i;
 
-	printk("-------------------------------------------"
+	pr_debug("-------------------------------------------"
 		"----------------------------------\n");
 
-	printk("INFTL Virtual Unit Chains:\n");
+	pr_debug("INFTL Virtual Unit Chains:\n");
 	for (logical = 0; logical < s->nb_blocks; logical++) {
 		block = s->VUtable[logical];
 		if (block > s->nb_blocks)
 			continue;
-		printk("  LOGICAL %d --> %d ", logical, block);
+		pr_debug("  LOGICAL %d --> %d ", logical, block);
 		for (i = 0; i < s->nb_blocks; i++) {
 			if (s->PUtable[block] == BLOCK_NIL)
 				break;
 			block = s->PUtable[block];
-			printk("%d ", block);
+			pr_debug("%d ", block);
 		}
-		printk("\n");
+		pr_debug("\n");
 	}
 
-	printk("-------------------------------------------"
+	pr_debug("-------------------------------------------"
 		"----------------------------------\n");
 }
 
@@ -555,7 +546,7 @@
 	int i;
 	u8 *ANACtable, ANAC;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_mount(inftl=%p)\n", s);
+	pr_debug("INFTL: INFTL_mount(inftl=%p)\n", s);
 
 	/* Search for INFTL MediaHeader and Spare INFTL Media Header */
 	if (find_boot_record(s) < 0) {
@@ -585,7 +576,7 @@
 	 * NOTEXPLORED state. Then at the end we will try to format it and
 	 * mark it as free.
 	 */
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 1, explore each unit\n");
+	pr_debug("INFTL: pass 1, explore each unit\n");
 	for (first_block = s->firstEUN; first_block <= s->lastEUN; first_block++) {
 		if (s->PUtable[first_block] != BLOCK_NOTEXPLORED)
 			continue;
@@ -717,17 +708,14 @@
 		logical_block = BLOCK_NIL;
 	}
 
-#ifdef CONFIG_MTD_DEBUG_VERBOSE
-	if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
-		INFTL_dumptables(s);
-#endif
+	INFTL_dumptables(s);
 
 	/*
 	 * Second pass, check for infinite loops in chains. These are
 	 * possible because we don't update the previous pointers when
 	 * we fold chains. No big deal, just fix them up in PUtable.
 	 */
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 2, validate virtual chains\n");
+	pr_debug("INFTL: pass 2, validate virtual chains\n");
 	for (logical_block = 0; logical_block < s->numvunits; logical_block++) {
 		block = s->VUtable[logical_block];
 		last_block = BLOCK_NIL;
@@ -772,12 +760,8 @@
 		}
 	}
 
-#ifdef CONFIG_MTD_DEBUG_VERBOSE
-	if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
-		INFTL_dumptables(s);
-	if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
-		INFTL_dumpVUchains(s);
-#endif
+	INFTL_dumptables(s);
+	INFTL_dumpVUchains(s);
 
 	/*
 	 * Third pass, format unreferenced blocks and init free block count.
@@ -785,7 +769,7 @@
 	s->numfreeEUNs = 0;
 	s->LastFreeEUN = BLOCK_NIL;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 3, format unused blocks\n");
+	pr_debug("INFTL: pass 3, format unused blocks\n");
 	for (block = s->firstEUN; block <= s->lastEUN; block++) {
 		if (s->PUtable[block] == BLOCK_NOTEXPLORED) {
 			printk("INFTL: unreferenced block %d, formatting it\n",
diff -druN linux-libre-3.1-gnu/drivers/mtd/Kconfig linux-libre-3.2-gnu/drivers/mtd/Kconfig
--- linux-libre-3.1-gnu/drivers/mtd/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -12,27 +12,17 @@
 
 if MTD
 
-config MTD_DEBUG
-	bool "Debugging"
-	help
-	  This turns on low-level debugging for the entire MTD sub-system.
-	  Normally, you should say 'N'.
-
-config MTD_DEBUG_VERBOSE
-	int "Debugging verbosity (0 = quiet, 3 = noisy)"
-	depends on MTD_DEBUG
-	default "0"
-	help
-	  Determines the verbosity level of the MTD debugging messages.
-
 config MTD_TESTS
-	tristate "MTD tests support"
+	tristate "MTD tests support (DANGEROUS)"
 	depends on m
 	help
 	  This option includes various MTD tests into compilation. The tests
 	  should normally be compiled as kernel modules. The modules perform
 	  various checks and verifications when loaded.
 
+	  WARNING: some of the tests will ERASE entire MTD device which they
+	  test. Do not use these tests unless you really know what you do.
+
 config MTD_REDBOOT_PARTS
 	tristate "RedBoot partition table parsing"
 	---help---
@@ -137,12 +127,13 @@
 	  'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example.
 
 config MTD_OF_PARTS
-	def_bool y
+	tristate "OpenFirmware partitioning information support"
+	default Y
 	depends on OF
 	help
 	  This provides a partition parsing function which derives
 	  the partition map from the children of the flash node,
-	  as described in Documentation/powerpc/booting-without-of.txt.
+	  as described in Documentation/devicetree/booting-without-of.txt.
 
 config MTD_AR7_PARTS
 	tristate "TI AR7 partitioning support"
diff -druN linux-libre-3.1-gnu/drivers/mtd/lpddr/lpddr_cmds.c linux-libre-3.2-gnu/drivers/mtd/lpddr/lpddr_cmds.c
--- linux-libre-3.1-gnu/drivers/mtd/lpddr/lpddr_cmds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/lpddr/lpddr_cmds.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/mtd/pfow.h>
 #include <linux/mtd/qinfo.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 static int lpddr_read(struct mtd_info *mtd, loff_t adr, size_t len,
 					size_t *retlen, u_char *buf);
diff -druN linux-libre-3.1-gnu/drivers/mtd/Makefile linux-libre-3.2-gnu/drivers/mtd/Makefile
--- linux-libre-3.1-gnu/drivers/mtd/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -5,8 +5,8 @@
 # Core functionality.
 obj-$(CONFIG_MTD)		+= mtd.o
 mtd-y				:= mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o
-mtd-$(CONFIG_MTD_OF_PARTS)	+= ofpart.o
 
+obj-$(CONFIG_MTD_OF_PARTS)	+= ofpart.o
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 obj-$(CONFIG_MTD_AFS_PARTS)	+= afs.o
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/bcm963xx-flash.c linux-libre-3.2-gnu/drivers/mtd/maps/bcm963xx-flash.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/bcm963xx-flash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/bcm963xx-flash.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/bfin-async-flash.c linux-libre-3.2-gnu/drivers/mtd/maps/bfin-async-flash.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/bfin-async-flash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/bfin-async-flash.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,7 +41,6 @@
 	uint32_t flash_ambctl0, flash_ambctl1;
 	uint32_t save_ambctl0, save_ambctl1;
 	unsigned long irq_flags;
-	struct mtd_partition *parts;
 };
 
 static void switch_to_flash(struct async_state *state)
@@ -165,18 +164,8 @@
 		return -ENXIO;
 	}
 
-	ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
-	if (ret > 0) {
-		pr_devinit(KERN_NOTICE DRIVER_NAME ": Using commandline partition definition\n");
-		mtd_device_register(state->mtd, pdata->parts, ret);
-		state->parts = pdata->parts;
-	} else if (pdata->nr_parts) {
-		pr_devinit(KERN_NOTICE DRIVER_NAME ": Using board partition definition\n");
-		mtd_device_register(state->mtd, pdata->parts, pdata->nr_parts);
-	} else {
-		pr_devinit(KERN_NOTICE DRIVER_NAME ": no partition info available, registering whole flash at once\n");
-		mtd_device_register(state->mtd, NULL, 0);
-	}
+	mtd_device_parse_register(state->mtd, part_probe_types, 0,
+			pdata->parts, pdata->nr_parts);
 
 	platform_set_drvdata(pdev, state);
 
@@ -188,7 +177,6 @@
 	struct async_state *state = platform_get_drvdata(pdev);
 	gpio_free(state->enet_flash_pin);
 	mtd_device_unregister(state->mtd);
-	kfree(state->parts);
 	map_destroy(state->mtd);
 	kfree(state);
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/ceiva.c linux-libre-3.2-gnu/drivers/mtd/maps/ceiva.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/ceiva.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/ceiva.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,341 +0,0 @@
-/*
- * Ceiva flash memory driver.
- * Copyright (C) 2002 Rob Scott <rscott@mtrob.fdns.net>
- *
- * Note: this driver supports jedec compatible devices. Modification
- * for CFI compatible devices should be straight forward: change
- * jedec_probe to cfi_probe.
- *
- * Based on: sa1100-flash.c, which has the following copyright:
- * Flash memory access on SA11x0 based devices
- *
- * (C) 2000 Nicolas Pitre <nico@fluxnic.net>
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/concat.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/io.h>
-#include <asm/sizes.h>
-
-/*
- * This isn't complete yet, so...
- */
-#define CONFIG_MTD_CEIVA_STATICMAP
-
-#ifdef CONFIG_MTD_CEIVA_STATICMAP
-/*
- * See include/linux/mtd/partitions.h for definition of the mtd_partition
- * structure.
- *
- * Please note:
- *  1. The flash size given should be the largest flash size that can
- *     be accommodated.
- *
- *  2. The bus width must defined in clps_setup_flash.
- *
- * The MTD layer will detect flash chip aliasing and reduce the size of
- * the map accordingly.
- *
- */
-
-#ifdef CONFIG_ARCH_CEIVA
-/* Flash / Partition sizing */
-/* For the 28F8003, we use the block mapping to calcuate the sizes */
-#define MAX_SIZE_KiB                  (16 + 8 + 8 + 96 + (7*128))
-#define BOOT_PARTITION_SIZE_KiB       (16)
-#define PARAMS_PARTITION_SIZE_KiB     (8)
-#define KERNEL_PARTITION_SIZE_KiB     (4*128)
-/* 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[] = {
-	{
-		.name = "Ceiva BOOT partition",
-		.size   = BOOT_PARTITION_SIZE_KiB*1024,
-		.offset = 0,
-
-	},{
-		.name = "Ceiva parameters partition",
-		.size   = PARAMS_PARTITION_SIZE_KiB*1024,
-		.offset = (16 + 8) * 1024,
-	},{
-		.name = "Ceiva kernel partition",
-		.size = (KERNEL_PARTITION_SIZE_KiB)*1024,
-		.offset = 0x20000,
-
-	},{
-		.name = "Ceiva root filesystem partition",
-		.offset = MTDPART_OFS_APPEND,
-		.size = (ROOT_PARTITION_SIZE_KiB)*1024,
-	}
-};
-#endif
-
-static int __init clps_static_partitions(struct mtd_partition **parts)
-{
-	int nb_parts = 0;
-
-#ifdef CONFIG_ARCH_CEIVA
-	if (machine_is_ceiva()) {
-		*parts       = ceiva_partitions;
-		nb_parts     = ARRAY_SIZE(ceiva_partitions);
-	}
-#endif
-	return nb_parts;
-}
-#endif
-
-struct clps_info {
-	unsigned long base;
-	unsigned long size;
-	int width;
-	void *vbase;
-	struct map_info *map;
-	struct mtd_info *mtd;
-	struct resource *res;
-};
-
-#define NR_SUBMTD 4
-
-static struct clps_info info[NR_SUBMTD];
-
-static int __init clps_setup_mtd(struct clps_info *clps, int nr, struct mtd_info **rmtd)
-{
-	struct mtd_info *subdev[nr];
-	struct map_info *maps;
-	int i, found = 0, ret = 0;
-
-	/*
-	 * Allocate the map_info structs in one go.
-	 */
-	maps = kzalloc(sizeof(struct map_info) * nr, GFP_KERNEL);
-	if (!maps)
-		return -ENOMEM;
-	/*
-	 * Claim and then map the memory regions.
-	 */
-	for (i = 0; i < nr; i++) {
-		if (clps[i].base == (unsigned long)-1)
-			break;
-
-		clps[i].res = request_mem_region(clps[i].base, clps[i].size, "clps flash");
-		if (!clps[i].res) {
-			ret = -EBUSY;
-			break;
-		}
-
-		clps[i].map = maps + i;
-
-		clps[i].map->name = "clps flash";
-		clps[i].map->phys = clps[i].base;
-
-		clps[i].vbase = ioremap(clps[i].base, clps[i].size);
-		if (!clps[i].vbase) {
-			ret = -ENOMEM;
-			break;
-		}
-
-		clps[i].map->virt = (void __iomem *)clps[i].vbase;
-		clps[i].map->bankwidth = clps[i].width;
-		clps[i].map->size = clps[i].size;
-
-		simple_map_init(&clps[i].map);
-
-		clps[i].mtd = do_map_probe("jedec_probe", clps[i].map);
-		if (clps[i].mtd == NULL) {
-			ret = -ENXIO;
-			break;
-		}
-		clps[i].mtd->owner = THIS_MODULE;
-		subdev[i] = clps[i].mtd;
-
-		printk(KERN_INFO "clps flash: JEDEC device at 0x%08lx, %dMiB, "
-			"%d-bit\n", clps[i].base, clps[i].mtd->size >> 20,
-			clps[i].width * 8);
-		found += 1;
-	}
-
-	/*
-	 * ENXIO is special.  It means we didn't find a chip when
-	 * we probed.  We need to tear down the mapping, free the
-	 * resource and mark it as such.
-	 */
-	if (ret == -ENXIO) {
-		iounmap(clps[i].vbase);
-		clps[i].vbase = NULL;
-		release_resource(clps[i].res);
-		clps[i].res = NULL;
-	}
-
-	/*
-	 * If we found one device, don't bother with concat support.
-	 * If we found multiple devices, use concat if we have it
-	 * available, otherwise fail.
-	 */
-	if (ret == 0 || ret == -ENXIO) {
-		if (found == 1) {
-			*rmtd = subdev[0];
-			ret = 0;
-		} else if (found > 1) {
-			/*
-			 * We detected multiple devices.  Concatenate
-			 * them together.
-			 */
-			*rmtd = mtd_concat_create(subdev, found,
-						  "clps flash");
-			if (*rmtd == NULL)
-				ret = -ENXIO;
-		}
-	}
-
-	/*
-	 * If we failed, clean up.
-	 */
-	if (ret) {
-		do {
-			if (clps[i].mtd)
-				map_destroy(clps[i].mtd);
-			if (clps[i].vbase)
-				iounmap(clps[i].vbase);
-			if (clps[i].res)
-				release_resource(clps[i].res);
-		} while (i--);
-
-		kfree(maps);
-	}
-
-	return ret;
-}
-
-static void __exit clps_destroy_mtd(struct clps_info *clps, struct mtd_info *mtd)
-{
-	int i;
-
-	mtd_device_unregister(mtd);
-
-	if (mtd != clps[0].mtd)
-		mtd_concat_destroy(mtd);
-
-	for (i = NR_SUBMTD; i >= 0; i--) {
-		if (clps[i].mtd)
-			map_destroy(clps[i].mtd);
-		if (clps[i].vbase)
-			iounmap(clps[i].vbase);
-		if (clps[i].res)
-			release_resource(clps[i].res);
-	}
-	kfree(clps[0].map);
-}
-
-/*
- * We define the memory space, size, and width for the flash memory
- * space here.
- */
-
-static int __init clps_setup_flash(void)
-{
-	int nr = 0;
-
-#ifdef CONFIG_ARCH_CEIVA
-	if (machine_is_ceiva()) {
-		info[0].base = CS0_PHYS_BASE;
-		info[0].size = SZ_32M;
-		info[0].width = CEIVA_FLASH_WIDTH;
-		info[1].base = CS1_PHYS_BASE;
-		info[1].size = SZ_32M;
-		info[1].width = CEIVA_FLASH_WIDTH;
-		nr = 2;
-	}
-#endif
-	return nr;
-}
-
-static struct mtd_partition *parsed_parts;
-static const char *probes[] = { "cmdlinepart", "RedBoot", NULL };
-
-static void __init clps_locate_partitions(struct mtd_info *mtd)
-{
-	const char *part_type = NULL;
-	int nr_parts = 0;
-	do {
-		/*
-		 * Partition selection stuff.
-		 */
-		nr_parts = parse_mtd_partitions(mtd, probes, &parsed_parts, 0);
-		if (nr_parts > 0) {
-			part_type = "command line";
-			break;
-		}
-#ifdef CONFIG_MTD_CEIVA_STATICMAP
-		nr_parts = clps_static_partitions(&parsed_parts);
-		if (nr_parts > 0) {
-			part_type = "static";
-			break;
-		}
-		printk("found: %d partitions\n", nr_parts);
-#endif
-	} while (0);
-
-	if (nr_parts == 0) {
-		printk(KERN_NOTICE "clps flash: no partition info "
-			"available, registering whole flash\n");
-		mtd_device_register(mtd, NULL, 0);
-	} else {
-		printk(KERN_NOTICE "clps flash: using %s partition "
-			"definition\n", part_type);
-		mtd_device_register(mtd, parsed_parts, nr_parts);
-	}
-
-	/* Always succeeds. */
-}
-
-static void __exit clps_destroy_partitions(void)
-{
-	kfree(parsed_parts);
-}
-
-static struct mtd_info *mymtd;
-
-static int __init clps_mtd_init(void)
-{
-	int ret;
-	int nr;
-
-	nr = clps_setup_flash();
-	if (nr < 0)
-		return nr;
-
-	ret = clps_setup_mtd(info, nr, &mymtd);
-	if (ret)
-		return ret;
-
-	clps_locate_partitions(mymtd);
-
-	return 0;
-}
-
-static void __exit clps_mtd_cleanup(void)
-{
-	clps_destroy_mtd(info, mymtd);
-	clps_destroy_partitions();
-}
-
-module_init(clps_mtd_init);
-module_exit(clps_mtd_cleanup);
-
-MODULE_AUTHOR("Rob Scott");
-MODULE_DESCRIPTION("Cirrus Logic JEDEC map driver");
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/dc21285.c linux-libre-3.2-gnu/drivers/mtd/maps/dc21285.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/dc21285.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/dc21285.c	2012-01-04 18:55:44.000000000 -0500
@@ -145,14 +145,10 @@
 
 
 /* Partition stuff */
-static struct mtd_partition *dc21285_parts;
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 static int __init init_dc21285(void)
 {
-
-	int nrparts;
-
 	/* Determine bankwidth */
 	switch (*CSR_SA110_CNTL & (3<<14)) {
 		case SA110_CNTL_ROMWIDTH_8:
@@ -200,8 +196,7 @@
 
 	dc21285_mtd->owner = THIS_MODULE;
 
-	nrparts = parse_mtd_partitions(dc21285_mtd, probes, &dc21285_parts, 0);
-	mtd_device_register(dc21285_mtd, dc21285_parts, nrparts);
+	mtd_device_parse_register(dc21285_mtd, probes, 0, NULL, 0);
 
 	if(machine_is_ebsa285()) {
 		/*
@@ -224,8 +219,6 @@
 static void __exit cleanup_dc21285(void)
 {
 	mtd_device_unregister(dc21285_mtd);
-	if (dc21285_parts)
-		kfree(dc21285_parts);
 	map_destroy(dc21285_mtd);
 	iounmap(dc21285_map.virt);
 }
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/edb7312.c linux-libre-3.2-gnu/drivers/mtd/maps/edb7312.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/edb7312.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/edb7312.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,134 +0,0 @@
-/*
- * Handle mapping of the NOR flash on Cogent EDB7312 boards
- *
- * Copyright 2002 SYSGO Real-Time Solutions GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#define WINDOW_ADDR 0x00000000      /* physical properties of flash */
-#define WINDOW_SIZE 0x01000000
-#define BUSWIDTH    2
-#define FLASH_BLOCKSIZE_MAIN	0x20000
-#define FLASH_NUMBLOCKS_MAIN	128
-/* can be "cfi_probe", "jedec_probe", "map_rom", NULL }; */
-#define PROBETYPES { "cfi_probe", NULL }
-
-#define MSG_PREFIX "EDB7312-NOR:"   /* prefix for our printk()'s */
-#define MTDID      "edb7312-nor"    /* for mtdparts= partitioning */
-
-static struct mtd_info *mymtd;
-
-struct map_info edb7312nor_map = {
-	.name = "NOR flash on EDB7312",
-	.size = WINDOW_SIZE,
-	.bankwidth = BUSWIDTH,
-	.phys = WINDOW_ADDR,
-};
-
-/*
- * MTD partitioning stuff
- */
-static struct mtd_partition static_partitions[3] =
-{
-	{
-		.name = "ARMboot",
-		.size = 0x40000,
-		.offset = 0
-	},
-	{
-		.name = "Kernel",
-		.size = 0x200000,
-		.offset = 0x40000
-	},
-	{
-		.name = "RootFS",
-		.size = 0xDC0000,
-		.offset = 0x240000
-	},
-};
-
-static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
-
-static int                   mtd_parts_nb = 0;
-static struct mtd_partition *mtd_parts    = 0;
-
-static int __init init_edb7312nor(void)
-{
-	static const char *rom_probe_types[] = PROBETYPES;
-	const char **type;
-	const char *part_type = 0;
-
-       	printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n",
-	       WINDOW_SIZE, WINDOW_ADDR);
-	edb7312nor_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
-
-	if (!edb7312nor_map.virt) {
-		printk(MSG_PREFIX "failed to ioremap\n");
-		return -EIO;
-	}
-
-	simple_map_init(&edb7312nor_map);
-
-	mymtd = 0;
-	type = rom_probe_types;
-	for(; !mymtd && *type; type++) {
-		mymtd = do_map_probe(*type, &edb7312nor_map);
-	}
-	if (mymtd) {
-		mymtd->owner = THIS_MODULE;
-
-		mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, MTDID);
-		if (mtd_parts_nb > 0)
-			part_type = "detected";
-
-		if (mtd_parts_nb == 0) {
-			mtd_parts = static_partitions;
-			mtd_parts_nb = ARRAY_SIZE(static_partitions);
-			part_type = "static";
-		}
-
-		if (mtd_parts_nb == 0)
-			printk(KERN_NOTICE MSG_PREFIX "no partition info available\n");
-		else
-			printk(KERN_NOTICE MSG_PREFIX
-			       "using %s partition definition\n", part_type);
-		/* Register the whole device first. */
-		mtd_device_register(mymtd, NULL, 0);
-		mtd_device_register(mymtd, mtd_parts, mtd_parts_nb);
-		return 0;
-	}
-
-	iounmap((void *)edb7312nor_map.virt);
-	return -ENXIO;
-}
-
-static void __exit cleanup_edb7312nor(void)
-{
-	if (mymtd) {
-		mtd_device_unregister(mymtd);
-		map_destroy(mymtd);
-	}
-	if (edb7312nor_map.virt) {
-		iounmap((void *)edb7312nor_map.virt);
-		edb7312nor_map.virt = 0;
-	}
-}
-
-module_init(init_edb7312nor);
-module_exit(cleanup_edb7312nor);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Marius Groeger <mag@sysgo.de>");
-MODULE_DESCRIPTION("Generic configurable MTD map driver");
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/gpio-addr-flash.c linux-libre-3.2-gnu/drivers/mtd/maps/gpio-addr-flash.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/gpio-addr-flash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/gpio-addr-flash.c	2012-01-04 18:55:44.000000000 -0500
@@ -187,7 +187,6 @@
  */
 static int __devinit gpio_flash_probe(struct platform_device *pdev)
 {
-	int nr_parts;
 	size_t i, arr_size;
 	struct physmap_flash_data *pdata;
 	struct resource *memory;
@@ -252,20 +251,9 @@
 		return -ENXIO;
 	}
 
-	nr_parts = parse_mtd_partitions(state->mtd, part_probe_types,
-					&pdata->parts, 0);
-	if (nr_parts > 0) {
-		pr_devinit(KERN_NOTICE PFX "Using commandline partition definition\n");
-		kfree(pdata->parts);
-	} else if (pdata->nr_parts) {
-		pr_devinit(KERN_NOTICE PFX "Using board partition definition\n");
-		nr_parts = pdata->nr_parts;
-	} else {
-		pr_devinit(KERN_NOTICE PFX "no partition info available, registering whole flash at once\n");
-		nr_parts = 0;
-	}
 
-	mtd_device_register(state->mtd, pdata->parts, nr_parts);
+	mtd_device_parse_register(state->mtd, part_probe_types, 0,
+			pdata->parts, pdata->nr_parts);
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/h720x-flash.c linux-libre-3.2-gnu/drivers/mtd/maps/h720x-flash.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/h720x-flash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/h720x-flash.c	2012-01-04 18:55:44.000000000 -0500
@@ -58,18 +58,11 @@
 
 #define NUM_PARTITIONS ARRAY_SIZE(h720x_partitions)
 
-static int                   nr_mtd_parts;
-static struct mtd_partition *mtd_parts;
-static const char *probes[] = { "cmdlinepart", NULL };
-
 /*
  * Initialize FLASH support
  */
 static int __init h720x_mtd_init(void)
 {
-
-	char	*part_type = NULL;
-
 	h720x_map.virt = ioremap(h720x_map.phys, h720x_map.size);
 
 	if (!h720x_map.virt) {
@@ -92,16 +85,8 @@
 	if (mymtd) {
 		mymtd->owner = THIS_MODULE;
 
-		nr_mtd_parts = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0);
-		if (nr_mtd_parts > 0)
-			part_type = "command line";
-		if (nr_mtd_parts <= 0) {
-			mtd_parts = h720x_partitions;
-			nr_mtd_parts = NUM_PARTITIONS;
-			part_type = "builtin";
-		}
-		printk(KERN_INFO "Using %s partition table\n", part_type);
-		mtd_device_register(mymtd, mtd_parts, nr_mtd_parts);
+		mtd_device_parse_register(mymtd, NULL, 0,
+				h720x_partitions, NUM_PARTITIONS);
 		return 0;
 	}
 
@@ -120,10 +105,6 @@
 		map_destroy(mymtd);
 	}
 
-	/* Free partition info, if commandline partition was used */
-	if (mtd_parts && (mtd_parts != h720x_partitions))
-		kfree (mtd_parts);
-
 	if (h720x_map.virt) {
 		iounmap((void *)h720x_map.virt);
 		h720x_map.virt = 0;
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/impa7.c linux-libre-3.2-gnu/drivers/mtd/maps/impa7.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/impa7.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/impa7.c	2012-01-04 18:55:44.000000000 -0500
@@ -49,7 +49,7 @@
 /*
  * MTD partitioning stuff
  */
-static struct mtd_partition static_partitions[] =
+static struct mtd_partition partitions[] =
 {
 	{
 		.name = "FileSystem",
@@ -58,16 +58,10 @@
 	},
 };
 
-static int mtd_parts_nb[NUM_FLASHBANKS];
-static struct mtd_partition *mtd_parts[NUM_FLASHBANKS];
-
-static const char *probes[] = { "cmdlinepart", NULL };
-
 static int __init init_impa7(void)
 {
 	static const char *rom_probe_types[] = PROBETYPES;
 	const char **type;
-	const char *part_type = 0;
 	int i;
 	static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = {
 	  { WINDOW_ADDR0, WINDOW_SIZE0 },
@@ -97,23 +91,9 @@
 		if (impa7_mtd[i]) {
 			impa7_mtd[i]->owner = THIS_MODULE;
 			devicesfound++;
-			mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i],
-							       probes,
-							       &mtd_parts[i],
-							       0);
-			if (mtd_parts_nb[i] > 0) {
-				part_type = "command line";
-			} else {
-				mtd_parts[i] = static_partitions;
-				mtd_parts_nb[i] = ARRAY_SIZE(static_partitions);
-				part_type = "static";
-			}
-
-			printk(KERN_NOTICE MSG_PREFIX
-			       "using %s partition definition\n",
-			       part_type);
-			mtd_device_register(impa7_mtd[i],
-					    mtd_parts[i], mtd_parts_nb[i]);
+			mtd_device_parse_register(impa7_mtd[i], NULL, 0,
+						  partitions,
+						  ARRAY_SIZE(partitions));
 		}
 		else
 			iounmap((void *)impa7_map[i].virt);
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/intel_vr_nor.c linux-libre-3.2-gnu/drivers/mtd/maps/intel_vr_nor.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/intel_vr_nor.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/intel_vr_nor.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,7 +44,6 @@
 	void __iomem *csr_base;
 	struct map_info map;
 	struct mtd_info *info;
-	int nr_parts;
 	struct pci_dev *dev;
 };
 
@@ -71,13 +70,9 @@
 
 static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p)
 {
-	struct mtd_partition *parts;
-	static const char *part_probes[] = { "cmdlinepart", NULL };
-
 	/* register the flash bank */
 	/* partition the flash bank */
-	p->nr_parts = parse_mtd_partitions(p->info, part_probes, &parts, 0);
-	return mtd_device_register(p->info, parts, p->nr_parts);
+	return mtd_device_parse_register(p->info, NULL, 0, NULL, 0);
 }
 
 static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p)
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/ixp2000.c linux-libre-3.2-gnu/drivers/mtd/maps/ixp2000.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/ixp2000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/ixp2000.c	2012-01-04 18:55:44.000000000 -0500
@@ -38,7 +38,6 @@
 struct ixp2000_flash_info {
 	struct		mtd_info *mtd;
 	struct		map_info map;
-	struct		mtd_partition *partitions;
 	struct		resource *res;
 };
 
@@ -125,8 +124,6 @@
 	if (info->map.map_priv_1)
 		iounmap((void *) info->map.map_priv_1);
 
-	kfree(info->partitions);
-
 	if (info->res) {
 		release_resource(info->res);
 		kfree(info->res);
@@ -229,13 +226,7 @@
 	}
 	info->mtd->owner = THIS_MODULE;
 
-	err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
-	if (err > 0) {
-		err = mtd_device_register(info->mtd, info->partitions, err);
-		if(err)
-			dev_err(&dev->dev, "Could not parse partitions\n");
-	}
-
+	err = mtd_device_parse_register(info->mtd, probes, 0, NULL, 0);
 	if (err)
 		goto Error;
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/ixp4xx.c linux-libre-3.2-gnu/drivers/mtd/maps/ixp4xx.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/ixp4xx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/ixp4xx.c	2012-01-04 18:55:44.000000000 -0500
@@ -145,7 +145,6 @@
 struct ixp4xx_flash_info {
 	struct mtd_info *mtd;
 	struct map_info map;
-	struct mtd_partition *partitions;
 	struct resource *res;
 };
 
@@ -168,8 +167,6 @@
 	if (info->map.virt)
 		iounmap(info->map.virt);
 
-	kfree(info->partitions);
-
 	if (info->res) {
 		release_resource(info->res);
 		kfree(info->res);
@@ -185,8 +182,6 @@
 {
 	struct flash_platform_data *plat = dev->dev.platform_data;
 	struct ixp4xx_flash_info *info;
-	const char *part_type = NULL;
-	int nr_parts = 0;
 	int err = -1;
 
 	if (!plat)
@@ -252,28 +247,12 @@
 	/* Use the fast version */
 	info->map.write = ixp4xx_write16;
 
-	nr_parts = parse_mtd_partitions(info->mtd, probes, &info->partitions,
-					dev->resource->start);
-	if (nr_parts > 0) {
-		part_type = "dynamic";
-	} else {
-		info->partitions = plat->parts;
-		nr_parts = plat->nr_parts;
-		part_type = "static";
-	}
-	if (nr_parts == 0)
-		printk(KERN_NOTICE "IXP4xx flash: no partition info "
-			"available, registering whole flash\n");
-	else
-		printk(KERN_NOTICE "IXP4xx flash: using %s partition "
-			"definition\n", part_type);
-
-	err = mtd_device_register(info->mtd, info->partitions, nr_parts);
-	if (err)
+	err = mtd_device_parse_register(info->mtd, probes, dev->resource->start,
+			plat->parts, plat->nr_parts);
+	if (err) {
 		printk(KERN_ERR "Could not parse partitions\n");
-
-	if (err)
 		goto Error;
+	}
 
 	return 0;
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/Kconfig linux-libre-3.2-gnu/drivers/mtd/maps/Kconfig
--- linux-libre-3.1-gnu/drivers/mtd/maps/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -41,8 +41,6 @@
 	  are mapped on your particular target board. Refer to the
 	  memory map which should hopefully be in the documentation for
 	  your board.
-	  Ignore this option if you use run-time physmap configuration
-	  (i.e., run-time calling physmap_configure()).
 
 config MTD_PHYSMAP_LEN
 	hex "Physical length of flash mapping"
@@ -55,8 +53,6 @@
 	  than the total amount of flash present. Refer to the memory
 	  map which should hopefully be in the documentation for your
 	  board.
-	  Ignore this option if you use run-time physmap configuration
-	  (i.e., run-time calling physmap_configure()).
 
 config MTD_PHYSMAP_BANKWIDTH
 	int "Bank width in octets"
@@ -67,8 +63,6 @@
 	  in octets. For example, if you have a data bus width of 32
 	  bits, you would set the bus width octet value to 4. This is
 	  used internally by the CFI drivers.
-	  Ignore this option if you use run-time physmap configuration
-	  (i.e., run-time calling physmap_configure()).
 
 config MTD_PHYSMAP_OF
 	tristate "Flash device in physical memory map based on OF description"
@@ -260,7 +254,6 @@
 config MTD_LANTIQ
 	tristate "Lantiq SoC NOR support"
 	depends on LANTIQ
-	select MTD_PARTITIONS
 	help
 	  Support for NOR flash attached to the Lantiq SoC's External Bus Unit.
 
@@ -339,10 +332,6 @@
 	  This enables access to the flash chips on the Hitachi SolutionEngine and
 	  similar boards. Say 'Y' if you are building a kernel for such a board.
 
-config MTD_ARM_INTEGRATOR
-	tristate "CFI Flash device mapped on ARM Integrator/P720T"
-	depends on ARM && MTD_CFI
-
 config MTD_CDB89712
 	tristate "Cirrus CDB89712 evaluation board mappings"
 	depends on MTD_CFI && ARCH_CDB89712
@@ -398,13 +387,6 @@
 	  This enables access to the NV-RAM on autronix autcpu12 board.
 	  If you have such a board, say 'Y'.
 
-config MTD_EDB7312
-	tristate "CFI Flash device mapped on EDB7312"
-	depends on ARCH_EDB7312 && MTD_CFI
-	help
-	  This enables access to the CFI Flash on the Cogent EDB7312 board.
-	  If you have such a board, say 'Y' here.
-
 config MTD_IMPA7
 	tristate "JEDEC Flash device mapped on impA7"
 	depends on ARM && MTD_JEDECPROBE
@@ -412,14 +394,6 @@
 	  This enables access to the NOR Flash on the impA7 board of
 	  implementa GmbH. If you have such a board, say 'Y' here.
 
-config MTD_CEIVA
-	tristate "JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame"
-	depends on MTD_JEDECPROBE && ARCH_CEIVA
-	help
-	  This enables access to the flash chips on the Ceiva/Polaroid
-	  PhotoMax Digital Picture Frame.
-	  If you have such a device, say 'Y'.
-
 config MTD_H720X
 	tristate "Hynix evaluation board mappings"
 	depends on MTD_CFI && ( ARCH_H7201 || ARCH_H7202 )
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/lantiq-flash.c linux-libre-3.2-gnu/drivers/mtd/maps/lantiq-flash.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/lantiq-flash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/lantiq-flash.c	2012-01-04 18:55:44.000000000 -0500
@@ -107,16 +107,12 @@
 	spin_unlock_irqrestore(&ebu_lock, flags);
 }
 
-static const char const *part_probe_types[] = { "cmdlinepart", NULL };
-
 static int __init
 ltq_mtd_probe(struct platform_device *pdev)
 {
 	struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev);
 	struct ltq_mtd *ltq_mtd;
-	struct mtd_partition *parts;
 	struct resource *res;
-	int nr_parts = 0;
 	struct cfi_private *cfi;
 	int err;
 
@@ -172,17 +168,8 @@
 	cfi->addr_unlock1 ^= 1;
 	cfi->addr_unlock2 ^= 1;
 
-	nr_parts = parse_mtd_partitions(ltq_mtd->mtd,
-				part_probe_types, &parts, 0);
-	if (nr_parts > 0) {
-		dev_info(&pdev->dev,
-			"using %d partitions from cmdline", nr_parts);
-	} else {
-		nr_parts = ltq_mtd_data->nr_parts;
-		parts = ltq_mtd_data->parts;
-	}
-
-	err = add_mtd_partitions(ltq_mtd->mtd, parts, nr_parts);
+	err = mtd_device_parse_register(ltq_mtd->mtd, NULL, 0,
+			ltq_mtd_data->parts, ltq_mtd_data->nr_parts);
 	if (err) {
 		dev_err(&pdev->dev, "failed to add partitions\n");
 		goto err_destroy;
@@ -208,7 +195,7 @@
 
 	if (ltq_mtd) {
 		if (ltq_mtd->mtd) {
-			del_mtd_partitions(ltq_mtd->mtd);
+			mtd_device_unregister(ltq_mtd->mtd);
 			map_destroy(ltq_mtd->mtd);
 		}
 		if (ltq_mtd->map->virt)
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/latch-addr-flash.c linux-libre-3.2-gnu/drivers/mtd/maps/latch-addr-flash.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/latch-addr-flash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/latch-addr-flash.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,9 +33,6 @@
 	/* cache; could be found out of res */
 	unsigned long		win_mask;
 
-	int			nr_parts;
-	struct mtd_partition	*parts;
-
 	spinlock_t		lock;
 };
 
@@ -97,8 +94,6 @@
 
 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;
@@ -112,8 +107,6 @@
 	latch_addr_data = dev->dev.platform_data;
 
 	if (info->mtd != NULL) {
-		if (info->nr_parts)
-			kfree(info->parts);
 		mtd_device_unregister(info->mtd);
 		map_destroy(info->mtd);
 	}
@@ -206,21 +199,8 @@
 	}
 	info->mtd->owner = THIS_MODULE;
 
-	err = parse_mtd_partitions(info->mtd, (const char **)part_probe_types,
-				   &info->parts, 0);
-	if (err > 0) {
-		mtd_device_register(info->mtd, info->parts, err);
-		return 0;
-	}
-	if (latch_addr_data->nr_parts) {
-		pr_notice("Using latch-addr-flash partition information\n");
-		mtd_device_register(info->mtd,
-				    latch_addr_data->parts,
-				    latch_addr_data->nr_parts);
-		return 0;
-	}
-
-	mtd_device_register(info->mtd, NULL, 0);
+	mtd_device_parse_register(info->mtd, NULL, 0,
+			latch_addr_data->parts, latch_addr_data->nr_parts);
 	return 0;
 
 iounmap:
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/Makefile linux-libre-3.2-gnu/drivers/mtd/maps/Makefile
--- linux-libre-3.1-gnu/drivers/mtd/maps/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,6 @@
 obj-$(CONFIG_MTD_TSUNAMI)	+= tsunami_flash.o
 obj-$(CONFIG_MTD_PXA2XX)	+= pxa2xx-flash.o
 obj-$(CONFIG_MTD_MBX860)	+= mbx860.o
-obj-$(CONFIG_MTD_CEIVA)		+= ceiva.o
 obj-$(CONFIG_MTD_OCTAGON)	+= octagon-5066.o
 obj-$(CONFIG_MTD_PHYSMAP)	+= physmap.o
 obj-$(CONFIG_MTD_PHYSMAP_OF)	+= physmap_of.o
@@ -40,7 +39,6 @@
 obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
 obj-$(CONFIG_MTD_PCI)		+= pci.o
 obj-$(CONFIG_MTD_AUTCPU12)	+= autcpu12-nvram.o
-obj-$(CONFIG_MTD_EDB7312)	+= edb7312.o
 obj-$(CONFIG_MTD_IMPA7)		+= impa7.o
 obj-$(CONFIG_MTD_FORTUNET)	+= fortunet.o
 obj-$(CONFIG_MTD_UCLINUX)	+= uclinux.o
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/pcmciamtd.c linux-libre-3.2-gnu/drivers/mtd/maps/pcmciamtd.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/pcmciamtd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/pcmciamtd.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,22 +22,6 @@
 #include <linux/mtd/map.h>
 #include <linux/mtd/mtd.h>
 
-#ifdef CONFIG_MTD_DEBUG
-static int debug = CONFIG_MTD_DEBUG_VERBOSE;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy");
-#undef DEBUG
-#define DEBUG(n, format, arg...) \
-	if (n <= debug) {	 \
-		printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
-	}
-
-#else
-#undef DEBUG
-#define DEBUG(n, arg...)
-static const int debug = 0;
-#endif
-
 #define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg)
 
 #define DRIVER_DESC	"PCMCIA Flash memory card driver"
@@ -105,13 +89,13 @@
 	int ret;
 
 	if (!pcmcia_dev_present(dev->p_dev)) {
-		DEBUG(1, "device removed");
+		pr_debug("device removed\n");
 		return 0;
 	}
 
 	offset = to & ~(dev->win_size-1);
 	if (offset != dev->offset) {
-		DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x",
+		pr_debug("Remapping window from 0x%8.8x to 0x%8.8x\n",
 		      dev->offset, offset);
 		ret = pcmcia_map_mem_page(dev->p_dev, win, offset);
 		if (ret != 0)
@@ -132,7 +116,7 @@
 		return d;
 
 	d.x[0] = readb(addr);
-	DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02lx", ofs, addr, d.x[0]);
+	pr_debug("ofs = 0x%08lx (%p) data = 0x%02lx\n", ofs, addr, d.x[0]);
 	return d;
 }
 
@@ -147,7 +131,7 @@
 		return d;
 
 	d.x[0] = readw(addr);
-	DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04lx", ofs, addr, d.x[0]);
+	pr_debug("ofs = 0x%08lx (%p) data = 0x%04lx\n", ofs, addr, d.x[0]);
 	return d;
 }
 
@@ -157,7 +141,7 @@
 	struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
 	unsigned long win_size = dev->win_size;
 
-	DEBUG(3, "to = %p from = %lu len = %zd", to, from, len);
+	pr_debug("to = %p from = %lu len = %zd\n", to, from, len);
 	while(len) {
 		int toread = win_size - (from & (win_size-1));
 		caddr_t addr;
@@ -169,7 +153,7 @@
 		if(!addr)
 			return;
 
-		DEBUG(4, "memcpy from %p to %p len = %d", addr, to, toread);
+		pr_debug("memcpy from %p to %p len = %d\n", addr, to, toread);
 		memcpy_fromio(to, addr, toread);
 		len -= toread;
 		to += toread;
@@ -185,7 +169,7 @@
 	if(!addr)
 		return;
 
-	DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%02lx", adr, addr, d.x[0]);
+	pr_debug("adr = 0x%08lx (%p)  data = 0x%02lx\n", adr, addr, d.x[0]);
 	writeb(d.x[0], addr);
 }
 
@@ -196,7 +180,7 @@
 	if(!addr)
 		return;
 
-	DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%04lx", adr, addr, d.x[0]);
+	pr_debug("adr = 0x%08lx (%p)  data = 0x%04lx\n", adr, addr, d.x[0]);
 	writew(d.x[0], addr);
 }
 
@@ -206,7 +190,7 @@
 	struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
 	unsigned long win_size = dev->win_size;
 
-	DEBUG(3, "to = %lu from = %p len = %zd", to, from, len);
+	pr_debug("to = %lu from = %p len = %zd\n", to, from, len);
 	while(len) {
 		int towrite = win_size - (to & (win_size-1));
 		caddr_t addr;
@@ -218,7 +202,7 @@
 		if(!addr)
 			return;
 
-		DEBUG(4, "memcpy from %p to %p len = %d", from, addr, towrite);
+		pr_debug("memcpy from %p to %p len = %d\n", from, addr, towrite);
 		memcpy_toio(addr, from, towrite);
 		len -= towrite;
 		to += towrite;
@@ -240,7 +224,7 @@
 		return d;
 
 	d.x[0] = readb(win_base + ofs);
-	DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02lx",
+	pr_debug("ofs = 0x%08lx (%p) data = 0x%02lx\n",
 	      ofs, win_base + ofs, d.x[0]);
 	return d;
 }
@@ -255,7 +239,7 @@
 		return d;
 
 	d.x[0] = readw(win_base + ofs);
-	DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04lx",
+	pr_debug("ofs = 0x%08lx (%p) data = 0x%04lx\n",
 	      ofs, win_base + ofs, d.x[0]);
 	return d;
 }
@@ -268,7 +252,7 @@
 	if(DEV_REMOVED(map))
 		return;
 
-	DEBUG(3, "to = %p from = %lu len = %zd", to, from, len);
+	pr_debug("to = %p from = %lu len = %zd\n", to, from, len);
 	memcpy_fromio(to, win_base + from, len);
 }
 
@@ -280,7 +264,7 @@
 	if(DEV_REMOVED(map))
 		return;
 
-	DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%02lx",
+	pr_debug("adr = 0x%08lx (%p)  data = 0x%02lx\n",
 	      adr, win_base + adr, d.x[0]);
 	writeb(d.x[0], win_base + adr);
 }
@@ -293,7 +277,7 @@
 	if(DEV_REMOVED(map))
 		return;
 
-	DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%04lx",
+	pr_debug("adr = 0x%08lx (%p)  data = 0x%04lx\n",
 	      adr, win_base + adr, d.x[0]);
 	writew(d.x[0], win_base + adr);
 }
@@ -306,7 +290,7 @@
 	if(DEV_REMOVED(map))
 		return;
 
-	DEBUG(3, "to = %lu from = %p len = %zd", to, from, len);
+	pr_debug("to = %lu from = %p len = %zd\n", to, from, len);
 	memcpy_toio(win_base + to, from, len);
 }
 
@@ -316,7 +300,7 @@
 	struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
 	struct pcmcia_device *link = dev->p_dev;
 
-	DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
+	pr_debug("dev = %p on = %d vpp = %d\n\n", dev, on, dev->vpp);
 	pcmcia_fixup_vpp(link, on ? dev->vpp : 0);
 }
 
@@ -325,7 +309,7 @@
 {
 	struct pcmciamtd_dev *dev = link->priv;
 
-	DEBUG(3, "link = 0x%p", link);
+	pr_debug("link = 0x%p\n", link);
 
 	if (link->resource[2]->end) {
 		if(dev->win_base) {
@@ -337,7 +321,6 @@
 }
 
 
-#ifdef CONFIG_MTD_DEBUG
 static int pcmciamtd_cistpl_format(struct pcmcia_device *p_dev,
 				tuple_t *tuple,
 				void *priv_data)
@@ -347,7 +330,7 @@
 	if (!pcmcia_parse_tuple(tuple, &parse)) {
 		cistpl_format_t *t = &parse.format;
 		(void)t; /* Shut up, gcc */
-		DEBUG(2, "Format type: %u, Error Detection: %u, offset = %u, length =%u",
+		pr_debug("Format type: %u, Error Detection: %u, offset = %u, length =%u\n",
 			t->type, t->edc, t->offset, t->length);
 	}
 	return -ENOSPC;
@@ -363,12 +346,11 @@
 	if (!pcmcia_parse_tuple(tuple, &parse)) {
 		cistpl_jedec_t *t = &parse.jedec;
 		for (i = 0; i < t->nid; i++)
-			DEBUG(2, "JEDEC: 0x%02x 0x%02x",
+			pr_debug("JEDEC: 0x%02x 0x%02x\n",
 			      t->id[i].mfr, t->id[i].info);
 	}
 	return -ENOSPC;
 }
-#endif
 
 static int pcmciamtd_cistpl_device(struct pcmcia_device *p_dev,
 				tuple_t *tuple,
@@ -382,14 +364,14 @@
 	if (pcmcia_parse_tuple(tuple, &parse))
 		return -EINVAL;
 
-	DEBUG(2, "Common memory:");
+	pr_debug("Common memory:\n");
 	dev->pcmcia_map.size = t->dev[0].size;
 	/* from here on: DEBUG only */
 	for (i = 0; i < t->ndev; i++) {
-		DEBUG(2, "Region %d, type = %u", i, t->dev[i].type);
-		DEBUG(2, "Region %d, wp = %u", i, t->dev[i].wp);
-		DEBUG(2, "Region %d, speed = %u ns", i, t->dev[i].speed);
-		DEBUG(2, "Region %d, size = %u bytes", i, t->dev[i].size);
+		pr_debug("Region %d, type = %u\n", i, t->dev[i].type);
+		pr_debug("Region %d, wp = %u\n", i, t->dev[i].wp);
+		pr_debug("Region %d, speed = %u ns\n", i, t->dev[i].speed);
+		pr_debug("Region %d, size = %u bytes\n", i, t->dev[i].size);
 	}
 	return 0;
 }
@@ -409,12 +391,12 @@
 	dev->pcmcia_map.bankwidth = t->geo[0].buswidth;
 	/* from here on: DEBUG only */
 	for (i = 0; i < t->ngeo; i++) {
-		DEBUG(2, "region: %d bankwidth = %u", i, t->geo[i].buswidth);
-		DEBUG(2, "region: %d erase_block = %u", i, t->geo[i].erase_block);
-		DEBUG(2, "region: %d read_block = %u", i, t->geo[i].read_block);
-		DEBUG(2, "region: %d write_block = %u", i, t->geo[i].write_block);
-		DEBUG(2, "region: %d partition = %u", i, t->geo[i].partition);
-		DEBUG(2, "region: %d interleave = %u", i, t->geo[i].interleave);
+		pr_debug("region: %d bankwidth = %u\n", i, t->geo[i].buswidth);
+		pr_debug("region: %d erase_block = %u\n", i, t->geo[i].erase_block);
+		pr_debug("region: %d read_block = %u\n", i, t->geo[i].read_block);
+		pr_debug("region: %d write_block = %u\n", i, t->geo[i].write_block);
+		pr_debug("region: %d partition = %u\n", i, t->geo[i].partition);
+		pr_debug("region: %d interleave = %u\n", i, t->geo[i].interleave);
 	}
 	return 0;
 }
@@ -432,13 +414,11 @@
 			if (p_dev->prod_id[i])
 				strcat(dev->mtd_name, p_dev->prod_id[i]);
 		}
-		DEBUG(2, "Found name: %s", dev->mtd_name);
+		pr_debug("Found name: %s\n", dev->mtd_name);
 	}
 
-#ifdef CONFIG_MTD_DEBUG
 	pcmcia_loop_tuple(p_dev, CISTPL_FORMAT, pcmciamtd_cistpl_format, NULL);
 	pcmcia_loop_tuple(p_dev, CISTPL_JEDEC_C, pcmciamtd_cistpl_jedec, NULL);
-#endif
 	pcmcia_loop_tuple(p_dev, CISTPL_DEVICE, pcmciamtd_cistpl_device, dev);
 	pcmcia_loop_tuple(p_dev, CISTPL_DEVICE_GEO, pcmciamtd_cistpl_geo, dev);
 
@@ -450,12 +430,12 @@
 
 	if(force_size) {
 		dev->pcmcia_map.size = force_size << 20;
-		DEBUG(2, "size forced to %dM", force_size);
+		pr_debug("size forced to %dM\n", force_size);
 	}
 
 	if(bankwidth) {
 		dev->pcmcia_map.bankwidth = bankwidth;
-		DEBUG(2, "bankwidth forced to %d", bankwidth);
+		pr_debug("bankwidth forced to %d\n", bankwidth);
 	}
 
 	dev->pcmcia_map.name = dev->mtd_name;
@@ -464,7 +444,7 @@
 		*new_name = 1;
 	}
 
-	DEBUG(1, "Device: Size: %lu Width:%d Name: %s",
+	pr_debug("Device: Size: %lu Width:%d Name: %s\n",
 	      dev->pcmcia_map.size,
 	      dev->pcmcia_map.bankwidth << 3, dev->mtd_name);
 }
@@ -479,7 +459,7 @@
 	static char *probes[] = { "jedec_probe", "cfi_probe" };
 	int new_name = 0;
 
-	DEBUG(3, "link=0x%p", link);
+	pr_debug("link=0x%p\n", link);
 
 	card_settings(dev, link, &new_name);
 
@@ -512,11 +492,11 @@
 
 	do {
 		int ret;
-		DEBUG(2, "requesting window with size = %luKiB memspeed = %d",
+		pr_debug("requesting window with size = %luKiB memspeed = %d\n",
 			(unsigned long) resource_size(link->resource[2]) >> 10,
 			mem_speed);
 		ret = pcmcia_request_window(link, link->resource[2], mem_speed);
-		DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size);
+		pr_debug("ret = %d dev->win_size = %d\n", ret, dev->win_size);
 		if(ret) {
 			j++;
 			link->resource[2]->start = 0;
@@ -524,21 +504,21 @@
 					force_size << 20 : MAX_PCMCIA_ADDR;
 			link->resource[2]->end >>= j;
 		} else {
-			DEBUG(2, "Got window of size %luKiB", (unsigned long)
+			pr_debug("Got window of size %luKiB\n", (unsigned long)
 				resource_size(link->resource[2]) >> 10);
 			dev->win_size = resource_size(link->resource[2]);
 			break;
 		}
 	} while (link->resource[2]->end >= 0x1000);
 
-	DEBUG(2, "dev->win_size = %d", dev->win_size);
+	pr_debug("dev->win_size = %d\n", dev->win_size);
 
 	if(!dev->win_size) {
 		dev_err(&dev->p_dev->dev, "Cannot allocate memory window\n");
 		pcmciamtd_release(link);
 		return -ENODEV;
 	}
-	DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10);
+	pr_debug("Allocated a window of %dKiB\n", dev->win_size >> 10);
 
 	/* Get write protect status */
 	dev->win_base = ioremap(link->resource[2]->start,
@@ -549,7 +529,7 @@
 		pcmciamtd_release(link);
 		return -ENODEV;
 	}
-	DEBUG(1, "mapped window dev = %p @ %pR, base = %p",
+	pr_debug("mapped window dev = %p @ %pR, base = %p\n",
 	      dev, link->resource[2], dev->win_base);
 
 	dev->offset = 0;
@@ -564,7 +544,7 @@
 	}
 
 	link->config_index = 0;
-	DEBUG(2, "Setting Configuration");
+	pr_debug("Setting Configuration\n");
 	ret = pcmcia_enable_device(link);
 	if (ret != 0) {
 		if (dev->win_base) {
@@ -580,17 +560,17 @@
 		mtd = do_map_probe("map_rom", &dev->pcmcia_map);
 	} else {
 		for(i = 0; i < ARRAY_SIZE(probes); i++) {
-			DEBUG(1, "Trying %s", probes[i]);
+			pr_debug("Trying %s\n", probes[i]);
 			mtd = do_map_probe(probes[i], &dev->pcmcia_map);
 			if(mtd)
 				break;
 
-			DEBUG(1, "FAILED: %s", probes[i]);
+			pr_debug("FAILED: %s\n", probes[i]);
 		}
 	}
 
 	if(!mtd) {
-		DEBUG(1, "Can not find an MTD");
+		pr_debug("Can not find an MTD\n");
 		pcmciamtd_release(link);
 		return -ENODEV;
 	}
@@ -617,7 +597,7 @@
 	/* If the memory found is fits completely into the mapped PCMCIA window,
 	   use the faster non-remapping read/write functions */
 	if(mtd->size <= dev->win_size) {
-		DEBUG(1, "Using non remapping memory functions");
+		pr_debug("Using non remapping memory functions\n");
 		dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
 		if (dev->pcmcia_map.bankwidth == 1) {
 			dev->pcmcia_map.read = pcmcia_read8;
@@ -645,7 +625,7 @@
 
 static int pcmciamtd_suspend(struct pcmcia_device *dev)
 {
-	DEBUG(2, "EVENT_PM_RESUME");
+	pr_debug("EVENT_PM_RESUME\n");
 
 	/* get_lock(link); */
 
@@ -654,7 +634,7 @@
 
 static int pcmciamtd_resume(struct pcmcia_device *dev)
 {
-	DEBUG(2, "EVENT_PM_SUSPEND");
+	pr_debug("EVENT_PM_SUSPEND\n");
 
 	/* free_lock(link); */
 
@@ -666,7 +646,7 @@
 {
 	struct pcmciamtd_dev *dev = link->priv;
 
-	DEBUG(3, "link=0x%p", link);
+	pr_debug("link=0x%p\n", link);
 
 	if(dev->mtd_info) {
 		mtd_device_unregister(dev->mtd_info);
@@ -686,7 +666,7 @@
 	/* Create new memory card device */
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev) return -ENOMEM;
-	DEBUG(1, "dev=0x%p", dev);
+	pr_debug("dev=0x%p\n", dev);
 
 	dev->p_dev = link;
 	link->priv = dev;
@@ -755,7 +735,7 @@
 
 static void __exit exit_pcmciamtd(void)
 {
-	DEBUG(1, DRIVER_DESC " unloading");
+	pr_debug(DRIVER_DESC " unloading");
 	pcmcia_unregister_driver(&pcmciamtd_driver);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/physmap.c linux-libre-3.2-gnu/drivers/mtd/maps/physmap.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/physmap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/physmap.c	2012-01-04 18:55:44.000000000 -0500
@@ -27,8 +27,6 @@
 	struct mtd_info		*mtd[MAX_RESOURCES];
 	struct mtd_info		*cmtd;
 	struct map_info		map[MAX_RESOURCES];
-	int			nr_parts;
-	struct mtd_partition	*parts;
 };
 
 static int physmap_flash_remove(struct platform_device *dev)
@@ -46,8 +44,6 @@
 
 	if (info->cmtd) {
 		mtd_device_unregister(info->cmtd);
-		if (info->nr_parts)
-			kfree(info->parts);
 		if (info->cmtd != info->mtd[0])
 			mtd_concat_destroy(info->cmtd);
 	}
@@ -175,23 +171,8 @@
 	if (err)
 		goto err_out;
 
-	err = parse_mtd_partitions(info->cmtd, part_probe_types,
-				   &info->parts, 0);
-	if (err > 0) {
-		mtd_device_register(info->cmtd, info->parts, err);
-		info->nr_parts = err;
-		return 0;
-	}
-
-	if (physmap_data->nr_parts) {
-		printk(KERN_NOTICE "Using physmap partition information\n");
-		mtd_device_register(info->cmtd, physmap_data->parts,
-				    physmap_data->nr_parts);
-		return 0;
-	}
-
-	mtd_device_register(info->cmtd, NULL, 0);
-
+	mtd_device_parse_register(info->cmtd, part_probe_types, 0,
+				  physmap_data->parts, physmap_data->nr_parts);
 	return 0;
 
 err_out:
@@ -245,21 +226,6 @@
 	.num_resources	= 1,
 	.resource	= &physmap_flash_resource,
 };
-
-void physmap_configure(unsigned long addr, unsigned long size,
-		int bankwidth, void (*set_vpp)(struct map_info *, int))
-{
-	physmap_flash_resource.start = addr;
-	physmap_flash_resource.end = addr + size - 1;
-	physmap_flash_data.width = bankwidth;
-	physmap_flash_data.set_vpp = set_vpp;
-}
-
-void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
-{
-	physmap_flash_data.nr_parts = num_parts;
-	physmap_flash_data.parts = parts;
-}
 #endif
 
 static int __init physmap_init(void)
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/physmap_of.c linux-libre-3.2-gnu/drivers/mtd/maps/physmap_of.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/physmap_of.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/physmap_of.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,58 +34,10 @@
 
 struct of_flash {
 	struct mtd_info		*cmtd;
-	struct mtd_partition	*parts;
 	int list_size; /* number of elements in of_flash_list */
 	struct of_flash_list	list[0];
 };
 
-#define OF_FLASH_PARTS(info)	((info)->parts)
-static int parse_obsolete_partitions(struct platform_device *dev,
-				     struct of_flash *info,
-				     struct device_node *dp)
-{
-	int i, plen, nr_parts;
-	const struct {
-		__be32 offset, len;
-	} *part;
-	const char *names;
-
-	part = of_get_property(dp, "partitions", &plen);
-	if (!part)
-		return 0; /* No partitions found */
-
-	dev_warn(&dev->dev, "Device tree uses obsolete partition map binding\n");
-
-	nr_parts = plen / sizeof(part[0]);
-
-	info->parts = kzalloc(nr_parts * sizeof(*info->parts), GFP_KERNEL);
-	if (!info->parts)
-		return -ENOMEM;
-
-	names = of_get_property(dp, "partition-names", &plen);
-
-	for (i = 0; i < nr_parts; i++) {
-		info->parts[i].offset = be32_to_cpu(part->offset);
-		info->parts[i].size   = be32_to_cpu(part->len) & ~1;
-		if (be32_to_cpu(part->len) & 1) /* bit 0 set signifies read only partition */
-			info->parts[i].mask_flags = MTD_WRITEABLE;
-
-		if (names && (plen > 0)) {
-			int len = strlen(names) + 1;
-
-			info->parts[i].name = (char *)names;
-			plen -= len;
-			names += len;
-		} else {
-			info->parts[i].name = "unnamed";
-		}
-
-		part++;
-	}
-
-	return nr_parts;
-}
-
 static int of_flash_remove(struct platform_device *dev)
 {
 	struct of_flash *info;
@@ -101,11 +53,8 @@
 		mtd_concat_destroy(info->cmtd);
 	}
 
-	if (info->cmtd) {
-		if (OF_FLASH_PARTS(info))
-			kfree(OF_FLASH_PARTS(info));
+	if (info->cmtd)
 		mtd_device_unregister(info->cmtd);
-	}
 
 	for (i = 0; i < info->list_size; i++) {
 		if (info->list[i].mtd)
@@ -165,7 +114,8 @@
    specifies the list of partition probers to use. If none is given then the
    default is use. These take precedence over other device tree
    information. */
-static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot", NULL };
+static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
+					"ofpart", "ofoldpart", NULL };
 static const char ** __devinit of_get_probes(struct device_node *dp)
 {
 	const char *cp;
@@ -218,6 +168,7 @@
 	int reg_tuple_size;
 	struct mtd_info **mtd_list = NULL;
 	resource_size_t res_size;
+	struct mtd_part_parser_data ppdata;
 
 	match = of_match_device(of_flash_match, &dev->dev);
 	if (!match)
@@ -331,29 +282,12 @@
 	if (err)
 		goto err_out;
 
+	ppdata.of_node = dp;
 	part_probe_types = of_get_probes(dp);
-	err = parse_mtd_partitions(info->cmtd, part_probe_types,
-				   &info->parts, 0);
-	if (err < 0) {
-		of_free_probes(part_probe_types);
-		goto err_out;
-	}
+	mtd_device_parse_register(info->cmtd, part_probe_types, &ppdata,
+			NULL, 0);
 	of_free_probes(part_probe_types);
 
-	if (err == 0) {
-		err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);
-		if (err < 0)
-			goto err_out;
-	}
-
-	if (err == 0) {
-		err = parse_obsolete_partitions(dev, info, dp);
-		if (err < 0)
-			goto err_out;
-	}
-
-	mtd_device_register(info->cmtd, info->parts, err);
-
 	kfree(mtd_list);
 
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/plat-ram.c linux-libre-3.2-gnu/drivers/mtd/maps/plat-ram.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/plat-ram.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/plat-ram.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,8 +44,6 @@
 	struct device		*dev;
 	struct mtd_info		*mtd;
 	struct map_info		 map;
-	struct mtd_partition	*partitions;
-	bool			free_partitions;
 	struct resource		*area;
 	struct platdata_mtd_ram	*pdata;
 };
@@ -95,10 +93,6 @@
 
 	if (info->mtd) {
 		mtd_device_unregister(info->mtd);
-		if (info->partitions) {
-			if (info->free_partitions)
-				kfree(info->partitions);
-		}
 		map_destroy(info->mtd);
 	}
 
@@ -228,28 +222,19 @@
 	/* check to see if there are any available partitions, or wether
 	 * to add this device whole */
 
-	if (!pdata->nr_partitions) {
-		/* try to probe using the supplied probe type */
-		if (pdata->probes) {
-			err = parse_mtd_partitions(info->mtd, pdata->probes,
-					   &info->partitions, 0);
-			info->free_partitions = 1;
-			if (err > 0)
-				err = mtd_device_register(info->mtd,
-					info->partitions, err);
-		}
-	}
-	/* use the static mapping */
-	else
-		err = mtd_device_register(info->mtd, pdata->partitions,
-					  pdata->nr_partitions);
+	err = mtd_device_parse_register(info->mtd, pdata->probes, 0,
+			pdata->partitions, pdata->nr_partitions);
 	if (!err)
 		dev_info(&pdev->dev, "registered mtd device\n");
 
-	/* add the whole device. */
-	err = mtd_device_register(info->mtd, NULL, 0);
-	if (err)
-		dev_err(&pdev->dev, "failed to register the entire device\n");
+	if (pdata->nr_partitions) {
+		/* add the whole device. */
+		err = mtd_device_register(info->mtd, NULL, 0);
+		if (err) {
+			dev_err(&pdev->dev,
+				"failed to register the entire device\n");
+		}
+	}
 
 	return err;
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/pxa2xx-flash.c linux-libre-3.2-gnu/drivers/mtd/maps/pxa2xx-flash.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/pxa2xx-flash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/pxa2xx-flash.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,8 +41,6 @@
 }
 
 struct pxa2xx_flash_info {
-	struct mtd_partition	*parts;
-	int			nr_parts;
 	struct mtd_info		*mtd;
 	struct map_info		map;
 };
@@ -55,9 +53,7 @@
 {
 	struct flash_platform_data *flash = pdev->dev.platform_data;
 	struct pxa2xx_flash_info *info;
-	struct mtd_partition *parts;
 	struct resource *res;
-	int ret = 0;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
@@ -71,8 +67,6 @@
 	info->map.bankwidth = flash->width;
 	info->map.phys = res->start;
 	info->map.size = resource_size(res);
-	info->parts = flash->parts;
-	info->nr_parts = flash->nr_parts;
 
 	info->map.virt = ioremap(info->map.phys, info->map.size);
 	if (!info->map.virt) {
@@ -104,18 +98,7 @@
 	}
 	info->mtd->owner = THIS_MODULE;
 
-	ret = parse_mtd_partitions(info->mtd, probes, &parts, 0);
-
-	if (ret > 0) {
-		info->nr_parts = ret;
-		info->parts = parts;
-	}
-
-	if (!info->nr_parts)
-		printk("Registering %s as whole device\n",
-		       info->map.name);
-
-	mtd_device_register(info->mtd, info->parts, info->nr_parts);
+	mtd_device_parse_register(info->mtd, probes, 0, flash->parts, flash->nr_parts);
 
 	platform_set_drvdata(pdev, info);
 	return 0;
@@ -133,7 +116,6 @@
 	iounmap(info->map.virt);
 	if (info->map.cached)
 		iounmap(info->map.cached);
-	kfree(info->parts);
 	kfree(info);
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/rbtx4939-flash.c linux-libre-3.2-gnu/drivers/mtd/maps/rbtx4939-flash.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/rbtx4939-flash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/rbtx4939-flash.c	2012-01-04 18:55:44.000000000 -0500
@@ -25,8 +25,6 @@
 struct rbtx4939_flash_info {
 	struct mtd_info *mtd;
 	struct map_info map;
-	int nr_parts;
-	struct mtd_partition *parts;
 };
 
 static int rbtx4939_flash_remove(struct platform_device *dev)
@@ -41,8 +39,6 @@
 	if (info->mtd) {
 		struct rbtx4939_flash_data *pdata = dev->dev.platform_data;
 
-		if (info->nr_parts)
-			kfree(info->parts);
 		mtd_device_unregister(info->mtd);
 		map_destroy(info->mtd);
 	}
@@ -50,7 +46,6 @@
 }
 
 static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
-static const char *part_probe_types[] = { "cmdlinepart", NULL };
 
 static int rbtx4939_flash_probe(struct platform_device *dev)
 {
@@ -107,22 +102,11 @@
 	info->mtd->owner = THIS_MODULE;
 	if (err)
 		goto err_out;
+	err = mtd_device_parse_register(info->mtd, NULL, 0,
+			pdata->parts, pdata->nr_parts);
 
-	err = parse_mtd_partitions(info->mtd, part_probe_types,
-				&info->parts, 0);
-	if (err > 0) {
-		mtd_device_register(info->mtd, info->parts, err);
-		info->nr_parts = err;
-		return 0;
-	}
-
-	if (pdata->nr_parts) {
-		pr_notice("Using rbtx4939 partition information\n");
-		mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
-		return 0;
-	}
-
-	mtd_device_register(info->mtd, NULL, 0);
+	if (err)
+		goto err_out;
 	return 0;
 
 err_out:
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/sa1100-flash.c linux-libre-3.2-gnu/drivers/mtd/maps/sa1100-flash.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/sa1100-flash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/sa1100-flash.c	2012-01-04 18:55:44.000000000 -0500
@@ -131,10 +131,8 @@
 };
 
 struct sa_info {
-	struct mtd_partition	*parts;
 	struct mtd_info		*mtd;
 	int			num_subdev;
-	unsigned int		nr_parts;
 	struct sa_subdev_info	subdev[0];
 };
 
@@ -231,8 +229,6 @@
 			mtd_concat_destroy(info->mtd);
 	}
 
-	kfree(info->parts);
-
 	for (i = info->num_subdev - 1; i >= 0; i--)
 		sa1100_destroy_subdev(&info->subdev[i]);
 	kfree(info);
@@ -341,10 +337,8 @@
 static int __devinit sa1100_mtd_probe(struct platform_device *pdev)
 {
 	struct flash_platform_data *plat = pdev->dev.platform_data;
-	struct mtd_partition *parts;
-	const char *part_type = NULL;
 	struct sa_info *info;
-	int err, nr_parts = 0;
+	int err;
 
 	if (!plat)
 		return -ENODEV;
@@ -358,26 +352,8 @@
 	/*
 	 * Partition selection stuff.
 	 */
-	nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0);
-	if (nr_parts > 0) {
-		info->parts = parts;
-		part_type = "dynamic";
-	} else {
-		parts = plat->parts;
-		nr_parts = plat->nr_parts;
-		part_type = "static";
-	}
-
-	if (nr_parts == 0)
-		printk(KERN_NOTICE "SA1100 flash: no partition info "
-			"available, registering whole flash\n");
-	else
-		printk(KERN_NOTICE "SA1100 flash: using %s partition "
-			"definition\n", part_type);
-
-	mtd_device_register(info->mtd, parts, nr_parts);
-
-	info->nr_parts = nr_parts;
+	mtd_device_parse_register(info->mtd, part_probes, 0,
+			plat->parts, plat->nr_parts);
 
 	platform_set_drvdata(pdev, info);
 	err = 0;
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/solutionengine.c linux-libre-3.2-gnu/drivers/mtd/maps/solutionengine.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/solutionengine.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/solutionengine.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,8 +19,6 @@
 static struct mtd_info *flash_mtd;
 static struct mtd_info *eprom_mtd;
 
-static struct mtd_partition *parsed_parts;
-
 struct map_info soleng_eprom_map = {
 	.name = "Solution Engine EPROM",
 	.size = 0x400000,
@@ -51,12 +49,14 @@
 		.size = MTDPART_SIZ_FULL,
 	}
 };
+#define NUM_PARTITIONS ARRAY_SIZE(superh_se_partitions)
+#else
+#define superh_se_partitions NULL
+#define NUM_PARTITIONS 0
 #endif /* CONFIG_MTD_SUPERH_RESERVE */
 
 static int __init init_soleng_maps(void)
 {
-	int nr_parts = 0;
-
 	/* First probe at offset 0 */
 	soleng_flash_map.phys = 0;
 	soleng_flash_map.virt = (void __iomem *)P2SEGADDR(0);
@@ -92,21 +92,8 @@
 		mtd_device_register(eprom_mtd, NULL, 0);
 	}
 
-	nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0);
-
-#ifdef CONFIG_MTD_SUPERH_RESERVE
-	if (nr_parts <= 0) {
-		printk(KERN_NOTICE "Using configured partition at 0x%08x.\n",
-		       CONFIG_MTD_SUPERH_RESERVE);
-		parsed_parts = superh_se_partitions;
-		nr_parts = sizeof(superh_se_partitions)/sizeof(*parsed_parts);
-	}
-#endif /* CONFIG_MTD_SUPERH_RESERVE */
-
-	if (nr_parts > 0)
-		mtd_device_register(flash_mtd, parsed_parts, nr_parts);
-	else
-		mtd_device_register(flash_mtd, NULL, 0);
+	mtd_device_parse_register(flash_mtd, probes, 0,
+			superh_se_partitions, NUM_PARTITIONS);
 
 	return 0;
 }
@@ -118,10 +105,7 @@
 		map_destroy(eprom_mtd);
 	}
 
-	if (parsed_parts)
-		mtd_device_unregister(flash_mtd);
-	else
-		mtd_device_unregister(flash_mtd);
+	mtd_device_unregister(flash_mtd);
 	map_destroy(flash_mtd);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/maps/wr_sbc82xx_flash.c linux-libre-3.2-gnu/drivers/mtd/maps/wr_sbc82xx_flash.c
--- linux-libre-3.1-gnu/drivers/mtd/maps/wr_sbc82xx_flash.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/maps/wr_sbc82xx_flash.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,7 +20,6 @@
 #include <asm/immap_cpm2.h>
 
 static struct mtd_info *sbcmtd[3];
-static struct mtd_partition *sbcmtd_parts[3];
 
 struct map_info sbc82xx_flash_map[3] = {
 	{.name = "Boot flash"},
@@ -101,6 +100,7 @@
 	for (i=0; i<3; i++) {
 		int8_t flashcs[3] = { 0, 6, 1 };
 		int nr_parts;
+		struct mtd_partition *defparts;
 
 		printk(KERN_NOTICE "PowerQUICC II %s (%ld MiB on CS%d",
 		       sbc82xx_flash_map[i].name,
@@ -113,7 +113,8 @@
 		}
 		printk(" at %08lx)\n",  sbc82xx_flash_map[i].phys);
 
-		sbc82xx_flash_map[i].virt = ioremap(sbc82xx_flash_map[i].phys, sbc82xx_flash_map[i].size);
+		sbc82xx_flash_map[i].virt = ioremap(sbc82xx_flash_map[i].phys,
+						    sbc82xx_flash_map[i].size);
 
 		if (!sbc82xx_flash_map[i].virt) {
 			printk("Failed to ioremap\n");
@@ -129,24 +130,20 @@
 
 		sbcmtd[i]->owner = THIS_MODULE;
 
-		nr_parts = parse_mtd_partitions(sbcmtd[i], part_probes,
-						&sbcmtd_parts[i], 0);
-		if (nr_parts > 0) {
-			mtd_device_register(sbcmtd[i], sbcmtd_parts[i],
-					    nr_parts);
-			continue;
-		}
-
 		/* No partitioning detected. Use default */
 		if (i == 2) {
-			mtd_device_register(sbcmtd[i], NULL, 0);
+			defparts = NULL;
+			nr_parts = 0;
 		} else if (i == bigflash) {
-			mtd_device_register(sbcmtd[i], bigflash_parts,
-					    ARRAY_SIZE(bigflash_parts));
+			defparts = bigflash_parts;
+			nr_parts = ARRAY_SIZE(bigflash_parts);
 		} else {
-			mtd_device_register(sbcmtd[i], smallflash_parts,
-					    ARRAY_SIZE(smallflash_parts));
+			defparts = smallflash_parts;
+			nr_parts = ARRAY_SIZE(smallflash_parts);
 		}
+
+		mtd_device_parse_register(sbcmtd[i], part_probes, 0,
+					  defparts, nr_parts);
 	}
 	return 0;
 }
@@ -159,12 +156,8 @@
 		if (!sbcmtd[i])
 			continue;
 
-		if (i<2 || sbcmtd_parts[i])
-			mtd_device_unregister(sbcmtd[i]);
-		else
-			mtd_device_unregister(sbcmtd[i]);
+		mtd_device_unregister(sbcmtd[i]);
 
-		kfree(sbcmtd_parts[i]);
 		map_destroy(sbcmtd[i]);
 
 		iounmap((void *)sbc82xx_flash_map[i].virt);
diff -druN linux-libre-3.1-gnu/drivers/mtd/mtd_blkdevs.c linux-libre-3.2-gnu/drivers/mtd/mtd_blkdevs.c
--- linux-libre-3.1-gnu/drivers/mtd/mtd_blkdevs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/mtd_blkdevs.c	2012-01-04 18:55:44.000000000 -0500
@@ -426,6 +426,8 @@
 	new->rq->queuedata = new;
 	blk_queue_logical_block_size(new->rq, tr->blksize);
 
+	queue_flag_set_unlocked(QUEUE_FLAG_NONROT, new->rq);
+
 	if (tr->discard) {
 		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, new->rq);
 		new->rq->limits.max_discard_sectors = UINT_MAX;
diff -druN linux-libre-3.1-gnu/drivers/mtd/mtdblock.c linux-libre-3.2-gnu/drivers/mtd/mtdblock.c
--- linux-libre-3.1-gnu/drivers/mtd/mtdblock.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/mtdblock.c	2012-01-04 18:55:44.000000000 -0500
@@ -44,7 +44,7 @@
 	enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state;
 };
 
-static struct mutex mtdblks_lock;
+static DEFINE_MUTEX(mtdblks_lock);
 
 /*
  * Cache stuff...
@@ -119,7 +119,7 @@
 	if (mtdblk->cache_state != STATE_DIRTY)
 		return 0;
 
-	DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: writing cached data for \"%s\" "
+	pr_debug("mtdblock: writing cached data for \"%s\" "
 			"at 0x%lx, size 0x%x\n", mtd->name,
 			mtdblk->cache_offset, mtdblk->cache_size);
 
@@ -148,7 +148,7 @@
 	size_t retlen;
 	int ret;
 
-	DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n",
+	pr_debug("mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n",
 		mtd->name, pos, len);
 
 	if (!sect_size)
@@ -218,7 +218,7 @@
 	size_t retlen;
 	int ret;
 
-	DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n",
+	pr_debug("mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n",
 			mtd->name, pos, len);
 
 	if (!sect_size)
@@ -283,7 +283,7 @@
 {
 	struct mtdblk_dev *mtdblk = container_of(mbd, struct mtdblk_dev, mbd);
 
-	DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n");
+	pr_debug("mtdblock_open\n");
 
 	mutex_lock(&mtdblks_lock);
 	if (mtdblk->count) {
@@ -303,7 +303,7 @@
 
 	mutex_unlock(&mtdblks_lock);
 
-	DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
+	pr_debug("ok\n");
 
 	return 0;
 }
@@ -312,7 +312,7 @@
 {
 	struct mtdblk_dev *mtdblk = container_of(mbd, struct mtdblk_dev, mbd);
 
-   	DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n");
+	pr_debug("mtdblock_release\n");
 
 	mutex_lock(&mtdblks_lock);
 
@@ -329,7 +329,7 @@
 
 	mutex_unlock(&mtdblks_lock);
 
-	DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
+	pr_debug("ok\n");
 
 	return 0;
 }
@@ -389,8 +389,6 @@
 
 static int __init init_mtdblock(void)
 {
-	mutex_init(&mtdblks_lock);
-
 	return register_mtd_blktrans(&mtdblock_tr);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/mtdblock_ro.c linux-libre-3.2-gnu/drivers/mtd/mtdblock_ro.c
--- linux-libre-3.1-gnu/drivers/mtd/mtdblock_ro.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/mtdblock_ro.c	2012-01-04 18:55:44.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/blktrans.h>
+#include <linux/module.h>
 
 static int mtdblock_readsect(struct mtd_blktrans_dev *dev,
 			      unsigned long block, char *buf)
diff -druN linux-libre-3.1-gnu/drivers/mtd/mtdchar.c linux-libre-3.2-gnu/drivers/mtd/mtdchar.c
--- linux-libre-3.1-gnu/drivers/mtd/mtdchar.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/mtdchar.c	2012-01-04 18:55:44.000000000 -0500
@@ -43,7 +43,7 @@
 
 /*
  * Data structure to hold the pointer to the mtd device as well
- * as mode information ofr various use cases.
+ * as mode information of various use cases.
  */
 struct mtd_file_info {
 	struct mtd_info *mtd;
@@ -86,7 +86,7 @@
 	struct mtd_file_info *mfi;
 	struct inode *mtd_ino;
 
-	DEBUG(MTD_DEBUG_LEVEL0, "MTD_open\n");
+	pr_debug("MTD_open\n");
 
 	/* You can't open the RO devices RW */
 	if ((file->f_mode & FMODE_WRITE) && (minor & 1))
@@ -151,7 +151,7 @@
 	struct mtd_file_info *mfi = file->private_data;
 	struct mtd_info *mtd = mfi->mtd;
 
-	DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
+	pr_debug("MTD_close\n");
 
 	/* Only sync if opened RW */
 	if ((file->f_mode & FMODE_WRITE) && mtd->sync)
@@ -195,7 +195,7 @@
 	size_t size = count;
 	char *kbuf;
 
-	DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n");
+	pr_debug("MTD_read\n");
 
 	if (*ppos + count > mtd->size)
 		count = mtd->size - *ppos;
@@ -211,17 +211,17 @@
 		len = min_t(size_t, count, size);
 
 		switch (mfi->mode) {
-		case MTD_MODE_OTP_FACTORY:
+		case MTD_FILE_MODE_OTP_FACTORY:
 			ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf);
 			break;
-		case MTD_MODE_OTP_USER:
+		case MTD_FILE_MODE_OTP_USER:
 			ret = mtd->read_user_prot_reg(mtd, *ppos, len, &retlen, kbuf);
 			break;
-		case MTD_MODE_RAW:
+		case MTD_FILE_MODE_RAW:
 		{
 			struct mtd_oob_ops ops;
 
-			ops.mode = MTD_OOB_RAW;
+			ops.mode = MTD_OPS_RAW;
 			ops.datbuf = kbuf;
 			ops.oobbuf = NULL;
 			ops.len = len;
@@ -233,16 +233,16 @@
 		default:
 			ret = mtd->read(mtd, *ppos, len, &retlen, kbuf);
 		}
-		/* Nand returns -EBADMSG on ecc errors, but it returns
+		/* Nand returns -EBADMSG on ECC errors, but it returns
 		 * the data. For our userspace tools it is important
-		 * to dump areas with ecc errors !
+		 * to dump areas with ECC errors!
 		 * For kernel internal usage it also might return -EUCLEAN
 		 * 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
 		 */
-		if (!ret || (ret == -EUCLEAN) || (ret == -EBADMSG)) {
+		if (!ret || mtd_is_bitflip_or_eccerr(ret)) {
 			*ppos += retlen;
 			if (copy_to_user(buf, kbuf, retlen)) {
 				kfree(kbuf);
@@ -278,7 +278,7 @@
 	int ret=0;
 	int len;
 
-	DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n");
+	pr_debug("MTD_write\n");
 
 	if (*ppos == mtd->size)
 		return -ENOSPC;
@@ -302,10 +302,10 @@
 		}
 
 		switch (mfi->mode) {
-		case MTD_MODE_OTP_FACTORY:
+		case MTD_FILE_MODE_OTP_FACTORY:
 			ret = -EROFS;
 			break;
-		case MTD_MODE_OTP_USER:
+		case MTD_FILE_MODE_OTP_USER:
 			if (!mtd->write_user_prot_reg) {
 				ret = -EOPNOTSUPP;
 				break;
@@ -313,13 +313,14 @@
 			ret = mtd->write_user_prot_reg(mtd, *ppos, len, &retlen, kbuf);
 			break;
 
-		case MTD_MODE_RAW:
+		case MTD_FILE_MODE_RAW:
 		{
 			struct mtd_oob_ops ops;
 
-			ops.mode = MTD_OOB_RAW;
+			ops.mode = MTD_OPS_RAW;
 			ops.datbuf = kbuf;
 			ops.oobbuf = NULL;
+			ops.ooboffs = 0;
 			ops.len = len;
 
 			ret = mtd->write_oob(mtd, *ppos, &ops);
@@ -367,13 +368,13 @@
 		if (!mtd->read_fact_prot_reg)
 			ret = -EOPNOTSUPP;
 		else
-			mfi->mode = MTD_MODE_OTP_FACTORY;
+			mfi->mode = MTD_FILE_MODE_OTP_FACTORY;
 		break;
 	case MTD_OTP_USER:
 		if (!mtd->read_fact_prot_reg)
 			ret = -EOPNOTSUPP;
 		else
-			mfi->mode = MTD_MODE_OTP_USER;
+			mfi->mode = MTD_FILE_MODE_OTP_USER;
 		break;
 	default:
 		ret = -EINVAL;
@@ -390,6 +391,7 @@
 	uint64_t start, uint32_t length, void __user *ptr,
 	uint32_t __user *retp)
 {
+	struct mtd_file_info *mfi = file->private_data;
 	struct mtd_oob_ops ops;
 	uint32_t retlen;
 	int ret = 0;
@@ -409,9 +411,10 @@
 		return ret;
 
 	ops.ooblen = length;
-	ops.ooboffs = start & (mtd->oobsize - 1);
+	ops.ooboffs = start & (mtd->writesize - 1);
 	ops.datbuf = NULL;
-	ops.mode = MTD_OOB_PLACE;
+	ops.mode = (mfi->mode == MTD_FILE_MODE_RAW) ? MTD_OPS_RAW :
+		MTD_OPS_PLACE_OOB;
 
 	if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
 		return -EINVAL;
@@ -420,7 +423,7 @@
 	if (IS_ERR(ops.oobbuf))
 		return PTR_ERR(ops.oobbuf);
 
-	start &= ~((uint64_t)mtd->oobsize - 1);
+	start &= ~((uint64_t)mtd->writesize - 1);
 	ret = mtd->write_oob(mtd, start, &ops);
 
 	if (ops.oobretlen > 0xFFFFFFFFU)
@@ -433,9 +436,11 @@
 	return ret;
 }
 
-static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
-	uint32_t length, void __user *ptr, uint32_t __user *retp)
+static int mtd_do_readoob(struct file *file, struct mtd_info *mtd,
+	uint64_t start, uint32_t length, void __user *ptr,
+	uint32_t __user *retp)
 {
+	struct mtd_file_info *mfi = file->private_data;
 	struct mtd_oob_ops ops;
 	int ret = 0;
 
@@ -451,9 +456,10 @@
 		return ret;
 
 	ops.ooblen = length;
-	ops.ooboffs = start & (mtd->oobsize - 1);
+	ops.ooboffs = start & (mtd->writesize - 1);
 	ops.datbuf = NULL;
-	ops.mode = MTD_OOB_PLACE;
+	ops.mode = (mfi->mode == MTD_FILE_MODE_RAW) ? MTD_OPS_RAW :
+		MTD_OPS_PLACE_OOB;
 
 	if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
 		return -EINVAL;
@@ -462,7 +468,7 @@
 	if (!ops.oobbuf)
 		return -ENOMEM;
 
-	start &= ~((uint64_t)mtd->oobsize - 1);
+	start &= ~((uint64_t)mtd->writesize - 1);
 	ret = mtd->read_oob(mtd, start, &ops);
 
 	if (put_user(ops.oobretlen, retp))
@@ -472,13 +478,29 @@
 		ret = -EFAULT;
 
 	kfree(ops.oobbuf);
+
+	/*
+	 * NAND returns -EBADMSG on ECC errors, but it returns the OOB
+	 * 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
+	 * been corrected by the ECC algorithm.
+	 *
+	 * Note: currently the standard NAND function, nand_read_oob_std,
+	 * does not calculate ECC for the OOB area, so do not rely on
+	 * this behavior unless you have replaced it with your own.
+	 */
+	if (mtd_is_bitflip_or_eccerr(ret))
+		return 0;
+
 	return ret;
 }
 
 /*
  * Copies (and truncates, if necessary) data from the larger struct,
  * nand_ecclayout, to the smaller, deprecated layout struct,
- * nand_ecclayout_user. This is necessary only to suppport the deprecated
+ * nand_ecclayout_user. This is necessary only to support the deprecated
  * API ioctl ECCGETLAYOUT while allowing all new functionality to use
  * nand_ecclayout flexibly (i.e. the struct may change size in new
  * releases without requiring major rewrites).
@@ -544,6 +566,55 @@
 	}
 }
 
+static int mtd_write_ioctl(struct mtd_info *mtd,
+		struct mtd_write_req __user *argp)
+{
+	struct mtd_write_req req;
+	struct mtd_oob_ops ops;
+	void __user *usr_data, *usr_oob;
+	int ret;
+
+	if (copy_from_user(&req, argp, sizeof(req)) ||
+			!access_ok(VERIFY_READ, req.usr_data, req.len) ||
+			!access_ok(VERIFY_READ, req.usr_oob, req.ooblen))
+		return -EFAULT;
+	if (!mtd->write_oob)
+		return -EOPNOTSUPP;
+
+	ops.mode = req.mode;
+	ops.len = (size_t)req.len;
+	ops.ooblen = (size_t)req.ooblen;
+	ops.ooboffs = 0;
+
+	usr_data = (void __user *)(uintptr_t)req.usr_data;
+	usr_oob = (void __user *)(uintptr_t)req.usr_oob;
+
+	if (req.usr_data) {
+		ops.datbuf = memdup_user(usr_data, ops.len);
+		if (IS_ERR(ops.datbuf))
+			return PTR_ERR(ops.datbuf);
+	} else {
+		ops.datbuf = NULL;
+	}
+
+	if (req.usr_oob) {
+		ops.oobbuf = memdup_user(usr_oob, ops.ooblen);
+		if (IS_ERR(ops.oobbuf)) {
+			kfree(ops.datbuf);
+			return PTR_ERR(ops.oobbuf);
+		}
+	} else {
+		ops.oobbuf = NULL;
+	}
+
+	ret = mtd->write_oob(mtd, (loff_t)req.start, &ops);
+
+	kfree(ops.datbuf);
+	kfree(ops.oobbuf);
+
+	return ret;
+}
+
 static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
 {
 	struct mtd_file_info *mfi = file->private_data;
@@ -553,7 +624,7 @@
 	u_long size;
 	struct mtd_info_user info;
 
-	DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n");
+	pr_debug("MTD_ioctl\n");
 
 	size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
 	if (cmd & IOC_IN) {
@@ -601,8 +672,8 @@
 		info.erasesize	= mtd->erasesize;
 		info.writesize	= mtd->writesize;
 		info.oobsize	= mtd->oobsize;
-		/* The below fields are obsolete */
-		info.ecctype	= -1;
+		/* The below field is obsolete */
+		info.padding	= 0;
 		if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
 			return -EFAULT;
 		break;
@@ -698,7 +769,7 @@
 		if (copy_from_user(&buf, argp, sizeof(buf)))
 			ret = -EFAULT;
 		else
-			ret = mtd_do_readoob(mtd, buf.start, buf.length,
+			ret = mtd_do_readoob(file, mtd, buf.start, buf.length,
 				buf.ptr, &buf_user->start);
 		break;
 	}
@@ -725,12 +796,19 @@
 		if (copy_from_user(&buf, argp, sizeof(buf)))
 			ret = -EFAULT;
 		else
-			ret = mtd_do_readoob(mtd, buf.start, buf.length,
+			ret = mtd_do_readoob(file, mtd, buf.start, buf.length,
 				(void __user *)(uintptr_t)buf.usr_ptr,
 				&buf_user->length);
 		break;
 	}
 
+	case MEMWRITE:
+	{
+		ret = mtd_write_ioctl(mtd,
+		      (struct mtd_write_req __user *)arg);
+		break;
+	}
+
 	case MEMLOCK:
 	{
 		struct erase_info_user einfo;
@@ -827,7 +905,7 @@
 		if (copy_from_user(&mode, argp, sizeof(int)))
 			return -EFAULT;
 
-		mfi->mode = MTD_MODE_NORMAL;
+		mfi->mode = MTD_FILE_MODE_NORMAL;
 
 		ret = otp_select_filemode(mfi, mode);
 
@@ -843,11 +921,11 @@
 			return -ENOMEM;
 		ret = -EOPNOTSUPP;
 		switch (mfi->mode) {
-		case MTD_MODE_OTP_FACTORY:
+		case MTD_FILE_MODE_OTP_FACTORY:
 			if (mtd->get_fact_prot_info)
 				ret = mtd->get_fact_prot_info(mtd, buf, 4096);
 			break;
-		case MTD_MODE_OTP_USER:
+		case MTD_FILE_MODE_OTP_USER:
 			if (mtd->get_user_prot_info)
 				ret = mtd->get_user_prot_info(mtd, buf, 4096);
 			break;
@@ -871,7 +949,7 @@
 	{
 		struct otp_info oinfo;
 
-		if (mfi->mode != MTD_MODE_OTP_USER)
+		if (mfi->mode != MTD_FILE_MODE_OTP_USER)
 			return -EINVAL;
 		if (copy_from_user(&oinfo, argp, sizeof(oinfo)))
 			return -EFAULT;
@@ -882,7 +960,7 @@
 	}
 #endif
 
-	/* This ioctl is being deprecated - it truncates the ecc layout */
+	/* This ioctl is being deprecated - it truncates the ECC layout */
 	case ECCGETLAYOUT:
 	{
 		struct nand_ecclayout_user *usrlay;
@@ -915,17 +993,17 @@
 		mfi->mode = 0;
 
 		switch(arg) {
-		case MTD_MODE_OTP_FACTORY:
-		case MTD_MODE_OTP_USER:
+		case MTD_FILE_MODE_OTP_FACTORY:
+		case MTD_FILE_MODE_OTP_USER:
 			ret = otp_select_filemode(mfi, arg);
 			break;
 
-		case MTD_MODE_RAW:
+		case MTD_FILE_MODE_RAW:
 			if (!mtd->read_oob || !mtd->write_oob)
 				return -EOPNOTSUPP;
 			mfi->mode = arg;
 
-		case MTD_MODE_NORMAL:
+		case MTD_FILE_MODE_NORMAL:
 			break;
 		default:
 			ret = -EINVAL;
@@ -1011,7 +1089,7 @@
 		if (copy_from_user(&buf, argp, sizeof(buf)))
 			ret = -EFAULT;
 		else
-			ret = mtd_do_readoob(mtd, buf.start,
+			ret = mtd_do_readoob(file, mtd, buf.start,
 				buf.length, compat_ptr(buf.ptr),
 				&buf_user->start);
 		break;
@@ -1144,7 +1222,7 @@
 
 	if (mtd_ino) {
 		/* Destroy the inode if it exists */
-		mtd_ino->i_nlink = 0;
+		clear_nlink(mtd_ino);
 		iput(mtd_ino);
 	}
 }
diff -druN linux-libre-3.1-gnu/drivers/mtd/mtdconcat.c linux-libre-3.2-gnu/drivers/mtd/mtdconcat.c
--- linux-libre-3.1-gnu/drivers/mtd/mtdconcat.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/mtdconcat.c	2012-01-04 18:55:44.000000000 -0500
@@ -95,10 +95,10 @@
 
 		/* Save information about bitflips! */
 		if (unlikely(err)) {
-			if (err == -EBADMSG) {
+			if (mtd_is_eccerr(err)) {
 				mtd->ecc_stats.failed++;
 				ret = err;
-			} else if (err == -EUCLEAN) {
+			} else if (mtd_is_bitflip(err)) {
 				mtd->ecc_stats.corrected++;
 				/* Do not overwrite -EBADMSG !! */
 				if (!ret)
@@ -279,10 +279,10 @@
 
 		/* Save information about bitflips! */
 		if (unlikely(err)) {
-			if (err == -EBADMSG) {
+			if (mtd_is_eccerr(err)) {
 				mtd->ecc_stats.failed++;
 				ret = err;
-			} else if (err == -EUCLEAN) {
+			} else if (mtd_is_bitflip(err)) {
 				mtd->ecc_stats.corrected++;
 				/* Do not overwrite -EBADMSG !! */
 				if (!ret)
@@ -770,7 +770,7 @@
 
 	/*
 	 * Set up the new "super" device's MTD object structure, check for
-	 * incompatibilites between the subdevices.
+	 * incompatibilities between the subdevices.
 	 */
 	concat->mtd.type = subdev[0]->type;
 	concat->mtd.flags = subdev[0]->flags;
diff -druN linux-libre-3.1-gnu/drivers/mtd/mtdcore.c linux-libre-3.2-gnu/drivers/mtd/mtdcore.c
--- linux-libre-3.1-gnu/drivers/mtd/mtdcore.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/mtdcore.c	2012-01-04 18:55:44.000000000 -0500
@@ -362,7 +362,7 @@
 			      MTD_DEVT(i) + 1,
 			      NULL, "mtd%dro", i);
 
-	DEBUG(0, "mtd: Giving out device %d to %s\n", i, mtd->name);
+	pr_debug("mtd: Giving out device %d to %s\n", i, mtd->name);
 	/* No need to get a refcount on the module containing
 	   the notifier, since we hold the mtd_table_mutex */
 	list_for_each_entry(not, &mtd_notifiers, list)
@@ -429,27 +429,63 @@
 }
 
 /**
- * mtd_device_register - register an MTD device.
+ * mtd_device_parse_register - parse partitions and register an MTD device.
  *
- * @master: the MTD device to register
- * @parts: the partitions to register - only valid if nr_parts > 0
- * @nr_parts: the number of partitions in parts.  If zero then the full MTD
- *            device is registered
+ * @mtd: the MTD device to register
+ * @types: the list of MTD partition probes to try, see
+ *         'parse_mtd_partitions()' for more information
+ * @parser_data: MTD partition parser-specific data
+ * @parts: fallback partition information to register, if parsing fails;
+ *         only valid if %nr_parts > %0
+ * @nr_parts: the number of partitions in parts, if zero then the full
+ *            MTD device is registered if no partition info is found
  *
- * Register an MTD device with the system and optionally, a number of
- * partitions.  If nr_parts is 0 then the whole device is registered, otherwise
- * only the partitions are registered.  To register both the full device *and*
- * the partitions, call mtd_device_register() twice, once with nr_parts == 0
- * and once equal to the number of partitions.
+ * This function aggregates MTD partitions parsing (done by
+ * 'parse_mtd_partitions()') and MTD device and partitions registering. It
+ * basically follows the most common pattern found in many MTD drivers:
+ *
+ * * It first tries to probe partitions on MTD device @mtd using parsers
+ *   specified in @types (if @types is %NULL, then the default list of parsers
+ *   is used, see 'parse_mtd_partitions()' for more information). If none are
+ *   found this functions tries to fallback to information specified in
+ *   @parts/@nr_parts.
+ * * If any partitioning info was found, this function registers the found
+ *   partitions.
+ * * If no partitions were found this function just registers the MTD device
+ *   @mtd and exits.
+ *
+ * Returns zero in case of success and a negative error code in case of failure.
  */
-int mtd_device_register(struct mtd_info *master,
-			const struct mtd_partition *parts,
-			int nr_parts)
+int mtd_device_parse_register(struct mtd_info *mtd, const char **types,
+			      struct mtd_part_parser_data *parser_data,
+			      const struct mtd_partition *parts,
+			      int nr_parts)
 {
-	return parts ? add_mtd_partitions(master, parts, nr_parts) :
-		add_mtd_device(master);
+	int err;
+	struct mtd_partition *real_parts;
+
+	err = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
+	if (err <= 0 && nr_parts && parts) {
+		real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
+				     GFP_KERNEL);
+		if (!real_parts)
+			err = -ENOMEM;
+		else
+			err = nr_parts;
+	}
+
+	if (err > 0) {
+		err = add_mtd_partitions(mtd, real_parts, err);
+		kfree(real_parts);
+	} else if (err == 0) {
+		err = add_mtd_device(mtd);
+		if (err == 1)
+			err = -ENODEV;
+	}
+
+	return err;
 }
-EXPORT_SYMBOL_GPL(mtd_device_register);
+EXPORT_SYMBOL_GPL(mtd_device_parse_register);
 
 /**
  * mtd_device_unregister - unregister an existing MTD device.
diff -druN linux-libre-3.1-gnu/drivers/mtd/mtdcore.h linux-libre-3.2-gnu/drivers/mtd/mtdcore.h
--- linux-libre-3.1-gnu/drivers/mtd/mtdcore.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/mtdcore.h	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,9 @@
 extern int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *,
 			      int);
 extern int del_mtd_partitions(struct mtd_info *);
+extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
+				struct mtd_partition **pparts,
+				struct mtd_part_parser_data *data);
 
 #define mtd_for_each_device(mtd)			\
 	for ((mtd) = __mtd_next_device(0);		\
diff -druN linux-libre-3.1-gnu/drivers/mtd/mtdoops.c linux-libre-3.2-gnu/drivers/mtd/mtdoops.c
--- linux-libre-3.1-gnu/drivers/mtd/mtdoops.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/mtdoops.c	2012-01-04 18:55:44.000000000 -0500
@@ -258,7 +258,7 @@
 		ret = mtd->read(mtd, page * record_size, MTDOOPS_HEADER_SIZE,
 				&retlen, (u_char *) &count[0]);
 		if (retlen != MTDOOPS_HEADER_SIZE ||
-				(ret < 0 && ret != -EUCLEAN)) {
+				(ret < 0 && !mtd_is_bitflip(ret))) {
 			printk(KERN_ERR "mtdoops: read failure at %ld (%td of %d read), err %d\n",
 			       page * record_size, retlen,
 			       MTDOOPS_HEADER_SIZE, ret);
diff -druN linux-libre-3.1-gnu/drivers/mtd/mtdpart.c linux-libre-3.2-gnu/drivers/mtd/mtdpart.c
--- linux-libre-3.1-gnu/drivers/mtd/mtdpart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/mtdpart.c	2012-01-04 18:55:44.000000000 -0500
@@ -73,9 +73,9 @@
 	res = part->master->read(part->master, from + part->offset,
 				   len, retlen, buf);
 	if (unlikely(res)) {
-		if (res == -EUCLEAN)
+		if (mtd_is_bitflip(res))
 			mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected;
-		if (res == -EBADMSG)
+		if (mtd_is_eccerr(res))
 			mtd->ecc_stats.failed += part->master->ecc_stats.failed - stats.failed;
 	}
 	return res;
@@ -130,7 +130,7 @@
 	if (ops->oobbuf) {
 		size_t len, pages;
 
-		if (ops->mode == MTD_OOB_AUTO)
+		if (ops->mode == MTD_OPS_AUTO_OOB)
 			len = mtd->oobavail;
 		else
 			len = mtd->oobsize;
@@ -142,9 +142,9 @@
 
 	res = part->master->read_oob(part->master, from + part->offset, ops);
 	if (unlikely(res)) {
-		if (res == -EUCLEAN)
+		if (mtd_is_bitflip(res))
 			mtd->ecc_stats.corrected++;
-		if (res == -EBADMSG)
+		if (mtd_is_eccerr(res))
 			mtd->ecc_stats.failed++;
 	}
 	return res;
@@ -479,6 +479,19 @@
 			       (unsigned long long)cur_offset, (unsigned long long)slave->offset);
 		}
 	}
+	if (slave->offset == MTDPART_OFS_RETAIN) {
+		slave->offset = cur_offset;
+		if (master->size - slave->offset >= slave->mtd.size) {
+			slave->mtd.size = master->size - slave->offset
+							- slave->mtd.size;
+		} else {
+			printk(KERN_ERR "mtd partition \"%s\" doesn't have enough space: %#llx < %#llx, disabled\n",
+				part->name, master->size - slave->offset,
+				slave->mtd.size);
+			/* register to preserve ordering */
+			goto out_register;
+		}
+	}
 	if (slave->mtd.size == MTDPART_SIZ_FULL)
 		slave->mtd.size = master->size - slave->offset;
 
@@ -693,6 +706,8 @@
 	return ret;
 }
 
+#define put_partition_parser(p) do { module_put((p)->owner); } while (0)
+
 int register_mtd_parser(struct mtd_part_parser *p)
 {
 	spin_lock(&part_parser_lock);
@@ -712,19 +727,51 @@
 }
 EXPORT_SYMBOL_GPL(deregister_mtd_parser);
 
+/*
+ * Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if you
+ * are changing this array!
+ */
+static const char *default_mtd_part_types[] = {
+	"cmdlinepart",
+	"ofpart",
+	NULL
+};
+
+/**
+ * parse_mtd_partitions - parse MTD partitions
+ * @master: the master partition (describes whole MTD device)
+ * @types: names of partition parsers to try or %NULL
+ * @pparts: array of partitions found is returned here
+ * @data: MTD partition parser-specific data
+ *
+ * This function tries to find partition on MTD device @master. It uses MTD
+ * partition parsers, specified in @types. However, if @types is %NULL, then
+ * the default list of parsers is used. The default list contains only the
+ * "cmdlinepart" and "ofpart" parsers ATM.
+ *
+ * This function may return:
+ * o a negative error code in case of failure
+ * o zero if no partitions were found
+ * o a positive number of found partitions, in which case on exit @pparts will
+ *   point to an array containing this number of &struct mtd_info objects.
+ */
 int parse_mtd_partitions(struct mtd_info *master, const char **types,
-			 struct mtd_partition **pparts, unsigned long origin)
+			 struct mtd_partition **pparts,
+			 struct mtd_part_parser_data *data)
 {
 	struct mtd_part_parser *parser;
 	int ret = 0;
 
+	if (!types)
+		types = default_mtd_part_types;
+
 	for ( ; ret <= 0 && *types; types++) {
 		parser = get_partition_parser(*types);
 		if (!parser && !request_module("%s", *types))
 				parser = get_partition_parser(*types);
 		if (!parser)
 			continue;
-		ret = (*parser->parse_fn)(master, pparts, origin);
+		ret = (*parser->parse_fn)(master, pparts, data);
 		if (ret > 0) {
 			printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
 			       ret, parser->name, master->name);
@@ -733,7 +780,6 @@
 	}
 	return ret;
 }
-EXPORT_SYMBOL_GPL(parse_mtd_partitions);
 
 int mtd_is_partition(struct mtd_info *mtd)
 {
diff -druN linux-libre-3.1-gnu/drivers/mtd/mtdsuper.c linux-libre-3.2-gnu/drivers/mtd/mtdsuper.c
--- linux-libre-3.1-gnu/drivers/mtd/mtdsuper.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/mtdsuper.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,6 +14,7 @@
 
 #include <linux/mtd/super.h>
 #include <linux/namei.h>
+#include <linux/export.h>
 #include <linux/ctype.h>
 #include <linux/slab.h>
 
@@ -26,12 +27,12 @@
 	struct mtd_info *mtd = _mtd;
 
 	if (sb->s_mtd == mtd) {
-		DEBUG(2, "MTDSB: Match on device %d (\"%s\")\n",
+		pr_debug("MTDSB: Match on device %d (\"%s\")\n",
 		      mtd->index, mtd->name);
 		return 1;
 	}
 
-	DEBUG(2, "MTDSB: No match, device %d (\"%s\"), device %d (\"%s\")\n",
+	pr_debug("MTDSB: No match, device %d (\"%s\"), device %d (\"%s\")\n",
 	      sb->s_mtd->index, sb->s_mtd->name, mtd->index, mtd->name);
 	return 0;
 }
@@ -70,7 +71,7 @@
 		goto already_mounted;
 
 	/* fresh new superblock */
-	DEBUG(1, "MTDSB: New superblock for device %d (\"%s\")\n",
+	pr_debug("MTDSB: New superblock for device %d (\"%s\")\n",
 	      mtd->index, mtd->name);
 
 	sb->s_flags = flags;
@@ -87,7 +88,7 @@
 
 	/* new mountpoint for an already mounted superblock */
 already_mounted:
-	DEBUG(1, "MTDSB: Device %d (\"%s\") is already mounted\n",
+	pr_debug("MTDSB: Device %d (\"%s\") is already mounted\n",
 	      mtd->index, mtd->name);
 	put_mtd_device(mtd);
 	return dget(sb->s_root);
@@ -108,7 +109,7 @@
 
 	mtd = get_mtd_device(NULL, mtdnr);
 	if (IS_ERR(mtd)) {
-		DEBUG(0, "MTDSB: Device #%u doesn't appear to exist\n", mtdnr);
+		pr_debug("MTDSB: Device #%u doesn't appear to exist\n", mtdnr);
 		return ERR_CAST(mtd);
 	}
 
@@ -131,7 +132,7 @@
 	if (!dev_name)
 		return ERR_PTR(-EINVAL);
 
-	DEBUG(2, "MTDSB: dev_name \"%s\"\n", dev_name);
+	pr_debug("MTDSB: dev_name \"%s\"\n", dev_name);
 
 	/* the preferred way of mounting in future; especially when
 	 * CONFIG_BLOCK=n - we specify the underlying MTD device by number or
@@ -142,7 +143,7 @@
 			struct mtd_info *mtd;
 
 			/* mount by MTD device name */
-			DEBUG(1, "MTDSB: mtd:%%s, name \"%s\"\n",
+			pr_debug("MTDSB: mtd:%%s, name \"%s\"\n",
 			      dev_name + 4);
 
 			mtd = get_mtd_device_nm(dev_name + 4);
@@ -163,7 +164,7 @@
 			mtdnr = simple_strtoul(dev_name + 3, &endptr, 0);
 			if (!*endptr) {
 				/* It was a valid number */
-				DEBUG(1, "MTDSB: mtd%%d, mtdnr %d\n",
+				pr_debug("MTDSB: mtd%%d, mtdnr %d\n",
 				      mtdnr);
 				return mount_mtd_nr(fs_type, flags,
 						     dev_name, data,
@@ -179,10 +180,10 @@
 	bdev = lookup_bdev(dev_name);
 	if (IS_ERR(bdev)) {
 		ret = PTR_ERR(bdev);
-		DEBUG(1, "MTDSB: lookup_bdev() returned %d\n", ret);
+		pr_debug("MTDSB: lookup_bdev() returned %d\n", ret);
 		return ERR_PTR(ret);
 	}
-	DEBUG(1, "MTDSB: lookup_bdev() returned 0\n");
+	pr_debug("MTDSB: lookup_bdev() returned 0\n");
 
 	ret = -EINVAL;
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/mtdswap.c linux-libre-3.2-gnu/drivers/mtd/mtdswap.c
--- linux-libre-3.1-gnu/drivers/mtd/mtdswap.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/mtdswap.c	2012-01-04 18:55:44.000000000 -0500
@@ -86,7 +86,7 @@
 	unsigned int flags;
 	unsigned int active_count;
 	unsigned int erase_count;
-	unsigned int pad;		/* speeds up pointer decremtnt */
+	unsigned int pad;		/* speeds up pointer decrement */
 };
 
 #define MTDSWAP_ECNT_MIN(rbroot) (rb_entry(rb_first(rbroot), struct swap_eb, \
@@ -314,7 +314,7 @@
 {
 	int ret = d->mtd->read_oob(d->mtd, from, ops);
 
-	if (ret == -EUCLEAN)
+	if (mtd_is_bitflip(ret))
 		return ret;
 
 	if (ret) {
@@ -350,11 +350,11 @@
 	ops.oobbuf = d->oob_buf;
 	ops.ooboffs = 0;
 	ops.datbuf = NULL;
-	ops.mode = MTD_OOB_AUTO;
+	ops.mode = MTD_OPS_AUTO_OOB;
 
 	ret = mtdswap_read_oob(d, offset, &ops);
 
-	if (ret && ret != -EUCLEAN)
+	if (ret && !mtd_is_bitflip(ret))
 		return ret;
 
 	data = (struct mtdswap_oobdata *)d->oob_buf;
@@ -363,7 +363,7 @@
 
 	if (le16_to_cpu(data->magic) == MTDSWAP_MAGIC_CLEAN) {
 		eb->erase_count = le32_to_cpu(data->count);
-		if (ret == -EUCLEAN)
+		if (mtd_is_bitflip(ret))
 			ret = MTDSWAP_SCANNED_BITFLIP;
 		else {
 			if (le16_to_cpu(data2->magic) == MTDSWAP_MAGIC_DIRTY)
@@ -389,7 +389,7 @@
 
 	ops.ooboffs = 0;
 	ops.oobbuf = (uint8_t *)&n;
-	ops.mode = MTD_OOB_AUTO;
+	ops.mode = MTD_OPS_AUTO_OOB;
 	ops.datbuf = NULL;
 
 	if (marker == MTDSWAP_TYPE_CLEAN) {
@@ -408,7 +408,7 @@
 	if (ret) {
 		dev_warn(d->dev, "Write OOB failed for block at %08llx "
 			"error %d\n", offset, ret);
-		if (ret == -EIO || ret == -EBADMSG)
+		if (ret == -EIO || mtd_is_eccerr(ret))
 			mtdswap_handle_write_error(d, eb);
 		return ret;
 	}
@@ -628,7 +628,7 @@
 			TREE_COUNT(d, CLEAN)--;
 
 			ret = mtdswap_write_marker(d, eb, MTDSWAP_TYPE_DIRTY);
-		} while (ret == -EIO || ret == -EBADMSG);
+		} while (ret == -EIO || mtd_is_eccerr(ret));
 
 		if (ret)
 			return ret;
@@ -678,7 +678,7 @@
 	ret = mtdswap_map_free_block(d, page, bp);
 	eb = d->eb_data + (*bp / d->pages_per_eblk);
 
-	if (ret == -EIO || ret == -EBADMSG) {
+	if (ret == -EIO || mtd_is_eccerr(ret)) {
 		d->curr_write = NULL;
 		eb->active_count--;
 		d->revmap[*bp] = PAGE_UNDEF;
@@ -690,7 +690,7 @@
 
 	writepos = (loff_t)*bp << PAGE_SHIFT;
 	ret =  mtd->write(mtd, writepos, PAGE_SIZE, &retlen, buf);
-	if (ret == -EIO || ret == -EBADMSG) {
+	if (ret == -EIO || mtd_is_eccerr(ret)) {
 		d->curr_write_pos--;
 		eb->active_count--;
 		d->revmap[*bp] = PAGE_UNDEF;
@@ -738,7 +738,7 @@
 retry:
 	ret = mtd->read(mtd, readpos, PAGE_SIZE, &retlen, d->page_buf);
 
-	if (ret < 0 && ret != -EUCLEAN) {
+	if (ret < 0 && !mtd_is_bitflip(ret)) {
 		oldeb = d->eb_data + oldblock / d->pages_per_eblk;
 		oldeb->flags |= EBLOCK_READERR;
 
@@ -931,7 +931,7 @@
 	struct mtd_oob_ops ops;
 	int ret;
 
-	ops.mode = MTD_OOB_AUTO;
+	ops.mode = MTD_OPS_AUTO_OOB;
 	ops.len = mtd->writesize;
 	ops.ooblen = mtd->ecclayout->oobavail;
 	ops.ooboffs = 0;
@@ -1016,7 +1016,7 @@
 
 	if (ret == 0)
 		mtdswap_rb_add(d, eb, MTDSWAP_CLEAN);
-	else if (ret != -EIO && ret != -EBADMSG)
+	else if (ret != -EIO && !mtd_is_eccerr(ret))
 		mtdswap_rb_add(d, eb, MTDSWAP_DIRTY);
 
 	return 0;
@@ -1164,7 +1164,7 @@
 	ret = mtd->read(mtd, readpos, PAGE_SIZE, &retlen, buf);
 
 	d->mtd_read_count++;
-	if (ret == -EUCLEAN) {
+	if (mtd_is_bitflip(ret)) {
 		eb->flags |= EBLOCK_BITFLIP;
 		mtdswap_rb_add(d, eb, MTDSWAP_BITFLIP);
 		ret = 0;
@@ -1374,11 +1374,10 @@
 		goto revmap_fail;
 
 	eblk_bytes = sizeof(struct swap_eb)*d->eblks;
-	d->eb_data = vmalloc(eblk_bytes);
+	d->eb_data = vzalloc(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;
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/ams-delta.c linux-libre-3.2-gnu/drivers/mtd/nand/ams-delta.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/ams-delta.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/ams-delta.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,7 +26,7 @@
 #include <asm/io.h>
 #include <mach/hardware.h>
 #include <asm/sizes.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
 #include <plat/board-ams-delta.h>
 
 /*
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/atmel_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/atmel_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/atmel_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/atmel_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -161,37 +161,6 @@
                 !!host->board->rdy_pin_active_low;
 }
 
-/*
- * Minimal-overhead PIO for data access.
- */
-static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
-{
-	struct nand_chip	*nand_chip = mtd->priv;
-
-	__raw_readsb(nand_chip->IO_ADDR_R, buf, len);
-}
-
-static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
-{
-	struct nand_chip	*nand_chip = mtd->priv;
-
-	__raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
-}
-
-static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len)
-{
-	struct nand_chip	*nand_chip = mtd->priv;
-
-	__raw_writesb(nand_chip->IO_ADDR_W, buf, len);
-}
-
-static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
-{
-	struct nand_chip	*nand_chip = mtd->priv;
-
-	__raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
-}
-
 static void dma_complete_func(void *completion)
 {
 	complete(completion);
@@ -266,33 +235,27 @@
 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);
+	/* if no DMA operation possible, use PIO */
+	memcpy_fromio(buf, chip->IO_ADDR_R, 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);
+	/* if no DMA operation possible, use PIO */
+	memcpy_toio(chip->IO_ADDR_W, buf, len);
 }
 
 /*
@@ -481,10 +444,6 @@
 	}
 }
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-static const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
-
 /*
  * Probe for the NAND device.
  */
@@ -496,8 +455,6 @@
 	struct resource *regs;
 	struct resource *mem;
 	int res;
-	struct mtd_partition *partitions = NULL;
-	int num_partitions = 0;
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem) {
@@ -583,7 +540,7 @@
 
 	if (on_flash_bbt) {
 		printk(KERN_INFO "atmel_nand: Use On Flash BBT\n");
-		nand_chip->options |= NAND_USE_FLASH_BBT;
+		nand_chip->bbt_options |= NAND_BBT_USE_FLASH;
 	}
 
 	if (!cpu_has_dma())
@@ -594,7 +551,7 @@
 
 		dma_cap_zero(mask);
 		dma_cap_set(DMA_MEMCPY, mask);
-		host->dma_chan = dma_request_channel(mask, 0, NULL);
+		host->dma_chan = dma_request_channel(mask, NULL, NULL);
 		if (!host->dma_chan) {
 			dev_err(host->dev, "Failed to request DMA channel\n");
 			use_dma = 0;
@@ -655,27 +612,12 @@
 		goto err_scan_tail;
 	}
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
 	mtd->name = "atmel_nand";
-	num_partitions = parse_mtd_partitions(mtd, part_probes,
-					      &partitions, 0);
-#endif
-	if (num_partitions <= 0 && host->board->partition_info)
-		partitions = host->board->partition_info(mtd->size,
-							 &num_partitions);
-
-	if ((!partitions) || (num_partitions == 0)) {
-		printk(KERN_ERR "atmel_nand: No partitions defined, or unsupported device.\n");
-		res = -ENXIO;
-		goto err_no_partitions;
-	}
-
-	res = mtd_device_register(mtd, partitions, num_partitions);
+	res = mtd_device_parse_register(mtd, NULL, 0,
+			host->board->parts, host->board->num_parts);
 	if (!res)
 		return res;
 
-err_no_partitions:
-	nand_release(mtd);
 err_scan_tail:
 err_scan_ident:
 err_no_card:
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/au1550nd.c linux-libre-3.2-gnu/drivers/mtd/nand/au1550nd.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/au1550nd.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/au1550nd.c	2012-01-04 18:55:44.000000000 -0500
@@ -19,7 +19,11 @@
 #include <linux/mtd/partitions.h>
 #include <asm/io.h>
 
-#include <asm/mach-au1x00/au1xxx.h>
+#ifdef CONFIG_MIPS_PB1550
+#include <asm/mach-pb1x00/pb1550.h>
+#elif defined(CONFIG_MIPS_DB1550)
+#include <asm/mach-db1x00/db1x00.h>
+#endif
 #include <asm/mach-db1x00/bcsr.h>
 
 /*
@@ -48,7 +52,7 @@
  * au_read_byte -  read one byte from the chip
  * @mtd:	MTD device structure
  *
- *  read function for 8bit buswith
+ * read function for 8bit buswidth
  */
 static u_char au_read_byte(struct mtd_info *mtd)
 {
@@ -63,7 +67,7 @@
  * @mtd:	MTD device structure
  * @byte:	pointer to data byte to write
  *
- *  write function for 8it buswith
+ * write function for 8it buswidth
  */
 static void au_write_byte(struct mtd_info *mtd, u_char byte)
 {
@@ -73,11 +77,10 @@
 }
 
 /**
- * au_read_byte16 -  read one byte endianess aware from the chip
+ * au_read_byte16 -  read one byte endianness aware from the chip
  * @mtd:	MTD device structure
  *
- *  read function for 16bit buswith with
- * endianess conversion
+ * read function for 16bit buswidth with endianness conversion
  */
 static u_char au_read_byte16(struct mtd_info *mtd)
 {
@@ -88,12 +91,11 @@
 }
 
 /**
- * au_write_byte16 -  write one byte endianess aware to the chip
+ * au_write_byte16 -  write one byte endianness aware to the chip
  * @mtd:	MTD device structure
  * @byte:	pointer to data byte to write
  *
- *  write function for 16bit buswith with
- * endianess conversion
+ * write function for 16bit buswidth with endianness conversion
  */
 static void au_write_byte16(struct mtd_info *mtd, u_char byte)
 {
@@ -106,8 +108,7 @@
  * au_read_word -  read one word from the chip
  * @mtd:	MTD device structure
  *
- *  read function for 16bit buswith without
- * endianess conversion
+ * read function for 16bit buswidth without endianness conversion
  */
 static u16 au_read_word(struct mtd_info *mtd)
 {
@@ -123,7 +124,7 @@
  * @buf:	data buffer
  * @len:	number of bytes to write
  *
- *  write function for 8bit buswith
+ * write function for 8bit buswidth
  */
 static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
@@ -142,7 +143,7 @@
  * @buf:	buffer to store date
  * @len:	number of bytes to read
  *
- *  read function for 8bit buswith
+ * read function for 8bit buswidth
  */
 static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
@@ -161,7 +162,7 @@
  * @buf:	buffer containing the data to compare
  * @len:	number of bytes to compare
  *
- *  verify function for 8bit buswith
+ * verify function for 8bit buswidth
  */
 static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
@@ -183,7 +184,7 @@
  * @buf:	data buffer
  * @len:	number of bytes to write
  *
- *  write function for 16bit buswith
+ * write function for 16bit buswidth
  */
 static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
 {
@@ -205,7 +206,7 @@
  * @buf:	buffer to store date
  * @len:	number of bytes to read
  *
- *  read function for 16bit buswith
+ * read function for 16bit buswidth
  */
 static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
 {
@@ -226,7 +227,7 @@
  * @buf:	buffer containing the data to compare
  * @len:	number of bytes to compare
  *
- *  verify function for 16bit buswith
+ * verify function for 16bit buswidth
  */
 static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
 {
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/autcpu12.c linux-libre-3.2-gnu/drivers/mtd/nand/autcpu12.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/autcpu12.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/autcpu12.c	2012-01-04 18:55:44.000000000 -0500
@@ -172,9 +172,9 @@
 
 	/* Enable the following for a flash based bad block table */
 	/*
-	   this->options = NAND_USE_FLASH_BBT;
+	   this->bbt_options = NAND_BBT_USE_FLASH;
 	 */
-	this->options = NAND_USE_FLASH_BBT;
+	this->bbt_options = NAND_BBT_USE_FLASH;
 
 	/* Scan to find existence of the device */
 	if (nand_scan(autcpu12_mtd, 1)) {
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/bcm_umi_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/bcm_umi_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/bcm_umi_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/bcm_umi_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -52,8 +52,6 @@
 static const __devinitconst char gBanner[] = KERN_INFO \
 	"BCM UMI MTD NAND Driver: 1.00\n";
 
-const char *part_probes[] = { "cmdlinepart", NULL };
-
 #if NAND_ECC_BCH
 static uint8_t scan_ff_pattern[] = { 0xff };
 
@@ -376,16 +374,18 @@
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	if (!r)
-		return -ENXIO;
+	if (!r) {
+		err = -ENXIO;
+		goto out_free;
+	}
 
 	/* map physical address */
 	bcm_umi_io_base = ioremap(r->start, resource_size(r));
 
 	if (!bcm_umi_io_base) {
 		printk(KERN_ERR "ioremap to access BCM UMI NAND chip failed\n");
-		kfree(board_mtd);
-		return -EIO;
+		err = -EIO;
+		goto out_free;
 	}
 
 	/* Get pointer to private data */
@@ -401,9 +401,8 @@
 	/* Initialize the NAND hardware.  */
 	if (bcm_umi_nand_inithw() < 0) {
 		printk(KERN_ERR "BCM UMI NAND chip could not be initialized\n");
-		iounmap(bcm_umi_io_base);
-		kfree(board_mtd);
-		return -EIO;
+		err = -EIO;
+		goto out_unmap;
 	}
 
 	/* Set address of NAND IO lines */
@@ -436,7 +435,7 @@
 #if USE_DMA
 	err = nand_dma_init();
 	if (err != 0)
-		return err;
+		goto out_unmap;
 #endif
 
 	/* Figure out the size of the device that we have.
@@ -447,9 +446,7 @@
 	err = nand_scan_ident(board_mtd, 1, NULL);
 	if (err) {
 		printk(KERN_ERR "nand_scan failed: %d\n", err);
-		iounmap(bcm_umi_io_base);
-		kfree(board_mtd);
-		return err;
+		goto out_unmap;
 	}
 
 	/* Now that we know the nand size, we can setup the ECC layout */
@@ -468,13 +465,14 @@
 		{
 			printk(KERN_ERR "NAND - Unrecognized pagesize: %d\n",
 					 board_mtd->writesize);
-			return -EINVAL;
+			err = -EINVAL;
+			goto out_unmap;
 		}
 	}
 
 #if NAND_ECC_BCH
 	if (board_mtd->writesize > 512) {
-		if (this->options & NAND_USE_FLASH_BBT)
+		if (this->bbt_options & NAND_BBT_USE_FLASH)
 			largepage_bbt.options = NAND_BBT_SCAN2NDPAGE;
 		this->badblock_pattern = &largepage_bbt;
 	}
@@ -485,33 +483,20 @@
 	err = nand_scan_tail(board_mtd);
 	if (err) {
 		printk(KERN_ERR "nand_scan failed: %d\n", err);
-		iounmap(bcm_umi_io_base);
-		kfree(board_mtd);
-		return err;
+		goto out_unmap;
 	}
 
 	/* Register the partitions */
-	{
-		int nr_partitions;
-		struct mtd_partition *partition_info;
-
-		board_mtd->name = "bcm_umi-nand";
-		nr_partitions =
-		    parse_mtd_partitions(board_mtd, part_probes,
-					 &partition_info, 0);
-
-		if (nr_partitions <= 0) {
-			printk(KERN_ERR "BCM UMI NAND: Too few partitions - %d\n",
-			       nr_partitions);
-			iounmap(bcm_umi_io_base);
-			kfree(board_mtd);
-			return -EIO;
-		}
-		mtd_device_register(board_mtd, partition_info, nr_partitions);
-	}
+	board_mtd->name = "bcm_umi-nand";
+	mtd_device_parse_register(board_mtd, NULL, 0, NULL, 0);
 
 	/* Return happy */
 	return 0;
+out_unmap:
+	iounmap(bcm_umi_io_base);
+out_free:
+	kfree(board_mtd);
+	return err;
 }
 
 static int bcm_umi_nand_remove(struct platform_device *pdev)
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/cafe_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/cafe_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/cafe_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/cafe_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <asm/io.h>
 
 #define CAFE_NAND_CTRL1		0x00
@@ -57,7 +58,6 @@
 
 struct cafe_priv {
 	struct nand_chip nand;
-	struct mtd_partition *parts;
 	struct pci_dev *pdev;
 	void __iomem *mmio;
 	struct rs_control *rs;
@@ -371,7 +371,7 @@
 	return 1;
 }
 /**
- * cafe_nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read
+ * cafe_nand_read_page_syndrome - [REPLACEABLE] hardware ecc syndrome based page read
  * @mtd:	mtd info structure
  * @chip:	nand chip info structure
  * @buf:	buffer to store read data
@@ -630,8 +630,6 @@
 	struct cafe_priv *cafe;
 	uint32_t ctrl;
 	int err = 0;
-	struct mtd_partition *parts;
-	int nr_parts;
 
 	/* Very old versions shared the same PCI ident for all three
 	   functions on the chip. Verify the class too... */
@@ -686,7 +684,8 @@
 	cafe->nand.chip_delay = 0;
 
 	/* Enable the following for a flash based bad block table */
-	cafe->nand.options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR | NAND_OWN_BUFFERS;
+	cafe->nand.bbt_options = NAND_BBT_USE_FLASH;
+	cafe->nand.options = NAND_NO_AUTOINCR | NAND_OWN_BUFFERS;
 
 	if (skipbbt) {
 		cafe->nand.options |= NAND_SKIP_BBTSCAN;
@@ -799,18 +798,9 @@
 
 	pci_set_drvdata(pdev, mtd);
 
-	/* We register the whole device first, separate from the partitions */
-	mtd_device_register(mtd, NULL, 0);
-
-#ifdef CONFIG_MTD_CMDLINE_PARTS
 	mtd->name = "cafe_nand";
-#endif
-	nr_parts = parse_mtd_partitions(mtd, part_probes, &parts, 0);
-	if (nr_parts > 0) {
-		cafe->parts = parts;
-		dev_info(&cafe->pdev->dev, "%d partitions found\n", nr_parts);
-		mtd_device_register(mtd, parts, nr_parts);
-	}
+	mtd_device_parse_register(mtd, part_probes, 0, NULL, 0);
+
 	goto out;
 
  out_irq:
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/cmx270_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/cmx270_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/cmx270_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/cmx270_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
+#include <linux/module.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -50,8 +51,6 @@
 };
 #define NUM_PARTITIONS (ARRAY_SIZE(partition_info))
 
-const char *part_probes[] = { "cmdlinepart", NULL };
-
 static u_char cmx270_read_byte(struct mtd_info *mtd)
 {
 	struct nand_chip *this = mtd->priv;
@@ -151,9 +150,6 @@
 static int __init cmx270_init(void)
 {
 	struct nand_chip *this;
-	const char *part_type;
-	struct mtd_partition *mtd_parts;
-	int mtd_parts_nb = 0;
 	int ret;
 
 	if (!(machine_is_armcore() && cpu_is_pxa27x()))
@@ -222,23 +218,9 @@
 		goto err_scan;
 	}
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-	mtd_parts_nb = parse_mtd_partitions(cmx270_nand_mtd, part_probes,
-					    &mtd_parts, 0);
-	if (mtd_parts_nb > 0)
-		part_type = "command line";
-	else
-		mtd_parts_nb = 0;
-#endif
-	if (!mtd_parts_nb) {
-		mtd_parts = partition_info;
-		mtd_parts_nb = NUM_PARTITIONS;
-		part_type = "static";
-	}
-
 	/* Register the partitions */
-	pr_notice("Using %s partition definition\n", part_type);
-	ret = mtd_device_register(cmx270_nand_mtd, mtd_parts, mtd_parts_nb);
+	ret = mtd_device_parse_register(cmx270_nand_mtd, NULL, 0,
+					partition_info, NUM_PARTITIONS);
 	if (ret)
 		goto err_scan;
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/cs553x_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/cs553x_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/cs553x_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/cs553x_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -239,7 +239,8 @@
 	this->ecc.correct  = nand_correct_data;
 
 	/* Enable the following for a flash based bad block table */
-	this->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR;
+	this->bbt_options = NAND_BBT_USE_FLASH;
+	this->options = NAND_NO_AUTOINCR;
 
 	/* Scan to find existence of the device */
 	if (nand_scan(new_mtd, 1)) {
@@ -277,15 +278,11 @@
 	return 0;
 }
 
-static const char *part_probes[] = { "cmdlinepart", NULL };
-
 static int __init cs553x_init(void)
 {
 	int err = -ENXIO;
 	int i;
 	uint64_t val;
-	int mtd_parts_nb = 0;
-	struct mtd_partition *mtd_parts = NULL;
 
 	/* If the CPU isn't a Geode GX or LX, abort */
 	if (!is_geode())
@@ -315,13 +312,9 @@
 	   do mtdconcat etc. if we want to. */
 	for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
 		if (cs553x_mtd[i]) {
-
 			/* If any devices registered, return success. Else the last error. */
-			mtd_parts_nb = parse_mtd_partitions(cs553x_mtd[i], part_probes, &mtd_parts, 0);
-			if (mtd_parts_nb > 0)
-				printk(KERN_NOTICE "Using command line partition definition\n");
-			mtd_device_register(cs553x_mtd[i], mtd_parts,
-					    mtd_parts_nb);
+			mtd_device_parse_register(cs553x_mtd[i], NULL, 0,
+						  NULL, 0);
 			err = 0;
 		}
 	}
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/davinci_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/davinci_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/davinci_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/davinci_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -57,7 +57,6 @@
 
 	struct device		*dev;
 	struct clk		*clk;
-	bool			partitioned;
 
 	bool			is_readmode;
 
@@ -530,8 +529,6 @@
 	int				ret;
 	uint32_t			val;
 	nand_ecc_modes_t		ecc_mode;
-	struct mtd_partition		*mtd_parts = NULL;
-	int				mtd_parts_nb = 0;
 
 	/* insist on board-specific configuration */
 	if (!pdata)
@@ -581,7 +578,9 @@
 	info->chip.chip_delay	= 0;
 	info->chip.select_chip	= nand_davinci_select_chip;
 
-	/* options such as NAND_USE_FLASH_BBT or 16-bit widths */
+	/* options such as NAND_BBT_USE_FLASH */
+	info->chip.bbt_options	= pdata->bbt_options;
+	/* options such as 16-bit widths */
 	info->chip.options	= pdata->options;
 	info->chip.bbt_td	= pdata->bbt_td;
 	info->chip.bbt_md	= pdata->bbt_md;
@@ -751,33 +750,8 @@
 	if (ret < 0)
 		goto err_scan;
 
-	if (mtd_has_cmdlinepart()) {
-		static const char *probes[] __initconst = {
-			"cmdlinepart", NULL
-		};
-
-		mtd_parts_nb = parse_mtd_partitions(&info->mtd, probes,
-						    &mtd_parts, 0);
-	}
-
-	if (mtd_parts_nb <= 0) {
-		mtd_parts = pdata->parts;
-		mtd_parts_nb = pdata->nr_parts;
-	}
-
-	/* Register any partitions */
-	if (mtd_parts_nb > 0) {
-		ret = mtd_device_register(&info->mtd, mtd_parts,
-					  mtd_parts_nb);
-		if (ret == 0)
-			info->partitioned = true;
-	}
-
-	/* If there's no partition info, just package the whole chip
-	 * as a single MTD device.
-	 */
-	if (!info->partitioned)
-		ret = mtd_device_register(&info->mtd, NULL, 0) ? -ENODEV : 0;
+	ret = mtd_device_parse_register(&info->mtd, NULL, 0,
+			pdata->parts, pdata->nr_parts);
 
 	if (ret < 0)
 		goto err_scan;
@@ -816,9 +790,6 @@
 static int __exit nand_davinci_remove(struct platform_device *pdev)
 {
 	struct davinci_nand_info *info = platform_get_drvdata(pdev);
-	int status;
-
-	status = mtd_device_unregister(&info->mtd);
 
 	spin_lock_irq(&davinci_nand_lock);
 	if (info->chip.ecc.mode == NAND_ECC_HW_SYNDROME)
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/denali.c linux-libre-3.2-gnu/drivers/mtd/nand/denali.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/denali.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/denali.c	2012-01-04 18:55:44.000000000 -0500
@@ -1346,6 +1346,7 @@
 	 * */
 	denali->bbtskipbytes = ioread32(denali->flash_reg +
 						SPARE_AREA_SKIP_BYTES);
+	detect_max_banks(denali);
 	denali_nand_reset(denali);
 	iowrite32(0x0F, denali->flash_reg + RB_PIN_ENABLED);
 	iowrite32(CHIP_EN_DONT_CARE__FLAG,
@@ -1356,7 +1357,6 @@
 	/* Should set value for these registers when init */
 	iowrite32(0, denali->flash_reg + TWO_ROW_ADDR_CYCLES);
 	iowrite32(1, denali->flash_reg + ECC_ENABLE);
-	detect_max_banks(denali);
 	denali_nand_timing_set(denali);
 	denali_irq_init(denali);
 }
@@ -1577,7 +1577,8 @@
 	denali->nand.bbt_md = &bbt_mirror_descr;
 
 	/* skip the scan for now until we have OOB read and write support */
-	denali->nand.options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN;
+	denali->nand.bbt_options |= NAND_BBT_USE_FLASH;
+	denali->nand.options |= NAND_SKIP_BBTSCAN;
 	denali->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
 
 	/* Denali Controller only support 15bit and 8bit ECC in MRST,
@@ -1676,7 +1677,6 @@
 	struct denali_nand_info *denali = pci_get_drvdata(dev);
 
 	nand_release(&denali->mtd);
-	mtd_device_unregister(&denali->mtd);
 
 	denali_irq_cleanup(dev->irq, denali);
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/diskonchip.c linux-libre-3.2-gnu/drivers/mtd/nand/diskonchip.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/diskonchip.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/diskonchip.c	2012-01-04 18:55:44.000000000 -0500
@@ -31,6 +31,7 @@
 #include <linux/mtd/doc2000.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/inftl.h>
+#include <linux/module.h>
 
 /* Where to look for the devices? */
 #ifndef CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS
@@ -132,7 +133,7 @@
 
 /*
  * The HW decoder in the DoC ASIC's provides us a error syndrome,
- * which we must convert to a standard syndrom usable by the generic
+ * which we must convert to a standard syndrome usable by the generic
  * Reed-Solomon library code.
  *
  * Fabrice Bellard figured this out in the old docecc code. I added
@@ -153,7 +154,7 @@
 	ds[3] = ((ecc[3] & 0xc0) >> 6) | ((ecc[0] & 0xff) << 2);
 	parity = ecc[1];
 
-	/* Initialize the syndrom buffer */
+	/* Initialize the syndrome buffer */
 	for (i = 0; i < NROOTS; i++)
 		s[i] = ds[0];
 	/*
@@ -1031,7 +1032,7 @@
 		WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
 	else
 		WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
-	if (no_ecc_failures && (ret == -EBADMSG)) {
+	if (no_ecc_failures && mtd_is_eccerr(ret)) {
 		printk(KERN_ERR "suppressing ECC failure\n");
 		ret = 0;
 	}
@@ -1652,7 +1653,7 @@
 	nand->ecc.mode		= NAND_ECC_HW_SYNDROME;
 	nand->ecc.size		= 512;
 	nand->ecc.bytes		= 6;
-	nand->options		= NAND_USE_FLASH_BBT;
+	nand->bbt_options	= NAND_BBT_USE_FLASH;
 
 	doc->physadr		= physadr;
 	doc->virtadr		= virtadr;
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/edb7312.c linux-libre-3.2-gnu/drivers/mtd/nand/edb7312.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/edb7312.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/edb7312.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,203 +0,0 @@
-/*
- *  drivers/mtd/nand/edb7312.c
- *
- *  Copyright (C) 2002 Marius GrÃ¶ger (mag@sysgo.de)
- *
- *  Derived from drivers/mtd/nand/autcpu12.c
- *       Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.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.
- *
- *  Overview:
- *   This is a device driver for the NAND flash device found on the
- *   CLEP7312 board which utilizes the Toshiba TC58V64AFT part. This is
- *   a 64Mibit (8MiB x 8 bits) NAND flash device.
- */
-
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-#include <mach/hardware.h>	/* for CLPS7111_VIRT_BASE */
-#include <asm/sizes.h>
-#include <asm/hardware/clps7111.h>
-
-/*
- * MTD structure for EDB7312 board
- */
-static struct mtd_info *ep7312_mtd = NULL;
-
-/*
- * Values specific to the EDB7312 board (used with EP7312 processor)
- */
-#define EP7312_FIO_PBASE 0x10000000	/* Phys address of flash */
-#define EP7312_PXDR	0x0001	/*
-				 * IO offset to Port B data register
-				 * where the CLE, ALE and NCE pins
-				 * are wired to.
-				 */
-#define EP7312_PXDDR	0x0041	/*
-				 * IO offset to Port B data direction
-				 * register so we can control the IO
-				 * lines.
-				 */
-
-/*
- * Module stuff
- */
-
-static unsigned long ep7312_fio_pbase = EP7312_FIO_PBASE;
-static void __iomem *ep7312_pxdr = (void __iomem *)EP7312_PXDR;
-static void __iomem *ep7312_pxddr = (void __iomem *)EP7312_PXDDR;
-
-/*
- * Define static partitions for flash device
- */
-static struct mtd_partition partition_info[] = {
-	{.name = "EP7312 Nand Flash",
-	 .offset = 0,
-	 .size = 8 * 1024 * 1024}
-};
-
-#define NUM_PARTITIONS 1
-
-/*
- *	hardware specific access to control-lines
- *
- *	NAND_NCE: bit 0 -> bit 6 (bit 7 = 1)
- *	NAND_CLE: bit 1 -> bit 4
- *	NAND_ALE: bit 2 -> bit 5
- */
-static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
-	struct nand_chip *chip = mtd->priv;
-
-	if (ctrl & NAND_CTRL_CHANGE) {
-		unsigned char bits = 0x80;
-
-		bits |= (ctrl & (NAND_CLE | NAND_ALE)) << 3;
-		bits |= (ctrl & NAND_NCE) ? 0x00 : 0x40;
-
-		clps_writeb((clps_readb(ep7312_pxdr)  & 0xF0) | bits,
-			    ep7312_pxdr);
-	}
-	if (cmd != NAND_CMD_NONE)
-		writeb(cmd, chip->IO_ADDR_W);
-}
-
-/*
- *	read device ready pin
- */
-static int ep7312_device_ready(struct mtd_info *mtd)
-{
-	return 1;
-}
-
-const char *part_probes[] = { "cmdlinepart", NULL };
-
-/*
- * Main initialization routine
- */
-static int __init ep7312_init(void)
-{
-	struct nand_chip *this;
-	const char *part_type = 0;
-	int mtd_parts_nb = 0;
-	struct mtd_partition *mtd_parts = 0;
-	void __iomem *ep7312_fio_base;
-
-	/* Allocate memory for MTD device structure and private data */
-	ep7312_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
-	if (!ep7312_mtd) {
-		printk("Unable to allocate EDB7312 NAND MTD device structure.\n");
-		return -ENOMEM;
-	}
-
-	/* map physical address */
-	ep7312_fio_base = ioremap(ep7312_fio_pbase, SZ_1K);
-	if (!ep7312_fio_base) {
-		printk("ioremap EDB7312 NAND flash failed\n");
-		kfree(ep7312_mtd);
-		return -EIO;
-	}
-
-	/* Get pointer to private data */
-	this = (struct nand_chip *)(&ep7312_mtd[1]);
-
-	/* Initialize structures */
-	memset(ep7312_mtd, 0, sizeof(struct mtd_info));
-	memset(this, 0, sizeof(struct nand_chip));
-
-	/* Link the private data with the MTD structure */
-	ep7312_mtd->priv = this;
-	ep7312_mtd->owner = THIS_MODULE;
-
-	/*
-	 * Set GPIO Port B control register so that the pins are configured
-	 * to be outputs for controlling the NAND flash.
-	 */
-	clps_writeb(0xf0, ep7312_pxddr);
-
-	/* insert callbacks */
-	this->IO_ADDR_R = ep7312_fio_base;
-	this->IO_ADDR_W = ep7312_fio_base;
-	this->cmd_ctrl = ep7312_hwcontrol;
-	this->dev_ready = ep7312_device_ready;
-	/* 15 us command delay time */
-	this->chip_delay = 15;
-
-	/* Scan to find existence of the device */
-	if (nand_scan(ep7312_mtd, 1)) {
-		iounmap((void *)ep7312_fio_base);
-		kfree(ep7312_mtd);
-		return -ENXIO;
-	}
-	ep7312_mtd->name = "edb7312-nand";
-	mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, &mtd_parts, 0);
-	if (mtd_parts_nb > 0)
-		part_type = "command line";
-	else
-		mtd_parts_nb = 0;
-	if (mtd_parts_nb == 0) {
-		mtd_parts = partition_info;
-		mtd_parts_nb = NUM_PARTITIONS;
-		part_type = "static";
-	}
-
-	/* Register the partitions */
-	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-	mtd_device_register(ep7312_mtd, mtd_parts, mtd_parts_nb);
-
-	/* Return happy */
-	return 0;
-}
-
-module_init(ep7312_init);
-
-/*
- * Clean up routine
- */
-static void __exit ep7312_cleanup(void)
-{
-	struct nand_chip *this = (struct nand_chip *)&ep7312_mtd[1];
-
-	/* Release resources, unregister device */
-	nand_release(ap7312_mtd);
-
-	/* Release io resource */
-	iounmap(this->IO_ADDR_R);
-
-	/* Free the MTD device structure */
-	kfree(ep7312_mtd);
-}
-
-module_exit(ep7312_cleanup);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Marius Groeger <mag@sysgo.de>");
-MODULE_DESCRIPTION("MTD map driver for Cogent EDB7312 board");
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/fsl_elbc_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/fsl_elbc_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/fsl_elbc_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/fsl_elbc_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -75,7 +75,6 @@
 	unsigned int use_mdr;    /* Non zero if the MDR is to be set      */
 	unsigned int oob;        /* Non zero if operating on OOB data     */
 	unsigned int counter;	 /* counter for the initializations	  */
-	char *oob_poi;           /* Place to write ECC after read back    */
 };
 
 /* These map to the positions used by the FCM hardware ECC generator */
@@ -244,6 +243,25 @@
 		return -EIO;
 	}
 
+	if (chip->ecc.mode != NAND_ECC_HW)
+		return 0;
+
+	if (elbc_fcm_ctrl->read_bytes == mtd->writesize + mtd->oobsize) {
+		uint32_t lteccr = in_be32(&lbc->lteccr);
+		/*
+		 * if command was a full page read and the ELBC
+		 * has the LTECCR register, then bits 12-15 (ppc order) of
+		 * LTECCR indicates which 512 byte sub-pages had fixed errors.
+		 * bits 28-31 are uncorrectable errors, marked elsewhere.
+		 * for small page nand only 1 bit is used.
+		 * if the ELBC doesn't have the lteccr register it reads 0
+		 */
+		if (lteccr & 0x000F000F)
+			out_be32(&lbc->lteccr, 0x000F000F); /* clear lteccr */
+		if (lteccr & 0x000F0000)
+			mtd->ecc_stats.corrected++;
+	}
+
 	return 0;
 }
 
@@ -435,7 +453,6 @@
 
 	/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
 	case NAND_CMD_PAGEPROG: {
-		int full_page;
 		dev_vdbg(priv->dev,
 		         "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
 			 "writing %d bytes.\n", elbc_fcm_ctrl->index);
@@ -445,34 +462,12 @@
 		 * write so the HW generates the ECC.
 		 */
 		if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 ||
-		    elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) {
+		    elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize)
 			out_be32(&lbc->fbcr, elbc_fcm_ctrl->index);
-			full_page = 0;
-		} else {
+		else
 			out_be32(&lbc->fbcr, 0);
-			full_page = 1;
-		}
 
 		fsl_elbc_run_command(mtd);
-
-		/* Read back the page in order to fill in the ECC for the
-		 * caller.  Is this really needed?
-		 */
-		if (full_page && elbc_fcm_ctrl->oob_poi) {
-			out_be32(&lbc->fbcr, 3);
-			set_addr(mtd, 6, page_addr, 1);
-
-			elbc_fcm_ctrl->read_bytes = mtd->writesize + 9;
-
-			fsl_elbc_do_read(chip, 1);
-			fsl_elbc_run_command(mtd);
-
-			memcpy_fromio(elbc_fcm_ctrl->oob_poi + 6,
-				&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], 3);
-			elbc_fcm_ctrl->index += 3;
-		}
-
-		elbc_fcm_ctrl->oob_poi = NULL;
 		return;
 	}
 
@@ -752,13 +747,8 @@
                                 struct nand_chip *chip,
                                 const uint8_t *buf)
 {
-	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
-
 	fsl_elbc_write_buf(mtd, buf, mtd->writesize);
 	fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
-
-	elbc_fcm_ctrl->oob_poi = chip->oob_poi;
 }
 
 static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
@@ -791,8 +781,8 @@
 	chip->bbt_md = &bbt_mirror_descr;
 
 	/* set up nand options */
-	chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
-			NAND_USE_FLASH_BBT;
+	chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR;
+	chip->bbt_options = NAND_BBT_USE_FLASH;
 
 	chip->controller = &elbc_fcm_ctrl->controller;
 	chip->priv = priv;
@@ -829,7 +819,6 @@
 
 	elbc_fcm_ctrl->chips[priv->bank] = NULL;
 	kfree(priv);
-	kfree(elbc_fcm_ctrl);
 	return 0;
 }
 
@@ -842,13 +831,14 @@
 	struct resource res;
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl;
 	static const char *part_probe_types[]
-		= { "cmdlinepart", "RedBoot", NULL };
-	struct mtd_partition *parts;
+		= { "cmdlinepart", "RedBoot", "ofpart", NULL };
 	int ret;
 	int bank;
 	struct device *dev;
 	struct device_node *node = pdev->dev.of_node;
+	struct mtd_part_parser_data ppdata;
 
+	ppdata.of_node = pdev->dev.of_node;
 	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
 		return -ENODEV;
 	lbc = fsl_lbc_ctrl_dev->regs;
@@ -934,17 +924,8 @@
 
 	/* First look for RedBoot table or partitions on the command
 	 * line, these take precedence over device tree information */
-	ret = parse_mtd_partitions(&priv->mtd, part_probe_types, &parts, 0);
-	if (ret < 0)
-		goto err;
-
-	if (ret == 0) {
-		ret = of_mtd_parse_partitions(priv->dev, node, &parts);
-		if (ret < 0)
-			goto err;
-	}
-
-	mtd_device_register(&priv->mtd, parts, ret);
+	mtd_device_parse_register(&priv->mtd, part_probe_types, &ppdata,
+				  NULL, 0);
 
 	printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n",
 	       (unsigned long long)res.start, priv->bank);
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/fsl_upm.c linux-libre-3.2-gnu/drivers/mtd/nand/fsl_upm.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/fsl_upm.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/fsl_upm.c	2012-01-04 18:55:44.000000000 -0500
@@ -158,7 +158,7 @@
 {
 	int ret;
 	struct device_node *flash_np;
-	static const char *part_types[] = { "cmdlinepart", NULL, };
+	struct mtd_part_parser_data ppdata;
 
 	fun->chip.IO_ADDR_R = fun->io_base;
 	fun->chip.IO_ADDR_W = fun->io_base;
@@ -192,18 +192,12 @@
 	if (ret)
 		goto err;
 
-	ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0);
-
-#ifdef CONFIG_MTD_OF_PARTS
-	if (ret == 0) {
-		ret = of_mtd_parse_partitions(fun->dev, flash_np, &fun->parts);
-		if (ret < 0)
-			goto err;
-	}
-#endif
-	ret = mtd_device_register(&fun->mtd, fun->parts, ret);
+	ppdata.of_node = flash_np;
+	ret = mtd_device_parse_register(&fun->mtd, NULL, &ppdata, NULL, 0);
 err:
 	of_node_put(flash_np);
+	if (ret)
+		kfree(fun->mtd.name);
 	return ret;
 }
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/fsmc_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/fsmc_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/fsmc_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/fsmc_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -146,7 +146,7 @@
 	{
 		.name = "Root File System",
 		.offset = 0x460000,
-		.size = 0,
+		.size = MTDPART_SIZ_FULL,
 	},
 };
 
@@ -173,13 +173,10 @@
 	{
 		.name = "Root File System",
 		.offset = 0x800000,
-		.size = 0,
+		.size = MTDPART_SIZ_FULL,
 	},
 };
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
 
 /**
  * struct fsmc_nand_data - structure for FSMC NAND device state
@@ -187,8 +184,6 @@
  * @pid:		Part ID on the AMBA PrimeCell format
  * @mtd:		MTD info for a NAND flash.
  * @nand:		Chip related info for a NAND flash.
- * @partitions:		Partition info for a NAND Flash.
- * @nr_partitions:	Total number of partition of a NAND flash.
  *
  * @ecc_place:		ECC placing locations in oobfree type format.
  * @bank:		Bank number for probed device.
@@ -203,8 +198,6 @@
 	u32			pid;
 	struct mtd_info		mtd;
 	struct nand_chip	nand;
-	struct mtd_partition	*partitions;
-	unsigned int		nr_partitions;
 
 	struct fsmc_eccplace	*ecc_place;
 	unsigned int		bank;
@@ -716,65 +709,17 @@
 	 * platform data,
 	 * default partition information present in driver.
 	 */
-#ifdef CONFIG_MTD_CMDLINE_PARTS
 	/*
-	 * Check if partition info passed via command line
+	 * Check for partition info passed
 	 */
 	host->mtd.name = "nand";
-	host->nr_partitions = parse_mtd_partitions(&host->mtd, part_probes,
-			&host->partitions, 0);
-	if (host->nr_partitions <= 0) {
-#endif
-		/*
-		 * Check if partition info passed via command line
-		 */
-		if (pdata->partitions) {
-			host->partitions = pdata->partitions;
-			host->nr_partitions = pdata->nr_partitions;
-		} else {
-			struct mtd_partition *partition;
-			int i;
-
-			/* Select the default partitions info */
-			switch (host->mtd.size) {
-			case 0x01000000:
-			case 0x02000000:
-			case 0x04000000:
-				host->partitions = partition_info_16KB_blk;
-				host->nr_partitions =
-					sizeof(partition_info_16KB_blk) /
-					sizeof(struct mtd_partition);
-				break;
-			case 0x08000000:
-			case 0x10000000:
-			case 0x20000000:
-			case 0x40000000:
-				host->partitions = partition_info_128KB_blk;
-				host->nr_partitions =
-					sizeof(partition_info_128KB_blk) /
-					sizeof(struct mtd_partition);
-				break;
-			default:
-				ret = -ENXIO;
-				pr_err("Unsupported NAND size\n");
-				goto err_probe;
-			}
-
-			partition = host->partitions;
-			for (i = 0; i < host->nr_partitions; i++, partition++) {
-				if (partition->size == 0) {
-					partition->size = host->mtd.size -
-						partition->offset;
-					break;
-				}
-			}
-		}
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-	}
-#endif
-
-	ret = mtd_device_register(&host->mtd, host->partitions,
-				  host->nr_partitions);
+	ret = mtd_device_parse_register(&host->mtd, NULL, 0,
+			host->mtd.size <= 0x04000000 ?
+				partition_info_16KB_blk :
+				partition_info_128KB_blk,
+			host->mtd.size <= 0x04000000 ?
+				ARRAY_SIZE(partition_info_16KB_blk) :
+				ARRAY_SIZE(partition_info_128KB_blk));
 	if (ret)
 		goto err_probe;
 
@@ -822,7 +767,7 @@
 	platform_set_drvdata(pdev, NULL);
 
 	if (host) {
-		mtd_device_unregister(&host->mtd);
+		nand_release(&host->mtd);
 		clk_disable(host->clk);
 		clk_put(host->clk);
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/gpmi-nand/bch-regs.h linux-libre-3.2-gnu/drivers/mtd/nand/gpmi-nand/bch-regs.h
--- linux-libre-3.1-gnu/drivers/mtd/nand/gpmi-nand/bch-regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/mtd/nand/gpmi-nand/bch-regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,84 @@
+/*
+ * Freescale GPMI NAND Flash Driver
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, 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.
+ */
+#ifndef __GPMI_NAND_BCH_REGS_H
+#define __GPMI_NAND_BCH_REGS_H
+
+#define HW_BCH_CTRL				0x00000000
+#define HW_BCH_CTRL_SET				0x00000004
+#define HW_BCH_CTRL_CLR				0x00000008
+#define HW_BCH_CTRL_TOG				0x0000000c
+
+#define BM_BCH_CTRL_COMPLETE_IRQ_EN		(1 << 8)
+#define BM_BCH_CTRL_COMPLETE_IRQ		(1 << 0)
+
+#define HW_BCH_STATUS0				0x00000010
+#define HW_BCH_MODE				0x00000020
+#define HW_BCH_ENCODEPTR			0x00000030
+#define HW_BCH_DATAPTR				0x00000040
+#define HW_BCH_METAPTR				0x00000050
+#define HW_BCH_LAYOUTSELECT			0x00000070
+
+#define HW_BCH_FLASH0LAYOUT0			0x00000080
+
+#define BP_BCH_FLASH0LAYOUT0_NBLOCKS		24
+#define BM_BCH_FLASH0LAYOUT0_NBLOCKS	(0xff << BP_BCH_FLASH0LAYOUT0_NBLOCKS)
+#define BF_BCH_FLASH0LAYOUT0_NBLOCKS(v)		\
+	(((v) << BP_BCH_FLASH0LAYOUT0_NBLOCKS) & BM_BCH_FLASH0LAYOUT0_NBLOCKS)
+
+#define BP_BCH_FLASH0LAYOUT0_META_SIZE		16
+#define BM_BCH_FLASH0LAYOUT0_META_SIZE	(0xff << BP_BCH_FLASH0LAYOUT0_META_SIZE)
+#define BF_BCH_FLASH0LAYOUT0_META_SIZE(v)	\
+	(((v) << BP_BCH_FLASH0LAYOUT0_META_SIZE)\
+					 & BM_BCH_FLASH0LAYOUT0_META_SIZE)
+
+#define BP_BCH_FLASH0LAYOUT0_ECC0		12
+#define BM_BCH_FLASH0LAYOUT0_ECC0	(0xf << BP_BCH_FLASH0LAYOUT0_ECC0)
+#define BF_BCH_FLASH0LAYOUT0_ECC0(v)		\
+	(((v) << BP_BCH_FLASH0LAYOUT0_ECC0) & BM_BCH_FLASH0LAYOUT0_ECC0)
+
+#define BP_BCH_FLASH0LAYOUT0_DATA0_SIZE		0
+#define BM_BCH_FLASH0LAYOUT0_DATA0_SIZE		\
+			(0xfff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE)
+#define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v)	\
+	(((v) << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE)\
+					 & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE)
+
+#define HW_BCH_FLASH0LAYOUT1			0x00000090
+
+#define BP_BCH_FLASH0LAYOUT1_PAGE_SIZE		16
+#define BM_BCH_FLASH0LAYOUT1_PAGE_SIZE		\
+			(0xffff << BP_BCH_FLASH0LAYOUT1_PAGE_SIZE)
+#define BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(v)	\
+	(((v) << BP_BCH_FLASH0LAYOUT1_PAGE_SIZE) \
+					 & BM_BCH_FLASH0LAYOUT1_PAGE_SIZE)
+
+#define BP_BCH_FLASH0LAYOUT1_ECCN		12
+#define BM_BCH_FLASH0LAYOUT1_ECCN	(0xf << BP_BCH_FLASH0LAYOUT1_ECCN)
+#define BF_BCH_FLASH0LAYOUT1_ECCN(v)		\
+	(((v) << BP_BCH_FLASH0LAYOUT1_ECCN) & BM_BCH_FLASH0LAYOUT1_ECCN)
+
+#define BP_BCH_FLASH0LAYOUT1_DATAN_SIZE		0
+#define BM_BCH_FLASH0LAYOUT1_DATAN_SIZE		\
+			(0xfff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE)
+#define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v)	\
+	(((v) << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) \
+					 & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE)
+#endif
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/gpmi-nand/gpmi-lib.c linux-libre-3.2-gnu/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/gpmi-nand/gpmi-lib.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/mtd/nand/gpmi-nand/gpmi-lib.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1057 @@
+/*
+ * Freescale GPMI NAND Flash Driver
+ *
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 Embedded Alley Solutions, 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/mtd/gpmi-nand.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <mach/mxs.h>
+
+#include "gpmi-nand.h"
+#include "gpmi-regs.h"
+#include "bch-regs.h"
+
+struct timing_threshod timing_default_threshold = {
+	.max_data_setup_cycles       = (BM_GPMI_TIMING0_DATA_SETUP >>
+						BP_GPMI_TIMING0_DATA_SETUP),
+	.internal_data_setup_in_ns   = 0,
+	.max_sample_delay_factor     = (BM_GPMI_CTRL1_RDN_DELAY >>
+						BP_GPMI_CTRL1_RDN_DELAY),
+	.max_dll_clock_period_in_ns  = 32,
+	.max_dll_delay_in_ns         = 16,
+};
+
+/*
+ * Clear the bit and poll it cleared.  This is usually called with
+ * a reset address and mask being either SFTRST(bit 31) or CLKGATE
+ * (bit 30).
+ */
+static int clear_poll_bit(void __iomem *addr, u32 mask)
+{
+	int timeout = 0x400;
+
+	/* clear the bit */
+	__mxs_clrl(mask, addr);
+
+	/*
+	 * SFTRST needs 3 GPMI clocks to settle, the reference manual
+	 * recommends to wait 1us.
+	 */
+	udelay(1);
+
+	/* poll the bit becoming clear */
+	while ((readl(addr) & mask) && --timeout)
+		/* nothing */;
+
+	return !timeout;
+}
+
+#define MODULE_CLKGATE		(1 << 30)
+#define MODULE_SFTRST		(1 << 31)
+/*
+ * The current mxs_reset_block() will do two things:
+ *  [1] enable the module.
+ *  [2] reset the module.
+ *
+ * In most of the cases, it's ok. But there is a hardware bug in the BCH block.
+ * If you try to soft reset the BCH block, it becomes unusable until
+ * the next hard reset. This case occurs in the NAND boot mode. When the board
+ * boots by NAND, the ROM of the chip will initialize the BCH blocks itself.
+ * So If the driver tries to reset the BCH again, the BCH will not work anymore.
+ * You will see a DMA timeout in this case.
+ *
+ * To avoid this bug, just add a new parameter `just_enable` for
+ * the mxs_reset_block(), and rewrite it here.
+ */
+int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
+{
+	int ret;
+	int timeout = 0x400;
+
+	/* clear and poll SFTRST */
+	ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
+	if (unlikely(ret))
+		goto error;
+
+	/* clear CLKGATE */
+	__mxs_clrl(MODULE_CLKGATE, reset_addr);
+
+	if (!just_enable) {
+		/* set SFTRST to reset the block */
+		__mxs_setl(MODULE_SFTRST, reset_addr);
+		udelay(1);
+
+		/* poll CLKGATE becoming set */
+		while ((!(readl(reset_addr) & MODULE_CLKGATE)) && --timeout)
+			/* nothing */;
+		if (unlikely(!timeout))
+			goto error;
+	}
+
+	/* clear and poll SFTRST */
+	ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
+	if (unlikely(ret))
+		goto error;
+
+	/* clear and poll CLKGATE */
+	ret = clear_poll_bit(reset_addr, MODULE_CLKGATE);
+	if (unlikely(ret))
+		goto error;
+
+	return 0;
+
+error:
+	pr_err("%s(%p): module reset timeout\n", __func__, reset_addr);
+	return -ETIMEDOUT;
+}
+
+int gpmi_init(struct gpmi_nand_data *this)
+{
+	struct resources *r = &this->resources;
+	int ret;
+
+	ret = clk_enable(r->clock);
+	if (ret)
+		goto err_out;
+	ret = gpmi_reset_block(r->gpmi_regs, false);
+	if (ret)
+		goto err_out;
+
+	/* Choose NAND mode. */
+	writel(BM_GPMI_CTRL1_GPMI_MODE, r->gpmi_regs + HW_GPMI_CTRL1_CLR);
+
+	/* Set the IRQ polarity. */
+	writel(BM_GPMI_CTRL1_ATA_IRQRDY_POLARITY,
+				r->gpmi_regs + HW_GPMI_CTRL1_SET);
+
+	/* Disable Write-Protection. */
+	writel(BM_GPMI_CTRL1_DEV_RESET, r->gpmi_regs + HW_GPMI_CTRL1_SET);
+
+	/* Select BCH ECC. */
+	writel(BM_GPMI_CTRL1_BCH_MODE, r->gpmi_regs + HW_GPMI_CTRL1_SET);
+
+	clk_disable(r->clock);
+	return 0;
+err_out:
+	return ret;
+}
+
+/* This function is very useful. It is called only when the bug occur. */
+void gpmi_dump_info(struct gpmi_nand_data *this)
+{
+	struct resources *r = &this->resources;
+	struct bch_geometry *geo = &this->bch_geometry;
+	u32 reg;
+	int i;
+
+	pr_err("Show GPMI registers :\n");
+	for (i = 0; i <= HW_GPMI_DEBUG / 0x10 + 1; i++) {
+		reg = readl(r->gpmi_regs + i * 0x10);
+		pr_err("offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
+	}
+
+	/* start to print out the BCH info */
+	pr_err("BCH Geometry :\n");
+	pr_err("GF length              : %u\n", geo->gf_len);
+	pr_err("ECC Strength           : %u\n", geo->ecc_strength);
+	pr_err("Page Size in Bytes     : %u\n", geo->page_size);
+	pr_err("Metadata Size in Bytes : %u\n", geo->metadata_size);
+	pr_err("ECC Chunk Size in Bytes: %u\n", geo->ecc_chunk_size);
+	pr_err("ECC Chunk Count        : %u\n", geo->ecc_chunk_count);
+	pr_err("Payload Size in Bytes  : %u\n", geo->payload_size);
+	pr_err("Auxiliary Size in Bytes: %u\n", geo->auxiliary_size);
+	pr_err("Auxiliary Status Offset: %u\n", geo->auxiliary_status_offset);
+	pr_err("Block Mark Byte Offset : %u\n", geo->block_mark_byte_offset);
+	pr_err("Block Mark Bit Offset  : %u\n", geo->block_mark_bit_offset);
+}
+
+/* Configures the geometry for BCH.  */
+int bch_set_geometry(struct gpmi_nand_data *this)
+{
+	struct resources *r = &this->resources;
+	struct bch_geometry *bch_geo = &this->bch_geometry;
+	unsigned int block_count;
+	unsigned int block_size;
+	unsigned int metadata_size;
+	unsigned int ecc_strength;
+	unsigned int page_size;
+	int ret;
+
+	if (common_nfc_set_geometry(this))
+		return !0;
+
+	block_count   = bch_geo->ecc_chunk_count - 1;
+	block_size    = bch_geo->ecc_chunk_size;
+	metadata_size = bch_geo->metadata_size;
+	ecc_strength  = bch_geo->ecc_strength >> 1;
+	page_size     = bch_geo->page_size;
+
+	ret = clk_enable(r->clock);
+	if (ret)
+		goto err_out;
+
+	ret = gpmi_reset_block(r->bch_regs, true);
+	if (ret)
+		goto err_out;
+
+	/* Configure layout 0. */
+	writel(BF_BCH_FLASH0LAYOUT0_NBLOCKS(block_count)
+			| BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size)
+			| BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength)
+			| BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size),
+			r->bch_regs + HW_BCH_FLASH0LAYOUT0);
+
+	writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size)
+			| BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength)
+			| BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size),
+			r->bch_regs + HW_BCH_FLASH0LAYOUT1);
+
+	/* Set *all* chip selects to use layout 0. */
+	writel(0, r->bch_regs + HW_BCH_LAYOUTSELECT);
+
+	/* Enable interrupts. */
+	writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
+				r->bch_regs + HW_BCH_CTRL_SET);
+
+	clk_disable(r->clock);
+	return 0;
+err_out:
+	return ret;
+}
+
+/* Converts time in nanoseconds to cycles. */
+static unsigned int ns_to_cycles(unsigned int time,
+			unsigned int period, unsigned int min)
+{
+	unsigned int k;
+
+	k = (time + period - 1) / period;
+	return max(k, min);
+}
+
+/* Apply timing to current hardware conditions. */
+static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this,
+					struct gpmi_nfc_hardware_timing *hw)
+{
+	struct gpmi_nand_platform_data *pdata = this->pdata;
+	struct timing_threshod *nfc = &timing_default_threshold;
+	struct nand_chip *nand = &this->nand;
+	struct nand_timing target = this->timing;
+	bool improved_timing_is_available;
+	unsigned long clock_frequency_in_hz;
+	unsigned int clock_period_in_ns;
+	bool dll_use_half_periods;
+	unsigned int dll_delay_shift;
+	unsigned int max_sample_delay_in_ns;
+	unsigned int address_setup_in_cycles;
+	unsigned int data_setup_in_ns;
+	unsigned int data_setup_in_cycles;
+	unsigned int data_hold_in_cycles;
+	int ideal_sample_delay_in_ns;
+	unsigned int sample_delay_factor;
+	int tEYE;
+	unsigned int min_prop_delay_in_ns = pdata->min_prop_delay_in_ns;
+	unsigned int max_prop_delay_in_ns = pdata->max_prop_delay_in_ns;
+
+	/*
+	 * If there are multiple chips, we need to relax the timings to allow
+	 * for signal distortion due to higher capacitance.
+	 */
+	if (nand->numchips > 2) {
+		target.data_setup_in_ns    += 10;
+		target.data_hold_in_ns     += 10;
+		target.address_setup_in_ns += 10;
+	} else if (nand->numchips > 1) {
+		target.data_setup_in_ns    += 5;
+		target.data_hold_in_ns     += 5;
+		target.address_setup_in_ns += 5;
+	}
+
+	/* Check if improved timing information is available. */
+	improved_timing_is_available =
+		(target.tREA_in_ns  >= 0) &&
+		(target.tRLOH_in_ns >= 0) &&
+		(target.tRHOH_in_ns >= 0) ;
+
+	/* Inspect the clock. */
+	clock_frequency_in_hz = nfc->clock_frequency_in_hz;
+	clock_period_in_ns    = 1000000000 / clock_frequency_in_hz;
+
+	/*
+	 * The NFC quantizes setup and hold parameters in terms of clock cycles.
+	 * Here, we quantize the setup and hold timing parameters to the
+	 * next-highest clock period to make sure we apply at least the
+	 * specified times.
+	 *
+	 * For data setup and data hold, the hardware interprets a value of zero
+	 * as the largest possible delay. This is not what's intended by a zero
+	 * in the input parameter, so we impose a minimum of one cycle.
+	 */
+	data_setup_in_cycles    = ns_to_cycles(target.data_setup_in_ns,
+							clock_period_in_ns, 1);
+	data_hold_in_cycles     = ns_to_cycles(target.data_hold_in_ns,
+							clock_period_in_ns, 1);
+	address_setup_in_cycles = ns_to_cycles(target.address_setup_in_ns,
+							clock_period_in_ns, 0);
+
+	/*
+	 * The clock's period affects the sample delay in a number of ways:
+	 *
+	 * (1) The NFC HAL tells us the maximum clock period the sample delay
+	 *     DLL can tolerate. If the clock period is greater than half that
+	 *     maximum, we must configure the DLL to be driven by half periods.
+	 *
+	 * (2) We need to convert from an ideal sample delay, in ns, to a
+	 *     "sample delay factor," which the NFC uses. This factor depends on
+	 *     whether we're driving the DLL with full or half periods.
+	 *     Paraphrasing the reference manual:
+	 *
+	 *         AD = SDF x 0.125 x RP
+	 *
+	 * where:
+	 *
+	 *     AD   is the applied delay, in ns.
+	 *     SDF  is the sample delay factor, which is dimensionless.
+	 *     RP   is the reference period, in ns, which is a full clock period
+	 *          if the DLL is being driven by full periods, or half that if
+	 *          the DLL is being driven by half periods.
+	 *
+	 * Let's re-arrange this in a way that's more useful to us:
+	 *
+	 *                        8
+	 *         SDF  =  AD x ----
+	 *                       RP
+	 *
+	 * The reference period is either the clock period or half that, so this
+	 * is:
+	 *
+	 *                        8       AD x DDF
+	 *         SDF  =  AD x -----  =  --------
+	 *                      f x P        P
+	 *
+	 * where:
+	 *
+	 *       f  is 1 or 1/2, depending on how we're driving the DLL.
+	 *       P  is the clock period.
+	 *     DDF  is the DLL Delay Factor, a dimensionless value that
+	 *          incorporates all the constants in the conversion.
+	 *
+	 * DDF will be either 8 or 16, both of which are powers of two. We can
+	 * reduce the cost of this conversion by using bit shifts instead of
+	 * multiplication or division. Thus:
+	 *
+	 *                 AD << DDS
+	 *         SDF  =  ---------
+	 *                     P
+	 *
+	 *     or
+	 *
+	 *         AD  =  (SDF >> DDS) x P
+	 *
+	 * where:
+	 *
+	 *     DDS  is the DLL Delay Shift, the logarithm to base 2 of the DDF.
+	 */
+	if (clock_period_in_ns > (nfc->max_dll_clock_period_in_ns >> 1)) {
+		dll_use_half_periods = true;
+		dll_delay_shift      = 3 + 1;
+	} else {
+		dll_use_half_periods = false;
+		dll_delay_shift      = 3;
+	}
+
+	/*
+	 * Compute the maximum sample delay the NFC allows, under current
+	 * conditions. If the clock is running too slowly, no sample delay is
+	 * possible.
+	 */
+	if (clock_period_in_ns > nfc->max_dll_clock_period_in_ns)
+		max_sample_delay_in_ns = 0;
+	else {
+		/*
+		 * Compute the delay implied by the largest sample delay factor
+		 * the NFC allows.
+		 */
+		max_sample_delay_in_ns =
+			(nfc->max_sample_delay_factor * clock_period_in_ns) >>
+								dll_delay_shift;
+
+		/*
+		 * Check if the implied sample delay larger than the NFC
+		 * actually allows.
+		 */
+		if (max_sample_delay_in_ns > nfc->max_dll_delay_in_ns)
+			max_sample_delay_in_ns = nfc->max_dll_delay_in_ns;
+	}
+
+	/*
+	 * Check if improved timing information is available. If not, we have to
+	 * use a less-sophisticated algorithm.
+	 */
+	if (!improved_timing_is_available) {
+		/*
+		 * Fold the read setup time required by the NFC into the ideal
+		 * sample delay.
+		 */
+		ideal_sample_delay_in_ns = target.gpmi_sample_delay_in_ns +
+						nfc->internal_data_setup_in_ns;
+
+		/*
+		 * The ideal sample delay may be greater than the maximum
+		 * allowed by the NFC. If so, we can trade off sample delay time
+		 * for more data setup time.
+		 *
+		 * In each iteration of the following loop, we add a cycle to
+		 * the data setup time and subtract a corresponding amount from
+		 * the sample delay until we've satisified the constraints or
+		 * can't do any better.
+		 */
+		while ((ideal_sample_delay_in_ns > max_sample_delay_in_ns) &&
+			(data_setup_in_cycles < nfc->max_data_setup_cycles)) {
+
+			data_setup_in_cycles++;
+			ideal_sample_delay_in_ns -= clock_period_in_ns;
+
+			if (ideal_sample_delay_in_ns < 0)
+				ideal_sample_delay_in_ns = 0;
+
+		}
+
+		/*
+		 * Compute the sample delay factor that corresponds most closely
+		 * to the ideal sample delay. If the result is too large for the
+		 * NFC, use the maximum value.
+		 *
+		 * Notice that we use the ns_to_cycles function to compute the
+		 * sample delay factor. We do this because the form of the
+		 * computation is the same as that for calculating cycles.
+		 */
+		sample_delay_factor =
+			ns_to_cycles(
+				ideal_sample_delay_in_ns << dll_delay_shift,
+							clock_period_in_ns, 0);
+
+		if (sample_delay_factor > nfc->max_sample_delay_factor)
+			sample_delay_factor = nfc->max_sample_delay_factor;
+
+		/* Skip to the part where we return our results. */
+		goto return_results;
+	}
+
+	/*
+	 * If control arrives here, we have more detailed timing information,
+	 * so we can use a better algorithm.
+	 */
+
+	/*
+	 * Fold the read setup time required by the NFC into the maximum
+	 * propagation delay.
+	 */
+	max_prop_delay_in_ns += nfc->internal_data_setup_in_ns;
+
+	/*
+	 * Earlier, we computed the number of clock cycles required to satisfy
+	 * the data setup time. Now, we need to know the actual nanoseconds.
+	 */
+	data_setup_in_ns = clock_period_in_ns * data_setup_in_cycles;
+
+	/*
+	 * Compute tEYE, the width of the data eye when reading from the NAND
+	 * Flash. The eye width is fundamentally determined by the data setup
+	 * time, perturbed by propagation delays and some characteristics of the
+	 * NAND Flash device.
+	 *
+	 * start of the eye = max_prop_delay + tREA
+	 * end of the eye   = min_prop_delay + tRHOH + data_setup
+	 */
+	tEYE = (int)min_prop_delay_in_ns + (int)target.tRHOH_in_ns +
+							(int)data_setup_in_ns;
+
+	tEYE -= (int)max_prop_delay_in_ns + (int)target.tREA_in_ns;
+
+	/*
+	 * The eye must be open. If it's not, we can try to open it by
+	 * increasing its main forcer, the data setup time.
+	 *
+	 * In each iteration of the following loop, we increase the data setup
+	 * time by a single clock cycle. We do this until either the eye is
+	 * open or we run into NFC limits.
+	 */
+	while ((tEYE <= 0) &&
+			(data_setup_in_cycles < nfc->max_data_setup_cycles)) {
+		/* Give a cycle to data setup. */
+		data_setup_in_cycles++;
+		/* Synchronize the data setup time with the cycles. */
+		data_setup_in_ns += clock_period_in_ns;
+		/* Adjust tEYE accordingly. */
+		tEYE += clock_period_in_ns;
+	}
+
+	/*
+	 * When control arrives here, the eye is open. The ideal time to sample
+	 * the data is in the center of the eye:
+	 *
+	 *     end of the eye + start of the eye
+	 *     ---------------------------------  -  data_setup
+	 *                    2
+	 *
+	 * After some algebra, this simplifies to the code immediately below.
+	 */
+	ideal_sample_delay_in_ns =
+		((int)max_prop_delay_in_ns +
+			(int)target.tREA_in_ns +
+				(int)min_prop_delay_in_ns +
+					(int)target.tRHOH_in_ns -
+						(int)data_setup_in_ns) >> 1;
+
+	/*
+	 * The following figure illustrates some aspects of a NAND Flash read:
+	 *
+	 *
+	 *           __                   _____________________________________
+	 * RDN         \_________________/
+	 *
+	 *                                         <---- tEYE ----->
+	 *                                        /-----------------\
+	 * Read Data ----------------------------<                   >---------
+	 *                                        \-----------------/
+	 *             ^                 ^                 ^              ^
+	 *             |                 |                 |              |
+	 *             |<--Data Setup -->|<--Delay Time -->|              |
+	 *             |                 |                 |              |
+	 *             |                 |                                |
+	 *             |                 |<--   Quantized Delay Time   -->|
+	 *             |                 |                                |
+	 *
+	 *
+	 * We have some issues we must now address:
+	 *
+	 * (1) The *ideal* sample delay time must not be negative. If it is, we
+	 *     jam it to zero.
+	 *
+	 * (2) The *ideal* sample delay time must not be greater than that
+	 *     allowed by the NFC. If it is, we can increase the data setup
+	 *     time, which will reduce the delay between the end of the data
+	 *     setup and the center of the eye. It will also make the eye
+	 *     larger, which might help with the next issue...
+	 *
+	 * (3) The *quantized* sample delay time must not fall either before the
+	 *     eye opens or after it closes (the latter is the problem
+	 *     illustrated in the above figure).
+	 */
+
+	/* Jam a negative ideal sample delay to zero. */
+	if (ideal_sample_delay_in_ns < 0)
+		ideal_sample_delay_in_ns = 0;
+
+	/*
+	 * Extend the data setup as needed to reduce the ideal sample delay
+	 * below the maximum permitted by the NFC.
+	 */
+	while ((ideal_sample_delay_in_ns > max_sample_delay_in_ns) &&
+			(data_setup_in_cycles < nfc->max_data_setup_cycles)) {
+
+		/* Give a cycle to data setup. */
+		data_setup_in_cycles++;
+		/* Synchronize the data setup time with the cycles. */
+		data_setup_in_ns += clock_period_in_ns;
+		/* Adjust tEYE accordingly. */
+		tEYE += clock_period_in_ns;
+
+		/*
+		 * Decrease the ideal sample delay by one half cycle, to keep it
+		 * in the middle of the eye.
+		 */
+		ideal_sample_delay_in_ns -= (clock_period_in_ns >> 1);
+
+		/* Jam a negative ideal sample delay to zero. */
+		if (ideal_sample_delay_in_ns < 0)
+			ideal_sample_delay_in_ns = 0;
+	}
+
+	/*
+	 * Compute the sample delay factor that corresponds to the ideal sample
+	 * delay. If the result is too large, then use the maximum allowed
+	 * value.
+	 *
+	 * Notice that we use the ns_to_cycles function to compute the sample
+	 * delay factor. We do this because the form of the computation is the
+	 * same as that for calculating cycles.
+	 */
+	sample_delay_factor =
+		ns_to_cycles(ideal_sample_delay_in_ns << dll_delay_shift,
+							clock_period_in_ns, 0);
+
+	if (sample_delay_factor > nfc->max_sample_delay_factor)
+		sample_delay_factor = nfc->max_sample_delay_factor;
+
+	/*
+	 * These macros conveniently encapsulate a computation we'll use to
+	 * continuously evaluate whether or not the data sample delay is inside
+	 * the eye.
+	 */
+	#define IDEAL_DELAY  ((int) ideal_sample_delay_in_ns)
+
+	#define QUANTIZED_DELAY  \
+		((int) ((sample_delay_factor * clock_period_in_ns) >> \
+							dll_delay_shift))
+
+	#define DELAY_ERROR  (abs(QUANTIZED_DELAY - IDEAL_DELAY))
+
+	#define SAMPLE_IS_NOT_WITHIN_THE_EYE  (DELAY_ERROR > (tEYE >> 1))
+
+	/*
+	 * While the quantized sample time falls outside the eye, reduce the
+	 * sample delay or extend the data setup to move the sampling point back
+	 * toward the eye. Do not allow the number of data setup cycles to
+	 * exceed the maximum allowed by the NFC.
+	 */
+	while (SAMPLE_IS_NOT_WITHIN_THE_EYE &&
+			(data_setup_in_cycles < nfc->max_data_setup_cycles)) {
+		/*
+		 * If control arrives here, the quantized sample delay falls
+		 * outside the eye. Check if it's before the eye opens, or after
+		 * the eye closes.
+		 */
+		if (QUANTIZED_DELAY > IDEAL_DELAY) {
+			/*
+			 * If control arrives here, the quantized sample delay
+			 * falls after the eye closes. Decrease the quantized
+			 * delay time and then go back to re-evaluate.
+			 */
+			if (sample_delay_factor != 0)
+				sample_delay_factor--;
+			continue;
+		}
+
+		/*
+		 * If control arrives here, the quantized sample delay falls
+		 * before the eye opens. Shift the sample point by increasing
+		 * data setup time. This will also make the eye larger.
+		 */
+
+		/* Give a cycle to data setup. */
+		data_setup_in_cycles++;
+		/* Synchronize the data setup time with the cycles. */
+		data_setup_in_ns += clock_period_in_ns;
+		/* Adjust tEYE accordingly. */
+		tEYE += clock_period_in_ns;
+
+		/*
+		 * Decrease the ideal sample delay by one half cycle, to keep it
+		 * in the middle of the eye.
+		 */
+		ideal_sample_delay_in_ns -= (clock_period_in_ns >> 1);
+
+		/* ...and one less period for the delay time. */
+		ideal_sample_delay_in_ns -= clock_period_in_ns;
+
+		/* Jam a negative ideal sample delay to zero. */
+		if (ideal_sample_delay_in_ns < 0)
+			ideal_sample_delay_in_ns = 0;
+
+		/*
+		 * We have a new ideal sample delay, so re-compute the quantized
+		 * delay.
+		 */
+		sample_delay_factor =
+			ns_to_cycles(
+				ideal_sample_delay_in_ns << dll_delay_shift,
+							clock_period_in_ns, 0);
+
+		if (sample_delay_factor > nfc->max_sample_delay_factor)
+			sample_delay_factor = nfc->max_sample_delay_factor;
+	}
+
+	/* Control arrives here when we're ready to return our results. */
+return_results:
+	hw->data_setup_in_cycles    = data_setup_in_cycles;
+	hw->data_hold_in_cycles     = data_hold_in_cycles;
+	hw->address_setup_in_cycles = address_setup_in_cycles;
+	hw->use_half_periods        = dll_use_half_periods;
+	hw->sample_delay_factor     = sample_delay_factor;
+
+	/* Return success. */
+	return 0;
+}
+
+/* Begin the I/O */
+void gpmi_begin(struct gpmi_nand_data *this)
+{
+	struct resources *r = &this->resources;
+	struct timing_threshod *nfc = &timing_default_threshold;
+	unsigned char  *gpmi_regs = r->gpmi_regs;
+	unsigned int   clock_period_in_ns;
+	uint32_t       reg;
+	unsigned int   dll_wait_time_in_us;
+	struct gpmi_nfc_hardware_timing  hw;
+	int ret;
+
+	/* Enable the clock. */
+	ret = clk_enable(r->clock);
+	if (ret) {
+		pr_err("We failed in enable the clk\n");
+		goto err_out;
+	}
+
+	/* set ready/busy timeout */
+	writel(0x500 << BP_GPMI_TIMING1_BUSY_TIMEOUT,
+		gpmi_regs + HW_GPMI_TIMING1);
+
+	/* Get the timing information we need. */
+	nfc->clock_frequency_in_hz = clk_get_rate(r->clock);
+	clock_period_in_ns = 1000000000 / nfc->clock_frequency_in_hz;
+
+	gpmi_nfc_compute_hardware_timing(this, &hw);
+
+	/* Set up all the simple timing parameters. */
+	reg = BF_GPMI_TIMING0_ADDRESS_SETUP(hw.address_setup_in_cycles) |
+		BF_GPMI_TIMING0_DATA_HOLD(hw.data_hold_in_cycles)         |
+		BF_GPMI_TIMING0_DATA_SETUP(hw.data_setup_in_cycles)       ;
+
+	writel(reg, gpmi_regs + HW_GPMI_TIMING0);
+
+	/*
+	 * DLL_ENABLE must be set to 0 when setting RDN_DELAY or HALF_PERIOD.
+	 */
+	writel(BM_GPMI_CTRL1_DLL_ENABLE, gpmi_regs + HW_GPMI_CTRL1_CLR);
+
+	/* Clear out the DLL control fields. */
+	writel(BM_GPMI_CTRL1_RDN_DELAY,   gpmi_regs + HW_GPMI_CTRL1_CLR);
+	writel(BM_GPMI_CTRL1_HALF_PERIOD, gpmi_regs + HW_GPMI_CTRL1_CLR);
+
+	/* If no sample delay is called for, return immediately. */
+	if (!hw.sample_delay_factor)
+		return;
+
+	/* Configure the HALF_PERIOD flag. */
+	if (hw.use_half_periods)
+		writel(BM_GPMI_CTRL1_HALF_PERIOD,
+						gpmi_regs + HW_GPMI_CTRL1_SET);
+
+	/* Set the delay factor. */
+	writel(BF_GPMI_CTRL1_RDN_DELAY(hw.sample_delay_factor),
+						gpmi_regs + HW_GPMI_CTRL1_SET);
+
+	/* Enable the DLL. */
+	writel(BM_GPMI_CTRL1_DLL_ENABLE, gpmi_regs + HW_GPMI_CTRL1_SET);
+
+	/*
+	 * After we enable the GPMI DLL, we have to wait 64 clock cycles before
+	 * we can use the GPMI.
+	 *
+	 * Calculate the amount of time we need to wait, in microseconds.
+	 */
+	dll_wait_time_in_us = (clock_period_in_ns * 64) / 1000;
+
+	if (!dll_wait_time_in_us)
+		dll_wait_time_in_us = 1;
+
+	/* Wait for the DLL to settle. */
+	udelay(dll_wait_time_in_us);
+
+err_out:
+	return;
+}
+
+void gpmi_end(struct gpmi_nand_data *this)
+{
+	struct resources *r = &this->resources;
+	clk_disable(r->clock);
+}
+
+/* Clears a BCH interrupt. */
+void gpmi_clear_bch(struct gpmi_nand_data *this)
+{
+	struct resources *r = &this->resources;
+	writel(BM_BCH_CTRL_COMPLETE_IRQ, r->bch_regs + HW_BCH_CTRL_CLR);
+}
+
+/* Returns the Ready/Busy status of the given chip. */
+int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip)
+{
+	struct resources *r = &this->resources;
+	uint32_t mask = 0;
+	uint32_t reg = 0;
+
+	if (GPMI_IS_MX23(this)) {
+		mask = MX23_BM_GPMI_DEBUG_READY0 << chip;
+		reg = readl(r->gpmi_regs + HW_GPMI_DEBUG);
+	} else if (GPMI_IS_MX28(this)) {
+		mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip);
+		reg = readl(r->gpmi_regs + HW_GPMI_STAT);
+	} else
+		pr_err("unknow arch.\n");
+	return reg & mask;
+}
+
+static inline void set_dma_type(struct gpmi_nand_data *this,
+					enum dma_ops_type type)
+{
+	this->last_dma_type = this->dma_type;
+	this->dma_type = type;
+}
+
+int gpmi_send_command(struct gpmi_nand_data *this)
+{
+	struct dma_chan *channel = get_dma_chan(this);
+	struct dma_async_tx_descriptor *desc;
+	struct scatterlist *sgl;
+	int chip = this->current_chip;
+	u32 pio[3];
+
+	/* [1] send out the PIO words */
+	pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__WRITE)
+		| BM_GPMI_CTRL0_WORD_LENGTH
+		| BF_GPMI_CTRL0_CS(chip, this)
+		| BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+		| BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_CLE)
+		| BM_GPMI_CTRL0_ADDRESS_INCREMENT
+		| BF_GPMI_CTRL0_XFER_COUNT(this->command_length);
+	pio[1] = pio[2] = 0;
+	desc = channel->device->device_prep_slave_sg(channel,
+					(struct scatterlist *)pio,
+					ARRAY_SIZE(pio), DMA_NONE, 0);
+	if (!desc) {
+		pr_err("step 1 error\n");
+		return -1;
+	}
+
+	/* [2] send out the COMMAND + ADDRESS string stored in @buffer */
+	sgl = &this->cmd_sgl;
+
+	sg_init_one(sgl, this->cmd_buffer, this->command_length);
+	dma_map_sg(this->dev, sgl, 1, DMA_TO_DEVICE);
+	desc = channel->device->device_prep_slave_sg(channel,
+					sgl, 1, DMA_TO_DEVICE, 1);
+	if (!desc) {
+		pr_err("step 2 error\n");
+		return -1;
+	}
+
+	/* [3] submit the DMA */
+	set_dma_type(this, DMA_FOR_COMMAND);
+	return start_dma_without_bch_irq(this, desc);
+}
+
+int gpmi_send_data(struct gpmi_nand_data *this)
+{
+	struct dma_async_tx_descriptor *desc;
+	struct dma_chan *channel = get_dma_chan(this);
+	int chip = this->current_chip;
+	uint32_t command_mode;
+	uint32_t address;
+	u32 pio[2];
+
+	/* [1] PIO */
+	command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WRITE;
+	address      = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
+
+	pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
+		| BM_GPMI_CTRL0_WORD_LENGTH
+		| BF_GPMI_CTRL0_CS(chip, this)
+		| BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+		| BF_GPMI_CTRL0_ADDRESS(address)
+		| BF_GPMI_CTRL0_XFER_COUNT(this->upper_len);
+	pio[1] = 0;
+	desc = channel->device->device_prep_slave_sg(channel,
+					(struct scatterlist *)pio,
+					ARRAY_SIZE(pio), DMA_NONE, 0);
+	if (!desc) {
+		pr_err("step 1 error\n");
+		return -1;
+	}
+
+	/* [2] send DMA request */
+	prepare_data_dma(this, DMA_TO_DEVICE);
+	desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl,
+						1, DMA_TO_DEVICE, 1);
+	if (!desc) {
+		pr_err("step 2 error\n");
+		return -1;
+	}
+	/* [3] submit the DMA */
+	set_dma_type(this, DMA_FOR_WRITE_DATA);
+	return start_dma_without_bch_irq(this, desc);
+}
+
+int gpmi_read_data(struct gpmi_nand_data *this)
+{
+	struct dma_async_tx_descriptor *desc;
+	struct dma_chan *channel = get_dma_chan(this);
+	int chip = this->current_chip;
+	u32 pio[2];
+
+	/* [1] : send PIO */
+	pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__READ)
+		| BM_GPMI_CTRL0_WORD_LENGTH
+		| BF_GPMI_CTRL0_CS(chip, this)
+		| BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+		| BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_DATA)
+		| BF_GPMI_CTRL0_XFER_COUNT(this->upper_len);
+	pio[1] = 0;
+	desc = channel->device->device_prep_slave_sg(channel,
+					(struct scatterlist *)pio,
+					ARRAY_SIZE(pio), DMA_NONE, 0);
+	if (!desc) {
+		pr_err("step 1 error\n");
+		return -1;
+	}
+
+	/* [2] : send DMA request */
+	prepare_data_dma(this, DMA_FROM_DEVICE);
+	desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl,
+						1, DMA_FROM_DEVICE, 1);
+	if (!desc) {
+		pr_err("step 2 error\n");
+		return -1;
+	}
+
+	/* [3] : submit the DMA */
+	set_dma_type(this, DMA_FOR_READ_DATA);
+	return start_dma_without_bch_irq(this, desc);
+}
+
+int gpmi_send_page(struct gpmi_nand_data *this,
+			dma_addr_t payload, dma_addr_t auxiliary)
+{
+	struct bch_geometry *geo = &this->bch_geometry;
+	uint32_t command_mode;
+	uint32_t address;
+	uint32_t ecc_command;
+	uint32_t buffer_mask;
+	struct dma_async_tx_descriptor *desc;
+	struct dma_chan *channel = get_dma_chan(this);
+	int chip = this->current_chip;
+	u32 pio[6];
+
+	/* A DMA descriptor that does an ECC page read. */
+	command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WRITE;
+	address      = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
+	ecc_command  = BV_GPMI_ECCCTRL_ECC_CMD__BCH_ENCODE;
+	buffer_mask  = BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE |
+				BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY;
+
+	pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
+		| BM_GPMI_CTRL0_WORD_LENGTH
+		| BF_GPMI_CTRL0_CS(chip, this)
+		| BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+		| BF_GPMI_CTRL0_ADDRESS(address)
+		| BF_GPMI_CTRL0_XFER_COUNT(0);
+	pio[1] = 0;
+	pio[2] = BM_GPMI_ECCCTRL_ENABLE_ECC
+		| BF_GPMI_ECCCTRL_ECC_CMD(ecc_command)
+		| BF_GPMI_ECCCTRL_BUFFER_MASK(buffer_mask);
+	pio[3] = geo->page_size;
+	pio[4] = payload;
+	pio[5] = auxiliary;
+
+	desc = channel->device->device_prep_slave_sg(channel,
+					(struct scatterlist *)pio,
+					ARRAY_SIZE(pio), DMA_NONE, 0);
+	if (!desc) {
+		pr_err("step 2 error\n");
+		return -1;
+	}
+	set_dma_type(this, DMA_FOR_WRITE_ECC_PAGE);
+	return start_dma_with_bch_irq(this, desc);
+}
+
+int gpmi_read_page(struct gpmi_nand_data *this,
+				dma_addr_t payload, dma_addr_t auxiliary)
+{
+	struct bch_geometry *geo = &this->bch_geometry;
+	uint32_t command_mode;
+	uint32_t address;
+	uint32_t ecc_command;
+	uint32_t buffer_mask;
+	struct dma_async_tx_descriptor *desc;
+	struct dma_chan *channel = get_dma_chan(this);
+	int chip = this->current_chip;
+	u32 pio[6];
+
+	/* [1] Wait for the chip to report ready. */
+	command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY;
+	address      = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
+
+	pio[0] =  BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
+		| BM_GPMI_CTRL0_WORD_LENGTH
+		| BF_GPMI_CTRL0_CS(chip, this)
+		| BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+		| BF_GPMI_CTRL0_ADDRESS(address)
+		| BF_GPMI_CTRL0_XFER_COUNT(0);
+	pio[1] = 0;
+	desc = channel->device->device_prep_slave_sg(channel,
+				(struct scatterlist *)pio, 2, DMA_NONE, 0);
+	if (!desc) {
+		pr_err("step 1 error\n");
+		return -1;
+	}
+
+	/* [2] Enable the BCH block and read. */
+	command_mode = BV_GPMI_CTRL0_COMMAND_MODE__READ;
+	address      = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
+	ecc_command  = BV_GPMI_ECCCTRL_ECC_CMD__BCH_DECODE;
+	buffer_mask  = BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE
+			| BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY;
+
+	pio[0] =  BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
+		| BM_GPMI_CTRL0_WORD_LENGTH
+		| BF_GPMI_CTRL0_CS(chip, this)
+		| BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+		| BF_GPMI_CTRL0_ADDRESS(address)
+		| BF_GPMI_CTRL0_XFER_COUNT(geo->page_size);
+
+	pio[1] = 0;
+	pio[2] =  BM_GPMI_ECCCTRL_ENABLE_ECC
+		| BF_GPMI_ECCCTRL_ECC_CMD(ecc_command)
+		| BF_GPMI_ECCCTRL_BUFFER_MASK(buffer_mask);
+	pio[3] = geo->page_size;
+	pio[4] = payload;
+	pio[5] = auxiliary;
+	desc = channel->device->device_prep_slave_sg(channel,
+					(struct scatterlist *)pio,
+					ARRAY_SIZE(pio), DMA_NONE, 1);
+	if (!desc) {
+		pr_err("step 2 error\n");
+		return -1;
+	}
+
+	/* [3] Disable the BCH block */
+	command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY;
+	address      = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
+
+	pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
+		| BM_GPMI_CTRL0_WORD_LENGTH
+		| BF_GPMI_CTRL0_CS(chip, this)
+		| BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this)
+		| BF_GPMI_CTRL0_ADDRESS(address)
+		| BF_GPMI_CTRL0_XFER_COUNT(geo->page_size);
+	pio[1] = 0;
+	desc = channel->device->device_prep_slave_sg(channel,
+				(struct scatterlist *)pio, 2, DMA_NONE, 1);
+	if (!desc) {
+		pr_err("step 3 error\n");
+		return -1;
+	}
+
+	/* [4] submit the DMA */
+	set_dma_type(this, DMA_FOR_READ_ECC_PAGE);
+	return start_dma_with_bch_irq(this, desc);
+}
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/gpmi-nand/gpmi-nand.c linux-libre-3.2-gnu/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/gpmi-nand/gpmi-nand.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/mtd/nand/gpmi-nand/gpmi-nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1619 @@
+/*
+ * Freescale GPMI NAND Flash Driver
+ *
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 Embedded Alley Solutions, 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/clk.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mtd/gpmi-nand.h>
+#include <linux/mtd/partitions.h>
+#include "gpmi-nand.h"
+
+/* add our owner bbt descriptor */
+static uint8_t scan_ff_pattern[] = { 0xff };
+static struct nand_bbt_descr gpmi_bbt_descr = {
+	.options	= 0,
+	.offs		= 0,
+	.len		= 1,
+	.pattern	= scan_ff_pattern
+};
+
+/*  We will use all the (page + OOB). */
+static struct nand_ecclayout gpmi_hw_ecclayout = {
+	.eccbytes = 0,
+	.eccpos = { 0, },
+	.oobfree = { {.offset = 0, .length = 0} }
+};
+
+static irqreturn_t bch_irq(int irq, void *cookie)
+{
+	struct gpmi_nand_data *this = cookie;
+
+	gpmi_clear_bch(this);
+	complete(&this->bch_done);
+	return IRQ_HANDLED;
+}
+
+/*
+ *  Calculate the ECC strength by hand:
+ *	E : The ECC strength.
+ *	G : the length of Galois Field.
+ *	N : The chunk count of per page.
+ *	O : the oobsize of the NAND chip.
+ *	M : the metasize of per page.
+ *
+ *	The formula is :
+ *		E * G * N
+ *	      ------------ <= (O - M)
+ *                  8
+ *
+ *      So, we get E by:
+ *                    (O - M) * 8
+ *              E <= -------------
+ *                       G * N
+ */
+static inline int get_ecc_strength(struct gpmi_nand_data *this)
+{
+	struct bch_geometry *geo = &this->bch_geometry;
+	struct mtd_info	*mtd = &this->mtd;
+	int ecc_strength;
+
+	ecc_strength = ((mtd->oobsize - geo->metadata_size) * 8)
+			/ (geo->gf_len * geo->ecc_chunk_count);
+
+	/* We need the minor even number. */
+	return round_down(ecc_strength, 2);
+}
+
+int common_nfc_set_geometry(struct gpmi_nand_data *this)
+{
+	struct bch_geometry *geo = &this->bch_geometry;
+	struct mtd_info *mtd = &this->mtd;
+	unsigned int metadata_size;
+	unsigned int status_size;
+	unsigned int block_mark_bit_offset;
+
+	/*
+	 * The size of the metadata can be changed, though we set it to 10
+	 * bytes now. But it can't be too large, because we have to save
+	 * enough space for BCH.
+	 */
+	geo->metadata_size = 10;
+
+	/* The default for the length of Galois Field. */
+	geo->gf_len = 13;
+
+	/* The default for chunk size. There is no oobsize greater then 512. */
+	geo->ecc_chunk_size = 512;
+	while (geo->ecc_chunk_size < mtd->oobsize)
+		geo->ecc_chunk_size *= 2; /* keep C >= O */
+
+	geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
+
+	/* We use the same ECC strength for all chunks. */
+	geo->ecc_strength = get_ecc_strength(this);
+	if (!geo->ecc_strength) {
+		pr_err("We get a wrong ECC strength.\n");
+		return -EINVAL;
+	}
+
+	geo->page_size = mtd->writesize + mtd->oobsize;
+	geo->payload_size = mtd->writesize;
+
+	/*
+	 * The auxiliary buffer contains the metadata and the ECC status. The
+	 * metadata is padded to the nearest 32-bit boundary. The ECC status
+	 * contains one byte for every ECC chunk, and is also padded to the
+	 * nearest 32-bit boundary.
+	 */
+	metadata_size = ALIGN(geo->metadata_size, 4);
+	status_size   = ALIGN(geo->ecc_chunk_count, 4);
+
+	geo->auxiliary_size = metadata_size + status_size;
+	geo->auxiliary_status_offset = metadata_size;
+
+	if (!this->swap_block_mark)
+		return 0;
+
+	/*
+	 * We need to compute the byte and bit offsets of
+	 * the physical block mark within the ECC-based view of the page.
+	 *
+	 * NAND chip with 2K page shows below:
+	 *                                             (Block Mark)
+	 *                                                   |      |
+	 *                                                   |  D   |
+	 *                                                   |<---->|
+	 *                                                   V      V
+	 *    +---+----------+-+----------+-+----------+-+----------+-+
+	 *    | M |   data   |E|   data   |E|   data   |E|   data   |E|
+	 *    +---+----------+-+----------+-+----------+-+----------+-+
+	 *
+	 * The position of block mark moves forward in the ECC-based view
+	 * of page, and the delta is:
+	 *
+	 *                   E * G * (N - 1)
+	 *             D = (---------------- + M)
+	 *                          8
+	 *
+	 * With the formula to compute the ECC strength, and the condition
+	 *       : C >= O         (C is the ecc chunk size)
+	 *
+	 * It's easy to deduce to the following result:
+	 *
+	 *         E * G       (O - M)      C - M         C - M
+	 *      ----------- <= ------- <=  --------  <  ---------
+	 *           8            N           N          (N - 1)
+	 *
+	 *  So, we get:
+	 *
+	 *                   E * G * (N - 1)
+	 *             D = (---------------- + M) < C
+	 *                          8
+	 *
+	 *  The above inequality means the position of block mark
+	 *  within the ECC-based view of the page is still in the data chunk,
+	 *  and it's NOT in the ECC bits of the chunk.
+	 *
+	 *  Use the following to compute the bit position of the
+	 *  physical block mark within the ECC-based view of the page:
+	 *          (page_size - D) * 8
+	 *
+	 *  --Huang Shijie
+	 */
+	block_mark_bit_offset = mtd->writesize * 8 -
+		(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
+				+ geo->metadata_size * 8);
+
+	geo->block_mark_byte_offset = block_mark_bit_offset / 8;
+	geo->block_mark_bit_offset  = block_mark_bit_offset % 8;
+	return 0;
+}
+
+struct dma_chan *get_dma_chan(struct gpmi_nand_data *this)
+{
+	int chipnr = this->current_chip;
+
+	return this->dma_chans[chipnr];
+}
+
+/* Can we use the upper's buffer directly for DMA? */
+void prepare_data_dma(struct gpmi_nand_data *this, enum dma_data_direction dr)
+{
+	struct scatterlist *sgl = &this->data_sgl;
+	int ret;
+
+	this->direct_dma_map_ok = true;
+
+	/* first try to map the upper buffer directly */
+	sg_init_one(sgl, this->upper_buf, this->upper_len);
+	ret = dma_map_sg(this->dev, sgl, 1, dr);
+	if (ret == 0) {
+		/* We have to use our own DMA buffer. */
+		sg_init_one(sgl, this->data_buffer_dma, PAGE_SIZE);
+
+		if (dr == DMA_TO_DEVICE)
+			memcpy(this->data_buffer_dma, this->upper_buf,
+				this->upper_len);
+
+		ret = dma_map_sg(this->dev, sgl, 1, dr);
+		if (ret == 0)
+			pr_err("map failed.\n");
+
+		this->direct_dma_map_ok = false;
+	}
+}
+
+/* This will be called after the DMA operation is finished. */
+static void dma_irq_callback(void *param)
+{
+	struct gpmi_nand_data *this = param;
+	struct completion *dma_c = &this->dma_done;
+
+	complete(dma_c);
+
+	switch (this->dma_type) {
+	case DMA_FOR_COMMAND:
+		dma_unmap_sg(this->dev, &this->cmd_sgl, 1, DMA_TO_DEVICE);
+		break;
+
+	case DMA_FOR_READ_DATA:
+		dma_unmap_sg(this->dev, &this->data_sgl, 1, DMA_FROM_DEVICE);
+		if (this->direct_dma_map_ok == false)
+			memcpy(this->upper_buf, this->data_buffer_dma,
+				this->upper_len);
+		break;
+
+	case DMA_FOR_WRITE_DATA:
+		dma_unmap_sg(this->dev, &this->data_sgl, 1, DMA_TO_DEVICE);
+		break;
+
+	case DMA_FOR_READ_ECC_PAGE:
+	case DMA_FOR_WRITE_ECC_PAGE:
+		/* We have to wait the BCH interrupt to finish. */
+		break;
+
+	default:
+		pr_err("in wrong DMA operation.\n");
+	}
+}
+
+int start_dma_without_bch_irq(struct gpmi_nand_data *this,
+				struct dma_async_tx_descriptor *desc)
+{
+	struct completion *dma_c = &this->dma_done;
+	int err;
+
+	init_completion(dma_c);
+
+	desc->callback		= dma_irq_callback;
+	desc->callback_param	= this;
+	dmaengine_submit(desc);
+
+	/* Wait for the interrupt from the DMA block. */
+	err = wait_for_completion_timeout(dma_c, msecs_to_jiffies(1000));
+	if (!err) {
+		pr_err("DMA timeout, last DMA :%d\n", this->last_dma_type);
+		gpmi_dump_info(this);
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+/*
+ * This function is used in BCH reading or BCH writing pages.
+ * It will wait for the BCH interrupt as long as ONE second.
+ * Actually, we must wait for two interrupts :
+ *	[1] firstly the DMA interrupt and
+ *	[2] secondly the BCH interrupt.
+ */
+int start_dma_with_bch_irq(struct gpmi_nand_data *this,
+			struct dma_async_tx_descriptor *desc)
+{
+	struct completion *bch_c = &this->bch_done;
+	int err;
+
+	/* Prepare to receive an interrupt from the BCH block. */
+	init_completion(bch_c);
+
+	/* start the DMA */
+	start_dma_without_bch_irq(this, desc);
+
+	/* Wait for the interrupt from the BCH block. */
+	err = wait_for_completion_timeout(bch_c, msecs_to_jiffies(1000));
+	if (!err) {
+		pr_err("BCH timeout, last DMA :%d\n", this->last_dma_type);
+		gpmi_dump_info(this);
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+static int __devinit
+acquire_register_block(struct gpmi_nand_data *this, const char *res_name)
+{
+	struct platform_device *pdev = this->pdev;
+	struct resources *res = &this->resources;
+	struct resource *r;
+	void *p;
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
+	if (!r) {
+		pr_err("Can't get resource for %s\n", res_name);
+		return -ENXIO;
+	}
+
+	p = ioremap(r->start, resource_size(r));
+	if (!p) {
+		pr_err("Can't remap %s\n", res_name);
+		return -ENOMEM;
+	}
+
+	if (!strcmp(res_name, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME))
+		res->gpmi_regs = p;
+	else if (!strcmp(res_name, GPMI_NAND_BCH_REGS_ADDR_RES_NAME))
+		res->bch_regs = p;
+	else
+		pr_err("unknown resource name : %s\n", res_name);
+
+	return 0;
+}
+
+static void release_register_block(struct gpmi_nand_data *this)
+{
+	struct resources *res = &this->resources;
+	if (res->gpmi_regs)
+		iounmap(res->gpmi_regs);
+	if (res->bch_regs)
+		iounmap(res->bch_regs);
+	res->gpmi_regs = NULL;
+	res->bch_regs = NULL;
+}
+
+static int __devinit
+acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h)
+{
+	struct platform_device *pdev = this->pdev;
+	struct resources *res = &this->resources;
+	const char *res_name = GPMI_NAND_BCH_INTERRUPT_RES_NAME;
+	struct resource *r;
+	int err;
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
+	if (!r) {
+		pr_err("Can't get resource for %s\n", res_name);
+		return -ENXIO;
+	}
+
+	err = request_irq(r->start, irq_h, 0, res_name, this);
+	if (err) {
+		pr_err("Can't own %s\n", res_name);
+		return err;
+	}
+
+	res->bch_low_interrupt = r->start;
+	res->bch_high_interrupt = r->end;
+	return 0;
+}
+
+static void release_bch_irq(struct gpmi_nand_data *this)
+{
+	struct resources *res = &this->resources;
+	int i = res->bch_low_interrupt;
+
+	for (; i <= res->bch_high_interrupt; i++)
+		free_irq(i, this);
+}
+
+static bool gpmi_dma_filter(struct dma_chan *chan, void *param)
+{
+	struct gpmi_nand_data *this = param;
+	struct resource *r = this->private;
+
+	if (!mxs_dma_is_apbh(chan))
+		return false;
+	/*
+	 * only catch the GPMI dma channels :
+	 *	for mx23 :	MX23_DMA_GPMI0 ~ MX23_DMA_GPMI3
+	 *		(These four channels share the same IRQ!)
+	 *
+	 *	for mx28 :	MX28_DMA_GPMI0 ~ MX28_DMA_GPMI7
+	 *		(These eight channels share the same IRQ!)
+	 */
+	if (r->start <= chan->chan_id && chan->chan_id <= r->end) {
+		chan->private = &this->dma_data;
+		return true;
+	}
+	return false;
+}
+
+static void release_dma_channels(struct gpmi_nand_data *this)
+{
+	unsigned int i;
+	for (i = 0; i < DMA_CHANS; i++)
+		if (this->dma_chans[i]) {
+			dma_release_channel(this->dma_chans[i]);
+			this->dma_chans[i] = NULL;
+		}
+}
+
+static int __devinit acquire_dma_channels(struct gpmi_nand_data *this)
+{
+	struct platform_device *pdev = this->pdev;
+	struct gpmi_nand_platform_data *pdata = this->pdata;
+	struct resources *res = &this->resources;
+	struct resource *r, *r_dma;
+	unsigned int i;
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_DMA,
+					GPMI_NAND_DMA_CHANNELS_RES_NAME);
+	r_dma = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
+					GPMI_NAND_DMA_INTERRUPT_RES_NAME);
+	if (!r || !r_dma) {
+		pr_err("Can't get resource for DMA\n");
+		return -ENXIO;
+	}
+
+	/* used in gpmi_dma_filter() */
+	this->private = r;
+
+	for (i = r->start; i <= r->end; i++) {
+		struct dma_chan *dma_chan;
+		dma_cap_mask_t mask;
+
+		if (i - r->start >= pdata->max_chip_count)
+			break;
+
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+
+		/* get the DMA interrupt */
+		if (r_dma->start == r_dma->end) {
+			/* only register the first. */
+			if (i == r->start)
+				this->dma_data.chan_irq = r_dma->start;
+			else
+				this->dma_data.chan_irq = NO_IRQ;
+		} else
+			this->dma_data.chan_irq = r_dma->start + (i - r->start);
+
+		dma_chan = dma_request_channel(mask, gpmi_dma_filter, this);
+		if (!dma_chan)
+			goto acquire_err;
+
+		/* fill the first empty item */
+		this->dma_chans[i - r->start] = dma_chan;
+	}
+
+	res->dma_low_channel = r->start;
+	res->dma_high_channel = i;
+	return 0;
+
+acquire_err:
+	pr_err("Can't acquire DMA channel %u\n", i);
+	release_dma_channels(this);
+	return -EINVAL;
+}
+
+static int __devinit acquire_resources(struct gpmi_nand_data *this)
+{
+	struct resources *res = &this->resources;
+	int ret;
+
+	ret = acquire_register_block(this, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME);
+	if (ret)
+		goto exit_regs;
+
+	ret = acquire_register_block(this, GPMI_NAND_BCH_REGS_ADDR_RES_NAME);
+	if (ret)
+		goto exit_regs;
+
+	ret = acquire_bch_irq(this, bch_irq);
+	if (ret)
+		goto exit_regs;
+
+	ret = acquire_dma_channels(this);
+	if (ret)
+		goto exit_dma_channels;
+
+	res->clock = clk_get(&this->pdev->dev, NULL);
+	if (IS_ERR(res->clock)) {
+		pr_err("can not get the clock\n");
+		ret = -ENOENT;
+		goto exit_clock;
+	}
+	return 0;
+
+exit_clock:
+	release_dma_channels(this);
+exit_dma_channels:
+	release_bch_irq(this);
+exit_regs:
+	release_register_block(this);
+	return ret;
+}
+
+static void release_resources(struct gpmi_nand_data *this)
+{
+	struct resources *r = &this->resources;
+
+	clk_put(r->clock);
+	release_register_block(this);
+	release_bch_irq(this);
+	release_dma_channels(this);
+}
+
+static int __devinit init_hardware(struct gpmi_nand_data *this)
+{
+	int ret;
+
+	/*
+	 * This structure contains the "safe" GPMI timing that should succeed
+	 * with any NAND Flash device
+	 * (although, with less-than-optimal performance).
+	 */
+	struct nand_timing  safe_timing = {
+		.data_setup_in_ns        = 80,
+		.data_hold_in_ns         = 60,
+		.address_setup_in_ns     = 25,
+		.gpmi_sample_delay_in_ns =  6,
+		.tREA_in_ns              = -1,
+		.tRLOH_in_ns             = -1,
+		.tRHOH_in_ns             = -1,
+	};
+
+	/* Initialize the hardwares. */
+	ret = gpmi_init(this);
+	if (ret)
+		return ret;
+
+	this->timing = safe_timing;
+	return 0;
+}
+
+static int read_page_prepare(struct gpmi_nand_data *this,
+			void *destination, unsigned length,
+			void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
+			void **use_virt, dma_addr_t *use_phys)
+{
+	struct device *dev = this->dev;
+
+	if (virt_addr_valid(destination)) {
+		dma_addr_t dest_phys;
+
+		dest_phys = dma_map_single(dev, destination,
+						length, DMA_FROM_DEVICE);
+		if (dma_mapping_error(dev, dest_phys)) {
+			if (alt_size < length) {
+				pr_err("Alternate buffer is too small\n");
+				return -ENOMEM;
+			}
+			goto map_failed;
+		}
+		*use_virt = destination;
+		*use_phys = dest_phys;
+		this->direct_dma_map_ok = true;
+		return 0;
+	}
+
+map_failed:
+	*use_virt = alt_virt;
+	*use_phys = alt_phys;
+	this->direct_dma_map_ok = false;
+	return 0;
+}
+
+static inline void read_page_end(struct gpmi_nand_data *this,
+			void *destination, unsigned length,
+			void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
+			void *used_virt, dma_addr_t used_phys)
+{
+	if (this->direct_dma_map_ok)
+		dma_unmap_single(this->dev, used_phys, length, DMA_FROM_DEVICE);
+}
+
+static inline void read_page_swap_end(struct gpmi_nand_data *this,
+			void *destination, unsigned length,
+			void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
+			void *used_virt, dma_addr_t used_phys)
+{
+	if (!this->direct_dma_map_ok)
+		memcpy(destination, alt_virt, length);
+}
+
+static int send_page_prepare(struct gpmi_nand_data *this,
+			const void *source, unsigned length,
+			void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
+			const void **use_virt, dma_addr_t *use_phys)
+{
+	struct device *dev = this->dev;
+
+	if (virt_addr_valid(source)) {
+		dma_addr_t source_phys;
+
+		source_phys = dma_map_single(dev, (void *)source, length,
+						DMA_TO_DEVICE);
+		if (dma_mapping_error(dev, source_phys)) {
+			if (alt_size < length) {
+				pr_err("Alternate buffer is too small\n");
+				return -ENOMEM;
+			}
+			goto map_failed;
+		}
+		*use_virt = source;
+		*use_phys = source_phys;
+		return 0;
+	}
+map_failed:
+	/*
+	 * Copy the content of the source buffer into the alternate
+	 * buffer and set up the return values accordingly.
+	 */
+	memcpy(alt_virt, source, length);
+
+	*use_virt = alt_virt;
+	*use_phys = alt_phys;
+	return 0;
+}
+
+static void send_page_end(struct gpmi_nand_data *this,
+			const void *source, unsigned length,
+			void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
+			const void *used_virt, dma_addr_t used_phys)
+{
+	struct device *dev = this->dev;
+	if (used_virt == source)
+		dma_unmap_single(dev, used_phys, length, DMA_TO_DEVICE);
+}
+
+static void gpmi_free_dma_buffer(struct gpmi_nand_data *this)
+{
+	struct device *dev = this->dev;
+
+	if (this->page_buffer_virt && virt_addr_valid(this->page_buffer_virt))
+		dma_free_coherent(dev, this->page_buffer_size,
+					this->page_buffer_virt,
+					this->page_buffer_phys);
+	kfree(this->cmd_buffer);
+	kfree(this->data_buffer_dma);
+
+	this->cmd_buffer	= NULL;
+	this->data_buffer_dma	= NULL;
+	this->page_buffer_virt	= NULL;
+	this->page_buffer_size	=  0;
+}
+
+/* Allocate the DMA buffers */
+static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
+{
+	struct bch_geometry *geo = &this->bch_geometry;
+	struct device *dev = this->dev;
+
+	/* [1] Allocate a command buffer. PAGE_SIZE is enough. */
+	this->cmd_buffer = kzalloc(PAGE_SIZE, GFP_DMA);
+	if (this->cmd_buffer == NULL)
+		goto error_alloc;
+
+	/* [2] Allocate a read/write data buffer. PAGE_SIZE is enough. */
+	this->data_buffer_dma = kzalloc(PAGE_SIZE, GFP_DMA);
+	if (this->data_buffer_dma == NULL)
+		goto error_alloc;
+
+	/*
+	 * [3] Allocate the page buffer.
+	 *
+	 * Both the payload buffer and the auxiliary buffer must appear on
+	 * 32-bit boundaries. We presume the size of the payload buffer is a
+	 * power of two and is much larger than four, which guarantees the
+	 * auxiliary buffer will appear on a 32-bit boundary.
+	 */
+	this->page_buffer_size = geo->payload_size + geo->auxiliary_size;
+	this->page_buffer_virt = dma_alloc_coherent(dev, this->page_buffer_size,
+					&this->page_buffer_phys, GFP_DMA);
+	if (!this->page_buffer_virt)
+		goto error_alloc;
+
+
+	/* Slice up the page buffer. */
+	this->payload_virt = this->page_buffer_virt;
+	this->payload_phys = this->page_buffer_phys;
+	this->auxiliary_virt = this->payload_virt + geo->payload_size;
+	this->auxiliary_phys = this->payload_phys + geo->payload_size;
+	return 0;
+
+error_alloc:
+	gpmi_free_dma_buffer(this);
+	pr_err("allocate DMA buffer ret!!\n");
+	return -ENOMEM;
+}
+
+static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct gpmi_nand_data *this = chip->priv;
+	int ret;
+
+	/*
+	 * Every operation begins with a command byte and a series of zero or
+	 * more address bytes. These are distinguished by either the Address
+	 * Latch Enable (ALE) or Command Latch Enable (CLE) signals being
+	 * asserted. When MTD is ready to execute the command, it will deassert
+	 * both latch enables.
+	 *
+	 * Rather than run a separate DMA operation for every single byte, we
+	 * queue them up and run a single DMA operation for the entire series
+	 * of command and data bytes. NAND_CMD_NONE means the END of the queue.
+	 */
+	if ((ctrl & (NAND_ALE | NAND_CLE))) {
+		if (data != NAND_CMD_NONE)
+			this->cmd_buffer[this->command_length++] = data;
+		return;
+	}
+
+	if (!this->command_length)
+		return;
+
+	ret = gpmi_send_command(this);
+	if (ret)
+		pr_err("Chip: %u, Error %d\n", this->current_chip, ret);
+
+	this->command_length = 0;
+}
+
+static int gpmi_dev_ready(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct gpmi_nand_data *this = chip->priv;
+
+	return gpmi_is_ready(this, this->current_chip);
+}
+
+static void gpmi_select_chip(struct mtd_info *mtd, int chipnr)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct gpmi_nand_data *this = chip->priv;
+
+	if ((this->current_chip < 0) && (chipnr >= 0))
+		gpmi_begin(this);
+	else if ((this->current_chip >= 0) && (chipnr < 0))
+		gpmi_end(this);
+
+	this->current_chip = chipnr;
+}
+
+static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct gpmi_nand_data *this = chip->priv;
+
+	pr_debug("len is %d\n", len);
+	this->upper_buf	= buf;
+	this->upper_len	= len;
+
+	gpmi_read_data(this);
+}
+
+static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct gpmi_nand_data *this = chip->priv;
+
+	pr_debug("len is %d\n", len);
+	this->upper_buf	= (uint8_t *)buf;
+	this->upper_len	= len;
+
+	gpmi_send_data(this);
+}
+
+static uint8_t gpmi_read_byte(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct gpmi_nand_data *this = chip->priv;
+	uint8_t *buf = this->data_buffer_dma;
+
+	gpmi_read_buf(mtd, buf, 1);
+	return buf[0];
+}
+
+/*
+ * Handles block mark swapping.
+ * It can be called in swapping the block mark, or swapping it back,
+ * because the the operations are the same.
+ */
+static void block_mark_swapping(struct gpmi_nand_data *this,
+				void *payload, void *auxiliary)
+{
+	struct bch_geometry *nfc_geo = &this->bch_geometry;
+	unsigned char *p;
+	unsigned char *a;
+	unsigned int  bit;
+	unsigned char mask;
+	unsigned char from_data;
+	unsigned char from_oob;
+
+	if (!this->swap_block_mark)
+		return;
+
+	/*
+	 * If control arrives here, we're swapping. Make some convenience
+	 * variables.
+	 */
+	bit = nfc_geo->block_mark_bit_offset;
+	p   = payload + nfc_geo->block_mark_byte_offset;
+	a   = auxiliary;
+
+	/*
+	 * Get the byte from the data area that overlays the block mark. Since
+	 * the ECC engine applies its own view to the bits in the page, the
+	 * physical block mark won't (in general) appear on a byte boundary in
+	 * the data.
+	 */
+	from_data = (p[0] >> bit) | (p[1] << (8 - bit));
+
+	/* Get the byte from the OOB. */
+	from_oob = a[0];
+
+	/* Swap them. */
+	a[0] = from_data;
+
+	mask = (0x1 << bit) - 1;
+	p[0] = (p[0] & mask) | (from_oob << bit);
+
+	mask = ~0 << bit;
+	p[1] = (p[1] & mask) | (from_oob >> (8 - bit));
+}
+
+static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+				uint8_t *buf, int page)
+{
+	struct gpmi_nand_data *this = chip->priv;
+	struct bch_geometry *nfc_geo = &this->bch_geometry;
+	void          *payload_virt;
+	dma_addr_t    payload_phys;
+	void          *auxiliary_virt;
+	dma_addr_t    auxiliary_phys;
+	unsigned int  i;
+	unsigned char *status;
+	unsigned int  failed;
+	unsigned int  corrected;
+	int           ret;
+
+	pr_debug("page number is : %d\n", page);
+	ret = read_page_prepare(this, buf, mtd->writesize,
+					this->payload_virt, this->payload_phys,
+					nfc_geo->payload_size,
+					&payload_virt, &payload_phys);
+	if (ret) {
+		pr_err("Inadequate DMA buffer\n");
+		ret = -ENOMEM;
+		return ret;
+	}
+	auxiliary_virt = this->auxiliary_virt;
+	auxiliary_phys = this->auxiliary_phys;
+
+	/* go! */
+	ret = gpmi_read_page(this, payload_phys, auxiliary_phys);
+	read_page_end(this, buf, mtd->writesize,
+			this->payload_virt, this->payload_phys,
+			nfc_geo->payload_size,
+			payload_virt, payload_phys);
+	if (ret) {
+		pr_err("Error in ECC-based read: %d\n", ret);
+		goto exit_nfc;
+	}
+
+	/* handle the block mark swapping */
+	block_mark_swapping(this, payload_virt, auxiliary_virt);
+
+	/* Loop over status bytes, accumulating ECC status. */
+	failed		= 0;
+	corrected	= 0;
+	status		= auxiliary_virt + nfc_geo->auxiliary_status_offset;
+
+	for (i = 0; i < nfc_geo->ecc_chunk_count; i++, status++) {
+		if ((*status == STATUS_GOOD) || (*status == STATUS_ERASED))
+			continue;
+
+		if (*status == STATUS_UNCORRECTABLE) {
+			failed++;
+			continue;
+		}
+		corrected += *status;
+	}
+
+	/*
+	 * Propagate ECC status to the owning MTD only when failed or
+	 * corrected times nearly reaches our ECC correction threshold.
+	 */
+	if (failed || corrected >= (nfc_geo->ecc_strength - 1)) {
+		mtd->ecc_stats.failed    += failed;
+		mtd->ecc_stats.corrected += corrected;
+	}
+
+	/*
+	 * It's time to deliver the OOB bytes. See gpmi_ecc_read_oob() for
+	 * details about our policy for delivering the OOB.
+	 *
+	 * We fill the caller's buffer with set bits, and then copy the block
+	 * mark to th caller's buffer. Note that, if block mark swapping was
+	 * necessary, it has already been done, so we can rely on the first
+	 * byte of the auxiliary buffer to contain the block mark.
+	 */
+	memset(chip->oob_poi, ~0, mtd->oobsize);
+	chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0];
+
+	read_page_swap_end(this, buf, mtd->writesize,
+			this->payload_virt, this->payload_phys,
+			nfc_geo->payload_size,
+			payload_virt, payload_phys);
+exit_nfc:
+	return ret;
+}
+
+static void gpmi_ecc_write_page(struct mtd_info *mtd,
+				struct nand_chip *chip, const uint8_t *buf)
+{
+	struct gpmi_nand_data *this = chip->priv;
+	struct bch_geometry *nfc_geo = &this->bch_geometry;
+	const void *payload_virt;
+	dma_addr_t payload_phys;
+	const void *auxiliary_virt;
+	dma_addr_t auxiliary_phys;
+	int        ret;
+
+	pr_debug("ecc write page.\n");
+	if (this->swap_block_mark) {
+		/*
+		 * If control arrives here, we're doing block mark swapping.
+		 * Since we can't modify the caller's buffers, we must copy them
+		 * into our own.
+		 */
+		memcpy(this->payload_virt, buf, mtd->writesize);
+		payload_virt = this->payload_virt;
+		payload_phys = this->payload_phys;
+
+		memcpy(this->auxiliary_virt, chip->oob_poi,
+				nfc_geo->auxiliary_size);
+		auxiliary_virt = this->auxiliary_virt;
+		auxiliary_phys = this->auxiliary_phys;
+
+		/* Handle block mark swapping. */
+		block_mark_swapping(this,
+				(void *) payload_virt, (void *) auxiliary_virt);
+	} else {
+		/*
+		 * If control arrives here, we're not doing block mark swapping,
+		 * so we can to try and use the caller's buffers.
+		 */
+		ret = send_page_prepare(this,
+				buf, mtd->writesize,
+				this->payload_virt, this->payload_phys,
+				nfc_geo->payload_size,
+				&payload_virt, &payload_phys);
+		if (ret) {
+			pr_err("Inadequate payload DMA buffer\n");
+			return;
+		}
+
+		ret = send_page_prepare(this,
+				chip->oob_poi, mtd->oobsize,
+				this->auxiliary_virt, this->auxiliary_phys,
+				nfc_geo->auxiliary_size,
+				&auxiliary_virt, &auxiliary_phys);
+		if (ret) {
+			pr_err("Inadequate auxiliary DMA buffer\n");
+			goto exit_auxiliary;
+		}
+	}
+
+	/* Ask the NFC. */
+	ret = gpmi_send_page(this, payload_phys, auxiliary_phys);
+	if (ret)
+		pr_err("Error in ECC-based write: %d\n", ret);
+
+	if (!this->swap_block_mark) {
+		send_page_end(this, chip->oob_poi, mtd->oobsize,
+				this->auxiliary_virt, this->auxiliary_phys,
+				nfc_geo->auxiliary_size,
+				auxiliary_virt, auxiliary_phys);
+exit_auxiliary:
+		send_page_end(this, buf, mtd->writesize,
+				this->payload_virt, this->payload_phys,
+				nfc_geo->payload_size,
+				payload_virt, payload_phys);
+	}
+}
+
+/*
+ * There are several places in this driver where we have to handle the OOB and
+ * block marks. This is the function where things are the most complicated, so
+ * this is where we try to explain it all. All the other places refer back to
+ * here.
+ *
+ * These are the rules, in order of decreasing importance:
+ *
+ * 1) Nothing the caller does can be allowed to imperil the block mark.
+ *
+ * 2) In read operations, the first byte of the OOB we return must reflect the
+ *    true state of the block mark, no matter where that block mark appears in
+ *    the physical page.
+ *
+ * 3) ECC-based read operations return an OOB full of set bits (since we never
+ *    allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads
+ *    return).
+ *
+ * 4) "Raw" read operations return a direct view of the physical bytes in the
+ *    page, using the conventional definition of which bytes are data and which
+ *    are OOB. This gives the caller a way to see the actual, physical bytes
+ *    in the page, without the distortions applied by our ECC engine.
+ *
+ *
+ * What we do for this specific read operation depends on two questions:
+ *
+ * 1) Are we doing a "raw" read, or an ECC-based read?
+ *
+ * 2) Are we using block mark swapping or transcription?
+ *
+ * There are four cases, illustrated by the following Karnaugh map:
+ *
+ *                    |           Raw           |         ECC-based       |
+ *       -------------+-------------------------+-------------------------+
+ *                    | Read the conventional   |                         |
+ *                    | OOB at the end of the   |                         |
+ *       Swapping     | page and return it. It  |                         |
+ *                    | contains exactly what   |                         |
+ *                    | we want.                | Read the block mark and |
+ *       -------------+-------------------------+ return it in a buffer   |
+ *                    | Read the conventional   | full of set bits.       |
+ *                    | OOB at the end of the   |                         |
+ *                    | page and also the block |                         |
+ *       Transcribing | mark in the metadata.   |                         |
+ *                    | Copy the block mark     |                         |
+ *                    | into the first byte of  |                         |
+ *                    | the OOB.                |                         |
+ *       -------------+-------------------------+-------------------------+
+ *
+ * Note that we break rule #4 in the Transcribing/Raw case because we're not
+ * giving an accurate view of the actual, physical bytes in the page (we're
+ * overwriting the block mark). That's OK because it's more important to follow
+ * rule #2.
+ *
+ * It turns out that knowing whether we want an "ECC-based" or "raw" read is not
+ * easy. When reading a page, for example, the NAND Flash MTD code calls our
+ * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an
+ * ECC-based or raw view of the page is implicit in which function it calls
+ * (there is a similar pair of ECC-based/raw functions for writing).
+ *
+ * Since MTD assumes the OOB is not covered by ECC, there is no pair of
+ * ECC-based/raw functions for reading or or writing the OOB. The fact that the
+ * caller wants an ECC-based or raw view of the page is not propagated down to
+ * this driver.
+ */
+static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
+				int page, int sndcmd)
+{
+	struct gpmi_nand_data *this = chip->priv;
+
+	pr_debug("page number is %d\n", page);
+	/* clear the OOB buffer */
+	memset(chip->oob_poi, ~0, mtd->oobsize);
+
+	/* Read out the conventional OOB. */
+	chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+	/*
+	 * Now, we want to make sure the block mark is correct. In the
+	 * Swapping/Raw case, we already have it. Otherwise, we need to
+	 * explicitly read it.
+	 */
+	if (!this->swap_block_mark) {
+		/* Read the block mark into the first byte of the OOB buffer. */
+		chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+		chip->oob_poi[0] = chip->read_byte(mtd);
+	}
+
+	/*
+	 * Return true, indicating that the next call to this function must send
+	 * a command.
+	 */
+	return true;
+}
+
+static int
+gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
+{
+	/*
+	 * The BCH will use all the (page + oob).
+	 * Our gpmi_hw_ecclayout can only prohibit the JFFS2 to write the oob.
+	 * But it can not stop some ioctls such MEMWRITEOOB which uses
+	 * MTD_OPS_PLACE_OOB. So We have to implement this function to prohibit
+	 * these ioctls too.
+	 */
+	return -EPERM;
+}
+
+static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct gpmi_nand_data *this = chip->priv;
+	int block, ret = 0;
+	uint8_t *block_mark;
+	int column, page, status, chipnr;
+
+	/* Get block number */
+	block = (int)(ofs >> chip->bbt_erase_shift);
+	if (chip->bbt)
+		chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
+
+	/* Do we have a flash based bad block table ? */
+	if (chip->options & NAND_BBT_USE_FLASH)
+		ret = nand_update_bbt(mtd, ofs);
+	else {
+		chipnr = (int)(ofs >> chip->chip_shift);
+		chip->select_chip(mtd, chipnr);
+
+		column = this->swap_block_mark ? mtd->writesize : 0;
+
+		/* Write the block mark. */
+		block_mark = this->data_buffer_dma;
+		block_mark[0] = 0; /* bad block marker */
+
+		/* Shift to get page */
+		page = (int)(ofs >> chip->page_shift);
+
+		chip->cmdfunc(mtd, NAND_CMD_SEQIN, column, page);
+		chip->write_buf(mtd, block_mark, 1);
+		chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+		status = chip->waitfunc(mtd, chip);
+		if (status & NAND_STATUS_FAIL)
+			ret = -EIO;
+
+		chip->select_chip(mtd, -1);
+	}
+	if (!ret)
+		mtd->ecc_stats.badblocks++;
+
+	return ret;
+}
+
+static int __devinit nand_boot_set_geometry(struct gpmi_nand_data *this)
+{
+	struct boot_rom_geometry *geometry = &this->rom_geometry;
+
+	/*
+	 * Set the boot block stride size.
+	 *
+	 * In principle, we should be reading this from the OTP bits, since
+	 * that's where the ROM is going to get it. In fact, we don't have any
+	 * way to read the OTP bits, so we go with the default and hope for the
+	 * best.
+	 */
+	geometry->stride_size_in_pages = 64;
+
+	/*
+	 * Set the search area stride exponent.
+	 *
+	 * In principle, we should be reading this from the OTP bits, since
+	 * that's where the ROM is going to get it. In fact, we don't have any
+	 * way to read the OTP bits, so we go with the default and hope for the
+	 * best.
+	 */
+	geometry->search_area_stride_exponent = 2;
+	return 0;
+}
+
+static const char  *fingerprint = "STMP";
+static int __devinit mx23_check_transcription_stamp(struct gpmi_nand_data *this)
+{
+	struct boot_rom_geometry *rom_geo = &this->rom_geometry;
+	struct device *dev = this->dev;
+	struct mtd_info *mtd = &this->mtd;
+	struct nand_chip *chip = &this->nand;
+	unsigned int search_area_size_in_strides;
+	unsigned int stride;
+	unsigned int page;
+	loff_t byte;
+	uint8_t *buffer = chip->buffers->databuf;
+	int saved_chip_number;
+	int found_an_ncb_fingerprint = false;
+
+	/* Compute the number of strides in a search area. */
+	search_area_size_in_strides = 1 << rom_geo->search_area_stride_exponent;
+
+	saved_chip_number = this->current_chip;
+	chip->select_chip(mtd, 0);
+
+	/*
+	 * Loop through the first search area, looking for the NCB fingerprint.
+	 */
+	dev_dbg(dev, "Scanning for an NCB fingerprint...\n");
+
+	for (stride = 0; stride < search_area_size_in_strides; stride++) {
+		/* Compute the page and byte addresses. */
+		page = stride * rom_geo->stride_size_in_pages;
+		byte = page   * mtd->writesize;
+
+		dev_dbg(dev, "Looking for a fingerprint in page 0x%x\n", page);
+
+		/*
+		 * Read the NCB fingerprint. The fingerprint is four bytes long
+		 * and starts in the 12th byte of the page.
+		 */
+		chip->cmdfunc(mtd, NAND_CMD_READ0, 12, page);
+		chip->read_buf(mtd, buffer, strlen(fingerprint));
+
+		/* Look for the fingerprint. */
+		if (!memcmp(buffer, fingerprint, strlen(fingerprint))) {
+			found_an_ncb_fingerprint = true;
+			break;
+		}
+
+	}
+
+	chip->select_chip(mtd, saved_chip_number);
+
+	if (found_an_ncb_fingerprint)
+		dev_dbg(dev, "\tFound a fingerprint\n");
+	else
+		dev_dbg(dev, "\tNo fingerprint found\n");
+	return found_an_ncb_fingerprint;
+}
+
+/* Writes a transcription stamp. */
+static int __devinit mx23_write_transcription_stamp(struct gpmi_nand_data *this)
+{
+	struct device *dev = this->dev;
+	struct boot_rom_geometry *rom_geo = &this->rom_geometry;
+	struct mtd_info *mtd = &this->mtd;
+	struct nand_chip *chip = &this->nand;
+	unsigned int block_size_in_pages;
+	unsigned int search_area_size_in_strides;
+	unsigned int search_area_size_in_pages;
+	unsigned int search_area_size_in_blocks;
+	unsigned int block;
+	unsigned int stride;
+	unsigned int page;
+	loff_t       byte;
+	uint8_t      *buffer = chip->buffers->databuf;
+	int saved_chip_number;
+	int status;
+
+	/* Compute the search area geometry. */
+	block_size_in_pages = mtd->erasesize / mtd->writesize;
+	search_area_size_in_strides = 1 << rom_geo->search_area_stride_exponent;
+	search_area_size_in_pages = search_area_size_in_strides *
+					rom_geo->stride_size_in_pages;
+	search_area_size_in_blocks =
+		  (search_area_size_in_pages + (block_size_in_pages - 1)) /
+				    block_size_in_pages;
+
+	dev_dbg(dev, "Search Area Geometry :\n");
+	dev_dbg(dev, "\tin Blocks : %u\n", search_area_size_in_blocks);
+	dev_dbg(dev, "\tin Strides: %u\n", search_area_size_in_strides);
+	dev_dbg(dev, "\tin Pages  : %u\n", search_area_size_in_pages);
+
+	/* Select chip 0. */
+	saved_chip_number = this->current_chip;
+	chip->select_chip(mtd, 0);
+
+	/* Loop over blocks in the first search area, erasing them. */
+	dev_dbg(dev, "Erasing the search area...\n");
+
+	for (block = 0; block < search_area_size_in_blocks; block++) {
+		/* Compute the page address. */
+		page = block * block_size_in_pages;
+
+		/* Erase this block. */
+		dev_dbg(dev, "\tErasing block 0x%x\n", block);
+		chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
+		chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
+
+		/* Wait for the erase to finish. */
+		status = chip->waitfunc(mtd, chip);
+		if (status & NAND_STATUS_FAIL)
+			dev_err(dev, "[%s] Erase failed.\n", __func__);
+	}
+
+	/* Write the NCB fingerprint into the page buffer. */
+	memset(buffer, ~0, mtd->writesize);
+	memset(chip->oob_poi, ~0, mtd->oobsize);
+	memcpy(buffer + 12, fingerprint, strlen(fingerprint));
+
+	/* Loop through the first search area, writing NCB fingerprints. */
+	dev_dbg(dev, "Writing NCB fingerprints...\n");
+	for (stride = 0; stride < search_area_size_in_strides; stride++) {
+		/* Compute the page and byte addresses. */
+		page = stride * rom_geo->stride_size_in_pages;
+		byte = page   * mtd->writesize;
+
+		/* Write the first page of the current stride. */
+		dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page);
+		chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+		chip->ecc.write_page_raw(mtd, chip, buffer);
+		chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+		/* Wait for the write to finish. */
+		status = chip->waitfunc(mtd, chip);
+		if (status & NAND_STATUS_FAIL)
+			dev_err(dev, "[%s] Write failed.\n", __func__);
+	}
+
+	/* Deselect chip 0. */
+	chip->select_chip(mtd, saved_chip_number);
+	return 0;
+}
+
+static int __devinit mx23_boot_init(struct gpmi_nand_data  *this)
+{
+	struct device *dev = this->dev;
+	struct nand_chip *chip = &this->nand;
+	struct mtd_info *mtd = &this->mtd;
+	unsigned int block_count;
+	unsigned int block;
+	int     chipnr;
+	int     page;
+	loff_t  byte;
+	uint8_t block_mark;
+	int     ret = 0;
+
+	/*
+	 * If control arrives here, we can't use block mark swapping, which
+	 * means we're forced to use transcription. First, scan for the
+	 * transcription stamp. If we find it, then we don't have to do
+	 * anything -- the block marks are already transcribed.
+	 */
+	if (mx23_check_transcription_stamp(this))
+		return 0;
+
+	/*
+	 * If control arrives here, we couldn't find a transcription stamp, so
+	 * so we presume the block marks are in the conventional location.
+	 */
+	dev_dbg(dev, "Transcribing bad block marks...\n");
+
+	/* Compute the number of blocks in the entire medium. */
+	block_count = chip->chipsize >> chip->phys_erase_shift;
+
+	/*
+	 * Loop over all the blocks in the medium, transcribing block marks as
+	 * we go.
+	 */
+	for (block = 0; block < block_count; block++) {
+		/*
+		 * Compute the chip, page and byte addresses for this block's
+		 * conventional mark.
+		 */
+		chipnr = block >> (chip->chip_shift - chip->phys_erase_shift);
+		page = block << (chip->phys_erase_shift - chip->page_shift);
+		byte = block <<  chip->phys_erase_shift;
+
+		/* Send the command to read the conventional block mark. */
+		chip->select_chip(mtd, chipnr);
+		chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+		block_mark = chip->read_byte(mtd);
+		chip->select_chip(mtd, -1);
+
+		/*
+		 * Check if the block is marked bad. If so, we need to mark it
+		 * again, but this time the result will be a mark in the
+		 * location where we transcribe block marks.
+		 */
+		if (block_mark != 0xff) {
+			dev_dbg(dev, "Transcribing mark in block %u\n", block);
+			ret = chip->block_markbad(mtd, byte);
+			if (ret)
+				dev_err(dev, "Failed to mark block bad with "
+							"ret %d\n", ret);
+		}
+	}
+
+	/* Write the stamp that indicates we've transcribed the block marks. */
+	mx23_write_transcription_stamp(this);
+	return 0;
+}
+
+static int __devinit nand_boot_init(struct gpmi_nand_data  *this)
+{
+	nand_boot_set_geometry(this);
+
+	/* This is ROM arch-specific initilization before the BBT scanning. */
+	if (GPMI_IS_MX23(this))
+		return mx23_boot_init(this);
+	return 0;
+}
+
+static int __devinit gpmi_set_geometry(struct gpmi_nand_data *this)
+{
+	int ret;
+
+	/* Free the temporary DMA memory for reading ID. */
+	gpmi_free_dma_buffer(this);
+
+	/* Set up the NFC geometry which is used by BCH. */
+	ret = bch_set_geometry(this);
+	if (ret) {
+		pr_err("set geometry ret : %d\n", ret);
+		return ret;
+	}
+
+	/* Alloc the new DMA buffers according to the pagesize and oobsize */
+	return gpmi_alloc_dma_buffer(this);
+}
+
+static int gpmi_pre_bbt_scan(struct gpmi_nand_data  *this)
+{
+	int ret;
+
+	/* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
+	if (GPMI_IS_MX23(this))
+		this->swap_block_mark = false;
+	else
+		this->swap_block_mark = true;
+
+	/* Set up the medium geometry */
+	ret = gpmi_set_geometry(this);
+	if (ret)
+		return ret;
+
+	/* NAND boot init, depends on the gpmi_set_geometry(). */
+	return nand_boot_init(this);
+}
+
+static int gpmi_scan_bbt(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct gpmi_nand_data *this = chip->priv;
+	int ret;
+
+	/* Prepare for the BBT scan. */
+	ret = gpmi_pre_bbt_scan(this);
+	if (ret)
+		return ret;
+
+	/* use the default BBT implementation */
+	return nand_default_bbt(mtd);
+}
+
+void gpmi_nfc_exit(struct gpmi_nand_data *this)
+{
+	nand_release(&this->mtd);
+	gpmi_free_dma_buffer(this);
+}
+
+static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this)
+{
+	struct gpmi_nand_platform_data *pdata = this->pdata;
+	struct mtd_info  *mtd = &this->mtd;
+	struct nand_chip *chip = &this->nand;
+	int ret;
+
+	/* init current chip */
+	this->current_chip	= -1;
+
+	/* init the MTD data structures */
+	mtd->priv		= chip;
+	mtd->name		= "gpmi-nand";
+	mtd->owner		= THIS_MODULE;
+
+	/* init the nand_chip{}, we don't support a 16-bit NAND Flash bus. */
+	chip->priv		= this;
+	chip->select_chip	= gpmi_select_chip;
+	chip->cmd_ctrl		= gpmi_cmd_ctrl;
+	chip->dev_ready		= gpmi_dev_ready;
+	chip->read_byte		= gpmi_read_byte;
+	chip->read_buf		= gpmi_read_buf;
+	chip->write_buf		= gpmi_write_buf;
+	chip->ecc.read_page	= gpmi_ecc_read_page;
+	chip->ecc.write_page	= gpmi_ecc_write_page;
+	chip->ecc.read_oob	= gpmi_ecc_read_oob;
+	chip->ecc.write_oob	= gpmi_ecc_write_oob;
+	chip->scan_bbt		= gpmi_scan_bbt;
+	chip->badblock_pattern	= &gpmi_bbt_descr;
+	chip->block_markbad	= gpmi_block_markbad;
+	chip->options		|= NAND_NO_SUBPAGE_WRITE;
+	chip->ecc.mode		= NAND_ECC_HW;
+	chip->ecc.size		= 1;
+	chip->ecc.layout	= &gpmi_hw_ecclayout;
+
+	/* Allocate a temporary DMA buffer for reading ID in the nand_scan() */
+	this->bch_geometry.payload_size = 1024;
+	this->bch_geometry.auxiliary_size = 128;
+	ret = gpmi_alloc_dma_buffer(this);
+	if (ret)
+		goto err_out;
+
+	ret = nand_scan(mtd, pdata->max_chip_count);
+	if (ret) {
+		pr_err("Chip scan failed\n");
+		goto err_out;
+	}
+
+	ret = mtd_device_parse_register(mtd, NULL, NULL,
+			pdata->partitions, pdata->partition_count);
+	if (ret)
+		goto err_out;
+	return 0;
+
+err_out:
+	gpmi_nfc_exit(this);
+	return ret;
+}
+
+static int __devinit gpmi_nand_probe(struct platform_device *pdev)
+{
+	struct gpmi_nand_platform_data *pdata = pdev->dev.platform_data;
+	struct gpmi_nand_data *this;
+	int ret;
+
+	this = kzalloc(sizeof(*this), GFP_KERNEL);
+	if (!this) {
+		pr_err("Failed to allocate per-device memory\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, this);
+	this->pdev  = pdev;
+	this->dev   = &pdev->dev;
+	this->pdata = pdata;
+
+	if (pdata->platform_init) {
+		ret = pdata->platform_init();
+		if (ret)
+			goto platform_init_error;
+	}
+
+	ret = acquire_resources(this);
+	if (ret)
+		goto exit_acquire_resources;
+
+	ret = init_hardware(this);
+	if (ret)
+		goto exit_nfc_init;
+
+	ret = gpmi_nfc_init(this);
+	if (ret)
+		goto exit_nfc_init;
+
+	return 0;
+
+exit_nfc_init:
+	release_resources(this);
+platform_init_error:
+exit_acquire_resources:
+	platform_set_drvdata(pdev, NULL);
+	kfree(this);
+	return ret;
+}
+
+static int __exit gpmi_nand_remove(struct platform_device *pdev)
+{
+	struct gpmi_nand_data *this = platform_get_drvdata(pdev);
+
+	gpmi_nfc_exit(this);
+	release_resources(this);
+	platform_set_drvdata(pdev, NULL);
+	kfree(this);
+	return 0;
+}
+
+static const struct platform_device_id gpmi_ids[] = {
+	{
+		.name = "imx23-gpmi-nand",
+		.driver_data = IS_MX23,
+	}, {
+		.name = "imx28-gpmi-nand",
+		.driver_data = IS_MX28,
+	}, {},
+};
+
+static struct platform_driver gpmi_nand_driver = {
+	.driver = {
+		.name = "gpmi-nand",
+	},
+	.probe   = gpmi_nand_probe,
+	.remove  = __exit_p(gpmi_nand_remove),
+	.id_table = gpmi_ids,
+};
+
+static int __init gpmi_nand_init(void)
+{
+	int err;
+
+	err = platform_driver_register(&gpmi_nand_driver);
+	if (err == 0)
+		printk(KERN_INFO "GPMI NAND driver registered. (IMX)\n");
+	else
+		pr_err("i.MX GPMI NAND driver registration failed\n");
+	return err;
+}
+
+static void __exit gpmi_nand_exit(void)
+{
+	platform_driver_unregister(&gpmi_nand_driver);
+}
+
+module_init(gpmi_nand_init);
+module_exit(gpmi_nand_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("i.MX GPMI NAND Flash Controller Driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/gpmi-nand/gpmi-nand.h linux-libre-3.2-gnu/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
--- linux-libre-3.1-gnu/drivers/mtd/nand/gpmi-nand/gpmi-nand.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/mtd/nand/gpmi-nand/gpmi-nand.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,273 @@
+/*
+ * Freescale GPMI NAND Flash Driver
+ *
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 Embedded Alley Solutions, 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.
+ */
+#ifndef __DRIVERS_MTD_NAND_GPMI_NAND_H
+#define __DRIVERS_MTD_NAND_GPMI_NAND_H
+
+#include <linux/mtd/nand.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <mach/dma.h>
+
+struct resources {
+	void          *gpmi_regs;
+	void          *bch_regs;
+	unsigned int  bch_low_interrupt;
+	unsigned int  bch_high_interrupt;
+	unsigned int  dma_low_channel;
+	unsigned int  dma_high_channel;
+	struct clk    *clock;
+};
+
+/**
+ * struct bch_geometry - BCH geometry description.
+ * @gf_len:                   The length of Galois Field. (e.g., 13 or 14)
+ * @ecc_strength:             A number that describes the strength of the ECC
+ *                            algorithm.
+ * @page_size:                The size, in bytes, of a physical page, including
+ *                            both data and OOB.
+ * @metadata_size:            The size, in bytes, of the metadata.
+ * @ecc_chunk_size:           The size, in bytes, of a single ECC chunk. Note
+ *                            the first chunk in the page includes both data and
+ *                            metadata, so it's a bit larger than this value.
+ * @ecc_chunk_count:          The number of ECC chunks in the page,
+ * @payload_size:             The size, in bytes, of the payload buffer.
+ * @auxiliary_size:           The size, in bytes, of the auxiliary buffer.
+ * @auxiliary_status_offset:  The offset into the auxiliary buffer at which
+ *                            the ECC status appears.
+ * @block_mark_byte_offset:   The byte offset in the ECC-based page view at
+ *                            which the underlying physical block mark appears.
+ * @block_mark_bit_offset:    The bit offset into the ECC-based page view at
+ *                            which the underlying physical block mark appears.
+ */
+struct bch_geometry {
+	unsigned int  gf_len;
+	unsigned int  ecc_strength;
+	unsigned int  page_size;
+	unsigned int  metadata_size;
+	unsigned int  ecc_chunk_size;
+	unsigned int  ecc_chunk_count;
+	unsigned int  payload_size;
+	unsigned int  auxiliary_size;
+	unsigned int  auxiliary_status_offset;
+	unsigned int  block_mark_byte_offset;
+	unsigned int  block_mark_bit_offset;
+};
+
+/**
+ * struct boot_rom_geometry - Boot ROM geometry description.
+ * @stride_size_in_pages:        The size of a boot block stride, in pages.
+ * @search_area_stride_exponent: The logarithm to base 2 of the size of a
+ *                               search area in boot block strides.
+ */
+struct boot_rom_geometry {
+	unsigned int  stride_size_in_pages;
+	unsigned int  search_area_stride_exponent;
+};
+
+/* DMA operations types */
+enum dma_ops_type {
+	DMA_FOR_COMMAND = 1,
+	DMA_FOR_READ_DATA,
+	DMA_FOR_WRITE_DATA,
+	DMA_FOR_READ_ECC_PAGE,
+	DMA_FOR_WRITE_ECC_PAGE
+};
+
+/**
+ * struct nand_timing - Fundamental timing attributes for NAND.
+ * @data_setup_in_ns:         The data setup time, in nanoseconds. Usually the
+ *                            maximum of tDS and tWP. A negative value
+ *                            indicates this characteristic isn't known.
+ * @data_hold_in_ns:          The data hold time, in nanoseconds. Usually the
+ *                            maximum of tDH, tWH and tREH. A negative value
+ *                            indicates this characteristic isn't known.
+ * @address_setup_in_ns:      The address setup time, in nanoseconds. Usually
+ *                            the maximum of tCLS, tCS and tALS. A negative
+ *                            value indicates this characteristic isn't known.
+ * @gpmi_sample_delay_in_ns:  A GPMI-specific timing parameter. A negative value
+ *                            indicates this characteristic isn't known.
+ * @tREA_in_ns:               tREA, in nanoseconds, from the data sheet. A
+ *                            negative value indicates this characteristic isn't
+ *                            known.
+ * @tRLOH_in_ns:              tRLOH, in nanoseconds, from the data sheet. A
+ *                            negative value indicates this characteristic isn't
+ *                            known.
+ * @tRHOH_in_ns:              tRHOH, in nanoseconds, from the data sheet. A
+ *                            negative value indicates this characteristic isn't
+ *                            known.
+ */
+struct nand_timing {
+	int8_t  data_setup_in_ns;
+	int8_t  data_hold_in_ns;
+	int8_t  address_setup_in_ns;
+	int8_t  gpmi_sample_delay_in_ns;
+	int8_t  tREA_in_ns;
+	int8_t  tRLOH_in_ns;
+	int8_t  tRHOH_in_ns;
+};
+
+struct gpmi_nand_data {
+	/* System Interface */
+	struct device		*dev;
+	struct platform_device	*pdev;
+	struct gpmi_nand_platform_data	*pdata;
+
+	/* Resources */
+	struct resources	resources;
+
+	/* Flash Hardware */
+	struct nand_timing	timing;
+
+	/* BCH */
+	struct bch_geometry	bch_geometry;
+	struct completion	bch_done;
+
+	/* NAND Boot issue */
+	bool			swap_block_mark;
+	struct boot_rom_geometry rom_geometry;
+
+	/* MTD / NAND */
+	struct nand_chip	nand;
+	struct mtd_info		mtd;
+
+	/* General-use Variables */
+	int			current_chip;
+	unsigned int		command_length;
+
+	/* passed from upper layer */
+	uint8_t			*upper_buf;
+	int			upper_len;
+
+	/* for DMA operations */
+	bool			direct_dma_map_ok;
+
+	struct scatterlist	cmd_sgl;
+	char			*cmd_buffer;
+
+	struct scatterlist	data_sgl;
+	char			*data_buffer_dma;
+
+	void			*page_buffer_virt;
+	dma_addr_t		page_buffer_phys;
+	unsigned int		page_buffer_size;
+
+	void			*payload_virt;
+	dma_addr_t		payload_phys;
+
+	void			*auxiliary_virt;
+	dma_addr_t		auxiliary_phys;
+
+	/* DMA channels */
+#define DMA_CHANS		8
+	struct dma_chan		*dma_chans[DMA_CHANS];
+	struct mxs_dma_data	dma_data;
+	enum dma_ops_type	last_dma_type;
+	enum dma_ops_type	dma_type;
+	struct completion	dma_done;
+
+	/* private */
+	void			*private;
+};
+
+/**
+ * struct gpmi_nfc_hardware_timing - GPMI hardware timing parameters.
+ * @data_setup_in_cycles:      The data setup time, in cycles.
+ * @data_hold_in_cycles:       The data hold time, in cycles.
+ * @address_setup_in_cycles:   The address setup time, in cycles.
+ * @use_half_periods:          Indicates the clock is running slowly, so the
+ *                             NFC DLL should use half-periods.
+ * @sample_delay_factor:       The sample delay factor.
+ */
+struct gpmi_nfc_hardware_timing {
+	uint8_t  data_setup_in_cycles;
+	uint8_t  data_hold_in_cycles;
+	uint8_t  address_setup_in_cycles;
+	bool     use_half_periods;
+	uint8_t  sample_delay_factor;
+};
+
+/**
+ * struct timing_threshod - Timing threshold
+ * @max_data_setup_cycles:       The maximum number of data setup cycles that
+ *                               can be expressed in the hardware.
+ * @internal_data_setup_in_ns:   The time, in ns, that the NFC hardware requires
+ *                               for data read internal setup. In the Reference
+ *                               Manual, see the chapter "High-Speed NAND
+ *                               Timing" for more details.
+ * @max_sample_delay_factor:     The maximum sample delay factor that can be
+ *                               expressed in the hardware.
+ * @max_dll_clock_period_in_ns:  The maximum period of the GPMI clock that the
+ *                               sample delay DLL hardware can possibly work
+ *                               with (the DLL is unusable with longer periods).
+ *                               If the full-cycle period is greater than HALF
+ *                               this value, the DLL must be configured to use
+ *                               half-periods.
+ * @max_dll_delay_in_ns:         The maximum amount of delay, in ns, that the
+ *                               DLL can implement.
+ * @clock_frequency_in_hz:       The clock frequency, in Hz, during the current
+ *                               I/O transaction. If no I/O transaction is in
+ *                               progress, this is the clock frequency during
+ *                               the most recent I/O transaction.
+ */
+struct timing_threshod {
+	const unsigned int      max_chip_count;
+	const unsigned int      max_data_setup_cycles;
+	const unsigned int      internal_data_setup_in_ns;
+	const unsigned int      max_sample_delay_factor;
+	const unsigned int      max_dll_clock_period_in_ns;
+	const unsigned int      max_dll_delay_in_ns;
+	unsigned long           clock_frequency_in_hz;
+
+};
+
+/* Common Services */
+extern int common_nfc_set_geometry(struct gpmi_nand_data *);
+extern struct dma_chan *get_dma_chan(struct gpmi_nand_data *);
+extern void prepare_data_dma(struct gpmi_nand_data *,
+				enum dma_data_direction dr);
+extern int start_dma_without_bch_irq(struct gpmi_nand_data *,
+				struct dma_async_tx_descriptor *);
+extern int start_dma_with_bch_irq(struct gpmi_nand_data *,
+				struct dma_async_tx_descriptor *);
+
+/* GPMI-NAND helper function library */
+extern int gpmi_init(struct gpmi_nand_data *);
+extern void gpmi_clear_bch(struct gpmi_nand_data *);
+extern void gpmi_dump_info(struct gpmi_nand_data *);
+extern int bch_set_geometry(struct gpmi_nand_data *);
+extern int gpmi_is_ready(struct gpmi_nand_data *, unsigned chip);
+extern int gpmi_send_command(struct gpmi_nand_data *);
+extern void gpmi_begin(struct gpmi_nand_data *);
+extern void gpmi_end(struct gpmi_nand_data *);
+extern int gpmi_read_data(struct gpmi_nand_data *);
+extern int gpmi_send_data(struct gpmi_nand_data *);
+extern int gpmi_send_page(struct gpmi_nand_data *,
+			dma_addr_t payload, dma_addr_t auxiliary);
+extern int gpmi_read_page(struct gpmi_nand_data *,
+			dma_addr_t payload, dma_addr_t auxiliary);
+
+/* BCH : Status Block Completion Codes */
+#define STATUS_GOOD		0x00
+#define STATUS_ERASED		0xff
+#define STATUS_UNCORRECTABLE	0xfe
+
+/* Use the platform_id to distinguish different Archs. */
+#define IS_MX23			0x1
+#define IS_MX28			0x2
+#define GPMI_IS_MX23(x)		((x)->pdev->id_entry->driver_data == IS_MX23)
+#define GPMI_IS_MX28(x)		((x)->pdev->id_entry->driver_data == IS_MX28)
+#endif
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/gpmi-nand/gpmi-regs.h linux-libre-3.2-gnu/drivers/mtd/nand/gpmi-nand/gpmi-regs.h
--- linux-libre-3.1-gnu/drivers/mtd/nand/gpmi-nand/gpmi-regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/mtd/nand/gpmi-nand/gpmi-regs.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,172 @@
+/*
+ * Freescale GPMI NAND Flash Driver
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, 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.
+ */
+#ifndef __GPMI_NAND_GPMI_REGS_H
+#define __GPMI_NAND_GPMI_REGS_H
+
+#define HW_GPMI_CTRL0					0x00000000
+#define HW_GPMI_CTRL0_SET				0x00000004
+#define HW_GPMI_CTRL0_CLR				0x00000008
+#define HW_GPMI_CTRL0_TOG				0x0000000c
+
+#define BP_GPMI_CTRL0_COMMAND_MODE			24
+#define BM_GPMI_CTRL0_COMMAND_MODE	(3 << BP_GPMI_CTRL0_COMMAND_MODE)
+#define BF_GPMI_CTRL0_COMMAND_MODE(v)	\
+	(((v) << BP_GPMI_CTRL0_COMMAND_MODE) & BM_GPMI_CTRL0_COMMAND_MODE)
+#define BV_GPMI_CTRL0_COMMAND_MODE__WRITE		0x0
+#define BV_GPMI_CTRL0_COMMAND_MODE__READ		0x1
+#define BV_GPMI_CTRL0_COMMAND_MODE__READ_AND_COMPARE	0x2
+#define BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY	0x3
+
+#define BM_GPMI_CTRL0_WORD_LENGTH			(1 << 23)
+#define BV_GPMI_CTRL0_WORD_LENGTH__16_BIT		0x0
+#define BV_GPMI_CTRL0_WORD_LENGTH__8_BIT		0x1
+
+/*
+ *  Difference in LOCK_CS between imx23 and imx28 :
+ *  This bit may impact the _POWER_ consumption. So some chips
+ *  do not set it.
+ */
+#define MX23_BP_GPMI_CTRL0_LOCK_CS			22
+#define MX28_BP_GPMI_CTRL0_LOCK_CS			27
+#define LOCK_CS_ENABLE					0x1
+#define BF_GPMI_CTRL0_LOCK_CS(v, x)			0x0
+
+/* Difference in CS between imx23 and imx28 */
+#define BP_GPMI_CTRL0_CS				20
+#define MX23_BM_GPMI_CTRL0_CS		(3 << BP_GPMI_CTRL0_CS)
+#define MX28_BM_GPMI_CTRL0_CS		(7 << BP_GPMI_CTRL0_CS)
+#define BF_GPMI_CTRL0_CS(v, x)		(((v) << BP_GPMI_CTRL0_CS) & \
+						(GPMI_IS_MX23((x)) \
+						? MX23_BM_GPMI_CTRL0_CS	\
+						: MX28_BM_GPMI_CTRL0_CS))
+
+#define BP_GPMI_CTRL0_ADDRESS				17
+#define BM_GPMI_CTRL0_ADDRESS		(3 << BP_GPMI_CTRL0_ADDRESS)
+#define BF_GPMI_CTRL0_ADDRESS(v)	\
+		(((v) << BP_GPMI_CTRL0_ADDRESS) & BM_GPMI_CTRL0_ADDRESS)
+#define BV_GPMI_CTRL0_ADDRESS__NAND_DATA		0x0
+#define BV_GPMI_CTRL0_ADDRESS__NAND_CLE			0x1
+#define BV_GPMI_CTRL0_ADDRESS__NAND_ALE			0x2
+
+#define BM_GPMI_CTRL0_ADDRESS_INCREMENT			(1 << 16)
+#define BV_GPMI_CTRL0_ADDRESS_INCREMENT__DISABLED	0x0
+#define BV_GPMI_CTRL0_ADDRESS_INCREMENT__ENABLED	0x1
+
+#define BP_GPMI_CTRL0_XFER_COUNT			0
+#define BM_GPMI_CTRL0_XFER_COUNT	(0xffff << BP_GPMI_CTRL0_XFER_COUNT)
+#define BF_GPMI_CTRL0_XFER_COUNT(v)	\
+		(((v) << BP_GPMI_CTRL0_XFER_COUNT) & BM_GPMI_CTRL0_XFER_COUNT)
+
+#define HW_GPMI_COMPARE					0x00000010
+
+#define HW_GPMI_ECCCTRL					0x00000020
+#define HW_GPMI_ECCCTRL_SET				0x00000024
+#define HW_GPMI_ECCCTRL_CLR				0x00000028
+#define HW_GPMI_ECCCTRL_TOG				0x0000002c
+
+#define BP_GPMI_ECCCTRL_ECC_CMD				13
+#define BM_GPMI_ECCCTRL_ECC_CMD		(3 << BP_GPMI_ECCCTRL_ECC_CMD)
+#define BF_GPMI_ECCCTRL_ECC_CMD(v)	\
+		(((v) << BP_GPMI_ECCCTRL_ECC_CMD) & BM_GPMI_ECCCTRL_ECC_CMD)
+#define BV_GPMI_ECCCTRL_ECC_CMD__BCH_DECODE		0x0
+#define BV_GPMI_ECCCTRL_ECC_CMD__BCH_ENCODE		0x1
+
+#define BM_GPMI_ECCCTRL_ENABLE_ECC			(1 << 12)
+#define BV_GPMI_ECCCTRL_ENABLE_ECC__ENABLE		0x1
+#define BV_GPMI_ECCCTRL_ENABLE_ECC__DISABLE		0x0
+
+#define BP_GPMI_ECCCTRL_BUFFER_MASK			0
+#define BM_GPMI_ECCCTRL_BUFFER_MASK	(0x1ff << BP_GPMI_ECCCTRL_BUFFER_MASK)
+#define BF_GPMI_ECCCTRL_BUFFER_MASK(v)	\
+	(((v) << BP_GPMI_ECCCTRL_BUFFER_MASK) & BM_GPMI_ECCCTRL_BUFFER_MASK)
+#define BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY	0x100
+#define BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE		0x1FF
+
+#define HW_GPMI_ECCCOUNT				0x00000030
+#define HW_GPMI_PAYLOAD					0x00000040
+#define HW_GPMI_AUXILIARY				0x00000050
+#define HW_GPMI_CTRL1					0x00000060
+#define HW_GPMI_CTRL1_SET				0x00000064
+#define HW_GPMI_CTRL1_CLR				0x00000068
+#define HW_GPMI_CTRL1_TOG				0x0000006c
+
+#define BM_GPMI_CTRL1_BCH_MODE				(1 << 18)
+
+#define BP_GPMI_CTRL1_DLL_ENABLE			17
+#define BM_GPMI_CTRL1_DLL_ENABLE	(1 << BP_GPMI_CTRL1_DLL_ENABLE)
+
+#define BP_GPMI_CTRL1_HALF_PERIOD			16
+#define BM_GPMI_CTRL1_HALF_PERIOD	(1 << BP_GPMI_CTRL1_HALF_PERIOD)
+
+#define BP_GPMI_CTRL1_RDN_DELAY				12
+#define BM_GPMI_CTRL1_RDN_DELAY		(0xf << BP_GPMI_CTRL1_RDN_DELAY)
+#define BF_GPMI_CTRL1_RDN_DELAY(v)	\
+		(((v) << BP_GPMI_CTRL1_RDN_DELAY) & BM_GPMI_CTRL1_RDN_DELAY)
+
+#define BM_GPMI_CTRL1_DEV_RESET				(1 << 3)
+#define BV_GPMI_CTRL1_DEV_RESET__ENABLED		0x0
+#define BV_GPMI_CTRL1_DEV_RESET__DISABLED		0x1
+
+#define BM_GPMI_CTRL1_ATA_IRQRDY_POLARITY		(1 << 2)
+#define BV_GPMI_CTRL1_ATA_IRQRDY_POLARITY__ACTIVELOW	0x0
+#define BV_GPMI_CTRL1_ATA_IRQRDY_POLARITY__ACTIVEHIGH	0x1
+
+#define BM_GPMI_CTRL1_CAMERA_MODE			(1 << 1)
+#define BV_GPMI_CTRL1_GPMI_MODE__NAND			0x0
+#define BV_GPMI_CTRL1_GPMI_MODE__ATA			0x1
+
+#define BM_GPMI_CTRL1_GPMI_MODE				(1 << 0)
+
+#define HW_GPMI_TIMING0					0x00000070
+
+#define BP_GPMI_TIMING0_ADDRESS_SETUP			16
+#define BM_GPMI_TIMING0_ADDRESS_SETUP	(0xff << BP_GPMI_TIMING0_ADDRESS_SETUP)
+#define BF_GPMI_TIMING0_ADDRESS_SETUP(v)	\
+	(((v) << BP_GPMI_TIMING0_ADDRESS_SETUP) & BM_GPMI_TIMING0_ADDRESS_SETUP)
+
+#define BP_GPMI_TIMING0_DATA_HOLD			8
+#define BM_GPMI_TIMING0_DATA_HOLD	(0xff << BP_GPMI_TIMING0_DATA_HOLD)
+#define BF_GPMI_TIMING0_DATA_HOLD(v)		\
+	(((v) << BP_GPMI_TIMING0_DATA_HOLD) & BM_GPMI_TIMING0_DATA_HOLD)
+
+#define BP_GPMI_TIMING0_DATA_SETUP			0
+#define BM_GPMI_TIMING0_DATA_SETUP	(0xff << BP_GPMI_TIMING0_DATA_SETUP)
+#define BF_GPMI_TIMING0_DATA_SETUP(v)		\
+	(((v) << BP_GPMI_TIMING0_DATA_SETUP) & BM_GPMI_TIMING0_DATA_SETUP)
+
+#define HW_GPMI_TIMING1					0x00000080
+#define BP_GPMI_TIMING1_BUSY_TIMEOUT			16
+
+#define HW_GPMI_TIMING2					0x00000090
+#define HW_GPMI_DATA					0x000000a0
+
+/* MX28 uses this to detect READY. */
+#define HW_GPMI_STAT					0x000000b0
+#define MX28_BP_GPMI_STAT_READY_BUSY			24
+#define MX28_BM_GPMI_STAT_READY_BUSY	(0xff << MX28_BP_GPMI_STAT_READY_BUSY)
+#define MX28_BF_GPMI_STAT_READY_BUSY(v)		\
+	(((v) << MX28_BP_GPMI_STAT_READY_BUSY) & MX28_BM_GPMI_STAT_READY_BUSY)
+
+/* MX23 uses this to detect READY. */
+#define HW_GPMI_DEBUG					0x000000c0
+#define MX23_BP_GPMI_DEBUG_READY0			28
+#define MX23_BM_GPMI_DEBUG_READY0	(1 << MX23_BP_GPMI_DEBUG_READY0)
+#endif
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/gpmi-nand/Makefile linux-libre-3.2-gnu/drivers/mtd/nand/gpmi-nand/Makefile
--- linux-libre-3.1-gnu/drivers/mtd/nand/gpmi-nand/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/mtd/nand/gpmi-nand/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,3 @@
+obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi_nand.o
+gpmi_nand-objs += gpmi-nand.o
+gpmi_nand-objs += gpmi-lib.o
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/h1910.c linux-libre-3.2-gnu/drivers/mtd/nand/h1910.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/h1910.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/h1910.c	2012-01-04 18:55:44.000000000 -0500
@@ -81,9 +81,6 @@
 static int __init h1910_init(void)
 {
 	struct nand_chip *this;
-	const char *part_type = 0;
-	int mtd_parts_nb = 0;
-	struct mtd_partition *mtd_parts = 0;
 	void __iomem *nandaddr;
 
 	if (!machine_is_h1900())
@@ -136,22 +133,10 @@
 		iounmap((void *)nandaddr);
 		return -ENXIO;
 	}
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-	mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, "h1910-nand");
-	if (mtd_parts_nb > 0)
-		part_type = "command line";
-	else
-		mtd_parts_nb = 0;
-#endif
-	if (mtd_parts_nb == 0) {
-		mtd_parts = partition_info;
-		mtd_parts_nb = NUM_PARTITIONS;
-		part_type = "static";
-	}
 
 	/* Register the partitions */
-	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-	mtd_device_register(h1910_nand_mtd, mtd_parts, mtd_parts_nb);
+	mtd_device_parse_register(h1910_nand_mtd, NULL, 0,
+			partition_info, NUM_PARTITIONS);
 
 	/* Return happy */
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/jz4740_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/jz4740_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/jz4740_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/jz4740_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -251,10 +251,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-static const char *part_probes[] = {"cmdline", NULL};
-#endif
-
 static int jz_nand_ioremap_resource(struct platform_device *pdev,
 	const char *name, struct resource **res, void __iomem **base)
 {
@@ -299,8 +295,6 @@
 	struct nand_chip *chip;
 	struct mtd_info *mtd;
 	struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
-	struct mtd_partition *partition_info;
-	int num_partitions = 0;
 
 	nand = kzalloc(sizeof(*nand), GFP_KERNEL);
 	if (!nand) {
@@ -373,15 +367,9 @@
 		goto err_gpio_free;
 	}
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-	num_partitions = parse_mtd_partitions(mtd, part_probes,
-						&partition_info, 0);
-#endif
-	if (num_partitions <= 0 && pdata) {
-		num_partitions = pdata->num_partitions;
-		partition_info = pdata->partitions;
-	}
-	ret = mtd_device_register(mtd, partition_info, num_partitions);
+	ret = mtd_device_parse_register(mtd, NULL, 0,
+			pdata ? pdata->partitions : NULL,
+			pdata ? pdata->num_partitions : 0);
 
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to add mtd device\n");
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/Kconfig linux-libre-3.2-gnu/drivers/mtd/nand/Kconfig
--- linux-libre-3.1-gnu/drivers/mtd/nand/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -83,16 +83,9 @@
           scratch register here to enable this feature. On Intel Moorestown
           boards, the scratch register is at 0xFF108018.
 
-config MTD_NAND_EDB7312
-	tristate "Support for Cirrus Logic EBD7312 evaluation board"
-	depends on ARCH_EDB7312
-	help
-	  This enables the driver for the Cirrus Logic EBD7312 evaluation
-	  board to access the onboard NAND Flash.
-
 config MTD_NAND_H1900
 	tristate "iPAQ H1900 flash"
-	depends on ARCH_PXA
+	depends on ARCH_PXA && BROKEN
 	help
 	  This enables the driver for the iPAQ h1900 flash.
 
@@ -116,10 +109,11 @@
 	  Support for NAND flash on Amstrad E3 (Delta).
 
 config MTD_NAND_OMAP2
-	tristate "NAND Flash device on OMAP2 and OMAP3"
-	depends on ARM && (ARCH_OMAP2 || ARCH_OMAP3)
+	tristate "NAND Flash device on OMAP2, OMAP3 and OMAP4"
+	depends on ARM && (ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP4)
 	help
-          Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms.
+          Support for NAND flash on Texas Instruments OMAP2, OMAP3 and OMAP4
+	  platforms.
 
 config MTD_NAND_IDS
 	tristate
@@ -138,7 +132,7 @@
 
 config MTD_NAND_AU1550
 	tristate "Au1550/1200 NAND support"
-	depends on SOC_AU1200 || SOC_AU1550
+	depends on MIPS_ALCHEMY
 	help
 	  This enables the driver for the NAND flash controller on the
 	  AMD/Alchemy 1550 SOC.
@@ -423,6 +417,19 @@
 	  The simulator may simulate various NAND flash chips for the
 	  MTD nand layer.
 
+config MTD_NAND_GPMI_NAND
+        bool "GPMI NAND Flash Controller driver"
+        depends on MTD_NAND && (SOC_IMX23 || SOC_IMX28)
+	select MTD_PARTITIONS
+	select MTD_CMDLINE_PARTS
+        help
+	 Enables NAND Flash support for IMX23 or IMX28.
+	 The GPMI controller is very powerful, with the help of BCH
+	 module, it can do the hardware ECC. The GPMI supports several
+	 NAND flashs at the same time. The GPMI may conflicts with other
+	 block, such as SD card. So pay attention to it when you enable
+	 the GPMI.
+
 config MTD_NAND_PLATFORM
 	tristate "Support for generic platform NAND driver"
 	help
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/Makefile linux-libre-3.2-gnu/drivers/mtd/nand/Makefile
--- linux-libre-3.1-gnu/drivers/mtd/nand/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -13,7 +13,6 @@
 obj-$(CONFIG_MTD_NAND_AMS_DELTA)	+= ams-delta.o
 obj-$(CONFIG_MTD_NAND_AUTCPU12)		+= autcpu12.o
 obj-$(CONFIG_MTD_NAND_DENALI)		+= denali.o
-obj-$(CONFIG_MTD_NAND_EDB7312)		+= edb7312.o
 obj-$(CONFIG_MTD_NAND_AU1550)		+= au1550nd.o
 obj-$(CONFIG_MTD_NAND_BF5XX)		+= bf5xx_nand.o
 obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB)	+= ppchameleonevb.o
@@ -49,5 +48,6 @@
 obj-$(CONFIG_MTD_NAND_MPC5121_NFC)	+= mpc5121_nfc.o
 obj-$(CONFIG_MTD_NAND_RICOH)		+= r852.o
 obj-$(CONFIG_MTD_NAND_JZ4740)		+= jz4740_nand.o
+obj-$(CONFIG_MTD_NAND_GPMI_NAND)	+= gpmi-nand/
 
 nand-objs := nand_base.o nand_bbt.o
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/mpc5121_nfc.c linux-libre-3.2-gnu/drivers/mtd/nand/mpc5121_nfc.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/mpc5121_nfc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/mpc5121_nfc.c	2012-01-04 18:55:44.000000000 -0500
@@ -131,8 +131,6 @@
 
 static void mpc5121_nfc_done(struct mtd_info *mtd);
 
-static const char *mpc5121_nfc_pprobes[] = { "cmdlinepart", NULL };
-
 /* Read NFC register */
 static inline u16 nfc_read(struct mtd_info *mtd, uint reg)
 {
@@ -656,13 +654,13 @@
 	struct mpc5121_nfc_prv *prv;
 	struct resource res;
 	struct mtd_info *mtd;
-	struct mtd_partition *parts;
 	struct nand_chip *chip;
 	unsigned long regs_paddr, regs_size;
 	const __be32 *chips_no;
 	int resettime = 0;
 	int retval = 0;
 	int rev, len;
+	struct mtd_part_parser_data ppdata;
 
 	/*
 	 * Check SoC revision. This driver supports only NFC
@@ -727,6 +725,7 @@
 	}
 
 	mtd->name = "MPC5121 NAND";
+	ppdata.of_node = dn;
 	chip->dev_ready = mpc5121_nfc_dev_ready;
 	chip->cmdfunc = mpc5121_nfc_command;
 	chip->read_byte = mpc5121_nfc_read_byte;
@@ -735,7 +734,8 @@
 	chip->write_buf = mpc5121_nfc_write_buf;
 	chip->verify_buf = mpc5121_nfc_verify_buf;
 	chip->select_chip = mpc5121_nfc_select_chip;
-	chip->options = NAND_NO_AUTOINCR | NAND_USE_FLASH_BBT;
+	chip->options = NAND_NO_AUTOINCR;
+	chip->bbt_options = NAND_BBT_USE_FLASH;
 	chip->ecc.mode = NAND_ECC_SOFT;
 
 	/* Support external chip-select logic on ADS5121 board */
@@ -837,19 +837,7 @@
 	dev_set_drvdata(dev, mtd);
 
 	/* Register device in MTD */
-	retval = parse_mtd_partitions(mtd, mpc5121_nfc_pprobes, &parts, 0);
-#ifdef CONFIG_MTD_OF_PARTS
-	if (retval == 0)
-		retval = of_mtd_parse_partitions(dev, dn, &parts);
-#endif
-	if (retval < 0) {
-		dev_err(dev, "Error parsing MTD partitions!\n");
-		devm_free_irq(dev, prv->irq, mtd);
-		retval = -EINVAL;
-		goto error;
-	}
-
-	retval = mtd_device_register(mtd, parts, retval);
+	retval = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
 	if (retval) {
 		dev_err(dev, "Error adding MTD device!\n");
 		devm_free_irq(dev, prv->irq, mtd);
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/mxc_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/mxc_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/mxc_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/mxc_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -41,7 +41,7 @@
 
 #define nfc_is_v21()		(cpu_is_mx25() || cpu_is_mx35())
 #define nfc_is_v1()		(cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
-#define nfc_is_v3_2()		cpu_is_mx51()
+#define nfc_is_v3_2()		(cpu_is_mx51() || cpu_is_mx53())
 #define nfc_is_v3()		nfc_is_v3_2()
 
 /* Addresses for NFC registers */
@@ -143,7 +143,6 @@
 struct mxc_nand_host {
 	struct mtd_info		mtd;
 	struct nand_chip	nand;
-	struct mtd_partition	*parts;
 	struct device		*dev;
 
 	void			*spare0;
@@ -350,8 +349,7 @@
 			udelay(1);
 		}
 		if (max_retries < 0)
-			DEBUG(MTD_DEBUG_LEVEL0, "%s: INT not set\n",
-			      __func__);
+			pr_debug("%s: INT not set\n", __func__);
 	}
 }
 
@@ -371,7 +369,7 @@
  * waits for completion. */
 static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
 {
-	DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
+	pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq);
 
 	writew(cmd, NFC_V1_V2_FLASH_CMD);
 	writew(NFC_CMD, NFC_V1_V2_CONFIG2);
@@ -387,8 +385,7 @@
 			udelay(1);
 		}
 		if (max_retries < 0)
-			DEBUG(MTD_DEBUG_LEVEL0, "%s: RESET failed\n",
-			      __func__);
+			pr_debug("%s: RESET failed\n", __func__);
 	} else {
 		/* Wait for operation to complete */
 		wait_op_done(host, useirq);
@@ -411,7 +408,7 @@
  * a NAND command. */
 static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
 {
-	DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
+	pr_debug("send_addr(host, 0x%x %d)\n", addr, islast);
 
 	writew(addr, NFC_V1_V2_FLASH_ADDR);
 	writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
@@ -561,8 +558,7 @@
 	uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT);
 
 	if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
-		DEBUG(MTD_DEBUG_LEVEL0,
-		      "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
+		pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
 		return -1;
 	}
 
@@ -849,7 +845,7 @@
 		writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
 	} else if (nfc_is_v1()) {
 		writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
-		writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR);
+		writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
 	} else
 		BUG();
 
@@ -932,8 +928,7 @@
 	struct nand_chip *nand_chip = mtd->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
 
-	DEBUG(MTD_DEBUG_LEVEL3,
-	      "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
+	pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
 	      command, column, page_addr);
 
 	/* Reset command state information */
@@ -1044,7 +1039,7 @@
 	struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
 	struct mxc_nand_host *host;
 	struct resource *res;
-	int err = 0, __maybe_unused nr_parts = 0;
+	int err = 0;
 	struct nand_ecclayout *oob_smallpage, *oob_largepage;
 
 	/* Allocate memory for MTD device structure and private data */
@@ -1179,7 +1174,7 @@
 		this->bbt_td = &bbt_main_descr;
 		this->bbt_md = &bbt_mirror_descr;
 		/* update flash based bbt */
-		this->options |= NAND_USE_FLASH_BBT;
+		this->bbt_options |= NAND_BBT_USE_FLASH;
 	}
 
 	init_completion(&host->op_completion);
@@ -1231,16 +1226,8 @@
 	}
 
 	/* Register the partitions */
-	nr_parts =
-	    parse_mtd_partitions(mtd, part_probes, &host->parts, 0);
-	if (nr_parts > 0)
-		mtd_device_register(mtd, host->parts, nr_parts);
-	else if (pdata->parts)
-		mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
-	else {
-		pr_info("Registering %s as whole device\n", mtd->name);
-		mtd_device_register(mtd, NULL, 0);
-	}
+	mtd_device_parse_register(mtd, part_probes, 0,
+			pdata->parts, pdata->nr_parts);
 
 	platform_set_drvdata(pdev, host);
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/nand_base.c linux-libre-3.2-gnu/drivers/mtd/nand/nand_base.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/nand_base.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/nand_base.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,7 +21,7 @@
  *  TODO:
  *	Enable cached programming for 2k page size chips
  *	Check, if mtd->ecctype should be set to MTD_ECC_HW
- *	if we have HW ecc support.
+ *	if we have HW ECC support.
  *	The AG-AND chips have nice features for speed improvement,
  *	which are not supported yet. Read / program 4 pages in one go.
  *	BBT table is not serialized, has to be fixed
@@ -113,21 +113,19 @@
 
 	/* Start address must align on block boundary */
 	if (ofs & ((1 << chip->phys_erase_shift) - 1)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Unaligned address\n", __func__);
+		pr_debug("%s: unaligned address\n", __func__);
 		ret = -EINVAL;
 	}
 
 	/* Length must align on block boundary */
 	if (len & ((1 << chip->phys_erase_shift) - 1)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Length not block aligned\n",
-					__func__);
+		pr_debug("%s: length not block aligned\n", __func__);
 		ret = -EINVAL;
 	}
 
 	/* Do not allow past end of device */
 	if (ofs + len > mtd->size) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Past end of device\n",
-					__func__);
+		pr_debug("%s: past end of device\n", __func__);
 		ret = -EINVAL;
 	}
 
@@ -136,9 +134,9 @@
 
 /**
  * nand_release_device - [GENERIC] release chip
- * @mtd:	MTD device structure
+ * @mtd: MTD device structure
  *
- * Deselect, release chip lock and wake up anyone waiting on the device
+ * Deselect, release chip lock and wake up anyone waiting on the device.
  */
 static void nand_release_device(struct mtd_info *mtd)
 {
@@ -157,9 +155,9 @@
 
 /**
  * nand_read_byte - [DEFAULT] read one byte from the chip
- * @mtd:	MTD device structure
+ * @mtd: MTD device structure
  *
- * Default read function for 8bit buswith
+ * Default read function for 8bit buswidth
  */
 static uint8_t nand_read_byte(struct mtd_info *mtd)
 {
@@ -169,10 +167,11 @@
 
 /**
  * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
- * @mtd:	MTD device structure
+ * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip
+ * @mtd: MTD device structure
+ *
+ * Default read function for 16bit buswidth with endianness conversion.
  *
- * Default read function for 16bit buswith with
- * endianess conversion
  */
 static uint8_t nand_read_byte16(struct mtd_info *mtd)
 {
@@ -182,10 +181,9 @@
 
 /**
  * nand_read_word - [DEFAULT] read one word from the chip
- * @mtd:	MTD device structure
+ * @mtd: MTD device structure
  *
- * Default read function for 16bit buswith without
- * endianess conversion
+ * Default read function for 16bit buswidth without endianness conversion.
  */
 static u16 nand_read_word(struct mtd_info *mtd)
 {
@@ -195,8 +193,8 @@
 
 /**
  * nand_select_chip - [DEFAULT] control CE line
- * @mtd:	MTD device structure
- * @chipnr:	chipnumber to select, -1 for deselect
+ * @mtd: MTD device structure
+ * @chipnr: chipnumber to select, -1 for deselect
  *
  * Default select function for 1 chip devices.
  */
@@ -218,11 +216,11 @@
 
 /**
  * nand_write_buf - [DEFAULT] write buffer to chip
- * @mtd:	MTD device structure
- * @buf:	data buffer
- * @len:	number of bytes to write
+ * @mtd: MTD device structure
+ * @buf: data buffer
+ * @len: number of bytes to write
  *
- * Default write function for 8bit buswith
+ * Default write function for 8bit buswidth.
  */
 static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
@@ -235,11 +233,11 @@
 
 /**
  * nand_read_buf - [DEFAULT] read chip data into buffer
- * @mtd:	MTD device structure
- * @buf:	buffer to store date
- * @len:	number of bytes to read
+ * @mtd: MTD device structure
+ * @buf: buffer to store date
+ * @len: number of bytes to read
  *
- * Default read function for 8bit buswith
+ * Default read function for 8bit buswidth.
  */
 static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
@@ -252,11 +250,11 @@
 
 /**
  * nand_verify_buf - [DEFAULT] Verify chip data against buffer
- * @mtd:	MTD device structure
- * @buf:	buffer containing the data to compare
- * @len:	number of bytes to compare
+ * @mtd: MTD device structure
+ * @buf: buffer containing the data to compare
+ * @len: number of bytes to compare
  *
- * Default verify function for 8bit buswith
+ * Default verify function for 8bit buswidth.
  */
 static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
@@ -271,11 +269,11 @@
 
 /**
  * nand_write_buf16 - [DEFAULT] write buffer to chip
- * @mtd:	MTD device structure
- * @buf:	data buffer
- * @len:	number of bytes to write
+ * @mtd: MTD device structure
+ * @buf: data buffer
+ * @len: number of bytes to write
  *
- * Default write function for 16bit buswith
+ * Default write function for 16bit buswidth.
  */
 static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
@@ -291,11 +289,11 @@
 
 /**
  * nand_read_buf16 - [DEFAULT] read chip data into buffer
- * @mtd:	MTD device structure
- * @buf:	buffer to store date
- * @len:	number of bytes to read
+ * @mtd: MTD device structure
+ * @buf: buffer to store date
+ * @len: number of bytes to read
  *
- * Default read function for 16bit buswith
+ * Default read function for 16bit buswidth.
  */
 static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
 {
@@ -310,11 +308,11 @@
 
 /**
  * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer
- * @mtd:	MTD device structure
- * @buf:	buffer containing the data to compare
- * @len:	number of bytes to compare
+ * @mtd: MTD device structure
+ * @buf: buffer containing the data to compare
+ * @len: number of bytes to compare
  *
- * Default verify function for 16bit buswith
+ * Default verify function for 16bit buswidth.
  */
 static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
@@ -332,9 +330,9 @@
 
 /**
  * nand_block_bad - [DEFAULT] Read bad block marker from the chip
- * @mtd:	MTD device structure
- * @ofs:	offset from device start
- * @getchip:	0, if the chip is already selected
+ * @mtd: MTD device structure
+ * @ofs: offset from device start
+ * @getchip: 0, if the chip is already selected
  *
  * Check, if the block is bad.
  */
@@ -344,7 +342,7 @@
 	struct nand_chip *chip = mtd->priv;
 	u16 bad;
 
-	if (chip->options & NAND_BBT_SCANLASTPAGE)
+	if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
 		ofs += mtd->erasesize - mtd->writesize;
 
 	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
@@ -384,11 +382,11 @@
 
 /**
  * nand_default_block_markbad - [DEFAULT] mark a block bad
- * @mtd:	MTD device structure
- * @ofs:	offset from device start
+ * @mtd: MTD device structure
+ * @ofs: offset from device start
  *
- * This is the default implementation, which can be overridden by
- * a hardware specific driver.
+ * This is the default implementation, which can be overridden by a hardware
+ * specific driver.
 */
 static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
@@ -396,7 +394,7 @@
 	uint8_t buf[2] = { 0, 0 };
 	int block, ret, i = 0;
 
-	if (chip->options & NAND_BBT_SCANLASTPAGE)
+	if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
 		ofs += mtd->erasesize - mtd->writesize;
 
 	/* Get block number */
@@ -404,33 +402,31 @@
 	if (chip->bbt)
 		chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
 
-	/* Do we have a flash based bad block table ? */
-	if (chip->options & NAND_USE_FLASH_BBT)
+	/* Do we have a flash based bad block table? */
+	if (chip->bbt_options & NAND_BBT_USE_FLASH)
 		ret = nand_update_bbt(mtd, ofs);
 	else {
+		struct mtd_oob_ops ops;
+
 		nand_get_device(chip, mtd, FL_WRITING);
 
-		/* Write to first two pages and to byte 1 and 6 if necessary.
-		 * If we write to more than one location, the first error
-		 * encountered quits the procedure. We write two bytes per
-		 * location, so we dont have to mess with 16 bit access.
+		/*
+		 * Write to first two pages if necessary. If we write to more
+		 * than one location, the first error encountered quits the
+		 * procedure. We write two bytes per location, so we dont have
+		 * to mess with 16 bit access.
 		 */
+		ops.len = ops.ooblen = 2;
+		ops.datbuf = NULL;
+		ops.oobbuf = buf;
+		ops.ooboffs = chip->badblockpos & ~0x01;
+		ops.mode = MTD_OPS_PLACE_OOB;
 		do {
-			chip->ops.len = chip->ops.ooblen = 2;
-			chip->ops.datbuf = NULL;
-			chip->ops.oobbuf = buf;
-			chip->ops.ooboffs = chip->badblockpos & ~0x01;
-
-			ret = nand_do_write_oob(mtd, ofs, &chip->ops);
+			ret = nand_do_write_oob(mtd, ofs, &ops);
 
-			if (!ret && (chip->options & NAND_BBT_SCANBYTE1AND6)) {
-				chip->ops.ooboffs = NAND_SMALL_BADBLOCK_POS
-					& ~0x01;
-				ret = nand_do_write_oob(mtd, ofs, &chip->ops);
-			}
 			i++;
 			ofs += mtd->writesize;
-		} while (!ret && (chip->options & NAND_BBT_SCAN2NDPAGE) &&
+		} while (!ret && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE) &&
 				i < 2);
 
 		nand_release_device(mtd);
@@ -443,16 +439,16 @@
 
 /**
  * nand_check_wp - [GENERIC] check if the chip is write protected
- * @mtd:	MTD device structure
- * Check, if the device is write protected
+ * @mtd: MTD device structure
  *
- * The function expects, that the device is already selected
+ * Check, if the device is write protected. The function expects, that the
+ * device is already selected.
  */
 static int nand_check_wp(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
 
-	/* broken xD cards report WP despite being writable */
+	/* Broken xD cards report WP despite being writable */
 	if (chip->options & NAND_BROKEN_XD)
 		return 0;
 
@@ -463,10 +459,10 @@
 
 /**
  * nand_block_checkbad - [GENERIC] Check if a block is marked bad
- * @mtd:	MTD device structure
- * @ofs:	offset from device start
- * @getchip:	0, if the chip is already selected
- * @allowbbt:	1, if its allowed to access the bbt area
+ * @mtd: MTD device structure
+ * @ofs: offset from device start
+ * @getchip: 0, if the chip is already selected
+ * @allowbbt: 1, if its allowed to access the bbt area
  *
  * Check, if the block is bad. Either by reading the bad block table or
  * calling of the scan function.
@@ -485,8 +481,8 @@
 
 /**
  * panic_nand_wait_ready - [GENERIC] Wait for the ready pin after commands.
- * @mtd:	MTD device structure
- * @timeo:	Timeout
+ * @mtd: MTD device structure
+ * @timeo: Timeout
  *
  * Helper function for nand_wait_ready used when needing to wait in interrupt
  * context.
@@ -505,10 +501,7 @@
 	}
 }
 
-/*
- * Wait for the ready pin, after a command
- * The timeout is catched later.
- */
+/* Wait for the ready pin, after a command. The timeout is caught later. */
 void nand_wait_ready(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
@@ -519,7 +512,7 @@
 		return panic_nand_wait_ready(mtd, 400);
 
 	led_trigger_event(nand_led_trigger, LED_FULL);
-	/* wait until command is processed or timeout occures */
+	/* Wait until command is processed or timeout occurs */
 	do {
 		if (chip->dev_ready(mtd))
 			break;
@@ -531,13 +524,13 @@
 
 /**
  * nand_command - [DEFAULT] Send command to NAND device
- * @mtd:	MTD device structure
- * @command:	the command to be sent
- * @column:	the column address for this command, -1 if none
- * @page_addr:	the page address for this command, -1 if none
+ * @mtd: MTD device structure
+ * @command: the command to be sent
+ * @column: the column address for this command, -1 if none
+ * @page_addr: the page address for this command, -1 if none
  *
- * Send command to NAND device. This function is used for small page
- * devices (256/512 Bytes per page)
+ * Send command to NAND device. This function is used for small page devices
+ * (256/512 Bytes per page).
  */
 static void nand_command(struct mtd_info *mtd, unsigned int command,
 			 int column, int page_addr)
@@ -545,9 +538,7 @@
 	register struct nand_chip *chip = mtd->priv;
 	int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
 
-	/*
-	 * Write out the command to the device.
-	 */
+	/* Write out the command to the device */
 	if (command == NAND_CMD_SEQIN) {
 		int readcmd;
 
@@ -567,9 +558,7 @@
 	}
 	chip->cmd_ctrl(mtd, command, ctrl);
 
-	/*
-	 * Address cycle, when necessary
-	 */
+	/* Address cycle, when necessary */
 	ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
 	/* Serially input address */
 	if (column != -1) {
@@ -590,8 +579,8 @@
 	chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
 	/*
-	 * program and erase have their own busy handlers
-	 * status and sequential in needs no delay
+	 * Program and erase have their own busy handlers status and sequential
+	 * in needs no delay
 	 */
 	switch (command) {
 
@@ -625,8 +614,10 @@
 			return;
 		}
 	}
-	/* Apply this short delay always to ensure that we do wait tWB in
-	 * any case on any machine. */
+	/*
+	 * Apply this short delay always to ensure that we do wait tWB in
+	 * any case on any machine.
+	 */
 	ndelay(100);
 
 	nand_wait_ready(mtd);
@@ -634,14 +625,14 @@
 
 /**
  * nand_command_lp - [DEFAULT] Send command to NAND large page device
- * @mtd:	MTD device structure
- * @command:	the command to be sent
- * @column:	the column address for this command, -1 if none
- * @page_addr:	the page address for this command, -1 if none
+ * @mtd: MTD device structure
+ * @command: the command to be sent
+ * @column: the column address for this command, -1 if none
+ * @page_addr: the page address for this command, -1 if none
  *
  * Send command to NAND device. This is the version for the new large page
- * devices We dont have the separate regions as we have in the small page
- * devices.  We must emulate NAND_CMD_READOOB to keep the code compatible.
+ * devices. We don't have the separate regions as we have in the small page
+ * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
  */
 static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
 			    int column, int page_addr)
@@ -683,8 +674,8 @@
 	chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
 	/*
-	 * program and erase have their own busy handlers
-	 * status, sequential in, and deplete1 need no delay
+	 * Program and erase have their own busy handlers status, sequential
+	 * in, and deplete1 need no delay.
 	 */
 	switch (command) {
 
@@ -698,14 +689,12 @@
 	case NAND_CMD_DEPLETE1:
 		return;
 
-		/*
-		 * read error status commands require only a short delay
-		 */
 	case NAND_CMD_STATUS_ERROR:
 	case NAND_CMD_STATUS_ERROR0:
 	case NAND_CMD_STATUS_ERROR1:
 	case NAND_CMD_STATUS_ERROR2:
 	case NAND_CMD_STATUS_ERROR3:
+		/* Read error status commands require only a short delay */
 		udelay(chip->chip_delay);
 		return;
 
@@ -739,7 +728,7 @@
 	default:
 		/*
 		 * If we don't have access to the busy pin, we apply the given
-		 * command delay
+		 * command delay.
 		 */
 		if (!chip->dev_ready) {
 			udelay(chip->chip_delay);
@@ -747,8 +736,10 @@
 		}
 	}
 
-	/* Apply this short delay always to ensure that we do wait tWB in
-	 * any case on any machine. */
+	/*
+	 * Apply this short delay always to ensure that we do wait tWB in
+	 * any case on any machine.
+	 */
 	ndelay(100);
 
 	nand_wait_ready(mtd);
@@ -756,25 +747,25 @@
 
 /**
  * panic_nand_get_device - [GENERIC] Get chip for selected access
- * @chip:	the nand chip descriptor
- * @mtd:	MTD device structure
- * @new_state:	the state which is requested
+ * @chip: the nand chip descriptor
+ * @mtd: MTD device structure
+ * @new_state: the state which is requested
  *
  * Used when in panic, no locks are taken.
  */
 static void panic_nand_get_device(struct nand_chip *chip,
 		      struct mtd_info *mtd, int new_state)
 {
-	/* Hardware controller shared among independend devices */
+	/* Hardware controller shared among independent devices */
 	chip->controller->active = chip;
 	chip->state = new_state;
 }
 
 /**
  * nand_get_device - [GENERIC] Get chip for selected access
- * @chip:	the nand chip descriptor
- * @mtd:	MTD device structure
- * @new_state:	the state which is requested
+ * @chip: the nand chip descriptor
+ * @mtd: MTD device structure
+ * @new_state: the state which is requested
  *
  * Get the device and lock it for exclusive access
  */
@@ -812,10 +803,10 @@
 }
 
 /**
- * panic_nand_wait - [GENERIC]  wait until the command is done
- * @mtd:	MTD device structure
- * @chip:	NAND chip structure
- * @timeo:	Timeout
+ * panic_nand_wait - [GENERIC] wait until the command is done
+ * @mtd: MTD device structure
+ * @chip: NAND chip structure
+ * @timeo: timeout
  *
  * Wait for command done. This is a helper function for nand_wait used when
  * we are in interrupt context. May happen when in panic and trying to write
@@ -838,13 +829,13 @@
 }
 
 /**
- * nand_wait - [DEFAULT]  wait until the command is done
- * @mtd:	MTD device structure
- * @chip:	NAND chip structure
+ * nand_wait - [DEFAULT] wait until the command is done
+ * @mtd: MTD device structure
+ * @chip: NAND chip structure
  *
- * Wait for command done. This applies to erase and program only
- * Erase can take up to 400ms and program up to 20ms according to
- * general NAND and SmartMedia specs
+ * Wait for command done. This applies to erase and program only. Erase can
+ * take up to 400ms and program up to 20ms according to general NAND and
+ * SmartMedia specs.
  */
 static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
 {
@@ -859,8 +850,10 @@
 
 	led_trigger_event(nand_led_trigger, LED_FULL);
 
-	/* Apply this short delay always to ensure that we do wait tWB in
-	 * any case on any machine. */
+	/*
+	 * Apply this short delay always to ensure that we do wait tWB in any
+	 * case on any machine.
+	 */
 	ndelay(100);
 
 	if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
@@ -890,16 +883,15 @@
 
 /**
  * __nand_unlock - [REPLACEABLE] unlocks specified locked blocks
- *
  * @mtd: mtd info
  * @ofs: offset to start unlock from
  * @len: length to unlock
- * @invert:   when = 0, unlock the range of blocks within the lower and
- *                      upper boundary address
- *            when = 1, unlock the range of blocks outside the boundaries
- *                      of the lower and upper boundary address
+ * @invert: when = 0, unlock the range of blocks within the lower and
+ *                    upper boundary address
+ *          when = 1, unlock the range of blocks outside the boundaries
+ *                    of the lower and upper boundary address
  *
- * return - unlock status
+ * Returs unlock status.
  */
 static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
 					uint64_t len, int invert)
@@ -919,10 +911,9 @@
 
 	/* Call wait ready function */
 	status = chip->waitfunc(mtd, chip);
-	udelay(1000);
 	/* See if device thinks it succeeded */
 	if (status & 0x01) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Error status = 0x%08x\n",
+		pr_debug("%s: error status = 0x%08x\n",
 					__func__, status);
 		ret = -EIO;
 	}
@@ -932,12 +923,11 @@
 
 /**
  * nand_unlock - [REPLACEABLE] unlocks specified locked blocks
- *
  * @mtd: mtd info
  * @ofs: offset to start unlock from
  * @len: length to unlock
  *
- * return - unlock status
+ * Returns unlock status.
  */
 int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
@@ -945,7 +935,7 @@
 	int chipnr;
 	struct nand_chip *chip = mtd->priv;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n",
+	pr_debug("%s: start = 0x%012llx, len = %llu\n",
 			__func__, (unsigned long long)ofs, len);
 
 	if (check_offs_len(mtd, ofs, len))
@@ -964,7 +954,7 @@
 
 	/* Check, if it is write protected */
 	if (nand_check_wp(mtd)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n",
+		pr_debug("%s: device is write protected!\n",
 					__func__);
 		ret = -EIO;
 		goto out;
@@ -981,18 +971,16 @@
 
 /**
  * nand_lock - [REPLACEABLE] locks all blocks present in the device
- *
  * @mtd: mtd info
  * @ofs: offset to start unlock from
  * @len: length to unlock
  *
- * return - lock status
- *
- * This feature is not supported in many NAND parts. 'Micron' NAND parts
- * do have this feature, but it allows only to lock all blocks, not for
- * specified range for block.
+ * This feature is not supported in many NAND parts. 'Micron' NAND parts do
+ * have this feature, but it allows only to lock all blocks, not for specified
+ * range for block. Implementing 'lock' feature by making use of 'unlock', for
+ * now.
  *
- * Implementing 'lock' feature by making use of 'unlock', for now.
+ * Returns lock status.
  */
 int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
@@ -1000,7 +988,7 @@
 	int chipnr, status, page;
 	struct nand_chip *chip = mtd->priv;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n",
+	pr_debug("%s: start = 0x%012llx, len = %llu\n",
 			__func__, (unsigned long long)ofs, len);
 
 	if (check_offs_len(mtd, ofs, len))
@@ -1015,7 +1003,7 @@
 
 	/* Check, if it is write protected */
 	if (nand_check_wp(mtd)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n",
+		pr_debug("%s: device is write protected!\n",
 					__func__);
 		status = MTD_ERASE_FAILED;
 		ret = -EIO;
@@ -1028,10 +1016,9 @@
 
 	/* Call wait ready function */
 	status = chip->waitfunc(mtd, chip);
-	udelay(1000);
 	/* See if device thinks it succeeded */
 	if (status & 0x01) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Error status = 0x%08x\n",
+		pr_debug("%s: error status = 0x%08x\n",
 					__func__, status);
 		ret = -EIO;
 		goto out;
@@ -1047,13 +1034,13 @@
 EXPORT_SYMBOL(nand_lock);
 
 /**
- * nand_read_page_raw - [Intern] read raw page data without ecc
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @buf:	buffer to store read data
- * @page:	page number to read
+ * nand_read_page_raw - [INTERN] read raw page data without ecc
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ * @page: page number to read
  *
- * Not for syndrome calculating ecc controllers, which use a special oob layout
+ * Not for syndrome calculating ECC controllers, which use a special oob layout.
  */
 static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 			      uint8_t *buf, int page)
@@ -1064,11 +1051,11 @@
 }
 
 /**
- * nand_read_page_raw_syndrome - [Intern] read raw page data without ecc
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @buf:	buffer to store read data
- * @page:	page number to read
+ * nand_read_page_raw_syndrome - [INTERN] read raw page data without ecc
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ * @page: page number to read
  *
  * We need a special oob layout and handling even when OOB isn't used.
  */
@@ -1107,11 +1094,11 @@
 }
 
 /**
- * nand_read_page_swecc - [REPLACABLE] software ecc based page read function
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @buf:	buffer to store read data
- * @page:	page number to read
+ * nand_read_page_swecc - [REPLACEABLE] software ECC based page read function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ * @page: page number to read
  */
 static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
 				uint8_t *buf, int page)
@@ -1148,12 +1135,12 @@
 }
 
 /**
- * nand_read_subpage - [REPLACABLE] software ecc based sub-page read function
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @data_offs:	offset of requested data within the page
- * @readlen:	data length
- * @bufpoi:	buffer to store read data
+ * nand_read_subpage - [REPLACEABLE] software ECC based sub-page read function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @data_offs: offset of requested data within the page
+ * @readlen: data length
+ * @bufpoi: buffer to store read data
  */
 static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
 			uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi)
@@ -1166,12 +1153,12 @@
 	int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1;
 	int index = 0;
 
-	/* Column address wihin the page aligned to ECC size (256bytes). */
+	/* Column address within the page aligned to ECC size (256bytes) */
 	start_step = data_offs / chip->ecc.size;
 	end_step = (data_offs + readlen - 1) / chip->ecc.size;
 	num_steps = end_step - start_step + 1;
 
-	/* Data size aligned to ECC ecc.size*/
+	/* Data size aligned to ECC ecc.size */
 	datafrag_len = num_steps * chip->ecc.size;
 	eccfrag_len = num_steps * chip->ecc.bytes;
 
@@ -1183,13 +1170,14 @@
 	p = bufpoi + data_col_addr;
 	chip->read_buf(mtd, p, datafrag_len);
 
-	/* Calculate  ECC */
+	/* Calculate ECC */
 	for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size)
 		chip->ecc.calculate(mtd, p, &chip->buffers->ecccalc[i]);
 
-	/* The performance is faster if to position offsets
-	   according to ecc.pos. Let make sure here that
-	   there are no gaps in ecc positions */
+	/*
+	 * The performance is faster if we position offsets according to
+	 * ecc.pos. Let's make sure that there are no gaps in ECC positions.
+	 */
 	for (i = 0; i < eccfrag_len - 1; i++) {
 		if (eccpos[i + start_step * chip->ecc.bytes] + 1 !=
 			eccpos[i + start_step * chip->ecc.bytes + 1]) {
@@ -1201,8 +1189,10 @@
 		chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
 		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 	} else {
-		/* send the command to read the particular ecc bytes */
-		/* take care about buswidth alignment in read_buf */
+		/*
+		 * Send the command to read the particular ECC bytes take care
+		 * about buswidth alignment in read_buf.
+		 */
 		index = start_step * chip->ecc.bytes;
 
 		aligned_pos = eccpos[index] & ~(busw - 1);
@@ -1235,13 +1225,13 @@
 }
 
 /**
- * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @buf:	buffer to store read data
- * @page:	page number to read
+ * nand_read_page_hwecc - [REPLACEABLE] hardware ECC based page read function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ * @page: page number to read
  *
- * Not for syndrome calculating ecc controllers which need a special oob layout
+ * Not for syndrome calculating ECC controllers which need a special oob layout.
  */
 static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
 				uint8_t *buf, int page)
@@ -1280,18 +1270,17 @@
 }
 
 /**
- * nand_read_page_hwecc_oob_first - [REPLACABLE] hw ecc, read oob first
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @buf:	buffer to store read data
- * @page:	page number to read
+ * nand_read_page_hwecc_oob_first - [REPLACEABLE] hw ecc, read oob first
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ * @page: page number to read
  *
- * Hardware ECC for large page chips, require OOB to be read first.
- * For this ECC mode, the write_page method is re-used from ECC_HW.
- * These methods read/write ECC from the OOB area, unlike the
- * ECC_HW_SYNDROME support with multiple ECC steps, follows the
- * "infix ECC" scheme and reads/writes ECC from the data area, by
- * overwriting the NAND manufacturer bad block markings.
+ * Hardware ECC for large page chips, require OOB to be read first. For this
+ * ECC mode, the write_page method is re-used from ECC_HW. These methods
+ * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME support with
+ * multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from
+ * the data area, by overwriting the NAND manufacturer bad block markings.
  */
 static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
 	struct nand_chip *chip, uint8_t *buf, int page)
@@ -1329,14 +1318,14 @@
 }
 
 /**
- * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @buf:	buffer to store read data
- * @page:	page number to read
+ * nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ * @page: page number to read
  *
- * The hw generator calculates the error syndrome automatically. Therefor
- * we need a special oob layout and handling.
+ * The hw generator calculates the error syndrome automatically. Therefore we
+ * need a special oob layout and handling.
  */
 static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
 				   uint8_t *buf, int page)
@@ -1384,29 +1373,29 @@
 }
 
 /**
- * nand_transfer_oob - [Internal] Transfer oob to client buffer
- * @chip:	nand chip structure
- * @oob:	oob destination address
- * @ops:	oob ops structure
- * @len:	size of oob to transfer
+ * nand_transfer_oob - [INTERN] Transfer oob to client buffer
+ * @chip: nand chip structure
+ * @oob: oob destination address
+ * @ops: oob ops structure
+ * @len: size of oob to transfer
  */
 static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
 				  struct mtd_oob_ops *ops, size_t len)
 {
 	switch (ops->mode) {
 
-	case MTD_OOB_PLACE:
-	case MTD_OOB_RAW:
+	case MTD_OPS_PLACE_OOB:
+	case MTD_OPS_RAW:
 		memcpy(oob, chip->oob_poi + ops->ooboffs, len);
 		return oob + len;
 
-	case MTD_OOB_AUTO: {
+	case MTD_OPS_AUTO_OOB: {
 		struct nand_oobfree *free = chip->ecc.layout->oobfree;
 		uint32_t boffs = 0, roffs = ops->ooboffs;
 		size_t bytes = 0;
 
 		for (; free->length && len; free++, len -= bytes) {
-			/* Read request not from offset 0 ? */
+			/* Read request not from offset 0? */
 			if (unlikely(roffs)) {
 				if (roffs >= free->length) {
 					roffs -= free->length;
@@ -1432,11 +1421,10 @@
 }
 
 /**
- * nand_do_read_ops - [Internal] Read data with ECC
- *
- * @mtd:	MTD device structure
- * @from:	offset to read from
- * @ops:	oob ops structure
+ * nand_do_read_ops - [INTERN] Read data with ECC
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @ops: oob ops structure
  *
  * Internal function. Called with chip held.
  */
@@ -1451,7 +1439,7 @@
 	int ret = 0;
 	uint32_t readlen = ops->len;
 	uint32_t oobreadlen = ops->ooblen;
-	uint32_t max_oobsize = ops->mode == MTD_OOB_AUTO ?
+	uint32_t max_oobsize = ops->mode == MTD_OPS_AUTO_OOB ?
 		mtd->oobavail : mtd->oobsize;
 
 	uint8_t *bufpoi, *oob, *buf;
@@ -1473,7 +1461,7 @@
 		bytes = min(mtd->writesize - col, readlen);
 		aligned = (bytes == mtd->writesize);
 
-		/* Is the current page in the buffer ? */
+		/* Is the current page in the buffer? */
 		if (realpage != chip->pagebuf || oob) {
 			bufpoi = aligned ? buf : chip->buffers->databuf;
 
@@ -1483,7 +1471,7 @@
 			}
 
 			/* Now read the page into the buffer */
-			if (unlikely(ops->mode == MTD_OOB_RAW))
+			if (unlikely(ops->mode == MTD_OPS_RAW))
 				ret = chip->ecc.read_page_raw(mtd, chip,
 							      bufpoi, page);
 			else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
@@ -1492,14 +1480,22 @@
 			else
 				ret = chip->ecc.read_page(mtd, chip, bufpoi,
 							  page);
-			if (ret < 0)
+			if (ret < 0) {
+				if (!aligned)
+					/* Invalidate page cache */
+					chip->pagebuf = -1;
 				break;
+			}
 
 			/* Transfer not aligned data */
 			if (!aligned) {
 				if (!NAND_SUBPAGE_READ(chip) && !oob &&
-				    !(mtd->ecc_stats.failed - stats.failed))
+				    !(mtd->ecc_stats.failed - stats.failed) &&
+				    (ops->mode != MTD_OPS_RAW))
 					chip->pagebuf = realpage;
+				else
+					/* Invalidate page cache */
+					chip->pagebuf = -1;
 				memcpy(buf, chip->buffers->databuf + col, bytes);
 			}
 
@@ -1539,7 +1535,7 @@
 		if (!readlen)
 			break;
 
-		/* For subsequent reads align to page boundary. */
+		/* For subsequent reads align to page boundary */
 		col = 0;
 		/* Increment page address */
 		realpage++;
@@ -1552,8 +1548,9 @@
 			chip->select_chip(mtd, chipnr);
 		}
 
-		/* Check, if the chip supports auto page increment
-		 * or if we have hit a block boundary.
+		/*
+		 * Check, if the chip supports auto page increment or if we
+		 * have hit a block boundary.
 		 */
 		if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
 			sndcmd = 1;
@@ -1574,18 +1571,19 @@
 
 /**
  * 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
- * @retlen:	pointer to variable to store the number of read bytes
- * @buf:	the databuffer to put data
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @len: number of bytes to read
+ * @retlen: pointer to variable to store the number of read bytes
+ * @buf: the databuffer to put data
  *
- * Get hold of the chip and call nand_do_read
+ * Get hold of the chip and call nand_do_read.
  */
 static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
 		     size_t *retlen, uint8_t *buf)
 {
 	struct nand_chip *chip = mtd->priv;
+	struct mtd_oob_ops ops;
 	int ret;
 
 	/* Do not allow reads past end of device */
@@ -1596,13 +1594,14 @@
 
 	nand_get_device(chip, mtd, FL_READING);
 
-	chip->ops.len = len;
-	chip->ops.datbuf = buf;
-	chip->ops.oobbuf = NULL;
+	ops.len = len;
+	ops.datbuf = buf;
+	ops.oobbuf = NULL;
+	ops.mode = 0;
 
-	ret = nand_do_read_ops(mtd, from, &chip->ops);
+	ret = nand_do_read_ops(mtd, from, &ops);
 
-	*retlen = chip->ops.retlen;
+	*retlen = ops.retlen;
 
 	nand_release_device(mtd);
 
@@ -1610,11 +1609,11 @@
 }
 
 /**
- * nand_read_oob_std - [REPLACABLE] the most common OOB data read function
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @page:	page number to read
- * @sndcmd:	flag whether to issue read command or not
+ * nand_read_oob_std - [REPLACEABLE] the most common OOB data read function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @page: page number to read
+ * @sndcmd: flag whether to issue read command or not
  */
 static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
 			     int page, int sndcmd)
@@ -1628,12 +1627,12 @@
 }
 
 /**
- * nand_read_oob_syndrome - [REPLACABLE] OOB data read function for HW ECC
+ * nand_read_oob_syndrome - [REPLACEABLE] OOB data read function for HW ECC
  *			    with syndromes
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @page:	page number to read
- * @sndcmd:	flag whether to issue read command or not
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @page: page number to read
+ * @sndcmd: flag whether to issue read command or not
  */
 static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
 				  int page, int sndcmd)
@@ -1667,10 +1666,10 @@
 }
 
 /**
- * nand_write_oob_std - [REPLACABLE] the most common OOB data write function
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @page:	page number to write
+ * nand_write_oob_std - [REPLACEABLE] the most common OOB data write function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @page: page number to write
  */
 static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
 			      int page)
@@ -1690,11 +1689,11 @@
 }
 
 /**
- * nand_write_oob_syndrome - [REPLACABLE] OOB data write function for HW ECC
- *			     with syndrome - only for large page flash !
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @page:	page number to write
+ * nand_write_oob_syndrome - [REPLACEABLE] OOB data write function for HW ECC
+ *			     with syndrome - only for large page flash
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @page: page number to write
  */
 static int nand_write_oob_syndrome(struct mtd_info *mtd,
 				   struct nand_chip *chip, int page)
@@ -1749,34 +1748,37 @@
 }
 
 /**
- * nand_do_read_oob - [Intern] NAND read out-of-band
- * @mtd:	MTD device structure
- * @from:	offset to read from
- * @ops:	oob operations description structure
+ * nand_do_read_oob - [INTERN] NAND read out-of-band
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @ops: oob operations description structure
  *
- * NAND read out-of-band data from the spare area
+ * NAND read out-of-band data from the spare area.
  */
 static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
 			    struct mtd_oob_ops *ops)
 {
 	int page, realpage, chipnr, sndcmd = 1;
 	struct nand_chip *chip = mtd->priv;
+	struct mtd_ecc_stats stats;
 	int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
 	int readlen = ops->ooblen;
 	int len;
 	uint8_t *buf = ops->oobbuf;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08Lx, len = %i\n",
+	pr_debug("%s: from = 0x%08Lx, len = %i\n",
 			__func__, (unsigned long long)from, readlen);
 
-	if (ops->mode == MTD_OOB_AUTO)
+	stats = mtd->ecc_stats;
+
+	if (ops->mode == MTD_OPS_AUTO_OOB)
 		len = chip->ecc.layout->oobavail;
 	else
 		len = mtd->oobsize;
 
 	if (unlikely(ops->ooboffs >= len)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to start read "
-					"outside oob\n", __func__);
+		pr_debug("%s: attempt to start read outside oob\n",
+				__func__);
 		return -EINVAL;
 	}
 
@@ -1784,8 +1786,8 @@
 	if (unlikely(from >= mtd->size ||
 		     ops->ooboffs + readlen > ((mtd->size >> chip->page_shift) -
 					(from >> chip->page_shift)) * len)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt read beyond end "
-					"of device\n", __func__);
+		pr_debug("%s: attempt to read beyond end of device\n",
+				__func__);
 		return -EINVAL;
 	}
 
@@ -1797,7 +1799,10 @@
 	page = realpage & chip->pagemask;
 
 	while (1) {
-		sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
+		if (ops->mode == MTD_OPS_RAW)
+			sndcmd = chip->ecc.read_oob_raw(mtd, chip, page, sndcmd);
+		else
+			sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
 
 		len = min(len, readlen);
 		buf = nand_transfer_oob(chip, buf, ops, len);
@@ -1830,24 +1835,29 @@
 			chip->select_chip(mtd, chipnr);
 		}
 
-		/* Check, if the chip supports auto page increment
-		 * or if we have hit a block boundary.
+		/*
+		 * Check, if the chip supports auto page increment or if we
+		 * have hit a block boundary.
 		 */
 		if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
 			sndcmd = 1;
 	}
 
 	ops->oobretlen = ops->ooblen;
-	return 0;
+
+	if (mtd->ecc_stats.failed - stats.failed)
+		return -EBADMSG;
+
+	return  mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
 }
 
 /**
  * nand_read_oob - [MTD Interface] NAND read data and/or out-of-band
- * @mtd:	MTD device structure
- * @from:	offset to read from
- * @ops:	oob operation description structure
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @ops: oob operation description structure
  *
- * NAND read data and/or out-of-band data
+ * NAND read data and/or out-of-band data.
  */
 static int nand_read_oob(struct mtd_info *mtd, loff_t from,
 			 struct mtd_oob_ops *ops)
@@ -1859,17 +1869,17 @@
 
 	/* Do not allow reads past end of device */
 	if (ops->datbuf && (from + ops->len) > mtd->size) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt read "
-				"beyond end of device\n", __func__);
+		pr_debug("%s: attempt to read beyond end of device\n",
+				__func__);
 		return -EINVAL;
 	}
 
 	nand_get_device(chip, mtd, FL_READING);
 
 	switch (ops->mode) {
-	case MTD_OOB_PLACE:
-	case MTD_OOB_AUTO:
-	case MTD_OOB_RAW:
+	case MTD_OPS_PLACE_OOB:
+	case MTD_OPS_AUTO_OOB:
+	case MTD_OPS_RAW:
 		break;
 
 	default:
@@ -1888,12 +1898,12 @@
 
 
 /**
- * nand_write_page_raw - [Intern] raw page write function
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @buf:	data buffer
+ * nand_write_page_raw - [INTERN] raw page write function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: data buffer
  *
- * Not for syndrome calculating ecc controllers, which use a special oob layout
+ * Not for syndrome calculating ECC controllers, which use a special oob layout.
  */
 static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 				const uint8_t *buf)
@@ -1903,10 +1913,10 @@
 }
 
 /**
- * nand_write_page_raw_syndrome - [Intern] raw page write function
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @buf:	data buffer
+ * nand_write_page_raw_syndrome - [INTERN] raw page write function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: data buffer
  *
  * We need a special oob layout and handling even when ECC isn't checked.
  */
@@ -1942,10 +1952,10 @@
 		chip->write_buf(mtd, oob, size);
 }
 /**
- * nand_write_page_swecc - [REPLACABLE] software ecc based page write function
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @buf:	data buffer
+ * nand_write_page_swecc - [REPLACEABLE] software ECC based page write function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: data buffer
  */
 static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
 				  const uint8_t *buf)
@@ -1957,7 +1967,7 @@
 	const uint8_t *p = buf;
 	uint32_t *eccpos = chip->ecc.layout->eccpos;
 
-	/* Software ecc calculation */
+	/* Software ECC calculation */
 	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
 		chip->ecc.calculate(mtd, p, &ecc_calc[i]);
 
@@ -1968,10 +1978,10 @@
 }
 
 /**
- * nand_write_page_hwecc - [REPLACABLE] hardware ecc based page write function
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @buf:	data buffer
+ * nand_write_page_hwecc - [REPLACEABLE] hardware ECC based page write function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: data buffer
  */
 static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
 				  const uint8_t *buf)
@@ -1996,13 +2006,13 @@
 }
 
 /**
- * nand_write_page_syndrome - [REPLACABLE] hardware ecc syndrom based page write
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @buf:	data buffer
+ * nand_write_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page write
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: data buffer
  *
- * The hw generator calculates the error syndrome automatically. Therefor
- * we need a special oob layout and handling.
+ * The hw generator calculates the error syndrome automatically. Therefore we
+ * need a special oob layout and handling.
  */
 static void nand_write_page_syndrome(struct mtd_info *mtd,
 				    struct nand_chip *chip, const uint8_t *buf)
@@ -2041,12 +2051,12 @@
 
 /**
  * nand_write_page - [REPLACEABLE] write one page
- * @mtd:	MTD device structure
- * @chip:	NAND chip descriptor
- * @buf:	the data to write
- * @page:	page number to write
- * @cached:	cached programming
- * @raw:	use _raw version of write_page
+ * @mtd: MTD device structure
+ * @chip: NAND chip descriptor
+ * @buf: the data to write
+ * @page: page number to write
+ * @cached: cached programming
+ * @raw: use _raw version of write_page
  */
 static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 			   const uint8_t *buf, int page, int cached, int raw)
@@ -2061,8 +2071,8 @@
 		chip->ecc.write_page(mtd, chip, buf);
 
 	/*
-	 * Cached progamming disabled for now, Not sure if its worth the
-	 * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s)
+	 * Cached progamming disabled for now. Not sure if it's worth the
+	 * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s).
 	 */
 	cached = 0;
 
@@ -2072,7 +2082,7 @@
 		status = chip->waitfunc(mtd, chip);
 		/*
 		 * See if operation failed and additional status checks are
-		 * available
+		 * available.
 		 */
 		if ((status & NAND_STATUS_FAIL) && (chip->errstat))
 			status = chip->errstat(mtd, chip, FL_WRITING, status,
@@ -2096,29 +2106,37 @@
 }
 
 /**
- * nand_fill_oob - [Internal] Transfer client buffer to oob
- * @chip:	nand chip structure
- * @oob:	oob data buffer
- * @len:	oob data write length
- * @ops:	oob ops structure
+ * nand_fill_oob - [INTERN] Transfer client buffer to oob
+ * @mtd: MTD device structure
+ * @oob: oob data buffer
+ * @len: oob data write length
+ * @ops: oob ops structure
  */
-static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,
-						struct mtd_oob_ops *ops)
+static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
+			      struct mtd_oob_ops *ops)
 {
+	struct nand_chip *chip = mtd->priv;
+
+	/*
+	 * Initialise to all 0xFF, to avoid the possibility of left over OOB
+	 * data from a previous OOB read.
+	 */
+	memset(chip->oob_poi, 0xff, mtd->oobsize);
+
 	switch (ops->mode) {
 
-	case MTD_OOB_PLACE:
-	case MTD_OOB_RAW:
+	case MTD_OPS_PLACE_OOB:
+	case MTD_OPS_RAW:
 		memcpy(chip->oob_poi + ops->ooboffs, oob, len);
 		return oob + len;
 
-	case MTD_OOB_AUTO: {
+	case MTD_OPS_AUTO_OOB: {
 		struct nand_oobfree *free = chip->ecc.layout->oobfree;
 		uint32_t boffs = 0, woffs = ops->ooboffs;
 		size_t bytes = 0;
 
 		for (; free->length && len; free++, len -= bytes) {
-			/* Write request not from offset 0 ? */
+			/* Write request not from offset 0? */
 			if (unlikely(woffs)) {
 				if (woffs >= free->length) {
 					woffs -= free->length;
@@ -2146,12 +2164,12 @@
 #define NOTALIGNED(x)	((x & (chip->subpagesize - 1)) != 0)
 
 /**
- * nand_do_write_ops - [Internal] NAND write with ECC
- * @mtd:	MTD device structure
- * @to:		offset to write to
- * @ops:	oob operations description structure
+ * nand_do_write_ops - [INTERN] NAND write with ECC
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @ops: oob operations description structure
  *
- * NAND write with ECC
+ * NAND write with ECC.
  */
 static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
 			     struct mtd_oob_ops *ops)
@@ -2161,7 +2179,7 @@
 	uint32_t writelen = ops->len;
 
 	uint32_t oobwritelen = ops->ooblen;
-	uint32_t oobmaxlen = ops->mode == MTD_OOB_AUTO ?
+	uint32_t oobmaxlen = ops->mode == MTD_OPS_AUTO_OOB ?
 				mtd->oobavail : mtd->oobsize;
 
 	uint8_t *oob = ops->oobbuf;
@@ -2172,10 +2190,10 @@
 	if (!writelen)
 		return 0;
 
-	/* reject writes, which are not page aligned */
+	/* Reject writes, which are not page aligned */
 	if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
-		printk(KERN_NOTICE "%s: Attempt to write not "
-				"page aligned data\n", __func__);
+		pr_notice("%s: attempt to write non page aligned data\n",
+			   __func__);
 		return -EINVAL;
 	}
 
@@ -2201,10 +2219,6 @@
 	    (chip->pagebuf << chip->page_shift) < (to + ops->len))
 		chip->pagebuf = -1;
 
-	/* If we're not given explicit OOB data, let it be 0xFF */
-	if (likely(!oob))
-		memset(chip->oob_poi, 0xff, mtd->oobsize);
-
 	/* Don't allow multipage oob writes with offset */
 	if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen))
 		return -EINVAL;
@@ -2214,7 +2228,7 @@
 		int cached = writelen > bytes && page != blockmask;
 		uint8_t *wbuf = buf;
 
-		/* Partial page write ? */
+		/* Partial page write? */
 		if (unlikely(column || writelen < (mtd->writesize - 1))) {
 			cached = 0;
 			bytes = min_t(int, bytes - column, (int) writelen);
@@ -2226,12 +2240,15 @@
 
 		if (unlikely(oob)) {
 			size_t len = min(oobwritelen, oobmaxlen);
-			oob = nand_fill_oob(chip, oob, len, ops);
+			oob = nand_fill_oob(mtd, oob, len, ops);
 			oobwritelen -= len;
+		} else {
+			/* We still need to erase leftover OOB data */
+			memset(chip->oob_poi, 0xff, mtd->oobsize);
 		}
 
 		ret = chip->write_page(mtd, chip, wbuf, page, cached,
-				       (ops->mode == MTD_OOB_RAW));
+				       (ops->mode == MTD_OPS_RAW));
 		if (ret)
 			break;
 
@@ -2260,11 +2277,11 @@
 
 /**
  * panic_nand_write - [MTD Interface] NAND write with ECC
- * @mtd:	MTD device structure
- * @to:		offset to write to
- * @len:	number of bytes to write
- * @retlen:	pointer to variable to store the number of written bytes
- * @buf:	the data to write
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @len: number of bytes to write
+ * @retlen: pointer to variable to store the number of written bytes
+ * @buf: the data to write
  *
  * NAND write with ECC. Used when performing writes in interrupt context, this
  * may for example be called by mtdoops when writing an oops while in panic.
@@ -2273,6 +2290,7 @@
 			    size_t *retlen, const uint8_t *buf)
 {
 	struct nand_chip *chip = mtd->priv;
+	struct mtd_oob_ops ops;
 	int ret;
 
 	/* Do not allow reads past end of device */
@@ -2281,36 +2299,38 @@
 	if (!len)
 		return 0;
 
-	/* Wait for the device to get ready.  */
+	/* Wait for the device to get ready */
 	panic_nand_wait(mtd, chip, 400);
 
-	/* Grab the device.  */
+	/* Grab the device */
 	panic_nand_get_device(chip, mtd, FL_WRITING);
 
-	chip->ops.len = len;
-	chip->ops.datbuf = (uint8_t *)buf;
-	chip->ops.oobbuf = NULL;
+	ops.len = len;
+	ops.datbuf = (uint8_t *)buf;
+	ops.oobbuf = NULL;
+	ops.mode = 0;
 
-	ret = nand_do_write_ops(mtd, to, &chip->ops);
+	ret = nand_do_write_ops(mtd, to, &ops);
 
-	*retlen = chip->ops.retlen;
+	*retlen = ops.retlen;
 	return ret;
 }
 
 /**
  * nand_write - [MTD Interface] NAND write with ECC
- * @mtd:	MTD device structure
- * @to:		offset to write to
- * @len:	number of bytes to write
- * @retlen:	pointer to variable to store the number of written bytes
- * @buf:	the data to write
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @len: number of bytes to write
+ * @retlen: pointer to variable to store the number of written bytes
+ * @buf: the data to write
  *
- * NAND write with ECC
+ * NAND write with ECC.
  */
 static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
 			  size_t *retlen, const uint8_t *buf)
 {
 	struct nand_chip *chip = mtd->priv;
+	struct mtd_oob_ops ops;
 	int ret;
 
 	/* Do not allow reads past end of device */
@@ -2321,13 +2341,14 @@
 
 	nand_get_device(chip, mtd, FL_WRITING);
 
-	chip->ops.len = len;
-	chip->ops.datbuf = (uint8_t *)buf;
-	chip->ops.oobbuf = NULL;
+	ops.len = len;
+	ops.datbuf = (uint8_t *)buf;
+	ops.oobbuf = NULL;
+	ops.mode = 0;
 
-	ret = nand_do_write_ops(mtd, to, &chip->ops);
+	ret = nand_do_write_ops(mtd, to, &ops);
 
-	*retlen = chip->ops.retlen;
+	*retlen = ops.retlen;
 
 	nand_release_device(mtd);
 
@@ -2336,11 +2357,11 @@
 
 /**
  * nand_do_write_oob - [MTD Interface] NAND write out-of-band
- * @mtd:	MTD device structure
- * @to:		offset to write to
- * @ops:	oob operation description structure
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @ops: oob operation description structure
  *
- * NAND write out-of-band
+ * NAND write out-of-band.
  */
 static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 			     struct mtd_oob_ops *ops)
@@ -2348,24 +2369,24 @@
 	int chipnr, page, status, len;
 	struct nand_chip *chip = mtd->priv;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
+	pr_debug("%s: to = 0x%08x, len = %i\n",
 			 __func__, (unsigned int)to, (int)ops->ooblen);
 
-	if (ops->mode == MTD_OOB_AUTO)
+	if (ops->mode == MTD_OPS_AUTO_OOB)
 		len = chip->ecc.layout->oobavail;
 	else
 		len = mtd->oobsize;
 
 	/* Do not allow write past end of page */
 	if ((ops->ooboffs + ops->ooblen) > len) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to write "
-				"past end of page\n", __func__);
+		pr_debug("%s: attempt to write past end of page\n",
+				__func__);
 		return -EINVAL;
 	}
 
 	if (unlikely(ops->ooboffs >= len)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to start "
-				"write outside oob\n", __func__);
+		pr_debug("%s: attempt to start write outside oob\n",
+				__func__);
 		return -EINVAL;
 	}
 
@@ -2374,8 +2395,8 @@
 		     ops->ooboffs + ops->ooblen >
 			((mtd->size >> chip->page_shift) -
 			 (to >> chip->page_shift)) * len)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt write beyond "
-				"end of device\n", __func__);
+		pr_debug("%s: attempt to write beyond end of device\n",
+				__func__);
 		return -EINVAL;
 	}
 
@@ -2401,10 +2422,12 @@
 	if (page == chip->pagebuf)
 		chip->pagebuf = -1;
 
-	memset(chip->oob_poi, 0xff, mtd->oobsize);
-	nand_fill_oob(chip, ops->oobbuf, ops->ooblen, ops);
-	status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
-	memset(chip->oob_poi, 0xff, mtd->oobsize);
+	nand_fill_oob(mtd, ops->oobbuf, ops->ooblen, ops);
+
+	if (ops->mode == MTD_OPS_RAW)
+		status = chip->ecc.write_oob_raw(mtd, chip, page & chip->pagemask);
+	else
+		status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
 
 	if (status)
 		return status;
@@ -2416,9 +2439,9 @@
 
 /**
  * nand_write_oob - [MTD Interface] NAND write data and/or out-of-band
- * @mtd:	MTD device structure
- * @to:		offset to write to
- * @ops:	oob operation description structure
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @ops: oob operation description structure
  */
 static int nand_write_oob(struct mtd_info *mtd, loff_t to,
 			  struct mtd_oob_ops *ops)
@@ -2430,17 +2453,17 @@
 
 	/* Do not allow writes past end of device */
 	if (ops->datbuf && (to + ops->len) > mtd->size) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt write beyond "
-				"end of device\n", __func__);
+		pr_debug("%s: attempt to write beyond end of device\n",
+				__func__);
 		return -EINVAL;
 	}
 
 	nand_get_device(chip, mtd, FL_WRITING);
 
 	switch (ops->mode) {
-	case MTD_OOB_PLACE:
-	case MTD_OOB_AUTO:
-	case MTD_OOB_RAW:
+	case MTD_OPS_PLACE_OOB:
+	case MTD_OPS_AUTO_OOB:
+	case MTD_OPS_RAW:
 		break;
 
 	default:
@@ -2458,11 +2481,11 @@
 }
 
 /**
- * single_erease_cmd - [GENERIC] NAND standard block erase command function
- * @mtd:	MTD device structure
- * @page:	the page address of the block which will be erased
+ * single_erase_cmd - [GENERIC] NAND standard block erase command function
+ * @mtd: MTD device structure
+ * @page: the page address of the block which will be erased
  *
- * Standard erase command for NAND chips
+ * Standard erase command for NAND chips.
  */
 static void single_erase_cmd(struct mtd_info *mtd, int page)
 {
@@ -2473,12 +2496,11 @@
 }
 
 /**
- * multi_erease_cmd - [GENERIC] AND specific block erase command function
- * @mtd:	MTD device structure
- * @page:	the page address of the block which will be erased
+ * multi_erase_cmd - [GENERIC] AND specific block erase command function
+ * @mtd: MTD device structure
+ * @page: the page address of the block which will be erased
  *
- * AND multi block erase command function
- * Erase 4 consecutive blocks
+ * AND multi block erase command function. Erase 4 consecutive blocks.
  */
 static void multi_erase_cmd(struct mtd_info *mtd, int page)
 {
@@ -2493,10 +2515,10 @@
 
 /**
  * nand_erase - [MTD Interface] erase block(s)
- * @mtd:	MTD device structure
- * @instr:	erase instruction
+ * @mtd: MTD device structure
+ * @instr: erase instruction
  *
- * Erase one ore more blocks
+ * Erase one ore more blocks.
  */
 static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
@@ -2505,12 +2527,12 @@
 
 #define BBT_PAGE_MASK	0xffffff3f
 /**
- * nand_erase_nand - [Internal] erase block(s)
- * @mtd:	MTD device structure
- * @instr:	erase instruction
- * @allowbbt:	allow erasing the bbt area
+ * nand_erase_nand - [INTERN] erase block(s)
+ * @mtd: MTD device structure
+ * @instr: erase instruction
+ * @allowbbt: allow erasing the bbt area
  *
- * Erase one ore more blocks
+ * Erase one ore more blocks.
  */
 int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 		    int allowbbt)
@@ -2521,9 +2543,9 @@
 	unsigned int bbt_masked_page = 0xffffffff;
 	loff_t len;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n",
-				__func__, (unsigned long long)instr->addr,
-				(unsigned long long)instr->len);
+	pr_debug("%s: start = 0x%012llx, len = %llu\n",
+			__func__, (unsigned long long)instr->addr,
+			(unsigned long long)instr->len);
 
 	if (check_offs_len(mtd, instr->addr, instr->len))
 		return -EINVAL;
@@ -2545,8 +2567,8 @@
 
 	/* Check, if it is write protected */
 	if (nand_check_wp(mtd)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n",
-					__func__);
+		pr_debug("%s: device is write protected!\n",
+				__func__);
 		instr->state = MTD_ERASE_FAILED;
 		goto erase_exit;
 	}
@@ -2555,7 +2577,7 @@
 	 * If BBT requires refresh, set the BBT page mask to see if the BBT
 	 * should be rewritten. Otherwise the mask is set to 0xffffffff which
 	 * can not be matched. This is also done when the bbt is actually
-	 * erased to avoid recusrsive updates
+	 * erased to avoid recursive updates.
 	 */
 	if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
 		bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
@@ -2566,20 +2588,18 @@
 	instr->state = MTD_ERASING;
 
 	while (len) {
-		/*
-		 * heck if we have a bad block, we do not erase bad blocks !
-		 */
+		/* Heck if we have a bad block, we do not erase bad blocks! */
 		if (nand_block_checkbad(mtd, ((loff_t) page) <<
 					chip->page_shift, 0, allowbbt)) {
-			printk(KERN_WARNING "%s: attempt to erase a bad block "
-					"at page 0x%08x\n", __func__, page);
+			pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",
+				    __func__, page);
 			instr->state = MTD_ERASE_FAILED;
 			goto erase_exit;
 		}
 
 		/*
 		 * Invalidate the page cache, if we erase the block which
-		 * contains the current cached page
+		 * contains the current cached page.
 		 */
 		if (page <= chip->pagebuf && chip->pagebuf <
 		    (page + pages_per_block))
@@ -2599,8 +2619,8 @@
 
 		/* See if block erase succeeded */
 		if (status & NAND_STATUS_FAIL) {
-			DEBUG(MTD_DEBUG_LEVEL0, "%s: Failed erase, "
-					"page 0x%08x\n", __func__, page);
+			pr_debug("%s: failed erase, page 0x%08x\n",
+					__func__, page);
 			instr->state = MTD_ERASE_FAILED;
 			instr->fail_addr =
 				((loff_t)page << chip->page_shift);
@@ -2609,7 +2629,7 @@
 
 		/*
 		 * If BBT requires refresh, set the BBT rewrite flag to the
-		 * page being erased
+		 * page being erased.
 		 */
 		if (bbt_masked_page != 0xffffffff &&
 		    (page & BBT_PAGE_MASK) == bbt_masked_page)
@@ -2628,7 +2648,7 @@
 
 			/*
 			 * If BBT requires refresh and BBT-PERCHIP, set the BBT
-			 * page mask to see if this BBT should be rewritten
+			 * page mask to see if this BBT should be rewritten.
 			 */
 			if (bbt_masked_page != 0xffffffff &&
 			    (chip->bbt_td->options & NAND_BBT_PERCHIP))
@@ -2651,7 +2671,7 @@
 
 	/*
 	 * If BBT requires refresh and erase was successful, rewrite any
-	 * selected bad block tables
+	 * selected bad block tables.
 	 */
 	if (bbt_masked_page == 0xffffffff || ret)
 		return ret;
@@ -2659,10 +2679,10 @@
 	for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
 		if (!rewrite_bbt[chipnr])
 			continue;
-		/* update the BBT for chip */
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: nand_update_bbt "
-			"(%d:0x%0llx 0x%0x)\n", __func__, chipnr,
-			rewrite_bbt[chipnr], chip->bbt_td->pages[chipnr]);
+		/* Update the BBT for chip */
+		pr_debug("%s: nand_update_bbt (%d:0x%0llx 0x%0x)\n",
+				__func__, chipnr, rewrite_bbt[chipnr],
+				chip->bbt_td->pages[chipnr]);
 		nand_update_bbt(mtd, rewrite_bbt[chipnr]);
 	}
 
@@ -2672,15 +2692,15 @@
 
 /**
  * nand_sync - [MTD Interface] sync
- * @mtd:	MTD device structure
+ * @mtd: MTD device structure
  *
- * Sync is actually a wait for chip ready function
+ * Sync is actually a wait for chip ready function.
  */
 static void nand_sync(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: called\n", __func__);
+	pr_debug("%s: called\n", __func__);
 
 	/* Grab the lock and see if the device is available */
 	nand_get_device(chip, mtd, FL_SYNCING);
@@ -2690,8 +2710,8 @@
 
 /**
  * nand_block_isbad - [MTD Interface] Check if block at offset is bad
- * @mtd:	MTD device structure
- * @offs:	offset relative to mtd start
+ * @mtd: MTD device structure
+ * @offs: offset relative to mtd start
  */
 static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
 {
@@ -2704,8 +2724,8 @@
 
 /**
  * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad
- * @mtd:	MTD device structure
- * @ofs:	offset relative to mtd start
+ * @mtd: MTD device structure
+ * @ofs: offset relative to mtd start
  */
 static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
@@ -2714,7 +2734,7 @@
 
 	ret = nand_block_isbad(mtd, ofs);
 	if (ret) {
-		/* If it was bad already, return success and do nothing. */
+		/* If it was bad already, return success and do nothing */
 		if (ret > 0)
 			return 0;
 		return ret;
@@ -2725,7 +2745,7 @@
 
 /**
  * nand_suspend - [MTD Interface] Suspend the NAND flash
- * @mtd:	MTD device structure
+ * @mtd: MTD device structure
  */
 static int nand_suspend(struct mtd_info *mtd)
 {
@@ -2736,7 +2756,7 @@
 
 /**
  * nand_resume - [MTD Interface] Resume the NAND flash
- * @mtd:	MTD device structure
+ * @mtd: MTD device structure
  */
 static void nand_resume(struct mtd_info *mtd)
 {
@@ -2745,13 +2765,11 @@
 	if (chip->state == FL_PM_SUSPENDED)
 		nand_release_device(mtd);
 	else
-		printk(KERN_ERR "%s called for a chip which is not "
-		       "in suspended state\n", __func__);
+		pr_err("%s called for a chip which is not in suspended state\n",
+			__func__);
 }
 
-/*
- * Set default functions
- */
+/* Set default functions */
 static void nand_set_defaults(struct nand_chip *chip, int busw)
 {
 	/* check for proper chip_delay setup, set 20us if not */
@@ -2793,23 +2811,21 @@
 
 }
 
-/*
- * sanitize ONFI strings so we can safely print them
- */
+/* Sanitize ONFI strings so we can safely print them */
 static void sanitize_string(uint8_t *s, size_t len)
 {
 	ssize_t i;
 
-	/* null terminate */
+	/* Null terminate */
 	s[len - 1] = 0;
 
-	/* remove non printable chars */
+	/* Remove non printable chars */
 	for (i = 0; i < len - 1; i++) {
 		if (s[i] < ' ' || s[i] > 127)
 			s[i] = '?';
 	}
 
-	/* remove trailing spaces */
+	/* Remove trailing spaces */
 	strim(s);
 }
 
@@ -2826,28 +2842,28 @@
 }
 
 /*
- * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise
+ * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
  */
 static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
-					int busw)
+					int *busw)
 {
 	struct nand_onfi_params *p = &chip->onfi_params;
 	int i;
 	int val;
 
-	/* try ONFI for unknow chip or LP */
+	/* Try ONFI for unknown chip or LP */
 	chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
 	if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
 		chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
 		return 0;
 
-	printk(KERN_INFO "ONFI flash detected\n");
+	pr_info("ONFI flash detected\n");
 	chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
 	for (i = 0; i < 3; i++) {
 		chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
 		if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
 				le16_to_cpu(p->crc)) {
-			printk(KERN_INFO "ONFI param page %d valid\n", i);
+			pr_info("ONFI param page %d valid\n", i);
 			break;
 		}
 	}
@@ -2855,7 +2871,7 @@
 	if (i == 3)
 		return 0;
 
-	/* check version */
+	/* Check version */
 	val = le16_to_cpu(p->revision);
 	if (val & (1 << 5))
 		chip->onfi_version = 23;
@@ -2871,8 +2887,7 @@
 		chip->onfi_version = 0;
 
 	if (!chip->onfi_version) {
-		printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
-								__func__, val);
+		pr_info("%s: unsupported ONFI version: %d\n", __func__, val);
 		return 0;
 	}
 
@@ -2884,9 +2899,9 @@
 	mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize;
 	mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
 	chip->chipsize = (uint64_t)le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
-	busw = 0;
+	*busw = 0;
 	if (le16_to_cpu(p->features) & 1)
-		busw = NAND_BUSWIDTH_16;
+		*busw = NAND_BUSWIDTH_16;
 
 	chip->options &= ~NAND_CHIPOPTIONS_MSK;
 	chip->options |= (NAND_NO_READRDY |
@@ -2896,7 +2911,7 @@
 }
 
 /*
- * Get the flash and manufacturer id and lookup if the type is supported
+ * Get the flash and manufacturer id and lookup if the type is supported.
  */
 static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 						  struct nand_chip *chip,
@@ -2913,7 +2928,7 @@
 
 	/*
 	 * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
-	 * after power-up
+	 * after power-up.
 	 */
 	chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
 
@@ -2924,7 +2939,8 @@
 	*maf_id = chip->read_byte(mtd);
 	*dev_id = chip->read_byte(mtd);
 
-	/* Try again to make sure, as some systems the bus-hold or other
+	/*
+	 * Try again to make sure, as some systems the bus-hold or other
 	 * interface concerns can cause random data which looks like a
 	 * possibly credible NAND flash to appear. If the two results do
 	 * not match, ignore the device completely.
@@ -2936,9 +2952,9 @@
 		id_data[i] = chip->read_byte(mtd);
 
 	if (id_data[0] != *maf_id || id_data[1] != *dev_id) {
-		printk(KERN_INFO "%s: second ID read did not match "
-		       "%02x,%02x against %02x,%02x\n", __func__,
-		       *maf_id, *dev_id, id_data[0], id_data[1]);
+		pr_info("%s: second ID read did not match "
+			"%02x,%02x against %02x,%02x\n", __func__,
+			*maf_id, *dev_id, id_data[0], id_data[1]);
 		return ERR_PTR(-ENODEV);
 	}
 
@@ -2952,7 +2968,7 @@
 	chip->onfi_version = 0;
 	if (!type->name || !type->pagesize) {
 		/* Check is chip is ONFI compliant */
-		ret = nand_flash_detect_onfi(mtd, chip, busw);
+		ret = nand_flash_detect_onfi(mtd, chip, &busw);
 		if (ret)
 			goto ident_done;
 	}
@@ -2973,7 +2989,7 @@
 	chip->chipsize = (uint64_t)type->chipsize << 20;
 
 	if (!type->pagesize && chip->init_size) {
-		/* set the pagesize, oobsize, erasesize by the driver*/
+		/* Set the pagesize, oobsize, erasesize by the driver */
 		busw = chip->init_size(mtd, chip, id_data);
 	} else if (!type->pagesize) {
 		int extid;
@@ -3033,7 +3049,7 @@
 		}
 	} else {
 		/*
-		 * Old devices have chip data hardcoded in the device id table
+		 * Old devices have chip data hardcoded in the device id table.
 		 */
 		mtd->erasesize = type->erasesize;
 		mtd->writesize = type->pagesize;
@@ -3043,7 +3059,7 @@
 		/*
 		 * Check for Spansion/AMD ID + repeating 5th, 6th byte since
 		 * some Spansion chips have erasesize that conflicts with size
-		 * listed in nand_ids table
+		 * listed in nand_ids table.
 		 * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39)
 		 */
 		if (*maf_id == NAND_MFR_AMD && id_data[4] != 0x00 &&
@@ -3057,15 +3073,16 @@
 	chip->options &= ~NAND_CHIPOPTIONS_MSK;
 	chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
 
-	/* Check if chip is a not a samsung device. Do not clear the
-	 * options for chips which are not having an extended id.
+	/*
+	 * Check if chip is not a Samsung device. Do not clear the
+	 * options for chips which do not have an extended id.
 	 */
 	if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
 		chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
 ident_done:
 
 	/*
-	 * Set chip as a default. Board drivers can override it, if necessary
+	 * Set chip as a default. Board drivers can override it, if necessary.
 	 */
 	chip->options |= NAND_NO_AUTOINCR;
 
@@ -3077,21 +3094,21 @@
 
 	/*
 	 * Check, if buswidth is correct. Hardware drivers should set
-	 * chip correct !
+	 * chip correct!
 	 */
 	if (busw != (chip->options & NAND_BUSWIDTH_16)) {
-		printk(KERN_INFO "NAND device: Manufacturer ID:"
-		       " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
-		       *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
-		printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
-		       (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
-		       busw ? 16 : 8);
+		pr_info("NAND device: Manufacturer ID:"
+			" 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
+			*dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
+		pr_warn("NAND bus width %d instead %d bit\n",
+			   (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
+			   busw ? 16 : 8);
 		return ERR_PTR(-EINVAL);
 	}
 
 	/* Calculate the address shift from the page size */
 	chip->page_shift = ffs(mtd->writesize) - 1;
-	/* Convert chipsize to number of pages per chip -1. */
+	/* Convert chipsize to number of pages per chip -1 */
 	chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
 
 	chip->bbt_erase_shift = chip->phys_erase_shift =
@@ -3121,7 +3138,7 @@
 	if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
 			(*maf_id == NAND_MFR_SAMSUNG ||
 			 *maf_id == NAND_MFR_HYNIX))
-		chip->options |= NAND_BBT_SCANLASTPAGE;
+		chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
 	else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
 				(*maf_id == NAND_MFR_SAMSUNG ||
 				 *maf_id == NAND_MFR_HYNIX ||
@@ -3129,17 +3146,7 @@
 				 *maf_id == NAND_MFR_AMD)) ||
 			(mtd->writesize == 2048 &&
 			 *maf_id == NAND_MFR_MICRON))
-		chip->options |= NAND_BBT_SCAN2NDPAGE;
-
-	/*
-	 * Numonyx/ST 2K pages, x8 bus use BOTH byte 1 and 6
-	 */
-	if (!(busw & NAND_BUSWIDTH_16) &&
-			*maf_id == NAND_MFR_STMICRO &&
-			mtd->writesize == 2048) {
-		chip->options |= NAND_BBT_SCANBYTE1AND6;
-		chip->badblockpos = 0;
-	}
+		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
 
 	/* Check for AND chips with 4 page planes */
 	if (chip->options & NAND_4PAGE_ARRAY)
@@ -3147,12 +3154,11 @@
 	else
 		chip->erase_cmd = single_erase_cmd;
 
-	/* Do not replace user supplied command function ! */
+	/* Do not replace user supplied command function! */
 	if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
 		chip->cmdfunc = nand_command_lp;
 
-	/* TODO onfi flash name */
-	printk(KERN_INFO "NAND device: Manufacturer ID:"
+	pr_info("NAND device: Manufacturer ID:"
 		" 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id,
 		nand_manuf_ids[maf_idx].name,
 		chip->onfi_version ? chip->onfi_params.model : type->name);
@@ -3162,12 +3168,12 @@
 
 /**
  * nand_scan_ident - [NAND Interface] Scan for the NAND device
- * @mtd:	     MTD device structure
- * @maxchips:	     Number of chips to scan for
- * @table:	     Alternative NAND ID table
+ * @mtd: MTD device structure
+ * @maxchips: number of chips to scan for
+ * @table: alternative NAND ID table
  *
- * This is the first phase of the normal nand_scan() function. It
- * reads the flash ID and sets up MTD fields accordingly.
+ * This is the first phase of the normal nand_scan() function. It reads the
+ * flash ID and sets up MTD fields accordingly.
  *
  * The mtd->owner field must be set to the module of the caller.
  */
@@ -3189,7 +3195,7 @@
 
 	if (IS_ERR(type)) {
 		if (!(chip->options & NAND_SCAN_SILENT_NODEV))
-			printk(KERN_WARNING "No NAND device found.\n");
+			pr_warn("No NAND device found\n");
 		chip->select_chip(mtd, -1);
 		return PTR_ERR(type);
 	}
@@ -3207,7 +3213,7 @@
 			break;
 	}
 	if (i > 1)
-		printk(KERN_INFO "%d NAND chips detected\n", i);
+		pr_info("%d NAND chips detected\n", i);
 
 	/* Store the number of chips and calc total size for mtd */
 	chip->numchips = i;
@@ -3220,11 +3226,11 @@
 
 /**
  * nand_scan_tail - [NAND Interface] Scan for the NAND device
- * @mtd:	    MTD device structure
+ * @mtd: MTD device structure
  *
- * This is the second phase of the normal nand_scan() function. It
- * fills out all the uninitialized function pointers with the defaults
- * and scans for a bad block table if appropriate.
+ * This is the second phase of the normal nand_scan() function. It fills out
+ * all the uninitialized function pointers with the defaults and scans for a
+ * bad block table if appropriate.
  */
 int nand_scan_tail(struct mtd_info *mtd)
 {
@@ -3240,7 +3246,7 @@
 	chip->oob_poi = chip->buffers->databuf + mtd->writesize;
 
 	/*
-	 * If no default placement scheme is given, select an appropriate one
+	 * If no default placement scheme is given, select an appropriate one.
 	 */
 	if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) {
 		switch (mtd->oobsize) {
@@ -3257,8 +3263,8 @@
 			chip->ecc.layout = &nand_oob_128;
 			break;
 		default:
-			printk(KERN_WARNING "No oob scheme defined for "
-			       "oobsize %d\n", mtd->oobsize);
+			pr_warn("No oob scheme defined for oobsize %d\n",
+				   mtd->oobsize);
 			BUG();
 		}
 	}
@@ -3267,7 +3273,7 @@
 		chip->write_page = nand_write_page;
 
 	/*
-	 * check ECC mode, default to software if 3byte/512byte hardware ECC is
+	 * Check ECC mode, default to software if 3byte/512byte hardware ECC is
 	 * selected and we have 256 byte pagesize fallback to software ECC
 	 */
 
@@ -3276,15 +3282,15 @@
 		/* Similar to NAND_ECC_HW, but a separate read_page handle */
 		if (!chip->ecc.calculate || !chip->ecc.correct ||
 		     !chip->ecc.hwctl) {
-			printk(KERN_WARNING "No ECC functions supplied; "
-			       "Hardware ECC not possible\n");
+			pr_warn("No ECC functions supplied; "
+				   "hardware ECC not possible\n");
 			BUG();
 		}
 		if (!chip->ecc.read_page)
 			chip->ecc.read_page = nand_read_page_hwecc_oob_first;
 
 	case NAND_ECC_HW:
-		/* Use standard hwecc read page function ? */
+		/* Use standard hwecc read page function? */
 		if (!chip->ecc.read_page)
 			chip->ecc.read_page = nand_read_page_hwecc;
 		if (!chip->ecc.write_page)
@@ -3305,11 +3311,11 @@
 		     chip->ecc.read_page == nand_read_page_hwecc ||
 		     !chip->ecc.write_page ||
 		     chip->ecc.write_page == nand_write_page_hwecc)) {
-			printk(KERN_WARNING "No ECC functions supplied; "
-			       "Hardware ECC not possible\n");
+			pr_warn("No ECC functions supplied; "
+				   "hardware ECC not possible\n");
 			BUG();
 		}
-		/* Use standard syndrome read/write page function ? */
+		/* Use standard syndrome read/write page function? */
 		if (!chip->ecc.read_page)
 			chip->ecc.read_page = nand_read_page_syndrome;
 		if (!chip->ecc.write_page)
@@ -3325,9 +3331,9 @@
 
 		if (mtd->writesize >= chip->ecc.size)
 			break;
-		printk(KERN_WARNING "%d byte HW ECC not possible on "
-		       "%d byte page size, fallback to SW ECC\n",
-		       chip->ecc.size, mtd->writesize);
+		pr_warn("%d byte HW ECC not possible on "
+			   "%d byte page size, fallback to SW ECC\n",
+			   chip->ecc.size, mtd->writesize);
 		chip->ecc.mode = NAND_ECC_SOFT;
 
 	case NAND_ECC_SOFT:
@@ -3347,7 +3353,7 @@
 
 	case NAND_ECC_SOFT_BCH:
 		if (!mtd_nand_has_bch()) {
-			printk(KERN_WARNING "CONFIG_MTD_ECC_BCH not enabled\n");
+			pr_warn("CONFIG_MTD_ECC_BCH not enabled\n");
 			BUG();
 		}
 		chip->ecc.calculate = nand_bch_calculate_ecc;
@@ -3362,8 +3368,8 @@
 		/*
 		 * 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
+		 * for details. Otherwise, default to 4 bits for large page
+		 * devices.
 		 */
 		if (!chip->ecc.size && (mtd->oobsize >= 64)) {
 			chip->ecc.size = 512;
@@ -3374,14 +3380,14 @@
 					       chip->ecc.bytes,
 					       &chip->ecc.layout);
 		if (!chip->ecc.priv) {
-			printk(KERN_WARNING "BCH ECC initialization failed!\n");
+			pr_warn("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");
+		pr_warn("NAND_ECC_NONE selected by board driver. "
+			   "This is not recommended!\n");
 		chip->ecc.read_page = nand_read_page_raw;
 		chip->ecc.write_page = nand_write_page_raw;
 		chip->ecc.read_oob = nand_read_oob_std;
@@ -3393,14 +3399,19 @@
 		break;
 
 	default:
-		printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
-		       chip->ecc.mode);
+		pr_warn("Invalid NAND_ECC_MODE %d\n", chip->ecc.mode);
 		BUG();
 	}
 
+	/* For many systems, the standard OOB write also works for raw */
+	if (!chip->ecc.read_oob_raw)
+		chip->ecc.read_oob_raw = chip->ecc.read_oob;
+	if (!chip->ecc.write_oob_raw)
+		chip->ecc.write_oob_raw = chip->ecc.write_oob;
+
 	/*
 	 * The number of bytes available for a client to place data into
-	 * the out of band area
+	 * the out of band area.
 	 */
 	chip->ecc.layout->oobavail = 0;
 	for (i = 0; chip->ecc.layout->oobfree[i].length
@@ -3411,19 +3422,16 @@
 
 	/*
 	 * Set the number of read / write steps for one page depending on ECC
-	 * mode
+	 * mode.
 	 */
 	chip->ecc.steps = mtd->writesize / chip->ecc.size;
 	if (chip->ecc.steps * chip->ecc.size != mtd->writesize) {
-		printk(KERN_WARNING "Invalid ecc parameters\n");
+		pr_warn("Invalid ECC parameters\n");
 		BUG();
 	}
 	chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
 
-	/*
-	 * Allow subpage writes up to ecc.steps. Not possible for MLC
-	 * FLASH.
-	 */
+	/* Allow subpage writes up to ecc.steps. Not possible for MLC flash */
 	if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
 	    !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
 		switch (chip->ecc.steps) {
@@ -3481,9 +3489,11 @@
 }
 EXPORT_SYMBOL(nand_scan_tail);
 
-/* is_module_text_address() isn't exported, and it's mostly a pointless
+/*
+ * is_module_text_address() isn't exported, and it's mostly a pointless
  * test if this is a module _anyway_ -- they'd have to try _really_ hard
- * to call us from in-kernel code if the core NAND support is modular. */
+ * to call us from in-kernel code if the core NAND support is modular.
+ */
 #ifdef MODULE
 #define caller_is_module() (1)
 #else
@@ -3493,15 +3503,13 @@
 
 /**
  * nand_scan - [NAND Interface] Scan for the NAND device
- * @mtd:	MTD device structure
- * @maxchips:	Number of chips to scan for
- *
- * This fills out all the uninitialized function pointers
- * with the defaults.
- * The flash ID is read and the mtd/chip structures are
- * filled with the appropriate values.
- * The mtd->owner field must be set to the module of the caller
+ * @mtd: MTD device structure
+ * @maxchips: number of chips to scan for
  *
+ * This fills out all the uninitialized function pointers with the defaults.
+ * The flash ID is read and the mtd/chip structures are filled with the
+ * appropriate values. The mtd->owner field must be set to the module of the
+ * caller.
  */
 int nand_scan(struct mtd_info *mtd, int maxchips)
 {
@@ -3509,8 +3517,7 @@
 
 	/* Many callers got this wrong, so check for it for a while... */
 	if (!mtd->owner && caller_is_module()) {
-		printk(KERN_CRIT "%s called with NULL mtd->owner!\n",
-				__func__);
+		pr_crit("%s called with NULL mtd->owner!\n", __func__);
 		BUG();
 	}
 
@@ -3523,8 +3530,8 @@
 
 /**
  * nand_release - [NAND Interface] Free resources held by the NAND device
- * @mtd:	MTD device structure
-*/
+ * @mtd: MTD device structure
+ */
 void nand_release(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/nand_bbt.c linux-libre-3.2-gnu/drivers/mtd/nand/nand_bbt.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/nand_bbt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/nand_bbt.c	2012-01-04 18:55:44.000000000 -0500
@@ -14,7 +14,7 @@
  *
  * When nand_scan_bbt is called, then it tries to find the bad block table
  * depending on the options in the BBT descriptor(s). If no flash based BBT
- * (NAND_USE_FLASH_BBT) is specified then the device is scanned for factory
+ * (NAND_BBT_USE_FLASH) is specified then the device is scanned for factory
  * marked good / bad blocks. This information is used to create a memory BBT.
  * Once a new bad block is discovered then the "factory" information is updated
  * on the device.
@@ -36,9 +36,9 @@
  * The table is marked in the OOB area with an ident pattern and a version
  * number which indicates which of both tables is more up to date. If the NAND
  * controller needs the complete OOB area for the ECC information then the
- * option NAND_USE_FLASH_BBT_NO_OOB should be used: it moves the ident pattern
- * and the version byte into the data area and the OOB area will remain
- * untouched.
+ * option NAND_BBT_NO_OOB should be used (along with NAND_BBT_USE_FLASH, of
+ * course): it moves the ident pattern and the version byte into the data area
+ * and the OOB area will remain untouched.
  *
  * The table uses 2 bits per block
  * 11b:		block is good
@@ -67,6 +67,7 @@
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 
 static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)
 {
@@ -80,17 +81,15 @@
 
 /**
  * check_pattern - [GENERIC] check if a pattern is in the buffer
- * @buf:	the buffer to search
- * @len:	the length of buffer to search
- * @paglen:	the pagelength
- * @td:		search pattern descriptor
- *
- * Check for a pattern at the given place. Used to search bad block
- * tables and good / bad block identifiers.
- * If the SCAN_EMPTY option is set then check, if all bytes except the
- * pattern area contain 0xff
+ * @buf: the buffer to search
+ * @len: the length of buffer to search
+ * @paglen: the pagelength
+ * @td: search pattern descriptor
  *
-*/
+ * Check for a pattern at the given place. Used to search bad block tables and
+ * good / bad block identifiers. If the SCAN_EMPTY option is set then check, if
+ * all bytes except the pattern area contain 0xff.
+ */
 static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
 {
 	int i, end = 0;
@@ -109,32 +108,8 @@
 	p += end;
 
 	/* Compare the pattern */
-	for (i = 0; i < td->len; i++) {
-		if (p[i] != td->pattern[i])
-			return -1;
-	}
-
-	/* Check both positions 1 and 6 for pattern? */
-	if (td->options & NAND_BBT_SCANBYTE1AND6) {
-		if (td->options & NAND_BBT_SCANEMPTY) {
-			p += td->len;
-			end += NAND_SMALL_BADBLOCK_POS - td->offs;
-			/* Check region between positions 1 and 6 */
-			for (i = 0; i < NAND_SMALL_BADBLOCK_POS - td->offs - td->len;
-					i++) {
-				if (*p++ != 0xff)
-					return -1;
-			}
-		}
-		else {
-			p += NAND_SMALL_BADBLOCK_POS - td->offs;
-		}
-		/* Compare the pattern */
-		for (i = 0; i < td->len; i++) {
-			if (p[i] != td->pattern[i])
-				return -1;
-		}
-	}
+	if (memcmp(p, td->pattern, td->len))
+		return -1;
 
 	if (td->options & NAND_BBT_SCANEMPTY) {
 		p += td->len;
@@ -149,14 +124,13 @@
 
 /**
  * check_short_pattern - [GENERIC] check if a pattern is in the buffer
- * @buf:	the buffer to search
- * @td:		search pattern descriptor
- *
- * Check for a pattern at the given place. Used to search bad block
- * tables and good / bad block identifiers. Same as check_pattern, but
- * no optional empty check
+ * @buf: the buffer to search
+ * @td:	search pattern descriptor
  *
-*/
+ * Check for a pattern at the given place. Used to search bad block tables and
+ * good / bad block identifiers. Same as check_pattern, but no optional empty
+ * check.
+ */
 static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
 {
 	int i;
@@ -167,21 +141,14 @@
 		if (p[td->offs + i] != td->pattern[i])
 			return -1;
 	}
-	/* Need to check location 1 AND 6? */
-	if (td->options & NAND_BBT_SCANBYTE1AND6) {
-		for (i = 0; i < td->len; i++) {
-			if (p[NAND_SMALL_BADBLOCK_POS + i] != td->pattern[i])
-				return -1;
-		}
-	}
 	return 0;
 }
 
 /**
  * add_marker_len - compute the length of the marker in data area
- * @td:		BBT descriptor used for computation
+ * @td: BBT descriptor used for computation
  *
- * The length will be 0 if the markeris located in OOB area.
+ * The length will be 0 if the marker is located in OOB area.
  */
 static u32 add_marker_len(struct nand_bbt_descr *td)
 {
@@ -198,34 +165,33 @@
 
 /**
  * read_bbt - [GENERIC] Read the bad block table starting from page
- * @mtd:	MTD device structure
- * @buf:	temporary buffer
- * @page:	the starting page
- * @num:	the number of bbt descriptors to read
- * @td:		the bbt describtion table
- * @offs:	offset in the memory table
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @page: the starting page
+ * @num: the number of bbt descriptors to read
+ * @td: the bbt describtion table
+ * @offs: offset in the memory table
  *
  * Read the bad block table starting from page.
- *
  */
 static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 		struct nand_bbt_descr *td, int offs)
 {
-	int res, i, j, act = 0;
+	int res, ret = 0, i, j, act = 0;
 	struct nand_chip *this = mtd->priv;
 	size_t retlen, len, totlen;
 	loff_t from;
 	int bits = td->options & NAND_BBT_NRBITS_MSK;
-	uint8_t msk = (uint8_t) ((1 << bits) - 1);
+	uint8_t msk = (uint8_t)((1 << bits) - 1);
 	u32 marker_len;
 	int reserved_block_code = td->reserved_block_code;
 
 	totlen = (num * bits) >> 3;
 	marker_len = add_marker_len(td);
-	from = ((loff_t) page) << this->page_shift;
+	from = ((loff_t)page) << this->page_shift;
 
 	while (totlen) {
-		len = min(totlen, (size_t) (1 << this->bbt_erase_shift));
+		len = min(totlen, (size_t)(1 << this->bbt_erase_shift));
 		if (marker_len) {
 			/*
 			 * In case the BBT marker is not in the OOB area it
@@ -237,11 +203,18 @@
 		}
 		res = mtd->read(mtd, from, len, &retlen, buf);
 		if (res < 0) {
-			if (retlen != len) {
-				printk(KERN_INFO "nand_bbt: Error reading bad block table\n");
+			if (mtd_is_eccerr(res)) {
+				pr_info("nand_bbt: ECC error in BBT at "
+					"0x%012llx\n", from & ~mtd->writesize);
+				return res;
+			} else if (mtd_is_bitflip(res)) {
+				pr_info("nand_bbt: corrected error in BBT at "
+					"0x%012llx\n", from & ~mtd->writesize);
+				ret = res;
+			} else {
+				pr_info("nand_bbt: error reading BBT\n");
 				return res;
 			}
-			printk(KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
 		}
 
 		/* Analyse data */
@@ -252,17 +225,19 @@
 				if (tmp == msk)
 					continue;
 				if (reserved_block_code && (tmp == reserved_block_code)) {
-					printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%012llx\n",
-					       (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
+					pr_info("nand_read_bbt: reserved block at 0x%012llx\n",
+						 (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
 					this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
 					mtd->ecc_stats.bbtblocks++;
 					continue;
 				}
-				/* Leave it for now, if its matured we can move this
-				 * message to MTD_DEBUG_LEVEL0 */
-				printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%012llx\n",
-				       (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
-				/* Factory marked bad or worn out ? */
+				/*
+				 * Leave it for now, if it's matured we can
+				 * move this message to pr_debug.
+				 */
+				pr_info("nand_read_bbt: bad block at 0x%012llx\n",
+					 (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
+				/* Factory marked bad or worn out? */
 				if (tmp == 0)
 					this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
 				else
@@ -273,20 +248,20 @@
 		totlen -= len;
 		from += len;
 	}
-	return 0;
+	return ret;
 }
 
 /**
  * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page
- * @mtd:	MTD device structure
- * @buf:	temporary buffer
- * @td:		descriptor for the bad block table
- * @chip:	read the table for a specific chip, -1 read all chips.
- *		Applies only if NAND_BBT_PERCHIP option is set
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @td: descriptor for the bad block table
+ * @chip: read the table for a specific chip, -1 read all chips; applies only if
+ *        NAND_BBT_PERCHIP option is set
  *
- * Read the bad block table for all chips starting at a given page
- * We assume that the bbt bits are in consecutive order.
-*/
+ * Read the bad block table for all chips starting at a given page. We assume
+ * that the bbt bits are in consecutive order.
+ */
 static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
 {
 	struct nand_chip *this = mtd->priv;
@@ -312,9 +287,7 @@
 	return 0;
 }
 
-/*
- * BBT marker is in the first page, no OOB.
- */
+/* BBT marker is in the first page, no OOB */
 static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
 			 struct nand_bbt_descr *td)
 {
@@ -328,35 +301,26 @@
 	return mtd->read(mtd, offs, len, &retlen, buf);
 }
 
-/*
- * Scan read raw data from flash
- */
+/* Scan read raw data from flash */
 static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
 			 size_t len)
 {
 	struct mtd_oob_ops ops;
 	int res;
 
-	ops.mode = MTD_OOB_RAW;
+	ops.mode = MTD_OPS_RAW;
 	ops.ooboffs = 0;
 	ops.ooblen = mtd->oobsize;
 
-
 	while (len > 0) {
-		if (len <= mtd->writesize) {
-			ops.oobbuf = buf + len;
-			ops.datbuf = buf;
-			ops.len = len;
-			return mtd->read_oob(mtd, offs, &ops);
-		} else {
-			ops.oobbuf = buf + mtd->writesize;
-			ops.datbuf = buf;
-			ops.len = mtd->writesize;
-			res = mtd->read_oob(mtd, offs, &ops);
+		ops.datbuf = buf;
+		ops.len = min(len, (size_t)mtd->writesize);
+		ops.oobbuf = buf + ops.len;
 
-			if (res)
-				return res;
-		}
+		res = mtd->read_oob(mtd, offs, &ops);
+
+		if (res)
+			return res;
 
 		buf += mtd->oobsize + mtd->writesize;
 		len -= mtd->writesize;
@@ -373,15 +337,13 @@
 		return scan_read_raw_oob(mtd, buf, offs, len);
 }
 
-/*
- * Scan write data with oob to flash
- */
+/* Scan write data with oob to flash */
 static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len,
 			  uint8_t *buf, uint8_t *oob)
 {
 	struct mtd_oob_ops ops;
 
-	ops.mode = MTD_OOB_PLACE;
+	ops.mode = MTD_OPS_PLACE_OOB;
 	ops.ooboffs = 0;
 	ops.ooblen = mtd->oobsize;
 	ops.datbuf = buf;
@@ -402,15 +364,14 @@
 
 /**
  * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page
- * @mtd:	MTD device structure
- * @buf:	temporary buffer
- * @td:		descriptor for the bad block table
- * @md:		descriptor for the bad block table mirror
- *
- * Read the bad block table(s) for all chips starting at a given page
- * We assume that the bbt bits are in consecutive order.
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @td: descriptor for the bad block table
+ * @md:	descriptor for the bad block table mirror
  *
-*/
+ * Read the bad block table(s) for all chips starting at a given page. We
+ * assume that the bbt bits are in consecutive order.
+ */
 static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
 			 struct nand_bbt_descr *td, struct nand_bbt_descr *md)
 {
@@ -421,8 +382,8 @@
 		scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift,
 			      mtd->writesize, td);
 		td->version[0] = buf[bbt_get_ver_offs(mtd, td)];
-		printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
-		       td->pages[0], td->version[0]);
+		pr_info("Bad block table at page %d, version 0x%02X\n",
+			 td->pages[0], td->version[0]);
 	}
 
 	/* Read the mirror version, if available */
@@ -430,15 +391,13 @@
 		scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift,
 			      mtd->writesize, td);
 		md->version[0] = buf[bbt_get_ver_offs(mtd, md)];
-		printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
-		       md->pages[0], md->version[0]);
+		pr_info("Bad block table at page %d, version 0x%02X\n",
+			 md->pages[0], md->version[0]);
 	}
 	return 1;
 }
 
-/*
- * Scan a given block full
- */
+/* Scan a given block full */
 static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
 			   loff_t offs, uint8_t *buf, size_t readlen,
 			   int scanlen, int len)
@@ -446,7 +405,8 @@
 	int ret, j;
 
 	ret = scan_read_raw_oob(mtd, buf, offs, readlen);
-	if (ret)
+	/* Ignore ECC errors when checking for BBM */
+	if (ret && !mtd_is_bitflip_or_eccerr(ret))
 		return ret;
 
 	for (j = 0; j < len; j++, buf += scanlen) {
@@ -456,9 +416,7 @@
 	return 0;
 }
 
-/*
- * Scan a given block partially
- */
+/* Scan a given block partially */
 static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
 			   loff_t offs, uint8_t *buf, int len)
 {
@@ -469,16 +427,16 @@
 	ops.oobbuf = buf;
 	ops.ooboffs = 0;
 	ops.datbuf = NULL;
-	ops.mode = MTD_OOB_PLACE;
+	ops.mode = MTD_OPS_PLACE_OOB;
 
 	for (j = 0; j < len; j++) {
 		/*
-		 * Read the full oob until read_oob is fixed to
-		 * handle single byte reads for 16 bit
-		 * buswidth
+		 * Read the full oob until read_oob is fixed to handle single
+		 * byte reads for 16 bit buswidth.
 		 */
 		ret = mtd->read_oob(mtd, offs, &ops);
-		if (ret)
+		/* Ignore ECC errors when checking for BBM */
+		if (ret && !mtd_is_bitflip_or_eccerr(ret))
 			return ret;
 
 		if (check_short_pattern(buf, bd))
@@ -491,14 +449,14 @@
 
 /**
  * create_bbt - [GENERIC] Create a bad block table by scanning the device
- * @mtd:	MTD device structure
- * @buf:	temporary buffer
- * @bd:		descriptor for the good/bad block search pattern
- * @chip:	create the table for a specific chip, -1 read all chips.
- *		Applies only if NAND_BBT_PERCHIP option is set
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @bd: descriptor for the good/bad block search pattern
+ * @chip: create the table for a specific chip, -1 read all chips; applies only
+ *        if NAND_BBT_PERCHIP option is set
  *
- * Create a bad block table by scanning the device
- * for the given good/bad block identify pattern
+ * Create a bad block table by scanning the device for the given good/bad block
+ * identify pattern.
  */
 static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 	struct nand_bbt_descr *bd, int chip)
@@ -509,7 +467,7 @@
 	loff_t from;
 	size_t readlen;
 
-	printk(KERN_INFO "Scanning device for bad blocks\n");
+	pr_info("Scanning device for bad blocks\n");
 
 	if (bd->options & NAND_BBT_SCANALLPAGES)
 		len = 1 << (this->bbt_erase_shift - this->page_shift);
@@ -529,14 +487,16 @@
 	}
 
 	if (chip == -1) {
-		/* Note that numblocks is 2 * (real numblocks) here, see i+=2
-		 * below as it makes shifting and masking less painful */
+		/*
+		 * Note that numblocks is 2 * (real numblocks) here, see i+=2
+		 * below as it makes shifting and masking less painful
+		 */
 		numblocks = mtd->size >> (this->bbt_erase_shift - 1);
 		startblock = 0;
 		from = 0;
 	} else {
 		if (chip >= this->numchips) {
-			printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
+			pr_warn("create_bbt(): chipnr (%d) > available chips (%d)\n",
 			       chip + 1, this->numchips);
 			return -EINVAL;
 		}
@@ -546,7 +506,7 @@
 		from = (loff_t)startblock << (this->bbt_erase_shift - 1);
 	}
 
-	if (this->options & NAND_BBT_SCANLASTPAGE)
+	if (this->bbt_options & NAND_BBT_SCANLASTPAGE)
 		from += mtd->erasesize - (mtd->writesize * len);
 
 	for (i = startblock; i < numblocks;) {
@@ -565,8 +525,8 @@
 
 		if (ret) {
 			this->bbt[i >> 3] |= 0x03 << (i & 0x6);
-			printk(KERN_WARNING "Bad eraseblock %d at 0x%012llx\n",
-			       i >> 1, (unsigned long long)from);
+			pr_warn("Bad eraseblock %d at 0x%012llx\n",
+				i >> 1, (unsigned long long)from);
 			mtd->ecc_stats.badblocks++;
 		}
 
@@ -578,20 +538,18 @@
 
 /**
  * search_bbt - [GENERIC] scan the device for a specific bad block table
- * @mtd:	MTD device structure
- * @buf:	temporary buffer
- * @td:		descriptor for the bad block table
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @td: descriptor for the bad block table
  *
- * Read the bad block table by searching for a given ident pattern.
- * Search is preformed either from the beginning up or from the end of
- * the device downwards. The search starts always at the start of a
- * block.
- * If the option NAND_BBT_PERCHIP is given, each chip is searched
- * for a bbt, which contains the bad block information of this chip.
- * This is necessary to provide support for certain DOC devices.
+ * Read the bad block table by searching for a given ident pattern. Search is
+ * preformed either from the beginning up or from the end of the device
+ * downwards. The search starts always at the start of a block. If the option
+ * NAND_BBT_PERCHIP is given, each chip is searched for a bbt, which contains
+ * the bad block information of this chip. This is necessary to provide support
+ * for certain DOC devices.
  *
- * The bbt ident pattern resides in the oob area of the first page
- * in a block.
+ * The bbt ident pattern resides in the oob area of the first page in a block.
  */
 static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
 {
@@ -602,7 +560,7 @@
 	int bbtblocks;
 	int blocktopage = this->bbt_erase_shift - this->page_shift;
 
-	/* Search direction top -> down ? */
+	/* Search direction top -> down? */
 	if (td->options & NAND_BBT_LASTBLOCK) {
 		startblock = (mtd->size >> this->bbt_erase_shift) - 1;
 		dir = -1;
@@ -611,7 +569,7 @@
 		dir = 1;
 	}
 
-	/* Do we have a bbt per chip ? */
+	/* Do we have a bbt per chip? */
 	if (td->options & NAND_BBT_PERCHIP) {
 		chips = this->numchips;
 		bbtblocks = this->chipsize >> this->bbt_erase_shift;
@@ -650,23 +608,23 @@
 	/* Check, if we found a bbt for each requested chip */
 	for (i = 0; i < chips; i++) {
 		if (td->pages[i] == -1)
-			printk(KERN_WARNING "Bad block table not found for chip %d\n", i);
+			pr_warn("Bad block table not found for chip %d\n", i);
 		else
-			printk(KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i],
-			       td->version[i]);
+			pr_info("Bad block table found at page %d, version "
+				 "0x%02X\n", td->pages[i], td->version[i]);
 	}
 	return 0;
 }
 
 /**
  * search_read_bbts - [GENERIC] scan the device for bad block table(s)
- * @mtd:	MTD device structure
- * @buf:	temporary buffer
- * @td:		descriptor for the bad block table
- * @md:		descriptor for the bad block table mirror
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @td: descriptor for the bad block table
+ * @md: descriptor for the bad block table mirror
  *
- * Search and read the bad block table(s)
-*/
+ * Search and read the bad block table(s).
+ */
 static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md)
 {
 	/* Search the primary table */
@@ -682,16 +640,14 @@
 
 /**
  * write_bbt - [GENERIC] (Re)write the bad block table
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @td: descriptor for the bad block table
+ * @md: descriptor for the bad block table mirror
+ * @chipsel: selector for a specific chip, -1 for all
  *
- * @mtd:	MTD device structure
- * @buf:	temporary buffer
- * @td:		descriptor for the bad block table
- * @md:		descriptor for the bad block table mirror
- * @chipsel:	selector for a specific chip, -1 for all
- *
- * (Re)write the bad block table
- *
-*/
+ * (Re)write the bad block table.
+ */
 static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 		     struct nand_bbt_descr *td, struct nand_bbt_descr *md,
 		     int chipsel)
@@ -710,14 +666,14 @@
 	ops.ooblen = mtd->oobsize;
 	ops.ooboffs = 0;
 	ops.datbuf = NULL;
-	ops.mode = MTD_OOB_PLACE;
+	ops.mode = MTD_OPS_PLACE_OOB;
 
 	if (!rcode)
 		rcode = 0xff;
-	/* Write bad block table per chip rather than per device ? */
+	/* Write bad block table per chip rather than per device? */
 	if (td->options & NAND_BBT_PERCHIP) {
 		numblocks = (int)(this->chipsize >> this->bbt_erase_shift);
-		/* Full device write or specific chip ? */
+		/* Full device write or specific chip? */
 		if (chipsel == -1) {
 			nrchips = this->numchips;
 		} else {
@@ -731,8 +687,8 @@
 
 	/* Loop through the chips */
 	for (; chip < nrchips; chip++) {
-
-		/* There was already a version of the table, reuse the page
+		/*
+		 * There was already a version of the table, reuse the page
 		 * This applies for absolute placement too, as we have the
 		 * page nr. in td->pages.
 		 */
@@ -741,8 +697,10 @@
 			goto write;
 		}
 
-		/* Automatic placement of the bad block table */
-		/* Search direction top -> down ? */
+		/*
+		 * Automatic placement of the bad block table. Search direction
+		 * top -> down?
+		 */
 		if (td->options & NAND_BBT_LASTBLOCK) {
 			startblock = numblocks * (chip + 1) - 1;
 			dir = -1;
@@ -766,7 +724,7 @@
 			if (!md || md->pages[chip] != page)
 				goto write;
 		}
-		printk(KERN_ERR "No space left to write bad block table\n");
+		pr_err("No space left to write bad block table\n");
 		return -ENOSPC;
 	write:
 
@@ -791,24 +749,22 @@
 
 		bbtoffs = chip * (numblocks >> 2);
 
-		to = ((loff_t) page) << this->page_shift;
+		to = ((loff_t)page) << this->page_shift;
 
-		/* Must we save the block contents ? */
+		/* Must we save the block contents? */
 		if (td->options & NAND_BBT_SAVECONTENT) {
 			/* Make it block aligned */
-			to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
+			to &= ~((loff_t)((1 << this->bbt_erase_shift) - 1));
 			len = 1 << this->bbt_erase_shift;
 			res = mtd->read(mtd, to, len, &retlen, buf);
 			if (res < 0) {
 				if (retlen != len) {
-					printk(KERN_INFO "nand_bbt: Error "
-					       "reading block for writing "
-					       "the bad block table\n");
+					pr_info("nand_bbt: error reading block "
+						"for writing the bad block table\n");
 					return res;
 				}
-				printk(KERN_WARNING "nand_bbt: ECC error "
-				       "while reading block for writing "
-				       "bad block table\n");
+				pr_warn("nand_bbt: ECC error while reading "
+					"block for writing bad block table\n");
 			}
 			/* Read oob data */
 			ops.ooblen = (len >> this->page_shift) * mtd->oobsize;
@@ -821,19 +777,19 @@
 			pageoffs = page - (int)(to >> this->page_shift);
 			offs = pageoffs << this->page_shift;
 			/* Preset the bbt area with 0xff */
-			memset(&buf[offs], 0xff, (size_t) (numblocks >> sft));
+			memset(&buf[offs], 0xff, (size_t)(numblocks >> sft));
 			ooboffs = len + (pageoffs * mtd->oobsize);
 
 		} else if (td->options & NAND_BBT_NO_OOB) {
 			ooboffs = 0;
 			offs = td->len;
-			/* the version byte */
+			/* The version byte */
 			if (td->options & NAND_BBT_VERSION)
 				offs++;
 			/* Calc length */
-			len = (size_t) (numblocks >> sft);
+			len = (size_t)(numblocks >> sft);
 			len += offs;
-			/* Make it page aligned ! */
+			/* Make it page aligned! */
 			len = ALIGN(len, mtd->writesize);
 			/* Preset the buffer with 0xff */
 			memset(buf, 0xff, len);
@@ -841,8 +797,8 @@
 			memcpy(buf, td->pattern, td->len);
 		} else {
 			/* Calc length */
-			len = (size_t) (numblocks >> sft);
-			/* Make it page aligned ! */
+			len = (size_t)(numblocks >> sft);
+			/* Make it page aligned! */
 			len = ALIGN(len, mtd->writesize);
 			/* Preset the buffer with 0xff */
 			memset(buf, 0xff, len +
@@ -856,13 +812,13 @@
 		if (td->options & NAND_BBT_VERSION)
 			buf[ooboffs + td->veroffs] = td->version[chip];
 
-		/* walk through the memory table */
+		/* Walk through the memory table */
 		for (i = 0; i < numblocks;) {
 			uint8_t dat;
 			dat = this->bbt[bbtoffs + (i >> 2)];
 			for (j = 0; j < 4; j++, i++) {
 				int sftcnt = (i << (3 - sft)) & sftmsk;
-				/* Do not store the reserved bbt blocks ! */
+				/* Do not store the reserved bbt blocks! */
 				buf[offs + (i >> sft)] &=
 					~(msk[dat & 0x03] << sftcnt);
 				dat >>= 2;
@@ -883,8 +839,8 @@
 		if (res < 0)
 			goto outerr;
 
-		printk(KERN_DEBUG "Bad block table written to 0x%012llx, version "
-		       "0x%02X\n", (unsigned long long)to, td->version[chip]);
+		pr_info("Bad block table written to 0x%012llx, version 0x%02X\n",
+			 (unsigned long long)to, td->version[chip]);
 
 		/* Mark it as used */
 		td->pages[chip] = page;
@@ -892,19 +848,18 @@
 	return 0;
 
  outerr:
-	printk(KERN_WARNING
-	       "nand_bbt: Error while writing bad block table %d\n", res);
+	pr_warn("nand_bbt: error while writing bad block table %d\n", res);
 	return res;
 }
 
 /**
  * nand_memory_bbt - [GENERIC] create a memory based bad block table
- * @mtd:	MTD device structure
- * @bd:		descriptor for the good/bad block search pattern
+ * @mtd: MTD device structure
+ * @bd: descriptor for the good/bad block search pattern
  *
- * The function creates a memory based bbt by scanning the device
- * for manufacturer / software marked good / bad blocks
-*/
+ * The function creates a memory based bbt by scanning the device for
+ * manufacturer / software marked good / bad blocks.
+ */
 static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
 	struct nand_chip *this = mtd->priv;
@@ -915,25 +870,24 @@
 
 /**
  * check_create - [GENERIC] create and write bbt(s) if necessary
- * @mtd:	MTD device structure
- * @buf:	temporary buffer
- * @bd:		descriptor for the good/bad block search pattern
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @bd: descriptor for the good/bad block search pattern
  *
- * The function checks the results of the previous call to read_bbt
- * and creates / updates the bbt(s) if necessary
- * Creation is necessary if no bbt was found for the chip/device
- * Update is necessary if one of the tables is missing or the
- * version nr. of one table is less than the other
-*/
+ * The function checks the results of the previous call to read_bbt and creates
+ * / updates the bbt(s) if necessary. Creation is necessary if no bbt was found
+ * for the chip/device. Update is necessary if one of the tables is missing or
+ * the version nr. of one table is less than the other.
+ */
 static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
 {
-	int i, chips, writeops, chipsel, res;
+	int i, chips, writeops, create, chipsel, res, res2;
 	struct nand_chip *this = mtd->priv;
 	struct nand_bbt_descr *td = this->bbt_td;
 	struct nand_bbt_descr *md = this->bbt_md;
 	struct nand_bbt_descr *rd, *rd2;
 
-	/* Do we have a bbt per chip ? */
+	/* Do we have a bbt per chip? */
 	if (td->options & NAND_BBT_PERCHIP)
 		chips = this->numchips;
 	else
@@ -941,86 +895,98 @@
 
 	for (i = 0; i < chips; i++) {
 		writeops = 0;
+		create = 0;
 		rd = NULL;
 		rd2 = NULL;
-		/* Per chip or per device ? */
+		res = res2 = 0;
+		/* Per chip or per device? */
 		chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1;
-		/* Mirrored table available ? */
+		/* Mirrored table available? */
 		if (md) {
 			if (td->pages[i] == -1 && md->pages[i] == -1) {
+				create = 1;
 				writeops = 0x03;
-				goto create;
-			}
-
-			if (td->pages[i] == -1) {
+			} else if (td->pages[i] == -1) {
 				rd = md;
-				td->version[i] = md->version[i];
-				writeops = 1;
-				goto writecheck;
-			}
-
-			if (md->pages[i] == -1) {
+				writeops = 0x01;
+			} else if (md->pages[i] == -1) {
 				rd = td;
-				md->version[i] = td->version[i];
-				writeops = 2;
-				goto writecheck;
-			}
-
-			if (td->version[i] == md->version[i]) {
+				writeops = 0x02;
+			} else if (td->version[i] == md->version[i]) {
 				rd = td;
 				if (!(td->options & NAND_BBT_VERSION))
 					rd2 = md;
-				goto writecheck;
-			}
-
-			if (((int8_t) (td->version[i] - md->version[i])) > 0) {
+			} else if (((int8_t)(td->version[i] - md->version[i])) > 0) {
 				rd = td;
-				md->version[i] = td->version[i];
-				writeops = 2;
+				writeops = 0x02;
 			} else {
 				rd = md;
-				td->version[i] = md->version[i];
-				writeops = 1;
+				writeops = 0x01;
 			}
-
-			goto writecheck;
-
 		} else {
 			if (td->pages[i] == -1) {
+				create = 1;
 				writeops = 0x01;
-				goto create;
+			} else {
+				rd = td;
 			}
-			rd = td;
-			goto writecheck;
 		}
-	create:
-		/* Create the bad block table by scanning the device ? */
-		if (!(td->options & NAND_BBT_CREATE))
-			continue;
 
-		/* Create the table in memory by scanning the chip(s) */
-		if (!(this->options & NAND_CREATE_EMPTY_BBT))
-			create_bbt(mtd, buf, bd, chipsel);
+		if (create) {
+			/* Create the bad block table by scanning the device? */
+			if (!(td->options & NAND_BBT_CREATE))
+				continue;
 
-		td->version[i] = 1;
-		if (md)
-			md->version[i] = 1;
-	writecheck:
-		/* read back first ? */
-		if (rd)
-			read_abs_bbt(mtd, buf, rd, chipsel);
-		/* If they weren't versioned, read both. */
-		if (rd2)
-			read_abs_bbt(mtd, buf, rd2, chipsel);
+			/* Create the table in memory by scanning the chip(s) */
+			if (!(this->bbt_options & NAND_BBT_CREATE_EMPTY))
+				create_bbt(mtd, buf, bd, chipsel);
 
-		/* Write the bad block table to the device ? */
+			td->version[i] = 1;
+			if (md)
+				md->version[i] = 1;
+		}
+
+		/* Read back first? */
+		if (rd) {
+			res = read_abs_bbt(mtd, buf, rd, chipsel);
+			if (mtd_is_eccerr(res)) {
+				/* Mark table as invalid */
+				rd->pages[i] = -1;
+				rd->version[i] = 0;
+				i--;
+				continue;
+			}
+		}
+		/* If they weren't versioned, read both */
+		if (rd2) {
+			res2 = read_abs_bbt(mtd, buf, rd2, chipsel);
+			if (mtd_is_eccerr(res2)) {
+				/* Mark table as invalid */
+				rd2->pages[i] = -1;
+				rd2->version[i] = 0;
+				i--;
+				continue;
+			}
+		}
+
+		/* Scrub the flash table(s)? */
+		if (mtd_is_bitflip(res) || mtd_is_bitflip(res2))
+			writeops = 0x03;
+
+		/* Update version numbers before writing */
+		if (md) {
+			td->version[i] = max(td->version[i], md->version[i]);
+			md->version[i] = td->version[i];
+		}
+
+		/* Write the bad block table to the device? */
 		if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
 			res = write_bbt(mtd, buf, td, md, chipsel);
 			if (res < 0)
 				return res;
 		}
 
-		/* Write the mirror bad block table to the device ? */
+		/* Write the mirror bad block table to the device? */
 		if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
 			res = write_bbt(mtd, buf, md, td, chipsel);
 			if (res < 0)
@@ -1032,20 +998,19 @@
 
 /**
  * mark_bbt_regions - [GENERIC] mark the bad block table regions
- * @mtd:	MTD device structure
- * @td:		bad block table descriptor
+ * @mtd: MTD device structure
+ * @td: bad block table descriptor
  *
- * The bad block table regions are marked as "bad" to prevent
- * accidental erasures / writes. The regions are identified by
- * the mark 0x02.
-*/
+ * The bad block table regions are marked as "bad" to prevent accidental
+ * erasures / writes. The regions are identified by the mark 0x02.
+ */
 static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 {
 	struct nand_chip *this = mtd->priv;
 	int i, j, chips, block, nrblocks, update;
 	uint8_t oldval, newval;
 
-	/* Do we have a bbt per chip ? */
+	/* Do we have a bbt per chip? */
 	if (td->options & NAND_BBT_PERCHIP) {
 		chips = this->numchips;
 		nrblocks = (int)(this->chipsize >> this->bbt_erase_shift);
@@ -1082,9 +1047,11 @@
 				update = 1;
 			block += 2;
 		}
-		/* If we want reserved blocks to be recorded to flash, and some
-		   new ones have been marked, then we need to update the stored
-		   bbts.  This should only happen once. */
+		/*
+		 * If we want reserved blocks to be recorded to flash, and some
+		 * new ones have been marked, then we need to update the stored
+		 * bbts.  This should only happen once.
+		 */
 		if (update && td->reserved_block_code)
 			nand_update_bbt(mtd, (loff_t)(block - 2) << (this->bbt_erase_shift - 1));
 	}
@@ -1092,8 +1059,8 @@
 
 /**
  * verify_bbt_descr - verify the bad block description
- * @mtd:	MTD device structure
- * @bd:		the table to verify
+ * @mtd: MTD device structure
+ * @bd: the table to verify
  *
  * This functions performs a few sanity checks on the bad block description
  * table.
@@ -1111,16 +1078,16 @@
 	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((this->bbt_options & NAND_BBT_NO_OOB) &&
+			!(this->bbt_options & NAND_BBT_USE_FLASH));
 	BUG_ON(!bits);
 
 	if (bd->options & NAND_BBT_VERSION)
 		pattern_len++;
 
 	if (bd->options & NAND_BBT_NO_OOB) {
-		BUG_ON(!(this->options & NAND_USE_FLASH_BBT));
-		BUG_ON(!(this->options & NAND_USE_FLASH_BBT_NO_OOB));
+		BUG_ON(!(this->bbt_options & NAND_BBT_USE_FLASH));
+		BUG_ON(!(this->bbt_options & NAND_BBT_NO_OOB));
 		BUG_ON(bd->offs);
 		if (bd->options & NAND_BBT_VERSION)
 			BUG_ON(bd->veroffs != bd->len);
@@ -1140,18 +1107,16 @@
 
 /**
  * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s)
- * @mtd:	MTD device structure
- * @bd:		descriptor for the good/bad block search pattern
- *
- * The function checks, if a bad block table(s) is/are already
- * available. If not it scans the device for manufacturer
- * marked good / bad blocks and writes the bad block table(s) to
- * the selected place.
+ * @mtd: MTD device structure
+ * @bd: descriptor for the good/bad block search pattern
  *
- * The bad block table memory is allocated here. It must be freed
- * by calling the nand_free_bbt function.
+ * The function checks, if a bad block table(s) is/are already available. If
+ * not it scans the device for manufacturer marked good / bad blocks and writes
+ * the bad block table(s) to the selected place.
  *
-*/
+ * The bad block table memory is allocated here. It must be freed by calling
+ * the nand_free_bbt function.
+ */
 int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
 	struct nand_chip *this = mtd->priv;
@@ -1161,19 +1126,21 @@
 	struct nand_bbt_descr *md = this->bbt_md;
 
 	len = mtd->size >> (this->bbt_erase_shift + 2);
-	/* Allocate memory (2bit per block) and clear the memory bad block table */
+	/*
+	 * Allocate memory (2bit per block) and clear the memory bad block
+	 * table.
+	 */
 	this->bbt = kzalloc(len, GFP_KERNEL);
-	if (!this->bbt) {
-		printk(KERN_ERR "nand_scan_bbt: Out of memory\n");
+	if (!this->bbt)
 		return -ENOMEM;
-	}
 
-	/* If no primary table decriptor is given, scan the device
-	 * to build a memory based bad block table
+	/*
+	 * If no primary table decriptor is given, scan the device to build a
+	 * memory based bad block table.
 	 */
 	if (!td) {
 		if ((res = nand_memory_bbt(mtd, bd))) {
-			printk(KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");
+			pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n");
 			kfree(this->bbt);
 			this->bbt = NULL;
 		}
@@ -1187,13 +1154,12 @@
 	len += (len >> this->page_shift) * mtd->oobsize;
 	buf = vmalloc(len);
 	if (!buf) {
-		printk(KERN_ERR "nand_bbt: Out of memory\n");
 		kfree(this->bbt);
 		this->bbt = NULL;
 		return -ENOMEM;
 	}
 
-	/* Is the bbt at a given page ? */
+	/* Is the bbt at a given page? */
 	if (td->options & NAND_BBT_ABSPAGE) {
 		res = read_abs_bbts(mtd, buf, td, md);
 	} else {
@@ -1215,15 +1181,15 @@
 
 /**
  * nand_update_bbt - [NAND Interface] update bad block table(s)
- * @mtd:	MTD device structure
- * @offs:	the offset of the newly marked block
+ * @mtd: MTD device structure
+ * @offs: the offset of the newly marked block
  *
- * The function updates the bad block table(s)
-*/
+ * The function updates the bad block table(s).
+ */
 int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
 {
 	struct nand_chip *this = mtd->priv;
-	int len, res = 0, writeops = 0;
+	int len, res = 0;
 	int chip, chipsel;
 	uint8_t *buf;
 	struct nand_bbt_descr *td = this->bbt_td;
@@ -1236,14 +1202,10 @@
 	len = (1 << this->bbt_erase_shift);
 	len += (len >> this->page_shift) * mtd->oobsize;
 	buf = kmalloc(len, GFP_KERNEL);
-	if (!buf) {
-		printk(KERN_ERR "nand_update_bbt: Out of memory\n");
+	if (!buf)
 		return -ENOMEM;
-	}
-
-	writeops = md != NULL ? 0x03 : 0x01;
 
-	/* Do we have a bbt per chip ? */
+	/* Do we have a bbt per chip? */
 	if (td->options & NAND_BBT_PERCHIP) {
 		chip = (int)(offs >> this->chip_shift);
 		chipsel = chip;
@@ -1256,14 +1218,14 @@
 	if (md)
 		md->version[chip]++;
 
-	/* Write the bad block table to the device ? */
-	if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
+	/* Write the bad block table to the device? */
+	if (td->options & NAND_BBT_WRITE) {
 		res = write_bbt(mtd, buf, td, md, chipsel);
 		if (res < 0)
 			goto out;
 	}
-	/* Write the mirror bad block table to the device ? */
-	if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
+	/* Write the mirror bad block table to the device? */
+	if (md && (md->options & NAND_BBT_WRITE)) {
 		res = write_bbt(mtd, buf, md, td, chipsel);
 	}
 
@@ -1272,8 +1234,10 @@
 	return res;
 }
 
-/* Define some generic bad / good block scan pattern which are used
- * while scanning a device for factory marked good / bad blocks. */
+/*
+ * 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, 0xff };
 
 static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 };
@@ -1285,8 +1249,7 @@
 	.pattern = scan_agand_pattern
 };
 
-/* Generic flash bbt decriptors
-*/
+/* Generic flash bbt descriptors */
 static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
 static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
 
@@ -1330,31 +1293,27 @@
 	.pattern = mirror_pattern
 };
 
-#define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \
-		NAND_BBT_SCANBYTE1AND6)
+#define BADBLOCK_SCAN_MASK (~NAND_BBT_NO_OOB)
 /**
- * nand_create_default_bbt_descr - [Internal] Creates a BBT descriptor structure
- * @this:	NAND chip to create descriptor for
+ * nand_create_badblock_pattern - [INTERN] Creates a BBT descriptor structure
+ * @this: NAND chip to create descriptor for
  *
  * This function allocates and initializes a nand_bbt_descr for BBM detection
- * based on the properties of "this". The new descriptor is stored in
+ * based on the properties of @this. The new descriptor is stored in
  * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
  * passed to this function.
- *
  */
-static int nand_create_default_bbt_descr(struct nand_chip *this)
+static int nand_create_badblock_pattern(struct nand_chip *this)
 {
 	struct nand_bbt_descr *bd;
 	if (this->badblock_pattern) {
-		printk(KERN_WARNING "BBT descr already allocated; not replacing.\n");
+		pr_warn("Bad block pattern already allocated; not replacing\n");
 		return -EINVAL;
 	}
 	bd = kzalloc(sizeof(*bd), GFP_KERNEL);
-	if (!bd) {
-		printk(KERN_ERR "nand_create_default_bbt_descr: Out of memory\n");
+	if (!bd)
 		return -ENOMEM;
-	}
-	bd->options = this->options & BBT_SCAN_OPTIONS;
+	bd->options = this->bbt_options & BADBLOCK_SCAN_MASK;
 	bd->offs = this->badblockpos;
 	bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1;
 	bd->pattern = scan_ff_pattern;
@@ -1365,22 +1324,20 @@
 
 /**
  * nand_default_bbt - [NAND Interface] Select a default bad block table for the device
- * @mtd:	MTD device structure
- *
- * This function selects the default bad block table
- * support for the device and calls the nand_scan_bbt function
+ * @mtd: MTD device structure
  *
-*/
+ * This function selects the default bad block table support for the device and
+ * calls the nand_scan_bbt function.
+ */
 int nand_default_bbt(struct mtd_info *mtd)
 {
 	struct nand_chip *this = mtd->priv;
 
-	/* Default for AG-AND. We must use a flash based
-	 * bad block table as the devices have factory marked
-	 * _good_ blocks. Erasing those blocks leads to loss
-	 * of the good / bad information, so we _must_ store
-	 * this information in a good / bad table during
-	 * startup
+	/*
+	 * Default for AG-AND. We must use a flash based bad block table as the
+	 * devices have factory marked _good_ blocks. Erasing those blocks
+	 * leads to loss of the good / bad information, so we _must_ store this
+	 * information in a good / bad table during startup.
 	 */
 	if (this->options & NAND_IS_AND) {
 		/* Use the default pattern descriptors */
@@ -1388,15 +1345,15 @@
 			this->bbt_td = &bbt_main_descr;
 			this->bbt_md = &bbt_mirror_descr;
 		}
-		this->options |= NAND_USE_FLASH_BBT;
+		this->bbt_options |= NAND_BBT_USE_FLASH;
 		return nand_scan_bbt(mtd, &agand_flashbased);
 	}
 
-	/* Is a flash based bad block table requested ? */
-	if (this->options & NAND_USE_FLASH_BBT) {
+	/* Is a flash based bad block table requested? */
+	if (this->bbt_options & NAND_BBT_USE_FLASH) {
 		/* Use the default pattern descriptors */
 		if (!this->bbt_td) {
-			if (this->options & NAND_USE_FLASH_BBT_NO_OOB) {
+			if (this->bbt_options & NAND_BBT_NO_OOB) {
 				this->bbt_td = &bbt_main_no_bbt_descr;
 				this->bbt_md = &bbt_mirror_no_bbt_descr;
 			} else {
@@ -1410,18 +1367,17 @@
 	}
 
 	if (!this->badblock_pattern)
-		nand_create_default_bbt_descr(this);
+		nand_create_badblock_pattern(this);
 
 	return nand_scan_bbt(mtd, this->badblock_pattern);
 }
 
 /**
  * nand_isbad_bbt - [NAND Interface] Check if a block is bad
- * @mtd:	MTD device structure
- * @offs:	offset in the device
- * @allowbbt:	allow access to bad block table region
- *
-*/
+ * @mtd: MTD device structure
+ * @offs: offset in the device
+ * @allowbbt: allow access to bad block table region
+ */
 int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
 {
 	struct nand_chip *this = mtd->priv;
@@ -1432,8 +1388,9 @@
 	block = (int)(offs >> (this->bbt_erase_shift - 1));
 	res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
 
-	DEBUG(MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
-	      (unsigned int)offs, block >> 1, res);
+	pr_debug("nand_isbad_bbt(): bbt info for offs 0x%08x: "
+			"(block %d) 0x%02x\n",
+			(unsigned int)offs, block >> 1, res);
 
 	switch ((int)res) {
 	case 0x00:
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/nand_bch.c linux-libre-3.2-gnu/drivers/mtd/nand/nand_bch.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/nand_bch.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/nand_bch.c	2012-01-04 18:55:44.000000000 -0500
@@ -93,8 +93,8 @@
 				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]);
+			pr_debug("%s: corrected bitflip %u\n", __func__,
+					errloc[i]);
 		}
 	} else if (count < 0) {
 		printk(KERN_ERR "ecc unrecoverable error\n");
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/nand_ecc.c linux-libre-3.2-gnu/drivers/mtd/nand/nand_ecc.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/nand_ecc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/nand_ecc.c	2012-01-04 18:55:44.000000000 -0500
@@ -110,7 +110,7 @@
 
 /*
  * addressbits is a lookup table to filter out the bits from the xor-ed
- * ecc data that identify the faulty location.
+ * ECC data that identify the faulty location.
  * this is only used for repairing parity
  * see the comments in nand_correct_data for more details
  */
@@ -153,7 +153,7 @@
  * __nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte
  *			 block
  * @buf:	input buffer with raw data
- * @eccsize:	data bytes per ecc step (256 or 512)
+ * @eccsize:	data bytes per ECC step (256 or 512)
  * @code:	output buffer with ECC
  */
 void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize,
@@ -348,7 +348,7 @@
 		rp17 = (par ^ rp16) & 0xff;
 
 	/*
-	 * Finally calculate the ecc bits.
+	 * Finally calculate the ECC bits.
 	 * Again here it might seem that there are performance optimisations
 	 * possible, but benchmarks showed that on the system this is developed
 	 * the code below is the fastest
@@ -436,7 +436,7 @@
  * @buf:	raw data read from the chip
  * @read_ecc:	ECC from the chip
  * @calc_ecc:	the ECC calculated from raw data
- * @eccsize:	data bytes per ecc step (256 or 512)
+ * @eccsize:	data bytes per ECC step (256 or 512)
  *
  * Detect and correct a 1 bit error for eccsize byte block
  */
@@ -505,7 +505,7 @@
 	}
 	/* count nr of bits; use table lookup, faster than calculating it */
 	if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1)
-		return 1;	/* error in ecc data; no action needed */
+		return 1;	/* error in ECC data; no action needed */
 
 	printk(KERN_ERR "uncorrectable error : ");
 	return -1;
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/nandsim.c linux-libre-3.2-gnu/drivers/mtd/nand/nandsim.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/nandsim.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/nandsim.c	2012-01-04 18:55:44.000000000 -0500
@@ -2273,9 +2273,9 @@
 
 	switch (bbt) {
 	case 2:
-		 chip->options |= NAND_USE_FLASH_BBT_NO_OOB;
+		 chip->bbt_options |= NAND_BBT_NO_OOB;
 	case 1:
-		 chip->options |= NAND_USE_FLASH_BBT;
+		 chip->bbt_options |= NAND_BBT_USE_FLASH;
 	case 0:
 		break;
 	default:
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/ndfc.c linux-libre-3.2-gnu/drivers/mtd/nand/ndfc.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/ndfc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/ndfc.c	2012-01-04 18:55:44.000000000 -0500
@@ -42,7 +42,6 @@
 	struct nand_chip chip;
 	int chip_select;
 	struct nand_hw_control ndfc_control;
-	struct mtd_partition *parts;
 };
 
 static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS];
@@ -159,13 +158,9 @@
 static int ndfc_chip_init(struct ndfc_controller *ndfc,
 			  struct device_node *node)
 {
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-	static const char *part_types[] = { "cmdlinepart", NULL };
-#else
-	static const char *part_types[] = { NULL };
-#endif
 	struct device_node *flash_np;
 	struct nand_chip *chip = &ndfc->chip;
+	struct mtd_part_parser_data ppdata;
 	int ret;
 
 	chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
@@ -193,6 +188,7 @@
 	if (!flash_np)
 		return -ENODEV;
 
+	ppdata.of_node = flash_np;
 	ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s",
 			dev_name(&ndfc->ofdev->dev), flash_np->name);
 	if (!ndfc->mtd.name) {
@@ -204,18 +200,7 @@
 	if (ret)
 		goto err;
 
-	ret = parse_mtd_partitions(&ndfc->mtd, part_types, &ndfc->parts, 0);
-	if (ret < 0)
-		goto err;
-
-	if (ret == 0) {
-		ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np,
-					      &ndfc->parts);
-		if (ret < 0)
-			goto err;
-	}
-
-	ret = mtd_device_register(&ndfc->mtd, ndfc->parts, ret);
+	ret = mtd_device_parse_register(&ndfc->mtd, NULL, &ppdata, NULL, 0);
 
 err:
 	of_node_put(flash_np);
@@ -288,6 +273,7 @@
 	struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev);
 
 	nand_release(&ndfc->mtd);
+	kfree(ndfc->mtd.name);
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/nomadik_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/nomadik_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/nomadik_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/nomadik_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -187,6 +187,7 @@
 		pdata->exit();
 
 	if (host) {
+		nand_release(&host->mtd);
 		iounmap(host->cmd_va);
 		iounmap(host->data_va);
 		iounmap(host->addr_va);
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/nuc900_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/nuc900_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/nuc900_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/nuc900_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -339,6 +339,7 @@
 	struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev);
 	struct resource *res;
 
+	nand_release(&nuc900_nand->mtd);
 	iounmap(nuc900_nand->reg);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/omap2.c linux-libre-3.2-gnu/drivers/mtd/nand/omap2.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/omap2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/omap2.c	2012-01-04 18:55:44.000000000 -0500
@@ -11,6 +11,7 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
 #include <linux/sched.h>
@@ -94,8 +95,6 @@
 #define P4e_s(a)	(TF(a & NAND_Ecc_P4e)		<< 0)
 #define P4o_s(a)	(TF(a & NAND_Ecc_P4o)		<< 1)
 
-static const char *part_probes[] = { "cmdlinepart", NULL };
-
 /* 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
@@ -114,7 +113,6 @@
 	struct nand_hw_control		controller;
 	struct omap_nand_platform_data	*pdata;
 	struct mtd_info			mtd;
-	struct mtd_partition		*parts;
 	struct nand_chip		nand;
 	struct platform_device		*pdev;
 
@@ -744,12 +742,12 @@
 
 	case 1:
 		/* Uncorrectable error */
-		DEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n");
+		pr_debug("ECC UNCORRECTED_ERROR 1\n");
 		return -1;
 
 	case 11:
 		/* UN-Correctable error */
-		DEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR B\n");
+		pr_debug("ECC UNCORRECTED_ERROR B\n");
 		return -1;
 
 	case 12:
@@ -766,8 +764,8 @@
 
 		find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1];
 
-		DEBUG(MTD_DEBUG_LEVEL0, "Correcting single bit ECC error at "
-				"offset: %d, bit: %d\n", find_byte, find_bit);
+		pr_debug("Correcting single bit ECC error at offset: "
+				"%d, bit: %d\n", find_byte, find_bit);
 
 		page_data[find_byte] ^= (1 << find_bit);
 
@@ -779,7 +777,7 @@
 			    ecc_data2[2] == 0)
 				return 0;
 		}
-		DEBUG(MTD_DEBUG_LEVEL0, "UNCORRECTED_ERROR default\n");
+		pr_debug("UNCORRECTED_ERROR default\n");
 		return -1;
 	}
 }
@@ -1103,13 +1101,8 @@
 		goto out_release_mem_region;
 	}
 
-	err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
-	if (err > 0)
-		mtd_device_register(&info->mtd, info->parts, err);
-	else if (pdata->parts)
-		mtd_device_register(&info->mtd, pdata->parts, pdata->nr_parts);
-	else
-		mtd_device_register(&info->mtd, NULL, 0);
+	mtd_device_parse_register(&info->mtd, NULL, 0,
+			pdata->parts, pdata->nr_parts);
 
 	platform_set_drvdata(pdev, &info->mtd);
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/orion_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/orion_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/orion_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/orion_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,8 +21,6 @@
 #include <mach/hardware.h>
 #include <plat/orion_nand.h>
 
-static const char *part_probes[] = { "cmdlinepart", NULL };
-
 static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
 	struct nand_chip *nc = mtd->priv;
@@ -81,8 +79,6 @@
 	struct resource *res;
 	void __iomem *io_base;
 	int ret = 0;
-	struct mtd_partition *partitions = NULL;
-	int num_part = 0;
 
 	nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL);
 	if (!nc) {
@@ -132,17 +128,9 @@
 		goto no_dev;
 	}
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
 	mtd->name = "orion_nand";
-	num_part = parse_mtd_partitions(mtd, part_probes, &partitions, 0);
-#endif
-	/* If cmdline partitions have been passed, let them be used */
-	if (num_part <= 0) {
-		num_part = board->nr_parts;
-		partitions = board->parts;
-	}
-
-	ret = mtd_device_register(mtd, partitions, num_part);
+	ret = mtd_device_parse_register(mtd, NULL, 0,
+			board->parts, board->nr_parts);
 	if (ret) {
 		nand_release(mtd);
 		goto no_dev;
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/pasemi_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/pasemi_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/pasemi_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/pasemi_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -155,7 +155,8 @@
 	chip->ecc.mode = NAND_ECC_SOFT;
 
 	/* Enable the following for a flash based bad block table */
-	chip->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR;
+	chip->options = NAND_NO_AUTOINCR;
+	chip->bbt_options = NAND_BBT_USE_FLASH;
 
 	/* Scan to find existence of the device */
 	if (nand_scan(pasemi_nand_mtd, 1)) {
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/plat_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/plat_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/plat_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/plat_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -21,8 +21,6 @@
 	struct nand_chip	chip;
 	struct mtd_info		mtd;
 	void __iomem		*io_base;
-	int			nr_parts;
-	struct mtd_partition	*parts;
 };
 
 /*
@@ -79,6 +77,7 @@
 	data->chip.read_buf = pdata->ctrl.read_buf;
 	data->chip.chip_delay = pdata->chip.chip_delay;
 	data->chip.options |= pdata->chip.options;
+	data->chip.bbt_options |= pdata->chip.bbt_options;
 
 	data->chip.ecc.hwctl = pdata->ctrl.hwcontrol;
 	data->chip.ecc.layout = pdata->chip.ecclayout;
@@ -99,23 +98,9 @@
 		goto out;
 	}
 
-	if (pdata->chip.part_probe_types) {
-		err = parse_mtd_partitions(&data->mtd,
-					pdata->chip.part_probe_types,
-					&data->parts, 0);
-		if (err > 0) {
-			mtd_device_register(&data->mtd, data->parts, err);
-			return 0;
-		}
-	}
-	if (pdata->chip.set_parts)
-		pdata->chip.set_parts(data->mtd.size, &pdata->chip);
-	if (pdata->chip.partitions) {
-		data->parts = pdata->chip.partitions;
-		err = mtd_device_register(&data->mtd, data->parts,
-			pdata->chip.nr_partitions);
-	} else
-		err = mtd_device_register(&data->mtd, NULL, 0);
+	err = mtd_device_parse_register(&data->mtd,
+			pdata->chip.part_probe_types, 0,
+			pdata->chip.partitions, pdata->chip.nr_partitions);
 
 	if (!err)
 		return err;
@@ -145,8 +130,6 @@
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
 	nand_release(&data->mtd);
-	if (data->parts && data->parts != pdata->chip.partitions)
-		kfree(data->parts);
 	if (pdata->ctrl.remove)
 		pdata->ctrl.remove(pdev);
 	iounmap(data->io_base);
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/ppchameleonevb.c linux-libre-3.2-gnu/drivers/mtd/nand/ppchameleonevb.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/ppchameleonevb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/ppchameleonevb.c	2012-01-04 18:55:44.000000000 -0500
@@ -99,8 +99,6 @@
 
 #define NUM_PARTITIONS 1
 
-extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, const char *mtd_id);
-
 /*
  *	hardware specific access to control-lines
  */
@@ -187,18 +185,12 @@
 }
 #endif
 
-const char *part_probes[] = { "cmdlinepart", NULL };
-const char *part_probes_evb[] = { "cmdlinepart", NULL };
-
 /*
  * Main initialization routine
  */
 static int __init ppchameleonevb_init(void)
 {
 	struct nand_chip *this;
-	const char *part_type = 0;
-	int mtd_parts_nb = 0;
-	struct mtd_partition *mtd_parts = 0;
 	void __iomem *ppchameleon_fio_base;
 	void __iomem *ppchameleonevb_fio_base;
 
@@ -281,24 +273,13 @@
 #endif
 
 	ppchameleon_mtd->name = "ppchameleon-nand";
-	mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, part_probes, &mtd_parts, 0);
-	if (mtd_parts_nb > 0)
-		part_type = "command line";
-	else
-		mtd_parts_nb = 0;
-
-	if (mtd_parts_nb == 0) {
-		if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
-			mtd_parts = partition_info_me;
-		else
-			mtd_parts = partition_info_hi;
-		mtd_parts_nb = NUM_PARTITIONS;
-		part_type = "static";
-	}
 
 	/* Register the partitions */
-	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-	mtd_device_register(ppchameleon_mtd, mtd_parts, mtd_parts_nb);
+	mtd_device_parse_register(ppchameleon_mtd, NULL, 0,
+			ppchameleon_mtd->size == NAND_SMALL_SIZE ?
+				partition_info_me :
+				partition_info_hi,
+			NUM_PARTITIONS);
 
  nand_evb_init:
 	/****************************
@@ -382,21 +363,13 @@
 	}
 
 	ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME;
-	mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, part_probes_evb, &mtd_parts, 0);
-	if (mtd_parts_nb > 0)
-		part_type = "command line";
-	else
-		mtd_parts_nb = 0;
-
-	if (mtd_parts_nb == 0) {
-		mtd_parts = partition_info_evb;
-		mtd_parts_nb = NUM_PARTITIONS;
-		part_type = "static";
-	}
 
 	/* Register the partitions */
-	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-	mtd_device_register(ppchameleonevb_mtd, mtd_parts, mtd_parts_nb);
+	mtd_device_parse_register(ppchameleonevb_mtd, NULL, 0,
+			ppchameleon_mtd->size == NAND_SMALL_SIZE ?
+				partition_info_me :
+				partition_info_hi,
+			NUM_PARTITIONS);
 
 	/* Return happy */
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/pxa3xx_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/pxa3xx_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/pxa3xx_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/pxa3xx_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -110,6 +110,7 @@
 
 enum {
 	STATE_IDLE = 0,
+	STATE_PREPARED,
 	STATE_CMD_HANDLE,
 	STATE_DMA_READING,
 	STATE_DMA_WRITING,
@@ -120,21 +121,40 @@
 	STATE_READY,
 };
 
-struct pxa3xx_nand_info {
-	struct nand_chip	nand_chip;
+struct pxa3xx_nand_host {
+	struct nand_chip	chip;
+	struct pxa3xx_nand_cmdset *cmdset;
+	struct mtd_info         *mtd;
+	void			*info_data;
+
+	/* page size of attached chip */
+	unsigned int		page_size;
+	int			use_ecc;
+	int			cs;
+
+	/* calculated from pxa3xx_nand_flash data */
+	unsigned int		col_addr_cycles;
+	unsigned int		row_addr_cycles;
+	size_t			read_id_bytes;
 
+	/* cached register value */
+	uint32_t		reg_ndcr;
+	uint32_t		ndtr0cs0;
+	uint32_t		ndtr1cs0;
+};
+
+struct pxa3xx_nand_info {
 	struct nand_hw_control	controller;
 	struct platform_device	 *pdev;
-	struct pxa3xx_nand_cmdset *cmdset;
 
 	struct clk		*clk;
 	void __iomem		*mmio_base;
 	unsigned long		mmio_phys;
+	struct completion	cmd_complete;
 
 	unsigned int 		buf_start;
 	unsigned int		buf_count;
 
-	struct mtd_info         *mtd;
 	/* DMA information */
 	int			drcmr_dat;
 	int			drcmr_cmd;
@@ -142,44 +162,27 @@
 	unsigned char		*data_buff;
 	unsigned char		*oob_buff;
 	dma_addr_t 		data_buff_phys;
-	size_t			data_buff_size;
 	int 			data_dma_ch;
 	struct pxa_dma_desc	*data_desc;
 	dma_addr_t 		data_desc_addr;
 
-	uint32_t		reg_ndcr;
-
-	/* saved column/page_addr during CMD_SEQIN */
-	int			seqin_column;
-	int			seqin_page_addr;
-
-	/* relate to the command */
+	struct pxa3xx_nand_host *host[NUM_CHIP_SELECT];
 	unsigned int		state;
 
+	int			cs;
 	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 */
+	unsigned int		oob_size;
 	int 			retcode;
-	struct completion 	cmd_complete;
 
 	/* generated NDCBx register values */
 	uint32_t		ndcb0;
 	uint32_t		ndcb1;
 	uint32_t		ndcb2;
-
-	/* timing calcuted from setting */
-	uint32_t		ndtr0cs0;
-	uint32_t		ndtr1cs0;
-
-	/* calculated from pxa3xx_nand_flash data */
-	size_t		oob_size;
-	size_t		read_id_bytes;
-
-	unsigned int	col_addr_cycles;
-	unsigned int	row_addr_cycles;
 };
 
 static int use_dma = 1;
@@ -225,7 +228,7 @@
 /* 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};
+const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL};
 
 #define NDTR0_tCH(c)	(min((c), 7) << 19)
 #define NDTR0_tCS(c)	(min((c), 7) << 16)
@@ -241,9 +244,10 @@
 /* convert nano-seconds to nand flash controller clock cycles */
 #define ns2cycle(ns, clk)	(int)((ns) * (clk / 1000000) / 1000)
 
-static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
+static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
 				   const struct pxa3xx_nand_timing *t)
 {
+	struct pxa3xx_nand_info *info = host->info_data;
 	unsigned long nand_clk = clk_get_rate(info->clk);
 	uint32_t ndtr0, ndtr1;
 
@@ -258,23 +262,24 @@
 		NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) |
 		NDTR1_tAR(ns2cycle(t->tAR, nand_clk));
 
-	info->ndtr0cs0 = ndtr0;
-	info->ndtr1cs0 = ndtr1;
+	host->ndtr0cs0 = ndtr0;
+	host->ndtr1cs0 = ndtr1;
 	nand_writel(info, NDTR0CS0, ndtr0);
 	nand_writel(info, NDTR1CS0, ndtr1);
 }
 
 static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
 {
-	int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
+	struct pxa3xx_nand_host *host = info->host[info->cs];
+	int oob_enable = host->reg_ndcr & NDCR_SPARE_EN;
 
-	info->data_size = info->page_size;
+	info->data_size = host->page_size;
 	if (!oob_enable) {
 		info->oob_size = 0;
 		return;
 	}
 
-	switch (info->page_size) {
+	switch (host->page_size) {
 	case 2048:
 		info->oob_size = (info->use_ecc) ? 40 : 64;
 		break;
@@ -292,9 +297,10 @@
  */
 static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
 {
+	struct pxa3xx_nand_host *host = info->host[info->cs];
 	uint32_t ndcr;
 
-	ndcr = info->reg_ndcr;
+	ndcr = host->reg_ndcr;
 	ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
 	ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
 	ndcr |= NDCR_ND_RUN;
@@ -359,7 +365,7 @@
 					DIV_ROUND_UP(info->oob_size, 4));
 		break;
 	default:
-		printk(KERN_ERR "%s: invalid state %d\n", __func__,
+		dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
 				info->state);
 		BUG();
 	}
@@ -385,7 +391,7 @@
 		desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
 		break;
 	default:
-		printk(KERN_ERR "%s: invalid state %d\n", __func__,
+		dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
 				info->state);
 		BUG();
 	}
@@ -416,6 +422,15 @@
 {
 	struct pxa3xx_nand_info *info = devid;
 	unsigned int status, is_completed = 0;
+	unsigned int ready, cmd_done;
+
+	if (info->cs == 0) {
+		ready           = NDSR_FLASH_RDY;
+		cmd_done        = NDSR_CS0_CMDD;
+	} else {
+		ready           = NDSR_RDY;
+		cmd_done        = NDSR_CS1_CMDD;
+	}
 
 	status = nand_readl(info, NDSR);
 
@@ -437,11 +452,11 @@
 			handle_data_pio(info);
 		}
 	}
-	if (status & NDSR_CS0_CMDD) {
+	if (status & cmd_done) {
 		info->state = STATE_CMD_DONE;
 		is_completed = 1;
 	}
-	if (status & NDSR_FLASH_RDY) {
+	if (status & ready) {
 		info->is_ready = 1;
 		info->state = STATE_READY;
 	}
@@ -463,12 +478,6 @@
 	return IRQ_HANDLED;
 }
 
-static int pxa3xx_nand_dev_ready(struct mtd_info *mtd)
-{
-	struct pxa3xx_nand_info *info = mtd->priv;
-	return (nand_readl(info, NDSR) & NDSR_RDY) ? 1 : 0;
-}
-
 static inline int is_buf_blank(uint8_t *buf, size_t len)
 {
 	for (; len > 0; len--)
@@ -481,10 +490,12 @@
 		uint16_t column, int page_addr)
 {
 	uint16_t cmd;
-	int addr_cycle, exec_cmd, ndcb0;
-	struct mtd_info *mtd = info->mtd;
+	int addr_cycle, exec_cmd;
+	struct pxa3xx_nand_host *host;
+	struct mtd_info *mtd;
 
-	ndcb0 = 0;
+	host = info->host[info->cs];
+	mtd = host->mtd;
 	addr_cycle = 0;
 	exec_cmd = 1;
 
@@ -495,6 +506,10 @@
 	info->use_ecc		= 0;
 	info->is_ready		= 0;
 	info->retcode		= ERR_NONE;
+	if (info->cs != 0)
+		info->ndcb0 = NDCB0_CSEL;
+	else
+		info->ndcb0 = 0;
 
 	switch (command) {
 	case NAND_CMD_READ0:
@@ -512,20 +527,19 @@
 		break;
 	}
 
-	info->ndcb0 = ndcb0;
-	addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
-				    + info->col_addr_cycles);
+	addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles
+				    + host->col_addr_cycles);
 
 	switch (command) {
 	case NAND_CMD_READOOB:
 	case NAND_CMD_READ0:
-		cmd = info->cmdset->read1;
+		cmd = host->cmdset->read1;
 		if (command == NAND_CMD_READOOB)
 			info->buf_start = mtd->writesize + column;
 		else
 			info->buf_start = column;
 
-		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
+		if (unlikely(host->page_size < PAGE_CHUNK_SIZE))
 			info->ndcb0 |= NDCB0_CMD_TYPE(0)
 					| addr_cycle
 					| (cmd & NDCB0_CMD1_MASK);
@@ -537,7 +551,7 @@
 
 	case NAND_CMD_SEQIN:
 		/* small page addr setting */
-		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
+		if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) {
 			info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
 					| (column & 0xFF);
 
@@ -564,7 +578,7 @@
 			break;
 		}
 
-		cmd = info->cmdset->program;
+		cmd = host->cmdset->program;
 		info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
 				| NDCB0_AUTO_RS
 				| NDCB0_ST_ROW_EN
@@ -574,8 +588,8 @@
 		break;
 
 	case NAND_CMD_READID:
-		cmd = info->cmdset->read_id;
-		info->buf_count = info->read_id_bytes;
+		cmd = host->cmdset->read_id;
+		info->buf_count = host->read_id_bytes;
 		info->ndcb0 |= NDCB0_CMD_TYPE(3)
 				| NDCB0_ADDR_CYC(1)
 				| cmd;
@@ -583,7 +597,7 @@
 		info->data_size = 8;
 		break;
 	case NAND_CMD_STATUS:
-		cmd = info->cmdset->read_status;
+		cmd = host->cmdset->read_status;
 		info->buf_count = 1;
 		info->ndcb0 |= NDCB0_CMD_TYPE(4)
 				| NDCB0_ADDR_CYC(1)
@@ -593,7 +607,7 @@
 		break;
 
 	case NAND_CMD_ERASE1:
-		cmd = info->cmdset->erase;
+		cmd = host->cmdset->erase;
 		info->ndcb0 |= NDCB0_CMD_TYPE(2)
 				| NDCB0_AUTO_RS
 				| NDCB0_ADDR_CYC(3)
@@ -604,7 +618,7 @@
 
 		break;
 	case NAND_CMD_RESET:
-		cmd = info->cmdset->reset;
+		cmd = host->cmdset->reset;
 		info->ndcb0 |= NDCB0_CMD_TYPE(5)
 				| cmd;
 
@@ -616,8 +630,8 @@
 
 	default:
 		exec_cmd = 0;
-		printk(KERN_ERR "pxa3xx-nand: non-supported"
-			" command %x\n", command);
+		dev_err(&info->pdev->dev, "non-supported command %x\n",
+				command);
 		break;
 	}
 
@@ -627,7 +641,8 @@
 static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 				int column, int page_addr)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	int ret, exec_cmd;
 
 	/*
@@ -635,9 +650,21 @@
 	 * "byte" address into a "word" address appropriate
 	 * for indexing a word-oriented device
 	 */
-	if (info->reg_ndcr & NDCR_DWIDTH_M)
+	if (host->reg_ndcr & NDCR_DWIDTH_M)
 		column /= 2;
 
+	/*
+	 * There may be different NAND chip hooked to
+	 * different chip select, so check whether
+	 * chip select has been changed, if yes, reset the timing
+	 */
+	if (info->cs != host->cs) {
+		info->cs = host->cs;
+		nand_writel(info, NDTR0CS0, host->ndtr0cs0);
+		nand_writel(info, NDTR1CS0, host->ndtr1cs0);
+	}
+
+	info->state = STATE_PREPARED;
 	exec_cmd = prepare_command_pool(info, command, column, page_addr);
 	if (exec_cmd) {
 		init_completion(&info->cmd_complete);
@@ -646,12 +673,12 @@
 		ret = wait_for_completion_timeout(&info->cmd_complete,
 				CHIP_DELAY_TIMEOUT);
 		if (!ret) {
-			printk(KERN_ERR "Wait time out!!!\n");
+			dev_err(&info->pdev->dev, "Wait time out!!!\n");
 			/* Stop State Machine for next command cycle */
 			pxa3xx_nand_stop(info);
 		}
-		info->state = STATE_IDLE;
 	}
+	info->state = STATE_IDLE;
 }
 
 static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
@@ -664,7 +691,8 @@
 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;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 
 	chip->read_buf(mtd, buf, mtd->writesize);
 	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -685,6 +713,8 @@
 		 * OOB, ignore such double bit errors
 		 */
 		if (is_buf_blank(buf, mtd->writesize))
+			info->retcode = ERR_NONE;
+		else
 			mtd->ecc_stats.failed++;
 	}
 
@@ -693,7 +723,8 @@
 
 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	char retval = 0xFF;
 
 	if (info->buf_start < info->buf_count)
@@ -705,7 +736,8 @@
 
 static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	u16 retval = 0xFFFF;
 
 	if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
@@ -717,7 +749,8 @@
 
 static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
 
 	memcpy(buf, info->data_buff + info->buf_start, real_len);
@@ -727,7 +760,8 @@
 static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
 		const uint8_t *buf, int len)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
 
 	memcpy(info->data_buff + info->buf_start, buf, real_len);
@@ -747,7 +781,8 @@
 
 static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 
 	/* pxa3xx_nand_send_command has waited for command complete */
 	if (this->state == FL_WRITING || this->state == FL_ERASING) {
@@ -770,54 +805,70 @@
 {
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+	struct pxa3xx_nand_host *host = info->host[info->cs];
 	uint32_t ndcr = 0x0; /* enable all interrupts */
 
-	if (f->page_size != 2048 && f->page_size != 512)
+	if (f->page_size != 2048 && f->page_size != 512) {
+		dev_err(&pdev->dev, "Current only support 2048 and 512 size\n");
 		return -EINVAL;
+	}
 
-	if (f->flash_width != 16 && f->flash_width != 8)
+	if (f->flash_width != 16 && f->flash_width != 8) {
+		dev_err(&pdev->dev, "Only support 8bit and 16 bit!\n");
 		return -EINVAL;
+	}
 
 	/* calculate flash information */
-	info->cmdset = &default_cmdset;
-	info->page_size = f->page_size;
-	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
+	host->cmdset = &default_cmdset;
+	host->page_size = f->page_size;
+	host->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
 
 	/* calculate addressing information */
-	info->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
+	host->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
 
 	if (f->num_blocks * f->page_per_block > 65536)
-		info->row_addr_cycles = 3;
+		host->row_addr_cycles = 3;
 	else
-		info->row_addr_cycles = 2;
+		host->row_addr_cycles = 2;
 
 	ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
-	ndcr |= (info->col_addr_cycles == 2) ? NDCR_RA_START : 0;
+	ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
 	ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
 	ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
 	ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
 	ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
 
-	ndcr |= NDCR_RD_ID_CNT(info->read_id_bytes);
+	ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes);
 	ndcr |= NDCR_SPARE_EN; /* enable spare by default */
 
-	info->reg_ndcr = ndcr;
+	host->reg_ndcr = ndcr;
 
-	pxa3xx_nand_set_timing(info, f->timing);
+	pxa3xx_nand_set_timing(host, f->timing);
 	return 0;
 }
 
 static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 {
+	/*
+	 * We set 0 by hard coding here, for we don't support keep_config
+	 * when there is more than one chip attached to the controller
+	 */
+	struct pxa3xx_nand_host *host = info->host[0];
 	uint32_t ndcr = nand_readl(info, NDCR);
-	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
-	/* 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;
 
-	info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
-	info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
+	if (ndcr & NDCR_PAGE_SZ) {
+		host->page_size = 2048;
+		host->read_id_bytes = 4;
+	} else {
+		host->page_size = 512;
+		host->read_id_bytes = 2;
+	}
+
+	host->reg_ndcr = ndcr & ~NDCR_INT_MASK;
+	host->cmdset = &default_cmdset;
+
+	host->ndtr0cs0 = nand_readl(info, NDTR0CS0);
+	host->ndtr1cs0 = nand_readl(info, NDTR1CS0);
 
 	return 0;
 }
@@ -847,7 +898,6 @@
 		return -ENOMEM;
 	}
 
-	info->data_buff_size = MAX_BUFF_SIZE;
 	info->data_desc = (void *)info->data_buff + data_desc_offset;
 	info->data_desc_addr = info->data_buff_phys + data_desc_offset;
 
@@ -855,7 +905,7 @@
 				pxa3xx_nand_data_dma_irq, info);
 	if (info->data_dma_ch < 0) {
 		dev_err(&pdev->dev, "failed to request data dma\n");
-		dma_free_coherent(&pdev->dev, info->data_buff_size,
+		dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE,
 				info->data_buff, info->data_buff_phys);
 		return info->data_dma_ch;
 	}
@@ -865,24 +915,28 @@
 
 static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
 {
-	struct mtd_info *mtd = info->mtd;
-	struct nand_chip *chip = mtd->priv;
-
+	struct mtd_info *mtd;
+	int ret;
+	mtd = info->host[info->cs]->mtd;
 	/* 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);
+	ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+	if (ret)
+		return ret;
+
+	pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
 	if (info->is_ready)
-		return 1;
-	else
 		return 0;
+
+	return -ENODEV;
 }
 
 static int pxa3xx_nand_scan(struct mtd_info *mtd)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	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,} };
+	struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
 	const struct pxa3xx_nand_flash *f = NULL;
 	struct nand_chip *chip = mtd->priv;
 	uint32_t id = -1;
@@ -893,22 +947,20 @@
 		goto KEEP_CONFIG;
 
 	ret = pxa3xx_nand_sensing(info);
-	if (!ret) {
-		kfree(mtd);
-		info->mtd = NULL;
-		printk(KERN_INFO "There is no nand chip on cs 0!\n");
+	if (ret) {
+		dev_info(&info->pdev->dev, "There is no chip on cs %d!\n",
+			 info->cs);
 
-		return -EINVAL;
+		return ret;
 	}
 
 	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);
+		dev_info(&info->pdev->dev, "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");
+		dev_warn(&info->pdev->dev,
+			 "Read out ID 0, potential timing set wrong!!\n");
 
 		return -EINVAL;
 	}
@@ -926,14 +978,17 @@
 	}
 
 	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
-		kfree(mtd);
-		info->mtd = NULL;
-		printk(KERN_ERR "ERROR!! flash not defined!!!\n");
+		dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n");
 
 		return -EINVAL;
 	}
 
-	pxa3xx_nand_config_flash(info, f);
+	ret = pxa3xx_nand_config_flash(info, f);
+	if (ret) {
+		dev_err(&info->pdev->dev, "ERROR! Configure failed\n");
+		return ret;
+	}
+
 	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;
@@ -942,62 +997,78 @@
 	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;
+	pxa3xx_flash_ids[1].name = NULL;
+	def = pxa3xx_flash_ids;
 KEEP_CONFIG:
-	if (nand_scan_ident(mtd, 1, pxa3xx_flash_ids))
+	chip->ecc.mode = NAND_ECC_HW;
+	chip->ecc.size = host->page_size;
+
+	chip->options = NAND_NO_AUTOINCR;
+	chip->options |= NAND_NO_READRDY;
+	if (host->reg_ndcr & NDCR_DWIDTH_M)
+		chip->options |= NAND_BUSWIDTH_16;
+
+	if (nand_scan_ident(mtd, 1, def))
 		return -ENODEV;
 	/* calculate addressing information */
-	info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
+	if (mtd->writesize >= 2048)
+		host->col_addr_cycles = 2;
+	else
+		host->col_addr_cycles = 1;
+
 	info->oob_buff = info->data_buff + mtd->writesize;
 	if ((mtd->size >> chip->page_shift) > 65536)
-		info->row_addr_cycles = 3;
+		host->row_addr_cycles = 3;
 	else
-		info->row_addr_cycles = 2;
-	mtd->name = mtd_names[0];
-	chip->ecc.mode = NAND_ECC_HW;
-	chip->ecc.size = f->page_size;
-
-	chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16 : 0;
-	chip->options |= NAND_NO_AUTOINCR;
-	chip->options |= NAND_NO_READRDY;
+		host->row_addr_cycles = 2;
 
+	mtd->name = mtd_names[0];
 	return nand_scan_tail(mtd);
 }
 
-static
-struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
+static int alloc_nand_resource(struct platform_device *pdev)
 {
+	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
+	struct pxa3xx_nand_host *host;
 	struct nand_chip *chip;
 	struct mtd_info *mtd;
 	struct resource *r;
-	int ret, irq;
+	int ret, irq, cs;
 
-	mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info),
-			GFP_KERNEL);
-	if (!mtd) {
+	pdata = pdev->dev.platform_data;
+	info = kzalloc(sizeof(*info) + (sizeof(*mtd) +
+		       sizeof(*host)) * pdata->num_cs, GFP_KERNEL);
+	if (!info) {
 		dev_err(&pdev->dev, "failed to allocate memory\n");
-		return NULL;
+		return -ENOMEM;
 	}
 
-	info = (struct pxa3xx_nand_info *)(&mtd[1]);
-	chip = (struct nand_chip *)(&mtd[1]);
 	info->pdev = pdev;
-	info->mtd = mtd;
-	mtd->priv = info;
-	mtd->owner = THIS_MODULE;
+	for (cs = 0; cs < pdata->num_cs; cs++) {
+		mtd = (struct mtd_info *)((unsigned int)&info[1] +
+		      (sizeof(*mtd) + sizeof(*host)) * cs);
+		chip = (struct nand_chip *)(&mtd[1]);
+		host = (struct pxa3xx_nand_host *)chip;
+		info->host[cs] = host;
+		host->mtd = mtd;
+		host->cs = cs;
+		host->info_data = info;
+		mtd->priv = host;
+		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;
+		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->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);
@@ -1070,13 +1141,13 @@
 
 	platform_set_drvdata(pdev, info);
 
-	return info;
+	return 0;
 
 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,
+		dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE,
 			info->data_buff, info->data_buff_phys);
 	} else
 		kfree(info->data_buff);
@@ -1088,17 +1159,21 @@
 	clk_disable(info->clk);
 	clk_put(info->clk);
 fail_free_mtd:
-	kfree(mtd);
-	return NULL;
+	kfree(info);
+	return ret;
 }
 
 static int pxa3xx_nand_remove(struct platform_device *pdev)
 {
 	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
-	struct mtd_info *mtd = info->mtd;
+	struct pxa3xx_nand_platform_data *pdata;
 	struct resource *r;
-	int irq;
+	int irq, cs;
 
+	if (!info)
+		return 0;
+
+	pdata = pdev->dev.platform_data;
 	platform_set_drvdata(pdev, NULL);
 
 	irq = platform_get_irq(pdev, 0);
@@ -1106,7 +1181,7 @@
 		free_irq(irq, info);
 	if (use_dma) {
 		pxa_free_dma(info->data_dma_ch);
-		dma_free_writecombine(&pdev->dev, info->data_buff_size,
+		dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
 				info->data_buff, info->data_buff_phys);
 	} else
 		kfree(info->data_buff);
@@ -1118,10 +1193,9 @@
 	clk_disable(info->clk);
 	clk_put(info->clk);
 
-	if (mtd) {
-		mtd_device_unregister(mtd);
-		kfree(mtd);
-	}
+	for (cs = 0; cs < pdata->num_cs; cs++)
+		nand_release(info->host[cs]->mtd);
+	kfree(info);
 	return 0;
 }
 
@@ -1129,6 +1203,7 @@
 {
 	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
+	int ret, cs, probe_success;
 
 	pdata = pdev->dev.platform_data;
 	if (!pdata) {
@@ -1136,52 +1211,88 @@
 		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;
+	ret = alloc_nand_resource(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "alloc nand resource failed\n");
+		return ret;
 	}
 
-	if (mtd_has_cmdlinepart()) {
-		const char *probes[] = { "cmdlinepart", NULL };
-		struct mtd_partition *parts;
-		int nr_parts;
+	info = platform_get_drvdata(pdev);
+	probe_success = 0;
+	for (cs = 0; cs < pdata->num_cs; cs++) {
+		info->cs = cs;
+		ret = pxa3xx_nand_scan(info->host[cs]->mtd);
+		if (ret) {
+			dev_warn(&pdev->dev, "failed to scan nand at cs %d\n",
+				cs);
+			continue;
+		}
 
-		nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
+		ret = mtd_device_parse_register(info->host[cs]->mtd, NULL, 0,
+				pdata->parts[cs], pdata->nr_parts[cs]);
+		if (!ret)
+			probe_success = 1;
+	}
 
-		if (nr_parts)
-			return mtd_device_register(info->mtd, parts, nr_parts);
+	if (!probe_success) {
+		pxa3xx_nand_remove(pdev);
+		return -ENODEV;
 	}
 
-	return mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
+	return 0;
 }
 
 #ifdef CONFIG_PM
 static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
 {
 	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
-	struct mtd_info *mtd = info->mtd;
+	struct pxa3xx_nand_platform_data *pdata;
+	struct mtd_info *mtd;
+	int cs;
 
+	pdata = pdev->dev.platform_data;
 	if (info->state) {
 		dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
 		return -EAGAIN;
 	}
 
+	for (cs = 0; cs < pdata->num_cs; cs++) {
+		mtd = info->host[cs]->mtd;
+		mtd->suspend(mtd);
+	}
+
 	return 0;
 }
 
 static int pxa3xx_nand_resume(struct platform_device *pdev)
 {
 	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
-	struct mtd_info *mtd = info->mtd;
+	struct pxa3xx_nand_platform_data *pdata;
+	struct mtd_info *mtd;
+	int cs;
 
-	nand_writel(info, NDTR0CS0, info->ndtr0cs0);
-	nand_writel(info, NDTR1CS0, info->ndtr1cs0);
-	clk_enable(info->clk);
+	pdata = pdev->dev.platform_data;
+	/* We don't want to handle interrupt without calling mtd routine */
+	disable_int(info, NDCR_INT_MASK);
+
+	/*
+	 * Directly set the chip select to a invalid value,
+	 * then the driver would reset the timing according
+	 * to current chip select at the beginning of cmdfunc
+	 */
+	info->cs = 0xff;
+
+	/*
+	 * As the spec says, the NDSR would be updated to 0x1800 when
+	 * doing the nand_clk disable/enable.
+	 * To prevent it damaging state machine of the driver, clear
+	 * all status before resume
+	 */
+	nand_writel(info, NDSR, NDSR_MASK);
+	for (cs = 0; cs < pdata->num_cs; cs++) {
+		mtd = info->host[cs]->mtd;
+		mtd->resume(mtd);
+	}
 
 	return 0;
 }
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/r852.c linux-libre-3.2-gnu/drivers/mtd/nand/r852.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/r852.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/r852.c	2012-01-04 18:55:44.000000000 -0500
@@ -1027,7 +1027,7 @@
 }
 
 #ifdef CONFIG_PM
-int r852_suspend(struct device *device)
+static int r852_suspend(struct device *device)
 {
 	struct r852_device *dev = pci_get_drvdata(to_pci_dev(device));
 
@@ -1048,7 +1048,7 @@
 	return 0;
 }
 
-int r852_resume(struct device *device)
+static int r852_resume(struct device *device)
 {
 	struct r852_device *dev = pci_get_drvdata(to_pci_dev(device));
 
@@ -1092,7 +1092,7 @@
 
 MODULE_DEVICE_TABLE(pci, r852_pci_id_tbl);
 
-SIMPLE_DEV_PM_OPS(r852_pm_ops, r852_suspend, r852_resume);
+static SIMPLE_DEV_PM_OPS(r852_pm_ops, r852_suspend, r852_resume);
 
 static struct pci_driver r852_pci_driver = {
 	.name		= DRV_NAME,
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/rtc_from4.c linux-libre-3.2-gnu/drivers/mtd/nand/rtc_from4.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/rtc_from4.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/rtc_from4.c	2012-01-04 18:55:44.000000000 -0500
@@ -351,7 +351,7 @@
 		return 0;
 	}
 
-	/* Read the syndrom pattern from the FPGA and correct the bitorder */
+	/* Read the syndrome pattern from the FPGA and correct the bitorder */
 	rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC);
 	for (i = 0; i < 8; i++) {
 		ecc[i] = bitrev8(*rs_ecc);
@@ -380,7 +380,7 @@
 	/* Let the library code do its magic. */
 	res = decode_rs8(rs_decoder, (uint8_t *) buf, par, 512, syn, 0, NULL, 0xff, NULL);
 	if (res > 0) {
-		DEBUG(MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " "ECC corrected %d errors on read\n", res);
+		pr_debug("rtc_from4_correct_data: " "ECC corrected %d errors on read\n", res);
 	}
 	return res;
 }
@@ -444,7 +444,6 @@
 		len = mtd->writesize;
 		buf = kmalloc(len, GFP_KERNEL);
 		if (!buf) {
-			printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n");
 			er_stat = 1;
 			goto out;
 		}
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/s3c2410.c linux-libre-3.2-gnu/drivers/mtd/nand/s3c2410.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/s3c2410.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/s3c2410.c	2012-01-04 18:55:44.000000000 -0500
@@ -723,7 +723,7 @@
 
 	/* free the common resources */
 
-	if (info->clk != NULL && !IS_ERR(info->clk)) {
+	if (!IS_ERR(info->clk)) {
 		s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
 		clk_put(info->clk);
 	}
@@ -744,26 +744,15 @@
 	return 0;
 }
 
-const char *part_probes[] = { "cmdlinepart", NULL };
 static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
 				      struct s3c2410_nand_mtd *mtd,
 				      struct s3c2410_nand_set *set)
 {
-	struct mtd_partition *part_info;
-	int nr_part = 0;
-
-	if (set == NULL)
-		return mtd_device_register(&mtd->mtd, NULL, 0);
-
-	mtd->mtd.name = set->name;
-	nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, &part_info, 0);
-
-	if (nr_part <= 0 && set->nr_partitions > 0) {
-		nr_part = set->nr_partitions;
-		part_info = set->partitions;
-	}
+	if (set)
+		mtd->mtd.name = set->name;
 
-	return mtd_device_register(&mtd->mtd, part_info, nr_part);
+	return mtd_device_parse_register(&mtd->mtd, NULL, 0,
+			set->partitions, set->nr_partitions);
 }
 
 /**
@@ -880,8 +869,10 @@
 	/* If you use u-boot BBT creation code, specifying this flag will
 	 * let the kernel fish out the BBT from the NAND, and also skip the
 	 * full NAND scan that can take 1/2s or so. Little things... */
-	if (set->flash_bbt)
-		chip->options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN;
+	if (set->flash_bbt) {
+		chip->bbt_options |= NAND_BBT_USE_FLASH;
+		chip->options |= NAND_SKIP_BBTSCAN;
+	}
 }
 
 /**
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/sharpsl.c linux-libre-3.2-gnu/drivers/mtd/nand/sharpsl.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/sharpsl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/sharpsl.c	2012-01-04 18:55:44.000000000 -0500
@@ -103,16 +103,12 @@
 	return readb(sharpsl->io + ECCCNTR) != 0;
 }
 
-static const char *part_probes[] = { "cmdlinepart", NULL };
-
 /*
  * Main initialization routine
  */
 static int __devinit sharpsl_nand_probe(struct platform_device *pdev)
 {
 	struct nand_chip *this;
-	struct mtd_partition *sharpsl_partition_info;
-	int nr_partitions;
 	struct resource *r;
 	int err = 0;
 	struct sharpsl_nand *sharpsl;
@@ -184,14 +180,9 @@
 
 	/* Register the partitions */
 	sharpsl->mtd.name = "sharpsl-nand";
-	nr_partitions = parse_mtd_partitions(&sharpsl->mtd, part_probes, &sharpsl_partition_info, 0);
-	if (nr_partitions <= 0) {
-		nr_partitions = data->nr_partitions;
-		sharpsl_partition_info = data->partitions;
-	}
 
-	err = mtd_device_register(&sharpsl->mtd, sharpsl_partition_info,
-				  nr_partitions);
+	err = mtd_device_parse_register(&sharpsl->mtd, NULL, 0,
+			data->partitions, data->nr_partitions);
 	if (err)
 		goto err_add;
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/sm_common.c linux-libre-3.2-gnu/drivers/mtd/nand/sm_common.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/sm_common.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/sm_common.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,6 +8,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/mtd/nand.h>
+#include <linux/module.h>
 #include "sm_common.h"
 
 static struct nand_ecclayout nand_oob_sm = {
@@ -47,7 +48,7 @@
 
 	/* As long as this function is called on erase block boundaries
 		it will work correctly for 256 byte nand */
-	ops.mode = MTD_OOB_PLACE;
+	ops.mode = MTD_OPS_PLACE_OOB;
 	ops.ooboffs = 0;
 	ops.ooblen = mtd->oobsize;
 	ops.oobbuf = (void *)&oob;
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/socrates_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/socrates_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/socrates_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/socrates_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -155,8 +155,6 @@
 	return 1;
 }
 
-static const char *part_probes[] = { "cmdlinepart", NULL };
-
 /*
  * Probe for the NAND device.
  */
@@ -166,8 +164,7 @@
 	struct mtd_info *mtd;
 	struct nand_chip *nand_chip;
 	int res;
-	struct mtd_partition *partitions = NULL;
-	int num_partitions = 0;
+	struct mtd_part_parser_data ppdata;
 
 	/* Allocate memory for the device structure (and zero it) */
 	host = kzalloc(sizeof(struct socrates_nand_host), GFP_KERNEL);
@@ -193,6 +190,7 @@
 	mtd->name = "socrates_nand";
 	mtd->owner = THIS_MODULE;
 	mtd->dev.parent = &ofdev->dev;
+	ppdata.of_node = ofdev->dev.of_node;
 
 	/*should never be accessed directly */
 	nand_chip->IO_ADDR_R = (void *)0xdeadbeef;
@@ -225,30 +223,10 @@
 		goto out;
 	}
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-	num_partitions = parse_mtd_partitions(mtd, part_probes,
-					      &partitions, 0);
-	if (num_partitions < 0) {
-		res = num_partitions;
-		goto release;
-	}
-#endif
-
-	if (num_partitions == 0) {
-		num_partitions = of_mtd_parse_partitions(&ofdev->dev,
-							 ofdev->dev.of_node,
-							 &partitions);
-		if (num_partitions < 0) {
-			res = num_partitions;
-			goto release;
-		}
-	}
-
-	res = mtd_device_register(mtd, partitions, num_partitions);
+	res = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
 	if (!res)
 		return res;
 
-release:
 	nand_release(mtd);
 
 out:
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/tmio_nand.c linux-libre-3.2-gnu/drivers/mtd/nand/tmio_nand.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/tmio_nand.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/tmio_nand.c	2012-01-04 18:55:44.000000000 -0500
@@ -121,9 +121,6 @@
 
 #define mtd_to_tmio(m)			container_of(m, struct tmio_nand, mtd)
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-static const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
 
 /*--------------------------------------------------------------------------*/
 
@@ -381,8 +378,6 @@
 	struct tmio_nand *tmio;
 	struct mtd_info *mtd;
 	struct nand_chip *nand_chip;
-	struct mtd_partition *parts;
-	int nbparts = 0;
 	int retval;
 
 	if (data == NULL)
@@ -461,15 +456,9 @@
 		goto err_scan;
 	}
 	/* Register the partitions */
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-	nbparts = parse_mtd_partitions(mtd, part_probes, &parts, 0);
-#endif
-	if (nbparts <= 0 && data) {
-		parts = data->partition;
-		nbparts = data->num_partitions;
-	}
-
-	retval = mtd_device_register(mtd, parts, nbparts);
+	retval = mtd_device_parse_register(mtd, NULL, 0,
+			data ? data->partition : NULL,
+			data ? data->num_partitions : 0);
 	if (!retval)
 		return retval;
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/nand/txx9ndfmc.c linux-libre-3.2-gnu/drivers/mtd/nand/txx9ndfmc.c
--- linux-libre-3.1-gnu/drivers/mtd/nand/txx9ndfmc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nand/txx9ndfmc.c	2012-01-04 18:55:44.000000000 -0500
@@ -74,7 +74,6 @@
 	unsigned char hold;	/* in gbusclock */
 	unsigned char spw;	/* in gbusclock */
 	struct nand_hw_control hw_control;
-	struct mtd_partition *parts[MAX_TXX9NDFMC_DEV];
 };
 
 static struct platform_device *mtd_to_platdev(struct mtd_info *mtd)
@@ -287,7 +286,6 @@
 static int __init txx9ndfmc_probe(struct platform_device *dev)
 {
 	struct txx9ndfmc_platform_data *plat = dev->dev.platform_data;
-	static const char *probes[] = { "cmdlinepart", NULL };
 	int hold, spw;
 	int i;
 	struct txx9ndfmc_drvdata *drvdata;
@@ -333,7 +331,6 @@
 		struct txx9ndfmc_priv *txx9_priv;
 		struct nand_chip *chip;
 		struct mtd_info *mtd;
-		int nr_parts;
 
 		if (!(plat->ch_mask & (1 << i)))
 			continue;
@@ -393,9 +390,7 @@
 		}
 		mtd->name = txx9_priv->mtdname;
 
-		nr_parts = parse_mtd_partitions(mtd, probes,
-						&drvdata->parts[i], 0);
-		mtd_device_register(mtd, drvdata->parts[i], nr_parts);
+		mtd_device_parse_register(mtd, NULL, 0, NULL, 0);
 		drvdata->mtds[i] = mtd;
 	}
 
@@ -421,7 +416,6 @@
 		txx9_priv = chip->priv;
 
 		nand_release(mtd);
-		kfree(drvdata->parts[i]);
 		kfree(txx9_priv->mtdname);
 		kfree(txx9_priv);
 	}
diff -druN linux-libre-3.1-gnu/drivers/mtd/nftlcore.c linux-libre-3.2-gnu/drivers/mtd/nftlcore.c
--- linux-libre-3.1-gnu/drivers/mtd/nftlcore.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nftlcore.c	2012-01-04 18:55:44.000000000 -0500
@@ -63,14 +63,12 @@
 		return;
 	}
 
-	DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name);
+	pr_debug("NFTL: add_mtd for %s\n", mtd->name);
 
 	nftl = kzalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
 
-	if (!nftl) {
-		printk(KERN_WARNING "NFTL: out of memory for data structures\n");
+	if (!nftl)
 		return;
-	}
 
 	nftl->mbd.mtd = mtd;
 	nftl->mbd.devnum = -1;
@@ -132,7 +130,7 @@
 {
 	struct NFTLrecord *nftl = (void *)dev;
 
-	DEBUG(MTD_DEBUG_LEVEL1, "NFTL: remove_dev (i=%d)\n", dev->devnum);
+	pr_debug("NFTL: remove_dev (i=%d)\n", dev->devnum);
 
 	del_mtd_blktrans_dev(dev);
 	kfree(nftl->ReplUnitTable);
@@ -149,7 +147,7 @@
 	struct mtd_oob_ops ops;
 	int res;
 
-	ops.mode = MTD_OOB_PLACE;
+	ops.mode = MTD_OPS_PLACE_OOB;
 	ops.ooboffs = offs & mask;
 	ops.ooblen = len;
 	ops.oobbuf = buf;
@@ -170,7 +168,7 @@
 	struct mtd_oob_ops ops;
 	int res;
 
-	ops.mode = MTD_OOB_PLACE;
+	ops.mode = MTD_OPS_PLACE_OOB;
 	ops.ooboffs = offs & mask;
 	ops.ooblen = len;
 	ops.oobbuf = buf;
@@ -193,7 +191,7 @@
 	struct mtd_oob_ops ops;
 	int res;
 
-	ops.mode = MTD_OOB_PLACE;
+	ops.mode = MTD_OPS_PLACE_OOB;
 	ops.ooboffs = offs & mask;
 	ops.ooblen = mtd->oobsize;
 	ops.oobbuf = oob;
@@ -220,7 +218,7 @@
 
 	/* Normally, we force a fold to happen before we run out of free blocks completely */
 	if (!desperate && nftl->numfreeEUNs < 2) {
-		DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n");
+		pr_debug("NFTL_findfreeblock: there are too few free EUNs\n");
 		return BLOCK_NIL;
 	}
 
@@ -291,8 +289,7 @@
 			if (block == 2) {
 				foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1;
 				if (foldmark == FOLD_MARK_IN_PROGRESS) {
-					DEBUG(MTD_DEBUG_LEVEL1,
-					      "Write Inhibited on EUN %d\n", thisEUN);
+					pr_debug("Write Inhibited on EUN %d\n", thisEUN);
 					inplace = 0;
 				} else {
 					/* There's no other reason not to do inplace,
@@ -357,7 +354,7 @@
 			if (BlockLastState[block] != SECTOR_FREE &&
 			    BlockMap[block] != BLOCK_NIL &&
 			    BlockMap[block] != targetEUN) {
-				DEBUG(MTD_DEBUG_LEVEL1, "Setting inplace to 0. VUC %d, "
+				pr_debug("Setting inplace to 0. VUC %d, "
 				      "block %d was %x lastEUN, "
 				      "and is in EUN %d (%s) %d\n",
 				      thisVUC, block, BlockLastState[block],
@@ -373,14 +370,14 @@
 		    pendingblock < ((thisVUC + 1)* (nftl->EraseSize / 512)) &&
 		    BlockLastState[pendingblock - (thisVUC * (nftl->EraseSize / 512))] !=
 		    SECTOR_FREE) {
-			DEBUG(MTD_DEBUG_LEVEL1, "Pending write not free in EUN %d. "
+			pr_debug("Pending write not free in EUN %d. "
 			      "Folding out of place.\n", targetEUN);
 			inplace = 0;
 		}
 	}
 
 	if (!inplace) {
-		DEBUG(MTD_DEBUG_LEVEL1, "Cannot fold Virtual Unit Chain %d in place. "
+		pr_debug("Cannot fold Virtual Unit Chain %d in place. "
 		      "Trying out-of-place\n", thisVUC);
 		/* We need to find a targetEUN to fold into. */
 		targetEUN = NFTL_findfreeblock(nftl, 1);
@@ -410,7 +407,7 @@
 	   and the Erase Unit into which we are supposed to be copying.
 	   Go for it.
 	*/
-	DEBUG(MTD_DEBUG_LEVEL1,"Folding chain %d into unit %d\n", thisVUC, targetEUN);
+	pr_debug("Folding chain %d into unit %d\n", thisVUC, targetEUN);
 	for (block = 0; block < nftl->EraseSize / 512 ; block++) {
 		unsigned char movebuf[512];
 		int ret;
@@ -428,7 +425,7 @@
 
 		ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),
 				512, &retlen, movebuf);
-		if (ret < 0 && ret != -EUCLEAN) {
+		if (ret < 0 && !mtd_is_bitflip(ret)) {
 			ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block])
 					+ (block * 512), 512, &retlen,
 					movebuf);
@@ -457,7 +454,7 @@
 	   has duplicate chains, we need to free one of the chains because it's not necessary any more.
 	*/
 	thisEUN = nftl->EUNtable[thisVUC];
-	DEBUG(MTD_DEBUG_LEVEL1,"Want to erase\n");
+	pr_debug("Want to erase\n");
 
 	/* For each block in the old chain (except the targetEUN of course),
 	   free it and make it available for future use */
@@ -570,7 +567,7 @@
 				      (writeEUN * nftl->EraseSize) + blockofs,
 				      8, &retlen, (char *)&bci);
 
-			DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n",
+			pr_debug("Status of block %d in EUN %d is %x\n",
 			      block , writeEUN, le16_to_cpu(bci.Status));
 
 			status = bci.Status | bci.Status1;
@@ -623,7 +620,7 @@
 				   but they are reserved for when we're
 				   desperate. Well, now we're desperate.
 				*/
-				DEBUG(MTD_DEBUG_LEVEL1, "Using desperate==1 to find free EUN to accommodate write to VUC %d\n", thisVUC);
+				pr_debug("Using desperate==1 to find free EUN to accommodate write to VUC %d\n", thisVUC);
 				writeEUN = NFTL_findfreeblock(nftl, 1);
 			}
 			if (writeEUN == BLOCK_NIL) {
@@ -776,7 +773,7 @@
 		size_t retlen;
 		int res = mtd->read(mtd, ptr, 512, &retlen, buffer);
 
-		if (res < 0 && res != -EUCLEAN)
+		if (res < 0 && !mtd_is_bitflip(res))
 			return -EIO;
 	}
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/mtd/nftlmount.c linux-libre-3.2-gnu/drivers/mtd/nftlmount.c
--- linux-libre-3.1-gnu/drivers/mtd/nftlmount.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/nftlmount.c	2012-01-04 18:55:44.000000000 -0500
@@ -32,7 +32,7 @@
 
 /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
  *	various device information of the NFTL partition and Bad Unit Table. Update
- *	the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[]
+ *	the ReplUnitTable[] table according to the Bad Unit Table. ReplUnitTable[]
  *	is used for management of Erase Unit in other routines in nftl.c and nftlmount.c
  */
 static int find_boot_record(struct NFTLrecord *nftl)
@@ -297,7 +297,7 @@
  *
  * Return: 0 when succeed, -1 on error.
  *
- *  ToDo: 1. Is it neceressary to check_free_sector after erasing ??
+ *  ToDo: 1. Is it necessary to check_free_sector after erasing ??
  */
 int NFTL_formatblock(struct NFTLrecord *nftl, int block)
 {
@@ -337,7 +337,7 @@
 		nb_erases = le32_to_cpu(uci.WearInfo);
 		nb_erases++;
 
-		/* wrap (almost impossible with current flashs) or free block */
+		/* wrap (almost impossible with current flash) or free block */
 		if (nb_erases == 0)
 			nb_erases = 1;
 
@@ -363,10 +363,10 @@
  *	Mark as 'IGNORE' each incorrect sector. This check is only done if the chain
  *	was being folded when NFTL was interrupted.
  *
- *	The check_free_sectors in this function is neceressary. There is a possible
+ *	The check_free_sectors in this function is necessary. There is a possible
  *	situation that after writing the Data area, the Block Control Information is
  *	not updated according (due to power failure or something) which leaves the block
- *	in an umconsistent state. So we have to check if a block is really FREE in this
+ *	in an inconsistent state. So we have to check if a block is really FREE in this
  *	case. */
 static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_block)
 {
@@ -428,7 +428,7 @@
 
 	for (;;) {
 		length++;
-		/* avoid infinite loops, although this is guaranted not to
+		/* avoid infinite loops, although this is guaranteed not to
 		   happen because of the previous checks */
 		if (length >= nftl->nb_blocks) {
 			printk("nftl: length too long %d !\n", length);
@@ -447,11 +447,11 @@
 /* format_chain: Format an invalid Virtual Unit chain. It frees all the Erase Units in a
  *	Virtual Unit Chain, i.e. all the units are disconnected.
  *
- *	It is not stricly correct to begin from the first block of the chain because
+ *	It is not strictly correct to begin from the first block of the chain because
  *	if we stop the code, we may see again a valid chain if there was a first_block
  *	flag in a block inside it. But is it really a problem ?
  *
- * FixMe: Figure out what the last statesment means. What if power failure when we are
+ * FixMe: Figure out what the last statement means. What if power failure when we are
  *	in the for (;;) loop formatting blocks ??
  */
 static void format_chain(struct NFTLrecord *nftl, unsigned int first_block)
@@ -485,7 +485,7 @@
  *	totally free (only 0xff).
  *
  * Definition: Free Erase Unit -- A properly erased/formatted Free Erase Unit should have meet the
- *	following critia:
+ *	following criteria:
  *	1. */
 static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
 {
@@ -502,7 +502,7 @@
 	erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
 	if (erase_mark != ERASE_MARK) {
 		/* if no erase mark, the block must be totally free. This is
-		   possible in two cases : empty filsystem or interrupted erase (very unlikely) */
+		   possible in two cases : empty filesystem or interrupted erase (very unlikely) */
 		if (check_free_sectors (nftl, block * nftl->EraseSize, nftl->EraseSize, 1) != 0)
 			return -1;
 
@@ -544,7 +544,7 @@
 /* get_fold_mark: Read fold mark from Unit Control Information #2, we use FOLD_MARK_IN_PROGRESS
  *	to indicate that we are in the progression of a Virtual Unit Chain folding. If the UCI #2
  *	is FOLD_MARK_IN_PROGRESS when mounting the NFTL, the (previous) folding process is interrupted
- *	for some reason. A clean up/check of the VUC is neceressary in this case.
+ *	for some reason. A clean up/check of the VUC is necessary in this case.
  *
  * WARNING: return 0 if read error
  */
@@ -657,7 +657,7 @@
 						printk("Block %d: incorrect logical block: %d expected: %d\n",
 						       block, logical_block, first_logical_block);
 						/* the chain is incorrect : we must format it,
-						   but we need to read it completly */
+						   but we need to read it completely */
 						do_format_chain = 1;
 					}
 					if (is_first_block) {
@@ -669,7 +669,7 @@
 							printk("Block %d: incorrectly marked as first block in chain\n",
 							       block);
 							/* the chain is incorrect : we must format it,
-							   but we need to read it completly */
+							   but we need to read it completely */
 							do_format_chain = 1;
 						} else {
 							printk("Block %d: folding in progress - ignoring first block flag\n",
diff -druN linux-libre-3.1-gnu/drivers/mtd/ofpart.c linux-libre-3.2-gnu/drivers/mtd/ofpart.c
--- linux-libre-3.1-gnu/drivers/mtd/ofpart.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/ofpart.c	2012-01-04 18:55:44.000000000 -0500
@@ -20,14 +20,23 @@
 #include <linux/slab.h>
 #include <linux/mtd/partitions.h>
 
-int __devinit of_mtd_parse_partitions(struct device *dev,
-                                      struct device_node *node,
-                                      struct mtd_partition **pparts)
+static int parse_ofpart_partitions(struct mtd_info *master,
+				   struct mtd_partition **pparts,
+				   struct mtd_part_parser_data *data)
 {
+	struct device_node *node;
 	const char *partname;
 	struct device_node *pp;
 	int nr_parts, i;
 
+
+	if (!data)
+		return 0;
+
+	node = data->of_node;
+	if (!node)
+		return 0;
+
 	/* First count the subnodes */
 	pp = NULL;
 	nr_parts = 0;
@@ -69,7 +78,7 @@
 
 	if (!i) {
 		of_node_put(pp);
-		dev_err(dev, "No valid partition found on %s\n", node->full_name);
+		pr_err("No valid partition found on %s\n", node->full_name);
 		kfree(*pparts);
 		*pparts = NULL;
 		return -EINVAL;
@@ -77,6 +86,99 @@
 
 	return nr_parts;
 }
-EXPORT_SYMBOL(of_mtd_parse_partitions);
+
+static struct mtd_part_parser ofpart_parser = {
+	.owner = THIS_MODULE,
+	.parse_fn = parse_ofpart_partitions,
+	.name = "ofpart",
+};
+
+static int parse_ofoldpart_partitions(struct mtd_info *master,
+				      struct mtd_partition **pparts,
+				      struct mtd_part_parser_data *data)
+{
+	struct device_node *dp;
+	int i, plen, nr_parts;
+	const struct {
+		__be32 offset, len;
+	} *part;
+	const char *names;
+
+	if (!data)
+		return 0;
+
+	dp = data->of_node;
+	if (!dp)
+		return 0;
+
+	part = of_get_property(dp, "partitions", &plen);
+	if (!part)
+		return 0; /* No partitions found */
+
+	pr_warning("Device tree uses obsolete partition map binding: %s\n",
+			dp->full_name);
+
+	nr_parts = plen / sizeof(part[0]);
+
+	*pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL);
+	if (!pparts)
+		return -ENOMEM;
+
+	names = of_get_property(dp, "partition-names", &plen);
+
+	for (i = 0; i < nr_parts; i++) {
+		(*pparts)[i].offset = be32_to_cpu(part->offset);
+		(*pparts)[i].size   = be32_to_cpu(part->len) & ~1;
+		/* bit 0 set signifies read only partition */
+		if (be32_to_cpu(part->len) & 1)
+			(*pparts)[i].mask_flags = MTD_WRITEABLE;
+
+		if (names && (plen > 0)) {
+			int len = strlen(names) + 1;
+
+			(*pparts)[i].name = (char *)names;
+			plen -= len;
+			names += len;
+		} else {
+			(*pparts)[i].name = "unnamed";
+		}
+
+		part++;
+	}
+
+	return nr_parts;
+}
+
+static struct mtd_part_parser ofoldpart_parser = {
+	.owner = THIS_MODULE,
+	.parse_fn = parse_ofoldpart_partitions,
+	.name = "ofoldpart",
+};
+
+static int __init ofpart_parser_init(void)
+{
+	int rc;
+	rc = register_mtd_parser(&ofpart_parser);
+	if (rc)
+		goto out;
+
+	rc = register_mtd_parser(&ofoldpart_parser);
+	if (!rc)
+		return 0;
+
+	deregister_mtd_parser(&ofoldpart_parser);
+out:
+	return rc;
+}
+
+module_init(ofpart_parser_init);
 
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree");
+MODULE_AUTHOR("Vitaly Wool, David Gibson");
+/*
+ * When MTD core cannot find the requested parser, it tries to load the module
+ * with the same name. Since we provide the ofoldpart parser, we should have
+ * the corresponding alias.
+ */
+MODULE_ALIAS("ofoldpart");
diff -druN linux-libre-3.1-gnu/drivers/mtd/onenand/generic.c linux-libre-3.2-gnu/drivers/mtd/onenand/generic.c
--- linux-libre-3.1-gnu/drivers/mtd/onenand/generic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/onenand/generic.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,11 +30,8 @@
  */
 #define DRIVER_NAME	"onenand-flash"
 
-static const char *part_probes[] = { "cmdlinepart", NULL,  };
-
 struct onenand_info {
 	struct mtd_info		mtd;
-	struct mtd_partition	*parts;
 	struct onenand_chip	onenand;
 };
 
@@ -73,13 +70,9 @@
 		goto out_iounmap;
 	}
 
-	err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
-	if (err > 0)
-		mtd_device_register(&info->mtd, info->parts, err);
-	else if (err <= 0 && pdata && pdata->parts)
-		mtd_device_register(&info->mtd, pdata->parts, pdata->nr_parts);
-	else
-		err = mtd_device_register(&info->mtd, NULL, 0);
+	err = mtd_device_parse_register(&info->mtd, NULL, 0,
+			pdata ? pdata->parts : NULL,
+			pdata ? pdata->nr_parts : 0);
 
 	platform_set_drvdata(pdev, info);
 
@@ -104,7 +97,6 @@
 	platform_set_drvdata(pdev, NULL);
 
 	if (info) {
-		mtd_device_unregister(&info->mtd);
 		onenand_release(&info->mtd);
 		release_mem_region(res->start, size);
 		iounmap(info->onenand.base);
diff -druN linux-libre-3.1-gnu/drivers/mtd/onenand/omap2.c linux-libre-3.2-gnu/drivers/mtd/onenand/omap2.c
--- linux-libre-3.1-gnu/drivers/mtd/onenand/omap2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/onenand/omap2.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,7 +40,7 @@
 #include <asm/mach/flash.h>
 #include <plat/gpmc.h>
 #include <plat/onenand.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
 
 #include <plat/dma.h>
 
@@ -57,7 +57,6 @@
 	unsigned long phys_base;
 	int gpio_irq;
 	struct mtd_info mtd;
-	struct mtd_partition *parts;
 	struct onenand_chip onenand;
 	struct completion irq_done;
 	struct completion dma_done;
@@ -67,8 +66,6 @@
 	struct regulator *regulator;
 };
 
-static const char *part_probes[] = { "cmdlinepart", NULL,  };
-
 static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
 {
 	struct omap2_onenand *c = data;
@@ -741,6 +738,7 @@
 		c->regulator = regulator_get(&pdev->dev, "vonenand");
 		if (IS_ERR(c->regulator)) {
 			dev_err(&pdev->dev,  "Failed to get regulator\n");
+			r = PTR_ERR(c->regulator);
 			goto err_release_dma;
 		}
 		c->onenand.enable = omap2_onenand_enable;
@@ -753,13 +751,9 @@
 	if ((r = onenand_scan(&c->mtd, 1)) < 0)
 		goto err_release_regulator;
 
-	r = parse_mtd_partitions(&c->mtd, part_probes, &c->parts, 0);
-	if (r > 0)
-		r = mtd_device_register(&c->mtd, c->parts, r);
-	else if (pdata->parts != NULL)
-		r = mtd_device_register(&c->mtd, pdata->parts, pdata->nr_parts);
-	else
-		r = mtd_device_register(&c->mtd, NULL, 0);
+	r = mtd_device_parse_register(&c->mtd, NULL, 0,
+			pdata ? pdata->parts : NULL,
+			pdata ? pdata->nr_parts : 0);
 	if (r)
 		goto err_release_onenand;
 
@@ -786,7 +780,6 @@
 err_free_cs:
 	gpmc_cs_free(c->gpmc_cs);
 err_kfree:
-	kfree(c->parts);
 	kfree(c);
 
 	return r;
@@ -809,7 +802,6 @@
 	iounmap(c->onenand.base);
 	release_mem_region(c->phys_base, ONENAND_IO_SIZE);
 	gpmc_cs_free(c->gpmc_cs);
-	kfree(c->parts);
 	kfree(c);
 
 	return 0;
diff -druN linux-libre-3.1-gnu/drivers/mtd/onenand/onenand_base.c linux-libre-3.2-gnu/drivers/mtd/onenand/onenand_base.c
--- linux-libre-3.1-gnu/drivers/mtd/onenand/onenand_base.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/onenand/onenand_base.c	2012-01-04 18:55:44.000000000 -0500
@@ -1015,7 +1015,7 @@
 }
 
 /**
- * onenand_transfer_auto_oob - [Internal] oob auto-placement transfer
+ * onenand_transfer_auto_oob - [INTERN] oob auto-placement transfer
  * @param mtd		MTD device structure
  * @param buf		destination address
  * @param column	oob offset to read from
@@ -1079,7 +1079,7 @@
 		return status;
 
 	/* check if we failed due to uncorrectable error */
-	if (status != -EBADMSG && status != ONENAND_BBT_READ_ECC_ERROR)
+	if (!mtd_is_eccerr(status) && status != ONENAND_BBT_READ_ECC_ERROR)
 		return status;
 
 	/* check if address lies in MLC region */
@@ -1122,10 +1122,10 @@
 	int ret = 0;
 	int writesize = this->writesize;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %i\n",
-	      __func__, (unsigned int) from, (int) len);
+	pr_debug("%s: from = 0x%08x, len = %i\n", __func__, (unsigned int)from,
+			(int)len);
 
-	if (ops->mode == MTD_OOB_AUTO)
+	if (ops->mode == MTD_OPS_AUTO_OOB)
 		oobsize = this->ecclayout->oobavail;
 	else
 		oobsize = mtd->oobsize;
@@ -1159,7 +1159,7 @@
 			if (unlikely(ret))
 				ret = onenand_recover_lsb(mtd, from, ret);
 			onenand_update_bufferram(mtd, from, !ret);
-			if (ret == -EBADMSG)
+			if (mtd_is_eccerr(ret))
 				ret = 0;
 			if (ret)
 				break;
@@ -1170,7 +1170,7 @@
 			thisooblen = oobsize - oobcolumn;
 			thisooblen = min_t(int, thisooblen, ooblen - oobread);
 
-			if (ops->mode == MTD_OOB_AUTO)
+			if (ops->mode == MTD_OPS_AUTO_OOB)
 				onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen);
 			else
 				this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen);
@@ -1226,10 +1226,10 @@
 	int ret = 0, boundary = 0;
 	int writesize = this->writesize;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %i\n",
-			__func__, (unsigned int) from, (int) len);
+	pr_debug("%s: from = 0x%08x, len = %i\n", __func__, (unsigned int)from,
+			(int)len);
 
-	if (ops->mode == MTD_OOB_AUTO)
+	if (ops->mode == MTD_OPS_AUTO_OOB)
 		oobsize = this->ecclayout->oobavail;
 	else
 		oobsize = mtd->oobsize;
@@ -1255,7 +1255,7 @@
 			this->command(mtd, ONENAND_CMD_READ, from, writesize);
  			ret = this->wait(mtd, FL_READING);
  			onenand_update_bufferram(mtd, from, !ret);
-			if (ret == -EBADMSG)
+			if (mtd_is_eccerr(ret))
 				ret = 0;
  		}
  	}
@@ -1291,7 +1291,7 @@
 			thisooblen = oobsize - oobcolumn;
 			thisooblen = min_t(int, thisooblen, ooblen - oobread);
 
-			if (ops->mode == MTD_OOB_AUTO)
+			if (ops->mode == MTD_OPS_AUTO_OOB)
 				onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen);
 			else
 				this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen);
@@ -1315,7 +1315,7 @@
  		/* Now wait for load */
  		ret = this->wait(mtd, FL_READING);
  		onenand_update_bufferram(mtd, from, !ret);
-		if (ret == -EBADMSG)
+		if (mtd_is_eccerr(ret))
 			ret = 0;
  	}
 
@@ -1351,19 +1351,19 @@
 	struct mtd_ecc_stats stats;
 	int read = 0, thislen, column, oobsize;
 	size_t len = ops->ooblen;
-	mtd_oob_mode_t mode = ops->mode;
+	unsigned int mode = ops->mode;
 	u_char *buf = ops->oobbuf;
 	int ret = 0, readcmd;
 
 	from += ops->ooboffs;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %i\n",
-		__func__, (unsigned int) from, (int) len);
+	pr_debug("%s: from = 0x%08x, len = %i\n", __func__, (unsigned int)from,
+			(int)len);
 
 	/* Initialize return length value */
 	ops->oobretlen = 0;
 
-	if (mode == MTD_OOB_AUTO)
+	if (mode == MTD_OPS_AUTO_OOB)
 		oobsize = this->ecclayout->oobavail;
 	else
 		oobsize = mtd->oobsize;
@@ -1403,13 +1403,13 @@
 		if (unlikely(ret))
 			ret = onenand_recover_lsb(mtd, from, ret);
 
-		if (ret && ret != -EBADMSG) {
+		if (ret && !mtd_is_eccerr(ret)) {
 			printk(KERN_ERR "%s: read failed = 0x%x\n",
 				__func__, ret);
 			break;
 		}
 
-		if (mode == MTD_OOB_AUTO)
+		if (mode == MTD_OPS_AUTO_OOB)
 			onenand_transfer_auto_oob(mtd, buf, column, thislen);
 		else
 			this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
@@ -1487,10 +1487,10 @@
 	int ret;
 
 	switch (ops->mode) {
-	case MTD_OOB_PLACE:
-	case MTD_OOB_AUTO:
+	case MTD_OPS_PLACE_OOB:
+	case MTD_OPS_AUTO_OOB:
 		break;
-	case MTD_OOB_RAW:
+	case MTD_OPS_RAW:
 		/* Not implemented yet */
 	default:
 		return -EINVAL;
@@ -1576,8 +1576,8 @@
 	size_t len = ops->ooblen;
 	u_char *buf = ops->oobbuf;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %zi\n",
-		__func__, (unsigned int) from, len);
+	pr_debug("%s: from = 0x%08x, len = %zi\n", __func__, (unsigned int)from,
+			len);
 
 	/* Initialize return value */
 	ops->oobretlen = 0;
@@ -1750,8 +1750,8 @@
 	/* Wait for any existing operation to clear */
 	onenand_panic_wait(mtd);
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
-		__func__, (unsigned int) to, (int) len);
+	pr_debug("%s: to = 0x%08x, len = %i\n", __func__, (unsigned int)to,
+			(int)len);
 
 	/* Initialize retlen, in case of early exit */
 	*retlen = 0;
@@ -1821,7 +1821,7 @@
 }
 
 /**
- * onenand_fill_auto_oob - [Internal] oob auto-placement transfer
+ * onenand_fill_auto_oob - [INTERN] oob auto-placement transfer
  * @param mtd		MTD device structure
  * @param oob_buf	oob buffer
  * @param buf		source address
@@ -1883,8 +1883,8 @@
 	u_char *oobbuf;
 	int ret = 0, cmd;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
-		__func__, (unsigned int) to, (int) len);
+	pr_debug("%s: to = 0x%08x, len = %i\n", __func__, (unsigned int)to,
+			(int)len);
 
 	/* Initialize retlen, in case of early exit */
 	ops->retlen = 0;
@@ -1908,7 +1908,7 @@
 	if (!len)
 		return 0;
 
-	if (ops->mode == MTD_OOB_AUTO)
+	if (ops->mode == MTD_OPS_AUTO_OOB)
 		oobsize = this->ecclayout->oobavail;
 	else
 		oobsize = mtd->oobsize;
@@ -1945,7 +1945,7 @@
 				/* We send data to spare ram with oobsize
 				 * to prevent byte access */
 				memset(oobbuf, 0xff, mtd->oobsize);
-				if (ops->mode == MTD_OOB_AUTO)
+				if (ops->mode == MTD_OPS_AUTO_OOB)
 					onenand_fill_auto_oob(mtd, oobbuf, oob, oobcolumn, thisooblen);
 				else
 					memcpy(oobbuf + oobcolumn, oob, thisooblen);
@@ -2055,7 +2055,7 @@
 
 
 /**
- * onenand_write_oob_nolock - [Internal] OneNAND write out-of-band
+ * onenand_write_oob_nolock - [INTERN] OneNAND write out-of-band
  * @param mtd		MTD device structure
  * @param to		offset to write to
  * @param len		number of bytes to write
@@ -2074,17 +2074,17 @@
 	u_char *oobbuf;
 	size_t len = ops->ooblen;
 	const u_char *buf = ops->oobbuf;
-	mtd_oob_mode_t mode = ops->mode;
+	unsigned int mode = ops->mode;
 
 	to += ops->ooboffs;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
-		__func__, (unsigned int) to, (int) len);
+	pr_debug("%s: to = 0x%08x, len = %i\n", __func__, (unsigned int)to,
+			(int)len);
 
 	/* Initialize retlen, in case of early exit */
 	ops->oobretlen = 0;
 
-	if (mode == MTD_OOB_AUTO)
+	if (mode == MTD_OPS_AUTO_OOB)
 		oobsize = this->ecclayout->oobavail;
 	else
 		oobsize = mtd->oobsize;
@@ -2128,7 +2128,7 @@
 		/* We send data to spare ram with oobsize
 		 * to prevent byte access */
 		memset(oobbuf, 0xff, mtd->oobsize);
-		if (mode == MTD_OOB_AUTO)
+		if (mode == MTD_OPS_AUTO_OOB)
 			onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen);
 		else
 			memcpy(oobbuf + column, buf, thislen);
@@ -2217,10 +2217,10 @@
 	int ret;
 
 	switch (ops->mode) {
-	case MTD_OOB_PLACE:
-	case MTD_OOB_AUTO:
+	case MTD_OPS_PLACE_OOB:
+	case MTD_OPS_AUTO_OOB:
 		break;
-	case MTD_OOB_RAW:
+	case MTD_OPS_RAW:
 		/* Not implemented yet */
 	default:
 		return -EINVAL;
@@ -2281,7 +2281,7 @@
 }
 
 /**
- * onenand_multiblock_erase - [Internal] erase block(s) using multiblock erase
+ * onenand_multiblock_erase - [INTERN] erase block(s) using multiblock erase
  * @param mtd		MTD device structure
  * @param instr		erase instruction
  * @param region	erase region
@@ -2397,7 +2397,7 @@
 
 
 /**
- * onenand_block_by_block_erase - [Internal] erase block(s) using regular erase
+ * onenand_block_by_block_erase - [INTERN] erase block(s) using regular erase
  * @param mtd		MTD device structure
  * @param instr		erase instruction
  * @param region	erase region
@@ -2489,8 +2489,9 @@
 	struct mtd_erase_region_info *region = NULL;
 	loff_t region_offset = 0;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: start=0x%012llx, len=%llu\n", __func__,
-	      (unsigned long long) instr->addr, (unsigned long long) instr->len);
+	pr_debug("%s: start=0x%012llx, len=%llu\n", __func__,
+			(unsigned long long)instr->addr,
+			(unsigned long long)instr->len);
 
 	/* Do not allow erase past end of device */
 	if (unlikely((len + addr) > mtd->size)) {
@@ -2558,7 +2559,7 @@
  */
 static void onenand_sync(struct mtd_info *mtd)
 {
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: called\n", __func__);
+	pr_debug("%s: called\n", __func__);
 
 	/* Grab the lock and see if the device is available */
 	onenand_get_device(mtd, FL_SYNCING);
@@ -2602,7 +2603,7 @@
 	struct bbm_info *bbm = this->bbm;
 	u_char buf[2] = {0, 0};
 	struct mtd_oob_ops ops = {
-		.mode = MTD_OOB_PLACE,
+		.mode = MTD_OPS_PLACE_OOB,
 		.ooblen = 2,
 		.oobbuf = buf,
 		.ooboffs = 0,
@@ -2922,7 +2923,7 @@
 }
 
 /**
- * onenand_otp_write_oob_nolock - [Internal] OneNAND write out-of-band, specific to OTP
+ * onenand_otp_write_oob_nolock - [INTERN] OneNAND write out-of-band, specific to OTP
  * @param mtd		MTD device structure
  * @param to		offset to write to
  * @param len		number of bytes to write
@@ -3170,7 +3171,7 @@
 		this->command(mtd, ONENAND_CMD_RESET, 0, 0);
 		this->wait(mtd, FL_RESETING);
 	} else {
-		ops.mode = MTD_OOB_PLACE;
+		ops.mode = MTD_OPS_PLACE_OOB;
 		ops.ooblen = len;
 		ops.oobbuf = buf;
 		ops.ooboffs = 0;
@@ -3429,6 +3430,19 @@
 		else if (numbufs == 1) {
 			this->options |= ONENAND_HAS_4KB_PAGE;
 			this->options |= ONENAND_HAS_CACHE_PROGRAM;
+			/*
+			 * There are two different 4KiB pagesize chips
+			 * and no way to detect it by H/W config values.
+			 *
+			 * To detect the correct NOP for each chips,
+			 * It should check the version ID as workaround.
+			 *
+			 * Now it has as following
+			 * KFM4G16Q4M has NOP 4 with version ID 0x0131
+			 * KFM4G16Q5M has NOP 1 with versoin ID 0x013e
+			 */
+			if ((this->version_id & 0xf) == 0xe)
+				this->options |= ONENAND_HAS_NOP_1;
 		}
 
 	case ONENAND_DEVICE_DENSITY_2Gb:
@@ -3663,7 +3677,7 @@
 	int i, ret;
 	int block;
 	struct mtd_oob_ops ops = {
-		.mode = MTD_OOB_PLACE,
+		.mode = MTD_OPS_PLACE_OOB,
 		.ooboffs = 0,
 		.ooblen	= mtd->oobsize,
 		.datbuf	= NULL,
@@ -4054,6 +4068,8 @@
 			this->ecclayout = &onenand_oob_128;
 			mtd->subpage_sft = 2;
 		}
+		if (ONENAND_IS_NOP_1(this))
+			mtd->subpage_sft = 0;
 		break;
 	case 64:
 		this->ecclayout = &onenand_oob_64;
diff -druN linux-libre-3.1-gnu/drivers/mtd/onenand/onenand_bbt.c linux-libre-3.2-gnu/drivers/mtd/onenand/onenand_bbt.c
--- linux-libre-3.1-gnu/drivers/mtd/onenand/onenand_bbt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/onenand/onenand_bbt.c	2012-01-04 18:55:44.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/onenand.h>
+#include <linux/export.h>
 
 /**
  * check_short_pattern - [GENERIC] check if a pattern is in the buffer
@@ -80,7 +81,7 @@
 	startblock = 0;
 	from = 0;
 
-	ops.mode = MTD_OOB_PLACE;
+	ops.mode = MTD_OPS_PLACE_OOB;
 	ops.ooblen = readlen;
 	ops.oobbuf = buf;
 	ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
@@ -153,7 +154,7 @@
 	block = (int) (onenand_block(this, offs) << 1);
 	res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03;
 
-	DEBUG(MTD_DEBUG_LEVEL2, "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
+	pr_debug("onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
 		(unsigned int) offs, block >> 1, res);
 
 	switch ((int) res) {
@@ -188,10 +189,8 @@
 	len = this->chipsize >> (this->erase_shift + 2);
 	/* Allocate memory (2bit per block) and clear the memory bad block table */
 	bbm->bbt = kzalloc(len, GFP_KERNEL);
-	if (!bbm->bbt) {
-		printk(KERN_ERR "onenand_scan_bbt: Out of memory\n");
+	if (!bbm->bbt)
 		return -ENOMEM;
-	}
 
 	/* Set the bad block position */
 	bbm->badblockpos = ONENAND_BADBLOCK_POS;
diff -druN linux-libre-3.1-gnu/drivers/mtd/onenand/samsung.c linux-libre-3.2-gnu/drivers/mtd/onenand/samsung.c
--- linux-libre-3.1-gnu/drivers/mtd/onenand/samsung.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/onenand/samsung.c	2012-01-04 18:55:44.000000000 -0500
@@ -147,7 +147,6 @@
 	struct resource *dma_res;
 	unsigned long	phys_base;
 	struct completion	complete;
-	struct mtd_partition *parts;
 };
 
 #define CMD_MAP_00(dev, addr)		(dev->cmd_map(MAP_00, ((addr) << 1)))
@@ -157,8 +156,6 @@
 
 static struct s3c_onenand *onenand;
 
-static const char *part_probes[] = { "cmdlinepart", NULL, };
-
 static inline int s3c_read_reg(int offset)
 {
 	return readl(onenand->base + offset);
@@ -1017,13 +1014,9 @@
 	if (s3c_read_reg(MEM_CFG_OFFSET) & ONENAND_SYS_CFG1_SYNC_READ)
 		dev_info(&onenand->pdev->dev, "OneNAND Sync. Burst Read enabled\n");
 
-	err = parse_mtd_partitions(mtd, part_probes, &onenand->parts, 0);
-	if (err > 0)
-		mtd_device_register(mtd, onenand->parts, err);
-	else if (err <= 0 && pdata && pdata->parts)
-		mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
-	else
-		err = mtd_device_register(mtd, NULL, 0);
+	err = mtd_device_parse_register(mtd, NULL, 0,
+					pdata ? pdata->parts : NULL,
+					pdata ? pdata->nr_parts : 0);
 
 	platform_set_drvdata(pdev, mtd);
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/redboot.c linux-libre-3.2-gnu/drivers/mtd/redboot.c
--- linux-libre-3.1-gnu/drivers/mtd/redboot.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/redboot.c	2012-01-04 18:55:44.000000000 -0500
@@ -28,6 +28,7 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/module.h>
 
 struct fis_image_desc {
     unsigned char name[16];      // Null terminated name
@@ -56,8 +57,8 @@
 }
 
 static int parse_redboot_partitions(struct mtd_info *master,
-                             struct mtd_partition **pparts,
-                             unsigned long fis_origin)
+				    struct mtd_partition **pparts,
+				    struct mtd_part_parser_data *data)
 {
 	int nrparts = 0;
 	struct fis_image_desc *buf;
@@ -197,11 +198,10 @@
 			goto out;
 		}
 		new_fl->img = &buf[i];
-                if (fis_origin) {
-                        buf[i].flash_base -= fis_origin;
-                } else {
-                        buf[i].flash_base &= master->size-1;
-                }
+		if (data && data->origin)
+			buf[i].flash_base -= data->origin;
+		else
+			buf[i].flash_base &= master->size-1;
 
 		/* I'm sure the JFFS2 code has done me permanent damage.
 		 * I now think the following is _normal_
@@ -297,6 +297,9 @@
 	.name = "RedBoot",
 };
 
+/* mtd parsers will request the module by parser name */
+MODULE_ALIAS("RedBoot");
+
 static int __init redboot_parser_init(void)
 {
 	return register_mtd_parser(&redboot_parser);
diff -druN linux-libre-3.1-gnu/drivers/mtd/rfd_ftl.c linux-libre-3.2-gnu/drivers/mtd/rfd_ftl.c
--- linux-libre-3.1-gnu/drivers/mtd/rfd_ftl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/rfd_ftl.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
+#include <linux/module.h>
 
 #include <asm/types.h>
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/sm_ftl.c linux-libre-3.2-gnu/drivers/mtd/sm_ftl.c
--- linux-libre-3.1-gnu/drivers/mtd/sm_ftl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/sm_ftl.c	2012-01-04 18:55:44.000000000 -0500
@@ -34,7 +34,7 @@
 MODULE_PARM_DESC(debug, "Debug level (0-2)");
 
 
-/* ------------------- sysfs attributtes ---------------------------------- */
+/* ------------------- sysfs attributes ---------------------------------- */
 struct sm_sysfs_attribute {
 	struct device_attribute dev_attr;
 	char *data;
@@ -138,7 +138,7 @@
 	if ((lba[0] & 0xF8) != 0x10)
 		return -2;
 
-	/* check parity - endianess doesn't matter */
+	/* check parity - endianness doesn't matter */
 	if (hweight16(*(uint16_t *)lba) & 1)
 		return -2;
 
@@ -147,7 +147,7 @@
 
 
 /*
- * Read LBA asscociated with block
+ * Read LBA associated with block
  * returns -1, if block is erased
  * returns -2 if error happens
  */
@@ -252,11 +252,11 @@
 		return 0;
 	}
 
-	/* User might not need the oob, but we do for data vertification */
+	/* User might not need the oob, but we do for data verification */
 	if (!oob)
 		oob = &tmp_oob;
 
-	ops.mode = ftl->smallpagenand ? MTD_OOB_RAW : MTD_OOB_PLACE;
+	ops.mode = ftl->smallpagenand ? MTD_OPS_RAW : MTD_OPS_PLACE_OOB;
 	ops.ooboffs = 0;
 	ops.ooblen = SM_OOB_SIZE;
 	ops.oobbuf = (void *)oob;
@@ -276,12 +276,12 @@
 			return ret;
 	}
 
-	/* Unfortunelly, oob read will _always_ succeed,
+	/* Unfortunately, oob read will _always_ succeed,
 		despite card removal..... */
 	ret = mtd->read_oob(mtd, sm_mkoffset(ftl, zone, block, boffset), &ops);
 
 	/* Test for unknown errors */
-	if (ret != 0 && ret != -EUCLEAN && ret != -EBADMSG) {
+	if (ret != 0 && !mtd_is_bitflip_or_eccerr(ret)) {
 		dbg("read of block %d at zone %d, failed due to error (%d)",
 			block, zone, ret);
 		goto again;
@@ -306,7 +306,7 @@
 	}
 
 	/* Test ECC*/
-	if (ret == -EBADMSG ||
+	if (mtd_is_eccerr(ret) ||
 		(ftl->smallpagenand && sm_correct_sector(buffer, oob))) {
 
 		dbg("read of block %d at zone %d, failed due to ECC error",
@@ -336,7 +336,7 @@
 	if (ftl->unstable)
 		return -EIO;
 
-	ops.mode = ftl->smallpagenand ? MTD_OOB_RAW : MTD_OOB_PLACE;
+	ops.mode = ftl->smallpagenand ? MTD_OPS_RAW : MTD_OPS_PLACE_OOB;
 	ops.len = SM_SECTOR_SIZE;
 	ops.datbuf = buffer;
 	ops.ooboffs = 0;
@@ -447,14 +447,14 @@
 
 	/* We aren't checking the return value, because we don't care */
 	/* This also fails on fake xD cards, but I guess these won't expose
-		any bad blocks till fail completly */
+		any bad blocks till fail completely */
 	for (boffset = 0; boffset < ftl->block_size; boffset += SM_SECTOR_SIZE)
 		sm_write_sector(ftl, zone, block, boffset, NULL, &oob);
 }
 
 /*
  * Erase a block within a zone
- * If erase succedes, it updates free block fifo, otherwise marks block as bad
+ * If erase succeeds, it updates free block fifo, otherwise marks block as bad
  */
 static int sm_erase_block(struct sm_ftl *ftl, int zone_num, uint16_t block,
 			  int put_free)
@@ -510,7 +510,7 @@
 	complete(&ftl->erase_completion);
 }
 
-/* Throughtly test that block is valid. */
+/* Thoroughly test that block is valid. */
 static int sm_check_block(struct sm_ftl *ftl, int zone, int block)
 {
 	int boffset;
@@ -526,7 +526,7 @@
 	for (boffset = 0; boffset < ftl->block_size;
 					boffset += SM_SECTOR_SIZE) {
 
-		/* This shoudn't happen anyway */
+		/* This shouldn't happen anyway */
 		if (sm_read_sector(ftl, zone, block, boffset, NULL, &oob))
 			return -2;
 
diff -druN linux-libre-3.1-gnu/drivers/mtd/ssfdc.c linux-libre-3.2-gnu/drivers/mtd/ssfdc.c
--- linux-libre-3.1-gnu/drivers/mtd/ssfdc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/ssfdc.c	2012-01-04 18:55:44.000000000 -0500
@@ -135,8 +135,7 @@
 				/* Found */
 				cis_sector = (int)(offset >> SECTOR_SHIFT);
 			} else {
-				DEBUG(MTD_DEBUG_LEVEL1,
-					"SSFDC_RO: CIS/IDI sector not found"
+				pr_debug("SSFDC_RO: CIS/IDI sector not found"
 					" on %s (mtd%d)\n", mtd->name,
 					mtd->index);
 			}
@@ -170,7 +169,7 @@
 	struct mtd_oob_ops ops;
 	int ret;
 
-	ops.mode = MTD_OOB_RAW;
+	ops.mode = MTD_OPS_RAW;
 	ops.ooboffs = 0;
 	ops.ooblen = OOB_SIZE;
 	ops.oobbuf = buf;
@@ -221,8 +220,7 @@
 			block_address >>= 1;
 
 			if (get_parity(block_address, 10) != parity) {
-				DEBUG(MTD_DEBUG_LEVEL0,
-					"SSFDC_RO: logical address field%d"
+				pr_debug("SSFDC_RO: logical address field%d"
 					"parity error(0x%04X)\n", j+1,
 					block_address);
 			} else {
@@ -235,7 +233,7 @@
 	if (!ok)
 		block_address = -2;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "SSFDC_RO: get_logical_address() %d\n",
+	pr_debug("SSFDC_RO: get_logical_address() %d\n",
 		block_address);
 
 	return block_address;
@@ -249,7 +247,7 @@
 	int ret, block_address, phys_block;
 	struct mtd_info *mtd = ssfdc->mbd.mtd;
 
-	DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: build_block_map() nblks=%d (%luK)\n",
+	pr_debug("SSFDC_RO: build_block_map() nblks=%d (%luK)\n",
 	      ssfdc->map_len,
 	      (unsigned long)ssfdc->map_len * ssfdc->erase_size / 1024);
 
@@ -262,8 +260,7 @@
 
 		ret = read_raw_oob(mtd, offset, oob_buf);
 		if (ret < 0) {
-			DEBUG(MTD_DEBUG_LEVEL0,
-				"SSFDC_RO: mtd read_oob() failed at %lu\n",
+			pr_debug("SSFDC_RO: mtd read_oob() failed at %lu\n",
 				offset);
 			return -1;
 		}
@@ -279,8 +276,7 @@
 			ssfdc->logic_block_map[block_address] =
 				(unsigned short)phys_block;
 
-			DEBUG(MTD_DEBUG_LEVEL2,
-				"SSFDC_RO: build_block_map() phys_block=%d,"
+			pr_debug("SSFDC_RO: build_block_map() phys_block=%d,"
 				"logic_block_addr=%d, zone=%d\n",
 				phys_block, block_address, zone_index);
 		}
@@ -304,11 +300,8 @@
 		return;
 
 	ssfdc = kzalloc(sizeof(struct ssfdcr_record), GFP_KERNEL);
-	if (!ssfdc) {
-		printk(KERN_WARNING
-			"SSFDC_RO: out of memory for data structures\n");
+	if (!ssfdc)
 		return;
-	}
 
 	ssfdc->mbd.mtd = mtd;
 	ssfdc->mbd.devnum = -1;
@@ -319,8 +312,7 @@
 	ssfdc->erase_size = mtd->erasesize;
 	ssfdc->map_len = (u32)mtd->size / mtd->erasesize;
 
-	DEBUG(MTD_DEBUG_LEVEL1,
-		"SSFDC_RO: cis_block=%d,erase_size=%d,map_len=%d,n_zones=%d\n",
+	pr_debug("SSFDC_RO: cis_block=%d,erase_size=%d,map_len=%d,n_zones=%d\n",
 		ssfdc->cis_block, ssfdc->erase_size, ssfdc->map_len,
 		DIV_ROUND_UP(ssfdc->map_len, MAX_PHYS_BLK_PER_ZONE));
 
@@ -331,7 +323,7 @@
 	ssfdc->cylinders = (unsigned short)(((u32)mtd->size >> SECTOR_SHIFT) /
 			((long)ssfdc->sectors * (long)ssfdc->heads));
 
-	DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: using C:%d H:%d S:%d == %ld sects\n",
+	pr_debug("SSFDC_RO: using C:%d H:%d S:%d == %ld sects\n",
 		ssfdc->cylinders, ssfdc->heads , ssfdc->sectors,
 		(long)ssfdc->cylinders * (long)ssfdc->heads *
 		(long)ssfdc->sectors);
@@ -342,11 +334,8 @@
 	/* Allocate logical block map */
 	ssfdc->logic_block_map = kmalloc(sizeof(ssfdc->logic_block_map[0]) *
 					 ssfdc->map_len, GFP_KERNEL);
-	if (!ssfdc->logic_block_map) {
-		printk(KERN_WARNING
-			"SSFDC_RO: out of memory for data structures\n");
+	if (!ssfdc->logic_block_map)
 		goto out_err;
-	}
 	memset(ssfdc->logic_block_map, 0xff, sizeof(ssfdc->logic_block_map[0]) *
 		ssfdc->map_len);
 
@@ -371,7 +360,7 @@
 {
 	struct ssfdcr_record *ssfdc = (struct ssfdcr_record *)dev;
 
-	DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: remove_dev (i=%d)\n", dev->devnum);
+	pr_debug("SSFDC_RO: remove_dev (i=%d)\n", dev->devnum);
 
 	del_mtd_blktrans_dev(dev);
 	kfree(ssfdc->logic_block_map);
@@ -387,8 +376,7 @@
 	offset = (int)(logic_sect_no % sectors_per_block);
 	block_address = (int)(logic_sect_no / sectors_per_block);
 
-	DEBUG(MTD_DEBUG_LEVEL3,
-		"SSFDC_RO: ssfdcr_readsect(%lu) sec_per_blk=%d, ofst=%d,"
+	pr_debug("SSFDC_RO: ssfdcr_readsect(%lu) sec_per_blk=%d, ofst=%d,"
 		" block_addr=%d\n", logic_sect_no, sectors_per_block, offset,
 		block_address);
 
@@ -397,8 +385,7 @@
 
 	block_address = ssfdc->logic_block_map[block_address];
 
-	DEBUG(MTD_DEBUG_LEVEL3,
-		"SSFDC_RO: ssfdcr_readsect() phys_block_addr=%d\n",
+	pr_debug("SSFDC_RO: ssfdcr_readsect() phys_block_addr=%d\n",
 		block_address);
 
 	if (block_address < 0xffff) {
@@ -407,8 +394,7 @@
 		sect_no = (unsigned long)block_address * sectors_per_block +
 				offset;
 
-		DEBUG(MTD_DEBUG_LEVEL3,
-			"SSFDC_RO: ssfdcr_readsect() phys_sect_no=%lu\n",
+		pr_debug("SSFDC_RO: ssfdcr_readsect() phys_sect_no=%lu\n",
 			sect_no);
 
 		if (read_physical_sector(ssfdc->mbd.mtd, buf, sect_no) < 0)
@@ -424,7 +410,7 @@
 {
 	struct ssfdcr_record *ssfdc = (struct ssfdcr_record *)dev;
 
-	DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: ssfdcr_getgeo() C=%d, H=%d, S=%d\n",
+	pr_debug("SSFDC_RO: ssfdcr_getgeo() C=%d, H=%d, S=%d\n",
 			ssfdc->cylinders, ssfdc->heads, ssfdc->sectors);
 
 	geo->heads = ssfdc->heads;
diff -druN linux-libre-3.1-gnu/drivers/mtd/tests/mtd_oobtest.c linux-libre-3.2-gnu/drivers/mtd/tests/mtd_oobtest.c
--- linux-libre-3.1-gnu/drivers/mtd/tests/mtd_oobtest.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/tests/mtd_oobtest.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@
 
 #define PRINT_PREF KERN_INFO "mtd_oobtest: "
 
-static int dev;
+static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
 
@@ -131,7 +131,7 @@
 
 	for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
 		set_random_data(writebuf, use_len);
-		ops.mode      = MTD_OOB_AUTO;
+		ops.mode      = MTD_OPS_AUTO_OOB;
 		ops.len       = 0;
 		ops.retlen    = 0;
 		ops.ooblen    = use_len;
@@ -184,7 +184,7 @@
 
 	for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
 		set_random_data(writebuf, use_len);
-		ops.mode      = MTD_OOB_AUTO;
+		ops.mode      = MTD_OPS_AUTO_OOB;
 		ops.len       = 0;
 		ops.retlen    = 0;
 		ops.ooblen    = use_len;
@@ -211,7 +211,7 @@
 		if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) {
 			int k;
 
-			ops.mode      = MTD_OOB_AUTO;
+			ops.mode      = MTD_OPS_AUTO_OOB;
 			ops.len       = 0;
 			ops.retlen    = 0;
 			ops.ooblen    = mtd->ecclayout->oobavail;
@@ -276,7 +276,7 @@
 	size_t len = mtd->ecclayout->oobavail * pgcnt;
 
 	set_random_data(writebuf, len);
-	ops.mode      = MTD_OOB_AUTO;
+	ops.mode      = MTD_OPS_AUTO_OOB;
 	ops.len       = 0;
 	ops.retlen    = 0;
 	ops.ooblen    = len;
@@ -366,6 +366,13 @@
 
 	printk(KERN_INFO "\n");
 	printk(KERN_INFO "=================================================\n");
+
+	if (dev < 0) {
+		printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+		printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+		return -EINVAL;
+	}
+
 	printk(PRINT_PREF "MTD device: %d\n", dev);
 
 	mtd = get_mtd_device(NULL, dev);
@@ -507,7 +514,7 @@
 		addr0 += mtd->erasesize;
 
 	/* Attempt to write off end of OOB */
-	ops.mode      = MTD_OOB_AUTO;
+	ops.mode      = MTD_OPS_AUTO_OOB;
 	ops.len       = 0;
 	ops.retlen    = 0;
 	ops.ooblen    = 1;
@@ -527,7 +534,7 @@
 	}
 
 	/* Attempt to read off end of OOB */
-	ops.mode      = MTD_OOB_AUTO;
+	ops.mode      = MTD_OPS_AUTO_OOB;
 	ops.len       = 0;
 	ops.retlen    = 0;
 	ops.ooblen    = 1;
@@ -551,7 +558,7 @@
 		       "block is bad\n");
 	else {
 		/* Attempt to write off end of device */
-		ops.mode      = MTD_OOB_AUTO;
+		ops.mode      = MTD_OPS_AUTO_OOB;
 		ops.len       = 0;
 		ops.retlen    = 0;
 		ops.ooblen    = mtd->ecclayout->oobavail + 1;
@@ -571,7 +578,7 @@
 		}
 
 		/* Attempt to read off end of device */
-		ops.mode      = MTD_OOB_AUTO;
+		ops.mode      = MTD_OPS_AUTO_OOB;
 		ops.len       = 0;
 		ops.retlen    = 0;
 		ops.ooblen    = mtd->ecclayout->oobavail + 1;
@@ -595,7 +602,7 @@
 			goto out;
 
 		/* Attempt to write off end of device */
-		ops.mode      = MTD_OOB_AUTO;
+		ops.mode      = MTD_OPS_AUTO_OOB;
 		ops.len       = 0;
 		ops.retlen    = 0;
 		ops.ooblen    = mtd->ecclayout->oobavail;
@@ -615,7 +622,7 @@
 		}
 
 		/* Attempt to read off end of device */
-		ops.mode      = MTD_OOB_AUTO;
+		ops.mode      = MTD_OPS_AUTO_OOB;
 		ops.len       = 0;
 		ops.retlen    = 0;
 		ops.ooblen    = mtd->ecclayout->oobavail;
@@ -655,7 +662,7 @@
 		addr = (i + 1) * mtd->erasesize - mtd->writesize;
 		for (pg = 0; pg < cnt; ++pg) {
 			set_random_data(writebuf, sz);
-			ops.mode      = MTD_OOB_AUTO;
+			ops.mode      = MTD_OPS_AUTO_OOB;
 			ops.len       = 0;
 			ops.retlen    = 0;
 			ops.ooblen    = sz;
@@ -683,7 +690,7 @@
 			continue;
 		set_random_data(writebuf, mtd->ecclayout->oobavail * 2);
 		addr = (i + 1) * mtd->erasesize - mtd->writesize;
-		ops.mode      = MTD_OOB_AUTO;
+		ops.mode      = MTD_OPS_AUTO_OOB;
 		ops.len       = 0;
 		ops.retlen    = 0;
 		ops.ooblen    = mtd->ecclayout->oobavail * 2;
diff -druN linux-libre-3.1-gnu/drivers/mtd/tests/mtd_pagetest.c linux-libre-3.2-gnu/drivers/mtd/tests/mtd_pagetest.c
--- linux-libre-3.1-gnu/drivers/mtd/tests/mtd_pagetest.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/tests/mtd_pagetest.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@
 
 #define PRINT_PREF KERN_INFO "mtd_pagetest: "
 
-static int dev;
+static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
 
@@ -128,7 +128,7 @@
 	for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) {
 		/* Do a read to set the internal dataRAMs to different data */
 		err = mtd->read(mtd, addr0, bufsize, &read, twopages);
-		if (err == -EUCLEAN)
+		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != bufsize) {
 			printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -136,7 +136,7 @@
 			return err;
 		}
 		err = mtd->read(mtd, addrn - bufsize, bufsize, &read, twopages);
-		if (err == -EUCLEAN)
+		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != bufsize) {
 			printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -146,7 +146,7 @@
 		memset(twopages, 0, bufsize);
 		read = 0;
 		err = mtd->read(mtd, addr, bufsize, &read, twopages);
-		if (err == -EUCLEAN)
+		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != bufsize) {
 			printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -164,7 +164,7 @@
 		unsigned long oldnext = next;
 		/* Do a read to set the internal dataRAMs to different data */
 		err = mtd->read(mtd, addr0, bufsize, &read, twopages);
-		if (err == -EUCLEAN)
+		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != bufsize) {
 			printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -172,7 +172,7 @@
 			return err;
 		}
 		err = mtd->read(mtd, addrn - bufsize, bufsize, &read, twopages);
-		if (err == -EUCLEAN)
+		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != bufsize) {
 			printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -182,7 +182,7 @@
 		memset(twopages, 0, bufsize);
 		read = 0;
 		err = mtd->read(mtd, addr, bufsize, &read, twopages);
-		if (err == -EUCLEAN)
+		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != bufsize) {
 			printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -231,7 +231,7 @@
 	read = 0;
 	addr = addrn - pgsize - pgsize;
 	err = mtd->read(mtd, addr, pgsize, &read, pp1);
-	if (err == -EUCLEAN)
+	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != pgsize) {
 		printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -244,7 +244,7 @@
 	read = 0;
 	addr = addrn - pgsize - pgsize - pgsize;
 	err = mtd->read(mtd, addr, pgsize, &read, pp1);
-	if (err == -EUCLEAN)
+	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != pgsize) {
 		printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -258,7 +258,7 @@
 	addr = addr0;
 	printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
 	err = mtd->read(mtd, addr, pgsize, &read, pp2);
-	if (err == -EUCLEAN)
+	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != pgsize) {
 		printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -272,7 +272,7 @@
 	addr = addrn - pgsize;
 	printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
 	err = mtd->read(mtd, addr, pgsize, &read, pp3);
-	if (err == -EUCLEAN)
+	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != pgsize) {
 		printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -286,7 +286,7 @@
 	addr = addr0;
 	printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
 	err = mtd->read(mtd, addr, pgsize, &read, pp4);
-	if (err == -EUCLEAN)
+	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != pgsize) {
 		printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -345,7 +345,7 @@
 	printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
 	memset(readbuf, 0, pgsize);
 	err = mtd->read(mtd, addr0, pgsize, &read, readbuf);
-	if (err == -EUCLEAN)
+	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != pgsize) {
 		printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -383,7 +383,7 @@
 	printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
 	memset(readbuf, 0, pgsize);
 	err = mtd->read(mtd, addr0, pgsize, &read, readbuf);
-	if (err == -EUCLEAN)
+	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != pgsize) {
 		printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -439,7 +439,7 @@
 
 	printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
 	err = mtd->read(mtd, addr0, pgsize, &read, twopages);
-	if (err == -EUCLEAN)
+	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != pgsize) {
 		printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -504,6 +504,13 @@
 
 	printk(KERN_INFO "\n");
 	printk(KERN_INFO "=================================================\n");
+
+	if (dev < 0) {
+		printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+		printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+		return -EINVAL;
+	}
+
 	printk(PRINT_PREF "MTD device: %d\n", dev);
 
 	mtd = get_mtd_device(NULL, dev);
diff -druN linux-libre-3.1-gnu/drivers/mtd/tests/mtd_readtest.c linux-libre-3.2-gnu/drivers/mtd/tests/mtd_readtest.c
--- linux-libre-3.1-gnu/drivers/mtd/tests/mtd_readtest.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/tests/mtd_readtest.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,7 @@
 
 #define PRINT_PREF KERN_INFO "mtd_readtest: "
 
-static int dev;
+static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
 
@@ -66,7 +66,7 @@
 		if (mtd->oobsize) {
 			struct mtd_oob_ops ops;
 
-			ops.mode      = MTD_OOB_PLACE;
+			ops.mode      = MTD_OPS_PLACE_OOB;
 			ops.len       = 0;
 			ops.retlen    = 0;
 			ops.ooblen    = mtd->oobsize;
@@ -75,7 +75,8 @@
 			ops.datbuf    = NULL;
 			ops.oobbuf    = oobbuf;
 			ret = mtd->read_oob(mtd, addr, &ops);
-			if (ret || ops.oobretlen != mtd->oobsize) {
+			if ((ret && !mtd_is_bitflip(ret)) ||
+					ops.oobretlen != mtd->oobsize) {
 				printk(PRINT_PREF "error: read oob failed at "
 						  "%#llx\n", (long long)addr);
 				if (!err)
@@ -169,6 +170,12 @@
 
 	printk(KERN_INFO "\n");
 	printk(KERN_INFO "=================================================\n");
+
+	if (dev < 0) {
+		printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+		return -EINVAL;
+	}
+
 	printk(PRINT_PREF "MTD device: %d\n", dev);
 
 	mtd = get_mtd_device(NULL, dev);
diff -druN linux-libre-3.1-gnu/drivers/mtd/tests/mtd_speedtest.c linux-libre-3.2-gnu/drivers/mtd/tests/mtd_speedtest.c
--- linux-libre-3.1-gnu/drivers/mtd/tests/mtd_speedtest.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/tests/mtd_speedtest.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,7 @@
 
 #define PRINT_PREF KERN_INFO "mtd_speedtest: "
 
-static int dev;
+static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
 
@@ -216,7 +216,7 @@
 
 	err = mtd->read(mtd, addr, mtd->erasesize, &read, iobuf);
 	/* Ignore corrected ECC errors */
-	if (err == -EUCLEAN)
+	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != mtd->erasesize) {
 		printk(PRINT_PREF "error: read failed at %#llx\n", addr);
@@ -237,7 +237,7 @@
 	for (i = 0; i < pgcnt; i++) {
 		err = mtd->read(mtd, addr, pgsize, &read, buf);
 		/* Ignore corrected ECC errors */
-		if (err == -EUCLEAN)
+		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != pgsize) {
 			printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -263,7 +263,7 @@
 	for (i = 0; i < n; i++) {
 		err = mtd->read(mtd, addr, sz, &read, buf);
 		/* Ignore corrected ECC errors */
-		if (err == -EUCLEAN)
+		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != sz) {
 			printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -278,7 +278,7 @@
 	if (pgcnt % 2) {
 		err = mtd->read(mtd, addr, pgsize, &read, buf);
 		/* Ignore corrected ECC errors */
-		if (err == -EUCLEAN)
+		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != pgsize) {
 			printk(PRINT_PREF "error: read failed at %#llx\n",
@@ -361,6 +361,13 @@
 
 	printk(KERN_INFO "\n");
 	printk(KERN_INFO "=================================================\n");
+
+	if (dev < 0) {
+		printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+		printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+		return -EINVAL;
+	}
+
 	if (count)
 		printk(PRINT_PREF "MTD device: %d    count: %d\n", dev, count);
 	else
diff -druN linux-libre-3.1-gnu/drivers/mtd/tests/mtd_stresstest.c linux-libre-3.2-gnu/drivers/mtd/tests/mtd_stresstest.c
--- linux-libre-3.1-gnu/drivers/mtd/tests/mtd_stresstest.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/tests/mtd_stresstest.c	2012-01-04 18:55:44.000000000 -0500
@@ -30,7 +30,7 @@
 
 #define PRINT_PREF KERN_INFO "mtd_stresstest: "
 
-static int dev;
+static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
 
@@ -154,7 +154,7 @@
 	}
 	addr = eb * mtd->erasesize + offs;
 	err = mtd->read(mtd, addr, len, &read, readbuf);
-	if (err == -EUCLEAN)
+	if (mtd_is_bitflip(err))
 		err = 0;
 	if (unlikely(err || read != len)) {
 		printk(PRINT_PREF "error: read failed at 0x%llx\n",
@@ -250,6 +250,13 @@
 
 	printk(KERN_INFO "\n");
 	printk(KERN_INFO "=================================================\n");
+
+	if (dev < 0) {
+		printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+		printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+		return -EINVAL;
+	}
+
 	printk(PRINT_PREF "MTD device: %d\n", dev);
 
 	mtd = get_mtd_device(NULL, dev);
diff -druN linux-libre-3.1-gnu/drivers/mtd/tests/mtd_subpagetest.c linux-libre-3.2-gnu/drivers/mtd/tests/mtd_subpagetest.c
--- linux-libre-3.1-gnu/drivers/mtd/tests/mtd_subpagetest.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/tests/mtd_subpagetest.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,7 @@
 
 #define PRINT_PREF KERN_INFO "mtd_subpagetest: "
 
-static int dev;
+static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
 
@@ -198,7 +198,7 @@
 	read = 0;
 	err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
 	if (unlikely(err || read != subpgsize)) {
-		if (err == -EUCLEAN && read == subpgsize) {
+		if (mtd_is_bitflip(err) && read == subpgsize) {
 			printk(PRINT_PREF "ECC correction at %#llx\n",
 			       (long long)addr);
 			err = 0;
@@ -226,7 +226,7 @@
 	read = 0;
 	err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
 	if (unlikely(err || read != subpgsize)) {
-		if (err == -EUCLEAN && read == subpgsize) {
+		if (mtd_is_bitflip(err) && read == subpgsize) {
 			printk(PRINT_PREF "ECC correction at %#llx\n",
 			       (long long)addr);
 			err = 0;
@@ -264,7 +264,7 @@
 		read = 0;
 		err = mtd->read(mtd, addr, subpgsize * k, &read, readbuf);
 		if (unlikely(err || read != subpgsize * k)) {
-			if (err == -EUCLEAN && read == subpgsize * k) {
+			if (mtd_is_bitflip(err) && read == subpgsize * k) {
 				printk(PRINT_PREF "ECC correction at %#llx\n",
 				       (long long)addr);
 				err = 0;
@@ -298,7 +298,7 @@
 		read = 0;
 		err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
 		if (unlikely(err || read != subpgsize)) {
-			if (err == -EUCLEAN && read == subpgsize) {
+			if (mtd_is_bitflip(err) && read == subpgsize) {
 				printk(PRINT_PREF "ECC correction at %#llx\n",
 				       (long long)addr);
 				err = 0;
@@ -379,6 +379,13 @@
 
 	printk(KERN_INFO "\n");
 	printk(KERN_INFO "=================================================\n");
+
+	if (dev < 0) {
+		printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+		printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+		return -EINVAL;
+	}
+
 	printk(PRINT_PREF "MTD device: %d\n", dev);
 
 	mtd = get_mtd_device(NULL, dev);
diff -druN linux-libre-3.1-gnu/drivers/mtd/tests/mtd_torturetest.c linux-libre-3.2-gnu/drivers/mtd/tests/mtd_torturetest.c
--- linux-libre-3.1-gnu/drivers/mtd/tests/mtd_torturetest.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/tests/mtd_torturetest.c	2012-01-04 18:55:44.000000000 -0500
@@ -46,7 +46,7 @@
 module_param(pgcnt, int, S_IRUGO);
 MODULE_PARM_DESC(pgcnt, "number of pages per eraseblock to torture (0 => all)");
 
-static int dev;
+static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
 
@@ -138,7 +138,7 @@
 
 retry:
 	err = mtd->read(mtd, addr, len, &read, check_buf);
-	if (err == -EUCLEAN)
+	if (mtd_is_bitflip(err))
 		printk(PRINT_PREF "single bit flip occurred at EB %d "
 		       "MTD reported that it was fixed.\n", ebnum);
 	else if (err) {
@@ -213,6 +213,13 @@
 	printk(KERN_INFO "=================================================\n");
 	printk(PRINT_PREF "Warning: this program is trying to wear out your "
 	       "flash, stop it if this is not wanted.\n");
+
+	if (dev < 0) {
+		printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+		printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+		return -EINVAL;
+	}
+
 	printk(PRINT_PREF "MTD device: %d\n", dev);
 	printk(PRINT_PREF "torture %d eraseblocks (%d-%d) of mtd%d\n",
 	       ebcnt, eb, eb + ebcnt - 1, dev);
diff -druN linux-libre-3.1-gnu/drivers/mtd/ubi/eba.c linux-libre-3.2-gnu/drivers/mtd/ubi/eba.c
--- linux-libre-3.1-gnu/drivers/mtd/ubi/eba.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/ubi/eba.c	2012-01-04 18:55:44.000000000 -0500
@@ -443,7 +443,7 @@
 		if (err == UBI_IO_BITFLIPS) {
 			scrub = 1;
 			err = 0;
-		} else if (err == -EBADMSG) {
+		} else if (mtd_is_eccerr(err)) {
 			if (vol->vol_type == UBI_DYNAMIC_VOLUME)
 				goto out_unlock;
 			scrub = 1;
diff -druN linux-libre-3.1-gnu/drivers/mtd/ubi/io.c linux-libre-3.2-gnu/drivers/mtd/ubi/io.c
--- linux-libre-3.1-gnu/drivers/mtd/ubi/io.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/ubi/io.c	2012-01-04 18:55:44.000000000 -0500
@@ -172,9 +172,9 @@
 retry:
 	err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
 	if (err) {
-		const char *errstr = (err == -EBADMSG) ? " (ECC error)" : "";
+		const char *errstr = mtd_is_eccerr(err) ? " (ECC error)" : "";
 
-		if (err == -EUCLEAN) {
+		if (mtd_is_bitflip(err)) {
 			/*
 			 * -EUCLEAN is reported if there was a bit-flip which
 			 * was corrected, so this is harmless.
@@ -205,7 +205,7 @@
 		 * all the requested data. But some buggy drivers might do
 		 * this, so we change it to -EIO.
 		 */
-		if (read != len && err == -EBADMSG) {
+		if (read != len && mtd_is_eccerr(err)) {
 			ubi_assert(0);
 			err = -EIO;
 		}
@@ -469,7 +469,7 @@
 
 out:
 	mutex_unlock(&ubi->buf_mutex);
-	if (err == UBI_IO_BITFLIPS || err == -EBADMSG) {
+	if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) {
 		/*
 		 * If a bit-flip or data integrity error was detected, the test
 		 * has not passed because it happened on a freshly erased
@@ -760,7 +760,7 @@
 
 	read_err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
 	if (read_err) {
-		if (read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
+		if (read_err != UBI_IO_BITFLIPS && !mtd_is_eccerr(read_err))
 			return read_err;
 
 		/*
@@ -776,7 +776,7 @@
 
 	magic = be32_to_cpu(ec_hdr->magic);
 	if (magic != UBI_EC_HDR_MAGIC) {
-		if (read_err == -EBADMSG)
+		if (mtd_is_eccerr(read_err))
 			return UBI_IO_BAD_HDR_EBADMSG;
 
 		/*
@@ -1032,12 +1032,12 @@
 	p = (char *)vid_hdr - ubi->vid_hdr_shift;
 	read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
 			  ubi->vid_hdr_alsize);
-	if (read_err && read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
+	if (read_err && read_err != UBI_IO_BITFLIPS && !mtd_is_eccerr(read_err))
 		return read_err;
 
 	magic = be32_to_cpu(vid_hdr->magic);
 	if (magic != UBI_VID_HDR_MAGIC) {
-		if (read_err == -EBADMSG)
+		if (mtd_is_eccerr(read_err))
 			return UBI_IO_BAD_HDR_EBADMSG;
 
 		if (ubi_check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
@@ -1219,7 +1219,7 @@
 		return -ENOMEM;
 
 	err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
-	if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG)
+	if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err))
 		goto exit;
 
 	crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
@@ -1306,7 +1306,7 @@
 	p = (char *)vid_hdr - ubi->vid_hdr_shift;
 	err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
 			  ubi->vid_hdr_alsize);
-	if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG)
+	if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err))
 		goto exit;
 
 	crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_EC_HDR_SIZE_CRC);
@@ -1358,7 +1358,7 @@
 	}
 
 	err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf1);
-	if (err && err != -EUCLEAN)
+	if (err && !mtd_is_bitflip(err))
 		goto out_free;
 
 	for (i = 0; i < len; i++) {
@@ -1422,7 +1422,7 @@
 	}
 
 	err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
-	if (err && err != -EUCLEAN) {
+	if (err && !mtd_is_bitflip(err)) {
 		ubi_err("error %d while reading %d bytes from PEB %d:%d, "
 			"read %zd bytes", err, len, pnum, offset, read);
 		goto error;
diff -druN linux-libre-3.1-gnu/drivers/mtd/ubi/kapi.c linux-libre-3.2-gnu/drivers/mtd/ubi/kapi.c
--- linux-libre-3.1-gnu/drivers/mtd/ubi/kapi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/ubi/kapi.c	2012-01-04 18:55:44.000000000 -0500
@@ -410,7 +410,7 @@
 		return 0;
 
 	err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check);
-	if (err && err == -EBADMSG && vol->vol_type == UBI_STATIC_VOLUME) {
+	if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) {
 		ubi_warn("mark volume %d as corrupted", vol_id);
 		vol->corrupted = 1;
 	}
diff -druN linux-libre-3.1-gnu/drivers/mtd/ubi/misc.c linux-libre-3.2-gnu/drivers/mtd/ubi/misc.c
--- linux-libre-3.1-gnu/drivers/mtd/ubi/misc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/ubi/misc.c	2012-01-04 18:55:44.000000000 -0500
@@ -81,7 +81,7 @@
 
 		err = ubi_eba_read_leb(ubi, vol, i, buf, 0, size, 1);
 		if (err) {
-			if (err == -EBADMSG)
+			if (mtd_is_eccerr(err))
 				err = 1;
 			break;
 		}
diff -druN linux-libre-3.1-gnu/drivers/mtd/ubi/scan.c linux-libre-3.2-gnu/drivers/mtd/ubi/scan.c
--- linux-libre-3.1-gnu/drivers/mtd/ubi/scan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/ubi/scan.c	2012-01-04 18:55:44.000000000 -0500
@@ -395,7 +395,7 @@
 	}
 
 	err = ubi_io_read_data(ubi, buf, pnum, 0, len);
-	if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG)
+	if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err))
 		goto out_free_buf;
 
 	data_crc = be32_to_cpu(vid_hdr->data_crc);
@@ -793,7 +793,7 @@
 
 	err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start,
 			  ubi->leb_size);
-	if (err == UBI_IO_BITFLIPS || err == -EBADMSG) {
+	if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) {
 		/*
 		 * Bit-flips or integrity errors while reading the data area.
 		 * It is difficult to say for sure what type of corruption is
diff -druN linux-libre-3.1-gnu/drivers/mtd/ubi/vmt.c linux-libre-3.2-gnu/drivers/mtd/ubi/vmt.c
--- linux-libre-3.1-gnu/drivers/mtd/ubi/vmt.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/ubi/vmt.c	2012-01-04 18:55:44.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/err.h>
 #include <linux/math64.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include "ubi.h"
 
 #ifdef CONFIG_MTD_UBI_DEBUG
diff -druN linux-libre-3.1-gnu/drivers/mtd/ubi/vtbl.c linux-libre-3.2-gnu/drivers/mtd/ubi/vtbl.c
--- linux-libre-3.1-gnu/drivers/mtd/ubi/vtbl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/mtd/ubi/vtbl.c	2012-01-04 18:55:44.000000000 -0500
@@ -423,7 +423,7 @@
 
 		err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0,
 				       ubi->vtbl_size);
-		if (err == UBI_IO_BITFLIPS || err == -EBADMSG)
+		if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err))
 			/*
 			 * Scrub the PEB later. Note, -EBADMSG indicates an
 			 * uncorrectable ECC error, but we have our own CRC and
diff -druN linux-libre-3.1-gnu/drivers/net/3c501.c linux-libre-3.2-gnu/drivers/net/3c501.c
--- linux-libre-3.1-gnu/drivers/net/3c501.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/3c501.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,896 +0,0 @@
-/* 3c501.c: A 3Com 3c501 Ethernet driver for Linux. */
-/*
-    Written 1992,1993,1994  Donald Becker
-
-    Copyright 1993 United States Government as represented by the
-    Director, National Security Agency.  This software may be used and
-    distributed according to the terms of the GNU General Public License,
-    incorporated herein by reference.
-
-    This is a device driver for the 3Com Etherlink 3c501.
-    Do not purchase this card, even as a joke.  It's performance is horrible,
-    and it breaks in many ways.
-
-    The original author may be reached as becker@scyld.com, or C/O
-	Scyld Computing Corporation
-	410 Severn Ave., Suite 210
-	Annapolis MD 21403
-
-    Fixed (again!) the missing interrupt locking on TX/RX shifting.
-	Alan Cox <alan@lxorguk.ukuu.org.uk>
-
-    Removed calls to init_etherdev since they are no longer needed, and
-    cleaned up modularization just a bit. The driver still allows only
-    the default address for cards when loaded as a module, but that's
-    really less braindead than anyone using a 3c501 board. :)
-		    19950208 (invid@msen.com)
-
-    Added traps for interrupts hitting the window as we clear and TX load
-    the board. Now getting 150K/second FTP with a 3c501 card. Still playing
-    with a TX-TX optimisation to see if we can touch 180-200K/second as seems
-    theoretically maximum.
-		19950402 Alan Cox <alan@lxorguk.ukuu.org.uk>
-
-    Cleaned up for 2.3.x because we broke SMP now.
-		20000208 Alan Cox <alan@lxorguk.ukuu.org.uk>
-
-    Check up pass for 2.5. Nothing significant changed
-		20021009 Alan Cox <alan@lxorguk.ukuu.org.uk>
-
-    Fixed zero fill corner case
-		20030104 Alan Cox <alan@lxorguk.ukuu.org.uk>
-
-
-   For the avoidance of doubt the "preferred form" of this code is one which
-   is in an open non patent encumbered format. Where cryptographic key signing
-   forms part of the process of creating an executable the information
-   including keys needed to generate an equivalently functional executable
-   are deemed to be part of the source code.
-
-*/
-
-
-/**
- * DOC: 3c501 Card Notes
- *
- *  Some notes on this thing if you have to hack it.  [Alan]
- *
- *  Some documentation is available from 3Com. Due to the boards age
- *  standard responses when you ask for this will range from 'be serious'
- *  to 'give it to a museum'. The documentation is incomplete and mostly
- *  of historical interest anyway.
- *
- *  The basic system is a single buffer which can be used to receive or
- *  transmit a packet. A third command mode exists when you are setting
- *  things up.
- *
- *  If it's transmitting it's not receiving and vice versa. In fact the
- *  time to get the board back into useful state after an operation is
- *  quite large.
- *
- *  The driver works by keeping the board in receive mode waiting for a
- *  packet to arrive. When one arrives it is copied out of the buffer
- *  and delivered to the kernel. The card is reloaded and off we go.
- *
- *  When transmitting lp->txing is set and the card is reset (from
- *  receive mode) [possibly losing a packet just received] to command
- *  mode. A packet is loaded and transmit mode triggered. The interrupt
- *  handler runs different code for transmit interrupts and can handle
- *  returning to receive mode or retransmissions (yes you have to help
- *  out with those too).
- *
- * DOC: Problems
- *
- *  There are a wide variety of undocumented error returns from the card
- *  and you basically have to kick the board and pray if they turn up. Most
- *  only occur under extreme load or if you do something the board doesn't
- *  like (eg touching a register at the wrong time).
- *
- *  The driver is less efficient than it could be. It switches through
- *  receive mode even if more transmits are queued. If this worries you buy
- *  a real Ethernet card.
- *
- *  The combination of slow receive restart and no real multicast
- *  filter makes the board unusable with a kernel compiled for IP
- *  multicasting in a real multicast environment. That's down to the board,
- *  but even with no multicast programs running a multicast IP kernel is
- *  in group 224.0.0.1 and you will therefore be listening to all multicasts.
- *  One nv conference running over that Ethernet and you can give up.
- *
- */
-
-#define DRV_NAME	"3c501"
-#define DRV_VERSION	"2002/10/09"
-
-
-static const char version[] =
-	DRV_NAME ".c: " DRV_VERSION " Alan Cox (alan@lxorguk.ukuu.org.uk).\n";
-
-/*
- *	Braindamage remaining:
- *	The 3c501 board.
- */
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/spinlock.h>
-#include <linux/ethtool.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-
-#include "3c501.h"
-
-/*
- *	The boilerplate probe code.
- */
-
-static int io = 0x280;
-static int irq = 5;
-static int mem_start;
-
-/**
- * el1_probe:		-	probe for a 3c501
- * @dev: The device structure passed in to probe.
- *
- * This can be called from two places. The network layer will probe using
- * a device structure passed in with the probe information completed. For a
- * modular driver we use #init_module to fill in our own structure and probe
- * for it.
- *
- * Returns 0 on success. ENXIO if asked not to probe and ENODEV if asked to
- * probe and failing to find anything.
- */
-
-struct net_device * __init el1_probe(int unit)
-{
-	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
-	static const unsigned ports[] = { 0x280, 0x300, 0};
-	const unsigned *port;
-	int err = 0;
-
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	if (unit >= 0) {
-		sprintf(dev->name, "eth%d", unit);
-		netdev_boot_setup_check(dev);
-		io = dev->base_addr;
-		irq = dev->irq;
-		mem_start = dev->mem_start & 7;
-	}
-
-	if (io > 0x1ff) {	/* Check a single specified location. */
-		err = el1_probe1(dev, io);
-	} else if (io != 0) {
-		err = -ENXIO;		/* Don't probe at all. */
-	} else {
-		for (port = ports; *port && el1_probe1(dev, *port); port++)
-			;
-		if (!*port)
-			err = -ENODEV;
-	}
-	if (err)
-		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
-	return dev;
-out1:
-	release_region(dev->base_addr, EL1_IO_EXTENT);
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-
-static const struct net_device_ops el_netdev_ops = {
-	.ndo_open		= el_open,
-	.ndo_stop		= el1_close,
-	.ndo_start_xmit 	= el_start_xmit,
-	.ndo_tx_timeout		= el_timeout,
-	.ndo_set_multicast_list = set_multicast_list,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-/**
- *	el1_probe1:
- *	@dev: The device structure to use
- *	@ioaddr: An I/O address to probe at.
- *
- *	The actual probe. This is iterated over by #el1_probe in order to
- *	check all the applicable device locations.
- *
- *	Returns 0 for a success, in which case the device is activated,
- *	EAGAIN if the IRQ is in use by another driver, and ENODEV if the
- *	board cannot be found.
- */
-
-static int __init el1_probe1(struct net_device *dev, int ioaddr)
-{
-	struct net_local *lp;
-	const char *mname;		/* Vendor name */
-	unsigned char station_addr[6];
-	int autoirq = 0;
-	int i;
-
-	/*
-	 *	Reserve I/O resource for exclusive use by this driver
-	 */
-
-	if (!request_region(ioaddr, EL1_IO_EXTENT, DRV_NAME))
-		return -ENODEV;
-
-	/*
-	 *	Read the station address PROM data from the special port.
-	 */
-
-	for (i = 0; i < 6; i++) {
-		outw(i, ioaddr + EL1_DATAPTR);
-		station_addr[i] = inb(ioaddr + EL1_SAPROM);
-	}
-	/*
-	 *	Check the first three octets of the S.A. for 3Com's prefix, or
-	 *	for the Sager NP943 prefix.
-	 */
-
-	if (station_addr[0] == 0x02 && station_addr[1] == 0x60 &&
-	    station_addr[2] == 0x8c)
-		mname = "3c501";
-	else if (station_addr[0] == 0x00 && station_addr[1] == 0x80 &&
-		 station_addr[2] == 0xC8)
-		mname = "NP943";
-	else {
-		release_region(ioaddr, EL1_IO_EXTENT);
-		return -ENODEV;
-	}
-
-	/*
-	 *	We auto-IRQ by shutting off the interrupt line and letting it
-	 *	float high.
-	 */
-
-	dev->irq = irq;
-
-	if (dev->irq < 2) {
-		unsigned long irq_mask;
-
-		irq_mask = probe_irq_on();
-		inb(RX_STATUS);		/* Clear pending interrupts. */
-		inb(TX_STATUS);
-		outb(AX_LOOP + 1, AX_CMD);
-
-		outb(0x00, AX_CMD);
-
-		mdelay(20);
-		autoirq = probe_irq_off(irq_mask);
-
-		if (autoirq == 0) {
-			pr_warning("%s probe at %#x failed to detect IRQ line.\n",
-				mname, ioaddr);
-			release_region(ioaddr, EL1_IO_EXTENT);
-			return -EAGAIN;
-		}
-	}
-
-	outb(AX_RESET+AX_LOOP, AX_CMD);			/* Loopback mode. */
-	dev->base_addr = ioaddr;
-	memcpy(dev->dev_addr, station_addr, ETH_ALEN);
-
-	if (mem_start & 0xf)
-		el_debug = mem_start & 0x7;
-	if (autoirq)
-		dev->irq = autoirq;
-
-	pr_info("%s: %s EtherLink at %#lx, using %sIRQ %d.\n",
-			dev->name, mname, dev->base_addr,
-			autoirq ? "auto":"assigned ", dev->irq);
-
-#ifdef CONFIG_IP_MULTICAST
-	pr_warning("WARNING: Use of the 3c501 in a multicast kernel is NOT recommended.\n");
-#endif
-
-	if (el_debug)
-		pr_debug("%s", version);
-
-	lp = netdev_priv(dev);
-	memset(lp, 0, sizeof(struct net_local));
-	spin_lock_init(&lp->lock);
-
-	/*
-	 *	The EL1-specific entries in the device structure.
-	 */
-
-	dev->netdev_ops = &el_netdev_ops;
-	dev->watchdog_timeo = HZ;
-	dev->ethtool_ops = &netdev_ethtool_ops;
-	return 0;
-}
-
-/**
- *	el1_open:
- *	@dev: device that is being opened
- *
- *	When an ifconfig is issued which changes the device flags to include
- *	IFF_UP this function is called. It is only called when the change
- *	occurs, not when the interface remains up. #el1_close will be called
- *	when it goes down.
- *
- *	Returns 0 for a successful open, or -EAGAIN if someone has run off
- *	with our interrupt line.
- */
-
-static int el_open(struct net_device *dev)
-{
-	int retval;
-	int ioaddr = dev->base_addr;
-	struct net_local *lp = netdev_priv(dev);
-	unsigned long flags;
-
-	if (el_debug > 2)
-		pr_debug("%s: Doing el_open()...\n", dev->name);
-
-	retval = request_irq(dev->irq, el_interrupt, 0, dev->name, dev);
-	if (retval)
-		return retval;
-
-	spin_lock_irqsave(&lp->lock, flags);
-	el_reset(dev);
-	spin_unlock_irqrestore(&lp->lock, flags);
-
-	lp->txing = 0;		/* Board in RX mode */
-	outb(AX_RX, AX_CMD);	/* Aux control, irq and receive enabled */
-	netif_start_queue(dev);
-	return 0;
-}
-
-/**
- * el_timeout:
- * @dev: The 3c501 card that has timed out
- *
- * Attempt to restart the board. This is basically a mixture of extreme
- * violence and prayer
- *
- */
-
-static void el_timeout(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-
-	if (el_debug)
-		pr_debug("%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n",
-			dev->name, inb(TX_STATUS),
-			inb(AX_STATUS), inb(RX_STATUS));
-	dev->stats.tx_errors++;
-	outb(TX_NORM, TX_CMD);
-	outb(RX_NORM, RX_CMD);
-	outb(AX_OFF, AX_CMD);	/* Just trigger a false interrupt. */
-	outb(AX_RX, AX_CMD);	/* Aux control, irq and receive enabled */
-	lp->txing = 0;		/* Ripped back in to RX */
-	netif_wake_queue(dev);
-}
-
-
-/**
- * el_start_xmit:
- * @skb: The packet that is queued to be sent
- * @dev: The 3c501 card we want to throw it down
- *
- * Attempt to send a packet to a 3c501 card. There are some interesting
- * catches here because the 3c501 is an extremely old and therefore
- * stupid piece of technology.
- *
- * If we are handling an interrupt on the other CPU we cannot load a packet
- * 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 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
- * lock while loading 1500 bytes onto the controller we would drop a lot of
- * serial port characters. This requires we do extra locking, but we have
- * no real choice.
- */
-
-static netdev_tx_t el_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-	unsigned long flags;
-
-	/*
-	 *	Avoid incoming interrupts between us flipping txing and flipping
-	 *	mode as the driver assumes txing is a faithful indicator of card
-	 *	state
-	 */
-
-	spin_lock_irqsave(&lp->lock, flags);
-
-	/*
-	 *	Avoid timer-based retransmission conflicts.
-	 */
-
-	netif_stop_queue(dev);
-
-	do {
-		int len = skb->len;
-		int pad = 0;
-		int gp_start;
-		unsigned char *buf = skb->data;
-
-		if (len < ETH_ZLEN)
-			pad = ETH_ZLEN - len;
-
-		gp_start = 0x800 - (len + pad);
-
-		lp->tx_pkt_start = gp_start;
-		lp->collisions = 0;
-
-		dev->stats.tx_bytes += skb->len;
-
-		/*
-		 *	Command mode with status cleared should [in theory]
-		 *	mean no more interrupts can be pending on the card.
-		 */
-
-		outb_p(AX_SYS, AX_CMD);
-		inb_p(RX_STATUS);
-		inb_p(TX_STATUS);
-
-		lp->loading = 1;
-		lp->txing = 1;
-
-		/*
-		 *	Turn interrupts back on while we spend a pleasant
-		 *	afternoon loading bytes into the board
-		 */
-
-		spin_unlock_irqrestore(&lp->lock, flags);
-
-		/* Set rx packet area to 0. */
-		outw(0x00, RX_BUF_CLR);
-		/* aim - packet will be loaded into buffer start */
-		outw(gp_start, GP_LOW);
-		/* load buffer (usual thing each byte increments the pointer) */
-		outsb(DATAPORT, buf, len);
-		if (pad) {
-			while (pad--)		/* Zero fill buffer tail */
-				outb(0, DATAPORT);
-		}
-		/* the board reuses the same register */
-		outw(gp_start, GP_LOW);
-
-		if (lp->loading != 2) {
-			/* fire ... Trigger xmit.  */
-			outb(AX_XMIT, AX_CMD);
-			lp->loading = 0;
-			if (el_debug > 2)
-				pr_debug(" queued xmit.\n");
-			dev_kfree_skb(skb);
-			return NETDEV_TX_OK;
-		}
-		/* A receive upset our load, despite our best efforts */
-		if (el_debug > 2)
-			pr_debug("%s: burped during tx load.\n", dev->name);
-		spin_lock_irqsave(&lp->lock, flags);
-	} while (1);
-}
-
-/**
- * el_interrupt:
- * @irq: Interrupt number
- * @dev_id: The 3c501 that burped
- *
- * 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 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
- * speak of. We simply pull the packet out of its PIO buffer (which is slow)
- * and queue it for the kernel. Then we reset the card for the next packet.
- *
- * We sometimes get surprise interrupts late both because the SMP IRQ delivery
- * is message passing and because the card sometimes seems to deliver late. I
- * think if it is part way through a receive and the mode is changed it carries
- * on receiving and sends us an interrupt. We have to band aid all these cases
- * to get a sensible 150kBytes/second performance. Even then you want a small
- * TCP window.
- */
-
-static irqreturn_t el_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct net_local *lp;
-	int ioaddr;
-	int axsr;			/* Aux. status reg. */
-
-	ioaddr = dev->base_addr;
-	lp = netdev_priv(dev);
-
-	spin_lock(&lp->lock);
-
-	/*
-	 *	What happened ?
-	 */
-
-	axsr = inb(AX_STATUS);
-
-	/*
-	 *	Log it
-	 */
-
-	if (el_debug > 3)
-		pr_debug("%s: el_interrupt() aux=%#02x\n", dev->name, axsr);
-
-	if (lp->loading == 1 && !lp->txing)
-		pr_warning("%s: Inconsistent state loading while not in tx\n",
-			dev->name);
-
-	if (lp->txing) {
-		/*
-		 *	Board in transmit mode. May be loading. If we are
-		 *	loading we shouldn't have got this.
-		 */
-		int txsr = inb(TX_STATUS);
-
-		if (lp->loading == 1) {
-			if (el_debug > 2)
-				pr_debug("%s: Interrupt while loading [txsr=%02x gp=%04x rp=%04x]\n",
-					dev->name, txsr, inw(GP_LOW), inw(RX_LOW));
-
-			/* Force a reload */
-			lp->loading = 2;
-			spin_unlock(&lp->lock);
-			goto out;
-		}
-		if (el_debug > 6)
-			pr_debug("%s: txsr=%02x gp=%04x rp=%04x\n", dev->name,
-					txsr, inw(GP_LOW), inw(RX_LOW));
-
-		if ((axsr & 0x80) && (txsr & TX_READY) == 0) {
-			/*
-			 *	FIXME: is there a logic to whether to keep
-			 *	on trying or reset immediately ?
-			 */
-			if (el_debug > 1)
-				pr_debug("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x gp=%03x rp=%03x.\n",
-					dev->name, txsr, axsr,
-					inw(ioaddr + EL1_DATAPTR),
-					inw(ioaddr + EL1_RXPTR));
-			lp->txing = 0;
-			netif_wake_queue(dev);
-		} else if (txsr & TX_16COLLISIONS) {
-			/*
-			 *	Timed out
-			 */
-			if (el_debug)
-				pr_debug("%s: Transmit failed 16 times, Ethernet jammed?\n", dev->name);
-			outb(AX_SYS, AX_CMD);
-			lp->txing = 0;
-			dev->stats.tx_aborted_errors++;
-			netif_wake_queue(dev);
-		} else if (txsr & TX_COLLISION) {
-			/*
-			 *	Retrigger xmit.
-			 */
-
-			if (el_debug > 6)
-				pr_debug("%s: retransmitting after a collision.\n", dev->name);
-			/*
-			 *	Poor little chip can't reset its own start
-			 *	pointer
-			 */
-
-			outb(AX_SYS, AX_CMD);
-			outw(lp->tx_pkt_start, GP_LOW);
-			outb(AX_XMIT, AX_CMD);
-			dev->stats.collisions++;
-			spin_unlock(&lp->lock);
-			goto out;
-		} else {
-			/*
-			 *	It worked.. we will now fall through and receive
-			 */
-			dev->stats.tx_packets++;
-			if (el_debug > 6)
-				pr_debug("%s: Tx succeeded %s\n", dev->name,
-					(txsr & TX_RDY) ? "." : "but tx is busy!");
-			/*
-			 *	This is safe the interrupt is atomic WRT itself.
-			 */
-			lp->txing = 0;
-			/* In case more to transmit */
-			netif_wake_queue(dev);
-		}
-	} else {
-		/*
-		 *	In receive mode.
-		 */
-
-		int rxsr = inb(RX_STATUS);
-		if (el_debug > 5)
-			pr_debug("%s: rxsr=%02x txsr=%02x rp=%04x\n",
-				dev->name, rxsr, inb(TX_STATUS), inw(RX_LOW));
-		/*
-		 *	Just reading rx_status fixes most errors.
-		 */
-		if (rxsr & RX_MISSED)
-			dev->stats.rx_missed_errors++;
-		else if (rxsr & RX_RUNT) {
-			/* Handled to avoid board lock-up. */
-			dev->stats.rx_length_errors++;
-			if (el_debug > 5)
-				pr_debug("%s: runt.\n", dev->name);
-		} else if (rxsr & RX_GOOD) {
-			/*
-			 *	Receive worked.
-			 */
-			el_receive(dev);
-		} else {
-			/*
-			 *	Nothing?  Something is broken!
-			 */
-			if (el_debug > 2)
-				pr_debug("%s: No packet seen, rxsr=%02x **resetting 3c501***\n",
-					dev->name, rxsr);
-			el_reset(dev);
-		}
-	}
-
-	/*
-	 *	Move into receive mode
-	 */
-
-	outb(AX_RX, AX_CMD);
-	outw(0x00, RX_BUF_CLR);
-	inb(RX_STATUS);		/* Be certain that interrupts are cleared. */
-	inb(TX_STATUS);
-	spin_unlock(&lp->lock);
-out:
-	return IRQ_HANDLED;
-}
-
-
-/**
- * el_receive:
- * @dev: Device to pull the packets from
- *
- * We have a good packet. Well, not really "good", just mostly not broken.
- * We must check everything to see if it is good. In particular we occasionally
- * get wild packet sizes from the card. If the packet seems sane we PIO it
- * off the card and queue it for the protocol layers.
- */
-
-static void el_receive(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	int pkt_len;
-	struct sk_buff *skb;
-
-	pkt_len = inw(RX_LOW);
-
-	if (el_debug > 4)
-		pr_debug(" el_receive %d.\n", pkt_len);
-
-	if (pkt_len < 60 || pkt_len > 1536) {
-		if (el_debug)
-			pr_debug("%s: bogus packet, length=%d\n",
-						dev->name, pkt_len);
-		dev->stats.rx_over_errors++;
-		return;
-	}
-
-	/*
-	 *	Command mode so we can empty the buffer
-	 */
-
-	outb(AX_SYS, AX_CMD);
-	skb = dev_alloc_skb(pkt_len+2);
-
-	/*
-	 *	Start of frame
-	 */
-
-	outw(0x00, GP_LOW);
-	if (skb == NULL) {
-		pr_info("%s: Memory squeeze, dropping packet.\n", dev->name);
-		dev->stats.rx_dropped++;
-		return;
-	} else {
-		skb_reserve(skb, 2);	/* Force 16 byte alignment */
-		/*
-		 *	The read increments through the bytes. The interrupt
-		 *	handler will fix the pointer when it returns to
-		 *	receive mode.
-		 */
-		insb(DATAPORT, skb_put(skb, pkt_len), pkt_len);
-		skb->protocol = eth_type_trans(skb, dev);
-		netif_rx(skb);
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += pkt_len;
-	}
-}
-
-/**
- * el_reset: Reset a 3c501 card
- * @dev: The 3c501 card about to get zapped
- *
- * 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.
- */
-
-static void  el_reset(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-
-	if (el_debug > 2)
-		pr_info("3c501 reset...\n");
-	outb(AX_RESET, AX_CMD);		/* Reset the chip */
-	/* Aux control, irq and loopback enabled */
-	outb(AX_LOOP, AX_CMD);
-	{
-		int i;
-		for (i = 0; i < 6; i++)	/* Set the station address. */
-			outb(dev->dev_addr[i], ioaddr + i);
-	}
-
-	outw(0, RX_BUF_CLR);		/* Set rx packet area to 0. */
-	outb(TX_NORM, TX_CMD);		/* tx irq on done, collision */
-	outb(RX_NORM, RX_CMD);		/* Set Rx commands. */
-	inb(RX_STATUS);			/* Clear status. */
-	inb(TX_STATUS);
-	lp->txing = 0;
-}
-
-/**
- * el1_close:
- * @dev: 3c501 card to shut down
- *
- * Close a 3c501 card. The IFF_UP flag has been cleared by the user via
- * the SIOCSIFFLAGS ioctl. We stop any further transmissions being queued,
- * and then disable the interrupts. Finally we reset the chip. The effects
- * of the rest will be cleaned up by #el1_open. Always returns 0 indicating
- * a success.
- */
-
-static int el1_close(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-
-	if (el_debug > 2)
-		pr_info("%s: Shutting down Ethernet card at %#x.\n",
-						dev->name, ioaddr);
-
-	netif_stop_queue(dev);
-
-	/*
-	 *	Free and disable the IRQ.
-	 */
-
-	free_irq(dev->irq, dev);
-	outb(AX_RESET, AX_CMD);		/* Reset the chip */
-
-	return 0;
-}
-
-/**
- * set_multicast_list:
- * @dev: The device to adjust
- *
- * Set or clear the multicast filter for this adaptor to use the best-effort
- * filtering supported. The 3c501 supports only three modes of filtering.
- * It always receives broadcasts and packets for itself. You can choose to
- * optionally receive all packets, or all multicast packets on top of this.
- */
-
-static void set_multicast_list(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-
-	if (dev->flags & IFF_PROMISC) {
-		outb(RX_PROM, RX_CMD);
-		inb(RX_STATUS);
-	} else if (!netdev_mc_empty(dev) || dev->flags & IFF_ALLMULTI) {
-		/* Multicast or all multicast is the same */
-		outb(RX_MULT, RX_CMD);
-		inb(RX_STATUS);		/* Clear status. */
-	} else {
-		outb(RX_NORM, RX_CMD);
-		inb(RX_STATUS);
-	}
-}
-
-
-static void netdev_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-	sprintf(info->bus_info, "ISA 0x%lx", dev->base_addr);
-}
-
-static u32 netdev_get_msglevel(struct net_device *dev)
-{
-	return debug;
-}
-
-static void netdev_set_msglevel(struct net_device *dev, u32 level)
-{
-	debug = level;
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-	.get_drvinfo		= netdev_get_drvinfo,
-	.get_msglevel		= netdev_get_msglevel,
-	.set_msglevel		= netdev_set_msglevel,
-};
-
-#ifdef MODULE
-
-static struct net_device *dev_3c501;
-
-module_param(io, int, 0);
-module_param(irq, int, 0);
-MODULE_PARM_DESC(io, "EtherLink I/O base address");
-MODULE_PARM_DESC(irq, "EtherLink IRQ number");
-
-/**
- * init_module:
- *
- * When the driver is loaded as a module this function is called. We fake up
- * a device structure with the base I/O and interrupt set as if it were being
- * called from Space.c. This minimises the extra code that would otherwise
- * be required.
- *
- * Returns 0 for success or -EIO if a card is not found. Returning an error
- * here also causes the module to be unloaded
- */
-
-int __init init_module(void)
-{
-	dev_3c501 = el1_probe(-1);
-	if (IS_ERR(dev_3c501))
-		return PTR_ERR(dev_3c501);
-	return 0;
-}
-
-/**
- * cleanup_module:
- *
- * The module is being unloaded. We unhook our network device from the system
- * and then free up the resources we took when the card was found.
- */
-
-void __exit cleanup_module(void)
-{
-	struct net_device *dev = dev_3c501;
-	unregister_netdev(dev);
-	release_region(dev->base_addr, EL1_IO_EXTENT);
-	free_netdev(dev);
-}
-
-#endif /* MODULE */
-
-MODULE_AUTHOR("Donald Becker, Alan Cox");
-MODULE_DESCRIPTION("Support for the ancient 3Com 3c501 ethernet card");
-MODULE_LICENSE("GPL");
-
diff -druN linux-libre-3.1-gnu/drivers/net/3c501.h linux-libre-3.2-gnu/drivers/net/3c501.h
--- linux-libre-3.1-gnu/drivers/net/3c501.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/3c501.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-
-/*
- *	Index to functions.
- */
-
-static int  el1_probe1(struct net_device *dev, int ioaddr);
-static int  el_open(struct net_device *dev);
-static void el_timeout(struct net_device *dev);
-static netdev_tx_t el_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t el_interrupt(int irq, void *dev_id);
-static void el_receive(struct net_device *dev);
-static void el_reset(struct net_device *dev);
-static int  el1_close(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
-static const struct ethtool_ops netdev_ethtool_ops;
-
-#define EL1_IO_EXTENT	16
-
-#ifndef EL_DEBUG
-#define EL_DEBUG  0	/* use 0 for production, 1 for devel., >2 for debug */
-#endif			/* Anything above 5 is wordy death! */
-#define debug el_debug
-static int el_debug = EL_DEBUG;
-
-/*
- *	Board-specific info in netdev_priv(dev).
- */
-
-struct net_local
-{
-	int		tx_pkt_start;	/* The length of the current Tx packet. */
-	int		collisions;	/* Tx collisions this packet */
-	int		loading;	/* Spot buffer load collisions */
-	int		txing;		/* True if card is in TX mode */
-	spinlock_t	lock;		/* Serializing lock */
-};
-
-
-#define RX_STATUS (ioaddr + 0x06)
-#define RX_CMD	  RX_STATUS
-#define TX_STATUS (ioaddr + 0x07)
-#define TX_CMD	  TX_STATUS
-#define GP_LOW 	  (ioaddr + 0x08)
-#define GP_HIGH   (ioaddr + 0x09)
-#define RX_BUF_CLR (ioaddr + 0x0A)
-#define RX_LOW	  (ioaddr + 0x0A)
-#define RX_HIGH   (ioaddr + 0x0B)
-#define SAPROM	  (ioaddr + 0x0C)
-#define AX_STATUS (ioaddr + 0x0E)
-#define AX_CMD	  AX_STATUS
-#define DATAPORT  (ioaddr + 0x0F)
-#define TX_RDY 0x08		/* In TX_STATUS */
-
-#define EL1_DATAPTR	0x08
-#define EL1_RXPTR	0x0A
-#define EL1_SAPROM	0x0C
-#define EL1_DATAPORT 	0x0f
-
-/*
- *	Writes to the ax command register.
- */
-
-#define AX_OFF	0x00			/* Irq off, buffer access on */
-#define AX_SYS  0x40			/* Load the buffer */
-#define AX_XMIT 0x44			/* Transmit a packet */
-#define AX_RX	0x48			/* Receive a packet */
-#define AX_LOOP	0x0C			/* Loopback mode */
-#define AX_RESET 0x80
-
-/*
- *	Normal receive mode written to RX_STATUS.  We must intr on short packets
- *	to avoid bogus rx lockups.
- */
-
-#define RX_NORM 0xA8		/* 0x68 == all addrs, 0xA8 only to me. */
-#define RX_PROM 0x68		/* Senior Prom, uhmm promiscuous mode. */
-#define RX_MULT 0xE8		/* Accept multicast packets. */
-#define TX_NORM 0x0A		/* Interrupt on everything that might hang the chip */
-
-/*
- *	TX_STATUS register.
- */
-
-#define TX_COLLISION 0x02
-#define TX_16COLLISIONS 0x04
-#define TX_READY 0x08
-
-#define RX_RUNT 0x08
-#define RX_MISSED 0x01		/* Missed a packet due to 3c501 braindamage. */
-#define RX_GOOD	0x30		/* Good packet 0x20, or simple overflow 0x10. */
-
diff -druN linux-libre-3.1-gnu/drivers/net/3c503.c linux-libre-3.2-gnu/drivers/net/3c503.c
--- linux-libre-3.1-gnu/drivers/net/3c503.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/3c503.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,778 +0,0 @@
-/* 3c503.c: A shared-memory NS8390 ethernet driver for linux. */
-/*
-    Written 1992-94 by Donald Becker.
-
-    Copyright 1993 United States Government as represented by the
-    Director, National Security Agency.  This software may be used and
-    distributed according to the terms of the GNU General Public License,
-    incorporated herein by reference.
-
-    The author may be reached as becker@scyld.com, or C/O
-	Scyld Computing Corporation
-	410 Severn Ave., Suite 210
-	Annapolis MD 21403
-
-
-    This driver should work with the 3c503 and 3c503/16.  It should be used
-    in shared memory mode for best performance, although it may also work
-    in programmed-I/O mode.
-
-    Sources:
-    EtherLink II Technical Reference Manual,
-    EtherLink II/16 Technical Reference Manual Supplement,
-    3Com Corporation, 5400 Bayfront Plaza, Santa Clara CA 95052-8145
-
-    The Crynwr 3c503 packet driver.
-
-    Changelog:
-
-    Paul Gortmaker	: add support for the 2nd 8kB of RAM on 16 bit cards.
-    Paul Gortmaker	: multiple card support for module users.
-    rjohnson@analogic.com : Fix up PIO interface for efficient operation.
-    Jeff Garzik		: ethtool support
-
-*/
-
-#define DRV_NAME	"3c503"
-#define DRV_VERSION	"1.10a"
-#define DRV_RELDATE	"11/17/2001"
-
-
-static const char version[] =
-    DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Donald Becker (becker@scyld.com)\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ethtool.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/byteorder.h>
-
-#include "8390.h"
-#include "3c503.h"
-#define WRD_COUNT 4
-
-static int el2_pio_probe(struct net_device *dev);
-static int el2_probe1(struct net_device *dev, int ioaddr);
-
-/* A zero-terminated list of I/O addresses to be probed in PIO mode. */
-static unsigned int netcard_portlist[] __initdata =
-	{ 0x300,0x310,0x330,0x350,0x250,0x280,0x2a0,0x2e0,0};
-
-#define EL2_IO_EXTENT	16
-
-static int el2_open(struct net_device *dev);
-static int el2_close(struct net_device *dev);
-static void el2_reset_8390(struct net_device *dev);
-static void el2_init_card(struct net_device *dev);
-static void el2_block_output(struct net_device *dev, int count,
-			     const unsigned char *buf, int start_page);
-static void el2_block_input(struct net_device *dev, int count, struct sk_buff *skb,
-			   int ring_offset);
-static void el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-			 int ring_page);
-static const struct ethtool_ops netdev_ethtool_ops;
-
-
-/* This routine probes for a memory-mapped 3c503 board by looking for
-   the "location register" at the end of the jumpered boot PROM space.
-   This works even if a PROM isn't there.
-
-   If the ethercard isn't found there is an optional probe for
-   ethercard jumpered to programmed-I/O mode.
-   */
-static int __init do_el2_probe(struct net_device *dev)
-{
-    int *addr, addrs[] = { 0xddffe, 0xd9ffe, 0xcdffe, 0xc9ffe, 0};
-    int base_addr = dev->base_addr;
-    int irq = dev->irq;
-
-    if (base_addr > 0x1ff)	/* Check a single specified location. */
-	return el2_probe1(dev, base_addr);
-    else if (base_addr != 0)		/* Don't probe at all. */
-	return -ENXIO;
-
-    for (addr = addrs; *addr; addr++) {
-	void __iomem *p = ioremap(*addr, 1);
-	unsigned base_bits;
-	int i;
-
-	if (!p)
-		continue;
-	base_bits = readb(p);
-	iounmap(p);
-	i = ffs(base_bits) - 1;
-	if (i == -1 || base_bits != (1 << i))
-	    continue;
-	if (el2_probe1(dev, netcard_portlist[i]) == 0)
-	    return 0;
-	dev->irq = irq;
-    }
-#if ! defined(no_probe_nonshared_memory)
-    return el2_pio_probe(dev);
-#else
-    return -ENODEV;
-#endif
-}
-
-/*  Try all of the locations that aren't obviously empty.  This touches
-    a lot of locations, and is much riskier than the code above. */
-static int __init
-el2_pio_probe(struct net_device *dev)
-{
-    int i;
-    int base_addr = dev->base_addr;
-    int irq = dev->irq;
-
-    if (base_addr > 0x1ff)	/* Check a single specified location. */
-	return el2_probe1(dev, base_addr);
-    else if (base_addr != 0)	/* Don't probe at all. */
-	return -ENXIO;
-
-    for (i = 0; netcard_portlist[i]; i++) {
-	if (el2_probe1(dev, netcard_portlist[i]) == 0)
-	    return 0;
-	dev->irq = irq;
-    }
-
-    return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init el2_probe(int unit)
-{
-	struct net_device *dev = alloc_eip_netdev();
-	int err;
-
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	sprintf(dev->name, "eth%d", unit);
-	netdev_boot_setup_check(dev);
-
-	err = do_el2_probe(dev);
-	if (err)
-		goto out;
-	return dev;
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-#endif
-
-static const struct net_device_ops el2_netdev_ops = {
-	.ndo_open		= el2_open,
-	.ndo_stop		= el2_close,
-
-	.ndo_start_xmit		= eip_start_xmit,
-	.ndo_tx_timeout		= eip_tx_timeout,
-	.ndo_get_stats		= eip_get_stats,
-	.ndo_set_multicast_list = eip_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 	= eip_poll,
-#endif
-};
-
-/* Probe for the Etherlink II card at I/O port base IOADDR,
-   returning non-zero on success.  If found, set the station
-   address and memory parameters in DEVICE. */
-static int __init
-el2_probe1(struct net_device *dev, int ioaddr)
-{
-    int i, iobase_reg, membase_reg, saved_406, wordlength, retval;
-    static unsigned version_printed;
-    unsigned long vendor_id;
-
-    if (!request_region(ioaddr, EL2_IO_EXTENT, DRV_NAME))
-	return -EBUSY;
-
-    if (!request_region(ioaddr + 0x400, 8, DRV_NAME)) {
-	retval = -EBUSY;
-	goto out;
-    }
-
-    /* Reset and/or avoid any lurking NE2000 */
-    if (inb(ioaddr + 0x408) == 0xff) {
-    	mdelay(1);
-	retval = -ENODEV;
-	goto out1;
-    }
-
-    /* We verify that it's a 3C503 board by checking the first three octets
-       of its ethernet address. */
-    iobase_reg = inb(ioaddr+0x403);
-    membase_reg = inb(ioaddr+0x404);
-    /* ASIC location registers should be 0 or have only a single bit set. */
-    if ((iobase_reg  & (iobase_reg - 1)) ||
-	(membase_reg & (membase_reg - 1))) {
-	retval = -ENODEV;
-	goto out1;
-    }
-    saved_406 = inb_p(ioaddr + 0x406);
-    outb_p(ECNTRL_RESET|ECNTRL_THIN, ioaddr + 0x406); /* Reset it... */
-    outb_p(ECNTRL_THIN, ioaddr + 0x406);
-    /* Map the station addr PROM into the lower I/O ports. We now check
-       for both the old and new 3Com prefix */
-    outb(ECNTRL_SAPROM|ECNTRL_THIN, ioaddr + 0x406);
-    vendor_id = inb(ioaddr)*0x10000 + inb(ioaddr + 1)*0x100 + inb(ioaddr + 2);
-    if ((vendor_id != OLD_3COM_ID) && (vendor_id != NEW_3COM_ID)) {
-	/* Restore the register we frobbed. */
-	outb(saved_406, ioaddr + 0x406);
-	retval = -ENODEV;
-	goto out1;
-    }
-
-    if (ei_debug  &&  version_printed++ == 0)
-	pr_debug("%s", version);
-
-    dev->base_addr = ioaddr;
-
-    pr_info("%s: 3c503 at i/o base %#3x, node ", dev->name, ioaddr);
-
-    /* Retrieve and print the ethernet address. */
-    for (i = 0; i < 6; i++)
-	dev->dev_addr[i] = inb(ioaddr + i);
-    pr_cont("%pM", dev->dev_addr);
-
-    /* Map the 8390 back into the window. */
-    outb(ECNTRL_THIN, ioaddr + 0x406);
-
-    /* Check for EL2/16 as described in tech. man. */
-    outb_p(E8390_PAGE0, ioaddr + E8390_CMD);
-    outb_p(0, ioaddr + EN0_DCFG);
-    outb_p(E8390_PAGE2, ioaddr + E8390_CMD);
-    wordlength = inb_p(ioaddr + EN0_DCFG) & ENDCFG_WTS;
-    outb_p(E8390_PAGE0, ioaddr + E8390_CMD);
-
-    /* Probe for, turn on and clear the board's shared memory. */
-    if (ei_debug > 2)
-	pr_cont(" memory jumpers %2.2x ", membase_reg);
-    outb(EGACFR_NORM, ioaddr + 0x405);	/* Enable RAM */
-
-    /* This should be probed for (or set via an ioctl()) at run-time.
-       Right now we use a sleazy hack to pass in the interface number
-       at boot-time via the low bits of the mem_end field.  That value is
-       unused, and the low bits would be discarded even if it was used. */
-#if defined(EI8390_THICK) || defined(EL2_AUI)
-    ei_status.interface_num = 1;
-#else
-    ei_status.interface_num = dev->mem_end & 0xf;
-#endif
-    pr_cont(", using %sternal xcvr.\n", ei_status.interface_num == 0 ? "in" : "ex");
-
-    if ((membase_reg & 0xf0) == 0) {
-	dev->mem_start = 0;
-	ei_status.name = "3c503-PIO";
-	ei_status.mem = NULL;
-    } else {
-	dev->mem_start = ((membase_reg & 0xc0) ? 0xD8000 : 0xC8000) +
-	    ((membase_reg & 0xA0) ? 0x4000 : 0);
-#define EL2_MEMSIZE (EL2_MB1_STOP_PG - EL2_MB1_START_PG)*256
-	ei_status.mem = ioremap(dev->mem_start, EL2_MEMSIZE);
-
-#ifdef EL2MEMTEST
-	/* This has never found an error, but someone might care.
-	   Note that it only tests the 2nd 8kB on 16kB 3c503/16
-	   cards between card addr. 0x2000 and 0x3fff. */
-	{			/* Check the card's memory. */
-	    void __iomem *mem_base = ei_status.mem;
-	    unsigned int test_val = 0xbbadf00d;
-	    writel(0xba5eba5e, mem_base);
-	    for (i = sizeof(test_val); i < EL2_MEMSIZE; i+=sizeof(test_val)) {
-		writel(test_val, mem_base + i);
-		if (readl(mem_base) != 0xba5eba5e ||
-		    readl(mem_base + i) != test_val) {
-		    pr_warning("3c503: memory failure or memory address conflict.\n");
-		    dev->mem_start = 0;
-		    ei_status.name = "3c503-PIO";
-		    iounmap(mem_base);
-		    ei_status.mem = NULL;
-		    break;
-		}
-		test_val += 0x55555555;
-		writel(0, mem_base + i);
-	    }
-	}
-#endif  /* EL2MEMTEST */
-
-	if (dev->mem_start)
-		dev->mem_end = dev->mem_start + EL2_MEMSIZE;
-
-	if (wordlength) {	/* No Tx pages to skip over to get to Rx */
-		ei_status.priv = 0;
-		ei_status.name = "3c503/16";
-	} else {
-		ei_status.priv = TX_PAGES * 256;
-		ei_status.name = "3c503";
-	}
-    }
-
-    /*
-	Divide up the memory on the card. This is the same regardless of
-	whether shared-mem or PIO is used. For 16 bit cards (16kB RAM),
-	we use the entire 8k of bank1 for an Rx ring. We only use 3k
-	of the bank0 for 2 full size Tx packet slots. For 8 bit cards,
-	(8kB RAM) we use 3kB of bank1 for two Tx slots, and the remaining
-	5kB for an Rx ring.  */
-
-    if (wordlength) {
-	ei_status.tx_start_page = EL2_MB0_START_PG;
-	ei_status.rx_start_page = EL2_MB1_START_PG;
-    } else {
-	ei_status.tx_start_page = EL2_MB1_START_PG;
-	ei_status.rx_start_page = EL2_MB1_START_PG + TX_PAGES;
-    }
-
-    /* Finish setting the board's parameters. */
-    ei_status.stop_page = EL2_MB1_STOP_PG;
-    ei_status.word16 = wordlength;
-    ei_status.reset_8390 = el2_reset_8390;
-    ei_status.get_8390_hdr = el2_get_8390_hdr;
-    ei_status.block_input = el2_block_input;
-    ei_status.block_output = el2_block_output;
-
-    if (dev->irq == 2)
-	dev->irq = 9;
-    else if (dev->irq > 5 && dev->irq != 9) {
-	pr_warning("3c503: configured interrupt %d invalid, will use autoIRQ.\n",
-	       dev->irq);
-	dev->irq = 0;
-    }
-
-    ei_status.saved_irq = dev->irq;
-
-    dev->netdev_ops = &el2_netdev_ops;
-    dev->ethtool_ops = &netdev_ethtool_ops;
-
-    retval = register_netdev(dev);
-    if (retval)
-	goto out1;
-
-    if (dev->mem_start)
-	pr_info("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n",
-		dev->name, ei_status.name, (wordlength+1)<<3,
-		dev->mem_start, dev->mem_end-1);
-
-    else
-    {
-	ei_status.tx_start_page = EL2_MB1_START_PG;
-	ei_status.rx_start_page = EL2_MB1_START_PG + TX_PAGES;
-	pr_info("%s: %s, %dkB RAM, using programmed I/O (REJUMPER for SHARED MEMORY).\n",
-	       dev->name, ei_status.name, (wordlength+1)<<3);
-    }
-    release_region(ioaddr + 0x400, 8);
-    return 0;
-out1:
-    release_region(ioaddr + 0x400, 8);
-out:
-    release_region(ioaddr, EL2_IO_EXTENT);
-    return retval;
-}
-
-static irqreturn_t el2_probe_interrupt(int irq, void *seen)
-{
-	*(bool *)seen = true;
-	return IRQ_HANDLED;
-}
-
-static int
-el2_open(struct net_device *dev)
-{
-    int retval;
-
-    if (dev->irq < 2) {
-	static const int irqlist[] = {5, 9, 3, 4, 0};
-	const int *irqp = irqlist;
-
-	outb(EGACFR_NORM, E33G_GACFR);	/* Enable RAM and interrupts. */
-	do {
-		bool seen;
-
-		retval = request_irq(*irqp, el2_probe_interrupt, 0,
-				     dev->name, &seen);
-		if (retval == -EBUSY)
-			continue;
-		if (retval < 0)
-			goto err_disable;
-
-		/* Twinkle the interrupt, and check if it's seen. */
-		seen = false;
-		smp_wmb();
-		outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR);
-		outb_p(0x00, E33G_IDCFR);
-		msleep(1);
-		free_irq(*irqp, &seen);
-		if (!seen)
-			continue;
-
-		retval = request_irq(dev->irq = *irqp, eip_interrupt, 0,
-				     dev->name, dev);
-		if (retval == -EBUSY)
-			continue;
-		if (retval < 0)
-			goto err_disable;
-		break;
-	} while (*++irqp);
-
-	if (*irqp == 0) {
-	err_disable:
-	    outb(EGACFR_IRQOFF, E33G_GACFR);	/* disable interrupts. */
-	    return -EAGAIN;
-	}
-    } else {
-	if ((retval = request_irq(dev->irq, eip_interrupt, 0, dev->name, dev))) {
-	    return retval;
-	}
-    }
-
-    el2_init_card(dev);
-    eip_open(dev);
-    return 0;
-}
-
-static int
-el2_close(struct net_device *dev)
-{
-    free_irq(dev->irq, dev);
-    dev->irq = ei_status.saved_irq;
-    outb(EGACFR_IRQOFF, E33G_GACFR);	/* disable interrupts. */
-
-    eip_close(dev);
-    return 0;
-}
-
-/* This is called whenever we have a unrecoverable failure:
-       transmit timeout
-       Bad ring buffer packet header
- */
-static void
-el2_reset_8390(struct net_device *dev)
-{
-    if (ei_debug > 1) {
-	pr_debug("%s: Resetting the 3c503 board...", dev->name);
-	pr_cont(" %#lx=%#02x %#lx=%#02x %#lx=%#02x...", E33G_IDCFR, inb(E33G_IDCFR),
-	       E33G_CNTRL, inb(E33G_CNTRL), E33G_GACFR, inb(E33G_GACFR));
-    }
-    outb_p(ECNTRL_RESET|ECNTRL_THIN, E33G_CNTRL);
-    ei_status.txing = 0;
-    outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
-    el2_init_card(dev);
-    if (ei_debug > 1)
-	pr_cont("done\n");
-}
-
-/* Initialize the 3c503 GA registers after a reset. */
-static void
-el2_init_card(struct net_device *dev)
-{
-    /* Unmap the station PROM and select the DIX or BNC connector. */
-    outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
-
-    /* Set ASIC copy of rx's first and last+1 buffer pages */
-    /* These must be the same as in the 8390. */
-    outb(ei_status.rx_start_page, E33G_STARTPG);
-    outb(ei_status.stop_page,  E33G_STOPPG);
-
-    /* Point the vector pointer registers somewhere ?harmless?. */
-    outb(0xff, E33G_VP2);	/* Point at the ROM restart location 0xffff0 */
-    outb(0xff, E33G_VP1);
-    outb(0x00, E33G_VP0);
-    /* Turn off all interrupts until we're opened. */
-    outb_p(0x00,  dev->base_addr + EN0_IMR);
-    /* Enable IRQs iff started. */
-    outb(EGACFR_NORM, E33G_GACFR);
-
-    /* Set the interrupt line. */
-    outb_p((0x04 << (dev->irq == 9 ? 2 : dev->irq)), E33G_IDCFR);
-    outb_p((WRD_COUNT << 1), E33G_DRQCNT);	/* Set burst size to 8 */
-    outb_p(0x20, E33G_DMAAH);	/* Put a valid addr in the GA DMA */
-    outb_p(0x00, E33G_DMAAL);
-    return;			/* We always succeed */
-}
-
-/*
- * Either use the shared memory (if enabled on the board) or put the packet
- * out through the ASIC FIFO.
- */
-static void
-el2_block_output(struct net_device *dev, int count,
-		 const unsigned char *buf, int start_page)
-{
-    unsigned short int *wrd;
-    int boguscount;		/* timeout counter */
-    unsigned short word;	/* temporary for better machine code */
-    void __iomem *base = ei_status.mem;
-
-    if (ei_status.word16)      /* Tx packets go into bank 0 on EL2/16 card */
-	outb(EGACFR_RSEL|EGACFR_TCM, E33G_GACFR);
-    else
-	outb(EGACFR_NORM, E33G_GACFR);
-
-    if (base) {	/* Shared memory transfer */
-	memcpy_toio(base + ((start_page - ei_status.tx_start_page) << 8),
-			buf, count);
-	outb(EGACFR_NORM, E33G_GACFR);	/* Back to bank1 in case on bank0 */
-	return;
-    }
-
-/*
- *  No shared memory, put the packet out the other way.
- *  Set up then start the internal memory transfer to Tx Start Page
- */
-
-    word = (unsigned short)start_page;
-    outb(word&0xFF, E33G_DMAAH);
-    outb(word>>8, E33G_DMAAL);
-
-    outb_p((ei_status.interface_num ? ECNTRL_AUI : ECNTRL_THIN ) | ECNTRL_OUTPUT
-	   | ECNTRL_START, E33G_CNTRL);
-
-/*
- *  Here I am going to write data to the FIFO as quickly as possible.
- *  Note that E33G_FIFOH is defined incorrectly. It is really
- *  E33G_FIFOL, the lowest port address for both the byte and
- *  word write. Variable 'count' is NOT checked. Caller must supply a
- *  valid count. Note that I may write a harmless extra byte to the
- *  8390 if the byte-count was not even.
- */
-    wrd = (unsigned short int *) buf;
-    count  = (count + 1) >> 1;
-    for(;;)
-    {
-        boguscount = 0x1000;
-        while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
-        {
-            if(!boguscount--)
-            {
-                pr_notice("%s: FIFO blocked in el2_block_output.\n", dev->name);
-                el2_reset_8390(dev);
-                goto blocked;
-            }
-        }
-        if(count > WRD_COUNT)
-        {
-            outsw(E33G_FIFOH, wrd, WRD_COUNT);
-            wrd   += WRD_COUNT;
-            count -= WRD_COUNT;
-        }
-        else
-        {
-            outsw(E33G_FIFOH, wrd, count);
-            break;
-        }
-    }
-    blocked:;
-    outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
-}
-
-/* Read the 4 byte, page aligned 8390 specific header. */
-static void
-el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-    int boguscount;
-    void __iomem *base = ei_status.mem;
-    unsigned short word;
-
-    if (base) {       /* Use the shared memory. */
-	void __iomem *hdr_start = base + ((ring_page - EL2_MB1_START_PG)<<8);
-	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
-	hdr->count = le16_to_cpu(hdr->count);
-	return;
-    }
-
-/*
- *  No shared memory, use programmed I/O.
- */
-
-    word = (unsigned short)ring_page;
-    outb(word&0xFF, E33G_DMAAH);
-    outb(word>>8, E33G_DMAAL);
-
-    outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT
-	   | ECNTRL_START, E33G_CNTRL);
-    boguscount = 0x1000;
-    while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
-    {
-        if(!boguscount--)
-        {
-            pr_notice("%s: FIFO blocked in el2_get_8390_hdr.\n", dev->name);
-            memset(hdr, 0x00, sizeof(struct e8390_pkt_hdr));
-            el2_reset_8390(dev);
-            goto blocked;
-        }
-    }
-    insw(E33G_FIFOH, hdr, (sizeof(struct e8390_pkt_hdr))>> 1);
-    blocked:;
-    outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
-}
-
-
-static void
-el2_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-    int boguscount = 0;
-    void __iomem *base = ei_status.mem;
-    unsigned short int *buf;
-    unsigned short word;
-
-    /* Maybe enable shared memory just be to be safe... nahh.*/
-    if (base) {	/* Use the shared memory. */
-	ring_offset -= (EL2_MB1_START_PG<<8);
-	if (ring_offset + count > EL2_MEMSIZE) {
-	    /* We must wrap the input move. */
-	    int semi_count = EL2_MEMSIZE - ring_offset;
-	    memcpy_fromio(skb->data, base + ring_offset, semi_count);
-	    count -= semi_count;
-	    memcpy_fromio(skb->data + semi_count, base + ei_status.priv, count);
-	} else {
-		memcpy_fromio(skb->data, base + ring_offset, count);
-	}
-	return;
-    }
-
-/*
- *  No shared memory, use programmed I/O.
- */
-    word = (unsigned short) ring_offset;
-    outb(word>>8, E33G_DMAAH);
-    outb(word&0xFF, E33G_DMAAL);
-
-    outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT
-	   | ECNTRL_START, E33G_CNTRL);
-
-/*
- *  Here I also try to get data as fast as possible. I am betting that I
- *  can read one extra byte without clobbering anything in the kernel because
- *  this would only occur on an odd byte-count and allocation of skb->data
- *  is word-aligned. Variable 'count' is NOT checked. Caller must check
- *  for a valid count.
- *  [This is currently quite safe.... but if one day the 3c503 explodes
- *   you know where to come looking ;)]
- */
-
-    buf =  (unsigned short int *) skb->data;
-    count =  (count + 1) >> 1;
-    for(;;)
-    {
-        boguscount = 0x1000;
-        while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
-        {
-            if(!boguscount--)
-            {
-                pr_notice("%s: FIFO blocked in el2_block_input.\n", dev->name);
-                el2_reset_8390(dev);
-                goto blocked;
-            }
-        }
-        if(count > WRD_COUNT)
-        {
-            insw(E33G_FIFOH, buf, WRD_COUNT);
-            buf   += WRD_COUNT;
-            count -= WRD_COUNT;
-        }
-        else
-        {
-            insw(E33G_FIFOH, buf, count);
-            break;
-        }
-    }
-    blocked:;
-    outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
-}
-
-
-static void netdev_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-	sprintf(info->bus_info, "ISA 0x%lx", dev->base_addr);
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-	.get_drvinfo		= netdev_get_drvinfo,
-};
-
-#ifdef MODULE
-#define MAX_EL2_CARDS	4	/* Max number of EL2 cards per module */
-
-static struct net_device *dev_el2[MAX_EL2_CARDS];
-static int io[MAX_EL2_CARDS];
-static int irq[MAX_EL2_CARDS];
-static int xcvr[MAX_EL2_CARDS];	/* choose int. or ext. xcvr */
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(xcvr, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es)");
-MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
-MODULE_PARM_DESC(xcvr, "transceiver(s) (0=internal, 1=external)");
-MODULE_DESCRIPTION("3Com ISA EtherLink II, II/16 (3c503, 3c503/16) driver");
-MODULE_LICENSE("GPL");
-
-/* This is set up so that only a single autoprobe takes place per call.
-ISA device autoprobes on a running machine are not recommended. */
-int __init
-init_module(void)
-{
-	struct net_device *dev;
-	int this_dev, found = 0;
-
-	for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) {
-		if (io[this_dev] == 0)  {
-			if (this_dev != 0) break; /* only autoprobe 1st one */
-			pr_notice("3c503.c: Presently autoprobing (not recommended) for a single card.\n");
-		}
-		dev = alloc_eip_netdev();
-		if (!dev)
-			break;
-		dev->irq = irq[this_dev];
-		dev->base_addr = io[this_dev];
-		dev->mem_end = xcvr[this_dev];	/* low 4bits = xcvr sel. */
-		if (do_el2_probe(dev) == 0) {
-			dev_el2[found++] = dev;
-			continue;
-		}
-		free_netdev(dev);
-		pr_warning("3c503.c: No 3c503 card found (i/o = 0x%x).\n", io[this_dev]);
-		break;
-	}
-	if (found)
-		return 0;
-	return -ENXIO;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-	/* NB: el2_close() handles free_irq */
-	release_region(dev->base_addr, EL2_IO_EXTENT);
-	if (ei_status.mem)
-		iounmap(ei_status.mem);
-}
-
-void __exit
-cleanup_module(void)
-{
-	int this_dev;
-
-	for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) {
-		struct net_device *dev = dev_el2[this_dev];
-		if (dev) {
-			unregister_netdev(dev);
-			cleanup_card(dev);
-			free_netdev(dev);
-		}
-	}
-}
-#endif /* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/3c503.h linux-libre-3.2-gnu/drivers/net/3c503.h
--- linux-libre-3.1-gnu/drivers/net/3c503.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/3c503.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-/* Definitions for the 3Com 3c503 Etherlink 2. */
-/* This file is distributed under the GPL.
-   Many of these names and comments are directly from the Crynwr packet
-   drivers, which are released under the GPL. */
-
-#define EL2H (dev->base_addr + 0x400)
-#define EL2L (dev->base_addr)
-
-/* Vendor unique hardware addr. prefix. 3Com has 2 because they ran
-   out of available addresses on the first one... */
-
-#define OLD_3COM_ID	0x02608c
-#define NEW_3COM_ID	0x0020af
-
-/* Shared memory management parameters. NB: The 8 bit cards have only
-   one bank (MB1) which serves both Tx and Rx packet space. The 16bit
-   cards have 2 banks, MB0 for Tx packets, and MB1 for Rx packets.
-   You choose which bank appears in the sh. mem window with EGACFR_MBSn */
-
-#define EL2_MB0_START_PG	(0x00)	/* EL2/16 Tx packets go in bank 0 */
-#define EL2_MB1_START_PG	(0x20)	/* First page of bank 1 */
-#define EL2_MB1_STOP_PG		(0x40)	/* Last page +1 of bank 1 */
-
-/* 3Com 3c503 ASIC registers */
-#define E33G_STARTPG	(EL2H+0)	/* Start page, matching EN0_STARTPG */
-#define E33G_STOPPG	(EL2H+1)	/* Stop page, must match EN0_STOPPG */
-#define E33G_DRQCNT	(EL2H+2)	/* DMA burst count */
-#define E33G_IOBASE	(EL2H+3)	/* Read of I/O base jumpers. */
-	/* (non-useful, but it also appears at the end of EPROM space) */
-#define E33G_ROMBASE	(EL2H+4)	/* Read of memory base jumpers. */
-#define E33G_GACFR	(EL2H+5)	/* Config/setup bits for the ASIC GA */
-#define E33G_CNTRL	(EL2H+6)	/* Board's main control register */
-#define E33G_STATUS	(EL2H+7)	/* Status on completions. */
-#define E33G_IDCFR	(EL2H+8)	/* Interrupt/DMA config register */
-				/* (Which IRQ to assert, DMA chan to use) */
-#define E33G_DMAAH	(EL2H+9)	/* High byte of DMA address reg */
-#define E33G_DMAAL	(EL2H+10)	/* Low byte of DMA address reg */
-/* "Vector pointer" - if this address matches a read, the EPROM (rather than
-   shared RAM) is mapped into memory space. */
-#define E33G_VP2	(EL2H+11)
-#define E33G_VP1	(EL2H+12)
-#define E33G_VP0	(EL2H+13)
-#define E33G_FIFOH	(EL2H+14)	/* FIFO for programmed I/O moves */
-#define E33G_FIFOL	(EL2H+15)	/* ... low byte of above. */
-
-/* Bits in E33G_CNTRL register: */
-
-#define ECNTRL_RESET	(0x01)	/* Software reset of the ASIC and 8390 */
-#define ECNTRL_THIN	(0x02)	/* Onboard xcvr enable, AUI disable */
-#define ECNTRL_AUI	(0x00)	/* Onboard xcvr disable, AUI enable */
-#define ECNTRL_SAPROM	(0x04)	/* Map the station address prom */
-#define ECNTRL_DBLBFR	(0x20)	/* FIFO configuration bit */
-#define ECNTRL_OUTPUT	(0x40)	/* PC-to-3C503 direction if 1 */
-#define ECNTRL_INPUT	(0x00)	/* 3C503-to-PC direction if 0 */
-#define ECNTRL_START	(0x80)	/* Start the DMA logic */
-
-/* Bits in E33G_STATUS register: */
-
-#define ESTAT_DPRDY	(0x80)	/* Data port (of FIFO) ready */
-#define ESTAT_UFLW	(0x40)	/* Tried to read FIFO when it was empty */
-#define ESTAT_OFLW	(0x20)	/* Tried to write FIFO when it was full */
-#define ESTAT_DTC	(0x10)	/* Terminal Count from PC bus DMA logic */
-#define ESTAT_DIP	(0x08)	/* DMA In Progress */
-
-/* Bits in E33G_GACFR register: */
-
-#define EGACFR_NIM	(0x80)	/* NIC interrupt mask */
-#define EGACFR_TCM	(0x40)	/* DMA term. count interrupt mask */
-#define EGACFR_RSEL	(0x08)	/* Map a bank of card mem into system mem */
-#define EGACFR_MBS2	(0x04)	/* Memory bank select, bit 2. */
-#define EGACFR_MBS1	(0x02)	/* Memory bank select, bit 1. */
-#define EGACFR_MBS0	(0x01)	/* Memory bank select, bit 0. */
-
-#define EGACFR_NORM	(0x49)	/* TCM | RSEL | MBS0 */
-#define EGACFR_IRQOFF	(0xc9)	/* TCM | RSEL | MBS0 | NIM */
-
-/*
-	MBS2	MBS1	MBS0	Sh. mem windows card mem at:
-	----	----	----	-----------------------------
-	0	0	0	0x0000 -- bank 0
-	0	0	1	0x2000 -- bank 1 (only choice for 8bit card)
-	0	1	0	0x4000 -- bank 2, not used
-	0	1	1	0x6000 -- bank 3, not used
-
-There was going to be a 32k card that used bank 2 and 3, but it
-never got produced.
-
-*/
-
-
-/* End of 3C503 parameter definitions */
diff -druN linux-libre-3.1-gnu/drivers/net/3c505.c linux-libre-3.2-gnu/drivers/net/3c505.c
--- linux-libre-3.1-gnu/drivers/net/3c505.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/3c505.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1673 +0,0 @@
-/*
- * Linux Ethernet device driver for the 3Com Etherlink Plus (3C505)
- *      By Craig Southeren, Juha Laiho and Philip Blundell
- *
- * 3c505.c      This module implements an interface to the 3Com
- *              Etherlink Plus (3c505) Ethernet card. Linux device
- *              driver interface reverse engineered from the Linux 3C509
- *              device drivers. Some 3C505 information gleaned from
- *              the Crynwr packet driver. Still this driver would not
- *              be here without 3C505 technical reference provided by
- *              3Com.
- *
- * $Id: 3c505.c,v 1.10 1996/04/16 13:06:27 phil Exp $
- *
- * Authors:     Linux 3c505 device driver by
- *                      Craig Southeren, <craigs@ineluki.apana.org.au>
- *              Final debugging by
- *                      Andrew Tridgell, <tridge@nimbus.anu.edu.au>
- *              Auto irq/address, tuning, cleanup and v1.1.4+ kernel mods by
- *                      Juha Laiho, <jlaiho@ichaos.nullnet.fi>
- *              Linux 3C509 driver by
- *                      Donald Becker, <becker@super.org>
- *			(Now at <becker@scyld.com>)
- *              Crynwr packet driver by
- *                      Krishnan Gopalan and Gregg Stefancik,
- *                      Clemson University Engineering Computer Operations.
- *                      Portions of the code have been adapted from the 3c505
- *                         driver for NCSA Telnet by Bruce Orchard and later
- *                         modified by Warren Van Houten and krus@diku.dk.
- *              3C505 technical information provided by
- *                      Terry Murphy, of 3Com Network Adapter Division
- *              Linux 1.3.0 changes by
- *                      Alan Cox <Alan.Cox@linux.org>
- *              More debugging, DMA support, currently maintained by
- *                      Philip Blundell <philb@gnu.org>
- *              Multicard/soft configurable dma channel/rev 2 hardware support
- *                      by Christopher Collins <ccollins@pcug.org.au>
- *		Ethtool support (jgarzik), 11/17/2001
- */
-
-#define DRV_NAME	"3c505"
-#define DRV_VERSION	"1.10a"
-
-
-/* Theory of operation:
- *
- * The 3c505 is quite an intelligent board.  All communication with it is done
- * by means of Primary Command Blocks (PCBs); these are transferred using PIO
- * through the command register.  The card has 256k of on-board RAM, which is
- * used to buffer received packets.  It might seem at first that more buffers
- * are better, but in fact this isn't true.  From my tests, it seems that
- * more than about 10 buffers are unnecessary, and there is a noticeable
- * performance hit in having more active on the card.  So the majority of the
- * card's memory isn't, in fact, used.  Sadly, the card only has one transmit
- * buffer and, short of loading our own firmware into it (which is what some
- * drivers resort to) there's nothing we can do about this.
- *
- * We keep up to 4 "receive packet" commands active on the board at a time.
- * When a packet comes in, so long as there is a receive command active, the
- * board will send us a "packet received" PCB and then add the data for that
- * packet to the DMA queue.  If a DMA transfer is not already in progress, we
- * set one up to start uploading the data.  We have to maintain a list of
- * backlogged receive packets, because the card may decide to tell us about
- * a newly-arrived packet at any time, and we may not be able to start a DMA
- * transfer immediately (ie one may already be going on).  We can't NAK the
- * PCB, because then it would throw the packet away.
- *
- * Trying to send a PCB to the card at the wrong moment seems to have bad
- * effects.  If we send it a transmit PCB while a receive DMA is happening,
- * it will just NAK the PCB and so we will have wasted our time.  Worse, it
- * sometimes seems to interrupt the transfer.  The majority of the low-level
- * code is protected by one huge semaphore -- "busy" -- which is set whenever
- * it probably isn't safe to do anything to the card.  The receive routine
- * must gain a lock on "busy" before it can start a DMA transfer, and the
- * transmit routine must gain a lock before it sends the first PCB to the card.
- * The send_pcb() routine also has an internal semaphore to protect it against
- * being re-entered (which would be disastrous) -- this is needed because
- * several things can happen asynchronously (re-priming the receiver and
- * asking the card for statistics, for example).  send_pcb() will also refuse
- * to talk to the card at all if a DMA upload is happening.  The higher-level
- * networking code will reschedule a later retry if some part of the driver
- * is blocked.  In practice, this doesn't seem to happen very often.
- */
-
-/* This driver may now work with revision 2.x hardware, since all the read
- * operations on the HCR have been removed (we now keep our own softcopy).
- * But I don't have an old card to test it on.
- *
- * This has had the bad effect that the autoprobe routine is now a bit
- * less friendly to other devices.  However, it was never very good.
- * before, so I doubt it will hurt anybody.
- */
-
-/* The driver is a mess.  I took Craig's and Juha's code, and hacked it firstly
- * to make it more reliable, and secondly to add DMA mode.  Many things could
- * probably be done better; the concurrency protection is particularly awful.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/in.h>
-#include <linux/ioport.h>
-#include <linux/spinlock.h>
-#include <linux/ethtool.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-#include <linux/gfp.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-
-#include "3c505.h"
-
-/*********************************************************
- *
- *  define debug messages here as common strings to reduce space
- *
- *********************************************************/
-
-#define filename __FILE__
-
-#define timeout_msg "*** timeout at %s:%s (line %d) ***\n"
-#define TIMEOUT_MSG(lineno) \
-	pr_notice(timeout_msg, filename, __func__, (lineno))
-
-#define invalid_pcb_msg "*** invalid pcb length %d at %s:%s (line %d) ***\n"
-#define INVALID_PCB_MSG(len) \
-	pr_notice(invalid_pcb_msg, (len), filename, __func__, __LINE__)
-
-#define search_msg "%s: Looking for 3c505 adapter at address %#x..."
-
-#define stilllooking_msg "still looking..."
-
-#define found_msg "found.\n"
-
-#define notfound_msg "not found (reason = %d)\n"
-
-#define couldnot_msg "%s: 3c505 not found\n"
-
-/*********************************************************
- *
- *  various other debug stuff
- *
- *********************************************************/
-
-#ifdef ELP_DEBUG
-static int elp_debug = ELP_DEBUG;
-#else
-static int elp_debug;
-#endif
-#define debug elp_debug
-
-/*
- *  0 = no messages (well, some)
- *  1 = messages when high level commands performed
- *  2 = messages when low level commands performed
- *  3 = messages when interrupts received
- */
-
-/*****************************************************************
- *
- * List of I/O-addresses we try to auto-sense
- * Last element MUST BE 0!
- *****************************************************************/
-
-static int addr_list[] __initdata = {0x300, 0x280, 0x310, 0};
-
-/* Dma Memory related stuff */
-
-static unsigned long dma_mem_alloc(int size)
-{
-	int order = get_order(size);
-	return __get_dma_pages(GFP_KERNEL, order);
-}
-
-
-/*****************************************************************
- *
- * Functions for I/O (note the inline !)
- *
- *****************************************************************/
-
-static inline unsigned char inb_status(unsigned int base_addr)
-{
-	return inb(base_addr + PORT_STATUS);
-}
-
-static inline int inb_command(unsigned int base_addr)
-{
-	return inb(base_addr + PORT_COMMAND);
-}
-
-static inline void outb_control(unsigned char val, struct net_device *dev)
-{
-	outb(val, dev->base_addr + PORT_CONTROL);
-	((elp_device *)(netdev_priv(dev)))->hcr_val = val;
-}
-
-#define HCR_VAL(x)   (((elp_device *)(netdev_priv(x)))->hcr_val)
-
-static inline void outb_command(unsigned char val, unsigned int base_addr)
-{
-	outb(val, base_addr + PORT_COMMAND);
-}
-
-static inline unsigned int backlog_next(unsigned int n)
-{
-	return (n + 1) % BACKLOG_SIZE;
-}
-
-/*****************************************************************
- *
- *  useful functions for accessing the adapter
- *
- *****************************************************************/
-
-/*
- * use this routine when accessing the ASF bits as they are
- * changed asynchronously by the adapter
- */
-
-/* get adapter PCB status */
-#define	GET_ASF(addr) \
-	(get_status(addr)&ASF_PCB_MASK)
-
-static inline int get_status(unsigned int base_addr)
-{
-	unsigned long timeout = jiffies + 10*HZ/100;
-	register int stat1;
-	do {
-		stat1 = inb_status(base_addr);
-	} while (stat1 != inb_status(base_addr) && time_before(jiffies, timeout));
-	if (time_after_eq(jiffies, timeout))
-		TIMEOUT_MSG(__LINE__);
-	return stat1;
-}
-
-static inline void set_hsf(struct net_device *dev, int hsf)
-{
-	elp_device *adapter = netdev_priv(dev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	outb_control((HCR_VAL(dev) & ~HSF_PCB_MASK) | hsf, dev);
-	spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-static bool start_receive(struct net_device *, pcb_struct *);
-
-static inline void adapter_reset(struct net_device *dev)
-{
-	unsigned long timeout;
-	elp_device *adapter = netdev_priv(dev);
-	unsigned char orig_hcr = adapter->hcr_val;
-
-	outb_control(0, dev);
-
-	if (inb_status(dev->base_addr) & ACRF) {
-		do {
-			inb_command(dev->base_addr);
-			timeout = jiffies + 2*HZ/100;
-			while (time_before_eq(jiffies, timeout) && !(inb_status(dev->base_addr) & ACRF));
-		} while (inb_status(dev->base_addr) & ACRF);
-		set_hsf(dev, HSF_PCB_NAK);
-	}
-	outb_control(adapter->hcr_val | ATTN | DIR, dev);
-	mdelay(10);
-	outb_control(adapter->hcr_val & ~ATTN, dev);
-	mdelay(10);
-	outb_control(adapter->hcr_val | FLSH, dev);
-	mdelay(10);
-	outb_control(adapter->hcr_val & ~FLSH, dev);
-	mdelay(10);
-
-	outb_control(orig_hcr, dev);
-	if (!start_receive(dev, &adapter->tx_pcb))
-		pr_err("%s: start receive command failed\n", dev->name);
-}
-
-/* Check to make sure that a DMA transfer hasn't timed out.  This should
- * never happen in theory, but seems to occur occasionally if the card gets
- * prodded at the wrong time.
- */
-static inline void check_3c505_dma(struct net_device *dev)
-{
-	elp_device *adapter = netdev_priv(dev);
-	if (adapter->dmaing && time_after(jiffies, adapter->current_dma.start_time + 10)) {
-		unsigned long flags, f;
-		pr_err("%s: DMA %s timed out, %d bytes left\n", dev->name,
-			adapter->current_dma.direction ? "download" : "upload",
-			get_dma_residue(dev->dma));
-		spin_lock_irqsave(&adapter->lock, flags);
-		adapter->dmaing = 0;
-		adapter->busy = 0;
-
-		f=claim_dma_lock();
-		disable_dma(dev->dma);
-		release_dma_lock(f);
-
-		if (adapter->rx_active)
-			adapter->rx_active--;
-		outb_control(adapter->hcr_val & ~(DMAE | TCEN | DIR), dev);
-		spin_unlock_irqrestore(&adapter->lock, flags);
-	}
-}
-
-/* Primitive functions used by send_pcb() */
-static inline bool send_pcb_slow(unsigned int base_addr, unsigned char byte)
-{
-	unsigned long timeout;
-	outb_command(byte, base_addr);
-	for (timeout = jiffies + 5*HZ/100; time_before(jiffies, timeout);) {
-		if (inb_status(base_addr) & HCRE)
-			return false;
-	}
-	pr_warning("3c505: send_pcb_slow timed out\n");
-	return true;
-}
-
-static inline bool send_pcb_fast(unsigned int base_addr, unsigned char byte)
-{
-	unsigned int timeout;
-	outb_command(byte, base_addr);
-	for (timeout = 0; timeout < 40000; timeout++) {
-		if (inb_status(base_addr) & HCRE)
-			return false;
-	}
-	pr_warning("3c505: send_pcb_fast timed out\n");
-	return true;
-}
-
-/* Check to see if the receiver needs restarting, and kick it if so */
-static inline void prime_rx(struct net_device *dev)
-{
-	elp_device *adapter = netdev_priv(dev);
-	while (adapter->rx_active < ELP_RX_PCBS && netif_running(dev)) {
-		if (!start_receive(dev, &adapter->itx_pcb))
-			break;
-	}
-}
-
-/*****************************************************************
- *
- * send_pcb
- *   Send a PCB to the adapter.
- *
- *	output byte to command reg  --<--+
- *	wait until HCRE is non zero      |
- *	loop until all bytes sent   -->--+
- *	set HSF1 and HSF2 to 1
- *	output pcb length
- *	wait until ASF give ACK or NAK
- *	set HSF1 and HSF2 to 0
- *
- *****************************************************************/
-
-/* This can be quite slow -- the adapter is allowed to take up to 40ms
- * to respond to the initial interrupt.
- *
- * We run initially with interrupts turned on, but with a semaphore set
- * so that nobody tries to re-enter this code.  Once the first byte has
- * gone through, we turn interrupts off and then send the others (the
- * timeout is reduced to 500us).
- */
-
-static bool send_pcb(struct net_device *dev, pcb_struct * pcb)
-{
-	int i;
-	unsigned long timeout;
-	elp_device *adapter = netdev_priv(dev);
-	unsigned long flags;
-
-	check_3c505_dma(dev);
-
-	if (adapter->dmaing && adapter->current_dma.direction == 0)
-		return false;
-
-	/* Avoid contention */
-	if (test_and_set_bit(1, &adapter->send_pcb_semaphore)) {
-		if (elp_debug >= 3) {
-			pr_debug("%s: send_pcb entered while threaded\n", dev->name);
-		}
-		return false;
-	}
-	/*
-	 * load each byte into the command register and
-	 * wait for the HCRE bit to indicate the adapter
-	 * had read the byte
-	 */
-	set_hsf(dev, 0);
-
-	if (send_pcb_slow(dev->base_addr, pcb->command))
-		goto abort;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-
-	if (send_pcb_fast(dev->base_addr, pcb->length))
-		goto sti_abort;
-
-	for (i = 0; i < pcb->length; i++) {
-		if (send_pcb_fast(dev->base_addr, pcb->data.raw[i]))
-			goto sti_abort;
-	}
-
-	outb_control(adapter->hcr_val | 3, dev);	/* signal end of PCB */
-	outb_command(2 + pcb->length, dev->base_addr);
-
-	/* now wait for the acknowledgement */
-	spin_unlock_irqrestore(&adapter->lock, flags);
-
-	for (timeout = jiffies + 5*HZ/100; time_before(jiffies, timeout);) {
-		switch (GET_ASF(dev->base_addr)) {
-		case ASF_PCB_ACK:
-			adapter->send_pcb_semaphore = 0;
-			return true;
-
-		case ASF_PCB_NAK:
-#ifdef ELP_DEBUG
-			pr_debug("%s: send_pcb got NAK\n", dev->name);
-#endif
-			goto abort;
-		}
-	}
-
-	if (elp_debug >= 1)
-		pr_debug("%s: timeout waiting for PCB acknowledge (status %02x)\n",
-			dev->name, inb_status(dev->base_addr));
-	goto abort;
-
-      sti_abort:
-	spin_unlock_irqrestore(&adapter->lock, flags);
-      abort:
-	adapter->send_pcb_semaphore = 0;
-	return false;
-}
-
-
-/*****************************************************************
- *
- * receive_pcb
- *   Read a PCB from the adapter
- *
- *	wait for ACRF to be non-zero        ---<---+
- *	input a byte                               |
- *	if ASF1 and ASF2 were not both one         |
- *		before byte was read, loop      --->---+
- *	set HSF1 and HSF2 for ack
- *
- *****************************************************************/
-
-static bool receive_pcb(struct net_device *dev, pcb_struct * pcb)
-{
-	int i, j;
-	int total_length;
-	int stat;
-	unsigned long timeout;
-	unsigned long flags;
-
-	elp_device *adapter = netdev_priv(dev);
-
-	set_hsf(dev, 0);
-
-	/* get the command code */
-	timeout = jiffies + 2*HZ/100;
-	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout));
-	if (time_after_eq(jiffies, timeout)) {
-		TIMEOUT_MSG(__LINE__);
-		return false;
-	}
-	pcb->command = inb_command(dev->base_addr);
-
-	/* read the data length */
-	timeout = jiffies + 3*HZ/100;
-	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout));
-	if (time_after_eq(jiffies, timeout)) {
-		TIMEOUT_MSG(__LINE__);
-		pr_info("%s: status %02x\n", dev->name, stat);
-		return false;
-	}
-	pcb->length = inb_command(dev->base_addr);
-
-	if (pcb->length > MAX_PCB_DATA) {
-		INVALID_PCB_MSG(pcb->length);
-		adapter_reset(dev);
-		return false;
-	}
-	/* read the data */
-	spin_lock_irqsave(&adapter->lock, flags);
-	for (i = 0; i < MAX_PCB_DATA; i++) {
-		for (j = 0; j < 20000; j++) {
-			stat = get_status(dev->base_addr);
-			if (stat & ACRF)
-				break;
-		}
-		pcb->data.raw[i] = inb_command(dev->base_addr);
-		if ((stat & ASF_PCB_MASK) == ASF_PCB_END || j >= 20000)
-			break;
-	}
-	spin_unlock_irqrestore(&adapter->lock, flags);
-	if (i >= MAX_PCB_DATA) {
-		INVALID_PCB_MSG(i);
-		return false;
-	}
-	if (j >= 20000) {
-		TIMEOUT_MSG(__LINE__);
-		return false;
-	}
-	/* the last "data" byte was really the length! */
-	total_length = pcb->data.raw[i];
-
-	/* safety check total length vs data length */
-	if (total_length != (pcb->length + 2)) {
-		if (elp_debug >= 2)
-			pr_warning("%s: mangled PCB received\n", dev->name);
-		set_hsf(dev, HSF_PCB_NAK);
-		return false;
-	}
-
-	if (pcb->command == CMD_RECEIVE_PACKET_COMPLETE) {
-		if (test_and_set_bit(0, (void *) &adapter->busy)) {
-			if (backlog_next(adapter->rx_backlog.in) == adapter->rx_backlog.out) {
-				set_hsf(dev, HSF_PCB_NAK);
-				pr_warning("%s: PCB rejected, transfer in progress and backlog full\n", dev->name);
-				pcb->command = 0;
-				return true;
-			} else {
-				pcb->command = 0xff;
-			}
-		}
-	}
-	set_hsf(dev, HSF_PCB_ACK);
-	return true;
-}
-
-/******************************************************
- *
- *  queue a receive command on the adapter so we will get an
- *  interrupt when a packet is received.
- *
- ******************************************************/
-
-static bool start_receive(struct net_device *dev, pcb_struct * tx_pcb)
-{
-	bool status;
-	elp_device *adapter = netdev_priv(dev);
-
-	if (elp_debug >= 3)
-		pr_debug("%s: restarting receiver\n", dev->name);
-	tx_pcb->command = CMD_RECEIVE_PACKET;
-	tx_pcb->length = sizeof(struct Rcv_pkt);
-	tx_pcb->data.rcv_pkt.buf_seg
-	    = tx_pcb->data.rcv_pkt.buf_ofs = 0;		/* Unused */
-	tx_pcb->data.rcv_pkt.buf_len = 1600;
-	tx_pcb->data.rcv_pkt.timeout = 0;	/* set timeout to zero */
-	status = send_pcb(dev, tx_pcb);
-	if (status)
-		adapter->rx_active++;
-	return status;
-}
-
-/******************************************************
- *
- * extract a packet from the adapter
- * this routine is only called from within the interrupt
- * service routine, so no cli/sti calls are needed
- * note that the length is always assumed to be even
- *
- ******************************************************/
-
-static void receive_packet(struct net_device *dev, int len)
-{
-	int rlen;
-	elp_device *adapter = netdev_priv(dev);
-	void *target;
-	struct sk_buff *skb;
-	unsigned long flags;
-
-	rlen = (len + 1) & ~1;
-	skb = dev_alloc_skb(rlen + 2);
-
-	if (!skb) {
-		pr_warning("%s: memory squeeze, dropping packet\n", dev->name);
-		target = adapter->dma_buffer;
-		adapter->current_dma.target = NULL;
-		/* FIXME: stats */
-		return;
-	}
-
-	skb_reserve(skb, 2);
-	target = skb_put(skb, rlen);
-	if ((unsigned long)(target + rlen) >= MAX_DMA_ADDRESS) {
-		adapter->current_dma.target = target;
-		target = adapter->dma_buffer;
-	} else {
-		adapter->current_dma.target = NULL;
-	}
-
-	/* if this happens, we die */
-	if (test_and_set_bit(0, (void *) &adapter->dmaing))
-		pr_err("%s: rx blocked, DMA in progress, dir %d\n",
-			dev->name, adapter->current_dma.direction);
-
-	adapter->current_dma.direction = 0;
-	adapter->current_dma.length = rlen;
-	adapter->current_dma.skb = skb;
-	adapter->current_dma.start_time = jiffies;
-
-	outb_control(adapter->hcr_val | DIR | TCEN | DMAE, dev);
-
-	flags=claim_dma_lock();
-	disable_dma(dev->dma);
-	clear_dma_ff(dev->dma);
-	set_dma_mode(dev->dma, 0x04);	/* dma read */
-	set_dma_addr(dev->dma, isa_virt_to_bus(target));
-	set_dma_count(dev->dma, rlen);
-	enable_dma(dev->dma);
-	release_dma_lock(flags);
-
-	if (elp_debug >= 3) {
-		pr_debug("%s: rx DMA transfer started\n", dev->name);
-	}
-
-	if (adapter->rx_active)
-		adapter->rx_active--;
-
-	if (!adapter->busy)
-		pr_warning("%s: receive_packet called, busy not set.\n", dev->name);
-}
-
-/******************************************************
- *
- * interrupt handler
- *
- ******************************************************/
-
-static irqreturn_t elp_interrupt(int irq, void *dev_id)
-{
-	int len;
-	int dlen;
-	int icount = 0;
-	struct net_device *dev = dev_id;
-	elp_device *adapter = netdev_priv(dev);
-	unsigned long timeout;
-
-	spin_lock(&adapter->lock);
-
-	do {
-		/*
-		 * has a DMA transfer finished?
-		 */
-		if (inb_status(dev->base_addr) & DONE) {
-			if (!adapter->dmaing)
-				pr_warning("%s: phantom DMA completed\n", dev->name);
-
-			if (elp_debug >= 3)
-				pr_debug("%s: %s DMA complete, status %02x\n", dev->name,
-					adapter->current_dma.direction ? "tx" : "rx",
-					inb_status(dev->base_addr));
-
-			outb_control(adapter->hcr_val & ~(DMAE | TCEN | DIR), dev);
-			if (adapter->current_dma.direction) {
-				dev_kfree_skb_irq(adapter->current_dma.skb);
-			} else {
-				struct sk_buff *skb = adapter->current_dma.skb;
-				if (skb) {
-					if (adapter->current_dma.target) {
-				  	/* have already done the skb_put() */
-				  	memcpy(adapter->current_dma.target, adapter->dma_buffer, adapter->current_dma.length);
-					}
-					skb->protocol = eth_type_trans(skb,dev);
-					dev->stats.rx_bytes += skb->len;
-					netif_rx(skb);
-				}
-			}
-			adapter->dmaing = 0;
-			if (adapter->rx_backlog.in != adapter->rx_backlog.out) {
-				int t = adapter->rx_backlog.length[adapter->rx_backlog.out];
-				adapter->rx_backlog.out = backlog_next(adapter->rx_backlog.out);
-				if (elp_debug >= 2)
-					pr_debug("%s: receiving backlogged packet (%d)\n", dev->name, t);
-				receive_packet(dev, t);
-			} else {
-				adapter->busy = 0;
-			}
-		} else {
-			/* has one timed out? */
-			check_3c505_dma(dev);
-		}
-
-		/*
-		 * receive a PCB from the adapter
-		 */
-		timeout = jiffies + 3*HZ/100;
-		while ((inb_status(dev->base_addr) & ACRF) != 0 && time_before(jiffies, timeout)) {
-			if (receive_pcb(dev, &adapter->irx_pcb)) {
-				switch (adapter->irx_pcb.command)
-				{
-				case 0:
-					break;
-					/*
-					 * received a packet - this must be handled fast
-					 */
-				case 0xff:
-				case CMD_RECEIVE_PACKET_COMPLETE:
-					/* if the device isn't open, don't pass packets up the stack */
-					if (!netif_running(dev))
-						break;
-					len = adapter->irx_pcb.data.rcv_resp.pkt_len;
-					dlen = adapter->irx_pcb.data.rcv_resp.buf_len;
-					if (adapter->irx_pcb.data.rcv_resp.timeout != 0) {
-						pr_err("%s: interrupt - packet not received correctly\n", dev->name);
-					} else {
-						if (elp_debug >= 3) {
-							pr_debug("%s: interrupt - packet received of length %i (%i)\n",
-								dev->name, len, dlen);
-						}
-						if (adapter->irx_pcb.command == 0xff) {
-							if (elp_debug >= 2)
-								pr_debug("%s: adding packet to backlog (len = %d)\n",
-									dev->name, dlen);
-							adapter->rx_backlog.length[adapter->rx_backlog.in] = dlen;
-							adapter->rx_backlog.in = backlog_next(adapter->rx_backlog.in);
-						} else {
-							receive_packet(dev, dlen);
-						}
-						if (elp_debug >= 3)
-							pr_debug("%s: packet received\n", dev->name);
-					}
-					break;
-
-					/*
-					 * 82586 configured correctly
-					 */
-				case CMD_CONFIGURE_82586_RESPONSE:
-					adapter->got[CMD_CONFIGURE_82586] = 1;
-					if (elp_debug >= 3)
-						pr_debug("%s: interrupt - configure response received\n", dev->name);
-					break;
-
-					/*
-					 * Adapter memory configuration
-					 */
-				case CMD_CONFIGURE_ADAPTER_RESPONSE:
-					adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 1;
-					if (elp_debug >= 3)
-						pr_debug("%s: Adapter memory configuration %s.\n", dev->name,
-						       adapter->irx_pcb.data.failed ? "failed" : "succeeded");
-					break;
-
-					/*
-					 * Multicast list loading
-					 */
-				case CMD_LOAD_MULTICAST_RESPONSE:
-					adapter->got[CMD_LOAD_MULTICAST_LIST] = 1;
-					if (elp_debug >= 3)
-						pr_debug("%s: Multicast address list loading %s.\n", dev->name,
-						       adapter->irx_pcb.data.failed ? "failed" : "succeeded");
-					break;
-
-					/*
-					 * Station address setting
-					 */
-				case CMD_SET_ADDRESS_RESPONSE:
-					adapter->got[CMD_SET_STATION_ADDRESS] = 1;
-					if (elp_debug >= 3)
-						pr_debug("%s: Ethernet address setting %s.\n", dev->name,
-						       adapter->irx_pcb.data.failed ? "failed" : "succeeded");
-					break;
-
-
-					/*
-					 * received board statistics
-					 */
-				case CMD_NETWORK_STATISTICS_RESPONSE:
-					dev->stats.rx_packets += adapter->irx_pcb.data.netstat.tot_recv;
-					dev->stats.tx_packets += adapter->irx_pcb.data.netstat.tot_xmit;
-					dev->stats.rx_crc_errors += adapter->irx_pcb.data.netstat.err_CRC;
-					dev->stats.rx_frame_errors += adapter->irx_pcb.data.netstat.err_align;
-					dev->stats.rx_fifo_errors += adapter->irx_pcb.data.netstat.err_ovrrun;
-					dev->stats.rx_over_errors += adapter->irx_pcb.data.netstat.err_res;
-					adapter->got[CMD_NETWORK_STATISTICS] = 1;
-					if (elp_debug >= 3)
-						pr_debug("%s: interrupt - statistics response received\n", dev->name);
-					break;
-
-					/*
-					 * sent a packet
-					 */
-				case CMD_TRANSMIT_PACKET_COMPLETE:
-					if (elp_debug >= 3)
-						pr_debug("%s: interrupt - packet sent\n", dev->name);
-					if (!netif_running(dev))
-						break;
-					switch (adapter->irx_pcb.data.xmit_resp.c_stat) {
-					case 0xffff:
-						dev->stats.tx_aborted_errors++;
-						pr_info("%s: transmit timed out, network cable problem?\n", dev->name);
-						break;
-					case 0xfffe:
-						dev->stats.tx_fifo_errors++;
-						pr_info("%s: transmit timed out, FIFO underrun\n", dev->name);
-						break;
-					}
-					netif_wake_queue(dev);
-					break;
-
-					/*
-					 * some unknown PCB
-					 */
-				default:
-					pr_debug("%s: unknown PCB received - %2.2x\n",
-						dev->name, adapter->irx_pcb.command);
-					break;
-				}
-			} else {
-				pr_warning("%s: failed to read PCB on interrupt\n", dev->name);
-				adapter_reset(dev);
-			}
-		}
-
-	} while (icount++ < 5 && (inb_status(dev->base_addr) & (ACRF | DONE)));
-
-	prime_rx(dev);
-
-	/*
-	 * indicate no longer in interrupt routine
-	 */
-	spin_unlock(&adapter->lock);
-	return IRQ_HANDLED;
-}
-
-
-/******************************************************
- *
- * open the board
- *
- ******************************************************/
-
-static int elp_open(struct net_device *dev)
-{
-	elp_device *adapter = netdev_priv(dev);
-	int retval;
-
-	if (elp_debug >= 3)
-		pr_debug("%s: request to open device\n", dev->name);
-
-	/*
-	 * make sure we actually found the device
-	 */
-	if (adapter == NULL) {
-		pr_err("%s: Opening a non-existent physical device\n", dev->name);
-		return -EAGAIN;
-	}
-	/*
-	 * disable interrupts on the board
-	 */
-	outb_control(0, dev);
-
-	/*
-	 * clear any pending interrupts
-	 */
-	inb_command(dev->base_addr);
-	adapter_reset(dev);
-
-	/*
-	 * no receive PCBs active
-	 */
-	adapter->rx_active = 0;
-
-	adapter->busy = 0;
-	adapter->send_pcb_semaphore = 0;
-	adapter->rx_backlog.in = 0;
-	adapter->rx_backlog.out = 0;
-
-	spin_lock_init(&adapter->lock);
-
-	/*
-	 * install our interrupt service routine
-	 */
-	if ((retval = request_irq(dev->irq, elp_interrupt, 0, dev->name, dev))) {
-		pr_err("%s: could not allocate IRQ%d\n", dev->name, dev->irq);
-		return retval;
-	}
-	if ((retval = request_dma(dev->dma, dev->name))) {
-		free_irq(dev->irq, dev);
-		pr_err("%s: could not allocate DMA%d channel\n", dev->name, dev->dma);
-		return retval;
-	}
-	adapter->dma_buffer = (void *) dma_mem_alloc(DMA_BUFFER_SIZE);
-	if (!adapter->dma_buffer) {
-		pr_err("%s: could not allocate DMA buffer\n", dev->name);
-		free_dma(dev->dma);
-		free_irq(dev->irq, dev);
-		return -ENOMEM;
-	}
-	adapter->dmaing = 0;
-
-	/*
-	 * enable interrupts on the board
-	 */
-	outb_control(CMDE, dev);
-
-	/*
-	 * configure adapter memory: we need 10 multicast addresses, default==0
-	 */
-	if (elp_debug >= 3)
-		pr_debug("%s: sending 3c505 memory configuration command\n", dev->name);
-	adapter->tx_pcb.command = CMD_CONFIGURE_ADAPTER_MEMORY;
-	adapter->tx_pcb.data.memconf.cmd_q = 10;
-	adapter->tx_pcb.data.memconf.rcv_q = 20;
-	adapter->tx_pcb.data.memconf.mcast = 10;
-	adapter->tx_pcb.data.memconf.frame = 20;
-	adapter->tx_pcb.data.memconf.rcv_b = 20;
-	adapter->tx_pcb.data.memconf.progs = 0;
-	adapter->tx_pcb.length = sizeof(struct Memconf);
-	adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 0;
-	if (!send_pcb(dev, &adapter->tx_pcb))
-		pr_err("%s: couldn't send memory configuration command\n", dev->name);
-	else {
-		unsigned long timeout = jiffies + TIMEOUT;
-		while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && time_before(jiffies, timeout));
-		if (time_after_eq(jiffies, timeout))
-			TIMEOUT_MSG(__LINE__);
-	}
-
-
-	/*
-	 * configure adapter to receive broadcast messages and wait for response
-	 */
-	if (elp_debug >= 3)
-		pr_debug("%s: sending 82586 configure command\n", dev->name);
-	adapter->tx_pcb.command = CMD_CONFIGURE_82586;
-	adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD;
-	adapter->tx_pcb.length = 2;
-	adapter->got[CMD_CONFIGURE_82586] = 0;
-	if (!send_pcb(dev, &adapter->tx_pcb))
-		pr_err("%s: couldn't send 82586 configure command\n", dev->name);
-	else {
-		unsigned long timeout = jiffies + TIMEOUT;
-		while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout));
-		if (time_after_eq(jiffies, timeout))
-			TIMEOUT_MSG(__LINE__);
-	}
-
-	/* enable burst-mode DMA */
-	/* outb(0x1, dev->base_addr + PORT_AUXDMA); */
-
-	/*
-	 * queue receive commands to provide buffering
-	 */
-	prime_rx(dev);
-	if (elp_debug >= 3)
-		pr_debug("%s: %d receive PCBs active\n", dev->name, adapter->rx_active);
-
-	/*
-	 * device is now officially open!
-	 */
-
-	netif_start_queue(dev);
-	return 0;
-}
-
-
-/******************************************************
- *
- * send a packet to the adapter
- *
- ******************************************************/
-
-static netdev_tx_t send_packet(struct net_device *dev, struct sk_buff *skb)
-{
-	elp_device *adapter = netdev_priv(dev);
-	unsigned long target;
-	unsigned long flags;
-
-	/*
-	 * make sure the length is even and no shorter than 60 bytes
-	 */
-	unsigned int nlen = (((skb->len < 60) ? 60 : skb->len) + 1) & (~1);
-
-	if (test_and_set_bit(0, (void *) &adapter->busy)) {
-		if (elp_debug >= 2)
-			pr_debug("%s: transmit blocked\n", dev->name);
-		return false;
-	}
-
-	dev->stats.tx_bytes += nlen;
-
-	/*
-	 * send the adapter a transmit packet command. Ignore segment and offset
-	 * and make sure the length is even
-	 */
-	adapter->tx_pcb.command = CMD_TRANSMIT_PACKET;
-	adapter->tx_pcb.length = sizeof(struct Xmit_pkt);
-	adapter->tx_pcb.data.xmit_pkt.buf_ofs
-	    = adapter->tx_pcb.data.xmit_pkt.buf_seg = 0;	/* Unused */
-	adapter->tx_pcb.data.xmit_pkt.pkt_len = nlen;
-
-	if (!send_pcb(dev, &adapter->tx_pcb)) {
-		adapter->busy = 0;
-		return false;
-	}
-	/* if this happens, we die */
-	if (test_and_set_bit(0, (void *) &adapter->dmaing))
-		pr_debug("%s: tx: DMA %d in progress\n", dev->name, adapter->current_dma.direction);
-
-	adapter->current_dma.direction = 1;
-	adapter->current_dma.start_time = jiffies;
-
-	if ((unsigned long)(skb->data + nlen) >= MAX_DMA_ADDRESS || nlen != skb->len) {
-		skb_copy_from_linear_data(skb, adapter->dma_buffer, nlen);
-		memset(adapter->dma_buffer+skb->len, 0, nlen-skb->len);
-		target = isa_virt_to_bus(adapter->dma_buffer);
-	}
-	else {
-		target = isa_virt_to_bus(skb->data);
-	}
-	adapter->current_dma.skb = skb;
-
-	flags=claim_dma_lock();
-	disable_dma(dev->dma);
-	clear_dma_ff(dev->dma);
-	set_dma_mode(dev->dma, 0x48);	/* dma memory -> io */
-	set_dma_addr(dev->dma, target);
-	set_dma_count(dev->dma, nlen);
-	outb_control(adapter->hcr_val | DMAE | TCEN, dev);
-	enable_dma(dev->dma);
-	release_dma_lock(flags);
-
-	if (elp_debug >= 3)
-		pr_debug("%s: DMA transfer started\n", dev->name);
-
-	return true;
-}
-
-/*
- *	The upper layer thinks we timed out
- */
-
-static void elp_timeout(struct net_device *dev)
-{
-	int stat;
-
-	stat = inb_status(dev->base_addr);
-	pr_warning("%s: transmit timed out, lost %s?\n", dev->name,
-		   (stat & ACRF) ? "interrupt" : "command");
-	if (elp_debug >= 1)
-		pr_debug("%s: status %#02x\n", dev->name, stat);
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	dev->stats.tx_dropped++;
-	netif_wake_queue(dev);
-}
-
-/******************************************************
- *
- * start the transmitter
- *    return 0 if sent OK, else return 1
- *
- ******************************************************/
-
-static netdev_tx_t elp_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	unsigned long flags;
-	elp_device *adapter = netdev_priv(dev);
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	check_3c505_dma(dev);
-
-	if (elp_debug >= 3)
-		pr_debug("%s: request to send packet of length %d\n", dev->name, (int) skb->len);
-
-	netif_stop_queue(dev);
-
-	/*
-	 * send the packet at skb->data for skb->len
-	 */
-	if (!send_packet(dev, skb)) {
-		if (elp_debug >= 2) {
-			pr_debug("%s: failed to transmit packet\n", dev->name);
-		}
-		spin_unlock_irqrestore(&adapter->lock, flags);
-		return NETDEV_TX_BUSY;
-	}
-	if (elp_debug >= 3)
-		pr_debug("%s: packet of length %d sent\n", dev->name, (int) skb->len);
-
-	prime_rx(dev);
-	spin_unlock_irqrestore(&adapter->lock, flags);
-	netif_start_queue(dev);
-	return NETDEV_TX_OK;
-}
-
-/******************************************************
- *
- * return statistics on the board
- *
- ******************************************************/
-
-static struct net_device_stats *elp_get_stats(struct net_device *dev)
-{
-	elp_device *adapter = netdev_priv(dev);
-
-	if (elp_debug >= 3)
-		pr_debug("%s: request for stats\n", dev->name);
-
-	/* If the device is closed, just return the latest stats we have,
-	   - we cannot ask from the adapter without interrupts */
-	if (!netif_running(dev))
-		return &dev->stats;
-
-	/* send a get statistics command to the board */
-	adapter->tx_pcb.command = CMD_NETWORK_STATISTICS;
-	adapter->tx_pcb.length = 0;
-	adapter->got[CMD_NETWORK_STATISTICS] = 0;
-	if (!send_pcb(dev, &adapter->tx_pcb))
-		pr_err("%s: couldn't send get statistics command\n", dev->name);
-	else {
-		unsigned long timeout = jiffies + TIMEOUT;
-		while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && time_before(jiffies, timeout));
-		if (time_after_eq(jiffies, timeout)) {
-			TIMEOUT_MSG(__LINE__);
-			return &dev->stats;
-		}
-	}
-
-	/* statistics are now up to date */
-	return &dev->stats;
-}
-
-
-static void netdev_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-	sprintf(info->bus_info, "ISA 0x%lx", dev->base_addr);
-}
-
-static u32 netdev_get_msglevel(struct net_device *dev)
-{
-	return debug;
-}
-
-static void netdev_set_msglevel(struct net_device *dev, u32 level)
-{
-	debug = level;
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-	.get_drvinfo		= netdev_get_drvinfo,
-	.get_msglevel		= netdev_get_msglevel,
-	.set_msglevel		= netdev_set_msglevel,
-};
-
-/******************************************************
- *
- * close the board
- *
- ******************************************************/
-
-static int elp_close(struct net_device *dev)
-{
-	elp_device *adapter = netdev_priv(dev);
-
-	if (elp_debug >= 3)
-		pr_debug("%s: request to close device\n", dev->name);
-
-	netif_stop_queue(dev);
-
-	/* Someone may request the device statistic information even when
-	 * the interface is closed. The following will update the statistics
-	 * structure in the driver, so we'll be able to give current statistics.
-	 */
-	(void) elp_get_stats(dev);
-
-	/*
-	 * disable interrupts on the board
-	 */
-	outb_control(0, dev);
-
-	/*
-	 * release the IRQ
-	 */
-	free_irq(dev->irq, dev);
-
-	free_dma(dev->dma);
-	free_pages((unsigned long) adapter->dma_buffer, get_order(DMA_BUFFER_SIZE));
-
-	return 0;
-}
-
-
-/************************************************************
- *
- * Set multicast list
- * num_addrs==0: clear mc_list
- * num_addrs==-1: set promiscuous mode
- * num_addrs>0: set mc_list
- *
- ************************************************************/
-
-static void elp_set_mc_list(struct net_device *dev)
-{
-	elp_device *adapter = netdev_priv(dev);
-	struct netdev_hw_addr *ha;
-	int i;
-	unsigned long flags;
-
-	if (elp_debug >= 3)
-		pr_debug("%s: request to set multicast list\n", dev->name);
-
-	spin_lock_irqsave(&adapter->lock, flags);
-
-	if (!(dev->flags & (IFF_PROMISC | IFF_ALLMULTI))) {
-		/* send a "load multicast list" command to the board, max 10 addrs/cmd */
-		/* if num_addrs==0 the list will be cleared */
-		adapter->tx_pcb.command = CMD_LOAD_MULTICAST_LIST;
-		adapter->tx_pcb.length = 6 * netdev_mc_count(dev);
-		i = 0;
-		netdev_for_each_mc_addr(ha, dev)
-			memcpy(adapter->tx_pcb.data.multicast[i++],
-			       ha->addr, 6);
-		adapter->got[CMD_LOAD_MULTICAST_LIST] = 0;
-		if (!send_pcb(dev, &adapter->tx_pcb))
-			pr_err("%s: couldn't send set_multicast command\n", dev->name);
-		else {
-			unsigned long timeout = jiffies + TIMEOUT;
-			while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && time_before(jiffies, timeout));
-			if (time_after_eq(jiffies, timeout)) {
-				TIMEOUT_MSG(__LINE__);
-			}
-		}
-		if (!netdev_mc_empty(dev))
-			adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD | RECV_MULTI;
-		else		/* num_addrs == 0 */
-			adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD;
-	} else
-		adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_PROMISC;
-	/*
-	 * configure adapter to receive messages (as specified above)
-	 * and wait for response
-	 */
-	if (elp_debug >= 3)
-		pr_debug("%s: sending 82586 configure command\n", dev->name);
-	adapter->tx_pcb.command = CMD_CONFIGURE_82586;
-	adapter->tx_pcb.length = 2;
-	adapter->got[CMD_CONFIGURE_82586] = 0;
-	if (!send_pcb(dev, &adapter->tx_pcb))
-	{
-		spin_unlock_irqrestore(&adapter->lock, flags);
-		pr_err("%s: couldn't send 82586 configure command\n", dev->name);
-	}
-	else {
-		unsigned long timeout = jiffies + TIMEOUT;
-		spin_unlock_irqrestore(&adapter->lock, flags);
-		while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout));
-		if (time_after_eq(jiffies, timeout))
-			TIMEOUT_MSG(__LINE__);
-	}
-}
-
-/************************************************************
- *
- * A couple of tests to see if there's 3C505 or not
- * Called only by elp_autodetect
- ************************************************************/
-
-static int __init elp_sense(struct net_device *dev)
-{
-	int addr = dev->base_addr;
-	const char *name = dev->name;
-	byte orig_HSR;
-
-	if (!request_region(addr, ELP_IO_EXTENT, "3c505"))
-		return -ENODEV;
-
-	orig_HSR = inb_status(addr);
-
-	if (elp_debug > 0)
-		pr_debug(search_msg, name, addr);
-
-	if (orig_HSR == 0xff) {
-		if (elp_debug > 0)
-			pr_cont(notfound_msg, 1);
-		goto out;
-	}
-
-	/* Wait for a while; the adapter may still be booting up */
-	if (elp_debug > 0)
-		pr_cont(stilllooking_msg);
-
-	if (orig_HSR & DIR) {
-		/* If HCR.DIR is up, we pull it down. HSR.DIR should follow. */
-		outb(0, dev->base_addr + PORT_CONTROL);
-		msleep(300);
-		if (inb_status(addr) & DIR) {
-			if (elp_debug > 0)
-				pr_cont(notfound_msg, 2);
-			goto out;
-		}
-	} else {
-		/* If HCR.DIR is down, we pull it up. HSR.DIR should follow. */
-		outb(DIR, dev->base_addr + PORT_CONTROL);
-		msleep(300);
-		if (!(inb_status(addr) & DIR)) {
-			if (elp_debug > 0)
-				pr_cont(notfound_msg, 3);
-			goto out;
-		}
-	}
-	/*
-	 * It certainly looks like a 3c505.
-	 */
-	if (elp_debug > 0)
-		pr_cont(found_msg);
-
-	return 0;
-out:
-	release_region(addr, ELP_IO_EXTENT);
-	return -ENODEV;
-}
-
-/*************************************************************
- *
- * Search through addr_list[] and try to find a 3C505
- * Called only by eplus_probe
- *************************************************************/
-
-static int __init elp_autodetect(struct net_device *dev)
-{
-	int idx = 0;
-
-	/* if base address set, then only check that address
-	   otherwise, run through the table */
-	if (dev->base_addr != 0) {	/* dev->base_addr == 0 ==> plain autodetect */
-		if (elp_sense(dev) == 0)
-			return dev->base_addr;
-	} else
-		while ((dev->base_addr = addr_list[idx++])) {
-			if (elp_sense(dev) == 0)
-				return dev->base_addr;
-		}
-
-	/* could not find an adapter */
-	if (elp_debug > 0)
-		pr_debug(couldnot_msg, dev->name);
-
-	return 0;		/* Because of this, the layer above will return -ENODEV */
-}
-
-static const struct net_device_ops elp_netdev_ops = {
-	.ndo_open		= elp_open,
-	.ndo_stop		= elp_close,
-	.ndo_get_stats 		= elp_get_stats,
-	.ndo_start_xmit		= elp_start_xmit,
-	.ndo_tx_timeout 	= elp_timeout,
-	.ndo_set_multicast_list = elp_set_mc_list,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-/******************************************************
- *
- * probe for an Etherlink Plus board at the specified address
- *
- ******************************************************/
-
-/* There are three situations we need to be able to detect here:
-
- *  a) the card is idle
- *  b) the card is still booting up
- *  c) the card is stuck in a strange state (some DOS drivers do this)
- *
- * In case (a), all is well.  In case (b), we wait 10 seconds to see if the
- * card finishes booting, and carry on if so.  In case (c), we do a hard reset,
- * loop round, and hope for the best.
- *
- * This is all very unpleasant, but hopefully avoids the problems with the old
- * probe code (which had a 15-second delay if the card was idle, and didn't
- * work at all if it was in a weird state).
- */
-
-static int __init elplus_setup(struct net_device *dev)
-{
-	elp_device *adapter = netdev_priv(dev);
-	int i, tries, tries1, okay;
-	unsigned long timeout;
-	unsigned long cookie = 0;
-	int err = -ENODEV;
-
-	/*
-	 *  setup adapter structure
-	 */
-
-	dev->base_addr = elp_autodetect(dev);
-	if (!dev->base_addr)
-		return -ENODEV;
-
-	adapter->send_pcb_semaphore = 0;
-
-	for (tries1 = 0; tries1 < 3; tries1++) {
-		outb_control((adapter->hcr_val | CMDE) & ~DIR, dev);
-		/* First try to write just one byte, to see if the card is
-		 * responding at all normally.
-		 */
-		timeout = jiffies + 5*HZ/100;
-		okay = 0;
-		while (time_before(jiffies, timeout) && !(inb_status(dev->base_addr) & HCRE));
-		if ((inb_status(dev->base_addr) & HCRE)) {
-			outb_command(0, dev->base_addr);	/* send a spurious byte */
-			timeout = jiffies + 5*HZ/100;
-			while (time_before(jiffies, timeout) && !(inb_status(dev->base_addr) & HCRE));
-			if (inb_status(dev->base_addr) & HCRE)
-				okay = 1;
-		}
-		if (!okay) {
-			/* Nope, it's ignoring the command register.  This means that
-			 * either it's still booting up, or it's died.
-			 */
-			pr_err("%s: command register wouldn't drain, ", dev->name);
-			if ((inb_status(dev->base_addr) & 7) == 3) {
-				/* If the adapter status is 3, it *could* still be booting.
-				 * Give it the benefit of the doubt for 10 seconds.
-				 */
-				pr_cont("assuming 3c505 still starting\n");
-				timeout = jiffies + 10*HZ;
-				while (time_before(jiffies, timeout) && (inb_status(dev->base_addr) & 7));
-				if (inb_status(dev->base_addr) & 7) {
-					pr_err("%s: 3c505 failed to start\n", dev->name);
-				} else {
-					okay = 1;  /* It started */
-				}
-			} else {
-				/* Otherwise, it must just be in a strange
-				 * state.  We probably need to kick it.
-				 */
-				pr_cont("3c505 is sulking\n");
-			}
-		}
-		for (tries = 0; tries < 5 && okay; tries++) {
-
-			/*
-			 * Try to set the Ethernet address, to make sure that the board
-			 * is working.
-			 */
-			adapter->tx_pcb.command = CMD_STATION_ADDRESS;
-			adapter->tx_pcb.length = 0;
-			cookie = probe_irq_on();
-			if (!send_pcb(dev, &adapter->tx_pcb)) {
-				pr_err("%s: could not send first PCB\n", dev->name);
-				probe_irq_off(cookie);
-				continue;
-			}
-			if (!receive_pcb(dev, &adapter->rx_pcb)) {
-				pr_err("%s: could not read first PCB\n", dev->name);
-				probe_irq_off(cookie);
-				continue;
-			}
-			if ((adapter->rx_pcb.command != CMD_ADDRESS_RESPONSE) ||
-			    (adapter->rx_pcb.length != 6)) {
-				pr_err("%s: first PCB wrong (%d, %d)\n", dev->name,
-					adapter->rx_pcb.command, adapter->rx_pcb.length);
-				probe_irq_off(cookie);
-				continue;
-			}
-			goto okay;
-		}
-		/* It's broken.  Do a hard reset to re-initialise the board,
-		 * and try again.
-		 */
-		pr_info("%s: resetting adapter\n", dev->name);
-		outb_control(adapter->hcr_val | FLSH | ATTN, dev);
-		outb_control(adapter->hcr_val & ~(FLSH | ATTN), dev);
-	}
-	pr_err("%s: failed to initialise 3c505\n", dev->name);
-	goto out;
-
-      okay:
-	if (dev->irq) {		/* Is there a preset IRQ? */
-		int rpt = probe_irq_off(cookie);
-		if (dev->irq != rpt) {
-			pr_warning("%s: warning, irq %d configured but %d detected\n", dev->name, dev->irq, rpt);
-		}
-		/* if dev->irq == probe_irq_off(cookie), all is well */
-	} else		       /* No preset IRQ; just use what we can detect */
-		dev->irq = probe_irq_off(cookie);
-	switch (dev->irq) {    /* Legal, sane? */
-	case 0:
-		pr_err("%s: IRQ probe failed: check 3c505 jumpers.\n",
-		       dev->name);
-		goto out;
-	case 1:
-	case 6:
-	case 8:
-	case 13:
-		pr_err("%s: Impossible IRQ %d reported by probe_irq_off().\n",
-		       dev->name, dev->irq);
-		       goto out;
-	}
-	/*
-	 *  Now we have the IRQ number so we can disable the interrupts from
-	 *  the board until the board is opened.
-	 */
-	outb_control(adapter->hcr_val & ~CMDE, dev);
-
-	/*
-	 * copy Ethernet address into structure
-	 */
-	for (i = 0; i < 6; i++)
-		dev->dev_addr[i] = adapter->rx_pcb.data.eth_addr[i];
-
-	/* find a DMA channel */
-	if (!dev->dma) {
-		if (dev->mem_start) {
-			dev->dma = dev->mem_start & 7;
-		}
-		else {
-			pr_warning("%s: warning, DMA channel not specified, using default\n", dev->name);
-			dev->dma = ELP_DMA;
-		}
-	}
-
-	/*
-	 * print remainder of startup message
-	 */
-	pr_info("%s: 3c505 at %#lx, irq %d, dma %d, addr %pM, ",
-		dev->name, dev->base_addr, dev->irq, dev->dma, dev->dev_addr);
-	/*
-	 * read more information from the adapter
-	 */
-
-	adapter->tx_pcb.command = CMD_ADAPTER_INFO;
-	adapter->tx_pcb.length = 0;
-	if (!send_pcb(dev, &adapter->tx_pcb) ||
-	    !receive_pcb(dev, &adapter->rx_pcb) ||
-	    (adapter->rx_pcb.command != CMD_ADAPTER_INFO_RESPONSE) ||
-	    (adapter->rx_pcb.length != 10)) {
-		pr_cont("not responding to second PCB\n");
-	}
-	pr_cont("rev %d.%d, %dk\n", adapter->rx_pcb.data.info.major_vers,
-		adapter->rx_pcb.data.info.minor_vers, adapter->rx_pcb.data.info.RAM_sz);
-
-	/*
-	 * reconfigure the adapter memory to better suit our purposes
-	 */
-	adapter->tx_pcb.command = CMD_CONFIGURE_ADAPTER_MEMORY;
-	adapter->tx_pcb.length = 12;
-	adapter->tx_pcb.data.memconf.cmd_q = 8;
-	adapter->tx_pcb.data.memconf.rcv_q = 8;
-	adapter->tx_pcb.data.memconf.mcast = 10;
-	adapter->tx_pcb.data.memconf.frame = 10;
-	adapter->tx_pcb.data.memconf.rcv_b = 10;
-	adapter->tx_pcb.data.memconf.progs = 0;
-	if (!send_pcb(dev, &adapter->tx_pcb) ||
-	    !receive_pcb(dev, &adapter->rx_pcb) ||
-	    (adapter->rx_pcb.command != CMD_CONFIGURE_ADAPTER_RESPONSE) ||
-	    (adapter->rx_pcb.length != 2)) {
-		pr_err("%s: could not configure adapter memory\n", dev->name);
-	}
-	if (adapter->rx_pcb.data.configure) {
-		pr_err("%s: adapter configuration failed\n", dev->name);
-	}
-
-	dev->netdev_ops = &elp_netdev_ops;
-	dev->watchdog_timeo = 10*HZ;
-	dev->ethtool_ops = &netdev_ethtool_ops;		/* local */
-
-	dev->mem_start = dev->mem_end = 0;
-
-	err = register_netdev(dev);
-	if (err)
-		goto out;
-
-	return 0;
-out:
-	release_region(dev->base_addr, ELP_IO_EXTENT);
-	return err;
-}
-
-#ifndef MODULE
-struct net_device * __init elplus_probe(int unit)
-{
-	struct net_device *dev = alloc_etherdev(sizeof(elp_device));
-	int err;
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	sprintf(dev->name, "eth%d", unit);
-	netdev_boot_setup_check(dev);
-
-	err = elplus_setup(dev);
-	if (err) {
-		free_netdev(dev);
-		return ERR_PTR(err);
-	}
-	return dev;
-}
-
-#else
-static struct net_device *dev_3c505[ELP_MAX_CARDS];
-static int io[ELP_MAX_CARDS];
-static int irq[ELP_MAX_CARDS];
-static int dma[ELP_MAX_CARDS];
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(dma, int, NULL, 0);
-MODULE_PARM_DESC(io, "EtherLink Plus I/O base address(es)");
-MODULE_PARM_DESC(irq, "EtherLink Plus IRQ number(s) (assigned)");
-MODULE_PARM_DESC(dma, "EtherLink Plus DMA channel(s)");
-
-int __init init_module(void)
-{
-	int this_dev, found = 0;
-
-	for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) {
-		struct net_device *dev = alloc_etherdev(sizeof(elp_device));
-		if (!dev)
-			break;
-
-		dev->irq = irq[this_dev];
-		dev->base_addr = io[this_dev];
-		if (dma[this_dev]) {
-			dev->dma = dma[this_dev];
-		} else {
-			dev->dma = ELP_DMA;
-			pr_warning("3c505.c: warning, using default DMA channel,\n");
-		}
-		if (io[this_dev] == 0) {
-			if (this_dev) {
-				free_netdev(dev);
-				break;
-			}
-			pr_notice("3c505.c: module autoprobe not recommended, give io=xx.\n");
-		}
-		if (elplus_setup(dev) != 0) {
-			pr_warning("3c505.c: Failed to register card at 0x%x.\n", io[this_dev]);
-			free_netdev(dev);
-			break;
-		}
-		dev_3c505[this_dev] = dev;
-		found++;
-	}
-	if (!found)
-		return -ENODEV;
-	return 0;
-}
-
-void __exit cleanup_module(void)
-{
-	int this_dev;
-
-	for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) {
-		struct net_device *dev = dev_3c505[this_dev];
-		if (dev) {
-			unregister_netdev(dev);
-			release_region(dev->base_addr, ELP_IO_EXTENT);
-			free_netdev(dev);
-		}
-	}
-}
-
-#endif				/* MODULE */
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/3c505.h linux-libre-3.2-gnu/drivers/net/3c505.h
--- linux-libre-3.1-gnu/drivers/net/3c505.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/3c505.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,292 +0,0 @@
-/*****************************************************************
- *
- *  defines for 3Com Etherlink Plus adapter
- *
- *****************************************************************/
-
-#define ELP_DMA       6
-#define ELP_RX_PCBS   4
-#define ELP_MAX_CARDS 4
-
-/*
- * I/O register offsets
- */
-#define	PORT_COMMAND	0x00	/* read/write, 8-bit */
-#define	PORT_STATUS	0x02	/* read only, 8-bit */
-#define	PORT_AUXDMA	0x02	/* write only, 8-bit */
-#define	PORT_DATA	0x04	/* read/write, 16-bit */
-#define	PORT_CONTROL	0x06	/* read/write, 8-bit */
-
-#define ELP_IO_EXTENT	0x10	/* size of used IO registers */
-
-/*
- * host control registers bits
- */
-#define	ATTN	0x80	/* attention */
-#define	FLSH	0x40	/* flush data register */
-#define DMAE	0x20	/* DMA enable */
-#define DIR	0x10	/* direction */
-#define	TCEN	0x08	/* terminal count interrupt enable */
-#define	CMDE	0x04	/* command register interrupt enable */
-#define	HSF2	0x02	/* host status flag 2 */
-#define	HSF1	0x01	/* host status flag 1 */
-
-/*
- * combinations of HSF flags used for PCB transmission
- */
-#define	HSF_PCB_ACK	HSF1
-#define	HSF_PCB_NAK	HSF2
-#define	HSF_PCB_END	(HSF2|HSF1)
-#define	HSF_PCB_MASK	(HSF2|HSF1)
-
-/*
- * host status register bits
- */
-#define	HRDY	0x80	/* data register ready */
-#define	HCRE	0x40	/* command register empty */
-#define	ACRF	0x20	/* adapter command register full */
-/* #define DIR 	0x10	direction - same as in control register */
-#define	DONE	0x08	/* DMA done */
-#define	ASF3	0x04	/* adapter status flag 3 */
-#define	ASF2	0x02	/* adapter status flag 2 */
-#define	ASF1	0x01	/* adapter status flag 1 */
-
-/*
- * combinations of ASF flags used for PCB reception
- */
-#define	ASF_PCB_ACK	ASF1
-#define	ASF_PCB_NAK	ASF2
-#define	ASF_PCB_END	(ASF2|ASF1)
-#define	ASF_PCB_MASK	(ASF2|ASF1)
-
-/*
- * host aux DMA register bits
- */
-#define	DMA_BRST	0x01	/* DMA burst */
-
-/*
- * maximum amount of data allowed in a PCB
- */
-#define	MAX_PCB_DATA	62
-
-/*****************************************************************
- *
- *  timeout value
- *	this is a rough value used for loops to stop them from
- *	locking up the whole machine in the case of failure or
- *	error conditions
- *
- *****************************************************************/
-
-#define	TIMEOUT	300
-
-/*****************************************************************
- *
- * PCB commands
- *
- *****************************************************************/
-
-enum {
-  /*
-   * host PCB commands
-   */
-  CMD_CONFIGURE_ADAPTER_MEMORY	= 0x01,
-  CMD_CONFIGURE_82586		= 0x02,
-  CMD_STATION_ADDRESS		= 0x03,
-  CMD_DMA_DOWNLOAD		= 0x04,
-  CMD_DMA_UPLOAD		= 0x05,
-  CMD_PIO_DOWNLOAD		= 0x06,
-  CMD_PIO_UPLOAD		= 0x07,
-  CMD_RECEIVE_PACKET		= 0x08,
-  CMD_TRANSMIT_PACKET		= 0x09,
-  CMD_NETWORK_STATISTICS	= 0x0a,
-  CMD_LOAD_MULTICAST_LIST	= 0x0b,
-  CMD_CLEAR_PROGRAM		= 0x0c,
-  CMD_DOWNLOAD_PROGRAM		= 0x0d,
-  CMD_EXECUTE_PROGRAM		= 0x0e,
-  CMD_SELF_TEST			= 0x0f,
-  CMD_SET_STATION_ADDRESS	= 0x10,
-  CMD_ADAPTER_INFO		= 0x11,
-  NUM_TRANSMIT_CMDS,
-
-  /*
-   * adapter PCB commands
-   */
-  CMD_CONFIGURE_ADAPTER_RESPONSE	= 0x31,
-  CMD_CONFIGURE_82586_RESPONSE		= 0x32,
-  CMD_ADDRESS_RESPONSE			= 0x33,
-  CMD_DOWNLOAD_DATA_REQUEST		= 0x34,
-  CMD_UPLOAD_DATA_REQUEST		= 0x35,
-  CMD_RECEIVE_PACKET_COMPLETE		= 0x38,
-  CMD_TRANSMIT_PACKET_COMPLETE		= 0x39,
-  CMD_NETWORK_STATISTICS_RESPONSE	= 0x3a,
-  CMD_LOAD_MULTICAST_RESPONSE		= 0x3b,
-  CMD_CLEAR_PROGRAM_RESPONSE		= 0x3c,
-  CMD_DOWNLOAD_PROGRAM_RESPONSE		= 0x3d,
-  CMD_EXECUTE_RESPONSE			= 0x3e,
-  CMD_SELF_TEST_RESPONSE		= 0x3f,
-  CMD_SET_ADDRESS_RESPONSE		= 0x40,
-  CMD_ADAPTER_INFO_RESPONSE		= 0x41
-};
-
-/* Definitions for the PCB data structure */
-
-/* Data units */
-typedef unsigned char         byte;
-typedef unsigned short int    word;
-typedef unsigned long int     dword;
-
-/* Data structures */
-struct Memconf {
-	word	cmd_q,
-		rcv_q,
-		mcast,
-		frame,
-		rcv_b,
-		progs;
-};
-
-struct Rcv_pkt {
-	word	buf_ofs,
-		buf_seg,
-		buf_len,
-		timeout;
-};
-
-struct Xmit_pkt {
-	word	buf_ofs,
-		buf_seg,
-		pkt_len;
-};
-
-struct Rcv_resp {
-	word	buf_ofs,
-		buf_seg,
-		buf_len,
-		pkt_len,
-		timeout,
-		status;
-	dword	timetag;
-};
-
-struct Xmit_resp {
-	word	buf_ofs,
-		buf_seg,
-		c_stat,
-		status;
-};
-
-
-struct Netstat {
-	dword	tot_recv,
-		tot_xmit;
-	word	err_CRC,
-		err_align,
-		err_res,
-		err_ovrrun;
-};
-
-
-struct Selftest {
-	word	error;
-	union {
-		word ROM_cksum;
-		struct {
-			word ofs, seg;
-		} RAM;
-		word i82586;
-	} failure;
-};
-
-struct Info {
-	byte	minor_vers,
-		major_vers;
-	word	ROM_cksum,
-		RAM_sz,
-		free_ofs,
-		free_seg;
-};
-
-struct Memdump {
-       word size,
-            off,
-            seg;
-};
-
-/*
-Primary Command Block. The most important data structure. All communication
-between the host and the adapter is done with these. (Except for the actual
-Ethernet data, which has different packaging.)
-*/
-typedef struct {
-	byte	command;
-	byte	length;
-	union	{
-		struct Memconf		memconf;
-		word			configure;
-		struct Rcv_pkt		rcv_pkt;
-		struct Xmit_pkt		xmit_pkt;
-		byte			multicast[10][6];
-		byte			eth_addr[6];
-		byte			failed;
-		struct Rcv_resp		rcv_resp;
-		struct Xmit_resp	xmit_resp;
-		struct Netstat		netstat;
-		struct Selftest		selftest;
-		struct Info		info;
-		struct Memdump    	memdump;
-		byte			raw[62];
-	} data;
-} pcb_struct;
-
-/* These defines for 'configure' */
-#define RECV_STATION	0x00
-#define RECV_BROAD	0x01
-#define RECV_MULTI	0x02
-#define RECV_PROMISC	0x04
-#define NO_LOOPBACK	0x00
-#define INT_LOOPBACK	0x08
-#define EXT_LOOPBACK	0x10
-
-/*****************************************************************
- *
- *  structure to hold context information for adapter
- *
- *****************************************************************/
-
-#define DMA_BUFFER_SIZE  1600
-#define BACKLOG_SIZE      4
-
-typedef struct {
-	volatile short got[NUM_TRANSMIT_CMDS];	/* flags for
-						   command completion */
-	pcb_struct tx_pcb;	/* PCB for foreground sending */
-	pcb_struct rx_pcb;	/* PCB for foreground receiving */
-	pcb_struct itx_pcb;	/* PCB for background sending */
-	pcb_struct irx_pcb;	/* PCB for background receiving */
-
-	void *dma_buffer;
-
-	struct {
-		unsigned int length[BACKLOG_SIZE];
-		unsigned int in;
-		unsigned int out;
-	} rx_backlog;
-
-	struct {
-		unsigned int direction;
-		unsigned int length;
-		struct sk_buff *skb;
-	        void *target;
-		unsigned long start_time;
-	} current_dma;
-
-	/* flags */
-	unsigned long send_pcb_semaphore;
-	unsigned long dmaing;
-	unsigned long busy;
-
-	unsigned int rx_active;  /* number of receive PCBs */
-        volatile unsigned char hcr_val;  /* what we think the HCR contains */
-        spinlock_t lock;	/* Interrupt v tx lock */
-} elp_device;
diff -druN linux-libre-3.1-gnu/drivers/net/3c507.c linux-libre-3.2-gnu/drivers/net/3c507.c
--- linux-libre-3.1-gnu/drivers/net/3c507.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/3c507.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,939 +0,0 @@
-/* 3c507.c: An EtherLink16 device driver for Linux. */
-/*
-	Written 1993,1994 by Donald Becker.
-
-	Copyright 1993 United States Government as represented by the
-	Director, National Security Agency.
-
-	This software may be used and distributed according to the terms
-	of the GNU General Public License, incorporated herein by reference.
-
-	The author may be reached as becker@scyld.com, or C/O
-	Scyld Computing Corporation
-	410 Severn Ave., Suite 210
-	Annapolis MD 21403
-
-
-	Thanks go to jennings@Montrouge.SMR.slb.com ( Patrick Jennings)
-	and jrs@world.std.com (Rick Sladkey) for testing and bugfixes.
-	Mark Salazar <leslie@access.digex.net> made the changes for cards with
-	only 16K packet buffers.
-
-	Things remaining to do:
-	Verify that the tx and rx buffers don't have fencepost errors.
-	Move the theory of operation and memory map documentation.
-	The statistics need to be updated correctly.
-*/
-
-#define DRV_NAME		"3c507"
-#define DRV_VERSION		"1.10a"
-#define DRV_RELDATE		"11/17/2001"
-
-static const char version[] =
-	DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Donald Becker (becker@scyld.com)\n";
-
-/*
-  Sources:
-	This driver wouldn't have been written with the availability of the
-	Crynwr driver source code.	It provided a known-working implementation
-	that filled in the gaping holes of the Intel documentation.  Three cheers
-	for Russ Nelson.
-
-	Intel Microcommunications Databook, Vol. 1, 1990.  It provides just enough
-	info that the casual reader might think that it documents the i82586 :-<.
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/spinlock.h>
-#include <linux/ethtool.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_ether.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-/* use 0 for production, 1 for verification, 2..7 for debug */
-#ifndef NET_DEBUG
-#define NET_DEBUG 1
-#endif
-static unsigned int net_debug = NET_DEBUG;
-#define debug net_debug
-
-
-/*
-  			Details of the i82586.
-
-   You'll really need the databook to understand the details of this part,
-   but the outline is that the i82586 has two separate processing units.
-   Both are started from a list of three configuration tables, of which only
-   the last, the System Control Block (SCB), is used after reset-time.  The SCB
-   has the following fields:
-		Status word
-		Command word
-		Tx/Command block addr.
-		Rx block addr.
-   The command word accepts the following controls for the Tx and Rx units:
-  */
-
-#define	 CUC_START	 0x0100
-#define	 CUC_RESUME	 0x0200
-#define	 CUC_SUSPEND 0x0300
-#define	 RX_START	 0x0010
-#define	 RX_RESUME	 0x0020
-#define	 RX_SUSPEND	 0x0030
-
-/* The Rx unit uses a list of frame descriptors and a list of data buffer
-   descriptors.  We use full-sized (1518 byte) data buffers, so there is
-   a one-to-one pairing of frame descriptors to buffer descriptors.
-
-   The Tx ("command") unit executes a list of commands that look like:
-		Status word		Written by the 82586 when the command is done.
-		Command word	Command in lower 3 bits, post-command action in upper 3
-		Link word		The address of the next command.
-		Parameters		(as needed).
-
-	Some definitions related to the Command Word are:
- */
-#define CMD_EOL		0x8000			/* The last command of the list, stop. */
-#define CMD_SUSP	0x4000			/* Suspend after doing cmd. */
-#define CMD_INTR	0x2000			/* Interrupt after doing cmd. */
-
-enum commands {
-	CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
-	CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7};
-
-/* Information that need to be kept for each board. */
-struct net_local {
-	int last_restart;
-	ushort rx_head;
-	ushort rx_tail;
-	ushort tx_head;
-	ushort tx_cmd_link;
-	ushort tx_reap;
-	ushort tx_pkts_in_ring;
-	spinlock_t lock;
-	void __iomem *base;
-};
-
-/*
-  		Details of the EtherLink16 Implementation
-  The 3c507 is a generic shared-memory i82586 implementation.
-  The host can map 16K, 32K, 48K, or 64K of the 64K memory into
-  0x0[CD][08]0000, or all 64K into 0xF[02468]0000.
-  */
-
-/* Offsets from the base I/O address. */
-#define	SA_DATA		0	/* Station address data, or 3Com signature. */
-#define MISC_CTRL	6	/* Switch the SA_DATA banks, and bus config bits. */
-#define RESET_IRQ	10	/* Reset the latched IRQ line. */
-#define SIGNAL_CA	11	/* Frob the 82586 Channel Attention line. */
-#define ROM_CONFIG	13
-#define MEM_CONFIG	14
-#define IRQ_CONFIG	15
-#define EL16_IO_EXTENT 16
-
-/* The ID port is used at boot-time to locate the ethercard. */
-#define ID_PORT		0x100
-
-/* Offsets to registers in the mailbox (SCB). */
-#define iSCB_STATUS	0x8
-#define iSCB_CMD		0xA
-#define iSCB_CBL		0xC	/* Command BLock offset. */
-#define iSCB_RFA		0xE	/* Rx Frame Area offset. */
-
-/*  Since the 3c507 maps the shared memory window so that the last byte is
-	at 82586 address FFFF, the first byte is at 82586 address 0, 16K, 32K, or
-	48K corresponding to window sizes of 64K, 48K, 32K and 16K respectively.
-	We can account for this be setting the 'SBC Base' entry in the ISCP table
-	below for all the 16 bit offset addresses, and also adding the 'SCB Base'
-	value to all 24 bit physical addresses (in the SCP table and the TX and RX
-	Buffer Descriptors).
-					-Mark
-	*/
-#define SCB_BASE		((unsigned)64*1024 - (dev->mem_end - dev->mem_start))
-
-/*
-  What follows in 'init_words[]' is the "program" that is downloaded to the
-  82586 memory.	 It's mostly tables and command blocks, and starts at the
-  reset address 0xfffff6.  This is designed to be similar to the EtherExpress,
-  thus the unusual location of the SCB at 0x0008.
-
-  Even with the additional "don't care" values, doing it this way takes less
-  program space than initializing the individual tables, and I feel it's much
-  cleaner.
-
-  The databook is particularly useless for the first two structures, I had
-  to use the Crynwr driver as an example.
-
-   The memory setup is as follows:
-   */
-
-#define CONFIG_CMD	0x0018
-#define SET_SA_CMD	0x0024
-#define SA_OFFSET	0x002A
-#define IDLELOOP	0x30
-#define TDR_CMD		0x38
-#define TDR_TIME	0x3C
-#define DUMP_CMD	0x40
-#define DIAG_CMD	0x48
-#define SET_MC_CMD	0x4E
-#define DUMP_DATA	0x56	/* A 170 byte buffer for dump and Set-MC into. */
-
-#define TX_BUF_START	0x0100
-#define NUM_TX_BUFS 	5
-#define TX_BUF_SIZE 	(1518+14+20+16) /* packet+header+TBD */
-
-#define RX_BUF_START	0x2000
-#define RX_BUF_SIZE 	(1518+14+18)	/* packet+header+RBD */
-#define RX_BUF_END		(dev->mem_end - dev->mem_start)
-
-#define TX_TIMEOUT (HZ/20)
-
-/*
-  That's it: only 86 bytes to set up the beast, including every extra
-  command available.  The 170 byte buffer at DUMP_DATA is shared between the
-  Dump command (called only by the diagnostic program) and the SetMulticastList
-  command.
-
-  To complete the memory setup you only have to write the station address at
-  SA_OFFSET and create the Tx & Rx buffer lists.
-
-  The Tx command chain and buffer list is setup as follows:
-  A Tx command table, with the data buffer pointing to...
-  A Tx data buffer descriptor.  The packet is in a single buffer, rather than
-	chaining together several smaller buffers.
-  A NoOp command, which initially points to itself,
-  And the packet data.
-
-  A transmit is done by filling in the Tx command table and data buffer,
-  re-writing the NoOp command, and finally changing the offset of the last
-  command to point to the current Tx command.  When the Tx command is finished,
-  it jumps to the NoOp, when it loops until the next Tx command changes the
-  "link offset" in the NoOp.  This way the 82586 never has to go through the
-  slow restart sequence.
-
-  The Rx buffer list is set up in the obvious ring structure.  We have enough
-  memory (and low enough interrupt latency) that we can avoid the complicated
-  Rx buffer linked lists by alway associating a full-size Rx data buffer with
-  each Rx data frame.
-
-  I current use four transmit buffers starting at TX_BUF_START (0x0100), and
-  use the rest of memory, from RX_BUF_START to RX_BUF_END, for Rx buffers.
-
-  */
-
-static unsigned short init_words[] = {
-	/*	System Configuration Pointer (SCP). */
-	0x0000,					/* Set bus size to 16 bits. */
-	0,0,					/* pad words. */
-	0x0000,0x0000,			/* ISCP phys addr, set in init_82586_mem(). */
-
-	/*	Intermediate System Configuration Pointer (ISCP). */
-	0x0001,					/* Status word that's cleared when init is done. */
-	0x0008,0,0,				/* SCB offset, (skip, skip) */
-
-	/* System Control Block (SCB). */
-	0,0xf000|RX_START|CUC_START,	/* SCB status and cmd. */
-	CONFIG_CMD,				/* Command list pointer, points to Configure. */
-	RX_BUF_START,				/* Rx block list. */
-	0,0,0,0,				/* Error count: CRC, align, buffer, overrun. */
-
-	/* 0x0018: Configure command.  Change to put MAC data with packet. */
-	0, CmdConfigure,		/* Status, command.		*/
-	SET_SA_CMD,				/* Next command is Set Station Addr. */
-	0x0804,					/* "4" bytes of config data, 8 byte FIFO. */
-	0x2e40,					/* Magic values, including MAC data location. */
-	0,						/* Unused pad word. */
-
-	/* 0x0024: Setup station address command. */
-	0, CmdSASetup,
-	SET_MC_CMD,				/* Next command. */
-	0xaa00,0xb000,0x0bad,	/* Station address (to be filled in) */
-
-	/* 0x0030: NOP, looping back to itself.	 Point to first Tx buffer to Tx. */
-	0, CmdNOp, IDLELOOP, 0 /* pad */,
-
-	/* 0x0038: A unused Time-Domain Reflectometer command. */
-	0, CmdTDR, IDLELOOP, 0,
-
-	/* 0x0040: An unused Dump State command. */
-	0, CmdDump, IDLELOOP, DUMP_DATA,
-
-	/* 0x0048: An unused Diagnose command. */
-	0, CmdDiagnose, IDLELOOP,
-
-	/* 0x004E: An empty set-multicast-list command. */
-	0, CmdMulticastList, IDLELOOP, 0,
-};
-
-/* Index to functions, as function prototypes. */
-
-static int	el16_probe1(struct net_device *dev, int ioaddr);
-static int	el16_open(struct net_device *dev);
-static netdev_tx_t el16_send_packet(struct sk_buff *skb,
-				    struct net_device *dev);
-static irqreturn_t el16_interrupt(int irq, void *dev_id);
-static void el16_rx(struct net_device *dev);
-static int	el16_close(struct net_device *dev);
-static void el16_tx_timeout (struct net_device *dev);
-
-static void hardware_send_packet(struct net_device *dev, void *buf, short length, short pad);
-static void init_82586_mem(struct net_device *dev);
-static const struct ethtool_ops netdev_ethtool_ops;
-static void init_rx_bufs(struct net_device *);
-
-static int io = 0x300;
-static int irq;
-static int mem_start;
-
-
-/* Check for a network adaptor of this type, and return '0' iff one exists.
-	If dev->base_addr == 0, probe all likely locations.
-	If dev->base_addr == 1, always return failure.
-	If dev->base_addr == 2, (detachable devices only) allocate space for the
-	device and return success.
-	*/
-
-struct net_device * __init el16_probe(int unit)
-{
-	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
-	static const unsigned ports[] = { 0x300, 0x320, 0x340, 0x280, 0};
-	const unsigned *port;
-	int err = -ENODEV;
-
-	if (!dev)
-		return ERR_PTR(-ENODEV);
-
-	if (unit >= 0) {
-		sprintf(dev->name, "eth%d", unit);
-		netdev_boot_setup_check(dev);
-		io = dev->base_addr;
-		irq = dev->irq;
-		mem_start = dev->mem_start & 15;
-	}
-
-	if (io > 0x1ff) 	/* Check a single specified location. */
-		err = el16_probe1(dev, io);
-	else if (io != 0)
-		err = -ENXIO;		/* Don't probe at all. */
-	else {
-		for (port = ports; *port; port++) {
-			err = el16_probe1(dev, *port);
-			if (!err)
-				break;
-		}
-	}
-
-	if (err)
-		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
-	return dev;
-out1:
-	free_irq(dev->irq, dev);
-	iounmap(((struct net_local *)netdev_priv(dev))->base);
-	release_region(dev->base_addr, EL16_IO_EXTENT);
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-
-static const struct net_device_ops netdev_ops = {
-	.ndo_open		= el16_open,
-	.ndo_stop		= el16_close,
-	.ndo_start_xmit 	= el16_send_packet,
-	.ndo_tx_timeout 	= el16_tx_timeout,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-static int __init el16_probe1(struct net_device *dev, int ioaddr)
-{
-	static unsigned char init_ID_done;
-	int i, irq, irqval, retval;
-	struct net_local *lp;
-
-	if (init_ID_done == 0) {
-		ushort lrs_state = 0xff;
-		/* Send the ID sequence to the ID_PORT to enable the board(s). */
-		outb(0x00, ID_PORT);
-		for(i = 0; i < 255; i++) {
-			outb(lrs_state, ID_PORT);
-			lrs_state <<= 1;
-			if (lrs_state & 0x100)
-				lrs_state ^= 0xe7;
-		}
-		outb(0x00, ID_PORT);
-		init_ID_done = 1;
-	}
-
-	if (!request_region(ioaddr, EL16_IO_EXTENT, DRV_NAME))
-		return -ENODEV;
-
-	if ((inb(ioaddr) != '*') || (inb(ioaddr + 1) != '3') ||
-	    (inb(ioaddr + 2) != 'C') || (inb(ioaddr + 3) != 'O')) {
-		retval = -ENODEV;
-		goto out;
-	}
-
-	pr_info("%s: 3c507 at %#x,", dev->name, ioaddr);
-
-	/* We should make a few more checks here, like the first three octets of
-	   the S.A. for the manufacturer's code. */
-
-	irq = inb(ioaddr + IRQ_CONFIG) & 0x0f;
-
-	irqval = request_irq(irq, el16_interrupt, 0, DRV_NAME, dev);
-	if (irqval) {
-		pr_cont("\n");
-		pr_err("3c507: unable to get IRQ %d (irqval=%d).\n", irq, irqval);
-		retval = -EAGAIN;
-		goto out;
-	}
-
-	/* We've committed to using the board, and can start filling in *dev. */
-	dev->base_addr = ioaddr;
-
-	outb(0x01, ioaddr + MISC_CTRL);
-	for (i = 0; i < 6; i++)
-		dev->dev_addr[i] = inb(ioaddr + i);
-	pr_cont(" %pM", dev->dev_addr);
-
-	if (mem_start)
-		net_debug = mem_start & 7;
-
-#ifdef MEM_BASE
-	dev->mem_start = MEM_BASE;
-	dev->mem_end = dev->mem_start + 0x10000;
-#else
-	{
-		int base;
-		int size;
-		char mem_config = inb(ioaddr + MEM_CONFIG);
-		if (mem_config & 0x20) {
-			size = 64*1024;
-			base = 0xf00000 + (mem_config & 0x08 ? 0x080000
-							   : ((mem_config & 3) << 17));
-		} else {
-			size = ((mem_config & 3) + 1) << 14;
-			base = 0x0c0000 + ( (mem_config & 0x18) << 12);
-		}
-		dev->mem_start = base;
-		dev->mem_end = base + size;
-	}
-#endif
-
-	dev->if_port = (inb(ioaddr + ROM_CONFIG) & 0x80) ? 1 : 0;
-	dev->irq = inb(ioaddr + IRQ_CONFIG) & 0x0f;
-
-	pr_cont(", IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->irq,
-		   dev->if_port ? "ex" : "in", dev->mem_start, dev->mem_end-1);
-
-	if (net_debug)
-		pr_debug("%s", version);
-
-	lp = netdev_priv(dev);
-	spin_lock_init(&lp->lock);
-	lp->base = ioremap(dev->mem_start, RX_BUF_END);
-	if (!lp->base) {
-		pr_err("3c507: unable to remap memory\n");
-		retval = -EAGAIN;
-		goto out1;
-	}
-
-	dev->netdev_ops = &netdev_ops;
-	dev->watchdog_timeo = TX_TIMEOUT;
-	dev->ethtool_ops = &netdev_ethtool_ops;
- 	dev->flags &= ~IFF_MULTICAST;	/* Multicast doesn't work */
-	return 0;
-out1:
-	free_irq(dev->irq, dev);
-out:
-	release_region(ioaddr, EL16_IO_EXTENT);
-	return retval;
-}
-
-static int el16_open(struct net_device *dev)
-{
-	/* Initialize the 82586 memory and start it. */
-	init_82586_mem(dev);
-
-	netif_start_queue(dev);
-	return 0;
-}
-
-
-static void el16_tx_timeout (struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-	void __iomem *shmem = lp->base;
-
-	if (net_debug > 1)
-		pr_debug("%s: transmit timed out, %s?  ", dev->name,
-			readw(shmem + iSCB_STATUS) & 0x8000 ? "IRQ conflict" :
-			"network cable problem");
-	/* Try to restart the adaptor. */
-	if (lp->last_restart == dev->stats.tx_packets) {
-		if (net_debug > 1)
-			pr_cont("Resetting board.\n");
-		/* Completely reset the adaptor. */
-		init_82586_mem (dev);
-		lp->tx_pkts_in_ring = 0;
-	} else {
-		/* Issue the channel attention signal and hope it "gets better". */
-		if (net_debug > 1)
-			pr_cont("Kicking board.\n");
-		writew(0xf000 | CUC_START | RX_START, shmem + iSCB_CMD);
-		outb (0, ioaddr + SIGNAL_CA);	/* Issue channel-attn. */
-		lp->last_restart = dev->stats.tx_packets;
-	}
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	netif_wake_queue (dev);
-}
-
-
-static netdev_tx_t el16_send_packet (struct sk_buff *skb,
-				     struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-	unsigned long flags;
-	short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-	unsigned char *buf = skb->data;
-
-	netif_stop_queue (dev);
-
-	spin_lock_irqsave (&lp->lock, flags);
-
-	dev->stats.tx_bytes += length;
-	/* Disable the 82586's input to the interrupt line. */
-	outb (0x80, ioaddr + MISC_CTRL);
-
-	hardware_send_packet (dev, buf, skb->len, length - skb->len);
-
-	/* Enable the 82586 interrupt input. */
-	outb (0x84, ioaddr + MISC_CTRL);
-
-	spin_unlock_irqrestore (&lp->lock, flags);
-
-	dev_kfree_skb (skb);
-
-	/* You might need to clean up and record Tx statistics here. */
-
-	return NETDEV_TX_OK;
-}
-
-/*	The typical workload of the driver:
-	Handle the network interface interrupts. */
-static irqreturn_t el16_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct net_local *lp;
-	int ioaddr, status, boguscount = 0;
-	ushort ack_cmd = 0;
-	void __iomem *shmem;
-
-	if (dev == NULL) {
-		pr_err("net_interrupt(): irq %d for unknown device.\n", irq);
-		return IRQ_NONE;
-	}
-
-	ioaddr = dev->base_addr;
-	lp = netdev_priv(dev);
-	shmem = lp->base;
-
-	spin_lock(&lp->lock);
-
-	status = readw(shmem+iSCB_STATUS);
-
-	if (net_debug > 4) {
-		pr_debug("%s: 3c507 interrupt, status %4.4x.\n", dev->name, status);
-	}
-
-	/* Disable the 82586's input to the interrupt line. */
-	outb(0x80, ioaddr + MISC_CTRL);
-
-	/* Reap the Tx packet buffers. */
-	while (lp->tx_pkts_in_ring) {
-	  unsigned short tx_status = readw(shmem+lp->tx_reap);
-	  if (!(tx_status & 0x8000)) {
-		if (net_debug > 5)
-			pr_debug("Tx command incomplete (%#x).\n", lp->tx_reap);
-		break;
-	  }
-	  /* Tx unsuccessful or some interesting status bit set. */
-	  if (!(tx_status & 0x2000) || (tx_status & 0x0f3f)) {
-		dev->stats.tx_errors++;
-		if (tx_status & 0x0600)  dev->stats.tx_carrier_errors++;
-		if (tx_status & 0x0100)  dev->stats.tx_fifo_errors++;
-		if (!(tx_status & 0x0040))  dev->stats.tx_heartbeat_errors++;
-		if (tx_status & 0x0020)  dev->stats.tx_aborted_errors++;
-		dev->stats.collisions += tx_status & 0xf;
-	  }
-	  dev->stats.tx_packets++;
-	  if (net_debug > 5)
-		  pr_debug("Reaped %x, Tx status %04x.\n" , lp->tx_reap, tx_status);
-	  lp->tx_reap += TX_BUF_SIZE;
-	  if (lp->tx_reap > RX_BUF_START - TX_BUF_SIZE)
-		lp->tx_reap = TX_BUF_START;
-
-	  lp->tx_pkts_in_ring--;
-	  /* There is always more space in the Tx ring buffer now. */
-	  netif_wake_queue(dev);
-
-	  if (++boguscount > 10)
-		break;
-	}
-
-	if (status & 0x4000) { /* Packet received. */
-		if (net_debug > 5)
-			pr_debug("Received packet, rx_head %04x.\n", lp->rx_head);
-		el16_rx(dev);
-	}
-
-	/* Acknowledge the interrupt sources. */
-	ack_cmd = status & 0xf000;
-
-	if ((status & 0x0700) != 0x0200 && netif_running(dev)) {
-		if (net_debug)
-			pr_debug("%s: Command unit stopped, status %04x, restarting.\n",
-				   dev->name, status);
-		/* If this ever occurs we should really re-write the idle loop, reset
-		   the Tx list, and do a complete restart of the command unit.
-		   For now we rely on the Tx timeout if the resume doesn't work. */
-		ack_cmd |= CUC_RESUME;
-	}
-
-	if ((status & 0x0070) != 0x0040 && netif_running(dev)) {
-		/* The Rx unit is not ready, it must be hung.  Restart the receiver by
-		   initializing the rx buffers, and issuing an Rx start command. */
-		if (net_debug)
-			pr_debug("%s: Rx unit stopped, status %04x, restarting.\n",
-				   dev->name, status);
-		init_rx_bufs(dev);
-		writew(RX_BUF_START,shmem+iSCB_RFA);
-		ack_cmd |= RX_START;
-	}
-
-	writew(ack_cmd,shmem+iSCB_CMD);
-	outb(0, ioaddr + SIGNAL_CA);			/* Issue channel-attn. */
-
-	/* Clear the latched interrupt. */
-	outb(0, ioaddr + RESET_IRQ);
-
-	/* Enable the 82586's interrupt input. */
-	outb(0x84, ioaddr + MISC_CTRL);
-	spin_unlock(&lp->lock);
-	return IRQ_HANDLED;
-}
-
-static int el16_close(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-	void __iomem *shmem = lp->base;
-
-	netif_stop_queue(dev);
-
-	/* Flush the Tx and disable Rx. */
-	writew(RX_SUSPEND | CUC_SUSPEND,shmem+iSCB_CMD);
-	outb(0, ioaddr + SIGNAL_CA);
-
-	/* Disable the 82586's input to the interrupt line. */
-	outb(0x80, ioaddr + MISC_CTRL);
-
-	/* We always physically use the IRQ line, so we don't do free_irq(). */
-
-	/* Update the statistics here. */
-
-	return 0;
-}
-
-/* Initialize the Rx-block list. */
-static void init_rx_bufs(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	void __iomem *write_ptr;
-	unsigned short SCB_base = SCB_BASE;
-
-	int cur_rxbuf = lp->rx_head = RX_BUF_START;
-
-	/* Initialize each Rx frame + data buffer. */
-	do {	/* While there is room for one more. */
-
-		write_ptr = lp->base + cur_rxbuf;
-
-		writew(0x0000,write_ptr);			/* Status */
-		writew(0x0000,write_ptr+=2);			/* Command */
-		writew(cur_rxbuf + RX_BUF_SIZE,write_ptr+=2);	/* Link */
-		writew(cur_rxbuf + 22,write_ptr+=2);		/* Buffer offset */
-		writew(0x0000,write_ptr+=2);			/* Pad for dest addr. */
-		writew(0x0000,write_ptr+=2);
-		writew(0x0000,write_ptr+=2);
-		writew(0x0000,write_ptr+=2);			/* Pad for source addr. */
-		writew(0x0000,write_ptr+=2);
-		writew(0x0000,write_ptr+=2);
-		writew(0x0000,write_ptr+=2);			/* Pad for protocol. */
-
-		writew(0x0000,write_ptr+=2);			/* Buffer: Actual count */
-		writew(-1,write_ptr+=2);			/* Buffer: Next (none). */
-		writew(cur_rxbuf + 0x20 + SCB_base,write_ptr+=2);/* Buffer: Address low */
-		writew(0x0000,write_ptr+=2);
-		/* Finally, the number of bytes in the buffer. */
-		writew(0x8000 + RX_BUF_SIZE-0x20,write_ptr+=2);
-
-		lp->rx_tail = cur_rxbuf;
-		cur_rxbuf += RX_BUF_SIZE;
-	} while (cur_rxbuf <= RX_BUF_END - RX_BUF_SIZE);
-
-	/* Terminate the list by setting the EOL bit, and wrap the pointer to make
-	   the list a ring. */
-	write_ptr = lp->base + lp->rx_tail + 2;
-	writew(0xC000,write_ptr);				/* Command, mark as last. */
-	writew(lp->rx_head,write_ptr+2);			/* Link */
-}
-
-static void init_82586_mem(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	short ioaddr = dev->base_addr;
-	void __iomem *shmem = lp->base;
-
-	/* Enable loopback to protect the wire while starting up,
-	   and hold the 586 in reset during the memory initialization. */
-	outb(0x20, ioaddr + MISC_CTRL);
-
-	/* Fix the ISCP address and base. */
-	init_words[3] = SCB_BASE;
-	init_words[7] = SCB_BASE;
-
-	/* Write the words at 0xfff6 (address-aliased to 0xfffff6). */
-	memcpy_toio(lp->base + RX_BUF_END - 10, init_words, 10);
-
-	/* Write the words at 0x0000. */
-	memcpy_toio(lp->base, init_words + 5, sizeof(init_words) - 10);
-
-	/* Fill in the station address. */
-	memcpy_toio(lp->base+SA_OFFSET, dev->dev_addr, ETH_ALEN);
-
-	/* The Tx-block list is written as needed.  We just set up the values. */
-	lp->tx_cmd_link = IDLELOOP + 4;
-	lp->tx_head = lp->tx_reap = TX_BUF_START;
-
-	init_rx_bufs(dev);
-
-	/* Start the 586 by releasing the reset line, but leave loopback. */
-	outb(0xA0, ioaddr + MISC_CTRL);
-
-	/* This was time consuming to track down: you need to give two channel
-	   attention signals to reliably start up the i82586. */
-	outb(0, ioaddr + SIGNAL_CA);
-
-	{
-		int boguscnt = 50;
-		while (readw(shmem+iSCB_STATUS) == 0)
-			if (--boguscnt == 0) {
-				pr_warning("%s: i82586 initialization timed out with status %04x, cmd %04x.\n",
-					dev->name, readw(shmem+iSCB_STATUS), readw(shmem+iSCB_CMD));
-				break;
-			}
-		/* Issue channel-attn -- the 82586 won't start. */
-		outb(0, ioaddr + SIGNAL_CA);
-	}
-
-	/* Disable loopback and enable interrupts. */
-	outb(0x84, ioaddr + MISC_CTRL);
-	if (net_debug > 4)
-		pr_debug("%s: Initialized 82586, status %04x.\n", dev->name,
-			   readw(shmem+iSCB_STATUS));
-}
-
-static void hardware_send_packet(struct net_device *dev, void *buf, short length, short pad)
-{
-	struct net_local *lp = netdev_priv(dev);
-	short ioaddr = dev->base_addr;
-	ushort tx_block = lp->tx_head;
-	void __iomem *write_ptr = lp->base + tx_block;
-	static char padding[ETH_ZLEN];
-
-	/* Set the write pointer to the Tx block, and put out the header. */
-	writew(0x0000,write_ptr);			/* Tx status */
-	writew(CMD_INTR|CmdTx,write_ptr+=2);		/* Tx command */
-	writew(tx_block+16,write_ptr+=2);		/* Next command is a NoOp. */
-	writew(tx_block+8,write_ptr+=2);			/* Data Buffer offset. */
-
-	/* Output the data buffer descriptor. */
-	writew((pad + length) | 0x8000,write_ptr+=2);		/* Byte count parameter. */
-	writew(-1,write_ptr+=2);			/* No next data buffer. */
-	writew(tx_block+22+SCB_BASE,write_ptr+=2);	/* Buffer follows the NoOp command. */
-	writew(0x0000,write_ptr+=2);			/* Buffer address high bits (always zero). */
-
-	/* Output the Loop-back NoOp command. */
-	writew(0x0000,write_ptr+=2);			/* Tx status */
-	writew(CmdNOp,write_ptr+=2);			/* Tx command */
-	writew(tx_block+16,write_ptr+=2);		/* Next is myself. */
-
-	/* Output the packet at the write pointer. */
-	memcpy_toio(write_ptr+2, buf, length);
-	if (pad)
-		memcpy_toio(write_ptr+length+2, padding, pad);
-
-	/* Set the old command link pointing to this send packet. */
-	writew(tx_block,lp->base + lp->tx_cmd_link);
-	lp->tx_cmd_link = tx_block + 20;
-
-	/* Set the next free tx region. */
-	lp->tx_head = tx_block + TX_BUF_SIZE;
-	if (lp->tx_head > RX_BUF_START - TX_BUF_SIZE)
-		lp->tx_head = TX_BUF_START;
-
-	if (net_debug > 4) {
-		pr_debug("%s: 3c507 @%x send length = %d, tx_block %3x, next %3x.\n",
-			   dev->name, ioaddr, length, tx_block, lp->tx_head);
-	}
-
-	/* Grimly block further packets if there has been insufficient reaping. */
-	if (++lp->tx_pkts_in_ring < NUM_TX_BUFS)
-		netif_wake_queue(dev);
-}
-
-static void el16_rx(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	void __iomem *shmem = lp->base;
-	ushort rx_head = lp->rx_head;
-	ushort rx_tail = lp->rx_tail;
-	ushort boguscount = 10;
-	short frame_status;
-
-	while ((frame_status = readw(shmem+rx_head)) < 0) {   /* Command complete */
-		void __iomem *read_frame = lp->base + rx_head;
-		ushort rfd_cmd = readw(read_frame+2);
-		ushort next_rx_frame = readw(read_frame+4);
-		ushort data_buffer_addr = readw(read_frame+6);
-		void __iomem *data_frame = lp->base + data_buffer_addr;
-		ushort pkt_len = readw(data_frame);
-
-		if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22 ||
-		    (pkt_len & 0xC000) != 0xC000) {
-			pr_err("%s: Rx frame at %#x corrupted, "
-			       "status %04x cmd %04x next %04x "
-			       "data-buf @%04x %04x.\n",
-			       dev->name, rx_head, frame_status, rfd_cmd,
-			       next_rx_frame, data_buffer_addr, pkt_len);
-		} else if ((frame_status & 0x2000) == 0) {
-			/* Frame Rxed, but with error. */
-			dev->stats.rx_errors++;
-			if (frame_status & 0x0800) dev->stats.rx_crc_errors++;
-			if (frame_status & 0x0400) dev->stats.rx_frame_errors++;
-			if (frame_status & 0x0200) dev->stats.rx_fifo_errors++;
-			if (frame_status & 0x0100) dev->stats.rx_over_errors++;
-			if (frame_status & 0x0080) dev->stats.rx_length_errors++;
-		} else {
-			/* Malloc up new buffer. */
-			struct sk_buff *skb;
-
-			pkt_len &= 0x3fff;
-			skb = dev_alloc_skb(pkt_len+2);
-			if (skb == NULL) {
-				pr_err("%s: Memory squeeze, dropping packet.\n",
-				       dev->name);
-				dev->stats.rx_dropped++;
-				break;
-			}
-
-			skb_reserve(skb,2);
-
-			/* 'skb->data' points to the start of sk_buff data area. */
-			memcpy_fromio(skb_put(skb,pkt_len), data_frame + 10, pkt_len);
-
-			skb->protocol=eth_type_trans(skb,dev);
-			netif_rx(skb);
-			dev->stats.rx_packets++;
-			dev->stats.rx_bytes += pkt_len;
-		}
-
-		/* Clear the status word and set End-of-List on the rx frame. */
-		writew(0,read_frame);
-		writew(0xC000,read_frame+2);
-		/* Clear the end-of-list on the prev. RFD. */
-		writew(0x0000,lp->base + rx_tail + 2);
-
-		rx_tail = rx_head;
-		rx_head = next_rx_frame;
-		if (--boguscount == 0)
-			break;
-	}
-
-	lp->rx_head = rx_head;
-	lp->rx_tail = rx_tail;
-}
-
-static void netdev_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-	sprintf(info->bus_info, "ISA 0x%lx", dev->base_addr);
-}
-
-static u32 netdev_get_msglevel(struct net_device *dev)
-{
-	return debug;
-}
-
-static void netdev_set_msglevel(struct net_device *dev, u32 level)
-{
-	debug = level;
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-	.get_drvinfo		= netdev_get_drvinfo,
-	.get_msglevel		= netdev_get_msglevel,
-	.set_msglevel		= netdev_set_msglevel,
-};
-
-#ifdef MODULE
-static struct net_device *dev_3c507;
-module_param(io, int, 0);
-module_param(irq, int, 0);
-MODULE_PARM_DESC(io, "EtherLink16 I/O base address");
-MODULE_PARM_DESC(irq, "(ignored)");
-
-int __init init_module(void)
-{
-	if (io == 0)
-		pr_notice("3c507: You should not use auto-probing with insmod!\n");
-	dev_3c507 = el16_probe(-1);
-	return IS_ERR(dev_3c507) ? PTR_ERR(dev_3c507) : 0;
-}
-
-void __exit
-cleanup_module(void)
-{
-	struct net_device *dev = dev_3c507;
-	unregister_netdev(dev);
-	free_irq(dev->irq, dev);
-	iounmap(((struct net_local *)netdev_priv(dev))->base);
-	release_region(dev->base_addr, EL16_IO_EXTENT);
-	free_netdev(dev);
-}
-#endif /* MODULE */
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/3c509.c linux-libre-3.2-gnu/drivers/net/3c509.c
--- linux-libre-3.1-gnu/drivers/net/3c509.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/3c509.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1594 +0,0 @@
-/* 3c509.c: A 3c509 EtherLink3 ethernet driver for linux. */
-/*
-	Written 1993-2000 by Donald Becker.
-
-	Copyright 1994-2000 by Donald Becker.
-	Copyright 1993 United States Government as represented by the
-	Director, National Security Agency.	 This software may be used and
-	distributed according to the terms of the GNU General Public License,
-	incorporated herein by reference.
-
-	This driver is for the 3Com EtherLinkIII series.
-
-	The author may be reached as becker@scyld.com, or C/O
-	Scyld Computing Corporation
-	410 Severn Ave., Suite 210
-	Annapolis MD 21403
-
-	Known limitations:
-	Because of the way 3c509 ISA detection works it's difficult to predict
-	a priori which of several ISA-mode cards will be detected first.
-
-	This driver does not use predictive interrupt mode, resulting in higher
-	packet latency but lower overhead.  If interrupts are disabled for an
-	unusually long time it could also result in missed packets, but in
-	practice this rarely happens.
-
-
-	FIXES:
-		Alan Cox:       Removed the 'Unexpected interrupt' bug.
-		Michael Meskes:	Upgraded to Donald Becker's version 1.07.
-		Alan Cox:	Increased the eeprom delay. Regardless of
-				what the docs say some people definitely
-				get problems with lower (but in card spec)
-				delays
-		v1.10 4/21/97 Fixed module code so that multiple cards may be detected,
-				other cleanups.  -djb
-		Andrea Arcangeli:	Upgraded to Donald Becker's version 1.12.
-		Rick Payne:	Fixed SMP race condition
-		v1.13 9/8/97 Made 'max_interrupt_work' an insmod-settable variable -djb
-		v1.14 10/15/97 Avoided waiting..discard message for fast machines -djb
-		v1.15 1/31/98 Faster recovery for Tx errors. -djb
-		v1.16 2/3/98 Different ID port handling to avoid sound cards. -djb
-		v1.18 12Mar2001 Andrew Morton
-			- Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz)
-			- Reviewed against 1.18 from scyld.com
-		v1.18a 17Nov2001 Jeff Garzik <jgarzik@pobox.com>
-			- ethtool support
-		v1.18b 1Mar2002 Zwane Mwaikambo <zwane@commfireservices.com>
-			- Power Management support
-		v1.18c 1Mar2002 David Ruggiero <jdr@farfalle.com>
-			- Full duplex support
-		v1.19  16Oct2002 Zwane Mwaikambo <zwane@linuxpower.ca>
-			- Additional ethtool features
-		v1.19a 28Oct2002 Davud Ruggiero <jdr@farfalle.com>
-			- Increase *read_eeprom udelay to workaround oops with 2 cards.
-		v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
-			- Introduce driver model for EISA cards.
-		v1.20  04Feb2008 Ondrej Zary <linux@rainbow-software.org>
-			- convert to isa_driver and pnp_driver and some cleanups
-*/
-
-#define DRV_NAME	"3c509"
-#define DRV_VERSION	"1.20"
-#define DRV_RELDATE	"04Feb2008"
-
-/* A few values that may be tweaked. */
-
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  (400*HZ/1000)
-
-#include <linux/module.h>
-#include <linux/mca.h>
-#include <linux/isa.h>
-#include <linux/pnp.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/in.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/pm.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>	/* for udelay() */
-#include <linux/spinlock.h>
-#include <linux/ethtool.h>
-#include <linux/device.h>
-#include <linux/eisa.h>
-#include <linux/bitops.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-static char version[] __devinitdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
-
-#ifdef EL3_DEBUG
-static int el3_debug = EL3_DEBUG;
-#else
-static int el3_debug = 2;
-#endif
-
-/* Used to do a global count of all the cards in the system.  Must be
- * a global variable so that the mca/eisa probe routines can increment
- * it */
-static int el3_cards = 0;
-#define EL3_MAX_CARDS 8
-
-/* To minimize the size of the driver source I only define operating
-   constants if they are used several times.  You'll need the manual
-   anyway if you want to understand driver details. */
-/* Offsets from base I/O address. */
-#define EL3_DATA 0x00
-#define EL3_CMD 0x0e
-#define EL3_STATUS 0x0e
-#define	EEPROM_READ 0x80
-
-#define EL3_IO_EXTENT	16
-
-#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
-
-
-/* The top five bits written to EL3_CMD are a command, the lower
-   11 bits are the parameter, if applicable. */
-enum c509cmd {
-	TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
-	RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11,
-	TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
-	FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
-	SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
-	SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11,
-	StatsDisable = 22<<11, StopCoax = 23<<11, PowerUp = 27<<11,
-	PowerDown = 28<<11, PowerAuto = 29<<11};
-
-enum c509status {
-	IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
-	TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
-	IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000, };
-
-/* The SetRxFilter command accepts the following classes: */
-enum RxFilter {
-	RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 };
-
-/* Register window 1 offsets, the window used in normal operation. */
-#define TX_FIFO		0x00
-#define RX_FIFO		0x00
-#define RX_STATUS 	0x08
-#define TX_STATUS 	0x0B
-#define TX_FREE		0x0C		/* Remaining free bytes in Tx buffer. */
-
-#define WN0_CONF_CTRL	0x04		/* Window 0: Configuration control register */
-#define WN0_ADDR_CONF	0x06		/* Window 0: Address configuration register */
-#define WN0_IRQ		0x08		/* Window 0: Set IRQ line in bits 12-15. */
-#define WN4_MEDIA	0x0A		/* Window 4: Various transcvr/media bits. */
-#define	MEDIA_TP	0x00C0		/* Enable link beat and jabber for 10baseT. */
-#define WN4_NETDIAG	0x06		/* Window 4: Net diagnostic */
-#define FD_ENABLE	0x8000		/* Enable full-duplex ("external loopback") */
-
-/*
- * Must be a power of two (we use a binary and in the
- * circular queue)
- */
-#define SKB_QUEUE_SIZE	64
-
-enum el3_cardtype { EL3_ISA, EL3_PNP, EL3_MCA, EL3_EISA };
-
-struct el3_private {
-	spinlock_t lock;
-	/* skb send-queue */
-	int head, size;
-	struct sk_buff *queue[SKB_QUEUE_SIZE];
-	enum el3_cardtype type;
-};
-static int id_port;
-static int current_tag;
-static struct net_device *el3_devs[EL3_MAX_CARDS];
-
-/* Parameters that may be passed into the module. */
-static int debug = -1;
-static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 10;
-#ifdef CONFIG_PNP
-static int nopnp;
-#endif
-
-static int __devinit el3_common_init(struct net_device *dev);
-static void el3_common_remove(struct net_device *dev);
-static ushort id_read_eeprom(int index);
-static ushort read_eeprom(int ioaddr, int index);
-static int el3_open(struct net_device *dev);
-static netdev_tx_t el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t el3_interrupt(int irq, void *dev_id);
-static void update_stats(struct net_device *dev);
-static struct net_device_stats *el3_get_stats(struct net_device *dev);
-static int el3_rx(struct net_device *dev);
-static int el3_close(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
-static void el3_tx_timeout (struct net_device *dev);
-static void el3_down(struct net_device *dev);
-static void el3_up(struct net_device *dev);
-static const struct ethtool_ops ethtool_ops;
-#ifdef CONFIG_PM
-static int el3_suspend(struct device *, pm_message_t);
-static int el3_resume(struct device *);
-#else
-#define el3_suspend NULL
-#define el3_resume NULL
-#endif
-
-
-/* generic device remove for all device types */
-static int el3_device_remove (struct device *device);
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void el3_poll_controller(struct net_device *dev);
-#endif
-
-/* Return 0 on success, 1 on error, 2 when found already detected PnP card */
-static int el3_isa_id_sequence(__be16 *phys_addr)
-{
-	short lrs_state = 0xff;
-	int i;
-
-	/* ISA boards are detected by sending the ID sequence to the
-	   ID_PORT.  We find cards past the first by setting the 'current_tag'
-	   on cards as they are found.  Cards with their tag set will not
-	   respond to subsequent ID sequences. */
-
-	outb(0x00, id_port);
-	outb(0x00, id_port);
-	for (i = 0; i < 255; i++) {
-		outb(lrs_state, id_port);
-		lrs_state <<= 1;
-		lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
-	}
-	/* For the first probe, clear all board's tag registers. */
-	if (current_tag == 0)
-		outb(0xd0, id_port);
-	else			/* Otherwise kill off already-found boards. */
-		outb(0xd8, id_port);
-	if (id_read_eeprom(7) != 0x6d50)
-		return 1;
-	/* Read in EEPROM data, which does contention-select.
-	   Only the lowest address board will stay "on-line".
-	   3Com got the byte order backwards. */
-	for (i = 0; i < 3; i++)
-		phys_addr[i] = htons(id_read_eeprom(i));
-#ifdef CONFIG_PNP
-	if (!nopnp) {
-		/* The ISA PnP 3c509 cards respond to the ID sequence too.
-		   This check is needed in order not to register them twice. */
-		for (i = 0; i < el3_cards; i++) {
-			struct el3_private *lp = netdev_priv(el3_devs[i]);
-			if (lp->type == EL3_PNP &&
-			    !memcmp(phys_addr, el3_devs[i]->dev_addr,
-				    ETH_ALEN)) {
-				if (el3_debug > 3)
-					pr_debug("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
-						phys_addr[0] & 0xff, phys_addr[0] >> 8,
-						phys_addr[1] & 0xff, phys_addr[1] >> 8,
-						phys_addr[2] & 0xff, phys_addr[2] >> 8);
-				/* Set the adaptor tag so that the next card can be found. */
-				outb(0xd0 + ++current_tag, id_port);
-				return 2;
-			}
-		}
-	}
-#endif /* CONFIG_PNP */
-	return 0;
-
-}
-
-static void __devinit el3_dev_fill(struct net_device *dev, __be16 *phys_addr,
-				   int ioaddr, int irq, int if_port,
-				   enum el3_cardtype type)
-{
-	struct el3_private *lp = netdev_priv(dev);
-
-	memcpy(dev->dev_addr, phys_addr, ETH_ALEN);
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-	dev->if_port = if_port;
-	lp->type = type;
-}
-
-static int __devinit el3_isa_match(struct device *pdev,
-				   unsigned int ndev)
-{
-	struct net_device *dev;
-	int ioaddr, isa_irq, if_port, err;
-	unsigned int iobase;
-	__be16 phys_addr[3];
-
-	while ((err = el3_isa_id_sequence(phys_addr)) == 2)
-		;	/* Skip to next card when PnP card found */
-	if (err == 1)
-		return 0;
-
-	iobase = id_read_eeprom(8);
-	if_port = iobase >> 14;
-	ioaddr = 0x200 + ((iobase & 0x1f) << 4);
-	if (irq[el3_cards] > 1 && irq[el3_cards] < 16)
-		isa_irq = irq[el3_cards];
-	else
-		isa_irq = id_read_eeprom(9) >> 12;
-
-	dev = alloc_etherdev(sizeof(struct el3_private));
-	if (!dev)
-		return -ENOMEM;
-
-	netdev_boot_setup_check(dev);
-
-	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-isa")) {
-		free_netdev(dev);
-		return 0;
-	}
-
-	/* Set the adaptor tag so that the next card can be found. */
-	outb(0xd0 + ++current_tag, id_port);
-
-	/* Activate the adaptor at the EEPROM location. */
-	outb((ioaddr >> 4) | 0xe0, id_port);
-
-	EL3WINDOW(0);
-	if (inw(ioaddr) != 0x6d50) {
-		free_netdev(dev);
-		return 0;
-	}
-
-	/* Free the interrupt so that some other card can use it. */
-	outw(0x0f00, ioaddr + WN0_IRQ);
-
-	el3_dev_fill(dev, phys_addr, ioaddr, isa_irq, if_port, EL3_ISA);
-	dev_set_drvdata(pdev, dev);
-	if (el3_common_init(dev)) {
-		free_netdev(dev);
-		return 0;
-	}
-
-	el3_devs[el3_cards++] = dev;
-	return 1;
-}
-
-static int __devexit el3_isa_remove(struct device *pdev,
-				    unsigned int ndev)
-{
-	el3_device_remove(pdev);
-	dev_set_drvdata(pdev, NULL);
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int el3_isa_suspend(struct device *dev, unsigned int n,
-			   pm_message_t state)
-{
-	current_tag = 0;
-	return el3_suspend(dev, state);
-}
-
-static int el3_isa_resume(struct device *dev, unsigned int n)
-{
-	struct net_device *ndev = dev_get_drvdata(dev);
-	int ioaddr = ndev->base_addr, err;
-	__be16 phys_addr[3];
-
-	while ((err = el3_isa_id_sequence(phys_addr)) == 2)
-		;	/* Skip to next card when PnP card found */
-	if (err == 1)
-		return 0;
-	/* Set the adaptor tag so that the next card can be found. */
-	outb(0xd0 + ++current_tag, id_port);
-	/* Enable the card */
-	outb((ioaddr >> 4) | 0xe0, id_port);
-	EL3WINDOW(0);
-	if (inw(ioaddr) != 0x6d50)
-		return 1;
-	/* Free the interrupt so that some other card can use it. */
-	outw(0x0f00, ioaddr + WN0_IRQ);
-	return el3_resume(dev);
-}
-#endif
-
-static struct isa_driver el3_isa_driver = {
-	.match		= el3_isa_match,
-	.remove		= __devexit_p(el3_isa_remove),
-#ifdef CONFIG_PM
-	.suspend	= el3_isa_suspend,
-	.resume		= el3_isa_resume,
-#endif
-	.driver		= {
-		.name	= "3c509"
-	},
-};
-static int isa_registered;
-
-#ifdef CONFIG_PNP
-static struct pnp_device_id el3_pnp_ids[] = {
-	{ .id = "TCM5090" }, /* 3Com Etherlink III (TP) */
-	{ .id = "TCM5091" }, /* 3Com Etherlink III */
-	{ .id = "TCM5094" }, /* 3Com Etherlink III (combo) */
-	{ .id = "TCM5095" }, /* 3Com Etherlink III (TPO) */
-	{ .id = "TCM5098" }, /* 3Com Etherlink III (TPC) */
-	{ .id = "PNP80f7" }, /* 3Com Etherlink III compatible */
-	{ .id = "PNP80f8" }, /* 3Com Etherlink III compatible */
-	{ .id = "" }
-};
-MODULE_DEVICE_TABLE(pnp, el3_pnp_ids);
-
-static int __devinit el3_pnp_probe(struct pnp_dev *pdev,
-				    const struct pnp_device_id *id)
-{
-	short i;
-	int ioaddr, irq, if_port;
-	__be16 phys_addr[3];
-	struct net_device *dev = NULL;
-	int err;
-
-	ioaddr = pnp_port_start(pdev, 0);
-	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-pnp"))
-		return -EBUSY;
-	irq = pnp_irq(pdev, 0);
-	EL3WINDOW(0);
-	for (i = 0; i < 3; i++)
-		phys_addr[i] = htons(read_eeprom(ioaddr, i));
-	if_port = read_eeprom(ioaddr, 8) >> 14;
-	dev = alloc_etherdev(sizeof(struct el3_private));
-	if (!dev) {
-		release_region(ioaddr, EL3_IO_EXTENT);
-		return -ENOMEM;
-	}
-	SET_NETDEV_DEV(dev, &pdev->dev);
-	netdev_boot_setup_check(dev);
-
-	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_PNP);
-	pnp_set_drvdata(pdev, dev);
-	err = el3_common_init(dev);
-
-	if (err) {
-		pnp_set_drvdata(pdev, NULL);
-		free_netdev(dev);
-		return err;
-	}
-
-	el3_devs[el3_cards++] = dev;
-	return 0;
-}
-
-static void __devexit el3_pnp_remove(struct pnp_dev *pdev)
-{
-	el3_common_remove(pnp_get_drvdata(pdev));
-	pnp_set_drvdata(pdev, NULL);
-}
-
-#ifdef CONFIG_PM
-static int el3_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
-{
-	return el3_suspend(&pdev->dev, state);
-}
-
-static int el3_pnp_resume(struct pnp_dev *pdev)
-{
-	return el3_resume(&pdev->dev);
-}
-#endif
-
-static struct pnp_driver el3_pnp_driver = {
-	.name		= "3c509",
-	.id_table	= el3_pnp_ids,
-	.probe		= el3_pnp_probe,
-	.remove		= __devexit_p(el3_pnp_remove),
-#ifdef CONFIG_PM
-	.suspend	= el3_pnp_suspend,
-	.resume		= el3_pnp_resume,
-#endif
-};
-static int pnp_registered;
-#endif /* CONFIG_PNP */
-
-#ifdef CONFIG_EISA
-static struct eisa_device_id el3_eisa_ids[] = {
-		{ "TCM5090" },
-		{ "TCM5091" },
-		{ "TCM5092" },
-		{ "TCM5093" },
-		{ "TCM5094" },
-		{ "TCM5095" },
-		{ "TCM5098" },
-		{ "" }
-};
-MODULE_DEVICE_TABLE(eisa, el3_eisa_ids);
-
-static int el3_eisa_probe (struct device *device);
-
-static struct eisa_driver el3_eisa_driver = {
-		.id_table = el3_eisa_ids,
-		.driver   = {
-				.name    = "3c579",
-				.probe   = el3_eisa_probe,
-				.remove  = __devexit_p (el3_device_remove),
-				.suspend = el3_suspend,
-				.resume  = el3_resume,
-		}
-};
-static int eisa_registered;
-#endif
-
-#ifdef CONFIG_MCA
-static int el3_mca_probe(struct device *dev);
-
-static short el3_mca_adapter_ids[] __initdata = {
-		0x627c,
-		0x627d,
-		0x62db,
-		0x62f6,
-		0x62f7,
-		0x0000
-};
-
-static char *el3_mca_adapter_names[] __initdata = {
-		"3Com 3c529 EtherLink III (10base2)",
-		"3Com 3c529 EtherLink III (10baseT)",
-		"3Com 3c529 EtherLink III (test mode)",
-		"3Com 3c529 EtherLink III (TP or coax)",
-		"3Com 3c529 EtherLink III (TP)",
-		NULL
-};
-
-static struct mca_driver el3_mca_driver = {
-		.id_table = el3_mca_adapter_ids,
-		.driver = {
-				.name = "3c529",
-				.bus = &mca_bus_type,
-				.probe = el3_mca_probe,
-				.remove = __devexit_p(el3_device_remove),
-				.suspend = el3_suspend,
-				.resume  = el3_resume,
-		},
-};
-static int mca_registered;
-#endif /* CONFIG_MCA */
-
-static const struct net_device_ops netdev_ops = {
-	.ndo_open 		= el3_open,
-	.ndo_stop	 	= el3_close,
-	.ndo_start_xmit 	= el3_start_xmit,
-	.ndo_get_stats 		= el3_get_stats,
-	.ndo_set_multicast_list = set_multicast_list,
-	.ndo_tx_timeout 	= el3_tx_timeout,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= el3_poll_controller,
-#endif
-};
-
-static int __devinit el3_common_init(struct net_device *dev)
-{
-	struct el3_private *lp = netdev_priv(dev);
-	int err;
-	const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
-
-	spin_lock_init(&lp->lock);
-
-	if (dev->mem_start & 0x05) { /* xcvr codes 1/3/4/12 */
-		dev->if_port = (dev->mem_start & 0x0f);
-	} else { /* xcvr codes 0/8 */
-		/* use eeprom value, but save user's full-duplex selection */
-		dev->if_port |= (dev->mem_start & 0x08);
-	}
-
-	/* The EL3-specific entries in the device structure. */
-	dev->netdev_ops = &netdev_ops;
-	dev->watchdog_timeo = TX_TIMEOUT;
-	SET_ETHTOOL_OPS(dev, &ethtool_ops);
-
-	err = register_netdev(dev);
-	if (err) {
-		pr_err("Failed to register 3c5x9 at %#3.3lx, IRQ %d.\n",
-			dev->base_addr, dev->irq);
-		release_region(dev->base_addr, EL3_IO_EXTENT);
-		return err;
-	}
-
-	pr_info("%s: 3c5x9 found at %#3.3lx, %s port, address %pM, IRQ %d.\n",
-	       dev->name, dev->base_addr, if_names[(dev->if_port & 0x03)],
-	       dev->dev_addr, dev->irq);
-
-	if (el3_debug > 0)
-		pr_info("%s", version);
-	return 0;
-
-}
-
-static void el3_common_remove (struct net_device *dev)
-{
-	unregister_netdev (dev);
-	release_region(dev->base_addr, EL3_IO_EXTENT);
-	free_netdev (dev);
-}
-
-#ifdef CONFIG_MCA
-static int __init el3_mca_probe(struct device *device)
-{
-	/* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch,
-	 * heavily modified by Chris Beauregard
-	 * (cpbeaure@csclub.uwaterloo.ca) to support standard MCA
-	 * probing.
-	 *
-	 * redone for multi-card detection by ZP Gu (zpg@castle.net)
-	 * now works as a module */
-
-	short i;
-	int ioaddr, irq, if_port;
-	__be16 phys_addr[3];
-	struct net_device *dev = NULL;
-	u_char pos4, pos5;
-	struct mca_device *mdev = to_mca_device(device);
-	int slot = mdev->slot;
-	int err;
-
-	pos4 = mca_device_read_stored_pos(mdev, 4);
-	pos5 = mca_device_read_stored_pos(mdev, 5);
-
-	ioaddr = ((short)((pos4&0xfc)|0x02)) << 8;
-	irq = pos5 & 0x0f;
-
-
-	pr_info("3c529: found %s at slot %d\n",
-		el3_mca_adapter_names[mdev->index], slot + 1);
-
-	/* claim the slot */
-	strncpy(mdev->name, el3_mca_adapter_names[mdev->index],
-			sizeof(mdev->name));
-	mca_device_set_claim(mdev, 1);
-
-	if_port = pos4 & 0x03;
-
-	irq = mca_device_transform_irq(mdev, irq);
-	ioaddr = mca_device_transform_ioport(mdev, ioaddr);
-	if (el3_debug > 2) {
-		pr_debug("3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
-	}
-	EL3WINDOW(0);
-	for (i = 0; i < 3; i++)
-		phys_addr[i] = htons(read_eeprom(ioaddr, i));
-
-	dev = alloc_etherdev(sizeof (struct el3_private));
-	if (dev == NULL) {
-		release_region(ioaddr, EL3_IO_EXTENT);
-		return -ENOMEM;
-	}
-
-	netdev_boot_setup_check(dev);
-
-	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_MCA);
-	dev_set_drvdata(device, dev);
-	err = el3_common_init(dev);
-
-	if (err) {
-		dev_set_drvdata(device, NULL);
-		free_netdev(dev);
-		return -ENOMEM;
-	}
-
-	el3_devs[el3_cards++] = dev;
-	return 0;
-}
-
-#endif /* CONFIG_MCA */
-
-#ifdef CONFIG_EISA
-static int __init el3_eisa_probe (struct device *device)
-{
-	short i;
-	int ioaddr, irq, if_port;
-	__be16 phys_addr[3];
-	struct net_device *dev = NULL;
-	struct eisa_device *edev;
-	int err;
-
-	/* Yeepee, The driver framework is calling us ! */
-	edev = to_eisa_device (device);
-	ioaddr = edev->base_addr;
-
-	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c579-eisa"))
-		return -EBUSY;
-
-	/* Change the register set to the configuration window 0. */
-	outw(SelectWindow | 0, ioaddr + 0xC80 + EL3_CMD);
-
-	irq = inw(ioaddr + WN0_IRQ) >> 12;
-	if_port = inw(ioaddr + 6)>>14;
-	for (i = 0; i < 3; i++)
-		phys_addr[i] = htons(read_eeprom(ioaddr, i));
-
-	/* Restore the "Product ID" to the EEPROM read register. */
-	read_eeprom(ioaddr, 3);
-
-	dev = alloc_etherdev(sizeof (struct el3_private));
-	if (dev == NULL) {
-		release_region(ioaddr, EL3_IO_EXTENT);
-		return -ENOMEM;
-	}
-
-	netdev_boot_setup_check(dev);
-
-	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_EISA);
-	eisa_set_drvdata (edev, dev);
-	err = el3_common_init(dev);
-
-	if (err) {
-		eisa_set_drvdata (edev, NULL);
-		free_netdev(dev);
-		return err;
-	}
-
-	el3_devs[el3_cards++] = dev;
-	return 0;
-}
-#endif
-
-/* This remove works for all device types.
- *
- * The net dev must be stored in the driver data field */
-static int __devexit el3_device_remove (struct device *device)
-{
-	struct net_device *dev;
-
-	dev = dev_get_drvdata(device);
-
-	el3_common_remove (dev);
-	return 0;
-}
-
-/* Read a word from the EEPROM using the regular EEPROM access register.
-   Assume that we are in register window zero.
- */
-static ushort read_eeprom(int ioaddr, int index)
-{
-	outw(EEPROM_READ + index, ioaddr + 10);
-	/* Pause for at least 162 us. for the read to take place.
-	   Some chips seem to require much longer */
-	mdelay(2);
-	return inw(ioaddr + 12);
-}
-
-/* Read a word from the EEPROM when in the ISA ID probe state. */
-static ushort id_read_eeprom(int index)
-{
-	int bit, word = 0;
-
-	/* Issue read command, and pause for at least 162 us. for it to complete.
-	   Assume extra-fast 16Mhz bus. */
-	outb(EEPROM_READ + index, id_port);
-
-	/* Pause for at least 162 us. for the read to take place. */
-	/* Some chips seem to require much longer */
-	mdelay(4);
-
-	for (bit = 15; bit >= 0; bit--)
-		word = (word << 1) + (inb(id_port) & 0x01);
-
-	if (el3_debug > 3)
-		pr_debug("  3c509 EEPROM word %d %#4.4x.\n", index, word);
-
-	return word;
-}
-
-
-static int
-el3_open(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	int i;
-
-	outw(TxReset, ioaddr + EL3_CMD);
-	outw(RxReset, ioaddr + EL3_CMD);
-	outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
-
-	i = request_irq(dev->irq, el3_interrupt, 0, dev->name, dev);
-	if (i)
-		return i;
-
-	EL3WINDOW(0);
-	if (el3_debug > 3)
-		pr_debug("%s: Opening, IRQ %d	 status@%x %4.4x.\n", dev->name,
-			   dev->irq, ioaddr + EL3_STATUS, inw(ioaddr + EL3_STATUS));
-
-	el3_up(dev);
-
-	if (el3_debug > 3)
-		pr_debug("%s: Opened 3c509  IRQ %d  status %4.4x.\n",
-			   dev->name, dev->irq, inw(ioaddr + EL3_STATUS));
-
-	return 0;
-}
-
-static void
-el3_tx_timeout (struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-
-	/* Transmitter timeout, serious problems. */
-	pr_warning("%s: transmit timed out, Tx_status %2.2x status %4.4x Tx FIFO room %d.\n",
-		   dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
-		   inw(ioaddr + TX_FREE));
-	dev->stats.tx_errors++;
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	/* Issue TX_RESET and TX_START commands. */
-	outw(TxReset, ioaddr + EL3_CMD);
-	outw(TxEnable, ioaddr + EL3_CMD);
-	netif_wake_queue(dev);
-}
-
-
-static netdev_tx_t
-el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct el3_private *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-	unsigned long flags;
-
-	netif_stop_queue (dev);
-
-	dev->stats.tx_bytes += skb->len;
-
-	if (el3_debug > 4) {
-		pr_debug("%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
-			   dev->name, skb->len, inw(ioaddr + EL3_STATUS));
-	}
-#if 0
-#ifndef final_version
-	{	/* Error-checking code, delete someday. */
-		ushort status = inw(ioaddr + EL3_STATUS);
-		if (status & 0x0001 && 		/* IRQ line active, missed one. */
-		    inw(ioaddr + EL3_STATUS) & 1) { 			/* Make sure. */
-			pr_debug("%s: Missed interrupt, status then %04x now %04x"
-				   "  Tx %2.2x Rx %4.4x.\n", dev->name, status,
-				   inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS),
-				   inw(ioaddr + RX_STATUS));
-			/* Fake interrupt trigger by masking, acknowledge interrupts. */
-			outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
-			outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
-				 ioaddr + EL3_CMD);
-			outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
-		}
-	}
-#endif
-#endif
-	/*
-	 *	We lock the driver against other processors. Note
-	 *	we don't need to lock versus the IRQ as we suspended
-	 *	that. This means that we lose the ability to take
-	 *	an RX during a TX upload. That sucks a bit with SMP
-	 *	on an original 3c509 (2K buffer)
-	 *
-	 *	Using disable_irq stops us crapping on other
-	 *	time sensitive devices.
-	 */
-
-	spin_lock_irqsave(&lp->lock, flags);
-
-	/* Put out the doubleword header... */
-	outw(skb->len, ioaddr + TX_FIFO);
-	outw(0x00, ioaddr + TX_FIFO);
-	/* ... and the packet rounded to a doubleword. */
-	outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
-
-	if (inw(ioaddr + TX_FREE) > 1536)
-		netif_start_queue(dev);
-	else
-		/* Interrupt us when the FIFO has room for max-sized packet. */
-		outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
-
-	spin_unlock_irqrestore(&lp->lock, flags);
-
-	dev_kfree_skb (skb);
-
-	/* Clear the Tx status stack. */
-	{
-		short tx_status;
-		int i = 4;
-
-		while (--i > 0	&&	(tx_status = inb(ioaddr + TX_STATUS)) > 0) {
-			if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
-			if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
-			if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
-			outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
-		}
-	}
-	return NETDEV_TX_OK;
-}
-
-/* The EL3 interrupt handler. */
-static irqreturn_t
-el3_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct el3_private *lp;
-	int ioaddr, status;
-	int i = max_interrupt_work;
-
-	lp = netdev_priv(dev);
-	spin_lock(&lp->lock);
-
-	ioaddr = dev->base_addr;
-
-	if (el3_debug > 4) {
-		status = inw(ioaddr + EL3_STATUS);
-		pr_debug("%s: interrupt, status %4.4x.\n", dev->name, status);
-	}
-
-	while ((status = inw(ioaddr + EL3_STATUS)) &
-		   (IntLatch | RxComplete | StatsFull)) {
-
-		if (status & RxComplete)
-			el3_rx(dev);
-
-		if (status & TxAvailable) {
-			if (el3_debug > 5)
-				pr_debug("	TX room bit was handled.\n");
-			/* There's room in the FIFO for a full-sized packet. */
-			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
-			netif_wake_queue (dev);
-		}
-		if (status & (AdapterFailure | RxEarly | StatsFull | TxComplete)) {
-			/* Handle all uncommon interrupts. */
-			if (status & StatsFull)				/* Empty statistics. */
-				update_stats(dev);
-			if (status & RxEarly) {				/* Rx early is unused. */
-				el3_rx(dev);
-				outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
-			}
-			if (status & TxComplete) {			/* Really Tx error. */
-				short tx_status;
-				int i = 4;
-
-				while (--i>0 && (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
-					if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
-					if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
-					if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
-					outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
-				}
-			}
-			if (status & AdapterFailure) {
-				/* Adapter failure requires Rx reset and reinit. */
-				outw(RxReset, ioaddr + EL3_CMD);
-				/* Set the Rx filter to the current state. */
-				outw(SetRxFilter | RxStation | RxBroadcast
-					 | (dev->flags & IFF_ALLMULTI ? RxMulticast : 0)
-					 | (dev->flags & IFF_PROMISC ? RxProm : 0),
-					 ioaddr + EL3_CMD);
-				outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
-				outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
-			}
-		}
-
-		if (--i < 0) {
-			pr_err("%s: Infinite loop in interrupt, status %4.4x.\n",
-				   dev->name, status);
-			/* Clear all interrupts. */
-			outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
-			break;
-		}
-		/* Acknowledge the IRQ. */
-		outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); /* Ack IRQ */
-	}
-
-	if (el3_debug > 4) {
-		pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name,
-			   inw(ioaddr + EL3_STATUS));
-	}
-	spin_unlock(&lp->lock);
-	return IRQ_HANDLED;
-}
-
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Polling receive - used by netconsole and other diagnostic tools
- * to allow network i/o with interrupts disabled.
- */
-static void el3_poll_controller(struct net_device *dev)
-{
-	disable_irq(dev->irq);
-	el3_interrupt(dev->irq, dev);
-	enable_irq(dev->irq);
-}
-#endif
-
-static struct net_device_stats *
-el3_get_stats(struct net_device *dev)
-{
-	struct el3_private *lp = netdev_priv(dev);
-	unsigned long flags;
-
-	/*
-	 *	This is fast enough not to bother with disable IRQ
-	 *	stuff.
-	 */
-
-	spin_lock_irqsave(&lp->lock, flags);
-	update_stats(dev);
-	spin_unlock_irqrestore(&lp->lock, flags);
-	return &dev->stats;
-}
-
-/*  Update statistics.  We change to register window 6, so this should be run
-	single-threaded if the device is active. This is expected to be a rare
-	operation, and it's simpler for the rest of the driver to assume that
-	window 1 is always valid rather than use a special window-state variable.
-	*/
-static void update_stats(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-
-	if (el3_debug > 5)
-		pr_debug("   Updating the statistics.\n");
-	/* Turn off statistics updates while reading. */
-	outw(StatsDisable, ioaddr + EL3_CMD);
-	/* Switch to the stats window, and read everything. */
-	EL3WINDOW(6);
-	dev->stats.tx_carrier_errors 	+= inb(ioaddr + 0);
-	dev->stats.tx_heartbeat_errors	+= inb(ioaddr + 1);
-	/* Multiple collisions. */	   inb(ioaddr + 2);
-	dev->stats.collisions		+= inb(ioaddr + 3);
-	dev->stats.tx_window_errors	+= inb(ioaddr + 4);
-	dev->stats.rx_fifo_errors	+= inb(ioaddr + 5);
-	dev->stats.tx_packets		+= inb(ioaddr + 6);
-	/* Rx packets	*/		   inb(ioaddr + 7);
-	/* Tx deferrals */		   inb(ioaddr + 8);
-	inw(ioaddr + 10);	/* Total Rx and Tx octets. */
-	inw(ioaddr + 12);
-
-	/* Back to window 1, and turn statistics back on. */
-	EL3WINDOW(1);
-	outw(StatsEnable, ioaddr + EL3_CMD);
-}
-
-static int
-el3_rx(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	short rx_status;
-
-	if (el3_debug > 5)
-		pr_debug("   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
-			   inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
-	while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) {
-		if (rx_status & 0x4000) { /* Error, update stats. */
-			short error = rx_status & 0x3800;
-
-			outw(RxDiscard, ioaddr + EL3_CMD);
-			dev->stats.rx_errors++;
-			switch (error) {
-			case 0x0000:		dev->stats.rx_over_errors++; break;
-			case 0x0800:		dev->stats.rx_length_errors++; break;
-			case 0x1000:		dev->stats.rx_frame_errors++; break;
-			case 0x1800:		dev->stats.rx_length_errors++; break;
-			case 0x2000:		dev->stats.rx_frame_errors++; break;
-			case 0x2800:		dev->stats.rx_crc_errors++; break;
-			}
-		} else {
-			short pkt_len = rx_status & 0x7ff;
-			struct sk_buff *skb;
-
-			skb = dev_alloc_skb(pkt_len+5);
-			if (el3_debug > 4)
-				pr_debug("Receiving packet size %d status %4.4x.\n",
-					   pkt_len, rx_status);
-			if (skb != NULL) {
-				skb_reserve(skb, 2);     /* Align IP on 16 byte */
-
-				/* 'skb->data' points to the start of sk_buff data area. */
-				insl(ioaddr + RX_FIFO, skb_put(skb,pkt_len),
-					 (pkt_len + 3) >> 2);
-
-				outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
-				skb->protocol = eth_type_trans(skb,dev);
-				netif_rx(skb);
-				dev->stats.rx_bytes += pkt_len;
-				dev->stats.rx_packets++;
-				continue;
-			}
-			outw(RxDiscard, ioaddr + EL3_CMD);
-			dev->stats.rx_dropped++;
-			if (el3_debug)
-				pr_debug("%s: Couldn't allocate a sk_buff of size %d.\n",
-					   dev->name, pkt_len);
-		}
-		inw(ioaddr + EL3_STATUS); 				/* Delay. */
-		while (inw(ioaddr + EL3_STATUS) & 0x1000)
-			pr_debug("	Waiting for 3c509 to discard packet, status %x.\n",
-				   inw(ioaddr + EL3_STATUS) );
-	}
-
-	return 0;
-}
-
-/*
- *     Set or clear the multicast filter for this adaptor.
- */
-static void
-set_multicast_list(struct net_device *dev)
-{
-	unsigned long flags;
-	struct el3_private *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-	int mc_count = netdev_mc_count(dev);
-
-	if (el3_debug > 1) {
-		static int old;
-		if (old != mc_count) {
-			old = mc_count;
-			pr_debug("%s: Setting Rx mode to %d addresses.\n",
-				 dev->name, mc_count);
-		}
-	}
-	spin_lock_irqsave(&lp->lock, flags);
-	if (dev->flags&IFF_PROMISC) {
-		outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
-			 ioaddr + EL3_CMD);
-	}
-	else if (mc_count || (dev->flags&IFF_ALLMULTI)) {
-		outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast, ioaddr + EL3_CMD);
-	}
-	else
-		outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
-	spin_unlock_irqrestore(&lp->lock, flags);
-}
-
-static int
-el3_close(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	struct el3_private *lp = netdev_priv(dev);
-
-	if (el3_debug > 2)
-		pr_debug("%s: Shutting down ethercard.\n", dev->name);
-
-	el3_down(dev);
-
-	free_irq(dev->irq, dev);
-	/* Switching back to window 0 disables the IRQ. */
-	EL3WINDOW(0);
-	if (lp->type != EL3_EISA) {
-		/* But we explicitly zero the IRQ line select anyway. Don't do
-		 * it on EISA cards, it prevents the module from getting an
-		 * IRQ after unload+reload... */
-		outw(0x0f00, ioaddr + WN0_IRQ);
-	}
-
-	return 0;
-}
-
-static int
-el3_link_ok(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	u16 tmp;
-
-	EL3WINDOW(4);
-	tmp = inw(ioaddr + WN4_MEDIA);
-	EL3WINDOW(1);
-	return tmp & (1<<11);
-}
-
-static int
-el3_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	u16 tmp;
-	int ioaddr = dev->base_addr;
-
-	EL3WINDOW(0);
-	/* obtain current transceiver via WN4_MEDIA? */
-	tmp = inw(ioaddr + WN0_ADDR_CONF);
-	ecmd->transceiver = XCVR_INTERNAL;
-	switch (tmp >> 14) {
-	case 0:
-		ecmd->port = PORT_TP;
-		break;
-	case 1:
-		ecmd->port = PORT_AUI;
-		ecmd->transceiver = XCVR_EXTERNAL;
-		break;
-	case 3:
-		ecmd->port = PORT_BNC;
-	default:
-		break;
-	}
-
-	ecmd->duplex = DUPLEX_HALF;
-	ecmd->supported = 0;
-	tmp = inw(ioaddr + WN0_CONF_CTRL);
-	if (tmp & (1<<13))
-		ecmd->supported |= SUPPORTED_AUI;
-	if (tmp & (1<<12))
-		ecmd->supported |= SUPPORTED_BNC;
-	if (tmp & (1<<9)) {
-		ecmd->supported |= SUPPORTED_TP | SUPPORTED_10baseT_Half |
-				SUPPORTED_10baseT_Full;	/* hmm... */
-		EL3WINDOW(4);
-		tmp = inw(ioaddr + WN4_NETDIAG);
-		if (tmp & FD_ENABLE)
-			ecmd->duplex = DUPLEX_FULL;
-	}
-
-	ethtool_cmd_speed_set(ecmd, SPEED_10);
-	EL3WINDOW(1);
-	return 0;
-}
-
-static int
-el3_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	u16 tmp;
-	int ioaddr = dev->base_addr;
-
-	if (ecmd->speed != SPEED_10)
-		return -EINVAL;
-	if ((ecmd->duplex != DUPLEX_HALF) && (ecmd->duplex != DUPLEX_FULL))
-		return -EINVAL;
-	if ((ecmd->transceiver != XCVR_INTERNAL) && (ecmd->transceiver != XCVR_EXTERNAL))
-		return -EINVAL;
-
-	/* change XCVR type */
-	EL3WINDOW(0);
-	tmp = inw(ioaddr + WN0_ADDR_CONF);
-	switch (ecmd->port) {
-	case PORT_TP:
-		tmp &= ~(3<<14);
-		dev->if_port = 0;
-		break;
-	case PORT_AUI:
-		tmp |= (1<<14);
-		dev->if_port = 1;
-		break;
-	case PORT_BNC:
-		tmp |= (3<<14);
-		dev->if_port = 3;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	outw(tmp, ioaddr + WN0_ADDR_CONF);
-	if (dev->if_port == 3) {
-		/* fire up the DC-DC convertor if BNC gets enabled */
-		tmp = inw(ioaddr + WN0_ADDR_CONF);
-		if (tmp & (3 << 14)) {
-			outw(StartCoax, ioaddr + EL3_CMD);
-			udelay(800);
-		} else
-			return -EIO;
-	}
-
-	EL3WINDOW(4);
-	tmp = inw(ioaddr + WN4_NETDIAG);
-	if (ecmd->duplex == DUPLEX_FULL)
-		tmp |= FD_ENABLE;
-	else
-		tmp &= ~FD_ENABLE;
-	outw(tmp, ioaddr + WN4_NETDIAG);
-	EL3WINDOW(1);
-
-	return 0;
-}
-
-static void el3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-}
-
-static int el3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	struct el3_private *lp = netdev_priv(dev);
-	int ret;
-
-	spin_lock_irq(&lp->lock);
-	ret = el3_netdev_get_ecmd(dev, ecmd);
-	spin_unlock_irq(&lp->lock);
-	return ret;
-}
-
-static int el3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	struct el3_private *lp = netdev_priv(dev);
-	int ret;
-
-	spin_lock_irq(&lp->lock);
-	ret = el3_netdev_set_ecmd(dev, ecmd);
-	spin_unlock_irq(&lp->lock);
-	return ret;
-}
-
-static u32 el3_get_link(struct net_device *dev)
-{
-	struct el3_private *lp = netdev_priv(dev);
-	u32 ret;
-
-	spin_lock_irq(&lp->lock);
-	ret = el3_link_ok(dev);
-	spin_unlock_irq(&lp->lock);
-	return ret;
-}
-
-static u32 el3_get_msglevel(struct net_device *dev)
-{
-	return el3_debug;
-}
-
-static void el3_set_msglevel(struct net_device *dev, u32 v)
-{
-	el3_debug = v;
-}
-
-static const struct ethtool_ops ethtool_ops = {
-	.get_drvinfo = el3_get_drvinfo,
-	.get_settings = el3_get_settings,
-	.set_settings = el3_set_settings,
-	.get_link = el3_get_link,
-	.get_msglevel = el3_get_msglevel,
-	.set_msglevel = el3_set_msglevel,
-};
-
-static void
-el3_down(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-
-	netif_stop_queue(dev);
-
-	/* Turn off statistics ASAP.  We update lp->stats below. */
-	outw(StatsDisable, ioaddr + EL3_CMD);
-
-	/* Disable the receiver and transmitter. */
-	outw(RxDisable, ioaddr + EL3_CMD);
-	outw(TxDisable, ioaddr + EL3_CMD);
-
-	if (dev->if_port == 3)
-		/* Turn off thinnet power.  Green! */
-		outw(StopCoax, ioaddr + EL3_CMD);
-	else if (dev->if_port == 0) {
-		/* Disable link beat and jabber, if_port may change here next open(). */
-		EL3WINDOW(4);
-		outw(inw(ioaddr + WN4_MEDIA) & ~MEDIA_TP, ioaddr + WN4_MEDIA);
-	}
-
-	outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
-
-	update_stats(dev);
-}
-
-static void
-el3_up(struct net_device *dev)
-{
-	int i, sw_info, net_diag;
-	int ioaddr = dev->base_addr;
-
-	/* Activating the board required and does no harm otherwise */
-	outw(0x0001, ioaddr + 4);
-
-	/* Set the IRQ line. */
-	outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
-
-	/* Set the station address in window 2 each time opened. */
-	EL3WINDOW(2);
-
-	for (i = 0; i < 6; i++)
-		outb(dev->dev_addr[i], ioaddr + i);
-
-	if ((dev->if_port & 0x03) == 3) /* BNC interface */
-		/* Start the thinnet transceiver. We should really wait 50ms...*/
-		outw(StartCoax, ioaddr + EL3_CMD);
-	else if ((dev->if_port & 0x03) == 0) { /* 10baseT interface */
-		/* Combine secondary sw_info word (the adapter level) and primary
-			sw_info word (duplex setting plus other useless bits) */
-		EL3WINDOW(0);
-		sw_info = (read_eeprom(ioaddr, 0x14) & 0x400f) |
-			(read_eeprom(ioaddr, 0x0d) & 0xBff0);
-
-		EL3WINDOW(4);
-		net_diag = inw(ioaddr + WN4_NETDIAG);
-		net_diag = (net_diag | FD_ENABLE); /* temporarily assume full-duplex will be set */
-		pr_info("%s: ", dev->name);
-		switch (dev->if_port & 0x0c) {
-			case 12:
-				/* force full-duplex mode if 3c5x9b */
-				if (sw_info & 0x000f) {
-					pr_cont("Forcing 3c5x9b full-duplex mode");
-					break;
-				}
-			case 8:
-				/* set full-duplex mode based on eeprom config setting */
-				if ((sw_info & 0x000f) && (sw_info & 0x8000)) {
-					pr_cont("Setting 3c5x9b full-duplex mode (from EEPROM configuration bit)");
-					break;
-				}
-			default:
-				/* xcvr=(0 || 4) OR user has an old 3c5x9 non "B" model */
-				pr_cont("Setting 3c5x9/3c5x9B half-duplex mode");
-				net_diag = (net_diag & ~FD_ENABLE); /* disable full duplex */
-		}
-
-		outw(net_diag, ioaddr + WN4_NETDIAG);
-		pr_cont(" if_port: %d, sw_info: %4.4x\n", dev->if_port, sw_info);
-		if (el3_debug > 3)
-			pr_debug("%s: 3c5x9 net diag word is now: %4.4x.\n", dev->name, net_diag);
-		/* Enable link beat and jabber check. */
-		outw(inw(ioaddr + WN4_MEDIA) | MEDIA_TP, ioaddr + WN4_MEDIA);
-	}
-
-	/* Switch to the stats window, and clear all stats by reading. */
-	outw(StatsDisable, ioaddr + EL3_CMD);
-	EL3WINDOW(6);
-	for (i = 0; i < 9; i++)
-		inb(ioaddr + i);
-	inw(ioaddr + 10);
-	inw(ioaddr + 12);
-
-	/* Switch to register set 1 for normal use. */
-	EL3WINDOW(1);
-
-	/* Accept b-case and phys addr only. */
-	outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
-	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
-
-	outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
-	outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
-	/* Allow status bits to be seen. */
-	outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
-	/* Ack all pending events, and set active indicator mask. */
-	outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
-		 ioaddr + EL3_CMD);
-	outw(SetIntrEnb | IntLatch|TxAvailable|TxComplete|RxComplete|StatsFull,
-		 ioaddr + EL3_CMD);
-
-	netif_start_queue(dev);
-}
-
-/* Power Management support functions */
-#ifdef CONFIG_PM
-
-static int
-el3_suspend(struct device *pdev, pm_message_t state)
-{
-	unsigned long flags;
-	struct net_device *dev;
-	struct el3_private *lp;
-	int ioaddr;
-
-	dev = dev_get_drvdata(pdev);
-	lp = netdev_priv(dev);
-	ioaddr = dev->base_addr;
-
-	spin_lock_irqsave(&lp->lock, flags);
-
-	if (netif_running(dev))
-		netif_device_detach(dev);
-
-	el3_down(dev);
-	outw(PowerDown, ioaddr + EL3_CMD);
-
-	spin_unlock_irqrestore(&lp->lock, flags);
-	return 0;
-}
-
-static int
-el3_resume(struct device *pdev)
-{
-	unsigned long flags;
-	struct net_device *dev;
-	struct el3_private *lp;
-	int ioaddr;
-
-	dev = dev_get_drvdata(pdev);
-	lp = netdev_priv(dev);
-	ioaddr = dev->base_addr;
-
-	spin_lock_irqsave(&lp->lock, flags);
-
-	outw(PowerUp, ioaddr + EL3_CMD);
-	EL3WINDOW(0);
-	el3_up(dev);
-
-	if (netif_running(dev))
-		netif_device_attach(dev);
-
-	spin_unlock_irqrestore(&lp->lock, flags);
-	return 0;
-}
-
-#endif /* CONFIG_PM */
-
-module_param(debug,int, 0);
-module_param_array(irq, int, NULL, 0);
-module_param(max_interrupt_work, int, 0);
-MODULE_PARM_DESC(debug, "debug level (0-6)");
-MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
-MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
-#ifdef CONFIG_PNP
-module_param(nopnp, int, 0);
-MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
-#endif	/* CONFIG_PNP */
-MODULE_DESCRIPTION("3Com Etherlink III (3c509, 3c509B, 3c529, 3c579) ethernet driver");
-MODULE_LICENSE("GPL");
-
-static int __init el3_init_module(void)
-{
-	int ret = 0;
-
-	if (debug >= 0)
-		el3_debug = debug;
-
-#ifdef CONFIG_PNP
-	if (!nopnp) {
-		ret = pnp_register_driver(&el3_pnp_driver);
-		if (!ret)
-			pnp_registered = 1;
-	}
-#endif
-	/* Select an open I/O location at 0x1*0 to do ISA contention select. */
-	/* Start with 0x110 to avoid some sound cards.*/
-	for (id_port = 0x110 ; id_port < 0x200; id_port += 0x10) {
-		if (!request_region(id_port, 1, "3c509-control"))
-			continue;
-		outb(0x00, id_port);
-		outb(0xff, id_port);
-		if (inb(id_port) & 0x01)
-			break;
-		else
-			release_region(id_port, 1);
-	}
-	if (id_port >= 0x200) {
-		id_port = 0;
-		pr_err("No I/O port available for 3c509 activation.\n");
-	} else {
-		ret = isa_register_driver(&el3_isa_driver, EL3_MAX_CARDS);
-		if (!ret)
-			isa_registered = 1;
-	}
-#ifdef CONFIG_EISA
-	ret = eisa_driver_register(&el3_eisa_driver);
-	if (!ret)
-		eisa_registered = 1;
-#endif
-#ifdef CONFIG_MCA
-	ret = mca_register_driver(&el3_mca_driver);
-	if (!ret)
-		mca_registered = 1;
-#endif
-
-#ifdef CONFIG_PNP
-	if (pnp_registered)
-		ret = 0;
-#endif
-	if (isa_registered)
-		ret = 0;
-#ifdef CONFIG_EISA
-	if (eisa_registered)
-		ret = 0;
-#endif
-#ifdef CONFIG_MCA
-	if (mca_registered)
-		ret = 0;
-#endif
-	return ret;
-}
-
-static void __exit el3_cleanup_module(void)
-{
-#ifdef CONFIG_PNP
-	if (pnp_registered)
-		pnp_unregister_driver(&el3_pnp_driver);
-#endif
-	if (isa_registered)
-		isa_unregister_driver(&el3_isa_driver);
-	if (id_port)
-		release_region(id_port, 1);
-#ifdef CONFIG_EISA
-	if (eisa_registered)
-		eisa_driver_unregister(&el3_eisa_driver);
-#endif
-#ifdef CONFIG_MCA
-	if (mca_registered)
-		mca_unregister_driver(&el3_mca_driver);
-#endif
-}
-
-module_init (el3_init_module);
-module_exit (el3_cleanup_module);
diff -druN linux-libre-3.1-gnu/drivers/net/3c515.c linux-libre-3.2-gnu/drivers/net/3c515.c
--- linux-libre-3.1-gnu/drivers/net/3c515.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/3c515.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1584 +0,0 @@
-/*
-	Written 1997-1998 by Donald Becker.
-
-	This software may be used and distributed according to the terms
-	of the GNU General Public License, incorporated herein by reference.
-
-	This driver is for the 3Com ISA EtherLink XL "Corkscrew" 3c515 ethercard.
-
-	The author may be reached as becker@scyld.com, or C/O
-	Scyld Computing Corporation
-	410 Severn Ave., Suite 210
-	Annapolis MD 21403
-
-
-	2000/2/2- Added support for kernel-level ISAPnP
-		by Stephen Frost <sfrost@snowman.net> and Alessandro Zummo
-	Cleaned up for 2.3.x/softnet by Jeff Garzik and Alan Cox.
-
-	2001/11/17 - Added ethtool support (jgarzik)
-
-	2002/10/28 - Locking updates for 2.5 (alan@lxorguk.ukuu.org.uk)
-
-*/
-
-#define DRV_NAME		"3c515"
-#define DRV_VERSION		"0.99t-ac"
-#define DRV_RELDATE		"28-Oct-2002"
-
-static char *version =
-DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " becker@scyld.com and others\n";
-
-#define CORKSCREW 1
-
-/* "Knobs" that adjust features and parameters. */
-/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
-   Setting to > 1512 effectively disables this feature. */
-static int rx_copybreak = 200;
-
-/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
-static const int mtu = 1500;
-
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 20;
-
-/* Enable the automatic media selection code -- usually set. */
-#define AUTOMEDIA 1
-
-/* Allow the use of fragment bus master transfers instead of only
-   programmed-I/O for Vortex cards.  Full-bus-master transfers are always
-   enabled by default on Boomerang cards.  If VORTEX_BUS_MASTER is defined,
-   the feature may be turned on using 'options'. */
-#define VORTEX_BUS_MASTER
-
-/* A few values that may be tweaked. */
-/* Keep the ring sizes a power of two for efficiency. */
-#define TX_RING_SIZE	16
-#define RX_RING_SIZE	16
-#define PKT_BUF_SZ		1536	/* Size of each temporary Rx buffer. */
-
-#include <linux/module.h>
-#include <linux/isapnp.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/in.h>
-#include <linux/ioport.h>
-#include <linux/skbuff.h>
-#include <linux/etherdevice.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/ethtool.h>
-#include <linux/bitops.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#define NEW_MULTICAST
-#include <linux/delay.h>
-
-#define MAX_UNITS 8
-
-MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
-MODULE_DESCRIPTION("3Com 3c515 Corkscrew driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-
-/* "Knobs" for adjusting internal parameters. */
-/* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */
-#define DRIVER_DEBUG 1
-/* Some values here only for performance evaluation and path-coverage
-   debugging. */
-static int rx_nocopy, rx_copy, queued_packet;
-
-/* Number of times to check to see if the Tx FIFO has space, used in some
-   limited cases. */
-#define WAIT_TX_AVAIL 200
-
-/* Operational parameter that usually are not changed. */
-#define TX_TIMEOUT  ((4*HZ)/10)	/* Time in jiffies before concluding Tx hung */
-
-/* The size here is somewhat misleading: the Corkscrew also uses the ISA
-   aliased registers at <base>+0x400.
-   */
-#define CORKSCREW_TOTAL_SIZE 0x20
-
-#ifdef DRIVER_DEBUG
-static int corkscrew_debug = DRIVER_DEBUG;
-#else
-static int corkscrew_debug = 1;
-#endif
-
-#define CORKSCREW_ID 10
-
-/*
-				Theory of Operation
-
-I. Board Compatibility
-
-This device driver is designed for the 3Com 3c515 ISA Fast EtherLink XL,
-3Com's ISA bus adapter for Fast Ethernet.  Due to the unique I/O port layout,
-it's not practical to integrate this driver with the other EtherLink drivers.
-
-II. Board-specific settings
-
-The Corkscrew has an EEPROM for configuration, but no special settings are
-needed for Linux.
-
-III. Driver operation
-
-The 3c515 series use an interface that's very similar to the 3c900 "Boomerang"
-PCI cards, with the bus master interface extensively modified to work with
-the ISA bus.
-
-The card is capable of full-bus-master transfers with separate
-lists of transmit and receive descriptors, similar to the AMD LANCE/PCnet,
-DEC Tulip and Intel Speedo3.
-
-This driver uses a "RX_COPYBREAK" scheme rather than a fixed intermediate
-receive buffer.  This scheme allocates full-sized skbuffs as receive
-buffers.  The value RX_COPYBREAK is used as the copying breakpoint: it is
-chosen to trade-off the memory wasted by passing the full-sized skbuff to
-the queue layer for all frames vs. the copying cost of copying a frame to a
-correctly-sized skbuff.
-
-
-IIIC. Synchronization
-The driver runs as two independent, single-threaded flows of control.  One
-is the send-packet routine, which enforces single-threaded use by the netif
-layer.  The other thread is the interrupt handler, which is single
-threaded by the hardware and other software.
-
-IV. Notes
-
-Thanks to Terry Murphy of 3Com for providing documentation and a development
-board.
-
-The names "Vortex", "Boomerang" and "Corkscrew" are the internal 3Com
-project names.  I use these names to eliminate confusion -- 3Com product
-numbers and names are very similar and often confused.
-
-The new chips support both ethernet (1.5K) and FDDI (4.5K) frame sizes!
-This driver only supports ethernet frames because of the recent MTU limit
-of 1.5K, but the changes to support 4.5K are minimal.
-*/
-
-/* Operational definitions.
-   These are not used by other compilation units and thus are not
-   exported in a ".h" file.
-
-   First the windows.  There are eight register windows, with the command
-   and status registers available in each.
-   */
-#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
-#define EL3_CMD 0x0e
-#define EL3_STATUS 0x0e
-
-/* The top five bits written to EL3_CMD are a command, the lower
-   11 bits are the parameter, if applicable.
-   Note that 11 parameters bits was fine for ethernet, but the new chips
-   can handle FDDI length frames (~4500 octets) and now parameters count
-   32-bit 'Dwords' rather than octets. */
-
-enum corkscrew_cmd {
-	TotalReset = 0 << 11, SelectWindow = 1 << 11, StartCoax = 2 << 11,
-	RxDisable = 3 << 11, RxEnable = 4 << 11, RxReset = 5 << 11,
-	UpStall = 6 << 11, UpUnstall = (6 << 11) + 1, DownStall = (6 << 11) + 2,
-	DownUnstall = (6 << 11) + 3, RxDiscard = 8 << 11, TxEnable = 9 << 11,
-	TxDisable = 10 << 11, TxReset = 11 << 11, FakeIntr = 12 << 11,
-	AckIntr = 13 << 11, SetIntrEnb = 14 << 11, SetStatusEnb = 15 << 11,
-	SetRxFilter = 16 << 11, SetRxThreshold = 17 << 11,
-	SetTxThreshold = 18 << 11, SetTxStart = 19 << 11, StartDMAUp = 20 << 11,
-	StartDMADown = (20 << 11) + 1, StatsEnable = 21 << 11,
-	StatsDisable = 22 << 11, StopCoax = 23 << 11,
-};
-
-/* The SetRxFilter command accepts the following classes: */
-enum RxFilter {
-	RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
-};
-
-/* Bits in the general status register. */
-enum corkscrew_status {
-	IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
-	TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
-	IntReq = 0x0040, StatsFull = 0x0080,
-	DMADone = 1 << 8, DownComplete = 1 << 9, UpComplete = 1 << 10,
-	DMAInProgress = 1 << 11,	/* DMA controller is still busy. */
-	CmdInProgress = 1 << 12,	/* EL3_CMD is still busy. */
-};
-
-/* Register window 1 offsets, the window used in normal operation.
-   On the Corkscrew this window is always mapped at offsets 0x10-0x1f. */
-enum Window1 {
-	TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14,
-	RxStatus = 0x18, Timer = 0x1A, TxStatus = 0x1B,
-	TxFree = 0x1C,		/* Remaining free bytes in Tx buffer. */
-};
-enum Window0 {
-	Wn0IRQ = 0x08,
-#if defined(CORKSCREW)
-	Wn0EepromCmd = 0x200A,	/* Corkscrew EEPROM command register. */
-	Wn0EepromData = 0x200C,	/* Corkscrew EEPROM results register. */
-#else
-	Wn0EepromCmd = 10,	/* Window 0: EEPROM command register. */
-	Wn0EepromData = 12,	/* Window 0: EEPROM results register. */
-#endif
-};
-enum Win0_EEPROM_bits {
-	EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
-	EEPROM_EWENB = 0x30,	/* Enable erasing/writing for 10 msec. */
-	EEPROM_EWDIS = 0x00,	/* Disable EWENB before 10 msec timeout. */
-};
-
-/* EEPROM locations. */
-enum eeprom_offset {
-	PhysAddr01 = 0, PhysAddr23 = 1, PhysAddr45 = 2, ModelID = 3,
-	EtherLink3ID = 7,
-};
-
-enum Window3 {			/* Window 3: MAC/config bits. */
-	Wn3_Config = 0, Wn3_MAC_Ctrl = 6, Wn3_Options = 8,
-};
-enum wn3_config {
-	Ram_size = 7,
-	Ram_width = 8,
-	Ram_speed = 0x30,
-	Rom_size = 0xc0,
-	Ram_split_shift = 16,
-	Ram_split = 3 << Ram_split_shift,
-	Xcvr_shift = 20,
-	Xcvr = 7 << Xcvr_shift,
-	Autoselect = 0x1000000,
-};
-
-enum Window4 {
-	Wn4_NetDiag = 6, Wn4_Media = 10,	/* Window 4: Xcvr/media bits. */
-};
-enum Win4_Media_bits {
-	Media_SQE = 0x0008,	/* Enable SQE error counting for AUI. */
-	Media_10TP = 0x00C0,	/* Enable link beat and jabber for 10baseT. */
-	Media_Lnk = 0x0080,	/* Enable just link beat for 100TX/100FX. */
-	Media_LnkBeat = 0x0800,
-};
-enum Window7 {			/* Window 7: Bus Master control. */
-	Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
-};
-
-/* Boomerang-style bus master control registers.  Note ISA aliases! */
-enum MasterCtrl {
-	PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen =
-	    0x40c,
-	TxFreeThreshold = 0x40f, UpPktStatus = 0x410, UpListPtr = 0x418,
-};
-
-/* The Rx and Tx descriptor lists.
-   Caution Alpha hackers: these types are 32 bits!  Note also the 8 byte
-   alignment contraint on tx_ring[] and rx_ring[]. */
-struct boom_rx_desc {
-	u32 next;
-	s32 status;
-	u32 addr;
-	s32 length;
-};
-
-/* Values for the Rx status entry. */
-enum rx_desc_status {
-	RxDComplete = 0x00008000, RxDError = 0x4000,
-	/* See boomerang_rx() for actual error bits */
-};
-
-struct boom_tx_desc {
-	u32 next;
-	s32 status;
-	u32 addr;
-	s32 length;
-};
-
-struct corkscrew_private {
-	const char *product_name;
-	struct list_head list;
-	struct net_device *our_dev;
-	/* The Rx and Tx rings are here to keep them quad-word-aligned. */
-	struct boom_rx_desc rx_ring[RX_RING_SIZE];
-	struct boom_tx_desc tx_ring[TX_RING_SIZE];
-	/* The addresses of transmit- and receive-in-place skbuffs. */
-	struct sk_buff *rx_skbuff[RX_RING_SIZE];
-	struct sk_buff *tx_skbuff[TX_RING_SIZE];
-	unsigned int cur_rx, cur_tx;	/* The next free ring entry */
-	unsigned int dirty_rx, dirty_tx;/* The ring entries to be free()ed. */
-	struct sk_buff *tx_skb;	/* Packet being eaten by bus master ctrl.  */
-	struct timer_list timer;	/* Media selection timer. */
-	int capabilities	;	/* Adapter capabilities word. */
-	int options;			/* User-settable misc. driver options. */
-	int last_rx_packets;		/* For media autoselection. */
-	unsigned int available_media:8,	/* From Wn3_Options */
-		media_override:3,	/* Passed-in media type. */
-		default_media:3,	/* Read from the EEPROM. */
-		full_duplex:1, autoselect:1, bus_master:1,	/* Vortex can only do a fragment bus-m. */
-		full_bus_master_tx:1, full_bus_master_rx:1,	/* Boomerang  */
-		tx_full:1;
-	spinlock_t lock;
-	struct device *dev;
-};
-
-/* The action to take with a media selection timer tick.
-   Note that we deviate from the 3Com order by checking 10base2 before AUI.
- */
-enum xcvr_types {
-	XCVR_10baseT = 0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,
-	XCVR_100baseFx, XCVR_MII = 6, XCVR_Default = 8,
-};
-
-static struct media_table {
-	char *name;
-	unsigned int media_bits:16,	/* Bits to set in Wn4_Media register. */
-		mask:8,			/* The transceiver-present bit in Wn3_Config. */
-		next:8;			/* The media type to try next. */
-	short wait;			/* Time before we check media status. */
-} media_tbl[] = {
-	{ "10baseT", Media_10TP, 0x08, XCVR_10base2, (14 * HZ) / 10 },
-	{ "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1 * HZ) / 10},
-	{ "undefined", 0, 0x80, XCVR_10baseT, 10000},
-	{ "10base2", 0, 0x10, XCVR_AUI, (1 * HZ) / 10},
-	{ "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14 * HZ) / 10},
-	{ "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14 * HZ) / 10},
-	{ "MII", 0, 0x40, XCVR_10baseT, 3 * HZ},
-	{ "undefined", 0, 0x01, XCVR_10baseT, 10000},
-	{ "Default", 0, 0xFF, XCVR_10baseT, 10000},
-};
-
-#ifdef __ISAPNP__
-static struct isapnp_device_id corkscrew_isapnp_adapters[] = {
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5051),
-		(long) "3Com Fast EtherLink ISA" },
-	{ }	/* terminate list */
-};
-
-MODULE_DEVICE_TABLE(isapnp, corkscrew_isapnp_adapters);
-
-static int nopnp;
-#endif /* __ISAPNP__ */
-
-static struct net_device *corkscrew_scan(int unit);
-static int corkscrew_setup(struct net_device *dev, int ioaddr,
-			    struct pnp_dev *idev, int card_number);
-static int corkscrew_open(struct net_device *dev);
-static void corkscrew_timer(unsigned long arg);
-static netdev_tx_t corkscrew_start_xmit(struct sk_buff *skb,
-					struct net_device *dev);
-static int corkscrew_rx(struct net_device *dev);
-static void corkscrew_timeout(struct net_device *dev);
-static int boomerang_rx(struct net_device *dev);
-static irqreturn_t corkscrew_interrupt(int irq, void *dev_id);
-static int corkscrew_close(struct net_device *dev);
-static void update_stats(int addr, struct net_device *dev);
-static struct net_device_stats *corkscrew_get_stats(struct net_device *dev);
-static void set_rx_mode(struct net_device *dev);
-static const struct ethtool_ops netdev_ethtool_ops;
-
-
-/*
-   Unfortunately maximizing the shared code between the integrated and
-   module version of the driver results in a complicated set of initialization
-   procedures.
-   init_module() -- modules /  tc59x_init()  -- built-in
-		The wrappers for corkscrew_scan()
-   corkscrew_scan()  		 The common routine that scans for PCI and EISA cards
-   corkscrew_found_device() Allocate a device structure when we find a card.
-					Different versions exist for modules and built-in.
-   corkscrew_probe1()		Fill in the device structure -- this is separated
-					so that the modules code can put it in dev->init.
-*/
-/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
-/* Note: this is the only limit on the number of cards supported!! */
-static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1, };
-
-#ifdef MODULE
-static int debug = -1;
-
-module_param(debug, int, 0);
-module_param_array(options, int, NULL, 0);
-module_param(rx_copybreak, int, 0);
-module_param(max_interrupt_work, int, 0);
-MODULE_PARM_DESC(debug, "3c515 debug level (0-6)");
-MODULE_PARM_DESC(options, "3c515: Bits 0-2: media type, bit 3: full duplex, bit 4: bus mastering");
-MODULE_PARM_DESC(rx_copybreak, "3c515 copy breakpoint for copy-only-tiny-frames");
-MODULE_PARM_DESC(max_interrupt_work, "3c515 maximum events handled per interrupt");
-
-/* A list of all installed Vortex devices, for removing the driver module. */
-/* we will need locking (and refcounting) if we ever use it for more */
-static LIST_HEAD(root_corkscrew_dev);
-
-int init_module(void)
-{
-	int found = 0;
-	if (debug >= 0)
-		corkscrew_debug = debug;
-	if (corkscrew_debug)
-		pr_debug("%s", version);
-	while (corkscrew_scan(-1))
-		found++;
-	return found ? 0 : -ENODEV;
-}
-
-#else
-struct net_device *tc515_probe(int unit)
-{
-	struct net_device *dev = corkscrew_scan(unit);
-	static int printed;
-
-	if (!dev)
-		return ERR_PTR(-ENODEV);
-
-	if (corkscrew_debug > 0 && !printed) {
-		printed = 1;
-		pr_debug("%s", version);
-	}
-
-	return dev;
-}
-#endif				/* not MODULE */
-
-static int check_device(unsigned ioaddr)
-{
-	int timer;
-
-	if (!request_region(ioaddr, CORKSCREW_TOTAL_SIZE, "3c515"))
-		return 0;
-	/* Check the resource configuration for a matching ioaddr. */
-	if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0)) {
-		release_region(ioaddr, CORKSCREW_TOTAL_SIZE);
-		return 0;
-	}
-	/* Verify by reading the device ID from the EEPROM. */
-	outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd);
-	/* Pause for at least 162 us. for the read to take place. */
-	for (timer = 4; timer >= 0; timer--) {
-		udelay(162);
-		if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
-			break;
-	}
-	if (inw(ioaddr + Wn0EepromData) != 0x6d50) {
-		release_region(ioaddr, CORKSCREW_TOTAL_SIZE);
-		return 0;
-	}
-	return 1;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-	struct corkscrew_private *vp = netdev_priv(dev);
-	list_del_init(&vp->list);
-	if (dev->dma)
-		free_dma(dev->dma);
-	outw(TotalReset, dev->base_addr + EL3_CMD);
-	release_region(dev->base_addr, CORKSCREW_TOTAL_SIZE);
-	if (vp->dev)
-		pnp_device_detach(to_pnp_dev(vp->dev));
-}
-
-static struct net_device *corkscrew_scan(int unit)
-{
-	struct net_device *dev;
-	static int cards_found = 0;
-	static int ioaddr;
-	int err;
-#ifdef __ISAPNP__
-	short i;
-	static int pnp_cards;
-#endif
-
-	dev = alloc_etherdev(sizeof(struct corkscrew_private));
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	if (unit >= 0) {
-		sprintf(dev->name, "eth%d", unit);
-		netdev_boot_setup_check(dev);
-	}
-
-#ifdef __ISAPNP__
-	if(nopnp == 1)
-		goto no_pnp;
-	for(i=0; corkscrew_isapnp_adapters[i].vendor != 0; i++) {
-		struct pnp_dev *idev = NULL;
-		int irq;
-		while((idev = pnp_find_dev(NULL,
-					   corkscrew_isapnp_adapters[i].vendor,
-					   corkscrew_isapnp_adapters[i].function,
-					   idev))) {
-
-			if (pnp_device_attach(idev) < 0)
-				continue;
-			if (pnp_activate_dev(idev) < 0) {
-				pr_warning("pnp activate failed (out of resources?)\n");
-				pnp_device_detach(idev);
-				continue;
-			}
-			if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) {
-				pnp_device_detach(idev);
-				continue;
-			}
-			ioaddr = pnp_port_start(idev, 0);
-			irq = pnp_irq(idev, 0);
-			if (!check_device(ioaddr)) {
-				pnp_device_detach(idev);
-				continue;
-			}
-			if(corkscrew_debug)
-				pr_debug("ISAPNP reports %s at i/o 0x%x, irq %d\n",
-					(char*) corkscrew_isapnp_adapters[i].driver_data, ioaddr, irq);
-			pr_info("3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
-		     		inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
-			/* irq = inw(ioaddr + 0x2002) & 15; */ /* Use the irq from isapnp */
-			SET_NETDEV_DEV(dev, &idev->dev);
-			pnp_cards++;
-			err = corkscrew_setup(dev, ioaddr, idev, cards_found++);
-			if (!err)
-				return dev;
-			cleanup_card(dev);
-		}
-	}
-no_pnp:
-#endif /* __ISAPNP__ */
-
-	/* Check all locations on the ISA bus -- evil! */
-	for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20) {
-		if (!check_device(ioaddr))
-			continue;
-
-		pr_info("3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
-		     inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
-		err = corkscrew_setup(dev, ioaddr, NULL, cards_found++);
-		if (!err)
-			return dev;
-		cleanup_card(dev);
-	}
-	free_netdev(dev);
-	return NULL;
-}
-
-
-static const struct net_device_ops netdev_ops = {
-	.ndo_open		= corkscrew_open,
-	.ndo_stop		= corkscrew_close,
-	.ndo_start_xmit		= corkscrew_start_xmit,
-	.ndo_tx_timeout		= corkscrew_timeout,
-	.ndo_get_stats		= corkscrew_get_stats,
-	.ndo_set_multicast_list = set_rx_mode,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-
-static int corkscrew_setup(struct net_device *dev, int ioaddr,
-			    struct pnp_dev *idev, int card_number)
-{
-	struct corkscrew_private *vp = netdev_priv(dev);
-	unsigned int eeprom[0x40], checksum = 0;	/* EEPROM contents */
-	int i;
-	int irq;
-
-#ifdef __ISAPNP__
-	if (idev) {
-		irq = pnp_irq(idev, 0);
-		vp->dev = &idev->dev;
-	} else {
-		irq = inw(ioaddr + 0x2002) & 15;
-	}
-#else
-	irq = inw(ioaddr + 0x2002) & 15;
-#endif
-
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-	dev->dma = inw(ioaddr + 0x2000) & 7;
-	vp->product_name = "3c515";
-	vp->options = dev->mem_start;
-	vp->our_dev = dev;
-
-	if (!vp->options) {
-		 if (card_number >= MAX_UNITS)
-			vp->options = -1;
-		else
-			vp->options = options[card_number];
-	}
-
-	if (vp->options >= 0) {
-		vp->media_override = vp->options & 7;
-		if (vp->media_override == 2)
-			vp->media_override = 0;
-		vp->full_duplex = (vp->options & 8) ? 1 : 0;
-		vp->bus_master = (vp->options & 16) ? 1 : 0;
-	} else {
-		vp->media_override = 7;
-		vp->full_duplex = 0;
-		vp->bus_master = 0;
-	}
-#ifdef MODULE
-	list_add(&vp->list, &root_corkscrew_dev);
-#endif
-
-	pr_info("%s: 3Com %s at %#3x,", dev->name, vp->product_name, ioaddr);
-
-	spin_lock_init(&vp->lock);
-
-	/* Read the station address from the EEPROM. */
-	EL3WINDOW(0);
-	for (i = 0; i < 0x18; i++) {
-		__be16 *phys_addr = (__be16 *) dev->dev_addr;
-		int timer;
-		outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
-		/* Pause for at least 162 us. for the read to take place. */
-		for (timer = 4; timer >= 0; timer--) {
-			udelay(162);
-			if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
-				break;
-		}
-		eeprom[i] = inw(ioaddr + Wn0EepromData);
-		checksum ^= eeprom[i];
-		if (i < 3)
-			phys_addr[i] = htons(eeprom[i]);
-	}
-	checksum = (checksum ^ (checksum >> 8)) & 0xff;
-	if (checksum != 0x00)
-		pr_cont(" ***INVALID CHECKSUM %4.4x*** ", checksum);
-	pr_cont(" %pM", dev->dev_addr);
-	if (eeprom[16] == 0x11c7) {	/* Corkscrew */
-		if (request_dma(dev->dma, "3c515")) {
-			pr_cont(", DMA %d allocation failed", dev->dma);
-			dev->dma = 0;
-		} else
-			pr_cont(", DMA %d", dev->dma);
-	}
-	pr_cont(", IRQ %d\n", dev->irq);
-	/* Tell them about an invalid IRQ. */
-	if (corkscrew_debug && (dev->irq <= 0 || dev->irq > 15))
-		pr_warning(" *** Warning: this IRQ is unlikely to work! ***\n");
-
-	{
-		static const char * const ram_split[] = {
-			"5:3", "3:1", "1:1", "3:5"
-		};
-		__u32 config;
-		EL3WINDOW(3);
-		vp->available_media = inw(ioaddr + Wn3_Options);
-		config = inl(ioaddr + Wn3_Config);
-		if (corkscrew_debug > 1)
-			pr_info("  Internal config register is %4.4x, transceivers %#x.\n",
-				config, inw(ioaddr + Wn3_Options));
-		pr_info("  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
-			8 << config & Ram_size,
-			config & Ram_width ? "word" : "byte",
-			ram_split[(config & Ram_split) >> Ram_split_shift],
-			config & Autoselect ? "autoselect/" : "",
-			media_tbl[(config & Xcvr) >> Xcvr_shift].name);
-		vp->default_media = (config & Xcvr) >> Xcvr_shift;
-		vp->autoselect = config & Autoselect ? 1 : 0;
-		dev->if_port = vp->default_media;
-	}
-	if (vp->media_override != 7) {
-		pr_info("  Media override to transceiver type %d (%s).\n",
-		       vp->media_override,
-		       media_tbl[vp->media_override].name);
-		dev->if_port = vp->media_override;
-	}
-
-	vp->capabilities = eeprom[16];
-	vp->full_bus_master_tx = (vp->capabilities & 0x20) ? 1 : 0;
-	/* Rx is broken at 10mbps, so we always disable it. */
-	/* vp->full_bus_master_rx = 0; */
-	vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0;
-
-	/* The 3c51x-specific entries in the device structure. */
-	dev->netdev_ops = &netdev_ops;
-	dev->watchdog_timeo = (400 * HZ) / 1000;
-	dev->ethtool_ops = &netdev_ethtool_ops;
-
-	return register_netdev(dev);
-}
-
-
-static int corkscrew_open(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	struct corkscrew_private *vp = netdev_priv(dev);
-	__u32 config;
-	int i;
-
-	/* Before initializing select the active media port. */
-	EL3WINDOW(3);
-	if (vp->full_duplex)
-		outb(0x20, ioaddr + Wn3_MAC_Ctrl);	/* Set the full-duplex bit. */
-	config = inl(ioaddr + Wn3_Config);
-
-	if (vp->media_override != 7) {
-		if (corkscrew_debug > 1)
-			pr_info("%s: Media override to transceiver %d (%s).\n",
-				dev->name, vp->media_override,
-				media_tbl[vp->media_override].name);
-		dev->if_port = vp->media_override;
-	} else if (vp->autoselect) {
-		/* Find first available media type, starting with 100baseTx. */
-		dev->if_port = 4;
-		while (!(vp->available_media & media_tbl[dev->if_port].mask))
-			dev->if_port = media_tbl[dev->if_port].next;
-
-		if (corkscrew_debug > 1)
-			pr_debug("%s: Initial media type %s.\n",
-			       dev->name, media_tbl[dev->if_port].name);
-
-		init_timer(&vp->timer);
-		vp->timer.expires = jiffies + media_tbl[dev->if_port].wait;
-		vp->timer.data = (unsigned long) dev;
-		vp->timer.function = corkscrew_timer;	/* timer handler */
-		add_timer(&vp->timer);
-	} else
-		dev->if_port = vp->default_media;
-
-	config = (config & ~Xcvr) | (dev->if_port << Xcvr_shift);
-	outl(config, ioaddr + Wn3_Config);
-
-	if (corkscrew_debug > 1) {
-		pr_debug("%s: corkscrew_open() InternalConfig %8.8x.\n",
-		       dev->name, config);
-	}
-
-	outw(TxReset, ioaddr + EL3_CMD);
-	for (i = 20; i >= 0; i--)
-		if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
-			break;
-
-	outw(RxReset, ioaddr + EL3_CMD);
-	/* Wait a few ticks for the RxReset command to complete. */
-	for (i = 20; i >= 0; i--)
-		if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
-			break;
-
-	outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
-
-	/* Use the now-standard shared IRQ implementation. */
-	if (vp->capabilities == 0x11c7) {
-		/* Corkscrew: Cannot share ISA resources. */
-		if (dev->irq == 0 ||
-		    dev->dma == 0 ||
-		    request_irq(dev->irq, corkscrew_interrupt, 0,
-				vp->product_name, dev))
-			return -EAGAIN;
-		enable_dma(dev->dma);
-		set_dma_mode(dev->dma, DMA_MODE_CASCADE);
-	} else if (request_irq(dev->irq, corkscrew_interrupt, IRQF_SHARED,
-			       vp->product_name, dev)) {
-		return -EAGAIN;
-	}
-
-	if (corkscrew_debug > 1) {
-		EL3WINDOW(4);
-		pr_debug("%s: corkscrew_open() irq %d media status %4.4x.\n",
-		       dev->name, dev->irq, inw(ioaddr + Wn4_Media));
-	}
-
-	/* Set the station address and mask in window 2 each time opened. */
-	EL3WINDOW(2);
-	for (i = 0; i < 6; i++)
-		outb(dev->dev_addr[i], ioaddr + i);
-	for (; i < 12; i += 2)
-		outw(0, ioaddr + i);
-
-	if (dev->if_port == 3)
-		/* Start the thinnet transceiver. We should really wait 50ms... */
-		outw(StartCoax, ioaddr + EL3_CMD);
-	EL3WINDOW(4);
-	outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP | Media_SQE)) |
-	     media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
-
-	/* Switch to the stats window, and clear all stats by reading. */
-	outw(StatsDisable, ioaddr + EL3_CMD);
-	EL3WINDOW(6);
-	for (i = 0; i < 10; i++)
-		inb(ioaddr + i);
-	inw(ioaddr + 10);
-	inw(ioaddr + 12);
-	/* New: On the Vortex we must also clear the BadSSD counter. */
-	EL3WINDOW(4);
-	inb(ioaddr + 12);
-	/* ..and on the Boomerang we enable the extra statistics bits. */
-	outw(0x0040, ioaddr + Wn4_NetDiag);
-
-	/* Switch to register set 7 for normal use. */
-	EL3WINDOW(7);
-
-	if (vp->full_bus_master_rx) {	/* Boomerang bus master. */
-		vp->cur_rx = vp->dirty_rx = 0;
-		if (corkscrew_debug > 2)
-			pr_debug("%s:  Filling in the Rx ring.\n", dev->name);
-		for (i = 0; i < RX_RING_SIZE; i++) {
-			struct sk_buff *skb;
-			if (i < (RX_RING_SIZE - 1))
-				vp->rx_ring[i].next =
-				    isa_virt_to_bus(&vp->rx_ring[i + 1]);
-			else
-				vp->rx_ring[i].next = 0;
-			vp->rx_ring[i].status = 0;	/* Clear complete bit. */
-			vp->rx_ring[i].length = PKT_BUF_SZ | 0x80000000;
-			skb = dev_alloc_skb(PKT_BUF_SZ);
-			vp->rx_skbuff[i] = skb;
-			if (skb == NULL)
-				break;	/* Bad news!  */
-			skb->dev = dev;	/* Mark as being used by this device. */
-			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			vp->rx_ring[i].addr = isa_virt_to_bus(skb->data);
-		}
-		if (i != 0)
-			vp->rx_ring[i - 1].next =
-				isa_virt_to_bus(&vp->rx_ring[0]);	/* Wrap the ring. */
-		outl(isa_virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
-	}
-	if (vp->full_bus_master_tx) {	/* Boomerang bus master Tx. */
-		vp->cur_tx = vp->dirty_tx = 0;
-		outb(PKT_BUF_SZ >> 8, ioaddr + TxFreeThreshold);	/* Room for a packet. */
-		/* Clear the Tx ring. */
-		for (i = 0; i < TX_RING_SIZE; i++)
-			vp->tx_skbuff[i] = NULL;
-		outl(0, ioaddr + DownListPtr);
-	}
-	/* Set receiver mode: presumably accept b-case and phys addr only. */
-	set_rx_mode(dev);
-	outw(StatsEnable, ioaddr + EL3_CMD);	/* Turn on statistics. */
-
-	netif_start_queue(dev);
-
-	outw(RxEnable, ioaddr + EL3_CMD);	/* Enable the receiver. */
-	outw(TxEnable, ioaddr + EL3_CMD);	/* Enable transmitter. */
-	/* Allow status bits to be seen. */
-	outw(SetStatusEnb | AdapterFailure | IntReq | StatsFull |
-	     (vp->full_bus_master_tx ? DownComplete : TxAvailable) |
-	     (vp->full_bus_master_rx ? UpComplete : RxComplete) |
-	     (vp->bus_master ? DMADone : 0), ioaddr + EL3_CMD);
-	/* Ack all pending events, and set active indicator mask. */
-	outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
-	     ioaddr + EL3_CMD);
-	outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
-	     | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
-	     ioaddr + EL3_CMD);
-
-	return 0;
-}
-
-static void corkscrew_timer(unsigned long data)
-{
-#ifdef AUTOMEDIA
-	struct net_device *dev = (struct net_device *) data;
-	struct corkscrew_private *vp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-	unsigned long flags;
-	int ok = 0;
-
-	if (corkscrew_debug > 1)
-		pr_debug("%s: Media selection timer tick happened, %s.\n",
-		       dev->name, media_tbl[dev->if_port].name);
-
-	spin_lock_irqsave(&vp->lock, flags);
-
-	{
-		int old_window = inw(ioaddr + EL3_CMD) >> 13;
-		int media_status;
-		EL3WINDOW(4);
-		media_status = inw(ioaddr + Wn4_Media);
-		switch (dev->if_port) {
-		case 0:
-		case 4:
-		case 5:	/* 10baseT, 100baseTX, 100baseFX  */
-			if (media_status & Media_LnkBeat) {
-				ok = 1;
-				if (corkscrew_debug > 1)
-					pr_debug("%s: Media %s has link beat, %x.\n",
-						dev->name,
-						media_tbl[dev->if_port].name,
-						media_status);
-			} else if (corkscrew_debug > 1)
-				pr_debug("%s: Media %s is has no link beat, %x.\n",
-					dev->name,
-					media_tbl[dev->if_port].name,
-					media_status);
-
-			break;
-		default:	/* Other media types handled by Tx timeouts. */
-			if (corkscrew_debug > 1)
-				pr_debug("%s: Media %s is has no indication, %x.\n",
-					dev->name,
-					media_tbl[dev->if_port].name,
-					media_status);
-			ok = 1;
-		}
-		if (!ok) {
-			__u32 config;
-
-			do {
-				dev->if_port =
-				    media_tbl[dev->if_port].next;
-			}
-			while (!(vp->available_media & media_tbl[dev->if_port].mask));
-
-			if (dev->if_port == 8) {	/* Go back to default. */
-				dev->if_port = vp->default_media;
-				if (corkscrew_debug > 1)
-					pr_debug("%s: Media selection failing, using default %s port.\n",
-						dev->name,
-						media_tbl[dev->if_port].name);
-			} else {
-				if (corkscrew_debug > 1)
-					pr_debug("%s: Media selection failed, now trying %s port.\n",
-						dev->name,
-						media_tbl[dev->if_port].name);
-				vp->timer.expires = jiffies + media_tbl[dev->if_port].wait;
-				add_timer(&vp->timer);
-			}
-			outw((media_status & ~(Media_10TP | Media_SQE)) |
-			     media_tbl[dev->if_port].media_bits,
-			     ioaddr + Wn4_Media);
-
-			EL3WINDOW(3);
-			config = inl(ioaddr + Wn3_Config);
-			config = (config & ~Xcvr) | (dev->if_port << Xcvr_shift);
-			outl(config, ioaddr + Wn3_Config);
-
-			outw(dev->if_port == 3 ? StartCoax : StopCoax,
-			     ioaddr + EL3_CMD);
-		}
-		EL3WINDOW(old_window);
-	}
-
-	spin_unlock_irqrestore(&vp->lock, flags);
-	if (corkscrew_debug > 1)
-		pr_debug("%s: Media selection timer finished, %s.\n",
-		       dev->name, media_tbl[dev->if_port].name);
-
-#endif				/* AUTOMEDIA */
-}
-
-static void corkscrew_timeout(struct net_device *dev)
-{
-	int i;
-	struct corkscrew_private *vp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-
-	pr_warning("%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
-	       dev->name, inb(ioaddr + TxStatus),
-	       inw(ioaddr + EL3_STATUS));
-	/* Slight code bloat to be user friendly. */
-	if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
-		pr_warning("%s: Transmitter encountered 16 collisions --"
-		       " network cable problem?\n", dev->name);
-#ifndef final_version
-	pr_debug("  Flags; bus-master %d, full %d; dirty %d current %d.\n",
-	       vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx,
-	       vp->cur_tx);
-	pr_debug("  Down list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr),
-	       &vp->tx_ring[0]);
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		pr_debug("  %d: %p  length %8.8x status %8.8x\n", i,
-		       &vp->tx_ring[i],
-		       vp->tx_ring[i].length, vp->tx_ring[i].status);
-	}
-#endif
-	/* Issue TX_RESET and TX_START commands. */
-	outw(TxReset, ioaddr + EL3_CMD);
-	for (i = 20; i >= 0; i--)
-		if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
-			break;
-	outw(TxEnable, ioaddr + EL3_CMD);
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	dev->stats.tx_errors++;
-	dev->stats.tx_dropped++;
-	netif_wake_queue(dev);
-}
-
-static netdev_tx_t corkscrew_start_xmit(struct sk_buff *skb,
-					struct net_device *dev)
-{
-	struct corkscrew_private *vp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-
-	/* Block a timer-based transmit from overlapping. */
-
-	netif_stop_queue(dev);
-
-	if (vp->full_bus_master_tx) {	/* BOOMERANG bus-master */
-		/* Calculate the next Tx descriptor entry. */
-		int entry = vp->cur_tx % TX_RING_SIZE;
-		struct boom_tx_desc *prev_entry;
-		unsigned long flags;
-		int i;
-
-		if (vp->tx_full)	/* No room to transmit with */
-			return NETDEV_TX_BUSY;
-		if (vp->cur_tx != 0)
-			prev_entry = &vp->tx_ring[(vp->cur_tx - 1) % TX_RING_SIZE];
-		else
-			prev_entry = NULL;
-		if (corkscrew_debug > 3)
-			pr_debug("%s: Trying to send a packet, Tx index %d.\n",
-				dev->name, vp->cur_tx);
-		/* vp->tx_full = 1; */
-		vp->tx_skbuff[entry] = skb;
-		vp->tx_ring[entry].next = 0;
-		vp->tx_ring[entry].addr = isa_virt_to_bus(skb->data);
-		vp->tx_ring[entry].length = skb->len | 0x80000000;
-		vp->tx_ring[entry].status = skb->len | 0x80000000;
-
-		spin_lock_irqsave(&vp->lock, flags);
-		outw(DownStall, ioaddr + EL3_CMD);
-		/* Wait for the stall to complete. */
-		for (i = 20; i >= 0; i--)
-			if ((inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0)
-				break;
-		if (prev_entry)
-			prev_entry->next = isa_virt_to_bus(&vp->tx_ring[entry]);
-		if (inl(ioaddr + DownListPtr) == 0) {
-			outl(isa_virt_to_bus(&vp->tx_ring[entry]),
-			     ioaddr + DownListPtr);
-			queued_packet++;
-		}
-		outw(DownUnstall, ioaddr + EL3_CMD);
-		spin_unlock_irqrestore(&vp->lock, flags);
-
-		vp->cur_tx++;
-		if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)
-			vp->tx_full = 1;
-		else {		/* Clear previous interrupt enable. */
-			if (prev_entry)
-				prev_entry->status &= ~0x80000000;
-			netif_wake_queue(dev);
-		}
-		return NETDEV_TX_OK;
-	}
-	/* Put out the doubleword header... */
-	outl(skb->len, ioaddr + TX_FIFO);
-	dev->stats.tx_bytes += skb->len;
-#ifdef VORTEX_BUS_MASTER
-	if (vp->bus_master) {
-		/* Set the bus-master controller to transfer the packet. */
-		outl((int) (skb->data), ioaddr + Wn7_MasterAddr);
-		outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
-		vp->tx_skb = skb;
-		outw(StartDMADown, ioaddr + EL3_CMD);
-		/* queue will be woken at the DMADone interrupt. */
-	} else {
-		/* ... and the packet rounded to a doubleword. */
-		outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
-		dev_kfree_skb(skb);
-		if (inw(ioaddr + TxFree) > 1536) {
-			netif_wake_queue(dev);
-		} else
-			/* Interrupt us when the FIFO has room for max-sized packet. */
-			outw(SetTxThreshold + (1536 >> 2),
-			     ioaddr + EL3_CMD);
-	}
-#else
-	/* ... and the packet rounded to a doubleword. */
-	outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
-	dev_kfree_skb(skb);
-	if (inw(ioaddr + TxFree) > 1536) {
-		netif_wake_queue(dev);
-	} else
-		/* Interrupt us when the FIFO has room for max-sized packet. */
-		outw(SetTxThreshold + (1536 >> 2), ioaddr + EL3_CMD);
-#endif				/* bus master */
-
-
-	/* Clear the Tx status stack. */
-	{
-		short tx_status;
-		int i = 4;
-
-		while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) {
-			if (tx_status & 0x3C) {	/* A Tx-disabling error occurred.  */
-				if (corkscrew_debug > 2)
-					pr_debug("%s: Tx error, status %2.2x.\n",
-						dev->name, tx_status);
-				if (tx_status & 0x04)
-					dev->stats.tx_fifo_errors++;
-				if (tx_status & 0x38)
-					dev->stats.tx_aborted_errors++;
-				if (tx_status & 0x30) {
-					int j;
-					outw(TxReset, ioaddr + EL3_CMD);
-					for (j = 20; j >= 0; j--)
-						if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
-							break;
-				}
-				outw(TxEnable, ioaddr + EL3_CMD);
-			}
-			outb(0x00, ioaddr + TxStatus);	/* Pop the status stack. */
-		}
-	}
-	return NETDEV_TX_OK;
-}
-
-/* The interrupt handler does all of the Rx thread work and cleans up
-   after the Tx thread. */
-
-static irqreturn_t corkscrew_interrupt(int irq, void *dev_id)
-{
-	/* Use the now-standard shared IRQ implementation. */
-	struct net_device *dev = dev_id;
-	struct corkscrew_private *lp = netdev_priv(dev);
-	int ioaddr, status;
-	int latency;
-	int i = max_interrupt_work;
-
-	ioaddr = dev->base_addr;
-	latency = inb(ioaddr + Timer);
-
-	spin_lock(&lp->lock);
-
-	status = inw(ioaddr + EL3_STATUS);
-
-	if (corkscrew_debug > 4)
-		pr_debug("%s: interrupt, status %4.4x, timer %d.\n",
-			dev->name, status, latency);
-	if ((status & 0xE000) != 0xE000) {
-		static int donedidthis;
-		/* Some interrupt controllers store a bogus interrupt from boot-time.
-		   Ignore a single early interrupt, but don't hang the machine for
-		   other interrupt problems. */
-		if (donedidthis++ > 100) {
-			pr_err("%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n",
-				   dev->name, status, netif_running(dev));
-			free_irq(dev->irq, dev);
-			dev->irq = -1;
-		}
-	}
-
-	do {
-		if (corkscrew_debug > 5)
-			pr_debug("%s: In interrupt loop, status %4.4x.\n",
-			       dev->name, status);
-		if (status & RxComplete)
-			corkscrew_rx(dev);
-
-		if (status & TxAvailable) {
-			if (corkscrew_debug > 5)
-				pr_debug("	TX room bit was handled.\n");
-			/* There's room in the FIFO for a full-sized packet. */
-			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
-			netif_wake_queue(dev);
-		}
-		if (status & DownComplete) {
-			unsigned int dirty_tx = lp->dirty_tx;
-
-			while (lp->cur_tx - dirty_tx > 0) {
-				int entry = dirty_tx % TX_RING_SIZE;
-				if (inl(ioaddr + DownListPtr) == isa_virt_to_bus(&lp->tx_ring[entry]))
-					break;	/* It still hasn't been processed. */
-				if (lp->tx_skbuff[entry]) {
-					dev_kfree_skb_irq(lp->tx_skbuff[entry]);
-					lp->tx_skbuff[entry] = NULL;
-				}
-				dirty_tx++;
-			}
-			lp->dirty_tx = dirty_tx;
-			outw(AckIntr | DownComplete, ioaddr + EL3_CMD);
-			if (lp->tx_full && (lp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
-				lp->tx_full = 0;
-				netif_wake_queue(dev);
-			}
-		}
-#ifdef VORTEX_BUS_MASTER
-		if (status & DMADone) {
-			outw(0x1000, ioaddr + Wn7_MasterStatus);	/* Ack the event. */
-			dev_kfree_skb_irq(lp->tx_skb);	/* Release the transferred buffer */
-			netif_wake_queue(dev);
-		}
-#endif
-		if (status & UpComplete) {
-			boomerang_rx(dev);
-			outw(AckIntr | UpComplete, ioaddr + EL3_CMD);
-		}
-		if (status & (AdapterFailure | RxEarly | StatsFull)) {
-			/* Handle all uncommon interrupts at once. */
-			if (status & RxEarly) {	/* Rx early is unused. */
-				corkscrew_rx(dev);
-				outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
-			}
-			if (status & StatsFull) {	/* Empty statistics. */
-				static int DoneDidThat;
-				if (corkscrew_debug > 4)
-					pr_debug("%s: Updating stats.\n", dev->name);
-				update_stats(ioaddr, dev);
-				/* DEBUG HACK: Disable statistics as an interrupt source. */
-				/* This occurs when we have the wrong media type! */
-				if (DoneDidThat == 0 && inw(ioaddr + EL3_STATUS) & StatsFull) {
-					int win, reg;
-					pr_notice("%s: Updating stats failed, disabling stats as an interrupt source.\n",
-						dev->name);
-					for (win = 0; win < 8; win++) {
-						EL3WINDOW(win);
-						pr_notice("Vortex window %d:", win);
-						for (reg = 0; reg < 16; reg++)
-							pr_cont(" %2.2x", inb(ioaddr + reg));
-						pr_cont("\n");
-					}
-					EL3WINDOW(7);
-					outw(SetIntrEnb | TxAvailable |
-					     RxComplete | AdapterFailure |
-					     UpComplete | DownComplete |
-					     TxComplete, ioaddr + EL3_CMD);
-					DoneDidThat++;
-				}
-			}
-			if (status & AdapterFailure) {
-				/* Adapter failure requires Rx reset and reinit. */
-				outw(RxReset, ioaddr + EL3_CMD);
-				/* Set the Rx filter to the current state. */
-				set_rx_mode(dev);
-				outw(RxEnable, ioaddr + EL3_CMD);	/* Re-enable the receiver. */
-				outw(AckIntr | AdapterFailure,
-				     ioaddr + EL3_CMD);
-			}
-		}
-
-		if (--i < 0) {
-			pr_err("%s: Too much work in interrupt, status %4.4x. Disabling functions (%4.4x).\n",
-				dev->name, status, SetStatusEnb | ((~status) & 0x7FE));
-			/* Disable all pending interrupts. */
-			outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD);
-			outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
-			break;
-		}
-		/* Acknowledge the IRQ. */
-		outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
-
-	} while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
-
-	spin_unlock(&lp->lock);
-
-	if (corkscrew_debug > 4)
-		pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name, status);
-	return IRQ_HANDLED;
-}
-
-static int corkscrew_rx(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	int i;
-	short rx_status;
-
-	if (corkscrew_debug > 5)
-		pr_debug("   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
-		     inw(ioaddr + EL3_STATUS), inw(ioaddr + RxStatus));
-	while ((rx_status = inw(ioaddr + RxStatus)) > 0) {
-		if (rx_status & 0x4000) {	/* Error, update stats. */
-			unsigned char rx_error = inb(ioaddr + RxErrors);
-			if (corkscrew_debug > 2)
-				pr_debug(" Rx error: status %2.2x.\n",
-				       rx_error);
-			dev->stats.rx_errors++;
-			if (rx_error & 0x01)
-				dev->stats.rx_over_errors++;
-			if (rx_error & 0x02)
-				dev->stats.rx_length_errors++;
-			if (rx_error & 0x04)
-				dev->stats.rx_frame_errors++;
-			if (rx_error & 0x08)
-				dev->stats.rx_crc_errors++;
-			if (rx_error & 0x10)
-				dev->stats.rx_length_errors++;
-		} else {
-			/* The packet length: up to 4.5K!. */
-			short pkt_len = rx_status & 0x1fff;
-			struct sk_buff *skb;
-
-			skb = dev_alloc_skb(pkt_len + 5 + 2);
-			if (corkscrew_debug > 4)
-				pr_debug("Receiving packet size %d status %4.4x.\n",
-				     pkt_len, rx_status);
-			if (skb != NULL) {
-				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-				/* 'skb_put()' points to the start of sk_buff data area. */
-				insl(ioaddr + RX_FIFO,
-				     skb_put(skb, pkt_len),
-				     (pkt_len + 3) >> 2);
-				outw(RxDiscard, ioaddr + EL3_CMD);	/* Pop top Rx packet. */
-				skb->protocol = eth_type_trans(skb, dev);
-				netif_rx(skb);
-				dev->stats.rx_packets++;
-				dev->stats.rx_bytes += pkt_len;
-				/* Wait a limited time to go to next packet. */
-				for (i = 200; i >= 0; i--)
-					if (! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
-						break;
-				continue;
-			} else if (corkscrew_debug)
-				pr_debug("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, pkt_len);
-		}
-		outw(RxDiscard, ioaddr + EL3_CMD);
-		dev->stats.rx_dropped++;
-		/* Wait a limited time to skip this packet. */
-		for (i = 200; i >= 0; i--)
-			if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
-				break;
-	}
-	return 0;
-}
-
-static int boomerang_rx(struct net_device *dev)
-{
-	struct corkscrew_private *vp = netdev_priv(dev);
-	int entry = vp->cur_rx % RX_RING_SIZE;
-	int ioaddr = dev->base_addr;
-	int rx_status;
-
-	if (corkscrew_debug > 5)
-		pr_debug("   In boomerang_rx(), status %4.4x, rx_status %4.4x.\n",
-			inw(ioaddr + EL3_STATUS), inw(ioaddr + RxStatus));
-	while ((rx_status = vp->rx_ring[entry].status) & RxDComplete) {
-		if (rx_status & RxDError) {	/* Error, update stats. */
-			unsigned char rx_error = rx_status >> 16;
-			if (corkscrew_debug > 2)
-				pr_debug(" Rx error: status %2.2x.\n",
-				       rx_error);
-			dev->stats.rx_errors++;
-			if (rx_error & 0x01)
-				dev->stats.rx_over_errors++;
-			if (rx_error & 0x02)
-				dev->stats.rx_length_errors++;
-			if (rx_error & 0x04)
-				dev->stats.rx_frame_errors++;
-			if (rx_error & 0x08)
-				dev->stats.rx_crc_errors++;
-			if (rx_error & 0x10)
-				dev->stats.rx_length_errors++;
-		} else {
-			/* The packet length: up to 4.5K!. */
-			short pkt_len = rx_status & 0x1fff;
-			struct sk_buff *skb;
-
-			dev->stats.rx_bytes += pkt_len;
-			if (corkscrew_debug > 4)
-				pr_debug("Receiving packet size %d status %4.4x.\n",
-				     pkt_len, rx_status);
-
-			/* Check if the packet is long enough to just accept without
-			   copying to a properly sized skbuff. */
-			if (pkt_len < rx_copybreak &&
-			    (skb = dev_alloc_skb(pkt_len + 4)) != NULL) {
-				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-				/* 'skb_put()' points to the start of sk_buff data area. */
-				memcpy(skb_put(skb, pkt_len),
-				       isa_bus_to_virt(vp->rx_ring[entry].
-						   addr), pkt_len);
-				rx_copy++;
-			} else {
-				void *temp;
-				/* Pass up the skbuff already on the Rx ring. */
-				skb = vp->rx_skbuff[entry];
-				vp->rx_skbuff[entry] = NULL;
-				temp = skb_put(skb, pkt_len);
-				/* Remove this checking code for final release. */
-				if (isa_bus_to_virt(vp->rx_ring[entry].addr) != temp)
-					pr_warning("%s: Warning -- the skbuff addresses do not match"
-					     " in boomerang_rx: %p vs. %p / %p.\n",
-					     dev->name,
-					     isa_bus_to_virt(vp->
-							 rx_ring[entry].
-							 addr), skb->head,
-					     temp);
-				rx_nocopy++;
-			}
-			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
-			dev->stats.rx_packets++;
-		}
-		entry = (++vp->cur_rx) % RX_RING_SIZE;
-	}
-	/* Refill the Rx ring buffers. */
-	for (; vp->cur_rx - vp->dirty_rx > 0; vp->dirty_rx++) {
-		struct sk_buff *skb;
-		entry = vp->dirty_rx % RX_RING_SIZE;
-		if (vp->rx_skbuff[entry] == NULL) {
-			skb = dev_alloc_skb(PKT_BUF_SZ);
-			if (skb == NULL)
-				break;	/* Bad news!  */
-			skb->dev = dev;	/* Mark as being used by this device. */
-			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			vp->rx_ring[entry].addr = isa_virt_to_bus(skb->data);
-			vp->rx_skbuff[entry] = skb;
-		}
-		vp->rx_ring[entry].status = 0;	/* Clear complete bit. */
-	}
-	return 0;
-}
-
-static int corkscrew_close(struct net_device *dev)
-{
-	struct corkscrew_private *vp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-	int i;
-
-	netif_stop_queue(dev);
-
-	if (corkscrew_debug > 1) {
-		pr_debug("%s: corkscrew_close() status %4.4x, Tx status %2.2x.\n",
-		     dev->name, inw(ioaddr + EL3_STATUS),
-		     inb(ioaddr + TxStatus));
-		pr_debug("%s: corkscrew close stats: rx_nocopy %d rx_copy %d tx_queued %d.\n",
-			dev->name, rx_nocopy, rx_copy, queued_packet);
-	}
-
-	del_timer(&vp->timer);
-
-	/* Turn off statistics ASAP.  We update lp->stats below. */
-	outw(StatsDisable, ioaddr + EL3_CMD);
-
-	/* Disable the receiver and transmitter. */
-	outw(RxDisable, ioaddr + EL3_CMD);
-	outw(TxDisable, ioaddr + EL3_CMD);
-
-	if (dev->if_port == XCVR_10base2)
-		/* Turn off thinnet power.  Green! */
-		outw(StopCoax, ioaddr + EL3_CMD);
-
-	free_irq(dev->irq, dev);
-
-	outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
-
-	update_stats(ioaddr, dev);
-	if (vp->full_bus_master_rx) {	/* Free Boomerang bus master Rx buffers. */
-		outl(0, ioaddr + UpListPtr);
-		for (i = 0; i < RX_RING_SIZE; i++)
-			if (vp->rx_skbuff[i]) {
-				dev_kfree_skb(vp->rx_skbuff[i]);
-				vp->rx_skbuff[i] = NULL;
-			}
-	}
-	if (vp->full_bus_master_tx) {	/* Free Boomerang bus master Tx buffers. */
-		outl(0, ioaddr + DownListPtr);
-		for (i = 0; i < TX_RING_SIZE; i++)
-			if (vp->tx_skbuff[i]) {
-				dev_kfree_skb(vp->tx_skbuff[i]);
-				vp->tx_skbuff[i] = NULL;
-			}
-	}
-
-	return 0;
-}
-
-static struct net_device_stats *corkscrew_get_stats(struct net_device *dev)
-{
-	struct corkscrew_private *vp = netdev_priv(dev);
-	unsigned long flags;
-
-	if (netif_running(dev)) {
-		spin_lock_irqsave(&vp->lock, flags);
-		update_stats(dev->base_addr, dev);
-		spin_unlock_irqrestore(&vp->lock, flags);
-	}
-	return &dev->stats;
-}
-
-/*  Update statistics.
-	Unlike with the EL3 we need not worry about interrupts changing
-	the window setting from underneath us, but we must still guard
-	against a race condition with a StatsUpdate interrupt updating the
-	table.  This is done by checking that the ASM (!) code generated uses
-	atomic updates with '+='.
-	*/
-static void update_stats(int ioaddr, struct net_device *dev)
-{
-	/* Unlike the 3c5x9 we need not turn off stats updates while reading. */
-	/* Switch to the stats window, and read everything. */
-	EL3WINDOW(6);
-	dev->stats.tx_carrier_errors += inb(ioaddr + 0);
-	dev->stats.tx_heartbeat_errors += inb(ioaddr + 1);
-	/* Multiple collisions. */ inb(ioaddr + 2);
-	dev->stats.collisions += inb(ioaddr + 3);
-	dev->stats.tx_window_errors += inb(ioaddr + 4);
-	dev->stats.rx_fifo_errors += inb(ioaddr + 5);
-	dev->stats.tx_packets += inb(ioaddr + 6);
-	dev->stats.tx_packets += (inb(ioaddr + 9) & 0x30) << 4;
-						/* Rx packets   */ inb(ioaddr + 7);
-						/* Must read to clear */
-	/* Tx deferrals */ inb(ioaddr + 8);
-	/* Don't bother with register 9, an extension of registers 6&7.
-	   If we do use the 6&7 values the atomic update assumption above
-	   is invalid. */
-	inw(ioaddr + 10);	/* Total Rx and Tx octets. */
-	inw(ioaddr + 12);
-	/* New: On the Vortex we must also clear the BadSSD counter. */
-	EL3WINDOW(4);
-	inb(ioaddr + 12);
-
-	/* We change back to window 7 (not 1) with the Vortex. */
-	EL3WINDOW(7);
-}
-
-/* This new version of set_rx_mode() supports v1.4 kernels.
-   The Vortex chip has no documented multicast filter, so the only
-   multicast setting is to receive all multicast frames.  At least
-   the chip has a very clean way to set the mode, unlike many others. */
-static void set_rx_mode(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	short new_mode;
-
-	if (dev->flags & IFF_PROMISC) {
-		if (corkscrew_debug > 3)
-			pr_debug("%s: Setting promiscuous mode.\n",
-			       dev->name);
-		new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm;
-	} else if (!netdev_mc_empty(dev) || dev->flags & IFF_ALLMULTI) {
-		new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast;
-	} else
-		new_mode = SetRxFilter | RxStation | RxBroadcast;
-
-	outw(new_mode, ioaddr + EL3_CMD);
-}
-
-static void netdev_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-	sprintf(info->bus_info, "ISA 0x%lx", dev->base_addr);
-}
-
-static u32 netdev_get_msglevel(struct net_device *dev)
-{
-	return corkscrew_debug;
-}
-
-static void netdev_set_msglevel(struct net_device *dev, u32 level)
-{
-	corkscrew_debug = level;
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-	.get_drvinfo		= netdev_get_drvinfo,
-	.get_msglevel		= netdev_get_msglevel,
-	.set_msglevel		= netdev_set_msglevel,
-};
-
-
-#ifdef MODULE
-void cleanup_module(void)
-{
-	while (!list_empty(&root_corkscrew_dev)) {
-		struct net_device *dev;
-		struct corkscrew_private *vp;
-
-		vp = list_entry(root_corkscrew_dev.next,
-				struct corkscrew_private, list);
-		dev = vp->our_dev;
-		unregister_netdev(dev);
-		cleanup_card(dev);
-		free_netdev(dev);
-	}
-}
-#endif				/* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/3c523.c linux-libre-3.2-gnu/drivers/net/3c523.c
--- linux-libre-3.1-gnu/drivers/net/3c523.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/3c523.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1312 +0,0 @@
-/*
-   net-3-driver for the 3c523 Etherlink/MC card (i82586 Ethernet chip)
-
-
-   This is an extension to the Linux operating system, and is covered by the
-   same GNU General Public License that covers that work.
-
-   Copyright 1995, 1996 by Chris Beauregard (cpbeaure@undergrad.math.uwaterloo.ca)
-
-   This is basically Michael Hipp's ni52 driver, with a new probing
-   algorithm and some minor changes to the 82586 CA and reset routines.
-   Thanks a lot Michael for a really clean i82586 implementation!  Unless
-   otherwise documented in ni52.c, any bugs are mine.
-
-   Contrary to the Ethernet-HOWTO, this isn't based on the 3c507 driver in
-   any way.  The ni52 is a lot easier to modify.
-
-   sources:
-   ni52.c
-
-   Crynwr packet driver collection was a great reference for my first
-   attempt at this sucker.  The 3c507 driver also helped, until I noticed
-   that ni52.c was a lot nicer.
-
-   EtherLink/MC: Micro Channel Ethernet Adapter Technical Reference
-   Manual, courtesy of 3Com CardFacts, documents the 3c523-specific
-   stuff.  Information on CardFacts is found in the Ethernet HOWTO.
-   Also see <a href="http://www.3com.com/">
-
-   Microprocessor Communications Support Chips, T.J. Byers, ISBN
-   0-444-01224-9, has a section on the i82586.  It tells you just enough
-   to know that you really don't want to learn how to program the chip.
-
-   The original device probe code was stolen from ps2esdi.c
-
-   Known Problems:
-   Since most of the code was stolen from ni52.c, you'll run across the
-   same bugs in the 0.62 version of ni52.c, plus maybe a few because of
-   the 3c523 idiosynchacies.  The 3c523 has 16K of RAM though, so there
-   shouldn't be the overrun problem that the 8K ni52 has.
-
-   This driver is for a 16K adapter.  It should work fine on the 64K
-   adapters, but it will only use one of the 4 banks of RAM.  Modifying
-   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 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?
-
-   It seems to be stable now when multiple transmit buffers are used.  I
-   can't see any performance difference, but then I'm working on a 386SX.
-
-   Multicast doesn't work.  It doesn't even pretend to work.  Don't use
-   it.  Don't compile your kernel with multicast support.  I don't know
-   why.
-
-   Features:
-   This driver is useable as a loadable module.  If you try to specify an
-   IRQ or a IO address (via insmod 3c523.o irq=xx io=0xyyy), it will
-   search the MCA slots until it finds a 3c523 with the specified
-   parameters.
-
-   This driver does support multiple ethernet cards when used as a module
-   (up to MAX_3C523_CARDS, the default being 4)
-
-   This has been tested with both BNC and TP versions, internal and
-   external transceivers.  Haven't tested with the 64K version (that I
-   know of).
-
-   History:
-   Jan 1st, 1996
-   first public release
-   Feb 4th, 1996
-   update to 1.3.59, incorporated multicast diffs from ni52.c
-   Feb 15th, 1996
-   added shared irq support
-   Apr 1999
-   added support for multiple cards when used as a module
-   added option to disable multicast as is causes problems
-       Ganesh Sittampalam <ganesh.sittampalam@magdalen.oxford.ac.uk>
-       Stuart Adamson <stuart.adamson@compsoc.net>
-   Nov 2001
-   added support for ethtool (jgarzik)
-
-   $Header: /fsys2/home/chrisb/linux-1.3.59-MCA/drivers/net/RCS/3c523.c,v 1.1 1996/02/05 01:53:46 chrisb Exp chrisb $
- */
-
-#define DRV_NAME		"3c523"
-#define DRV_VERSION		"17-Nov-2001"
-
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/skbuff.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/mca-legacy.h>
-#include <linux/ethtool.h>
-#include <linux/bitops.h>
-#include <linux/jiffies.h>
-
-#include <asm/uaccess.h>
-#include <asm/processor.h>
-#include <asm/io.h>
-
-#include "3c523.h"
-
-/*************************************************************************/
-#define DEBUG			/* debug on */
-#define SYSBUSVAL 0		/* 1 = 8 Bit, 0 = 16 bit - 3c523 only does 16 bit */
-#undef ELMC_MULTICAST		/* Disable multicast support as it is somewhat seriously broken at the moment */
-
-#define make32(ptr16) (p->memtop + (short) (ptr16) )
-#define make24(ptr32) ((char *) (ptr32) - p->base)
-#define make16(ptr32) ((unsigned short) ((unsigned long) (ptr32) - (unsigned long) p->memtop ))
-
-/*************************************************************************/
-/*
-   Tables to which we can map values in the configuration registers.
- */
-static int irq_table[] __initdata = {
-	12, 7, 3, 9
-};
-
-static int csr_table[] __initdata = {
-	0x300, 0x1300, 0x2300, 0x3300
-};
-
-static int shm_table[] __initdata = {
-	0x0c0000, 0x0c8000, 0x0d0000, 0x0d8000
-};
-
-/******************* how to calculate the buffers *****************************
-
-
-  * IMPORTANT NOTE: if you configure only one NUM_XMIT_BUFFS, the driver works
-  * --------------- in a different (more stable?) mode. Only in this mode it's
-  *                 possible to configure the driver with 'NO_NOPCOMMANDS'
-
-sizeof(scp)=12; sizeof(scb)=16; sizeof(iscp)=8;
-sizeof(scp)+sizeof(iscp)+sizeof(scb) = 36 = INIT
-sizeof(rfd) = 24; sizeof(rbd) = 12;
-sizeof(tbd) = 8; sizeof(transmit_cmd) = 16;
-sizeof(nop_cmd) = 8;
-
-  * if you don't know the driver, better do not change this values: */
-
-#define RECV_BUFF_SIZE 1524	/* slightly oversized */
-#define XMIT_BUFF_SIZE 1524	/* slightly oversized */
-#define NUM_XMIT_BUFFS 1	/* config for both, 8K and 16K shmem */
-#define NUM_RECV_BUFFS_8  4	/* config for 8K shared mem */
-#define NUM_RECV_BUFFS_16 9	/* config for 16K shared mem */
-
-#if (NUM_XMIT_BUFFS == 1)
-#define NO_NOPCOMMANDS		/* only possible with NUM_XMIT_BUFFS=1 */
-#endif
-
-/**************************************************************************/
-
-#define DELAY(x) { mdelay(32 * x); }
-
-/* a much shorter delay: */
-#define DELAY_16(); { udelay(16) ; }
-
-/* wait for command with timeout: */
-#define WAIT_4_SCB_CMD() { int i; \
-  for(i=0;i<1024;i++) { \
-    if(!p->scb->cmd) break; \
-    DELAY_16(); \
-    if(i == 1023) { \
-      pr_warning("%s:%d: scb_cmd timed out .. resetting i82586\n",\
-      	dev->name,__LINE__); \
-      elmc_id_reset586(); } } }
-
-static irqreturn_t elmc_interrupt(int irq, void *dev_id);
-static int elmc_open(struct net_device *dev);
-static int elmc_close(struct net_device *dev);
-static netdev_tx_t elmc_send_packet(struct sk_buff *, struct net_device *);
-static struct net_device_stats *elmc_get_stats(struct net_device *dev);
-static void elmc_timeout(struct net_device *dev);
-#ifdef ELMC_MULTICAST
-static void set_multicast_list(struct net_device *dev);
-#endif
-static const struct ethtool_ops netdev_ethtool_ops;
-
-/* helper-functions */
-static int init586(struct net_device *dev);
-static int check586(struct net_device *dev, unsigned long where, unsigned size);
-static void alloc586(struct net_device *dev);
-static void startrecv586(struct net_device *dev);
-static void *alloc_rfa(struct net_device *dev, void *ptr);
-static void elmc_rcv_int(struct net_device *dev);
-static void elmc_xmt_int(struct net_device *dev);
-static void elmc_rnr_int(struct net_device *dev);
-
-struct priv {
-	unsigned long base;
-	char *memtop;
-	unsigned long mapped_start;		/* Start of ioremap */
-	volatile struct rfd_struct *rfd_last, *rfd_top, *rfd_first;
-	volatile struct scp_struct *scp;	/* volatile is important */
-	volatile struct iscp_struct *iscp;	/* volatile is important */
-	volatile struct scb_struct *scb;	/* volatile is important */
-	volatile struct tbd_struct *xmit_buffs[NUM_XMIT_BUFFS];
-#if (NUM_XMIT_BUFFS == 1)
-	volatile struct transmit_cmd_struct *xmit_cmds[2];
-	volatile struct nop_cmd_struct *nop_cmds[2];
-#else
-	volatile struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS];
-	volatile struct nop_cmd_struct *nop_cmds[NUM_XMIT_BUFFS];
-#endif
-	volatile int nop_point, num_recv_buffs;
-	volatile char *xmit_cbuffs[NUM_XMIT_BUFFS];
-	volatile int xmit_count, xmit_last;
-	volatile int slot;
-};
-
-#define elmc_attn586()  {elmc_do_attn586(dev->base_addr,ELMC_CTRL_INTE);}
-#define elmc_reset586() {elmc_do_reset586(dev->base_addr,ELMC_CTRL_INTE);}
-
-/* with interrupts disabled - this will clear the interrupt bit in the
-   3c523 control register, and won't put it back.  This effectively
-   disables interrupts on the card. */
-#define elmc_id_attn586()  {elmc_do_attn586(dev->base_addr,0);}
-#define elmc_id_reset586() {elmc_do_reset586(dev->base_addr,0);}
-
-/*************************************************************************/
-/*
-   Do a Channel Attention on the 3c523.  This is extremely board dependent.
- */
-static void elmc_do_attn586(int ioaddr, int ints)
-{
-	/* the 3c523 requires a minimum of 500 ns.  The delays here might be
-	   a little too large, and hence they may cut the performance of the
-	   card slightly.  If someone who knows a little more about Linux
-	   timing would care to play with these, I'd appreciate it. */
-
-	/* this bit masking stuff is crap.  I'd rather have separate
-	   registers with strobe triggers for each of these functions.  <sigh>
-	   Ya take what ya got. */
-
-	outb(ELMC_CTRL_RST | 0x3 | ELMC_CTRL_CA | ints, ioaddr + ELMC_CTRL);
-	DELAY_16();		/* > 500 ns */
-	outb(ELMC_CTRL_RST | 0x3 | ints, ioaddr + ELMC_CTRL);
-}
-
-/*************************************************************************/
-/*
-   Reset the 82586 on the 3c523.  Also very board dependent.
- */
-static void elmc_do_reset586(int ioaddr, int ints)
-{
-	/* toggle the RST bit low then high */
-	outb(0x3 | ELMC_CTRL_LBK, ioaddr + ELMC_CTRL);
-	DELAY_16();		/* > 500 ns */
-	outb(ELMC_CTRL_RST | ELMC_CTRL_LBK | 0x3, ioaddr + ELMC_CTRL);
-
-	elmc_do_attn586(ioaddr, ints);
-}
-
-/**********************************************
- * close device
- */
-
-static int elmc_close(struct net_device *dev)
-{
-	netif_stop_queue(dev);
-	elmc_id_reset586();	/* the hard way to stop the receiver */
-	free_irq(dev->irq, dev);
-	return 0;
-}
-
-/**********************************************
- * open device
- */
-
-static int elmc_open(struct net_device *dev)
-{
-	int ret;
-
-	elmc_id_attn586();	/* disable interrupts */
-
-	ret = request_irq(dev->irq, elmc_interrupt, IRQF_SHARED,
-			  dev->name, dev);
-	if (ret) {
-		pr_err("%s: couldn't get irq %d\n", dev->name, dev->irq);
-		elmc_id_reset586();
-		return ret;
-	}
-	alloc586(dev);
-	init586(dev);
-	startrecv586(dev);
-	netif_start_queue(dev);
-	return 0;		/* most done by init */
-}
-
-/**********************************************
- * Check to see if there's an 82586 out there.
- */
-
-static int __init check586(struct net_device *dev, unsigned long where, unsigned size)
-{
-	struct priv *p = netdev_priv(dev);
-	char *iscp_addrs[2];
-	int i = 0;
-
-	p->base = (unsigned long) isa_bus_to_virt((unsigned long)where) + size - 0x01000000;
-	p->memtop = isa_bus_to_virt((unsigned long)where) + size;
-	p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
-	memset((char *) p->scp, 0, sizeof(struct scp_struct));
-	p->scp->sysbus = SYSBUSVAL;	/* 1 = 8Bit-Bus, 0 = 16 Bit */
-
-	iscp_addrs[0] = isa_bus_to_virt((unsigned long)where);
-	iscp_addrs[1] = (char *) p->scp - sizeof(struct iscp_struct);
-
-	for (i = 0; i < 2; i++) {
-		p->iscp = (struct iscp_struct *) iscp_addrs[i];
-		memset((char *) p->iscp, 0, sizeof(struct iscp_struct));
-
-		p->scp->iscp = make24(p->iscp);
-		p->iscp->busy = 1;
-
-		elmc_id_reset586();
-
-		/* reset586 does an implicit CA */
-
-		/* apparently, you sometimes have to kick the 82586 twice... */
-		elmc_id_attn586();
-		DELAY(1);
-
-		if (p->iscp->busy) {	/* i82586 clears 'busy' after successful init */
-			return 0;
-		}
-	}
-	return 1;
-}
-
-/******************************************************************
- * set iscp at the right place, called by elmc_probe and open586.
- */
-
-static void alloc586(struct net_device *dev)
-{
-	struct priv *p = netdev_priv(dev);
-
-	elmc_id_reset586();
-	DELAY(2);
-
-	p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS);
-	p->scb = (struct scb_struct *) isa_bus_to_virt(dev->mem_start);
-	p->iscp = (struct iscp_struct *) ((char *) p->scp - sizeof(struct iscp_struct));
-
-	memset((char *) p->iscp, 0, sizeof(struct iscp_struct));
-	memset((char *) p->scp, 0, sizeof(struct scp_struct));
-
-	p->scp->iscp = make24(p->iscp);
-	p->scp->sysbus = SYSBUSVAL;
-	p->iscp->scb_offset = make16(p->scb);
-
-	p->iscp->busy = 1;
-	elmc_id_reset586();
-	elmc_id_attn586();
-
-	DELAY(2);
-
-	if (p->iscp->busy)
-		pr_err("%s: Init-Problems (alloc).\n", dev->name);
-
-	memset((char *) p->scb, 0, sizeof(struct scb_struct));
-}
-
-/*****************************************************************/
-
-static int elmc_getinfo(char *buf, int slot, void *d)
-{
-	int len = 0;
-	struct net_device *dev = d;
-
-	if (dev == NULL)
-		return len;
-
-	len += sprintf(buf + len, "Revision: 0x%x\n",
-		       inb(dev->base_addr + ELMC_REVISION) & 0xf);
-	len += sprintf(buf + len, "IRQ: %d\n", dev->irq);
-	len += sprintf(buf + len, "IO Address: %#lx-%#lx\n", dev->base_addr,
-		       dev->base_addr + ELMC_IO_EXTENT);
-	len += sprintf(buf + len, "Memory: %#lx-%#lx\n", dev->mem_start,
-		       dev->mem_end - 1);
-	len += sprintf(buf + len, "Transceiver: %s\n", dev->if_port ?
-		       "External" : "Internal");
-	len += sprintf(buf + len, "Device: %s\n", dev->name);
-	len += sprintf(buf + len, "Hardware Address: %pM\n",
-		       dev->dev_addr);
-
-	return len;
-}				/* elmc_getinfo() */
-
-static const struct net_device_ops netdev_ops = {
-	.ndo_open 		= elmc_open,
-	.ndo_stop		= elmc_close,
-	.ndo_get_stats		= elmc_get_stats,
-	.ndo_start_xmit		= elmc_send_packet,
-	.ndo_tx_timeout		= elmc_timeout,
-#ifdef ELMC_MULTICAST
-	.ndo_set_multicast_list = set_multicast_list,
-#endif
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-/*****************************************************************/
-
-static int __init do_elmc_probe(struct net_device *dev)
-{
-	static int slot;
-	int base_addr = dev->base_addr;
-	int irq = dev->irq;
-	u_char status = 0;
-	u_char revision = 0;
-	int i = 0;
-	unsigned int size = 0;
-	int retval;
-	struct priv *pr = netdev_priv(dev);
-
-	if (MCA_bus == 0) {
-		return -ENODEV;
-	}
-	/* search through the slots for the 3c523. */
-	slot = mca_find_adapter(ELMC_MCA_ID, 0);
-	while (slot != -1) {
-		status = mca_read_stored_pos(slot, 2);
-
-		dev->irq=irq_table[(status & ELMC_STATUS_IRQ_SELECT) >> 6];
-		dev->base_addr=csr_table[(status & ELMC_STATUS_CSR_SELECT) >> 1];
-
-		/*
-		   If we're trying to match a specified irq or IO address,
-		   we'll reject a match unless it's what we're looking for.
-		   Also reject it if the card is already in use.
-		 */
-
-		if ((irq && irq != dev->irq) ||
-		    (base_addr && base_addr != dev->base_addr)) {
-			slot = mca_find_adapter(ELMC_MCA_ID, slot + 1);
-			continue;
-		}
-		if (!request_region(dev->base_addr, ELMC_IO_EXTENT, DRV_NAME)) {
-			slot = mca_find_adapter(ELMC_MCA_ID, slot + 1);
-			continue;
-		}
-
-		/* found what we're looking for... */
-		break;
-	}
-
-	/* we didn't find any 3c523 in the slots we checked for */
-	if (slot == MCA_NOTFOUND)
-		return (base_addr || irq) ? -ENXIO : -ENODEV;
-
-	mca_set_adapter_name(slot, "3Com 3c523 Etherlink/MC");
-	mca_set_adapter_procfn(slot, (MCA_ProcFn) elmc_getinfo, dev);
-
-	/* if we get this far, adapter has been found - carry on */
-	pr_info("%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1);
-
-	/* Now we extract configuration info from the card.
-	   The 3c523 provides information in two of the POS registers, but
-	   the second one is only needed if we want to tell the card what IRQ
-	   to use.  I suspect that whoever sets the thing up initially would
-	   prefer we don't screw with those things.
-
-	   Note that we read the status info when we found the card...
-
-	   See 3c523.h for more details.
-	 */
-
-	/* revision is stored in the first 4 bits of the revision register */
-	revision = inb(dev->base_addr + ELMC_REVISION) & 0xf;
-
-	/* according to docs, we read the interrupt and write it back to
-	   the IRQ select register, since the POST might not configure the IRQ
-	   properly. */
-	switch (dev->irq) {
-	case 3:
-		mca_write_pos(slot, 3, 0x04);
-		break;
-	case 7:
-		mca_write_pos(slot, 3, 0x02);
-		break;
-	case 9:
-		mca_write_pos(slot, 3, 0x08);
-		break;
-	case 12:
-		mca_write_pos(slot, 3, 0x01);
-		break;
-	}
-
-	pr->slot = slot;
-
-	pr_info("%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision,
-	       dev->base_addr);
-
-	/* Determine if we're using the on-board transceiver (i.e. coax) or
-	   an external one.  The information is pretty much useless, but I
-	   guess it's worth brownie points. */
-	dev->if_port = (status & ELMC_STATUS_DISABLE_THIN);
-
-	/* The 3c523 has a 24K chunk of memory.  The first 16K is the
-	   shared memory, while the last 8K is for the EtherStart BIOS ROM.
-	   Which we don't care much about here.  We'll just tell Linux that
-	   we're using 16K.  MCA won't permit address space conflicts caused
-	   by not mapping the other 8K. */
-	dev->mem_start = shm_table[(status & ELMC_STATUS_MEMORY_SELECT) >> 3];
-
-	/* We're using MCA, so it's a given that the information about memory
-	   size is correct.  The Crynwr drivers do something like this. */
-
-	elmc_id_reset586();	/* seems like a good idea before checking it... */
-
-	size = 0x4000;		/* check for 16K mem */
-	if (!check586(dev, dev->mem_start, size)) {
-		pr_err("%s: memprobe, Can't find memory at 0x%lx!\n", dev->name,
-		       dev->mem_start);
-		retval = -ENODEV;
-		goto err_out;
-	}
-	dev->mem_end = dev->mem_start + size;	/* set mem_end showed by 'ifconfig' */
-
-	pr->memtop = isa_bus_to_virt(dev->mem_start) + size;
-	pr->base = (unsigned long) isa_bus_to_virt(dev->mem_start) + size - 0x01000000;
-	alloc586(dev);
-
-	elmc_id_reset586();	/* make sure it doesn't generate spurious ints */
-
-	/* set number of receive-buffs according to memsize */
-	pr->num_recv_buffs = NUM_RECV_BUFFS_16;
-
-	/* dump all the assorted information */
-	pr_info("%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name,
-	       dev->irq, dev->if_port ? "ex" : "in",
-	       dev->mem_start, dev->mem_end - 1);
-
-	/* The hardware address for the 3c523 is stored in the first six
-	   bytes of the IO address. */
-	for (i = 0; i < 6; i++)
-		dev->dev_addr[i] = inb(dev->base_addr + i);
-
-	pr_info("%s: hardware address %pM\n",
-	       dev->name, dev->dev_addr);
-
-	dev->netdev_ops = &netdev_ops;
-	dev->watchdog_timeo = HZ;
-	dev->ethtool_ops = &netdev_ethtool_ops;
-
-	/* note that we haven't actually requested the IRQ from the kernel.
-	   That gets done in elmc_open().  I'm not sure that's such a good idea,
-	   but it works, so I'll go with it. */
-
-#ifndef ELMC_MULTICAST
-        dev->flags&=~IFF_MULTICAST;     /* Multicast doesn't work */
-#endif
-
-	retval = register_netdev(dev);
-	if (retval)
-		goto err_out;
-
-	return 0;
-err_out:
-	mca_set_adapter_procfn(slot, NULL, NULL);
-	release_region(dev->base_addr, ELMC_IO_EXTENT);
-	return retval;
-}
-
-#ifdef MODULE
-static void cleanup_card(struct net_device *dev)
-{
-	mca_set_adapter_procfn(((struct priv *)netdev_priv(dev))->slot,
-				NULL, NULL);
-	release_region(dev->base_addr, ELMC_IO_EXTENT);
-}
-#else
-struct net_device * __init elmc_probe(int unit)
-{
-	struct net_device *dev = alloc_etherdev(sizeof(struct priv));
-	int err;
-
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	sprintf(dev->name, "eth%d", unit);
-	netdev_boot_setup_check(dev);
-
-	err = do_elmc_probe(dev);
-	if (err)
-		goto out;
-	return dev;
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-#endif
-
-/**********************************************
- * init the chip (elmc-interrupt should be disabled?!)
- * needs a correct 'allocated' memory
- */
-
-static int init586(struct net_device *dev)
-{
-	void *ptr;
-	unsigned long s;
-	int i, result = 0;
-	struct priv *p = netdev_priv(dev);
-	volatile struct configure_cmd_struct *cfg_cmd;
-	volatile struct iasetup_cmd_struct *ias_cmd;
-	volatile struct tdr_cmd_struct *tdr_cmd;
-	volatile struct mcsetup_cmd_struct *mc_cmd;
-	struct netdev_hw_addr *ha;
-	int num_addrs = netdev_mc_count(dev);
-
-	ptr = (void *) ((char *) p->scb + sizeof(struct scb_struct));
-
-	cfg_cmd = (struct configure_cmd_struct *) ptr;	/* configure-command */
-	cfg_cmd->cmd_status = 0;
-	cfg_cmd->cmd_cmd = CMD_CONFIGURE | CMD_LAST;
-	cfg_cmd->cmd_link = 0xffff;
-
-	cfg_cmd->byte_cnt = 0x0a;	/* number of cfg bytes */
-	cfg_cmd->fifo = 0x08;	/* fifo-limit (8=tx:32/rx:64) */
-	cfg_cmd->sav_bf = 0x40;	/* hold or discard bad recv frames (bit 7) */
-	cfg_cmd->adr_len = 0x2e;	/* addr_len |!src_insert |pre-len |loopback */
-	cfg_cmd->priority = 0x00;
-	cfg_cmd->ifs = 0x60;
-	cfg_cmd->time_low = 0x00;
-	cfg_cmd->time_high = 0xf2;
-	cfg_cmd->promisc = 0;
-	if (dev->flags & (IFF_ALLMULTI | IFF_PROMISC))
-		cfg_cmd->promisc = 1;
-	cfg_cmd->carr_coll = 0x00;
-
-	p->scb->cbl_offset = make16(cfg_cmd);
-
-	p->scb->cmd = CUC_START;	/* cmd.-unit start */
-	elmc_id_attn586();
-
-	s = jiffies;		/* warning: only active with interrupts on !! */
-	while (!(cfg_cmd->cmd_status & STAT_COMPL)) {
-		if (time_after(jiffies, s + 30*HZ/100))
-			break;
-	}
-
-	if ((cfg_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_COMPL | STAT_OK)) {
-		pr_warning("%s (elmc): configure command failed: %x\n", dev->name, cfg_cmd->cmd_status);
-		return 1;
-	}
-	/*
-	 * individual address setup
-	 */
-	ias_cmd = (struct iasetup_cmd_struct *) ptr;
-
-	ias_cmd->cmd_status = 0;
-	ias_cmd->cmd_cmd = CMD_IASETUP | CMD_LAST;
-	ias_cmd->cmd_link = 0xffff;
-
-	memcpy((char *) &ias_cmd->iaddr, (char *) dev->dev_addr, ETH_ALEN);
-
-	p->scb->cbl_offset = make16(ias_cmd);
-
-	p->scb->cmd = CUC_START;	/* cmd.-unit start */
-	elmc_id_attn586();
-
-	s = jiffies;
-	while (!(ias_cmd->cmd_status & STAT_COMPL)) {
-		if (time_after(jiffies, s + 30*HZ/100))
-			break;
-	}
-
-	if ((ias_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_OK | STAT_COMPL)) {
-		pr_warning("%s (elmc): individual address setup command failed: %04x\n",
-			dev->name, ias_cmd->cmd_status);
-		return 1;
-	}
-	/*
-	 * TDR, wire check .. e.g. no resistor e.t.c
-	 */
-	tdr_cmd = (struct tdr_cmd_struct *) ptr;
-
-	tdr_cmd->cmd_status = 0;
-	tdr_cmd->cmd_cmd = CMD_TDR | CMD_LAST;
-	tdr_cmd->cmd_link = 0xffff;
-	tdr_cmd->status = 0;
-
-	p->scb->cbl_offset = make16(tdr_cmd);
-
-	p->scb->cmd = CUC_START;	/* cmd.-unit start */
-	elmc_attn586();
-
-	s = jiffies;
-	while (!(tdr_cmd->cmd_status & STAT_COMPL)) {
-		if (time_after(jiffies, s + 30*HZ/100)) {
-			pr_warning("%s: %d Problems while running the TDR.\n", dev->name, __LINE__);
-			result = 1;
-			break;
-		}
-	}
-
-	if (!result) {
-		DELAY(2);	/* wait for result */
-		result = tdr_cmd->status;
-
-		p->scb->cmd = p->scb->status & STAT_MASK;
-		elmc_id_attn586();	/* ack the interrupts */
-
-		if (result & TDR_LNK_OK) {
-			/* empty */
-		} else if (result & TDR_XCVR_PRB) {
-			pr_warning("%s: TDR: Transceiver problem!\n", dev->name);
-		} else if (result & TDR_ET_OPN) {
-			pr_warning("%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
-		} else if (result & TDR_ET_SRT) {
-			if (result & TDR_TIMEMASK)	/* time == 0 -> strange :-) */
-				pr_warning("%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
-		} else {
-			pr_warning("%s: TDR: Unknown status %04x\n", dev->name, result);
-		}
-	}
-	/*
-	 * ack interrupts
-	 */
-	p->scb->cmd = p->scb->status & STAT_MASK;
-	elmc_id_attn586();
-
-	/*
-	 * alloc nop/xmit-cmds
-	 */
-#if (NUM_XMIT_BUFFS == 1)
-	for (i = 0; i < 2; i++) {
-		p->nop_cmds[i] = (struct nop_cmd_struct *) ptr;
-		p->nop_cmds[i]->cmd_cmd = CMD_NOP;
-		p->nop_cmds[i]->cmd_status = 0;
-		p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i]));
-		ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
-	}
-	p->xmit_cmds[0] = (struct transmit_cmd_struct *) ptr;	/* transmit cmd/buff 0 */
-	ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);
-#else
-	for (i = 0; i < NUM_XMIT_BUFFS; i++) {
-		p->nop_cmds[i] = (struct nop_cmd_struct *) ptr;
-		p->nop_cmds[i]->cmd_cmd = CMD_NOP;
-		p->nop_cmds[i]->cmd_status = 0;
-		p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i]));
-		ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
-		p->xmit_cmds[i] = (struct transmit_cmd_struct *) ptr;	/*transmit cmd/buff 0 */
-		ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);
-	}
-#endif
-
-	ptr = alloc_rfa(dev, (void *) ptr);	/* init receive-frame-area */
-
-	/*
-	 * Multicast setup
-	 */
-
-	if (num_addrs) {
-		/* I don't understand this: do we really need memory after the init? */
-		int len = ((char *) p->iscp - (char *) ptr - 8) / 6;
-		if (len <= 0) {
-			pr_err("%s: Ooooops, no memory for MC-Setup!\n", dev->name);
-		} else {
-			if (len < num_addrs) {
-				num_addrs = len;
-				pr_warning("%s: Sorry, can only apply %d MC-Address(es).\n",
-				       dev->name, num_addrs);
-			}
-			mc_cmd = (struct mcsetup_cmd_struct *) ptr;
-			mc_cmd->cmd_status = 0;
-			mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST;
-			mc_cmd->cmd_link = 0xffff;
-			mc_cmd->mc_cnt = num_addrs * 6;
-			i = 0;
-			netdev_for_each_mc_addr(ha, dev)
-				memcpy((char *) mc_cmd->mc_list[i++],
-				       ha->addr, 6);
-			p->scb->cbl_offset = make16(mc_cmd);
-			p->scb->cmd = CUC_START;
-			elmc_id_attn586();
-			s = jiffies;
-			while (!(mc_cmd->cmd_status & STAT_COMPL)) {
-				if (time_after(jiffies, s + 30*HZ/100))
-					break;
-			}
-			if (!(mc_cmd->cmd_status & STAT_COMPL)) {
-				pr_warning("%s: Can't apply multicast-address-list.\n", dev->name);
-			}
-		}
-	}
-	/*
-	 * alloc xmit-buffs / init xmit_cmds
-	 */
-	for (i = 0; i < NUM_XMIT_BUFFS; i++) {
-		p->xmit_cbuffs[i] = (char *) ptr;	/* char-buffs */
-		ptr = (char *) ptr + XMIT_BUFF_SIZE;
-		p->xmit_buffs[i] = (struct tbd_struct *) ptr;	/* TBD */
-		ptr = (char *) ptr + sizeof(struct tbd_struct);
-		if ((void *) ptr > (void *) p->iscp) {
-			pr_err("%s: not enough shared-mem for your configuration!\n", dev->name);
-			return 1;
-		}
-		memset((char *) (p->xmit_cmds[i]), 0, sizeof(struct transmit_cmd_struct));
-		memset((char *) (p->xmit_buffs[i]), 0, sizeof(struct tbd_struct));
-		p->xmit_cmds[i]->cmd_status = STAT_COMPL;
-		p->xmit_cmds[i]->cmd_cmd = CMD_XMIT | CMD_INT;
-		p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i]));
-		p->xmit_buffs[i]->next = 0xffff;
-		p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i]));
-	}
-
-	p->xmit_count = 0;
-	p->xmit_last = 0;
-#ifndef NO_NOPCOMMANDS
-	p->nop_point = 0;
-#endif
-
-	/*
-	 * 'start transmitter' (nop-loop)
-	 */
-#ifndef NO_NOPCOMMANDS
-	p->scb->cbl_offset = make16(p->nop_cmds[0]);
-	p->scb->cmd = CUC_START;
-	elmc_id_attn586();
-	WAIT_4_SCB_CMD();
-#else
-	p->xmit_cmds[0]->cmd_link = 0xffff;
-	p->xmit_cmds[0]->cmd_cmd = CMD_XMIT | CMD_LAST | CMD_INT;
-#endif
-
-	return 0;
-}
-
-/******************************************************
- * This is a helper routine for elmc_rnr_int() and init586().
- * It sets up the Receive Frame Area (RFA).
- */
-
-static void *alloc_rfa(struct net_device *dev, void *ptr)
-{
-	volatile struct rfd_struct *rfd = (struct rfd_struct *) ptr;
-	volatile struct rbd_struct *rbd;
-	int i;
-	struct priv *p = netdev_priv(dev);
-
-	memset((char *) rfd, 0, sizeof(struct rfd_struct) * p->num_recv_buffs);
-	p->rfd_first = rfd;
-
-	for (i = 0; i < p->num_recv_buffs; i++) {
-		rfd[i].next = make16(rfd + (i + 1) % p->num_recv_buffs);
-	}
-	rfd[p->num_recv_buffs - 1].last = RFD_SUSP;	/* RU suspend */
-
-	ptr = (void *) (rfd + p->num_recv_buffs);
-
-	rbd = (struct rbd_struct *) ptr;
-	ptr = (void *) (rbd + p->num_recv_buffs);
-
-	/* clr descriptors */
-	memset((char *) rbd, 0, sizeof(struct rbd_struct) * p->num_recv_buffs);
-
-	for (i = 0; i < p->num_recv_buffs; i++) {
-		rbd[i].next = make16((rbd + (i + 1) % p->num_recv_buffs));
-		rbd[i].size = RECV_BUFF_SIZE;
-		rbd[i].buffer = make24(ptr);
-		ptr = (char *) ptr + RECV_BUFF_SIZE;
-	}
-
-	p->rfd_top = p->rfd_first;
-	p->rfd_last = p->rfd_first + p->num_recv_buffs - 1;
-
-	p->scb->rfa_offset = make16(p->rfd_first);
-	p->rfd_first->rbd_offset = make16(rbd);
-
-	return ptr;
-}
-
-
-/**************************************************
- * Interrupt Handler ...
- */
-
-static irqreturn_t
-elmc_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	unsigned short stat;
-	struct priv *p;
-
-	if (!netif_running(dev)) {
-		/* The 3c523 has this habit of generating interrupts during the
-		   reset.  I'm not sure if the ni52 has this same problem, but it's
-		   really annoying if we haven't finished initializing it.  I was
-		   hoping all the elmc_id_* commands would disable this, but I
-		   might have missed a few. */
-
-		elmc_id_attn586();	/* ack inter. and disable any more */
-		return IRQ_HANDLED;
-	} else if (!(ELMC_CTRL_INT & inb(dev->base_addr + ELMC_CTRL))) {
-		/* wasn't this device */
-		return IRQ_NONE;
-	}
-	/* reading ELMC_CTRL also clears the INT bit. */
-
-	p = netdev_priv(dev);
-
-	while ((stat = p->scb->status & STAT_MASK))
-	{
-		p->scb->cmd = stat;
-		elmc_attn586();	/* ack inter. */
-
-		if (stat & STAT_CX) {
-			/* command with I-bit set complete */
-			elmc_xmt_int(dev);
-		}
-		if (stat & STAT_FR) {
-			/* received a frame */
-			elmc_rcv_int(dev);
-		}
-#ifndef NO_NOPCOMMANDS
-		if (stat & STAT_CNA) {
-			/* CU went 'not ready' */
-			if (netif_running(dev)) {
-				pr_warning("%s: oops! CU has left active state. stat: %04x/%04x.\n",
-					dev->name, (int) stat, (int) p->scb->status);
-			}
-		}
-#endif
-
-		if (stat & STAT_RNR) {
-			/* RU went 'not ready' */
-
-			if (p->scb->status & RU_SUSPEND) {
-				/* special case: RU_SUSPEND */
-
-				WAIT_4_SCB_CMD();
-				p->scb->cmd = RUC_RESUME;
-				elmc_attn586();
-			} else {
-				pr_warning("%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n",
-					dev->name, (int) stat, (int) p->scb->status);
-				elmc_rnr_int(dev);
-			}
-		}
-		WAIT_4_SCB_CMD();	/* wait for ack. (elmc_xmt_int can be faster than ack!!) */
-		if (p->scb->cmd) {	/* timed out? */
-			break;
-		}
-	}
-	return IRQ_HANDLED;
-}
-
-/*******************************************************
- * receive-interrupt
- */
-
-static void elmc_rcv_int(struct net_device *dev)
-{
-	int status;
-	unsigned short totlen;
-	struct sk_buff *skb;
-	struct rbd_struct *rbd;
-	struct priv *p = netdev_priv(dev);
-
-	for (; (status = p->rfd_top->status) & STAT_COMPL;) {
-		rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset);
-
-		if (status & STAT_OK) {		/* frame received without error? */
-			if ((totlen = rbd->status) & RBD_LAST) {	/* the first and the last buffer? */
-				totlen &= RBD_MASK;	/* length of this frame */
-				rbd->status = 0;
-				skb = (struct sk_buff *) dev_alloc_skb(totlen + 2);
-				if (skb != NULL) {
-					skb_reserve(skb, 2);	/* 16 byte alignment */
-					skb_put(skb,totlen);
-					skb_copy_to_linear_data(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen);
-					skb->protocol = eth_type_trans(skb, dev);
-					netif_rx(skb);
-					dev->stats.rx_packets++;
-					dev->stats.rx_bytes += totlen;
-				} else {
-					dev->stats.rx_dropped++;
-				}
-			} else {
-				pr_warning("%s: received oversized frame.\n", dev->name);
-				dev->stats.rx_dropped++;
-			}
-		} else {	/* frame !(ok), only with 'save-bad-frames' */
-			pr_warning("%s: oops! rfd-error-status: %04x\n", dev->name, status);
-			dev->stats.rx_errors++;
-		}
-		p->rfd_top->status = 0;
-		p->rfd_top->last = RFD_SUSP;
-		p->rfd_last->last = 0;	/* delete RU_SUSP  */
-		p->rfd_last = p->rfd_top;
-		p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next);	/* step to next RFD */
-	}
-}
-
-/**********************************************************
- * handle 'Receiver went not ready'.
- */
-
-static void elmc_rnr_int(struct net_device *dev)
-{
-	struct priv *p = netdev_priv(dev);
-
-	dev->stats.rx_errors++;
-
-	WAIT_4_SCB_CMD();	/* wait for the last cmd */
-	p->scb->cmd = RUC_ABORT;	/* usually the RU is in the 'no resource'-state .. abort it now. */
-	elmc_attn586();
-	WAIT_4_SCB_CMD();	/* wait for accept cmd. */
-
-	alloc_rfa(dev, (char *) p->rfd_first);
-	startrecv586(dev);	/* restart RU */
-
-	pr_warning("%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status);
-
-}
-
-/**********************************************************
- * handle xmit - interrupt
- */
-
-static void elmc_xmt_int(struct net_device *dev)
-{
-	int status;
-	struct priv *p = netdev_priv(dev);
-
-	status = p->xmit_cmds[p->xmit_last]->cmd_status;
-	if (!(status & STAT_COMPL)) {
-		pr_warning("%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name);
-	}
-	if (status & STAT_OK) {
-		dev->stats.tx_packets++;
-		dev->stats.collisions += (status & TCMD_MAXCOLLMASK);
-	} else {
-		dev->stats.tx_errors++;
-		if (status & TCMD_LATECOLL) {
-			pr_warning("%s: late collision detected.\n", dev->name);
-			dev->stats.collisions++;
-		} else if (status & TCMD_NOCARRIER) {
-			dev->stats.tx_carrier_errors++;
-			pr_warning("%s: no carrier detected.\n", dev->name);
-		} else if (status & TCMD_LOSTCTS) {
-			pr_warning("%s: loss of CTS detected.\n", dev->name);
-		} else if (status & TCMD_UNDERRUN) {
-			dev->stats.tx_fifo_errors++;
-			pr_warning("%s: DMA underrun detected.\n", dev->name);
-		} else if (status & TCMD_MAXCOLL) {
-			pr_warning("%s: Max. collisions exceeded.\n", dev->name);
-			dev->stats.collisions += 16;
-		}
-	}
-
-#if (NUM_XMIT_BUFFS != 1)
-	if ((++p->xmit_last) == NUM_XMIT_BUFFS) {
-		p->xmit_last = 0;
-	}
-#endif
-
-	netif_wake_queue(dev);
-}
-
-/***********************************************************
- * (re)start the receiver
- */
-
-static void startrecv586(struct net_device *dev)
-{
-	struct priv *p = netdev_priv(dev);
-
-	p->scb->rfa_offset = make16(p->rfd_first);
-	p->scb->cmd = RUC_START;
-	elmc_attn586();		/* start cmd. */
-	WAIT_4_SCB_CMD();	/* wait for accept cmd. (no timeout!!) */
-}
-
-/******************************************************
- * timeout
- */
-
-static void elmc_timeout(struct net_device *dev)
-{
-	struct priv *p = netdev_priv(dev);
-	/* COMMAND-UNIT active? */
-	if (p->scb->status & CU_ACTIVE) {
-		pr_debug("%s: strange ... timeout with CU active?!?\n", dev->name);
-		pr_debug("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name,
-			(int)p->xmit_cmds[0]->cmd_status,
-			(int)p->nop_cmds[0]->cmd_status,
-			(int)p->nop_cmds[1]->cmd_status, (int)p->nop_point);
-		p->scb->cmd = CUC_ABORT;
-		elmc_attn586();
-		WAIT_4_SCB_CMD();
-		p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);
-		p->scb->cmd = CUC_START;
-		elmc_attn586();
-		WAIT_4_SCB_CMD();
-		netif_wake_queue(dev);
-	} else {
-		pr_debug("%s: xmitter timed out, try to restart! stat: %04x\n",
-			dev->name, p->scb->status);
-		pr_debug("%s: command-stats: %04x %04x\n", dev->name,
-			p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status);
-		elmc_close(dev);
-		elmc_open(dev);
-	}
-}
-
-/******************************************************
- * send frame
- */
-
-static netdev_tx_t elmc_send_packet(struct sk_buff *skb, struct net_device *dev)
-{
-	int len;
-	int i;
-#ifndef NO_NOPCOMMANDS
-	int next_nop;
-#endif
-	struct priv *p = netdev_priv(dev);
-
-	netif_stop_queue(dev);
-
-	len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
-
-	if (len != skb->len)
-		memset((char *) p->xmit_cbuffs[p->xmit_count], 0, ETH_ZLEN);
-	skb_copy_from_linear_data(skb, (char *) p->xmit_cbuffs[p->xmit_count], skb->len);
-
-#if (NUM_XMIT_BUFFS == 1)
-#ifdef NO_NOPCOMMANDS
-	p->xmit_buffs[0]->size = TBD_LAST | len;
-	for (i = 0; i < 16; i++) {
-		p->scb->cbl_offset = make16(p->xmit_cmds[0]);
-		p->scb->cmd = CUC_START;
-		p->xmit_cmds[0]->cmd_status = 0;
-			elmc_attn586();
-		if (!i) {
-			dev_kfree_skb(skb);
-		}
-		WAIT_4_SCB_CMD();
-		if ((p->scb->status & CU_ACTIVE)) {	/* test it, because CU sometimes doesn't start immediately */
-			break;
-		}
-		if (p->xmit_cmds[0]->cmd_status) {
-			break;
-		}
-		if (i == 15) {
-			pr_warning("%s: Can't start transmit-command.\n", dev->name);
-		}
-	}
-#else
-	next_nop = (p->nop_point + 1) & 0x1;
-	p->xmit_buffs[0]->size = TBD_LAST | len;
-
-	p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link
-	    = make16((p->nop_cmds[next_nop]));
-	p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0;
-
-	p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0]));
-	p->nop_point = next_nop;
-	dev_kfree_skb(skb);
-#endif
-#else
-	p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len;
-	if ((next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS) {
-		next_nop = 0;
-	}
-	p->xmit_cmds[p->xmit_count]->cmd_status = 0;
-	p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link
-	    = make16((p->nop_cmds[next_nop]));
-	p->nop_cmds[next_nop]->cmd_status = 0;
-		p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count]));
-	p->xmit_count = next_nop;
-	if (p->xmit_count != p->xmit_last)
-		netif_wake_queue(dev);
-	dev_kfree_skb(skb);
-#endif
-	return NETDEV_TX_OK;
-}
-
-/*******************************************
- * Someone wanna have the statistics
- */
-
-static struct net_device_stats *elmc_get_stats(struct net_device *dev)
-{
-	struct priv *p = netdev_priv(dev);
-	unsigned short crc, aln, rsc, ovrn;
-
-	crc = p->scb->crc_errs;	/* get error-statistic from the ni82586 */
-	p->scb->crc_errs -= crc;
-	aln = p->scb->aln_errs;
-	p->scb->aln_errs -= aln;
-	rsc = p->scb->rsc_errs;
-	p->scb->rsc_errs -= rsc;
-	ovrn = p->scb->ovrn_errs;
-	p->scb->ovrn_errs -= ovrn;
-
-	dev->stats.rx_crc_errors += crc;
-	dev->stats.rx_fifo_errors += ovrn;
-	dev->stats.rx_frame_errors += aln;
-	dev->stats.rx_dropped += rsc;
-
-	return &dev->stats;
-}
-
-/********************************************************
- * Set MC list ..
- */
-
-#ifdef ELMC_MULTICAST
-static void set_multicast_list(struct net_device *dev)
-{
-	if (!dev->start) {
-		/* without a running interface, promiscuous doesn't work */
-		return;
-	}
-	dev->start = 0;
-	alloc586(dev);
-	init586(dev);
-	startrecv586(dev);
-	dev->start = 1;
-}
-#endif
-
-static void netdev_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-	sprintf(info->bus_info, "MCA 0x%lx", dev->base_addr);
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-	.get_drvinfo		= netdev_get_drvinfo,
-};
-
-#ifdef MODULE
-
-/* Increase if needed ;) */
-#define MAX_3C523_CARDS 4
-
-static struct net_device *dev_elmc[MAX_3C523_CARDS];
-static int irq[MAX_3C523_CARDS];
-static int io[MAX_3C523_CARDS];
-module_param_array(irq, int, NULL, 0);
-module_param_array(io, int, NULL, 0);
-MODULE_PARM_DESC(io, "EtherLink/MC I/O base address(es)");
-MODULE_PARM_DESC(irq, "EtherLink/MC IRQ number(s)");
-MODULE_LICENSE("GPL");
-
-int __init init_module(void)
-{
-	int this_dev,found = 0;
-
-	/* Loop until we either can't find any more cards, or we have MAX_3C523_CARDS */
-	for(this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) {
-		struct net_device *dev = alloc_etherdev(sizeof(struct priv));
-		if (!dev)
-			break;
-		dev->irq=irq[this_dev];
-		dev->base_addr=io[this_dev];
-		if (do_elmc_probe(dev) == 0) {
-			dev_elmc[this_dev] = dev;
-			found++;
-			continue;
-		}
-		free_netdev(dev);
-		if (io[this_dev]==0)
-			break;
-		pr_warning("3c523.c: No 3c523 card found at io=%#x\n",io[this_dev]);
-	}
-
-	if(found==0) {
-		if (io[0]==0)
-			pr_notice("3c523.c: No 3c523 cards found\n");
-		return -ENXIO;
-	} else return 0;
-}
-
-void __exit cleanup_module(void)
-{
-	int this_dev;
-	for (this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) {
-		struct net_device *dev = dev_elmc[this_dev];
-		if (dev) {
-			unregister_netdev(dev);
-			cleanup_card(dev);
-			free_netdev(dev);
-		}
-	}
-}
-
-#endif				/* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/3c523.h linux-libre-3.2-gnu/drivers/net/3c523.h
--- linux-libre-3.1-gnu/drivers/net/3c523.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/3c523.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,355 +0,0 @@
-#ifndef _3c523_INCLUDE_
-#define _3c523_INCLUDE_
-/*
-	This is basically a hacked version of ni52.h, for the 3c523
-	Etherlink/MC.
-*/
-
-/*
- * Intel i82586 Ethernet definitions
- *
- * This is an extension to the Linux operating system, and is covered by the
- * same GNU General Public License that covers that work.
- *
- * Copyright 1995 by Chris Beauregard (cpbeaure@undergrad.math.uwaterloo.ca)
- *
- * See 3c523.c for details.
- *
- * $Header: /home/chrisb/linux-1.2.13-3c523/drivers/net/RCS/3c523.h,v 1.6 1996/01/20 05:09:00 chrisb Exp chrisb $
- */
-
-/*
- * where to find the System Configuration Pointer (SCP)
- */
-#define SCP_DEFAULT_ADDRESS 0xfffff4
-
-
-/*
- * System Configuration Pointer Struct
- */
-
-struct scp_struct
-{
-  unsigned short zero_dum0;	/* has to be zero */
-  unsigned char  sysbus;	/* 0=16Bit,1=8Bit */
-  unsigned char  zero_dum1;	/* has to be zero for 586 */
-  unsigned short zero_dum2;
-  unsigned short zero_dum3;
-  char          *iscp;		/* pointer to the iscp-block */
-};
-
-
-/*
- * Intermediate System Configuration Pointer (ISCP)
- */
-struct iscp_struct
-{
-  unsigned char  busy;          /* 586 clears after successful init */
-  unsigned char  zero_dummy;    /* hast to be zero */
-  unsigned short scb_offset;    /* pointeroffset to the scb_base */
-  char          *scb_base;      /* base-address of all 16-bit offsets */
-};
-
-/*
- * System Control Block (SCB)
- */
-struct scb_struct
-{
-  unsigned short status;        /* status word */
-  unsigned short cmd;           /* command word */
-  unsigned short cbl_offset;    /* pointeroffset, command block list */
-  unsigned short rfa_offset;    /* pointeroffset, receive frame area */
-  unsigned short crc_errs;      /* CRC-Error counter */
-  unsigned short aln_errs;      /* alignmenterror counter */
-  unsigned short rsc_errs;      /* Resourceerror counter */
-  unsigned short ovrn_errs;     /* OVerrunerror counter */
-};
-
-/*
- * possible command values for the command word
- */
-#define RUC_MASK	0x0070	/* mask for RU commands */
-#define RUC_NOP		0x0000	/* NOP-command */
-#define RUC_START	0x0010	/* start RU */
-#define RUC_RESUME	0x0020	/* resume RU after suspend */
-#define RUC_SUSPEND	0x0030	/* suspend RU */
-#define RUC_ABORT	0x0040	/* abort receiver operation immediately */
-
-#define CUC_MASK	0x0700	/* mask for CU command */
-#define CUC_NOP		0x0000	/* NOP-command */
-#define CUC_START	0x0100	/* start execution of 1. cmd on the CBL */
-#define CUC_RESUME	0x0200	/* resume after suspend */
-#define CUC_SUSPEND	0x0300	/* Suspend CU */
-#define CUC_ABORT	0x0400	/* abort command operation immediately */
-
-#define ACK_MASK	0xf000	/* mask for ACK command */
-#define ACK_CX		0x8000	/* acknowledges STAT_CX */
-#define ACK_FR		0x4000	/* ack. STAT_FR */
-#define ACK_CNA		0x2000	/* ack. STAT_CNA */
-#define ACK_RNR		0x1000	/* ack. STAT_RNR */
-
-/*
- * possible status values for the status word
- */
-#define STAT_MASK	0xf000	/* mask for cause of interrupt */
-#define STAT_CX		0x8000	/* CU finished cmd with its I bit set */
-#define STAT_FR		0x4000	/* RU finished receiving a frame */
-#define STAT_CNA	0x2000	/* CU left active state */
-#define STAT_RNR	0x1000	/* RU left ready state */
-
-#define CU_STATUS	0x700	/* CU status, 0=idle */
-#define CU_SUSPEND	0x100	/* CU is suspended */
-#define CU_ACTIVE	0x200	/* CU is active */
-
-#define RU_STATUS	0x70	/* RU status, 0=idle */
-#define RU_SUSPEND	0x10	/* RU suspended */
-#define RU_NOSPACE	0x20	/* RU no resources */
-#define RU_READY	0x40	/* RU is ready */
-
-/*
- * Receive Frame Descriptor (RFD)
- */
-struct rfd_struct
-{
-  unsigned short status;	/* status word */
-  unsigned short last;		/* Bit15,Last Frame on List / Bit14,suspend */
-  unsigned short next;		/* linkoffset to next RFD */
-  unsigned short rbd_offset;	/* pointeroffset to RBD-buffer */
-  unsigned char  dest[6];	/* ethernet-address, destination */
-  unsigned char  source[6];	/* ethernet-address, source */
-  unsigned short length;	/* 802.3 frame-length */
-  unsigned short zero_dummy;	/* dummy */
-};
-
-#define RFD_LAST     0x8000	/* last: last rfd in the list */
-#define RFD_SUSP     0x4000	/* last: suspend RU after  */
-#define RFD_ERRMASK  0x0fe1     /* status: errormask */
-#define RFD_MATCHADD 0x0002     /* status: Destinationaddress !matches IA */
-#define RFD_RNR      0x0200	/* status: receiver out of resources */
-
-/*
- * Receive Buffer Descriptor (RBD)
- */
-struct rbd_struct
-{
-  unsigned short status;	/* status word,number of used bytes in buff */
-  unsigned short next;		/* pointeroffset to next RBD */
-  char          *buffer;	/* receive buffer address pointer */
-  unsigned short size;		/* size of this buffer */
-  unsigned short zero_dummy;    /* dummy */
-};
-
-#define RBD_LAST	0x8000	/* last buffer */
-#define RBD_USED	0x4000	/* this buffer has data */
-#define RBD_MASK	0x3fff	/* size-mask for length */
-
-/*
- * Statusvalues for Commands/RFD
- */
-#define STAT_COMPL   0x8000	/* status: frame/command is complete */
-#define STAT_BUSY    0x4000	/* status: frame/command is busy */
-#define STAT_OK      0x2000	/* status: frame/command is ok */
-
-/*
- * Action-Commands
- */
-#define CMD_NOP		0x0000	/* NOP */
-#define CMD_IASETUP	0x0001	/* initial address setup command */
-#define CMD_CONFIGURE	0x0002	/* configure command */
-#define CMD_MCSETUP	0x0003	/* MC setup command */
-#define CMD_XMIT	0x0004	/* transmit command */
-#define CMD_TDR		0x0005	/* time domain reflectometer (TDR) command */
-#define CMD_DUMP	0x0006	/* dump command */
-#define CMD_DIAGNOSE	0x0007	/* diagnose command */
-
-/*
- * Action command bits
- */
-#define CMD_LAST	0x8000	/* indicates last command in the CBL */
-#define CMD_SUSPEND	0x4000	/* suspend CU after this CB */
-#define CMD_INT		0x2000	/* generate interrupt after execution */
-
-/*
- * NOP - command
- */
-struct nop_cmd_struct
-{
-  unsigned short cmd_status;	/* status of this command */
-  unsigned short cmd_cmd;       /* the command itself (+bits) */
-  unsigned short cmd_link;      /* offsetpointer to next command */
-};
-
-/*
- * IA Setup command
- */
-struct iasetup_cmd_struct
-{
-  unsigned short cmd_status;
-  unsigned short cmd_cmd;
-  unsigned short cmd_link;
-  unsigned char  iaddr[6];
-};
-
-/*
- * Configure command
- */
-struct configure_cmd_struct
-{
-  unsigned short cmd_status;
-  unsigned short cmd_cmd;
-  unsigned short cmd_link;
-  unsigned char  byte_cnt;   /* size of the config-cmd */
-  unsigned char  fifo;       /* fifo/recv monitor */
-  unsigned char  sav_bf;     /* save bad frames (bit7=1)*/
-  unsigned char  adr_len;    /* adr_len(0-2),al_loc(3),pream(4-5),loopbak(6-7)*/
-  unsigned char  priority;   /* lin_prio(0-2),exp_prio(4-6),bof_metd(7) */
-  unsigned char  ifs;        /* inter frame spacing */
-  unsigned char  time_low;   /* slot time low */
-  unsigned char  time_high;  /* slot time high(0-2) and max. retries(4-7) */
-  unsigned char  promisc;    /* promisc-mode(0) , et al (1-7) */
-  unsigned char  carr_coll;  /* carrier(0-3)/collision(4-7) stuff */
-  unsigned char  fram_len;   /* minimal frame len */
-  unsigned char  dummy;	     /* dummy */
-};
-
-/*
- * Multicast Setup command
- */
-struct mcsetup_cmd_struct
-{
-  unsigned short cmd_status;
-  unsigned short cmd_cmd;
-  unsigned short cmd_link;
-  unsigned short mc_cnt;		/* number of bytes in the MC-List */
-  unsigned char  mc_list[0][6];  	/* pointer to 6 bytes entries */
-};
-
-/*
- * transmit command
- */
-struct transmit_cmd_struct
-{
-  unsigned short cmd_status;
-  unsigned short cmd_cmd;
-  unsigned short cmd_link;
-  unsigned short tbd_offset;	/* pointeroffset to TBD */
-  unsigned char  dest[6];       /* destination address of the frame */
-  unsigned short length;	/* user defined: 802.3 length / Ether type */
-};
-
-#define TCMD_ERRMASK     0x0fa0
-#define TCMD_MAXCOLLMASK 0x000f
-#define TCMD_MAXCOLL     0x0020
-#define TCMD_HEARTBEAT   0x0040
-#define TCMD_DEFERRED    0x0080
-#define TCMD_UNDERRUN    0x0100
-#define TCMD_LOSTCTS     0x0200
-#define TCMD_NOCARRIER   0x0400
-#define TCMD_LATECOLL    0x0800
-
-struct tdr_cmd_struct
-{
-  unsigned short cmd_status;
-  unsigned short cmd_cmd;
-  unsigned short cmd_link;
-  unsigned short status;
-};
-
-#define TDR_LNK_OK	0x8000	/* No link problem identified */
-#define TDR_XCVR_PRB	0x4000	/* indicates a transceiver problem */
-#define TDR_ET_OPN	0x2000	/* open, no correct termination */
-#define TDR_ET_SRT	0x1000	/* TDR detected a short circuit */
-#define TDR_TIMEMASK	0x07ff	/* mask for the time field */
-
-/*
- * Transmit Buffer Descriptor (TBD)
- */
-struct tbd_struct
-{
-  unsigned short size;		/* size + EOF-Flag(15) */
-  unsigned short next;          /* pointeroffset to next TBD */
-  char          *buffer;        /* pointer to buffer */
-};
-
-#define TBD_LAST 0x8000         /* EOF-Flag, indicates last buffer in list */
-
-/*************************************************************************/
-/*
-Verbatim from the Crynwyr stuff:
-
-    The 3c523 responds with adapter code 0x6042 at slot
-registers xxx0 and xxx1.  The setup register is at xxx2 and
-contains the following bits:
-
-0: card enable
-2,1: csr address select
-    00 = 0300
-    01 = 1300
-    10 = 2300
-    11 = 3300
-4,3: shared memory address select
-    00 = 0c0000
-    01 = 0c8000
-    10 = 0d0000
-    11 = 0d8000
-5: set to disable on-board thinnet
-7,6: (read-only) shows selected irq
-    00 = 12
-    01 = 7
-    10 = 3
-    11 = 9
-
-The interrupt-select register is at xxx3 and uses one bit per irq.
-
-0: int 12
-1: int 7
-2: int 3
-3: int 9
-
-    Again, the documentation stresses that the setup register
-should never be written.  The interrupt-select register may be
-written with the value corresponding to bits 7.6 in
-the setup register to insure corret setup.
-*/
-
-/* Offsets from the base I/O address. */
-#define	ELMC_SA		0	/* first 6 bytes are IEEE network address */
-#define ELMC_CTRL	6	/* control & status register */
-#define ELMC_REVISION	7	/* revision register, first 4 bits only */
-#define ELMC_IO_EXTENT  8
-
-/* these are the bit selects for the port register 2 */
-#define ELMC_STATUS_ENABLED	0x01
-#define ELMC_STATUS_CSR_SELECT	0x06
-#define ELMC_STATUS_MEMORY_SELECT	0x18
-#define ELMC_STATUS_DISABLE_THIN	0x20
-#define ELMC_STATUS_IRQ_SELECT	0xc0
-
-/* this is the card id used in the detection code.  You might recognize
-it from @6042.adf */
-#define ELMC_MCA_ID 0x6042
-
-/*
-   The following define the bits for the control & status register
-
-   The bank select registers can be used if more than 16K of memory is
-   on the card.  For some stupid reason, bank 3 is the one for the
-   bottom 16K, and the card defaults to bank 0.  So we have to set the
-   bank to 3 before the card will even think of operating.  To get bank
-   3, set BS0 and BS1 to high (of course...)
-*/
-#define ELMC_CTRL_BS0	0x01	/* RW bank select */
-#define ELMC_CTRL_BS1	0x02	/* RW bank select */
-#define ELMC_CTRL_INTE	0x04	/* RW interrupt enable, assert high */
-#define ELMC_CTRL_INT	0x08	/* R interrupt active, assert high */
-/*#define ELMC_CTRL_*	0x10*/	/* reserved */
-#define ELMC_CTRL_LBK	0x20	/* RW loopback enable, assert high */
-#define ELMC_CTRL_CA	0x40	/* RW channel attention, assert high */
-#define ELMC_CTRL_RST	0x80	/* RW 82586 reset, assert low */
-
-/* some handy compound bits */
-
-/* normal operation should have bank 3 and RST high, ints enabled */
-#define ELMC_NORMAL (ELMC_CTRL_INTE|ELMC_CTRL_RST|0x3)
-
-#endif /* _3c523_INCLUDE_ */
diff -druN linux-libre-3.1-gnu/drivers/net/3c527.c linux-libre-3.2-gnu/drivers/net/3c527.c
--- linux-libre-3.1-gnu/drivers/net/3c527.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/3c527.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1661 +0,0 @@
-/* 3c527.c: 3Com Etherlink/MC32 driver for Linux 2.4 and 2.6.
- *
- *	(c) Copyright 1998 Red Hat Software Inc
- *	Written by Alan Cox.
- *	Further debugging by Carl Drougge.
- *      Initial SMP support by Felipe W Damasio <felipewd@terra.com.br>
- *      Heavily modified by Richard Procter <rnp@paradise.net.nz>
- *
- *	Based on skeleton.c written 1993-94 by Donald Becker and ne2.c
- *	(for the MCA stuff) written by Wim Dumon.
- *
- *	Thanks to 3Com for making this possible by providing me with the
- *	documentation.
- *
- *	This software may be used and distributed according to the terms
- *	of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#define DRV_NAME		"3c527"
-#define DRV_VERSION		"0.7-SMP"
-#define DRV_RELDATE		"2003/09/21"
-
-static const char *version =
-DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Richard Procter <rnp@paradise.net.nz>\n";
-
-/**
- * DOC: Traps for the unwary
- *
- *	The diagram (Figure 1-1) and the POS summary disagree with the
- *	"Interrupt Level" section in the manual.
- *
- *	The manual contradicts itself when describing the minimum number
- *	buffers in the 'configure lists' command.
- *	My card accepts a buffer config of 4/4.
- *
- *	Setting the SAV BP bit does not save bad packets, but
- *	only enables RX on-card stats collection.
- *
- *	The documentation in places seems to miss things. In actual fact
- *	I've always eventually found everything is documented, it just
- *	requires careful study.
- *
- * DOC: Theory Of Operation
- *
- *	The 3com 3c527 is a 32bit MCA bus mastering adapter with a large
- *	amount of on board intelligence that housekeeps a somewhat dumber
- *	Intel NIC. For performance we want to keep the transmit queue deep
- *	as the card can transmit packets while fetching others from main
- *	memory by bus master DMA. Transmission and reception are driven by
- *	circular buffer queues.
- *
- *	The mailboxes can be used for controlling how the card traverses
- *	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
- *	multicast lists.  We have to do a certain amount of interesting
- *	hoop jumping as the multicast list changes can occur in interrupt
- *	state when the card has an exec command pending. We defer such
- *	events until the command completion interrupt.
- *
- *	A copy break scheme (taken from 3c59x.c) is employed whereby
- *	received frames exceeding a configurable length are passed
- *	directly to the higher networking layers without incuring a copy,
- *	in what amounts to a time/space trade-off.
- *
- *	The card also keeps a large amount of statistical information
- *	on-board. In a perfect world, these could be used safely at no
- *	cost. However, lacking information to the contrary, processing
- *	them without races would involve so much extra complexity as to
- *	make it unworthwhile to do so. In the end, a hybrid SW/HW
- *	implementation was made necessary --- see mc32_update_stats().
- *
- * DOC: Notes
- *
- *	It should be possible to use two or more cards, but at this stage
- *	only by loading two copies of the same module.
- *
- *	The on-board 82586 NIC has trouble receiving multiple
- *	back-to-back frames and so is likely to drop packets from fast
- *	senders.
-**/
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_ether.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/mca-legacy.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/wait.h>
-#include <linux/ethtool.h>
-#include <linux/completion.h>
-#include <linux/bitops.h>
-#include <linux/semaphore.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#include "3c527.h"
-
-MODULE_LICENSE("GPL");
-
-/*
- * The name of the card. Is used for messages and in the requests for
- * io regions, irqs and dma channels
- */
-static const char* cardname = DRV_NAME;
-
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifndef NET_DEBUG
-#define NET_DEBUG 2
-#endif
-
-static unsigned int mc32_debug = NET_DEBUG;
-
-/* The number of low I/O ports used by the ethercard. */
-#define MC32_IO_EXTENT	8
-
-/* As implemented, values must be a power-of-2 -- 4/8/16/32 */
-#define TX_RING_LEN     32       /* Typically the card supports 37  */
-#define RX_RING_LEN     8        /*     "       "        "          */
-
-/* Copy break point, see above for details.
- * Setting to > 1512 effectively disables this feature.	*/
-#define RX_COPYBREAK    200      /* Value from 3c59x.c */
-
-/* Issue the 82586 workaround command - this is for "busy lans", but
- * basically means for all lans now days - has a performance (latency)
- * cost, but best set. */
-static const int WORKAROUND_82586=1;
-
-/* Pointers to buffers and their on-card records */
-struct mc32_ring_desc
-{
-	volatile struct skb_header *p;
-	struct sk_buff *skb;
-};
-
-/* Information that needs to be kept for each board. */
-struct mc32_local
-{
-	int slot;
-
-	u32 base;
-	volatile struct mc32_mailbox *rx_box;
-	volatile struct mc32_mailbox *tx_box;
-	volatile struct mc32_mailbox *exec_box;
-        volatile struct mc32_stats *stats;    /* Start of on-card statistics */
-        u16 tx_chain;           /* Transmit list start offset */
-	u16 rx_chain;           /* Receive list start offset */
-        u16 tx_len;             /* Transmit list count */
-        u16 rx_len;             /* Receive list count */
-
-	u16 xceiver_desired_state; /* HALTED or RUNNING */
-	u16 cmd_nonblocking;    /* Thread is uninterested in command result */
-	u16 mc_reload_wait;	/* A multicast load request is pending */
-	u32 mc_list_valid;	/* True when the mclist is set */
-
-	struct mc32_ring_desc tx_ring[TX_RING_LEN];	/* Host Transmit ring */
-	struct mc32_ring_desc rx_ring[RX_RING_LEN];	/* Host Receive ring */
-
-	atomic_t tx_count;	/* buffers left */
-	atomic_t tx_ring_head;  /* index to tx en-queue end */
-	u16 tx_ring_tail;       /* index to tx de-queue end */
-
-	u16 rx_ring_tail;       /* index to rx de-queue end */
-
-	struct semaphore cmd_mutex;    /* Serialises issuing of execute commands */
-        struct completion execution_cmd; /* Card has completed an execute command */
-	struct completion xceiver_cmd;   /* Card has completed a tx or rx command */
-};
-
-/* The station (ethernet) address prefix, used for a sanity check. */
-#define SA_ADDR0 0x02
-#define SA_ADDR1 0x60
-#define SA_ADDR2 0xAC
-
-struct mca_adapters_t {
-	unsigned int	id;
-	char		*name;
-};
-
-static const struct mca_adapters_t mc32_adapters[] = {
-	{ 0x0041, "3COM EtherLink MC/32" },
-	{ 0x8EF5, "IBM High Performance Lan Adapter" },
-	{ 0x0000, NULL }
-};
-
-
-/* Macros for ring index manipulations */
-static inline u16 next_rx(u16 rx) { return (rx+1)&(RX_RING_LEN-1); };
-static inline u16 prev_rx(u16 rx) { return (rx-1)&(RX_RING_LEN-1); };
-
-static inline u16 next_tx(u16 tx) { return (tx+1)&(TX_RING_LEN-1); };
-
-
-/* Index to functions, as function prototypes. */
-static int	mc32_probe1(struct net_device *dev, int ioaddr);
-static int      mc32_command(struct net_device *dev, u16 cmd, void *data, int len);
-static int	mc32_open(struct net_device *dev);
-static void	mc32_timeout(struct net_device *dev);
-static netdev_tx_t mc32_send_packet(struct sk_buff *skb,
-				    struct net_device *dev);
-static irqreturn_t mc32_interrupt(int irq, void *dev_id);
-static int	mc32_close(struct net_device *dev);
-static struct	net_device_stats *mc32_get_stats(struct net_device *dev);
-static void	mc32_set_multicast_list(struct net_device *dev);
-static void	mc32_reset_multicast_list(struct net_device *dev);
-static const struct ethtool_ops netdev_ethtool_ops;
-
-static void cleanup_card(struct net_device *dev)
-{
-	struct mc32_local *lp = netdev_priv(dev);
-	unsigned slot = lp->slot;
-	mca_mark_as_unused(slot);
-	mca_set_adapter_name(slot, NULL);
-	free_irq(dev->irq, dev);
-	release_region(dev->base_addr, MC32_IO_EXTENT);
-}
-
-/**
- * mc32_probe 	-	Search for supported boards
- * @unit: interface number to use
- *
- * Because MCA bus is a real bus and we can scan for cards we could do a
- * single scan for all boards here. Right now we use the passed in device
- * structure and scan for only one board. This needs fixing for modules
- * in particular.
- */
-
-struct net_device *__init mc32_probe(int unit)
-{
-	struct net_device *dev = alloc_etherdev(sizeof(struct mc32_local));
-	static int current_mca_slot = -1;
-	int i;
-	int err;
-
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	if (unit >= 0)
-		sprintf(dev->name, "eth%d", unit);
-
-	/* Do not check any supplied i/o locations.
-	   POS registers usually don't fail :) */
-
-	/* MCA cards have POS registers.
-	   Autodetecting MCA cards is extremely simple.
-	   Just search for the card. */
-
-	for(i = 0; (mc32_adapters[i].name != NULL); i++) {
-		current_mca_slot =
-			mca_find_unused_adapter(mc32_adapters[i].id, 0);
-
-		if(current_mca_slot != MCA_NOTFOUND) {
-			if(!mc32_probe1(dev, current_mca_slot))
-			{
-				mca_set_adapter_name(current_mca_slot,
-						mc32_adapters[i].name);
-				mca_mark_as_used(current_mca_slot);
-				err = register_netdev(dev);
-				if (err) {
-					cleanup_card(dev);
-					free_netdev(dev);
-					dev = ERR_PTR(err);
-				}
-				return dev;
-			}
-
-		}
-	}
-	free_netdev(dev);
-	return ERR_PTR(-ENODEV);
-}
-
-static const struct net_device_ops netdev_ops = {
-	.ndo_open		= mc32_open,
-	.ndo_stop		= mc32_close,
-	.ndo_start_xmit		= mc32_send_packet,
-	.ndo_get_stats		= mc32_get_stats,
-	.ndo_set_multicast_list = mc32_set_multicast_list,
-	.ndo_tx_timeout		= mc32_timeout,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-/**
- * mc32_probe1	-	Check a given slot for a board and test the card
- * @dev:  Device structure to fill in
- * @slot: The MCA bus slot being used by this card
- *
- * Decode the slot data and configure the card structures. Having done this we
- * can reset the card and configure it. The card does a full self test cycle
- * in firmware so we have to wait for it to return and post us either a
- * failure case or some addresses we use to find the board internals.
- */
-
-static int __init mc32_probe1(struct net_device *dev, int slot)
-{
-	static unsigned version_printed;
-	int i, err;
-	u8 POS;
-	u32 base;
-	struct mc32_local *lp = netdev_priv(dev);
-	static const u16 mca_io_bases[] = {
-		0x7280,0x7290,
-		0x7680,0x7690,
-		0x7A80,0x7A90,
-		0x7E80,0x7E90
-	};
-	static const u32 mca_mem_bases[] = {
-		0x00C0000,
-		0x00C4000,
-		0x00C8000,
-		0x00CC000,
-		0x00D0000,
-		0x00D4000,
-		0x00D8000,
-		0x00DC000
-	};
-	static const char * const failures[] = {
-		"Processor instruction",
-		"Processor data bus",
-		"Processor data bus",
-		"Processor data bus",
-		"Adapter bus",
-		"ROM checksum",
-		"Base RAM",
-		"Extended RAM",
-		"82586 internal loopback",
-		"82586 initialisation failure",
-		"Adapter list configuration error"
-	};
-
-	/* Time to play MCA games */
-
-	if (mc32_debug  &&  version_printed++ == 0)
-		pr_debug("%s", version);
-
-	pr_info("%s: %s found in slot %d: ", dev->name, cardname, slot);
-
-	POS = mca_read_stored_pos(slot, 2);
-
-	if(!(POS&1))
-	{
-		pr_cont("disabled.\n");
-		return -ENODEV;
-	}
-
-	/* Fill in the 'dev' fields. */
-	dev->base_addr = mca_io_bases[(POS>>1)&7];
-	dev->mem_start = mca_mem_bases[(POS>>4)&7];
-
-	POS = mca_read_stored_pos(slot, 4);
-	if(!(POS&1))
-	{
-		pr_cont("memory window disabled.\n");
-		return -ENODEV;
-	}
-
-	POS = mca_read_stored_pos(slot, 5);
-
-	i=(POS>>4)&3;
-	if(i==3)
-	{
-		pr_cont("invalid memory window.\n");
-		return -ENODEV;
-	}
-
-	i*=16384;
-	i+=16384;
-
-	dev->mem_end=dev->mem_start + i;
-
-	dev->irq = ((POS>>2)&3)+9;
-
-	if(!request_region(dev->base_addr, MC32_IO_EXTENT, cardname))
-	{
-		pr_cont("io 0x%3lX, which is busy.\n", dev->base_addr);
-		return -EBUSY;
-	}
-
-	pr_cont("io 0x%3lX irq %d mem 0x%lX (%dK)\n",
-		dev->base_addr, dev->irq, dev->mem_start, i/1024);
-
-
-	/* We ought to set the cache line size here.. */
-
-
-	/*
-	 *	Go PROM browsing
-	 */
-
-	/* Retrieve and print the ethernet address. */
-	for (i = 0; i < 6; i++)
-	{
-		mca_write_pos(slot, 6, i+12);
-		mca_write_pos(slot, 7, 0);
-
-		dev->dev_addr[i] = mca_read_pos(slot,3);
-	}
-
-	pr_info("%s: Address %pM ", dev->name, dev->dev_addr);
-
-	mca_write_pos(slot, 6, 0);
-	mca_write_pos(slot, 7, 0);
-
-	POS = mca_read_stored_pos(slot, 4);
-
-	if(POS&2)
-		pr_cont(": BNC port selected.\n");
-	else
-		pr_cont(": AUI port selected.\n");
-
-	POS=inb(dev->base_addr+HOST_CTRL);
-	POS|=HOST_CTRL_ATTN|HOST_CTRL_RESET;
-	POS&=~HOST_CTRL_INTE;
-	outb(POS, dev->base_addr+HOST_CTRL);
-	/* Reset adapter */
-	udelay(100);
-	/* Reset off */
-	POS&=~(HOST_CTRL_ATTN|HOST_CTRL_RESET);
-	outb(POS, dev->base_addr+HOST_CTRL);
-
-	udelay(300);
-
-	/*
-	 *	Grab the IRQ
-	 */
-
-	err = request_irq(dev->irq, mc32_interrupt, IRQF_SHARED, DRV_NAME, dev);
-	if (err) {
-		release_region(dev->base_addr, MC32_IO_EXTENT);
-		pr_err("%s: unable to get IRQ %d.\n", DRV_NAME, dev->irq);
-		goto err_exit_ports;
-	}
-
-	memset(lp, 0, sizeof(struct mc32_local));
-	lp->slot = slot;
-
-	i=0;
-
-	base = inb(dev->base_addr);
-
-	while(base == 0xFF)
-	{
-		i++;
-		if(i == 1000)
-		{
-			pr_err("%s: failed to boot adapter.\n", dev->name);
-			err = -ENODEV;
-			goto err_exit_irq;
-		}
-		udelay(1000);
-		if(inb(dev->base_addr+2)&(1<<5))
-			base = inb(dev->base_addr);
-	}
-
-	if(base>0)
-	{
-		if(base < 0x0C)
-			pr_err("%s: %s%s.\n", dev->name, failures[base-1],
-				base<0x0A?" test failure":"");
-		else
-			pr_err("%s: unknown failure %d.\n", dev->name, base);
-		err = -ENODEV;
-		goto err_exit_irq;
-	}
-
-	base=0;
-	for(i=0;i<4;i++)
-	{
-		int n=0;
-
-		while(!(inb(dev->base_addr+2)&(1<<5)))
-		{
-			n++;
-			udelay(50);
-			if(n>100)
-			{
-				pr_err("%s: mailbox read fail (%d).\n", dev->name, i);
-				err = -ENODEV;
-				goto err_exit_irq;
-			}
-		}
-
-		base|=(inb(dev->base_addr)<<(8*i));
-	}
-
-	lp->exec_box=isa_bus_to_virt(dev->mem_start+base);
-
-	base=lp->exec_box->data[1]<<16|lp->exec_box->data[0];
-
-	lp->base = dev->mem_start+base;
-
-	lp->rx_box=isa_bus_to_virt(lp->base + lp->exec_box->data[2]);
-	lp->tx_box=isa_bus_to_virt(lp->base + lp->exec_box->data[3]);
-
-	lp->stats = isa_bus_to_virt(lp->base + lp->exec_box->data[5]);
-
-	/*
-	 *	Descriptor chains (card relative)
-	 */
-
-	lp->tx_chain 		= lp->exec_box->data[8];   /* Transmit list start offset */
-	lp->rx_chain 		= lp->exec_box->data[10];  /* Receive list start offset */
-	lp->tx_len 		= lp->exec_box->data[9];   /* Transmit list count */
-	lp->rx_len 		= lp->exec_box->data[11];  /* Receive list count */
-
-	sema_init(&lp->cmd_mutex, 0);
-	init_completion(&lp->execution_cmd);
-	init_completion(&lp->xceiver_cmd);
-
-	pr_info("%s: Firmware Rev %d. %d RX buffers, %d TX buffers. Base of 0x%08X.\n",
-		dev->name, lp->exec_box->data[12], lp->rx_len, lp->tx_len, lp->base);
-
-	dev->netdev_ops		= &netdev_ops;
-	dev->watchdog_timeo	= HZ*5;	/* Board does all the work */
-	dev->ethtool_ops	= &netdev_ethtool_ops;
-
-	return 0;
-
-err_exit_irq:
-	free_irq(dev->irq, dev);
-err_exit_ports:
-	release_region(dev->base_addr, MC32_IO_EXTENT);
-	return err;
-}
-
-
-/**
- *	mc32_ready_poll		-	wait until we can feed it a command
- *	@dev:	The device to wait for
- *
- *	Wait until the card becomes ready to accept a command via the
- *	command register. This tells us nothing about the completion
- *	status of any pending commands and takes very little time at all.
- */
-
-static inline void mc32_ready_poll(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));
-}
-
-
-/**
- *	mc32_command_nowait	-	send a command non blocking
- *	@dev: The 3c527 to issue the command to
- *	@cmd: The command word to write to the mailbox
- *	@data: A data block if the command expects one
- *	@len: Length of the data block
- *
- *	Send a command from interrupt state. If there is a command
- *	currently being executed then we return an error of -1. It
- *	simply isn't viable to wait around as commands may be
- *	slow. This can theoretically be starved on SMP, but it's hard
- *	to see a realistic situation.  We do not wait for the command
- *	to complete --- we rely on the interrupt handler to tidy up
- *	after us.
- */
-
-static int mc32_command_nowait(struct net_device *dev, u16 cmd, void *data, int len)
-{
-	struct mc32_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-	int ret = -1;
-
-	if (down_trylock(&lp->cmd_mutex) == 0)
-	{
-		lp->cmd_nonblocking=1;
-		lp->exec_box->mbox=0;
-		lp->exec_box->mbox=cmd;
-		memcpy((void *)lp->exec_box->data, data, len);
-		barrier();	/* the memcpy forgot the volatile so be sure */
-
-		/* Send the command */
-		mc32_ready_poll(dev);
-		outb(1<<6, ioaddr+HOST_CMD);
-
-		ret = 0;
-
-		/* Interrupt handler will signal mutex on completion */
-	}
-
-	return ret;
-}
-
-
-/**
- *	mc32_command	-	send a command and sleep until completion
- *	@dev: The 3c527 card to issue the command to
- *	@cmd: The command word to write to the mailbox
- *	@data: A data block if the command expects one
- *	@len: Length of the data block
- *
- *	Sends exec commands in a user context. This permits us to wait around
- *	for the replies and also to wait for the command buffer to complete
- *	from a previous command before we execute our command. After our
- *	command completes we will attempt any pending multicast reload
- *	we blocked off by hogging the exec buffer.
- *
- *	You feed the card a command, you wait, it interrupts you get a
- *	reply. All well and good. The complication arises because you use
- *	commands for filter list changes which come in at bh level from things
- *	like IPV6 group stuff.
- */
-
-static int mc32_command(struct net_device *dev, u16 cmd, void *data, int len)
-{
-	struct mc32_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-	int ret = 0;
-
-	down(&lp->cmd_mutex);
-
-	/*
-	 *     My Turn
-	 */
-
-	lp->cmd_nonblocking=0;
-	lp->exec_box->mbox=0;
-	lp->exec_box->mbox=cmd;
-	memcpy((void *)lp->exec_box->data, data, len);
-	barrier();	/* the memcpy forgot the volatile so be sure */
-
-	mc32_ready_poll(dev);
-	outb(1<<6, ioaddr+HOST_CMD);
-
-	wait_for_completion(&lp->execution_cmd);
-
-	if(lp->exec_box->mbox&(1<<13))
-		ret = -1;
-
-	up(&lp->cmd_mutex);
-
-	/*
-	 *	A multicast set got blocked - try it now
-         */
-
-	if(lp->mc_reload_wait)
-	{
-		mc32_reset_multicast_list(dev);
-	}
-
-	return ret;
-}
-
-
-/**
- *	mc32_start_transceiver	-	tell board to restart tx/rx
- *	@dev: The 3c527 card to issue the command to
- *
- *	This may be called from the interrupt state, where it is used
- *	to restart the rx ring if the card runs out of rx buffers.
- *
- * 	We must first check if it's ok to (re)start the transceiver. See
- *      mc32_close for details.
- */
-
-static void mc32_start_transceiver(struct net_device *dev) {
-
-	struct mc32_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-
-	/* Ignore RX overflow on device closure */
-	if (lp->xceiver_desired_state==HALTED)
-		return;
-
-	/* Give the card the offset to the post-EOL-bit RX descriptor */
-	mc32_ready_poll(dev);
-	lp->rx_box->mbox=0;
-	lp->rx_box->data[0]=lp->rx_ring[prev_rx(lp->rx_ring_tail)].p->next;
-	outb(HOST_CMD_START_RX, ioaddr+HOST_CMD);
-
-	mc32_ready_poll(dev);
-	lp->tx_box->mbox=0;
-	outb(HOST_CMD_RESTRT_TX, ioaddr+HOST_CMD);   /* card ignores this on RX restart */
-
-	/* We are not interrupted on start completion */
-}
-
-
-/**
- *	mc32_halt_transceiver	-	tell board to stop tx/rx
- *	@dev: The 3c527 card to issue the command to
- *
- *	We issue the commands to halt the card's transceiver. In fact,
- *	after some experimenting we now simply tell the card to
- *	suspend. When issuing aborts occasionally odd things happened.
- *
- *	We then sleep until the card has notified us that both rx and
- *	tx have been suspended.
- */
-
-static void mc32_halt_transceiver(struct net_device *dev)
-{
-	struct mc32_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-
-	mc32_ready_poll(dev);
-	lp->rx_box->mbox=0;
-	outb(HOST_CMD_SUSPND_RX, ioaddr+HOST_CMD);
-	wait_for_completion(&lp->xceiver_cmd);
-
-	mc32_ready_poll(dev);
-	lp->tx_box->mbox=0;
-	outb(HOST_CMD_SUSPND_TX, ioaddr+HOST_CMD);
-	wait_for_completion(&lp->xceiver_cmd);
-}
-
-
-/**
- *	mc32_load_rx_ring	-	load the ring of receive buffers
- *	@dev: 3c527 to build the ring for
- *
- *	This initialises the on-card and driver datastructures to
- *	the point where mc32_start_transceiver() can be called.
- *
- *	The card sets up the receive ring for us. We are required to use the
- *	ring it provides, although the size of the ring is configurable.
- *
- * 	We allocate an sk_buff for each ring entry in turn and
- * 	initialise its house-keeping info. At the same time, we read
- * 	each 'next' pointer in our rx_ring array. This reduces slow
- * 	shared-memory reads and makes it easy to access predecessor
- * 	descriptors.
- *
- *	We then set the end-of-list bit for the last entry so that the
- * 	card will know when it has run out of buffers.
- */
-
-static int mc32_load_rx_ring(struct net_device *dev)
-{
-	struct mc32_local *lp = netdev_priv(dev);
-	int i;
-	u16 rx_base;
-	volatile struct skb_header *p;
-
-	rx_base=lp->rx_chain;
-
-	for(i=0; i<RX_RING_LEN; i++) {
-		lp->rx_ring[i].skb=alloc_skb(1532, GFP_KERNEL);
-		if (lp->rx_ring[i].skb==NULL) {
-			for (;i>=0;i--)
-				kfree_skb(lp->rx_ring[i].skb);
-			return -ENOBUFS;
-		}
-		skb_reserve(lp->rx_ring[i].skb, 18);
-
-		p=isa_bus_to_virt(lp->base+rx_base);
-
-		p->control=0;
-		p->data=isa_virt_to_bus(lp->rx_ring[i].skb->data);
-		p->status=0;
-		p->length=1532;
-
-		lp->rx_ring[i].p=p;
-		rx_base=p->next;
-	}
-
-	lp->rx_ring[i-1].p->control |= CONTROL_EOL;
-
-	lp->rx_ring_tail=0;
-
-	return 0;
-}
-
-
-/**
- *	mc32_flush_rx_ring	-	free the ring of receive buffers
- *	@lp: Local data of 3c527 to flush the rx ring of
- *
- *	Free the buffer for each ring slot. This may be called
- *      before mc32_load_rx_ring(), eg. on error in mc32_open().
- *      Requires rx skb pointers to point to a valid skb, or NULL.
- */
-
-static void mc32_flush_rx_ring(struct net_device *dev)
-{
-	struct mc32_local *lp = netdev_priv(dev);
-	int i;
-
-	for(i=0; i < RX_RING_LEN; i++)
-	{
-		if (lp->rx_ring[i].skb) {
-			dev_kfree_skb(lp->rx_ring[i].skb);
-			lp->rx_ring[i].skb = NULL;
-		}
-		lp->rx_ring[i].p=NULL;
-	}
-}
-
-
-/**
- *	mc32_load_tx_ring	-	load transmit ring
- *	@dev: The 3c527 card to issue the command to
- *
- *	This sets up the host transmit data-structures.
- *
- *	First, we obtain from the card it's current position in the tx
- *	ring, so that we will know where to begin transmitting
- *	packets.
- *
- * 	Then, we read the 'next' pointers from the on-card tx ring into
- *  	our tx_ring array to reduce slow shared-mem reads. Finally, we
- * 	intitalise the tx house keeping variables.
- *
- */
-
-static void mc32_load_tx_ring(struct net_device *dev)
-{
-	struct mc32_local *lp = netdev_priv(dev);
-	volatile struct skb_header *p;
-	int i;
-	u16 tx_base;
-
-	tx_base=lp->tx_box->data[0];
-
-	for(i=0 ; i<TX_RING_LEN ; i++)
-	{
-		p=isa_bus_to_virt(lp->base+tx_base);
-		lp->tx_ring[i].p=p;
-		lp->tx_ring[i].skb=NULL;
-
-		tx_base=p->next;
-	}
-
-	/* -1 so that tx_ring_head cannot "lap" tx_ring_tail */
-	/* see mc32_tx_ring */
-
-	atomic_set(&lp->tx_count, TX_RING_LEN-1);
-	atomic_set(&lp->tx_ring_head, 0);
-	lp->tx_ring_tail=0;
-}
-
-
-/**
- *	mc32_flush_tx_ring 	-	free transmit ring
- *	@lp: Local data of 3c527 to flush the tx ring of
- *
- *      If the ring is non-empty, zip over the it, freeing any
- *      allocated skb_buffs.  The tx ring house-keeping variables are
- *      then reset. Requires rx skb pointers to point to a valid skb,
- *      or NULL.
- */
-
-static void mc32_flush_tx_ring(struct net_device *dev)
-{
-	struct mc32_local *lp = netdev_priv(dev);
-	int i;
-
-	for (i=0; i < TX_RING_LEN; i++)
-	{
-		if (lp->tx_ring[i].skb)
-		{
-			dev_kfree_skb(lp->tx_ring[i].skb);
-			lp->tx_ring[i].skb = NULL;
-		}
-	}
-
-	atomic_set(&lp->tx_count, 0);
-	atomic_set(&lp->tx_ring_head, 0);
-	lp->tx_ring_tail=0;
-}
-
-
-/**
- *	mc32_open	-	handle 'up' of card
- *	@dev: device to open
- *
- *	The user is trying to bring the card into ready state. This requires
- *	a brief dialogue with the card. Firstly we enable interrupts and then
- *	'indications'. Without these enabled the card doesn't bother telling
- *	us what it has done. This had me puzzled for a week.
- *
- *	We configure the number of card descriptors, then load the network
- *	address and multicast filters. Turn on the workaround mode. This
- *	works around a bug in the 82586 - it asks the firmware to do
- *	so. It has a performance (latency) hit but is needed on busy
- *	[read most] lans. We load the ring with buffers then we kick it
- *	all off.
- */
-
-static int mc32_open(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	struct mc32_local *lp = netdev_priv(dev);
-	u8 one=1;
-	u8 regs;
-	u16 descnumbuffs[2] = {TX_RING_LEN, RX_RING_LEN};
-
-	/*
-	 *	Interrupts enabled
-	 */
-
-	regs=inb(ioaddr+HOST_CTRL);
-	regs|=HOST_CTRL_INTE;
-	outb(regs, ioaddr+HOST_CTRL);
-
-	/*
-	 *      Allow ourselves to issue commands
-	 */
-
-	up(&lp->cmd_mutex);
-
-
-	/*
-	 *	Send the indications on command
-	 */
-
-	mc32_command(dev, 4, &one, 2);
-
-	/*
-	 *	Poke it to make sure it's really dead.
-	 */
-
-	mc32_halt_transceiver(dev);
-	mc32_flush_tx_ring(dev);
-
-	/*
-	 *	Ask card to set up on-card descriptors to our spec
-	 */
-
-	if(mc32_command(dev, 8, descnumbuffs, 4)) {
-		pr_info("%s: %s rejected our buffer configuration!\n",
-	 	       dev->name, cardname);
-		mc32_close(dev);
-		return -ENOBUFS;
-	}
-
-	/* Report new configuration */
-	mc32_command(dev, 6, NULL, 0);
-
-	lp->tx_chain 		= lp->exec_box->data[8];   /* Transmit list start offset */
-	lp->rx_chain 		= lp->exec_box->data[10];  /* Receive list start offset */
-	lp->tx_len 		= lp->exec_box->data[9];   /* Transmit list count */
-	lp->rx_len 		= lp->exec_box->data[11];  /* Receive list count */
-
-	/* Set Network Address */
-	mc32_command(dev, 1, dev->dev_addr, 6);
-
-	/* Set the filters */
-	mc32_set_multicast_list(dev);
-
-	if (WORKAROUND_82586) {
-		u16 zero_word=0;
-		mc32_command(dev, 0x0D, &zero_word, 2);   /* 82586 bug workaround on  */
-	}
-
-	mc32_load_tx_ring(dev);
-
-	if(mc32_load_rx_ring(dev))
-	{
-		mc32_close(dev);
-		return -ENOBUFS;
-	}
-
-	lp->xceiver_desired_state = RUNNING;
-
-	/* And finally, set the ball rolling... */
-	mc32_start_transceiver(dev);
-
-	netif_start_queue(dev);
-
-	return 0;
-}
-
-
-/**
- *	mc32_timeout	-	handle a timeout from the network layer
- *	@dev: 3c527 that timed out
- *
- *	Handle a timeout on transmit from the 3c527. This normally means
- *	bad things as the hardware handles cable timeouts and mess for
- *	us.
- *
- */
-
-static void mc32_timeout(struct net_device *dev)
-{
-	pr_warning("%s: transmit timed out?\n", dev->name);
-	/* Try to restart the adaptor. */
-	netif_wake_queue(dev);
-}
-
-
-/**
- *	mc32_send_packet	-	queue a frame for transmit
- *	@skb: buffer to transmit
- *	@dev: 3c527 to send it out of
- *
- *	Transmit a buffer. This normally means throwing the buffer onto
- *	the transmit queue as the queue is quite large. If the queue is
- *	full then we set tx_busy and return. Once the interrupt handler
- *	gets messages telling it to reclaim transmit queue entries, we will
- *	clear tx_busy and the kernel will start calling this again.
- *
- *      We do not disable interrupts or acquire any locks; this can
- *      run concurrently with mc32_tx_ring(), and the function itself
- *      is serialised at a higher layer. However, similarly for the
- *      card itself, we must ensure that we update tx_ring_head only
- *      after we've established a valid packet on the tx ring (and
- *      before we let the card "see" it, to prevent it racing with the
- *      irq handler).
- *
- */
-
-static netdev_tx_t mc32_send_packet(struct sk_buff *skb,
-				    struct net_device *dev)
-{
-	struct mc32_local *lp = netdev_priv(dev);
-	u32 head = atomic_read(&lp->tx_ring_head);
-
-	volatile struct skb_header *p, *np;
-
-	netif_stop_queue(dev);
-
-	if(atomic_read(&lp->tx_count)==0) {
-		return NETDEV_TX_BUSY;
-	}
-
-	if (skb_padto(skb, ETH_ZLEN)) {
-		netif_wake_queue(dev);
-		return NETDEV_TX_OK;
-	}
-
-	atomic_dec(&lp->tx_count);
-
-	/* P is the last sending/sent buffer as a pointer */
-	p=lp->tx_ring[head].p;
-
-	head = next_tx(head);
-
-	/* NP is the buffer we will be loading */
-	np=lp->tx_ring[head].p;
-
-	/* We will need this to flush the buffer out */
-	lp->tx_ring[head].skb=skb;
-
-	np->length      = unlikely(skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
-	np->data	= isa_virt_to_bus(skb->data);
-	np->status	= 0;
-	np->control     = CONTROL_EOP | CONTROL_EOL;
-	wmb();
-
-	/*
-	 * The new frame has been setup; we can now
-	 * let the interrupt handler and card "see" it
-	 */
-
-	atomic_set(&lp->tx_ring_head, head);
-	p->control     &= ~CONTROL_EOL;
-
-	netif_wake_queue(dev);
-	return NETDEV_TX_OK;
-}
-
-
-/**
- *	mc32_update_stats	-	pull off the on board statistics
- *	@dev: 3c527 to service
- *
- *
- *	Query and reset the on-card stats. There's the small possibility
- *	of a race here, which would result in an underestimation of
- *	actual errors. As such, we'd prefer to keep all our stats
- *	collection in software. As a rule, we do. However it can't be
- *	used for rx errors and collisions as, by default, the card discards
- *	bad rx packets.
- *
- *	Setting the SAV BP in the rx filter command supposedly
- *	stops this behaviour. However, testing shows that it only seems to
- *	enable the collation of on-card rx statistics --- the driver
- *	never sees an RX descriptor with an error status set.
- *
- */
-
-static void mc32_update_stats(struct net_device *dev)
-{
-	struct mc32_local *lp = netdev_priv(dev);
-	volatile struct mc32_stats *st = lp->stats;
-
-	u32 rx_errors=0;
-
-	rx_errors+=dev->stats.rx_crc_errors   +=st->rx_crc_errors;
-	                                           st->rx_crc_errors=0;
-	rx_errors+=dev->stats.rx_fifo_errors  +=st->rx_overrun_errors;
-	                                           st->rx_overrun_errors=0;
-	rx_errors+=dev->stats.rx_frame_errors +=st->rx_alignment_errors;
- 	                                           st->rx_alignment_errors=0;
-	rx_errors+=dev->stats.rx_length_errors+=st->rx_tooshort_errors;
-	                                           st->rx_tooshort_errors=0;
-	rx_errors+=dev->stats.rx_missed_errors+=st->rx_outofresource_errors;
-	                                           st->rx_outofresource_errors=0;
-        dev->stats.rx_errors=rx_errors;
-
-	/* Number of packets which saw one collision */
-	dev->stats.collisions+=st->dataC[10];
-	st->dataC[10]=0;
-
-	/* Number of packets which saw 2--15 collisions */
-	dev->stats.collisions+=st->dataC[11];
-	st->dataC[11]=0;
-}
-
-
-/**
- *	mc32_rx_ring	-	process the receive ring
- *	@dev: 3c527 that needs its receive ring processing
- *
- *
- *	We have received one or more indications from the card that a
- *	receive has completed. The buffer ring thus contains dirty
- *	entries. We walk the ring by iterating over the circular rx_ring
- *	array, starting at the next dirty buffer (which happens to be the
- *	one we finished up at last time around).
- *
- *	For each completed packet, we will either copy it and pass it up
- * 	the stack or, if the packet is near MTU sized, we allocate
- *	another buffer and flip the old one up the stack.
- *
- *	We must succeed in keeping a buffer on the ring. If necessary we
- *	will toss a received packet rather than lose a ring entry. Once
- *	the first uncompleted descriptor is found, we move the
- *	End-Of-List bit to include the buffers just processed.
- *
- */
-
-static void mc32_rx_ring(struct net_device *dev)
-{
-	struct mc32_local *lp = netdev_priv(dev);
-	volatile struct skb_header *p;
-	u16 rx_ring_tail;
-	u16 rx_old_tail;
-	int x=0;
-
-	rx_old_tail = rx_ring_tail = lp->rx_ring_tail;
-
-	do
-	{
-		p=lp->rx_ring[rx_ring_tail].p;
-
-		if(!(p->status & (1<<7))) { /* Not COMPLETED */
-			break;
-		}
-		if(p->status & (1<<6)) /* COMPLETED_OK */
-		{
-
-			u16 length=p->length;
-			struct sk_buff *skb;
-			struct sk_buff *newskb;
-
-			/* Try to save time by avoiding a copy on big frames */
-
-			if ((length > RX_COPYBREAK) &&
-			    ((newskb=dev_alloc_skb(1532)) != NULL))
-			{
-				skb=lp->rx_ring[rx_ring_tail].skb;
-				skb_put(skb, length);
-
-				skb_reserve(newskb,18);
-				lp->rx_ring[rx_ring_tail].skb=newskb;
-				p->data=isa_virt_to_bus(newskb->data);
-			}
-			else
-			{
-				skb=dev_alloc_skb(length+2);
-
-				if(skb==NULL) {
-					dev->stats.rx_dropped++;
-					goto dropped;
-				}
-
-				skb_reserve(skb,2);
-				memcpy(skb_put(skb, length),
-				       lp->rx_ring[rx_ring_tail].skb->data, length);
-			}
-
-			skb->protocol=eth_type_trans(skb,dev);
- 			dev->stats.rx_packets++;
- 			dev->stats.rx_bytes += length;
-			netif_rx(skb);
-		}
-
-	dropped:
-		p->length = 1532;
-		p->status = 0;
-
-		rx_ring_tail=next_rx(rx_ring_tail);
-	}
-        while(x++<48);
-
-	/* If there was actually a frame to be processed, place the EOL bit */
-	/* at the descriptor prior to the one to be filled next */
-
-	if (rx_ring_tail != rx_old_tail)
-	{
-		lp->rx_ring[prev_rx(rx_ring_tail)].p->control |=  CONTROL_EOL;
-		lp->rx_ring[prev_rx(rx_old_tail)].p->control  &= ~CONTROL_EOL;
-
-		lp->rx_ring_tail=rx_ring_tail;
-	}
-}
-
-
-/**
- *	mc32_tx_ring	-	process completed transmits
- *	@dev: 3c527 that needs its transmit ring processing
- *
- *
- *	This operates in a similar fashion to mc32_rx_ring. We iterate
- *	over the transmit ring. For each descriptor which has been
- *	processed by the card, we free its associated buffer and note
- *	any errors. This continues until the transmit ring is emptied
- *	or we reach a descriptor that hasn't yet been processed by the
- *	card.
- *
- */
-
-static void mc32_tx_ring(struct net_device *dev)
-{
-	struct mc32_local *lp = netdev_priv(dev);
-	volatile struct skb_header *np;
-
-	/*
-	 * We rely on head==tail to mean 'queue empty'.
-	 * This is why lp->tx_count=TX_RING_LEN-1: in order to prevent
-	 * tx_ring_head wrapping to tail and confusing a 'queue empty'
-	 * condition with 'queue full'
-	 */
-
-	while (lp->tx_ring_tail != atomic_read(&lp->tx_ring_head))
-	{
-		u16 t;
-
-		t=next_tx(lp->tx_ring_tail);
-		np=lp->tx_ring[t].p;
-
-		if(!(np->status & (1<<7)))
-		{
-			/* Not COMPLETED */
-			break;
-		}
-		dev->stats.tx_packets++;
-		if(!(np->status & (1<<6))) /* Not COMPLETED_OK */
-		{
-			dev->stats.tx_errors++;
-
-			switch(np->status&0x0F)
-			{
-				case 1:
-					dev->stats.tx_aborted_errors++;
-					break; /* Max collisions */
-				case 2:
-					dev->stats.tx_fifo_errors++;
-					break;
-				case 3:
-					dev->stats.tx_carrier_errors++;
-					break;
-				case 4:
-					dev->stats.tx_window_errors++;
-					break;  /* CTS Lost */
-				case 5:
-					dev->stats.tx_aborted_errors++;
-					break; /* Transmit timeout */
-			}
-		}
-		/* Packets are sent in order - this is
-		    basically a FIFO queue of buffers matching
-		    the card ring */
-		dev->stats.tx_bytes+=lp->tx_ring[t].skb->len;
-		dev_kfree_skb_irq(lp->tx_ring[t].skb);
-		lp->tx_ring[t].skb=NULL;
-		atomic_inc(&lp->tx_count);
-		netif_wake_queue(dev);
-
-		lp->tx_ring_tail=t;
-	}
-
-}
-
-
-/**
- *	mc32_interrupt		-	handle an interrupt from a 3c527
- *	@irq: Interrupt number
- *	@dev_id: 3c527 that requires servicing
- *	@regs: Registers (unused)
- *
- *
- *	An interrupt is raised whenever the 3c527 writes to the command
- *	register. This register contains the message it wishes to send us
- *	packed into a single byte field. We keep reading status entries
- *	until we have processed all the control items, but simply count
- *	transmit and receive reports. When all reports are in we empty the
- *	transceiver rings as appropriate. This saves the overhead of
- *	multiple command requests.
- *
- *	Because MCA is level-triggered, we shouldn't miss indications.
- *	Therefore, we needn't ask the card to suspend interrupts within
- *	this handler. The card receives an implicit acknowledgment of the
- *	current interrupt when we read the command register.
- *
- */
-
-static irqreturn_t mc32_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct mc32_local *lp;
-	int ioaddr, status, boguscount = 0;
-	int rx_event = 0;
-	int tx_event = 0;
-
-	ioaddr = dev->base_addr;
-	lp = netdev_priv(dev);
-
-	/* See whats cooking */
-
-	while((inb(ioaddr+HOST_STATUS)&HOST_STATUS_CWR) && boguscount++<2000)
-	{
-		status=inb(ioaddr+HOST_CMD);
-
-		pr_debug("Status TX%d RX%d EX%d OV%d BC%d\n",
-			(status&7), (status>>3)&7, (status>>6)&1,
-			(status>>7)&1, boguscount);
-
-		switch(status&7)
-		{
-			case 0:
-				break;
-			case 6: /* TX fail */
-			case 2:	/* TX ok */
-				tx_event = 1;
-				break;
-			case 3: /* Halt */
-			case 4: /* Abort */
-				complete(&lp->xceiver_cmd);
-				break;
-			default:
-				pr_notice("%s: strange tx ack %d\n", dev->name, status&7);
-		}
-		status>>=3;
-		switch(status&7)
-		{
-			case 0:
-				break;
-			case 2:	/* RX */
-				rx_event=1;
-				break;
-			case 3: /* Halt */
-			case 4: /* Abort */
-				complete(&lp->xceiver_cmd);
-				break;
-			case 6:
-				/* Out of RX buffers stat */
-				/* Must restart rx */
-				dev->stats.rx_dropped++;
-				mc32_rx_ring(dev);
-				mc32_start_transceiver(dev);
-				break;
-			default:
-				pr_notice("%s: strange rx ack %d\n",
-					dev->name, status&7);
-		}
-		status>>=3;
-		if(status&1)
-		{
-			/*
-			 * No thread is waiting: we need to tidy
-			 * up ourself.
-			 */
-
-			if (lp->cmd_nonblocking) {
-				up(&lp->cmd_mutex);
-				if (lp->mc_reload_wait)
-					mc32_reset_multicast_list(dev);
-			}
-			else complete(&lp->execution_cmd);
-		}
-		if(status&2)
-		{
-			/*
-			 *	We get interrupted once per
-			 *	counter that is about to overflow.
-			 */
-
-			mc32_update_stats(dev);
-		}
-	}
-
-
-	/*
-	 *	Process the transmit and receive rings
-         */
-
-	if(tx_event)
-		mc32_tx_ring(dev);
-
-	if(rx_event)
-		mc32_rx_ring(dev);
-
-	return IRQ_HANDLED;
-}
-
-
-/**
- *	mc32_close	-	user configuring the 3c527 down
- *	@dev: 3c527 card to shut down
- *
- *	The 3c527 is a bus mastering device. We must be careful how we
- *	shut it down. It may also be running shared interrupt so we have
- *	to be sure to silence it properly
- *
- *	We indicate that the card is closing to the rest of the
- *	driver.  Otherwise, it is possible that the card may run out
- *	of receive buffers and restart the transceiver while we're
- *	trying to close it.
- *
- *	We abort any receive and transmits going on and then wait until
- *	any pending exec commands have completed in other code threads.
- *	In theory we can't get here while that is true, in practice I am
- *	paranoid
- *
- *	We turn off the interrupt enable for the board to be sure it can't
- *	intefere with other devices.
- */
-
-static int mc32_close(struct net_device *dev)
-{
-	struct mc32_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-
-	u8 regs;
-	u16 one=1;
-
-	lp->xceiver_desired_state = HALTED;
-	netif_stop_queue(dev);
-
-	/*
-	 *	Send the indications on command (handy debug check)
-	 */
-
-	mc32_command(dev, 4, &one, 2);
-
-	/* Shut down the transceiver */
-
-	mc32_halt_transceiver(dev);
-
-	/* Ensure we issue no more commands beyond this point */
-
-	down(&lp->cmd_mutex);
-
-	/* Ok the card is now stopping */
-
-	regs=inb(ioaddr+HOST_CTRL);
-	regs&=~HOST_CTRL_INTE;
-	outb(regs, ioaddr+HOST_CTRL);
-
-	mc32_flush_rx_ring(dev);
-	mc32_flush_tx_ring(dev);
-
-	mc32_update_stats(dev);
-
-	return 0;
-}
-
-
-/**
- *	mc32_get_stats		-	hand back stats to network layer
- *	@dev: The 3c527 card to handle
- *
- *	We've collected all the stats we can in software already. Now
- *	it's time to update those kept on-card and return the lot.
- *
- */
-
-static struct net_device_stats *mc32_get_stats(struct net_device *dev)
-{
-	mc32_update_stats(dev);
-	return &dev->stats;
-}
-
-
-/**
- *	do_mc32_set_multicast_list	-	attempt to update multicasts
- *	@dev: 3c527 device to load the list on
- *	@retry: indicates this is not the first call.
- *
- *
- * 	Actually set or clear the multicast filter for this adaptor. The
- *	locking issues are handled by this routine. We have to track
- *	state as it may take multiple calls to get the command sequence
- *	completed. We just keep trying to schedule the loads until we
- *	manage to process them all.
- *
- *	num_addrs == -1	Promiscuous mode, receive all packets
- *
- *	num_addrs == 0	Normal mode, clear multicast list
- *
- *	num_addrs > 0	Multicast mode, receive normal and MC packets,
- *			and do best-effort filtering.
- *
- *	See mc32_update_stats() regards setting the SAV BP bit.
- *
- */
-
-static void do_mc32_set_multicast_list(struct net_device *dev, int retry)
-{
-	struct mc32_local *lp = netdev_priv(dev);
-	u16 filt = (1<<2); /* Save Bad Packets, for stats purposes */
-
-	if ((dev->flags&IFF_PROMISC) ||
-	    (dev->flags&IFF_ALLMULTI) ||
-	    netdev_mc_count(dev) > 10)
-		/* Enable promiscuous mode */
-		filt |= 1;
-	else if (!netdev_mc_empty(dev))
-	{
-		unsigned char block[62];
-		unsigned char *bp;
-		struct netdev_hw_addr *ha;
-
-		if(retry==0)
-			lp->mc_list_valid = 0;
-		if(!lp->mc_list_valid)
-		{
-			block[1]=0;
-			block[0]=netdev_mc_count(dev);
-			bp=block+2;
-
-			netdev_for_each_mc_addr(ha, dev) {
-				memcpy(bp, ha->addr, 6);
-				bp+=6;
-			}
-			if(mc32_command_nowait(dev, 2, block,
-					       2+6*netdev_mc_count(dev))==-1)
-			{
-				lp->mc_reload_wait = 1;
-				return;
-			}
-			lp->mc_list_valid=1;
-		}
-	}
-
-	if(mc32_command_nowait(dev, 0, &filt, 2)==-1)
-	{
-		lp->mc_reload_wait = 1;
-	}
-	else {
-		lp->mc_reload_wait = 0;
-	}
-}
-
-
-/**
- *	mc32_set_multicast_list	-	queue multicast list update
- *	@dev: The 3c527 to use
- *
- *	Commence loading the multicast list. This is called when the kernel
- *	changes the lists. It will override any pending list we are trying to
- *	load.
- */
-
-static void mc32_set_multicast_list(struct net_device *dev)
-{
-	do_mc32_set_multicast_list(dev,0);
-}
-
-
-/**
- *	mc32_reset_multicast_list	-	reset multicast list
- *	@dev: The 3c527 to use
- *
- *	Attempt the next step in loading the multicast lists. If this attempt
- *	fails to complete then it will be scheduled and this function called
- *	again later from elsewhere.
- */
-
-static void mc32_reset_multicast_list(struct net_device *dev)
-{
-	do_mc32_set_multicast_list(dev,1);
-}
-
-static void netdev_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-	sprintf(info->bus_info, "MCA 0x%lx", dev->base_addr);
-}
-
-static u32 netdev_get_msglevel(struct net_device *dev)
-{
-	return mc32_debug;
-}
-
-static void netdev_set_msglevel(struct net_device *dev, u32 level)
-{
-	mc32_debug = level;
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-	.get_drvinfo		= netdev_get_drvinfo,
-	.get_msglevel		= netdev_get_msglevel,
-	.set_msglevel		= netdev_set_msglevel,
-};
-
-#ifdef MODULE
-
-static struct net_device *this_device;
-
-/**
- *	init_module		-	entry point
- *
- *	Probe and locate a 3c527 card. This really should probe and locate
- *	all the 3c527 cards in the machine not just one of them. Yes you can
- *	insmod multiple modules for now but it's a hack.
- */
-
-int __init init_module(void)
-{
-	this_device = mc32_probe(-1);
-	if (IS_ERR(this_device))
-		return PTR_ERR(this_device);
-	return 0;
-}
-
-/**
- *	cleanup_module	-	free resources for an unload
- *
- *	Unloading time. We release the MCA bus resources and the interrupt
- *	at which point everything is ready to unload. The card must be stopped
- *	at this point or we would not have been called. When we unload we
- *	leave the card stopped but not totally shut down. When the card is
- *	initialized it must be rebooted or the rings reloaded before any
- *	transmit operations are allowed to start scribbling into memory.
- */
-
-void __exit cleanup_module(void)
-{
-	unregister_netdev(this_device);
-	cleanup_card(this_device);
-	free_netdev(this_device);
-}
-
-#endif /* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/3c527.h linux-libre-3.2-gnu/drivers/net/3c527.h
--- linux-libre-3.1-gnu/drivers/net/3c527.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/3c527.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-/*
- *	3COM "EtherLink MC/32" Descriptions
- */
-
-/*
- *	Registers
- */
-
-#define HOST_CMD		0
-#define         HOST_CMD_START_RX   (1<<3)
-#define         HOST_CMD_SUSPND_RX  (3<<3)
-#define         HOST_CMD_RESTRT_RX  (5<<3)
-
-#define         HOST_CMD_SUSPND_TX  3
-#define         HOST_CMD_RESTRT_TX  5
-
-
-#define HOST_STATUS		2
-#define		HOST_STATUS_CRR	(1<<6)
-#define		HOST_STATUS_CWR	(1<<5)
-
-
-#define HOST_CTRL		6
-#define		HOST_CTRL_ATTN	(1<<7)
-#define 	HOST_CTRL_RESET	(1<<6)
-#define 	HOST_CTRL_INTE	(1<<2)
-
-#define HOST_RAMPAGE		8
-
-#define HALTED 0
-#define RUNNING 1
-
-struct mc32_mailbox
-{
- 	u16 mbox;
- 	u16 data[1];
-} __packed;
-
-struct skb_header
-{
-	u8 status;
-	u8 control;
-	u16 next;	/* Do not change! */
-	u16 length;
-	u32 data;
-} __packed;
-
-struct mc32_stats
-{
-	/* RX Errors */
-	u32 rx_crc_errors;
-	u32 rx_alignment_errors;
-	u32 rx_overrun_errors;
-	u32 rx_tooshort_errors;
-	u32 rx_toolong_errors;
-	u32 rx_outofresource_errors;
-
-	u32 rx_discarded;  /* via card pattern match filter */
-
-	/* TX Errors */
-	u32 tx_max_collisions;
-	u32 tx_carrier_errors;
-	u32 tx_underrun_errors;
-	u32 tx_cts_errors;
-	u32 tx_timeout_errors;
-
-	/* various cruft */
-	u32 dataA[6];
-	u16 dataB[5];
-	u32 dataC[14];
-} __packed;
-
-#define STATUS_MASK	0x0F
-#define COMPLETED	(1<<7)
-#define COMPLETED_OK	(1<<6)
-#define BUFFER_BUSY	(1<<5)
-
-#define CONTROL_EOP	(1<<7)	/* End Of Packet */
-#define CONTROL_EOL	(1<<6)	/* End of List */
-
-#define MCA_MC32_ID	0x0041	/* Our MCA ident */
diff -druN linux-libre-3.1-gnu/drivers/net/3c59x.c linux-libre-3.2-gnu/drivers/net/3c59x.c
--- linux-libre-3.1-gnu/drivers/net/3c59x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/3c59x.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3326 +0,0 @@
-/* EtherLinkXL.c: A 3Com EtherLink PCI III/XL ethernet driver for linux. */
-/*
-	Written 1996-1999 by Donald Becker.
-
-	This software may be used and distributed according to the terms
-	of the GNU General Public License, incorporated herein by reference.
-
-	This driver is for the 3Com "Vortex" and "Boomerang" series ethercards.
-	Members of the series include Fast EtherLink 3c590/3c592/3c595/3c597
-	and the EtherLink XL 3c900 and 3c905 cards.
-
-	Problem reports and questions should be directed to
-	vortex@scyld.com
-
-	The author may be reached as becker@scyld.com, or C/O
-	Scyld Computing Corporation
-	410 Severn Ave., Suite 210
-	Annapolis MD 21403
-
-*/
-
-/*
- * FIXME: This driver _could_ support MTU changing, but doesn't.  See Don's hamachi.c implementation
- * as well as other drivers
- *
- * NOTE: If you make 'vortex_debug' a constant (#define vortex_debug 0) the driver shrinks by 2k
- * due to dead code elimination.  There will be some performance benefits from this due to
- * elimination of all the tests and reduced cache footprint.
- */
-
-
-#define DRV_NAME	"3c59x"
-
-
-
-/* A few values that may be tweaked. */
-/* Keep the ring sizes a power of two for efficiency. */
-#define TX_RING_SIZE	16
-#define RX_RING_SIZE	32
-#define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
-
-/* "Knobs" that adjust features and parameters. */
-/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
-   Setting to > 1512 effectively disables this feature. */
-#ifndef __arm__
-static int rx_copybreak = 200;
-#else
-/* ARM systems perform better by disregarding the bus-master
-   transfer capability of these cards. -- rmk */
-static int rx_copybreak = 1513;
-#endif
-/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
-static const int mtu = 1500;
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 32;
-/* Tx timeout interval (millisecs) */
-static int watchdog = 5000;
-
-/* Allow aggregation of Tx interrupts.  Saves CPU load at the cost
- * of possible Tx stalls if the system is blocking interrupts
- * somewhere else.  Undefine this to disable.
- */
-#define tx_interrupt_mitigation 1
-
-/* Put out somewhat more debugging messages. (0: no msg, 1 minimal .. 6). */
-#define vortex_debug debug
-#ifdef VORTEX_DEBUG
-static int vortex_debug = VORTEX_DEBUG;
-#else
-static int vortex_debug = 1;
-#endif
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/errno.h>
-#include <linux/in.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/mii.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/ethtool.h>
-#include <linux/highmem.h>
-#include <linux/eisa.h>
-#include <linux/bitops.h>
-#include <linux/jiffies.h>
-#include <linux/gfp.h>
-#include <asm/irq.h>			/* For nr_irqs only. */
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-/* Kernel compatibility defines, some common to David Hinds' PCMCIA package.
-   This is only in the support-all-kernels source code. */
-
-#define RUN_AT(x) (jiffies + (x))
-
-#include <linux/delay.h>
-
-
-static const char version[] __devinitconst =
-	DRV_NAME ": Donald Becker and others.\n";
-
-MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
-MODULE_DESCRIPTION("3Com 3c59x/3c9xx ethernet driver ");
-MODULE_LICENSE("GPL");
-
-
-/* Operational parameter that usually are not changed. */
-
-/* The Vortex size is twice that of the original EtherLinkIII series: the
-   runtime register window, window 1, is now always mapped in.
-   The Boomerang size is twice as large as the Vortex -- it has additional
-   bus master control registers. */
-#define VORTEX_TOTAL_SIZE 0x20
-#define BOOMERANG_TOTAL_SIZE 0x40
-
-/* Set iff a MII transceiver on any interface requires mdio preamble.
-   This only set with the original DP83840 on older 3c905 boards, so the extra
-   code size of a per-interface flag is not worthwhile. */
-static char mii_preamble_required;
-
-#define PFX DRV_NAME ": "
-
-
-
-/*
-				Theory of Operation
-
-I. Board Compatibility
-
-This device driver is designed for the 3Com FastEtherLink and FastEtherLink
-XL, 3Com's PCI to 10/100baseT adapters.  It also works with the 10Mbs
-versions of the FastEtherLink cards.  The supported product IDs are
-  3c590, 3c592, 3c595, 3c597, 3c900, 3c905
-
-The related ISA 3c515 is supported with a separate driver, 3c515.c, included
-with the kernel source or available from
-    cesdis.gsfc.nasa.gov:/pub/linux/drivers/3c515.html
-
-II. Board-specific settings
-
-PCI bus devices are configured by the system at boot time, so no jumpers
-need to be set on the board.  The system BIOS should be set to assign the
-PCI INTA signal to an otherwise unused system IRQ line.
-
-The EEPROM settings for media type and forced-full-duplex are observed.
-The EEPROM media type should be left at the default "autoselect" unless using
-10base2 or AUI connections which cannot be reliably detected.
-
-III. Driver operation
-
-The 3c59x series use an interface that's very similar to the previous 3c5x9
-series.  The primary interface is two programmed-I/O FIFOs, with an
-alternate single-contiguous-region bus-master transfer (see next).
-
-The 3c900 "Boomerang" series uses a full-bus-master interface with separate
-lists of transmit and receive descriptors, similar to the AMD LANCE/PCnet,
-DEC Tulip and Intel Speedo3.  The first chip version retains a compatible
-programmed-I/O interface that has been removed in 'B' and subsequent board
-revisions.
-
-One extension that is advertised in a very large font is that the adapters
-are capable of being bus masters.  On the Vortex chip this capability was
-only for a single contiguous region making it far less useful than the full
-bus master capability.  There is a significant performance impact of taking
-an extra interrupt or polling for the completion of each transfer, as well
-as difficulty sharing the single transfer engine between the transmit and
-receive threads.  Using DMA transfers is a win only with large blocks or
-with the flawed versions of the Intel Orion motherboard PCI controller.
-
-The Boomerang chip's full-bus-master interface is useful, and has the
-currently-unused advantages over other similar chips that queued transmit
-packets may be reordered and receive buffer groups are associated with a
-single frame.
-
-With full-bus-master support, this driver uses a "RX_COPYBREAK" scheme.
-Rather than a fixed intermediate receive buffer, this scheme allocates
-full-sized skbuffs as receive buffers.  The value RX_COPYBREAK is used as
-the copying breakpoint: it is chosen to trade-off the memory wasted by
-passing the full-sized skbuff to the queue layer for all frames vs. the
-copying cost of copying a frame to a correctly-sized skbuff.
-
-IIIC. Synchronization
-The driver runs as two independent, single-threaded flows of control.  One
-is the send-packet routine, which enforces single-threaded use by the
-dev->tbusy flag.  The other thread is the interrupt handler, which is single
-threaded by the hardware and other software.
-
-IV. Notes
-
-Thanks to Cameron Spitzer and Terry Murphy of 3Com for providing development
-3c590, 3c595, and 3c900 boards.
-The name "Vortex" is the internal 3Com project name for the PCI ASIC, and
-the EISA version is called "Demon".  According to Terry these names come
-from rides at the local amusement park.
-
-The new chips support both ethernet (1.5K) and FDDI (4.5K) packet sizes!
-This driver only supports ethernet packets because of the skbuff allocation
-limit of 4K.
-*/
-
-/* This table drives the PCI probe routines.  It's mostly boilerplate in all
-   of the drivers, and will likely be provided by some future kernel.
-*/
-enum pci_flags_bit {
-	PCI_USES_MASTER=4,
-};
-
-enum {	IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4, IS_TORNADO=8,
-	EEPROM_8BIT=0x10,	/* AKPM: Uses 0x230 as the base bitmaps for EEPROM reads */
-	HAS_PWR_CTRL=0x20, HAS_MII=0x40, HAS_NWAY=0x80, HAS_CB_FNS=0x100,
-	INVERT_MII_PWR=0x200, INVERT_LED_PWR=0x400, MAX_COLLISION_RESET=0x800,
-	EEPROM_OFFSET=0x1000, HAS_HWCKSM=0x2000, WNO_XCVR_PWR=0x4000,
-	EXTRA_PREAMBLE=0x8000, EEPROM_RESET=0x10000, };
-
-enum vortex_chips {
-	CH_3C590 = 0,
-	CH_3C592,
-	CH_3C597,
-	CH_3C595_1,
-	CH_3C595_2,
-
-	CH_3C595_3,
-	CH_3C900_1,
-	CH_3C900_2,
-	CH_3C900_3,
-	CH_3C900_4,
-
-	CH_3C900_5,
-	CH_3C900B_FL,
-	CH_3C905_1,
-	CH_3C905_2,
-	CH_3C905B_TX,
-	CH_3C905B_1,
-
-	CH_3C905B_2,
-	CH_3C905B_FX,
-	CH_3C905C,
-	CH_3C9202,
-	CH_3C980,
-	CH_3C9805,
-
-	CH_3CSOHO100_TX,
-	CH_3C555,
-	CH_3C556,
-	CH_3C556B,
-	CH_3C575,
-
-	CH_3C575_1,
-	CH_3CCFE575,
-	CH_3CCFE575CT,
-	CH_3CCFE656,
-	CH_3CCFEM656,
-
-	CH_3CCFEM656_1,
-	CH_3C450,
-	CH_3C920,
-	CH_3C982A,
-	CH_3C982B,
-
-	CH_905BT4,
-	CH_920B_EMB_WNM,
-};
-
-
-/* note: this array directly indexed by above enums, and MUST
- * be kept in sync with both the enums above, and the PCI device
- * table below
- */
-static struct vortex_chip_info {
-	const char *name;
-	int flags;
-	int drv_flags;
-	int io_size;
-} vortex_info_tbl[] __devinitdata = {
-	{"3c590 Vortex 10Mbps",
-	 PCI_USES_MASTER, IS_VORTEX, 32, },
-	{"3c592 EISA 10Mbps Demon/Vortex",					/* AKPM: from Don's 3c59x_cb.c 0.49H */
-	 PCI_USES_MASTER, IS_VORTEX, 32, },
-	{"3c597 EISA Fast Demon/Vortex",					/* AKPM: from Don's 3c59x_cb.c 0.49H */
-	 PCI_USES_MASTER, IS_VORTEX, 32, },
-	{"3c595 Vortex 100baseTx",
-	 PCI_USES_MASTER, IS_VORTEX, 32, },
-	{"3c595 Vortex 100baseT4",
-	 PCI_USES_MASTER, IS_VORTEX, 32, },
-
-	{"3c595 Vortex 100base-MII",
-	 PCI_USES_MASTER, IS_VORTEX, 32, },
-	{"3c900 Boomerang 10baseT",
-	 PCI_USES_MASTER, IS_BOOMERANG|EEPROM_RESET, 64, },
-	{"3c900 Boomerang 10Mbps Combo",
-	 PCI_USES_MASTER, IS_BOOMERANG|EEPROM_RESET, 64, },
-	{"3c900 Cyclone 10Mbps TPO",						/* AKPM: from Don's 0.99M */
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
-	{"3c900 Cyclone 10Mbps Combo",
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
-
-	{"3c900 Cyclone 10Mbps TPC",						/* AKPM: from Don's 0.99M */
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
-	{"3c900B-FL Cyclone 10base-FL",
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
-	{"3c905 Boomerang 100baseTx",
-	 PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, },
-	{"3c905 Boomerang 100baseT4",
-	 PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, },
-	{"3C905B-TX Fast Etherlink XL PCI",
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
-	{"3c905B Cyclone 100baseTx",
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
-
-	{"3c905B Cyclone 10/100/BNC",
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
-	{"3c905B-FX Cyclone 100baseFx",
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
-	{"3c905C Tornado",
-	PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
-	{"3c920B-EMB-WNM (ATI Radeon 9100 IGP)",
-	 PCI_USES_MASTER, IS_TORNADO|HAS_MII|HAS_HWCKSM, 128, },
-	{"3c980 Cyclone",
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
-
-	{"3c980C Python-T",
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
-	{"3cSOHO100-TX Hurricane",
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
-	{"3c555 Laptop Hurricane",
-	 PCI_USES_MASTER, IS_CYCLONE|EEPROM_8BIT|HAS_HWCKSM, 128, },
-	{"3c556 Laptop Tornado",
-	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_8BIT|HAS_CB_FNS|INVERT_MII_PWR|
-									HAS_HWCKSM, 128, },
-	{"3c556B Laptop Hurricane",
-	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_OFFSET|HAS_CB_FNS|INVERT_MII_PWR|
-	                                WNO_XCVR_PWR|HAS_HWCKSM, 128, },
-
-	{"3c575 [Megahertz] 10/100 LAN 	CardBus",
-	PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, },
-	{"3c575 Boomerang CardBus",
-	 PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, },
-	{"3CCFE575BT Cyclone CardBus",
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|
-									INVERT_LED_PWR|HAS_HWCKSM, 128, },
-	{"3CCFE575CT Tornado CardBus",
-	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
-									MAX_COLLISION_RESET|HAS_HWCKSM, 128, },
-	{"3CCFE656 Cyclone CardBus",
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
-									INVERT_LED_PWR|HAS_HWCKSM, 128, },
-
-	{"3CCFEM656B Cyclone+Winmodem CardBus",
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
-									INVERT_LED_PWR|HAS_HWCKSM, 128, },
-	{"3CXFEM656C Tornado+Winmodem CardBus",			/* From pcmcia-cs-3.1.5 */
-	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
-									MAX_COLLISION_RESET|HAS_HWCKSM, 128, },
-	{"3c450 HomePNA Tornado",						/* AKPM: from Don's 0.99Q */
-	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
-	{"3c920 Tornado",
-	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
-	{"3c982 Hydra Dual Port A",
-	 PCI_USES_MASTER, IS_TORNADO|HAS_HWCKSM|HAS_NWAY, 128, },
-
-	{"3c982 Hydra Dual Port B",
-	 PCI_USES_MASTER, IS_TORNADO|HAS_HWCKSM|HAS_NWAY, 128, },
-	{"3c905B-T4",
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
-	{"3c920B-EMB-WNM Tornado",
-	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
-
-	{NULL,}, /* NULL terminated list. */
-};
-
-
-static DEFINE_PCI_DEVICE_TABLE(vortex_pci_tbl) = {
-	{ 0x10B7, 0x5900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C590 },
-	{ 0x10B7, 0x5920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C592 },
-	{ 0x10B7, 0x5970, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C597 },
-	{ 0x10B7, 0x5950, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C595_1 },
-	{ 0x10B7, 0x5951, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C595_2 },
-
-	{ 0x10B7, 0x5952, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C595_3 },
-	{ 0x10B7, 0x9000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_1 },
-	{ 0x10B7, 0x9001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_2 },
-	{ 0x10B7, 0x9004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_3 },
-	{ 0x10B7, 0x9005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_4 },
-
-	{ 0x10B7, 0x9006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_5 },
-	{ 0x10B7, 0x900A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900B_FL },
-	{ 0x10B7, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_1 },
-	{ 0x10B7, 0x9051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_2 },
-	{ 0x10B7, 0x9054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_TX },
-	{ 0x10B7, 0x9055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_1 },
-
-	{ 0x10B7, 0x9058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_2 },
-	{ 0x10B7, 0x905A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_FX },
-	{ 0x10B7, 0x9200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905C },
-	{ 0x10B7, 0x9202, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C9202 },
-	{ 0x10B7, 0x9800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C980 },
-	{ 0x10B7, 0x9805, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C9805 },
-
-	{ 0x10B7, 0x7646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CSOHO100_TX },
-	{ 0x10B7, 0x5055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C555 },
-	{ 0x10B7, 0x6055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C556 },
-	{ 0x10B7, 0x6056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C556B },
-	{ 0x10B7, 0x5b57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575 },
-
-	{ 0x10B7, 0x5057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575_1 },
-	{ 0x10B7, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575 },
-	{ 0x10B7, 0x5257, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575CT },
-	{ 0x10B7, 0x6560, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE656 },
-	{ 0x10B7, 0x6562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656 },
-
-	{ 0x10B7, 0x6564, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656_1 },
-	{ 0x10B7, 0x4500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C450 },
-	{ 0x10B7, 0x9201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C920 },
-	{ 0x10B7, 0x1201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C982A },
-	{ 0x10B7, 0x1202, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C982B },
-
-	{ 0x10B7, 0x9056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_905BT4 },
-	{ 0x10B7, 0x9210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_920B_EMB_WNM },
-
-	{0,}						/* 0 terminated list. */
-};
-MODULE_DEVICE_TABLE(pci, vortex_pci_tbl);
-
-
-/* Operational definitions.
-   These are not used by other compilation units and thus are not
-   exported in a ".h" file.
-
-   First the windows.  There are eight register windows, with the command
-   and status registers available in each.
-   */
-#define EL3_CMD 0x0e
-#define EL3_STATUS 0x0e
-
-/* The top five bits written to EL3_CMD are a command, the lower
-   11 bits are the parameter, if applicable.
-   Note that 11 parameters bits was fine for ethernet, but the new chip
-   can handle FDDI length frames (~4500 octets) and now parameters count
-   32-bit 'Dwords' rather than octets. */
-
-enum vortex_cmd {
-	TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
-	RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11,
-	UpStall = 6<<11, UpUnstall = (6<<11)+1,
-	DownStall = (6<<11)+2, DownUnstall = (6<<11)+3,
-	RxDiscard = 8<<11, TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
-	FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
-	SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
-	SetTxThreshold = 18<<11, SetTxStart = 19<<11,
-	StartDMAUp = 20<<11, StartDMADown = (20<<11)+1, StatsEnable = 21<<11,
-	StatsDisable = 22<<11, StopCoax = 23<<11, SetFilterBit = 25<<11,};
-
-/* The SetRxFilter command accepts the following classes: */
-enum RxFilter {
-	RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 };
-
-/* Bits in the general status register. */
-enum vortex_status {
-	IntLatch = 0x0001, HostError = 0x0002, TxComplete = 0x0004,
-	TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
-	IntReq = 0x0040, StatsFull = 0x0080,
-	DMADone = 1<<8, DownComplete = 1<<9, UpComplete = 1<<10,
-	DMAInProgress = 1<<11,			/* DMA controller is still busy.*/
-	CmdInProgress = 1<<12,			/* EL3_CMD is still busy.*/
-};
-
-/* Register window 1 offsets, the window used in normal operation.
-   On the Vortex this window is always mapped at offsets 0x10-0x1f. */
-enum Window1 {
-	TX_FIFO = 0x10,  RX_FIFO = 0x10,  RxErrors = 0x14,
-	RxStatus = 0x18,  Timer=0x1A, TxStatus = 0x1B,
-	TxFree = 0x1C, /* Remaining free bytes in Tx buffer. */
-};
-enum Window0 {
-	Wn0EepromCmd = 10,		/* Window 0: EEPROM command register. */
-	Wn0EepromData = 12,		/* Window 0: EEPROM results register. */
-	IntrStatus=0x0E,		/* Valid in all windows. */
-};
-enum Win0_EEPROM_bits {
-	EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
-	EEPROM_EWENB = 0x30,		/* Enable erasing/writing for 10 msec. */
-	EEPROM_EWDIS = 0x00,		/* Disable EWENB before 10 msec timeout. */
-};
-/* EEPROM locations. */
-enum eeprom_offset {
-	PhysAddr01=0, PhysAddr23=1, PhysAddr45=2, ModelID=3,
-	EtherLink3ID=7, IFXcvrIO=8, IRQLine=9,
-	NodeAddr01=10, NodeAddr23=11, NodeAddr45=12,
-	DriverTune=13, Checksum=15};
-
-enum Window2 {			/* Window 2. */
-	Wn2_ResetOptions=12,
-};
-enum Window3 {			/* Window 3: MAC/config bits. */
-	Wn3_Config=0, Wn3_MaxPktSize=4, Wn3_MAC_Ctrl=6, Wn3_Options=8,
-};
-
-#define BFEXT(value, offset, bitcount)  \
-    ((((unsigned long)(value)) >> (offset)) & ((1 << (bitcount)) - 1))
-
-#define BFINS(lhs, rhs, offset, bitcount)					\
-	(((lhs) & ~((((1 << (bitcount)) - 1)) << (offset))) |	\
-	(((rhs) & ((1 << (bitcount)) - 1)) << (offset)))
-
-#define RAM_SIZE(v)		BFEXT(v, 0, 3)
-#define RAM_WIDTH(v)	BFEXT(v, 3, 1)
-#define RAM_SPEED(v)	BFEXT(v, 4, 2)
-#define ROM_SIZE(v)		BFEXT(v, 6, 2)
-#define RAM_SPLIT(v)	BFEXT(v, 16, 2)
-#define XCVR(v)			BFEXT(v, 20, 4)
-#define AUTOSELECT(v)	BFEXT(v, 24, 1)
-
-enum Window4 {		/* Window 4: Xcvr/media bits. */
-	Wn4_FIFODiag = 4, Wn4_NetDiag = 6, Wn4_PhysicalMgmt=8, Wn4_Media = 10,
-};
-enum Win4_Media_bits {
-	Media_SQE = 0x0008,		/* Enable SQE error counting for AUI. */
-	Media_10TP = 0x00C0,	/* Enable link beat and jabber for 10baseT. */
-	Media_Lnk = 0x0080,		/* Enable just link beat for 100TX/100FX. */
-	Media_LnkBeat = 0x0800,
-};
-enum Window7 {					/* Window 7: Bus Master control. */
-	Wn7_MasterAddr = 0, Wn7_VlanEtherType=4, Wn7_MasterLen = 6,
-	Wn7_MasterStatus = 12,
-};
-/* Boomerang bus master control registers. */
-enum MasterCtrl {
-	PktStatus = 0x20, DownListPtr = 0x24, FragAddr = 0x28, FragLen = 0x2c,
-	TxFreeThreshold = 0x2f, UpPktStatus = 0x30, UpListPtr = 0x38,
-};
-
-/* The Rx and Tx descriptor lists.
-   Caution Alpha hackers: these types are 32 bits!  Note also the 8 byte
-   alignment contraint on tx_ring[] and rx_ring[]. */
-#define LAST_FRAG 	0x80000000			/* Last Addr/Len pair in descriptor. */
-#define DN_COMPLETE	0x00010000			/* This packet has been downloaded */
-struct boom_rx_desc {
-	__le32 next;					/* Last entry points to 0.   */
-	__le32 status;
-	__le32 addr;					/* Up to 63 addr/len pairs possible. */
-	__le32 length;					/* Set LAST_FRAG to indicate last pair. */
-};
-/* Values for the Rx status entry. */
-enum rx_desc_status {
-	RxDComplete=0x00008000, RxDError=0x4000,
-	/* See boomerang_rx() for actual error bits */
-	IPChksumErr=1<<25, TCPChksumErr=1<<26, UDPChksumErr=1<<27,
-	IPChksumValid=1<<29, TCPChksumValid=1<<30, UDPChksumValid=1<<31,
-};
-
-#ifdef MAX_SKB_FRAGS
-#define DO_ZEROCOPY 1
-#else
-#define DO_ZEROCOPY 0
-#endif
-
-struct boom_tx_desc {
-	__le32 next;					/* Last entry points to 0.   */
-	__le32 status;					/* bits 0:12 length, others see below.  */
-#if DO_ZEROCOPY
-	struct {
-		__le32 addr;
-		__le32 length;
-	} frag[1+MAX_SKB_FRAGS];
-#else
-		__le32 addr;
-		__le32 length;
-#endif
-};
-
-/* Values for the Tx status entry. */
-enum tx_desc_status {
-	CRCDisable=0x2000, TxDComplete=0x8000,
-	AddIPChksum=0x02000000, AddTCPChksum=0x04000000, AddUDPChksum=0x08000000,
-	TxIntrUploaded=0x80000000,		/* IRQ when in FIFO, but maybe not sent. */
-};
-
-/* Chip features we care about in vp->capabilities, read from the EEPROM. */
-enum ChipCaps { CapBusMaster=0x20, CapPwrMgmt=0x2000 };
-
-struct vortex_extra_stats {
-	unsigned long tx_deferred;
-	unsigned long tx_max_collisions;
-	unsigned long tx_multiple_collisions;
-	unsigned long tx_single_collisions;
-	unsigned long rx_bad_ssd;
-};
-
-struct vortex_private {
-	/* The Rx and Tx rings should be quad-word-aligned. */
-	struct boom_rx_desc* rx_ring;
-	struct boom_tx_desc* tx_ring;
-	dma_addr_t rx_ring_dma;
-	dma_addr_t tx_ring_dma;
-	/* The addresses of transmit- and receive-in-place skbuffs. */
-	struct sk_buff* rx_skbuff[RX_RING_SIZE];
-	struct sk_buff* tx_skbuff[TX_RING_SIZE];
-	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
-	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
-	struct vortex_extra_stats xstats;	/* NIC-specific extra stats */
-	struct sk_buff *tx_skb;				/* Packet being eaten by bus master ctrl.  */
-	dma_addr_t tx_skb_dma;				/* Allocated DMA address for bus master ctrl DMA.   */
-
-	/* PCI configuration space information. */
-	struct device *gendev;
-	void __iomem *ioaddr;			/* IO address space */
-	void __iomem *cb_fn_base;		/* CardBus function status addr space. */
-
-	/* Some values here only for performance evaluation and path-coverage */
-	int rx_nocopy, rx_copy, queued_packet, rx_csumhits;
-	int card_idx;
-
-	/* The remainder are related to chip state, mostly media selection. */
-	struct timer_list timer;			/* Media selection timer. */
-	struct timer_list rx_oom_timer;		/* Rx skb allocation retry timer */
-	int options;						/* User-settable misc. driver options. */
-	unsigned int media_override:4, 		/* Passed-in media type. */
-		default_media:4,				/* Read from the EEPROM/Wn3_Config. */
-		full_duplex:1, autoselect:1,
-		bus_master:1,					/* Vortex can only do a fragment bus-m. */
-		full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang  */
-		flow_ctrl:1,					/* Use 802.3x flow control (PAUSE only) */
-		partner_flow_ctrl:1,			/* Partner supports flow control */
-		has_nway:1,
-		enable_wol:1,					/* Wake-on-LAN is enabled */
-		pm_state_valid:1,				/* pci_dev->saved_config_space has sane contents */
-		open:1,
-		medialock:1,
-		must_free_region:1,				/* Flag: if zero, Cardbus owns the I/O region */
-		large_frames:1,			/* accept large frames */
-		handling_irq:1;			/* private in_irq indicator */
-	/* {get|set}_wol operations are already serialized by rtnl.
-	 * no additional locking is required for the enable_wol and acpi_set_WOL()
-	 */
-	int drv_flags;
-	u16 status_enable;
-	u16 intr_enable;
-	u16 available_media;				/* From Wn3_Options. */
-	u16 capabilities, info1, info2;		/* Various, from EEPROM. */
-	u16 advertising;					/* NWay media advertisement */
-	unsigned char phys[2];				/* MII device addresses. */
-	u16 deferred;						/* Resend these interrupts when we
-										 * bale from the ISR */
-	u16 io_size;						/* Size of PCI region (for release_region) */
-
-	/* Serialises access to hardware other than MII and variables below.
-	 * The lock hierarchy is rtnl_lock > {lock, mii_lock} > window_lock. */
-	spinlock_t lock;
-
-	spinlock_t mii_lock;		/* Serialises access to MII */
-	struct mii_if_info mii;		/* MII lib hooks/info */
-	spinlock_t window_lock;		/* Serialises access to windowed regs */
-	int window;			/* Register window */
-};
-
-static void window_set(struct vortex_private *vp, int window)
-{
-	if (window != vp->window) {
-		iowrite16(SelectWindow + window, vp->ioaddr + EL3_CMD);
-		vp->window = window;
-	}
-}
-
-#define DEFINE_WINDOW_IO(size)						\
-static u ## size							\
-window_read ## size(struct vortex_private *vp, int window, int addr)	\
-{									\
-	unsigned long flags;						\
-	u ## size ret;							\
-	spin_lock_irqsave(&vp->window_lock, flags);			\
-	window_set(vp, window);						\
-	ret = ioread ## size(vp->ioaddr + addr);			\
-	spin_unlock_irqrestore(&vp->window_lock, flags);		\
-	return ret;							\
-}									\
-static void								\
-window_write ## size(struct vortex_private *vp, u ## size value,	\
-		     int window, int addr)				\
-{									\
-	unsigned long flags;						\
-	spin_lock_irqsave(&vp->window_lock, flags);			\
-	window_set(vp, window);						\
-	iowrite ## size(value, vp->ioaddr + addr);			\
-	spin_unlock_irqrestore(&vp->window_lock, flags);		\
-}
-DEFINE_WINDOW_IO(8)
-DEFINE_WINDOW_IO(16)
-DEFINE_WINDOW_IO(32)
-
-#ifdef CONFIG_PCI
-#define DEVICE_PCI(dev) (((dev)->bus == &pci_bus_type) ? to_pci_dev((dev)) : NULL)
-#else
-#define DEVICE_PCI(dev) NULL
-#endif
-
-#define VORTEX_PCI(vp)							\
-	((struct pci_dev *) (((vp)->gendev) ? DEVICE_PCI((vp)->gendev) : NULL))
-
-#ifdef CONFIG_EISA
-#define DEVICE_EISA(dev) (((dev)->bus == &eisa_bus_type) ? to_eisa_device((dev)) : NULL)
-#else
-#define DEVICE_EISA(dev) NULL
-#endif
-
-#define VORTEX_EISA(vp)							\
-	((struct eisa_device *) (((vp)->gendev) ? DEVICE_EISA((vp)->gendev) : NULL))
-
-/* The action to take with a media selection timer tick.
-   Note that we deviate from the 3Com order by checking 10base2 before AUI.
- */
-enum xcvr_types {
-	XCVR_10baseT=0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,
-	XCVR_100baseFx, XCVR_MII=6, XCVR_NWAY=8, XCVR_ExtMII=9, XCVR_Default=10,
-};
-
-static const struct media_table {
-	char *name;
-	unsigned int media_bits:16,		/* Bits to set in Wn4_Media register. */
-		mask:8,						/* The transceiver-present bit in Wn3_Config.*/
-		next:8;						/* The media type to try next. */
-	int wait;						/* Time before we check media status. */
-} media_tbl[] = {
-  {	"10baseT",   Media_10TP,0x08, XCVR_10base2, (14*HZ)/10},
-  { "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1*HZ)/10},
-  { "undefined", 0,			0x80, XCVR_10baseT, 10000},
-  { "10base2",   0,			0x10, XCVR_AUI,		(1*HZ)/10},
-  { "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14*HZ)/10},
-  { "100baseFX", Media_Lnk, 0x04, XCVR_MII,		(14*HZ)/10},
-  { "MII",		 0,			0x41, XCVR_10baseT, 3*HZ },
-  { "undefined", 0,			0x01, XCVR_10baseT, 10000},
-  { "Autonegotiate", 0,		0x41, XCVR_10baseT, 3*HZ},
-  { "MII-External",	 0,		0x41, XCVR_10baseT, 3*HZ },
-  { "Default",	 0,			0xFF, XCVR_10baseT, 10000},
-};
-
-static struct {
-	const char str[ETH_GSTRING_LEN];
-} ethtool_stats_keys[] = {
-	{ "tx_deferred" },
-	{ "tx_max_collisions" },
-	{ "tx_multiple_collisions" },
-	{ "tx_single_collisions" },
-	{ "rx_bad_ssd" },
-};
-
-/* number of ETHTOOL_GSTATS u64's */
-#define VORTEX_NUM_STATS    5
-
-static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
-				   int chip_idx, int card_idx);
-static int vortex_up(struct net_device *dev);
-static void vortex_down(struct net_device *dev, int final);
-static int vortex_open(struct net_device *dev);
-static void mdio_sync(struct vortex_private *vp, int bits);
-static int mdio_read(struct net_device *dev, int phy_id, int location);
-static void mdio_write(struct net_device *vp, int phy_id, int location, int value);
-static void vortex_timer(unsigned long arg);
-static void rx_oom_timer(unsigned long arg);
-static netdev_tx_t vortex_start_xmit(struct sk_buff *skb,
-				     struct net_device *dev);
-static netdev_tx_t boomerang_start_xmit(struct sk_buff *skb,
-					struct net_device *dev);
-static int vortex_rx(struct net_device *dev);
-static int boomerang_rx(struct net_device *dev);
-static irqreturn_t vortex_interrupt(int irq, void *dev_id);
-static irqreturn_t boomerang_interrupt(int irq, void *dev_id);
-static int vortex_close(struct net_device *dev);
-static void dump_tx_ring(struct net_device *dev);
-static void update_stats(void __iomem *ioaddr, struct net_device *dev);
-static struct net_device_stats *vortex_get_stats(struct net_device *dev);
-static void set_rx_mode(struct net_device *dev);
-#ifdef CONFIG_PCI
-static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-#endif
-static void vortex_tx_timeout(struct net_device *dev);
-static void acpi_set_WOL(struct net_device *dev);
-static const struct ethtool_ops vortex_ethtool_ops;
-static void set_8021q_mode(struct net_device *dev, int enable);
-
-/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
-/* Option count limit only -- unlimited interfaces are supported. */
-#define MAX_UNITS 8
-static int options[MAX_UNITS] = { [0 ... MAX_UNITS-1] = -1 };
-static int full_duplex[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
-static int hw_checksums[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
-static int flow_ctrl[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
-static int enable_wol[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
-static int use_mmio[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
-static int global_options = -1;
-static int global_full_duplex = -1;
-static int global_enable_wol = -1;
-static int global_use_mmio = -1;
-
-/* Variables to work-around the Compaq PCI BIOS32 problem. */
-static int compaq_ioaddr, compaq_irq, compaq_device_id = 0x5900;
-static struct net_device *compaq_net_device;
-
-static int vortex_cards_found;
-
-module_param(debug, int, 0);
-module_param(global_options, int, 0);
-module_param_array(options, int, NULL, 0);
-module_param(global_full_duplex, int, 0);
-module_param_array(full_duplex, int, NULL, 0);
-module_param_array(hw_checksums, int, NULL, 0);
-module_param_array(flow_ctrl, int, NULL, 0);
-module_param(global_enable_wol, int, 0);
-module_param_array(enable_wol, int, NULL, 0);
-module_param(rx_copybreak, int, 0);
-module_param(max_interrupt_work, int, 0);
-module_param(compaq_ioaddr, int, 0);
-module_param(compaq_irq, int, 0);
-module_param(compaq_device_id, int, 0);
-module_param(watchdog, int, 0);
-module_param(global_use_mmio, int, 0);
-module_param_array(use_mmio, int, NULL, 0);
-MODULE_PARM_DESC(debug, "3c59x debug level (0-6)");
-MODULE_PARM_DESC(options, "3c59x: Bits 0-3: media type, bit 4: bus mastering, bit 9: full duplex");
-MODULE_PARM_DESC(global_options, "3c59x: same as options, but applies to all NICs if options is unset");
-MODULE_PARM_DESC(full_duplex, "3c59x full duplex setting(s) (1)");
-MODULE_PARM_DESC(global_full_duplex, "3c59x: same as full_duplex, but applies to all NICs if full_duplex is unset");
-MODULE_PARM_DESC(hw_checksums, "3c59x Hardware checksum checking by adapter(s) (0-1)");
-MODULE_PARM_DESC(flow_ctrl, "3c59x 802.3x flow control usage (PAUSE only) (0-1)");
-MODULE_PARM_DESC(enable_wol, "3c59x: Turn on Wake-on-LAN for adapter(s) (0-1)");
-MODULE_PARM_DESC(global_enable_wol, "3c59x: same as enable_wol, but applies to all NICs if enable_wol is unset");
-MODULE_PARM_DESC(rx_copybreak, "3c59x copy breakpoint for copy-only-tiny-frames");
-MODULE_PARM_DESC(max_interrupt_work, "3c59x maximum events handled per interrupt");
-MODULE_PARM_DESC(compaq_ioaddr, "3c59x PCI I/O base address (Compaq BIOS problem workaround)");
-MODULE_PARM_DESC(compaq_irq, "3c59x PCI IRQ number (Compaq BIOS problem workaround)");
-MODULE_PARM_DESC(compaq_device_id, "3c59x PCI device ID (Compaq BIOS problem workaround)");
-MODULE_PARM_DESC(watchdog, "3c59x transmit timeout in milliseconds");
-MODULE_PARM_DESC(global_use_mmio, "3c59x: same as use_mmio, but applies to all NICs if options is unset");
-MODULE_PARM_DESC(use_mmio, "3c59x: use memory-mapped PCI I/O resource (0-1)");
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void poll_vortex(struct net_device *dev)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	unsigned long flags;
-	local_irq_save(flags);
-	(vp->full_bus_master_rx ? boomerang_interrupt:vortex_interrupt)(dev->irq,dev);
-	local_irq_restore(flags);
-}
-#endif
-
-#ifdef CONFIG_PM
-
-static int vortex_suspend(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct net_device *ndev = pci_get_drvdata(pdev);
-
-	if (!ndev || !netif_running(ndev))
-		return 0;
-
-	netif_device_detach(ndev);
-	vortex_down(ndev, 1);
-
-	return 0;
-}
-
-static int vortex_resume(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct net_device *ndev = pci_get_drvdata(pdev);
-	int err;
-
-	if (!ndev || !netif_running(ndev))
-		return 0;
-
-	err = vortex_up(ndev);
-	if (err)
-		return err;
-
-	netif_device_attach(ndev);
-
-	return 0;
-}
-
-static const struct dev_pm_ops vortex_pm_ops = {
-	.suspend = vortex_suspend,
-	.resume = vortex_resume,
-	.freeze = vortex_suspend,
-	.thaw = vortex_resume,
-	.poweroff = vortex_suspend,
-	.restore = vortex_resume,
-};
-
-#define VORTEX_PM_OPS (&vortex_pm_ops)
-
-#else /* !CONFIG_PM */
-
-#define VORTEX_PM_OPS NULL
-
-#endif /* !CONFIG_PM */
-
-#ifdef CONFIG_EISA
-static struct eisa_device_id vortex_eisa_ids[] = {
-	{ "TCM5920", CH_3C592 },
-	{ "TCM5970", CH_3C597 },
-	{ "" }
-};
-MODULE_DEVICE_TABLE(eisa, vortex_eisa_ids);
-
-static int __init vortex_eisa_probe(struct device *device)
-{
-	void __iomem *ioaddr;
-	struct eisa_device *edev;
-
-	edev = to_eisa_device(device);
-
-	if (!request_region(edev->base_addr, VORTEX_TOTAL_SIZE, DRV_NAME))
-		return -EBUSY;
-
-	ioaddr = ioport_map(edev->base_addr, VORTEX_TOTAL_SIZE);
-
-	if (vortex_probe1(device, ioaddr, ioread16(ioaddr + 0xC88) >> 12,
-					  edev->id.driver_data, vortex_cards_found)) {
-		release_region(edev->base_addr, VORTEX_TOTAL_SIZE);
-		return -ENODEV;
-	}
-
-	vortex_cards_found++;
-
-	return 0;
-}
-
-static int __devexit vortex_eisa_remove(struct device *device)
-{
-	struct eisa_device *edev;
-	struct net_device *dev;
-	struct vortex_private *vp;
-	void __iomem *ioaddr;
-
-	edev = to_eisa_device(device);
-	dev = eisa_get_drvdata(edev);
-
-	if (!dev) {
-		pr_err("vortex_eisa_remove called for Compaq device!\n");
-		BUG();
-	}
-
-	vp = netdev_priv(dev);
-	ioaddr = vp->ioaddr;
-
-	unregister_netdev(dev);
-	iowrite16(TotalReset|0x14, ioaddr + EL3_CMD);
-	release_region(dev->base_addr, VORTEX_TOTAL_SIZE);
-
-	free_netdev(dev);
-	return 0;
-}
-
-static struct eisa_driver vortex_eisa_driver = {
-	.id_table = vortex_eisa_ids,
-	.driver   = {
-		.name    = "3c59x",
-		.probe   = vortex_eisa_probe,
-		.remove  = __devexit_p(vortex_eisa_remove)
-	}
-};
-
-#endif /* CONFIG_EISA */
-
-/* returns count found (>= 0), or negative on error */
-static int __init vortex_eisa_init(void)
-{
-	int eisa_found = 0;
-	int orig_cards_found = vortex_cards_found;
-
-#ifdef CONFIG_EISA
-	int err;
-
-	err = eisa_driver_register (&vortex_eisa_driver);
-	if (!err) {
-		/*
-		 * Because of the way EISA bus is probed, we cannot assume
-		 * 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 happened...
-		 */
-		eisa_found = 1;
-	}
-#endif
-
-	/* Special code to work-around the Compaq PCI BIOS32 problem. */
-	if (compaq_ioaddr) {
-		vortex_probe1(NULL, ioport_map(compaq_ioaddr, VORTEX_TOTAL_SIZE),
-			      compaq_irq, compaq_device_id, vortex_cards_found++);
-	}
-
-	return vortex_cards_found - orig_cards_found + eisa_found;
-}
-
-/* returns count (>= 0), or negative on error */
-static int __devinit vortex_init_one(struct pci_dev *pdev,
-				      const struct pci_device_id *ent)
-{
-	int rc, unit, pci_bar;
-	struct vortex_chip_info *vci;
-	void __iomem *ioaddr;
-
-	/* wake up and enable device */
-	rc = pci_enable_device(pdev);
-	if (rc < 0)
-		goto out;
-
-	unit = vortex_cards_found;
-
-	if (global_use_mmio < 0 && (unit >= MAX_UNITS || use_mmio[unit] < 0)) {
-		/* Determine the default if the user didn't override us */
-		vci = &vortex_info_tbl[ent->driver_data];
-		pci_bar = vci->drv_flags & (IS_CYCLONE | IS_TORNADO) ? 1 : 0;
-	} else if (unit < MAX_UNITS && use_mmio[unit] >= 0)
-		pci_bar = use_mmio[unit] ? 1 : 0;
-	else
-		pci_bar = global_use_mmio ? 1 : 0;
-
-	ioaddr = pci_iomap(pdev, pci_bar, 0);
-	if (!ioaddr) /* If mapping fails, fall-back to BAR 0... */
-		ioaddr = pci_iomap(pdev, 0, 0);
-	if (!ioaddr) {
-		pci_disable_device(pdev);
-		rc = -ENOMEM;
-		goto out;
-	}
-
-	rc = vortex_probe1(&pdev->dev, ioaddr, pdev->irq,
-			   ent->driver_data, unit);
-	if (rc < 0) {
-		pci_iounmap(pdev, ioaddr);
-		pci_disable_device(pdev);
-		goto out;
-	}
-
-	vortex_cards_found++;
-
-out:
-	return rc;
-}
-
-static const struct net_device_ops boomrang_netdev_ops = {
-	.ndo_open		= vortex_open,
-	.ndo_stop		= vortex_close,
-	.ndo_start_xmit		= boomerang_start_xmit,
-	.ndo_tx_timeout		= vortex_tx_timeout,
-	.ndo_get_stats		= vortex_get_stats,
-#ifdef CONFIG_PCI
-	.ndo_do_ioctl 		= vortex_ioctl,
-#endif
-	.ndo_set_multicast_list = set_rx_mode,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= poll_vortex,
-#endif
-};
-
-static const struct net_device_ops vortex_netdev_ops = {
-	.ndo_open		= vortex_open,
-	.ndo_stop		= vortex_close,
-	.ndo_start_xmit		= vortex_start_xmit,
-	.ndo_tx_timeout		= vortex_tx_timeout,
-	.ndo_get_stats		= vortex_get_stats,
-#ifdef CONFIG_PCI
-	.ndo_do_ioctl 		= vortex_ioctl,
-#endif
-	.ndo_set_multicast_list = set_rx_mode,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= poll_vortex,
-#endif
-};
-
-/*
- * Start up the PCI/EISA device which is described by *gendev.
- * Return 0 on success.
- *
- * NOTE: pdev can be NULL, for the case of a Compaq device
- */
-static int __devinit vortex_probe1(struct device *gendev,
-				   void __iomem *ioaddr, int irq,
-				   int chip_idx, int card_idx)
-{
-	struct vortex_private *vp;
-	int option;
-	unsigned int eeprom[0x40], checksum = 0;		/* EEPROM contents */
-	int i, step;
-	struct net_device *dev;
-	static int printed_version;
-	int retval, print_info;
-	struct vortex_chip_info * const vci = &vortex_info_tbl[chip_idx];
-	const char *print_name = "3c59x";
-	struct pci_dev *pdev = NULL;
-	struct eisa_device *edev = NULL;
-
-	if (!printed_version) {
-		pr_info("%s", version);
-		printed_version = 1;
-	}
-
-	if (gendev) {
-		if ((pdev = DEVICE_PCI(gendev))) {
-			print_name = pci_name(pdev);
-		}
-
-		if ((edev = DEVICE_EISA(gendev))) {
-			print_name = dev_name(&edev->dev);
-		}
-	}
-
-	dev = alloc_etherdev(sizeof(*vp));
-	retval = -ENOMEM;
-	if (!dev) {
-		pr_err(PFX "unable to allocate etherdev, aborting\n");
-		goto out;
-	}
-	SET_NETDEV_DEV(dev, gendev);
-	vp = netdev_priv(dev);
-
-	option = global_options;
-
-	/* The lower four bits are the media type. */
-	if (dev->mem_start) {
-		/*
-		 * The 'options' param is passed in as the third arg to the
-		 * LILO 'ether=' argument for non-modular use
-		 */
-		option = dev->mem_start;
-	}
-	else if (card_idx < MAX_UNITS) {
-		if (options[card_idx] >= 0)
-			option = options[card_idx];
-	}
-
-	if (option > 0) {
-		if (option & 0x8000)
-			vortex_debug = 7;
-		if (option & 0x4000)
-			vortex_debug = 2;
-		if (option & 0x0400)
-			vp->enable_wol = 1;
-	}
-
-	print_info = (vortex_debug > 1);
-	if (print_info)
-		pr_info("See Documentation/networking/vortex.txt\n");
-
-	pr_info("%s: 3Com %s %s at %p.\n",
-	       print_name,
-	       pdev ? "PCI" : "EISA",
-	       vci->name,
-	       ioaddr);
-
-	dev->base_addr = (unsigned long)ioaddr;
-	dev->irq = irq;
-	dev->mtu = mtu;
-	vp->ioaddr = ioaddr;
-	vp->large_frames = mtu > 1500;
-	vp->drv_flags = vci->drv_flags;
-	vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0;
-	vp->io_size = vci->io_size;
-	vp->card_idx = card_idx;
-	vp->window = -1;
-
-	/* module list only for Compaq device */
-	if (gendev == NULL) {
-		compaq_net_device = dev;
-	}
-
-	/* PCI-only startup logic */
-	if (pdev) {
-		/* EISA resources already marked, so only PCI needs to do this here */
-		/* Ignore return value, because Cardbus drivers already allocate for us */
-		if (request_region(dev->base_addr, vci->io_size, print_name) != NULL)
-			vp->must_free_region = 1;
-
-		/* enable bus-mastering if necessary */
-		if (vci->flags & PCI_USES_MASTER)
-			pci_set_master(pdev);
-
-		if (vci->drv_flags & IS_VORTEX) {
-			u8 pci_latency;
-			u8 new_latency = 248;
-
-			/* Check the PCI latency value.  On the 3c590 series the latency timer
-			   must be set to the maximum value to avoid data corruption that occurs
-			   when the timer expires during a transfer.  This bug exists the Vortex
-			   chip only. */
-			pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
-			if (pci_latency < new_latency) {
-				pr_info("%s: Overriding PCI latency timer (CFLT) setting of %d, new value is %d.\n",
-					print_name, pci_latency, new_latency);
-				pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency);
-			}
-		}
-	}
-
-	spin_lock_init(&vp->lock);
-	spin_lock_init(&vp->mii_lock);
-	spin_lock_init(&vp->window_lock);
-	vp->gendev = gendev;
-	vp->mii.dev = dev;
-	vp->mii.mdio_read = mdio_read;
-	vp->mii.mdio_write = mdio_write;
-	vp->mii.phy_id_mask = 0x1f;
-	vp->mii.reg_num_mask = 0x1f;
-
-	/* Makes sure rings are at least 16 byte aligned. */
-	vp->rx_ring = pci_alloc_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE
-					   + sizeof(struct boom_tx_desc) * TX_RING_SIZE,
-					   &vp->rx_ring_dma);
-	retval = -ENOMEM;
-	if (!vp->rx_ring)
-		goto free_region;
-
-	vp->tx_ring = (struct boom_tx_desc *)(vp->rx_ring + RX_RING_SIZE);
-	vp->tx_ring_dma = vp->rx_ring_dma + sizeof(struct boom_rx_desc) * RX_RING_SIZE;
-
-	/* if we are a PCI driver, we store info in pdev->driver_data
-	 * instead of a module list */
-	if (pdev)
-		pci_set_drvdata(pdev, dev);
-	if (edev)
-		eisa_set_drvdata(edev, dev);
-
-	vp->media_override = 7;
-	if (option >= 0) {
-		vp->media_override = ((option & 7) == 2)  ?  0  :  option & 15;
-		if (vp->media_override != 7)
-			vp->medialock = 1;
-		vp->full_duplex = (option & 0x200) ? 1 : 0;
-		vp->bus_master = (option & 16) ? 1 : 0;
-	}
-
-	if (global_full_duplex > 0)
-		vp->full_duplex = 1;
-	if (global_enable_wol > 0)
-		vp->enable_wol = 1;
-
-	if (card_idx < MAX_UNITS) {
-		if (full_duplex[card_idx] > 0)
-			vp->full_duplex = 1;
-		if (flow_ctrl[card_idx] > 0)
-			vp->flow_ctrl = 1;
-		if (enable_wol[card_idx] > 0)
-			vp->enable_wol = 1;
-	}
-
-	vp->mii.force_media = vp->full_duplex;
-	vp->options = option;
-	/* Read the station address from the EEPROM. */
-	{
-		int base;
-
-		if (vci->drv_flags & EEPROM_8BIT)
-			base = 0x230;
-		else if (vci->drv_flags & EEPROM_OFFSET)
-			base = EEPROM_Read + 0x30;
-		else
-			base = EEPROM_Read;
-
-		for (i = 0; i < 0x40; i++) {
-			int timer;
-			window_write16(vp, base + i, 0, Wn0EepromCmd);
-			/* Pause for at least 162 us. for the read to take place. */
-			for (timer = 10; timer >= 0; timer--) {
-				udelay(162);
-				if ((window_read16(vp, 0, Wn0EepromCmd) &
-				     0x8000) == 0)
-					break;
-			}
-			eeprom[i] = window_read16(vp, 0, Wn0EepromData);
-		}
-	}
-	for (i = 0; i < 0x18; i++)
-		checksum ^= eeprom[i];
-	checksum = (checksum ^ (checksum >> 8)) & 0xff;
-	if (checksum != 0x00) {		/* Grrr, needless incompatible change 3Com. */
-		while (i < 0x21)
-			checksum ^= eeprom[i++];
-		checksum = (checksum ^ (checksum >> 8)) & 0xff;
-	}
-	if ((checksum != 0x00) && !(vci->drv_flags & IS_TORNADO))
-		pr_cont(" ***INVALID CHECKSUM %4.4x*** ", checksum);
-	for (i = 0; i < 3; i++)
-		((__be16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]);
-	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-	if (print_info)
-		pr_cont(" %pM", dev->dev_addr);
-	/* Unfortunately an all zero eeprom passes the checksum and this
-	   gets found in the wild in failure cases. Crypto is hard 8) */
-	if (!is_valid_ether_addr(dev->dev_addr)) {
-		retval = -EINVAL;
-		pr_err("*** EEPROM MAC address is invalid.\n");
-		goto free_ring;	/* With every pack */
-	}
-	for (i = 0; i < 6; i++)
-		window_write8(vp, dev->dev_addr[i], 2, i);
-
-	if (print_info)
-		pr_cont(", IRQ %d\n", dev->irq);
-	/* Tell them about an invalid IRQ. */
-	if (dev->irq <= 0 || dev->irq >= nr_irqs)
-		pr_warning(" *** Warning: IRQ %d is unlikely to work! ***\n",
-			   dev->irq);
-
-	step = (window_read8(vp, 4, Wn4_NetDiag) & 0x1e) >> 1;
-	if (print_info) {
-		pr_info("  product code %02x%02x rev %02x.%d date %02d-%02d-%02d\n",
-			eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14],
-			step, (eeprom[4]>>5) & 15, eeprom[4] & 31, eeprom[4]>>9);
-	}
-
-
-	if (pdev && vci->drv_flags & HAS_CB_FNS) {
-		unsigned short n;
-
-		vp->cb_fn_base = pci_iomap(pdev, 2, 0);
-		if (!vp->cb_fn_base) {
-			retval = -ENOMEM;
-			goto free_ring;
-		}
-
-		if (print_info) {
-			pr_info("%s: CardBus functions mapped %16.16llx->%p\n",
-				print_name,
-				(unsigned long long)pci_resource_start(pdev, 2),
-				vp->cb_fn_base);
-		}
-
-		n = window_read16(vp, 2, Wn2_ResetOptions) & ~0x4010;
-		if (vp->drv_flags & INVERT_LED_PWR)
-			n |= 0x10;
-		if (vp->drv_flags & INVERT_MII_PWR)
-			n |= 0x4000;
-		window_write16(vp, n, 2, Wn2_ResetOptions);
-		if (vp->drv_flags & WNO_XCVR_PWR) {
-			window_write16(vp, 0x0800, 0, 0);
-		}
-	}
-
-	/* Extract our information from the EEPROM data. */
-	vp->info1 = eeprom[13];
-	vp->info2 = eeprom[15];
-	vp->capabilities = eeprom[16];
-
-	if (vp->info1 & 0x8000) {
-		vp->full_duplex = 1;
-		if (print_info)
-			pr_info("Full duplex capable\n");
-	}
-
-	{
-		static const char * const ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
-		unsigned int config;
-		vp->available_media = window_read16(vp, 3, Wn3_Options);
-		if ((vp->available_media & 0xff) == 0)		/* Broken 3c916 */
-			vp->available_media = 0x40;
-		config = window_read32(vp, 3, Wn3_Config);
-		if (print_info) {
-			pr_debug("  Internal config register is %4.4x, transceivers %#x.\n",
-				config, window_read16(vp, 3, Wn3_Options));
-			pr_info("  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
-				   8 << RAM_SIZE(config),
-				   RAM_WIDTH(config) ? "word" : "byte",
-				   ram_split[RAM_SPLIT(config)],
-				   AUTOSELECT(config) ? "autoselect/" : "",
-				   XCVR(config) > XCVR_ExtMII ? "<invalid transceiver>" :
-				   media_tbl[XCVR(config)].name);
-		}
-		vp->default_media = XCVR(config);
-		if (vp->default_media == XCVR_NWAY)
-			vp->has_nway = 1;
-		vp->autoselect = AUTOSELECT(config);
-	}
-
-	if (vp->media_override != 7) {
-		pr_info("%s:  Media override to transceiver type %d (%s).\n",
-				print_name, vp->media_override,
-				media_tbl[vp->media_override].name);
-		dev->if_port = vp->media_override;
-	} else
-		dev->if_port = vp->default_media;
-
-	if ((vp->available_media & 0x40) || (vci->drv_flags & HAS_NWAY) ||
-		dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
-		int phy, phy_idx = 0;
-		mii_preamble_required++;
-		if (vp->drv_flags & EXTRA_PREAMBLE)
-			mii_preamble_required++;
-		mdio_sync(vp, 32);
-		mdio_read(dev, 24, MII_BMSR);
-		for (phy = 0; phy < 32 && phy_idx < 1; phy++) {
-			int mii_status, phyx;
-
-			/*
-			 * For the 3c905CX we look at index 24 first, because it bogusly
-			 * reports an external PHY at all indices
-			 */
-			if (phy == 0)
-				phyx = 24;
-			else if (phy <= 24)
-				phyx = phy - 1;
-			else
-				phyx = phy;
-			mii_status = mdio_read(dev, phyx, MII_BMSR);
-			if (mii_status  &&  mii_status != 0xffff) {
-				vp->phys[phy_idx++] = phyx;
-				if (print_info) {
-					pr_info("  MII transceiver found at address %d, status %4x.\n",
-						phyx, mii_status);
-				}
-				if ((mii_status & 0x0040) == 0)
-					mii_preamble_required++;
-			}
-		}
-		mii_preamble_required--;
-		if (phy_idx == 0) {
-			pr_warning("  ***WARNING*** No MII transceivers found!\n");
-			vp->phys[0] = 24;
-		} else {
-			vp->advertising = mdio_read(dev, vp->phys[0], MII_ADVERTISE);
-			if (vp->full_duplex) {
-				/* Only advertise the FD media types. */
-				vp->advertising &= ~0x02A0;
-				mdio_write(dev, vp->phys[0], 4, vp->advertising);
-			}
-		}
-		vp->mii.phy_id = vp->phys[0];
-	}
-
-	if (vp->capabilities & CapBusMaster) {
-		vp->full_bus_master_tx = 1;
-		if (print_info) {
-			pr_info("  Enabling bus-master transmits and %s receives.\n",
-			(vp->info2 & 1) ? "early" : "whole-frame" );
-		}
-		vp->full_bus_master_rx = (vp->info2 & 1) ? 1 : 2;
-		vp->bus_master = 0;		/* AKPM: vortex only */
-	}
-
-	/* The 3c59x-specific entries in the device structure. */
-	if (vp->full_bus_master_tx) {
-		dev->netdev_ops = &boomrang_netdev_ops;
-		/* Actually, it still should work with iommu. */
-		if (card_idx < MAX_UNITS &&
-		    ((hw_checksums[card_idx] == -1 && (vp->drv_flags & HAS_HWCKSM)) ||
-				hw_checksums[card_idx] == 1)) {
-			dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
-		}
-	} else
-		dev->netdev_ops =  &vortex_netdev_ops;
-
-	if (print_info) {
-		pr_info("%s: scatter/gather %sabled. h/w checksums %sabled\n",
-				print_name,
-				(dev->features & NETIF_F_SG) ? "en":"dis",
-				(dev->features & NETIF_F_IP_CSUM) ? "en":"dis");
-	}
-
-	dev->ethtool_ops = &vortex_ethtool_ops;
-	dev->watchdog_timeo = (watchdog * HZ) / 1000;
-
-	if (pdev) {
-		vp->pm_state_valid = 1;
- 		pci_save_state(VORTEX_PCI(vp));
- 		acpi_set_WOL(dev);
-	}
-	retval = register_netdev(dev);
-	if (retval == 0)
-		return 0;
-
-free_ring:
-	pci_free_consistent(pdev,
-						sizeof(struct boom_rx_desc) * RX_RING_SIZE
-							+ sizeof(struct boom_tx_desc) * TX_RING_SIZE,
-						vp->rx_ring,
-						vp->rx_ring_dma);
-free_region:
-	if (vp->must_free_region)
-		release_region(dev->base_addr, vci->io_size);
-	free_netdev(dev);
-	pr_err(PFX "vortex_probe1 fails.  Returns %d\n", retval);
-out:
-	return retval;
-}
-
-static void
-issue_and_wait(struct net_device *dev, int cmd)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	void __iomem *ioaddr = vp->ioaddr;
-	int i;
-
-	iowrite16(cmd, ioaddr + EL3_CMD);
-	for (i = 0; i < 2000; i++) {
-		if (!(ioread16(ioaddr + EL3_STATUS) & CmdInProgress))
-			return;
-	}
-
-	/* OK, that didn't work.  Do it the slow way.  One second */
-	for (i = 0; i < 100000; i++) {
-		if (!(ioread16(ioaddr + EL3_STATUS) & CmdInProgress)) {
-			if (vortex_debug > 1)
-				pr_info("%s: command 0x%04x took %d usecs\n",
-					   dev->name, cmd, i * 10);
-			return;
-		}
-		udelay(10);
-	}
-	pr_err("%s: command 0x%04x did not complete! Status=0x%x\n",
-			   dev->name, cmd, ioread16(ioaddr + EL3_STATUS));
-}
-
-static void
-vortex_set_duplex(struct net_device *dev)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-
-	pr_info("%s:  setting %s-duplex.\n",
-		dev->name, (vp->full_duplex) ? "full" : "half");
-
-	/* Set the full-duplex bit. */
-	window_write16(vp,
-		       ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
-		       (vp->large_frames ? 0x40 : 0) |
-		       ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ?
-			0x100 : 0),
-		       3, Wn3_MAC_Ctrl);
-}
-
-static void vortex_check_media(struct net_device *dev, unsigned int init)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	unsigned int ok_to_print = 0;
-
-	if (vortex_debug > 3)
-		ok_to_print = 1;
-
-	if (mii_check_media(&vp->mii, ok_to_print, init)) {
-		vp->full_duplex = vp->mii.full_duplex;
-		vortex_set_duplex(dev);
-	} else if (init) {
-		vortex_set_duplex(dev);
-	}
-}
-
-static int
-vortex_up(struct net_device *dev)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	void __iomem *ioaddr = vp->ioaddr;
-	unsigned int config;
-	int i, mii_reg1, mii_reg5, err = 0;
-
-	if (VORTEX_PCI(vp)) {
-		pci_set_power_state(VORTEX_PCI(vp), PCI_D0);	/* Go active */
-		if (vp->pm_state_valid)
-			pci_restore_state(VORTEX_PCI(vp));
-		err = pci_enable_device(VORTEX_PCI(vp));
-		if (err) {
-			pr_warning("%s: Could not enable device\n",
-				dev->name);
-			goto err_out;
-		}
-	}
-
-	/* Before initializing select the active media port. */
-	config = window_read32(vp, 3, Wn3_Config);
-
-	if (vp->media_override != 7) {
-		pr_info("%s: Media override to transceiver %d (%s).\n",
-			   dev->name, vp->media_override,
-			   media_tbl[vp->media_override].name);
-		dev->if_port = vp->media_override;
-	} else if (vp->autoselect) {
-		if (vp->has_nway) {
-			if (vortex_debug > 1)
-				pr_info("%s: using NWAY device table, not %d\n",
-								dev->name, dev->if_port);
-			dev->if_port = XCVR_NWAY;
-		} else {
-			/* Find first available media type, starting with 100baseTx. */
-			dev->if_port = XCVR_100baseTx;
-			while (! (vp->available_media & media_tbl[dev->if_port].mask))
-				dev->if_port = media_tbl[dev->if_port].next;
-			if (vortex_debug > 1)
-				pr_info("%s: first available media type: %s\n",
-					dev->name, media_tbl[dev->if_port].name);
-		}
-	} else {
-		dev->if_port = vp->default_media;
-		if (vortex_debug > 1)
-			pr_info("%s: using default media %s\n",
-				dev->name, media_tbl[dev->if_port].name);
-	}
-
-	init_timer(&vp->timer);
-	vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
-	vp->timer.data = (unsigned long)dev;
-	vp->timer.function = vortex_timer;		/* timer handler */
-	add_timer(&vp->timer);
-
-	init_timer(&vp->rx_oom_timer);
-	vp->rx_oom_timer.data = (unsigned long)dev;
-	vp->rx_oom_timer.function = rx_oom_timer;
-
-	if (vortex_debug > 1)
-		pr_debug("%s: Initial media type %s.\n",
-			   dev->name, media_tbl[dev->if_port].name);
-
-	vp->full_duplex = vp->mii.force_media;
-	config = BFINS(config, dev->if_port, 20, 4);
-	if (vortex_debug > 6)
-		pr_debug("vortex_up(): writing 0x%x to InternalConfig\n", config);
-	window_write32(vp, config, 3, Wn3_Config);
-
-	if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
-		mii_reg1 = mdio_read(dev, vp->phys[0], MII_BMSR);
-		mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA);
-		vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0);
-		vp->mii.full_duplex = vp->full_duplex;
-
-		vortex_check_media(dev, 1);
-	}
-	else
-		vortex_set_duplex(dev);
-
-	issue_and_wait(dev, TxReset);
-	/*
-	 * Don't reset the PHY - that upsets autonegotiation during DHCP operations.
-	 */
-	issue_and_wait(dev, RxReset|0x04);
-
-
-	iowrite16(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
-
-	if (vortex_debug > 1) {
-		pr_debug("%s: vortex_up() irq %d media status %4.4x.\n",
-			   dev->name, dev->irq, window_read16(vp, 4, Wn4_Media));
-	}
-
-	/* Set the station address and mask in window 2 each time opened. */
-	for (i = 0; i < 6; i++)
-		window_write8(vp, dev->dev_addr[i], 2, i);
-	for (; i < 12; i+=2)
-		window_write16(vp, 0, 2, i);
-
-	if (vp->cb_fn_base) {
-		unsigned short n = window_read16(vp, 2, Wn2_ResetOptions) & ~0x4010;
-		if (vp->drv_flags & INVERT_LED_PWR)
-			n |= 0x10;
-		if (vp->drv_flags & INVERT_MII_PWR)
-			n |= 0x4000;
-		window_write16(vp, n, 2, Wn2_ResetOptions);
-	}
-
-	if (dev->if_port == XCVR_10base2)
-		/* Start the thinnet transceiver. We should really wait 50ms...*/
-		iowrite16(StartCoax, ioaddr + EL3_CMD);
-	if (dev->if_port != XCVR_NWAY) {
-		window_write16(vp,
-			       (window_read16(vp, 4, Wn4_Media) &
-				~(Media_10TP|Media_SQE)) |
-			       media_tbl[dev->if_port].media_bits,
-			       4, Wn4_Media);
-	}
-
-	/* Switch to the stats window, and clear all stats by reading. */
-	iowrite16(StatsDisable, ioaddr + EL3_CMD);
-	for (i = 0; i < 10; i++)
-		window_read8(vp, 6, i);
-	window_read16(vp, 6, 10);
-	window_read16(vp, 6, 12);
-	/* New: On the Vortex we must also clear the BadSSD counter. */
-	window_read8(vp, 4, 12);
-	/* ..and on the Boomerang we enable the extra statistics bits. */
-	window_write16(vp, 0x0040, 4, Wn4_NetDiag);
-
-	if (vp->full_bus_master_rx) { /* Boomerang bus master. */
-		vp->cur_rx = vp->dirty_rx = 0;
-		/* Initialize the RxEarly register as recommended. */
-		iowrite16(SetRxThreshold + (1536>>2), ioaddr + EL3_CMD);
-		iowrite32(0x0020, ioaddr + PktStatus);
-		iowrite32(vp->rx_ring_dma, ioaddr + UpListPtr);
-	}
-	if (vp->full_bus_master_tx) { 		/* Boomerang bus master Tx. */
-		vp->cur_tx = vp->dirty_tx = 0;
-		if (vp->drv_flags & IS_BOOMERANG)
-			iowrite8(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */
-		/* Clear the Rx, Tx rings. */
-		for (i = 0; i < RX_RING_SIZE; i++)	/* AKPM: this is done in vortex_open, too */
-			vp->rx_ring[i].status = 0;
-		for (i = 0; i < TX_RING_SIZE; i++)
-			vp->tx_skbuff[i] = NULL;
-		iowrite32(0, ioaddr + DownListPtr);
-	}
-	/* Set receiver mode: presumably accept b-case and phys addr only. */
-	set_rx_mode(dev);
-	/* enable 802.1q tagged frames */
-	set_8021q_mode(dev, 1);
-	iowrite16(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
-
-	iowrite16(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
-	iowrite16(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
-	/* Allow status bits to be seen. */
-	vp->status_enable = SetStatusEnb | HostError|IntReq|StatsFull|TxComplete|
-		(vp->full_bus_master_tx ? DownComplete : TxAvailable) |
-		(vp->full_bus_master_rx ? UpComplete : RxComplete) |
-		(vp->bus_master ? DMADone : 0);
-	vp->intr_enable = SetIntrEnb | IntLatch | TxAvailable |
-		(vp->full_bus_master_rx ? 0 : RxComplete) |
-		StatsFull | HostError | TxComplete | IntReq
-		| (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete;
-	iowrite16(vp->status_enable, ioaddr + EL3_CMD);
-	/* Ack all pending events, and set active indicator mask. */
-	iowrite16(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
-		 ioaddr + EL3_CMD);
-	iowrite16(vp->intr_enable, ioaddr + EL3_CMD);
-	if (vp->cb_fn_base)			/* The PCMCIA people are idiots.  */
-		iowrite32(0x8000, vp->cb_fn_base + 4);
-	netif_start_queue (dev);
-err_out:
-	return err;
-}
-
-static int
-vortex_open(struct net_device *dev)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	int i;
-	int retval;
-
-	/* Use the now-standard shared IRQ implementation. */
-	if ((retval = request_irq(dev->irq, vp->full_bus_master_rx ?
-				boomerang_interrupt : vortex_interrupt, IRQF_SHARED, dev->name, dev))) {
-		pr_err("%s: Could not reserve IRQ %d\n", dev->name, dev->irq);
-		goto err;
-	}
-
-	if (vp->full_bus_master_rx) { /* Boomerang bus master. */
-		if (vortex_debug > 2)
-			pr_debug("%s:  Filling in the Rx ring.\n", dev->name);
-		for (i = 0; i < RX_RING_SIZE; i++) {
-			struct sk_buff *skb;
-			vp->rx_ring[i].next = cpu_to_le32(vp->rx_ring_dma + sizeof(struct boom_rx_desc) * (i+1));
-			vp->rx_ring[i].status = 0;	/* Clear complete bit. */
-			vp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG);
-
-			skb = __netdev_alloc_skb(dev, PKT_BUF_SZ + NET_IP_ALIGN,
-						 GFP_KERNEL);
-			vp->rx_skbuff[i] = skb;
-			if (skb == NULL)
-				break;			/* Bad news!  */
-
-			skb_reserve(skb, NET_IP_ALIGN);	/* Align IP on 16 byte boundaries */
-			vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));
-		}
-		if (i != RX_RING_SIZE) {
-			int j;
-			pr_emerg("%s: no memory for rx ring\n", dev->name);
-			for (j = 0; j < i; j++) {
-				if (vp->rx_skbuff[j]) {
-					dev_kfree_skb(vp->rx_skbuff[j]);
-					vp->rx_skbuff[j] = NULL;
-				}
-			}
-			retval = -ENOMEM;
-			goto err_free_irq;
-		}
-		/* Wrap the ring. */
-		vp->rx_ring[i-1].next = cpu_to_le32(vp->rx_ring_dma);
-	}
-
-	retval = vortex_up(dev);
-	if (!retval)
-		goto out;
-
-err_free_irq:
-	free_irq(dev->irq, dev);
-err:
-	if (vortex_debug > 1)
-		pr_err("%s: vortex_open() fails: returning %d\n", dev->name, retval);
-out:
-	return retval;
-}
-
-static void
-vortex_timer(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *)data;
-	struct vortex_private *vp = netdev_priv(dev);
-	void __iomem *ioaddr = vp->ioaddr;
-	int next_tick = 60*HZ;
-	int ok = 0;
-	int media_status;
-
-	if (vortex_debug > 2) {
-		pr_debug("%s: Media selection timer tick happened, %s.\n",
-			   dev->name, media_tbl[dev->if_port].name);
-		pr_debug("dev->watchdog_timeo=%d\n", dev->watchdog_timeo);
-	}
-
-	media_status = window_read16(vp, 4, Wn4_Media);
-	switch (dev->if_port) {
-	case XCVR_10baseT:  case XCVR_100baseTx:  case XCVR_100baseFx:
-		if (media_status & Media_LnkBeat) {
-			netif_carrier_on(dev);
-			ok = 1;
-			if (vortex_debug > 1)
-				pr_debug("%s: Media %s has link beat, %x.\n",
-					   dev->name, media_tbl[dev->if_port].name, media_status);
-		} else {
-			netif_carrier_off(dev);
-			if (vortex_debug > 1) {
-				pr_debug("%s: Media %s has no link beat, %x.\n",
-					   dev->name, media_tbl[dev->if_port].name, media_status);
-			}
-		}
-		break;
-	case XCVR_MII: case XCVR_NWAY:
-		{
-			ok = 1;
-			vortex_check_media(dev, 0);
-		}
-		break;
-	  default:					/* Other media types handled by Tx timeouts. */
-		if (vortex_debug > 1)
-		  pr_debug("%s: Media %s has no indication, %x.\n",
-				 dev->name, media_tbl[dev->if_port].name, media_status);
-		ok = 1;
-	}
-
-	if (!netif_carrier_ok(dev))
-		next_tick = 5*HZ;
-
-	if (vp->medialock)
-		goto leave_media_alone;
-
-	if (!ok) {
-		unsigned int config;
-
-		spin_lock_irq(&vp->lock);
-
-		do {
-			dev->if_port = media_tbl[dev->if_port].next;
-		} while ( ! (vp->available_media & media_tbl[dev->if_port].mask));
-		if (dev->if_port == XCVR_Default) { /* Go back to default. */
-		  dev->if_port = vp->default_media;
-		  if (vortex_debug > 1)
-			pr_debug("%s: Media selection failing, using default %s port.\n",
-				   dev->name, media_tbl[dev->if_port].name);
-		} else {
-			if (vortex_debug > 1)
-				pr_debug("%s: Media selection failed, now trying %s port.\n",
-					   dev->name, media_tbl[dev->if_port].name);
-			next_tick = media_tbl[dev->if_port].wait;
-		}
-		window_write16(vp,
-			       (media_status & ~(Media_10TP|Media_SQE)) |
-			       media_tbl[dev->if_port].media_bits,
-			       4, Wn4_Media);
-
-		config = window_read32(vp, 3, Wn3_Config);
-		config = BFINS(config, dev->if_port, 20, 4);
-		window_write32(vp, config, 3, Wn3_Config);
-
-		iowrite16(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax,
-			 ioaddr + EL3_CMD);
-		if (vortex_debug > 1)
-			pr_debug("wrote 0x%08x to Wn3_Config\n", config);
-		/* AKPM: FIXME: Should reset Rx & Tx here.  P60 of 3c90xc.pdf */
-
-		spin_unlock_irq(&vp->lock);
-	}
-
-leave_media_alone:
-	if (vortex_debug > 2)
-	  pr_debug("%s: Media selection timer finished, %s.\n",
-			 dev->name, media_tbl[dev->if_port].name);
-
-	mod_timer(&vp->timer, RUN_AT(next_tick));
-	if (vp->deferred)
-		iowrite16(FakeIntr, ioaddr + EL3_CMD);
-}
-
-static void vortex_tx_timeout(struct net_device *dev)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	void __iomem *ioaddr = vp->ioaddr;
-
-	pr_err("%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
-		   dev->name, ioread8(ioaddr + TxStatus),
-		   ioread16(ioaddr + EL3_STATUS));
-	pr_err("  diagnostics: net %04x media %04x dma %08x fifo %04x\n",
-			window_read16(vp, 4, Wn4_NetDiag),
-			window_read16(vp, 4, Wn4_Media),
-			ioread32(ioaddr + PktStatus),
-			window_read16(vp, 4, Wn4_FIFODiag));
-	/* Slight code bloat to be user friendly. */
-	if ((ioread8(ioaddr + TxStatus) & 0x88) == 0x88)
-		pr_err("%s: Transmitter encountered 16 collisions --"
-			   " network cable problem?\n", dev->name);
-	if (ioread16(ioaddr + EL3_STATUS) & IntLatch) {
-		pr_err("%s: Interrupt posted but not delivered --"
-			   " IRQ blocked by another device?\n", dev->name);
-		/* Bad idea here.. but we might as well handle a few events. */
-		{
-			/*
-			 * Block interrupts because vortex_interrupt does a bare spin_lock()
-			 */
-			unsigned long flags;
-			local_irq_save(flags);
-			if (vp->full_bus_master_tx)
-				boomerang_interrupt(dev->irq, dev);
-			else
-				vortex_interrupt(dev->irq, dev);
-			local_irq_restore(flags);
-		}
-	}
-
-	if (vortex_debug > 0)
-		dump_tx_ring(dev);
-
-	issue_and_wait(dev, TxReset);
-
-	dev->stats.tx_errors++;
-	if (vp->full_bus_master_tx) {
-		pr_debug("%s: Resetting the Tx ring pointer.\n", dev->name);
-		if (vp->cur_tx - vp->dirty_tx > 0  &&  ioread32(ioaddr + DownListPtr) == 0)
-			iowrite32(vp->tx_ring_dma + (vp->dirty_tx % TX_RING_SIZE) * sizeof(struct boom_tx_desc),
-				 ioaddr + DownListPtr);
-		if (vp->cur_tx - vp->dirty_tx < TX_RING_SIZE)
-			netif_wake_queue (dev);
-		if (vp->drv_flags & IS_BOOMERANG)
-			iowrite8(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
-		iowrite16(DownUnstall, ioaddr + EL3_CMD);
-	} else {
-		dev->stats.tx_dropped++;
-		netif_wake_queue(dev);
-	}
-
-	/* Issue Tx Enable */
-	iowrite16(TxEnable, ioaddr + EL3_CMD);
-	dev->trans_start = jiffies; /* prevent tx timeout */
-}
-
-/*
- * Handle uncommon interrupt sources.  This is a separate routine to minimize
- * the cache impact.
- */
-static void
-vortex_error(struct net_device *dev, int status)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	void __iomem *ioaddr = vp->ioaddr;
-	int do_tx_reset = 0, reset_mask = 0;
-	unsigned char tx_status = 0;
-
-	if (vortex_debug > 2) {
-		pr_err("%s: vortex_error(), status=0x%x\n", dev->name, status);
-	}
-
-	if (status & TxComplete) {			/* Really "TxError" for us. */
-		tx_status = ioread8(ioaddr + TxStatus);
-		/* Presumably a tx-timeout. We must merely re-enable. */
-		if (vortex_debug > 2 ||
-		    (tx_status != 0x88 && vortex_debug > 0)) {
-			pr_err("%s: Transmit error, Tx status register %2.2x.\n",
-				   dev->name, tx_status);
-			if (tx_status == 0x82) {
-				pr_err("Probably a duplex mismatch.  See "
-						"Documentation/networking/vortex.txt\n");
-			}
-			dump_tx_ring(dev);
-		}
-		if (tx_status & 0x14)  dev->stats.tx_fifo_errors++;
-		if (tx_status & 0x38)  dev->stats.tx_aborted_errors++;
-		if (tx_status & 0x08)  vp->xstats.tx_max_collisions++;
-		iowrite8(0, ioaddr + TxStatus);
-		if (tx_status & 0x30) {			/* txJabber or txUnderrun */
-			do_tx_reset = 1;
-		} else if ((tx_status & 0x08) && (vp->drv_flags & MAX_COLLISION_RESET))  {	/* maxCollisions */
-			do_tx_reset = 1;
-			reset_mask = 0x0108;		/* Reset interface logic, but not download logic */
-		} else {				/* Merely re-enable the transmitter. */
-			iowrite16(TxEnable, ioaddr + EL3_CMD);
-		}
-	}
-
-	if (status & RxEarly)				/* Rx early is unused. */
-		iowrite16(AckIntr | RxEarly, ioaddr + EL3_CMD);
-
-	if (status & StatsFull) {			/* Empty statistics. */
-		static int DoneDidThat;
-		if (vortex_debug > 4)
-			pr_debug("%s: Updating stats.\n", dev->name);
-		update_stats(ioaddr, dev);
-		/* HACK: Disable statistics as an interrupt source. */
-		/* This occurs when we have the wrong media type! */
-		if (DoneDidThat == 0  &&
-			ioread16(ioaddr + EL3_STATUS) & StatsFull) {
-			pr_warning("%s: Updating statistics failed, disabling "
-				   "stats as an interrupt source.\n", dev->name);
-			iowrite16(SetIntrEnb |
-				  (window_read16(vp, 5, 10) & ~StatsFull),
-				  ioaddr + EL3_CMD);
-			vp->intr_enable &= ~StatsFull;
-			DoneDidThat++;
-		}
-	}
-	if (status & IntReq) {		/* Restore all interrupt sources.  */
-		iowrite16(vp->status_enable, ioaddr + EL3_CMD);
-		iowrite16(vp->intr_enable, ioaddr + EL3_CMD);
-	}
-	if (status & HostError) {
-		u16 fifo_diag;
-		fifo_diag = window_read16(vp, 4, Wn4_FIFODiag);
-		pr_err("%s: Host error, FIFO diagnostic register %4.4x.\n",
-			   dev->name, fifo_diag);
-		/* Adapter failure requires Tx/Rx reset and reinit. */
-		if (vp->full_bus_master_tx) {
-			int bus_status = ioread32(ioaddr + PktStatus);
-			/* 0x80000000 PCI master abort. */
-			/* 0x40000000 PCI target abort. */
-			if (vortex_debug)
-				pr_err("%s: PCI bus error, bus status %8.8x\n", dev->name, bus_status);
-
-			/* In this case, blow the card away */
-			/* Must not enter D3 or we can't legally issue the reset! */
-			vortex_down(dev, 0);
-			issue_and_wait(dev, TotalReset | 0xff);
-			vortex_up(dev);		/* AKPM: bug.  vortex_up() assumes that the rx ring is full. It may not be. */
-		} else if (fifo_diag & 0x0400)
-			do_tx_reset = 1;
-		if (fifo_diag & 0x3000) {
-			/* Reset Rx fifo and upload logic */
-			issue_and_wait(dev, RxReset|0x07);
-			/* Set the Rx filter to the current state. */
-			set_rx_mode(dev);
-			/* enable 802.1q VLAN tagged frames */
-			set_8021q_mode(dev, 1);
-			iowrite16(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
-			iowrite16(AckIntr | HostError, ioaddr + EL3_CMD);
-		}
-	}
-
-	if (do_tx_reset) {
-		issue_and_wait(dev, TxReset|reset_mask);
-		iowrite16(TxEnable, ioaddr + EL3_CMD);
-		if (!vp->full_bus_master_tx)
-			netif_wake_queue(dev);
-	}
-}
-
-static netdev_tx_t
-vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	void __iomem *ioaddr = vp->ioaddr;
-
-	/* Put out the doubleword header... */
-	iowrite32(skb->len, ioaddr + TX_FIFO);
-	if (vp->bus_master) {
-		/* Set the bus-master controller to transfer the packet. */
-		int len = (skb->len + 3) & ~3;
-		vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len,
-						PCI_DMA_TODEVICE);
-		spin_lock_irq(&vp->window_lock);
-		window_set(vp, 7);
-		iowrite32(vp->tx_skb_dma, ioaddr + Wn7_MasterAddr);
-		iowrite16(len, ioaddr + Wn7_MasterLen);
-		spin_unlock_irq(&vp->window_lock);
-		vp->tx_skb = skb;
-		iowrite16(StartDMADown, ioaddr + EL3_CMD);
-		/* netif_wake_queue() will be called at the DMADone interrupt. */
-	} else {
-		/* ... and the packet rounded to a doubleword. */
-		iowrite32_rep(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
-		dev_kfree_skb (skb);
-		if (ioread16(ioaddr + TxFree) > 1536) {
-			netif_start_queue (dev);	/* AKPM: redundant? */
-		} else {
-			/* Interrupt us when the FIFO has room for max-sized packet. */
-			netif_stop_queue(dev);
-			iowrite16(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
-		}
-	}
-
-
-	/* Clear the Tx status stack. */
-	{
-		int tx_status;
-		int i = 32;
-
-		while (--i > 0	&&	(tx_status = ioread8(ioaddr + TxStatus)) > 0) {
-			if (tx_status & 0x3C) {		/* A Tx-disabling error occurred.  */
-				if (vortex_debug > 2)
-				  pr_debug("%s: Tx error, status %2.2x.\n",
-						 dev->name, tx_status);
-				if (tx_status & 0x04) dev->stats.tx_fifo_errors++;
-				if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
-				if (tx_status & 0x30) {
-					issue_and_wait(dev, TxReset);
-				}
-				iowrite16(TxEnable, ioaddr + EL3_CMD);
-			}
-			iowrite8(0x00, ioaddr + TxStatus); /* Pop the status stack. */
-		}
-	}
-	return NETDEV_TX_OK;
-}
-
-static netdev_tx_t
-boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	void __iomem *ioaddr = vp->ioaddr;
-	/* Calculate the next Tx descriptor entry. */
-	int entry = vp->cur_tx % TX_RING_SIZE;
-	struct boom_tx_desc *prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE];
-	unsigned long flags;
-
-	if (vortex_debug > 6) {
-		pr_debug("boomerang_start_xmit()\n");
-		pr_debug("%s: Trying to send a packet, Tx index %d.\n",
-			   dev->name, vp->cur_tx);
-	}
-
-	/*
-	 * We can't allow a recursion from our interrupt handler back into the
-	 * tx routine, as they take the same spin lock, and that causes
-	 * deadlock.  Just return NETDEV_TX_BUSY and let the stack try again in
-	 * a bit
-	 */
-	if (vp->handling_irq)
-		return NETDEV_TX_BUSY;
-
-	if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) {
-		if (vortex_debug > 0)
-			pr_warning("%s: BUG! Tx Ring full, refusing to send buffer.\n",
-				   dev->name);
-		netif_stop_queue(dev);
-		return NETDEV_TX_BUSY;
-	}
-
-	vp->tx_skbuff[entry] = skb;
-
-	vp->tx_ring[entry].next = 0;
-#if DO_ZEROCOPY
-	if (skb->ip_summed != CHECKSUM_PARTIAL)
-			vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
-	else
-			vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded | AddTCPChksum | AddUDPChksum);
-
-	if (!skb_shinfo(skb)->nr_frags) {
-		vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data,
-										skb->len, PCI_DMA_TODEVICE));
-		vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb->len | LAST_FRAG);
-	} else {
-		int i;
-
-		vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data,
-										skb_headlen(skb), PCI_DMA_TODEVICE));
-		vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb_headlen(skb));
-
-		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
-			vp->tx_ring[entry].frag[i+1].addr =
-					cpu_to_le32(pci_map_single(VORTEX_PCI(vp),
-											   (void*)page_address(frag->page) + frag->page_offset,
-											   frag->size, PCI_DMA_TODEVICE));
-
-			if (i == skb_shinfo(skb)->nr_frags-1)
-					vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(frag->size|LAST_FRAG);
-			else
-					vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(frag->size);
-		}
-	}
-#else
-	vp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, skb->len, PCI_DMA_TODEVICE));
-	vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
-	vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
-#endif
-
-	spin_lock_irqsave(&vp->lock, flags);
-	/* Wait for the stall to complete. */
-	issue_and_wait(dev, DownStall);
-	prev_entry->next = cpu_to_le32(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc));
-	if (ioread32(ioaddr + DownListPtr) == 0) {
-		iowrite32(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc), ioaddr + DownListPtr);
-		vp->queued_packet++;
-	}
-
-	vp->cur_tx++;
-	if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1) {
-		netif_stop_queue (dev);
-	} else {					/* Clear previous interrupt enable. */
-#if defined(tx_interrupt_mitigation)
-		/* Dubious. If in boomeang_interrupt "faster" cyclone ifdef
-		 * were selected, this would corrupt DN_COMPLETE. No?
-		 */
-		prev_entry->status &= cpu_to_le32(~TxIntrUploaded);
-#endif
-	}
-	iowrite16(DownUnstall, ioaddr + EL3_CMD);
-	spin_unlock_irqrestore(&vp->lock, flags);
-	return NETDEV_TX_OK;
-}
-
-/* The interrupt handler does all of the Rx thread work and cleans up
-   after the Tx thread. */
-
-/*
- * This is the ISR for the vortex series chips.
- * full_bus_master_tx == 0 && full_bus_master_rx == 0
- */
-
-static irqreturn_t
-vortex_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct vortex_private *vp = netdev_priv(dev);
-	void __iomem *ioaddr;
-	int status;
-	int work_done = max_interrupt_work;
-	int handled = 0;
-
-	ioaddr = vp->ioaddr;
-	spin_lock(&vp->lock);
-
-	status = ioread16(ioaddr + EL3_STATUS);
-
-	if (vortex_debug > 6)
-		pr_debug("vortex_interrupt(). status=0x%4x\n", status);
-
-	if ((status & IntLatch) == 0)
-		goto handler_exit;		/* No interrupt: shared IRQs cause this */
-	handled = 1;
-
-	if (status & IntReq) {
-		status |= vp->deferred;
-		vp->deferred = 0;
-	}
-
-	if (status == 0xffff)		/* h/w no longer present (hotplug)? */
-		goto handler_exit;
-
-	if (vortex_debug > 4)
-		pr_debug("%s: interrupt, status %4.4x, latency %d ticks.\n",
-			   dev->name, status, ioread8(ioaddr + Timer));
-
-	spin_lock(&vp->window_lock);
-	window_set(vp, 7);
-
-	do {
-		if (vortex_debug > 5)
-				pr_debug("%s: In interrupt loop, status %4.4x.\n",
-					   dev->name, status);
-		if (status & RxComplete)
-			vortex_rx(dev);
-
-		if (status & TxAvailable) {
-			if (vortex_debug > 5)
-				pr_debug("	TX room bit was handled.\n");
-			/* There's room in the FIFO for a full-sized packet. */
-			iowrite16(AckIntr | TxAvailable, ioaddr + EL3_CMD);
-			netif_wake_queue (dev);
-		}
-
-		if (status & DMADone) {
-			if (ioread16(ioaddr + Wn7_MasterStatus) & 0x1000) {
-				iowrite16(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
-				pci_unmap_single(VORTEX_PCI(vp), vp->tx_skb_dma, (vp->tx_skb->len + 3) & ~3, PCI_DMA_TODEVICE);
-				dev_kfree_skb_irq(vp->tx_skb); /* Release the transferred buffer */
-				if (ioread16(ioaddr + TxFree) > 1536) {
-					/*
-					 * AKPM: FIXME: I don't think we need this.  If the queue was stopped due to
-					 * insufficient FIFO room, the TxAvailable test will succeed and call
-					 * netif_wake_queue()
-					 */
-					netif_wake_queue(dev);
-				} else { /* Interrupt when FIFO has room for max-sized packet. */
-					iowrite16(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
-					netif_stop_queue(dev);
-				}
-			}
-		}
-		/* Check for all uncommon interrupts at once. */
-		if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) {
-			if (status == 0xffff)
-				break;
-			if (status & RxEarly)
-				vortex_rx(dev);
-			spin_unlock(&vp->window_lock);
-			vortex_error(dev, status);
-			spin_lock(&vp->window_lock);
-			window_set(vp, 7);
-		}
-
-		if (--work_done < 0) {
-			pr_warning("%s: Too much work in interrupt, status %4.4x.\n",
-				dev->name, status);
-			/* Disable all pending interrupts. */
-			do {
-				vp->deferred |= status;
-				iowrite16(SetStatusEnb | (~vp->deferred & vp->status_enable),
-					 ioaddr + EL3_CMD);
-				iowrite16(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
-			} while ((status = ioread16(ioaddr + EL3_CMD)) & IntLatch);
-			/* The timer will reenable interrupts. */
-			mod_timer(&vp->timer, jiffies + 1*HZ);
-			break;
-		}
-		/* Acknowledge the IRQ. */
-		iowrite16(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
-	} while ((status = ioread16(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
-
-	spin_unlock(&vp->window_lock);
-
-	if (vortex_debug > 4)
-		pr_debug("%s: exiting interrupt, status %4.4x.\n",
-			   dev->name, status);
-handler_exit:
-	spin_unlock(&vp->lock);
-	return IRQ_RETVAL(handled);
-}
-
-/*
- * This is the ISR for the boomerang series chips.
- * full_bus_master_tx == 1 && full_bus_master_rx == 1
- */
-
-static irqreturn_t
-boomerang_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct vortex_private *vp = netdev_priv(dev);
-	void __iomem *ioaddr;
-	int status;
-	int work_done = max_interrupt_work;
-
-	ioaddr = vp->ioaddr;
-
-
-	/*
-	 * It seems dopey to put the spinlock this early, but we could race against vortex_tx_timeout
-	 * and boomerang_start_xmit
-	 */
-	spin_lock(&vp->lock);
-	vp->handling_irq = 1;
-
-	status = ioread16(ioaddr + EL3_STATUS);
-
-	if (vortex_debug > 6)
-		pr_debug("boomerang_interrupt. status=0x%4x\n", status);
-
-	if ((status & IntLatch) == 0)
-		goto handler_exit;		/* No interrupt: shared IRQs can cause this */
-
-	if (status == 0xffff) {		/* h/w no longer present (hotplug)? */
-		if (vortex_debug > 1)
-			pr_debug("boomerang_interrupt(1): status = 0xffff\n");
-		goto handler_exit;
-	}
-
-	if (status & IntReq) {
-		status |= vp->deferred;
-		vp->deferred = 0;
-	}
-
-	if (vortex_debug > 4)
-		pr_debug("%s: interrupt, status %4.4x, latency %d ticks.\n",
-			   dev->name, status, ioread8(ioaddr + Timer));
-	do {
-		if (vortex_debug > 5)
-				pr_debug("%s: In interrupt loop, status %4.4x.\n",
-					   dev->name, status);
-		if (status & UpComplete) {
-			iowrite16(AckIntr | UpComplete, ioaddr + EL3_CMD);
-			if (vortex_debug > 5)
-				pr_debug("boomerang_interrupt->boomerang_rx\n");
-			boomerang_rx(dev);
-		}
-
-		if (status & DownComplete) {
-			unsigned int dirty_tx = vp->dirty_tx;
-
-			iowrite16(AckIntr | DownComplete, ioaddr + EL3_CMD);
-			while (vp->cur_tx - dirty_tx > 0) {
-				int entry = dirty_tx % TX_RING_SIZE;
-#if 1	/* AKPM: the latter is faster, but cyclone-only */
-				if (ioread32(ioaddr + DownListPtr) ==
-					vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc))
-					break;			/* It still hasn't been processed. */
-#else
-				if ((vp->tx_ring[entry].status & DN_COMPLETE) == 0)
-					break;			/* It still hasn't been processed. */
-#endif
-
-				if (vp->tx_skbuff[entry]) {
-					struct sk_buff *skb = vp->tx_skbuff[entry];
-#if DO_ZEROCOPY
-					int i;
-					for (i=0; i<=skb_shinfo(skb)->nr_frags; i++)
-							pci_unmap_single(VORTEX_PCI(vp),
-											 le32_to_cpu(vp->tx_ring[entry].frag[i].addr),
-											 le32_to_cpu(vp->tx_ring[entry].frag[i].length)&0xFFF,
-											 PCI_DMA_TODEVICE);
-#else
-					pci_unmap_single(VORTEX_PCI(vp),
-						le32_to_cpu(vp->tx_ring[entry].addr), skb->len, PCI_DMA_TODEVICE);
-#endif
-					dev_kfree_skb_irq(skb);
-					vp->tx_skbuff[entry] = NULL;
-				} else {
-					pr_debug("boomerang_interrupt: no skb!\n");
-				}
-				/* dev->stats.tx_packets++;  Counted below. */
-				dirty_tx++;
-			}
-			vp->dirty_tx = dirty_tx;
-			if (vp->cur_tx - dirty_tx <= TX_RING_SIZE - 1) {
-				if (vortex_debug > 6)
-					pr_debug("boomerang_interrupt: wake queue\n");
-				netif_wake_queue (dev);
-			}
-		}
-
-		/* Check for all uncommon interrupts at once. */
-		if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq))
-			vortex_error(dev, status);
-
-		if (--work_done < 0) {
-			pr_warning("%s: Too much work in interrupt, status %4.4x.\n",
-				dev->name, status);
-			/* Disable all pending interrupts. */
-			do {
-				vp->deferred |= status;
-				iowrite16(SetStatusEnb | (~vp->deferred & vp->status_enable),
-					 ioaddr + EL3_CMD);
-				iowrite16(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
-			} while ((status = ioread16(ioaddr + EL3_CMD)) & IntLatch);
-			/* The timer will reenable interrupts. */
-			mod_timer(&vp->timer, jiffies + 1*HZ);
-			break;
-		}
-		/* Acknowledge the IRQ. */
-		iowrite16(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
-		if (vp->cb_fn_base)			/* The PCMCIA people are idiots.  */
-			iowrite32(0x8000, vp->cb_fn_base + 4);
-
-	} while ((status = ioread16(ioaddr + EL3_STATUS)) & IntLatch);
-
-	if (vortex_debug > 4)
-		pr_debug("%s: exiting interrupt, status %4.4x.\n",
-			   dev->name, status);
-handler_exit:
-	vp->handling_irq = 0;
-	spin_unlock(&vp->lock);
-	return IRQ_HANDLED;
-}
-
-static int vortex_rx(struct net_device *dev)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	void __iomem *ioaddr = vp->ioaddr;
-	int i;
-	short rx_status;
-
-	if (vortex_debug > 5)
-		pr_debug("vortex_rx(): status %4.4x, rx_status %4.4x.\n",
-			   ioread16(ioaddr+EL3_STATUS), ioread16(ioaddr+RxStatus));
-	while ((rx_status = ioread16(ioaddr + RxStatus)) > 0) {
-		if (rx_status & 0x4000) { /* Error, update stats. */
-			unsigned char rx_error = ioread8(ioaddr + RxErrors);
-			if (vortex_debug > 2)
-				pr_debug(" Rx error: status %2.2x.\n", rx_error);
-			dev->stats.rx_errors++;
-			if (rx_error & 0x01)  dev->stats.rx_over_errors++;
-			if (rx_error & 0x02)  dev->stats.rx_length_errors++;
-			if (rx_error & 0x04)  dev->stats.rx_frame_errors++;
-			if (rx_error & 0x08)  dev->stats.rx_crc_errors++;
-			if (rx_error & 0x10)  dev->stats.rx_length_errors++;
-		} else {
-			/* The packet length: up to 4.5K!. */
-			int pkt_len = rx_status & 0x1fff;
-			struct sk_buff *skb;
-
-			skb = dev_alloc_skb(pkt_len + 5);
-			if (vortex_debug > 4)
-				pr_debug("Receiving packet size %d status %4.4x.\n",
-					   pkt_len, rx_status);
-			if (skb != NULL) {
-				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-				/* 'skb_put()' points to the start of sk_buff data area. */
-				if (vp->bus_master &&
-					! (ioread16(ioaddr + Wn7_MasterStatus) & 0x8000)) {
-					dma_addr_t dma = pci_map_single(VORTEX_PCI(vp), skb_put(skb, pkt_len),
-									   pkt_len, PCI_DMA_FROMDEVICE);
-					iowrite32(dma, ioaddr + Wn7_MasterAddr);
-					iowrite16((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
-					iowrite16(StartDMAUp, ioaddr + EL3_CMD);
-					while (ioread16(ioaddr + Wn7_MasterStatus) & 0x8000)
-						;
-					pci_unmap_single(VORTEX_PCI(vp), dma, pkt_len, PCI_DMA_FROMDEVICE);
-				} else {
-					ioread32_rep(ioaddr + RX_FIFO,
-					             skb_put(skb, pkt_len),
-						     (pkt_len + 3) >> 2);
-				}
-				iowrite16(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
-				skb->protocol = eth_type_trans(skb, dev);
-				netif_rx(skb);
-				dev->stats.rx_packets++;
-				/* Wait a limited time to go to next packet. */
-				for (i = 200; i >= 0; i--)
-					if ( ! (ioread16(ioaddr + EL3_STATUS) & CmdInProgress))
-						break;
-				continue;
-			} else if (vortex_debug > 0)
-				pr_notice("%s: No memory to allocate a sk_buff of size %d.\n",
-					dev->name, pkt_len);
-			dev->stats.rx_dropped++;
-		}
-		issue_and_wait(dev, RxDiscard);
-	}
-
-	return 0;
-}
-
-static int
-boomerang_rx(struct net_device *dev)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	int entry = vp->cur_rx % RX_RING_SIZE;
-	void __iomem *ioaddr = vp->ioaddr;
-	int rx_status;
-	int rx_work_limit = vp->dirty_rx + RX_RING_SIZE - vp->cur_rx;
-
-	if (vortex_debug > 5)
-		pr_debug("boomerang_rx(): status %4.4x\n", ioread16(ioaddr+EL3_STATUS));
-
-	while ((rx_status = le32_to_cpu(vp->rx_ring[entry].status)) & RxDComplete){
-		if (--rx_work_limit < 0)
-			break;
-		if (rx_status & RxDError) { /* Error, update stats. */
-			unsigned char rx_error = rx_status >> 16;
-			if (vortex_debug > 2)
-				pr_debug(" Rx error: status %2.2x.\n", rx_error);
-			dev->stats.rx_errors++;
-			if (rx_error & 0x01)  dev->stats.rx_over_errors++;
-			if (rx_error & 0x02)  dev->stats.rx_length_errors++;
-			if (rx_error & 0x04)  dev->stats.rx_frame_errors++;
-			if (rx_error & 0x08)  dev->stats.rx_crc_errors++;
-			if (rx_error & 0x10)  dev->stats.rx_length_errors++;
-		} else {
-			/* The packet length: up to 4.5K!. */
-			int pkt_len = rx_status & 0x1fff;
-			struct sk_buff *skb;
-			dma_addr_t dma = le32_to_cpu(vp->rx_ring[entry].addr);
-
-			if (vortex_debug > 4)
-				pr_debug("Receiving packet size %d status %4.4x.\n",
-					   pkt_len, rx_status);
-
-			/* Check if the packet is long enough to just accept without
-			   copying to a properly sized skbuff. */
-			if (pkt_len < rx_copybreak && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
-				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-				pci_dma_sync_single_for_cpu(VORTEX_PCI(vp), dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
-				/* 'skb_put()' points to the start of sk_buff data area. */
-				memcpy(skb_put(skb, pkt_len),
-					   vp->rx_skbuff[entry]->data,
-					   pkt_len);
-				pci_dma_sync_single_for_device(VORTEX_PCI(vp), dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
-				vp->rx_copy++;
-			} else {
-				/* Pass up the skbuff already on the Rx ring. */
-				skb = vp->rx_skbuff[entry];
-				vp->rx_skbuff[entry] = NULL;
-				skb_put(skb, pkt_len);
-				pci_unmap_single(VORTEX_PCI(vp), dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
-				vp->rx_nocopy++;
-			}
-			skb->protocol = eth_type_trans(skb, dev);
-			{					/* Use hardware checksum info. */
-				int csum_bits = rx_status & 0xee000000;
-				if (csum_bits &&
-					(csum_bits == (IPChksumValid | TCPChksumValid) ||
-					 csum_bits == (IPChksumValid | UDPChksumValid))) {
-					skb->ip_summed = CHECKSUM_UNNECESSARY;
-					vp->rx_csumhits++;
-				}
-			}
-			netif_rx(skb);
-			dev->stats.rx_packets++;
-		}
-		entry = (++vp->cur_rx) % RX_RING_SIZE;
-	}
-	/* Refill the Rx ring buffers. */
-	for (; vp->cur_rx - vp->dirty_rx > 0; vp->dirty_rx++) {
-		struct sk_buff *skb;
-		entry = vp->dirty_rx % RX_RING_SIZE;
-		if (vp->rx_skbuff[entry] == NULL) {
-			skb = netdev_alloc_skb_ip_align(dev, PKT_BUF_SZ);
-			if (skb == NULL) {
-				static unsigned long last_jif;
-				if (time_after(jiffies, last_jif + 10 * HZ)) {
-					pr_warning("%s: memory shortage\n", dev->name);
-					last_jif = jiffies;
-				}
-				if ((vp->cur_rx - vp->dirty_rx) == RX_RING_SIZE)
-					mod_timer(&vp->rx_oom_timer, RUN_AT(HZ * 1));
-				break;			/* Bad news!  */
-			}
-
-			vp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));
-			vp->rx_skbuff[entry] = skb;
-		}
-		vp->rx_ring[entry].status = 0;	/* Clear complete bit. */
-		iowrite16(UpUnstall, ioaddr + EL3_CMD);
-	}
-	return 0;
-}
-
-/*
- * If we've hit a total OOM refilling the Rx ring we poll once a second
- * for some memory.  Otherwise there is no way to restart the rx process.
- */
-static void
-rx_oom_timer(unsigned long arg)
-{
-	struct net_device *dev = (struct net_device *)arg;
-	struct vortex_private *vp = netdev_priv(dev);
-
-	spin_lock_irq(&vp->lock);
-	if ((vp->cur_rx - vp->dirty_rx) == RX_RING_SIZE)	/* This test is redundant, but makes me feel good */
-		boomerang_rx(dev);
-	if (vortex_debug > 1) {
-		pr_debug("%s: rx_oom_timer %s\n", dev->name,
-			((vp->cur_rx - vp->dirty_rx) != RX_RING_SIZE) ? "succeeded" : "retrying");
-	}
-	spin_unlock_irq(&vp->lock);
-}
-
-static void
-vortex_down(struct net_device *dev, int final_down)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	void __iomem *ioaddr = vp->ioaddr;
-
-	netif_stop_queue (dev);
-
-	del_timer_sync(&vp->rx_oom_timer);
-	del_timer_sync(&vp->timer);
-
-	/* Turn off statistics ASAP.  We update dev->stats below. */
-	iowrite16(StatsDisable, ioaddr + EL3_CMD);
-
-	/* Disable the receiver and transmitter. */
-	iowrite16(RxDisable, ioaddr + EL3_CMD);
-	iowrite16(TxDisable, ioaddr + EL3_CMD);
-
-	/* Disable receiving 802.1q tagged frames */
-	set_8021q_mode(dev, 0);
-
-	if (dev->if_port == XCVR_10base2)
-		/* Turn off thinnet power.  Green! */
-		iowrite16(StopCoax, ioaddr + EL3_CMD);
-
-	iowrite16(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
-
-	update_stats(ioaddr, dev);
-	if (vp->full_bus_master_rx)
-		iowrite32(0, ioaddr + UpListPtr);
-	if (vp->full_bus_master_tx)
-		iowrite32(0, ioaddr + DownListPtr);
-
-	if (final_down && VORTEX_PCI(vp)) {
-		vp->pm_state_valid = 1;
-		pci_save_state(VORTEX_PCI(vp));
-		acpi_set_WOL(dev);
-	}
-}
-
-static int
-vortex_close(struct net_device *dev)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	void __iomem *ioaddr = vp->ioaddr;
-	int i;
-
-	if (netif_device_present(dev))
-		vortex_down(dev, 1);
-
-	if (vortex_debug > 1) {
-		pr_debug("%s: vortex_close() status %4.4x, Tx status %2.2x.\n",
-			   dev->name, ioread16(ioaddr + EL3_STATUS), ioread8(ioaddr + TxStatus));
-		pr_debug("%s: vortex close stats: rx_nocopy %d rx_copy %d"
-			   " tx_queued %d Rx pre-checksummed %d.\n",
-			   dev->name, vp->rx_nocopy, vp->rx_copy, vp->queued_packet, vp->rx_csumhits);
-	}
-
-#if DO_ZEROCOPY
-	if (vp->rx_csumhits &&
-	    (vp->drv_flags & HAS_HWCKSM) == 0 &&
-	    (vp->card_idx >= MAX_UNITS || hw_checksums[vp->card_idx] == -1)) {
-		pr_warning("%s supports hardware checksums, and we're not using them!\n", dev->name);
-	}
-#endif
-
-	free_irq(dev->irq, dev);
-
-	if (vp->full_bus_master_rx) { /* Free Boomerang bus master Rx buffers. */
-		for (i = 0; i < RX_RING_SIZE; i++)
-			if (vp->rx_skbuff[i]) {
-				pci_unmap_single(	VORTEX_PCI(vp), le32_to_cpu(vp->rx_ring[i].addr),
-									PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
-				dev_kfree_skb(vp->rx_skbuff[i]);
-				vp->rx_skbuff[i] = NULL;
-			}
-	}
-	if (vp->full_bus_master_tx) { /* Free Boomerang bus master Tx buffers. */
-		for (i = 0; i < TX_RING_SIZE; i++) {
-			if (vp->tx_skbuff[i]) {
-				struct sk_buff *skb = vp->tx_skbuff[i];
-#if DO_ZEROCOPY
-				int k;
-
-				for (k=0; k<=skb_shinfo(skb)->nr_frags; k++)
-						pci_unmap_single(VORTEX_PCI(vp),
-										 le32_to_cpu(vp->tx_ring[i].frag[k].addr),
-										 le32_to_cpu(vp->tx_ring[i].frag[k].length)&0xFFF,
-										 PCI_DMA_TODEVICE);
-#else
-				pci_unmap_single(VORTEX_PCI(vp), le32_to_cpu(vp->tx_ring[i].addr), skb->len, PCI_DMA_TODEVICE);
-#endif
-				dev_kfree_skb(skb);
-				vp->tx_skbuff[i] = NULL;
-			}
-		}
-	}
-
-	return 0;
-}
-
-static void
-dump_tx_ring(struct net_device *dev)
-{
-	if (vortex_debug > 0) {
-	struct vortex_private *vp = netdev_priv(dev);
-		void __iomem *ioaddr = vp->ioaddr;
-
-		if (vp->full_bus_master_tx) {
-			int i;
-			int stalled = ioread32(ioaddr + PktStatus) & 0x04;	/* Possible racy. But it's only debug stuff */
-
-			pr_err("  Flags; bus-master %d, dirty %d(%d) current %d(%d)\n",
-					vp->full_bus_master_tx,
-					vp->dirty_tx, vp->dirty_tx % TX_RING_SIZE,
-					vp->cur_tx, vp->cur_tx % TX_RING_SIZE);
-			pr_err("  Transmit list %8.8x vs. %p.\n",
-				   ioread32(ioaddr + DownListPtr),
-				   &vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]);
-			issue_and_wait(dev, DownStall);
-			for (i = 0; i < TX_RING_SIZE; i++) {
-				unsigned int length;
-
-#if DO_ZEROCOPY
-				length = le32_to_cpu(vp->tx_ring[i].frag[0].length);
-#else
-				length = le32_to_cpu(vp->tx_ring[i].length);
-#endif
-				pr_err("  %d: @%p  length %8.8x status %8.8x\n",
-					   i, &vp->tx_ring[i], length,
-					   le32_to_cpu(vp->tx_ring[i].status));
-			}
-			if (!stalled)
-				iowrite16(DownUnstall, ioaddr + EL3_CMD);
-		}
-	}
-}
-
-static struct net_device_stats *vortex_get_stats(struct net_device *dev)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	void __iomem *ioaddr = vp->ioaddr;
-	unsigned long flags;
-
-	if (netif_device_present(dev)) {	/* AKPM: Used to be netif_running */
-		spin_lock_irqsave (&vp->lock, flags);
-		update_stats(ioaddr, dev);
-		spin_unlock_irqrestore (&vp->lock, flags);
-	}
-	return &dev->stats;
-}
-
-/*  Update statistics.
-	Unlike with the EL3 we need not worry about interrupts changing
-	the window setting from underneath us, but we must still guard
-	against a race condition with a StatsUpdate interrupt updating the
-	table.  This is done by checking that the ASM (!) code generated uses
-	atomic updates with '+='.
-	*/
-static void update_stats(void __iomem *ioaddr, struct net_device *dev)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-
-	/* Unlike the 3c5x9 we need not turn off stats updates while reading. */
-	/* Switch to the stats window, and read everything. */
-	dev->stats.tx_carrier_errors		+= window_read8(vp, 6, 0);
-	dev->stats.tx_heartbeat_errors		+= window_read8(vp, 6, 1);
-	dev->stats.tx_window_errors		+= window_read8(vp, 6, 4);
-	dev->stats.rx_fifo_errors		+= window_read8(vp, 6, 5);
-	dev->stats.tx_packets			+= window_read8(vp, 6, 6);
-	dev->stats.tx_packets			+= (window_read8(vp, 6, 9) &
-						    0x30) << 4;
-	/* Rx packets	*/			window_read8(vp, 6, 7);   /* Must read to clear */
-	/* Don't bother with register 9, an extension of registers 6&7.
-	   If we do use the 6&7 values the atomic update assumption above
-	   is invalid. */
-	dev->stats.rx_bytes 			+= window_read16(vp, 6, 10);
-	dev->stats.tx_bytes 			+= window_read16(vp, 6, 12);
-	/* Extra stats for get_ethtool_stats() */
-	vp->xstats.tx_multiple_collisions	+= window_read8(vp, 6, 2);
-	vp->xstats.tx_single_collisions         += window_read8(vp, 6, 3);
-	vp->xstats.tx_deferred			+= window_read8(vp, 6, 8);
-	vp->xstats.rx_bad_ssd			+= window_read8(vp, 4, 12);
-
-	dev->stats.collisions = vp->xstats.tx_multiple_collisions
-		+ vp->xstats.tx_single_collisions
-		+ vp->xstats.tx_max_collisions;
-
-	{
-		u8 up = window_read8(vp, 4, 13);
-		dev->stats.rx_bytes += (up & 0x0f) << 16;
-		dev->stats.tx_bytes += (up & 0xf0) << 12;
-	}
-}
-
-static int vortex_nway_reset(struct net_device *dev)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-
-	return mii_nway_restart(&vp->mii);
-}
-
-static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-
-	return mii_ethtool_gset(&vp->mii, cmd);
-}
-
-static int vortex_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-
-	return mii_ethtool_sset(&vp->mii, cmd);
-}
-
-static u32 vortex_get_msglevel(struct net_device *dev)
-{
-	return vortex_debug;
-}
-
-static void vortex_set_msglevel(struct net_device *dev, u32 dbg)
-{
-	vortex_debug = dbg;
-}
-
-static int vortex_get_sset_count(struct net_device *dev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		return VORTEX_NUM_STATS;
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void vortex_get_ethtool_stats(struct net_device *dev,
-	struct ethtool_stats *stats, u64 *data)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	void __iomem *ioaddr = vp->ioaddr;
-	unsigned long flags;
-
-	spin_lock_irqsave(&vp->lock, flags);
-	update_stats(ioaddr, dev);
-	spin_unlock_irqrestore(&vp->lock, flags);
-
-	data[0] = vp->xstats.tx_deferred;
-	data[1] = vp->xstats.tx_max_collisions;
-	data[2] = vp->xstats.tx_multiple_collisions;
-	data[3] = vp->xstats.tx_single_collisions;
-	data[4] = vp->xstats.rx_bad_ssd;
-}
-
-
-static void vortex_get_strings(struct net_device *dev, u32 stringset, u8 *data)
-{
-	switch (stringset) {
-	case ETH_SS_STATS:
-		memcpy(data, &ethtool_stats_keys, sizeof(ethtool_stats_keys));
-		break;
-	default:
-		WARN_ON(1);
-		break;
-	}
-}
-
-static void vortex_get_drvinfo(struct net_device *dev,
-					struct ethtool_drvinfo *info)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-
-	strcpy(info->driver, DRV_NAME);
-	if (VORTEX_PCI(vp)) {
-		strcpy(info->bus_info, pci_name(VORTEX_PCI(vp)));
-	} else {
-		if (VORTEX_EISA(vp))
-			strcpy(info->bus_info, dev_name(vp->gendev));
-		else
-			sprintf(info->bus_info, "EISA 0x%lx %d",
-					dev->base_addr, dev->irq);
-	}
-}
-
-static void vortex_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-
-	if (!VORTEX_PCI(vp))
-		return;
-
-	wol->supported = WAKE_MAGIC;
-
-	wol->wolopts = 0;
-	if (vp->enable_wol)
-		wol->wolopts |= WAKE_MAGIC;
-}
-
-static int vortex_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-
-	if (!VORTEX_PCI(vp))
-		return -EOPNOTSUPP;
-
-	if (wol->wolopts & ~WAKE_MAGIC)
-		return -EINVAL;
-
-	if (wol->wolopts & WAKE_MAGIC)
-		vp->enable_wol = 1;
-	else
-		vp->enable_wol = 0;
-	acpi_set_WOL(dev);
-
-	return 0;
-}
-
-static const struct ethtool_ops vortex_ethtool_ops = {
-	.get_drvinfo		= vortex_get_drvinfo,
-	.get_strings            = vortex_get_strings,
-	.get_msglevel           = vortex_get_msglevel,
-	.set_msglevel           = vortex_set_msglevel,
-	.get_ethtool_stats      = vortex_get_ethtool_stats,
-	.get_sset_count		= vortex_get_sset_count,
-	.get_settings           = vortex_get_settings,
-	.set_settings           = vortex_set_settings,
-	.get_link               = ethtool_op_get_link,
-	.nway_reset             = vortex_nway_reset,
-	.get_wol                = vortex_get_wol,
-	.set_wol                = vortex_set_wol,
-};
-
-#ifdef CONFIG_PCI
-/*
- *	Must power the device up to do MDIO operations
- */
-static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	int err;
-	struct vortex_private *vp = netdev_priv(dev);
-	pci_power_t state = 0;
-
-	if(VORTEX_PCI(vp))
-		state = VORTEX_PCI(vp)->current_state;
-
-	/* The kernel core really should have pci_get_power_state() */
-
-	if(state != 0)
-		pci_set_power_state(VORTEX_PCI(vp), PCI_D0);
-	err = generic_mii_ioctl(&vp->mii, if_mii(rq), cmd, NULL);
-	if(state != 0)
-		pci_set_power_state(VORTEX_PCI(vp), state);
-
-	return err;
-}
-#endif
-
-
-/* Pre-Cyclone chips have no documented multicast filter, so the only
-   multicast setting is to receive all multicast frames.  At least
-   the chip has a very clean way to set the mode, unlike many others. */
-static void set_rx_mode(struct net_device *dev)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	void __iomem *ioaddr = vp->ioaddr;
-	int new_mode;
-
-	if (dev->flags & IFF_PROMISC) {
-		if (vortex_debug > 3)
-			pr_notice("%s: Setting promiscuous mode.\n", dev->name);
-		new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast|RxProm;
-	} else	if (!netdev_mc_empty(dev) || dev->flags & IFF_ALLMULTI) {
-		new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast;
-	} else
-		new_mode = SetRxFilter | RxStation | RxBroadcast;
-
-	iowrite16(new_mode, ioaddr + EL3_CMD);
-}
-
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-/* Setup the card so that it can receive frames with an 802.1q VLAN tag.
-   Note that this must be done after each RxReset due to some backwards
-   compatibility logic in the Cyclone and Tornado ASICs */
-
-/* The Ethernet Type used for 802.1q tagged frames */
-#define VLAN_ETHER_TYPE 0x8100
-
-static void set_8021q_mode(struct net_device *dev, int enable)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	int mac_ctrl;
-
-	if ((vp->drv_flags&IS_CYCLONE) || (vp->drv_flags&IS_TORNADO)) {
-		/* cyclone and tornado chipsets can recognize 802.1q
-		 * tagged frames and treat them correctly */
-
-		int max_pkt_size = dev->mtu+14;	/* MTU+Ethernet header */
-		if (enable)
-			max_pkt_size += 4;	/* 802.1Q VLAN tag */
-
-		window_write16(vp, max_pkt_size, 3, Wn3_MaxPktSize);
-
-		/* set VlanEtherType to let the hardware checksumming
-		   treat tagged frames correctly */
-		window_write16(vp, VLAN_ETHER_TYPE, 7, Wn7_VlanEtherType);
-	} else {
-		/* on older cards we have to enable large frames */
-
-		vp->large_frames = dev->mtu > 1500 || enable;
-
-		mac_ctrl = window_read16(vp, 3, Wn3_MAC_Ctrl);
-		if (vp->large_frames)
-			mac_ctrl |= 0x40;
-		else
-			mac_ctrl &= ~0x40;
-		window_write16(vp, mac_ctrl, 3, Wn3_MAC_Ctrl);
-	}
-}
-#else
-
-static void set_8021q_mode(struct net_device *dev, int enable)
-{
-}
-
-
-#endif
-
-/* MII transceiver control section.
-   Read and write the MII registers using software-generated serial
-   MDIO protocol.  See the MII specifications or DP83840A data sheet
-   for details. */
-
-/* The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
-   met by back-to-back PCI I/O cycles, but we insert a delay to avoid
-   "overclocking" issues. */
-static void mdio_delay(struct vortex_private *vp)
-{
-	window_read32(vp, 4, Wn4_PhysicalMgmt);
-}
-
-#define MDIO_SHIFT_CLK	0x01
-#define MDIO_DIR_WRITE	0x04
-#define MDIO_DATA_WRITE0 (0x00 | MDIO_DIR_WRITE)
-#define MDIO_DATA_WRITE1 (0x02 | MDIO_DIR_WRITE)
-#define MDIO_DATA_READ	0x02
-#define MDIO_ENB_IN		0x00
-
-/* Generate the preamble required for initial synchronization and
-   a few older transceivers. */
-static void mdio_sync(struct vortex_private *vp, int bits)
-{
-	/* Establish sync by sending at least 32 logic ones. */
-	while (-- bits >= 0) {
-		window_write16(vp, MDIO_DATA_WRITE1, 4, Wn4_PhysicalMgmt);
-		mdio_delay(vp);
-		window_write16(vp, MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK,
-			       4, Wn4_PhysicalMgmt);
-		mdio_delay(vp);
-	}
-}
-
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
-	int i;
-	struct vortex_private *vp = netdev_priv(dev);
-	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
-	unsigned int retval = 0;
-
-	spin_lock_bh(&vp->mii_lock);
-
-	if (mii_preamble_required)
-		mdio_sync(vp, 32);
-
-	/* Shift the read command bits out. */
-	for (i = 14; i >= 0; i--) {
-		int dataval = (read_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
-		window_write16(vp, dataval, 4, Wn4_PhysicalMgmt);
-		mdio_delay(vp);
-		window_write16(vp, dataval | MDIO_SHIFT_CLK,
-			       4, Wn4_PhysicalMgmt);
-		mdio_delay(vp);
-	}
-	/* Read the two transition, 16 data, and wire-idle bits. */
-	for (i = 19; i > 0; i--) {
-		window_write16(vp, MDIO_ENB_IN, 4, Wn4_PhysicalMgmt);
-		mdio_delay(vp);
-		retval = (retval << 1) |
-			((window_read16(vp, 4, Wn4_PhysicalMgmt) &
-			  MDIO_DATA_READ) ? 1 : 0);
-		window_write16(vp, MDIO_ENB_IN | MDIO_SHIFT_CLK,
-			       4, Wn4_PhysicalMgmt);
-		mdio_delay(vp);
-	}
-
-	spin_unlock_bh(&vp->mii_lock);
-
-	return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff;
-}
-
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
-	int i;
-
-	spin_lock_bh(&vp->mii_lock);
-
-	if (mii_preamble_required)
-		mdio_sync(vp, 32);
-
-	/* Shift the command bits out. */
-	for (i = 31; i >= 0; i--) {
-		int dataval = (write_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
-		window_write16(vp, dataval, 4, Wn4_PhysicalMgmt);
-		mdio_delay(vp);
-		window_write16(vp, dataval | MDIO_SHIFT_CLK,
-			       4, Wn4_PhysicalMgmt);
-		mdio_delay(vp);
-	}
-	/* Leave the interface idle. */
-	for (i = 1; i >= 0; i--) {
-		window_write16(vp, MDIO_ENB_IN, 4, Wn4_PhysicalMgmt);
-		mdio_delay(vp);
-		window_write16(vp, MDIO_ENB_IN | MDIO_SHIFT_CLK,
-			       4, Wn4_PhysicalMgmt);
-		mdio_delay(vp);
-	}
-
-	spin_unlock_bh(&vp->mii_lock);
-}
-
-/* ACPI: Advanced Configuration and Power Interface. */
-/* Set Wake-On-LAN mode and put the board into D3 (power-down) state. */
-static void acpi_set_WOL(struct net_device *dev)
-{
-	struct vortex_private *vp = netdev_priv(dev);
-	void __iomem *ioaddr = vp->ioaddr;
-
-	device_set_wakeup_enable(vp->gendev, vp->enable_wol);
-
-	if (vp->enable_wol) {
-		/* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */
-		window_write16(vp, 2, 7, 0x0c);
-		/* The RxFilter must accept the WOL frames. */
-		iowrite16(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
-		iowrite16(RxEnable, ioaddr + EL3_CMD);
-
-		if (pci_enable_wake(VORTEX_PCI(vp), PCI_D3hot, 1)) {
-			pr_info("%s: WOL not supported.\n", pci_name(VORTEX_PCI(vp)));
-
-			vp->enable_wol = 0;
-			return;
-		}
-
-		if (VORTEX_PCI(vp)->current_state < PCI_D3hot)
-			return;
-
-		/* Change the power state to D3; RxEnable doesn't take effect. */
-		pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot);
-	}
-}
-
-
-static void __devexit vortex_remove_one(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct vortex_private *vp;
-
-	if (!dev) {
-		pr_err("vortex_remove_one called for Compaq device!\n");
-		BUG();
-	}
-
-	vp = netdev_priv(dev);
-
-	if (vp->cb_fn_base)
-		pci_iounmap(VORTEX_PCI(vp), vp->cb_fn_base);
-
-	unregister_netdev(dev);
-
-	if (VORTEX_PCI(vp)) {
-		pci_set_power_state(VORTEX_PCI(vp), PCI_D0);	/* Go active */
-		if (vp->pm_state_valid)
-			pci_restore_state(VORTEX_PCI(vp));
-		pci_disable_device(VORTEX_PCI(vp));
-	}
-	/* Should really use issue_and_wait() here */
-	iowrite16(TotalReset | ((vp->drv_flags & EEPROM_RESET) ? 0x04 : 0x14),
-	     vp->ioaddr + EL3_CMD);
-
-	pci_iounmap(VORTEX_PCI(vp), vp->ioaddr);
-
-	pci_free_consistent(pdev,
-						sizeof(struct boom_rx_desc) * RX_RING_SIZE
-							+ sizeof(struct boom_tx_desc) * TX_RING_SIZE,
-						vp->rx_ring,
-						vp->rx_ring_dma);
-	if (vp->must_free_region)
-		release_region(dev->base_addr, vp->io_size);
-	free_netdev(dev);
-}
-
-
-static struct pci_driver vortex_driver = {
-	.name		= "3c59x",
-	.probe		= vortex_init_one,
-	.remove		= __devexit_p(vortex_remove_one),
-	.id_table	= vortex_pci_tbl,
-	.driver.pm	= VORTEX_PM_OPS,
-};
-
-
-static int vortex_have_pci;
-static int vortex_have_eisa;
-
-
-static int __init vortex_init(void)
-{
-	int pci_rc, eisa_rc;
-
-	pci_rc = pci_register_driver(&vortex_driver);
-	eisa_rc = vortex_eisa_init();
-
-	if (pci_rc == 0)
-		vortex_have_pci = 1;
-	if (eisa_rc > 0)
-		vortex_have_eisa = 1;
-
-	return (vortex_have_pci + vortex_have_eisa) ? 0 : -ENODEV;
-}
-
-
-static void __exit vortex_eisa_cleanup(void)
-{
-	struct vortex_private *vp;
-	void __iomem *ioaddr;
-
-#ifdef CONFIG_EISA
-	/* Take care of the EISA devices */
-	eisa_driver_unregister(&vortex_eisa_driver);
-#endif
-
-	if (compaq_net_device) {
-		vp = netdev_priv(compaq_net_device);
-		ioaddr = ioport_map(compaq_net_device->base_addr,
-		                    VORTEX_TOTAL_SIZE);
-
-		unregister_netdev(compaq_net_device);
-		iowrite16(TotalReset, ioaddr + EL3_CMD);
-		release_region(compaq_net_device->base_addr,
-		               VORTEX_TOTAL_SIZE);
-
-		free_netdev(compaq_net_device);
-	}
-}
-
-
-static void __exit vortex_cleanup(void)
-{
-	if (vortex_have_pci)
-		pci_unregister_driver(&vortex_driver);
-	if (vortex_have_eisa)
-		vortex_eisa_cleanup();
-}
-
-
-module_init(vortex_init);
-module_exit(vortex_cleanup);
diff -druN linux-libre-3.1-gnu/drivers/net/7990.c linux-libre-3.2-gnu/drivers/net/7990.c
--- linux-libre-3.1-gnu/drivers/net/7990.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/7990.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,662 +0,0 @@
-/*
- * 7990.c -- LANCE ethernet IC generic routines.
- * This is an attempt to separate out the bits of various ethernet
- * drivers that are common because they all use the AMD 7990 LANCE
- * (Local Area Network Controller for Ethernet) chip.
- *
- * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
- *
- * Most of this stuff was obtained by looking at other LANCE drivers,
- * in particular a2065.[ch]. The AMD C-LANCE datasheet was also helpful.
- * NB: this was made easy by the fact that Jes Sorensen had cleaned up
- * most of a2025 and sunlance with the aim of merging them, so the
- * common code was pretty obvious.
- */
-#include <linux/crc32.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/route.h>
-#include <linux/string.h>
-#include <linux/skbuff.h>
-#include <asm/irq.h>
-/* Used for the temporal inet entries and routing */
-#include <linux/socket.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/pgtable.h>
-#ifdef CONFIG_HP300
-#include <asm/blinken.h>
-#endif
-
-#include "7990.h"
-
-#define WRITERAP(lp,x) out_be16(lp->base + LANCE_RAP, (x))
-#define WRITERDP(lp,x) out_be16(lp->base + LANCE_RDP, (x))
-#define READRDP(lp) in_be16(lp->base + LANCE_RDP)
-
-#if defined(CONFIG_HPLANCE) || defined(CONFIG_HPLANCE_MODULE)
-#include "hplance.h"
-
-#undef WRITERAP
-#undef WRITERDP
-#undef READRDP
-
-#if defined(CONFIG_MVME147_NET) || defined(CONFIG_MVME147_NET_MODULE)
-
-/* Lossage Factor Nine, Mr Sulu. */
-#define WRITERAP(lp,x) (lp->writerap(lp,x))
-#define WRITERDP(lp,x) (lp->writerdp(lp,x))
-#define READRDP(lp) (lp->readrdp(lp))
-
-#else
-
-/* These inlines can be used if only CONFIG_HPLANCE is defined */
-static inline void WRITERAP(struct lance_private *lp, __u16 value)
-{
-	do {
-		out_be16(lp->base + HPLANCE_REGOFF + LANCE_RAP, value);
-	} while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
-}
-
-static inline void WRITERDP(struct lance_private *lp, __u16 value)
-{
-	do {
-		out_be16(lp->base + HPLANCE_REGOFF + LANCE_RDP, value);
-	} while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
-}
-
-static inline __u16 READRDP(struct lance_private *lp)
-{
-	__u16 value;
-	do {
-		value = in_be16(lp->base + HPLANCE_REGOFF + LANCE_RDP);
-	} while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
-	return value;
-}
-
-#endif
-#endif /* CONFIG_HPLANCE || CONFIG_HPLANCE_MODULE */
-
-/* debugging output macros, various flavours */
-/* #define TEST_HITS */
-#ifdef UNDEF
-#define PRINT_RINGS() \
-do { \
-        int t; \
-        for (t=0; t < RX_RING_SIZE; t++) { \
-                printk("R%d: @(%02X %04X) len %04X, mblen %04X, bits %02X\n",\
-                       t, ib->brx_ring[t].rmd1_hadr, ib->brx_ring[t].rmd0,\
-                       ib->brx_ring[t].length,\
-                       ib->brx_ring[t].mblength, ib->brx_ring[t].rmd1_bits);\
-        }\
-        for (t=0; t < TX_RING_SIZE; t++) { \
-                printk("T%d: @(%02X %04X) len %04X, misc %04X, bits %02X\n",\
-                       t, ib->btx_ring[t].tmd1_hadr, ib->btx_ring[t].tmd0,\
-                       ib->btx_ring[t].length,\
-                       ib->btx_ring[t].misc, ib->btx_ring[t].tmd1_bits);\
-        }\
-} while (0)
-#else
-#define PRINT_RINGS()
-#endif
-
-/* Load the CSR registers. The LANCE has to be STOPped when we do this! */
-static void load_csrs (struct lance_private *lp)
-{
-        volatile struct lance_init_block *aib = lp->lance_init_block;
-        int leptr;
-
-        leptr = LANCE_ADDR (aib);
-
-        WRITERAP(lp, LE_CSR1);                    /* load address of init block */
-        WRITERDP(lp, leptr & 0xFFFF);
-        WRITERAP(lp, LE_CSR2);
-        WRITERDP(lp, leptr >> 16);
-        WRITERAP(lp, LE_CSR3);
-        WRITERDP(lp, lp->busmaster_regval);       /* set byteswap/ALEctrl/byte ctrl */
-
-        /* Point back to csr0 */
-        WRITERAP(lp, LE_CSR0);
-}
-
-/* #define to 0 or 1 appropriately */
-#define DEBUG_IRING 0
-/* Set up the Lance Rx and Tx rings and the init block */
-static void lance_init_ring (struct net_device *dev)
-{
-        struct lance_private *lp = netdev_priv(dev);
-        volatile struct lance_init_block *ib = lp->init_block;
-        volatile struct lance_init_block *aib; /* for LANCE_ADDR computations */
-        int leptr;
-        int i;
-
-        aib = lp->lance_init_block;
-
-        lp->rx_new = lp->tx_new = 0;
-        lp->rx_old = lp->tx_old = 0;
-
-        ib->mode = LE_MO_PROM;                             /* normal, enable Tx & Rx */
-
-        /* Copy the ethernet address to the lance init block
-         * Notice that we do a byteswap if we're big endian.
-         * [I think this is the right criterion; at least, sunlance,
-         * a2065 and atarilance do the byteswap and lance.c (PC) doesn't.
-         * However, the datasheet says that the BSWAP bit doesn't affect
-         * the init block, so surely it should be low byte first for
-         * everybody? Um.]
-         * We could define the ib->physaddr as three 16bit values and
-         * use (addr[1] << 8) | addr[0] & co, but this is more efficient.
-         */
-#ifdef __BIG_ENDIAN
-        ib->phys_addr [0] = dev->dev_addr [1];
-        ib->phys_addr [1] = dev->dev_addr [0];
-        ib->phys_addr [2] = dev->dev_addr [3];
-        ib->phys_addr [3] = dev->dev_addr [2];
-        ib->phys_addr [4] = dev->dev_addr [5];
-        ib->phys_addr [5] = dev->dev_addr [4];
-#else
-        for (i=0; i<6; i++)
-           ib->phys_addr[i] = dev->dev_addr[i];
-#endif
-
-        if (DEBUG_IRING)
-                printk ("TX rings:\n");
-
-	lp->tx_full = 0;
-        /* Setup the Tx ring entries */
-        for (i = 0; i < (1<<lp->lance_log_tx_bufs); i++) {
-                leptr = LANCE_ADDR(&aib->tx_buf[i][0]);
-                ib->btx_ring [i].tmd0      = leptr;
-                ib->btx_ring [i].tmd1_hadr = leptr >> 16;
-                ib->btx_ring [i].tmd1_bits = 0;
-                ib->btx_ring [i].length    = 0xf000; /* The ones required by tmd2 */
-                ib->btx_ring [i].misc      = 0;
-                if (DEBUG_IRING)
-                   printk ("%d: 0x%8.8x\n", i, leptr);
-        }
-
-        /* Setup the Rx ring entries */
-        if (DEBUG_IRING)
-                printk ("RX rings:\n");
-        for (i = 0; i < (1<<lp->lance_log_rx_bufs); i++) {
-                leptr = LANCE_ADDR(&aib->rx_buf[i][0]);
-
-                ib->brx_ring [i].rmd0      = leptr;
-                ib->brx_ring [i].rmd1_hadr = leptr >> 16;
-                ib->brx_ring [i].rmd1_bits = LE_R1_OWN;
-                /* 0xf000 == bits that must be one (reserved, presumably) */
-                ib->brx_ring [i].length    = -RX_BUFF_SIZE | 0xf000;
-                ib->brx_ring [i].mblength  = 0;
-                if (DEBUG_IRING)
-                        printk ("%d: 0x%8.8x\n", i, leptr);
-        }
-
-        /* Setup the initialization block */
-
-        /* Setup rx descriptor pointer */
-        leptr = LANCE_ADDR(&aib->brx_ring);
-        ib->rx_len = (lp->lance_log_rx_bufs << 13) | (leptr >> 16);
-        ib->rx_ptr = leptr;
-        if (DEBUG_IRING)
-                printk ("RX ptr: %8.8x\n", leptr);
-
-        /* Setup tx descriptor pointer */
-        leptr = LANCE_ADDR(&aib->btx_ring);
-        ib->tx_len = (lp->lance_log_tx_bufs << 13) | (leptr >> 16);
-        ib->tx_ptr = leptr;
-        if (DEBUG_IRING)
-                printk ("TX ptr: %8.8x\n", leptr);
-
-        /* Clear the multicast filter */
-        ib->filter [0] = 0;
-        ib->filter [1] = 0;
-        PRINT_RINGS();
-}
-
-/* LANCE must be STOPped before we do this, too... */
-static int init_restart_lance (struct lance_private *lp)
-{
-        int i;
-
-        WRITERAP(lp, LE_CSR0);
-        WRITERDP(lp, LE_C0_INIT);
-
-        /* Need a hook here for sunlance ledma stuff */
-
-        /* Wait for the lance to complete initialization */
-        for (i = 0; (i < 100) && !(READRDP(lp) & (LE_C0_ERR | LE_C0_IDON)); i++)
-                barrier();
-        if ((i == 100) || (READRDP(lp) & LE_C0_ERR)) {
-                printk ("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, READRDP(lp));
-                return -1;
-        }
-
-        /* Clear IDON by writing a "1", enable interrupts and start lance */
-        WRITERDP(lp, LE_C0_IDON);
-        WRITERDP(lp, LE_C0_INEA | LE_C0_STRT);
-
-        return 0;
-}
-
-static int lance_reset (struct net_device *dev)
-{
-        struct lance_private *lp = netdev_priv(dev);
-        int status;
-
-        /* Stop the lance */
-        WRITERAP(lp, LE_CSR0);
-        WRITERDP(lp, LE_C0_STOP);
-
-        load_csrs (lp);
-        lance_init_ring (dev);
-        dev->trans_start = jiffies; /* prevent tx timeout */
-        status = init_restart_lance (lp);
-#ifdef DEBUG_DRIVER
-        printk ("Lance restart=%d\n", status);
-#endif
-        return status;
-}
-
-static int lance_rx (struct net_device *dev)
-{
-        struct lance_private *lp = netdev_priv(dev);
-        volatile struct lance_init_block *ib = lp->init_block;
-        volatile struct lance_rx_desc *rd;
-        unsigned char bits;
-#ifdef TEST_HITS
-        int i;
-#endif
-
-#ifdef TEST_HITS
-        printk ("[");
-        for (i = 0; i < RX_RING_SIZE; i++) {
-                if (i == lp->rx_new)
-                        printk ("%s",
-                                ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "_" : "X");
-                else
-                        printk ("%s",
-                                ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "." : "1");
-        }
-        printk ("]");
-#endif
-#ifdef CONFIG_HP300
-	blinken_leds(0x40, 0);
-#endif
-        WRITERDP(lp, LE_C0_RINT | LE_C0_INEA);     /* ack Rx int, reenable ints */
-        for (rd = &ib->brx_ring [lp->rx_new];     /* For each Rx ring we own... */
-             !((bits = rd->rmd1_bits) & LE_R1_OWN);
-             rd = &ib->brx_ring [lp->rx_new]) {
-
-                /* We got an incomplete frame? */
-                if ((bits & LE_R1_POK) != LE_R1_POK) {
-                        dev->stats.rx_over_errors++;
-                        dev->stats.rx_errors++;
-                        continue;
-                } else if (bits & LE_R1_ERR) {
-                        /* Count only the end frame as a rx error,
-                         * not the beginning
-                         */
-                        if (bits & LE_R1_BUF) dev->stats.rx_fifo_errors++;
-                        if (bits & LE_R1_CRC) dev->stats.rx_crc_errors++;
-                        if (bits & LE_R1_OFL) dev->stats.rx_over_errors++;
-                        if (bits & LE_R1_FRA) dev->stats.rx_frame_errors++;
-                        if (bits & LE_R1_EOP) dev->stats.rx_errors++;
-                } else {
-			int len = (rd->mblength & 0xfff) - 4;
-			struct sk_buff *skb = dev_alloc_skb (len+2);
-
-                        if (!skb) {
-                                printk ("%s: Memory squeeze, deferring packet.\n",
-                                        dev->name);
-                                dev->stats.rx_dropped++;
-                                rd->mblength = 0;
-                                rd->rmd1_bits = LE_R1_OWN;
-                                lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask;
-                                return 0;
-                        }
-
-                        skb_reserve (skb, 2);           /* 16 byte align */
-                        skb_put (skb, len);             /* make room */
-                        skb_copy_to_linear_data(skb,
-                                         (unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
-                                         len);
-                        skb->protocol = eth_type_trans (skb, dev);
-			netif_rx (skb);
-			dev->stats.rx_packets++;
-			dev->stats.rx_bytes += len;
-                }
-
-                /* Return the packet to the pool */
-                rd->mblength = 0;
-                rd->rmd1_bits = LE_R1_OWN;
-                lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask;
-        }
-        return 0;
-}
-
-static int lance_tx (struct net_device *dev)
-{
-        struct lance_private *lp = netdev_priv(dev);
-        volatile struct lance_init_block *ib = lp->init_block;
-        volatile struct lance_tx_desc *td;
-        int i, j;
-        int status;
-
-#ifdef CONFIG_HP300
-	blinken_leds(0x80, 0);
-#endif
-        /* csr0 is 2f3 */
-        WRITERDP(lp, LE_C0_TINT | LE_C0_INEA);
-        /* csr0 is 73 */
-
-        j = lp->tx_old;
-        for (i = j; i != lp->tx_new; i = j) {
-                td = &ib->btx_ring [i];
-
-                /* If we hit a packet not owned by us, stop */
-                if (td->tmd1_bits & LE_T1_OWN)
-                        break;
-
-                if (td->tmd1_bits & LE_T1_ERR) {
-                        status = td->misc;
-
-                        dev->stats.tx_errors++;
-                        if (status & LE_T3_RTY)  dev->stats.tx_aborted_errors++;
-                        if (status & LE_T3_LCOL) dev->stats.tx_window_errors++;
-
-                        if (status & LE_T3_CLOS) {
-                                dev->stats.tx_carrier_errors++;
-                                if (lp->auto_select) {
-                                        lp->tpe = 1 - lp->tpe;
-                                        printk("%s: Carrier Lost, trying %s\n",
-                                               dev->name, lp->tpe?"TPE":"AUI");
-                                        /* Stop the lance */
-                                        WRITERAP(lp, LE_CSR0);
-                                        WRITERDP(lp, LE_C0_STOP);
-                                        lance_init_ring (dev);
-                                        load_csrs (lp);
-                                        init_restart_lance (lp);
-                                        return 0;
-                                }
-                        }
-
-                        /* buffer errors and underflows turn off the transmitter */
-                        /* Restart the adapter */
-                        if (status & (LE_T3_BUF|LE_T3_UFL)) {
-                                dev->stats.tx_fifo_errors++;
-
-                                printk ("%s: Tx: ERR_BUF|ERR_UFL, restarting\n",
-                                        dev->name);
-                                /* Stop the lance */
-                                WRITERAP(lp, LE_CSR0);
-                                WRITERDP(lp, LE_C0_STOP);
-                                lance_init_ring (dev);
-                                load_csrs (lp);
-                                init_restart_lance (lp);
-                                return 0;
-                        }
-                } else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) {
-                        /*
-                         * So we don't count the packet more than once.
-                         */
-                        td->tmd1_bits &= ~(LE_T1_POK);
-
-                        /* One collision before packet was sent. */
-                        if (td->tmd1_bits & LE_T1_EONE)
-                                dev->stats.collisions++;
-
-                        /* More than one collision, be optimistic. */
-                        if (td->tmd1_bits & LE_T1_EMORE)
-                                dev->stats.collisions += 2;
-
-                        dev->stats.tx_packets++;
-                }
-
-                j = (j + 1) & lp->tx_ring_mod_mask;
-        }
-        lp->tx_old = j;
-        WRITERDP(lp, LE_C0_TINT | LE_C0_INEA);
-        return 0;
-}
-
-static irqreturn_t
-lance_interrupt (int irq, void *dev_id)
-{
-        struct net_device *dev = (struct net_device *)dev_id;
-        struct lance_private *lp = netdev_priv(dev);
-        int csr0;
-
-	spin_lock (&lp->devlock);
-
-        WRITERAP(lp, LE_CSR0);              /* LANCE Controller Status */
-        csr0 = READRDP(lp);
-
-        PRINT_RINGS();
-
-        if (!(csr0 & LE_C0_INTR)) {     /* Check if any interrupt has */
-		spin_unlock (&lp->devlock);
-                return IRQ_NONE;        /* been generated by the Lance. */
-	}
-
-        /* Acknowledge all the interrupt sources ASAP */
-        WRITERDP(lp, csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|LE_C0_INIT));
-
-        if ((csr0 & LE_C0_ERR)) {
-                /* Clear the error condition */
-                WRITERDP(lp, LE_C0_BABL|LE_C0_ERR|LE_C0_MISS|LE_C0_INEA);
-        }
-
-        if (csr0 & LE_C0_RINT)
-                lance_rx (dev);
-
-        if (csr0 & LE_C0_TINT)
-                lance_tx (dev);
-
-        /* Log misc errors. */
-        if (csr0 & LE_C0_BABL)
-                dev->stats.tx_errors++;       /* Tx babble. */
-        if (csr0 & LE_C0_MISS)
-                dev->stats.rx_errors++;       /* Missed a Rx frame. */
-        if (csr0 & LE_C0_MERR) {
-                printk("%s: Bus master arbitration failure, status %4.4x.\n",
-                       dev->name, csr0);
-                /* Restart the chip. */
-                WRITERDP(lp, LE_C0_STRT);
-        }
-
-        if (lp->tx_full && netif_queue_stopped(dev) && (TX_BUFFS_AVAIL >= 0)) {
-		lp->tx_full = 0;
-		netif_wake_queue (dev);
-        }
-
-        WRITERAP(lp, LE_CSR0);
-        WRITERDP(lp, LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|LE_C0_IDON|LE_C0_INEA);
-
-	spin_unlock (&lp->devlock);
-	return IRQ_HANDLED;
-}
-
-int lance_open (struct net_device *dev)
-{
-        struct lance_private *lp = netdev_priv(dev);
-	int res;
-
-        /* Install the Interrupt handler. Or we could shunt this out to specific drivers? */
-        if (request_irq(lp->irq, lance_interrupt, IRQF_SHARED, lp->name, dev))
-                return -EAGAIN;
-
-        res = lance_reset(dev);
-	spin_lock_init(&lp->devlock);
-	netif_start_queue (dev);
-
-	return res;
-}
-EXPORT_SYMBOL_GPL(lance_open);
-
-int lance_close (struct net_device *dev)
-{
-        struct lance_private *lp = netdev_priv(dev);
-
-	netif_stop_queue (dev);
-
-        /* Stop the LANCE */
-        WRITERAP(lp, LE_CSR0);
-        WRITERDP(lp, LE_C0_STOP);
-
-        free_irq(lp->irq, dev);
-
-        return 0;
-}
-EXPORT_SYMBOL_GPL(lance_close);
-
-void lance_tx_timeout(struct net_device *dev)
-{
-	printk("lance_tx_timeout\n");
-	lance_reset(dev);
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	netif_wake_queue (dev);
-}
-EXPORT_SYMBOL_GPL(lance_tx_timeout);
-
-int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
-{
-        struct lance_private *lp = netdev_priv(dev);
-        volatile struct lance_init_block *ib = lp->init_block;
-        int entry, skblen, len;
-        static int outs;
-	unsigned long flags;
-
-        if (!TX_BUFFS_AVAIL)
-                return NETDEV_TX_LOCKED;
-
-	netif_stop_queue (dev);
-
-        skblen = skb->len;
-
-#ifdef DEBUG_DRIVER
-        /* dump the packet */
-        {
-                int i;
-
-                for (i = 0; i < 64; i++) {
-                        if ((i % 16) == 0)
-                                printk ("\n");
-                        printk ("%2.2x ", skb->data [i]);
-                }
-        }
-#endif
-        len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
-        entry = lp->tx_new & lp->tx_ring_mod_mask;
-        ib->btx_ring [entry].length = (-len) | 0xf000;
-        ib->btx_ring [entry].misc = 0;
-
-	if (skb->len < ETH_ZLEN)
-		memset((void *)&ib->tx_buf[entry][0], 0, ETH_ZLEN);
-        skb_copy_from_linear_data(skb, (void *)&ib->tx_buf[entry][0], skblen);
-
-        /* Now, give the packet to the lance */
-        ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
-        lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask;
-
-        outs++;
-        /* Kick the lance: transmit now */
-        WRITERDP(lp, LE_C0_INEA | LE_C0_TDMD);
-        dev_kfree_skb (skb);
-
-	spin_lock_irqsave (&lp->devlock, flags);
-        if (TX_BUFFS_AVAIL)
-		netif_start_queue (dev);
-	else
-		lp->tx_full = 1;
-	spin_unlock_irqrestore (&lp->devlock, flags);
-
-        return NETDEV_TX_OK;
-}
-EXPORT_SYMBOL_GPL(lance_start_xmit);
-
-/* taken from the depca driver via a2065.c */
-static void lance_load_multicast (struct net_device *dev)
-{
-        struct lance_private *lp = netdev_priv(dev);
-        volatile struct lance_init_block *ib = lp->init_block;
-        volatile u16 *mcast_table = (u16 *)&ib->filter;
-	struct netdev_hw_addr *ha;
-        u32 crc;
-
-        /* set all multicast bits */
-        if (dev->flags & IFF_ALLMULTI){
-                ib->filter [0] = 0xffffffff;
-                ib->filter [1] = 0xffffffff;
-                return;
-        }
-        /* clear the multicast filter */
-        ib->filter [0] = 0;
-        ib->filter [1] = 0;
-
-        /* Add addresses */
-	netdev_for_each_mc_addr(ha, dev) {
-		crc = ether_crc_le(6, ha->addr);
-                crc = crc >> 26;
-                mcast_table [crc >> 4] |= 1 << (crc & 0xf);
-        }
-}
-
-
-void lance_set_multicast (struct net_device *dev)
-{
-        struct lance_private *lp = netdev_priv(dev);
-        volatile struct lance_init_block *ib = lp->init_block;
-	int stopped;
-
-	stopped = netif_queue_stopped(dev);
-	if (!stopped)
-		netif_stop_queue (dev);
-
-        while (lp->tx_old != lp->tx_new)
-                schedule();
-
-        WRITERAP(lp, LE_CSR0);
-        WRITERDP(lp, LE_C0_STOP);
-        lance_init_ring (dev);
-
-        if (dev->flags & IFF_PROMISC) {
-                ib->mode |= LE_MO_PROM;
-        } else {
-                ib->mode &= ~LE_MO_PROM;
-                lance_load_multicast (dev);
-        }
-        load_csrs (lp);
-        init_restart_lance (lp);
-
-	if (!stopped)
-		netif_start_queue (dev);
-}
-EXPORT_SYMBOL_GPL(lance_set_multicast);
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-void lance_poll(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-
-	spin_lock (&lp->devlock);
-	WRITERAP(lp, LE_CSR0);
-	WRITERDP(lp, LE_C0_STRT);
-	spin_unlock (&lp->devlock);
-	lance_interrupt(dev->irq, dev);
-}
-#endif
-
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/7990.h linux-libre-3.2-gnu/drivers/net/7990.h
--- linux-libre-3.1-gnu/drivers/net/7990.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/7990.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,254 +0,0 @@
-/*
- * 7990.h -- LANCE ethernet IC generic routines.
- * This is an attempt to separate out the bits of various ethernet
- * drivers that are common because they all use the AMD 7990 LANCE
- * (Local Area Network Controller for Ethernet) chip.
- *
- * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
- *
- * Most of this stuff was obtained by looking at other LANCE drivers,
- * in particular a2065.[ch]. The AMD C-LANCE datasheet was also helpful.
- */
-
-#ifndef _7990_H
-#define _7990_H
-
-/* The lance only has two register locations. We communicate mostly via memory. */
-#define LANCE_RDP	0	/* Register Data Port */
-#define LANCE_RAP	2	/* Register Address Port */
-
-/* Transmit/receive ring definitions.
- * We allow the specific drivers to override these defaults if they want to.
- * NB: according to lance.c, increasing the number of buffers is a waste
- * of space and reduces the chance that an upper layer will be able to
- * reorder queued Tx packets based on priority. [Clearly there is a minimum
- * limit too: too small and we drop rx packets and can't tx at full speed.]
- * 4+4 seems to be the usual setting; the atarilance driver uses 3 and 5.
- */
-
-/* Blast! This won't work. The problem is that we can't specify a default
- * setting because that would cause the lance_init_block struct to be
- * too long (and overflow the RAM on shared-memory cards like the HP LANCE.
- */
-#ifndef LANCE_LOG_TX_BUFFERS
-#define LANCE_LOG_TX_BUFFERS 1
-#define LANCE_LOG_RX_BUFFERS 3
-#endif
-
-#define TX_RING_SIZE (1<<LANCE_LOG_TX_BUFFERS)
-#define RX_RING_SIZE (1<<LANCE_LOG_RX_BUFFERS)
-#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
-#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
-#define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29)
-#define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)
-#define PKT_BUFF_SIZE (1544)
-#define RX_BUFF_SIZE PKT_BUFF_SIZE
-#define TX_BUFF_SIZE PKT_BUFF_SIZE
-
-/* Each receive buffer is described by a receive message descriptor (RMD) */
-struct lance_rx_desc {
-	volatile unsigned short rmd0;        /* low address of packet */
-	volatile unsigned char  rmd1_bits;   /* descriptor bits */
-	volatile unsigned char  rmd1_hadr;   /* high address of packet */
-	volatile short    length;    	    /* This length is 2s complement (negative)!
-				     * Buffer length
-				     */
-	volatile unsigned short mblength;    /* Actual number of bytes received */
-};
-
-/* Ditto for TMD: */
-struct lance_tx_desc {
-	volatile unsigned short tmd0;        /* low address of packet */
-	volatile unsigned char  tmd1_bits;   /* descriptor bits */
-	volatile unsigned char  tmd1_hadr;   /* high address of packet */
-	volatile short    length;       	    /* Length is 2s complement (negative)! */
-	volatile unsigned short misc;
-};
-
-/* There are three memory structures accessed by the LANCE:
- * the initialization block, the receive and transmit descriptor rings,
- * and the data buffers themselves. In fact we might as well put the
- * init block,the Tx and Rx rings and the buffers together in memory:
- */
-struct lance_init_block {
-        volatile unsigned short mode;            /* Pre-set mode (reg. 15) */
-        volatile unsigned char phys_addr[6];     /* Physical ethernet address */
-        volatile unsigned filter[2];             /* Multicast filter (64 bits) */
-
-        /* Receive and transmit ring base, along with extra bits. */
-        volatile unsigned short rx_ptr;          /* receive descriptor addr */
-        volatile unsigned short rx_len;          /* receive len and high addr */
-        volatile unsigned short tx_ptr;          /* transmit descriptor addr */
-        volatile unsigned short tx_len;          /* transmit len and high addr */
-
-        /* The Tx and Rx ring entries must be aligned on 8-byte boundaries.
-         * This will be true if this whole struct is 8-byte aligned.
-         */
-        volatile struct lance_tx_desc btx_ring[TX_RING_SIZE];
-        volatile struct lance_rx_desc brx_ring[RX_RING_SIZE];
-
-        volatile char   tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
-        volatile char   rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
-        /* we use this just to make the struct big enough that we can move its startaddr
-         * in order to force alignment to an eight byte boundary.
-         */
-};
-
-/* This is where we keep all the stuff the driver needs to know about.
- * I'm definitely unhappy about the mechanism for allowing specific
- * drivers to add things...
- */
-struct lance_private
-{
-        char *name;
-	unsigned long base;
-        volatile struct lance_init_block *init_block; /* CPU address of RAM */
-        volatile struct lance_init_block *lance_init_block; /* LANCE address of RAM */
-
-        int rx_new, tx_new;
-        int rx_old, tx_old;
-
-        int lance_log_rx_bufs, lance_log_tx_bufs;
-        int rx_ring_mod_mask, tx_ring_mod_mask;
-
-        int tpe;                                  /* TPE is selected */
-        int auto_select;                          /* cable-selection is by carrier */
-        unsigned short busmaster_regval;
-
-        unsigned int irq;                         /* IRQ to register */
-
-        /* This is because the HP LANCE is disgusting and you have to check
-         * a DIO-specific register every time you read/write the LANCE regs :-<
-         * [could we get away with making these some sort of macro?]
-         */
-        void (*writerap)(void *, unsigned short);
-        void (*writerdp)(void *, unsigned short);
-        unsigned short (*readrdp)(void *);
-	spinlock_t devlock;
-	char tx_full;
-};
-
-/*
- *              Am7990 Control and Status Registers
- */
-#define LE_CSR0         0x0000          /* LANCE Controller Status */
-#define LE_CSR1         0x0001          /* IADR[15:0] (bit0==0 ie word aligned) */
-#define LE_CSR2         0x0002          /* IADR[23:16] (high bits reserved) */
-#define LE_CSR3         0x0003          /* Misc */
-
-/*
- *		Bit definitions for CSR0 (LANCE Controller Status)
- */
-#define LE_C0_ERR	0x8000		/* Error = BABL | CERR | MISS | MERR */
-#define LE_C0_BABL	0x4000		/* Babble: Transmitted too many bits */
-#define LE_C0_CERR	0x2000		/* No Heartbeat (10BASE-T) */
-#define LE_C0_MISS	0x1000		/* Missed Frame (no rx buffer to put it in) */
-#define LE_C0_MERR	0x0800		/* Memory Error */
-#define LE_C0_RINT	0x0400		/* Receive Interrupt */
-#define LE_C0_TINT	0x0200		/* Transmit Interrupt */
-#define LE_C0_IDON	0x0100		/* Initialization Done */
-#define LE_C0_INTR	0x0080		/* Interrupt Flag
-                                         = BABL | MISS | MERR | RINT | TINT | IDON */
-#define LE_C0_INEA	0x0040		/* Interrupt Enable */
-#define LE_C0_RXON	0x0020		/* Receive On */
-#define LE_C0_TXON	0x0010		/* Transmit On */
-#define LE_C0_TDMD	0x0008		/* Transmit Demand */
-#define LE_C0_STOP	0x0004		/* Stop */
-#define LE_C0_STRT	0x0002		/* Start */
-#define LE_C0_INIT	0x0001		/* Initialize */
-
-
-/*
- *		Bit definitions for CSR3
- */
-#define LE_C3_BSWP	0x0004		/* Byte Swap
-					   (on for big endian byte order) */
-#define LE_C3_ACON	0x0002		/* ALE Control
-					   (on for active low ALE) */
-#define LE_C3_BCON	0x0001		/* Byte Control */
-
-
-/*
- *		Mode Flags
- */
-#define LE_MO_PROM	0x8000		/* Promiscuous Mode */
-/* these next ones 0x4000 -- 0x0080 are not available on the LANCE 7990,
- * but they are in NetBSD's am7990.h, presumably for backwards-compatible chips
- */
-#define LE_MO_DRCVBC  0x4000          /* disable receive broadcast */
-#define LE_MO_DRCVPA  0x2000          /* disable physical address detection */
-#define LE_MO_DLNKTST 0x1000          /* disable link status */
-#define LE_MO_DAPC    0x0800          /* disable automatic polarity correction */
-#define LE_MO_MENDECL 0x0400          /* MENDEC loopback mode */
-#define LE_MO_LRTTSEL 0x0200          /* lower RX threshold / TX mode selection */
-#define LE_MO_PSEL1   0x0100          /* port selection bit1 */
-#define LE_MO_PSEL0   0x0080          /* port selection bit0 */
-/* and this one is from the C-LANCE data sheet... */
-#define LE_MO_EMBA      0x0080          /* Enable Modified Backoff Algorithm
-                                           (C-LANCE, not original LANCE) */
-#define LE_MO_INTL	0x0040		/* Internal Loopback */
-#define LE_MO_DRTY	0x0020		/* Disable Retry */
-#define LE_MO_FCOLL	0x0010		/* Force Collision */
-#define LE_MO_DXMTFCS	0x0008		/* Disable Transmit CRC */
-#define LE_MO_LOOP	0x0004		/* Loopback Enable */
-#define LE_MO_DTX	0x0002		/* Disable Transmitter */
-#define LE_MO_DRX	0x0001		/* Disable Receiver */
-
-
-/*
- *		Receive Flags
- */
-#define LE_R1_OWN	0x80		/* LANCE owns the descriptor */
-#define LE_R1_ERR	0x40		/* Error */
-#define LE_R1_FRA	0x20		/* Framing Error */
-#define LE_R1_OFL	0x10		/* Overflow Error */
-#define LE_R1_CRC	0x08		/* CRC Error */
-#define LE_R1_BUF	0x04		/* Buffer Error */
-#define LE_R1_SOP	0x02		/* Start of Packet */
-#define LE_R1_EOP	0x01		/* End of Packet */
-#define LE_R1_POK       0x03		/* Packet is complete: SOP + EOP */
-
-
-/*
- *		Transmit Flags
- */
-#define LE_T1_OWN	0x80		/* LANCE owns the descriptor */
-#define LE_T1_ERR	0x40		/* Error */
-#define LE_T1_RES	0x20		/* Reserved, LANCE writes this with a zero */
-#define LE_T1_EMORE	0x10		/* More than one retry needed */
-#define LE_T1_EONE	0x08		/* One retry needed */
-#define LE_T1_EDEF	0x04		/* Deferred */
-#define LE_T1_SOP	0x02		/* Start of Packet */
-#define LE_T1_EOP	0x01		/* End of Packet */
-#define LE_T1_POK	0x03		/* Packet is complete: SOP + EOP */
-
-/*
- *		Error Flags
- */
-#define LE_T3_BUF 	0x8000		/* Buffer Error */
-#define LE_T3_UFL 	0x4000		/* Underflow Error */
-#define LE_T3_LCOL 	0x1000		/* Late Collision */
-#define LE_T3_CLOS 	0x0800		/* Loss of Carrier */
-#define LE_T3_RTY 	0x0400		/* Retry Error */
-#define LE_T3_TDR	0x03ff		/* Time Domain Reflectometry */
-
-/* Miscellaneous useful macros */
-
-#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
-                        lp->tx_old+lp->tx_ring_mod_mask-lp->tx_new:\
-                        lp->tx_old - lp->tx_new-1)
-
-/* The LANCE only uses 24 bit addresses. This does the obvious thing. */
-#define LANCE_ADDR(x) ((int)(x) & ~0xff000000)
-
-/* Now the prototypes we export */
-extern int lance_open(struct net_device *dev);
-extern int lance_close (struct net_device *dev);
-extern int lance_start_xmit (struct sk_buff *skb, struct net_device *dev);
-extern void lance_set_multicast (struct net_device *dev);
-extern void lance_tx_timeout(struct net_device *dev);
-#ifdef CONFIG_NET_POLL_CONTROLLER
-extern void lance_poll(struct net_device *dev);
-#endif
-
-#endif /* ndef _7990_H */
diff -druN linux-libre-3.1-gnu/drivers/net/8139cp.c linux-libre-3.2-gnu/drivers/net/8139cp.c
--- linux-libre-3.1-gnu/drivers/net/8139cp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/8139cp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2064 +0,0 @@
-/* 8139cp.c: A Linux PCI Ethernet driver for the RealTek 8139C+ chips. */
-/*
-	Copyright 2001-2004 Jeff Garzik <jgarzik@pobox.com>
-
-	Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com) [tg3.c]
-	Copyright (C) 2000, 2001 David S. Miller (davem@redhat.com) [sungem.c]
-	Copyright 2001 Manfred Spraul				    [natsemi.c]
-	Copyright 1999-2001 by Donald Becker.			    [natsemi.c]
-       	Written 1997-2001 by Donald Becker.			    [8139too.c]
-	Copyright 1998-2001 by Jes Sorensen, <jes@trained-monkey.org>. [acenic.c]
-
-	This software may be used and distributed according to the terms of
-	the GNU General Public License (GPL), incorporated herein by reference.
-	Drivers based on or derived from this code fall under the GPL and must
-	retain the authorship, copyright and license notice.  This file is not
-	a complete program and may only be used when the entire operating
-	system is licensed under the GPL.
-
-	See the file COPYING in this distribution for more information.
-
-	Contributors:
-
-		Wake-on-LAN support - Felipe Damasio <felipewd@terra.com.br>
-		PCI suspend/resume  - Felipe Damasio <felipewd@terra.com.br>
-		LinkChg interrupt   - Felipe Damasio <felipewd@terra.com.br>
-
-	TODO:
-	* Test Tx checksumming thoroughly
-
-	Low priority TODO:
-	* Complete reset on PciErr
-	* Consider Rx interrupt mitigation using TimerIntr
-	* Investigate using skb->priority with h/w VLAN priority
-	* Investigate using High Priority Tx Queue with skb->priority
-	* Adjust Rx FIFO threshold and Max Rx DMA burst on Rx FIFO error
-	* Adjust Tx FIFO threshold and Max Tx DMA burst on Tx FIFO error
-	* Implement Tx software interrupt mitigation via
-	  Tx descriptor bit
-	* The real minimum of CP_MIN_MTU is 4 bytes.  However,
-	  for this to be supported, one must(?) turn on packet padding.
-	* Support external MII transceivers (patch available)
-
-	NOTES:
-	* TX checksumming is considered experimental.  It is off by
-	  default, use ethtool to turn it on.
-
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define DRV_NAME		"8139cp"
-#define DRV_VERSION		"1.3"
-#define DRV_RELDATE		"Mar 22, 2004"
-
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/compiler.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/ethtool.h>
-#include <linux/gfp.h>
-#include <linux/mii.h>
-#include <linux/if_vlan.h>
-#include <linux/crc32.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
-#include <linux/cache.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-
-/* These identify the driver base version and may not be removed. */
-static char version[] =
-DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
-
-MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
-MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver");
-MODULE_VERSION(DRV_VERSION);
-MODULE_LICENSE("GPL");
-
-static int debug = -1;
-module_param(debug, int, 0);
-MODULE_PARM_DESC (debug, "8139cp: bitmapped message enable number");
-
-/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
-   The RTL chips use a 64 element hash table based on the Ethernet CRC.  */
-static int multicast_filter_limit = 32;
-module_param(multicast_filter_limit, int, 0);
-MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered multicast addresses");
-
-#define CP_DEF_MSG_ENABLE	(NETIF_MSG_DRV		| \
-				 NETIF_MSG_PROBE 	| \
-				 NETIF_MSG_LINK)
-#define CP_NUM_STATS		14	/* struct cp_dma_stats, plus one */
-#define CP_STATS_SIZE		64	/* size in bytes of DMA stats block */
-#define CP_REGS_SIZE		(0xff + 1)
-#define CP_REGS_VER		1		/* version 1 */
-#define CP_RX_RING_SIZE		64
-#define CP_TX_RING_SIZE		64
-#define CP_RING_BYTES		\
-		((sizeof(struct cp_desc) * CP_RX_RING_SIZE) +	\
-		 (sizeof(struct cp_desc) * CP_TX_RING_SIZE) +	\
-		 CP_STATS_SIZE)
-#define NEXT_TX(N)		(((N) + 1) & (CP_TX_RING_SIZE - 1))
-#define NEXT_RX(N)		(((N) + 1) & (CP_RX_RING_SIZE - 1))
-#define TX_BUFFS_AVAIL(CP)					\
-	(((CP)->tx_tail <= (CP)->tx_head) ?			\
-	  (CP)->tx_tail + (CP_TX_RING_SIZE - 1) - (CP)->tx_head :	\
-	  (CP)->tx_tail - (CP)->tx_head - 1)
-
-#define PKT_BUF_SZ		1536	/* Size of each temporary Rx buffer.*/
-#define CP_INTERNAL_PHY		32
-
-/* The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024, 7==end of packet. */
-#define RX_FIFO_THRESH		5	/* Rx buffer level before first PCI xfer.  */
-#define RX_DMA_BURST		4	/* Maximum PCI burst, '4' is 256 */
-#define TX_DMA_BURST		6	/* Maximum PCI burst, '6' is 1024 */
-#define TX_EARLY_THRESH		256	/* Early Tx threshold, in bytes */
-
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT		(6*HZ)
-
-/* hardware minimum and maximum for a single frame's data payload */
-#define CP_MIN_MTU		60	/* TODO: allow lower, but pad */
-#define CP_MAX_MTU		4096
-
-enum {
-	/* NIC register offsets */
-	MAC0		= 0x00,	/* Ethernet hardware address. */
-	MAR0		= 0x08,	/* Multicast filter. */
-	StatsAddr	= 0x10,	/* 64-bit start addr of 64-byte DMA stats blk */
-	TxRingAddr	= 0x20, /* 64-bit start addr of Tx ring */
-	HiTxRingAddr	= 0x28, /* 64-bit start addr of high priority Tx ring */
-	Cmd		= 0x37, /* Command register */
-	IntrMask	= 0x3C, /* Interrupt mask */
-	IntrStatus	= 0x3E, /* Interrupt status */
-	TxConfig	= 0x40, /* Tx configuration */
-	ChipVersion	= 0x43, /* 8-bit chip version, inside TxConfig */
-	RxConfig	= 0x44, /* Rx configuration */
-	RxMissed	= 0x4C,	/* 24 bits valid, write clears */
-	Cfg9346		= 0x50, /* EEPROM select/control; Cfg reg [un]lock */
-	Config1		= 0x52, /* Config1 */
-	Config3		= 0x59, /* Config3 */
-	Config4		= 0x5A, /* Config4 */
-	MultiIntr	= 0x5C, /* Multiple interrupt select */
-	BasicModeCtrl	= 0x62,	/* MII BMCR */
-	BasicModeStatus	= 0x64, /* MII BMSR */
-	NWayAdvert	= 0x66, /* MII ADVERTISE */
-	NWayLPAR	= 0x68, /* MII LPA */
-	NWayExpansion	= 0x6A, /* MII Expansion */
-	Config5		= 0xD8,	/* Config5 */
-	TxPoll		= 0xD9,	/* Tell chip to check Tx descriptors for work */
-	RxMaxSize	= 0xDA, /* Max size of an Rx packet (8169 only) */
-	CpCmd		= 0xE0, /* C+ Command register (C+ mode only) */
-	IntrMitigate	= 0xE2,	/* rx/tx interrupt mitigation control */
-	RxRingAddr	= 0xE4, /* 64-bit start addr of Rx ring */
-	TxThresh	= 0xEC, /* Early Tx threshold */
-	OldRxBufAddr	= 0x30, /* DMA address of Rx ring buffer (C mode) */
-	OldTSD0		= 0x10, /* DMA address of first Tx desc (C mode) */
-
-	/* Tx and Rx status descriptors */
-	DescOwn		= (1 << 31), /* Descriptor is owned by NIC */
-	RingEnd		= (1 << 30), /* End of descriptor ring */
-	FirstFrag	= (1 << 29), /* First segment of a packet */
-	LastFrag	= (1 << 28), /* Final segment of a packet */
-	LargeSend	= (1 << 27), /* TCP Large Send Offload (TSO) */
-	MSSShift	= 16,	     /* MSS value position */
-	MSSMask		= 0xfff,     /* MSS value: 11 bits */
-	TxError		= (1 << 23), /* Tx error summary */
-	RxError		= (1 << 20), /* Rx error summary */
-	IPCS		= (1 << 18), /* Calculate IP checksum */
-	UDPCS		= (1 << 17), /* Calculate UDP/IP checksum */
-	TCPCS		= (1 << 16), /* Calculate TCP/IP checksum */
-	TxVlanTag	= (1 << 17), /* Add VLAN tag */
-	RxVlanTagged	= (1 << 16), /* Rx VLAN tag available */
-	IPFail		= (1 << 15), /* IP checksum failed */
-	UDPFail		= (1 << 14), /* UDP/IP checksum failed */
-	TCPFail		= (1 << 13), /* TCP/IP checksum failed */
-	NormalTxPoll	= (1 << 6),  /* One or more normal Tx packets to send */
-	PID1		= (1 << 17), /* 2 protocol id bits:  0==non-IP, */
-	PID0		= (1 << 16), /* 1==UDP/IP, 2==TCP/IP, 3==IP */
-	RxProtoTCP	= 1,
-	RxProtoUDP	= 2,
-	RxProtoIP	= 3,
-	TxFIFOUnder	= (1 << 25), /* Tx FIFO underrun */
-	TxOWC		= (1 << 22), /* Tx Out-of-window collision */
-	TxLinkFail	= (1 << 21), /* Link failed during Tx of packet */
-	TxMaxCol	= (1 << 20), /* Tx aborted due to excessive collisions */
-	TxColCntShift	= 16,	     /* Shift, to get 4-bit Tx collision cnt */
-	TxColCntMask	= 0x01 | 0x02 | 0x04 | 0x08, /* 4-bit collision count */
-	RxErrFrame	= (1 << 27), /* Rx frame alignment error */
-	RxMcast		= (1 << 26), /* Rx multicast packet rcv'd */
-	RxErrCRC	= (1 << 18), /* Rx CRC error */
-	RxErrRunt	= (1 << 19), /* Rx error, packet < 64 bytes */
-	RxErrLong	= (1 << 21), /* Rx error, packet > 4096 bytes */
-	RxErrFIFO	= (1 << 22), /* Rx error, FIFO overflowed, pkt bad */
-
-	/* StatsAddr register */
-	DumpStats	= (1 << 3),  /* Begin stats dump */
-
-	/* RxConfig register */
-	RxCfgFIFOShift	= 13,	     /* Shift, to get Rx FIFO thresh value */
-	RxCfgDMAShift	= 8,	     /* Shift, to get Rx Max DMA value */
-	AcceptErr	= 0x20,	     /* Accept packets with CRC errors */
-	AcceptRunt	= 0x10,	     /* Accept runt (<64 bytes) packets */
-	AcceptBroadcast	= 0x08,	     /* Accept broadcast packets */
-	AcceptMulticast	= 0x04,	     /* Accept multicast packets */
-	AcceptMyPhys	= 0x02,	     /* Accept pkts with our MAC as dest */
-	AcceptAllPhys	= 0x01,	     /* Accept all pkts w/ physical dest */
-
-	/* IntrMask / IntrStatus registers */
-	PciErr		= (1 << 15), /* System error on the PCI bus */
-	TimerIntr	= (1 << 14), /* Asserted when TCTR reaches TimerInt value */
-	LenChg		= (1 << 13), /* Cable length change */
-	SWInt		= (1 << 8),  /* Software-requested interrupt */
-	TxEmpty		= (1 << 7),  /* No Tx descriptors available */
-	RxFIFOOvr	= (1 << 6),  /* Rx FIFO Overflow */
-	LinkChg		= (1 << 5),  /* Packet underrun, or link change */
-	RxEmpty		= (1 << 4),  /* No Rx descriptors available */
-	TxErr		= (1 << 3),  /* Tx error */
-	TxOK		= (1 << 2),  /* Tx packet sent */
-	RxErr		= (1 << 1),  /* Rx error */
-	RxOK		= (1 << 0),  /* Rx packet received */
-	IntrResvd	= (1 << 10), /* reserved, according to RealTek engineers,
-					but hardware likes to raise it */
-
-	IntrAll		= PciErr | TimerIntr | LenChg | SWInt | TxEmpty |
-			  RxFIFOOvr | LinkChg | RxEmpty | TxErr | TxOK |
-			  RxErr | RxOK | IntrResvd,
-
-	/* C mode command register */
-	CmdReset	= (1 << 4),  /* Enable to reset; self-clearing */
-	RxOn		= (1 << 3),  /* Rx mode enable */
-	TxOn		= (1 << 2),  /* Tx mode enable */
-
-	/* C+ mode command register */
-	RxVlanOn	= (1 << 6),  /* Rx VLAN de-tagging enable */
-	RxChkSum	= (1 << 5),  /* Rx checksum offload enable */
-	PCIDAC		= (1 << 4),  /* PCI Dual Address Cycle (64-bit PCI) */
-	PCIMulRW	= (1 << 3),  /* Enable PCI read/write multiple */
-	CpRxOn		= (1 << 1),  /* Rx mode enable */
-	CpTxOn		= (1 << 0),  /* Tx mode enable */
-
-	/* Cfg9436 EEPROM control register */
-	Cfg9346_Lock	= 0x00,	     /* Lock ConfigX/MII register access */
-	Cfg9346_Unlock	= 0xC0,	     /* Unlock ConfigX/MII register access */
-
-	/* TxConfig register */
-	IFG		= (1 << 25) | (1 << 24), /* standard IEEE interframe gap */
-	TxDMAShift	= 8,	     /* DMA burst value (0-7) is shift this many bits */
-
-	/* Early Tx Threshold register */
-	TxThreshMask	= 0x3f,	     /* Mask bits 5-0 */
-	TxThreshMax	= 2048,	     /* Max early Tx threshold */
-
-	/* Config1 register */
-	DriverLoaded	= (1 << 5),  /* Software marker, driver is loaded */
-	LWACT           = (1 << 4),  /* LWAKE active mode */
-	PMEnable	= (1 << 0),  /* Enable various PM features of chip */
-
-	/* Config3 register */
-	PARMEnable	= (1 << 6),  /* Enable auto-loading of PHY parms */
-	MagicPacket     = (1 << 5),  /* Wake up when receives a Magic Packet */
-	LinkUp          = (1 << 4),  /* Wake up when the cable connection is re-established */
-
-	/* Config4 register */
-	LWPTN           = (1 << 1),  /* LWAKE Pattern */
-	LWPME           = (1 << 4),  /* LANWAKE vs PMEB */
-
-	/* Config5 register */
-	BWF             = (1 << 6),  /* Accept Broadcast wakeup frame */
-	MWF             = (1 << 5),  /* Accept Multicast wakeup frame */
-	UWF             = (1 << 4),  /* Accept Unicast wakeup frame */
-	LANWake         = (1 << 1),  /* Enable LANWake signal */
-	PMEStatus	= (1 << 0),  /* PME status can be reset by PCI RST# */
-
-	cp_norx_intr_mask = PciErr | LinkChg | TxOK | TxErr | TxEmpty,
-	cp_rx_intr_mask = RxOK | RxErr | RxEmpty | RxFIFOOvr,
-	cp_intr_mask = cp_rx_intr_mask | cp_norx_intr_mask,
-};
-
-static const unsigned int cp_rx_config =
-	  (RX_FIFO_THRESH << RxCfgFIFOShift) |
-	  (RX_DMA_BURST << RxCfgDMAShift);
-
-struct cp_desc {
-	__le32		opts1;
-	__le32		opts2;
-	__le64		addr;
-};
-
-struct cp_dma_stats {
-	__le64			tx_ok;
-	__le64			rx_ok;
-	__le64			tx_err;
-	__le32			rx_err;
-	__le16			rx_fifo;
-	__le16			frame_align;
-	__le32			tx_ok_1col;
-	__le32			tx_ok_mcol;
-	__le64			rx_ok_phys;
-	__le64			rx_ok_bcast;
-	__le32			rx_ok_mcast;
-	__le16			tx_abort;
-	__le16			tx_underrun;
-} __packed;
-
-struct cp_extra_stats {
-	unsigned long		rx_frags;
-};
-
-struct cp_private {
-	void			__iomem *regs;
-	struct net_device	*dev;
-	spinlock_t		lock;
-	u32			msg_enable;
-
-	struct napi_struct	napi;
-
-	struct pci_dev		*pdev;
-	u32			rx_config;
-	u16			cpcmd;
-
-	struct cp_extra_stats	cp_stats;
-
-	unsigned		rx_head		____cacheline_aligned;
-	unsigned		rx_tail;
-	struct cp_desc		*rx_ring;
-	struct sk_buff		*rx_skb[CP_RX_RING_SIZE];
-
-	unsigned		tx_head		____cacheline_aligned;
-	unsigned		tx_tail;
-	struct cp_desc		*tx_ring;
-	struct sk_buff		*tx_skb[CP_TX_RING_SIZE];
-
-	unsigned		rx_buf_sz;
-	unsigned		wol_enabled : 1; /* Is Wake-on-LAN enabled? */
-
-	dma_addr_t		ring_dma;
-
-	struct mii_if_info	mii_if;
-};
-
-#define cpr8(reg)	readb(cp->regs + (reg))
-#define cpr16(reg)	readw(cp->regs + (reg))
-#define cpr32(reg)	readl(cp->regs + (reg))
-#define cpw8(reg,val)	writeb((val), cp->regs + (reg))
-#define cpw16(reg,val)	writew((val), cp->regs + (reg))
-#define cpw32(reg,val)	writel((val), cp->regs + (reg))
-#define cpw8_f(reg,val) do {			\
-	writeb((val), cp->regs + (reg));	\
-	readb(cp->regs + (reg));		\
-	} while (0)
-#define cpw16_f(reg,val) do {			\
-	writew((val), cp->regs + (reg));	\
-	readw(cp->regs + (reg));		\
-	} while (0)
-#define cpw32_f(reg,val) do {			\
-	writel((val), cp->regs + (reg));	\
-	readl(cp->regs + (reg));		\
-	} while (0)
-
-
-static void __cp_set_rx_mode (struct net_device *dev);
-static void cp_tx (struct cp_private *cp);
-static void cp_clean_rings (struct cp_private *cp);
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void cp_poll_controller(struct net_device *dev);
-#endif
-static int cp_get_eeprom_len(struct net_device *dev);
-static int cp_get_eeprom(struct net_device *dev,
-			 struct ethtool_eeprom *eeprom, u8 *data);
-static int cp_set_eeprom(struct net_device *dev,
-			 struct ethtool_eeprom *eeprom, u8 *data);
-
-static DEFINE_PCI_DEVICE_TABLE(cp_pci_tbl) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	PCI_DEVICE_ID_REALTEK_8139), },
-	{ PCI_DEVICE(PCI_VENDOR_ID_TTTECH,	PCI_DEVICE_ID_TTTECH_MC322), },
-	{ },
-};
-MODULE_DEVICE_TABLE(pci, cp_pci_tbl);
-
-static struct {
-	const char str[ETH_GSTRING_LEN];
-} ethtool_stats_keys[] = {
-	{ "tx_ok" },
-	{ "rx_ok" },
-	{ "tx_err" },
-	{ "rx_err" },
-	{ "rx_fifo" },
-	{ "frame_align" },
-	{ "tx_ok_1col" },
-	{ "tx_ok_mcol" },
-	{ "rx_ok_phys" },
-	{ "rx_ok_bcast" },
-	{ "rx_ok_mcast" },
-	{ "tx_abort" },
-	{ "tx_underrun" },
-	{ "rx_frags" },
-};
-
-
-static inline void cp_set_rxbufsize (struct cp_private *cp)
-{
-	unsigned int mtu = cp->dev->mtu;
-
-	if (mtu > ETH_DATA_LEN)
-		/* MTU + ethernet header + FCS + optional VLAN tag */
-		cp->rx_buf_sz = mtu + ETH_HLEN + 8;
-	else
-		cp->rx_buf_sz = PKT_BUF_SZ;
-}
-
-static inline void cp_rx_skb (struct cp_private *cp, struct sk_buff *skb,
-			      struct cp_desc *desc)
-{
-	u32 opts2 = le32_to_cpu(desc->opts2);
-
-	skb->protocol = eth_type_trans (skb, cp->dev);
-
-	cp->dev->stats.rx_packets++;
-	cp->dev->stats.rx_bytes += skb->len;
-
-	if (opts2 & RxVlanTagged)
-		__vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
-
-	napi_gro_receive(&cp->napi, skb);
-}
-
-static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
-			    u32 status, u32 len)
-{
-	netif_dbg(cp, rx_err, cp->dev, "rx err, slot %d status 0x%x len %d\n",
-		  rx_tail, status, len);
-	cp->dev->stats.rx_errors++;
-	if (status & RxErrFrame)
-		cp->dev->stats.rx_frame_errors++;
-	if (status & RxErrCRC)
-		cp->dev->stats.rx_crc_errors++;
-	if ((status & RxErrRunt) || (status & RxErrLong))
-		cp->dev->stats.rx_length_errors++;
-	if ((status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag))
-		cp->dev->stats.rx_length_errors++;
-	if (status & RxErrFIFO)
-		cp->dev->stats.rx_fifo_errors++;
-}
-
-static inline unsigned int cp_rx_csum_ok (u32 status)
-{
-	unsigned int protocol = (status >> 16) & 0x3;
-
-	if (((protocol == RxProtoTCP) && !(status & TCPFail)) ||
-	    ((protocol == RxProtoUDP) && !(status & UDPFail)))
-		return 1;
-	else
-		return 0;
-}
-
-static int cp_rx_poll(struct napi_struct *napi, int budget)
-{
-	struct cp_private *cp = container_of(napi, struct cp_private, napi);
-	struct net_device *dev = cp->dev;
-	unsigned int rx_tail = cp->rx_tail;
-	int rx;
-
-rx_status_loop:
-	rx = 0;
-	cpw16(IntrStatus, cp_rx_intr_mask);
-
-	while (1) {
-		u32 status, len;
-		dma_addr_t mapping;
-		struct sk_buff *skb, *new_skb;
-		struct cp_desc *desc;
-		const unsigned buflen = cp->rx_buf_sz;
-
-		skb = cp->rx_skb[rx_tail];
-		BUG_ON(!skb);
-
-		desc = &cp->rx_ring[rx_tail];
-		status = le32_to_cpu(desc->opts1);
-		if (status & DescOwn)
-			break;
-
-		len = (status & 0x1fff) - 4;
-		mapping = le64_to_cpu(desc->addr);
-
-		if ((status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag)) {
-			/* we don't support incoming fragmented frames.
-			 * instead, we attempt to ensure that the
-			 * pre-allocated RX skbs are properly sized such
-			 * that RX fragments are never encountered
-			 */
-			cp_rx_err_acct(cp, rx_tail, status, len);
-			dev->stats.rx_dropped++;
-			cp->cp_stats.rx_frags++;
-			goto rx_next;
-		}
-
-		if (status & (RxError | RxErrFIFO)) {
-			cp_rx_err_acct(cp, rx_tail, status, len);
-			goto rx_next;
-		}
-
-		netif_dbg(cp, rx_status, dev, "rx slot %d status 0x%x len %d\n",
-			  rx_tail, status, len);
-
-		new_skb = netdev_alloc_skb_ip_align(dev, buflen);
-		if (!new_skb) {
-			dev->stats.rx_dropped++;
-			goto rx_next;
-		}
-
-		dma_unmap_single(&cp->pdev->dev, mapping,
-				 buflen, PCI_DMA_FROMDEVICE);
-
-		/* Handle checksum offloading for incoming packets. */
-		if (cp_rx_csum_ok(status))
-			skb->ip_summed = CHECKSUM_UNNECESSARY;
-		else
-			skb_checksum_none_assert(skb);
-
-		skb_put(skb, len);
-
-		mapping = dma_map_single(&cp->pdev->dev, new_skb->data, buflen,
-					 PCI_DMA_FROMDEVICE);
-		cp->rx_skb[rx_tail] = new_skb;
-
-		cp_rx_skb(cp, skb, desc);
-		rx++;
-
-rx_next:
-		cp->rx_ring[rx_tail].opts2 = 0;
-		cp->rx_ring[rx_tail].addr = cpu_to_le64(mapping);
-		if (rx_tail == (CP_RX_RING_SIZE - 1))
-			desc->opts1 = cpu_to_le32(DescOwn | RingEnd |
-						  cp->rx_buf_sz);
-		else
-			desc->opts1 = cpu_to_le32(DescOwn | cp->rx_buf_sz);
-		rx_tail = NEXT_RX(rx_tail);
-
-		if (rx >= budget)
-			break;
-	}
-
-	cp->rx_tail = rx_tail;
-
-	/* if we did not reach work limit, then we're done with
-	 * this round of polling
-	 */
-	if (rx < budget) {
-		unsigned long flags;
-
-		if (cpr16(IntrStatus) & cp_rx_intr_mask)
-			goto rx_status_loop;
-
-		spin_lock_irqsave(&cp->lock, flags);
-		__napi_complete(napi);
-		cpw16_f(IntrMask, cp_intr_mask);
-		spin_unlock_irqrestore(&cp->lock, flags);
-	}
-
-	return rx;
-}
-
-static irqreturn_t cp_interrupt (int irq, void *dev_instance)
-{
-	struct net_device *dev = dev_instance;
-	struct cp_private *cp;
-	u16 status;
-
-	if (unlikely(dev == NULL))
-		return IRQ_NONE;
-	cp = netdev_priv(dev);
-
-	status = cpr16(IntrStatus);
-	if (!status || (status == 0xFFFF))
-		return IRQ_NONE;
-
-	netif_dbg(cp, intr, dev, "intr, status %04x cmd %02x cpcmd %04x\n",
-		  status, cpr8(Cmd), cpr16(CpCmd));
-
-	cpw16(IntrStatus, status & ~cp_rx_intr_mask);
-
-	spin_lock(&cp->lock);
-
-	/* close possible race's with dev_close */
-	if (unlikely(!netif_running(dev))) {
-		cpw16(IntrMask, 0);
-		spin_unlock(&cp->lock);
-		return IRQ_HANDLED;
-	}
-
-	if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr))
-		if (napi_schedule_prep(&cp->napi)) {
-			cpw16_f(IntrMask, cp_norx_intr_mask);
-			__napi_schedule(&cp->napi);
-		}
-
-	if (status & (TxOK | TxErr | TxEmpty | SWInt))
-		cp_tx(cp);
-	if (status & LinkChg)
-		mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
-
-	spin_unlock(&cp->lock);
-
-	if (status & PciErr) {
-		u16 pci_status;
-
-		pci_read_config_word(cp->pdev, PCI_STATUS, &pci_status);
-		pci_write_config_word(cp->pdev, PCI_STATUS, pci_status);
-		netdev_err(dev, "PCI bus error, status=%04x, PCI status=%04x\n",
-			   status, pci_status);
-
-		/* TODO: reset hardware */
-	}
-
-	return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Polling receive - used by netconsole and other diagnostic tools
- * to allow network i/o with interrupts disabled.
- */
-static void cp_poll_controller(struct net_device *dev)
-{
-	disable_irq(dev->irq);
-	cp_interrupt(dev->irq, dev);
-	enable_irq(dev->irq);
-}
-#endif
-
-static void cp_tx (struct cp_private *cp)
-{
-	unsigned tx_head = cp->tx_head;
-	unsigned tx_tail = cp->tx_tail;
-
-	while (tx_tail != tx_head) {
-		struct cp_desc *txd = cp->tx_ring + tx_tail;
-		struct sk_buff *skb;
-		u32 status;
-
-		rmb();
-		status = le32_to_cpu(txd->opts1);
-		if (status & DescOwn)
-			break;
-
-		skb = cp->tx_skb[tx_tail];
-		BUG_ON(!skb);
-
-		dma_unmap_single(&cp->pdev->dev, le64_to_cpu(txd->addr),
-				 le32_to_cpu(txd->opts1) & 0xffff,
-				 PCI_DMA_TODEVICE);
-
-		if (status & LastFrag) {
-			if (status & (TxError | TxFIFOUnder)) {
-				netif_dbg(cp, tx_err, cp->dev,
-					  "tx err, status 0x%x\n", status);
-				cp->dev->stats.tx_errors++;
-				if (status & TxOWC)
-					cp->dev->stats.tx_window_errors++;
-				if (status & TxMaxCol)
-					cp->dev->stats.tx_aborted_errors++;
-				if (status & TxLinkFail)
-					cp->dev->stats.tx_carrier_errors++;
-				if (status & TxFIFOUnder)
-					cp->dev->stats.tx_fifo_errors++;
-			} else {
-				cp->dev->stats.collisions +=
-					((status >> TxColCntShift) & TxColCntMask);
-				cp->dev->stats.tx_packets++;
-				cp->dev->stats.tx_bytes += skb->len;
-				netif_dbg(cp, tx_done, cp->dev,
-					  "tx done, slot %d\n", tx_tail);
-			}
-			dev_kfree_skb_irq(skb);
-		}
-
-		cp->tx_skb[tx_tail] = NULL;
-
-		tx_tail = NEXT_TX(tx_tail);
-	}
-
-	cp->tx_tail = tx_tail;
-
-	if (TX_BUFFS_AVAIL(cp) > (MAX_SKB_FRAGS + 1))
-		netif_wake_queue(cp->dev);
-}
-
-static inline u32 cp_tx_vlan_tag(struct sk_buff *skb)
-{
-	return vlan_tx_tag_present(skb) ?
-		TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
-}
-
-static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
-					struct net_device *dev)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	unsigned entry;
-	u32 eor, flags;
-	unsigned long intr_flags;
-	__le32 opts2;
-	int mss = 0;
-
-	spin_lock_irqsave(&cp->lock, intr_flags);
-
-	/* This is a hard error, log it. */
-	if (TX_BUFFS_AVAIL(cp) <= (skb_shinfo(skb)->nr_frags + 1)) {
-		netif_stop_queue(dev);
-		spin_unlock_irqrestore(&cp->lock, intr_flags);
-		netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
-		return NETDEV_TX_BUSY;
-	}
-
-	entry = cp->tx_head;
-	eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
-	mss = skb_shinfo(skb)->gso_size;
-
-	opts2 = cpu_to_le32(cp_tx_vlan_tag(skb));
-
-	if (skb_shinfo(skb)->nr_frags == 0) {
-		struct cp_desc *txd = &cp->tx_ring[entry];
-		u32 len;
-		dma_addr_t mapping;
-
-		len = skb->len;
-		mapping = dma_map_single(&cp->pdev->dev, skb->data, len, PCI_DMA_TODEVICE);
-		txd->opts2 = opts2;
-		txd->addr = cpu_to_le64(mapping);
-		wmb();
-
-		flags = eor | len | DescOwn | FirstFrag | LastFrag;
-
-		if (mss)
-			flags |= LargeSend | ((mss & MSSMask) << MSSShift);
-		else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-			const struct iphdr *ip = ip_hdr(skb);
-			if (ip->protocol == IPPROTO_TCP)
-				flags |= IPCS | TCPCS;
-			else if (ip->protocol == IPPROTO_UDP)
-				flags |= IPCS | UDPCS;
-			else
-				WARN_ON(1);	/* we need a WARN() */
-		}
-
-		txd->opts1 = cpu_to_le32(flags);
-		wmb();
-
-		cp->tx_skb[entry] = skb;
-		entry = NEXT_TX(entry);
-	} else {
-		struct cp_desc *txd;
-		u32 first_len, first_eor;
-		dma_addr_t first_mapping;
-		int frag, first_entry = entry;
-		const struct iphdr *ip = ip_hdr(skb);
-
-		/* We must give this initial chunk to the device last.
-		 * Otherwise we could race with the device.
-		 */
-		first_eor = eor;
-		first_len = skb_headlen(skb);
-		first_mapping = dma_map_single(&cp->pdev->dev, skb->data,
-					       first_len, PCI_DMA_TODEVICE);
-		cp->tx_skb[entry] = skb;
-		entry = NEXT_TX(entry);
-
-		for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
-			skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
-			u32 len;
-			u32 ctrl;
-			dma_addr_t mapping;
-
-			len = this_frag->size;
-			mapping = dma_map_single(&cp->pdev->dev,
-						 ((void *) page_address(this_frag->page) +
-						  this_frag->page_offset),
-						 len, PCI_DMA_TODEVICE);
-			eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
-
-			ctrl = eor | len | DescOwn;
-
-			if (mss)
-				ctrl |= LargeSend |
-					((mss & MSSMask) << MSSShift);
-			else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-				if (ip->protocol == IPPROTO_TCP)
-					ctrl |= IPCS | TCPCS;
-				else if (ip->protocol == IPPROTO_UDP)
-					ctrl |= IPCS | UDPCS;
-				else
-					BUG();
-			}
-
-			if (frag == skb_shinfo(skb)->nr_frags - 1)
-				ctrl |= LastFrag;
-
-			txd = &cp->tx_ring[entry];
-			txd->opts2 = opts2;
-			txd->addr = cpu_to_le64(mapping);
-			wmb();
-
-			txd->opts1 = cpu_to_le32(ctrl);
-			wmb();
-
-			cp->tx_skb[entry] = skb;
-			entry = NEXT_TX(entry);
-		}
-
-		txd = &cp->tx_ring[first_entry];
-		txd->opts2 = opts2;
-		txd->addr = cpu_to_le64(first_mapping);
-		wmb();
-
-		if (skb->ip_summed == CHECKSUM_PARTIAL) {
-			if (ip->protocol == IPPROTO_TCP)
-				txd->opts1 = cpu_to_le32(first_eor | first_len |
-							 FirstFrag | DescOwn |
-							 IPCS | TCPCS);
-			else if (ip->protocol == IPPROTO_UDP)
-				txd->opts1 = cpu_to_le32(first_eor | first_len |
-							 FirstFrag | DescOwn |
-							 IPCS | UDPCS);
-			else
-				BUG();
-		} else
-			txd->opts1 = cpu_to_le32(first_eor | first_len |
-						 FirstFrag | DescOwn);
-		wmb();
-	}
-	cp->tx_head = entry;
-	netif_dbg(cp, tx_queued, cp->dev, "tx queued, slot %d, skblen %d\n",
-		  entry, skb->len);
-	if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1))
-		netif_stop_queue(dev);
-
-	spin_unlock_irqrestore(&cp->lock, intr_flags);
-
-	cpw8(TxPoll, NormalTxPoll);
-
-	return NETDEV_TX_OK;
-}
-
-/* Set or clear the multicast filter for this adaptor.
-   This routine is not state sensitive and need not be SMP locked. */
-
-static void __cp_set_rx_mode (struct net_device *dev)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	u32 mc_filter[2];	/* Multicast hash filter */
-	int rx_mode;
-	u32 tmp;
-
-	/* Note: do not reorder, GCC is clever about common statements. */
-	if (dev->flags & IFF_PROMISC) {
-		/* Unconditionally log net taps. */
-		rx_mode =
-		    AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
-		    AcceptAllPhys;
-		mc_filter[1] = mc_filter[0] = 0xffffffff;
-	} else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
-		   (dev->flags & IFF_ALLMULTI)) {
-		/* Too many to filter perfectly -- accept all multicasts. */
-		rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
-		mc_filter[1] = mc_filter[0] = 0xffffffff;
-	} else {
-		struct netdev_hw_addr *ha;
-		rx_mode = AcceptBroadcast | AcceptMyPhys;
-		mc_filter[1] = mc_filter[0] = 0;
-		netdev_for_each_mc_addr(ha, dev) {
-			int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
-
-			mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
-			rx_mode |= AcceptMulticast;
-		}
-	}
-
-	/* We can safely update without stopping the chip. */
-	tmp = cp_rx_config | rx_mode;
-	if (cp->rx_config != tmp) {
-		cpw32_f (RxConfig, tmp);
-		cp->rx_config = tmp;
-	}
-	cpw32_f (MAR0 + 0, mc_filter[0]);
-	cpw32_f (MAR0 + 4, mc_filter[1]);
-}
-
-static void cp_set_rx_mode (struct net_device *dev)
-{
-	unsigned long flags;
-	struct cp_private *cp = netdev_priv(dev);
-
-	spin_lock_irqsave (&cp->lock, flags);
-	__cp_set_rx_mode(dev);
-	spin_unlock_irqrestore (&cp->lock, flags);
-}
-
-static void __cp_get_stats(struct cp_private *cp)
-{
-	/* only lower 24 bits valid; write any value to clear */
-	cp->dev->stats.rx_missed_errors += (cpr32 (RxMissed) & 0xffffff);
-	cpw32 (RxMissed, 0);
-}
-
-static struct net_device_stats *cp_get_stats(struct net_device *dev)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	unsigned long flags;
-
-	/* The chip only need report frame silently dropped. */
-	spin_lock_irqsave(&cp->lock, flags);
- 	if (netif_running(dev) && netif_device_present(dev))
- 		__cp_get_stats(cp);
-	spin_unlock_irqrestore(&cp->lock, flags);
-
-	return &dev->stats;
-}
-
-static void cp_stop_hw (struct cp_private *cp)
-{
-	cpw16(IntrStatus, ~(cpr16(IntrStatus)));
-	cpw16_f(IntrMask, 0);
-	cpw8(Cmd, 0);
-	cpw16_f(CpCmd, 0);
-	cpw16_f(IntrStatus, ~(cpr16(IntrStatus)));
-
-	cp->rx_tail = 0;
-	cp->tx_head = cp->tx_tail = 0;
-}
-
-static void cp_reset_hw (struct cp_private *cp)
-{
-	unsigned work = 1000;
-
-	cpw8(Cmd, CmdReset);
-
-	while (work--) {
-		if (!(cpr8(Cmd) & CmdReset))
-			return;
-
-		schedule_timeout_uninterruptible(10);
-	}
-
-	netdev_err(cp->dev, "hardware reset timeout\n");
-}
-
-static inline void cp_start_hw (struct cp_private *cp)
-{
-	cpw16(CpCmd, cp->cpcmd);
-	cpw8(Cmd, RxOn | TxOn);
-}
-
-static void cp_init_hw (struct cp_private *cp)
-{
-	struct net_device *dev = cp->dev;
-	dma_addr_t ring_dma;
-
-	cp_reset_hw(cp);
-
-	cpw8_f (Cfg9346, Cfg9346_Unlock);
-
-	/* Restore our idea of the MAC address. */
-	cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0)));
-	cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4)));
-
-	cp_start_hw(cp);
-	cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */
-
-	__cp_set_rx_mode(dev);
-	cpw32_f (TxConfig, IFG | (TX_DMA_BURST << TxDMAShift));
-
-	cpw8(Config1, cpr8(Config1) | DriverLoaded | PMEnable);
-	/* Disable Wake-on-LAN. Can be turned on with ETHTOOL_SWOL */
-	cpw8(Config3, PARMEnable);
-	cp->wol_enabled = 0;
-
-	cpw8(Config5, cpr8(Config5) & PMEStatus);
-
-	cpw32_f(HiTxRingAddr, 0);
-	cpw32_f(HiTxRingAddr + 4, 0);
-
-	ring_dma = cp->ring_dma;
-	cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
-	cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
-
-	ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
-	cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
-	cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
-
-	cpw16(MultiIntr, 0);
-
-	cpw16_f(IntrMask, cp_intr_mask);
-
-	cpw8_f(Cfg9346, Cfg9346_Lock);
-}
-
-static int cp_refill_rx(struct cp_private *cp)
-{
-	struct net_device *dev = cp->dev;
-	unsigned i;
-
-	for (i = 0; i < CP_RX_RING_SIZE; i++) {
-		struct sk_buff *skb;
-		dma_addr_t mapping;
-
-		skb = netdev_alloc_skb_ip_align(dev, cp->rx_buf_sz);
-		if (!skb)
-			goto err_out;
-
-		mapping = dma_map_single(&cp->pdev->dev, skb->data,
-					 cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-		cp->rx_skb[i] = skb;
-
-		cp->rx_ring[i].opts2 = 0;
-		cp->rx_ring[i].addr = cpu_to_le64(mapping);
-		if (i == (CP_RX_RING_SIZE - 1))
-			cp->rx_ring[i].opts1 =
-				cpu_to_le32(DescOwn | RingEnd | cp->rx_buf_sz);
-		else
-			cp->rx_ring[i].opts1 =
-				cpu_to_le32(DescOwn | cp->rx_buf_sz);
-	}
-
-	return 0;
-
-err_out:
-	cp_clean_rings(cp);
-	return -ENOMEM;
-}
-
-static void cp_init_rings_index (struct cp_private *cp)
-{
-	cp->rx_tail = 0;
-	cp->tx_head = cp->tx_tail = 0;
-}
-
-static int cp_init_rings (struct cp_private *cp)
-{
-	memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
-	cp->tx_ring[CP_TX_RING_SIZE - 1].opts1 = cpu_to_le32(RingEnd);
-
-	cp_init_rings_index(cp);
-
-	return cp_refill_rx (cp);
-}
-
-static int cp_alloc_rings (struct cp_private *cp)
-{
-	void *mem;
-
-	mem = dma_alloc_coherent(&cp->pdev->dev, CP_RING_BYTES,
-				 &cp->ring_dma, GFP_KERNEL);
-	if (!mem)
-		return -ENOMEM;
-
-	cp->rx_ring = mem;
-	cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE];
-
-	return cp_init_rings(cp);
-}
-
-static void cp_clean_rings (struct cp_private *cp)
-{
-	struct cp_desc *desc;
-	unsigned i;
-
-	for (i = 0; i < CP_RX_RING_SIZE; i++) {
-		if (cp->rx_skb[i]) {
-			desc = cp->rx_ring + i;
-			dma_unmap_single(&cp->pdev->dev,le64_to_cpu(desc->addr),
-					 cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-			dev_kfree_skb(cp->rx_skb[i]);
-		}
-	}
-
-	for (i = 0; i < CP_TX_RING_SIZE; i++) {
-		if (cp->tx_skb[i]) {
-			struct sk_buff *skb = cp->tx_skb[i];
-
-			desc = cp->tx_ring + i;
-			dma_unmap_single(&cp->pdev->dev,le64_to_cpu(desc->addr),
-					 le32_to_cpu(desc->opts1) & 0xffff,
-					 PCI_DMA_TODEVICE);
-			if (le32_to_cpu(desc->opts1) & LastFrag)
-				dev_kfree_skb(skb);
-			cp->dev->stats.tx_dropped++;
-		}
-	}
-
-	memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
-	memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
-
-	memset(cp->rx_skb, 0, sizeof(struct sk_buff *) * CP_RX_RING_SIZE);
-	memset(cp->tx_skb, 0, sizeof(struct sk_buff *) * CP_TX_RING_SIZE);
-}
-
-static void cp_free_rings (struct cp_private *cp)
-{
-	cp_clean_rings(cp);
-	dma_free_coherent(&cp->pdev->dev, CP_RING_BYTES, cp->rx_ring,
-			  cp->ring_dma);
-	cp->rx_ring = NULL;
-	cp->tx_ring = NULL;
-}
-
-static int cp_open (struct net_device *dev)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	int rc;
-
-	netif_dbg(cp, ifup, dev, "enabling interface\n");
-
-	rc = cp_alloc_rings(cp);
-	if (rc)
-		return rc;
-
-	napi_enable(&cp->napi);
-
-	cp_init_hw(cp);
-
-	rc = request_irq(dev->irq, cp_interrupt, IRQF_SHARED, dev->name, dev);
-	if (rc)
-		goto err_out_hw;
-
-	netif_carrier_off(dev);
-	mii_check_media(&cp->mii_if, netif_msg_link(cp), true);
-	netif_start_queue(dev);
-
-	return 0;
-
-err_out_hw:
-	napi_disable(&cp->napi);
-	cp_stop_hw(cp);
-	cp_free_rings(cp);
-	return rc;
-}
-
-static int cp_close (struct net_device *dev)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	unsigned long flags;
-
-	napi_disable(&cp->napi);
-
-	netif_dbg(cp, ifdown, dev, "disabling interface\n");
-
-	spin_lock_irqsave(&cp->lock, flags);
-
-	netif_stop_queue(dev);
-	netif_carrier_off(dev);
-
-	cp_stop_hw(cp);
-
-	spin_unlock_irqrestore(&cp->lock, flags);
-
-	free_irq(dev->irq, dev);
-
-	cp_free_rings(cp);
-	return 0;
-}
-
-static void cp_tx_timeout(struct net_device *dev)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	unsigned long flags;
-	int rc;
-
-	netdev_warn(dev, "Transmit timeout, status %2x %4x %4x %4x\n",
-		    cpr8(Cmd), cpr16(CpCmd),
-		    cpr16(IntrStatus), cpr16(IntrMask));
-
-	spin_lock_irqsave(&cp->lock, flags);
-
-	cp_stop_hw(cp);
-	cp_clean_rings(cp);
-	rc = cp_init_rings(cp);
-	cp_start_hw(cp);
-
-	netif_wake_queue(dev);
-
-	spin_unlock_irqrestore(&cp->lock, flags);
-}
-
-#ifdef BROKEN
-static int cp_change_mtu(struct net_device *dev, int new_mtu)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	int rc;
-	unsigned long flags;
-
-	/* check for invalid MTU, according to hardware limits */
-	if (new_mtu < CP_MIN_MTU || new_mtu > CP_MAX_MTU)
-		return -EINVAL;
-
-	/* if network interface not up, no need for complexity */
-	if (!netif_running(dev)) {
-		dev->mtu = new_mtu;
-		cp_set_rxbufsize(cp);	/* set new rx buf size */
-		return 0;
-	}
-
-	spin_lock_irqsave(&cp->lock, flags);
-
-	cp_stop_hw(cp);			/* stop h/w and free rings */
-	cp_clean_rings(cp);
-
-	dev->mtu = new_mtu;
-	cp_set_rxbufsize(cp);		/* set new rx buf size */
-
-	rc = cp_init_rings(cp);		/* realloc and restart h/w */
-	cp_start_hw(cp);
-
-	spin_unlock_irqrestore(&cp->lock, flags);
-
-	return rc;
-}
-#endif /* BROKEN */
-
-static const char mii_2_8139_map[8] = {
-	BasicModeCtrl,
-	BasicModeStatus,
-	0,
-	0,
-	NWayAdvert,
-	NWayLPAR,
-	NWayExpansion,
-	0
-};
-
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
-	struct cp_private *cp = netdev_priv(dev);
-
-	return location < 8 && mii_2_8139_map[location] ?
-	       readw(cp->regs + mii_2_8139_map[location]) : 0;
-}
-
-
-static void mdio_write(struct net_device *dev, int phy_id, int location,
-		       int value)
-{
-	struct cp_private *cp = netdev_priv(dev);
-
-	if (location == 0) {
-		cpw8(Cfg9346, Cfg9346_Unlock);
-		cpw16(BasicModeCtrl, value);
-		cpw8(Cfg9346, Cfg9346_Lock);
-	} else if (location < 8 && mii_2_8139_map[location])
-		cpw16(mii_2_8139_map[location], value);
-}
-
-/* Set the ethtool Wake-on-LAN settings */
-static int netdev_set_wol (struct cp_private *cp,
-			   const struct ethtool_wolinfo *wol)
-{
-	u8 options;
-
-	options = cpr8 (Config3) & ~(LinkUp | MagicPacket);
-	/* If WOL is being disabled, no need for complexity */
-	if (wol->wolopts) {
-		if (wol->wolopts & WAKE_PHY)	options |= LinkUp;
-		if (wol->wolopts & WAKE_MAGIC)	options |= MagicPacket;
-	}
-
-	cpw8 (Cfg9346, Cfg9346_Unlock);
-	cpw8 (Config3, options);
-	cpw8 (Cfg9346, Cfg9346_Lock);
-
-	options = 0; /* Paranoia setting */
-	options = cpr8 (Config5) & ~(UWF | MWF | BWF);
-	/* If WOL is being disabled, no need for complexity */
-	if (wol->wolopts) {
-		if (wol->wolopts & WAKE_UCAST)  options |= UWF;
-		if (wol->wolopts & WAKE_BCAST)	options |= BWF;
-		if (wol->wolopts & WAKE_MCAST)	options |= MWF;
-	}
-
-	cpw8 (Config5, options);
-
-	cp->wol_enabled = (wol->wolopts) ? 1 : 0;
-
-	return 0;
-}
-
-/* Get the ethtool Wake-on-LAN settings */
-static void netdev_get_wol (struct cp_private *cp,
-	             struct ethtool_wolinfo *wol)
-{
-	u8 options;
-
-	wol->wolopts   = 0; /* Start from scratch */
-	wol->supported = WAKE_PHY   | WAKE_BCAST | WAKE_MAGIC |
-		         WAKE_MCAST | WAKE_UCAST;
-	/* We don't need to go on if WOL is disabled */
-	if (!cp->wol_enabled) return;
-
-	options        = cpr8 (Config3);
-	if (options & LinkUp)        wol->wolopts |= WAKE_PHY;
-	if (options & MagicPacket)   wol->wolopts |= WAKE_MAGIC;
-
-	options        = 0; /* Paranoia setting */
-	options        = cpr8 (Config5);
-	if (options & UWF)           wol->wolopts |= WAKE_UCAST;
-	if (options & BWF)           wol->wolopts |= WAKE_BCAST;
-	if (options & MWF)           wol->wolopts |= WAKE_MCAST;
-}
-
-static void cp_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct cp_private *cp = netdev_priv(dev);
-
-	strcpy (info->driver, DRV_NAME);
-	strcpy (info->version, DRV_VERSION);
-	strcpy (info->bus_info, pci_name(cp->pdev));
-}
-
-static int cp_get_regs_len(struct net_device *dev)
-{
-	return CP_REGS_SIZE;
-}
-
-static int cp_get_sset_count (struct net_device *dev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		return CP_NUM_STATS;
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static int cp_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	int rc;
-	unsigned long flags;
-
-	spin_lock_irqsave(&cp->lock, flags);
-	rc = mii_ethtool_gset(&cp->mii_if, cmd);
-	spin_unlock_irqrestore(&cp->lock, flags);
-
-	return rc;
-}
-
-static int cp_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	int rc;
-	unsigned long flags;
-
-	spin_lock_irqsave(&cp->lock, flags);
-	rc = mii_ethtool_sset(&cp->mii_if, cmd);
-	spin_unlock_irqrestore(&cp->lock, flags);
-
-	return rc;
-}
-
-static int cp_nway_reset(struct net_device *dev)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	return mii_nway_restart(&cp->mii_if);
-}
-
-static u32 cp_get_msglevel(struct net_device *dev)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	return cp->msg_enable;
-}
-
-static void cp_set_msglevel(struct net_device *dev, u32 value)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	cp->msg_enable = value;
-}
-
-static int cp_set_features(struct net_device *dev, u32 features)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	unsigned long flags;
-
-	if (!((dev->features ^ features) & NETIF_F_RXCSUM))
-		return 0;
-
-	spin_lock_irqsave(&cp->lock, flags);
-
-	if (features & NETIF_F_RXCSUM)
-		cp->cpcmd |= RxChkSum;
-	else
-		cp->cpcmd &= ~RxChkSum;
-
-	if (features & NETIF_F_HW_VLAN_RX)
-		cp->cpcmd |= RxVlanOn;
-	else
-		cp->cpcmd &= ~RxVlanOn;
-
-	cpw16_f(CpCmd, cp->cpcmd);
-	spin_unlock_irqrestore(&cp->lock, flags);
-
-	return 0;
-}
-
-static void cp_get_regs(struct net_device *dev, struct ethtool_regs *regs,
-		        void *p)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	unsigned long flags;
-
-	if (regs->len < CP_REGS_SIZE)
-		return /* -EINVAL */;
-
-	regs->version = CP_REGS_VER;
-
-	spin_lock_irqsave(&cp->lock, flags);
-	memcpy_fromio(p, cp->regs, CP_REGS_SIZE);
-	spin_unlock_irqrestore(&cp->lock, flags);
-}
-
-static void cp_get_wol (struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	unsigned long flags;
-
-	spin_lock_irqsave (&cp->lock, flags);
-	netdev_get_wol (cp, wol);
-	spin_unlock_irqrestore (&cp->lock, flags);
-}
-
-static int cp_set_wol (struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	unsigned long flags;
-	int rc;
-
-	spin_lock_irqsave (&cp->lock, flags);
-	rc = netdev_set_wol (cp, wol);
-	spin_unlock_irqrestore (&cp->lock, flags);
-
-	return rc;
-}
-
-static void cp_get_strings (struct net_device *dev, u32 stringset, u8 *buf)
-{
-	switch (stringset) {
-	case ETH_SS_STATS:
-		memcpy(buf, &ethtool_stats_keys, sizeof(ethtool_stats_keys));
-		break;
-	default:
-		BUG();
-		break;
-	}
-}
-
-static void cp_get_ethtool_stats (struct net_device *dev,
-				  struct ethtool_stats *estats, u64 *tmp_stats)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	struct cp_dma_stats *nic_stats;
-	dma_addr_t dma;
-	int i;
-
-	nic_stats = dma_alloc_coherent(&cp->pdev->dev, sizeof(*nic_stats),
-				       &dma, GFP_KERNEL);
-	if (!nic_stats)
-		return;
-
-	/* begin NIC statistics dump */
-	cpw32(StatsAddr + 4, (u64)dma >> 32);
-	cpw32(StatsAddr, ((u64)dma & DMA_BIT_MASK(32)) | DumpStats);
-	cpr32(StatsAddr);
-
-	for (i = 0; i < 1000; i++) {
-		if ((cpr32(StatsAddr) & DumpStats) == 0)
-			break;
-		udelay(10);
-	}
-	cpw32(StatsAddr, 0);
-	cpw32(StatsAddr + 4, 0);
-	cpr32(StatsAddr);
-
-	i = 0;
-	tmp_stats[i++] = le64_to_cpu(nic_stats->tx_ok);
-	tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok);
-	tmp_stats[i++] = le64_to_cpu(nic_stats->tx_err);
-	tmp_stats[i++] = le32_to_cpu(nic_stats->rx_err);
-	tmp_stats[i++] = le16_to_cpu(nic_stats->rx_fifo);
-	tmp_stats[i++] = le16_to_cpu(nic_stats->frame_align);
-	tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_1col);
-	tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_mcol);
-	tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_phys);
-	tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_bcast);
-	tmp_stats[i++] = le32_to_cpu(nic_stats->rx_ok_mcast);
-	tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort);
-	tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun);
-	tmp_stats[i++] = cp->cp_stats.rx_frags;
-	BUG_ON(i != CP_NUM_STATS);
-
-	dma_free_coherent(&cp->pdev->dev, sizeof(*nic_stats), nic_stats, dma);
-}
-
-static const struct ethtool_ops cp_ethtool_ops = {
-	.get_drvinfo		= cp_get_drvinfo,
-	.get_regs_len		= cp_get_regs_len,
-	.get_sset_count		= cp_get_sset_count,
-	.get_settings		= cp_get_settings,
-	.set_settings		= cp_set_settings,
-	.nway_reset		= cp_nway_reset,
-	.get_link		= ethtool_op_get_link,
-	.get_msglevel		= cp_get_msglevel,
-	.set_msglevel		= cp_set_msglevel,
-	.get_regs		= cp_get_regs,
-	.get_wol		= cp_get_wol,
-	.set_wol		= cp_set_wol,
-	.get_strings		= cp_get_strings,
-	.get_ethtool_stats	= cp_get_ethtool_stats,
-	.get_eeprom_len		= cp_get_eeprom_len,
-	.get_eeprom		= cp_get_eeprom,
-	.set_eeprom		= cp_set_eeprom,
-};
-
-static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	int rc;
-	unsigned long flags;
-
-	if (!netif_running(dev))
-		return -EINVAL;
-
-	spin_lock_irqsave(&cp->lock, flags);
-	rc = generic_mii_ioctl(&cp->mii_if, if_mii(rq), cmd, NULL);
-	spin_unlock_irqrestore(&cp->lock, flags);
-	return rc;
-}
-
-static int cp_set_mac_address(struct net_device *dev, void *p)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	struct sockaddr *addr = p;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
-	spin_lock_irq(&cp->lock);
-
-	cpw8_f(Cfg9346, Cfg9346_Unlock);
-	cpw32_f(MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0)));
-	cpw32_f(MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4)));
-	cpw8_f(Cfg9346, Cfg9346_Lock);
-
-	spin_unlock_irq(&cp->lock);
-
-	return 0;
-}
-
-/* Serial EEPROM section. */
-
-/*  EEPROM_Ctrl bits. */
-#define EE_SHIFT_CLK	0x04	/* EEPROM shift clock. */
-#define EE_CS			0x08	/* EEPROM chip select. */
-#define EE_DATA_WRITE	0x02	/* EEPROM chip data in. */
-#define EE_WRITE_0		0x00
-#define EE_WRITE_1		0x02
-#define EE_DATA_READ	0x01	/* EEPROM chip data out. */
-#define EE_ENB			(0x80 | EE_CS)
-
-/* Delay between EEPROM clock transitions.
-   No extra delay is needed with 33Mhz PCI, but 66Mhz may change this.
- */
-
-#define eeprom_delay()	readl(ee_addr)
-
-/* The EEPROM commands include the alway-set leading bit. */
-#define EE_EXTEND_CMD	(4)
-#define EE_WRITE_CMD	(5)
-#define EE_READ_CMD		(6)
-#define EE_ERASE_CMD	(7)
-
-#define EE_EWDS_ADDR	(0)
-#define EE_WRAL_ADDR	(1)
-#define EE_ERAL_ADDR	(2)
-#define EE_EWEN_ADDR	(3)
-
-#define CP_EEPROM_MAGIC PCI_DEVICE_ID_REALTEK_8139
-
-static void eeprom_cmd_start(void __iomem *ee_addr)
-{
-	writeb (EE_ENB & ~EE_CS, ee_addr);
-	writeb (EE_ENB, ee_addr);
-	eeprom_delay ();
-}
-
-static void eeprom_cmd(void __iomem *ee_addr, int cmd, int cmd_len)
-{
-	int i;
-
-	/* Shift the command bits out. */
-	for (i = cmd_len - 1; i >= 0; i--) {
-		int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0;
-		writeb (EE_ENB | dataval, ee_addr);
-		eeprom_delay ();
-		writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
-		eeprom_delay ();
-	}
-	writeb (EE_ENB, ee_addr);
-	eeprom_delay ();
-}
-
-static void eeprom_cmd_end(void __iomem *ee_addr)
-{
-	writeb (~EE_CS, ee_addr);
-	eeprom_delay ();
-}
-
-static void eeprom_extend_cmd(void __iomem *ee_addr, int extend_cmd,
-			      int addr_len)
-{
-	int cmd = (EE_EXTEND_CMD << addr_len) | (extend_cmd << (addr_len - 2));
-
-	eeprom_cmd_start(ee_addr);
-	eeprom_cmd(ee_addr, cmd, 3 + addr_len);
-	eeprom_cmd_end(ee_addr);
-}
-
-static u16 read_eeprom (void __iomem *ioaddr, int location, int addr_len)
-{
-	int i;
-	u16 retval = 0;
-	void __iomem *ee_addr = ioaddr + Cfg9346;
-	int read_cmd = location | (EE_READ_CMD << addr_len);
-
-	eeprom_cmd_start(ee_addr);
-	eeprom_cmd(ee_addr, read_cmd, 3 + addr_len);
-
-	for (i = 16; i > 0; i--) {
-		writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);
-		eeprom_delay ();
-		retval =
-		    (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 :
-				     0);
-		writeb (EE_ENB, ee_addr);
-		eeprom_delay ();
-	}
-
-	eeprom_cmd_end(ee_addr);
-
-	return retval;
-}
-
-static void write_eeprom(void __iomem *ioaddr, int location, u16 val,
-			 int addr_len)
-{
-	int i;
-	void __iomem *ee_addr = ioaddr + Cfg9346;
-	int write_cmd = location | (EE_WRITE_CMD << addr_len);
-
-	eeprom_extend_cmd(ee_addr, EE_EWEN_ADDR, addr_len);
-
-	eeprom_cmd_start(ee_addr);
-	eeprom_cmd(ee_addr, write_cmd, 3 + addr_len);
-	eeprom_cmd(ee_addr, val, 16);
-	eeprom_cmd_end(ee_addr);
-
-	eeprom_cmd_start(ee_addr);
-	for (i = 0; i < 20000; i++)
-		if (readb(ee_addr) & EE_DATA_READ)
-			break;
-	eeprom_cmd_end(ee_addr);
-
-	eeprom_extend_cmd(ee_addr, EE_EWDS_ADDR, addr_len);
-}
-
-static int cp_get_eeprom_len(struct net_device *dev)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	int size;
-
-	spin_lock_irq(&cp->lock);
-	size = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 256 : 128;
-	spin_unlock_irq(&cp->lock);
-
-	return size;
-}
-
-static int cp_get_eeprom(struct net_device *dev,
-			 struct ethtool_eeprom *eeprom, u8 *data)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	unsigned int addr_len;
-	u16 val;
-	u32 offset = eeprom->offset >> 1;
-	u32 len = eeprom->len;
-	u32 i = 0;
-
-	eeprom->magic = CP_EEPROM_MAGIC;
-
-	spin_lock_irq(&cp->lock);
-
-	addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6;
-
-	if (eeprom->offset & 1) {
-		val = read_eeprom(cp->regs, offset, addr_len);
-		data[i++] = (u8)(val >> 8);
-		offset++;
-	}
-
-	while (i < len - 1) {
-		val = read_eeprom(cp->regs, offset, addr_len);
-		data[i++] = (u8)val;
-		data[i++] = (u8)(val >> 8);
-		offset++;
-	}
-
-	if (i < len) {
-		val = read_eeprom(cp->regs, offset, addr_len);
-		data[i] = (u8)val;
-	}
-
-	spin_unlock_irq(&cp->lock);
-	return 0;
-}
-
-static int cp_set_eeprom(struct net_device *dev,
-			 struct ethtool_eeprom *eeprom, u8 *data)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	unsigned int addr_len;
-	u16 val;
-	u32 offset = eeprom->offset >> 1;
-	u32 len = eeprom->len;
-	u32 i = 0;
-
-	if (eeprom->magic != CP_EEPROM_MAGIC)
-		return -EINVAL;
-
-	spin_lock_irq(&cp->lock);
-
-	addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6;
-
-	if (eeprom->offset & 1) {
-		val = read_eeprom(cp->regs, offset, addr_len) & 0xff;
-		val |= (u16)data[i++] << 8;
-		write_eeprom(cp->regs, offset, val, addr_len);
-		offset++;
-	}
-
-	while (i < len - 1) {
-		val = (u16)data[i++];
-		val |= (u16)data[i++] << 8;
-		write_eeprom(cp->regs, offset, val, addr_len);
-		offset++;
-	}
-
-	if (i < len) {
-		val = read_eeprom(cp->regs, offset, addr_len) & 0xff00;
-		val |= (u16)data[i];
-		write_eeprom(cp->regs, offset, val, addr_len);
-	}
-
-	spin_unlock_irq(&cp->lock);
-	return 0;
-}
-
-/* Put the board into D3cold state and wait for WakeUp signal */
-static void cp_set_d3_state (struct cp_private *cp)
-{
-	pci_enable_wake (cp->pdev, 0, 1); /* Enable PME# generation */
-	pci_set_power_state (cp->pdev, PCI_D3hot);
-}
-
-static const struct net_device_ops cp_netdev_ops = {
-	.ndo_open		= cp_open,
-	.ndo_stop		= cp_close,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address 	= cp_set_mac_address,
-	.ndo_set_multicast_list	= cp_set_rx_mode,
-	.ndo_get_stats		= cp_get_stats,
-	.ndo_do_ioctl		= cp_ioctl,
-	.ndo_start_xmit		= cp_start_xmit,
-	.ndo_tx_timeout		= cp_tx_timeout,
-	.ndo_set_features	= cp_set_features,
-#ifdef BROKEN
-	.ndo_change_mtu		= cp_change_mtu,
-#endif
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= cp_poll_controller,
-#endif
-};
-
-static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	struct net_device *dev;
-	struct cp_private *cp;
-	int rc;
-	void __iomem *regs;
-	resource_size_t pciaddr;
-	unsigned int addr_len, i, pci_using_dac;
-
-#ifndef MODULE
-	static int version_printed;
-	if (version_printed++ == 0)
-		pr_info("%s", version);
-#endif
-
-	if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
-	    pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision < 0x20) {
-		dev_info(&pdev->dev,
-			 "This (id %04x:%04x rev %02x) is not an 8139C+ compatible chip, use 8139too\n",
-			 pdev->vendor, pdev->device, pdev->revision);
-		return -ENODEV;
-	}
-
-	dev = alloc_etherdev(sizeof(struct cp_private));
-	if (!dev)
-		return -ENOMEM;
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-	cp = netdev_priv(dev);
-	cp->pdev = pdev;
-	cp->dev = dev;
-	cp->msg_enable = (debug < 0 ? CP_DEF_MSG_ENABLE : debug);
-	spin_lock_init (&cp->lock);
-	cp->mii_if.dev = dev;
-	cp->mii_if.mdio_read = mdio_read;
-	cp->mii_if.mdio_write = mdio_write;
-	cp->mii_if.phy_id = CP_INTERNAL_PHY;
-	cp->mii_if.phy_id_mask = 0x1f;
-	cp->mii_if.reg_num_mask = 0x1f;
-	cp_set_rxbufsize(cp);
-
-	rc = pci_enable_device(pdev);
-	if (rc)
-		goto err_out_free;
-
-	rc = pci_set_mwi(pdev);
-	if (rc)
-		goto err_out_disable;
-
-	rc = pci_request_regions(pdev, DRV_NAME);
-	if (rc)
-		goto err_out_mwi;
-
-	pciaddr = pci_resource_start(pdev, 1);
-	if (!pciaddr) {
-		rc = -EIO;
-		dev_err(&pdev->dev, "no MMIO resource\n");
-		goto err_out_res;
-	}
-	if (pci_resource_len(pdev, 1) < CP_REGS_SIZE) {
-		rc = -EIO;
-		dev_err(&pdev->dev, "MMIO resource (%llx) too small\n",
-		       (unsigned long long)pci_resource_len(pdev, 1));
-		goto err_out_res;
-	}
-
-	/* Configure DMA attributes. */
-	if ((sizeof(dma_addr_t) > 4) &&
-	    !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) &&
-	    !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-		pci_using_dac = 1;
-	} else {
-		pci_using_dac = 0;
-
-		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-		if (rc) {
-			dev_err(&pdev->dev,
-				"No usable DMA configuration, aborting\n");
-			goto err_out_res;
-		}
-		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-		if (rc) {
-			dev_err(&pdev->dev,
-				"No usable consistent DMA configuration, aborting\n");
-			goto err_out_res;
-		}
-	}
-
-	cp->cpcmd = (pci_using_dac ? PCIDAC : 0) |
-		    PCIMulRW | RxChkSum | CpRxOn | CpTxOn;
-
-	dev->features |= NETIF_F_RXCSUM;
-	dev->hw_features |= NETIF_F_RXCSUM;
-
-	regs = ioremap(pciaddr, CP_REGS_SIZE);
-	if (!regs) {
-		rc = -EIO;
-		dev_err(&pdev->dev, "Cannot map PCI MMIO (%Lx@%Lx)\n",
-			(unsigned long long)pci_resource_len(pdev, 1),
-		       (unsigned long long)pciaddr);
-		goto err_out_res;
-	}
-	dev->base_addr = (unsigned long) regs;
-	cp->regs = regs;
-
-	cp_stop_hw(cp);
-
-	/* read MAC address from EEPROM */
-	addr_len = read_eeprom (regs, 0, 8) == 0x8129 ? 8 : 6;
-	for (i = 0; i < 3; i++)
-		((__le16 *) (dev->dev_addr))[i] =
-		    cpu_to_le16(read_eeprom (regs, i + 7, addr_len));
-	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
-	dev->netdev_ops = &cp_netdev_ops;
-	netif_napi_add(dev, &cp->napi, cp_rx_poll, 16);
-	dev->ethtool_ops = &cp_ethtool_ops;
-	dev->watchdog_timeo = TX_TIMEOUT;
-
-	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-
-	if (pci_using_dac)
-		dev->features |= NETIF_F_HIGHDMA;
-
-	/* disabled by default until verified */
-	dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
-		NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-	dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
-		NETIF_F_HIGHDMA;
-
-	dev->irq = pdev->irq;
-
-	rc = register_netdev(dev);
-	if (rc)
-		goto err_out_iomap;
-
-	netdev_info(dev, "RTL-8139C+ at 0x%lx, %pM, IRQ %d\n",
-		    dev->base_addr, dev->dev_addr, dev->irq);
-
-	pci_set_drvdata(pdev, dev);
-
-	/* enable busmastering and memory-write-invalidate */
-	pci_set_master(pdev);
-
-	if (cp->wol_enabled)
-		cp_set_d3_state (cp);
-
-	return 0;
-
-err_out_iomap:
-	iounmap(regs);
-err_out_res:
-	pci_release_regions(pdev);
-err_out_mwi:
-	pci_clear_mwi(pdev);
-err_out_disable:
-	pci_disable_device(pdev);
-err_out_free:
-	free_netdev(dev);
-	return rc;
-}
-
-static void cp_remove_one (struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct cp_private *cp = netdev_priv(dev);
-
-	unregister_netdev(dev);
-	iounmap(cp->regs);
-	if (cp->wol_enabled)
-		pci_set_power_state (pdev, PCI_D0);
-	pci_release_regions(pdev);
-	pci_clear_mwi(pdev);
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-	free_netdev(dev);
-}
-
-#ifdef CONFIG_PM
-static int cp_suspend (struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct cp_private *cp = netdev_priv(dev);
-	unsigned long flags;
-
-	if (!netif_running(dev))
-		return 0;
-
-	netif_device_detach (dev);
-	netif_stop_queue (dev);
-
-	spin_lock_irqsave (&cp->lock, flags);
-
-	/* Disable Rx and Tx */
-	cpw16 (IntrMask, 0);
-	cpw8  (Cmd, cpr8 (Cmd) & (~RxOn | ~TxOn));
-
-	spin_unlock_irqrestore (&cp->lock, flags);
-
-	pci_save_state(pdev);
-	pci_enable_wake(pdev, pci_choose_state(pdev, state), cp->wol_enabled);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
-	return 0;
-}
-
-static int cp_resume (struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata (pdev);
-	struct cp_private *cp = netdev_priv(dev);
-	unsigned long flags;
-
-	if (!netif_running(dev))
-		return 0;
-
-	netif_device_attach (dev);
-
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	pci_enable_wake(pdev, PCI_D0, 0);
-
-	/* FIXME: sh*t may happen if the Rx ring buffer is depleted */
-	cp_init_rings_index (cp);
-	cp_init_hw (cp);
-	netif_start_queue (dev);
-
-	spin_lock_irqsave (&cp->lock, flags);
-
-	mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
-
-	spin_unlock_irqrestore (&cp->lock, flags);
-
-	return 0;
-}
-#endif /* CONFIG_PM */
-
-static struct pci_driver cp_driver = {
-	.name         = DRV_NAME,
-	.id_table     = cp_pci_tbl,
-	.probe        =	cp_init_one,
-	.remove       = cp_remove_one,
-#ifdef CONFIG_PM
-	.resume       = cp_resume,
-	.suspend      = cp_suspend,
-#endif
-};
-
-static int __init cp_init (void)
-{
-#ifdef MODULE
-	pr_info("%s", version);
-#endif
-	return pci_register_driver(&cp_driver);
-}
-
-static void __exit cp_exit (void)
-{
-	pci_unregister_driver (&cp_driver);
-}
-
-module_init(cp_init);
-module_exit(cp_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/8139too.c linux-libre-3.2-gnu/drivers/net/8139too.c
--- linux-libre-3.1-gnu/drivers/net/8139too.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/8139too.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2622 +0,0 @@
-/*
-
-	8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux.
-
-	Maintained by Jeff Garzik <jgarzik@pobox.com>
-	Copyright 2000-2002 Jeff Garzik
-
-	Much code comes from Donald Becker's rtl8139.c driver,
-	versions 1.13 and older.  This driver was originally based
-	on rtl8139.c version 1.07.  Header of rtl8139.c version 1.13:
-
-	-----<snip>-----
-
-        	Written 1997-2001 by Donald Becker.
-		This software may be used and distributed according to the
-		terms of the GNU General Public License (GPL), incorporated
-		herein by reference.  Drivers based on or derived from this
-		code fall under the GPL and must retain the authorship,
-		copyright and license notice.  This file is not a complete
-		program and may only be used when the entire operating
-		system is licensed under the GPL.
-
-		This driver is for boards based on the RTL8129 and RTL8139
-		PCI ethernet chips.
-
-		The author may be reached as becker@scyld.com, or C/O Scyld
-		Computing Corporation 410 Severn Ave., Suite 210 Annapolis
-		MD 21403
-
-		Support and updates available at
-		http://www.scyld.com/network/rtl8139.html
-
-		Twister-tuning table provided by Kinston
-		<shangh@realtek.com.tw>.
-
-	-----<snip>-----
-
-	This software may be used and distributed according to the terms
-	of the GNU General Public License, incorporated herein by reference.
-
-	Contributors:
-
-		Donald Becker - he wrote the original driver, kudos to him!
-		(but please don't e-mail him for support, this isn't his driver)
-
-		Tigran Aivazian - bug fixes, skbuff free cleanup
-
-		Martin Mares - suggestions for PCI cleanup
-
-		David S. Miller - PCI DMA and softnet updates
-
-		Ernst Gill - fixes ported from BSD driver
-
-		Daniel Kobras - identified specific locations of
-			posted MMIO write bugginess
-
-		Gerard Sharp - bug fix, testing and feedback
-
-		David Ford - Rx ring wrap fix
-
-		Dan DeMaggio - swapped RTL8139 cards with me, and allowed me
-		to find and fix a crucial bug on older chipsets.
-
-		Donald Becker/Chris Butterworth/Marcus Westergren -
-		Noticed various Rx packet size-related buglets.
-
-		Santiago Garcia Mantinan - testing and feedback
-
-		Jens David - 2.2.x kernel backports
-
-		Martin Dennett - incredibly helpful insight on undocumented
-		features of the 8139 chips
-
-		Jean-Jacques Michel - bug fix
-
-		Tobias RingstrÃ¶m - Rx interrupt status checking suggestion
-
-		Andrew Morton - Clear blocked signals, avoid
-		buffer overrun setting current->comm.
-
-		Kalle Olavi Niemitalo - Wake-on-LAN ioctls
-
-		Robert Kuebel - Save kernel thread from dying on any signal.
-
-	Submitting bug reports:
-
-		"rtl8139-diag -mmmaaavvveefN" output
-		enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log
-
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define DRV_NAME	"8139too"
-#define DRV_VERSION	"0.9.28"
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/compiler.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/rtnetlink.h>
-#include <linux/delay.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-#include <linux/completion.h>
-#include <linux/crc32.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-#include <linux/gfp.h>
-#include <asm/irq.h>
-
-#define RTL8139_DRIVER_NAME   DRV_NAME " Fast Ethernet driver " DRV_VERSION
-
-/* Default Message level */
-#define RTL8139_DEF_MSG_ENABLE   (NETIF_MSG_DRV   | \
-                                 NETIF_MSG_PROBE  | \
-                                 NETIF_MSG_LINK)
-
-
-/* define to 1, 2 or 3 to enable copious debugging info */
-#define RTL8139_DEBUG 0
-
-/* define to 1 to disable lightweight runtime debugging checks */
-#undef RTL8139_NDEBUG
-
-
-#ifdef RTL8139_NDEBUG
-#  define assert(expr) do {} while (0)
-#else
-#  define assert(expr) \
-        if (unlikely(!(expr))) {				\
-		pr_err("Assertion failed! %s,%s,%s,line=%d\n",	\
-		       #expr, __FILE__, __func__, __LINE__);	\
-        }
-#endif
-
-
-/* A few user-configurable values. */
-/* media options */
-#define MAX_UNITS 8
-static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-
-/* Whether to use MMIO or PIO. Default to MMIO. */
-#ifdef CONFIG_8139TOO_PIO
-static int use_io = 1;
-#else
-static int use_io = 0;
-#endif
-
-/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
-   The RTL chips use a 64 element hash table based on the Ethernet CRC.  */
-static int multicast_filter_limit = 32;
-
-/* bitmapped message enable number */
-static int debug = -1;
-
-/*
- * Receive ring size
- * Warning: 64K ring has hardware issues and may lock up.
- */
-#if defined(CONFIG_SH_DREAMCAST)
-#define RX_BUF_IDX 0	/* 8K ring */
-#else
-#define RX_BUF_IDX	2	/* 32K ring */
-#endif
-#define RX_BUF_LEN	(8192 << RX_BUF_IDX)
-#define RX_BUF_PAD	16
-#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */
-
-#if RX_BUF_LEN == 65536
-#define RX_BUF_TOT_LEN	RX_BUF_LEN
-#else
-#define RX_BUF_TOT_LEN	(RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD)
-#endif
-
-/* Number of Tx descriptor registers. */
-#define NUM_TX_DESC	4
-
-/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/
-#define MAX_ETH_FRAME_SIZE	1536
-
-/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */
-#define TX_BUF_SIZE	MAX_ETH_FRAME_SIZE
-#define TX_BUF_TOT_LEN	(TX_BUF_SIZE * NUM_TX_DESC)
-
-/* PCI Tuning Parameters
-   Threshold is bytes transferred to chip before transmission starts. */
-#define TX_FIFO_THRESH 256	/* In bytes, rounded down to 32 byte units. */
-
-/* The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024, 7==end of packet. */
-#define RX_FIFO_THRESH	7	/* Rx buffer level before first PCI xfer.  */
-#define RX_DMA_BURST	7	/* Maximum PCI burst, '6' is 1024 */
-#define TX_DMA_BURST	6	/* Maximum PCI burst, '6' is 1024 */
-#define TX_RETRY	8	/* 0-15.  retries = 16 + (TX_RETRY * 16) */
-
-/* Operational parameters that usually are not changed. */
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  (6*HZ)
-
-
-enum {
-	HAS_MII_XCVR = 0x010000,
-	HAS_CHIP_XCVR = 0x020000,
-	HAS_LNK_CHNG = 0x040000,
-};
-
-#define RTL_NUM_STATS 4		/* number of ETHTOOL_GSTATS u64's */
-#define RTL_REGS_VER 1		/* version of reg. data in ETHTOOL_GREGS */
-#define RTL_MIN_IO_SIZE 0x80
-#define RTL8139B_IO_SIZE 256
-
-#define RTL8129_CAPS	HAS_MII_XCVR
-#define RTL8139_CAPS	(HAS_CHIP_XCVR|HAS_LNK_CHNG)
-
-typedef enum {
-	RTL8139 = 0,
-	RTL8129,
-} board_t;
-
-
-/* indexed by board_t, above */
-static const struct {
-	const char *name;
-	u32 hw_flags;
-} board_info[] __devinitdata = {
-	{ "RealTek RTL8139", RTL8139_CAPS },
-	{ "RealTek RTL8129", RTL8129_CAPS },
-};
-
-
-static DEFINE_PCI_DEVICE_TABLE(rtl8139_pci_tbl) = {
-	{0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-
-#ifdef CONFIG_SH_SECUREEDGE5410
-	/* Bogus 8139 silicon reports 8129 without external PROM :-( */
-	{0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-#endif
-#ifdef CONFIG_8139TOO_8129
-	{0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 },
-#endif
-
-	/* some crazy cards report invalid vendor ids like
-	 * 0x0001 here.  The other ids are valid and constant,
-	 * so we simply don't match on the main vendor id.
-	 */
-	{PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 },
-	{PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 },
-	{PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 },
-
-	{0,}
-};
-MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl);
-
-static struct {
-	const char str[ETH_GSTRING_LEN];
-} ethtool_stats_keys[] = {
-	{ "early_rx" },
-	{ "tx_buf_mapped" },
-	{ "tx_timeouts" },
-	{ "rx_lost_in_ring" },
-};
-
-/* The rest of these values should never change. */
-
-/* Symbolic offsets to registers. */
-enum RTL8139_registers {
-	MAC0		= 0,	 /* Ethernet hardware address. */
-	MAR0		= 8,	 /* Multicast filter. */
-	TxStatus0	= 0x10,	 /* Transmit status (Four 32bit registers). */
-	TxAddr0		= 0x20,	 /* Tx descriptors (also four 32bit). */
-	RxBuf		= 0x30,
-	ChipCmd		= 0x37,
-	RxBufPtr	= 0x38,
-	RxBufAddr	= 0x3A,
-	IntrMask	= 0x3C,
-	IntrStatus	= 0x3E,
-	TxConfig	= 0x40,
-	RxConfig	= 0x44,
-	Timer		= 0x48,	 /* A general-purpose counter. */
-	RxMissed	= 0x4C,  /* 24 bits valid, write clears. */
-	Cfg9346		= 0x50,
-	Config0		= 0x51,
-	Config1		= 0x52,
-	TimerInt	= 0x54,
-	MediaStatus	= 0x58,
-	Config3		= 0x59,
-	Config4		= 0x5A,	 /* absent on RTL-8139A */
-	HltClk		= 0x5B,
-	MultiIntr	= 0x5C,
-	TxSummary	= 0x60,
-	BasicModeCtrl	= 0x62,
-	BasicModeStatus	= 0x64,
-	NWayAdvert	= 0x66,
-	NWayLPAR	= 0x68,
-	NWayExpansion	= 0x6A,
-	/* Undocumented registers, but required for proper operation. */
-	FIFOTMS		= 0x70,	 /* FIFO Control and test. */
-	CSCR		= 0x74,	 /* Chip Status and Configuration Register. */
-	PARA78		= 0x78,
-	FlashReg	= 0xD4,	/* Communication with Flash ROM, four bytes. */
-	PARA7c		= 0x7c,	 /* Magic transceiver parameter register. */
-	Config5		= 0xD8,	 /* absent on RTL-8139A */
-};
-
-enum ClearBitMasks {
-	MultiIntrClear	= 0xF000,
-	ChipCmdClear	= 0xE2,
-	Config1Clear	= (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1),
-};
-
-enum ChipCmdBits {
-	CmdReset	= 0x10,
-	CmdRxEnb	= 0x08,
-	CmdTxEnb	= 0x04,
-	RxBufEmpty	= 0x01,
-};
-
-/* Interrupt register bits, using my own meaningful names. */
-enum IntrStatusBits {
-	PCIErr		= 0x8000,
-	PCSTimeout	= 0x4000,
-	RxFIFOOver	= 0x40,
-	RxUnderrun	= 0x20,
-	RxOverflow	= 0x10,
-	TxErr		= 0x08,
-	TxOK		= 0x04,
-	RxErr		= 0x02,
-	RxOK		= 0x01,
-
-	RxAckBits	= RxFIFOOver | RxOverflow | RxOK,
-};
-
-enum TxStatusBits {
-	TxHostOwns	= 0x2000,
-	TxUnderrun	= 0x4000,
-	TxStatOK	= 0x8000,
-	TxOutOfWindow	= 0x20000000,
-	TxAborted	= 0x40000000,
-	TxCarrierLost	= 0x80000000,
-};
-enum RxStatusBits {
-	RxMulticast	= 0x8000,
-	RxPhysical	= 0x4000,
-	RxBroadcast	= 0x2000,
-	RxBadSymbol	= 0x0020,
-	RxRunt		= 0x0010,
-	RxTooLong	= 0x0008,
-	RxCRCErr	= 0x0004,
-	RxBadAlign	= 0x0002,
-	RxStatusOK	= 0x0001,
-};
-
-/* Bits in RxConfig. */
-enum rx_mode_bits {
-	AcceptErr	= 0x20,
-	AcceptRunt	= 0x10,
-	AcceptBroadcast	= 0x08,
-	AcceptMulticast	= 0x04,
-	AcceptMyPhys	= 0x02,
-	AcceptAllPhys	= 0x01,
-};
-
-/* Bits in TxConfig. */
-enum tx_config_bits {
-        /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */
-        TxIFGShift	= 24,
-        TxIFG84		= (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */
-        TxIFG88		= (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */
-        TxIFG92		= (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */
-        TxIFG96		= (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */
-
-	TxLoopBack	= (1 << 18) | (1 << 17), /* enable loopback test mode */
-	TxCRC		= (1 << 16),	/* DISABLE Tx pkt CRC append */
-	TxClearAbt	= (1 << 0),	/* Clear abort (WO) */
-	TxDMAShift	= 8, /* DMA burst value (0-7) is shifted X many bits */
-	TxRetryShift	= 4, /* TXRR value (0-15) is shifted X many bits */
-
-	TxVersionMask	= 0x7C800000, /* mask out version bits 30-26, 23 */
-};
-
-/* Bits in Config1 */
-enum Config1Bits {
-	Cfg1_PM_Enable	= 0x01,
-	Cfg1_VPD_Enable	= 0x02,
-	Cfg1_PIO	= 0x04,
-	Cfg1_MMIO	= 0x08,
-	LWAKE		= 0x10,		/* not on 8139, 8139A */
-	Cfg1_Driver_Load = 0x20,
-	Cfg1_LED0	= 0x40,
-	Cfg1_LED1	= 0x80,
-	SLEEP		= (1 << 1),	/* only on 8139, 8139A */
-	PWRDN		= (1 << 0),	/* only on 8139, 8139A */
-};
-
-/* Bits in Config3 */
-enum Config3Bits {
-	Cfg3_FBtBEn   	= (1 << 0), /* 1	= Fast Back to Back */
-	Cfg3_FuncRegEn	= (1 << 1), /* 1	= enable CardBus Function registers */
-	Cfg3_CLKRUN_En	= (1 << 2), /* 1	= enable CLKRUN */
-	Cfg3_CardB_En 	= (1 << 3), /* 1	= enable CardBus registers */
-	Cfg3_LinkUp   	= (1 << 4), /* 1	= wake up on link up */
-	Cfg3_Magic    	= (1 << 5), /* 1	= wake up on Magic Packet (tm) */
-	Cfg3_PARM_En  	= (1 << 6), /* 0	= software can set twister parameters */
-	Cfg3_GNTSel   	= (1 << 7), /* 1	= delay 1 clock from PCI GNT signal */
-};
-
-/* Bits in Config4 */
-enum Config4Bits {
-	LWPTN	= (1 << 2),	/* not on 8139, 8139A */
-};
-
-/* Bits in Config5 */
-enum Config5Bits {
-	Cfg5_PME_STS   	= (1 << 0), /* 1	= PCI reset resets PME_Status */
-	Cfg5_LANWake   	= (1 << 1), /* 1	= enable LANWake signal */
-	Cfg5_LDPS      	= (1 << 2), /* 0	= save power when link is down */
-	Cfg5_FIFOAddrPtr= (1 << 3), /* Realtek internal SRAM testing */
-	Cfg5_UWF        = (1 << 4), /* 1 = accept unicast wakeup frame */
-	Cfg5_MWF        = (1 << 5), /* 1 = accept multicast wakeup frame */
-	Cfg5_BWF        = (1 << 6), /* 1 = accept broadcast wakeup frame */
-};
-
-enum RxConfigBits {
-	/* rx fifo threshold */
-	RxCfgFIFOShift	= 13,
-	RxCfgFIFONone	= (7 << RxCfgFIFOShift),
-
-	/* Max DMA burst */
-	RxCfgDMAShift	= 8,
-	RxCfgDMAUnlimited = (7 << RxCfgDMAShift),
-
-	/* rx ring buffer length */
-	RxCfgRcv8K	= 0,
-	RxCfgRcv16K	= (1 << 11),
-	RxCfgRcv32K	= (1 << 12),
-	RxCfgRcv64K	= (1 << 11) | (1 << 12),
-
-	/* Disable packet wrap at end of Rx buffer. (not possible with 64k) */
-	RxNoWrap	= (1 << 7),
-};
-
-/* Twister tuning parameters from RealTek.
-   Completely undocumented, but required to tune bad links on some boards. */
-enum CSCRBits {
-	CSCR_LinkOKBit		= 0x0400,
-	CSCR_LinkChangeBit	= 0x0800,
-	CSCR_LinkStatusBits	= 0x0f000,
-	CSCR_LinkDownOffCmd	= 0x003c0,
-	CSCR_LinkDownCmd	= 0x0f3c0,
-};
-
-enum Cfg9346Bits {
-	Cfg9346_Lock	= 0x00,
-	Cfg9346_Unlock	= 0xC0,
-};
-
-typedef enum {
-	CH_8139	= 0,
-	CH_8139_K,
-	CH_8139A,
-	CH_8139A_G,
-	CH_8139B,
-	CH_8130,
-	CH_8139C,
-	CH_8100,
-	CH_8100B_8139D,
-	CH_8101,
-} chip_t;
-
-enum chip_flags {
-	HasHltClk	= (1 << 0),
-	HasLWake	= (1 << 1),
-};
-
-#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \
-	(b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22)
-#define HW_REVID_MASK	HW_REVID(1, 1, 1, 1, 1, 1, 1)
-
-/* directly indexed by chip_t, above */
-static const struct {
-	const char *name;
-	u32 version; /* from RTL8139C/RTL8139D docs */
-	u32 flags;
-} rtl_chip_info[] = {
-	{ "RTL-8139",
-	  HW_REVID(1, 0, 0, 0, 0, 0, 0),
-	  HasHltClk,
-	},
-
-	{ "RTL-8139 rev K",
-	  HW_REVID(1, 1, 0, 0, 0, 0, 0),
-	  HasHltClk,
-	},
-
-	{ "RTL-8139A",
-	  HW_REVID(1, 1, 1, 0, 0, 0, 0),
-	  HasHltClk, /* XXX undocumented? */
-	},
-
-	{ "RTL-8139A rev G",
-	  HW_REVID(1, 1, 1, 0, 0, 1, 0),
-	  HasHltClk, /* XXX undocumented? */
-	},
-
-	{ "RTL-8139B",
-	  HW_REVID(1, 1, 1, 1, 0, 0, 0),
-	  HasLWake,
-	},
-
-	{ "RTL-8130",
-	  HW_REVID(1, 1, 1, 1, 1, 0, 0),
-	  HasLWake,
-	},
-
-	{ "RTL-8139C",
-	  HW_REVID(1, 1, 1, 0, 1, 0, 0),
-	  HasLWake,
-	},
-
-	{ "RTL-8100",
-	  HW_REVID(1, 1, 1, 1, 0, 1, 0),
- 	  HasLWake,
- 	},
-
-	{ "RTL-8100B/8139D",
-	  HW_REVID(1, 1, 1, 0, 1, 0, 1),
-	  HasHltClk /* XXX undocumented? */
-	| HasLWake,
-	},
-
-	{ "RTL-8101",
-	  HW_REVID(1, 1, 1, 0, 1, 1, 1),
-	  HasLWake,
-	},
-};
-
-struct rtl_extra_stats {
-	unsigned long early_rx;
-	unsigned long tx_buf_mapped;
-	unsigned long tx_timeouts;
-	unsigned long rx_lost_in_ring;
-};
-
-struct rtl8139_private {
-	void __iomem		*mmio_addr;
-	int			drv_flags;
-	struct pci_dev		*pci_dev;
-	u32			msg_enable;
-	struct napi_struct	napi;
-	struct net_device	*dev;
-
-	unsigned char		*rx_ring;
-	unsigned int		cur_rx;	/* RX buf index of next pkt */
-	dma_addr_t		rx_ring_dma;
-
-	unsigned int		tx_flag;
-	unsigned long		cur_tx;
-	unsigned long		dirty_tx;
-	unsigned char		*tx_buf[NUM_TX_DESC];	/* Tx bounce buffers */
-	unsigned char		*tx_bufs;	/* Tx bounce buffer region. */
-	dma_addr_t		tx_bufs_dma;
-
-	signed char		phys[4];	/* MII device addresses. */
-
-				/* Twister tune state. */
-	char			twistie, twist_row, twist_col;
-
-	unsigned int		watchdog_fired : 1;
-	unsigned int		default_port : 4; /* Last dev->if_port value. */
-	unsigned int		have_thread : 1;
-
-	spinlock_t		lock;
-	spinlock_t		rx_lock;
-
-	chip_t			chipset;
-	u32			rx_config;
-	struct rtl_extra_stats	xstats;
-
-	struct delayed_work	thread;
-
-	struct mii_if_info	mii;
-	unsigned int		regs_len;
-	unsigned long		fifo_copy_timeout;
-};
-
-MODULE_AUTHOR ("Jeff Garzik <jgarzik@pobox.com>");
-MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-
-module_param(use_io, int, 0);
-MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO");
-module_param(multicast_filter_limit, int, 0);
-module_param_array(media, int, NULL, 0);
-module_param_array(full_duplex, int, NULL, 0);
-module_param(debug, int, 0);
-MODULE_PARM_DESC (debug, "8139too bitmapped message enable number");
-MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses");
-MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps");
-MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)");
-
-static int read_eeprom (void __iomem *ioaddr, int location, int addr_len);
-static int rtl8139_open (struct net_device *dev);
-static int mdio_read (struct net_device *dev, int phy_id, int location);
-static void mdio_write (struct net_device *dev, int phy_id, int location,
-			int val);
-static void rtl8139_start_thread(struct rtl8139_private *tp);
-static void rtl8139_tx_timeout (struct net_device *dev);
-static void rtl8139_init_ring (struct net_device *dev);
-static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb,
-				       struct net_device *dev);
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void rtl8139_poll_controller(struct net_device *dev);
-#endif
-static int rtl8139_set_mac_address(struct net_device *dev, void *p);
-static int rtl8139_poll(struct napi_struct *napi, int budget);
-static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance);
-static int rtl8139_close (struct net_device *dev);
-static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
-static struct net_device_stats *rtl8139_get_stats (struct net_device *dev);
-static void rtl8139_set_rx_mode (struct net_device *dev);
-static void __set_rx_mode (struct net_device *dev);
-static void rtl8139_hw_start (struct net_device *dev);
-static void rtl8139_thread (struct work_struct *work);
-static void rtl8139_tx_timeout_task(struct work_struct *work);
-static const struct ethtool_ops rtl8139_ethtool_ops;
-
-/* write MMIO register, with flush */
-/* Flush avoids rtl8139 bug w/ posted MMIO writes */
-#define RTL_W8_F(reg, val8)	do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0)
-#define RTL_W16_F(reg, val16)	do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0)
-#define RTL_W32_F(reg, val32)	do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0)
-
-/* write MMIO register */
-#define RTL_W8(reg, val8)	iowrite8 ((val8), ioaddr + (reg))
-#define RTL_W16(reg, val16)	iowrite16 ((val16), ioaddr + (reg))
-#define RTL_W32(reg, val32)	iowrite32 ((val32), ioaddr + (reg))
-
-/* read MMIO register */
-#define RTL_R8(reg)		ioread8 (ioaddr + (reg))
-#define RTL_R16(reg)		ioread16 (ioaddr + (reg))
-#define RTL_R32(reg)		ioread32 (ioaddr + (reg))
-
-
-static const u16 rtl8139_intr_mask =
-	PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver |
-	TxErr | TxOK | RxErr | RxOK;
-
-static const u16 rtl8139_norx_intr_mask =
-	PCIErr | PCSTimeout | RxUnderrun |
-	TxErr | TxOK | RxErr ;
-
-#if RX_BUF_IDX == 0
-static const unsigned int rtl8139_rx_config =
-	RxCfgRcv8K | RxNoWrap |
-	(RX_FIFO_THRESH << RxCfgFIFOShift) |
-	(RX_DMA_BURST << RxCfgDMAShift);
-#elif RX_BUF_IDX == 1
-static const unsigned int rtl8139_rx_config =
-	RxCfgRcv16K | RxNoWrap |
-	(RX_FIFO_THRESH << RxCfgFIFOShift) |
-	(RX_DMA_BURST << RxCfgDMAShift);
-#elif RX_BUF_IDX == 2
-static const unsigned int rtl8139_rx_config =
-	RxCfgRcv32K | RxNoWrap |
-	(RX_FIFO_THRESH << RxCfgFIFOShift) |
-	(RX_DMA_BURST << RxCfgDMAShift);
-#elif RX_BUF_IDX == 3
-static const unsigned int rtl8139_rx_config =
-	RxCfgRcv64K |
-	(RX_FIFO_THRESH << RxCfgFIFOShift) |
-	(RX_DMA_BURST << RxCfgDMAShift);
-#else
-#error "Invalid configuration for 8139_RXBUF_IDX"
-#endif
-
-static const unsigned int rtl8139_tx_config =
-	TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift);
-
-static void __rtl8139_cleanup_dev (struct net_device *dev)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	struct pci_dev *pdev;
-
-	assert (dev != NULL);
-	assert (tp->pci_dev != NULL);
-	pdev = tp->pci_dev;
-
-	if (tp->mmio_addr)
-		pci_iounmap (pdev, tp->mmio_addr);
-
-	/* it's ok to call this even if we have no regions to free */
-	pci_release_regions (pdev);
-
-	free_netdev(dev);
-	pci_set_drvdata (pdev, NULL);
-}
-
-
-static void rtl8139_chip_reset (void __iomem *ioaddr)
-{
-	int i;
-
-	/* Soft reset the chip. */
-	RTL_W8 (ChipCmd, CmdReset);
-
-	/* Check that the chip has finished the reset. */
-	for (i = 1000; i > 0; i--) {
-		barrier();
-		if ((RTL_R8 (ChipCmd) & CmdReset) == 0)
-			break;
-		udelay (10);
-	}
-}
-
-
-static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev)
-{
-	void __iomem *ioaddr;
-	struct net_device *dev;
-	struct rtl8139_private *tp;
-	u8 tmp8;
-	int rc, disable_dev_on_err = 0;
-	unsigned int i;
-	unsigned long pio_start, pio_end, pio_flags, pio_len;
-	unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
-	u32 version;
-
-	assert (pdev != NULL);
-
-	/* dev and priv zeroed in alloc_etherdev */
-	dev = alloc_etherdev (sizeof (*tp));
-	if (dev == NULL) {
-		dev_err(&pdev->dev, "Unable to alloc new net device\n");
-		return ERR_PTR(-ENOMEM);
-	}
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-	tp = netdev_priv(dev);
-	tp->pci_dev = pdev;
-
-	/* enable device (incl. PCI PM wakeup and hotplug setup) */
-	rc = pci_enable_device (pdev);
-	if (rc)
-		goto err_out;
-
-	pio_start = pci_resource_start (pdev, 0);
-	pio_end = pci_resource_end (pdev, 0);
-	pio_flags = pci_resource_flags (pdev, 0);
-	pio_len = pci_resource_len (pdev, 0);
-
-	mmio_start = pci_resource_start (pdev, 1);
-	mmio_end = pci_resource_end (pdev, 1);
-	mmio_flags = pci_resource_flags (pdev, 1);
-	mmio_len = pci_resource_len (pdev, 1);
-
-	/* set this immediately, we need to know before
-	 * we talk to the chip directly */
-	pr_debug("PIO region size == 0x%02lX\n", pio_len);
-	pr_debug("MMIO region size == 0x%02lX\n", mmio_len);
-
-retry:
-	if (use_io) {
-		/* make sure PCI base addr 0 is PIO */
-		if (!(pio_flags & IORESOURCE_IO)) {
-			dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n");
-			rc = -ENODEV;
-			goto err_out;
-		}
-		/* check for weird/broken PCI region reporting */
-		if (pio_len < RTL_MIN_IO_SIZE) {
-			dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n");
-			rc = -ENODEV;
-			goto err_out;
-		}
-	} else {
-		/* make sure PCI base addr 1 is MMIO */
-		if (!(mmio_flags & IORESOURCE_MEM)) {
-			dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n");
-			rc = -ENODEV;
-			goto err_out;
-		}
-		if (mmio_len < RTL_MIN_IO_SIZE) {
-			dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n");
-			rc = -ENODEV;
-			goto err_out;
-		}
-	}
-
-	rc = pci_request_regions (pdev, DRV_NAME);
-	if (rc)
-		goto err_out;
-	disable_dev_on_err = 1;
-
-	/* enable PCI bus-mastering */
-	pci_set_master (pdev);
-
-	if (use_io) {
-		ioaddr = pci_iomap(pdev, 0, 0);
-		if (!ioaddr) {
-			dev_err(&pdev->dev, "cannot map PIO, aborting\n");
-			rc = -EIO;
-			goto err_out;
-		}
-		dev->base_addr = pio_start;
-		tp->regs_len = pio_len;
-	} else {
-		/* ioremap MMIO region */
-		ioaddr = pci_iomap(pdev, 1, 0);
-		if (ioaddr == NULL) {
-			dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n");
-			pci_release_regions(pdev);
-			use_io = 1;
-			goto retry;
-		}
-		dev->base_addr = (long) ioaddr;
-		tp->regs_len = mmio_len;
-	}
-	tp->mmio_addr = ioaddr;
-
-	/* Bring old chips out of low-power mode. */
-	RTL_W8 (HltClk, 'R');
-
-	/* check for missing/broken hardware */
-	if (RTL_R32 (TxConfig) == 0xFFFFFFFF) {
-		dev_err(&pdev->dev, "Chip not responding, ignoring board\n");
-		rc = -EIO;
-		goto err_out;
-	}
-
-	/* identify chip attached to board */
-	version = RTL_R32 (TxConfig) & HW_REVID_MASK;
-	for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++)
-		if (version == rtl_chip_info[i].version) {
-			tp->chipset = i;
-			goto match;
-		}
-
-	/* if unknown chip, assume array element #0, original RTL-8139 in this case */
-	i = 0;
-	dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n");
-	dev_dbg(&pdev->dev, "TxConfig = 0x%x\n", RTL_R32 (TxConfig));
-	tp->chipset = 0;
-
-match:
-	pr_debug("chipset id (%d) == index %d, '%s'\n",
-		 version, i, rtl_chip_info[i].name);
-
-	if (tp->chipset >= CH_8139B) {
-		u8 new_tmp8 = tmp8 = RTL_R8 (Config1);
-		pr_debug("PCI PM wakeup\n");
-		if ((rtl_chip_info[tp->chipset].flags & HasLWake) &&
-		    (tmp8 & LWAKE))
-			new_tmp8 &= ~LWAKE;
-		new_tmp8 |= Cfg1_PM_Enable;
-		if (new_tmp8 != tmp8) {
-			RTL_W8 (Cfg9346, Cfg9346_Unlock);
-			RTL_W8 (Config1, tmp8);
-			RTL_W8 (Cfg9346, Cfg9346_Lock);
-		}
-		if (rtl_chip_info[tp->chipset].flags & HasLWake) {
-			tmp8 = RTL_R8 (Config4);
-			if (tmp8 & LWPTN) {
-				RTL_W8 (Cfg9346, Cfg9346_Unlock);
-				RTL_W8 (Config4, tmp8 & ~LWPTN);
-				RTL_W8 (Cfg9346, Cfg9346_Lock);
-			}
-		}
-	} else {
-		pr_debug("Old chip wakeup\n");
-		tmp8 = RTL_R8 (Config1);
-		tmp8 &= ~(SLEEP | PWRDN);
-		RTL_W8 (Config1, tmp8);
-	}
-
-	rtl8139_chip_reset (ioaddr);
-
-	return dev;
-
-err_out:
-	__rtl8139_cleanup_dev (dev);
-	if (disable_dev_on_err)
-		pci_disable_device (pdev);
-	return ERR_PTR(rc);
-}
-
-static const struct net_device_ops rtl8139_netdev_ops = {
-	.ndo_open		= rtl8139_open,
-	.ndo_stop		= rtl8139_close,
-	.ndo_get_stats		= rtl8139_get_stats,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address 	= rtl8139_set_mac_address,
-	.ndo_start_xmit		= rtl8139_start_xmit,
-	.ndo_set_multicast_list	= rtl8139_set_rx_mode,
-	.ndo_do_ioctl		= netdev_ioctl,
-	.ndo_tx_timeout		= rtl8139_tx_timeout,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= rtl8139_poll_controller,
-#endif
-};
-
-static int __devinit rtl8139_init_one (struct pci_dev *pdev,
-				       const struct pci_device_id *ent)
-{
-	struct net_device *dev = NULL;
-	struct rtl8139_private *tp;
-	int i, addr_len, option;
-	void __iomem *ioaddr;
-	static int board_idx = -1;
-
-	assert (pdev != NULL);
-	assert (ent != NULL);
-
-	board_idx++;
-
-	/* when we're built into the kernel, the driver version message
-	 * is only printed if at least one 8139 board has been found
-	 */
-#ifndef MODULE
-	{
-		static int printed_version;
-		if (!printed_version++)
-			pr_info(RTL8139_DRIVER_NAME "\n");
-	}
-#endif
-
-	if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
-	    pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) {
-		dev_info(&pdev->dev,
-			   "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n",
-		       	   pdev->vendor, pdev->device, pdev->revision);
-		return -ENODEV;
-	}
-
-	if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
-	    pdev->device == PCI_DEVICE_ID_REALTEK_8139 &&
-	    pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS &&
-	    pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) {
-		pr_info("OQO Model 2 detected. Forcing PIO\n");
-		use_io = 1;
-	}
-
-	dev = rtl8139_init_board (pdev);
-	if (IS_ERR(dev))
-		return PTR_ERR(dev);
-
-	assert (dev != NULL);
-	tp = netdev_priv(dev);
-	tp->dev = dev;
-
-	ioaddr = tp->mmio_addr;
-	assert (ioaddr != NULL);
-
-	addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6;
-	for (i = 0; i < 3; i++)
-		((__le16 *) (dev->dev_addr))[i] =
-		    cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len));
-	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
-	/* The Rtl8139-specific entries in the device structure. */
-	dev->netdev_ops = &rtl8139_netdev_ops;
-	dev->ethtool_ops = &rtl8139_ethtool_ops;
-	dev->watchdog_timeo = TX_TIMEOUT;
-	netif_napi_add(dev, &tp->napi, rtl8139_poll, 64);
-
-	/* note: the hardware is not capable of sg/csum/highdma, however
-	 * through the use of skb_copy_and_csum_dev we enable these
-	 * features
-	 */
-	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA;
-	dev->vlan_features = dev->features;
-
-	dev->irq = pdev->irq;
-
-	/* tp zeroed and aligned in alloc_etherdev */
-	tp = netdev_priv(dev);
-
-	/* note: tp->chipset set in rtl8139_init_board */
-	tp->drv_flags = board_info[ent->driver_data].hw_flags;
-	tp->mmio_addr = ioaddr;
-	tp->msg_enable =
-		(debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1));
-	spin_lock_init (&tp->lock);
-	spin_lock_init (&tp->rx_lock);
-	INIT_DELAYED_WORK(&tp->thread, rtl8139_thread);
-	tp->mii.dev = dev;
-	tp->mii.mdio_read = mdio_read;
-	tp->mii.mdio_write = mdio_write;
-	tp->mii.phy_id_mask = 0x3f;
-	tp->mii.reg_num_mask = 0x1f;
-
-	/* dev is fully set up and ready to use now */
-	pr_debug("about to register device named %s (%p)...\n",
-		 dev->name, dev);
-	i = register_netdev (dev);
-	if (i) goto err_out;
-
-	pci_set_drvdata (pdev, dev);
-
-	netdev_info(dev, "%s at 0x%lx, %pM, IRQ %d\n",
-		    board_info[ent->driver_data].name,
-		    dev->base_addr, dev->dev_addr, dev->irq);
-
-	netdev_dbg(dev, "Identified 8139 chip type '%s'\n",
-		   rtl_chip_info[tp->chipset].name);
-
-	/* Find the connected MII xcvrs.
-	   Doing this in open() would allow detecting external xcvrs later, but
-	   takes too much time. */
-#ifdef CONFIG_8139TOO_8129
-	if (tp->drv_flags & HAS_MII_XCVR) {
-		int phy, phy_idx = 0;
-		for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) {
-			int mii_status = mdio_read(dev, phy, 1);
-			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
-				u16 advertising = mdio_read(dev, phy, 4);
-				tp->phys[phy_idx++] = phy;
-				netdev_info(dev, "MII transceiver %d status 0x%04x advertising %04x\n",
-					    phy, mii_status, advertising);
-			}
-		}
-		if (phy_idx == 0) {
-			netdev_info(dev, "No MII transceivers found! Assuming SYM transceiver\n");
-			tp->phys[0] = 32;
-		}
-	} else
-#endif
-		tp->phys[0] = 32;
-	tp->mii.phy_id = tp->phys[0];
-
-	/* The lower four bits are the media type. */
-	option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx];
-	if (option > 0) {
-		tp->mii.full_duplex = (option & 0x210) ? 1 : 0;
-		tp->default_port = option & 0xFF;
-		if (tp->default_port)
-			tp->mii.force_media = 1;
-	}
-	if (board_idx < MAX_UNITS  &&  full_duplex[board_idx] > 0)
-		tp->mii.full_duplex = full_duplex[board_idx];
-	if (tp->mii.full_duplex) {
-		netdev_info(dev, "Media type forced to Full Duplex\n");
-		/* Changing the MII-advertised media because might prevent
-		   re-connection. */
-		tp->mii.force_media = 1;
-	}
-	if (tp->default_port) {
-		netdev_info(dev, "  Forcing %dMbps %s-duplex operation\n",
-			    (option & 0x20 ? 100 : 10),
-			    (option & 0x10 ? "full" : "half"));
-		mdio_write(dev, tp->phys[0], 0,
-				   ((option & 0x20) ? 0x2000 : 0) | 	/* 100Mbps? */
-				   ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */
-	}
-
-	/* Put the chip into low-power mode. */
-	if (rtl_chip_info[tp->chipset].flags & HasHltClk)
-		RTL_W8 (HltClk, 'H');	/* 'R' would leave the clock running. */
-
-	return 0;
-
-err_out:
-	__rtl8139_cleanup_dev (dev);
-	pci_disable_device (pdev);
-	return i;
-}
-
-
-static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata (pdev);
-	struct rtl8139_private *tp = netdev_priv(dev);
-
-	assert (dev != NULL);
-
-	cancel_delayed_work_sync(&tp->thread);
-
-	unregister_netdev (dev);
-
-	__rtl8139_cleanup_dev (dev);
-	pci_disable_device (pdev);
-}
-
-
-/* Serial EEPROM section. */
-
-/*  EEPROM_Ctrl bits. */
-#define EE_SHIFT_CLK	0x04	/* EEPROM shift clock. */
-#define EE_CS			0x08	/* EEPROM chip select. */
-#define EE_DATA_WRITE	0x02	/* EEPROM chip data in. */
-#define EE_WRITE_0		0x00
-#define EE_WRITE_1		0x02
-#define EE_DATA_READ	0x01	/* EEPROM chip data out. */
-#define EE_ENB			(0x80 | EE_CS)
-
-/* Delay between EEPROM clock transitions.
-   No extra delay is needed with 33Mhz PCI, but 66Mhz may change this.
- */
-
-#define eeprom_delay()	(void)RTL_R32(Cfg9346)
-
-/* The EEPROM commands include the alway-set leading bit. */
-#define EE_WRITE_CMD	(5)
-#define EE_READ_CMD		(6)
-#define EE_ERASE_CMD	(7)
-
-static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len)
-{
-	int i;
-	unsigned retval = 0;
-	int read_cmd = location | (EE_READ_CMD << addr_len);
-
-	RTL_W8 (Cfg9346, EE_ENB & ~EE_CS);
-	RTL_W8 (Cfg9346, EE_ENB);
-	eeprom_delay ();
-
-	/* Shift the read command bits out. */
-	for (i = 4 + addr_len; i >= 0; i--) {
-		int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
-		RTL_W8 (Cfg9346, EE_ENB | dataval);
-		eeprom_delay ();
-		RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK);
-		eeprom_delay ();
-	}
-	RTL_W8 (Cfg9346, EE_ENB);
-	eeprom_delay ();
-
-	for (i = 16; i > 0; i--) {
-		RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK);
-		eeprom_delay ();
-		retval =
-		    (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 :
-				     0);
-		RTL_W8 (Cfg9346, EE_ENB);
-		eeprom_delay ();
-	}
-
-	/* Terminate the EEPROM access. */
-	RTL_W8 (Cfg9346, ~EE_CS);
-	eeprom_delay ();
-
-	return retval;
-}
-
-/* MII serial management: mostly bogus for now. */
-/* Read and write the MII management registers using software-generated
-   serial MDIO protocol.
-   The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
-   met by back-to-back PCI I/O cycles, but we insert a delay to avoid
-   "overclocking" issues. */
-#define MDIO_DIR		0x80
-#define MDIO_DATA_OUT	0x04
-#define MDIO_DATA_IN	0x02
-#define MDIO_CLK		0x01
-#define MDIO_WRITE0 (MDIO_DIR)
-#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT)
-
-#define mdio_delay()	RTL_R8(Config4)
-
-
-static const char mii_2_8139_map[8] = {
-	BasicModeCtrl,
-	BasicModeStatus,
-	0,
-	0,
-	NWayAdvert,
-	NWayLPAR,
-	NWayExpansion,
-	0
-};
-
-
-#ifdef CONFIG_8139TOO_8129
-/* Syncronize the MII management interface by shifting 32 one bits out. */
-static void mdio_sync (void __iomem *ioaddr)
-{
-	int i;
-
-	for (i = 32; i >= 0; i--) {
-		RTL_W8 (Config4, MDIO_WRITE1);
-		mdio_delay ();
-		RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK);
-		mdio_delay ();
-	}
-}
-#endif
-
-static int mdio_read (struct net_device *dev, int phy_id, int location)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	int retval = 0;
-#ifdef CONFIG_8139TOO_8129
-	void __iomem *ioaddr = tp->mmio_addr;
-	int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
-	int i;
-#endif
-
-	if (phy_id > 31) {	/* Really a 8139.  Use internal registers. */
-		void __iomem *ioaddr = tp->mmio_addr;
-		return location < 8 && mii_2_8139_map[location] ?
-		    RTL_R16 (mii_2_8139_map[location]) : 0;
-	}
-
-#ifdef CONFIG_8139TOO_8129
-	mdio_sync (ioaddr);
-	/* Shift the read command bits out. */
-	for (i = 15; i >= 0; i--) {
-		int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
-
-		RTL_W8 (Config4, MDIO_DIR | dataval);
-		mdio_delay ();
-		RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK);
-		mdio_delay ();
-	}
-
-	/* Read the two transition, 16 data, and wire-idle bits. */
-	for (i = 19; i > 0; i--) {
-		RTL_W8 (Config4, 0);
-		mdio_delay ();
-		retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0);
-		RTL_W8 (Config4, MDIO_CLK);
-		mdio_delay ();
-	}
-#endif
-
-	return (retval >> 1) & 0xffff;
-}
-
-
-static void mdio_write (struct net_device *dev, int phy_id, int location,
-			int value)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-#ifdef CONFIG_8139TOO_8129
-	void __iomem *ioaddr = tp->mmio_addr;
-	int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
-	int i;
-#endif
-
-	if (phy_id > 31) {	/* Really a 8139.  Use internal registers. */
-		void __iomem *ioaddr = tp->mmio_addr;
-		if (location == 0) {
-			RTL_W8 (Cfg9346, Cfg9346_Unlock);
-			RTL_W16 (BasicModeCtrl, value);
-			RTL_W8 (Cfg9346, Cfg9346_Lock);
-		} else if (location < 8 && mii_2_8139_map[location])
-			RTL_W16 (mii_2_8139_map[location], value);
-		return;
-	}
-
-#ifdef CONFIG_8139TOO_8129
-	mdio_sync (ioaddr);
-
-	/* Shift the command bits out. */
-	for (i = 31; i >= 0; i--) {
-		int dataval =
-		    (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
-		RTL_W8 (Config4, dataval);
-		mdio_delay ();
-		RTL_W8 (Config4, dataval | MDIO_CLK);
-		mdio_delay ();
-	}
-	/* Clear out extra bits. */
-	for (i = 2; i > 0; i--) {
-		RTL_W8 (Config4, 0);
-		mdio_delay ();
-		RTL_W8 (Config4, MDIO_CLK);
-		mdio_delay ();
-	}
-#endif
-}
-
-
-static int rtl8139_open (struct net_device *dev)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	int retval;
-	void __iomem *ioaddr = tp->mmio_addr;
-
-	retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev);
-	if (retval)
-		return retval;
-
-	tp->tx_bufs = dma_alloc_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN,
-					   &tp->tx_bufs_dma, GFP_KERNEL);
-	tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN,
-					   &tp->rx_ring_dma, GFP_KERNEL);
-	if (tp->tx_bufs == NULL || tp->rx_ring == NULL) {
-		free_irq(dev->irq, dev);
-
-		if (tp->tx_bufs)
-			dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN,
-					    tp->tx_bufs, tp->tx_bufs_dma);
-		if (tp->rx_ring)
-			dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN,
-					    tp->rx_ring, tp->rx_ring_dma);
-
-		return -ENOMEM;
-
-	}
-
-	napi_enable(&tp->napi);
-
-	tp->mii.full_duplex = tp->mii.force_media;
-	tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
-
-	rtl8139_init_ring (dev);
-	rtl8139_hw_start (dev);
-	netif_start_queue (dev);
-
-	netif_dbg(tp, ifup, dev,
-		  "%s() ioaddr %#llx IRQ %d GP Pins %02x %s-duplex\n",
-		  __func__,
-		  (unsigned long long)pci_resource_start (tp->pci_dev, 1),
-		  dev->irq, RTL_R8 (MediaStatus),
-		  tp->mii.full_duplex ? "full" : "half");
-
-	rtl8139_start_thread(tp);
-
-	return 0;
-}
-
-
-static void rtl_check_media (struct net_device *dev, unsigned int init_media)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-
-	if (tp->phys[0] >= 0) {
-		mii_check_media(&tp->mii, netif_msg_link(tp), init_media);
-	}
-}
-
-/* Start the hardware at open or resume. */
-static void rtl8139_hw_start (struct net_device *dev)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	void __iomem *ioaddr = tp->mmio_addr;
-	u32 i;
-	u8 tmp;
-
-	/* Bring old chips out of low-power mode. */
-	if (rtl_chip_info[tp->chipset].flags & HasHltClk)
-		RTL_W8 (HltClk, 'R');
-
-	rtl8139_chip_reset (ioaddr);
-
-	/* unlock Config[01234] and BMCR register writes */
-	RTL_W8_F (Cfg9346, Cfg9346_Unlock);
-	/* Restore our idea of the MAC address. */
-	RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0)));
-	RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4)));
-
-	tp->cur_rx = 0;
-
-	/* init Rx ring buffer DMA address */
-	RTL_W32_F (RxBuf, tp->rx_ring_dma);
-
-	/* Must enable Tx/Rx before setting transfer thresholds! */
-	RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
-
-	tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys;
-	RTL_W32 (RxConfig, tp->rx_config);
-	RTL_W32 (TxConfig, rtl8139_tx_config);
-
-	rtl_check_media (dev, 1);
-
-	if (tp->chipset >= CH_8139B) {
-		/* Disable magic packet scanning, which is enabled
-		 * when PM is enabled in Config1.  It can be reenabled
-		 * via ETHTOOL_SWOL if desired.  */
-		RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic);
-	}
-
-	netdev_dbg(dev, "init buffer addresses\n");
-
-	/* Lock Config[01234] and BMCR register writes */
-	RTL_W8 (Cfg9346, Cfg9346_Lock);
-
-	/* init Tx buffer DMA addresses */
-	for (i = 0; i < NUM_TX_DESC; i++)
-		RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs));
-
-	RTL_W32 (RxMissed, 0);
-
-	rtl8139_set_rx_mode (dev);
-
-	/* no early-rx interrupts */
-	RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear);
-
-	/* make sure RxTx has started */
-	tmp = RTL_R8 (ChipCmd);
-	if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb)))
-		RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
-
-	/* Enable all known interrupts by setting the interrupt mask. */
-	RTL_W16 (IntrMask, rtl8139_intr_mask);
-}
-
-
-/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void rtl8139_init_ring (struct net_device *dev)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	int i;
-
-	tp->cur_rx = 0;
-	tp->cur_tx = 0;
-	tp->dirty_tx = 0;
-
-	for (i = 0; i < NUM_TX_DESC; i++)
-		tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE];
-}
-
-
-/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */
-static int next_tick = 3 * HZ;
-
-#ifndef CONFIG_8139TOO_TUNE_TWISTER
-static inline void rtl8139_tune_twister (struct net_device *dev,
-				  struct rtl8139_private *tp) {}
-#else
-enum TwisterParamVals {
-	PARA78_default	= 0x78fa8388,
-	PARA7c_default	= 0xcb38de43,	/* param[0][3] */
-	PARA7c_xxx	= 0xcb38de43,
-};
-
-static const unsigned long param[4][4] = {
-	{0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43},
-	{0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83},
-	{0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83},
-	{0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83}
-};
-
-static void rtl8139_tune_twister (struct net_device *dev,
-				  struct rtl8139_private *tp)
-{
-	int linkcase;
-	void __iomem *ioaddr = tp->mmio_addr;
-
-	/* This is a complicated state machine to configure the "twister" for
-	   impedance/echos based on the cable length.
-	   All of this is magic and undocumented.
-	 */
-	switch (tp->twistie) {
-	case 1:
-		if (RTL_R16 (CSCR) & CSCR_LinkOKBit) {
-			/* We have link beat, let us tune the twister. */
-			RTL_W16 (CSCR, CSCR_LinkDownOffCmd);
-			tp->twistie = 2;	/* Change to state 2. */
-			next_tick = HZ / 10;
-		} else {
-			/* Just put in some reasonable defaults for when beat returns. */
-			RTL_W16 (CSCR, CSCR_LinkDownCmd);
-			RTL_W32 (FIFOTMS, 0x20);	/* Turn on cable test mode. */
-			RTL_W32 (PARA78, PARA78_default);
-			RTL_W32 (PARA7c, PARA7c_default);
-			tp->twistie = 0;	/* Bail from future actions. */
-		}
-		break;
-	case 2:
-		/* Read how long it took to hear the echo. */
-		linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits;
-		if (linkcase == 0x7000)
-			tp->twist_row = 3;
-		else if (linkcase == 0x3000)
-			tp->twist_row = 2;
-		else if (linkcase == 0x1000)
-			tp->twist_row = 1;
-		else
-			tp->twist_row = 0;
-		tp->twist_col = 0;
-		tp->twistie = 3;	/* Change to state 2. */
-		next_tick = HZ / 10;
-		break;
-	case 3:
-		/* Put out four tuning parameters, one per 100msec. */
-		if (tp->twist_col == 0)
-			RTL_W16 (FIFOTMS, 0);
-		RTL_W32 (PARA7c, param[(int) tp->twist_row]
-			 [(int) tp->twist_col]);
-		next_tick = HZ / 10;
-		if (++tp->twist_col >= 4) {
-			/* For short cables we are done.
-			   For long cables (row == 3) check for mistune. */
-			tp->twistie =
-			    (tp->twist_row == 3) ? 4 : 0;
-		}
-		break;
-	case 4:
-		/* Special case for long cables: check for mistune. */
-		if ((RTL_R16 (CSCR) &
-		     CSCR_LinkStatusBits) == 0x7000) {
-			tp->twistie = 0;
-			break;
-		} else {
-			RTL_W32 (PARA7c, 0xfb38de03);
-			tp->twistie = 5;
-			next_tick = HZ / 10;
-		}
-		break;
-	case 5:
-		/* Retune for shorter cable (column 2). */
-		RTL_W32 (FIFOTMS, 0x20);
-		RTL_W32 (PARA78, PARA78_default);
-		RTL_W32 (PARA7c, PARA7c_default);
-		RTL_W32 (FIFOTMS, 0x00);
-		tp->twist_row = 2;
-		tp->twist_col = 0;
-		tp->twistie = 3;
-		next_tick = HZ / 10;
-		break;
-
-	default:
-		/* do nothing */
-		break;
-	}
-}
-#endif /* CONFIG_8139TOO_TUNE_TWISTER */
-
-static inline void rtl8139_thread_iter (struct net_device *dev,
-				 struct rtl8139_private *tp,
-				 void __iomem *ioaddr)
-{
-	int mii_lpa;
-
-	mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA);
-
-	if (!tp->mii.force_media && mii_lpa != 0xffff) {
-		int duplex = ((mii_lpa & LPA_100FULL) ||
-			      (mii_lpa & 0x01C0) == 0x0040);
-		if (tp->mii.full_duplex != duplex) {
-			tp->mii.full_duplex = duplex;
-
-			if (mii_lpa) {
-				netdev_info(dev, "Setting %s-duplex based on MII #%d link partner ability of %04x\n",
-					    tp->mii.full_duplex ? "full" : "half",
-					    tp->phys[0], mii_lpa);
-			} else {
-				netdev_info(dev, "media is unconnected, link down, or incompatible connection\n");
-			}
-#if 0
-			RTL_W8 (Cfg9346, Cfg9346_Unlock);
-			RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20);
-			RTL_W8 (Cfg9346, Cfg9346_Lock);
-#endif
-		}
-	}
-
-	next_tick = HZ * 60;
-
-	rtl8139_tune_twister (dev, tp);
-
-	netdev_dbg(dev, "Media selection tick, Link partner %04x\n",
-		   RTL_R16(NWayLPAR));
-	netdev_dbg(dev, "Other registers are IntMask %04x IntStatus %04x\n",
-		   RTL_R16(IntrMask), RTL_R16(IntrStatus));
-	netdev_dbg(dev, "Chip config %02x %02x\n",
-		   RTL_R8(Config0), RTL_R8(Config1));
-}
-
-static void rtl8139_thread (struct work_struct *work)
-{
-	struct rtl8139_private *tp =
-		container_of(work, struct rtl8139_private, thread.work);
-	struct net_device *dev = tp->mii.dev;
-	unsigned long thr_delay = next_tick;
-
-	rtnl_lock();
-
-	if (!netif_running(dev))
-		goto out_unlock;
-
-	if (tp->watchdog_fired) {
-		tp->watchdog_fired = 0;
-		rtl8139_tx_timeout_task(work);
-	} else
-		rtl8139_thread_iter(dev, tp, tp->mmio_addr);
-
-	if (tp->have_thread)
-		schedule_delayed_work(&tp->thread, thr_delay);
-out_unlock:
-	rtnl_unlock ();
-}
-
-static void rtl8139_start_thread(struct rtl8139_private *tp)
-{
-	tp->twistie = 0;
-	if (tp->chipset == CH_8139_K)
-		tp->twistie = 1;
-	else if (tp->drv_flags & HAS_LNK_CHNG)
-		return;
-
-	tp->have_thread = 1;
-	tp->watchdog_fired = 0;
-
-	schedule_delayed_work(&tp->thread, next_tick);
-}
-
-static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
-{
-	tp->cur_tx = 0;
-	tp->dirty_tx = 0;
-
-	/* XXX account for unsent Tx packets in tp->stats.tx_dropped */
-}
-
-static void rtl8139_tx_timeout_task (struct work_struct *work)
-{
-	struct rtl8139_private *tp =
-		container_of(work, struct rtl8139_private, thread.work);
-	struct net_device *dev = tp->mii.dev;
-	void __iomem *ioaddr = tp->mmio_addr;
-	int i;
-	u8 tmp8;
-
-	netdev_dbg(dev, "Transmit timeout, status %02x %04x %04x media %02x\n",
-		   RTL_R8(ChipCmd), RTL_R16(IntrStatus),
-		   RTL_R16(IntrMask), RTL_R8(MediaStatus));
-	/* Emit info to figure out what went wrong. */
-	netdev_dbg(dev, "Tx queue start entry %ld  dirty entry %ld\n",
-		   tp->cur_tx, tp->dirty_tx);
-	for (i = 0; i < NUM_TX_DESC; i++)
-		netdev_dbg(dev, "Tx descriptor %d is %08x%s\n",
-			   i, RTL_R32(TxStatus0 + (i * 4)),
-			   i == tp->dirty_tx % NUM_TX_DESC ?
-			   " (queue head)" : "");
-
-	tp->xstats.tx_timeouts++;
-
-	/* disable Tx ASAP, if not already */
-	tmp8 = RTL_R8 (ChipCmd);
-	if (tmp8 & CmdTxEnb)
-		RTL_W8 (ChipCmd, CmdRxEnb);
-
-	spin_lock_bh(&tp->rx_lock);
-	/* Disable interrupts by clearing the interrupt mask. */
-	RTL_W16 (IntrMask, 0x0000);
-
-	/* Stop a shared interrupt from scavenging while we are. */
-	spin_lock_irq(&tp->lock);
-	rtl8139_tx_clear (tp);
-	spin_unlock_irq(&tp->lock);
-
-	/* ...and finally, reset everything */
-	if (netif_running(dev)) {
-		rtl8139_hw_start (dev);
-		netif_wake_queue (dev);
-	}
-	spin_unlock_bh(&tp->rx_lock);
-}
-
-static void rtl8139_tx_timeout (struct net_device *dev)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-
-	tp->watchdog_fired = 1;
-	if (!tp->have_thread) {
-		INIT_DELAYED_WORK(&tp->thread, rtl8139_thread);
-		schedule_delayed_work(&tp->thread, next_tick);
-	}
-}
-
-static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb,
-					     struct net_device *dev)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	void __iomem *ioaddr = tp->mmio_addr;
-	unsigned int entry;
-	unsigned int len = skb->len;
-	unsigned long flags;
-
-	/* Calculate the next Tx descriptor entry. */
-	entry = tp->cur_tx % NUM_TX_DESC;
-
-	/* Note: the chip doesn't have auto-pad! */
-	if (likely(len < TX_BUF_SIZE)) {
-		if (len < ETH_ZLEN)
-			memset(tp->tx_buf[entry], 0, ETH_ZLEN);
-		skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
-		dev_kfree_skb(skb);
-	} else {
-		dev_kfree_skb(skb);
-		dev->stats.tx_dropped++;
-		return NETDEV_TX_OK;
-	}
-
-	spin_lock_irqsave(&tp->lock, flags);
-	/*
-	 * Writing to TxStatus triggers a DMA transfer of the data
-	 * copied to tp->tx_buf[entry] above. Use a memory barrier
-	 * to make sure that the device sees the updated data.
-	 */
-	wmb();
-	RTL_W32_F (TxStatus0 + (entry * sizeof (u32)),
-		   tp->tx_flag | max(len, (unsigned int)ETH_ZLEN));
-
-	tp->cur_tx++;
-
-	if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
-		netif_stop_queue (dev);
-	spin_unlock_irqrestore(&tp->lock, flags);
-
-	netif_dbg(tp, tx_queued, dev, "Queued Tx packet size %u to slot %d\n",
-		  len, entry);
-
-	return NETDEV_TX_OK;
-}
-
-
-static void rtl8139_tx_interrupt (struct net_device *dev,
-				  struct rtl8139_private *tp,
-				  void __iomem *ioaddr)
-{
-	unsigned long dirty_tx, tx_left;
-
-	assert (dev != NULL);
-	assert (ioaddr != NULL);
-
-	dirty_tx = tp->dirty_tx;
-	tx_left = tp->cur_tx - dirty_tx;
-	while (tx_left > 0) {
-		int entry = dirty_tx % NUM_TX_DESC;
-		int txstatus;
-
-		txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32)));
-
-		if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted)))
-			break;	/* It still hasn't been Txed */
-
-		/* Note: TxCarrierLost is always asserted at 100mbps. */
-		if (txstatus & (TxOutOfWindow | TxAborted)) {
-			/* There was an major error, log it. */
-			netif_dbg(tp, tx_err, dev, "Transmit error, Tx status %08x\n",
-				  txstatus);
-			dev->stats.tx_errors++;
-			if (txstatus & TxAborted) {
-				dev->stats.tx_aborted_errors++;
-				RTL_W32 (TxConfig, TxClearAbt);
-				RTL_W16 (IntrStatus, TxErr);
-				wmb();
-			}
-			if (txstatus & TxCarrierLost)
-				dev->stats.tx_carrier_errors++;
-			if (txstatus & TxOutOfWindow)
-				dev->stats.tx_window_errors++;
-		} else {
-			if (txstatus & TxUnderrun) {
-				/* Add 64 to the Tx FIFO threshold. */
-				if (tp->tx_flag < 0x00300000)
-					tp->tx_flag += 0x00020000;
-				dev->stats.tx_fifo_errors++;
-			}
-			dev->stats.collisions += (txstatus >> 24) & 15;
-			dev->stats.tx_bytes += txstatus & 0x7ff;
-			dev->stats.tx_packets++;
-		}
-
-		dirty_tx++;
-		tx_left--;
-	}
-
-#ifndef RTL8139_NDEBUG
-	if (tp->cur_tx - dirty_tx > NUM_TX_DESC) {
-		netdev_err(dev, "Out-of-sync dirty pointer, %ld vs. %ld\n",
-			   dirty_tx, tp->cur_tx);
-		dirty_tx += NUM_TX_DESC;
-	}
-#endif /* RTL8139_NDEBUG */
-
-	/* only wake the queue if we did work, and the queue is stopped */
-	if (tp->dirty_tx != dirty_tx) {
-		tp->dirty_tx = dirty_tx;
-		mb();
-		netif_wake_queue (dev);
-	}
-}
-
-
-/* TODO: clean this up!  Rx reset need not be this intensive */
-static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,
-			    struct rtl8139_private *tp, void __iomem *ioaddr)
-{
-	u8 tmp8;
-#ifdef CONFIG_8139_OLD_RX_RESET
-	int tmp_work;
-#endif
-
-	netif_dbg(tp, rx_err, dev, "Ethernet frame had errors, status %08x\n",
-		  rx_status);
-	dev->stats.rx_errors++;
-	if (!(rx_status & RxStatusOK)) {
-		if (rx_status & RxTooLong) {
-			netdev_dbg(dev, "Oversized Ethernet frame, status %04x!\n",
-				   rx_status);
-			/* A.C.: The chip hangs here. */
-		}
-		if (rx_status & (RxBadSymbol | RxBadAlign))
-			dev->stats.rx_frame_errors++;
-		if (rx_status & (RxRunt | RxTooLong))
-			dev->stats.rx_length_errors++;
-		if (rx_status & RxCRCErr)
-			dev->stats.rx_crc_errors++;
-	} else {
-		tp->xstats.rx_lost_in_ring++;
-	}
-
-#ifndef CONFIG_8139_OLD_RX_RESET
-	tmp8 = RTL_R8 (ChipCmd);
-	RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb);
-	RTL_W8 (ChipCmd, tmp8);
-	RTL_W32 (RxConfig, tp->rx_config);
-	tp->cur_rx = 0;
-#else
-	/* Reset the receiver, based on RealTek recommendation. (Bug?) */
-
-	/* disable receive */
-	RTL_W8_F (ChipCmd, CmdTxEnb);
-	tmp_work = 200;
-	while (--tmp_work > 0) {
-		udelay(1);
-		tmp8 = RTL_R8 (ChipCmd);
-		if (!(tmp8 & CmdRxEnb))
-			break;
-	}
-	if (tmp_work <= 0)
-		netdev_warn(dev, "rx stop wait too long\n");
-	/* restart receive */
-	tmp_work = 200;
-	while (--tmp_work > 0) {
-		RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb);
-		udelay(1);
-		tmp8 = RTL_R8 (ChipCmd);
-		if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb))
-			break;
-	}
-	if (tmp_work <= 0)
-		netdev_warn(dev, "tx/rx enable wait too long\n");
-
-	/* and reinitialize all rx related registers */
-	RTL_W8_F (Cfg9346, Cfg9346_Unlock);
-	/* Must enable Tx/Rx before setting transfer thresholds! */
-	RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
-
-	tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys;
-	RTL_W32 (RxConfig, tp->rx_config);
-	tp->cur_rx = 0;
-
-	netdev_dbg(dev, "init buffer addresses\n");
-
-	/* Lock Config[01234] and BMCR register writes */
-	RTL_W8 (Cfg9346, Cfg9346_Lock);
-
-	/* init Rx ring buffer DMA address */
-	RTL_W32_F (RxBuf, tp->rx_ring_dma);
-
-	/* A.C.: Reset the multicast list. */
-	__set_rx_mode (dev);
-#endif
-}
-
-#if RX_BUF_IDX == 3
-static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring,
-				 u32 offset, unsigned int size)
-{
-	u32 left = RX_BUF_LEN - offset;
-
-	if (size > left) {
-		skb_copy_to_linear_data(skb, ring + offset, left);
-		skb_copy_to_linear_data_offset(skb, left, ring, size - left);
-	} else
-		skb_copy_to_linear_data(skb, ring + offset, size);
-}
-#endif
-
-static void rtl8139_isr_ack(struct rtl8139_private *tp)
-{
-	void __iomem *ioaddr = tp->mmio_addr;
-	u16 status;
-
-	status = RTL_R16 (IntrStatus) & RxAckBits;
-
-	/* Clear out errors and receive interrupts */
-	if (likely(status != 0)) {
-		if (unlikely(status & (RxFIFOOver | RxOverflow))) {
-			tp->dev->stats.rx_errors++;
-			if (status & RxFIFOOver)
-				tp->dev->stats.rx_fifo_errors++;
-		}
-		RTL_W16_F (IntrStatus, RxAckBits);
-	}
-}
-
-static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
-		      int budget)
-{
-	void __iomem *ioaddr = tp->mmio_addr;
-	int received = 0;
-	unsigned char *rx_ring = tp->rx_ring;
-	unsigned int cur_rx = tp->cur_rx;
-	unsigned int rx_size = 0;
-
-	netdev_dbg(dev, "In %s(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n",
-		   __func__, (u16)cur_rx,
-		   RTL_R16(RxBufAddr), RTL_R16(RxBufPtr), RTL_R8(ChipCmd));
-
-	while (netif_running(dev) && received < budget &&
-	       (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
-		u32 ring_offset = cur_rx % RX_BUF_LEN;
-		u32 rx_status;
-		unsigned int pkt_size;
-		struct sk_buff *skb;
-
-		rmb();
-
-		/* read size+status of next frame from DMA ring buffer */
-		rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset));
-		rx_size = rx_status >> 16;
-		pkt_size = rx_size - 4;
-
-		netif_dbg(tp, rx_status, dev, "%s() status %04x, size %04x, cur %04x\n",
-			  __func__, rx_status, rx_size, cur_rx);
-#if RTL8139_DEBUG > 2
-		print_hex_dump(KERN_DEBUG, "Frame contents: ",
-			       DUMP_PREFIX_OFFSET, 16, 1,
-			       &rx_ring[ring_offset], 70, true);
-#endif
-
-		/* Packet copy from FIFO still in progress.
-		 * Theoretically, this should never happen
-		 * since EarlyRx is disabled.
-		 */
-		if (unlikely(rx_size == 0xfff0)) {
-			if (!tp->fifo_copy_timeout)
-				tp->fifo_copy_timeout = jiffies + 2;
-			else if (time_after(jiffies, tp->fifo_copy_timeout)) {
-				netdev_dbg(dev, "hung FIFO. Reset\n");
-				rx_size = 0;
-				goto no_early_rx;
-			}
-			netif_dbg(tp, intr, dev, "fifo copy in progress\n");
-			tp->xstats.early_rx++;
-			break;
-		}
-
-no_early_rx:
-		tp->fifo_copy_timeout = 0;
-
-		/* If Rx err or invalid rx_size/rx_status received
-		 * (which happens if we get lost in the ring),
-		 * Rx process gets reset, so we abort any further
-		 * Rx processing.
-		 */
-		if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) ||
-			     (rx_size < 8) ||
-			     (!(rx_status & RxStatusOK)))) {
-			rtl8139_rx_err (rx_status, dev, tp, ioaddr);
-			received = -1;
-			goto out;
-		}
-
-		/* Malloc up new buffer, compatible with net-2e. */
-		/* Omit the four octet CRC from the length. */
-
-		skb = netdev_alloc_skb_ip_align(dev, pkt_size);
-		if (likely(skb)) {
-#if RX_BUF_IDX == 3
-			wrap_copy(skb, rx_ring, ring_offset+4, pkt_size);
-#else
-			skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size);
-#endif
-			skb_put (skb, pkt_size);
-
-			skb->protocol = eth_type_trans (skb, dev);
-
-			dev->stats.rx_bytes += pkt_size;
-			dev->stats.rx_packets++;
-
-			netif_receive_skb (skb);
-		} else {
-			if (net_ratelimit())
-				netdev_warn(dev, "Memory squeeze, dropping packet\n");
-			dev->stats.rx_dropped++;
-		}
-		received++;
-
-		cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
-		RTL_W16 (RxBufPtr, (u16) (cur_rx - 16));
-
-		rtl8139_isr_ack(tp);
-	}
-
-	if (unlikely(!received || rx_size == 0xfff0))
-		rtl8139_isr_ack(tp);
-
-	netdev_dbg(dev, "Done %s(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n",
-		   __func__, cur_rx,
-		   RTL_R16(RxBufAddr), RTL_R16(RxBufPtr), RTL_R8(ChipCmd));
-
-	tp->cur_rx = cur_rx;
-
-	/*
-	 * The receive buffer should be mostly empty.
-	 * Tell NAPI to reenable the Rx irq.
-	 */
-	if (tp->fifo_copy_timeout)
-		received = budget;
-
-out:
-	return received;
-}
-
-
-static void rtl8139_weird_interrupt (struct net_device *dev,
-				     struct rtl8139_private *tp,
-				     void __iomem *ioaddr,
-				     int status, int link_changed)
-{
-	netdev_dbg(dev, "Abnormal interrupt, status %08x\n", status);
-
-	assert (dev != NULL);
-	assert (tp != NULL);
-	assert (ioaddr != NULL);
-
-	/* Update the error count. */
-	dev->stats.rx_missed_errors += RTL_R32 (RxMissed);
-	RTL_W32 (RxMissed, 0);
-
-	if ((status & RxUnderrun) && link_changed &&
-	    (tp->drv_flags & HAS_LNK_CHNG)) {
-		rtl_check_media(dev, 0);
-		status &= ~RxUnderrun;
-	}
-
-	if (status & (RxUnderrun | RxErr))
-		dev->stats.rx_errors++;
-
-	if (status & PCSTimeout)
-		dev->stats.rx_length_errors++;
-	if (status & RxUnderrun)
-		dev->stats.rx_fifo_errors++;
-	if (status & PCIErr) {
-		u16 pci_cmd_status;
-		pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status);
-		pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status);
-
-		netdev_err(dev, "PCI Bus error %04x\n", pci_cmd_status);
-	}
-}
-
-static int rtl8139_poll(struct napi_struct *napi, int budget)
-{
-	struct rtl8139_private *tp = container_of(napi, struct rtl8139_private, napi);
-	struct net_device *dev = tp->dev;
-	void __iomem *ioaddr = tp->mmio_addr;
-	int work_done;
-
-	spin_lock(&tp->rx_lock);
-	work_done = 0;
-	if (likely(RTL_R16(IntrStatus) & RxAckBits))
-		work_done += rtl8139_rx(dev, tp, budget);
-
-	if (work_done < budget) {
-		unsigned long flags;
-		/*
-		 * Order is important since data can get interrupted
-		 * again when we think we are done.
-		 */
-		spin_lock_irqsave(&tp->lock, flags);
-		__napi_complete(napi);
-		RTL_W16_F(IntrMask, rtl8139_intr_mask);
-		spin_unlock_irqrestore(&tp->lock, flags);
-	}
-	spin_unlock(&tp->rx_lock);
-
-	return work_done;
-}
-
-/* The interrupt handler does all of the Rx thread work and cleans up
-   after the Tx thread. */
-static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance)
-{
-	struct net_device *dev = (struct net_device *) dev_instance;
-	struct rtl8139_private *tp = netdev_priv(dev);
-	void __iomem *ioaddr = tp->mmio_addr;
-	u16 status, ackstat;
-	int link_changed = 0; /* avoid bogus "uninit" warning */
-	int handled = 0;
-
-	spin_lock (&tp->lock);
-	status = RTL_R16 (IntrStatus);
-
-	/* shared irq? */
-	if (unlikely((status & rtl8139_intr_mask) == 0))
-		goto out;
-
-	handled = 1;
-
-	/* h/w no longer present (hotplug?) or major error, bail */
-	if (unlikely(status == 0xFFFF))
-		goto out;
-
-	/* close possible race's with dev_close */
-	if (unlikely(!netif_running(dev))) {
-		RTL_W16 (IntrMask, 0);
-		goto out;
-	}
-
-	/* Acknowledge all of the current interrupt sources ASAP, but
-	   an first get an additional status bit from CSCR. */
-	if (unlikely(status & RxUnderrun))
-		link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit;
-
-	ackstat = status & ~(RxAckBits | TxErr);
-	if (ackstat)
-		RTL_W16 (IntrStatus, ackstat);
-
-	/* Receive packets are processed by poll routine.
-	   If not running start it now. */
-	if (status & RxAckBits){
-		if (napi_schedule_prep(&tp->napi)) {
-			RTL_W16_F (IntrMask, rtl8139_norx_intr_mask);
-			__napi_schedule(&tp->napi);
-		}
-	}
-
-	/* Check uncommon events with one test. */
-	if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr)))
-		rtl8139_weird_interrupt (dev, tp, ioaddr,
-					 status, link_changed);
-
-	if (status & (TxOK | TxErr)) {
-		rtl8139_tx_interrupt (dev, tp, ioaddr);
-		if (status & TxErr)
-			RTL_W16 (IntrStatus, TxErr);
-	}
- out:
-	spin_unlock (&tp->lock);
-
-	netdev_dbg(dev, "exiting interrupt, intr_status=%#4.4x\n",
-		   RTL_R16(IntrStatus));
-	return IRQ_RETVAL(handled);
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Polling receive - used by netconsole and other diagnostic tools
- * to allow network i/o with interrupts disabled.
- */
-static void rtl8139_poll_controller(struct net_device *dev)
-{
-	disable_irq(dev->irq);
-	rtl8139_interrupt(dev->irq, dev);
-	enable_irq(dev->irq);
-}
-#endif
-
-static int rtl8139_set_mac_address(struct net_device *dev, void *p)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	void __iomem *ioaddr = tp->mmio_addr;
-	struct sockaddr *addr = p;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
-	spin_lock_irq(&tp->lock);
-
-	RTL_W8_F(Cfg9346, Cfg9346_Unlock);
-	RTL_W32_F(MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0)));
-	RTL_W32_F(MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4)));
-	RTL_W8_F(Cfg9346, Cfg9346_Lock);
-
-	spin_unlock_irq(&tp->lock);
-
-	return 0;
-}
-
-static int rtl8139_close (struct net_device *dev)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	void __iomem *ioaddr = tp->mmio_addr;
-	unsigned long flags;
-
-	netif_stop_queue(dev);
-	napi_disable(&tp->napi);
-
-	netif_dbg(tp, ifdown, dev, "Shutting down ethercard, status was 0x%04x\n",
-		  RTL_R16(IntrStatus));
-
-	spin_lock_irqsave (&tp->lock, flags);
-
-	/* Stop the chip's Tx and Rx DMA processes. */
-	RTL_W8 (ChipCmd, 0);
-
-	/* Disable interrupts by clearing the interrupt mask. */
-	RTL_W16 (IntrMask, 0);
-
-	/* Update the error counts. */
-	dev->stats.rx_missed_errors += RTL_R32 (RxMissed);
-	RTL_W32 (RxMissed, 0);
-
-	spin_unlock_irqrestore (&tp->lock, flags);
-
-	free_irq (dev->irq, dev);
-
-	rtl8139_tx_clear (tp);
-
-	dma_free_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN,
-			  tp->rx_ring, tp->rx_ring_dma);
-	dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN,
-			  tp->tx_bufs, tp->tx_bufs_dma);
-	tp->rx_ring = NULL;
-	tp->tx_bufs = NULL;
-
-	/* Green! Put the chip in low-power mode. */
-	RTL_W8 (Cfg9346, Cfg9346_Unlock);
-
-	if (rtl_chip_info[tp->chipset].flags & HasHltClk)
-		RTL_W8 (HltClk, 'H');	/* 'R' would leave the clock running. */
-
-	return 0;
-}
-
-
-/* Get the ethtool Wake-on-LAN settings.  Assumes that wol points to
-   kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and
-   other threads or interrupts aren't messing with the 8139.  */
-static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	void __iomem *ioaddr = tp->mmio_addr;
-
-	spin_lock_irq(&tp->lock);
-	if (rtl_chip_info[tp->chipset].flags & HasLWake) {
-		u8 cfg3 = RTL_R8 (Config3);
-		u8 cfg5 = RTL_R8 (Config5);
-
-		wol->supported = WAKE_PHY | WAKE_MAGIC
-			| WAKE_UCAST | WAKE_MCAST | WAKE_BCAST;
-
-		wol->wolopts = 0;
-		if (cfg3 & Cfg3_LinkUp)
-			wol->wolopts |= WAKE_PHY;
-		if (cfg3 & Cfg3_Magic)
-			wol->wolopts |= WAKE_MAGIC;
-		/* (KON)FIXME: See how netdev_set_wol() handles the
-		   following constants.  */
-		if (cfg5 & Cfg5_UWF)
-			wol->wolopts |= WAKE_UCAST;
-		if (cfg5 & Cfg5_MWF)
-			wol->wolopts |= WAKE_MCAST;
-		if (cfg5 & Cfg5_BWF)
-			wol->wolopts |= WAKE_BCAST;
-	}
-	spin_unlock_irq(&tp->lock);
-}
-
-
-/* Set the ethtool Wake-on-LAN settings.  Return 0 or -errno.  Assumes
-   that wol points to kernel memory and other threads or interrupts
-   aren't messing with the 8139.  */
-static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	void __iomem *ioaddr = tp->mmio_addr;
-	u32 support;
-	u8 cfg3, cfg5;
-
-	support = ((rtl_chip_info[tp->chipset].flags & HasLWake)
-		   ? (WAKE_PHY | WAKE_MAGIC
-		      | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST)
-		   : 0);
-	if (wol->wolopts & ~support)
-		return -EINVAL;
-
-	spin_lock_irq(&tp->lock);
-	cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic);
-	if (wol->wolopts & WAKE_PHY)
-		cfg3 |= Cfg3_LinkUp;
-	if (wol->wolopts & WAKE_MAGIC)
-		cfg3 |= Cfg3_Magic;
-	RTL_W8 (Cfg9346, Cfg9346_Unlock);
-	RTL_W8 (Config3, cfg3);
-	RTL_W8 (Cfg9346, Cfg9346_Lock);
-
-	cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF);
-	/* (KON)FIXME: These are untested.  We may have to set the
-	   CRC0, Wakeup0 and LSBCRC0 registers too, but I have no
-	   documentation.  */
-	if (wol->wolopts & WAKE_UCAST)
-		cfg5 |= Cfg5_UWF;
-	if (wol->wolopts & WAKE_MCAST)
-		cfg5 |= Cfg5_MWF;
-	if (wol->wolopts & WAKE_BCAST)
-		cfg5 |= Cfg5_BWF;
-	RTL_W8 (Config5, cfg5);	/* need not unlock via Cfg9346 */
-	spin_unlock_irq(&tp->lock);
-
-	return 0;
-}
-
-static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-	strcpy(info->bus_info, pci_name(tp->pci_dev));
-	info->regdump_len = tp->regs_len;
-}
-
-static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	spin_lock_irq(&tp->lock);
-	mii_ethtool_gset(&tp->mii, cmd);
-	spin_unlock_irq(&tp->lock);
-	return 0;
-}
-
-static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	int rc;
-	spin_lock_irq(&tp->lock);
-	rc = mii_ethtool_sset(&tp->mii, cmd);
-	spin_unlock_irq(&tp->lock);
-	return rc;
-}
-
-static int rtl8139_nway_reset(struct net_device *dev)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	return mii_nway_restart(&tp->mii);
-}
-
-static u32 rtl8139_get_link(struct net_device *dev)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	return mii_link_ok(&tp->mii);
-}
-
-static u32 rtl8139_get_msglevel(struct net_device *dev)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	return tp->msg_enable;
-}
-
-static void rtl8139_set_msglevel(struct net_device *dev, u32 datum)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	tp->msg_enable = datum;
-}
-
-static int rtl8139_get_regs_len(struct net_device *dev)
-{
-	struct rtl8139_private *tp;
-	/* TODO: we are too slack to do reg dumping for pio, for now */
-	if (use_io)
-		return 0;
-	tp = netdev_priv(dev);
-	return tp->regs_len;
-}
-
-static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf)
-{
-	struct rtl8139_private *tp;
-
-	/* TODO: we are too slack to do reg dumping for pio, for now */
-	if (use_io)
-		return;
-	tp = netdev_priv(dev);
-
-	regs->version = RTL_REGS_VER;
-
-	spin_lock_irq(&tp->lock);
-	memcpy_fromio(regbuf, tp->mmio_addr, regs->len);
-	spin_unlock_irq(&tp->lock);
-}
-
-static int rtl8139_get_sset_count(struct net_device *dev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		return RTL_NUM_STATS;
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-
-	data[0] = tp->xstats.early_rx;
-	data[1] = tp->xstats.tx_buf_mapped;
-	data[2] = tp->xstats.tx_timeouts;
-	data[3] = tp->xstats.rx_lost_in_ring;
-}
-
-static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data)
-{
-	memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys));
-}
-
-static const struct ethtool_ops rtl8139_ethtool_ops = {
-	.get_drvinfo		= rtl8139_get_drvinfo,
-	.get_settings		= rtl8139_get_settings,
-	.set_settings		= rtl8139_set_settings,
-	.get_regs_len		= rtl8139_get_regs_len,
-	.get_regs		= rtl8139_get_regs,
-	.nway_reset		= rtl8139_nway_reset,
-	.get_link		= rtl8139_get_link,
-	.get_msglevel		= rtl8139_get_msglevel,
-	.set_msglevel		= rtl8139_set_msglevel,
-	.get_wol		= rtl8139_get_wol,
-	.set_wol		= rtl8139_set_wol,
-	.get_strings		= rtl8139_get_strings,
-	.get_sset_count		= rtl8139_get_sset_count,
-	.get_ethtool_stats	= rtl8139_get_ethtool_stats,
-};
-
-static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	int rc;
-
-	if (!netif_running(dev))
-		return -EINVAL;
-
-	spin_lock_irq(&tp->lock);
-	rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL);
-	spin_unlock_irq(&tp->lock);
-
-	return rc;
-}
-
-
-static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	void __iomem *ioaddr = tp->mmio_addr;
-	unsigned long flags;
-
-	if (netif_running(dev)) {
-		spin_lock_irqsave (&tp->lock, flags);
-		dev->stats.rx_missed_errors += RTL_R32 (RxMissed);
-		RTL_W32 (RxMissed, 0);
-		spin_unlock_irqrestore (&tp->lock, flags);
-	}
-
-	return &dev->stats;
-}
-
-/* Set or clear the multicast filter for this adaptor.
-   This routine is not state sensitive and need not be SMP locked. */
-
-static void __set_rx_mode (struct net_device *dev)
-{
-	struct rtl8139_private *tp = netdev_priv(dev);
-	void __iomem *ioaddr = tp->mmio_addr;
-	u32 mc_filter[2];	/* Multicast hash filter */
-	int rx_mode;
-	u32 tmp;
-
-	netdev_dbg(dev, "rtl8139_set_rx_mode(%04x) done -- Rx config %08x\n",
-		   dev->flags, RTL_R32(RxConfig));
-
-	/* Note: do not reorder, GCC is clever about common statements. */
-	if (dev->flags & IFF_PROMISC) {
-		rx_mode =
-		    AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
-		    AcceptAllPhys;
-		mc_filter[1] = mc_filter[0] = 0xffffffff;
-	} else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
-		   (dev->flags & IFF_ALLMULTI)) {
-		/* Too many to filter perfectly -- accept all multicasts. */
-		rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
-		mc_filter[1] = mc_filter[0] = 0xffffffff;
-	} else {
-		struct netdev_hw_addr *ha;
-		rx_mode = AcceptBroadcast | AcceptMyPhys;
-		mc_filter[1] = mc_filter[0] = 0;
-		netdev_for_each_mc_addr(ha, dev) {
-			int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
-
-			mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
-			rx_mode |= AcceptMulticast;
-		}
-	}
-
-	/* We can safely update without stopping the chip. */
-	tmp = rtl8139_rx_config | rx_mode;
-	if (tp->rx_config != tmp) {
-		RTL_W32_F (RxConfig, tmp);
-		tp->rx_config = tmp;
-	}
-	RTL_W32_F (MAR0 + 0, mc_filter[0]);
-	RTL_W32_F (MAR0 + 4, mc_filter[1]);
-}
-
-static void rtl8139_set_rx_mode (struct net_device *dev)
-{
-	unsigned long flags;
-	struct rtl8139_private *tp = netdev_priv(dev);
-
-	spin_lock_irqsave (&tp->lock, flags);
-	__set_rx_mode(dev);
-	spin_unlock_irqrestore (&tp->lock, flags);
-}
-
-#ifdef CONFIG_PM
-
-static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *dev = pci_get_drvdata (pdev);
-	struct rtl8139_private *tp = netdev_priv(dev);
-	void __iomem *ioaddr = tp->mmio_addr;
-	unsigned long flags;
-
-	pci_save_state (pdev);
-
-	if (!netif_running (dev))
-		return 0;
-
-	netif_device_detach (dev);
-
-	spin_lock_irqsave (&tp->lock, flags);
-
-	/* Disable interrupts, stop Tx and Rx. */
-	RTL_W16 (IntrMask, 0);
-	RTL_W8 (ChipCmd, 0);
-
-	/* Update the error counts. */
-	dev->stats.rx_missed_errors += RTL_R32 (RxMissed);
-	RTL_W32 (RxMissed, 0);
-
-	spin_unlock_irqrestore (&tp->lock, flags);
-
-	pci_set_power_state (pdev, PCI_D3hot);
-
-	return 0;
-}
-
-
-static int rtl8139_resume (struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata (pdev);
-
-	pci_restore_state (pdev);
-	if (!netif_running (dev))
-		return 0;
-	pci_set_power_state (pdev, PCI_D0);
-	rtl8139_init_ring (dev);
-	rtl8139_hw_start (dev);
-	netif_device_attach (dev);
-	return 0;
-}
-
-#endif /* CONFIG_PM */
-
-
-static struct pci_driver rtl8139_pci_driver = {
-	.name		= DRV_NAME,
-	.id_table	= rtl8139_pci_tbl,
-	.probe		= rtl8139_init_one,
-	.remove		= __devexit_p(rtl8139_remove_one),
-#ifdef CONFIG_PM
-	.suspend	= rtl8139_suspend,
-	.resume		= rtl8139_resume,
-#endif /* CONFIG_PM */
-};
-
-
-static int __init rtl8139_init_module (void)
-{
-	/* when we're a module, we always print a version message,
-	 * even if no 8139 board is found.
-	 */
-#ifdef MODULE
-	pr_info(RTL8139_DRIVER_NAME "\n");
-#endif
-
-	return pci_register_driver(&rtl8139_pci_driver);
-}
-
-
-static void __exit rtl8139_cleanup_module (void)
-{
-	pci_unregister_driver (&rtl8139_pci_driver);
-}
-
-
-module_init(rtl8139_init_module);
-module_exit(rtl8139_cleanup_module);
diff -druN linux-libre-3.1-gnu/drivers/net/82596.c linux-libre-3.2-gnu/drivers/net/82596.c
--- linux-libre-3.1-gnu/drivers/net/82596.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/82596.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1632 +0,0 @@
-/* 82596.c: A generic 82596 ethernet driver for linux. */
-/*
-   Based on Apricot.c
-   Written 1994 by Mark Evans.
-   This driver is for the Apricot 82596 bus-master interface
-
-   Modularised 12/94 Mark Evans
-
-
-   Modified to support the 82596 ethernet chips on 680x0 VME boards.
-   by Richard Hirst <richard@sleepie.demon.co.uk>
-   Renamed to be 82596.c
-
-   980825:  Changed to receive directly in to sk_buffs which are
-   allocated at open() time.  Eliminates copy on incoming frames
-   (small ones are still copied).  Shared data now held in a
-   non-cached page, so we can run on 68060 in copyback mode.
-
-   TBD:
-   * look at deferring rx frames rather than discarding (as per tulip)
-   * handle tx ring full as per tulip
-   * performance test to tune rx_copybreak
-
-   Most of my modifications relate to the braindead big-endian
-   implementation by Intel.  When the i596 is operating in
-   'big-endian' mode, it thinks a 32 bit value of 0x12345678
-   should be stored as 0x56781234.  This is a real pain, when
-   you have linked lists which are shared by the 680x0 and the
-   i596.
-
-   Driver skeleton
-   Written 1993 by Donald Becker.
-   Copyright 1993 United States Government as represented by the Director,
-   National Security Agency. This software may only be used and distributed
-   according to the terms of the GNU General Public License as modified by SRC,
-   incorporated herein by reference.
-
-   The author may be reached as becker@scyld.com, or C/O
-   Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
-
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/gfp.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/pgtable.h>
-#include <asm/cacheflush.h>
-
-static char version[] __initdata =
-	"82596.c $Revision: 1.5 $\n";
-
-#define DRV_NAME	"82596"
-
-/* DEBUG flags
- */
-
-#define DEB_INIT	0x0001
-#define DEB_PROBE	0x0002
-#define DEB_SERIOUS	0x0004
-#define DEB_ERRORS	0x0008
-#define DEB_MULTI	0x0010
-#define DEB_TDR		0x0020
-#define DEB_OPEN	0x0040
-#define DEB_RESET	0x0080
-#define DEB_ADDCMD	0x0100
-#define DEB_STATUS	0x0200
-#define DEB_STARTTX	0x0400
-#define DEB_RXADDR	0x0800
-#define DEB_TXADDR	0x1000
-#define DEB_RXFRAME	0x2000
-#define DEB_INTS	0x4000
-#define DEB_STRUCT	0x8000
-#define DEB_ANY		0xffff
-
-
-#define DEB(x,y)	if (i596_debug & (x)) y
-
-
-#if defined(CONFIG_MVME16x_NET) || defined(CONFIG_MVME16x_NET_MODULE)
-#define ENABLE_MVME16x_NET
-#endif
-#if defined(CONFIG_BVME6000_NET) || defined(CONFIG_BVME6000_NET_MODULE)
-#define ENABLE_BVME6000_NET
-#endif
-#if defined(CONFIG_APRICOT) || defined(CONFIG_APRICOT_MODULE)
-#define ENABLE_APRICOT
-#endif
-
-#ifdef ENABLE_MVME16x_NET
-#include <asm/mvme16xhw.h>
-#endif
-#ifdef ENABLE_BVME6000_NET
-#include <asm/bvme6000hw.h>
-#endif
-
-/*
- * Define various macros for Channel Attention, word swapping etc., dependent
- * on architecture.  MVME and BVME are 680x0 based, otherwise it is Intel.
- */
-
-#ifdef __mc68000__
-#define WSWAPrfd(x)  ((struct i596_rfd *) (((u32)(x)<<16) | ((((u32)(x)))>>16)))
-#define WSWAPrbd(x)  ((struct i596_rbd *) (((u32)(x)<<16) | ((((u32)(x)))>>16)))
-#define WSWAPiscp(x) ((struct i596_iscp *)(((u32)(x)<<16) | ((((u32)(x)))>>16)))
-#define WSWAPscb(x)  ((struct i596_scb *) (((u32)(x)<<16) | ((((u32)(x)))>>16)))
-#define WSWAPcmd(x)  ((struct i596_cmd *) (((u32)(x)<<16) | ((((u32)(x)))>>16)))
-#define WSWAPtbd(x)  ((struct i596_tbd *) (((u32)(x)<<16) | ((((u32)(x)))>>16)))
-#define WSWAPchar(x) ((char *)            (((u32)(x)<<16) | ((((u32)(x)))>>16)))
-#define ISCP_BUSY	0x00010000
-#define MACH_IS_APRICOT	0
-#else
-#define WSWAPrfd(x)     ((struct i596_rfd *)((long)x))
-#define WSWAPrbd(x)     ((struct i596_rbd *)((long)x))
-#define WSWAPiscp(x)    ((struct i596_iscp *)((long)x))
-#define WSWAPscb(x)     ((struct i596_scb *)((long)x))
-#define WSWAPcmd(x)     ((struct i596_cmd *)((long)x))
-#define WSWAPtbd(x)     ((struct i596_tbd *)((long)x))
-#define WSWAPchar(x)    ((char *)((long)x))
-#define ISCP_BUSY	0x0001
-#define MACH_IS_APRICOT	1
-#endif
-
-/*
- * The MPU_PORT command allows direct access to the 82596. With PORT access
- * the following commands are available (p5-18). The 32-bit port command
- * must be word-swapped with the most significant word written first.
- * This only applies to VME boards.
- */
-#define PORT_RESET		0x00	/* reset 82596 */
-#define PORT_SELFTEST		0x01	/* selftest */
-#define PORT_ALTSCP		0x02	/* alternate SCB address */
-#define PORT_ALTDUMP		0x03	/* Alternate DUMP address */
-
-static int i596_debug = (DEB_SERIOUS|DEB_PROBE);
-
-MODULE_AUTHOR("Richard Hirst");
-MODULE_DESCRIPTION("i82596 driver");
-MODULE_LICENSE("GPL");
-
-module_param(i596_debug, int, 0);
-MODULE_PARM_DESC(i596_debug, "i82596 debug mask");
-
-
-/* Copy frames shorter than rx_copybreak, otherwise pass on up in
- * a full sized sk_buff.  Value of 100 stolen from tulip.c (!alpha).
- */
-static int rx_copybreak = 100;
-
-#define PKT_BUF_SZ	1536
-#define MAX_MC_CNT	64
-
-#define I596_TOTAL_SIZE 17
-
-#define I596_NULL ((void *)0xffffffff)
-
-#define CMD_EOL		0x8000	/* The last command of the list, stop. */
-#define CMD_SUSP	0x4000	/* Suspend after doing cmd. */
-#define CMD_INTR	0x2000	/* Interrupt after doing cmd. */
-
-#define CMD_FLEX	0x0008	/* Enable flexible memory model */
-
-enum commands {
-	CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
-	CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7
-};
-
-#define STAT_C		0x8000	/* Set to 0 after execution */
-#define STAT_B		0x4000	/* Command being executed */
-#define STAT_OK		0x2000	/* Command executed ok */
-#define STAT_A		0x1000	/* Command aborted */
-
-#define	 CUC_START	0x0100
-#define	 CUC_RESUME	0x0200
-#define	 CUC_SUSPEND    0x0300
-#define	 CUC_ABORT	0x0400
-#define	 RX_START	0x0010
-#define	 RX_RESUME	0x0020
-#define	 RX_SUSPEND	0x0030
-#define	 RX_ABORT	0x0040
-
-#define TX_TIMEOUT	(HZ/20)
-
-
-struct i596_reg {
-	unsigned short porthi;
-	unsigned short portlo;
-	unsigned long ca;
-};
-
-#define EOF		0x8000
-#define SIZE_MASK	0x3fff
-
-struct i596_tbd {
-	unsigned short size;
-	unsigned short pad;
-	struct i596_tbd *next;
-	char *data;
-};
-
-/* The command structure has two 'next' pointers; v_next is the address of
- * the next command as seen by the CPU, b_next is the address of the next
- * command as seen by the 82596.  The b_next pointer, as used by the 82596
- * always references the status field of the next command, rather than the
- * v_next field, because the 82596 is unaware of v_next.  It may seem more
- * logical to put v_next at the end of the structure, but we cannot do that
- * because the 82596 expects other fields to be there, depending on command
- * type.
- */
-
-struct i596_cmd {
-	struct i596_cmd *v_next;	/* Address from CPUs viewpoint */
-	unsigned short status;
-	unsigned short command;
-	struct i596_cmd *b_next;	/* Address from i596 viewpoint */
-};
-
-struct tx_cmd {
-	struct i596_cmd cmd;
-	struct i596_tbd *tbd;
-	unsigned short size;
-	unsigned short pad;
-	struct sk_buff *skb;	/* So we can free it after tx */
-};
-
-struct tdr_cmd {
-	struct i596_cmd cmd;
-	unsigned short status;
-	unsigned short pad;
-};
-
-struct mc_cmd {
-	struct i596_cmd cmd;
-	short mc_cnt;
-	char mc_addrs[MAX_MC_CNT*6];
-};
-
-struct sa_cmd {
-	struct i596_cmd cmd;
-	char eth_addr[8];
-};
-
-struct cf_cmd {
-	struct i596_cmd cmd;
-	char i596_config[16];
-};
-
-struct i596_rfd {
-	unsigned short stat;
-	unsigned short cmd;
-	struct i596_rfd *b_next;	/* Address from i596 viewpoint */
-	struct i596_rbd *rbd;
-	unsigned short count;
-	unsigned short size;
-	struct i596_rfd *v_next;	/* Address from CPUs viewpoint */
-	struct i596_rfd *v_prev;
-};
-
-struct i596_rbd {
-    unsigned short count;
-    unsigned short zero1;
-    struct i596_rbd *b_next;
-    unsigned char *b_data;		/* Address from i596 viewpoint */
-    unsigned short size;
-    unsigned short zero2;
-    struct sk_buff *skb;
-    struct i596_rbd *v_next;
-    struct i596_rbd *b_addr;		/* This rbd addr from i596 view */
-    unsigned char *v_data;		/* Address from CPUs viewpoint */
-};
-
-#define TX_RING_SIZE 64
-#define RX_RING_SIZE 16
-
-struct i596_scb {
-	unsigned short status;
-	unsigned short command;
-	struct i596_cmd *cmd;
-	struct i596_rfd *rfd;
-	unsigned long crc_err;
-	unsigned long align_err;
-	unsigned long resource_err;
-	unsigned long over_err;
-	unsigned long rcvdt_err;
-	unsigned long short_err;
-	unsigned short t_on;
-	unsigned short t_off;
-};
-
-struct i596_iscp {
-	unsigned long stat;
-	struct i596_scb *scb;
-};
-
-struct i596_scp {
-	unsigned long sysbus;
-	unsigned long pad;
-	struct i596_iscp *iscp;
-};
-
-struct i596_private {
-	volatile struct i596_scp scp;
-	volatile struct i596_iscp iscp;
-	volatile struct i596_scb scb;
-	struct sa_cmd sa_cmd;
-	struct cf_cmd cf_cmd;
-	struct tdr_cmd tdr_cmd;
-	struct mc_cmd mc_cmd;
-	unsigned long stat;
-	int last_restart __attribute__((aligned(4)));
-	struct i596_rfd *rfd_head;
-	struct i596_rbd *rbd_head;
-	struct i596_cmd *cmd_tail;
-	struct i596_cmd *cmd_head;
-	int cmd_backlog;
-	unsigned long last_cmd;
-	struct i596_rfd rfds[RX_RING_SIZE];
-	struct i596_rbd rbds[RX_RING_SIZE];
-	struct tx_cmd tx_cmds[TX_RING_SIZE];
-	struct i596_tbd tbds[TX_RING_SIZE];
-	int next_tx_cmd;
-	spinlock_t lock;
-};
-
-static char init_setup[] =
-{
-	0x8E,			/* length, prefetch on */
-	0xC8,			/* fifo to 8, monitor off */
-#ifdef CONFIG_VME
-	0xc0,			/* don't save bad frames */
-#else
-	0x80,			/* don't save bad frames */
-#endif
-	0x2E,			/* No source address insertion, 8 byte preamble */
-	0x00,			/* priority and backoff defaults */
-	0x60,			/* interframe spacing */
-	0x00,			/* slot time LSB */
-	0xf2,			/* slot time and retries */
-	0x00,			/* promiscuous mode */
-	0x00,			/* collision detect */
-	0x40,			/* minimum frame length */
-	0xff,
-	0x00,
-	0x7f /*  *multi IA */ };
-
-static int i596_open(struct net_device *dev);
-static netdev_tx_t i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t i596_interrupt(int irq, void *dev_id);
-static int i596_close(struct net_device *dev);
-static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
-static void i596_tx_timeout (struct net_device *dev);
-static void print_eth(unsigned char *buf, char *str);
-static void set_multicast_list(struct net_device *dev);
-
-static int rx_ring_size = RX_RING_SIZE;
-static int ticks_limit = 25;
-static int max_cmd_backlog = TX_RING_SIZE-1;
-
-
-static inline void CA(struct net_device *dev)
-{
-#ifdef ENABLE_MVME16x_NET
-	if (MACH_IS_MVME16x) {
-		((struct i596_reg *) dev->base_addr)->ca = 1;
-	}
-#endif
-#ifdef ENABLE_BVME6000_NET
-	if (MACH_IS_BVME6000) {
-		volatile u32 i;
-
-		i = *(volatile u32 *) (dev->base_addr);
-	}
-#endif
-#ifdef ENABLE_APRICOT
-	if (MACH_IS_APRICOT) {
-		outw(0, (short) (dev->base_addr) + 4);
-	}
-#endif
-}
-
-
-static inline void MPU_PORT(struct net_device *dev, int c, volatile void *x)
-{
-#ifdef ENABLE_MVME16x_NET
-	if (MACH_IS_MVME16x) {
-		struct i596_reg *p = (struct i596_reg *) (dev->base_addr);
-		p->porthi = ((c) | (u32) (x)) & 0xffff;
-		p->portlo = ((c) | (u32) (x)) >> 16;
-	}
-#endif
-#ifdef ENABLE_BVME6000_NET
-	if (MACH_IS_BVME6000) {
-		u32 v = (u32) (c) | (u32) (x);
-		v = ((u32) (v) << 16) | ((u32) (v) >> 16);
-		*(volatile u32 *) dev->base_addr = v;
-		udelay(1);
-		*(volatile u32 *) dev->base_addr = v;
-	}
-#endif
-}
-
-
-static inline int wait_istat(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
-{
-	while (--delcnt && lp->iscp.stat)
-		udelay(10);
-	if (!delcnt) {
-		printk(KERN_ERR "%s: %s, status %4.4x, cmd %4.4x.\n",
-		     dev->name, str, lp->scb.status, lp->scb.command);
-		return -1;
-	}
-	else
-		return 0;
-}
-
-
-static inline int wait_cmd(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
-{
-	while (--delcnt && lp->scb.command)
-		udelay(10);
-	if (!delcnt) {
-		printk(KERN_ERR "%s: %s, status %4.4x, cmd %4.4x.\n",
-		     dev->name, str, lp->scb.status, lp->scb.command);
-		return -1;
-	}
-	else
-		return 0;
-}
-
-
-static inline int wait_cfg(struct net_device *dev, struct i596_cmd *cmd, int delcnt, char *str)
-{
-	volatile struct i596_cmd *c = cmd;
-
-	while (--delcnt && c->command)
-		udelay(10);
-	if (!delcnt) {
-		printk(KERN_ERR "%s: %s.\n", dev->name, str);
-		return -1;
-	}
-	else
-		return 0;
-}
-
-
-static void i596_display_data(struct net_device *dev)
-{
-	struct i596_private *lp = dev->ml_priv;
-	struct i596_cmd *cmd;
-	struct i596_rfd *rfd;
-	struct i596_rbd *rbd;
-
-	printk(KERN_ERR "lp and scp at %p, .sysbus = %08lx, .iscp = %p\n",
-	       &lp->scp, lp->scp.sysbus, lp->scp.iscp);
-	printk(KERN_ERR "iscp at %p, iscp.stat = %08lx, .scb = %p\n",
-	       &lp->iscp, lp->iscp.stat, lp->iscp.scb);
-	printk(KERN_ERR "scb at %p, scb.status = %04x, .command = %04x,"
-		" .cmd = %p, .rfd = %p\n",
-	       &lp->scb, lp->scb.status, lp->scb.command,
-		lp->scb.cmd, lp->scb.rfd);
-	printk(KERN_ERR "   errors: crc %lx, align %lx, resource %lx,"
-               " over %lx, rcvdt %lx, short %lx\n",
-		lp->scb.crc_err, lp->scb.align_err, lp->scb.resource_err,
-		lp->scb.over_err, lp->scb.rcvdt_err, lp->scb.short_err);
-	cmd = lp->cmd_head;
-	while (cmd != I596_NULL) {
-		printk(KERN_ERR "cmd at %p, .status = %04x, .command = %04x, .b_next = %p\n",
-		  cmd, cmd->status, cmd->command, cmd->b_next);
-		cmd = cmd->v_next;
-	}
-	rfd = lp->rfd_head;
-	printk(KERN_ERR "rfd_head = %p\n", rfd);
-	do {
-		printk(KERN_ERR "   %p .stat %04x, .cmd %04x, b_next %p, rbd %p,"
-                        " count %04x\n",
-			rfd, rfd->stat, rfd->cmd, rfd->b_next, rfd->rbd,
-			rfd->count);
-		rfd = rfd->v_next;
-	} while (rfd != lp->rfd_head);
-	rbd = lp->rbd_head;
-	printk(KERN_ERR "rbd_head = %p\n", rbd);
-	do {
-		printk(KERN_ERR "   %p .count %04x, b_next %p, b_data %p, size %04x\n",
-			rbd, rbd->count, rbd->b_next, rbd->b_data, rbd->size);
-		rbd = rbd->v_next;
-	} while (rbd != lp->rbd_head);
-}
-
-
-#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
-static irqreturn_t i596_error(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-#ifdef ENABLE_MVME16x_NET
-	if (MACH_IS_MVME16x) {
-		volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
-
-		pcc2[0x28] = 1;
-		pcc2[0x2b] = 0x1d;
-	}
-#endif
-#ifdef ENABLE_BVME6000_NET
-	if (MACH_IS_BVME6000) {
-		volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
-
-		*ethirq = 1;
-		*ethirq = 3;
-	}
-#endif
-	printk(KERN_ERR "%s: Error interrupt\n", dev->name);
-	i596_display_data(dev);
-	return IRQ_HANDLED;
-}
-#endif
-
-static inline void remove_rx_bufs(struct net_device *dev)
-{
-	struct i596_private *lp = dev->ml_priv;
-	struct i596_rbd *rbd;
-	int i;
-
-	for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
-		if (rbd->skb == NULL)
-			break;
-		dev_kfree_skb(rbd->skb);
-		rbd->skb = NULL;
-	}
-}
-
-static inline int init_rx_bufs(struct net_device *dev)
-{
-	struct i596_private *lp = dev->ml_priv;
-	int i;
-	struct i596_rfd *rfd;
-	struct i596_rbd *rbd;
-
-	/* First build the Receive Buffer Descriptor List */
-
-	for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
-		struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
-
-		if (skb == NULL) {
-			remove_rx_bufs(dev);
-			return -ENOMEM;
-		}
-
-		skb->dev = dev;
-		rbd->v_next = rbd+1;
-		rbd->b_next = WSWAPrbd(virt_to_bus(rbd+1));
-		rbd->b_addr = WSWAPrbd(virt_to_bus(rbd));
-		rbd->skb = skb;
-		rbd->v_data = skb->data;
-		rbd->b_data = WSWAPchar(virt_to_bus(skb->data));
-		rbd->size = PKT_BUF_SZ;
-#ifdef __mc68000__
-		cache_clear(virt_to_phys(skb->data), PKT_BUF_SZ);
-#endif
-	}
-	lp->rbd_head = lp->rbds;
-	rbd = lp->rbds + rx_ring_size - 1;
-	rbd->v_next = lp->rbds;
-	rbd->b_next = WSWAPrbd(virt_to_bus(lp->rbds));
-
-	/* Now build the Receive Frame Descriptor List */
-
-	for (i = 0, rfd = lp->rfds; i < rx_ring_size; i++, rfd++) {
-		rfd->rbd = I596_NULL;
-		rfd->v_next = rfd+1;
-		rfd->v_prev = rfd-1;
-		rfd->b_next = WSWAPrfd(virt_to_bus(rfd+1));
-		rfd->cmd = CMD_FLEX;
-	}
-	lp->rfd_head = lp->rfds;
-	lp->scb.rfd = WSWAPrfd(virt_to_bus(lp->rfds));
-	rfd = lp->rfds;
-	rfd->rbd = lp->rbd_head;
-	rfd->v_prev = lp->rfds + rx_ring_size - 1;
-	rfd = lp->rfds + rx_ring_size - 1;
-	rfd->v_next = lp->rfds;
-	rfd->b_next = WSWAPrfd(virt_to_bus(lp->rfds));
-	rfd->cmd = CMD_EOL|CMD_FLEX;
-
-	return 0;
-}
-
-
-static void rebuild_rx_bufs(struct net_device *dev)
-{
-	struct i596_private *lp = dev->ml_priv;
-	int i;
-
-	/* Ensure rx frame/buffer descriptors are tidy */
-
-	for (i = 0; i < rx_ring_size; i++) {
-		lp->rfds[i].rbd = I596_NULL;
-		lp->rfds[i].cmd = CMD_FLEX;
-	}
-	lp->rfds[rx_ring_size-1].cmd = CMD_EOL|CMD_FLEX;
-	lp->rfd_head = lp->rfds;
-	lp->scb.rfd = WSWAPrfd(virt_to_bus(lp->rfds));
-	lp->rbd_head = lp->rbds;
-	lp->rfds[0].rbd = WSWAPrbd(virt_to_bus(lp->rbds));
-}
-
-
-static int init_i596_mem(struct net_device *dev)
-{
-	struct i596_private *lp = dev->ml_priv;
-#if !defined(ENABLE_MVME16x_NET) && !defined(ENABLE_BVME6000_NET) || defined(ENABLE_APRICOT)
-	short ioaddr = dev->base_addr;
-#endif
-	unsigned long flags;
-
-	MPU_PORT(dev, PORT_RESET, NULL);
-
-	udelay(100);		/* Wait 100us - seems to help */
-
-#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
-#ifdef ENABLE_MVME16x_NET
-	if (MACH_IS_MVME16x) {
-		volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
-
-		/* Disable all ints for now */
-		pcc2[0x28] = 1;
-		pcc2[0x2a] = 0x48;
-		/* Following disables snooping.  Snooping is not required
-		 * as we make appropriate use of non-cached pages for
-		 * shared data, and cache_push/cache_clear.
-		 */
-		pcc2[0x2b] = 0x08;
-	}
-#endif
-#ifdef ENABLE_BVME6000_NET
-	if (MACH_IS_BVME6000) {
-		volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
-
-		*ethirq = 1;
-	}
-#endif
-
-	/* change the scp address */
-
-	MPU_PORT(dev, PORT_ALTSCP, (void *)virt_to_bus((void *)&lp->scp));
-
-#elif defined(ENABLE_APRICOT)
-
-	{
-		u32 scp = virt_to_bus(&lp->scp);
-
-		/* change the scp address */
-		outw(0, ioaddr);
-		outw(0, ioaddr);
-		outb(4, ioaddr + 0xf);
-		outw(scp | 2, ioaddr);
-		outw(scp >> 16, ioaddr);
-	}
-#endif
-
-	lp->last_cmd = jiffies;
-
-#ifdef ENABLE_MVME16x_NET
-	if (MACH_IS_MVME16x)
-		lp->scp.sysbus = 0x00000054;
-#endif
-#ifdef ENABLE_BVME6000_NET
-	if (MACH_IS_BVME6000)
-		lp->scp.sysbus = 0x0000004c;
-#endif
-#ifdef ENABLE_APRICOT
-	if (MACH_IS_APRICOT)
-		lp->scp.sysbus = 0x00440000;
-#endif
-
-	lp->scp.iscp = WSWAPiscp(virt_to_bus((void *)&lp->iscp));
-	lp->iscp.scb = WSWAPscb(virt_to_bus((void *)&lp->scb));
-	lp->iscp.stat = ISCP_BUSY;
-	lp->cmd_backlog = 0;
-
-	lp->cmd_head = lp->scb.cmd = I596_NULL;
-
-#ifdef ENABLE_BVME6000_NET
-	if (MACH_IS_BVME6000) {
-		lp->scb.t_on  = 7 * 25;
-		lp->scb.t_off = 1 * 25;
-	}
-#endif
-
-	DEB(DEB_INIT,printk(KERN_DEBUG "%s: starting i82596.\n", dev->name));
-
-#if defined(ENABLE_APRICOT)
-	(void) inb(ioaddr + 0x10);
-	outb(4, ioaddr + 0xf);
-#endif
-	CA(dev);
-
-	if (wait_istat(dev,lp,1000,"initialization timed out"))
-		goto failed;
-	DEB(DEB_INIT,printk(KERN_DEBUG "%s: i82596 initialization successful\n", dev->name));
-
-	/* Ensure rx frame/buffer descriptors are tidy */
-	rebuild_rx_bufs(dev);
-	lp->scb.command = 0;
-
-#ifdef ENABLE_MVME16x_NET
-	if (MACH_IS_MVME16x) {
-		volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
-
-		/* Enable ints, etc. now */
-		pcc2[0x2a] = 0x55;	/* Edge sensitive */
-		pcc2[0x2b] = 0x15;
-	}
-#endif
-#ifdef ENABLE_BVME6000_NET
-	if (MACH_IS_BVME6000) {
-		volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
-
-		*ethirq = 3;
-	}
-#endif
-
-
-	DEB(DEB_INIT,printk(KERN_DEBUG "%s: queuing CmdConfigure\n", dev->name));
-	memcpy(lp->cf_cmd.i596_config, init_setup, 14);
-	lp->cf_cmd.cmd.command = CmdConfigure;
-	i596_add_cmd(dev, &lp->cf_cmd.cmd);
-
-	DEB(DEB_INIT,printk(KERN_DEBUG "%s: queuing CmdSASetup\n", dev->name));
-	memcpy(lp->sa_cmd.eth_addr, dev->dev_addr, 6);
-	lp->sa_cmd.cmd.command = CmdSASetup;
-	i596_add_cmd(dev, &lp->sa_cmd.cmd);
-
-	DEB(DEB_INIT,printk(KERN_DEBUG "%s: queuing CmdTDR\n", dev->name));
-	lp->tdr_cmd.cmd.command = CmdTDR;
-	i596_add_cmd(dev, &lp->tdr_cmd.cmd);
-
-	spin_lock_irqsave (&lp->lock, flags);
-
-	if (wait_cmd(dev,lp,1000,"timed out waiting to issue RX_START")) {
-		spin_unlock_irqrestore (&lp->lock, flags);
-		goto failed;
-	}
-	DEB(DEB_INIT,printk(KERN_DEBUG "%s: Issuing RX_START\n", dev->name));
-	lp->scb.command = RX_START;
-	CA(dev);
-
-	spin_unlock_irqrestore (&lp->lock, flags);
-
-	if (wait_cmd(dev,lp,1000,"RX_START not processed"))
-		goto failed;
-	DEB(DEB_INIT,printk(KERN_DEBUG "%s: Receive unit started OK\n", dev->name));
-	return 0;
-
-failed:
-	printk(KERN_CRIT "%s: Failed to initialise 82596\n", dev->name);
-	MPU_PORT(dev, PORT_RESET, NULL);
-	return -1;
-}
-
-static inline int i596_rx(struct net_device *dev)
-{
-	struct i596_private *lp = dev->ml_priv;
-	struct i596_rfd *rfd;
-	struct i596_rbd *rbd;
-	int frames = 0;
-
-	DEB(DEB_RXFRAME,printk(KERN_DEBUG "i596_rx(), rfd_head %p, rbd_head %p\n",
-			lp->rfd_head, lp->rbd_head));
-
-	rfd = lp->rfd_head;		/* Ref next frame to check */
-
-	while ((rfd->stat) & STAT_C) {	/* Loop while complete frames */
-		if (rfd->rbd == I596_NULL)
-			rbd = I596_NULL;
-		else if (rfd->rbd == lp->rbd_head->b_addr)
-			rbd = lp->rbd_head;
-		else {
-			printk(KERN_CRIT "%s: rbd chain broken!\n", dev->name);
-			/* XXX Now what? */
-			rbd = I596_NULL;
-		}
-		DEB(DEB_RXFRAME, printk(KERN_DEBUG "  rfd %p, rfd.rbd %p, rfd.stat %04x\n",
-			rfd, rfd->rbd, rfd->stat));
-
-		if (rbd != I596_NULL && ((rfd->stat) & STAT_OK)) {
-			/* a good frame */
-			int pkt_len = rbd->count & 0x3fff;
-			struct sk_buff *skb = rbd->skb;
-			int rx_in_place = 0;
-
-			DEB(DEB_RXADDR,print_eth(rbd->v_data, "received"));
-			frames++;
-
-			/* Check if the packet is long enough to just accept
-			 * without copying to a properly sized skbuff.
-			 */
-
-			if (pkt_len > rx_copybreak) {
-				struct sk_buff *newskb;
-
-				/* Get fresh skbuff to replace filled one. */
-				newskb = dev_alloc_skb(PKT_BUF_SZ);
-				if (newskb == NULL) {
-					skb = NULL;	/* drop pkt */
-					goto memory_squeeze;
-				}
-				/* Pass up the skb already on the Rx ring. */
-				skb_put(skb, pkt_len);
-				rx_in_place = 1;
-				rbd->skb = newskb;
-				newskb->dev = dev;
-				rbd->v_data = newskb->data;
-				rbd->b_data = WSWAPchar(virt_to_bus(newskb->data));
-#ifdef __mc68000__
-				cache_clear(virt_to_phys(newskb->data), PKT_BUF_SZ);
-#endif
-			}
-			else
-				skb = dev_alloc_skb(pkt_len + 2);
-memory_squeeze:
-			if (skb == NULL) {
-				/* XXX tulip.c can defer packets here!! */
-				printk(KERN_WARNING "%s: i596_rx Memory squeeze, dropping packet.\n", dev->name);
-				dev->stats.rx_dropped++;
-			}
-			else {
-				if (!rx_in_place) {
-					/* 16 byte align the data fields */
-					skb_reserve(skb, 2);
-					memcpy(skb_put(skb,pkt_len), rbd->v_data, pkt_len);
-				}
-				skb->protocol=eth_type_trans(skb,dev);
-				skb->len = pkt_len;
-#ifdef __mc68000__
-				cache_clear(virt_to_phys(rbd->skb->data),
-						pkt_len);
-#endif
-				netif_rx(skb);
-				dev->stats.rx_packets++;
-				dev->stats.rx_bytes+=pkt_len;
-			}
-		}
-		else {
-			DEB(DEB_ERRORS, printk(KERN_DEBUG "%s: Error, rfd.stat = 0x%04x\n",
-					dev->name, rfd->stat));
-			dev->stats.rx_errors++;
-			if ((rfd->stat) & 0x0001)
-				dev->stats.collisions++;
-			if ((rfd->stat) & 0x0080)
-				dev->stats.rx_length_errors++;
-			if ((rfd->stat) & 0x0100)
-				dev->stats.rx_over_errors++;
-			if ((rfd->stat) & 0x0200)
-				dev->stats.rx_fifo_errors++;
-			if ((rfd->stat) & 0x0400)
-				dev->stats.rx_frame_errors++;
-			if ((rfd->stat) & 0x0800)
-				dev->stats.rx_crc_errors++;
-			if ((rfd->stat) & 0x1000)
-				dev->stats.rx_length_errors++;
-		}
-
-		/* Clear the buffer descriptor count and EOF + F flags */
-
-		if (rbd != I596_NULL && (rbd->count & 0x4000)) {
-			rbd->count = 0;
-			lp->rbd_head = rbd->v_next;
-		}
-
-		/* Tidy the frame descriptor, marking it as end of list */
-
-		rfd->rbd = I596_NULL;
-		rfd->stat = 0;
-		rfd->cmd = CMD_EOL|CMD_FLEX;
-		rfd->count = 0;
-
-		/* Remove end-of-list from old end descriptor */
-
-		rfd->v_prev->cmd = CMD_FLEX;
-
-		/* Update record of next frame descriptor to process */
-
-		lp->scb.rfd = rfd->b_next;
-		lp->rfd_head = rfd->v_next;
-		rfd = lp->rfd_head;
-	}
-
-	DEB(DEB_RXFRAME,printk(KERN_DEBUG "frames %d\n", frames));
-
-	return 0;
-}
-
-
-static void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
-{
-	struct i596_cmd *ptr;
-
-	while (lp->cmd_head != I596_NULL) {
-		ptr = lp->cmd_head;
-		lp->cmd_head = ptr->v_next;
-		lp->cmd_backlog--;
-
-		switch ((ptr->command) & 0x7) {
-		case CmdTx:
-			{
-				struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
-				struct sk_buff *skb = tx_cmd->skb;
-
-				dev_kfree_skb(skb);
-
-				dev->stats.tx_errors++;
-				dev->stats.tx_aborted_errors++;
-
-				ptr->v_next = ptr->b_next = I596_NULL;
-				tx_cmd->cmd.command = 0;  /* Mark as free */
-				break;
-			}
-		default:
-			ptr->v_next = ptr->b_next = I596_NULL;
-		}
-	}
-
-	wait_cmd(dev,lp,100,"i596_cleanup_cmd timed out");
-	lp->scb.cmd = I596_NULL;
-}
-
-static void i596_reset(struct net_device *dev, struct i596_private *lp,
-			int ioaddr)
-{
-	unsigned long flags;
-
-	DEB(DEB_RESET,printk(KERN_DEBUG "i596_reset\n"));
-
-	spin_lock_irqsave (&lp->lock, flags);
-
-	wait_cmd(dev,lp,100,"i596_reset timed out");
-
-	netif_stop_queue(dev);
-
-	lp->scb.command = CUC_ABORT | RX_ABORT;
-	CA(dev);
-
-	/* wait for shutdown */
-	wait_cmd(dev,lp,1000,"i596_reset 2 timed out");
-	spin_unlock_irqrestore (&lp->lock, flags);
-
-	i596_cleanup_cmd(dev,lp);
-	i596_rx(dev);
-
-	netif_start_queue(dev);
-	init_i596_mem(dev);
-}
-
-static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
-{
-	struct i596_private *lp = dev->ml_priv;
-	int ioaddr = dev->base_addr;
-	unsigned long flags;
-
-	DEB(DEB_ADDCMD,printk(KERN_DEBUG "i596_add_cmd\n"));
-
-	cmd->status = 0;
-	cmd->command |= (CMD_EOL | CMD_INTR);
-	cmd->v_next = cmd->b_next = I596_NULL;
-
-	spin_lock_irqsave (&lp->lock, flags);
-
-	if (lp->cmd_head != I596_NULL) {
-		lp->cmd_tail->v_next = cmd;
-		lp->cmd_tail->b_next = WSWAPcmd(virt_to_bus(&cmd->status));
-	} else {
-		lp->cmd_head = cmd;
-		wait_cmd(dev,lp,100,"i596_add_cmd timed out");
-		lp->scb.cmd = WSWAPcmd(virt_to_bus(&cmd->status));
-		lp->scb.command = CUC_START;
-		CA(dev);
-	}
-	lp->cmd_tail = cmd;
-	lp->cmd_backlog++;
-
-	spin_unlock_irqrestore (&lp->lock, flags);
-
-	if (lp->cmd_backlog > max_cmd_backlog) {
-		unsigned long tickssofar = jiffies - lp->last_cmd;
-
-		if (tickssofar < ticks_limit)
-			return;
-
-		printk(KERN_NOTICE "%s: command unit timed out, status resetting.\n", dev->name);
-
-		i596_reset(dev, lp, ioaddr);
-	}
-}
-
-static int i596_open(struct net_device *dev)
-{
-	int res = 0;
-
-	DEB(DEB_OPEN,printk(KERN_DEBUG "%s: i596_open() irq %d.\n", dev->name, dev->irq));
-
-	if (request_irq(dev->irq, i596_interrupt, 0, "i82596", dev)) {
-		printk(KERN_ERR "%s: IRQ %d not free\n", dev->name, dev->irq);
-		return -EAGAIN;
-	}
-#ifdef ENABLE_MVME16x_NET
-	if (MACH_IS_MVME16x) {
-		if (request_irq(0x56, i596_error, 0, "i82596_error", dev)) {
-			res = -EAGAIN;
-			goto err_irq_dev;
-		}
-	}
-#endif
-	res = init_rx_bufs(dev);
-	if (res)
-		goto err_irq_56;
-
-	netif_start_queue(dev);
-
-	if (init_i596_mem(dev)) {
-		res = -EAGAIN;
-		goto err_queue;
-	}
-
-	return 0;
-
-err_queue:
-	netif_stop_queue(dev);
-	remove_rx_bufs(dev);
-err_irq_56:
-#ifdef ENABLE_MVME16x_NET
-	free_irq(0x56, dev);
-err_irq_dev:
-#endif
-	free_irq(dev->irq, dev);
-
-	return res;
-}
-
-static void i596_tx_timeout (struct net_device *dev)
-{
-	struct i596_private *lp = dev->ml_priv;
-	int ioaddr = dev->base_addr;
-
-	/* Transmitter timeout, serious problems. */
-	DEB(DEB_ERRORS,printk(KERN_ERR "%s: transmit timed out, status resetting.\n",
-			dev->name));
-
-	dev->stats.tx_errors++;
-
-	/* Try to restart the adaptor */
-	if (lp->last_restart == dev->stats.tx_packets) {
-		DEB(DEB_ERRORS,printk(KERN_ERR "Resetting board.\n"));
-		/* Shutdown and restart */
-		i596_reset (dev, lp, ioaddr);
-	} else {
-		/* Issue a channel attention signal */
-		DEB(DEB_ERRORS,printk(KERN_ERR "Kicking board.\n"));
-		lp->scb.command = CUC_START | RX_START;
-		CA (dev);
-		lp->last_restart = dev->stats.tx_packets;
-	}
-
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	netif_wake_queue (dev);
-}
-
-static netdev_tx_t i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct i596_private *lp = dev->ml_priv;
-	struct tx_cmd *tx_cmd;
-	struct i596_tbd *tbd;
-	short length = skb->len;
-
-	DEB(DEB_STARTTX,printk(KERN_DEBUG "%s: i596_start_xmit(%x,%p) called\n",
-				dev->name, skb->len, skb->data));
-
-	if (skb->len < ETH_ZLEN) {
-		if (skb_padto(skb, ETH_ZLEN))
-			return NETDEV_TX_OK;
-		length = ETH_ZLEN;
-	}
-	netif_stop_queue(dev);
-
-	tx_cmd = lp->tx_cmds + lp->next_tx_cmd;
-	tbd = lp->tbds + lp->next_tx_cmd;
-
-	if (tx_cmd->cmd.command) {
-		printk(KERN_NOTICE "%s: xmit ring full, dropping packet.\n",
-				dev->name);
-		dev->stats.tx_dropped++;
-
-		dev_kfree_skb(skb);
-	} else {
-		if (++lp->next_tx_cmd == TX_RING_SIZE)
-			lp->next_tx_cmd = 0;
-		tx_cmd->tbd = WSWAPtbd(virt_to_bus(tbd));
-		tbd->next = I596_NULL;
-
-		tx_cmd->cmd.command = CMD_FLEX | CmdTx;
-		tx_cmd->skb = skb;
-
-		tx_cmd->pad = 0;
-		tx_cmd->size = 0;
-		tbd->pad = 0;
-		tbd->size = EOF | length;
-
-		tbd->data = WSWAPchar(virt_to_bus(skb->data));
-
-#ifdef __mc68000__
-		cache_push(virt_to_phys(skb->data), length);
-#endif
-		DEB(DEB_TXADDR,print_eth(skb->data, "tx-queued"));
-		i596_add_cmd(dev, &tx_cmd->cmd);
-
-		dev->stats.tx_packets++;
-		dev->stats.tx_bytes += length;
-	}
-
-	netif_start_queue(dev);
-
-	return NETDEV_TX_OK;
-}
-
-static void print_eth(unsigned char *add, char *str)
-{
-	printk(KERN_DEBUG "i596 0x%p, %pM --> %pM %02X%02X, %s\n",
-	       add, add + 6, add, add[12], add[13], str);
-}
-
-static int io = 0x300;
-static int irq = 10;
-
-static const struct net_device_ops i596_netdev_ops = {
-	.ndo_open 		= i596_open,
-	.ndo_stop		= i596_close,
-	.ndo_start_xmit		= i596_start_xmit,
-	.ndo_set_multicast_list = set_multicast_list,
-	.ndo_tx_timeout		= i596_tx_timeout,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-struct net_device * __init i82596_probe(int unit)
-{
-	struct net_device *dev;
-	int i;
-	struct i596_private *lp;
-	char eth_addr[8];
-	static int probed;
-	int err;
-
-	if (probed)
-		return ERR_PTR(-ENODEV);
-	probed++;
-
-	dev = alloc_etherdev(0);
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	if (unit >= 0) {
-		sprintf(dev->name, "eth%d", unit);
-		netdev_boot_setup_check(dev);
-	} else {
-		dev->base_addr = io;
-		dev->irq = irq;
-	}
-
-#ifdef ENABLE_MVME16x_NET
-	if (MACH_IS_MVME16x) {
-		if (mvme16x_config & MVME16x_CONFIG_NO_ETHERNET) {
-			printk(KERN_NOTICE "Ethernet probe disabled - chip not present\n");
-			err = -ENODEV;
-			goto out;
-		}
-		memcpy(eth_addr, (void *) 0xfffc1f2c, 6);	/* YUCK! Get addr from NOVRAM */
-		dev->base_addr = MVME_I596_BASE;
-		dev->irq = (unsigned) MVME16x_IRQ_I596;
-		goto found;
-	}
-#endif
-#ifdef ENABLE_BVME6000_NET
-	if (MACH_IS_BVME6000) {
-		volatile unsigned char *rtc = (unsigned char *) BVME_RTC_BASE;
-		unsigned char msr = rtc[3];
-		int i;
-
-		rtc[3] |= 0x80;
-		for (i = 0; i < 6; i++)
-			eth_addr[i] = rtc[i * 4 + 7];	/* Stored in RTC RAM at offset 1 */
-		rtc[3] = msr;
-		dev->base_addr = BVME_I596_BASE;
-		dev->irq = (unsigned) BVME_IRQ_I596;
-		goto found;
-	}
-#endif
-#ifdef ENABLE_APRICOT
-	{
-		int checksum = 0;
-		int ioaddr = 0x300;
-
-		/* this is easy the ethernet interface can only be at 0x300 */
-		/* first check nothing is already registered here */
-
-		if (!request_region(ioaddr, I596_TOTAL_SIZE, DRV_NAME)) {
-			printk(KERN_ERR "82596: IO address 0x%04x in use\n", ioaddr);
-			err = -EBUSY;
-			goto out;
-		}
-
-		dev->base_addr = ioaddr;
-
-		for (i = 0; i < 8; i++) {
-			eth_addr[i] = inb(ioaddr + 8 + i);
-			checksum += eth_addr[i];
-		}
-
-		/* checksum is a multiple of 0x100, got this wrong first time
-		   some machines have 0x100, some 0x200. The DOS driver doesn't
-		   even bother with the checksum.
-		   Some other boards trip the checksum.. but then appear as
-		   ether address 0. Trap these - AC */
-
-		if ((checksum % 0x100) ||
-		    (memcmp(eth_addr, "\x00\x00\x49", 3) != 0)) {
-			err = -ENODEV;
-			goto out1;
-		}
-
-		dev->irq = 10;
-		goto found;
-	}
-#endif
-	err = -ENODEV;
-	goto out;
-
-found:
-	dev->mem_start = (int)__get_free_pages(GFP_ATOMIC, 0);
-	if (!dev->mem_start) {
-		err = -ENOMEM;
-		goto out1;
-	}
-
-	DEB(DEB_PROBE,printk(KERN_INFO "%s: 82596 at %#3lx,", dev->name, dev->base_addr));
-
-	for (i = 0; i < 6; i++)
-		DEB(DEB_PROBE,printk(" %2.2X", dev->dev_addr[i] = eth_addr[i]));
-
-	DEB(DEB_PROBE,printk(" IRQ %d.\n", dev->irq));
-
-	DEB(DEB_PROBE,printk(KERN_INFO "%s", version));
-
-	/* The 82596-specific entries in the device structure. */
-	dev->netdev_ops = &i596_netdev_ops;
-	dev->watchdog_timeo = TX_TIMEOUT;
-
-	dev->ml_priv = (void *)(dev->mem_start);
-
-	lp = dev->ml_priv;
-	DEB(DEB_INIT,printk(KERN_DEBUG "%s: lp at 0x%08lx (%zd bytes), "
-			"lp->scb at 0x%08lx\n",
-			dev->name, (unsigned long)lp,
-			sizeof(struct i596_private), (unsigned long)&lp->scb));
-	memset((void *) lp, 0, sizeof(struct i596_private));
-
-#ifdef __mc68000__
-	cache_push(virt_to_phys((void *)(dev->mem_start)), 4096);
-	cache_clear(virt_to_phys((void *)(dev->mem_start)), 4096);
-	kernel_set_cachemode((void *)(dev->mem_start), 4096, IOMAP_NOCACHE_SER);
-#endif
-	lp->scb.command = 0;
-	lp->scb.cmd = I596_NULL;
-	lp->scb.rfd = I596_NULL;
-	spin_lock_init(&lp->lock);
-
-	err = register_netdev(dev);
-	if (err)
-		goto out2;
-	return dev;
-out2:
-#ifdef __mc68000__
-	/* XXX This assumes default cache mode to be IOMAP_FULL_CACHING,
-	 * XXX which may be invalid (CONFIG_060_WRITETHROUGH)
-	 */
-	kernel_set_cachemode((void *)(dev->mem_start), 4096,
-			IOMAP_FULL_CACHING);
-#endif
-	free_page ((u32)(dev->mem_start));
-out1:
-#ifdef ENABLE_APRICOT
-	release_region(dev->base_addr, I596_TOTAL_SIZE);
-#endif
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-
-static irqreturn_t i596_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct i596_private *lp;
-	short ioaddr;
-	unsigned short status, ack_cmd = 0;
-	int handled = 0;
-
-#ifdef ENABLE_BVME6000_NET
-	if (MACH_IS_BVME6000) {
-		if (*(char *) BVME_LOCAL_IRQ_STAT & BVME_ETHERR) {
-			i596_error(irq, dev_id);
-			return IRQ_HANDLED;
-		}
-	}
-#endif
-	if (dev == NULL) {
-		printk(KERN_ERR "i596_interrupt(): irq %d for unknown device.\n", irq);
-		return IRQ_NONE;
-	}
-
-	ioaddr = dev->base_addr;
-	lp = dev->ml_priv;
-
-	spin_lock (&lp->lock);
-
-	wait_cmd(dev,lp,100,"i596 interrupt, timeout");
-	status = lp->scb.status;
-
-	DEB(DEB_INTS,printk(KERN_DEBUG "%s: i596 interrupt, IRQ %d, status %4.4x.\n",
-			dev->name, irq, status));
-
-	ack_cmd = status & 0xf000;
-
-	if ((status & 0x8000) || (status & 0x2000)) {
-		struct i596_cmd *ptr;
-
-		handled = 1;
-		if ((status & 0x8000))
-			DEB(DEB_INTS,printk(KERN_DEBUG "%s: i596 interrupt completed command.\n", dev->name));
-		if ((status & 0x2000))
-			DEB(DEB_INTS,printk(KERN_DEBUG "%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700));
-
-		while ((lp->cmd_head != I596_NULL) && (lp->cmd_head->status & STAT_C)) {
-			ptr = lp->cmd_head;
-
-			DEB(DEB_STATUS,printk(KERN_DEBUG "cmd_head->status = %04x, ->command = %04x\n",
-				       lp->cmd_head->status, lp->cmd_head->command));
-			lp->cmd_head = ptr->v_next;
-			lp->cmd_backlog--;
-
-			switch ((ptr->command) & 0x7) {
-			case CmdTx:
-			    {
-				struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
-				struct sk_buff *skb = tx_cmd->skb;
-
-				if ((ptr->status) & STAT_OK) {
-					DEB(DEB_TXADDR,print_eth(skb->data, "tx-done"));
-				} else {
-					dev->stats.tx_errors++;
-					if ((ptr->status) & 0x0020)
-						dev->stats.collisions++;
-					if (!((ptr->status) & 0x0040))
-						dev->stats.tx_heartbeat_errors++;
-					if ((ptr->status) & 0x0400)
-						dev->stats.tx_carrier_errors++;
-					if ((ptr->status) & 0x0800)
-						dev->stats.collisions++;
-					if ((ptr->status) & 0x1000)
-						dev->stats.tx_aborted_errors++;
-				}
-
-				dev_kfree_skb_irq(skb);
-
-				tx_cmd->cmd.command = 0; /* Mark free */
-				break;
-			    }
-			case CmdTDR:
-			    {
-				unsigned short status = ((struct tdr_cmd *)ptr)->status;
-
-				if (status & 0x8000) {
-					DEB(DEB_TDR,printk(KERN_INFO "%s: link ok.\n", dev->name));
-				} else {
-					if (status & 0x4000)
-						printk(KERN_ERR "%s: Transceiver problem.\n", dev->name);
-					if (status & 0x2000)
-						printk(KERN_ERR "%s: Termination problem.\n", dev->name);
-					if (status & 0x1000)
-						printk(KERN_ERR "%s: Short circuit.\n", dev->name);
-
-					DEB(DEB_TDR,printk(KERN_INFO "%s: Time %d.\n", dev->name, status & 0x07ff));
-				}
-				break;
-			    }
-			case CmdConfigure:
-			case CmdMulticastList:
-				/* Zap command so set_multicast_list() knows it is free */
-				ptr->command = 0;
-				break;
-			}
-			ptr->v_next = ptr->b_next = I596_NULL;
-			lp->last_cmd = jiffies;
-		}
-
-		ptr = lp->cmd_head;
-		while ((ptr != I596_NULL) && (ptr != lp->cmd_tail)) {
-			ptr->command &= 0x1fff;
-			ptr = ptr->v_next;
-		}
-
-		if ((lp->cmd_head != I596_NULL))
-			ack_cmd |= CUC_START;
-		lp->scb.cmd = WSWAPcmd(virt_to_bus(&lp->cmd_head->status));
-	}
-	if ((status & 0x1000) || (status & 0x4000)) {
-		if ((status & 0x4000))
-			DEB(DEB_INTS,printk(KERN_DEBUG "%s: i596 interrupt received a frame.\n", dev->name));
-		i596_rx(dev);
-		/* Only RX_START if stopped - RGH 07-07-96 */
-		if (status & 0x1000) {
-			if (netif_running(dev)) {
-				DEB(DEB_ERRORS,printk(KERN_ERR "%s: i596 interrupt receive unit inactive, status 0x%x\n", dev->name, status));
-				ack_cmd |= RX_START;
-				dev->stats.rx_errors++;
-				dev->stats.rx_fifo_errors++;
-				rebuild_rx_bufs(dev);
-			}
-		}
-	}
-	wait_cmd(dev,lp,100,"i596 interrupt, timeout");
-	lp->scb.command = ack_cmd;
-
-#ifdef ENABLE_MVME16x_NET
-	if (MACH_IS_MVME16x) {
-		/* Ack the interrupt */
-
-		volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
-
-		pcc2[0x2a] |= 0x08;
-	}
-#endif
-#ifdef ENABLE_BVME6000_NET
-	if (MACH_IS_BVME6000) {
-		volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
-
-		*ethirq = 1;
-		*ethirq = 3;
-	}
-#endif
-#ifdef ENABLE_APRICOT
-	(void) inb(ioaddr + 0x10);
-	outb(4, ioaddr + 0xf);
-#endif
-	CA(dev);
-
-	DEB(DEB_INTS,printk(KERN_DEBUG "%s: exiting interrupt.\n", dev->name));
-
-	spin_unlock (&lp->lock);
-	return IRQ_RETVAL(handled);
-}
-
-static int i596_close(struct net_device *dev)
-{
-	struct i596_private *lp = dev->ml_priv;
-	unsigned long flags;
-
-	netif_stop_queue(dev);
-
-	DEB(DEB_INIT,printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n",
-		       dev->name, lp->scb.status));
-
-	spin_lock_irqsave(&lp->lock, flags);
-
-	wait_cmd(dev,lp,100,"close1 timed out");
-	lp->scb.command = CUC_ABORT | RX_ABORT;
-	CA(dev);
-
-	wait_cmd(dev,lp,100,"close2 timed out");
-
-	spin_unlock_irqrestore(&lp->lock, flags);
-	DEB(DEB_STRUCT,i596_display_data(dev));
-	i596_cleanup_cmd(dev,lp);
-
-#ifdef ENABLE_MVME16x_NET
-	if (MACH_IS_MVME16x) {
-		volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
-
-		/* Disable all ints */
-		pcc2[0x28] = 1;
-		pcc2[0x2a] = 0x40;
-		pcc2[0x2b] = 0x40;	/* Set snooping bits now! */
-	}
-#endif
-#ifdef ENABLE_BVME6000_NET
-	if (MACH_IS_BVME6000) {
-		volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
-
-		*ethirq = 1;
-	}
-#endif
-
-#ifdef ENABLE_MVME16x_NET
-	free_irq(0x56, dev);
-#endif
-	free_irq(dev->irq, dev);
-	remove_rx_bufs(dev);
-
-	return 0;
-}
-
-/*
- *    Set or clear the multicast filter for this adaptor.
- */
-
-static void set_multicast_list(struct net_device *dev)
-{
-	struct i596_private *lp = dev->ml_priv;
-	int config = 0, cnt;
-
-	DEB(DEB_MULTI,printk(KERN_DEBUG "%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
-		dev->name, netdev_mc_count(dev),
-		dev->flags & IFF_PROMISC  ? "ON" : "OFF",
-		dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
-
-	if (wait_cfg(dev, &lp->cf_cmd.cmd, 1000, "config change request timed out"))
-		return;
-
-	if ((dev->flags & IFF_PROMISC) && !(lp->cf_cmd.i596_config[8] & 0x01)) {
-		lp->cf_cmd.i596_config[8] |= 0x01;
-		config = 1;
-	}
-	if (!(dev->flags & IFF_PROMISC) && (lp->cf_cmd.i596_config[8] & 0x01)) {
-		lp->cf_cmd.i596_config[8] &= ~0x01;
-		config = 1;
-	}
-	if ((dev->flags & IFF_ALLMULTI) && (lp->cf_cmd.i596_config[11] & 0x20)) {
-		lp->cf_cmd.i596_config[11] &= ~0x20;
-		config = 1;
-	}
-	if (!(dev->flags & IFF_ALLMULTI) && !(lp->cf_cmd.i596_config[11] & 0x20)) {
-		lp->cf_cmd.i596_config[11] |= 0x20;
-		config = 1;
-	}
-	if (config) {
-		lp->cf_cmd.cmd.command = CmdConfigure;
-		i596_add_cmd(dev, &lp->cf_cmd.cmd);
-	}
-
-	cnt = netdev_mc_count(dev);
-	if (cnt > MAX_MC_CNT)
-	{
-		cnt = MAX_MC_CNT;
-		printk(KERN_ERR "%s: Only %d multicast addresses supported",
-			dev->name, cnt);
-	}
-
-	if (!netdev_mc_empty(dev)) {
-		struct netdev_hw_addr *ha;
-		unsigned char *cp;
-		struct mc_cmd *cmd;
-
-		if (wait_cfg(dev, &lp->mc_cmd.cmd, 1000, "multicast list change request timed out"))
-			return;
-		cmd = &lp->mc_cmd;
-		cmd->cmd.command = CmdMulticastList;
-		cmd->mc_cnt = cnt * ETH_ALEN;
-		cp = cmd->mc_addrs;
-		netdev_for_each_mc_addr(ha, dev) {
-			if (!cnt--)
-				break;
-			memcpy(cp, ha->addr, ETH_ALEN);
-			if (i596_debug > 1)
-				DEB(DEB_MULTI,printk(KERN_INFO "%s: Adding address %pM\n",
-						dev->name, cp));
-			cp += ETH_ALEN;
-		}
-		i596_add_cmd(dev, &cmd->cmd);
-	}
-}
-
-#ifdef MODULE
-static struct net_device *dev_82596;
-
-#ifdef ENABLE_APRICOT
-module_param(irq, int, 0);
-MODULE_PARM_DESC(irq, "Apricot IRQ number");
-#endif
-
-static int debug = -1;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "i82596 debug mask");
-
-int __init init_module(void)
-{
-	if (debug >= 0)
-		i596_debug = debug;
-	dev_82596 = i82596_probe(-1);
-	if (IS_ERR(dev_82596))
-		return PTR_ERR(dev_82596);
-	return 0;
-}
-
-void __exit cleanup_module(void)
-{
-	unregister_netdev(dev_82596);
-#ifdef __mc68000__
-	/* XXX This assumes default cache mode to be IOMAP_FULL_CACHING,
-	 * XXX which may be invalid (CONFIG_060_WRITETHROUGH)
-	 */
-
-	kernel_set_cachemode((void *)(dev_82596->mem_start), 4096,
-			IOMAP_FULL_CACHING);
-#endif
-	free_page ((u32)(dev_82596->mem_start));
-#ifdef ENABLE_APRICOT
-	/* If we don't do this, we can't re-insmod it later. */
-	release_region(dev_82596->base_addr, I596_TOTAL_SIZE);
-#endif
-	free_netdev(dev_82596);
-}
-
-#endif				/* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/8390.c linux-libre-3.2-gnu/drivers/net/8390.c
--- linux-libre-3.1-gnu/drivers/net/8390.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/8390.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,103 +0,0 @@
-/* 8390 core for usual drivers */
-
-static const char version[] =
-    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#include "lib8390.c"
-
-int ei_open(struct net_device *dev)
-{
-	return __ei_open(dev);
-}
-EXPORT_SYMBOL(ei_open);
-
-int ei_close(struct net_device *dev)
-{
-	return __ei_close(dev);
-}
-EXPORT_SYMBOL(ei_close);
-
-netdev_tx_t ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	return __ei_start_xmit(skb, dev);
-}
-EXPORT_SYMBOL(ei_start_xmit);
-
-struct net_device_stats *ei_get_stats(struct net_device *dev)
-{
-	return __ei_get_stats(dev);
-}
-EXPORT_SYMBOL(ei_get_stats);
-
-void ei_set_multicast_list(struct net_device *dev)
-{
-	__ei_set_multicast_list(dev);
-}
-EXPORT_SYMBOL(ei_set_multicast_list);
-
-void ei_tx_timeout(struct net_device *dev)
-{
-	__ei_tx_timeout(dev);
-}
-EXPORT_SYMBOL(ei_tx_timeout);
-
-irqreturn_t ei_interrupt(int irq, void *dev_id)
-{
-	return __ei_interrupt(irq, dev_id);
-}
-EXPORT_SYMBOL(ei_interrupt);
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-void ei_poll(struct net_device *dev)
-{
-	__ei_poll(dev);
-}
-EXPORT_SYMBOL(ei_poll);
-#endif
-
-const struct net_device_ops ei_netdev_ops = {
-	.ndo_open		= ei_open,
-	.ndo_stop		= ei_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_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,
-#endif
-};
-EXPORT_SYMBOL(ei_netdev_ops);
-
-struct net_device *__alloc_ei_netdev(int size)
-{
-	struct net_device *dev = ____alloc_ei_netdev(size);
-	if (dev)
-		dev->netdev_ops = &ei_netdev_ops;
-	return dev;
-}
-EXPORT_SYMBOL(__alloc_ei_netdev);
-
-void NS8390_init(struct net_device *dev, int startp)
-{
-	__NS8390_init(dev, startp);
-}
-EXPORT_SYMBOL(NS8390_init);
-
-#if defined(MODULE)
-
-static int __init ns8390_module_init(void)
-{
-	return 0;
-}
-
-static void __exit ns8390_module_exit(void)
-{
-}
-
-module_init(ns8390_module_init);
-module_exit(ns8390_module_exit);
-#endif /* MODULE */
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/8390.h linux-libre-3.2-gnu/drivers/net/8390.h
--- linux-libre-3.1-gnu/drivers/net/8390.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/8390.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,232 +0,0 @@
-/* Generic NS8390 register definitions. */
-/* This file is part of Donald Becker's 8390 drivers, and is distributed
-   under the same license. Auto-loading of 8390.o only in v2.2 - Paul G.
-   Some of these names and comments originated from the Crynwr
-   packet drivers, which are distributed under the GPL. */
-
-#ifndef _8390_h
-#define _8390_h
-
-#include <linux/if_ether.h>
-#include <linux/ioport.h>
-#include <linux/irqreturn.h>
-#include <linux/skbuff.h>
-
-#define TX_PAGES 12	/* Two Tx slots */
-
-#define ETHER_ADDR_LEN 6
-
-/* The 8390 specific per-packet-header format. */
-struct e8390_pkt_hdr {
-  unsigned char status; /* status */
-  unsigned char next;   /* pointer to next packet. */
-  unsigned short count; /* header + packet length in bytes */
-};
-
-#ifdef notdef
-extern int ei_debug;
-#else
-#define ei_debug 1
-#endif
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-extern void ei_poll(struct net_device *dev);
-extern void eip_poll(struct net_device *dev);
-#endif
-
-
-/* Without I/O delay - non ISA or later chips */
-extern void NS8390_init(struct net_device *dev, int startp);
-extern int ei_open(struct net_device *dev);
-extern int ei_close(struct net_device *dev);
-extern irqreturn_t ei_interrupt(int irq, void *dev_id);
-extern void ei_tx_timeout(struct net_device *dev);
-extern netdev_tx_t ei_start_xmit(struct sk_buff *skb, struct net_device *dev);
-extern void ei_set_multicast_list(struct net_device *dev);
-extern struct net_device_stats *ei_get_stats(struct net_device *dev);
-
-extern const struct net_device_ops ei_netdev_ops;
-
-extern struct net_device *__alloc_ei_netdev(int size);
-static inline struct net_device *alloc_ei_netdev(void)
-{
-	return __alloc_ei_netdev(0);
-}
-
-/* With I/O delay form */
-extern void NS8390p_init(struct net_device *dev, int startp);
-extern int eip_open(struct net_device *dev);
-extern int eip_close(struct net_device *dev);
-extern irqreturn_t eip_interrupt(int irq, void *dev_id);
-extern void eip_tx_timeout(struct net_device *dev);
-extern netdev_tx_t eip_start_xmit(struct sk_buff *skb, struct net_device *dev);
-extern void eip_set_multicast_list(struct net_device *dev);
-extern struct net_device_stats *eip_get_stats(struct net_device *dev);
-
-extern const struct net_device_ops eip_netdev_ops;
-
-extern struct net_device *__alloc_eip_netdev(int size);
-static inline struct net_device *alloc_eip_netdev(void)
-{
-	return __alloc_eip_netdev(0);
-}
-
-/* You have one of these per-board */
-struct ei_device {
-	const char *name;
-	void (*reset_8390)(struct net_device *);
-	void (*get_8390_hdr)(struct net_device *, struct e8390_pkt_hdr *, int);
-	void (*block_output)(struct net_device *, int, const unsigned char *, int);
-	void (*block_input)(struct net_device *, int, struct sk_buff *, int);
-	unsigned long rmem_start;
-	unsigned long rmem_end;
-	void __iomem *mem;
-	unsigned char mcfilter[8];
-	unsigned open:1;
-	unsigned word16:1;  		/* We have the 16-bit (vs 8-bit) version of the card. */
-	unsigned bigendian:1;		/* 16-bit big endian mode. Do NOT */
-					/* set this on random 8390 clones! */
-	unsigned txing:1;		/* Transmit Active */
-	unsigned irqlock:1;		/* 8390's intrs disabled when '1'. */
-	unsigned dmaing:1;		/* Remote DMA Active */
-	unsigned char tx_start_page, rx_start_page, stop_page;
-	unsigned char current_page;	/* Read pointer in buffer  */
-	unsigned char interface_num;	/* Net port (AUI, 10bT.) to use. */
-	unsigned char txqueue;		/* Tx Packet buffer queue length. */
-	short tx1, tx2;			/* Packet lengths for ping-pong tx. */
-	short lasttx;			/* Alpha version consistency check. */
-	unsigned char reg0;		/* Register '0' in a WD8013 */
-	unsigned char reg5;		/* Register '5' in a WD8013 */
-	unsigned char saved_irq;	/* Original dev->irq value. */
-	u32 *reg_offset;		/* Register mapping table */
-	spinlock_t page_lock;		/* Page register locks */
-	unsigned long priv;		/* Private field to store bus IDs etc. */
-#ifdef AX88796_PLATFORM
-	unsigned char rxcr_base;	/* default value for RXCR */
-#endif
-};
-
-/* The maximum number of 8390 interrupt service routines called per IRQ. */
-#define MAX_SERVICE 12
-
-/* The maximum time waited (in jiffies) before assuming a Tx failed. (20ms) */
-#define TX_TIMEOUT (20*HZ/100)
-
-#define ei_status (*(struct ei_device *)netdev_priv(dev))
-
-/* Some generic ethernet register configurations. */
-#define E8390_TX_IRQ_MASK	0xa	/* For register EN0_ISR */
-#define E8390_RX_IRQ_MASK	0x5
-
-#ifdef AX88796_PLATFORM
-#define E8390_RXCONFIG		(ei_status.rxcr_base | 0x04)
-#define E8390_RXOFF		(ei_status.rxcr_base | 0x20)
-#else
-#define E8390_RXCONFIG		0x4	/* EN0_RXCR: broadcasts, no multicast,errors */
-#define E8390_RXOFF		0x20	/* EN0_RXCR: Accept no packets */
-#endif
-
-#define E8390_TXCONFIG		0x00	/* EN0_TXCR: Normal transmit mode */
-#define E8390_TXOFF		0x02	/* EN0_TXCR: Transmitter off */
-
-
-/*  Register accessed at EN_CMD, the 8390 base addr.  */
-#define E8390_STOP	0x01	/* Stop and reset the chip */
-#define E8390_START	0x02	/* Start the chip, clear reset */
-#define E8390_TRANS	0x04	/* Transmit a frame */
-#define E8390_RREAD	0x08	/* Remote read */
-#define E8390_RWRITE	0x10	/* Remote write  */
-#define E8390_NODMA	0x20	/* Remote DMA */
-#define E8390_PAGE0	0x00	/* Select page chip registers */
-#define E8390_PAGE1	0x40	/* using the two high-order bits */
-#define E8390_PAGE2	0x80	/* Page 3 is invalid. */
-
-/*
- *	Only generate indirect loads given a machine that needs them.
- *      - removed AMIGA_PCMCIA from this list, handled as ISA io now
- *	- the _p for generates no delay by default 8390p.c overrides this.
- */
-
-#ifndef ei_inb
-#define ei_inb(_p)	inb(_p)
-#define ei_outb(_v,_p)	outb(_v,_p)
-#define ei_inb_p(_p)	inb(_p)
-#define ei_outb_p(_v,_p) outb(_v,_p)
-#endif
-
-#ifndef EI_SHIFT
-#define EI_SHIFT(x)	(x)
-#endif
-
-#define E8390_CMD	EI_SHIFT(0x00)  /* The command register (for all pages) */
-/* Page 0 register offsets. */
-#define EN0_CLDALO	EI_SHIFT(0x01)	/* Low byte of current local dma addr  RD */
-#define EN0_STARTPG	EI_SHIFT(0x01)	/* Starting page of ring bfr WR */
-#define EN0_CLDAHI	EI_SHIFT(0x02)	/* High byte of current local dma addr  RD */
-#define EN0_STOPPG	EI_SHIFT(0x02)	/* Ending page +1 of ring bfr WR */
-#define EN0_BOUNDARY	EI_SHIFT(0x03)	/* Boundary page of ring bfr RD WR */
-#define EN0_TSR		EI_SHIFT(0x04)	/* Transmit status reg RD */
-#define EN0_TPSR	EI_SHIFT(0x04)	/* Transmit starting page WR */
-#define EN0_NCR		EI_SHIFT(0x05)	/* Number of collision reg RD */
-#define EN0_TCNTLO	EI_SHIFT(0x05)	/* Low  byte of tx byte count WR */
-#define EN0_FIFO	EI_SHIFT(0x06)	/* FIFO RD */
-#define EN0_TCNTHI	EI_SHIFT(0x06)	/* High byte of tx byte count WR */
-#define EN0_ISR		EI_SHIFT(0x07)	/* Interrupt status reg RD WR */
-#define EN0_CRDALO	EI_SHIFT(0x08)	/* low byte of current remote dma address RD */
-#define EN0_RSARLO	EI_SHIFT(0x08)	/* Remote start address reg 0 */
-#define EN0_CRDAHI	EI_SHIFT(0x09)	/* high byte, current remote dma address RD */
-#define EN0_RSARHI	EI_SHIFT(0x09)	/* Remote start address reg 1 */
-#define EN0_RCNTLO	EI_SHIFT(0x0a)	/* Remote byte count reg WR */
-#define EN0_RCNTHI	EI_SHIFT(0x0b)	/* Remote byte count reg WR */
-#define EN0_RSR		EI_SHIFT(0x0c)	/* rx status reg RD */
-#define EN0_RXCR	EI_SHIFT(0x0c)	/* RX configuration reg WR */
-#define EN0_TXCR	EI_SHIFT(0x0d)	/* TX configuration reg WR */
-#define EN0_COUNTER0	EI_SHIFT(0x0d)	/* Rcv alignment error counter RD */
-#define EN0_DCFG	EI_SHIFT(0x0e)	/* Data configuration reg WR */
-#define EN0_COUNTER1	EI_SHIFT(0x0e)	/* Rcv CRC error counter RD */
-#define EN0_IMR		EI_SHIFT(0x0f)	/* Interrupt mask reg WR */
-#define EN0_COUNTER2	EI_SHIFT(0x0f)	/* Rcv missed frame error counter RD */
-
-/* Bits in EN0_ISR - Interrupt status register */
-#define ENISR_RX	0x01	/* Receiver, no error */
-#define ENISR_TX	0x02	/* Transmitter, no error */
-#define ENISR_RX_ERR	0x04	/* Receiver, with error */
-#define ENISR_TX_ERR	0x08	/* Transmitter, with error */
-#define ENISR_OVER	0x10	/* Receiver overwrote the ring */
-#define ENISR_COUNTERS	0x20	/* Counters need emptying */
-#define ENISR_RDC	0x40	/* remote dma complete */
-#define ENISR_RESET	0x80	/* Reset completed */
-#define ENISR_ALL	0x3f	/* Interrupts we will enable */
-
-/* Bits in EN0_DCFG - Data config register */
-#define ENDCFG_WTS	0x01	/* word transfer mode selection */
-#define ENDCFG_BOS	0x02	/* byte order selection */
-
-/* Page 1 register offsets. */
-#define EN1_PHYS   EI_SHIFT(0x01)	/* This board's physical enet addr RD WR */
-#define EN1_PHYS_SHIFT(i)  EI_SHIFT(i+1) /* Get and set mac address */
-#define EN1_CURPAG EI_SHIFT(0x07)	/* Current memory page RD WR */
-#define EN1_MULT   EI_SHIFT(0x08)	/* Multicast filter mask array (8 bytes) RD WR */
-#define EN1_MULT_SHIFT(i)  EI_SHIFT(8+i) /* Get and set multicast filter */
-
-/* Bits in received packet status byte and EN0_RSR*/
-#define ENRSR_RXOK	0x01	/* Received a good packet */
-#define ENRSR_CRC	0x02	/* CRC error */
-#define ENRSR_FAE	0x04	/* frame alignment error */
-#define ENRSR_FO	0x08	/* FIFO overrun */
-#define ENRSR_MPA	0x10	/* missed pkt */
-#define ENRSR_PHY	0x20	/* physical/multicast address */
-#define ENRSR_DIS	0x40	/* receiver disable. set in monitor mode */
-#define ENRSR_DEF	0x80	/* deferring */
-
-/* Transmitted packet status, EN0_TSR. */
-#define ENTSR_PTX 0x01	/* Packet transmitted without error */
-#define ENTSR_ND  0x02	/* The transmit wasn't deferred. */
-#define ENTSR_COL 0x04	/* The transmit collided at least once. */
-#define ENTSR_ABT 0x08  /* The transmit collided 16 times, and was deferred. */
-#define ENTSR_CRS 0x10	/* The carrier sense was lost. */
-#define ENTSR_FU  0x20  /* A "FIFO underrun" occurred during transmit. */
-#define ENTSR_CDH 0x40	/* The collision detect "heartbeat" signal was lost. */
-#define ENTSR_OWC 0x80  /* There was an out-of-window collision. */
-
-#endif /* _8390_h */
diff -druN linux-libre-3.1-gnu/drivers/net/8390p.c linux-libre-3.2-gnu/drivers/net/8390p.c
--- linux-libre-3.1-gnu/drivers/net/8390p.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/8390p.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,105 +0,0 @@
-/* 8390 core for ISA devices needing bus delays */
-
-static const char version[] =
-    "8390p.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#define ei_inb(_p)	inb(_p)
-#define ei_outb(_v, _p)	outb(_v, _p)
-#define ei_inb_p(_p)	inb_p(_p)
-#define ei_outb_p(_v, _p) outb_p(_v, _p)
-
-#include "lib8390.c"
-
-int eip_open(struct net_device *dev)
-{
-	return __ei_open(dev);
-}
-EXPORT_SYMBOL(eip_open);
-
-int eip_close(struct net_device *dev)
-{
-	return __ei_close(dev);
-}
-EXPORT_SYMBOL(eip_close);
-
-netdev_tx_t eip_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	return __ei_start_xmit(skb, dev);
-}
-EXPORT_SYMBOL(eip_start_xmit);
-
-struct net_device_stats *eip_get_stats(struct net_device *dev)
-{
-	return __ei_get_stats(dev);
-}
-EXPORT_SYMBOL(eip_get_stats);
-
-void eip_set_multicast_list(struct net_device *dev)
-{
-	__ei_set_multicast_list(dev);
-}
-EXPORT_SYMBOL(eip_set_multicast_list);
-
-void eip_tx_timeout(struct net_device *dev)
-{
-	__ei_tx_timeout(dev);
-}
-EXPORT_SYMBOL(eip_tx_timeout);
-
-irqreturn_t eip_interrupt(int irq, void *dev_id)
-{
-	return __ei_interrupt(irq, dev_id);
-}
-EXPORT_SYMBOL(eip_interrupt);
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-void eip_poll(struct net_device *dev)
-{
-	__ei_poll(dev);
-}
-EXPORT_SYMBOL(eip_poll);
-#endif
-
-const struct net_device_ops eip_netdev_ops = {
-	.ndo_open		= eip_open,
-	.ndo_stop		= eip_close,
-	.ndo_start_xmit		= eip_start_xmit,
-	.ndo_tx_timeout		= eip_tx_timeout,
-	.ndo_get_stats		= eip_get_stats,
-	.ndo_set_multicast_list = eip_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	= eip_poll,
-#endif
-};
-EXPORT_SYMBOL(eip_netdev_ops);
-
-struct net_device *__alloc_eip_netdev(int size)
-{
-	struct net_device *dev = ____alloc_ei_netdev(size);
-	if (dev)
-		dev->netdev_ops = &eip_netdev_ops;
-	return dev;
-}
-EXPORT_SYMBOL(__alloc_eip_netdev);
-
-void NS8390p_init(struct net_device *dev, int startp)
-{
-	__NS8390_init(dev, startp);
-}
-EXPORT_SYMBOL(NS8390p_init);
-
-static int __init NS8390p_init_module(void)
-{
-	return 0;
-}
-
-static void __exit NS8390p_cleanup_module(void)
-{
-}
-
-module_init(NS8390p_init_module);
-module_exit(NS8390p_cleanup_module);
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/a2065.c linux-libre-3.2-gnu/drivers/net/a2065.c
--- linux-libre-3.1-gnu/drivers/net/a2065.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/a2065.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,781 +0,0 @@
-/*
- * Amiga Linux/68k A2065 Ethernet Driver
- *
- * (C) Copyright 1995-2003 by Geert Uytterhoeven <geert@linux-m68k.org>
- *
- * Fixes and tips by:
- *	- Janos Farkas (CHEXUM@sparta.banki.hu)
- *	- Jes Degn Soerensen (jds@kom.auc.dk)
- *	- Matt Domsch (Matt_Domsch@dell.com)
- *
- * ----------------------------------------------------------------------------
- *
- * This program is based on
- *
- *	ariadne.?:	Amiga Linux/68k Ariadne Ethernet Driver
- *			(C) Copyright 1995 by Geert Uytterhoeven,
- *                                            Peter De Schrijver
- *
- *	lance.c:	An AMD LANCE ethernet driver for linux.
- *			Written 1993-94 by Donald Becker.
- *
- *	Am79C960:	PCnet(tm)-ISA Single-Chip Ethernet Controller
- *			Advanced Micro Devices
- *			Publication #16907, Rev. B, Amendment/0, May 1994
- *
- * ----------------------------------------------------------------------------
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of the Linux
- * distribution for more details.
- *
- * ----------------------------------------------------------------------------
- *
- * The A2065 is a Zorro-II board made by Commodore/Ameristar. It contains:
- *
- *	- an Am7990 Local Area Network Controller for Ethernet (LANCE) with
- *	  both 10BASE-2 (thin coax) and AUI (DB-15) connectors
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-/*#define DEBUG*/
-/*#define TEST_HITS*/
-
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/module.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/skbuff.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/crc32.h>
-#include <linux/zorro.h>
-#include <linux/bitops.h>
-
-#include <asm/irq.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-
-#include "a2065.h"
-
-/* Transmit/Receive Ring Definitions */
-
-#define LANCE_LOG_TX_BUFFERS	(2)
-#define LANCE_LOG_RX_BUFFERS	(4)
-
-#define TX_RING_SIZE		(1 << LANCE_LOG_TX_BUFFERS)
-#define RX_RING_SIZE		(1 << LANCE_LOG_RX_BUFFERS)
-
-#define TX_RING_MOD_MASK	(TX_RING_SIZE - 1)
-#define RX_RING_MOD_MASK	(RX_RING_SIZE - 1)
-
-#define PKT_BUF_SIZE		(1544)
-#define RX_BUFF_SIZE            PKT_BUF_SIZE
-#define TX_BUFF_SIZE            PKT_BUF_SIZE
-
-/* Layout of the Lance's RAM Buffer */
-
-struct lance_init_block {
-	unsigned short mode;		/* Pre-set mode (reg. 15) */
-	unsigned char phys_addr[6];     /* Physical ethernet address */
-	unsigned filter[2];		/* Multicast filter. */
-
-	/* Receive and transmit ring base, along with extra bits. */
-	unsigned short rx_ptr;		/* receive descriptor addr */
-	unsigned short rx_len;		/* receive len and high addr */
-	unsigned short tx_ptr;		/* transmit descriptor addr */
-	unsigned short tx_len;		/* transmit len and high addr */
-
-	/* The Tx and Rx ring entries must aligned on 8-byte boundaries. */
-	struct lance_rx_desc brx_ring[RX_RING_SIZE];
-	struct lance_tx_desc btx_ring[TX_RING_SIZE];
-
-	char rx_buf[RX_RING_SIZE][RX_BUFF_SIZE];
-	char tx_buf[TX_RING_SIZE][TX_BUFF_SIZE];
-};
-
-/* Private Device Data */
-
-struct lance_private {
-	char *name;
-	volatile struct lance_regs *ll;
-	volatile struct lance_init_block *init_block;	    /* Hosts view */
-	volatile struct lance_init_block *lance_init_block; /* Lance view */
-
-	int rx_new, tx_new;
-	int rx_old, tx_old;
-
-	int lance_log_rx_bufs, lance_log_tx_bufs;
-	int rx_ring_mod_mask, tx_ring_mod_mask;
-
-	int tpe;		      /* cable-selection is TPE */
-	int auto_select;	      /* cable-selection by carrier */
-	unsigned short busmaster_regval;
-
-#ifdef CONFIG_SUNLANCE
-	struct Linux_SBus_DMA *ledma; /* if set this points to ledma and arch=4m */
-	int burst_sizes;	      /* ledma SBus burst sizes */
-#endif
-	struct timer_list         multicast_timer;
-};
-
-#define LANCE_ADDR(x) ((int)(x) & ~0xff000000)
-
-/* Load the CSR registers */
-static void load_csrs(struct lance_private *lp)
-{
-	volatile struct lance_regs *ll = lp->ll;
-	volatile struct lance_init_block *aib = lp->lance_init_block;
-	int leptr = LANCE_ADDR(aib);
-
-	ll->rap = LE_CSR1;
-	ll->rdp = (leptr & 0xFFFF);
-	ll->rap = LE_CSR2;
-	ll->rdp = leptr >> 16;
-	ll->rap = LE_CSR3;
-	ll->rdp = lp->busmaster_regval;
-
-	/* Point back to csr0 */
-	ll->rap = LE_CSR0;
-}
-
-/* Setup the Lance Rx and Tx rings */
-static void lance_init_ring(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
-	volatile struct lance_init_block *aib = lp->lance_init_block;
-					/* for LANCE_ADDR computations */
-	int leptr;
-	int i;
-
-	/* Lock out other processes while setting up hardware */
-	netif_stop_queue(dev);
-	lp->rx_new = lp->tx_new = 0;
-	lp->rx_old = lp->tx_old = 0;
-
-	ib->mode = 0;
-
-	/* Copy the ethernet address to the lance init block
-	 * Note that on the sparc you need to swap the ethernet address.
-	 */
-	ib->phys_addr[0] = dev->dev_addr[1];
-	ib->phys_addr[1] = dev->dev_addr[0];
-	ib->phys_addr[2] = dev->dev_addr[3];
-	ib->phys_addr[3] = dev->dev_addr[2];
-	ib->phys_addr[4] = dev->dev_addr[5];
-	ib->phys_addr[5] = dev->dev_addr[4];
-
-	/* Setup the Tx ring entries */
-	netdev_dbg(dev, "TX rings:\n");
-	for (i = 0; i <= 1 << lp->lance_log_tx_bufs; i++) {
-		leptr = LANCE_ADDR(&aib->tx_buf[i][0]);
-		ib->btx_ring[i].tmd0      = leptr;
-		ib->btx_ring[i].tmd1_hadr = leptr >> 16;
-		ib->btx_ring[i].tmd1_bits = 0;
-		ib->btx_ring[i].length    = 0xf000; /* The ones required by tmd2 */
-		ib->btx_ring[i].misc      = 0;
-		if (i < 3)
-			netdev_dbg(dev, "%d: 0x%08x\n", i, leptr);
-	}
-
-	/* Setup the Rx ring entries */
-	netdev_dbg(dev, "RX rings:\n");
-	for (i = 0; i < 1 << lp->lance_log_rx_bufs; i++) {
-		leptr = LANCE_ADDR(&aib->rx_buf[i][0]);
-
-		ib->brx_ring[i].rmd0      = leptr;
-		ib->brx_ring[i].rmd1_hadr = leptr >> 16;
-		ib->brx_ring[i].rmd1_bits = LE_R1_OWN;
-		ib->brx_ring[i].length    = -RX_BUFF_SIZE | 0xf000;
-		ib->brx_ring[i].mblength  = 0;
-		if (i < 3)
-			netdev_dbg(dev, "%d: 0x%08x\n", i, leptr);
-	}
-
-	/* Setup the initialization block */
-
-	/* Setup rx descriptor pointer */
-	leptr = LANCE_ADDR(&aib->brx_ring);
-	ib->rx_len = (lp->lance_log_rx_bufs << 13) | (leptr >> 16);
-	ib->rx_ptr = leptr;
-	netdev_dbg(dev, "RX ptr: %08x\n", leptr);
-
-	/* Setup tx descriptor pointer */
-	leptr = LANCE_ADDR(&aib->btx_ring);
-	ib->tx_len = (lp->lance_log_tx_bufs << 13) | (leptr >> 16);
-	ib->tx_ptr = leptr;
-	netdev_dbg(dev, "TX ptr: %08x\n", leptr);
-
-	/* Clear the multicast filter */
-	ib->filter[0] = 0;
-	ib->filter[1] = 0;
-}
-
-static int init_restart_lance(struct lance_private *lp)
-{
-	volatile struct lance_regs *ll = lp->ll;
-	int i;
-
-	ll->rap = LE_CSR0;
-	ll->rdp = LE_C0_INIT;
-
-	/* Wait for the lance to complete initialization */
-	for (i = 0; (i < 100) && !(ll->rdp & (LE_C0_ERR | LE_C0_IDON)); i++)
-		barrier();
-	if ((i == 100) || (ll->rdp & LE_C0_ERR)) {
-		pr_err("unopened after %d ticks, csr0=%04x\n", i, ll->rdp);
-		return -EIO;
-	}
-
-	/* Clear IDON by writing a "1", enable interrupts and start lance */
-	ll->rdp = LE_C0_IDON;
-	ll->rdp = LE_C0_INEA | LE_C0_STRT;
-
-	return 0;
-}
-
-static int lance_rx(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
-	volatile struct lance_regs *ll = lp->ll;
-	volatile struct lance_rx_desc *rd;
-	unsigned char bits;
-
-#ifdef TEST_HITS
-	int i;
-	char buf[RX_RING_SIZE + 1];
-
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		char r1_own = ib->brx_ring[i].rmd1_bits & LE_R1_OWN;
-		if (i == lp->rx_new)
-			buf[i] = r1_own ? '_' : 'X';
-		else
-			buf[i] = r1_own ? '.' : '1';
-	}
-	buf[RX_RING_SIZE] = 0;
-
-	pr_debug("RxRing TestHits: [%s]\n", buf);
-#endif
-
-	ll->rdp = LE_C0_RINT | LE_C0_INEA;
-	for (rd = &ib->brx_ring[lp->rx_new];
-	     !((bits = rd->rmd1_bits) & LE_R1_OWN);
-	     rd = &ib->brx_ring[lp->rx_new]) {
-
-		/* We got an incomplete frame? */
-		if ((bits & LE_R1_POK) != LE_R1_POK) {
-			dev->stats.rx_over_errors++;
-			dev->stats.rx_errors++;
-			continue;
-		} else if (bits & LE_R1_ERR) {
-			/* Count only the end frame as a rx error,
-			 * not the beginning
-			 */
-			if (bits & LE_R1_BUF)
-				dev->stats.rx_fifo_errors++;
-			if (bits & LE_R1_CRC)
-				dev->stats.rx_crc_errors++;
-			if (bits & LE_R1_OFL)
-				dev->stats.rx_over_errors++;
-			if (bits & LE_R1_FRA)
-				dev->stats.rx_frame_errors++;
-			if (bits & LE_R1_EOP)
-				dev->stats.rx_errors++;
-		} else {
-			int len = (rd->mblength & 0xfff) - 4;
-			struct sk_buff *skb = dev_alloc_skb(len + 2);
-
-			if (!skb) {
-				netdev_warn(dev, "Memory squeeze, deferring packet\n");
-				dev->stats.rx_dropped++;
-				rd->mblength = 0;
-				rd->rmd1_bits = LE_R1_OWN;
-				lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask;
-				return 0;
-			}
-
-			skb_reserve(skb, 2);		/* 16 byte align */
-			skb_put(skb, len);		/* make room */
-			skb_copy_to_linear_data(skb,
-				 (unsigned char *)&ib->rx_buf[lp->rx_new][0],
-				 len);
-			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
-			dev->stats.rx_packets++;
-			dev->stats.rx_bytes += len;
-		}
-
-		/* Return the packet to the pool */
-		rd->mblength = 0;
-		rd->rmd1_bits = LE_R1_OWN;
-		lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask;
-	}
-	return 0;
-}
-
-static int lance_tx(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
-	volatile struct lance_regs *ll = lp->ll;
-	volatile struct lance_tx_desc *td;
-	int i, j;
-	int status;
-
-	/* csr0 is 2f3 */
-	ll->rdp = LE_C0_TINT | LE_C0_INEA;
-	/* csr0 is 73 */
-
-	j = lp->tx_old;
-	for (i = j; i != lp->tx_new; i = j) {
-		td = &ib->btx_ring[i];
-
-		/* If we hit a packet not owned by us, stop */
-		if (td->tmd1_bits & LE_T1_OWN)
-			break;
-
-		if (td->tmd1_bits & LE_T1_ERR) {
-			status = td->misc;
-
-			dev->stats.tx_errors++;
-			if (status & LE_T3_RTY)
-				dev->stats.tx_aborted_errors++;
-			if (status & LE_T3_LCOL)
-				dev->stats.tx_window_errors++;
-
-			if (status & LE_T3_CLOS) {
-				dev->stats.tx_carrier_errors++;
-				if (lp->auto_select) {
-					lp->tpe = 1 - lp->tpe;
-					netdev_err(dev, "Carrier Lost, trying %s\n",
-						   lp->tpe ? "TPE" : "AUI");
-					/* Stop the lance */
-					ll->rap = LE_CSR0;
-					ll->rdp = LE_C0_STOP;
-					lance_init_ring(dev);
-					load_csrs(lp);
-					init_restart_lance(lp);
-					return 0;
-				}
-			}
-
-			/* buffer errors and underflows turn off
-			 * the transmitter, so restart the adapter
-			 */
-			if (status & (LE_T3_BUF | LE_T3_UFL)) {
-				dev->stats.tx_fifo_errors++;
-
-				netdev_err(dev, "Tx: ERR_BUF|ERR_UFL, restarting\n");
-				/* Stop the lance */
-				ll->rap = LE_CSR0;
-				ll->rdp = LE_C0_STOP;
-				lance_init_ring(dev);
-				load_csrs(lp);
-				init_restart_lance(lp);
-				return 0;
-			}
-		} else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) {
-			/* So we don't count the packet more than once. */
-			td->tmd1_bits &= ~(LE_T1_POK);
-
-			/* One collision before packet was sent. */
-			if (td->tmd1_bits & LE_T1_EONE)
-				dev->stats.collisions++;
-
-			/* More than one collision, be optimistic. */
-			if (td->tmd1_bits & LE_T1_EMORE)
-				dev->stats.collisions += 2;
-
-			dev->stats.tx_packets++;
-		}
-
-		j = (j + 1) & lp->tx_ring_mod_mask;
-	}
-	lp->tx_old = j;
-	ll->rdp = LE_C0_TINT | LE_C0_INEA;
-	return 0;
-}
-
-static int lance_tx_buffs_avail(struct lance_private *lp)
-{
-	if (lp->tx_old <= lp->tx_new)
-		return lp->tx_old + lp->tx_ring_mod_mask - lp->tx_new;
-	return lp->tx_old - lp->tx_new - 1;
-}
-
-static irqreturn_t lance_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_regs *ll = lp->ll;
-	int csr0;
-
-	ll->rap = LE_CSR0;		/* LANCE Controller Status */
-	csr0 = ll->rdp;
-
-	if (!(csr0 & LE_C0_INTR))	/* Check if any interrupt has */
-		return IRQ_NONE;	/* been generated by the Lance. */
-
-	/* Acknowledge all the interrupt sources ASAP */
-	ll->rdp = csr0 & ~(LE_C0_INEA | LE_C0_TDMD | LE_C0_STOP | LE_C0_STRT |
-			   LE_C0_INIT);
-
-	if (csr0 & LE_C0_ERR) {
-		/* Clear the error condition */
-		ll->rdp = LE_C0_BABL | LE_C0_ERR | LE_C0_MISS | LE_C0_INEA;
-	}
-
-	if (csr0 & LE_C0_RINT)
-		lance_rx(dev);
-
-	if (csr0 & LE_C0_TINT)
-		lance_tx(dev);
-
-	/* Log misc errors. */
-	if (csr0 & LE_C0_BABL)
-		dev->stats.tx_errors++;       /* Tx babble. */
-	if (csr0 & LE_C0_MISS)
-		dev->stats.rx_errors++;       /* Missed a Rx frame. */
-	if (csr0 & LE_C0_MERR) {
-		netdev_err(dev, "Bus master arbitration failure, status %04x\n",
-			   csr0);
-		/* Restart the chip. */
-		ll->rdp = LE_C0_STRT;
-	}
-
-	if (netif_queue_stopped(dev) && lance_tx_buffs_avail(lp) > 0)
-		netif_wake_queue(dev);
-
-	ll->rap = LE_CSR0;
-	ll->rdp = (LE_C0_BABL | LE_C0_CERR | LE_C0_MISS | LE_C0_MERR |
-		   LE_C0_IDON | LE_C0_INEA);
-	return IRQ_HANDLED;
-}
-
-static int lance_open(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_regs *ll = lp->ll;
-	int ret;
-
-	/* Stop the Lance */
-	ll->rap = LE_CSR0;
-	ll->rdp = LE_C0_STOP;
-
-	/* Install the Interrupt handler */
-	ret = request_irq(IRQ_AMIGA_PORTS, lance_interrupt, IRQF_SHARED,
-			  dev->name, dev);
-	if (ret)
-		return ret;
-
-	load_csrs(lp);
-	lance_init_ring(dev);
-
-	netif_start_queue(dev);
-
-	return init_restart_lance(lp);
-}
-
-static int lance_close(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_regs *ll = lp->ll;
-
-	netif_stop_queue(dev);
-	del_timer_sync(&lp->multicast_timer);
-
-	/* Stop the card */
-	ll->rap = LE_CSR0;
-	ll->rdp = LE_C0_STOP;
-
-	free_irq(IRQ_AMIGA_PORTS, dev);
-	return 0;
-}
-
-static inline int lance_reset(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_regs *ll = lp->ll;
-	int status;
-
-	/* Stop the lance */
-	ll->rap = LE_CSR0;
-	ll->rdp = LE_C0_STOP;
-
-	load_csrs(lp);
-
-	lance_init_ring(dev);
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	netif_start_queue(dev);
-
-	status = init_restart_lance(lp);
-	netdev_dbg(dev, "Lance restart=%d\n", status);
-
-	return status;
-}
-
-static void lance_tx_timeout(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_regs *ll = lp->ll;
-
-	netdev_err(dev, "transmit timed out, status %04x, reset\n", ll->rdp);
-	lance_reset(dev);
-	netif_wake_queue(dev);
-}
-
-static netdev_tx_t lance_start_xmit(struct sk_buff *skb,
-				    struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_regs *ll = lp->ll;
-	volatile struct lance_init_block *ib = lp->init_block;
-	int entry, skblen;
-	int status = NETDEV_TX_OK;
-	unsigned long flags;
-
-	if (skb_padto(skb, ETH_ZLEN))
-		return NETDEV_TX_OK;
-	skblen = max_t(unsigned, skb->len, ETH_ZLEN);
-
-	local_irq_save(flags);
-
-	if (!lance_tx_buffs_avail(lp)) {
-		local_irq_restore(flags);
-		return NETDEV_TX_LOCKED;
-	}
-
-#ifdef DEBUG
-	/* dump the packet */
-	print_hex_dump(KERN_DEBUG, "skb->data: ", DUMP_PREFIX_NONE,
-		       16, 1, skb->data, 64, true);
-#endif
-	entry = lp->tx_new & lp->tx_ring_mod_mask;
-	ib->btx_ring[entry].length = (-skblen) | 0xf000;
-	ib->btx_ring[entry].misc = 0;
-
-	skb_copy_from_linear_data(skb, (void *)&ib->tx_buf[entry][0], skblen);
-
-	/* Now, give the packet to the lance */
-	ib->btx_ring[entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN);
-	lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask;
-	dev->stats.tx_bytes += skblen;
-
-	if (lance_tx_buffs_avail(lp) <= 0)
-		netif_stop_queue(dev);
-
-	/* Kick the lance: transmit now */
-	ll->rdp = LE_C0_INEA | LE_C0_TDMD;
-	dev_kfree_skb(skb);
-
-	local_irq_restore(flags);
-
-	return status;
-}
-
-/* taken from the depca driver */
-static void lance_load_multicast(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
-	volatile u16 *mcast_table = (u16 *)&ib->filter;
-	struct netdev_hw_addr *ha;
-	u32 crc;
-
-	/* set all multicast bits */
-	if (dev->flags & IFF_ALLMULTI) {
-		ib->filter[0] = 0xffffffff;
-		ib->filter[1] = 0xffffffff;
-		return;
-	}
-	/* clear the multicast filter */
-	ib->filter[0] = 0;
-	ib->filter[1] = 0;
-
-	/* Add addresses */
-	netdev_for_each_mc_addr(ha, dev) {
-		crc = ether_crc_le(6, ha->addr);
-		crc = crc >> 26;
-		mcast_table[crc >> 4] |= 1 << (crc & 0xf);
-	}
-}
-
-static void lance_set_multicast(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
-	volatile struct lance_regs *ll = lp->ll;
-
-	if (!netif_running(dev))
-		return;
-
-	if (lp->tx_old != lp->tx_new) {
-		mod_timer(&lp->multicast_timer, jiffies + 4);
-		netif_wake_queue(dev);
-		return;
-	}
-
-	netif_stop_queue(dev);
-
-	ll->rap = LE_CSR0;
-	ll->rdp = LE_C0_STOP;
-	lance_init_ring(dev);
-
-	if (dev->flags & IFF_PROMISC) {
-		ib->mode |= LE_MO_PROM;
-	} else {
-		ib->mode &= ~LE_MO_PROM;
-		lance_load_multicast(dev);
-	}
-	load_csrs(lp);
-	init_restart_lance(lp);
-	netif_wake_queue(dev);
-}
-
-static int __devinit a2065_init_one(struct zorro_dev *z,
-				    const struct zorro_device_id *ent);
-static void __devexit a2065_remove_one(struct zorro_dev *z);
-
-
-static struct zorro_device_id a2065_zorro_tbl[] __devinitdata = {
-	{ ZORRO_PROD_CBM_A2065_1 },
-	{ ZORRO_PROD_CBM_A2065_2 },
-	{ ZORRO_PROD_AMERISTAR_A2065 },
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(zorro, a2065_zorro_tbl);
-
-static struct zorro_driver a2065_driver = {
-	.name		= "a2065",
-	.id_table	= a2065_zorro_tbl,
-	.probe		= a2065_init_one,
-	.remove		= __devexit_p(a2065_remove_one),
-};
-
-static const struct net_device_ops lance_netdev_ops = {
-	.ndo_open		= lance_open,
-	.ndo_stop		= lance_close,
-	.ndo_start_xmit		= lance_start_xmit,
-	.ndo_tx_timeout		= lance_tx_timeout,
-	.ndo_set_multicast_list	= lance_set_multicast,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address	= eth_mac_addr,
-};
-
-static int __devinit a2065_init_one(struct zorro_dev *z,
-				    const struct zorro_device_id *ent)
-{
-	struct net_device *dev;
-	struct lance_private *priv;
-	unsigned long board = z->resource.start;
-	unsigned long base_addr = board + A2065_LANCE;
-	unsigned long mem_start = board + A2065_RAM;
-	struct resource *r1, *r2;
-	int err;
-
-	r1 = request_mem_region(base_addr, sizeof(struct lance_regs),
-				"Am7990");
-	if (!r1)
-		return -EBUSY;
-	r2 = request_mem_region(mem_start, A2065_RAM_SIZE, "RAM");
-	if (!r2) {
-		release_mem_region(base_addr, sizeof(struct lance_regs));
-		return -EBUSY;
-	}
-
-	dev = alloc_etherdev(sizeof(struct lance_private));
-	if (dev == NULL) {
-		release_mem_region(base_addr, sizeof(struct lance_regs));
-		release_mem_region(mem_start, A2065_RAM_SIZE);
-		return -ENOMEM;
-	}
-
-	priv = netdev_priv(dev);
-
-	r1->name = dev->name;
-	r2->name = dev->name;
-
-	dev->dev_addr[0] = 0x00;
-	if (z->id != ZORRO_PROD_AMERISTAR_A2065) {	/* Commodore */
-		dev->dev_addr[1] = 0x80;
-		dev->dev_addr[2] = 0x10;
-	} else {					/* Ameristar */
-		dev->dev_addr[1] = 0x00;
-		dev->dev_addr[2] = 0x9f;
-	}
-	dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff;
-	dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff;
-	dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
-	dev->base_addr = ZTWO_VADDR(base_addr);
-	dev->mem_start = ZTWO_VADDR(mem_start);
-	dev->mem_end = dev->mem_start + A2065_RAM_SIZE;
-
-	priv->ll = (volatile struct lance_regs *)dev->base_addr;
-	priv->init_block = (struct lance_init_block *)dev->mem_start;
-	priv->lance_init_block = (struct lance_init_block *)A2065_RAM;
-	priv->auto_select = 0;
-	priv->busmaster_regval = LE_C3_BSWP;
-
-	priv->lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;
-	priv->lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
-	priv->rx_ring_mod_mask = RX_RING_MOD_MASK;
-	priv->tx_ring_mod_mask = TX_RING_MOD_MASK;
-
-	dev->netdev_ops = &lance_netdev_ops;
-	dev->watchdog_timeo = 5*HZ;
-	dev->dma = 0;
-
-	init_timer(&priv->multicast_timer);
-	priv->multicast_timer.data = (unsigned long) dev;
-	priv->multicast_timer.function =
-		(void (*)(unsigned long))lance_set_multicast;
-
-	err = register_netdev(dev);
-	if (err) {
-		release_mem_region(base_addr, sizeof(struct lance_regs));
-		release_mem_region(mem_start, A2065_RAM_SIZE);
-		free_netdev(dev);
-		return err;
-	}
-	zorro_set_drvdata(z, dev);
-
-	netdev_info(dev, "A2065 at 0x%08lx, Ethernet Address %pM\n",
-		    board, dev->dev_addr);
-
-	return 0;
-}
-
-
-static void __devexit a2065_remove_one(struct zorro_dev *z)
-{
-	struct net_device *dev = zorro_get_drvdata(z);
-
-	unregister_netdev(dev);
-	release_mem_region(ZTWO_PADDR(dev->base_addr),
-			   sizeof(struct lance_regs));
-	release_mem_region(ZTWO_PADDR(dev->mem_start), A2065_RAM_SIZE);
-	free_netdev(dev);
-}
-
-static int __init a2065_init_module(void)
-{
-	return zorro_register_driver(&a2065_driver);
-}
-
-static void __exit a2065_cleanup_module(void)
-{
-	zorro_unregister_driver(&a2065_driver);
-}
-
-module_init(a2065_init_module);
-module_exit(a2065_cleanup_module);
-
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/a2065.h linux-libre-3.2-gnu/drivers/net/a2065.h
--- linux-libre-3.1-gnu/drivers/net/a2065.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/a2065.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,173 +0,0 @@
-/*
- * Amiga Linux/68k A2065 Ethernet Driver
- *
- * (C) Copyright 1995 by Geert Uytterhoeven <geert@linux-m68k.org>
- *
- * ---------------------------------------------------------------------------
- *
- * This program is based on
- *
- *	ariadne.?:	Amiga Linux/68k Ariadne Ethernet Driver
- *			(C) Copyright 1995 by Geert Uytterhoeven,
- *			Peter De Schrijver
- *
- *	lance.c:	An AMD LANCE ethernet driver for linux.
- *			Written 1993-94 by Donald Becker.
- *
- *	Am79C960:	PCnet(tm)-ISA Single-Chip Ethernet Controller
- *			Advanced Micro Devices
- *			Publication #16907, Rev. B, Amendment/0, May 1994
- *
- * ---------------------------------------------------------------------------
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of the Linux
- * distribution for more details.
- *
- * ---------------------------------------------------------------------------
- *
- * The A2065 is a Zorro-II board made by Commodore/Ameristar. It contains:
- *
- *	- an Am7990 Local Area Network Controller for Ethernet (LANCE) with
- *	  both 10BASE-2 (thin coax) and AUI (DB-15) connectors
- */
-
-
-/*
- *		Am7990 Local Area Network Controller for Ethernet (LANCE)
- */
-
-struct lance_regs {
-	unsigned short rdp;		/* Register Data Port */
-	unsigned short rap;		/* Register Address Port */
-};
-
-
-/*
- *		Am7990 Control and Status Registers
- */
-
-#define LE_CSR0		0x0000		/* LANCE Controller Status */
-#define LE_CSR1		0x0001		/* IADR[15:0] */
-#define LE_CSR2		0x0002		/* IADR[23:16] */
-#define LE_CSR3		0x0003		/* Misc */
-
-
-/*
- *		Bit definitions for CSR0 (LANCE Controller Status)
- */
-
-#define LE_C0_ERR	0x8000		/* Error */
-#define LE_C0_BABL	0x4000		/* Babble: Transmitted too many bits */
-#define LE_C0_CERR	0x2000		/* No Heartbeat (10BASE-T) */
-#define LE_C0_MISS	0x1000		/* Missed Frame */
-#define LE_C0_MERR	0x0800		/* Memory Error */
-#define LE_C0_RINT	0x0400		/* Receive Interrupt */
-#define LE_C0_TINT	0x0200		/* Transmit Interrupt */
-#define LE_C0_IDON	0x0100		/* Initialization Done */
-#define LE_C0_INTR	0x0080		/* Interrupt Flag */
-#define LE_C0_INEA	0x0040		/* Interrupt Enable */
-#define LE_C0_RXON	0x0020		/* Receive On */
-#define LE_C0_TXON	0x0010		/* Transmit On */
-#define LE_C0_TDMD	0x0008		/* Transmit Demand */
-#define LE_C0_STOP	0x0004		/* Stop */
-#define LE_C0_STRT	0x0002		/* Start */
-#define LE_C0_INIT	0x0001		/* Initialize */
-
-
-/*
- *		Bit definitions for CSR3
- */
-
-#define LE_C3_BSWP	0x0004		/* Byte Swap
-					   (on for big endian byte order) */
-#define LE_C3_ACON	0x0002		/* ALE Control
-					   (on for active low ALE) */
-#define LE_C3_BCON	0x0001		/* Byte Control */
-
-
-/*
- *		Mode Flags
- */
-
-#define LE_MO_PROM	0x8000		/* Promiscuous Mode */
-#define LE_MO_INTL	0x0040		/* Internal Loopback */
-#define LE_MO_DRTY	0x0020		/* Disable Retry */
-#define LE_MO_FCOLL	0x0010		/* Force Collision */
-#define LE_MO_DXMTFCS	0x0008		/* Disable Transmit CRC */
-#define LE_MO_LOOP	0x0004		/* Loopback Enable */
-#define LE_MO_DTX	0x0002		/* Disable Transmitter */
-#define LE_MO_DRX	0x0001		/* Disable Receiver */
-
-
-struct lance_rx_desc {
-	unsigned short rmd0;        /* low address of packet */
-	unsigned char  rmd1_bits;   /* descriptor bits */
-	unsigned char  rmd1_hadr;   /* high address of packet */
-	short    length;    	    /* This length is 2s complement (negative)!
-				     * Buffer length
-				     */
-	unsigned short mblength;    /* Aactual number of bytes received */
-};
-
-struct lance_tx_desc {
-	unsigned short tmd0;        /* low address of packet */
-	unsigned char  tmd1_bits;   /* descriptor bits */
-	unsigned char  tmd1_hadr;   /* high address of packet */
-	short    length;       	    /* Length is 2s complement (negative)! */
-	unsigned short misc;
-};
-
-
-/*
- *		Receive Flags
- */
-
-#define LE_R1_OWN	0x80		/* LANCE owns the descriptor */
-#define LE_R1_ERR	0x40		/* Error */
-#define LE_R1_FRA	0x20		/* Framing Error */
-#define LE_R1_OFL	0x10		/* Overflow Error */
-#define LE_R1_CRC	0x08		/* CRC Error */
-#define LE_R1_BUF	0x04		/* Buffer Error */
-#define LE_R1_SOP	0x02		/* Start of Packet */
-#define LE_R1_EOP	0x01		/* End of Packet */
-#define LE_R1_POK       0x03		/* Packet is complete: SOP + EOP */
-
-
-/*
- *		Transmit Flags
- */
-
-#define LE_T1_OWN	0x80		/* LANCE owns the descriptor */
-#define LE_T1_ERR	0x40		/* Error */
-#define LE_T1_RES	0x20		/* Reserved,
-					   LANCE writes this with a zero */
-#define LE_T1_EMORE	0x10		/* More than one retry needed */
-#define LE_T1_EONE	0x08		/* One retry needed */
-#define LE_T1_EDEF	0x04		/* Deferred */
-#define LE_T1_SOP	0x02		/* Start of Packet */
-#define LE_T1_EOP	0x01		/* End of Packet */
-#define LE_T1_POK	0x03		/* Packet is complete: SOP + EOP */
-
-
-/*
- *		Error Flags
- */
-
-#define LE_T3_BUF 	0x8000		/* Buffer Error */
-#define LE_T3_UFL 	0x4000		/* Underflow Error */
-#define LE_T3_LCOL 	0x1000		/* Late Collision */
-#define LE_T3_CLOS 	0x0800		/* Loss of Carrier */
-#define LE_T3_RTY 	0x0400		/* Retry Error */
-#define LE_T3_TDR	0x03ff		/* Time Domain Reflectometry */
-
-
-/*
- *		A2065 Expansion Board Structure
- */
-
-#define A2065_LANCE		0x4000
-
-#define A2065_RAM		0x8000
-#define A2065_RAM_SIZE		0x8000
-
diff -druN linux-libre-3.1-gnu/drivers/net/ac3200.c linux-libre-3.2-gnu/drivers/net/ac3200.c
--- linux-libre-3.1-gnu/drivers/net/ac3200.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/ac3200.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,432 +0,0 @@
-/* ac3200.c: A driver for the Ansel Communications EISA ethernet adaptor. */
-/*
-	Written 1993, 1994 by Donald Becker.
-	Copyright 1993 United States Government as represented by the Director,
-	National Security Agency.  This software may only be used and distributed
-	according to the terms of the GNU General Public License as modified by SRC,
-	incorporated herein by reference.
-
-	The author may be reached as becker@scyld.com, or C/O
-	Scyld Computing Corporation
-	410 Severn Ave., Suite 210
-	Annapolis MD 21403
-
-	This is driver for the Ansel Communications Model 3200 EISA Ethernet LAN
-	Adapter.  The programming information is from the users manual, as related
-	by glee@ardnassak.math.clemson.edu.
-
-	Changelog:
-
-	Paul Gortmaker 05/98	: add support for shared mem above 1MB.
-
-  */
-
-static const char version[] =
-	"ac3200.c:v1.01 7/1/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#include <linux/module.h>
-#include <linux/eisa.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include "8390.h"
-
-#define DRV_NAME	"ac3200"
-
-/* Offsets from the base address. */
-#define AC_NIC_BASE	0x00
-#define AC_SA_PROM	0x16			/* The station address PROM. */
-#define AC_ADDR0	0x00			/* Prefix station address values. */
-#define AC_ADDR1	0x40
-#define AC_ADDR2	0x90
-#define AC_ID_PORT	0xC80
-#define AC_EISA_ID	0x0110d305
-#define AC_RESET_PORT	0xC84
-#define AC_RESET	0x00
-#define AC_ENABLE	0x01
-#define AC_CONFIG	0xC90	/* The configuration port. */
-
-#define AC_IO_EXTENT 0x20
-                                /* Actually accessed is:
-								 * AC_NIC_BASE (0-15)
-								 * AC_SA_PROM (0-5)
-								 * AC_ID_PORT (0-3)
-								 * AC_RESET_PORT
-								 * AC_CONFIG
-								 */
-
-/* Decoding of the configuration register. */
-static unsigned char config2irqmap[8] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
-static int addrmap[8] =
-{0xFF0000, 0xFE0000, 0xFD0000, 0xFFF0000, 0xFFE0000, 0xFFC0000,  0xD0000, 0 };
-static const char *port_name[4] = { "10baseT", "invalid", "AUI", "10base2"};
-
-#define config2irq(configval)	config2irqmap[((configval) >> 3) & 7]
-#define config2mem(configval)	addrmap[(configval) & 7]
-#define config2name(configval)	port_name[((configval) >> 6) & 3]
-
-/* First and last 8390 pages. */
-#define AC_START_PG		0x00	/* First page of 8390 TX buffer */
-#define AC_STOP_PG		0x80	/* Last page +1 of the 8390 RX ring */
-
-static int ac_probe1(int ioaddr, struct net_device *dev);
-
-static int ac_open(struct net_device *dev);
-static void ac_reset_8390(struct net_device *dev);
-static void ac_block_input(struct net_device *dev, int count,
-					struct sk_buff *skb, int ring_offset);
-static void ac_block_output(struct net_device *dev, const int count,
-							const unsigned char *buf, const int start_page);
-static void ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-					int ring_page);
-
-static int ac_close_card(struct net_device *dev);
-
-
-/*	Probe for the AC3200.
-
-	The AC3200 can be identified by either the EISA configuration registers,
-	or the unique value in the station address PROM.
-	*/
-
-static int __init do_ac3200_probe(struct net_device *dev)
-{
-	unsigned short ioaddr = dev->base_addr;
-	int irq = dev->irq;
-	int mem_start = dev->mem_start;
-
-	if (ioaddr > 0x1ff)		/* Check a single specified location. */
-		return ac_probe1(ioaddr, dev);
-	else if (ioaddr > 0)		/* Don't probe at all. */
-		return -ENXIO;
-
-	if ( ! EISA_bus)
-		return -ENXIO;
-
-	for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
-		if (ac_probe1(ioaddr, dev) == 0)
-			return 0;
-		dev->irq = irq;
-		dev->mem_start = mem_start;
-	}
-
-	return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init ac3200_probe(int unit)
-{
-	struct net_device *dev = alloc_ei_netdev();
-	int err;
-
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	sprintf(dev->name, "eth%d", unit);
-	netdev_boot_setup_check(dev);
-
-	err = do_ac3200_probe(dev);
-	if (err)
-		goto out;
-	return dev;
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-#endif
-
-static const struct net_device_ops ac_netdev_ops = {
-	.ndo_open		= ac_open,
-	.ndo_stop 		= ac_close_card,
-
-	.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,
-#endif
-};
-
-static int __init ac_probe1(int ioaddr, struct net_device *dev)
-{
-	int i, retval;
-
-	if (!request_region(ioaddr, AC_IO_EXTENT, DRV_NAME))
-		return -EBUSY;
-
-	if (inb_p(ioaddr + AC_ID_PORT) == 0xff) {
-		retval = -ENODEV;
-		goto out;
-	}
-
-	if (inl(ioaddr + AC_ID_PORT) != AC_EISA_ID) {
-		retval = -ENODEV;
-		goto out;
-	}
-
-#ifndef final_version
-	printk(KERN_DEBUG "AC3200 ethercard configuration register is %#02x,"
-		   " EISA ID %02x %02x %02x %02x.\n", inb(ioaddr + AC_CONFIG),
-		   inb(ioaddr + AC_ID_PORT + 0), inb(ioaddr + AC_ID_PORT + 1),
-		   inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3));
-#endif
-
-	for (i = 0; i < 6; i++)
-		dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i);
-
-	printk(KERN_DEBUG "AC3200 in EISA slot %d, node %pM",
-	       ioaddr/0x1000, dev->dev_addr);
-#if 0
-	/* Check the vendor ID/prefix. Redundant after checking the EISA ID */
-	if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0
-		|| inb(ioaddr + AC_SA_PROM + 1) != AC_ADDR1
-		|| inb(ioaddr + AC_SA_PROM + 2) != AC_ADDR2 ) {
-		printk(", not found (invalid prefix).\n");
-		retval = -ENODEV;
-		goto out;
-	}
-#endif
-
-	/* Assign and allocate the interrupt now. */
-	if (dev->irq == 0) {
-		dev->irq = config2irq(inb(ioaddr + AC_CONFIG));
-		printk(", using");
-	} else {
-		dev->irq = irq_canonicalize(dev->irq);
-		printk(", assigning");
-	}
-
-	retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
-	if (retval) {
-		printk (" nothing! Unable to get IRQ %d.\n", dev->irq);
-		goto out;
-	}
-
-	printk(" IRQ %d, %s port\n", dev->irq, port_name[dev->if_port]);
-
-	dev->base_addr = ioaddr;
-
-#ifdef notyet
-	if (dev->mem_start)	{		/* Override the value from the board. */
-		for (i = 0; i < 7; i++)
-			if (addrmap[i] == dev->mem_start)
-				break;
-		if (i >= 7)
-			i = 0;
-		outb((inb(ioaddr + AC_CONFIG) & ~7) | i, ioaddr + AC_CONFIG);
-	}
-#endif
-
-	dev->if_port = inb(ioaddr + AC_CONFIG) >> 6;
-	dev->mem_start = config2mem(inb(ioaddr + AC_CONFIG));
-
-	printk("%s: AC3200 at %#3x with %dkB memory at physical address %#lx.\n",
-			dev->name, ioaddr, AC_STOP_PG/4, dev->mem_start);
-
-	/*
-	 *  BEWARE!! Some dain-bramaged EISA SCUs will allow you to put
-	 *  the card mem within the region covered by `normal' RAM  !!!
-	 *
-	 *  ioremap() will fail in that case.
-	 */
-	ei_status.mem = ioremap(dev->mem_start, AC_STOP_PG*0x100);
-	if (!ei_status.mem) {
-		printk(KERN_ERR "ac3200.c: Unable to remap card memory above 1MB !!\n");
-		printk(KERN_ERR "ac3200.c: Try using EISA SCU to set memory below 1MB.\n");
-		printk(KERN_ERR "ac3200.c: Driver NOT installed.\n");
-		retval = -EINVAL;
-		goto out1;
-	}
-	printk("ac3200.c: remapped %dkB card memory to virtual address %p\n",
-			AC_STOP_PG/4, ei_status.mem);
-
-	dev->mem_start = (unsigned long)ei_status.mem;
-	dev->mem_end = dev->mem_start + (AC_STOP_PG - AC_START_PG)*256;
-
-	ei_status.name = "AC3200";
-	ei_status.tx_start_page = AC_START_PG;
-	ei_status.rx_start_page = AC_START_PG + TX_PAGES;
-	ei_status.stop_page = AC_STOP_PG;
-	ei_status.word16 = 1;
-
-	if (ei_debug > 0)
-		printk(version);
-
-	ei_status.reset_8390 = &ac_reset_8390;
-	ei_status.block_input = &ac_block_input;
-	ei_status.block_output = &ac_block_output;
-	ei_status.get_8390_hdr = &ac_get_8390_hdr;
-
-	dev->netdev_ops = &ac_netdev_ops;
-	NS8390_init(dev, 0);
-
-	retval = register_netdev(dev);
-	if (retval)
-		goto out2;
-	return 0;
-out2:
-	if (ei_status.reg0)
-		iounmap(ei_status.mem);
-out1:
-	free_irq(dev->irq, dev);
-out:
-	release_region(ioaddr, AC_IO_EXTENT);
-	return retval;
-}
-
-static int ac_open(struct net_device *dev)
-{
-#ifdef notyet
-	/* Someday we may enable the IRQ and shared memory here. */
-	int ioaddr = dev->base_addr;
-#endif
-
-	ei_open(dev);
-	return 0;
-}
-
-static void ac_reset_8390(struct net_device *dev)
-{
-	ushort ioaddr = dev->base_addr;
-
-	outb(AC_RESET, ioaddr + AC_RESET_PORT);
-	if (ei_debug > 1) printk("resetting AC3200, t=%ld...", jiffies);
-
-	ei_status.txing = 0;
-	outb(AC_ENABLE, ioaddr + AC_RESET_PORT);
-	if (ei_debug > 1) printk("reset done\n");
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
-   we don't need to be concerned with ring wrap as the header will be at
-   the start of a page, so we optimize accordingly. */
-
-static void
-ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-	void __iomem *hdr_start = ei_status.mem + ((ring_page - AC_START_PG)<<8);
-	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
-}
-
-/*  Block input and output are easy on shared memory ethercards, the only
-	complication is when the ring buffer wraps. */
-
-static void ac_block_input(struct net_device *dev, int count, struct sk_buff *skb,
-						  int ring_offset)
-{
-	void __iomem *start = ei_status.mem + ring_offset - AC_START_PG*256;
-
-	if (ring_offset + count > AC_STOP_PG*256) {
-		/* We must wrap the input move. */
-		int semi_count = AC_STOP_PG*256 - ring_offset;
-		memcpy_fromio(skb->data, start, semi_count);
-		count -= semi_count;
-		memcpy_fromio(skb->data + semi_count,
-				ei_status.mem + TX_PAGES*256, count);
-	} else {
-		memcpy_fromio(skb->data, start, count);
-	}
-}
-
-static void ac_block_output(struct net_device *dev, int count,
-							const unsigned char *buf, int start_page)
-{
-	void __iomem *shmem = ei_status.mem + ((start_page - AC_START_PG)<<8);
-
-	memcpy_toio(shmem, buf, count);
-}
-
-static int ac_close_card(struct net_device *dev)
-{
-	if (ei_debug > 1)
-		printk("%s: Shutting down ethercard.\n", dev->name);
-
-#ifdef notyet
-	/* We should someday disable shared memory and interrupts. */
-	outb(0x00, ioaddr + 6);	/* Disable interrupts. */
-	free_irq(dev->irq, dev);
-#endif
-
-	ei_close(dev);
-	return 0;
-}
-
-#ifdef MODULE
-#define MAX_AC32_CARDS	4	/* Max number of AC32 cards per module */
-static struct net_device *dev_ac32[MAX_AC32_CARDS];
-static int io[MAX_AC32_CARDS];
-static int irq[MAX_AC32_CARDS];
-static int mem[MAX_AC32_CARDS];
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(mem, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es)");
-MODULE_PARM_DESC(irq, "IRQ number(s)");
-MODULE_PARM_DESC(mem, "Memory base address(es)");
-MODULE_DESCRIPTION("Ansel AC3200 EISA ethernet driver");
-MODULE_LICENSE("GPL");
-
-static int __init ac3200_module_init(void)
-{
-	struct net_device *dev;
-	int this_dev, found = 0;
-
-	for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
-		if (io[this_dev] == 0 && this_dev != 0)
-			break;
-		dev = alloc_ei_netdev();
-		if (!dev)
-			break;
-		dev->irq = irq[this_dev];
-		dev->base_addr = io[this_dev];
-		dev->mem_start = mem[this_dev];		/* Currently ignored by driver */
-		if (do_ac3200_probe(dev) == 0) {
-			dev_ac32[found++] = dev;
-			continue;
-		}
-		free_netdev(dev);
-		printk(KERN_WARNING "ac3200.c: No ac3200 card found (i/o = 0x%x).\n", io[this_dev]);
-		break;
-	}
-	if (found)
-		return 0;
-	return -ENXIO;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-	/* Someday free_irq may be in ac_close_card() */
-	free_irq(dev->irq, dev);
-	release_region(dev->base_addr, AC_IO_EXTENT);
-	iounmap(ei_status.mem);
-}
-
-static void __exit ac3200_module_exit(void)
-{
-	int this_dev;
-
-	for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
-		struct net_device *dev = dev_ac32[this_dev];
-		if (dev) {
-			unregister_netdev(dev);
-			cleanup_card(dev);
-			free_netdev(dev);
-		}
-	}
-}
-module_init(ac3200_module_init);
-module_exit(ac3200_module_exit);
-#endif /* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/acenic.c linux-libre-3.2-gnu/drivers/net/acenic.c
--- linux-libre-3.1-gnu/drivers/net/acenic.c	2012-03-19 21:41:38.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/acenic.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3206 +0,0 @@
-/*
- * acenic.c: Linux driver for the Alteon AceNIC Gigabit Ethernet card
- *           and other Tigon based cards.
- *
- * Copyright 1998-2002 by Jes Sorensen, <jes@trained-monkey.org>.
- *
- * Thanks to Alteon and 3Com for providing hardware and documentation
- * enabling me to write this driver.
- *
- * A mailing list for discussing the use of this driver has been
- * setup, please subscribe to the lists if you have any questions
- * about the driver. Send mail to linux-acenic-help@sunsite.auc.dk to
- * see how to subscribe.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Additional credits:
- *   Pete Wyckoff <wyckoff@ca.sandia.gov>: Initial Linux/Alpha and trace
- *       dump support. The trace dump support has not been
- *       integrated yet however.
- *   Troy Benjegerdes: Big Endian (PPC) patches.
- *   Nate Stahl: Better out of memory handling and stats support.
- *   Aman Singla: Nasty race between interrupt handler and tx code dealing
- *                with 'testing the tx_ret_csm and setting tx_full'
- *   David S. Miller <davem@redhat.com>: conversion to new PCI dma mapping
- *                                       infrastructure and Sparc support
- *   Pierrick Pinasseau (CERN): For lending me an Ultra 5 to test the
- *                              driver under Linux/Sparc64
- *   Matt Domsch <Matt_Domsch@dell.com>: Detect Alteon 1000baseT cards
- *                                       ETHTOOL_GDRVINFO support
- *   Chip Salzenberg <chip@valinux.com>: Fix race condition between tx
- *                                       handler and close() cleanup.
- *   Ken Aaker <kdaaker@rchland.vnet.ibm.com>: Correct check for whether
- *                                       memory mapped IO is enabled to
- *                                       make the driver work on RS/6000.
- *   Takayoshi Kouchi <kouchi@hpc.bs1.fc.nec.co.jp>: Identifying problem
- *                                       where the driver would disable
- *                                       bus master mode if it had to disable
- *                                       write and invalidate.
- *   Stephen Hack <stephen_hack@hp.com>: Fixed ace_set_mac_addr for little
- *                                       endian systems.
- *   Val Henson <vhenson@esscom.com>:    Reset Jumbo skb producer and
- *                                       rx producer index when
- *                                       flushing the Jumbo ring.
- *   Hans Grobler <grobh@sun.ac.za>:     Memory leak fixes in the
- *                                       driver init path.
- *   Grant Grundler <grundler@cup.hp.com>: PCI write posting fixes.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/sockios.h>
-#include <linux/firmware.h>
-#include <linux/slab.h>
-#include <linux/prefetch.h>
-#include <linux/if_vlan.h>
-
-#ifdef SIOCETHTOOL
-#include <linux/ethtool.h>
-#endif
-
-#include <net/sock.h>
-#include <net/ip.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-
-
-#define DRV_NAME "acenic"
-
-#undef INDEX_DEBUG
-
-#ifdef CONFIG_ACENIC_OMIT_TIGON_I
-#define ACE_IS_TIGON_I(ap)	0
-#define ACE_TX_RING_ENTRIES(ap)	MAX_TX_RING_ENTRIES
-#else
-#define ACE_IS_TIGON_I(ap)	(ap->version == 1)
-#define ACE_TX_RING_ENTRIES(ap)	ap->tx_ring_entries
-#endif
-
-#ifndef PCI_VENDOR_ID_ALTEON
-#define PCI_VENDOR_ID_ALTEON		0x12ae
-#endif
-#ifndef PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE
-#define PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE  0x0001
-#define PCI_DEVICE_ID_ALTEON_ACENIC_COPPER 0x0002
-#endif
-#ifndef PCI_DEVICE_ID_3COM_3C985
-#define PCI_DEVICE_ID_3COM_3C985	0x0001
-#endif
-#ifndef PCI_VENDOR_ID_NETGEAR
-#define PCI_VENDOR_ID_NETGEAR		0x1385
-#define PCI_DEVICE_ID_NETGEAR_GA620	0x620a
-#endif
-#ifndef PCI_DEVICE_ID_NETGEAR_GA620T
-#define PCI_DEVICE_ID_NETGEAR_GA620T	0x630a
-#endif
-
-
-/*
- * Farallon used the DEC vendor ID by mistake and they seem not
- * to care - stinky!
- */
-#ifndef PCI_DEVICE_ID_FARALLON_PN9000SX
-#define PCI_DEVICE_ID_FARALLON_PN9000SX	0x1a
-#endif
-#ifndef PCI_DEVICE_ID_FARALLON_PN9100T
-#define PCI_DEVICE_ID_FARALLON_PN9100T  0xfa
-#endif
-#ifndef PCI_VENDOR_ID_SGI
-#define PCI_VENDOR_ID_SGI		0x10a9
-#endif
-#ifndef PCI_DEVICE_ID_SGI_ACENIC
-#define PCI_DEVICE_ID_SGI_ACENIC	0x0009
-#endif
-
-static DEFINE_PCI_DEVICE_TABLE(acenic_pci_tbl) = {
-	{ PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE,
-	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
-	{ PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_COPPER,
-	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
-	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C985,
-	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
-	{ PCI_VENDOR_ID_NETGEAR, PCI_DEVICE_ID_NETGEAR_GA620,
-	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
-	{ PCI_VENDOR_ID_NETGEAR, PCI_DEVICE_ID_NETGEAR_GA620T,
-	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
-	/*
-	 * Farallon used the DEC vendor ID on their cards incorrectly,
-	 * then later Alteon's ID.
-	 */
-	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_FARALLON_PN9000SX,
-	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
-	{ PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_FARALLON_PN9100T,
-	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
-	{ PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_ACENIC,
-	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
-
-#define ace_sync_irq(irq)	synchronize_irq(irq)
-
-#ifndef offset_in_page
-#define offset_in_page(ptr)	((unsigned long)(ptr) & ~PAGE_MASK)
-#endif
-
-#define ACE_MAX_MOD_PARMS	8
-#define BOARD_IDX_STATIC	0
-#define BOARD_IDX_OVERFLOW	-1
-
-#include "acenic.h"
-
-/*
- * These must be defined before the firmware is included.
- */
-#define MAX_TEXT_LEN	96*1024
-#define MAX_RODATA_LEN	8*1024
-#define MAX_DATA_LEN	2*1024
-
-#ifndef tigon2FwReleaseLocal
-#define tigon2FwReleaseLocal 0
-#endif
-
-/*
- * This driver currently supports Tigon I and Tigon II based cards
- * including the Alteon AceNIC, the 3Com 3C985[B] and NetGear
- * GA620. The driver should also work on the SGI, DEC and Farallon
- * versions of the card, however I have not been able to test that
- * myself.
- *
- * This card is really neat, it supports receive hardware checksumming
- * and jumbo frames (up to 9000 bytes) and does a lot of work in the
- * firmware. Also the programming interface is quite neat, except for
- * the parts dealing with the i2c eeprom on the card ;-)
- *
- * Using jumbo frames:
- *
- * To enable jumbo frames, simply specify an mtu between 1500 and 9000
- * bytes to ifconfig. Jumbo frames can be enabled or disabled at any time
- * by running `ifconfig eth<X> mtu <MTU>' with <X> being the Ethernet
- * interface number and <MTU> being the MTU value.
- *
- * Module parameters:
- *
- * When compiled as a loadable module, the driver allows for a number
- * of module parameters to be specified. The driver supports the
- * following module parameters:
- *
- *  trace=<val> - Firmware trace level. This requires special traced
- *                firmware to replace the firmware supplied with
- *                the driver - for debugging purposes only.
- *
- *  link=<val>  - Link state. Normally you want to use the default link
- *                parameters set by the driver. This can be used to
- *                override these in case your switch doesn't negotiate
- *                the link properly. Valid values are:
- *         0x0001 - Force half duplex link.
- *         0x0002 - Do not negotiate line speed with the other end.
- *         0x0010 - 10Mbit/sec link.
- *         0x0020 - 100Mbit/sec link.
- *         0x0040 - 1000Mbit/sec link.
- *         0x0100 - Do not negotiate flow control.
- *         0x0200 - Enable RX flow control Y
- *         0x0400 - Enable TX flow control Y (Tigon II NICs only).
- *                Default value is 0x0270, ie. enable link+flow
- *                control negotiation. Negotiating the highest
- *                possible link speed with RX flow control enabled.
- *
- *                When disabling link speed negotiation, only one link
- *                speed is allowed to be specified!
- *
- *  tx_coal_tick=<val> - number of coalescing clock ticks (us) allowed
- *                to wait for more packets to arive before
- *                interrupting the host, from the time the first
- *                packet arrives.
- *
- *  rx_coal_tick=<val> - number of coalescing clock ticks (us) allowed
- *                to wait for more packets to arive in the transmit ring,
- *                before interrupting the host, after transmitting the
- *                first packet in the ring.
- *
- *  max_tx_desc=<val> - maximum number of transmit descriptors
- *                (packets) transmitted before interrupting the host.
- *
- *  max_rx_desc=<val> - maximum number of receive descriptors
- *                (packets) received before interrupting the host.
- *
- *  tx_ratio=<val> - 7 bit value (0 - 63) specifying the split in 64th
- *                increments of the NIC's on board memory to be used for
- *                transmit and receive buffers. For the 1MB NIC app. 800KB
- *                is available, on the 1/2MB NIC app. 300KB is available.
- *                68KB will always be available as a minimum for both
- *                directions. The default value is a 50/50 split.
- *  dis_pci_mem_inval=<val> - disable PCI memory write and invalidate
- *                operations, default (1) is to always disable this as
- *                that is what Alteon does on NT. I have not been able
- *                to measure any real performance differences with
- *                this on my systems. Set <val>=0 if you want to
- *                enable these operations.
- *
- * If you use more than one NIC, specify the parameters for the
- * individual NICs with a comma, ie. trace=0,0x00001fff,0 you want to
- * run tracing on NIC #2 but not on NIC #1 and #3.
- *
- * TODO:
- *
- * - Proper multicast support.
- * - NIC dump support.
- * - More tuning parameters.
- *
- * The mini ring is not used under Linux and I am not sure it makes sense
- * to actually use it.
- *
- * New interrupt handler strategy:
- *
- * The old interrupt handler worked using the traditional method of
- * replacing an skbuff with a new one when a packet arrives. However
- * the rx rings do not need to contain a static number of buffer
- * descriptors, thus it makes sense to move the memory allocation out
- * of the main interrupt handler and do it in a bottom half handler
- * and only allocate new buffers when the number of buffers in the
- * ring is below a certain threshold. In order to avoid starving the
- * NIC under heavy load it is however necessary to force allocation
- * when hitting a minimum threshold. The strategy for alloction is as
- * follows:
- *
- *     RX_LOW_BUF_THRES    - allocate buffers in the bottom half
- *     RX_PANIC_LOW_THRES  - we are very low on buffers, allocate
- *                           the buffers in the interrupt handler
- *     RX_RING_THRES       - maximum number of buffers in the rx ring
- *     RX_MINI_THRES       - maximum number of buffers in the mini ring
- *     RX_JUMBO_THRES      - maximum number of buffers in the jumbo ring
- *
- * One advantagous side effect of this allocation approach is that the
- * entire rx processing can be done without holding any spin lock
- * since the rx rings and registers are totally independent of the tx
- * ring and its registers.  This of course includes the kmalloc's of
- * new skb's. Thus start_xmit can run in parallel with rx processing
- * and the memory allocation on SMP systems.
- *
- * Note that running the skb reallocation in a bottom half opens up
- * another can of races which needs to be handled properly. In
- * particular it can happen that the interrupt handler tries to run
- * the reallocation while the bottom half is either running on another
- * CPU or was interrupted on the same CPU. To get around this the
- * driver uses bitops to prevent the reallocation routines from being
- * reentered.
- *
- * TX handling can also be done without holding any spin lock, wheee
- * this is fun! since tx_ret_csm is only written to by the interrupt
- * handler. The case to be aware of is when shutting down the device
- * and cleaning up where it is necessary to make sure that
- * start_xmit() is not running while this is happening. Well DaveM
- * informs me that this case is already protected against ... bye bye
- * Mr. Spin Lock, it was nice to know you.
- *
- * TX interrupts are now partly disabled so the NIC will only generate
- * TX interrupts for the number of coal ticks, not for the number of
- * TX packets in the queue. This should reduce the number of TX only,
- * ie. when no RX processing is done, interrupts seen.
- */
-
-/*
- * Threshold values for RX buffer allocation - the low water marks for
- * when to start refilling the rings are set to 75% of the ring
- * sizes. It seems to make sense to refill the rings entirely from the
- * intrrupt handler once it gets below the panic threshold, that way
- * we don't risk that the refilling is moved to another CPU when the
- * one running the interrupt handler just got the slab code hot in its
- * cache.
- */
-#define RX_RING_SIZE		72
-#define RX_MINI_SIZE		64
-#define RX_JUMBO_SIZE		48
-
-#define RX_PANIC_STD_THRES	16
-#define RX_PANIC_STD_REFILL	(3*RX_PANIC_STD_THRES)/2
-#define RX_LOW_STD_THRES	(3*RX_RING_SIZE)/4
-#define RX_PANIC_MINI_THRES	12
-#define RX_PANIC_MINI_REFILL	(3*RX_PANIC_MINI_THRES)/2
-#define RX_LOW_MINI_THRES	(3*RX_MINI_SIZE)/4
-#define RX_PANIC_JUMBO_THRES	6
-#define RX_PANIC_JUMBO_REFILL	(3*RX_PANIC_JUMBO_THRES)/2
-#define RX_LOW_JUMBO_THRES	(3*RX_JUMBO_SIZE)/4
-
-
-/*
- * Size of the mini ring entries, basically these just should be big
- * enough to take TCP ACKs
- */
-#define ACE_MINI_SIZE		100
-
-#define ACE_MINI_BUFSIZE	ACE_MINI_SIZE
-#define ACE_STD_BUFSIZE		(ACE_STD_MTU + ETH_HLEN + 4)
-#define ACE_JUMBO_BUFSIZE	(ACE_JUMBO_MTU + ETH_HLEN + 4)
-
-/*
- * There seems to be a magic difference in the effect between 995 and 996
- * but little difference between 900 and 995 ... no idea why.
- *
- * There is now a default set of tuning parameters which is set, depending
- * on whether or not the user enables Jumbo frames. It's assumed that if
- * Jumbo frames are enabled, the user wants optimal tuning for that case.
- */
-#define DEF_TX_COAL		400 /* 996 */
-#define DEF_TX_MAX_DESC		60  /* was 40 */
-#define DEF_RX_COAL		120 /* 1000 */
-#define DEF_RX_MAX_DESC		25
-#define DEF_TX_RATIO		21 /* 24 */
-
-#define DEF_JUMBO_TX_COAL	20
-#define DEF_JUMBO_TX_MAX_DESC	60
-#define DEF_JUMBO_RX_COAL	30
-#define DEF_JUMBO_RX_MAX_DESC	6
-#define DEF_JUMBO_TX_RATIO	21
-
-#if tigon2FwReleaseLocal < 20001118
-/*
- * Standard firmware and early modifications duplicate
- * IRQ load without this flag (coal timer is never reset).
- * Note that with this flag tx_coal should be less than
- * time to xmit full tx ring.
- * 400usec is not so bad for tx ring size of 128.
- */
-#define TX_COAL_INTS_ONLY	1	/* worth it */
-#else
-/*
- * With modified firmware, this is not necessary, but still useful.
- */
-#define TX_COAL_INTS_ONLY	1
-#endif
-
-#define DEF_TRACE		0
-#define DEF_STAT		(2 * TICKS_PER_SEC)
-
-
-static int link_state[ACE_MAX_MOD_PARMS];
-static int trace[ACE_MAX_MOD_PARMS];
-static int tx_coal_tick[ACE_MAX_MOD_PARMS];
-static int rx_coal_tick[ACE_MAX_MOD_PARMS];
-static int max_tx_desc[ACE_MAX_MOD_PARMS];
-static int max_rx_desc[ACE_MAX_MOD_PARMS];
-static int tx_ratio[ACE_MAX_MOD_PARMS];
-static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};
-
-MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver");
-#ifndef CONFIG_ACENIC_OMIT_TIGON_I
-/*(DEBLOBBED)*/
-#endif
-/*(DEBLOBBED)*/
-
-module_param_array_named(link, link_state, int, NULL, 0);
-module_param_array(trace, int, NULL, 0);
-module_param_array(tx_coal_tick, int, NULL, 0);
-module_param_array(max_tx_desc, int, NULL, 0);
-module_param_array(rx_coal_tick, int, NULL, 0);
-module_param_array(max_rx_desc, int, NULL, 0);
-module_param_array(tx_ratio, int, NULL, 0);
-MODULE_PARM_DESC(link, "AceNIC/3C985/NetGear link state");
-MODULE_PARM_DESC(trace, "AceNIC/3C985/NetGear firmware trace level");
-MODULE_PARM_DESC(tx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first tx descriptor arrives");
-MODULE_PARM_DESC(max_tx_desc, "AceNIC/3C985/GA620 max number of transmit descriptors to wait");
-MODULE_PARM_DESC(rx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first rx descriptor arrives");
-MODULE_PARM_DESC(max_rx_desc, "AceNIC/3C985/GA620 max number of receive descriptors to wait");
-MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)");
-
-
-static const char version[] __devinitconst =
-  "acenic.c: v0.92 08/05/2002  Jes Sorensen, linux-acenic@SunSITE.dk\n"
-  "                            http://home.cern.ch/~jes/gige/acenic.html\n";
-
-static int ace_get_settings(struct net_device *, struct ethtool_cmd *);
-static int ace_set_settings(struct net_device *, struct ethtool_cmd *);
-static void ace_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
-
-static const struct ethtool_ops ace_ethtool_ops = {
-	.get_settings = ace_get_settings,
-	.set_settings = ace_set_settings,
-	.get_drvinfo = ace_get_drvinfo,
-};
-
-static void ace_watchdog(struct net_device *dev);
-
-static const struct net_device_ops ace_netdev_ops = {
-	.ndo_open		= ace_open,
-	.ndo_stop		= ace_close,
-	.ndo_tx_timeout		= ace_watchdog,
-	.ndo_get_stats		= ace_get_stats,
-	.ndo_start_xmit		= ace_start_xmit,
-	.ndo_set_multicast_list	= ace_set_multicast_list,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address	= ace_set_mac_addr,
-	.ndo_change_mtu		= ace_change_mtu,
-};
-
-static int __devinit acenic_probe_one(struct pci_dev *pdev,
-		const struct pci_device_id *id)
-{
-	struct net_device *dev;
-	struct ace_private *ap;
-	static int boards_found;
-
-	dev = alloc_etherdev(sizeof(struct ace_private));
-	if (dev == NULL) {
-		printk(KERN_ERR "acenic: Unable to allocate "
-		       "net_device structure!\n");
-		return -ENOMEM;
-	}
-
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-	ap = netdev_priv(dev);
-	ap->pdev = pdev;
-	ap->name = pci_name(pdev);
-
-	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
-	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-
-	dev->watchdog_timeo = 5*HZ;
-
-	dev->netdev_ops = &ace_netdev_ops;
-	SET_ETHTOOL_OPS(dev, &ace_ethtool_ops);
-
-	/* we only display this string ONCE */
-	if (!boards_found)
-		printk(version);
-
-	if (pci_enable_device(pdev))
-		goto fail_free_netdev;
-
-	/*
-	 * Enable master mode before we start playing with the
-	 * pci_command word since pci_set_master() will modify
-	 * it.
-	 */
-	pci_set_master(pdev);
-
-	pci_read_config_word(pdev, PCI_COMMAND, &ap->pci_command);
-
-	/* OpenFirmware on Mac's does not set this - DOH.. */
-	if (!(ap->pci_command & PCI_COMMAND_MEMORY)) {
-		printk(KERN_INFO "%s: Enabling PCI Memory Mapped "
-		       "access - was not enabled by BIOS/Firmware\n",
-		       ap->name);
-		ap->pci_command = ap->pci_command | PCI_COMMAND_MEMORY;
-		pci_write_config_word(ap->pdev, PCI_COMMAND,
-				      ap->pci_command);
-		wmb();
-	}
-
-	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &ap->pci_latency);
-	if (ap->pci_latency <= 0x40) {
-		ap->pci_latency = 0x40;
-		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, ap->pci_latency);
-	}
-
-	/*
-	 * Remap the regs into kernel space - this is abuse of
-	 * dev->base_addr since it was means for I/O port
-	 * addresses but who gives a damn.
-	 */
-	dev->base_addr = pci_resource_start(pdev, 0);
-	ap->regs = ioremap(dev->base_addr, 0x4000);
-	if (!ap->regs) {
-		printk(KERN_ERR "%s:  Unable to map I/O register, "
-		       "AceNIC %i will be disabled.\n",
-		       ap->name, boards_found);
-		goto fail_free_netdev;
-	}
-
-	switch(pdev->vendor) {
-	case PCI_VENDOR_ID_ALTEON:
-		if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) {
-			printk(KERN_INFO "%s: Farallon PN9100-T ",
-			       ap->name);
-		} else {
-			printk(KERN_INFO "%s: Alteon AceNIC ",
-			       ap->name);
-		}
-		break;
-	case PCI_VENDOR_ID_3COM:
-		printk(KERN_INFO "%s: 3Com 3C985 ", ap->name);
-		break;
-	case PCI_VENDOR_ID_NETGEAR:
-		printk(KERN_INFO "%s: NetGear GA620 ", ap->name);
-		break;
-	case PCI_VENDOR_ID_DEC:
-		if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX) {
-			printk(KERN_INFO "%s: Farallon PN9000-SX ",
-			       ap->name);
-			break;
-		}
-	case PCI_VENDOR_ID_SGI:
-		printk(KERN_INFO "%s: SGI AceNIC ", ap->name);
-		break;
-	default:
-		printk(KERN_INFO "%s: Unknown AceNIC ", ap->name);
-		break;
-	}
-
-	printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr);
-	printk("irq %d\n", pdev->irq);
-
-#ifdef CONFIG_ACENIC_OMIT_TIGON_I
-	if ((readl(&ap->regs->HostCtrl) >> 28) == 4) {
-		printk(KERN_ERR "%s: Driver compiled without Tigon I"
-		       " support - NIC disabled\n", dev->name);
-		goto fail_uninit;
-	}
-#endif
-
-	if (ace_allocate_descriptors(dev))
-		goto fail_free_netdev;
-
-#ifdef MODULE
-	if (boards_found >= ACE_MAX_MOD_PARMS)
-		ap->board_idx = BOARD_IDX_OVERFLOW;
-	else
-		ap->board_idx = boards_found;
-#else
-	ap->board_idx = BOARD_IDX_STATIC;
-#endif
-
-	if (ace_init(dev))
-		goto fail_free_netdev;
-
-	if (register_netdev(dev)) {
-		printk(KERN_ERR "acenic: device registration failed\n");
-		goto fail_uninit;
-	}
-	ap->name = dev->name;
-
-	if (ap->pci_using_dac)
-		dev->features |= NETIF_F_HIGHDMA;
-
-	pci_set_drvdata(pdev, dev);
-
-	boards_found++;
-	return 0;
-
- fail_uninit:
-	ace_init_cleanup(dev);
- fail_free_netdev:
-	free_netdev(dev);
-	return -ENODEV;
-}
-
-static void __devexit acenic_remove_one(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-	short i;
-
-	unregister_netdev(dev);
-
-	writel(readl(&regs->CpuCtrl) | CPU_HALT, &regs->CpuCtrl);
-	if (ap->version >= 2)
-		writel(readl(&regs->CpuBCtrl) | CPU_HALT, &regs->CpuBCtrl);
-
-	/*
-	 * This clears any pending interrupts
-	 */
-	writel(1, &regs->Mb0Lo);
-	readl(&regs->CpuCtrl);	/* flush */
-
-	/*
-	 * Make sure no other CPUs are processing interrupts
-	 * on the card before the buffers are being released.
-	 * Otherwise one might experience some `interesting'
-	 * effects.
-	 *
-	 * Then release the RX buffers - jumbo buffers were
-	 * already released in ace_close().
-	 */
-	ace_sync_irq(dev->irq);
-
-	for (i = 0; i < RX_STD_RING_ENTRIES; i++) {
-		struct sk_buff *skb = ap->skb->rx_std_skbuff[i].skb;
-
-		if (skb) {
-			struct ring_info *ringp;
-			dma_addr_t mapping;
-
-			ringp = &ap->skb->rx_std_skbuff[i];
-			mapping = dma_unmap_addr(ringp, mapping);
-			pci_unmap_page(ap->pdev, mapping,
-				       ACE_STD_BUFSIZE,
-				       PCI_DMA_FROMDEVICE);
-
-			ap->rx_std_ring[i].size = 0;
-			ap->skb->rx_std_skbuff[i].skb = NULL;
-			dev_kfree_skb(skb);
-		}
-	}
-
-	if (ap->version >= 2) {
-		for (i = 0; i < RX_MINI_RING_ENTRIES; i++) {
-			struct sk_buff *skb = ap->skb->rx_mini_skbuff[i].skb;
-
-			if (skb) {
-				struct ring_info *ringp;
-				dma_addr_t mapping;
-
-				ringp = &ap->skb->rx_mini_skbuff[i];
-				mapping = dma_unmap_addr(ringp,mapping);
-				pci_unmap_page(ap->pdev, mapping,
-					       ACE_MINI_BUFSIZE,
-					       PCI_DMA_FROMDEVICE);
-
-				ap->rx_mini_ring[i].size = 0;
-				ap->skb->rx_mini_skbuff[i].skb = NULL;
-				dev_kfree_skb(skb);
-			}
-		}
-	}
-
-	for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++) {
-		struct sk_buff *skb = ap->skb->rx_jumbo_skbuff[i].skb;
-		if (skb) {
-			struct ring_info *ringp;
-			dma_addr_t mapping;
-
-			ringp = &ap->skb->rx_jumbo_skbuff[i];
-			mapping = dma_unmap_addr(ringp, mapping);
-			pci_unmap_page(ap->pdev, mapping,
-				       ACE_JUMBO_BUFSIZE,
-				       PCI_DMA_FROMDEVICE);
-
-			ap->rx_jumbo_ring[i].size = 0;
-			ap->skb->rx_jumbo_skbuff[i].skb = NULL;
-			dev_kfree_skb(skb);
-		}
-	}
-
-	ace_init_cleanup(dev);
-	free_netdev(dev);
-}
-
-static struct pci_driver acenic_pci_driver = {
-	.name		= "acenic",
-	.id_table	= acenic_pci_tbl,
-	.probe		= acenic_probe_one,
-	.remove		= __devexit_p(acenic_remove_one),
-};
-
-static int __init acenic_init(void)
-{
-	return pci_register_driver(&acenic_pci_driver);
-}
-
-static void __exit acenic_exit(void)
-{
-	pci_unregister_driver(&acenic_pci_driver);
-}
-
-module_init(acenic_init);
-module_exit(acenic_exit);
-
-static void ace_free_descriptors(struct net_device *dev)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	int size;
-
-	if (ap->rx_std_ring != NULL) {
-		size = (sizeof(struct rx_desc) *
-			(RX_STD_RING_ENTRIES +
-			 RX_JUMBO_RING_ENTRIES +
-			 RX_MINI_RING_ENTRIES +
-			 RX_RETURN_RING_ENTRIES));
-		pci_free_consistent(ap->pdev, size, ap->rx_std_ring,
-				    ap->rx_ring_base_dma);
-		ap->rx_std_ring = NULL;
-		ap->rx_jumbo_ring = NULL;
-		ap->rx_mini_ring = NULL;
-		ap->rx_return_ring = NULL;
-	}
-	if (ap->evt_ring != NULL) {
-		size = (sizeof(struct event) * EVT_RING_ENTRIES);
-		pci_free_consistent(ap->pdev, size, ap->evt_ring,
-				    ap->evt_ring_dma);
-		ap->evt_ring = NULL;
-	}
-	if (ap->tx_ring != NULL && !ACE_IS_TIGON_I(ap)) {
-		size = (sizeof(struct tx_desc) * MAX_TX_RING_ENTRIES);
-		pci_free_consistent(ap->pdev, size, ap->tx_ring,
-				    ap->tx_ring_dma);
-	}
-	ap->tx_ring = NULL;
-
-	if (ap->evt_prd != NULL) {
-		pci_free_consistent(ap->pdev, sizeof(u32),
-				    (void *)ap->evt_prd, ap->evt_prd_dma);
-		ap->evt_prd = NULL;
-	}
-	if (ap->rx_ret_prd != NULL) {
-		pci_free_consistent(ap->pdev, sizeof(u32),
-				    (void *)ap->rx_ret_prd,
-				    ap->rx_ret_prd_dma);
-		ap->rx_ret_prd = NULL;
-	}
-	if (ap->tx_csm != NULL) {
-		pci_free_consistent(ap->pdev, sizeof(u32),
-				    (void *)ap->tx_csm, ap->tx_csm_dma);
-		ap->tx_csm = NULL;
-	}
-}
-
-
-static int ace_allocate_descriptors(struct net_device *dev)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	int size;
-
-	size = (sizeof(struct rx_desc) *
-		(RX_STD_RING_ENTRIES +
-		 RX_JUMBO_RING_ENTRIES +
-		 RX_MINI_RING_ENTRIES +
-		 RX_RETURN_RING_ENTRIES));
-
-	ap->rx_std_ring = pci_alloc_consistent(ap->pdev, size,
-					       &ap->rx_ring_base_dma);
-	if (ap->rx_std_ring == NULL)
-		goto fail;
-
-	ap->rx_jumbo_ring = ap->rx_std_ring + RX_STD_RING_ENTRIES;
-	ap->rx_mini_ring = ap->rx_jumbo_ring + RX_JUMBO_RING_ENTRIES;
-	ap->rx_return_ring = ap->rx_mini_ring + RX_MINI_RING_ENTRIES;
-
-	size = (sizeof(struct event) * EVT_RING_ENTRIES);
-
-	ap->evt_ring = pci_alloc_consistent(ap->pdev, size, &ap->evt_ring_dma);
-
-	if (ap->evt_ring == NULL)
-		goto fail;
-
-	/*
-	 * Only allocate a host TX ring for the Tigon II, the Tigon I
-	 * has to use PCI registers for this ;-(
-	 */
-	if (!ACE_IS_TIGON_I(ap)) {
-		size = (sizeof(struct tx_desc) * MAX_TX_RING_ENTRIES);
-
-		ap->tx_ring = pci_alloc_consistent(ap->pdev, size,
-						   &ap->tx_ring_dma);
-
-		if (ap->tx_ring == NULL)
-			goto fail;
-	}
-
-	ap->evt_prd = pci_alloc_consistent(ap->pdev, sizeof(u32),
-					   &ap->evt_prd_dma);
-	if (ap->evt_prd == NULL)
-		goto fail;
-
-	ap->rx_ret_prd = pci_alloc_consistent(ap->pdev, sizeof(u32),
-					      &ap->rx_ret_prd_dma);
-	if (ap->rx_ret_prd == NULL)
-		goto fail;
-
-	ap->tx_csm = pci_alloc_consistent(ap->pdev, sizeof(u32),
-					  &ap->tx_csm_dma);
-	if (ap->tx_csm == NULL)
-		goto fail;
-
-	return 0;
-
-fail:
-	/* Clean up. */
-	ace_init_cleanup(dev);
-	return 1;
-}
-
-
-/*
- * Generic cleanup handling data allocated during init. Used when the
- * module is unloaded or if an error occurs during initialization
- */
-static void ace_init_cleanup(struct net_device *dev)
-{
-	struct ace_private *ap;
-
-	ap = netdev_priv(dev);
-
-	ace_free_descriptors(dev);
-
-	if (ap->info)
-		pci_free_consistent(ap->pdev, sizeof(struct ace_info),
-				    ap->info, ap->info_dma);
-	kfree(ap->skb);
-	kfree(ap->trace_buf);
-
-	if (dev->irq)
-		free_irq(dev->irq, dev);
-
-	iounmap(ap->regs);
-}
-
-
-/*
- * Commands are considered to be slow.
- */
-static inline void ace_issue_cmd(struct ace_regs __iomem *regs, struct cmd *cmd)
-{
-	u32 idx;
-
-	idx = readl(&regs->CmdPrd);
-
-	writel(*(u32 *)(cmd), &regs->CmdRng[idx]);
-	idx = (idx + 1) % CMD_RING_ENTRIES;
-
-	writel(idx, &regs->CmdPrd);
-}
-
-
-static int __devinit ace_init(struct net_device *dev)
-{
-	struct ace_private *ap;
-	struct ace_regs __iomem *regs;
-	struct ace_info *info = NULL;
-	struct pci_dev *pdev;
-	unsigned long myjif;
-	u64 tmp_ptr;
-	u32 tig_ver, mac1, mac2, tmp, pci_state;
-	int board_idx, ecode = 0;
-	short i;
-	unsigned char cache_size;
-
-	ap = netdev_priv(dev);
-	regs = ap->regs;
-
-	board_idx = ap->board_idx;
-
-	/*
-	 * aman@sgi.com - its useful to do a NIC reset here to
-	 * address the `Firmware not running' problem subsequent
-	 * to any crashes involving the NIC
-	 */
-	writel(HW_RESET | (HW_RESET << 24), &regs->HostCtrl);
-	readl(&regs->HostCtrl);		/* PCI write posting */
-	udelay(5);
-
-	/*
-	 * Don't access any other registers before this point!
-	 */
-#ifdef __BIG_ENDIAN
-	/*
-	 * This will most likely need BYTE_SWAP once we switch
-	 * to using __raw_writel()
-	 */
-	writel((WORD_SWAP | CLR_INT | ((WORD_SWAP | CLR_INT) << 24)),
-	       &regs->HostCtrl);
-#else
-	writel((CLR_INT | WORD_SWAP | ((CLR_INT | WORD_SWAP) << 24)),
-	       &regs->HostCtrl);
-#endif
-	readl(&regs->HostCtrl);		/* PCI write posting */
-
-	/*
-	 * Stop the NIC CPU and clear pending interrupts
-	 */
-	writel(readl(&regs->CpuCtrl) | CPU_HALT, &regs->CpuCtrl);
-	readl(&regs->CpuCtrl);		/* PCI write posting */
-	writel(0, &regs->Mb0Lo);
-
-	tig_ver = readl(&regs->HostCtrl) >> 28;
-
-	switch(tig_ver){
-#ifndef CONFIG_ACENIC_OMIT_TIGON_I
-	case 4:
-	case 5:
-		printk(KERN_INFO "  Tigon I  (Rev. %i), Firmware: %i.%i.%i, ",
-		       tig_ver, ap->firmware_major, ap->firmware_minor,
-		       ap->firmware_fix);
-		writel(0, &regs->LocalCtrl);
-		ap->version = 1;
-		ap->tx_ring_entries = TIGON_I_TX_RING_ENTRIES;
-		break;
-#endif
-	case 6:
-		printk(KERN_INFO "  Tigon II (Rev. %i), Firmware: %i.%i.%i, ",
-		       tig_ver, ap->firmware_major, ap->firmware_minor,
-		       ap->firmware_fix);
-		writel(readl(&regs->CpuBCtrl) | CPU_HALT, &regs->CpuBCtrl);
-		readl(&regs->CpuBCtrl);		/* PCI write posting */
-		/*
-		 * The SRAM bank size does _not_ indicate the amount
-		 * of memory on the card, it controls the _bank_ size!
-		 * Ie. a 1MB AceNIC will have two banks of 512KB.
-		 */
-		writel(SRAM_BANK_512K, &regs->LocalCtrl);
-		writel(SYNC_SRAM_TIMING, &regs->MiscCfg);
-		ap->version = 2;
-		ap->tx_ring_entries = MAX_TX_RING_ENTRIES;
-		break;
-	default:
-		printk(KERN_WARNING "  Unsupported Tigon version detected "
-		       "(%i)\n", tig_ver);
-		ecode = -ENODEV;
-		goto init_error;
-	}
-
-	/*
-	 * ModeStat _must_ be set after the SRAM settings as this change
-	 * seems to corrupt the ModeStat and possible other registers.
-	 * The SRAM settings survive resets and setting it to the same
-	 * value a second time works as well. This is what caused the
-	 * `Firmware not running' problem on the Tigon II.
-	 */
-#ifdef __BIG_ENDIAN
-	writel(ACE_BYTE_SWAP_DMA | ACE_WARN | ACE_FATAL | ACE_BYTE_SWAP_BD |
-	       ACE_WORD_SWAP_BD | ACE_NO_JUMBO_FRAG, &regs->ModeStat);
-#else
-	writel(ACE_BYTE_SWAP_DMA | ACE_WARN | ACE_FATAL |
-	       ACE_WORD_SWAP_BD | ACE_NO_JUMBO_FRAG, &regs->ModeStat);
-#endif
-	readl(&regs->ModeStat);		/* PCI write posting */
-
-	mac1 = 0;
-	for(i = 0; i < 4; i++) {
-		int t;
-
-		mac1 = mac1 << 8;
-		t = read_eeprom_byte(dev, 0x8c+i);
-		if (t < 0) {
-			ecode = -EIO;
-			goto init_error;
-		} else
-			mac1 |= (t & 0xff);
-	}
-	mac2 = 0;
-	for(i = 4; i < 8; i++) {
-		int t;
-
-		mac2 = mac2 << 8;
-		t = read_eeprom_byte(dev, 0x8c+i);
-		if (t < 0) {
-			ecode = -EIO;
-			goto init_error;
-		} else
-			mac2 |= (t & 0xff);
-	}
-
-	writel(mac1, &regs->MacAddrHi);
-	writel(mac2, &regs->MacAddrLo);
-
-	dev->dev_addr[0] = (mac1 >> 8) & 0xff;
-	dev->dev_addr[1] = mac1 & 0xff;
-	dev->dev_addr[2] = (mac2 >> 24) & 0xff;
-	dev->dev_addr[3] = (mac2 >> 16) & 0xff;
-	dev->dev_addr[4] = (mac2 >> 8) & 0xff;
-	dev->dev_addr[5] = mac2 & 0xff;
-
-	printk("MAC: %pM\n", dev->dev_addr);
-
-	/*
-	 * Looks like this is necessary to deal with on all architectures,
-	 * even this %$#%$# N440BX Intel based thing doesn't get it right.
-	 * Ie. having two NICs in the machine, one will have the cache
-	 * line set at boot time, the other will not.
-	 */
-	pdev = ap->pdev;
-	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_size);
-	cache_size <<= 2;
-	if (cache_size != SMP_CACHE_BYTES) {
-		printk(KERN_INFO "  PCI cache line size set incorrectly "
-		       "(%i bytes) by BIOS/FW, ", cache_size);
-		if (cache_size > SMP_CACHE_BYTES)
-			printk("expecting %i\n", SMP_CACHE_BYTES);
-		else {
-			printk("correcting to %i\n", SMP_CACHE_BYTES);
-			pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE,
-					      SMP_CACHE_BYTES >> 2);
-		}
-	}
-
-	pci_state = readl(&regs->PciState);
-	printk(KERN_INFO "  PCI bus width: %i bits, speed: %iMHz, "
-	       "latency: %i clks\n",
-	       	(pci_state & PCI_32BIT) ? 32 : 64,
-		(pci_state & PCI_66MHZ) ? 66 : 33,
-		ap->pci_latency);
-
-	/*
-	 * Set the max DMA transfer size. Seems that for most systems
-	 * the performance is better when no MAX parameter is
-	 * set. However for systems enabling PCI write and invalidate,
-	 * DMA writes must be set to the L1 cache line size to get
-	 * optimal performance.
-	 *
-	 * The default is now to turn the PCI write and invalidate off
-	 * - that is what Alteon does for NT.
-	 */
-	tmp = READ_CMD_MEM | WRITE_CMD_MEM;
-	if (ap->version >= 2) {
-		tmp |= (MEM_READ_MULTIPLE | (pci_state & PCI_66MHZ));
-		/*
-		 * Tuning parameters only supported for 8 cards
-		 */
-		if (board_idx == BOARD_IDX_OVERFLOW ||
-		    dis_pci_mem_inval[board_idx]) {
-			if (ap->pci_command & PCI_COMMAND_INVALIDATE) {
-				ap->pci_command &= ~PCI_COMMAND_INVALIDATE;
-				pci_write_config_word(pdev, PCI_COMMAND,
-						      ap->pci_command);
-				printk(KERN_INFO "  Disabling PCI memory "
-				       "write and invalidate\n");
-			}
-		} else if (ap->pci_command & PCI_COMMAND_INVALIDATE) {
-			printk(KERN_INFO "  PCI memory write & invalidate "
-			       "enabled by BIOS, enabling counter measures\n");
-
-			switch(SMP_CACHE_BYTES) {
-			case 16:
-				tmp |= DMA_WRITE_MAX_16;
-				break;
-			case 32:
-				tmp |= DMA_WRITE_MAX_32;
-				break;
-			case 64:
-				tmp |= DMA_WRITE_MAX_64;
-				break;
-			case 128:
-				tmp |= DMA_WRITE_MAX_128;
-				break;
-			default:
-				printk(KERN_INFO "  Cache line size %i not "
-				       "supported, PCI write and invalidate "
-				       "disabled\n", SMP_CACHE_BYTES);
-				ap->pci_command &= ~PCI_COMMAND_INVALIDATE;
-				pci_write_config_word(pdev, PCI_COMMAND,
-						      ap->pci_command);
-			}
-		}
-	}
-
-#ifdef __sparc__
-	/*
-	 * On this platform, we know what the best dma settings
-	 * are.  We use 64-byte maximum bursts, because if we
-	 * burst larger than the cache line size (or even cross
-	 * a 64byte boundary in a single burst) the UltraSparc
-	 * PCI controller will disconnect at 64-byte multiples.
-	 *
-	 * Read-multiple will be properly enabled above, and when
-	 * set will give the PCI controller proper hints about
-	 * prefetching.
-	 */
-	tmp &= ~DMA_READ_WRITE_MASK;
-	tmp |= DMA_READ_MAX_64;
-	tmp |= DMA_WRITE_MAX_64;
-#endif
-#ifdef __alpha__
-	tmp &= ~DMA_READ_WRITE_MASK;
-	tmp |= DMA_READ_MAX_128;
-	/*
-	 * All the docs say MUST NOT. Well, I did.
-	 * Nothing terrible happens, if we load wrong size.
-	 * Bit w&i still works better!
-	 */
-	tmp |= DMA_WRITE_MAX_128;
-#endif
-	writel(tmp, &regs->PciState);
-
-#if 0
-	/*
-	 * The Host PCI bus controller driver has to set FBB.
-	 * If all devices on that PCI bus support FBB, then the controller
-	 * can enable FBB support in the Host PCI Bus controller (or on
-	 * the PCI-PCI bridge if that applies).
-	 * -ggg
-	 */
-	/*
-	 * I have received reports from people having problems when this
-	 * bit is enabled.
-	 */
-	if (!(ap->pci_command & PCI_COMMAND_FAST_BACK)) {
-		printk(KERN_INFO "  Enabling PCI Fast Back to Back\n");
-		ap->pci_command |= PCI_COMMAND_FAST_BACK;
-		pci_write_config_word(pdev, PCI_COMMAND, ap->pci_command);
-	}
-#endif
-
-	/*
-	 * Configure DMA attributes.
-	 */
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-		ap->pci_using_dac = 1;
-	} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
-		ap->pci_using_dac = 0;
-	} else {
-		ecode = -ENODEV;
-		goto init_error;
-	}
-
-	/*
-	 * Initialize the generic info block and the command+event rings
-	 * and the control blocks for the transmit and receive rings
-	 * as they need to be setup once and for all.
-	 */
-	if (!(info = pci_alloc_consistent(ap->pdev, sizeof(struct ace_info),
-					  &ap->info_dma))) {
-		ecode = -EAGAIN;
-		goto init_error;
-	}
-	ap->info = info;
-
-	/*
-	 * Get the memory for the skb rings.
-	 */
-	if (!(ap->skb = kmalloc(sizeof(struct ace_skb), GFP_KERNEL))) {
-		ecode = -EAGAIN;
-		goto init_error;
-	}
-
-	ecode = request_irq(pdev->irq, ace_interrupt, IRQF_SHARED,
-			    DRV_NAME, dev);
-	if (ecode) {
-		printk(KERN_WARNING "%s: Requested IRQ %d is busy\n",
-		       DRV_NAME, pdev->irq);
-		goto init_error;
-	} else
-		dev->irq = pdev->irq;
-
-#ifdef INDEX_DEBUG
-	spin_lock_init(&ap->debug_lock);
-	ap->last_tx = ACE_TX_RING_ENTRIES(ap) - 1;
-	ap->last_std_rx = 0;
-	ap->last_mini_rx = 0;
-#endif
-
-	memset(ap->info, 0, sizeof(struct ace_info));
-	memset(ap->skb, 0, sizeof(struct ace_skb));
-
-	ecode = ace_load_firmware(dev);
-	if (ecode)
-		goto init_error;
-
-	ap->fw_running = 0;
-
-	tmp_ptr = ap->info_dma;
-	writel(tmp_ptr >> 32, &regs->InfoPtrHi);
-	writel(tmp_ptr & 0xffffffff, &regs->InfoPtrLo);
-
-	memset(ap->evt_ring, 0, EVT_RING_ENTRIES * sizeof(struct event));
-
-	set_aceaddr(&info->evt_ctrl.rngptr, ap->evt_ring_dma);
-	info->evt_ctrl.flags = 0;
-
-	*(ap->evt_prd) = 0;
-	wmb();
-	set_aceaddr(&info->evt_prd_ptr, ap->evt_prd_dma);
-	writel(0, &regs->EvtCsm);
-
-	set_aceaddr(&info->cmd_ctrl.rngptr, 0x100);
-	info->cmd_ctrl.flags = 0;
-	info->cmd_ctrl.max_len = 0;
-
-	for (i = 0; i < CMD_RING_ENTRIES; i++)
-		writel(0, &regs->CmdRng[i]);
-
-	writel(0, &regs->CmdPrd);
-	writel(0, &regs->CmdCsm);
-
-	tmp_ptr = ap->info_dma;
-	tmp_ptr += (unsigned long) &(((struct ace_info *)0)->s.stats);
-	set_aceaddr(&info->stats2_ptr, (dma_addr_t) tmp_ptr);
-
-	set_aceaddr(&info->rx_std_ctrl.rngptr, ap->rx_ring_base_dma);
-	info->rx_std_ctrl.max_len = ACE_STD_BUFSIZE;
-	info->rx_std_ctrl.flags =
-	  RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | RCB_FLG_VLAN_ASSIST;
-
-	memset(ap->rx_std_ring, 0,
-	       RX_STD_RING_ENTRIES * sizeof(struct rx_desc));
-
-	for (i = 0; i < RX_STD_RING_ENTRIES; i++)
-		ap->rx_std_ring[i].flags = BD_FLG_TCP_UDP_SUM;
-
-	ap->rx_std_skbprd = 0;
-	atomic_set(&ap->cur_rx_bufs, 0);
-
-	set_aceaddr(&info->rx_jumbo_ctrl.rngptr,
-		    (ap->rx_ring_base_dma +
-		     (sizeof(struct rx_desc) * RX_STD_RING_ENTRIES)));
-	info->rx_jumbo_ctrl.max_len = 0;
-	info->rx_jumbo_ctrl.flags =
-	  RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | RCB_FLG_VLAN_ASSIST;
-
-	memset(ap->rx_jumbo_ring, 0,
-	       RX_JUMBO_RING_ENTRIES * sizeof(struct rx_desc));
-
-	for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++)
-		ap->rx_jumbo_ring[i].flags = BD_FLG_TCP_UDP_SUM | BD_FLG_JUMBO;
-
-	ap->rx_jumbo_skbprd = 0;
-	atomic_set(&ap->cur_jumbo_bufs, 0);
-
-	memset(ap->rx_mini_ring, 0,
-	       RX_MINI_RING_ENTRIES * sizeof(struct rx_desc));
-
-	if (ap->version >= 2) {
-		set_aceaddr(&info->rx_mini_ctrl.rngptr,
-			    (ap->rx_ring_base_dma +
-			     (sizeof(struct rx_desc) *
-			      (RX_STD_RING_ENTRIES +
-			       RX_JUMBO_RING_ENTRIES))));
-		info->rx_mini_ctrl.max_len = ACE_MINI_SIZE;
-		info->rx_mini_ctrl.flags =
-		  RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR|RCB_FLG_VLAN_ASSIST;
-
-		for (i = 0; i < RX_MINI_RING_ENTRIES; i++)
-			ap->rx_mini_ring[i].flags =
-				BD_FLG_TCP_UDP_SUM | BD_FLG_MINI;
-	} else {
-		set_aceaddr(&info->rx_mini_ctrl.rngptr, 0);
-		info->rx_mini_ctrl.flags = RCB_FLG_RNG_DISABLE;
-		info->rx_mini_ctrl.max_len = 0;
-	}
-
-	ap->rx_mini_skbprd = 0;
-	atomic_set(&ap->cur_mini_bufs, 0);
-
-	set_aceaddr(&info->rx_return_ctrl.rngptr,
-		    (ap->rx_ring_base_dma +
-		     (sizeof(struct rx_desc) *
-		      (RX_STD_RING_ENTRIES +
-		       RX_JUMBO_RING_ENTRIES +
-		       RX_MINI_RING_ENTRIES))));
-	info->rx_return_ctrl.flags = 0;
-	info->rx_return_ctrl.max_len = RX_RETURN_RING_ENTRIES;
-
-	memset(ap->rx_return_ring, 0,
-	       RX_RETURN_RING_ENTRIES * sizeof(struct rx_desc));
-
-	set_aceaddr(&info->rx_ret_prd_ptr, ap->rx_ret_prd_dma);
-	*(ap->rx_ret_prd) = 0;
-
-	writel(TX_RING_BASE, &regs->WinBase);
-
-	if (ACE_IS_TIGON_I(ap)) {
-		ap->tx_ring = (__force struct tx_desc *) regs->Window;
-		for (i = 0; i < (TIGON_I_TX_RING_ENTRIES
-				 * sizeof(struct tx_desc)) / sizeof(u32); i++)
-			writel(0, (__force void __iomem *)ap->tx_ring  + i * 4);
-
-		set_aceaddr(&info->tx_ctrl.rngptr, TX_RING_BASE);
-	} else {
-		memset(ap->tx_ring, 0,
-		       MAX_TX_RING_ENTRIES * sizeof(struct tx_desc));
-
-		set_aceaddr(&info->tx_ctrl.rngptr, ap->tx_ring_dma);
-	}
-
-	info->tx_ctrl.max_len = ACE_TX_RING_ENTRIES(ap);
-	tmp = RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | RCB_FLG_VLAN_ASSIST;
-
-	/*
-	 * The Tigon I does not like having the TX ring in host memory ;-(
-	 */
-	if (!ACE_IS_TIGON_I(ap))
-		tmp |= RCB_FLG_TX_HOST_RING;
-#if TX_COAL_INTS_ONLY
-	tmp |= RCB_FLG_COAL_INT_ONLY;
-#endif
-	info->tx_ctrl.flags = tmp;
-
-	set_aceaddr(&info->tx_csm_ptr, ap->tx_csm_dma);
-
-	/*
-	 * Potential item for tuning parameter
-	 */
-#if 0 /* NO */
-	writel(DMA_THRESH_16W, &regs->DmaReadCfg);
-	writel(DMA_THRESH_16W, &regs->DmaWriteCfg);
-#else
-	writel(DMA_THRESH_8W, &regs->DmaReadCfg);
-	writel(DMA_THRESH_8W, &regs->DmaWriteCfg);
-#endif
-
-	writel(0, &regs->MaskInt);
-	writel(1, &regs->IfIdx);
-#if 0
-	/*
-	 * McKinley boxes do not like us fiddling with AssistState
-	 * this early
-	 */
-	writel(1, &regs->AssistState);
-#endif
-
-	writel(DEF_STAT, &regs->TuneStatTicks);
-	writel(DEF_TRACE, &regs->TuneTrace);
-
-	ace_set_rxtx_parms(dev, 0);
-
-	if (board_idx == BOARD_IDX_OVERFLOW) {
-		printk(KERN_WARNING "%s: more than %i NICs detected, "
-		       "ignoring module parameters!\n",
-		       ap->name, ACE_MAX_MOD_PARMS);
-	} else if (board_idx >= 0) {
-		if (tx_coal_tick[board_idx])
-			writel(tx_coal_tick[board_idx],
-			       &regs->TuneTxCoalTicks);
-		if (max_tx_desc[board_idx])
-			writel(max_tx_desc[board_idx], &regs->TuneMaxTxDesc);
-
-		if (rx_coal_tick[board_idx])
-			writel(rx_coal_tick[board_idx],
-			       &regs->TuneRxCoalTicks);
-		if (max_rx_desc[board_idx])
-			writel(max_rx_desc[board_idx], &regs->TuneMaxRxDesc);
-
-		if (trace[board_idx])
-			writel(trace[board_idx], &regs->TuneTrace);
-
-		if ((tx_ratio[board_idx] > 0) && (tx_ratio[board_idx] < 64))
-			writel(tx_ratio[board_idx], &regs->TxBufRat);
-	}
-
-	/*
-	 * Default link parameters
-	 */
-	tmp = LNK_ENABLE | LNK_FULL_DUPLEX | LNK_1000MB | LNK_100MB |
-		LNK_10MB | LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL | LNK_NEGOTIATE;
-	if(ap->version >= 2)
-		tmp |= LNK_TX_FLOW_CTL_Y;
-
-	/*
-	 * Override link default parameters
-	 */
-	if ((board_idx >= 0) && link_state[board_idx]) {
-		int option = link_state[board_idx];
-
-		tmp = LNK_ENABLE;
-
-		if (option & 0x01) {
-			printk(KERN_INFO "%s: Setting half duplex link\n",
-			       ap->name);
-			tmp &= ~LNK_FULL_DUPLEX;
-		}
-		if (option & 0x02)
-			tmp &= ~LNK_NEGOTIATE;
-		if (option & 0x10)
-			tmp |= LNK_10MB;
-		if (option & 0x20)
-			tmp |= LNK_100MB;
-		if (option & 0x40)
-			tmp |= LNK_1000MB;
-		if ((option & 0x70) == 0) {
-			printk(KERN_WARNING "%s: No media speed specified, "
-			       "forcing auto negotiation\n", ap->name);
-			tmp |= LNK_NEGOTIATE | LNK_1000MB |
-				LNK_100MB | LNK_10MB;
-		}
-		if ((option & 0x100) == 0)
-			tmp |= LNK_NEG_FCTL;
-		else
-			printk(KERN_INFO "%s: Disabling flow control "
-			       "negotiation\n", ap->name);
-		if (option & 0x200)
-			tmp |= LNK_RX_FLOW_CTL_Y;
-		if ((option & 0x400) && (ap->version >= 2)) {
-			printk(KERN_INFO "%s: Enabling TX flow control\n",
-			       ap->name);
-			tmp |= LNK_TX_FLOW_CTL_Y;
-		}
-	}
-
-	ap->link = tmp;
-	writel(tmp, &regs->TuneLink);
-	if (ap->version >= 2)
-		writel(tmp, &regs->TuneFastLink);
-
-	writel(ap->firmware_start, &regs->Pc);
-
-	writel(0, &regs->Mb0Lo);
-
-	/*
-	 * Set tx_csm before we start receiving interrupts, otherwise
-	 * the interrupt handler might think it is supposed to process
-	 * tx ints before we are up and running, which may cause a null
-	 * pointer access in the int handler.
-	 */
-	ap->cur_rx = 0;
-	ap->tx_prd = *(ap->tx_csm) = ap->tx_ret_csm = 0;
-
-	wmb();
-	ace_set_txprd(regs, ap, 0);
-	writel(0, &regs->RxRetCsm);
-
-       /*
-	* Enable DMA engine now.
-	* If we do this sooner, Mckinley box pukes.
-	* I assume it's because Tigon II DMA engine wants to check
-	* *something* even before the CPU is started.
-	*/
-       writel(1, &regs->AssistState);  /* enable DMA */
-
-	/*
-	 * Start the NIC CPU
-	 */
-	writel(readl(&regs->CpuCtrl) & ~(CPU_HALT|CPU_TRACE), &regs->CpuCtrl);
-	readl(&regs->CpuCtrl);
-
-	/*
-	 * Wait for the firmware to spin up - max 3 seconds.
-	 */
-	myjif = jiffies + 3 * HZ;
-	while (time_before(jiffies, myjif) && !ap->fw_running)
-		cpu_relax();
-
-	if (!ap->fw_running) {
-		printk(KERN_ERR "%s: Firmware NOT running!\n", ap->name);
-
-		ace_dump_trace(ap);
-		writel(readl(&regs->CpuCtrl) | CPU_HALT, &regs->CpuCtrl);
-		readl(&regs->CpuCtrl);
-
-		/* aman@sgi.com - account for badly behaving firmware/NIC:
-		 * - have observed that the NIC may continue to generate
-		 *   interrupts for some reason; attempt to stop it - halt
-		 *   second CPU for Tigon II cards, and also clear Mb0
-		 * - if we're a module, we'll fail to load if this was
-		 *   the only GbE card in the system => if the kernel does
-		 *   see an interrupt from the NIC, code to handle it is
-		 *   gone and OOps! - so free_irq also
-		 */
-		if (ap->version >= 2)
-			writel(readl(&regs->CpuBCtrl) | CPU_HALT,
-			       &regs->CpuBCtrl);
-		writel(0, &regs->Mb0Lo);
-		readl(&regs->Mb0Lo);
-
-		ecode = -EBUSY;
-		goto init_error;
-	}
-
-	/*
-	 * We load the ring here as there seem to be no way to tell the
-	 * firmware to wipe the ring without re-initializing it.
-	 */
-	if (!test_and_set_bit(0, &ap->std_refill_busy))
-		ace_load_std_rx_ring(dev, RX_RING_SIZE);
-	else
-		printk(KERN_ERR "%s: Someone is busy refilling the RX ring\n",
-		       ap->name);
-	if (ap->version >= 2) {
-		if (!test_and_set_bit(0, &ap->mini_refill_busy))
-			ace_load_mini_rx_ring(dev, RX_MINI_SIZE);
-		else
-			printk(KERN_ERR "%s: Someone is busy refilling "
-			       "the RX mini ring\n", ap->name);
-	}
-	return 0;
-
- init_error:
-	ace_init_cleanup(dev);
-	return ecode;
-}
-
-
-static void ace_set_rxtx_parms(struct net_device *dev, int jumbo)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-	int board_idx = ap->board_idx;
-
-	if (board_idx >= 0) {
-		if (!jumbo) {
-			if (!tx_coal_tick[board_idx])
-				writel(DEF_TX_COAL, &regs->TuneTxCoalTicks);
-			if (!max_tx_desc[board_idx])
-				writel(DEF_TX_MAX_DESC, &regs->TuneMaxTxDesc);
-			if (!rx_coal_tick[board_idx])
-				writel(DEF_RX_COAL, &regs->TuneRxCoalTicks);
-			if (!max_rx_desc[board_idx])
-				writel(DEF_RX_MAX_DESC, &regs->TuneMaxRxDesc);
-			if (!tx_ratio[board_idx])
-				writel(DEF_TX_RATIO, &regs->TxBufRat);
-		} else {
-			if (!tx_coal_tick[board_idx])
-				writel(DEF_JUMBO_TX_COAL,
-				       &regs->TuneTxCoalTicks);
-			if (!max_tx_desc[board_idx])
-				writel(DEF_JUMBO_TX_MAX_DESC,
-				       &regs->TuneMaxTxDesc);
-			if (!rx_coal_tick[board_idx])
-				writel(DEF_JUMBO_RX_COAL,
-				       &regs->TuneRxCoalTicks);
-			if (!max_rx_desc[board_idx])
-				writel(DEF_JUMBO_RX_MAX_DESC,
-				       &regs->TuneMaxRxDesc);
-			if (!tx_ratio[board_idx])
-				writel(DEF_JUMBO_TX_RATIO, &regs->TxBufRat);
-		}
-	}
-}
-
-
-static void ace_watchdog(struct net_device *data)
-{
-	struct net_device *dev = data;
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-
-	/*
-	 * We haven't received a stats update event for more than 2.5
-	 * seconds and there is data in the transmit queue, thus we
-	 * assume the card is stuck.
-	 */
-	if (*ap->tx_csm != ap->tx_ret_csm) {
-		printk(KERN_WARNING "%s: Transmitter is stuck, %08x\n",
-		       dev->name, (unsigned int)readl(&regs->HostCtrl));
-		/* This can happen due to ieee flow control. */
-	} else {
-		printk(KERN_DEBUG "%s: BUG... transmitter died. Kicking it.\n",
-		       dev->name);
-#if 0
-		netif_wake_queue(dev);
-#endif
-	}
-}
-
-
-static void ace_tasklet(unsigned long arg)
-{
-	struct net_device *dev = (struct net_device *) arg;
-	struct ace_private *ap = netdev_priv(dev);
-	int cur_size;
-
-	cur_size = atomic_read(&ap->cur_rx_bufs);
-	if ((cur_size < RX_LOW_STD_THRES) &&
-	    !test_and_set_bit(0, &ap->std_refill_busy)) {
-#ifdef DEBUG
-		printk("refilling buffers (current %i)\n", cur_size);
-#endif
-		ace_load_std_rx_ring(dev, RX_RING_SIZE - cur_size);
-	}
-
-	if (ap->version >= 2) {
-		cur_size = atomic_read(&ap->cur_mini_bufs);
-		if ((cur_size < RX_LOW_MINI_THRES) &&
-		    !test_and_set_bit(0, &ap->mini_refill_busy)) {
-#ifdef DEBUG
-			printk("refilling mini buffers (current %i)\n",
-			       cur_size);
-#endif
-			ace_load_mini_rx_ring(dev, RX_MINI_SIZE - cur_size);
-		}
-	}
-
-	cur_size = atomic_read(&ap->cur_jumbo_bufs);
-	if (ap->jumbo && (cur_size < RX_LOW_JUMBO_THRES) &&
-	    !test_and_set_bit(0, &ap->jumbo_refill_busy)) {
-#ifdef DEBUG
-		printk("refilling jumbo buffers (current %i)\n", cur_size);
-#endif
-		ace_load_jumbo_rx_ring(dev, RX_JUMBO_SIZE - cur_size);
-	}
-	ap->tasklet_pending = 0;
-}
-
-
-/*
- * Copy the contents of the NIC's trace buffer to kernel memory.
- */
-static void ace_dump_trace(struct ace_private *ap)
-{
-#if 0
-	if (!ap->trace_buf)
-		if (!(ap->trace_buf = kmalloc(ACE_TRACE_SIZE, GFP_KERNEL)))
-		    return;
-#endif
-}
-
-
-/*
- * Load the standard rx ring.
- *
- * Loading rings is safe without holding the spin lock since this is
- * done only before the device is enabled, thus no interrupts are
- * generated and by the interrupt handler/tasklet handler.
- */
-static void ace_load_std_rx_ring(struct net_device *dev, int nr_bufs)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-	short i, idx;
-
-
-	prefetchw(&ap->cur_rx_bufs);
-
-	idx = ap->rx_std_skbprd;
-
-	for (i = 0; i < nr_bufs; i++) {
-		struct sk_buff *skb;
-		struct rx_desc *rd;
-		dma_addr_t mapping;
-
-		skb = netdev_alloc_skb_ip_align(dev, ACE_STD_BUFSIZE);
-		if (!skb)
-			break;
-
-		mapping = pci_map_page(ap->pdev, virt_to_page(skb->data),
-				       offset_in_page(skb->data),
-				       ACE_STD_BUFSIZE,
-				       PCI_DMA_FROMDEVICE);
-		ap->skb->rx_std_skbuff[idx].skb = skb;
-		dma_unmap_addr_set(&ap->skb->rx_std_skbuff[idx],
-				   mapping, mapping);
-
-		rd = &ap->rx_std_ring[idx];
-		set_aceaddr(&rd->addr, mapping);
-		rd->size = ACE_STD_BUFSIZE;
-		rd->idx = idx;
-		idx = (idx + 1) % RX_STD_RING_ENTRIES;
-	}
-
-	if (!i)
-		goto error_out;
-
-	atomic_add(i, &ap->cur_rx_bufs);
-	ap->rx_std_skbprd = idx;
-
-	if (ACE_IS_TIGON_I(ap)) {
-		struct cmd cmd;
-		cmd.evt = C_SET_RX_PRD_IDX;
-		cmd.code = 0;
-		cmd.idx = ap->rx_std_skbprd;
-		ace_issue_cmd(regs, &cmd);
-	} else {
-		writel(idx, &regs->RxStdPrd);
-		wmb();
-	}
-
- out:
-	clear_bit(0, &ap->std_refill_busy);
-	return;
-
- error_out:
-	printk(KERN_INFO "Out of memory when allocating "
-	       "standard receive buffers\n");
-	goto out;
-}
-
-
-static void ace_load_mini_rx_ring(struct net_device *dev, int nr_bufs)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-	short i, idx;
-
-	prefetchw(&ap->cur_mini_bufs);
-
-	idx = ap->rx_mini_skbprd;
-	for (i = 0; i < nr_bufs; i++) {
-		struct sk_buff *skb;
-		struct rx_desc *rd;
-		dma_addr_t mapping;
-
-		skb = netdev_alloc_skb_ip_align(dev, ACE_MINI_BUFSIZE);
-		if (!skb)
-			break;
-
-		mapping = pci_map_page(ap->pdev, virt_to_page(skb->data),
-				       offset_in_page(skb->data),
-				       ACE_MINI_BUFSIZE,
-				       PCI_DMA_FROMDEVICE);
-		ap->skb->rx_mini_skbuff[idx].skb = skb;
-		dma_unmap_addr_set(&ap->skb->rx_mini_skbuff[idx],
-				   mapping, mapping);
-
-		rd = &ap->rx_mini_ring[idx];
-		set_aceaddr(&rd->addr, mapping);
-		rd->size = ACE_MINI_BUFSIZE;
-		rd->idx = idx;
-		idx = (idx + 1) % RX_MINI_RING_ENTRIES;
-	}
-
-	if (!i)
-		goto error_out;
-
-	atomic_add(i, &ap->cur_mini_bufs);
-
-	ap->rx_mini_skbprd = idx;
-
-	writel(idx, &regs->RxMiniPrd);
-	wmb();
-
- out:
-	clear_bit(0, &ap->mini_refill_busy);
-	return;
- error_out:
-	printk(KERN_INFO "Out of memory when allocating "
-	       "mini receive buffers\n");
-	goto out;
-}
-
-
-/*
- * Load the jumbo rx ring, this may happen at any time if the MTU
- * is changed to a value > 1500.
- */
-static void ace_load_jumbo_rx_ring(struct net_device *dev, int nr_bufs)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-	short i, idx;
-
-	idx = ap->rx_jumbo_skbprd;
-
-	for (i = 0; i < nr_bufs; i++) {
-		struct sk_buff *skb;
-		struct rx_desc *rd;
-		dma_addr_t mapping;
-
-		skb = netdev_alloc_skb_ip_align(dev, ACE_JUMBO_BUFSIZE);
-		if (!skb)
-			break;
-
-		mapping = pci_map_page(ap->pdev, virt_to_page(skb->data),
-				       offset_in_page(skb->data),
-				       ACE_JUMBO_BUFSIZE,
-				       PCI_DMA_FROMDEVICE);
-		ap->skb->rx_jumbo_skbuff[idx].skb = skb;
-		dma_unmap_addr_set(&ap->skb->rx_jumbo_skbuff[idx],
-				   mapping, mapping);
-
-		rd = &ap->rx_jumbo_ring[idx];
-		set_aceaddr(&rd->addr, mapping);
-		rd->size = ACE_JUMBO_BUFSIZE;
-		rd->idx = idx;
-		idx = (idx + 1) % RX_JUMBO_RING_ENTRIES;
-	}
-
-	if (!i)
-		goto error_out;
-
-	atomic_add(i, &ap->cur_jumbo_bufs);
-	ap->rx_jumbo_skbprd = idx;
-
-	if (ACE_IS_TIGON_I(ap)) {
-		struct cmd cmd;
-		cmd.evt = C_SET_RX_JUMBO_PRD_IDX;
-		cmd.code = 0;
-		cmd.idx = ap->rx_jumbo_skbprd;
-		ace_issue_cmd(regs, &cmd);
-	} else {
-		writel(idx, &regs->RxJumboPrd);
-		wmb();
-	}
-
- out:
-	clear_bit(0, &ap->jumbo_refill_busy);
-	return;
- error_out:
-	if (net_ratelimit())
-		printk(KERN_INFO "Out of memory when allocating "
-		       "jumbo receive buffers\n");
-	goto out;
-}
-
-
-/*
- * All events are considered to be slow (RX/TX ints do not generate
- * events) and are handled here, outside the main interrupt handler,
- * to reduce the size of the handler.
- */
-static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd)
-{
-	struct ace_private *ap;
-
-	ap = netdev_priv(dev);
-
-	while (evtcsm != evtprd) {
-		switch (ap->evt_ring[evtcsm].evt) {
-		case E_FW_RUNNING:
-			printk(KERN_INFO "%s: Firmware up and running\n",
-			       ap->name);
-			ap->fw_running = 1;
-			wmb();
-			break;
-		case E_STATS_UPDATED:
-			break;
-		case E_LNK_STATE:
-		{
-			u16 code = ap->evt_ring[evtcsm].code;
-			switch (code) {
-			case E_C_LINK_UP:
-			{
-				u32 state = readl(&ap->regs->GigLnkState);
-				printk(KERN_WARNING "%s: Optical link UP "
-				       "(%s Duplex, Flow Control: %s%s)\n",
-				       ap->name,
-				       state & LNK_FULL_DUPLEX ? "Full":"Half",
-				       state & LNK_TX_FLOW_CTL_Y ? "TX " : "",
-				       state & LNK_RX_FLOW_CTL_Y ? "RX" : "");
-				break;
-			}
-			case E_C_LINK_DOWN:
-				printk(KERN_WARNING "%s: Optical link DOWN\n",
-				       ap->name);
-				break;
-			case E_C_LINK_10_100:
-				printk(KERN_WARNING "%s: 10/100BaseT link "
-				       "UP\n", ap->name);
-				break;
-			default:
-				printk(KERN_ERR "%s: Unknown optical link "
-				       "state %02x\n", ap->name, code);
-			}
-			break;
-		}
-		case E_ERROR:
-			switch(ap->evt_ring[evtcsm].code) {
-			case E_C_ERR_INVAL_CMD:
-				printk(KERN_ERR "%s: invalid command error\n",
-				       ap->name);
-				break;
-			case E_C_ERR_UNIMP_CMD:
-				printk(KERN_ERR "%s: unimplemented command "
-				       "error\n", ap->name);
-				break;
-			case E_C_ERR_BAD_CFG:
-				printk(KERN_ERR "%s: bad config error\n",
-				       ap->name);
-				break;
-			default:
-				printk(KERN_ERR "%s: unknown error %02x\n",
-				       ap->name, ap->evt_ring[evtcsm].code);
-			}
-			break;
-		case E_RESET_JUMBO_RNG:
-		{
-			int i;
-			for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++) {
-				if (ap->skb->rx_jumbo_skbuff[i].skb) {
-					ap->rx_jumbo_ring[i].size = 0;
-					set_aceaddr(&ap->rx_jumbo_ring[i].addr, 0);
-					dev_kfree_skb(ap->skb->rx_jumbo_skbuff[i].skb);
-					ap->skb->rx_jumbo_skbuff[i].skb = NULL;
-				}
-			}
-
- 			if (ACE_IS_TIGON_I(ap)) {
- 				struct cmd cmd;
- 				cmd.evt = C_SET_RX_JUMBO_PRD_IDX;
- 				cmd.code = 0;
- 				cmd.idx = 0;
- 				ace_issue_cmd(ap->regs, &cmd);
- 			} else {
- 				writel(0, &((ap->regs)->RxJumboPrd));
- 				wmb();
- 			}
-
-			ap->jumbo = 0;
-			ap->rx_jumbo_skbprd = 0;
-			printk(KERN_INFO "%s: Jumbo ring flushed\n",
-			       ap->name);
-			clear_bit(0, &ap->jumbo_refill_busy);
-			break;
-		}
-		default:
-			printk(KERN_ERR "%s: Unhandled event 0x%02x\n",
-			       ap->name, ap->evt_ring[evtcsm].evt);
-		}
-		evtcsm = (evtcsm + 1) % EVT_RING_ENTRIES;
-	}
-
-	return evtcsm;
-}
-
-
-static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	u32 idx;
-	int mini_count = 0, std_count = 0;
-
-	idx = rxretcsm;
-
-	prefetchw(&ap->cur_rx_bufs);
-	prefetchw(&ap->cur_mini_bufs);
-
-	while (idx != rxretprd) {
-		struct ring_info *rip;
-		struct sk_buff *skb;
-		struct rx_desc *rxdesc, *retdesc;
-		u32 skbidx;
-		int bd_flags, desc_type, mapsize;
-		u16 csum;
-
-
-		/* make sure the rx descriptor isn't read before rxretprd */
-		if (idx == rxretcsm)
-			rmb();
-
-		retdesc = &ap->rx_return_ring[idx];
-		skbidx = retdesc->idx;
-		bd_flags = retdesc->flags;
-		desc_type = bd_flags & (BD_FLG_JUMBO | BD_FLG_MINI);
-
-		switch(desc_type) {
-			/*
-			 * Normal frames do not have any flags set
-			 *
-			 * Mini and normal frames arrive frequently,
-			 * so use a local counter to avoid doing
-			 * atomic operations for each packet arriving.
-			 */
-		case 0:
-			rip = &ap->skb->rx_std_skbuff[skbidx];
-			mapsize = ACE_STD_BUFSIZE;
-			rxdesc = &ap->rx_std_ring[skbidx];
-			std_count++;
-			break;
-		case BD_FLG_JUMBO:
-			rip = &ap->skb->rx_jumbo_skbuff[skbidx];
-			mapsize = ACE_JUMBO_BUFSIZE;
-			rxdesc = &ap->rx_jumbo_ring[skbidx];
-			atomic_dec(&ap->cur_jumbo_bufs);
-			break;
-		case BD_FLG_MINI:
-			rip = &ap->skb->rx_mini_skbuff[skbidx];
-			mapsize = ACE_MINI_BUFSIZE;
-			rxdesc = &ap->rx_mini_ring[skbidx];
-			mini_count++;
-			break;
-		default:
-			printk(KERN_INFO "%s: unknown frame type (0x%02x) "
-			       "returned by NIC\n", dev->name,
-			       retdesc->flags);
-			goto error;
-		}
-
-		skb = rip->skb;
-		rip->skb = NULL;
-		pci_unmap_page(ap->pdev,
-			       dma_unmap_addr(rip, mapping),
-			       mapsize,
-			       PCI_DMA_FROMDEVICE);
-		skb_put(skb, retdesc->size);
-
-		/*
-		 * Fly baby, fly!
-		 */
-		csum = retdesc->tcp_udp_csum;
-
-		skb->protocol = eth_type_trans(skb, dev);
-
-		/*
-		 * Instead of forcing the poor tigon mips cpu to calculate
-		 * pseudo hdr checksum, we do this ourselves.
-		 */
-		if (bd_flags & BD_FLG_TCP_UDP_SUM) {
-			skb->csum = htons(csum);
-			skb->ip_summed = CHECKSUM_COMPLETE;
-		} else {
-			skb_checksum_none_assert(skb);
-		}
-
-		/* send it up */
-		if ((bd_flags & BD_FLG_VLAN_TAG))
-			__vlan_hwaccel_put_tag(skb, retdesc->vlan);
-		netif_rx(skb);
-
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += retdesc->size;
-
-		idx = (idx + 1) % RX_RETURN_RING_ENTRIES;
-	}
-
-	atomic_sub(std_count, &ap->cur_rx_bufs);
-	if (!ACE_IS_TIGON_I(ap))
-		atomic_sub(mini_count, &ap->cur_mini_bufs);
-
- out:
-	/*
-	 * According to the documentation RxRetCsm is obsolete with
-	 * the 12.3.x Firmware - my Tigon I NICs seem to disagree!
-	 */
-	if (ACE_IS_TIGON_I(ap)) {
-		writel(idx, &ap->regs->RxRetCsm);
-	}
-	ap->cur_rx = idx;
-
-	return;
- error:
-	idx = rxretprd;
-	goto out;
-}
-
-
-static inline void ace_tx_int(struct net_device *dev,
-			      u32 txcsm, u32 idx)
-{
-	struct ace_private *ap = netdev_priv(dev);
-
-	do {
-		struct sk_buff *skb;
-		struct tx_ring_info *info;
-
-		info = ap->skb->tx_skbuff + idx;
-		skb = info->skb;
-
-		if (dma_unmap_len(info, maplen)) {
-			pci_unmap_page(ap->pdev, dma_unmap_addr(info, mapping),
-				       dma_unmap_len(info, maplen),
-				       PCI_DMA_TODEVICE);
-			dma_unmap_len_set(info, maplen, 0);
-		}
-
-		if (skb) {
-			dev->stats.tx_packets++;
-			dev->stats.tx_bytes += skb->len;
-			dev_kfree_skb_irq(skb);
-			info->skb = NULL;
-		}
-
-		idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
-	} while (idx != txcsm);
-
-	if (netif_queue_stopped(dev))
-		netif_wake_queue(dev);
-
-	wmb();
-	ap->tx_ret_csm = txcsm;
-
-	/* So... tx_ret_csm is advanced _after_ check for device wakeup.
-	 *
-	 * We could try to make it before. In this case we would get
-	 * the following race condition: hard_start_xmit on other cpu
-	 * enters after we advanced tx_ret_csm and fills space,
-	 * which we have just freed, so that we make illegal device wakeup.
-	 * There is no good way to workaround this (at entry
-	 * to ace_start_xmit detects this condition and prevents
-	 * ring corruption, but it is not a good workaround.)
-	 *
-	 * When tx_ret_csm is advanced after, we wake up device _only_
-	 * if we really have some space in ring (though the core doing
-	 * hard_start_xmit can see full ring for some period and has to
-	 * synchronize.) Superb.
-	 * BUT! We get another subtle race condition. hard_start_xmit
-	 * may think that ring is full between wakeup and advancing
-	 * tx_ret_csm and will stop device instantly! It is not so bad.
-	 * We are guaranteed that there is something in ring, so that
-	 * the next irq will resume transmission. To speedup this we could
-	 * mark descriptor, which closes ring with BD_FLG_COAL_NOW
-	 * (see ace_start_xmit).
-	 *
-	 * Well, this dilemma exists in all lock-free devices.
-	 * We, following scheme used in drivers by Donald Becker,
-	 * select the least dangerous.
-	 *							--ANK
-	 */
-}
-
-
-static irqreturn_t ace_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = (struct net_device *)dev_id;
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-	u32 idx;
-	u32 txcsm, rxretcsm, rxretprd;
-	u32 evtcsm, evtprd;
-
-	/*
-	 * In case of PCI shared interrupts or spurious interrupts,
-	 * we want to make sure it is actually our interrupt before
-	 * spending any time in here.
-	 */
-	if (!(readl(&regs->HostCtrl) & IN_INT))
-		return IRQ_NONE;
-
-	/*
-	 * ACK intr now. Otherwise we will lose updates to rx_ret_prd,
-	 * which happened _after_ rxretprd = *ap->rx_ret_prd; but before
-	 * writel(0, &regs->Mb0Lo).
-	 *
-	 * "IRQ avoidance" recommended in docs applies to IRQs served
-	 * threads and it is wrong even for that case.
-	 */
-	writel(0, &regs->Mb0Lo);
-	readl(&regs->Mb0Lo);
-
-	/*
-	 * There is no conflict between transmit handling in
-	 * start_xmit and receive processing, thus there is no reason
-	 * to take a spin lock for RX handling. Wait until we start
-	 * working on the other stuff - hey we don't need a spin lock
-	 * anymore.
-	 */
-	rxretprd = *ap->rx_ret_prd;
-	rxretcsm = ap->cur_rx;
-
-	if (rxretprd != rxretcsm)
-		ace_rx_int(dev, rxretprd, rxretcsm);
-
-	txcsm = *ap->tx_csm;
-	idx = ap->tx_ret_csm;
-
-	if (txcsm != idx) {
-		/*
-		 * If each skb takes only one descriptor this check degenerates
-		 * to identity, because new space has just been opened.
-		 * But if skbs are fragmented we must check that this index
-		 * update releases enough of space, otherwise we just
-		 * wait for device to make more work.
-		 */
-		if (!tx_ring_full(ap, txcsm, ap->tx_prd))
-			ace_tx_int(dev, txcsm, idx);
-	}
-
-	evtcsm = readl(&regs->EvtCsm);
-	evtprd = *ap->evt_prd;
-
-	if (evtcsm != evtprd) {
-		evtcsm = ace_handle_event(dev, evtcsm, evtprd);
-		writel(evtcsm, &regs->EvtCsm);
-	}
-
-	/*
-	 * This has to go last in the interrupt handler and run with
-	 * the spin lock released ... what lock?
-	 */
-	if (netif_running(dev)) {
-		int cur_size;
-		int run_tasklet = 0;
-
-		cur_size = atomic_read(&ap->cur_rx_bufs);
-		if (cur_size < RX_LOW_STD_THRES) {
-			if ((cur_size < RX_PANIC_STD_THRES) &&
-			    !test_and_set_bit(0, &ap->std_refill_busy)) {
-#ifdef DEBUG
-				printk("low on std buffers %i\n", cur_size);
-#endif
-				ace_load_std_rx_ring(dev,
-						     RX_RING_SIZE - cur_size);
-			} else
-				run_tasklet = 1;
-		}
-
-		if (!ACE_IS_TIGON_I(ap)) {
-			cur_size = atomic_read(&ap->cur_mini_bufs);
-			if (cur_size < RX_LOW_MINI_THRES) {
-				if ((cur_size < RX_PANIC_MINI_THRES) &&
-				    !test_and_set_bit(0,
-						      &ap->mini_refill_busy)) {
-#ifdef DEBUG
-					printk("low on mini buffers %i\n",
-					       cur_size);
-#endif
-					ace_load_mini_rx_ring(dev,
-							      RX_MINI_SIZE - cur_size);
-				} else
-					run_tasklet = 1;
-			}
-		}
-
-		if (ap->jumbo) {
-			cur_size = atomic_read(&ap->cur_jumbo_bufs);
-			if (cur_size < RX_LOW_JUMBO_THRES) {
-				if ((cur_size < RX_PANIC_JUMBO_THRES) &&
-				    !test_and_set_bit(0,
-						      &ap->jumbo_refill_busy)){
-#ifdef DEBUG
-					printk("low on jumbo buffers %i\n",
-					       cur_size);
-#endif
-					ace_load_jumbo_rx_ring(dev,
-							       RX_JUMBO_SIZE - cur_size);
-				} else
-					run_tasklet = 1;
-			}
-		}
-		if (run_tasklet && !ap->tasklet_pending) {
-			ap->tasklet_pending = 1;
-			tasklet_schedule(&ap->ace_tasklet);
-		}
-	}
-
-	return IRQ_HANDLED;
-}
-
-static int ace_open(struct net_device *dev)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-	struct cmd cmd;
-
-	if (!(ap->fw_running)) {
-		printk(KERN_WARNING "%s: Firmware not running!\n", dev->name);
-		return -EBUSY;
-	}
-
-	writel(dev->mtu + ETH_HLEN + 4, &regs->IfMtu);
-
-	cmd.evt = C_CLEAR_STATS;
-	cmd.code = 0;
-	cmd.idx = 0;
-	ace_issue_cmd(regs, &cmd);
-
-	cmd.evt = C_HOST_STATE;
-	cmd.code = C_C_STACK_UP;
-	cmd.idx = 0;
-	ace_issue_cmd(regs, &cmd);
-
-	if (ap->jumbo &&
-	    !test_and_set_bit(0, &ap->jumbo_refill_busy))
-		ace_load_jumbo_rx_ring(dev, RX_JUMBO_SIZE);
-
-	if (dev->flags & IFF_PROMISC) {
-		cmd.evt = C_SET_PROMISC_MODE;
-		cmd.code = C_C_PROMISC_ENABLE;
-		cmd.idx = 0;
-		ace_issue_cmd(regs, &cmd);
-
-		ap->promisc = 1;
-	}else
-		ap->promisc = 0;
-	ap->mcast_all = 0;
-
-#if 0
-	cmd.evt = C_LNK_NEGOTIATION;
-	cmd.code = 0;
-	cmd.idx = 0;
-	ace_issue_cmd(regs, &cmd);
-#endif
-
-	netif_start_queue(dev);
-
-	/*
-	 * Setup the bottom half rx ring refill handler
-	 */
-	tasklet_init(&ap->ace_tasklet, ace_tasklet, (unsigned long)dev);
-	return 0;
-}
-
-
-static int ace_close(struct net_device *dev)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-	struct cmd cmd;
-	unsigned long flags;
-	short i;
-
-	/*
-	 * Without (or before) releasing irq and stopping hardware, this
-	 * is an absolute non-sense, by the way. It will be reset instantly
-	 * by the first irq.
-	 */
-	netif_stop_queue(dev);
-
-
-	if (ap->promisc) {
-		cmd.evt = C_SET_PROMISC_MODE;
-		cmd.code = C_C_PROMISC_DISABLE;
-		cmd.idx = 0;
-		ace_issue_cmd(regs, &cmd);
-		ap->promisc = 0;
-	}
-
-	cmd.evt = C_HOST_STATE;
-	cmd.code = C_C_STACK_DOWN;
-	cmd.idx = 0;
-	ace_issue_cmd(regs, &cmd);
-
-	tasklet_kill(&ap->ace_tasklet);
-
-	/*
-	 * Make sure one CPU is not processing packets while
-	 * buffers are being released by another.
-	 */
-
-	local_irq_save(flags);
-	ace_mask_irq(dev);
-
-	for (i = 0; i < ACE_TX_RING_ENTRIES(ap); i++) {
-		struct sk_buff *skb;
-		struct tx_ring_info *info;
-
-		info = ap->skb->tx_skbuff + i;
-		skb = info->skb;
-
-		if (dma_unmap_len(info, maplen)) {
-			if (ACE_IS_TIGON_I(ap)) {
-				/* NB: TIGON_1 is special, tx_ring is in io space */
-				struct tx_desc __iomem *tx;
-				tx = (__force struct tx_desc __iomem *) &ap->tx_ring[i];
-				writel(0, &tx->addr.addrhi);
-				writel(0, &tx->addr.addrlo);
-				writel(0, &tx->flagsize);
-			} else
-				memset(ap->tx_ring + i, 0,
-				       sizeof(struct tx_desc));
-			pci_unmap_page(ap->pdev, dma_unmap_addr(info, mapping),
-				       dma_unmap_len(info, maplen),
-				       PCI_DMA_TODEVICE);
-			dma_unmap_len_set(info, maplen, 0);
-		}
-		if (skb) {
-			dev_kfree_skb(skb);
-			info->skb = NULL;
-		}
-	}
-
-	if (ap->jumbo) {
-		cmd.evt = C_RESET_JUMBO_RNG;
-		cmd.code = 0;
-		cmd.idx = 0;
-		ace_issue_cmd(regs, &cmd);
-	}
-
-	ace_unmask_irq(dev);
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-
-static inline dma_addr_t
-ace_map_tx_skb(struct ace_private *ap, struct sk_buff *skb,
-	       struct sk_buff *tail, u32 idx)
-{
-	dma_addr_t mapping;
-	struct tx_ring_info *info;
-
-	mapping = pci_map_page(ap->pdev, virt_to_page(skb->data),
-			       offset_in_page(skb->data),
-			       skb->len, PCI_DMA_TODEVICE);
-
-	info = ap->skb->tx_skbuff + idx;
-	info->skb = tail;
-	dma_unmap_addr_set(info, mapping, mapping);
-	dma_unmap_len_set(info, maplen, skb->len);
-	return mapping;
-}
-
-
-static inline void
-ace_load_tx_bd(struct ace_private *ap, struct tx_desc *desc, u64 addr,
-	       u32 flagsize, u32 vlan_tag)
-{
-#if !USE_TX_COAL_NOW
-	flagsize &= ~BD_FLG_COAL_NOW;
-#endif
-
-	if (ACE_IS_TIGON_I(ap)) {
-		struct tx_desc __iomem *io = (__force struct tx_desc __iomem *) desc;
-		writel(addr >> 32, &io->addr.addrhi);
-		writel(addr & 0xffffffff, &io->addr.addrlo);
-		writel(flagsize, &io->flagsize);
-		writel(vlan_tag, &io->vlanres);
-	} else {
-		desc->addr.addrhi = addr >> 32;
-		desc->addr.addrlo = addr;
-		desc->flagsize = flagsize;
-		desc->vlanres = vlan_tag;
-	}
-}
-
-
-static netdev_tx_t ace_start_xmit(struct sk_buff *skb,
-				  struct net_device *dev)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-	struct tx_desc *desc;
-	u32 idx, flagsize;
-	unsigned long maxjiff = jiffies + 3*HZ;
-
-restart:
-	idx = ap->tx_prd;
-
-	if (tx_ring_full(ap, ap->tx_ret_csm, idx))
-		goto overflow;
-
-	if (!skb_shinfo(skb)->nr_frags)	{
-		dma_addr_t mapping;
-		u32 vlan_tag = 0;
-
-		mapping = ace_map_tx_skb(ap, skb, skb, idx);
-		flagsize = (skb->len << 16) | (BD_FLG_END);
-		if (skb->ip_summed == CHECKSUM_PARTIAL)
-			flagsize |= BD_FLG_TCP_UDP_SUM;
-		if (vlan_tx_tag_present(skb)) {
-			flagsize |= BD_FLG_VLAN_TAG;
-			vlan_tag = vlan_tx_tag_get(skb);
-		}
-		desc = ap->tx_ring + idx;
-		idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
-
-		/* Look at ace_tx_int for explanations. */
-		if (tx_ring_full(ap, ap->tx_ret_csm, idx))
-			flagsize |= BD_FLG_COAL_NOW;
-
-		ace_load_tx_bd(ap, desc, mapping, flagsize, vlan_tag);
-	} else {
-		dma_addr_t mapping;
-		u32 vlan_tag = 0;
-		int i, len = 0;
-
-		mapping = ace_map_tx_skb(ap, skb, NULL, idx);
-		flagsize = (skb_headlen(skb) << 16);
-		if (skb->ip_summed == CHECKSUM_PARTIAL)
-			flagsize |= BD_FLG_TCP_UDP_SUM;
-		if (vlan_tx_tag_present(skb)) {
-			flagsize |= BD_FLG_VLAN_TAG;
-			vlan_tag = vlan_tx_tag_get(skb);
-		}
-
-		ace_load_tx_bd(ap, ap->tx_ring + idx, mapping, flagsize, vlan_tag);
-
-		idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
-
-		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-			struct tx_ring_info *info;
-
-			len += frag->size;
-			info = ap->skb->tx_skbuff + idx;
-			desc = ap->tx_ring + idx;
-
-			mapping = pci_map_page(ap->pdev, frag->page,
-					       frag->page_offset, frag->size,
-					       PCI_DMA_TODEVICE);
-
-			flagsize = (frag->size << 16);
-			if (skb->ip_summed == CHECKSUM_PARTIAL)
-				flagsize |= BD_FLG_TCP_UDP_SUM;
-			idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
-
-			if (i == skb_shinfo(skb)->nr_frags - 1) {
-				flagsize |= BD_FLG_END;
-				if (tx_ring_full(ap, ap->tx_ret_csm, idx))
-					flagsize |= BD_FLG_COAL_NOW;
-
-				/*
-				 * Only the last fragment frees
-				 * the skb!
-				 */
-				info->skb = skb;
-			} else {
-				info->skb = NULL;
-			}
-			dma_unmap_addr_set(info, mapping, mapping);
-			dma_unmap_len_set(info, maplen, frag->size);
-			ace_load_tx_bd(ap, desc, mapping, flagsize, vlan_tag);
-		}
-	}
-
- 	wmb();
- 	ap->tx_prd = idx;
- 	ace_set_txprd(regs, ap, idx);
-
-	if (flagsize & BD_FLG_COAL_NOW) {
-		netif_stop_queue(dev);
-
-		/*
-		 * A TX-descriptor producer (an IRQ) might have gotten
-		 * between, making the ring free again. Since xmit is
-		 * serialized, this is the only situation we have to
-		 * re-test.
-		 */
-		if (!tx_ring_full(ap, ap->tx_ret_csm, idx))
-			netif_wake_queue(dev);
-	}
-
-	return NETDEV_TX_OK;
-
-overflow:
-	/*
-	 * This race condition is unavoidable with lock-free drivers.
-	 * We wake up the queue _before_ tx_prd is advanced, so that we can
-	 * enter hard_start_xmit too early, while tx ring still looks closed.
-	 * This happens ~1-4 times per 100000 packets, so that we can allow
-	 * to loop syncing to other CPU. Probably, we need an additional
-	 * wmb() in ace_tx_intr as well.
-	 *
-	 * Note that this race is relieved by reserving one more entry
-	 * in tx ring than it is necessary (see original non-SG driver).
-	 * However, with SG we need to reserve 2*MAX_SKB_FRAGS+1, which
-	 * is already overkill.
-	 *
-	 * Alternative is to return with 1 not throttling queue. In this
-	 * case loop becomes longer, no more useful effects.
-	 */
-	if (time_before(jiffies, maxjiff)) {
-		barrier();
-		cpu_relax();
-		goto restart;
-	}
-
-	/* The ring is stuck full. */
-	printk(KERN_WARNING "%s: Transmit ring stuck full\n", dev->name);
-	return NETDEV_TX_BUSY;
-}
-
-
-static int ace_change_mtu(struct net_device *dev, int new_mtu)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-
-	if (new_mtu > ACE_JUMBO_MTU)
-		return -EINVAL;
-
-	writel(new_mtu + ETH_HLEN + 4, &regs->IfMtu);
-	dev->mtu = new_mtu;
-
-	if (new_mtu > ACE_STD_MTU) {
-		if (!(ap->jumbo)) {
-			printk(KERN_INFO "%s: Enabling Jumbo frame "
-			       "support\n", dev->name);
-			ap->jumbo = 1;
-			if (!test_and_set_bit(0, &ap->jumbo_refill_busy))
-				ace_load_jumbo_rx_ring(dev, RX_JUMBO_SIZE);
-			ace_set_rxtx_parms(dev, 1);
-		}
-	} else {
-		while (test_and_set_bit(0, &ap->jumbo_refill_busy));
-		ace_sync_irq(dev->irq);
-		ace_set_rxtx_parms(dev, 0);
-		if (ap->jumbo) {
-			struct cmd cmd;
-
-			cmd.evt = C_RESET_JUMBO_RNG;
-			cmd.code = 0;
-			cmd.idx = 0;
-			ace_issue_cmd(regs, &cmd);
-		}
-	}
-
-	return 0;
-}
-
-static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-	u32 link;
-
-	memset(ecmd, 0, sizeof(struct ethtool_cmd));
-	ecmd->supported =
-		(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
-		 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
-		 SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full |
-		 SUPPORTED_Autoneg | SUPPORTED_FIBRE);
-
-	ecmd->port = PORT_FIBRE;
-	ecmd->transceiver = XCVR_INTERNAL;
-
-	link = readl(&regs->GigLnkState);
-	if (link & LNK_1000MB)
-		ethtool_cmd_speed_set(ecmd, SPEED_1000);
-	else {
-		link = readl(&regs->FastLnkState);
-		if (link & LNK_100MB)
-			ethtool_cmd_speed_set(ecmd, SPEED_100);
-		else if (link & LNK_10MB)
-			ethtool_cmd_speed_set(ecmd, SPEED_10);
-		else
-			ethtool_cmd_speed_set(ecmd, 0);
-	}
-	if (link & LNK_FULL_DUPLEX)
-		ecmd->duplex = DUPLEX_FULL;
-	else
-		ecmd->duplex = DUPLEX_HALF;
-
-	if (link & LNK_NEGOTIATE)
-		ecmd->autoneg = AUTONEG_ENABLE;
-	else
-		ecmd->autoneg = AUTONEG_DISABLE;
-
-#if 0
-	/*
-	 * Current struct ethtool_cmd is insufficient
-	 */
-	ecmd->trace = readl(&regs->TuneTrace);
-
-	ecmd->txcoal = readl(&regs->TuneTxCoalTicks);
-	ecmd->rxcoal = readl(&regs->TuneRxCoalTicks);
-#endif
-	ecmd->maxtxpkt = readl(&regs->TuneMaxTxDesc);
-	ecmd->maxrxpkt = readl(&regs->TuneMaxRxDesc);
-
-	return 0;
-}
-
-static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-	u32 link, speed;
-
-	link = readl(&regs->GigLnkState);
-	if (link & LNK_1000MB)
-		speed = SPEED_1000;
-	else {
-		link = readl(&regs->FastLnkState);
-		if (link & LNK_100MB)
-			speed = SPEED_100;
-		else if (link & LNK_10MB)
-			speed = SPEED_10;
-		else
-			speed = SPEED_100;
-	}
-
-	link = LNK_ENABLE | LNK_1000MB | LNK_100MB | LNK_10MB |
-		LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL;
-	if (!ACE_IS_TIGON_I(ap))
-		link |= LNK_TX_FLOW_CTL_Y;
-	if (ecmd->autoneg == AUTONEG_ENABLE)
-		link |= LNK_NEGOTIATE;
-	if (ethtool_cmd_speed(ecmd) != speed) {
-		link &= ~(LNK_1000MB | LNK_100MB | LNK_10MB);
-		switch (ethtool_cmd_speed(ecmd)) {
-		case SPEED_1000:
-			link |= LNK_1000MB;
-			break;
-		case SPEED_100:
-			link |= LNK_100MB;
-			break;
-		case SPEED_10:
-			link |= LNK_10MB;
-			break;
-		}
-	}
-
-	if (ecmd->duplex == DUPLEX_FULL)
-		link |= LNK_FULL_DUPLEX;
-
-	if (link != ap->link) {
-		struct cmd cmd;
-		printk(KERN_INFO "%s: Renegotiating link state\n",
-		       dev->name);
-
-		ap->link = link;
-		writel(link, &regs->TuneLink);
-		if (!ACE_IS_TIGON_I(ap))
-			writel(link, &regs->TuneFastLink);
-		wmb();
-
-		cmd.evt = C_LNK_NEGOTIATION;
-		cmd.code = 0;
-		cmd.idx = 0;
-		ace_issue_cmd(regs, &cmd);
-	}
-	return 0;
-}
-
-static void ace_get_drvinfo(struct net_device *dev,
-			    struct ethtool_drvinfo *info)
-{
-	struct ace_private *ap = netdev_priv(dev);
-
-	strlcpy(info->driver, "acenic", sizeof(info->driver));
-	snprintf(info->version, sizeof(info->version), "%i.%i.%i",
-		 ap->firmware_major, ap->firmware_minor,
-		 ap->firmware_fix);
-
-	if (ap->pdev)
-		strlcpy(info->bus_info, pci_name(ap->pdev),
-			sizeof(info->bus_info));
-
-}
-
-/*
- * Set the hardware MAC address.
- */
-static int ace_set_mac_addr(struct net_device *dev, void *p)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-	struct sockaddr *addr=p;
-	u8 *da;
-	struct cmd cmd;
-
-	if(netif_running(dev))
-		return -EBUSY;
-
-	memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
-
-	da = (u8 *)dev->dev_addr;
-
-	writel(da[0] << 8 | da[1], &regs->MacAddrHi);
-	writel((da[2] << 24) | (da[3] << 16) | (da[4] << 8) | da[5],
-	       &regs->MacAddrLo);
-
-	cmd.evt = C_SET_MAC_ADDR;
-	cmd.code = 0;
-	cmd.idx = 0;
-	ace_issue_cmd(regs, &cmd);
-
-	return 0;
-}
-
-
-static void ace_set_multicast_list(struct net_device *dev)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-	struct cmd cmd;
-
-	if ((dev->flags & IFF_ALLMULTI) && !(ap->mcast_all)) {
-		cmd.evt = C_SET_MULTICAST_MODE;
-		cmd.code = C_C_MCAST_ENABLE;
-		cmd.idx = 0;
-		ace_issue_cmd(regs, &cmd);
-		ap->mcast_all = 1;
-	} else if (ap->mcast_all) {
-		cmd.evt = C_SET_MULTICAST_MODE;
-		cmd.code = C_C_MCAST_DISABLE;
-		cmd.idx = 0;
-		ace_issue_cmd(regs, &cmd);
-		ap->mcast_all = 0;
-	}
-
-	if ((dev->flags & IFF_PROMISC) && !(ap->promisc)) {
-		cmd.evt = C_SET_PROMISC_MODE;
-		cmd.code = C_C_PROMISC_ENABLE;
-		cmd.idx = 0;
-		ace_issue_cmd(regs, &cmd);
-		ap->promisc = 1;
-	}else if (!(dev->flags & IFF_PROMISC) && (ap->promisc)) {
-		cmd.evt = C_SET_PROMISC_MODE;
-		cmd.code = C_C_PROMISC_DISABLE;
-		cmd.idx = 0;
-		ace_issue_cmd(regs, &cmd);
-		ap->promisc = 0;
-	}
-
-	/*
-	 * For the time being multicast relies on the upper layers
-	 * filtering it properly. The Firmware does not allow one to
-	 * set the entire multicast list at a time and keeping track of
-	 * it here is going to be messy.
-	 */
-	if (!netdev_mc_empty(dev) && !ap->mcast_all) {
-		cmd.evt = C_SET_MULTICAST_MODE;
-		cmd.code = C_C_MCAST_ENABLE;
-		cmd.idx = 0;
-		ace_issue_cmd(regs, &cmd);
-	}else if (!ap->mcast_all) {
-		cmd.evt = C_SET_MULTICAST_MODE;
-		cmd.code = C_C_MCAST_DISABLE;
-		cmd.idx = 0;
-		ace_issue_cmd(regs, &cmd);
-	}
-}
-
-
-static struct net_device_stats *ace_get_stats(struct net_device *dev)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_mac_stats __iomem *mac_stats =
-		(struct ace_mac_stats __iomem *)ap->regs->Stats;
-
-	dev->stats.rx_missed_errors = readl(&mac_stats->drop_space);
-	dev->stats.multicast = readl(&mac_stats->kept_mc);
-	dev->stats.collisions = readl(&mac_stats->coll);
-
-	return &dev->stats;
-}
-
-
-static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src,
-			       u32 dest, int size)
-{
-	void __iomem *tdest;
-	short tsize, i;
-
-	if (size <= 0)
-		return;
-
-	while (size > 0) {
-		tsize = min_t(u32, ((~dest & (ACE_WINDOW_SIZE - 1)) + 1),
-			    min_t(u32, size, ACE_WINDOW_SIZE));
-		tdest = (void __iomem *) &regs->Window +
-			(dest & (ACE_WINDOW_SIZE - 1));
-		writel(dest & ~(ACE_WINDOW_SIZE - 1), &regs->WinBase);
-		for (i = 0; i < (tsize / 4); i++) {
-			/* Firmware is big-endian */
-			writel(be32_to_cpup(src), tdest);
-			src++;
-			tdest += 4;
-			dest += 4;
-			size -= 4;
-		}
-	}
-}
-
-
-static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int size)
-{
-	void __iomem *tdest;
-	short tsize = 0, i;
-
-	if (size <= 0)
-		return;
-
-	while (size > 0) {
-		tsize = min_t(u32, ((~dest & (ACE_WINDOW_SIZE - 1)) + 1),
-				min_t(u32, size, ACE_WINDOW_SIZE));
-		tdest = (void __iomem *) &regs->Window +
-			(dest & (ACE_WINDOW_SIZE - 1));
-		writel(dest & ~(ACE_WINDOW_SIZE - 1), &regs->WinBase);
-
-		for (i = 0; i < (tsize / 4); i++) {
-			writel(0, tdest + i*4);
-		}
-
-		dest += tsize;
-		size -= tsize;
-	}
-}
-
-
-/*
- * Download the firmware into the SRAM on the NIC
- *
- * This operation requires the NIC to be halted and is performed with
- * interrupts disabled and with the spinlock hold.
- */
-static int __devinit ace_load_firmware(struct net_device *dev)
-{
-	const struct firmware *fw;
-	const char *fw_name = "/*(DEBLOBBED)*/";
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-	const __be32 *fw_data;
-	u32 load_addr;
-	int ret;
-
-	if (!(readl(&regs->CpuCtrl) & CPU_HALTED)) {
-		printk(KERN_ERR "%s: trying to download firmware while the "
-		       "CPU is running!\n", ap->name);
-		return -EFAULT;
-	}
-
-	if (ACE_IS_TIGON_I(ap))
-		fw_name = "/*(DEBLOBBED)*/";
-
-	ret = reject_firmware(&fw, fw_name, &ap->pdev->dev);
-	if (ret) {
-		printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n",
-		       ap->name, fw_name);
-		return ret;
-	}
-
-	fw_data = (void *)fw->data;
-
-	/* Firmware blob starts with version numbers, followed by
-	   load and start address. Remainder is the blob to be loaded
-	   contiguously from load address. We don't bother to represent
-	   the BSS/SBSS sections any more, since we were clearing the
-	   whole thing anyway. */
-	ap->firmware_major = fw->data[0];
-	ap->firmware_minor = fw->data[1];
-	ap->firmware_fix = fw->data[2];
-
-	ap->firmware_start = be32_to_cpu(fw_data[1]);
-	if (ap->firmware_start < 0x4000 || ap->firmware_start >= 0x80000) {
-		printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n",
-		       ap->name, ap->firmware_start, fw_name);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	load_addr = be32_to_cpu(fw_data[2]);
-	if (load_addr < 0x4000 || load_addr >= 0x80000) {
-		printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n",
-		       ap->name, load_addr, fw_name);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/*
-	 * Do not try to clear more than 512KiB or we end up seeing
-	 * funny things on NICs with only 512KiB SRAM
-	 */
-	ace_clear(regs, 0x2000, 0x80000-0x2000);
-	ace_copy(regs, &fw_data[3], load_addr, fw->size-12);
- out:
-	release_firmware(fw);
-	return ret;
-}
-
-
-/*
- * The eeprom on the AceNIC is an Atmel i2c EEPROM.
- *
- * Accessing the EEPROM is `interesting' to say the least - don't read
- * this code right after dinner.
- *
- * This is all about black magic and bit-banging the device .... I
- * wonder in what hospital they have put the guy who designed the i2c
- * specs.
- *
- * Oh yes, this is only the beginning!
- *
- * Thanks to Stevarino Webinski for helping tracking down the bugs in the
- * code i2c readout code by beta testing all my hacks.
- */
-static void __devinit eeprom_start(struct ace_regs __iomem *regs)
-{
-	u32 local;
-
-	readl(&regs->LocalCtrl);
-	udelay(ACE_SHORT_DELAY);
-	local = readl(&regs->LocalCtrl);
-	local |= EEPROM_DATA_OUT | EEPROM_WRITE_ENABLE;
-	writel(local, &regs->LocalCtrl);
-	readl(&regs->LocalCtrl);
-	mb();
-	udelay(ACE_SHORT_DELAY);
-	local |= EEPROM_CLK_OUT;
-	writel(local, &regs->LocalCtrl);
-	readl(&regs->LocalCtrl);
-	mb();
-	udelay(ACE_SHORT_DELAY);
-	local &= ~EEPROM_DATA_OUT;
-	writel(local, &regs->LocalCtrl);
-	readl(&regs->LocalCtrl);
-	mb();
-	udelay(ACE_SHORT_DELAY);
-	local &= ~EEPROM_CLK_OUT;
-	writel(local, &regs->LocalCtrl);
-	readl(&regs->LocalCtrl);
-	mb();
-}
-
-
-static void __devinit eeprom_prep(struct ace_regs __iomem *regs, u8 magic)
-{
-	short i;
-	u32 local;
-
-	udelay(ACE_SHORT_DELAY);
-	local = readl(&regs->LocalCtrl);
-	local &= ~EEPROM_DATA_OUT;
-	local |= EEPROM_WRITE_ENABLE;
-	writel(local, &regs->LocalCtrl);
-	readl(&regs->LocalCtrl);
-	mb();
-
-	for (i = 0; i < 8; i++, magic <<= 1) {
-		udelay(ACE_SHORT_DELAY);
-		if (magic & 0x80)
-			local |= EEPROM_DATA_OUT;
-		else
-			local &= ~EEPROM_DATA_OUT;
-		writel(local, &regs->LocalCtrl);
-		readl(&regs->LocalCtrl);
-		mb();
-
-		udelay(ACE_SHORT_DELAY);
-		local |= EEPROM_CLK_OUT;
-		writel(local, &regs->LocalCtrl);
-		readl(&regs->LocalCtrl);
-		mb();
-		udelay(ACE_SHORT_DELAY);
-		local &= ~(EEPROM_CLK_OUT | EEPROM_DATA_OUT);
-		writel(local, &regs->LocalCtrl);
-		readl(&regs->LocalCtrl);
-		mb();
-	}
-}
-
-
-static int __devinit eeprom_check_ack(struct ace_regs __iomem *regs)
-{
-	int state;
-	u32 local;
-
-	local = readl(&regs->LocalCtrl);
-	local &= ~EEPROM_WRITE_ENABLE;
-	writel(local, &regs->LocalCtrl);
-	readl(&regs->LocalCtrl);
-	mb();
-	udelay(ACE_LONG_DELAY);
-	local |= EEPROM_CLK_OUT;
-	writel(local, &regs->LocalCtrl);
-	readl(&regs->LocalCtrl);
-	mb();
-	udelay(ACE_SHORT_DELAY);
-	/* sample data in middle of high clk */
-	state = (readl(&regs->LocalCtrl) & EEPROM_DATA_IN) != 0;
-	udelay(ACE_SHORT_DELAY);
-	mb();
-	writel(readl(&regs->LocalCtrl) & ~EEPROM_CLK_OUT, &regs->LocalCtrl);
-	readl(&regs->LocalCtrl);
-	mb();
-
-	return state;
-}
-
-
-static void __devinit eeprom_stop(struct ace_regs __iomem *regs)
-{
-	u32 local;
-
-	udelay(ACE_SHORT_DELAY);
-	local = readl(&regs->LocalCtrl);
-	local |= EEPROM_WRITE_ENABLE;
-	writel(local, &regs->LocalCtrl);
-	readl(&regs->LocalCtrl);
-	mb();
-	udelay(ACE_SHORT_DELAY);
-	local &= ~EEPROM_DATA_OUT;
-	writel(local, &regs->LocalCtrl);
-	readl(&regs->LocalCtrl);
-	mb();
-	udelay(ACE_SHORT_DELAY);
-	local |= EEPROM_CLK_OUT;
-	writel(local, &regs->LocalCtrl);
-	readl(&regs->LocalCtrl);
-	mb();
-	udelay(ACE_SHORT_DELAY);
-	local |= EEPROM_DATA_OUT;
-	writel(local, &regs->LocalCtrl);
-	readl(&regs->LocalCtrl);
-	mb();
-	udelay(ACE_LONG_DELAY);
-	local &= ~EEPROM_CLK_OUT;
-	writel(local, &regs->LocalCtrl);
-	mb();
-}
-
-
-/*
- * Read a whole byte from the EEPROM.
- */
-static int __devinit read_eeprom_byte(struct net_device *dev,
-				   unsigned long offset)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-	unsigned long flags;
-	u32 local;
-	int result = 0;
-	short i;
-
-	/*
-	 * Don't take interrupts on this CPU will bit banging
-	 * the %#%#@$ I2C device
-	 */
-	local_irq_save(flags);
-
-	eeprom_start(regs);
-
-	eeprom_prep(regs, EEPROM_WRITE_SELECT);
-	if (eeprom_check_ack(regs)) {
-		local_irq_restore(flags);
-		printk(KERN_ERR "%s: Unable to sync eeprom\n", ap->name);
-		result = -EIO;
-		goto eeprom_read_error;
-	}
-
-	eeprom_prep(regs, (offset >> 8) & 0xff);
-	if (eeprom_check_ack(regs)) {
-		local_irq_restore(flags);
-		printk(KERN_ERR "%s: Unable to set address byte 0\n",
-		       ap->name);
-		result = -EIO;
-		goto eeprom_read_error;
-	}
-
-	eeprom_prep(regs, offset & 0xff);
-	if (eeprom_check_ack(regs)) {
-		local_irq_restore(flags);
-		printk(KERN_ERR "%s: Unable to set address byte 1\n",
-		       ap->name);
-		result = -EIO;
-		goto eeprom_read_error;
-	}
-
-	eeprom_start(regs);
-	eeprom_prep(regs, EEPROM_READ_SELECT);
-	if (eeprom_check_ack(regs)) {
-		local_irq_restore(flags);
-		printk(KERN_ERR "%s: Unable to set READ_SELECT\n",
-		       ap->name);
-		result = -EIO;
-		goto eeprom_read_error;
-	}
-
-	for (i = 0; i < 8; i++) {
-		local = readl(&regs->LocalCtrl);
-		local &= ~EEPROM_WRITE_ENABLE;
-		writel(local, &regs->LocalCtrl);
-		readl(&regs->LocalCtrl);
-		udelay(ACE_LONG_DELAY);
-		mb();
-		local |= EEPROM_CLK_OUT;
-		writel(local, &regs->LocalCtrl);
-		readl(&regs->LocalCtrl);
-		mb();
-		udelay(ACE_SHORT_DELAY);
-		/* sample data mid high clk */
-		result = (result << 1) |
-			((readl(&regs->LocalCtrl) & EEPROM_DATA_IN) != 0);
-		udelay(ACE_SHORT_DELAY);
-		mb();
-		local = readl(&regs->LocalCtrl);
-		local &= ~EEPROM_CLK_OUT;
-		writel(local, &regs->LocalCtrl);
-		readl(&regs->LocalCtrl);
-		udelay(ACE_SHORT_DELAY);
-		mb();
-		if (i == 7) {
-			local |= EEPROM_WRITE_ENABLE;
-			writel(local, &regs->LocalCtrl);
-			readl(&regs->LocalCtrl);
-			mb();
-			udelay(ACE_SHORT_DELAY);
-		}
-	}
-
-	local |= EEPROM_DATA_OUT;
-	writel(local, &regs->LocalCtrl);
-	readl(&regs->LocalCtrl);
-	mb();
-	udelay(ACE_SHORT_DELAY);
-	writel(readl(&regs->LocalCtrl) | EEPROM_CLK_OUT, &regs->LocalCtrl);
-	readl(&regs->LocalCtrl);
-	udelay(ACE_LONG_DELAY);
-	writel(readl(&regs->LocalCtrl) & ~EEPROM_CLK_OUT, &regs->LocalCtrl);
-	readl(&regs->LocalCtrl);
-	mb();
-	udelay(ACE_SHORT_DELAY);
-	eeprom_stop(regs);
-
-	local_irq_restore(flags);
- out:
-	return result;
-
- eeprom_read_error:
-	printk(KERN_ERR "%s: Unable to read eeprom byte 0x%02lx\n",
-	       ap->name, offset);
-	goto out;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/acenic.h linux-libre-3.2-gnu/drivers/net/acenic.h
--- linux-libre-3.1-gnu/drivers/net/acenic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/acenic.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,790 +0,0 @@
-#ifndef _ACENIC_H_
-#define _ACENIC_H_
-#include <linux/interrupt.h>
-
-
-/*
- * Generate TX index update each time, when TX ring is closed.
- * Normally, this is not useful, because results in more dma (and irqs
- * without TX_COAL_INTS_ONLY).
- */
-#define USE_TX_COAL_NOW	 0
-
-/*
- * Addressing:
- *
- * The Tigon uses 64-bit host addresses, regardless of their actual
- * length, and it expects a big-endian format. For 32 bit systems the
- * upper 32 bits of the address are simply ignored (zero), however for
- * little endian 64 bit systems (Alpha) this looks strange with the
- * two parts of the address word being swapped.
- *
- * The addresses are split in two 32 bit words for all architectures
- * as some of them are in PCI shared memory and it is necessary to use
- * readl/writel to access them.
- *
- * The addressing code is derived from Pete Wyckoff's work, but
- * modified to deal properly with readl/writel usage.
- */
-
-struct ace_regs {
-	u32	pad0[16];	/* PCI control registers */
-
-	u32	HostCtrl;	/* 0x40 */
-	u32	LocalCtrl;
-
-	u32	pad1[2];
-
-	u32	MiscCfg;	/* 0x50 */
-
-	u32	pad2[2];
-
-	u32	PciState;
-
-	u32	pad3[2];	/* 0x60 */
-
-	u32	WinBase;
-	u32	WinData;
-
-	u32	pad4[12];	/* 0x70 */
-
-	u32	DmaWriteState;	/* 0xa0 */
-	u32	pad5[3];
-	u32	DmaReadState;	/* 0xb0 */
-
-	u32	pad6[26];
-
-	u32	AssistState;
-
-	u32	pad7[8];	/* 0x120 */
-
-	u32	CpuCtrl;	/* 0x140 */
-	u32	Pc;
-
-	u32	pad8[3];
-
-	u32	SramAddr;	/* 0x154 */
-	u32	SramData;
-
-	u32	pad9[49];
-
-	u32	MacRxState;	/* 0x220 */
-
-	u32	pad10[7];
-
-	u32	CpuBCtrl;	/* 0x240 */
-	u32	PcB;
-
-	u32	pad11[3];
-
-	u32	SramBAddr;	/* 0x254 */
-	u32	SramBData;
-
-	u32	pad12[105];
-
-	u32	pad13[32];	/* 0x400 */
-	u32	Stats[32];
-
-	u32	Mb0Hi;		/* 0x500 */
-	u32	Mb0Lo;
-	u32	Mb1Hi;
-	u32	CmdPrd;
-	u32	Mb2Hi;
-	u32	TxPrd;
-	u32	Mb3Hi;
-	u32	RxStdPrd;
-	u32	Mb4Hi;
-	u32	RxJumboPrd;
-	u32	Mb5Hi;
-	u32	RxMiniPrd;
-	u32	Mb6Hi;
-	u32	Mb6Lo;
-	u32	Mb7Hi;
-	u32	Mb7Lo;
-	u32	Mb8Hi;
-	u32	Mb8Lo;
-	u32	Mb9Hi;
-	u32	Mb9Lo;
-	u32	MbAHi;
-	u32	MbALo;
-	u32	MbBHi;
-	u32	MbBLo;
-	u32	MbCHi;
-	u32	MbCLo;
-	u32	MbDHi;
-	u32	MbDLo;
-	u32	MbEHi;
-	u32	MbELo;
-	u32	MbFHi;
-	u32	MbFLo;
-
-	u32	pad14[32];
-
-	u32	MacAddrHi;	/* 0x600 */
-	u32	MacAddrLo;
-	u32	InfoPtrHi;
-	u32	InfoPtrLo;
-	u32	MultiCastHi;	/* 0x610 */
-	u32	MultiCastLo;
-	u32	ModeStat;
-	u32	DmaReadCfg;
-	u32	DmaWriteCfg;	/* 0x620 */
-	u32	TxBufRat;
-	u32	EvtCsm;
-	u32	CmdCsm;
-	u32	TuneRxCoalTicks;/* 0x630 */
-	u32	TuneTxCoalTicks;
-	u32	TuneStatTicks;
-	u32	TuneMaxTxDesc;
-	u32	TuneMaxRxDesc;	/* 0x640 */
-	u32	TuneTrace;
-	u32	TuneLink;
-	u32	TuneFastLink;
-	u32	TracePtr;	/* 0x650 */
-	u32	TraceStrt;
-	u32	TraceLen;
-	u32	IfIdx;
-	u32	IfMtu;		/* 0x660 */
-	u32	MaskInt;
-	u32	GigLnkState;
-	u32	FastLnkState;
-	u32	pad16[4];	/* 0x670 */
-	u32	RxRetCsm;	/* 0x680 */
-
-	u32	pad17[31];
-
-	u32	CmdRng[64];	/* 0x700 */
-	u32	Window[0x200];
-};
-
-
-typedef struct {
-	u32 addrhi;
-	u32 addrlo;
-} aceaddr;
-
-
-#define ACE_WINDOW_SIZE	0x800
-
-#define ACE_JUMBO_MTU 9000
-#define ACE_STD_MTU 1500
-
-#define ACE_TRACE_SIZE 0x8000
-
-/*
- * Host control register bits.
- */
-
-#define IN_INT		0x01
-#define CLR_INT		0x02
-#define HW_RESET	0x08
-#define BYTE_SWAP	0x10
-#define WORD_SWAP	0x20
-#define MASK_INTS	0x40
-
-/*
- * Local control register bits.
- */
-
-#define EEPROM_DATA_IN		0x800000
-#define EEPROM_DATA_OUT		0x400000
-#define EEPROM_WRITE_ENABLE	0x200000
-#define EEPROM_CLK_OUT		0x100000
-
-#define EEPROM_BASE		0xa0000000
-
-#define EEPROM_WRITE_SELECT	0xa0
-#define EEPROM_READ_SELECT	0xa1
-
-#define SRAM_BANK_512K		0x200
-
-
-/*
- * udelay() values for when clocking the eeprom
- */
-#define ACE_SHORT_DELAY		2
-#define ACE_LONG_DELAY		4
-
-
-/*
- * Misc Config bits
- */
-
-#define SYNC_SRAM_TIMING	0x100000
-
-
-/*
- * CPU state bits.
- */
-
-#define CPU_RESET		0x01
-#define CPU_TRACE		0x02
-#define CPU_PROM_FAILED		0x10
-#define CPU_HALT		0x00010000
-#define CPU_HALTED		0xffff0000
-
-
-/*
- * PCI State bits.
- */
-
-#define DMA_READ_MAX_4		0x04
-#define DMA_READ_MAX_16		0x08
-#define DMA_READ_MAX_32		0x0c
-#define DMA_READ_MAX_64		0x10
-#define DMA_READ_MAX_128	0x14
-#define DMA_READ_MAX_256	0x18
-#define DMA_READ_MAX_1K		0x1c
-#define DMA_WRITE_MAX_4		0x20
-#define DMA_WRITE_MAX_16	0x40
-#define DMA_WRITE_MAX_32	0x60
-#define DMA_WRITE_MAX_64	0x80
-#define DMA_WRITE_MAX_128	0xa0
-#define DMA_WRITE_MAX_256	0xc0
-#define DMA_WRITE_MAX_1K	0xe0
-#define DMA_READ_WRITE_MASK	0xfc
-#define MEM_READ_MULTIPLE	0x00020000
-#define PCI_66MHZ		0x00080000
-#define PCI_32BIT		0x00100000
-#define DMA_WRITE_ALL_ALIGN	0x00800000
-#define READ_CMD_MEM		0x06000000
-#define WRITE_CMD_MEM		0x70000000
-
-
-/*
- * Mode status
- */
-
-#define ACE_BYTE_SWAP_BD	0x02
-#define ACE_WORD_SWAP_BD	0x04		/* not actually used */
-#define ACE_WARN		0x08
-#define ACE_BYTE_SWAP_DMA	0x10
-#define ACE_NO_JUMBO_FRAG	0x200
-#define ACE_FATAL		0x40000000
-
-
-/*
- * DMA config
- */
-
-#define DMA_THRESH_1W		0x10
-#define DMA_THRESH_2W		0x20
-#define DMA_THRESH_4W		0x40
-#define DMA_THRESH_8W		0x80
-#define DMA_THRESH_16W		0x100
-#define DMA_THRESH_32W		0x0	/* not described in doc, but exists. */
-
-
-/*
- * Tuning parameters
- */
-
-#define TICKS_PER_SEC		1000000
-
-
-/*
- * Link bits
- */
-
-#define LNK_PREF		0x00008000
-#define LNK_10MB		0x00010000
-#define LNK_100MB		0x00020000
-#define LNK_1000MB		0x00040000
-#define LNK_FULL_DUPLEX		0x00080000
-#define LNK_HALF_DUPLEX		0x00100000
-#define LNK_TX_FLOW_CTL_Y	0x00200000
-#define LNK_NEG_ADVANCED	0x00400000
-#define LNK_RX_FLOW_CTL_Y	0x00800000
-#define LNK_NIC			0x01000000
-#define LNK_JAM			0x02000000
-#define LNK_JUMBO		0x04000000
-#define LNK_ALTEON		0x08000000
-#define LNK_NEG_FCTL		0x10000000
-#define LNK_NEGOTIATE		0x20000000
-#define LNK_ENABLE		0x40000000
-#define LNK_UP			0x80000000
-
-
-/*
- * Event definitions
- */
-
-#define EVT_RING_ENTRIES	256
-#define EVT_RING_SIZE	(EVT_RING_ENTRIES * sizeof(struct event))
-
-struct event {
-#ifdef __LITTLE_ENDIAN_BITFIELD
-	u32	idx:12;
-	u32	code:12;
-	u32	evt:8;
-#else
-	u32	evt:8;
-	u32	code:12;
-	u32	idx:12;
-#endif
-	u32     pad;
-};
-
-
-/*
- * Events
- */
-
-#define E_FW_RUNNING		0x01
-#define E_STATS_UPDATED		0x04
-
-#define E_STATS_UPDATE		0x04
-
-#define E_LNK_STATE		0x06
-#define E_C_LINK_UP		0x01
-#define E_C_LINK_DOWN		0x02
-#define E_C_LINK_10_100		0x03
-
-#define E_ERROR			0x07
-#define E_C_ERR_INVAL_CMD	0x01
-#define E_C_ERR_UNIMP_CMD	0x02
-#define E_C_ERR_BAD_CFG		0x03
-
-#define E_MCAST_LIST		0x08
-#define E_C_MCAST_ADDR_ADD	0x01
-#define E_C_MCAST_ADDR_DEL	0x02
-
-#define E_RESET_JUMBO_RNG	0x09
-
-
-/*
- * Commands
- */
-
-#define CMD_RING_ENTRIES	64
-
-struct cmd {
-#ifdef __LITTLE_ENDIAN_BITFIELD
-	u32	idx:12;
-	u32	code:12;
-	u32	evt:8;
-#else
-	u32	evt:8;
-	u32	code:12;
-	u32	idx:12;
-#endif
-};
-
-
-#define C_HOST_STATE		0x01
-#define C_C_STACK_UP		0x01
-#define C_C_STACK_DOWN		0x02
-
-#define C_FDR_FILTERING		0x02
-#define C_C_FDR_FILT_ENABLE	0x01
-#define C_C_FDR_FILT_DISABLE	0x02
-
-#define C_SET_RX_PRD_IDX	0x03
-#define C_UPDATE_STATS		0x04
-#define C_RESET_JUMBO_RNG	0x05
-#define C_ADD_MULTICAST_ADDR	0x08
-#define C_DEL_MULTICAST_ADDR	0x09
-
-#define C_SET_PROMISC_MODE	0x0a
-#define C_C_PROMISC_ENABLE	0x01
-#define C_C_PROMISC_DISABLE	0x02
-
-#define C_LNK_NEGOTIATION	0x0b
-#define C_C_NEGOTIATE_BOTH	0x00
-#define C_C_NEGOTIATE_GIG	0x01
-#define C_C_NEGOTIATE_10_100	0x02
-
-#define C_SET_MAC_ADDR		0x0c
-#define C_CLEAR_PROFILE		0x0d
-
-#define C_SET_MULTICAST_MODE	0x0e
-#define C_C_MCAST_ENABLE	0x01
-#define C_C_MCAST_DISABLE	0x02
-
-#define C_CLEAR_STATS		0x0f
-#define C_SET_RX_JUMBO_PRD_IDX	0x10
-#define C_REFRESH_STATS		0x11
-
-
-/*
- * Descriptor flags
- */
-#define BD_FLG_TCP_UDP_SUM	0x01
-#define BD_FLG_IP_SUM		0x02
-#define BD_FLG_END		0x04
-#define BD_FLG_MORE		0x08
-#define BD_FLG_JUMBO		0x10
-#define BD_FLG_UCAST		0x20
-#define BD_FLG_MCAST		0x40
-#define BD_FLG_BCAST		0x60
-#define BD_FLG_TYP_MASK		0x60
-#define BD_FLG_IP_FRAG		0x80
-#define BD_FLG_IP_FRAG_END	0x100
-#define BD_FLG_VLAN_TAG		0x200
-#define BD_FLG_FRAME_ERROR	0x400
-#define BD_FLG_COAL_NOW		0x800
-#define BD_FLG_MINI		0x1000
-
-
-/*
- * Ring Control block flags
- */
-#define RCB_FLG_TCP_UDP_SUM	0x01
-#define RCB_FLG_IP_SUM		0x02
-#define RCB_FLG_NO_PSEUDO_HDR	0x08
-#define RCB_FLG_VLAN_ASSIST	0x10
-#define RCB_FLG_COAL_INT_ONLY	0x20
-#define RCB_FLG_TX_HOST_RING	0x40
-#define RCB_FLG_IEEE_SNAP_SUM	0x80
-#define RCB_FLG_EXT_RX_BD	0x100
-#define RCB_FLG_RNG_DISABLE	0x200
-
-
-/*
- * TX ring - maximum TX ring entries for Tigon I's is 128
- */
-#define MAX_TX_RING_ENTRIES	256
-#define TIGON_I_TX_RING_ENTRIES	128
-#define TX_RING_SIZE		(MAX_TX_RING_ENTRIES * sizeof(struct tx_desc))
-#define TX_RING_BASE		0x3800
-
-struct tx_desc{
-        aceaddr	addr;
-	u32	flagsize;
-#if 0
-/*
- * This is in PCI shared mem and must be accessed with readl/writel
- * real layout is:
- */
-#if __LITTLE_ENDIAN
-	u16	flags;
-	u16	size;
-	u16	vlan;
-	u16	reserved;
-#else
-	u16	size;
-	u16	flags;
-	u16	reserved;
-	u16	vlan;
-#endif
-#endif
-	u32	vlanres;
-};
-
-
-#define RX_STD_RING_ENTRIES	512
-#define RX_STD_RING_SIZE	(RX_STD_RING_ENTRIES * sizeof(struct rx_desc))
-
-#define RX_JUMBO_RING_ENTRIES	256
-#define RX_JUMBO_RING_SIZE	(RX_JUMBO_RING_ENTRIES *sizeof(struct rx_desc))
-
-#define RX_MINI_RING_ENTRIES	1024
-#define RX_MINI_RING_SIZE	(RX_MINI_RING_ENTRIES *sizeof(struct rx_desc))
-
-#define RX_RETURN_RING_ENTRIES	2048
-#define RX_RETURN_RING_SIZE	(RX_MAX_RETURN_RING_ENTRIES * \
-				 sizeof(struct rx_desc))
-
-struct rx_desc{
-	aceaddr	addr;
-#ifdef __LITTLE_ENDIAN
-	u16	size;
-	u16	idx;
-#else
-	u16	idx;
-	u16	size;
-#endif
-#ifdef __LITTLE_ENDIAN
-	u16	flags;
-	u16	type;
-#else
-	u16	type;
-	u16	flags;
-#endif
-#ifdef __LITTLE_ENDIAN
-	u16	tcp_udp_csum;
-	u16	ip_csum;
-#else
-	u16	ip_csum;
-	u16	tcp_udp_csum;
-#endif
-#ifdef __LITTLE_ENDIAN
-	u16	vlan;
-	u16	err_flags;
-#else
-	u16	err_flags;
-	u16	vlan;
-#endif
-	u32	reserved;
-	u32	opague;
-};
-
-
-/*
- * This struct is shared with the NIC firmware.
- */
-struct ring_ctrl {
-	aceaddr	rngptr;
-#ifdef __LITTLE_ENDIAN
-	u16	flags;
-	u16	max_len;
-#else
-	u16	max_len;
-	u16	flags;
-#endif
-	u32	pad;
-};
-
-
-struct ace_mac_stats {
-	u32 excess_colls;
-	u32 coll_1;
-	u32 coll_2;
-	u32 coll_3;
-	u32 coll_4;
-	u32 coll_5;
-	u32 coll_6;
-	u32 coll_7;
-	u32 coll_8;
-	u32 coll_9;
-	u32 coll_10;
-	u32 coll_11;
-	u32 coll_12;
-	u32 coll_13;
-	u32 coll_14;
-	u32 coll_15;
-	u32 late_coll;
-	u32 defers;
-	u32 crc_err;
-	u32 underrun;
-	u32 crs_err;
-	u32 pad[3];
-	u32 drop_ula;
-	u32 drop_mc;
-	u32 drop_fc;
-	u32 drop_space;
-	u32 coll;
-	u32 kept_bc;
-	u32 kept_mc;
-	u32 kept_uc;
-};
-
-
-struct ace_info {
-	union {
-		u32 stats[256];
-	} s;
-	struct ring_ctrl	evt_ctrl;
-	struct ring_ctrl	cmd_ctrl;
-	struct ring_ctrl	tx_ctrl;
-	struct ring_ctrl	rx_std_ctrl;
-	struct ring_ctrl	rx_jumbo_ctrl;
-	struct ring_ctrl	rx_mini_ctrl;
-	struct ring_ctrl	rx_return_ctrl;
-	aceaddr	evt_prd_ptr;
-	aceaddr	rx_ret_prd_ptr;
-	aceaddr	tx_csm_ptr;
-	aceaddr	stats2_ptr;
-};
-
-
-struct ring_info {
-	struct sk_buff		*skb;
-	DEFINE_DMA_UNMAP_ADDR(mapping);
-};
-
-
-/*
- * Funny... As soon as we add maplen on alpha, it starts to work
- * much slower. Hmm... is it because struct does not fit to one cacheline?
- * So, split tx_ring_info.
- */
-struct tx_ring_info {
-	struct sk_buff		*skb;
-	DEFINE_DMA_UNMAP_ADDR(mapping);
-	DEFINE_DMA_UNMAP_LEN(maplen);
-};
-
-
-/*
- * struct ace_skb holding the rings of skb's. This is an awful lot of
- * pointers, but I don't see any other smart mode to do this in an
- * efficient manner ;-(
- */
-struct ace_skb
-{
-	struct tx_ring_info	tx_skbuff[MAX_TX_RING_ENTRIES];
-	struct ring_info	rx_std_skbuff[RX_STD_RING_ENTRIES];
-	struct ring_info	rx_mini_skbuff[RX_MINI_RING_ENTRIES];
-	struct ring_info	rx_jumbo_skbuff[RX_JUMBO_RING_ENTRIES];
-};
-
-
-/*
- * Struct private for the AceNIC.
- *
- * Elements are grouped so variables used by the tx handling goes
- * together, and will go into the same cache lines etc. in order to
- * avoid cache line contention between the rx and tx handling on SMP.
- *
- * Frequently accessed variables are put at the beginning of the
- * struct to help the compiler generate better/shorter code.
- */
-struct ace_private
-{
-	struct ace_info		*info;
-	struct ace_regs	__iomem	*regs;		/* register base */
-	struct ace_skb		*skb;
-	dma_addr_t		info_dma;	/* 32/64 bit */
-
-	int			version, link;
-	int			promisc, mcast_all;
-
-	/*
-	 * TX elements
-	 */
-	struct tx_desc		*tx_ring;
-	u32			tx_prd;
-	volatile u32		tx_ret_csm;
-	int			tx_ring_entries;
-
-	/*
-	 * RX elements
-	 */
-	unsigned long		std_refill_busy
-				__attribute__ ((aligned (SMP_CACHE_BYTES)));
-	unsigned long		mini_refill_busy, jumbo_refill_busy;
-	atomic_t		cur_rx_bufs;
-	atomic_t		cur_mini_bufs;
-	atomic_t		cur_jumbo_bufs;
-	u32			rx_std_skbprd, rx_mini_skbprd, rx_jumbo_skbprd;
-	u32			cur_rx;
-
-	struct rx_desc		*rx_std_ring;
-	struct rx_desc		*rx_jumbo_ring;
-	struct rx_desc		*rx_mini_ring;
-	struct rx_desc		*rx_return_ring;
-
-	int			tasklet_pending, jumbo;
-	struct tasklet_struct	ace_tasklet;
-
-	struct event		*evt_ring;
-
-	volatile u32		*evt_prd, *rx_ret_prd, *tx_csm;
-
-	dma_addr_t		tx_ring_dma;	/* 32/64 bit */
-	dma_addr_t		rx_ring_base_dma;
-	dma_addr_t		evt_ring_dma;
-	dma_addr_t		evt_prd_dma, rx_ret_prd_dma, tx_csm_dma;
-
-	unsigned char		*trace_buf;
-	struct pci_dev		*pdev;
-	struct net_device	*next;
-	volatile int		fw_running;
-	int			board_idx;
-	u16			pci_command;
-	u8			pci_latency;
-	const char		*name;
-#ifdef INDEX_DEBUG
-	spinlock_t		debug_lock
-				__attribute__ ((aligned (SMP_CACHE_BYTES)));
-	u32			last_tx, last_std_rx, last_mini_rx;
-#endif
-	int			pci_using_dac;
-	u8			firmware_major;
-	u8			firmware_minor;
-	u8			firmware_fix;
-	u32			firmware_start;
-};
-
-
-#define TX_RESERVED	MAX_SKB_FRAGS
-
-static inline int tx_space (struct ace_private *ap, u32 csm, u32 prd)
-{
-	return (csm - prd - 1) & (ACE_TX_RING_ENTRIES(ap) - 1);
-}
-
-#define tx_free(ap) 		tx_space((ap)->tx_ret_csm, (ap)->tx_prd, ap)
-#define tx_ring_full(ap, csm, prd)	(tx_space(ap, csm, prd) <= TX_RESERVED)
-
-static inline void set_aceaddr(aceaddr *aa, dma_addr_t addr)
-{
-	u64 baddr = (u64) addr;
-	aa->addrlo = baddr & 0xffffffff;
-	aa->addrhi = baddr >> 32;
-	wmb();
-}
-
-
-static inline void ace_set_txprd(struct ace_regs __iomem *regs,
-				 struct ace_private *ap, u32 value)
-{
-#ifdef INDEX_DEBUG
-	unsigned long flags;
-	spin_lock_irqsave(&ap->debug_lock, flags);
-	writel(value, &regs->TxPrd);
-	if (value == ap->last_tx)
-		printk(KERN_ERR "AceNIC RACE ALERT! writing identical value "
-		       "to tx producer (%i)\n", value);
-	ap->last_tx = value;
-	spin_unlock_irqrestore(&ap->debug_lock, flags);
-#else
-	writel(value, &regs->TxPrd);
-#endif
-	wmb();
-}
-
-
-static inline void ace_mask_irq(struct net_device *dev)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-
-	if (ACE_IS_TIGON_I(ap))
-		writel(1, &regs->MaskInt);
-	else
-		writel(readl(&regs->HostCtrl) | MASK_INTS, &regs->HostCtrl);
-
-	ace_sync_irq(dev->irq);
-}
-
-
-static inline void ace_unmask_irq(struct net_device *dev)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs __iomem *regs = ap->regs;
-
-	if (ACE_IS_TIGON_I(ap))
-		writel(0, &regs->MaskInt);
-	else
-		writel(readl(&regs->HostCtrl) & ~MASK_INTS, &regs->HostCtrl);
-}
-
-
-/*
- * Prototypes
- */
-static int ace_init(struct net_device *dev);
-static void ace_load_std_rx_ring(struct net_device *dev, int nr_bufs);
-static void ace_load_mini_rx_ring(struct net_device *dev, int nr_bufs);
-static void ace_load_jumbo_rx_ring(struct net_device *dev, int nr_bufs);
-static irqreturn_t ace_interrupt(int irq, void *dev_id);
-static int ace_load_firmware(struct net_device *dev);
-static int ace_open(struct net_device *dev);
-static netdev_tx_t ace_start_xmit(struct sk_buff *skb,
-				  struct net_device *dev);
-static int ace_close(struct net_device *dev);
-static void ace_tasklet(unsigned long dev);
-static void ace_dump_trace(struct ace_private *ap);
-static void ace_set_multicast_list(struct net_device *dev);
-static int ace_change_mtu(struct net_device *dev, int new_mtu);
-static int ace_set_mac_addr(struct net_device *dev, void *p);
-static void ace_set_rxtx_parms(struct net_device *dev, int jumbo);
-static int ace_allocate_descriptors(struct net_device *dev);
-static void ace_free_descriptors(struct net_device *dev);
-static void ace_init_cleanup(struct net_device *dev);
-static struct net_device_stats *ace_get_stats(struct net_device *dev);
-static int read_eeprom_byte(struct net_device *dev, unsigned long offset);
-
-#endif /* _ACENIC_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/amd8111e.c linux-libre-3.2-gnu/drivers/net/amd8111e.c
--- linux-libre-3.1-gnu/drivers/net/amd8111e.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/amd8111e.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1992 +0,0 @@
-
-/* Advanced  Micro Devices Inc. AMD8111E Linux Network Driver
- * Copyright (C) 2004 Advanced Micro Devices
- *
- *
- * Copyright 2001,2002 Jeff Garzik <jgarzik@mandrakesoft.com> [ 8139cp.c,tg3.c ]
- * Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com)[ tg3.c]
- * Copyright 1996-1999 Thomas Bogendoerfer [ pcnet32.c ]
- * Derived from the lance driver written 1993,1994,1995 by Donald Becker.
- * Copyright 1993 United States Government as represented by the
- *	Director, National Security Agency.[ pcnet32.c ]
- * Carsten Langgaard, carstenl@mips.com [ pcnet32.c ]
- * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
- * USA
-
-Module Name:
-
-	amd8111e.c
-
-Abstract:
-
- 	 AMD8111 based 10/100 Ethernet Controller Driver.
-
-Environment:
-
-	Kernel Mode
-
-Revision History:
- 	3.0.0
-	   Initial Revision.
-	3.0.1
-	 1. Dynamic interrupt coalescing.
-	 2. Removed prev_stats.
-	 3. MII support.
-	 4. Dynamic IPG support
-	3.0.2  05/29/2003
-	 1. Bug fix: Fixed failure to send jumbo packets larger than 4k.
-	 2. Bug fix: Fixed VLAN support failure.
-	 3. Bug fix: Fixed receive interrupt coalescing bug.
-	 4. Dynamic IPG support is disabled by default.
-	3.0.3 06/05/2003
-	 1. Bug fix: Fixed failure to close the interface if SMP is enabled.
-	3.0.4 12/09/2003
-	 1. Added set_mac_address routine for bonding driver support.
-	 2. Tested the driver for bonding support
-	 3. Bug fix: Fixed mismach in actual receive buffer lenth and lenth
-	    indicated to the h/w.
-	 4. Modified amd8111e_rx() routine to receive all the received packets
-	    in the first interrupt.
-	 5. Bug fix: Corrected  rx_errors  reported in get_stats() function.
-	3.0.5 03/22/2004
-	 1. Added NAPI support
-
-*/
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/compiler.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-#include <linux/if_vlan.h>
-#include <linux/ctype.h>
-#include <linux/crc32.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-#define AMD8111E_VLAN_TAG_USED 1
-#else
-#define AMD8111E_VLAN_TAG_USED 0
-#endif
-
-#include "amd8111e.h"
-#define MODULE_NAME	"amd8111e"
-#define MODULE_VERS	"3.0.7"
-MODULE_AUTHOR("Advanced Micro Devices, Inc.");
-MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version "MODULE_VERS);
-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 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);
-MODULE_PARM_DESC(dynamic_ipg, "Enable or Disable dynamic IPG, 1: Enable, 0: Disable");
-
-static DEFINE_PCI_DEVICE_TABLE(amd8111e_pci_tbl) = {
-
-	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD8111E_7462,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-	{ 0, }
-
-};
-/*
-This function will read the PHY registers.
-*/
-static int amd8111e_read_phy(struct amd8111e_priv* lp, int phy_id, int reg, u32* val)
-{
-	void __iomem *mmio = lp->mmio;
-	unsigned int reg_val;
-	unsigned int repeat= REPEAT_CNT;
-
-	reg_val = readl(mmio + PHY_ACCESS);
-	while (reg_val & PHY_CMD_ACTIVE)
-		reg_val = readl( mmio + PHY_ACCESS );
-
-	writel( PHY_RD_CMD | ((phy_id & 0x1f) << 21) |
-			   ((reg & 0x1f) << 16),  mmio +PHY_ACCESS);
-	do{
-		reg_val = readl(mmio + PHY_ACCESS);
-		udelay(30);  /* It takes 30 us to read/write data */
-	} while (--repeat && (reg_val & PHY_CMD_ACTIVE));
-	if(reg_val & PHY_RD_ERR)
-		goto err_phy_read;
-
-	*val = reg_val & 0xffff;
-	return 0;
-err_phy_read:
-	*val = 0;
-	return -EINVAL;
-
-}
-
-/*
-This function will write into PHY registers.
-*/
-static int amd8111e_write_phy(struct amd8111e_priv* lp,int phy_id, int reg, u32 val)
-{
-	unsigned int repeat = REPEAT_CNT;
-	void __iomem *mmio = lp->mmio;
-	unsigned int reg_val;
-
-	reg_val = readl(mmio + PHY_ACCESS);
-	while (reg_val & PHY_CMD_ACTIVE)
-		reg_val = readl( mmio + PHY_ACCESS );
-
-	writel( PHY_WR_CMD | ((phy_id & 0x1f) << 21) |
-			   ((reg & 0x1f) << 16)|val, mmio + PHY_ACCESS);
-
-	do{
-		reg_val = readl(mmio + PHY_ACCESS);
-		udelay(30);  /* It takes 30 us to read/write the data */
-	} while (--repeat && (reg_val & PHY_CMD_ACTIVE));
-
-	if(reg_val & PHY_RD_ERR)
-		goto err_phy_write;
-
-	return 0;
-
-err_phy_write:
-	return -EINVAL;
-
-}
-/*
-This is the mii register read function provided to the mii interface.
-*/
-static int amd8111e_mdio_read(struct net_device * dev, int phy_id, int reg_num)
-{
-	struct amd8111e_priv* lp = netdev_priv(dev);
-	unsigned int reg_val;
-
-	amd8111e_read_phy(lp,phy_id,reg_num,&reg_val);
-	return reg_val;
-
-}
-
-/*
-This is the mii register write function provided to the mii interface.
-*/
-static void amd8111e_mdio_write(struct net_device * dev, int phy_id, int reg_num, int val)
-{
-	struct amd8111e_priv* lp = netdev_priv(dev);
-
-	amd8111e_write_phy(lp, phy_id, reg_num, val);
-}
-
-/*
-This function will set PHY speed. During initialization sets the original speed to 100 full.
-*/
-static void amd8111e_set_ext_phy(struct net_device *dev)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	u32 bmcr,advert,tmp;
-
-	/* Determine mii register values to set the speed */
-	advert = amd8111e_mdio_read(dev, lp->ext_phy_addr, MII_ADVERTISE);
-	tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
-	switch (lp->ext_phy_option){
-
-		default:
-		case SPEED_AUTONEG: /* advertise all values */
-			tmp |= ( ADVERTISE_10HALF|ADVERTISE_10FULL|
-				ADVERTISE_100HALF|ADVERTISE_100FULL) ;
-			break;
-		case SPEED10_HALF:
-			tmp |= ADVERTISE_10HALF;
-			break;
-		case SPEED10_FULL:
-			tmp |= ADVERTISE_10FULL;
-			break;
-		case SPEED100_HALF:
-			tmp |= ADVERTISE_100HALF;
-			break;
-		case SPEED100_FULL:
-			tmp |= ADVERTISE_100FULL;
-			break;
-	}
-
-	if(advert != tmp)
-		amd8111e_mdio_write(dev, lp->ext_phy_addr, MII_ADVERTISE, tmp);
-	/* Restart auto negotiation */
-	bmcr = amd8111e_mdio_read(dev, lp->ext_phy_addr, MII_BMCR);
-	bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
-	amd8111e_mdio_write(dev, lp->ext_phy_addr, MII_BMCR, bmcr);
-
-}
-
-/*
-This function will unmap skb->data space and will free
-all transmit and receive skbuffs.
-*/
-static int amd8111e_free_skbs(struct net_device *dev)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	struct sk_buff* rx_skbuff;
-	int i;
-
-	/* Freeing transmit skbs */
-	for(i = 0; i < NUM_TX_BUFFERS; i++){
-		if(lp->tx_skbuff[i]){
-			pci_unmap_single(lp->pci_dev,lp->tx_dma_addr[i],					lp->tx_skbuff[i]->len,PCI_DMA_TODEVICE);
-			dev_kfree_skb (lp->tx_skbuff[i]);
-			lp->tx_skbuff[i] = NULL;
-			lp->tx_dma_addr[i] = 0;
-		}
-	}
-	/* Freeing previously allocated receive buffers */
-	for (i = 0; i < NUM_RX_BUFFERS; i++){
-		rx_skbuff = lp->rx_skbuff[i];
-		if(rx_skbuff != NULL){
-			pci_unmap_single(lp->pci_dev,lp->rx_dma_addr[i],
-				  lp->rx_buff_len - 2,PCI_DMA_FROMDEVICE);
-			dev_kfree_skb(lp->rx_skbuff[i]);
-			lp->rx_skbuff[i] = NULL;
-			lp->rx_dma_addr[i] = 0;
-		}
-	}
-
-	return 0;
-}
-
-/*
-This will set the receive buffer length corresponding to the mtu size of networkinterface.
-*/
-static inline void amd8111e_set_rx_buff_len(struct net_device* dev)
-{
-	struct amd8111e_priv* lp = netdev_priv(dev);
-	unsigned int mtu = dev->mtu;
-
-	if (mtu > ETH_DATA_LEN){
-		/* MTU + ethernet header + FCS
-		+ optional VLAN tag + skb reserve space 2 */
-
-		lp->rx_buff_len = mtu + ETH_HLEN + 10;
-		lp->options |= OPTION_JUMBO_ENABLE;
-	} else{
-		lp->rx_buff_len = PKT_BUFF_SZ;
-		lp->options &= ~OPTION_JUMBO_ENABLE;
-	}
-}
-
-/*
-This function will free all the previously allocated buffers, determine new receive buffer length  and will allocate new receive buffers. This function also allocates and initializes both the transmitter and receive hardware descriptors.
- */
-static int amd8111e_init_ring(struct net_device *dev)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	int i;
-
-	lp->rx_idx = lp->tx_idx = 0;
-	lp->tx_complete_idx = 0;
-	lp->tx_ring_idx = 0;
-
-
-	if(lp->opened)
-		/* Free previously allocated transmit and receive skbs */
-		amd8111e_free_skbs(dev);
-
-	else{
-		 /* allocate the tx and rx descriptors */
-	     	if((lp->tx_ring = pci_alloc_consistent(lp->pci_dev,
-			sizeof(struct amd8111e_tx_dr)*NUM_TX_RING_DR,
-			&lp->tx_ring_dma_addr)) == NULL)
-
-			goto err_no_mem;
-
-	     	if((lp->rx_ring = pci_alloc_consistent(lp->pci_dev,
-			sizeof(struct amd8111e_rx_dr)*NUM_RX_RING_DR,
-			&lp->rx_ring_dma_addr)) == NULL)
-
-			goto err_free_tx_ring;
-
-	}
-	/* Set new receive buff size */
-	amd8111e_set_rx_buff_len(dev);
-
-	/* Allocating receive  skbs */
-	for (i = 0; i < NUM_RX_BUFFERS; i++) {
-
-		if (!(lp->rx_skbuff[i] = dev_alloc_skb(lp->rx_buff_len))) {
-				/* Release previos allocated skbs */
-				for(--i; i >= 0 ;i--)
-					dev_kfree_skb(lp->rx_skbuff[i]);
-				goto err_free_rx_ring;
-		}
-		skb_reserve(lp->rx_skbuff[i],2);
-	}
-        /* Initilaizing receive descriptors */
-	for (i = 0; i < NUM_RX_BUFFERS; i++) {
-		lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev,
-			lp->rx_skbuff[i]->data,lp->rx_buff_len-2, PCI_DMA_FROMDEVICE);
-
-		lp->rx_ring[i].buff_phy_addr = cpu_to_le32(lp->rx_dma_addr[i]);
-		lp->rx_ring[i].buff_count = cpu_to_le16(lp->rx_buff_len-2);
-		wmb();
-		lp->rx_ring[i].rx_flags = cpu_to_le16(OWN_BIT);
-	}
-
-	/* Initializing transmit descriptors */
-	for (i = 0; i < NUM_TX_RING_DR; i++) {
-		lp->tx_ring[i].buff_phy_addr = 0;
-		lp->tx_ring[i].tx_flags = 0;
-		lp->tx_ring[i].buff_count = 0;
-	}
-
-	return 0;
-
-err_free_rx_ring:
-
-	pci_free_consistent(lp->pci_dev,
-		sizeof(struct amd8111e_rx_dr)*NUM_RX_RING_DR,lp->rx_ring,
-		lp->rx_ring_dma_addr);
-
-err_free_tx_ring:
-
-	pci_free_consistent(lp->pci_dev,
-		 sizeof(struct amd8111e_tx_dr)*NUM_TX_RING_DR,lp->tx_ring,
-		 lp->tx_ring_dma_addr);
-
-err_no_mem:
-	return -ENOMEM;
-}
-/* This function will set the interrupt coalescing according to the input arguments */
-static int amd8111e_set_coalesce(struct net_device * dev, enum coal_mode cmod)
-{
-	unsigned int timeout;
-	unsigned int event_count;
-
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	void __iomem *mmio = lp->mmio;
-	struct amd8111e_coalesce_conf * coal_conf = &lp->coal_conf;
-
-
-	switch(cmod)
-	{
-		case RX_INTR_COAL :
-			timeout = coal_conf->rx_timeout;
-			event_count = coal_conf->rx_event_count;
-			if( timeout > MAX_TIMEOUT ||
-					event_count > MAX_EVENT_COUNT )
-				return -EINVAL;
-
-			timeout = timeout * DELAY_TIMER_CONV;
-			writel(VAL0|STINTEN, mmio+INTEN0);
-			writel((u32)DLY_INT_A_R0|( event_count<< 16 )|timeout,
-							mmio+DLY_INT_A);
-			break;
-
-		case TX_INTR_COAL :
-			timeout = coal_conf->tx_timeout;
-			event_count = coal_conf->tx_event_count;
-			if( timeout > MAX_TIMEOUT ||
-					event_count > MAX_EVENT_COUNT )
-				return -EINVAL;
-
-
-			timeout = timeout * DELAY_TIMER_CONV;
-			writel(VAL0|STINTEN,mmio+INTEN0);
-			writel((u32)DLY_INT_B_T0|( event_count<< 16 )|timeout,
-							 mmio+DLY_INT_B);
-			break;
-
-		case DISABLE_COAL:
-			writel(0,mmio+STVAL);
-			writel(STINTEN, mmio+INTEN0);
-			writel(0, mmio +DLY_INT_B);
-			writel(0, mmio+DLY_INT_A);
-			break;
-		 case ENABLE_COAL:
-		       /* Start the timer */
-			writel((u32)SOFT_TIMER_FREQ, mmio+STVAL); /*  0.5 sec */
-			writel(VAL0|STINTEN, mmio+INTEN0);
-			break;
-		default:
-			break;
-
-   }
-	return 0;
-
-}
-
-/*
-This function initializes the device registers  and starts the device.
-*/
-static int amd8111e_restart(struct net_device *dev)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	void __iomem *mmio = lp->mmio;
-	int i,reg_val;
-
-	/* stop the chip */
-	 writel(RUN, mmio + CMD0);
-
-	if(amd8111e_init_ring(dev))
-		return -ENOMEM;
-
-	/* enable the port manager and set auto negotiation always */
-	writel((u32) VAL1|EN_PMGR, mmio + CMD3 );
-	writel((u32)XPHYANE|XPHYRST , mmio + CTRL2);
-
-	amd8111e_set_ext_phy(dev);
-
-	/* set control registers */
-	reg_val = readl(mmio + CTRL1);
-	reg_val &= ~XMTSP_MASK;
-	writel( reg_val| XMTSP_128 | CACHE_ALIGN, mmio + CTRL1 );
-
-	/* enable interrupt */
-	writel( APINT5EN | APINT4EN | APINT3EN | APINT2EN | APINT1EN |
-		APINT0EN | MIIPDTINTEN | MCCIINTEN | MCCINTEN | MREINTEN |
-		SPNDINTEN | MPINTEN | SINTEN | STINTEN, mmio + INTEN0);
-
-	writel(VAL3 | LCINTEN | VAL1 | TINTEN0 | VAL0 | RINTEN0, mmio + INTEN0);
-
-	/* initialize tx and rx ring base addresses */
-	writel((u32)lp->tx_ring_dma_addr,mmio + XMT_RING_BASE_ADDR0);
-	writel((u32)lp->rx_ring_dma_addr,mmio+ RCV_RING_BASE_ADDR0);
-
-	writew((u32)NUM_TX_RING_DR, mmio + XMT_RING_LEN0);
-	writew((u16)NUM_RX_RING_DR, mmio + RCV_RING_LEN0);
-
-	/* set default IPG to 96 */
-	writew((u32)DEFAULT_IPG,mmio+IPG);
-	writew((u32)(DEFAULT_IPG-IFS1_DELTA), mmio + IFS1);
-
-	if(lp->options & OPTION_JUMBO_ENABLE){
-		writel((u32)VAL2|JUMBO, mmio + CMD3);
-		/* Reset REX_UFLO */
-		writel( REX_UFLO, mmio + CMD2);
-		/* Should not set REX_UFLO for jumbo frames */
-		writel( VAL0 | APAD_XMT|REX_RTRY , mmio + CMD2);
-	}else{
-		writel( VAL0 | APAD_XMT | REX_RTRY|REX_UFLO, mmio + CMD2);
-		writel((u32)JUMBO, mmio + CMD3);
-	}
-
-#if AMD8111E_VLAN_TAG_USED
-	writel((u32) VAL2|VSIZE|VL_TAG_DEL, mmio + CMD3);
-#endif
-	writel( VAL0 | APAD_XMT | REX_RTRY, mmio + CMD2 );
-
-	/* Setting the MAC address to the device */
-	for(i = 0; i < ETH_ADDR_LEN; i++)
-		writeb( dev->dev_addr[i], mmio + PADR + i );
-
-	/* Enable interrupt coalesce */
-	if(lp->options & OPTION_INTR_COAL_ENABLE){
-		printk(KERN_INFO "%s: Interrupt Coalescing Enabled.\n",
-								dev->name);
-		amd8111e_set_coalesce(dev,ENABLE_COAL);
-	}
-
-	/* set RUN bit to start the chip */
-	writel(VAL2 | RDMD0, mmio + CMD0);
-	writel(VAL0 | INTREN | RUN, mmio + CMD0);
-
-	/* To avoid PCI posting bug */
-	readl(mmio+CMD0);
-	return 0;
-}
-/*
-This function clears necessary the device registers.
-*/
-static void amd8111e_init_hw_default( struct amd8111e_priv* lp)
-{
-	unsigned int reg_val;
-	unsigned int logic_filter[2] ={0,};
-	void __iomem *mmio = lp->mmio;
-
-
-        /* stop the chip */
-	writel(RUN, mmio + CMD0);
-
-	/* AUTOPOLL0 Register *//*TBD default value is 8100 in FPS */
-	writew( 0x8100 | lp->ext_phy_addr, mmio + AUTOPOLL0);
-
-	/* Clear RCV_RING_BASE_ADDR */
-	writel(0, mmio + RCV_RING_BASE_ADDR0);
-
-	/* Clear XMT_RING_BASE_ADDR */
-	writel(0, mmio + XMT_RING_BASE_ADDR0);
-	writel(0, mmio + XMT_RING_BASE_ADDR1);
-	writel(0, mmio + XMT_RING_BASE_ADDR2);
-	writel(0, mmio + XMT_RING_BASE_ADDR3);
-
-	/* Clear CMD0  */
-	writel(CMD0_CLEAR,mmio + CMD0);
-
-	/* Clear CMD2 */
-	writel(CMD2_CLEAR, mmio +CMD2);
-
-	/* Clear CMD7 */
-	writel(CMD7_CLEAR , mmio + CMD7);
-
-	/* Clear DLY_INT_A and DLY_INT_B */
-	writel(0x0, mmio + DLY_INT_A);
-	writel(0x0, mmio + DLY_INT_B);
-
-	/* Clear FLOW_CONTROL */
-	writel(0x0, mmio + FLOW_CONTROL);
-
-	/* Clear INT0  write 1 to clear register */
-	reg_val = readl(mmio + INT0);
-	writel(reg_val, mmio + INT0);
-
-	/* Clear STVAL */
-	writel(0x0, mmio + STVAL);
-
-	/* Clear INTEN0 */
-	writel( INTEN0_CLEAR, mmio + INTEN0);
-
-	/* Clear LADRF */
-	writel(0x0 , mmio + LADRF);
-
-	/* Set SRAM_SIZE & SRAM_BOUNDARY registers  */
-	writel( 0x80010,mmio + SRAM_SIZE);
-
-	/* Clear RCV_RING0_LEN */
-	writel(0x0, mmio +  RCV_RING_LEN0);
-
-	/* Clear XMT_RING0/1/2/3_LEN */
-	writel(0x0, mmio +  XMT_RING_LEN0);
-	writel(0x0, mmio +  XMT_RING_LEN1);
-	writel(0x0, mmio +  XMT_RING_LEN2);
-	writel(0x0, mmio +  XMT_RING_LEN3);
-
-	/* Clear XMT_RING_LIMIT */
-	writel(0x0, mmio + XMT_RING_LIMIT);
-
-	/* Clear MIB */
-	writew(MIB_CLEAR, mmio + MIB_ADDR);
-
-	/* Clear LARF */
-	amd8111e_writeq(*(u64*)logic_filter,mmio+LADRF);
-
-	/* SRAM_SIZE register */
-	reg_val = readl(mmio + SRAM_SIZE);
-
-	if(lp->options & OPTION_JUMBO_ENABLE)
-		writel( VAL2|JUMBO, mmio + CMD3);
-#if AMD8111E_VLAN_TAG_USED
-	writel(VAL2|VSIZE|VL_TAG_DEL, mmio + CMD3 );
-#endif
-	/* Set default value to CTRL1 Register */
-	writel(CTRL1_DEFAULT, mmio + CTRL1);
-
-	/* To avoid PCI posting bug */
-	readl(mmio + CMD2);
-
-}
-
-/*
-This function disables the interrupt and clears all the pending
-interrupts in INT0
- */
-static void amd8111e_disable_interrupt(struct amd8111e_priv* lp)
-{
-	u32 intr0;
-
-	/* Disable interrupt */
-	writel(INTREN, lp->mmio + CMD0);
-
-	/* Clear INT0 */
-	intr0 = readl(lp->mmio + INT0);
-	writel(intr0, lp->mmio + INT0);
-
-	/* To avoid PCI posting bug */
-	readl(lp->mmio + INT0);
-
-}
-
-/*
-This function stops the chip.
-*/
-static void amd8111e_stop_chip(struct amd8111e_priv* lp)
-{
-	writel(RUN, lp->mmio + CMD0);
-
-	/* To avoid PCI posting bug */
-	readl(lp->mmio + CMD0);
-}
-
-/*
-This function frees the  transmiter and receiver descriptor rings.
-*/
-static void amd8111e_free_ring(struct amd8111e_priv* lp)
-{
-	/* Free transmit and receive descriptor rings */
-	if(lp->rx_ring){
-		pci_free_consistent(lp->pci_dev,
-			sizeof(struct amd8111e_rx_dr)*NUM_RX_RING_DR,
-			lp->rx_ring, lp->rx_ring_dma_addr);
-		lp->rx_ring = NULL;
-	}
-
-	if(lp->tx_ring){
-		pci_free_consistent(lp->pci_dev,
-			sizeof(struct amd8111e_tx_dr)*NUM_TX_RING_DR,
-			lp->tx_ring, lp->tx_ring_dma_addr);
-
-		lp->tx_ring = NULL;
-	}
-
-}
-
-/*
-This function will free all the transmit skbs that are actually transmitted by the device. It will check the ownership of the skb before freeing the skb.
-*/
-static int amd8111e_tx(struct net_device *dev)
-{
-	struct amd8111e_priv* lp = netdev_priv(dev);
-	int tx_index = lp->tx_complete_idx & TX_RING_DR_MOD_MASK;
-	int status;
-	/* Complete all the transmit packet */
-	while (lp->tx_complete_idx != lp->tx_idx){
-		tx_index =  lp->tx_complete_idx & TX_RING_DR_MOD_MASK;
-		status = le16_to_cpu(lp->tx_ring[tx_index].tx_flags);
-
-		if(status & OWN_BIT)
-			break;	/* It still hasn't been Txed */
-
-		lp->tx_ring[tx_index].buff_phy_addr = 0;
-
-		/* We must free the original skb */
-		if (lp->tx_skbuff[tx_index]) {
-			pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[tx_index],
-				  	lp->tx_skbuff[tx_index]->len,
-					PCI_DMA_TODEVICE);
-			dev_kfree_skb_irq (lp->tx_skbuff[tx_index]);
-			lp->tx_skbuff[tx_index] = NULL;
-			lp->tx_dma_addr[tx_index] = 0;
-		}
-		lp->tx_complete_idx++;
-		/*COAL update tx coalescing parameters */
-		lp->coal_conf.tx_packets++;
-		lp->coal_conf.tx_bytes +=
-			le16_to_cpu(lp->tx_ring[tx_index].buff_count);
-
-		if (netif_queue_stopped(dev) &&
-			lp->tx_complete_idx > lp->tx_idx - NUM_TX_BUFFERS +2){
-			/* The ring is no longer full, clear tbusy. */
-			/* lp->tx_full = 0; */
-			netif_wake_queue (dev);
-		}
-	}
-	return 0;
-}
-
-/* This function handles the driver receive operation in polling mode */
-static int amd8111e_rx_poll(struct napi_struct *napi, int budget)
-{
-	struct amd8111e_priv *lp = container_of(napi, struct amd8111e_priv, napi);
-	struct net_device *dev = lp->amd8111e_net_dev;
-	int rx_index = lp->rx_idx & RX_RING_DR_MOD_MASK;
-	void __iomem *mmio = lp->mmio;
-	struct sk_buff *skb,*new_skb;
-	int min_pkt_len, status;
-	unsigned int intr0;
-	int num_rx_pkt = 0;
-	short pkt_len;
-#if AMD8111E_VLAN_TAG_USED
-	short vtag;
-#endif
-	int rx_pkt_limit = budget;
-	unsigned long flags;
-
-	do{
-		/* process receive packets until we use the quota*/
-		/* If we own the next entry, it's a new packet. Send it up. */
-		while(1) {
-			status = le16_to_cpu(lp->rx_ring[rx_index].rx_flags);
-			if (status & OWN_BIT)
-				break;
-
-			/*
-			 * There is a tricky error noted by John Murphy,
-			 * <murf@perftech.com> to Russ Nelson: Even with
-			 * full-sized * buffers it's possible for a
-			 * jabber packet to use two buffers, with only
-			 * the last correctly noting the error.
-			 */
-
-			if(status & ERR_BIT) {
-				/* reseting flags */
-				lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
-				goto err_next_pkt;
-			}
-			/* check for STP and ENP */
-			if(!((status & STP_BIT) && (status & ENP_BIT))){
-				/* reseting flags */
-				lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
-				goto err_next_pkt;
-			}
-			pkt_len = le16_to_cpu(lp->rx_ring[rx_index].msg_count) - 4;
-
-#if AMD8111E_VLAN_TAG_USED
-			vtag = status & TT_MASK;
-			/*MAC will strip vlan tag*/
-			if (vtag != 0)
-				min_pkt_len =MIN_PKT_LEN - 4;
-			else
-#endif
-				min_pkt_len =MIN_PKT_LEN;
-
-			if (pkt_len < min_pkt_len) {
-				lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
-				lp->drv_rx_errors++;
-				goto err_next_pkt;
-			}
-			if(--rx_pkt_limit < 0)
-				goto rx_not_empty;
-			if(!(new_skb = dev_alloc_skb(lp->rx_buff_len))){
-				/* if allocation fail,
-				   ignore that pkt and go to next one */
-				lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
-				lp->drv_rx_errors++;
-				goto err_next_pkt;
-			}
-
-			skb_reserve(new_skb, 2);
-			skb = lp->rx_skbuff[rx_index];
-			pci_unmap_single(lp->pci_dev,lp->rx_dma_addr[rx_index],
-					 lp->rx_buff_len-2, PCI_DMA_FROMDEVICE);
-			skb_put(skb, pkt_len);
-			lp->rx_skbuff[rx_index] = new_skb;
-			lp->rx_dma_addr[rx_index] = pci_map_single(lp->pci_dev,
-								   new_skb->data,
-								   lp->rx_buff_len-2,
-								   PCI_DMA_FROMDEVICE);
-
-			skb->protocol = eth_type_trans(skb, dev);
-
-#if AMD8111E_VLAN_TAG_USED
-			if (vtag == TT_VLAN_TAGGED){
-				u16 vlan_tag = le16_to_cpu(lp->rx_ring[rx_index].tag_ctrl_info);
-				__vlan_hwaccel_put_tag(skb, vlan_tag);
-			}
-#endif
-			netif_receive_skb(skb);
-			/*COAL update rx coalescing parameters*/
-			lp->coal_conf.rx_packets++;
-			lp->coal_conf.rx_bytes += pkt_len;
-			num_rx_pkt++;
-
-		err_next_pkt:
-			lp->rx_ring[rx_index].buff_phy_addr
-				= cpu_to_le32(lp->rx_dma_addr[rx_index]);
-			lp->rx_ring[rx_index].buff_count =
-				cpu_to_le16(lp->rx_buff_len-2);
-			wmb();
-			lp->rx_ring[rx_index].rx_flags |= cpu_to_le16(OWN_BIT);
-			rx_index = (++lp->rx_idx) & RX_RING_DR_MOD_MASK;
-		}
-		/* Check the interrupt status register for more packets in the
-		   mean time. Process them since we have not used up our quota.*/
-
-		intr0 = readl(mmio + INT0);
-		/*Ack receive packets */
-		writel(intr0 & RINT0,mmio + INT0);
-
-	} while(intr0 & RINT0);
-
-	if (rx_pkt_limit > 0) {
-		/* Receive descriptor is empty now */
-		spin_lock_irqsave(&lp->lock, flags);
-		__napi_complete(napi);
-		writel(VAL0|RINTEN0, mmio + INTEN0);
-		writel(VAL2 | RDMD0, mmio + CMD0);
-		spin_unlock_irqrestore(&lp->lock, flags);
-	}
-
-rx_not_empty:
-	return num_rx_pkt;
-}
-
-/*
-This function will indicate the link status to the kernel.
-*/
-static int amd8111e_link_change(struct net_device* dev)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	int status0,speed;
-
-	/* read the link change */
-     	status0 = readl(lp->mmio + STAT0);
-
-	if(status0 & LINK_STATS){
-		if(status0 & AUTONEG_COMPLETE)
-			lp->link_config.autoneg = AUTONEG_ENABLE;
-		else
-			lp->link_config.autoneg = AUTONEG_DISABLE;
-
-		if(status0 & FULL_DPLX)
-			lp->link_config.duplex = DUPLEX_FULL;
-		else
-			lp->link_config.duplex = DUPLEX_HALF;
-		speed = (status0 & SPEED_MASK) >> 7;
-		if(speed == PHY_SPEED_10)
-			lp->link_config.speed = SPEED_10;
-		else if(speed == PHY_SPEED_100)
-			lp->link_config.speed = SPEED_100;
-
-		printk(KERN_INFO "%s: Link is Up. Speed is %s Mbps %s Duplex\n",			dev->name,
-		       (lp->link_config.speed == SPEED_100) ? "100": "10",
-		       (lp->link_config.duplex == DUPLEX_FULL)? "Full": "Half");
-		netif_carrier_on(dev);
-	}
-	else{
-		lp->link_config.speed = SPEED_INVALID;
-		lp->link_config.duplex = DUPLEX_INVALID;
-		lp->link_config.autoneg = AUTONEG_INVALID;
-		printk(KERN_INFO "%s: Link is Down.\n",dev->name);
-		netif_carrier_off(dev);
-	}
-
-	return 0;
-}
-/*
-This function reads the mib counters.
-*/
-static int amd8111e_read_mib(void __iomem *mmio, u8 MIB_COUNTER)
-{
-	unsigned int  status;
-	unsigned  int data;
-	unsigned int repeat = REPEAT_CNT;
-
-	writew( MIB_RD_CMD | MIB_COUNTER, mmio + MIB_ADDR);
-	do {
-		status = readw(mmio + MIB_ADDR);
-		udelay(2);	/* controller takes MAX 2 us to get mib data */
-	}
-	while (--repeat && (status & MIB_CMD_ACTIVE));
-
-	data = readl(mmio + MIB_DATA);
-	return data;
-}
-
-/*
- * This function reads the mib registers and returns the hardware statistics.
- * It updates previous internal driver statistics with new values.
- */
-static struct net_device_stats *amd8111e_get_stats(struct net_device *dev)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	void __iomem *mmio = lp->mmio;
-	unsigned long flags;
-	struct net_device_stats *new_stats = &dev->stats;
-
-	if (!lp->opened)
-		return new_stats;
-	spin_lock_irqsave (&lp->lock, flags);
-
-	/* stats.rx_packets */
-	new_stats->rx_packets = amd8111e_read_mib(mmio, rcv_broadcast_pkts)+
-				amd8111e_read_mib(mmio, rcv_multicast_pkts)+
-				amd8111e_read_mib(mmio, rcv_unicast_pkts);
-
-	/* stats.tx_packets */
-	new_stats->tx_packets = amd8111e_read_mib(mmio, xmt_packets);
-
-	/*stats.rx_bytes */
-	new_stats->rx_bytes = amd8111e_read_mib(mmio, rcv_octets);
-
-	/* stats.tx_bytes */
-	new_stats->tx_bytes = amd8111e_read_mib(mmio, xmt_octets);
-
-	/* stats.rx_errors */
-	/* hw errors + errors driver reported */
-	new_stats->rx_errors = amd8111e_read_mib(mmio, rcv_undersize_pkts)+
-				amd8111e_read_mib(mmio, rcv_fragments)+
-				amd8111e_read_mib(mmio, rcv_jabbers)+
-				amd8111e_read_mib(mmio, rcv_alignment_errors)+
-				amd8111e_read_mib(mmio, rcv_fcs_errors)+
-				amd8111e_read_mib(mmio, rcv_miss_pkts)+
-				lp->drv_rx_errors;
-
-	/* stats.tx_errors */
-	new_stats->tx_errors = amd8111e_read_mib(mmio, xmt_underrun_pkts);
-
-	/* stats.rx_dropped*/
-	new_stats->rx_dropped = amd8111e_read_mib(mmio, rcv_miss_pkts);
-
-	/* stats.tx_dropped*/
-	new_stats->tx_dropped = amd8111e_read_mib(mmio,  xmt_underrun_pkts);
-
-	/* stats.multicast*/
-	new_stats->multicast = amd8111e_read_mib(mmio, rcv_multicast_pkts);
-
-	/* stats.collisions*/
-	new_stats->collisions = amd8111e_read_mib(mmio, xmt_collisions);
-
-	/* stats.rx_length_errors*/
-	new_stats->rx_length_errors =
-		amd8111e_read_mib(mmio, rcv_undersize_pkts)+
-		amd8111e_read_mib(mmio, rcv_oversize_pkts);
-
-	/* stats.rx_over_errors*/
-	new_stats->rx_over_errors = amd8111e_read_mib(mmio, rcv_miss_pkts);
-
-	/* stats.rx_crc_errors*/
-	new_stats->rx_crc_errors = amd8111e_read_mib(mmio, rcv_fcs_errors);
-
-	/* stats.rx_frame_errors*/
-	new_stats->rx_frame_errors =
-		amd8111e_read_mib(mmio, rcv_alignment_errors);
-
-	/* stats.rx_fifo_errors */
-	new_stats->rx_fifo_errors = amd8111e_read_mib(mmio, rcv_miss_pkts);
-
-	/* stats.rx_missed_errors */
-	new_stats->rx_missed_errors = amd8111e_read_mib(mmio, rcv_miss_pkts);
-
-	/* stats.tx_aborted_errors*/
-	new_stats->tx_aborted_errors =
-		amd8111e_read_mib(mmio, xmt_excessive_collision);
-
-	/* stats.tx_carrier_errors*/
-	new_stats->tx_carrier_errors =
-		amd8111e_read_mib(mmio, xmt_loss_carrier);
-
-	/* stats.tx_fifo_errors*/
-	new_stats->tx_fifo_errors = amd8111e_read_mib(mmio, xmt_underrun_pkts);
-
-	/* stats.tx_window_errors*/
-	new_stats->tx_window_errors =
-		amd8111e_read_mib(mmio, xmt_late_collision);
-
-	/* Reset the mibs for collecting new statistics */
-	/* writew(MIB_CLEAR, mmio + MIB_ADDR);*/
-
-	spin_unlock_irqrestore (&lp->lock, flags);
-
-	return new_stats;
-}
-/* This function recalculate the interrupt coalescing  mode on every interrupt
-according to the datarate and the packet rate.
-*/
-static int amd8111e_calc_coalesce(struct net_device *dev)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	struct amd8111e_coalesce_conf * coal_conf = &lp->coal_conf;
-	int tx_pkt_rate;
-	int rx_pkt_rate;
-	int tx_data_rate;
-	int rx_data_rate;
-	int rx_pkt_size;
-	int tx_pkt_size;
-
-	tx_pkt_rate = coal_conf->tx_packets - coal_conf->tx_prev_packets;
-	coal_conf->tx_prev_packets =  coal_conf->tx_packets;
-
-	tx_data_rate = coal_conf->tx_bytes - coal_conf->tx_prev_bytes;
-	coal_conf->tx_prev_bytes =  coal_conf->tx_bytes;
-
-	rx_pkt_rate = coal_conf->rx_packets - coal_conf->rx_prev_packets;
-	coal_conf->rx_prev_packets =  coal_conf->rx_packets;
-
-	rx_data_rate = coal_conf->rx_bytes - coal_conf->rx_prev_bytes;
-	coal_conf->rx_prev_bytes =  coal_conf->rx_bytes;
-
-	if(rx_pkt_rate < 800){
-		if(coal_conf->rx_coal_type != NO_COALESCE){
-
-			coal_conf->rx_timeout = 0x0;
-			coal_conf->rx_event_count = 0;
-			amd8111e_set_coalesce(dev,RX_INTR_COAL);
-			coal_conf->rx_coal_type = NO_COALESCE;
-		}
-	}
-	else{
-
-		rx_pkt_size = rx_data_rate/rx_pkt_rate;
-		if (rx_pkt_size < 128){
-			if(coal_conf->rx_coal_type != NO_COALESCE){
-
-				coal_conf->rx_timeout = 0;
-				coal_conf->rx_event_count = 0;
-				amd8111e_set_coalesce(dev,RX_INTR_COAL);
-				coal_conf->rx_coal_type = NO_COALESCE;
-			}
-
-		}
-		else if ( (rx_pkt_size >= 128) && (rx_pkt_size < 512) ){
-
-			if(coal_conf->rx_coal_type !=  LOW_COALESCE){
-				coal_conf->rx_timeout = 1;
-				coal_conf->rx_event_count = 4;
-				amd8111e_set_coalesce(dev,RX_INTR_COAL);
-				coal_conf->rx_coal_type = LOW_COALESCE;
-			}
-		}
-		else if ((rx_pkt_size >= 512) && (rx_pkt_size < 1024)){
-
-			if(coal_conf->rx_coal_type !=  MEDIUM_COALESCE){
-				coal_conf->rx_timeout = 1;
-				coal_conf->rx_event_count = 4;
-				amd8111e_set_coalesce(dev,RX_INTR_COAL);
-				coal_conf->rx_coal_type = MEDIUM_COALESCE;
-			}
-
-		}
-		else if(rx_pkt_size >= 1024){
-			if(coal_conf->rx_coal_type !=  HIGH_COALESCE){
-				coal_conf->rx_timeout = 2;
-				coal_conf->rx_event_count = 3;
-				amd8111e_set_coalesce(dev,RX_INTR_COAL);
-				coal_conf->rx_coal_type = HIGH_COALESCE;
-			}
-		}
-	}
-    	/* NOW FOR TX INTR COALESC */
-	if(tx_pkt_rate < 800){
-		if(coal_conf->tx_coal_type != NO_COALESCE){
-
-			coal_conf->tx_timeout = 0x0;
-			coal_conf->tx_event_count = 0;
-			amd8111e_set_coalesce(dev,TX_INTR_COAL);
-			coal_conf->tx_coal_type = NO_COALESCE;
-		}
-	}
-	else{
-
-		tx_pkt_size = tx_data_rate/tx_pkt_rate;
-		if (tx_pkt_size < 128){
-
-			if(coal_conf->tx_coal_type != NO_COALESCE){
-
-				coal_conf->tx_timeout = 0;
-				coal_conf->tx_event_count = 0;
-				amd8111e_set_coalesce(dev,TX_INTR_COAL);
-				coal_conf->tx_coal_type = NO_COALESCE;
-			}
-
-		}
-		else if ( (tx_pkt_size >= 128) && (tx_pkt_size < 512) ){
-
-			if(coal_conf->tx_coal_type !=  LOW_COALESCE){
-				coal_conf->tx_timeout = 1;
-				coal_conf->tx_event_count = 2;
-				amd8111e_set_coalesce(dev,TX_INTR_COAL);
-				coal_conf->tx_coal_type = LOW_COALESCE;
-
-			}
-		}
-		else if ((tx_pkt_size >= 512) && (tx_pkt_size < 1024)){
-
-			if(coal_conf->tx_coal_type !=  MEDIUM_COALESCE){
-				coal_conf->tx_timeout = 2;
-				coal_conf->tx_event_count = 5;
-				amd8111e_set_coalesce(dev,TX_INTR_COAL);
-				coal_conf->tx_coal_type = MEDIUM_COALESCE;
-			}
-
-		}
-		else if(tx_pkt_size >= 1024){
-			if (tx_pkt_size >= 1024){
-				if(coal_conf->tx_coal_type !=  HIGH_COALESCE){
-					coal_conf->tx_timeout = 4;
-					coal_conf->tx_event_count = 8;
-					amd8111e_set_coalesce(dev,TX_INTR_COAL);
-					coal_conf->tx_coal_type = HIGH_COALESCE;
-				}
-			}
-		}
-	}
-	return 0;
-
-}
-/*
-This is device interrupt function. It handles transmit, receive,link change and hardware timer interrupts.
-*/
-static irqreturn_t amd8111e_interrupt(int irq, void *dev_id)
-{
-
-	struct net_device * dev = (struct net_device *) dev_id;
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	void __iomem *mmio = lp->mmio;
-	unsigned int intr0, intren0;
-	unsigned int handled = 1;
-
-	if(unlikely(dev == NULL))
-		return IRQ_NONE;
-
-	spin_lock(&lp->lock);
-
-	/* disabling interrupt */
-	writel(INTREN, mmio + CMD0);
-
-	/* Read interrupt status */
-	intr0 = readl(mmio + INT0);
-	intren0 = readl(mmio + INTEN0);
-
-	/* Process all the INT event until INTR bit is clear. */
-
-	if (!(intr0 & INTR)){
-		handled = 0;
-		goto err_no_interrupt;
-	}
-
-	/* Current driver processes 4 interrupts : RINT,TINT,LCINT,STINT */
-	writel(intr0, mmio + INT0);
-
-	/* Check if Receive Interrupt has occurred. */
-	if (intr0 & RINT0) {
-		if (napi_schedule_prep(&lp->napi)) {
-			/* Disable receive interupts */
-			writel(RINTEN0, mmio + INTEN0);
-			/* Schedule a polling routine */
-			__napi_schedule(&lp->napi);
-		} else if (intren0 & RINTEN0) {
-			printk("************Driver bug! interrupt while in poll\n");
-			/* Fix by disable receive interrupts */
-			writel(RINTEN0, mmio + INTEN0);
-		}
-	}
-
-	/* Check if  Transmit Interrupt has occurred. */
-	if (intr0 & TINT0)
-		amd8111e_tx(dev);
-
-	/* Check if  Link Change Interrupt has occurred. */
-	if (intr0 & LCINT)
-		amd8111e_link_change(dev);
-
-	/* Check if Hardware Timer Interrupt has occurred. */
-	if (intr0 & STINT)
-		amd8111e_calc_coalesce(dev);
-
-err_no_interrupt:
-	writel( VAL0 | INTREN,mmio + CMD0);
-
-	spin_unlock(&lp->lock);
-
-	return IRQ_RETVAL(handled);
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void amd8111e_poll(struct net_device *dev)
-{
-	unsigned long flags;
-	local_irq_save(flags);
-	amd8111e_interrupt(0, dev);
-	local_irq_restore(flags);
-}
-#endif
-
-
-/*
-This function closes the network interface and updates the statistics so that most recent statistics will be available after the interface is down.
-*/
-static int amd8111e_close(struct net_device * dev)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	netif_stop_queue(dev);
-
-	napi_disable(&lp->napi);
-
-	spin_lock_irq(&lp->lock);
-
-	amd8111e_disable_interrupt(lp);
-	amd8111e_stop_chip(lp);
-
-	/* Free transmit and receive skbs */
-	amd8111e_free_skbs(lp->amd8111e_net_dev);
-
-	netif_carrier_off(lp->amd8111e_net_dev);
-
-	/* Delete ipg timer */
-	if(lp->options & OPTION_DYN_IPG_ENABLE)
-		del_timer_sync(&lp->ipg_data.ipg_timer);
-
-	spin_unlock_irq(&lp->lock);
-	free_irq(dev->irq, dev);
-	amd8111e_free_ring(lp);
-
-	/* Update the statistics before closing */
-	amd8111e_get_stats(dev);
-	lp->opened = 0;
-	return 0;
-}
-/* This function opens new interface.It requests irq for the device, initializes the device,buffers and descriptors, and starts the device.
-*/
-static int amd8111e_open(struct net_device * dev )
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-
-	if(dev->irq ==0 || request_irq(dev->irq, amd8111e_interrupt, IRQF_SHARED,
-					 dev->name, dev))
-		return -EAGAIN;
-
-	napi_enable(&lp->napi);
-
-	spin_lock_irq(&lp->lock);
-
-	amd8111e_init_hw_default(lp);
-
-	if(amd8111e_restart(dev)){
-		spin_unlock_irq(&lp->lock);
-		napi_disable(&lp->napi);
-		if (dev->irq)
-			free_irq(dev->irq, dev);
-		return -ENOMEM;
-	}
-	/* Start ipg timer */
-	if(lp->options & OPTION_DYN_IPG_ENABLE){
-		add_timer(&lp->ipg_data.ipg_timer);
-		printk(KERN_INFO "%s: Dynamic IPG Enabled.\n",dev->name);
-	}
-
-	lp->opened = 1;
-
-	spin_unlock_irq(&lp->lock);
-
-	netif_start_queue(dev);
-
-	return 0;
-}
-/*
-This function checks if there is any transmit  descriptors available to queue more packet.
-*/
-static int amd8111e_tx_queue_avail(struct amd8111e_priv* lp )
-{
-	int tx_index = lp->tx_idx & TX_BUFF_MOD_MASK;
-	if (lp->tx_skbuff[tx_index])
-		return -1;
-	else
-		return 0;
-
-}
-/*
-This function will queue the transmit packets to the descriptors and will trigger the send operation. It also initializes the transmit descriptors with buffer physical address, byte count, ownership to hardware etc.
-*/
-
-static netdev_tx_t amd8111e_start_xmit(struct sk_buff *skb,
-				       struct net_device * dev)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	int tx_index;
-	unsigned long flags;
-
-	spin_lock_irqsave(&lp->lock, flags);
-
-	tx_index = lp->tx_idx & TX_RING_DR_MOD_MASK;
-
-	lp->tx_ring[tx_index].buff_count = cpu_to_le16(skb->len);
-
-	lp->tx_skbuff[tx_index] = skb;
-	lp->tx_ring[tx_index].tx_flags = 0;
-
-#if AMD8111E_VLAN_TAG_USED
-	if (vlan_tx_tag_present(skb)) {
-		lp->tx_ring[tx_index].tag_ctrl_cmd |=
-				cpu_to_le16(TCC_VLAN_INSERT);
-		lp->tx_ring[tx_index].tag_ctrl_info =
-				cpu_to_le16(vlan_tx_tag_get(skb));
-
-	}
-#endif
-	lp->tx_dma_addr[tx_index] =
-	    pci_map_single(lp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
-	lp->tx_ring[tx_index].buff_phy_addr =
-	    cpu_to_le32(lp->tx_dma_addr[tx_index]);
-
-	/*  Set FCS and LTINT bits */
-	wmb();
-	lp->tx_ring[tx_index].tx_flags |=
-	    cpu_to_le16(OWN_BIT | STP_BIT | ENP_BIT|ADD_FCS_BIT|LTINT_BIT);
-
-	lp->tx_idx++;
-
-	/* Trigger an immediate send poll. */
-	writel( VAL1 | TDMD0, lp->mmio + CMD0);
-	writel( VAL2 | RDMD0,lp->mmio + CMD0);
-
-	if(amd8111e_tx_queue_avail(lp) < 0){
-		netif_stop_queue(dev);
-	}
-	spin_unlock_irqrestore(&lp->lock, flags);
-	return NETDEV_TX_OK;
-}
-/*
-This function returns all the memory mapped registers of the device.
-*/
-static void amd8111e_read_regs(struct amd8111e_priv *lp, u32 *buf)
-{
-	void __iomem *mmio = lp->mmio;
-	/* Read only necessary registers */
-	buf[0] = readl(mmio + XMT_RING_BASE_ADDR0);
-	buf[1] = readl(mmio + XMT_RING_LEN0);
-	buf[2] = readl(mmio + RCV_RING_BASE_ADDR0);
-	buf[3] = readl(mmio + RCV_RING_LEN0);
-	buf[4] = readl(mmio + CMD0);
-	buf[5] = readl(mmio + CMD2);
-	buf[6] = readl(mmio + CMD3);
-	buf[7] = readl(mmio + CMD7);
-	buf[8] = readl(mmio + INT0);
-	buf[9] = readl(mmio + INTEN0);
-	buf[10] = readl(mmio + LADRF);
-	buf[11] = readl(mmio + LADRF+4);
-	buf[12] = readl(mmio + STAT0);
-}
-
-
-/*
-This function sets promiscuos mode, all-multi mode or the multicast address
-list to the device.
-*/
-static void amd8111e_set_multicast_list(struct net_device *dev)
-{
-	struct netdev_hw_addr *ha;
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	u32 mc_filter[2] ;
-	int bit_num;
-
-	if(dev->flags & IFF_PROMISC){
-		writel( VAL2 | PROM, lp->mmio + CMD2);
-		return;
-	}
-	else
-		writel( PROM, lp->mmio + CMD2);
-	if (dev->flags & IFF_ALLMULTI ||
-	    netdev_mc_count(dev) > MAX_FILTER_SIZE) {
-		/* get all multicast packet */
-		mc_filter[1] = mc_filter[0] = 0xffffffff;
-		lp->options |= OPTION_MULTICAST_ENABLE;
-		amd8111e_writeq(*(u64*)mc_filter,lp->mmio + LADRF);
-		return;
-	}
-	if (netdev_mc_empty(dev)) {
-		/* get only own packets */
-		mc_filter[1] = mc_filter[0] = 0;
-		lp->options &= ~OPTION_MULTICAST_ENABLE;
-		amd8111e_writeq(*(u64*)mc_filter,lp->mmio + LADRF);
-		/* disable promiscuous mode */
-		writel(PROM, lp->mmio + CMD2);
-		return;
-	}
-	/* load all the multicast addresses in the logic filter */
-	lp->options |= OPTION_MULTICAST_ENABLE;
-	mc_filter[1] = mc_filter[0] = 0;
-	netdev_for_each_mc_addr(ha, dev) {
-		bit_num = (ether_crc_le(ETH_ALEN, ha->addr) >> 26) & 0x3f;
-		mc_filter[bit_num >> 5] |= 1 << (bit_num & 31);
-	}
-	amd8111e_writeq(*(u64*)mc_filter,lp->mmio+ LADRF);
-
-	/* To eliminate PCI posting bug */
-	readl(lp->mmio + CMD2);
-
-}
-
-static void amd8111e_get_drvinfo(struct net_device* dev, struct ethtool_drvinfo *info)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	struct pci_dev *pci_dev = lp->pci_dev;
-	strcpy (info->driver, MODULE_NAME);
-	strcpy (info->version, MODULE_VERS);
-	sprintf(info->fw_version,"%u",chip_version);
-	strcpy (info->bus_info, pci_name(pci_dev));
-}
-
-static int amd8111e_get_regs_len(struct net_device *dev)
-{
-	return AMD8111E_REG_DUMP_LEN;
-}
-
-static void amd8111e_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	regs->version = 0;
-	amd8111e_read_regs(lp, buf);
-}
-
-static int amd8111e_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	spin_lock_irq(&lp->lock);
-	mii_ethtool_gset(&lp->mii_if, ecmd);
-	spin_unlock_irq(&lp->lock);
-	return 0;
-}
-
-static int amd8111e_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	int res;
-	spin_lock_irq(&lp->lock);
-	res = mii_ethtool_sset(&lp->mii_if, ecmd);
-	spin_unlock_irq(&lp->lock);
-	return res;
-}
-
-static int amd8111e_nway_reset(struct net_device *dev)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	return mii_nway_restart(&lp->mii_if);
-}
-
-static u32 amd8111e_get_link(struct net_device *dev)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	return mii_link_ok(&lp->mii_if);
-}
-
-static void amd8111e_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol_info)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	wol_info->supported = WAKE_MAGIC|WAKE_PHY;
-	if (lp->options & OPTION_WOL_ENABLE)
-		wol_info->wolopts = WAKE_MAGIC;
-}
-
-static int amd8111e_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol_info)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	if (wol_info->wolopts & ~(WAKE_MAGIC|WAKE_PHY))
-		return -EINVAL;
-	spin_lock_irq(&lp->lock);
-	if (wol_info->wolopts & WAKE_MAGIC)
-		lp->options |=
-			(OPTION_WOL_ENABLE | OPTION_WAKE_MAGIC_ENABLE);
-	else if(wol_info->wolopts & WAKE_PHY)
-		lp->options |=
-			(OPTION_WOL_ENABLE | OPTION_WAKE_PHY_ENABLE);
-	else
-		lp->options &= ~OPTION_WOL_ENABLE;
-	spin_unlock_irq(&lp->lock);
-	return 0;
-}
-
-static const struct ethtool_ops ops = {
-	.get_drvinfo = amd8111e_get_drvinfo,
-	.get_regs_len = amd8111e_get_regs_len,
-	.get_regs = amd8111e_get_regs,
-	.get_settings = amd8111e_get_settings,
-	.set_settings = amd8111e_set_settings,
-	.nway_reset = amd8111e_nway_reset,
-	.get_link = amd8111e_get_link,
-	.get_wol = amd8111e_get_wol,
-	.set_wol = amd8111e_set_wol,
-};
-
-/*
-This function handles all the  ethtool ioctls. It gives driver info, gets/sets driver speed, gets memory mapped register values, forces auto negotiation, sets/gets WOL options for ethtool application.
-*/
-
-static int amd8111e_ioctl(struct net_device * dev , struct ifreq *ifr, int cmd)
-{
-	struct mii_ioctl_data *data = if_mii(ifr);
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	int err;
-	u32 mii_regval;
-
-	switch(cmd) {
-	case SIOCGMIIPHY:
-		data->phy_id = lp->ext_phy_addr;
-
-	/* fallthru */
-	case SIOCGMIIREG:
-
-		spin_lock_irq(&lp->lock);
-		err = amd8111e_read_phy(lp, data->phy_id,
-			data->reg_num & PHY_REG_ADDR_MASK, &mii_regval);
-		spin_unlock_irq(&lp->lock);
-
-		data->val_out = mii_regval;
-		return err;
-
-	case SIOCSMIIREG:
-
-		spin_lock_irq(&lp->lock);
-		err = amd8111e_write_phy(lp, data->phy_id,
-			data->reg_num & PHY_REG_ADDR_MASK, data->val_in);
-		spin_unlock_irq(&lp->lock);
-
-		return err;
-
-	default:
-		/* do nothing */
-		break;
-	}
-	return -EOPNOTSUPP;
-}
-static int amd8111e_set_mac_address(struct net_device *dev, void *p)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	int i;
-	struct sockaddr *addr = p;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-	spin_lock_irq(&lp->lock);
-	/* Setting the MAC address to the device */
-	for(i = 0; i < ETH_ADDR_LEN; i++)
-		writeb( dev->dev_addr[i], lp->mmio + PADR + i );
-
-	spin_unlock_irq(&lp->lock);
-
-	return 0;
-}
-
-/*
-This function changes the mtu of the device. It restarts the device  to initialize the descriptor with new receive buffers.
-*/
-static int amd8111e_change_mtu(struct net_device *dev, int new_mtu)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	int err;
-
-	if ((new_mtu < AMD8111E_MIN_MTU) || (new_mtu > AMD8111E_MAX_MTU))
-		return -EINVAL;
-
-	if (!netif_running(dev)) {
-		/* new_mtu will be used
-		   when device starts netxt time */
-		dev->mtu = new_mtu;
-		return 0;
-	}
-
-	spin_lock_irq(&lp->lock);
-
-        /* stop the chip */
-	writel(RUN, lp->mmio + CMD0);
-
-	dev->mtu = new_mtu;
-
-	err = amd8111e_restart(dev);
-	spin_unlock_irq(&lp->lock);
-	if(!err)
-		netif_start_queue(dev);
-	return err;
-}
-
-static int amd8111e_enable_magicpkt(struct amd8111e_priv* lp)
-{
-	writel( VAL1|MPPLBA, lp->mmio + CMD3);
-	writel( VAL0|MPEN_SW, lp->mmio + CMD7);
-
-	/* To eliminate PCI posting bug */
-	readl(lp->mmio + CMD7);
-	return 0;
-}
-
-static int amd8111e_enable_link_change(struct amd8111e_priv* lp)
-{
-
-	/* Adapter is already stoped/suspended/interrupt-disabled */
-	writel(VAL0|LCMODE_SW,lp->mmio + CMD7);
-
-	/* To eliminate PCI posting bug */
-	readl(lp->mmio + CMD7);
-	return 0;
-}
-
-/*
- * This function is called when a packet transmission fails to complete
- * within a reasonable period, on the assumption that an interrupt have
- * failed or the interface is locked up. This function will reinitialize
- * the hardware.
- */
-static void amd8111e_tx_timeout(struct net_device *dev)
-{
-	struct amd8111e_priv* lp = netdev_priv(dev);
-	int err;
-
-	printk(KERN_ERR "%s: transmit timed out, resetting\n",
-	 					      dev->name);
-	spin_lock_irq(&lp->lock);
-	err = amd8111e_restart(dev);
-	spin_unlock_irq(&lp->lock);
-	if(!err)
-		netif_wake_queue(dev);
-}
-static int amd8111e_suspend(struct pci_dev *pci_dev, pm_message_t state)
-{
-	struct net_device *dev = pci_get_drvdata(pci_dev);
-	struct amd8111e_priv *lp = netdev_priv(dev);
-
-	if (!netif_running(dev))
-		return 0;
-
-	/* disable the interrupt */
-	spin_lock_irq(&lp->lock);
-	amd8111e_disable_interrupt(lp);
-	spin_unlock_irq(&lp->lock);
-
-	netif_device_detach(dev);
-
-	/* stop chip */
-	spin_lock_irq(&lp->lock);
-	if(lp->options & OPTION_DYN_IPG_ENABLE)
-		del_timer_sync(&lp->ipg_data.ipg_timer);
-	amd8111e_stop_chip(lp);
-	spin_unlock_irq(&lp->lock);
-
-	if(lp->options & OPTION_WOL_ENABLE){
-		 /* enable wol */
-		if(lp->options & OPTION_WAKE_MAGIC_ENABLE)
-			amd8111e_enable_magicpkt(lp);
-		if(lp->options & OPTION_WAKE_PHY_ENABLE)
-			amd8111e_enable_link_change(lp);
-
-		pci_enable_wake(pci_dev, PCI_D3hot, 1);
-		pci_enable_wake(pci_dev, PCI_D3cold, 1);
-
-	}
-	else{
-		pci_enable_wake(pci_dev, PCI_D3hot, 0);
-		pci_enable_wake(pci_dev, PCI_D3cold, 0);
-	}
-
-	pci_save_state(pci_dev);
-	pci_set_power_state(pci_dev, PCI_D3hot);
-
-	return 0;
-}
-static int amd8111e_resume(struct pci_dev *pci_dev)
-{
-	struct net_device *dev = pci_get_drvdata(pci_dev);
-	struct amd8111e_priv *lp = netdev_priv(dev);
-
-	if (!netif_running(dev))
-		return 0;
-
-	pci_set_power_state(pci_dev, PCI_D0);
-	pci_restore_state(pci_dev);
-
-	pci_enable_wake(pci_dev, PCI_D3hot, 0);
-	pci_enable_wake(pci_dev, PCI_D3cold, 0); /* D3 cold */
-
-	netif_device_attach(dev);
-
-	spin_lock_irq(&lp->lock);
-	amd8111e_restart(dev);
-	/* Restart ipg timer */
-	if(lp->options & OPTION_DYN_IPG_ENABLE)
-		mod_timer(&lp->ipg_data.ipg_timer,
-				jiffies + IPG_CONVERGE_JIFFIES);
-	spin_unlock_irq(&lp->lock);
-
-	return 0;
-}
-
-
-static void __devexit amd8111e_remove_one(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	if (dev) {
-		unregister_netdev(dev);
-		iounmap(((struct amd8111e_priv *)netdev_priv(dev))->mmio);
-		free_netdev(dev);
-		pci_release_regions(pdev);
-		pci_disable_device(pdev);
-		pci_set_drvdata(pdev, NULL);
-	}
-}
-static void amd8111e_config_ipg(struct net_device* dev)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	struct ipg_info* ipg_data = &lp->ipg_data;
-	void __iomem *mmio = lp->mmio;
-	unsigned int prev_col_cnt = ipg_data->col_cnt;
-	unsigned int total_col_cnt;
-	unsigned int tmp_ipg;
-
-	if(lp->link_config.duplex == DUPLEX_FULL){
-		ipg_data->ipg = DEFAULT_IPG;
-		return;
-	}
-
-	if(ipg_data->ipg_state == SSTATE){
-
-		if(ipg_data->timer_tick == IPG_STABLE_TIME){
-
-			ipg_data->timer_tick = 0;
-			ipg_data->ipg = MIN_IPG - IPG_STEP;
-			ipg_data->current_ipg = MIN_IPG;
-			ipg_data->diff_col_cnt = 0xFFFFFFFF;
-			ipg_data->ipg_state = CSTATE;
-		}
-		else
-			ipg_data->timer_tick++;
-	}
-
-	if(ipg_data->ipg_state == CSTATE){
-
-		/* Get the current collision count */
-
-		total_col_cnt = ipg_data->col_cnt =
-				amd8111e_read_mib(mmio, xmt_collisions);
-
-		if ((total_col_cnt - prev_col_cnt) <
-				(ipg_data->diff_col_cnt)){
-
-			ipg_data->diff_col_cnt =
-				total_col_cnt - prev_col_cnt ;
-
-			ipg_data->ipg = ipg_data->current_ipg;
-		}
-
-		ipg_data->current_ipg += IPG_STEP;
-
-		if (ipg_data->current_ipg <= MAX_IPG)
-			tmp_ipg = ipg_data->current_ipg;
-		else{
-			tmp_ipg = ipg_data->ipg;
-			ipg_data->ipg_state = SSTATE;
-		}
-		writew((u32)tmp_ipg, mmio + IPG);
-		writew((u32)(tmp_ipg - IFS1_DELTA), mmio + IFS1);
-	}
-	 mod_timer(&lp->ipg_data.ipg_timer, jiffies + IPG_CONVERGE_JIFFIES);
-	return;
-
-}
-
-static void __devinit amd8111e_probe_ext_phy(struct net_device* dev)
-{
-	struct amd8111e_priv *lp = netdev_priv(dev);
-	int i;
-
-	for (i = 0x1e; i >= 0; i--) {
-		u32 id1, id2;
-
-		if (amd8111e_read_phy(lp, i, MII_PHYSID1, &id1))
-			continue;
-		if (amd8111e_read_phy(lp, i, MII_PHYSID2, &id2))
-			continue;
-		lp->ext_phy_id = (id1 << 16) | id2;
-		lp->ext_phy_addr = i;
-		return;
-	}
-	lp->ext_phy_id = 0;
-	lp->ext_phy_addr = 1;
-}
-
-static const struct net_device_ops amd8111e_netdev_ops = {
-	.ndo_open		= amd8111e_open,
-	.ndo_stop		= amd8111e_close,
-	.ndo_start_xmit		= amd8111e_start_xmit,
-	.ndo_tx_timeout		= amd8111e_tx_timeout,
-	.ndo_get_stats		= amd8111e_get_stats,
-	.ndo_set_multicast_list = amd8111e_set_multicast_list,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address	= amd8111e_set_mac_address,
-	.ndo_do_ioctl		= amd8111e_ioctl,
-	.ndo_change_mtu		= amd8111e_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	 = amd8111e_poll,
-#endif
-};
-
-static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
-				  const struct pci_device_id *ent)
-{
-	int err,i,pm_cap;
-	unsigned long reg_addr,reg_len;
-	struct amd8111e_priv* lp;
-	struct net_device* dev;
-
-	err = pci_enable_device(pdev);
-	if(err){
-		printk(KERN_ERR "amd8111e: Cannot enable new PCI device, "
-			"exiting.\n");
-		return err;
-	}
-
-	if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)){
-		printk(KERN_ERR "amd8111e: Cannot find PCI base address, "
-		       "exiting.\n");
-		err = -ENODEV;
-		goto err_disable_pdev;
-	}
-
-	err = pci_request_regions(pdev, MODULE_NAME);
-	if(err){
-		printk(KERN_ERR "amd8111e: Cannot obtain PCI resources, "
-		       "exiting.\n");
-		goto err_disable_pdev;
-	}
-
-	pci_set_master(pdev);
-
-	/* Find power-management capability. */
-	if((pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM))==0){
-		printk(KERN_ERR "amd8111e: No Power Management capability, "
-		       "exiting.\n");
-		goto err_free_reg;
-	}
-
-	/* Initialize DMA */
-	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) < 0) {
-		printk(KERN_ERR "amd8111e: DMA not supported,"
-			"exiting.\n");
-		goto err_free_reg;
-	}
-
-	reg_addr = pci_resource_start(pdev, 0);
-	reg_len = pci_resource_len(pdev, 0);
-
-	dev = alloc_etherdev(sizeof(struct amd8111e_priv));
-	if (!dev) {
-		printk(KERN_ERR "amd8111e: Etherdev alloc failed, exiting.\n");
-		err = -ENOMEM;
-		goto err_free_reg;
-	}
-
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-#if AMD8111E_VLAN_TAG_USED
-	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX ;
-#endif
-
-	lp = netdev_priv(dev);
-	lp->pci_dev = pdev;
-	lp->amd8111e_net_dev = dev;
-	lp->pm_cap = pm_cap;
-
-	spin_lock_init(&lp->lock);
-
-	lp->mmio = ioremap(reg_addr, reg_len);
-	if (!lp->mmio) {
-		printk(KERN_ERR "amd8111e: Cannot map device registers, "
-		       "exiting\n");
-		err = -ENOMEM;
-		goto err_free_dev;
-	}
-
-	/* Initializing MAC address */
-	for(i = 0; i < ETH_ADDR_LEN; i++)
-		dev->dev_addr[i] = readb(lp->mmio + PADR + i);
-
-	/* Setting user defined parametrs */
-	lp->ext_phy_option = speed_duplex[card_idx];
-	if(coalesce[card_idx])
-		lp->options |= OPTION_INTR_COAL_ENABLE;
-	if(dynamic_ipg[card_idx++])
-		lp->options |= OPTION_DYN_IPG_ENABLE;
-
-
-	/* Initialize driver entry points */
-	dev->netdev_ops = &amd8111e_netdev_ops;
-	SET_ETHTOOL_OPS(dev, &ops);
-	dev->irq =pdev->irq;
-	dev->watchdog_timeo = AMD8111E_TX_TIMEOUT;
-	netif_napi_add(dev, &lp->napi, amd8111e_rx_poll, 32);
-
-#if AMD8111E_VLAN_TAG_USED
-	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
-	/* Probe the external PHY */
-	amd8111e_probe_ext_phy(dev);
-
-	/* setting mii default values */
-	lp->mii_if.dev = dev;
-	lp->mii_if.mdio_read = amd8111e_mdio_read;
-	lp->mii_if.mdio_write = amd8111e_mdio_write;
-	lp->mii_if.phy_id = lp->ext_phy_addr;
-
-	/* Set receive buffer length and set jumbo option*/
-	amd8111e_set_rx_buff_len(dev);
-
-
-	err = register_netdev(dev);
-	if (err) {
-		printk(KERN_ERR "amd8111e: Cannot register net device, "
-		       "exiting.\n");
-		goto err_iounmap;
-	}
-
-	pci_set_drvdata(pdev, dev);
-
-	/* Initialize software ipg timer */
-	if(lp->options & OPTION_DYN_IPG_ENABLE){
-		init_timer(&lp->ipg_data.ipg_timer);
-		lp->ipg_data.ipg_timer.data = (unsigned long) dev;
-		lp->ipg_data.ipg_timer.function = (void *)&amd8111e_config_ipg;
-		lp->ipg_data.ipg_timer.expires = jiffies +
-						 IPG_CONVERGE_JIFFIES;
-		lp->ipg_data.ipg = DEFAULT_IPG;
-		lp->ipg_data.ipg_state = CSTATE;
-	}
-
-	/*  display driver and device information */
-
-    	chip_version = (readl(lp->mmio + CHIPID) & 0xf0000000)>>28;
-	printk(KERN_INFO "%s: AMD-8111e Driver Version: %s\n",
-	       dev->name,MODULE_VERS);
-	printk(KERN_INFO "%s: [ Rev %x ] PCI 10/100BaseT Ethernet %pM\n",
-	       dev->name, chip_version, dev->dev_addr);
-	if (lp->ext_phy_id)
-		printk(KERN_INFO "%s: Found MII PHY ID 0x%08x at address 0x%02x\n",
-		       dev->name, lp->ext_phy_id, lp->ext_phy_addr);
-	else
-		printk(KERN_INFO "%s: Couldn't detect MII PHY, assuming address 0x01\n",
-		       dev->name);
-    	return 0;
-err_iounmap:
-	iounmap(lp->mmio);
-
-err_free_dev:
-	free_netdev(dev);
-
-err_free_reg:
-	pci_release_regions(pdev);
-
-err_disable_pdev:
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-	return err;
-
-}
-
-static struct pci_driver amd8111e_driver = {
-	.name   	= MODULE_NAME,
-	.id_table	= amd8111e_pci_tbl,
-	.probe		= amd8111e_probe_one,
-	.remove		= __devexit_p(amd8111e_remove_one),
-	.suspend	= amd8111e_suspend,
-	.resume		= amd8111e_resume
-};
-
-static int __init amd8111e_init(void)
-{
-	return pci_register_driver(&amd8111e_driver);
-}
-
-static void __exit amd8111e_cleanup(void)
-{
-	pci_unregister_driver(&amd8111e_driver);
-}
-
-module_init(amd8111e_init);
-module_exit(amd8111e_cleanup);
diff -druN linux-libre-3.1-gnu/drivers/net/amd8111e.h linux-libre-3.2-gnu/drivers/net/amd8111e.h
--- linux-libre-3.1-gnu/drivers/net/amd8111e.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/amd8111e.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,816 +0,0 @@
-/*
- * Advanced  Micro Devices Inc. AMD8111E Linux Network Driver
- * Copyright (C) 2003 Advanced Micro 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
- * USA
-
-Module Name:
-
-    amd8111e.h
-
-Abstract:
-
- 	 AMD8111 based 10/100 Ethernet Controller driver definitions.
-
-Environment:
-
-	Kernel Mode
-
-Revision History:
- 	3.0.0
-	   Initial Revision.
-	3.0.1
-*/
-
-#ifndef _AMD811E_H
-#define _AMD811E_H
-
-/* Command style register access
-
-Registers CMD0, CMD2, CMD3,CMD7 and INTEN0 uses a write access technique called command style access. It allows the write to selected bits of this register without altering the bits that are not selected. Command style registers are divided into 4 bytes that can be written independently. Higher order bit of each byte is the  value bit that specifies the value that will be written into the selected bits of register.
-
-eg., if the value 10011010b is written into the least significant byte of a command style register, bits 1,3 and 4 of the register will be set to 1, and the other bits will not be altered. If the value 00011010b is written into the same byte, bits 1,3 and 4 will be cleared to 0 and the other bits will not be altered.
-
-*/
-
-/*  Offset for Memory Mapped Registers. */
-/* 32 bit registers */
-
-#define  ASF_STAT		0x00	/* ASF status register */
-#define CHIPID			0x04	/* Chip ID regsiter */
-#define	MIB_DATA		0x10	/* MIB data register */
-#define MIB_ADDR		0x14	/* MIB address register */
-#define STAT0			0x30	/* Status0 register */
-#define INT0			0x38	/* Interrupt0 register */
-#define INTEN0			0x40	/* Interrupt0  enable register*/
-#define CMD0			0x48	/* Command0 register */
-#define CMD2			0x50	/* Command2 register */
-#define CMD3			0x54	/* Command3 resiter */
-#define CMD7			0x64	/* Command7 register */
-
-#define CTRL1 			0x6C	/* Control1 register */
-#define CTRL2 			0x70	/* Control2 register */
-
-#define XMT_RING_LIMIT		0x7C	/* Transmit ring limit register */
-
-#define AUTOPOLL0		0x88	/* Auto-poll0 register */
-#define AUTOPOLL1		0x8A	/* Auto-poll1 register */
-#define AUTOPOLL2		0x8C	/* Auto-poll2 register */
-#define AUTOPOLL3		0x8E	/* Auto-poll3 register */
-#define AUTOPOLL4		0x90	/* Auto-poll4 register */
-#define	AUTOPOLL5		0x92	/* Auto-poll5 register */
-
-#define AP_VALUE		0x98	/* Auto-poll value register */
-#define DLY_INT_A		0xA8	/* Group A delayed interrupt register */
-#define DLY_INT_B		0xAC	/* Group B delayed interrupt register */
-
-#define FLOW_CONTROL		0xC8	/* Flow control register */
-#define PHY_ACCESS		0xD0	/* PHY access register */
-
-#define STVAL			0xD8	/* Software timer value register */
-
-#define XMT_RING_BASE_ADDR0	0x100	/* Transmit ring0 base addr register */
-#define XMT_RING_BASE_ADDR1	0x108	/* Transmit ring1 base addr register */
-#define XMT_RING_BASE_ADDR2	0x110	/* Transmit ring2 base addr register */
-#define XMT_RING_BASE_ADDR3	0x118	/* Transmit ring2 base addr register */
-
-#define RCV_RING_BASE_ADDR0	0x120	/* Transmit ring0 base addr register */
-
-#define PMAT0			0x190	/* OnNow pattern register0 */
-#define PMAT1			0x194	/* OnNow pattern register1 */
-
-/* 16bit registers */
-
-#define XMT_RING_LEN0		0x140	/* Transmit Ring0 length register */
-#define XMT_RING_LEN1		0x144	/* Transmit Ring1 length register */
-#define XMT_RING_LEN2		0x148 	/* Transmit Ring2 length register */
-#define XMT_RING_LEN3		0x14C	/* Transmit Ring3 length register */
-
-#define RCV_RING_LEN0		0x150	/* Receive Ring0 length register */
-
-#define SRAM_SIZE		0x178	/* SRAM size register */
-#define SRAM_BOUNDARY		0x17A	/* SRAM boundary register */
-
-/* 48bit register */
-
-#define PADR			0x160	/* Physical address register */
-
-#define IFS1			0x18C	/* Inter-frame spacing Part1 register */
-#define IFS			0x18D	/* Inter-frame spacing register */
-#define IPG			0x18E	/* Inter-frame gap register */
-/* 64bit register */
-
-#define LADRF			0x168	/* Logical address filter register */
-
-
-/* Register Bit Definitions */
-typedef enum {
-
-	ASF_INIT_DONE		= (1 << 1),
-	ASF_INIT_PRESENT	= (1 << 0),
-
-}STAT_ASF_BITS;
-
-typedef enum {
-
-	MIB_CMD_ACTIVE		= (1 << 15 ),
-	MIB_RD_CMD		= (1 << 13 ),
-	MIB_CLEAR		= (1 << 12 ),
-	MIB_ADDRESS		= (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)|
-					(1 << 4) | (1 << 5),
-}MIB_ADDR_BITS;
-
-
-typedef enum {
-
-	PMAT_DET		= (1 << 12),
-	MP_DET		        = (1 << 11),
-	LC_DET			= (1 << 10),
-	SPEED_MASK		= (1 << 9)|(1 << 8)|(1 << 7),
-	FULL_DPLX		= (1 << 6),
-	LINK_STATS		= (1 << 5),
-	AUTONEG_COMPLETE	= (1 << 4),
-	MIIPD			= (1 << 3),
-	RX_SUSPENDED		= (1 << 2),
-	TX_SUSPENDED		= (1 << 1),
-	RUNNING			= (1 << 0),
-
-}STAT0_BITS;
-
-#define PHY_SPEED_10		0x2
-#define PHY_SPEED_100		0x3
-
-/* INT0				0x38, 32bit register */
-typedef enum {
-
-	INTR			= (1 << 31),
-	PCSINT			= (1 << 28),
-	LCINT			= (1 << 27),
-	APINT5			= (1 << 26),
-	APINT4			= (1 << 25),
-	APINT3			= (1 << 24),
-	TINT_SUM		= (1 << 23),
-	APINT2			= (1 << 22),
-	APINT1			= (1 << 21),
-	APINT0			= (1 << 20),
-	MIIPDTINT		= (1 << 19),
-	MCCINT			= (1 << 17),
-	MREINT			= (1 << 16),
-	RINT_SUM		= (1 << 15),
-	SPNDINT			= (1 << 14),
-	MPINT			= (1 << 13),
-	SINT			= (1 << 12),
-	TINT3			= (1 << 11),
-	TINT2			= (1 << 10),
-	TINT1			= (1 << 9),
-	TINT0			= (1 << 8),
-	UINT			= (1 << 7),
-	STINT			= (1 << 4),
-	RINT0			= (1 << 0),
-
-}INT0_BITS;
-
-typedef enum {
-
-	VAL3			= (1 << 31),   /* VAL bit for byte 3 */
-	VAL2			= (1 << 23),   /* VAL bit for byte 2 */
-	VAL1			= (1 << 15),   /* VAL bit for byte 1 */
-	VAL0			= (1 << 7),    /* VAL bit for byte 0 */
-
-}VAL_BITS;
-
-typedef enum {
-
-	/* VAL3 */
-	LCINTEN			= (1 << 27),
-	APINT5EN		= (1 << 26),
-	APINT4EN		= (1 << 25),
-	APINT3EN		= (1 << 24),
-	/* VAL2 */
-	APINT2EN		= (1 << 22),
-	APINT1EN		= (1 << 21),
-	APINT0EN		= (1 << 20),
-	MIIPDTINTEN		= (1 << 19),
-	MCCIINTEN		= (1 << 18),
-	MCCINTEN		= (1 << 17),
-	MREINTEN		= (1 << 16),
-	/* VAL1 */
-	SPNDINTEN		= (1 << 14),
-	MPINTEN			= (1 << 13),
-	TINTEN3			= (1 << 11),
-	SINTEN			= (1 << 12),
-	TINTEN2			= (1 << 10),
-	TINTEN1			= (1 << 9),
-	TINTEN0			= (1 << 8),
-	/* VAL0 */
-	STINTEN			= (1 << 4),
-	RINTEN0			= (1 << 0),
-
-	INTEN0_CLEAR 		= 0x1F7F7F1F, /* Command style register */
-
-}INTEN0_BITS;
-
-typedef enum {
-	/* VAL2 */
-	RDMD0			= (1 << 16),
-	/* VAL1 */
-	TDMD3			= (1 << 11),
-	TDMD2			= (1 << 10),
-	TDMD1			= (1 << 9),
-	TDMD0			= (1 << 8),
-	/* VAL0 */
-	UINTCMD			= (1 << 6),
-	RX_FAST_SPND		= (1 << 5),
-	TX_FAST_SPND		= (1 << 4),
-	RX_SPND			= (1 << 3),
-	TX_SPND			= (1 << 2),
-	INTREN			= (1 << 1),
-	RUN			= (1 << 0),
-
-	CMD0_CLEAR 		= 0x000F0F7F,   /* Command style register */
-
-}CMD0_BITS;
-
-typedef enum {
-
-	/* VAL3 */
-	CONDUIT_MODE		= (1 << 29),
-	/* VAL2 */
-	RPA			= (1 << 19),
-	DRCVPA			= (1 << 18),
-	DRCVBC			= (1 << 17),
-	PROM			= (1 << 16),
-	/* VAL1 */
-	ASTRP_RCV		= (1 << 13),
-	RCV_DROP0	  	= (1 << 12),
-	EMBA			= (1 << 11),
-	DXMT2PD			= (1 << 10),
-	LTINTEN			= (1 << 9),
-	DXMTFCS			= (1 << 8),
-	/* VAL0 */
-	APAD_XMT		= (1 << 6),
-	DRTY			= (1 << 5),
-	INLOOP			= (1 << 4),
-	EXLOOP			= (1 << 3),
-	REX_RTRY		= (1 << 2),
-	REX_UFLO		= (1 << 1),
-	REX_LCOL		= (1 << 0),
-
-	CMD2_CLEAR 		= 0x3F7F3F7F,   /* Command style register */
-
-}CMD2_BITS;
-
-typedef enum {
-
-	/* VAL3 */
-	ASF_INIT_DONE_ALIAS	= (1 << 29),
-	/* VAL2 */
-	JUMBO			= (1 << 21),
-	VSIZE			= (1 << 20),
-	VLONLY			= (1 << 19),
-	VL_TAG_DEL		= (1 << 18),
-	/* VAL1 */
-	EN_PMGR			= (1 << 14),
-	INTLEVEL		= (1 << 13),
-	FORCE_FULL_DUPLEX	= (1 << 12),
-	FORCE_LINK_STATUS	= (1 << 11),
-	APEP			= (1 << 10),
-	MPPLBA			= (1 << 9),
-	/* VAL0 */
-	RESET_PHY_PULSE		= (1 << 2),
-	RESET_PHY		= (1 << 1),
-	PHY_RST_POL		= (1 << 0),
-
-}CMD3_BITS;
-
-
-typedef enum {
-
-	/* VAL0 */
-	PMAT_SAVE_MATCH		= (1 << 4),
-	PMAT_MODE		= (1 << 3),
-	MPEN_SW			= (1 << 1),
-	LCMODE_SW		= (1 << 0),
-
-	CMD7_CLEAR  		= 0x0000001B	/* Command style register */
-
-}CMD7_BITS;
-
-
-typedef enum {
-
-	RESET_PHY_WIDTH		= (0xF << 16) | (0xF<< 20), /* 0x00FF0000 */
-	XMTSP_MASK		= (1 << 9) | (1 << 8),	/* 9:8 */
-	XMTSP_128		= (1 << 9),	/* 9 */
-	XMTSP_64		= (1 << 8),
-	CACHE_ALIGN		= (1 << 4),
-	BURST_LIMIT_MASK	= (0xF << 0 ),
-	CTRL1_DEFAULT		= 0x00010111,
-
-}CTRL1_BITS;
-
-typedef enum {
-
-	FMDC_MASK		= (1 << 9)|(1 << 8),	/* 9:8 */
-	XPHYRST			= (1 << 7),
-	XPHYANE			= (1 << 6),
-	XPHYFD			= (1 << 5),
-	XPHYSP			= (1 << 4) | (1 << 3),	/* 4:3 */
-	APDW_MASK		= (1 <<	2) | (1 << 1) | (1 << 0), /* 2:0 */
-
-}CTRL2_BITS;
-
-/* XMT_RING_LIMIT		0x7C, 32bit register */
-typedef enum {
-
-	XMT_RING2_LIMIT		= (0xFF << 16),	/* 23:16 */
-	XMT_RING1_LIMIT		= (0xFF << 8),	/* 15:8 */
-	XMT_RING0_LIMIT		= (0xFF << 0), 	/* 7:0 */
-
-}XMT_RING_LIMIT_BITS;
-
-typedef enum {
-
-	AP_REG0_EN		= (1 << 15),
-	AP_REG0_ADDR_MASK	= (0xF << 8) |(1 << 12),/* 12:8 */
-	AP_PHY0_ADDR_MASK	= (0xF << 0) |(1 << 4),/* 4:0 */
-
-}AUTOPOLL0_BITS;
-
-/* AUTOPOLL1			0x8A, 16bit register */
-typedef enum {
-
-	AP_REG1_EN		= (1 << 15),
-	AP_REG1_ADDR_MASK	= (0xF << 8) |(1 << 12),/* 12:8 */
-	AP_PRE_SUP1		= (1 << 6),
-	AP_PHY1_DFLT		= (1 << 5),
-	AP_PHY1_ADDR_MASK	= (0xF << 0) |(1 << 4),/* 4:0 */
-
-}AUTOPOLL1_BITS;
-
-
-typedef enum {
-
-	AP_REG2_EN		= (1 << 15),
-	AP_REG2_ADDR_MASK	= (0xF << 8) |(1 << 12),/* 12:8 */
-	AP_PRE_SUP2		= (1 << 6),
-	AP_PHY2_DFLT		= (1 << 5),
-	AP_PHY2_ADDR_MASK	= (0xF << 0) |(1 << 4),/* 4:0 */
-
-}AUTOPOLL2_BITS;
-
-typedef enum {
-
-	AP_REG3_EN		= (1 << 15),
-	AP_REG3_ADDR_MASK	= (0xF << 8) |(1 << 12),/* 12:8 */
-	AP_PRE_SUP3		= (1 << 6),
-	AP_PHY3_DFLT		= (1 << 5),
-	AP_PHY3_ADDR_MASK	= (0xF << 0) |(1 << 4),/* 4:0 */
-
-}AUTOPOLL3_BITS;
-
-
-typedef enum {
-
-	AP_REG4_EN		= (1 << 15),
-	AP_REG4_ADDR_MASK	= (0xF << 8) |(1 << 12),/* 12:8 */
-	AP_PRE_SUP4		= (1 << 6),
-	AP_PHY4_DFLT		= (1 << 5),
-	AP_PHY4_ADDR_MASK	= (0xF << 0) |(1 << 4),/* 4:0 */
-
-}AUTOPOLL4_BITS;
-
-
-typedef enum {
-
-	AP_REG5_EN		= (1 << 15),
-	AP_REG5_ADDR_MASK	= (0xF << 8) |(1 << 12),/* 12:8 */
-	AP_PRE_SUP5		= (1 << 6),
-	AP_PHY5_DFLT		= (1 << 5),
-	AP_PHY5_ADDR_MASK	= (0xF << 0) |(1 << 4),/* 4:0 */
-
-}AUTOPOLL5_BITS;
-
-
-
-
-/* AP_VALUE 			0x98, 32bit ragister */
-typedef enum {
-
-	AP_VAL_ACTIVE		= (1 << 31),
-	AP_VAL_RD_CMD		= ( 1 << 29),
-	AP_ADDR			= (1 << 18)|(1 << 17)|(1 << 16), /* 18:16 */
-	AP_VAL			= (0xF << 0) | (0xF << 4) |( 0xF << 8) |
-				  (0xF << 12),	/* 15:0 */
-
-}AP_VALUE_BITS;
-
-typedef enum {
-
-	DLY_INT_A_R3		= (1 << 31),
-	DLY_INT_A_R2		= (1 << 30),
-	DLY_INT_A_R1		= (1 << 29),
-	DLY_INT_A_R0		= (1 << 28),
-	DLY_INT_A_T3		= (1 << 27),
-	DLY_INT_A_T2		= (1 << 26),
-	DLY_INT_A_T1		= (1 << 25),
-	DLY_INT_A_T0		= ( 1 << 24),
-	EVENT_COUNT_A		= (0xF << 16) | (0x1 << 20),/* 20:16 */
-	MAX_DELAY_TIME_A	= (0xF << 0) | (0xF << 4) | (1 << 8)|
-				  (1 << 9) | (1 << 10),	/* 10:0 */
-
-}DLY_INT_A_BITS;
-
-typedef enum {
-
-	DLY_INT_B_R3		= (1 << 31),
-	DLY_INT_B_R2		= (1 << 30),
-	DLY_INT_B_R1		= (1 << 29),
-	DLY_INT_B_R0		= (1 << 28),
-	DLY_INT_B_T3		= (1 << 27),
-	DLY_INT_B_T2		= (1 << 26),
-	DLY_INT_B_T1		= (1 << 25),
-	DLY_INT_B_T0		= ( 1 << 24),
-	EVENT_COUNT_B		= (0xF << 16) | (0x1 << 20),/* 20:16 */
-	MAX_DELAY_TIME_B	= (0xF << 0) | (0xF << 4) | (1 << 8)|
-				  (1 << 9) | (1 << 10),	/* 10:0 */
-}DLY_INT_B_BITS;
-
-
-/* FLOW_CONTROL 		0xC8, 32bit register */
-typedef enum {
-
-	PAUSE_LEN_CHG		= (1 << 30),
-	FTPE			= (1 << 22),
-	FRPE			= (1 << 21),
-	NAPA			= (1 << 20),
-	NPA			= (1 << 19),
-	FIXP			= ( 1 << 18),
-	FCCMD			= ( 1 << 16),
-	PAUSE_LEN		= (0xF << 0) | (0xF << 4) |( 0xF << 8) |	 				  (0xF << 12),	/* 15:0 */
-
-}FLOW_CONTROL_BITS;
-
-/* PHY_ ACCESS			0xD0, 32bit register */
-typedef enum {
-
-	PHY_CMD_ACTIVE		= (1 << 31),
-	PHY_WR_CMD		= (1 << 30),
-	PHY_RD_CMD		= (1 << 29),
-	PHY_RD_ERR		= (1 << 28),
-	PHY_PRE_SUP		= (1 << 27),
-	PHY_ADDR		= (1 << 21) | (1 << 22) | (1 << 23)|
-				  	(1 << 24) |(1 << 25),/* 25:21 */
-	PHY_REG_ADDR		= (1 << 16) | (1 << 17) | (1 << 18)|	 			  	   	  	(1 << 19) | (1 << 20),/* 20:16 */
-	PHY_DATA		= (0xF << 0)|(0xF << 4) |(0xF << 8)|
-					(0xF << 12),/* 15:0 */
-
-}PHY_ACCESS_BITS;
-
-
-/* PMAT0			0x190,	 32bit register */
-typedef enum {
-	PMR_ACTIVE		= (1 << 31),
-	PMR_WR_CMD		= (1 << 30),
-	PMR_RD_CMD		= (1 << 29),
-	PMR_BANK		= (1 <<28),
-	PMR_ADDR		= (0xF << 16)|(1 << 20)|(1 << 21)|
-				  	(1 << 22),/* 22:16 */
-	PMR_B4			= (0xF << 0) | (0xF << 4),/* 15:0 */
-}PMAT0_BITS;
-
-
-/* PMAT1			0x194,	 32bit register */
-typedef enum {
-	PMR_B3			= (0xF << 24) | (0xF <<28),/* 31:24 */
-	PMR_B2			= (0xF << 16) |(0xF << 20),/* 23:16 */
-	PMR_B1			= (0xF << 8) | (0xF <<12), /* 15:8 */
-	PMR_B0			= (0xF << 0)|(0xF << 4),/* 7:0 */
-}PMAT1_BITS;
-
-/************************************************************************/
-/*                                                                      */
-/*                      MIB counter definitions                         */
-/*                                                                      */
-/************************************************************************/
-
-#define rcv_miss_pkts				0x00
-#define rcv_octets				0x01
-#define rcv_broadcast_pkts			0x02
-#define rcv_multicast_pkts			0x03
-#define rcv_undersize_pkts			0x04
-#define rcv_oversize_pkts			0x05
-#define rcv_fragments				0x06
-#define rcv_jabbers				0x07
-#define rcv_unicast_pkts			0x08
-#define rcv_alignment_errors			0x09
-#define rcv_fcs_errors				0x0A
-#define rcv_good_octets				0x0B
-#define rcv_mac_ctrl				0x0C
-#define rcv_flow_ctrl				0x0D
-#define rcv_pkts_64_octets			0x0E
-#define rcv_pkts_65to127_octets			0x0F
-#define rcv_pkts_128to255_octets		0x10
-#define rcv_pkts_256to511_octets		0x11
-#define rcv_pkts_512to1023_octets		0x12
-#define rcv_pkts_1024to1518_octets		0x13
-#define rcv_unsupported_opcode			0x14
-#define rcv_symbol_errors			0x15
-#define rcv_drop_pkts_ring1			0x16
-#define rcv_drop_pkts_ring2			0x17
-#define rcv_drop_pkts_ring3			0x18
-#define rcv_drop_pkts_ring4			0x19
-#define rcv_jumbo_pkts				0x1A
-
-#define xmt_underrun_pkts			0x20
-#define xmt_octets				0x21
-#define xmt_packets				0x22
-#define xmt_broadcast_pkts			0x23
-#define xmt_multicast_pkts			0x24
-#define xmt_collisions				0x25
-#define xmt_unicast_pkts			0x26
-#define xmt_one_collision			0x27
-#define xmt_multiple_collision			0x28
-#define xmt_deferred_transmit			0x29
-#define xmt_late_collision			0x2A
-#define xmt_excessive_defer			0x2B
-#define xmt_loss_carrier			0x2C
-#define xmt_excessive_collision			0x2D
-#define xmt_back_pressure			0x2E
-#define xmt_flow_ctrl				0x2F
-#define xmt_pkts_64_octets			0x30
-#define xmt_pkts_65to127_octets			0x31
-#define xmt_pkts_128to255_octets		0x32
-#define xmt_pkts_256to511_octets		0x33
-#define xmt_pkts_512to1023_octets		0x34
-#define xmt_pkts_1024to1518_octet		0x35
-#define xmt_oversize_pkts			0x36
-#define xmt_jumbo_pkts				0x37
-
-
-/* Driver definitions */
-
-#define	 PCI_VENDOR_ID_AMD		0x1022
-#define  PCI_DEVICE_ID_AMD8111E_7462	0x7462
-
-#define MAX_UNITS			8 /* Maximum number of devices possible */
-
-#define NUM_TX_BUFFERS			32 /* Number of transmit buffers */
-#define NUM_RX_BUFFERS			32 /* Number of receive buffers */
-
-#define TX_BUFF_MOD_MASK         	31 /* (NUM_TX_BUFFERS -1) */
-#define RX_BUFF_MOD_MASK         	31 /* (NUM_RX_BUFFERS -1) */
-
-#define NUM_TX_RING_DR			32
-#define NUM_RX_RING_DR			32
-
-#define TX_RING_DR_MOD_MASK         	31 /* (NUM_TX_RING_DR -1) */
-#define RX_RING_DR_MOD_MASK         	31 /* (NUM_RX_RING_DR -1) */
-
-#define MAX_FILTER_SIZE			64 /* Maximum multicast address */
-#define AMD8111E_MIN_MTU	 	60
-#define AMD8111E_MAX_MTU		9000
-
-#define PKT_BUFF_SZ			1536
-#define MIN_PKT_LEN			60
-#define ETH_ADDR_LEN			6
-
-#define  AMD8111E_TX_TIMEOUT		(3 * HZ)/* 3 sec */
-#define SOFT_TIMER_FREQ 		0xBEBC  /* 0.5 sec */
-#define DELAY_TIMER_CONV		50    /* msec to 10 usec conversion.
-						 Only 500 usec resolution */
-#define OPTION_VLAN_ENABLE		0x0001
-#define OPTION_JUMBO_ENABLE		0x0002
-#define OPTION_MULTICAST_ENABLE		0x0004
-#define OPTION_WOL_ENABLE		0x0008
-#define OPTION_WAKE_MAGIC_ENABLE	0x0010
-#define OPTION_WAKE_PHY_ENABLE		0x0020
-#define OPTION_INTR_COAL_ENABLE		0x0040
-#define OPTION_DYN_IPG_ENABLE	        0x0080
-
-#define PHY_REG_ADDR_MASK		0x1f
-
-/* ipg parameters */
-#define DEFAULT_IPG			0x60
-#define IFS1_DELTA			36
-#define	IPG_CONVERGE_JIFFIES (HZ/2)
-#define	IPG_STABLE_TIME	5
-#define	MIN_IPG	96
-#define	MAX_IPG	255
-#define IPG_STEP	16
-#define CSTATE  1
-#define SSTATE  2
-
-/* Assume contoller gets data 10 times the maximum processing time */
-#define  REPEAT_CNT			10
-
-/* amd8111e decriptor flag definitions */
-typedef enum {
-
-	OWN_BIT		=	(1 << 15),
-	ADD_FCS_BIT	=	(1 << 13),
-	LTINT_BIT	=	(1 << 12),
-	STP_BIT		=	(1 << 9),
-	ENP_BIT		=	(1 << 8),
-	KILL_BIT	= 	(1 << 6),
-	TCC_VLAN_INSERT	=	(1 << 1),
-	TCC_VLAN_REPLACE =	(1 << 1) |( 1<< 0),
-
-}TX_FLAG_BITS;
-
-typedef enum {
-	ERR_BIT 	=	(1 << 14),
-	FRAM_BIT	=  	(1 << 13),
-	OFLO_BIT	=       (1 << 12),
-	CRC_BIT		=	(1 << 11),
-	PAM_BIT		=	(1 << 6),
-	LAFM_BIT	= 	(1 << 5),
-	BAM_BIT		=	(1 << 4),
-	TT_VLAN_TAGGED	= 	(1 << 3) |(1 << 2),/* 0x000 */
-	TT_PRTY_TAGGED	=	(1 << 3),/* 0x0008 */
-
-}RX_FLAG_BITS;
-
-#define RESET_RX_FLAGS		0x0000
-#define TT_MASK			0x000c
-#define TCC_MASK		0x0003
-
-/* driver ioctl parameters */
-#define AMD8111E_REG_DUMP_LEN	 13*sizeof(u32)
-
-/* amd8111e desriptor format */
-
-struct amd8111e_tx_dr{
-
-	__le16 buff_count; /* Size of the buffer pointed by this descriptor */
-
-	__le16 tx_flags;
-
-	__le16 tag_ctrl_info;
-
-	__le16 tag_ctrl_cmd;
-
-	__le32 buff_phy_addr;
-
-	__le32 reserved;
-};
-
-struct amd8111e_rx_dr{
-
-	__le32 reserved;
-
-	__le16 msg_count; /* Received message len */
-
-	__le16 tag_ctrl_info;
-
-	__le16 buff_count;  /* Len of the buffer pointed by descriptor. */
-
-	__le16 rx_flags;
-
-	__le32 buff_phy_addr;
-
-};
-struct amd8111e_link_config{
-
-#define SPEED_INVALID		0xffff
-#define DUPLEX_INVALID		0xff
-#define AUTONEG_INVALID		0xff
-
-	unsigned long			orig_phy_option;
-	u16				speed;
-	u8				duplex;
-	u8				autoneg;
-	u8				reserved;  /* 32bit alignment */
-};
-
-enum coal_type{
-
-	NO_COALESCE,
-	LOW_COALESCE,
-	MEDIUM_COALESCE,
-	HIGH_COALESCE,
-
-};
-
-enum coal_mode{
-       	RX_INTR_COAL,
-	TX_INTR_COAL,
-	DISABLE_COAL,
-	ENABLE_COAL,
-
-};
-#define MAX_TIMEOUT	40
-#define MAX_EVENT_COUNT 31
-struct amd8111e_coalesce_conf{
-
-	unsigned int rx_timeout;
-	unsigned int rx_event_count;
-	unsigned long rx_packets;
-	unsigned long rx_prev_packets;
-	unsigned long rx_bytes;
-	unsigned long rx_prev_bytes;
-	unsigned int rx_coal_type;
-
-	unsigned int tx_timeout;
-	unsigned int tx_event_count;
-	unsigned long tx_packets;
-	unsigned long tx_prev_packets;
-	unsigned long tx_bytes;
-	unsigned long tx_prev_bytes;
-	unsigned int tx_coal_type;
-
-};
-struct ipg_info{
-
-	unsigned int ipg_state;
-	unsigned int ipg;
-	unsigned int current_ipg;
-	unsigned int col_cnt;
-	unsigned int diff_col_cnt;
-	unsigned int timer_tick;
-	unsigned int prev_ipg;
-	struct timer_list ipg_timer;
-};
-
-struct amd8111e_priv{
-
-	struct amd8111e_tx_dr*  tx_ring;
-	struct amd8111e_rx_dr* rx_ring;
-	dma_addr_t tx_ring_dma_addr;	/* tx descriptor ring base address */
-	dma_addr_t rx_ring_dma_addr;	/* rx descriptor ring base address */
-	const char *name;
-	struct pci_dev *pci_dev;	/* Ptr to the associated pci_dev */
-	struct net_device* amd8111e_net_dev; 	/* ptr to associated net_device */
-	/* Transmit and recive skbs */
-	struct sk_buff *tx_skbuff[NUM_TX_BUFFERS];
-	struct sk_buff *rx_skbuff[NUM_RX_BUFFERS];
-	/* Transmit and receive dma mapped addr */
-	dma_addr_t tx_dma_addr[NUM_TX_BUFFERS];
-	dma_addr_t rx_dma_addr[NUM_RX_BUFFERS];
-	/* Reg memory mapped address */
-	void __iomem *mmio;
-
-	struct napi_struct napi;
-
-	spinlock_t lock;	/* Guard lock */
-	unsigned long rx_idx, tx_idx;	/* The next free ring entry */
-	unsigned long tx_complete_idx;
-	unsigned long tx_ring_complete_idx;
-	unsigned long tx_ring_idx;
-	unsigned int rx_buff_len;	/* Buffer length of rx buffers */
-	int options;		/* Options enabled/disabled for the device */
-
-	unsigned long ext_phy_option;
-	int ext_phy_addr;
-	u32 ext_phy_id;
-
-	struct amd8111e_link_config link_config;
-	int pm_cap;
-
-	struct net_device *next;
-	int mii;
-	struct mii_if_info mii_if;
-	char opened;
-	unsigned int drv_rx_errors;
-	struct amd8111e_coalesce_conf coal_conf;
-
-	struct ipg_info  ipg_data;
-
-};
-
-/* kernel provided writeq does not write 64 bits into the amd8111e device register instead writes only higher 32bits data into lower 32bits of the register.
-BUG? */
-#define  amd8111e_writeq(_UlData,_memMap)   \
-		writel(*(u32*)(&_UlData), _memMap);	\
-		writel(*(u32*)((u8*)(&_UlData)+4), _memMap+4)
-
-/* maps the external speed options to internal value */
-typedef enum {
-	SPEED_AUTONEG,
-	SPEED10_HALF,
-	SPEED10_FULL,
-	SPEED100_HALF,
-	SPEED100_FULL,
-}EXT_PHY_OPTION;
-
-static int card_idx;
-static int speed_duplex[MAX_UNITS] = { 0, };
-static int coalesce[MAX_UNITS] = {1,1,1,1,1,1,1,1};
-static int dynamic_ipg[MAX_UNITS] = {0,0,0,0,0,0,0,0};
-static unsigned int chip_version;
-
-#endif /* _AMD8111E_H */
-
diff -druN linux-libre-3.1-gnu/drivers/net/apne.c linux-libre-3.2-gnu/drivers/net/apne.c
--- linux-libre-3.1-gnu/drivers/net/apne.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/apne.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,620 +0,0 @@
-/*
- * Amiga Linux/68k 8390 based PCMCIA Ethernet Driver for the Amiga 1200
- *
- * (C) Copyright 1997 Alain Malek
- *                    (Alain.Malek@cryogen.com)
- *
- * ----------------------------------------------------------------------------
- *
- * This program is based on
- *
- * ne.c:       A general non-shared-memory NS8390 ethernet driver for linux
- *             Written 1992-94 by Donald Becker.
- *
- * 8390.c:     A general NS8390 ethernet driver core for linux.
- *             Written 1992-94 by Donald Becker.
- *
- * cnetdevice: A Sana-II ethernet driver for AmigaOS
- *             Written by Bruce Abbott (bhabbott@inhb.co.nz)
- *
- * ----------------------------------------------------------------------------
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of the Linux
- * distribution for more details.
- *
- * ----------------------------------------------------------------------------
- *
- */
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/interrupt.h>
-#include <linux/jiffies.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/setup.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-#include <asm/amigayle.h>
-#include <asm/amipcmcia.h>
-
-#include "8390.h"
-
-/* ---- No user-serviceable parts below ---- */
-
-#define DRV_NAME "apne"
-
-#define NE_BASE	 (dev->base_addr)
-#define NE_CMD	 		0x00
-#define NE_DATAPORT		0x10            /* NatSemi-defined port window offset. */
-#define NE_RESET		0x1f            /* Issue a read to reset, a write to clear. */
-#define NE_IO_EXTENT	        0x20
-
-#define NE_EN0_ISR		0x07
-#define NE_EN0_DCFG		0x0e
-
-#define NE_EN0_RSARLO	        0x08
-#define NE_EN0_RSARHI	        0x09
-#define NE_EN0_RCNTLO	        0x0a
-#define NE_EN0_RXCR		0x0c
-#define NE_EN0_TXCR		0x0d
-#define NE_EN0_RCNTHI	        0x0b
-#define NE_EN0_IMR		0x0f
-
-#define NE1SM_START_PG	0x20	/* First page of TX buffer */
-#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 */
-
-
-struct net_device * __init apne_probe(int unit);
-static int apne_probe1(struct net_device *dev, int ioaddr);
-
-static void apne_reset_8390(struct net_device *dev);
-static void apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-			  int ring_page);
-static void apne_block_input(struct net_device *dev, int count,
-								struct sk_buff *skb, int ring_offset);
-static void apne_block_output(struct net_device *dev, const int count,
-							const unsigned char *buf, const int start_page);
-static irqreturn_t apne_interrupt(int irq, void *dev_id);
-
-static int init_pcmcia(void);
-
-/* IO base address used for nic */
-
-#define IOBASE 0x300
-
-/*
-   use MANUAL_CONFIG and MANUAL_OFFSET for enabling IO by hand
-   you can find the values to use by looking at the cnet.device
-   config file example (the default values are for the CNET40BC card)
-*/
-
-/*
-#define MANUAL_CONFIG 0x20
-#define MANUAL_OFFSET 0x3f8
-
-#define MANUAL_HWADDR0 0x00
-#define MANUAL_HWADDR1 0x12
-#define MANUAL_HWADDR2 0x34
-#define MANUAL_HWADDR3 0x56
-#define MANUAL_HWADDR4 0x78
-#define MANUAL_HWADDR5 0x9a
-*/
-
-static const char version[] =
-    "apne.c:v1.1 7/10/98 Alain Malek (Alain.Malek@cryogen.ch)\n";
-
-static int apne_owned;	/* signal if card already owned */
-
-struct net_device * __init apne_probe(int unit)
-{
-	struct net_device *dev;
-#ifndef MANUAL_CONFIG
-	char tuple[8];
-#endif
-	int err;
-
-	if (!MACH_IS_AMIGA)
-		return ERR_PTR(-ENODEV);
-
-	if (apne_owned)
-		return ERR_PTR(-ENODEV);
-
-	if ( !(AMIGAHW_PRESENT(PCMCIA)) )
-		return ERR_PTR(-ENODEV);
-
-	printk("Looking for PCMCIA ethernet card : ");
-
-	/* check if a card is inserted */
-	if (!(PCMCIA_INSERTED)) {
-		printk("NO PCMCIA card inserted\n");
-		return ERR_PTR(-ENODEV);
-	}
-
-	dev = alloc_ei_netdev();
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-	if (unit >= 0) {
-		sprintf(dev->name, "eth%d", unit);
-		netdev_boot_setup_check(dev);
-	}
-
-	/* disable pcmcia irq for readtuple */
-	pcmcia_disable_irq();
-
-#ifndef MANUAL_CONFIG
-	if ((pcmcia_copy_tuple(CISTPL_FUNCID, tuple, 8) < 3) ||
-		(tuple[2] != CISTPL_FUNCID_NETWORK)) {
-		printk("not an ethernet card\n");
-		/* XXX: shouldn't we re-enable irq here? */
-		free_netdev(dev);
-		return ERR_PTR(-ENODEV);
-	}
-#endif
-
-	printk("ethernet PCMCIA card inserted\n");
-
-	if (!init_pcmcia()) {
-		/* XXX: shouldn't we re-enable irq here? */
-		free_netdev(dev);
-		return ERR_PTR(-ENODEV);
-	}
-
-	if (!request_region(IOBASE, 0x20, DRV_NAME)) {
-		free_netdev(dev);
-		return ERR_PTR(-EBUSY);
-	}
-
-	err = apne_probe1(dev, IOBASE);
-	if (err) {
-		release_region(IOBASE, 0x20);
-		free_netdev(dev);
-		return ERR_PTR(err);
-	}
-	err = register_netdev(dev);
-	if (!err)
-		return dev;
-
-	pcmcia_disable_irq();
-	free_irq(IRQ_AMIGA_PORTS, dev);
-	pcmcia_reset();
-	release_region(IOBASE, 0x20);
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-
-static int __init apne_probe1(struct net_device *dev, int ioaddr)
-{
-    int i;
-    unsigned char SA_prom[32];
-    int wordlength = 2;
-    const char *name = NULL;
-    int start_page, stop_page;
-#ifndef MANUAL_HWADDR0
-    int neX000, ctron;
-#endif
-    static unsigned version_printed;
-
-    if (ei_debug  &&  version_printed++ == 0)
-	printk(version);
-
-    printk("PCMCIA NE*000 ethercard probe");
-
-    /* Reset card. Who knows what dain-bramaged state it was left in. */
-    {	unsigned long reset_start_time = jiffies;
-
-	outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
-
-	while ((inb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
-		if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
-			printk(" not found (no reset ack).\n");
-			return -ENODEV;
-		}
-
-	outb(0xff, ioaddr + NE_EN0_ISR);		/* Ack all intr. */
-    }
-
-#ifndef MANUAL_HWADDR0
-
-    /* Read the 16 bytes of station address PROM.
-       We must first initialize registers, similar to NS8390_init(eifdev, 0).
-       We can't reliably read the SAPROM address without this.
-       (I learned the hard way!). */
-    {
-	struct {unsigned long value, offset; } program_seq[] = {
-	    {E8390_NODMA+E8390_PAGE0+E8390_STOP, NE_CMD}, /* Select page 0*/
-	    {0x48,	NE_EN0_DCFG},	/* Set byte-wide (0x48) access. */
-	    {0x00,	NE_EN0_RCNTLO},	/* Clear the count regs. */
-	    {0x00,	NE_EN0_RCNTHI},
-	    {0x00,	NE_EN0_IMR},	/* Mask completion irq. */
-	    {0xFF,	NE_EN0_ISR},
-	    {E8390_RXOFF, NE_EN0_RXCR},	/* 0x20  Set to monitor */
-	    {E8390_TXOFF, NE_EN0_TXCR},	/* 0x02  and loopback mode. */
-	    {32,	NE_EN0_RCNTLO},
-	    {0x00,	NE_EN0_RCNTHI},
-	    {0x00,	NE_EN0_RSARLO},	/* DMA starting at 0x0000. */
-	    {0x00,	NE_EN0_RSARHI},
-	    {E8390_RREAD+E8390_START, NE_CMD},
-	};
-	for (i = 0; i < ARRAY_SIZE(program_seq); i++) {
-	    outb(program_seq[i].value, ioaddr + program_seq[i].offset);
-	}
-
-    }
-    for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
-	SA_prom[i] = inb(ioaddr + NE_DATAPORT);
-	SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
-	if (SA_prom[i] != SA_prom[i+1])
-	    wordlength = 1;
-    }
-
-    /*	At this point, wordlength *only* tells us if the SA_prom is doubled
-	up or not because some broken PCI cards don't respect the byte-wide
-	request in program_seq above, and hence don't have doubled up values.
-	These broken cards would otherwise be detected as an ne1000.  */
-
-    if (wordlength == 2)
-	for (i = 0; i < 16; i++)
-		SA_prom[i] = SA_prom[i+i];
-
-    if (wordlength == 2) {
-	/* We must set the 8390 for word mode. */
-	outb(0x49, ioaddr + NE_EN0_DCFG);
-	start_page = NESM_START_PG;
-	stop_page = NESM_STOP_PG;
-    } else {
-	start_page = NE1SM_START_PG;
-	stop_page = NE1SM_STOP_PG;
-    }
-
-    neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
-    ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
-
-    /* Set up the rest of the parameters. */
-    if (neX000) {
-	name = (wordlength == 2) ? "NE2000" : "NE1000";
-    } else if (ctron) {
-	name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
-	start_page = 0x01;
-	stop_page = (wordlength == 2) ? 0x40 : 0x20;
-    } else {
-	printk(" not found.\n");
-	return -ENXIO;
-
-    }
-
-#else
-    wordlength = 2;
-    /* We must set the 8390 for word mode. */
-    outb(0x49, ioaddr + NE_EN0_DCFG);
-    start_page = NESM_START_PG;
-    stop_page = NESM_STOP_PG;
-
-    SA_prom[0] = MANUAL_HWADDR0;
-    SA_prom[1] = MANUAL_HWADDR1;
-    SA_prom[2] = MANUAL_HWADDR2;
-    SA_prom[3] = MANUAL_HWADDR3;
-    SA_prom[4] = MANUAL_HWADDR4;
-    SA_prom[5] = MANUAL_HWADDR5;
-    name = "NE2000";
-#endif
-
-    dev->base_addr = ioaddr;
-    dev->irq = IRQ_AMIGA_PORTS;
-    dev->netdev_ops = &ei_netdev_ops;
-
-    /* Install the Interrupt handler */
-    i = request_irq(dev->irq, apne_interrupt, IRQF_SHARED, DRV_NAME, dev);
-    if (i) return i;
-
-    for(i = 0; i < ETHER_ADDR_LEN; i++)
-	dev->dev_addr[i] = SA_prom[i];
-
-    printk(" %pM\n", dev->dev_addr);
-
-    printk("%s: %s found.\n", dev->name, name);
-
-    ei_status.name = name;
-    ei_status.tx_start_page = start_page;
-    ei_status.stop_page = stop_page;
-    ei_status.word16 = (wordlength == 2);
-
-    ei_status.rx_start_page = start_page + TX_PAGES;
-
-    ei_status.reset_8390 = &apne_reset_8390;
-    ei_status.block_input = &apne_block_input;
-    ei_status.block_output = &apne_block_output;
-    ei_status.get_8390_hdr = &apne_get_8390_hdr;
-
-    NS8390_init(dev, 0);
-
-    pcmcia_ack_int(pcmcia_get_intreq());		/* ack PCMCIA int req */
-    pcmcia_enable_irq();
-
-    apne_owned = 1;
-
-    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. */
-static void
-apne_reset_8390(struct net_device *dev)
-{
-    unsigned long reset_start_time = jiffies;
-
-    init_pcmcia();
-
-    if (ei_debug > 1) printk("resetting the 8390 t=%ld...", jiffies);
-
-    outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
-    ei_status.txing = 0;
-    ei_status.dmaing = 0;
-
-    /* This check _should_not_ be necessary, omit eventually. */
-    while ((inb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0)
-	if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
-	    printk("%s: ne_reset_8390() did not complete.\n", dev->name);
-	    break;
-	}
-    outb(ENISR_RESET, NE_BASE + NE_EN0_ISR);	/* Ack intr. */
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
-   we don't need to be concerned with ring wrap as the header will be at
-   the start of a page, so we optimize accordingly. */
-
-static void
-apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-
-    int nic_base = dev->base_addr;
-    int cnt;
-    char *ptrc;
-    short *ptrs;
-
-    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-    if (ei_status.dmaing) {
-	printk("%s: DMAing conflict in ne_get_8390_hdr "
-	   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
-	   dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
-	return;
-    }
-
-    ei_status.dmaing |= 0x01;
-    outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-    outb(ENISR_RDC, nic_base + NE_EN0_ISR);
-    outb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
-    outb(0, nic_base + NE_EN0_RCNTHI);
-    outb(0, nic_base + NE_EN0_RSARLO);		/* On page boundary */
-    outb(ring_page, nic_base + NE_EN0_RSARHI);
-    outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
-    if (ei_status.word16) {
-        ptrs = (short*)hdr;
-        for(cnt = 0; cnt < (sizeof(struct e8390_pkt_hdr)>>1); cnt++)
-            *ptrs++ = inw(NE_BASE + NE_DATAPORT);
-    } else {
-        ptrc = (char*)hdr;
-        for(cnt = 0; cnt < sizeof(struct e8390_pkt_hdr); cnt++)
-            *ptrc++ = inb(NE_BASE + NE_DATAPORT);
-    }
-
-    outb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
-    ei_status.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 outb. */
-
-static void
-apne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-    int nic_base = dev->base_addr;
-    char *buf = skb->data;
-    char *ptrc;
-    short *ptrs;
-    int cnt;
-
-    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-    if (ei_status.dmaing) {
-	printk("%s: DMAing conflict in ne_block_input "
-	   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
-	   dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
-	return;
-    }
-    ei_status.dmaing |= 0x01;
-    outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-    outb(ENISR_RDC, nic_base + NE_EN0_ISR);
-    outb(count & 0xff, nic_base + NE_EN0_RCNTLO);
-    outb(count >> 8, nic_base + NE_EN0_RCNTHI);
-    outb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
-    outb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
-    outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-    if (ei_status.word16) {
-      ptrs = (short*)buf;
-      for (cnt = 0; cnt < (count>>1); cnt++)
-        *ptrs++ = inw(NE_BASE + NE_DATAPORT);
-      if (count & 0x01) {
-	buf[count-1] = inb(NE_BASE + NE_DATAPORT);
-      }
-    } else {
-      ptrc = (char*)buf;
-      for (cnt = 0; cnt < count; cnt++)
-        *ptrc++ = inb(NE_BASE + NE_DATAPORT);
-    }
-
-    outb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
-    ei_status.dmaing &= ~0x01;
-}
-
-static void
-apne_block_output(struct net_device *dev, int count,
-		const unsigned char *buf, const int start_page)
-{
-    int nic_base = NE_BASE;
-    unsigned long dma_start;
-    char *ptrc;
-    short *ptrs;
-    int cnt;
-
-    /* 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))
-      count++;
-
-    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-    if (ei_status.dmaing) {
-	printk("%s: DMAing conflict in ne_block_output."
-	   "[DMAstat:%d][irqlock:%d][intr:%d]\n",
-	   dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
-	return;
-    }
-    ei_status.dmaing |= 0x01;
-    /* We should already be in page 0, but to be safe... */
-    outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
-    outb(ENISR_RDC, nic_base + NE_EN0_ISR);
-
-   /* Now the normal output. */
-    outb(count & 0xff, nic_base + NE_EN0_RCNTLO);
-    outb(count >> 8,   nic_base + NE_EN0_RCNTHI);
-    outb(0x00, nic_base + NE_EN0_RSARLO);
-    outb(start_page, nic_base + NE_EN0_RSARHI);
-
-    outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
-    if (ei_status.word16) {
-        ptrs = (short*)buf;
-        for (cnt = 0; cnt < count>>1; cnt++)
-            outw(*ptrs++, NE_BASE+NE_DATAPORT);
-    } else {
-        ptrc = (char*)buf;
-        for (cnt = 0; cnt < count; cnt++)
-	    outb(*ptrc++, NE_BASE + NE_DATAPORT);
-    }
-
-    dma_start = jiffies;
-
-    while ((inb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
-	if (time_after(jiffies, dma_start + 2*HZ/100)) {	/* 20ms */
-		printk("%s: timeout waiting for Tx RDC.\n", dev->name);
-		apne_reset_8390(dev);
-		NS8390_init(dev,1);
-		break;
-	}
-
-    outb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
-    ei_status.dmaing &= ~0x01;
-}
-
-static irqreturn_t apne_interrupt(int irq, void *dev_id)
-{
-    unsigned char pcmcia_intreq;
-
-    if (!(gayle.inten & GAYLE_IRQ_IRQ))
-        return IRQ_NONE;
-
-    pcmcia_intreq = pcmcia_get_intreq();
-
-    if (!(pcmcia_intreq & GAYLE_IRQ_IRQ)) {
-        pcmcia_ack_int(pcmcia_intreq);
-        return IRQ_NONE;
-    }
-    if (ei_debug > 3)
-        printk("pcmcia intreq = %x\n", pcmcia_intreq);
-    pcmcia_disable_irq();			/* to get rid of the sti() within ei_interrupt */
-    ei_interrupt(irq, dev_id);
-    pcmcia_ack_int(pcmcia_get_intreq());
-    pcmcia_enable_irq();
-    return IRQ_HANDLED;
-}
-
-#ifdef MODULE
-static struct net_device *apne_dev;
-
-static int __init apne_module_init(void)
-{
-	apne_dev = apne_probe(-1);
-	if (IS_ERR(apne_dev))
-		return PTR_ERR(apne_dev);
-	return 0;
-}
-
-static void __exit apne_module_exit(void)
-{
-	unregister_netdev(apne_dev);
-
-	pcmcia_disable_irq();
-
-	free_irq(IRQ_AMIGA_PORTS, apne_dev);
-
-	pcmcia_reset();
-
-	release_region(IOBASE, 0x20);
-
-	free_netdev(apne_dev);
-}
-module_init(apne_module_init);
-module_exit(apne_module_exit);
-#endif
-
-static int init_pcmcia(void)
-{
-	u_char config;
-#ifndef MANUAL_CONFIG
-	u_char tuple[32];
-	int offset_len;
-#endif
-	u_long offset;
-
-	pcmcia_reset();
-	pcmcia_program_voltage(PCMCIA_0V);
-	pcmcia_access_speed(PCMCIA_SPEED_250NS);
-	pcmcia_write_enable();
-
-#ifdef MANUAL_CONFIG
-	config = MANUAL_CONFIG;
-#else
-	/* get and write config byte to enable IO port */
-
-	if (pcmcia_copy_tuple(CISTPL_CFTABLE_ENTRY, tuple, 32) < 3)
-		return 0;
-
-	config = tuple[2] & 0x3f;
-#endif
-#ifdef MANUAL_OFFSET
-	offset = MANUAL_OFFSET;
-#else
-	if (pcmcia_copy_tuple(CISTPL_CONFIG, tuple, 32) < 6)
-		return 0;
-
-	offset_len = (tuple[2] & 0x3) + 1;
-	offset = 0;
-	while(offset_len--) {
-		offset = (offset << 8) | tuple[4+offset_len];
-	}
-#endif
-
-	out_8(GAYLE_ATTRIBUTE+offset, config);
-
-	return 1;
-}
-
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/appletalk/cops.c linux-libre-3.2-gnu/drivers/net/appletalk/cops.c
--- linux-libre-3.1-gnu/drivers/net/appletalk/cops.c	2012-03-19 21:47:39.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/appletalk/cops.c	2012-03-19 21:50:29.000000000 -0400
@@ -263,7 +263,7 @@
 	.ndo_start_xmit   	= cops_send_packet,
 	.ndo_tx_timeout		= cops_timeout,
         .ndo_do_ioctl           = cops_ioctl,
-	.ndo_set_multicast_list = set_multicast_list,
+	.ndo_set_rx_mode	= set_multicast_list,
 };
 
 /*
diff -druN linux-libre-3.1-gnu/drivers/net/appletalk/ltpc.c linux-libre-3.2-gnu/drivers/net/appletalk/ltpc.c
--- linux-libre-3.1-gnu/drivers/net/appletalk/ltpc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/appletalk/ltpc.c	2012-01-04 18:55:44.000000000 -0500
@@ -1014,7 +1014,7 @@
 static const struct net_device_ops ltpc_netdev = {
 	.ndo_start_xmit		= ltpc_xmit,
 	.ndo_do_ioctl		= ltpc_ioctl,
-	.ndo_set_multicast_list = set_multicast_list,
+	.ndo_set_rx_mode	= set_multicast_list,
 };
 
 struct net_device * __init ltpc_probe(void)
diff -druN linux-libre-3.1-gnu/drivers/net/arcnet/com20020.c linux-libre-3.2-gnu/drivers/net/arcnet/com20020.c
--- linux-libre-3.1-gnu/drivers/net/arcnet/com20020.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arcnet/com20020.c	2012-01-04 18:55:44.000000000 -0500
@@ -154,7 +154,7 @@
 	.ndo_stop	= arcnet_close,
 	.ndo_start_xmit = arcnet_send_packet,
 	.ndo_tx_timeout = arcnet_timeout,
-	.ndo_set_multicast_list = com20020_set_mc_list,
+	.ndo_set_rx_mode = com20020_set_mc_list,
 };
 
 /* Set up the struct net_device associated with this card.  Called after
diff -druN linux-libre-3.1-gnu/drivers/net/arcnet/com20020_cs.c linux-libre-3.2-gnu/drivers/net/arcnet/com20020_cs.c
--- linux-libre-3.1-gnu/drivers/net/arcnet/com20020_cs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/arcnet/com20020_cs.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,349 @@
+/*
+ * Linux ARCnet driver - COM20020 PCMCIA support
+ * 
+ * Written 1994-1999 by Avery Pennarun,
+ *    based on an ISA version by David Woodhouse.
+ * Derived from ibmtr_cs.c by Steve Kipisz (pcmcia-cs 3.1.4)
+ *    which was derived from pcnet_cs.c by David Hinds.
+ * Some additional portions derived from skeleton.c by Donald Becker.
+ *
+ * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
+ *  for sponsoring the further development of this driver.
+ *
+ * **********************
+ *
+ * The original copyright of skeleton.c was as follows:
+ *
+ * skeleton.c Written 1993 by Donald Becker.
+ * Copyright 1993 United States Government as represented by the
+ * Director, National Security Agency.  This software may only be used
+ * and distributed according to the terms of the GNU General Public License as
+ * modified by SRC, incorporated herein by reference.
+ * 
+ * **********************
+ * Changes:
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/08/2000
+ * - reorganize kmallocs in com20020_attach, checking all for failure
+ *   and releasing the previous allocations if one fails
+ * **********************
+ * 
+ * For more details, see drivers/net/arcnet.c
+ *
+ * **********************
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/arcdevice.h>
+#include <linux/com20020.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#define VERSION "arcnet: COM20020 PCMCIA support loaded.\n"
+
+
+static void regdump(struct net_device *dev)
+{
+#ifdef DEBUG
+    int ioaddr = dev->base_addr;
+    int count;
+    
+    netdev_dbg(dev, "register dump:\n");
+    for (count = ioaddr; count < ioaddr + 16; count++)
+    {
+	if (!(count % 16))
+	    pr_cont("%04X:", count);
+	pr_cont(" %02X", inb(count));
+    }
+    pr_cont("\n");
+    
+    netdev_dbg(dev, "buffer0 dump:\n");
+	/* set up the address register */
+        count = 0;
+	outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI);
+	outb(count & 0xff, _ADDR_LO);
+    
+    for (count = 0; count < 256+32; count++)
+    {
+	if (!(count % 16))
+	    pr_cont("%04X:", count);
+	
+	/* copy the data */
+	pr_cont(" %02X", inb(_MEMDATA));
+    }
+    pr_cont("\n");
+#endif
+}
+
+
+
+/*====================================================================*/
+
+/* Parameters that can be set with 'insmod' */
+
+static int node;
+static int timeout = 3;
+static int backplane;
+static int clockp;
+static int clockm;
+
+module_param(node, int, 0);
+module_param(timeout, int, 0);
+module_param(backplane, int, 0);
+module_param(clockp, int, 0);
+module_param(clockm, int, 0);
+
+MODULE_LICENSE("GPL");
+
+/*====================================================================*/
+
+static int com20020_config(struct pcmcia_device *link);
+static void com20020_release(struct pcmcia_device *link);
+
+static void com20020_detach(struct pcmcia_device *p_dev);
+
+/*====================================================================*/
+
+typedef struct com20020_dev_t {
+    struct net_device       *dev;
+} com20020_dev_t;
+
+static int com20020_probe(struct pcmcia_device *p_dev)
+{
+    com20020_dev_t *info;
+    struct net_device *dev;
+    struct arcnet_local *lp;
+
+    dev_dbg(&p_dev->dev, "com20020_attach()\n");
+
+    /* Create new network device */
+    info = kzalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
+    if (!info)
+	goto fail_alloc_info;
+
+    dev = alloc_arcdev("");
+    if (!dev)
+	goto fail_alloc_dev;
+
+    lp = netdev_priv(dev);
+    lp->timeout = timeout;
+    lp->backplane = backplane;
+    lp->clockp = clockp;
+    lp->clockm = clockm & 3;
+    lp->hw.owner = THIS_MODULE;
+
+    /* fill in our module parameters as defaults */
+    dev->dev_addr[0] = node;
+
+    p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+    p_dev->resource[0]->end = 16;
+    p_dev->config_flags |= CONF_ENABLE_IRQ;
+
+    info->dev = dev;
+    p_dev->priv = info;
+
+    return com20020_config(p_dev);
+
+fail_alloc_dev:
+    kfree(info);
+fail_alloc_info:
+    return -ENOMEM;
+} /* com20020_attach */
+
+static void com20020_detach(struct pcmcia_device *link)
+{
+    struct com20020_dev_t *info = link->priv;
+    struct net_device *dev = info->dev;
+
+    dev_dbg(&link->dev, "detach...\n");
+
+    dev_dbg(&link->dev, "com20020_detach\n");
+
+    dev_dbg(&link->dev, "unregister...\n");
+
+    unregister_netdev(dev);
+
+    /*
+     * this is necessary because we register our IRQ separately
+     * from card services.
+     */
+    if (dev->irq)
+	    free_irq(dev->irq, dev);
+
+    com20020_release(link);
+
+    /* Unlink device structure, free bits */
+    dev_dbg(&link->dev, "unlinking...\n");
+    if (link->priv)
+    {
+	dev = info->dev;
+	if (dev)
+	{
+	    dev_dbg(&link->dev, "kfree...\n");
+	    free_netdev(dev);
+	}
+	dev_dbg(&link->dev, "kfree2...\n");
+	kfree(info);
+    }
+
+} /* com20020_detach */
+
+static int com20020_config(struct pcmcia_device *link)
+{
+    struct arcnet_local *lp;
+    com20020_dev_t *info;
+    struct net_device *dev;
+    int i, ret;
+    int ioaddr;
+
+    info = link->priv;
+    dev = info->dev;
+
+    dev_dbg(&link->dev, "config...\n");
+
+    dev_dbg(&link->dev, "com20020_config\n");
+
+    dev_dbg(&link->dev, "baseport1 is %Xh\n",
+	    (unsigned int) link->resource[0]->start);
+
+    i = -ENODEV;
+    link->io_lines = 16;
+
+    if (!link->resource[0]->start)
+    {
+	for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
+	{
+	    link->resource[0]->start = ioaddr;
+	    i = pcmcia_request_io(link);
+	    if (i == 0)
+		break;
+	}
+    }
+    else
+	i = pcmcia_request_io(link);
+    
+    if (i != 0)
+    {
+	dev_dbg(&link->dev, "requestIO failed totally!\n");
+	goto failed;
+    }
+	
+    ioaddr = dev->base_addr = link->resource[0]->start;
+    dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr);
+
+    dev_dbg(&link->dev, "request IRQ %d\n",
+	    link->irq);
+    if (!link->irq)
+    {
+	dev_dbg(&link->dev, "requestIRQ failed totally!\n");
+	goto failed;
+    }
+
+    dev->irq = link->irq;
+
+    ret = pcmcia_enable_device(link);
+    if (ret)
+	    goto failed;
+
+    if (com20020_check(dev))
+    {
+	regdump(dev);
+	goto failed;
+    }
+    
+    lp = netdev_priv(dev);
+    lp->card_name = "PCMCIA COM20020";
+    lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
+
+    SET_NETDEV_DEV(dev, &link->dev);
+
+    i = com20020_found(dev, 0);	/* calls register_netdev */
+    
+    if (i != 0) {
+	dev_notice(&link->dev,
+		   "com20020_found() failed\n");
+	goto failed;
+    }
+
+    netdev_dbg(dev, "port %#3lx, irq %d\n",
+	       dev->base_addr, dev->irq);
+    return 0;
+
+failed:
+    dev_dbg(&link->dev, "com20020_config failed...\n");
+    com20020_release(link);
+    return -ENODEV;
+} /* com20020_config */
+
+static void com20020_release(struct pcmcia_device *link)
+{
+	dev_dbg(&link->dev, "com20020_release\n");
+	pcmcia_disable_device(link);
+}
+
+static int com20020_suspend(struct pcmcia_device *link)
+{
+	com20020_dev_t *info = link->priv;
+	struct net_device *dev = info->dev;
+
+	if (link->open)
+		netif_device_detach(dev);
+
+	return 0;
+}
+
+static int com20020_resume(struct pcmcia_device *link)
+{
+	com20020_dev_t *info = link->priv;
+	struct net_device *dev = info->dev;
+
+	if (link->open) {
+		int ioaddr = dev->base_addr;
+		struct arcnet_local *lp = netdev_priv(dev);
+		ARCRESET;
+	}
+
+	return 0;
+}
+
+static const struct pcmcia_device_id com20020_ids[] = {
+	PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.",
+			"PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
+	PCMCIA_DEVICE_PROD_ID12("SoHard AG",
+			"SH ARC PCMCIA", 0xf8991729, 0x69dff0c7),
+	PCMCIA_DEVICE_NULL
+};
+MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
+
+static struct pcmcia_driver com20020_cs_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "com20020_cs",
+	.probe		= com20020_probe,
+	.remove		= com20020_detach,
+	.id_table	= com20020_ids,
+	.suspend	= com20020_suspend,
+	.resume		= com20020_resume,
+};
+
+static int __init init_com20020_cs(void)
+{
+	return pcmcia_register_driver(&com20020_cs_driver);
+}
+
+static void __exit exit_com20020_cs(void)
+{
+	pcmcia_unregister_driver(&com20020_cs_driver);
+}
+
+module_init(init_com20020_cs);
+module_exit(exit_com20020_cs);
diff -druN linux-libre-3.1-gnu/drivers/net/arcnet/Kconfig linux-libre-3.2-gnu/drivers/net/arcnet/Kconfig
--- linux-libre-3.1-gnu/drivers/net/arcnet/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arcnet/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -3,7 +3,7 @@
 #
 
 menuconfig ARCNET
-	depends on NETDEVICES && (ISA || PCI)
+	depends on NETDEVICES && (ISA || PCI || PCMCIA)
 	tristate "ARCnet support"
 	---help---
 	  If you have a network card of this type, say Y and check out the
@@ -123,4 +123,14 @@
 	tristate "Support for COM20020 on PCI"
 	depends on ARCNET_COM20020 && PCI
 
+config ARCNET_COM20020_CS
+	tristate "COM20020 ARCnet PCMCIA support"
+	depends on ARCNET_COM20020 && PCMCIA
+	help
+	  Say Y here if you intend to attach this type of ARCnet PCMCIA card
+	  to your computer.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called com20020_cs.  If unsure, say N.
+
 endif # ARCNET
diff -druN linux-libre-3.1-gnu/drivers/net/arcnet/Makefile linux-libre-3.2-gnu/drivers/net/arcnet/Makefile
--- linux-libre-3.1-gnu/drivers/net/arcnet/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arcnet/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -12,3 +12,4 @@
 obj-$(CONFIG_ARCNET_COM20020) += com20020.o
 obj-$(CONFIG_ARCNET_COM20020_ISA) += com20020-isa.o
 obj-$(CONFIG_ARCNET_COM20020_PCI) += com20020-pci.o
+obj-$(CONFIG_ARCNET_COM20020_CS) += com20020_cs.o
diff -druN linux-libre-3.1-gnu/drivers/net/ariadne.c linux-libre-3.2-gnu/drivers/net/ariadne.c
--- linux-libre-3.1-gnu/drivers/net/ariadne.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/ariadne.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,793 +0,0 @@
-/*
- *  Amiga Linux/m68k Ariadne Ethernet Driver
- *
- *  Â© Copyright 1995-2003 by Geert Uytterhoeven (geert@linux-m68k.org)
- *			     Peter De Schrijver (p2@mind.be)
- *
- *  ---------------------------------------------------------------------------
- *
- *  This program is based on
- *
- *	lance.c:	An AMD LANCE ethernet driver for linux.
- *			Written 1993-94 by Donald Becker.
- *
- *	Am79C960:	PCnet(tm)-ISA Single-Chip Ethernet Controller
- *			Advanced Micro Devices
- *			Publication #16907, Rev. B, Amendment/0, May 1994
- *
- *	MC68230:	Parallel Interface/Timer (PI/T)
- *			Motorola Semiconductors, December, 1983
- *
- *  ---------------------------------------------------------------------------
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of the Linux
- *  distribution for more details.
- *
- *  ---------------------------------------------------------------------------
- *
- *  The Ariadne is a Zorro-II board made by Village Tronic. It contains:
- *
- *	- an Am79C960 PCnet-ISA Single-Chip Ethernet Controller with both
- *	  10BASE-2 (thin coax) and 10BASE-T (UTP) connectors
- *
- *	- an MC68230 Parallel Interface/Timer configured as 2 parallel ports
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-/*#define DEBUG*/
-
-#include <linux/module.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/interrupt.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-#include <linux/zorro.h>
-#include <linux/bitops.h>
-
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-#include <asm/irq.h>
-
-#include "ariadne.h"
-
-#ifdef ARIADNE_DEBUG
-int ariadne_debug = ARIADNE_DEBUG;
-#else
-int ariadne_debug = 1;
-#endif
-
-/* Macros to Fix Endianness problems */
-
-/* Swap the Bytes in a WORD */
-#define swapw(x)	(((x >> 8) & 0x00ff) | ((x << 8) & 0xff00))
-/* Get the Low BYTE in a WORD */
-#define lowb(x)		(x & 0xff)
-/* Get the Swapped High WORD in a LONG */
-#define swhighw(x)	((((x) >> 8) & 0xff00) | (((x) >> 24) & 0x00ff))
-/* Get the Swapped Low WORD in a LONG */
-#define swloww(x)	((((x) << 8) & 0xff00) | (((x) >> 8) & 0x00ff))
-
-/* Transmit/Receive Ring Definitions */
-
-#define TX_RING_SIZE	5
-#define RX_RING_SIZE	16
-
-#define PKT_BUF_SIZE	1520
-
-/* Private Device Data */
-
-struct ariadne_private {
-	volatile struct TDRE *tx_ring[TX_RING_SIZE];
-	volatile struct RDRE *rx_ring[RX_RING_SIZE];
-	volatile u_short *tx_buff[TX_RING_SIZE];
-	volatile u_short *rx_buff[RX_RING_SIZE];
-	int cur_tx, cur_rx;		/* The next free ring entry */
-	int dirty_tx;			/* The ring entries to be free()ed */
-	char tx_full;
-};
-
-/* Structure Created in the Ariadne's RAM Buffer */
-
-struct lancedata {
-	struct TDRE tx_ring[TX_RING_SIZE];
-	struct RDRE rx_ring[RX_RING_SIZE];
-	u_short tx_buff[TX_RING_SIZE][PKT_BUF_SIZE / sizeof(u_short)];
-	u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE / sizeof(u_short)];
-};
-
-static void memcpyw(volatile u_short *dest, u_short *src, int len)
-{
-	while (len >= 2) {
-		*(dest++) = *(src++);
-		len -= 2;
-	}
-	if (len == 1)
-		*dest = (*(u_char *)src) << 8;
-}
-
-static void ariadne_init_ring(struct net_device *dev)
-{
-	struct ariadne_private *priv = netdev_priv(dev);
-	volatile struct lancedata *lancedata = (struct lancedata *)dev->mem_start;
-	int i;
-
-	netif_stop_queue(dev);
-
-	priv->tx_full = 0;
-	priv->cur_rx = priv->cur_tx = 0;
-	priv->dirty_tx = 0;
-
-	/* Set up TX Ring */
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		volatile struct TDRE *t = &lancedata->tx_ring[i];
-		t->TMD0 = swloww(ARIADNE_RAM +
-				 offsetof(struct lancedata, tx_buff[i]));
-		t->TMD1 = swhighw(ARIADNE_RAM +
-				  offsetof(struct lancedata, tx_buff[i])) |
-			TF_STP | TF_ENP;
-		t->TMD2 = swapw((u_short)-PKT_BUF_SIZE);
-		t->TMD3 = 0;
-		priv->tx_ring[i] = &lancedata->tx_ring[i];
-		priv->tx_buff[i] = lancedata->tx_buff[i];
-		netdev_dbg(dev, "TX Entry %2d at %p, Buf at %p\n",
-			   i, &lancedata->tx_ring[i], lancedata->tx_buff[i]);
-	}
-
-	/* Set up RX Ring */
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		volatile struct RDRE *r = &lancedata->rx_ring[i];
-		r->RMD0 = swloww(ARIADNE_RAM +
-				 offsetof(struct lancedata, rx_buff[i]));
-		r->RMD1 = swhighw(ARIADNE_RAM +
-				  offsetof(struct lancedata, rx_buff[i])) |
-			RF_OWN;
-		r->RMD2 = swapw((u_short)-PKT_BUF_SIZE);
-		r->RMD3 = 0x0000;
-		priv->rx_ring[i] = &lancedata->rx_ring[i];
-		priv->rx_buff[i] = lancedata->rx_buff[i];
-		netdev_dbg(dev, "RX Entry %2d at %p, Buf at %p\n",
-			   i, &lancedata->rx_ring[i], lancedata->rx_buff[i]);
-	}
-}
-
-static int ariadne_rx(struct net_device *dev)
-{
-	struct ariadne_private *priv = netdev_priv(dev);
-	int entry = priv->cur_rx % RX_RING_SIZE;
-	int i;
-
-	/* If we own the next entry, it's a new packet. Send it up */
-	while (!(lowb(priv->rx_ring[entry]->RMD1) & RF_OWN)) {
-		int status = lowb(priv->rx_ring[entry]->RMD1);
-
-		if (status != (RF_STP | RF_ENP)) {	/* There was an error */
-			/* There is a tricky error noted by
-			 * John Murphy <murf@perftech.com> to Russ Nelson:
-			 * Even with full-sized buffers it's possible for a
-			 * jabber packet to use two buffers, with only the
-			 * last correctly noting the error
-			 */
-			/* Only count a general error at the end of a packet */
-			if (status & RF_ENP)
-				dev->stats.rx_errors++;
-			if (status & RF_FRAM)
-				dev->stats.rx_frame_errors++;
-			if (status & RF_OFLO)
-				dev->stats.rx_over_errors++;
-			if (status & RF_CRC)
-				dev->stats.rx_crc_errors++;
-			if (status & RF_BUFF)
-				dev->stats.rx_fifo_errors++;
-			priv->rx_ring[entry]->RMD1 &= 0xff00 | RF_STP | RF_ENP;
-		} else {
-			/* Malloc up new buffer, compatible with net-3 */
-			short pkt_len = swapw(priv->rx_ring[entry]->RMD3);
-			struct sk_buff *skb;
-
-			skb = dev_alloc_skb(pkt_len + 2);
-			if (skb == NULL) {
-				netdev_warn(dev, "Memory squeeze, deferring packet\n");
-				for (i = 0; i < RX_RING_SIZE; i++)
-					if (lowb(priv->rx_ring[(entry + i) % RX_RING_SIZE]->RMD1) & RF_OWN)
-						break;
-
-				if (i > RX_RING_SIZE - 2) {
-					dev->stats.rx_dropped++;
-					priv->rx_ring[entry]->RMD1 |= RF_OWN;
-					priv->cur_rx++;
-				}
-				break;
-			}
-
-
-			skb_reserve(skb, 2);	/* 16 byte align */
-			skb_put(skb, pkt_len);	/* Make room */
-			skb_copy_to_linear_data(skb,
-						(const void *)priv->rx_buff[entry],
-						pkt_len);
-			skb->protocol = eth_type_trans(skb, dev);
-			netdev_dbg(dev, "RX pkt type 0x%04x from %pM to %pM data 0x%08x len %d\n",
-				   ((u_short *)skb->data)[6],
-				   skb->data + 6, skb->data,
-				   (int)skb->data, (int)skb->len);
-
-			netif_rx(skb);
-			dev->stats.rx_packets++;
-			dev->stats.rx_bytes += pkt_len;
-		}
-
-		priv->rx_ring[entry]->RMD1 |= RF_OWN;
-		entry = (++priv->cur_rx) % RX_RING_SIZE;
-	}
-
-	priv->cur_rx = priv->cur_rx % RX_RING_SIZE;
-
-	/* We should check that at least two ring entries are free.
-	 * If not, we should free one and mark stats->rx_dropped++
-	 */
-
-	return 0;
-}
-
-static irqreturn_t ariadne_interrupt(int irq, void *data)
-{
-	struct net_device *dev = (struct net_device *)data;
-	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
-	struct ariadne_private *priv;
-	int csr0, boguscnt;
-	int handled = 0;
-
-	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
-
-	if (!(lance->RDP & INTR))	/* Check if any interrupt has been */
-		return IRQ_NONE;	/* generated by the board */
-
-	priv = netdev_priv(dev);
-
-	boguscnt = 10;
-	while ((csr0 = lance->RDP) & (ERR | RINT | TINT) && --boguscnt >= 0) {
-		/* Acknowledge all of the current interrupt sources ASAP */
-		lance->RDP = csr0 & ~(INEA | TDMD | STOP | STRT | INIT);
-
-#ifdef DEBUG
-		if (ariadne_debug > 5) {
-			netdev_dbg(dev, "interrupt  csr0=%#02x new csr=%#02x [",
-				   csr0, lance->RDP);
-			if (csr0 & INTR)
-				pr_cont(" INTR");
-			if (csr0 & INEA)
-				pr_cont(" INEA");
-			if (csr0 & RXON)
-				pr_cont(" RXON");
-			if (csr0 & TXON)
-				pr_cont(" TXON");
-			if (csr0 & TDMD)
-				pr_cont(" TDMD");
-			if (csr0 & STOP)
-				pr_cont(" STOP");
-			if (csr0 & STRT)
-				pr_cont(" STRT");
-			if (csr0 & INIT)
-				pr_cont(" INIT");
-			if (csr0 & ERR)
-				pr_cont(" ERR");
-			if (csr0 & BABL)
-				pr_cont(" BABL");
-			if (csr0 & CERR)
-				pr_cont(" CERR");
-			if (csr0 & MISS)
-				pr_cont(" MISS");
-			if (csr0 & MERR)
-				pr_cont(" MERR");
-			if (csr0 & RINT)
-				pr_cont(" RINT");
-			if (csr0 & TINT)
-				pr_cont(" TINT");
-			if (csr0 & IDON)
-				pr_cont(" IDON");
-			pr_cont(" ]\n");
-		}
-#endif
-
-		if (csr0 & RINT) {	/* Rx interrupt */
-			handled = 1;
-			ariadne_rx(dev);
-		}
-
-		if (csr0 & TINT) {	/* Tx-done interrupt */
-			int dirty_tx = priv->dirty_tx;
-
-			handled = 1;
-			while (dirty_tx < priv->cur_tx) {
-				int entry = dirty_tx % TX_RING_SIZE;
-				int status = lowb(priv->tx_ring[entry]->TMD1);
-
-				if (status & TF_OWN)
-					break;	/* It still hasn't been Txed */
-
-				priv->tx_ring[entry]->TMD1 &= 0xff00;
-
-				if (status & TF_ERR) {
-					/* There was an major error, log it */
-					int err_status = priv->tx_ring[entry]->TMD3;
-					dev->stats.tx_errors++;
-					if (err_status & EF_RTRY)
-						dev->stats.tx_aborted_errors++;
-					if (err_status & EF_LCAR)
-						dev->stats.tx_carrier_errors++;
-					if (err_status & EF_LCOL)
-						dev->stats.tx_window_errors++;
-					if (err_status & EF_UFLO) {
-						/* Ackk!  On FIFO errors the Tx unit is turned off! */
-						dev->stats.tx_fifo_errors++;
-						/* Remove this verbosity later! */
-						netdev_err(dev, "Tx FIFO error! Status %04x\n",
-							   csr0);
-						/* Restart the chip */
-						lance->RDP = STRT;
-					}
-				} else {
-					if (status & (TF_MORE | TF_ONE))
-						dev->stats.collisions++;
-					dev->stats.tx_packets++;
-				}
-				dirty_tx++;
-			}
-
-#ifndef final_version
-			if (priv->cur_tx - dirty_tx >= TX_RING_SIZE) {
-				netdev_err(dev, "out-of-sync dirty pointer, %d vs. %d, full=%d\n",
-					   dirty_tx, priv->cur_tx,
-					   priv->tx_full);
-				dirty_tx += TX_RING_SIZE;
-			}
-#endif
-
-			if (priv->tx_full && netif_queue_stopped(dev) &&
-			    dirty_tx > priv->cur_tx - TX_RING_SIZE + 2) {
-				/* The ring is no longer full */
-				priv->tx_full = 0;
-				netif_wake_queue(dev);
-			}
-
-			priv->dirty_tx = dirty_tx;
-		}
-
-		/* Log misc errors */
-		if (csr0 & BABL) {
-			handled = 1;
-			dev->stats.tx_errors++;	/* Tx babble */
-		}
-		if (csr0 & MISS) {
-			handled = 1;
-			dev->stats.rx_errors++;	/* Missed a Rx frame */
-		}
-		if (csr0 & MERR) {
-			handled = 1;
-			netdev_err(dev, "Bus master arbitration failure, status %04x\n",
-				   csr0);
-			/* Restart the chip */
-			lance->RDP = STRT;
-		}
-	}
-
-	/* Clear any other interrupt, and set interrupt enable */
-	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
-	lance->RDP = INEA | BABL | CERR | MISS | MERR | IDON;
-
-	if (ariadne_debug > 4)
-		netdev_dbg(dev, "exiting interrupt, csr%d=%#04x\n",
-			   lance->RAP, lance->RDP);
-
-	return IRQ_RETVAL(handled);
-}
-
-static int ariadne_open(struct net_device *dev)
-{
-	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
-	u_short in;
-	u_long version;
-	int i;
-
-	/* Reset the LANCE */
-	in = lance->Reset;
-
-	/* Stop the LANCE */
-	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
-	lance->RDP = STOP;
-
-	/* Check the LANCE version */
-	lance->RAP = CSR88;		/* Chip ID */
-	version = swapw(lance->RDP);
-	lance->RAP = CSR89;		/* Chip ID */
-	version |= swapw(lance->RDP) << 16;
-	if ((version & 0x00000fff) != 0x00000003) {
-		pr_warn("Couldn't find AMD Ethernet Chip\n");
-		return -EAGAIN;
-	}
-	if ((version & 0x0ffff000) != 0x00003000) {
-		pr_warn("Couldn't find Am79C960 (Wrong part number = %ld)\n",
-		       (version & 0x0ffff000) >> 12);
-		return -EAGAIN;
-	}
-
-	netdev_dbg(dev, "Am79C960 (PCnet-ISA) Revision %ld\n",
-		   (version & 0xf0000000) >> 28);
-
-	ariadne_init_ring(dev);
-
-	/* Miscellaneous Stuff */
-	lance->RAP = CSR3;		/* Interrupt Masks and Deferral Control */
-	lance->RDP = 0x0000;
-	lance->RAP = CSR4;		/* Test and Features Control */
-	lance->RDP = DPOLL | APAD_XMT | MFCOM | RCVCCOM | TXSTRTM | JABM;
-
-	/* Set the Multicast Table */
-	lance->RAP = CSR8;		/* Logical Address Filter, LADRF[15:0] */
-	lance->RDP = 0x0000;
-	lance->RAP = CSR9;		/* Logical Address Filter, LADRF[31:16] */
-	lance->RDP = 0x0000;
-	lance->RAP = CSR10;		/* Logical Address Filter, LADRF[47:32] */
-	lance->RDP = 0x0000;
-	lance->RAP = CSR11;		/* Logical Address Filter, LADRF[63:48] */
-	lance->RDP = 0x0000;
-
-	/* Set the Ethernet Hardware Address */
-	lance->RAP = CSR12;		/* Physical Address Register, PADR[15:0] */
-	lance->RDP = ((u_short *)&dev->dev_addr[0])[0];
-	lance->RAP = CSR13;		/* Physical Address Register, PADR[31:16] */
-	lance->RDP = ((u_short *)&dev->dev_addr[0])[1];
-	lance->RAP = CSR14;		/* Physical Address Register, PADR[47:32] */
-	lance->RDP = ((u_short *)&dev->dev_addr[0])[2];
-
-	/* Set the Init Block Mode */
-	lance->RAP = CSR15;		/* Mode Register */
-	lance->RDP = 0x0000;
-
-	/* Set the Transmit Descriptor Ring Pointer */
-	lance->RAP = CSR30;		/* Base Address of Transmit Ring */
-	lance->RDP = swloww(ARIADNE_RAM + offsetof(struct lancedata, tx_ring));
-	lance->RAP = CSR31;		/* Base Address of transmit Ring */
-	lance->RDP = swhighw(ARIADNE_RAM + offsetof(struct lancedata, tx_ring));
-
-	/* Set the Receive Descriptor Ring Pointer */
-	lance->RAP = CSR24;		/* Base Address of Receive Ring */
-	lance->RDP = swloww(ARIADNE_RAM + offsetof(struct lancedata, rx_ring));
-	lance->RAP = CSR25;		/* Base Address of Receive Ring */
-	lance->RDP = swhighw(ARIADNE_RAM + offsetof(struct lancedata, rx_ring));
-
-	/* Set the Number of RX and TX Ring Entries */
-	lance->RAP = CSR76;		/* Receive Ring Length */
-	lance->RDP = swapw(((u_short)-RX_RING_SIZE));
-	lance->RAP = CSR78;		/* Transmit Ring Length */
-	lance->RDP = swapw(((u_short)-TX_RING_SIZE));
-
-	/* Enable Media Interface Port Auto Select (10BASE-2/10BASE-T) */
-	lance->RAP = ISACSR2;		/* Miscellaneous Configuration */
-	lance->IDP = ASEL;
-
-	/* LED Control */
-	lance->RAP = ISACSR5;		/* LED1 Status */
-	lance->IDP = PSE|XMTE;
-	lance->RAP = ISACSR6;	/* LED2 Status */
-	lance->IDP = PSE|COLE;
-	lance->RAP = ISACSR7;	/* LED3 Status */
-	lance->IDP = PSE|RCVE;
-
-	netif_start_queue(dev);
-
-	i = request_irq(IRQ_AMIGA_PORTS, ariadne_interrupt, IRQF_SHARED,
-			dev->name, dev);
-	if (i)
-		return i;
-
-	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
-	lance->RDP = INEA | STRT;
-
-	return 0;
-}
-
-static int ariadne_close(struct net_device *dev)
-{
-	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
-
-	netif_stop_queue(dev);
-
-	lance->RAP = CSR112;		/* Missed Frame Count */
-	dev->stats.rx_missed_errors = swapw(lance->RDP);
-	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
-
-	if (ariadne_debug > 1) {
-		netdev_dbg(dev, "Shutting down ethercard, status was %02x\n",
-			   lance->RDP);
-		netdev_dbg(dev, "%lu packets missed\n",
-			   dev->stats.rx_missed_errors);
-	}
-
-	/* We stop the LANCE here -- it occasionally polls memory if we don't */
-	lance->RDP = STOP;
-
-	free_irq(IRQ_AMIGA_PORTS, dev);
-
-	return 0;
-}
-
-static inline void ariadne_reset(struct net_device *dev)
-{
-	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
-
-	lance->RAP = CSR0;	/* PCnet-ISA Controller Status */
-	lance->RDP = STOP;
-	ariadne_init_ring(dev);
-	lance->RDP = INEA | STRT;
-	netif_start_queue(dev);
-}
-
-static void ariadne_tx_timeout(struct net_device *dev)
-{
-	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
-
-	netdev_err(dev, "transmit timed out, status %04x, resetting\n",
-		   lance->RDP);
-	ariadne_reset(dev);
-	netif_wake_queue(dev);
-}
-
-static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb,
-				      struct net_device *dev)
-{
-	struct ariadne_private *priv = netdev_priv(dev);
-	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
-	int entry;
-	unsigned long flags;
-	int len = skb->len;
-
-#if 0
-	if (ariadne_debug > 3) {
-		lance->RAP = CSR0;	/* PCnet-ISA Controller Status */
-		netdev_dbg(dev, "%s: csr0 %04x\n", __func__, lance->RDP);
-		lance->RDP = 0x0000;
-	}
-#endif
-
-	/* FIXME: is the 79C960 new enough to do its own padding right ? */
-	if (skb->len < ETH_ZLEN) {
-		if (skb_padto(skb, ETH_ZLEN))
-			return NETDEV_TX_OK;
-		len = ETH_ZLEN;
-	}
-
-	/* Fill in a Tx ring entry */
-
-	netdev_dbg(dev, "TX pkt type 0x%04x from %pM to %pM data 0x%08x len %d\n",
-		   ((u_short *)skb->data)[6],
-		   skb->data + 6, skb->data,
-		   (int)skb->data, (int)skb->len);
-
-	local_irq_save(flags);
-
-	entry = priv->cur_tx % TX_RING_SIZE;
-
-	/* Caution: the write order is important here, set the base address with
-	   the "ownership" bits last */
-
-	priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len);
-	priv->tx_ring[entry]->TMD3 = 0x0000;
-	memcpyw(priv->tx_buff[entry], (u_short *)skb->data, len);
-
-#ifdef DEBUG
-	print_hex_dump(KERN_DEBUG, "tx_buff: ", DUMP_PREFIX_OFFSET, 16, 1,
-		       (void *)priv->tx_buff[entry],
-		       skb->len > 64 ? 64 : skb->len, true);
-#endif
-
-	priv->tx_ring[entry]->TMD1 = (priv->tx_ring[entry]->TMD1 & 0xff00)
-		| TF_OWN | TF_STP | TF_ENP;
-
-	dev_kfree_skb(skb);
-
-	priv->cur_tx++;
-	if ((priv->cur_tx >= TX_RING_SIZE) &&
-	    (priv->dirty_tx >= TX_RING_SIZE)) {
-
-		netdev_dbg(dev, "*** Subtracting TX_RING_SIZE from cur_tx (%d) and dirty_tx (%d)\n",
-			   priv->cur_tx, priv->dirty_tx);
-
-		priv->cur_tx -= TX_RING_SIZE;
-		priv->dirty_tx -= TX_RING_SIZE;
-	}
-	dev->stats.tx_bytes += len;
-
-	/* Trigger an immediate send poll */
-	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
-	lance->RDP = INEA | TDMD;
-
-	if (lowb(priv->tx_ring[(entry + 1) % TX_RING_SIZE]->TMD1) != 0) {
-		netif_stop_queue(dev);
-		priv->tx_full = 1;
-	}
-	local_irq_restore(flags);
-
-	return NETDEV_TX_OK;
-}
-
-static struct net_device_stats *ariadne_get_stats(struct net_device *dev)
-{
-	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
-	short saved_addr;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	saved_addr = lance->RAP;
-	lance->RAP = CSR112;		/* Missed Frame Count */
-	dev->stats.rx_missed_errors = swapw(lance->RDP);
-	lance->RAP = saved_addr;
-	local_irq_restore(flags);
-
-	return &dev->stats;
-}
-
-/* Set or clear the multicast filter for this adaptor.
- * num_addrs == -1	Promiscuous mode, receive all packets
- * num_addrs == 0	Normal mode, clear multicast list
- * num_addrs > 0	Multicast mode, receive normal and MC packets,
- * 			and do best-effort filtering.
- */
-static void set_multicast_list(struct net_device *dev)
-{
-	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
-
-	if (!netif_running(dev))
-		return;
-
-	netif_stop_queue(dev);
-
-	/* We take the simple way out and always enable promiscuous mode */
-	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
-	lance->RDP = STOP;		/* Temporarily stop the lance */
-	ariadne_init_ring(dev);
-
-	if (dev->flags & IFF_PROMISC) {
-		lance->RAP = CSR15;	/* Mode Register */
-		lance->RDP = PROM;	/* Set promiscuous mode */
-	} else {
-		short multicast_table[4];
-		int num_addrs = netdev_mc_count(dev);
-		int i;
-		/* We don't use the multicast table,
-		 * but rely on upper-layer filtering
-		 */
-		memset(multicast_table, (num_addrs == 0) ? 0 : -1,
-		       sizeof(multicast_table));
-		for (i = 0; i < 4; i++) {
-			lance->RAP = CSR8 + (i << 8);
-					/* Logical Address Filter */
-			lance->RDP = swapw(multicast_table[i]);
-		}
-		lance->RAP = CSR15;	/* Mode Register */
-		lance->RDP = 0x0000;	/* Unset promiscuous mode */
-	}
-
-	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
-	lance->RDP = INEA | STRT | IDON;/* Resume normal operation */
-
-	netif_wake_queue(dev);
-}
-
-
-static void __devexit ariadne_remove_one(struct zorro_dev *z)
-{
-	struct net_device *dev = zorro_get_drvdata(z);
-
-	unregister_netdev(dev);
-	release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960));
-	release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE);
-	free_netdev(dev);
-}
-
-static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = {
-	{ ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl);
-
-static const struct net_device_ops ariadne_netdev_ops = {
-	.ndo_open		= ariadne_open,
-	.ndo_stop		= ariadne_close,
-	.ndo_start_xmit		= ariadne_start_xmit,
-	.ndo_tx_timeout		= ariadne_tx_timeout,
-	.ndo_get_stats		= ariadne_get_stats,
-	.ndo_set_multicast_list	= set_multicast_list,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address	= eth_mac_addr,
-};
-
-static int __devinit ariadne_init_one(struct zorro_dev *z,
-				      const struct zorro_device_id *ent)
-{
-	unsigned long board = z->resource.start;
-	unsigned long base_addr = board + ARIADNE_LANCE;
-	unsigned long mem_start = board + ARIADNE_RAM;
-	struct resource *r1, *r2;
-	struct net_device *dev;
-	struct ariadne_private *priv;
-	int err;
-
-	r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960");
-	if (!r1)
-		return -EBUSY;
-	r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM");
-	if (!r2) {
-		release_mem_region(base_addr, sizeof(struct Am79C960));
-		return -EBUSY;
-	}
-
-	dev = alloc_etherdev(sizeof(struct ariadne_private));
-	if (dev == NULL) {
-		release_mem_region(base_addr, sizeof(struct Am79C960));
-		release_mem_region(mem_start, ARIADNE_RAM_SIZE);
-		return -ENOMEM;
-	}
-
-	priv = netdev_priv(dev);
-
-	r1->name = dev->name;
-	r2->name = dev->name;
-
-	dev->dev_addr[0] = 0x00;
-	dev->dev_addr[1] = 0x60;
-	dev->dev_addr[2] = 0x30;
-	dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff;
-	dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff;
-	dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
-	dev->base_addr = ZTWO_VADDR(base_addr);
-	dev->mem_start = ZTWO_VADDR(mem_start);
-	dev->mem_end = dev->mem_start + ARIADNE_RAM_SIZE;
-
-	dev->netdev_ops = &ariadne_netdev_ops;
-	dev->watchdog_timeo = 5 * HZ;
-
-	err = register_netdev(dev);
-	if (err) {
-		release_mem_region(base_addr, sizeof(struct Am79C960));
-		release_mem_region(mem_start, ARIADNE_RAM_SIZE);
-		free_netdev(dev);
-		return err;
-	}
-	zorro_set_drvdata(z, dev);
-
-	netdev_info(dev, "Ariadne at 0x%08lx, Ethernet Address %pM\n",
-		    board, dev->dev_addr);
-
-	return 0;
-}
-
-static struct zorro_driver ariadne_driver = {
-	.name		= "ariadne",
-	.id_table	= ariadne_zorro_tbl,
-	.probe		= ariadne_init_one,
-	.remove		= __devexit_p(ariadne_remove_one),
-};
-
-static int __init ariadne_init_module(void)
-{
-	return zorro_register_driver(&ariadne_driver);
-}
-
-static void __exit ariadne_cleanup_module(void)
-{
-	zorro_unregister_driver(&ariadne_driver);
-}
-
-module_init(ariadne_init_module);
-module_exit(ariadne_cleanup_module);
-
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/ariadne.h linux-libre-3.2-gnu/drivers/net/ariadne.h
--- linux-libre-3.1-gnu/drivers/net/ariadne.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/ariadne.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,415 +0,0 @@
-/*
- *  Amiga Linux/m68k Ariadne Ethernet Driver
- *
- *  Â© Copyright 1995 by Geert Uytterhoeven (geert@linux-m68k.org)
- *			Peter De Schrijver
- *		       (Peter.DeSchrijver@linux.cc.kuleuven.ac.be)
- *
- *  ----------------------------------------------------------------------------------
- *
- *  This program is based on
- *
- *	lance.c:	An AMD LANCE ethernet driver for linux.
- *			Written 1993-94 by Donald Becker.
- *
- *	Am79C960:	PCnet(tm)-ISA Single-Chip Ethernet Controller
- *			Advanced Micro Devices
- *			Publication #16907, Rev. B, Amendment/0, May 1994
- *
- *	MC68230:	Parallel Interface/Timer (PI/T)
- *			Motorola Semiconductors, December, 1983
- *
- *  ----------------------------------------------------------------------------------
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of the Linux
- *  distribution for more details.
- *
- *  ----------------------------------------------------------------------------------
- *
- *  The Ariadne is a Zorro-II board made by Village Tronic. It contains:
- *
- *	- an Am79C960 PCnet-ISA Single-Chip Ethernet Controller with both
- *	  10BASE-2 (thin coax) and 10BASE-T (UTP) connectors
- *
- *	- an MC68230 Parallel Interface/Timer configured as 2 parallel ports
- */
-
-
-    /*
-     *	Am79C960 PCnet-ISA
-     */
-
-struct Am79C960 {
-    volatile u_short AddressPROM[8];
-				/* IEEE Address PROM (Unused in the Ariadne) */
-    volatile u_short RDP;	/* Register Data Port */
-    volatile u_short RAP;	/* Register Address Port */
-    volatile u_short Reset;	/* Reset Chip on Read Access */
-    volatile u_short IDP;	/* ISACSR Data Port */
-};
-
-
-    /*
-     *	Am79C960 Control and Status Registers
-     *
-     *	These values are already swap()ed!!
-     *
-     *	Only registers marked with a `-' are intended for network software
-     *	access
-     */
-
-#define CSR0		0x0000	/* - PCnet-ISA Controller Status */
-#define CSR1		0x0100	/* - IADR[15:0] */
-#define CSR2		0x0200	/* - IADR[23:16] */
-#define CSR3		0x0300	/* - Interrupt Masks and Deferral Control */
-#define CSR4		0x0400	/* - Test and Features Control */
-#define CSR6		0x0600	/*   RCV/XMT Descriptor Table Length */
-#define CSR8		0x0800	/* - Logical Address Filter, LADRF[15:0] */
-#define CSR9		0x0900	/* - Logical Address Filter, LADRF[31:16] */
-#define CSR10		0x0a00	/* - Logical Address Filter, LADRF[47:32] */
-#define CSR11		0x0b00	/* - Logical Address Filter, LADRF[63:48] */
-#define CSR12		0x0c00	/* - Physical Address Register, PADR[15:0] */
-#define CSR13		0x0d00	/* - Physical Address Register, PADR[31:16] */
-#define CSR14		0x0e00	/* - Physical Address Register, PADR[47:32] */
-#define CSR15		0x0f00	/* - Mode Register */
-#define CSR16		0x1000	/*   Initialization Block Address Lower */
-#define CSR17		0x1100	/*   Initialization Block Address Upper */
-#define CSR18		0x1200	/*   Current Receive Buffer Address */
-#define CSR19		0x1300	/*   Current Receive Buffer Address */
-#define CSR20		0x1400	/*   Current Transmit Buffer Address */
-#define CSR21		0x1500	/*   Current Transmit Buffer Address */
-#define CSR22		0x1600	/*   Next Receive Buffer Address */
-#define CSR23		0x1700	/*   Next Receive Buffer Address */
-#define CSR24		0x1800	/* - Base Address of Receive Ring */
-#define CSR25		0x1900	/* - Base Address of Receive Ring */
-#define CSR26		0x1a00	/*   Next Receive Descriptor Address */
-#define CSR27		0x1b00	/*   Next Receive Descriptor Address */
-#define CSR28		0x1c00	/*   Current Receive Descriptor Address */
-#define CSR29		0x1d00	/*   Current Receive Descriptor Address */
-#define CSR30		0x1e00	/* - Base Address of Transmit Ring */
-#define CSR31		0x1f00	/* - Base Address of transmit Ring */
-#define CSR32		0x2000	/*   Next Transmit Descriptor Address */
-#define CSR33		0x2100	/*   Next Transmit Descriptor Address */
-#define CSR34		0x2200	/*   Current Transmit Descriptor Address */
-#define CSR35		0x2300	/*   Current Transmit Descriptor Address */
-#define CSR36		0x2400	/*   Next Next Receive Descriptor Address */
-#define CSR37		0x2500	/*   Next Next Receive Descriptor Address */
-#define CSR38		0x2600	/*   Next Next Transmit Descriptor Address */
-#define CSR39		0x2700	/*   Next Next Transmit Descriptor Address */
-#define CSR40		0x2800	/*   Current Receive Status and Byte Count */
-#define CSR41		0x2900	/*   Current Receive Status and Byte Count */
-#define CSR42		0x2a00	/*   Current Transmit Status and Byte Count */
-#define CSR43		0x2b00	/*   Current Transmit Status and Byte Count */
-#define CSR44		0x2c00	/*   Next Receive Status and Byte Count */
-#define CSR45		0x2d00	/*   Next Receive Status and Byte Count */
-#define CSR46		0x2e00	/*   Poll Time Counter */
-#define CSR47		0x2f00	/*   Polling Interval */
-#define CSR48		0x3000	/*   Temporary Storage */
-#define CSR49		0x3100	/*   Temporary Storage */
-#define CSR50		0x3200	/*   Temporary Storage */
-#define CSR51		0x3300	/*   Temporary Storage */
-#define CSR52		0x3400	/*   Temporary Storage */
-#define CSR53		0x3500	/*   Temporary Storage */
-#define CSR54		0x3600	/*   Temporary Storage */
-#define CSR55		0x3700	/*   Temporary Storage */
-#define CSR56		0x3800	/*   Temporary Storage */
-#define CSR57		0x3900	/*   Temporary Storage */
-#define CSR58		0x3a00	/*   Temporary Storage */
-#define CSR59		0x3b00	/*   Temporary Storage */
-#define CSR60		0x3c00	/*   Previous Transmit Descriptor Address */
-#define CSR61		0x3d00	/*   Previous Transmit Descriptor Address */
-#define CSR62		0x3e00	/*   Previous Transmit Status and Byte Count */
-#define CSR63		0x3f00	/*   Previous Transmit Status and Byte Count */
-#define CSR64		0x4000	/*   Next Transmit Buffer Address */
-#define CSR65		0x4100	/*   Next Transmit Buffer Address */
-#define CSR66		0x4200	/*   Next Transmit Status and Byte Count */
-#define CSR67		0x4300	/*   Next Transmit Status and Byte Count */
-#define CSR68		0x4400	/*   Transmit Status Temporary Storage */
-#define CSR69		0x4500	/*   Transmit Status Temporary Storage */
-#define CSR70		0x4600	/*   Temporary Storage */
-#define CSR71		0x4700	/*   Temporary Storage */
-#define CSR72		0x4800	/*   Receive Ring Counter */
-#define CSR74		0x4a00	/*   Transmit Ring Counter */
-#define CSR76		0x4c00	/* - Receive Ring Length */
-#define CSR78		0x4e00	/* - Transmit Ring Length */
-#define CSR80		0x5000	/* - Burst and FIFO Threshold Control */
-#define CSR82		0x5200	/* - Bus Activity Timer */
-#define CSR84		0x5400	/*   DMA Address */
-#define CSR85		0x5500	/*   DMA Address */
-#define CSR86		0x5600	/*   Buffer Byte Counter */
-#define CSR88		0x5800	/* - Chip ID */
-#define CSR89		0x5900	/* - Chip ID */
-#define CSR92		0x5c00	/*   Ring Length Conversion */
-#define CSR94		0x5e00	/*   Transmit Time Domain Reflectometry Count */
-#define CSR96		0x6000	/*   Bus Interface Scratch Register 0 */
-#define CSR97		0x6100	/*   Bus Interface Scratch Register 0 */
-#define CSR98		0x6200	/*   Bus Interface Scratch Register 1 */
-#define CSR99		0x6300	/*   Bus Interface Scratch Register 1 */
-#define CSR104		0x6800	/*   SWAP */
-#define CSR105		0x6900	/*   SWAP */
-#define CSR108		0x6c00	/*   Buffer Management Scratch */
-#define CSR109		0x6d00	/*   Buffer Management Scratch */
-#define CSR112		0x7000	/* - Missed Frame Count */
-#define CSR114		0x7200	/* - Receive Collision Count */
-#define CSR124		0x7c00	/* - Buffer Management Unit Test */
-
-
-    /*
-     *	Am79C960 ISA Control and Status Registers
-     *
-     *	These values are already swap()ed!!
-     */
-
-#define ISACSR0		0x0000	/* Master Mode Read Active */
-#define ISACSR1		0x0100	/* Master Mode Write Active */
-#define ISACSR2		0x0200	/* Miscellaneous Configuration */
-#define ISACSR4		0x0400	/* LED0 Status (Link Integrity) */
-#define ISACSR5		0x0500	/* LED1 Status */
-#define ISACSR6		0x0600	/* LED2 Status */
-#define ISACSR7		0x0700	/* LED3 Status */
-
-
-    /*
-     *	Bit definitions for CSR0 (PCnet-ISA Controller Status)
-     *
-     *	These values are already swap()ed!!
-     */
-
-#define ERR		0x0080	/* Error */
-#define BABL		0x0040	/* Babble: Transmitted too many bits */
-#define CERR		0x0020	/* No Heartbeat (10BASE-T) */
-#define MISS		0x0010	/* Missed Frame */
-#define MERR		0x0008	/* Memory Error */
-#define RINT		0x0004	/* Receive Interrupt */
-#define TINT		0x0002	/* Transmit Interrupt */
-#define IDON		0x0001	/* Initialization Done */
-#define INTR		0x8000	/* Interrupt Flag */
-#define INEA		0x4000	/* Interrupt Enable */
-#define RXON		0x2000	/* Receive On */
-#define TXON		0x1000	/* Transmit On */
-#define TDMD		0x0800	/* Transmit Demand */
-#define STOP		0x0400	/* Stop */
-#define STRT		0x0200	/* Start */
-#define INIT		0x0100	/* Initialize */
-
-
-    /*
-     *	Bit definitions for CSR3 (Interrupt Masks and Deferral Control)
-     *
-     *	These values are already swap()ed!!
-     */
-
-#define BABLM		0x0040	/* Babble Mask */
-#define MISSM		0x0010	/* Missed Frame Mask */
-#define MERRM		0x0008	/* Memory Error Mask */
-#define RINTM		0x0004	/* Receive Interrupt Mask */
-#define TINTM		0x0002	/* Transmit Interrupt Mask */
-#define IDONM		0x0001	/* Initialization Done Mask */
-#define DXMT2PD		0x1000	/* Disable Transmit Two Part Deferral */
-#define EMBA		0x0800	/* Enable Modified Back-off Algorithm */
-
-
-    /*
-     *	Bit definitions for CSR4 (Test and Features Control)
-     *
-     *	These values are already swap()ed!!
-     */
-
-#define ENTST		0x0080	/* Enable Test Mode */
-#define DMAPLUS		0x0040	/* Disable Burst Transaction Counter */
-#define TIMER		0x0020	/* Timer Enable Register */
-#define DPOLL		0x0010	/* Disable Transmit Polling */
-#define APAD_XMT	0x0008	/* Auto Pad Transmit */
-#define ASTRP_RCV	0x0004	/* Auto Pad Stripping */
-#define MFCO		0x0002	/* Missed Frame Counter Overflow Interrupt */
-#define MFCOM		0x0001	/* Missed Frame Counter Overflow Mask */
-#define RCVCCO		0x2000	/* Receive Collision Counter Overflow Interrupt */
-#define RCVCCOM		0x1000	/* Receive Collision Counter Overflow Mask */
-#define TXSTRT		0x0800	/* Transmit Start Status */
-#define TXSTRTM		0x0400	/* Transmit Start Mask */
-#define JAB		0x0200	/* Jabber Error */
-#define JABM		0x0100	/* Jabber Error Mask */
-
-
-    /*
-     *	Bit definitions for CSR15 (Mode Register)
-     *
-     *	These values are already swap()ed!!
-     */
-
-#define PROM		0x0080	/* Promiscuous Mode */
-#define DRCVBC		0x0040	/* Disable Receive Broadcast */
-#define DRCVPA		0x0020	/* Disable Receive Physical Address */
-#define DLNKTST		0x0010	/* Disable Link Status */
-#define DAPC		0x0008	/* Disable Automatic Polarity Correction */
-#define MENDECL		0x0004	/* MENDEC Loopback Mode */
-#define LRTTSEL		0x0002	/* Low Receive Threshold/Transmit Mode Select */
-#define PORTSEL1	0x0001	/* Port Select Bits */
-#define PORTSEL2	0x8000	/* Port Select Bits */
-#define INTL		0x4000	/* Internal Loopback */
-#define DRTY		0x2000	/* Disable Retry */
-#define FCOLL		0x1000	/* Force Collision */
-#define DXMTFCS		0x0800	/* Disable Transmit CRC */
-#define LOOP		0x0400	/* Loopback Enable */
-#define DTX		0x0200	/* Disable Transmitter */
-#define DRX		0x0100	/* Disable Receiver */
-
-
-    /*
-     *	Bit definitions for ISACSR2 (Miscellaneous Configuration)
-     *
-     *	These values are already swap()ed!!
-     */
-
-#define ASEL		0x0200	/* Media Interface Port Auto Select */
-
-
-    /*
-     *	Bit definitions for ISACSR5-7 (LED1-3 Status)
-     *
-     *	These values are already swap()ed!!
-     */
-
-#define LEDOUT		0x0080	/* Current LED Status */
-#define PSE		0x8000	/* Pulse Stretcher Enable */
-#define XMTE		0x1000	/* Enable Transmit Status Signal */
-#define RVPOLE		0x0800	/* Enable Receive Polarity Signal */
-#define RCVE		0x0400	/* Enable Receive Status Signal */
-#define JABE		0x0200	/* Enable Jabber Signal */
-#define COLE		0x0100	/* Enable Collision Signal */
-
-
-    /*
-     *	Receive Descriptor Ring Entry
-     */
-
-struct RDRE {
-    volatile u_short RMD0;	/* LADR[15:0] */
-    volatile u_short RMD1;	/* HADR[23:16] | Receive Flags */
-    volatile u_short RMD2;	/* Buffer Byte Count (two's complement) */
-    volatile u_short RMD3;	/* Message Byte Count */
-};
-
-
-    /*
-     *	Transmit Descriptor Ring Entry
-     */
-
-struct TDRE {
-    volatile u_short TMD0;	/* LADR[15:0] */
-    volatile u_short TMD1;	/* HADR[23:16] | Transmit Flags */
-    volatile u_short TMD2;	/* Buffer Byte Count (two's complement) */
-    volatile u_short TMD3;	/* Error Flags */
-};
-
-
-    /*
-     *	Receive Flags
-     */
-
-#define RF_OWN		0x0080	/* PCnet-ISA controller owns the descriptor */
-#define RF_ERR		0x0040	/* Error */
-#define RF_FRAM		0x0020	/* Framing Error */
-#define RF_OFLO		0x0010	/* Overflow Error */
-#define RF_CRC		0x0008	/* CRC Error */
-#define RF_BUFF		0x0004	/* Buffer Error */
-#define RF_STP		0x0002	/* Start of Packet */
-#define RF_ENP		0x0001	/* End of Packet */
-
-
-    /*
-     *	Transmit Flags
-     */
-
-#define TF_OWN		0x0080	/* PCnet-ISA controller owns the descriptor */
-#define TF_ERR		0x0040	/* Error */
-#define TF_ADD_FCS	0x0020	/* Controls FCS Generation */
-#define TF_MORE		0x0010	/* More than one retry needed */
-#define TF_ONE		0x0008	/* One retry needed */
-#define TF_DEF		0x0004	/* Deferred */
-#define TF_STP		0x0002	/* Start of Packet */
-#define TF_ENP		0x0001	/* End of Packet */
-
-
-    /*
-     *	Error Flags
-     */
-
-#define EF_BUFF		0x0080	/* Buffer Error */
-#define EF_UFLO		0x0040	/* Underflow Error */
-#define EF_LCOL		0x0010	/* Late Collision */
-#define EF_LCAR		0x0008	/* Loss of Carrier */
-#define EF_RTRY		0x0004	/* Retry Error */
-#define EF_TDR		0xff03	/* Time Domain Reflectometry */
-
-
-
-    /*
-     *	MC68230 Parallel Interface/Timer
-     */
-
-struct MC68230 {
-    volatile u_char PGCR;	/* Port General Control Register */
-    u_char Pad1[1];
-    volatile u_char PSRR;	/* Port Service Request Register */
-    u_char Pad2[1];
-    volatile u_char PADDR;	/* Port A Data Direction Register */
-    u_char Pad3[1];
-    volatile u_char PBDDR;	/* Port B Data Direction Register */
-    u_char Pad4[1];
-    volatile u_char PCDDR;	/* Port C Data Direction Register */
-    u_char Pad5[1];
-    volatile u_char PIVR;	/* Port Interrupt Vector Register */
-    u_char Pad6[1];
-    volatile u_char PACR;	/* Port A Control Register */
-    u_char Pad7[1];
-    volatile u_char PBCR;	/* Port B Control Register */
-    u_char Pad8[1];
-    volatile u_char PADR;	/* Port A Data Register */
-    u_char Pad9[1];
-    volatile u_char PBDR;	/* Port B Data Register */
-    u_char Pad10[1];
-    volatile u_char PAAR;	/* Port A Alternate Register */
-    u_char Pad11[1];
-    volatile u_char PBAR;	/* Port B Alternate Register */
-    u_char Pad12[1];
-    volatile u_char PCDR;	/* Port C Data Register */
-    u_char Pad13[1];
-    volatile u_char PSR;	/* Port Status Register */
-    u_char Pad14[5];
-    volatile u_char TCR;	/* Timer Control Register */
-    u_char Pad15[1];
-    volatile u_char TIVR;	/* Timer Interrupt Vector Register */
-    u_char Pad16[3];
-    volatile u_char CPRH;	/* Counter Preload Register (High) */
-    u_char Pad17[1];
-    volatile u_char CPRM;	/* Counter Preload Register (Mid) */
-    u_char Pad18[1];
-    volatile u_char CPRL;	/* Counter Preload Register (Low) */
-    u_char Pad19[3];
-    volatile u_char CNTRH;	/* Count Register (High) */
-    u_char Pad20[1];
-    volatile u_char CNTRM;	/* Count Register (Mid) */
-    u_char Pad21[1];
-    volatile u_char CNTRL;	/* Count Register (Low) */
-    u_char Pad22[1];
-    volatile u_char TSR;	/* Timer Status Register */
-    u_char Pad23[11];
-};
-
-
-    /*
-     *	Ariadne Expansion Board Structure
-     */
-
-#define ARIADNE_LANCE		0x360
-
-#define ARIADNE_PIT		0x1000
-
-#define ARIADNE_BOOTPROM	0x4000	/* I guess it's here :-) */
-#define ARIADNE_BOOTPROM_SIZE	0x4000
-
-#define ARIADNE_RAM		0x8000	/* Always access WORDs!! */
-#define ARIADNE_RAM_SIZE	0x8000
-
diff -druN linux-libre-3.1-gnu/drivers/net/arm/am79c961a.c linux-libre-3.2-gnu/drivers/net/arm/am79c961a.c
--- linux-libre-3.1-gnu/drivers/net/arm/am79c961a.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arm/am79c961a.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,770 +0,0 @@
-/*
- *  linux/drivers/net/am79c961.c
- *
- *  by Russell King <rmk@arm.linux.org.uk> 1995-2001.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Derived from various things including skeleton.c
- *
- * This is a special driver for the am79c961A Lance chip used in the
- * Intel (formally Digital Equipment Corp) EBSA110 platform.  Please
- * note that this can not be built as a module (it doesn't make sense).
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/crc32.h>
-#include <linux/bitops.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/system.h>
-
-#define TX_BUFFERS 15
-#define RX_BUFFERS 25
-
-#include "am79c961a.h"
-
-static irqreturn_t
-am79c961_interrupt (int irq, void *dev_id);
-
-static unsigned int net_debug = NET_DEBUG;
-
-static const char version[] =
-	"am79c961 ethernet driver (C) 1995-2001 Russell King v0.04\n";
-
-/* --------------------------------------------------------------------------- */
-
-#ifdef __arm__
-static void write_rreg(u_long base, u_int reg, u_int val)
-{
-	asm volatile(
-	"str%?h	%1, [%2]	@ NET_RAP\n\t"
-	"str%?h	%0, [%2, #-4]	@ NET_RDP"
-	:
-	: "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
-}
-
-static inline unsigned short read_rreg(u_long base_addr, u_int reg)
-{
-	unsigned short v;
-	asm volatile(
-	"str%?h	%1, [%2]	@ NET_RAP\n\t"
-	"ldr%?h	%0, [%2, #-4]	@ NET_RDP"
-	: "=r" (v)
-	: "r" (reg), "r" (ISAIO_BASE + 0x0464));
-	return v;
-}
-
-static inline void write_ireg(u_long base, u_int reg, u_int val)
-{
-	asm volatile(
-	"str%?h	%1, [%2]	@ NET_RAP\n\t"
-	"str%?h	%0, [%2, #8]	@ NET_IDP"
-	:
-	: "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
-}
-
-static inline unsigned short read_ireg(u_long base_addr, u_int reg)
-{
-	u_short v;
-	asm volatile(
-	"str%?h	%1, [%2]	@ NAT_RAP\n\t"
-	"ldr%?h	%0, [%2, #8]	@ NET_IDP\n\t"
-	: "=r" (v)
-	: "r" (reg), "r" (ISAIO_BASE + 0x0464));
-	return v;
-}
-
-#define am_writeword(dev,off,val) __raw_writew(val, ISAMEM_BASE + ((off) << 1))
-#define am_readword(dev,off)      __raw_readw(ISAMEM_BASE + ((off) << 1))
-
-static void
-am_writebuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length)
-{
-	offset = ISAMEM_BASE + (offset << 1);
-	length = (length + 1) & ~1;
-	if ((int)buf & 2) {
-		asm volatile("str%?h	%2, [%0], #4"
-		 : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
-		buf += 2;
-		length -= 2;
-	}
-	while (length > 8) {
-		register unsigned int tmp asm("r2"), tmp2 asm("r3");
-		asm volatile(
-			"ldm%?ia	%0!, {%1, %2}"
-			: "+r" (buf), "=&r" (tmp), "=&r" (tmp2));
-		length -= 8;
-		asm volatile(
-			"str%?h	%1, [%0], #4\n\t"
-			"mov%?	%1, %1, lsr #16\n\t"
-			"str%?h	%1, [%0], #4\n\t"
-			"str%?h	%2, [%0], #4\n\t"
-			"mov%?	%2, %2, lsr #16\n\t"
-			"str%?h	%2, [%0], #4"
-		: "+r" (offset), "=&r" (tmp), "=&r" (tmp2));
-	}
-	while (length > 0) {
-		asm volatile("str%?h	%2, [%0], #4"
-		 : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
-		buf += 2;
-		length -= 2;
-	}
-}
-
-static void
-am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length)
-{
-	offset = ISAMEM_BASE + (offset << 1);
-	length = (length + 1) & ~1;
-	if ((int)buf & 2) {
-		unsigned int tmp;
-		asm volatile(
-			"ldr%?h	%2, [%0], #4\n\t"
-			"str%?b	%2, [%1], #1\n\t"
-			"mov%?	%2, %2, lsr #8\n\t"
-			"str%?b	%2, [%1], #1"
-		: "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
-		length -= 2;
-	}
-	while (length > 8) {
-		register unsigned int tmp asm("r2"), tmp2 asm("r3"), tmp3;
-		asm volatile(
-			"ldr%?h	%2, [%0], #4\n\t"
-			"ldr%?h	%4, [%0], #4\n\t"
-			"ldr%?h	%3, [%0], #4\n\t"
-			"orr%?	%2, %2, %4, lsl #16\n\t"
-			"ldr%?h	%4, [%0], #4\n\t"
-			"orr%?	%3, %3, %4, lsl #16\n\t"
-			"stm%?ia	%1!, {%2, %3}"
-		: "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
-		: "0" (offset), "1" (buf));
-		length -= 8;
-	}
-	while (length > 0) {
-		unsigned int tmp;
-		asm volatile(
-			"ldr%?h	%2, [%0], #4\n\t"
-			"str%?b	%2, [%1], #1\n\t"
-			"mov%?	%2, %2, lsr #8\n\t"
-			"str%?b	%2, [%1], #1"
-		: "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
-		length -= 2;
-	}
-}
-#else
-#error Not compatible
-#endif
-
-static int
-am79c961_ramtest(struct net_device *dev, unsigned int val)
-{
-	unsigned char *buffer = kmalloc (65536, GFP_KERNEL);
-	int i, error = 0, errorcount = 0;
-
-	if (!buffer)
-		return 0;
-	memset (buffer, val, 65536);
-	am_writebuffer(dev, 0, buffer, 65536);
-	memset (buffer, val ^ 255, 65536);
-	am_readbuffer(dev, 0, buffer, 65536);
-	for (i = 0; i < 65536; i++) {
-		if (buffer[i] != val && !error) {
-			printk ("%s: buffer error (%02X %02X) %05X - ", dev->name, val, buffer[i], i);
-			error = 1;
-			errorcount ++;
-		} else if (error && buffer[i] == val) {
-			printk ("%05X\n", i);
-			error = 0;
-		}
-	}
-	if (error)
-		printk ("10000\n");
-	kfree (buffer);
-	return errorcount;
-}
-
-static void am79c961_mc_hash(char *addr, u16 *hash)
-{
-	int idx, bit;
-	u32 crc;
-
-	crc = ether_crc_le(ETH_ALEN, addr);
-
-	idx = crc >> 30;
-	bit = (crc >> 26) & 15;
-
-	hash[idx] |= 1 << bit;
-}
-
-static unsigned int am79c961_get_rx_mode(struct net_device *dev, u16 *hash)
-{
-	unsigned int mode = MODE_PORT_10BT;
-
-	if (dev->flags & IFF_PROMISC) {
-		mode |= MODE_PROMISC;
-		memset(hash, 0xff, 4 * sizeof(*hash));
-	} else if (dev->flags & IFF_ALLMULTI) {
-		memset(hash, 0xff, 4 * sizeof(*hash));
-	} else {
-		struct netdev_hw_addr *ha;
-
-		memset(hash, 0, 4 * sizeof(*hash));
-
-		netdev_for_each_mc_addr(ha, dev)
-			am79c961_mc_hash(ha->addr, hash);
-	}
-
-	return mode;
-}
-
-static void
-am79c961_init_for_open(struct net_device *dev)
-{
-	struct dev_priv *priv = netdev_priv(dev);
-	unsigned long flags;
-	unsigned char *p;
-	u_int hdr_addr, first_free_addr;
-	u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash);
-	int i;
-
-	/*
-	 * Stop the chip.
-	 */
-	spin_lock_irqsave(&priv->chip_lock, flags);
-	write_rreg (dev->base_addr, CSR0, CSR0_BABL|CSR0_CERR|CSR0_MISS|CSR0_MERR|CSR0_TINT|CSR0_RINT|CSR0_STOP);
-	spin_unlock_irqrestore(&priv->chip_lock, flags);
-
-	write_ireg (dev->base_addr, 5, 0x00a0); /* Receive address LED */
-	write_ireg (dev->base_addr, 6, 0x0081); /* Collision LED */
-	write_ireg (dev->base_addr, 7, 0x0090); /* XMIT LED */
-	write_ireg (dev->base_addr, 2, 0x0000); /* MODE register selects media */
-
-	for (i = LADRL; i <= LADRH; i++)
-		write_rreg (dev->base_addr, i, multi_hash[i - LADRL]);
-
-	for (i = PADRL, p = dev->dev_addr; i <= PADRH; i++, p += 2)
-		write_rreg (dev->base_addr, i, p[0] | (p[1] << 8));
-
-	write_rreg (dev->base_addr, MODE, mode);
-	write_rreg (dev->base_addr, POLLINT, 0);
-	write_rreg (dev->base_addr, SIZERXR, -RX_BUFFERS);
-	write_rreg (dev->base_addr, SIZETXR, -TX_BUFFERS);
-
-	first_free_addr = RX_BUFFERS * 8 + TX_BUFFERS * 8 + 16;
-	hdr_addr = 0;
-
-	priv->rxhead = 0;
-	priv->rxtail = 0;
-	priv->rxhdr = hdr_addr;
-
-	for (i = 0; i < RX_BUFFERS; i++) {
-		priv->rxbuffer[i] = first_free_addr;
-		am_writeword (dev, hdr_addr, first_free_addr);
-		am_writeword (dev, hdr_addr + 2, RMD_OWN);
-		am_writeword (dev, hdr_addr + 4, (-1600));
-		am_writeword (dev, hdr_addr + 6, 0);
-		first_free_addr += 1600;
-		hdr_addr += 8;
-	}
-	priv->txhead = 0;
-	priv->txtail = 0;
-	priv->txhdr = hdr_addr;
-	for (i = 0; i < TX_BUFFERS; i++) {
-		priv->txbuffer[i] = first_free_addr;
-		am_writeword (dev, hdr_addr, first_free_addr);
-		am_writeword (dev, hdr_addr + 2, TMD_STP|TMD_ENP);
-		am_writeword (dev, hdr_addr + 4, 0xf000);
-		am_writeword (dev, hdr_addr + 6, 0);
-		first_free_addr += 1600;
-		hdr_addr += 8;
-	}
-
-	write_rreg (dev->base_addr, BASERXL, priv->rxhdr);
-	write_rreg (dev->base_addr, BASERXH, 0);
-	write_rreg (dev->base_addr, BASETXL, priv->txhdr);
-	write_rreg (dev->base_addr, BASERXH, 0);
-	write_rreg (dev->base_addr, CSR0, CSR0_STOP);
-	write_rreg (dev->base_addr, CSR3, CSR3_IDONM|CSR3_BABLM|CSR3_DXSUFLO);
-	write_rreg (dev->base_addr, CSR4, CSR4_APAD_XMIT|CSR4_MFCOM|CSR4_RCVCCOM|CSR4_TXSTRTM|CSR4_JABM);
-	write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT);
-}
-
-static void am79c961_timer(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *)data;
-	struct dev_priv *priv = netdev_priv(dev);
-	unsigned int lnkstat, carrier;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->chip_lock, flags);
-	lnkstat = read_ireg(dev->base_addr, ISALED0) & ISALED0_LNKST;
-	spin_unlock_irqrestore(&priv->chip_lock, flags);
-	carrier = netif_carrier_ok(dev);
-
-	if (lnkstat && !carrier) {
-		netif_carrier_on(dev);
-		printk("%s: link up\n", dev->name);
-	} else if (!lnkstat && carrier) {
-		netif_carrier_off(dev);
-		printk("%s: link down\n", dev->name);
-	}
-
-	mod_timer(&priv->timer, jiffies + msecs_to_jiffies(500));
-}
-
-/*
- * Open/initialize the board.
- */
-static int
-am79c961_open(struct net_device *dev)
-{
-	struct dev_priv *priv = netdev_priv(dev);
-	int ret;
-
-	ret = request_irq(dev->irq, am79c961_interrupt, 0, dev->name, dev);
-	if (ret)
-		return ret;
-
-	am79c961_init_for_open(dev);
-
-	netif_carrier_off(dev);
-
-	priv->timer.expires = jiffies;
-	add_timer(&priv->timer);
-
-	netif_start_queue(dev);
-
-	return 0;
-}
-
-/*
- * The inverse routine to am79c961_open().
- */
-static int
-am79c961_close(struct net_device *dev)
-{
-	struct dev_priv *priv = netdev_priv(dev);
-	unsigned long flags;
-
-	del_timer_sync(&priv->timer);
-
-	netif_stop_queue(dev);
-	netif_carrier_off(dev);
-
-	spin_lock_irqsave(&priv->chip_lock, flags);
-	write_rreg (dev->base_addr, CSR0, CSR0_STOP);
-	write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
-	spin_unlock_irqrestore(&priv->chip_lock, flags);
-
-	free_irq (dev->irq, dev);
-
-	return 0;
-}
-
-/*
- * Set or clear promiscuous/multicast mode filter for this adapter.
- */
-static void am79c961_setmulticastlist (struct net_device *dev)
-{
-	struct dev_priv *priv = netdev_priv(dev);
-	unsigned long flags;
-	u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash);
-	int i, stopped;
-
-	spin_lock_irqsave(&priv->chip_lock, flags);
-
-	stopped = read_rreg(dev->base_addr, CSR0) & CSR0_STOP;
-
-	if (!stopped) {
-		/*
-		 * Put the chip into suspend mode
-		 */
-		write_rreg(dev->base_addr, CTRL1, CTRL1_SPND);
-
-		/*
-		 * Spin waiting for chip to report suspend mode
-		 */
-		while ((read_rreg(dev->base_addr, CTRL1) & CTRL1_SPND) == 0) {
-			spin_unlock_irqrestore(&priv->chip_lock, flags);
-			nop();
-			spin_lock_irqsave(&priv->chip_lock, flags);
-		}
-	}
-
-	/*
-	 * Update the multicast hash table
-	 */
-	for (i = 0; i < ARRAY_SIZE(multi_hash); i++)
-		write_rreg(dev->base_addr, i + LADRL, multi_hash[i]);
-
-	/*
-	 * Write the mode register
-	 */
-	write_rreg(dev->base_addr, MODE, mode);
-
-	if (!stopped) {
-		/*
-		 * Put the chip back into running mode
-		 */
-		write_rreg(dev->base_addr, CTRL1, 0);
-	}
-
-	spin_unlock_irqrestore(&priv->chip_lock, flags);
-}
-
-static void am79c961_timeout(struct net_device *dev)
-{
-	printk(KERN_WARNING "%s: transmit timed out, network cable problem?\n",
-		dev->name);
-
-	/*
-	 * ought to do some setup of the tx side here
-	 */
-
-	netif_wake_queue(dev);
-}
-
-/*
- * Transmit a packet
- */
-static int
-am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev)
-{
-	struct dev_priv *priv = netdev_priv(dev);
-	unsigned int hdraddr, bufaddr;
-	unsigned int head;
-	unsigned long flags;
-
-	head = priv->txhead;
-	hdraddr = priv->txhdr + (head << 3);
-	bufaddr = priv->txbuffer[head];
-	head += 1;
-	if (head >= TX_BUFFERS)
-		head = 0;
-
-	am_writebuffer (dev, bufaddr, skb->data, skb->len);
-	am_writeword (dev, hdraddr + 4, -skb->len);
-	am_writeword (dev, hdraddr + 2, TMD_OWN|TMD_STP|TMD_ENP);
-	priv->txhead = head;
-
-	spin_lock_irqsave(&priv->chip_lock, flags);
-	write_rreg (dev->base_addr, CSR0, CSR0_TDMD|CSR0_IENA);
-	spin_unlock_irqrestore(&priv->chip_lock, flags);
-
-	/*
-	 * If the next packet is owned by the ethernet device,
-	 * then the tx ring is full and we can't add another
-	 * packet.
-	 */
-	if (am_readword(dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN)
-		netif_stop_queue(dev);
-
-	dev_kfree_skb(skb);
-
-	return NETDEV_TX_OK;
-}
-
-/*
- * If we have a good packet(s), get it/them out of the buffers.
- */
-static void
-am79c961_rx(struct net_device *dev, struct dev_priv *priv)
-{
-	do {
-		struct sk_buff *skb;
-		u_int hdraddr;
-		u_int pktaddr;
-		u_int status;
-		int len;
-
-		hdraddr = priv->rxhdr + (priv->rxtail << 3);
-		pktaddr = priv->rxbuffer[priv->rxtail];
-
-		status = am_readword (dev, hdraddr + 2);
-		if (status & RMD_OWN) /* do we own it? */
-			break;
-
-		priv->rxtail ++;
-		if (priv->rxtail >= RX_BUFFERS)
-			priv->rxtail = 0;
-
-		if ((status & (RMD_ERR|RMD_STP|RMD_ENP)) != (RMD_STP|RMD_ENP)) {
-			am_writeword (dev, hdraddr + 2, RMD_OWN);
-			dev->stats.rx_errors++;
-			if (status & RMD_ERR) {
-				if (status & RMD_FRAM)
-					dev->stats.rx_frame_errors++;
-				if (status & RMD_CRC)
-					dev->stats.rx_crc_errors++;
-			} else if (status & RMD_STP)
-				dev->stats.rx_length_errors++;
-			continue;
-		}
-
-		len = am_readword(dev, hdraddr + 6);
-		skb = dev_alloc_skb(len + 2);
-
-		if (skb) {
-			skb_reserve(skb, 2);
-
-			am_readbuffer(dev, pktaddr, skb_put(skb, len), len);
-			am_writeword(dev, hdraddr + 2, RMD_OWN);
-			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
-			dev->stats.rx_bytes += len;
-			dev->stats.rx_packets++;
-		} else {
-			am_writeword (dev, hdraddr + 2, RMD_OWN);
-			printk (KERN_WARNING "%s: memory squeeze, dropping packet.\n", dev->name);
-			dev->stats.rx_dropped++;
-			break;
-		}
-	} while (1);
-}
-
-/*
- * Update stats for the transmitted packet
- */
-static void
-am79c961_tx(struct net_device *dev, struct dev_priv *priv)
-{
-	do {
-		short len;
-		u_int hdraddr;
-		u_int status;
-
-		hdraddr = priv->txhdr + (priv->txtail << 3);
-		status = am_readword (dev, hdraddr + 2);
-		if (status & TMD_OWN)
-			break;
-
-		priv->txtail ++;
-		if (priv->txtail >= TX_BUFFERS)
-			priv->txtail = 0;
-
-		if (status & TMD_ERR) {
-			u_int status2;
-
-			dev->stats.tx_errors++;
-
-			status2 = am_readword (dev, hdraddr + 6);
-
-			/*
-			 * Clear the error byte
-			 */
-			am_writeword (dev, hdraddr + 6, 0);
-
-			if (status2 & TST_RTRY)
-				dev->stats.collisions += 16;
-			if (status2 & TST_LCOL)
-				dev->stats.tx_window_errors++;
-			if (status2 & TST_LCAR)
-				dev->stats.tx_carrier_errors++;
-			if (status2 & TST_UFLO)
-				dev->stats.tx_fifo_errors++;
-			continue;
-		}
-		dev->stats.tx_packets++;
-		len = am_readword (dev, hdraddr + 4);
-		dev->stats.tx_bytes += -len;
-	} while (priv->txtail != priv->txhead);
-
-	netif_wake_queue(dev);
-}
-
-static irqreturn_t
-am79c961_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = (struct net_device *)dev_id;
-	struct dev_priv *priv = netdev_priv(dev);
-	u_int status, n = 100;
-	int handled = 0;
-
-	do {
-		status = read_rreg(dev->base_addr, CSR0);
-		write_rreg(dev->base_addr, CSR0, status &
-			   (CSR0_IENA|CSR0_TINT|CSR0_RINT|
-			    CSR0_MERR|CSR0_MISS|CSR0_CERR|CSR0_BABL));
-
-		if (status & CSR0_RINT) {
-			handled = 1;
-			am79c961_rx(dev, priv);
-		}
-		if (status & CSR0_TINT) {
-			handled = 1;
-			am79c961_tx(dev, priv);
-		}
-		if (status & CSR0_MISS) {
-			handled = 1;
-			dev->stats.rx_dropped++;
-		}
-		if (status & CSR0_CERR) {
-			handled = 1;
-			mod_timer(&priv->timer, jiffies);
-		}
-	} while (--n && status & (CSR0_RINT | CSR0_TINT));
-
-	return IRQ_RETVAL(handled);
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void am79c961_poll_controller(struct net_device *dev)
-{
-	unsigned long flags;
-	local_irq_save(flags);
-	am79c961_interrupt(dev->irq, dev);
-	local_irq_restore(flags);
-}
-#endif
-
-/*
- * Initialise the chip.  Note that we always expect
- * to be entered with interrupts enabled.
- */
-static int
-am79c961_hw_init(struct net_device *dev)
-{
-	struct dev_priv *priv = netdev_priv(dev);
-
-	spin_lock_irq(&priv->chip_lock);
-	write_rreg (dev->base_addr, CSR0, CSR0_STOP);
-	write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
-	spin_unlock_irq(&priv->chip_lock);
-
-	am79c961_ramtest(dev, 0x66);
-	am79c961_ramtest(dev, 0x99);
-
-	return 0;
-}
-
-static void __init am79c961_banner(void)
-{
-	static unsigned version_printed;
-
-	if (net_debug && version_printed++ == 0)
-		printk(KERN_INFO "%s", version);
-}
-static const struct net_device_ops am79c961_netdev_ops = {
-	.ndo_open		= am79c961_open,
-	.ndo_stop		= am79c961_close,
-	.ndo_start_xmit		= am79c961_sendpacket,
-	.ndo_set_multicast_list	= am79c961_setmulticastlist,
-	.ndo_tx_timeout		= am79c961_timeout,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address	= eth_mac_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= am79c961_poll_controller,
-#endif
-};
-
-static int __devinit am79c961_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	struct net_device *dev;
-	struct dev_priv *priv;
-	int i, ret;
-
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!res)
-		return -ENODEV;
-
-	dev = alloc_etherdev(sizeof(struct dev_priv));
-	ret = -ENOMEM;
-	if (!dev)
-		goto out;
-
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-	priv = netdev_priv(dev);
-
-	/*
-	 * Fixed address and IRQ lines here.
-	 * The PNP initialisation should have been
-	 * done by the ether bootp loader.
-	 */
-	dev->base_addr = res->start;
-	ret = platform_get_irq(pdev, 0);
-
-	if (ret < 0) {
-		ret = -ENODEV;
-		goto nodev;
-	}
-	dev->irq = ret;
-
-	ret = -ENODEV;
-	if (!request_region(dev->base_addr, 0x18, dev->name))
-		goto nodev;
-
-	/*
-	 * Reset the device.
-	 */
-	inb(dev->base_addr + NET_RESET);
-	udelay(5);
-
-	/*
-	 * Check the manufacturer part of the
-	 * ether address.
-	 */
-	if (inb(dev->base_addr) != 0x08 ||
-	    inb(dev->base_addr + 2) != 0x00 ||
-	    inb(dev->base_addr + 4) != 0x2b)
-	    	goto release;
-
-	for (i = 0; i < 6; i++)
-		dev->dev_addr[i] = inb(dev->base_addr + i * 2) & 0xff;
-
-	am79c961_banner();
-
-	spin_lock_init(&priv->chip_lock);
-	init_timer(&priv->timer);
-	priv->timer.data = (unsigned long)dev;
-	priv->timer.function = am79c961_timer;
-
-	if (am79c961_hw_init(dev))
-		goto release;
-
-	dev->netdev_ops = &am79c961_netdev_ops;
-
-	ret = register_netdev(dev);
-	if (ret == 0) {
-		printk(KERN_INFO "%s: ether address %pM\n",
-		       dev->name, dev->dev_addr);
-		return 0;
-	}
-
-release:
-	release_region(dev->base_addr, 0x18);
-nodev:
-	free_netdev(dev);
-out:
-	return ret;
-}
-
-static struct platform_driver am79c961_driver = {
-	.probe		= am79c961_probe,
-	.driver		= {
-		.name	= "am79c961",
-	},
-};
-
-static int __init am79c961_init(void)
-{
-	return platform_driver_register(&am79c961_driver);
-}
-
-__initcall(am79c961_init);
diff -druN linux-libre-3.1-gnu/drivers/net/arm/am79c961a.h linux-libre-3.2-gnu/drivers/net/arm/am79c961a.h
--- linux-libre-3.1-gnu/drivers/net/arm/am79c961a.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arm/am79c961a.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,145 +0,0 @@
-/*
- * linux/drivers/net/arm/am79c961a.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 _LINUX_am79c961a_H
-#define _LINUX_am79c961a_H
-
-/* use 0 for production, 1 for verification, >2 for debug. debug flags: */
-#define DEBUG_TX	 2
-#define DEBUG_RX	 4
-#define DEBUG_INT	 8
-#define DEBUG_IC	16
-#ifndef NET_DEBUG
-#define NET_DEBUG 	0
-#endif
-
-#define NET_UID		0
-#define NET_RDP		0x10
-#define NET_RAP		0x12
-#define NET_RESET	0x14
-#define NET_IDP		0x16
-
-/*
- * RAP registers
- */
-#define CSR0		0
-#define CSR0_INIT	0x0001
-#define CSR0_STRT	0x0002
-#define CSR0_STOP	0x0004
-#define CSR0_TDMD	0x0008
-#define CSR0_TXON	0x0010
-#define CSR0_RXON	0x0020
-#define CSR0_IENA	0x0040
-#define CSR0_INTR	0x0080
-#define CSR0_IDON	0x0100
-#define CSR0_TINT	0x0200
-#define CSR0_RINT	0x0400
-#define CSR0_MERR	0x0800
-#define CSR0_MISS	0x1000
-#define CSR0_CERR	0x2000
-#define CSR0_BABL	0x4000
-#define CSR0_ERR	0x8000
-
-#define CSR3		3
-#define CSR3_EMBA	0x0008
-#define CSR3_DXMT2PD	0x0010
-#define CSR3_LAPPEN	0x0020
-#define CSR3_DXSUFLO	0x0040
-#define CSR3_IDONM	0x0100
-#define CSR3_TINTM	0x0200
-#define CSR3_RINTM	0x0400
-#define CSR3_MERRM	0x0800
-#define CSR3_MISSM	0x1000
-#define CSR3_BABLM	0x4000
-#define CSR3_MASKALL	0x5F00
-
-#define CSR4		4
-#define CSR4_JABM	0x0001
-#define CSR4_JAB	0x0002
-#define CSR4_TXSTRTM	0x0004
-#define CSR4_TXSTRT	0x0008
-#define CSR4_RCVCCOM	0x0010
-#define CSR4_RCVCCO	0x0020
-#define CSR4_MFCOM	0x0100
-#define CSR4_MFCO	0x0200
-#define CSR4_ASTRP_RCV	0x0400
-#define CSR4_APAD_XMIT	0x0800
-
-#define CTRL1		5
-#define CTRL1_SPND	0x0001
-
-#define LADRL		8
-#define LADRM1		9
-#define LADRM2		10
-#define LADRH		11
-#define PADRL		12
-#define PADRM		13
-#define PADRH		14
-
-#define MODE		15
-#define MODE_DISRX	0x0001
-#define MODE_DISTX	0x0002
-#define MODE_LOOP	0x0004
-#define MODE_DTCRC	0x0008
-#define MODE_COLL	0x0010
-#define MODE_DRETRY	0x0020
-#define MODE_INTLOOP	0x0040
-#define MODE_PORT_AUI	0x0000
-#define MODE_PORT_10BT	0x0080
-#define MODE_DRXPA	0x2000
-#define MODE_DRXBA	0x4000
-#define MODE_PROMISC	0x8000
-
-#define BASERXL		24
-#define BASERXH		25
-#define BASETXL		30
-#define BASETXH		31
-
-#define POLLINT		47
-
-#define SIZERXR		76
-#define SIZETXR		78
-
-#define CSR_MFC		112
-
-#define RMD_ENP		0x0100
-#define RMD_STP		0x0200
-#define RMD_CRC		0x0800
-#define RMD_FRAM	0x2000
-#define RMD_ERR		0x4000
-#define RMD_OWN		0x8000
-
-#define TMD_ENP		0x0100
-#define TMD_STP		0x0200
-#define TMD_MORE	0x1000
-#define TMD_ERR		0x4000
-#define TMD_OWN		0x8000
-
-#define TST_RTRY	0x0400
-#define TST_LCAR	0x0800
-#define TST_LCOL	0x1000
-#define TST_UFLO	0x4000
-#define TST_BUFF	0x8000
-
-#define ISALED0		0x0004
-#define ISALED0_LNKST	0x8000
-
-struct dev_priv {
-    unsigned long	rxbuffer[RX_BUFFERS];
-    unsigned long	txbuffer[TX_BUFFERS];
-    unsigned char	txhead;
-    unsigned char	txtail;
-    unsigned char	rxhead;
-    unsigned char	rxtail;
-    unsigned long	rxhdr;
-    unsigned long	txhdr;
-    spinlock_t		chip_lock;
-    struct timer_list	timer;
-};
-
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/arm/at91_ether.c linux-libre-3.2-gnu/drivers/net/arm/at91_ether.c
--- linux-libre-3.1-gnu/drivers/net/arm/at91_ether.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arm/at91_ether.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1254 +0,0 @@
-/*
- * Ethernet driver for the Atmel AT91RM9200 (Thunder)
- *
- *  Copyright (C) 2003 SAN People (Pty) Ltd
- *
- * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
- * Initial version by Rick Bronson 01/11/2003
- *
- * Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker
- *   (Polaroid Corporation)
- *
- * Realtek RTL8201(B)L PHY support by Roman Avramenko <roman@imsystems.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.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/mii.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/dma-mapping.h>
-#include <linux/ethtool.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/gfp.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/mach-types.h>
-
-#include <mach/at91rm9200_emac.h>
-#include <mach/gpio.h>
-#include <mach/board.h>
-
-#include "at91_ether.h"
-
-#define DRV_NAME	"at91_ether"
-#define DRV_VERSION	"1.0"
-
-#define LINK_POLL_INTERVAL	(HZ)
-
-/* ..................................................................... */
-
-/*
- * Read from a EMAC register.
- */
-static inline unsigned long at91_emac_read(unsigned int reg)
-{
-	void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC;
-
-	return __raw_readl(emac_base + reg);
-}
-
-/*
- * Write to a EMAC register.
- */
-static inline void at91_emac_write(unsigned int reg, unsigned long value)
-{
-	void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC;
-
-	__raw_writel(value, emac_base + reg);
-}
-
-/* ........................... PHY INTERFACE ........................... */
-
-/*
- * Enable the MDIO bit in MAC control register
- * When not called from an interrupt-handler, access to the PHY must be
- *  protected by a spinlock.
- */
-static void enable_mdi(void)
-{
-	unsigned long ctl;
-
-	ctl = at91_emac_read(AT91_EMAC_CTL);
-	at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_MPE);	/* enable management port */
-}
-
-/*
- * Disable the MDIO bit in the MAC control register
- */
-static void disable_mdi(void)
-{
-	unsigned long ctl;
-
-	ctl = at91_emac_read(AT91_EMAC_CTL);
-	at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE);	/* disable management port */
-}
-
-/*
- * Wait until the PHY operation is complete.
- */
-static inline void at91_phy_wait(void) {
-	unsigned long timeout = jiffies + 2;
-
-	while (!(at91_emac_read(AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) {
-		if (time_after(jiffies, timeout)) {
-			printk("at91_ether: MIO timeout\n");
-			break;
-		}
-		cpu_relax();
-	}
-}
-
-/*
- * Write value to the a PHY register
- * Note: MDI interface is assumed to already have been enabled.
- */
-static void write_phy(unsigned char phy_addr, unsigned char address, unsigned int value)
-{
-	at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W
-		| ((phy_addr & 0x1f) << 23) | (address << 18) | (value & AT91_EMAC_DATA));
-
-	/* Wait until IDLE bit in Network Status register is cleared */
-	at91_phy_wait();
-}
-
-/*
- * Read value stored in a PHY register.
- * Note: MDI interface is assumed to already have been enabled.
- */
-static void read_phy(unsigned char phy_addr, unsigned char address, unsigned int *value)
-{
-	at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R
-		| ((phy_addr & 0x1f) << 23) | (address << 18));
-
-	/* Wait until IDLE bit in Network Status register is cleared */
-	at91_phy_wait();
-
-	*value = at91_emac_read(AT91_EMAC_MAN) & AT91_EMAC_DATA;
-}
-
-/* ........................... PHY MANAGEMENT .......................... */
-
-/*
- * Access the PHY to determine the current link speed and mode, and update the
- * MAC accordingly.
- * If no link or auto-negotiation is busy, then no changes are made.
- */
-static void update_linkspeed(struct net_device *dev, int silent)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned int bmsr, bmcr, lpa, mac_cfg;
-	unsigned int speed, duplex;
-
-	if (!mii_link_ok(&lp->mii)) {		/* no link */
-		netif_carrier_off(dev);
-		if (!silent)
-			printk(KERN_INFO "%s: Link down.\n", dev->name);
-		return;
-	}
-
-	/* Link up, or auto-negotiation still in progress */
-	read_phy(lp->phy_address, MII_BMSR, &bmsr);
-	read_phy(lp->phy_address, MII_BMCR, &bmcr);
-	if (bmcr & BMCR_ANENABLE) {				/* AutoNegotiation is enabled */
-		if (!(bmsr & BMSR_ANEGCOMPLETE))
-			return;			/* Do nothing - another interrupt generated when negotiation complete */
-
-		read_phy(lp->phy_address, MII_LPA, &lpa);
-		if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100;
-		else speed = SPEED_10;
-		if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL;
-		else duplex = DUPLEX_HALF;
-	} else {
-		speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
-		duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
-	}
-
-	/* Update the MAC */
-	mac_cfg = at91_emac_read(AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD);
-	if (speed == SPEED_100) {
-		if (duplex == DUPLEX_FULL)		/* 100 Full Duplex */
-			mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD;
-		else					/* 100 Half Duplex */
-			mac_cfg |= AT91_EMAC_SPD;
-	} else {
-		if (duplex == DUPLEX_FULL)		/* 10 Full Duplex */
-			mac_cfg |= AT91_EMAC_FD;
-		else {}					/* 10 Half Duplex */
-	}
-	at91_emac_write(AT91_EMAC_CFG, mac_cfg);
-
-	if (!silent)
-		printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
-	netif_carrier_on(dev);
-}
-
-/*
- * Handle interrupts from the PHY
- */
-static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = (struct net_device *) dev_id;
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned int phy;
-
-	/*
-	 * This hander is triggered on both edges, but the PHY chips expect
-	 * level-triggering.  We therefore have to check if the PHY actually has
-	 * an IRQ pending.
-	 */
-	enable_mdi();
-	if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
-		read_phy(lp->phy_address, MII_DSINTR_REG, &phy);	/* ack interrupt in Davicom PHY */
-		if (!(phy & (1 << 0)))
-			goto done;
-	}
-	else if (lp->phy_type == MII_LXT971A_ID) {
-		read_phy(lp->phy_address, MII_ISINTS_REG, &phy);	/* ack interrupt in Intel PHY */
-		if (!(phy & (1 << 2)))
-			goto done;
-	}
-	else if (lp->phy_type == MII_BCM5221_ID) {
-		read_phy(lp->phy_address, MII_BCMINTR_REG, &phy);	/* ack interrupt in Broadcom PHY */
-		if (!(phy & (1 << 0)))
-			goto done;
-	}
-	else if (lp->phy_type == MII_KS8721_ID) {
-		read_phy(lp->phy_address, MII_TPISTATUS, &phy);		/* ack interrupt in Micrel PHY */
-		if (!(phy & ((1 << 2) | 1)))
-			goto done;
-	}
-	else if (lp->phy_type == MII_T78Q21x3_ID) {			/* ack interrupt in Teridian PHY */
-		read_phy(lp->phy_address, MII_T78Q21INT_REG, &phy);
-		if (!(phy & ((1 << 2) | 1)))
-			goto done;
-	}
-	else if (lp->phy_type == MII_DP83848_ID) {
-		read_phy(lp->phy_address, MII_DPPHYSTS_REG, &phy);	/* ack interrupt in DP83848 PHY */
-		if (!(phy & (1 << 7)))
-			goto done;
-	}
-
-	update_linkspeed(dev, 0);
-
-done:
-	disable_mdi();
-
-	return IRQ_HANDLED;
-}
-
-/*
- * Initialize and enable the PHY interrupt for link-state changes
- */
-static void enable_phyirq(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned int dsintr, irq_number;
-	int status;
-
-	irq_number = lp->board_data.phy_irq_pin;
-	if (!irq_number) {
-		/*
-		 * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L),
-		 * or board does not have it connected.
-		 */
-		mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
-		return;
-	}
-
-	status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev);
-	if (status) {
-		printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status);
-		return;
-	}
-
-	spin_lock_irq(&lp->lock);
-	enable_mdi();
-
-	if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {	/* for Davicom PHY */
-		read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr);
-		dsintr = dsintr & ~0xf00;		/* clear bits 8..11 */
-		write_phy(lp->phy_address, MII_DSINTR_REG, dsintr);
-	}
-	else if (lp->phy_type == MII_LXT971A_ID) {	/* for Intel PHY */
-		read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr);
-		dsintr = dsintr | 0xf2;			/* set bits 1, 4..7 */
-		write_phy(lp->phy_address, MII_ISINTE_REG, dsintr);
-	}
-	else if (lp->phy_type == MII_BCM5221_ID) {	/* for Broadcom PHY */
-		dsintr = (1 << 15) | ( 1 << 14);
-		write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr);
-	}
-	else if (lp->phy_type == MII_KS8721_ID) {	/* for Micrel PHY */
-		dsintr = (1 << 10) | ( 1 << 8);
-		write_phy(lp->phy_address, MII_TPISTATUS, dsintr);
-	}
-	else if (lp->phy_type == MII_T78Q21x3_ID) {	/* for Teridian PHY */
-		read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr);
-		dsintr = dsintr | 0x500;		/* set bits 8, 10 */
-		write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr);
-	}
-	else if (lp->phy_type == MII_DP83848_ID) {	/* National Semiconductor DP83848 PHY */
-		read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr);
-		dsintr = dsintr | 0x3c;			/* set bits 2..5 */
-		write_phy(lp->phy_address, MII_DPMISR_REG, dsintr);
-		read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr);
-		dsintr = dsintr | 0x3;			/* set bits 0,1 */
-		write_phy(lp->phy_address, MII_DPMICR_REG, dsintr);
-	}
-
-	disable_mdi();
-	spin_unlock_irq(&lp->lock);
-}
-
-/*
- * Disable the PHY interrupt
- */
-static void disable_phyirq(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned int dsintr;
-	unsigned int irq_number;
-
-	irq_number = lp->board_data.phy_irq_pin;
-	if (!irq_number) {
-		del_timer_sync(&lp->check_timer);
-		return;
-	}
-
-	spin_lock_irq(&lp->lock);
-	enable_mdi();
-
-	if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {	/* for Davicom PHY */
-		read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr);
-		dsintr = dsintr | 0xf00;			/* set bits 8..11 */
-		write_phy(lp->phy_address, MII_DSINTR_REG, dsintr);
-	}
-	else if (lp->phy_type == MII_LXT971A_ID) {	/* for Intel PHY */
-		read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr);
-		dsintr = dsintr & ~0xf2;			/* clear bits 1, 4..7 */
-		write_phy(lp->phy_address, MII_ISINTE_REG, dsintr);
-	}
-	else if (lp->phy_type == MII_BCM5221_ID) {	/* for Broadcom PHY */
-		read_phy(lp->phy_address, MII_BCMINTR_REG, &dsintr);
-		dsintr = ~(1 << 14);
-		write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr);
-	}
-	else if (lp->phy_type == MII_KS8721_ID) {	/* for Micrel PHY */
-		read_phy(lp->phy_address, MII_TPISTATUS, &dsintr);
-		dsintr = ~((1 << 10) | (1 << 8));
-		write_phy(lp->phy_address, MII_TPISTATUS, dsintr);
-	}
-	else if (lp->phy_type == MII_T78Q21x3_ID) {	/* for Teridian PHY */
-		read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr);
-		dsintr = dsintr & ~0x500;			/* clear bits 8, 10 */
-		write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr);
-	}
-	else if (lp->phy_type == MII_DP83848_ID) {	/* National Semiconductor DP83848 PHY */
-		read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr);
-		dsintr = dsintr & ~0x3;				/* clear bits 0, 1 */
-		write_phy(lp->phy_address, MII_DPMICR_REG, dsintr);
-		read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr);
-		dsintr = dsintr & ~0x3c;			/* clear bits 2..5 */
-		write_phy(lp->phy_address, MII_DPMISR_REG, dsintr);
-	}
-
-	disable_mdi();
-	spin_unlock_irq(&lp->lock);
-
-	free_irq(irq_number, dev);			/* Free interrupt handler */
-}
-
-/*
- * Perform a software reset of the PHY.
- */
-#if 0
-static void reset_phy(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned int bmcr;
-
-	spin_lock_irq(&lp->lock);
-	enable_mdi();
-
-	/* Perform PHY reset */
-	write_phy(lp->phy_address, MII_BMCR, BMCR_RESET);
-
-	/* Wait until PHY reset is complete */
-	do {
-		read_phy(lp->phy_address, MII_BMCR, &bmcr);
-	} while (!(bmcr & BMCR_RESET));
-
-	disable_mdi();
-	spin_unlock_irq(&lp->lock);
-}
-#endif
-
-static void at91ether_check_link(unsigned long dev_id)
-{
-	struct net_device *dev = (struct net_device *) dev_id;
-	struct at91_private *lp = netdev_priv(dev);
-
-	enable_mdi();
-	update_linkspeed(dev, 1);
-	disable_mdi();
-
-	mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
-}
-
-/* ......................... ADDRESS MANAGEMENT ........................ */
-
-/*
- * NOTE: Your bootloader must always set the MAC address correctly before
- * booting into Linux.
- *
- * - It must always set the MAC address after reset, even if it doesn't
- *   happen to access the Ethernet while it's booting.  Some versions of
- *   U-Boot on the AT91RM9200-DK do not do this.
- *
- * - Likewise it must store the addresses in the correct byte order.
- *   MicroMonitor (uMon) on the CSB337 does this incorrectly (and
- *   continues to do so, for bug-compatibility).
- */
-
-static short __init unpack_mac_address(struct net_device *dev, unsigned int hi, unsigned int lo)
-{
-	char addr[6];
-
-	if (machine_is_csb337()) {
-		addr[5] = (lo & 0xff);			/* The CSB337 bootloader stores the MAC the wrong-way around */
-		addr[4] = (lo & 0xff00) >> 8;
-		addr[3] = (lo & 0xff0000) >> 16;
-		addr[2] = (lo & 0xff000000) >> 24;
-		addr[1] = (hi & 0xff);
-		addr[0] = (hi & 0xff00) >> 8;
-	}
-	else {
-		addr[0] = (lo & 0xff);
-		addr[1] = (lo & 0xff00) >> 8;
-		addr[2] = (lo & 0xff0000) >> 16;
-		addr[3] = (lo & 0xff000000) >> 24;
-		addr[4] = (hi & 0xff);
-		addr[5] = (hi & 0xff00) >> 8;
-	}
-
-	if (is_valid_ether_addr(addr)) {
-		memcpy(dev->dev_addr, &addr, 6);
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * Set the ethernet MAC address in dev->dev_addr
- */
-static void __init get_mac_address(struct net_device *dev)
-{
-	/* Check Specific-Address 1 */
-	if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA1H), at91_emac_read(AT91_EMAC_SA1L)))
-		return;
-	/* Check Specific-Address 2 */
-	if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA2H), at91_emac_read(AT91_EMAC_SA2L)))
-		return;
-	/* Check Specific-Address 3 */
-	if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA3H), at91_emac_read(AT91_EMAC_SA3L)))
-		return;
-	/* Check Specific-Address 4 */
-	if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA4H), at91_emac_read(AT91_EMAC_SA4L)))
-		return;
-
-	printk(KERN_ERR "at91_ether: Your bootloader did not configure a MAC address.\n");
-}
-
-/*
- * Program the hardware MAC address from dev->dev_addr.
- */
-static void update_mac_address(struct net_device *dev)
-{
-	at91_emac_write(AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]));
-	at91_emac_write(AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4]));
-
-	at91_emac_write(AT91_EMAC_SA2L, 0);
-	at91_emac_write(AT91_EMAC_SA2H, 0);
-}
-
-/*
- * Store the new hardware address in dev->dev_addr, and update the MAC.
- */
-static int set_mac_address(struct net_device *dev, void* addr)
-{
-	struct sockaddr *address = addr;
-
-	if (!is_valid_ether_addr(address->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
-	update_mac_address(dev);
-
-	printk("%s: Setting MAC address to %pM\n", dev->name,
-	       dev->dev_addr);
-
-	return 0;
-}
-
-static int inline hash_bit_value(int bitnr, __u8 *addr)
-{
-	if (addr[bitnr / 8] & (1 << (bitnr % 8)))
-		return 1;
-	return 0;
-}
-
-/*
- * The hash address register is 64 bits long and takes up two locations in the memory map.
- * The least significant bits are stored in EMAC_HSL and the most significant
- * bits in EMAC_HSH.
- *
- * The unicast hash enable and the multicast hash enable bits in the network configuration
- *  register enable the reception of hash matched frames. The destination address is
- *  reduced to a 6 bit index into the 64 bit hash register using the following hash function.
- * The hash function is an exclusive or of every sixth bit of the destination address.
- *   hash_index[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47]
- *   hash_index[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46]
- *   hash_index[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45]
- *   hash_index[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44]
- *   hash_index[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43]
- *   hash_index[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42]
- * da[0] represents the least significant bit of the first byte received, that is, the multicast/
- *  unicast indicator, and da[47] represents the most significant bit of the last byte
- *  received.
- * If the hash index points to a bit that is set in the hash register then the frame will be
- *  matched according to whether the frame is multicast or unicast.
- * A multicast match will be signalled if the multicast hash enable bit is set, da[0] is 1 and
- *  the hash index points to a bit set in the hash register.
- * A unicast match will be signalled if the unicast hash enable bit is set, da[0] is 0 and the
- *  hash index points to a bit set in the hash register.
- * To receive all multicast frames, the hash register should be set with all ones and the
- *  multicast hash enable bit should be set in the network configuration register.
- */
-
-/*
- * Return the hash index value for the specified address.
- */
-static int hash_get_index(__u8 *addr)
-{
-	int i, j, bitval;
-	int hash_index = 0;
-
-	for (j = 0; j < 6; j++) {
-		for (i = 0, bitval = 0; i < 8; i++)
-			bitval ^= hash_bit_value(i*6 + j, addr);
-
-		hash_index |= (bitval << j);
-	}
-
-	return hash_index;
-}
-
-/*
- * Add multicast addresses to the internal multicast-hash table.
- */
-static void at91ether_sethashtable(struct net_device *dev)
-{
-	struct netdev_hw_addr *ha;
-	unsigned long mc_filter[2];
-	unsigned int bitnr;
-
-	mc_filter[0] = mc_filter[1] = 0;
-
-	netdev_for_each_mc_addr(ha, dev) {
-		bitnr = hash_get_index(ha->addr);
-		mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
-	}
-
-	at91_emac_write(AT91_EMAC_HSL, mc_filter[0]);
-	at91_emac_write(AT91_EMAC_HSH, mc_filter[1]);
-}
-
-/*
- * Enable/Disable promiscuous and multicast modes.
- */
-static void at91ether_set_multicast_list(struct net_device *dev)
-{
-	unsigned long cfg;
-
-	cfg = at91_emac_read(AT91_EMAC_CFG);
-
-	if (dev->flags & IFF_PROMISC)			/* Enable promiscuous mode */
-		cfg |= AT91_EMAC_CAF;
-	else if (dev->flags & (~IFF_PROMISC))		/* Disable promiscuous mode */
-		cfg &= ~AT91_EMAC_CAF;
-
-	if (dev->flags & IFF_ALLMULTI) {		/* Enable all multicast mode */
-		at91_emac_write(AT91_EMAC_HSH, -1);
-		at91_emac_write(AT91_EMAC_HSL, -1);
-		cfg |= AT91_EMAC_MTI;
-	} else if (!netdev_mc_empty(dev)) { /* Enable specific multicasts */
-		at91ether_sethashtable(dev);
-		cfg |= AT91_EMAC_MTI;
-	} else if (dev->flags & (~IFF_ALLMULTI)) {	/* Disable all multicast mode */
-		at91_emac_write(AT91_EMAC_HSH, 0);
-		at91_emac_write(AT91_EMAC_HSL, 0);
-		cfg &= ~AT91_EMAC_MTI;
-	}
-
-	at91_emac_write(AT91_EMAC_CFG, cfg);
-}
-
-/* ......................... ETHTOOL SUPPORT ........................... */
-
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
-	unsigned int value;
-
-	read_phy(phy_id, location, &value);
-	return value;
-}
-
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
-{
-	write_phy(phy_id, location, value);
-}
-
-static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	int ret;
-
-	spin_lock_irq(&lp->lock);
-	enable_mdi();
-
-	ret = mii_ethtool_gset(&lp->mii, cmd);
-
-	disable_mdi();
-	spin_unlock_irq(&lp->lock);
-
-	if (lp->phy_media == PORT_FIBRE) {		/* override media type since mii.c doesn't know */
-		cmd->supported = SUPPORTED_FIBRE;
-		cmd->port = PORT_FIBRE;
-	}
-
-	return ret;
-}
-
-static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	int ret;
-
-	spin_lock_irq(&lp->lock);
-	enable_mdi();
-
-	ret = mii_ethtool_sset(&lp->mii, cmd);
-
-	disable_mdi();
-	spin_unlock_irq(&lp->lock);
-
-	return ret;
-}
-
-static int at91ether_nwayreset(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	int ret;
-
-	spin_lock_irq(&lp->lock);
-	enable_mdi();
-
-	ret = mii_nway_restart(&lp->mii);
-
-	disable_mdi();
-	spin_unlock_irq(&lp->lock);
-
-	return ret;
-}
-
-static void at91ether_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-	strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info));
-}
-
-static const struct ethtool_ops at91ether_ethtool_ops = {
-	.get_settings	= at91ether_get_settings,
-	.set_settings	= at91ether_set_settings,
-	.get_drvinfo	= at91ether_get_drvinfo,
-	.nway_reset	= at91ether_nwayreset,
-	.get_link	= ethtool_op_get_link,
-};
-
-static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	int res;
-
-	if (!netif_running(dev))
-		return -EINVAL;
-
-	spin_lock_irq(&lp->lock);
-	enable_mdi();
-	res = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL);
-	disable_mdi();
-	spin_unlock_irq(&lp->lock);
-
-	return res;
-}
-
-/* ................................ MAC ................................ */
-
-/*
- * Initialize and start the Receiver and Transmit subsystems
- */
-static void at91ether_start(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	struct recv_desc_bufs *dlist, *dlist_phys;
-	int i;
-	unsigned long ctl;
-
-	dlist = lp->dlist;
-	dlist_phys = lp->dlist_phys;
-
-	for (i = 0; i < MAX_RX_DESCR; i++) {
-		dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0];
-		dlist->descriptors[i].size = 0;
-	}
-
-	/* Set the Wrap bit on the last descriptor */
-	dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP;
-
-	/* Reset buffer index */
-	lp->rxBuffIndex = 0;
-
-	/* Program address of descriptor list in Rx Buffer Queue register */
-	at91_emac_write(AT91_EMAC_RBQP, (unsigned long) dlist_phys);
-
-	/* Enable Receive and Transmit */
-	ctl = at91_emac_read(AT91_EMAC_CTL);
-	at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE);
-}
-
-/*
- * Open the ethernet interface
- */
-static int at91ether_open(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned long ctl;
-
-	if (!is_valid_ether_addr(dev->dev_addr))
-		return -EADDRNOTAVAIL;
-
-	clk_enable(lp->ether_clk);		/* Re-enable Peripheral clock */
-
-	/* Clear internal statistics */
-	ctl = at91_emac_read(AT91_EMAC_CTL);
-	at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_CSR);
-
-	/* Update the MAC address (incase user has changed it) */
-	update_mac_address(dev);
-
-	/* Enable PHY interrupt */
-	enable_phyirq(dev);
-
-	/* Enable MAC interrupts */
-	at91_emac_write(AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA
-				| AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
-				| AT91_EMAC_ROVR | AT91_EMAC_ABT);
-
-	/* Determine current link speed */
-	spin_lock_irq(&lp->lock);
-	enable_mdi();
-	update_linkspeed(dev, 0);
-	disable_mdi();
-	spin_unlock_irq(&lp->lock);
-
-	at91ether_start(dev);
-	netif_start_queue(dev);
-	return 0;
-}
-
-/*
- * Close the interface
- */
-static int at91ether_close(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned long ctl;
-
-	/* Disable Receiver and Transmitter */
-	ctl = at91_emac_read(AT91_EMAC_CTL);
-	at91_emac_write(AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE));
-
-	/* Disable PHY interrupt */
-	disable_phyirq(dev);
-
-	/* Disable MAC interrupts */
-	at91_emac_write(AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA
-				| AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
-				| AT91_EMAC_ROVR | AT91_EMAC_ABT);
-
-	netif_stop_queue(dev);
-
-	clk_disable(lp->ether_clk);		/* Disable Peripheral clock */
-
-	return 0;
-}
-
-/*
- * Transmit packet.
- */
-static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-
-	if (at91_emac_read(AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) {
-		netif_stop_queue(dev);
-
-		/* Store packet information (to free when Tx completed) */
-		lp->skb = skb;
-		lp->skb_length = skb->len;
-		lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE);
-		dev->stats.tx_bytes += skb->len;
-
-		/* Set address of the data in the Transmit Address register */
-		at91_emac_write(AT91_EMAC_TAR, lp->skb_physaddr);
-		/* Set length of the packet in the Transmit Control register */
-		at91_emac_write(AT91_EMAC_TCR, skb->len);
-
-	} else {
-		printk(KERN_ERR "at91_ether.c: at91ether_start_xmit() called, but device is busy!\n");
-		return NETDEV_TX_BUSY;	/* if we return anything but zero, dev.c:1055 calls kfree_skb(skb)
-				on this skb, he also reports -ENETDOWN and printk's, so either
-				we free and return(0) or don't free and return 1 */
-	}
-
-	return NETDEV_TX_OK;
-}
-
-/*
- * Update the current statistics from the internal statistics registers.
- */
-static struct net_device_stats *at91ether_stats(struct net_device *dev)
-{
-	int ale, lenerr, seqe, lcol, ecol;
-
-	if (netif_running(dev)) {
-		dev->stats.rx_packets += at91_emac_read(AT91_EMAC_OK);		/* Good frames received */
-		ale = at91_emac_read(AT91_EMAC_ALE);
-		dev->stats.rx_frame_errors += ale;				/* Alignment errors */
-		lenerr = at91_emac_read(AT91_EMAC_ELR) + at91_emac_read(AT91_EMAC_USF);
-		dev->stats.rx_length_errors += lenerr;				/* Excessive Length or Undersize Frame error */
-		seqe = at91_emac_read(AT91_EMAC_SEQE);
-		dev->stats.rx_crc_errors += seqe;				/* CRC error */
-		dev->stats.rx_fifo_errors += at91_emac_read(AT91_EMAC_DRFC);	/* Receive buffer not available */
-		dev->stats.rx_errors += (ale + lenerr + seqe
-			+ at91_emac_read(AT91_EMAC_CDE) + at91_emac_read(AT91_EMAC_RJB));
-
-		dev->stats.tx_packets += at91_emac_read(AT91_EMAC_FRA);		/* Frames successfully transmitted */
-		dev->stats.tx_fifo_errors += at91_emac_read(AT91_EMAC_TUE);	/* Transmit FIFO underruns */
-		dev->stats.tx_carrier_errors += at91_emac_read(AT91_EMAC_CSE);	/* Carrier Sense errors */
-		dev->stats.tx_heartbeat_errors += at91_emac_read(AT91_EMAC_SQEE);/* Heartbeat error */
-
-		lcol = at91_emac_read(AT91_EMAC_LCOL);
-		ecol = at91_emac_read(AT91_EMAC_ECOL);
-		dev->stats.tx_window_errors += lcol;			/* Late collisions */
-		dev->stats.tx_aborted_errors += ecol;			/* 16 collisions */
-
-		dev->stats.collisions += (at91_emac_read(AT91_EMAC_SCOL) + at91_emac_read(AT91_EMAC_MCOL) + lcol + ecol);
-	}
-	return &dev->stats;
-}
-
-/*
- * Extract received frame from buffer descriptors and sent to upper layers.
- * (Called from interrupt context)
- */
-static void at91ether_rx(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	struct recv_desc_bufs *dlist;
-	unsigned char *p_recv;
-	struct sk_buff *skb;
-	unsigned int pktlen;
-
-	dlist = lp->dlist;
-	while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) {
-		p_recv = dlist->recv_buf[lp->rxBuffIndex];
-		pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff;	/* Length of frame including FCS */
-		skb = dev_alloc_skb(pktlen + 2);
-		if (skb != NULL) {
-			skb_reserve(skb, 2);
-			memcpy(skb_put(skb, pktlen), p_recv, pktlen);
-
-			skb->protocol = eth_type_trans(skb, dev);
-			dev->stats.rx_bytes += pktlen;
-			netif_rx(skb);
-		}
-		else {
-			dev->stats.rx_dropped += 1;
-			printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
-		}
-
-		if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST)
-			dev->stats.multicast++;
-
-		dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE;	/* reset ownership bit */
-		if (lp->rxBuffIndex == MAX_RX_DESCR-1)				/* wrap after last buffer */
-			lp->rxBuffIndex = 0;
-		else
-			lp->rxBuffIndex++;
-	}
-}
-
-/*
- * MAC interrupt handler
- */
-static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = (struct net_device *) dev_id;
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned long intstatus, ctl;
-
-	/* MAC Interrupt Status register indicates what interrupts are pending.
-	   It is automatically cleared once read. */
-	intstatus = at91_emac_read(AT91_EMAC_ISR);
-
-	if (intstatus & AT91_EMAC_RCOM)		/* Receive complete */
-		at91ether_rx(dev);
-
-	if (intstatus & AT91_EMAC_TCOM) {	/* Transmit complete */
-		/* The TCOM bit is set even if the transmission failed. */
-		if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY))
-			dev->stats.tx_errors += 1;
-
-		if (lp->skb) {
-			dev_kfree_skb_irq(lp->skb);
-			lp->skb = NULL;
-			dma_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, DMA_TO_DEVICE);
-		}
-		netif_wake_queue(dev);
-	}
-
-	/* Work-around for Errata #11 */
-	if (intstatus & AT91_EMAC_RBNA) {
-		ctl = at91_emac_read(AT91_EMAC_CTL);
-		at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE);
-		at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE);
-	}
-
-	if (intstatus & AT91_EMAC_ROVR)
-		printk("%s: ROVR error\n", dev->name);
-
-	return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void at91ether_poll_controller(struct net_device *dev)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	at91ether_interrupt(dev->irq, dev);
-	local_irq_restore(flags);
-}
-#endif
-
-static const struct net_device_ops at91ether_netdev_ops = {
-	.ndo_open		= at91ether_open,
-	.ndo_stop		= at91ether_close,
-	.ndo_start_xmit		= at91ether_start_xmit,
-	.ndo_get_stats		= at91ether_stats,
-	.ndo_set_multicast_list	= at91ether_set_multicast_list,
-	.ndo_set_mac_address	= set_mac_address,
-	.ndo_do_ioctl		= at91ether_ioctl,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= at91ether_poll_controller,
-#endif
-};
-
-/*
- * Initialize the ethernet interface
- */
-static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address,
-			struct platform_device *pdev, struct clk *ether_clk)
-{
-	struct at91_eth_data *board_data = pdev->dev.platform_data;
-	struct net_device *dev;
-	struct at91_private *lp;
-	unsigned int val;
-	int res;
-
-	dev = alloc_etherdev(sizeof(struct at91_private));
-	if (!dev)
-		return -ENOMEM;
-
-	dev->base_addr = AT91_VA_BASE_EMAC;
-	dev->irq = AT91RM9200_ID_EMAC;
-
-	/* Install the interrupt handler */
-	if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev)) {
-		free_netdev(dev);
-		return -EBUSY;
-	}
-
-	/* Allocate memory for DMA Receive descriptors */
-	lp = netdev_priv(dev);
-	lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL);
-	if (lp->dlist == NULL) {
-		free_irq(dev->irq, dev);
-		free_netdev(dev);
-		return -ENOMEM;
-	}
-	lp->board_data = *board_data;
-	lp->ether_clk = ether_clk;
-	platform_set_drvdata(pdev, dev);
-
-	spin_lock_init(&lp->lock);
-
-	ether_setup(dev);
-	dev->netdev_ops = &at91ether_netdev_ops;
-	dev->ethtool_ops = &at91ether_ethtool_ops;
-
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-	get_mac_address(dev);		/* Get ethernet address and store it in dev->dev_addr */
-	update_mac_address(dev);	/* Program ethernet address into MAC */
-
-	at91_emac_write(AT91_EMAC_CTL, 0);
-
-	if (lp->board_data.is_rmii)
-		at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII);
-	else
-		at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG);
-
-	/* Perform PHY-specific initialization */
-	spin_lock_irq(&lp->lock);
-	enable_mdi();
-	if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
-		read_phy(phy_address, MII_DSCR_REG, &val);
-		if ((val & (1 << 10)) == 0)			/* DSCR bit 10 is 0 -- fiber mode */
-			lp->phy_media = PORT_FIBRE;
-	} else if (machine_is_csb337()) {
-		/* mix link activity status into LED2 link state */
-		write_phy(phy_address, MII_LEDCTRL_REG, 0x0d22);
-	} else if (machine_is_ecbat91())
-		write_phy(phy_address, MII_LEDCTRL_REG, 0x156A);
-
-	disable_mdi();
-	spin_unlock_irq(&lp->lock);
-
-	lp->mii.dev = dev;		/* Support for ethtool */
-	lp->mii.mdio_read = mdio_read;
-	lp->mii.mdio_write = mdio_write;
-	lp->mii.phy_id = phy_address;
-	lp->mii.phy_id_mask = 0x1f;
-	lp->mii.reg_num_mask = 0x1f;
-
-	lp->phy_type = phy_type;	/* Type of PHY connected */
-	lp->phy_address = phy_address;	/* MDI address of PHY */
-
-	/* Register the network interface */
-	res = register_netdev(dev);
-	if (res) {
-		free_irq(dev->irq, dev);
-		free_netdev(dev);
-		dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
-		return res;
-	}
-
-	/* Determine current link speed */
-	spin_lock_irq(&lp->lock);
-	enable_mdi();
-	update_linkspeed(dev, 0);
-	disable_mdi();
-	spin_unlock_irq(&lp->lock);
-	netif_carrier_off(dev);		/* will be enabled in open() */
-
-	/* If board has no PHY IRQ, use a timer to poll the PHY */
-	if (!lp->board_data.phy_irq_pin) {
-		init_timer(&lp->check_timer);
-		lp->check_timer.data = (unsigned long)dev;
-		lp->check_timer.function = at91ether_check_link;
-	} else if (lp->board_data.phy_irq_pin >= 32)
-		gpio_request(lp->board_data.phy_irq_pin, "ethernet_phy");
-
-	/* Display ethernet banner */
-	printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%pM)\n",
-	       dev->name, (uint) dev->base_addr, dev->irq,
-	       at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-",
-	       at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex",
-	       dev->dev_addr);
-	if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
-		printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
-	else if (phy_type == MII_LXT971A_ID)
-		printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
-	else if (phy_type == MII_RTL8201_ID)
-		printk(KERN_INFO "%s: Realtek RTL8201(B)L PHY\n", dev->name);
-	else if (phy_type == MII_BCM5221_ID)
-		printk(KERN_INFO "%s: Broadcom BCM5221 PHY\n", dev->name);
-	else if (phy_type == MII_DP83847_ID)
-		printk(KERN_INFO "%s: National Semiconductor DP83847 PHY\n", dev->name);
-	else if (phy_type == MII_DP83848_ID)
-		printk(KERN_INFO "%s: National Semiconductor DP83848 PHY\n", dev->name);
-	else if (phy_type == MII_AC101L_ID)
-		printk(KERN_INFO "%s: Altima AC101L PHY\n", dev->name);
-	else if (phy_type == MII_KS8721_ID)
-		printk(KERN_INFO "%s: Micrel KS8721 PHY\n", dev->name);
-	else if (phy_type == MII_T78Q21x3_ID)
-		printk(KERN_INFO "%s: Teridian 78Q21x3 PHY\n", dev->name);
-	else if (phy_type == MII_LAN83C185_ID)
-		printk(KERN_INFO "%s: SMSC LAN83C185 PHY\n", dev->name);
-
-	return 0;
-}
-
-/*
- * Detect MAC and PHY and perform initialization
- */
-static int __init at91ether_probe(struct platform_device *pdev)
-{
-	unsigned int phyid1, phyid2;
-	int detected = -1;
-	unsigned long phy_id;
-	unsigned short phy_address = 0;
-	struct clk *ether_clk;
-
-	ether_clk = clk_get(&pdev->dev, "ether_clk");
-	if (IS_ERR(ether_clk)) {
-		printk(KERN_ERR "at91_ether: no clock defined\n");
-		return -ENODEV;
-	}
-	clk_enable(ether_clk);					/* Enable Peripheral clock */
-
-	while ((detected != 0) && (phy_address < 32)) {
-		/* Read the PHY ID registers */
-		enable_mdi();
-		read_phy(phy_address, MII_PHYSID1, &phyid1);
-		read_phy(phy_address, MII_PHYSID2, &phyid2);
-		disable_mdi();
-
-		phy_id = (phyid1 << 16) | (phyid2 & 0xfff0);
-		switch (phy_id) {
-			case MII_DM9161_ID:		/* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */
-			case MII_DM9161A_ID:		/* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */
-			case MII_LXT971A_ID:		/* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */
-			case MII_RTL8201_ID:		/* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */
-			case MII_BCM5221_ID:		/* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */
-			case MII_DP83847_ID:		/* National Semiconductor DP83847:  */
-			case MII_DP83848_ID:		/* National Semiconductor DP83848:  */
-			case MII_AC101L_ID:		/* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
-			case MII_KS8721_ID:		/* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
-			case MII_T78Q21x3_ID:		/* Teridian 78Q21x3: PHY_ID1 = 0x0E, PHY_ID2 = 7237 */
-			case MII_LAN83C185_ID:		/* SMSC LAN83C185: PHY_ID1 = 0x0007, PHY_ID2 = 0xC0A1 */
-				detected = at91ether_setup(phy_id, phy_address, pdev, ether_clk);
-				break;
-		}
-
-		phy_address++;
-	}
-
-	clk_disable(ether_clk);					/* Disable Peripheral clock */
-
-	return detected;
-}
-
-static int __devexit at91ether_remove(struct platform_device *pdev)
-{
-	struct net_device *dev = platform_get_drvdata(pdev);
-	struct at91_private *lp = netdev_priv(dev);
-
-	if (lp->board_data.phy_irq_pin >= 32)
-		gpio_free(lp->board_data.phy_irq_pin);
-
-	unregister_netdev(dev);
-	free_irq(dev->irq, dev);
-	dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
-	clk_put(lp->ether_clk);
-
-	platform_set_drvdata(pdev, NULL);
-	free_netdev(dev);
-	return 0;
-}
-
-#ifdef CONFIG_PM
-
-static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-	struct net_device *net_dev = platform_get_drvdata(pdev);
-	struct at91_private *lp = netdev_priv(net_dev);
-	int phy_irq = lp->board_data.phy_irq_pin;
-
-	if (netif_running(net_dev)) {
-		if (phy_irq)
-			disable_irq(phy_irq);
-
-		netif_stop_queue(net_dev);
-		netif_device_detach(net_dev);
-
-		clk_disable(lp->ether_clk);
-	}
-	return 0;
-}
-
-static int at91ether_resume(struct platform_device *pdev)
-{
-	struct net_device *net_dev = platform_get_drvdata(pdev);
-	struct at91_private *lp = netdev_priv(net_dev);
-	int phy_irq = lp->board_data.phy_irq_pin;
-
-	if (netif_running(net_dev)) {
-		clk_enable(lp->ether_clk);
-
-		netif_device_attach(net_dev);
-		netif_start_queue(net_dev);
-
-		if (phy_irq)
-			enable_irq(phy_irq);
-	}
-	return 0;
-}
-
-#else
-#define at91ether_suspend	NULL
-#define at91ether_resume	NULL
-#endif
-
-static struct platform_driver at91ether_driver = {
-	.remove		= __devexit_p(at91ether_remove),
-	.suspend	= at91ether_suspend,
-	.resume		= at91ether_resume,
-	.driver		= {
-		.name	= DRV_NAME,
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init at91ether_init(void)
-{
-	return platform_driver_probe(&at91ether_driver, at91ether_probe);
-}
-
-static void __exit at91ether_exit(void)
-{
-	platform_driver_unregister(&at91ether_driver);
-}
-
-module_init(at91ether_init)
-module_exit(at91ether_exit)
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
-MODULE_AUTHOR("Andrew Victor");
-MODULE_ALIAS("platform:" DRV_NAME);
diff -druN linux-libre-3.1-gnu/drivers/net/arm/at91_ether.h linux-libre-3.2-gnu/drivers/net/arm/at91_ether.h
--- linux-libre-3.1-gnu/drivers/net/arm/at91_ether.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arm/at91_ether.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,109 +0,0 @@
-/*
- * Ethernet driver for the Atmel AT91RM9200 (Thunder)
- *
- *  Copyright (C) SAN People (Pty) Ltd
- *
- * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
- * Initial version by Rick Bronson.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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 AT91_ETHERNET
-#define AT91_ETHERNET
-
-
-/* Davicom 9161 PHY */
-#define MII_DM9161_ID		0x0181b880
-#define MII_DM9161A_ID		0x0181b8a0
-#define MII_DSCR_REG		16
-#define MII_DSCSR_REG		17
-#define MII_DSINTR_REG		21
-
-/* Intel LXT971A PHY */
-#define MII_LXT971A_ID		0x001378E0
-#define MII_ISINTE_REG		18
-#define MII_ISINTS_REG		19
-#define MII_LEDCTRL_REG		20
-
-/* Realtek RTL8201 PHY */
-#define MII_RTL8201_ID		0x00008200
-
-/* Broadcom BCM5221 PHY */
-#define MII_BCM5221_ID		0x004061e0
-#define MII_BCMINTR_REG		26
-
-/* National Semiconductor DP83847 */
-#define MII_DP83847_ID		0x20005c30
-
-/* National Semiconductor DP83848 */
-#define MII_DP83848_ID		0x20005c90
-#define MII_DPPHYSTS_REG	16
-#define MII_DPMICR_REG		17
-#define MII_DPMISR_REG		18
-
-/* Altima AC101L PHY */
-#define MII_AC101L_ID		0x00225520
-
-/* Micrel KS8721 PHY */
-#define MII_KS8721_ID		0x00221610
-
-/* Teridian 78Q2123/78Q2133 */
-#define MII_T78Q21x3_ID		0x000e7230
-#define MII_T78Q21INT_REG	17
-
-/* SMSC LAN83C185 */
-#define MII_LAN83C185_ID	0x0007C0A0
-
-/* ........................................................................ */
-
-#define MAX_RBUFF_SZ	0x600		/* 1518 rounded up */
-#define MAX_RX_DESCR	9		/* max number of receive buffers */
-
-#define EMAC_DESC_DONE	0x00000001	/* bit for if DMA is done */
-#define EMAC_DESC_WRAP	0x00000002	/* bit for wrap */
-
-#define EMAC_BROADCAST	0x80000000	/* broadcast address */
-#define EMAC_MULTICAST	0x40000000	/* multicast address */
-#define EMAC_UNICAST	0x20000000	/* unicast address */
-
-struct rbf_t
-{
-	unsigned int addr;
-	unsigned long size;
-};
-
-struct recv_desc_bufs
-{
-	struct rbf_t descriptors[MAX_RX_DESCR];		/* must be on sizeof (rbf_t) boundary */
-	char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ];	/* must be on long boundary */
-};
-
-struct at91_private
-{
-	struct mii_if_info mii;			/* ethtool support */
-	struct at91_eth_data board_data;	/* board-specific configuration */
-	struct clk *ether_clk;			/* clock */
-
-	/* PHY */
-	unsigned long phy_type;			/* type of PHY (PHY_ID) */
-	spinlock_t lock;			/* lock for MDI interface */
-	short phy_media;			/* media interface type */
-	unsigned short phy_address;		/* 5-bit MDI address of PHY (0..31) */
-	struct timer_list check_timer;		/* Poll link status */
-
-	/* Transmit */
-	struct sk_buff *skb;			/* holds skb until xmit interrupt completes */
-	dma_addr_t skb_physaddr;		/* phys addr from pci_map_single */
-	int skb_length;				/* saved skb length for pci_unmap_single */
-
-	/* Receive */
-	int rxBuffIndex;			/* index into receive descriptor list */
-	struct recv_desc_bufs *dlist;		/* descriptor list address */
-	struct recv_desc_bufs *dlist_phys;	/* descriptor list physical address */
-};
-
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/arm/ep93xx_eth.c linux-libre-3.2-gnu/drivers/net/arm/ep93xx_eth.c
--- linux-libre-3.1-gnu/drivers/net/arm/ep93xx_eth.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arm/ep93xx_eth.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,904 +0,0 @@
-/*
- * EP93xx ethernet network device driver
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
- * Dedicated to Marija Kulikova.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
-
-#include <linux/dma-mapping.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/mii.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <mach/hardware.h>
-
-#define DRV_MODULE_NAME		"ep93xx-eth"
-#define DRV_MODULE_VERSION	"0.1"
-
-#define RX_QUEUE_ENTRIES	64
-#define TX_QUEUE_ENTRIES	8
-
-#define MAX_PKT_SIZE		2044
-#define PKT_BUF_SIZE		2048
-
-#define REG_RXCTL		0x0000
-#define  REG_RXCTL_DEFAULT	0x00073800
-#define REG_TXCTL		0x0004
-#define  REG_TXCTL_ENABLE	0x00000001
-#define REG_MIICMD		0x0010
-#define  REG_MIICMD_READ	0x00008000
-#define  REG_MIICMD_WRITE	0x00004000
-#define REG_MIIDATA		0x0014
-#define REG_MIISTS		0x0018
-#define  REG_MIISTS_BUSY	0x00000001
-#define REG_SELFCTL		0x0020
-#define  REG_SELFCTL_RESET	0x00000001
-#define REG_INTEN		0x0024
-#define  REG_INTEN_TX		0x00000008
-#define  REG_INTEN_RX		0x00000007
-#define REG_INTSTSP		0x0028
-#define  REG_INTSTS_TX		0x00000008
-#define  REG_INTSTS_RX		0x00000004
-#define REG_INTSTSC		0x002c
-#define REG_AFP			0x004c
-#define REG_INDAD0		0x0050
-#define REG_INDAD1		0x0051
-#define REG_INDAD2		0x0052
-#define REG_INDAD3		0x0053
-#define REG_INDAD4		0x0054
-#define REG_INDAD5		0x0055
-#define REG_GIINTMSK		0x0064
-#define  REG_GIINTMSK_ENABLE	0x00008000
-#define REG_BMCTL		0x0080
-#define  REG_BMCTL_ENABLE_TX	0x00000100
-#define  REG_BMCTL_ENABLE_RX	0x00000001
-#define REG_BMSTS		0x0084
-#define  REG_BMSTS_RX_ACTIVE	0x00000008
-#define REG_RXDQBADD		0x0090
-#define REG_RXDQBLEN		0x0094
-#define REG_RXDCURADD		0x0098
-#define REG_RXDENQ		0x009c
-#define REG_RXSTSQBADD		0x00a0
-#define REG_RXSTSQBLEN		0x00a4
-#define REG_RXSTSQCURADD	0x00a8
-#define REG_RXSTSENQ		0x00ac
-#define REG_TXDQBADD		0x00b0
-#define REG_TXDQBLEN		0x00b4
-#define REG_TXDQCURADD		0x00b8
-#define REG_TXDENQ		0x00bc
-#define REG_TXSTSQBADD		0x00c0
-#define REG_TXSTSQBLEN		0x00c4
-#define REG_TXSTSQCURADD	0x00c8
-#define REG_MAXFRMLEN		0x00e8
-
-struct ep93xx_rdesc
-{
-	u32	buf_addr;
-	u32	rdesc1;
-};
-
-#define RDESC1_NSOF		0x80000000
-#define RDESC1_BUFFER_INDEX	0x7fff0000
-#define RDESC1_BUFFER_LENGTH	0x0000ffff
-
-struct ep93xx_rstat
-{
-	u32	rstat0;
-	u32	rstat1;
-};
-
-#define RSTAT0_RFP		0x80000000
-#define RSTAT0_RWE		0x40000000
-#define RSTAT0_EOF		0x20000000
-#define RSTAT0_EOB		0x10000000
-#define RSTAT0_AM		0x00c00000
-#define RSTAT0_RX_ERR		0x00200000
-#define RSTAT0_OE		0x00100000
-#define RSTAT0_FE		0x00080000
-#define RSTAT0_RUNT		0x00040000
-#define RSTAT0_EDATA		0x00020000
-#define RSTAT0_CRCE		0x00010000
-#define RSTAT0_CRCI		0x00008000
-#define RSTAT0_HTI		0x00003f00
-#define RSTAT1_RFP		0x80000000
-#define RSTAT1_BUFFER_INDEX	0x7fff0000
-#define RSTAT1_FRAME_LENGTH	0x0000ffff
-
-struct ep93xx_tdesc
-{
-	u32	buf_addr;
-	u32	tdesc1;
-};
-
-#define TDESC1_EOF		0x80000000
-#define TDESC1_BUFFER_INDEX	0x7fff0000
-#define TDESC1_BUFFER_ABORT	0x00008000
-#define TDESC1_BUFFER_LENGTH	0x00000fff
-
-struct ep93xx_tstat
-{
-	u32	tstat0;
-};
-
-#define TSTAT0_TXFP		0x80000000
-#define TSTAT0_TXWE		0x40000000
-#define TSTAT0_FA		0x20000000
-#define TSTAT0_LCRS		0x10000000
-#define TSTAT0_OW		0x04000000
-#define TSTAT0_TXU		0x02000000
-#define TSTAT0_ECOLL		0x01000000
-#define TSTAT0_NCOLL		0x001f0000
-#define TSTAT0_BUFFER_INDEX	0x00007fff
-
-struct ep93xx_descs
-{
-	struct ep93xx_rdesc	rdesc[RX_QUEUE_ENTRIES];
-	struct ep93xx_tdesc	tdesc[TX_QUEUE_ENTRIES];
-	struct ep93xx_rstat	rstat[RX_QUEUE_ENTRIES];
-	struct ep93xx_tstat	tstat[TX_QUEUE_ENTRIES];
-};
-
-struct ep93xx_priv
-{
-	struct resource		*res;
-	void __iomem		*base_addr;
-	int			irq;
-
-	struct ep93xx_descs	*descs;
-	dma_addr_t		descs_dma_addr;
-
-	void			*rx_buf[RX_QUEUE_ENTRIES];
-	void			*tx_buf[TX_QUEUE_ENTRIES];
-
-	spinlock_t		rx_lock;
-	unsigned int		rx_pointer;
-	unsigned int		tx_clean_pointer;
-	unsigned int		tx_pointer;
-	spinlock_t		tx_pending_lock;
-	unsigned int		tx_pending;
-
-	struct net_device	*dev;
-	struct napi_struct	napi;
-
-	struct mii_if_info	mii;
-	u8			mdc_divisor;
-};
-
-#define rdb(ep, off)		__raw_readb((ep)->base_addr + (off))
-#define rdw(ep, off)		__raw_readw((ep)->base_addr + (off))
-#define rdl(ep, off)		__raw_readl((ep)->base_addr + (off))
-#define wrb(ep, off, val)	__raw_writeb((val), (ep)->base_addr + (off))
-#define wrw(ep, off, val)	__raw_writew((val), (ep)->base_addr + (off))
-#define wrl(ep, off, val)	__raw_writel((val), (ep)->base_addr + (off))
-
-static int ep93xx_mdio_read(struct net_device *dev, int phy_id, int reg)
-{
-	struct ep93xx_priv *ep = netdev_priv(dev);
-	int data;
-	int i;
-
-	wrl(ep, REG_MIICMD, REG_MIICMD_READ | (phy_id << 5) | reg);
-
-	for (i = 0; i < 10; i++) {
-		if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0)
-			break;
-		msleep(1);
-	}
-
-	if (i == 10) {
-		pr_info("mdio read timed out\n");
-		data = 0xffff;
-	} else {
-		data = rdl(ep, REG_MIIDATA);
-	}
-
-	return data;
-}
-
-static void ep93xx_mdio_write(struct net_device *dev, int phy_id, int reg, int data)
-{
-	struct ep93xx_priv *ep = netdev_priv(dev);
-	int i;
-
-	wrl(ep, REG_MIIDATA, data);
-	wrl(ep, REG_MIICMD, REG_MIICMD_WRITE | (phy_id << 5) | reg);
-
-	for (i = 0; i < 10; i++) {
-		if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0)
-			break;
-		msleep(1);
-	}
-
-	if (i == 10)
-		pr_info("mdio write timed out\n");
-}
-
-static int ep93xx_rx(struct net_device *dev, int processed, int budget)
-{
-	struct ep93xx_priv *ep = netdev_priv(dev);
-
-	while (processed < budget) {
-		int entry;
-		struct ep93xx_rstat *rstat;
-		u32 rstat0;
-		u32 rstat1;
-		int length;
-		struct sk_buff *skb;
-
-		entry = ep->rx_pointer;
-		rstat = ep->descs->rstat + entry;
-
-		rstat0 = rstat->rstat0;
-		rstat1 = rstat->rstat1;
-		if (!(rstat0 & RSTAT0_RFP) || !(rstat1 & RSTAT1_RFP))
-			break;
-
-		rstat->rstat0 = 0;
-		rstat->rstat1 = 0;
-
-		if (!(rstat0 & RSTAT0_EOF))
-			pr_crit("not end-of-frame %.8x %.8x\n", rstat0, rstat1);
-		if (!(rstat0 & RSTAT0_EOB))
-			pr_crit("not end-of-buffer %.8x %.8x\n", rstat0, rstat1);
-		if ((rstat1 & RSTAT1_BUFFER_INDEX) >> 16 != entry)
-			pr_crit("entry mismatch %.8x %.8x\n", rstat0, rstat1);
-
-		if (!(rstat0 & RSTAT0_RWE)) {
-			dev->stats.rx_errors++;
-			if (rstat0 & RSTAT0_OE)
-				dev->stats.rx_fifo_errors++;
-			if (rstat0 & RSTAT0_FE)
-				dev->stats.rx_frame_errors++;
-			if (rstat0 & (RSTAT0_RUNT | RSTAT0_EDATA))
-				dev->stats.rx_length_errors++;
-			if (rstat0 & RSTAT0_CRCE)
-				dev->stats.rx_crc_errors++;
-			goto err;
-		}
-
-		length = rstat1 & RSTAT1_FRAME_LENGTH;
-		if (length > MAX_PKT_SIZE) {
-			pr_notice("invalid length %.8x %.8x\n", rstat0, rstat1);
-			goto err;
-		}
-
-		/* Strip FCS.  */
-		if (rstat0 & RSTAT0_CRCI)
-			length -= 4;
-
-		skb = dev_alloc_skb(length + 2);
-		if (likely(skb != NULL)) {
-			struct ep93xx_rdesc *rxd = &ep->descs->rdesc[entry];
-			skb_reserve(skb, 2);
-			dma_sync_single_for_cpu(dev->dev.parent, rxd->buf_addr,
-						length, DMA_FROM_DEVICE);
-			skb_copy_to_linear_data(skb, ep->rx_buf[entry], length);
-			dma_sync_single_for_device(dev->dev.parent,
-						   rxd->buf_addr, length,
-						   DMA_FROM_DEVICE);
-			skb_put(skb, length);
-			skb->protocol = eth_type_trans(skb, dev);
-
-			netif_receive_skb(skb);
-
-			dev->stats.rx_packets++;
-			dev->stats.rx_bytes += length;
-		} else {
-			dev->stats.rx_dropped++;
-		}
-
-err:
-		ep->rx_pointer = (entry + 1) & (RX_QUEUE_ENTRIES - 1);
-		processed++;
-	}
-
-	return processed;
-}
-
-static int ep93xx_have_more_rx(struct ep93xx_priv *ep)
-{
-	struct ep93xx_rstat *rstat = ep->descs->rstat + ep->rx_pointer;
-	return !!((rstat->rstat0 & RSTAT0_RFP) && (rstat->rstat1 & RSTAT1_RFP));
-}
-
-static int ep93xx_poll(struct napi_struct *napi, int budget)
-{
-	struct ep93xx_priv *ep = container_of(napi, struct ep93xx_priv, napi);
-	struct net_device *dev = ep->dev;
-	int rx = 0;
-
-poll_some_more:
-	rx = ep93xx_rx(dev, rx, budget);
-	if (rx < budget) {
-		int more = 0;
-
-		spin_lock_irq(&ep->rx_lock);
-		__napi_complete(napi);
-		wrl(ep, REG_INTEN, REG_INTEN_TX | REG_INTEN_RX);
-		if (ep93xx_have_more_rx(ep)) {
-			wrl(ep, REG_INTEN, REG_INTEN_TX);
-			wrl(ep, REG_INTSTSP, REG_INTSTS_RX);
-			more = 1;
-		}
-		spin_unlock_irq(&ep->rx_lock);
-
-		if (more && napi_reschedule(napi))
-			goto poll_some_more;
-	}
-
-	if (rx) {
-		wrw(ep, REG_RXDENQ, rx);
-		wrw(ep, REG_RXSTSENQ, rx);
-	}
-
-	return rx;
-}
-
-static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct ep93xx_priv *ep = netdev_priv(dev);
-	struct ep93xx_tdesc *txd;
-	int entry;
-
-	if (unlikely(skb->len > MAX_PKT_SIZE)) {
-		dev->stats.tx_dropped++;
-		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-
-	entry = ep->tx_pointer;
-	ep->tx_pointer = (ep->tx_pointer + 1) & (TX_QUEUE_ENTRIES - 1);
-
-	txd = &ep->descs->tdesc[entry];
-
-	txd->tdesc1 = TDESC1_EOF | (entry << 16) | (skb->len & 0xfff);
-	dma_sync_single_for_cpu(dev->dev.parent, txd->buf_addr, skb->len,
-				DMA_TO_DEVICE);
-	skb_copy_and_csum_dev(skb, ep->tx_buf[entry]);
-	dma_sync_single_for_device(dev->dev.parent, txd->buf_addr, skb->len,
-				   DMA_TO_DEVICE);
-	dev_kfree_skb(skb);
-
-	spin_lock_irq(&ep->tx_pending_lock);
-	ep->tx_pending++;
-	if (ep->tx_pending == TX_QUEUE_ENTRIES)
-		netif_stop_queue(dev);
-	spin_unlock_irq(&ep->tx_pending_lock);
-
-	wrl(ep, REG_TXDENQ, 1);
-
-	return NETDEV_TX_OK;
-}
-
-static void ep93xx_tx_complete(struct net_device *dev)
-{
-	struct ep93xx_priv *ep = netdev_priv(dev);
-	int wake;
-
-	wake = 0;
-
-	spin_lock(&ep->tx_pending_lock);
-	while (1) {
-		int entry;
-		struct ep93xx_tstat *tstat;
-		u32 tstat0;
-
-		entry = ep->tx_clean_pointer;
-		tstat = ep->descs->tstat + entry;
-
-		tstat0 = tstat->tstat0;
-		if (!(tstat0 & TSTAT0_TXFP))
-			break;
-
-		tstat->tstat0 = 0;
-
-		if (tstat0 & TSTAT0_FA)
-			pr_crit("frame aborted %.8x\n", tstat0);
-		if ((tstat0 & TSTAT0_BUFFER_INDEX) != entry)
-			pr_crit("entry mismatch %.8x\n", tstat0);
-
-		if (tstat0 & TSTAT0_TXWE) {
-			int length = ep->descs->tdesc[entry].tdesc1 & 0xfff;
-
-			dev->stats.tx_packets++;
-			dev->stats.tx_bytes += length;
-		} else {
-			dev->stats.tx_errors++;
-		}
-
-		if (tstat0 & TSTAT0_OW)
-			dev->stats.tx_window_errors++;
-		if (tstat0 & TSTAT0_TXU)
-			dev->stats.tx_fifo_errors++;
-		dev->stats.collisions += (tstat0 >> 16) & 0x1f;
-
-		ep->tx_clean_pointer = (entry + 1) & (TX_QUEUE_ENTRIES - 1);
-		if (ep->tx_pending == TX_QUEUE_ENTRIES)
-			wake = 1;
-		ep->tx_pending--;
-	}
-	spin_unlock(&ep->tx_pending_lock);
-
-	if (wake)
-		netif_wake_queue(dev);
-}
-
-static irqreturn_t ep93xx_irq(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct ep93xx_priv *ep = netdev_priv(dev);
-	u32 status;
-
-	status = rdl(ep, REG_INTSTSC);
-	if (status == 0)
-		return IRQ_NONE;
-
-	if (status & REG_INTSTS_RX) {
-		spin_lock(&ep->rx_lock);
-		if (likely(napi_schedule_prep(&ep->napi))) {
-			wrl(ep, REG_INTEN, REG_INTEN_TX);
-			__napi_schedule(&ep->napi);
-		}
-		spin_unlock(&ep->rx_lock);
-	}
-
-	if (status & REG_INTSTS_TX)
-		ep93xx_tx_complete(dev);
-
-	return IRQ_HANDLED;
-}
-
-static void ep93xx_free_buffers(struct ep93xx_priv *ep)
-{
-	struct device *dev = ep->dev->dev.parent;
-	int i;
-
-	for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
-		dma_addr_t d;
-
-		d = ep->descs->rdesc[i].buf_addr;
-		if (d)
-			dma_unmap_single(dev, d, PKT_BUF_SIZE, DMA_FROM_DEVICE);
-
-		if (ep->rx_buf[i] != NULL)
-			kfree(ep->rx_buf[i]);
-	}
-
-	for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
-		dma_addr_t d;
-
-		d = ep->descs->tdesc[i].buf_addr;
-		if (d)
-			dma_unmap_single(dev, d, PKT_BUF_SIZE, DMA_TO_DEVICE);
-
-		if (ep->tx_buf[i] != NULL)
-			kfree(ep->tx_buf[i]);
-	}
-
-	dma_free_coherent(dev, sizeof(struct ep93xx_descs), ep->descs,
-							ep->descs_dma_addr);
-}
-
-static int ep93xx_alloc_buffers(struct ep93xx_priv *ep)
-{
-	struct device *dev = ep->dev->dev.parent;
-	int i;
-
-	ep->descs = dma_alloc_coherent(dev, sizeof(struct ep93xx_descs),
-				&ep->descs_dma_addr, GFP_KERNEL);
-	if (ep->descs == NULL)
-		return 1;
-
-	for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
-		void *buf;
-		dma_addr_t d;
-
-		buf = kmalloc(PKT_BUF_SIZE, GFP_KERNEL);
-		if (buf == NULL)
-			goto err;
-
-		d = dma_map_single(dev, buf, PKT_BUF_SIZE, DMA_FROM_DEVICE);
-		if (dma_mapping_error(dev, d)) {
-			kfree(buf);
-			goto err;
-		}
-
-		ep->rx_buf[i] = buf;
-		ep->descs->rdesc[i].buf_addr = d;
-		ep->descs->rdesc[i].rdesc1 = (i << 16) | PKT_BUF_SIZE;
-	}
-
-	for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
-		void *buf;
-		dma_addr_t d;
-
-		buf = kmalloc(PKT_BUF_SIZE, GFP_KERNEL);
-		if (buf == NULL)
-			goto err;
-
-		d = dma_map_single(dev, buf, PKT_BUF_SIZE, DMA_TO_DEVICE);
-		if (dma_mapping_error(dev, d)) {
-			kfree(buf);
-			goto err;
-		}
-
-		ep->tx_buf[i] = buf;
-		ep->descs->tdesc[i].buf_addr = d;
-	}
-
-	return 0;
-
-err:
-	ep93xx_free_buffers(ep);
-	return 1;
-}
-
-static int ep93xx_start_hw(struct net_device *dev)
-{
-	struct ep93xx_priv *ep = netdev_priv(dev);
-	unsigned long addr;
-	int i;
-
-	wrl(ep, REG_SELFCTL, REG_SELFCTL_RESET);
-	for (i = 0; i < 10; i++) {
-		if ((rdl(ep, REG_SELFCTL) & REG_SELFCTL_RESET) == 0)
-			break;
-		msleep(1);
-	}
-
-	if (i == 10) {
-		pr_crit("hw failed to reset\n");
-		return 1;
-	}
-
-	wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9));
-
-	/* Does the PHY support preamble suppress?  */
-	if ((ep93xx_mdio_read(dev, ep->mii.phy_id, MII_BMSR) & 0x0040) != 0)
-		wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9) | (1 << 8));
-
-	/* Receive descriptor ring.  */
-	addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, rdesc);
-	wrl(ep, REG_RXDQBADD, addr);
-	wrl(ep, REG_RXDCURADD, addr);
-	wrw(ep, REG_RXDQBLEN, RX_QUEUE_ENTRIES * sizeof(struct ep93xx_rdesc));
-
-	/* Receive status ring.  */
-	addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, rstat);
-	wrl(ep, REG_RXSTSQBADD, addr);
-	wrl(ep, REG_RXSTSQCURADD, addr);
-	wrw(ep, REG_RXSTSQBLEN, RX_QUEUE_ENTRIES * sizeof(struct ep93xx_rstat));
-
-	/* Transmit descriptor ring.  */
-	addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, tdesc);
-	wrl(ep, REG_TXDQBADD, addr);
-	wrl(ep, REG_TXDQCURADD, addr);
-	wrw(ep, REG_TXDQBLEN, TX_QUEUE_ENTRIES * sizeof(struct ep93xx_tdesc));
-
-	/* Transmit status ring.  */
-	addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, tstat);
-	wrl(ep, REG_TXSTSQBADD, addr);
-	wrl(ep, REG_TXSTSQCURADD, addr);
-	wrw(ep, REG_TXSTSQBLEN, TX_QUEUE_ENTRIES * sizeof(struct ep93xx_tstat));
-
-	wrl(ep, REG_BMCTL, REG_BMCTL_ENABLE_TX | REG_BMCTL_ENABLE_RX);
-	wrl(ep, REG_INTEN, REG_INTEN_TX | REG_INTEN_RX);
-	wrl(ep, REG_GIINTMSK, 0);
-
-	for (i = 0; i < 10; i++) {
-		if ((rdl(ep, REG_BMSTS) & REG_BMSTS_RX_ACTIVE) != 0)
-			break;
-		msleep(1);
-	}
-
-	if (i == 10) {
-		pr_crit("hw failed to start\n");
-		return 1;
-	}
-
-	wrl(ep, REG_RXDENQ, RX_QUEUE_ENTRIES);
-	wrl(ep, REG_RXSTSENQ, RX_QUEUE_ENTRIES);
-
-	wrb(ep, REG_INDAD0, dev->dev_addr[0]);
-	wrb(ep, REG_INDAD1, dev->dev_addr[1]);
-	wrb(ep, REG_INDAD2, dev->dev_addr[2]);
-	wrb(ep, REG_INDAD3, dev->dev_addr[3]);
-	wrb(ep, REG_INDAD4, dev->dev_addr[4]);
-	wrb(ep, REG_INDAD5, dev->dev_addr[5]);
-	wrl(ep, REG_AFP, 0);
-
-	wrl(ep, REG_MAXFRMLEN, (MAX_PKT_SIZE << 16) | MAX_PKT_SIZE);
-
-	wrl(ep, REG_RXCTL, REG_RXCTL_DEFAULT);
-	wrl(ep, REG_TXCTL, REG_TXCTL_ENABLE);
-
-	return 0;
-}
-
-static void ep93xx_stop_hw(struct net_device *dev)
-{
-	struct ep93xx_priv *ep = netdev_priv(dev);
-	int i;
-
-	wrl(ep, REG_SELFCTL, REG_SELFCTL_RESET);
-	for (i = 0; i < 10; i++) {
-		if ((rdl(ep, REG_SELFCTL) & REG_SELFCTL_RESET) == 0)
-			break;
-		msleep(1);
-	}
-
-	if (i == 10)
-		pr_crit("hw failed to reset\n");
-}
-
-static int ep93xx_open(struct net_device *dev)
-{
-	struct ep93xx_priv *ep = netdev_priv(dev);
-	int err;
-
-	if (ep93xx_alloc_buffers(ep))
-		return -ENOMEM;
-
-	napi_enable(&ep->napi);
-
-	if (ep93xx_start_hw(dev)) {
-		napi_disable(&ep->napi);
-		ep93xx_free_buffers(ep);
-		return -EIO;
-	}
-
-	spin_lock_init(&ep->rx_lock);
-	ep->rx_pointer = 0;
-	ep->tx_clean_pointer = 0;
-	ep->tx_pointer = 0;
-	spin_lock_init(&ep->tx_pending_lock);
-	ep->tx_pending = 0;
-
-	err = request_irq(ep->irq, ep93xx_irq, IRQF_SHARED, dev->name, dev);
-	if (err) {
-		napi_disable(&ep->napi);
-		ep93xx_stop_hw(dev);
-		ep93xx_free_buffers(ep);
-		return err;
-	}
-
-	wrl(ep, REG_GIINTMSK, REG_GIINTMSK_ENABLE);
-
-	netif_start_queue(dev);
-
-	return 0;
-}
-
-static int ep93xx_close(struct net_device *dev)
-{
-	struct ep93xx_priv *ep = netdev_priv(dev);
-
-	napi_disable(&ep->napi);
-	netif_stop_queue(dev);
-
-	wrl(ep, REG_GIINTMSK, 0);
-	free_irq(ep->irq, dev);
-	ep93xx_stop_hw(dev);
-	ep93xx_free_buffers(ep);
-
-	return 0;
-}
-
-static int ep93xx_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	struct ep93xx_priv *ep = netdev_priv(dev);
-	struct mii_ioctl_data *data = if_mii(ifr);
-
-	return generic_mii_ioctl(&ep->mii, data, cmd, NULL);
-}
-
-static void ep93xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, DRV_MODULE_NAME);
-	strcpy(info->version, DRV_MODULE_VERSION);
-}
-
-static int ep93xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct ep93xx_priv *ep = netdev_priv(dev);
-	return mii_ethtool_gset(&ep->mii, cmd);
-}
-
-static int ep93xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct ep93xx_priv *ep = netdev_priv(dev);
-	return mii_ethtool_sset(&ep->mii, cmd);
-}
-
-static int ep93xx_nway_reset(struct net_device *dev)
-{
-	struct ep93xx_priv *ep = netdev_priv(dev);
-	return mii_nway_restart(&ep->mii);
-}
-
-static u32 ep93xx_get_link(struct net_device *dev)
-{
-	struct ep93xx_priv *ep = netdev_priv(dev);
-	return mii_link_ok(&ep->mii);
-}
-
-static const struct ethtool_ops ep93xx_ethtool_ops = {
-	.get_drvinfo		= ep93xx_get_drvinfo,
-	.get_settings		= ep93xx_get_settings,
-	.set_settings		= ep93xx_set_settings,
-	.nway_reset		= ep93xx_nway_reset,
-	.get_link		= ep93xx_get_link,
-};
-
-static const struct net_device_ops ep93xx_netdev_ops = {
-	.ndo_open		= ep93xx_open,
-	.ndo_stop		= ep93xx_close,
-	.ndo_start_xmit		= ep93xx_xmit,
-	.ndo_do_ioctl		= ep93xx_ioctl,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address	= eth_mac_addr,
-};
-
-static struct net_device *ep93xx_dev_alloc(struct ep93xx_eth_data *data)
-{
-	struct net_device *dev;
-
-	dev = alloc_etherdev(sizeof(struct ep93xx_priv));
-	if (dev == NULL)
-		return NULL;
-
-	memcpy(dev->dev_addr, data->dev_addr, ETH_ALEN);
-
-	dev->ethtool_ops = &ep93xx_ethtool_ops;
-	dev->netdev_ops = &ep93xx_netdev_ops;
-
-	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
-
-	return dev;
-}
-
-
-static int ep93xx_eth_remove(struct platform_device *pdev)
-{
-	struct net_device *dev;
-	struct ep93xx_priv *ep;
-
-	dev = platform_get_drvdata(pdev);
-	if (dev == NULL)
-		return 0;
-	platform_set_drvdata(pdev, NULL);
-
-	ep = netdev_priv(dev);
-
-	/* @@@ Force down.  */
-	unregister_netdev(dev);
-	ep93xx_free_buffers(ep);
-
-	if (ep->base_addr != NULL)
-		iounmap(ep->base_addr);
-
-	if (ep->res != NULL) {
-		release_resource(ep->res);
-		kfree(ep->res);
-	}
-
-	free_netdev(dev);
-
-	return 0;
-}
-
-static int ep93xx_eth_probe(struct platform_device *pdev)
-{
-	struct ep93xx_eth_data *data;
-	struct net_device *dev;
-	struct ep93xx_priv *ep;
-	struct resource *mem;
-	int irq;
-	int err;
-
-	if (pdev == NULL)
-		return -ENODEV;
-	data = pdev->dev.platform_data;
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	irq = platform_get_irq(pdev, 0);
-	if (!mem || irq < 0)
-		return -ENXIO;
-
-	dev = ep93xx_dev_alloc(data);
-	if (dev == NULL) {
-		err = -ENOMEM;
-		goto err_out;
-	}
-	ep = netdev_priv(dev);
-	ep->dev = dev;
-	SET_NETDEV_DEV(dev, &pdev->dev);
-	netif_napi_add(dev, &ep->napi, ep93xx_poll, 64);
-
-	platform_set_drvdata(pdev, dev);
-
-	ep->res = request_mem_region(mem->start, resource_size(mem),
-				     dev_name(&pdev->dev));
-	if (ep->res == NULL) {
-		dev_err(&pdev->dev, "Could not reserve memory region\n");
-		err = -ENOMEM;
-		goto err_out;
-	}
-
-	ep->base_addr = ioremap(mem->start, resource_size(mem));
-	if (ep->base_addr == NULL) {
-		dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
-		err = -EIO;
-		goto err_out;
-	}
-	ep->irq = irq;
-
-	ep->mii.phy_id = data->phy_id;
-	ep->mii.phy_id_mask = 0x1f;
-	ep->mii.reg_num_mask = 0x1f;
-	ep->mii.dev = dev;
-	ep->mii.mdio_read = ep93xx_mdio_read;
-	ep->mii.mdio_write = ep93xx_mdio_write;
-	ep->mdc_divisor = 40;	/* Max HCLK 100 MHz, min MDIO clk 2.5 MHz.  */
-
-	if (is_zero_ether_addr(dev->dev_addr))
-		random_ether_addr(dev->dev_addr);
-
-	err = register_netdev(dev);
-	if (err) {
-		dev_err(&pdev->dev, "Failed to register netdev\n");
-		goto err_out;
-	}
-
-	printk(KERN_INFO "%s: ep93xx on-chip ethernet, IRQ %d, %pM\n",
-			dev->name, ep->irq, dev->dev_addr);
-
-	return 0;
-
-err_out:
-	ep93xx_eth_remove(pdev);
-	return err;
-}
-
-
-static struct platform_driver ep93xx_eth_driver = {
-	.probe		= ep93xx_eth_probe,
-	.remove		= ep93xx_eth_remove,
-	.driver		= {
-		.name	= "ep93xx-eth",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init ep93xx_eth_init_module(void)
-{
-	printk(KERN_INFO DRV_MODULE_NAME " version " DRV_MODULE_VERSION " loading\n");
-	return platform_driver_register(&ep93xx_eth_driver);
-}
-
-static void __exit ep93xx_eth_cleanup_module(void)
-{
-	platform_driver_unregister(&ep93xx_eth_driver);
-}
-
-module_init(ep93xx_eth_init_module);
-module_exit(ep93xx_eth_cleanup_module);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:ep93xx-eth");
diff -druN linux-libre-3.1-gnu/drivers/net/arm/ether1.c linux-libre-3.2-gnu/drivers/net/arm/ether1.c
--- linux-libre-3.1-gnu/drivers/net/arm/ether1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arm/ether1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1094 +0,0 @@
-/*
- *  linux/drivers/acorn/net/ether1.c
- *
- *  Copyright (C) 1996-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.
- *
- *  Acorn ether1 driver (82586 chip) for Acorn machines
- *
- * We basically keep two queues in the cards memory - one for transmit
- * and one for receive.  Each has a head and a tail.  The head is where
- * we/the chip adds packets to be transmitted/received, and the tail
- * is where the transmitter has got to/where the receiver will stop.
- * Both of these queues are circular, and since the chip is running
- * all the time, we have to be careful when we modify the pointers etc
- * so that the buffer memory contents is valid all the time.
- *
- * Change log:
- * 1.00	RMK			Released
- * 1.01	RMK	19/03/1996	Transfers the last odd byte onto/off of the card now.
- * 1.02	RMK	25/05/1997	Added code to restart RU if it goes not ready
- * 1.03	RMK	14/09/1997	Cleaned up the handling of a reset during the TX interrupt.
- *				Should prevent lockup.
- * 1.04 RMK	17/09/1997	Added more info when initialsation of chip goes wrong.
- *				TDR now only reports failure when chip reports non-zero
- *				TDR time-distance.
- * 1.05	RMK	31/12/1997	Removed calls to dev_tint for 2.1
- * 1.06	RMK	10/02/2000	Updated for 2.3.43
- * 1.07	RMK	13/05/2000	Updated for 2.3.99-pre8
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/ecard.h>
-
-#define __ETHER1_C
-#include "ether1.h"
-
-static unsigned int net_debug = NET_DEBUG;
-
-#define BUFFER_SIZE	0x10000
-#define TX_AREA_START	0x00100
-#define TX_AREA_END	0x05000
-#define RX_AREA_START	0x05000
-#define RX_AREA_END	0x0fc00
-
-static int ether1_open(struct net_device *dev);
-static int ether1_sendpacket(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t ether1_interrupt(int irq, void *dev_id);
-static int ether1_close(struct net_device *dev);
-static void ether1_setmulticastlist(struct net_device *dev);
-static void ether1_timeout(struct net_device *dev);
-
-/* ------------------------------------------------------------------------- */
-
-static char version[] __devinitdata = "ether1 ethernet driver (c) 2000 Russell King v1.07\n";
-
-#define BUS_16 16
-#define BUS_8  8
-
-/* ------------------------------------------------------------------------- */
-
-#define DISABLEIRQS 1
-#define NORMALIRQS  0
-
-#define ether1_readw(dev, addr, type, offset, svflgs) ether1_inw_p (dev, addr + (int)(&((type *)0)->offset), svflgs)
-#define ether1_writew(dev, val, addr, type, offset, svflgs) ether1_outw_p (dev, val, addr + (int)(&((type *)0)->offset), svflgs)
-
-static inline unsigned short
-ether1_inw_p (struct net_device *dev, int addr, int svflgs)
-{
-	unsigned long flags;
-	unsigned short ret;
-
-	if (svflgs)
-		local_irq_save (flags);
-
-	writeb(addr >> 12, REG_PAGE);
-	ret = readw(ETHER1_RAM + ((addr & 4095) << 1));
-	if (svflgs)
-		local_irq_restore (flags);
-	return ret;
-}
-
-static inline void
-ether1_outw_p (struct net_device *dev, unsigned short val, int addr, int svflgs)
-{
-	unsigned long flags;
-
-	if (svflgs)
-		local_irq_save (flags);
-
-	writeb(addr >> 12, REG_PAGE);
-	writew(val, ETHER1_RAM + ((addr & 4095) << 1));
-	if (svflgs)
-		local_irq_restore (flags);
-}
-
-/*
- * Some inline assembler to allow fast transfers on to/off of the card.
- * Since this driver depends on some features presented by the ARM
- * specific architecture, and that you can't configure this driver
- * without specifiing ARM mode, this is not a problem.
- *
- * This routine is essentially an optimised memcpy from the card's
- * onboard RAM to kernel memory.
- */
-static void
-ether1_writebuffer (struct net_device *dev, void *data, unsigned int start, unsigned int length)
-{
-	unsigned int page, thislen, offset;
-	void __iomem *addr;
-
-	offset = start & 4095;
-	page = start >> 12;
-	addr = ETHER1_RAM + (offset << 1);
-
-	if (offset + length > 4096)
-		thislen = 4096 - offset;
-	else
-		thislen = length;
-
-	do {
-		int used;
-
-		writeb(page, REG_PAGE);
-		length -= thislen;
-
-		__asm__ __volatile__(
-	"subs	%3, %3, #2\n\
-	bmi	2f\n\
-1:	ldr	%0, [%1], #2\n\
-	mov	%0, %0, lsl #16\n\
-	orr	%0, %0, %0, lsr #16\n\
-	str	%0, [%2], #4\n\
-	subs	%3, %3, #2\n\
-	bmi	2f\n\
-	ldr	%0, [%1], #2\n\
-	mov	%0, %0, lsl #16\n\
-	orr	%0, %0, %0, lsr #16\n\
-	str	%0, [%2], #4\n\
-	subs	%3, %3, #2\n\
-	bmi	2f\n\
-	ldr	%0, [%1], #2\n\
-	mov	%0, %0, lsl #16\n\
-	orr	%0, %0, %0, lsr #16\n\
-	str	%0, [%2], #4\n\
-	subs	%3, %3, #2\n\
-	bmi	2f\n\
-	ldr	%0, [%1], #2\n\
-	mov	%0, %0, lsl #16\n\
-	orr	%0, %0, %0, lsr #16\n\
-	str	%0, [%2], #4\n\
-	subs	%3, %3, #2\n\
-	bpl	1b\n\
-2:	adds	%3, %3, #1\n\
-	ldreqb	%0, [%1]\n\
-	streqb	%0, [%2]"
-		: "=&r" (used), "=&r" (data)
-		: "r"  (addr), "r" (thislen), "1" (data));
-
-		addr = ETHER1_RAM;
-
-		thislen = length;
-		if (thislen > 4096)
-			thislen = 4096;
-		page++;
-	} while (thislen);
-}
-
-static void
-ether1_readbuffer (struct net_device *dev, void *data, unsigned int start, unsigned int length)
-{
-	unsigned int page, thislen, offset;
-	void __iomem *addr;
-
-	offset = start & 4095;
-	page = start >> 12;
-	addr = ETHER1_RAM + (offset << 1);
-
-	if (offset + length > 4096)
-		thislen = 4096 - offset;
-	else
-		thislen = length;
-
-	do {
-		int used;
-
-		writeb(page, REG_PAGE);
-		length -= thislen;
-
-		__asm__ __volatile__(
-	"subs	%3, %3, #2\n\
-	bmi	2f\n\
-1:	ldr	%0, [%2], #4\n\
-	strb	%0, [%1], #1\n\
-	mov	%0, %0, lsr #8\n\
-	strb	%0, [%1], #1\n\
-	subs	%3, %3, #2\n\
-	bmi	2f\n\
-	ldr	%0, [%2], #4\n\
-	strb	%0, [%1], #1\n\
-	mov	%0, %0, lsr #8\n\
-	strb	%0, [%1], #1\n\
-	subs	%3, %3, #2\n\
-	bmi	2f\n\
-	ldr	%0, [%2], #4\n\
-	strb	%0, [%1], #1\n\
-	mov	%0, %0, lsr #8\n\
-	strb	%0, [%1], #1\n\
-	subs	%3, %3, #2\n\
-	bmi	2f\n\
-	ldr	%0, [%2], #4\n\
-	strb	%0, [%1], #1\n\
-	mov	%0, %0, lsr #8\n\
-	strb	%0, [%1], #1\n\
-	subs	%3, %3, #2\n\
-	bpl	1b\n\
-2:	adds	%3, %3, #1\n\
-	ldreqb	%0, [%2]\n\
-	streqb	%0, [%1]"
-		: "=&r" (used), "=&r" (data)
-		: "r"  (addr), "r" (thislen), "1" (data));
-
-		addr = ETHER1_RAM;
-
-		thislen = length;
-		if (thislen > 4096)
-			thislen = 4096;
-		page++;
-	} while (thislen);
-}
-
-static int __devinit
-ether1_ramtest(struct net_device *dev, unsigned char byte)
-{
-	unsigned char *buffer = kmalloc (BUFFER_SIZE, GFP_KERNEL);
-	int i, ret = BUFFER_SIZE;
-	int max_errors = 15;
-	int bad = -1;
-	int bad_start = 0;
-
-	if (!buffer)
-		return 1;
-
-	memset (buffer, byte, BUFFER_SIZE);
-	ether1_writebuffer (dev, buffer, 0, BUFFER_SIZE);
-	memset (buffer, byte ^ 0xff, BUFFER_SIZE);
-	ether1_readbuffer (dev, buffer, 0, BUFFER_SIZE);
-
-	for (i = 0; i < BUFFER_SIZE; i++) {
-		if (buffer[i] != byte) {
-			if (max_errors >= 0 && bad != buffer[i]) {
-				if (bad != -1)
-					printk ("\n");
-				printk (KERN_CRIT "%s: RAM failed with (%02X instead of %02X) at 0x%04X",
-					dev->name, buffer[i], byte, i);
-				ret = -ENODEV;
-				max_errors --;
-				bad = buffer[i];
-				bad_start = i;
-			}
-		} else {
-			if (bad != -1) {
-			    	if (bad_start == i - 1)
-					printk ("\n");
-				else
-					printk (" - 0x%04X\n", i - 1);
-				bad = -1;
-			}
-		}
-	}
-
-	if (bad != -1)
-		printk (" - 0x%04X\n", BUFFER_SIZE);
-	kfree (buffer);
-
-	return ret;
-}
-
-static int
-ether1_reset (struct net_device *dev)
-{
-	writeb(CTRL_RST|CTRL_ACK, REG_CONTROL);
-	return BUS_16;
-}
-
-static int __devinit
-ether1_init_2(struct net_device *dev)
-{
-	int i;
-	dev->mem_start = 0;
-
-	i = ether1_ramtest (dev, 0x5a);
-
-	if (i > 0)
-		i = ether1_ramtest (dev, 0x1e);
-
-	if (i <= 0)
-	    	return -ENODEV;
-
-	dev->mem_end = i;
-	return 0;
-}
-
-/*
- * These are the structures that are loaded into the ether RAM card to
- * initialise the 82586
- */
-
-/* at 0x0100 */
-#define NOP_ADDR	(TX_AREA_START)
-#define NOP_SIZE	(0x06)
-static nop_t  init_nop  = {
-	0,
-	CMD_NOP,
-	NOP_ADDR
-};
-
-/* at 0x003a */
-#define TDR_ADDR	(0x003a)
-#define TDR_SIZE	(0x08)
-static tdr_t  init_tdr	= {
-	0,
-	CMD_TDR | CMD_INTR,
-	NOP_ADDR,
-	0
-};
-
-/* at 0x002e */
-#define MC_ADDR		(0x002e)
-#define MC_SIZE		(0x0c)
-static mc_t   init_mc   = {
-	0,
-	CMD_SETMULTICAST,
-	TDR_ADDR,
-	0,
-	{ { 0, } }
-};
-
-/* at 0x0022 */
-#define SA_ADDR		(0x0022)
-#define SA_SIZE		(0x0c)
-static sa_t   init_sa   = {
-	0,
-	CMD_SETADDRESS,
-	MC_ADDR,
-	{ 0, }
-};
-
-/* at 0x0010 */
-#define CFG_ADDR	(0x0010)
-#define CFG_SIZE	(0x12)
-static cfg_t  init_cfg  = {
-	0,
-	CMD_CONFIG,
-	SA_ADDR,
-	8,
-	8,
-	CFG8_SRDY,
-	CFG9_PREAMB8 | CFG9_ADDRLENBUF | CFG9_ADDRLEN(6),
-	0,
-	0x60,
-	0,
-	CFG13_RETRY(15) | CFG13_SLOTH(2),
-	0,
-};
-
-/* at 0x0000 */
-#define SCB_ADDR	(0x0000)
-#define SCB_SIZE	(0x10)
-static scb_t  init_scb  = {
-	0,
-	SCB_CMDACKRNR | SCB_CMDACKCNA | SCB_CMDACKFR | SCB_CMDACKCX,
-	CFG_ADDR,
-	RX_AREA_START,
-	0,
-	0,
-	0,
-	0
-};
-
-/* at 0xffee */
-#define ISCP_ADDR	(0xffee)
-#define ISCP_SIZE	(0x08)
-static iscp_t init_iscp = {
-	1,
-	SCB_ADDR,
-	0x0000,
-	0x0000
-};
-
-/* at 0xfff6 */
-#define SCP_ADDR	(0xfff6)
-#define SCP_SIZE	(0x0a)
-static scp_t  init_scp  = {
-	SCP_SY_16BBUS,
-	{ 0, 0 },
-	ISCP_ADDR,
-	0
-};
-
-#define RFD_SIZE	(0x16)
-static rfd_t  init_rfd	= {
-	0,
-	0,
-	0,
-	0,
-	{ 0, },
-	{ 0, },
-	0
-};
-
-#define RBD_SIZE	(0x0a)
-static rbd_t  init_rbd	= {
-	0,
-	0,
-	0,
-	0,
-	ETH_FRAME_LEN + 8
-};
-
-#define TX_SIZE		(0x08)
-#define TBD_SIZE	(0x08)
-
-static int
-ether1_init_for_open (struct net_device *dev)
-{
-	int i, status, addr, next, next2;
-	int failures = 0;
-	unsigned long timeout;
-
-	writeb(CTRL_RST|CTRL_ACK, REG_CONTROL);
-
-	for (i = 0; i < 6; i++)
-		init_sa.sa_addr[i] = dev->dev_addr[i];
-
-	/* load data structures into ether1 RAM */
-	ether1_writebuffer (dev, &init_scp,  SCP_ADDR,  SCP_SIZE);
-	ether1_writebuffer (dev, &init_iscp, ISCP_ADDR, ISCP_SIZE);
-	ether1_writebuffer (dev, &init_scb,  SCB_ADDR,  SCB_SIZE);
-	ether1_writebuffer (dev, &init_cfg,  CFG_ADDR,  CFG_SIZE);
-	ether1_writebuffer (dev, &init_sa,   SA_ADDR,   SA_SIZE);
-	ether1_writebuffer (dev, &init_mc,   MC_ADDR,   MC_SIZE);
-	ether1_writebuffer (dev, &init_tdr,  TDR_ADDR,  TDR_SIZE);
-	ether1_writebuffer (dev, &init_nop,  NOP_ADDR,  NOP_SIZE);
-
-	if (ether1_readw(dev, CFG_ADDR, cfg_t, cfg_command, NORMALIRQS) != CMD_CONFIG) {
-		printk (KERN_ERR "%s: detected either RAM fault or compiler bug\n",
-			dev->name);
-		return 1;
-	}
-
-	/*
-	 * setup circularly linked list of { rfd, rbd, buffer }, with
-	 * all rfds circularly linked, rbds circularly linked.
-	 * First rfd is linked to scp, first rbd is linked to first
-	 * rfd.  Last rbd has a suspend command.
-	 */
-	addr = RX_AREA_START;
-	do {
-		next = addr + RFD_SIZE + RBD_SIZE + ETH_FRAME_LEN + 10;
-		next2 = next + RFD_SIZE + RBD_SIZE + ETH_FRAME_LEN + 10;
-
-		if (next2 >= RX_AREA_END) {
-			next = RX_AREA_START;
-			init_rfd.rfd_command = RFD_CMDEL | RFD_CMDSUSPEND;
-			priv(dev)->rx_tail = addr;
-		} else
-			init_rfd.rfd_command = 0;
-		if (addr == RX_AREA_START)
-			init_rfd.rfd_rbdoffset = addr + RFD_SIZE;
-		else
-			init_rfd.rfd_rbdoffset = 0;
-		init_rfd.rfd_link = next;
-		init_rbd.rbd_link = next + RFD_SIZE;
-		init_rbd.rbd_bufl = addr + RFD_SIZE + RBD_SIZE;
-
-		ether1_writebuffer (dev, &init_rfd, addr, RFD_SIZE);
-		ether1_writebuffer (dev, &init_rbd, addr + RFD_SIZE, RBD_SIZE);
-		addr = next;
-	} while (next2 < RX_AREA_END);
-
-	priv(dev)->tx_link = NOP_ADDR;
-	priv(dev)->tx_head = NOP_ADDR + NOP_SIZE;
-	priv(dev)->tx_tail = TDR_ADDR;
-	priv(dev)->rx_head = RX_AREA_START;
-
-	/* release reset & give 586 a prod */
-	priv(dev)->resetting = 1;
-	priv(dev)->initialising = 1;
-	writeb(CTRL_RST, REG_CONTROL);
-	writeb(0, REG_CONTROL);
-	writeb(CTRL_CA, REG_CONTROL);
-
-	/* 586 should now unset iscp.busy */
-	timeout = jiffies + HZ/2;
-	while (ether1_readw(dev, ISCP_ADDR, iscp_t, iscp_busy, DISABLEIRQS) == 1) {
-		if (time_after(jiffies, timeout)) {
-			printk (KERN_WARNING "%s: can't initialise 82586: iscp is busy\n", dev->name);
-			return 1;
-		}
-	}
-
-	/* check status of commands that we issued */
-	timeout += HZ/10;
-	while (((status = ether1_readw(dev, CFG_ADDR, cfg_t, cfg_status, DISABLEIRQS))
-			& STAT_COMPLETE) == 0) {
-		if (time_after(jiffies, timeout))
-			break;
-	}
-
-	if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
-		printk (KERN_WARNING "%s: can't initialise 82586: config status %04X\n", dev->name, status);
-		printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
-			ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
-			ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
-			ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
-			ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
-		failures += 1;
-	}
-
-	timeout += HZ/10;
-	while (((status = ether1_readw(dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS))
-			& STAT_COMPLETE) == 0) {
-		if (time_after(jiffies, timeout))
-			break;
-	}
-
-	if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
-		printk (KERN_WARNING "%s: can't initialise 82586: set address status %04X\n", dev->name, status);
-		printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
-			ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
-			ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
-			ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
-			ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
-		failures += 1;
-	}
-
-	timeout += HZ/10;
-	while (((status = ether1_readw(dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS))
-			& STAT_COMPLETE) == 0) {
-		if (time_after(jiffies, timeout))
-			break;
-	}
-
-	if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
-		printk (KERN_WARNING "%s: can't initialise 82586: set multicast status %04X\n", dev->name, status);
-		printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
-			ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
-			ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
-			ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
-			ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
-		failures += 1;
-	}
-
-	timeout += HZ;
-	while (((status = ether1_readw(dev, TDR_ADDR, tdr_t, tdr_status, DISABLEIRQS))
-			& STAT_COMPLETE) == 0) {
-		if (time_after(jiffies, timeout))
-			break;
-	}
-
-	if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
-		printk (KERN_WARNING "%s: can't tdr (ignored)\n", dev->name);
-		printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
-			ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
-			ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
-			ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
-			ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
-	} else {
-		status = ether1_readw(dev, TDR_ADDR, tdr_t, tdr_result, DISABLEIRQS);
-		if (status & TDR_XCVRPROB)
-			printk (KERN_WARNING "%s: i/f failed tdr: transceiver problem\n", dev->name);
-		else if ((status & (TDR_SHORT|TDR_OPEN)) && (status & TDR_TIME)) {
-#ifdef FANCY
-			printk (KERN_WARNING "%s: i/f failed tdr: cable %s %d.%d us away\n", dev->name,
-				status & TDR_SHORT ? "short" : "open", (status & TDR_TIME) / 10,
-				(status & TDR_TIME) % 10);
-#else
-			printk (KERN_WARNING "%s: i/f failed tdr: cable %s %d clks away\n", dev->name,
-				status & TDR_SHORT ? "short" : "open", (status & TDR_TIME));
-#endif
-		}
-	}
-
-	if (failures)
-		ether1_reset (dev);
-	return failures ? 1 : 0;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int
-ether1_txalloc (struct net_device *dev, int size)
-{
-	int start, tail;
-
-	size = (size + 1) & ~1;
-	tail = priv(dev)->tx_tail;
-
-	if (priv(dev)->tx_head + size > TX_AREA_END) {
-		if (tail > priv(dev)->tx_head)
-			return -1;
-		start = TX_AREA_START;
-		if (start + size > tail)
-			return -1;
-		priv(dev)->tx_head = start + size;
-	} else {
-		if (priv(dev)->tx_head < tail && (priv(dev)->tx_head + size) > tail)
-			return -1;
-		start = priv(dev)->tx_head;
-		priv(dev)->tx_head += size;
-	}
-
-	return start;
-}
-
-static int
-ether1_open (struct net_device *dev)
-{
-	if (!is_valid_ether_addr(dev->dev_addr)) {
-		printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
-			dev->name);
-		return -EINVAL;
-	}
-
-	if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev))
-		return -EAGAIN;
-
-	if (ether1_init_for_open (dev)) {
-		free_irq (dev->irq, dev);
-		return -EAGAIN;
-	}
-
-	netif_start_queue(dev);
-
-	return 0;
-}
-
-static void
-ether1_timeout(struct net_device *dev)
-{
-	printk(KERN_WARNING "%s: transmit timeout, network cable problem?\n",
-		dev->name);
-	printk(KERN_WARNING "%s: resetting device\n", dev->name);
-
-	ether1_reset (dev);
-
-	if (ether1_init_for_open (dev))
-		printk (KERN_ERR "%s: unable to restart interface\n", dev->name);
-
-	dev->stats.tx_errors++;
-	netif_wake_queue(dev);
-}
-
-static int
-ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
-{
-	int tmp, tst, nopaddr, txaddr, tbdaddr, dataddr;
-	unsigned long flags;
-	tx_t tx;
-	tbd_t tbd;
-	nop_t nop;
-
-	if (priv(dev)->restart) {
-		printk(KERN_WARNING "%s: resetting device\n", dev->name);
-
-		ether1_reset(dev);
-
-		if (ether1_init_for_open(dev))
-			printk(KERN_ERR "%s: unable to restart interface\n", dev->name);
-		else
-			priv(dev)->restart = 0;
-	}
-
-	if (skb->len < ETH_ZLEN) {
-		if (skb_padto(skb, ETH_ZLEN))
-			goto out;
-	}
-
-	/*
-	 * insert packet followed by a nop
-	 */
-	txaddr = ether1_txalloc (dev, TX_SIZE);
-	tbdaddr = ether1_txalloc (dev, TBD_SIZE);
-	dataddr = ether1_txalloc (dev, skb->len);
-	nopaddr = ether1_txalloc (dev, NOP_SIZE);
-
-	tx.tx_status = 0;
-	tx.tx_command = CMD_TX | CMD_INTR;
-	tx.tx_link = nopaddr;
-	tx.tx_tbdoffset = tbdaddr;
-	tbd.tbd_opts = TBD_EOL | skb->len;
-	tbd.tbd_link = I82586_NULL;
-	tbd.tbd_bufl = dataddr;
-	tbd.tbd_bufh = 0;
-	nop.nop_status = 0;
-	nop.nop_command = CMD_NOP;
-	nop.nop_link = nopaddr;
-
-	local_irq_save(flags);
-	ether1_writebuffer (dev, &tx, txaddr, TX_SIZE);
-	ether1_writebuffer (dev, &tbd, tbdaddr, TBD_SIZE);
-	ether1_writebuffer (dev, skb->data, dataddr, skb->len);
-	ether1_writebuffer (dev, &nop, nopaddr, NOP_SIZE);
-	tmp = priv(dev)->tx_link;
-	priv(dev)->tx_link = nopaddr;
-
-	/* now reset the previous nop pointer */
-	ether1_writew(dev, txaddr, tmp, nop_t, nop_link, NORMALIRQS);
-
-	local_irq_restore(flags);
-
-	/* handle transmit */
-
-	/* check to see if we have room for a full sized ether frame */
-	tmp = priv(dev)->tx_head;
-	tst = ether1_txalloc (dev, TX_SIZE + TBD_SIZE + NOP_SIZE + ETH_FRAME_LEN);
-	priv(dev)->tx_head = tmp;
-	dev_kfree_skb (skb);
-
-	if (tst == -1)
-		netif_stop_queue(dev);
-
- out:
-	return NETDEV_TX_OK;
-}
-
-static void
-ether1_xmit_done (struct net_device *dev)
-{
-	nop_t nop;
-	int caddr, tst;
-
-	caddr = priv(dev)->tx_tail;
-
-again:
-	ether1_readbuffer (dev, &nop, caddr, NOP_SIZE);
-
-	switch (nop.nop_command & CMD_MASK) {
-	case CMD_TDR:
-		/* special case */
-		if (ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
-				!= (unsigned short)I82586_NULL) {
-			ether1_writew(dev, SCB_CMDCUCSTART | SCB_CMDRXSTART, SCB_ADDR, scb_t,
-				    scb_command, NORMALIRQS);
-			writeb(CTRL_CA, REG_CONTROL);
-		}
-		priv(dev)->tx_tail = NOP_ADDR;
-		return;
-
-	case CMD_NOP:
-		if (nop.nop_link == caddr) {
-			if (priv(dev)->initialising == 0)
-				printk (KERN_WARNING "%s: strange command complete with no tx command!\n", dev->name);
-			else
-			        priv(dev)->initialising = 0;
-			return;
-		}
-		if (caddr == nop.nop_link)
-			return;
-		caddr = nop.nop_link;
-		goto again;
-
-	case CMD_TX:
-		if (nop.nop_status & STAT_COMPLETE)
-			break;
-		printk (KERN_ERR "%s: strange command complete without completed command\n", dev->name);
-		priv(dev)->restart = 1;
-		return;
-
-	default:
-		printk (KERN_WARNING "%s: strange command %d complete! (offset %04X)", dev->name,
-			nop.nop_command & CMD_MASK, caddr);
-		priv(dev)->restart = 1;
-		return;
-	}
-
-	while (nop.nop_status & STAT_COMPLETE) {
-		if (nop.nop_status & STAT_OK) {
-			dev->stats.tx_packets++;
-			dev->stats.collisions += (nop.nop_status & STAT_COLLISIONS);
-		} else {
-			dev->stats.tx_errors++;
-
-			if (nop.nop_status & STAT_COLLAFTERTX)
-				dev->stats.collisions++;
-			if (nop.nop_status & STAT_NOCARRIER)
-				dev->stats.tx_carrier_errors++;
-			if (nop.nop_status & STAT_TXLOSTCTS)
-				printk (KERN_WARNING "%s: cts lost\n", dev->name);
-			if (nop.nop_status & STAT_TXSLOWDMA)
-				dev->stats.tx_fifo_errors++;
-			if (nop.nop_status & STAT_COLLEXCESSIVE)
-				dev->stats.collisions += 16;
-		}
-
-		if (nop.nop_link == caddr) {
-			printk (KERN_ERR "%s: tx buffer chaining error: tx command points to itself\n", dev->name);
-			break;
-		}
-
-		caddr = nop.nop_link;
-		ether1_readbuffer (dev, &nop, caddr, NOP_SIZE);
-		if ((nop.nop_command & CMD_MASK) != CMD_NOP) {
-			printk (KERN_ERR "%s: tx buffer chaining error: no nop after tx command\n", dev->name);
-			break;
-		}
-
-		if (caddr == nop.nop_link)
-			break;
-
-		caddr = nop.nop_link;
-		ether1_readbuffer (dev, &nop, caddr, NOP_SIZE);
-		if ((nop.nop_command & CMD_MASK) != CMD_TX) {
-			printk (KERN_ERR "%s: tx buffer chaining error: no tx command after nop\n", dev->name);
-			break;
-		}
-	}
-	priv(dev)->tx_tail = caddr;
-
-	caddr = priv(dev)->tx_head;
-	tst = ether1_txalloc (dev, TX_SIZE + TBD_SIZE + NOP_SIZE + ETH_FRAME_LEN);
-	priv(dev)->tx_head = caddr;
-	if (tst != -1)
-		netif_wake_queue(dev);
-}
-
-static void
-ether1_recv_done (struct net_device *dev)
-{
-	int status;
-	int nexttail, rbdaddr;
-	rbd_t rbd;
-
-	do {
-		status = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_status, NORMALIRQS);
-		if ((status & RFD_COMPLETE) == 0)
-			break;
-
-		rbdaddr = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_rbdoffset, NORMALIRQS);
-		ether1_readbuffer (dev, &rbd, rbdaddr, RBD_SIZE);
-
-		if ((rbd.rbd_status & (RBD_EOF | RBD_ACNTVALID)) == (RBD_EOF | RBD_ACNTVALID)) {
-			int length = rbd.rbd_status & RBD_ACNT;
-			struct sk_buff *skb;
-
-			length = (length + 1) & ~1;
-			skb = dev_alloc_skb (length + 2);
-
-			if (skb) {
-				skb_reserve (skb, 2);
-
-				ether1_readbuffer (dev, skb_put (skb, length), rbd.rbd_bufl, length);
-
-				skb->protocol = eth_type_trans (skb, dev);
-				netif_rx (skb);
-				dev->stats.rx_packets++;
-			} else
-				dev->stats.rx_dropped++;
-		} else {
-			printk(KERN_WARNING "%s: %s\n", dev->name,
-				(rbd.rbd_status & RBD_EOF) ? "oversized packet" : "acnt not valid");
-			dev->stats.rx_dropped++;
-		}
-
-		nexttail = ether1_readw(dev, priv(dev)->rx_tail, rfd_t, rfd_link, NORMALIRQS);
-		/* nexttail should be rx_head */
-		if (nexttail != priv(dev)->rx_head)
-			printk(KERN_ERR "%s: receiver buffer chaining error (%04X != %04X)\n",
-				dev->name, nexttail, priv(dev)->rx_head);
-		ether1_writew(dev, RFD_CMDEL | RFD_CMDSUSPEND, nexttail, rfd_t, rfd_command, NORMALIRQS);
-		ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_command, NORMALIRQS);
-		ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_status, NORMALIRQS);
-		ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_rbdoffset, NORMALIRQS);
-	
-		priv(dev)->rx_tail = nexttail;
-		priv(dev)->rx_head = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_link, NORMALIRQS);
-	} while (1);
-}
-
-static irqreturn_t
-ether1_interrupt (int irq, void *dev_id)
-{
-	struct net_device *dev = (struct net_device *)dev_id;
-	int status;
-
-	status = ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS);
-
-	if (status) {
-		ether1_writew(dev, status & (SCB_STRNR | SCB_STCNA | SCB_STFR | SCB_STCX),
-			    SCB_ADDR, scb_t, scb_command, NORMALIRQS);
-		writeb(CTRL_CA | CTRL_ACK, REG_CONTROL);
-		if (status & SCB_STCX) {
-			ether1_xmit_done (dev);
-		}
-		if (status & SCB_STCNA) {
-			if (priv(dev)->resetting == 0)
-				printk (KERN_WARNING "%s: CU went not ready ???\n", dev->name);
-			else
-				priv(dev)->resetting += 1;
-			if (ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
-					!= (unsigned short)I82586_NULL) {
-				ether1_writew(dev, SCB_CMDCUCSTART, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
-				writeb(CTRL_CA, REG_CONTROL);
-			}
-			if (priv(dev)->resetting == 2)
-				priv(dev)->resetting = 0;
-		}
-		if (status & SCB_STFR) {
-			ether1_recv_done (dev);
-		}
-		if (status & SCB_STRNR) {
-			if (ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS) & SCB_STRXSUSP) {
-				printk (KERN_WARNING "%s: RU went not ready: RU suspended\n", dev->name);
-				ether1_writew(dev, SCB_CMDRXRESUME, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
-				writeb(CTRL_CA, REG_CONTROL);
-				dev->stats.rx_dropped++;	/* we suspended due to lack of buffer space */
-			} else
-				printk(KERN_WARNING "%s: RU went not ready: %04X\n", dev->name,
-					ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS));
-			printk (KERN_WARNING "RU ptr = %04X\n", ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset,
-						NORMALIRQS));
-		}
-	} else
-		writeb(CTRL_ACK, REG_CONTROL);
-
-	return IRQ_HANDLED;
-}
-
-static int
-ether1_close (struct net_device *dev)
-{
-	ether1_reset (dev);
-
-	free_irq(dev->irq, dev);
-
-	return 0;
-}
-
-/*
- * Set or clear the multicast filter for this adaptor.
- * num_addrs == -1	Promiscuous mode, receive all packets.
- * num_addrs == 0	Normal mode, clear multicast list.
- * num_addrs > 0	Multicast mode, receive normal and MC packets, and do
- *			best-effort filtering.
- */
-static void
-ether1_setmulticastlist (struct net_device *dev)
-{
-}
-
-/* ------------------------------------------------------------------------- */
-
-static void __devinit ether1_banner(void)
-{
-	static unsigned int version_printed = 0;
-
-	if (net_debug && version_printed++ == 0)
-		printk(KERN_INFO "%s", version);
-}
-
-static const struct net_device_ops ether1_netdev_ops = {
-	.ndo_open		= ether1_open,
-	.ndo_stop		= ether1_close,
-	.ndo_start_xmit		= ether1_sendpacket,
-	.ndo_set_multicast_list	= ether1_setmulticastlist,
-	.ndo_tx_timeout		= ether1_timeout,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address	= eth_mac_addr,
-};
-
-static int __devinit
-ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
-{
-	struct net_device *dev;
-	int i, ret = 0;
-
-	ether1_banner();
-
-	ret = ecard_request_resources(ec);
-	if (ret)
-		goto out;
-
-	dev = alloc_etherdev(sizeof(struct ether1_priv));
-	if (!dev) {
-		ret = -ENOMEM;
-		goto release;
-	}
-
-	SET_NETDEV_DEV(dev, &ec->dev);
-
-	dev->irq = ec->irq;
-	priv(dev)->base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
-	if (!priv(dev)->base) {
-		ret = -ENOMEM;
-		goto free;
-	}
-
-	if ((priv(dev)->bus_type = ether1_reset(dev)) == 0) {
-		ret = -ENODEV;
-		goto free;
-	}
-
-	for (i = 0; i < 6; i++)
-		dev->dev_addr[i] = readb(IDPROM_ADDRESS + (i << 2));
-
-	if (ether1_init_2(dev)) {
-		ret = -ENODEV;
-		goto free;
-	}
-
-	dev->netdev_ops		= &ether1_netdev_ops;
-	dev->watchdog_timeo	= 5 * HZ / 100;
-
-	ret = register_netdev(dev);
-	if (ret)
-		goto free;
-
-	printk(KERN_INFO "%s: ether1 in slot %d, %pM\n",
-		dev->name, ec->slot_no, dev->dev_addr);
-    
-	ecard_set_drvdata(ec, dev);
-	return 0;
-
- free:
-	free_netdev(dev);
- release:
-	ecard_release_resources(ec);
- out:
-	return ret;
-}
-
-static void __devexit ether1_remove(struct expansion_card *ec)
-{
-	struct net_device *dev = ecard_get_drvdata(ec);
-
-	ecard_set_drvdata(ec, NULL);	
-
-	unregister_netdev(dev);
-	free_netdev(dev);
-	ecard_release_resources(ec);
-}
-
-static const struct ecard_id ether1_ids[] = {
-	{ MANU_ACORN, PROD_ACORN_ETHER1 },
-	{ 0xffff, 0xffff }
-};
-
-static struct ecard_driver ether1_driver = {
-	.probe		= ether1_probe,
-	.remove		= __devexit_p(ether1_remove),
-	.id_table	= ether1_ids,
-	.drv = {
-		.name	= "ether1",
-	},
-};
-
-static int __init ether1_init(void)
-{
-	return ecard_register_driver(&ether1_driver);
-}
-
-static void __exit ether1_exit(void)
-{
-	ecard_remove_driver(&ether1_driver);
-}
-
-module_init(ether1_init);
-module_exit(ether1_exit);
-
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/arm/ether1.h linux-libre-3.2-gnu/drivers/net/arm/ether1.h
--- linux-libre-3.1-gnu/drivers/net/arm/ether1.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arm/ether1.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,280 +0,0 @@
-/*
- *  linux/drivers/acorn/net/ether1.h
- *
- *  Copyright (C) 1996 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.
- *
- *  Network driver for Acorn Ether1 cards.
- */
-
-#ifndef _LINUX_ether1_H
-#define _LINUX_ether1_H
-
-#ifdef __ETHER1_C
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifndef NET_DEBUG
-#define NET_DEBUG 0
-#endif
-
-#define priv(dev)	((struct ether1_priv *)netdev_priv(dev))
-
-/* Page register */
-#define REG_PAGE	(priv(dev)->base + 0x0000)
-
-/* Control register */
-#define REG_CONTROL	(priv(dev)->base + 0x0004)
-#define CTRL_RST	0x01
-#define CTRL_LOOPBACK	0x02
-#define CTRL_CA		0x04
-#define CTRL_ACK	0x08
-
-#define ETHER1_RAM	(priv(dev)->base + 0x2000)
-
-/* HW address */
-#define IDPROM_ADDRESS	(priv(dev)->base + 0x0024)
-
-struct ether1_priv {
-	void __iomem *base;
-	unsigned int tx_link;
-	unsigned int tx_head;
-	volatile unsigned int tx_tail;
-	volatile unsigned int rx_head;
-	volatile unsigned int rx_tail;
-	unsigned char bus_type;
-	unsigned char resetting;
-	unsigned char initialising : 1;
-	unsigned char restart      : 1;
-};
-
-#define I82586_NULL (-1)
-
-typedef struct { /* tdr */
-	unsigned short tdr_status;
-	unsigned short tdr_command;
-	unsigned short tdr_link;
-	unsigned short tdr_result;
-#define TDR_TIME	(0x7ff)
-#define TDR_SHORT	(1 << 12)
-#define TDR_OPEN	(1 << 13)
-#define TDR_XCVRPROB	(1 << 14)
-#define TDR_LNKOK	(1 << 15)
-} tdr_t;
-
-typedef struct { /* transmit */
-	unsigned short tx_status;
-	unsigned short tx_command;
-	unsigned short tx_link;
-	unsigned short tx_tbdoffset;
-} tx_t;
-
-typedef struct { /* tbd */
-	unsigned short tbd_opts;
-#define TBD_CNT		(0x3fff)
-#define TBD_EOL		(1 << 15)
-	unsigned short tbd_link;
-	unsigned short tbd_bufl;
-	unsigned short tbd_bufh;
-} tbd_t;
-
-typedef struct { /* rfd */
-	unsigned short rfd_status;
-#define RFD_NOEOF	(1 << 6)
-#define RFD_FRAMESHORT	(1 << 7)
-#define RFD_DMAOVRN	(1 << 8)
-#define RFD_NORESOURCES	(1 << 9)
-#define RFD_ALIGNERROR	(1 << 10)
-#define RFD_CRCERROR	(1 << 11)
-#define RFD_OK		(1 << 13)
-#define RFD_FDCONSUMED	(1 << 14)
-#define RFD_COMPLETE	(1 << 15)
-	unsigned short rfd_command;
-#define RFD_CMDSUSPEND	(1 << 14)
-#define RFD_CMDEL	(1 << 15)
-	unsigned short rfd_link;
-	unsigned short rfd_rbdoffset;
-	unsigned char  rfd_dest[6];
-	unsigned char  rfd_src[6];
-	unsigned short rfd_len;
-} rfd_t;
-
-typedef struct { /* rbd */
-	unsigned short rbd_status;
-#define RBD_ACNT	(0x3fff)
-#define RBD_ACNTVALID	(1 << 14)
-#define RBD_EOF		(1 << 15)
-	unsigned short rbd_link;
-	unsigned short rbd_bufl;
-	unsigned short rbd_bufh;
-	unsigned short rbd_len;
-} rbd_t;
-
-typedef struct { /* nop */
-	unsigned short nop_status;
-	unsigned short nop_command;
-	unsigned short nop_link;
-} nop_t;
-
-typedef struct { /* set multicast */
-	unsigned short mc_status;
-	unsigned short mc_command;
-	unsigned short mc_link;
-	unsigned short mc_cnt;
-	unsigned char  mc_addrs[1][6];
-} mc_t;
-
-typedef struct { /* set address */
-	unsigned short sa_status;
-	unsigned short sa_command;
-	unsigned short sa_link;
-	unsigned char  sa_addr[6];
-} sa_t;
-
-typedef struct { /* config command */
-	unsigned short cfg_status;
-	unsigned short cfg_command;
-	unsigned short cfg_link;
-	unsigned char  cfg_bytecnt;	/* size foll data: 4 - 12		 */
-	unsigned char  cfg_fifolim;	/* FIFO threshold			 */
-	unsigned char  cfg_byte8;
-#define CFG8_SRDY	(1 << 6)
-#define CFG8_SAVEBADF	(1 << 7)
-	unsigned char  cfg_byte9;
-#define CFG9_ADDRLEN(x)	(x)
-#define CFG9_ADDRLENBUF	(1 << 3)
-#define CFG9_PREAMB2	(0 << 4)
-#define CFG9_PREAMB4	(1 << 4)
-#define CFG9_PREAMB8	(2 << 4)
-#define CFG9_PREAMB16	(3 << 4)
-#define CFG9_ILOOPBACK	(1 << 6)
-#define CFG9_ELOOPBACK	(1 << 7)
-	unsigned char  cfg_byte10;
-#define CFG10_LINPRI(x)	(x)
-#define CFG10_ACR(x)	(x << 4)
-#define CFG10_BOFMET	(1 << 7)
-	unsigned char  cfg_ifs;
-	unsigned char  cfg_slotl;
-	unsigned char  cfg_byte13;
-#define CFG13_SLOTH(x)	(x)
-#define CFG13_RETRY(x)	(x << 4)
-	unsigned char  cfg_byte14;
-#define CFG14_PROMISC	(1 << 0)
-#define CFG14_DISBRD	(1 << 1)
-#define CFG14_MANCH	(1 << 2)
-#define CFG14_TNCRS	(1 << 3)
-#define CFG14_NOCRC	(1 << 4)
-#define CFG14_CRC16	(1 << 5)
-#define CFG14_BTSTF	(1 << 6)
-#define CFG14_FLGPAD	(1 << 7)
-	unsigned char  cfg_byte15;
-#define CFG15_CSTF(x)	(x)
-#define CFG15_ICSS	(1 << 3)
-#define CFG15_CDTF(x)	(x << 4)
-#define CFG15_ICDS	(1 << 7)
-	unsigned short cfg_minfrmlen;
-} cfg_t;
-
-typedef struct { /* scb */
-	unsigned short scb_status;	/* status of 82586			*/
-#define SCB_STRXMASK		(7 << 4)	/* Receive unit status		*/
-#define SCB_STRXIDLE		(0 << 4)	/* Idle				*/
-#define SCB_STRXSUSP		(1 << 4)	/* Suspended			*/
-#define SCB_STRXNRES		(2 << 4)	/* No resources			*/
-#define SCB_STRXRDY		(4 << 4)	/* Ready			*/
-#define SCB_STCUMASK		(7 << 8)	/* Command unit status		*/
-#define SCB_STCUIDLE		(0 << 8)	/* Idle				*/
-#define SCB_STCUSUSP		(1 << 8)	/* Suspended			*/
-#define SCB_STCUACTV		(2 << 8)	/* Active			*/
-#define SCB_STRNR		(1 << 12)	/* Receive unit not ready	*/
-#define SCB_STCNA		(1 << 13)	/* Command unit not ready	*/
-#define SCB_STFR		(1 << 14)	/* Frame received		*/
-#define SCB_STCX		(1 << 15)	/* Command completed		*/
-	unsigned short scb_command;	/* Next command				*/
-#define SCB_CMDRXSTART		(1 << 4)	/* Start (at rfa_offset)	*/
-#define SCB_CMDRXRESUME		(2 << 4)	/* Resume reception		*/
-#define SCB_CMDRXSUSPEND	(3 << 4)	/* Suspend reception		*/
-#define SCB_CMDRXABORT		(4 << 4)	/* Abort reception		*/
-#define SCB_CMDCUCSTART		(1 << 8)	/* Start (at cbl_offset)	*/
-#define SCB_CMDCUCRESUME	(2 << 8)	/* Resume execution		*/
-#define SCB_CMDCUCSUSPEND	(3 << 8)	/* Suspend execution		*/
-#define SCB_CMDCUCABORT		(4 << 8)	/* Abort execution		*/
-#define SCB_CMDACKRNR		(1 << 12)	/* Ack RU not ready		*/
-#define SCB_CMDACKCNA		(1 << 13)	/* Ack CU not ready		*/
-#define SCB_CMDACKFR		(1 << 14)	/* Ack Frame received		*/
-#define SCB_CMDACKCX		(1 << 15)	/* Ack Command complete		*/
-	unsigned short scb_cbl_offset;	/* Offset of first command unit		*/
-	unsigned short scb_rfa_offset;	/* Offset of first receive frame area	*/
-	unsigned short scb_crc_errors;	/* Properly aligned frame with CRC error*/
-	unsigned short scb_aln_errors;	/* Misaligned frames			*/
-	unsigned short scb_rsc_errors;	/* Frames lost due to no space		*/
-	unsigned short scb_ovn_errors;	/* Frames lost due to slow bus		*/
-} scb_t;
-
-typedef struct { /* iscp */
-	unsigned short iscp_busy;	/* set by CPU before CA			*/
-	unsigned short iscp_offset;	/* offset of SCB			*/
-	unsigned short iscp_basel;	/* base of SCB				*/
-	unsigned short iscp_baseh;
-} iscp_t;
-
-    /* this address must be 0xfff6 */
-typedef struct { /* scp */
-	unsigned short scp_sysbus;	/* bus size */
-#define SCP_SY_16BBUS	0x00
-#define SCP_SY_8BBUS	0x01
-	unsigned short scp_junk[2];	/* junk */
-	unsigned short scp_iscpl;	/* lower 16 bits of iscp */
-	unsigned short scp_iscph;	/* upper 16 bits of iscp */
-} scp_t;
-
-/* commands */
-#define CMD_NOP			0
-#define CMD_SETADDRESS		1
-#define CMD_CONFIG		2
-#define CMD_SETMULTICAST	3
-#define CMD_TX			4
-#define CMD_TDR			5
-#define CMD_DUMP		6
-#define CMD_DIAGNOSE		7
-
-#define CMD_MASK		7
-
-#define CMD_INTR		(1 << 13)
-#define CMD_SUSP		(1 << 14)
-#define CMD_EOL			(1 << 15)
-
-#define STAT_COLLISIONS		(15)
-#define STAT_COLLEXCESSIVE	(1 << 5)
-#define STAT_COLLAFTERTX	(1 << 6)
-#define STAT_TXDEFERRED		(1 << 7)
-#define STAT_TXSLOWDMA		(1 << 8)
-#define STAT_TXLOSTCTS		(1 << 9)
-#define STAT_NOCARRIER		(1 << 10)
-#define STAT_FAIL		(1 << 11)
-#define STAT_ABORTED		(1 << 12)
-#define STAT_OK			(1 << 13)
-#define STAT_BUSY		(1 << 14)
-#define STAT_COMPLETE		(1 << 15)
-#endif
-#endif
-
-/*
- * Ether1 card definitions:
- *
- * FAST accesses:
- *	+0	Page register
- * 			16 pages
- *	+4	Control
- *			'1' = reset
- *			'2' = loopback
- *			'4' = CA
- *			'8' = int ack
- *
- * RAM at address + 0x2000
- * Pod. Prod id = 3
- * Words after ID block [base + 8 words]
- *	+0 pcb issue (0x0c and 0xf3 invalid)
- *	+1 - +6 eth hw address
- */
diff -druN linux-libre-3.1-gnu/drivers/net/arm/ether3.c linux-libre-3.2-gnu/drivers/net/arm/ether3.c
--- linux-libre-3.1-gnu/drivers/net/arm/ether3.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arm/ether3.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,918 +0,0 @@
-/*
- *  linux/drivers/acorn/net/ether3.c
- *
- *  Copyright (C) 1995-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.
- *
- * SEEQ nq8005 ethernet driver for Acorn/ANT Ether3 card
- *  for Acorn machines
- *
- * By Russell King, with some suggestions from borris@ant.co.uk
- *
- * Changelog:
- * 1.04	RMK	29/02/1996	Won't pass packets that are from our ethernet
- *				address up to the higher levels - they're
- *				silently ignored.  I/F can now be put into
- *				multicast mode.  Receiver routine optimised.
- * 1.05	RMK	30/02/1996	Now claims interrupt at open when part of
- *				the kernel rather than when a module.
- * 1.06	RMK	02/03/1996	Various code cleanups
- * 1.07	RMK	13/10/1996	Optimised interrupt routine and transmit
- *				routines.
- * 1.08	RMK	14/10/1996	Fixed problem with too many packets,
- *				prevented the kernel message about dropped
- *				packets appearing too many times a second.
- *				Now does not disable all IRQs, only the IRQ
- *				used by this card.
- * 1.09	RMK	10/11/1996	Only enables TX irq when buffer space is low,
- *				but we still service the TX queue if we get a
- *				RX interrupt.
- * 1.10	RMK	15/07/1997	Fixed autoprobing of NQ8004.
- * 1.11	RMK	16/11/1997	Fixed autoprobing of NQ8005A.
- * 1.12	RMK	31/12/1997	Removed reference to dev_tint for Linux 2.1.
- *      RMK	27/06/1998	Changed asm/delay.h to linux/delay.h.
- * 1.13	RMK	29/06/1998	Fixed problem with transmission of packets.
- *				Chip seems to have a bug in, whereby if the
- *				packet starts two bytes from the end of the
- *				buffer, it corrupts the receiver chain, and
- *				never updates the transmit status correctly.
- * 1.14	RMK	07/01/1998	Added initial code for ETHERB addressing.
- * 1.15	RMK	30/04/1999	More fixes to the transmit routine for buggy
- *				hardware.
- * 1.16	RMK	10/02/2000	Updated for 2.3.43
- * 1.17	RMK	13/05/2000	Updated for 2.3.99-pre8
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/ecard.h>
-#include <asm/io.h>
-
-static char version[] __devinitdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
-
-#include "ether3.h"
-
-static unsigned int net_debug = NET_DEBUG;
-
-static void	ether3_setmulticastlist(struct net_device *dev);
-static int	ether3_rx(struct net_device *dev, unsigned int maxcnt);
-static void	ether3_tx(struct net_device *dev);
-static int	ether3_open (struct net_device *dev);
-static int	ether3_sendpacket (struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t ether3_interrupt (int irq, void *dev_id);
-static int	ether3_close (struct net_device *dev);
-static void	ether3_setmulticastlist (struct net_device *dev);
-static void	ether3_timeout(struct net_device *dev);
-
-#define BUS_16		2
-#define BUS_8		1
-#define BUS_UNKNOWN	0
-
-/* --------------------------------------------------------------------------- */
-
-typedef enum {
-	buffer_write,
-	buffer_read
-} buffer_rw_t;
-
-/*
- * ether3 read/write.  Slow things down a bit...
- * The SEEQ8005 doesn't like us writing to its registers
- * too quickly.
- */
-static inline void ether3_outb(int v, const void __iomem *r)
-{
-	writeb(v, r);
-	udelay(1);
-}
-
-static inline void ether3_outw(int v, const void __iomem *r)
-{
-	writew(v, r);
-	udelay(1);
-}
-#define ether3_inb(r)		({ unsigned int __v = readb((r)); udelay(1); __v; })
-#define ether3_inw(r)		({ unsigned int __v = readw((r)); udelay(1); __v; })
-
-static int
-ether3_setbuffer(struct net_device *dev, buffer_rw_t read, int start)
-{
-	int timeout = 1000;
-
-	ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
-	ether3_outw(priv(dev)->regs.command | CMD_FIFOWRITE, REG_COMMAND);
-
-	while ((ether3_inw(REG_STATUS) & STAT_FIFOEMPTY) == 0) {
-		if (!timeout--) {
-			printk("%s: setbuffer broken\n", dev->name);
-			priv(dev)->broken = 1;
-			return 1;
-		}
-		udelay(1);
-	}
-
-	if (read == buffer_read) {
-		ether3_outw(start, REG_DMAADDR);
-		ether3_outw(priv(dev)->regs.command | CMD_FIFOREAD, REG_COMMAND);
-	} else {
-		ether3_outw(priv(dev)->regs.command | CMD_FIFOWRITE, REG_COMMAND);
-		ether3_outw(start, REG_DMAADDR);
-	}
-	return 0;
-}
-
-/*
- * write data to the buffer memory
- */
-#define ether3_writebuffer(dev,data,length)			\
-	writesw(REG_BUFWIN, (data), (length) >> 1)
-
-#define ether3_writeword(dev,data)				\
-	writew((data), REG_BUFWIN)
-
-#define ether3_writelong(dev,data)	{			\
-	void __iomem *reg_bufwin = REG_BUFWIN;			\
-	writew((data), reg_bufwin);				\
-	writew((data) >> 16, reg_bufwin);			\
-}
-
-/*
- * read data from the buffer memory
- */
-#define ether3_readbuffer(dev,data,length)			\
-	readsw(REG_BUFWIN, (data), (length) >> 1)
-
-#define ether3_readword(dev)					\
-	readw(REG_BUFWIN)
-
-#define ether3_readlong(dev)	 				\
-	readw(REG_BUFWIN) | (readw(REG_BUFWIN) << 16)
-
-/*
- * Switch LED off...
- */
-static void ether3_ledoff(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *)data;
-	ether3_outw(priv(dev)->regs.config2 |= CFG2_CTRLO, REG_CONFIG2);
-}
-
-/*
- * switch LED on...
- */
-static inline void ether3_ledon(struct net_device *dev)
-{
-	del_timer(&priv(dev)->timer);
-	priv(dev)->timer.expires = jiffies + HZ / 50; /* leave on for 1/50th second */
-	priv(dev)->timer.data = (unsigned long)dev;
-	priv(dev)->timer.function = ether3_ledoff;
-	add_timer(&priv(dev)->timer);
-	if (priv(dev)->regs.config2 & CFG2_CTRLO)
-		ether3_outw(priv(dev)->regs.config2 &= ~CFG2_CTRLO, REG_CONFIG2);
-}
-
-/*
- * Read the ethernet address string from the on board rom.
- * This is an ascii string!!!
- */
-static int __devinit
-ether3_addr(char *addr, struct expansion_card *ec)
-{
-	struct in_chunk_dir cd;
-	char *s;
-	
-	if (ecard_readchunk(&cd, ec, 0xf5, 0) && (s = strchr(cd.d.string, '('))) {
-		int i;
-		for (i = 0; i<6; i++) {
-			addr[i] = simple_strtoul(s + 1, &s, 0x10);
-			if (*s != (i==5?')' : ':' ))
-				break;
-		}
-		if (i == 6)
-			return 0;
-	}
-	/* I wonder if we should even let the user continue in this case
-	 *   - no, it would be better to disable the device
-	 */
-	printk(KERN_ERR "ether3: Couldn't read a valid MAC address from card.\n");
-	return -ENODEV;
-}
-
-/* --------------------------------------------------------------------------- */
-
-static int __devinit
-ether3_ramtest(struct net_device *dev, unsigned char byte)
-{
-	unsigned char *buffer = kmalloc(RX_END, GFP_KERNEL);
-	int i,ret = 0;
-	int max_errors = 4;
-	int bad = -1;
-
-	if (!buffer)
-		return 1;
-
-	memset(buffer, byte, RX_END);
-	ether3_setbuffer(dev, buffer_write, 0);
-	ether3_writebuffer(dev, buffer, TX_END);
-	ether3_setbuffer(dev, buffer_write, RX_START);
-	ether3_writebuffer(dev, buffer + RX_START, RX_LEN);
-	memset(buffer, byte ^ 0xff, RX_END);
-	ether3_setbuffer(dev, buffer_read, 0);
-	ether3_readbuffer(dev, buffer, TX_END);
-	ether3_setbuffer(dev, buffer_read, RX_START);
-	ether3_readbuffer(dev, buffer + RX_START, RX_LEN);
-
-	for (i = 0; i < RX_END; i++) {
-		if (buffer[i] != byte) {
-			if (max_errors > 0 && bad != buffer[i]) {
-				printk("%s: RAM failed with (%02X instead of %02X) at 0x%04X",
-				       dev->name, buffer[i], byte, i);
-				ret = 2;
-				max_errors--;
-				bad = i;
-			}
-		} else {
-			if (bad != -1) {
-				if (bad != i - 1)
-					printk(" - 0x%04X\n", i - 1);
-				printk("\n");
-				bad = -1;
-			}
-		}
-	}
-	if (bad != -1)
-		printk(" - 0xffff\n");
-	kfree(buffer);
-
-	return ret;
-}
-
-/* ------------------------------------------------------------------------------- */
-
-static int __devinit ether3_init_2(struct net_device *dev)
-{
-	int i;
-
-	priv(dev)->regs.config1 = CFG1_RECVCOMPSTAT0|CFG1_DMABURST8;
-	priv(dev)->regs.config2 = CFG2_CTRLO|CFG2_RECVCRC|CFG2_ERRENCRC;
-	priv(dev)->regs.command = 0;
-
-	/*
-	 * Set up our hardware address
-	 */
-	ether3_outw(priv(dev)->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1);
-	for (i = 0; i < 6; i++)
-		ether3_outb(dev->dev_addr[i], REG_BUFWIN);
-
-	if (dev->flags & IFF_PROMISC)
-		priv(dev)->regs.config1 |= CFG1_RECVPROMISC;
-	else if (dev->flags & IFF_MULTICAST)
-		priv(dev)->regs.config1 |= CFG1_RECVSPECBRMULTI;
-	else
-		priv(dev)->regs.config1 |= CFG1_RECVSPECBROAD;
-
-	/*
-	 * There is a problem with the NQ8005 in that it occasionally loses the
-	 * last two bytes.  To get round this problem, we receive the CRC as
-	 * well.  That way, if we do lose the last two, then it doesn't matter.
-	 */
-	ether3_outw(priv(dev)->regs.config1 | CFG1_TRANSEND, REG_CONFIG1);
-	ether3_outw((TX_END>>8) - 1, REG_BUFWIN);
-	ether3_outw(priv(dev)->rx_head, REG_RECVPTR);
-	ether3_outw(0, REG_TRANSMITPTR);
-	ether3_outw(priv(dev)->rx_head >> 8, REG_RECVEND);
-	ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);
-	ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
-	ether3_outw(priv(dev)->regs.command, REG_COMMAND);
-
-	i = ether3_ramtest(dev, 0x5A);
-	if(i)
-		return i;
-	i = ether3_ramtest(dev, 0x1E);
-	if(i)
-		return i;
-
-	ether3_setbuffer(dev, buffer_write, 0);
-	ether3_writelong(dev, 0);
-	return 0;
-}
-
-static void
-ether3_init_for_open(struct net_device *dev)
-{
-	int i;
-
-	/* Reset the chip */
-	ether3_outw(CFG2_RESET, REG_CONFIG2);
-	udelay(4);
-
-	priv(dev)->regs.command = 0;
-	ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND);
-	while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON))
-		barrier();
-
-	ether3_outw(priv(dev)->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1);
-	for (i = 0; i < 6; i++)
-		ether3_outb(dev->dev_addr[i], REG_BUFWIN);
-
-	priv(dev)->tx_head	= 0;
-	priv(dev)->tx_tail	= 0;
-	priv(dev)->regs.config2 |= CFG2_CTRLO;
-	priv(dev)->rx_head	= RX_START;
-
-	ether3_outw(priv(dev)->regs.config1 | CFG1_TRANSEND, REG_CONFIG1);
-	ether3_outw((TX_END>>8) - 1, REG_BUFWIN);
-	ether3_outw(priv(dev)->rx_head, REG_RECVPTR);
-	ether3_outw(priv(dev)->rx_head >> 8, REG_RECVEND);
-	ether3_outw(0, REG_TRANSMITPTR);
-	ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);
-	ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
-
-	ether3_setbuffer(dev, buffer_write, 0);
-	ether3_writelong(dev, 0);
-
-	priv(dev)->regs.command = CMD_ENINTRX | CMD_ENINTTX;
-	ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND);
-}
-
-static inline int
-ether3_probe_bus_8(struct net_device *dev, int val)
-{
-	int write_low, write_high, read_low, read_high;
-
-	write_low = val & 255;
-	write_high = val >> 8;
-
-	printk(KERN_DEBUG "ether3_probe: write8 [%02X:%02X]", write_high, write_low);
-
-	ether3_outb(write_low, REG_RECVPTR);
-	ether3_outb(write_high, REG_RECVPTR + 4);
-
-	read_low = ether3_inb(REG_RECVPTR);
-	read_high = ether3_inb(REG_RECVPTR + 4);
-
-	printk(", read8 [%02X:%02X]\n", read_high, read_low);
-
-	return read_low == write_low && read_high == write_high;
-}
-
-static inline int
-ether3_probe_bus_16(struct net_device *dev, int val)
-{
-	int read_val;
-
-	ether3_outw(val, REG_RECVPTR);
-	read_val = ether3_inw(REG_RECVPTR);
-
-	printk(KERN_DEBUG "ether3_probe: write16 [%04X], read16 [%04X]\n", val, read_val);
-
-	return read_val == val;
-}
-
-/*
- * Open/initialize the board.  This is called (in the current kernel)
- * sometime after booting when the 'ifconfig' program is run.
- *
- * This routine should set everything up anew at each open, even
- * registers that "should" only need to be set once at boot, so that
- * there is non-reboot way to recover if something goes wrong.
- */
-static int
-ether3_open(struct net_device *dev)
-{
-	if (!is_valid_ether_addr(dev->dev_addr)) {
-		printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
-			dev->name);
-		return -EINVAL;
-	}
-
-	if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev))
-		return -EAGAIN;
-
-	ether3_init_for_open(dev);
-
-	netif_start_queue(dev);
-
-	return 0;
-}
-
-/*
- * The inverse routine to ether3_open().
- */
-static int
-ether3_close(struct net_device *dev)
-{
-	netif_stop_queue(dev);
-
-	disable_irq(dev->irq);
-
-	ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND);
-	priv(dev)->regs.command = 0;
-	while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON))
-		barrier();
-	ether3_outb(0x80, REG_CONFIG2 + 4);
-	ether3_outw(0, REG_COMMAND);
-
-	free_irq(dev->irq, dev);
-
-	return 0;
-}
-
-/*
- * Set or clear promiscuous/multicast mode filter for this adaptor.
- *
- * We don't attempt any packet filtering.  The card may have a SEEQ 8004
- * in which does not have the other ethernet address registers present...
- */
-static void ether3_setmulticastlist(struct net_device *dev)
-{
-	priv(dev)->regs.config1 &= ~CFG1_RECVPROMISC;
-
-	if (dev->flags & IFF_PROMISC) {
-		/* promiscuous mode */
-		priv(dev)->regs.config1 |= CFG1_RECVPROMISC;
-	} else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev)) {
-		priv(dev)->regs.config1 |= CFG1_RECVSPECBRMULTI;
-	} else
-		priv(dev)->regs.config1 |= CFG1_RECVSPECBROAD;
-
-	ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
-}
-
-static void ether3_timeout(struct net_device *dev)
-{
-	unsigned long flags;
-
-	del_timer(&priv(dev)->timer);
-
-	local_irq_save(flags);
-	printk(KERN_ERR "%s: transmit timed out, network cable problem?\n", dev->name);
-	printk(KERN_ERR "%s: state: { status=%04X cfg1=%04X cfg2=%04X }\n", dev->name,
-		ether3_inw(REG_STATUS), ether3_inw(REG_CONFIG1), ether3_inw(REG_CONFIG2));
-	printk(KERN_ERR "%s: { rpr=%04X rea=%04X tpr=%04X }\n", dev->name,
-		ether3_inw(REG_RECVPTR), ether3_inw(REG_RECVEND), ether3_inw(REG_TRANSMITPTR));
-	printk(KERN_ERR "%s: tx head=%X tx tail=%X\n", dev->name,
-		priv(dev)->tx_head, priv(dev)->tx_tail);
-	ether3_setbuffer(dev, buffer_read, priv(dev)->tx_tail);
-	printk(KERN_ERR "%s: packet status = %08X\n", dev->name, ether3_readlong(dev));
-	local_irq_restore(flags);
-
-	priv(dev)->regs.config2 |= CFG2_CTRLO;
-	dev->stats.tx_errors += 1;
-	ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);
-	priv(dev)->tx_head = priv(dev)->tx_tail = 0;
-
-	netif_wake_queue(dev);
-}
-
-/*
- * Transmit a packet
- */
-static int
-ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
-{
-	unsigned long flags;
-	unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-	unsigned int ptr, next_ptr;
-
-	if (priv(dev)->broken) {
-		dev_kfree_skb(skb);
-		dev->stats.tx_dropped++;
-		netif_start_queue(dev);
-		return NETDEV_TX_OK;
-	}
-
-	length = (length + 1) & ~1;
-	if (length != skb->len) {
-		if (skb_padto(skb, length))
-			goto out;
-	}
-
-	next_ptr = (priv(dev)->tx_head + 1) & 15;
-
-	local_irq_save(flags);
-
-	if (priv(dev)->tx_tail == next_ptr) {
-		local_irq_restore(flags);
-		return NETDEV_TX_BUSY;	/* unable to queue */
-	}
-
-	ptr		 = 0x600 * priv(dev)->tx_head;
-	priv(dev)->tx_head = next_ptr;
-	next_ptr	*= 0x600;
-
-#define TXHDR_FLAGS (TXHDR_TRANSMIT|TXHDR_CHAINCONTINUE|TXHDR_DATAFOLLOWS|TXHDR_ENSUCCESS)
-
-	ether3_setbuffer(dev, buffer_write, next_ptr);
-	ether3_writelong(dev, 0);
-	ether3_setbuffer(dev, buffer_write, ptr);
-	ether3_writelong(dev, 0);
-	ether3_writebuffer(dev, skb->data, length);
-	ether3_writeword(dev, htons(next_ptr));
-	ether3_writeword(dev, TXHDR_CHAINCONTINUE >> 16);
-	ether3_setbuffer(dev, buffer_write, ptr);
-	ether3_writeword(dev, htons((ptr + length + 4)));
-	ether3_writeword(dev, TXHDR_FLAGS >> 16);
-	ether3_ledon(dev);
-
-	if (!(ether3_inw(REG_STATUS) & STAT_TXON)) {
-		ether3_outw(ptr, REG_TRANSMITPTR);
-		ether3_outw(priv(dev)->regs.command | CMD_TXON, REG_COMMAND);
-	}
-
-	next_ptr = (priv(dev)->tx_head + 1) & 15;
-	local_irq_restore(flags);
-
-	dev_kfree_skb(skb);
-
-	if (priv(dev)->tx_tail == next_ptr)
-		netif_stop_queue(dev);
-
- out:
-	return NETDEV_TX_OK;
-}
-
-static irqreturn_t
-ether3_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = (struct net_device *)dev_id;
-	unsigned int status, handled = IRQ_NONE;
-
-#if NET_DEBUG > 1
-	if(net_debug & DEBUG_INT)
-		printk("eth3irq: %d ", irq);
-#endif
-
-	status = ether3_inw(REG_STATUS);
-
-	if (status & STAT_INTRX) {
-		ether3_outw(CMD_ACKINTRX | priv(dev)->regs.command, REG_COMMAND);
-		ether3_rx(dev, 12);
-		handled = IRQ_HANDLED;
-	}
-
-	if (status & STAT_INTTX) {
-		ether3_outw(CMD_ACKINTTX | priv(dev)->regs.command, REG_COMMAND);
-		ether3_tx(dev);
-		handled = IRQ_HANDLED;
-	}
-
-#if NET_DEBUG > 1
-	if(net_debug & DEBUG_INT)
-		printk("done\n");
-#endif
-	return handled;
-}
-
-/*
- * If we have a good packet(s), get it/them out of the buffers.
- */
-static int ether3_rx(struct net_device *dev, unsigned int maxcnt)
-{
-	unsigned int next_ptr = priv(dev)->rx_head, received = 0;
-
-	ether3_ledon(dev);
-
-	do {
-		unsigned int this_ptr, status;
-		unsigned char addrs[16];
-
-		/*
-		 * read the first 16 bytes from the buffer.
-		 * This contains the status bytes etc and ethernet addresses,
-		 * and we also check the source ethernet address to see if
-		 * it originated from us.
-		 */
-		{
-			unsigned int temp_ptr;
-			ether3_setbuffer(dev, buffer_read, next_ptr);
-			temp_ptr = ether3_readword(dev);
-			status = ether3_readword(dev);
-			if ((status & (RXSTAT_DONE | RXHDR_CHAINCONTINUE | RXHDR_RECEIVE)) !=
-				(RXSTAT_DONE | RXHDR_CHAINCONTINUE) || !temp_ptr)
-				break;
-
-			this_ptr = next_ptr + 4;
-			next_ptr = ntohs(temp_ptr);
-		}
-		ether3_setbuffer(dev, buffer_read, this_ptr);
-		ether3_readbuffer(dev, addrs+2, 12);
-
-if (next_ptr < RX_START || next_ptr >= RX_END) {
- int i;
- printk("%s: bad next pointer @%04X: ", dev->name, priv(dev)->rx_head);
- printk("%02X %02X %02X %02X ", next_ptr >> 8, next_ptr & 255, status & 255, status >> 8);
- for (i = 2; i < 14; i++)
-   printk("%02X ", addrs[i]);
- printk("\n");
- next_ptr = priv(dev)->rx_head;
- break;
-}
-		/*
- 		 * ignore our own packets...
-	 	 */
-		if (!(*(unsigned long *)&dev->dev_addr[0] ^ *(unsigned long *)&addrs[2+6]) &&
-		    !(*(unsigned short *)&dev->dev_addr[4] ^ *(unsigned short *)&addrs[2+10])) {
-			maxcnt ++; /* compensate for loopedback packet */
-			ether3_outw(next_ptr >> 8, REG_RECVEND);
-		} else
-		if (!(status & (RXSTAT_OVERSIZE|RXSTAT_CRCERROR|RXSTAT_DRIBBLEERROR|RXSTAT_SHORTPACKET))) {
-			unsigned int length = next_ptr - this_ptr;
-			struct sk_buff *skb;
-
-			if (next_ptr <= this_ptr)
-				length += RX_END - RX_START;
-
-			skb = dev_alloc_skb(length + 2);
-			if (skb) {
-				unsigned char *buf;
-
-				skb_reserve(skb, 2);
-				buf = skb_put(skb, length);
-				ether3_readbuffer(dev, buf + 12, length - 12);
-				ether3_outw(next_ptr >> 8, REG_RECVEND);
-				*(unsigned short *)(buf + 0)	= *(unsigned short *)(addrs + 2);
-				*(unsigned long *)(buf + 2)	= *(unsigned long *)(addrs + 4);
-				*(unsigned long *)(buf + 6)	= *(unsigned long *)(addrs + 8);
-				*(unsigned short *)(buf + 10)	= *(unsigned short *)(addrs + 12);
-				skb->protocol = eth_type_trans(skb, dev);
-				netif_rx(skb);
-				received ++;
-			} else
-				goto dropping;
-		} else {
-			struct net_device_stats *stats = &dev->stats;
-			ether3_outw(next_ptr >> 8, REG_RECVEND);
-			if (status & RXSTAT_OVERSIZE)	  stats->rx_over_errors ++;
-			if (status & RXSTAT_CRCERROR)	  stats->rx_crc_errors ++;
-			if (status & RXSTAT_DRIBBLEERROR) stats->rx_fifo_errors ++;
-			if (status & RXSTAT_SHORTPACKET)  stats->rx_length_errors ++;
-			stats->rx_errors++;
-		}
-	}
-	while (-- maxcnt);
-
-done:
-	dev->stats.rx_packets += received;
-	priv(dev)->rx_head = next_ptr;
-	/*
-	 * If rx went off line, then that means that the buffer may be full.  We
-	 * have dropped at least one packet.
-	 */
-	if (!(ether3_inw(REG_STATUS) & STAT_RXON)) {
-		dev->stats.rx_dropped++;
-    		ether3_outw(next_ptr, REG_RECVPTR);
-		ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND);
-	}
-
-	return maxcnt;
-
-dropping:{
-	static unsigned long last_warned;
-
-	ether3_outw(next_ptr >> 8, REG_RECVEND);
-	/*
-	 * Don't print this message too many times...
-	 */
-	if (time_after(jiffies, last_warned + 10 * HZ)) {
-		last_warned = jiffies;
-		printk("%s: memory squeeze, dropping packet.\n", dev->name);
-	}
-	dev->stats.rx_dropped++;
-	goto done;
-	}
-}
-
-/*
- * Update stats for the transmitted packet(s)
- */
-static void ether3_tx(struct net_device *dev)
-{
-	unsigned int tx_tail = priv(dev)->tx_tail;
-	int max_work = 14;
-
-	do {
-	    	unsigned long status;
-
-    		/*
-	    	 * Read the packet header
-    		 */
-	    	ether3_setbuffer(dev, buffer_read, tx_tail * 0x600);
-    		status = ether3_readlong(dev);
-
-		/*
-		 * Check to see if this packet has been transmitted
-		 */
-		if ((status & (TXSTAT_DONE | TXHDR_TRANSMIT)) !=
-		    (TXSTAT_DONE | TXHDR_TRANSMIT))
-			break;
-
-		/*
-		 * Update errors
-		 */
-		if (!(status & (TXSTAT_BABBLED | TXSTAT_16COLLISIONS)))
-			dev->stats.tx_packets++;
-		else {
-			dev->stats.tx_errors++;
-			if (status & TXSTAT_16COLLISIONS)
-				dev->stats.collisions += 16;
-			if (status & TXSTAT_BABBLED)
-				dev->stats.tx_fifo_errors++;
-		}
-
-		tx_tail = (tx_tail + 1) & 15;
-	} while (--max_work);
-
-	if (priv(dev)->tx_tail != tx_tail) {
-		priv(dev)->tx_tail = tx_tail;
-		netif_wake_queue(dev);
-	}
-}
-
-static void __devinit ether3_banner(void)
-{
-	static unsigned version_printed = 0;
-
-	if (net_debug && version_printed++ == 0)
-		printk(KERN_INFO "%s", version);
-}
-
-static const struct net_device_ops ether3_netdev_ops = {
-	.ndo_open		= ether3_open,
-	.ndo_stop		= ether3_close,
-	.ndo_start_xmit		= ether3_sendpacket,
-	.ndo_set_multicast_list	= ether3_setmulticastlist,
-	.ndo_tx_timeout		= ether3_timeout,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address	= eth_mac_addr,
-};
-
-static int __devinit
-ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
-{
-	const struct ether3_data *data = id->data;
-	struct net_device *dev;
-	int bus_type, ret;
-
-	ether3_banner();
-
-	ret = ecard_request_resources(ec);
-	if (ret)
-		goto out;
-
-	dev = alloc_etherdev(sizeof(struct dev_priv));
-	if (!dev) {
-		ret = -ENOMEM;
-		goto release;
-	}
-
-	SET_NETDEV_DEV(dev, &ec->dev);
-
-	priv(dev)->base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
-	if (!priv(dev)->base) {
-		ret = -ENOMEM;
-		goto free;
-	}
-
-	ec->irqaddr = priv(dev)->base + data->base_offset;
-	ec->irqmask = 0xf0;
-
-	priv(dev)->seeq = priv(dev)->base + data->base_offset;
-	dev->irq = ec->irq;
-
-	ether3_addr(dev->dev_addr, ec);
-
-	init_timer(&priv(dev)->timer);
-
-	/* Reset card...
-	 */
-	ether3_outb(0x80, REG_CONFIG2 + 4);
-	bus_type = BUS_UNKNOWN;
-	udelay(4);
-
-	/* Test using Receive Pointer (16-bit register) to find out
-	 * how the ether3 is connected to the bus...
-	 */
-	if (ether3_probe_bus_8(dev, 0x100) &&
-	    ether3_probe_bus_8(dev, 0x201))
-		bus_type = BUS_8;
-
-	if (bus_type == BUS_UNKNOWN &&
-	    ether3_probe_bus_16(dev, 0x101) &&
-	    ether3_probe_bus_16(dev, 0x201))
-		bus_type = BUS_16;
-
-	switch (bus_type) {
-	case BUS_UNKNOWN:
-		printk(KERN_ERR "%s: unable to identify bus width\n", dev->name);
-		ret = -ENODEV;
-		goto free;
-
-	case BUS_8:
-		printk(KERN_ERR "%s: %s found, but is an unsupported "
-			"8-bit card\n", dev->name, data->name);
-		ret = -ENODEV;
-		goto free;
-
-	default:
-		break;
-	}
-
-	if (ether3_init_2(dev)) {
-		ret = -ENODEV;
-		goto free;
-	}
-
-	dev->netdev_ops		= &ether3_netdev_ops;
-	dev->watchdog_timeo	= 5 * HZ / 100;
-
-	ret = register_netdev(dev);
-	if (ret)
-		goto free;
-
-	printk("%s: %s in slot %d, %pM\n",
-	       dev->name, data->name, ec->slot_no, dev->dev_addr);
-
-	ecard_set_drvdata(ec, dev);
-	return 0;
-
- free:
-	free_netdev(dev);
- release:
-	ecard_release_resources(ec);
- out:
-	return ret;
-}
-
-static void __devexit ether3_remove(struct expansion_card *ec)
-{
-	struct net_device *dev = ecard_get_drvdata(ec);
-
-	ecard_set_drvdata(ec, NULL);
-
-	unregister_netdev(dev);
-	free_netdev(dev);
-	ecard_release_resources(ec);
-}
-
-static struct ether3_data ether3 = {
-	.name		= "ether3",
-	.base_offset	= 0,
-};
-
-static struct ether3_data etherb = {
-	.name		= "etherb",
-	.base_offset	= 0x800,
-};
-
-static const struct ecard_id ether3_ids[] = {
-	{ MANU_ANT2, PROD_ANT_ETHER3, &ether3 },
-	{ MANU_ANT,  PROD_ANT_ETHER3, &ether3 },
-	{ MANU_ANT,  PROD_ANT_ETHERB, &etherb },
-	{ 0xffff, 0xffff }
-};
-
-static struct ecard_driver ether3_driver = {
-	.probe		= ether3_probe,
-	.remove		= __devexit_p(ether3_remove),
-	.id_table	= ether3_ids,
-	.drv = {
-		.name	= "ether3",
-	},
-};
-
-static int __init ether3_init(void)
-{
-	return ecard_register_driver(&ether3_driver);
-}
-
-static void __exit ether3_exit(void)
-{
-	ecard_remove_driver(&ether3_driver);
-}
-
-module_init(ether3_init);
-module_exit(ether3_exit);
-
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/arm/ether3.h linux-libre-3.2-gnu/drivers/net/arm/ether3.h
--- linux-libre-3.1-gnu/drivers/net/arm/ether3.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arm/ether3.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,176 +0,0 @@
-/*
- *  linux/drivers/acorn/net/ether3.h
- *
- *  Copyright (C) 1995-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.
- *
- *  network driver for Acorn/ANT Ether3 cards
- */
-
-#ifndef _LINUX_ether3_H
-#define _LINUX_ether3_H
-
-/* use 0 for production, 1 for verification, >2 for debug. debug flags: */
-#define DEBUG_TX	 2
-#define DEBUG_RX	 4
-#define DEBUG_INT	 8
-#define DEBUG_IC	16
-#ifndef NET_DEBUG
-#define NET_DEBUG 	0
-#endif
-
-#define priv(dev)	((struct dev_priv *)netdev_priv(dev))
-
-/* Command register definitions & bits */
-#define REG_COMMAND		(priv(dev)->seeq + 0x0000)
-#define CMD_ENINTDMA		0x0001
-#define CMD_ENINTRX		0x0002
-#define CMD_ENINTTX		0x0004
-#define CMD_ENINTBUFWIN		0x0008
-#define CMD_ACKINTDMA		0x0010
-#define CMD_ACKINTRX		0x0020
-#define CMD_ACKINTTX		0x0040
-#define CMD_ACKINTBUFWIN	0x0080
-#define CMD_DMAON		0x0100
-#define CMD_RXON		0x0200
-#define CMD_TXON		0x0400
-#define CMD_DMAOFF		0x0800
-#define CMD_RXOFF		0x1000
-#define CMD_TXOFF		0x2000
-#define CMD_FIFOREAD		0x4000
-#define CMD_FIFOWRITE		0x8000
-
-/* status register */
-#define REG_STATUS		(priv(dev)->seeq + 0x0000)
-#define STAT_ENINTSTAT		0x0001
-#define STAT_ENINTRX		0x0002
-#define STAT_ENINTTX		0x0004
-#define STAT_ENINTBUFWIN	0x0008
-#define STAT_INTDMA		0x0010
-#define STAT_INTRX		0x0020
-#define STAT_INTTX		0x0040
-#define STAT_INTBUFWIN		0x0080
-#define STAT_DMAON		0x0100
-#define STAT_RXON		0x0200
-#define STAT_TXON		0x0400
-#define STAT_FIFOFULL		0x2000
-#define STAT_FIFOEMPTY		0x4000
-#define STAT_FIFODIR		0x8000
-
-/* configuration register 1 */
-#define REG_CONFIG1		(priv(dev)->seeq + 0x0040)
-#define CFG1_BUFSELSTAT0	0x0000
-#define CFG1_BUFSELSTAT1	0x0001
-#define CFG1_BUFSELSTAT2	0x0002
-#define CFG1_BUFSELSTAT3	0x0003
-#define CFG1_BUFSELSTAT4	0x0004
-#define CFG1_BUFSELSTAT5	0x0005
-#define CFG1_ADDRPROM		0x0006
-#define CFG1_TRANSEND		0x0007
-#define CFG1_LOCBUFMEM		0x0008
-#define CFG1_INTVECTOR		0x0009
-#define CFG1_RECVSPECONLY	0x0000
-#define CFG1_RECVSPECBROAD	0x4000
-#define CFG1_RECVSPECBRMULTI	0x8000
-#define CFG1_RECVPROMISC	0xC000
-
-/* The following aren't in 8004 */
-#define CFG1_DMABURSTCONT	0x0000
-#define CFG1_DMABURST800NS	0x0010
-#define CFG1_DMABURST1600NS	0x0020
-#define CFG1_DMABURST3200NS	0x0030
-#define CFG1_DMABURST1		0x0000
-#define CFG1_DMABURST4		0x0040
-#define CFG1_DMABURST8		0x0080
-#define CFG1_DMABURST16		0x00C0
-#define CFG1_RECVCOMPSTAT0	0x0100
-#define CFG1_RECVCOMPSTAT1	0x0200
-#define CFG1_RECVCOMPSTAT2	0x0400
-#define CFG1_RECVCOMPSTAT3	0x0800
-#define CFG1_RECVCOMPSTAT4	0x1000
-#define CFG1_RECVCOMPSTAT5	0x2000
-
-/* configuration register 2 */
-#define REG_CONFIG2		(priv(dev)->seeq + 0x0080)
-#define CFG2_BYTESWAP		0x0001
-#define CFG2_ERRENCRC		0x0008
-#define CFG2_ERRENDRIBBLE	0x0010
-#define CFG2_ERRSHORTFRAME	0x0020
-#define CFG2_SLOTSELECT		0x0040
-#define CFG2_PREAMSELECT	0x0080
-#define CFG2_ADDRLENGTH		0x0100
-#define CFG2_RECVCRC		0x0200
-#define CFG2_XMITNOCRC		0x0400
-#define CFG2_LOOPBACK		0x0800
-#define CFG2_CTRLO		0x1000
-#define CFG2_RESET		0x8000
-
-#define REG_RECVEND		(priv(dev)->seeq + 0x00c0)
-
-#define REG_BUFWIN		(priv(dev)->seeq + 0x0100)
-
-#define REG_RECVPTR		(priv(dev)->seeq + 0x0140)
-
-#define REG_TRANSMITPTR		(priv(dev)->seeq + 0x0180)
-
-#define REG_DMAADDR		(priv(dev)->seeq + 0x01c0)
-
-/*
- * Cards transmit/receive headers
- */
-#define TX_NEXT			(0xffff)
-#define TXHDR_ENBABBLEINT	(1 << 16)
-#define TXHDR_ENCOLLISIONINT	(1 << 17)
-#define TXHDR_EN16COLLISION	(1 << 18)
-#define TXHDR_ENSUCCESS		(1 << 19)
-#define TXHDR_DATAFOLLOWS	(1 << 21)
-#define TXHDR_CHAINCONTINUE	(1 << 22)
-#define TXHDR_TRANSMIT		(1 << 23)
-#define TXSTAT_BABBLED		(1 << 24)
-#define TXSTAT_COLLISION	(1 << 25)
-#define TXSTAT_16COLLISIONS	(1 << 26)
-#define TXSTAT_DONE		(1 << 31)
-
-#define RX_NEXT			(0xffff)
-#define RXHDR_CHAINCONTINUE	(1 << 6)
-#define RXHDR_RECEIVE		(1 << 7)
-#define RXSTAT_OVERSIZE		(1 << 8)
-#define RXSTAT_CRCERROR		(1 << 9)
-#define RXSTAT_DRIBBLEERROR	(1 << 10)
-#define RXSTAT_SHORTPACKET	(1 << 11)
-#define RXSTAT_DONE		(1 << 15)
-
-
-#define TX_START	0x0000
-#define TX_END		0x6000
-#define RX_START	0x6000
-#define RX_LEN		0xA000
-#define RX_END		0x10000
-/* must be a power of 2 and greater than MAX_TX_BUFFERED */
-#define MAX_TXED	16
-#define MAX_TX_BUFFERED	10
-
-struct dev_priv {
-    void __iomem *base;
-    void __iomem *seeq;
-    struct {
-	unsigned int command;
-	unsigned int config1;
-	unsigned int config2;
-    } regs;
-    unsigned char tx_head;		/* buffer nr to insert next packet	 */
-    unsigned char tx_tail;		/* buffer nr of transmitting packet	 */
-    unsigned int rx_head;		/* address to fetch next packet from	 */
-    struct timer_list timer;
-    int broken;				/* 0 = ok, 1 = something went wrong	 */
-};
-
-struct ether3_data {
-	const char name[8];
-	unsigned long base_offset;
-};
-
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/arm/etherh.c linux-libre-3.2-gnu/drivers/net/arm/etherh.c
--- linux-libre-3.1-gnu/drivers/net/arm/etherh.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arm/etherh.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,866 +0,0 @@
-/*
- *  linux/drivers/acorn/net/etherh.c
- *
- *  Copyright (C) 2000-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.
- *
- * NS8390 I-cubed EtherH and ANT EtherM specific driver
- * Thanks to I-Cubed for information on their cards.
- * EtherM conversion (C) 1999 Chris Kemp and Tim Watterton
- * EtherM integration (C) 2000 Aleph One Ltd (Tak-Shing Chan)
- * EtherM integration re-engineered by Russell King.
- *
- * Changelog:
- *  08-12-1996	RMK	1.00	Created
- *		RMK	1.03	Added support for EtherLan500 cards
- *  23-11-1997	RMK	1.04	Added media autodetection
- *  16-04-1998	RMK	1.05	Improved media autodetection
- *  10-02-2000	RMK	1.06	Updated for 2.3.43
- *  13-05-2000	RMK	1.07	Updated for 2.3.99-pre8
- *  12-10-1999  CK/TEW		EtherM driver first release
- *  21-12-2000	TTC		EtherH/EtherM integration
- *  25-12-2000	RMK	1.08	Clean integration of EtherM into this driver.
- *  03-01-2002	RMK	1.09	Always enable IRQs if we're in the nic slot.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/jiffies.h>
-
-#include <asm/system.h>
-#include <asm/ecard.h>
-#include <asm/io.h>
-
-#define EI_SHIFT(x)	(ei_local->reg_offset[x])
-
-#define ei_inb(_p)	 readb((void __iomem *)_p)
-#define ei_outb(_v,_p)	 writeb(_v,(void __iomem *)_p)
-#define ei_inb_p(_p)	 readb((void __iomem *)_p)
-#define ei_outb_p(_v,_p) writeb(_v,(void __iomem *)_p)
-
-#define NET_DEBUG  0
-#define DEBUG_INIT 2
-
-#define DRV_NAME	"etherh"
-#define DRV_VERSION	"1.11"
-
-static char version[] __initdata =
-	"EtherH/EtherM Driver (c) 2002-2004 Russell King " DRV_VERSION "\n";
-
-#include "../lib8390.c"
-
-static unsigned int net_debug = NET_DEBUG;
-
-struct etherh_priv {
-	void __iomem	*ioc_fast;
-	void __iomem	*memc;
-	void __iomem	*dma_base;
-	unsigned int	id;
-	void __iomem	*ctrl_port;
-	unsigned char	ctrl;
-	u32		supported;
-};
-
-struct etherh_data {
-	unsigned long	ns8390_offset;
-	unsigned long	dataport_offset;
-	unsigned long	ctrlport_offset;
-	int		ctrl_ioc;
-	const char	name[16];
-	u32		supported;
-	unsigned char	tx_start_page;
-	unsigned char	stop_page;
-};
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("EtherH/EtherM driver");
-MODULE_LICENSE("GPL");
-
-#define ETHERH500_DATAPORT	0x800	/* MEMC */
-#define ETHERH500_NS8390	0x000	/* MEMC */
-#define ETHERH500_CTRLPORT	0x800	/* IOC  */
-
-#define ETHERH600_DATAPORT	0x040	/* MEMC */
-#define ETHERH600_NS8390	0x800	/* MEMC */
-#define ETHERH600_CTRLPORT	0x200	/* MEMC */
-
-#define ETHERH_CP_IE		1
-#define ETHERH_CP_IF		2
-#define ETHERH_CP_HEARTBEAT	2
-
-#define ETHERH_TX_START_PAGE	1
-#define ETHERH_STOP_PAGE	127
-
-/*
- * These came from CK/TEW
- */
-#define ETHERM_DATAPORT		0x200	/* MEMC */
-#define ETHERM_NS8390		0x800	/* MEMC */
-#define ETHERM_CTRLPORT		0x23c	/* MEMC */
-
-#define ETHERM_TX_START_PAGE	64
-#define ETHERM_STOP_PAGE	127
-
-/* ------------------------------------------------------------------------ */
-
-#define etherh_priv(dev) \
- ((struct etherh_priv *)(((char *)netdev_priv(dev)) + sizeof(struct ei_device)))
-
-static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned char mask)
-{
-	unsigned char ctrl = eh->ctrl | mask;
-	eh->ctrl = ctrl;
-	writeb(ctrl, eh->ctrl_port);
-}
-
-static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned char mask)
-{
-	unsigned char ctrl = eh->ctrl & ~mask;
-	eh->ctrl = ctrl;
-	writeb(ctrl, eh->ctrl_port);
-}
-
-static inline unsigned int etherh_get_stat(struct etherh_priv *eh)
-{
-	return readb(eh->ctrl_port);
-}
-
-
-
-
-static void etherh_irq_enable(ecard_t *ec, int irqnr)
-{
-	struct etherh_priv *eh = ec->irq_data;
-
-	etherh_set_ctrl(eh, ETHERH_CP_IE);
-}
-
-static void etherh_irq_disable(ecard_t *ec, int irqnr)
-{
-	struct etherh_priv *eh = ec->irq_data;
-
-	etherh_clr_ctrl(eh, ETHERH_CP_IE);
-}
-
-static expansioncard_ops_t etherh_ops = {
-	.irqenable	= etherh_irq_enable,
-	.irqdisable	= etherh_irq_disable,
-};
-
-
-
-
-static void
-etherh_setif(struct net_device *dev)
-{
-	struct ei_device *ei_local = netdev_priv(dev);
-	unsigned long flags;
-	void __iomem *addr;
-
-	local_irq_save(flags);
-
-	/* set the interface type */
-	switch (etherh_priv(dev)->id) {
-	case PROD_I3_ETHERLAN600:
-	case PROD_I3_ETHERLAN600A:
-		addr = (void __iomem *)dev->base_addr + EN0_RCNTHI;
-
-		switch (dev->if_port) {
-		case IF_PORT_10BASE2:
-			writeb((readb(addr) & 0xf8) | 1, addr);
-			break;
-		case IF_PORT_10BASET:
-			writeb((readb(addr) & 0xf8), addr);
-			break;
-		}
-		break;
-
-	case PROD_I3_ETHERLAN500:
-		switch (dev->if_port) {
-		case IF_PORT_10BASE2:
-			etherh_clr_ctrl(etherh_priv(dev), ETHERH_CP_IF);
-			break;
-
-		case IF_PORT_10BASET:
-			etherh_set_ctrl(etherh_priv(dev), ETHERH_CP_IF);
-			break;
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	local_irq_restore(flags);
-}
-
-static int
-etherh_getifstat(struct net_device *dev)
-{
-	struct ei_device *ei_local = netdev_priv(dev);
-	void __iomem *addr;
-	int stat = 0;
-
-	switch (etherh_priv(dev)->id) {
-	case PROD_I3_ETHERLAN600:
-	case PROD_I3_ETHERLAN600A:
-		addr = (void __iomem *)dev->base_addr + EN0_RCNTHI;
-		switch (dev->if_port) {
-		case IF_PORT_10BASE2:
-			stat = 1;
-			break;
-		case IF_PORT_10BASET:
-			stat = readb(addr) & 4;
-			break;
-		}
-		break;
-
-	case PROD_I3_ETHERLAN500:
-		switch (dev->if_port) {
-		case IF_PORT_10BASE2:
-			stat = 1;
-			break;
-		case IF_PORT_10BASET:
-			stat = etherh_get_stat(etherh_priv(dev)) & ETHERH_CP_HEARTBEAT;
-			break;
-		}
-		break;
-
-	default:
-		stat = 0;
-		break;
-	}
-
-	return stat != 0;
-}
-
-/*
- * Configure the interface.  Note that we ignore the other
- * parts of ifmap, since its mostly meaningless for this driver.
- */
-static int etherh_set_config(struct net_device *dev, struct ifmap *map)
-{
-	switch (map->port) {
-	case IF_PORT_10BASE2:
-	case IF_PORT_10BASET:
-		/*
-		 * If the user explicitly sets the interface
-		 * media type, turn off automedia detection.
-		 */
-		dev->flags &= ~IFF_AUTOMEDIA;
-		dev->if_port = map->port;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	etherh_setif(dev);
-
-	return 0;
-}
-
-/*
- * Reset the 8390 (hard reset).  Note that we can't actually do this.
- */
-static void
-etherh_reset(struct net_device *dev)
-{
-	struct ei_device *ei_local = netdev_priv(dev);
-	void __iomem *addr = (void __iomem *)dev->base_addr;
-
-	writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, addr);
-
-	/*
-	 * See if we need to change the interface type.
-	 * Note that we use 'interface_num' as a flag
-	 * to indicate that we need to change the media.
-	 */
-	if (dev->flags & IFF_AUTOMEDIA && ei_local->interface_num) {
-		ei_local->interface_num = 0;
-
-		if (dev->if_port == IF_PORT_10BASET)
-			dev->if_port = IF_PORT_10BASE2;
-		else
-			dev->if_port = IF_PORT_10BASET;
-
-		etherh_setif(dev);
-	}
-}
-
-/*
- * Write a block of data out to the 8390
- */
-static void
-etherh_block_output (struct net_device *dev, int count, const unsigned char *buf, int start_page)
-{
-	struct ei_device *ei_local = netdev_priv(dev);
-	unsigned long dma_start;
-	void __iomem *dma_base, *addr;
-
-	if (ei_local->dmaing) {
-		printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: "
-			" DMAstat %d irqlock %d\n", dev->name,
-			ei_local->dmaing, ei_local->irqlock);
-		return;
-	}
-
-	/*
-	 * Make sure we have a round number of bytes if we're in word mode.
-	 */
-	if (count & 1 && ei_local->word16)
-		count++;
-
-	ei_local->dmaing = 1;
-
-	addr = (void __iomem *)dev->base_addr;
-	dma_base = etherh_priv(dev)->dma_base;
-
-	count = (count + 1) & ~1;
-	writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
-
-	writeb (0x42, addr + EN0_RCNTLO);
-	writeb (0x00, addr + EN0_RCNTHI);
-	writeb (0x42, addr + EN0_RSARLO);
-	writeb (0x00, addr + EN0_RSARHI);
-	writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
-
-	udelay (1);
-
-	writeb (ENISR_RDC, addr + EN0_ISR);
-	writeb (count, addr + EN0_RCNTLO);
-	writeb (count >> 8, addr + EN0_RCNTHI);
-	writeb (0, addr + EN0_RSARLO);
-	writeb (start_page, addr + EN0_RSARHI);
-	writeb (E8390_RWRITE | E8390_START, addr + E8390_CMD);
-
-	if (ei_local->word16)
-		writesw (dma_base, buf, count >> 1);
-	else
-		writesb (dma_base, buf, count);
-
-	dma_start = jiffies;
-
-	while ((readb (addr + EN0_ISR) & ENISR_RDC) == 0)
-		if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
-			printk(KERN_ERR "%s: timeout waiting for TX RDC\n",
-				dev->name);
-			etherh_reset (dev);
-			__NS8390_init (dev, 1);
-			break;
-		}
-
-	writeb (ENISR_RDC, addr + EN0_ISR);
-	ei_local->dmaing = 0;
-}
-
-/*
- * Read a block of data from the 8390
- */
-static void
-etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-	struct ei_device *ei_local = netdev_priv(dev);
-	unsigned char *buf;
-	void __iomem *dma_base, *addr;
-
-	if (ei_local->dmaing) {
-		printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: "
-			" DMAstat %d irqlock %d\n", dev->name,
-			ei_local->dmaing, ei_local->irqlock);
-		return;
-	}
-
-	ei_local->dmaing = 1;
-
-	addr = (void __iomem *)dev->base_addr;
-	dma_base = etherh_priv(dev)->dma_base;
-
-	buf = skb->data;
-	writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
-	writeb (count, addr + EN0_RCNTLO);
-	writeb (count >> 8, addr + EN0_RCNTHI);
-	writeb (ring_offset, addr + EN0_RSARLO);
-	writeb (ring_offset >> 8, addr + EN0_RSARHI);
-	writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
-
-	if (ei_local->word16) {
-		readsw (dma_base, buf, count >> 1);
-		if (count & 1)
-			buf[count - 1] = readb (dma_base);
-	} else
-		readsb (dma_base, buf, count);
-
-	writeb (ENISR_RDC, addr + EN0_ISR);
-	ei_local->dmaing = 0;
-}
-
-/*
- * Read a header from the 8390
- */
-static void
-etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-	struct ei_device *ei_local = netdev_priv(dev);
-	void __iomem *dma_base, *addr;
-
-	if (ei_local->dmaing) {
-		printk(KERN_ERR "%s: DMAing conflict in etherh_get_header: "
-			" DMAstat %d irqlock %d\n", dev->name,
-			ei_local->dmaing, ei_local->irqlock);
-		return;
-	}
-
-	ei_local->dmaing = 1;
-
-	addr = (void __iomem *)dev->base_addr;
-	dma_base = etherh_priv(dev)->dma_base;
-
-	writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
-	writeb (sizeof (*hdr), addr + EN0_RCNTLO);
-	writeb (0, addr + EN0_RCNTHI);
-	writeb (0, addr + EN0_RSARLO);
-	writeb (ring_page, addr + EN0_RSARHI);
-	writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
-
-	if (ei_local->word16)
-		readsw (dma_base, hdr, sizeof (*hdr) >> 1);
-	else
-		readsb (dma_base, hdr, sizeof (*hdr));
-
-	writeb (ENISR_RDC, addr + EN0_ISR);
-	ei_local->dmaing = 0;
-}
-
-/*
- * Open/initialize the board.  This is called (in the current kernel)
- * sometime after booting when the 'ifconfig' program is run.
- *
- * This routine should set everything up anew at each open, even
- * registers that "should" only need to be set once at boot, so that
- * there is non-reboot way to recover if something goes wrong.
- */
-static int
-etherh_open(struct net_device *dev)
-{
-	struct ei_device *ei_local = netdev_priv(dev);
-
-	if (!is_valid_ether_addr(dev->dev_addr)) {
-		printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
-			dev->name);
-		return -EINVAL;
-	}
-
-	if (request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev))
-		return -EAGAIN;
-
-	/*
-	 * Make sure that we aren't going to change the
-	 * media type on the next reset - we are about to
-	 * do automedia manually now.
-	 */
-	ei_local->interface_num = 0;
-
-	/*
-	 * If we are doing automedia detection, do it now.
-	 * This is more reliable than the 8390's detection.
-	 */
-	if (dev->flags & IFF_AUTOMEDIA) {
-		dev->if_port = IF_PORT_10BASET;
-		etherh_setif(dev);
-		mdelay(1);
-		if (!etherh_getifstat(dev)) {
-			dev->if_port = IF_PORT_10BASE2;
-			etherh_setif(dev);
-		}
-	} else
-		etherh_setif(dev);
-
-	etherh_reset(dev);
-	__ei_open(dev);
-
-	return 0;
-}
-
-/*
- * The inverse routine to etherh_open().
- */
-static int
-etherh_close(struct net_device *dev)
-{
-	__ei_close (dev);
-	free_irq (dev->irq, dev);
-	return 0;
-}
-
-/*
- * Initialisation
- */
-
-static void __init etherh_banner(void)
-{
-	static int version_printed;
-
-	if (net_debug && version_printed++ == 0)
-		printk(KERN_INFO "%s", version);
-}
-
-/*
- * Read the ethernet address string from the on board rom.
- * This is an ascii string...
- */
-static int __devinit etherh_addr(char *addr, struct expansion_card *ec)
-{
-	struct in_chunk_dir cd;
-	char *s;
-	
-	if (!ecard_readchunk(&cd, ec, 0xf5, 0)) {
-		printk(KERN_ERR "%s: unable to read podule description string\n",
-		       dev_name(&ec->dev));
-		goto no_addr;
-	}
-
-	s = strchr(cd.d.string, '(');
-	if (s) {
-		int i;
-
-		for (i = 0; i < 6; i++) {
-			addr[i] = simple_strtoul(s + 1, &s, 0x10);
-			if (*s != (i == 5? ')' : ':'))
-				break;
-		}
-
-		if (i == 6)
-			return 0;
-	}
-
-	printk(KERN_ERR "%s: unable to parse MAC address: %s\n",
-	       dev_name(&ec->dev), cd.d.string);
-
- no_addr:
-	return -ENODEV;
-}
-
-/*
- * Create an ethernet address from the system serial number.
- */
-static int __init etherm_addr(char *addr)
-{
-	unsigned int serial;
-
-	if (system_serial_low == 0 && system_serial_high == 0)
-		return -ENODEV;
-
-	serial = system_serial_low | system_serial_high;
-
-	addr[0] = 0;
-	addr[1] = 0;
-	addr[2] = 0xa4;
-	addr[3] = 0x10 + (serial >> 24);
-	addr[4] = serial >> 16;
-	addr[5] = serial >> 8;
-	return 0;
-}
-
-static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-	strlcpy(info->bus_info, dev_name(dev->dev.parent),
-		sizeof(info->bus_info));
-}
-
-static int etherh_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	cmd->supported	= etherh_priv(dev)->supported;
-	ethtool_cmd_speed_set(cmd, SPEED_10);
-	cmd->duplex	= DUPLEX_HALF;
-	cmd->port	= dev->if_port == IF_PORT_10BASET ? PORT_TP : PORT_BNC;
-	cmd->autoneg	= (dev->flags & IFF_AUTOMEDIA ?
-			   AUTONEG_ENABLE : AUTONEG_DISABLE);
-	return 0;
-}
-
-static int etherh_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	switch (cmd->autoneg) {
-	case AUTONEG_ENABLE:
-		dev->flags |= IFF_AUTOMEDIA;
-		break;
-
-	case AUTONEG_DISABLE:
-		switch (cmd->port) {
-		case PORT_TP:
-			dev->if_port = IF_PORT_10BASET;
-			break;
-
-		case PORT_BNC:
-			dev->if_port = IF_PORT_10BASE2;
-			break;
-
-		default:
-			return -EINVAL;
-		}
-		dev->flags &= ~IFF_AUTOMEDIA;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	etherh_setif(dev);
-
-	return 0;
-}
-
-static const struct ethtool_ops etherh_ethtool_ops = {
-	.get_settings	= etherh_get_settings,
-	.set_settings	= etherh_set_settings,
-	.get_drvinfo	= etherh_get_drvinfo,
-};
-
-static const struct net_device_ops etherh_netdev_ops = {
-	.ndo_open		= etherh_open,
-	.ndo_stop		= etherh_close,
-	.ndo_set_config		= etherh_set_config,
-	.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,
-#endif
-};
-
-static u32 etherh_regoffsets[16];
-static u32 etherm_regoffsets[16];
-
-static int __devinit
-etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
-{
-	const struct etherh_data *data = id->data;
-	struct ei_device *ei_local;
-	struct net_device *dev;
-	struct etherh_priv *eh;
-	int ret;
-
-	etherh_banner();
-
-	ret = ecard_request_resources(ec);
-	if (ret)
-		goto out;
-
-	dev = ____alloc_ei_netdev(sizeof(struct etherh_priv));
-	if (!dev) {
-		ret = -ENOMEM;
-		goto release;
-	}
-
-	SET_NETDEV_DEV(dev, &ec->dev);
-
-	dev->netdev_ops		= &etherh_netdev_ops;
-	dev->irq		= ec->irq;
-	dev->ethtool_ops	= &etherh_ethtool_ops;
-
-	if (data->supported & SUPPORTED_Autoneg)
-		dev->flags |= IFF_AUTOMEDIA;
-	if (data->supported & SUPPORTED_TP) {
-		dev->flags |= IFF_PORTSEL;
-		dev->if_port = IF_PORT_10BASET;
-	} else if (data->supported & SUPPORTED_BNC) {
-		dev->flags |= IFF_PORTSEL;
-		dev->if_port = IF_PORT_10BASE2;
-	} else
-		dev->if_port = IF_PORT_UNKNOWN;
-
-	eh = etherh_priv(dev);
-	eh->supported		= data->supported;
-	eh->ctrl		= 0;
-	eh->id			= ec->cid.product;
-	eh->memc		= ecardm_iomap(ec, ECARD_RES_MEMC, 0, PAGE_SIZE);
-	if (!eh->memc) {
-		ret = -ENOMEM;
-		goto free;
-	}
-
-	eh->ctrl_port = eh->memc;
-	if (data->ctrl_ioc) {
-		eh->ioc_fast = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, PAGE_SIZE);
-		if (!eh->ioc_fast) {
-			ret = -ENOMEM;
-			goto free;
-		}
-		eh->ctrl_port = eh->ioc_fast;
-	}
-
-	dev->base_addr = (unsigned long)eh->memc + data->ns8390_offset;
-	eh->dma_base = eh->memc + data->dataport_offset;
-	eh->ctrl_port += data->ctrlport_offset;
-
-	/*
-	 * IRQ and control port handling - only for non-NIC slot cards.
-	 */
-	if (ec->slot_no != 8) {
-		ecard_setirq(ec, &etherh_ops, eh);
-	} else {
-		/*
-		 * If we're in the NIC slot, make sure the IRQ is enabled
-		 */
-		etherh_set_ctrl(eh, ETHERH_CP_IE);
-	}
-
-	ei_local = netdev_priv(dev);
-	spin_lock_init(&ei_local->page_lock);
-
-	if (ec->cid.product == PROD_ANT_ETHERM) {
-		etherm_addr(dev->dev_addr);
-		ei_local->reg_offset = etherm_regoffsets;
-	} else {
-		etherh_addr(dev->dev_addr, ec);
-		ei_local->reg_offset = etherh_regoffsets;
-	}
-
-	ei_local->name          = dev->name;
-	ei_local->word16        = 1;
-	ei_local->tx_start_page = data->tx_start_page;
-	ei_local->rx_start_page = ei_local->tx_start_page + TX_PAGES;
-	ei_local->stop_page     = data->stop_page;
-	ei_local->reset_8390    = etherh_reset;
-	ei_local->block_input   = etherh_block_input;
-	ei_local->block_output  = etherh_block_output;
-	ei_local->get_8390_hdr  = etherh_get_header;
-	ei_local->interface_num = 0;
-
-	etherh_reset(dev);
-	__NS8390_init(dev, 0);
-
-	ret = register_netdev(dev);
-	if (ret)
-		goto free;
-
-	printk(KERN_INFO "%s: %s in slot %d, %pM\n",
-		dev->name, data->name, ec->slot_no, dev->dev_addr);
-
-	ecard_set_drvdata(ec, dev);
-
-	return 0;
-
- free:
-	free_netdev(dev);
- release:
-	ecard_release_resources(ec);
- out:
-	return ret;
-}
-
-static void __devexit etherh_remove(struct expansion_card *ec)
-{
-	struct net_device *dev = ecard_get_drvdata(ec);
-
-	ecard_set_drvdata(ec, NULL);
-
-	unregister_netdev(dev);
-
-	free_netdev(dev);
-
-	ecard_release_resources(ec);
-}
-
-static struct etherh_data etherm_data = {
-	.ns8390_offset		= ETHERM_NS8390,
-	.dataport_offset	= ETHERM_NS8390 + ETHERM_DATAPORT,
-	.ctrlport_offset	= ETHERM_NS8390 + ETHERM_CTRLPORT,
-	.name			= "ANT EtherM",
-	.supported		= SUPPORTED_10baseT_Half,
-	.tx_start_page		= ETHERM_TX_START_PAGE,
-	.stop_page		= ETHERM_STOP_PAGE,
-};
-
-static struct etherh_data etherlan500_data = {
-	.ns8390_offset		= ETHERH500_NS8390,
-	.dataport_offset	= ETHERH500_NS8390 + ETHERH500_DATAPORT,
-	.ctrlport_offset	= ETHERH500_CTRLPORT,
-	.ctrl_ioc		= 1,
-	.name			= "i3 EtherH 500",
-	.supported		= SUPPORTED_10baseT_Half,
-	.tx_start_page		= ETHERH_TX_START_PAGE,
-	.stop_page		= ETHERH_STOP_PAGE,
-};
-
-static struct etherh_data etherlan600_data = {
-	.ns8390_offset		= ETHERH600_NS8390,
-	.dataport_offset	= ETHERH600_NS8390 + ETHERH600_DATAPORT,
-	.ctrlport_offset	= ETHERH600_NS8390 + ETHERH600_CTRLPORT,
-	.name			= "i3 EtherH 600",
-	.supported		= SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg,
-	.tx_start_page		= ETHERH_TX_START_PAGE,
-	.stop_page		= ETHERH_STOP_PAGE,
-};
-
-static struct etherh_data etherlan600a_data = {
-	.ns8390_offset		= ETHERH600_NS8390,
-	.dataport_offset	= ETHERH600_NS8390 + ETHERH600_DATAPORT,
-	.ctrlport_offset	= ETHERH600_NS8390 + ETHERH600_CTRLPORT,
-	.name			= "i3 EtherH 600A",
-	.supported		= SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg,
-	.tx_start_page		= ETHERH_TX_START_PAGE,
-	.stop_page		= ETHERH_STOP_PAGE,
-};
-
-static const struct ecard_id etherh_ids[] = {
-	{ MANU_ANT, PROD_ANT_ETHERM,      &etherm_data       },
-	{ MANU_I3,  PROD_I3_ETHERLAN500,  &etherlan500_data  },
-	{ MANU_I3,  PROD_I3_ETHERLAN600,  &etherlan600_data  },
-	{ MANU_I3,  PROD_I3_ETHERLAN600A, &etherlan600a_data },
-	{ 0xffff,   0xffff }
-};
-
-static struct ecard_driver etherh_driver = {
-	.probe		= etherh_probe,
-	.remove		= __devexit_p(etherh_remove),
-	.id_table	= etherh_ids,
-	.drv = {
-		.name	= DRV_NAME,
-	},
-};
-
-static int __init etherh_init(void)
-{
-	int i;
-
-	for (i = 0; i < 16; i++) {
-		etherh_regoffsets[i] = i << 2;
-		etherm_regoffsets[i] = i << 5;
-	}
-
-	return ecard_register_driver(&etherh_driver);
-}
-
-static void __exit etherh_exit(void)
-{
-	ecard_remove_driver(&etherh_driver);
-}
-
-module_init(etherh_init);
-module_exit(etherh_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/arm/ixp4xx_eth.c linux-libre-3.2-gnu/drivers/net/arm/ixp4xx_eth.c
--- linux-libre-3.1-gnu/drivers/net/arm/ixp4xx_eth.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arm/ixp4xx_eth.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1489 +0,0 @@
-/*
- * Intel IXP4xx Ethernet driver for Linux
- *
- * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
- *
- * 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.
- *
- * Ethernet port config (0x00 is not present on IXP42X):
- *
- * logical port		0x00		0x10		0x20
- * NPE			0 (NPE-A)	1 (NPE-B)	2 (NPE-C)
- * physical PortId	2		0		1
- * TX queue		23		24		25
- * RX-free queue	26		27		28
- * TX-done queue is always 31, per-port RX and TX-ready queues are configurable
- *
- *
- * Queue entries:
- * bits 0 -> 1	- NPE ID (RX and TX-done)
- * bits 0 -> 2	- priority (TX, per 802.1D)
- * bits 3 -> 4	- port ID (user-set?)
- * bits 5 -> 31	- physical descriptor address
- */
-
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
-#include <linux/etherdevice.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/net_tstamp.h>
-#include <linux/phy.h>
-#include <linux/platform_device.h>
-#include <linux/ptp_classify.h>
-#include <linux/slab.h>
-#include <mach/ixp46x_ts.h>
-#include <mach/npe.h>
-#include <mach/qmgr.h>
-
-#define DEBUG_DESC		0
-#define DEBUG_RX		0
-#define DEBUG_TX		0
-#define DEBUG_PKT_BYTES		0
-#define DEBUG_MDIO		0
-#define DEBUG_CLOSE		0
-
-#define DRV_NAME		"ixp4xx_eth"
-
-#define MAX_NPES		3
-
-#define RX_DESCS		64 /* also length of all RX queues */
-#define TX_DESCS		16 /* also length of all TX queues */
-#define TXDONE_QUEUE_LEN	64 /* dwords */
-
-#define POOL_ALLOC_SIZE		(sizeof(struct desc) * (RX_DESCS + TX_DESCS))
-#define REGS_SIZE		0x1000
-#define MAX_MRU			1536 /* 0x600 */
-#define RX_BUFF_SIZE		ALIGN((NET_IP_ALIGN) + MAX_MRU, 4)
-
-#define NAPI_WEIGHT		16
-#define MDIO_INTERVAL		(3 * HZ)
-#define MAX_MDIO_RETRIES	100 /* microseconds, typically 30 cycles */
-#define MAX_CLOSE_WAIT		1000 /* microseconds, typically 2-3 cycles */
-
-#define NPE_ID(port_id)		((port_id) >> 4)
-#define PHYSICAL_ID(port_id)	((NPE_ID(port_id) + 2) % 3)
-#define TX_QUEUE(port_id)	(NPE_ID(port_id) + 23)
-#define RXFREE_QUEUE(port_id)	(NPE_ID(port_id) + 26)
-#define TXDONE_QUEUE		31
-
-#define PTP_SLAVE_MODE		1
-#define PTP_MASTER_MODE		2
-#define PORT2CHANNEL(p)		NPE_ID(p->id)
-
-/* TX Control Registers */
-#define TX_CNTRL0_TX_EN		0x01
-#define TX_CNTRL0_HALFDUPLEX	0x02
-#define TX_CNTRL0_RETRY		0x04
-#define TX_CNTRL0_PAD_EN	0x08
-#define TX_CNTRL0_APPEND_FCS	0x10
-#define TX_CNTRL0_2DEFER	0x20
-#define TX_CNTRL0_RMII		0x40 /* reduced MII */
-#define TX_CNTRL1_RETRIES	0x0F /* 4 bits */
-
-/* RX Control Registers */
-#define RX_CNTRL0_RX_EN		0x01
-#define RX_CNTRL0_PADSTRIP_EN	0x02
-#define RX_CNTRL0_SEND_FCS	0x04
-#define RX_CNTRL0_PAUSE_EN	0x08
-#define RX_CNTRL0_LOOP_EN	0x10
-#define RX_CNTRL0_ADDR_FLTR_EN	0x20
-#define RX_CNTRL0_RX_RUNT_EN	0x40
-#define RX_CNTRL0_BCAST_DIS	0x80
-#define RX_CNTRL1_DEFER_EN	0x01
-
-/* Core Control Register */
-#define CORE_RESET		0x01
-#define CORE_RX_FIFO_FLUSH	0x02
-#define CORE_TX_FIFO_FLUSH	0x04
-#define CORE_SEND_JAM		0x08
-#define CORE_MDC_EN		0x10 /* MDIO using NPE-B ETH-0 only */
-
-#define DEFAULT_TX_CNTRL0	(TX_CNTRL0_TX_EN | TX_CNTRL0_RETRY |	\
-				 TX_CNTRL0_PAD_EN | TX_CNTRL0_APPEND_FCS | \
-				 TX_CNTRL0_2DEFER)
-#define DEFAULT_RX_CNTRL0	RX_CNTRL0_RX_EN
-#define DEFAULT_CORE_CNTRL	CORE_MDC_EN
-
-
-/* NPE message codes */
-#define NPE_GETSTATUS			0x00
-#define NPE_EDB_SETPORTADDRESS		0x01
-#define NPE_EDB_GETMACADDRESSDATABASE	0x02
-#define NPE_EDB_SETMACADDRESSSDATABASE	0x03
-#define NPE_GETSTATS			0x04
-#define NPE_RESETSTATS			0x05
-#define NPE_SETMAXFRAMELENGTHS		0x06
-#define NPE_VLAN_SETRXTAGMODE		0x07
-#define NPE_VLAN_SETDEFAULTRXVID	0x08
-#define NPE_VLAN_SETPORTVLANTABLEENTRY	0x09
-#define NPE_VLAN_SETPORTVLANTABLERANGE	0x0A
-#define NPE_VLAN_SETRXQOSENTRY		0x0B
-#define NPE_VLAN_SETPORTIDEXTRACTIONMODE 0x0C
-#define NPE_STP_SETBLOCKINGSTATE	0x0D
-#define NPE_FW_SETFIREWALLMODE		0x0E
-#define NPE_PC_SETFRAMECONTROLDURATIONID 0x0F
-#define NPE_PC_SETAPMACTABLE		0x11
-#define NPE_SETLOOPBACK_MODE		0x12
-#define NPE_PC_SETBSSIDTABLE		0x13
-#define NPE_ADDRESS_FILTER_CONFIG	0x14
-#define NPE_APPENDFCSCONFIG		0x15
-#define NPE_NOTIFY_MAC_RECOVERY_DONE	0x16
-#define NPE_MAC_RECOVERY_START		0x17
-
-
-#ifdef __ARMEB__
-typedef struct sk_buff buffer_t;
-#define free_buffer dev_kfree_skb
-#define free_buffer_irq dev_kfree_skb_irq
-#else
-typedef void buffer_t;
-#define free_buffer kfree
-#define free_buffer_irq kfree
-#endif
-
-struct eth_regs {
-	u32 tx_control[2], __res1[2];		/* 000 */
-	u32 rx_control[2], __res2[2];		/* 010 */
-	u32 random_seed, __res3[3];		/* 020 */
-	u32 partial_empty_threshold, __res4;	/* 030 */
-	u32 partial_full_threshold, __res5;	/* 038 */
-	u32 tx_start_bytes, __res6[3];		/* 040 */
-	u32 tx_deferral, rx_deferral, __res7[2];/* 050 */
-	u32 tx_2part_deferral[2], __res8[2];	/* 060 */
-	u32 slot_time, __res9[3];		/* 070 */
-	u32 mdio_command[4];			/* 080 */
-	u32 mdio_status[4];			/* 090 */
-	u32 mcast_mask[6], __res10[2];		/* 0A0 */
-	u32 mcast_addr[6], __res11[2];		/* 0C0 */
-	u32 int_clock_threshold, __res12[3];	/* 0E0 */
-	u32 hw_addr[6], __res13[61];		/* 0F0 */
-	u32 core_control;			/* 1FC */
-};
-
-struct port {
-	struct resource *mem_res;
-	struct eth_regs __iomem *regs;
-	struct npe *npe;
-	struct net_device *netdev;
-	struct napi_struct napi;
-	struct phy_device *phydev;
-	struct eth_plat_info *plat;
-	buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS];
-	struct desc *desc_tab;	/* coherent */
-	u32 desc_tab_phys;
-	int id;			/* logical port ID */
-	int speed, duplex;
-	u8 firmware[4];
-	int hwts_tx_en;
-	int hwts_rx_en;
-};
-
-/* NPE message structure */
-struct msg {
-#ifdef __ARMEB__
-	u8 cmd, eth_id, byte2, byte3;
-	u8 byte4, byte5, byte6, byte7;
-#else
-	u8 byte3, byte2, eth_id, cmd;
-	u8 byte7, byte6, byte5, byte4;
-#endif
-};
-
-/* Ethernet packet descriptor */
-struct desc {
-	u32 next;		/* pointer to next buffer, unused */
-
-#ifdef __ARMEB__
-	u16 buf_len;		/* buffer length */
-	u16 pkt_len;		/* packet length */
-	u32 data;		/* pointer to data buffer in RAM */
-	u8 dest_id;
-	u8 src_id;
-	u16 flags;
-	u8 qos;
-	u8 padlen;
-	u16 vlan_tci;
-#else
-	u16 pkt_len;		/* packet length */
-	u16 buf_len;		/* buffer length */
-	u32 data;		/* pointer to data buffer in RAM */
-	u16 flags;
-	u8 src_id;
-	u8 dest_id;
-	u16 vlan_tci;
-	u8 padlen;
-	u8 qos;
-#endif
-
-#ifdef __ARMEB__
-	u8 dst_mac_0, dst_mac_1, dst_mac_2, dst_mac_3;
-	u8 dst_mac_4, dst_mac_5, src_mac_0, src_mac_1;
-	u8 src_mac_2, src_mac_3, src_mac_4, src_mac_5;
-#else
-	u8 dst_mac_3, dst_mac_2, dst_mac_1, dst_mac_0;
-	u8 src_mac_1, src_mac_0, dst_mac_5, dst_mac_4;
-	u8 src_mac_5, src_mac_4, src_mac_3, src_mac_2;
-#endif
-};
-
-
-#define rx_desc_phys(port, n)	((port)->desc_tab_phys +		\
-				 (n) * sizeof(struct desc))
-#define rx_desc_ptr(port, n)	(&(port)->desc_tab[n])
-
-#define tx_desc_phys(port, n)	((port)->desc_tab_phys +		\
-				 ((n) + RX_DESCS) * sizeof(struct desc))
-#define tx_desc_ptr(port, n)	(&(port)->desc_tab[(n) + RX_DESCS])
-
-#ifndef __ARMEB__
-static inline void memcpy_swab32(u32 *dest, u32 *src, int cnt)
-{
-	int i;
-	for (i = 0; i < cnt; i++)
-		dest[i] = swab32(src[i]);
-}
-#endif
-
-static spinlock_t mdio_lock;
-static struct eth_regs __iomem *mdio_regs; /* mdio command and status only */
-static struct mii_bus *mdio_bus;
-static int ports_open;
-static struct port *npe_port_tab[MAX_NPES];
-static struct dma_pool *dma_pool;
-
-static struct sock_filter ptp_filter[] = {
-	PTP_FILTER
-};
-
-static int ixp_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid)
-{
-	u8 *data = skb->data;
-	unsigned int offset;
-	u16 *hi, *id;
-	u32 lo;
-
-	if (sk_run_filter(skb, ptp_filter) != PTP_CLASS_V1_IPV4)
-		return 0;
-
-	offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
-
-	if (skb->len < offset + OFF_PTP_SEQUENCE_ID + sizeof(seqid))
-		return 0;
-
-	hi = (u16 *)(data + offset + OFF_PTP_SOURCE_UUID);
-	id = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
-
-	memcpy(&lo, &hi[1], sizeof(lo));
-
-	return (uid_hi == ntohs(*hi) &&
-		uid_lo == ntohl(lo) &&
-		seqid  == ntohs(*id));
-}
-
-static void ixp_rx_timestamp(struct port *port, struct sk_buff *skb)
-{
-	struct skb_shared_hwtstamps *shhwtstamps;
-	struct ixp46x_ts_regs *regs;
-	u64 ns;
-	u32 ch, hi, lo, val;
-	u16 uid, seq;
-
-	if (!port->hwts_rx_en)
-		return;
-
-	ch = PORT2CHANNEL(port);
-
-	regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
-
-	val = __raw_readl(&regs->channel[ch].ch_event);
-
-	if (!(val & RX_SNAPSHOT_LOCKED))
-		return;
-
-	lo = __raw_readl(&regs->channel[ch].src_uuid_lo);
-	hi = __raw_readl(&regs->channel[ch].src_uuid_hi);
-
-	uid = hi & 0xffff;
-	seq = (hi >> 16) & 0xffff;
-
-	if (!ixp_ptp_match(skb, htons(uid), htonl(lo), htons(seq)))
-		goto out;
-
-	lo = __raw_readl(&regs->channel[ch].rx_snap_lo);
-	hi = __raw_readl(&regs->channel[ch].rx_snap_hi);
-	ns = ((u64) hi) << 32;
-	ns |= lo;
-	ns <<= TICKS_NS_SHIFT;
-
-	shhwtstamps = skb_hwtstamps(skb);
-	memset(shhwtstamps, 0, sizeof(*shhwtstamps));
-	shhwtstamps->hwtstamp = ns_to_ktime(ns);
-out:
-	__raw_writel(RX_SNAPSHOT_LOCKED, &regs->channel[ch].ch_event);
-}
-
-static void ixp_tx_timestamp(struct port *port, struct sk_buff *skb)
-{
-	struct skb_shared_hwtstamps shhwtstamps;
-	struct ixp46x_ts_regs *regs;
-	struct skb_shared_info *shtx;
-	u64 ns;
-	u32 ch, cnt, hi, lo, val;
-
-	shtx = skb_shinfo(skb);
-	if (unlikely(shtx->tx_flags & SKBTX_HW_TSTAMP && port->hwts_tx_en))
-		shtx->tx_flags |= SKBTX_IN_PROGRESS;
-	else
-		return;
-
-	ch = PORT2CHANNEL(port);
-
-	regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
-
-	/*
-	 * This really stinks, but we have to poll for the Tx time stamp.
-	 * Usually, the time stamp is ready after 4 to 6 microseconds.
-	 */
-	for (cnt = 0; cnt < 100; cnt++) {
-		val = __raw_readl(&regs->channel[ch].ch_event);
-		if (val & TX_SNAPSHOT_LOCKED)
-			break;
-		udelay(1);
-	}
-	if (!(val & TX_SNAPSHOT_LOCKED)) {
-		shtx->tx_flags &= ~SKBTX_IN_PROGRESS;
-		return;
-	}
-
-	lo = __raw_readl(&regs->channel[ch].tx_snap_lo);
-	hi = __raw_readl(&regs->channel[ch].tx_snap_hi);
-	ns = ((u64) hi) << 32;
-	ns |= lo;
-	ns <<= TICKS_NS_SHIFT;
-
-	memset(&shhwtstamps, 0, sizeof(shhwtstamps));
-	shhwtstamps.hwtstamp = ns_to_ktime(ns);
-	skb_tstamp_tx(skb, &shhwtstamps);
-
-	__raw_writel(TX_SNAPSHOT_LOCKED, &regs->channel[ch].ch_event);
-}
-
-static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	struct hwtstamp_config cfg;
-	struct ixp46x_ts_regs *regs;
-	struct port *port = netdev_priv(netdev);
-	int ch;
-
-	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
-		return -EFAULT;
-
-	if (cfg.flags) /* reserved for future extensions */
-		return -EINVAL;
-
-	ch = PORT2CHANNEL(port);
-	regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT;
-
-	switch (cfg.tx_type) {
-	case HWTSTAMP_TX_OFF:
-		port->hwts_tx_en = 0;
-		break;
-	case HWTSTAMP_TX_ON:
-		port->hwts_tx_en = 1;
-		break;
-	default:
-		return -ERANGE;
-	}
-
-	switch (cfg.rx_filter) {
-	case HWTSTAMP_FILTER_NONE:
-		port->hwts_rx_en = 0;
-		break;
-	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
-		port->hwts_rx_en = PTP_SLAVE_MODE;
-		__raw_writel(0, &regs->channel[ch].ch_control);
-		break;
-	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
-		port->hwts_rx_en = PTP_MASTER_MODE;
-		__raw_writel(MASTER_MODE, &regs->channel[ch].ch_control);
-		break;
-	default:
-		return -ERANGE;
-	}
-
-	/* Clear out any old time stamps. */
-	__raw_writel(TX_SNAPSHOT_LOCKED | RX_SNAPSHOT_LOCKED,
-		     &regs->channel[ch].ch_event);
-
-	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
-}
-
-static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location,
-			   int write, u16 cmd)
-{
-	int cycles = 0;
-
-	if (__raw_readl(&mdio_regs->mdio_command[3]) & 0x80) {
-		printk(KERN_ERR "%s: MII not ready to transmit\n", bus->name);
-		return -1;
-	}
-
-	if (write) {
-		__raw_writel(cmd & 0xFF, &mdio_regs->mdio_command[0]);
-		__raw_writel(cmd >> 8, &mdio_regs->mdio_command[1]);
-	}
-	__raw_writel(((phy_id << 5) | location) & 0xFF,
-		     &mdio_regs->mdio_command[2]);
-	__raw_writel((phy_id >> 3) | (write << 2) | 0x80 /* GO */,
-		     &mdio_regs->mdio_command[3]);
-
-	while ((cycles < MAX_MDIO_RETRIES) &&
-	       (__raw_readl(&mdio_regs->mdio_command[3]) & 0x80)) {
-		udelay(1);
-		cycles++;
-	}
-
-	if (cycles == MAX_MDIO_RETRIES) {
-		printk(KERN_ERR "%s #%i: MII write failed\n", bus->name,
-		       phy_id);
-		return -1;
-	}
-
-#if DEBUG_MDIO
-	printk(KERN_DEBUG "%s #%i: mdio_%s() took %i cycles\n", bus->name,
-	       phy_id, write ? "write" : "read", cycles);
-#endif
-
-	if (write)
-		return 0;
-
-	if (__raw_readl(&mdio_regs->mdio_status[3]) & 0x80) {
-#if DEBUG_MDIO
-		printk(KERN_DEBUG "%s #%i: MII read failed\n", bus->name,
-		       phy_id);
-#endif
-		return 0xFFFF; /* don't return error */
-	}
-
-	return (__raw_readl(&mdio_regs->mdio_status[0]) & 0xFF) |
-		((__raw_readl(&mdio_regs->mdio_status[1]) & 0xFF) << 8);
-}
-
-static int ixp4xx_mdio_read(struct mii_bus *bus, int phy_id, int location)
-{
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&mdio_lock, flags);
-	ret = ixp4xx_mdio_cmd(bus, phy_id, location, 0, 0);
-	spin_unlock_irqrestore(&mdio_lock, flags);
-#if DEBUG_MDIO
-	printk(KERN_DEBUG "%s #%i: MII read [%i] -> 0x%X\n", bus->name,
-	       phy_id, location, ret);
-#endif
-	return ret;
-}
-
-static int ixp4xx_mdio_write(struct mii_bus *bus, int phy_id, int location,
-			     u16 val)
-{
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&mdio_lock, flags);
-	ret = ixp4xx_mdio_cmd(bus, phy_id, location, 1, val);
-	spin_unlock_irqrestore(&mdio_lock, flags);
-#if DEBUG_MDIO
-	printk(KERN_DEBUG "%s #%i: MII write [%i] <- 0x%X, err = %i\n",
-	       bus->name, phy_id, location, val, ret);
-#endif
-	return ret;
-}
-
-static int ixp4xx_mdio_register(void)
-{
-	int err;
-
-	if (!(mdio_bus = mdiobus_alloc()))
-		return -ENOMEM;
-
-	if (cpu_is_ixp43x()) {
-		/* IXP43x lacks NPE-B and uses NPE-C for MII PHY access */
-		if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEC_ETH))
-			return -ENODEV;
-		mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT;
-	} else {
-		/* All MII PHY accesses use NPE-B Ethernet registers */
-		if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0))
-			return -ENODEV;
-		mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
-	}
-
-	__raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control);
-	spin_lock_init(&mdio_lock);
-	mdio_bus->name = "IXP4xx MII Bus";
-	mdio_bus->read = &ixp4xx_mdio_read;
-	mdio_bus->write = &ixp4xx_mdio_write;
-	strcpy(mdio_bus->id, "0");
-
-	if ((err = mdiobus_register(mdio_bus)))
-		mdiobus_free(mdio_bus);
-	return err;
-}
-
-static void ixp4xx_mdio_remove(void)
-{
-	mdiobus_unregister(mdio_bus);
-	mdiobus_free(mdio_bus);
-}
-
-
-static void ixp4xx_adjust_link(struct net_device *dev)
-{
-	struct port *port = netdev_priv(dev);
-	struct phy_device *phydev = port->phydev;
-
-	if (!phydev->link) {
-		if (port->speed) {
-			port->speed = 0;
-			printk(KERN_INFO "%s: link down\n", dev->name);
-		}
-		return;
-	}
-
-	if (port->speed == phydev->speed && port->duplex == phydev->duplex)
-		return;
-
-	port->speed = phydev->speed;
-	port->duplex = phydev->duplex;
-
-	if (port->duplex)
-		__raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX,
-			     &port->regs->tx_control[0]);
-	else
-		__raw_writel(DEFAULT_TX_CNTRL0 | TX_CNTRL0_HALFDUPLEX,
-			     &port->regs->tx_control[0]);
-
-	printk(KERN_INFO "%s: link up, speed %u Mb/s, %s duplex\n",
-	       dev->name, port->speed, port->duplex ? "full" : "half");
-}
-
-
-static inline void debug_pkt(struct net_device *dev, const char *func,
-			     u8 *data, int len)
-{
-#if DEBUG_PKT_BYTES
-	int i;
-
-	printk(KERN_DEBUG "%s: %s(%i) ", dev->name, func, len);
-	for (i = 0; i < len; i++) {
-		if (i >= DEBUG_PKT_BYTES)
-			break;
-		printk("%s%02X",
-		       ((i == 6) || (i == 12) || (i >= 14)) ? " " : "",
-		       data[i]);
-	}
-	printk("\n");
-#endif
-}
-
-
-static inline void debug_desc(u32 phys, struct desc *desc)
-{
-#if DEBUG_DESC
-	printk(KERN_DEBUG "%X: %X %3X %3X %08X %2X < %2X %4X %X"
-	       " %X %X %02X%02X%02X%02X%02X%02X < %02X%02X%02X%02X%02X%02X\n",
-	       phys, desc->next, desc->buf_len, desc->pkt_len,
-	       desc->data, desc->dest_id, desc->src_id, desc->flags,
-	       desc->qos, desc->padlen, desc->vlan_tci,
-	       desc->dst_mac_0, desc->dst_mac_1, desc->dst_mac_2,
-	       desc->dst_mac_3, desc->dst_mac_4, desc->dst_mac_5,
-	       desc->src_mac_0, desc->src_mac_1, desc->src_mac_2,
-	       desc->src_mac_3, desc->src_mac_4, desc->src_mac_5);
-#endif
-}
-
-static inline int queue_get_desc(unsigned int queue, struct port *port,
-				 int is_tx)
-{
-	u32 phys, tab_phys, n_desc;
-	struct desc *tab;
-
-	if (!(phys = qmgr_get_entry(queue)))
-		return -1;
-
-	phys &= ~0x1F; /* mask out non-address bits */
-	tab_phys = is_tx ? tx_desc_phys(port, 0) : rx_desc_phys(port, 0);
-	tab = is_tx ? tx_desc_ptr(port, 0) : rx_desc_ptr(port, 0);
-	n_desc = (phys - tab_phys) / sizeof(struct desc);
-	BUG_ON(n_desc >= (is_tx ? TX_DESCS : RX_DESCS));
-	debug_desc(phys, &tab[n_desc]);
-	BUG_ON(tab[n_desc].next);
-	return n_desc;
-}
-
-static inline void queue_put_desc(unsigned int queue, u32 phys,
-				  struct desc *desc)
-{
-	debug_desc(phys, desc);
-	BUG_ON(phys & 0x1F);
-	qmgr_put_entry(queue, phys);
-	/* Don't check for queue overflow here, we've allocated sufficient
-	   length and queues >= 32 don't support this check anyway. */
-}
-
-
-static inline void dma_unmap_tx(struct port *port, struct desc *desc)
-{
-#ifdef __ARMEB__
-	dma_unmap_single(&port->netdev->dev, desc->data,
-			 desc->buf_len, DMA_TO_DEVICE);
-#else
-	dma_unmap_single(&port->netdev->dev, desc->data & ~3,
-			 ALIGN((desc->data & 3) + desc->buf_len, 4),
-			 DMA_TO_DEVICE);
-#endif
-}
-
-
-static void eth_rx_irq(void *pdev)
-{
-	struct net_device *dev = pdev;
-	struct port *port = netdev_priv(dev);
-
-#if DEBUG_RX
-	printk(KERN_DEBUG "%s: eth_rx_irq\n", dev->name);
-#endif
-	qmgr_disable_irq(port->plat->rxq);
-	napi_schedule(&port->napi);
-}
-
-static int eth_poll(struct napi_struct *napi, int budget)
-{
-	struct port *port = container_of(napi, struct port, napi);
-	struct net_device *dev = port->netdev;
-	unsigned int rxq = port->plat->rxq, rxfreeq = RXFREE_QUEUE(port->id);
-	int received = 0;
-
-#if DEBUG_RX
-	printk(KERN_DEBUG "%s: eth_poll\n", dev->name);
-#endif
-
-	while (received < budget) {
-		struct sk_buff *skb;
-		struct desc *desc;
-		int n;
-#ifdef __ARMEB__
-		struct sk_buff *temp;
-		u32 phys;
-#endif
-
-		if ((n = queue_get_desc(rxq, port, 0)) < 0) {
-#if DEBUG_RX
-			printk(KERN_DEBUG "%s: eth_poll napi_complete\n",
-			       dev->name);
-#endif
-			napi_complete(napi);
-			qmgr_enable_irq(rxq);
-			if (!qmgr_stat_below_low_watermark(rxq) &&
-			    napi_reschedule(napi)) { /* not empty again */
-#if DEBUG_RX
-				printk(KERN_DEBUG "%s: eth_poll"
-				       " napi_reschedule successed\n",
-				       dev->name);
-#endif
-				qmgr_disable_irq(rxq);
-				continue;
-			}
-#if DEBUG_RX
-			printk(KERN_DEBUG "%s: eth_poll all done\n",
-			       dev->name);
-#endif
-			return received; /* all work done */
-		}
-
-		desc = rx_desc_ptr(port, n);
-
-#ifdef __ARMEB__
-		if ((skb = netdev_alloc_skb(dev, RX_BUFF_SIZE))) {
-			phys = dma_map_single(&dev->dev, skb->data,
-					      RX_BUFF_SIZE, DMA_FROM_DEVICE);
-			if (dma_mapping_error(&dev->dev, phys)) {
-				dev_kfree_skb(skb);
-				skb = NULL;
-			}
-		}
-#else
-		skb = netdev_alloc_skb(dev,
-				       ALIGN(NET_IP_ALIGN + desc->pkt_len, 4));
-#endif
-
-		if (!skb) {
-			dev->stats.rx_dropped++;
-			/* put the desc back on RX-ready queue */
-			desc->buf_len = MAX_MRU;
-			desc->pkt_len = 0;
-			queue_put_desc(rxfreeq, rx_desc_phys(port, n), desc);
-			continue;
-		}
-
-		/* process received frame */
-#ifdef __ARMEB__
-		temp = skb;
-		skb = port->rx_buff_tab[n];
-		dma_unmap_single(&dev->dev, desc->data - NET_IP_ALIGN,
-				 RX_BUFF_SIZE, DMA_FROM_DEVICE);
-#else
-		dma_sync_single_for_cpu(&dev->dev, desc->data - NET_IP_ALIGN,
-					RX_BUFF_SIZE, DMA_FROM_DEVICE);
-		memcpy_swab32((u32 *)skb->data, (u32 *)port->rx_buff_tab[n],
-			      ALIGN(NET_IP_ALIGN + desc->pkt_len, 4) / 4);
-#endif
-		skb_reserve(skb, NET_IP_ALIGN);
-		skb_put(skb, desc->pkt_len);
-
-		debug_pkt(dev, "eth_poll", skb->data, skb->len);
-
-		ixp_rx_timestamp(port, skb);
-		skb->protocol = eth_type_trans(skb, dev);
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += skb->len;
-		netif_receive_skb(skb);
-
-		/* put the new buffer on RX-free queue */
-#ifdef __ARMEB__
-		port->rx_buff_tab[n] = temp;
-		desc->data = phys + NET_IP_ALIGN;
-#endif
-		desc->buf_len = MAX_MRU;
-		desc->pkt_len = 0;
-		queue_put_desc(rxfreeq, rx_desc_phys(port, n), desc);
-		received++;
-	}
-
-#if DEBUG_RX
-	printk(KERN_DEBUG "eth_poll(): end, not all work done\n");
-#endif
-	return received;		/* not all work done */
-}
-
-
-static void eth_txdone_irq(void *unused)
-{
-	u32 phys;
-
-#if DEBUG_TX
-	printk(KERN_DEBUG DRV_NAME ": eth_txdone_irq\n");
-#endif
-	while ((phys = qmgr_get_entry(TXDONE_QUEUE)) != 0) {
-		u32 npe_id, n_desc;
-		struct port *port;
-		struct desc *desc;
-		int start;
-
-		npe_id = phys & 3;
-		BUG_ON(npe_id >= MAX_NPES);
-		port = npe_port_tab[npe_id];
-		BUG_ON(!port);
-		phys &= ~0x1F; /* mask out non-address bits */
-		n_desc = (phys - tx_desc_phys(port, 0)) / sizeof(struct desc);
-		BUG_ON(n_desc >= TX_DESCS);
-		desc = tx_desc_ptr(port, n_desc);
-		debug_desc(phys, desc);
-
-		if (port->tx_buff_tab[n_desc]) { /* not the draining packet */
-			port->netdev->stats.tx_packets++;
-			port->netdev->stats.tx_bytes += desc->pkt_len;
-
-			dma_unmap_tx(port, desc);
-#if DEBUG_TX
-			printk(KERN_DEBUG "%s: eth_txdone_irq free %p\n",
-			       port->netdev->name, port->tx_buff_tab[n_desc]);
-#endif
-			free_buffer_irq(port->tx_buff_tab[n_desc]);
-			port->tx_buff_tab[n_desc] = NULL;
-		}
-
-		start = qmgr_stat_below_low_watermark(port->plat->txreadyq);
-		queue_put_desc(port->plat->txreadyq, phys, desc);
-		if (start) { /* TX-ready queue was empty */
-#if DEBUG_TX
-			printk(KERN_DEBUG "%s: eth_txdone_irq xmit ready\n",
-			       port->netdev->name);
-#endif
-			netif_wake_queue(port->netdev);
-		}
-	}
-}
-
-static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct port *port = netdev_priv(dev);
-	unsigned int txreadyq = port->plat->txreadyq;
-	int len, offset, bytes, n;
-	void *mem;
-	u32 phys;
-	struct desc *desc;
-
-#if DEBUG_TX
-	printk(KERN_DEBUG "%s: eth_xmit\n", dev->name);
-#endif
-
-	if (unlikely(skb->len > MAX_MRU)) {
-		dev_kfree_skb(skb);
-		dev->stats.tx_errors++;
-		return NETDEV_TX_OK;
-	}
-
-	debug_pkt(dev, "eth_xmit", skb->data, skb->len);
-
-	len = skb->len;
-#ifdef __ARMEB__
-	offset = 0; /* no need to keep alignment */
-	bytes = len;
-	mem = skb->data;
-#else
-	offset = (int)skb->data & 3; /* keep 32-bit alignment */
-	bytes = ALIGN(offset + len, 4);
-	if (!(mem = kmalloc(bytes, GFP_ATOMIC))) {
-		dev_kfree_skb(skb);
-		dev->stats.tx_dropped++;
-		return NETDEV_TX_OK;
-	}
-	memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4);
-#endif
-
-	phys = dma_map_single(&dev->dev, mem, bytes, DMA_TO_DEVICE);
-	if (dma_mapping_error(&dev->dev, phys)) {
-		dev_kfree_skb(skb);
-#ifndef __ARMEB__
-		kfree(mem);
-#endif
-		dev->stats.tx_dropped++;
-		return NETDEV_TX_OK;
-	}
-
-	n = queue_get_desc(txreadyq, port, 1);
-	BUG_ON(n < 0);
-	desc = tx_desc_ptr(port, n);
-
-#ifdef __ARMEB__
-	port->tx_buff_tab[n] = skb;
-#else
-	port->tx_buff_tab[n] = mem;
-#endif
-	desc->data = phys + offset;
-	desc->buf_len = desc->pkt_len = len;
-
-	/* NPE firmware pads short frames with zeros internally */
-	wmb();
-	queue_put_desc(TX_QUEUE(port->id), tx_desc_phys(port, n), desc);
-
-	if (qmgr_stat_below_low_watermark(txreadyq)) { /* empty */
-#if DEBUG_TX
-		printk(KERN_DEBUG "%s: eth_xmit queue full\n", dev->name);
-#endif
-		netif_stop_queue(dev);
-		/* we could miss TX ready interrupt */
-		/* really empty in fact */
-		if (!qmgr_stat_below_low_watermark(txreadyq)) {
-#if DEBUG_TX
-			printk(KERN_DEBUG "%s: eth_xmit ready again\n",
-			       dev->name);
-#endif
-			netif_wake_queue(dev);
-		}
-	}
-
-#if DEBUG_TX
-	printk(KERN_DEBUG "%s: eth_xmit end\n", dev->name);
-#endif
-
-	ixp_tx_timestamp(port, skb);
-	skb_tx_timestamp(skb);
-
-#ifndef __ARMEB__
-	dev_kfree_skb(skb);
-#endif
-	return NETDEV_TX_OK;
-}
-
-
-static void eth_set_mcast_list(struct net_device *dev)
-{
-	struct port *port = netdev_priv(dev);
-	struct netdev_hw_addr *ha;
-	u8 diffs[ETH_ALEN], *addr;
-	int i;
-	static const u8 allmulti[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-	if (dev->flags & IFF_ALLMULTI) {
-		for (i = 0; i < ETH_ALEN; i++) {
-			__raw_writel(allmulti[i], &port->regs->mcast_addr[i]);
-			__raw_writel(allmulti[i], &port->regs->mcast_mask[i]);
-		}
-		__raw_writel(DEFAULT_RX_CNTRL0 | RX_CNTRL0_ADDR_FLTR_EN,
-			&port->regs->rx_control[0]);
-		return;
-	}
-
-	if ((dev->flags & IFF_PROMISC) || netdev_mc_empty(dev)) {
-		__raw_writel(DEFAULT_RX_CNTRL0 & ~RX_CNTRL0_ADDR_FLTR_EN,
-			     &port->regs->rx_control[0]);
-		return;
-	}
-
-	memset(diffs, 0, ETH_ALEN);
-
-	addr = NULL;
-	netdev_for_each_mc_addr(ha, dev) {
-		if (!addr)
-			addr = ha->addr; /* first MAC address */
-		for (i = 0; i < ETH_ALEN; i++)
-			diffs[i] |= addr[i] ^ ha->addr[i];
-	}
-
-	for (i = 0; i < ETH_ALEN; i++) {
-		__raw_writel(addr[i], &port->regs->mcast_addr[i]);
-		__raw_writel(~diffs[i], &port->regs->mcast_mask[i]);
-	}
-
-	__raw_writel(DEFAULT_RX_CNTRL0 | RX_CNTRL0_ADDR_FLTR_EN,
-		     &port->regs->rx_control[0]);
-}
-
-
-static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
-{
-	struct port *port = netdev_priv(dev);
-
-	if (!netif_running(dev))
-		return -EINVAL;
-
-	if (cpu_is_ixp46x() && cmd == SIOCSHWTSTAMP)
-		return hwtstamp_ioctl(dev, req, cmd);
-
-	return phy_mii_ioctl(port->phydev, req, cmd);
-}
-
-/* ethtool support */
-
-static void ixp4xx_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	struct port *port = netdev_priv(dev);
-	strcpy(info->driver, DRV_NAME);
-	snprintf(info->fw_version, sizeof(info->fw_version), "%u:%u:%u:%u",
-		 port->firmware[0], port->firmware[1],
-		 port->firmware[2], port->firmware[3]);
-	strcpy(info->bus_info, "internal");
-}
-
-static int ixp4xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct port *port = netdev_priv(dev);
-	return phy_ethtool_gset(port->phydev, cmd);
-}
-
-static int ixp4xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct port *port = netdev_priv(dev);
-	return phy_ethtool_sset(port->phydev, cmd);
-}
-
-static int ixp4xx_nway_reset(struct net_device *dev)
-{
-	struct port *port = netdev_priv(dev);
-	return phy_start_aneg(port->phydev);
-}
-
-static const struct ethtool_ops ixp4xx_ethtool_ops = {
-	.get_drvinfo = ixp4xx_get_drvinfo,
-	.get_settings = ixp4xx_get_settings,
-	.set_settings = ixp4xx_set_settings,
-	.nway_reset = ixp4xx_nway_reset,
-	.get_link = ethtool_op_get_link,
-};
-
-
-static int request_queues(struct port *port)
-{
-	int err;
-
-	err = qmgr_request_queue(RXFREE_QUEUE(port->id), RX_DESCS, 0, 0,
-				 "%s:RX-free", port->netdev->name);
-	if (err)
-		return err;
-
-	err = qmgr_request_queue(port->plat->rxq, RX_DESCS, 0, 0,
-				 "%s:RX", port->netdev->name);
-	if (err)
-		goto rel_rxfree;
-
-	err = qmgr_request_queue(TX_QUEUE(port->id), TX_DESCS, 0, 0,
-				 "%s:TX", port->netdev->name);
-	if (err)
-		goto rel_rx;
-
-	err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0,
-				 "%s:TX-ready", port->netdev->name);
-	if (err)
-		goto rel_tx;
-
-	/* TX-done queue handles skbs sent out by the NPEs */
-	if (!ports_open) {
-		err = qmgr_request_queue(TXDONE_QUEUE, TXDONE_QUEUE_LEN, 0, 0,
-					 "%s:TX-done", DRV_NAME);
-		if (err)
-			goto rel_txready;
-	}
-	return 0;
-
-rel_txready:
-	qmgr_release_queue(port->plat->txreadyq);
-rel_tx:
-	qmgr_release_queue(TX_QUEUE(port->id));
-rel_rx:
-	qmgr_release_queue(port->plat->rxq);
-rel_rxfree:
-	qmgr_release_queue(RXFREE_QUEUE(port->id));
-	printk(KERN_DEBUG "%s: unable to request hardware queues\n",
-	       port->netdev->name);
-	return err;
-}
-
-static void release_queues(struct port *port)
-{
-	qmgr_release_queue(RXFREE_QUEUE(port->id));
-	qmgr_release_queue(port->plat->rxq);
-	qmgr_release_queue(TX_QUEUE(port->id));
-	qmgr_release_queue(port->plat->txreadyq);
-
-	if (!ports_open)
-		qmgr_release_queue(TXDONE_QUEUE);
-}
-
-static int init_queues(struct port *port)
-{
-	int i;
-
-	if (!ports_open)
-		if (!(dma_pool = dma_pool_create(DRV_NAME, NULL,
-						 POOL_ALLOC_SIZE, 32, 0)))
-			return -ENOMEM;
-
-	if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
-					      &port->desc_tab_phys)))
-		return -ENOMEM;
-	memset(port->desc_tab, 0, POOL_ALLOC_SIZE);
-	memset(port->rx_buff_tab, 0, sizeof(port->rx_buff_tab)); /* tables */
-	memset(port->tx_buff_tab, 0, sizeof(port->tx_buff_tab));
-
-	/* Setup RX buffers */
-	for (i = 0; i < RX_DESCS; i++) {
-		struct desc *desc = rx_desc_ptr(port, i);
-		buffer_t *buff; /* skb or kmalloc()ated memory */
-		void *data;
-#ifdef __ARMEB__
-		if (!(buff = netdev_alloc_skb(port->netdev, RX_BUFF_SIZE)))
-			return -ENOMEM;
-		data = buff->data;
-#else
-		if (!(buff = kmalloc(RX_BUFF_SIZE, GFP_KERNEL)))
-			return -ENOMEM;
-		data = buff;
-#endif
-		desc->buf_len = MAX_MRU;
-		desc->data = dma_map_single(&port->netdev->dev, data,
-					    RX_BUFF_SIZE, DMA_FROM_DEVICE);
-		if (dma_mapping_error(&port->netdev->dev, desc->data)) {
-			free_buffer(buff);
-			return -EIO;
-		}
-		desc->data += NET_IP_ALIGN;
-		port->rx_buff_tab[i] = buff;
-	}
-
-	return 0;
-}
-
-static void destroy_queues(struct port *port)
-{
-	int i;
-
-	if (port->desc_tab) {
-		for (i = 0; i < RX_DESCS; i++) {
-			struct desc *desc = rx_desc_ptr(port, i);
-			buffer_t *buff = port->rx_buff_tab[i];
-			if (buff) {
-				dma_unmap_single(&port->netdev->dev,
-						 desc->data - NET_IP_ALIGN,
-						 RX_BUFF_SIZE, DMA_FROM_DEVICE);
-				free_buffer(buff);
-			}
-		}
-		for (i = 0; i < TX_DESCS; i++) {
-			struct desc *desc = tx_desc_ptr(port, i);
-			buffer_t *buff = port->tx_buff_tab[i];
-			if (buff) {
-				dma_unmap_tx(port, desc);
-				free_buffer(buff);
-			}
-		}
-		dma_pool_free(dma_pool, port->desc_tab, port->desc_tab_phys);
-		port->desc_tab = NULL;
-	}
-
-	if (!ports_open && dma_pool) {
-		dma_pool_destroy(dma_pool);
-		dma_pool = NULL;
-	}
-}
-
-static int eth_open(struct net_device *dev)
-{
-	struct port *port = netdev_priv(dev);
-	struct npe *npe = port->npe;
-	struct msg msg;
-	int i, err;
-
-	if (!npe_running(npe)) {
-		err = npe_load_firmware(npe, npe_name(npe), &dev->dev);
-		if (err)
-			return err;
-
-		if (npe_recv_message(npe, &msg, "ETH_GET_STATUS")) {
-			printk(KERN_ERR "%s: %s not responding\n", dev->name,
-			       npe_name(npe));
-			return -EIO;
-		}
-		port->firmware[0] = msg.byte4;
-		port->firmware[1] = msg.byte5;
-		port->firmware[2] = msg.byte6;
-		port->firmware[3] = msg.byte7;
-	}
-
-	memset(&msg, 0, sizeof(msg));
-	msg.cmd = NPE_VLAN_SETRXQOSENTRY;
-	msg.eth_id = port->id;
-	msg.byte5 = port->plat->rxq | 0x80;
-	msg.byte7 = port->plat->rxq << 4;
-	for (i = 0; i < 8; i++) {
-		msg.byte3 = i;
-		if (npe_send_recv_message(port->npe, &msg, "ETH_SET_RXQ"))
-			return -EIO;
-	}
-
-	msg.cmd = NPE_EDB_SETPORTADDRESS;
-	msg.eth_id = PHYSICAL_ID(port->id);
-	msg.byte2 = dev->dev_addr[0];
-	msg.byte3 = dev->dev_addr[1];
-	msg.byte4 = dev->dev_addr[2];
-	msg.byte5 = dev->dev_addr[3];
-	msg.byte6 = dev->dev_addr[4];
-	msg.byte7 = dev->dev_addr[5];
-	if (npe_send_recv_message(port->npe, &msg, "ETH_SET_MAC"))
-		return -EIO;
-
-	memset(&msg, 0, sizeof(msg));
-	msg.cmd = NPE_FW_SETFIREWALLMODE;
-	msg.eth_id = port->id;
-	if (npe_send_recv_message(port->npe, &msg, "ETH_SET_FIREWALL_MODE"))
-		return -EIO;
-
-	if ((err = request_queues(port)) != 0)
-		return err;
-
-	if ((err = init_queues(port)) != 0) {
-		destroy_queues(port);
-		release_queues(port);
-		return err;
-	}
-
-	port->speed = 0;	/* force "link up" message */
-	phy_start(port->phydev);
-
-	for (i = 0; i < ETH_ALEN; i++)
-		__raw_writel(dev->dev_addr[i], &port->regs->hw_addr[i]);
-	__raw_writel(0x08, &port->regs->random_seed);
-	__raw_writel(0x12, &port->regs->partial_empty_threshold);
-	__raw_writel(0x30, &port->regs->partial_full_threshold);
-	__raw_writel(0x08, &port->regs->tx_start_bytes);
-	__raw_writel(0x15, &port->regs->tx_deferral);
-	__raw_writel(0x08, &port->regs->tx_2part_deferral[0]);
-	__raw_writel(0x07, &port->regs->tx_2part_deferral[1]);
-	__raw_writel(0x80, &port->regs->slot_time);
-	__raw_writel(0x01, &port->regs->int_clock_threshold);
-
-	/* Populate queues with buffers, no failure after this point */
-	for (i = 0; i < TX_DESCS; i++)
-		queue_put_desc(port->plat->txreadyq,
-			       tx_desc_phys(port, i), tx_desc_ptr(port, i));
-
-	for (i = 0; i < RX_DESCS; i++)
-		queue_put_desc(RXFREE_QUEUE(port->id),
-			       rx_desc_phys(port, i), rx_desc_ptr(port, i));
-
-	__raw_writel(TX_CNTRL1_RETRIES, &port->regs->tx_control[1]);
-	__raw_writel(DEFAULT_TX_CNTRL0, &port->regs->tx_control[0]);
-	__raw_writel(0, &port->regs->rx_control[1]);
-	__raw_writel(DEFAULT_RX_CNTRL0, &port->regs->rx_control[0]);
-
-	napi_enable(&port->napi);
-	eth_set_mcast_list(dev);
-	netif_start_queue(dev);
-
-	qmgr_set_irq(port->plat->rxq, QUEUE_IRQ_SRC_NOT_EMPTY,
-		     eth_rx_irq, dev);
-	if (!ports_open) {
-		qmgr_set_irq(TXDONE_QUEUE, QUEUE_IRQ_SRC_NOT_EMPTY,
-			     eth_txdone_irq, NULL);
-		qmgr_enable_irq(TXDONE_QUEUE);
-	}
-	ports_open++;
-	/* we may already have RX data, enables IRQ */
-	napi_schedule(&port->napi);
-	return 0;
-}
-
-static int eth_close(struct net_device *dev)
-{
-	struct port *port = netdev_priv(dev);
-	struct msg msg;
-	int buffs = RX_DESCS; /* allocated RX buffers */
-	int i;
-
-	ports_open--;
-	qmgr_disable_irq(port->plat->rxq);
-	napi_disable(&port->napi);
-	netif_stop_queue(dev);
-
-	while (queue_get_desc(RXFREE_QUEUE(port->id), port, 0) >= 0)
-		buffs--;
-
-	memset(&msg, 0, sizeof(msg));
-	msg.cmd = NPE_SETLOOPBACK_MODE;
-	msg.eth_id = port->id;
-	msg.byte3 = 1;
-	if (npe_send_recv_message(port->npe, &msg, "ETH_ENABLE_LOOPBACK"))
-		printk(KERN_CRIT "%s: unable to enable loopback\n", dev->name);
-
-	i = 0;
-	do {			/* drain RX buffers */
-		while (queue_get_desc(port->plat->rxq, port, 0) >= 0)
-			buffs--;
-		if (!buffs)
-			break;
-		if (qmgr_stat_empty(TX_QUEUE(port->id))) {
-			/* we have to inject some packet */
-			struct desc *desc;
-			u32 phys;
-			int n = queue_get_desc(port->plat->txreadyq, port, 1);
-			BUG_ON(n < 0);
-			desc = tx_desc_ptr(port, n);
-			phys = tx_desc_phys(port, n);
-			desc->buf_len = desc->pkt_len = 1;
-			wmb();
-			queue_put_desc(TX_QUEUE(port->id), phys, desc);
-		}
-		udelay(1);
-	} while (++i < MAX_CLOSE_WAIT);
-
-	if (buffs)
-		printk(KERN_CRIT "%s: unable to drain RX queue, %i buffer(s)"
-		       " left in NPE\n", dev->name, buffs);
-#if DEBUG_CLOSE
-	if (!buffs)
-		printk(KERN_DEBUG "Draining RX queue took %i cycles\n", i);
-#endif
-
-	buffs = TX_DESCS;
-	while (queue_get_desc(TX_QUEUE(port->id), port, 1) >= 0)
-		buffs--; /* cancel TX */
-
-	i = 0;
-	do {
-		while (queue_get_desc(port->plat->txreadyq, port, 1) >= 0)
-			buffs--;
-		if (!buffs)
-			break;
-	} while (++i < MAX_CLOSE_WAIT);
-
-	if (buffs)
-		printk(KERN_CRIT "%s: unable to drain TX queue, %i buffer(s) "
-		       "left in NPE\n", dev->name, buffs);
-#if DEBUG_CLOSE
-	if (!buffs)
-		printk(KERN_DEBUG "Draining TX queues took %i cycles\n", i);
-#endif
-
-	msg.byte3 = 0;
-	if (npe_send_recv_message(port->npe, &msg, "ETH_DISABLE_LOOPBACK"))
-		printk(KERN_CRIT "%s: unable to disable loopback\n",
-		       dev->name);
-
-	phy_stop(port->phydev);
-
-	if (!ports_open)
-		qmgr_disable_irq(TXDONE_QUEUE);
-	destroy_queues(port);
-	release_queues(port);
-	return 0;
-}
-
-static const struct net_device_ops ixp4xx_netdev_ops = {
-	.ndo_open = eth_open,
-	.ndo_stop = eth_close,
-	.ndo_start_xmit = eth_xmit,
-	.ndo_set_multicast_list = eth_set_mcast_list,
-	.ndo_do_ioctl = eth_ioctl,
-	.ndo_change_mtu = eth_change_mtu,
-	.ndo_set_mac_address = eth_mac_addr,
-	.ndo_validate_addr = eth_validate_addr,
-};
-
-static int __devinit eth_init_one(struct platform_device *pdev)
-{
-	struct port *port;
-	struct net_device *dev;
-	struct eth_plat_info *plat = pdev->dev.platform_data;
-	u32 regs_phys;
-	char phy_id[MII_BUS_ID_SIZE + 3];
-	int err;
-
-	if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) {
-		pr_err("ixp4xx_eth: bad ptp filter\n");
-		return -EINVAL;
-	}
-
-	if (!(dev = alloc_etherdev(sizeof(struct port))))
-		return -ENOMEM;
-
-	SET_NETDEV_DEV(dev, &pdev->dev);
-	port = netdev_priv(dev);
-	port->netdev = dev;
-	port->id = pdev->id;
-
-	switch (port->id) {
-	case IXP4XX_ETH_NPEA:
-		port->regs = (struct eth_regs __iomem *)IXP4XX_EthA_BASE_VIRT;
-		regs_phys  = IXP4XX_EthA_BASE_PHYS;
-		break;
-	case IXP4XX_ETH_NPEB:
-		port->regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
-		regs_phys  = IXP4XX_EthB_BASE_PHYS;
-		break;
-	case IXP4XX_ETH_NPEC:
-		port->regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT;
-		regs_phys  = IXP4XX_EthC_BASE_PHYS;
-		break;
-	default:
-		err = -ENODEV;
-		goto err_free;
-	}
-
-	dev->netdev_ops = &ixp4xx_netdev_ops;
-	dev->ethtool_ops = &ixp4xx_ethtool_ops;
-	dev->tx_queue_len = 100;
-
-	netif_napi_add(dev, &port->napi, eth_poll, NAPI_WEIGHT);
-
-	if (!(port->npe = npe_request(NPE_ID(port->id)))) {
-		err = -EIO;
-		goto err_free;
-	}
-
-	port->mem_res = request_mem_region(regs_phys, REGS_SIZE, dev->name);
-	if (!port->mem_res) {
-		err = -EBUSY;
-		goto err_npe_rel;
-	}
-
-	port->plat = plat;
-	npe_port_tab[NPE_ID(port->id)] = port;
-	memcpy(dev->dev_addr, plat->hwaddr, ETH_ALEN);
-
-	platform_set_drvdata(pdev, dev);
-
-	__raw_writel(DEFAULT_CORE_CNTRL | CORE_RESET,
-		     &port->regs->core_control);
-	udelay(50);
-	__raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control);
-	udelay(50);
-
-	snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, "0", plat->phy);
-	port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0,
-				   PHY_INTERFACE_MODE_MII);
-	if (IS_ERR(port->phydev)) {
-		err = PTR_ERR(port->phydev);
-		goto err_free_mem;
-	}
-
-	port->phydev->irq = PHY_POLL;
-
-	if ((err = register_netdev(dev)))
-		goto err_phy_dis;
-
-	printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy,
-	       npe_name(port->npe));
-
-	return 0;
-
-err_phy_dis:
-	phy_disconnect(port->phydev);
-err_free_mem:
-	npe_port_tab[NPE_ID(port->id)] = NULL;
-	platform_set_drvdata(pdev, NULL);
-	release_resource(port->mem_res);
-err_npe_rel:
-	npe_release(port->npe);
-err_free:
-	free_netdev(dev);
-	return err;
-}
-
-static int __devexit eth_remove_one(struct platform_device *pdev)
-{
-	struct net_device *dev = platform_get_drvdata(pdev);
-	struct port *port = netdev_priv(dev);
-
-	unregister_netdev(dev);
-	phy_disconnect(port->phydev);
-	npe_port_tab[NPE_ID(port->id)] = NULL;
-	platform_set_drvdata(pdev, NULL);
-	npe_release(port->npe);
-	release_resource(port->mem_res);
-	free_netdev(dev);
-	return 0;
-}
-
-static struct platform_driver ixp4xx_eth_driver = {
-	.driver.name	= DRV_NAME,
-	.probe		= eth_init_one,
-	.remove		= eth_remove_one,
-};
-
-static int __init eth_init_module(void)
-{
-	int err;
-	if ((err = ixp4xx_mdio_register()))
-		return err;
-	return platform_driver_register(&ixp4xx_eth_driver);
-}
-
-static void __exit eth_cleanup_module(void)
-{
-	platform_driver_unregister(&ixp4xx_eth_driver);
-	ixp4xx_mdio_remove();
-}
-
-MODULE_AUTHOR("Krzysztof Halasa");
-MODULE_DESCRIPTION("Intel IXP4xx Ethernet driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:ixp4xx_eth");
-module_init(eth_init_module);
-module_exit(eth_cleanup_module);
diff -druN linux-libre-3.1-gnu/drivers/net/arm/Kconfig linux-libre-3.2-gnu/drivers/net/arm/Kconfig
--- linux-libre-3.1-gnu/drivers/net/arm/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arm/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,74 +0,0 @@
-#
-# Acorn Network device configuration
-#  These are for Acorn's Expansion card network interfaces
-#
-config ARM_AM79C961A
-	bool "ARM EBSA110 AM79C961A support"
-	depends on ARM && ARCH_EBSA110
-	select CRC32
-	help
-	  If you wish to compile a kernel for the EBSA-110, then you should
-	  always answer Y to this.
-
-config ARM_ETHER1
-	tristate "Acorn Ether1 support"
-	depends on ARM && ARCH_ACORN
-	help
-	  If you have an Acorn system with one of these (AKA25) network cards,
-	  you should say Y to this option if you wish to use it with Linux.
-
-config ARM_ETHER3
-	tristate "Acorn/ANT Ether3 support"
-	depends on ARM && ARCH_ACORN
-	help
-	  If you have an Acorn system with one of these network cards, you
-	  should say Y to this option if you wish to use it with Linux.
-
-config ARM_ETHERH
-	tristate "I-cubed EtherH/ANT EtherM support"
-	depends on ARM && ARCH_ACORN
-	select CRC32
-	help
-	  If you have an Acorn system with one of these network cards, you
-	  should say Y to this option if you wish to use it with Linux.
-
-config ARM_AT91_ETHER
-	tristate "AT91RM9200 Ethernet support"
-	depends on ARM && ARCH_AT91RM9200
-	select MII
-	help
-	  If you wish to compile a kernel for the AT91RM9200 and enable
-	  ethernet support, then you should always answer Y to this.
-
-config ARM_KS8695_ETHER
-	tristate "KS8695 Ethernet support"
-	depends on ARM && ARCH_KS8695
-	select MII
-	help
-	  If you wish to compile a kernel for the KS8695 and want to
-	  use the internal ethernet then you should answer Y to this.
-
-config EP93XX_ETH
-	tristate "EP93xx Ethernet support"
-	depends on ARM && ARCH_EP93XX
-	select MII
-	help
-	  This is a driver for the ethernet hardware included in EP93xx CPUs.
-	  Say Y if you are building a kernel for EP93xx based devices.
-
-config IXP4XX_ETH
-	tristate "Intel IXP4xx Ethernet support"
-	depends on ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR
-	select PHYLIB
-	help
-	  Say Y here if you want to use built-in Ethernet ports
-	  on IXP4xx processor.
-
-config W90P910_ETH
-	tristate "Nuvoton w90p910 Ethernet support"
-	depends on ARM && ARCH_W90X900
-	select PHYLIB
-	select MII
-	help
-	  Say Y here if you want to use built-in Ethernet ports
-	  on w90p910 processor.
diff -druN linux-libre-3.1-gnu/drivers/net/arm/ks8695net.c linux-libre-3.2-gnu/drivers/net/arm/ks8695net.c
--- linux-libre-3.1-gnu/drivers/net/arm/ks8695net.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arm/ks8695net.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1656 +0,0 @@
-/*
- * Micrel KS8695 (Centaur) Ethernet.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
- * General Public License for more details.
- *
- * Copyright 2008 Simtec Electronics
- *		  Daniel Silverstone <dsilvers@simtec.co.uk>
- *		  Vincent Sanders <vince@simtec.co.uk>
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/crc32.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <asm/irq.h>
-
-#include <mach/regs-switch.h>
-#include <mach/regs-misc.h>
-#include <asm/mach/irq.h>
-#include <mach/regs-irq.h>
-
-#include "ks8695net.h"
-
-#define MODULENAME	"ks8695_ether"
-#define MODULEVERSION	"1.02"
-
-/*
- * Transmit and device reset timeout, default 5 seconds.
- */
-static int watchdog = 5000;
-
-/* Hardware structures */
-
-/**
- *	struct rx_ring_desc - Receive descriptor ring element
- *	@status: The status of the descriptor element (E.g. who owns it)
- *	@length: The number of bytes in the block pointed to by data_ptr
- *	@data_ptr: The physical address of the data block to receive into
- *	@next_desc: The physical address of the next descriptor element.
- */
-struct rx_ring_desc {
-	__le32	status;
-	__le32	length;
-	__le32	data_ptr;
-	__le32	next_desc;
-};
-
-/**
- *	struct tx_ring_desc - Transmit descriptor ring element
- *	@owner: Who owns the descriptor
- *	@status: The number of bytes in the block pointed to by data_ptr
- *	@data_ptr: The physical address of the data block to receive into
- *	@next_desc: The physical address of the next descriptor element.
- */
-struct tx_ring_desc {
-	__le32	owner;
-	__le32	status;
-	__le32	data_ptr;
-	__le32	next_desc;
-};
-
-/**
- *	struct ks8695_skbuff - sk_buff wrapper for rx/tx rings.
- *	@skb: The buffer in the ring
- *	@dma_ptr: The mapped DMA pointer of the buffer
- *	@length: The number of bytes mapped to dma_ptr
- */
-struct ks8695_skbuff {
-	struct sk_buff	*skb;
-	dma_addr_t	dma_ptr;
-	u32		length;
-};
-
-/* Private device structure */
-
-#define MAX_TX_DESC 8
-#define MAX_TX_DESC_MASK 0x7
-#define MAX_RX_DESC 16
-#define MAX_RX_DESC_MASK 0xf
-
-/*napi_weight have better more than rx DMA buffers*/
-#define NAPI_WEIGHT   64
-
-#define MAX_RXBUF_SIZE 0x700
-
-#define TX_RING_DMA_SIZE (sizeof(struct tx_ring_desc) * MAX_TX_DESC)
-#define RX_RING_DMA_SIZE (sizeof(struct rx_ring_desc) * MAX_RX_DESC)
-#define RING_DMA_SIZE (TX_RING_DMA_SIZE + RX_RING_DMA_SIZE)
-
-/**
- *	enum ks8695_dtype - Device type
- *	@KS8695_DTYPE_WAN: This device is a WAN interface
- *	@KS8695_DTYPE_LAN: This device is a LAN interface
- *	@KS8695_DTYPE_HPNA: This device is an HPNA interface
- */
-enum ks8695_dtype {
-	KS8695_DTYPE_WAN,
-	KS8695_DTYPE_LAN,
-	KS8695_DTYPE_HPNA,
-};
-
-/**
- *	struct ks8695_priv - Private data for the KS8695 Ethernet
- *	@in_suspend: Flag to indicate if we're suspending/resuming
- *	@ndev: The net_device for this interface
- *	@dev: The platform device object for this interface
- *	@dtype: The type of this device
- *	@io_regs: The ioremapped registers for this interface
- *      @napi : Add support NAPI for Rx
- *	@rx_irq_name: The textual name of the RX IRQ from the platform data
- *	@tx_irq_name: The textual name of the TX IRQ from the platform data
- *	@link_irq_name: The textual name of the link IRQ from the
- *			platform data if available
- *	@rx_irq: The IRQ number for the RX IRQ
- *	@tx_irq: The IRQ number for the TX IRQ
- *	@link_irq: The IRQ number for the link IRQ if available
- *	@regs_req: The resource request for the registers region
- *	@phyiface_req: The resource request for the phy/switch region
- *		       if available
- *	@phyiface_regs: The ioremapped registers for the phy/switch if available
- *	@ring_base: The base pointer of the dma coherent memory for the rings
- *	@ring_base_dma: The DMA mapped equivalent of ring_base
- *	@tx_ring: The pointer in ring_base of the TX ring
- *	@tx_ring_used: The number of slots in the TX ring which are occupied
- *	@tx_ring_next_slot: The next slot to fill in the TX ring
- *	@tx_ring_dma: The DMA mapped equivalent of tx_ring
- *	@tx_buffers: The sk_buff mappings for the TX ring
- *	@txq_lock: A lock to protect the tx_buffers tx_ring_used etc variables
- *	@rx_ring: The pointer in ring_base of the RX ring
- *	@rx_ring_dma: The DMA mapped equivalent of rx_ring
- *	@rx_buffers: The sk_buff mappings for the RX ring
- *	@next_rx_desc_read: The next RX descriptor to read from on IRQ
- *      @rx_lock: A lock to protect Rx irq function
- *	@msg_enable: The flags for which messages to emit
- */
-struct ks8695_priv {
-	int in_suspend;
-	struct net_device *ndev;
-	struct device *dev;
-	enum ks8695_dtype dtype;
-	void __iomem *io_regs;
-
-	struct napi_struct	napi;
-
-	const char *rx_irq_name, *tx_irq_name, *link_irq_name;
-	int rx_irq, tx_irq, link_irq;
-
-	struct resource *regs_req, *phyiface_req;
-	void __iomem *phyiface_regs;
-
-	void *ring_base;
-	dma_addr_t ring_base_dma;
-
-	struct tx_ring_desc *tx_ring;
-	int tx_ring_used;
-	int tx_ring_next_slot;
-	dma_addr_t tx_ring_dma;
-	struct ks8695_skbuff tx_buffers[MAX_TX_DESC];
-	spinlock_t txq_lock;
-
-	struct rx_ring_desc *rx_ring;
-	dma_addr_t rx_ring_dma;
-	struct ks8695_skbuff rx_buffers[MAX_RX_DESC];
-	int next_rx_desc_read;
-	spinlock_t rx_lock;
-
-	int msg_enable;
-};
-
-/* Register access */
-
-/**
- *	ks8695_readreg - Read from a KS8695 ethernet register
- *	@ksp: The device to read from
- *	@reg: The register to read
- */
-static inline u32
-ks8695_readreg(struct ks8695_priv *ksp, int reg)
-{
-	return readl(ksp->io_regs + reg);
-}
-
-/**
- *	ks8695_writereg - Write to a KS8695 ethernet register
- *	@ksp: The device to write to
- *	@reg: The register to write
- *	@value: The value to write to the register
- */
-static inline void
-ks8695_writereg(struct ks8695_priv *ksp, int reg, u32 value)
-{
-	writel(value, ksp->io_regs + reg);
-}
-
-/* Utility functions */
-
-/**
- *	ks8695_port_type - Retrieve port-type as user-friendly string
- *	@ksp: The device to return the type for
- *
- *	Returns a string indicating which of the WAN, LAN or HPNA
- *	ports this device is likely to represent.
- */
-static const char *
-ks8695_port_type(struct ks8695_priv *ksp)
-{
-	switch (ksp->dtype) {
-	case KS8695_DTYPE_LAN:
-		return "LAN";
-	case KS8695_DTYPE_WAN:
-		return "WAN";
-	case KS8695_DTYPE_HPNA:
-		return "HPNA";
-	}
-
-	return "UNKNOWN";
-}
-
-/**
- *	ks8695_update_mac - Update the MAC registers in the device
- *	@ksp: The device to update
- *
- *	Updates the MAC registers in the KS8695 device from the address in the
- *	net_device structure associated with this interface.
- */
-static void
-ks8695_update_mac(struct ks8695_priv *ksp)
-{
-	/* Update the HW with the MAC from the net_device */
-	struct net_device *ndev = ksp->ndev;
-	u32 machigh, maclow;
-
-	maclow	= ((ndev->dev_addr[2] << 24) | (ndev->dev_addr[3] << 16) |
-		   (ndev->dev_addr[4] <<  8) | (ndev->dev_addr[5] <<  0));
-	machigh = ((ndev->dev_addr[0] <<  8) | (ndev->dev_addr[1] <<  0));
-
-	ks8695_writereg(ksp, KS8695_MAL, maclow);
-	ks8695_writereg(ksp, KS8695_MAH, machigh);
-
-}
-
-/**
- *	ks8695_refill_rxbuffers - Re-fill the RX buffer ring
- *	@ksp: The device to refill
- *
- *	Iterates the RX ring of the device looking for empty slots.
- *	For each empty slot, we allocate and map a new SKB and give it
- *	to the hardware.
- *	This can be called from interrupt context safely.
- */
-static void
-ks8695_refill_rxbuffers(struct ks8695_priv *ksp)
-{
-	/* Run around the RX ring, filling in any missing sk_buff's */
-	int buff_n;
-
-	for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
-		if (!ksp->rx_buffers[buff_n].skb) {
-			struct sk_buff *skb = dev_alloc_skb(MAX_RXBUF_SIZE);
-			dma_addr_t mapping;
-
-			ksp->rx_buffers[buff_n].skb = skb;
-			if (skb == NULL) {
-				/* Failed to allocate one, perhaps
-				 * we'll try again later.
-				 */
-				break;
-			}
-
-			mapping = dma_map_single(ksp->dev, skb->data,
-						 MAX_RXBUF_SIZE,
-						 DMA_FROM_DEVICE);
-			if (unlikely(dma_mapping_error(ksp->dev, mapping))) {
-				/* Failed to DMA map this SKB, try later */
-				dev_kfree_skb_irq(skb);
-				ksp->rx_buffers[buff_n].skb = NULL;
-				break;
-			}
-			ksp->rx_buffers[buff_n].dma_ptr = mapping;
-			skb->dev = ksp->ndev;
-			ksp->rx_buffers[buff_n].length = MAX_RXBUF_SIZE;
-
-			/* Record this into the DMA ring */
-			ksp->rx_ring[buff_n].data_ptr = cpu_to_le32(mapping);
-			ksp->rx_ring[buff_n].length =
-				cpu_to_le32(MAX_RXBUF_SIZE);
-
-			wmb();
-
-			/* And give ownership over to the hardware */
-			ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN);
-		}
-	}
-}
-
-/* Maximum number of multicast addresses which the KS8695 HW supports */
-#define KS8695_NR_ADDRESSES	16
-
-/**
- *	ks8695_init_partial_multicast - Init the mcast addr registers
- *	@ksp: The device to initialise
- *	@addr: The multicast address list to use
- *	@nr_addr: The number of addresses in the list
- *
- *	This routine is a helper for ks8695_set_multicast - it writes
- *	the additional-address registers in the KS8695 ethernet device
- *	and cleans up any others left behind.
- */
-static void
-ks8695_init_partial_multicast(struct ks8695_priv *ksp,
-			      struct net_device *ndev)
-{
-	u32 low, high;
-	int i;
-	struct netdev_hw_addr *ha;
-
-	i = 0;
-	netdev_for_each_mc_addr(ha, ndev) {
-		/* Ran out of space in chip? */
-		BUG_ON(i == KS8695_NR_ADDRESSES);
-
-		low = (ha->addr[2] << 24) | (ha->addr[3] << 16) |
-		      (ha->addr[4] << 8) | (ha->addr[5]);
-		high = (ha->addr[0] << 8) | (ha->addr[1]);
-
-		ks8695_writereg(ksp, KS8695_AAL_(i), low);
-		ks8695_writereg(ksp, KS8695_AAH_(i), AAH_E | high);
-		i++;
-	}
-
-	/* Clear the remaining Additional Station Addresses */
-	for (; i < KS8695_NR_ADDRESSES; i++) {
-		ks8695_writereg(ksp, KS8695_AAL_(i), 0);
-		ks8695_writereg(ksp, KS8695_AAH_(i), 0);
-	}
-}
-
-/* Interrupt handling */
-
-/**
- *	ks8695_tx_irq - Transmit IRQ handler
- *	@irq: The IRQ which went off (ignored)
- *	@dev_id: The net_device for the interrupt
- *
- *	Process the TX ring, clearing out any transmitted slots.
- *	Allows the net_device to pass us new packets once slots are
- *	freed.
- */
-static irqreturn_t
-ks8695_tx_irq(int irq, void *dev_id)
-{
-	struct net_device *ndev = (struct net_device *)dev_id;
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	int buff_n;
-
-	for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
-		if (ksp->tx_buffers[buff_n].skb &&
-		    !(ksp->tx_ring[buff_n].owner & cpu_to_le32(TDES_OWN))) {
-			rmb();
-			/* An SKB which is not owned by HW is present */
-			/* Update the stats for the net_device */
-			ndev->stats.tx_packets++;
-			ndev->stats.tx_bytes += ksp->tx_buffers[buff_n].length;
-
-			/* Free the packet from the ring */
-			ksp->tx_ring[buff_n].data_ptr = 0;
-
-			/* Free the sk_buff */
-			dma_unmap_single(ksp->dev,
-					 ksp->tx_buffers[buff_n].dma_ptr,
-					 ksp->tx_buffers[buff_n].length,
-					 DMA_TO_DEVICE);
-			dev_kfree_skb_irq(ksp->tx_buffers[buff_n].skb);
-			ksp->tx_buffers[buff_n].skb = NULL;
-			ksp->tx_ring_used--;
-		}
-	}
-
-	netif_wake_queue(ndev);
-
-	return IRQ_HANDLED;
-}
-
-/**
- *	ks8695_get_rx_enable_bit - Get rx interrupt enable/status bit
- *	@ksp: Private data for the KS8695 Ethernet
- *
- *    For KS8695 document:
- *    Interrupt Enable Register (offset 0xE204)
- *        Bit29 : WAN MAC Receive Interrupt Enable
- *        Bit16 : LAN MAC Receive Interrupt Enable
- *    Interrupt Status Register (Offset 0xF208)
- *        Bit29: WAN MAC Receive Status
- *        Bit16: LAN MAC Receive Status
- *    So, this Rx interrrupt enable/status bit number is equal
- *    as Rx IRQ number.
- */
-static inline u32 ks8695_get_rx_enable_bit(struct ks8695_priv *ksp)
-{
-	return ksp->rx_irq;
-}
-
-/**
- *	ks8695_rx_irq - Receive IRQ handler
- *	@irq: The IRQ which went off (ignored)
- *	@dev_id: The net_device for the interrupt
- *
- *	Inform NAPI that packet reception needs to be scheduled
- */
-
-static irqreturn_t
-ks8695_rx_irq(int irq, void *dev_id)
-{
-	struct net_device *ndev = (struct net_device *)dev_id;
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-
-	spin_lock(&ksp->rx_lock);
-
-	if (napi_schedule_prep(&ksp->napi)) {
-		unsigned long status = readl(KS8695_IRQ_VA + KS8695_INTEN);
-		unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
-		/*disable rx interrupt*/
-		status &= ~mask_bit;
-		writel(status , KS8695_IRQ_VA + KS8695_INTEN);
-		__napi_schedule(&ksp->napi);
-	}
-
-	spin_unlock(&ksp->rx_lock);
-	return IRQ_HANDLED;
-}
-
-/**
- *	ks8695_rx - Receive packets called by NAPI poll method
- *	@ksp: Private data for the KS8695 Ethernet
- *	@budget: Number of packets allowed to process
- */
-static int ks8695_rx(struct ks8695_priv *ksp, int budget)
-{
-	struct net_device *ndev = ksp->ndev;
-	struct sk_buff *skb;
-	int buff_n;
-	u32 flags;
-	int pktlen;
-	int received = 0;
-
-	buff_n = ksp->next_rx_desc_read;
-	while (received < budget
-			&& ksp->rx_buffers[buff_n].skb
-			&& (!(ksp->rx_ring[buff_n].status &
-					cpu_to_le32(RDES_OWN)))) {
-			rmb();
-			flags = le32_to_cpu(ksp->rx_ring[buff_n].status);
-
-			/* Found an SKB which we own, this means we
-			 * received a packet
-			 */
-			if ((flags & (RDES_FS | RDES_LS)) !=
-			    (RDES_FS | RDES_LS)) {
-				/* This packet is not the first and
-				 * the last segment.  Therefore it is
-				 * a "spanning" packet and we can't
-				 * handle it
-				 */
-				goto rx_failure;
-			}
-
-			if (flags & (RDES_ES | RDES_RE)) {
-				/* It's an error packet */
-				ndev->stats.rx_errors++;
-				if (flags & RDES_TL)
-					ndev->stats.rx_length_errors++;
-				if (flags & RDES_RF)
-					ndev->stats.rx_length_errors++;
-				if (flags & RDES_CE)
-					ndev->stats.rx_crc_errors++;
-				if (flags & RDES_RE)
-					ndev->stats.rx_missed_errors++;
-
-				goto rx_failure;
-			}
-
-			pktlen = flags & RDES_FLEN;
-			pktlen -= 4; /* Drop the CRC */
-
-			/* Retrieve the sk_buff */
-			skb = ksp->rx_buffers[buff_n].skb;
-
-			/* Clear it from the ring */
-			ksp->rx_buffers[buff_n].skb = NULL;
-			ksp->rx_ring[buff_n].data_ptr = 0;
-
-			/* Unmap the SKB */
-			dma_unmap_single(ksp->dev,
-					 ksp->rx_buffers[buff_n].dma_ptr,
-					 ksp->rx_buffers[buff_n].length,
-					 DMA_FROM_DEVICE);
-
-			/* Relinquish the SKB to the network layer */
-			skb_put(skb, pktlen);
-			skb->protocol = eth_type_trans(skb, ndev);
-			netif_receive_skb(skb);
-
-			/* Record stats */
-			ndev->stats.rx_packets++;
-			ndev->stats.rx_bytes += pktlen;
-			goto rx_finished;
-
-rx_failure:
-			/* This ring entry is an error, but we can
-			 * re-use the skb
-			 */
-			/* Give the ring entry back to the hardware */
-			ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN);
-rx_finished:
-			received++;
-			buff_n = (buff_n + 1) & MAX_RX_DESC_MASK;
-	}
-
-	/* And note which RX descriptor we last did */
-	ksp->next_rx_desc_read = buff_n;
-
-	/* And refill the buffers */
-	ks8695_refill_rxbuffers(ksp);
-
-	/* Kick the RX DMA engine, in case it became suspended */
-	ks8695_writereg(ksp, KS8695_DRSC, 0);
-
-	return received;
-}
-
-
-/**
- *	ks8695_poll - Receive packet by NAPI poll method
- *	@ksp: Private data for the KS8695 Ethernet
- *	@budget: The remaining number packets for network subsystem
- *
- *     Invoked by the network core when it requests for new
- *     packets from the driver
- */
-static int ks8695_poll(struct napi_struct *napi, int budget)
-{
-	struct ks8695_priv *ksp = container_of(napi, struct ks8695_priv, napi);
-	unsigned long  work_done;
-
-	unsigned long isr = readl(KS8695_IRQ_VA + KS8695_INTEN);
-	unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
-
-	work_done = ks8695_rx(ksp, budget);
-
-	if (work_done < budget) {
-		unsigned long flags;
-		spin_lock_irqsave(&ksp->rx_lock, flags);
-		__napi_complete(napi);
-		/*enable rx interrupt*/
-		writel(isr | mask_bit, KS8695_IRQ_VA + KS8695_INTEN);
-		spin_unlock_irqrestore(&ksp->rx_lock, flags);
-	}
-	return work_done;
-}
-
-/**
- *	ks8695_link_irq - Link change IRQ handler
- *	@irq: The IRQ which went off (ignored)
- *	@dev_id: The net_device for the interrupt
- *
- *	The WAN interface can generate an IRQ when the link changes,
- *	report this to the net layer and the user.
- */
-static irqreturn_t
-ks8695_link_irq(int irq, void *dev_id)
-{
-	struct net_device *ndev = (struct net_device *)dev_id;
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	u32 ctrl;
-
-	ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-	if (ctrl & WMC_WLS) {
-		netif_carrier_on(ndev);
-		if (netif_msg_link(ksp))
-			dev_info(ksp->dev,
-				 "%s: Link is now up (10%sMbps/%s-duplex)\n",
-				 ndev->name,
-				 (ctrl & WMC_WSS) ? "0" : "",
-				 (ctrl & WMC_WDS) ? "Full" : "Half");
-	} else {
-		netif_carrier_off(ndev);
-		if (netif_msg_link(ksp))
-			dev_info(ksp->dev, "%s: Link is now down.\n",
-				 ndev->name);
-	}
-
-	return IRQ_HANDLED;
-}
-
-
-/* KS8695 Device functions */
-
-/**
- *	ks8695_reset - Reset a KS8695 ethernet interface
- *	@ksp: The interface to reset
- *
- *	Perform an engine reset of the interface and re-program it
- *	with sensible defaults.
- */
-static void
-ks8695_reset(struct ks8695_priv *ksp)
-{
-	int reset_timeout = watchdog;
-	/* Issue the reset via the TX DMA control register */
-	ks8695_writereg(ksp, KS8695_DTXC, DTXC_TRST);
-	while (reset_timeout--) {
-		if (!(ks8695_readreg(ksp, KS8695_DTXC) & DTXC_TRST))
-			break;
-		msleep(1);
-	}
-
-	if (reset_timeout < 0) {
-		dev_crit(ksp->dev,
-			 "Timeout waiting for DMA engines to reset\n");
-		/* And blithely carry on */
-	}
-
-	/* Definitely wait long enough before attempting to program
-	 * the engines
-	 */
-	msleep(10);
-
-	/* RX: unicast and broadcast */
-	ks8695_writereg(ksp, KS8695_DRXC, DRXC_RU | DRXC_RB);
-	/* TX: pad and add CRC */
-	ks8695_writereg(ksp, KS8695_DTXC, DTXC_TEP | DTXC_TAC);
-}
-
-/**
- *	ks8695_shutdown - Shut down a KS8695 ethernet interface
- *	@ksp: The interface to shut down
- *
- *	This disables packet RX/TX, cleans up IRQs, drains the rings,
- *	and basically places the interface into a clean shutdown
- *	state.
- */
-static void
-ks8695_shutdown(struct ks8695_priv *ksp)
-{
-	u32 ctrl;
-	int buff_n;
-
-	/* Disable packet transmission */
-	ctrl = ks8695_readreg(ksp, KS8695_DTXC);
-	ks8695_writereg(ksp, KS8695_DTXC, ctrl & ~DTXC_TE);
-
-	/* Disable packet reception */
-	ctrl = ks8695_readreg(ksp, KS8695_DRXC);
-	ks8695_writereg(ksp, KS8695_DRXC, ctrl & ~DRXC_RE);
-
-	/* Release the IRQs */
-	free_irq(ksp->rx_irq, ksp->ndev);
-	free_irq(ksp->tx_irq, ksp->ndev);
-	if (ksp->link_irq != -1)
-		free_irq(ksp->link_irq, ksp->ndev);
-
-	/* Throw away any pending TX packets */
-	for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
-		if (ksp->tx_buffers[buff_n].skb) {
-			/* Remove this SKB from the TX ring */
-			ksp->tx_ring[buff_n].owner = 0;
-			ksp->tx_ring[buff_n].status = 0;
-			ksp->tx_ring[buff_n].data_ptr = 0;
-
-			/* Unmap and bin this SKB */
-			dma_unmap_single(ksp->dev,
-					 ksp->tx_buffers[buff_n].dma_ptr,
-					 ksp->tx_buffers[buff_n].length,
-					 DMA_TO_DEVICE);
-			dev_kfree_skb_irq(ksp->tx_buffers[buff_n].skb);
-			ksp->tx_buffers[buff_n].skb = NULL;
-		}
-	}
-
-	/* Purge the RX buffers */
-	for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
-		if (ksp->rx_buffers[buff_n].skb) {
-			/* Remove the SKB from the RX ring */
-			ksp->rx_ring[buff_n].status = 0;
-			ksp->rx_ring[buff_n].data_ptr = 0;
-
-			/* Unmap and bin the SKB */
-			dma_unmap_single(ksp->dev,
-					 ksp->rx_buffers[buff_n].dma_ptr,
-					 ksp->rx_buffers[buff_n].length,
-					 DMA_FROM_DEVICE);
-			dev_kfree_skb_irq(ksp->rx_buffers[buff_n].skb);
-			ksp->rx_buffers[buff_n].skb = NULL;
-		}
-	}
-}
-
-
-/**
- *	ks8695_setup_irq - IRQ setup helper function
- *	@irq: The IRQ number to claim
- *	@irq_name: The name to give the IRQ claimant
- *	@handler: The function to call to handle the IRQ
- *	@ndev: The net_device to pass in as the dev_id argument to the handler
- *
- *	Return 0 on success.
- */
-static int
-ks8695_setup_irq(int irq, const char *irq_name,
-		 irq_handler_t handler, struct net_device *ndev)
-{
-	int ret;
-
-	ret = request_irq(irq, handler, IRQF_SHARED, irq_name, ndev);
-
-	if (ret) {
-		dev_err(&ndev->dev, "failure to request IRQ %d\n", irq);
-		return ret;
-	}
-
-	return 0;
-}
-
-/**
- *	ks8695_init_net - Initialise a KS8695 ethernet interface
- *	@ksp: The interface to initialise
- *
- *	This routine fills the RX ring, initialises the DMA engines,
- *	allocates the IRQs and then starts the packet TX and RX
- *	engines.
- */
-static int
-ks8695_init_net(struct ks8695_priv *ksp)
-{
-	int ret;
-	u32 ctrl;
-
-	ks8695_refill_rxbuffers(ksp);
-
-	/* Initialise the DMA engines */
-	ks8695_writereg(ksp, KS8695_RDLB, (u32) ksp->rx_ring_dma);
-	ks8695_writereg(ksp, KS8695_TDLB, (u32) ksp->tx_ring_dma);
-
-	/* Request the IRQs */
-	ret = ks8695_setup_irq(ksp->rx_irq, ksp->rx_irq_name,
-			       ks8695_rx_irq, ksp->ndev);
-	if (ret)
-		return ret;
-	ret = ks8695_setup_irq(ksp->tx_irq, ksp->tx_irq_name,
-			       ks8695_tx_irq, ksp->ndev);
-	if (ret)
-		return ret;
-	if (ksp->link_irq != -1) {
-		ret = ks8695_setup_irq(ksp->link_irq, ksp->link_irq_name,
-				       ks8695_link_irq, ksp->ndev);
-		if (ret)
-			return ret;
-	}
-
-	/* Set up the ring indices */
-	ksp->next_rx_desc_read = 0;
-	ksp->tx_ring_next_slot = 0;
-	ksp->tx_ring_used = 0;
-
-	/* Bring up transmission */
-	ctrl = ks8695_readreg(ksp, KS8695_DTXC);
-	/* Enable packet transmission */
-	ks8695_writereg(ksp, KS8695_DTXC, ctrl | DTXC_TE);
-
-	/* Bring up the reception */
-	ctrl = ks8695_readreg(ksp, KS8695_DRXC);
-	/* Enable packet reception */
-	ks8695_writereg(ksp, KS8695_DRXC, ctrl | DRXC_RE);
-	/* And start the DMA engine */
-	ks8695_writereg(ksp, KS8695_DRSC, 0);
-
-	/* All done */
-	return 0;
-}
-
-/**
- *	ks8695_release_device - HW resource release for KS8695 e-net
- *	@ksp: The device to be freed
- *
- *	This unallocates io memory regions, dma-coherent regions etc
- *	which were allocated in ks8695_probe.
- */
-static void
-ks8695_release_device(struct ks8695_priv *ksp)
-{
-	/* Unmap the registers */
-	iounmap(ksp->io_regs);
-	if (ksp->phyiface_regs)
-		iounmap(ksp->phyiface_regs);
-
-	/* And release the request */
-	release_resource(ksp->regs_req);
-	kfree(ksp->regs_req);
-	if (ksp->phyiface_req) {
-		release_resource(ksp->phyiface_req);
-		kfree(ksp->phyiface_req);
-	}
-
-	/* Free the ring buffers */
-	dma_free_coherent(ksp->dev, RING_DMA_SIZE,
-			  ksp->ring_base, ksp->ring_base_dma);
-}
-
-/* Ethtool support */
-
-/**
- *	ks8695_get_msglevel - Get the messages enabled for emission
- *	@ndev: The network device to read from
- */
-static u32
-ks8695_get_msglevel(struct net_device *ndev)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-
-	return ksp->msg_enable;
-}
-
-/**
- *	ks8695_set_msglevel - Set the messages enabled for emission
- *	@ndev: The network device to configure
- *	@value: The messages to set for emission
- */
-static void
-ks8695_set_msglevel(struct net_device *ndev, u32 value)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-
-	ksp->msg_enable = value;
-}
-
-/**
- *	ks8695_wan_get_settings - Get device-specific settings.
- *	@ndev: The network device to read settings from
- *	@cmd: The ethtool structure to read into
- */
-static int
-ks8695_wan_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	u32 ctrl;
-
-	/* All ports on the KS8695 support these... */
-	cmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
-			  SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
-			  SUPPORTED_TP | SUPPORTED_MII);
-	cmd->transceiver = XCVR_INTERNAL;
-
-	cmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
-	cmd->port = PORT_MII;
-	cmd->supported |= (SUPPORTED_Autoneg | SUPPORTED_Pause);
-	cmd->phy_address = 0;
-
-	ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-	if ((ctrl & WMC_WAND) == 0) {
-		/* auto-negotiation is enabled */
-		cmd->advertising |= ADVERTISED_Autoneg;
-		if (ctrl & WMC_WANA100F)
-			cmd->advertising |= ADVERTISED_100baseT_Full;
-		if (ctrl & WMC_WANA100H)
-			cmd->advertising |= ADVERTISED_100baseT_Half;
-		if (ctrl & WMC_WANA10F)
-			cmd->advertising |= ADVERTISED_10baseT_Full;
-		if (ctrl & WMC_WANA10H)
-			cmd->advertising |= ADVERTISED_10baseT_Half;
-		if (ctrl & WMC_WANAP)
-			cmd->advertising |= ADVERTISED_Pause;
-		cmd->autoneg = AUTONEG_ENABLE;
-
-		ethtool_cmd_speed_set(cmd,
-				      (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10);
-		cmd->duplex = (ctrl & WMC_WDS) ?
-			DUPLEX_FULL : DUPLEX_HALF;
-	} else {
-		/* auto-negotiation is disabled */
-		cmd->autoneg = AUTONEG_DISABLE;
-
-		ethtool_cmd_speed_set(cmd, ((ctrl & WMC_WANF100) ?
-					    SPEED_100 : SPEED_10));
-		cmd->duplex = (ctrl & WMC_WANFF) ?
-			DUPLEX_FULL : DUPLEX_HALF;
-	}
-
-	return 0;
-}
-
-/**
- *	ks8695_wan_set_settings - Set device-specific settings.
- *	@ndev: The network device to configure
- *	@cmd: The settings to configure
- */
-static int
-ks8695_wan_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	u32 ctrl;
-
-	if ((cmd->speed != SPEED_10) && (cmd->speed != SPEED_100))
-		return -EINVAL;
-	if ((cmd->duplex != DUPLEX_HALF) && (cmd->duplex != DUPLEX_FULL))
-		return -EINVAL;
-	if (cmd->port != PORT_MII)
-		return -EINVAL;
-	if (cmd->transceiver != XCVR_INTERNAL)
-		return -EINVAL;
-	if ((cmd->autoneg != AUTONEG_DISABLE) &&
-	    (cmd->autoneg != AUTONEG_ENABLE))
-		return -EINVAL;
-
-	if (cmd->autoneg == AUTONEG_ENABLE) {
-		if ((cmd->advertising & (ADVERTISED_10baseT_Half |
-				ADVERTISED_10baseT_Full |
-				ADVERTISED_100baseT_Half |
-				ADVERTISED_100baseT_Full)) == 0)
-			return -EINVAL;
-
-		ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
-		ctrl &= ~(WMC_WAND | WMC_WANA100F | WMC_WANA100H |
-			  WMC_WANA10F | WMC_WANA10H);
-		if (cmd->advertising & ADVERTISED_100baseT_Full)
-			ctrl |= WMC_WANA100F;
-		if (cmd->advertising & ADVERTISED_100baseT_Half)
-			ctrl |= WMC_WANA100H;
-		if (cmd->advertising & ADVERTISED_10baseT_Full)
-			ctrl |= WMC_WANA10F;
-		if (cmd->advertising & ADVERTISED_10baseT_Half)
-			ctrl |= WMC_WANA10H;
-
-		/* force a re-negotiation */
-		ctrl |= WMC_WANR;
-		writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
-	} else {
-		ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
-		/* disable auto-negotiation */
-		ctrl |= WMC_WAND;
-		ctrl &= ~(WMC_WANF100 | WMC_WANFF);
-
-		if (cmd->speed == SPEED_100)
-			ctrl |= WMC_WANF100;
-		if (cmd->duplex == DUPLEX_FULL)
-			ctrl |= WMC_WANFF;
-
-		writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
-	}
-
-	return 0;
-}
-
-/**
- *	ks8695_wan_nwayreset - Restart the autonegotiation on the port.
- *	@ndev: The network device to restart autoneotiation on
- */
-static int
-ks8695_wan_nwayreset(struct net_device *ndev)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	u32 ctrl;
-
-	ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
-	if ((ctrl & WMC_WAND) == 0)
-		writel(ctrl | WMC_WANR,
-		       ksp->phyiface_regs + KS8695_WMC);
-	else
-		/* auto-negotiation not enabled */
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- *	ks8695_wan_get_pause - Retrieve network pause/flow-control advertising
- *	@ndev: The device to retrieve settings from
- *	@param: The structure to fill out with the information
- */
-static void
-ks8695_wan_get_pause(struct net_device *ndev, struct ethtool_pauseparam *param)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	u32 ctrl;
-
-	ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
-
-	/* advertise Pause */
-	param->autoneg = (ctrl & WMC_WANAP);
-
-	/* current Rx Flow-control */
-	ctrl = ks8695_readreg(ksp, KS8695_DRXC);
-	param->rx_pause = (ctrl & DRXC_RFCE);
-
-	/* current Tx Flow-control */
-	ctrl = ks8695_readreg(ksp, KS8695_DTXC);
-	param->tx_pause = (ctrl & DTXC_TFCE);
-}
-
-/**
- *	ks8695_get_drvinfo - Retrieve driver information
- *	@ndev: The network device to retrieve info about
- *	@info: The info structure to fill out.
- */
-static void
-ks8695_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info)
-{
-	strlcpy(info->driver, MODULENAME, sizeof(info->driver));
-	strlcpy(info->version, MODULEVERSION, sizeof(info->version));
-	strlcpy(info->bus_info, dev_name(ndev->dev.parent),
-		sizeof(info->bus_info));
-}
-
-static const struct ethtool_ops ks8695_ethtool_ops = {
-	.get_msglevel	= ks8695_get_msglevel,
-	.set_msglevel	= ks8695_set_msglevel,
-	.get_drvinfo	= ks8695_get_drvinfo,
-};
-
-static const struct ethtool_ops ks8695_wan_ethtool_ops = {
-	.get_msglevel	= ks8695_get_msglevel,
-	.set_msglevel	= ks8695_set_msglevel,
-	.get_settings	= ks8695_wan_get_settings,
-	.set_settings	= ks8695_wan_set_settings,
-	.nway_reset	= ks8695_wan_nwayreset,
-	.get_link	= ethtool_op_get_link,
-	.get_pauseparam = ks8695_wan_get_pause,
-	.get_drvinfo	= ks8695_get_drvinfo,
-};
-
-/* Network device interface functions */
-
-/**
- *	ks8695_set_mac - Update MAC in net dev and HW
- *	@ndev: The network device to update
- *	@addr: The new MAC address to set
- */
-static int
-ks8695_set_mac(struct net_device *ndev, void *addr)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	struct sockaddr *address = addr;
-
-	if (!is_valid_ether_addr(address->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(ndev->dev_addr, address->sa_data, ndev->addr_len);
-
-	ks8695_update_mac(ksp);
-
-	dev_dbg(ksp->dev, "%s: Updated MAC address to %pM\n",
-		ndev->name, ndev->dev_addr);
-
-	return 0;
-}
-
-/**
- *	ks8695_set_multicast - Set up the multicast behaviour of the interface
- *	@ndev: The net_device to configure
- *
- *	This routine, called by the net layer, configures promiscuity
- *	and multicast reception behaviour for the interface.
- */
-static void
-ks8695_set_multicast(struct net_device *ndev)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	u32 ctrl;
-
-	ctrl = ks8695_readreg(ksp, KS8695_DRXC);
-
-	if (ndev->flags & IFF_PROMISC) {
-		/* enable promiscuous mode */
-		ctrl |= DRXC_RA;
-	} else if (ndev->flags & ~IFF_PROMISC) {
-		/* disable promiscuous mode */
-		ctrl &= ~DRXC_RA;
-	}
-
-	if (ndev->flags & IFF_ALLMULTI) {
-		/* enable all multicast mode */
-		ctrl |= DRXC_RM;
-	} else if (netdev_mc_count(ndev) > KS8695_NR_ADDRESSES) {
-		/* more specific multicast addresses than can be
-		 * handled in hardware
-		 */
-		ctrl |= DRXC_RM;
-	} else {
-		/* enable specific multicasts */
-		ctrl &= ~DRXC_RM;
-		ks8695_init_partial_multicast(ksp, ndev);
-	}
-
-	ks8695_writereg(ksp, KS8695_DRXC, ctrl);
-}
-
-/**
- *	ks8695_timeout - Handle a network tx/rx timeout.
- *	@ndev: The net_device which timed out.
- *
- *	A network transaction timed out, reset the device.
- */
-static void
-ks8695_timeout(struct net_device *ndev)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-
-	netif_stop_queue(ndev);
-	ks8695_shutdown(ksp);
-
-	ks8695_reset(ksp);
-
-	ks8695_update_mac(ksp);
-
-	/* We ignore the return from this since it managed to init
-	 * before it probably will be okay to init again.
-	 */
-	ks8695_init_net(ksp);
-
-	/* Reconfigure promiscuity etc */
-	ks8695_set_multicast(ndev);
-
-	/* And start the TX queue once more */
-	netif_start_queue(ndev);
-}
-
-/**
- *	ks8695_start_xmit - Start a packet transmission
- *	@skb: The packet to transmit
- *	@ndev: The network device to send the packet on
- *
- *	This routine, called by the net layer, takes ownership of the
- *	sk_buff and adds it to the TX ring. It then kicks the TX DMA
- *	engine to ensure transmission begins.
- */
-static int
-ks8695_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	int buff_n;
-	dma_addr_t dmap;
-
-	spin_lock_irq(&ksp->txq_lock);
-
-	if (ksp->tx_ring_used == MAX_TX_DESC) {
-		/* Somehow we got entered when we have no room */
-		spin_unlock_irq(&ksp->txq_lock);
-		return NETDEV_TX_BUSY;
-	}
-
-	buff_n = ksp->tx_ring_next_slot;
-
-	BUG_ON(ksp->tx_buffers[buff_n].skb);
-
-	dmap = dma_map_single(ksp->dev, skb->data, skb->len, DMA_TO_DEVICE);
-	if (unlikely(dma_mapping_error(ksp->dev, dmap))) {
-		/* Failed to DMA map this SKB, give it back for now */
-		spin_unlock_irq(&ksp->txq_lock);
-		dev_dbg(ksp->dev, "%s: Could not map DMA memory for "\
-			"transmission, trying later\n", ndev->name);
-		return NETDEV_TX_BUSY;
-	}
-
-	ksp->tx_buffers[buff_n].dma_ptr = dmap;
-	/* Mapped okay, store the buffer pointer and length for later */
-	ksp->tx_buffers[buff_n].skb = skb;
-	ksp->tx_buffers[buff_n].length = skb->len;
-
-	/* Fill out the TX descriptor */
-	ksp->tx_ring[buff_n].data_ptr =
-		cpu_to_le32(ksp->tx_buffers[buff_n].dma_ptr);
-	ksp->tx_ring[buff_n].status =
-		cpu_to_le32(TDES_IC | TDES_FS | TDES_LS |
-			    (skb->len & TDES_TBS));
-
-	wmb();
-
-	/* Hand it over to the hardware */
-	ksp->tx_ring[buff_n].owner = cpu_to_le32(TDES_OWN);
-
-	if (++ksp->tx_ring_used == MAX_TX_DESC)
-		netif_stop_queue(ndev);
-
-	/* Kick the TX DMA in case it decided to go IDLE */
-	ks8695_writereg(ksp, KS8695_DTSC, 0);
-
-	/* And update the next ring slot */
-	ksp->tx_ring_next_slot = (buff_n + 1) & MAX_TX_DESC_MASK;
-
-	spin_unlock_irq(&ksp->txq_lock);
-	return NETDEV_TX_OK;
-}
-
-/**
- *	ks8695_stop - Stop (shutdown) a KS8695 ethernet interface
- *	@ndev: The net_device to stop
- *
- *	This disables the TX queue and cleans up a KS8695 ethernet
- *	device.
- */
-static int
-ks8695_stop(struct net_device *ndev)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-
-	netif_stop_queue(ndev);
-	napi_disable(&ksp->napi);
-
-	ks8695_shutdown(ksp);
-
-	return 0;
-}
-
-/**
- *	ks8695_open - Open (bring up) a KS8695 ethernet interface
- *	@ndev: The net_device to open
- *
- *	This resets, configures the MAC, initialises the RX ring and
- *	DMA engines and starts the TX queue for a KS8695 ethernet
- *	device.
- */
-static int
-ks8695_open(struct net_device *ndev)
-{
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-	int ret;
-
-	if (!is_valid_ether_addr(ndev->dev_addr))
-		return -EADDRNOTAVAIL;
-
-	ks8695_reset(ksp);
-
-	ks8695_update_mac(ksp);
-
-	ret = ks8695_init_net(ksp);
-	if (ret) {
-		ks8695_shutdown(ksp);
-		return ret;
-	}
-
-	napi_enable(&ksp->napi);
-	netif_start_queue(ndev);
-
-	return 0;
-}
-
-/* Platform device driver */
-
-/**
- *	ks8695_init_switch - Init LAN switch to known good defaults.
- *	@ksp: The device to initialise
- *
- *	This initialises the LAN switch in the KS8695 to a known-good
- *	set of defaults.
- */
-static void __devinit
-ks8695_init_switch(struct ks8695_priv *ksp)
-{
-	u32 ctrl;
-
-	/* Default value for SEC0 according to datasheet */
-	ctrl = 0x40819e00;
-
-	/* LED0 = Speed	 LED1 = Link/Activity */
-	ctrl &= ~(SEC0_LLED1S | SEC0_LLED0S);
-	ctrl |= (LLED0S_LINK | LLED1S_LINK_ACTIVITY);
-
-	/* Enable Switch */
-	ctrl |= SEC0_ENABLE;
-
-	writel(ctrl, ksp->phyiface_regs + KS8695_SEC0);
-
-	/* Defaults for SEC1 */
-	writel(0x9400100, ksp->phyiface_regs + KS8695_SEC1);
-}
-
-/**
- *	ks8695_init_wan_phy - Initialise the WAN PHY to sensible defaults
- *	@ksp: The device to initialise
- *
- *	This initialises a KS8695's WAN phy to sensible values for
- *	autonegotiation etc.
- */
-static void __devinit
-ks8695_init_wan_phy(struct ks8695_priv *ksp)
-{
-	u32 ctrl;
-
-	/* Support auto-negotiation */
-	ctrl = (WMC_WANAP | WMC_WANA100F | WMC_WANA100H |
-		WMC_WANA10F | WMC_WANA10H);
-
-	/* LED0 = Activity , LED1 = Link */
-	ctrl |= (WLED0S_ACTIVITY | WLED1S_LINK);
-
-	/* Restart Auto-negotiation */
-	ctrl |= WMC_WANR;
-
-	writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
-
-	writel(0, ksp->phyiface_regs + KS8695_WPPM);
-	writel(0, ksp->phyiface_regs + KS8695_PPS);
-}
-
-static const struct net_device_ops ks8695_netdev_ops = {
-	.ndo_open		= ks8695_open,
-	.ndo_stop		= ks8695_stop,
-	.ndo_start_xmit		= ks8695_start_xmit,
-	.ndo_tx_timeout		= ks8695_timeout,
-	.ndo_set_mac_address	= ks8695_set_mac,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_multicast_list	= ks8695_set_multicast,
-};
-
-/**
- *	ks8695_probe - Probe and initialise a KS8695 ethernet interface
- *	@pdev: The platform device to probe
- *
- *	Initialise a KS8695 ethernet device from platform data.
- *
- *	This driver requires at least one IORESOURCE_MEM for the
- *	registers and two IORESOURCE_IRQ for the RX and TX IRQs
- *	respectively. It can optionally take an additional
- *	IORESOURCE_MEM for the switch or phy in the case of the lan or
- *	wan ports, and an IORESOURCE_IRQ for the link IRQ for the wan
- *	port.
- */
-static int __devinit
-ks8695_probe(struct platform_device *pdev)
-{
-	struct ks8695_priv *ksp;
-	struct net_device *ndev;
-	struct resource *regs_res, *phyiface_res;
-	struct resource *rxirq_res, *txirq_res, *linkirq_res;
-	int ret = 0;
-	int buff_n;
-	u32 machigh, maclow;
-
-	/* Initialise a net_device */
-	ndev = alloc_etherdev(sizeof(struct ks8695_priv));
-	if (!ndev) {
-		dev_err(&pdev->dev, "could not allocate device.\n");
-		return -ENOMEM;
-	}
-
-	SET_NETDEV_DEV(ndev, &pdev->dev);
-
-	dev_dbg(&pdev->dev, "ks8695_probe() called\n");
-
-	/* Configure our private structure a little */
-	ksp = netdev_priv(ndev);
-
-	ksp->dev = &pdev->dev;
-	ksp->ndev = ndev;
-	ksp->msg_enable = NETIF_MSG_LINK;
-
-	/* Retrieve resources */
-	regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	phyiface_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-
-	rxirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	txirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
-	linkirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 2);
-
-	if (!(regs_res && rxirq_res && txirq_res)) {
-		dev_err(ksp->dev, "insufficient resources\n");
-		ret = -ENOENT;
-		goto failure;
-	}
-
-	ksp->regs_req = request_mem_region(regs_res->start,
-					   resource_size(regs_res),
-					   pdev->name);
-
-	if (!ksp->regs_req) {
-		dev_err(ksp->dev, "cannot claim register space\n");
-		ret = -EIO;
-		goto failure;
-	}
-
-	ksp->io_regs = ioremap(regs_res->start, resource_size(regs_res));
-
-	if (!ksp->io_regs) {
-		dev_err(ksp->dev, "failed to ioremap registers\n");
-		ret = -EINVAL;
-		goto failure;
-	}
-
-	if (phyiface_res) {
-		ksp->phyiface_req =
-			request_mem_region(phyiface_res->start,
-					   resource_size(phyiface_res),
-					   phyiface_res->name);
-
-		if (!ksp->phyiface_req) {
-			dev_err(ksp->dev,
-				"cannot claim switch register space\n");
-			ret = -EIO;
-			goto failure;
-		}
-
-		ksp->phyiface_regs = ioremap(phyiface_res->start,
-					     resource_size(phyiface_res));
-
-		if (!ksp->phyiface_regs) {
-			dev_err(ksp->dev,
-				"failed to ioremap switch registers\n");
-			ret = -EINVAL;
-			goto failure;
-		}
-	}
-
-	ksp->rx_irq = rxirq_res->start;
-	ksp->rx_irq_name = rxirq_res->name ? rxirq_res->name : "Ethernet RX";
-	ksp->tx_irq = txirq_res->start;
-	ksp->tx_irq_name = txirq_res->name ? txirq_res->name : "Ethernet TX";
-	ksp->link_irq = (linkirq_res ? linkirq_res->start : -1);
-	ksp->link_irq_name = (linkirq_res && linkirq_res->name) ?
-		linkirq_res->name : "Ethernet Link";
-
-	/* driver system setup */
-	ndev->netdev_ops = &ks8695_netdev_ops;
-	ndev->watchdog_timeo	 = msecs_to_jiffies(watchdog);
-
-	netif_napi_add(ndev, &ksp->napi, ks8695_poll, NAPI_WEIGHT);
-
-	/* Retrieve the default MAC addr from the chip. */
-	/* The bootloader should have left it in there for us. */
-
-	machigh = ks8695_readreg(ksp, KS8695_MAH);
-	maclow = ks8695_readreg(ksp, KS8695_MAL);
-
-	ndev->dev_addr[0] = (machigh >> 8) & 0xFF;
-	ndev->dev_addr[1] = machigh & 0xFF;
-	ndev->dev_addr[2] = (maclow >> 24) & 0xFF;
-	ndev->dev_addr[3] = (maclow >> 16) & 0xFF;
-	ndev->dev_addr[4] = (maclow >> 8) & 0xFF;
-	ndev->dev_addr[5] = maclow & 0xFF;
-
-	if (!is_valid_ether_addr(ndev->dev_addr))
-		dev_warn(ksp->dev, "%s: Invalid ethernet MAC address. Please "
-			 "set using ifconfig\n", ndev->name);
-
-	/* In order to be efficient memory-wise, we allocate both
-	 * rings in one go.
-	 */
-	ksp->ring_base = dma_alloc_coherent(&pdev->dev, RING_DMA_SIZE,
-					    &ksp->ring_base_dma, GFP_KERNEL);
-	if (!ksp->ring_base) {
-		ret = -ENOMEM;
-		goto failure;
-	}
-
-	/* Specify the TX DMA ring buffer */
-	ksp->tx_ring = ksp->ring_base;
-	ksp->tx_ring_dma = ksp->ring_base_dma;
-
-	/* And initialise the queue's lock */
-	spin_lock_init(&ksp->txq_lock);
-	spin_lock_init(&ksp->rx_lock);
-
-	/* Specify the RX DMA ring buffer */
-	ksp->rx_ring = ksp->ring_base + TX_RING_DMA_SIZE;
-	ksp->rx_ring_dma = ksp->ring_base_dma + TX_RING_DMA_SIZE;
-
-	/* Zero the descriptor rings */
-	memset(ksp->tx_ring, 0, TX_RING_DMA_SIZE);
-	memset(ksp->rx_ring, 0, RX_RING_DMA_SIZE);
-
-	/* Build the rings */
-	for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
-		ksp->tx_ring[buff_n].next_desc =
-			cpu_to_le32(ksp->tx_ring_dma +
-				    (sizeof(struct tx_ring_desc) *
-				     ((buff_n + 1) & MAX_TX_DESC_MASK)));
-	}
-
-	for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
-		ksp->rx_ring[buff_n].next_desc =
-			cpu_to_le32(ksp->rx_ring_dma +
-				    (sizeof(struct rx_ring_desc) *
-				     ((buff_n + 1) & MAX_RX_DESC_MASK)));
-	}
-
-	/* Initialise the port (physically) */
-	if (ksp->phyiface_regs && ksp->link_irq == -1) {
-		ks8695_init_switch(ksp);
-		ksp->dtype = KS8695_DTYPE_LAN;
-		SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops);
-	} else if (ksp->phyiface_regs && ksp->link_irq != -1) {
-		ks8695_init_wan_phy(ksp);
-		ksp->dtype = KS8695_DTYPE_WAN;
-		SET_ETHTOOL_OPS(ndev, &ks8695_wan_ethtool_ops);
-	} else {
-		/* No initialisation since HPNA does not have a PHY */
-		ksp->dtype = KS8695_DTYPE_HPNA;
-		SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops);
-	}
-
-	/* And bring up the net_device with the net core */
-	platform_set_drvdata(pdev, ndev);
-	ret = register_netdev(ndev);
-
-	if (ret == 0) {
-		dev_info(ksp->dev, "ks8695 ethernet (%s) MAC: %pM\n",
-			 ks8695_port_type(ksp), ndev->dev_addr);
-	} else {
-		/* Report the failure to register the net_device */
-		dev_err(ksp->dev, "ks8695net: failed to register netdev.\n");
-		goto failure;
-	}
-
-	/* All is well */
-	return 0;
-
-	/* Error exit path */
-failure:
-	ks8695_release_device(ksp);
-	free_netdev(ndev);
-
-	return ret;
-}
-
-/**
- *	ks8695_drv_suspend - Suspend a KS8695 ethernet platform device.
- *	@pdev: The device to suspend
- *	@state: The suspend state
- *
- *	This routine detaches and shuts down a KS8695 ethernet device.
- */
-static int
-ks8695_drv_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct net_device *ndev = platform_get_drvdata(pdev);
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-
-	ksp->in_suspend = 1;
-
-	if (netif_running(ndev)) {
-		netif_device_detach(ndev);
-		ks8695_shutdown(ksp);
-	}
-
-	return 0;
-}
-
-/**
- *	ks8695_drv_resume - Resume a KS8695 ethernet platform device.
- *	@pdev: The device to resume
- *
- *	This routine re-initialises and re-attaches a KS8695 ethernet
- *	device.
- */
-static int
-ks8695_drv_resume(struct platform_device *pdev)
-{
-	struct net_device *ndev = platform_get_drvdata(pdev);
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-
-	if (netif_running(ndev)) {
-		ks8695_reset(ksp);
-		ks8695_init_net(ksp);
-		ks8695_set_multicast(ndev);
-		netif_device_attach(ndev);
-	}
-
-	ksp->in_suspend = 0;
-
-	return 0;
-}
-
-/**
- *	ks8695_drv_remove - Remove a KS8695 net device on driver unload.
- *	@pdev: The platform device to remove
- *
- *	This unregisters and releases a KS8695 ethernet device.
- */
-static int __devexit
-ks8695_drv_remove(struct platform_device *pdev)
-{
-	struct net_device *ndev = platform_get_drvdata(pdev);
-	struct ks8695_priv *ksp = netdev_priv(ndev);
-
-	platform_set_drvdata(pdev, NULL);
-	netif_napi_del(&ksp->napi);
-
-	unregister_netdev(ndev);
-	ks8695_release_device(ksp);
-	free_netdev(ndev);
-
-	dev_dbg(&pdev->dev, "released and freed device\n");
-	return 0;
-}
-
-static struct platform_driver ks8695_driver = {
-	.driver = {
-		.name	= MODULENAME,
-		.owner	= THIS_MODULE,
-	},
-	.probe		= ks8695_probe,
-	.remove		= __devexit_p(ks8695_drv_remove),
-	.suspend	= ks8695_drv_suspend,
-	.resume		= ks8695_drv_resume,
-};
-
-/* Module interface */
-
-static int __init
-ks8695_init(void)
-{
-	printk(KERN_INFO "%s Ethernet driver, V%s\n",
-	       MODULENAME, MODULEVERSION);
-
-	return platform_driver_register(&ks8695_driver);
-}
-
-static void __exit
-ks8695_cleanup(void)
-{
-	platform_driver_unregister(&ks8695_driver);
-}
-
-module_init(ks8695_init);
-module_exit(ks8695_cleanup);
-
-MODULE_AUTHOR("Simtec Electronics");
-MODULE_DESCRIPTION("Micrel KS8695 (Centaur) Ethernet driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" MODULENAME);
-
-module_param(watchdog, int, 0400);
-MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
diff -druN linux-libre-3.1-gnu/drivers/net/arm/ks8695net.h linux-libre-3.2-gnu/drivers/net/arm/ks8695net.h
--- linux-libre-3.1-gnu/drivers/net/arm/ks8695net.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arm/ks8695net.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,107 +0,0 @@
-/*
- * Micrel KS8695 (Centaur) Ethernet.
- *
- * Copyright 2008 Simtec Electronics
- *		  Daniel Silverstone <dsilvers@simtec.co.uk>
- *		  Vincent Sanders <vince@simtec.co.uk>
- */
-
-#ifndef KS8695NET_H
-#define KS8695NET_H
-
-/* Receive descriptor flags */
-#define RDES_OWN	(1 << 31)	/* Ownership */
-#define RDES_FS		(1 << 30)	/* First Descriptor */
-#define RDES_LS		(1 << 29)	/* Last Descriptor */
-#define RDES_IPE	(1 << 28)	/* IP Checksum error */
-#define RDES_TCPE	(1 << 27)	/* TCP Checksum error */
-#define RDES_UDPE	(1 << 26)	/* UDP Checksum error */
-#define RDES_ES		(1 << 25)	/* Error summary */
-#define RDES_MF		(1 << 24)	/* Multicast Frame */
-#define RDES_RE		(1 << 19)	/* MII Error reported */
-#define RDES_TL		(1 << 18)	/* Frame too Long */
-#define RDES_RF		(1 << 17)	/* Runt Frame */
-#define RDES_CE		(1 << 16)	/* CRC error */
-#define RDES_FT		(1 << 15)	/* Frame Type */
-#define RDES_FLEN	(0x7ff)		/* Frame Length */
-
-#define RDES_RER	(1 << 25)	/* Receive End of Ring */
-#define RDES_RBS	(0x7ff)		/* Receive Buffer Size */
-
-/* Transmit descriptor flags */
-
-#define TDES_OWN	(1 << 31)	/* Ownership */
-
-#define TDES_IC		(1 << 31)	/* Interrupt on Completion */
-#define TDES_FS		(1 << 30)	/* First Segment */
-#define TDES_LS		(1 << 29)	/* Last Segment */
-#define TDES_IPCKG	(1 << 28)	/* IP Checksum generate */
-#define TDES_TCPCKG	(1 << 27)	/* TCP Checksum generate */
-#define TDES_UDPCKG	(1 << 26)	/* UDP Checksum generate */
-#define TDES_TER	(1 << 25)	/* Transmit End of Ring */
-#define TDES_TBS	(0x7ff)		/* Transmit Buffer Size */
-
-/*
- * Network controller register offsets
- */
-#define KS8695_DTXC		(0x00)		/* DMA Transmit Control */
-#define KS8695_DRXC		(0x04)		/* DMA Receive Control */
-#define KS8695_DTSC		(0x08)		/* DMA Transmit Start Command */
-#define KS8695_DRSC		(0x0c)		/* DMA Receive Start Command */
-#define KS8695_TDLB		(0x10)		/* Transmit Descriptor List
-						 * Base Address
-						 */
-#define KS8695_RDLB		(0x14)		/* Receive Descriptor List
-						 * Base Address
-						 */
-#define KS8695_MAL		(0x18)		/* MAC Station Address Low */
-#define KS8695_MAH		(0x1c)		/* MAC Station Address High */
-#define KS8695_AAL_(n)		(0x80 + ((n)*8))	/* MAC Additional
-							 * Station Address
-							 * (0..15) Low
-							 */
-#define KS8695_AAH_(n)		(0x84 + ((n)*8))	/* MAC Additional
-							 * Station Address
-							 * (0..15) High
-							 */
-
-
-/* DMA Transmit Control Register */
-#define DTXC_TRST		(1    << 31)	/* Soft Reset */
-#define DTXC_TBS		(0x3f << 24)	/* Transmit Burst Size */
-#define DTXC_TUCG		(1    << 18)	/* Transmit UDP
-						 * Checksum Generate
-						 */
-#define DTXC_TTCG		(1    << 17)	/* Transmit TCP
-						 * Checksum Generate
-						 */
-#define DTXC_TICG		(1    << 16)	/* Transmit IP
-						 * Checksum Generate
-						 */
-#define DTXC_TFCE		(1    <<  9)	/* Transmit Flow
-						 * Control Enable
-						 */
-#define DTXC_TLB		(1    <<  8)	/* Loopback mode */
-#define DTXC_TEP		(1    <<  2)	/* Transmit Enable Padding */
-#define DTXC_TAC		(1    <<  1)	/* Transmit Add CRC */
-#define DTXC_TE			(1    <<  0)	/* TX Enable */
-
-/* DMA Receive Control Register */
-#define DRXC_RBS		(0x3f << 24)	/* Receive Burst Size */
-#define DRXC_RUCC		(1    << 18)	/* Receive UDP Checksum check */
-#define DRXC_RTCG		(1    << 17)	/* Receive TCP Checksum check */
-#define DRXC_RICG		(1    << 16)	/* Receive IP Checksum check */
-#define DRXC_RFCE		(1    <<  9)	/* Receive Flow Control
-						 * Enable
-						 */
-#define DRXC_RB			(1    <<  6)	/* Receive Broadcast */
-#define DRXC_RM			(1    <<  5)	/* Receive Multicast */
-#define DRXC_RU			(1    <<  4)	/* Receive Unicast */
-#define DRXC_RERR		(1    <<  3)	/* Receive Error Frame */
-#define DRXC_RA			(1    <<  2)	/* Receive All */
-#define DRXC_RE			(1    <<  0)	/* RX Enable */
-
-/* Additional Station Address High */
-#define AAH_E			(1    << 31)	/* Address Enabled */
-
-#endif /* KS8695NET_H */
diff -druN linux-libre-3.1-gnu/drivers/net/arm/Makefile linux-libre-3.2-gnu/drivers/net/arm/Makefile
--- linux-libre-3.1-gnu/drivers/net/arm/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arm/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-# File: drivers/net/arm/Makefile
-#
-# Makefile for the ARM network device drivers
-#
-
-obj-$(CONFIG_ARM_AM79C961A)	+= am79c961a.o
-obj-$(CONFIG_ARM_ETHERH)	+= etherh.o
-obj-$(CONFIG_ARM_ETHER3)	+= ether3.o
-obj-$(CONFIG_ARM_ETHER1)	+= ether1.o
-obj-$(CONFIG_ARM_AT91_ETHER)	+= at91_ether.o
-obj-$(CONFIG_ARM_KS8695_ETHER)	+= ks8695net.o
-obj-$(CONFIG_EP93XX_ETH)	+= ep93xx_eth.o
-obj-$(CONFIG_IXP4XX_ETH)	+= ixp4xx_eth.o
-obj-$(CONFIG_W90P910_ETH)	+= w90p910_ether.o
diff -druN linux-libre-3.1-gnu/drivers/net/arm/w90p910_ether.c linux-libre-3.2-gnu/drivers/net/arm/w90p910_ether.c
--- linux-libre-3.1-gnu/drivers/net/arm/w90p910_ether.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/arm/w90p910_ether.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1123 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/mii.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/ethtool.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/gfp.h>
-
-#define DRV_MODULE_NAME		"w90p910-emc"
-#define DRV_MODULE_VERSION	"0.1"
-
-/* Ethernet MAC Registers */
-#define REG_CAMCMR		0x00
-#define REG_CAMEN		0x04
-#define REG_CAMM_BASE		0x08
-#define REG_CAML_BASE		0x0c
-#define REG_TXDLSA		0x88
-#define REG_RXDLSA		0x8C
-#define REG_MCMDR		0x90
-#define REG_MIID		0x94
-#define REG_MIIDA		0x98
-#define REG_FFTCR		0x9C
-#define REG_TSDR		0xa0
-#define REG_RSDR		0xa4
-#define REG_DMARFC		0xa8
-#define REG_MIEN		0xac
-#define REG_MISTA		0xb0
-#define REG_CTXDSA		0xcc
-#define REG_CTXBSA		0xd0
-#define REG_CRXDSA		0xd4
-#define REG_CRXBSA		0xd8
-
-/* mac controller bit */
-#define MCMDR_RXON		0x01
-#define MCMDR_ACP		(0x01 << 3)
-#define MCMDR_SPCRC		(0x01 << 5)
-#define MCMDR_TXON		(0x01 << 8)
-#define MCMDR_FDUP		(0x01 << 18)
-#define MCMDR_ENMDC		(0x01 << 19)
-#define MCMDR_OPMOD		(0x01 << 20)
-#define SWR			(0x01 << 24)
-
-/* cam command regiser */
-#define CAMCMR_AUP		0x01
-#define CAMCMR_AMP		(0x01 << 1)
-#define CAMCMR_ABP		(0x01 << 2)
-#define CAMCMR_CCAM		(0x01 << 3)
-#define CAMCMR_ECMP		(0x01 << 4)
-#define CAM0EN			0x01
-
-/* mac mii controller bit */
-#define MDCCR			(0x0a << 20)
-#define PHYAD			(0x01 << 8)
-#define PHYWR			(0x01 << 16)
-#define PHYBUSY			(0x01 << 17)
-#define PHYPRESP		(0x01 << 18)
-#define CAM_ENTRY_SIZE		0x08
-
-/* rx and tx status */
-#define TXDS_TXCP		(0x01 << 19)
-#define RXDS_CRCE		(0x01 << 17)
-#define RXDS_PTLE		(0x01 << 19)
-#define RXDS_RXGD		(0x01 << 20)
-#define RXDS_ALIE		(0x01 << 21)
-#define RXDS_RP			(0x01 << 22)
-
-/* mac interrupt status*/
-#define MISTA_EXDEF		(0x01 << 19)
-#define MISTA_TXBERR		(0x01 << 24)
-#define MISTA_TDU		(0x01 << 23)
-#define MISTA_RDU		(0x01 << 10)
-#define MISTA_RXBERR		(0x01 << 11)
-
-#define ENSTART			0x01
-#define ENRXINTR		0x01
-#define ENRXGD			(0x01 << 4)
-#define ENRXBERR		(0x01 << 11)
-#define ENTXINTR		(0x01 << 16)
-#define ENTXCP			(0x01 << 18)
-#define ENTXABT			(0x01 << 21)
-#define ENTXBERR		(0x01 << 24)
-#define ENMDC			(0x01 << 19)
-#define PHYBUSY			(0x01 << 17)
-#define MDCCR_VAL		0xa00000
-
-/* rx and tx owner bit */
-#define RX_OWEN_DMA		(0x01 << 31)
-#define RX_OWEN_CPU		(~(0x03 << 30))
-#define TX_OWEN_DMA		(0x01 << 31)
-#define TX_OWEN_CPU		(~(0x01 << 31))
-
-/* tx frame desc controller bit */
-#define MACTXINTEN		0x04
-#define CRCMODE			0x02
-#define PADDINGMODE		0x01
-
-/* fftcr controller bit */
-#define TXTHD 			(0x03 << 8)
-#define BLENGTH			(0x01 << 20)
-
-/* global setting for driver */
-#define RX_DESC_SIZE		50
-#define TX_DESC_SIZE		10
-#define MAX_RBUFF_SZ		0x600
-#define MAX_TBUFF_SZ		0x600
-#define TX_TIMEOUT		(HZ/2)
-#define DELAY			1000
-#define CAM0			0x0
-
-static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg);
-
-struct w90p910_rxbd {
-	unsigned int sl;
-	unsigned int buffer;
-	unsigned int reserved;
-	unsigned int next;
-};
-
-struct w90p910_txbd {
-	unsigned int mode;
-	unsigned int buffer;
-	unsigned int sl;
-	unsigned int next;
-};
-
-struct recv_pdesc {
-	struct w90p910_rxbd desclist[RX_DESC_SIZE];
-	char recv_buf[RX_DESC_SIZE][MAX_RBUFF_SZ];
-};
-
-struct tran_pdesc {
-	struct w90p910_txbd desclist[TX_DESC_SIZE];
-	char tran_buf[TX_DESC_SIZE][MAX_TBUFF_SZ];
-};
-
-struct  w90p910_ether {
-	struct recv_pdesc *rdesc;
-	struct tran_pdesc *tdesc;
-	dma_addr_t rdesc_phys;
-	dma_addr_t tdesc_phys;
-	struct net_device_stats stats;
-	struct platform_device *pdev;
-	struct resource *res;
-	struct sk_buff *skb;
-	struct clk *clk;
-	struct clk *rmiiclk;
-	struct mii_if_info mii;
-	struct timer_list check_timer;
-	void __iomem *reg;
-	int rxirq;
-	int txirq;
-	unsigned int cur_tx;
-	unsigned int cur_rx;
-	unsigned int finish_tx;
-	unsigned int rx_packets;
-	unsigned int rx_bytes;
-	unsigned int start_tx_ptr;
-	unsigned int start_rx_ptr;
-	unsigned int linkflag;
-};
-
-static void update_linkspeed_register(struct net_device *dev,
-				unsigned int speed, unsigned int duplex)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	val = __raw_readl(ether->reg + REG_MCMDR);
-
-	if (speed == SPEED_100) {
-		/* 100 full/half duplex */
-		if (duplex == DUPLEX_FULL) {
-			val |= (MCMDR_OPMOD | MCMDR_FDUP);
-		} else {
-			val |= MCMDR_OPMOD;
-			val &= ~MCMDR_FDUP;
-		}
-	} else {
-		/* 10 full/half duplex */
-		if (duplex == DUPLEX_FULL) {
-			val |= MCMDR_FDUP;
-			val &= ~MCMDR_OPMOD;
-		} else {
-			val &= ~(MCMDR_FDUP | MCMDR_OPMOD);
-		}
-	}
-
-	__raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void update_linkspeed(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	struct platform_device *pdev;
-	unsigned int bmsr, bmcr, lpa, speed, duplex;
-
-	pdev = ether->pdev;
-
-	if (!mii_link_ok(&ether->mii)) {
-		ether->linkflag = 0x0;
-		netif_carrier_off(dev);
-		dev_warn(&pdev->dev, "%s: Link down.\n", dev->name);
-		return;
-	}
-
-	if (ether->linkflag == 1)
-		return;
-
-	bmsr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMSR);
-	bmcr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMCR);
-
-	if (bmcr & BMCR_ANENABLE) {
-		if (!(bmsr & BMSR_ANEGCOMPLETE))
-			return;
-
-		lpa = w90p910_mdio_read(dev, ether->mii.phy_id, MII_LPA);
-
-		if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF))
-			speed = SPEED_100;
-		else
-			speed = SPEED_10;
-
-		if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL))
-			duplex = DUPLEX_FULL;
-		else
-			duplex = DUPLEX_HALF;
-
-	} else {
-		speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
-		duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
-	}
-
-	update_linkspeed_register(dev, speed, duplex);
-
-	dev_info(&pdev->dev, "%s: Link now %i-%s\n", dev->name, speed,
-			(duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
-	ether->linkflag = 0x01;
-
-	netif_carrier_on(dev);
-}
-
-static void w90p910_check_link(unsigned long dev_id)
-{
-	struct net_device *dev = (struct net_device *) dev_id;
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	update_linkspeed(dev);
-	mod_timer(&ether->check_timer, jiffies + msecs_to_jiffies(1000));
-}
-
-static void w90p910_write_cam(struct net_device *dev,
-				unsigned int x, unsigned char *pval)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int msw, lsw;
-
-	msw = (pval[0] << 24) | (pval[1] << 16) | (pval[2] << 8) | pval[3];
-
-	lsw = (pval[4] << 24) | (pval[5] << 16);
-
-	__raw_writel(lsw, ether->reg + REG_CAML_BASE + x * CAM_ENTRY_SIZE);
-	__raw_writel(msw, ether->reg + REG_CAMM_BASE + x * CAM_ENTRY_SIZE);
-}
-
-static int w90p910_init_desc(struct net_device *dev)
-{
-	struct w90p910_ether *ether;
-	struct w90p910_txbd  *tdesc;
-	struct w90p910_rxbd  *rdesc;
-	struct platform_device *pdev;
-	unsigned int i;
-
-	ether = netdev_priv(dev);
-	pdev = ether->pdev;
-
-	ether->tdesc = (struct tran_pdesc *)
-		dma_alloc_coherent(&pdev->dev, sizeof(struct tran_pdesc),
-					&ether->tdesc_phys, GFP_KERNEL);
-
-	if (!ether->tdesc) {
-		dev_err(&pdev->dev, "Failed to allocate memory for tx desc\n");
-		return -ENOMEM;
-	}
-
-	ether->rdesc = (struct recv_pdesc *)
-		dma_alloc_coherent(&pdev->dev, sizeof(struct recv_pdesc),
-					&ether->rdesc_phys, GFP_KERNEL);
-
-	if (!ether->rdesc) {
-		dev_err(&pdev->dev, "Failed to allocate memory for rx desc\n");
-		dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc),
-					ether->tdesc, ether->tdesc_phys);
-		return -ENOMEM;
-	}
-
-	for (i = 0; i < TX_DESC_SIZE; i++) {
-		unsigned int offset;
-
-		tdesc = &(ether->tdesc->desclist[i]);
-
-		if (i == TX_DESC_SIZE - 1)
-			offset = offsetof(struct tran_pdesc, desclist[0]);
-		else
-			offset = offsetof(struct tran_pdesc, desclist[i + 1]);
-
-		tdesc->next = ether->tdesc_phys + offset;
-		tdesc->buffer = ether->tdesc_phys +
-			offsetof(struct tran_pdesc, tran_buf[i]);
-		tdesc->sl = 0;
-		tdesc->mode = 0;
-	}
-
-	ether->start_tx_ptr = ether->tdesc_phys;
-
-	for (i = 0; i < RX_DESC_SIZE; i++) {
-		unsigned int offset;
-
-		rdesc = &(ether->rdesc->desclist[i]);
-
-		if (i == RX_DESC_SIZE - 1)
-			offset = offsetof(struct recv_pdesc, desclist[0]);
-		else
-			offset = offsetof(struct recv_pdesc, desclist[i + 1]);
-
-		rdesc->next = ether->rdesc_phys + offset;
-		rdesc->sl = RX_OWEN_DMA;
-		rdesc->buffer = ether->rdesc_phys +
-			offsetof(struct recv_pdesc, recv_buf[i]);
-	  }
-
-	ether->start_rx_ptr = ether->rdesc_phys;
-
-	return 0;
-}
-
-static void w90p910_set_fifo_threshold(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	val = TXTHD | BLENGTH;
-	__raw_writel(val, ether->reg + REG_FFTCR);
-}
-
-static void w90p910_return_default_idle(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	val = __raw_readl(ether->reg + REG_MCMDR);
-	val |= SWR;
-	__raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void w90p910_trigger_rx(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	__raw_writel(ENSTART, ether->reg + REG_RSDR);
-}
-
-static void w90p910_trigger_tx(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	__raw_writel(ENSTART, ether->reg + REG_TSDR);
-}
-
-static void w90p910_enable_mac_interrupt(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	val = ENTXINTR | ENRXINTR | ENRXGD | ENTXCP;
-	val |= ENTXBERR | ENRXBERR | ENTXABT;
-
-	__raw_writel(val, ether->reg + REG_MIEN);
-}
-
-static void w90p910_get_and_clear_int(struct net_device *dev,
-							unsigned int *val)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	*val = __raw_readl(ether->reg + REG_MISTA);
-	__raw_writel(*val, ether->reg + REG_MISTA);
-}
-
-static void w90p910_set_global_maccmd(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	val = __raw_readl(ether->reg + REG_MCMDR);
-	val |= MCMDR_SPCRC | MCMDR_ENMDC | MCMDR_ACP | ENMDC;
-	__raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void w90p910_enable_cam(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	w90p910_write_cam(dev, CAM0, dev->dev_addr);
-
-	val = __raw_readl(ether->reg + REG_CAMEN);
-	val |= CAM0EN;
-	__raw_writel(val, ether->reg + REG_CAMEN);
-}
-
-static void w90p910_enable_cam_command(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	val = CAMCMR_ECMP | CAMCMR_ABP | CAMCMR_AMP;
-	__raw_writel(val, ether->reg + REG_CAMCMR);
-}
-
-static void w90p910_enable_tx(struct net_device *dev, unsigned int enable)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	val = __raw_readl(ether->reg + REG_MCMDR);
-
-	if (enable)
-		val |= MCMDR_TXON;
-	else
-		val &= ~MCMDR_TXON;
-
-	__raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void w90p910_enable_rx(struct net_device *dev, unsigned int enable)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	unsigned int val;
-
-	val = __raw_readl(ether->reg + REG_MCMDR);
-
-	if (enable)
-		val |= MCMDR_RXON;
-	else
-		val &= ~MCMDR_RXON;
-
-	__raw_writel(val, ether->reg + REG_MCMDR);
-}
-
-static void w90p910_set_curdest(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	__raw_writel(ether->start_rx_ptr, ether->reg + REG_RXDLSA);
-	__raw_writel(ether->start_tx_ptr, ether->reg + REG_TXDLSA);
-}
-
-static void w90p910_reset_mac(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	w90p910_enable_tx(dev, 0);
-	w90p910_enable_rx(dev, 0);
-	w90p910_set_fifo_threshold(dev);
-	w90p910_return_default_idle(dev);
-
-	if (!netif_queue_stopped(dev))
-		netif_stop_queue(dev);
-
-	w90p910_init_desc(dev);
-
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	ether->cur_tx = 0x0;
-	ether->finish_tx = 0x0;
-	ether->cur_rx = 0x0;
-
-	w90p910_set_curdest(dev);
-	w90p910_enable_cam(dev);
-	w90p910_enable_cam_command(dev);
-	w90p910_enable_mac_interrupt(dev);
-	w90p910_enable_tx(dev, 1);
-	w90p910_enable_rx(dev, 1);
-	w90p910_trigger_tx(dev);
-	w90p910_trigger_rx(dev);
-
-	dev->trans_start = jiffies; /* prevent tx timeout */
-
-	if (netif_queue_stopped(dev))
-		netif_wake_queue(dev);
-}
-
-static void w90p910_mdio_write(struct net_device *dev,
-					int phy_id, int reg, int data)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	struct platform_device *pdev;
-	unsigned int val, i;
-
-	pdev = ether->pdev;
-
-	__raw_writel(data, ether->reg + REG_MIID);
-
-	val = (phy_id << 0x08) | reg;
-	val |= PHYBUSY | PHYWR | MDCCR_VAL;
-	__raw_writel(val, ether->reg + REG_MIIDA);
-
-	for (i = 0; i < DELAY; i++) {
-		if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0)
-			break;
-	}
-
-	if (i == DELAY)
-		dev_warn(&pdev->dev, "mdio write timed out\n");
-}
-
-static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	struct platform_device *pdev;
-	unsigned int val, i, data;
-
-	pdev = ether->pdev;
-
-	val = (phy_id << 0x08) | reg;
-	val |= PHYBUSY | MDCCR_VAL;
-	__raw_writel(val, ether->reg + REG_MIIDA);
-
-	for (i = 0; i < DELAY; i++) {
-		if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0)
-			break;
-	}
-
-	if (i == DELAY) {
-		dev_warn(&pdev->dev, "mdio read timed out\n");
-		data = 0xffff;
-	} else {
-		data = __raw_readl(ether->reg + REG_MIID);
-	}
-
-	return data;
-}
-
-static int w90p910_set_mac_address(struct net_device *dev, void *addr)
-{
-	struct sockaddr *address = addr;
-
-	if (!is_valid_ether_addr(address->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
-	w90p910_write_cam(dev, CAM0, dev->dev_addr);
-
-	return 0;
-}
-
-static int w90p910_ether_close(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	struct platform_device *pdev;
-
-	pdev = ether->pdev;
-
-	dma_free_coherent(&pdev->dev, sizeof(struct recv_pdesc),
-					ether->rdesc, ether->rdesc_phys);
-	dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc),
-					ether->tdesc, ether->tdesc_phys);
-
-	netif_stop_queue(dev);
-
-	del_timer_sync(&ether->check_timer);
-	clk_disable(ether->rmiiclk);
-	clk_disable(ether->clk);
-
-	free_irq(ether->txirq, dev);
-	free_irq(ether->rxirq, dev);
-
-	return 0;
-}
-
-static struct net_device_stats *w90p910_ether_stats(struct net_device *dev)
-{
-	struct w90p910_ether *ether;
-
-	ether = netdev_priv(dev);
-
-	return &ether->stats;
-}
-
-static int w90p910_send_frame(struct net_device *dev,
-					unsigned char *data, int length)
-{
-	struct w90p910_ether *ether;
-	struct w90p910_txbd *txbd;
-	struct platform_device *pdev;
-	unsigned char *buffer;
-
-	ether = netdev_priv(dev);
-	pdev = ether->pdev;
-
-	txbd = &ether->tdesc->desclist[ether->cur_tx];
-	buffer = ether->tdesc->tran_buf[ether->cur_tx];
-
-	if (length > 1514) {
-		dev_err(&pdev->dev, "send data %d bytes, check it\n", length);
-		length = 1514;
-	}
-
-	txbd->sl = length & 0xFFFF;
-
-	memcpy(buffer, data, length);
-
-	txbd->mode = TX_OWEN_DMA | PADDINGMODE | CRCMODE | MACTXINTEN;
-
-	w90p910_enable_tx(dev, 1);
-
-	w90p910_trigger_tx(dev);
-
-	if (++ether->cur_tx >= TX_DESC_SIZE)
-		ether->cur_tx = 0;
-
-	txbd = &ether->tdesc->desclist[ether->cur_tx];
-
-	if (txbd->mode & TX_OWEN_DMA)
-		netif_stop_queue(dev);
-
-	return 0;
-}
-
-static int w90p910_ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	if (!(w90p910_send_frame(dev, skb->data, skb->len))) {
-		ether->skb = skb;
-		dev_kfree_skb_irq(skb);
-		return 0;
-	}
-	return -EAGAIN;
-}
-
-static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id)
-{
-	struct w90p910_ether *ether;
-	struct w90p910_txbd  *txbd;
-	struct platform_device *pdev;
-	struct net_device *dev;
-	unsigned int cur_entry, entry, status;
-
-	dev = dev_id;
-	ether = netdev_priv(dev);
-	pdev = ether->pdev;
-
-	w90p910_get_and_clear_int(dev, &status);
-
-	cur_entry = __raw_readl(ether->reg + REG_CTXDSA);
-
-	entry = ether->tdesc_phys +
-		offsetof(struct tran_pdesc, desclist[ether->finish_tx]);
-
-	while (entry != cur_entry) {
-		txbd = &ether->tdesc->desclist[ether->finish_tx];
-
-		if (++ether->finish_tx >= TX_DESC_SIZE)
-			ether->finish_tx = 0;
-
-		if (txbd->sl & TXDS_TXCP) {
-			ether->stats.tx_packets++;
-			ether->stats.tx_bytes += txbd->sl & 0xFFFF;
-		} else {
-			ether->stats.tx_errors++;
-		}
-
-		txbd->sl = 0x0;
-		txbd->mode = 0x0;
-
-		if (netif_queue_stopped(dev))
-			netif_wake_queue(dev);
-
-		entry = ether->tdesc_phys +
-			offsetof(struct tran_pdesc, desclist[ether->finish_tx]);
-	}
-
-	if (status & MISTA_EXDEF) {
-		dev_err(&pdev->dev, "emc defer exceed interrupt\n");
-	} else if (status & MISTA_TXBERR) {
-		dev_err(&pdev->dev, "emc bus error interrupt\n");
-		w90p910_reset_mac(dev);
-	} else if (status & MISTA_TDU) {
-		if (netif_queue_stopped(dev))
-			netif_wake_queue(dev);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static void netdev_rx(struct net_device *dev)
-{
-	struct w90p910_ether *ether;
-	struct w90p910_rxbd *rxbd;
-	struct platform_device *pdev;
-	struct sk_buff *skb;
-	unsigned char *data;
-	unsigned int length, status, val, entry;
-
-	ether = netdev_priv(dev);
-	pdev = ether->pdev;
-
-	rxbd = &ether->rdesc->desclist[ether->cur_rx];
-
-	do {
-		val = __raw_readl(ether->reg + REG_CRXDSA);
-
-		entry = ether->rdesc_phys +
-			offsetof(struct recv_pdesc, desclist[ether->cur_rx]);
-
-		if (val == entry)
-			break;
-
-		status = rxbd->sl;
-		length = status & 0xFFFF;
-
-		if (status & RXDS_RXGD) {
-			data = ether->rdesc->recv_buf[ether->cur_rx];
-			skb = dev_alloc_skb(length+2);
-			if (!skb) {
-				dev_err(&pdev->dev, "get skb buffer error\n");
-				ether->stats.rx_dropped++;
-				return;
-			}
-
-			skb_reserve(skb, 2);
-			skb_put(skb, length);
-			skb_copy_to_linear_data(skb, data, length);
-			skb->protocol = eth_type_trans(skb, dev);
-			ether->stats.rx_packets++;
-			ether->stats.rx_bytes += length;
-			netif_rx(skb);
-		} else {
-			ether->stats.rx_errors++;
-
-			if (status & RXDS_RP) {
-				dev_err(&pdev->dev, "rx runt err\n");
-				ether->stats.rx_length_errors++;
-			} else if (status & RXDS_CRCE) {
-				dev_err(&pdev->dev, "rx crc err\n");
-				ether->stats.rx_crc_errors++;
-			} else if (status & RXDS_ALIE) {
-				dev_err(&pdev->dev, "rx aligment err\n");
-				ether->stats.rx_frame_errors++;
-			} else if (status & RXDS_PTLE) {
-				dev_err(&pdev->dev, "rx longer err\n");
-				ether->stats.rx_over_errors++;
-			}
-		}
-
-		rxbd->sl = RX_OWEN_DMA;
-		rxbd->reserved = 0x0;
-
-		if (++ether->cur_rx >= RX_DESC_SIZE)
-			ether->cur_rx = 0;
-
-		rxbd = &ether->rdesc->desclist[ether->cur_rx];
-
-	} while (1);
-}
-
-static irqreturn_t w90p910_rx_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev;
-	struct w90p910_ether  *ether;
-	struct platform_device *pdev;
-	unsigned int status;
-
-	dev = dev_id;
-	ether = netdev_priv(dev);
-	pdev = ether->pdev;
-
-	w90p910_get_and_clear_int(dev, &status);
-
-	if (status & MISTA_RDU) {
-		netdev_rx(dev);
-		w90p910_trigger_rx(dev);
-
-		return IRQ_HANDLED;
-	} else if (status & MISTA_RXBERR) {
-		dev_err(&pdev->dev, "emc rx bus error\n");
-		w90p910_reset_mac(dev);
-	}
-
-	netdev_rx(dev);
-	return IRQ_HANDLED;
-}
-
-static int w90p910_ether_open(struct net_device *dev)
-{
-	struct w90p910_ether *ether;
-	struct platform_device *pdev;
-
-	ether = netdev_priv(dev);
-	pdev = ether->pdev;
-
-	w90p910_reset_mac(dev);
-	w90p910_set_fifo_threshold(dev);
-	w90p910_set_curdest(dev);
-	w90p910_enable_cam(dev);
-	w90p910_enable_cam_command(dev);
-	w90p910_enable_mac_interrupt(dev);
-	w90p910_set_global_maccmd(dev);
-	w90p910_enable_rx(dev, 1);
-
-	clk_enable(ether->rmiiclk);
-	clk_enable(ether->clk);
-
-	ether->rx_packets = 0x0;
-	ether->rx_bytes = 0x0;
-
-	if (request_irq(ether->txirq, w90p910_tx_interrupt,
-						0x0, pdev->name, dev)) {
-		dev_err(&pdev->dev, "register irq tx failed\n");
-		return -EAGAIN;
-	}
-
-	if (request_irq(ether->rxirq, w90p910_rx_interrupt,
-						0x0, pdev->name, dev)) {
-		dev_err(&pdev->dev, "register irq rx failed\n");
-		free_irq(ether->txirq, dev);
-		return -EAGAIN;
-	}
-
-	mod_timer(&ether->check_timer, jiffies + msecs_to_jiffies(1000));
-	netif_start_queue(dev);
-	w90p910_trigger_rx(dev);
-
-	dev_info(&pdev->dev, "%s is OPENED\n", dev->name);
-
-	return 0;
-}
-
-static void w90p910_ether_set_multicast_list(struct net_device *dev)
-{
-	struct w90p910_ether *ether;
-	unsigned int rx_mode;
-
-	ether = netdev_priv(dev);
-
-	if (dev->flags & IFF_PROMISC)
-		rx_mode = CAMCMR_AUP | CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP;
-	else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev))
-		rx_mode = CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP;
-	else
-		rx_mode = CAMCMR_ECMP | CAMCMR_ABP;
-	__raw_writel(rx_mode, ether->reg + REG_CAMCMR);
-}
-
-static int w90p910_ether_ioctl(struct net_device *dev,
-						struct ifreq *ifr, int cmd)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	struct mii_ioctl_data *data = if_mii(ifr);
-
-	return generic_mii_ioctl(&ether->mii, data, cmd, NULL);
-}
-
-static void w90p910_get_drvinfo(struct net_device *dev,
-					struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, DRV_MODULE_NAME);
-	strcpy(info->version, DRV_MODULE_VERSION);
-}
-
-static int w90p910_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	return mii_ethtool_gset(&ether->mii, cmd);
-}
-
-static int w90p910_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	return mii_ethtool_sset(&ether->mii, cmd);
-}
-
-static int w90p910_nway_reset(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	return mii_nway_restart(&ether->mii);
-}
-
-static u32 w90p910_get_link(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	return mii_link_ok(&ether->mii);
-}
-
-static const struct ethtool_ops w90p910_ether_ethtool_ops = {
-	.get_settings	= w90p910_get_settings,
-	.set_settings	= w90p910_set_settings,
-	.get_drvinfo	= w90p910_get_drvinfo,
-	.nway_reset	= w90p910_nway_reset,
-	.get_link	= w90p910_get_link,
-};
-
-static const struct net_device_ops w90p910_ether_netdev_ops = {
-	.ndo_open		= w90p910_ether_open,
-	.ndo_stop		= w90p910_ether_close,
-	.ndo_start_xmit		= w90p910_ether_start_xmit,
-	.ndo_get_stats		= w90p910_ether_stats,
-	.ndo_set_multicast_list	= w90p910_ether_set_multicast_list,
-	.ndo_set_mac_address	= w90p910_set_mac_address,
-	.ndo_do_ioctl		= w90p910_ether_ioctl,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
-};
-
-static void __init get_mac_address(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-	struct platform_device *pdev;
-	char addr[6];
-
-	pdev = ether->pdev;
-
-	addr[0] = 0x00;
-	addr[1] = 0x02;
-	addr[2] = 0xac;
-	addr[3] = 0x55;
-	addr[4] = 0x88;
-	addr[5] = 0xa8;
-
-	if (is_valid_ether_addr(addr))
-		memcpy(dev->dev_addr, &addr, 0x06);
-	else
-		dev_err(&pdev->dev, "invalid mac address\n");
-}
-
-static int w90p910_ether_setup(struct net_device *dev)
-{
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	ether_setup(dev);
-	dev->netdev_ops = &w90p910_ether_netdev_ops;
-	dev->ethtool_ops = &w90p910_ether_ethtool_ops;
-
-	dev->tx_queue_len = 16;
-	dev->dma = 0x0;
-	dev->watchdog_timeo = TX_TIMEOUT;
-
-	get_mac_address(dev);
-
-	ether->cur_tx = 0x0;
-	ether->cur_rx = 0x0;
-	ether->finish_tx = 0x0;
-	ether->linkflag = 0x0;
-	ether->mii.phy_id = 0x01;
-	ether->mii.phy_id_mask = 0x1f;
-	ether->mii.reg_num_mask = 0x1f;
-	ether->mii.dev = dev;
-	ether->mii.mdio_read = w90p910_mdio_read;
-	ether->mii.mdio_write = w90p910_mdio_write;
-
-	setup_timer(&ether->check_timer, w90p910_check_link,
-						(unsigned long)dev);
-
-	return 0;
-}
-
-static int __devinit w90p910_ether_probe(struct platform_device *pdev)
-{
-	struct w90p910_ether *ether;
-	struct net_device *dev;
-	int error;
-
-	dev = alloc_etherdev(sizeof(struct w90p910_ether));
-	if (!dev)
-		return -ENOMEM;
-
-	ether = netdev_priv(dev);
-
-	ether->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (ether->res == NULL) {
-		dev_err(&pdev->dev, "failed to get I/O memory\n");
-		error = -ENXIO;
-		goto failed_free;
-	}
-
-	if (!request_mem_region(ether->res->start,
-				resource_size(ether->res), pdev->name)) {
-		dev_err(&pdev->dev, "failed to request I/O memory\n");
-		error = -EBUSY;
-		goto failed_free;
-	}
-
-	ether->reg = ioremap(ether->res->start, resource_size(ether->res));
-	if (ether->reg == NULL) {
-		dev_err(&pdev->dev, "failed to remap I/O memory\n");
-		error = -ENXIO;
-		goto failed_free_mem;
-	}
-
-	ether->txirq = platform_get_irq(pdev, 0);
-	if (ether->txirq < 0) {
-		dev_err(&pdev->dev, "failed to get ether tx irq\n");
-		error = -ENXIO;
-		goto failed_free_io;
-	}
-
-	ether->rxirq = platform_get_irq(pdev, 1);
-	if (ether->rxirq < 0) {
-		dev_err(&pdev->dev, "failed to get ether rx irq\n");
-		error = -ENXIO;
-		goto failed_free_txirq;
-	}
-
-	platform_set_drvdata(pdev, dev);
-
-	ether->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(ether->clk)) {
-		dev_err(&pdev->dev, "failed to get ether clock\n");
-		error = PTR_ERR(ether->clk);
-		goto failed_free_rxirq;
-	}
-
-	ether->rmiiclk = clk_get(&pdev->dev, "RMII");
-	if (IS_ERR(ether->rmiiclk)) {
-		dev_err(&pdev->dev, "failed to get ether clock\n");
-		error = PTR_ERR(ether->rmiiclk);
-		goto failed_put_clk;
-	}
-
-	ether->pdev = pdev;
-
-	w90p910_ether_setup(dev);
-
-	error = register_netdev(dev);
-	if (error != 0) {
-		dev_err(&pdev->dev, "Regiter EMC w90p910 FAILED\n");
-		error = -ENODEV;
-		goto failed_put_rmiiclk;
-	}
-
-	return 0;
-failed_put_rmiiclk:
-	clk_put(ether->rmiiclk);
-failed_put_clk:
-	clk_put(ether->clk);
-failed_free_rxirq:
-	free_irq(ether->rxirq, pdev);
-	platform_set_drvdata(pdev, NULL);
-failed_free_txirq:
-	free_irq(ether->txirq, pdev);
-failed_free_io:
-	iounmap(ether->reg);
-failed_free_mem:
-	release_mem_region(ether->res->start, resource_size(ether->res));
-failed_free:
-	free_netdev(dev);
-	return error;
-}
-
-static int __devexit w90p910_ether_remove(struct platform_device *pdev)
-{
-	struct net_device *dev = platform_get_drvdata(pdev);
-	struct w90p910_ether *ether = netdev_priv(dev);
-
-	unregister_netdev(dev);
-
-	clk_put(ether->rmiiclk);
-	clk_put(ether->clk);
-
-	iounmap(ether->reg);
-	release_mem_region(ether->res->start, resource_size(ether->res));
-
-	free_irq(ether->txirq, dev);
-	free_irq(ether->rxirq, dev);
-
-	del_timer_sync(&ether->check_timer);
-	platform_set_drvdata(pdev, NULL);
-
-	free_netdev(dev);
-	return 0;
-}
-
-static struct platform_driver w90p910_ether_driver = {
-	.probe		= w90p910_ether_probe,
-	.remove		= __devexit_p(w90p910_ether_remove),
-	.driver		= {
-		.name	= "nuc900-emc",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init w90p910_ether_init(void)
-{
-	return platform_driver_register(&w90p910_ether_driver);
-}
-
-static void __exit w90p910_ether_exit(void)
-{
-	platform_driver_unregister(&w90p910_ether_driver);
-}
-
-module_init(w90p910_ether_init);
-module_exit(w90p910_ether_exit);
-
-MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
-MODULE_DESCRIPTION("w90p910 MAC driver!");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:nuc900-emc");
-
diff -druN linux-libre-3.1-gnu/drivers/net/at1700.c linux-libre-3.2-gnu/drivers/net/at1700.c
--- linux-libre-3.1-gnu/drivers/net/at1700.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/at1700.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,900 +0,0 @@
-/* at1700.c: A network device driver for  the Allied Telesis AT1700.
-
-	Written 1993-98 by Donald Becker.
-
-	Copyright 1993 United States Government as represented by the
-	Director, National Security Agency.
-
-	This software may be used and distributed according to the terms
-	of the GNU General Public License, incorporated herein by reference.
-
-	The author may be reached as becker@scyld.com, or C/O
-	Scyld Computing Corporation
-	410 Severn Ave., Suite 210
-	Annapolis MD 21403
-
-	This is a device driver for the Allied Telesis AT1700, and
-        Fujitsu FMV-181/182/181A/182A/183/184/183A/184A, which are
-	straight-forward Fujitsu MB86965 implementations.
-
-	Modification for Fujitsu FMV-18X cards is done by Yutaka Tamiya
-	(tamy@flab.fujitsu.co.jp).
-
-  Sources:
-    The Fujitsu MB86965 datasheet.
-
-	After the initial version of this driver was written Gerry Sawkins of
-	ATI provided their EEPROM configuration code header file.
-    Thanks to NIIBE Yutaka <gniibe@mri.co.jp> for bug fixes.
-
-    MCA bus (AT1720) support by Rene Schmit <rene@bss.lu>
-
-  Bugs:
-	The MB86965 has a design flaw that makes all probes unreliable.  Not
-	only is it difficult to detect, it also moves around in I/O space in
-	response to inb()s from other device probes!
-*/
-
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/mca-legacy.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/skbuff.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/crc32.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-static char version[] __initdata =
-	"at1700.c:v1.16 9/11/06  Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#define DRV_NAME "at1700"
-
-/* Tunable parameters. */
-
-/* When to switch from the 64-entry multicast filter to Rx-all-multicast. */
-#define MC_FILTERBREAK 64
-
-/* These unusual address orders are used to verify the CONFIG register. */
-
-static int fmv18x_probe_list[] __initdata = {
-	0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0
-};
-
-/*
- *	ISA
- */
-
-static unsigned at1700_probe_list[] __initdata = {
-	0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
-};
-
-/*
- *	MCA
- */
-#ifdef CONFIG_MCA_LEGACY
-static int at1700_ioaddr_pattern[] __initdata = {
-	0x00, 0x04, 0x01, 0x05, 0x02, 0x06, 0x03, 0x07
-};
-
-static int at1700_mca_probe_list[] __initdata = {
-	0x400, 0x1400, 0x2400, 0x3400, 0x4400, 0x5400, 0x6400, 0x7400, 0
-};
-
-static int at1700_irq_pattern[] __initdata = {
-	0x00, 0x00, 0x00, 0x30, 0x70, 0xb0, 0x00, 0x00,
-	0x00, 0xf0, 0x34, 0x74, 0xb4, 0x00, 0x00, 0xf4, 0x00
-};
-#endif
-
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifndef NET_DEBUG
-#define NET_DEBUG 1
-#endif
-static unsigned int net_debug = NET_DEBUG;
-
-typedef unsigned char uchar;
-
-/* Information that need to be kept for each board. */
-struct net_local {
-	spinlock_t lock;
-	unsigned char mc_filter[8];
-	uint jumpered:1;			/* Set iff the board has jumper config. */
-	uint tx_started:1;			/* Packets are on the Tx queue. */
-	uint tx_queue_ready:1;			/* Tx queue is ready to be sent. */
-	uint rx_started:1;			/* Packets are Rxing. */
-	uchar tx_queue;				/* Number of packet on the Tx queue. */
-	char mca_slot;				/* -1 means ISA */
-	ushort tx_queue_len;			/* Current length of the Tx queue. */
-};
-
-
-/* Offsets from the base address. */
-#define STATUS			0
-#define TX_STATUS		0
-#define RX_STATUS		1
-#define TX_INTR			2		/* Bit-mapped interrupt enable registers. */
-#define RX_INTR			3
-#define TX_MODE			4
-#define RX_MODE			5
-#define CONFIG_0		6		/* Misc. configuration settings. */
-#define CONFIG_1		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		/* Control Reg for 16 collisions */
-#define MODE13			13
-#define RX_CTRL			14
-/* Configuration registers only on the '865A/B chips. */
-#define EEPROM_Ctrl 	16
-#define EEPROM_Data 	17
-#define CARDSTATUS	16			/* FMV-18x Card Status */
-#define CARDSTATUS1	17			/* FMV-18x Card Status */
-#define IOCONFIG		18		/* Either read the jumper, or move the I/O. */
-#define IOCONFIG1		19
-#define	SAPROM			20		/* The station address PROM, if no EEPROM. */
-#define MODE24			24
-#define RESET			31		/* Write to reset some parts of the chip. */
-#define AT1700_IO_EXTENT	32
-#define PORT_OFFSET(o) (o)
-
-
-#define TX_TIMEOUT		(HZ/10)
-
-
-/* Index to functions, as function prototypes. */
-
-static int at1700_probe1(struct net_device *dev, int ioaddr);
-static int read_eeprom(long ioaddr, int location);
-static int net_open(struct net_device *dev);
-static netdev_tx_t net_send_packet(struct sk_buff *skb,
-				   struct net_device *dev);
-static irqreturn_t net_interrupt(int irq, void *dev_id);
-static void net_rx(struct net_device *dev);
-static int net_close(struct net_device *dev);
-static void set_rx_mode(struct net_device *dev);
-static void net_tx_timeout (struct net_device *dev);
-
-
-#ifdef CONFIG_MCA_LEGACY
-struct at1720_mca_adapters_struct {
-	char* name;
-	int id;
-};
-/* rEnE : maybe there are others I don't know off... */
-
-static struct at1720_mca_adapters_struct at1720_mca_adapters[] __initdata = {
-	{ "Allied Telesys AT1720AT",	0x6410 },
-	{ "Allied Telesys AT1720BT", 	0x6413 },
-	{ "Allied Telesys AT1720T",	0x6416 },
-	{ NULL, 0 },
-};
-#endif
-
-/* Check for a network adaptor of this type, and return '0' iff one exists.
-   If dev->base_addr == 0, probe all likely locations.
-   If dev->base_addr == 1, always return failure.
-   If dev->base_addr == 2, allocate space for the device and return success
-   (detachable devices only).
-   */
-
-static int io = 0x260;
-
-static int irq;
-
-static void cleanup_card(struct net_device *dev)
-{
-#ifdef CONFIG_MCA_LEGACY
-	struct net_local *lp = netdev_priv(dev);
-	if (lp->mca_slot >= 0)
-		mca_mark_as_unused(lp->mca_slot);
-#endif
-	free_irq(dev->irq, NULL);
-	release_region(dev->base_addr, AT1700_IO_EXTENT);
-}
-
-struct net_device * __init at1700_probe(int unit)
-{
-	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
-	unsigned *port;
-	int err = 0;
-
-	if (!dev)
-		return ERR_PTR(-ENODEV);
-
-	if (unit >= 0) {
-		sprintf(dev->name, "eth%d", unit);
-		netdev_boot_setup_check(dev);
-		io = dev->base_addr;
-		irq = dev->irq;
-	} else {
-		dev->base_addr = io;
-		dev->irq = irq;
-	}
-
-	if (io > 0x1ff) {	/* Check a single specified location. */
-		err = at1700_probe1(dev, io);
-	} else if (io != 0) {	/* Don't probe at all. */
-		err = -ENXIO;
-	} else {
-		for (port = at1700_probe_list; *port; port++) {
-			if (at1700_probe1(dev, *port) == 0)
-				break;
-			dev->irq = irq;
-		}
-		if (!*port)
-			err = -ENODEV;
-	}
-	if (err)
-		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
-	return dev;
-out1:
-	cleanup_card(dev);
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-
-static const struct net_device_ops at1700_netdev_ops = {
-	.ndo_open		= net_open,
-	.ndo_stop		= net_close,
-	.ndo_start_xmit 	= net_send_packet,
-	.ndo_set_multicast_list = set_rx_mode,
-	.ndo_tx_timeout 	= net_tx_timeout,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-/* The Fujitsu datasheet suggests that the NIC be probed for by checking its
-   "signature", the default bit pattern after a reset.  This *doesn't* work --
-   there is no way to reset the bus interface without a complete power-cycle!
-
-   It turns out that ATI came to the same conclusion I did: the only thing
-   that can be done is checking a few bits and then diving right into an
-   EEPROM read. */
-
-static int __init at1700_probe1(struct net_device *dev, int ioaddr)
-{
-	static const char fmv_irqmap[4] = {3, 7, 10, 15};
-	static const char fmv_irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
-	static const char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
-	unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0;
-	int slot, ret = -ENODEV;
-	struct net_local *lp = netdev_priv(dev);
-
-	if (!request_region(ioaddr, AT1700_IO_EXTENT, DRV_NAME))
-		return -EBUSY;
-
-	/* Resetting the chip doesn't reset the ISA interface, so don't bother.
-	   That means we have to be careful with the register values we probe
-	   for.
-	 */
-#ifdef notdef
-	printk("at1700 probe at %#x, eeprom is %4.4x %4.4x %4.4x ctrl %4.4x.\n",
-		   ioaddr, read_eeprom(ioaddr, 4), read_eeprom(ioaddr, 5),
-		   read_eeprom(ioaddr, 6), inw(ioaddr + EEPROM_Ctrl));
-#endif
-
-#ifdef CONFIG_MCA_LEGACY
-	/* rEnE (rene@bss.lu): got this from 3c509 driver source , adapted for AT1720 */
-
-    /* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch, heavily
-	modified by Chris Beauregard (cpbeaure@csclub.uwaterloo.ca)
-	to support standard MCA probing. */
-
-	/* redone for multi-card detection by ZP Gu (zpg@castle.net) */
-	/* now works as a module */
-
-	if (MCA_bus) {
-		int j;
-		int l_i;
-		u_char pos3, pos4;
-
-		for (j = 0; at1720_mca_adapters[j].name != NULL; j ++) {
-			slot = 0;
-			while (slot != MCA_NOTFOUND) {
-
-				slot = mca_find_unused_adapter( at1720_mca_adapters[j].id, slot );
-				if (slot == MCA_NOTFOUND) break;
-
-				/* if we get this far, an adapter has been detected and is
-				enabled */
-
-				pos3 = mca_read_stored_pos( slot, 3 );
-				pos4 = mca_read_stored_pos( slot, 4 );
-
-				for (l_i = 0; l_i < 8; l_i++)
-					if (( pos3 & 0x07) == at1700_ioaddr_pattern[l_i])
-						break;
-				ioaddr = at1700_mca_probe_list[l_i];
-
-				for (irq = 0; irq < 0x10; irq++)
-					if (((((pos4>>4) & 0x0f) | (pos3 & 0xf0)) & 0xff) == at1700_irq_pattern[irq])
-						break;
-
-					/* probing for a card at a particular IO/IRQ */
-				if ((dev->irq && dev->irq != irq) ||
-				    (dev->base_addr && dev->base_addr != ioaddr)) {
-				  	slot++;		/* probing next slot */
-				  	continue;
-				}
-
-				dev->irq = irq;
-
-				/* claim the slot */
-				mca_set_adapter_name( slot, at1720_mca_adapters[j].name );
-				mca_mark_as_used(slot);
-
-				goto found;
-			}
-		}
-		/* if we get here, we didn't find an MCA adapter - try ISA */
-	}
-#endif
-	slot = -1;
-	/* We must check for the EEPROM-config boards first, else accessing
-	   IOCONFIG0 will move the board! */
-	if (at1700_probe_list[inb(ioaddr + IOCONFIG1) & 0x07] == ioaddr &&
-	    read_eeprom(ioaddr, 4) == 0x0000 &&
-	    (read_eeprom(ioaddr, 5) & 0xff00) == 0xF400)
-		is_at1700 = 1;
-	else if (inb(ioaddr + SAPROM    ) == 0x00 &&
-		 inb(ioaddr + SAPROM + 1) == 0x00 &&
-		 inb(ioaddr + SAPROM + 2) == 0x0e)
-		is_fmv18x = 1;
-	else {
-		goto err_out;
-	}
-
-#ifdef CONFIG_MCA_LEGACY
-found:
-#endif
-
-		/* Reset the internal state machines. */
-	outb(0, ioaddr + RESET);
-
-	if (is_at1700) {
-		irq = at1700_irqmap[(read_eeprom(ioaddr, 12)&0x04)
-						   | (read_eeprom(ioaddr, 0)>>14)];
-	} else {
-		/* Check PnP mode for FMV-183/184/183A/184A. */
-		/* This PnP routine is very poor. IO and IRQ should be known. */
-		if (inb(ioaddr + CARDSTATUS1) & 0x20) {
-			irq = dev->irq;
-			for (i = 0; i < 8; i++) {
-				if (irq == fmv_irqmap_pnp[i])
-					break;
-			}
-			if (i == 8) {
-				goto err_mca;
-			}
-		} else {
-			if (fmv18x_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr)
-				goto err_mca;
-			irq = fmv_irqmap[(inb(ioaddr + IOCONFIG)>>6) & 0x03];
-		}
-	}
-
-	printk("%s: %s found at %#3x, IRQ %d, address ", dev->name,
-		   is_at1700 ? "AT1700" : "FMV-18X", ioaddr, irq);
-
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-
-	if (is_at1700) {
-		for(i = 0; i < 3; i++) {
-			unsigned short eeprom_val = read_eeprom(ioaddr, 4+i);
-			((unsigned short *)dev->dev_addr)[i] = ntohs(eeprom_val);
-		}
-	} else {
-		for(i = 0; i < 6; i++) {
-			unsigned char val = inb(ioaddr + SAPROM + i);
-			dev->dev_addr[i] = val;
-		}
-	}
-	printk("%pM", dev->dev_addr);
-
-	/* The EEPROM word 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
-	   rather than 150 ohm shielded twisted pair compensation.
-	   0x0000 == auto-sense the interface
-	   0x0800 == use TP interface
-	   0x1800 == use coax interface
-	   */
-	{
-		const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2"};
-		if (is_at1700) {
-			ushort setup_value = read_eeprom(ioaddr, 12);
-			dev->if_port = setup_value >> 8;
-		} else {
-			ushort setup_value = inb(ioaddr + CARDSTATUS);
-			switch (setup_value & 0x07) {
-			case 0x01: /* 10base5 */
-			case 0x02: /* 10base2 */
-				dev->if_port = 0x18; break;
-			case 0x04: /* 10baseT */
-				dev->if_port = 0x08; break;
-			default:   /* auto-sense */
-				dev->if_port = 0x00; break;
-			}
-		}
-		printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]);
-	}
-
-	/* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit
-	   bus access, two 4K Tx queues, and disabled Tx and Rx. */
-	outb(0xda, ioaddr + CONFIG_0);
-
-	/* Set the station address in bank zero. */
-	outb(0x00, ioaddr + CONFIG_1);
-	for (i = 0; i < 6; i++)
-		outb(dev->dev_addr[i], ioaddr + PORT_OFFSET(8 + i));
-
-	/* Switch to bank 1 and set the multicast table to accept none. */
-	outb(0x04, ioaddr + CONFIG_1);
-	for (i = 0; i < 8; i++)
-		outb(0x00, ioaddr + PORT_OFFSET(8 + i));
-
-
-	/* Switch to bank 2 */
-	/* Lock our I/O address, and set manual processing mode for 16 collisions. */
-	outb(0x08, ioaddr + CONFIG_1);
-	outb(dev->if_port, ioaddr + MODE13);
-	outb(0x00, ioaddr + COL16CNTL);
-
-	if (net_debug)
-		printk(version);
-
-	dev->netdev_ops = &at1700_netdev_ops;
-	dev->watchdog_timeo = TX_TIMEOUT;
-
-	spin_lock_init(&lp->lock);
-
-	lp->jumpered = is_fmv18x;
-	lp->mca_slot = slot;
-	/* Snarf the interrupt vector now. */
-	ret = request_irq(irq, net_interrupt, 0, DRV_NAME, dev);
-	if (ret) {
-		printk(KERN_ERR "AT1700 at %#3x is unusable due to a "
-		       "conflict on IRQ %d.\n",
-		       ioaddr, irq);
-		goto err_mca;
-	}
-
-	return 0;
-
-err_mca:
-#ifdef CONFIG_MCA_LEGACY
-	if (slot >= 0)
-		mca_mark_as_unused(slot);
-#endif
-err_out:
-	release_region(ioaddr, AT1700_IO_EXTENT);
-	return ret;
-}
-
-
-/*  EEPROM_Ctrl bits. */
-#define EE_SHIFT_CLK	0x40	/* EEPROM shift clock, in reg. 16. */
-#define EE_CS			0x20	/* EEPROM chip select, in reg. 16. */
-#define EE_DATA_WRITE	0x80	/* EEPROM chip data in, in reg. 17. */
-#define EE_DATA_READ	0x80	/* EEPROM chip data out, in reg. 17. */
-
-/* The EEPROM commands include the alway-set leading bit. */
-#define EE_WRITE_CMD	(5 << 6)
-#define EE_READ_CMD		(6 << 6)
-#define EE_ERASE_CMD	(7 << 6)
-
-static int __init read_eeprom(long ioaddr, int location)
-{
-	int i;
-	unsigned short retval = 0;
-	long ee_addr = ioaddr + EEPROM_Ctrl;
-	long ee_daddr = ioaddr + EEPROM_Data;
-	int read_cmd = location | EE_READ_CMD;
-
-	/* Shift the read command bits out. */
-	for (i = 9; i >= 0; i--) {
-		short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
-		outb(EE_CS, ee_addr);
-		outb(dataval, ee_daddr);
-		outb(EE_CS | EE_SHIFT_CLK, ee_addr);	/* EEPROM clock tick. */
-	}
-	outb(EE_DATA_WRITE, ee_daddr);
-	for (i = 16; i > 0; i--) {
-		outb(EE_CS, ee_addr);
-		outb(EE_CS | EE_SHIFT_CLK, ee_addr);
-		retval = (retval << 1) | ((inb(ee_daddr) & EE_DATA_READ) ? 1 : 0);
-	}
-
-	/* Terminate the EEPROM access. */
-	outb(EE_CS, ee_addr);
-	outb(EE_SHIFT_CLK, ee_addr);
-	outb(0, ee_addr);
-	return retval;
-}
-
-
-
-static int net_open(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-
-	/* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit
-	   bus access, and two 4K Tx queues. */
-	outb(0x5a, ioaddr + CONFIG_0);
-
-	/* Powerup, switch to register bank 2, and enable the Rx and Tx. */
-	outb(0xe8, ioaddr + CONFIG_1);
-
-	lp->tx_started = 0;
-	lp->tx_queue_ready = 1;
-	lp->rx_started = 0;
-	lp->tx_queue = 0;
-	lp->tx_queue_len = 0;
-
-	/* Turn on hardware Tx and Rx interrupts. */
-	outb(0x82, ioaddr + TX_INTR);
-	outb(0x81, ioaddr + RX_INTR);
-
-	/* Enable the IRQ on boards of fmv18x it is feasible. */
-	if (lp->jumpered) {
-		outb(0x80, ioaddr + IOCONFIG1);
-	}
-
-	netif_start_queue(dev);
-	return 0;
-}
-
-static void net_tx_timeout (struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-
-	printk ("%s: transmit timed out with status %04x, %s?\n", dev->name,
-		inw (ioaddr + STATUS), inb (ioaddr + TX_STATUS) & 0x80
-		? "IRQ conflict" : "network cable problem");
-	printk ("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
-	 dev->name, inw(ioaddr + TX_STATUS), inw(ioaddr + TX_INTR), inw(ioaddr + TX_MODE),
-		inw(ioaddr + CONFIG_0), inw(ioaddr + DATAPORT), inw(ioaddr + TX_START),
-		inw(ioaddr + MODE13 - 1), inw(ioaddr + RX_CTRL));
-	dev->stats.tx_errors++;
-	/* ToDo: We should try to restart the adaptor... */
-	outw(0xffff, ioaddr + MODE24);
-	outw (0xffff, ioaddr + TX_STATUS);
-	outb (0x5a, ioaddr + CONFIG_0);
-	outb (0xe8, ioaddr + CONFIG_1);
-	outw (0x8182, ioaddr + TX_INTR);
-	outb (0x00, ioaddr + TX_START);
-	outb (0x03, ioaddr + COL16CNTL);
-
-	dev->trans_start = jiffies; /* prevent tx timeout */
-
-	lp->tx_started = 0;
-	lp->tx_queue_ready = 1;
-	lp->rx_started = 0;
-	lp->tx_queue = 0;
-	lp->tx_queue_len = 0;
-
-	netif_wake_queue(dev);
-}
-
-
-static netdev_tx_t net_send_packet (struct sk_buff *skb,
-				    struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-	short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-	short len = skb->len;
-	unsigned char *buf = skb->data;
-	static u8 pad[ETH_ZLEN];
-
-	netif_stop_queue (dev);
-
-	/* We may not start transmitting unless we finish transferring
-	   a packet into the Tx queue. During executing the following
-	   codes we possibly catch a Tx interrupt. Thus we flag off
-	   tx_queue_ready, so that we prevent the interrupt routine
-	   (net_interrupt) to start transmitting. */
-	lp->tx_queue_ready = 0;
-	{
-		outw (length, ioaddr + DATAPORT);
-		/* Packet data */
-		outsw (ioaddr + DATAPORT, buf, len >> 1);
-		/* Check for dribble byte */
-		if (len & 1) {
-			outw(skb->data[skb->len-1], ioaddr + DATAPORT);
-			len++;
-		}
-		/* Check for packet padding */
-		if (length != skb->len)
-			outsw(ioaddr + DATAPORT, pad, (length - len + 1) >> 1);
-
-		lp->tx_queue++;
-		lp->tx_queue_len += length + 2;
-	}
-	lp->tx_queue_ready = 1;
-
-	if (lp->tx_started == 0) {
-		/* If the Tx is idle, always trigger a transmit. */
-		outb (0x80 | lp->tx_queue, ioaddr + TX_START);
-		lp->tx_queue = 0;
-		lp->tx_queue_len = 0;
-		lp->tx_started = 1;
-		netif_start_queue (dev);
-	} else if (lp->tx_queue_len < 4096 - 1502)
-		/* Yes, there is room for one more packet. */
-		netif_start_queue (dev);
-	dev_kfree_skb (skb);
-
-	return NETDEV_TX_OK;
-}
-
-/* The typical workload of the driver:
-   Handle the network interface interrupts. */
-static irqreturn_t net_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct net_local *lp;
-	int ioaddr, status;
-	int handled = 0;
-
-	if (dev == NULL) {
-		printk ("at1700_interrupt(): irq %d for unknown device.\n", irq);
-		return IRQ_NONE;
-	}
-
-	ioaddr = dev->base_addr;
-	lp = netdev_priv(dev);
-
-	spin_lock (&lp->lock);
-
-	status = inw(ioaddr + TX_STATUS);
-	outw(status, ioaddr + TX_STATUS);
-
-	if (net_debug > 4)
-		printk("%s: Interrupt with status %04x.\n", dev->name, status);
-	if (lp->rx_started == 0 &&
-	    (status & 0xff00 || (inb(ioaddr + RX_MODE) & 0x40) == 0)) {
-		/* Got a packet(s).
-		   We cannot execute net_rx more than once at the same time for
-		   the same device. During executing net_rx, we possibly catch a
-		   Tx interrupt. Thus we flag on rx_started, so that we prevent
-		   the interrupt routine (net_interrupt) to dive into net_rx
-		   again. */
-		handled = 1;
-		lp->rx_started = 1;
-		outb(0x00, ioaddr + RX_INTR);	/* Disable RX intr. */
-		net_rx(dev);
-		outb(0x81, ioaddr + RX_INTR);	/* Enable  RX intr. */
-		lp->rx_started = 0;
-	}
-	if (status & 0x00ff) {
-		handled = 1;
-		if (status & 0x02) {
-			/* More than 16 collisions occurred */
-			if (net_debug > 4)
-				printk("%s: 16 Collision occur during Txing.\n", dev->name);
-			/* Cancel sending a packet. */
-			outb(0x03, ioaddr + COL16CNTL);
-			dev->stats.collisions++;
-		}
-		if (status & 0x82) {
-			dev->stats.tx_packets++;
-			/* The Tx queue has any packets and is not being
-			   transferred a packet from the host, start
-			   transmitting. */
-			if (lp->tx_queue && lp->tx_queue_ready) {
-				outb(0x80 | lp->tx_queue, ioaddr + TX_START);
-				lp->tx_queue = 0;
-				lp->tx_queue_len = 0;
-				dev->trans_start = jiffies;
-				netif_wake_queue (dev);
-			} else {
-				lp->tx_started = 0;
-				netif_wake_queue (dev);
-			}
-		}
-	}
-
-	spin_unlock (&lp->lock);
-	return IRQ_RETVAL(handled);
-}
-
-/* We have a good packet(s), get it/them out of the buffers. */
-static void
-net_rx(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	int boguscount = 5;
-
-	while ((inb(ioaddr + RX_MODE) & 0x40) == 0) {
-		ushort status = inw(ioaddr + DATAPORT);
-		ushort pkt_len = inw(ioaddr + DATAPORT);
-
-		if (net_debug > 4)
-			printk("%s: Rxing packet mode %02x status %04x.\n",
-				   dev->name, inb(ioaddr + RX_MODE), status);
-#ifndef final_version
-		if (status == 0) {
-			outb(0x05, ioaddr + RX_CTRL);
-			break;
-		}
-#endif
-
-		if ((status & 0xF0) != 0x20) {	/* There was an error. */
-			dev->stats.rx_errors++;
-			if (status & 0x08) dev->stats.rx_length_errors++;
-			if (status & 0x04) dev->stats.rx_frame_errors++;
-			if (status & 0x02) dev->stats.rx_crc_errors++;
-			if (status & 0x01) dev->stats.rx_over_errors++;
-		} else {
-			/* Malloc up new buffer. */
-			struct sk_buff *skb;
-
-			if (pkt_len > 1550) {
-				printk("%s: The AT1700 claimed a very large packet, size %d.\n",
-					   dev->name, pkt_len);
-				/* Prime the FIFO and then flush the packet. */
-				inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT);
-				outb(0x05, ioaddr + RX_CTRL);
-				dev->stats.rx_errors++;
-				break;
-			}
-			skb = dev_alloc_skb(pkt_len+3);
-			if (skb == NULL) {
-				printk("%s: Memory squeeze, dropping packet (len %d).\n",
-					   dev->name, pkt_len);
-				/* Prime the FIFO and then flush the packet. */
-				inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT);
-				outb(0x05, ioaddr + RX_CTRL);
-				dev->stats.rx_dropped++;
-				break;
-			}
-			skb_reserve(skb,2);
-
-			insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1);
-			skb->protocol=eth_type_trans(skb, dev);
-			netif_rx(skb);
-			dev->stats.rx_packets++;
-			dev->stats.rx_bytes += pkt_len;
-		}
-		if (--boguscount <= 0)
-			break;
-	}
-
-	/* If any worth-while packets have been received, dev_rint()
-	   has done a mark_bh(NET_BH) for us and will work on them
-	   when we get to the bottom-half routine. */
-	{
-		int i;
-		for (i = 0; i < 20; i++) {
-			if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
-				break;
-			inw(ioaddr + DATAPORT);				/* dummy status read */
-			outb(0x05, ioaddr + RX_CTRL);
-		}
-
-		if (net_debug > 5)
-			printk("%s: Exint Rx packet with mode %02x after %d ticks.\n",
-				   dev->name, inb(ioaddr + RX_MODE), i);
-	}
-}
-
-/* The inverse routine to net_open(). */
-static int net_close(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-
-	netif_stop_queue(dev);
-
-	/* Set configuration register 0 to disable Tx and Rx. */
-	outb(0xda, ioaddr + CONFIG_0);
-
-	/* No statistic counters on the chip to update. */
-
-	/* Disable the IRQ on boards of fmv18x where it is feasible. */
-	if (lp->jumpered)
-		outb(0x00, ioaddr + IOCONFIG1);
-
-	/* Power-down the chip.  Green, green, green! */
-	outb(0x00, ioaddr + CONFIG_1);
-	return 0;
-}
-
-/*
-  Set the multicast/promiscuous mode for this adaptor.
-*/
-
-static void
-set_rx_mode(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	struct net_local *lp = netdev_priv(dev);
-	unsigned char mc_filter[8];		 /* Multicast hash filter */
-	unsigned long flags;
-
-	if (dev->flags & IFF_PROMISC) {
-		memset(mc_filter, 0xff, sizeof(mc_filter));
-		outb(3, ioaddr + RX_MODE);	/* Enable promiscuous mode */
-	} else if (netdev_mc_count(dev) > MC_FILTERBREAK ||
-			   (dev->flags & IFF_ALLMULTI)) {
-		/* Too many to filter perfectly -- accept all multicasts. */
-		memset(mc_filter, 0xff, sizeof(mc_filter));
-		outb(2, ioaddr + RX_MODE);	/* Use normal mode. */
-	} else if (netdev_mc_empty(dev)) {
-		memset(mc_filter, 0x00, sizeof(mc_filter));
-		outb(1, ioaddr + RX_MODE);	/* Ignore almost all multicasts. */
-	} else {
-		struct netdev_hw_addr *ha;
-
-		memset(mc_filter, 0, sizeof(mc_filter));
-		netdev_for_each_mc_addr(ha, dev) {
-			unsigned int bit =
-				ether_crc_le(ETH_ALEN, ha->addr) >> 26;
-			mc_filter[bit >> 3] |= (1 << bit);
-		}
-		outb(0x02, ioaddr + RX_MODE);	/* Use normal mode. */
-	}
-
-	spin_lock_irqsave (&lp->lock, flags);
-	if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) {
-		int i;
-		int saved_bank = inw(ioaddr + CONFIG_0);
-		/* Switch to bank 1 and set the multicast table. */
-		outw((saved_bank & ~0x0C00) | 0x0480, ioaddr + CONFIG_0);
-		for (i = 0; i < 8; i++)
-			outb(mc_filter[i], ioaddr + PORT_OFFSET(8 + i));
-		memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter));
-		outw(saved_bank, ioaddr + CONFIG_0);
-	}
-	spin_unlock_irqrestore (&lp->lock, flags);
-}
-
-#ifdef MODULE
-static struct net_device *dev_at1700;
-
-module_param(io, int, 0);
-module_param(irq, int, 0);
-module_param(net_debug, int, 0);
-MODULE_PARM_DESC(io, "AT1700/FMV18X I/O base address");
-MODULE_PARM_DESC(irq, "AT1700/FMV18X IRQ number");
-MODULE_PARM_DESC(net_debug, "AT1700/FMV18X debug level (0-6)");
-
-static int __init at1700_module_init(void)
-{
-	if (io == 0)
-		printk("at1700: You should not use auto-probing with insmod!\n");
-	dev_at1700 = at1700_probe(-1);
-	if (IS_ERR(dev_at1700))
-		return PTR_ERR(dev_at1700);
-	return 0;
-}
-
-static void __exit at1700_module_exit(void)
-{
-	unregister_netdev(dev_at1700);
-	cleanup_card(dev_at1700);
-	free_netdev(dev_at1700);
-}
-module_init(at1700_module_init);
-module_exit(at1700_module_exit);
-#endif /* MODULE */
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/atarilance.c linux-libre-3.2-gnu/drivers/net/atarilance.c
--- linux-libre-3.1-gnu/drivers/net/atarilance.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atarilance.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1176 +0,0 @@
-/* atarilance.c: Ethernet driver for VME Lance cards on the Atari */
-/*
-	Written 1995/96 by Roman Hodek (Roman.Hodek@informatik.uni-erlangen.de)
-
-	This software may be used and distributed according to the terms
-	of the GNU General Public License, incorporated herein by reference.
-
-	This drivers was written with the following sources of reference:
-	 - The driver for the Riebl Lance card by the TU Vienna.
-	 - The modified TUW driver for PAM's VME cards
-	 - The PC-Linux driver for Lance cards (but this is for bus master
-       cards, not the shared memory ones)
-	 - The Amiga Ariadne driver
-
-	v1.0: (in 1.2.13pl4/0.9.13)
-	      Initial version
-	v1.1: (in 1.2.13pl5)
-	      more comments
-		  deleted some debugging stuff
-		  optimized register access (keep AREG pointing to CSR0)
-		  following AMD, CSR0_STRT should be set only after IDON is detected
-		  use memcpy() for data transfers, that also employs long word moves
-		  better probe procedure for 24-bit systems
-          non-VME-RieblCards need extra delays in memcpy
-		  must also do write test, since 0xfxe00000 may hit ROM
-		  use 8/32 tx/rx buffers, which should give better NFS performance;
-		    this is made possible by shifting the last packet buffer after the
-		    RieblCard reserved area
-    v1.2: (in 1.2.13pl8)
-	      again fixed probing for the Falcon; 0xfe01000 hits phys. 0x00010000
-		  and thus RAM, in case of no Lance found all memory contents have to
-		  be restored!
-		  Now possible to compile as module.
-	v1.3: 03/30/96 Jes Sorensen, Roman (in 1.3)
-	      Several little 1.3 adaptions
-		  When the lance is stopped it jumps back into little-endian
-		  mode. It is therefore necessary to put it back where it
-		  belongs, in big endian mode, in order to make things work.
-		  This might be the reason why multicast-mode didn't work
-		  before, but I'm not able to test it as I only got an Amiga
-		  (we had similar problems with the A2065 driver).
-
-*/
-
-static char version[] = "atarilance.c: v1.3 04/04/96 "
-					   "Roman.Hodek@informatik.uni-erlangen.de\n";
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/module.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/skbuff.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-
-#include <asm/setup.h>
-#include <asm/irq.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/io.h>
-
-/* Debug level:
- *  0 = silent, print only serious errors
- *  1 = normal, print error messages
- *  2 = debug, print debug infos
- *  3 = debug, print even more debug infos (packet data)
- */
-
-#define	LANCE_DEBUG	1
-
-#ifdef LANCE_DEBUG
-static int lance_debug = LANCE_DEBUG;
-#else
-static int lance_debug = 1;
-#endif
-module_param(lance_debug, int, 0);
-MODULE_PARM_DESC(lance_debug, "atarilance debug level (0-3)");
-MODULE_LICENSE("GPL");
-
-/* Print debug messages on probing? */
-#undef LANCE_DEBUG_PROBE
-
-#define	DPRINTK(n,a)							\
-	do {										\
-		if (lance_debug >= n)					\
-			printk a;							\
-	} while( 0 )
-
-#ifdef LANCE_DEBUG_PROBE
-# define PROBE_PRINT(a)	printk a
-#else
-# define PROBE_PRINT(a)
-#endif
-
-/* These define the number of Rx and Tx buffers as log2. (Only powers
- * of two are valid)
- * Much more rx buffers (32) are reserved than tx buffers (8), since receiving
- * is more time critical then sending and packets may have to remain in the
- * board's memory when main memory is low.
- */
-
-#define TX_LOG_RING_SIZE			3
-#define RX_LOG_RING_SIZE			5
-
-/* These are the derived values */
-
-#define TX_RING_SIZE			(1 << TX_LOG_RING_SIZE)
-#define TX_RING_LEN_BITS		(TX_LOG_RING_SIZE << 5)
-#define	TX_RING_MOD_MASK		(TX_RING_SIZE - 1)
-
-#define RX_RING_SIZE			(1 << RX_LOG_RING_SIZE)
-#define RX_RING_LEN_BITS		(RX_LOG_RING_SIZE << 5)
-#define	RX_RING_MOD_MASK		(RX_RING_SIZE - 1)
-
-#define TX_TIMEOUT	(HZ/5)
-
-/* The LANCE Rx and Tx ring descriptors. */
-struct lance_rx_head {
-	unsigned short			base;		/* Low word of base addr */
-	volatile unsigned char	flag;
-	unsigned char			base_hi;	/* High word of base addr (unused) */
-	short					buf_length;	/* This length is 2s complement! */
-	volatile short			msg_length;	/* This length is "normal". */
-};
-
-struct lance_tx_head {
-	unsigned short			base;		/* Low word of base addr */
-	volatile unsigned char	flag;
-	unsigned char			base_hi;	/* High word of base addr (unused) */
-	short					length;		/* Length is 2s complement! */
-	volatile short			misc;
-};
-
-struct ringdesc {
-	unsigned short	adr_lo;		/* Low 16 bits of address */
-	unsigned char	len;		/* Length bits */
-	unsigned char	adr_hi;		/* High 8 bits of address (unused) */
-};
-
-/* The LANCE initialization block, described in databook. */
-struct lance_init_block {
-	unsigned short	mode;		/* Pre-set mode */
-	unsigned char	hwaddr[6];	/* Physical ethernet address */
-	unsigned		filter[2];	/* Multicast filter (unused). */
-	/* Receive and transmit ring base, along with length bits. */
-	struct ringdesc	rx_ring;
-	struct ringdesc	tx_ring;
-};
-
-/* The whole layout of the Lance shared memory */
-struct lance_memory {
-	struct lance_init_block	init;
-	struct lance_tx_head	tx_head[TX_RING_SIZE];
-	struct lance_rx_head	rx_head[RX_RING_SIZE];
-	char					packet_area[0];	/* packet data follow after the
-											 * init block and the ring
-											 * descriptors and are located
-											 * at runtime */
-};
-
-/* RieblCard specifics:
- * The original TOS driver for these cards reserves the area from offset
- * 0xee70 to 0xeebb for storing configuration data. Of interest to us is the
- * Ethernet address there, and the magic for verifying the data's validity.
- * The reserved area isn't touch by packet buffers. Furthermore, offset 0xfffe
- * is reserved for the interrupt vector number.
- */
-#define	RIEBL_RSVD_START	0xee70
-#define	RIEBL_RSVD_END		0xeec0
-#define RIEBL_MAGIC			0x09051990
-#define RIEBL_MAGIC_ADDR	((unsigned long *)(((char *)MEM) + 0xee8a))
-#define RIEBL_HWADDR_ADDR	((unsigned char *)(((char *)MEM) + 0xee8e))
-#define RIEBL_IVEC_ADDR		((unsigned short *)(((char *)MEM) + 0xfffe))
-
-/* This is a default address for the old RieblCards without a battery
- * that have no ethernet address at boot time. 00:00:36:04 is the
- * prefix for Riebl cards, the 00:00 at the end is arbitrary.
- */
-
-static unsigned char OldRieblDefHwaddr[6] = {
-	0x00, 0x00, 0x36, 0x04, 0x00, 0x00
-};
-
-
-/* I/O registers of the Lance chip */
-
-struct lance_ioreg {
-/* base+0x0 */	volatile unsigned short	data;
-/* base+0x2 */	volatile unsigned short	addr;
-				unsigned char			_dummy1[3];
-/* base+0x7 */	volatile unsigned char	ivec;
-				unsigned char			_dummy2[5];
-/* base+0xd */	volatile unsigned char	eeprom;
-				unsigned char			_dummy3;
-/* base+0xf */	volatile unsigned char	mem;
-};
-
-/* Types of boards this driver supports */
-
-enum lance_type {
-	OLD_RIEBL,		/* old Riebl card without battery */
-	NEW_RIEBL,		/* new Riebl card with battery */
-	PAM_CARD		/* PAM card with EEPROM */
-};
-
-static char *lance_names[] = {
-	"Riebl-Card (without battery)",
-	"Riebl-Card (with battery)",
-	"PAM intern card"
-};
-
-/* The driver's private device structure */
-
-struct lance_private {
-	enum lance_type		cardtype;
-	struct lance_ioreg	*iobase;
-	struct lance_memory	*mem;
-	int		 	cur_rx, cur_tx;	/* The next free ring entry */
-	int			dirty_tx;		/* Ring entries to be freed. */
-				/* copy function */
-	void			*(*memcpy_f)( void *, const void *, size_t );
-/* This must be long for set_bit() */
-	long			tx_full;
-	spinlock_t		devlock;
-};
-
-/* I/O register access macros */
-
-#define	MEM		lp->mem
-#define	DREG	IO->data
-#define	AREG	IO->addr
-#define	REGA(a)	(*( AREG = (a), &DREG ))
-
-/* Definitions for packet buffer access: */
-#define PKT_BUF_SZ		1544
-/* Get the address of a packet buffer corresponding to a given buffer head */
-#define	PKTBUF_ADDR(head)	(((unsigned char *)(MEM)) + (head)->base)
-
-/* Possible memory/IO addresses for probing */
-
-static struct lance_addr {
-	unsigned long	memaddr;
-	unsigned long	ioaddr;
-	int				slow_flag;
-} lance_addr_list[] = {
-	{ 0xfe010000, 0xfe00fff0, 0 },	/* RieblCard VME in TT */
-	{ 0xffc10000, 0xffc0fff0, 0 },	/* RieblCard VME in MegaSTE
-									   (highest byte stripped) */
-	{ 0xffe00000, 0xffff7000, 1 },	/* RieblCard in ST
-									   (highest byte stripped) */
-	{ 0xffd00000, 0xffff7000, 1 },	/* RieblCard in ST with hw modif. to
-									   avoid conflict with ROM
-									   (highest byte stripped) */
-	{ 0xffcf0000, 0xffcffff0, 0 },	/* PAMCard VME in TT and MSTE
-									   (highest byte stripped) */
-	{ 0xfecf0000, 0xfecffff0, 0 },	/* Rhotron's PAMCard VME in TT and MSTE
-									   (highest byte stripped) */
-};
-
-#define	N_LANCE_ADDR	ARRAY_SIZE(lance_addr_list)
-
-
-/* Definitions for the Lance */
-
-/* tx_head flags */
-#define TMD1_ENP		0x01	/* end of packet */
-#define TMD1_STP		0x02	/* start of packet */
-#define TMD1_DEF		0x04	/* deferred */
-#define TMD1_ONE		0x08	/* one retry needed */
-#define TMD1_MORE		0x10	/* more than one retry needed */
-#define TMD1_ERR		0x40	/* error summary */
-#define TMD1_OWN 		0x80	/* ownership (set: chip owns) */
-
-#define TMD1_OWN_CHIP	TMD1_OWN
-#define TMD1_OWN_HOST	0
-
-/* tx_head misc field */
-#define TMD3_TDR		0x03FF	/* Time Domain Reflectometry counter */
-#define TMD3_RTRY		0x0400	/* failed after 16 retries */
-#define TMD3_LCAR		0x0800	/* carrier lost */
-#define TMD3_LCOL		0x1000	/* late collision */
-#define TMD3_UFLO		0x4000	/* underflow (late memory) */
-#define TMD3_BUFF		0x8000	/* buffering error (no ENP) */
-
-/* rx_head flags */
-#define RMD1_ENP		0x01	/* end of packet */
-#define RMD1_STP		0x02	/* start of packet */
-#define RMD1_BUFF		0x04	/* buffer error */
-#define RMD1_CRC		0x08	/* CRC error */
-#define RMD1_OFLO		0x10	/* overflow */
-#define RMD1_FRAM		0x20	/* framing error */
-#define RMD1_ERR		0x40	/* error summary */
-#define RMD1_OWN 		0x80	/* ownership (set: ship owns) */
-
-#define RMD1_OWN_CHIP	RMD1_OWN
-#define RMD1_OWN_HOST	0
-
-/* register names */
-#define CSR0	0		/* mode/status */
-#define CSR1	1		/* init block addr (low) */
-#define CSR2	2		/* init block addr (high) */
-#define CSR3	3		/* misc */
-#define CSR8	8	  	/* address filter */
-#define CSR15	15		/* promiscuous mode */
-
-/* CSR0 */
-/* (R=readable, W=writeable, S=set on write, C=clear on write) */
-#define CSR0_INIT	0x0001		/* initialize (RS) */
-#define CSR0_STRT	0x0002		/* start (RS) */
-#define CSR0_STOP	0x0004		/* stop (RS) */
-#define CSR0_TDMD	0x0008		/* transmit demand (RS) */
-#define CSR0_TXON	0x0010		/* transmitter on (R) */
-#define CSR0_RXON	0x0020		/* receiver on (R) */
-#define CSR0_INEA	0x0040		/* interrupt enable (RW) */
-#define CSR0_INTR	0x0080		/* interrupt active (R) */
-#define CSR0_IDON	0x0100		/* initialization done (RC) */
-#define CSR0_TINT	0x0200		/* transmitter interrupt (RC) */
-#define CSR0_RINT	0x0400		/* receiver interrupt (RC) */
-#define CSR0_MERR	0x0800		/* memory error (RC) */
-#define CSR0_MISS	0x1000		/* missed frame (RC) */
-#define CSR0_CERR	0x2000		/* carrier error (no heartbeat :-) (RC) */
-#define CSR0_BABL	0x4000		/* babble: tx-ed too many bits (RC) */
-#define CSR0_ERR	0x8000		/* error (RC) */
-
-/* CSR3 */
-#define CSR3_BCON	0x0001		/* byte control */
-#define CSR3_ACON	0x0002		/* ALE control */
-#define CSR3_BSWP	0x0004		/* byte swap (1=big endian) */
-
-
-
-/***************************** Prototypes *****************************/
-
-static unsigned long lance_probe1( struct net_device *dev, struct lance_addr
-                                   *init_rec );
-static int lance_open( struct net_device *dev );
-static void lance_init_ring( struct net_device *dev );
-static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev );
-static irqreturn_t lance_interrupt( int irq, void *dev_id );
-static int lance_rx( struct net_device *dev );
-static int lance_close( struct net_device *dev );
-static void set_multicast_list( struct net_device *dev );
-static int lance_set_mac_address( struct net_device *dev, void *addr );
-static void lance_tx_timeout (struct net_device *dev);
-
-/************************* End of Prototypes **************************/
-
-
-
-
-
-static void *slow_memcpy( void *dst, const void *src, size_t len )
-
-{	char *cto = dst;
-	const char *cfrom = src;
-
-	while( len-- ) {
-		*cto++ = *cfrom++;
-		MFPDELAY();
-	}
-	return dst;
-}
-
-
-struct net_device * __init atarilance_probe(int unit)
-{
-	int i;
-	static int found;
-	struct net_device *dev;
-	int err = -ENODEV;
-
-	if (!MACH_IS_ATARI || found)
-		/* Assume there's only one board possible... That seems true, since
-		 * the Riebl/PAM board's address cannot be changed. */
-		return ERR_PTR(-ENODEV);
-
-	dev = alloc_etherdev(sizeof(struct lance_private));
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-	if (unit >= 0) {
-		sprintf(dev->name, "eth%d", unit);
-		netdev_boot_setup_check(dev);
-	}
-
-	for( i = 0; i < N_LANCE_ADDR; ++i ) {
-		if (lance_probe1( dev, &lance_addr_list[i] )) {
-			found = 1;
-			err = register_netdev(dev);
-			if (!err)
-				return dev;
-			free_irq(dev->irq, dev);
-			break;
-		}
-	}
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-
-
-/* Derived from hwreg_present() in atari/config.c: */
-
-static noinline int __init addr_accessible(volatile void *regp, int wordflag,
-					   int writeflag)
-{
-	int		ret;
-	unsigned long	flags;
-	long	*vbr, save_berr;
-
-	local_irq_save(flags);
-
-	__asm__ __volatile__ ( "movec	%/vbr,%0" : "=r" (vbr) : );
-	save_berr = vbr[2];
-
-	__asm__ __volatile__
-	(	"movel	%/sp,%/d1\n\t"
-		"movel	#Lberr,%2@\n\t"
-		"moveq	#0,%0\n\t"
-		"tstl   %3\n\t"
-		"bne	1f\n\t"
-		"moveb	%1@,%/d0\n\t"
-		"nop	\n\t"
-		"bra	2f\n"
-"1:		 movew	%1@,%/d0\n\t"
-		"nop	\n"
-"2:		 tstl   %4\n\t"
-		"beq	2f\n\t"
-		"tstl	%3\n\t"
-		"bne	1f\n\t"
-		"clrb	%1@\n\t"
-		"nop	\n\t"
-		"moveb	%/d0,%1@\n\t"
-		"nop	\n\t"
-		"bra	2f\n"
-"1:		 clrw	%1@\n\t"
-		"nop	\n\t"
-		"movew	%/d0,%1@\n\t"
-		"nop	\n"
-"2:		 moveq	#1,%0\n"
-"Lberr:	 movel	%/d1,%/sp"
-		: "=&d" (ret)
-		: "a" (regp), "a" (&vbr[2]), "rm" (wordflag), "rm" (writeflag)
-		: "d0", "d1", "memory"
-	);
-
-	vbr[2] = save_berr;
-	local_irq_restore(flags);
-
-	return ret;
-}
-
-static const struct net_device_ops lance_netdev_ops = {
-	.ndo_open		= lance_open,
-	.ndo_stop		= lance_close,
-	.ndo_start_xmit		= lance_start_xmit,
-	.ndo_set_multicast_list	= set_multicast_list,
-	.ndo_set_mac_address	= lance_set_mac_address,
-	.ndo_tx_timeout		= lance_tx_timeout,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
-};
-
-static unsigned long __init lance_probe1( struct net_device *dev,
-					   struct lance_addr *init_rec )
-{
-	volatile unsigned short *memaddr =
-		(volatile unsigned short *)init_rec->memaddr;
-	volatile unsigned short *ioaddr =
-		(volatile unsigned short *)init_rec->ioaddr;
-	struct lance_private	*lp;
-	struct lance_ioreg		*IO;
-	int 					i;
-	static int 				did_version;
-	unsigned short			save1, save2;
-
-	PROBE_PRINT(( "Probing for Lance card at mem %#lx io %#lx\n",
-				  (long)memaddr, (long)ioaddr ));
-
-	/* Test whether memory readable and writable */
-	PROBE_PRINT(( "lance_probe1: testing memory to be accessible\n" ));
-	if (!addr_accessible( memaddr, 1, 1 )) goto probe_fail;
-
-	/* Written values should come back... */
-	PROBE_PRINT(( "lance_probe1: testing memory to be writable (1)\n" ));
-	save1 = *memaddr;
-	*memaddr = 0x0001;
-	if (*memaddr != 0x0001) goto probe_fail;
-	PROBE_PRINT(( "lance_probe1: testing memory to be writable (2)\n" ));
-	*memaddr = 0x0000;
-	if (*memaddr != 0x0000) goto probe_fail;
-	*memaddr = save1;
-
-	/* First port should be readable and writable */
-	PROBE_PRINT(( "lance_probe1: testing ioport to be accessible\n" ));
-	if (!addr_accessible( ioaddr, 1, 1 )) goto probe_fail;
-
-	/* and written values should be readable */
-	PROBE_PRINT(( "lance_probe1: testing ioport to be writeable\n" ));
-	save2 = ioaddr[1];
-	ioaddr[1] = 0x0001;
-	if (ioaddr[1] != 0x0001) goto probe_fail;
-
-	/* The CSR0_INIT bit should not be readable */
-	PROBE_PRINT(( "lance_probe1: testing CSR0 register function (1)\n" ));
-	save1 = ioaddr[0];
-	ioaddr[1] = CSR0;
-	ioaddr[0] = CSR0_INIT | CSR0_STOP;
-	if (ioaddr[0] != CSR0_STOP) {
-		ioaddr[0] = save1;
-		ioaddr[1] = save2;
-		goto probe_fail;
-	}
-	PROBE_PRINT(( "lance_probe1: testing CSR0 register function (2)\n" ));
-	ioaddr[0] = CSR0_STOP;
-	if (ioaddr[0] != CSR0_STOP) {
-		ioaddr[0] = save1;
-		ioaddr[1] = save2;
-		goto probe_fail;
-	}
-
-	/* Now ok... */
-	PROBE_PRINT(( "lance_probe1: Lance card detected\n" ));
-	goto probe_ok;
-
-  probe_fail:
-	return 0;
-
-  probe_ok:
-	lp = netdev_priv(dev);
-	MEM = (struct lance_memory *)memaddr;
-	IO = lp->iobase = (struct lance_ioreg *)ioaddr;
-	dev->base_addr = (unsigned long)ioaddr; /* informational only */
-	lp->memcpy_f = init_rec->slow_flag ? slow_memcpy : memcpy;
-
-	REGA( CSR0 ) = CSR0_STOP;
-
-	/* Now test for type: If the eeprom I/O port is readable, it is a
-	 * PAM card */
-	if (addr_accessible( &(IO->eeprom), 0, 0 )) {
-		/* Switch back to Ram */
-		i = IO->mem;
-		lp->cardtype = PAM_CARD;
-	}
-	else if (*RIEBL_MAGIC_ADDR == RIEBL_MAGIC) {
-		lp->cardtype = NEW_RIEBL;
-	}
-	else
-		lp->cardtype = OLD_RIEBL;
-
-	if (lp->cardtype == PAM_CARD ||
-		memaddr == (unsigned short *)0xffe00000) {
-		/* PAMs card and Riebl on ST use level 5 autovector */
-		if (request_irq(IRQ_AUTO_5, lance_interrupt, IRQ_TYPE_PRIO,
-		            "PAM,Riebl-ST Ethernet", dev)) {
-			printk( "Lance: request for irq %d failed\n", IRQ_AUTO_5 );
-			return 0;
-		}
-		dev->irq = (unsigned short)IRQ_AUTO_5;
-	}
-	else {
-		/* For VME-RieblCards, request a free VME int;
-		 * (This must be unsigned long, since dev->irq is short and the
-		 * IRQ_MACHSPEC bit would be cut off...)
-		 */
-		unsigned long irq = atari_register_vme_int();
-		if (!irq) {
-			printk( "Lance: request for VME interrupt failed\n" );
-			return 0;
-		}
-		if (request_irq(irq, lance_interrupt, IRQ_TYPE_PRIO,
-		            "Riebl-VME Ethernet", dev)) {
-			printk( "Lance: request for irq %ld failed\n", irq );
-			return 0;
-		}
-		dev->irq = irq;
-	}
-
-	printk("%s: %s at io %#lx, mem %#lx, irq %d%s, hwaddr ",
-		   dev->name, lance_names[lp->cardtype],
-		   (unsigned long)ioaddr,
-		   (unsigned long)memaddr,
-		   dev->irq,
-		   init_rec->slow_flag ? " (slow memcpy)" : "" );
-
-	/* Get the ethernet address */
-	switch( lp->cardtype ) {
-	  case OLD_RIEBL:
-		/* No ethernet address! (Set some default address) */
-		memcpy( dev->dev_addr, OldRieblDefHwaddr, 6 );
-		break;
-	  case NEW_RIEBL:
-		lp->memcpy_f( dev->dev_addr, RIEBL_HWADDR_ADDR, 6 );
-		break;
-	  case PAM_CARD:
-		i = IO->eeprom;
-		for( i = 0; i < 6; ++i )
-			dev->dev_addr[i] =
-				((((unsigned short *)MEM)[i*2] & 0x0f) << 4) |
-				((((unsigned short *)MEM)[i*2+1] & 0x0f));
-		i = IO->mem;
-		break;
-	}
-	printk("%pM\n", dev->dev_addr);
-	if (lp->cardtype == OLD_RIEBL) {
-		printk( "%s: Warning: This is a default ethernet address!\n",
-				dev->name );
-		printk( "      Use \"ifconfig hw ether ...\" to set the address.\n" );
-	}
-
-	spin_lock_init(&lp->devlock);
-
-	MEM->init.mode = 0x0000;		/* Disable Rx and Tx. */
-	for( i = 0; i < 6; i++ )
-		MEM->init.hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */
-	MEM->init.filter[0] = 0x00000000;
-	MEM->init.filter[1] = 0x00000000;
-	MEM->init.rx_ring.adr_lo = offsetof( struct lance_memory, rx_head );
-	MEM->init.rx_ring.adr_hi = 0;
-	MEM->init.rx_ring.len    = RX_RING_LEN_BITS;
-	MEM->init.tx_ring.adr_lo = offsetof( struct lance_memory, tx_head );
-	MEM->init.tx_ring.adr_hi = 0;
-	MEM->init.tx_ring.len    = TX_RING_LEN_BITS;
-
-	if (lp->cardtype == PAM_CARD)
-		IO->ivec = IRQ_SOURCE_TO_VECTOR(dev->irq);
-	else
-		*RIEBL_IVEC_ADDR = IRQ_SOURCE_TO_VECTOR(dev->irq);
-
-	if (did_version++ == 0)
-		DPRINTK( 1, ( version ));
-
-	dev->netdev_ops = &lance_netdev_ops;
-
-	/* XXX MSch */
-	dev->watchdog_timeo = TX_TIMEOUT;
-
-	return 1;
-}
-
-
-static int lance_open( struct net_device *dev )
-{
-	struct lance_private *lp = netdev_priv(dev);
-	struct lance_ioreg	 *IO = lp->iobase;
-	int i;
-
-	DPRINTK( 2, ( "%s: lance_open()\n", dev->name ));
-
-	lance_init_ring(dev);
-	/* Re-initialize the LANCE, and start it when done. */
-
-	REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
-	REGA( CSR2 ) = 0;
-	REGA( CSR1 ) = 0;
-	REGA( CSR0 ) = CSR0_INIT;
-	/* From now on, AREG is kept to point to CSR0 */
-
-	i = 1000000;
-	while (--i > 0)
-		if (DREG & CSR0_IDON)
-			break;
-	if (i <= 0 || (DREG & CSR0_ERR)) {
-		DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n",
-					  dev->name, i, DREG ));
-		DREG = CSR0_STOP;
-		return -EIO;
-	}
-	DREG = CSR0_IDON;
-	DREG = CSR0_STRT;
-	DREG = CSR0_INEA;
-
-	netif_start_queue (dev);
-
-	DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG ));
-
-	return 0;
-}
-
-
-/* Initialize the LANCE Rx and Tx rings. */
-
-static void lance_init_ring( struct net_device *dev )
-{
-	struct lance_private *lp = netdev_priv(dev);
-	int i;
-	unsigned offset;
-
-	lp->tx_full = 0;
-	lp->cur_rx = lp->cur_tx = 0;
-	lp->dirty_tx = 0;
-
-	offset = offsetof( struct lance_memory, packet_area );
-
-/* If the packet buffer at offset 'o' would conflict with the reserved area
- * of RieblCards, advance it */
-#define	CHECK_OFFSET(o)														 \
-	do {																	 \
-		if (lp->cardtype == OLD_RIEBL || lp->cardtype == NEW_RIEBL) {		 \
-			if (((o) < RIEBL_RSVD_START) ? (o)+PKT_BUF_SZ > RIEBL_RSVD_START \
-										 : (o) < RIEBL_RSVD_END)			 \
-				(o) = RIEBL_RSVD_END;										 \
-		}																	 \
-	} while(0)
-
-	for( i = 0; i < TX_RING_SIZE; i++ ) {
-		CHECK_OFFSET(offset);
-		MEM->tx_head[i].base = offset;
-		MEM->tx_head[i].flag = TMD1_OWN_HOST;
- 		MEM->tx_head[i].base_hi = 0;
-		MEM->tx_head[i].length = 0;
-		MEM->tx_head[i].misc = 0;
-		offset += PKT_BUF_SZ;
-	}
-
-	for( i = 0; i < RX_RING_SIZE; i++ ) {
-		CHECK_OFFSET(offset);
-		MEM->rx_head[i].base = offset;
-		MEM->rx_head[i].flag = TMD1_OWN_CHIP;
-		MEM->rx_head[i].base_hi = 0;
-		MEM->rx_head[i].buf_length = -PKT_BUF_SZ;
-		MEM->rx_head[i].msg_length = 0;
-		offset += PKT_BUF_SZ;
-	}
-}
-
-
-/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-
-
-static void lance_tx_timeout (struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	struct lance_ioreg	 *IO = lp->iobase;
-
-	AREG = CSR0;
-	DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n",
-			  dev->name, DREG ));
-	DREG = CSR0_STOP;
-	/*
-	 * Always set BSWP after a STOP as STOP puts it back into
-	 * little endian mode.
-	 */
-	REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
-	dev->stats.tx_errors++;
-#ifndef final_version
-		{	int i;
-			DPRINTK( 2, ( "Ring data: dirty_tx %d cur_tx %d%s cur_rx %d\n",
-						  lp->dirty_tx, lp->cur_tx,
-						  lp->tx_full ? " (full)" : "",
-						  lp->cur_rx ));
-			for( i = 0 ; i < RX_RING_SIZE; i++ )
-				DPRINTK( 2, ( "rx #%d: base=%04x blen=%04x mlen=%04x\n",
-							  i, MEM->rx_head[i].base,
-							  -MEM->rx_head[i].buf_length,
-							  MEM->rx_head[i].msg_length ));
-			for( i = 0 ; i < TX_RING_SIZE; i++ )
-				DPRINTK( 2, ( "tx #%d: base=%04x len=%04x misc=%04x\n",
-							  i, MEM->tx_head[i].base,
-							  -MEM->tx_head[i].length,
-							  MEM->tx_head[i].misc ));
-		}
-#endif
-	/* XXX MSch: maybe purge/reinit ring here */
-	/* lance_restart, essentially */
-	lance_init_ring(dev);
-	REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT;
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	netif_wake_queue(dev);
-}
-
-/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-
-static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
-{
-	struct lance_private *lp = netdev_priv(dev);
-	struct lance_ioreg	 *IO = lp->iobase;
-	int entry, len;
-	struct lance_tx_head *head;
-	unsigned long flags;
-
-	DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n",
-				  dev->name, DREG ));
-
-
-	/* The old LANCE chips doesn't automatically pad buffers to min. size. */
-	len = skb->len;
-	if (len < ETH_ZLEN)
-		len = ETH_ZLEN;
-	/* PAM-Card has a bug: Can only send packets with even number of bytes! */
-	else if (lp->cardtype == PAM_CARD && (len & 1))
-		++len;
-
-	if (len > skb->len) {
-		if (skb_padto(skb, len))
-			return NETDEV_TX_OK;
-	}
-
-	netif_stop_queue (dev);
-
-	/* Fill in a Tx ring entry */
-	if (lance_debug >= 3) {
-		printk( "%s: TX pkt type 0x%04x from %pM to %pM"
-				" data at 0x%08x len %d\n",
-				dev->name, ((u_short *)skb->data)[6],
-				&skb->data[6], skb->data,
-				(int)skb->data, (int)skb->len );
-	}
-
-	/* We're not prepared for the int until the last flags are set/reset. And
-	 * the int may happen already after setting the OWN_CHIP... */
-	spin_lock_irqsave (&lp->devlock, flags);
-
-	/* Mask to ring buffer boundary. */
-	entry = lp->cur_tx & TX_RING_MOD_MASK;
-	head  = &(MEM->tx_head[entry]);
-
-	/* Caution: the write order is important here, set the "ownership" bits
-	 * last.
-	 */
-
-
-	head->length = -len;
-	head->misc = 0;
-	lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len );
-	head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP;
-	dev->stats.tx_bytes += skb->len;
-	dev_kfree_skb( skb );
-	lp->cur_tx++;
-	while( lp->cur_tx >= TX_RING_SIZE && lp->dirty_tx >= TX_RING_SIZE ) {
-		lp->cur_tx -= TX_RING_SIZE;
-		lp->dirty_tx -= TX_RING_SIZE;
-	}
-
-	/* Trigger an immediate send poll. */
-	DREG = CSR0_INEA | CSR0_TDMD;
-
-	if ((MEM->tx_head[(entry+1) & TX_RING_MOD_MASK].flag & TMD1_OWN) ==
-		TMD1_OWN_HOST)
-		netif_start_queue (dev);
-	else
-		lp->tx_full = 1;
-	spin_unlock_irqrestore (&lp->devlock, flags);
-
-	return NETDEV_TX_OK;
-}
-
-/* The LANCE interrupt handler. */
-
-static irqreturn_t lance_interrupt( int irq, void *dev_id )
-{
-	struct net_device *dev = dev_id;
-	struct lance_private *lp;
-	struct lance_ioreg	 *IO;
-	int csr0, boguscnt = 10;
-	int handled = 0;
-
-	if (dev == NULL) {
-		DPRINTK( 1, ( "lance_interrupt(): interrupt for unknown device.\n" ));
-		return IRQ_NONE;
-	}
-
-	lp = netdev_priv(dev);
-	IO = lp->iobase;
-	spin_lock (&lp->devlock);
-
-	AREG = CSR0;
-
-	while( ((csr0 = DREG) & (CSR0_ERR | CSR0_TINT | CSR0_RINT)) &&
-		   --boguscnt >= 0) {
-		handled = 1;
-		/* Acknowledge all of the current interrupt sources ASAP. */
-		DREG = csr0 & ~(CSR0_INIT | CSR0_STRT | CSR0_STOP |
-									CSR0_TDMD | CSR0_INEA);
-
-		DPRINTK( 2, ( "%s: interrupt  csr0=%04x new csr=%04x.\n",
-					  dev->name, csr0, DREG ));
-
-		if (csr0 & CSR0_RINT)			/* Rx interrupt */
-			lance_rx( dev );
-
-		if (csr0 & CSR0_TINT) {			/* Tx-done interrupt */
-			int dirty_tx = lp->dirty_tx;
-
-			while( dirty_tx < lp->cur_tx) {
-				int entry = dirty_tx & TX_RING_MOD_MASK;
-				int status = MEM->tx_head[entry].flag;
-
-				if (status & TMD1_OWN_CHIP)
-					break;			/* It still hasn't been Txed */
-
-				MEM->tx_head[entry].flag = 0;
-
-				if (status & TMD1_ERR) {
-					/* There was an major error, log it. */
-					int err_status = MEM->tx_head[entry].misc;
-					dev->stats.tx_errors++;
-					if (err_status & TMD3_RTRY) dev->stats.tx_aborted_errors++;
-					if (err_status & TMD3_LCAR) dev->stats.tx_carrier_errors++;
-					if (err_status & TMD3_LCOL) dev->stats.tx_window_errors++;
-					if (err_status & TMD3_UFLO) {
-						/* Ackk!  On FIFO errors the Tx unit is turned off! */
-						dev->stats.tx_fifo_errors++;
-						/* Remove this verbosity later! */
-						DPRINTK( 1, ( "%s: Tx FIFO error! Status %04x\n",
-									  dev->name, csr0 ));
-						/* Restart the chip. */
-						DREG = CSR0_STRT;
-					}
-				} else {
-					if (status & (TMD1_MORE | TMD1_ONE | TMD1_DEF))
-						dev->stats.collisions++;
-					dev->stats.tx_packets++;
-				}
-
-				/* XXX MSch: free skb?? */
-				dirty_tx++;
-			}
-
-#ifndef final_version
-			if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) {
-				DPRINTK( 0, ( "out-of-sync dirty pointer,"
-							  " %d vs. %d, full=%ld.\n",
-							  dirty_tx, lp->cur_tx, lp->tx_full ));
-				dirty_tx += TX_RING_SIZE;
-			}
-#endif
-
-			if (lp->tx_full && (netif_queue_stopped(dev)) &&
-				dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
-				/* The ring is no longer full, clear tbusy. */
-				lp->tx_full = 0;
-				netif_wake_queue (dev);
-			}
-
-			lp->dirty_tx = dirty_tx;
-		}
-
-		/* Log misc errors. */
-		if (csr0 & CSR0_BABL) dev->stats.tx_errors++; /* Tx babble. */
-		if (csr0 & CSR0_MISS) dev->stats.rx_errors++; /* Missed a Rx frame. */
-		if (csr0 & CSR0_MERR) {
-			DPRINTK( 1, ( "%s: Bus master arbitration failure (?!?), "
-						  "status %04x.\n", dev->name, csr0 ));
-			/* Restart the chip. */
-			DREG = CSR0_STRT;
-		}
-	}
-
-    /* Clear any other interrupt, and set interrupt enable. */
-	DREG = CSR0_BABL | CSR0_CERR | CSR0_MISS | CSR0_MERR |
-		   CSR0_IDON | CSR0_INEA;
-
-	DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n",
-				  dev->name, DREG ));
-
-	spin_unlock (&lp->devlock);
-	return IRQ_RETVAL(handled);
-}
-
-
-static int lance_rx( struct net_device *dev )
-{
-	struct lance_private *lp = netdev_priv(dev);
-	int entry = lp->cur_rx & RX_RING_MOD_MASK;
-	int i;
-
-	DPRINTK( 2, ( "%s: rx int, flag=%04x\n", dev->name,
-				  MEM->rx_head[entry].flag ));
-
-	/* If we own the next entry, it's a new packet. Send it up. */
-	while( (MEM->rx_head[entry].flag & RMD1_OWN) == RMD1_OWN_HOST ) {
-		struct lance_rx_head *head = &(MEM->rx_head[entry]);
-		int status = head->flag;
-
-		if (status != (RMD1_ENP|RMD1_STP)) {		/* There was an error. */
-			/* There is a tricky error noted by John Murphy,
-			   <murf@perftech.com> to Russ Nelson: Even with full-sized
-			   buffers it's possible for a jabber packet to use two
-			   buffers, with only the last correctly noting the error. */
-			if (status & RMD1_ENP)	/* Only count a general error at the */
-				dev->stats.rx_errors++; /* end of a packet.*/
-			if (status & RMD1_FRAM) dev->stats.rx_frame_errors++;
-			if (status & RMD1_OFLO) dev->stats.rx_over_errors++;
-			if (status & RMD1_CRC) dev->stats.rx_crc_errors++;
-			if (status & RMD1_BUFF) dev->stats.rx_fifo_errors++;
-			head->flag &= (RMD1_ENP|RMD1_STP);
-		} else {
-			/* Malloc up new buffer, compatible with net-3. */
-			short pkt_len = head->msg_length & 0xfff;
-			struct sk_buff *skb;
-
-			if (pkt_len < 60) {
-				printk( "%s: Runt packet!\n", dev->name );
-				dev->stats.rx_errors++;
-			}
-			else {
-				skb = dev_alloc_skb( pkt_len+2 );
-				if (skb == NULL) {
-					DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n",
-								  dev->name ));
-					for( i = 0; i < RX_RING_SIZE; i++ )
-						if (MEM->rx_head[(entry+i) & RX_RING_MOD_MASK].flag &
-							RMD1_OWN_CHIP)
-							break;
-
-					if (i > RX_RING_SIZE - 2) {
-						dev->stats.rx_dropped++;
-						head->flag |= RMD1_OWN_CHIP;
-						lp->cur_rx++;
-					}
-					break;
-				}
-
-				if (lance_debug >= 3) {
-					u_char *data = PKTBUF_ADDR(head);
-
-					printk(KERN_DEBUG "%s: RX pkt type 0x%04x from %pM to %pM "
-						   "data %02x %02x %02x %02x %02x %02x %02x %02x "
-						   "len %d\n",
-						   dev->name, ((u_short *)data)[6],
-						   &data[6], data,
-						   data[15], data[16], data[17], data[18],
-						   data[19], data[20], data[21], data[22],
-						   pkt_len);
-				}
-
-				skb_reserve( skb, 2 );	/* 16 byte align */
-				skb_put( skb, pkt_len );	/* Make room */
-				lp->memcpy_f( skb->data, PKTBUF_ADDR(head), pkt_len );
-				skb->protocol = eth_type_trans( skb, dev );
-				netif_rx( skb );
-				dev->stats.rx_packets++;
-				dev->stats.rx_bytes += pkt_len;
-			}
-		}
-
-		head->flag |= RMD1_OWN_CHIP;
-		entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
-	}
-	lp->cur_rx &= RX_RING_MOD_MASK;
-
-	/* From lance.c (Donald Becker): */
-	/* We should check that at least two ring entries are free.	 If not,
-	   we should free one and mark stats->rx_dropped++. */
-
-	return 0;
-}
-
-
-static int lance_close( struct net_device *dev )
-{
-	struct lance_private *lp = netdev_priv(dev);
-	struct lance_ioreg	 *IO = lp->iobase;
-
-	netif_stop_queue (dev);
-
-	AREG = CSR0;
-
-	DPRINTK( 2, ( "%s: Shutting down ethercard, status was %2.2x.\n",
-				  dev->name, DREG ));
-
-	/* We stop the LANCE here -- it occasionally polls
-	   memory if we don't. */
-	DREG = CSR0_STOP;
-
-	return 0;
-}
-
-
-/* Set or clear the multicast filter for this adaptor.
-   num_addrs == -1		Promiscuous mode, receive all packets
-   num_addrs == 0		Normal mode, clear multicast list
-   num_addrs > 0		Multicast mode, receive normal and MC packets, and do
-						best-effort filtering.
- */
-
-static void set_multicast_list( struct net_device *dev )
-{
-	struct lance_private *lp = netdev_priv(dev);
-	struct lance_ioreg	 *IO = lp->iobase;
-
-	if (netif_running(dev))
-		/* Only possible if board is already started */
-		return;
-
-	/* We take the simple way out and always enable promiscuous mode. */
-	DREG = CSR0_STOP; /* Temporarily stop the lance. */
-
-	if (dev->flags & IFF_PROMISC) {
-		/* Log any net taps. */
-		DPRINTK( 2, ( "%s: Promiscuous mode enabled.\n", dev->name ));
-		REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */
-	} else {
-		short multicast_table[4];
-		int num_addrs = netdev_mc_count(dev);
-		int i;
-		/* We don't use the multicast table, but rely on upper-layer
-		 * filtering. */
-		memset( multicast_table, (num_addrs == 0) ? 0 : -1,
-				sizeof(multicast_table) );
-		for( i = 0; i < 4; i++ )
-			REGA( CSR8+i ) = multicast_table[i];
-		REGA( CSR15 ) = 0; /* Unset promiscuous mode */
-	}
-
-	/*
-	 * Always set BSWP after a STOP as STOP puts it back into
-	 * little endian mode.
-	 */
-	REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
-
-	/* Resume normal operation and reset AREG to CSR0 */
-	REGA( CSR0 ) = CSR0_IDON | CSR0_INEA | CSR0_STRT;
-}
-
-
-/* This is needed for old RieblCards and possible for new RieblCards */
-
-static int lance_set_mac_address( struct net_device *dev, void *addr )
-{
-	struct lance_private *lp = netdev_priv(dev);
-	struct sockaddr *saddr = addr;
-	int i;
-
-	if (lp->cardtype != OLD_RIEBL && lp->cardtype != NEW_RIEBL)
-		return -EOPNOTSUPP;
-
-	if (netif_running(dev)) {
-		/* Only possible while card isn't started */
-		DPRINTK( 1, ( "%s: hwaddr can be set only while card isn't open.\n",
-					  dev->name ));
-		return -EIO;
-	}
-
-	memcpy( dev->dev_addr, saddr->sa_data, dev->addr_len );
-	for( i = 0; i < 6; i++ )
-		MEM->init.hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */
-	lp->memcpy_f( RIEBL_HWADDR_ADDR, dev->dev_addr, 6 );
-	/* set also the magic for future sessions */
-	*RIEBL_MAGIC_ADDR = RIEBL_MAGIC;
-
-	return 0;
-}
-
-
-#ifdef MODULE
-static struct net_device *atarilance_dev;
-
-static int __init atarilance_module_init(void)
-{
-	atarilance_dev = atarilance_probe(-1);
-	if (IS_ERR(atarilance_dev))
-		return PTR_ERR(atarilance_dev);
-	return 0;
-}
-
-static void __exit atarilance_module_exit(void)
-{
-	unregister_netdev(atarilance_dev);
-	free_irq(atarilance_dev->irq, atarilance_dev);
-	free_netdev(atarilance_dev);
-}
-module_init(atarilance_module_init);
-module_exit(atarilance_module_exit);
-#endif /* MODULE */
-
-
-/*
- * Local variables:
- *  c-indent-level: 4
- *  tab-width: 4
- * End:
- */
diff -druN linux-libre-3.1-gnu/drivers/net/atl1c/atl1c_ethtool.c linux-libre-3.2-gnu/drivers/net/atl1c/atl1c_ethtool.c
--- linux-libre-3.1-gnu/drivers/net/atl1c/atl1c_ethtool.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atl1c/atl1c_ethtool.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,311 +0,0 @@
-/*
- * Copyright(c) 2009 - 2009 Atheros Corporation. All rights reserved.
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You 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/netdevice.h>
-#include <linux/ethtool.h>
-#include <linux/slab.h>
-
-#include "atl1c.h"
-
-static int atl1c_get_settings(struct net_device *netdev,
-			      struct ethtool_cmd *ecmd)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	struct atl1c_hw *hw = &adapter->hw;
-
-	ecmd->supported = (SUPPORTED_10baseT_Half  |
-			   SUPPORTED_10baseT_Full  |
-			   SUPPORTED_100baseT_Half |
-			   SUPPORTED_100baseT_Full |
-			   SUPPORTED_Autoneg       |
-			   SUPPORTED_TP);
-	if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M)
-		ecmd->supported |= SUPPORTED_1000baseT_Full;
-
-	ecmd->advertising = ADVERTISED_TP;
-
-	ecmd->advertising |= hw->autoneg_advertised;
-
-	ecmd->port = PORT_TP;
-	ecmd->phy_address = 0;
-	ecmd->transceiver = XCVR_INTERNAL;
-
-	if (adapter->link_speed != SPEED_0) {
-		ethtool_cmd_speed_set(ecmd, adapter->link_speed);
-		if (adapter->link_duplex == FULL_DUPLEX)
-			ecmd->duplex = DUPLEX_FULL;
-		else
-			ecmd->duplex = DUPLEX_HALF;
-	} else {
-		ethtool_cmd_speed_set(ecmd, -1);
-		ecmd->duplex = -1;
-	}
-
-	ecmd->autoneg = AUTONEG_ENABLE;
-	return 0;
-}
-
-static int atl1c_set_settings(struct net_device *netdev,
-			      struct ethtool_cmd *ecmd)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	struct atl1c_hw *hw = &adapter->hw;
-	u16  autoneg_advertised;
-
-	while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
-		msleep(1);
-
-	if (ecmd->autoneg == AUTONEG_ENABLE) {
-		autoneg_advertised = ADVERTISED_Autoneg;
-	} else {
-		u32 speed = ethtool_cmd_speed(ecmd);
-		if (speed == SPEED_1000) {
-			if (ecmd->duplex != DUPLEX_FULL) {
-				if (netif_msg_link(adapter))
-					dev_warn(&adapter->pdev->dev,
-						"1000M half is invalid\n");
-				clear_bit(__AT_RESETTING, &adapter->flags);
-				return -EINVAL;
-			}
-			autoneg_advertised = ADVERTISED_1000baseT_Full;
-		} else if (speed == SPEED_100) {
-			if (ecmd->duplex == DUPLEX_FULL)
-				autoneg_advertised = ADVERTISED_100baseT_Full;
-			else
-				autoneg_advertised = ADVERTISED_100baseT_Half;
-		} else {
-			if (ecmd->duplex == DUPLEX_FULL)
-				autoneg_advertised = ADVERTISED_10baseT_Full;
-			else
-				autoneg_advertised = ADVERTISED_10baseT_Half;
-		}
-	}
-
-	if (hw->autoneg_advertised != autoneg_advertised) {
-		hw->autoneg_advertised = autoneg_advertised;
-		if (atl1c_restart_autoneg(hw) != 0) {
-			if (netif_msg_link(adapter))
-				dev_warn(&adapter->pdev->dev,
-					"ethtool speed/duplex setting failed\n");
-			clear_bit(__AT_RESETTING, &adapter->flags);
-			return -EINVAL;
-		}
-	}
-	clear_bit(__AT_RESETTING, &adapter->flags);
-	return 0;
-}
-
-static u32 atl1c_get_msglevel(struct net_device *netdev)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	return adapter->msg_enable;
-}
-
-static void atl1c_set_msglevel(struct net_device *netdev, u32 data)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	adapter->msg_enable = data;
-}
-
-static int atl1c_get_regs_len(struct net_device *netdev)
-{
-	return AT_REGS_LEN;
-}
-
-static void atl1c_get_regs(struct net_device *netdev,
-			   struct ethtool_regs *regs, void *p)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	struct atl1c_hw *hw = &adapter->hw;
-	u32 *regs_buff = p;
-	u16 phy_data;
-
-	memset(p, 0, AT_REGS_LEN);
-
-	regs->version = 0;
-	AT_READ_REG(hw, REG_VPD_CAP, 		  p++);
-	AT_READ_REG(hw, REG_PM_CTRL, 		  p++);
-	AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL,  p++);
-	AT_READ_REG(hw, REG_TWSI_CTRL, 		  p++);
-	AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL,   p++);
-	AT_READ_REG(hw, REG_MASTER_CTRL, 	  p++);
-	AT_READ_REG(hw, REG_MANUAL_TIMER_INIT,    p++);
-	AT_READ_REG(hw, REG_IRQ_MODRT_TIMER_INIT, p++);
-	AT_READ_REG(hw, REG_GPHY_CTRL, 		  p++);
-	AT_READ_REG(hw, REG_LINK_CTRL, 		  p++);
-	AT_READ_REG(hw, REG_IDLE_STATUS, 	  p++);
-	AT_READ_REG(hw, REG_MDIO_CTRL, 		  p++);
-	AT_READ_REG(hw, REG_SERDES_LOCK, 	  p++);
-	AT_READ_REG(hw, REG_MAC_CTRL, 		  p++);
-	AT_READ_REG(hw, REG_MAC_IPG_IFG, 	  p++);
-	AT_READ_REG(hw, REG_MAC_STA_ADDR, 	  p++);
-	AT_READ_REG(hw, REG_MAC_STA_ADDR+4, 	  p++);
-	AT_READ_REG(hw, REG_RX_HASH_TABLE, 	  p++);
-	AT_READ_REG(hw, REG_RX_HASH_TABLE+4, 	  p++);
-	AT_READ_REG(hw, REG_RXQ_CTRL, 		  p++);
-	AT_READ_REG(hw, REG_TXQ_CTRL, 		  p++);
-	AT_READ_REG(hw, REG_MTU, 		  p++);
-	AT_READ_REG(hw, REG_WOL_CTRL, 		  p++);
-
-	atl1c_read_phy_reg(hw, MII_BMCR, &phy_data);
-	regs_buff[73] =	(u32) phy_data;
-	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
-	regs_buff[74] = (u32) phy_data;
-}
-
-static int atl1c_get_eeprom_len(struct net_device *netdev)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-
-	if (atl1c_check_eeprom_exist(&adapter->hw))
-		return AT_EEPROM_LEN;
-	else
-		return 0;
-}
-
-static int atl1c_get_eeprom(struct net_device *netdev,
-		struct ethtool_eeprom *eeprom, u8 *bytes)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	struct atl1c_hw *hw = &adapter->hw;
-	u32 *eeprom_buff;
-	int first_dword, last_dword;
-	int ret_val = 0;
-	int i;
-
-	if (eeprom->len == 0)
-		return -EINVAL;
-
-	if (!atl1c_check_eeprom_exist(hw)) /* not exist */
-		return -EINVAL;
-
-	eeprom->magic = adapter->pdev->vendor |
-			(adapter->pdev->device << 16);
-
-	first_dword = eeprom->offset >> 2;
-	last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
-
-	eeprom_buff = kmalloc(sizeof(u32) *
-			(last_dword - first_dword + 1), GFP_KERNEL);
-	if (eeprom_buff == NULL)
-		return -ENOMEM;
-
-	for (i = first_dword; i < last_dword; i++) {
-		if (!atl1c_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) {
-			kfree(eeprom_buff);
-			return -EIO;
-		}
-	}
-
-	memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3),
-			eeprom->len);
-	kfree(eeprom_buff);
-
-	return ret_val;
-	return 0;
-}
-
-static void atl1c_get_drvinfo(struct net_device *netdev,
-		struct ethtool_drvinfo *drvinfo)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-
-	strlcpy(drvinfo->driver,  atl1c_driver_name, sizeof(drvinfo->driver));
-	strlcpy(drvinfo->version, atl1c_driver_version,
-		sizeof(drvinfo->version));
-	strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
-	strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
-		sizeof(drvinfo->bus_info));
-	drvinfo->n_stats = 0;
-	drvinfo->testinfo_len = 0;
-	drvinfo->regdump_len = atl1c_get_regs_len(netdev);
-	drvinfo->eedump_len = atl1c_get_eeprom_len(netdev);
-}
-
-static void atl1c_get_wol(struct net_device *netdev,
-			  struct ethtool_wolinfo *wol)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-
-	wol->supported = WAKE_MAGIC | WAKE_PHY;
-	wol->wolopts = 0;
-
-	if (adapter->wol & AT_WUFC_EX)
-		wol->wolopts |= WAKE_UCAST;
-	if (adapter->wol & AT_WUFC_MC)
-		wol->wolopts |= WAKE_MCAST;
-	if (adapter->wol & AT_WUFC_BC)
-		wol->wolopts |= WAKE_BCAST;
-	if (adapter->wol & AT_WUFC_MAG)
-		wol->wolopts |= WAKE_MAGIC;
-	if (adapter->wol & AT_WUFC_LNKC)
-		wol->wolopts |= WAKE_PHY;
-}
-
-static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-
-	if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE |
-			    WAKE_UCAST | WAKE_BCAST | WAKE_MCAST))
-		return -EOPNOTSUPP;
-	/* these settings will always override what we currently have */
-	adapter->wol = 0;
-
-	if (wol->wolopts & WAKE_MAGIC)
-		adapter->wol |= AT_WUFC_MAG;
-	if (wol->wolopts & WAKE_PHY)
-		adapter->wol |= AT_WUFC_LNKC;
-
-	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
-
-	return 0;
-}
-
-static int atl1c_nway_reset(struct net_device *netdev)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	if (netif_running(netdev))
-		atl1c_reinit_locked(adapter);
-	return 0;
-}
-
-static const struct ethtool_ops atl1c_ethtool_ops = {
-	.get_settings           = atl1c_get_settings,
-	.set_settings           = atl1c_set_settings,
-	.get_drvinfo            = atl1c_get_drvinfo,
-	.get_regs_len           = atl1c_get_regs_len,
-	.get_regs               = atl1c_get_regs,
-	.get_wol                = atl1c_get_wol,
-	.set_wol                = atl1c_set_wol,
-	.get_msglevel           = atl1c_get_msglevel,
-	.set_msglevel           = atl1c_set_msglevel,
-	.nway_reset             = atl1c_nway_reset,
-	.get_link               = ethtool_op_get_link,
-	.get_eeprom_len         = atl1c_get_eeprom_len,
-	.get_eeprom             = atl1c_get_eeprom,
-};
-
-void atl1c_set_ethtool_ops(struct net_device *netdev)
-{
-	SET_ETHTOOL_OPS(netdev, &atl1c_ethtool_ops);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/atl1c/atl1c.h linux-libre-3.2-gnu/drivers/net/atl1c/atl1c.h
--- linux-libre-3.1-gnu/drivers/net/atl1c/atl1c.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atl1c/atl1c.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,636 +0,0 @@
-/*
- * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved.
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You 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 _ATL1C_H_
-#define _ATL1C_H_
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/udp.h>
-#include <linux/mii.h>
-#include <linux/io.h>
-#include <linux/vmalloc.h>
-#include <linux/pagemap.h>
-#include <linux/tcp.h>
-#include <linux/ethtool.h>
-#include <linux/if_vlan.h>
-#include <linux/workqueue.h>
-#include <net/checksum.h>
-#include <net/ip6_checksum.h>
-
-#include "atl1c_hw.h"
-
-/* Wake Up Filter Control */
-#define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
-#define AT_WUFC_MAG  0x00000002 /* Magic Packet Wakeup Enable */
-#define AT_WUFC_EX   0x00000004 /* Directed Exact Wakeup Enable */
-#define AT_WUFC_MC   0x00000008 /* Multicast Wakeup Enable */
-#define AT_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */
-
-#define AT_VLAN_TO_TAG(_vlan, _tag)	   \
-	_tag =  ((((_vlan) >> 8) & 0xFF)  |\
-		 (((_vlan) & 0xFF) << 8))
-
-#define AT_TAG_TO_VLAN(_tag, _vlan) 	 \
-	_vlan = ((((_tag) >> 8) & 0xFF) |\
-		(((_tag) & 0xFF) << 8))
-
-#define SPEED_0		   0xffff
-#define HALF_DUPLEX        1
-#define FULL_DUPLEX        2
-
-#define AT_RX_BUF_SIZE		(ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN)
-#define MAX_JUMBO_FRAME_SIZE	(6*1024)
-#define MAX_TSO_FRAME_SIZE      (7*1024)
-#define MAX_TX_OFFLOAD_THRESH	(9*1024)
-
-#define AT_MAX_RECEIVE_QUEUE    4
-#define AT_DEF_RECEIVE_QUEUE	1
-#define AT_MAX_TRANSMIT_QUEUE	2
-
-#define AT_DMA_HI_ADDR_MASK     0xffffffff00000000ULL
-#define AT_DMA_LO_ADDR_MASK     0x00000000ffffffffULL
-
-#define AT_TX_WATCHDOG  (5 * HZ)
-#define AT_MAX_INT_WORK		5
-#define AT_TWSI_EEPROM_TIMEOUT 	100
-#define AT_HW_MAX_IDLE_DELAY 	10
-#define AT_SUSPEND_LINK_TIMEOUT 100
-
-#define AT_ASPM_L0S_TIMER	6
-#define AT_ASPM_L1_TIMER	12
-#define AT_LCKDET_TIMER		12
-
-#define ATL1C_PCIE_L0S_L1_DISABLE 	0x01
-#define ATL1C_PCIE_PHY_RESET		0x02
-
-#define ATL1C_ASPM_L0s_ENABLE		0x0001
-#define ATL1C_ASPM_L1_ENABLE		0x0002
-
-#define AT_REGS_LEN	(75 * sizeof(u32))
-#define AT_EEPROM_LEN 	512
-
-#define ATL1C_GET_DESC(R, i, type)	(&(((type *)((R)->desc))[i]))
-#define ATL1C_RFD_DESC(R, i)	ATL1C_GET_DESC(R, i, struct atl1c_rx_free_desc)
-#define ATL1C_TPD_DESC(R, i)	ATL1C_GET_DESC(R, i, struct atl1c_tpd_desc)
-#define ATL1C_RRD_DESC(R, i)	ATL1C_GET_DESC(R, i, struct atl1c_recv_ret_status)
-
-/* tpd word 1 bit 0:7 General Checksum task offload */
-#define TPD_L4HDR_OFFSET_MASK	0x00FF
-#define TPD_L4HDR_OFFSET_SHIFT	0
-
-/* tpd word 1 bit 0:7 Large Send task offload (IPv4/IPV6) */
-#define TPD_TCPHDR_OFFSET_MASK	0x00FF
-#define TPD_TCPHDR_OFFSET_SHIFT	0
-
-/* tpd word 1 bit 0:7 Custom Checksum task offload */
-#define TPD_PLOADOFFSET_MASK	0x00FF
-#define TPD_PLOADOFFSET_SHIFT	0
-
-/* tpd word 1 bit 8:17 */
-#define TPD_CCSUM_EN_MASK	0x0001
-#define TPD_CCSUM_EN_SHIFT	8
-#define TPD_IP_CSUM_MASK	0x0001
-#define TPD_IP_CSUM_SHIFT	9
-#define TPD_TCP_CSUM_MASK	0x0001
-#define TPD_TCP_CSUM_SHIFT	10
-#define TPD_UDP_CSUM_MASK	0x0001
-#define TPD_UDP_CSUM_SHIFT	11
-#define TPD_LSO_EN_MASK		0x0001	/* TCP Large Send Offload */
-#define TPD_LSO_EN_SHIFT	12
-#define TPD_LSO_VER_MASK	0x0001
-#define TPD_LSO_VER_SHIFT	13 	/* 0 : ipv4; 1 : ipv4/ipv6 */
-#define TPD_CON_VTAG_MASK	0x0001
-#define TPD_CON_VTAG_SHIFT	14
-#define TPD_INS_VTAG_MASK	0x0001
-#define TPD_INS_VTAG_SHIFT	15
-#define TPD_IPV4_PACKET_MASK	0x0001  /* valid when LSO VER  is 1 */
-#define TPD_IPV4_PACKET_SHIFT	16
-#define TPD_ETH_TYPE_MASK	0x0001
-#define TPD_ETH_TYPE_SHIFT	17	/* 0 : 802.3 frame; 1 : Ethernet */
-
-/* tpd word 18:25 Custom Checksum task offload */
-#define TPD_CCSUM_OFFSET_MASK	0x00FF
-#define TPD_CCSUM_OFFSET_SHIFT	18
-#define TPD_CCSUM_EPAD_MASK	0x0001
-#define TPD_CCSUM_EPAD_SHIFT	30
-
-/* tpd word 18:30 Large Send task offload (IPv4/IPV6) */
-#define TPD_MSS_MASK            0x1FFF
-#define TPD_MSS_SHIFT		18
-
-#define TPD_EOP_MASK		0x0001
-#define TPD_EOP_SHIFT		31
-
-struct atl1c_tpd_desc {
-	__le16	buffer_len; /* include 4-byte CRC */
-	__le16	vlan_tag;
-	__le32	word1;
-	__le64	buffer_addr;
-};
-
-struct atl1c_tpd_ext_desc {
-	u32 reservd_0;
-	__le32 word1;
-	__le32 pkt_len;
-	u32 reservd_1;
-};
-/* rrs word 0 bit 0:31 */
-#define RRS_RX_CSUM_MASK	0xFFFF
-#define RRS_RX_CSUM_SHIFT	0
-#define RRS_RX_RFD_CNT_MASK	0x000F
-#define RRS_RX_RFD_CNT_SHIFT	16
-#define RRS_RX_RFD_INDEX_MASK	0x0FFF
-#define RRS_RX_RFD_INDEX_SHIFT	20
-
-/* rrs flag bit 0:16 */
-#define RRS_HEAD_LEN_MASK	0x00FF
-#define RRS_HEAD_LEN_SHIFT	0
-#define RRS_HDS_TYPE_MASK	0x0003
-#define RRS_HDS_TYPE_SHIFT	8
-#define RRS_CPU_NUM_MASK	0x0003
-#define	RRS_CPU_NUM_SHIFT	10
-#define RRS_HASH_FLG_MASK	0x000F
-#define RRS_HASH_FLG_SHIFT	12
-
-#define RRS_HDS_TYPE_HEAD	1
-#define RRS_HDS_TYPE_DATA	2
-
-#define RRS_IS_NO_HDS_TYPE(flag) \
-	((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == 0)
-
-#define RRS_IS_HDS_HEAD(flag) \
-	((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \
-			RRS_HDS_TYPE_HEAD)
-
-#define RRS_IS_HDS_DATA(flag) \
-	((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \
-			RRS_HDS_TYPE_DATA)
-
-/* rrs word 3 bit 0:31 */
-#define RRS_PKT_SIZE_MASK	0x3FFF
-#define RRS_PKT_SIZE_SHIFT	0
-#define RRS_ERR_L4_CSUM_MASK	0x0001
-#define RRS_ERR_L4_CSUM_SHIFT	14
-#define RRS_ERR_IP_CSUM_MASK	0x0001
-#define RRS_ERR_IP_CSUM_SHIFT	15
-#define RRS_VLAN_INS_MASK	0x0001
-#define RRS_VLAN_INS_SHIFT	16
-#define RRS_PROT_ID_MASK	0x0007
-#define RRS_PROT_ID_SHIFT	17
-#define RRS_RX_ERR_SUM_MASK	0x0001
-#define RRS_RX_ERR_SUM_SHIFT	20
-#define RRS_RX_ERR_CRC_MASK	0x0001
-#define RRS_RX_ERR_CRC_SHIFT	21
-#define RRS_RX_ERR_FAE_MASK	0x0001
-#define RRS_RX_ERR_FAE_SHIFT	22
-#define RRS_RX_ERR_TRUNC_MASK	0x0001
-#define RRS_RX_ERR_TRUNC_SHIFT	23
-#define RRS_RX_ERR_RUNC_MASK	0x0001
-#define RRS_RX_ERR_RUNC_SHIFT	24
-#define RRS_RX_ERR_ICMP_MASK	0x0001
-#define RRS_RX_ERR_ICMP_SHIFT	25
-#define RRS_PACKET_BCAST_MASK	0x0001
-#define RRS_PACKET_BCAST_SHIFT	26
-#define RRS_PACKET_MCAST_MASK	0x0001
-#define RRS_PACKET_MCAST_SHIFT	27
-#define RRS_PACKET_TYPE_MASK	0x0001
-#define RRS_PACKET_TYPE_SHIFT	28
-#define RRS_FIFO_FULL_MASK	0x0001
-#define RRS_FIFO_FULL_SHIFT	29
-#define RRS_802_3_LEN_ERR_MASK 	0x0001
-#define RRS_802_3_LEN_ERR_SHIFT 30
-#define RRS_RXD_UPDATED_MASK	0x0001
-#define RRS_RXD_UPDATED_SHIFT	31
-
-#define RRS_ERR_L4_CSUM         0x00004000
-#define RRS_ERR_IP_CSUM         0x00008000
-#define RRS_VLAN_INS            0x00010000
-#define RRS_RX_ERR_SUM          0x00100000
-#define RRS_RX_ERR_CRC          0x00200000
-#define RRS_802_3_LEN_ERR	0x40000000
-#define RRS_RXD_UPDATED		0x80000000
-
-#define RRS_PACKET_TYPE_802_3  	1
-#define RRS_PACKET_TYPE_ETH	0
-#define RRS_PACKET_IS_ETH(word) \
-	((((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK) == \
-			RRS_PACKET_TYPE_ETH)
-#define RRS_RXD_IS_VALID(word) \
-	((((word) >> RRS_RXD_UPDATED_SHIFT) & RRS_RXD_UPDATED_MASK) == 1)
-
-#define RRS_PACKET_PROT_IS_IPV4_ONLY(word) \
-	((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 1)
-#define RRS_PACKET_PROT_IS_IPV6_ONLY(word) \
-	((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 6)
-
-struct atl1c_recv_ret_status {
-	__le32  word0;
-	__le32	rss_hash;
-	__le16	vlan_tag;
-	__le16	flag;
-	__le32	word3;
-};
-
-/* RFD descriptor */
-struct atl1c_rx_free_desc {
-	__le64	buffer_addr;
-};
-
-/* DMA Order Settings */
-enum atl1c_dma_order {
-	atl1c_dma_ord_in = 1,
-	atl1c_dma_ord_enh = 2,
-	atl1c_dma_ord_out = 4
-};
-
-enum atl1c_dma_rcb {
-	atl1c_rcb_64 = 0,
-	atl1c_rcb_128 = 1
-};
-
-enum atl1c_mac_speed {
-	atl1c_mac_speed_0 = 0,
-	atl1c_mac_speed_10_100 = 1,
-	atl1c_mac_speed_1000 = 2
-};
-
-enum atl1c_dma_req_block {
-	atl1c_dma_req_128 = 0,
-	atl1c_dma_req_256 = 1,
-	atl1c_dma_req_512 = 2,
-	atl1c_dma_req_1024 = 3,
-	atl1c_dma_req_2048 = 4,
-	atl1c_dma_req_4096 = 5
-};
-
-enum atl1c_rss_mode {
-	atl1c_rss_mode_disable = 0,
-	atl1c_rss_sig_que = 1,
-	atl1c_rss_mul_que_sig_int = 2,
-	atl1c_rss_mul_que_mul_int = 4,
-};
-
-enum atl1c_rss_type {
-	atl1c_rss_disable = 0,
-	atl1c_rss_ipv4 = 1,
-	atl1c_rss_ipv4_tcp = 2,
-	atl1c_rss_ipv6 = 4,
-	atl1c_rss_ipv6_tcp = 8
-};
-
-enum atl1c_nic_type {
-	athr_l1c = 0,
-	athr_l2c = 1,
-	athr_l2c_b,
-	athr_l2c_b2,
-	athr_l1d,
-	athr_l1d_2,
-};
-
-enum atl1c_trans_queue {
-	atl1c_trans_normal = 0,
-	atl1c_trans_high = 1
-};
-
-struct atl1c_hw_stats {
-	/* rx */
-	unsigned long rx_ok;		/* The number of good packet received. */
-	unsigned long rx_bcast;		/* The number of good broadcast packet received. */
-	unsigned long rx_mcast;		/* The number of good multicast packet received. */
-	unsigned long rx_pause;		/* The number of Pause packet received. */
-	unsigned long rx_ctrl;		/* The number of Control packet received other than Pause frame. */
-	unsigned long rx_fcs_err;	/* The number of packets with bad FCS. */
-	unsigned long rx_len_err;	/* The number of packets with mismatch of length field and actual size. */
-	unsigned long rx_byte_cnt;	/* The number of bytes of good packet received. FCS is NOT included. */
-	unsigned long rx_runt;		/* The number of packets received that are less than 64 byte long and with good FCS. */
-	unsigned long rx_frag;		/* The number of packets received that are less than 64 byte long and with bad FCS. */
-	unsigned long rx_sz_64;		/* The number of good and bad packets received that are 64 byte long. */
-	unsigned long rx_sz_65_127;	/* The number of good and bad packets received that are between 65 and 127-byte long. */
-	unsigned long rx_sz_128_255;	/* The number of good and bad packets received that are between 128 and 255-byte long. */
-	unsigned long rx_sz_256_511;	/* The number of good and bad packets received that are between 256 and 511-byte long. */
-	unsigned long rx_sz_512_1023;	/* The number of good and bad packets received that are between 512 and 1023-byte long. */
-	unsigned long rx_sz_1024_1518;	/* The number of good and bad packets received that are between 1024 and 1518-byte long. */
-	unsigned long rx_sz_1519_max;	/* The number of good and bad packets received that are between 1519-byte and MTU. */
-	unsigned long rx_sz_ov;		/* The number of good and bad packets received that are more than MTU size truncated by Selene. */
-	unsigned long rx_rxf_ov;	/* The number of frame dropped due to occurrence of RX FIFO overflow. */
-	unsigned long rx_rrd_ov;	/* The number of frame dropped due to occurrence of RRD overflow. */
-	unsigned long rx_align_err;	/* Alignment Error */
-	unsigned long rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */
-	unsigned long rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */
-	unsigned long rx_err_addr;	/* The number of packets dropped due to address filtering. */
-
-	/* tx */
-	unsigned long tx_ok;		/* The number of good packet transmitted. */
-	unsigned long tx_bcast;		/* The number of good broadcast packet transmitted. */
-	unsigned long tx_mcast;		/* The number of good multicast packet transmitted. */
-	unsigned long tx_pause;		/* The number of Pause packet transmitted. */
-	unsigned long tx_exc_defer;	/* The number of packets transmitted with excessive deferral. */
-	unsigned long tx_ctrl;		/* The number of packets transmitted is a control frame, excluding Pause frame. */
-	unsigned long tx_defer;		/* The number of packets transmitted that is deferred. */
-	unsigned long tx_byte_cnt;	/* The number of bytes of data transmitted. FCS is NOT included. */
-	unsigned long tx_sz_64;		/* The number of good and bad packets transmitted that are 64 byte long. */
-	unsigned long tx_sz_65_127;	/* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
-	unsigned long tx_sz_128_255;	/* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
-	unsigned long tx_sz_256_511;	/* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
-	unsigned long tx_sz_512_1023;	/* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
-	unsigned long tx_sz_1024_1518;	/* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
-	unsigned long tx_sz_1519_max;	/* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
-	unsigned long tx_1_col;		/* The number of packets subsequently transmitted successfully with a single prior collision. */
-	unsigned long tx_2_col;		/* The number of packets subsequently transmitted successfully with multiple prior collisions. */
-	unsigned long tx_late_col;	/* The number of packets transmitted with late collisions. */
-	unsigned long tx_abort_col;	/* The number of transmit packets aborted due to excessive collisions. */
-	unsigned long tx_underrun;	/* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
-	unsigned long tx_rd_eop;	/* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
-	unsigned long tx_len_err;	/* The number of transmit packets with length field does NOT match the actual frame size. */
-	unsigned long tx_trunc;		/* The number of transmit packets truncated due to size exceeding MTU. */
-	unsigned long tx_bcast_byte;	/* The byte count of broadcast packet transmitted, excluding FCS. */
-	unsigned long tx_mcast_byte;	/* The byte count of multicast packet transmitted, excluding FCS. */
-};
-
-struct atl1c_hw {
-	u8 __iomem      *hw_addr;            /* inner register address */
-	struct atl1c_adapter *adapter;
-	enum atl1c_nic_type  nic_type;
-	enum atl1c_dma_order dma_order;
-	enum atl1c_dma_rcb   rcb_value;
-	enum atl1c_dma_req_block dmar_block;
-	enum atl1c_dma_req_block dmaw_block;
-
-	u16 device_id;
-	u16 vendor_id;
-	u16 subsystem_id;
-	u16 subsystem_vendor_id;
-	u8 revision_id;
-	u16 phy_id1;
-	u16 phy_id2;
-
-	u32 intr_mask;
-	u8 dmaw_dly_cnt;
-	u8 dmar_dly_cnt;
-
-	u8 preamble_len;
-	u16 max_frame_size;
-	u16 min_frame_size;
-
-	enum atl1c_mac_speed mac_speed;
-	bool mac_duplex;
-	bool hibernate;
-	u16 media_type;
-#define MEDIA_TYPE_AUTO_SENSOR  0
-#define MEDIA_TYPE_100M_FULL    1
-#define MEDIA_TYPE_100M_HALF    2
-#define MEDIA_TYPE_10M_FULL     3
-#define MEDIA_TYPE_10M_HALF     4
-
-	u16 autoneg_advertised;
-	u16 mii_autoneg_adv_reg;
-	u16 mii_1000t_ctrl_reg;
-
-	u16 tx_imt;	/* TX Interrupt Moderator timer ( 2us resolution) */
-	u16 rx_imt;	/* RX Interrupt Moderator timer ( 2us resolution) */
-	u16 ict;        /* Interrupt Clear timer (2us resolution) */
-	u16 ctrl_flags;
-#define ATL1C_INTR_CLEAR_ON_READ	0x0001
-#define ATL1C_INTR_MODRT_ENABLE	 	0x0002
-#define ATL1C_CMB_ENABLE		0x0004
-#define ATL1C_SMB_ENABLE		0x0010
-#define ATL1C_TXQ_MODE_ENHANCE		0x0020
-#define ATL1C_RX_IPV6_CHKSUM		0x0040
-#define ATL1C_ASPM_L0S_SUPPORT		0x0080
-#define ATL1C_ASPM_L1_SUPPORT		0x0100
-#define ATL1C_ASPM_CTRL_MON		0x0200
-#define ATL1C_HIB_DISABLE		0x0400
-#define ATL1C_APS_MODE_ENABLE           0x0800
-#define ATL1C_LINK_EXT_SYNC             0x1000
-#define ATL1C_CLK_GATING_EN             0x2000
-#define ATL1C_FPGA_VERSION              0x8000
-	u16 link_cap_flags;
-#define ATL1C_LINK_CAP_1000M		0x0001
-	u16 cmb_tpd;
-	u16 cmb_rrd;
-	u16 cmb_rx_timer; /* 2us resolution */
-	u16 cmb_tx_timer;
-	u32 smb_timer;
-
-	u16 rrd_thresh; /* Threshold of number of RRD produced to trigger
-			  interrupt request */
-	u16 tpd_thresh;
-	u8 tpd_burst;   /* Number of TPD to prefetch in cache-aligned burst. */
-	u8 rfd_burst;
-	enum atl1c_rss_type rss_type;
-	enum atl1c_rss_mode rss_mode;
-	u8 rss_hash_bits;
-	u32 base_cpu;
-	u32 indirect_tab;
-	u8 mac_addr[ETH_ALEN];
-	u8 perm_mac_addr[ETH_ALEN];
-
-	bool phy_configured;
-	bool re_autoneg;
-	bool emi_ca;
-};
-
-/*
- * atl1c_ring_header represents a single, contiguous block of DMA space
- * mapped for the three descriptor rings (tpd, rfd, rrd) and the two
- * message blocks (cmb, smb) described below
- */
-struct atl1c_ring_header {
-	void *desc;		/* virtual address */
-	dma_addr_t dma;		/* physical address*/
-	unsigned int size;	/* length in bytes */
-};
-
-/*
- * atl1c_buffer is wrapper around a pointer to a socket buffer
- * so a DMA handle can be stored along with the skb
- */
-struct atl1c_buffer {
-	struct sk_buff *skb;	/* socket buffer */
-	u16 length;		/* rx buffer length */
-	u16 flags;		/* information of buffer */
-#define ATL1C_BUFFER_FREE		0x0001
-#define ATL1C_BUFFER_BUSY		0x0002
-#define ATL1C_BUFFER_STATE_MASK		0x0003
-
-#define ATL1C_PCIMAP_SINGLE		0x0004
-#define ATL1C_PCIMAP_PAGE		0x0008
-#define ATL1C_PCIMAP_TYPE_MASK		0x000C
-
-#define ATL1C_PCIMAP_TODEVICE		0x0010
-#define ATL1C_PCIMAP_FROMDEVICE		0x0020
-#define ATL1C_PCIMAP_DIRECTION_MASK	0x0030
-	dma_addr_t dma;
-};
-
-#define ATL1C_SET_BUFFER_STATE(buff, state) do {	\
-	((buff)->flags) &= ~ATL1C_BUFFER_STATE_MASK;	\
-	((buff)->flags) |= (state);			\
-	} while (0)
-
-#define ATL1C_SET_PCIMAP_TYPE(buff, type, direction) do {	\
-	((buff)->flags) &= ~ATL1C_PCIMAP_TYPE_MASK;		\
-	((buff)->flags) |= (type);				\
-	((buff)->flags) &= ~ATL1C_PCIMAP_DIRECTION_MASK;	\
-	((buff)->flags) |= (direction);				\
-	} while (0)
-
-/* transimit packet descriptor (tpd) ring */
-struct atl1c_tpd_ring {
-	void *desc;		/* descriptor ring virtual address */
-	dma_addr_t dma;		/* descriptor ring physical address */
-	u16 size;		/* descriptor ring length in bytes */
-	u16 count;		/* number of descriptors in the ring */
-	u16 next_to_use; 	/* this is protectd by adapter->tx_lock */
-	atomic_t next_to_clean;
-	struct atl1c_buffer *buffer_info;
-};
-
-/* receive free descriptor (rfd) ring */
-struct atl1c_rfd_ring {
-	void *desc;		/* descriptor ring virtual address */
-	dma_addr_t dma;		/* descriptor ring physical address */
-	u16 size;		/* descriptor ring length in bytes */
-	u16 count;		/* number of descriptors in the ring */
-	u16 next_to_use;
-	u16 next_to_clean;
-	struct atl1c_buffer *buffer_info;
-};
-
-/* receive return descriptor (rrd) ring */
-struct atl1c_rrd_ring {
-	void *desc;		/* descriptor ring virtual address */
-	dma_addr_t dma;		/* descriptor ring physical address */
-	u16 size;		/* descriptor ring length in bytes */
-	u16 count;		/* number of descriptors in the ring */
-	u16 next_to_use;
-	u16 next_to_clean;
-};
-
-struct atl1c_cmb {
-	void *cmb;
-	dma_addr_t dma;
-};
-
-struct atl1c_smb {
-	void *smb;
-	dma_addr_t dma;
-};
-
-/* board specific private data structure */
-struct atl1c_adapter {
-	struct net_device   *netdev;
-	struct pci_dev      *pdev;
-	struct napi_struct  napi;
-	struct atl1c_hw        hw;
-	struct atl1c_hw_stats  hw_stats;
-	struct mii_if_info  mii;    /* MII interface info */
-	u16 rx_buffer_len;
-
-	unsigned long flags;
-#define __AT_TESTING        0x0001
-#define __AT_RESETTING      0x0002
-#define __AT_DOWN           0x0003
-	unsigned long work_event;
-#define	ATL1C_WORK_EVENT_RESET		0
-#define	ATL1C_WORK_EVENT_LINK_CHANGE	1
-	u32 msg_enable;
-
-	bool have_msi;
-	u32 wol;
-	u16 link_speed;
-	u16 link_duplex;
-
-	spinlock_t mdio_lock;
-	spinlock_t tx_lock;
-	atomic_t irq_sem;
-
-	struct work_struct common_task;
-	struct timer_list watchdog_timer;
-	struct timer_list phy_config_timer;
-
-	/* All Descriptor memory */
-	struct atl1c_ring_header ring_header;
-	struct atl1c_tpd_ring tpd_ring[AT_MAX_TRANSMIT_QUEUE];
-	struct atl1c_rfd_ring rfd_ring[AT_MAX_RECEIVE_QUEUE];
-	struct atl1c_rrd_ring rrd_ring[AT_MAX_RECEIVE_QUEUE];
-	struct atl1c_cmb cmb;
-	struct atl1c_smb smb;
-	int num_rx_queues;
-	u32 bd_number;     /* board number;*/
-};
-
-#define AT_WRITE_REG(a, reg, value) ( \
-		writel((value), ((a)->hw_addr + reg)))
-
-#define AT_WRITE_FLUSH(a) (\
-		readl((a)->hw_addr))
-
-#define AT_READ_REG(a, reg, pdata) do {					\
-		if (unlikely((a)->hibernate)) {				\
-			readl((a)->hw_addr + reg);			\
-			*(u32 *)pdata = readl((a)->hw_addr + reg);	\
-		} else {						\
-			*(u32 *)pdata = readl((a)->hw_addr + reg);	\
-		}							\
-	} while (0)
-
-#define AT_WRITE_REGB(a, reg, value) (\
-		writeb((value), ((a)->hw_addr + reg)))
-
-#define AT_READ_REGB(a, reg) (\
-		readb((a)->hw_addr + reg))
-
-#define AT_WRITE_REGW(a, reg, value) (\
-		writew((value), ((a)->hw_addr + reg)))
-
-#define AT_READ_REGW(a, reg) (\
-		readw((a)->hw_addr + reg))
-
-#define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \
-		writel((value), (((a)->hw_addr + reg) + ((offset) << 2))))
-
-#define AT_READ_REG_ARRAY(a, reg, offset) ( \
-		readl(((a)->hw_addr + reg) + ((offset) << 2)))
-
-extern char atl1c_driver_name[];
-extern char atl1c_driver_version[];
-
-extern void atl1c_reinit_locked(struct atl1c_adapter *adapter);
-extern s32 atl1c_reset_hw(struct atl1c_hw *hw);
-extern void atl1c_set_ethtool_ops(struct net_device *netdev);
-#endif /* _ATL1C_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/atl1c/atl1c_hw.c linux-libre-3.2-gnu/drivers/net/atl1c/atl1c_hw.c
--- linux-libre-3.1-gnu/drivers/net/atl1c/atl1c_hw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atl1c/atl1c_hw.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,662 +0,0 @@
-/*
- * Copyright(c) 2007 Atheros Corporation. All rights reserved.
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You 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/pci.h>
-#include <linux/delay.h>
-#include <linux/mii.h>
-#include <linux/crc32.h>
-
-#include "atl1c.h"
-
-/*
- * check_eeprom_exist
- * return 1 if eeprom exist
- */
-int atl1c_check_eeprom_exist(struct atl1c_hw *hw)
-{
-	u32 data;
-
-	AT_READ_REG(hw, REG_TWSI_DEBUG, &data);
-	if (data & TWSI_DEBUG_DEV_EXIST)
-		return 1;
-
-	AT_READ_REG(hw, REG_MASTER_CTRL, &data);
-	if (data & MASTER_CTRL_OTP_SEL)
-		return 1;
-	return 0;
-}
-
-void atl1c_hw_set_mac_addr(struct atl1c_hw *hw)
-{
-	u32 value;
-	/*
-	 * 00-0B-6A-F6-00-DC
-	 * 0:  6AF600DC 1: 000B
-	 * low dword
-	 */
-	value = (((u32)hw->mac_addr[2]) << 24) |
-		(((u32)hw->mac_addr[3]) << 16) |
-		(((u32)hw->mac_addr[4]) << 8)  |
-		(((u32)hw->mac_addr[5])) ;
-	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
-	/* hight dword */
-	value = (((u32)hw->mac_addr[0]) << 8) |
-		(((u32)hw->mac_addr[1])) ;
-	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
-}
-
-/*
- * atl1c_get_permanent_address
- * return 0 if get valid mac address,
- */
-static int atl1c_get_permanent_address(struct atl1c_hw *hw)
-{
-	u32 addr[2];
-	u32 i;
-	u32 otp_ctrl_data;
-	u32 twsi_ctrl_data;
-	u32 ltssm_ctrl_data;
-	u32 wol_data;
-	u8  eth_addr[ETH_ALEN];
-	u16 phy_data;
-	bool raise_vol = false;
-
-	/* init */
-	addr[0] = addr[1] = 0;
-	AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
-	if (atl1c_check_eeprom_exist(hw)) {
-		if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) {
-			/* Enable OTP CLK */
-			if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) {
-				otp_ctrl_data |= OTP_CTRL_CLK_EN;
-				AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
-				AT_WRITE_FLUSH(hw);
-				msleep(1);
-			}
-		}
-
-		if (hw->nic_type == athr_l2c_b ||
-		    hw->nic_type == athr_l2c_b2 ||
-		    hw->nic_type == athr_l1d) {
-			atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00);
-			if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
-				goto out;
-			phy_data &= 0xFF7F;
-			atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
-
-			atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
-			if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
-				goto out;
-			phy_data |= 0x8;
-			atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
-			udelay(20);
-			raise_vol = true;
-		}
-		/* close open bit of ReadOnly*/
-		AT_READ_REG(hw, REG_LTSSM_ID_CTRL, &ltssm_ctrl_data);
-		ltssm_ctrl_data &= ~LTSSM_ID_EN_WRO;
-		AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, ltssm_ctrl_data);
-
-		/* clear any WOL settings */
-		AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
-		AT_READ_REG(hw, REG_WOL_CTRL, &wol_data);
-
-
-		AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
-		twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
-		AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
-		for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
-			msleep(10);
-			AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
-			if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
-				break;
-		}
-		if (i >= AT_TWSI_EEPROM_TIMEOUT)
-			return -1;
-	}
-	/* Disable OTP_CLK */
-	if ((hw->nic_type == athr_l1c || hw->nic_type == athr_l2c)) {
-		otp_ctrl_data &= ~OTP_CTRL_CLK_EN;
-		AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
-		msleep(1);
-	}
-	if (raise_vol) {
-		if (hw->nic_type == athr_l2c_b ||
-		    hw->nic_type == athr_l2c_b2 ||
-		    hw->nic_type == athr_l1d ||
-		    hw->nic_type == athr_l1d_2) {
-			atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00);
-			if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
-				goto out;
-			phy_data |= 0x80;
-			atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
-
-			atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
-			if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
-				goto out;
-			phy_data &= 0xFFF7;
-			atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
-			udelay(20);
-		}
-	}
-
-	/* maybe MAC-address is from BIOS */
-	AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]);
-	AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]);
-	*(u32 *) &eth_addr[2] = swab32(addr[0]);
-	*(u16 *) &eth_addr[0] = swab16(*(u16 *)&addr[1]);
-
-	if (is_valid_ether_addr(eth_addr)) {
-		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
-		return 0;
-	}
-
-out:
-	return -1;
-}
-
-bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value)
-{
-	int i;
-	int ret = false;
-	u32 otp_ctrl_data;
-	u32 control;
-	u32 data;
-
-	if (offset & 3)
-		return ret; /* address do not align */
-
-	AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
-	if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))
-		AT_WRITE_REG(hw, REG_OTP_CTRL,
-				(otp_ctrl_data | OTP_CTRL_CLK_EN));
-
-	AT_WRITE_REG(hw, REG_EEPROM_DATA_LO, 0);
-	control = (offset & EEPROM_CTRL_ADDR_MASK) << EEPROM_CTRL_ADDR_SHIFT;
-	AT_WRITE_REG(hw, REG_EEPROM_CTRL, control);
-
-	for (i = 0; i < 10; i++) {
-		udelay(100);
-		AT_READ_REG(hw, REG_EEPROM_CTRL, &control);
-		if (control & EEPROM_CTRL_RW)
-			break;
-	}
-	if (control & EEPROM_CTRL_RW) {
-		AT_READ_REG(hw, REG_EEPROM_CTRL, &data);
-		AT_READ_REG(hw, REG_EEPROM_DATA_LO, p_value);
-		data = data & 0xFFFF;
-		*p_value = swab32((data << 16) | (*p_value >> 16));
-		ret = true;
-	}
-	if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))
-		AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
-
-	return ret;
-}
-/*
- * Reads the adapter's MAC address from the EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- */
-int atl1c_read_mac_addr(struct atl1c_hw *hw)
-{
-	int err = 0;
-
-	err = atl1c_get_permanent_address(hw);
-	if (err)
-		random_ether_addr(hw->perm_mac_addr);
-
-	memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
-	return 0;
-}
-
-/*
- * atl1c_hash_mc_addr
- *  purpose
- *      set hash value for a multicast address
- *      hash calcu processing :
- *          1. calcu 32bit CRC for multicast address
- *          2. reverse crc with MSB to LSB
- */
-u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr)
-{
-	u32 crc32;
-	u32 value = 0;
-	int i;
-
-	crc32 = ether_crc_le(6, mc_addr);
-	for (i = 0; i < 32; i++)
-		value |= (((crc32 >> i) & 1) << (31 - i));
-
-	return value;
-}
-
-/*
- * Sets the bit in the multicast table corresponding to the hash value.
- * hw - Struct containing variables accessed by shared code
- * hash_value - Multicast address hash value
- */
-void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value)
-{
-	u32 hash_bit, hash_reg;
-	u32 mta;
-
-	/*
-	 * The HASH Table  is a register array of 2 32-bit registers.
-	 * It is treated like an array of 64 bits.  We want to set
-	 * bit BitArray[hash_value]. So we figure out what register
-	 * the bit is in, read it, OR in the new bit, then write
-	 * back the new value.  The register is determined by the
-	 * upper bit of the hash value and the bit within that
-	 * register are determined by the lower 5 bits of the value.
-	 */
-	hash_reg = (hash_value >> 31) & 0x1;
-	hash_bit = (hash_value >> 26) & 0x1F;
-
-	mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);
-
-	mta |= (1 << hash_bit);
-
-	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
-}
-
-/*
- * Reads the value from a PHY register
- * hw - Struct containing variables accessed by shared code
- * reg_addr - address of the PHY register to read
- */
-int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
-{
-	u32 val;
-	int i;
-
-	val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
-		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
-		MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
-
-	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
-
-	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
-		udelay(2);
-		AT_READ_REG(hw, REG_MDIO_CTRL, &val);
-		if (!(val & (MDIO_START | MDIO_BUSY)))
-			break;
-	}
-	if (!(val & (MDIO_START | MDIO_BUSY))) {
-		*phy_data = (u16)val;
-		return 0;
-	}
-
-	return -1;
-}
-
-/*
- * Writes a value to a PHY register
- * hw - Struct containing variables accessed by shared code
- * reg_addr - address of the PHY register to write
- * data - data to write to the PHY
- */
-int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data)
-{
-	int i;
-	u32 val;
-
-	val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT   |
-	       (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
-	       MDIO_SUP_PREAMBLE | MDIO_START |
-	       MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
-
-	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
-
-	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
-		udelay(2);
-		AT_READ_REG(hw, REG_MDIO_CTRL, &val);
-		if (!(val & (MDIO_START | MDIO_BUSY)))
-			break;
-	}
-
-	if (!(val & (MDIO_START | MDIO_BUSY)))
-		return 0;
-
-	return -1;
-}
-
-/*
- * Configures PHY autoneg and flow control advertisement settings
- *
- * hw - Struct containing variables accessed by shared code
- */
-static int atl1c_phy_setup_adv(struct atl1c_hw *hw)
-{
-	u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_ALL;
-	u16 mii_giga_ctrl_data = GIGA_CR_1000T_DEFAULT_CAP &
-				~GIGA_CR_1000T_SPEED_MASK;
-
-	if (hw->autoneg_advertised & ADVERTISED_10baseT_Half)
-		mii_adv_data |= ADVERTISE_10HALF;
-	if (hw->autoneg_advertised & ADVERTISED_10baseT_Full)
-		mii_adv_data |= ADVERTISE_10FULL;
-	if (hw->autoneg_advertised & ADVERTISED_100baseT_Half)
-		mii_adv_data |= ADVERTISE_100HALF;
-	if (hw->autoneg_advertised & ADVERTISED_100baseT_Full)
-		mii_adv_data |= ADVERTISE_100FULL;
-
-	if (hw->autoneg_advertised & ADVERTISED_Autoneg)
-		mii_adv_data |= ADVERTISE_10HALF  | ADVERTISE_10FULL |
-				ADVERTISE_100HALF | ADVERTISE_100FULL;
-
-	if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M) {
-		if (hw->autoneg_advertised & ADVERTISED_1000baseT_Half)
-			mii_giga_ctrl_data |= ADVERTISE_1000HALF;
-		if (hw->autoneg_advertised & ADVERTISED_1000baseT_Full)
-			mii_giga_ctrl_data |= ADVERTISE_1000FULL;
-		if (hw->autoneg_advertised & ADVERTISED_Autoneg)
-			mii_giga_ctrl_data |= ADVERTISE_1000HALF |
-					ADVERTISE_1000FULL;
-	}
-
-	if (atl1c_write_phy_reg(hw, MII_ADVERTISE, mii_adv_data) != 0 ||
-	    atl1c_write_phy_reg(hw, MII_CTRL1000, mii_giga_ctrl_data) != 0)
-		return -1;
-	return 0;
-}
-
-void atl1c_phy_disable(struct atl1c_hw *hw)
-{
-	AT_WRITE_REGW(hw, REG_GPHY_CTRL,
-			GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
-}
-
-static void atl1c_phy_magic_data(struct atl1c_hw *hw)
-{
-	u16 data;
-
-	data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE |
-		((1 & ANA_INTERVAL_SEL_TIMER_MASK) <<
-		ANA_INTERVAL_SEL_TIMER_SHIFT);
-
-	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_18);
-	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
-	data = (2 & ANA_SERDES_CDR_BW_MASK) | ANA_MS_PAD_DBG |
-		ANA_SERDES_EN_DEEM | ANA_SERDES_SEL_HSP | ANA_SERDES_EN_PLL |
-		ANA_SERDES_EN_LCKDT;
-
-	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_5);
-	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
-	data = (44 & ANA_LONG_CABLE_TH_100_MASK) |
-		((33 & ANA_SHORT_CABLE_TH_100_MASK) <<
-		ANA_SHORT_CABLE_TH_100_SHIFT) | ANA_BP_BAD_LINK_ACCUM |
-		ANA_BP_SMALL_BW;
-
-	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_54);
-	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
-	data = (11 & ANA_IECHO_ADJ_MASK) | ((11 & ANA_IECHO_ADJ_MASK) <<
-		ANA_IECHO_ADJ_2_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
-		ANA_IECHO_ADJ_1_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
-		ANA_IECHO_ADJ_0_SHIFT);
-
-	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_4);
-	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
-	data = ANA_RESTART_CAL | ((7 & ANA_MANUL_SWICH_ON_MASK) <<
-		ANA_MANUL_SWICH_ON_SHIFT) | ANA_MAN_ENABLE |
-		ANA_SEL_HSP | ANA_EN_HB | ANA_OEN_125M;
-
-	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_0);
-	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
-	if (hw->ctrl_flags & ATL1C_HIB_DISABLE) {
-		atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_41);
-		if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
-			return;
-		data &= ~ANA_TOP_PS_EN;
-		atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
-		atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_11);
-		if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
-			return;
-		data &= ~ANA_PS_HIB_EN;
-		atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-	}
-}
-
-int atl1c_phy_reset(struct atl1c_hw *hw)
-{
-	struct atl1c_adapter *adapter = hw->adapter;
-	struct pci_dev *pdev = adapter->pdev;
-	u16 phy_data;
-	u32 phy_ctrl_data = GPHY_CTRL_DEFAULT;
-	u32 mii_ier_data = IER_LINK_UP | IER_LINK_DOWN;
-	int err;
-
-	if (hw->ctrl_flags & ATL1C_HIB_DISABLE)
-		phy_ctrl_data &= ~GPHY_CTRL_HIB_EN;
-
-	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
-	AT_WRITE_FLUSH(hw);
-	msleep(40);
-	phy_ctrl_data |= GPHY_CTRL_EXT_RESET;
-	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
-	AT_WRITE_FLUSH(hw);
-	msleep(10);
-
-	if (hw->nic_type == athr_l2c_b) {
-		atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x0A);
-		atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data);
-		atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xDFFF);
-	}
-
-	if (hw->nic_type == athr_l2c_b ||
-	    hw->nic_type == athr_l2c_b2 ||
-	    hw->nic_type == athr_l1d ||
-	    hw->nic_type == athr_l1d_2) {
-		atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
-		atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data);
-		atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xFFF7);
-		msleep(20);
-	}
-	if (hw->nic_type == athr_l1d) {
-		atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
-		atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x929D);
-	}
-	if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b2
-		|| hw->nic_type == athr_l2c) {
-		atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
-		atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD);
-	}
-	err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data);
-	if (err) {
-		if (netif_msg_hw(adapter))
-			dev_err(&pdev->dev,
-				"Error enable PHY linkChange Interrupt\n");
-		return err;
-	}
-	if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))
-		atl1c_phy_magic_data(hw);
-	return 0;
-}
-
-int atl1c_phy_init(struct atl1c_hw *hw)
-{
-	struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
-	struct pci_dev *pdev = adapter->pdev;
-	int ret_val;
-	u16 mii_bmcr_data = BMCR_RESET;
-
-	if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &hw->phy_id1) != 0) ||
-		(atl1c_read_phy_reg(hw, MII_PHYSID2, &hw->phy_id2) != 0)) {
-		dev_err(&pdev->dev, "Error get phy ID\n");
-		return -1;
-	}
-	switch (hw->media_type) {
-	case MEDIA_TYPE_AUTO_SENSOR:
-		ret_val = atl1c_phy_setup_adv(hw);
-		if (ret_val) {
-			if (netif_msg_link(adapter))
-				dev_err(&pdev->dev,
-					"Error Setting up Auto-Negotiation\n");
-			return ret_val;
-		}
-		mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART;
-		break;
-	case MEDIA_TYPE_100M_FULL:
-		mii_bmcr_data |= BMCR_SPEED100 | BMCR_FULLDPLX;
-		break;
-	case MEDIA_TYPE_100M_HALF:
-		mii_bmcr_data |= BMCR_SPEED100;
-		break;
-	case MEDIA_TYPE_10M_FULL:
-		mii_bmcr_data |= BMCR_FULLDPLX;
-		break;
-	case MEDIA_TYPE_10M_HALF:
-		break;
-	default:
-		if (netif_msg_link(adapter))
-			dev_err(&pdev->dev, "Wrong Media type %d\n",
-				hw->media_type);
-		return -1;
-		break;
-	}
-
-	ret_val = atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
-	if (ret_val)
-		return ret_val;
-	hw->phy_configured = true;
-
-	return 0;
-}
-
-/*
- * Detects the current speed and duplex settings of the hardware.
- *
- * hw - Struct containing variables accessed by shared code
- * speed - Speed of the connection
- * duplex - Duplex setting of the connection
- */
-int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex)
-{
-	int err;
-	u16 phy_data;
-
-	/* Read   PHY Specific Status Register (17) */
-	err = atl1c_read_phy_reg(hw, MII_GIGA_PSSR, &phy_data);
-	if (err)
-		return err;
-
-	if (!(phy_data & GIGA_PSSR_SPD_DPLX_RESOLVED))
-		return -1;
-
-	switch (phy_data & GIGA_PSSR_SPEED) {
-	case GIGA_PSSR_1000MBS:
-		*speed = SPEED_1000;
-		break;
-	case GIGA_PSSR_100MBS:
-		*speed = SPEED_100;
-		break;
-	case  GIGA_PSSR_10MBS:
-		*speed = SPEED_10;
-		break;
-	default:
-		return -1;
-		break;
-	}
-
-	if (phy_data & GIGA_PSSR_DPLX)
-		*duplex = FULL_DUPLEX;
-	else
-		*duplex = HALF_DUPLEX;
-
-	return 0;
-}
-
-int atl1c_phy_power_saving(struct atl1c_hw *hw)
-{
-	struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
-	struct pci_dev *pdev = adapter->pdev;
-	int ret = 0;
-	u16 autoneg_advertised = ADVERTISED_10baseT_Half;
-	u16 save_autoneg_advertised;
-	u16 phy_data;
-	u16 mii_lpa_data;
-	u16 speed = SPEED_0;
-	u16 duplex = FULL_DUPLEX;
-	int i;
-
-	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
-	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
-	if (phy_data & BMSR_LSTATUS) {
-		atl1c_read_phy_reg(hw, MII_LPA, &mii_lpa_data);
-		if (mii_lpa_data & LPA_10FULL)
-			autoneg_advertised = ADVERTISED_10baseT_Full;
-		else if (mii_lpa_data & LPA_10HALF)
-			autoneg_advertised = ADVERTISED_10baseT_Half;
-		else if (mii_lpa_data & LPA_100HALF)
-			autoneg_advertised = ADVERTISED_100baseT_Half;
-		else if (mii_lpa_data & LPA_100FULL)
-			autoneg_advertised = ADVERTISED_100baseT_Full;
-
-		save_autoneg_advertised = hw->autoneg_advertised;
-		hw->phy_configured = false;
-		hw->autoneg_advertised = autoneg_advertised;
-		if (atl1c_restart_autoneg(hw) != 0) {
-			dev_dbg(&pdev->dev, "phy autoneg failed\n");
-			ret = -1;
-		}
-		hw->autoneg_advertised = save_autoneg_advertised;
-
-		if (mii_lpa_data) {
-			for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) {
-				mdelay(100);
-				atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
-				atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
-				if (phy_data & BMSR_LSTATUS) {
-					if (atl1c_get_speed_and_duplex(hw, &speed,
-									&duplex) != 0)
-						dev_dbg(&pdev->dev,
-							"get speed and duplex failed\n");
-					break;
-				}
-			}
-		}
-	} else {
-		speed = SPEED_10;
-		duplex = HALF_DUPLEX;
-	}
-	adapter->link_speed = speed;
-	adapter->link_duplex = duplex;
-
-	return ret;
-}
-
-int atl1c_restart_autoneg(struct atl1c_hw *hw)
-{
-	int err = 0;
-	u16 mii_bmcr_data = BMCR_RESET;
-
-	err = atl1c_phy_setup_adv(hw);
-	if (err)
-		return err;
-	mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART;
-
-	return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/atl1c/atl1c_hw.h linux-libre-3.2-gnu/drivers/net/atl1c/atl1c_hw.h
--- linux-libre-3.1-gnu/drivers/net/atl1c/atl1c_hw.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atl1c/atl1c_hw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,868 +0,0 @@
-/*
- * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved.
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You 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 _ATL1C_HW_H_
-#define _ATL1C_HW_H_
-
-#include <linux/types.h>
-#include <linux/mii.h>
-
-struct atl1c_adapter;
-struct atl1c_hw;
-
-/* function prototype */
-void atl1c_phy_disable(struct atl1c_hw *hw);
-void atl1c_hw_set_mac_addr(struct atl1c_hw *hw);
-int atl1c_phy_reset(struct atl1c_hw *hw);
-int atl1c_read_mac_addr(struct atl1c_hw *hw);
-int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex);
-u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr);
-void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value);
-int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data);
-int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data);
-bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value);
-int atl1c_phy_init(struct atl1c_hw *hw);
-int atl1c_check_eeprom_exist(struct atl1c_hw *hw);
-int atl1c_restart_autoneg(struct atl1c_hw *hw);
-int atl1c_phy_power_saving(struct atl1c_hw *hw);
-/* register definition */
-#define REG_DEVICE_CAP              	0x5C
-#define DEVICE_CAP_MAX_PAYLOAD_MASK     0x7
-#define DEVICE_CAP_MAX_PAYLOAD_SHIFT    0
-
-#define REG_DEVICE_CTRL			0x60
-#define DEVICE_CTRL_MAX_PAYLOAD_MASK    0x7
-#define DEVICE_CTRL_MAX_PAYLOAD_SHIFT   5
-#define DEVICE_CTRL_MAX_RREQ_SZ_MASK    0x7
-#define DEVICE_CTRL_MAX_RREQ_SZ_SHIFT   12
-
-#define REG_LINK_CTRL			0x68
-#define LINK_CTRL_L0S_EN		0x01
-#define LINK_CTRL_L1_EN			0x02
-#define LINK_CTRL_EXT_SYNC		0x80
-
-#define REG_VPD_CAP			0x6C
-#define VPD_CAP_ID_MASK                 0xff
-#define VPD_CAP_ID_SHIFT                0
-#define VPD_CAP_NEXT_PTR_MASK           0xFF
-#define VPD_CAP_NEXT_PTR_SHIFT          8
-#define VPD_CAP_VPD_ADDR_MASK           0x7FFF
-#define VPD_CAP_VPD_ADDR_SHIFT          16
-#define VPD_CAP_VPD_FLAG                0x80000000
-
-#define REG_VPD_DATA                	0x70
-
-#define REG_PCIE_UC_SEVERITY		0x10C
-#define PCIE_UC_SERVRITY_TRN		0x00000001
-#define PCIE_UC_SERVRITY_DLP		0x00000010
-#define PCIE_UC_SERVRITY_PSN_TLP	0x00001000
-#define PCIE_UC_SERVRITY_FCP		0x00002000
-#define PCIE_UC_SERVRITY_CPL_TO		0x00004000
-#define PCIE_UC_SERVRITY_CA		0x00008000
-#define PCIE_UC_SERVRITY_UC		0x00010000
-#define PCIE_UC_SERVRITY_ROV		0x00020000
-#define PCIE_UC_SERVRITY_MLFP		0x00040000
-#define PCIE_UC_SERVRITY_ECRC		0x00080000
-#define PCIE_UC_SERVRITY_UR		0x00100000
-
-#define REG_DEV_SERIALNUM_CTRL		0x200
-#define REG_DEV_MAC_SEL_MASK		0x0 /* 0:EUI; 1:MAC */
-#define REG_DEV_MAC_SEL_SHIFT		0
-#define REG_DEV_SERIAL_NUM_EN_MASK	0x1
-#define REG_DEV_SERIAL_NUM_EN_SHIFT	1
-
-#define REG_TWSI_CTRL               	0x218
-#define TWSI_CTRL_LD_OFFSET_MASK        0xFF
-#define TWSI_CTRL_LD_OFFSET_SHIFT       0
-#define TWSI_CTRL_LD_SLV_ADDR_MASK      0x7
-#define TWSI_CTRL_LD_SLV_ADDR_SHIFT     8
-#define TWSI_CTRL_SW_LDSTART            0x800
-#define TWSI_CTRL_HW_LDSTART            0x1000
-#define TWSI_CTRL_SMB_SLV_ADDR_MASK     0x7F
-#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT    15
-#define TWSI_CTRL_LD_EXIST              0x400000
-#define TWSI_CTRL_READ_FREQ_SEL_MASK    0x3
-#define TWSI_CTRL_READ_FREQ_SEL_SHIFT   23
-#define TWSI_CTRL_FREQ_SEL_100K         0
-#define TWSI_CTRL_FREQ_SEL_200K         1
-#define TWSI_CTRL_FREQ_SEL_300K         2
-#define TWSI_CTRL_FREQ_SEL_400K         3
-#define TWSI_CTRL_SMB_SLV_ADDR
-#define TWSI_CTRL_WRITE_FREQ_SEL_MASK   0x3
-#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT  24
-
-
-#define REG_PCIE_DEV_MISC_CTRL      	0x21C
-#define PCIE_DEV_MISC_EXT_PIPE     	0x2
-#define PCIE_DEV_MISC_RETRY_BUFDIS 	0x1
-#define PCIE_DEV_MISC_SPIROM_EXIST 	0x4
-#define PCIE_DEV_MISC_SERDES_ENDIAN    	0x8
-#define PCIE_DEV_MISC_SERDES_SEL_DIN   	0x10
-
-#define REG_PCIE_PHYMISC	    	0x1000
-#define PCIE_PHYMISC_FORCE_RCV_DET	0x4
-
-#define REG_PCIE_PHYMISC2		0x1004
-#define PCIE_PHYMISC2_SERDES_CDR_MASK	0x3
-#define PCIE_PHYMISC2_SERDES_CDR_SHIFT	16
-#define PCIE_PHYMISC2_SERDES_TH_MASK	0x3
-#define PCIE_PHYMISC2_SERDES_TH_SHIFT	18
-
-#define REG_TWSI_DEBUG			0x1108
-#define TWSI_DEBUG_DEV_EXIST		0x20000000
-
-#define REG_EEPROM_CTRL			0x12C0
-#define EEPROM_CTRL_DATA_HI_MASK	0xFFFF
-#define EEPROM_CTRL_DATA_HI_SHIFT	0
-#define EEPROM_CTRL_ADDR_MASK		0x3FF
-#define EEPROM_CTRL_ADDR_SHIFT		16
-#define EEPROM_CTRL_ACK			0x40000000
-#define EEPROM_CTRL_RW			0x80000000
-
-#define REG_EEPROM_DATA_LO		0x12C4
-
-#define REG_OTP_CTRL			0x12F0
-#define OTP_CTRL_CLK_EN			0x0002
-
-#define REG_PM_CTRL			0x12F8
-#define PM_CTRL_SDES_EN			0x00000001
-#define PM_CTRL_RBER_EN			0x00000002
-#define PM_CTRL_CLK_REQ_EN		0x00000004
-#define PM_CTRL_ASPM_L1_EN		0x00000008
-#define PM_CTRL_SERDES_L1_EN		0x00000010
-#define PM_CTRL_SERDES_PLL_L1_EN	0x00000020
-#define PM_CTRL_SERDES_PD_EX_L1		0x00000040
-#define PM_CTRL_SERDES_BUDS_RX_L1_EN	0x00000080
-#define PM_CTRL_L0S_ENTRY_TIMER_MASK	0xF
-#define PM_CTRL_L0S_ENTRY_TIMER_SHIFT	8
-#define PM_CTRL_ASPM_L0S_EN		0x00001000
-#define PM_CTRL_CLK_SWH_L1		0x00002000
-#define PM_CTRL_CLK_PWM_VER1_1		0x00004000
-#define PM_CTRL_RCVR_WT_TIMER		0x00008000
-#define PM_CTRL_L1_ENTRY_TIMER_MASK	0xF
-#define PM_CTRL_L1_ENTRY_TIMER_SHIFT	16
-#define PM_CTRL_PM_REQ_TIMER_MASK	0xF
-#define PM_CTRL_PM_REQ_TIMER_SHIFT	20
-#define PM_CTRL_LCKDET_TIMER_MASK	0xF
-#define PM_CTRL_LCKDET_TIMER_SHIFT	24
-#define PM_CTRL_EN_BUFS_RX_L0S		0x10000000
-#define PM_CTRL_SA_DLY_EN		0x20000000
-#define PM_CTRL_MAC_ASPM_CHK		0x40000000
-#define PM_CTRL_HOTRST			0x80000000
-
-#define REG_LTSSM_ID_CTRL		0x12FC
-#define LTSSM_ID_EN_WRO			0x1000
-/* Selene Master Control Register */
-#define REG_MASTER_CTRL			0x1400
-#define MASTER_CTRL_SOFT_RST            0x1
-#define MASTER_CTRL_TEST_MODE_MASK	0x3
-#define MASTER_CTRL_TEST_MODE_SHIFT	2
-#define MASTER_CTRL_BERT_START		0x10
-#define MASTER_CTRL_OOB_DIS_OFF		0x40
-#define MASTER_CTRL_SA_TIMER_EN		0x80
-#define MASTER_CTRL_MTIMER_EN           0x100
-#define MASTER_CTRL_MANUAL_INT          0x200
-#define MASTER_CTRL_TX_ITIMER_EN	0x400
-#define MASTER_CTRL_RX_ITIMER_EN	0x800
-#define MASTER_CTRL_CLK_SEL_DIS		0x1000
-#define MASTER_CTRL_CLK_SWH_MODE	0x2000
-#define MASTER_CTRL_INT_RDCLR		0x4000
-#define MASTER_CTRL_REV_NUM_SHIFT	16
-#define MASTER_CTRL_REV_NUM_MASK	0xff
-#define MASTER_CTRL_DEV_ID_SHIFT	24
-#define MASTER_CTRL_DEV_ID_MASK		0x7f
-#define MASTER_CTRL_OTP_SEL		0x80000000
-
-/* Timer Initial Value Register */
-#define REG_MANUAL_TIMER_INIT       	0x1404
-
-/* IRQ ModeratorTimer Initial Value Register */
-#define REG_IRQ_MODRT_TIMER_INIT     	0x1408
-#define IRQ_MODRT_TIMER_MASK		0xffff
-#define IRQ_MODRT_TX_TIMER_SHIFT    	0
-#define IRQ_MODRT_RX_TIMER_SHIFT	16
-
-#define REG_GPHY_CTRL               	0x140C
-#define GPHY_CTRL_EXT_RESET         	0x1
-#define GPHY_CTRL_RTL_MODE		0x2
-#define GPHY_CTRL_LED_MODE		0x4
-#define GPHY_CTRL_ANEG_NOW		0x8
-#define GPHY_CTRL_REV_ANEG		0x10
-#define GPHY_CTRL_GATE_25M_EN       	0x20
-#define GPHY_CTRL_LPW_EXIT          	0x40
-#define GPHY_CTRL_PHY_IDDQ          	0x80
-#define GPHY_CTRL_PHY_IDDQ_DIS      	0x100
-#define GPHY_CTRL_GIGA_DIS		0x200
-#define GPHY_CTRL_HIB_EN            	0x400
-#define GPHY_CTRL_HIB_PULSE         	0x800
-#define GPHY_CTRL_SEL_ANA_RST       	0x1000
-#define GPHY_CTRL_PHY_PLL_ON        	0x2000
-#define GPHY_CTRL_PWDOWN_HW		0x4000
-#define GPHY_CTRL_PHY_PLL_BYPASS	0x8000
-
-#define GPHY_CTRL_DEFAULT (		 \
-		GPHY_CTRL_SEL_ANA_RST	|\
-		GPHY_CTRL_HIB_PULSE	|\
-		GPHY_CTRL_HIB_EN)
-
-#define GPHY_CTRL_PW_WOL_DIS (		 \
-		GPHY_CTRL_SEL_ANA_RST	|\
-		GPHY_CTRL_HIB_PULSE	|\
-		GPHY_CTRL_HIB_EN	|\
-		GPHY_CTRL_PWDOWN_HW	|\
-		GPHY_CTRL_PHY_IDDQ)
-
-#define GPHY_CTRL_POWER_SAVING (	\
-		GPHY_CTRL_SEL_ANA_RST	|\
-		GPHY_CTRL_HIB_EN	|\
-		GPHY_CTRL_HIB_PULSE	|\
-		GPHY_CTRL_PWDOWN_HW	|\
-		GPHY_CTRL_PHY_IDDQ)
-/* Block IDLE Status Register */
-#define REG_IDLE_STATUS  		0x1410
-#define IDLE_STATUS_MASK		0x00FF
-#define IDLE_STATUS_RXMAC_NO_IDLE      	0x1
-#define IDLE_STATUS_TXMAC_NO_IDLE      	0x2
-#define IDLE_STATUS_RXQ_NO_IDLE        	0x4
-#define IDLE_STATUS_TXQ_NO_IDLE        	0x8
-#define IDLE_STATUS_DMAR_NO_IDLE       	0x10
-#define IDLE_STATUS_DMAW_NO_IDLE       	0x20
-#define IDLE_STATUS_SMB_NO_IDLE        	0x40
-#define IDLE_STATUS_CMB_NO_IDLE        	0x80
-
-/* MDIO Control Register */
-#define REG_MDIO_CTRL           	0x1414
-#define MDIO_DATA_MASK          	0xffff  /* On MDIO write, the 16-bit
-						 * control data to write to PHY
-						 * MII management register */
-#define MDIO_DATA_SHIFT         	0       /* On MDIO read, the 16-bit
-						 * status data that was read
-						 * from the PHY MII management register */
-#define MDIO_REG_ADDR_MASK      	0x1f    /* MDIO register address */
-#define MDIO_REG_ADDR_SHIFT     	16
-#define MDIO_RW                 	0x200000  /* 1: read, 0: write */
-#define MDIO_SUP_PREAMBLE       	0x400000  /* Suppress preamble */
-#define MDIO_START              	0x800000  /* Write 1 to initiate the MDIO
-						   * master. And this bit is self
-						   * cleared after one cycle */
-#define MDIO_CLK_SEL_SHIFT      	24
-#define MDIO_CLK_25_4           	0
-#define MDIO_CLK_25_6           	2
-#define MDIO_CLK_25_8           	3
-#define MDIO_CLK_25_10          	4
-#define MDIO_CLK_25_14          	5
-#define MDIO_CLK_25_20          	6
-#define MDIO_CLK_25_28          	7
-#define MDIO_BUSY               	0x8000000
-#define MDIO_AP_EN              	0x10000000
-#define MDIO_WAIT_TIMES         	10
-
-/* MII PHY Status Register */
-#define REG_PHY_STATUS           	0x1418
-#define PHY_GENERAL_STATUS_MASK		0xFFFF
-#define PHY_STATUS_RECV_ENABLE		0x0001
-#define PHY_OE_PWSP_STATUS_MASK		0x07FF
-#define PHY_OE_PWSP_STATUS_SHIFT	16
-#define PHY_STATUS_LPW_STATE		0x80000000
-/* BIST Control and Status Register0 (for the Packet Memory) */
-#define REG_BIST0_CTRL              	0x141c
-#define BIST0_NOW                   	0x1
-#define BIST0_SRAM_FAIL             	0x2 /* 1: The SRAM failure is
-					     * un-repairable  because
-					     * it has address decoder
-					     * failure or more than 1 cell
-					     * stuck-to-x failure */
-#define BIST0_FUSE_FLAG             	0x4
-
-/* BIST Control and Status Register1(for the retry buffer of PCI Express) */
-#define REG_BIST1_CTRL			0x1420
-#define BIST1_NOW                   	0x1
-#define BIST1_SRAM_FAIL             	0x2
-#define BIST1_FUSE_FLAG             	0x4
-
-/* SerDes Lock Detect Control and Status Register */
-#define REG_SERDES_LOCK            	0x1424
-#define SERDES_LOCK_DETECT          	0x1  /* SerDes lock detected. This signal
-					      * comes from Analog SerDes */
-#define SERDES_LOCK_DETECT_EN       	0x2  /* 1: Enable SerDes Lock detect function */
-#define SERDES_LOCK_STS_SELFB_PLL_SHIFT 0xE
-#define SERDES_LOCK_STS_SELFB_PLL_MASK  0x3
-#define SERDES_OVCLK_18_25		0x0
-#define SERDES_OVCLK_12_18		0x1
-#define SERDES_OVCLK_0_4		0x2
-#define SERDES_OVCLK_4_12		0x3
-#define SERDES_MAC_CLK_SLOWDOWN		0x20000
-#define SERDES_PYH_CLK_SLOWDOWN		0x40000
-
-/* MAC Control Register  */
-#define REG_MAC_CTRL         		0x1480
-#define MAC_CTRL_TX_EN			0x1
-#define MAC_CTRL_RX_EN			0x2
-#define MAC_CTRL_TX_FLOW		0x4
-#define MAC_CTRL_RX_FLOW            	0x8
-#define MAC_CTRL_LOOPBACK          	0x10
-#define MAC_CTRL_DUPLX              	0x20
-#define MAC_CTRL_ADD_CRC            	0x40
-#define MAC_CTRL_PAD                	0x80
-#define MAC_CTRL_LENCHK             	0x100
-#define MAC_CTRL_HUGE_EN            	0x200
-#define MAC_CTRL_PRMLEN_SHIFT       	10
-#define MAC_CTRL_PRMLEN_MASK        	0xf
-#define MAC_CTRL_RMV_VLAN           	0x4000
-#define MAC_CTRL_PROMIS_EN          	0x8000
-#define MAC_CTRL_TX_PAUSE           	0x10000
-#define MAC_CTRL_SCNT               	0x20000
-#define MAC_CTRL_SRST_TX            	0x40000
-#define MAC_CTRL_TX_SIMURST         	0x80000
-#define MAC_CTRL_SPEED_SHIFT        	20
-#define MAC_CTRL_SPEED_MASK         	0x3
-#define MAC_CTRL_DBG_TX_BKPRESURE   	0x400000
-#define MAC_CTRL_TX_HUGE            	0x800000
-#define MAC_CTRL_RX_CHKSUM_EN       	0x1000000
-#define MAC_CTRL_MC_ALL_EN          	0x2000000
-#define MAC_CTRL_BC_EN              	0x4000000
-#define MAC_CTRL_DBG                	0x8000000
-#define MAC_CTRL_SINGLE_PAUSE_EN	0x10000000
-#define MAC_CTRL_HASH_ALG_CRC32		0x20000000
-#define MAC_CTRL_SPEED_MODE_SW		0x40000000
-
-/* MAC IPG/IFG Control Register  */
-#define REG_MAC_IPG_IFG             	0x1484
-#define MAC_IPG_IFG_IPGT_SHIFT      	0 	/* Desired back to back
-						 * inter-packet gap. The
-						 * default is 96-bit time */
-#define MAC_IPG_IFG_IPGT_MASK       	0x7f
-#define MAC_IPG_IFG_MIFG_SHIFT      	8       /* Minimum number of IFG to
-						 * enforce in between RX frames */
-#define MAC_IPG_IFG_MIFG_MASK       	0xff  	/* Frame gap below such IFP is dropped */
-#define MAC_IPG_IFG_IPGR1_SHIFT     	16   	/* 64bit Carrier-Sense window */
-#define MAC_IPG_IFG_IPGR1_MASK      	0x7f
-#define MAC_IPG_IFG_IPGR2_SHIFT     	24    	/* 96-bit IPG window */
-#define MAC_IPG_IFG_IPGR2_MASK      	0x7f
-
-/* MAC STATION ADDRESS  */
-#define REG_MAC_STA_ADDR		0x1488
-
-/* Hash table for multicast address */
-#define REG_RX_HASH_TABLE		0x1490
-
-/* MAC Half-Duplex Control Register */
-#define REG_MAC_HALF_DUPLX_CTRL     	0x1498
-#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT  0      /* Collision Window */
-#define MAC_HALF_DUPLX_CTRL_LCOL_MASK   0x3ff
-#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12
-#define MAC_HALF_DUPLX_CTRL_RETRY_MASK  0xf
-#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN  0x10000
-#define MAC_HALF_DUPLX_CTRL_NO_BACK_C   0x20000
-#define MAC_HALF_DUPLX_CTRL_NO_BACK_P   0x40000 /* No back-off on backpressure,
-						 * immediately start the
-						 * transmission after back pressure */
-#define MAC_HALF_DUPLX_CTRL_ABEBE        0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */
-#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT  20      /* Maximum binary exponential number */
-#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK   0xf
-#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24      /* IPG to start JAM for collision based flow control in half-duplex */
-#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK  0xf     /* mode. In unit of 8-bit time */
-
-/* Maximum Frame Length Control Register   */
-#define REG_MTU                     	0x149c
-
-/* Wake-On-Lan control register */
-#define REG_WOL_CTRL                	0x14a0
-#define WOL_PATTERN_EN              	0x00000001
-#define WOL_PATTERN_PME_EN              0x00000002
-#define WOL_MAGIC_EN                    0x00000004
-#define WOL_MAGIC_PME_EN                0x00000008
-#define WOL_LINK_CHG_EN                 0x00000010
-#define WOL_LINK_CHG_PME_EN             0x00000020
-#define WOL_PATTERN_ST                  0x00000100
-#define WOL_MAGIC_ST                    0x00000200
-#define WOL_LINKCHG_ST                  0x00000400
-#define WOL_CLK_SWITCH_EN               0x00008000
-#define WOL_PT0_EN                      0x00010000
-#define WOL_PT1_EN                      0x00020000
-#define WOL_PT2_EN                      0x00040000
-#define WOL_PT3_EN                      0x00080000
-#define WOL_PT4_EN                      0x00100000
-#define WOL_PT5_EN                      0x00200000
-#define WOL_PT6_EN                      0x00400000
-
-/* WOL Length ( 2 DWORD ) */
-#define REG_WOL_PATTERN_LEN         	0x14a4
-#define WOL_PT_LEN_MASK                 0x7f
-#define WOL_PT0_LEN_SHIFT               0
-#define WOL_PT1_LEN_SHIFT               8
-#define WOL_PT2_LEN_SHIFT               16
-#define WOL_PT3_LEN_SHIFT               24
-#define WOL_PT4_LEN_SHIFT               0
-#define WOL_PT5_LEN_SHIFT               8
-#define WOL_PT6_LEN_SHIFT               16
-
-/* Internal SRAM Partition Register */
-#define RFDX_HEAD_ADDR_MASK		0x03FF
-#define RFDX_HARD_ADDR_SHIFT		0
-#define RFDX_TAIL_ADDR_MASK		0x03FF
-#define RFDX_TAIL_ADDR_SHIFT            16
-
-#define REG_SRAM_RFD0_INFO		0x1500
-#define REG_SRAM_RFD1_INFO		0x1504
-#define REG_SRAM_RFD2_INFO		0x1508
-#define	REG_SRAM_RFD3_INFO		0x150C
-
-#define REG_RFD_NIC_LEN			0x1510 /* In 8-bytes */
-#define RFD_NIC_LEN_MASK		0x03FF
-
-#define REG_SRAM_TRD_ADDR           	0x1518
-#define TPD_HEAD_ADDR_MASK		0x03FF
-#define TPD_HEAD_ADDR_SHIFT		0
-#define TPD_TAIL_ADDR_MASK		0x03FF
-#define TPD_TAIL_ADDR_SHIFT		16
-
-#define REG_SRAM_TRD_LEN            	0x151C /* In 8-bytes */
-#define TPD_NIC_LEN_MASK		0x03FF
-
-#define REG_SRAM_RXF_ADDR          	0x1520
-#define REG_SRAM_RXF_LEN            	0x1524
-#define REG_SRAM_TXF_ADDR           	0x1528
-#define REG_SRAM_TXF_LEN            	0x152C
-#define REG_SRAM_TCPH_ADDR          	0x1530
-#define REG_SRAM_PKTH_ADDR          	0x1532
-
-/*
- * Load Ptr Register
- * Software sets this bit after the initialization of the head and tail */
-#define REG_LOAD_PTR                	0x1534
-
-/*
- * addresses of all descriptors, as well as the following descriptor
- * control register, which triggers each function block to load the head
- * pointer to prepare for the operation. This bit is then self-cleared
- * after one cycle.
- */
-#define REG_RX_BASE_ADDR_HI		0x1540
-#define REG_TX_BASE_ADDR_HI		0x1544
-#define REG_SMB_BASE_ADDR_HI		0x1548
-#define REG_SMB_BASE_ADDR_LO		0x154C
-#define REG_RFD0_HEAD_ADDR_LO		0x1550
-#define REG_RFD1_HEAD_ADDR_LO		0x1554
-#define REG_RFD2_HEAD_ADDR_LO		0x1558
-#define REG_RFD3_HEAD_ADDR_LO		0x155C
-#define REG_RFD_RING_SIZE		0x1560
-#define RFD_RING_SIZE_MASK		0x0FFF
-#define REG_RX_BUF_SIZE			0x1564
-#define RX_BUF_SIZE_MASK		0xFFFF
-#define REG_RRD0_HEAD_ADDR_LO		0x1568
-#define REG_RRD1_HEAD_ADDR_LO		0x156C
-#define REG_RRD2_HEAD_ADDR_LO		0x1570
-#define REG_RRD3_HEAD_ADDR_LO		0x1574
-#define REG_RRD_RING_SIZE		0x1578
-#define RRD_RING_SIZE_MASK		0x0FFF
-#define REG_HTPD_HEAD_ADDR_LO		0x157C
-#define REG_NTPD_HEAD_ADDR_LO		0x1580
-#define REG_TPD_RING_SIZE		0x1584
-#define TPD_RING_SIZE_MASK		0xFFFF
-#define REG_CMB_BASE_ADDR_LO		0x1588
-
-/* RSS about */
-#define REG_RSS_KEY0                    0x14B0
-#define REG_RSS_KEY1                    0x14B4
-#define REG_RSS_KEY2                    0x14B8
-#define REG_RSS_KEY3                    0x14BC
-#define REG_RSS_KEY4                    0x14C0
-#define REG_RSS_KEY5                    0x14C4
-#define REG_RSS_KEY6                    0x14C8
-#define REG_RSS_KEY7                    0x14CC
-#define REG_RSS_KEY8                    0x14D0
-#define REG_RSS_KEY9                    0x14D4
-#define REG_IDT_TABLE0                	0x14E0
-#define REG_IDT_TABLE1                  0x14E4
-#define REG_IDT_TABLE2                  0x14E8
-#define REG_IDT_TABLE3                  0x14EC
-#define REG_IDT_TABLE4                  0x14F0
-#define REG_IDT_TABLE5                  0x14F4
-#define REG_IDT_TABLE6                  0x14F8
-#define REG_IDT_TABLE7                  0x14FC
-#define REG_IDT_TABLE                   REG_IDT_TABLE0
-#define REG_RSS_HASH_VALUE              0x15B0
-#define REG_RSS_HASH_FLAG               0x15B4
-#define REG_BASE_CPU_NUMBER             0x15B8
-
-/* TXQ Control Register */
-#define REG_TXQ_CTRL                	0x1590
-#define	TXQ_NUM_TPD_BURST_MASK     	0xF
-#define TXQ_NUM_TPD_BURST_SHIFT    	0
-#define TXQ_CTRL_IP_OPTION_EN		0x10
-#define TXQ_CTRL_EN                     0x20
-#define TXQ_CTRL_ENH_MODE               0x40
-#define TXQ_CTRL_LS_8023_EN		0x80
-#define TXQ_TXF_BURST_NUM_SHIFT    	16
-#define TXQ_TXF_BURST_NUM_MASK     	0xFFFF
-
-/* Jumbo packet Threshold for task offload */
-#define REG_TX_TSO_OFFLOAD_THRESH	0x1594 /* In 8-bytes */
-#define TX_TSO_OFFLOAD_THRESH_MASK	0x07FF
-
-#define	REG_TXF_WATER_MARK		0x1598 /* In 8-bytes */
-#define TXF_WATER_MARK_MASK		0x0FFF
-#define TXF_LOW_WATER_MARK_SHIFT	0
-#define TXF_HIGH_WATER_MARK_SHIFT 	16
-#define TXQ_CTRL_BURST_MODE_EN		0x80000000
-
-#define REG_THRUPUT_MON_CTRL		0x159C
-#define THRUPUT_MON_RATE_MASK		0x3
-#define THRUPUT_MON_RATE_SHIFT		0
-#define THRUPUT_MON_EN			0x80
-
-/* RXQ Control Register */
-#define REG_RXQ_CTRL                	0x15A0
-#define ASPM_THRUPUT_LIMIT_MASK		0x3
-#define ASPM_THRUPUT_LIMIT_SHIFT	0
-#define ASPM_THRUPUT_LIMIT_NO		0x00
-#define ASPM_THRUPUT_LIMIT_1M		0x01
-#define ASPM_THRUPUT_LIMIT_10M		0x02
-#define ASPM_THRUPUT_LIMIT_100M		0x04
-#define RXQ1_CTRL_EN			0x10
-#define RXQ2_CTRL_EN			0x20
-#define RXQ3_CTRL_EN			0x40
-#define IPV6_CHKSUM_CTRL_EN		0x80
-#define RSS_HASH_BITS_MASK		0x00FF
-#define RSS_HASH_BITS_SHIFT		8
-#define RSS_HASH_IPV4			0x10000
-#define RSS_HASH_IPV4_TCP		0x20000
-#define RSS_HASH_IPV6			0x40000
-#define RSS_HASH_IPV6_TCP		0x80000
-#define RXQ_RFD_BURST_NUM_MASK		0x003F
-#define RXQ_RFD_BURST_NUM_SHIFT		20
-#define RSS_MODE_MASK			0x0003
-#define RSS_MODE_SHIFT			26
-#define RSS_NIP_QUEUE_SEL_MASK		0x1
-#define RSS_NIP_QUEUE_SEL_SHIFT		28
-#define RRS_HASH_CTRL_EN		0x20000000
-#define RX_CUT_THRU_EN			0x40000000
-#define RXQ_CTRL_EN			0x80000000
-
-#define REG_RFD_FREE_THRESH		0x15A4
-#define RFD_FREE_THRESH_MASK		0x003F
-#define RFD_FREE_HI_THRESH_SHIFT	0
-#define RFD_FREE_LO_THRESH_SHIFT	6
-
-/* RXF flow control register */
-#define REG_RXQ_RXF_PAUSE_THRESH    	0x15A8
-#define RXQ_RXF_PAUSE_TH_HI_SHIFT       0
-#define RXQ_RXF_PAUSE_TH_HI_MASK        0x0FFF
-#define RXQ_RXF_PAUSE_TH_LO_SHIFT       16
-#define RXQ_RXF_PAUSE_TH_LO_MASK        0x0FFF
-
-#define REG_RXD_DMA_CTRL		0x15AC
-#define RXD_DMA_THRESH_MASK		0x0FFF	/* In 8-bytes */
-#define RXD_DMA_THRESH_SHIFT		0
-#define RXD_DMA_DOWN_TIMER_MASK		0xFFFF
-#define RXD_DMA_DOWN_TIMER_SHIFT	16
-
-/* DMA Engine Control Register */
-#define REG_DMA_CTRL                	0x15C0
-#define DMA_CTRL_DMAR_IN_ORDER          0x1
-#define DMA_CTRL_DMAR_ENH_ORDER         0x2
-#define DMA_CTRL_DMAR_OUT_ORDER         0x4
-#define DMA_CTRL_RCB_VALUE              0x8
-#define DMA_CTRL_DMAR_BURST_LEN_MASK    0x0007
-#define DMA_CTRL_DMAR_BURST_LEN_SHIFT   4
-#define DMA_CTRL_DMAW_BURST_LEN_MASK    0x0007
-#define DMA_CTRL_DMAW_BURST_LEN_SHIFT   7
-#define DMA_CTRL_DMAR_REQ_PRI           0x400
-#define DMA_CTRL_DMAR_DLY_CNT_MASK      0x001F
-#define DMA_CTRL_DMAR_DLY_CNT_SHIFT     11
-#define DMA_CTRL_DMAW_DLY_CNT_MASK      0x000F
-#define DMA_CTRL_DMAW_DLY_CNT_SHIFT     16
-#define DMA_CTRL_CMB_EN               	0x100000
-#define DMA_CTRL_SMB_EN			0x200000
-#define DMA_CTRL_CMB_NOW		0x400000
-#define MAC_CTRL_SMB_DIS		0x1000000
-#define DMA_CTRL_SMB_NOW		0x80000000
-
-/* CMB/SMB Control Register */
-#define REG_SMB_STAT_TIMER		0x15C4	/* 2us resolution */
-#define SMB_STAT_TIMER_MASK		0xFFFFFF
-#define REG_CMB_TPD_THRESH		0x15C8
-#define CMB_TPD_THRESH_MASK		0xFFFF
-#define REG_CMB_TX_TIMER		0x15CC	/* 2us resolution */
-#define CMB_TX_TIMER_MASK		0xFFFF
-
-/* Mail box */
-#define MB_RFDX_PROD_IDX_MASK		0xFFFF
-#define REG_MB_RFD0_PROD_IDX		0x15E0
-#define REG_MB_RFD1_PROD_IDX		0x15E4
-#define REG_MB_RFD2_PROD_IDX		0x15E8
-#define REG_MB_RFD3_PROD_IDX		0x15EC
-
-#define MB_PRIO_PROD_IDX_MASK		0xFFFF
-#define REG_MB_PRIO_PROD_IDX		0x15F0
-#define MB_HTPD_PROD_IDX_SHIFT		0
-#define MB_NTPD_PROD_IDX_SHIFT		16
-
-#define MB_PRIO_CONS_IDX_MASK		0xFFFF
-#define REG_MB_PRIO_CONS_IDX		0x15F4
-#define MB_HTPD_CONS_IDX_SHIFT		0
-#define MB_NTPD_CONS_IDX_SHIFT		16
-
-#define REG_MB_RFD01_CONS_IDX		0x15F8
-#define MB_RFD0_CONS_IDX_MASK		0x0000FFFF
-#define MB_RFD1_CONS_IDX_MASK		0xFFFF0000
-#define REG_MB_RFD23_CONS_IDX		0x15FC
-#define MB_RFD2_CONS_IDX_MASK		0x0000FFFF
-#define MB_RFD3_CONS_IDX_MASK		0xFFFF0000
-
-/* Interrupt Status Register */
-#define REG_ISR    			0x1600
-#define ISR_SMB				0x00000001
-#define ISR_TIMER			0x00000002
-/*
- * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set
- * in Table 51 Selene Master Control Register (Offset 0x1400).
- */
-#define ISR_MANUAL         		0x00000004
-#define ISR_HW_RXF_OV          		0x00000008 /* RXF overflow interrupt */
-#define ISR_RFD0_UR			0x00000010 /* RFD0 under run */
-#define ISR_RFD1_UR			0x00000020
-#define ISR_RFD2_UR			0x00000040
-#define ISR_RFD3_UR			0x00000080
-#define ISR_TXF_UR			0x00000100
-#define ISR_DMAR_TO_RST			0x00000200
-#define ISR_DMAW_TO_RST			0x00000400
-#define ISR_TX_CREDIT			0x00000800
-#define ISR_GPHY			0x00001000
-/* GPHY low power state interrupt */
-#define ISR_GPHY_LPW           		0x00002000
-#define ISR_TXQ_TO_RST			0x00004000
-#define ISR_TX_PKT			0x00008000
-#define ISR_RX_PKT_0			0x00010000
-#define ISR_RX_PKT_1			0x00020000
-#define ISR_RX_PKT_2			0x00040000
-#define ISR_RX_PKT_3			0x00080000
-#define ISR_MAC_RX			0x00100000
-#define ISR_MAC_TX			0x00200000
-#define ISR_UR_DETECTED			0x00400000
-#define ISR_FERR_DETECTED		0x00800000
-#define ISR_NFERR_DETECTED		0x01000000
-#define ISR_CERR_DETECTED		0x02000000
-#define ISR_PHY_LINKDOWN		0x04000000
-#define ISR_DIS_INT			0x80000000
-
-/* Interrupt Mask Register */
-#define REG_IMR				0x1604
-
-#define IMR_NORMAL_MASK		(\
-		ISR_MANUAL	|\
-		ISR_HW_RXF_OV	|\
-		ISR_RFD0_UR	|\
-		ISR_TXF_UR	|\
-		ISR_DMAR_TO_RST	|\
-		ISR_TXQ_TO_RST  |\
-		ISR_DMAW_TO_RST	|\
-		ISR_GPHY	|\
-		ISR_TX_PKT	|\
-		ISR_RX_PKT_0	|\
-		ISR_GPHY_LPW    |\
-		ISR_PHY_LINKDOWN)
-
-#define ISR_RX_PKT 	(\
-	ISR_RX_PKT_0    |\
-	ISR_RX_PKT_1    |\
-	ISR_RX_PKT_2    |\
-	ISR_RX_PKT_3)
-
-#define ISR_OVER	(\
-	ISR_RFD0_UR 	|\
-	ISR_RFD1_UR	|\
-	ISR_RFD2_UR	|\
-	ISR_RFD3_UR	|\
-	ISR_HW_RXF_OV	|\
-	ISR_TXF_UR)
-
-#define ISR_ERROR	(\
-	ISR_DMAR_TO_RST	|\
-	ISR_TXQ_TO_RST  |\
-	ISR_DMAW_TO_RST	|\
-	ISR_PHY_LINKDOWN)
-
-#define REG_INT_RETRIG_TIMER		0x1608
-#define INT_RETRIG_TIMER_MASK		0xFFFF
-
-#define REG_HDS_CTRL			0x160C
-#define HDS_CTRL_EN			0x0001
-#define HDS_CTRL_BACKFILLSIZE_SHIFT	8
-#define HDS_CTRL_BACKFILLSIZE_MASK	0x0FFF
-#define HDS_CTRL_MAX_HDRSIZE_SHIFT	20
-#define HDS_CTRL_MAC_HDRSIZE_MASK	0x0FFF
-
-#define REG_MAC_RX_STATUS_BIN 		0x1700
-#define REG_MAC_RX_STATUS_END 		0x175c
-#define REG_MAC_TX_STATUS_BIN 		0x1760
-#define REG_MAC_TX_STATUS_END 		0x17c0
-
-#define REG_CLK_GATING_CTRL		0x1814
-#define CLK_GATING_DMAW_EN		0x0001
-#define CLK_GATING_DMAR_EN		0x0002
-#define CLK_GATING_TXQ_EN		0x0004
-#define CLK_GATING_RXQ_EN		0x0008
-#define CLK_GATING_TXMAC_EN		0x0010
-#define CLK_GATING_RXMAC_EN		0x0020
-
-#define CLK_GATING_EN_ALL	(CLK_GATING_DMAW_EN |\
-				 CLK_GATING_DMAR_EN |\
-				 CLK_GATING_TXQ_EN  |\
-				 CLK_GATING_RXQ_EN  |\
-				 CLK_GATING_TXMAC_EN|\
-				 CLK_GATING_RXMAC_EN)
-
-/* DEBUG ADDR */
-#define REG_DEBUG_DATA0 		0x1900
-#define REG_DEBUG_DATA1 		0x1904
-
-#define L1D_MPW_PHYID1			0xD01C  /* V7 */
-#define L1D_MPW_PHYID2			0xD01D  /* V1-V6 */
-#define L1D_MPW_PHYID3			0xD01E  /* V8 */
-
-
-/* Autoneg Advertisement Register */
-#define ADVERTISE_DEFAULT_CAP \
-	(ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)
-
-/* 1000BASE-T Control Register */
-#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 */
-#define GIGA_CR_1000T_MS_ENABLE		0x1000  /* 1=Master/Slave manual config value 0=Automatic Master/Slave config */
-#define GIGA_CR_1000T_TEST_MODE_NORMAL	0x0000  /* Normal Operation */
-#define GIGA_CR_1000T_TEST_MODE_1	0x2000  /* Transmit Waveform test */
-#define GIGA_CR_1000T_TEST_MODE_2	0x4000  /* Master Transmit Jitter test */
-#define GIGA_CR_1000T_TEST_MODE_3	0x6000  /* Slave Transmit Jitter test */
-#define GIGA_CR_1000T_TEST_MODE_4	0x8000	/* Transmitter Distortion test */
-#define GIGA_CR_1000T_SPEED_MASK	0x0300
-#define GIGA_CR_1000T_DEFAULT_CAP	0x0300
-
-/* PHY Specific Status Register */
-#define MII_GIGA_PSSR			0x11
-#define GIGA_PSSR_SPD_DPLX_RESOLVED	0x0800  /* 1=Speed & Duplex resolved */
-#define GIGA_PSSR_DPLX			0x2000  /* 1=Duplex 0=Half Duplex */
-#define GIGA_PSSR_SPEED			0xC000  /* Speed, bits 14:15 */
-#define GIGA_PSSR_10MBS			0x0000  /* 00=10Mbs */
-#define GIGA_PSSR_100MBS		0x4000  /* 01=100Mbs */
-#define GIGA_PSSR_1000MBS		0x8000  /* 10=1000Mbs */
-
-/* PHY Interrupt Enable Register */
-#define MII_IER				0x12
-#define IER_LINK_UP			0x0400
-#define IER_LINK_DOWN			0x0800
-
-/* PHY Interrupt Status Register */
-#define MII_ISR				0x13
-#define ISR_LINK_UP			0x0400
-#define ISR_LINK_DOWN			0x0800
-
-/* Cable-Detect-Test Control Register */
-#define MII_CDTC			0x16
-#define CDTC_EN_OFF			0   /* sc */
-#define CDTC_EN_BITS			1
-#define CDTC_PAIR_OFF			8
-#define CDTC_PAIR_BIT			2
-
-/* Cable-Detect-Test Status Register */
-#define MII_CDTS			0x1C
-#define CDTS_STATUS_OFF			8
-#define CDTS_STATUS_BITS		2
-#define CDTS_STATUS_NORMAL		0
-#define CDTS_STATUS_SHORT		1
-#define CDTS_STATUS_OPEN		2
-#define CDTS_STATUS_INVALID		3
-
-#define MII_DBG_ADDR			0x1D
-#define MII_DBG_DATA			0x1E
-
-#define MII_ANA_CTRL_0			0x0
-#define ANA_RESTART_CAL			0x0001
-#define ANA_MANUL_SWICH_ON_SHIFT	0x1
-#define ANA_MANUL_SWICH_ON_MASK		0xF
-#define ANA_MAN_ENABLE			0x0020
-#define ANA_SEL_HSP			0x0040
-#define ANA_EN_HB			0x0080
-#define ANA_EN_HBIAS			0x0100
-#define ANA_OEN_125M			0x0200
-#define ANA_EN_LCKDT			0x0400
-#define ANA_LCKDT_PHY			0x0800
-#define ANA_AFE_MODE			0x1000
-#define ANA_VCO_SLOW			0x2000
-#define ANA_VCO_FAST			0x4000
-#define ANA_SEL_CLK125M_DSP		0x8000
-
-#define MII_ANA_CTRL_4			0x4
-#define ANA_IECHO_ADJ_MASK		0xF
-#define ANA_IECHO_ADJ_3_SHIFT		0
-#define ANA_IECHO_ADJ_2_SHIFT		4
-#define ANA_IECHO_ADJ_1_SHIFT		8
-#define ANA_IECHO_ADJ_0_SHIFT		12
-
-#define MII_ANA_CTRL_5			0x5
-#define ANA_SERDES_CDR_BW_SHIFT		0
-#define ANA_SERDES_CDR_BW_MASK		0x3
-#define ANA_MS_PAD_DBG			0x0004
-#define ANA_SPEEDUP_DBG			0x0008
-#define ANA_SERDES_TH_LOS_SHIFT		4
-#define ANA_SERDES_TH_LOS_MASK		0x3
-#define ANA_SERDES_EN_DEEM		0x0040
-#define ANA_SERDES_TXELECIDLE		0x0080
-#define ANA_SERDES_BEACON		0x0100
-#define ANA_SERDES_HALFTXDR		0x0200
-#define ANA_SERDES_SEL_HSP		0x0400
-#define ANA_SERDES_EN_PLL		0x0800
-#define ANA_SERDES_EN			0x1000
-#define ANA_SERDES_EN_LCKDT		0x2000
-
-#define MII_ANA_CTRL_11			0xB
-#define ANA_PS_HIB_EN			0x8000
-
-#define MII_ANA_CTRL_18			0x12
-#define ANA_TEST_MODE_10BT_01SHIFT	0
-#define ANA_TEST_MODE_10BT_01MASK	0x3
-#define ANA_LOOP_SEL_10BT		0x0004
-#define ANA_RGMII_MODE_SW		0x0008
-#define ANA_EN_LONGECABLE		0x0010
-#define ANA_TEST_MODE_10BT_2		0x0020
-#define ANA_EN_10BT_IDLE		0x0400
-#define ANA_EN_MASK_TB			0x0800
-#define ANA_TRIGGER_SEL_TIMER_SHIFT	12
-#define ANA_TRIGGER_SEL_TIMER_MASK	0x3
-#define ANA_INTERVAL_SEL_TIMER_SHIFT	14
-#define ANA_INTERVAL_SEL_TIMER_MASK	0x3
-
-#define MII_ANA_CTRL_41			0x29
-#define ANA_TOP_PS_EN			0x8000
-
-#define MII_ANA_CTRL_54			0x36
-#define ANA_LONG_CABLE_TH_100_SHIFT	0
-#define ANA_LONG_CABLE_TH_100_MASK	0x3F
-#define ANA_DESERVED			0x0040
-#define ANA_EN_LIT_CH			0x0080
-#define ANA_SHORT_CABLE_TH_100_SHIFT	8
-#define ANA_SHORT_CABLE_TH_100_MASK	0x3F
-#define ANA_BP_BAD_LINK_ACCUM		0x4000
-#define ANA_BP_SMALL_BW			0x8000
-
-#endif /*_ATL1C_HW_H_*/
diff -druN linux-libre-3.1-gnu/drivers/net/atl1c/atl1c_main.c linux-libre-3.2-gnu/drivers/net/atl1c/atl1c_main.c
--- linux-libre-3.1-gnu/drivers/net/atl1c/atl1c_main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atl1c/atl1c_main.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2934 +0,0 @@
-/*
- * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved.
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You 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 "atl1c.h"
-
-#define ATL1C_DRV_VERSION "1.0.1.0-NAPI"
-char atl1c_driver_name[] = "atl1c";
-char atl1c_driver_version[] = ATL1C_DRV_VERSION;
-#define PCI_DEVICE_ID_ATTANSIC_L2C      0x1062
-#define PCI_DEVICE_ID_ATTANSIC_L1C      0x1063
-#define PCI_DEVICE_ID_ATHEROS_L2C_B	0x2060 /* AR8152 v1.1 Fast 10/100 */
-#define PCI_DEVICE_ID_ATHEROS_L2C_B2	0x2062 /* AR8152 v2.0 Fast 10/100 */
-#define PCI_DEVICE_ID_ATHEROS_L1D	0x1073 /* AR8151 v1.0 Gigabit 1000 */
-#define PCI_DEVICE_ID_ATHEROS_L1D_2_0	0x1083 /* AR8151 v2.0 Gigabit 1000 */
-#define L2CB_V10			0xc0
-#define L2CB_V11			0xc1
-
-/*
- * atl1c_pci_tbl - PCI Device ID Table
- *
- * Wildcard entries (PCI_ANY_ID) should come last
- * Last entry must be all 0s
- *
- * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
- *   Class, Class Mask, private data (not used) }
- */
-static DEFINE_PCI_DEVICE_TABLE(atl1c_pci_tbl) = {
-	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1C)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2C)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B2)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L1D)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L1D_2_0)},
-	/* required last entry */
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, atl1c_pci_tbl);
-
-MODULE_AUTHOR("Jie Yang <jie.yang@atheros.com>");
-MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(ATL1C_DRV_VERSION);
-
-static int atl1c_stop_mac(struct atl1c_hw *hw);
-static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw);
-static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw);
-static void atl1c_disable_l0s_l1(struct atl1c_hw *hw);
-static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup);
-static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter);
-static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que,
-		   int *work_done, int work_to_do);
-static int atl1c_up(struct atl1c_adapter *adapter);
-static void atl1c_down(struct atl1c_adapter *adapter);
-
-static const u16 atl1c_pay_load_size[] = {
-	128, 256, 512, 1024, 2048, 4096,
-};
-
-static const u16 atl1c_rfd_prod_idx_regs[AT_MAX_RECEIVE_QUEUE] =
-{
-	REG_MB_RFD0_PROD_IDX,
-	REG_MB_RFD1_PROD_IDX,
-	REG_MB_RFD2_PROD_IDX,
-	REG_MB_RFD3_PROD_IDX
-};
-
-static const u16 atl1c_rfd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] =
-{
-	REG_RFD0_HEAD_ADDR_LO,
-	REG_RFD1_HEAD_ADDR_LO,
-	REG_RFD2_HEAD_ADDR_LO,
-	REG_RFD3_HEAD_ADDR_LO
-};
-
-static const u16 atl1c_rrd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] =
-{
-	REG_RRD0_HEAD_ADDR_LO,
-	REG_RRD1_HEAD_ADDR_LO,
-	REG_RRD2_HEAD_ADDR_LO,
-	REG_RRD3_HEAD_ADDR_LO
-};
-
-static const u32 atl1c_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
-	NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP;
-static void atl1c_pcie_patch(struct atl1c_hw *hw)
-{
-	u32 data;
-
-	AT_READ_REG(hw, REG_PCIE_PHYMISC, &data);
-	data |= PCIE_PHYMISC_FORCE_RCV_DET;
-	AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data);
-
-	if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) {
-		AT_READ_REG(hw, REG_PCIE_PHYMISC2, &data);
-
-		data &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK <<
-			PCIE_PHYMISC2_SERDES_CDR_SHIFT);
-		data |= 3 << PCIE_PHYMISC2_SERDES_CDR_SHIFT;
-		data &= ~(PCIE_PHYMISC2_SERDES_TH_MASK <<
-			PCIE_PHYMISC2_SERDES_TH_SHIFT);
-		data |= 3 << PCIE_PHYMISC2_SERDES_TH_SHIFT;
-		AT_WRITE_REG(hw, REG_PCIE_PHYMISC2, data);
-	}
-}
-
-/* FIXME: no need any more ? */
-/*
- * atl1c_init_pcie - init PCIE module
- */
-static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
-{
-	u32 data;
-	u32 pci_cmd;
-	struct pci_dev *pdev = hw->adapter->pdev;
-
-	AT_READ_REG(hw, PCI_COMMAND, &pci_cmd);
-	pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
-	pci_cmd |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
-		PCI_COMMAND_IO);
-	AT_WRITE_REG(hw, PCI_COMMAND, pci_cmd);
-
-	/*
-	 * Clear any PowerSaveing Settings
-	 */
-	pci_enable_wake(pdev, PCI_D3hot, 0);
-	pci_enable_wake(pdev, PCI_D3cold, 0);
-
-	/*
-	 * Mask some pcie error bits
-	 */
-	AT_READ_REG(hw, REG_PCIE_UC_SEVERITY, &data);
-	data &= ~PCIE_UC_SERVRITY_DLP;
-	data &= ~PCIE_UC_SERVRITY_FCP;
-	AT_WRITE_REG(hw, REG_PCIE_UC_SEVERITY, data);
-
-	AT_READ_REG(hw, REG_LTSSM_ID_CTRL, &data);
-	data &= ~LTSSM_ID_EN_WRO;
-	AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, data);
-
-	atl1c_pcie_patch(hw);
-	if (flag & ATL1C_PCIE_L0S_L1_DISABLE)
-		atl1c_disable_l0s_l1(hw);
-	if (flag & ATL1C_PCIE_PHY_RESET)
-		AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT);
-	else
-		AT_WRITE_REG(hw, REG_GPHY_CTRL,
-			GPHY_CTRL_DEFAULT | GPHY_CTRL_EXT_RESET);
-
-	msleep(5);
-}
-
-/*
- * atl1c_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- */
-static inline void atl1c_irq_enable(struct atl1c_adapter *adapter)
-{
-	if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
-		AT_WRITE_REG(&adapter->hw, REG_ISR, 0x7FFFFFFF);
-		AT_WRITE_REG(&adapter->hw, REG_IMR, adapter->hw.intr_mask);
-		AT_WRITE_FLUSH(&adapter->hw);
-	}
-}
-
-/*
- * atl1c_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- */
-static inline void atl1c_irq_disable(struct atl1c_adapter *adapter)
-{
-	atomic_inc(&adapter->irq_sem);
-	AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
-	AT_WRITE_REG(&adapter->hw, REG_ISR, ISR_DIS_INT);
-	AT_WRITE_FLUSH(&adapter->hw);
-	synchronize_irq(adapter->pdev->irq);
-}
-
-/*
- * atl1c_irq_reset - reset interrupt confiure on the NIC
- * @adapter: board private structure
- */
-static inline void atl1c_irq_reset(struct atl1c_adapter *adapter)
-{
-	atomic_set(&adapter->irq_sem, 1);
-	atl1c_irq_enable(adapter);
-}
-
-/*
- * atl1c_wait_until_idle - wait up to AT_HW_MAX_IDLE_DELAY reads
- * of the idle status register until the device is actually idle
- */
-static u32 atl1c_wait_until_idle(struct atl1c_hw *hw)
-{
-	int timeout;
-	u32 data;
-
-	for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
-		AT_READ_REG(hw, REG_IDLE_STATUS, &data);
-		if ((data & IDLE_STATUS_MASK) == 0)
-			return 0;
-		msleep(1);
-	}
-	return data;
-}
-
-/*
- * atl1c_phy_config - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
- */
-static void atl1c_phy_config(unsigned long data)
-{
-	struct atl1c_adapter *adapter = (struct atl1c_adapter *) data;
-	struct atl1c_hw *hw = &adapter->hw;
-	unsigned long flags;
-
-	spin_lock_irqsave(&adapter->mdio_lock, flags);
-	atl1c_restart_autoneg(hw);
-	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
-}
-
-void atl1c_reinit_locked(struct atl1c_adapter *adapter)
-{
-	WARN_ON(in_interrupt());
-	atl1c_down(adapter);
-	atl1c_up(adapter);
-	clear_bit(__AT_RESETTING, &adapter->flags);
-}
-
-static void atl1c_check_link_status(struct atl1c_adapter *adapter)
-{
-	struct atl1c_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	struct pci_dev    *pdev   = adapter->pdev;
-	int err;
-	unsigned long flags;
-	u16 speed, duplex, phy_data;
-
-	spin_lock_irqsave(&adapter->mdio_lock, flags);
-	/* MII_BMSR must read twise */
-	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
-	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
-	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
-
-	if ((phy_data & BMSR_LSTATUS) == 0) {
-		/* link down */
-		hw->hibernate = true;
-		if (atl1c_stop_mac(hw) != 0)
-			if (netif_msg_hw(adapter))
-				dev_warn(&pdev->dev, "stop mac failed\n");
-		atl1c_set_aspm(hw, false);
-		netif_carrier_off(netdev);
-		netif_stop_queue(netdev);
-		atl1c_phy_reset(hw);
-		atl1c_phy_init(&adapter->hw);
-	} else {
-		/* Link Up */
-		hw->hibernate = false;
-		spin_lock_irqsave(&adapter->mdio_lock, flags);
-		err = atl1c_get_speed_and_duplex(hw, &speed, &duplex);
-		spin_unlock_irqrestore(&adapter->mdio_lock, flags);
-		if (unlikely(err))
-			return;
-		/* link result is our setting */
-		if (adapter->link_speed != speed ||
-		    adapter->link_duplex != duplex) {
-			adapter->link_speed  = speed;
-			adapter->link_duplex = duplex;
-			atl1c_set_aspm(hw, true);
-			atl1c_enable_tx_ctrl(hw);
-			atl1c_enable_rx_ctrl(hw);
-			atl1c_setup_mac_ctrl(adapter);
-			if (netif_msg_link(adapter))
-				dev_info(&pdev->dev,
-					"%s: %s NIC Link is Up<%d Mbps %s>\n",
-					atl1c_driver_name, netdev->name,
-					adapter->link_speed,
-					adapter->link_duplex == FULL_DUPLEX ?
-					"Full Duplex" : "Half Duplex");
-		}
-		if (!netif_carrier_ok(netdev))
-			netif_carrier_on(netdev);
-	}
-}
-
-static void atl1c_link_chg_event(struct atl1c_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct pci_dev    *pdev   = adapter->pdev;
-	u16 phy_data;
-	u16 link_up;
-
-	spin_lock(&adapter->mdio_lock);
-	atl1c_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
-	atl1c_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
-	spin_unlock(&adapter->mdio_lock);
-	link_up = phy_data & BMSR_LSTATUS;
-	/* notify upper layer link down ASAP */
-	if (!link_up) {
-		if (netif_carrier_ok(netdev)) {
-			/* old link state: Up */
-			netif_carrier_off(netdev);
-			if (netif_msg_link(adapter))
-				dev_info(&pdev->dev,
-					"%s: %s NIC Link is Down\n",
-					atl1c_driver_name, netdev->name);
-			adapter->link_speed = SPEED_0;
-		}
-	}
-
-	set_bit(ATL1C_WORK_EVENT_LINK_CHANGE, &adapter->work_event);
-	schedule_work(&adapter->common_task);
-}
-
-static void atl1c_common_task(struct work_struct *work)
-{
-	struct atl1c_adapter *adapter;
-	struct net_device *netdev;
-
-	adapter = container_of(work, struct atl1c_adapter, common_task);
-	netdev = adapter->netdev;
-
-	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);
-	}
-
-	if (test_and_clear_bit(ATL1C_WORK_EVENT_LINK_CHANGE,
-		&adapter->work_event))
-		atl1c_check_link_status(adapter);
-}
-
-
-static void atl1c_del_timer(struct atl1c_adapter *adapter)
-{
-	del_timer_sync(&adapter->phy_config_timer);
-}
-
-
-/*
- * atl1c_tx_timeout - Respond to a Tx Hang
- * @netdev: network interface device structure
- */
-static void atl1c_tx_timeout(struct net_device *netdev)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-
-	/* Do the reset outside of interrupt context */
-	set_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event);
-	schedule_work(&adapter->common_task);
-}
-
-/*
- * atl1c_set_multi - Multicast and Promiscuous mode set
- * @netdev: network interface device structure
- *
- * The set_multi entry point is called whenever the multicast address
- * list or the network interface flags are updated.  This routine is
- * responsible for configuring the hardware for proper multicast,
- * promiscuous mode, and all-multi behavior.
- */
-static void atl1c_set_multi(struct net_device *netdev)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	struct atl1c_hw *hw = &adapter->hw;
-	struct netdev_hw_addr *ha;
-	u32 mac_ctrl_data;
-	u32 hash_value;
-
-	/* Check for Promiscuous and All Multicast modes */
-	AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data);
-
-	if (netdev->flags & IFF_PROMISC) {
-		mac_ctrl_data |= MAC_CTRL_PROMIS_EN;
-	} else if (netdev->flags & IFF_ALLMULTI) {
-		mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;
-		mac_ctrl_data &= ~MAC_CTRL_PROMIS_EN;
-	} else {
-		mac_ctrl_data &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
-	}
-
-	AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
-
-	/* clear the old settings from the multicast hash table */
-	AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
-	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
-
-	/* comoute mc addresses' hash value ,and put it into hash table */
-	netdev_for_each_mc_addr(ha, netdev) {
-		hash_value = atl1c_hash_mc_addr(hw, ha->addr);
-		atl1c_hash_set(hw, hash_value);
-	}
-}
-
-static void __atl1c_vlan_mode(u32 features, u32 *mac_ctrl_data)
-{
-	if (features & NETIF_F_HW_VLAN_RX) {
-		/* enable VLAN tag insert/strip */
-		*mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
-	} else {
-		/* disable VLAN tag insert/strip */
-		*mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN;
-	}
-}
-
-static void atl1c_vlan_mode(struct net_device *netdev, u32 features)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	struct pci_dev *pdev = adapter->pdev;
-	u32 mac_ctrl_data = 0;
-
-	if (netif_msg_pktdata(adapter))
-		dev_dbg(&pdev->dev, "atl1c_vlan_mode\n");
-
-	atl1c_irq_disable(adapter);
-	AT_READ_REG(&adapter->hw, REG_MAC_CTRL, &mac_ctrl_data);
-	__atl1c_vlan_mode(features, &mac_ctrl_data);
-	AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data);
-	atl1c_irq_enable(adapter);
-}
-
-static void atl1c_restore_vlan(struct atl1c_adapter *adapter)
-{
-	struct pci_dev *pdev = adapter->pdev;
-
-	if (netif_msg_pktdata(adapter))
-		dev_dbg(&pdev->dev, "atl1c_restore_vlan\n");
-	atl1c_vlan_mode(adapter->netdev, adapter->netdev->features);
-}
-
-/*
- * atl1c_set_mac - Change the Ethernet Address of the NIC
- * @netdev: network interface device structure
- * @p: pointer to an address structure
- *
- * Returns 0 on success, negative on failure
- */
-static int atl1c_set_mac_addr(struct net_device *netdev, void *p)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	struct sockaddr *addr = p;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	if (netif_running(netdev))
-		return -EBUSY;
-
-	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
-
-	atl1c_hw_set_mac_addr(&adapter->hw);
-
-	return 0;
-}
-
-static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter,
-				struct net_device *dev)
-{
-	int mtu = dev->mtu;
-
-	adapter->rx_buffer_len = mtu > AT_RX_BUF_SIZE ?
-		roundup(mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN, 8) : AT_RX_BUF_SIZE;
-}
-
-static u32 atl1c_fix_features(struct net_device *netdev, u32 features)
-{
-	/*
-	 * Since there is no support for separate rx/tx vlan accel
-	 * enable/disable make sure tx flag is always in same state as rx.
-	 */
-	if (features & NETIF_F_HW_VLAN_RX)
-		features |= NETIF_F_HW_VLAN_TX;
-	else
-		features &= ~NETIF_F_HW_VLAN_TX;
-
-	if (netdev->mtu > MAX_TSO_FRAME_SIZE)
-		features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
-
-	return features;
-}
-
-static int atl1c_set_features(struct net_device *netdev, u32 features)
-{
-	u32 changed = netdev->features ^ features;
-
-	if (changed & NETIF_F_HW_VLAN_RX)
-		atl1c_vlan_mode(netdev, features);
-
-	return 0;
-}
-
-/*
- * atl1c_change_mtu - Change the Maximum Transfer Unit
- * @netdev: network interface device structure
- * @new_mtu: new value for maximum frame size
- *
- * Returns 0 on success, negative on failure
- */
-static int atl1c_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	int old_mtu   = netdev->mtu;
-	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
-
-	if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
-			(max_frame > MAX_JUMBO_FRAME_SIZE)) {
-		if (netif_msg_link(adapter))
-			dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
-		return -EINVAL;
-	}
-	/* set MTU */
-	if (old_mtu != new_mtu && netif_running(netdev)) {
-		while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
-			msleep(1);
-		netdev->mtu = new_mtu;
-		adapter->hw.max_frame_size = new_mtu;
-		atl1c_set_rxbufsize(adapter, netdev);
-		atl1c_down(adapter);
-		netdev_update_features(netdev);
-		atl1c_up(adapter);
-		clear_bit(__AT_RESETTING, &adapter->flags);
-		if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) {
-			u32 phy_data;
-
-			AT_READ_REG(&adapter->hw, 0x1414, &phy_data);
-			phy_data |= 0x10000000;
-			AT_WRITE_REG(&adapter->hw, 0x1414, phy_data);
-		}
-
-	}
-	return 0;
-}
-
-/*
- *  caller should hold mdio_lock
- */
-static int atl1c_mdio_read(struct net_device *netdev, int phy_id, int reg_num)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	u16 result;
-
-	atl1c_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result);
-	return result;
-}
-
-static void atl1c_mdio_write(struct net_device *netdev, int phy_id,
-			     int reg_num, int val)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-
-	atl1c_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val);
-}
-
-/*
- * atl1c_mii_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- */
-static int atl1c_mii_ioctl(struct net_device *netdev,
-			   struct ifreq *ifr, int cmd)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	struct pci_dev *pdev = adapter->pdev;
-	struct mii_ioctl_data *data = if_mii(ifr);
-	unsigned long flags;
-	int retval = 0;
-
-	if (!netif_running(netdev))
-		return -EINVAL;
-
-	spin_lock_irqsave(&adapter->mdio_lock, flags);
-	switch (cmd) {
-	case SIOCGMIIPHY:
-		data->phy_id = 0;
-		break;
-
-	case SIOCGMIIREG:
-		if (atl1c_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
-				    &data->val_out)) {
-			retval = -EIO;
-			goto out;
-		}
-		break;
-
-	case SIOCSMIIREG:
-		if (data->reg_num & ~(0x1F)) {
-			retval = -EFAULT;
-			goto out;
-		}
-
-		dev_dbg(&pdev->dev, "<atl1c_mii_ioctl> write %x %x",
-				data->reg_num, data->val_in);
-		if (atl1c_write_phy_reg(&adapter->hw,
-				     data->reg_num, data->val_in)) {
-			retval = -EIO;
-			goto out;
-		}
-		break;
-
-	default:
-		retval = -EOPNOTSUPP;
-		break;
-	}
-out:
-	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
-	return retval;
-}
-
-/*
- * atl1c_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- */
-static int atl1c_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	switch (cmd) {
-	case SIOCGMIIPHY:
-	case SIOCGMIIREG:
-	case SIOCSMIIREG:
-		return atl1c_mii_ioctl(netdev, ifr, cmd);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-/*
- * atl1c_alloc_queues - Allocate memory for all rings
- * @adapter: board private structure to initialize
- *
- */
-static int __devinit atl1c_alloc_queues(struct atl1c_adapter *adapter)
-{
-	return 0;
-}
-
-static void atl1c_set_mac_type(struct atl1c_hw *hw)
-{
-	switch (hw->device_id) {
-	case PCI_DEVICE_ID_ATTANSIC_L2C:
-		hw->nic_type = athr_l2c;
-		break;
-	case PCI_DEVICE_ID_ATTANSIC_L1C:
-		hw->nic_type = athr_l1c;
-		break;
-	case PCI_DEVICE_ID_ATHEROS_L2C_B:
-		hw->nic_type = athr_l2c_b;
-		break;
-	case PCI_DEVICE_ID_ATHEROS_L2C_B2:
-		hw->nic_type = athr_l2c_b2;
-		break;
-	case PCI_DEVICE_ID_ATHEROS_L1D:
-		hw->nic_type = athr_l1d;
-		break;
-	case PCI_DEVICE_ID_ATHEROS_L1D_2_0:
-		hw->nic_type = athr_l1d_2;
-		break;
-	default:
-		break;
-	}
-}
-
-static int atl1c_setup_mac_funcs(struct atl1c_hw *hw)
-{
-	u32 phy_status_data;
-	u32 link_ctrl_data;
-
-	atl1c_set_mac_type(hw);
-	AT_READ_REG(hw, REG_PHY_STATUS, &phy_status_data);
-	AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data);
-
-	hw->ctrl_flags = ATL1C_INTR_MODRT_ENABLE  |
-			 ATL1C_TXQ_MODE_ENHANCE;
-	if (link_ctrl_data & LINK_CTRL_L0S_EN)
-		hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT;
-	if (link_ctrl_data & LINK_CTRL_L1_EN)
-		hw->ctrl_flags |= ATL1C_ASPM_L1_SUPPORT;
-	if (link_ctrl_data & LINK_CTRL_EXT_SYNC)
-		hw->ctrl_flags |= ATL1C_LINK_EXT_SYNC;
-	hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON;
-
-	if (hw->nic_type == athr_l1c ||
-	    hw->nic_type == athr_l1d ||
-	    hw->nic_type == athr_l1d_2)
-		hw->link_cap_flags |= ATL1C_LINK_CAP_1000M;
-	return 0;
-}
-/*
- * atl1c_sw_init - Initialize general software structures (struct atl1c_adapter)
- * @adapter: board private structure to initialize
- *
- * atl1c_sw_init initializes the Adapter private data structure.
- * Fields are initialized based on PCI device information and
- * OS network device settings (MTU size).
- */
-static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
-{
-	struct atl1c_hw *hw   = &adapter->hw;
-	struct pci_dev	*pdev = adapter->pdev;
-	u32 revision;
-
-
-	adapter->wol = 0;
-	device_set_wakeup_enable(&pdev->dev, false);
-	adapter->link_speed = SPEED_0;
-	adapter->link_duplex = FULL_DUPLEX;
-	adapter->num_rx_queues = AT_DEF_RECEIVE_QUEUE;
-	adapter->tpd_ring[0].count = 1024;
-	adapter->rfd_ring[0].count = 512;
-
-	hw->vendor_id = pdev->vendor;
-	hw->device_id = pdev->device;
-	hw->subsystem_vendor_id = pdev->subsystem_vendor;
-	hw->subsystem_id = pdev->subsystem_device;
-	AT_READ_REG(hw, PCI_CLASS_REVISION, &revision);
-	hw->revision_id = revision & 0xFF;
-	/* before link up, we assume hibernate is true */
-	hw->hibernate = true;
-	hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
-	if (atl1c_setup_mac_funcs(hw) != 0) {
-		dev_err(&pdev->dev, "set mac function pointers failed\n");
-		return -1;
-	}
-	hw->intr_mask = IMR_NORMAL_MASK;
-	hw->phy_configured = false;
-	hw->preamble_len = 7;
-	hw->max_frame_size = adapter->netdev->mtu;
-	if (adapter->num_rx_queues < 2) {
-		hw->rss_type = atl1c_rss_disable;
-		hw->rss_mode = atl1c_rss_mode_disable;
-	} else {
-		hw->rss_type = atl1c_rss_ipv4;
-		hw->rss_mode = atl1c_rss_mul_que_mul_int;
-		hw->rss_hash_bits = 16;
-	}
-	hw->autoneg_advertised = ADVERTISED_Autoneg;
-	hw->indirect_tab = 0xE4E4E4E4;
-	hw->base_cpu = 0;
-
-	hw->ict = 50000;		/* 100ms */
-	hw->smb_timer = 200000;	  	/* 400ms */
-	hw->cmb_tpd = 4;
-	hw->cmb_tx_timer = 1;		/* 2 us  */
-	hw->rx_imt = 200;
-	hw->tx_imt = 1000;
-
-	hw->tpd_burst = 5;
-	hw->rfd_burst = 8;
-	hw->dma_order = atl1c_dma_ord_out;
-	hw->dmar_block = atl1c_dma_req_1024;
-	hw->dmaw_block = atl1c_dma_req_1024;
-	hw->dmar_dly_cnt = 15;
-	hw->dmaw_dly_cnt = 4;
-
-	if (atl1c_alloc_queues(adapter)) {
-		dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
-		return -ENOMEM;
-	}
-	/* TODO */
-	atl1c_set_rxbufsize(adapter, adapter->netdev);
-	atomic_set(&adapter->irq_sem, 1);
-	spin_lock_init(&adapter->mdio_lock);
-	spin_lock_init(&adapter->tx_lock);
-	set_bit(__AT_DOWN, &adapter->flags);
-
-	return 0;
-}
-
-static inline void atl1c_clean_buffer(struct pci_dev *pdev,
-				struct atl1c_buffer *buffer_info, int in_irq)
-{
-	u16 pci_driection;
-	if (buffer_info->flags & ATL1C_BUFFER_FREE)
-		return;
-	if (buffer_info->dma) {
-		if (buffer_info->flags & ATL1C_PCIMAP_FROMDEVICE)
-			pci_driection = PCI_DMA_FROMDEVICE;
-		else
-			pci_driection = PCI_DMA_TODEVICE;
-
-		if (buffer_info->flags & ATL1C_PCIMAP_SINGLE)
-			pci_unmap_single(pdev, buffer_info->dma,
-					buffer_info->length, pci_driection);
-		else if (buffer_info->flags & ATL1C_PCIMAP_PAGE)
-			pci_unmap_page(pdev, buffer_info->dma,
-					buffer_info->length, pci_driection);
-	}
-	if (buffer_info->skb) {
-		if (in_irq)
-			dev_kfree_skb_irq(buffer_info->skb);
-		else
-			dev_kfree_skb(buffer_info->skb);
-	}
-	buffer_info->dma = 0;
-	buffer_info->skb = NULL;
-	ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE);
-}
-/*
- * atl1c_clean_tx_ring - Free Tx-skb
- * @adapter: board private structure
- */
-static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter,
-				enum atl1c_trans_queue type)
-{
-	struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
-	struct atl1c_buffer *buffer_info;
-	struct pci_dev *pdev = adapter->pdev;
-	u16 index, ring_count;
-
-	ring_count = tpd_ring->count;
-	for (index = 0; index < ring_count; index++) {
-		buffer_info = &tpd_ring->buffer_info[index];
-		atl1c_clean_buffer(pdev, buffer_info, 0);
-	}
-
-	/* Zero out Tx-buffers */
-	memset(tpd_ring->desc, 0, sizeof(struct atl1c_tpd_desc) *
-		ring_count);
-	atomic_set(&tpd_ring->next_to_clean, 0);
-	tpd_ring->next_to_use = 0;
-}
-
-/*
- * atl1c_clean_rx_ring - Free rx-reservation skbs
- * @adapter: board private structure
- */
-static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter)
-{
-	struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
-	struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
-	struct atl1c_buffer *buffer_info;
-	struct pci_dev *pdev = adapter->pdev;
-	int i, j;
-
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		for (j = 0; j < rfd_ring[i].count; j++) {
-			buffer_info = &rfd_ring[i].buffer_info[j];
-			atl1c_clean_buffer(pdev, buffer_info, 0);
-		}
-		/* zero out the descriptor ring */
-		memset(rfd_ring[i].desc, 0, rfd_ring[i].size);
-		rfd_ring[i].next_to_clean = 0;
-		rfd_ring[i].next_to_use = 0;
-		rrd_ring[i].next_to_use = 0;
-		rrd_ring[i].next_to_clean = 0;
-	}
-}
-
-/*
- * Read / Write Ptr Initialize:
- */
-static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter)
-{
-	struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring;
-	struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
-	struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
-	struct atl1c_buffer *buffer_info;
-	int i, j;
-
-	for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) {
-		tpd_ring[i].next_to_use = 0;
-		atomic_set(&tpd_ring[i].next_to_clean, 0);
-		buffer_info = tpd_ring[i].buffer_info;
-		for (j = 0; j < tpd_ring->count; j++)
-			ATL1C_SET_BUFFER_STATE(&buffer_info[i],
-					ATL1C_BUFFER_FREE);
-	}
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		rfd_ring[i].next_to_use = 0;
-		rfd_ring[i].next_to_clean = 0;
-		rrd_ring[i].next_to_use = 0;
-		rrd_ring[i].next_to_clean = 0;
-		for (j = 0; j < rfd_ring[i].count; j++) {
-			buffer_info = &rfd_ring[i].buffer_info[j];
-			ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE);
-		}
-	}
-}
-
-/*
- * atl1c_free_ring_resources - Free Tx / RX descriptor Resources
- * @adapter: board private structure
- *
- * Free all transmit software resources
- */
-static void atl1c_free_ring_resources(struct atl1c_adapter *adapter)
-{
-	struct pci_dev *pdev = adapter->pdev;
-
-	pci_free_consistent(pdev, adapter->ring_header.size,
-					adapter->ring_header.desc,
-					adapter->ring_header.dma);
-	adapter->ring_header.desc = NULL;
-
-	/* Note: just free tdp_ring.buffer_info,
-	*  it contain rfd_ring.buffer_info, do not double free */
-	if (adapter->tpd_ring[0].buffer_info) {
-		kfree(adapter->tpd_ring[0].buffer_info);
-		adapter->tpd_ring[0].buffer_info = NULL;
-	}
-}
-
-/*
- * atl1c_setup_mem_resources - allocate Tx / RX descriptor resources
- * @adapter: board private structure
- *
- * Return 0 on success, negative on failure
- */
-static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
-{
-	struct pci_dev *pdev = adapter->pdev;
-	struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring;
-	struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
-	struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
-	struct atl1c_ring_header *ring_header = &adapter->ring_header;
-	int num_rx_queues = adapter->num_rx_queues;
-	int size;
-	int i;
-	int count = 0;
-	int rx_desc_count = 0;
-	u32 offset = 0;
-
-	rrd_ring[0].count = rfd_ring[0].count;
-	for (i = 1; i < AT_MAX_TRANSMIT_QUEUE; i++)
-		tpd_ring[i].count = tpd_ring[0].count;
-
-	for (i = 1; i < adapter->num_rx_queues; i++)
-		rfd_ring[i].count = rrd_ring[i].count = rfd_ring[0].count;
-
-	/* 2 tpd queue, one high priority queue,
-	 * another normal priority queue */
-	size = sizeof(struct atl1c_buffer) * (tpd_ring->count * 2 +
-		rfd_ring->count * num_rx_queues);
-	tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
-	if (unlikely(!tpd_ring->buffer_info)) {
-		dev_err(&pdev->dev, "kzalloc failed, size = %d\n",
-			size);
-		goto err_nomem;
-	}
-	for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) {
-		tpd_ring[i].buffer_info =
-			(struct atl1c_buffer *) (tpd_ring->buffer_info + count);
-		count += tpd_ring[i].count;
-	}
-
-	for (i = 0; i < num_rx_queues; i++) {
-		rfd_ring[i].buffer_info =
-			(struct atl1c_buffer *) (tpd_ring->buffer_info + count);
-		count += rfd_ring[i].count;
-		rx_desc_count += rfd_ring[i].count;
-	}
-	/*
-	 * real ring DMA buffer
-	 * each ring/block may need up to 8 bytes for alignment, hence the
-	 * additional bytes tacked onto the end.
-	 */
-	ring_header->size = size =
-		sizeof(struct atl1c_tpd_desc) * tpd_ring->count * 2 +
-		sizeof(struct atl1c_rx_free_desc) * rx_desc_count +
-		sizeof(struct atl1c_recv_ret_status) * rx_desc_count +
-		sizeof(struct atl1c_hw_stats) +
-		8 * 4 + 8 * 2 * num_rx_queues;
-
-	ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
-				&ring_header->dma);
-	if (unlikely(!ring_header->desc)) {
-		dev_err(&pdev->dev, "pci_alloc_consistend failed\n");
-		goto err_nomem;
-	}
-	memset(ring_header->desc, 0, ring_header->size);
-	/* init TPD ring */
-
-	tpd_ring[0].dma = roundup(ring_header->dma, 8);
-	offset = tpd_ring[0].dma - ring_header->dma;
-	for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) {
-		tpd_ring[i].dma = ring_header->dma + offset;
-		tpd_ring[i].desc = (u8 *) ring_header->desc + offset;
-		tpd_ring[i].size =
-			sizeof(struct atl1c_tpd_desc) * tpd_ring[i].count;
-		offset += roundup(tpd_ring[i].size, 8);
-	}
-	/* init RFD ring */
-	for (i = 0; i < num_rx_queues; i++) {
-		rfd_ring[i].dma = ring_header->dma + offset;
-		rfd_ring[i].desc = (u8 *) ring_header->desc + offset;
-		rfd_ring[i].size = sizeof(struct atl1c_rx_free_desc) *
-				rfd_ring[i].count;
-		offset += roundup(rfd_ring[i].size, 8);
-	}
-
-	/* init RRD ring */
-	for (i = 0; i < num_rx_queues; i++) {
-		rrd_ring[i].dma = ring_header->dma + offset;
-		rrd_ring[i].desc = (u8 *) ring_header->desc + offset;
-		rrd_ring[i].size = sizeof(struct atl1c_recv_ret_status) *
-				rrd_ring[i].count;
-		offset += roundup(rrd_ring[i].size, 8);
-	}
-
-	adapter->smb.dma = ring_header->dma + offset;
-	adapter->smb.smb = (u8 *)ring_header->desc + offset;
-	return 0;
-
-err_nomem:
-	kfree(tpd_ring->buffer_info);
-	return -ENOMEM;
-}
-
-static void atl1c_configure_des_ring(struct atl1c_adapter *adapter)
-{
-	struct atl1c_hw *hw = &adapter->hw;
-	struct atl1c_rfd_ring *rfd_ring = (struct atl1c_rfd_ring *)
-				adapter->rfd_ring;
-	struct atl1c_rrd_ring *rrd_ring = (struct atl1c_rrd_ring *)
-				adapter->rrd_ring;
-	struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *)
-				adapter->tpd_ring;
-	struct atl1c_cmb *cmb = (struct atl1c_cmb *) &adapter->cmb;
-	struct atl1c_smb *smb = (struct atl1c_smb *) &adapter->smb;
-	int i;
-	u32 data;
-
-	/* TPD */
-	AT_WRITE_REG(hw, REG_TX_BASE_ADDR_HI,
-			(u32)((tpd_ring[atl1c_trans_normal].dma &
-				AT_DMA_HI_ADDR_MASK) >> 32));
-	/* just enable normal priority TX queue */
-	AT_WRITE_REG(hw, REG_NTPD_HEAD_ADDR_LO,
-			(u32)(tpd_ring[atl1c_trans_normal].dma &
-				AT_DMA_LO_ADDR_MASK));
-	AT_WRITE_REG(hw, REG_HTPD_HEAD_ADDR_LO,
-			(u32)(tpd_ring[atl1c_trans_high].dma &
-				AT_DMA_LO_ADDR_MASK));
-	AT_WRITE_REG(hw, REG_TPD_RING_SIZE,
-			(u32)(tpd_ring[0].count & TPD_RING_SIZE_MASK));
-
-
-	/* RFD */
-	AT_WRITE_REG(hw, REG_RX_BASE_ADDR_HI,
-			(u32)((rfd_ring[0].dma & AT_DMA_HI_ADDR_MASK) >> 32));
-	for (i = 0; i < adapter->num_rx_queues; i++)
-		AT_WRITE_REG(hw, atl1c_rfd_addr_lo_regs[i],
-			(u32)(rfd_ring[i].dma & AT_DMA_LO_ADDR_MASK));
-
-	AT_WRITE_REG(hw, REG_RFD_RING_SIZE,
-			rfd_ring[0].count & RFD_RING_SIZE_MASK);
-	AT_WRITE_REG(hw, REG_RX_BUF_SIZE,
-			adapter->rx_buffer_len & RX_BUF_SIZE_MASK);
-
-	/* RRD */
-	for (i = 0; i < adapter->num_rx_queues; i++)
-		AT_WRITE_REG(hw, atl1c_rrd_addr_lo_regs[i],
-			(u32)(rrd_ring[i].dma & AT_DMA_LO_ADDR_MASK));
-	AT_WRITE_REG(hw, REG_RRD_RING_SIZE,
-			(rrd_ring[0].count & RRD_RING_SIZE_MASK));
-
-	/* CMB */
-	AT_WRITE_REG(hw, REG_CMB_BASE_ADDR_LO, cmb->dma & AT_DMA_LO_ADDR_MASK);
-
-	/* SMB */
-	AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_HI,
-			(u32)((smb->dma & AT_DMA_HI_ADDR_MASK) >> 32));
-	AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_LO,
-			(u32)(smb->dma & AT_DMA_LO_ADDR_MASK));
-	if (hw->nic_type == athr_l2c_b) {
-		AT_WRITE_REG(hw, REG_SRAM_RXF_LEN, 0x02a0L);
-		AT_WRITE_REG(hw, REG_SRAM_TXF_LEN, 0x0100L);
-		AT_WRITE_REG(hw, REG_SRAM_RXF_ADDR, 0x029f0000L);
-		AT_WRITE_REG(hw, REG_SRAM_RFD0_INFO, 0x02bf02a0L);
-		AT_WRITE_REG(hw, REG_SRAM_TXF_ADDR, 0x03bf02c0L);
-		AT_WRITE_REG(hw, REG_SRAM_TRD_ADDR, 0x03df03c0L);
-		AT_WRITE_REG(hw, REG_TXF_WATER_MARK, 0);	/* TX watermark, to enter l1 state.*/
-		AT_WRITE_REG(hw, REG_RXD_DMA_CTRL, 0);		/* RXD threshold.*/
-	}
-	if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d_2) {
-			/* Power Saving for L2c_B */
-		AT_READ_REG(hw, REG_SERDES_LOCK, &data);
-		data |= SERDES_MAC_CLK_SLOWDOWN;
-		data |= SERDES_PYH_CLK_SLOWDOWN;
-		AT_WRITE_REG(hw, REG_SERDES_LOCK, data);
-	}
-	/* Load all of base address above */
-	AT_WRITE_REG(hw, REG_LOAD_PTR, 1);
-}
-
-static void atl1c_configure_tx(struct atl1c_adapter *adapter)
-{
-	struct atl1c_hw *hw = &adapter->hw;
-	u32 dev_ctrl_data;
-	u32 max_pay_load;
-	u16 tx_offload_thresh;
-	u32 txq_ctrl_data;
-	u32 max_pay_load_data;
-
-	tx_offload_thresh = MAX_TX_OFFLOAD_THRESH;
-	AT_WRITE_REG(hw, REG_TX_TSO_OFFLOAD_THRESH,
-		(tx_offload_thresh >> 3) & TX_TSO_OFFLOAD_THRESH_MASK);
-	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_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_t(u32, max_pay_load, hw->dmar_block);
-
-	txq_ctrl_data = (hw->tpd_burst & TXQ_NUM_TPD_BURST_MASK) <<
-			TXQ_NUM_TPD_BURST_SHIFT;
-	if (hw->ctrl_flags & ATL1C_TXQ_MODE_ENHANCE)
-		txq_ctrl_data |= TXQ_CTRL_ENH_MODE;
-	max_pay_load_data = (atl1c_pay_load_size[hw->dmar_block] &
-			TXQ_TXF_BURST_NUM_MASK) << TXQ_TXF_BURST_NUM_SHIFT;
-	if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2)
-		max_pay_load_data >>= 1;
-	txq_ctrl_data |= max_pay_load_data;
-
-	AT_WRITE_REG(hw, REG_TXQ_CTRL, txq_ctrl_data);
-}
-
-static void atl1c_configure_rx(struct atl1c_adapter *adapter)
-{
-	struct atl1c_hw *hw = &adapter->hw;
-	u32 rxq_ctrl_data;
-
-	rxq_ctrl_data = (hw->rfd_burst & RXQ_RFD_BURST_NUM_MASK) <<
-			RXQ_RFD_BURST_NUM_SHIFT;
-
-	if (hw->ctrl_flags & ATL1C_RX_IPV6_CHKSUM)
-		rxq_ctrl_data |= IPV6_CHKSUM_CTRL_EN;
-	if (hw->rss_type == atl1c_rss_ipv4)
-		rxq_ctrl_data |= RSS_HASH_IPV4;
-	if (hw->rss_type == atl1c_rss_ipv4_tcp)
-		rxq_ctrl_data |= RSS_HASH_IPV4_TCP;
-	if (hw->rss_type == atl1c_rss_ipv6)
-		rxq_ctrl_data |= RSS_HASH_IPV6;
-	if (hw->rss_type == atl1c_rss_ipv6_tcp)
-		rxq_ctrl_data |= RSS_HASH_IPV6_TCP;
-	if (hw->rss_type != atl1c_rss_disable)
-		rxq_ctrl_data |= RRS_HASH_CTRL_EN;
-
-	rxq_ctrl_data |= (hw->rss_mode & RSS_MODE_MASK) <<
-			RSS_MODE_SHIFT;
-	rxq_ctrl_data |= (hw->rss_hash_bits & RSS_HASH_BITS_MASK) <<
-			RSS_HASH_BITS_SHIFT;
-	if (hw->ctrl_flags & ATL1C_ASPM_CTRL_MON)
-		rxq_ctrl_data |= (ASPM_THRUPUT_LIMIT_1M &
-			ASPM_THRUPUT_LIMIT_MASK) << ASPM_THRUPUT_LIMIT_SHIFT;
-
-	AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data);
-}
-
-static void atl1c_configure_rss(struct atl1c_adapter *adapter)
-{
-	struct atl1c_hw *hw = &adapter->hw;
-
-	AT_WRITE_REG(hw, REG_IDT_TABLE, hw->indirect_tab);
-	AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, hw->base_cpu);
-}
-
-static void atl1c_configure_dma(struct atl1c_adapter *adapter)
-{
-	struct atl1c_hw *hw = &adapter->hw;
-	u32 dma_ctrl_data;
-
-	dma_ctrl_data = DMA_CTRL_DMAR_REQ_PRI;
-	if (hw->ctrl_flags & ATL1C_CMB_ENABLE)
-		dma_ctrl_data |= DMA_CTRL_CMB_EN;
-	if (hw->ctrl_flags & ATL1C_SMB_ENABLE)
-		dma_ctrl_data |= DMA_CTRL_SMB_EN;
-	else
-		dma_ctrl_data |= MAC_CTRL_SMB_DIS;
-
-	switch (hw->dma_order) {
-	case atl1c_dma_ord_in:
-		dma_ctrl_data |= DMA_CTRL_DMAR_IN_ORDER;
-		break;
-	case atl1c_dma_ord_enh:
-		dma_ctrl_data |= DMA_CTRL_DMAR_ENH_ORDER;
-		break;
-	case atl1c_dma_ord_out:
-		dma_ctrl_data |= DMA_CTRL_DMAR_OUT_ORDER;
-		break;
-	default:
-		break;
-	}
-
-	dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
-		<< DMA_CTRL_DMAR_BURST_LEN_SHIFT;
-	dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
-		<< DMA_CTRL_DMAW_BURST_LEN_SHIFT;
-	dma_ctrl_data |= (((u32)hw->dmar_dly_cnt) & DMA_CTRL_DMAR_DLY_CNT_MASK)
-		<< DMA_CTRL_DMAR_DLY_CNT_SHIFT;
-	dma_ctrl_data |= (((u32)hw->dmaw_dly_cnt) & DMA_CTRL_DMAW_DLY_CNT_MASK)
-		<< DMA_CTRL_DMAW_DLY_CNT_SHIFT;
-
-	AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data);
-}
-
-/*
- * Stop the mac, transmit and receive units
- * hw - Struct containing variables accessed by shared code
- * return : 0  or  idle status (if error)
- */
-static int atl1c_stop_mac(struct atl1c_hw *hw)
-{
-	u32 data;
-
-	AT_READ_REG(hw, REG_RXQ_CTRL, &data);
-	data &= ~(RXQ1_CTRL_EN | RXQ2_CTRL_EN |
-		  RXQ3_CTRL_EN | RXQ_CTRL_EN);
-	AT_WRITE_REG(hw, REG_RXQ_CTRL, data);
-
-	AT_READ_REG(hw, REG_TXQ_CTRL, &data);
-	data &= ~TXQ_CTRL_EN;
-	AT_WRITE_REG(hw, REG_TWSI_CTRL, data);
-
-	atl1c_wait_until_idle(hw);
-
-	AT_READ_REG(hw, REG_MAC_CTRL, &data);
-	data &= ~(MAC_CTRL_TX_EN | MAC_CTRL_RX_EN);
-	AT_WRITE_REG(hw, REG_MAC_CTRL, data);
-
-	return (int)atl1c_wait_until_idle(hw);
-}
-
-static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw)
-{
-	u32 data;
-
-	AT_READ_REG(hw, REG_RXQ_CTRL, &data);
-	switch (hw->adapter->num_rx_queues) {
-	case 4:
-		data |= (RXQ3_CTRL_EN | RXQ2_CTRL_EN | RXQ1_CTRL_EN);
-		break;
-	case 3:
-		data |= (RXQ2_CTRL_EN | RXQ1_CTRL_EN);
-		break;
-	case 2:
-		data |= RXQ1_CTRL_EN;
-		break;
-	default:
-		break;
-	}
-	data |= RXQ_CTRL_EN;
-	AT_WRITE_REG(hw, REG_RXQ_CTRL, data);
-}
-
-static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw)
-{
-	u32 data;
-
-	AT_READ_REG(hw, REG_TXQ_CTRL, &data);
-	data |= TXQ_CTRL_EN;
-	AT_WRITE_REG(hw, REG_TXQ_CTRL, data);
-}
-
-/*
- * Reset the transmit and receive units; mask and clear all interrupts.
- * hw - Struct containing variables accessed by shared code
- * return : 0  or  idle status (if error)
- */
-static int atl1c_reset_mac(struct atl1c_hw *hw)
-{
-	struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
-	struct pci_dev *pdev = adapter->pdev;
-	u32 master_ctrl_data = 0;
-
-	AT_WRITE_REG(hw, REG_IMR, 0);
-	AT_WRITE_REG(hw, REG_ISR, ISR_DIS_INT);
-
-	atl1c_stop_mac(hw);
-	/*
-	 * Issue Soft Reset to the MAC.  This will reset the chip's
-	 * transmit, receive, DMA.  It will not effect
-	 * the current PCI configuration.  The global reset bit is self-
-	 * clearing, and should clear within a microsecond.
-	 */
-	AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
-	master_ctrl_data |= MASTER_CTRL_OOB_DIS_OFF;
-	AT_WRITE_REGW(hw, REG_MASTER_CTRL, ((master_ctrl_data | MASTER_CTRL_SOFT_RST)
-			& 0xFFFF));
-
-	AT_WRITE_FLUSH(hw);
-	msleep(10);
-	/* Wait at least 10ms for All module to be Idle */
-
-	if (atl1c_wait_until_idle(hw)) {
-		dev_err(&pdev->dev,
-			"MAC state machine can't be idle since"
-			" disabled for 10ms second\n");
-		return -1;
-	}
-	return 0;
-}
-
-static void atl1c_disable_l0s_l1(struct atl1c_hw *hw)
-{
-	u32 pm_ctrl_data;
-
-	AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data);
-	pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
-			PM_CTRL_L1_ENTRY_TIMER_SHIFT);
-	pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1;
-	pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
-	pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
-	pm_ctrl_data &= ~PM_CTRL_MAC_ASPM_CHK;
-	pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1;
-
-	pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN;
-	pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN;
-	pm_ctrl_data |=	PM_CTRL_SERDES_L1_EN;
-	AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data);
-}
-
-/*
- * Set ASPM state.
- * Enable/disable L0s/L1 depend on link state.
- */
-static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup)
-{
-	u32 pm_ctrl_data;
-	u32 link_ctrl_data;
-	u32 link_l1_timer = 0xF;
-
-	AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data);
-	AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data);
-
-	pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1;
-	pm_ctrl_data &=  ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
-			PM_CTRL_L1_ENTRY_TIMER_SHIFT);
-	pm_ctrl_data &= ~(PM_CTRL_LCKDET_TIMER_MASK <<
-			PM_CTRL_LCKDET_TIMER_SHIFT);
-	pm_ctrl_data |= AT_LCKDET_TIMER	<< PM_CTRL_LCKDET_TIMER_SHIFT;
-
-	if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d ||
-		hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) {
-		link_ctrl_data &= ~LINK_CTRL_EXT_SYNC;
-		if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) {
-			if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10)
-				link_ctrl_data |= LINK_CTRL_EXT_SYNC;
-		}
-
-		AT_WRITE_REG(hw, REG_LINK_CTRL, link_ctrl_data);
-
-		pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER;
-		pm_ctrl_data &= ~(PM_CTRL_PM_REQ_TIMER_MASK <<
-			PM_CTRL_PM_REQ_TIMER_SHIFT);
-		pm_ctrl_data |= AT_ASPM_L1_TIMER <<
-			PM_CTRL_PM_REQ_TIMER_SHIFT;
-		pm_ctrl_data &= ~PM_CTRL_SA_DLY_EN;
-		pm_ctrl_data &= ~PM_CTRL_HOTRST;
-		pm_ctrl_data |= 1 << PM_CTRL_L1_ENTRY_TIMER_SHIFT;
-		pm_ctrl_data |= PM_CTRL_SERDES_PD_EX_L1;
-	}
-	pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK;
-	if (linkup) {
-		pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
-		pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
-		if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT)
-			pm_ctrl_data |= PM_CTRL_ASPM_L1_EN;
-		if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT)
-			pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN;
-
-		if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d ||
-			hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) {
-			if (hw->nic_type == athr_l2c_b)
-				if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE))
-					pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
-			pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN;
-			pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN;
-			pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN;
-			pm_ctrl_data |= PM_CTRL_CLK_SWH_L1;
-		if (hw->adapter->link_speed == SPEED_100 ||
-				hw->adapter->link_speed == SPEED_1000) {
-				pm_ctrl_data &=  ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
-					PM_CTRL_L1_ENTRY_TIMER_SHIFT);
-				if (hw->nic_type == athr_l2c_b)
-					link_l1_timer = 7;
-				else if (hw->nic_type == athr_l2c_b2 ||
-					hw->nic_type == athr_l1d_2)
-					link_l1_timer = 4;
-				pm_ctrl_data |= link_l1_timer <<
-					PM_CTRL_L1_ENTRY_TIMER_SHIFT;
-			}
-		} else {
-			pm_ctrl_data |= PM_CTRL_SERDES_L1_EN;
-			pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN;
-			pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN;
-			pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1;
-			pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
-			pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
-
-		}
-	} else {
-		pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN;
-		pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
-		pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN;
-		pm_ctrl_data |= PM_CTRL_CLK_SWH_L1;
-
-		if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT)
-			pm_ctrl_data |= PM_CTRL_ASPM_L1_EN;
-		else
-			pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
-	}
-	AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data);
-
-	return;
-}
-
-static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter)
-{
-	struct atl1c_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	u32 mac_ctrl_data;
-
-	mac_ctrl_data = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
-	mac_ctrl_data |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
-
-	if (adapter->link_duplex == FULL_DUPLEX) {
-		hw->mac_duplex = true;
-		mac_ctrl_data |= MAC_CTRL_DUPLX;
-	}
-
-	if (adapter->link_speed == SPEED_1000)
-		hw->mac_speed = atl1c_mac_speed_1000;
-	else
-		hw->mac_speed = atl1c_mac_speed_10_100;
-
-	mac_ctrl_data |= (hw->mac_speed & MAC_CTRL_SPEED_MASK) <<
-			MAC_CTRL_SPEED_SHIFT;
-
-	mac_ctrl_data |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
-	mac_ctrl_data |= ((hw->preamble_len & MAC_CTRL_PRMLEN_MASK) <<
-			MAC_CTRL_PRMLEN_SHIFT);
-
-	__atl1c_vlan_mode(netdev->features, &mac_ctrl_data);
-
-	mac_ctrl_data |= MAC_CTRL_BC_EN;
-	if (netdev->flags & IFF_PROMISC)
-		mac_ctrl_data |= MAC_CTRL_PROMIS_EN;
-	if (netdev->flags & IFF_ALLMULTI)
-		mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;
-
-	mac_ctrl_data |= MAC_CTRL_SINGLE_PAUSE_EN;
-	if (hw->nic_type == athr_l1d || hw->nic_type == athr_l2c_b2 ||
-	    hw->nic_type == athr_l1d_2) {
-		mac_ctrl_data |= MAC_CTRL_SPEED_MODE_SW;
-		mac_ctrl_data |= MAC_CTRL_HASH_ALG_CRC32;
-	}
-	AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
-}
-
-/*
- * atl1c_configure - Configure Transmit&Receive Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Tx /Rx unit of the MAC after a reset.
- */
-static int atl1c_configure(struct atl1c_adapter *adapter)
-{
-	struct atl1c_hw *hw = &adapter->hw;
-	u32 master_ctrl_data = 0;
-	u32 intr_modrt_data;
-	u32 data;
-
-	/* clear interrupt status */
-	AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF);
-	/*  Clear any WOL status */
-	AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
-	/* set Interrupt Clear Timer
-	 * HW will enable self to assert interrupt event to system after
-	 * waiting x-time for software to notify it accept interrupt.
-	 */
-
-	data = CLK_GATING_EN_ALL;
-	if (hw->ctrl_flags & ATL1C_CLK_GATING_EN) {
-		if (hw->nic_type == athr_l2c_b)
-			data &= ~CLK_GATING_RXMAC_EN;
-	} else
-		data = 0;
-	AT_WRITE_REG(hw, REG_CLK_GATING_CTRL, data);
-
-	AT_WRITE_REG(hw, REG_INT_RETRIG_TIMER,
-		hw->ict & INT_RETRIG_TIMER_MASK);
-
-	atl1c_configure_des_ring(adapter);
-
-	if (hw->ctrl_flags & ATL1C_INTR_MODRT_ENABLE) {
-		intr_modrt_data = (hw->tx_imt & IRQ_MODRT_TIMER_MASK) <<
-					IRQ_MODRT_TX_TIMER_SHIFT;
-		intr_modrt_data |= (hw->rx_imt & IRQ_MODRT_TIMER_MASK) <<
-					IRQ_MODRT_RX_TIMER_SHIFT;
-		AT_WRITE_REG(hw, REG_IRQ_MODRT_TIMER_INIT, intr_modrt_data);
-		master_ctrl_data |=
-			MASTER_CTRL_TX_ITIMER_EN | MASTER_CTRL_RX_ITIMER_EN;
-	}
-
-	if (hw->ctrl_flags & ATL1C_INTR_CLEAR_ON_READ)
-		master_ctrl_data |= MASTER_CTRL_INT_RDCLR;
-
-	master_ctrl_data |= MASTER_CTRL_SA_TIMER_EN;
-	AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
-
-	if (hw->ctrl_flags & ATL1C_CMB_ENABLE) {
-		AT_WRITE_REG(hw, REG_CMB_TPD_THRESH,
-			hw->cmb_tpd & CMB_TPD_THRESH_MASK);
-		AT_WRITE_REG(hw, REG_CMB_TX_TIMER,
-			hw->cmb_tx_timer & CMB_TX_TIMER_MASK);
-	}
-
-	if (hw->ctrl_flags & ATL1C_SMB_ENABLE)
-		AT_WRITE_REG(hw, REG_SMB_STAT_TIMER,
-			hw->smb_timer & SMB_STAT_TIMER_MASK);
-	/* set MTU */
-	AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN +
-			VLAN_HLEN + ETH_FCS_LEN);
-	/* HDS, disable */
-	AT_WRITE_REG(hw, REG_HDS_CTRL, 0);
-
-	atl1c_configure_tx(adapter);
-	atl1c_configure_rx(adapter);
-	atl1c_configure_rss(adapter);
-	atl1c_configure_dma(adapter);
-
-	return 0;
-}
-
-static void atl1c_update_hw_stats(struct atl1c_adapter *adapter)
-{
-	u16 hw_reg_addr = 0;
-	unsigned long *stats_item = NULL;
-	u32 data;
-
-	/* update rx status */
-	hw_reg_addr = REG_MAC_RX_STATUS_BIN;
-	stats_item  = &adapter->hw_stats.rx_ok;
-	while (hw_reg_addr <= REG_MAC_RX_STATUS_END) {
-		AT_READ_REG(&adapter->hw, hw_reg_addr, &data);
-		*stats_item += data;
-		stats_item++;
-		hw_reg_addr += 4;
-	}
-/* update tx status */
-	hw_reg_addr = REG_MAC_TX_STATUS_BIN;
-	stats_item  = &adapter->hw_stats.tx_ok;
-	while (hw_reg_addr <= REG_MAC_TX_STATUS_END) {
-		AT_READ_REG(&adapter->hw, hw_reg_addr, &data);
-		*stats_item += data;
-		stats_item++;
-		hw_reg_addr += 4;
-	}
-}
-
-/*
- * atl1c_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- *
- * Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
- */
-static struct net_device_stats *atl1c_get_stats(struct net_device *netdev)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	struct atl1c_hw_stats  *hw_stats = &adapter->hw_stats;
-	struct net_device_stats *net_stats = &netdev->stats;
-
-	atl1c_update_hw_stats(adapter);
-	net_stats->rx_packets = hw_stats->rx_ok;
-	net_stats->tx_packets = hw_stats->tx_ok;
-	net_stats->rx_bytes   = hw_stats->rx_byte_cnt;
-	net_stats->tx_bytes   = hw_stats->tx_byte_cnt;
-	net_stats->multicast  = hw_stats->rx_mcast;
-	net_stats->collisions = hw_stats->tx_1_col +
-				hw_stats->tx_2_col * 2 +
-				hw_stats->tx_late_col + hw_stats->tx_abort_col;
-	net_stats->rx_errors  = hw_stats->rx_frag + hw_stats->rx_fcs_err +
-				hw_stats->rx_len_err + hw_stats->rx_sz_ov +
-				hw_stats->rx_rrd_ov + hw_stats->rx_align_err;
-	net_stats->rx_fifo_errors   = hw_stats->rx_rxf_ov;
-	net_stats->rx_length_errors = hw_stats->rx_len_err;
-	net_stats->rx_crc_errors    = hw_stats->rx_fcs_err;
-	net_stats->rx_frame_errors  = hw_stats->rx_align_err;
-	net_stats->rx_over_errors   = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov;
-
-	net_stats->rx_missed_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov;
-
-	net_stats->tx_errors = hw_stats->tx_late_col + hw_stats->tx_abort_col +
-				hw_stats->tx_underrun + hw_stats->tx_trunc;
-	net_stats->tx_fifo_errors    = hw_stats->tx_underrun;
-	net_stats->tx_aborted_errors = hw_stats->tx_abort_col;
-	net_stats->tx_window_errors  = hw_stats->tx_late_col;
-
-	return net_stats;
-}
-
-static inline void atl1c_clear_phy_int(struct atl1c_adapter *adapter)
-{
-	u16 phy_data;
-
-	spin_lock(&adapter->mdio_lock);
-	atl1c_read_phy_reg(&adapter->hw, MII_ISR, &phy_data);
-	spin_unlock(&adapter->mdio_lock);
-}
-
-static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter,
-				enum atl1c_trans_queue type)
-{
-	struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *)
-				&adapter->tpd_ring[type];
-	struct atl1c_buffer *buffer_info;
-	struct pci_dev *pdev = adapter->pdev;
-	u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
-	u16 hw_next_to_clean;
-	u16 shift;
-	u32 data;
-
-	if (type == atl1c_trans_high)
-		shift = MB_HTPD_CONS_IDX_SHIFT;
-	else
-		shift = MB_NTPD_CONS_IDX_SHIFT;
-
-	AT_READ_REG(&adapter->hw, REG_MB_PRIO_CONS_IDX, &data);
-	hw_next_to_clean = (data >> shift) & MB_PRIO_PROD_IDX_MASK;
-
-	while (next_to_clean != hw_next_to_clean) {
-		buffer_info = &tpd_ring->buffer_info[next_to_clean];
-		atl1c_clean_buffer(pdev, buffer_info, 1);
-		if (++next_to_clean == tpd_ring->count)
-			next_to_clean = 0;
-		atomic_set(&tpd_ring->next_to_clean, next_to_clean);
-	}
-
-	if (netif_queue_stopped(adapter->netdev) &&
-			netif_carrier_ok(adapter->netdev)) {
-		netif_wake_queue(adapter->netdev);
-	}
-
-	return true;
-}
-
-/*
- * atl1c_intr - Interrupt Handler
- * @irq: interrupt number
- * @data: pointer to a network interface device structure
- * @pt_regs: CPU registers structure
- */
-static irqreturn_t atl1c_intr(int irq, void *data)
-{
-	struct net_device *netdev  = data;
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	struct pci_dev *pdev = adapter->pdev;
-	struct atl1c_hw *hw = &adapter->hw;
-	int max_ints = AT_MAX_INT_WORK;
-	int handled = IRQ_NONE;
-	u32 status;
-	u32 reg_data;
-
-	do {
-		AT_READ_REG(hw, REG_ISR, &reg_data);
-		status = reg_data & hw->intr_mask;
-
-		if (status == 0 || (status & ISR_DIS_INT) != 0) {
-			if (max_ints != AT_MAX_INT_WORK)
-				handled = IRQ_HANDLED;
-			break;
-		}
-		/* link event */
-		if (status & ISR_GPHY)
-			atl1c_clear_phy_int(adapter);
-		/* Ack ISR */
-		AT_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT);
-		if (status & ISR_RX_PKT) {
-			if (likely(napi_schedule_prep(&adapter->napi))) {
-				hw->intr_mask &= ~ISR_RX_PKT;
-				AT_WRITE_REG(hw, REG_IMR, hw->intr_mask);
-				__napi_schedule(&adapter->napi);
-			}
-		}
-		if (status & ISR_TX_PKT)
-			atl1c_clean_tx_irq(adapter, atl1c_trans_normal);
-
-		handled = IRQ_HANDLED;
-		/* check if PCIE PHY Link down */
-		if (status & ISR_ERROR) {
-			if (netif_msg_hw(adapter))
-				dev_err(&pdev->dev,
-					"atl1c hardware error (status = 0x%x)\n",
-					status & ISR_ERROR);
-			/* reset MAC */
-			adapter->work_event |= ATL1C_WORK_EVENT_RESET;
-			schedule_work(&adapter->common_task);
-			return IRQ_HANDLED;
-		}
-
-		if (status & ISR_OVER)
-			if (netif_msg_intr(adapter))
-				dev_warn(&pdev->dev,
-					"TX/RX overflow (status = 0x%x)\n",
-					status & ISR_OVER);
-
-		/* link event */
-		if (status & (ISR_GPHY | ISR_MANUAL)) {
-			netdev->stats.tx_carrier_errors++;
-			atl1c_link_chg_event(adapter);
-			break;
-		}
-
-	} while (--max_ints > 0);
-	/* re-enable Interrupt*/
-	AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
-	return handled;
-}
-
-static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter,
-		  struct sk_buff *skb, struct atl1c_recv_ret_status *prrs)
-{
-	/*
-	 * The pid field in RRS in not correct sometimes, so we
-	 * cannot figure out if the packet is fragmented or not,
-	 * so we tell the KERNEL CHECKSUM_NONE
-	 */
-	skb_checksum_none_assert(skb);
-}
-
-static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid)
-{
-	struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[ringid];
-	struct pci_dev *pdev = adapter->pdev;
-	struct atl1c_buffer *buffer_info, *next_info;
-	struct sk_buff *skb;
-	void *vir_addr = NULL;
-	u16 num_alloc = 0;
-	u16 rfd_next_to_use, next_next;
-	struct atl1c_rx_free_desc *rfd_desc;
-
-	next_next = rfd_next_to_use = rfd_ring->next_to_use;
-	if (++next_next == rfd_ring->count)
-		next_next = 0;
-	buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
-	next_info = &rfd_ring->buffer_info[next_next];
-
-	while (next_info->flags & ATL1C_BUFFER_FREE) {
-		rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use);
-
-		skb = dev_alloc_skb(adapter->rx_buffer_len);
-		if (unlikely(!skb)) {
-			if (netif_msg_rx_err(adapter))
-				dev_warn(&pdev->dev, "alloc rx buffer failed\n");
-			break;
-		}
-
-		/*
-		 * Make buffer alignment 2 beyond a 16 byte boundary
-		 * this will result in a 16 byte aligned IP header after
-		 * the 14 byte MAC header is removed
-		 */
-		vir_addr = skb->data;
-		ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
-		buffer_info->skb = skb;
-		buffer_info->length = adapter->rx_buffer_len;
-		buffer_info->dma = pci_map_single(pdev, vir_addr,
-						buffer_info->length,
-						PCI_DMA_FROMDEVICE);
-		ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
-			ATL1C_PCIMAP_FROMDEVICE);
-		rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
-		rfd_next_to_use = next_next;
-		if (++next_next == rfd_ring->count)
-			next_next = 0;
-		buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
-		next_info = &rfd_ring->buffer_info[next_next];
-		num_alloc++;
-	}
-
-	if (num_alloc) {
-		/* TODO: update mailbox here */
-		wmb();
-		rfd_ring->next_to_use = rfd_next_to_use;
-		AT_WRITE_REG(&adapter->hw, atl1c_rfd_prod_idx_regs[ringid],
-			rfd_ring->next_to_use & MB_RFDX_PROD_IDX_MASK);
-	}
-
-	return num_alloc;
-}
-
-static void atl1c_clean_rrd(struct atl1c_rrd_ring *rrd_ring,
-			struct	atl1c_recv_ret_status *rrs, u16 num)
-{
-	u16 i;
-	/* the relationship between rrd and rfd is one map one */
-	for (i = 0; i < num; i++, rrs = ATL1C_RRD_DESC(rrd_ring,
-					rrd_ring->next_to_clean)) {
-		rrs->word3 &= ~RRS_RXD_UPDATED;
-		if (++rrd_ring->next_to_clean == rrd_ring->count)
-			rrd_ring->next_to_clean = 0;
-	}
-}
-
-static void atl1c_clean_rfd(struct atl1c_rfd_ring *rfd_ring,
-	struct atl1c_recv_ret_status *rrs, u16 num)
-{
-	u16 i;
-	u16 rfd_index;
-	struct atl1c_buffer *buffer_info = rfd_ring->buffer_info;
-
-	rfd_index = (rrs->word0 >> RRS_RX_RFD_INDEX_SHIFT) &
-			RRS_RX_RFD_INDEX_MASK;
-	for (i = 0; i < num; i++) {
-		buffer_info[rfd_index].skb = NULL;
-		ATL1C_SET_BUFFER_STATE(&buffer_info[rfd_index],
-					ATL1C_BUFFER_FREE);
-		if (++rfd_index == rfd_ring->count)
-			rfd_index = 0;
-	}
-	rfd_ring->next_to_clean = rfd_index;
-}
-
-static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que,
-		   int *work_done, int work_to_do)
-{
-	u16 rfd_num, rfd_index;
-	u16 count = 0;
-	u16 length;
-	struct pci_dev *pdev = adapter->pdev;
-	struct net_device *netdev  = adapter->netdev;
-	struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[que];
-	struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring[que];
-	struct sk_buff *skb;
-	struct atl1c_recv_ret_status *rrs;
-	struct atl1c_buffer *buffer_info;
-
-	while (1) {
-		if (*work_done >= work_to_do)
-			break;
-		rrs = ATL1C_RRD_DESC(rrd_ring, rrd_ring->next_to_clean);
-		if (likely(RRS_RXD_IS_VALID(rrs->word3))) {
-			rfd_num = (rrs->word0 >> RRS_RX_RFD_CNT_SHIFT) &
-				RRS_RX_RFD_CNT_MASK;
-			if (unlikely(rfd_num != 1))
-				/* TODO support mul rfd*/
-				if (netif_msg_rx_err(adapter))
-					dev_warn(&pdev->dev,
-						"Multi rfd not support yet!\n");
-			goto rrs_checked;
-		} else {
-			break;
-		}
-rrs_checked:
-		atl1c_clean_rrd(rrd_ring, rrs, rfd_num);
-		if (rrs->word3 & (RRS_RX_ERR_SUM | RRS_802_3_LEN_ERR)) {
-			atl1c_clean_rfd(rfd_ring, rrs, rfd_num);
-				if (netif_msg_rx_err(adapter))
-					dev_warn(&pdev->dev,
-						"wrong packet! rrs word3 is %x\n",
-						rrs->word3);
-			continue;
-		}
-
-		length = le16_to_cpu((rrs->word3 >> RRS_PKT_SIZE_SHIFT) &
-				RRS_PKT_SIZE_MASK);
-		/* Good Receive */
-		if (likely(rfd_num == 1)) {
-			rfd_index = (rrs->word0 >> RRS_RX_RFD_INDEX_SHIFT) &
-					RRS_RX_RFD_INDEX_MASK;
-			buffer_info = &rfd_ring->buffer_info[rfd_index];
-			pci_unmap_single(pdev, buffer_info->dma,
-				buffer_info->length, PCI_DMA_FROMDEVICE);
-			skb = buffer_info->skb;
-		} else {
-			/* TODO */
-			if (netif_msg_rx_err(adapter))
-				dev_warn(&pdev->dev,
-					"Multi rfd not support yet!\n");
-			break;
-		}
-		atl1c_clean_rfd(rfd_ring, rrs, rfd_num);
-		skb_put(skb, length - ETH_FCS_LEN);
-		skb->protocol = eth_type_trans(skb, netdev);
-		atl1c_rx_checksum(adapter, skb, rrs);
-		if (rrs->word3 & RRS_VLAN_INS) {
-			u16 vlan;
-
-			AT_TAG_TO_VLAN(rrs->vlan_tag, vlan);
-			vlan = le16_to_cpu(vlan);
-			__vlan_hwaccel_put_tag(skb, vlan);
-		}
-		netif_receive_skb(skb);
-
-		(*work_done)++;
-		count++;
-	}
-	if (count)
-		atl1c_alloc_rx_buffer(adapter, que);
-}
-
-/*
- * atl1c_clean - NAPI Rx polling callback
- * @adapter: board private structure
- */
-static int atl1c_clean(struct napi_struct *napi, int budget)
-{
-	struct atl1c_adapter *adapter =
-			container_of(napi, struct atl1c_adapter, napi);
-	int work_done = 0;
-
-	/* Keep link state information with original netdev */
-	if (!netif_carrier_ok(adapter->netdev))
-		goto quit_polling;
-	/* just enable one RXQ */
-	atl1c_clean_rx_irq(adapter, 0, &work_done, budget);
-
-	if (work_done < budget) {
-quit_polling:
-		napi_complete(napi);
-		adapter->hw.intr_mask |= ISR_RX_PKT;
-		AT_WRITE_REG(&adapter->hw, REG_IMR, adapter->hw.intr_mask);
-	}
-	return work_done;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-
-/*
- * Polling 'interrupt' - used by things like netconsole to send skbs
- * without having to re-enable interrupts. It's not called while
- * the interrupt routine is executing.
- */
-static void atl1c_netpoll(struct net_device *netdev)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-
-	disable_irq(adapter->pdev->irq);
-	atl1c_intr(adapter->pdev->irq, netdev);
-	enable_irq(adapter->pdev->irq);
-}
-#endif
-
-static inline u16 atl1c_tpd_avail(struct atl1c_adapter *adapter, enum atl1c_trans_queue type)
-{
-	struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
-	u16 next_to_use = 0;
-	u16 next_to_clean = 0;
-
-	next_to_clean = atomic_read(&tpd_ring->next_to_clean);
-	next_to_use   = tpd_ring->next_to_use;
-
-	return (u16)(next_to_clean > next_to_use) ?
-		(next_to_clean - next_to_use - 1) :
-		(tpd_ring->count + next_to_clean - next_to_use - 1);
-}
-
-/*
- * get next usable tpd
- * Note: should call atl1c_tdp_avail to make sure
- * there is enough tpd to use
- */
-static struct atl1c_tpd_desc *atl1c_get_tpd(struct atl1c_adapter *adapter,
-	enum atl1c_trans_queue type)
-{
-	struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
-	struct atl1c_tpd_desc *tpd_desc;
-	u16 next_to_use = 0;
-
-	next_to_use = tpd_ring->next_to_use;
-	if (++tpd_ring->next_to_use == tpd_ring->count)
-		tpd_ring->next_to_use = 0;
-	tpd_desc = ATL1C_TPD_DESC(tpd_ring, next_to_use);
-	memset(tpd_desc, 0, sizeof(struct atl1c_tpd_desc));
-	return	tpd_desc;
-}
-
-static struct atl1c_buffer *
-atl1c_get_tx_buffer(struct atl1c_adapter *adapter, struct atl1c_tpd_desc *tpd)
-{
-	struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring;
-
-	return &tpd_ring->buffer_info[tpd -
-			(struct atl1c_tpd_desc *)tpd_ring->desc];
-}
-
-/* Calculate the transmit packet descript needed*/
-static u16 atl1c_cal_tpd_req(const struct sk_buff *skb)
-{
-	u16 tpd_req;
-	u16 proto_hdr_len = 0;
-
-	tpd_req = skb_shinfo(skb)->nr_frags + 1;
-
-	if (skb_is_gso(skb)) {
-		proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-		if (proto_hdr_len < skb_headlen(skb))
-			tpd_req++;
-		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
-			tpd_req++;
-	}
-	return tpd_req;
-}
-
-static int atl1c_tso_csum(struct atl1c_adapter *adapter,
-			  struct sk_buff *skb,
-			  struct atl1c_tpd_desc **tpd,
-			  enum atl1c_trans_queue type)
-{
-	struct pci_dev *pdev = adapter->pdev;
-	u8 hdr_len;
-	u32 real_len;
-	unsigned short offload_type;
-	int err;
-
-	if (skb_is_gso(skb)) {
-		if (skb_header_cloned(skb)) {
-			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
-			if (unlikely(err))
-				return -1;
-		}
-		offload_type = skb_shinfo(skb)->gso_type;
-
-		if (offload_type & SKB_GSO_TCPV4) {
-			real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
-					+ ntohs(ip_hdr(skb)->tot_len));
-
-			if (real_len < skb->len)
-				pskb_trim(skb, real_len);
-
-			hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
-			if (unlikely(skb->len == hdr_len)) {
-				/* only xsum need */
-				if (netif_msg_tx_queued(adapter))
-					dev_warn(&pdev->dev,
-						"IPV4 tso with zero data??\n");
-				goto check_sum;
-			} else {
-				ip_hdr(skb)->check = 0;
-				tcp_hdr(skb)->check = ~csum_tcpudp_magic(
-							ip_hdr(skb)->saddr,
-							ip_hdr(skb)->daddr,
-							0, IPPROTO_TCP, 0);
-				(*tpd)->word1 |= 1 << TPD_IPV4_PACKET_SHIFT;
-			}
-		}
-
-		if (offload_type & SKB_GSO_TCPV6) {
-			struct atl1c_tpd_ext_desc *etpd =
-				*(struct atl1c_tpd_ext_desc **)(tpd);
-
-			memset(etpd, 0, sizeof(struct atl1c_tpd_ext_desc));
-			*tpd = atl1c_get_tpd(adapter, type);
-			ipv6_hdr(skb)->payload_len = 0;
-			/* check payload == 0 byte ? */
-			hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
-			if (unlikely(skb->len == hdr_len)) {
-				/* only xsum need */
-				if (netif_msg_tx_queued(adapter))
-					dev_warn(&pdev->dev,
-						"IPV6 tso with zero data??\n");
-				goto check_sum;
-			} else
-				tcp_hdr(skb)->check = ~csum_ipv6_magic(
-						&ipv6_hdr(skb)->saddr,
-						&ipv6_hdr(skb)->daddr,
-						0, IPPROTO_TCP, 0);
-			etpd->word1 |= 1 << TPD_LSO_EN_SHIFT;
-			etpd->word1 |= 1 << TPD_LSO_VER_SHIFT;
-			etpd->pkt_len = cpu_to_le32(skb->len);
-			(*tpd)->word1 |= 1 << TPD_LSO_VER_SHIFT;
-		}
-
-		(*tpd)->word1 |= 1 << TPD_LSO_EN_SHIFT;
-		(*tpd)->word1 |= (skb_transport_offset(skb) & TPD_TCPHDR_OFFSET_MASK) <<
-				TPD_TCPHDR_OFFSET_SHIFT;
-		(*tpd)->word1 |= (skb_shinfo(skb)->gso_size & TPD_MSS_MASK) <<
-				TPD_MSS_SHIFT;
-		return 0;
-	}
-
-check_sum:
-	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
-		u8 css, cso;
-		cso = skb_checksum_start_offset(skb);
-
-		if (unlikely(cso & 0x1)) {
-			if (netif_msg_tx_err(adapter))
-				dev_err(&adapter->pdev->dev,
-					"payload offset should not an event number\n");
-			return -1;
-		} else {
-			css = cso + skb->csum_offset;
-
-			(*tpd)->word1 |= ((cso >> 1) & TPD_PLOADOFFSET_MASK) <<
-					TPD_PLOADOFFSET_SHIFT;
-			(*tpd)->word1 |= ((css >> 1) & TPD_CCSUM_OFFSET_MASK) <<
-					TPD_CCSUM_OFFSET_SHIFT;
-			(*tpd)->word1 |= 1 << TPD_CCSUM_EN_SHIFT;
-		}
-	}
-	return 0;
-}
-
-static void atl1c_tx_map(struct atl1c_adapter *adapter,
-		      struct sk_buff *skb, struct atl1c_tpd_desc *tpd,
-			enum atl1c_trans_queue type)
-{
-	struct atl1c_tpd_desc *use_tpd = NULL;
-	struct atl1c_buffer *buffer_info = NULL;
-	u16 buf_len = skb_headlen(skb);
-	u16 map_len = 0;
-	u16 mapped_len = 0;
-	u16 hdr_len = 0;
-	u16 nr_frags;
-	u16 f;
-	int tso;
-
-	nr_frags = skb_shinfo(skb)->nr_frags;
-	tso = (tpd->word1 >> TPD_LSO_EN_SHIFT) & TPD_LSO_EN_MASK;
-	if (tso) {
-		/* TSO */
-		map_len = hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-		use_tpd = tpd;
-
-		buffer_info = atl1c_get_tx_buffer(adapter, use_tpd);
-		buffer_info->length = map_len;
-		buffer_info->dma = pci_map_single(adapter->pdev,
-					skb->data, hdr_len, PCI_DMA_TODEVICE);
-		ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
-		ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
-			ATL1C_PCIMAP_TODEVICE);
-		mapped_len += map_len;
-		use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
-		use_tpd->buffer_len = cpu_to_le16(buffer_info->length);
-	}
-
-	if (mapped_len < buf_len) {
-		/* mapped_len == 0, means we should use the first tpd,
-		   which is given by caller  */
-		if (mapped_len == 0)
-			use_tpd = tpd;
-		else {
-			use_tpd = atl1c_get_tpd(adapter, type);
-			memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc));
-		}
-		buffer_info = atl1c_get_tx_buffer(adapter, use_tpd);
-		buffer_info->length = buf_len - mapped_len;
-		buffer_info->dma =
-			pci_map_single(adapter->pdev, skb->data + mapped_len,
-					buffer_info->length, PCI_DMA_TODEVICE);
-		ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
-		ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
-			ATL1C_PCIMAP_TODEVICE);
-		use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
-		use_tpd->buffer_len  = cpu_to_le16(buffer_info->length);
-	}
-
-	for (f = 0; f < nr_frags; f++) {
-		struct skb_frag_struct *frag;
-
-		frag = &skb_shinfo(skb)->frags[f];
-
-		use_tpd = atl1c_get_tpd(adapter, type);
-		memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc));
-
-		buffer_info = atl1c_get_tx_buffer(adapter, use_tpd);
-		buffer_info->length = frag->size;
-		buffer_info->dma =
-			pci_map_page(adapter->pdev, frag->page,
-					frag->page_offset,
-					buffer_info->length,
-					PCI_DMA_TODEVICE);
-		ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
-		ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE,
-			ATL1C_PCIMAP_TODEVICE);
-		use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
-		use_tpd->buffer_len  = cpu_to_le16(buffer_info->length);
-	}
-
-	/* The last tpd */
-	use_tpd->word1 |= 1 << TPD_EOP_SHIFT;
-	/* The last buffer info contain the skb address,
-	   so it will be free after unmap */
-	buffer_info->skb = skb;
-}
-
-static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb,
-			   struct atl1c_tpd_desc *tpd, enum atl1c_trans_queue type)
-{
-	struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
-	u32 prod_data;
-
-	AT_READ_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, &prod_data);
-	switch (type) {
-	case atl1c_trans_high:
-		prod_data &= 0xFFFF0000;
-		prod_data |= tpd_ring->next_to_use & 0xFFFF;
-		break;
-	case atl1c_trans_normal:
-		prod_data &= 0x0000FFFF;
-		prod_data |= (tpd_ring->next_to_use & 0xFFFF) << 16;
-		break;
-	default:
-		break;
-	}
-	wmb();
-	AT_WRITE_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, prod_data);
-}
-
-static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb,
-					  struct net_device *netdev)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	unsigned long flags;
-	u16 tpd_req = 1;
-	struct atl1c_tpd_desc *tpd;
-	enum atl1c_trans_queue type = atl1c_trans_normal;
-
-	if (test_bit(__AT_DOWN, &adapter->flags)) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	tpd_req = atl1c_cal_tpd_req(skb);
-	if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) {
-		if (netif_msg_pktdata(adapter))
-			dev_info(&adapter->pdev->dev, "tx locked\n");
-		return NETDEV_TX_LOCKED;
-	}
-	if (skb->mark == 0x01)
-		type = atl1c_trans_high;
-	else
-		type = atl1c_trans_normal;
-
-	if (atl1c_tpd_avail(adapter, type) < tpd_req) {
-		/* no enough descriptor, just stop queue */
-		netif_stop_queue(netdev);
-		spin_unlock_irqrestore(&adapter->tx_lock, flags);
-		return NETDEV_TX_BUSY;
-	}
-
-	tpd = atl1c_get_tpd(adapter, type);
-
-	/* do TSO and check sum */
-	if (atl1c_tso_csum(adapter, skb, &tpd, type) != 0) {
-		spin_unlock_irqrestore(&adapter->tx_lock, flags);
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	if (unlikely(vlan_tx_tag_present(skb))) {
-		u16 vlan = vlan_tx_tag_get(skb);
-		__le16 tag;
-
-		vlan = cpu_to_le16(vlan);
-		AT_VLAN_TO_TAG(vlan, tag);
-		tpd->word1 |= 1 << TPD_INS_VTAG_SHIFT;
-		tpd->vlan_tag = tag;
-	}
-
-	if (skb_network_offset(skb) != ETH_HLEN)
-		tpd->word1 |= 1 << TPD_ETH_TYPE_SHIFT; /* Ethernet frame */
-
-	atl1c_tx_map(adapter, skb, tpd, type);
-	atl1c_tx_queue(adapter, skb, tpd, type);
-
-	spin_unlock_irqrestore(&adapter->tx_lock, flags);
-	return NETDEV_TX_OK;
-}
-
-static void atl1c_free_irq(struct atl1c_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-
-	free_irq(adapter->pdev->irq, netdev);
-
-	if (adapter->have_msi)
-		pci_disable_msi(adapter->pdev);
-}
-
-static int atl1c_request_irq(struct atl1c_adapter *adapter)
-{
-	struct pci_dev    *pdev   = adapter->pdev;
-	struct net_device *netdev = adapter->netdev;
-	int flags = 0;
-	int err = 0;
-
-	adapter->have_msi = true;
-	err = pci_enable_msi(adapter->pdev);
-	if (err) {
-		if (netif_msg_ifup(adapter))
-			dev_err(&pdev->dev,
-				"Unable to allocate MSI interrupt Error: %d\n",
-				err);
-		adapter->have_msi = false;
-	} else
-		netdev->irq = pdev->irq;
-
-	if (!adapter->have_msi)
-		flags |= IRQF_SHARED;
-	err = request_irq(adapter->pdev->irq, atl1c_intr, flags,
-			netdev->name, netdev);
-	if (err) {
-		if (netif_msg_ifup(adapter))
-			dev_err(&pdev->dev,
-				"Unable to allocate interrupt Error: %d\n",
-				err);
-		if (adapter->have_msi)
-			pci_disable_msi(adapter->pdev);
-		return err;
-	}
-	if (netif_msg_ifup(adapter))
-		dev_dbg(&pdev->dev, "atl1c_request_irq OK\n");
-	return err;
-}
-
-static int atl1c_up(struct atl1c_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	int num;
-	int err;
-	int i;
-
-	netif_carrier_off(netdev);
-	atl1c_init_ring_ptrs(adapter);
-	atl1c_set_multi(netdev);
-	atl1c_restore_vlan(adapter);
-
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		num = atl1c_alloc_rx_buffer(adapter, i);
-		if (unlikely(num == 0)) {
-			err = -ENOMEM;
-			goto err_alloc_rx;
-		}
-	}
-
-	if (atl1c_configure(adapter)) {
-		err = -EIO;
-		goto err_up;
-	}
-
-	err = atl1c_request_irq(adapter);
-	if (unlikely(err))
-		goto err_up;
-
-	clear_bit(__AT_DOWN, &adapter->flags);
-	napi_enable(&adapter->napi);
-	atl1c_irq_enable(adapter);
-	atl1c_check_link_status(adapter);
-	netif_start_queue(netdev);
-	return err;
-
-err_up:
-err_alloc_rx:
-	atl1c_clean_rx_ring(adapter);
-	return err;
-}
-
-static void atl1c_down(struct atl1c_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-
-	atl1c_del_timer(adapter);
-	adapter->work_event = 0; /* clear all event */
-	/* signal that we're down so the interrupt handler does not
-	 * reschedule our watchdog timer */
-	set_bit(__AT_DOWN, &adapter->flags);
-	netif_carrier_off(netdev);
-	napi_disable(&adapter->napi);
-	atl1c_irq_disable(adapter);
-	atl1c_free_irq(adapter);
-	/* reset MAC to disable all RX/TX */
-	atl1c_reset_mac(&adapter->hw);
-	msleep(1);
-
-	adapter->link_speed = SPEED_0;
-	adapter->link_duplex = -1;
-	atl1c_clean_tx_ring(adapter, atl1c_trans_normal);
-	atl1c_clean_tx_ring(adapter, atl1c_trans_high);
-	atl1c_clean_rx_ring(adapter);
-}
-
-/*
- * atl1c_open - Called when a network interface is made active
- * @netdev: network interface device structure
- *
- * Returns 0 on success, negative value on failure
- *
- * 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.
- */
-static int atl1c_open(struct net_device *netdev)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	int err;
-
-	/* disallow open during test */
-	if (test_bit(__AT_TESTING, &adapter->flags))
-		return -EBUSY;
-
-	/* allocate rx/tx dma buffer & descriptors */
-	err = atl1c_setup_ring_resources(adapter);
-	if (unlikely(err))
-		return err;
-
-	err = atl1c_up(adapter);
-	if (unlikely(err))
-		goto err_up;
-
-	if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) {
-		u32 phy_data;
-
-		AT_READ_REG(&adapter->hw, REG_MDIO_CTRL, &phy_data);
-		phy_data |= MDIO_AP_EN;
-		AT_WRITE_REG(&adapter->hw, REG_MDIO_CTRL, phy_data);
-	}
-	return 0;
-
-err_up:
-	atl1c_free_irq(adapter);
-	atl1c_free_ring_resources(adapter);
-	atl1c_reset_mac(&adapter->hw);
-	return err;
-}
-
-/*
- * atl1c_close - Disables a network interface
- * @netdev: network interface device structure
- *
- * 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.
- */
-static int atl1c_close(struct net_device *netdev)
-{
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-
-	WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
-	atl1c_down(adapter);
-	atl1c_free_ring_resources(adapter);
-	return 0;
-}
-
-static int atl1c_suspend(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	struct atl1c_hw *hw = &adapter->hw;
-	u32 mac_ctrl_data = 0;
-	u32 master_ctrl_data = 0;
-	u32 wol_ctrl_data = 0;
-	u16 mii_intr_status_data = 0;
-	u32 wufc = adapter->wol;
-
-	atl1c_disable_l0s_l1(hw);
-	if (netif_running(netdev)) {
-		WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
-		atl1c_down(adapter);
-	}
-	netif_device_detach(netdev);
-
-	if (wufc)
-		if (atl1c_phy_power_saving(hw) != 0)
-			dev_dbg(&pdev->dev, "phy power saving failed");
-
-	AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
-	AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data);
-
-	master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS;
-	mac_ctrl_data &= ~(MAC_CTRL_PRMLEN_MASK << MAC_CTRL_PRMLEN_SHIFT);
-	mac_ctrl_data |= (((u32)adapter->hw.preamble_len &
-			MAC_CTRL_PRMLEN_MASK) <<
-			MAC_CTRL_PRMLEN_SHIFT);
-	mac_ctrl_data &= ~(MAC_CTRL_SPEED_MASK << MAC_CTRL_SPEED_SHIFT);
-	mac_ctrl_data &= ~MAC_CTRL_DUPLX;
-
-	if (wufc) {
-		mac_ctrl_data |= MAC_CTRL_RX_EN;
-		if (adapter->link_speed == SPEED_1000 ||
-			adapter->link_speed == SPEED_0) {
-			mac_ctrl_data |= atl1c_mac_speed_1000 <<
-					MAC_CTRL_SPEED_SHIFT;
-			mac_ctrl_data |= MAC_CTRL_DUPLX;
-		} else
-			mac_ctrl_data |= atl1c_mac_speed_10_100 <<
-					MAC_CTRL_SPEED_SHIFT;
-
-		if (adapter->link_duplex == DUPLEX_FULL)
-			mac_ctrl_data |= MAC_CTRL_DUPLX;
-
-		/* turn on magic packet wol */
-		if (wufc & AT_WUFC_MAG)
-			wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
-
-		if (wufc & AT_WUFC_LNKC) {
-			wol_ctrl_data |=  WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
-			/* only link up can wake up */
-			if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) {
-				dev_dbg(&pdev->dev, "%s: read write phy "
-						  "register failed.\n",
-						  atl1c_driver_name);
-			}
-		}
-		/* clear phy interrupt */
-		atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data);
-		/* Config MAC Ctrl register */
-		__atl1c_vlan_mode(netdev->features, &mac_ctrl_data);
-
-		/* magic packet maybe Broadcast&multicast&Unicast frame */
-		if (wufc & AT_WUFC_MAG)
-			mac_ctrl_data |= MAC_CTRL_BC_EN;
-
-		dev_dbg(&pdev->dev,
-			"%s: suspend MAC=0x%x\n",
-			atl1c_driver_name, mac_ctrl_data);
-		AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
-		AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);
-		AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
-
-		AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |
-			GPHY_CTRL_EXT_RESET);
-	} else {
-		AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_POWER_SAVING);
-		master_ctrl_data |= MASTER_CTRL_CLK_SEL_DIS;
-		mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT;
-		mac_ctrl_data |= MAC_CTRL_DUPLX;
-		AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
-		AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
-		AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
-		hw->phy_configured = false; /* re-init PHY when resume */
-	}
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int atl1c_resume(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-
-	AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
-	atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE |
-			ATL1C_PCIE_PHY_RESET);
-
-	atl1c_phy_reset(&adapter->hw);
-	atl1c_reset_mac(&adapter->hw);
-	atl1c_phy_init(&adapter->hw);
-
-#if 0
-	AT_READ_REG(&adapter->hw, REG_PM_CTRLSTAT, &pm_data);
-	pm_data &= ~PM_CTRLSTAT_PME_EN;
-	AT_WRITE_REG(&adapter->hw, REG_PM_CTRLSTAT, pm_data);
-#endif
-
-	netif_device_attach(netdev);
-	if (netif_running(netdev))
-		atl1c_up(adapter);
-
-	return 0;
-}
-#endif
-
-static void atl1c_shutdown(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-
-	atl1c_suspend(&pdev->dev);
-	pci_wake_from_d3(pdev, adapter->wol);
-	pci_set_power_state(pdev, PCI_D3hot);
-}
-
-static const struct net_device_ops atl1c_netdev_ops = {
-	.ndo_open		= atl1c_open,
-	.ndo_stop		= atl1c_close,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_start_xmit		= atl1c_xmit_frame,
-	.ndo_set_mac_address	= atl1c_set_mac_addr,
-	.ndo_set_multicast_list = atl1c_set_multi,
-	.ndo_change_mtu		= atl1c_change_mtu,
-	.ndo_fix_features	= atl1c_fix_features,
-	.ndo_set_features	= atl1c_set_features,
-	.ndo_do_ioctl		= atl1c_ioctl,
-	.ndo_tx_timeout		= atl1c_tx_timeout,
-	.ndo_get_stats		= atl1c_get_stats,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= atl1c_netpoll,
-#endif
-};
-
-static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
-{
-	SET_NETDEV_DEV(netdev, &pdev->dev);
-	pci_set_drvdata(pdev, netdev);
-
-	netdev->irq  = pdev->irq;
-	netdev->netdev_ops = &atl1c_netdev_ops;
-	netdev->watchdog_timeo = AT_TX_WATCHDOG;
-	atl1c_set_ethtool_ops(netdev);
-
-	/* TODO: add when ready */
-	netdev->hw_features =	NETIF_F_SG	   |
-				NETIF_F_HW_CSUM	   |
-				NETIF_F_HW_VLAN_RX |
-				NETIF_F_TSO	   |
-				NETIF_F_TSO6;
-	netdev->features =	netdev->hw_features |
-				NETIF_F_HW_VLAN_TX;
-	return 0;
-}
-
-/*
- * atl1c_probe - Device Initialization Routine
- * @pdev: PCI device information struct
- * @ent: entry in atl1c_pci_tbl
- *
- * Returns 0 on success, negative on failure
- *
- * atl1c_probe initializes an adapter identified by a pci_dev structure.
- * The OS initialization, configuring of the adapter private structure,
- * and a hardware reset occur.
- */
-static int __devinit atl1c_probe(struct pci_dev *pdev,
-				 const struct pci_device_id *ent)
-{
-	struct net_device *netdev;
-	struct atl1c_adapter *adapter;
-	static int cards_found;
-
-	int err = 0;
-
-	/* enable device (incl. PCI PM wakeup and hotplug setup) */
-	err = pci_enable_device_mem(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "cannot enable PCI device\n");
-		return err;
-	}
-
-	/*
-	 * The atl1c chip can DMA to 64-bit addresses, but it uses a single
-	 * shared register for the high 32 bits, so only a single, aligned,
-	 * 4 GB physical address range can be used at a time.
-	 *
-	 * Supporting 64-bit DMA on this hardware is more trouble than it's
-	 * worth.  It is far easier to limit to 32-bit DMA than update
-	 * various kernel subsystems to support the mechanics required by a
-	 * fixed-high-32-bit system.
-	 */
-	if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) ||
-	    (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)) {
-		dev_err(&pdev->dev, "No usable DMA configuration,aborting\n");
-		goto err_dma;
-	}
-
-	err = pci_request_regions(pdev, atl1c_driver_name);
-	if (err) {
-		dev_err(&pdev->dev, "cannot obtain PCI resources\n");
-		goto err_pci_reg;
-	}
-
-	pci_set_master(pdev);
-
-	netdev = alloc_etherdev(sizeof(struct atl1c_adapter));
-	if (netdev == NULL) {
-		err = -ENOMEM;
-		dev_err(&pdev->dev, "etherdev alloc failed\n");
-		goto err_alloc_etherdev;
-	}
-
-	err = atl1c_init_netdev(netdev, pdev);
-	if (err) {
-		dev_err(&pdev->dev, "init netdevice failed\n");
-		goto err_init_netdev;
-	}
-	adapter = netdev_priv(netdev);
-	adapter->bd_number = cards_found;
-	adapter->netdev = netdev;
-	adapter->pdev = pdev;
-	adapter->hw.adapter = adapter;
-	adapter->msg_enable = netif_msg_init(-1, atl1c_default_msg);
-	adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
-	if (!adapter->hw.hw_addr) {
-		err = -EIO;
-		dev_err(&pdev->dev, "cannot map device registers\n");
-		goto err_ioremap;
-	}
-	netdev->base_addr = (unsigned long)adapter->hw.hw_addr;
-
-	/* init mii data */
-	adapter->mii.dev = netdev;
-	adapter->mii.mdio_read  = atl1c_mdio_read;
-	adapter->mii.mdio_write = atl1c_mdio_write;
-	adapter->mii.phy_id_mask = 0x1f;
-	adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK;
-	netif_napi_add(netdev, &adapter->napi, atl1c_clean, 64);
-	setup_timer(&adapter->phy_config_timer, atl1c_phy_config,
-			(unsigned long)adapter);
-	/* setup the private structure */
-	err = atl1c_sw_init(adapter);
-	if (err) {
-		dev_err(&pdev->dev, "net device private data init failed\n");
-		goto err_sw_init;
-	}
-	atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE |
-			ATL1C_PCIE_PHY_RESET);
-
-	/* Init GPHY as early as possible due to power saving issue  */
-	atl1c_phy_reset(&adapter->hw);
-
-	err = atl1c_reset_mac(&adapter->hw);
-	if (err) {
-		err = -EIO;
-		goto err_reset;
-	}
-
-	/* reset the controller to
-	 * put the device in a known good starting state */
-	err = atl1c_phy_init(&adapter->hw);
-	if (err) {
-		err = -EIO;
-		goto err_reset;
-	}
-	if (atl1c_read_mac_addr(&adapter->hw) != 0) {
-		err = -EIO;
-		dev_err(&pdev->dev, "get mac address failed\n");
-		goto err_eeprom;
-	}
-	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
-	memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
-	if (netif_msg_probe(adapter))
-		dev_dbg(&pdev->dev, "mac address : %pM\n",
-			adapter->hw.mac_addr);
-
-	atl1c_hw_set_mac_addr(&adapter->hw);
-	INIT_WORK(&adapter->common_task, atl1c_common_task);
-	adapter->work_event = 0;
-	err = register_netdev(netdev);
-	if (err) {
-		dev_err(&pdev->dev, "register netdevice failed\n");
-		goto err_register;
-	}
-
-	if (netif_msg_probe(adapter))
-		dev_info(&pdev->dev, "version %s\n", ATL1C_DRV_VERSION);
-	cards_found++;
-	return 0;
-
-err_reset:
-err_register:
-err_sw_init:
-err_eeprom:
-	iounmap(adapter->hw.hw_addr);
-err_init_netdev:
-err_ioremap:
-	free_netdev(netdev);
-err_alloc_etherdev:
-	pci_release_regions(pdev);
-err_pci_reg:
-err_dma:
-	pci_disable_device(pdev);
-	return err;
-}
-
-/*
- * atl1c_remove - Device Removal Routine
- * @pdev: PCI device information struct
- *
- * atl1c_remove is called by the PCI subsystem to alert the driver
- * that it should release a PCI device.  The could be caused by a
- * Hot-Plug event, or because the driver is going to be removed from
- * memory.
- */
-static void __devexit atl1c_remove(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-
-	unregister_netdev(netdev);
-	atl1c_phy_disable(&adapter->hw);
-
-	iounmap(adapter->hw.hw_addr);
-
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	free_netdev(netdev);
-}
-
-/*
- * atl1c_io_error_detected - called when PCI error is detected
- * @pdev: Pointer to PCI device
- * @state: The current pci connection state
- *
- * This function is called after a PCI bus error affecting
- * this device has been detected.
- */
-static pci_ers_result_t atl1c_io_error_detected(struct pci_dev *pdev,
-						pci_channel_state_t state)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-
-	netif_device_detach(netdev);
-
-	if (state == pci_channel_io_perm_failure)
-		return PCI_ERS_RESULT_DISCONNECT;
-
-	if (netif_running(netdev))
-		atl1c_down(adapter);
-
-	pci_disable_device(pdev);
-
-	/* Request a slot slot reset. */
-	return PCI_ERS_RESULT_NEED_RESET;
-}
-
-/*
- * atl1c_io_slot_reset - called after the pci bus has been reset.
- * @pdev: Pointer to PCI device
- *
- * Restart the card from scratch, as if from a cold-boot. Implementation
- * resembles the first-half of the e1000_resume routine.
- */
-static pci_ers_result_t atl1c_io_slot_reset(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-
-	if (pci_enable_device(pdev)) {
-		if (netif_msg_hw(adapter))
-			dev_err(&pdev->dev,
-				"Cannot re-enable PCI device after reset\n");
-		return PCI_ERS_RESULT_DISCONNECT;
-	}
-	pci_set_master(pdev);
-
-	pci_enable_wake(pdev, PCI_D3hot, 0);
-	pci_enable_wake(pdev, PCI_D3cold, 0);
-
-	atl1c_reset_mac(&adapter->hw);
-
-	return PCI_ERS_RESULT_RECOVERED;
-}
-
-/*
- * atl1c_io_resume - called when traffic can start flowing again.
- * @pdev: Pointer to PCI device
- *
- * This callback is called when the error recovery driver tells us that
- * its OK to resume normal operation. Implementation resembles the
- * second-half of the atl1c_resume routine.
- */
-static void atl1c_io_resume(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1c_adapter *adapter = netdev_priv(netdev);
-
-	if (netif_running(netdev)) {
-		if (atl1c_up(adapter)) {
-			if (netif_msg_hw(adapter))
-				dev_err(&pdev->dev,
-					"Cannot bring device back up after reset\n");
-			return;
-		}
-	}
-
-	netif_device_attach(netdev);
-}
-
-static struct pci_error_handlers atl1c_err_handler = {
-	.error_detected = atl1c_io_error_detected,
-	.slot_reset = atl1c_io_slot_reset,
-	.resume = atl1c_io_resume,
-};
-
-static SIMPLE_DEV_PM_OPS(atl1c_pm_ops, atl1c_suspend, atl1c_resume);
-
-static struct pci_driver atl1c_driver = {
-	.name     = atl1c_driver_name,
-	.id_table = atl1c_pci_tbl,
-	.probe    = atl1c_probe,
-	.remove   = __devexit_p(atl1c_remove),
-	.shutdown = atl1c_shutdown,
-	.err_handler = &atl1c_err_handler,
-	.driver.pm = &atl1c_pm_ops,
-};
-
-/*
- * atl1c_init_module - Driver Registration Routine
- *
- * atl1c_init_module is the first routine called when the driver is
- * loaded. All it does is register with the PCI subsystem.
- */
-static int __init atl1c_init_module(void)
-{
-	return pci_register_driver(&atl1c_driver);
-}
-
-/*
- * atl1c_exit_module - Driver Exit Cleanup Routine
- *
- * atl1c_exit_module is called just before the driver is removed
- * from memory.
- */
-static void __exit atl1c_exit_module(void)
-{
-	pci_unregister_driver(&atl1c_driver);
-}
-
-module_init(atl1c_init_module);
-module_exit(atl1c_exit_module);
diff -druN linux-libre-3.1-gnu/drivers/net/atl1c/Makefile linux-libre-3.2-gnu/drivers/net/atl1c/Makefile
--- linux-libre-3.1-gnu/drivers/net/atl1c/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atl1c/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,2 +0,0 @@
-obj-$(CONFIG_ATL1C) += atl1c.o
-atl1c-objs := atl1c_main.o atl1c_hw.o atl1c_ethtool.o
diff -druN linux-libre-3.1-gnu/drivers/net/atl1e/atl1e_ethtool.c linux-libre-3.2-gnu/drivers/net/atl1e/atl1e_ethtool.c
--- linux-libre-3.1-gnu/drivers/net/atl1e/atl1e_ethtool.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atl1e/atl1e_ethtool.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,390 +0,0 @@
-/*
- * Copyright(c) 2007 Atheros Corporation. All rights reserved.
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You 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/netdevice.h>
-#include <linux/ethtool.h>
-#include <linux/slab.h>
-
-#include "atl1e.h"
-
-static int atl1e_get_settings(struct net_device *netdev,
-			      struct ethtool_cmd *ecmd)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	struct atl1e_hw *hw = &adapter->hw;
-
-	ecmd->supported = (SUPPORTED_10baseT_Half  |
-			   SUPPORTED_10baseT_Full  |
-			   SUPPORTED_100baseT_Half |
-			   SUPPORTED_100baseT_Full |
-			   SUPPORTED_Autoneg       |
-			   SUPPORTED_TP);
-	if (hw->nic_type == athr_l1e)
-		ecmd->supported |= SUPPORTED_1000baseT_Full;
-
-	ecmd->advertising = ADVERTISED_TP;
-
-	ecmd->advertising |= ADVERTISED_Autoneg;
-	ecmd->advertising |= hw->autoneg_advertised;
-
-	ecmd->port = PORT_TP;
-	ecmd->phy_address = 0;
-	ecmd->transceiver = XCVR_INTERNAL;
-
-	if (adapter->link_speed != SPEED_0) {
-		ethtool_cmd_speed_set(ecmd, adapter->link_speed);
-		if (adapter->link_duplex == FULL_DUPLEX)
-			ecmd->duplex = DUPLEX_FULL;
-		else
-			ecmd->duplex = DUPLEX_HALF;
-	} else {
-		ethtool_cmd_speed_set(ecmd, -1);
-		ecmd->duplex = -1;
-	}
-
-	ecmd->autoneg = AUTONEG_ENABLE;
-	return 0;
-}
-
-static int atl1e_set_settings(struct net_device *netdev,
-			      struct ethtool_cmd *ecmd)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	struct atl1e_hw *hw = &adapter->hw;
-
-	while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
-		msleep(1);
-
-	if (ecmd->autoneg == AUTONEG_ENABLE) {
-		u16 adv4, adv9;
-
-		if ((ecmd->advertising&ADVERTISE_1000_FULL)) {
-			if (hw->nic_type == athr_l1e) {
-				hw->autoneg_advertised =
-					ecmd->advertising & AT_ADV_MASK;
-			} else {
-				clear_bit(__AT_RESETTING, &adapter->flags);
-				return -EINVAL;
-			}
-		} else if (ecmd->advertising&ADVERTISE_1000_HALF) {
-			clear_bit(__AT_RESETTING, &adapter->flags);
-			return -EINVAL;
-		} else {
-			hw->autoneg_advertised =
-				ecmd->advertising & AT_ADV_MASK;
-		}
-		ecmd->advertising = hw->autoneg_advertised |
-				    ADVERTISED_TP | ADVERTISED_Autoneg;
-
-		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 |= ADVERTISE_10HALF;
-		if (hw->autoneg_advertised & ADVERTISE_10_FULL)
-			adv4 |= ADVERTISE_10FULL;
-		if (hw->autoneg_advertised & ADVERTISE_100_HALF)
-			adv4 |= ADVERTISE_100HALF;
-		if (hw->autoneg_advertised & ADVERTISE_100_FULL)
-			adv4 |= ADVERTISE_100FULL;
-		if (hw->autoneg_advertised & ADVERTISE_1000_FULL)
-			adv9 |= ADVERTISE_1000FULL;
-
-		if (adv4 != hw->mii_autoneg_adv_reg ||
-				adv9 != hw->mii_1000t_ctrl_reg) {
-			hw->mii_autoneg_adv_reg = adv4;
-			hw->mii_1000t_ctrl_reg = adv9;
-			hw->re_autoneg = true;
-		}
-
-	} else {
-		clear_bit(__AT_RESETTING, &adapter->flags);
-		return -EINVAL;
-	}
-
-	/* reset the link */
-
-	if (netif_running(adapter->netdev)) {
-		atl1e_down(adapter);
-		atl1e_up(adapter);
-	} else
-		atl1e_reset_hw(&adapter->hw);
-
-	clear_bit(__AT_RESETTING, &adapter->flags);
-	return 0;
-}
-
-static u32 atl1e_get_msglevel(struct net_device *netdev)
-{
-#ifdef DBG
-	return 1;
-#else
-	return 0;
-#endif
-}
-
-static int atl1e_get_regs_len(struct net_device *netdev)
-{
-	return AT_REGS_LEN * sizeof(u32);
-}
-
-static void atl1e_get_regs(struct net_device *netdev,
-			   struct ethtool_regs *regs, void *p)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	struct atl1e_hw *hw = &adapter->hw;
-	u32 *regs_buff = p;
-	u16 phy_data;
-
-	memset(p, 0, AT_REGS_LEN * sizeof(u32));
-
-	regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
-
-	regs_buff[0]  = AT_READ_REG(hw, REG_VPD_CAP);
-	regs_buff[1]  = AT_READ_REG(hw, REG_SPI_FLASH_CTRL);
-	regs_buff[2]  = AT_READ_REG(hw, REG_SPI_FLASH_CONFIG);
-	regs_buff[3]  = AT_READ_REG(hw, REG_TWSI_CTRL);
-	regs_buff[4]  = AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL);
-	regs_buff[5]  = AT_READ_REG(hw, REG_MASTER_CTRL);
-	regs_buff[6]  = AT_READ_REG(hw, REG_MANUAL_TIMER_INIT);
-	regs_buff[7]  = AT_READ_REG(hw, REG_IRQ_MODU_TIMER_INIT);
-	regs_buff[8]  = AT_READ_REG(hw, REG_GPHY_CTRL);
-	regs_buff[9]  = AT_READ_REG(hw, REG_CMBDISDMA_TIMER);
-	regs_buff[10] = AT_READ_REG(hw, REG_IDLE_STATUS);
-	regs_buff[11] = AT_READ_REG(hw, REG_MDIO_CTRL);
-	regs_buff[12] = AT_READ_REG(hw, REG_SERDES_LOCK);
-	regs_buff[13] = AT_READ_REG(hw, REG_MAC_CTRL);
-	regs_buff[14] = AT_READ_REG(hw, REG_MAC_IPG_IFG);
-	regs_buff[15] = AT_READ_REG(hw, REG_MAC_STA_ADDR);
-	regs_buff[16] = AT_READ_REG(hw, REG_MAC_STA_ADDR+4);
-	regs_buff[17] = AT_READ_REG(hw, REG_RX_HASH_TABLE);
-	regs_buff[18] = AT_READ_REG(hw, REG_RX_HASH_TABLE+4);
-	regs_buff[19] = AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL);
-	regs_buff[20] = AT_READ_REG(hw, REG_MTU);
-	regs_buff[21] = AT_READ_REG(hw, REG_WOL_CTRL);
-	regs_buff[22] = AT_READ_REG(hw, REG_SRAM_TRD_ADDR);
-	regs_buff[23] = AT_READ_REG(hw, REG_SRAM_TRD_LEN);
-	regs_buff[24] = AT_READ_REG(hw, REG_SRAM_RXF_ADDR);
-	regs_buff[25] = AT_READ_REG(hw, REG_SRAM_RXF_LEN);
-	regs_buff[26] = AT_READ_REG(hw, REG_SRAM_TXF_ADDR);
-	regs_buff[27] = AT_READ_REG(hw, REG_SRAM_TXF_LEN);
-	regs_buff[28] = AT_READ_REG(hw, REG_SRAM_TCPH_ADDR);
-	regs_buff[29] = AT_READ_REG(hw, REG_SRAM_PKTH_ADDR);
-
-	atl1e_read_phy_reg(hw, MII_BMCR, &phy_data);
-	regs_buff[73] = (u32)phy_data;
-	atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
-	regs_buff[74] = (u32)phy_data;
-}
-
-static int atl1e_get_eeprom_len(struct net_device *netdev)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-
-	if (!atl1e_check_eeprom_exist(&adapter->hw))
-		return AT_EEPROM_LEN;
-	else
-		return 0;
-}
-
-static int atl1e_get_eeprom(struct net_device *netdev,
-		struct ethtool_eeprom *eeprom, u8 *bytes)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	struct atl1e_hw *hw = &adapter->hw;
-	u32 *eeprom_buff;
-	int first_dword, last_dword;
-	int ret_val = 0;
-	int i;
-
-	if (eeprom->len == 0)
-		return -EINVAL;
-
-	if (atl1e_check_eeprom_exist(hw)) /* not exist */
-		return -EINVAL;
-
-	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
-
-	first_dword = eeprom->offset >> 2;
-	last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
-
-	eeprom_buff = kmalloc(sizeof(u32) *
-			(last_dword - first_dword + 1), GFP_KERNEL);
-	if (eeprom_buff == NULL)
-		return -ENOMEM;
-
-	for (i = first_dword; i < last_dword; i++) {
-		if (!atl1e_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) {
-			kfree(eeprom_buff);
-			return -EIO;
-		}
-	}
-
-	memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3),
-			eeprom->len);
-	kfree(eeprom_buff);
-
-	return ret_val;
-}
-
-static int atl1e_set_eeprom(struct net_device *netdev,
-			    struct ethtool_eeprom *eeprom, u8 *bytes)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	struct atl1e_hw *hw = &adapter->hw;
-	u32 *eeprom_buff;
-	u32 *ptr;
-	int first_dword, last_dword;
-	int ret_val = 0;
-	int i;
-
-	if (eeprom->len == 0)
-		return -EOPNOTSUPP;
-
-	if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
-		return -EINVAL;
-
-	first_dword = eeprom->offset >> 2;
-	last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
-	eeprom_buff = kmalloc(AT_EEPROM_LEN, GFP_KERNEL);
-	if (eeprom_buff == NULL)
-		return -ENOMEM;
-
-	ptr = (u32 *)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 (!atl1e_read_eeprom(hw, first_dword * 4, &(eeprom_buff[0]))) {
-			ret_val = -EIO;
-			goto out;
-		}
-		ptr++;
-	}
-	if (((eeprom->offset + eeprom->len) & 3)) {
-		/* need read/modify/write of last changed EEPROM word */
-		/* only the first byte of the word is being modified */
-
-		if (!atl1e_read_eeprom(hw, last_dword * 4,
-				&(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 (!atl1e_write_eeprom(hw, ((first_dword + i) * 4),
-				  eeprom_buff[i])) {
-			ret_val = -EIO;
-			goto out;
-		}
-	}
-out:
-	kfree(eeprom_buff);
-	return ret_val;
-}
-
-static void atl1e_get_drvinfo(struct net_device *netdev,
-		struct ethtool_drvinfo *drvinfo)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-
-	strncpy(drvinfo->driver,  atl1e_driver_name, 32);
-	strncpy(drvinfo->version, atl1e_driver_version, 32);
-	strncpy(drvinfo->fw_version, "L1e", 32);
-	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
-	drvinfo->n_stats = 0;
-	drvinfo->testinfo_len = 0;
-	drvinfo->regdump_len = atl1e_get_regs_len(netdev);
-	drvinfo->eedump_len = atl1e_get_eeprom_len(netdev);
-}
-
-static void atl1e_get_wol(struct net_device *netdev,
-			  struct ethtool_wolinfo *wol)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-
-	wol->supported = WAKE_MAGIC | WAKE_PHY;
-	wol->wolopts = 0;
-
-	if (adapter->wol & AT_WUFC_EX)
-		wol->wolopts |= WAKE_UCAST;
-	if (adapter->wol & AT_WUFC_MC)
-		wol->wolopts |= WAKE_MCAST;
-	if (adapter->wol & AT_WUFC_BC)
-		wol->wolopts |= WAKE_BCAST;
-	if (adapter->wol & AT_WUFC_MAG)
-		wol->wolopts |= WAKE_MAGIC;
-	if (adapter->wol & AT_WUFC_LNKC)
-		wol->wolopts |= WAKE_PHY;
-}
-
-static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-
-	if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE |
-			    WAKE_UCAST | WAKE_MCAST | WAKE_BCAST))
-		return -EOPNOTSUPP;
-	/* these settings will always override what we currently have */
-	adapter->wol = 0;
-
-	if (wol->wolopts & WAKE_MAGIC)
-		adapter->wol |= AT_WUFC_MAG;
-	if (wol->wolopts & WAKE_PHY)
-		adapter->wol |= AT_WUFC_LNKC;
-
-	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
-
-	return 0;
-}
-
-static int atl1e_nway_reset(struct net_device *netdev)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	if (netif_running(netdev))
-		atl1e_reinit_locked(adapter);
-	return 0;
-}
-
-static const struct ethtool_ops atl1e_ethtool_ops = {
-	.get_settings           = atl1e_get_settings,
-	.set_settings           = atl1e_set_settings,
-	.get_drvinfo            = atl1e_get_drvinfo,
-	.get_regs_len           = atl1e_get_regs_len,
-	.get_regs               = atl1e_get_regs,
-	.get_wol                = atl1e_get_wol,
-	.set_wol                = atl1e_set_wol,
-	.get_msglevel           = atl1e_get_msglevel,
-	.nway_reset             = atl1e_nway_reset,
-	.get_link               = ethtool_op_get_link,
-	.get_eeprom_len         = atl1e_get_eeprom_len,
-	.get_eeprom             = atl1e_get_eeprom,
-	.set_eeprom             = atl1e_set_eeprom,
-};
-
-void atl1e_set_ethtool_ops(struct net_device *netdev)
-{
-	SET_ETHTOOL_OPS(netdev, &atl1e_ethtool_ops);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/atl1e/atl1e.h linux-libre-3.2-gnu/drivers/net/atl1e/atl1e.h
--- linux-libre-3.1-gnu/drivers/net/atl1e/atl1e.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atl1e/atl1e.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,509 +0,0 @@
-/*
- * Copyright(c) 2007 Atheros Corporation. All rights reserved.
- * Copyright(c) 2007 xiong huang <xiong.huang@atheros.com>
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You 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 _ATL1E_H_
-#define _ATL1E_H_
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/udp.h>
-#include <linux/mii.h>
-#include <linux/io.h>
-#include <linux/vmalloc.h>
-#include <linux/pagemap.h>
-#include <linux/tcp.h>
-#include <linux/ethtool.h>
-#include <linux/if_vlan.h>
-#include <linux/workqueue.h>
-#include <net/checksum.h>
-#include <net/ip6_checksum.h>
-
-#include "atl1e_hw.h"
-
-#define PCI_REG_COMMAND	 0x04    /* PCI Command Register */
-#define CMD_IO_SPACE	 0x0001
-#define CMD_MEMORY_SPACE 0x0002
-#define CMD_BUS_MASTER   0x0004
-
-#define BAR_0   0
-#define BAR_1   1
-#define BAR_5   5
-
-/* Wake Up Filter Control */
-#define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
-#define AT_WUFC_MAG  0x00000002 /* Magic Packet Wakeup Enable */
-#define AT_WUFC_EX   0x00000004 /* Directed Exact Wakeup Enable */
-#define AT_WUFC_MC   0x00000008 /* Multicast Wakeup Enable */
-#define AT_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */
-
-#define SPEED_0		   0xffff
-#define HALF_DUPLEX        1
-#define FULL_DUPLEX        2
-
-/* Error Codes */
-#define AT_ERR_EEPROM      1
-#define AT_ERR_PHY         2
-#define AT_ERR_CONFIG      3
-#define AT_ERR_PARAM       4
-#define AT_ERR_MAC_TYPE    5
-#define AT_ERR_PHY_TYPE    6
-#define AT_ERR_PHY_SPEED   7
-#define AT_ERR_PHY_RES     8
-#define AT_ERR_TIMEOUT     9
-
-#define MAX_JUMBO_FRAME_SIZE 0x2000
-
-#define AT_VLAN_TAG_TO_TPD_TAG(_vlan, _tpd)    \
-	_tpd = (((_vlan) << (4)) | (((_vlan) >> 13) & 7) |\
-		 (((_vlan) >> 9) & 8))
-
-#define AT_TPD_TAG_TO_VLAN_TAG(_tpd, _vlan)    \
-	_vlan = (((_tpd) >> 8) | (((_tpd) & 0x77) << 9) |\
-		   (((_tdp) & 0x88) << 5))
-
-#define AT_MAX_RECEIVE_QUEUE    4
-#define AT_PAGE_NUM_PER_QUEUE   2
-
-#define AT_DMA_HI_ADDR_MASK     0xffffffff00000000ULL
-#define AT_DMA_LO_ADDR_MASK     0x00000000ffffffffULL
-
-#define AT_TX_WATCHDOG  (5 * HZ)
-#define AT_MAX_INT_WORK		10
-#define AT_TWSI_EEPROM_TIMEOUT 	100
-#define AT_HW_MAX_IDLE_DELAY 	10
-#define AT_SUSPEND_LINK_TIMEOUT 28
-
-#define AT_REGS_LEN	75
-#define AT_EEPROM_LEN 	512
-#define AT_ADV_MASK	(ADVERTISE_10_HALF  |\
-			 ADVERTISE_10_FULL  |\
-			 ADVERTISE_100_HALF |\
-			 ADVERTISE_100_FULL |\
-			 ADVERTISE_1000_FULL)
-
-/* tpd word 2 */
-#define TPD_BUFLEN_MASK 	0x3FFF
-#define TPD_BUFLEN_SHIFT        0
-#define TPD_DMAINT_MASK		0x0001
-#define TPD_DMAINT_SHIFT        14
-#define TPD_PKTNT_MASK          0x0001
-#define TPD_PKTINT_SHIFT        15
-#define TPD_VLANTAG_MASK        0xFFFF
-#define TPD_VLAN_SHIFT          16
-
-/* tpd word 3 bits 0:4 */
-#define TPD_EOP_MASK            0x0001
-#define TPD_EOP_SHIFT           0
-#define TPD_IP_VERSION_MASK	0x0001
-#define TPD_IP_VERSION_SHIFT	1	/* 0 : IPV4, 1 : IPV6 */
-#define TPD_INS_VL_TAG_MASK	0x0001
-#define TPD_INS_VL_TAG_SHIFT	2
-#define TPD_CC_SEGMENT_EN_MASK	0x0001
-#define TPD_CC_SEGMENT_EN_SHIFT	3
-#define TPD_SEGMENT_EN_MASK     0x0001
-#define TPD_SEGMENT_EN_SHIFT    4
-
-/* tdp word 3 bits 5:7 if ip version is 0 */
-#define TPD_IP_CSUM_MASK        0x0001
-#define TPD_IP_CSUM_SHIFT       5
-#define TPD_TCP_CSUM_MASK       0x0001
-#define TPD_TCP_CSUM_SHIFT      6
-#define TPD_UDP_CSUM_MASK       0x0001
-#define TPD_UDP_CSUM_SHIFT      7
-
-/* tdp word 3 bits 5:7 if ip version is 1 */
-#define TPD_V6_IPHLLO_MASK	0x0007
-#define TPD_V6_IPHLLO_SHIFT	7
-
-/* tpd word 3 bits 8:9 bit */
-#define TPD_VL_TAGGED_MASK      0x0001
-#define TPD_VL_TAGGED_SHIFT     8
-#define TPD_ETHTYPE_MASK        0x0001
-#define TPD_ETHTYPE_SHIFT       9
-
-/* tdp word 3 bits 10:13 if ip version is 0 */
-#define TDP_V4_IPHL_MASK	0x000F
-#define TPD_V4_IPHL_SHIFT	10
-
-/* tdp word 3 bits 10:13 if ip version is 1 */
-#define TPD_V6_IPHLHI_MASK	0x000F
-#define TPD_V6_IPHLHI_SHIFT	10
-
-/* tpd word 3 bit 14:31 if segment enabled */
-#define TPD_TCPHDRLEN_MASK      0x000F
-#define TPD_TCPHDRLEN_SHIFT     14
-#define TPD_HDRFLAG_MASK        0x0001
-#define TPD_HDRFLAG_SHIFT       18
-#define TPD_MSS_MASK            0x1FFF
-#define TPD_MSS_SHIFT           19
-
-/* tdp word 3 bit 16:31 if custom csum enabled */
-#define TPD_PLOADOFFSET_MASK    0x00FF
-#define TPD_PLOADOFFSET_SHIFT   16
-#define TPD_CCSUMOFFSET_MASK    0x00FF
-#define TPD_CCSUMOFFSET_SHIFT   24
-
-struct atl1e_tpd_desc {
-	__le64 buffer_addr;
-	__le32 word2;
-	__le32 word3;
-};
-
-/* how about 0x2000 */
-#define MAX_TX_BUF_LEN      0x2000
-#define MAX_TX_BUF_SHIFT    13
-/*#define MAX_TX_BUF_LEN  0x3000 */
-
-/* rrs word 1 bit 0:31 */
-#define RRS_RX_CSUM_MASK	0xFFFF
-#define RRS_RX_CSUM_SHIFT	0
-#define RRS_PKT_SIZE_MASK	0x3FFF
-#define RRS_PKT_SIZE_SHIFT	16
-#define RRS_CPU_NUM_MASK	0x0003
-#define	RRS_CPU_NUM_SHIFT	30
-
-#define	RRS_IS_RSS_IPV4		0x0001
-#define RRS_IS_RSS_IPV4_TCP	0x0002
-#define RRS_IS_RSS_IPV6		0x0004
-#define RRS_IS_RSS_IPV6_TCP	0x0008
-#define RRS_IS_IPV6		0x0010
-#define RRS_IS_IP_FRAG		0x0020
-#define RRS_IS_IP_DF		0x0040
-#define RRS_IS_802_3		0x0080
-#define RRS_IS_VLAN_TAG		0x0100
-#define RRS_IS_ERR_FRAME	0x0200
-#define RRS_IS_IPV4		0x0400
-#define RRS_IS_UDP		0x0800
-#define RRS_IS_TCP		0x1000
-#define RRS_IS_BCAST		0x2000
-#define RRS_IS_MCAST		0x4000
-#define RRS_IS_PAUSE		0x8000
-
-#define RRS_ERR_BAD_CRC		0x0001
-#define RRS_ERR_CODE		0x0002
-#define RRS_ERR_DRIBBLE		0x0004
-#define RRS_ERR_RUNT		0x0008
-#define RRS_ERR_RX_OVERFLOW	0x0010
-#define RRS_ERR_TRUNC		0x0020
-#define RRS_ERR_IP_CSUM		0x0040
-#define RRS_ERR_L4_CSUM		0x0080
-#define RRS_ERR_LENGTH		0x0100
-#define RRS_ERR_DES_ADDR	0x0200
-
-struct atl1e_recv_ret_status {
-	u16 seq_num;
-	u16 hash_lo;
-	__le32	word1;
-	u16 pkt_flag;
-	u16 err_flag;
-	u16 hash_hi;
-	u16 vtag;
-};
-
-enum atl1e_dma_req_block {
-	atl1e_dma_req_128 = 0,
-	atl1e_dma_req_256 = 1,
-	atl1e_dma_req_512 = 2,
-	atl1e_dma_req_1024 = 3,
-	atl1e_dma_req_2048 = 4,
-	atl1e_dma_req_4096 = 5
-};
-
-enum atl1e_rrs_type {
-	atl1e_rrs_disable = 0,
-	atl1e_rrs_ipv4 = 1,
-	atl1e_rrs_ipv4_tcp = 2,
-	atl1e_rrs_ipv6 = 4,
-	atl1e_rrs_ipv6_tcp = 8
-};
-
-enum atl1e_nic_type {
-	athr_l1e = 0,
-	athr_l2e_revA = 1,
-	athr_l2e_revB = 2
-};
-
-struct atl1e_hw_stats {
-	/* rx */
-	unsigned long rx_ok;	      /* The number of good packet received. */
-	unsigned long rx_bcast;       /* The number of good broadcast packet received. */
-	unsigned long rx_mcast;       /* The number of good multicast packet received. */
-	unsigned long rx_pause;       /* The number of Pause packet received. */
-	unsigned long rx_ctrl;        /* The number of Control packet received other than Pause frame. */
-	unsigned long rx_fcs_err;     /* The number of packets with bad FCS. */
-	unsigned long rx_len_err;     /* The number of packets with mismatch of length field and actual size. */
-	unsigned long rx_byte_cnt;    /* The number of bytes of good packet received. FCS is NOT included. */
-	unsigned long rx_runt;        /* The number of packets received that are less than 64 byte long and with good FCS. */
-	unsigned long rx_frag;        /* The number of packets received that are less than 64 byte long and with bad FCS. */
-	unsigned long rx_sz_64;       /* The number of good and bad packets received that are 64 byte long. */
-	unsigned long rx_sz_65_127;   /* The number of good and bad packets received that are between 65 and 127-byte long. */
-	unsigned long rx_sz_128_255;  /* The number of good and bad packets received that are between 128 and 255-byte long. */
-	unsigned long rx_sz_256_511;  /* The number of good and bad packets received that are between 256 and 511-byte long. */
-	unsigned long rx_sz_512_1023; /* The number of good and bad packets received that are between 512 and 1023-byte long. */
-	unsigned long rx_sz_1024_1518;    /* The number of good and bad packets received that are between 1024 and 1518-byte long. */
-	unsigned long rx_sz_1519_max; /* The number of good and bad packets received that are between 1519-byte and MTU. */
-	unsigned long rx_sz_ov;       /* The number of good and bad packets received that are more than MTU size truncated by Selene. */
-	unsigned long rx_rxf_ov;      /* The number of frame dropped due to occurrence of RX FIFO overflow. */
-	unsigned long rx_rrd_ov;      /* The number of frame dropped due to occurrence of RRD overflow. */
-	unsigned long rx_align_err;   /* Alignment Error */
-	unsigned long rx_bcast_byte_cnt;  /* The byte count of broadcast packet received, excluding FCS. */
-	unsigned long rx_mcast_byte_cnt;  /* The byte count of multicast packet received, excluding FCS. */
-	unsigned long rx_err_addr;    /* The number of packets dropped due to address filtering. */
-
-	/* tx */
-	unsigned long tx_ok;      /* The number of good packet transmitted. */
-	unsigned long tx_bcast;       /* The number of good broadcast packet transmitted. */
-	unsigned long tx_mcast;       /* The number of good multicast packet transmitted. */
-	unsigned long tx_pause;       /* The number of Pause packet transmitted. */
-	unsigned long tx_exc_defer;   /* The number of packets transmitted with excessive deferral. */
-	unsigned long tx_ctrl;        /* The number of packets transmitted is a control frame, excluding Pause frame. */
-	unsigned long tx_defer;       /* The number of packets transmitted that is deferred. */
-	unsigned long tx_byte_cnt;    /* The number of bytes of data transmitted. FCS is NOT included. */
-	unsigned long tx_sz_64;       /* The number of good and bad packets transmitted that are 64 byte long. */
-	unsigned long tx_sz_65_127;   /* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
-	unsigned long tx_sz_128_255;  /* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
-	unsigned long tx_sz_256_511;  /* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
-	unsigned long tx_sz_512_1023; /* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
-	unsigned long tx_sz_1024_1518;    /* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
-	unsigned long tx_sz_1519_max; /* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
-	unsigned long tx_1_col;       /* The number of packets subsequently transmitted successfully with a single prior collision. */
-	unsigned long tx_2_col;       /* The number of packets subsequently transmitted successfully with multiple prior collisions. */
-	unsigned long tx_late_col;    /* The number of packets transmitted with late collisions. */
-	unsigned long tx_abort_col;   /* The number of transmit packets aborted due to excessive collisions. */
-	unsigned long tx_underrun;    /* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
-	unsigned long tx_rd_eop;      /* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
-	unsigned long tx_len_err;     /* The number of transmit packets with length field does NOT match the actual frame size. */
-	unsigned long tx_trunc;       /* The number of transmit packets truncated due to size exceeding MTU. */
-	unsigned long tx_bcast_byte;  /* The byte count of broadcast packet transmitted, excluding FCS. */
-	unsigned long tx_mcast_byte;  /* The byte count of multicast packet transmitted, excluding FCS. */
-};
-
-struct atl1e_hw {
-	u8 __iomem      *hw_addr;            /* inner register address */
-	resource_size_t mem_rang;
-	struct atl1e_adapter *adapter;
-	enum atl1e_nic_type  nic_type;
-	u16 device_id;
-	u16 vendor_id;
-	u16 subsystem_id;
-	u16 subsystem_vendor_id;
-	u8  revision_id;
-	u16 pci_cmd_word;
-	u8 mac_addr[ETH_ALEN];
-	u8 perm_mac_addr[ETH_ALEN];
-	u8 preamble_len;
-	u16 max_frame_size;
-	u16 rx_jumbo_th;
-	u16 tx_jumbo_th;
-
-	u16 media_type;
-#define MEDIA_TYPE_AUTO_SENSOR  0
-#define MEDIA_TYPE_100M_FULL    1
-#define MEDIA_TYPE_100M_HALF    2
-#define MEDIA_TYPE_10M_FULL     3
-#define MEDIA_TYPE_10M_HALF     4
-
-	u16 autoneg_advertised;
-#define ADVERTISE_10_HALF               0x0001
-#define ADVERTISE_10_FULL               0x0002
-#define ADVERTISE_100_HALF              0x0004
-#define ADVERTISE_100_FULL              0x0008
-#define ADVERTISE_1000_HALF             0x0010 /* Not used, just FYI */
-#define ADVERTISE_1000_FULL             0x0020
-	u16 mii_autoneg_adv_reg;
-	u16 mii_1000t_ctrl_reg;
-
-	u16 imt;        /* Interrupt Moderator timer ( 2us resolution) */
-	u16 ict;        /* Interrupt Clear timer (2us resolution) */
-	u32 smb_timer;
-	u16 rrd_thresh; /* Threshold of number of RRD produced to trigger
-			  interrupt request */
-	u16 tpd_thresh;
-	u16 rx_count_down; /* 2us resolution */
-	u16 tx_count_down;
-
-	u8 tpd_burst;   /* Number of TPD to prefetch in cache-aligned burst. */
-	enum atl1e_rrs_type rrs_type;
-	u32 base_cpu;
-	u32 indirect_tab;
-
-	enum atl1e_dma_req_block dmar_block;
-	enum atl1e_dma_req_block dmaw_block;
-	u8 dmaw_dly_cnt;
-	u8 dmar_dly_cnt;
-
-	bool phy_configured;
-	bool re_autoneg;
-	bool emi_ca;
-};
-
-/*
- * wrapper around a pointer to a socket buffer,
- * so a DMA handle can be stored along with the buffer
- */
-struct atl1e_tx_buffer {
-	struct sk_buff *skb;
-	u16 flags;
-#define ATL1E_TX_PCIMAP_SINGLE		0x0001
-#define ATL1E_TX_PCIMAP_PAGE		0x0002
-#define ATL1E_TX_PCIMAP_TYPE_MASK	0x0003
-	u16 length;
-	dma_addr_t dma;
-};
-
-#define ATL1E_SET_PCIMAP_TYPE(tx_buff, type) do {		\
-	((tx_buff)->flags) &= ~ATL1E_TX_PCIMAP_TYPE_MASK;	\
-	((tx_buff)->flags) |= (type);				\
-	} while (0)
-
-struct atl1e_rx_page {
-	dma_addr_t	dma;    /* receive rage DMA address */
-	u8		*addr;   /* receive rage virtual address */
-	dma_addr_t	write_offset_dma;  /* the DMA address which contain the
-					      receive data offset in the page */
-	u32		*write_offset_addr; /* the virtaul address which contain
-					     the receive data offset in the page */
-	u32		read_offset;       /* the offset where we have read */
-};
-
-struct atl1e_rx_page_desc {
-	struct atl1e_rx_page   rx_page[AT_PAGE_NUM_PER_QUEUE];
-	u8  rx_using;
-	u16 rx_nxseq;
-};
-
-/* transmit packet descriptor (tpd) ring */
-struct atl1e_tx_ring {
-	struct atl1e_tpd_desc *desc;  /* descriptor ring virtual address  */
-	dma_addr_t	   dma;    /* descriptor ring physical address */
-	u16       	   count;  /* the count of transmit rings  */
-	rwlock_t	   tx_lock;
-	u16		   next_to_use;
-	atomic_t	   next_to_clean;
-	struct atl1e_tx_buffer *tx_buffer;
-	dma_addr_t	   cmb_dma;
-	u32		   *cmb;
-};
-
-/* receive packet descriptor ring */
-struct atl1e_rx_ring {
-	void        	*desc;
-	dma_addr_t  	dma;
-	int         	size;
-	u32	    	page_size; /* bytes length of rxf page */
-	u32		real_page_size; /* real_page_size = page_size + jumbo + aliagn */
-	struct atl1e_rx_page_desc	rx_page_desc[AT_MAX_RECEIVE_QUEUE];
-};
-
-/* board specific private data structure */
-struct atl1e_adapter {
-	struct net_device   *netdev;
-	struct pci_dev      *pdev;
-	struct napi_struct  napi;
-	struct mii_if_info  mii;    /* MII interface info */
-	struct atl1e_hw        hw;
-	struct atl1e_hw_stats  hw_stats;
-
-	bool have_msi;
-	u32 wol;
-	u16 link_speed;
-	u16 link_duplex;
-
-	spinlock_t mdio_lock;
-	spinlock_t tx_lock;
-	atomic_t irq_sem;
-
-	struct work_struct reset_task;
-	struct work_struct link_chg_task;
-	struct timer_list watchdog_timer;
-	struct timer_list phy_config_timer;
-
-	/* All Descriptor memory */
-	dma_addr_t  	ring_dma;
-	void     	*ring_vir_addr;
-	u32             ring_size;
-
-	struct atl1e_tx_ring tx_ring;
-	struct atl1e_rx_ring rx_ring;
-	int num_rx_queues;
-	unsigned long flags;
-#define __AT_TESTING        0x0001
-#define __AT_RESETTING      0x0002
-#define __AT_DOWN           0x0003
-
-	u32 bd_number;     /* board number;*/
-	u32 pci_state[16];
-	u32 *config_space;
-};
-
-#define AT_WRITE_REG(a, reg, value) ( \
-		writel((value), ((a)->hw_addr + reg)))
-
-#define AT_WRITE_FLUSH(a) (\
-		readl((a)->hw_addr))
-
-#define AT_READ_REG(a, reg) ( \
-		readl((a)->hw_addr + reg))
-
-#define AT_WRITE_REGB(a, reg, value) (\
-		writeb((value), ((a)->hw_addr + reg)))
-
-#define AT_READ_REGB(a, reg) (\
-		readb((a)->hw_addr + reg))
-
-#define AT_WRITE_REGW(a, reg, value) (\
-		writew((value), ((a)->hw_addr + reg)))
-
-#define AT_READ_REGW(a, reg) (\
-		readw((a)->hw_addr + reg))
-
-#define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \
-		writel((value), (((a)->hw_addr + reg) + ((offset) << 2))))
-
-#define AT_READ_REG_ARRAY(a, reg, offset) ( \
-		readl(((a)->hw_addr + reg) + ((offset) << 2)))
-
-extern char atl1e_driver_name[];
-extern char atl1e_driver_version[];
-
-extern void atl1e_check_options(struct atl1e_adapter *adapter);
-extern int atl1e_up(struct atl1e_adapter *adapter);
-extern void atl1e_down(struct atl1e_adapter *adapter);
-extern void atl1e_reinit_locked(struct atl1e_adapter *adapter);
-extern s32 atl1e_reset_hw(struct atl1e_hw *hw);
-extern void atl1e_set_ethtool_ops(struct net_device *netdev);
-#endif /* _ATL1_E_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/atl1e/atl1e_hw.c linux-libre-3.2-gnu/drivers/net/atl1e/atl1e_hw.c
--- linux-libre-3.1-gnu/drivers/net/atl1e/atl1e_hw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atl1e/atl1e_hw.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,651 +0,0 @@
-/*
- * Copyright(c) 2007 Atheros Corporation. All rights reserved.
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You 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/pci.h>
-#include <linux/delay.h>
-#include <linux/mii.h>
-#include <linux/crc32.h>
-
-#include "atl1e.h"
-
-/*
- * check_eeprom_exist
- * return 0 if eeprom exist
- */
-int atl1e_check_eeprom_exist(struct atl1e_hw *hw)
-{
-	u32 value;
-
-	value = AT_READ_REG(hw, REG_SPI_FLASH_CTRL);
-	if (value & SPI_FLASH_CTRL_EN_VPD) {
-		value &= ~SPI_FLASH_CTRL_EN_VPD;
-		AT_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);
-	}
-	value = AT_READ_REGW(hw, REG_PCIE_CAP_LIST);
-	return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
-}
-
-void atl1e_hw_set_mac_addr(struct atl1e_hw *hw)
-{
-	u32 value;
-	/*
-	 * 00-0B-6A-F6-00-DC
-	 * 0:  6AF600DC 1: 000B
-	 * low dword
-	 */
-	value = (((u32)hw->mac_addr[2]) << 24) |
-		(((u32)hw->mac_addr[3]) << 16) |
-		(((u32)hw->mac_addr[4]) << 8)  |
-		(((u32)hw->mac_addr[5])) ;
-	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
-	/* hight dword */
-	value = (((u32)hw->mac_addr[0]) << 8) |
-		(((u32)hw->mac_addr[1])) ;
-	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
-}
-
-/*
- * atl1e_get_permanent_address
- * return 0 if get valid mac address,
- */
-static int atl1e_get_permanent_address(struct atl1e_hw *hw)
-{
-	u32 addr[2];
-	u32 i;
-	u32 twsi_ctrl_data;
-	u8  eth_addr[ETH_ALEN];
-
-	if (is_valid_ether_addr(hw->perm_mac_addr))
-		return 0;
-
-	/* init */
-	addr[0] = addr[1] = 0;
-
-	if (!atl1e_check_eeprom_exist(hw)) {
-		/* eeprom exist */
-		twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
-		twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
-		AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
-		for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
-			msleep(10);
-			twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
-			if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
-				break;
-		}
-		if (i >= AT_TWSI_EEPROM_TIMEOUT)
-			return AT_ERR_TIMEOUT;
-	}
-
-	/* maybe MAC-address is from BIOS */
-	addr[0] = AT_READ_REG(hw, REG_MAC_STA_ADDR);
-	addr[1] = AT_READ_REG(hw, REG_MAC_STA_ADDR + 4);
-	*(u32 *) &eth_addr[2] = swab32(addr[0]);
-	*(u16 *) &eth_addr[0] = swab16(*(u16 *)&addr[1]);
-
-	if (is_valid_ether_addr(eth_addr)) {
-		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
-		return 0;
-	}
-
-	return AT_ERR_EEPROM;
-}
-
-bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value)
-{
-	return true;
-}
-
-bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value)
-{
-	int i;
-	u32 control;
-
-	if (offset & 3)
-		return false; /* address do not align */
-
-	AT_WRITE_REG(hw, REG_VPD_DATA, 0);
-	control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
-	AT_WRITE_REG(hw, REG_VPD_CAP, control);
-
-	for (i = 0; i < 10; i++) {
-		msleep(2);
-		control = AT_READ_REG(hw, REG_VPD_CAP);
-		if (control & VPD_CAP_VPD_FLAG)
-			break;
-	}
-	if (control & VPD_CAP_VPD_FLAG) {
-		*p_value = AT_READ_REG(hw, REG_VPD_DATA);
-		return true;
-	}
-	return false; /* timeout */
-}
-
-void atl1e_force_ps(struct atl1e_hw *hw)
-{
-	AT_WRITE_REGW(hw, REG_GPHY_CTRL,
-			GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
-}
-
-/*
- * Reads the adapter's MAC address from the EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- */
-int atl1e_read_mac_addr(struct atl1e_hw *hw)
-{
-	int err = 0;
-
-	err = atl1e_get_permanent_address(hw);
-	if (err)
-		return AT_ERR_EEPROM;
-	memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
-	return 0;
-}
-
-/*
- * atl1e_hash_mc_addr
- *  purpose
- *      set hash value for a multicast address
- */
-u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr)
-{
-	u32 crc32;
-	u32 value = 0;
-	int i;
-
-	crc32 = ether_crc_le(6, mc_addr);
-	for (i = 0; i < 32; i++)
-		value |= (((crc32 >> i) & 1) << (31 - i));
-
-	return value;
-}
-
-/*
- * Sets the bit in the multicast table corresponding to the hash value.
- * hw - Struct containing variables accessed by shared code
- * hash_value - Multicast address hash value
- */
-void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value)
-{
-	u32 hash_bit, hash_reg;
-	u32 mta;
-
-	/*
-	 * The HASH Table  is a register array of 2 32-bit registers.
-	 * It is treated like an array of 64 bits.  We want to set
-	 * bit BitArray[hash_value]. So we figure out what register
-	 * the bit is in, read it, OR in the new bit, then write
-	 * back the new value.  The register is determined by the
-	 * upper 7 bits of the hash value and the bit within that
-	 * register are determined by the lower 5 bits of the value.
-	 */
-	hash_reg = (hash_value >> 31) & 0x1;
-	hash_bit = (hash_value >> 26) & 0x1F;
-
-	mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);
-
-	mta |= (1 << hash_bit);
-
-	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
-}
-/*
- * Reads the value from a PHY register
- * hw - Struct containing variables accessed by shared code
- * reg_addr - address of the PHY register to read
- */
-int atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data)
-{
-	u32 val;
-	int i;
-
-	val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
-		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
-		MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
-
-	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
-
-	wmb();
-
-	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
-		udelay(2);
-		val = AT_READ_REG(hw, REG_MDIO_CTRL);
-		if (!(val & (MDIO_START | MDIO_BUSY)))
-			break;
-		wmb();
-	}
-	if (!(val & (MDIO_START | MDIO_BUSY))) {
-		*phy_data = (u16)val;
-		return 0;
-	}
-
-	return AT_ERR_PHY;
-}
-
-/*
- * Writes a value to a PHY register
- * hw - Struct containing variables accessed by shared code
- * reg_addr - address of the PHY register to write
- * data - data to write to the PHY
- */
-int atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data)
-{
-	int i;
-	u32 val;
-
-	val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
-	       (reg_addr&MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
-	       MDIO_SUP_PREAMBLE |
-	       MDIO_START |
-	       MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
-
-	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
-	wmb();
-
-	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
-		udelay(2);
-		val = AT_READ_REG(hw, REG_MDIO_CTRL);
-		if (!(val & (MDIO_START | MDIO_BUSY)))
-			break;
-		wmb();
-	}
-
-	if (!(val & (MDIO_START | MDIO_BUSY)))
-		return 0;
-
-	return AT_ERR_PHY;
-}
-
-/*
- * atl1e_init_pcie - init PCIE module
- */
-static void atl1e_init_pcie(struct atl1e_hw *hw)
-{
-	u32 value;
-	/* comment 2lines below to save more power when sususpend
-	   value = LTSSM_TEST_MODE_DEF;
-	   AT_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value);
-	 */
-
-	/* pcie flow control mode change */
-	value = AT_READ_REG(hw, 0x1008);
-	value |= 0x8000;
-	AT_WRITE_REG(hw, 0x1008, value);
-}
-/*
- * Configures PHY autoneg and flow control advertisement settings
- *
- * hw - Struct containing variables accessed by shared code
- */
-static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw)
-{
-	s32 ret_val;
-	u16 mii_autoneg_adv_reg;
-	u16 mii_1000t_ctrl_reg;
-
-	if (0 != hw->mii_autoneg_adv_reg)
-		return 0;
-	/* Read the MII Auto-Neg Advertisement Register (Address 4/9). */
-	mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
-	mii_1000t_ctrl_reg  = MII_AT001_CR_1000T_DEFAULT_CAP_MASK;
-
-	/*
-	 * Need to parse autoneg_advertised  and set up
-	 * the appropriate PHY registers.  First we will parse for
-	 * autoneg_advertised software override.  Since we can advertise
-	 * a plethora of combinations, we need to check each bit
-	 * individually.
-	 */
-
-	/*
-	 * First we clear all the 10/100 mb speed bits in the Auto-Neg
-	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
-	 * the  1000Base-T control Register (Address 9).
-	 */
-	mii_autoneg_adv_reg &= ~ADVERTISE_ALL;
-	mii_1000t_ctrl_reg  &= ~MII_AT001_CR_1000T_SPEED_MASK;
-
-	/*
-	 * Need to parse MediaType and setup the
-	 * appropriate PHY registers.
-	 */
-	switch (hw->media_type) {
-	case MEDIA_TYPE_AUTO_SENSOR:
-		mii_autoneg_adv_reg |= ADVERTISE_ALL;
-		hw->autoneg_advertised = ADVERTISE_ALL;
-		if (hw->nic_type == athr_l1e) {
-			mii_1000t_ctrl_reg |= ADVERTISE_1000FULL;
-			hw->autoneg_advertised |= ADVERTISE_1000_FULL;
-		}
-		break;
-
-	case MEDIA_TYPE_100M_FULL:
-		mii_autoneg_adv_reg   |= ADVERTISE_100FULL;
-		hw->autoneg_advertised = ADVERTISE_100_FULL;
-		break;
-
-	case MEDIA_TYPE_100M_HALF:
-		mii_autoneg_adv_reg   |= ADVERTISE_100_HALF;
-		hw->autoneg_advertised = ADVERTISE_100_HALF;
-		break;
-
-	case MEDIA_TYPE_10M_FULL:
-		mii_autoneg_adv_reg   |= ADVERTISE_10_FULL;
-		hw->autoneg_advertised = ADVERTISE_10_FULL;
-		break;
-
-	default:
-		mii_autoneg_adv_reg   |= ADVERTISE_10_HALF;
-		hw->autoneg_advertised = ADVERTISE_10_HALF;
-		break;
-	}
-
-	/* flow control fixed to enable all */
-	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;
-
-	ret_val = atl1e_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
-	if (ret_val)
-		return ret_val;
-
-	if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
-		ret_val = atl1e_write_phy_reg(hw, MII_CTRL1000,
-					   mii_1000t_ctrl_reg);
-		if (ret_val)
-			return ret_val;
-	}
-
-	return 0;
-}
-
-
-/*
- * Resets the PHY and make all config validate
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Sets bit 15 and 12 of the MII control regiser (for F001 bug)
- */
-int atl1e_phy_commit(struct atl1e_hw *hw)
-{
-	struct atl1e_adapter *adapter = hw->adapter;
-	int ret_val;
-	u16 phy_data;
-
-	phy_data = BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART;
-
-	ret_val = atl1e_write_phy_reg(hw, MII_BMCR, phy_data);
-	if (ret_val) {
-		u32 val;
-		int i;
-		/**************************************
-		 * pcie serdes link may be down !
-		 **************************************/
-		for (i = 0; i < 25; i++) {
-			msleep(1);
-			val = AT_READ_REG(hw, REG_MDIO_CTRL);
-			if (!(val & (MDIO_START | MDIO_BUSY)))
-				break;
-		}
-
-		if (0 != (val & (MDIO_START | MDIO_BUSY))) {
-			netdev_err(adapter->netdev,
-				   "pcie linkdown at least for 25ms\n");
-			return ret_val;
-		}
-
-		netdev_err(adapter->netdev, "pcie linkup after %d ms\n", i);
-	}
-	return 0;
-}
-
-int atl1e_phy_init(struct atl1e_hw *hw)
-{
-	struct atl1e_adapter *adapter = hw->adapter;
-	s32 ret_val;
-	u16 phy_val;
-
-	if (hw->phy_configured) {
-		if (hw->re_autoneg) {
-			hw->re_autoneg = false;
-			return atl1e_restart_autoneg(hw);
-		}
-		return 0;
-	}
-
-	/* RESET GPHY Core */
-	AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT);
-	msleep(2);
-	AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |
-		      GPHY_CTRL_EXT_RESET);
-	msleep(2);
-
-	/* patches */
-	/* p1. eable hibernation mode */
-	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0xB);
-	if (ret_val)
-		return ret_val;
-	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0xBC00);
-	if (ret_val)
-		return ret_val;
-	/* p2. set Class A/B for all modes */
-	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0);
-	if (ret_val)
-		return ret_val;
-	phy_val = 0x02ef;
-	/* remove Class AB */
-	/* phy_val = hw->emi_ca ? 0x02ef : 0x02df; */
-	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, phy_val);
-	if (ret_val)
-		return ret_val;
-	/* p3. 10B ??? */
-	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x12);
-	if (ret_val)
-		return ret_val;
-	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x4C04);
-	if (ret_val)
-		return ret_val;
-	/* p4. 1000T power */
-	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x4);
-	if (ret_val)
-		return ret_val;
-	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x8BBB);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x5);
-	if (ret_val)
-		return ret_val;
-	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x2C46);
-	if (ret_val)
-		return ret_val;
-
-	msleep(1);
-
-	/*Enable PHY LinkChange Interrupt */
-	ret_val = atl1e_write_phy_reg(hw, MII_INT_CTRL, 0xC00);
-	if (ret_val) {
-		netdev_err(adapter->netdev,
-			   "Error enable PHY linkChange Interrupt\n");
-		return ret_val;
-	}
-	/* setup AutoNeg parameters */
-	ret_val = atl1e_phy_setup_autoneg_adv(hw);
-	if (ret_val) {
-		netdev_err(adapter->netdev,
-			   "Error Setting up Auto-Negotiation\n");
-		return ret_val;
-	}
-	/* SW.Reset & En-Auto-Neg to restart Auto-Neg*/
-	netdev_dbg(adapter->netdev, "Restarting Auto-Negotiation\n");
-	ret_val = atl1e_phy_commit(hw);
-	if (ret_val) {
-		netdev_err(adapter->netdev, "Error resetting the phy\n");
-		return ret_val;
-	}
-
-	hw->phy_configured = true;
-
-	return 0;
-}
-
-/*
- * Reset the transmit and receive units; mask and clear all interrupts.
- * hw - Struct containing variables accessed by shared code
- * return : 0  or  idle status (if error)
- */
-int atl1e_reset_hw(struct atl1e_hw *hw)
-{
-	struct atl1e_adapter *adapter = hw->adapter;
-	struct pci_dev *pdev = adapter->pdev;
-
-	u32 idle_status_data = 0;
-	u16 pci_cfg_cmd_word = 0;
-	int timeout = 0;
-
-	/* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */
-	pci_read_config_word(pdev, PCI_REG_COMMAND, &pci_cfg_cmd_word);
-	if ((pci_cfg_cmd_word & (CMD_IO_SPACE |
-				CMD_MEMORY_SPACE | CMD_BUS_MASTER))
-			!= (CMD_IO_SPACE | CMD_MEMORY_SPACE | CMD_BUS_MASTER)) {
-		pci_cfg_cmd_word |= (CMD_IO_SPACE |
-				     CMD_MEMORY_SPACE | CMD_BUS_MASTER);
-		pci_write_config_word(pdev, PCI_REG_COMMAND, pci_cfg_cmd_word);
-	}
-
-	/*
-	 * Issue Soft Reset to the MAC.  This will reset the chip's
-	 * transmit, receive, DMA.  It will not effect
-	 * the current PCI configuration.  The global reset bit is self-
-	 * clearing, and should clear within a microsecond.
-	 */
-	AT_WRITE_REG(hw, REG_MASTER_CTRL,
-			MASTER_CTRL_LED_MODE | MASTER_CTRL_SOFT_RST);
-	wmb();
-	msleep(1);
-
-	/* Wait at least 10ms for All module to be Idle */
-	for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
-		idle_status_data = AT_READ_REG(hw, REG_IDLE_STATUS);
-		if (idle_status_data == 0)
-			break;
-		msleep(1);
-		cpu_relax();
-	}
-
-	if (timeout >= AT_HW_MAX_IDLE_DELAY) {
-		netdev_err(adapter->netdev,
-			   "MAC state machine can't be idle since disabled for 10ms second\n");
-		return AT_ERR_TIMEOUT;
-	}
-
-	return 0;
-}
-
-
-/*
- * Performs basic configuration of the adapter.
- *
- * hw - Struct containing variables accessed by shared code
- * Assumes that the controller has previously been reset and is in a
- * post-reset uninitialized state. Initializes multicast table,
- * and  Calls routines to setup link
- * Leaves the transmit and receive units disabled and uninitialized.
- */
-int atl1e_init_hw(struct atl1e_hw *hw)
-{
-	s32 ret_val = 0;
-
-	atl1e_init_pcie(hw);
-
-	/* Zero out the Multicast HASH table */
-	/* clear the old settings from the multicast hash table */
-	AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
-	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
-
-	ret_val = atl1e_phy_init(hw);
-
-	return ret_val;
-}
-
-/*
- * Detects the current speed and duplex settings of the hardware.
- *
- * hw - Struct containing variables accessed by shared code
- * speed - Speed of the connection
- * duplex - Duplex setting of the connection
- */
-int atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex)
-{
-	int err;
-	u16 phy_data;
-
-	/* Read   PHY Specific Status Register (17) */
-	err = atl1e_read_phy_reg(hw, MII_AT001_PSSR, &phy_data);
-	if (err)
-		return err;
-
-	if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED))
-		return AT_ERR_PHY_RES;
-
-	switch (phy_data & MII_AT001_PSSR_SPEED) {
-	case MII_AT001_PSSR_1000MBS:
-		*speed = SPEED_1000;
-		break;
-	case MII_AT001_PSSR_100MBS:
-		*speed = SPEED_100;
-		break;
-	case MII_AT001_PSSR_10MBS:
-		*speed = SPEED_10;
-		break;
-	default:
-		return AT_ERR_PHY_SPEED;
-		break;
-	}
-
-	if (phy_data & MII_AT001_PSSR_DPLX)
-		*duplex = FULL_DUPLEX;
-	else
-		*duplex = HALF_DUPLEX;
-
-	return 0;
-}
-
-int atl1e_restart_autoneg(struct atl1e_hw *hw)
-{
-	int err = 0;
-
-	err = atl1e_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
-	if (err)
-		return err;
-
-	if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
-		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,
-			BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART);
-	return err;
-}
-
diff -druN linux-libre-3.1-gnu/drivers/net/atl1e/atl1e_hw.h linux-libre-3.2-gnu/drivers/net/atl1e/atl1e_hw.h
--- linux-libre-3.1-gnu/drivers/net/atl1e/atl1e_hw.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atl1e/atl1e_hw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,690 +0,0 @@
-/*
- * Copyright(c) 2007 Atheros Corporation. All rights reserved.
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You 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 _ATHL1E_HW_H_
-#define _ATHL1E_HW_H_
-
-#include <linux/types.h>
-#include <linux/mii.h>
-
-struct atl1e_adapter;
-struct atl1e_hw;
-
-/* function prototype */
-s32 atl1e_reset_hw(struct atl1e_hw *hw);
-s32 atl1e_read_mac_addr(struct atl1e_hw *hw);
-s32 atl1e_init_hw(struct atl1e_hw *hw);
-s32 atl1e_phy_commit(struct atl1e_hw *hw);
-s32 atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex);
-u32 atl1e_auto_get_fc(struct atl1e_adapter *adapter, u16 duplex);
-u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr);
-void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value);
-s32 atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data);
-s32 atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data);
-s32 atl1e_validate_mdi_setting(struct atl1e_hw *hw);
-void atl1e_hw_set_mac_addr(struct atl1e_hw *hw);
-bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value);
-bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value);
-s32 atl1e_phy_enter_power_saving(struct atl1e_hw *hw);
-s32 atl1e_phy_leave_power_saving(struct atl1e_hw *hw);
-s32 atl1e_phy_init(struct atl1e_hw *hw);
-int atl1e_check_eeprom_exist(struct atl1e_hw *hw);
-void atl1e_force_ps(struct atl1e_hw *hw);
-s32 atl1e_restart_autoneg(struct atl1e_hw *hw);
-
-/* register definition */
-#define REG_PM_CTRLSTAT             0x44
-
-#define REG_PCIE_CAP_LIST           0x58
-
-#define REG_DEVICE_CAP              0x5C
-#define     DEVICE_CAP_MAX_PAYLOAD_MASK     0x7
-#define     DEVICE_CAP_MAX_PAYLOAD_SHIFT    0
-
-#define REG_DEVICE_CTRL             0x60
-#define     DEVICE_CTRL_MAX_PAYLOAD_MASK    0x7
-#define     DEVICE_CTRL_MAX_PAYLOAD_SHIFT   5
-#define     DEVICE_CTRL_MAX_RREQ_SZ_MASK    0x7
-#define     DEVICE_CTRL_MAX_RREQ_SZ_SHIFT   12
-
-#define REG_VPD_CAP                 0x6C
-#define     VPD_CAP_ID_MASK                 0xff
-#define     VPD_CAP_ID_SHIFT                0
-#define     VPD_CAP_NEXT_PTR_MASK           0xFF
-#define     VPD_CAP_NEXT_PTR_SHIFT          8
-#define     VPD_CAP_VPD_ADDR_MASK           0x7FFF
-#define     VPD_CAP_VPD_ADDR_SHIFT          16
-#define     VPD_CAP_VPD_FLAG                0x80000000
-
-#define REG_VPD_DATA                0x70
-
-#define REG_SPI_FLASH_CTRL          0x200
-#define     SPI_FLASH_CTRL_STS_NON_RDY      0x1
-#define     SPI_FLASH_CTRL_STS_WEN          0x2
-#define     SPI_FLASH_CTRL_STS_WPEN         0x80
-#define     SPI_FLASH_CTRL_DEV_STS_MASK     0xFF
-#define     SPI_FLASH_CTRL_DEV_STS_SHIFT    0
-#define     SPI_FLASH_CTRL_INS_MASK         0x7
-#define     SPI_FLASH_CTRL_INS_SHIFT        8
-#define     SPI_FLASH_CTRL_START            0x800
-#define     SPI_FLASH_CTRL_EN_VPD           0x2000
-#define     SPI_FLASH_CTRL_LDSTART          0x8000
-#define     SPI_FLASH_CTRL_CS_HI_MASK       0x3
-#define     SPI_FLASH_CTRL_CS_HI_SHIFT      16
-#define     SPI_FLASH_CTRL_CS_HOLD_MASK     0x3
-#define     SPI_FLASH_CTRL_CS_HOLD_SHIFT    18
-#define     SPI_FLASH_CTRL_CLK_LO_MASK      0x3
-#define     SPI_FLASH_CTRL_CLK_LO_SHIFT     20
-#define     SPI_FLASH_CTRL_CLK_HI_MASK      0x3
-#define     SPI_FLASH_CTRL_CLK_HI_SHIFT     22
-#define     SPI_FLASH_CTRL_CS_SETUP_MASK    0x3
-#define     SPI_FLASH_CTRL_CS_SETUP_SHIFT   24
-#define     SPI_FLASH_CTRL_EROM_PGSZ_MASK   0x3
-#define     SPI_FLASH_CTRL_EROM_PGSZ_SHIFT  26
-#define     SPI_FLASH_CTRL_WAIT_READY       0x10000000
-
-#define REG_SPI_ADDR                0x204
-
-#define REG_SPI_DATA                0x208
-
-#define REG_SPI_FLASH_CONFIG        0x20C
-#define     SPI_FLASH_CONFIG_LD_ADDR_MASK   0xFFFFFF
-#define     SPI_FLASH_CONFIG_LD_ADDR_SHIFT  0
-#define     SPI_FLASH_CONFIG_VPD_ADDR_MASK  0x3
-#define     SPI_FLASH_CONFIG_VPD_ADDR_SHIFT 24
-#define     SPI_FLASH_CONFIG_LD_EXIST       0x4000000
-
-
-#define REG_SPI_FLASH_OP_PROGRAM    0x210
-#define REG_SPI_FLASH_OP_SC_ERASE   0x211
-#define REG_SPI_FLASH_OP_CHIP_ERASE 0x212
-#define REG_SPI_FLASH_OP_RDID       0x213
-#define REG_SPI_FLASH_OP_WREN       0x214
-#define REG_SPI_FLASH_OP_RDSR       0x215
-#define REG_SPI_FLASH_OP_WRSR       0x216
-#define REG_SPI_FLASH_OP_READ       0x217
-
-#define REG_TWSI_CTRL               0x218
-#define     TWSI_CTRL_LD_OFFSET_MASK        0xFF
-#define     TWSI_CTRL_LD_OFFSET_SHIFT       0
-#define     TWSI_CTRL_LD_SLV_ADDR_MASK      0x7
-#define     TWSI_CTRL_LD_SLV_ADDR_SHIFT     8
-#define     TWSI_CTRL_SW_LDSTART            0x800
-#define     TWSI_CTRL_HW_LDSTART            0x1000
-#define     TWSI_CTRL_SMB_SLV_ADDR_MASK     0x0x7F
-#define     TWSI_CTRL_SMB_SLV_ADDR_SHIFT    15
-#define     TWSI_CTRL_LD_EXIST              0x400000
-#define     TWSI_CTRL_READ_FREQ_SEL_MASK    0x3
-#define     TWSI_CTRL_READ_FREQ_SEL_SHIFT   23
-#define     TWSI_CTRL_FREQ_SEL_100K         0
-#define     TWSI_CTRL_FREQ_SEL_200K         1
-#define     TWSI_CTRL_FREQ_SEL_300K         2
-#define     TWSI_CTRL_FREQ_SEL_400K         3
-#define     TWSI_CTRL_SMB_SLV_ADDR
-#define     TWSI_CTRL_WRITE_FREQ_SEL_MASK   0x3
-#define     TWSI_CTRL_WRITE_FREQ_SEL_SHIFT  24
-
-
-#define REG_PCIE_DEV_MISC_CTRL      0x21C
-#define     PCIE_DEV_MISC_CTRL_EXT_PIPE     0x2
-#define     PCIE_DEV_MISC_CTRL_RETRY_BUFDIS 0x1
-#define     PCIE_DEV_MISC_CTRL_SPIROM_EXIST 0x4
-#define     PCIE_DEV_MISC_CTRL_SERDES_ENDIAN    0x8
-#define     PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN   0x10
-
-#define REG_PCIE_PHYMISC	    0x1000
-#define PCIE_PHYMISC_FORCE_RCV_DET	0x4
-
-#define REG_LTSSM_TEST_MODE         0x12FC
-#define         LTSSM_TEST_MODE_DEF     0xE000
-
-/* Selene Master Control Register */
-#define REG_MASTER_CTRL             0x1400
-#define     MASTER_CTRL_SOFT_RST            0x1
-#define     MASTER_CTRL_MTIMER_EN           0x2
-#define     MASTER_CTRL_ITIMER_EN           0x4
-#define     MASTER_CTRL_MANUAL_INT          0x8
-#define     MASTER_CTRL_ITIMER2_EN          0x20
-#define     MASTER_CTRL_INT_RDCLR           0x40
-#define     MASTER_CTRL_LED_MODE	    0x200
-#define     MASTER_CTRL_REV_NUM_SHIFT       16
-#define     MASTER_CTRL_REV_NUM_MASK        0xff
-#define     MASTER_CTRL_DEV_ID_SHIFT        24
-#define     MASTER_CTRL_DEV_ID_MASK         0xff
-
-/* Timer Initial Value Register */
-#define REG_MANUAL_TIMER_INIT       0x1404
-
-
-/* IRQ ModeratorTimer Initial Value Register */
-#define REG_IRQ_MODU_TIMER_INIT     0x1408   /* w */
-#define REG_IRQ_MODU_TIMER2_INIT    0x140A   /* w */
-
-
-#define REG_GPHY_CTRL               0x140C
-#define     GPHY_CTRL_EXT_RESET         1
-#define     GPHY_CTRL_PIPE_MOD          2
-#define     GPHY_CTRL_TEST_MODE_MASK    3
-#define     GPHY_CTRL_TEST_MODE_SHIFT   2
-#define     GPHY_CTRL_BERT_START        0x10
-#define     GPHY_CTRL_GATE_25M_EN       0x20
-#define     GPHY_CTRL_LPW_EXIT          0x40
-#define     GPHY_CTRL_PHY_IDDQ          0x80
-#define     GPHY_CTRL_PHY_IDDQ_DIS      0x100
-#define     GPHY_CTRL_PCLK_SEL_DIS      0x200
-#define     GPHY_CTRL_HIB_EN            0x400
-#define     GPHY_CTRL_HIB_PULSE         0x800
-#define     GPHY_CTRL_SEL_ANA_RST       0x1000
-#define     GPHY_CTRL_PHY_PLL_ON        0x2000
-#define     GPHY_CTRL_PWDOWN_HW		0x4000
-#define     GPHY_CTRL_DEFAULT (\
-		GPHY_CTRL_PHY_PLL_ON	|\
-		GPHY_CTRL_SEL_ANA_RST	|\
-		GPHY_CTRL_HIB_PULSE	|\
-		GPHY_CTRL_HIB_EN)
-
-#define     GPHY_CTRL_PW_WOL_DIS (\
-		GPHY_CTRL_PHY_PLL_ON	|\
-		GPHY_CTRL_SEL_ANA_RST	|\
-		GPHY_CTRL_HIB_PULSE	|\
-		GPHY_CTRL_HIB_EN	|\
-		GPHY_CTRL_PWDOWN_HW	|\
-		GPHY_CTRL_PCLK_SEL_DIS	|\
-		GPHY_CTRL_PHY_IDDQ)
-
-/* IRQ Anti-Lost Timer Initial Value Register */
-#define REG_CMBDISDMA_TIMER         0x140E
-
-
-/* Block IDLE Status Register */
-#define REG_IDLE_STATUS  	0x1410
-#define     IDLE_STATUS_RXMAC       1    /* 1: RXMAC state machine is in non-IDLE state. 0: RXMAC is idling */
-#define     IDLE_STATUS_TXMAC       2    /* 1: TXMAC state machine is in non-IDLE state. 0: TXMAC is idling */
-#define     IDLE_STATUS_RXQ         4    /* 1: RXQ state machine is in non-IDLE state.   0: RXQ is idling   */
-#define     IDLE_STATUS_TXQ         8    /* 1: TXQ state machine is in non-IDLE state.   0: TXQ is idling   */
-#define     IDLE_STATUS_DMAR        0x10 /* 1: DMAR state machine is in non-IDLE state.  0: DMAR is idling  */
-#define     IDLE_STATUS_DMAW        0x20 /* 1: DMAW state machine is in non-IDLE state.  0: DMAW is idling  */
-#define     IDLE_STATUS_SMB         0x40 /* 1: SMB state machine is in non-IDLE state.   0: SMB is idling   */
-#define     IDLE_STATUS_CMB         0x80 /* 1: CMB state machine is in non-IDLE state.   0: CMB is idling   */
-
-/* MDIO Control Register */
-#define REG_MDIO_CTRL           0x1414
-#define     MDIO_DATA_MASK          0xffff  /* On MDIO write, the 16-bit control data to write to PHY MII management register */
-#define     MDIO_DATA_SHIFT         0       /* On MDIO read, the 16-bit status data that was read from the PHY MII management register*/
-#define     MDIO_REG_ADDR_MASK      0x1f    /* MDIO register address */
-#define     MDIO_REG_ADDR_SHIFT     16
-#define     MDIO_RW                 0x200000      /* 1: read, 0: write */
-#define     MDIO_SUP_PREAMBLE       0x400000      /* Suppress preamble */
-#define     MDIO_START              0x800000      /* Write 1 to initiate the MDIO master. And this bit is self cleared after one cycle*/
-#define     MDIO_CLK_SEL_SHIFT      24
-#define     MDIO_CLK_25_4           0
-#define     MDIO_CLK_25_6           2
-#define     MDIO_CLK_25_8           3
-#define     MDIO_CLK_25_10          4
-#define     MDIO_CLK_25_14          5
-#define     MDIO_CLK_25_20          6
-#define     MDIO_CLK_25_28          7
-#define     MDIO_BUSY               0x8000000
-#define     MDIO_AP_EN              0x10000000
-#define MDIO_WAIT_TIMES         10
-
-/* MII PHY Status Register */
-#define REG_PHY_STATUS           0x1418
-#define     PHY_STATUS_100M	      0x20000
-#define     PHY_STATUS_EMI_CA	      0x40000
-
-/* BIST Control and Status Register0 (for the Packet Memory) */
-#define REG_BIST0_CTRL              0x141c
-#define     BIST0_NOW                   0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */
-/* BIST process and reset to zero when BIST is done */
-#define     BIST0_SRAM_FAIL             0x2 /* 1: The SRAM failure is un-repairable because it has address */
-/* decoder failure or more than 1 cell stuck-to-x failure */
-#define     BIST0_FUSE_FLAG             0x4 /* 1: Indicating one cell has been fixed */
-
-/* BIST Control and Status Register1(for the retry buffer of PCI Express) */
-#define REG_BIST1_CTRL              0x1420
-#define     BIST1_NOW                   0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */
-/* BIST process and reset to zero when BIST is done */
-#define     BIST1_SRAM_FAIL             0x2 /* 1: The SRAM failure is un-repairable because it has address */
-/* decoder failure or more than 1 cell stuck-to-x failure.*/
-#define     BIST1_FUSE_FLAG             0x4
-
-/* SerDes Lock Detect Control and Status Register */
-#define REG_SERDES_LOCK             0x1424
-#define     SERDES_LOCK_DETECT          1  /* 1: SerDes lock detected . This signal comes from Analog SerDes */
-#define     SERDES_LOCK_DETECT_EN       2  /* 1: Enable SerDes Lock detect function */
-
-/* MAC Control Register  */
-#define REG_MAC_CTRL                0x1480
-#define     MAC_CTRL_TX_EN              1  /* 1: Transmit Enable */
-#define     MAC_CTRL_RX_EN              2  /* 1: Receive Enable */
-#define     MAC_CTRL_TX_FLOW            4  /* 1: Transmit Flow Control Enable */
-#define     MAC_CTRL_RX_FLOW            8  /* 1: Receive Flow Control Enable */
-#define     MAC_CTRL_LOOPBACK           0x10      /* 1: Loop back at G/MII Interface */
-#define     MAC_CTRL_DUPLX              0x20      /* 1: Full-duplex mode  0: Half-duplex mode */
-#define     MAC_CTRL_ADD_CRC            0x40      /* 1: Instruct MAC to attach CRC on all egress Ethernet frames */
-#define     MAC_CTRL_PAD                0x80      /* 1: Instruct MAC to pad short frames to 60-bytes, and then attach CRC. This bit has higher priority over CRC_EN */
-#define     MAC_CTRL_LENCHK             0x100     /* 1: Instruct MAC to check if length field matches the real packet length */
-#define     MAC_CTRL_HUGE_EN            0x200     /* 1: receive Jumbo frame enable */
-#define     MAC_CTRL_PRMLEN_SHIFT       10        /* Preamble length */
-#define     MAC_CTRL_PRMLEN_MASK        0xf
-#define     MAC_CTRL_RMV_VLAN           0x4000    /* 1: to remove VLAN Tag automatically from all receive packets */
-#define     MAC_CTRL_PROMIS_EN          0x8000    /* 1: Promiscuous Mode Enable */
-#define     MAC_CTRL_TX_PAUSE           0x10000   /* 1: transmit test pause */
-#define     MAC_CTRL_SCNT               0x20000   /* 1: shortcut slot time counter */
-#define     MAC_CTRL_SRST_TX            0x40000   /* 1: synchronized reset Transmit MAC module */
-#define     MAC_CTRL_TX_SIMURST         0x80000   /* 1: transmit simulation reset */
-#define     MAC_CTRL_SPEED_SHIFT        20        /* 10: gigabit 01:10M/100M */
-#define     MAC_CTRL_SPEED_MASK         0x300000
-#define     MAC_CTRL_SPEED_1000         2
-#define     MAC_CTRL_SPEED_10_100       1
-#define     MAC_CTRL_DBG_TX_BKPRESURE   0x400000  /* 1: transmit maximum backoff (half-duplex test bit) */
-#define     MAC_CTRL_TX_HUGE            0x800000  /* 1: transmit huge enable */
-#define     MAC_CTRL_RX_CHKSUM_EN       0x1000000 /* 1: RX checksum enable */
-#define     MAC_CTRL_MC_ALL_EN          0x2000000 /* 1: upload all multicast frame without error to system */
-#define     MAC_CTRL_BC_EN              0x4000000 /* 1: upload all broadcast frame without error to system */
-#define     MAC_CTRL_DBG                0x8000000 /* 1: upload all received frame to system (Debug Mode) */
-
-/* MAC IPG/IFG Control Register  */
-#define REG_MAC_IPG_IFG             0x1484
-#define     MAC_IPG_IFG_IPGT_SHIFT      0     /* Desired back to back inter-packet gap. The default is 96-bit time */
-#define     MAC_IPG_IFG_IPGT_MASK       0x7f
-#define     MAC_IPG_IFG_MIFG_SHIFT      8     /* Minimum number of IFG to enforce in between RX frames */
-#define     MAC_IPG_IFG_MIFG_MASK       0xff  /* Frame gap below such IFP is dropped */
-#define     MAC_IPG_IFG_IPGR1_SHIFT     16    /* 64bit Carrier-Sense window */
-#define     MAC_IPG_IFG_IPGR1_MASK      0x7f
-#define     MAC_IPG_IFG_IPGR2_SHIFT     24    /* 96-bit IPG window */
-#define     MAC_IPG_IFG_IPGR2_MASK      0x7f
-
-/* MAC STATION ADDRESS  */
-#define REG_MAC_STA_ADDR            0x1488
-
-/* Hash table for multicast address */
-#define REG_RX_HASH_TABLE           0x1490
-
-
-/* MAC Half-Duplex Control Register */
-#define REG_MAC_HALF_DUPLX_CTRL     0x1498
-#define     MAC_HALF_DUPLX_CTRL_LCOL_SHIFT   0      /* Collision Window */
-#define     MAC_HALF_DUPLX_CTRL_LCOL_MASK    0x3ff
-#define     MAC_HALF_DUPLX_CTRL_RETRY_SHIFT  12     /* Retransmission maximum, afterwards the packet will be discarded */
-#define     MAC_HALF_DUPLX_CTRL_RETRY_MASK   0xf
-#define     MAC_HALF_DUPLX_CTRL_EXC_DEF_EN   0x10000 /* 1: Allow the transmission of a packet which has been excessively deferred */
-#define     MAC_HALF_DUPLX_CTRL_NO_BACK_C    0x20000 /* 1: No back-off on collision, immediately start the retransmission */
-#define     MAC_HALF_DUPLX_CTRL_NO_BACK_P    0x40000 /* 1: No back-off on backpressure, immediately start the transmission after back pressure */
-#define     MAC_HALF_DUPLX_CTRL_ABEBE        0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */
-#define     MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT  20      /* Maximum binary exponential number */
-#define     MAC_HALF_DUPLX_CTRL_ABEBT_MASK   0xf
-#define     MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24      /* IPG to start JAM for collision based flow control in half-duplex */
-#define     MAC_HALF_DUPLX_CTRL_JAMIPG_MASK  0xf     /* mode. In unit of 8-bit time */
-
-/* Maximum Frame Length Control Register   */
-#define REG_MTU                     0x149c
-
-/* Wake-On-Lan control register */
-#define REG_WOL_CTRL                0x14a0
-#define     WOL_PATTERN_EN                  0x00000001
-#define     WOL_PATTERN_PME_EN              0x00000002
-#define     WOL_MAGIC_EN                    0x00000004
-#define     WOL_MAGIC_PME_EN                0x00000008
-#define     WOL_LINK_CHG_EN                 0x00000010
-#define     WOL_LINK_CHG_PME_EN             0x00000020
-#define     WOL_PATTERN_ST                  0x00000100
-#define     WOL_MAGIC_ST                    0x00000200
-#define     WOL_LINKCHG_ST                  0x00000400
-#define     WOL_CLK_SWITCH_EN               0x00008000
-#define     WOL_PT0_EN                      0x00010000
-#define     WOL_PT1_EN                      0x00020000
-#define     WOL_PT2_EN                      0x00040000
-#define     WOL_PT3_EN                      0x00080000
-#define     WOL_PT4_EN                      0x00100000
-#define     WOL_PT5_EN                      0x00200000
-#define     WOL_PT6_EN                      0x00400000
-/* WOL Length ( 2 DWORD ) */
-#define REG_WOL_PATTERN_LEN         0x14a4
-#define     WOL_PT_LEN_MASK                 0x7f
-#define     WOL_PT0_LEN_SHIFT               0
-#define     WOL_PT1_LEN_SHIFT               8
-#define     WOL_PT2_LEN_SHIFT               16
-#define     WOL_PT3_LEN_SHIFT               24
-#define     WOL_PT4_LEN_SHIFT               0
-#define     WOL_PT5_LEN_SHIFT               8
-#define     WOL_PT6_LEN_SHIFT               16
-
-/* Internal SRAM Partition Register */
-#define REG_SRAM_TRD_ADDR           0x1518
-#define REG_SRAM_TRD_LEN            0x151C
-#define REG_SRAM_RXF_ADDR           0x1520
-#define REG_SRAM_RXF_LEN            0x1524
-#define REG_SRAM_TXF_ADDR           0x1528
-#define REG_SRAM_TXF_LEN            0x152C
-#define REG_SRAM_TCPH_ADDR          0x1530
-#define REG_SRAM_PKTH_ADDR          0x1532
-
-/* Load Ptr Register */
-#define REG_LOAD_PTR                0x1534  /* Software sets this bit after the initialization of the head and tail */
-
-/*
- * addresses of all descriptors, as well as the following descriptor
- * control register, which triggers each function block to load the head
- * pointer to prepare for the operation. This bit is then self-cleared
- * after one cycle.
- */
-
-/* Descriptor Control register  */
-#define REG_RXF3_BASE_ADDR_HI           0x153C
-#define REG_DESC_BASE_ADDR_HI           0x1540
-#define REG_RXF0_BASE_ADDR_HI           0x1540 /* share with DESC BASE ADDR HI */
-#define REG_HOST_RXF0_PAGE0_LO          0x1544
-#define REG_HOST_RXF0_PAGE1_LO          0x1548
-#define REG_TPD_BASE_ADDR_LO            0x154C
-#define REG_RXF1_BASE_ADDR_HI           0x1550
-#define REG_RXF2_BASE_ADDR_HI           0x1554
-#define REG_HOST_RXFPAGE_SIZE           0x1558
-#define REG_TPD_RING_SIZE               0x155C
-/* RSS about */
-#define REG_RSS_KEY0                    0x14B0
-#define REG_RSS_KEY1                    0x14B4
-#define REG_RSS_KEY2                    0x14B8
-#define REG_RSS_KEY3                    0x14BC
-#define REG_RSS_KEY4                    0x14C0
-#define REG_RSS_KEY5                    0x14C4
-#define REG_RSS_KEY6                    0x14C8
-#define REG_RSS_KEY7                    0x14CC
-#define REG_RSS_KEY8                    0x14D0
-#define REG_RSS_KEY9                    0x14D4
-#define REG_IDT_TABLE4                  0x14E0
-#define REG_IDT_TABLE5                  0x14E4
-#define REG_IDT_TABLE6                  0x14E8
-#define REG_IDT_TABLE7                  0x14EC
-#define REG_IDT_TABLE0                  0x1560
-#define REG_IDT_TABLE1                  0x1564
-#define REG_IDT_TABLE2                  0x1568
-#define REG_IDT_TABLE3                  0x156C
-#define REG_IDT_TABLE                   REG_IDT_TABLE0
-#define REG_RSS_HASH_VALUE              0x1570
-#define REG_RSS_HASH_FLAG               0x1574
-#define REG_BASE_CPU_NUMBER             0x157C
-
-
-/* TXQ Control Register */
-#define REG_TXQ_CTRL                0x1580
-#define     TXQ_CTRL_NUM_TPD_BURST_MASK     0xF
-#define     TXQ_CTRL_NUM_TPD_BURST_SHIFT    0
-#define     TXQ_CTRL_EN                     0x20  /* 1: Enable TXQ */
-#define     TXQ_CTRL_ENH_MODE               0x40  /* Performance enhancement mode, in which up to two back-to-back DMA read commands might be dispatched. */
-#define     TXQ_CTRL_TXF_BURST_NUM_SHIFT    16    /* Number of data byte to read in a cache-aligned burst. Each SRAM entry is 8-byte in length. */
-#define     TXQ_CTRL_TXF_BURST_NUM_MASK     0xffff
-
-/* Jumbo packet Threshold for task offload */
-#define REG_TX_EARLY_TH                     0x1584 /* Jumbo frame threshold in QWORD unit. Packet greater than */
-/* JUMBO_TASK_OFFLOAD_THRESHOLD will not be task offloaded. */
-#define     TX_TX_EARLY_TH_MASK             0x7ff
-#define     TX_TX_EARLY_TH_SHIFT            0
-
-
-/* RXQ Control Register */
-#define REG_RXQ_CTRL                0x15A0
-#define         RXQ_CTRL_PBA_ALIGN_32                   0   /* rx-packet alignment */
-#define         RXQ_CTRL_PBA_ALIGN_64                   1
-#define         RXQ_CTRL_PBA_ALIGN_128                  2
-#define         RXQ_CTRL_PBA_ALIGN_256                  3
-#define         RXQ_CTRL_Q1_EN				0x10
-#define         RXQ_CTRL_Q2_EN				0x20
-#define         RXQ_CTRL_Q3_EN				0x40
-#define         RXQ_CTRL_IPV6_XSUM_VERIFY_EN		0x80
-#define         RXQ_CTRL_HASH_TLEN_SHIFT                8
-#define         RXQ_CTRL_HASH_TLEN_MASK                 0xFF
-#define         RXQ_CTRL_HASH_TYPE_IPV4                 0x10000
-#define         RXQ_CTRL_HASH_TYPE_IPV4_TCP             0x20000
-#define         RXQ_CTRL_HASH_TYPE_IPV6                 0x40000
-#define         RXQ_CTRL_HASH_TYPE_IPV6_TCP             0x80000
-#define         RXQ_CTRL_RSS_MODE_DISABLE               0
-#define         RXQ_CTRL_RSS_MODE_SQSINT                0x4000000
-#define         RXQ_CTRL_RSS_MODE_MQUESINT              0x8000000
-#define         RXQ_CTRL_RSS_MODE_MQUEMINT              0xC000000
-#define         RXQ_CTRL_NIP_QUEUE_SEL_TBL              0x10000000
-#define         RXQ_CTRL_HASH_ENABLE                    0x20000000
-#define         RXQ_CTRL_CUT_THRU_EN                    0x40000000
-#define         RXQ_CTRL_EN                             0x80000000
-
-/* Rx jumbo packet threshold and rrd  retirement timer  */
-#define REG_RXQ_JMBOSZ_RRDTIM       0x15A4
-/*
- * Jumbo packet threshold for non-VLAN packet, in QWORD (64-bit) unit.
- * When the packet length greater than or equal to this value, RXQ
- * shall start cut-through forwarding of the received packet.
- */
-#define         RXQ_JMBOSZ_TH_MASK      0x7ff
-#define         RXQ_JMBOSZ_TH_SHIFT         0  /* RRD retirement timer. Decrement by 1 after every 512ns passes*/
-#define         RXQ_JMBO_LKAH_MASK          0xf
-#define         RXQ_JMBO_LKAH_SHIFT         11
-
-/* RXF flow control register */
-#define REG_RXQ_RXF_PAUSE_THRESH    0x15A8
-#define     RXQ_RXF_PAUSE_TH_HI_SHIFT       0
-#define     RXQ_RXF_PAUSE_TH_HI_MASK        0xfff
-#define     RXQ_RXF_PAUSE_TH_LO_SHIFT       16
-#define     RXQ_RXF_PAUSE_TH_LO_MASK        0xfff
-
-
-/* DMA Engine Control Register */
-#define REG_DMA_CTRL                0x15C0
-#define     DMA_CTRL_DMAR_IN_ORDER          0x1
-#define     DMA_CTRL_DMAR_ENH_ORDER         0x2
-#define     DMA_CTRL_DMAR_OUT_ORDER         0x4
-#define     DMA_CTRL_RCB_VALUE              0x8
-#define     DMA_CTRL_DMAR_BURST_LEN_SHIFT   4
-#define     DMA_CTRL_DMAR_BURST_LEN_MASK    7
-#define     DMA_CTRL_DMAW_BURST_LEN_SHIFT   7
-#define     DMA_CTRL_DMAW_BURST_LEN_MASK    7
-#define     DMA_CTRL_DMAR_REQ_PRI           0x400
-#define     DMA_CTRL_DMAR_DLY_CNT_MASK      0x1F
-#define     DMA_CTRL_DMAR_DLY_CNT_SHIFT     11
-#define     DMA_CTRL_DMAW_DLY_CNT_MASK      0xF
-#define     DMA_CTRL_DMAW_DLY_CNT_SHIFT     16
-#define     DMA_CTRL_TXCMB_EN               0x100000
-#define     DMA_CTRL_RXCMB_EN				0x200000
-
-
-/* CMB/SMB Control Register */
-#define REG_SMB_STAT_TIMER                      0x15C4
-#define REG_TRIG_RRD_THRESH                     0x15CA
-#define REG_TRIG_TPD_THRESH                     0x15C8
-#define REG_TRIG_TXTIMER                        0x15CC
-#define REG_TRIG_RXTIMER                        0x15CE
-
-/* HOST RXF Page 1,2,3 address */
-#define REG_HOST_RXF1_PAGE0_LO                  0x15D0
-#define REG_HOST_RXF1_PAGE1_LO                  0x15D4
-#define REG_HOST_RXF2_PAGE0_LO                  0x15D8
-#define REG_HOST_RXF2_PAGE1_LO                  0x15DC
-#define REG_HOST_RXF3_PAGE0_LO                  0x15E0
-#define REG_HOST_RXF3_PAGE1_LO                  0x15E4
-
-/* Mail box */
-#define REG_MB_RXF1_RADDR                       0x15B4
-#define REG_MB_RXF2_RADDR                       0x15B8
-#define REG_MB_RXF3_RADDR                       0x15BC
-#define REG_MB_TPD_PROD_IDX                     0x15F0
-
-/* RXF-Page 0-3  PageNo & Valid bit */
-#define REG_HOST_RXF0_PAGE0_VLD     0x15F4
-#define     HOST_RXF_VALID              1
-#define     HOST_RXF_PAGENO_SHIFT       1
-#define     HOST_RXF_PAGENO_MASK        0x7F
-#define REG_HOST_RXF0_PAGE1_VLD     0x15F5
-#define REG_HOST_RXF1_PAGE0_VLD     0x15F6
-#define REG_HOST_RXF1_PAGE1_VLD     0x15F7
-#define REG_HOST_RXF2_PAGE0_VLD     0x15F8
-#define REG_HOST_RXF2_PAGE1_VLD     0x15F9
-#define REG_HOST_RXF3_PAGE0_VLD     0x15FA
-#define REG_HOST_RXF3_PAGE1_VLD     0x15FB
-
-/* Interrupt Status Register */
-#define REG_ISR    0x1600
-#define  ISR_SMB   		1
-#define  ISR_TIMER		2       /* Interrupt when Timer is counted down to zero */
-/*
- * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set
- * in Table 51 Selene Master Control Register (Offset 0x1400).
- */
-#define  ISR_MANUAL         	4
-#define  ISR_HW_RXF_OV          8        /* RXF overflow interrupt */
-#define  ISR_HOST_RXF0_OV       0x10
-#define  ISR_HOST_RXF1_OV       0x20
-#define  ISR_HOST_RXF2_OV       0x40
-#define  ISR_HOST_RXF3_OV       0x80
-#define  ISR_TXF_UN             0x100
-#define  ISR_RX0_PAGE_FULL      0x200
-#define  ISR_DMAR_TO_RST        0x400
-#define  ISR_DMAW_TO_RST        0x800
-#define  ISR_GPHY               0x1000
-#define  ISR_TX_CREDIT          0x2000
-#define  ISR_GPHY_LPW           0x4000    /* GPHY low power state interrupt */
-#define  ISR_RX_PKT             0x10000   /* One packet received, triggered by RFD */
-#define  ISR_TX_PKT             0x20000   /* One packet transmitted, triggered by TPD */
-#define  ISR_TX_DMA             0x40000
-#define  ISR_RX_PKT_1           0x80000
-#define  ISR_RX_PKT_2           0x100000
-#define  ISR_RX_PKT_3           0x200000
-#define  ISR_MAC_RX             0x400000
-#define  ISR_MAC_TX             0x800000
-#define  ISR_UR_DETECTED        0x1000000
-#define  ISR_FERR_DETECTED      0x2000000
-#define  ISR_NFERR_DETECTED     0x4000000
-#define  ISR_CERR_DETECTED      0x8000000
-#define  ISR_PHY_LINKDOWN       0x10000000
-#define  ISR_DIS_INT            0x80000000
-
-
-/* Interrupt Mask Register */
-#define REG_IMR 0x1604
-
-
-#define IMR_NORMAL_MASK (\
-		ISR_SMB	        |\
-		ISR_TXF_UN      |\
-		ISR_HW_RXF_OV   |\
-		ISR_HOST_RXF0_OV|\
-		ISR_MANUAL      |\
-		ISR_GPHY        |\
-		ISR_GPHY_LPW    |\
-		ISR_DMAR_TO_RST |\
-		ISR_DMAW_TO_RST |\
-		ISR_PHY_LINKDOWN|\
-		ISR_RX_PKT      |\
-		ISR_TX_PKT)
-
-#define ISR_TX_EVENT (ISR_TXF_UN | ISR_TX_PKT)
-#define ISR_RX_EVENT (ISR_HOST_RXF0_OV | ISR_HW_RXF_OV | ISR_RX_PKT)
-
-#define REG_MAC_RX_STATUS_BIN 0x1700
-#define REG_MAC_RX_STATUS_END 0x175c
-#define REG_MAC_TX_STATUS_BIN 0x1760
-#define REG_MAC_TX_STATUS_END 0x17c0
-
-/* Hardware Offset Register */
-#define REG_HOST_RXF0_PAGEOFF 0x1800
-#define REG_TPD_CONS_IDX      0x1804
-#define REG_HOST_RXF1_PAGEOFF 0x1808
-#define REG_HOST_RXF2_PAGEOFF 0x180C
-#define REG_HOST_RXF3_PAGEOFF 0x1810
-
-/* RXF-Page 0-3 Offset DMA Address */
-#define REG_HOST_RXF0_MB0_LO  0x1820
-#define REG_HOST_RXF0_MB1_LO  0x1824
-#define REG_HOST_RXF1_MB0_LO  0x1828
-#define REG_HOST_RXF1_MB1_LO  0x182C
-#define REG_HOST_RXF2_MB0_LO  0x1830
-#define REG_HOST_RXF2_MB1_LO  0x1834
-#define REG_HOST_RXF3_MB0_LO  0x1838
-#define REG_HOST_RXF3_MB1_LO  0x183C
-
-/* Tpd CMB DMA Address */
-#define REG_HOST_TX_CMB_LO    0x1840
-#define REG_HOST_SMB_ADDR_LO  0x1844
-
-/* DEBUG ADDR */
-#define REG_DEBUG_DATA0 0x1900
-#define REG_DEBUG_DATA1 0x1904
-
-/***************************** MII definition ***************************************/
-/* PHY Common Register */
-#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_LBRERROR                    0x18
-#define MII_RESV2                       0x1a
-
-#define MII_DBG_ADDR			0x1D
-#define MII_DBG_DATA			0x1E
-
-/* Autoneg Advertisement Register */
-#define MII_AR_DEFAULT_CAP_MASK                 0
-
-/* 1000BASE-T Control Register */
-#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 */
-#define MII_AT001_PSCR_POLARITY_REVERSAL        0x0002  /* 1=Polarity Reversal enabled */
-#define MII_AT001_PSCR_SQE_TEST                 0x0004  /* 1=SQE Test enabled */
-#define MII_AT001_PSCR_MAC_POWERDOWN            0x0008
-#define MII_AT001_PSCR_CLK125_DISABLE           0x0010  /* 1=CLK125 low,
-							 * 0=CLK125 toggling
-							 */
-#define MII_AT001_PSCR_MDI_MANUAL_MODE          0x0000  /* MDI Crossover Mode bits 6:5 */
-/* Manual MDI configuration */
-#define MII_AT001_PSCR_MDIX_MANUAL_MODE         0x0020  /* Manual MDIX configuration */
-#define MII_AT001_PSCR_AUTO_X_1000T             0x0040  /* 1000BASE-T: Auto crossover,
-							 *  100BASE-TX/10BASE-T:
-							 *  MDI Mode
-							 */
-#define MII_AT001_PSCR_AUTO_X_MODE              0x0060  /* Auto crossover enabled
-							 * all speeds.
-							 */
-#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE     0x0080
-/* 1=Enable Extended 10BASE-T distance
- * (Lower 10BASE-T RX Threshold)
- * 0=Normal 10BASE-T RX Threshold */
-#define MII_AT001_PSCR_MII_5BIT_ENABLE          0x0100
-/* 1=5-Bit interface in 100BASE-TX
- * 0=MII interface in 100BASE-TX */
-#define MII_AT001_PSCR_SCRAMBLER_DISABLE        0x0200  /* 1=Scrambler disable */
-#define MII_AT001_PSCR_FORCE_LINK_GOOD          0x0400  /* 1=Force link good */
-#define MII_AT001_PSCR_ASSERT_CRS_ON_TX         0x0800  /* 1=Assert CRS on Transmit */
-#define MII_AT001_PSCR_POLARITY_REVERSAL_SHIFT    1
-#define MII_AT001_PSCR_AUTO_X_MODE_SHIFT          5
-#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
-/* AT001 PHY Specific Status Register */
-#define MII_AT001_PSSR_SPD_DPLX_RESOLVED        0x0800  /* 1=Speed & Duplex resolved */
-#define MII_AT001_PSSR_DPLX                     0x2000  /* 1=Duplex 0=Half Duplex */
-#define MII_AT001_PSSR_SPEED                    0xC000  /* Speed, bits 14:15 */
-#define MII_AT001_PSSR_10MBS                    0x0000  /* 00=10Mbs */
-#define MII_AT001_PSSR_100MBS                   0x4000  /* 01=100Mbs */
-#define MII_AT001_PSSR_1000MBS                  0x8000  /* 10=1000Mbs */
-
-#endif /*_ATHL1E_HW_H_*/
diff -druN linux-libre-3.1-gnu/drivers/net/atl1e/atl1e_main.c linux-libre-3.2-gnu/drivers/net/atl1e/atl1e_main.c
--- linux-libre-3.1-gnu/drivers/net/atl1e/atl1e_main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atl1e/atl1e_main.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2558 +0,0 @@
-/*
- * Copyright(c) 2007 Atheros Corporation. All rights reserved.
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You 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 "atl1e.h"
-
-#define DRV_VERSION "1.0.0.7-NAPI"
-
-char atl1e_driver_name[] = "ATL1E";
-char atl1e_driver_version[] = DRV_VERSION;
-#define PCI_DEVICE_ID_ATTANSIC_L1E      0x1026
-/*
- * atl1e_pci_tbl - PCI Device ID Table
- *
- * Wildcard entries (PCI_ANY_ID) should come last
- * Last entry must be all 0s
- *
- * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
- *   Class, Class Mask, private data (not used) }
- */
-static DEFINE_PCI_DEVICE_TABLE(atl1e_pci_tbl) = {
-	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1E)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, 0x1066)},
-	/* required last entry */
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, atl1e_pci_tbl);
-
-MODULE_AUTHOR("Atheros Corporation, <xiong.huang@atheros.com>, Jie Yang <jie.yang@atheros.com>");
-MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-
-static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter);
-
-static const u16
-atl1e_rx_page_vld_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] =
-{
-	{REG_HOST_RXF0_PAGE0_VLD, REG_HOST_RXF0_PAGE1_VLD},
-	{REG_HOST_RXF1_PAGE0_VLD, REG_HOST_RXF1_PAGE1_VLD},
-	{REG_HOST_RXF2_PAGE0_VLD, REG_HOST_RXF2_PAGE1_VLD},
-	{REG_HOST_RXF3_PAGE0_VLD, REG_HOST_RXF3_PAGE1_VLD}
-};
-
-static const u16 atl1e_rx_page_hi_addr_regs[AT_MAX_RECEIVE_QUEUE] =
-{
-	REG_RXF0_BASE_ADDR_HI,
-	REG_RXF1_BASE_ADDR_HI,
-	REG_RXF2_BASE_ADDR_HI,
-	REG_RXF3_BASE_ADDR_HI
-};
-
-static const u16
-atl1e_rx_page_lo_addr_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] =
-{
-	{REG_HOST_RXF0_PAGE0_LO, REG_HOST_RXF0_PAGE1_LO},
-	{REG_HOST_RXF1_PAGE0_LO, REG_HOST_RXF1_PAGE1_LO},
-	{REG_HOST_RXF2_PAGE0_LO, REG_HOST_RXF2_PAGE1_LO},
-	{REG_HOST_RXF3_PAGE0_LO, REG_HOST_RXF3_PAGE1_LO}
-};
-
-static const u16
-atl1e_rx_page_write_offset_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] =
-{
-	{REG_HOST_RXF0_MB0_LO,  REG_HOST_RXF0_MB1_LO},
-	{REG_HOST_RXF1_MB0_LO,  REG_HOST_RXF1_MB1_LO},
-	{REG_HOST_RXF2_MB0_LO,  REG_HOST_RXF2_MB1_LO},
-	{REG_HOST_RXF3_MB0_LO,  REG_HOST_RXF3_MB1_LO}
-};
-
-static const u16 atl1e_pay_load_size[] = {
-	128, 256, 512, 1024, 2048, 4096,
-};
-
-/*
- * atl1e_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- */
-static inline void atl1e_irq_enable(struct atl1e_adapter *adapter)
-{
-	if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
-		AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
-		AT_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK);
-		AT_WRITE_FLUSH(&adapter->hw);
-	}
-}
-
-/*
- * atl1e_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- */
-static inline void atl1e_irq_disable(struct atl1e_adapter *adapter)
-{
-	atomic_inc(&adapter->irq_sem);
-	AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
-	AT_WRITE_FLUSH(&adapter->hw);
-	synchronize_irq(adapter->pdev->irq);
-}
-
-/*
- * atl1e_irq_reset - reset interrupt confiure on the NIC
- * @adapter: board private structure
- */
-static inline void atl1e_irq_reset(struct atl1e_adapter *adapter)
-{
-	atomic_set(&adapter->irq_sem, 0);
-	AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
-	AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
-	AT_WRITE_FLUSH(&adapter->hw);
-}
-
-/*
- * atl1e_phy_config - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
- */
-static void atl1e_phy_config(unsigned long data)
-{
-	struct atl1e_adapter *adapter = (struct atl1e_adapter *) data;
-	struct atl1e_hw *hw = &adapter->hw;
-	unsigned long flags;
-
-	spin_lock_irqsave(&adapter->mdio_lock, flags);
-	atl1e_restart_autoneg(hw);
-	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
-}
-
-void atl1e_reinit_locked(struct atl1e_adapter *adapter)
-{
-
-	WARN_ON(in_interrupt());
-	while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
-		msleep(1);
-	atl1e_down(adapter);
-	atl1e_up(adapter);
-	clear_bit(__AT_RESETTING, &adapter->flags);
-}
-
-static void atl1e_reset_task(struct work_struct *work)
-{
-	struct atl1e_adapter *adapter;
-	adapter = container_of(work, struct atl1e_adapter, reset_task);
-
-	atl1e_reinit_locked(adapter);
-}
-
-static int atl1e_check_link(struct atl1e_adapter *adapter)
-{
-	struct atl1e_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	int err = 0;
-	u16 speed, duplex, phy_data;
-
-	/* MII_BMSR must read twice */
-	atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
-	atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
-	if ((phy_data & BMSR_LSTATUS) == 0) {
-		/* link down */
-		if (netif_carrier_ok(netdev)) { /* old link state: Up */
-			u32 value;
-			/* disable rx */
-			value = AT_READ_REG(hw, REG_MAC_CTRL);
-			value &= ~MAC_CTRL_RX_EN;
-			AT_WRITE_REG(hw, REG_MAC_CTRL, value);
-			adapter->link_speed = SPEED_0;
-			netif_carrier_off(netdev);
-			netif_stop_queue(netdev);
-		}
-	} else {
-		/* Link Up */
-		err = atl1e_get_speed_and_duplex(hw, &speed, &duplex);
-		if (unlikely(err))
-			return err;
-
-		/* link result is our setting */
-		if (adapter->link_speed != speed ||
-		    adapter->link_duplex != duplex) {
-			adapter->link_speed  = speed;
-			adapter->link_duplex = duplex;
-			atl1e_setup_mac_ctrl(adapter);
-			netdev_info(netdev,
-				    "NIC Link is Up <%d Mbps %s Duplex>\n",
-				    adapter->link_speed,
-				    adapter->link_duplex == FULL_DUPLEX ?
-				    "Full" : "Half");
-		}
-
-		if (!netif_carrier_ok(netdev)) {
-			/* Link down -> Up */
-			netif_carrier_on(netdev);
-			netif_wake_queue(netdev);
-		}
-	}
-	return 0;
-}
-
-/*
- * atl1e_link_chg_task - deal with link change event Out of interrupt context
- * @netdev: network interface device structure
- */
-static void atl1e_link_chg_task(struct work_struct *work)
-{
-	struct atl1e_adapter *adapter;
-	unsigned long flags;
-
-	adapter = container_of(work, struct atl1e_adapter, link_chg_task);
-	spin_lock_irqsave(&adapter->mdio_lock, flags);
-	atl1e_check_link(adapter);
-	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
-}
-
-static void atl1e_link_chg_event(struct atl1e_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	u16 phy_data = 0;
-	u16 link_up = 0;
-
-	spin_lock(&adapter->mdio_lock);
-	atl1e_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
-	atl1e_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
-	spin_unlock(&adapter->mdio_lock);
-	link_up = phy_data & BMSR_LSTATUS;
-	/* notify upper layer link down ASAP */
-	if (!link_up) {
-		if (netif_carrier_ok(netdev)) {
-			/* old link state: Up */
-			netdev_info(netdev, "NIC Link is Down\n");
-			adapter->link_speed = SPEED_0;
-			netif_stop_queue(netdev);
-		}
-	}
-	schedule_work(&adapter->link_chg_task);
-}
-
-static void atl1e_del_timer(struct atl1e_adapter *adapter)
-{
-	del_timer_sync(&adapter->phy_config_timer);
-}
-
-static void atl1e_cancel_work(struct atl1e_adapter *adapter)
-{
-	cancel_work_sync(&adapter->reset_task);
-	cancel_work_sync(&adapter->link_chg_task);
-}
-
-/*
- * atl1e_tx_timeout - Respond to a Tx Hang
- * @netdev: network interface device structure
- */
-static void atl1e_tx_timeout(struct net_device *netdev)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-
-	/* Do the reset outside of interrupt context */
-	schedule_work(&adapter->reset_task);
-}
-
-/*
- * atl1e_set_multi - Multicast and Promiscuous mode set
- * @netdev: network interface device structure
- *
- * The set_multi entry point is called whenever the multicast address
- * list or the network interface flags are updated.  This routine is
- * responsible for configuring the hardware for proper multicast,
- * promiscuous mode, and all-multi behavior.
- */
-static void atl1e_set_multi(struct net_device *netdev)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	struct atl1e_hw *hw = &adapter->hw;
-	struct netdev_hw_addr *ha;
-	u32 mac_ctrl_data = 0;
-	u32 hash_value;
-
-	/* Check for Promiscuous and All Multicast modes */
-	mac_ctrl_data = AT_READ_REG(hw, REG_MAC_CTRL);
-
-	if (netdev->flags & IFF_PROMISC) {
-		mac_ctrl_data |= MAC_CTRL_PROMIS_EN;
-	} else if (netdev->flags & IFF_ALLMULTI) {
-		mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;
-		mac_ctrl_data &= ~MAC_CTRL_PROMIS_EN;
-	} else {
-		mac_ctrl_data &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
-	}
-
-	AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
-
-	/* clear the old settings from the multicast hash table */
-	AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
-	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
-
-	/* comoute mc addresses' hash value ,and put it into hash table */
-	netdev_for_each_mc_addr(ha, netdev) {
-		hash_value = atl1e_hash_mc_addr(hw, ha->addr);
-		atl1e_hash_set(hw, hash_value);
-	}
-}
-
-static void __atl1e_vlan_mode(u32 features, u32 *mac_ctrl_data)
-{
-	if (features & NETIF_F_HW_VLAN_RX) {
-		/* enable VLAN tag insert/strip */
-		*mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
-	} else {
-		/* disable VLAN tag insert/strip */
-		*mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN;
-	}
-}
-
-static void atl1e_vlan_mode(struct net_device *netdev, u32 features)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	u32 mac_ctrl_data = 0;
-
-	netdev_dbg(adapter->netdev, "%s\n", __func__);
-
-	atl1e_irq_disable(adapter);
-	mac_ctrl_data = AT_READ_REG(&adapter->hw, REG_MAC_CTRL);
-	__atl1e_vlan_mode(features, &mac_ctrl_data);
-	AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data);
-	atl1e_irq_enable(adapter);
-}
-
-static void atl1e_restore_vlan(struct atl1e_adapter *adapter)
-{
-	netdev_dbg(adapter->netdev, "%s\n", __func__);
-	atl1e_vlan_mode(adapter->netdev, adapter->netdev->features);
-}
-
-/*
- * atl1e_set_mac - Change the Ethernet Address of the NIC
- * @netdev: network interface device structure
- * @p: pointer to an address structure
- *
- * Returns 0 on success, negative on failure
- */
-static int atl1e_set_mac_addr(struct net_device *netdev, void *p)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	struct sockaddr *addr = p;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	if (netif_running(netdev))
-		return -EBUSY;
-
-	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
-
-	atl1e_hw_set_mac_addr(&adapter->hw);
-
-	return 0;
-}
-
-static u32 atl1e_fix_features(struct net_device *netdev, u32 features)
-{
-	/*
-	 * Since there is no support for separate rx/tx vlan accel
-	 * enable/disable make sure tx flag is always in same state as rx.
-	 */
-	if (features & NETIF_F_HW_VLAN_RX)
-		features |= NETIF_F_HW_VLAN_TX;
-	else
-		features &= ~NETIF_F_HW_VLAN_TX;
-
-	return features;
-}
-
-static int atl1e_set_features(struct net_device *netdev, u32 features)
-{
-	u32 changed = netdev->features ^ features;
-
-	if (changed & NETIF_F_HW_VLAN_RX)
-		atl1e_vlan_mode(netdev, features);
-
-	return 0;
-}
-
-/*
- * atl1e_change_mtu - Change the Maximum Transfer Unit
- * @netdev: network interface device structure
- * @new_mtu: new value for maximum frame size
- *
- * Returns 0 on success, negative on failure
- */
-static int atl1e_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	int old_mtu   = netdev->mtu;
-	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
-
-	if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
-			(max_frame > MAX_JUMBO_FRAME_SIZE)) {
-		netdev_warn(adapter->netdev, "invalid MTU setting\n");
-		return -EINVAL;
-	}
-	/* set MTU */
-	if (old_mtu != new_mtu && netif_running(netdev)) {
-		while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
-			msleep(1);
-		netdev->mtu = new_mtu;
-		adapter->hw.max_frame_size = new_mtu;
-		adapter->hw.rx_jumbo_th = (max_frame + 7) >> 3;
-		atl1e_down(adapter);
-		atl1e_up(adapter);
-		clear_bit(__AT_RESETTING, &adapter->flags);
-	}
-	return 0;
-}
-
-/*
- *  caller should hold mdio_lock
- */
-static int atl1e_mdio_read(struct net_device *netdev, int phy_id, int reg_num)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	u16 result;
-
-	atl1e_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result);
-	return result;
-}
-
-static void atl1e_mdio_write(struct net_device *netdev, int phy_id,
-			     int reg_num, int val)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-
-	atl1e_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val);
-}
-
-/*
- * atl1e_mii_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- */
-static int atl1e_mii_ioctl(struct net_device *netdev,
-			   struct ifreq *ifr, int cmd)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	struct mii_ioctl_data *data = if_mii(ifr);
-	unsigned long flags;
-	int retval = 0;
-
-	if (!netif_running(netdev))
-		return -EINVAL;
-
-	spin_lock_irqsave(&adapter->mdio_lock, flags);
-	switch (cmd) {
-	case SIOCGMIIPHY:
-		data->phy_id = 0;
-		break;
-
-	case SIOCGMIIREG:
-		if (atl1e_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
-				    &data->val_out)) {
-			retval = -EIO;
-			goto out;
-		}
-		break;
-
-	case SIOCSMIIREG:
-		if (data->reg_num & ~(0x1F)) {
-			retval = -EFAULT;
-			goto out;
-		}
-
-		netdev_dbg(adapter->netdev, "<atl1e_mii_ioctl> write %x %x\n",
-			   data->reg_num, data->val_in);
-		if (atl1e_write_phy_reg(&adapter->hw,
-				     data->reg_num, data->val_in)) {
-			retval = -EIO;
-			goto out;
-		}
-		break;
-
-	default:
-		retval = -EOPNOTSUPP;
-		break;
-	}
-out:
-	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
-	return retval;
-
-}
-
-/*
- * atl1e_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- */
-static int atl1e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	switch (cmd) {
-	case SIOCGMIIPHY:
-	case SIOCGMIIREG:
-	case SIOCSMIIREG:
-		return atl1e_mii_ioctl(netdev, ifr, cmd);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void atl1e_setup_pcicmd(struct pci_dev *pdev)
-{
-	u16 cmd;
-
-	pci_read_config_word(pdev, PCI_COMMAND, &cmd);
-	cmd &= ~(PCI_COMMAND_INTX_DISABLE | PCI_COMMAND_IO);
-	cmd |=  (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
-	pci_write_config_word(pdev, PCI_COMMAND, cmd);
-
-	/*
-	 * some motherboards BIOS(PXE/EFI) driver may set PME
-	 * while they transfer control to OS (Windows/Linux)
-	 * so we should clear this bit before NIC work normally
-	 */
-	pci_write_config_dword(pdev, REG_PM_CTRLSTAT, 0);
-	msleep(1);
-}
-
-/*
- * atl1e_alloc_queues - Allocate memory for all rings
- * @adapter: board private structure to initialize
- *
- */
-static int __devinit atl1e_alloc_queues(struct atl1e_adapter *adapter)
-{
-	return 0;
-}
-
-/*
- * atl1e_sw_init - Initialize general software structures (struct atl1e_adapter)
- * @adapter: board private structure to initialize
- *
- * atl1e_sw_init initializes the Adapter private data structure.
- * Fields are initialized based on PCI device information and
- * OS network device settings (MTU size).
- */
-static int __devinit atl1e_sw_init(struct atl1e_adapter *adapter)
-{
-	struct atl1e_hw *hw   = &adapter->hw;
-	struct pci_dev	*pdev = adapter->pdev;
-	u32 phy_status_data = 0;
-
-	adapter->wol = 0;
-	adapter->link_speed = SPEED_0;   /* hardware init */
-	adapter->link_duplex = FULL_DUPLEX;
-	adapter->num_rx_queues = 1;
-
-	/* PCI config space info */
-	hw->vendor_id = pdev->vendor;
-	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_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
-
-	phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS);
-	/* nic type */
-	if (hw->revision_id >= 0xF0) {
-		hw->nic_type = athr_l2e_revB;
-	} else {
-		if (phy_status_data & PHY_STATUS_100M)
-			hw->nic_type = athr_l1e;
-		else
-			hw->nic_type = athr_l2e_revA;
-	}
-
-	phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS);
-
-	if (phy_status_data & PHY_STATUS_EMI_CA)
-		hw->emi_ca = true;
-	else
-		hw->emi_ca = false;
-
-	hw->phy_configured = false;
-	hw->preamble_len = 7;
-	hw->max_frame_size = adapter->netdev->mtu;
-	hw->rx_jumbo_th = (hw->max_frame_size + ETH_HLEN +
-				VLAN_HLEN + ETH_FCS_LEN + 7) >> 3;
-
-	hw->rrs_type = atl1e_rrs_disable;
-	hw->indirect_tab = 0;
-	hw->base_cpu = 0;
-
-	/* need confirm */
-
-	hw->ict = 50000;                 /* 100ms */
-	hw->smb_timer = 200000;          /* 200ms  */
-	hw->tpd_burst = 5;
-	hw->rrd_thresh = 1;
-	hw->tpd_thresh = adapter->tx_ring.count / 2;
-	hw->rx_count_down = 4;  /* 2us resolution */
-	hw->tx_count_down = hw->imt * 4 / 3;
-	hw->dmar_block = atl1e_dma_req_1024;
-	hw->dmaw_block = atl1e_dma_req_1024;
-	hw->dmar_dly_cnt = 15;
-	hw->dmaw_dly_cnt = 4;
-
-	if (atl1e_alloc_queues(adapter)) {
-		netdev_err(adapter->netdev, "Unable to allocate memory for queues\n");
-		return -ENOMEM;
-	}
-
-	atomic_set(&adapter->irq_sem, 1);
-	spin_lock_init(&adapter->mdio_lock);
-	spin_lock_init(&adapter->tx_lock);
-
-	set_bit(__AT_DOWN, &adapter->flags);
-
-	return 0;
-}
-
-/*
- * atl1e_clean_tx_ring - Free Tx-skb
- * @adapter: board private structure
- */
-static void atl1e_clean_tx_ring(struct atl1e_adapter *adapter)
-{
-	struct atl1e_tx_ring *tx_ring = (struct atl1e_tx_ring *)
-				&adapter->tx_ring;
-	struct atl1e_tx_buffer *tx_buffer = NULL;
-	struct pci_dev *pdev = adapter->pdev;
-	u16 index, ring_count;
-
-	if (tx_ring->desc == NULL || tx_ring->tx_buffer == NULL)
-		return;
-
-	ring_count = tx_ring->count;
-	/* first unmmap dma */
-	for (index = 0; index < ring_count; index++) {
-		tx_buffer = &tx_ring->tx_buffer[index];
-		if (tx_buffer->dma) {
-			if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
-				pci_unmap_single(pdev, tx_buffer->dma,
-					tx_buffer->length, PCI_DMA_TODEVICE);
-			else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
-				pci_unmap_page(pdev, tx_buffer->dma,
-					tx_buffer->length, PCI_DMA_TODEVICE);
-			tx_buffer->dma = 0;
-		}
-	}
-	/* second free skb */
-	for (index = 0; index < ring_count; index++) {
-		tx_buffer = &tx_ring->tx_buffer[index];
-		if (tx_buffer->skb) {
-			dev_kfree_skb_any(tx_buffer->skb);
-			tx_buffer->skb = NULL;
-		}
-	}
-	/* Zero out Tx-buffers */
-	memset(tx_ring->desc, 0, sizeof(struct atl1e_tpd_desc) *
-				ring_count);
-	memset(tx_ring->tx_buffer, 0, sizeof(struct atl1e_tx_buffer) *
-				ring_count);
-}
-
-/*
- * atl1e_clean_rx_ring - Free rx-reservation skbs
- * @adapter: board private structure
- */
-static void atl1e_clean_rx_ring(struct atl1e_adapter *adapter)
-{
-	struct atl1e_rx_ring *rx_ring =
-		(struct atl1e_rx_ring *)&adapter->rx_ring;
-	struct atl1e_rx_page_desc *rx_page_desc = rx_ring->rx_page_desc;
-	u16 i, j;
-
-
-	if (adapter->ring_vir_addr == NULL)
-		return;
-	/* Zero out the descriptor ring */
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
-			if (rx_page_desc[i].rx_page[j].addr != NULL) {
-				memset(rx_page_desc[i].rx_page[j].addr, 0,
-						rx_ring->real_page_size);
-			}
-		}
-	}
-}
-
-static void atl1e_cal_ring_size(struct atl1e_adapter *adapter, u32 *ring_size)
-{
-	*ring_size = ((u32)(adapter->tx_ring.count *
-		     sizeof(struct atl1e_tpd_desc) + 7
-			/* tx ring, qword align */
-		     + adapter->rx_ring.real_page_size * AT_PAGE_NUM_PER_QUEUE *
-			adapter->num_rx_queues + 31
-			/* rx ring,  32 bytes align */
-		     + (1 + AT_PAGE_NUM_PER_QUEUE * adapter->num_rx_queues) *
-			sizeof(u32) + 3));
-			/* tx, rx cmd, dword align   */
-}
-
-static void atl1e_init_ring_resources(struct atl1e_adapter *adapter)
-{
-	struct atl1e_rx_ring *rx_ring = NULL;
-
-	rx_ring = &adapter->rx_ring;
-
-	rx_ring->real_page_size = adapter->rx_ring.page_size
-				 + adapter->hw.max_frame_size
-				 + ETH_HLEN + VLAN_HLEN
-				 + ETH_FCS_LEN;
-	rx_ring->real_page_size = roundup(rx_ring->real_page_size, 32);
-	atl1e_cal_ring_size(adapter, &adapter->ring_size);
-
-	adapter->ring_vir_addr = NULL;
-	adapter->rx_ring.desc = NULL;
-	rwlock_init(&adapter->tx_ring.tx_lock);
-}
-
-/*
- * Read / Write Ptr Initialize:
- */
-static void atl1e_init_ring_ptrs(struct atl1e_adapter *adapter)
-{
-	struct atl1e_tx_ring *tx_ring = NULL;
-	struct atl1e_rx_ring *rx_ring = NULL;
-	struct atl1e_rx_page_desc *rx_page_desc = NULL;
-	int i, j;
-
-	tx_ring = &adapter->tx_ring;
-	rx_ring = &adapter->rx_ring;
-	rx_page_desc = rx_ring->rx_page_desc;
-
-	tx_ring->next_to_use = 0;
-	atomic_set(&tx_ring->next_to_clean, 0);
-
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		rx_page_desc[i].rx_using  = 0;
-		rx_page_desc[i].rx_nxseq = 0;
-		for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
-			*rx_page_desc[i].rx_page[j].write_offset_addr = 0;
-			rx_page_desc[i].rx_page[j].read_offset = 0;
-		}
-	}
-}
-
-/*
- * atl1e_free_ring_resources - Free Tx / RX descriptor Resources
- * @adapter: board private structure
- *
- * Free all transmit software resources
- */
-static void atl1e_free_ring_resources(struct atl1e_adapter *adapter)
-{
-	struct pci_dev *pdev = adapter->pdev;
-
-	atl1e_clean_tx_ring(adapter);
-	atl1e_clean_rx_ring(adapter);
-
-	if (adapter->ring_vir_addr) {
-		pci_free_consistent(pdev, adapter->ring_size,
-				adapter->ring_vir_addr, adapter->ring_dma);
-		adapter->ring_vir_addr = NULL;
-	}
-
-	if (adapter->tx_ring.tx_buffer) {
-		kfree(adapter->tx_ring.tx_buffer);
-		adapter->tx_ring.tx_buffer = NULL;
-	}
-}
-
-/*
- * atl1e_setup_mem_resources - allocate Tx / RX descriptor resources
- * @adapter: board private structure
- *
- * Return 0 on success, negative on failure
- */
-static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter)
-{
-	struct pci_dev *pdev = adapter->pdev;
-	struct atl1e_tx_ring *tx_ring;
-	struct atl1e_rx_ring *rx_ring;
-	struct atl1e_rx_page_desc  *rx_page_desc;
-	int size, i, j;
-	u32 offset = 0;
-	int err = 0;
-
-	if (adapter->ring_vir_addr != NULL)
-		return 0; /* alloced already */
-
-	tx_ring = &adapter->tx_ring;
-	rx_ring = &adapter->rx_ring;
-
-	/* real ring DMA buffer */
-
-	size = adapter->ring_size;
-	adapter->ring_vir_addr = pci_alloc_consistent(pdev,
-			adapter->ring_size, &adapter->ring_dma);
-
-	if (adapter->ring_vir_addr == NULL) {
-		netdev_err(adapter->netdev,
-			   "pci_alloc_consistent failed, size = D%d\n", size);
-		return -ENOMEM;
-	}
-
-	memset(adapter->ring_vir_addr, 0, adapter->ring_size);
-
-	rx_page_desc = rx_ring->rx_page_desc;
-
-	/* Init TPD Ring */
-	tx_ring->dma = roundup(adapter->ring_dma, 8);
-	offset = tx_ring->dma - adapter->ring_dma;
-	tx_ring->desc = adapter->ring_vir_addr + offset;
-	size = sizeof(struct atl1e_tx_buffer) * (tx_ring->count);
-	tx_ring->tx_buffer = kzalloc(size, GFP_KERNEL);
-	if (tx_ring->tx_buffer == NULL) {
-		netdev_err(adapter->netdev, "kzalloc failed, size = D%d\n",
-			   size);
-		err = -ENOMEM;
-		goto failed;
-	}
-
-	/* Init RXF-Pages */
-	offset += (sizeof(struct atl1e_tpd_desc) * tx_ring->count);
-	offset = roundup(offset, 32);
-
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
-			rx_page_desc[i].rx_page[j].dma =
-				adapter->ring_dma + offset;
-			rx_page_desc[i].rx_page[j].addr =
-				adapter->ring_vir_addr + offset;
-			offset += rx_ring->real_page_size;
-		}
-	}
-
-	/* Init CMB dma address */
-	tx_ring->cmb_dma = adapter->ring_dma + offset;
-	tx_ring->cmb = adapter->ring_vir_addr + offset;
-	offset += sizeof(u32);
-
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
-			rx_page_desc[i].rx_page[j].write_offset_dma =
-				adapter->ring_dma + offset;
-			rx_page_desc[i].rx_page[j].write_offset_addr =
-				adapter->ring_vir_addr + offset;
-			offset += sizeof(u32);
-		}
-	}
-
-	if (unlikely(offset > adapter->ring_size)) {
-		netdev_err(adapter->netdev, "offset(%d) > ring size(%d) !!\n",
-			   offset, adapter->ring_size);
-		err = -1;
-		goto failed;
-	}
-
-	return 0;
-failed:
-	if (adapter->ring_vir_addr != NULL) {
-		pci_free_consistent(pdev, adapter->ring_size,
-				adapter->ring_vir_addr, adapter->ring_dma);
-		adapter->ring_vir_addr = NULL;
-	}
-	return err;
-}
-
-static inline void atl1e_configure_des_ring(const struct atl1e_adapter *adapter)
-{
-
-	struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
-	struct atl1e_rx_ring *rx_ring =
-			(struct atl1e_rx_ring *)&adapter->rx_ring;
-	struct atl1e_tx_ring *tx_ring =
-			(struct atl1e_tx_ring *)&adapter->tx_ring;
-	struct atl1e_rx_page_desc *rx_page_desc = NULL;
-	int i, j;
-
-	AT_WRITE_REG(hw, REG_DESC_BASE_ADDR_HI,
-			(u32)((adapter->ring_dma & AT_DMA_HI_ADDR_MASK) >> 32));
-	AT_WRITE_REG(hw, REG_TPD_BASE_ADDR_LO,
-			(u32)((tx_ring->dma) & AT_DMA_LO_ADDR_MASK));
-	AT_WRITE_REG(hw, REG_TPD_RING_SIZE, (u16)(tx_ring->count));
-	AT_WRITE_REG(hw, REG_HOST_TX_CMB_LO,
-			(u32)((tx_ring->cmb_dma) & AT_DMA_LO_ADDR_MASK));
-
-	rx_page_desc = rx_ring->rx_page_desc;
-	/* RXF Page Physical address / Page Length */
-	for (i = 0; i < AT_MAX_RECEIVE_QUEUE; i++) {
-		AT_WRITE_REG(hw, atl1e_rx_page_hi_addr_regs[i],
-				 (u32)((adapter->ring_dma &
-				 AT_DMA_HI_ADDR_MASK) >> 32));
-		for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
-			u32 page_phy_addr;
-			u32 offset_phy_addr;
-
-			page_phy_addr = rx_page_desc[i].rx_page[j].dma;
-			offset_phy_addr =
-				   rx_page_desc[i].rx_page[j].write_offset_dma;
-
-			AT_WRITE_REG(hw, atl1e_rx_page_lo_addr_regs[i][j],
-					page_phy_addr & AT_DMA_LO_ADDR_MASK);
-			AT_WRITE_REG(hw, atl1e_rx_page_write_offset_regs[i][j],
-					offset_phy_addr & AT_DMA_LO_ADDR_MASK);
-			AT_WRITE_REGB(hw, atl1e_rx_page_vld_regs[i][j], 1);
-		}
-	}
-	/* Page Length */
-	AT_WRITE_REG(hw, REG_HOST_RXFPAGE_SIZE, rx_ring->page_size);
-	/* Load all of base address above */
-	AT_WRITE_REG(hw, REG_LOAD_PTR, 1);
-}
-
-static inline void atl1e_configure_tx(struct atl1e_adapter *adapter)
-{
-	struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
-	u32 dev_ctrl_data = 0;
-	u32 max_pay_load = 0;
-	u32 jumbo_thresh = 0;
-	u32 extra_size = 0;     /* Jumbo frame threshold in QWORD unit */
-
-	/* configure TXQ param */
-	if (hw->nic_type != athr_l2e_revB) {
-		extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
-		if (hw->max_frame_size <= 1500) {
-			jumbo_thresh = hw->max_frame_size + extra_size;
-		} else if (hw->max_frame_size < 6*1024) {
-			jumbo_thresh =
-				(hw->max_frame_size + extra_size) * 2 / 3;
-		} else {
-			jumbo_thresh = (hw->max_frame_size + extra_size) / 2;
-		}
-		AT_WRITE_REG(hw, REG_TX_EARLY_TH, (jumbo_thresh + 7) >> 3);
-	}
-
-	dev_ctrl_data = AT_READ_REG(hw, REG_DEVICE_CTRL);
-
-	max_pay_load  = ((dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT)) &
-			DEVICE_CTRL_MAX_PAYLOAD_MASK;
-
-	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_t(u32, max_pay_load, hw->dmar_block);
-
-	if (hw->nic_type != athr_l2e_revB)
-		AT_WRITE_REGW(hw, REG_TXQ_CTRL + 2,
-			      atl1e_pay_load_size[hw->dmar_block]);
-	/* enable TXQ */
-	AT_WRITE_REGW(hw, REG_TXQ_CTRL,
-			(((u16)hw->tpd_burst & TXQ_CTRL_NUM_TPD_BURST_MASK)
-			 << TXQ_CTRL_NUM_TPD_BURST_SHIFT)
-			| TXQ_CTRL_ENH_MODE | TXQ_CTRL_EN);
-}
-
-static inline void atl1e_configure_rx(struct atl1e_adapter *adapter)
-{
-	struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
-	u32 rxf_len  = 0;
-	u32 rxf_low  = 0;
-	u32 rxf_high = 0;
-	u32 rxf_thresh_data = 0;
-	u32 rxq_ctrl_data = 0;
-
-	if (hw->nic_type != athr_l2e_revB) {
-		AT_WRITE_REGW(hw, REG_RXQ_JMBOSZ_RRDTIM,
-			      (u16)((hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK) <<
-			      RXQ_JMBOSZ_TH_SHIFT |
-			      (1 & RXQ_JMBO_LKAH_MASK) <<
-			      RXQ_JMBO_LKAH_SHIFT));
-
-		rxf_len  = AT_READ_REG(hw, REG_SRAM_RXF_LEN);
-		rxf_high = rxf_len * 4 / 5;
-		rxf_low  = rxf_len / 5;
-		rxf_thresh_data = ((rxf_high  & RXQ_RXF_PAUSE_TH_HI_MASK)
-				  << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
-				  ((rxf_low & RXQ_RXF_PAUSE_TH_LO_MASK)
-				  << RXQ_RXF_PAUSE_TH_LO_SHIFT);
-
-		AT_WRITE_REG(hw, REG_RXQ_RXF_PAUSE_THRESH, rxf_thresh_data);
-	}
-
-	/* RRS */
-	AT_WRITE_REG(hw, REG_IDT_TABLE, hw->indirect_tab);
-	AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, hw->base_cpu);
-
-	if (hw->rrs_type & atl1e_rrs_ipv4)
-		rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV4;
-
-	if (hw->rrs_type & atl1e_rrs_ipv4_tcp)
-		rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV4_TCP;
-
-	if (hw->rrs_type & atl1e_rrs_ipv6)
-		rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV6;
-
-	if (hw->rrs_type & atl1e_rrs_ipv6_tcp)
-		rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV6_TCP;
-
-	if (hw->rrs_type != atl1e_rrs_disable)
-		rxq_ctrl_data |=
-			(RXQ_CTRL_HASH_ENABLE | RXQ_CTRL_RSS_MODE_MQUESINT);
-
-	rxq_ctrl_data |= RXQ_CTRL_IPV6_XSUM_VERIFY_EN | RXQ_CTRL_PBA_ALIGN_32 |
-			 RXQ_CTRL_CUT_THRU_EN | RXQ_CTRL_EN;
-
-	AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data);
-}
-
-static inline void atl1e_configure_dma(struct atl1e_adapter *adapter)
-{
-	struct atl1e_hw *hw = &adapter->hw;
-	u32 dma_ctrl_data = 0;
-
-	dma_ctrl_data = DMA_CTRL_RXCMB_EN;
-	dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
-		<< DMA_CTRL_DMAR_BURST_LEN_SHIFT;
-	dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
-		<< DMA_CTRL_DMAW_BURST_LEN_SHIFT;
-	dma_ctrl_data |= DMA_CTRL_DMAR_REQ_PRI | DMA_CTRL_DMAR_OUT_ORDER;
-	dma_ctrl_data |= (((u32)hw->dmar_dly_cnt) & DMA_CTRL_DMAR_DLY_CNT_MASK)
-		<< DMA_CTRL_DMAR_DLY_CNT_SHIFT;
-	dma_ctrl_data |= (((u32)hw->dmaw_dly_cnt) & DMA_CTRL_DMAW_DLY_CNT_MASK)
-		<< DMA_CTRL_DMAW_DLY_CNT_SHIFT;
-
-	AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data);
-}
-
-static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter)
-{
-	u32 value;
-	struct atl1e_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-
-	/* Config MAC CTRL Register */
-	value = MAC_CTRL_TX_EN |
-		MAC_CTRL_RX_EN ;
-
-	if (FULL_DUPLEX == adapter->link_duplex)
-		value |= MAC_CTRL_DUPLX;
-
-	value |= ((u32)((SPEED_1000 == adapter->link_speed) ?
-			  MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
-			  MAC_CTRL_SPEED_SHIFT);
-	value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
-
-	value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
-	value |= (((u32)adapter->hw.preamble_len &
-		  MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
-
-	__atl1e_vlan_mode(netdev->features, &value);
-
-	value |= MAC_CTRL_BC_EN;
-	if (netdev->flags & IFF_PROMISC)
-		value |= MAC_CTRL_PROMIS_EN;
-	if (netdev->flags & IFF_ALLMULTI)
-		value |= MAC_CTRL_MC_ALL_EN;
-
-	AT_WRITE_REG(hw, REG_MAC_CTRL, value);
-}
-
-/*
- * atl1e_configure - Configure Transmit&Receive Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Tx /Rx unit of the MAC after a reset.
- */
-static int atl1e_configure(struct atl1e_adapter *adapter)
-{
-	struct atl1e_hw *hw = &adapter->hw;
-
-	u32 intr_status_data = 0;
-
-	/* clear interrupt status */
-	AT_WRITE_REG(hw, REG_ISR, ~0);
-
-	/* 1. set MAC Address */
-	atl1e_hw_set_mac_addr(hw);
-
-	/* 2. Init the Multicast HASH table done by set_muti */
-
-	/* 3. Clear any WOL status */
-	AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
-
-	/* 4. Descripter Ring BaseMem/Length/Read ptr/Write ptr
-	 *    TPD Ring/SMB/RXF0 Page CMBs, they use the same
-	 *    High 32bits memory */
-	atl1e_configure_des_ring(adapter);
-
-	/* 5. set Interrupt Moderator Timer */
-	AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER_INIT, hw->imt);
-	AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER2_INIT, hw->imt);
-	AT_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_LED_MODE |
-			MASTER_CTRL_ITIMER_EN | MASTER_CTRL_ITIMER2_EN);
-
-	/* 6. rx/tx threshold to trig interrupt */
-	AT_WRITE_REGW(hw, REG_TRIG_RRD_THRESH, hw->rrd_thresh);
-	AT_WRITE_REGW(hw, REG_TRIG_TPD_THRESH, hw->tpd_thresh);
-	AT_WRITE_REGW(hw, REG_TRIG_RXTIMER, hw->rx_count_down);
-	AT_WRITE_REGW(hw, REG_TRIG_TXTIMER, hw->tx_count_down);
-
-	/* 7. set Interrupt Clear Timer */
-	AT_WRITE_REGW(hw, REG_CMBDISDMA_TIMER, hw->ict);
-
-	/* 8. set MTU */
-	AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN +
-			VLAN_HLEN + ETH_FCS_LEN);
-
-	/* 9. config TXQ early tx threshold */
-	atl1e_configure_tx(adapter);
-
-	/* 10. config RXQ */
-	atl1e_configure_rx(adapter);
-
-	/* 11. config  DMA Engine */
-	atl1e_configure_dma(adapter);
-
-	/* 12. smb timer to trig interrupt */
-	AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, hw->smb_timer);
-
-	intr_status_data = AT_READ_REG(hw, REG_ISR);
-	if (unlikely((intr_status_data & ISR_PHY_LINKDOWN) != 0)) {
-		netdev_err(adapter->netdev,
-			   "atl1e_configure failed, PCIE phy link down\n");
-		return -1;
-	}
-
-	AT_WRITE_REG(hw, REG_ISR, 0x7fffffff);
-	return 0;
-}
-
-/*
- * atl1e_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- *
- * Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
- */
-static struct net_device_stats *atl1e_get_stats(struct net_device *netdev)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	struct atl1e_hw_stats  *hw_stats = &adapter->hw_stats;
-	struct net_device_stats *net_stats = &netdev->stats;
-
-	net_stats->rx_packets = hw_stats->rx_ok;
-	net_stats->tx_packets = hw_stats->tx_ok;
-	net_stats->rx_bytes   = hw_stats->rx_byte_cnt;
-	net_stats->tx_bytes   = hw_stats->tx_byte_cnt;
-	net_stats->multicast  = hw_stats->rx_mcast;
-	net_stats->collisions = hw_stats->tx_1_col +
-				hw_stats->tx_2_col * 2 +
-				hw_stats->tx_late_col + hw_stats->tx_abort_col;
-
-	net_stats->rx_errors  = hw_stats->rx_frag + hw_stats->rx_fcs_err +
-				hw_stats->rx_len_err + hw_stats->rx_sz_ov +
-				hw_stats->rx_rrd_ov + hw_stats->rx_align_err;
-	net_stats->rx_fifo_errors   = hw_stats->rx_rxf_ov;
-	net_stats->rx_length_errors = hw_stats->rx_len_err;
-	net_stats->rx_crc_errors    = hw_stats->rx_fcs_err;
-	net_stats->rx_frame_errors  = hw_stats->rx_align_err;
-	net_stats->rx_over_errors   = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov;
-
-	net_stats->rx_missed_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov;
-
-	net_stats->tx_errors = hw_stats->tx_late_col + hw_stats->tx_abort_col +
-			       hw_stats->tx_underrun + hw_stats->tx_trunc;
-	net_stats->tx_fifo_errors    = hw_stats->tx_underrun;
-	net_stats->tx_aborted_errors = hw_stats->tx_abort_col;
-	net_stats->tx_window_errors  = hw_stats->tx_late_col;
-
-	return net_stats;
-}
-
-static void atl1e_update_hw_stats(struct atl1e_adapter *adapter)
-{
-	u16 hw_reg_addr = 0;
-	unsigned long *stats_item = NULL;
-
-	/* update rx status */
-	hw_reg_addr = REG_MAC_RX_STATUS_BIN;
-	stats_item  = &adapter->hw_stats.rx_ok;
-	while (hw_reg_addr <= REG_MAC_RX_STATUS_END) {
-		*stats_item += AT_READ_REG(&adapter->hw, hw_reg_addr);
-		stats_item++;
-		hw_reg_addr += 4;
-	}
-	/* update tx status */
-	hw_reg_addr = REG_MAC_TX_STATUS_BIN;
-	stats_item  = &adapter->hw_stats.tx_ok;
-	while (hw_reg_addr <= REG_MAC_TX_STATUS_END) {
-		*stats_item += AT_READ_REG(&adapter->hw, hw_reg_addr);
-		stats_item++;
-		hw_reg_addr += 4;
-	}
-}
-
-static inline void atl1e_clear_phy_int(struct atl1e_adapter *adapter)
-{
-	u16 phy_data;
-
-	spin_lock(&adapter->mdio_lock);
-	atl1e_read_phy_reg(&adapter->hw, MII_INT_STATUS, &phy_data);
-	spin_unlock(&adapter->mdio_lock);
-}
-
-static bool atl1e_clean_tx_irq(struct atl1e_adapter *adapter)
-{
-	struct atl1e_tx_ring *tx_ring = (struct atl1e_tx_ring *)
-					&adapter->tx_ring;
-	struct atl1e_tx_buffer *tx_buffer = NULL;
-	u16 hw_next_to_clean = AT_READ_REGW(&adapter->hw, REG_TPD_CONS_IDX);
-	u16 next_to_clean = atomic_read(&tx_ring->next_to_clean);
-
-	while (next_to_clean != hw_next_to_clean) {
-		tx_buffer = &tx_ring->tx_buffer[next_to_clean];
-		if (tx_buffer->dma) {
-			if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
-				pci_unmap_single(adapter->pdev, tx_buffer->dma,
-					tx_buffer->length, PCI_DMA_TODEVICE);
-			else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
-				pci_unmap_page(adapter->pdev, tx_buffer->dma,
-					tx_buffer->length, PCI_DMA_TODEVICE);
-			tx_buffer->dma = 0;
-		}
-
-		if (tx_buffer->skb) {
-			dev_kfree_skb_irq(tx_buffer->skb);
-			tx_buffer->skb = NULL;
-		}
-
-		if (++next_to_clean == tx_ring->count)
-			next_to_clean = 0;
-	}
-
-	atomic_set(&tx_ring->next_to_clean, next_to_clean);
-
-	if (netif_queue_stopped(adapter->netdev) &&
-			netif_carrier_ok(adapter->netdev)) {
-		netif_wake_queue(adapter->netdev);
-	}
-
-	return true;
-}
-
-/*
- * atl1e_intr - Interrupt Handler
- * @irq: interrupt number
- * @data: pointer to a network interface device structure
- * @pt_regs: CPU registers structure
- */
-static irqreturn_t atl1e_intr(int irq, void *data)
-{
-	struct net_device *netdev  = data;
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	struct atl1e_hw *hw = &adapter->hw;
-	int max_ints = AT_MAX_INT_WORK;
-	int handled = IRQ_NONE;
-	u32 status;
-
-	do {
-		status = AT_READ_REG(hw, REG_ISR);
-		if ((status & IMR_NORMAL_MASK) == 0 ||
-				(status & ISR_DIS_INT) != 0) {
-			if (max_ints != AT_MAX_INT_WORK)
-				handled = IRQ_HANDLED;
-			break;
-		}
-		/* link event */
-		if (status & ISR_GPHY)
-			atl1e_clear_phy_int(adapter);
-		/* Ack ISR */
-		AT_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT);
-
-		handled = IRQ_HANDLED;
-		/* check if PCIE PHY Link down */
-		if (status & ISR_PHY_LINKDOWN) {
-			netdev_err(adapter->netdev,
-				   "pcie phy linkdown %x\n", status);
-			if (netif_running(adapter->netdev)) {
-				/* reset MAC */
-				atl1e_irq_reset(adapter);
-				schedule_work(&adapter->reset_task);
-				break;
-			}
-		}
-
-		/* check if DMA read/write error */
-		if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
-			netdev_err(adapter->netdev,
-				   "PCIE DMA RW error (status = 0x%x)\n",
-				   status);
-			atl1e_irq_reset(adapter);
-			schedule_work(&adapter->reset_task);
-			break;
-		}
-
-		if (status & ISR_SMB)
-			atl1e_update_hw_stats(adapter);
-
-		/* link event */
-		if (status & (ISR_GPHY | ISR_MANUAL)) {
-			netdev->stats.tx_carrier_errors++;
-			atl1e_link_chg_event(adapter);
-			break;
-		}
-
-		/* transmit event */
-		if (status & ISR_TX_EVENT)
-			atl1e_clean_tx_irq(adapter);
-
-		if (status & ISR_RX_EVENT) {
-			/*
-			 * disable rx interrupts, without
-			 * the synchronize_irq bit
-			 */
-			AT_WRITE_REG(hw, REG_IMR,
-				     IMR_NORMAL_MASK & ~ISR_RX_EVENT);
-			AT_WRITE_FLUSH(hw);
-			if (likely(napi_schedule_prep(
-				   &adapter->napi)))
-				__napi_schedule(&adapter->napi);
-		}
-	} while (--max_ints > 0);
-	/* re-enable Interrupt*/
-	AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
-
-	return handled;
-}
-
-static inline void atl1e_rx_checksum(struct atl1e_adapter *adapter,
-		  struct sk_buff *skb, struct atl1e_recv_ret_status *prrs)
-{
-	u8 *packet = (u8 *)(prrs + 1);
-	struct iphdr *iph;
-	u16 head_len = ETH_HLEN;
-	u16 pkt_flags;
-	u16 err_flags;
-
-	skb_checksum_none_assert(skb);
-	pkt_flags = prrs->pkt_flag;
-	err_flags = prrs->err_flag;
-	if (((pkt_flags & RRS_IS_IPV4) || (pkt_flags & RRS_IS_IPV6)) &&
-		((pkt_flags & RRS_IS_TCP) || (pkt_flags & RRS_IS_UDP))) {
-		if (pkt_flags & RRS_IS_IPV4) {
-			if (pkt_flags & RRS_IS_802_3)
-				head_len += 8;
-			iph = (struct iphdr *) (packet + head_len);
-			if (iph->frag_off != 0 && !(pkt_flags & RRS_IS_IP_DF))
-				goto hw_xsum;
-		}
-		if (!(err_flags & (RRS_ERR_IP_CSUM | RRS_ERR_L4_CSUM))) {
-			skb->ip_summed = CHECKSUM_UNNECESSARY;
-			return;
-		}
-	}
-
-hw_xsum :
-	return;
-}
-
-static struct atl1e_rx_page *atl1e_get_rx_page(struct atl1e_adapter *adapter,
-					       u8 que)
-{
-	struct atl1e_rx_page_desc *rx_page_desc =
-		(struct atl1e_rx_page_desc *) adapter->rx_ring.rx_page_desc;
-	u8 rx_using = rx_page_desc[que].rx_using;
-
-	return (struct atl1e_rx_page *)&(rx_page_desc[que].rx_page[rx_using]);
-}
-
-static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que,
-		   int *work_done, int work_to_do)
-{
-	struct net_device *netdev  = adapter->netdev;
-	struct atl1e_rx_ring *rx_ring = (struct atl1e_rx_ring *)
-					 &adapter->rx_ring;
-	struct atl1e_rx_page_desc *rx_page_desc =
-		(struct atl1e_rx_page_desc *) rx_ring->rx_page_desc;
-	struct sk_buff *skb = NULL;
-	struct atl1e_rx_page *rx_page = atl1e_get_rx_page(adapter, que);
-	u32 packet_size, write_offset;
-	struct atl1e_recv_ret_status *prrs;
-
-	write_offset = *(rx_page->write_offset_addr);
-	if (likely(rx_page->read_offset < write_offset)) {
-		do {
-			if (*work_done >= work_to_do)
-				break;
-			(*work_done)++;
-			/* get new packet's  rrs */
-			prrs = (struct atl1e_recv_ret_status *) (rx_page->addr +
-						 rx_page->read_offset);
-			/* check sequence number */
-			if (prrs->seq_num != rx_page_desc[que].rx_nxseq) {
-				netdev_err(netdev,
-					   "rx sequence number error (rx=%d) (expect=%d)\n",
-					   prrs->seq_num,
-					   rx_page_desc[que].rx_nxseq);
-				rx_page_desc[que].rx_nxseq++;
-				/* just for debug use */
-				AT_WRITE_REG(&adapter->hw, REG_DEBUG_DATA0,
-					     (((u32)prrs->seq_num) << 16) |
-					     rx_page_desc[que].rx_nxseq);
-				goto fatal_err;
-			}
-			rx_page_desc[que].rx_nxseq++;
-
-			/* error packet */
-			if (prrs->pkt_flag & RRS_IS_ERR_FRAME) {
-				if (prrs->err_flag & (RRS_ERR_BAD_CRC |
-					RRS_ERR_DRIBBLE | RRS_ERR_CODE |
-					RRS_ERR_TRUNC)) {
-				/* hardware error, discard this packet*/
-					netdev_err(netdev,
-						   "rx packet desc error %x\n",
-						   *((u32 *)prrs + 1));
-					goto skip_pkt;
-				}
-			}
-
-			packet_size = ((prrs->word1 >> RRS_PKT_SIZE_SHIFT) &
-					RRS_PKT_SIZE_MASK) - 4; /* CRC */
-			skb = netdev_alloc_skb_ip_align(netdev, packet_size);
-			if (skb == NULL) {
-				netdev_warn(netdev,
-					    "Memory squeeze, deferring packet\n");
-				goto skip_pkt;
-			}
-			memcpy(skb->data, (u8 *)(prrs + 1), packet_size);
-			skb_put(skb, packet_size);
-			skb->protocol = eth_type_trans(skb, netdev);
-			atl1e_rx_checksum(adapter, skb, prrs);
-
-			if (prrs->pkt_flag & RRS_IS_VLAN_TAG) {
-				u16 vlan_tag = (prrs->vtag >> 4) |
-					       ((prrs->vtag & 7) << 13) |
-					       ((prrs->vtag & 8) << 9);
-				netdev_dbg(netdev,
-					   "RXD VLAN TAG<RRD>=0x%04x\n",
-					   prrs->vtag);
-				__vlan_hwaccel_put_tag(skb, vlan_tag);
-			}
-			netif_receive_skb(skb);
-
-skip_pkt:
-	/* skip current packet whether it's ok or not. */
-			rx_page->read_offset +=
-				(((u32)((prrs->word1 >> RRS_PKT_SIZE_SHIFT) &
-				RRS_PKT_SIZE_MASK) +
-				sizeof(struct atl1e_recv_ret_status) + 31) &
-						0xFFFFFFE0);
-
-			if (rx_page->read_offset >= rx_ring->page_size) {
-				/* mark this page clean */
-				u16 reg_addr;
-				u8  rx_using;
-
-				rx_page->read_offset =
-					*(rx_page->write_offset_addr) = 0;
-				rx_using = rx_page_desc[que].rx_using;
-				reg_addr =
-					atl1e_rx_page_vld_regs[que][rx_using];
-				AT_WRITE_REGB(&adapter->hw, reg_addr, 1);
-				rx_page_desc[que].rx_using ^= 1;
-				rx_page = atl1e_get_rx_page(adapter, que);
-			}
-			write_offset = *(rx_page->write_offset_addr);
-		} while (rx_page->read_offset < write_offset);
-	}
-
-	return;
-
-fatal_err:
-	if (!test_bit(__AT_DOWN, &adapter->flags))
-		schedule_work(&adapter->reset_task);
-}
-
-/*
- * atl1e_clean - NAPI Rx polling callback
- * @adapter: board private structure
- */
-static int atl1e_clean(struct napi_struct *napi, int budget)
-{
-	struct atl1e_adapter *adapter =
-			container_of(napi, struct atl1e_adapter, napi);
-	u32 imr_data;
-	int work_done = 0;
-
-	/* Keep link state information with original netdev */
-	if (!netif_carrier_ok(adapter->netdev))
-		goto quit_polling;
-
-	atl1e_clean_rx_irq(adapter, 0, &work_done, budget);
-
-	/* If no Tx and not enough Rx work done, exit the polling mode */
-	if (work_done < budget) {
-quit_polling:
-		napi_complete(napi);
-		imr_data = AT_READ_REG(&adapter->hw, REG_IMR);
-		AT_WRITE_REG(&adapter->hw, REG_IMR, imr_data | ISR_RX_EVENT);
-		/* test debug */
-		if (test_bit(__AT_DOWN, &adapter->flags)) {
-			atomic_dec(&adapter->irq_sem);
-			netdev_err(adapter->netdev,
-				   "atl1e_clean is called when AT_DOWN\n");
-		}
-		/* reenable RX intr */
-		/*atl1e_irq_enable(adapter); */
-
-	}
-	return work_done;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-
-/*
- * Polling 'interrupt' - used by things like netconsole to send skbs
- * without having to re-enable interrupts. It's not called while
- * the interrupt routine is executing.
- */
-static void atl1e_netpoll(struct net_device *netdev)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-
-	disable_irq(adapter->pdev->irq);
-	atl1e_intr(adapter->pdev->irq, netdev);
-	enable_irq(adapter->pdev->irq);
-}
-#endif
-
-static inline u16 atl1e_tpd_avail(struct atl1e_adapter *adapter)
-{
-	struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
-	u16 next_to_use = 0;
-	u16 next_to_clean = 0;
-
-	next_to_clean = atomic_read(&tx_ring->next_to_clean);
-	next_to_use   = tx_ring->next_to_use;
-
-	return (u16)(next_to_clean > next_to_use) ?
-		(next_to_clean - next_to_use - 1) :
-		(tx_ring->count + next_to_clean - next_to_use - 1);
-}
-
-/*
- * get next usable tpd
- * Note: should call atl1e_tdp_avail to make sure
- * there is enough tpd to use
- */
-static struct atl1e_tpd_desc *atl1e_get_tpd(struct atl1e_adapter *adapter)
-{
-	struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
-	u16 next_to_use = 0;
-
-	next_to_use = tx_ring->next_to_use;
-	if (++tx_ring->next_to_use == tx_ring->count)
-		tx_ring->next_to_use = 0;
-
-	memset(&tx_ring->desc[next_to_use], 0, sizeof(struct atl1e_tpd_desc));
-	return (struct atl1e_tpd_desc *)&tx_ring->desc[next_to_use];
-}
-
-static struct atl1e_tx_buffer *
-atl1e_get_tx_buffer(struct atl1e_adapter *adapter, struct atl1e_tpd_desc *tpd)
-{
-	struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
-
-	return &tx_ring->tx_buffer[tpd - tx_ring->desc];
-}
-
-/* Calculate the transmit packet descript needed*/
-static u16 atl1e_cal_tdp_req(const struct sk_buff *skb)
-{
-	int i = 0;
-	u16 tpd_req = 1;
-	u16 fg_size = 0;
-	u16 proto_hdr_len = 0;
-
-	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-		fg_size = skb_shinfo(skb)->frags[i].size;
-		tpd_req += ((fg_size + MAX_TX_BUF_LEN - 1) >> MAX_TX_BUF_SHIFT);
-	}
-
-	if (skb_is_gso(skb)) {
-		if (skb->protocol == htons(ETH_P_IP) ||
-		   (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6)) {
-			proto_hdr_len = skb_transport_offset(skb) +
-					tcp_hdrlen(skb);
-			if (proto_hdr_len < skb_headlen(skb)) {
-				tpd_req += ((skb_headlen(skb) - proto_hdr_len +
-					   MAX_TX_BUF_LEN - 1) >>
-					   MAX_TX_BUF_SHIFT);
-			}
-		}
-
-	}
-	return tpd_req;
-}
-
-static int atl1e_tso_csum(struct atl1e_adapter *adapter,
-		       struct sk_buff *skb, struct atl1e_tpd_desc *tpd)
-{
-	u8 hdr_len;
-	u32 real_len;
-	unsigned short offload_type;
-	int err;
-
-	if (skb_is_gso(skb)) {
-		if (skb_header_cloned(skb)) {
-			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
-			if (unlikely(err))
-				return -1;
-		}
-		offload_type = skb_shinfo(skb)->gso_type;
-
-		if (offload_type & SKB_GSO_TCPV4) {
-			real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
-					+ ntohs(ip_hdr(skb)->tot_len));
-
-			if (real_len < skb->len)
-				pskb_trim(skb, real_len);
-
-			hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
-			if (unlikely(skb->len == hdr_len)) {
-				/* only xsum need */
-				netdev_warn(adapter->netdev,
-					    "IPV4 tso with zero data??\n");
-				goto check_sum;
-			} else {
-				ip_hdr(skb)->check = 0;
-				ip_hdr(skb)->tot_len = 0;
-				tcp_hdr(skb)->check = ~csum_tcpudp_magic(
-							ip_hdr(skb)->saddr,
-							ip_hdr(skb)->daddr,
-							0, IPPROTO_TCP, 0);
-				tpd->word3 |= (ip_hdr(skb)->ihl &
-					TDP_V4_IPHL_MASK) <<
-					TPD_V4_IPHL_SHIFT;
-				tpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
-					TPD_TCPHDRLEN_MASK) <<
-					TPD_TCPHDRLEN_SHIFT;
-				tpd->word3 |= ((skb_shinfo(skb)->gso_size) &
-					TPD_MSS_MASK) << TPD_MSS_SHIFT;
-				tpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT;
-			}
-			return 0;
-		}
-	}
-
-check_sum:
-	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
-		u8 css, cso;
-
-		cso = skb_checksum_start_offset(skb);
-		if (unlikely(cso & 0x1)) {
-			netdev_err(adapter->netdev,
-				   "payload offset should not ant event number\n");
-			return -1;
-		} else {
-			css = cso + skb->csum_offset;
-			tpd->word3 |= (cso & TPD_PLOADOFFSET_MASK) <<
-					TPD_PLOADOFFSET_SHIFT;
-			tpd->word3 |= (css & TPD_CCSUMOFFSET_MASK) <<
-					TPD_CCSUMOFFSET_SHIFT;
-			tpd->word3 |= 1 << TPD_CC_SEGMENT_EN_SHIFT;
-		}
-	}
-
-	return 0;
-}
-
-static void atl1e_tx_map(struct atl1e_adapter *adapter,
-		      struct sk_buff *skb, struct atl1e_tpd_desc *tpd)
-{
-	struct atl1e_tpd_desc *use_tpd = NULL;
-	struct atl1e_tx_buffer *tx_buffer = NULL;
-	u16 buf_len = skb_headlen(skb);
-	u16 map_len = 0;
-	u16 mapped_len = 0;
-	u16 hdr_len = 0;
-	u16 nr_frags;
-	u16 f;
-	int segment;
-
-	nr_frags = skb_shinfo(skb)->nr_frags;
-	segment = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK;
-	if (segment) {
-		/* TSO */
-		map_len = hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-		use_tpd = tpd;
-
-		tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd);
-		tx_buffer->length = map_len;
-		tx_buffer->dma = pci_map_single(adapter->pdev,
-					skb->data, hdr_len, PCI_DMA_TODEVICE);
-		ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE);
-		mapped_len += map_len;
-		use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
-		use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
-			((cpu_to_le32(tx_buffer->length) &
-			TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT);
-	}
-
-	while (mapped_len < buf_len) {
-		/* mapped_len == 0, means we should use the first tpd,
-		   which is given by caller  */
-		if (mapped_len == 0) {
-			use_tpd = tpd;
-		} else {
-			use_tpd = atl1e_get_tpd(adapter);
-			memcpy(use_tpd, tpd, sizeof(struct atl1e_tpd_desc));
-		}
-		tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd);
-		tx_buffer->skb = NULL;
-
-		tx_buffer->length = map_len =
-			((buf_len - mapped_len) >= MAX_TX_BUF_LEN) ?
-			MAX_TX_BUF_LEN : (buf_len - mapped_len);
-		tx_buffer->dma =
-			pci_map_single(adapter->pdev, skb->data + mapped_len,
-					map_len, PCI_DMA_TODEVICE);
-		ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE);
-		mapped_len  += map_len;
-		use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
-		use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
-			((cpu_to_le32(tx_buffer->length) &
-			TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT);
-	}
-
-	for (f = 0; f < nr_frags; f++) {
-		struct skb_frag_struct *frag;
-		u16 i;
-		u16 seg_num;
-
-		frag = &skb_shinfo(skb)->frags[f];
-		buf_len = frag->size;
-
-		seg_num = (buf_len + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
-		for (i = 0; i < seg_num; i++) {
-			use_tpd = atl1e_get_tpd(adapter);
-			memcpy(use_tpd, tpd, sizeof(struct atl1e_tpd_desc));
-
-			tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd);
-			BUG_ON(tx_buffer->skb);
-
-			tx_buffer->skb = NULL;
-			tx_buffer->length =
-				(buf_len > MAX_TX_BUF_LEN) ?
-				MAX_TX_BUF_LEN : buf_len;
-			buf_len -= tx_buffer->length;
-
-			tx_buffer->dma =
-				pci_map_page(adapter->pdev, frag->page,
-						frag->page_offset +
-						(i * MAX_TX_BUF_LEN),
-						tx_buffer->length,
-						PCI_DMA_TODEVICE);
-			ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_PAGE);
-			use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
-			use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
-					((cpu_to_le32(tx_buffer->length) &
-					TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT);
-		}
-	}
-
-	if ((tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK)
-		/* note this one is a tcp header */
-		tpd->word3 |= 1 << TPD_HDRFLAG_SHIFT;
-	/* The last tpd */
-
-	use_tpd->word3 |= 1 << TPD_EOP_SHIFT;
-	/* The last buffer info contain the skb address,
-	   so it will be free after unmap */
-	tx_buffer->skb = skb;
-}
-
-static void atl1e_tx_queue(struct atl1e_adapter *adapter, u16 count,
-			   struct atl1e_tpd_desc *tpd)
-{
-	struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
-	/* Force memory writes to complete before letting h/w
-	 * know there are new descriptors to fetch.  (Only
-	 * applicable for weak-ordered memory model archs,
-	 * such as IA-64). */
-	wmb();
-	AT_WRITE_REG(&adapter->hw, REG_MB_TPD_PROD_IDX, tx_ring->next_to_use);
-}
-
-static netdev_tx_t atl1e_xmit_frame(struct sk_buff *skb,
-					  struct net_device *netdev)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	unsigned long flags;
-	u16 tpd_req = 1;
-	struct atl1e_tpd_desc *tpd;
-
-	if (test_bit(__AT_DOWN, &adapter->flags)) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	if (unlikely(skb->len <= 0)) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-	tpd_req = atl1e_cal_tdp_req(skb);
-	if (!spin_trylock_irqsave(&adapter->tx_lock, flags))
-		return NETDEV_TX_LOCKED;
-
-	if (atl1e_tpd_avail(adapter) < tpd_req) {
-		/* no enough descriptor, just stop queue */
-		netif_stop_queue(netdev);
-		spin_unlock_irqrestore(&adapter->tx_lock, flags);
-		return NETDEV_TX_BUSY;
-	}
-
-	tpd = atl1e_get_tpd(adapter);
-
-	if (vlan_tx_tag_present(skb)) {
-		u16 vlan_tag = vlan_tx_tag_get(skb);
-		u16 atl1e_vlan_tag;
-
-		tpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT;
-		AT_VLAN_TAG_TO_TPD_TAG(vlan_tag, atl1e_vlan_tag);
-		tpd->word2 |= (atl1e_vlan_tag & TPD_VLANTAG_MASK) <<
-				TPD_VLAN_SHIFT;
-	}
-
-	if (skb->protocol == htons(ETH_P_8021Q))
-		tpd->word3 |= 1 << TPD_VL_TAGGED_SHIFT;
-
-	if (skb_network_offset(skb) != ETH_HLEN)
-		tpd->word3 |= 1 << TPD_ETHTYPE_SHIFT; /* 802.3 frame */
-
-	/* do TSO and check sum */
-	if (atl1e_tso_csum(adapter, skb, tpd) != 0) {
-		spin_unlock_irqrestore(&adapter->tx_lock, flags);
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	atl1e_tx_map(adapter, skb, tpd);
-	atl1e_tx_queue(adapter, tpd_req, tpd);
-
-	netdev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
-	spin_unlock_irqrestore(&adapter->tx_lock, flags);
-	return NETDEV_TX_OK;
-}
-
-static void atl1e_free_irq(struct atl1e_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-
-	free_irq(adapter->pdev->irq, netdev);
-
-	if (adapter->have_msi)
-		pci_disable_msi(adapter->pdev);
-}
-
-static int atl1e_request_irq(struct atl1e_adapter *adapter)
-{
-	struct pci_dev    *pdev   = adapter->pdev;
-	struct net_device *netdev = adapter->netdev;
-	int flags = 0;
-	int err = 0;
-
-	adapter->have_msi = true;
-	err = pci_enable_msi(adapter->pdev);
-	if (err) {
-		netdev_dbg(adapter->netdev,
-			   "Unable to allocate MSI interrupt Error: %d\n", err);
-		adapter->have_msi = false;
-	} else
-		netdev->irq = pdev->irq;
-
-
-	if (!adapter->have_msi)
-		flags |= IRQF_SHARED;
-	err = request_irq(adapter->pdev->irq, atl1e_intr, flags,
-			netdev->name, netdev);
-	if (err) {
-		netdev_dbg(adapter->netdev,
-			   "Unable to allocate interrupt Error: %d\n", err);
-		if (adapter->have_msi)
-			pci_disable_msi(adapter->pdev);
-		return err;
-	}
-	netdev_dbg(adapter->netdev, "atl1e_request_irq OK\n");
-	return err;
-}
-
-int atl1e_up(struct atl1e_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	int err = 0;
-	u32 val;
-
-	/* hardware has been reset, we need to reload some things */
-	err = atl1e_init_hw(&adapter->hw);
-	if (err) {
-		err = -EIO;
-		return err;
-	}
-	atl1e_init_ring_ptrs(adapter);
-	atl1e_set_multi(netdev);
-	atl1e_restore_vlan(adapter);
-
-	if (atl1e_configure(adapter)) {
-		err = -EIO;
-		goto err_up;
-	}
-
-	clear_bit(__AT_DOWN, &adapter->flags);
-	napi_enable(&adapter->napi);
-	atl1e_irq_enable(adapter);
-	val = AT_READ_REG(&adapter->hw, REG_MASTER_CTRL);
-	AT_WRITE_REG(&adapter->hw, REG_MASTER_CTRL,
-		      val | MASTER_CTRL_MANUAL_INT);
-
-err_up:
-	return err;
-}
-
-void atl1e_down(struct atl1e_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-
-	/* signal that we're down so the interrupt handler does not
-	 * reschedule our watchdog timer */
-	set_bit(__AT_DOWN, &adapter->flags);
-
-	netif_stop_queue(netdev);
-
-	/* reset MAC to disable all RX/TX */
-	atl1e_reset_hw(&adapter->hw);
-	msleep(1);
-
-	napi_disable(&adapter->napi);
-	atl1e_del_timer(adapter);
-	atl1e_irq_disable(adapter);
-
-	netif_carrier_off(netdev);
-	adapter->link_speed = SPEED_0;
-	adapter->link_duplex = -1;
-	atl1e_clean_tx_ring(adapter);
-	atl1e_clean_rx_ring(adapter);
-}
-
-/*
- * atl1e_open - Called when a network interface is made active
- * @netdev: network interface device structure
- *
- * Returns 0 on success, negative value on failure
- *
- * 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.
- */
-static int atl1e_open(struct net_device *netdev)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	int err;
-
-	/* disallow open during test */
-	if (test_bit(__AT_TESTING, &adapter->flags))
-		return -EBUSY;
-
-	/* allocate rx/tx dma buffer & descriptors */
-	atl1e_init_ring_resources(adapter);
-	err = atl1e_setup_ring_resources(adapter);
-	if (unlikely(err))
-		return err;
-
-	err = atl1e_request_irq(adapter);
-	if (unlikely(err))
-		goto err_req_irq;
-
-	err = atl1e_up(adapter);
-	if (unlikely(err))
-		goto err_up;
-
-	return 0;
-
-err_up:
-	atl1e_free_irq(adapter);
-err_req_irq:
-	atl1e_free_ring_resources(adapter);
-	atl1e_reset_hw(&adapter->hw);
-
-	return err;
-}
-
-/*
- * atl1e_close - Disables a network interface
- * @netdev: network interface device structure
- *
- * 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.
- */
-static int atl1e_close(struct net_device *netdev)
-{
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-
-	WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
-	atl1e_down(adapter);
-	atl1e_free_irq(adapter);
-	atl1e_free_ring_resources(adapter);
-
-	return 0;
-}
-
-static int atl1e_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-	struct atl1e_hw *hw = &adapter->hw;
-	u32 ctrl = 0;
-	u32 mac_ctrl_data = 0;
-	u32 wol_ctrl_data = 0;
-	u16 mii_advertise_data = 0;
-	u16 mii_bmsr_data = 0;
-	u16 mii_intr_status_data = 0;
-	u32 wufc = adapter->wol;
-	u32 i;
-#ifdef CONFIG_PM
-	int retval = 0;
-#endif
-
-	if (netif_running(netdev)) {
-		WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
-		atl1e_down(adapter);
-	}
-	netif_device_detach(netdev);
-
-#ifdef CONFIG_PM
-	retval = pci_save_state(pdev);
-	if (retval)
-		return retval;
-#endif
-
-	if (wufc) {
-		/* get link status */
-		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 = ADVERTISE_10HALF;
-
-		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) {
-			netdev_dbg(adapter->netdev, "set phy register failed\n");
-			goto wol_dis;
-		}
-
-		hw->phy_configured = false; /* re-init PHY when resume */
-
-		/* turn on magic packet wol */
-		if (wufc & AT_WUFC_MAG)
-			wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
-
-		if (wufc & AT_WUFC_LNKC) {
-		/* if orignal link status is link, just wait for retrive link */
-			if (mii_bmsr_data & BMSR_LSTATUS) {
-				for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) {
-					msleep(100);
-					atl1e_read_phy_reg(hw, MII_BMSR,
-							(u16 *)&mii_bmsr_data);
-					if (mii_bmsr_data & BMSR_LSTATUS)
-						break;
-				}
-
-				if ((mii_bmsr_data & BMSR_LSTATUS) == 0)
-					netdev_dbg(adapter->netdev,
-						   "Link may change when suspend\n");
-			}
-			wol_ctrl_data |=  WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
-			/* only link up can wake up */
-			if (atl1e_write_phy_reg(hw, MII_INT_CTRL, 0x400) != 0) {
-				netdev_dbg(adapter->netdev,
-					   "read write phy register failed\n");
-				goto wol_dis;
-			}
-		}
-		/* clear phy interrupt */
-		atl1e_read_phy_reg(hw, MII_INT_STATUS, &mii_intr_status_data);
-		/* Config MAC Ctrl register */
-		mac_ctrl_data = MAC_CTRL_RX_EN;
-		/* set to 10/100M halt duplex */
-		mac_ctrl_data |= MAC_CTRL_SPEED_10_100 << MAC_CTRL_SPEED_SHIFT;
-		mac_ctrl_data |= (((u32)adapter->hw.preamble_len &
-				 MAC_CTRL_PRMLEN_MASK) <<
-				 MAC_CTRL_PRMLEN_SHIFT);
-
-		__atl1e_vlan_mode(netdev->features, &mac_ctrl_data);
-
-		/* magic packet maybe Broadcast&multicast&Unicast frame */
-		if (wufc & AT_WUFC_MAG)
-			mac_ctrl_data |= MAC_CTRL_BC_EN;
-
-		netdev_dbg(adapter->netdev, "suspend MAC=0x%x\n",
-			   mac_ctrl_data);
-
-		AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);
-		AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
-		/* pcie patch */
-		ctrl = AT_READ_REG(hw, REG_PCIE_PHYMISC);
-		ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
-		AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
-		pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
-		goto suspend_exit;
-	}
-wol_dis:
-
-	/* WOL disabled */
-	AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
-
-	/* pcie patch */
-	ctrl = AT_READ_REG(hw, REG_PCIE_PHYMISC);
-	ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
-	AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
-
-	atl1e_force_ps(hw);
-	hw->phy_configured = false; /* re-init PHY when resume */
-
-	pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
-
-suspend_exit:
-
-	if (netif_running(netdev))
-		atl1e_free_irq(adapter);
-
-	pci_disable_device(pdev);
-
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int atl1e_resume(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1e_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) {
-		netdev_err(adapter->netdev,
-			   "Cannot enable PCI device from suspend\n");
-		return err;
-	}
-
-	pci_set_master(pdev);
-
-	AT_READ_REG(&adapter->hw, REG_WOL_CTRL); /* clear WOL status */
-
-	pci_enable_wake(pdev, PCI_D3hot, 0);
-	pci_enable_wake(pdev, PCI_D3cold, 0);
-
-	AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
-
-	if (netif_running(netdev)) {
-		err = atl1e_request_irq(adapter);
-		if (err)
-			return err;
-	}
-
-	atl1e_reset_hw(&adapter->hw);
-
-	if (netif_running(netdev))
-		atl1e_up(adapter);
-
-	netif_device_attach(netdev);
-
-	return 0;
-}
-#endif
-
-static void atl1e_shutdown(struct pci_dev *pdev)
-{
-	atl1e_suspend(pdev, PMSG_SUSPEND);
-}
-
-static const struct net_device_ops atl1e_netdev_ops = {
-	.ndo_open		= atl1e_open,
-	.ndo_stop		= atl1e_close,
-	.ndo_start_xmit		= atl1e_xmit_frame,
-	.ndo_get_stats		= atl1e_get_stats,
-	.ndo_set_multicast_list	= atl1e_set_multi,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address	= atl1e_set_mac_addr,
-	.ndo_fix_features	= atl1e_fix_features,
-	.ndo_set_features	= atl1e_set_features,
-	.ndo_change_mtu		= atl1e_change_mtu,
-	.ndo_do_ioctl		= atl1e_ioctl,
-	.ndo_tx_timeout		= atl1e_tx_timeout,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= atl1e_netpoll,
-#endif
-
-};
-
-static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
-{
-	SET_NETDEV_DEV(netdev, &pdev->dev);
-	pci_set_drvdata(pdev, netdev);
-
-	netdev->irq  = pdev->irq;
-	netdev->netdev_ops = &atl1e_netdev_ops;
-
-	netdev->watchdog_timeo = AT_TX_WATCHDOG;
-	atl1e_set_ethtool_ops(netdev);
-
-	netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO |
-			      NETIF_F_HW_VLAN_RX;
-	netdev->features = netdev->hw_features | NETIF_F_LLTX |
-			   NETIF_F_HW_VLAN_TX;
-
-	return 0;
-}
-
-/*
- * atl1e_probe - Device Initialization Routine
- * @pdev: PCI device information struct
- * @ent: entry in atl1e_pci_tbl
- *
- * Returns 0 on success, negative on failure
- *
- * atl1e_probe initializes an adapter identified by a pci_dev structure.
- * The OS initialization, configuring of the adapter private structure,
- * and a hardware reset occur.
- */
-static int __devinit atl1e_probe(struct pci_dev *pdev,
-				 const struct pci_device_id *ent)
-{
-	struct net_device *netdev;
-	struct atl1e_adapter *adapter = NULL;
-	static int cards_found;
-
-	int err = 0;
-
-	err = pci_enable_device(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "cannot enable PCI device\n");
-		return err;
-	}
-
-	/*
-	 * The atl1e chip can DMA to 64-bit addresses, but it uses a single
-	 * shared register for the high 32 bits, so only a single, aligned,
-	 * 4 GB physical address range can be used at a time.
-	 *
-	 * Supporting 64-bit DMA on this hardware is more trouble than it's
-	 * worth.  It is far easier to limit to 32-bit DMA than update
-	 * various kernel subsystems to support the mechanics required by a
-	 * fixed-high-32-bit system.
-	 */
-	if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) ||
-	    (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)) {
-		dev_err(&pdev->dev, "No usable DMA configuration,aborting\n");
-		goto err_dma;
-	}
-
-	err = pci_request_regions(pdev, atl1e_driver_name);
-	if (err) {
-		dev_err(&pdev->dev, "cannot obtain PCI resources\n");
-		goto err_pci_reg;
-	}
-
-	pci_set_master(pdev);
-
-	netdev = alloc_etherdev(sizeof(struct atl1e_adapter));
-	if (netdev == NULL) {
-		err = -ENOMEM;
-		dev_err(&pdev->dev, "etherdev alloc failed\n");
-		goto err_alloc_etherdev;
-	}
-
-	err = atl1e_init_netdev(netdev, pdev);
-	if (err) {
-		netdev_err(netdev, "init netdevice failed\n");
-		goto err_init_netdev;
-	}
-	adapter = netdev_priv(netdev);
-	adapter->bd_number = cards_found;
-	adapter->netdev = netdev;
-	adapter->pdev = pdev;
-	adapter->hw.adapter = adapter;
-	adapter->hw.hw_addr = pci_iomap(pdev, BAR_0, 0);
-	if (!adapter->hw.hw_addr) {
-		err = -EIO;
-		netdev_err(netdev, "cannot map device registers\n");
-		goto err_ioremap;
-	}
-	netdev->base_addr = (unsigned long)adapter->hw.hw_addr;
-
-	/* init mii data */
-	adapter->mii.dev = netdev;
-	adapter->mii.mdio_read  = atl1e_mdio_read;
-	adapter->mii.mdio_write = atl1e_mdio_write;
-	adapter->mii.phy_id_mask = 0x1f;
-	adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK;
-
-	netif_napi_add(netdev, &adapter->napi, atl1e_clean, 64);
-
-	init_timer(&adapter->phy_config_timer);
-	adapter->phy_config_timer.function = atl1e_phy_config;
-	adapter->phy_config_timer.data = (unsigned long) adapter;
-
-	/* get user settings */
-	atl1e_check_options(adapter);
-	/*
-	 * Mark all PCI regions associated with PCI device
-	 * pdev as being reserved by owner atl1e_driver_name
-	 * Enables bus-mastering on the device and calls
-	 * pcibios_set_master to do the needed arch specific settings
-	 */
-	atl1e_setup_pcicmd(pdev);
-	/* setup the private structure */
-	err = atl1e_sw_init(adapter);
-	if (err) {
-		netdev_err(netdev, "net device private data init failed\n");
-		goto err_sw_init;
-	}
-
-	/* Init GPHY as early as possible due to power saving issue  */
-	atl1e_phy_init(&adapter->hw);
-	/* reset the controller to
-	 * put the device in a known good starting state */
-	err = atl1e_reset_hw(&adapter->hw);
-	if (err) {
-		err = -EIO;
-		goto err_reset;
-	}
-
-	if (atl1e_read_mac_addr(&adapter->hw) != 0) {
-		err = -EIO;
-		netdev_err(netdev, "get mac address failed\n");
-		goto err_eeprom;
-	}
-
-	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
-	memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
-	netdev_dbg(netdev, "mac address : %pM\n", adapter->hw.mac_addr);
-
-	INIT_WORK(&adapter->reset_task, atl1e_reset_task);
-	INIT_WORK(&adapter->link_chg_task, atl1e_link_chg_task);
-	err = register_netdev(netdev);
-	if (err) {
-		netdev_err(netdev, "register netdevice failed\n");
-		goto err_register;
-	}
-
-	/* assume we have no link for now */
-	netif_stop_queue(netdev);
-	netif_carrier_off(netdev);
-
-	cards_found++;
-
-	return 0;
-
-err_reset:
-err_register:
-err_sw_init:
-err_eeprom:
-	iounmap(adapter->hw.hw_addr);
-err_init_netdev:
-err_ioremap:
-	free_netdev(netdev);
-err_alloc_etherdev:
-	pci_release_regions(pdev);
-err_pci_reg:
-err_dma:
-	pci_disable_device(pdev);
-	return err;
-}
-
-/*
- * atl1e_remove - Device Removal Routine
- * @pdev: PCI device information struct
- *
- * atl1e_remove is called by the PCI subsystem to alert the driver
- * that it should release a PCI device.  The could be caused by a
- * Hot-Plug event, or because the driver is going to be removed from
- * memory.
- */
-static void __devexit atl1e_remove(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-
-	/*
-	 * flush_scheduled work may reschedule our watchdog task, so
-	 * explicitly disable watchdog tasks from being rescheduled
-	 */
-	set_bit(__AT_DOWN, &adapter->flags);
-
-	atl1e_del_timer(adapter);
-	atl1e_cancel_work(adapter);
-
-	unregister_netdev(netdev);
-	atl1e_free_ring_resources(adapter);
-	atl1e_force_ps(&adapter->hw);
-	iounmap(adapter->hw.hw_addr);
-	pci_release_regions(pdev);
-	free_netdev(netdev);
-	pci_disable_device(pdev);
-}
-
-/*
- * atl1e_io_error_detected - called when PCI error is detected
- * @pdev: Pointer to PCI device
- * @state: The current pci connection state
- *
- * This function is called after a PCI bus error affecting
- * this device has been detected.
- */
-static pci_ers_result_t
-atl1e_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-
-	netif_device_detach(netdev);
-
-	if (state == pci_channel_io_perm_failure)
-		return PCI_ERS_RESULT_DISCONNECT;
-
-	if (netif_running(netdev))
-		atl1e_down(adapter);
-
-	pci_disable_device(pdev);
-
-	/* Request a slot slot reset. */
-	return PCI_ERS_RESULT_NEED_RESET;
-}
-
-/*
- * atl1e_io_slot_reset - called after the pci bus has been reset.
- * @pdev: Pointer to PCI device
- *
- * Restart the card from scratch, as if from a cold-boot. Implementation
- * resembles the first-half of the e1000_resume routine.
- */
-static pci_ers_result_t atl1e_io_slot_reset(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-
-	if (pci_enable_device(pdev)) {
-		netdev_err(adapter->netdev,
-			   "Cannot re-enable PCI device after reset\n");
-		return PCI_ERS_RESULT_DISCONNECT;
-	}
-	pci_set_master(pdev);
-
-	pci_enable_wake(pdev, PCI_D3hot, 0);
-	pci_enable_wake(pdev, PCI_D3cold, 0);
-
-	atl1e_reset_hw(&adapter->hw);
-
-	return PCI_ERS_RESULT_RECOVERED;
-}
-
-/*
- * atl1e_io_resume - called when traffic can start flowing again.
- * @pdev: Pointer to PCI device
- *
- * This callback is called when the error recovery driver tells us that
- * its OK to resume normal operation. Implementation resembles the
- * second-half of the atl1e_resume routine.
- */
-static void atl1e_io_resume(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1e_adapter *adapter = netdev_priv(netdev);
-
-	if (netif_running(netdev)) {
-		if (atl1e_up(adapter)) {
-			netdev_err(adapter->netdev,
-				   "can't bring device back up after reset\n");
-			return;
-		}
-	}
-
-	netif_device_attach(netdev);
-}
-
-static struct pci_error_handlers atl1e_err_handler = {
-	.error_detected = atl1e_io_error_detected,
-	.slot_reset = atl1e_io_slot_reset,
-	.resume = atl1e_io_resume,
-};
-
-static struct pci_driver atl1e_driver = {
-	.name     = atl1e_driver_name,
-	.id_table = atl1e_pci_tbl,
-	.probe    = atl1e_probe,
-	.remove   = __devexit_p(atl1e_remove),
-	/* Power Management Hooks */
-#ifdef CONFIG_PM
-	.suspend  = atl1e_suspend,
-	.resume   = atl1e_resume,
-#endif
-	.shutdown = atl1e_shutdown,
-	.err_handler = &atl1e_err_handler
-};
-
-/*
- * atl1e_init_module - Driver Registration Routine
- *
- * atl1e_init_module is the first routine called when the driver is
- * loaded. All it does is register with the PCI subsystem.
- */
-static int __init atl1e_init_module(void)
-{
-	return pci_register_driver(&atl1e_driver);
-}
-
-/*
- * atl1e_exit_module - Driver Exit Cleanup Routine
- *
- * atl1e_exit_module is called just before the driver is removed
- * from memory.
- */
-static void __exit atl1e_exit_module(void)
-{
-	pci_unregister_driver(&atl1e_driver);
-}
-
-module_init(atl1e_init_module);
-module_exit(atl1e_exit_module);
diff -druN linux-libre-3.1-gnu/drivers/net/atl1e/atl1e_param.c linux-libre-3.2-gnu/drivers/net/atl1e/atl1e_param.c
--- linux-libre-3.1-gnu/drivers/net/atl1e/atl1e_param.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atl1e/atl1e_param.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,268 +0,0 @@
-/*
- * Copyright(c) 2007 Atheros Corporation. All rights reserved.
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You 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/netdevice.h>
-
-#include "atl1e.h"
-
-/* This is the only thing that needs to be changed to adjust the
- * maximum number of ports that the driver can manage.
- */
-
-#define ATL1E_MAX_NIC 32
-
-#define OPTION_UNSET    -1
-#define OPTION_DISABLED 0
-#define OPTION_ENABLED  1
-
-/* All parameters are treated the same, as an integer array of values.
- * This macro just reduces the need to repeat the same declaration code
- * over and over (plus this helps to avoid typo bugs).
- */
-#define ATL1E_PARAM_INIT { [0 ... ATL1E_MAX_NIC] = OPTION_UNSET }
-
-#define ATL1E_PARAM(x, desc) \
-	static int __devinitdata x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \
-	static unsigned int num_##x; \
-	module_param_array_named(x, x, int, &num_##x, 0); \
-	MODULE_PARM_DESC(x, desc);
-
-/* Transmit Memory count
- *
- * Valid Range: 64-2048
- *
- * Default Value: 128
- */
-#define ATL1E_MIN_TX_DESC_CNT		32
-#define ATL1E_MAX_TX_DESC_CNT		1020
-#define ATL1E_DEFAULT_TX_DESC_CNT	128
-ATL1E_PARAM(tx_desc_cnt, "Transmit description count");
-
-/* Receive Memory Block Count
- *
- * Valid Range: 16-512
- *
- * Default Value: 128
- */
-#define ATL1E_MIN_RX_MEM_SIZE		8    /* 8KB   */
-#define ATL1E_MAX_RX_MEM_SIZE		1024 /* 1MB   */
-#define ATL1E_DEFAULT_RX_MEM_SIZE	256  /* 128KB */
-ATL1E_PARAM(rx_mem_size, "memory size of rx buffer(KB)");
-
-/* User Specified MediaType Override
- *
- * Valid Range: 0-5
- *  - 0    - auto-negotiate at all supported speeds
- *  - 1    - only link at 100Mbps Full Duplex
- *  - 2    - only link at 100Mbps Half Duplex
- *  - 3    - only link at 10Mbps Full Duplex
- *  - 4    - only link at 10Mbps Half Duplex
- * Default Value: 0
- */
-
-ATL1E_PARAM(media_type, "MediaType Select");
-
-/* Interrupt Moderate Timer in units of 2 us
- *
- * Valid Range: 10-65535
- *
- * Default Value: 45000(90ms)
- */
-#define INT_MOD_DEFAULT_CNT             100 /* 200us */
-#define INT_MOD_MAX_CNT                 65000
-#define INT_MOD_MIN_CNT                 50
-ATL1E_PARAM(int_mod_timer, "Interrupt Moderator Timer");
-
-#define AUTONEG_ADV_DEFAULT  0x2F
-#define AUTONEG_ADV_MASK     0x2F
-#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
-
-#define FLASH_VENDOR_DEFAULT    0
-#define FLASH_VENDOR_MIN        0
-#define FLASH_VENDOR_MAX        2
-
-struct atl1e_option {
-	enum { enable_option, range_option, list_option } type;
-	char *name;
-	char *err;
-	int  def;
-	union {
-		struct { /* range_option info */
-			int min;
-			int max;
-		} r;
-		struct { /* list_option info */
-			int nr;
-			struct atl1e_opt_list { int i; char *str; } *p;
-		} l;
-	} arg;
-};
-
-static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt, struct atl1e_adapter *adapter)
-{
-	if (*value == OPTION_UNSET) {
-		*value = opt->def;
-		return 0;
-	}
-
-	switch (opt->type) {
-	case enable_option:
-		switch (*value) {
-		case OPTION_ENABLED:
-			netdev_info(adapter->netdev,
-				    "%s Enabled\n", opt->name);
-			return 0;
-		case OPTION_DISABLED:
-			netdev_info(adapter->netdev,
-				    "%s Disabled\n", opt->name);
-			return 0;
-		}
-		break;
-	case range_option:
-		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
-			netdev_info(adapter->netdev, "%s set to %i\n",
-				    opt->name, *value);
-			return 0;
-		}
-		break;
-	case list_option:{
-			int i;
-			struct atl1e_opt_list *ent;
-
-			for (i = 0; i < opt->arg.l.nr; i++) {
-				ent = &opt->arg.l.p[i];
-				if (*value == ent->i) {
-					if (ent->str[0] != '\0')
-						netdev_info(adapter->netdev,
-							    "%s\n", ent->str);
-					return 0;
-				}
-			}
-			break;
-		}
-	default:
-		BUG();
-	}
-
-	netdev_info(adapter->netdev, "Invalid %s specified (%i) %s\n",
-		    opt->name, *value, opt->err);
-	*value = opt->def;
-	return -1;
-}
-
-/*
- * atl1e_check_options - Range Checking for Command Line Parameters
- * @adapter: board private structure
- *
- * This routine checks all command line parameters for valid user
- * input.  If an invalid value is given, or if no user specified
- * value exists, a default value is used.  The final value is stored
- * in a variable in the adapter structure.
- */
-void __devinit atl1e_check_options(struct atl1e_adapter *adapter)
-{
-	int bd = adapter->bd_number;
-
-	if (bd >= ATL1E_MAX_NIC) {
-		netdev_notice(adapter->netdev,
-			      "no configuration for board #%i\n", bd);
-		netdev_notice(adapter->netdev,
-			      "Using defaults for all values\n");
-	}
-
-	{ 		/* Transmit Ring Size */
-		struct atl1e_option opt = {
-			.type = range_option,
-			.name = "Transmit Ddescription Count",
-			.err  = "using default of "
-				__MODULE_STRING(ATL1E_DEFAULT_TX_DESC_CNT),
-			.def  = ATL1E_DEFAULT_TX_DESC_CNT,
-			.arg  = { .r = { .min = ATL1E_MIN_TX_DESC_CNT,
-					 .max = ATL1E_MAX_TX_DESC_CNT} }
-		};
-		int val;
-		if (num_tx_desc_cnt > bd) {
-			val = tx_desc_cnt[bd];
-			atl1e_validate_option(&val, &opt, adapter);
-			adapter->tx_ring.count = (u16) val & 0xFFFC;
-		} else
-			adapter->tx_ring.count = (u16)opt.def;
-	}
-
-	{ 		/* Receive Memory Block Count */
-		struct atl1e_option opt = {
-			.type = range_option,
-			.name = "Memory size of rx buffer(KB)",
-			.err  = "using default of "
-				__MODULE_STRING(ATL1E_DEFAULT_RX_MEM_SIZE),
-			.def  = ATL1E_DEFAULT_RX_MEM_SIZE,
-			.arg  = { .r = { .min = ATL1E_MIN_RX_MEM_SIZE,
-					 .max = ATL1E_MAX_RX_MEM_SIZE} }
-		};
-		int val;
-		if (num_rx_mem_size > bd) {
-			val = rx_mem_size[bd];
-			atl1e_validate_option(&val, &opt, adapter);
-			adapter->rx_ring.page_size = (u32)val * 1024;
-		} else {
-			adapter->rx_ring.page_size = (u32)opt.def * 1024;
-		}
-	}
-
-	{ 		/* Interrupt Moderate Timer */
-		struct atl1e_option opt = {
-			.type = range_option,
-			.name = "Interrupt Moderate Timer",
-			.err  = "using default of "
-				__MODULE_STRING(INT_MOD_DEFAULT_CNT),
-			.def  = INT_MOD_DEFAULT_CNT,
-			.arg  = { .r = { .min = INT_MOD_MIN_CNT,
-					 .max = INT_MOD_MAX_CNT} }
-		} ;
-		int val;
-		if (num_int_mod_timer > bd) {
-			val = int_mod_timer[bd];
-			atl1e_validate_option(&val, &opt, adapter);
-			adapter->hw.imt = (u16) val;
-		} else
-			adapter->hw.imt = (u16)(opt.def);
-	}
-
-	{ 		/* MediaType */
-		struct atl1e_option opt = {
-			.type = range_option,
-			.name = "Speed/Duplex Selection",
-			.err  = "using default of "
-				__MODULE_STRING(MEDIA_TYPE_AUTO_SENSOR),
-			.def  = MEDIA_TYPE_AUTO_SENSOR,
-			.arg  = { .r = { .min = MEDIA_TYPE_AUTO_SENSOR,
-					 .max = MEDIA_TYPE_10M_HALF} }
-		} ;
-		int val;
-		if (num_media_type > bd) {
-			val = media_type[bd];
-			atl1e_validate_option(&val, &opt, adapter);
-			adapter->hw.media_type = (u16) val;
-		} else
-			adapter->hw.media_type = (u16)(opt.def);
-
-	}
-}
diff -druN linux-libre-3.1-gnu/drivers/net/atl1e/Makefile linux-libre-3.2-gnu/drivers/net/atl1e/Makefile
--- linux-libre-3.1-gnu/drivers/net/atl1e/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atl1e/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,2 +0,0 @@
-obj-$(CONFIG_ATL1E)	+= atl1e.o
-atl1e-objs		+= atl1e_main.o atl1e_hw.o atl1e_ethtool.o atl1e_param.o
diff -druN linux-libre-3.1-gnu/drivers/net/atlx/atl1.c linux-libre-3.2-gnu/drivers/net/atlx/atl1.c
--- linux-libre-3.1-gnu/drivers/net/atlx/atl1.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atlx/atl1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3675 +0,0 @@
-/*
- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
- * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com>
- * Copyright(c) 2006 - 2008 Jay Cliburn <jcliburn@gmail.com>
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called COPYING.
- *
- * Contact Information:
- * Xiong Huang <xiong.huang@atheros.com>
- * Jie Yang <jie.yang@atheros.com>
- * Chris Snook <csnook@redhat.com>
- * Jay Cliburn <jcliburn@gmail.com>
- *
- * This version is adapted from the Attansic reference driver.
- *
- * TODO:
- * Add more ethtool functions.
- * Fix abstruse irq enable/disable condition described here:
- *	http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2
- *
- * NEEDS TESTING:
- * VLAN
- * multicast
- * promiscuous mode
- * interrupt coalescing
- * SMP torture testing
- */
-
-#include <linux/atomic.h>
-#include <asm/byteorder.h>
-
-#include <linux/compiler.h>
-#include <linux/crc32.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/etherdevice.h>
-#include <linux/hardirq.h>
-#include <linux/if_ether.h>
-#include <linux/if_vlan.h>
-#include <linux/in.h>
-#include <linux/interrupt.h>
-#include <linux/ip.h>
-#include <linux/irqflags.h>
-#include <linux/irqreturn.h>
-#include <linux/jiffies.h>
-#include <linux/mii.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/net.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
-#include <linux/pm.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/tcp.h>
-#include <linux/timer.h>
-#include <linux/types.h>
-#include <linux/workqueue.h>
-
-#include <net/checksum.h>
-
-#include "atl1.h"
-
-#define ATLX_DRIVER_VERSION "2.1.3"
-MODULE_AUTHOR("Xiong Huang <xiong.huang@atheros.com>, "
-	      "Chris Snook <csnook@redhat.com>, "
-	      "Jay Cliburn <jcliburn@gmail.com>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(ATLX_DRIVER_VERSION);
-
-/* Temporary hack for merging atl1 and atl2 */
-#include "atlx.c"
-
-static const struct ethtool_ops atl1_ethtool_ops;
-
-/*
- * This is the only thing that needs to be changed to adjust the
- * maximum number of ports that the driver can manage.
- */
-#define ATL1_MAX_NIC 4
-
-#define OPTION_UNSET    -1
-#define OPTION_DISABLED 0
-#define OPTION_ENABLED  1
-
-#define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
-
-/*
- * Interrupt Moderate Timer in units of 2 us
- *
- * Valid Range: 10-65535
- *
- * Default Value: 100 (200us)
- */
-static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
-static unsigned int num_int_mod_timer;
-module_param_array_named(int_mod_timer, int_mod_timer, int,
-	&num_int_mod_timer, 0);
-MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer");
-
-#define DEFAULT_INT_MOD_CNT	100	/* 200us */
-#define MAX_INT_MOD_CNT		65000
-#define MIN_INT_MOD_CNT		50
-
-struct atl1_option {
-	enum { enable_option, range_option, list_option } type;
-	char *name;
-	char *err;
-	int def;
-	union {
-		struct {	/* range_option info */
-			int min;
-			int max;
-		} r;
-		struct {	/* list_option info */
-			int nr;
-			struct atl1_opt_list {
-				int i;
-				char *str;
-			} *p;
-		} l;
-	} arg;
-};
-
-static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
-	struct pci_dev *pdev)
-{
-	if (*value == OPTION_UNSET) {
-		*value = opt->def;
-		return 0;
-	}
-
-	switch (opt->type) {
-	case enable_option:
-		switch (*value) {
-		case OPTION_ENABLED:
-			dev_info(&pdev->dev, "%s enabled\n", opt->name);
-			return 0;
-		case OPTION_DISABLED:
-			dev_info(&pdev->dev, "%s disabled\n", opt->name);
-			return 0;
-		}
-		break;
-	case range_option:
-		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
-			dev_info(&pdev->dev, "%s set to %i\n", opt->name,
-				*value);
-			return 0;
-		}
-		break;
-	case list_option:{
-			int i;
-			struct atl1_opt_list *ent;
-
-			for (i = 0; i < opt->arg.l.nr; i++) {
-				ent = &opt->arg.l.p[i];
-				if (*value == ent->i) {
-					if (ent->str[0] != '\0')
-						dev_info(&pdev->dev, "%s\n",
-							ent->str);
-					return 0;
-				}
-			}
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	dev_info(&pdev->dev, "invalid %s specified (%i) %s\n",
-		opt->name, *value, opt->err);
-	*value = opt->def;
-	return -1;
-}
-
-/*
- * atl1_check_options - Range Checking for Command Line Parameters
- * @adapter: board private structure
- *
- * This routine checks all command line parameters for valid user
- * input.  If an invalid value is given, or if no user specified
- * value exists, a default value is used.  The final value is stored
- * in a variable in the adapter structure.
- */
-static void __devinit atl1_check_options(struct atl1_adapter *adapter)
-{
-	struct pci_dev *pdev = adapter->pdev;
-	int bd = adapter->bd_number;
-	if (bd >= ATL1_MAX_NIC) {
-		dev_notice(&pdev->dev, "no configuration for board#%i\n", bd);
-		dev_notice(&pdev->dev, "using defaults for all values\n");
-	}
-	{			/* Interrupt Moderate Timer */
-		struct atl1_option opt = {
-			.type = range_option,
-			.name = "Interrupt Moderator Timer",
-			.err = "using default of "
-				__MODULE_STRING(DEFAULT_INT_MOD_CNT),
-			.def = DEFAULT_INT_MOD_CNT,
-			.arg = {.r = {.min = MIN_INT_MOD_CNT,
-					.max = MAX_INT_MOD_CNT} }
-		};
-		int val;
-		if (num_int_mod_timer > bd) {
-			val = int_mod_timer[bd];
-			atl1_validate_option(&val, &opt, pdev);
-			adapter->imt = (u16) val;
-		} else
-			adapter->imt = (u16) (opt.def);
-	}
-}
-
-/*
- * atl1_pci_tbl - PCI Device ID Table
- */
-static DEFINE_PCI_DEVICE_TABLE(atl1_pci_tbl) = {
-	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)},
-	/* required last entry */
-	{0,}
-};
-MODULE_DEVICE_TABLE(pci, atl1_pci_tbl);
-
-static const u32 atl1_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
-	NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP;
-
-static int debug = -1;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Message level (0=none,...,16=all)");
-
-/*
- * Reset the transmit and receive units; mask and clear all interrupts.
- * hw - Struct containing variables accessed by shared code
- * return : 0  or  idle status (if error)
- */
-static s32 atl1_reset_hw(struct atl1_hw *hw)
-{
-	struct pci_dev *pdev = hw->back->pdev;
-	struct atl1_adapter *adapter = hw->back;
-	u32 icr;
-	int i;
-
-	/*
-	 * Clear Interrupt mask to stop board from generating
-	 * interrupts & Clear any pending interrupt events
-	 */
-	/*
-	 * iowrite32(0, hw->hw_addr + REG_IMR);
-	 * iowrite32(0xffffffff, hw->hw_addr + REG_ISR);
-	 */
-
-	/*
-	 * Issue Soft Reset to the MAC.  This will reset the chip's
-	 * transmit, receive, DMA.  It will not effect
-	 * the current PCI configuration.  The global reset bit is self-
-	 * clearing, and should clear within a microsecond.
-	 */
-	iowrite32(MASTER_CTRL_SOFT_RST, hw->hw_addr + REG_MASTER_CTRL);
-	ioread32(hw->hw_addr + REG_MASTER_CTRL);
-
-	iowrite16(1, hw->hw_addr + REG_PHY_ENABLE);
-	ioread16(hw->hw_addr + REG_PHY_ENABLE);
-
-	/* delay about 1ms */
-	msleep(1);
-
-	/* Wait at least 10ms for All module to be Idle */
-	for (i = 0; i < 10; i++) {
-		icr = ioread32(hw->hw_addr + REG_IDLE_STATUS);
-		if (!icr)
-			break;
-		/* delay 1 ms */
-		msleep(1);
-		/* FIXME: still the right way to do this? */
-		cpu_relax();
-	}
-
-	if (icr) {
-		if (netif_msg_hw(adapter))
-			dev_dbg(&pdev->dev, "ICR = 0x%x\n", icr);
-		return icr;
-	}
-
-	return 0;
-}
-
-/* function about EEPROM
- *
- * check_eeprom_exist
- * return 0 if eeprom exist
- */
-static int atl1_check_eeprom_exist(struct atl1_hw *hw)
-{
-	u32 value;
-	value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
-	if (value & SPI_FLASH_CTRL_EN_VPD) {
-		value &= ~SPI_FLASH_CTRL_EN_VPD;
-		iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
-	}
-
-	value = ioread16(hw->hw_addr + REG_PCIE_CAP_LIST);
-	return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
-}
-
-static bool atl1_read_eeprom(struct atl1_hw *hw, u32 offset, u32 *p_value)
-{
-	int i;
-	u32 control;
-
-	if (offset & 3)
-		/* address do not align */
-		return false;
-
-	iowrite32(0, hw->hw_addr + REG_VPD_DATA);
-	control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
-	iowrite32(control, hw->hw_addr + REG_VPD_CAP);
-	ioread32(hw->hw_addr + REG_VPD_CAP);
-
-	for (i = 0; i < 10; i++) {
-		msleep(2);
-		control = ioread32(hw->hw_addr + REG_VPD_CAP);
-		if (control & VPD_CAP_VPD_FLAG)
-			break;
-	}
-	if (control & VPD_CAP_VPD_FLAG) {
-		*p_value = ioread32(hw->hw_addr + REG_VPD_DATA);
-		return true;
-	}
-	/* timeout */
-	return false;
-}
-
-/*
- * Reads the value from a PHY register
- * hw - Struct containing variables accessed by shared code
- * reg_addr - address of the PHY register to read
- */
-static s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data)
-{
-	u32 val;
-	int i;
-
-	val = ((u32) (reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
-		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | MDIO_CLK_25_4 <<
-		MDIO_CLK_SEL_SHIFT;
-	iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
-	ioread32(hw->hw_addr + REG_MDIO_CTRL);
-
-	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
-		udelay(2);
-		val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
-		if (!(val & (MDIO_START | MDIO_BUSY)))
-			break;
-	}
-	if (!(val & (MDIO_START | MDIO_BUSY))) {
-		*phy_data = (u16) val;
-		return 0;
-	}
-	return ATLX_ERR_PHY;
-}
-
-#define CUSTOM_SPI_CS_SETUP	2
-#define CUSTOM_SPI_CLK_HI	2
-#define CUSTOM_SPI_CLK_LO	2
-#define CUSTOM_SPI_CS_HOLD	2
-#define CUSTOM_SPI_CS_HI	3
-
-static bool atl1_spi_read(struct atl1_hw *hw, u32 addr, u32 *buf)
-{
-	int i;
-	u32 value;
-
-	iowrite32(0, hw->hw_addr + REG_SPI_DATA);
-	iowrite32(addr, hw->hw_addr + REG_SPI_ADDR);
-
-	value = SPI_FLASH_CTRL_WAIT_READY |
-	    (CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) <<
-	    SPI_FLASH_CTRL_CS_SETUP_SHIFT | (CUSTOM_SPI_CLK_HI &
-					     SPI_FLASH_CTRL_CLK_HI_MASK) <<
-	    SPI_FLASH_CTRL_CLK_HI_SHIFT | (CUSTOM_SPI_CLK_LO &
-					   SPI_FLASH_CTRL_CLK_LO_MASK) <<
-	    SPI_FLASH_CTRL_CLK_LO_SHIFT | (CUSTOM_SPI_CS_HOLD &
-					   SPI_FLASH_CTRL_CS_HOLD_MASK) <<
-	    SPI_FLASH_CTRL_CS_HOLD_SHIFT | (CUSTOM_SPI_CS_HI &
-					    SPI_FLASH_CTRL_CS_HI_MASK) <<
-	    SPI_FLASH_CTRL_CS_HI_SHIFT | (1 & SPI_FLASH_CTRL_INS_MASK) <<
-	    SPI_FLASH_CTRL_INS_SHIFT;
-
-	iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
-
-	value |= SPI_FLASH_CTRL_START;
-	iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
-	ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
-
-	for (i = 0; i < 10; i++) {
-		msleep(1);
-		value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
-		if (!(value & SPI_FLASH_CTRL_START))
-			break;
-	}
-
-	if (value & SPI_FLASH_CTRL_START)
-		return false;
-
-	*buf = ioread32(hw->hw_addr + REG_SPI_DATA);
-
-	return true;
-}
-
-/*
- * get_permanent_address
- * return 0 if get valid mac address,
- */
-static int atl1_get_permanent_address(struct atl1_hw *hw)
-{
-	u32 addr[2];
-	u32 i, control;
-	u16 reg;
-	u8 eth_addr[ETH_ALEN];
-	bool key_valid;
-
-	if (is_valid_ether_addr(hw->perm_mac_addr))
-		return 0;
-
-	/* init */
-	addr[0] = addr[1] = 0;
-
-	if (!atl1_check_eeprom_exist(hw)) {
-		reg = 0;
-		key_valid = false;
-		/* Read out all EEPROM content */
-		i = 0;
-		while (1) {
-			if (atl1_read_eeprom(hw, i + 0x100, &control)) {
-				if (key_valid) {
-					if (reg == REG_MAC_STA_ADDR)
-						addr[0] = control;
-					else if (reg == (REG_MAC_STA_ADDR + 4))
-						addr[1] = control;
-					key_valid = false;
-				} else if ((control & 0xff) == 0x5A) {
-					key_valid = true;
-					reg = (u16) (control >> 16);
-				} else
-					break;
-			} else
-				/* read error */
-				break;
-			i += 4;
-		}
-
-		*(u32 *) &eth_addr[2] = swab32(addr[0]);
-		*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
-		if (is_valid_ether_addr(eth_addr)) {
-			memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
-			return 0;
-		}
-	}
-
-	/* see if SPI FLAGS exist ? */
-	addr[0] = addr[1] = 0;
-	reg = 0;
-	key_valid = false;
-	i = 0;
-	while (1) {
-		if (atl1_spi_read(hw, i + 0x1f000, &control)) {
-			if (key_valid) {
-				if (reg == REG_MAC_STA_ADDR)
-					addr[0] = control;
-				else if (reg == (REG_MAC_STA_ADDR + 4))
-					addr[1] = control;
-				key_valid = false;
-			} else if ((control & 0xff) == 0x5A) {
-				key_valid = true;
-				reg = (u16) (control >> 16);
-			} else
-				/* data end */
-				break;
-		} else
-			/* read error */
-			break;
-		i += 4;
-	}
-
-	*(u32 *) &eth_addr[2] = swab32(addr[0]);
-	*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
-	if (is_valid_ether_addr(eth_addr)) {
-		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
-		return 0;
-	}
-
-	/*
-	 * On some motherboards, the MAC address is written by the
-	 * BIOS directly to the MAC register during POST, and is
-	 * not stored in eeprom.  If all else thus far has failed
-	 * to fetch the permanent MAC address, try reading it directly.
-	 */
-	addr[0] = ioread32(hw->hw_addr + REG_MAC_STA_ADDR);
-	addr[1] = ioread16(hw->hw_addr + (REG_MAC_STA_ADDR + 4));
-	*(u32 *) &eth_addr[2] = swab32(addr[0]);
-	*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
-	if (is_valid_ether_addr(eth_addr)) {
-		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
-		return 0;
-	}
-
-	return 1;
-}
-
-/*
- * Reads the adapter's MAC address from the EEPROM
- * hw - Struct containing variables accessed by shared code
- */
-static s32 atl1_read_mac_addr(struct atl1_hw *hw)
-{
-	u16 i;
-
-	if (atl1_get_permanent_address(hw))
-		random_ether_addr(hw->perm_mac_addr);
-
-	for (i = 0; i < ETH_ALEN; i++)
-		hw->mac_addr[i] = hw->perm_mac_addr[i];
-	return 0;
-}
-
-/*
- * Hashes an address to determine its location in the multicast table
- * hw - Struct containing variables accessed by shared code
- * mc_addr - the multicast address to hash
- *
- * atl1_hash_mc_addr
- *  purpose
- *      set hash value for a multicast address
- *      hash calcu processing :
- *          1. calcu 32bit CRC for multicast address
- *          2. reverse crc with MSB to LSB
- */
-static u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr)
-{
-	u32 crc32, value = 0;
-	int i;
-
-	crc32 = ether_crc_le(6, mc_addr);
-	for (i = 0; i < 32; i++)
-		value |= (((crc32 >> i) & 1) << (31 - i));
-
-	return value;
-}
-
-/*
- * Sets the bit in the multicast table corresponding to the hash value.
- * hw - Struct containing variables accessed by shared code
- * hash_value - Multicast address hash value
- */
-static void atl1_hash_set(struct atl1_hw *hw, u32 hash_value)
-{
-	u32 hash_bit, hash_reg;
-	u32 mta;
-
-	/*
-	 * The HASH Table  is a register array of 2 32-bit registers.
-	 * It is treated like an array of 64 bits.  We want to set
-	 * bit BitArray[hash_value]. So we figure out what register
-	 * the bit is in, read it, OR in the new bit, then write
-	 * back the new value.  The register is determined by the
-	 * upper 7 bits of the hash value and the bit within that
-	 * register are determined by the lower 5 bits of the value.
-	 */
-	hash_reg = (hash_value >> 31) & 0x1;
-	hash_bit = (hash_value >> 26) & 0x1F;
-	mta = ioread32((hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
-	mta |= (1 << hash_bit);
-	iowrite32(mta, (hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
-}
-
-/*
- * Writes a value to a PHY register
- * hw - Struct containing variables accessed by shared code
- * reg_addr - address of the PHY register to write
- * data - data to write to the PHY
- */
-static s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data)
-{
-	int i;
-	u32 val;
-
-	val = ((u32) (phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
-	    (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
-	    MDIO_SUP_PREAMBLE |
-	    MDIO_START | MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
-	iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
-	ioread32(hw->hw_addr + REG_MDIO_CTRL);
-
-	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
-		udelay(2);
-		val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
-		if (!(val & (MDIO_START | MDIO_BUSY)))
-			break;
-	}
-
-	if (!(val & (MDIO_START | MDIO_BUSY)))
-		return 0;
-
-	return ATLX_ERR_PHY;
-}
-
-/*
- * Make L001's PHY out of Power Saving State (bug)
- * hw - Struct containing variables accessed by shared code
- * when power on, L001's PHY always on Power saving State
- * (Gigabit Link forbidden)
- */
-static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw)
-{
-	s32 ret;
-	ret = atl1_write_phy_reg(hw, 29, 0x0029);
-	if (ret)
-		return ret;
-	return atl1_write_phy_reg(hw, 30, 0);
-}
-
-/*
- * Resets the PHY and make all config validate
- * hw - Struct containing variables accessed by shared code
- *
- * Sets bit 15 and 12 of the MII Control regiser (for F001 bug)
- */
-static s32 atl1_phy_reset(struct atl1_hw *hw)
-{
-	struct pci_dev *pdev = hw->back->pdev;
-	struct atl1_adapter *adapter = hw->back;
-	s32 ret_val;
-	u16 phy_data;
-
-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
-	    hw->media_type == MEDIA_TYPE_1000M_FULL)
-		phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
-	else {
-		switch (hw->media_type) {
-		case MEDIA_TYPE_100M_FULL:
-			phy_data =
-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
-			    MII_CR_RESET;
-			break;
-		case MEDIA_TYPE_100M_HALF:
-			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
-			break;
-		case MEDIA_TYPE_10M_FULL:
-			phy_data =
-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
-			break;
-		default:
-			/* MEDIA_TYPE_10M_HALF: */
-			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
-			break;
-		}
-	}
-
-	ret_val = atl1_write_phy_reg(hw, MII_BMCR, phy_data);
-	if (ret_val) {
-		u32 val;
-		int i;
-		/* pcie serdes link may be down! */
-		if (netif_msg_hw(adapter))
-			dev_dbg(&pdev->dev, "pcie phy link down\n");
-
-		for (i = 0; i < 25; i++) {
-			msleep(1);
-			val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
-			if (!(val & (MDIO_START | MDIO_BUSY)))
-				break;
-		}
-
-		if ((val & (MDIO_START | MDIO_BUSY)) != 0) {
-			if (netif_msg_hw(adapter))
-				dev_warn(&pdev->dev,
-					"pcie link down at least 25ms\n");
-			return ret_val;
-		}
-	}
-	return 0;
-}
-
-/*
- * Configures PHY autoneg and flow control advertisement settings
- * hw - Struct containing variables accessed by shared code
- */
-static s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw)
-{
-	s32 ret_val;
-	s16 mii_autoneg_adv_reg;
-	s16 mii_1000t_ctrl_reg;
-
-	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
-	mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
-
-	/* Read the MII 1000Base-T Control Register (Address 9). */
-	mii_1000t_ctrl_reg = MII_ATLX_CR_1000T_DEFAULT_CAP_MASK;
-
-	/*
-	 * First we clear all the 10/100 mb speed bits in the Auto-Neg
-	 * 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_1000t_ctrl_reg &= ~MII_ATLX_CR_1000T_SPEED_MASK;
-
-	/*
-	 * Need to parse media_type  and set up
-	 * the appropriate PHY registers.
-	 */
-	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);
-		mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS;
-		break;
-
-	case MEDIA_TYPE_1000M_FULL:
-		mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS;
-		break;
-
-	case MEDIA_TYPE_100M_FULL:
-		mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
-		break;
-
-	case MEDIA_TYPE_100M_HALF:
-		mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
-		break;
-
-	case MEDIA_TYPE_10M_FULL:
-		mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
-		break;
-
-	default:
-		mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
-		break;
-	}
-
-	/* flow control fixed to enable all */
-	mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
-
-	hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
-	hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
-
-	ret_val = atl1_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = atl1_write_phy_reg(hw, MII_ATLX_CR, mii_1000t_ctrl_reg);
-	if (ret_val)
-		return ret_val;
-
-	return 0;
-}
-
-/*
- * Configures link settings.
- * hw - Struct containing variables accessed by shared code
- * Assumes the hardware has previously been reset and the
- * transmitter and receiver are not enabled.
- */
-static s32 atl1_setup_link(struct atl1_hw *hw)
-{
-	struct pci_dev *pdev = hw->back->pdev;
-	struct atl1_adapter *adapter = hw->back;
-	s32 ret_val;
-
-	/*
-	 * Options:
-	 *  PHY will advertise value(s) parsed from
-	 *  autoneg_advertised and fc
-	 *  no matter what autoneg is , We will not wait link result.
-	 */
-	ret_val = atl1_phy_setup_autoneg_adv(hw);
-	if (ret_val) {
-		if (netif_msg_link(adapter))
-			dev_dbg(&pdev->dev,
-				"error setting up autonegotiation\n");
-		return ret_val;
-	}
-	/* SW.Reset , En-Auto-Neg if needed */
-	ret_val = atl1_phy_reset(hw);
-	if (ret_val) {
-		if (netif_msg_link(adapter))
-			dev_dbg(&pdev->dev, "error resetting phy\n");
-		return ret_val;
-	}
-	hw->phy_configured = true;
-	return ret_val;
-}
-
-static void atl1_init_flash_opcode(struct atl1_hw *hw)
-{
-	if (hw->flash_vendor >= ARRAY_SIZE(flash_table))
-		/* Atmel */
-		hw->flash_vendor = 0;
-
-	/* Init OP table */
-	iowrite8(flash_table[hw->flash_vendor].cmd_program,
-		hw->hw_addr + REG_SPI_FLASH_OP_PROGRAM);
-	iowrite8(flash_table[hw->flash_vendor].cmd_sector_erase,
-		hw->hw_addr + REG_SPI_FLASH_OP_SC_ERASE);
-	iowrite8(flash_table[hw->flash_vendor].cmd_chip_erase,
-		hw->hw_addr + REG_SPI_FLASH_OP_CHIP_ERASE);
-	iowrite8(flash_table[hw->flash_vendor].cmd_rdid,
-		hw->hw_addr + REG_SPI_FLASH_OP_RDID);
-	iowrite8(flash_table[hw->flash_vendor].cmd_wren,
-		hw->hw_addr + REG_SPI_FLASH_OP_WREN);
-	iowrite8(flash_table[hw->flash_vendor].cmd_rdsr,
-		hw->hw_addr + REG_SPI_FLASH_OP_RDSR);
-	iowrite8(flash_table[hw->flash_vendor].cmd_wrsr,
-		hw->hw_addr + REG_SPI_FLASH_OP_WRSR);
-	iowrite8(flash_table[hw->flash_vendor].cmd_read,
-		hw->hw_addr + REG_SPI_FLASH_OP_READ);
-}
-
-/*
- * Performs basic configuration of the adapter.
- * hw - Struct containing variables accessed by shared code
- * Assumes that the controller has previously been reset and is in a
- * post-reset uninitialized state. Initializes multicast table,
- * and  Calls routines to setup link
- * Leaves the transmit and receive units disabled and uninitialized.
- */
-static s32 atl1_init_hw(struct atl1_hw *hw)
-{
-	u32 ret_val = 0;
-
-	/* Zero out the Multicast HASH table */
-	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
-	/* clear the old settings from the multicast hash table */
-	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
-
-	atl1_init_flash_opcode(hw);
-
-	if (!hw->phy_configured) {
-		/* enable GPHY LinkChange Interrrupt */
-		ret_val = atl1_write_phy_reg(hw, 18, 0xC00);
-		if (ret_val)
-			return ret_val;
-		/* make PHY out of power-saving state */
-		ret_val = atl1_phy_leave_power_saving(hw);
-		if (ret_val)
-			return ret_val;
-		/* Call a subroutine to configure the link */
-		ret_val = atl1_setup_link(hw);
-	}
-	return ret_val;
-}
-
-/*
- * Detects the current speed and duplex settings of the hardware.
- * hw - Struct containing variables accessed by shared code
- * speed - Speed of the connection
- * duplex - Duplex setting of the connection
- */
-static s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex)
-{
-	struct pci_dev *pdev = hw->back->pdev;
-	struct atl1_adapter *adapter = hw->back;
-	s32 ret_val;
-	u16 phy_data;
-
-	/* ; --- Read   PHY Specific Status Register (17) */
-	ret_val = atl1_read_phy_reg(hw, MII_ATLX_PSSR, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	if (!(phy_data & MII_ATLX_PSSR_SPD_DPLX_RESOLVED))
-		return ATLX_ERR_PHY_RES;
-
-	switch (phy_data & MII_ATLX_PSSR_SPEED) {
-	case MII_ATLX_PSSR_1000MBS:
-		*speed = SPEED_1000;
-		break;
-	case MII_ATLX_PSSR_100MBS:
-		*speed = SPEED_100;
-		break;
-	case MII_ATLX_PSSR_10MBS:
-		*speed = SPEED_10;
-		break;
-	default:
-		if (netif_msg_hw(adapter))
-			dev_dbg(&pdev->dev, "error getting speed\n");
-		return ATLX_ERR_PHY_SPEED;
-		break;
-	}
-	if (phy_data & MII_ATLX_PSSR_DPLX)
-		*duplex = FULL_DUPLEX;
-	else
-		*duplex = HALF_DUPLEX;
-
-	return 0;
-}
-
-static void atl1_set_mac_addr(struct atl1_hw *hw)
-{
-	u32 value;
-	/*
-	 * 00-0B-6A-F6-00-DC
-	 * 0:  6AF600DC   1: 000B
-	 * low dword
-	 */
-	value = (((u32) hw->mac_addr[2]) << 24) |
-	    (((u32) hw->mac_addr[3]) << 16) |
-	    (((u32) hw->mac_addr[4]) << 8) | (((u32) hw->mac_addr[5]));
-	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
-	/* high dword */
-	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
-	iowrite32(value, (hw->hw_addr + REG_MAC_STA_ADDR) + (1 << 2));
-}
-
-/*
- * atl1_sw_init - Initialize general software structures (struct atl1_adapter)
- * @adapter: board private structure to initialize
- *
- * atl1_sw_init initializes the Adapter private data structure.
- * Fields are initialized based on PCI device information and
- * OS network device settings (MTU size).
- */
-static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
-{
-	struct atl1_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-
-	hw->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
-	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 */
-	adapter->link_duplex = FULL_DUPLEX;
-
-	hw->phy_configured = false;
-	hw->preamble_len = 7;
-	hw->ipgt = 0x60;
-	hw->min_ifg = 0x50;
-	hw->ipgr1 = 0x40;
-	hw->ipgr2 = 0x60;
-	hw->max_retry = 0xf;
-	hw->lcol = 0x37;
-	hw->jam_ipg = 7;
-	hw->rfd_burst = 8;
-	hw->rrd_burst = 8;
-	hw->rfd_fetch_gap = 1;
-	hw->rx_jumbo_th = adapter->rx_buffer_len / 8;
-	hw->rx_jumbo_lkah = 1;
-	hw->rrd_ret_timer = 16;
-	hw->tpd_burst = 4;
-	hw->tpd_fetch_th = 16;
-	hw->txf_burst = 0x100;
-	hw->tx_jumbo_task_th = (hw->max_frame_size + 7) >> 3;
-	hw->tpd_fetch_gap = 1;
-	hw->rcb_value = atl1_rcb_64;
-	hw->dma_ord = atl1_dma_ord_enh;
-	hw->dmar_block = atl1_dma_req_256;
-	hw->dmaw_block = atl1_dma_req_256;
-	hw->cmb_rrd = 4;
-	hw->cmb_tpd = 4;
-	hw->cmb_rx_timer = 1;	/* about 2us */
-	hw->cmb_tx_timer = 1;	/* about 2us */
-	hw->smb_timer = 100000;	/* about 200ms */
-
-	spin_lock_init(&adapter->lock);
-	spin_lock_init(&adapter->mb_lock);
-
-	return 0;
-}
-
-static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	u16 result;
-
-	atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
-
-	return result;
-}
-
-static void mdio_write(struct net_device *netdev, int phy_id, int reg_num,
-	int val)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-
-	atl1_write_phy_reg(&adapter->hw, reg_num, val);
-}
-
-/*
- * atl1_mii_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- */
-static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	unsigned long flags;
-	int retval;
-
-	if (!netif_running(netdev))
-		return -EINVAL;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
-	spin_unlock_irqrestore(&adapter->lock, flags);
-
-	return retval;
-}
-
-/*
- * atl1_setup_mem_resources - allocate Tx / RX descriptor resources
- * @adapter: board private structure
- *
- * Return 0 on success, negative on failure
- */
-static s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
-{
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
-	struct atl1_ring_header *ring_header = &adapter->ring_header;
-	struct pci_dev *pdev = adapter->pdev;
-	int size;
-	u8 offset = 0;
-
-	size = sizeof(struct atl1_buffer) * (tpd_ring->count + rfd_ring->count);
-	tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
-	if (unlikely(!tpd_ring->buffer_info)) {
-		if (netif_msg_drv(adapter))
-			dev_err(&pdev->dev, "kzalloc failed , size = D%d\n",
-				size);
-		goto err_nomem;
-	}
-	rfd_ring->buffer_info =
-		(struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
-
-	/*
-	 * real ring DMA buffer
-	 * each ring/block may need up to 8 bytes for alignment, hence the
-	 * additional 40 bytes tacked onto the end.
-	 */
-	ring_header->size = size =
-		sizeof(struct tx_packet_desc) * tpd_ring->count
-		+ sizeof(struct rx_free_desc) * rfd_ring->count
-		+ sizeof(struct rx_return_desc) * rrd_ring->count
-		+ sizeof(struct coals_msg_block)
-		+ sizeof(struct stats_msg_block)
-		+ 40;
-
-	ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
-		&ring_header->dma);
-	if (unlikely(!ring_header->desc)) {
-		if (netif_msg_drv(adapter))
-			dev_err(&pdev->dev, "pci_alloc_consistent failed\n");
-		goto err_nomem;
-	}
-
-	memset(ring_header->desc, 0, ring_header->size);
-
-	/* init TPD ring */
-	tpd_ring->dma = ring_header->dma;
-	offset = (tpd_ring->dma & 0x7) ? (8 - (ring_header->dma & 0x7)) : 0;
-	tpd_ring->dma += offset;
-	tpd_ring->desc = (u8 *) ring_header->desc + offset;
-	tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count;
-
-	/* init RFD ring */
-	rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
-	offset = (rfd_ring->dma & 0x7) ? (8 - (rfd_ring->dma & 0x7)) : 0;
-	rfd_ring->dma += offset;
-	rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset);
-	rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count;
-
-
-	/* init RRD ring */
-	rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
-	offset = (rrd_ring->dma & 0x7) ? (8 - (rrd_ring->dma & 0x7)) : 0;
-	rrd_ring->dma += offset;
-	rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset);
-	rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count;
-
-
-	/* init CMB */
-	adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
-	offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0;
-	adapter->cmb.dma += offset;
-	adapter->cmb.cmb = (struct coals_msg_block *)
-		((u8 *) rrd_ring->desc + (rrd_ring->size + offset));
-
-	/* init SMB */
-	adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block);
-	offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0;
-	adapter->smb.dma += offset;
-	adapter->smb.smb = (struct stats_msg_block *)
-		((u8 *) adapter->cmb.cmb +
-		(sizeof(struct coals_msg_block) + offset));
-
-	return 0;
-
-err_nomem:
-	kfree(tpd_ring->buffer_info);
-	return -ENOMEM;
-}
-
-static void atl1_init_ring_ptrs(struct atl1_adapter *adapter)
-{
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
-
-	atomic_set(&tpd_ring->next_to_use, 0);
-	atomic_set(&tpd_ring->next_to_clean, 0);
-
-	rfd_ring->next_to_clean = 0;
-	atomic_set(&rfd_ring->next_to_use, 0);
-
-	rrd_ring->next_to_use = 0;
-	atomic_set(&rrd_ring->next_to_clean, 0);
-}
-
-/*
- * atl1_clean_rx_ring - Free RFD Buffers
- * @adapter: board private structure
- */
-static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
-{
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
-	struct atl1_buffer *buffer_info;
-	struct pci_dev *pdev = adapter->pdev;
-	unsigned long size;
-	unsigned int i;
-
-	/* Free all the Rx ring sk_buffs */
-	for (i = 0; i < rfd_ring->count; i++) {
-		buffer_info = &rfd_ring->buffer_info[i];
-		if (buffer_info->dma) {
-			pci_unmap_page(pdev, buffer_info->dma,
-				buffer_info->length, PCI_DMA_FROMDEVICE);
-			buffer_info->dma = 0;
-		}
-		if (buffer_info->skb) {
-			dev_kfree_skb(buffer_info->skb);
-			buffer_info->skb = NULL;
-		}
-	}
-
-	size = sizeof(struct atl1_buffer) * rfd_ring->count;
-	memset(rfd_ring->buffer_info, 0, size);
-
-	/* Zero out the descriptor ring */
-	memset(rfd_ring->desc, 0, rfd_ring->size);
-
-	rfd_ring->next_to_clean = 0;
-	atomic_set(&rfd_ring->next_to_use, 0);
-
-	rrd_ring->next_to_use = 0;
-	atomic_set(&rrd_ring->next_to_clean, 0);
-}
-
-/*
- * atl1_clean_tx_ring - Free Tx Buffers
- * @adapter: board private structure
- */
-static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
-{
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_buffer *buffer_info;
-	struct pci_dev *pdev = adapter->pdev;
-	unsigned long size;
-	unsigned int i;
-
-	/* Free all the Tx ring sk_buffs */
-	for (i = 0; i < tpd_ring->count; i++) {
-		buffer_info = &tpd_ring->buffer_info[i];
-		if (buffer_info->dma) {
-			pci_unmap_page(pdev, buffer_info->dma,
-				buffer_info->length, PCI_DMA_TODEVICE);
-			buffer_info->dma = 0;
-		}
-	}
-
-	for (i = 0; i < tpd_ring->count; i++) {
-		buffer_info = &tpd_ring->buffer_info[i];
-		if (buffer_info->skb) {
-			dev_kfree_skb_any(buffer_info->skb);
-			buffer_info->skb = NULL;
-		}
-	}
-
-	size = sizeof(struct atl1_buffer) * tpd_ring->count;
-	memset(tpd_ring->buffer_info, 0, size);
-
-	/* Zero out the descriptor ring */
-	memset(tpd_ring->desc, 0, tpd_ring->size);
-
-	atomic_set(&tpd_ring->next_to_use, 0);
-	atomic_set(&tpd_ring->next_to_clean, 0);
-}
-
-/*
- * atl1_free_ring_resources - Free Tx / RX descriptor Resources
- * @adapter: board private structure
- *
- * Free all transmit software resources
- */
-static void atl1_free_ring_resources(struct atl1_adapter *adapter)
-{
-	struct pci_dev *pdev = adapter->pdev;
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
-	struct atl1_ring_header *ring_header = &adapter->ring_header;
-
-	atl1_clean_tx_ring(adapter);
-	atl1_clean_rx_ring(adapter);
-
-	kfree(tpd_ring->buffer_info);
-	pci_free_consistent(pdev, ring_header->size, ring_header->desc,
-		ring_header->dma);
-
-	tpd_ring->buffer_info = NULL;
-	tpd_ring->desc = NULL;
-	tpd_ring->dma = 0;
-
-	rfd_ring->buffer_info = NULL;
-	rfd_ring->desc = NULL;
-	rfd_ring->dma = 0;
-
-	rrd_ring->desc = NULL;
-	rrd_ring->dma = 0;
-
-	adapter->cmb.dma = 0;
-	adapter->cmb.cmb = NULL;
-
-	adapter->smb.dma = 0;
-	adapter->smb.smb = NULL;
-}
-
-static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
-{
-	u32 value;
-	struct atl1_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	/* Config MAC CTRL Register */
-	value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
-	/* duplex */
-	if (FULL_DUPLEX == adapter->link_duplex)
-		value |= MAC_CTRL_DUPLX;
-	/* speed */
-	value |= ((u32) ((SPEED_1000 == adapter->link_speed) ?
-			 MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
-		  MAC_CTRL_SPEED_SHIFT);
-	/* flow control */
-	value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
-	/* PAD & CRC */
-	value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
-	/* preamble length */
-	value |= (((u32) adapter->hw.preamble_len
-		   & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
-	/* vlan */
-	__atlx_vlan_mode(netdev->features, &value);
-	/* rx checksum
-	   if (adapter->rx_csum)
-	   value |= MAC_CTRL_RX_CHKSUM_EN;
-	 */
-	/* filter mode */
-	value |= MAC_CTRL_BC_EN;
-	if (netdev->flags & IFF_PROMISC)
-		value |= MAC_CTRL_PROMIS_EN;
-	else if (netdev->flags & IFF_ALLMULTI)
-		value |= MAC_CTRL_MC_ALL_EN;
-	/* value |= MAC_CTRL_LOOPBACK; */
-	iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
-}
-
-static u32 atl1_check_link(struct atl1_adapter *adapter)
-{
-	struct atl1_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	u32 ret_val;
-	u16 speed, duplex, phy_data;
-	int reconfig = 0;
-
-	/* MII_BMSR must read twice */
-	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
-	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
-	if (!(phy_data & BMSR_LSTATUS)) {
-		/* link down */
-		if (netif_carrier_ok(netdev)) {
-			/* old link state: Up */
-			if (netif_msg_link(adapter))
-				dev_info(&adapter->pdev->dev, "link is down\n");
-			adapter->link_speed = SPEED_0;
-			netif_carrier_off(netdev);
-		}
-		return 0;
-	}
-
-	/* Link Up */
-	ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
-	if (ret_val)
-		return ret_val;
-
-	switch (hw->media_type) {
-	case MEDIA_TYPE_1000M_FULL:
-		if (speed != SPEED_1000 || duplex != FULL_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_100M_FULL:
-		if (speed != SPEED_100 || duplex != FULL_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_100M_HALF:
-		if (speed != SPEED_100 || duplex != HALF_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_10M_FULL:
-		if (speed != SPEED_10 || duplex != FULL_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_10M_HALF:
-		if (speed != SPEED_10 || duplex != HALF_DUPLEX)
-			reconfig = 1;
-		break;
-	}
-
-	/* link result is our setting */
-	if (!reconfig) {
-		if (adapter->link_speed != speed ||
-		    adapter->link_duplex != duplex) {
-			adapter->link_speed = speed;
-			adapter->link_duplex = duplex;
-			atl1_setup_mac_ctrl(adapter);
-			if (netif_msg_link(adapter))
-				dev_info(&adapter->pdev->dev,
-					"%s link is up %d Mbps %s\n",
-					netdev->name, adapter->link_speed,
-					adapter->link_duplex == FULL_DUPLEX ?
-					"full duplex" : "half duplex");
-		}
-		if (!netif_carrier_ok(netdev)) {
-			/* Link down -> Up */
-			netif_carrier_on(netdev);
-		}
-		return 0;
-	}
-
-	/* change original link status */
-	if (netif_carrier_ok(netdev)) {
-		adapter->link_speed = SPEED_0;
-		netif_carrier_off(netdev);
-		netif_stop_queue(netdev);
-	}
-
-	if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&
-	    hw->media_type != MEDIA_TYPE_1000M_FULL) {
-		switch (hw->media_type) {
-		case MEDIA_TYPE_100M_FULL:
-			phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
-			           MII_CR_RESET;
-			break;
-		case MEDIA_TYPE_100M_HALF:
-			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
-			break;
-		case MEDIA_TYPE_10M_FULL:
-			phy_data =
-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
-			break;
-		default:
-			/* MEDIA_TYPE_10M_HALF: */
-			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
-			break;
-		}
-		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
-		return 0;
-	}
-
-	/* auto-neg, insert timer to re-config phy */
-	if (!adapter->phy_timer_pending) {
-		adapter->phy_timer_pending = true;
-		mod_timer(&adapter->phy_config_timer,
-			  round_jiffies(jiffies + 3 * HZ));
-	}
-
-	return 0;
-}
-
-static void set_flow_ctrl_old(struct atl1_adapter *adapter)
-{
-	u32 hi, lo, value;
-
-	/* RFD Flow Control */
-	value = adapter->rfd_ring.count;
-	hi = value / 16;
-	if (hi < 2)
-		hi = 2;
-	lo = value * 7 / 8;
-
-	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
-		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
-	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
-
-	/* RRD Flow Control */
-	value = adapter->rrd_ring.count;
-	lo = value / 16;
-	hi = value * 7 / 8;
-	if (lo < 2)
-		lo = 2;
-	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
-		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
-	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
-}
-
-static void set_flow_ctrl_new(struct atl1_hw *hw)
-{
-	u32 hi, lo, value;
-
-	/* RXF Flow Control */
-	value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);
-	lo = value / 16;
-	if (lo < 192)
-		lo = 192;
-	hi = value * 7 / 8;
-	if (hi < lo)
-		hi = lo + 16;
-	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
-		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
-
-	/* RRD Flow Control */
-	value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);
-	lo = value / 8;
-	hi = value * 7 / 8;
-	if (lo < 2)
-		lo = 2;
-	if (hi < lo)
-		hi = lo + 3;
-	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
-		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
-}
-
-/*
- * atl1_configure - Configure Transmit&Receive Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Tx /Rx unit of the MAC after a reset.
- */
-static u32 atl1_configure(struct atl1_adapter *adapter)
-{
-	struct atl1_hw *hw = &adapter->hw;
-	u32 value;
-
-	/* clear interrupt status */
-	iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
-
-	/* set MAC Address */
-	value = (((u32) hw->mac_addr[2]) << 24) |
-		(((u32) hw->mac_addr[3]) << 16) |
-		(((u32) hw->mac_addr[4]) << 8) |
-		(((u32) hw->mac_addr[5]));
-	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
-	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
-	iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4));
-
-	/* tx / rx ring */
-
-	/* HI base address */
-	iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32),
-		hw->hw_addr + REG_DESC_BASE_ADDR_HI);
-	/* LO base address */
-	iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_RFD_ADDR_LO);
-	iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_RRD_ADDR_LO);
-	iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_TPD_ADDR_LO);
-	iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_CMB_ADDR_LO);
-	iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL),
-		hw->hw_addr + REG_DESC_SMB_ADDR_LO);
-
-	/* element count */
-	value = adapter->rrd_ring.count;
-	value <<= 16;
-	value += adapter->rfd_ring.count;
-	iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);
-	iowrite32(adapter->tpd_ring.count, hw->hw_addr +
-		REG_DESC_TPD_RING_SIZE);
-
-	/* Load Ptr */
-	iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
-
-	/* config Mailbox */
-	value = ((atomic_read(&adapter->tpd_ring.next_to_use)
-		  & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |
-		((atomic_read(&adapter->rrd_ring.next_to_clean)
-		& MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
-		((atomic_read(&adapter->rfd_ring.next_to_use)
-		& MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_MAILBOX);
-
-	/* config IPG/IFG */
-	value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)
-		 << MAC_IPG_IFG_IPGT_SHIFT) |
-		(((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
-		<< MAC_IPG_IFG_MIFG_SHIFT) |
-		(((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
-		<< MAC_IPG_IFG_IPGR1_SHIFT) |
-		(((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
-		<< MAC_IPG_IFG_IPGR2_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);
-
-	/* config  Half-Duplex Control */
-	value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
-		(((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
-		<< MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
-		MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
-		(0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
-		(((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
-		<< MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);
-
-	/* set Interrupt Moderator Timer */
-	iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT);
-	iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL);
-
-	/* set Interrupt Clear Timer */
-	iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
-
-	/* set max frame size hw will accept */
-	iowrite32(hw->max_frame_size, hw->hw_addr + REG_MTU);
-
-	/* jumbo size & rrd retirement timer */
-	value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
-		 << RXQ_JMBOSZ_TH_SHIFT) |
-		(((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
-		<< RXQ_JMBO_LKAH_SHIFT) |
-		(((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
-		<< RXQ_RRD_TIMER_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);
-
-	/* Flow Control */
-	switch (hw->dev_rev) {
-	case 0x8001:
-	case 0x9001:
-	case 0x9002:
-	case 0x9003:
-		set_flow_ctrl_old(adapter);
-		break;
-	default:
-		set_flow_ctrl_new(hw);
-		break;
-	}
-
-	/* config TXQ */
-	value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)
-		 << TXQ_CTRL_TPD_BURST_NUM_SHIFT) |
-		(((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
-		<< TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
-		(((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
-		<< TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE |
-		TXQ_CTRL_EN;
-	iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);
-
-	/* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */
-	value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)
-		<< TX_JUMBO_TASK_TH_SHIFT) |
-		(((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
-		<< TX_TPD_MIN_IPG_SHIFT);
-	iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);
-
-	/* config RXQ */
-	value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)
-		<< RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
-		(((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
-		<< RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
-		(((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
-		<< RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | RXQ_CTRL_CUT_THRU_EN |
-		RXQ_CTRL_EN;
-	iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);
-
-	/* config DMA Engine */
-	value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
-		<< DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
-		((((u32) hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
-		<< DMA_CTRL_DMAW_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN |
-		DMA_CTRL_DMAW_EN;
-	value |= (u32) hw->dma_ord;
-	if (atl1_rcb_128 == hw->rcb_value)
-		value |= DMA_CTRL_RCB_VALUE;
-	iowrite32(value, hw->hw_addr + REG_DMA_CTRL);
-
-	/* config CMB / SMB */
-	value = (hw->cmb_tpd > adapter->tpd_ring.count) ?
-		hw->cmb_tpd : adapter->tpd_ring.count;
-	value <<= 16;
-	value |= hw->cmb_rrd;
-	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH);
-	value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16);
-	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER);
-	iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER);
-
-	/* --- enable CMB / SMB */
-	value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;
-	iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);
-
-	value = ioread32(adapter->hw.hw_addr + REG_ISR);
-	if (unlikely((value & ISR_PHY_LINKDOWN) != 0))
-		value = 1;	/* config failed */
-	else
-		value = 0;
-
-	/* clear all interrupt status */
-	iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);
-	iowrite32(0, adapter->hw.hw_addr + REG_ISR);
-	return value;
-}
-
-/*
- * atl1_pcie_patch - Patch for PCIE module
- */
-static void atl1_pcie_patch(struct atl1_adapter *adapter)
-{
-	u32 value;
-
-	/* much vendor magic here */
-	value = 0x6500;
-	iowrite32(value, adapter->hw.hw_addr + 0x12FC);
-	/* pcie flow control mode change */
-	value = ioread32(adapter->hw.hw_addr + 0x1008);
-	value |= 0x8000;
-	iowrite32(value, adapter->hw.hw_addr + 0x1008);
-}
-
-/*
- * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
- * on PCI Command register is disable.
- * The function enable this bit.
- * Brackett, 2006/03/15
- */
-static void atl1_via_workaround(struct atl1_adapter *adapter)
-{
-	unsigned long value;
-
-	value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
-	if (value & PCI_COMMAND_INTX_DISABLE)
-		value &= ~PCI_COMMAND_INTX_DISABLE;
-	iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
-}
-
-static void atl1_inc_smb(struct atl1_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct stats_msg_block *smb = adapter->smb.smb;
-
-	/* Fill out the OS statistics structure */
-	adapter->soft_stats.rx_packets += smb->rx_ok;
-	adapter->soft_stats.tx_packets += smb->tx_ok;
-	adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;
-	adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;
-	adapter->soft_stats.multicast += smb->rx_mcast;
-	adapter->soft_stats.collisions += (smb->tx_1_col + smb->tx_2_col * 2 +
-		smb->tx_late_col + smb->tx_abort_col * adapter->hw.max_retry);
-
-	/* Rx Errors */
-	adapter->soft_stats.rx_errors += (smb->rx_frag + smb->rx_fcs_err +
-		smb->rx_len_err + smb->rx_sz_ov + smb->rx_rxf_ov +
-		smb->rx_rrd_ov + smb->rx_align_err);
-	adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;
-	adapter->soft_stats.rx_length_errors += smb->rx_len_err;
-	adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;
-	adapter->soft_stats.rx_frame_errors += smb->rx_align_err;
-	adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov +
-		smb->rx_rxf_ov);
-
-	adapter->soft_stats.rx_pause += smb->rx_pause;
-	adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;
-	adapter->soft_stats.rx_trunc += smb->rx_sz_ov;
-
-	/* Tx Errors */
-	adapter->soft_stats.tx_errors += (smb->tx_late_col +
-		smb->tx_abort_col + smb->tx_underrun + smb->tx_trunc);
-	adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;
-	adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;
-	adapter->soft_stats.tx_window_errors += smb->tx_late_col;
-
-	adapter->soft_stats.excecol += smb->tx_abort_col;
-	adapter->soft_stats.deffer += smb->tx_defer;
-	adapter->soft_stats.scc += smb->tx_1_col;
-	adapter->soft_stats.mcc += smb->tx_2_col;
-	adapter->soft_stats.latecol += smb->tx_late_col;
-	adapter->soft_stats.tx_underun += smb->tx_underrun;
-	adapter->soft_stats.tx_trunc += smb->tx_trunc;
-	adapter->soft_stats.tx_pause += smb->tx_pause;
-
-	netdev->stats.rx_packets = adapter->soft_stats.rx_packets;
-	netdev->stats.tx_packets = adapter->soft_stats.tx_packets;
-	netdev->stats.rx_bytes = adapter->soft_stats.rx_bytes;
-	netdev->stats.tx_bytes = adapter->soft_stats.tx_bytes;
-	netdev->stats.multicast = adapter->soft_stats.multicast;
-	netdev->stats.collisions = adapter->soft_stats.collisions;
-	netdev->stats.rx_errors = adapter->soft_stats.rx_errors;
-	netdev->stats.rx_over_errors =
-		adapter->soft_stats.rx_missed_errors;
-	netdev->stats.rx_length_errors =
-		adapter->soft_stats.rx_length_errors;
-	netdev->stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
-	netdev->stats.rx_frame_errors =
-		adapter->soft_stats.rx_frame_errors;
-	netdev->stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
-	netdev->stats.rx_missed_errors =
-		adapter->soft_stats.rx_missed_errors;
-	netdev->stats.tx_errors = adapter->soft_stats.tx_errors;
-	netdev->stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
-	netdev->stats.tx_aborted_errors =
-		adapter->soft_stats.tx_aborted_errors;
-	netdev->stats.tx_window_errors =
-		adapter->soft_stats.tx_window_errors;
-	netdev->stats.tx_carrier_errors =
-		adapter->soft_stats.tx_carrier_errors;
-}
-
-static void atl1_update_mailbox(struct atl1_adapter *adapter)
-{
-	unsigned long flags;
-	u32 tpd_next_to_use;
-	u32 rfd_next_to_use;
-	u32 rrd_next_to_clean;
-	u32 value;
-
-	spin_lock_irqsave(&adapter->mb_lock, flags);
-
-	tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
-	rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
-	rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
-
-	value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
-		MB_RFD_PROD_INDX_SHIFT) |
-		((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
-		MB_RRD_CONS_INDX_SHIFT) |
-		((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
-		MB_TPD_PROD_INDX_SHIFT);
-	iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
-
-	spin_unlock_irqrestore(&adapter->mb_lock, flags);
-}
-
-static void atl1_clean_alloc_flag(struct atl1_adapter *adapter,
-	struct rx_return_desc *rrd, u16 offset)
-{
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-
-	while (rfd_ring->next_to_clean != (rrd->buf_indx + offset)) {
-		rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0;
-		if (++rfd_ring->next_to_clean == rfd_ring->count) {
-			rfd_ring->next_to_clean = 0;
-		}
-	}
-}
-
-static void atl1_update_rfd_index(struct atl1_adapter *adapter,
-	struct rx_return_desc *rrd)
-{
-	u16 num_buf;
-
-	num_buf = (rrd->xsz.xsum_sz.pkt_size + adapter->rx_buffer_len - 1) /
-		adapter->rx_buffer_len;
-	if (rrd->num_buf == num_buf)
-		/* clean alloc flag for bad rrd */
-		atl1_clean_alloc_flag(adapter, rrd, num_buf);
-}
-
-static void atl1_rx_checksum(struct atl1_adapter *adapter,
-	struct rx_return_desc *rrd, struct sk_buff *skb)
-{
-	struct pci_dev *pdev = adapter->pdev;
-
-	/*
-	 * The L1 hardware contains a bug that erroneously sets the
-	 * PACKET_FLAG_ERR and ERR_FLAG_L4_CHKSUM bits whenever a
-	 * fragmented IP packet is received, even though the packet
-	 * is perfectly valid and its checksum is correct. There's
-	 * no way to distinguish between one of these good packets
-	 * and a packet that actually contains a TCP/UDP checksum
-	 * error, so all we can do is allow it to be handed up to
-	 * the higher layers and let it be sorted out there.
-	 */
-
-	skb_checksum_none_assert(skb);
-
-	if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
-		if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
-					ERR_FLAG_CODE | ERR_FLAG_OV)) {
-			adapter->hw_csum_err++;
-			if (netif_msg_rx_err(adapter))
-				dev_printk(KERN_DEBUG, &pdev->dev,
-					"rx checksum error\n");
-			return;
-		}
-	}
-
-	/* not IPv4 */
-	if (!(rrd->pkt_flg & PACKET_FLAG_IPV4))
-		/* checksum is invalid, but it's not an IPv4 pkt, so ok */
-		return;
-
-	/* IPv4 packet */
-	if (likely(!(rrd->err_flg &
-		(ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) {
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-		adapter->hw_csum_good++;
-		return;
-	}
-}
-
-/*
- * atl1_alloc_rx_buffers - Replace used receive buffers
- * @adapter: address of board private structure
- */
-static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
-{
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-	struct pci_dev *pdev = adapter->pdev;
-	struct page *page;
-	unsigned long offset;
-	struct atl1_buffer *buffer_info, *next_info;
-	struct sk_buff *skb;
-	u16 num_alloc = 0;
-	u16 rfd_next_to_use, next_next;
-	struct rx_free_desc *rfd_desc;
-
-	next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use);
-	if (++next_next == rfd_ring->count)
-		next_next = 0;
-	buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
-	next_info = &rfd_ring->buffer_info[next_next];
-
-	while (!buffer_info->alloced && !next_info->alloced) {
-		if (buffer_info->skb) {
-			buffer_info->alloced = 1;
-			goto next;
-		}
-
-		rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use);
-
-		skb = netdev_alloc_skb_ip_align(adapter->netdev,
-						adapter->rx_buffer_len);
-		if (unlikely(!skb)) {
-			/* Better luck next round */
-			adapter->netdev->stats.rx_dropped++;
-			break;
-		}
-
-		buffer_info->alloced = 1;
-		buffer_info->skb = skb;
-		buffer_info->length = (u16) adapter->rx_buffer_len;
-		page = virt_to_page(skb->data);
-		offset = (unsigned long)skb->data & ~PAGE_MASK;
-		buffer_info->dma = pci_map_page(pdev, page, offset,
-						adapter->rx_buffer_len,
-						PCI_DMA_FROMDEVICE);
-		rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
-		rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
-		rfd_desc->coalese = 0;
-
-next:
-		rfd_next_to_use = next_next;
-		if (unlikely(++next_next == rfd_ring->count))
-			next_next = 0;
-
-		buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
-		next_info = &rfd_ring->buffer_info[next_next];
-		num_alloc++;
-	}
-
-	if (num_alloc) {
-		/*
-		 * Force memory writes to complete before letting h/w
-		 * know there are new descriptors to fetch.  (Only
-		 * applicable for weak-ordered memory model archs,
-		 * such as IA-64).
-		 */
-		wmb();
-		atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use);
-	}
-	return num_alloc;
-}
-
-static void atl1_intr_rx(struct atl1_adapter *adapter)
-{
-	int i, count;
-	u16 length;
-	u16 rrd_next_to_clean;
-	u32 value;
-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
-	struct atl1_buffer *buffer_info;
-	struct rx_return_desc *rrd;
-	struct sk_buff *skb;
-
-	count = 0;
-
-	rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);
-
-	while (1) {
-		rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean);
-		i = 1;
-		if (likely(rrd->xsz.valid)) {	/* packet valid */
-chk_rrd:
-			/* check rrd status */
-			if (likely(rrd->num_buf == 1))
-				goto rrd_ok;
-			else if (netif_msg_rx_err(adapter)) {
-				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-					"unexpected RRD buffer count\n");
-				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-					"rx_buf_len = %d\n",
-					adapter->rx_buffer_len);
-				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-					"RRD num_buf = %d\n",
-					rrd->num_buf);
-				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-					"RRD pkt_len = %d\n",
-					rrd->xsz.xsum_sz.pkt_size);
-				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-					"RRD pkt_flg = 0x%08X\n",
-					rrd->pkt_flg);
-				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-					"RRD err_flg = 0x%08X\n",
-					rrd->err_flg);
-				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-					"RRD vlan_tag = 0x%08X\n",
-					rrd->vlan_tag);
-			}
-
-			/* rrd seems to be bad */
-			if (unlikely(i-- > 0)) {
-				/* rrd may not be DMAed completely */
-				udelay(1);
-				goto chk_rrd;
-			}
-			/* bad rrd */
-			if (netif_msg_rx_err(adapter))
-				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-					"bad RRD\n");
-			/* see if update RFD index */
-			if (rrd->num_buf > 1)
-				atl1_update_rfd_index(adapter, rrd);
-
-			/* update rrd */
-			rrd->xsz.valid = 0;
-			if (++rrd_next_to_clean == rrd_ring->count)
-				rrd_next_to_clean = 0;
-			count++;
-			continue;
-		} else {	/* current rrd still not be updated */
-
-			break;
-		}
-rrd_ok:
-		/* clean alloc flag for bad rrd */
-		atl1_clean_alloc_flag(adapter, rrd, 0);
-
-		buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];
-		if (++rfd_ring->next_to_clean == rfd_ring->count)
-			rfd_ring->next_to_clean = 0;
-
-		/* update rrd next to clean */
-		if (++rrd_next_to_clean == rrd_ring->count)
-			rrd_next_to_clean = 0;
-		count++;
-
-		if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
-			if (!(rrd->err_flg &
-				(ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM
-				| ERR_FLAG_LEN))) {
-				/* packet error, don't need upstream */
-				buffer_info->alloced = 0;
-				rrd->xsz.valid = 0;
-				continue;
-			}
-		}
-
-		/* Good Receive */
-		pci_unmap_page(adapter->pdev, buffer_info->dma,
-			       buffer_info->length, PCI_DMA_FROMDEVICE);
-		buffer_info->dma = 0;
-		skb = buffer_info->skb;
-		length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size);
-
-		skb_put(skb, length - ETH_FCS_LEN);
-
-		/* Receive Checksum Offload */
-		atl1_rx_checksum(adapter, rrd, skb);
-		skb->protocol = eth_type_trans(skb, adapter->netdev);
-
-		if (rrd->pkt_flg & PACKET_FLAG_VLAN_INS) {
-			u16 vlan_tag = (rrd->vlan_tag >> 4) |
-					((rrd->vlan_tag & 7) << 13) |
-					((rrd->vlan_tag & 8) << 9);
-
-			__vlan_hwaccel_put_tag(skb, vlan_tag);
-		}
-		netif_rx(skb);
-
-		/* let protocol layer free skb */
-		buffer_info->skb = NULL;
-		buffer_info->alloced = 0;
-		rrd->xsz.valid = 0;
-	}
-
-	atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);
-
-	atl1_alloc_rx_buffers(adapter);
-
-	/* update mailbox ? */
-	if (count) {
-		u32 tpd_next_to_use;
-		u32 rfd_next_to_use;
-
-		spin_lock(&adapter->mb_lock);
-
-		tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
-		rfd_next_to_use =
-		    atomic_read(&adapter->rfd_ring.next_to_use);
-		rrd_next_to_clean =
-		    atomic_read(&adapter->rrd_ring.next_to_clean);
-		value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
-			MB_RFD_PROD_INDX_SHIFT) |
-                        ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
-			MB_RRD_CONS_INDX_SHIFT) |
-                        ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
-			MB_TPD_PROD_INDX_SHIFT);
-		iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
-		spin_unlock(&adapter->mb_lock);
-	}
-}
-
-static void atl1_intr_tx(struct atl1_adapter *adapter)
-{
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_buffer *buffer_info;
-	u16 sw_tpd_next_to_clean;
-	u16 cmb_tpd_next_to_clean;
-
-	sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
-	cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
-
-	while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
-		buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
-		if (buffer_info->dma) {
-			pci_unmap_page(adapter->pdev, buffer_info->dma,
-				       buffer_info->length, PCI_DMA_TODEVICE);
-			buffer_info->dma = 0;
-		}
-
-		if (buffer_info->skb) {
-			dev_kfree_skb_irq(buffer_info->skb);
-			buffer_info->skb = NULL;
-		}
-
-		if (++sw_tpd_next_to_clean == tpd_ring->count)
-			sw_tpd_next_to_clean = 0;
-	}
-	atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean);
-
-	if (netif_queue_stopped(adapter->netdev) &&
-	    netif_carrier_ok(adapter->netdev))
-		netif_wake_queue(adapter->netdev);
-}
-
-static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring)
-{
-	u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
-	u16 next_to_use = atomic_read(&tpd_ring->next_to_use);
-	return (next_to_clean > next_to_use) ?
-		next_to_clean - next_to_use - 1 :
-		tpd_ring->count + next_to_clean - next_to_use - 1;
-}
-
-static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
-	struct tx_packet_desc *ptpd)
-{
-	u8 hdr_len, ip_off;
-	u32 real_len;
-	int err;
-
-	if (skb_shinfo(skb)->gso_size) {
-		if (skb_header_cloned(skb)) {
-			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
-			if (unlikely(err))
-				return -1;
-		}
-
-		if (skb->protocol == htons(ETH_P_IP)) {
-			struct iphdr *iph = ip_hdr(skb);
-
-			real_len = (((unsigned char *)iph - skb->data) +
-				ntohs(iph->tot_len));
-			if (real_len < skb->len)
-				pskb_trim(skb, real_len);
-			hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
-			if (skb->len == hdr_len) {
-				iph->check = 0;
-				tcp_hdr(skb)->check =
-					~csum_tcpudp_magic(iph->saddr,
-					iph->daddr, tcp_hdrlen(skb),
-					IPPROTO_TCP, 0);
-				ptpd->word3 |= (iph->ihl & TPD_IPHL_MASK) <<
-					TPD_IPHL_SHIFT;
-				ptpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
-					TPD_TCPHDRLEN_MASK) <<
-					TPD_TCPHDRLEN_SHIFT;
-				ptpd->word3 |= 1 << TPD_IP_CSUM_SHIFT;
-				ptpd->word3 |= 1 << TPD_TCP_CSUM_SHIFT;
-				return 1;
-			}
-
-			iph->check = 0;
-			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
-					iph->daddr, 0, IPPROTO_TCP, 0);
-			ip_off = (unsigned char *)iph -
-				(unsigned char *) skb_network_header(skb);
-			if (ip_off == 8) /* 802.3-SNAP frame */
-				ptpd->word3 |= 1 << TPD_ETHTYPE_SHIFT;
-			else if (ip_off != 0)
-				return -2;
-
-			ptpd->word3 |= (iph->ihl & TPD_IPHL_MASK) <<
-				TPD_IPHL_SHIFT;
-			ptpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
-				TPD_TCPHDRLEN_MASK) << TPD_TCPHDRLEN_SHIFT;
-			ptpd->word3 |= (skb_shinfo(skb)->gso_size &
-				TPD_MSS_MASK) << TPD_MSS_SHIFT;
-			ptpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT;
-			return 3;
-		}
-	}
-	return false;
-}
-
-static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
-	struct tx_packet_desc *ptpd)
-{
-	u8 css, cso;
-
-	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
-		css = skb_checksum_start_offset(skb);
-		cso = css + (u8) skb->csum_offset;
-		if (unlikely(css & 0x1)) {
-			/* L1 hardware requires an even number here */
-			if (netif_msg_tx_err(adapter))
-				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-					"payload offset not an even number\n");
-			return -1;
-		}
-		ptpd->word3 |= (css & TPD_PLOADOFFSET_MASK) <<
-			TPD_PLOADOFFSET_SHIFT;
-		ptpd->word3 |= (cso & TPD_CCSUMOFFSET_MASK) <<
-			TPD_CCSUMOFFSET_SHIFT;
-		ptpd->word3 |= 1 << TPD_CUST_CSUM_EN_SHIFT;
-		return true;
-	}
-	return 0;
-}
-
-static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
-	struct tx_packet_desc *ptpd)
-{
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_buffer *buffer_info;
-	u16 buf_len = skb->len;
-	struct page *page;
-	unsigned long offset;
-	unsigned int nr_frags;
-	unsigned int f;
-	int retval;
-	u16 next_to_use;
-	u16 data_len;
-	u8 hdr_len;
-
-	buf_len -= skb->data_len;
-	nr_frags = skb_shinfo(skb)->nr_frags;
-	next_to_use = atomic_read(&tpd_ring->next_to_use);
-	buffer_info = &tpd_ring->buffer_info[next_to_use];
-	BUG_ON(buffer_info->skb);
-	/* put skb in last TPD */
-	buffer_info->skb = NULL;
-
-	retval = (ptpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK;
-	if (retval) {
-		/* TSO */
-		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-		buffer_info->length = hdr_len;
-		page = virt_to_page(skb->data);
-		offset = (unsigned long)skb->data & ~PAGE_MASK;
-		buffer_info->dma = pci_map_page(adapter->pdev, page,
-						offset, hdr_len,
-						PCI_DMA_TODEVICE);
-
-		if (++next_to_use == tpd_ring->count)
-			next_to_use = 0;
-
-		if (buf_len > hdr_len) {
-			int i, nseg;
-
-			data_len = buf_len - hdr_len;
-			nseg = (data_len + ATL1_MAX_TX_BUF_LEN - 1) /
-				ATL1_MAX_TX_BUF_LEN;
-			for (i = 0; i < nseg; i++) {
-				buffer_info =
-				    &tpd_ring->buffer_info[next_to_use];
-				buffer_info->skb = NULL;
-				buffer_info->length =
-				    (ATL1_MAX_TX_BUF_LEN >=
-				     data_len) ? ATL1_MAX_TX_BUF_LEN : data_len;
-				data_len -= buffer_info->length;
-				page = virt_to_page(skb->data +
-					(hdr_len + i * ATL1_MAX_TX_BUF_LEN));
-				offset = (unsigned long)(skb->data +
-					(hdr_len + i * ATL1_MAX_TX_BUF_LEN)) &
-					~PAGE_MASK;
-				buffer_info->dma = pci_map_page(adapter->pdev,
-					page, offset, buffer_info->length,
-					PCI_DMA_TODEVICE);
-				if (++next_to_use == tpd_ring->count)
-					next_to_use = 0;
-			}
-		}
-	} else {
-		/* not TSO */
-		buffer_info->length = buf_len;
-		page = virt_to_page(skb->data);
-		offset = (unsigned long)skb->data & ~PAGE_MASK;
-		buffer_info->dma = pci_map_page(adapter->pdev, page,
-			offset, buf_len, PCI_DMA_TODEVICE);
-		if (++next_to_use == tpd_ring->count)
-			next_to_use = 0;
-	}
-
-	for (f = 0; f < nr_frags; f++) {
-		struct skb_frag_struct *frag;
-		u16 i, nseg;
-
-		frag = &skb_shinfo(skb)->frags[f];
-		buf_len = frag->size;
-
-		nseg = (buf_len + ATL1_MAX_TX_BUF_LEN - 1) /
-			ATL1_MAX_TX_BUF_LEN;
-		for (i = 0; i < nseg; i++) {
-			buffer_info = &tpd_ring->buffer_info[next_to_use];
-			BUG_ON(buffer_info->skb);
-
-			buffer_info->skb = NULL;
-			buffer_info->length = (buf_len > ATL1_MAX_TX_BUF_LEN) ?
-				ATL1_MAX_TX_BUF_LEN : buf_len;
-			buf_len -= buffer_info->length;
-			buffer_info->dma = pci_map_page(adapter->pdev,
-				frag->page,
-				frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN),
-				buffer_info->length, PCI_DMA_TODEVICE);
-
-			if (++next_to_use == tpd_ring->count)
-				next_to_use = 0;
-		}
-	}
-
-	/* last tpd's buffer-info */
-	buffer_info->skb = skb;
-}
-
-static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count,
-       struct tx_packet_desc *ptpd)
-{
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	struct atl1_buffer *buffer_info;
-	struct tx_packet_desc *tpd;
-	u16 j;
-	u32 val;
-	u16 next_to_use = (u16) atomic_read(&tpd_ring->next_to_use);
-
-	for (j = 0; j < count; j++) {
-		buffer_info = &tpd_ring->buffer_info[next_to_use];
-		tpd = ATL1_TPD_DESC(&adapter->tpd_ring, next_to_use);
-		if (tpd != ptpd)
-			memcpy(tpd, ptpd, sizeof(struct tx_packet_desc));
-		tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
-		tpd->word2 &= ~(TPD_BUFLEN_MASK << TPD_BUFLEN_SHIFT);
-		tpd->word2 |= (cpu_to_le16(buffer_info->length) &
-			TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT;
-
-		/*
-		 * if this is the first packet in a TSO chain, set
-		 * TPD_HDRFLAG, otherwise, clear it.
-		 */
-		val = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) &
-			TPD_SEGMENT_EN_MASK;
-		if (val) {
-			if (!j)
-				tpd->word3 |= 1 << TPD_HDRFLAG_SHIFT;
-			else
-				tpd->word3 &= ~(1 << TPD_HDRFLAG_SHIFT);
-		}
-
-		if (j == (count - 1))
-			tpd->word3 |= 1 << TPD_EOP_SHIFT;
-
-		if (++next_to_use == tpd_ring->count)
-			next_to_use = 0;
-	}
-	/*
-	 * Force memory writes to complete before letting h/w
-	 * know there are new descriptors to fetch.  (Only
-	 * applicable for weak-ordered memory model archs,
-	 * such as IA-64).
-	 */
-	wmb();
-
-	atomic_set(&tpd_ring->next_to_use, next_to_use);
-}
-
-static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb,
-					 struct net_device *netdev)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
-	int len;
-	int tso;
-	int count = 1;
-	int ret_val;
-	struct tx_packet_desc *ptpd;
-	u16 frag_size;
-	u16 vlan_tag;
-	unsigned int nr_frags = 0;
-	unsigned int mss = 0;
-	unsigned int f;
-	unsigned int proto_hdr_len;
-
-	len = skb_headlen(skb);
-
-	if (unlikely(skb->len <= 0)) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	nr_frags = skb_shinfo(skb)->nr_frags;
-	for (f = 0; f < nr_frags; f++) {
-		frag_size = skb_shinfo(skb)->frags[f].size;
-		if (frag_size)
-			count += (frag_size + ATL1_MAX_TX_BUF_LEN - 1) /
-				ATL1_MAX_TX_BUF_LEN;
-	}
-
-	mss = skb_shinfo(skb)->gso_size;
-	if (mss) {
-		if (skb->protocol == htons(ETH_P_IP)) {
-			proto_hdr_len = (skb_transport_offset(skb) +
-					 tcp_hdrlen(skb));
-			if (unlikely(proto_hdr_len > len)) {
-				dev_kfree_skb_any(skb);
-				return NETDEV_TX_OK;
-			}
-			/* need additional TPD ? */
-			if (proto_hdr_len != len)
-				count += (len - proto_hdr_len +
-					ATL1_MAX_TX_BUF_LEN - 1) /
-					ATL1_MAX_TX_BUF_LEN;
-		}
-	}
-
-	if (atl1_tpd_avail(&adapter->tpd_ring) < count) {
-		/* not enough descriptors */
-		netif_stop_queue(netdev);
-		if (netif_msg_tx_queued(adapter))
-			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-				"tx busy\n");
-		return NETDEV_TX_BUSY;
-	}
-
-	ptpd = ATL1_TPD_DESC(tpd_ring,
-		(u16) atomic_read(&tpd_ring->next_to_use));
-	memset(ptpd, 0, sizeof(struct tx_packet_desc));
-
-	if (vlan_tx_tag_present(skb)) {
-		vlan_tag = vlan_tx_tag_get(skb);
-		vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) |
-			((vlan_tag >> 9) & 0x8);
-		ptpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT;
-		ptpd->word2 |= (vlan_tag & TPD_VLANTAG_MASK) <<
-			TPD_VLANTAG_SHIFT;
-	}
-
-	tso = atl1_tso(adapter, skb, ptpd);
-	if (tso < 0) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	if (!tso) {
-		ret_val = atl1_tx_csum(adapter, skb, ptpd);
-		if (ret_val < 0) {
-			dev_kfree_skb_any(skb);
-			return NETDEV_TX_OK;
-		}
-	}
-
-	atl1_tx_map(adapter, skb, ptpd);
-	atl1_tx_queue(adapter, count, ptpd);
-	atl1_update_mailbox(adapter);
-	mmiowb();
-	return NETDEV_TX_OK;
-}
-
-/*
- * atl1_intr - Interrupt Handler
- * @irq: interrupt number
- * @data: pointer to a network interface device structure
- * @pt_regs: CPU registers structure
- */
-static irqreturn_t atl1_intr(int irq, void *data)
-{
-	struct atl1_adapter *adapter = netdev_priv(data);
-	u32 status;
-	int max_ints = 10;
-
-	status = adapter->cmb.cmb->int_stats;
-	if (!status)
-		return IRQ_NONE;
-
-	do {
-		/* clear CMB interrupt status at once */
-		adapter->cmb.cmb->int_stats = 0;
-
-		if (status & ISR_GPHY)	/* clear phy status */
-			atlx_clear_phy_int(adapter);
-
-		/* clear ISR status, and Enable CMB DMA/Disable Interrupt */
-		iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
-
-		/* check if SMB intr */
-		if (status & ISR_SMB)
-			atl1_inc_smb(adapter);
-
-		/* check if PCIE PHY Link down */
-		if (status & ISR_PHY_LINKDOWN) {
-			if (netif_msg_intr(adapter))
-				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-					"pcie phy link down %x\n", status);
-			if (netif_running(adapter->netdev)) {	/* reset MAC */
-				iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-				schedule_work(&adapter->pcie_dma_to_rst_task);
-				return IRQ_HANDLED;
-			}
-		}
-
-		/* check if DMA read/write error ? */
-		if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
-			if (netif_msg_intr(adapter))
-				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
-					"pcie DMA r/w error (status = 0x%x)\n",
-					status);
-			iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-			schedule_work(&adapter->pcie_dma_to_rst_task);
-			return IRQ_HANDLED;
-		}
-
-		/* link event */
-		if (status & ISR_GPHY) {
-			adapter->soft_stats.tx_carrier_errors++;
-			atl1_check_for_link(adapter);
-		}
-
-		/* transmit event */
-		if (status & ISR_CMB_TX)
-			atl1_intr_tx(adapter);
-
-		/* rx exception */
-		if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
-			ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
-			ISR_HOST_RRD_OV | ISR_CMB_RX))) {
-			if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
-				ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
-				ISR_HOST_RRD_OV))
-				if (netif_msg_intr(adapter))
-					dev_printk(KERN_DEBUG,
-						&adapter->pdev->dev,
-						"rx exception, ISR = 0x%x\n",
-						status);
-			atl1_intr_rx(adapter);
-		}
-
-		if (--max_ints < 0)
-			break;
-
-	} while ((status = adapter->cmb.cmb->int_stats));
-
-	/* re-enable Interrupt */
-	iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
-	return IRQ_HANDLED;
-}
-
-
-/*
- * atl1_phy_config - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
- */
-static void atl1_phy_config(unsigned long data)
-{
-	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
-	struct atl1_hw *hw = &adapter->hw;
-	unsigned long flags;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	adapter->phy_timer_pending = false;
-	atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
-	atl1_write_phy_reg(hw, MII_ATLX_CR, hw->mii_1000t_ctrl_reg);
-	atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
-	spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-/*
- * Orphaned vendor comment left intact here:
- * <vendor comment>
- * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
- * will assert. We do soft reset <0x1400=1> according
- * with the SPEC. BUT, it seemes that PCIE or DMA
- * state-machine will not be reset. DMAR_TO_INT will
- * assert again and again.
- * </vendor comment>
- */
-
-static int atl1_reset(struct atl1_adapter *adapter)
-{
-	int ret;
-	ret = atl1_reset_hw(&adapter->hw);
-	if (ret)
-		return ret;
-	return atl1_init_hw(&adapter->hw);
-}
-
-static s32 atl1_up(struct atl1_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	int err;
-	int irq_flags = 0;
-
-	/* hardware has been reset, we need to reload some things */
-	atlx_set_multi(netdev);
-	atl1_init_ring_ptrs(adapter);
-	atlx_restore_vlan(adapter);
-	err = atl1_alloc_rx_buffers(adapter);
-	if (unlikely(!err))
-		/* no RX BUFFER allocated */
-		return -ENOMEM;
-
-	if (unlikely(atl1_configure(adapter))) {
-		err = -EIO;
-		goto err_up;
-	}
-
-	err = pci_enable_msi(adapter->pdev);
-	if (err) {
-		if (netif_msg_ifup(adapter))
-			dev_info(&adapter->pdev->dev,
-				"Unable to enable MSI: %d\n", err);
-		irq_flags |= IRQF_SHARED;
-	}
-
-	err = request_irq(adapter->pdev->irq, atl1_intr, irq_flags,
-			netdev->name, netdev);
-	if (unlikely(err))
-		goto err_up;
-
-	atlx_irq_enable(adapter);
-	atl1_check_link(adapter);
-	netif_start_queue(netdev);
-	return 0;
-
-err_up:
-	pci_disable_msi(adapter->pdev);
-	/* free rx_buffers */
-	atl1_clean_rx_ring(adapter);
-	return err;
-}
-
-static void atl1_down(struct atl1_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-
-	netif_stop_queue(netdev);
-	del_timer_sync(&adapter->phy_config_timer);
-	adapter->phy_timer_pending = false;
-
-	atlx_irq_disable(adapter);
-	free_irq(adapter->pdev->irq, netdev);
-	pci_disable_msi(adapter->pdev);
-	atl1_reset_hw(&adapter->hw);
-	adapter->cmb.cmb->int_stats = 0;
-
-	adapter->link_speed = SPEED_0;
-	adapter->link_duplex = -1;
-	netif_carrier_off(netdev);
-
-	atl1_clean_tx_ring(adapter);
-	atl1_clean_rx_ring(adapter);
-}
-
-static void atl1_tx_timeout_task(struct work_struct *work)
-{
-	struct atl1_adapter *adapter =
-		container_of(work, struct atl1_adapter, tx_timeout_task);
-	struct net_device *netdev = adapter->netdev;
-
-	netif_device_detach(netdev);
-	atl1_down(adapter);
-	atl1_up(adapter);
-	netif_device_attach(netdev);
-}
-
-/*
- * atl1_change_mtu - Change the Maximum Transfer Unit
- * @netdev: network interface device structure
- * @new_mtu: new value for maximum frame size
- *
- * Returns 0 on success, negative on failure
- */
-static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	int old_mtu = netdev->mtu;
-	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
-
-	if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
-	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
-		if (netif_msg_link(adapter))
-			dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
-		return -EINVAL;
-	}
-
-	adapter->hw.max_frame_size = max_frame;
-	adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
-	adapter->rx_buffer_len = (max_frame + 7) & ~7;
-	adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
-
-	netdev->mtu = new_mtu;
-	if ((old_mtu != new_mtu) && netif_running(netdev)) {
-		atl1_down(adapter);
-		atl1_up(adapter);
-	}
-
-	return 0;
-}
-
-/*
- * atl1_open - Called when a network interface is made active
- * @netdev: network interface device structure
- *
- * Returns 0 on success, negative value on failure
- *
- * 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.
- */
-static int atl1_open(struct net_device *netdev)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	int err;
-
-	netif_carrier_off(netdev);
-
-	/* allocate transmit descriptors */
-	err = atl1_setup_ring_resources(adapter);
-	if (err)
-		return err;
-
-	err = atl1_up(adapter);
-	if (err)
-		goto err_up;
-
-	return 0;
-
-err_up:
-	atl1_reset(adapter);
-	return err;
-}
-
-/*
- * atl1_close - Disables a network interface
- * @netdev: network interface device structure
- *
- * 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.
- */
-static int atl1_close(struct net_device *netdev)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	atl1_down(adapter);
-	atl1_free_ring_resources(adapter);
-	return 0;
-}
-
-#ifdef CONFIG_PM
-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;
-	u16 speed;
-	u16 duplex;
-
-	netif_device_detach(netdev);
-	if (netif_running(netdev))
-		atl1_down(adapter);
-
-	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) {
-		val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
-		if (val) {
-			if (netif_msg_ifdown(adapter))
-				dev_printk(KERN_DEBUG, &pdev->dev,
-					"error getting speed/duplex\n");
-			goto disable_wol;
-		}
-
-		ctrl = 0;
-
-		/* enable magic packet WOL */
-		if (wufc & ATLX_WUFC_MAG)
-			ctrl |= (WOL_MAGIC_EN | WOL_MAGIC_PME_EN);
-		iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
-		ioread32(hw->hw_addr + REG_WOL_CTRL);
-
-		/* configure the mac */
-		ctrl = MAC_CTRL_RX_EN;
-		ctrl |= ((u32)((speed == SPEED_1000) ? MAC_CTRL_SPEED_1000 :
-			MAC_CTRL_SPEED_10_100) << MAC_CTRL_SPEED_SHIFT);
-		if (duplex == FULL_DUPLEX)
-			ctrl |= MAC_CTRL_DUPLX;
-		ctrl |= (((u32)adapter->hw.preamble_len &
-			MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
-		__atlx_vlan_mode(netdev->features, &ctrl);
-		if (wufc & ATLX_WUFC_MAG)
-			ctrl |= MAC_CTRL_BC_EN;
-		iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
-		ioread32(hw->hw_addr + REG_MAC_CTRL);
-
-		/* poke the PHY */
-		ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
-		ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
-		iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC);
-		ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
-	} 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;
-	}
-
-	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);
-	ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
-	iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC);
-	ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
-	hw->phy_configured = false;
-
-	return 0;
-}
-
-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);
-
-	iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
-
-	atl1_reset_hw(&adapter->hw);
-
-	if (netif_running(netdev)) {
-		adapter->cmb.cmb->int_stats = 0;
-		atl1_up(adapter);
-	}
-	netif_device_attach(netdev);
-
-	return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(atl1_pm_ops, atl1_suspend, atl1_resume);
-#define ATL1_PM_OPS	(&atl1_pm_ops)
-
-#else
-
-static int atl1_suspend(struct device *dev) { return 0; }
-
-#define ATL1_PM_OPS	NULL
-#endif
-
-static void atl1_shutdown(struct pci_dev *pdev)
-{
-	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
-static void atl1_poll_controller(struct net_device *netdev)
-{
-	disable_irq(netdev->irq);
-	atl1_intr(netdev->irq, netdev);
-	enable_irq(netdev->irq);
-}
-#endif
-
-static const struct net_device_ops atl1_netdev_ops = {
-	.ndo_open		= atl1_open,
-	.ndo_stop		= atl1_close,
-	.ndo_start_xmit		= atl1_xmit_frame,
-	.ndo_set_multicast_list	= atlx_set_multi,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address	= atl1_set_mac,
-	.ndo_change_mtu		= atl1_change_mtu,
-	.ndo_fix_features	= atlx_fix_features,
-	.ndo_set_features	= atlx_set_features,
-	.ndo_do_ioctl		= atlx_ioctl,
-	.ndo_tx_timeout		= atlx_tx_timeout,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= atl1_poll_controller,
-#endif
-};
-
-/*
- * atl1_probe - Device Initialization Routine
- * @pdev: PCI device information struct
- * @ent: entry in atl1_pci_tbl
- *
- * Returns 0 on success, negative on failure
- *
- * atl1_probe initializes an adapter identified by a pci_dev structure.
- * The OS initialization, configuring of the adapter private structure,
- * and a hardware reset occur.
- */
-static int __devinit atl1_probe(struct pci_dev *pdev,
-	const struct pci_device_id *ent)
-{
-	struct net_device *netdev;
-	struct atl1_adapter *adapter;
-	static int cards_found = 0;
-	int err;
-
-	err = pci_enable_device(pdev);
-	if (err)
-		return err;
-
-	/*
-	 * The atl1 chip can DMA to 64-bit addresses, but it uses a single
-	 * shared register for the high 32 bits, so only a single, aligned,
-	 * 4 GB physical address range can be used at a time.
-	 *
-	 * Supporting 64-bit DMA on this hardware is more trouble than it's
-	 * worth.  It is far easier to limit to 32-bit DMA than update
-	 * various kernel subsystems to support the mechanics required by a
-	 * fixed-high-32-bit system.
-	 */
-	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (err) {
-		dev_err(&pdev->dev, "no usable DMA configuration\n");
-		goto err_dma;
-	}
-	/*
-	 * Mark all PCI regions associated with PCI device
-	 * pdev as being reserved by owner atl1_driver_name
-	 */
-	err = pci_request_regions(pdev, ATLX_DRIVER_NAME);
-	if (err)
-		goto err_request_regions;
-
-	/*
-	 * Enables bus-mastering on the device and calls
-	 * pcibios_set_master to do the needed arch specific settings
-	 */
-	pci_set_master(pdev);
-
-	netdev = alloc_etherdev(sizeof(struct atl1_adapter));
-	if (!netdev) {
-		err = -ENOMEM;
-		goto err_alloc_etherdev;
-	}
-	SET_NETDEV_DEV(netdev, &pdev->dev);
-
-	pci_set_drvdata(pdev, netdev);
-	adapter = netdev_priv(netdev);
-	adapter->netdev = netdev;
-	adapter->pdev = pdev;
-	adapter->hw.back = adapter;
-	adapter->msg_enable = netif_msg_init(debug, atl1_default_msg);
-
-	adapter->hw.hw_addr = pci_iomap(pdev, 0, 0);
-	if (!adapter->hw.hw_addr) {
-		err = -EIO;
-		goto err_pci_iomap;
-	}
-	/* get device revision number */
-	adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr +
-		(REG_MASTER_CTRL + 2));
-	if (netif_msg_probe(adapter))
-		dev_info(&pdev->dev, "version %s\n", ATLX_DRIVER_VERSION);
-
-	/* set default ring resource counts */
-	adapter->rfd_ring.count = adapter->rrd_ring.count = ATL1_DEFAULT_RFD;
-	adapter->tpd_ring.count = ATL1_DEFAULT_TPD;
-
-	adapter->mii.dev = netdev;
-	adapter->mii.mdio_read = mdio_read;
-	adapter->mii.mdio_write = mdio_write;
-	adapter->mii.phy_id_mask = 0x1f;
-	adapter->mii.reg_num_mask = 0x1f;
-
-	netdev->netdev_ops = &atl1_netdev_ops;
-	netdev->watchdog_timeo = 5 * HZ;
-
-	netdev->ethtool_ops = &atl1_ethtool_ops;
-	adapter->bd_number = cards_found;
-
-	/* setup the private structure */
-	err = atl1_sw_init(adapter);
-	if (err)
-		goto err_common;
-
-	netdev->features = NETIF_F_HW_CSUM;
-	netdev->features |= NETIF_F_SG;
-	netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
-
-	netdev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_TSO |
-			      NETIF_F_HW_VLAN_RX;
-
-	/* is this valid? see atl1_setup_mac_ctrl() */
-	netdev->features |= NETIF_F_RXCSUM;
-
-	/*
-	 * patch for some L1 of old version,
-	 * the final version of L1 may not need these
-	 * patches
-	 */
-	/* atl1_pcie_patch(adapter); */
-
-	/* really reset GPHY core */
-	iowrite16(0, adapter->hw.hw_addr + REG_PHY_ENABLE);
-
-	/*
-	 * reset the controller to
-	 * put the device in a known good starting state
-	 */
-	if (atl1_reset_hw(&adapter->hw)) {
-		err = -EIO;
-		goto err_common;
-	}
-
-	/* copy the MAC address out of the EEPROM */
-	atl1_read_mac_addr(&adapter->hw);
-	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
-
-	if (!is_valid_ether_addr(netdev->dev_addr)) {
-		err = -EIO;
-		goto err_common;
-	}
-
-	atl1_check_options(adapter);
-
-	/* pre-init the MAC, and setup link */
-	err = atl1_init_hw(&adapter->hw);
-	if (err) {
-		err = -EIO;
-		goto err_common;
-	}
-
-	atl1_pcie_patch(adapter);
-	/* assume we have no link for now */
-	netif_carrier_off(netdev);
-
-	setup_timer(&adapter->phy_config_timer, atl1_phy_config,
-		    (unsigned long)adapter);
-	adapter->phy_timer_pending = false;
-
-	INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task);
-
-	INIT_WORK(&adapter->link_chg_task, atlx_link_chg_task);
-
-	INIT_WORK(&adapter->pcie_dma_to_rst_task, atl1_tx_timeout_task);
-
-	err = register_netdev(netdev);
-	if (err)
-		goto err_common;
-
-	cards_found++;
-	atl1_via_workaround(adapter);
-	return 0;
-
-err_common:
-	pci_iounmap(pdev, adapter->hw.hw_addr);
-err_pci_iomap:
-	free_netdev(netdev);
-err_alloc_etherdev:
-	pci_release_regions(pdev);
-err_dma:
-err_request_regions:
-	pci_disable_device(pdev);
-	return err;
-}
-
-/*
- * atl1_remove - Device Removal Routine
- * @pdev: PCI device information struct
- *
- * atl1_remove is called by the PCI subsystem to alert the driver
- * that it should release a PCI device.  The could be caused by a
- * Hot-Plug event, or because the driver is going to be removed from
- * memory.
- */
-static void __devexit atl1_remove(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl1_adapter *adapter;
-	/* Device not available. Return. */
-	if (!netdev)
-		return;
-
-	adapter = netdev_priv(netdev);
-
-	/*
-	 * Some atl1 boards lack persistent storage for their MAC, and get it
-	 * from the BIOS during POST.  If we've been messing with the MAC
-	 * address, we need to save the permanent one.
-	 */
-	if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) {
-		memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr,
-			ETH_ALEN);
-		atl1_set_mac_addr(&adapter->hw);
-	}
-
-	iowrite16(0, adapter->hw.hw_addr + REG_PHY_ENABLE);
-	unregister_netdev(netdev);
-	pci_iounmap(pdev, adapter->hw.hw_addr);
-	pci_release_regions(pdev);
-	free_netdev(netdev);
-	pci_disable_device(pdev);
-}
-
-static struct pci_driver atl1_driver = {
-	.name = ATLX_DRIVER_NAME,
-	.id_table = atl1_pci_tbl,
-	.probe = atl1_probe,
-	.remove = __devexit_p(atl1_remove),
-	.shutdown = atl1_shutdown,
-	.driver.pm = ATL1_PM_OPS,
-};
-
-/*
- * atl1_exit_module - Driver Exit Cleanup Routine
- *
- * atl1_exit_module is called just before the driver is removed
- * from memory.
- */
-static void __exit atl1_exit_module(void)
-{
-	pci_unregister_driver(&atl1_driver);
-}
-
-/*
- * atl1_init_module - Driver Registration Routine
- *
- * atl1_init_module is the first routine called when the driver is
- * loaded. All it does is register with the PCI subsystem.
- */
-static int __init atl1_init_module(void)
-{
-	return pci_register_driver(&atl1_driver);
-}
-
-module_init(atl1_init_module);
-module_exit(atl1_exit_module);
-
-struct atl1_stats {
-	char stat_string[ETH_GSTRING_LEN];
-	int sizeof_stat;
-	int stat_offset;
-};
-
-#define ATL1_STAT(m) \
-	sizeof(((struct atl1_adapter *)0)->m), offsetof(struct atl1_adapter, m)
-
-static struct atl1_stats atl1_gstrings_stats[] = {
-	{"rx_packets", ATL1_STAT(soft_stats.rx_packets)},
-	{"tx_packets", ATL1_STAT(soft_stats.tx_packets)},
-	{"rx_bytes", ATL1_STAT(soft_stats.rx_bytes)},
-	{"tx_bytes", ATL1_STAT(soft_stats.tx_bytes)},
-	{"rx_errors", ATL1_STAT(soft_stats.rx_errors)},
-	{"tx_errors", ATL1_STAT(soft_stats.tx_errors)},
-	{"multicast", ATL1_STAT(soft_stats.multicast)},
-	{"collisions", ATL1_STAT(soft_stats.collisions)},
-	{"rx_length_errors", ATL1_STAT(soft_stats.rx_length_errors)},
-	{"rx_over_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
-	{"rx_crc_errors", ATL1_STAT(soft_stats.rx_crc_errors)},
-	{"rx_frame_errors", ATL1_STAT(soft_stats.rx_frame_errors)},
-	{"rx_fifo_errors", ATL1_STAT(soft_stats.rx_fifo_errors)},
-	{"rx_missed_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
-	{"tx_aborted_errors", ATL1_STAT(soft_stats.tx_aborted_errors)},
-	{"tx_carrier_errors", ATL1_STAT(soft_stats.tx_carrier_errors)},
-	{"tx_fifo_errors", ATL1_STAT(soft_stats.tx_fifo_errors)},
-	{"tx_window_errors", ATL1_STAT(soft_stats.tx_window_errors)},
-	{"tx_abort_exce_coll", ATL1_STAT(soft_stats.excecol)},
-	{"tx_abort_late_coll", ATL1_STAT(soft_stats.latecol)},
-	{"tx_deferred_ok", ATL1_STAT(soft_stats.deffer)},
-	{"tx_single_coll_ok", ATL1_STAT(soft_stats.scc)},
-	{"tx_multi_coll_ok", ATL1_STAT(soft_stats.mcc)},
-	{"tx_underun", ATL1_STAT(soft_stats.tx_underun)},
-	{"tx_trunc", ATL1_STAT(soft_stats.tx_trunc)},
-	{"tx_pause", ATL1_STAT(soft_stats.tx_pause)},
-	{"rx_pause", ATL1_STAT(soft_stats.rx_pause)},
-	{"rx_rrd_ov", ATL1_STAT(soft_stats.rx_rrd_ov)},
-	{"rx_trunc", ATL1_STAT(soft_stats.rx_trunc)}
-};
-
-static void atl1_get_ethtool_stats(struct net_device *netdev,
-	struct ethtool_stats *stats, u64 *data)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	int i;
-	char *p;
-
-	for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
-		p = (char *)adapter+atl1_gstrings_stats[i].stat_offset;
-		data[i] = (atl1_gstrings_stats[i].sizeof_stat ==
-			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
-	}
-
-}
-
-static int atl1_get_sset_count(struct net_device *netdev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		return ARRAY_SIZE(atl1_gstrings_stats);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static int atl1_get_settings(struct net_device *netdev,
-	struct ethtool_cmd *ecmd)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-
-	ecmd->supported = (SUPPORTED_10baseT_Half |
-			   SUPPORTED_10baseT_Full |
-			   SUPPORTED_100baseT_Half |
-			   SUPPORTED_100baseT_Full |
-			   SUPPORTED_1000baseT_Full |
-			   SUPPORTED_Autoneg | SUPPORTED_TP);
-	ecmd->advertising = ADVERTISED_TP;
-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
-	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
-		ecmd->advertising |= ADVERTISED_Autoneg;
-		if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR) {
-			ecmd->advertising |= ADVERTISED_Autoneg;
-			ecmd->advertising |=
-			    (ADVERTISED_10baseT_Half |
-			     ADVERTISED_10baseT_Full |
-			     ADVERTISED_100baseT_Half |
-			     ADVERTISED_100baseT_Full |
-			     ADVERTISED_1000baseT_Full);
-		} else
-			ecmd->advertising |= (ADVERTISED_1000baseT_Full);
-	}
-	ecmd->port = PORT_TP;
-	ecmd->phy_address = 0;
-	ecmd->transceiver = XCVR_INTERNAL;
-
-	if (netif_carrier_ok(adapter->netdev)) {
-		u16 link_speed, link_duplex;
-		atl1_get_speed_and_duplex(hw, &link_speed, &link_duplex);
-		ethtool_cmd_speed_set(ecmd, link_speed);
-		if (link_duplex == FULL_DUPLEX)
-			ecmd->duplex = DUPLEX_FULL;
-		else
-			ecmd->duplex = DUPLEX_HALF;
-	} else {
-		ethtool_cmd_speed_set(ecmd, -1);
-		ecmd->duplex = -1;
-	}
-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
-	    hw->media_type == MEDIA_TYPE_1000M_FULL)
-		ecmd->autoneg = AUTONEG_ENABLE;
-	else
-		ecmd->autoneg = AUTONEG_DISABLE;
-
-	return 0;
-}
-
-static int atl1_set_settings(struct net_device *netdev,
-	struct ethtool_cmd *ecmd)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-	u16 phy_data;
-	int ret_val = 0;
-	u16 old_media_type = hw->media_type;
-
-	if (netif_running(adapter->netdev)) {
-		if (netif_msg_link(adapter))
-			dev_dbg(&adapter->pdev->dev,
-				"ethtool shutting down adapter\n");
-		atl1_down(adapter);
-	}
-
-	if (ecmd->autoneg == AUTONEG_ENABLE)
-		hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
-	else {
-		u32 speed = ethtool_cmd_speed(ecmd);
-		if (speed == SPEED_1000) {
-			if (ecmd->duplex != DUPLEX_FULL) {
-				if (netif_msg_link(adapter))
-					dev_warn(&adapter->pdev->dev,
-						"1000M half is invalid\n");
-				ret_val = -EINVAL;
-				goto exit_sset;
-			}
-			hw->media_type = MEDIA_TYPE_1000M_FULL;
-		} else if (speed == SPEED_100) {
-			if (ecmd->duplex == DUPLEX_FULL)
-				hw->media_type = MEDIA_TYPE_100M_FULL;
-			else
-				hw->media_type = MEDIA_TYPE_100M_HALF;
-		} else {
-			if (ecmd->duplex == DUPLEX_FULL)
-				hw->media_type = MEDIA_TYPE_10M_FULL;
-			else
-				hw->media_type = MEDIA_TYPE_10M_HALF;
-		}
-	}
-	switch (hw->media_type) {
-	case MEDIA_TYPE_AUTO_SENSOR:
-		ecmd->advertising =
-		    ADVERTISED_10baseT_Half |
-		    ADVERTISED_10baseT_Full |
-		    ADVERTISED_100baseT_Half |
-		    ADVERTISED_100baseT_Full |
-		    ADVERTISED_1000baseT_Full |
-		    ADVERTISED_Autoneg | ADVERTISED_TP;
-		break;
-	case MEDIA_TYPE_1000M_FULL:
-		ecmd->advertising =
-		    ADVERTISED_1000baseT_Full |
-		    ADVERTISED_Autoneg | ADVERTISED_TP;
-		break;
-	default:
-		ecmd->advertising = 0;
-		break;
-	}
-	if (atl1_phy_setup_autoneg_adv(hw)) {
-		ret_val = -EINVAL;
-		if (netif_msg_link(adapter))
-			dev_warn(&adapter->pdev->dev,
-				"invalid ethtool speed/duplex setting\n");
-		goto exit_sset;
-	}
-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
-	    hw->media_type == MEDIA_TYPE_1000M_FULL)
-		phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
-	else {
-		switch (hw->media_type) {
-		case MEDIA_TYPE_100M_FULL:
-			phy_data =
-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
-			    MII_CR_RESET;
-			break;
-		case MEDIA_TYPE_100M_HALF:
-			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
-			break;
-		case MEDIA_TYPE_10M_FULL:
-			phy_data =
-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
-			break;
-		default:
-			/* MEDIA_TYPE_10M_HALF: */
-			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
-			break;
-		}
-	}
-	atl1_write_phy_reg(hw, MII_BMCR, phy_data);
-exit_sset:
-	if (ret_val)
-		hw->media_type = old_media_type;
-
-	if (netif_running(adapter->netdev)) {
-		if (netif_msg_link(adapter))
-			dev_dbg(&adapter->pdev->dev,
-				"ethtool starting adapter\n");
-		atl1_up(adapter);
-	} else if (!ret_val) {
-		if (netif_msg_link(adapter))
-			dev_dbg(&adapter->pdev->dev,
-				"ethtool resetting adapter\n");
-		atl1_reset(adapter);
-	}
-	return ret_val;
-}
-
-static void atl1_get_drvinfo(struct net_device *netdev,
-	struct ethtool_drvinfo *drvinfo)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-
-	strlcpy(drvinfo->driver, ATLX_DRIVER_NAME, sizeof(drvinfo->driver));
-	strlcpy(drvinfo->version, ATLX_DRIVER_VERSION,
-		sizeof(drvinfo->version));
-	strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
-	strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
-		sizeof(drvinfo->bus_info));
-	drvinfo->eedump_len = ATL1_EEDUMP_LEN;
-}
-
-static void atl1_get_wol(struct net_device *netdev,
-	struct ethtool_wolinfo *wol)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-
-	wol->supported = WAKE_MAGIC;
-	wol->wolopts = 0;
-	if (adapter->wol & ATLX_WUFC_MAG)
-		wol->wolopts |= WAKE_MAGIC;
-}
-
-static int atl1_set_wol(struct net_device *netdev,
-	struct ethtool_wolinfo *wol)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-
-	if (wol->wolopts & (WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST |
-		WAKE_ARP | WAKE_MAGICSECURE))
-		return -EOPNOTSUPP;
-	adapter->wol = 0;
-	if (wol->wolopts & WAKE_MAGIC)
-		adapter->wol |= ATLX_WUFC_MAG;
-
-	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
-
-	return 0;
-}
-
-static u32 atl1_get_msglevel(struct net_device *netdev)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	return adapter->msg_enable;
-}
-
-static void atl1_set_msglevel(struct net_device *netdev, u32 value)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	adapter->msg_enable = value;
-}
-
-static int atl1_get_regs_len(struct net_device *netdev)
-{
-	return ATL1_REG_COUNT * sizeof(u32);
-}
-
-static void atl1_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
-	void *p)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-	unsigned int i;
-	u32 *regbuf = p;
-
-	for (i = 0; i < ATL1_REG_COUNT; i++) {
-		/*
-		 * This switch statement avoids reserved regions
-		 * of register space.
-		 */
-		switch (i) {
-		case 6 ... 9:
-		case 14:
-		case 29 ... 31:
-		case 34 ... 63:
-		case 75 ... 127:
-		case 136 ... 1023:
-		case 1027 ... 1087:
-		case 1091 ... 1151:
-		case 1194 ... 1195:
-		case 1200 ... 1201:
-		case 1206 ... 1213:
-		case 1216 ... 1279:
-		case 1290 ... 1311:
-		case 1323 ... 1343:
-		case 1358 ... 1359:
-		case 1368 ... 1375:
-		case 1378 ... 1383:
-		case 1388 ... 1391:
-		case 1393 ... 1395:
-		case 1402 ... 1403:
-		case 1410 ... 1471:
-		case 1522 ... 1535:
-			/* reserved region; don't read it */
-			regbuf[i] = 0;
-			break;
-		default:
-			/* unreserved region */
-			regbuf[i] = ioread32(hw->hw_addr + (i * sizeof(u32)));
-		}
-	}
-}
-
-static void atl1_get_ringparam(struct net_device *netdev,
-	struct ethtool_ringparam *ring)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_tpd_ring *txdr = &adapter->tpd_ring;
-	struct atl1_rfd_ring *rxdr = &adapter->rfd_ring;
-
-	ring->rx_max_pending = ATL1_MAX_RFD;
-	ring->tx_max_pending = ATL1_MAX_TPD;
-	ring->rx_mini_max_pending = 0;
-	ring->rx_jumbo_max_pending = 0;
-	ring->rx_pending = rxdr->count;
-	ring->tx_pending = txdr->count;
-	ring->rx_mini_pending = 0;
-	ring->rx_jumbo_pending = 0;
-}
-
-static int atl1_set_ringparam(struct net_device *netdev,
-	struct ethtool_ringparam *ring)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_tpd_ring *tpdr = &adapter->tpd_ring;
-	struct atl1_rrd_ring *rrdr = &adapter->rrd_ring;
-	struct atl1_rfd_ring *rfdr = &adapter->rfd_ring;
-
-	struct atl1_tpd_ring tpd_old, tpd_new;
-	struct atl1_rfd_ring rfd_old, rfd_new;
-	struct atl1_rrd_ring rrd_old, rrd_new;
-	struct atl1_ring_header rhdr_old, rhdr_new;
-	struct atl1_smb smb;
-	struct atl1_cmb cmb;
-	int err;
-
-	tpd_old = adapter->tpd_ring;
-	rfd_old = adapter->rfd_ring;
-	rrd_old = adapter->rrd_ring;
-	rhdr_old = adapter->ring_header;
-
-	if (netif_running(adapter->netdev))
-		atl1_down(adapter);
-
-	rfdr->count = (u16) max(ring->rx_pending, (u32) ATL1_MIN_RFD);
-	rfdr->count = rfdr->count > ATL1_MAX_RFD ? ATL1_MAX_RFD :
-			rfdr->count;
-	rfdr->count = (rfdr->count + 3) & ~3;
-	rrdr->count = rfdr->count;
-
-	tpdr->count = (u16) max(ring->tx_pending, (u32) ATL1_MIN_TPD);
-	tpdr->count = tpdr->count > ATL1_MAX_TPD ? ATL1_MAX_TPD :
-			tpdr->count;
-	tpdr->count = (tpdr->count + 3) & ~3;
-
-	if (netif_running(adapter->netdev)) {
-		/* try to get new resources before deleting old */
-		err = atl1_setup_ring_resources(adapter);
-		if (err)
-			goto err_setup_ring;
-
-		/*
-		 * save the new, restore the old in order to free it,
-		 * then restore the new back again
-		 */
-
-		rfd_new = adapter->rfd_ring;
-		rrd_new = adapter->rrd_ring;
-		tpd_new = adapter->tpd_ring;
-		rhdr_new = adapter->ring_header;
-		adapter->rfd_ring = rfd_old;
-		adapter->rrd_ring = rrd_old;
-		adapter->tpd_ring = tpd_old;
-		adapter->ring_header = rhdr_old;
-		/*
-		 * Save SMB and CMB, since atl1_free_ring_resources
-		 * will clear them.
-		 */
-		smb = adapter->smb;
-		cmb = adapter->cmb;
-		atl1_free_ring_resources(adapter);
-		adapter->rfd_ring = rfd_new;
-		adapter->rrd_ring = rrd_new;
-		adapter->tpd_ring = tpd_new;
-		adapter->ring_header = rhdr_new;
-		adapter->smb = smb;
-		adapter->cmb = cmb;
-
-		err = atl1_up(adapter);
-		if (err)
-			return err;
-	}
-	return 0;
-
-err_setup_ring:
-	adapter->rfd_ring = rfd_old;
-	adapter->rrd_ring = rrd_old;
-	adapter->tpd_ring = tpd_old;
-	adapter->ring_header = rhdr_old;
-	atl1_up(adapter);
-	return err;
-}
-
-static void atl1_get_pauseparam(struct net_device *netdev,
-	struct ethtool_pauseparam *epause)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-
-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
-	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
-		epause->autoneg = AUTONEG_ENABLE;
-	} else {
-		epause->autoneg = AUTONEG_DISABLE;
-	}
-	epause->rx_pause = 1;
-	epause->tx_pause = 1;
-}
-
-static int atl1_set_pauseparam(struct net_device *netdev,
-	struct ethtool_pauseparam *epause)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-
-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
-	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
-		epause->autoneg = AUTONEG_ENABLE;
-	} else {
-		epause->autoneg = AUTONEG_DISABLE;
-	}
-
-	epause->rx_pause = 1;
-	epause->tx_pause = 1;
-
-	return 0;
-}
-
-static void atl1_get_strings(struct net_device *netdev, u32 stringset,
-	u8 *data)
-{
-	u8 *p = data;
-	int i;
-
-	switch (stringset) {
-	case ETH_SS_STATS:
-		for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
-			memcpy(p, atl1_gstrings_stats[i].stat_string,
-				ETH_GSTRING_LEN);
-			p += ETH_GSTRING_LEN;
-		}
-		break;
-	}
-}
-
-static int atl1_nway_reset(struct net_device *netdev)
-{
-	struct atl1_adapter *adapter = netdev_priv(netdev);
-	struct atl1_hw *hw = &adapter->hw;
-
-	if (netif_running(netdev)) {
-		u16 phy_data;
-		atl1_down(adapter);
-
-		if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
-			hw->media_type == MEDIA_TYPE_1000M_FULL) {
-			phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
-		} else {
-			switch (hw->media_type) {
-			case MEDIA_TYPE_100M_FULL:
-				phy_data = MII_CR_FULL_DUPLEX |
-					MII_CR_SPEED_100 | MII_CR_RESET;
-				break;
-			case MEDIA_TYPE_100M_HALF:
-				phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
-				break;
-			case MEDIA_TYPE_10M_FULL:
-				phy_data = MII_CR_FULL_DUPLEX |
-					MII_CR_SPEED_10 | MII_CR_RESET;
-				break;
-			default:
-				/* MEDIA_TYPE_10M_HALF */
-				phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
-			}
-		}
-		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
-		atl1_up(adapter);
-	}
-	return 0;
-}
-
-static const struct ethtool_ops atl1_ethtool_ops = {
-	.get_settings		= atl1_get_settings,
-	.set_settings		= atl1_set_settings,
-	.get_drvinfo		= atl1_get_drvinfo,
-	.get_wol		= atl1_get_wol,
-	.set_wol		= atl1_set_wol,
-	.get_msglevel		= atl1_get_msglevel,
-	.set_msglevel		= atl1_set_msglevel,
-	.get_regs_len		= atl1_get_regs_len,
-	.get_regs		= atl1_get_regs,
-	.get_ringparam		= atl1_get_ringparam,
-	.set_ringparam		= atl1_set_ringparam,
-	.get_pauseparam		= atl1_get_pauseparam,
-	.set_pauseparam		= atl1_set_pauseparam,
-	.get_link		= ethtool_op_get_link,
-	.get_strings		= atl1_get_strings,
-	.nway_reset		= atl1_nway_reset,
-	.get_ethtool_stats	= atl1_get_ethtool_stats,
-	.get_sset_count		= atl1_get_sset_count,
-};
diff -druN linux-libre-3.1-gnu/drivers/net/atlx/atl1.h linux-libre-3.2-gnu/drivers/net/atlx/atl1.h
--- linux-libre-3.1-gnu/drivers/net/atlx/atl1.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atlx/atl1.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,792 +0,0 @@
-/*
- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
- * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com>
- * Copyright(c) 2006 - 2008 Jay Cliburn <jcliburn@gmail.com>
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You 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 ATL1_H
-#define ATL1_H
-
-#include <linux/compiler.h>
-#include <linux/ethtool.h>
-#include <linux/if_vlan.h>
-#include <linux/mii.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/timer.h>
-#include <linux/types.h>
-#include <linux/workqueue.h>
-
-#include "atlx.h"
-
-#define ATLX_DRIVER_NAME "atl1"
-
-MODULE_DESCRIPTION("Atheros L1 Gigabit Ethernet Driver");
-
-#define atlx_adapter		atl1_adapter
-#define atlx_check_for_link	atl1_check_for_link
-#define atlx_check_link		atl1_check_link
-#define atlx_hash_mc_addr	atl1_hash_mc_addr
-#define atlx_hash_set		atl1_hash_set
-#define atlx_hw			atl1_hw
-#define atlx_mii_ioctl		atl1_mii_ioctl
-#define atlx_read_phy_reg	atl1_read_phy_reg
-#define atlx_set_mac		atl1_set_mac
-#define atlx_set_mac_addr	atl1_set_mac_addr
-
-struct atl1_adapter;
-struct atl1_hw;
-
-/* function prototypes needed by multiple files */
-static u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr);
-static void atl1_hash_set(struct atl1_hw *hw, u32 hash_value);
-static void atl1_set_mac_addr(struct atl1_hw *hw);
-static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
-	int cmd);
-static u32 atl1_check_link(struct atl1_adapter *adapter);
-
-/* hardware definitions specific to L1 */
-
-/* Block IDLE Status Register */
-#define IDLE_STATUS_RXMAC			0x1
-#define IDLE_STATUS_TXMAC			0x2
-#define IDLE_STATUS_RXQ				0x4
-#define IDLE_STATUS_TXQ				0x8
-#define IDLE_STATUS_DMAR			0x10
-#define IDLE_STATUS_DMAW			0x20
-#define IDLE_STATUS_SMB				0x40
-#define IDLE_STATUS_CMB				0x80
-
-/* MDIO Control Register */
-#define MDIO_WAIT_TIMES				30
-
-/* MAC Control Register */
-#define MAC_CTRL_TX_PAUSE			0x10000
-#define MAC_CTRL_SCNT				0x20000
-#define MAC_CTRL_SRST_TX			0x40000
-#define MAC_CTRL_TX_SIMURST			0x80000
-#define MAC_CTRL_SPEED_SHIFT			20
-#define MAC_CTRL_SPEED_MASK			0x300000
-#define MAC_CTRL_SPEED_1000			0x2
-#define MAC_CTRL_SPEED_10_100			0x1
-#define MAC_CTRL_DBG_TX_BKPRESURE		0x400000
-#define MAC_CTRL_TX_HUGE			0x800000
-#define MAC_CTRL_RX_CHKSUM_EN			0x1000000
-#define MAC_CTRL_DBG				0x8000000
-
-/* Wake-On-Lan control register */
-#define WOL_CLK_SWITCH_EN			0x8000
-#define WOL_PT5_EN				0x200000
-#define WOL_PT6_EN				0x400000
-#define WOL_PT5_MATCH				0x8000000
-#define WOL_PT6_MATCH				0x10000000
-
-/* WOL Length ( 2 DWORD ) */
-#define REG_WOL_PATTERN_LEN			0x14A4
-#define WOL_PT_LEN_MASK				0x7F
-#define WOL_PT0_LEN_SHIFT			0
-#define WOL_PT1_LEN_SHIFT			8
-#define WOL_PT2_LEN_SHIFT			16
-#define WOL_PT3_LEN_SHIFT			24
-#define WOL_PT4_LEN_SHIFT			0
-#define WOL_PT5_LEN_SHIFT			8
-#define WOL_PT6_LEN_SHIFT			16
-
-/* Internal SRAM Partition Registers, low 32 bits */
-#define REG_SRAM_RFD_LEN			0x1504
-#define REG_SRAM_RRD_ADDR			0x1508
-#define REG_SRAM_RRD_LEN			0x150C
-#define REG_SRAM_TPD_ADDR			0x1510
-#define REG_SRAM_TPD_LEN			0x1514
-#define REG_SRAM_TRD_ADDR			0x1518
-#define REG_SRAM_TRD_LEN			0x151C
-#define REG_SRAM_RXF_ADDR			0x1520
-#define REG_SRAM_RXF_LEN			0x1524
-#define REG_SRAM_TXF_ADDR			0x1528
-#define REG_SRAM_TXF_LEN			0x152C
-#define REG_SRAM_TCPH_PATH_ADDR			0x1530
-#define SRAM_TCPH_ADDR_MASK			0xFFF
-#define SRAM_TCPH_ADDR_SHIFT			0
-#define SRAM_PATH_ADDR_MASK			0xFFF
-#define SRAM_PATH_ADDR_SHIFT			16
-
-/* Load Ptr Register */
-#define REG_LOAD_PTR				0x1534
-
-/* Descriptor Control registers, low 32 bits */
-#define REG_DESC_RFD_ADDR_LO			0x1544
-#define REG_DESC_RRD_ADDR_LO			0x1548
-#define REG_DESC_TPD_ADDR_LO			0x154C
-#define REG_DESC_CMB_ADDR_LO			0x1550
-#define REG_DESC_SMB_ADDR_LO			0x1554
-#define REG_DESC_RFD_RRD_RING_SIZE		0x1558
-#define DESC_RFD_RING_SIZE_MASK			0x7FF
-#define DESC_RFD_RING_SIZE_SHIFT		0
-#define DESC_RRD_RING_SIZE_MASK			0x7FF
-#define DESC_RRD_RING_SIZE_SHIFT		16
-#define REG_DESC_TPD_RING_SIZE			0x155C
-#define DESC_TPD_RING_SIZE_MASK			0x3FF
-#define DESC_TPD_RING_SIZE_SHIFT		0
-
-/* TXQ Control Register */
-#define REG_TXQ_CTRL				0x1580
-#define TXQ_CTRL_TPD_BURST_NUM_SHIFT		0
-#define TXQ_CTRL_TPD_BURST_NUM_MASK		0x1F
-#define TXQ_CTRL_EN				0x20
-#define TXQ_CTRL_ENH_MODE			0x40
-#define TXQ_CTRL_TPD_FETCH_TH_SHIFT		8
-#define TXQ_CTRL_TPD_FETCH_TH_MASK		0x3F
-#define TXQ_CTRL_TXF_BURST_NUM_SHIFT		16
-#define TXQ_CTRL_TXF_BURST_NUM_MASK		0xFFFF
-
-/* Jumbo packet Threshold for task offload */
-#define REG_TX_JUMBO_TASK_TH_TPD_IPG		0x1584
-#define TX_JUMBO_TASK_TH_MASK			0x7FF
-#define TX_JUMBO_TASK_TH_SHIFT			0
-#define TX_TPD_MIN_IPG_MASK			0x1F
-#define TX_TPD_MIN_IPG_SHIFT			16
-
-/* RXQ Control Register */
-#define REG_RXQ_CTRL				0x15A0
-#define RXQ_CTRL_RFD_BURST_NUM_SHIFT		0
-#define RXQ_CTRL_RFD_BURST_NUM_MASK		0xFF
-#define RXQ_CTRL_RRD_BURST_THRESH_SHIFT		8
-#define RXQ_CTRL_RRD_BURST_THRESH_MASK		0xFF
-#define RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT		16
-#define RXQ_CTRL_RFD_PREF_MIN_IPG_MASK		0x1F
-#define RXQ_CTRL_CUT_THRU_EN			0x40000000
-#define RXQ_CTRL_EN				0x80000000
-
-/* Rx jumbo packet threshold and rrd  retirement timer */
-#define REG_RXQ_JMBOSZ_RRDTIM			0x15A4
-#define RXQ_JMBOSZ_TH_MASK			0x7FF
-#define RXQ_JMBOSZ_TH_SHIFT			0
-#define RXQ_JMBO_LKAH_MASK			0xF
-#define RXQ_JMBO_LKAH_SHIFT			11
-#define RXQ_RRD_TIMER_MASK			0xFFFF
-#define RXQ_RRD_TIMER_SHIFT			16
-
-/* RFD flow control register */
-#define REG_RXQ_RXF_PAUSE_THRESH		0x15A8
-#define RXQ_RXF_PAUSE_TH_HI_SHIFT		16
-#define RXQ_RXF_PAUSE_TH_HI_MASK		0xFFF
-#define RXQ_RXF_PAUSE_TH_LO_SHIFT		0
-#define RXQ_RXF_PAUSE_TH_LO_MASK		0xFFF
-
-/* RRD flow control register */
-#define REG_RXQ_RRD_PAUSE_THRESH		0x15AC
-#define RXQ_RRD_PAUSE_TH_HI_SHIFT		0
-#define RXQ_RRD_PAUSE_TH_HI_MASK		0xFFF
-#define RXQ_RRD_PAUSE_TH_LO_SHIFT		16
-#define RXQ_RRD_PAUSE_TH_LO_MASK		0xFFF
-
-/* DMA Engine Control Register */
-#define REG_DMA_CTRL				0x15C0
-#define DMA_CTRL_DMAR_IN_ORDER			0x1
-#define DMA_CTRL_DMAR_ENH_ORDER			0x2
-#define DMA_CTRL_DMAR_OUT_ORDER			0x4
-#define DMA_CTRL_RCB_VALUE			0x8
-#define DMA_CTRL_DMAR_BURST_LEN_SHIFT		4
-#define DMA_CTRL_DMAR_BURST_LEN_MASK		7
-#define DMA_CTRL_DMAW_BURST_LEN_SHIFT		7
-#define DMA_CTRL_DMAW_BURST_LEN_MASK		7
-#define DMA_CTRL_DMAR_EN			0x400
-#define DMA_CTRL_DMAW_EN			0x800
-
-/* CMB/SMB Control Register */
-#define REG_CSMB_CTRL				0x15D0
-#define CSMB_CTRL_CMB_NOW			1
-#define CSMB_CTRL_SMB_NOW			2
-#define CSMB_CTRL_CMB_EN			4
-#define CSMB_CTRL_SMB_EN			8
-
-/* CMB DMA Write Threshold Register */
-#define REG_CMB_WRITE_TH			0x15D4
-#define CMB_RRD_TH_SHIFT			0
-#define CMB_RRD_TH_MASK				0x7FF
-#define CMB_TPD_TH_SHIFT			16
-#define CMB_TPD_TH_MASK				0x7FF
-
-/* RX/TX count-down timer to trigger CMB-write. 2us resolution. */
-#define REG_CMB_WRITE_TIMER			0x15D8
-#define CMB_RX_TM_SHIFT				0
-#define CMB_RX_TM_MASK				0xFFFF
-#define CMB_TX_TM_SHIFT				16
-#define CMB_TX_TM_MASK				0xFFFF
-
-/* Number of packet received since last CMB write */
-#define REG_CMB_RX_PKT_CNT			0x15DC
-
-/* Number of packet transmitted since last CMB write */
-#define REG_CMB_TX_PKT_CNT			0x15E0
-
-/* SMB auto DMA timer register */
-#define REG_SMB_TIMER				0x15E4
-
-/* Mailbox Register */
-#define REG_MAILBOX				0x15F0
-#define MB_RFD_PROD_INDX_SHIFT			0
-#define MB_RFD_PROD_INDX_MASK			0x7FF
-#define MB_RRD_CONS_INDX_SHIFT			11
-#define MB_RRD_CONS_INDX_MASK			0x7FF
-#define MB_TPD_PROD_INDX_SHIFT			22
-#define MB_TPD_PROD_INDX_MASK			0x3FF
-
-/* Interrupt Status Register */
-#define ISR_SMB					0x1
-#define ISR_TIMER				0x2
-#define ISR_MANUAL				0x4
-#define ISR_RXF_OV				0x8
-#define ISR_RFD_UNRUN				0x10
-#define ISR_RRD_OV				0x20
-#define ISR_TXF_UNRUN				0x40
-#define ISR_LINK				0x80
-#define ISR_HOST_RFD_UNRUN			0x100
-#define ISR_HOST_RRD_OV				0x200
-#define ISR_DMAR_TO_RST				0x400
-#define ISR_DMAW_TO_RST				0x800
-#define ISR_GPHY				0x1000
-#define ISR_RX_PKT				0x10000
-#define ISR_TX_PKT				0x20000
-#define ISR_TX_DMA				0x40000
-#define ISR_RX_DMA				0x80000
-#define ISR_CMB_RX				0x100000
-#define ISR_CMB_TX				0x200000
-#define ISR_MAC_RX				0x400000
-#define ISR_MAC_TX				0x800000
-#define ISR_DIS_SMB				0x20000000
-#define ISR_DIS_DMA				0x40000000
-
-/* Normal Interrupt mask  */
-#define IMR_NORMAL_MASK	(\
-	ISR_SMB		|\
-	ISR_GPHY	|\
-	ISR_PHY_LINKDOWN|\
-	ISR_DMAR_TO_RST	|\
-	ISR_DMAW_TO_RST	|\
-	ISR_CMB_TX	|\
-	ISR_CMB_RX)
-
-/* Debug Interrupt Mask  (enable all interrupt) */
-#define IMR_DEBUG_MASK	(\
-	ISR_SMB		|\
-	ISR_TIMER	|\
-	ISR_MANUAL	|\
-	ISR_RXF_OV	|\
-	ISR_RFD_UNRUN	|\
-	ISR_RRD_OV	|\
-	ISR_TXF_UNRUN	|\
-	ISR_LINK	|\
-	ISR_CMB_TX	|\
-	ISR_CMB_RX	|\
-	ISR_RX_PKT	|\
-	ISR_TX_PKT	|\
-	ISR_MAC_RX	|\
-	ISR_MAC_TX)
-
-#define MEDIA_TYPE_1000M_FULL			1
-#define MEDIA_TYPE_100M_FULL			2
-#define MEDIA_TYPE_100M_HALF			3
-#define MEDIA_TYPE_10M_FULL			4
-#define MEDIA_TYPE_10M_HALF			5
-
-#define AUTONEG_ADVERTISE_SPEED_DEFAULT		0x002F	/* All but 1000-Half */
-
-#define MAX_JUMBO_FRAME_SIZE			10240
-
-#define ATL1_EEDUMP_LEN				48
-
-/* Statistics counters collected by the MAC */
-struct stats_msg_block {
-	/* rx */
-	u32 rx_ok;		/* good RX packets */
-	u32 rx_bcast;		/* good RX broadcast packets */
-	u32 rx_mcast;		/* good RX multicast packets */
-	u32 rx_pause;		/* RX pause frames */
-	u32 rx_ctrl;		/* RX control packets other than pause frames */
-	u32 rx_fcs_err;		/* RX packets with bad FCS */
-	u32 rx_len_err;		/* RX packets with length != actual size */
-	u32 rx_byte_cnt;	/* good bytes received. FCS is NOT included */
-	u32 rx_runt;		/* RX packets < 64 bytes with good FCS */
-	u32 rx_frag;		/* RX packets < 64 bytes with bad FCS */
-	u32 rx_sz_64;		/* 64 byte RX packets */
-	u32 rx_sz_65_127;
-	u32 rx_sz_128_255;
-	u32 rx_sz_256_511;
-	u32 rx_sz_512_1023;
-	u32 rx_sz_1024_1518;
-	u32 rx_sz_1519_max;	/* 1519 byte to MTU RX packets */
-	u32 rx_sz_ov;		/* truncated RX packets > MTU */
-	u32 rx_rxf_ov;		/* frames dropped due to RX FIFO overflow */
-	u32 rx_rrd_ov;		/* frames dropped due to RRD overflow */
-	u32 rx_align_err;	/* alignment errors */
-	u32 rx_bcast_byte_cnt;	/* RX broadcast bytes, excluding FCS */
-	u32 rx_mcast_byte_cnt;	/* RX multicast bytes, excluding FCS */
-	u32 rx_err_addr;	/* packets dropped due to address filtering */
-
-	/* tx */
-	u32 tx_ok;		/* good TX packets */
-	u32 tx_bcast;		/* good TX broadcast packets */
-	u32 tx_mcast;		/* good TX multicast packets */
-	u32 tx_pause;		/* TX pause frames */
-	u32 tx_exc_defer;	/* TX packets deferred excessively */
-	u32 tx_ctrl;		/* TX control frames, excluding pause frames */
-	u32 tx_defer;		/* TX packets deferred */
-	u32 tx_byte_cnt;	/* bytes transmitted, FCS is NOT included */
-	u32 tx_sz_64;		/* 64 byte TX packets */
-	u32 tx_sz_65_127;
-	u32 tx_sz_128_255;
-	u32 tx_sz_256_511;
-	u32 tx_sz_512_1023;
-	u32 tx_sz_1024_1518;
-	u32 tx_sz_1519_max;	/* 1519 byte to MTU TX packets */
-	u32 tx_1_col;		/* packets TX after a single collision */
-	u32 tx_2_col;		/* packets TX after multiple collisions */
-	u32 tx_late_col;	/* TX packets with late collisions */
-	u32 tx_abort_col;	/* TX packets aborted w/excessive collisions */
-	u32 tx_underrun;	/* TX packets aborted due to TX FIFO underrun
-				 * or TRD FIFO underrun */
-	u32 tx_rd_eop;		/* reads beyond the EOP into the next frame
-				 * when TRD was not written timely */
-	u32 tx_len_err;		/* TX packets where length != actual size */
-	u32 tx_trunc;		/* TX packets truncated due to size > MTU */
-	u32 tx_bcast_byte;	/* broadcast bytes transmitted, excluding FCS */
-	u32 tx_mcast_byte;	/* multicast bytes transmitted, excluding FCS */
-	u32 smb_updated;	/* 1: SMB Updated. This is used by software to
-				 * indicate the statistics update. Software
-				 * should clear this bit after retrieving the
-				 * statistics information. */
-};
-
-/* Coalescing Message Block */
-struct coals_msg_block {
-	u32 int_stats;		/* interrupt status */
-	u16 rrd_prod_idx;	/* TRD Producer Index. */
-	u16 rfd_cons_idx;	/* RFD Consumer Index. */
-	u16 update;		/* Selene sets this bit every time it DMAs the
-				 * CMB to host memory. Software should clear
-				 * this bit when CMB info is processed. */
-	u16 tpd_cons_idx;	/* TPD Consumer Index. */
-};
-
-/* RRD descriptor */
-struct rx_return_desc {
-	u8 num_buf;	/* Number of RFD buffers used by the received packet */
-	u8 resved;
-	u16 buf_indx;	/* RFD Index of the first buffer */
-	union {
-		u32 valid;
-		struct {
-			u16 rx_chksum;
-			u16 pkt_size;
-		} xsum_sz;
-	} xsz;
-
-	u16 pkt_flg;	/* Packet flags */
-	u16 err_flg;	/* Error flags */
-	u16 resved2;
-	u16 vlan_tag;	/* VLAN TAG */
-};
-
-#define PACKET_FLAG_ETH_TYPE	0x0080
-#define PACKET_FLAG_VLAN_INS	0x0100
-#define PACKET_FLAG_ERR		0x0200
-#define PACKET_FLAG_IPV4	0x0400
-#define PACKET_FLAG_UDP		0x0800
-#define PACKET_FLAG_TCP		0x1000
-#define PACKET_FLAG_BCAST	0x2000
-#define PACKET_FLAG_MCAST	0x4000
-#define PACKET_FLAG_PAUSE	0x8000
-
-#define ERR_FLAG_CRC		0x0001
-#define ERR_FLAG_CODE		0x0002
-#define ERR_FLAG_DRIBBLE	0x0004
-#define ERR_FLAG_RUNT		0x0008
-#define ERR_FLAG_OV		0x0010
-#define ERR_FLAG_TRUNC		0x0020
-#define ERR_FLAG_IP_CHKSUM	0x0040
-#define ERR_FLAG_L4_CHKSUM	0x0080
-#define ERR_FLAG_LEN		0x0100
-#define ERR_FLAG_DES_ADDR	0x0200
-
-/* RFD descriptor */
-struct rx_free_desc {
-	__le64 buffer_addr;	/* Address of the descriptor's data buffer */
-	__le16 buf_len;		/* Size of the receive buffer in host memory */
-	u16 coalese;		/* Update consumer index to host after the
-				 * reception of this frame */
-	/* __packed is required */
-} __packed;
-
-/*
- * The L1 transmit packet descriptor is comprised of four 32-bit words.
- *
- *	31					0
- *	+---------------------------------------+
- *      |	Word 0: Buffer addr lo 		|
- *      +---------------------------------------+
- *      |	Word 1: Buffer addr hi		|
- *      +---------------------------------------+
- *      |		Word 2			|
- *      +---------------------------------------+
- *      |		Word 3			|
- *      +---------------------------------------+
- *
- * Words 0 and 1 combine to form a 64-bit buffer address.
- *
- * Word 2 is self explanatory in the #define block below.
- *
- * Word 3 has two forms, depending upon the state of bits 3 and 4.
- * If bits 3 and 4 are both zero, then bits 14:31 are unused by the
- * hardware.  Otherwise, if either bit 3 or 4 is set, the definition
- * of bits 14:31 vary according to the following depiction.
- *
- *	0	End of packet			0	End of packet
- *	1	Coalesce			1	Coalesce
- *	2	Insert VLAN tag			2	Insert VLAN tag
- *	3	Custom csum enable = 0		3	Custom csum enable = 1
- *	4	Segment enable = 1		4	Segment enable = 0
- *	5	Generate IP checksum		5	Generate IP checksum
- *	6	Generate TCP checksum		6	Generate TCP checksum
- *	7	Generate UDP checksum		7	Generate UDP checksum
- *	8	VLAN tagged			8	VLAN tagged
- *	9	Ethernet frame type		9	Ethernet frame type
- *	10-+ 					10-+
- *	11 |	IP hdr length (10:13)		11 |	IP hdr length (10:13)
- *	12 |	(num 32-bit words)		12 |	(num 32-bit words)
- *	13-+					13-+
- *	14-+					14	Unused
- *	15 |	TCP hdr length (14:17)		15	Unused
- *	16 |	(num 32-bit words)		16-+
- *	17-+					17 |
- *	18	Header TPD flag			18 |
- *	19-+					19 |	Payload offset
- *	20 |					20 |	    (16:23)
- *	21 |					21 |
- *	22 |					22 |
- *	23 |					23-+
- *	24 |					24-+
- *	25 |	MSS (19:31)			25 |
- *	26 |					26 |
- *	27 |					27 |	Custom csum offset
- *	28 |					28 |	     (24:31)
- *	29 |					29 |
- *	30 |					30 |
- *	31-+					31-+
- */
-
-/* tpd word 2 */
-#define TPD_BUFLEN_MASK		0x3FFF
-#define TPD_BUFLEN_SHIFT	0
-#define TPD_DMAINT_MASK		0x0001
-#define TPD_DMAINT_SHIFT	14
-#define TPD_PKTNT_MASK		0x0001
-#define TPD_PKTINT_SHIFT	15
-#define TPD_VLANTAG_MASK	0xFFFF
-#define TPD_VLANTAG_SHIFT	16
-
-/* tpd word 3 bits 0:13 */
-#define TPD_EOP_MASK		0x0001
-#define TPD_EOP_SHIFT		0
-#define TPD_COALESCE_MASK	0x0001
-#define TPD_COALESCE_SHIFT	1
-#define TPD_INS_VL_TAG_MASK	0x0001
-#define TPD_INS_VL_TAG_SHIFT	2
-#define TPD_CUST_CSUM_EN_MASK	0x0001
-#define TPD_CUST_CSUM_EN_SHIFT	3
-#define TPD_SEGMENT_EN_MASK	0x0001
-#define TPD_SEGMENT_EN_SHIFT	4
-#define TPD_IP_CSUM_MASK	0x0001
-#define TPD_IP_CSUM_SHIFT	5
-#define TPD_TCP_CSUM_MASK	0x0001
-#define TPD_TCP_CSUM_SHIFT	6
-#define TPD_UDP_CSUM_MASK	0x0001
-#define TPD_UDP_CSUM_SHIFT	7
-#define TPD_VL_TAGGED_MASK	0x0001
-#define TPD_VL_TAGGED_SHIFT	8
-#define TPD_ETHTYPE_MASK	0x0001
-#define TPD_ETHTYPE_SHIFT	9
-#define TPD_IPHL_MASK		0x000F
-#define TPD_IPHL_SHIFT		10
-
-/* tpd word 3 bits 14:31 if segment enabled */
-#define TPD_TCPHDRLEN_MASK	0x000F
-#define TPD_TCPHDRLEN_SHIFT	14
-#define TPD_HDRFLAG_MASK	0x0001
-#define TPD_HDRFLAG_SHIFT	18
-#define TPD_MSS_MASK		0x1FFF
-#define TPD_MSS_SHIFT		19
-
-/* tpd word 3 bits 16:31 if custom csum enabled */
-#define TPD_PLOADOFFSET_MASK	0x00FF
-#define TPD_PLOADOFFSET_SHIFT	16
-#define TPD_CCSUMOFFSET_MASK	0x00FF
-#define TPD_CCSUMOFFSET_SHIFT	24
-
-struct tx_packet_desc {
-	__le64 buffer_addr;
-	__le32 word2;
-	__le32 word3;
-};
-
-/* DMA Order Settings */
-enum atl1_dma_order {
-	atl1_dma_ord_in = 1,
-	atl1_dma_ord_enh = 2,
-	atl1_dma_ord_out = 4
-};
-
-enum atl1_dma_rcb {
-	atl1_rcb_64 = 0,
-	atl1_rcb_128 = 1
-};
-
-enum atl1_dma_req_block {
-	atl1_dma_req_128 = 0,
-	atl1_dma_req_256 = 1,
-	atl1_dma_req_512 = 2,
-	atl1_dma_req_1024 = 3,
-	atl1_dma_req_2048 = 4,
-	atl1_dma_req_4096 = 5
-};
-
-#define ATL1_MAX_INTR		3
-#define ATL1_MAX_TX_BUF_LEN	0x3000	/* 12288 bytes */
-
-#define ATL1_DEFAULT_TPD	256
-#define ATL1_MAX_TPD		1024
-#define ATL1_MIN_TPD		64
-#define ATL1_DEFAULT_RFD	512
-#define ATL1_MIN_RFD		128
-#define ATL1_MAX_RFD		2048
-#define ATL1_REG_COUNT		1538
-
-#define ATL1_GET_DESC(R, i, type)	(&(((type *)((R)->desc))[i]))
-#define ATL1_RFD_DESC(R, i)	ATL1_GET_DESC(R, i, struct rx_free_desc)
-#define ATL1_TPD_DESC(R, i)	ATL1_GET_DESC(R, i, struct tx_packet_desc)
-#define ATL1_RRD_DESC(R, i)	ATL1_GET_DESC(R, i, struct rx_return_desc)
-
-/*
- * atl1_ring_header represents a single, contiguous block of DMA space
- * mapped for the three descriptor rings (tpd, rfd, rrd) and the two
- * message blocks (cmb, smb) described below
- */
-struct atl1_ring_header {
-	void *desc;		/* virtual address */
-	dma_addr_t dma;		/* physical address*/
-	unsigned int size;	/* length in bytes */
-};
-
-/*
- * atl1_buffer is wrapper around a pointer to a socket buffer
- * so a DMA handle can be stored along with the skb
- */
-struct atl1_buffer {
-	struct sk_buff *skb;	/* socket buffer */
-	u16 length;		/* rx buffer length */
-	u16 alloced;		/* 1 if skb allocated */
-	dma_addr_t dma;
-};
-
-/* transmit packet descriptor (tpd) ring */
-struct atl1_tpd_ring {
-	void *desc;		/* descriptor ring virtual address */
-	dma_addr_t dma;		/* descriptor ring physical address */
-	u16 size;		/* descriptor ring length in bytes */
-	u16 count;		/* number of descriptors in the ring */
-	u16 hw_idx;		/* hardware index */
-	atomic_t next_to_clean;
-	atomic_t next_to_use;
-	struct atl1_buffer *buffer_info;
-};
-
-/* receive free descriptor (rfd) ring */
-struct atl1_rfd_ring {
-	void *desc;		/* descriptor ring virtual address */
-	dma_addr_t dma;		/* descriptor ring physical address */
-	u16 size;		/* descriptor ring length in bytes */
-	u16 count;		/* number of descriptors in the ring */
-	atomic_t next_to_use;
-	u16 next_to_clean;
-	struct atl1_buffer *buffer_info;
-};
-
-/* receive return descriptor (rrd) ring */
-struct atl1_rrd_ring {
-	void *desc;		/* descriptor ring virtual address */
-	dma_addr_t dma;		/* descriptor ring physical address */
-	unsigned int size;	/* descriptor ring length in bytes */
-	u16 count;		/* number of descriptors in the ring */
-	u16 next_to_use;
-	atomic_t next_to_clean;
-};
-
-/* coalescing message block (cmb) */
-struct atl1_cmb {
-	struct coals_msg_block *cmb;
-	dma_addr_t dma;
-};
-
-/* statistics message block (smb) */
-struct atl1_smb {
-	struct stats_msg_block *smb;
-	dma_addr_t dma;
-};
-
-/* Statistics counters */
-struct atl1_sft_stats {
-	u64 rx_packets;
-	u64 tx_packets;
-	u64 rx_bytes;
-	u64 tx_bytes;
-	u64 multicast;
-	u64 collisions;
-	u64 rx_errors;
-	u64 rx_length_errors;
-	u64 rx_crc_errors;
-	u64 rx_frame_errors;
-	u64 rx_fifo_errors;
-	u64 rx_missed_errors;
-	u64 tx_errors;
-	u64 tx_fifo_errors;
-	u64 tx_aborted_errors;
-	u64 tx_window_errors;
-	u64 tx_carrier_errors;
-	u64 tx_pause;		/* TX pause frames */
-	u64 excecol;		/* TX packets w/ excessive collisions */
-	u64 deffer;		/* TX packets deferred */
-	u64 scc;		/* packets TX after a single collision */
-	u64 mcc;		/* packets TX after multiple collisions */
-	u64 latecol;		/* TX packets w/ late collisions */
-	u64 tx_underun;		/* TX packets aborted due to TX FIFO underrun
-				 * or TRD FIFO underrun */
-	u64 tx_trunc;		/* TX packets truncated due to size > MTU */
-	u64 rx_pause;		/* num Pause packets received. */
-	u64 rx_rrd_ov;
-	u64 rx_trunc;
-};
-
-/* hardware structure */
-struct atl1_hw {
-	u8 __iomem *hw_addr;
-	struct atl1_adapter *back;
-	enum atl1_dma_order dma_ord;
-	enum atl1_dma_rcb rcb_value;
-	enum atl1_dma_req_block dmar_block;
-	enum atl1_dma_req_block dmaw_block;
-	u8 preamble_len;
-	u8 max_retry;
-	u8 jam_ipg;		/* IPG to start JAM for collision based flow
-				 * control in half-duplex mode. In units of
-				 * 8-bit time */
-	u8 ipgt;		/* Desired back to back inter-packet gap.
-				 * The default is 96-bit time */
-	u8 min_ifg;		/* Minimum number of IFG to enforce in between
-				 * receive frames. Frame gap below such IFP
-				 * is dropped */
-	u8 ipgr1;		/* 64bit Carrier-Sense window */
-	u8 ipgr2;		/* 96-bit IPG window */
-	u8 tpd_burst;		/* Number of TPD to prefetch in cache-aligned
-				 * burst. Each TPD is 16 bytes long */
-	u8 rfd_burst;		/* Number of RFD to prefetch in cache-aligned
-				 * burst. Each RFD is 12 bytes long */
-	u8 rfd_fetch_gap;
-	u8 rrd_burst;		/* Threshold number of RRDs that can be retired
-				 * in a burst. Each RRD is 16 bytes long */
-	u8 tpd_fetch_th;
-	u8 tpd_fetch_gap;
-	u16 tx_jumbo_task_th;
-	u16 txf_burst;		/* Number of data bytes to read in a cache-
-				 * aligned burst. Each SRAM entry is 8 bytes */
-	u16 rx_jumbo_th;	/* Jumbo packet size for non-VLAN packet. VLAN
-				 * packets should add 4 bytes */
-	u16 rx_jumbo_lkah;
-	u16 rrd_ret_timer;	/* RRD retirement timer. Decrement by 1 after
-				 * every 512ns passes. */
-	u16 lcol;		/* Collision Window */
-
-	u16 cmb_tpd;
-	u16 cmb_rrd;
-	u16 cmb_rx_timer;
-	u16 cmb_tx_timer;
-	u32 smb_timer;
-	u16 media_type;
-	u16 autoneg_advertised;
-
-	u16 mii_autoneg_adv_reg;
-	u16 mii_1000t_ctrl_reg;
-
-	u32 max_frame_size;
-	u32 min_frame_size;
-
-	u16 dev_rev;
-
-	/* spi flash */
-	u8 flash_vendor;
-
-	u8 mac_addr[ETH_ALEN];
-	u8 perm_mac_addr[ETH_ALEN];
-
-	bool phy_configured;
-};
-
-struct atl1_adapter {
-	struct net_device *netdev;
-	struct pci_dev *pdev;
-
-	struct atl1_sft_stats soft_stats;
-	u32 rx_buffer_len;
-	u32 wol;
-	u16 link_speed;
-	u16 link_duplex;
-	spinlock_t lock;
-	struct work_struct tx_timeout_task;
-	struct work_struct link_chg_task;
-	struct work_struct pcie_dma_to_rst_task;
-
-	struct timer_list phy_config_timer;
-	bool phy_timer_pending;
-
-	/* all descriptor rings' memory */
-	struct atl1_ring_header ring_header;
-
-	/* TX */
-	struct atl1_tpd_ring tpd_ring;
-	spinlock_t mb_lock;
-
-	/* RX */
-	struct atl1_rfd_ring rfd_ring;
-	struct atl1_rrd_ring rrd_ring;
-	u64 hw_csum_err;
-	u64 hw_csum_good;
-	u32 msg_enable;
-	u16 imt;		/* interrupt moderator timer (2us resolution) */
-	u16 ict;		/* interrupt clear timer (2us resolution */
-	struct mii_if_info mii;	/* MII interface info */
-
-	u32 bd_number;		/* board number */
-	bool pci_using_64;
-	struct atl1_hw hw;
-	struct atl1_smb smb;
-	struct atl1_cmb cmb;
-};
-
-#endif /* ATL1_H */
diff -druN linux-libre-3.1-gnu/drivers/net/atlx/atl2.c linux-libre-3.2-gnu/drivers/net/atlx/atl2.c
--- linux-libre-3.1-gnu/drivers/net/atlx/atl2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atlx/atl2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3119 +0,0 @@
-/*
- * Copyright(c) 2006 - 2007 Atheros Corporation. All rights reserved.
- * Copyright(c) 2007 - 2008 Chris Snook <csnook@redhat.com>
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You 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/atomic.h>
-#include <linux/crc32.h>
-#include <linux/dma-mapping.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/hardirq.h>
-#include <linux/if_vlan.h>
-#include <linux/in.h>
-#include <linux/interrupt.h>
-#include <linux/ip.h>
-#include <linux/irqflags.h>
-#include <linux/irqreturn.h>
-#include <linux/mii.h>
-#include <linux/net.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
-#include <linux/pm.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/tcp.h>
-#include <linux/timer.h>
-#include <linux/types.h>
-#include <linux/workqueue.h>
-
-#include "atl2.h"
-
-#define ATL2_DRV_VERSION "2.2.3"
-
-static const char atl2_driver_name[] = "atl2";
-static const char atl2_driver_string[] = "Atheros(R) L2 Ethernet Driver";
-static const char atl2_copyright[] = "Copyright (c) 2007 Atheros Corporation.";
-static const char atl2_driver_version[] = ATL2_DRV_VERSION;
-
-MODULE_AUTHOR("Atheros Corporation <xiong.huang@atheros.com>, Chris Snook <csnook@redhat.com>");
-MODULE_DESCRIPTION("Atheros Fast Ethernet Network Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(ATL2_DRV_VERSION);
-
-/*
- * atl2_pci_tbl - PCI Device ID Table
- */
-static DEFINE_PCI_DEVICE_TABLE(atl2_pci_tbl) = {
-	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2)},
-	/* required last entry */
-	{0,}
-};
-MODULE_DEVICE_TABLE(pci, atl2_pci_tbl);
-
-static void atl2_set_ethtool_ops(struct net_device *netdev);
-
-static void atl2_check_options(struct atl2_adapter *adapter);
-
-/*
- * atl2_sw_init - Initialize general software structures (struct atl2_adapter)
- * @adapter: board private structure to initialize
- *
- * atl2_sw_init initializes the Adapter private data structure.
- * Fields are initialized based on PCI device information and
- * OS network device settings (MTU size).
- */
-static int __devinit atl2_sw_init(struct atl2_adapter *adapter)
-{
-	struct atl2_hw *hw = &adapter->hw;
-	struct pci_dev *pdev = adapter->pdev;
-
-	/* PCI config space info */
-	hw->vendor_id = pdev->vendor;
-	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_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
-
-	adapter->wol = 0;
-	adapter->ict = 50000;  /* ~100ms */
-	adapter->link_speed = SPEED_0;   /* hardware init */
-	adapter->link_duplex = FULL_DUPLEX;
-
-	hw->phy_configured = false;
-	hw->preamble_len = 7;
-	hw->ipgt = 0x60;
-	hw->min_ifg = 0x50;
-	hw->ipgr1 = 0x40;
-	hw->ipgr2 = 0x60;
-	hw->retry_buf = 2;
-	hw->max_retry = 0xf;
-	hw->lcol = 0x37;
-	hw->jam_ipg = 7;
-	hw->fc_rxd_hi = 0;
-	hw->fc_rxd_lo = 0;
-	hw->max_frame_size = adapter->netdev->mtu;
-
-	spin_lock_init(&adapter->stats_lock);
-
-	set_bit(__ATL2_DOWN, &adapter->flags);
-
-	return 0;
-}
-
-/*
- * atl2_set_multi - Multicast and Promiscuous mode set
- * @netdev: network interface device structure
- *
- * The set_multi entry point is called whenever the multicast address
- * list or the network interface flags are updated.  This routine is
- * responsible for configuring the hardware for proper multicast,
- * promiscuous mode, and all-multi behavior.
- */
-static void atl2_set_multi(struct net_device *netdev)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-	struct atl2_hw *hw = &adapter->hw;
-	struct netdev_hw_addr *ha;
-	u32 rctl;
-	u32 hash_value;
-
-	/* Check for Promiscuous and All Multicast modes */
-	rctl = ATL2_READ_REG(hw, REG_MAC_CTRL);
-
-	if (netdev->flags & IFF_PROMISC) {
-		rctl |= MAC_CTRL_PROMIS_EN;
-	} else if (netdev->flags & IFF_ALLMULTI) {
-		rctl |= MAC_CTRL_MC_ALL_EN;
-		rctl &= ~MAC_CTRL_PROMIS_EN;
-	} else
-		rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
-
-	ATL2_WRITE_REG(hw, REG_MAC_CTRL, rctl);
-
-	/* clear the old settings from the multicast hash table */
-	ATL2_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
-	ATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
-
-	/* comoute mc addresses' hash value ,and put it into hash table */
-	netdev_for_each_mc_addr(ha, netdev) {
-		hash_value = atl2_hash_mc_addr(hw, ha->addr);
-		atl2_hash_set(hw, hash_value);
-	}
-}
-
-static void init_ring_ptrs(struct atl2_adapter *adapter)
-{
-	/* Read / Write Ptr Initialize: */
-	adapter->txd_write_ptr = 0;
-	atomic_set(&adapter->txd_read_ptr, 0);
-
-	adapter->rxd_read_ptr = 0;
-	adapter->rxd_write_ptr = 0;
-
-	atomic_set(&adapter->txs_write_ptr, 0);
-	adapter->txs_next_clear = 0;
-}
-
-/*
- * atl2_configure - Configure Transmit&Receive Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Tx /Rx unit of the MAC after a reset.
- */
-static int atl2_configure(struct atl2_adapter *adapter)
-{
-	struct atl2_hw *hw = &adapter->hw;
-	u32 value;
-
-	/* clear interrupt status */
-	ATL2_WRITE_REG(&adapter->hw, REG_ISR, 0xffffffff);
-
-	/* set MAC Address */
-	value = (((u32)hw->mac_addr[2]) << 24) |
-		(((u32)hw->mac_addr[3]) << 16) |
-		(((u32)hw->mac_addr[4]) << 8) |
-		(((u32)hw->mac_addr[5]));
-	ATL2_WRITE_REG(hw, REG_MAC_STA_ADDR, value);
-	value = (((u32)hw->mac_addr[0]) << 8) |
-		(((u32)hw->mac_addr[1]));
-	ATL2_WRITE_REG(hw, (REG_MAC_STA_ADDR+4), value);
-
-	/* HI base address */
-	ATL2_WRITE_REG(hw, REG_DESC_BASE_ADDR_HI,
-		(u32)((adapter->ring_dma & 0xffffffff00000000ULL) >> 32));
-
-	/* LO base address */
-	ATL2_WRITE_REG(hw, REG_TXD_BASE_ADDR_LO,
-		(u32)(adapter->txd_dma & 0x00000000ffffffffULL));
-	ATL2_WRITE_REG(hw, REG_TXS_BASE_ADDR_LO,
-		(u32)(adapter->txs_dma & 0x00000000ffffffffULL));
-	ATL2_WRITE_REG(hw, REG_RXD_BASE_ADDR_LO,
-		(u32)(adapter->rxd_dma & 0x00000000ffffffffULL));
-
-	/* element count */
-	ATL2_WRITE_REGW(hw, REG_TXD_MEM_SIZE, (u16)(adapter->txd_ring_size/4));
-	ATL2_WRITE_REGW(hw, REG_TXS_MEM_SIZE, (u16)adapter->txs_ring_size);
-	ATL2_WRITE_REGW(hw, REG_RXD_BUF_NUM,  (u16)adapter->rxd_ring_size);
-
-	/* config Internal SRAM */
-/*
-    ATL2_WRITE_REGW(hw, REG_SRAM_TXRAM_END, sram_tx_end);
-    ATL2_WRITE_REGW(hw, REG_SRAM_TXRAM_END, sram_rx_end);
-*/
-
-	/* config IPG/IFG */
-	value = (((u32)hw->ipgt & MAC_IPG_IFG_IPGT_MASK) <<
-		MAC_IPG_IFG_IPGT_SHIFT) |
-		(((u32)hw->min_ifg & MAC_IPG_IFG_MIFG_MASK) <<
-		MAC_IPG_IFG_MIFG_SHIFT) |
-		(((u32)hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK) <<
-		MAC_IPG_IFG_IPGR1_SHIFT)|
-		(((u32)hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK) <<
-		MAC_IPG_IFG_IPGR2_SHIFT);
-	ATL2_WRITE_REG(hw, REG_MAC_IPG_IFG, value);
-
-	/* config  Half-Duplex Control */
-	value = ((u32)hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
-		(((u32)hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK) <<
-		MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
-		MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
-		(0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
-		(((u32)hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK) <<
-		MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
-	ATL2_WRITE_REG(hw, REG_MAC_HALF_DUPLX_CTRL, value);
-
-	/* set Interrupt Moderator Timer */
-	ATL2_WRITE_REGW(hw, REG_IRQ_MODU_TIMER_INIT, adapter->imt);
-	ATL2_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_ITIMER_EN);
-
-	/* set Interrupt Clear Timer */
-	ATL2_WRITE_REGW(hw, REG_CMBDISDMA_TIMER, adapter->ict);
-
-	/* set MTU */
-	ATL2_WRITE_REG(hw, REG_MTU, adapter->netdev->mtu +
-		ENET_HEADER_SIZE + VLAN_SIZE + ETHERNET_FCS_SIZE);
-
-	/* 1590 */
-	ATL2_WRITE_REG(hw, REG_TX_CUT_THRESH, 0x177);
-
-	/* flow control */
-	ATL2_WRITE_REGW(hw, REG_PAUSE_ON_TH, hw->fc_rxd_hi);
-	ATL2_WRITE_REGW(hw, REG_PAUSE_OFF_TH, hw->fc_rxd_lo);
-
-	/* Init mailbox */
-	ATL2_WRITE_REGW(hw, REG_MB_TXD_WR_IDX, (u16)adapter->txd_write_ptr);
-	ATL2_WRITE_REGW(hw, REG_MB_RXD_RD_IDX, (u16)adapter->rxd_read_ptr);
-
-	/* enable DMA read/write */
-	ATL2_WRITE_REGB(hw, REG_DMAR, DMAR_EN);
-	ATL2_WRITE_REGB(hw, REG_DMAW, DMAW_EN);
-
-	value = ATL2_READ_REG(&adapter->hw, REG_ISR);
-	if ((value & ISR_PHY_LINKDOWN) != 0)
-		value = 1; /* config failed */
-	else
-		value = 0;
-
-	/* clear all interrupt status */
-	ATL2_WRITE_REG(&adapter->hw, REG_ISR, 0x3fffffff);
-	ATL2_WRITE_REG(&adapter->hw, REG_ISR, 0);
-	return value;
-}
-
-/*
- * atl2_setup_ring_resources - allocate Tx / RX descriptor resources
- * @adapter: board private structure
- *
- * Return 0 on success, negative on failure
- */
-static s32 atl2_setup_ring_resources(struct atl2_adapter *adapter)
-{
-	struct pci_dev *pdev = adapter->pdev;
-	int size;
-	u8 offset = 0;
-
-	/* real ring DMA buffer */
-	adapter->ring_size = size =
-		adapter->txd_ring_size * 1 + 7 +	/* dword align */
-		adapter->txs_ring_size * 4 + 7 +	/* dword align */
-		adapter->rxd_ring_size * 1536 + 127;	/* 128bytes align */
-
-	adapter->ring_vir_addr = pci_alloc_consistent(pdev, size,
-		&adapter->ring_dma);
-	if (!adapter->ring_vir_addr)
-		return -ENOMEM;
-	memset(adapter->ring_vir_addr, 0, adapter->ring_size);
-
-	/* Init TXD Ring */
-	adapter->txd_dma = adapter->ring_dma ;
-	offset = (adapter->txd_dma & 0x7) ? (8 - (adapter->txd_dma & 0x7)) : 0;
-	adapter->txd_dma += offset;
-	adapter->txd_ring = adapter->ring_vir_addr + offset;
-
-	/* Init TXS Ring */
-	adapter->txs_dma = adapter->txd_dma + adapter->txd_ring_size;
-	offset = (adapter->txs_dma & 0x7) ? (8 - (adapter->txs_dma & 0x7)) : 0;
-	adapter->txs_dma += offset;
-	adapter->txs_ring = (struct tx_pkt_status *)
-		(((u8 *)adapter->txd_ring) + (adapter->txd_ring_size + offset));
-
-	/* Init RXD Ring */
-	adapter->rxd_dma = adapter->txs_dma + adapter->txs_ring_size * 4;
-	offset = (adapter->rxd_dma & 127) ?
-		(128 - (adapter->rxd_dma & 127)) : 0;
-	if (offset > 7)
-		offset -= 8;
-	else
-		offset += (128 - 8);
-
-	adapter->rxd_dma += offset;
-	adapter->rxd_ring = (struct rx_desc *) (((u8 *)adapter->txs_ring) +
-		(adapter->txs_ring_size * 4 + offset));
-
-/*
- * Read / Write Ptr Initialize:
- *      init_ring_ptrs(adapter);
- */
-	return 0;
-}
-
-/*
- * atl2_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- */
-static inline void atl2_irq_enable(struct atl2_adapter *adapter)
-{
-	ATL2_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK);
-	ATL2_WRITE_FLUSH(&adapter->hw);
-}
-
-/*
- * atl2_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- */
-static inline void atl2_irq_disable(struct atl2_adapter *adapter)
-{
-    ATL2_WRITE_REG(&adapter->hw, REG_IMR, 0);
-    ATL2_WRITE_FLUSH(&adapter->hw);
-    synchronize_irq(adapter->pdev->irq);
-}
-
-static void __atl2_vlan_mode(u32 features, u32 *ctrl)
-{
-	if (features & NETIF_F_HW_VLAN_RX) {
-		/* enable VLAN tag insert/strip */
-		*ctrl |= MAC_CTRL_RMV_VLAN;
-	} else {
-		/* disable VLAN tag insert/strip */
-		*ctrl &= ~MAC_CTRL_RMV_VLAN;
-	}
-}
-
-static void atl2_vlan_mode(struct net_device *netdev, u32 features)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-	u32 ctrl;
-
-	atl2_irq_disable(adapter);
-
-	ctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL);
-	__atl2_vlan_mode(features, &ctrl);
-	ATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl);
-
-	atl2_irq_enable(adapter);
-}
-
-static void atl2_restore_vlan(struct atl2_adapter *adapter)
-{
-	atl2_vlan_mode(adapter->netdev, adapter->netdev->features);
-}
-
-static u32 atl2_fix_features(struct net_device *netdev, u32 features)
-{
-	/*
-	 * Since there is no support for separate rx/tx vlan accel
-	 * enable/disable make sure tx flag is always in same state as rx.
-	 */
-	if (features & NETIF_F_HW_VLAN_RX)
-		features |= NETIF_F_HW_VLAN_TX;
-	else
-		features &= ~NETIF_F_HW_VLAN_TX;
-
-	return features;
-}
-
-static int atl2_set_features(struct net_device *netdev, u32 features)
-{
-	u32 changed = netdev->features ^ features;
-
-	if (changed & NETIF_F_HW_VLAN_RX)
-		atl2_vlan_mode(netdev, features);
-
-	return 0;
-}
-
-static void atl2_intr_rx(struct atl2_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct rx_desc *rxd;
-	struct sk_buff *skb;
-
-	do {
-		rxd = adapter->rxd_ring+adapter->rxd_write_ptr;
-		if (!rxd->status.update)
-			break; /* end of tx */
-
-		/* clear this flag at once */
-		rxd->status.update = 0;
-
-		if (rxd->status.ok && rxd->status.pkt_size >= 60) {
-			int rx_size = (int)(rxd->status.pkt_size - 4);
-			/* alloc new buffer */
-			skb = netdev_alloc_skb_ip_align(netdev, rx_size);
-			if (NULL == skb) {
-				printk(KERN_WARNING
-					"%s: Mem squeeze, deferring packet.\n",
-					netdev->name);
-				/*
-				 * Check that some rx space is free. If not,
-				 * free one and mark stats->rx_dropped++.
-				 */
-				netdev->stats.rx_dropped++;
-				break;
-			}
-			memcpy(skb->data, rxd->packet, rx_size);
-			skb_put(skb, rx_size);
-			skb->protocol = eth_type_trans(skb, netdev);
-			if (rxd->status.vlan) {
-				u16 vlan_tag = (rxd->status.vtag>>4) |
-					((rxd->status.vtag&7) << 13) |
-					((rxd->status.vtag&8) << 9);
-
-				__vlan_hwaccel_put_tag(skb, vlan_tag);
-			}
-			netif_rx(skb);
-			netdev->stats.rx_bytes += rx_size;
-			netdev->stats.rx_packets++;
-		} else {
-			netdev->stats.rx_errors++;
-
-			if (rxd->status.ok && rxd->status.pkt_size <= 60)
-				netdev->stats.rx_length_errors++;
-			if (rxd->status.mcast)
-				netdev->stats.multicast++;
-			if (rxd->status.crc)
-				netdev->stats.rx_crc_errors++;
-			if (rxd->status.align)
-				netdev->stats.rx_frame_errors++;
-		}
-
-		/* advance write ptr */
-		if (++adapter->rxd_write_ptr == adapter->rxd_ring_size)
-			adapter->rxd_write_ptr = 0;
-	} while (1);
-
-	/* update mailbox? */
-	adapter->rxd_read_ptr = adapter->rxd_write_ptr;
-	ATL2_WRITE_REGW(&adapter->hw, REG_MB_RXD_RD_IDX, adapter->rxd_read_ptr);
-}
-
-static void atl2_intr_tx(struct atl2_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	u32 txd_read_ptr;
-	u32 txs_write_ptr;
-	struct tx_pkt_status *txs;
-	struct tx_pkt_header *txph;
-	int free_hole = 0;
-
-	do {
-		txs_write_ptr = (u32) atomic_read(&adapter->txs_write_ptr);
-		txs = adapter->txs_ring + txs_write_ptr;
-		if (!txs->update)
-			break; /* tx stop here */
-
-		free_hole = 1;
-		txs->update = 0;
-
-		if (++txs_write_ptr == adapter->txs_ring_size)
-			txs_write_ptr = 0;
-		atomic_set(&adapter->txs_write_ptr, (int)txs_write_ptr);
-
-		txd_read_ptr = (u32) atomic_read(&adapter->txd_read_ptr);
-		txph = (struct tx_pkt_header *)
-			(((u8 *)adapter->txd_ring) + txd_read_ptr);
-
-		if (txph->pkt_size != txs->pkt_size) {
-			struct tx_pkt_status *old_txs = txs;
-			printk(KERN_WARNING
-				"%s: txs packet size not consistent with txd"
-				" txd_:0x%08x, txs_:0x%08x!\n",
-				adapter->netdev->name,
-				*(u32 *)txph, *(u32 *)txs);
-			printk(KERN_WARNING
-				"txd read ptr: 0x%x\n",
-				txd_read_ptr);
-			txs = adapter->txs_ring + txs_write_ptr;
-			printk(KERN_WARNING
-				"txs-behind:0x%08x\n",
-				*(u32 *)txs);
-			if (txs_write_ptr < 2) {
-				txs = adapter->txs_ring +
-					(adapter->txs_ring_size +
-					txs_write_ptr - 2);
-			} else {
-				txs = adapter->txs_ring + (txs_write_ptr - 2);
-			}
-			printk(KERN_WARNING
-				"txs-before:0x%08x\n",
-				*(u32 *)txs);
-			txs = old_txs;
-		}
-
-		 /* 4for TPH */
-		txd_read_ptr += (((u32)(txph->pkt_size) + 7) & ~3);
-		if (txd_read_ptr >= adapter->txd_ring_size)
-			txd_read_ptr -= adapter->txd_ring_size;
-
-		atomic_set(&adapter->txd_read_ptr, (int)txd_read_ptr);
-
-		/* tx statistics: */
-		if (txs->ok) {
-			netdev->stats.tx_bytes += txs->pkt_size;
-			netdev->stats.tx_packets++;
-		}
-		else
-			netdev->stats.tx_errors++;
-
-		if (txs->defer)
-			netdev->stats.collisions++;
-		if (txs->abort_col)
-			netdev->stats.tx_aborted_errors++;
-		if (txs->late_col)
-			netdev->stats.tx_window_errors++;
-		if (txs->underun)
-			netdev->stats.tx_fifo_errors++;
-	} while (1);
-
-	if (free_hole) {
-		if (netif_queue_stopped(adapter->netdev) &&
-			netif_carrier_ok(adapter->netdev))
-			netif_wake_queue(adapter->netdev);
-	}
-}
-
-static void atl2_check_for_link(struct atl2_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	u16 phy_data = 0;
-
-	spin_lock(&adapter->stats_lock);
-	atl2_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
-	atl2_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
-	spin_unlock(&adapter->stats_lock);
-
-	/* notify upper layer link down ASAP */
-	if (!(phy_data & BMSR_LSTATUS)) { /* Link Down */
-		if (netif_carrier_ok(netdev)) { /* old link state: Up */
-		printk(KERN_INFO "%s: %s NIC Link is Down\n",
-			atl2_driver_name, netdev->name);
-		adapter->link_speed = SPEED_0;
-		netif_carrier_off(netdev);
-		netif_stop_queue(netdev);
-		}
-	}
-	schedule_work(&adapter->link_chg_task);
-}
-
-static inline void atl2_clear_phy_int(struct atl2_adapter *adapter)
-{
-	u16 phy_data;
-	spin_lock(&adapter->stats_lock);
-	atl2_read_phy_reg(&adapter->hw, 19, &phy_data);
-	spin_unlock(&adapter->stats_lock);
-}
-
-/*
- * atl2_intr - Interrupt Handler
- * @irq: interrupt number
- * @data: pointer to a network interface device structure
- * @pt_regs: CPU registers structure
- */
-static irqreturn_t atl2_intr(int irq, void *data)
-{
-	struct atl2_adapter *adapter = netdev_priv(data);
-	struct atl2_hw *hw = &adapter->hw;
-	u32 status;
-
-	status = ATL2_READ_REG(hw, REG_ISR);
-	if (0 == status)
-		return IRQ_NONE;
-
-	/* link event */
-	if (status & ISR_PHY)
-		atl2_clear_phy_int(adapter);
-
-	/* clear ISR status, and Enable CMB DMA/Disable Interrupt */
-	ATL2_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT);
-
-	/* check if PCIE PHY Link down */
-	if (status & ISR_PHY_LINKDOWN) {
-		if (netif_running(adapter->netdev)) { /* reset MAC */
-			ATL2_WRITE_REG(hw, REG_ISR, 0);
-			ATL2_WRITE_REG(hw, REG_IMR, 0);
-			ATL2_WRITE_FLUSH(hw);
-			schedule_work(&adapter->reset_task);
-			return IRQ_HANDLED;
-		}
-	}
-
-	/* check if DMA read/write error? */
-	if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
-		ATL2_WRITE_REG(hw, REG_ISR, 0);
-		ATL2_WRITE_REG(hw, REG_IMR, 0);
-		ATL2_WRITE_FLUSH(hw);
-		schedule_work(&adapter->reset_task);
-		return IRQ_HANDLED;
-	}
-
-	/* link event */
-	if (status & (ISR_PHY | ISR_MANUAL)) {
-		adapter->netdev->stats.tx_carrier_errors++;
-		atl2_check_for_link(adapter);
-	}
-
-	/* transmit event */
-	if (status & ISR_TX_EVENT)
-		atl2_intr_tx(adapter);
-
-	/* rx exception */
-	if (status & ISR_RX_EVENT)
-		atl2_intr_rx(adapter);
-
-	/* re-enable Interrupt */
-	ATL2_WRITE_REG(&adapter->hw, REG_ISR, 0);
-	return IRQ_HANDLED;
-}
-
-static int atl2_request_irq(struct atl2_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	int flags, err = 0;
-
-	flags = IRQF_SHARED;
-	adapter->have_msi = true;
-	err = pci_enable_msi(adapter->pdev);
-	if (err)
-		adapter->have_msi = false;
-
-	if (adapter->have_msi)
-		flags &= ~IRQF_SHARED;
-
-	return request_irq(adapter->pdev->irq, atl2_intr, flags, netdev->name,
-		netdev);
-}
-
-/*
- * atl2_free_ring_resources - Free Tx / RX descriptor Resources
- * @adapter: board private structure
- *
- * Free all transmit software resources
- */
-static void atl2_free_ring_resources(struct atl2_adapter *adapter)
-{
-	struct pci_dev *pdev = adapter->pdev;
-	pci_free_consistent(pdev, adapter->ring_size, adapter->ring_vir_addr,
-		adapter->ring_dma);
-}
-
-/*
- * atl2_open - Called when a network interface is made active
- * @netdev: network interface device structure
- *
- * Returns 0 on success, negative value on failure
- *
- * 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.
- */
-static int atl2_open(struct net_device *netdev)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-	int err;
-	u32 val;
-
-	/* disallow open during test */
-	if (test_bit(__ATL2_TESTING, &adapter->flags))
-		return -EBUSY;
-
-	/* allocate transmit descriptors */
-	err = atl2_setup_ring_resources(adapter);
-	if (err)
-		return err;
-
-	err = atl2_init_hw(&adapter->hw);
-	if (err) {
-		err = -EIO;
-		goto err_init_hw;
-	}
-
-	/* hardware has been reset, we need to reload some things */
-	atl2_set_multi(netdev);
-	init_ring_ptrs(adapter);
-
-	atl2_restore_vlan(adapter);
-
-	if (atl2_configure(adapter)) {
-		err = -EIO;
-		goto err_config;
-	}
-
-	err = atl2_request_irq(adapter);
-	if (err)
-		goto err_req_irq;
-
-	clear_bit(__ATL2_DOWN, &adapter->flags);
-
-	mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 4*HZ));
-
-	val = ATL2_READ_REG(&adapter->hw, REG_MASTER_CTRL);
-	ATL2_WRITE_REG(&adapter->hw, REG_MASTER_CTRL,
-		val | MASTER_CTRL_MANUAL_INT);
-
-	atl2_irq_enable(adapter);
-
-	return 0;
-
-err_init_hw:
-err_req_irq:
-err_config:
-	atl2_free_ring_resources(adapter);
-	atl2_reset_hw(&adapter->hw);
-
-	return err;
-}
-
-static void atl2_down(struct atl2_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-
-	/* signal that we're down so the interrupt handler does not
-	 * reschedule our watchdog timer */
-	set_bit(__ATL2_DOWN, &adapter->flags);
-
-	netif_tx_disable(netdev);
-
-	/* reset MAC to disable all RX/TX */
-	atl2_reset_hw(&adapter->hw);
-	msleep(1);
-
-	atl2_irq_disable(adapter);
-
-	del_timer_sync(&adapter->watchdog_timer);
-	del_timer_sync(&adapter->phy_config_timer);
-	clear_bit(0, &adapter->cfg_phy);
-
-	netif_carrier_off(netdev);
-	adapter->link_speed = SPEED_0;
-	adapter->link_duplex = -1;
-}
-
-static void atl2_free_irq(struct atl2_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-
-	free_irq(adapter->pdev->irq, netdev);
-
-#ifdef CONFIG_PCI_MSI
-	if (adapter->have_msi)
-		pci_disable_msi(adapter->pdev);
-#endif
-}
-
-/*
- * atl2_close - Disables a network interface
- * @netdev: network interface device structure
- *
- * 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.
- */
-static int atl2_close(struct net_device *netdev)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-
-	WARN_ON(test_bit(__ATL2_RESETTING, &adapter->flags));
-
-	atl2_down(adapter);
-	atl2_free_irq(adapter);
-	atl2_free_ring_resources(adapter);
-
-	return 0;
-}
-
-static inline int TxsFreeUnit(struct atl2_adapter *adapter)
-{
-	u32 txs_write_ptr = (u32) atomic_read(&adapter->txs_write_ptr);
-
-	return (adapter->txs_next_clear >= txs_write_ptr) ?
-		(int) (adapter->txs_ring_size - adapter->txs_next_clear +
-		txs_write_ptr - 1) :
-		(int) (txs_write_ptr - adapter->txs_next_clear - 1);
-}
-
-static inline int TxdFreeBytes(struct atl2_adapter *adapter)
-{
-	u32 txd_read_ptr = (u32)atomic_read(&adapter->txd_read_ptr);
-
-	return (adapter->txd_write_ptr >= txd_read_ptr) ?
-		(int) (adapter->txd_ring_size - adapter->txd_write_ptr +
-		txd_read_ptr - 1) :
-		(int) (txd_read_ptr - adapter->txd_write_ptr - 1);
-}
-
-static netdev_tx_t atl2_xmit_frame(struct sk_buff *skb,
-					 struct net_device *netdev)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-	struct tx_pkt_header *txph;
-	u32 offset, copy_len;
-	int txs_unused;
-	int txbuf_unused;
-
-	if (test_bit(__ATL2_DOWN, &adapter->flags)) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	if (unlikely(skb->len <= 0)) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	txs_unused = TxsFreeUnit(adapter);
-	txbuf_unused = TxdFreeBytes(adapter);
-
-	if (skb->len + sizeof(struct tx_pkt_header) + 4  > txbuf_unused ||
-		txs_unused < 1) {
-		/* not enough resources */
-		netif_stop_queue(netdev);
-		return NETDEV_TX_BUSY;
-	}
-
-	offset = adapter->txd_write_ptr;
-
-	txph = (struct tx_pkt_header *) (((u8 *)adapter->txd_ring) + offset);
-
-	*(u32 *)txph = 0;
-	txph->pkt_size = skb->len;
-
-	offset += 4;
-	if (offset >= adapter->txd_ring_size)
-		offset -= adapter->txd_ring_size;
-	copy_len = adapter->txd_ring_size - offset;
-	if (copy_len >= skb->len) {
-		memcpy(((u8 *)adapter->txd_ring) + offset, skb->data, skb->len);
-		offset += ((u32)(skb->len + 3) & ~3);
-	} else {
-		memcpy(((u8 *)adapter->txd_ring)+offset, skb->data, copy_len);
-		memcpy((u8 *)adapter->txd_ring, skb->data+copy_len,
-			skb->len-copy_len);
-		offset = ((u32)(skb->len-copy_len + 3) & ~3);
-	}
-#ifdef NETIF_F_HW_VLAN_TX
-	if (vlan_tx_tag_present(skb)) {
-		u16 vlan_tag = vlan_tx_tag_get(skb);
-		vlan_tag = (vlan_tag << 4) |
-			(vlan_tag >> 13) |
-			((vlan_tag >> 9) & 0x8);
-		txph->ins_vlan = 1;
-		txph->vlan = vlan_tag;
-	}
-#endif
-	if (offset >= adapter->txd_ring_size)
-		offset -= adapter->txd_ring_size;
-	adapter->txd_write_ptr = offset;
-
-	/* clear txs before send */
-	adapter->txs_ring[adapter->txs_next_clear].update = 0;
-	if (++adapter->txs_next_clear == adapter->txs_ring_size)
-		adapter->txs_next_clear = 0;
-
-	ATL2_WRITE_REGW(&adapter->hw, REG_MB_TXD_WR_IDX,
-		(adapter->txd_write_ptr >> 2));
-
-	mmiowb();
-	dev_kfree_skb_any(skb);
-	return NETDEV_TX_OK;
-}
-
-/*
- * atl2_change_mtu - Change the Maximum Transfer Unit
- * @netdev: network interface device structure
- * @new_mtu: new value for maximum frame size
- *
- * Returns 0 on success, negative on failure
- */
-static int atl2_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-	struct atl2_hw *hw = &adapter->hw;
-
-	if ((new_mtu < 40) || (new_mtu > (ETH_DATA_LEN + VLAN_SIZE)))
-		return -EINVAL;
-
-	/* set MTU */
-	if (hw->max_frame_size != new_mtu) {
-		netdev->mtu = new_mtu;
-		ATL2_WRITE_REG(hw, REG_MTU, new_mtu + ENET_HEADER_SIZE +
-			VLAN_SIZE + ETHERNET_FCS_SIZE);
-	}
-
-	return 0;
-}
-
-/*
- * atl2_set_mac - Change the Ethernet Address of the NIC
- * @netdev: network interface device structure
- * @p: pointer to an address structure
- *
- * Returns 0 on success, negative on failure
- */
-static int atl2_set_mac(struct net_device *netdev, void *p)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-	struct sockaddr *addr = p;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	if (netif_running(netdev))
-		return -EBUSY;
-
-	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
-
-	atl2_set_mac_addr(&adapter->hw);
-
-	return 0;
-}
-
-/*
- * atl2_mii_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- */
-static int atl2_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-	struct mii_ioctl_data *data = if_mii(ifr);
-	unsigned long flags;
-
-	switch (cmd) {
-	case SIOCGMIIPHY:
-		data->phy_id = 0;
-		break;
-	case SIOCGMIIREG:
-		spin_lock_irqsave(&adapter->stats_lock, flags);
-		if (atl2_read_phy_reg(&adapter->hw,
-			data->reg_num & 0x1F, &data->val_out)) {
-			spin_unlock_irqrestore(&adapter->stats_lock, flags);
-			return -EIO;
-		}
-		spin_unlock_irqrestore(&adapter->stats_lock, flags);
-		break;
-	case SIOCSMIIREG:
-		if (data->reg_num & ~(0x1F))
-			return -EFAULT;
-		spin_lock_irqsave(&adapter->stats_lock, flags);
-		if (atl2_write_phy_reg(&adapter->hw, data->reg_num,
-			data->val_in)) {
-			spin_unlock_irqrestore(&adapter->stats_lock, flags);
-			return -EIO;
-		}
-		spin_unlock_irqrestore(&adapter->stats_lock, flags);
-		break;
-	default:
-		return -EOPNOTSUPP;
-	}
-	return 0;
-}
-
-/*
- * atl2_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- */
-static int atl2_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	switch (cmd) {
-	case SIOCGMIIPHY:
-	case SIOCGMIIREG:
-	case SIOCSMIIREG:
-		return atl2_mii_ioctl(netdev, ifr, cmd);
-#ifdef ETHTOOL_OPS_COMPAT
-	case SIOCETHTOOL:
-		return ethtool_ioctl(ifr);
-#endif
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-/*
- * atl2_tx_timeout - Respond to a Tx Hang
- * @netdev: network interface device structure
- */
-static void atl2_tx_timeout(struct net_device *netdev)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-
-	/* Do the reset outside of interrupt context */
-	schedule_work(&adapter->reset_task);
-}
-
-/*
- * atl2_watchdog - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
- */
-static void atl2_watchdog(unsigned long data)
-{
-	struct atl2_adapter *adapter = (struct atl2_adapter *) data;
-
-	if (!test_bit(__ATL2_DOWN, &adapter->flags)) {
-		u32 drop_rxd, drop_rxs;
-		unsigned long flags;
-
-		spin_lock_irqsave(&adapter->stats_lock, flags);
-		drop_rxd = ATL2_READ_REG(&adapter->hw, REG_STS_RXD_OV);
-		drop_rxs = ATL2_READ_REG(&adapter->hw, REG_STS_RXS_OV);
-		spin_unlock_irqrestore(&adapter->stats_lock, flags);
-
-		adapter->netdev->stats.rx_over_errors += drop_rxd + drop_rxs;
-
-		/* Reset the timer */
-		mod_timer(&adapter->watchdog_timer,
-			  round_jiffies(jiffies + 4 * HZ));
-	}
-}
-
-/*
- * atl2_phy_config - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
- */
-static void atl2_phy_config(unsigned long data)
-{
-	struct atl2_adapter *adapter = (struct atl2_adapter *) data;
-	struct atl2_hw *hw = &adapter->hw;
-	unsigned long flags;
-
-	spin_lock_irqsave(&adapter->stats_lock, flags);
-	atl2_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
-	atl2_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN |
-		MII_CR_RESTART_AUTO_NEG);
-	spin_unlock_irqrestore(&adapter->stats_lock, flags);
-	clear_bit(0, &adapter->cfg_phy);
-}
-
-static int atl2_up(struct atl2_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	int err = 0;
-	u32 val;
-
-	/* hardware has been reset, we need to reload some things */
-
-	err = atl2_init_hw(&adapter->hw);
-	if (err) {
-		err = -EIO;
-		return err;
-	}
-
-	atl2_set_multi(netdev);
-	init_ring_ptrs(adapter);
-
-	atl2_restore_vlan(adapter);
-
-	if (atl2_configure(adapter)) {
-		err = -EIO;
-		goto err_up;
-	}
-
-	clear_bit(__ATL2_DOWN, &adapter->flags);
-
-	val = ATL2_READ_REG(&adapter->hw, REG_MASTER_CTRL);
-	ATL2_WRITE_REG(&adapter->hw, REG_MASTER_CTRL, val |
-		MASTER_CTRL_MANUAL_INT);
-
-	atl2_irq_enable(adapter);
-
-err_up:
-	return err;
-}
-
-static void atl2_reinit_locked(struct atl2_adapter *adapter)
-{
-	WARN_ON(in_interrupt());
-	while (test_and_set_bit(__ATL2_RESETTING, &adapter->flags))
-		msleep(1);
-	atl2_down(adapter);
-	atl2_up(adapter);
-	clear_bit(__ATL2_RESETTING, &adapter->flags);
-}
-
-static void atl2_reset_task(struct work_struct *work)
-{
-	struct atl2_adapter *adapter;
-	adapter = container_of(work, struct atl2_adapter, reset_task);
-
-	atl2_reinit_locked(adapter);
-}
-
-static void atl2_setup_mac_ctrl(struct atl2_adapter *adapter)
-{
-	u32 value;
-	struct atl2_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-
-	/* Config MAC CTRL Register */
-	value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN | MAC_CTRL_MACLP_CLK_PHY;
-
-	/* duplex */
-	if (FULL_DUPLEX == adapter->link_duplex)
-		value |= MAC_CTRL_DUPLX;
-
-	/* flow control */
-	value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
-
-	/* PAD & CRC */
-	value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
-
-	/* preamble length */
-	value |= (((u32)adapter->hw.preamble_len & MAC_CTRL_PRMLEN_MASK) <<
-		MAC_CTRL_PRMLEN_SHIFT);
-
-	/* vlan */
-	__atl2_vlan_mode(netdev->features, &value);
-
-	/* filter mode */
-	value |= MAC_CTRL_BC_EN;
-	if (netdev->flags & IFF_PROMISC)
-		value |= MAC_CTRL_PROMIS_EN;
-	else if (netdev->flags & IFF_ALLMULTI)
-		value |= MAC_CTRL_MC_ALL_EN;
-
-	/* half retry buffer */
-	value |= (((u32)(adapter->hw.retry_buf &
-		MAC_CTRL_HALF_LEFT_BUF_MASK)) << MAC_CTRL_HALF_LEFT_BUF_SHIFT);
-
-	ATL2_WRITE_REG(hw, REG_MAC_CTRL, value);
-}
-
-static int atl2_check_link(struct atl2_adapter *adapter)
-{
-	struct atl2_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	int ret_val;
-	u16 speed, duplex, phy_data;
-	int reconfig = 0;
-
-	/* MII_BMSR must read twise */
-	atl2_read_phy_reg(hw, MII_BMSR, &phy_data);
-	atl2_read_phy_reg(hw, MII_BMSR, &phy_data);
-	if (!(phy_data&BMSR_LSTATUS)) { /* link down */
-		if (netif_carrier_ok(netdev)) { /* old link state: Up */
-			u32 value;
-			/* disable rx */
-			value = ATL2_READ_REG(hw, REG_MAC_CTRL);
-			value &= ~MAC_CTRL_RX_EN;
-			ATL2_WRITE_REG(hw, REG_MAC_CTRL, value);
-			adapter->link_speed = SPEED_0;
-			netif_carrier_off(netdev);
-			netif_stop_queue(netdev);
-		}
-		return 0;
-	}
-
-	/* Link Up */
-	ret_val = atl2_get_speed_and_duplex(hw, &speed, &duplex);
-	if (ret_val)
-		return ret_val;
-	switch (hw->MediaType) {
-	case MEDIA_TYPE_100M_FULL:
-		if (speed  != SPEED_100 || duplex != FULL_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_100M_HALF:
-		if (speed  != SPEED_100 || duplex != HALF_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_10M_FULL:
-		if (speed != SPEED_10 || duplex != FULL_DUPLEX)
-			reconfig = 1;
-		break;
-	case MEDIA_TYPE_10M_HALF:
-		if (speed  != SPEED_10 || duplex != HALF_DUPLEX)
-			reconfig = 1;
-		break;
-	}
-	/* link result is our setting */
-	if (reconfig == 0) {
-		if (adapter->link_speed != speed ||
-			adapter->link_duplex != duplex) {
-			adapter->link_speed = speed;
-			adapter->link_duplex = duplex;
-			atl2_setup_mac_ctrl(adapter);
-			printk(KERN_INFO "%s: %s NIC Link is Up<%d Mbps %s>\n",
-				atl2_driver_name, netdev->name,
-				adapter->link_speed,
-				adapter->link_duplex == FULL_DUPLEX ?
-					"Full Duplex" : "Half Duplex");
-		}
-
-		if (!netif_carrier_ok(netdev)) { /* Link down -> Up */
-			netif_carrier_on(netdev);
-			netif_wake_queue(netdev);
-		}
-		return 0;
-	}
-
-	/* change original link status */
-	if (netif_carrier_ok(netdev)) {
-		u32 value;
-		/* disable rx */
-		value = ATL2_READ_REG(hw, REG_MAC_CTRL);
-		value &= ~MAC_CTRL_RX_EN;
-		ATL2_WRITE_REG(hw, REG_MAC_CTRL, value);
-
-		adapter->link_speed = SPEED_0;
-		netif_carrier_off(netdev);
-		netif_stop_queue(netdev);
-	}
-
-	/* auto-neg, insert timer to re-config phy
-	 * (if interval smaller than 5 seconds, something strange) */
-	if (!test_bit(__ATL2_DOWN, &adapter->flags)) {
-		if (!test_and_set_bit(0, &adapter->cfg_phy))
-			mod_timer(&adapter->phy_config_timer,
-				  round_jiffies(jiffies + 5 * HZ));
-	}
-
-	return 0;
-}
-
-/*
- * atl2_link_chg_task - deal with link change event Out of interrupt context
- * @netdev: network interface device structure
- */
-static void atl2_link_chg_task(struct work_struct *work)
-{
-	struct atl2_adapter *adapter;
-	unsigned long flags;
-
-	adapter = container_of(work, struct atl2_adapter, link_chg_task);
-
-	spin_lock_irqsave(&adapter->stats_lock, flags);
-	atl2_check_link(adapter);
-	spin_unlock_irqrestore(&adapter->stats_lock, flags);
-}
-
-static void atl2_setup_pcicmd(struct pci_dev *pdev)
-{
-	u16 cmd;
-
-	pci_read_config_word(pdev, PCI_COMMAND, &cmd);
-
-	if (cmd & PCI_COMMAND_INTX_DISABLE)
-		cmd &= ~PCI_COMMAND_INTX_DISABLE;
-	if (cmd & PCI_COMMAND_IO)
-		cmd &= ~PCI_COMMAND_IO;
-	if (0 == (cmd & PCI_COMMAND_MEMORY))
-		cmd |= PCI_COMMAND_MEMORY;
-	if (0 == (cmd & PCI_COMMAND_MASTER))
-		cmd |= PCI_COMMAND_MASTER;
-	pci_write_config_word(pdev, PCI_COMMAND, cmd);
-
-	/*
-	 * some motherboards BIOS(PXE/EFI) driver may set PME
-	 * while they transfer control to OS (Windows/Linux)
-	 * so we should clear this bit before NIC work normally
-	 */
-	pci_write_config_dword(pdev, REG_PM_CTRLSTAT, 0);
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void atl2_poll_controller(struct net_device *netdev)
-{
-	disable_irq(netdev->irq);
-	atl2_intr(netdev->irq, netdev);
-	enable_irq(netdev->irq);
-}
-#endif
-
-
-static const struct net_device_ops atl2_netdev_ops = {
-	.ndo_open		= atl2_open,
-	.ndo_stop		= atl2_close,
-	.ndo_start_xmit		= atl2_xmit_frame,
-	.ndo_set_multicast_list	= atl2_set_multi,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address	= atl2_set_mac,
-	.ndo_change_mtu		= atl2_change_mtu,
-	.ndo_fix_features	= atl2_fix_features,
-	.ndo_set_features	= atl2_set_features,
-	.ndo_do_ioctl		= atl2_ioctl,
-	.ndo_tx_timeout		= atl2_tx_timeout,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= atl2_poll_controller,
-#endif
-};
-
-/*
- * atl2_probe - Device Initialization Routine
- * @pdev: PCI device information struct
- * @ent: entry in atl2_pci_tbl
- *
- * Returns 0 on success, negative on failure
- *
- * atl2_probe initializes an adapter identified by a pci_dev structure.
- * The OS initialization, configuring of the adapter private structure,
- * and a hardware reset occur.
- */
-static int __devinit atl2_probe(struct pci_dev *pdev,
-	const struct pci_device_id *ent)
-{
-	struct net_device *netdev;
-	struct atl2_adapter *adapter;
-	static int cards_found;
-	unsigned long mmio_start;
-	int mmio_len;
-	int err;
-
-	cards_found = 0;
-
-	err = pci_enable_device(pdev);
-	if (err)
-		return err;
-
-	/*
-	 * atl2 is a shared-high-32-bit device, so we're stuck with 32-bit DMA
-	 * until the kernel has the proper infrastructure to support 64-bit DMA
-	 * on these devices.
-	 */
-	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) &&
-		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
-		printk(KERN_ERR "atl2: No usable DMA configuration, aborting\n");
-		goto err_dma;
-	}
-
-	/* Mark all PCI regions associated with PCI device
-	 * pdev as being reserved by owner atl2_driver_name */
-	err = pci_request_regions(pdev, atl2_driver_name);
-	if (err)
-		goto err_pci_reg;
-
-	/* Enables bus-mastering on the device and calls
-	 * pcibios_set_master to do the needed arch specific settings */
-	pci_set_master(pdev);
-
-	err = -ENOMEM;
-	netdev = alloc_etherdev(sizeof(struct atl2_adapter));
-	if (!netdev)
-		goto err_alloc_etherdev;
-
-	SET_NETDEV_DEV(netdev, &pdev->dev);
-
-	pci_set_drvdata(pdev, netdev);
-	adapter = netdev_priv(netdev);
-	adapter->netdev = netdev;
-	adapter->pdev = pdev;
-	adapter->hw.back = adapter;
-
-	mmio_start = pci_resource_start(pdev, 0x0);
-	mmio_len = pci_resource_len(pdev, 0x0);
-
-	adapter->hw.mem_rang = (u32)mmio_len;
-	adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
-	if (!adapter->hw.hw_addr) {
-		err = -EIO;
-		goto err_ioremap;
-	}
-
-	atl2_setup_pcicmd(pdev);
-
-	netdev->netdev_ops = &atl2_netdev_ops;
-	atl2_set_ethtool_ops(netdev);
-	netdev->watchdog_timeo = 5 * HZ;
-	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
-
-	netdev->mem_start = mmio_start;
-	netdev->mem_end = mmio_start + mmio_len;
-	adapter->bd_number = cards_found;
-	adapter->pci_using_64 = false;
-
-	/* setup the private structure */
-	err = atl2_sw_init(adapter);
-	if (err)
-		goto err_sw_init;
-
-	err = -EIO;
-
-	netdev->hw_features = NETIF_F_SG | NETIF_F_HW_VLAN_RX;
-	netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
-
-	/* Init PHY as early as possible due to power saving issue  */
-	atl2_phy_init(&adapter->hw);
-
-	/* reset the controller to
-	 * put the device in a known good starting state */
-
-	if (atl2_reset_hw(&adapter->hw)) {
-		err = -EIO;
-		goto err_reset;
-	}
-
-	/* copy the MAC address out of the EEPROM */
-	atl2_read_mac_addr(&adapter->hw);
-	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
-/* FIXME: do we still need this? */
-#ifdef ETHTOOL_GPERMADDR
-	memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
-
-	if (!is_valid_ether_addr(netdev->perm_addr)) {
-#else
-	if (!is_valid_ether_addr(netdev->dev_addr)) {
-#endif
-		err = -EIO;
-		goto err_eeprom;
-	}
-
-	atl2_check_options(adapter);
-
-	init_timer(&adapter->watchdog_timer);
-	adapter->watchdog_timer.function = atl2_watchdog;
-	adapter->watchdog_timer.data = (unsigned long) adapter;
-
-	init_timer(&adapter->phy_config_timer);
-	adapter->phy_config_timer.function = atl2_phy_config;
-	adapter->phy_config_timer.data = (unsigned long) adapter;
-
-	INIT_WORK(&adapter->reset_task, atl2_reset_task);
-	INIT_WORK(&adapter->link_chg_task, atl2_link_chg_task);
-
-	strcpy(netdev->name, "eth%d"); /* ?? */
-	err = register_netdev(netdev);
-	if (err)
-		goto err_register;
-
-	/* assume we have no link for now */
-	netif_carrier_off(netdev);
-	netif_stop_queue(netdev);
-
-	cards_found++;
-
-	return 0;
-
-err_reset:
-err_register:
-err_sw_init:
-err_eeprom:
-	iounmap(adapter->hw.hw_addr);
-err_ioremap:
-	free_netdev(netdev);
-err_alloc_etherdev:
-	pci_release_regions(pdev);
-err_pci_reg:
-err_dma:
-	pci_disable_device(pdev);
-	return err;
-}
-
-/*
- * atl2_remove - Device Removal Routine
- * @pdev: PCI device information struct
- *
- * atl2_remove is called by the PCI subsystem to alert the driver
- * that it should release a PCI device.  The could be caused by a
- * Hot-Plug event, or because the driver is going to be removed from
- * memory.
- */
-/* FIXME: write the original MAC address back in case it was changed from a
- * BIOS-set value, as in atl1 -- CHS */
-static void __devexit atl2_remove(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-
-	/* flush_scheduled work may reschedule our watchdog task, so
-	 * explicitly disable watchdog tasks from being rescheduled  */
-	set_bit(__ATL2_DOWN, &adapter->flags);
-
-	del_timer_sync(&adapter->watchdog_timer);
-	del_timer_sync(&adapter->phy_config_timer);
-	cancel_work_sync(&adapter->reset_task);
-	cancel_work_sync(&adapter->link_chg_task);
-
-	unregister_netdev(netdev);
-
-	atl2_force_ps(&adapter->hw);
-
-	iounmap(adapter->hw.hw_addr);
-	pci_release_regions(pdev);
-
-	free_netdev(netdev);
-
-	pci_disable_device(pdev);
-}
-
-static int atl2_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-	struct atl2_hw *hw = &adapter->hw;
-	u16 speed, duplex;
-	u32 ctrl = 0;
-	u32 wufc = adapter->wol;
-
-#ifdef CONFIG_PM
-	int retval = 0;
-#endif
-
-	netif_device_detach(netdev);
-
-	if (netif_running(netdev)) {
-		WARN_ON(test_bit(__ATL2_RESETTING, &adapter->flags));
-		atl2_down(adapter);
-	}
-
-#ifdef CONFIG_PM
-	retval = pci_save_state(pdev);
-	if (retval)
-		return retval;
-#endif
-
-	atl2_read_phy_reg(hw, MII_BMSR, (u16 *)&ctrl);
-	atl2_read_phy_reg(hw, MII_BMSR, (u16 *)&ctrl);
-	if (ctrl & BMSR_LSTATUS)
-		wufc &= ~ATLX_WUFC_LNKC;
-
-	if (0 != (ctrl & BMSR_LSTATUS) && 0 != wufc) {
-		u32 ret_val;
-		/* get current link speed & duplex */
-		ret_val = atl2_get_speed_and_duplex(hw, &speed, &duplex);
-		if (ret_val) {
-			printk(KERN_DEBUG
-				"%s: get speed&duplex error while suspend\n",
-				atl2_driver_name);
-			goto wol_dis;
-		}
-
-		ctrl = 0;
-
-		/* turn on magic packet wol */
-		if (wufc & ATLX_WUFC_MAG)
-			ctrl |= (WOL_MAGIC_EN | WOL_MAGIC_PME_EN);
-
-		/* ignore Link Chg event when Link is up */
-		ATL2_WRITE_REG(hw, REG_WOL_CTRL, ctrl);
-
-		/* Config MAC CTRL Register */
-		ctrl = MAC_CTRL_RX_EN | MAC_CTRL_MACLP_CLK_PHY;
-		if (FULL_DUPLEX == adapter->link_duplex)
-			ctrl |= MAC_CTRL_DUPLX;
-		ctrl |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
-		ctrl |= (((u32)adapter->hw.preamble_len &
-			MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
-		ctrl |= (((u32)(adapter->hw.retry_buf &
-			MAC_CTRL_HALF_LEFT_BUF_MASK)) <<
-			MAC_CTRL_HALF_LEFT_BUF_SHIFT);
-		if (wufc & ATLX_WUFC_MAG) {
-			/* magic packet maybe Broadcast&multicast&Unicast */
-			ctrl |= MAC_CTRL_BC_EN;
-		}
-
-		ATL2_WRITE_REG(hw, REG_MAC_CTRL, ctrl);
-
-		/* pcie patch */
-		ctrl = ATL2_READ_REG(hw, REG_PCIE_PHYMISC);
-		ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
-		ATL2_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
-		ctrl = ATL2_READ_REG(hw, REG_PCIE_DLL_TX_CTRL1);
-		ctrl |= PCIE_DLL_TX_CTRL1_SEL_NOR_CLK;
-		ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, ctrl);
-
-		pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
-		goto suspend_exit;
-	}
-
-	if (0 == (ctrl&BMSR_LSTATUS) && 0 != (wufc&ATLX_WUFC_LNKC)) {
-		/* link is down, so only LINK CHG WOL event enable */
-		ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
-		ATL2_WRITE_REG(hw, REG_WOL_CTRL, ctrl);
-		ATL2_WRITE_REG(hw, REG_MAC_CTRL, 0);
-
-		/* pcie patch */
-		ctrl = ATL2_READ_REG(hw, REG_PCIE_PHYMISC);
-		ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
-		ATL2_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
-		ctrl = ATL2_READ_REG(hw, REG_PCIE_DLL_TX_CTRL1);
-		ctrl |= PCIE_DLL_TX_CTRL1_SEL_NOR_CLK;
-		ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, ctrl);
-
-		hw->phy_configured = false; /* re-init PHY when resume */
-
-		pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
-
-		goto suspend_exit;
-	}
-
-wol_dis:
-	/* WOL disabled */
-	ATL2_WRITE_REG(hw, REG_WOL_CTRL, 0);
-
-	/* pcie patch */
-	ctrl = ATL2_READ_REG(hw, REG_PCIE_PHYMISC);
-	ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
-	ATL2_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
-	ctrl = ATL2_READ_REG(hw, REG_PCIE_DLL_TX_CTRL1);
-	ctrl |= PCIE_DLL_TX_CTRL1_SEL_NOR_CLK;
-	ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, ctrl);
-
-	atl2_force_ps(hw);
-	hw->phy_configured = false; /* re-init PHY when resume */
-
-	pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
-
-suspend_exit:
-	if (netif_running(netdev))
-		atl2_free_irq(adapter);
-
-	pci_disable_device(pdev);
-
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int atl2_resume(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct atl2_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) {
-		printk(KERN_ERR
-			"atl2: Cannot enable PCI device from suspend\n");
-		return err;
-	}
-
-	pci_set_master(pdev);
-
-	ATL2_READ_REG(&adapter->hw, REG_WOL_CTRL); /* clear WOL status */
-
-	pci_enable_wake(pdev, PCI_D3hot, 0);
-	pci_enable_wake(pdev, PCI_D3cold, 0);
-
-	ATL2_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
-
-	if (netif_running(netdev)) {
-		err = atl2_request_irq(adapter);
-		if (err)
-			return err;
-	}
-
-	atl2_reset_hw(&adapter->hw);
-
-	if (netif_running(netdev))
-		atl2_up(adapter);
-
-	netif_device_attach(netdev);
-
-	return 0;
-}
-#endif
-
-static void atl2_shutdown(struct pci_dev *pdev)
-{
-	atl2_suspend(pdev, PMSG_SUSPEND);
-}
-
-static struct pci_driver atl2_driver = {
-	.name     = atl2_driver_name,
-	.id_table = atl2_pci_tbl,
-	.probe    = atl2_probe,
-	.remove   = __devexit_p(atl2_remove),
-	/* Power Management Hooks */
-	.suspend  = atl2_suspend,
-#ifdef CONFIG_PM
-	.resume   = atl2_resume,
-#endif
-	.shutdown = atl2_shutdown,
-};
-
-/*
- * atl2_init_module - Driver Registration Routine
- *
- * atl2_init_module is the first routine called when the driver is
- * loaded. All it does is register with the PCI subsystem.
- */
-static int __init atl2_init_module(void)
-{
-	printk(KERN_INFO "%s - version %s\n", atl2_driver_string,
-		atl2_driver_version);
-	printk(KERN_INFO "%s\n", atl2_copyright);
-	return pci_register_driver(&atl2_driver);
-}
-module_init(atl2_init_module);
-
-/*
- * atl2_exit_module - Driver Exit Cleanup Routine
- *
- * atl2_exit_module is called just before the driver is removed
- * from memory.
- */
-static void __exit atl2_exit_module(void)
-{
-	pci_unregister_driver(&atl2_driver);
-}
-module_exit(atl2_exit_module);
-
-static void atl2_read_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value)
-{
-	struct atl2_adapter *adapter = hw->back;
-	pci_read_config_word(adapter->pdev, reg, value);
-}
-
-static void atl2_write_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value)
-{
-	struct atl2_adapter *adapter = hw->back;
-	pci_write_config_word(adapter->pdev, reg, *value);
-}
-
-static int atl2_get_settings(struct net_device *netdev,
-	struct ethtool_cmd *ecmd)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-	struct atl2_hw *hw = &adapter->hw;
-
-	ecmd->supported = (SUPPORTED_10baseT_Half |
-		SUPPORTED_10baseT_Full |
-		SUPPORTED_100baseT_Half |
-		SUPPORTED_100baseT_Full |
-		SUPPORTED_Autoneg |
-		SUPPORTED_TP);
-	ecmd->advertising = ADVERTISED_TP;
-
-	ecmd->advertising |= ADVERTISED_Autoneg;
-	ecmd->advertising |= hw->autoneg_advertised;
-
-	ecmd->port = PORT_TP;
-	ecmd->phy_address = 0;
-	ecmd->transceiver = XCVR_INTERNAL;
-
-	if (adapter->link_speed != SPEED_0) {
-		ethtool_cmd_speed_set(ecmd, adapter->link_speed);
-		if (adapter->link_duplex == FULL_DUPLEX)
-			ecmd->duplex = DUPLEX_FULL;
-		else
-			ecmd->duplex = DUPLEX_HALF;
-	} else {
-		ethtool_cmd_speed_set(ecmd, -1);
-		ecmd->duplex = -1;
-	}
-
-	ecmd->autoneg = AUTONEG_ENABLE;
-	return 0;
-}
-
-static int atl2_set_settings(struct net_device *netdev,
-	struct ethtool_cmd *ecmd)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-	struct atl2_hw *hw = &adapter->hw;
-
-	while (test_and_set_bit(__ATL2_RESETTING, &adapter->flags))
-		msleep(1);
-
-	if (ecmd->autoneg == AUTONEG_ENABLE) {
-#define MY_ADV_MASK	(ADVERTISE_10_HALF | \
-			 ADVERTISE_10_FULL | \
-			 ADVERTISE_100_HALF| \
-			 ADVERTISE_100_FULL)
-
-		if ((ecmd->advertising & MY_ADV_MASK) == MY_ADV_MASK) {
-			hw->MediaType = MEDIA_TYPE_AUTO_SENSOR;
-			hw->autoneg_advertised =  MY_ADV_MASK;
-		} else if ((ecmd->advertising & MY_ADV_MASK) ==
-				ADVERTISE_100_FULL) {
-			hw->MediaType = MEDIA_TYPE_100M_FULL;
-			hw->autoneg_advertised = ADVERTISE_100_FULL;
-		} else if ((ecmd->advertising & MY_ADV_MASK) ==
-				ADVERTISE_100_HALF) {
-			hw->MediaType = MEDIA_TYPE_100M_HALF;
-			hw->autoneg_advertised = ADVERTISE_100_HALF;
-		} else if ((ecmd->advertising & MY_ADV_MASK) ==
-				ADVERTISE_10_FULL) {
-			hw->MediaType = MEDIA_TYPE_10M_FULL;
-			hw->autoneg_advertised = ADVERTISE_10_FULL;
-		}  else if ((ecmd->advertising & MY_ADV_MASK) ==
-				ADVERTISE_10_HALF) {
-			hw->MediaType = MEDIA_TYPE_10M_HALF;
-			hw->autoneg_advertised = ADVERTISE_10_HALF;
-		} else {
-			clear_bit(__ATL2_RESETTING, &adapter->flags);
-			return -EINVAL;
-		}
-		ecmd->advertising = hw->autoneg_advertised |
-			ADVERTISED_TP | ADVERTISED_Autoneg;
-	} else {
-		clear_bit(__ATL2_RESETTING, &adapter->flags);
-		return -EINVAL;
-	}
-
-	/* reset the link */
-	if (netif_running(adapter->netdev)) {
-		atl2_down(adapter);
-		atl2_up(adapter);
-	} else
-		atl2_reset_hw(&adapter->hw);
-
-	clear_bit(__ATL2_RESETTING, &adapter->flags);
-	return 0;
-}
-
-static u32 atl2_get_msglevel(struct net_device *netdev)
-{
-	return 0;
-}
-
-/*
- * It's sane for this to be empty, but we might want to take advantage of this.
- */
-static void atl2_set_msglevel(struct net_device *netdev, u32 data)
-{
-}
-
-static int atl2_get_regs_len(struct net_device *netdev)
-{
-#define ATL2_REGS_LEN 42
-	return sizeof(u32) * ATL2_REGS_LEN;
-}
-
-static void atl2_get_regs(struct net_device *netdev,
-	struct ethtool_regs *regs, void *p)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-	struct atl2_hw *hw = &adapter->hw;
-	u32 *regs_buff = p;
-	u16 phy_data;
-
-	memset(p, 0, sizeof(u32) * ATL2_REGS_LEN);
-
-	regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
-
-	regs_buff[0]  = ATL2_READ_REG(hw, REG_VPD_CAP);
-	regs_buff[1]  = ATL2_READ_REG(hw, REG_SPI_FLASH_CTRL);
-	regs_buff[2]  = ATL2_READ_REG(hw, REG_SPI_FLASH_CONFIG);
-	regs_buff[3]  = ATL2_READ_REG(hw, REG_TWSI_CTRL);
-	regs_buff[4]  = ATL2_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL);
-	regs_buff[5]  = ATL2_READ_REG(hw, REG_MASTER_CTRL);
-	regs_buff[6]  = ATL2_READ_REG(hw, REG_MANUAL_TIMER_INIT);
-	regs_buff[7]  = ATL2_READ_REG(hw, REG_IRQ_MODU_TIMER_INIT);
-	regs_buff[8]  = ATL2_READ_REG(hw, REG_PHY_ENABLE);
-	regs_buff[9]  = ATL2_READ_REG(hw, REG_CMBDISDMA_TIMER);
-	regs_buff[10] = ATL2_READ_REG(hw, REG_IDLE_STATUS);
-	regs_buff[11] = ATL2_READ_REG(hw, REG_MDIO_CTRL);
-	regs_buff[12] = ATL2_READ_REG(hw, REG_SERDES_LOCK);
-	regs_buff[13] = ATL2_READ_REG(hw, REG_MAC_CTRL);
-	regs_buff[14] = ATL2_READ_REG(hw, REG_MAC_IPG_IFG);
-	regs_buff[15] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR);
-	regs_buff[16] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR+4);
-	regs_buff[17] = ATL2_READ_REG(hw, REG_RX_HASH_TABLE);
-	regs_buff[18] = ATL2_READ_REG(hw, REG_RX_HASH_TABLE+4);
-	regs_buff[19] = ATL2_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL);
-	regs_buff[20] = ATL2_READ_REG(hw, REG_MTU);
-	regs_buff[21] = ATL2_READ_REG(hw, REG_WOL_CTRL);
-	regs_buff[22] = ATL2_READ_REG(hw, REG_SRAM_TXRAM_END);
-	regs_buff[23] = ATL2_READ_REG(hw, REG_DESC_BASE_ADDR_HI);
-	regs_buff[24] = ATL2_READ_REG(hw, REG_TXD_BASE_ADDR_LO);
-	regs_buff[25] = ATL2_READ_REG(hw, REG_TXD_MEM_SIZE);
-	regs_buff[26] = ATL2_READ_REG(hw, REG_TXS_BASE_ADDR_LO);
-	regs_buff[27] = ATL2_READ_REG(hw, REG_TXS_MEM_SIZE);
-	regs_buff[28] = ATL2_READ_REG(hw, REG_RXD_BASE_ADDR_LO);
-	regs_buff[29] = ATL2_READ_REG(hw, REG_RXD_BUF_NUM);
-	regs_buff[30] = ATL2_READ_REG(hw, REG_DMAR);
-	regs_buff[31] = ATL2_READ_REG(hw, REG_TX_CUT_THRESH);
-	regs_buff[32] = ATL2_READ_REG(hw, REG_DMAW);
-	regs_buff[33] = ATL2_READ_REG(hw, REG_PAUSE_ON_TH);
-	regs_buff[34] = ATL2_READ_REG(hw, REG_PAUSE_OFF_TH);
-	regs_buff[35] = ATL2_READ_REG(hw, REG_MB_TXD_WR_IDX);
-	regs_buff[36] = ATL2_READ_REG(hw, REG_MB_RXD_RD_IDX);
-	regs_buff[38] = ATL2_READ_REG(hw, REG_ISR);
-	regs_buff[39] = ATL2_READ_REG(hw, REG_IMR);
-
-	atl2_read_phy_reg(hw, MII_BMCR, &phy_data);
-	regs_buff[40] = (u32)phy_data;
-	atl2_read_phy_reg(hw, MII_BMSR, &phy_data);
-	regs_buff[41] = (u32)phy_data;
-}
-
-static int atl2_get_eeprom_len(struct net_device *netdev)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-
-	if (!atl2_check_eeprom_exist(&adapter->hw))
-		return 512;
-	else
-		return 0;
-}
-
-static int atl2_get_eeprom(struct net_device *netdev,
-	struct ethtool_eeprom *eeprom, u8 *bytes)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-	struct atl2_hw *hw = &adapter->hw;
-	u32 *eeprom_buff;
-	int first_dword, last_dword;
-	int ret_val = 0;
-	int i;
-
-	if (eeprom->len == 0)
-		return -EINVAL;
-
-	if (atl2_check_eeprom_exist(hw))
-		return -EINVAL;
-
-	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
-
-	first_dword = eeprom->offset >> 2;
-	last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
-
-	eeprom_buff = kmalloc(sizeof(u32) * (last_dword - first_dword + 1),
-		GFP_KERNEL);
-	if (!eeprom_buff)
-		return -ENOMEM;
-
-	for (i = first_dword; i < last_dword; i++) {
-		if (!atl2_read_eeprom(hw, i*4, &(eeprom_buff[i-first_dword]))) {
-			ret_val = -EIO;
-			goto free;
-		}
-	}
-
-	memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3),
-		eeprom->len);
-free:
-	kfree(eeprom_buff);
-
-	return ret_val;
-}
-
-static int atl2_set_eeprom(struct net_device *netdev,
-	struct ethtool_eeprom *eeprom, u8 *bytes)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-	struct atl2_hw *hw = &adapter->hw;
-	u32 *eeprom_buff;
-	u32 *ptr;
-	int max_len, first_dword, last_dword, ret_val = 0;
-	int i;
-
-	if (eeprom->len == 0)
-		return -EOPNOTSUPP;
-
-	if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
-		return -EFAULT;
-
-	max_len = 512;
-
-	first_dword = eeprom->offset >> 2;
-	last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
-	eeprom_buff = kmalloc(max_len, GFP_KERNEL);
-	if (!eeprom_buff)
-		return -ENOMEM;
-
-	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]))) {
-			ret_val = -EIO;
-			goto out;
-		}
-		ptr++;
-	}
-	if (((eeprom->offset + eeprom->len) & 3)) {
-		/*
-		 * need read/modify/write of last changed EEPROM word
-		 * only the first byte of the word is being modified
-		 */
-		if (!atl2_read_eeprom(hw, last_dword * 4,
-					&(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])) {
-			ret_val = -EIO;
-			goto out;
-		}
-	}
- out:
-	kfree(eeprom_buff);
-	return ret_val;
-}
-
-static void atl2_get_drvinfo(struct net_device *netdev,
-	struct ethtool_drvinfo *drvinfo)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-
-	strncpy(drvinfo->driver,  atl2_driver_name, 32);
-	strncpy(drvinfo->version, atl2_driver_version, 32);
-	strncpy(drvinfo->fw_version, "L2", 32);
-	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
-	drvinfo->n_stats = 0;
-	drvinfo->testinfo_len = 0;
-	drvinfo->regdump_len = atl2_get_regs_len(netdev);
-	drvinfo->eedump_len = atl2_get_eeprom_len(netdev);
-}
-
-static void atl2_get_wol(struct net_device *netdev,
-	struct ethtool_wolinfo *wol)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-
-	wol->supported = WAKE_MAGIC;
-	wol->wolopts = 0;
-
-	if (adapter->wol & ATLX_WUFC_EX)
-		wol->wolopts |= WAKE_UCAST;
-	if (adapter->wol & ATLX_WUFC_MC)
-		wol->wolopts |= WAKE_MCAST;
-	if (adapter->wol & ATLX_WUFC_BC)
-		wol->wolopts |= WAKE_BCAST;
-	if (adapter->wol & ATLX_WUFC_MAG)
-		wol->wolopts |= WAKE_MAGIC;
-	if (adapter->wol & ATLX_WUFC_LNKC)
-		wol->wolopts |= WAKE_PHY;
-}
-
-static int atl2_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-
-	if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE))
-		return -EOPNOTSUPP;
-
-	if (wol->wolopts & (WAKE_UCAST | WAKE_BCAST | WAKE_MCAST))
-		return -EOPNOTSUPP;
-
-	/* these settings will always override what we currently have */
-	adapter->wol = 0;
-
-	if (wol->wolopts & WAKE_MAGIC)
-		adapter->wol |= ATLX_WUFC_MAG;
-	if (wol->wolopts & WAKE_PHY)
-		adapter->wol |= ATLX_WUFC_LNKC;
-
-	return 0;
-}
-
-static int atl2_nway_reset(struct net_device *netdev)
-{
-	struct atl2_adapter *adapter = netdev_priv(netdev);
-	if (netif_running(netdev))
-		atl2_reinit_locked(adapter);
-	return 0;
-}
-
-static const struct ethtool_ops atl2_ethtool_ops = {
-	.get_settings		= atl2_get_settings,
-	.set_settings		= atl2_set_settings,
-	.get_drvinfo		= atl2_get_drvinfo,
-	.get_regs_len		= atl2_get_regs_len,
-	.get_regs		= atl2_get_regs,
-	.get_wol		= atl2_get_wol,
-	.set_wol		= atl2_set_wol,
-	.get_msglevel		= atl2_get_msglevel,
-	.set_msglevel		= atl2_set_msglevel,
-	.nway_reset		= atl2_nway_reset,
-	.get_link		= ethtool_op_get_link,
-	.get_eeprom_len		= atl2_get_eeprom_len,
-	.get_eeprom		= atl2_get_eeprom,
-	.set_eeprom		= atl2_set_eeprom,
-};
-
-static void atl2_set_ethtool_ops(struct net_device *netdev)
-{
-	SET_ETHTOOL_OPS(netdev, &atl2_ethtool_ops);
-}
-
-#define LBYTESWAP(a)  ((((a) & 0x00ff00ff) << 8) | \
-	(((a) & 0xff00ff00) >> 8))
-#define LONGSWAP(a)   ((LBYTESWAP(a) << 16) | (LBYTESWAP(a) >> 16))
-#define SHORTSWAP(a)  (((a) << 8) | ((a) >> 8))
-
-/*
- * Reset the transmit and receive units; mask and clear all interrupts.
- *
- * hw - Struct containing variables accessed by shared code
- * return : 0  or  idle status (if error)
- */
-static s32 atl2_reset_hw(struct atl2_hw *hw)
-{
-	u32 icr;
-	u16 pci_cfg_cmd_word;
-	int i;
-
-	/* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */
-	atl2_read_pci_cfg(hw, PCI_REG_COMMAND, &pci_cfg_cmd_word);
-	if ((pci_cfg_cmd_word &
-		(CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER)) !=
-		(CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER)) {
-		pci_cfg_cmd_word |=
-			(CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER);
-		atl2_write_pci_cfg(hw, PCI_REG_COMMAND, &pci_cfg_cmd_word);
-	}
-
-	/* Clear Interrupt mask to stop board from generating
-	 * interrupts & Clear any pending interrupt events
-	 */
-	/* FIXME */
-	/* ATL2_WRITE_REG(hw, REG_IMR, 0); */
-	/* ATL2_WRITE_REG(hw, REG_ISR, 0xffffffff); */
-
-	/* Issue Soft Reset to the MAC.  This will reset the chip's
-	 * transmit, receive, DMA.  It will not effect
-	 * the current PCI configuration.  The global reset bit is self-
-	 * clearing, and should clear within a microsecond.
-	 */
-	ATL2_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_SOFT_RST);
-	wmb();
-	msleep(1); /* delay about 1ms */
-
-	/* Wait at least 10ms for All module to be Idle */
-	for (i = 0; i < 10; i++) {
-		icr = ATL2_READ_REG(hw, REG_IDLE_STATUS);
-		if (!icr)
-			break;
-		msleep(1); /* delay 1 ms */
-		cpu_relax();
-	}
-
-	if (icr)
-		return icr;
-
-	return 0;
-}
-
-#define CUSTOM_SPI_CS_SETUP        2
-#define CUSTOM_SPI_CLK_HI          2
-#define CUSTOM_SPI_CLK_LO          2
-#define CUSTOM_SPI_CS_HOLD         2
-#define CUSTOM_SPI_CS_HI           3
-
-static struct atl2_spi_flash_dev flash_table[] =
-{
-/* MFR    WRSR  READ  PROGRAM WREN  WRDI  RDSR  RDID  SECTOR_ERASE CHIP_ERASE */
-{"Atmel", 0x0,  0x03, 0x02,   0x06, 0x04, 0x05, 0x15, 0x52,        0x62 },
-{"SST",   0x01, 0x03, 0x02,   0x06, 0x04, 0x05, 0x90, 0x20,        0x60 },
-{"ST",    0x01, 0x03, 0x02,   0x06, 0x04, 0x05, 0xAB, 0xD8,        0xC7 },
-};
-
-static bool atl2_spi_read(struct atl2_hw *hw, u32 addr, u32 *buf)
-{
-	int i;
-	u32 value;
-
-	ATL2_WRITE_REG(hw, REG_SPI_DATA, 0);
-	ATL2_WRITE_REG(hw, REG_SPI_ADDR, addr);
-
-	value = SPI_FLASH_CTRL_WAIT_READY |
-		(CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) <<
-			SPI_FLASH_CTRL_CS_SETUP_SHIFT |
-		(CUSTOM_SPI_CLK_HI & SPI_FLASH_CTRL_CLK_HI_MASK) <<
-			SPI_FLASH_CTRL_CLK_HI_SHIFT |
-		(CUSTOM_SPI_CLK_LO & SPI_FLASH_CTRL_CLK_LO_MASK) <<
-			SPI_FLASH_CTRL_CLK_LO_SHIFT |
-		(CUSTOM_SPI_CS_HOLD & SPI_FLASH_CTRL_CS_HOLD_MASK) <<
-			SPI_FLASH_CTRL_CS_HOLD_SHIFT |
-		(CUSTOM_SPI_CS_HI & SPI_FLASH_CTRL_CS_HI_MASK) <<
-			SPI_FLASH_CTRL_CS_HI_SHIFT |
-		(0x1 & SPI_FLASH_CTRL_INS_MASK) << SPI_FLASH_CTRL_INS_SHIFT;
-
-	ATL2_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);
-
-	value |= SPI_FLASH_CTRL_START;
-
-	ATL2_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);
-
-	for (i = 0; i < 10; i++) {
-		msleep(1);
-		value = ATL2_READ_REG(hw, REG_SPI_FLASH_CTRL);
-		if (!(value & SPI_FLASH_CTRL_START))
-			break;
-	}
-
-	if (value & SPI_FLASH_CTRL_START)
-		return false;
-
-	*buf = ATL2_READ_REG(hw, REG_SPI_DATA);
-
-	return true;
-}
-
-/*
- * get_permanent_address
- * return 0 if get valid mac address,
- */
-static int get_permanent_address(struct atl2_hw *hw)
-{
-	u32 Addr[2];
-	u32 i, Control;
-	u16 Register;
-	u8  EthAddr[NODE_ADDRESS_SIZE];
-	bool KeyValid;
-
-	if (is_valid_ether_addr(hw->perm_mac_addr))
-		return 0;
-
-	Addr[0] = 0;
-	Addr[1] = 0;
-
-	if (!atl2_check_eeprom_exist(hw)) { /* eeprom exists */
-		Register = 0;
-		KeyValid = false;
-
-		/* Read out all EEPROM content */
-		i = 0;
-		while (1) {
-			if (atl2_read_eeprom(hw, i + 0x100, &Control)) {
-				if (KeyValid) {
-					if (Register == REG_MAC_STA_ADDR)
-						Addr[0] = Control;
-					else if (Register ==
-						(REG_MAC_STA_ADDR + 4))
-						Addr[1] = Control;
-					KeyValid = false;
-				} else if ((Control & 0xff) == 0x5A) {
-					KeyValid = true;
-					Register = (u16) (Control >> 16);
-				} else {
-			/* assume data end while encount an invalid KEYWORD */
-					break;
-				}
-			} else {
-				break; /* read error */
-			}
-			i += 4;
-		}
-
-		*(u32 *) &EthAddr[2] = LONGSWAP(Addr[0]);
-		*(u16 *) &EthAddr[0] = SHORTSWAP(*(u16 *) &Addr[1]);
-
-		if (is_valid_ether_addr(EthAddr)) {
-			memcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE);
-			return 0;
-		}
-		return 1;
-	}
-
-	/* see if SPI flash exists? */
-	Addr[0] = 0;
-	Addr[1] = 0;
-	Register = 0;
-	KeyValid = false;
-	i = 0;
-	while (1) {
-		if (atl2_spi_read(hw, i + 0x1f000, &Control)) {
-			if (KeyValid) {
-				if (Register == REG_MAC_STA_ADDR)
-					Addr[0] = Control;
-				else if (Register == (REG_MAC_STA_ADDR + 4))
-					Addr[1] = Control;
-				KeyValid = false;
-			} else if ((Control & 0xff) == 0x5A) {
-				KeyValid = true;
-				Register = (u16) (Control >> 16);
-			} else {
-				break; /* data end */
-			}
-		} else {
-			break; /* read error */
-		}
-		i += 4;
-	}
-
-	*(u32 *) &EthAddr[2] = LONGSWAP(Addr[0]);
-	*(u16 *) &EthAddr[0] = SHORTSWAP(*(u16 *)&Addr[1]);
-	if (is_valid_ether_addr(EthAddr)) {
-		memcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE);
-		return 0;
-	}
-	/* maybe MAC-address is from BIOS */
-	Addr[0] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR);
-	Addr[1] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR + 4);
-	*(u32 *) &EthAddr[2] = LONGSWAP(Addr[0]);
-	*(u16 *) &EthAddr[0] = SHORTSWAP(*(u16 *) &Addr[1]);
-
-	if (is_valid_ether_addr(EthAddr)) {
-		memcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE);
-		return 0;
-	}
-
-	return 1;
-}
-
-/*
- * Reads the adapter's MAC address from the EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- */
-static s32 atl2_read_mac_addr(struct atl2_hw *hw)
-{
-	u16 i;
-
-	if (get_permanent_address(hw)) {
-		/* for test */
-		/* FIXME: shouldn't we use random_ether_addr() here? */
-		hw->perm_mac_addr[0] = 0x00;
-		hw->perm_mac_addr[1] = 0x13;
-		hw->perm_mac_addr[2] = 0x74;
-		hw->perm_mac_addr[3] = 0x00;
-		hw->perm_mac_addr[4] = 0x5c;
-		hw->perm_mac_addr[5] = 0x38;
-	}
-
-	for (i = 0; i < NODE_ADDRESS_SIZE; i++)
-		hw->mac_addr[i] = hw->perm_mac_addr[i];
-
-	return 0;
-}
-
-/*
- * Hashes an address to determine its location in the multicast table
- *
- * hw - Struct containing variables accessed by shared code
- * mc_addr - the multicast address to hash
- *
- * atl2_hash_mc_addr
- *  purpose
- *      set hash value for a multicast address
- *      hash calcu processing :
- *          1. calcu 32bit CRC for multicast address
- *          2. reverse crc with MSB to LSB
- */
-static u32 atl2_hash_mc_addr(struct atl2_hw *hw, u8 *mc_addr)
-{
-	u32 crc32, value;
-	int i;
-
-	value = 0;
-	crc32 = ether_crc_le(6, mc_addr);
-
-	for (i = 0; i < 32; i++)
-		value |= (((crc32 >> i) & 1) << (31 - i));
-
-	return value;
-}
-
-/*
- * Sets the bit in the multicast table corresponding to the hash value.
- *
- * hw - Struct containing variables accessed by shared code
- * hash_value - Multicast address hash value
- */
-static void atl2_hash_set(struct atl2_hw *hw, u32 hash_value)
-{
-	u32 hash_bit, hash_reg;
-	u32 mta;
-
-	/* The HASH Table  is a register array of 2 32-bit registers.
-	 * It is treated like an array of 64 bits.  We want to set
-	 * bit BitArray[hash_value]. So we figure out what register
-	 * the bit is in, read it, OR in the new bit, then write
-	 * back the new value.  The register is determined by the
-	 * upper 7 bits of the hash value and the bit within that
-	 * register are determined by the lower 5 bits of the value.
-	 */
-	hash_reg = (hash_value >> 31) & 0x1;
-	hash_bit = (hash_value >> 26) & 0x1F;
-
-	mta = ATL2_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);
-
-	mta |= (1 << hash_bit);
-
-	ATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
-}
-
-/*
- * atl2_init_pcie - init PCIE module
- */
-static void atl2_init_pcie(struct atl2_hw *hw)
-{
-    u32 value;
-    value = LTSSM_TEST_MODE_DEF;
-    ATL2_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value);
-
-    value = PCIE_DLL_TX_CTRL1_DEF;
-    ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, value);
-}
-
-static void atl2_init_flash_opcode(struct atl2_hw *hw)
-{
-	if (hw->flash_vendor >= ARRAY_SIZE(flash_table))
-		hw->flash_vendor = 0; /* ATMEL */
-
-	/* Init OP table */
-	ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_PROGRAM,
-		flash_table[hw->flash_vendor].cmdPROGRAM);
-	ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_SC_ERASE,
-		flash_table[hw->flash_vendor].cmdSECTOR_ERASE);
-	ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_CHIP_ERASE,
-		flash_table[hw->flash_vendor].cmdCHIP_ERASE);
-	ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_RDID,
-		flash_table[hw->flash_vendor].cmdRDID);
-	ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_WREN,
-		flash_table[hw->flash_vendor].cmdWREN);
-	ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_RDSR,
-		flash_table[hw->flash_vendor].cmdRDSR);
-	ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_WRSR,
-		flash_table[hw->flash_vendor].cmdWRSR);
-	ATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_READ,
-		flash_table[hw->flash_vendor].cmdREAD);
-}
-
-/********************************************************************
-* Performs basic configuration of the adapter.
-*
-* hw - Struct containing variables accessed by shared code
-* Assumes that the controller has previously been reset and is in a
-* post-reset uninitialized state. Initializes multicast table,
-* and  Calls routines to setup link
-* Leaves the transmit and receive units disabled and uninitialized.
-********************************************************************/
-static s32 atl2_init_hw(struct atl2_hw *hw)
-{
-	u32 ret_val = 0;
-
-	atl2_init_pcie(hw);
-
-	/* Zero out the Multicast HASH table */
-	/* clear the old settings from the multicast hash table */
-	ATL2_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
-	ATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
-
-	atl2_init_flash_opcode(hw);
-
-	ret_val = atl2_phy_init(hw);
-
-	return ret_val;
-}
-
-/*
- * Detects the current speed and duplex settings of the hardware.
- *
- * hw - Struct containing variables accessed by shared code
- * speed - Speed of the connection
- * duplex - Duplex setting of the connection
- */
-static s32 atl2_get_speed_and_duplex(struct atl2_hw *hw, u16 *speed,
-	u16 *duplex)
-{
-	s32 ret_val;
-	u16 phy_data;
-
-	/* Read PHY Specific Status Register (17) */
-	ret_val = atl2_read_phy_reg(hw, MII_ATLX_PSSR, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	if (!(phy_data & MII_ATLX_PSSR_SPD_DPLX_RESOLVED))
-		return ATLX_ERR_PHY_RES;
-
-	switch (phy_data & MII_ATLX_PSSR_SPEED) {
-	case MII_ATLX_PSSR_100MBS:
-		*speed = SPEED_100;
-		break;
-	case MII_ATLX_PSSR_10MBS:
-		*speed = SPEED_10;
-		break;
-	default:
-		return ATLX_ERR_PHY_SPEED;
-		break;
-	}
-
-	if (phy_data & MII_ATLX_PSSR_DPLX)
-		*duplex = FULL_DUPLEX;
-	else
-		*duplex = HALF_DUPLEX;
-
-	return 0;
-}
-
-/*
- * Reads the value from a PHY register
- * hw - Struct containing variables accessed by shared code
- * reg_addr - address of the PHY register to read
- */
-static s32 atl2_read_phy_reg(struct atl2_hw *hw, u16 reg_addr, u16 *phy_data)
-{
-	u32 val;
-	int i;
-
-	val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
-		MDIO_START |
-		MDIO_SUP_PREAMBLE |
-		MDIO_RW |
-		MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
-	ATL2_WRITE_REG(hw, REG_MDIO_CTRL, val);
-
-	wmb();
-
-	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
-		udelay(2);
-		val = ATL2_READ_REG(hw, REG_MDIO_CTRL);
-		if (!(val & (MDIO_START | MDIO_BUSY)))
-			break;
-		wmb();
-	}
-	if (!(val & (MDIO_START | MDIO_BUSY))) {
-		*phy_data = (u16)val;
-		return 0;
-	}
-
-	return ATLX_ERR_PHY;
-}
-
-/*
- * Writes a value to a PHY register
- * hw - Struct containing variables accessed by shared code
- * reg_addr - address of the PHY register to write
- * data - data to write to the PHY
- */
-static s32 atl2_write_phy_reg(struct atl2_hw *hw, u32 reg_addr, u16 phy_data)
-{
-	int i;
-	u32 val;
-
-	val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
-		(reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
-		MDIO_SUP_PREAMBLE |
-		MDIO_START |
-		MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
-	ATL2_WRITE_REG(hw, REG_MDIO_CTRL, val);
-
-	wmb();
-
-	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
-		udelay(2);
-		val = ATL2_READ_REG(hw, REG_MDIO_CTRL);
-		if (!(val & (MDIO_START | MDIO_BUSY)))
-			break;
-
-		wmb();
-	}
-
-	if (!(val & (MDIO_START | MDIO_BUSY)))
-		return 0;
-
-	return ATLX_ERR_PHY;
-}
-
-/*
- * Configures PHY autoneg and flow control advertisement settings
- *
- * hw - Struct containing variables accessed by shared code
- */
-static s32 atl2_phy_setup_autoneg_adv(struct atl2_hw *hw)
-{
-	s32 ret_val;
-	s16 mii_autoneg_adv_reg;
-
-	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
-	mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
-
-	/* Need to parse autoneg_advertised  and set up
-	 * the appropriate PHY registers.  First we will parse for
-	 * autoneg_advertised software override.  Since we can advertise
-	 * a plethora of combinations, we need to check each bit
-	 * individually.
-	 */
-
-	/* First we clear all the 10/100 mb speed bits in the Auto-Neg
-	 * 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;
-
-	/* Need to parse MediaType and setup the
-	 * appropriate PHY registers. */
-	switch (hw->MediaType) {
-	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;
-		break;
-	case MEDIA_TYPE_100M_FULL:
-		mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
-		hw->autoneg_advertised = ADVERTISE_100_FULL;
-		break;
-	case MEDIA_TYPE_100M_HALF:
-		mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
-		hw->autoneg_advertised = ADVERTISE_100_HALF;
-		break;
-	case MEDIA_TYPE_10M_FULL:
-		mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
-		hw->autoneg_advertised = ADVERTISE_10_FULL;
-		break;
-	default:
-		mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
-		hw->autoneg_advertised = ADVERTISE_10_HALF;
-		break;
-	}
-
-	/* flow control fixed to enable all */
-	mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
-
-	hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
-
-	ret_val = atl2_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
-
-	if (ret_val)
-		return ret_val;
-
-	return 0;
-}
-
-/*
- * Resets the PHY and make all config validate
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Sets bit 15 and 12 of the MII Control regiser (for F001 bug)
- */
-static s32 atl2_phy_commit(struct atl2_hw *hw)
-{
-	s32 ret_val;
-	u16 phy_data;
-
-	phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG;
-	ret_val = atl2_write_phy_reg(hw, MII_BMCR, phy_data);
-	if (ret_val) {
-		u32 val;
-		int i;
-		/* pcie serdes link may be down ! */
-		for (i = 0; i < 25; i++) {
-			msleep(1);
-			val = ATL2_READ_REG(hw, REG_MDIO_CTRL);
-			if (!(val & (MDIO_START | MDIO_BUSY)))
-				break;
-		}
-
-		if (0 != (val & (MDIO_START | MDIO_BUSY))) {
-			printk(KERN_ERR "atl2: PCIe link down for at least 25ms !\n");
-			return ret_val;
-		}
-	}
-	return 0;
-}
-
-static s32 atl2_phy_init(struct atl2_hw *hw)
-{
-	s32 ret_val;
-	u16 phy_val;
-
-	if (hw->phy_configured)
-		return 0;
-
-	/* Enable PHY */
-	ATL2_WRITE_REGW(hw, REG_PHY_ENABLE, 1);
-	ATL2_WRITE_FLUSH(hw);
-	msleep(1);
-
-	/* check if the PHY is in powersaving mode */
-	atl2_write_phy_reg(hw, MII_DBG_ADDR, 0);
-	atl2_read_phy_reg(hw, MII_DBG_DATA, &phy_val);
-
-	/* 024E / 124E 0r 0274 / 1274 ? */
-	if (phy_val & 0x1000) {
-		phy_val &= ~0x1000;
-		atl2_write_phy_reg(hw, MII_DBG_DATA, phy_val);
-	}
-
-	msleep(1);
-
-	/*Enable PHY LinkChange Interrupt */
-	ret_val = atl2_write_phy_reg(hw, 18, 0xC00);
-	if (ret_val)
-		return ret_val;
-
-	/* setup AutoNeg parameters */
-	ret_val = atl2_phy_setup_autoneg_adv(hw);
-	if (ret_val)
-		return ret_val;
-
-	/* SW.Reset & En-Auto-Neg to restart Auto-Neg */
-	ret_val = atl2_phy_commit(hw);
-	if (ret_val)
-		return ret_val;
-
-	hw->phy_configured = true;
-
-	return ret_val;
-}
-
-static void atl2_set_mac_addr(struct atl2_hw *hw)
-{
-	u32 value;
-	/* 00-0B-6A-F6-00-DC
-	 * 0:  6AF600DC   1: 000B
-	 * low dword */
-	value = (((u32)hw->mac_addr[2]) << 24) |
-		(((u32)hw->mac_addr[3]) << 16) |
-		(((u32)hw->mac_addr[4]) << 8)  |
-		(((u32)hw->mac_addr[5]));
-	ATL2_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
-	/* hight dword */
-	value = (((u32)hw->mac_addr[0]) << 8) |
-		(((u32)hw->mac_addr[1]));
-	ATL2_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
-}
-
-/*
- * check_eeprom_exist
- * return 0 if eeprom exist
- */
-static int atl2_check_eeprom_exist(struct atl2_hw *hw)
-{
-	u32 value;
-
-	value = ATL2_READ_REG(hw, REG_SPI_FLASH_CTRL);
-	if (value & SPI_FLASH_CTRL_EN_VPD) {
-		value &= ~SPI_FLASH_CTRL_EN_VPD;
-		ATL2_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);
-	}
-	value = ATL2_READ_REGW(hw, REG_PCIE_CAP_LIST);
-	return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
-}
-
-/* FIXME: This doesn't look right. -- CHS */
-static bool atl2_write_eeprom(struct atl2_hw *hw, u32 offset, u32 value)
-{
-	return true;
-}
-
-static bool atl2_read_eeprom(struct atl2_hw *hw, u32 Offset, u32 *pValue)
-{
-	int i;
-	u32    Control;
-
-	if (Offset & 0x3)
-		return false; /* address do not align */
-
-	ATL2_WRITE_REG(hw, REG_VPD_DATA, 0);
-	Control = (Offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
-	ATL2_WRITE_REG(hw, REG_VPD_CAP, Control);
-
-	for (i = 0; i < 10; i++) {
-		msleep(2);
-		Control = ATL2_READ_REG(hw, REG_VPD_CAP);
-		if (Control & VPD_CAP_VPD_FLAG)
-			break;
-	}
-
-	if (Control & VPD_CAP_VPD_FLAG) {
-		*pValue = ATL2_READ_REG(hw, REG_VPD_DATA);
-		return true;
-	}
-	return false; /* timeout */
-}
-
-static void atl2_force_ps(struct atl2_hw *hw)
-{
-	u16 phy_val;
-
-	atl2_write_phy_reg(hw, MII_DBG_ADDR, 0);
-	atl2_read_phy_reg(hw, MII_DBG_DATA, &phy_val);
-	atl2_write_phy_reg(hw, MII_DBG_DATA, phy_val | 0x1000);
-
-	atl2_write_phy_reg(hw, MII_DBG_ADDR, 2);
-	atl2_write_phy_reg(hw, MII_DBG_DATA, 0x3000);
-	atl2_write_phy_reg(hw, MII_DBG_ADDR, 3);
-	atl2_write_phy_reg(hw, MII_DBG_DATA, 0);
-}
-
-/* This is the only thing that needs to be changed to adjust the
- * maximum number of ports that the driver can manage.
- */
-#define ATL2_MAX_NIC 4
-
-#define OPTION_UNSET    -1
-#define OPTION_DISABLED 0
-#define OPTION_ENABLED  1
-
-/* All parameters are treated the same, as an integer array of values.
- * This macro just reduces the need to repeat the same declaration code
- * over and over (plus this helps to avoid typo bugs).
- */
-#define ATL2_PARAM_INIT {[0 ... ATL2_MAX_NIC] = OPTION_UNSET}
-#ifndef module_param_array
-/* Module Parameters are always initialized to -1, so that the driver
- * can tell the difference between no user specified value or the
- * user asking for the default value.
- * The true default values are loaded in when atl2_check_options is called.
- *
- * This is a GCC extension to ANSI C.
- * See the item "Labeled Elements in Initializers" in the section
- * "Extensions to the C Language Family" of the GCC documentation.
- */
-
-#define ATL2_PARAM(X, desc) \
-    static const int __devinitdata X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \
-    MODULE_PARM(X, "1-" __MODULE_STRING(ATL2_MAX_NIC) "i"); \
-    MODULE_PARM_DESC(X, desc);
-#else
-#define ATL2_PARAM(X, desc) \
-    static int __devinitdata X[ATL2_MAX_NIC+1] = ATL2_PARAM_INIT; \
-    static unsigned int num_##X; \
-    module_param_array_named(X, X, int, &num_##X, 0); \
-    MODULE_PARM_DESC(X, desc);
-#endif
-
-/*
- * Transmit Memory Size
- * Valid Range: 64-2048
- * Default Value: 128
- */
-#define ATL2_MIN_TX_MEMSIZE		4	/* 4KB */
-#define ATL2_MAX_TX_MEMSIZE		64	/* 64KB */
-#define ATL2_DEFAULT_TX_MEMSIZE		8	/* 8KB */
-ATL2_PARAM(TxMemSize, "Bytes of Transmit Memory");
-
-/*
- * Receive Memory Block Count
- * Valid Range: 16-512
- * Default Value: 128
- */
-#define ATL2_MIN_RXD_COUNT		16
-#define ATL2_MAX_RXD_COUNT		512
-#define ATL2_DEFAULT_RXD_COUNT		64
-ATL2_PARAM(RxMemBlock, "Number of receive memory block");
-
-/*
- * User Specified MediaType Override
- *
- * Valid Range: 0-5
- *  - 0    - auto-negotiate at all supported speeds
- *  - 1    - only link at 1000Mbps Full Duplex
- *  - 2    - only link at 100Mbps Full Duplex
- *  - 3    - only link at 100Mbps Half Duplex
- *  - 4    - only link at 10Mbps Full Duplex
- *  - 5    - only link at 10Mbps Half Duplex
- * Default Value: 0
- */
-ATL2_PARAM(MediaType, "MediaType Select");
-
-/*
- * Interrupt Moderate Timer in units of 2048 ns (~2 us)
- * Valid Range: 10-65535
- * Default Value: 45000(90ms)
- */
-#define INT_MOD_DEFAULT_CNT	100 /* 200us */
-#define INT_MOD_MAX_CNT		65000
-#define INT_MOD_MIN_CNT		50
-ATL2_PARAM(IntModTimer, "Interrupt Moderator Timer");
-
-/*
- * FlashVendor
- * Valid Range: 0-2
- * 0 - Atmel
- * 1 - SST
- * 2 - ST
- */
-ATL2_PARAM(FlashVendor, "SPI Flash Vendor");
-
-#define AUTONEG_ADV_DEFAULT	0x2F
-#define AUTONEG_ADV_MASK	0x2F
-#define FLOW_CONTROL_DEFAULT	FLOW_CONTROL_FULL
-
-#define FLASH_VENDOR_DEFAULT	0
-#define FLASH_VENDOR_MIN	0
-#define FLASH_VENDOR_MAX	2
-
-struct atl2_option {
-	enum { enable_option, range_option, list_option } type;
-	char *name;
-	char *err;
-	int  def;
-	union {
-		struct { /* range_option info */
-			int min;
-			int max;
-		} r;
-		struct { /* list_option info */
-			int nr;
-			struct atl2_opt_list { int i; char *str; } *p;
-		} l;
-	} arg;
-};
-
-static int __devinit atl2_validate_option(int *value, struct atl2_option *opt)
-{
-	int i;
-	struct atl2_opt_list *ent;
-
-	if (*value == OPTION_UNSET) {
-		*value = opt->def;
-		return 0;
-	}
-
-	switch (opt->type) {
-	case enable_option:
-		switch (*value) {
-		case OPTION_ENABLED:
-			printk(KERN_INFO "%s Enabled\n", opt->name);
-			return 0;
-			break;
-		case OPTION_DISABLED:
-			printk(KERN_INFO "%s Disabled\n", opt->name);
-			return 0;
-			break;
-		}
-		break;
-	case range_option:
-		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
-			printk(KERN_INFO "%s set to %i\n", opt->name, *value);
-			return 0;
-		}
-		break;
-	case list_option:
-		for (i = 0; i < opt->arg.l.nr; i++) {
-			ent = &opt->arg.l.p[i];
-			if (*value == ent->i) {
-				if (ent->str[0] != '\0')
-					printk(KERN_INFO "%s\n", ent->str);
-			return 0;
-			}
-		}
-		break;
-	default:
-		BUG();
-	}
-
-	printk(KERN_INFO "Invalid %s specified (%i) %s\n",
-		opt->name, *value, opt->err);
-	*value = opt->def;
-	return -1;
-}
-
-/*
- * atl2_check_options - Range Checking for Command Line Parameters
- * @adapter: board private structure
- *
- * This routine checks all command line parameters for valid user
- * input.  If an invalid value is given, or if no user specified
- * value exists, a default value is used.  The final value is stored
- * in a variable in the adapter structure.
- */
-static void __devinit atl2_check_options(struct atl2_adapter *adapter)
-{
-	int val;
-	struct atl2_option opt;
-	int bd = adapter->bd_number;
-	if (bd >= ATL2_MAX_NIC) {
-		printk(KERN_NOTICE "Warning: no configuration for board #%i\n",
-			bd);
-		printk(KERN_NOTICE "Using defaults for all values\n");
-#ifndef module_param_array
-		bd = ATL2_MAX_NIC;
-#endif
-	}
-
-	/* Bytes of Transmit Memory */
-	opt.type = range_option;
-	opt.name = "Bytes of Transmit Memory";
-	opt.err = "using default of " __MODULE_STRING(ATL2_DEFAULT_TX_MEMSIZE);
-	opt.def = ATL2_DEFAULT_TX_MEMSIZE;
-	opt.arg.r.min = ATL2_MIN_TX_MEMSIZE;
-	opt.arg.r.max = ATL2_MAX_TX_MEMSIZE;
-#ifdef module_param_array
-	if (num_TxMemSize > bd) {
-#endif
-		val = TxMemSize[bd];
-		atl2_validate_option(&val, &opt);
-		adapter->txd_ring_size = ((u32) val) * 1024;
-#ifdef module_param_array
-	} else
-		adapter->txd_ring_size = ((u32)opt.def) * 1024;
-#endif
-	/* txs ring size: */
-	adapter->txs_ring_size = adapter->txd_ring_size / 128;
-	if (adapter->txs_ring_size > 160)
-		adapter->txs_ring_size = 160;
-
-	/* Receive Memory Block Count */
-	opt.type = range_option;
-	opt.name = "Number of receive memory block";
-	opt.err = "using default of " __MODULE_STRING(ATL2_DEFAULT_RXD_COUNT);
-	opt.def = ATL2_DEFAULT_RXD_COUNT;
-	opt.arg.r.min = ATL2_MIN_RXD_COUNT;
-	opt.arg.r.max = ATL2_MAX_RXD_COUNT;
-#ifdef module_param_array
-	if (num_RxMemBlock > bd) {
-#endif
-		val = RxMemBlock[bd];
-		atl2_validate_option(&val, &opt);
-		adapter->rxd_ring_size = (u32)val;
-		/* FIXME */
-		/* ((u16)val)&~1; */	/* even number */
-#ifdef module_param_array
-	} else
-		adapter->rxd_ring_size = (u32)opt.def;
-#endif
-	/* init RXD Flow control value */
-	adapter->hw.fc_rxd_hi = (adapter->rxd_ring_size / 8) * 7;
-	adapter->hw.fc_rxd_lo = (ATL2_MIN_RXD_COUNT / 8) >
-		(adapter->rxd_ring_size / 12) ? (ATL2_MIN_RXD_COUNT / 8) :
-		(adapter->rxd_ring_size / 12);
-
-	/* Interrupt Moderate Timer */
-	opt.type = range_option;
-	opt.name = "Interrupt Moderate Timer";
-	opt.err = "using default of " __MODULE_STRING(INT_MOD_DEFAULT_CNT);
-	opt.def = INT_MOD_DEFAULT_CNT;
-	opt.arg.r.min = INT_MOD_MIN_CNT;
-	opt.arg.r.max = INT_MOD_MAX_CNT;
-#ifdef module_param_array
-	if (num_IntModTimer > bd) {
-#endif
-		val = IntModTimer[bd];
-		atl2_validate_option(&val, &opt);
-		adapter->imt = (u16) val;
-#ifdef module_param_array
-	} else
-		adapter->imt = (u16)(opt.def);
-#endif
-	/* Flash Vendor */
-	opt.type = range_option;
-	opt.name = "SPI Flash Vendor";
-	opt.err = "using default of " __MODULE_STRING(FLASH_VENDOR_DEFAULT);
-	opt.def = FLASH_VENDOR_DEFAULT;
-	opt.arg.r.min = FLASH_VENDOR_MIN;
-	opt.arg.r.max = FLASH_VENDOR_MAX;
-#ifdef module_param_array
-	if (num_FlashVendor > bd) {
-#endif
-		val = FlashVendor[bd];
-		atl2_validate_option(&val, &opt);
-		adapter->hw.flash_vendor = (u8) val;
-#ifdef module_param_array
-	} else
-		adapter->hw.flash_vendor = (u8)(opt.def);
-#endif
-	/* MediaType */
-	opt.type = range_option;
-	opt.name = "Speed/Duplex Selection";
-	opt.err = "using default of " __MODULE_STRING(MEDIA_TYPE_AUTO_SENSOR);
-	opt.def = MEDIA_TYPE_AUTO_SENSOR;
-	opt.arg.r.min = MEDIA_TYPE_AUTO_SENSOR;
-	opt.arg.r.max = MEDIA_TYPE_10M_HALF;
-#ifdef module_param_array
-	if (num_MediaType > bd) {
-#endif
-		val = MediaType[bd];
-		atl2_validate_option(&val, &opt);
-		adapter->hw.MediaType = (u16) val;
-#ifdef module_param_array
-	} else
-		adapter->hw.MediaType = (u16)(opt.def);
-#endif
-}
diff -druN linux-libre-3.1-gnu/drivers/net/atlx/atl2.h linux-libre-3.2-gnu/drivers/net/atlx/atl2.h
--- linux-libre-3.1-gnu/drivers/net/atlx/atl2.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atlx/atl2.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,525 +0,0 @@
-/* atl2.h -- atl2 driver definitions
- *
- * Copyright(c) 2007 Atheros Corporation. All rights reserved.
- * Copyright(c) 2006 xiong huang <xiong.huang@atheros.com>
- * Copyright(c) 2007 Chris Snook <csnook@redhat.com>
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You 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 _ATL2_H_
-#define _ATL2_H_
-
-#include <linux/atomic.h>
-#include <linux/netdevice.h>
-
-#ifndef _ATL2_HW_H_
-#define _ATL2_HW_H_
-
-#ifndef _ATL2_OSDEP_H_
-#define _ATL2_OSDEP_H_
-
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-
-#include "atlx.h"
-
-#ifdef ETHTOOL_OPS_COMPAT
-extern int ethtool_ioctl(struct ifreq *ifr);
-#endif
-
-#define PCI_COMMAND_REGISTER	PCI_COMMAND
-#define CMD_MEM_WRT_INVALIDATE	PCI_COMMAND_INVALIDATE
-#define ETH_ADDR_LEN		ETH_ALEN
-
-#define ATL2_WRITE_REG(a, reg, value) (iowrite32((value), \
-	((a)->hw_addr + (reg))))
-
-#define ATL2_WRITE_FLUSH(a) (ioread32((a)->hw_addr))
-
-#define ATL2_READ_REG(a, reg) (ioread32((a)->hw_addr + (reg)))
-
-#define ATL2_WRITE_REGB(a, reg, value) (iowrite8((value), \
-	((a)->hw_addr + (reg))))
-
-#define ATL2_READ_REGB(a, reg) (ioread8((a)->hw_addr + (reg)))
-
-#define ATL2_WRITE_REGW(a, reg, value) (iowrite16((value), \
-	((a)->hw_addr + (reg))))
-
-#define ATL2_READ_REGW(a, reg) (ioread16((a)->hw_addr + (reg)))
-
-#define ATL2_WRITE_REG_ARRAY(a, reg, offset, value) \
-	(iowrite32((value), (((a)->hw_addr + (reg)) + ((offset) << 2))))
-
-#define ATL2_READ_REG_ARRAY(a, reg, offset) \
-	(ioread32(((a)->hw_addr + (reg)) + ((offset) << 2)))
-
-#endif /* _ATL2_OSDEP_H_ */
-
-struct atl2_adapter;
-struct atl2_hw;
-
-/* function prototype */
-static s32 atl2_reset_hw(struct atl2_hw *hw);
-static s32 atl2_read_mac_addr(struct atl2_hw *hw);
-static s32 atl2_init_hw(struct atl2_hw *hw);
-static s32 atl2_get_speed_and_duplex(struct atl2_hw *hw, u16 *speed,
-	u16 *duplex);
-static u32 atl2_hash_mc_addr(struct atl2_hw *hw, u8 *mc_addr);
-static void atl2_hash_set(struct atl2_hw *hw, u32 hash_value);
-static s32 atl2_read_phy_reg(struct atl2_hw *hw, u16 reg_addr, u16 *phy_data);
-static s32 atl2_write_phy_reg(struct atl2_hw *hw, u32 reg_addr, u16 phy_data);
-static void atl2_read_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value);
-static void atl2_write_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value);
-static void atl2_set_mac_addr(struct atl2_hw *hw);
-static bool atl2_read_eeprom(struct atl2_hw *hw, u32 Offset, u32 *pValue);
-static bool atl2_write_eeprom(struct atl2_hw *hw, u32 offset, u32 value);
-static s32 atl2_phy_init(struct atl2_hw *hw);
-static int atl2_check_eeprom_exist(struct atl2_hw *hw);
-static void atl2_force_ps(struct atl2_hw *hw);
-
-/* register definition */
-
-/* Block IDLE Status Register */
-#define IDLE_STATUS_RXMAC	1	/* 1: RXMAC is non-IDLE */
-#define IDLE_STATUS_TXMAC	2	/* 1: TXMAC is non-IDLE */
-#define IDLE_STATUS_DMAR	8	/* 1: DMAR is non-IDLE */
-#define IDLE_STATUS_DMAW	4	/* 1: DMAW is non-IDLE */
-
-/* MDIO Control Register */
-#define MDIO_WAIT_TIMES		10
-
-/* MAC Control Register */
-#define MAC_CTRL_DBG_TX_BKPRESURE	0x100000	/* 1: TX max backoff */
-#define MAC_CTRL_MACLP_CLK_PHY		0x8000000	/* 1: 25MHz from phy */
-#define MAC_CTRL_HALF_LEFT_BUF_SHIFT	28
-#define MAC_CTRL_HALF_LEFT_BUF_MASK	0xF		/* MAC retry buf x32B */
-
-/* Internal SRAM Partition Register */
-#define REG_SRAM_TXRAM_END	0x1500	/* Internal tail address of TXRAM
-					 * default: 2byte*1024 */
-#define REG_SRAM_RXRAM_END	0x1502	/* Internal tail address of RXRAM
-					 * default: 2byte*1024 */
-
-/* Descriptor Control register */
-#define REG_TXD_BASE_ADDR_LO	0x1544	/* The base address of the Transmit
-					 * Data Mem low 32-bit(dword align) */
-#define REG_TXD_MEM_SIZE	0x1548	/* Transmit Data Memory size(by
-					 * double word , max 256KB) */
-#define REG_TXS_BASE_ADDR_LO	0x154C	/* The base address of the Transmit
-					 * Status Memory low 32-bit(dword word
-					 * align) */
-#define REG_TXS_MEM_SIZE	0x1550	/* double word unit, max 4*2047
-					 * bytes. */
-#define REG_RXD_BASE_ADDR_LO	0x1554	/* The base address of the Transmit
-					 * Status Memory low 32-bit(unit 8
-					 * bytes) */
-#define REG_RXD_BUF_NUM		0x1558	/* Receive Data & Status Memory buffer
-					 * number (unit 1536bytes, max
-					 * 1536*2047) */
-
-/* DMAR Control Register */
-#define REG_DMAR	0x1580
-#define     DMAR_EN	0x1	/* 1: Enable DMAR */
-
-/* TX Cur-Through (early tx threshold) Control Register */
-#define REG_TX_CUT_THRESH	0x1590	/* TxMac begin transmit packet
-					 * threshold(unit word) */
-
-/* DMAW Control Register */
-#define REG_DMAW	0x15A0
-#define     DMAW_EN	0x1
-
-/* Flow control register */
-#define REG_PAUSE_ON_TH		0x15A8	/* RXD high watermark of overflow
-					 * threshold configuration register */
-#define REG_PAUSE_OFF_TH	0x15AA	/* RXD lower watermark of overflow
-					 * threshold configuration register */
-
-/* Mailbox Register */
-#define REG_MB_TXD_WR_IDX	0x15f0	/* double word align */
-#define REG_MB_RXD_RD_IDX	0x15F4	/* RXD Read index (unit: 1536byets) */
-
-/* Interrupt Status Register */
-#define ISR_TIMER	1	/* Interrupt when Timer counts down to zero */
-#define ISR_MANUAL	2	/* Software manual interrupt, for debug. Set
-				 * when SW_MAN_INT_EN is set in Table 51
-				 * Selene Master Control Register
-				 * (Offset 0x1400). */
-#define ISR_RXF_OV	4	/* RXF overflow interrupt */
-#define ISR_TXF_UR	8	/* TXF underrun interrupt */
-#define ISR_TXS_OV	0x10	/* Internal transmit status buffer full
-				 * interrupt */
-#define ISR_RXS_OV	0x20	/* Internal receive status buffer full
-				 * interrupt */
-#define ISR_LINK_CHG	0x40	/* Link Status Change Interrupt */
-#define ISR_HOST_TXD_UR	0x80
-#define ISR_HOST_RXD_OV	0x100	/* Host rx data memory full , one pulse */
-#define ISR_DMAR_TO_RST	0x200	/* DMAR op timeout interrupt. SW should
-				 * do Reset */
-#define ISR_DMAW_TO_RST	0x400
-#define ISR_PHY		0x800	/* phy interrupt */
-#define ISR_TS_UPDATE	0x10000	/* interrupt after new tx pkt status written
-				 * to host */
-#define ISR_RS_UPDATE	0x20000	/* interrupt ater new rx pkt status written
-				 * to host. */
-#define ISR_TX_EARLY	0x40000	/* interrupt when txmac begin transmit one
-				 * packet */
-
-#define ISR_TX_EVENT (ISR_TXF_UR | ISR_TXS_OV | ISR_HOST_TXD_UR |\
-	ISR_TS_UPDATE | ISR_TX_EARLY)
-#define ISR_RX_EVENT (ISR_RXF_OV | ISR_RXS_OV | ISR_HOST_RXD_OV |\
-	 ISR_RS_UPDATE)
-
-#define IMR_NORMAL_MASK		(\
-	/*ISR_LINK_CHG		|*/\
-	ISR_MANUAL		|\
-	ISR_DMAR_TO_RST		|\
-	ISR_DMAW_TO_RST		|\
-	ISR_PHY			|\
-	ISR_PHY_LINKDOWN	|\
-	ISR_TS_UPDATE		|\
-	ISR_RS_UPDATE)
-
-/* Receive MAC Statistics Registers */
-#define REG_STS_RX_PAUSE	0x1700	/* Num pause packets received */
-#define REG_STS_RXD_OV		0x1704	/* Num frames dropped due to RX
-					 * FIFO overflow */
-#define REG_STS_RXS_OV		0x1708	/* Num frames dropped due to RX
-					 * Status Buffer Overflow */
-#define REG_STS_RX_FILTER	0x170C	/* Num packets dropped due to
-					 * address filtering */
-
-/* MII definitions */
-
-/* PHY Common Register */
-#define MII_SMARTSPEED	0x14
-#define MII_DBG_ADDR	0x1D
-#define MII_DBG_DATA	0x1E
-
-/* PCI Command Register Bit Definitions */
-#define PCI_REG_COMMAND		0x04
-#define CMD_IO_SPACE		0x0001
-#define CMD_MEMORY_SPACE	0x0002
-#define CMD_BUS_MASTER		0x0004
-
-#define MEDIA_TYPE_100M_FULL	1
-#define MEDIA_TYPE_100M_HALF	2
-#define MEDIA_TYPE_10M_FULL	3
-#define MEDIA_TYPE_10M_HALF	4
-
-#define AUTONEG_ADVERTISE_SPEED_DEFAULT	0x000F	/* Everything */
-
-/* The size (in bytes) of a ethernet packet */
-#define ENET_HEADER_SIZE		14
-#define MAXIMUM_ETHERNET_FRAME_SIZE	1518	/* with FCS */
-#define MINIMUM_ETHERNET_FRAME_SIZE	64	/* with FCS */
-#define ETHERNET_FCS_SIZE		4
-#define MAX_JUMBO_FRAME_SIZE		0x2000
-#define VLAN_SIZE                                               4
-
-struct tx_pkt_header {
-	unsigned pkt_size:11;
-	unsigned:4;			/* reserved */
-	unsigned ins_vlan:1;		/* txmac should insert vlan */
-	unsigned short vlan;		/* vlan tag */
-};
-/* FIXME: replace above bitfields with MASK/SHIFT defines below */
-#define TX_PKT_HEADER_SIZE_MASK		0x7FF
-#define TX_PKT_HEADER_SIZE_SHIFT	0
-#define TX_PKT_HEADER_INS_VLAN_MASK	0x1
-#define TX_PKT_HEADER_INS_VLAN_SHIFT	15
-#define TX_PKT_HEADER_VLAN_TAG_MASK	0xFFFF
-#define TX_PKT_HEADER_VLAN_TAG_SHIFT	16
-
-struct tx_pkt_status {
-	unsigned pkt_size:11;
-	unsigned:5;		/* reserved */
-	unsigned ok:1;		/* current packet transmitted without error */
-	unsigned bcast:1;	/* broadcast packet */
-	unsigned mcast:1;	/* multicast packet */
-	unsigned pause:1;	/* transmiited a pause frame */
-	unsigned ctrl:1;
-	unsigned defer:1;    	/* current packet is xmitted with defer */
-	unsigned exc_defer:1;
-	unsigned single_col:1;
-	unsigned multi_col:1;
-	unsigned late_col:1;
-	unsigned abort_col:1;
-	unsigned underun:1;	/* current packet is aborted
-				 * due to txram underrun */
-	unsigned:3;		/* reserved */
-	unsigned update:1;	/* always 1'b1 in tx_status_buf */
-};
-/* FIXME: replace above bitfields with MASK/SHIFT defines below */
-#define TX_PKT_STATUS_SIZE_MASK		0x7FF
-#define TX_PKT_STATUS_SIZE_SHIFT	0
-#define TX_PKT_STATUS_OK_MASK		0x1
-#define TX_PKT_STATUS_OK_SHIFT		16
-#define TX_PKT_STATUS_BCAST_MASK	0x1
-#define TX_PKT_STATUS_BCAST_SHIFT	17
-#define TX_PKT_STATUS_MCAST_MASK	0x1
-#define TX_PKT_STATUS_MCAST_SHIFT	18
-#define TX_PKT_STATUS_PAUSE_MASK	0x1
-#define TX_PKT_STATUS_PAUSE_SHIFT	19
-#define TX_PKT_STATUS_CTRL_MASK		0x1
-#define TX_PKT_STATUS_CTRL_SHIFT	20
-#define TX_PKT_STATUS_DEFER_MASK	0x1
-#define TX_PKT_STATUS_DEFER_SHIFT	21
-#define TX_PKT_STATUS_EXC_DEFER_MASK	0x1
-#define TX_PKT_STATUS_EXC_DEFER_SHIFT	22
-#define TX_PKT_STATUS_SINGLE_COL_MASK	0x1
-#define TX_PKT_STATUS_SINGLE_COL_SHIFT	23
-#define TX_PKT_STATUS_MULTI_COL_MASK	0x1
-#define TX_PKT_STATUS_MULTI_COL_SHIFT	24
-#define TX_PKT_STATUS_LATE_COL_MASK	0x1
-#define TX_PKT_STATUS_LATE_COL_SHIFT	25
-#define TX_PKT_STATUS_ABORT_COL_MASK	0x1
-#define TX_PKT_STATUS_ABORT_COL_SHIFT	26
-#define TX_PKT_STATUS_UNDERRUN_MASK	0x1
-#define TX_PKT_STATUS_UNDERRUN_SHIFT	27
-#define TX_PKT_STATUS_UPDATE_MASK	0x1
-#define TX_PKT_STATUS_UPDATE_SHIFT	31
-
-struct rx_pkt_status {
-	unsigned pkt_size:11;	/* packet size, max 2047 bytes */
-	unsigned:5;		/* reserved */
-	unsigned ok:1;		/* current packet received ok without error */
-	unsigned bcast:1;	/* current packet is broadcast */
-	unsigned mcast:1;	/* current packet is multicast */
-	unsigned pause:1;
-	unsigned ctrl:1;
-	unsigned crc:1;		/* received a packet with crc error */
-	unsigned code:1;	/* received a packet with code error */
-	unsigned runt:1;	/* received a packet less than 64 bytes
-				 * with good crc */
-	unsigned frag:1;	/* received a packet less than 64 bytes
-				 * with bad crc */
-	unsigned trunc:1;	/* current frame truncated due to rxram full */
-	unsigned align:1;	/* this packet is alignment error */
-	unsigned vlan:1;	/* this packet has vlan */
-	unsigned:3;		/* reserved */
-	unsigned update:1;
-	unsigned short vtag;	/* vlan tag */
-	unsigned:16;
-};
-/* FIXME: replace above bitfields with MASK/SHIFT defines below */
-#define RX_PKT_STATUS_SIZE_MASK		0x7FF
-#define RX_PKT_STATUS_SIZE_SHIFT	0
-#define RX_PKT_STATUS_OK_MASK		0x1
-#define RX_PKT_STATUS_OK_SHIFT		16
-#define RX_PKT_STATUS_BCAST_MASK	0x1
-#define RX_PKT_STATUS_BCAST_SHIFT	17
-#define RX_PKT_STATUS_MCAST_MASK	0x1
-#define RX_PKT_STATUS_MCAST_SHIFT	18
-#define RX_PKT_STATUS_PAUSE_MASK	0x1
-#define RX_PKT_STATUS_PAUSE_SHIFT	19
-#define RX_PKT_STATUS_CTRL_MASK		0x1
-#define RX_PKT_STATUS_CTRL_SHIFT	20
-#define RX_PKT_STATUS_CRC_MASK		0x1
-#define RX_PKT_STATUS_CRC_SHIFT		21
-#define RX_PKT_STATUS_CODE_MASK		0x1
-#define RX_PKT_STATUS_CODE_SHIFT	22
-#define RX_PKT_STATUS_RUNT_MASK		0x1
-#define RX_PKT_STATUS_RUNT_SHIFT	23
-#define RX_PKT_STATUS_FRAG_MASK		0x1
-#define RX_PKT_STATUS_FRAG_SHIFT	24
-#define RX_PKT_STATUS_TRUNK_MASK	0x1
-#define RX_PKT_STATUS_TRUNK_SHIFT	25
-#define RX_PKT_STATUS_ALIGN_MASK	0x1
-#define RX_PKT_STATUS_ALIGN_SHIFT	26
-#define RX_PKT_STATUS_VLAN_MASK		0x1
-#define RX_PKT_STATUS_VLAN_SHIFT	27
-#define RX_PKT_STATUS_UPDATE_MASK	0x1
-#define RX_PKT_STATUS_UPDATE_SHIFT	31
-#define RX_PKT_STATUS_VLAN_TAG_MASK	0xFFFF
-#define RX_PKT_STATUS_VLAN_TAG_SHIFT	32
-
-struct rx_desc {
-	struct rx_pkt_status	status;
-	unsigned char     	packet[1536-sizeof(struct rx_pkt_status)];
-};
-
-enum atl2_speed_duplex {
-	atl2_10_half = 0,
-	atl2_10_full = 1,
-	atl2_100_half = 2,
-	atl2_100_full = 3
-};
-
-struct atl2_spi_flash_dev {
-	const char *manu_name;	/* manufacturer id */
-	/* op-code */
-	u8 cmdWRSR;
-	u8 cmdREAD;
-	u8 cmdPROGRAM;
-	u8 cmdWREN;
-	u8 cmdWRDI;
-	u8 cmdRDSR;
-	u8 cmdRDID;
-	u8 cmdSECTOR_ERASE;
-	u8 cmdCHIP_ERASE;
-};
-
-/* Structure containing variables used by the shared code (atl2_hw.c) */
-struct atl2_hw {
-	u8 __iomem *hw_addr;
-	void *back;
-
-	u8 preamble_len;
-	u8 max_retry;          /* Retransmission maximum, afterwards the
-				* packet will be discarded. */
-	u8 jam_ipg;            /* IPG to start JAM for collision based flow
-				* control in half-duplex mode. In unit of
-				* 8-bit time. */
-	u8 ipgt;               /* Desired back to back inter-packet gap. The
-				* default is 96-bit time. */
-	u8 min_ifg;            /* Minimum number of IFG to enforce in between
-				* RX frames. Frame gap below such IFP is
-				* dropped. */
-	u8 ipgr1;              /* 64bit Carrier-Sense window */
-	u8 ipgr2;              /* 96-bit IPG window */
-	u8 retry_buf;          /* When half-duplex mode, should hold some
-				* bytes for mac retry . (8*4bytes unit) */
-
-	u16 fc_rxd_hi;
-	u16 fc_rxd_lo;
-	u16 lcol;              /* Collision Window */
-	u16 max_frame_size;
-
-	u16 MediaType;
-	u16 autoneg_advertised;
-	u16 pci_cmd_word;
-
-	u16 mii_autoneg_adv_reg;
-
-	u32 mem_rang;
-	u32 txcw;
-	u32 mc_filter_type;
-	u32 num_mc_addrs;
-	u32 collision_delta;
-	u32 tx_packet_delta;
-	u16 phy_spd_default;
-
-	u16 device_id;
-	u16 vendor_id;
-	u16 subsystem_id;
-	u16 subsystem_vendor_id;
-	u8 revision_id;
-
-	/* spi flash */
-	u8 flash_vendor;
-
-	u8 dma_fairness;
-	u8 mac_addr[NODE_ADDRESS_SIZE];
-	u8 perm_mac_addr[NODE_ADDRESS_SIZE];
-
-	/* FIXME */
-	/* bool phy_preamble_sup; */
-	bool phy_configured;
-};
-
-#endif /* _ATL2_HW_H_ */
-
-struct atl2_ring_header {
-    /* pointer to the descriptor ring memory */
-    void *desc;
-    /* physical address of the descriptor ring */
-    dma_addr_t dma;
-    /* length of descriptor ring in bytes */
-    unsigned int size;
-};
-
-/* board specific private data structure */
-struct atl2_adapter {
-	/* OS defined structs */
-	struct net_device *netdev;
-	struct pci_dev *pdev;
-	u32 wol;
-	u16 link_speed;
-	u16 link_duplex;
-
-	spinlock_t stats_lock;
-
-	struct work_struct reset_task;
-	struct work_struct link_chg_task;
-	struct timer_list watchdog_timer;
-	struct timer_list phy_config_timer;
-
-	unsigned long cfg_phy;
-	bool mac_disabled;
-
-	/* All Descriptor memory */
-	dma_addr_t	ring_dma;
-	void		*ring_vir_addr;
-	int		ring_size;
-
-	struct tx_pkt_header	*txd_ring;
-	dma_addr_t	txd_dma;
-
-	struct tx_pkt_status	*txs_ring;
-	dma_addr_t	txs_dma;
-
-	struct rx_desc	*rxd_ring;
-	dma_addr_t	rxd_dma;
-
-	u32 txd_ring_size;         /* bytes per unit */
-	u32 txs_ring_size;         /* dwords per unit */
-	u32 rxd_ring_size;         /* 1536 bytes per unit */
-
-	/* read /write ptr: */
-	/* host */
-	u32 txd_write_ptr;
-	u32 txs_next_clear;
-	u32 rxd_read_ptr;
-
-	/* nic */
-	atomic_t txd_read_ptr;
-	atomic_t txs_write_ptr;
-	u32 rxd_write_ptr;
-
-	/* Interrupt Moderator timer ( 2us resolution) */
-	u16 imt;
-	/* Interrupt Clear timer (2us resolution) */
-	u16 ict;
-
-	unsigned long flags;
-	/* structs defined in atl2_hw.h */
-	u32 bd_number;     /* board number */
-	bool pci_using_64;
-	bool have_msi;
-	struct atl2_hw hw;
-
-	u32 usr_cmd;
-	/* FIXME */
-	/* u32 regs_buff[ATL2_REGS_LEN]; */
-	u32 pci_state[16];
-
-	u32 *config_space;
-};
-
-enum atl2_state_t {
-	__ATL2_TESTING,
-	__ATL2_RESETTING,
-	__ATL2_DOWN
-};
-
-#endif /* _ATL2_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/atlx/atlx.c linux-libre-3.2-gnu/drivers/net/atlx/atlx.c
--- linux-libre-3.1-gnu/drivers/net/atlx/atlx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atlx/atlx.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,269 +0,0 @@
-/* atlx.c -- common functions for Attansic network drivers
- *
- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
- * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com>
- * Copyright(c) 2006 - 2008 Jay Cliburn <jcliburn@gmail.com>
- * Copyright(c) 2007 Atheros Corporation. All rights reserved.
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You 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.
- */
-
-/* Including this file like a header is a temporary hack, I promise. -- CHS */
-#ifndef ATLX_C
-#define ATLX_C
-
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/etherdevice.h>
-#include <linux/if.h>
-#include <linux/netdevice.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/workqueue.h>
-
-#include "atlx.h"
-
-static s32 atlx_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data);
-static u32 atlx_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr);
-static void atlx_set_mac_addr(struct atl1_hw *hw);
-
-static struct atlx_spi_flash_dev flash_table[] = {
-/*	MFR_NAME  WRSR  READ  PRGM  WREN  WRDI  RDSR  RDID  SEC_ERS CHIP_ERS */
-	{"Atmel", 0x00, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52,   0x62},
-	{"SST",   0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20,   0x60},
-	{"ST",    0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8,   0xC7},
-};
-
-static int atlx_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	switch (cmd) {
-	case SIOCGMIIPHY:
-	case SIOCGMIIREG:
-	case SIOCSMIIREG:
-		return atlx_mii_ioctl(netdev, ifr, cmd);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-/*
- * atlx_set_mac - Change the Ethernet Address of the NIC
- * @netdev: network interface device structure
- * @p: pointer to an address structure
- *
- * Returns 0 on success, negative on failure
- */
-static int atlx_set_mac(struct net_device *netdev, void *p)
-{
-	struct atlx_adapter *adapter = netdev_priv(netdev);
-	struct sockaddr *addr = p;
-
-	if (netif_running(netdev))
-		return -EBUSY;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
-
-	atlx_set_mac_addr(&adapter->hw);
-	return 0;
-}
-
-static void atlx_check_for_link(struct atlx_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	u16 phy_data = 0;
-
-	spin_lock(&adapter->lock);
-	adapter->phy_timer_pending = false;
-	atlx_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
-	atlx_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
-	spin_unlock(&adapter->lock);
-
-	/* notify upper layer link down ASAP */
-	if (!(phy_data & BMSR_LSTATUS)) {
-		/* Link Down */
-		if (netif_carrier_ok(netdev)) {
-			/* old link state: Up */
-			dev_info(&adapter->pdev->dev, "%s link is down\n",
-				netdev->name);
-			adapter->link_speed = SPEED_0;
-			netif_carrier_off(netdev);
-		}
-	}
-	schedule_work(&adapter->link_chg_task);
-}
-
-/*
- * atlx_set_multi - Multicast and Promiscuous mode set
- * @netdev: network interface device structure
- *
- * The set_multi entry point is called whenever the multicast address
- * list or the network interface flags are updated.  This routine is
- * responsible for configuring the hardware for proper multicast,
- * promiscuous mode, and all-multi behavior.
- */
-static void atlx_set_multi(struct net_device *netdev)
-{
-	struct atlx_adapter *adapter = netdev_priv(netdev);
-	struct atlx_hw *hw = &adapter->hw;
-	struct netdev_hw_addr *ha;
-	u32 rctl;
-	u32 hash_value;
-
-	/* Check for Promiscuous and All Multicast modes */
-	rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
-	if (netdev->flags & IFF_PROMISC)
-		rctl |= MAC_CTRL_PROMIS_EN;
-	else if (netdev->flags & IFF_ALLMULTI) {
-		rctl |= MAC_CTRL_MC_ALL_EN;
-		rctl &= ~MAC_CTRL_PROMIS_EN;
-	} else
-		rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
-
-	iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
-
-	/* clear the old settings from the multicast hash table */
-	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
-	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
-
-	/* compute mc addresses' hash value ,and put it into hash table */
-	netdev_for_each_mc_addr(ha, netdev) {
-		hash_value = atlx_hash_mc_addr(hw, ha->addr);
-		atlx_hash_set(hw, hash_value);
-	}
-}
-
-/*
- * atlx_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- */
-static void atlx_irq_enable(struct atlx_adapter *adapter)
-{
-	iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
-	ioread32(adapter->hw.hw_addr + REG_IMR);
-}
-
-/*
- * atlx_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- */
-static void atlx_irq_disable(struct atlx_adapter *adapter)
-{
-	iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-	ioread32(adapter->hw.hw_addr + REG_IMR);
-	synchronize_irq(adapter->pdev->irq);
-}
-
-static void atlx_clear_phy_int(struct atlx_adapter *adapter)
-{
-	u16 phy_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	atlx_read_phy_reg(&adapter->hw, 19, &phy_data);
-	spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-/*
- * atlx_tx_timeout - Respond to a Tx Hang
- * @netdev: network interface device structure
- */
-static void atlx_tx_timeout(struct net_device *netdev)
-{
-	struct atlx_adapter *adapter = netdev_priv(netdev);
-	/* Do the reset outside of interrupt context */
-	schedule_work(&adapter->tx_timeout_task);
-}
-
-/*
- * atlx_link_chg_task - deal with link change event Out of interrupt context
- */
-static void atlx_link_chg_task(struct work_struct *work)
-{
-	struct atlx_adapter *adapter;
-	unsigned long flags;
-
-	adapter = container_of(work, struct atlx_adapter, link_chg_task);
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	atlx_check_link(adapter);
-	spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-static void __atlx_vlan_mode(u32 features, u32 *ctrl)
-{
-	if (features & NETIF_F_HW_VLAN_RX) {
-		/* enable VLAN tag insert/strip */
-		*ctrl |= MAC_CTRL_RMV_VLAN;
-	} else {
-		/* disable VLAN tag insert/strip */
-		*ctrl &= ~MAC_CTRL_RMV_VLAN;
-	}
-}
-
-static void atlx_vlan_mode(struct net_device *netdev, u32 features)
-{
-	struct atlx_adapter *adapter = netdev_priv(netdev);
-	unsigned long flags;
-	u32 ctrl;
-
-	spin_lock_irqsave(&adapter->lock, flags);
-	/* atlx_irq_disable(adapter); FIXME: confirm/remove */
-	ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
-	__atlx_vlan_mode(features, &ctrl);
-	iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
-	/* atlx_irq_enable(adapter); FIXME */
-	spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-static void atlx_restore_vlan(struct atlx_adapter *adapter)
-{
-	atlx_vlan_mode(adapter->netdev, adapter->netdev->features);
-}
-
-static u32 atlx_fix_features(struct net_device *netdev, u32 features)
-{
-	/*
-	 * Since there is no support for separate rx/tx vlan accel
-	 * enable/disable make sure tx flag is always in same state as rx.
-	 */
-	if (features & NETIF_F_HW_VLAN_RX)
-		features |= NETIF_F_HW_VLAN_TX;
-	else
-		features &= ~NETIF_F_HW_VLAN_TX;
-
-	return features;
-}
-
-static int atlx_set_features(struct net_device *netdev, u32 features)
-{
-	u32 changed = netdev->features ^ features;
-
-	if (changed & NETIF_F_HW_VLAN_RX)
-		atlx_vlan_mode(netdev, features);
-
-	return 0;
-}
-
-#endif /* ATLX_C */
diff -druN linux-libre-3.1-gnu/drivers/net/atlx/atlx.h linux-libre-3.2-gnu/drivers/net/atlx/atlx.h
--- linux-libre-3.1-gnu/drivers/net/atlx/atlx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atlx/atlx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,503 +0,0 @@
-/* atlx_hw.h -- common hardware definitions for Attansic network drivers
- *
- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
- * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com>
- * Copyright(c) 2006 - 2008 Jay Cliburn <jcliburn@gmail.com>
- * Copyright(c) 2007 Atheros Corporation. All rights reserved.
- *
- * Derived from Intel e1000 driver
- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You 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 ATLX_H
-#define ATLX_H
-
-#include <linux/module.h>
-#include <linux/types.h>
-
-#define ATLX_ERR_PHY			2
-#define ATLX_ERR_PHY_SPEED		7
-#define ATLX_ERR_PHY_RES		8
-
-#define SPEED_0				0xffff
-#define SPEED_10			10
-#define SPEED_100			100
-#define SPEED_1000			1000
-#define HALF_DUPLEX			1
-#define FULL_DUPLEX			2
-
-#define MEDIA_TYPE_AUTO_SENSOR		0
-
-/* register definitions */
-#define REG_PM_CTRLSTAT			0x44
-
-#define REG_PCIE_CAP_LIST		0x58
-
-#define REG_VPD_CAP			0x6C
-#define VPD_CAP_ID_MASK			0xFF
-#define VPD_CAP_ID_SHIFT		0
-#define VPD_CAP_NEXT_PTR_MASK		0xFF
-#define VPD_CAP_NEXT_PTR_SHIFT		8
-#define VPD_CAP_VPD_ADDR_MASK		0x7FFF
-#define VPD_CAP_VPD_ADDR_SHIFT		16
-#define VPD_CAP_VPD_FLAG		0x80000000
-
-#define REG_VPD_DATA			0x70
-
-#define REG_SPI_FLASH_CTRL		0x200
-#define SPI_FLASH_CTRL_STS_NON_RDY	0x1
-#define SPI_FLASH_CTRL_STS_WEN		0x2
-#define SPI_FLASH_CTRL_STS_WPEN		0x80
-#define SPI_FLASH_CTRL_DEV_STS_MASK	0xFF
-#define SPI_FLASH_CTRL_DEV_STS_SHIFT	0
-#define SPI_FLASH_CTRL_INS_MASK		0x7
-#define SPI_FLASH_CTRL_INS_SHIFT	8
-#define SPI_FLASH_CTRL_START		0x800
-#define SPI_FLASH_CTRL_EN_VPD		0x2000
-#define SPI_FLASH_CTRL_LDSTART		0x8000
-#define SPI_FLASH_CTRL_CS_HI_MASK	0x3
-#define SPI_FLASH_CTRL_CS_HI_SHIFT	16
-#define SPI_FLASH_CTRL_CS_HOLD_MASK	0x3
-#define SPI_FLASH_CTRL_CS_HOLD_SHIFT	18
-#define SPI_FLASH_CTRL_CLK_LO_MASK	0x3
-#define SPI_FLASH_CTRL_CLK_LO_SHIFT	20
-#define SPI_FLASH_CTRL_CLK_HI_MASK	0x3
-#define SPI_FLASH_CTRL_CLK_HI_SHIFT	22
-#define SPI_FLASH_CTRL_CS_SETUP_MASK	0x3
-#define SPI_FLASH_CTRL_CS_SETUP_SHIFT	24
-#define SPI_FLASH_CTRL_EROM_PGSZ_MASK	0x3
-#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT	26
-#define SPI_FLASH_CTRL_WAIT_READY	0x10000000
-
-#define REG_SPI_ADDR			0x204
-
-#define REG_SPI_DATA			0x208
-
-#define REG_SPI_FLASH_CONFIG		0x20C
-#define SPI_FLASH_CONFIG_LD_ADDR_MASK	0xFFFFFF
-#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT	0
-#define SPI_FLASH_CONFIG_VPD_ADDR_MASK	0x3
-#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT	24
-#define SPI_FLASH_CONFIG_LD_EXIST	0x4000000
-
-#define REG_SPI_FLASH_OP_PROGRAM	0x210
-#define REG_SPI_FLASH_OP_SC_ERASE	0x211
-#define REG_SPI_FLASH_OP_CHIP_ERASE	0x212
-#define REG_SPI_FLASH_OP_RDID		0x213
-#define REG_SPI_FLASH_OP_WREN		0x214
-#define REG_SPI_FLASH_OP_RDSR		0x215
-#define REG_SPI_FLASH_OP_WRSR		0x216
-#define REG_SPI_FLASH_OP_READ		0x217
-
-#define REG_TWSI_CTRL			0x218
-#define TWSI_CTRL_LD_OFFSET_MASK	0xFF
-#define TWSI_CTRL_LD_OFFSET_SHIFT	0
-#define TWSI_CTRL_LD_SLV_ADDR_MASK	0x7
-#define TWSI_CTRL_LD_SLV_ADDR_SHIFT	8
-#define TWSI_CTRL_SW_LDSTART		0x800
-#define TWSI_CTRL_HW_LDSTART		0x1000
-#define TWSI_CTRL_SMB_SLV_ADDR_MASK	0x7F
-#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT	15
-#define TWSI_CTRL_LD_EXIST		0x400000
-#define TWSI_CTRL_READ_FREQ_SEL_MASK	0x3
-#define TWSI_CTRL_READ_FREQ_SEL_SHIFT	23
-#define TWSI_CTRL_FREQ_SEL_100K		0
-#define TWSI_CTRL_FREQ_SEL_200K		1
-#define TWSI_CTRL_FREQ_SEL_300K		2
-#define TWSI_CTRL_FREQ_SEL_400K		3
-#define TWSI_CTRL_SMB_SLV_ADDR		/* FIXME: define or remove */
-#define TWSI_CTRL_WRITE_FREQ_SEL_MASK	0x3
-#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT	24
-
-#define REG_PCIE_DEV_MISC_CTRL			0x21C
-#define PCIE_DEV_MISC_CTRL_EXT_PIPE		0x2
-#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS		0x1
-#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST		0x4
-#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN	0x8
-#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN	0x10
-
-#define REG_PCIE_PHYMISC		0x1000
-#define PCIE_PHYMISC_FORCE_RCV_DET	0x4
-
-#define REG_PCIE_DLL_TX_CTRL1		0x1104
-#define PCIE_DLL_TX_CTRL1_SEL_NOR_CLK	0x400
-#define PCIE_DLL_TX_CTRL1_DEF		0x568
-
-#define REG_LTSSM_TEST_MODE		0x12FC
-#define LTSSM_TEST_MODE_DEF		0x6500
-
-/* Master Control Register */
-#define REG_MASTER_CTRL			0x1400
-#define MASTER_CTRL_SOFT_RST		0x1
-#define MASTER_CTRL_MTIMER_EN		0x2
-#define MASTER_CTRL_ITIMER_EN		0x4
-#define MASTER_CTRL_MANUAL_INT		0x8
-#define MASTER_CTRL_REV_NUM_SHIFT	16
-#define MASTER_CTRL_REV_NUM_MASK	0xFF
-#define MASTER_CTRL_DEV_ID_SHIFT	24
-#define MASTER_CTRL_DEV_ID_MASK		0xFF
-
-/* Timer Initial Value Register */
-#define REG_MANUAL_TIMER_INIT		0x1404
-
-/* IRQ Moderator Timer Initial Value Register */
-#define REG_IRQ_MODU_TIMER_INIT		0x1408
-
-#define REG_PHY_ENABLE			0x140C
-
-/* IRQ Anti-Lost Timer Initial Value Register */
-#define REG_CMBDISDMA_TIMER		0x140E
-
-/* Block IDLE Status Register */
-#define REG_IDLE_STATUS			0x1410
-
-/* MDIO Control Register */
-#define REG_MDIO_CTRL			0x1414
-#define MDIO_DATA_MASK			0xFFFF
-#define MDIO_DATA_SHIFT			0
-#define MDIO_REG_ADDR_MASK		0x1F
-#define MDIO_REG_ADDR_SHIFT		16
-#define MDIO_RW				0x200000
-#define MDIO_SUP_PREAMBLE		0x400000
-#define MDIO_START			0x800000
-#define MDIO_CLK_SEL_SHIFT		24
-#define MDIO_CLK_25_4			0
-#define MDIO_CLK_25_6			2
-#define MDIO_CLK_25_8			3
-#define MDIO_CLK_25_10			4
-#define MDIO_CLK_25_14			5
-#define MDIO_CLK_25_20			6
-#define MDIO_CLK_25_28			7
-#define MDIO_BUSY			0x8000000
-
-/* MII PHY Status Register */
-#define REG_PHY_STATUS			0x1418
-
-/* BIST Control and Status Register0 (for the Packet Memory) */
-#define REG_BIST0_CTRL			0x141C
-#define BIST0_NOW			0x1
-#define BIST0_SRAM_FAIL			0x2
-#define BIST0_FUSE_FLAG			0x4
-#define REG_BIST1_CTRL			0x1420
-#define BIST1_NOW			0x1
-#define BIST1_SRAM_FAIL			0x2
-#define BIST1_FUSE_FLAG			0x4
-
-/* SerDes Lock Detect Control and Status Register */
-#define REG_SERDES_LOCK			0x1424
-#define SERDES_LOCK_DETECT		1
-#define SERDES_LOCK_DETECT_EN		2
-
-/* MAC Control Register */
-#define REG_MAC_CTRL			0x1480
-#define MAC_CTRL_TX_EN			1
-#define MAC_CTRL_RX_EN			2
-#define MAC_CTRL_TX_FLOW		4
-#define MAC_CTRL_RX_FLOW		8
-#define MAC_CTRL_LOOPBACK		0x10
-#define MAC_CTRL_DUPLX			0x20
-#define MAC_CTRL_ADD_CRC		0x40
-#define MAC_CTRL_PAD			0x80
-#define MAC_CTRL_LENCHK			0x100
-#define MAC_CTRL_HUGE_EN		0x200
-#define MAC_CTRL_PRMLEN_SHIFT		10
-#define MAC_CTRL_PRMLEN_MASK		0xF
-#define MAC_CTRL_RMV_VLAN		0x4000
-#define MAC_CTRL_PROMIS_EN		0x8000
-#define MAC_CTRL_MC_ALL_EN		0x2000000
-#define MAC_CTRL_BC_EN			0x4000000
-
-/* MAC IPG/IFG Control Register */
-#define REG_MAC_IPG_IFG			0x1484
-#define MAC_IPG_IFG_IPGT_SHIFT		0
-#define MAC_IPG_IFG_IPGT_MASK		0x7F
-#define MAC_IPG_IFG_MIFG_SHIFT		8
-#define MAC_IPG_IFG_MIFG_MASK		0xFF
-#define MAC_IPG_IFG_IPGR1_SHIFT		16
-#define MAC_IPG_IFG_IPGR1_MASK		0x7F
-#define MAC_IPG_IFG_IPGR2_SHIFT		24
-#define MAC_IPG_IFG_IPGR2_MASK		0x7F
-
-/* MAC STATION ADDRESS */
-#define REG_MAC_STA_ADDR		0x1488
-
-/* Hash table for multicast address */
-#define REG_RX_HASH_TABLE		0x1490
-
-/* MAC Half-Duplex Control Register */
-#define REG_MAC_HALF_DUPLX_CTRL			0x1498
-#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT		0
-#define MAC_HALF_DUPLX_CTRL_LCOL_MASK		0x3FF
-#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT		12
-#define MAC_HALF_DUPLX_CTRL_RETRY_MASK		0xF
-#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN		0x10000
-#define MAC_HALF_DUPLX_CTRL_NO_BACK_C		0x20000
-#define MAC_HALF_DUPLX_CTRL_NO_BACK_P		0x40000
-#define MAC_HALF_DUPLX_CTRL_ABEBE		0x80000
-#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT		20
-#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK		0xF
-#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT	24
-#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK		0xF
-
-/* Maximum Frame Length Control Register */
-#define REG_MTU				0x149C
-
-/* Wake-On-Lan control register */
-#define REG_WOL_CTRL			0x14A0
-#define WOL_PATTERN_EN			0x1
-#define WOL_PATTERN_PME_EN		0x2
-#define WOL_MAGIC_EN			0x4
-#define WOL_MAGIC_PME_EN		0x8
-#define WOL_LINK_CHG_EN			0x10
-#define WOL_LINK_CHG_PME_EN		0x20
-#define WOL_PATTERN_ST			0x100
-#define WOL_MAGIC_ST			0x200
-#define WOL_LINKCHG_ST			0x400
-#define WOL_PT0_EN			0x10000
-#define WOL_PT1_EN			0x20000
-#define WOL_PT2_EN			0x40000
-#define WOL_PT3_EN			0x80000
-#define WOL_PT4_EN			0x100000
-#define WOL_PT0_MATCH			0x1000000
-#define WOL_PT1_MATCH			0x2000000
-#define WOL_PT2_MATCH			0x4000000
-#define WOL_PT3_MATCH			0x8000000
-#define WOL_PT4_MATCH			0x10000000
-
-/* Internal SRAM Partition Register, high 32 bits */
-#define REG_SRAM_RFD_ADDR		0x1500
-
-/* Descriptor Control register, high 32 bits */
-#define REG_DESC_BASE_ADDR_HI		0x1540
-
-/* Interrupt Status Register */
-#define REG_ISR				0x1600
-#define ISR_UR_DETECTED			0x1000000
-#define ISR_FERR_DETECTED		0x2000000
-#define ISR_NFERR_DETECTED		0x4000000
-#define ISR_CERR_DETECTED		0x8000000
-#define ISR_PHY_LINKDOWN		0x10000000
-#define ISR_DIS_INT			0x80000000
-
-/* Interrupt Mask Register */
-#define REG_IMR				0x1604
-
-#define REG_RFD_RRD_IDX			0x1800
-#define REG_TPD_IDX			0x1804
-
-/* MII definitions */
-
-/* PHY Common Register */
-#define MII_ATLX_CR			0x09
-#define MII_ATLX_SR			0x0A
-#define MII_ATLX_ESR			0x0F
-#define MII_ATLX_PSCR			0x10
-#define MII_ATLX_PSSR			0x11
-
-/* 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	/* Ext 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 stat 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	/* 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 Dir bit */
-#define MII_AR_REMOTE_FAULT		0x2000	/* Remote Fault detected */
-#define MII_AR_NEXT_PAGE		0x8000	/* Next Page ability support */
-#define MII_AR_SPEED_MASK		0x01E0
-#define MII_AR_DEFAULT_CAP_MASK		0x0DE0
-
-/* 1000BASE-T Control Register */
-#define MII_ATLX_CR_1000T_HD_CAPS	0x0100	/* Adv 1000T HD cap */
-#define MII_ATLX_CR_1000T_FD_CAPS	0x0200	/* Adv 1000T FD cap */
-#define MII_ATLX_CR_1000T_REPEATER_DTE	0x0400	/* 1=Repeater/switch device,
-						 * 0=DTE device */
-#define MII_ATLX_CR_1000T_MS_VALUE	0x0800	/* 1=Config PHY as Master,
-						 * 0=Configure PHY as Slave */
-#define MII_ATLX_CR_1000T_MS_ENABLE	0x1000	/* 1=Man Master/Slave config,
-						 * 0=Auto Master/Slave config
-						 */
-#define MII_ATLX_CR_1000T_TEST_MODE_NORMAL	0x0000	/* Normal Operation */
-#define MII_ATLX_CR_1000T_TEST_MODE_1	0x2000	/* Transmit Waveform test */
-#define MII_ATLX_CR_1000T_TEST_MODE_2	0x4000	/* Master Xmit Jitter test */
-#define MII_ATLX_CR_1000T_TEST_MODE_3	0x6000	/* Slave Xmit Jitter test */
-#define MII_ATLX_CR_1000T_TEST_MODE_4	0x8000	/* Xmitter Distortion test */
-#define MII_ATLX_CR_1000T_SPEED_MASK	0x0300
-#define MII_ATLX_CR_1000T_DEFAULT_CAP_MASK	0x0300
-
-/* 1000BASE-T Status Register */
-#define MII_ATLX_SR_1000T_LP_HD_CAPS	0x0400	/* LP is 1000T HD capable */
-#define MII_ATLX_SR_1000T_LP_FD_CAPS	0x0800	/* LP is 1000T FD capable */
-#define MII_ATLX_SR_1000T_REMOTE_RX_STATUS	0x1000	/* Remote receiver OK */
-#define MII_ATLX_SR_1000T_LOCAL_RX_STATUS	0x2000	/* Local receiver OK */
-#define MII_ATLX_SR_1000T_MS_CONFIG_RES		0x4000	/* 1=Local TX is Master
-							 * 0=Slave
-							 */
-#define MII_ATLX_SR_1000T_MS_CONFIG_FAULT	0x8000	/* Master/Slave config
-							 * fault */
-#define MII_ATLX_SR_1000T_REMOTE_RX_STATUS_SHIFT	12
-#define MII_ATLX_SR_1000T_LOCAL_RX_STATUS_SHIFT		13
-
-/* Extended Status Register */
-#define MII_ATLX_ESR_1000T_HD_CAPS	0x1000	/* 1000T HD capable */
-#define MII_ATLX_ESR_1000T_FD_CAPS	0x2000	/* 1000T FD capable */
-#define MII_ATLX_ESR_1000X_HD_CAPS	0x4000	/* 1000X HD capable */
-#define MII_ATLX_ESR_1000X_FD_CAPS	0x8000	/* 1000X FD capable */
-
-/* ATLX PHY Specific Control Register */
-#define MII_ATLX_PSCR_JABBER_DISABLE	0x0001	/* 1=Jabber Func disabled */
-#define MII_ATLX_PSCR_POLARITY_REVERSAL	0x0002	/* 1=Polarity Reversal enbld */
-#define MII_ATLX_PSCR_SQE_TEST		0x0004	/* 1=SQE Test enabled */
-#define MII_ATLX_PSCR_MAC_POWERDOWN	0x0008
-#define MII_ATLX_PSCR_CLK125_DISABLE	0x0010	/* 1=CLK125 low
-						 * 0=CLK125 toggling
-						 */
-#define MII_ATLX_PSCR_MDI_MANUAL_MODE	0x0000	/* MDI Crossover Mode bits 6:5,
-						 * Manual MDI configuration
-						 */
-#define MII_ATLX_PSCR_MDIX_MANUAL_MODE	0x0020	/* Manual MDIX configuration */
-#define MII_ATLX_PSCR_AUTO_X_1000T	0x0040	/* 1000BASE-T: Auto crossover
-						 * 100BASE-TX/10BASE-T: MDI
-						 * Mode */
-#define MII_ATLX_PSCR_AUTO_X_MODE	0x0060	/* Auto crossover enabled
-						 * all speeds.
-						 */
-#define MII_ATLX_PSCR_10BT_EXT_DIST_ENABLE	0x0080	/* 1=Enable Extended
-							 * 10BASE-T distance
-							 * (Lower 10BASE-T RX
-							 * Threshold)
-							 * 0=Normal 10BASE-T RX
-							 * Threshold
-							 */
-#define MII_ATLX_PSCR_MII_5BIT_ENABLE	0x0100	/* 1=5-Bit interface in
-						 * 100BASE-TX
-						 * 0=MII interface in
-						 * 100BASE-TX
-						 */
-#define MII_ATLX_PSCR_SCRAMBLER_DISABLE	0x0200	/* 1=Scrambler dsbl */
-#define MII_ATLX_PSCR_FORCE_LINK_GOOD	0x0400	/* 1=Force link good */
-#define MII_ATLX_PSCR_ASSERT_CRS_ON_TX	0x0800	/* 1=Assert CRS on Transmit */
-#define MII_ATLX_PSCR_POLARITY_REVERSAL_SHIFT		1
-#define MII_ATLX_PSCR_AUTO_X_MODE_SHIFT			5
-#define MII_ATLX_PSCR_10BT_EXT_DIST_ENABLE_SHIFT	7
-
-/* ATLX PHY Specific Status Register */
-#define MII_ATLX_PSSR_SPD_DPLX_RESOLVED	0x0800	/* 1=Speed & Duplex resolved */
-#define MII_ATLX_PSSR_DPLX		0x2000	/* 1=Duplex 0=Half Duplex */
-#define MII_ATLX_PSSR_SPEED		0xC000	/* Speed, bits 14:15 */
-#define MII_ATLX_PSSR_10MBS		0x0000	/* 00=10Mbs */
-#define MII_ATLX_PSSR_100MBS		0x4000	/* 01=100Mbs */
-#define MII_ATLX_PSSR_1000MBS		0x8000	/* 10=1000Mbs */
-
-#define MII_DBG_ADDR			0x1D
-#define MII_DBG_DATA			0x1E
-
-/* PCI Command Register Bit Definitions */
-#define PCI_REG_COMMAND			0x04	/* PCI Command Register */
-#define CMD_IO_SPACE			0x0001
-#define CMD_MEMORY_SPACE		0x0002
-#define CMD_BUS_MASTER			0x0004
-
-/* Wake Up Filter Control */
-#define ATLX_WUFC_LNKC	0x00000001	/* Link Status Change Wakeup Enable */
-#define ATLX_WUFC_MAG	0x00000002	/* Magic Packet Wakeup Enable */
-#define ATLX_WUFC_EX	0x00000004	/* Directed Exact Wakeup Enable */
-#define ATLX_WUFC_MC	0x00000008	/* Multicast Wakeup Enable */
-#define ATLX_WUFC_BC	0x00000010	/* Broadcast Wakeup Enable */
-
-#define ADVERTISE_10_HALF		0x0001
-#define ADVERTISE_10_FULL		0x0002
-#define ADVERTISE_100_HALF		0x0004
-#define ADVERTISE_100_FULL		0x0008
-#define ADVERTISE_1000_HALF		0x0010
-#define ADVERTISE_1000_FULL		0x0020
-#define AUTONEG_ADVERTISE_10_100_ALL	0x000F	/* All 10/100 speeds */
-#define AUTONEG_ADVERTISE_10_ALL	0x0003	/* 10Mbps Full & Half speeds */
-
-#define PHY_AUTO_NEG_TIME		45	/* 4.5 Seconds */
-#define PHY_FORCE_TIME			20	/* 2.0 Seconds */
-
-/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA */
-#define EEPROM_SUM			0xBABA
-#define NODE_ADDRESS_SIZE		6
-
-struct atlx_spi_flash_dev {
-	const char *manu_name;	/* manufacturer id */
-	/* op-code */
-	u8 cmd_wrsr;
-	u8 cmd_read;
-	u8 cmd_program;
-	u8 cmd_wren;
-	u8 cmd_wrdi;
-	u8 cmd_rdsr;
-	u8 cmd_rdid;
-	u8 cmd_sector_erase;
-	u8 cmd_chip_erase;
-};
-
-#endif /* ATLX_H */
diff -druN linux-libre-3.1-gnu/drivers/net/atlx/Makefile linux-libre-3.2-gnu/drivers/net/atlx/Makefile
--- linux-libre-3.1-gnu/drivers/net/atlx/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atlx/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,3 +0,0 @@
-obj-$(CONFIG_ATL1)	+= atl1.o
-obj-$(CONFIG_ATL2)	+= atl2.o
-
diff -druN linux-libre-3.1-gnu/drivers/net/atp.c linux-libre-3.2-gnu/drivers/net/atp.c
--- linux-libre-3.1-gnu/drivers/net/atp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,940 +0,0 @@
-/* atp.c: Attached (pocket) ethernet adapter driver for linux. */
-/*
-	This is a driver for commonly OEM pocket (parallel port)
-	ethernet adapters based on the Realtek RTL8002 and RTL8012 chips.
-
-	Written 1993-2000 by Donald Becker.
-
-	This software may be used and distributed according to the terms of
-	the GNU General Public License (GPL), incorporated herein by reference.
-	Drivers based on or derived from this code fall under the GPL and must
-	retain the authorship, copyright and license notice.  This file is not
-	a complete program and may only be used when the entire operating
-	system is licensed under the GPL.
-
-	Copyright 1993 United States Government as represented by the Director,
-	National Security Agency.  Copyright 1994-2000 retained by the original
-	author, Donald Becker. The timer-based reset code was supplied in 1995
-	by Bill Carlson, wwc@super.org.
-
-	The author may be reached as becker@scyld.com, or C/O
-	Scyld Computing Corporation
-	410 Severn Ave., Suite 210
-	Annapolis MD 21403
-
-	Support information and updates available at
-	http://www.scyld.com/network/atp.html
-
-
-	Modular support/softnet added by Alan Cox.
-	_bit abuse fixed up by Alan Cox
-
-*/
-
-static const char version[] =
-"atp.c:v1.09=ac 2002/10/01 Donald Becker <becker@scyld.com>\n";
-
-/* The user-configurable values.
-   These may be modified when a driver module is loaded.*/
-
-static int debug = 1; 			/* 1 normal messages, 0 quiet .. 7 verbose. */
-#define net_debug debug
-
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 15;
-
-#define NUM_UNITS 2
-/* The standard set of ISA module parameters. */
-static int io[NUM_UNITS];
-static int irq[NUM_UNITS];
-static int xcvr[NUM_UNITS]; 			/* The data transfer mode. */
-
-/* Operational parameters that are set at compile time. */
-
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  (400*HZ/1000)
-
-/*
-	This file is a device driver for the RealTek (aka AT-Lan-Tec) pocket
-	ethernet adapter.  This is a common low-cost OEM pocket ethernet
-	adapter, sold under many names.
-
-  Sources:
-	This driver was written from the packet driver assembly code provided by
-	Vincent Bono of AT-Lan-Tec.	 Ever try to figure out how a complicated
-	device works just from the assembly code?  It ain't pretty.  The following
-	description is written based on guesses and writing lots of special-purpose
-	code to test my theorized operation.
-
-	In 1997 Realtek made available the documentation for the second generation
-	RTL8012 chip, which has lead to several driver improvements.
-	  http://www.realtek.com.tw/
-
-					Theory of Operation
-
-	The RTL8002 adapter seems to be built around a custom spin of the SEEQ
-	controller core.  It probably has a 16K or 64K internal packet buffer, of
-	which the first 4K is devoted to transmit and the rest to receive.
-	The controller maintains the queue of received packet and the packet buffer
-	access pointer internally, with only 'reset to beginning' and 'skip to next
-	packet' commands visible.  The transmit packet queue holds two (or more?)
-	packets: both 'retransmit this packet' (due to collision) and 'transmit next
-	packet' commands must be started by hand.
-
-	The station address is stored in a standard bit-serial EEPROM which must be
-	read (ughh) by the device driver.  (Provisions have been made for
-	substituting a 74S288 PROM, but I haven't gotten reports of any models
-	using it.)  Unlike built-in devices, a pocket adapter can temporarily lose
-	power without indication to the device driver.  The major effect is that
-	the station address, receive filter (promiscuous, etc.) and transceiver
-	must be reset.
-
-	The controller itself has 16 registers, some of which use only the lower
-	bits.  The registers are read and written 4 bits at a time.  The four bit
-	register address is presented on the data lines along with a few additional
-	timing and control bits.  The data is then read from status port or written
-	to the data port.
-
-	Correction: the controller has two banks of 16 registers.  The second
-	bank contains only the multicast filter table (now used) and the EEPROM
-	access registers.
-
-	Since the bulk data transfer of the actual packets through the slow
-	parallel port dominates the driver's running time, four distinct data
-	(non-register) transfer modes are provided by the adapter, two in each
-	direction.  In the first mode timing for the nibble transfers is
-	provided through the data port.  In the second mode the same timing is
-	provided through the control port.  In either case the data is read from
-	the status port and written to the data port, just as it is accessing
-	registers.
-
-	In addition to the basic data transfer methods, several more are modes are
-	created by adding some delay by doing multiple reads of the data to allow
-	it to stabilize.  This delay seems to be needed on most machines.
-
-	The data transfer mode is stored in the 'dev->if_port' field.  Its default
-	value is '4'.  It may be overridden at boot-time using the third parameter
-	to the "ether=..." initialization.
-
-	The header file <atp.h> provides inline functions that encapsulate the
-	register and data access methods.  These functions are hand-tuned to
-	generate reasonable object code.  This header file also documents my
-	interpretations of the device registers.
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/crc32.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#include "atp.h"
-
-MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
-MODULE_DESCRIPTION("RealTek RTL8002/8012 parallel port Ethernet driver");
-MODULE_LICENSE("GPL");
-
-module_param(max_interrupt_work, int, 0);
-module_param(debug, int, 0);
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(xcvr, int, NULL, 0);
-MODULE_PARM_DESC(max_interrupt_work, "ATP maximum events handled per interrupt");
-MODULE_PARM_DESC(debug, "ATP debug level (0-7)");
-MODULE_PARM_DESC(io, "ATP I/O base address(es)");
-MODULE_PARM_DESC(irq, "ATP IRQ number(s)");
-MODULE_PARM_DESC(xcvr, "ATP transceiver(s) (0=internal, 1=external)");
-
-/* The number of low I/O ports used by the ethercard. */
-#define ETHERCARD_TOTAL_SIZE	3
-
-/* Sequence to switch an 8012 from printer mux to ethernet mode. */
-static char mux_8012[] = { 0xff, 0xf7, 0xff, 0xfb, 0xf3, 0xfb, 0xff, 0xf7,};
-
-struct net_local {
-    spinlock_t lock;
-    struct net_device *next_module;
-    struct timer_list timer;	/* Media selection timer. */
-    long last_rx_time;		/* Last Rx, in jiffies, to handle Rx hang. */
-    int saved_tx_size;
-    unsigned int tx_unit_busy:1;
-    unsigned char re_tx,	/* Number of packet retransmissions. */
-		addr_mode,		/* Current Rx filter e.g. promiscuous, etc. */
-		pac_cnt_in_tx_buf,
-		chip_type;
-};
-
-/* This code, written by wwc@super.org, resets the adapter every
-   TIMED_CHECKER ticks.  This recovers from an unknown error which
-   hangs the device. */
-#define TIMED_CHECKER (HZ/4)
-#ifdef TIMED_CHECKER
-#include <linux/timer.h>
-static void atp_timed_checker(unsigned long ignored);
-#endif
-
-/* Index to functions, as function prototypes. */
-
-static int atp_probe1(long ioaddr);
-static void get_node_ID(struct net_device *dev);
-static unsigned short eeprom_op(long ioaddr, unsigned int cmd);
-static int net_open(struct net_device *dev);
-static void hardware_init(struct net_device *dev);
-static void write_packet(long ioaddr, int length, unsigned char *packet, int pad, int mode);
-static void trigger_send(long ioaddr, int length);
-static netdev_tx_t atp_send_packet(struct sk_buff *skb,
-				   struct net_device *dev);
-static irqreturn_t atp_interrupt(int irq, void *dev_id);
-static void net_rx(struct net_device *dev);
-static void read_block(long ioaddr, int length, unsigned char *buffer, int data_mode);
-static int net_close(struct net_device *dev);
-static void set_rx_mode(struct net_device *dev);
-static void tx_timeout(struct net_device *dev);
-
-
-/* A list of all installed ATP devices, for removing the driver module. */
-static struct net_device *root_atp_dev;
-
-/* Check for a network adapter of this type, and return '0' iff one exists.
-   If dev->base_addr == 0, probe all likely locations.
-   If dev->base_addr == 1, always return failure.
-   If dev->base_addr == 2, allocate space for the device and return success
-   (detachable devices only).
-
-   FIXME: we should use the parport layer for this
-   */
-static int __init atp_init(void)
-{
-	int *port, ports[] = {0x378, 0x278, 0x3bc, 0};
-	int base_addr = io[0];
-
-	if (base_addr > 0x1ff)		/* Check a single specified location. */
-		return atp_probe1(base_addr);
-	else if (base_addr == 1)	/* Don't probe at all. */
-		return -ENXIO;
-
-	for (port = ports; *port; port++) {
-		long ioaddr = *port;
-		outb(0x57, ioaddr + PAR_DATA);
-		if (inb(ioaddr + PAR_DATA) != 0x57)
-			continue;
-		if (atp_probe1(ioaddr) == 0)
-			return 0;
-	}
-
-	return -ENODEV;
-}
-
-static const struct net_device_ops atp_netdev_ops = {
-	.ndo_open		= net_open,
-	.ndo_stop		= net_close,
-	.ndo_start_xmit		= atp_send_packet,
-	.ndo_set_multicast_list = set_rx_mode,
-	.ndo_tx_timeout		= tx_timeout,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-static int __init atp_probe1(long ioaddr)
-{
-	struct net_device *dev = NULL;
-	struct net_local *lp;
-	int saved_ctrl_reg, status, i;
-	int res;
-
-	outb(0xff, ioaddr + PAR_DATA);
-	/* Save the original value of the Control register, in case we guessed
-	   wrong. */
-	saved_ctrl_reg = inb(ioaddr + PAR_CONTROL);
-	if (net_debug > 3)
-		printk("atp: Control register was %#2.2x.\n", saved_ctrl_reg);
-	/* IRQEN=0, SLCTB=high INITB=high, AUTOFDB=high, STBB=high. */
-	outb(0x04, ioaddr + PAR_CONTROL);
-#ifndef final_version
-	if (net_debug > 3) {
-		/* Turn off the printer multiplexer on the 8012. */
-		for (i = 0; i < 8; i++)
-			outb(mux_8012[i], ioaddr + PAR_DATA);
-		write_reg(ioaddr, MODSEL, 0x00);
-		printk("atp: Registers are ");
-		for (i = 0; i < 32; i++)
-			printk(" %2.2x", read_nibble(ioaddr, i));
-		printk(".\n");
-	}
-#endif
-	/* Turn off the printer multiplexer on the 8012. */
-	for (i = 0; i < 8; i++)
-		outb(mux_8012[i], ioaddr + PAR_DATA);
-	write_reg_high(ioaddr, CMR1, CMR1h_RESET);
-	/* udelay() here? */
-	status = read_nibble(ioaddr, CMR1);
-
-	if (net_debug > 3) {
-		printk(KERN_DEBUG "atp: Status nibble was %#2.2x..", status);
-		for (i = 0; i < 32; i++)
-			printk(" %2.2x", read_nibble(ioaddr, i));
-		printk("\n");
-	}
-
-	if ((status & 0x78) != 0x08) {
-		/* The pocket adapter probe failed, restore the control register. */
-		outb(saved_ctrl_reg, ioaddr + PAR_CONTROL);
-		return -ENODEV;
-	}
-	status = read_nibble(ioaddr, CMR2_h);
-	if ((status & 0x78) != 0x10) {
-		outb(saved_ctrl_reg, ioaddr + PAR_CONTROL);
-		return -ENODEV;
-	}
-
-	dev = alloc_etherdev(sizeof(struct net_local));
-	if (!dev)
-		return -ENOMEM;
-
-	/* Find the IRQ used by triggering an interrupt. */
-	write_reg_byte(ioaddr, CMR2, 0x01);			/* No accept mode, IRQ out. */
-	write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE);	/* Enable Tx and Rx. */
-
-	/* Omit autoIRQ routine for now. Use "table lookup" instead.  Uhgggh. */
-	if (irq[0])
-		dev->irq = irq[0];
-	else if (ioaddr == 0x378)
-		dev->irq = 7;
-	else
-		dev->irq = 5;
-	write_reg_high(ioaddr, CMR1, CMR1h_TxRxOFF); /* Disable Tx and Rx units. */
-	write_reg(ioaddr, CMR2, CMR2_NULL);
-
-	dev->base_addr = ioaddr;
-
-	/* Read the station address PROM.  */
-	get_node_ID(dev);
-
-#ifndef MODULE
-	if (net_debug)
-		printk(KERN_INFO "%s", version);
-#endif
-
-	printk(KERN_NOTICE "%s: Pocket adapter found at %#3lx, IRQ %d, "
-	       "SAPROM %pM.\n",
-	       dev->name, dev->base_addr, dev->irq, dev->dev_addr);
-
-	/* Reset the ethernet hardware and activate the printer pass-through. */
-	write_reg_high(ioaddr, CMR1, CMR1h_RESET | CMR1h_MUX);
-
-	lp = netdev_priv(dev);
-	lp->chip_type = RTL8002;
-	lp->addr_mode = CMR2h_Normal;
-	spin_lock_init(&lp->lock);
-
-	/* For the ATP adapter the "if_port" is really the data transfer mode. */
-	if (xcvr[0])
-		dev->if_port = xcvr[0];
-	else
-		dev->if_port = (dev->mem_start & 0xf) ? (dev->mem_start & 0x7) : 4;
-	if (dev->mem_end & 0xf)
-		net_debug = dev->mem_end & 7;
-
-	dev->netdev_ops 	= &atp_netdev_ops;
-	dev->watchdog_timeo	= TX_TIMEOUT;
-
-	res = register_netdev(dev);
-	if (res) {
-		free_netdev(dev);
-		return res;
-	}
-
-	lp->next_module = root_atp_dev;
-	root_atp_dev = dev;
-
-	return 0;
-}
-
-/* Read the station address PROM, usually a word-wide EEPROM. */
-static void __init get_node_ID(struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-	int sa_offset = 0;
-	int i;
-
-	write_reg(ioaddr, CMR2, CMR2_EEPROM);	  /* Point to the EEPROM control registers. */
-
-	/* Some adapters have the station address at offset 15 instead of offset
-	   zero.  Check for it, and fix it if needed. */
-	if (eeprom_op(ioaddr, EE_READ(0)) == 0xffff)
-		sa_offset = 15;
-
-	for (i = 0; i < 3; i++)
-		((__be16 *)dev->dev_addr)[i] =
-			cpu_to_be16(eeprom_op(ioaddr, EE_READ(sa_offset + i)));
-
-	write_reg(ioaddr, CMR2, CMR2_NULL);
-}
-
-/*
-  An EEPROM read command starts by shifting out 0x60+address, and then
-  shifting in the serial data. See the NatSemi databook for details.
- *		   ________________
- * CS : __|
- *			   ___	   ___
- * CLK: ______|	  |___|	  |
- *		 __ _______ _______
- * DI :	 __X_______X_______X
- * DO :	 _________X_______X
- */
-
-static unsigned short __init eeprom_op(long ioaddr, u32 cmd)
-{
-	unsigned eedata_out = 0;
-	int num_bits = EE_CMD_SIZE;
-
-	while (--num_bits >= 0) {
-		char outval = (cmd & (1<<num_bits)) ? EE_DATA_WRITE : 0;
-		write_reg_high(ioaddr, PROM_CMD, outval | EE_CLK_LOW);
-		write_reg_high(ioaddr, PROM_CMD, outval | EE_CLK_HIGH);
-		eedata_out <<= 1;
-		if (read_nibble(ioaddr, PROM_DATA) & EE_DATA_READ)
-			eedata_out++;
-	}
-	write_reg_high(ioaddr, PROM_CMD, EE_CLK_LOW & ~EE_CS);
-	return eedata_out;
-}
-
-
-/* Open/initialize the board.  This is called (in the current kernel)
-   sometime after booting when the 'ifconfig' program is run.
-
-   This routine sets everything up anew at each open, even
-   registers that "should" only need to be set once at boot, so that
-   there is non-reboot way to recover if something goes wrong.
-
-   This is an attachable device: if there is no private entry then it wasn't
-   probed for at boot-time, and we need to probe for it again.
-   */
-static int net_open(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	int ret;
-
-	/* The interrupt line is turned off (tri-stated) when the device isn't in
-	   use.  That's especially important for "attached" interfaces where the
-	   port or interrupt may be shared. */
-	ret = request_irq(dev->irq, atp_interrupt, 0, dev->name, dev);
-	if (ret)
-		return ret;
-
-	hardware_init(dev);
-
-	init_timer(&lp->timer);
-	lp->timer.expires = jiffies + TIMED_CHECKER;
-	lp->timer.data = (unsigned long)dev;
-	lp->timer.function = atp_timed_checker;    /* timer handler */
-	add_timer(&lp->timer);
-
-	netif_start_queue(dev);
-	return 0;
-}
-
-/* This routine resets the hardware.  We initialize everything, assuming that
-   the hardware may have been temporarily detached. */
-static void hardware_init(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-    int i;
-
-	/* Turn off the printer multiplexer on the 8012. */
-	for (i = 0; i < 8; i++)
-		outb(mux_8012[i], ioaddr + PAR_DATA);
-	write_reg_high(ioaddr, CMR1, CMR1h_RESET);
-
-    for (i = 0; i < 6; i++)
-		write_reg_byte(ioaddr, PAR0 + i, dev->dev_addr[i]);
-
-	write_reg_high(ioaddr, CMR2, lp->addr_mode);
-
-	if (net_debug > 2) {
-		printk(KERN_DEBUG "%s: Reset: current Rx mode %d.\n", dev->name,
-			   (read_nibble(ioaddr, CMR2_h) >> 3) & 0x0f);
-	}
-
-    write_reg(ioaddr, CMR2, CMR2_IRQOUT);
-    write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE);
-
-	/* Enable the interrupt line from the serial port. */
-	outb(Ctrl_SelData + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
-
-	/* Unmask the interesting interrupts. */
-    write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
-    write_reg_high(ioaddr, IMR, ISRh_RxErr);
-
-	lp->tx_unit_busy = 0;
-    lp->pac_cnt_in_tx_buf = 0;
-	lp->saved_tx_size = 0;
-}
-
-static void trigger_send(long ioaddr, int length)
-{
-	write_reg_byte(ioaddr, TxCNT0, length & 0xff);
-	write_reg(ioaddr, TxCNT1, length >> 8);
-	write_reg(ioaddr, CMR1, CMR1_Xmit);
-}
-
-static void write_packet(long ioaddr, int length, unsigned char *packet, int pad_len, int data_mode)
-{
-    if (length & 1)
-    {
-    	length++;
-    	pad_len++;
-    }
-
-    outb(EOC+MAR, ioaddr + PAR_DATA);
-    if ((data_mode & 1) == 0) {
-		/* Write the packet out, starting with the write addr. */
-		outb(WrAddr+MAR, ioaddr + PAR_DATA);
-		do {
-			write_byte_mode0(ioaddr, *packet++);
-		} while (--length > pad_len) ;
-		do {
-			write_byte_mode0(ioaddr, 0);
-		} while (--length > 0) ;
-    } else {
-		/* Write the packet out in slow mode. */
-		unsigned char outbyte = *packet++;
-
-		outb(Ctrl_LNibWrite + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
-		outb(WrAddr+MAR, ioaddr + PAR_DATA);
-
-		outb((outbyte & 0x0f)|0x40, ioaddr + PAR_DATA);
-		outb(outbyte & 0x0f, ioaddr + PAR_DATA);
-		outbyte >>= 4;
-		outb(outbyte & 0x0f, ioaddr + PAR_DATA);
-		outb(Ctrl_HNibWrite + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
-		while (--length > pad_len)
-			write_byte_mode1(ioaddr, *packet++);
-		while (--length > 0)
-			write_byte_mode1(ioaddr, 0);
-    }
-    /* Terminate the Tx frame.  End of write: ECB. */
-    outb(0xff, ioaddr + PAR_DATA);
-    outb(Ctrl_HNibWrite | Ctrl_SelData | Ctrl_IRQEN, ioaddr + PAR_CONTROL);
-}
-
-static void tx_timeout(struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-
-	printk(KERN_WARNING "%s: Transmit timed out, %s?\n", dev->name,
-		   inb(ioaddr + PAR_CONTROL) & 0x10 ? "network cable problem"
-		   :  "IRQ conflict");
-	dev->stats.tx_errors++;
-	/* Try to restart the adapter. */
-	hardware_init(dev);
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	netif_wake_queue(dev);
-	dev->stats.tx_errors++;
-}
-
-static netdev_tx_t atp_send_packet(struct sk_buff *skb,
-				   struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	int length;
-	unsigned long flags;
-
-	length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-
-	netif_stop_queue(dev);
-
-	/* Disable interrupts by writing 0x00 to the Interrupt Mask Register.
-	   This sequence must not be interrupted by an incoming packet. */
-
-	spin_lock_irqsave(&lp->lock, flags);
-	write_reg(ioaddr, IMR, 0);
-	write_reg_high(ioaddr, IMR, 0);
-	spin_unlock_irqrestore(&lp->lock, flags);
-
-	write_packet(ioaddr, length, skb->data, length-skb->len, dev->if_port);
-
-	lp->pac_cnt_in_tx_buf++;
-	if (lp->tx_unit_busy == 0) {
-		trigger_send(ioaddr, length);
-		lp->saved_tx_size = 0; 				/* Redundant */
-		lp->re_tx = 0;
-		lp->tx_unit_busy = 1;
-	} else
-		lp->saved_tx_size = length;
-	/* Re-enable the LPT interrupts. */
-	write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
-	write_reg_high(ioaddr, IMR, ISRh_RxErr);
-
-	dev_kfree_skb (skb);
-	return NETDEV_TX_OK;
-}
-
-
-/* The typical workload of the driver:
-   Handle the network interface interrupts. */
-static irqreturn_t atp_interrupt(int irq, void *dev_instance)
-{
-	struct net_device *dev = dev_instance;
-	struct net_local *lp;
-	long ioaddr;
-	static int num_tx_since_rx;
-	int boguscount = max_interrupt_work;
-	int handled = 0;
-
-	ioaddr = dev->base_addr;
-	lp = netdev_priv(dev);
-
-	spin_lock(&lp->lock);
-
-	/* Disable additional spurious interrupts. */
-	outb(Ctrl_SelData, ioaddr + PAR_CONTROL);
-
-	/* The adapter's output is currently the IRQ line, switch it to data. */
-	write_reg(ioaddr, CMR2, CMR2_NULL);
-	write_reg(ioaddr, IMR, 0);
-
-	if (net_debug > 5) printk(KERN_DEBUG "%s: In interrupt ", dev->name);
-    while (--boguscount > 0) {
-		int status = read_nibble(ioaddr, ISR);
-		if (net_debug > 5) printk("loop status %02x..", status);
-
-		if (status & (ISR_RxOK<<3)) {
-			handled = 1;
-			write_reg(ioaddr, ISR, ISR_RxOK); /* Clear the Rx interrupt. */
-			do {
-				int read_status = read_nibble(ioaddr, CMR1);
-				if (net_debug > 6)
-					printk("handling Rx packet %02x..", read_status);
-				/* We acknowledged the normal Rx interrupt, so if the interrupt
-				   is still outstanding we must have a Rx error. */
-				if (read_status & (CMR1_IRQ << 3)) { /* Overrun. */
-					dev->stats.rx_over_errors++;
-					/* Set to no-accept mode long enough to remove a packet. */
-					write_reg_high(ioaddr, CMR2, CMR2h_OFF);
-					net_rx(dev);
-					/* Clear the interrupt and return to normal Rx mode. */
-					write_reg_high(ioaddr, ISR, ISRh_RxErr);
-					write_reg_high(ioaddr, CMR2, lp->addr_mode);
-				} else if ((read_status & (CMR1_BufEnb << 3)) == 0) {
-					net_rx(dev);
-					num_tx_since_rx = 0;
-				} else
-					break;
-			} while (--boguscount > 0);
-		} else if (status & ((ISR_TxErr + ISR_TxOK)<<3)) {
-			handled = 1;
-			if (net_debug > 6)  printk("handling Tx done..");
-			/* Clear the Tx interrupt.  We should check for too many failures
-			   and reinitialize the adapter. */
-			write_reg(ioaddr, ISR, ISR_TxErr + ISR_TxOK);
-			if (status & (ISR_TxErr<<3)) {
-				dev->stats.collisions++;
-				if (++lp->re_tx > 15) {
-					dev->stats.tx_aborted_errors++;
-					hardware_init(dev);
-					break;
-				}
-				/* Attempt to retransmit. */
-				if (net_debug > 6)  printk("attempting to ReTx");
-				write_reg(ioaddr, CMR1, CMR1_ReXmit + CMR1_Xmit);
-			} else {
-				/* Finish up the transmit. */
-				dev->stats.tx_packets++;
-				lp->pac_cnt_in_tx_buf--;
-				if ( lp->saved_tx_size) {
-					trigger_send(ioaddr, lp->saved_tx_size);
-					lp->saved_tx_size = 0;
-					lp->re_tx = 0;
-				} else
-					lp->tx_unit_busy = 0;
-				netif_wake_queue(dev);	/* Inform upper layers. */
-			}
-			num_tx_since_rx++;
-		} else if (num_tx_since_rx > 8 &&
-			   time_after(jiffies, dev->last_rx + HZ)) {
-			if (net_debug > 2)
-				printk(KERN_DEBUG "%s: Missed packet? No Rx after %d Tx and "
-					   "%ld jiffies status %02x  CMR1 %02x.\n", dev->name,
-					   num_tx_since_rx, jiffies - dev->last_rx, status,
-					   (read_nibble(ioaddr, CMR1) >> 3) & 15);
-			dev->stats.rx_missed_errors++;
-			hardware_init(dev);
-			num_tx_since_rx = 0;
-			break;
-		} else
-			break;
-    }
-
-	/* This following code fixes a rare (and very difficult to track down)
-	   problem where the adapter forgets its ethernet address. */
-	{
-		int i;
-		for (i = 0; i < 6; i++)
-			write_reg_byte(ioaddr, PAR0 + i, dev->dev_addr[i]);
-#if 0 && defined(TIMED_CHECKER)
-		mod_timer(&lp->timer, jiffies + TIMED_CHECKER);
-#endif
-	}
-
-	/* Tell the adapter that it can go back to using the output line as IRQ. */
-    write_reg(ioaddr, CMR2, CMR2_IRQOUT);
-	/* Enable the physical interrupt line, which is sure to be low until.. */
-	outb(Ctrl_SelData + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
-	/* .. we enable the interrupt sources. */
-	write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
-	write_reg_high(ioaddr, IMR, ISRh_RxErr); 			/* Hmmm, really needed? */
-
-	spin_unlock(&lp->lock);
-
-	if (net_debug > 5) printk("exiting interrupt.\n");
-	return IRQ_RETVAL(handled);
-}
-
-#ifdef TIMED_CHECKER
-/* This following code fixes a rare (and very difficult to track down)
-   problem where the adapter forgets its ethernet address. */
-static void atp_timed_checker(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *)data;
-	long ioaddr = dev->base_addr;
-	struct net_local *lp = netdev_priv(dev);
-	int tickssofar = jiffies - lp->last_rx_time;
-	int i;
-
-	spin_lock(&lp->lock);
-	if (tickssofar > 2*HZ) {
-#if 1
-		for (i = 0; i < 6; i++)
-			write_reg_byte(ioaddr, PAR0 + i, dev->dev_addr[i]);
-		lp->last_rx_time = jiffies;
-#else
-		for (i = 0; i < 6; i++)
-			if (read_cmd_byte(ioaddr, PAR0 + i) != atp_timed_dev->dev_addr[i])
-				{
-			struct net_local *lp = netdev_priv(atp_timed_dev);
-			write_reg_byte(ioaddr, PAR0 + i, atp_timed_dev->dev_addr[i]);
-			if (i == 2)
-			  dev->stats.tx_errors++;
-			else if (i == 3)
-			  dev->stats.tx_dropped++;
-			else if (i == 4)
-			  dev->stats.collisions++;
-			else
-			  dev->stats.rx_errors++;
-		  }
-#endif
-	}
-	spin_unlock(&lp->lock);
-	lp->timer.expires = jiffies + TIMED_CHECKER;
-	add_timer(&lp->timer);
-}
-#endif
-
-/* We have a good packet(s), get it/them out of the buffers. */
-static void net_rx(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	struct rx_header rx_head;
-
-	/* Process the received packet. */
-	outb(EOC+MAR, ioaddr + PAR_DATA);
-	read_block(ioaddr, 8, (unsigned char*)&rx_head, dev->if_port);
-	if (net_debug > 5)
-		printk(KERN_DEBUG " rx_count %04x %04x %04x %04x..", rx_head.pad,
-			   rx_head.rx_count, rx_head.rx_status, rx_head.cur_addr);
-	if ((rx_head.rx_status & 0x77) != 0x01) {
-		dev->stats.rx_errors++;
-		if (rx_head.rx_status & 0x0004) dev->stats.rx_frame_errors++;
-		else if (rx_head.rx_status & 0x0002) dev->stats.rx_crc_errors++;
-		if (net_debug > 3)
-			printk(KERN_DEBUG "%s: Unknown ATP Rx error %04x.\n",
-				   dev->name, rx_head.rx_status);
-		if  (rx_head.rx_status & 0x0020) {
-			dev->stats.rx_fifo_errors++;
-			write_reg_high(ioaddr, CMR1, CMR1h_TxENABLE);
-			write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE);
-		} else if (rx_head.rx_status & 0x0050)
-			hardware_init(dev);
-		return;
-	} else {
-		/* Malloc up new buffer. The "-4" omits the FCS (CRC). */
-		int pkt_len = (rx_head.rx_count & 0x7ff) - 4;
-		struct sk_buff *skb;
-
-		skb = dev_alloc_skb(pkt_len + 2);
-		if (skb == NULL) {
-			printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n",
-				   dev->name);
-			dev->stats.rx_dropped++;
-			goto done;
-		}
-
-		skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-		read_block(ioaddr, pkt_len, skb_put(skb,pkt_len), dev->if_port);
-		skb->protocol = eth_type_trans(skb, dev);
-		netif_rx(skb);
-		dev->last_rx = jiffies;
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += pkt_len;
-	}
- done:
-	write_reg(ioaddr, CMR1, CMR1_NextPkt);
-	lp->last_rx_time = jiffies;
-}
-
-static void read_block(long ioaddr, int length, unsigned char *p, int data_mode)
-{
-	if (data_mode <= 3) { /* Mode 0 or 1 */
-		outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL);
-		outb(length == 8  ?  RdAddr | HNib | MAR  :  RdAddr | MAR,
-			 ioaddr + PAR_DATA);
-		if (data_mode <= 1) { /* Mode 0 or 1 */
-			do { *p++ = read_byte_mode0(ioaddr); } while (--length > 0);
-		} else { /* Mode 2 or 3 */
-			do { *p++ = read_byte_mode2(ioaddr); } while (--length > 0);
-		}
-	} else if (data_mode <= 5) {
-		do { *p++ = read_byte_mode4(ioaddr); } while (--length > 0);
-	} else {
-		do { *p++ = read_byte_mode6(ioaddr); } while (--length > 0);
-	}
-
-	outb(EOC+HNib+MAR, ioaddr + PAR_DATA);
-	outb(Ctrl_SelData, ioaddr + PAR_CONTROL);
-}
-
-/* The inverse routine to net_open(). */
-static int
-net_close(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-
-	netif_stop_queue(dev);
-
-	del_timer_sync(&lp->timer);
-
-	/* Flush the Tx and disable Rx here. */
-	lp->addr_mode = CMR2h_OFF;
-	write_reg_high(ioaddr, CMR2, CMR2h_OFF);
-
-	/* Free the IRQ line. */
-	outb(0x00, ioaddr + PAR_CONTROL);
-	free_irq(dev->irq, dev);
-
-	/* Reset the ethernet hardware and activate the printer pass-through. */
-	write_reg_high(ioaddr, CMR1, CMR1h_RESET | CMR1h_MUX);
-	return 0;
-}
-
-/*
- *	Set or clear the multicast filter for this adapter.
- */
-
-static void set_rx_mode_8002(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-
-	if (!netdev_mc_empty(dev) || (dev->flags & (IFF_ALLMULTI|IFF_PROMISC)))
-		lp->addr_mode = CMR2h_PROMISC;
-	else
-		lp->addr_mode = CMR2h_Normal;
-	write_reg_high(ioaddr, CMR2, lp->addr_mode);
-}
-
-static void set_rx_mode_8012(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	unsigned char new_mode, mc_filter[8]; /* Multicast hash filter */
-	int i;
-
-	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
-		new_mode = CMR2h_PROMISC;
-	} else if ((netdev_mc_count(dev) > 1000) ||
-		   (dev->flags & IFF_ALLMULTI)) {
-		/* Too many to filter perfectly -- accept all multicasts. */
-		memset(mc_filter, 0xff, sizeof(mc_filter));
-		new_mode = CMR2h_Normal;
-	} else {
-		struct netdev_hw_addr *ha;
-
-		memset(mc_filter, 0, sizeof(mc_filter));
-		netdev_for_each_mc_addr(ha, dev) {
-			int filterbit = ether_crc_le(ETH_ALEN, ha->addr) & 0x3f;
-			mc_filter[filterbit >> 5] |= 1 << (filterbit & 31);
-		}
-		new_mode = CMR2h_Normal;
-	}
-	lp->addr_mode = new_mode;
-    write_reg(ioaddr, CMR2, CMR2_IRQOUT | 0x04); /* Switch to page 1. */
-    for (i = 0; i < 8; i++)
-		write_reg_byte(ioaddr, i, mc_filter[i]);
-	if (net_debug > 2 || 1) {
-		lp->addr_mode = 1;
-		printk(KERN_DEBUG "%s: Mode %d, setting multicast filter to",
-			   dev->name, lp->addr_mode);
-		for (i = 0; i < 8; i++)
-			printk(" %2.2x", mc_filter[i]);
-		printk(".\n");
-	}
-
-	write_reg_high(ioaddr, CMR2, lp->addr_mode);
-    write_reg(ioaddr, CMR2, CMR2_IRQOUT); /* Switch back to page 0 */
-}
-
-static void set_rx_mode(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-
-	if (lp->chip_type == RTL8002)
-		return set_rx_mode_8002(dev);
-	else
-		return set_rx_mode_8012(dev);
-}
-
-
-static int __init atp_init_module(void) {
-	if (debug)					/* Emit version even if no cards detected. */
-		printk(KERN_INFO "%s", version);
-	return atp_init();
-}
-
-static void __exit atp_cleanup_module(void) {
-	struct net_device *next_dev;
-
-	while (root_atp_dev) {
-		struct net_local *atp_local = netdev_priv(root_atp_dev);
-		next_dev = atp_local->next_module;
-		unregister_netdev(root_atp_dev);
-		/* No need to release_region(), since we never snarf it. */
-		free_netdev(root_atp_dev);
-		root_atp_dev = next_dev;
-	}
-}
-
-module_init(atp_init_module);
-module_exit(atp_cleanup_module);
diff -druN linux-libre-3.1-gnu/drivers/net/atp.h linux-libre-3.2-gnu/drivers/net/atp.h
--- linux-libre-3.1-gnu/drivers/net/atp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/atp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,259 +0,0 @@
-/* Linux header file for the ATP pocket ethernet adapter. */
-/* v1.09 8/9/2000 becker@scyld.com. */
-
-#include <linux/if_ether.h>
-#include <linux/types.h>
-
-/* The header prepended to received packets. */
-struct rx_header {
-    ushort pad;			/* Pad. */
-    ushort rx_count;
-    ushort rx_status;		/* Unknown bit assignments :-<.  */
-    ushort cur_addr;		/* Apparently the current buffer address(?) */
-};
-
-#define PAR_DATA	0
-#define PAR_STATUS	1
-#define PAR_CONTROL 2
-
-enum chip_type { RTL8002, RTL8012 };
-
-#define Ctrl_LNibRead	0x08	/* LP_PSELECP */
-#define Ctrl_HNibRead	0
-#define Ctrl_LNibWrite	0x08	/* LP_PSELECP */
-#define Ctrl_HNibWrite	0
-#define Ctrl_SelData	0x04	/* LP_PINITP */
-#define Ctrl_IRQEN	0x10	/* LP_PINTEN */
-
-#define EOW	0xE0
-#define EOC	0xE0
-#define WrAddr	0x40	/* Set address of EPLC read, write register. */
-#define RdAddr	0xC0
-#define HNib	0x10
-
-enum page0_regs
-{
-    /* The first six registers hold the ethernet physical station address. */
-    PAR0 = 0, PAR1 = 1, PAR2 = 2, PAR3 = 3, PAR4 = 4, PAR5 = 5,
-    TxCNT0 = 6, TxCNT1 = 7,		/* The transmit byte count. */
-    TxSTAT = 8, RxSTAT = 9,		/* Tx and Rx status. */
-    ISR = 10, IMR = 11,			/* Interrupt status and mask. */
-    CMR1 = 12,				/* Command register 1. */
-    CMR2 = 13,				/* Command register 2. */
-    MODSEL = 14,			/* Mode select register. */
-    MAR = 14,				/* Memory address register (?). */
-    CMR2_h = 0x1d, };
-
-enum eepage_regs
-{ PROM_CMD = 6, PROM_DATA = 7 };	/* Note that PROM_CMD is in the "high" bits. */
-
-
-#define ISR_TxOK	0x01
-#define ISR_RxOK	0x04
-#define ISR_TxErr	0x02
-#define ISRh_RxErr	0x11	/* ISR, high nibble */
-
-#define CMR1h_MUX	0x08	/* Select printer multiplexor on 8012. */
-#define CMR1h_RESET	0x04	/* Reset. */
-#define CMR1h_RxENABLE	0x02	/* Rx unit enable.  */
-#define CMR1h_TxENABLE	0x01	/* Tx unit enable.  */
-#define CMR1h_TxRxOFF	0x00
-#define CMR1_ReXmit	0x08	/* Trigger a retransmit. */
-#define CMR1_Xmit	0x04	/* Trigger a transmit. */
-#define	CMR1_IRQ	0x02	/* Interrupt active. */
-#define	CMR1_BufEnb	0x01	/* Enable the buffer(?). */
-#define	CMR1_NextPkt	0x01	/* Enable the buffer(?). */
-
-#define CMR2_NULL	8
-#define CMR2_IRQOUT	9
-#define CMR2_RAMTEST	10
-#define CMR2_EEPROM	12	/* Set to page 1, for reading the EEPROM. */
-
-#define CMR2h_OFF	0	/* No accept mode. */
-#define CMR2h_Physical	1	/* Accept a physical address match only. */
-#define CMR2h_Normal	2	/* Accept physical and broadcast address. */
-#define CMR2h_PROMISC	3	/* Promiscuous mode. */
-
-/* An inline function used below: it differs from inb() by explicitly return an unsigned
-   char, saving a truncation. */
-static inline unsigned char inbyte(unsigned short port)
-{
-    unsigned char _v;
-    __asm__ __volatile__ ("inb %w1,%b0" :"=a" (_v):"d" (port));
-    return _v;
-}
-
-/* Read register OFFSET.
-   This command should always be terminated with read_end(). */
-static inline unsigned char read_nibble(short port, unsigned char offset)
-{
-    unsigned char retval;
-    outb(EOC+offset, port + PAR_DATA);
-    outb(RdAddr+offset, port + PAR_DATA);
-    inbyte(port + PAR_STATUS);		/* Settling time delay */
-    retval = inbyte(port + PAR_STATUS);
-    outb(EOC+offset, port + PAR_DATA);
-
-    return retval;
-}
-
-/* Functions for bulk data read.  The interrupt line is always disabled. */
-/* Get a byte using read mode 0, reading data from the control lines. */
-static inline unsigned char read_byte_mode0(short ioaddr)
-{
-    unsigned char low_nib;
-
-    outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL);
-    inbyte(ioaddr + PAR_STATUS);
-    low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f;
-    outb(Ctrl_HNibRead, ioaddr + PAR_CONTROL);
-    inbyte(ioaddr + PAR_STATUS);	/* Settling time delay -- needed!  */
-    inbyte(ioaddr + PAR_STATUS);	/* Settling time delay -- needed!  */
-    return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0);
-}
-
-/* The same as read_byte_mode0(), but does multiple inb()s for stability. */
-static inline unsigned char read_byte_mode2(short ioaddr)
-{
-    unsigned char low_nib;
-
-    outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL);
-    inbyte(ioaddr + PAR_STATUS);
-    low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f;
-    outb(Ctrl_HNibRead, ioaddr + PAR_CONTROL);
-    inbyte(ioaddr + PAR_STATUS);	/* Settling time delay -- needed!  */
-    return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0);
-}
-
-/* Read a byte through the data register. */
-static inline unsigned char read_byte_mode4(short ioaddr)
-{
-    unsigned char low_nib;
-
-    outb(RdAddr | MAR, ioaddr + PAR_DATA);
-    low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f;
-    outb(RdAddr | HNib | MAR, ioaddr + PAR_DATA);
-    return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0);
-}
-
-/* Read a byte through the data register, double reading to allow settling. */
-static inline unsigned char read_byte_mode6(short ioaddr)
-{
-    unsigned char low_nib;
-
-    outb(RdAddr | MAR, ioaddr + PAR_DATA);
-    inbyte(ioaddr + PAR_STATUS);
-    low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f;
-    outb(RdAddr | HNib | MAR, ioaddr + PAR_DATA);
-    inbyte(ioaddr + PAR_STATUS);
-    return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0);
-}
-
-static inline void
-write_reg(short port, unsigned char reg, unsigned char value)
-{
-    unsigned char outval;
-    outb(EOC | reg, port + PAR_DATA);
-    outval = WrAddr | reg;
-    outb(outval, port + PAR_DATA);
-    outb(outval, port + PAR_DATA);	/* Double write for PS/2. */
-
-    outval &= 0xf0;
-    outval |= value;
-    outb(outval, port + PAR_DATA);
-    outval &= 0x1f;
-    outb(outval, port + PAR_DATA);
-    outb(outval, port + PAR_DATA);
-
-    outb(EOC | outval, port + PAR_DATA);
-}
-
-static inline void
-write_reg_high(short port, unsigned char reg, unsigned char value)
-{
-    unsigned char outval = EOC | HNib | reg;
-
-    outb(outval, port + PAR_DATA);
-    outval &= WrAddr | HNib | 0x0f;
-    outb(outval, port + PAR_DATA);
-    outb(outval, port + PAR_DATA);	/* Double write for PS/2. */
-
-    outval = WrAddr | HNib | value;
-    outb(outval, port + PAR_DATA);
-    outval &= HNib | 0x0f;		/* HNib | value */
-    outb(outval, port + PAR_DATA);
-    outb(outval, port + PAR_DATA);
-
-    outb(EOC | HNib | outval, port + PAR_DATA);
-}
-
-/* Write a byte out using nibble mode.  The low nibble is written first. */
-static inline void
-write_reg_byte(short port, unsigned char reg, unsigned char value)
-{
-    unsigned char outval;
-    outb(EOC | reg, port + PAR_DATA); 	/* Reset the address register. */
-    outval = WrAddr | reg;
-    outb(outval, port + PAR_DATA);
-    outb(outval, port + PAR_DATA);	/* Double write for PS/2. */
-
-    outb((outval & 0xf0) | (value & 0x0f), port + PAR_DATA);
-    outb(value & 0x0f, port + PAR_DATA);
-    value >>= 4;
-    outb(value, port + PAR_DATA);
-    outb(0x10 | value, port + PAR_DATA);
-    outb(0x10 | value, port + PAR_DATA);
-
-    outb(EOC  | value, port + PAR_DATA); 	/* Reset the address register. */
-}
-
-/*
- * Bulk data writes to the packet buffer.  The interrupt line remains enabled.
- * The first, faster method uses only the dataport (data modes 0, 2 & 4).
- * The second (backup) method uses data and control regs (modes 1, 3 & 5).
- * It should only be needed when there is skew between the individual data
- * lines.
- */
-static inline void write_byte_mode0(short ioaddr, unsigned char value)
-{
-    outb(value & 0x0f, ioaddr + PAR_DATA);
-    outb((value>>4) | 0x10, ioaddr + PAR_DATA);
-}
-
-static inline void write_byte_mode1(short ioaddr, unsigned char value)
-{
-    outb(value & 0x0f, ioaddr + PAR_DATA);
-    outb(Ctrl_IRQEN | Ctrl_LNibWrite, ioaddr + PAR_CONTROL);
-    outb((value>>4) | 0x10, ioaddr + PAR_DATA);
-    outb(Ctrl_IRQEN | Ctrl_HNibWrite, ioaddr + PAR_CONTROL);
-}
-
-/* Write 16bit VALUE to the packet buffer: the same as above just doubled. */
-static inline void write_word_mode0(short ioaddr, unsigned short value)
-{
-    outb(value & 0x0f, ioaddr + PAR_DATA);
-    value >>= 4;
-    outb((value & 0x0f) | 0x10, ioaddr + PAR_DATA);
-    value >>= 4;
-    outb(value & 0x0f, ioaddr + PAR_DATA);
-    value >>= 4;
-    outb((value & 0x0f) | 0x10, ioaddr + PAR_DATA);
-}
-
-/*  EEPROM_Ctrl bits. */
-#define EE_SHIFT_CLK	0x04	/* EEPROM shift clock. */
-#define EE_CS		0x02	/* EEPROM chip select. */
-#define EE_CLK_HIGH	0x12
-#define EE_CLK_LOW	0x16
-#define EE_DATA_WRITE	0x01	/* EEPROM chip data in. */
-#define EE_DATA_READ	0x08	/* EEPROM chip data out. */
-
-/* Delay between EEPROM clock transitions. */
-#define eeprom_delay(ticks) \
-do { int _i = 40; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
-
-/* The EEPROM commands include the alway-set leading bit. */
-#define EE_WRITE_CMD(offset)	(((5 << 6) + (offset)) << 17)
-#define EE_READ(offset) 	(((6 << 6) + (offset)) << 17)
-#define EE_ERASE(offset)	(((7 << 6) + (offset)) << 17)
-#define EE_CMD_SIZE	27	/* The command+address+data size. */
diff -druN linux-libre-3.1-gnu/drivers/net/au1000_eth.c linux-libre-3.2-gnu/drivers/net/au1000_eth.c
--- linux-libre-3.1-gnu/drivers/net/au1000_eth.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/au1000_eth.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1332 +0,0 @@
-/*
- *
- * Alchemy Au1x00 ethernet driver
- *
- * Copyright 2001-2003, 2006 MontaVista Software Inc.
- * Copyright 2002 TimeSys Corp.
- * Added ethtool/mii-tool support,
- * Copyright 2004 Matt Porter <mporter@kernel.crashing.org>
- * Update: 2004 Bjoern Riemer, riemer@fokus.fraunhofer.de
- * or riemer@riemer-nt.de: fixed the link beat detection with
- * ioctls (SIOCGMIIPHY)
- * Copyright 2006 Herbert Valerio Riedel <hvr@gnu.org>
- *  converted to use linux-2.6.x's PHY framework
- *
- * Author: MontaVista Software, Inc.
- *		ppopov@mvista.com or source@mvista.com
- *
- * ########################################################################
- *
- *  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.
- *
- * ########################################################################
- *
- *
- */
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/capability.h>
-#include <linux/dma-mapping.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/errno.h>
-#include <linux/in.h>
-#include <linux/ioport.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
-#include <linux/crc32.h>
-#include <linux/phy.h>
-#include <linux/platform_device.h>
-#include <linux/cpu.h>
-#include <linux/io.h>
-
-#include <asm/mipsregs.h>
-#include <asm/irq.h>
-#include <asm/processor.h>
-
-#include <au1000.h>
-#include <au1xxx_eth.h>
-#include <prom.h>
-
-#include "au1000_eth.h"
-
-#ifdef AU1000_ETH_DEBUG
-static int au1000_debug = 5;
-#else
-static int au1000_debug = 3;
-#endif
-
-#define AU1000_DEF_MSG_ENABLE	(NETIF_MSG_DRV	| \
-				NETIF_MSG_PROBE	| \
-				NETIF_MSG_LINK)
-
-#define DRV_NAME	"au1000_eth"
-#define DRV_VERSION	"1.7"
-#define DRV_AUTHOR	"Pete Popov <ppopov@embeddedalley.com>"
-#define DRV_DESC	"Au1xxx on-chip Ethernet driver"
-
-MODULE_AUTHOR(DRV_AUTHOR);
-MODULE_DESCRIPTION(DRV_DESC);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-
-/*
- * Theory of operation
- *
- * The Au1000 MACs use a simple rx and tx descriptor ring scheme.
- * There are four receive and four transmit descriptors.  These
- * descriptors are not in memory; rather, they are just a set of
- * hardware registers.
- *
- * Since the Au1000 has a coherent data cache, the receive and
- * transmit buffers are allocated from the KSEG0 segment. The
- * hardware registers, however, are still mapped at KSEG1 to
- * make sure there's no out-of-order writes, and that all writes
- * complete immediately.
- */
-
-/*
- * board-specific configurations
- *
- * PHY detection algorithm
- *
- * If phy_static_config is undefined, the PHY setup is
- * autodetected:
- *
- * mii_probe() first searches the current MAC's MII bus for a PHY,
- * selecting the first (or last, if phy_search_highest_addr is
- * defined) PHY address not already claimed by another netdev.
- *
- * If nothing was found that way when searching for the 2nd ethernet
- * controller's PHY and phy1_search_mac0 is defined, then
- * the first MII bus is searched as well for an unclaimed PHY; this is
- * needed in case of a dual-PHY accessible only through the MAC0's MII
- * bus.
- *
- * Finally, if no PHY is found, then the corresponding ethernet
- * controller is not registered to the network subsystem.
- */
-
-/* autodetection defaults: phy1_search_mac0 */
-
-/* static PHY setup
- *
- * most boards PHY setup should be detectable properly with the
- * autodetection algorithm in mii_probe(), but in some cases (e.g. if
- * you have a switch attached, or want to use the PHY's interrupt
- * notification capabilities) you can provide a static PHY
- * configuration here
- *
- * IRQs may only be set, if a PHY address was configured
- * If a PHY address is given, also a bus id is required to be set
- *
- * ps: make sure the used irqs are configured properly in the board
- * specific irq-map
- */
-
-static void au1000_enable_mac(struct net_device *dev, int force_reset)
-{
-	unsigned long flags;
-	struct au1000_private *aup = netdev_priv(dev);
-
-	spin_lock_irqsave(&aup->lock, flags);
-
-	if (force_reset || (!aup->mac_enabled)) {
-		writel(MAC_EN_CLOCK_ENABLE, aup->enable);
-		au_sync_delay(2);
-		writel((MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
-				| MAC_EN_CLOCK_ENABLE), aup->enable);
-		au_sync_delay(2);
-
-		aup->mac_enabled = 1;
-	}
-
-	spin_unlock_irqrestore(&aup->lock, flags);
-}
-
-/*
- * MII operations
- */
-static int au1000_mdio_read(struct net_device *dev, int phy_addr, int reg)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-	u32 *const mii_control_reg = &aup->mac->mii_control;
-	u32 *const mii_data_reg = &aup->mac->mii_data;
-	u32 timedout = 20;
-	u32 mii_control;
-
-	while (readl(mii_control_reg) & MAC_MII_BUSY) {
-		mdelay(1);
-		if (--timedout == 0) {
-			netdev_err(dev, "read_MII busy timeout!!\n");
-			return -1;
-		}
-	}
-
-	mii_control = MAC_SET_MII_SELECT_REG(reg) |
-		MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_READ;
-
-	writel(mii_control, mii_control_reg);
-
-	timedout = 20;
-	while (readl(mii_control_reg) & MAC_MII_BUSY) {
-		mdelay(1);
-		if (--timedout == 0) {
-			netdev_err(dev, "mdio_read busy timeout!!\n");
-			return -1;
-		}
-	}
-	return readl(mii_data_reg);
-}
-
-static void au1000_mdio_write(struct net_device *dev, int phy_addr,
-			      int reg, u16 value)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-	u32 *const mii_control_reg = &aup->mac->mii_control;
-	u32 *const mii_data_reg = &aup->mac->mii_data;
-	u32 timedout = 20;
-	u32 mii_control;
-
-	while (readl(mii_control_reg) & MAC_MII_BUSY) {
-		mdelay(1);
-		if (--timedout == 0) {
-			netdev_err(dev, "mdio_write busy timeout!!\n");
-			return;
-		}
-	}
-
-	mii_control = MAC_SET_MII_SELECT_REG(reg) |
-		MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_WRITE;
-
-	writel(value, mii_data_reg);
-	writel(mii_control, mii_control_reg);
-}
-
-static int au1000_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
-{
-	/* WARNING: bus->phy_map[phy_addr].attached_dev == dev does
-	 * _NOT_ hold (e.g. when PHY is accessed through other MAC's MII bus)
-	 */
-	struct net_device *const dev = bus->priv;
-
-	/* make sure the MAC associated with this
-	 * mii_bus is enabled
-	 */
-	au1000_enable_mac(dev, 0);
-
-	return au1000_mdio_read(dev, phy_addr, regnum);
-}
-
-static int au1000_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
-				u16 value)
-{
-	struct net_device *const dev = bus->priv;
-
-	/* make sure the MAC associated with this
-	 * mii_bus is enabled
-	 */
-	au1000_enable_mac(dev, 0);
-
-	au1000_mdio_write(dev, phy_addr, regnum, value);
-	return 0;
-}
-
-static int au1000_mdiobus_reset(struct mii_bus *bus)
-{
-	struct net_device *const dev = bus->priv;
-
-	/* make sure the MAC associated with this
-	 * mii_bus is enabled
-	 */
-	au1000_enable_mac(dev, 0);
-
-	return 0;
-}
-
-static void au1000_hard_stop(struct net_device *dev)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-	u32 reg;
-
-	netif_dbg(aup, drv, dev, "hard stop\n");
-
-	reg = readl(&aup->mac->control);
-	reg &= ~(MAC_RX_ENABLE | MAC_TX_ENABLE);
-	writel(reg, &aup->mac->control);
-	au_sync_delay(10);
-}
-
-static void au1000_enable_rx_tx(struct net_device *dev)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-	u32 reg;
-
-	netif_dbg(aup, hw, dev, "enable_rx_tx\n");
-
-	reg = readl(&aup->mac->control);
-	reg |= (MAC_RX_ENABLE | MAC_TX_ENABLE);
-	writel(reg, &aup->mac->control);
-	au_sync_delay(10);
-}
-
-static void
-au1000_adjust_link(struct net_device *dev)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-	struct phy_device *phydev = aup->phy_dev;
-	unsigned long flags;
-	u32 reg;
-
-	int status_change = 0;
-
-	BUG_ON(!aup->phy_dev);
-
-	spin_lock_irqsave(&aup->lock, flags);
-
-	if (phydev->link && (aup->old_speed != phydev->speed)) {
-		/* speed changed */
-
-		switch (phydev->speed) {
-		case SPEED_10:
-		case SPEED_100:
-			break;
-		default:
-			netdev_warn(dev, "Speed (%d) is not 10/100 ???\n",
-							phydev->speed);
-			break;
-		}
-
-		aup->old_speed = phydev->speed;
-
-		status_change = 1;
-	}
-
-	if (phydev->link && (aup->old_duplex != phydev->duplex)) {
-		/* duplex mode changed */
-
-		/* switching duplex mode requires to disable rx and tx! */
-		au1000_hard_stop(dev);
-
-		reg = readl(&aup->mac->control);
-		if (DUPLEX_FULL == phydev->duplex) {
-			reg |= MAC_FULL_DUPLEX;
-			reg &= ~MAC_DISABLE_RX_OWN;
-		} else {
-			reg &= ~MAC_FULL_DUPLEX;
-			reg |= MAC_DISABLE_RX_OWN;
-		}
-		writel(reg, &aup->mac->control);
-		au_sync_delay(1);
-
-		au1000_enable_rx_tx(dev);
-		aup->old_duplex = phydev->duplex;
-
-		status_change = 1;
-	}
-
-	if (phydev->link != aup->old_link) {
-		/* link state changed */
-
-		if (!phydev->link) {
-			/* link went down */
-			aup->old_speed = 0;
-			aup->old_duplex = -1;
-		}
-
-		aup->old_link = phydev->link;
-		status_change = 1;
-	}
-
-	spin_unlock_irqrestore(&aup->lock, flags);
-
-	if (status_change) {
-		if (phydev->link)
-			netdev_info(dev, "link up (%d/%s)\n",
-			       phydev->speed,
-			       DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
-		else
-			netdev_info(dev, "link down\n");
-	}
-}
-
-static int au1000_mii_probe(struct net_device *dev)
-{
-	struct au1000_private *const aup = netdev_priv(dev);
-	struct phy_device *phydev = NULL;
-	int phy_addr;
-
-	if (aup->phy_static_config) {
-		BUG_ON(aup->mac_id < 0 || aup->mac_id > 1);
-
-		if (aup->phy_addr)
-			phydev = aup->mii_bus->phy_map[aup->phy_addr];
-		else
-			netdev_info(dev, "using PHY-less setup\n");
-		return 0;
-	}
-
-	/* find the first (lowest address) PHY
-	 * on the current MAC's MII bus
-	 */
-	for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++)
-		if (aup->mii_bus->phy_map[phy_addr]) {
-			phydev = aup->mii_bus->phy_map[phy_addr];
-			if (!aup->phy_search_highest_addr)
-				/* break out with first one found */
-				break;
-		}
-
-	if (aup->phy1_search_mac0) {
-		/* try harder to find a PHY */
-		if (!phydev && (aup->mac_id == 1)) {
-			/* no PHY found, maybe we have a dual PHY? */
-			dev_info(&dev->dev, ": no PHY found on MAC1, "
-				"let's see if it's attached to MAC0...\n");
-
-			/* find the first (lowest address) non-attached
-			 * PHY on the MAC0 MII bus
-			 */
-			for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
-				struct phy_device *const tmp_phydev =
-					aup->mii_bus->phy_map[phy_addr];
-
-				if (aup->mac_id == 1)
-					break;
-
-				/* no PHY here... */
-				if (!tmp_phydev)
-					continue;
-
-				/* already claimed by MAC0 */
-				if (tmp_phydev->attached_dev)
-					continue;
-
-				phydev = tmp_phydev;
-				break; /* found it */
-			}
-		}
-	}
-
-	if (!phydev) {
-		netdev_err(dev, "no PHY found\n");
-		return -1;
-	}
-
-	/* now we are supposed to have a proper phydev, to attach to... */
-	BUG_ON(phydev->attached_dev);
-
-	phydev = phy_connect(dev, dev_name(&phydev->dev), &au1000_adjust_link,
-			0, PHY_INTERFACE_MODE_MII);
-
-	if (IS_ERR(phydev)) {
-		netdev_err(dev, "Could not attach to PHY\n");
-		return PTR_ERR(phydev);
-	}
-
-	/* mask with MAC supported features */
-	phydev->supported &= (SUPPORTED_10baseT_Half
-			      | SUPPORTED_10baseT_Full
-			      | SUPPORTED_100baseT_Half
-			      | SUPPORTED_100baseT_Full
-			      | SUPPORTED_Autoneg
-			      /* | SUPPORTED_Pause | SUPPORTED_Asym_Pause */
-			      | SUPPORTED_MII
-			      | SUPPORTED_TP);
-
-	phydev->advertising = phydev->supported;
-
-	aup->old_link = 0;
-	aup->old_speed = 0;
-	aup->old_duplex = -1;
-	aup->phy_dev = phydev;
-
-	netdev_info(dev, "attached PHY driver [%s] "
-	       "(mii_bus:phy_addr=%s, irq=%d)\n",
-	       phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
-
-	return 0;
-}
-
-
-/*
- * Buffer allocation/deallocation routines. The buffer descriptor returned
- * has the virtual and dma address of a buffer suitable for
- * both, receive and transmit operations.
- */
-static struct db_dest *au1000_GetFreeDB(struct au1000_private *aup)
-{
-	struct db_dest *pDB;
-	pDB = aup->pDBfree;
-
-	if (pDB)
-		aup->pDBfree = pDB->pnext;
-
-	return pDB;
-}
-
-void au1000_ReleaseDB(struct au1000_private *aup, struct db_dest *pDB)
-{
-	struct db_dest *pDBfree = aup->pDBfree;
-	if (pDBfree)
-		pDBfree->pnext = pDB;
-	aup->pDBfree = pDB;
-}
-
-static void au1000_reset_mac_unlocked(struct net_device *dev)
-{
-	struct au1000_private *const aup = netdev_priv(dev);
-	int i;
-
-	au1000_hard_stop(dev);
-
-	writel(MAC_EN_CLOCK_ENABLE, aup->enable);
-	au_sync_delay(2);
-	writel(0, aup->enable);
-	au_sync_delay(2);
-
-	aup->tx_full = 0;
-	for (i = 0; i < NUM_RX_DMA; i++) {
-		/* reset control bits */
-		aup->rx_dma_ring[i]->buff_stat &= ~0xf;
-	}
-	for (i = 0; i < NUM_TX_DMA; i++) {
-		/* reset control bits */
-		aup->tx_dma_ring[i]->buff_stat &= ~0xf;
-	}
-
-	aup->mac_enabled = 0;
-
-}
-
-static void au1000_reset_mac(struct net_device *dev)
-{
-	struct au1000_private *const aup = netdev_priv(dev);
-	unsigned long flags;
-
-	netif_dbg(aup, hw, dev, "reset mac, aup %x\n",
-					(unsigned)aup);
-
-	spin_lock_irqsave(&aup->lock, flags);
-
-	au1000_reset_mac_unlocked(dev);
-
-	spin_unlock_irqrestore(&aup->lock, flags);
-}
-
-/*
- * Setup the receive and transmit "rings".  These pointers are the addresses
- * of the rx and tx MAC DMA registers so they are fixed by the hardware --
- * these are not descriptors sitting in memory.
- */
-static void
-au1000_setup_hw_rings(struct au1000_private *aup, u32 rx_base, u32 tx_base)
-{
-	int i;
-
-	for (i = 0; i < NUM_RX_DMA; i++) {
-		aup->rx_dma_ring[i] =
-			(struct rx_dma *)
-					(rx_base + sizeof(struct rx_dma)*i);
-	}
-	for (i = 0; i < NUM_TX_DMA; i++) {
-		aup->tx_dma_ring[i] =
-			(struct tx_dma *)
-					(tx_base + sizeof(struct tx_dma)*i);
-	}
-}
-
-/*
- * ethtool operations
- */
-
-static int au1000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-
-	if (aup->phy_dev)
-		return phy_ethtool_gset(aup->phy_dev, cmd);
-
-	return -EINVAL;
-}
-
-static int au1000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	if (aup->phy_dev)
-		return phy_ethtool_sset(aup->phy_dev, cmd);
-
-	return -EINVAL;
-}
-
-static void
-au1000_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-	info->fw_version[0] = '\0';
-	sprintf(info->bus_info, "%s %d", DRV_NAME, aup->mac_id);
-	info->regdump_len = 0;
-}
-
-static void au1000_set_msglevel(struct net_device *dev, u32 value)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-	aup->msg_enable = value;
-}
-
-static u32 au1000_get_msglevel(struct net_device *dev)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-	return aup->msg_enable;
-}
-
-static const struct ethtool_ops au1000_ethtool_ops = {
-	.get_settings = au1000_get_settings,
-	.set_settings = au1000_set_settings,
-	.get_drvinfo = au1000_get_drvinfo,
-	.get_link = ethtool_op_get_link,
-	.get_msglevel = au1000_get_msglevel,
-	.set_msglevel = au1000_set_msglevel,
-};
-
-
-/*
- * Initialize the interface.
- *
- * When the device powers up, the clocks are disabled and the
- * mac is in reset state.  When the interface is closed, we
- * do the same -- reset the device and disable the clocks to
- * conserve power. Thus, whenever au1000_init() is called,
- * the device should already be in reset state.
- */
-static int au1000_init(struct net_device *dev)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-	unsigned long flags;
-	int i;
-	u32 control;
-
-	netif_dbg(aup, hw, dev, "au1000_init\n");
-
-	/* bring the device out of reset */
-	au1000_enable_mac(dev, 1);
-
-	spin_lock_irqsave(&aup->lock, flags);
-
-	writel(0, &aup->mac->control);
-	aup->tx_head = (aup->tx_dma_ring[0]->buff_stat & 0xC) >> 2;
-	aup->tx_tail = aup->tx_head;
-	aup->rx_head = (aup->rx_dma_ring[0]->buff_stat & 0xC) >> 2;
-
-	writel(dev->dev_addr[5]<<8 | dev->dev_addr[4],
-					&aup->mac->mac_addr_high);
-	writel(dev->dev_addr[3]<<24 | dev->dev_addr[2]<<16 |
-		dev->dev_addr[1]<<8 | dev->dev_addr[0],
-					&aup->mac->mac_addr_low);
-
-
-	for (i = 0; i < NUM_RX_DMA; i++)
-		aup->rx_dma_ring[i]->buff_stat |= RX_DMA_ENABLE;
-
-	au_sync();
-
-	control = MAC_RX_ENABLE | MAC_TX_ENABLE;
-#ifndef CONFIG_CPU_LITTLE_ENDIAN
-	control |= MAC_BIG_ENDIAN;
-#endif
-	if (aup->phy_dev) {
-		if (aup->phy_dev->link && (DUPLEX_FULL == aup->phy_dev->duplex))
-			control |= MAC_FULL_DUPLEX;
-		else
-			control |= MAC_DISABLE_RX_OWN;
-	} else { /* PHY-less op, assume full-duplex */
-		control |= MAC_FULL_DUPLEX;
-	}
-
-	writel(control, &aup->mac->control);
-	writel(0x8100, &aup->mac->vlan1_tag); /* activate vlan support */
-	au_sync();
-
-	spin_unlock_irqrestore(&aup->lock, flags);
-	return 0;
-}
-
-static inline void au1000_update_rx_stats(struct net_device *dev, u32 status)
-{
-	struct net_device_stats *ps = &dev->stats;
-
-	ps->rx_packets++;
-	if (status & RX_MCAST_FRAME)
-		ps->multicast++;
-
-	if (status & RX_ERROR) {
-		ps->rx_errors++;
-		if (status & RX_MISSED_FRAME)
-			ps->rx_missed_errors++;
-		if (status & (RX_OVERLEN | RX_RUNT | RX_LEN_ERROR))
-			ps->rx_length_errors++;
-		if (status & RX_CRC_ERROR)
-			ps->rx_crc_errors++;
-		if (status & RX_COLL)
-			ps->collisions++;
-	} else
-		ps->rx_bytes += status & RX_FRAME_LEN_MASK;
-
-}
-
-/*
- * Au1000 receive routine.
- */
-static int au1000_rx(struct net_device *dev)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-	struct sk_buff *skb;
-	struct rx_dma *prxd;
-	u32 buff_stat, status;
-	struct db_dest *pDB;
-	u32	frmlen;
-
-	netif_dbg(aup, rx_status, dev, "au1000_rx head %d\n", aup->rx_head);
-
-	prxd = aup->rx_dma_ring[aup->rx_head];
-	buff_stat = prxd->buff_stat;
-	while (buff_stat & RX_T_DONE)  {
-		status = prxd->status;
-		pDB = aup->rx_db_inuse[aup->rx_head];
-		au1000_update_rx_stats(dev, status);
-		if (!(status & RX_ERROR))  {
-
-			/* good frame */
-			frmlen = (status & RX_FRAME_LEN_MASK);
-			frmlen -= 4; /* Remove FCS */
-			skb = dev_alloc_skb(frmlen + 2);
-			if (skb == NULL) {
-				netdev_err(dev, "Memory squeeze, dropping packet.\n");
-				dev->stats.rx_dropped++;
-				continue;
-			}
-			skb_reserve(skb, 2);	/* 16 byte IP header align */
-			skb_copy_to_linear_data(skb,
-				(unsigned char *)pDB->vaddr, frmlen);
-			skb_put(skb, frmlen);
-			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);	/* pass the packet to upper layers */
-		} else {
-			if (au1000_debug > 4) {
-				pr_err("rx_error(s):");
-				if (status & RX_MISSED_FRAME)
-					pr_cont(" miss");
-				if (status & RX_WDOG_TIMER)
-					pr_cont(" wdog");
-				if (status & RX_RUNT)
-					pr_cont(" runt");
-				if (status & RX_OVERLEN)
-					pr_cont(" overlen");
-				if (status & RX_COLL)
-					pr_cont(" coll");
-				if (status & RX_MII_ERROR)
-					pr_cont(" mii error");
-				if (status & RX_CRC_ERROR)
-					pr_cont(" crc error");
-				if (status & RX_LEN_ERROR)
-					pr_cont(" len error");
-				if (status & RX_U_CNTRL_FRAME)
-					pr_cont(" u control frame");
-				pr_cont("\n");
-			}
-		}
-		prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE);
-		aup->rx_head = (aup->rx_head + 1) & (NUM_RX_DMA - 1);
-		au_sync();
-
-		/* next descriptor */
-		prxd = aup->rx_dma_ring[aup->rx_head];
-		buff_stat = prxd->buff_stat;
-	}
-	return 0;
-}
-
-static void au1000_update_tx_stats(struct net_device *dev, u32 status)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-	struct net_device_stats *ps = &dev->stats;
-
-	if (status & TX_FRAME_ABORTED) {
-		if (!aup->phy_dev || (DUPLEX_FULL == aup->phy_dev->duplex)) {
-			if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) {
-				/* any other tx errors are only valid
-				 * in half duplex mode
-				 */
-				ps->tx_errors++;
-				ps->tx_aborted_errors++;
-			}
-		} else {
-			ps->tx_errors++;
-			ps->tx_aborted_errors++;
-			if (status & (TX_NO_CARRIER | TX_LOSS_CARRIER))
-				ps->tx_carrier_errors++;
-		}
-	}
-}
-
-/*
- * Called from the interrupt service routine to acknowledge
- * the TX DONE bits.  This is a must if the irq is setup as
- * edge triggered.
- */
-static void au1000_tx_ack(struct net_device *dev)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-	struct tx_dma *ptxd;
-
-	ptxd = aup->tx_dma_ring[aup->tx_tail];
-
-	while (ptxd->buff_stat & TX_T_DONE) {
-		au1000_update_tx_stats(dev, ptxd->status);
-		ptxd->buff_stat &= ~TX_T_DONE;
-		ptxd->len = 0;
-		au_sync();
-
-		aup->tx_tail = (aup->tx_tail + 1) & (NUM_TX_DMA - 1);
-		ptxd = aup->tx_dma_ring[aup->tx_tail];
-
-		if (aup->tx_full) {
-			aup->tx_full = 0;
-			netif_wake_queue(dev);
-		}
-	}
-}
-
-/*
- * Au1000 interrupt service routine.
- */
-static irqreturn_t au1000_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-
-	/* Handle RX interrupts first to minimize chance of overrun */
-
-	au1000_rx(dev);
-	au1000_tx_ack(dev);
-	return IRQ_RETVAL(1);
-}
-
-static int au1000_open(struct net_device *dev)
-{
-	int retval;
-	struct au1000_private *aup = netdev_priv(dev);
-
-	netif_dbg(aup, drv, dev, "open: dev=%p\n", dev);
-
-	retval = request_irq(dev->irq, au1000_interrupt, 0,
-					dev->name, dev);
-	if (retval) {
-		netdev_err(dev, "unable to get IRQ %d\n", dev->irq);
-		return retval;
-	}
-
-	retval = au1000_init(dev);
-	if (retval) {
-		netdev_err(dev, "error in au1000_init\n");
-		free_irq(dev->irq, dev);
-		return retval;
-	}
-
-	if (aup->phy_dev) {
-		/* cause the PHY state machine to schedule a link state check */
-		aup->phy_dev->state = PHY_CHANGELINK;
-		phy_start(aup->phy_dev);
-	}
-
-	netif_start_queue(dev);
-
-	netif_dbg(aup, drv, dev, "open: Initialization done.\n");
-
-	return 0;
-}
-
-static int au1000_close(struct net_device *dev)
-{
-	unsigned long flags;
-	struct au1000_private *const aup = netdev_priv(dev);
-
-	netif_dbg(aup, drv, dev, "close: dev=%p\n", dev);
-
-	if (aup->phy_dev)
-		phy_stop(aup->phy_dev);
-
-	spin_lock_irqsave(&aup->lock, flags);
-
-	au1000_reset_mac_unlocked(dev);
-
-	/* stop the device */
-	netif_stop_queue(dev);
-
-	/* disable the interrupt */
-	free_irq(dev->irq, dev);
-	spin_unlock_irqrestore(&aup->lock, flags);
-
-	return 0;
-}
-
-/*
- * Au1000 transmit routine.
- */
-static netdev_tx_t au1000_tx(struct sk_buff *skb, struct net_device *dev)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-	struct net_device_stats *ps = &dev->stats;
-	struct tx_dma *ptxd;
-	u32 buff_stat;
-	struct db_dest *pDB;
-	int i;
-
-	netif_dbg(aup, tx_queued, dev, "tx: aup %x len=%d, data=%p, head %d\n",
-				(unsigned)aup, skb->len,
-				skb->data, aup->tx_head);
-
-	ptxd = aup->tx_dma_ring[aup->tx_head];
-	buff_stat = ptxd->buff_stat;
-	if (buff_stat & TX_DMA_ENABLE) {
-		/* We've wrapped around and the transmitter is still busy */
-		netif_stop_queue(dev);
-		aup->tx_full = 1;
-		return NETDEV_TX_BUSY;
-	} else if (buff_stat & TX_T_DONE) {
-		au1000_update_tx_stats(dev, ptxd->status);
-		ptxd->len = 0;
-	}
-
-	if (aup->tx_full) {
-		aup->tx_full = 0;
-		netif_wake_queue(dev);
-	}
-
-	pDB = aup->tx_db_inuse[aup->tx_head];
-	skb_copy_from_linear_data(skb, (void *)pDB->vaddr, skb->len);
-	if (skb->len < ETH_ZLEN) {
-		for (i = skb->len; i < ETH_ZLEN; i++)
-			((char *)pDB->vaddr)[i] = 0;
-
-		ptxd->len = ETH_ZLEN;
-	} else
-		ptxd->len = skb->len;
-
-	ps->tx_packets++;
-	ps->tx_bytes += ptxd->len;
-
-	ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE;
-	au_sync();
-	dev_kfree_skb(skb);
-	aup->tx_head = (aup->tx_head + 1) & (NUM_TX_DMA - 1);
-	return NETDEV_TX_OK;
-}
-
-/*
- * The Tx ring has been full longer than the watchdog timeout
- * value. The transmitter must be hung?
- */
-static void au1000_tx_timeout(struct net_device *dev)
-{
-	netdev_err(dev, "au1000_tx_timeout: dev=%p\n", dev);
-	au1000_reset_mac(dev);
-	au1000_init(dev);
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	netif_wake_queue(dev);
-}
-
-static void au1000_multicast_list(struct net_device *dev)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-	u32 reg;
-
-	netif_dbg(aup, drv, dev, "%s: flags=%x\n", __func__, dev->flags);
-	reg = readl(&aup->mac->control);
-	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
-		reg |= MAC_PROMISCUOUS;
-	} else if ((dev->flags & IFF_ALLMULTI)  ||
-			   netdev_mc_count(dev) > MULTICAST_FILTER_LIMIT) {
-		reg |= MAC_PASS_ALL_MULTI;
-		reg &= ~MAC_PROMISCUOUS;
-		netdev_info(dev, "Pass all multicast\n");
-	} else {
-		struct netdev_hw_addr *ha;
-		u32 mc_filter[2];	/* Multicast hash filter */
-
-		mc_filter[1] = mc_filter[0] = 0;
-		netdev_for_each_mc_addr(ha, dev)
-			set_bit(ether_crc(ETH_ALEN, ha->addr)>>26,
-					(long *)mc_filter);
-		writel(mc_filter[1], &aup->mac->multi_hash_high);
-		writel(mc_filter[0], &aup->mac->multi_hash_low);
-		reg &= ~MAC_PROMISCUOUS;
-		reg |= MAC_HASH_MODE;
-	}
-	writel(reg, &aup->mac->control);
-}
-
-static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct au1000_private *aup = netdev_priv(dev);
-
-	if (!netif_running(dev))
-		return -EINVAL;
-
-	if (!aup->phy_dev)
-		return -EINVAL; /* PHY not controllable */
-
-	return phy_mii_ioctl(aup->phy_dev, rq, cmd);
-}
-
-static const struct net_device_ops au1000_netdev_ops = {
-	.ndo_open		= au1000_open,
-	.ndo_stop		= au1000_close,
-	.ndo_start_xmit		= au1000_tx,
-	.ndo_set_multicast_list	= au1000_multicast_list,
-	.ndo_do_ioctl		= au1000_ioctl,
-	.ndo_tx_timeout		= au1000_tx_timeout,
-	.ndo_set_mac_address	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
-};
-
-static int __devinit au1000_probe(struct platform_device *pdev)
-{
-	static unsigned version_printed;
-	struct au1000_private *aup = NULL;
-	struct au1000_eth_platform_data *pd;
-	struct net_device *dev = NULL;
-	struct db_dest *pDB, *pDBfree;
-	int irq, i, err = 0;
-	struct resource *base, *macen;
-
-	base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!base) {
-		dev_err(&pdev->dev, "failed to retrieve base register\n");
-		err = -ENODEV;
-		goto out;
-	}
-
-	macen = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (!macen) {
-		dev_err(&pdev->dev, "failed to retrieve MAC Enable register\n");
-		err = -ENODEV;
-		goto out;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "failed to retrieve IRQ\n");
-		err = -ENODEV;
-		goto out;
-	}
-
-	if (!request_mem_region(base->start, resource_size(base),
-							pdev->name)) {
-		dev_err(&pdev->dev, "failed to request memory region for base registers\n");
-		err = -ENXIO;
-		goto out;
-	}
-
-	if (!request_mem_region(macen->start, resource_size(macen),
-							pdev->name)) {
-		dev_err(&pdev->dev, "failed to request memory region for MAC enable register\n");
-		err = -ENXIO;
-		goto err_request;
-	}
-
-	dev = alloc_etherdev(sizeof(struct au1000_private));
-	if (!dev) {
-		dev_err(&pdev->dev, "alloc_etherdev failed\n");
-		err = -ENOMEM;
-		goto err_alloc;
-	}
-
-	SET_NETDEV_DEV(dev, &pdev->dev);
-	platform_set_drvdata(pdev, dev);
-	aup = netdev_priv(dev);
-
-	spin_lock_init(&aup->lock);
-	aup->msg_enable = (au1000_debug < 4 ?
-				AU1000_DEF_MSG_ENABLE : au1000_debug);
-
-	/* Allocate the data buffers
-	 * Snooping works fine with eth on all au1xxx
-	 */
-	aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE *
-						(NUM_TX_BUFFS + NUM_RX_BUFFS),
-						&aup->dma_addr,	0);
-	if (!aup->vaddr) {
-		dev_err(&pdev->dev, "failed to allocate data buffers\n");
-		err = -ENOMEM;
-		goto err_vaddr;
-	}
-
-	/* aup->mac is the base address of the MAC's registers */
-	aup->mac = (struct mac_reg *)
-			ioremap_nocache(base->start, resource_size(base));
-	if (!aup->mac) {
-		dev_err(&pdev->dev, "failed to ioremap MAC registers\n");
-		err = -ENXIO;
-		goto err_remap1;
-	}
-
-	/* Setup some variables for quick register address access */
-	aup->enable = (u32 *)ioremap_nocache(macen->start,
-						resource_size(macen));
-	if (!aup->enable) {
-		dev_err(&pdev->dev, "failed to ioremap MAC enable register\n");
-		err = -ENXIO;
-		goto err_remap2;
-	}
-	aup->mac_id = pdev->id;
-
-	if (pdev->id == 0)
-		au1000_setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
-	else if (pdev->id == 1)
-		au1000_setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR);
-
-	/* set a random MAC now in case platform_data doesn't provide one */
-	random_ether_addr(dev->dev_addr);
-
-	writel(0, aup->enable);
-	aup->mac_enabled = 0;
-
-	pd = pdev->dev.platform_data;
-	if (!pd) {
-		dev_info(&pdev->dev, "no platform_data passed,"
-					" PHY search on MAC0\n");
-		aup->phy1_search_mac0 = 1;
-	} else {
-		if (is_valid_ether_addr(pd->mac))
-			memcpy(dev->dev_addr, pd->mac, 6);
-
-		aup->phy_static_config = pd->phy_static_config;
-		aup->phy_search_highest_addr = pd->phy_search_highest_addr;
-		aup->phy1_search_mac0 = pd->phy1_search_mac0;
-		aup->phy_addr = pd->phy_addr;
-		aup->phy_busid = pd->phy_busid;
-		aup->phy_irq = pd->phy_irq;
-	}
-
-	if (aup->phy_busid && aup->phy_busid > 0) {
-		dev_err(&pdev->dev, "MAC0-associated PHY attached 2nd MACs MII bus not supported yet\n");
-		err = -ENODEV;
-		goto err_mdiobus_alloc;
-	}
-
-	aup->mii_bus = mdiobus_alloc();
-	if (aup->mii_bus == NULL) {
-		dev_err(&pdev->dev, "failed to allocate mdiobus structure\n");
-		err = -ENOMEM;
-		goto err_mdiobus_alloc;
-	}
-
-	aup->mii_bus->priv = dev;
-	aup->mii_bus->read = au1000_mdiobus_read;
-	aup->mii_bus->write = au1000_mdiobus_write;
-	aup->mii_bus->reset = au1000_mdiobus_reset;
-	aup->mii_bus->name = "au1000_eth_mii";
-	snprintf(aup->mii_bus->id, MII_BUS_ID_SIZE, "%x", aup->mac_id);
-	aup->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
-	if (aup->mii_bus->irq == NULL)
-		goto err_out;
-
-	for (i = 0; i < PHY_MAX_ADDR; ++i)
-		aup->mii_bus->irq[i] = PHY_POLL;
-	/* if known, set corresponding PHY IRQs */
-	if (aup->phy_static_config)
-		if (aup->phy_irq && aup->phy_busid == aup->mac_id)
-			aup->mii_bus->irq[aup->phy_addr] = aup->phy_irq;
-
-	err = mdiobus_register(aup->mii_bus);
-	if (err) {
-		dev_err(&pdev->dev, "failed to register MDIO bus\n");
-		goto err_mdiobus_reg;
-	}
-
-	if (au1000_mii_probe(dev) != 0)
-		goto err_out;
-
-	pDBfree = NULL;
-	/* setup the data buffer descriptors and attach a buffer to each one */
-	pDB = aup->db;
-	for (i = 0; i < (NUM_TX_BUFFS+NUM_RX_BUFFS); i++) {
-		pDB->pnext = pDBfree;
-		pDBfree = pDB;
-		pDB->vaddr = (u32 *)((unsigned)aup->vaddr + MAX_BUF_SIZE*i);
-		pDB->dma_addr = (dma_addr_t)virt_to_bus(pDB->vaddr);
-		pDB++;
-	}
-	aup->pDBfree = pDBfree;
-
-	for (i = 0; i < NUM_RX_DMA; i++) {
-		pDB = au1000_GetFreeDB(aup);
-		if (!pDB)
-			goto err_out;
-
-		aup->rx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
-		aup->rx_db_inuse[i] = pDB;
-	}
-	for (i = 0; i < NUM_TX_DMA; i++) {
-		pDB = au1000_GetFreeDB(aup);
-		if (!pDB)
-			goto err_out;
-
-		aup->tx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
-		aup->tx_dma_ring[i]->len = 0;
-		aup->tx_db_inuse[i] = pDB;
-	}
-
-	dev->base_addr = base->start;
-	dev->irq = irq;
-	dev->netdev_ops = &au1000_netdev_ops;
-	SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
-	dev->watchdog_timeo = ETH_TX_TIMEOUT;
-
-	/*
-	 * The boot code uses the ethernet controller, so reset it to start
-	 * fresh.  au1000_init() expects that the device is in reset state.
-	 */
-	au1000_reset_mac(dev);
-
-	err = register_netdev(dev);
-	if (err) {
-		netdev_err(dev, "Cannot register net device, aborting.\n");
-		goto err_out;
-	}
-
-	netdev_info(dev, "Au1xx0 Ethernet found at 0x%lx, irq %d\n",
-			(unsigned long)base->start, irq);
-	if (version_printed++ == 0)
-		pr_info("%s version %s %s\n",
-					DRV_NAME, DRV_VERSION, DRV_AUTHOR);
-
-	return 0;
-
-err_out:
-	if (aup->mii_bus != NULL)
-		mdiobus_unregister(aup->mii_bus);
-
-	/* here we should have a valid dev plus aup-> register addresses
-	 * so we can reset the mac properly.
-	 */
-	au1000_reset_mac(dev);
-
-	for (i = 0; i < NUM_RX_DMA; i++) {
-		if (aup->rx_db_inuse[i])
-			au1000_ReleaseDB(aup, aup->rx_db_inuse[i]);
-	}
-	for (i = 0; i < NUM_TX_DMA; i++) {
-		if (aup->tx_db_inuse[i])
-			au1000_ReleaseDB(aup, aup->tx_db_inuse[i]);
-	}
-err_mdiobus_reg:
-	mdiobus_free(aup->mii_bus);
-err_mdiobus_alloc:
-	iounmap(aup->enable);
-err_remap2:
-	iounmap(aup->mac);
-err_remap1:
-	dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
-			     (void *)aup->vaddr, aup->dma_addr);
-err_vaddr:
-	free_netdev(dev);
-err_alloc:
-	release_mem_region(macen->start, resource_size(macen));
-err_request:
-	release_mem_region(base->start, resource_size(base));
-out:
-	return err;
-}
-
-static int __devexit au1000_remove(struct platform_device *pdev)
-{
-	struct net_device *dev = platform_get_drvdata(pdev);
-	struct au1000_private *aup = netdev_priv(dev);
-	int i;
-	struct resource *base, *macen;
-
-	platform_set_drvdata(pdev, NULL);
-
-	unregister_netdev(dev);
-	mdiobus_unregister(aup->mii_bus);
-	mdiobus_free(aup->mii_bus);
-
-	for (i = 0; i < NUM_RX_DMA; i++)
-		if (aup->rx_db_inuse[i])
-			au1000_ReleaseDB(aup, aup->rx_db_inuse[i]);
-
-	for (i = 0; i < NUM_TX_DMA; i++)
-		if (aup->tx_db_inuse[i])
-			au1000_ReleaseDB(aup, aup->tx_db_inuse[i]);
-
-	dma_free_noncoherent(NULL, MAX_BUF_SIZE *
-			(NUM_TX_BUFFS + NUM_RX_BUFFS),
-			(void *)aup->vaddr, aup->dma_addr);
-
-	iounmap(aup->mac);
-	iounmap(aup->enable);
-
-	base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(base->start, resource_size(base));
-
-	macen = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	release_mem_region(macen->start, resource_size(macen));
-
-	free_netdev(dev);
-
-	return 0;
-}
-
-static struct platform_driver au1000_eth_driver = {
-	.probe  = au1000_probe,
-	.remove = __devexit_p(au1000_remove),
-	.driver = {
-		.name   = "au1000-eth",
-		.owner  = THIS_MODULE,
-	},
-};
-MODULE_ALIAS("platform:au1000-eth");
-
-
-static int __init au1000_init_module(void)
-{
-	return platform_driver_register(&au1000_eth_driver);
-}
-
-static void __exit au1000_exit_module(void)
-{
-	platform_driver_unregister(&au1000_eth_driver);
-}
-
-module_init(au1000_init_module);
-module_exit(au1000_exit_module);
diff -druN linux-libre-3.1-gnu/drivers/net/au1000_eth.h linux-libre-3.2-gnu/drivers/net/au1000_eth.h
--- linux-libre-3.1-gnu/drivers/net/au1000_eth.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/au1000_eth.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,134 +0,0 @@
-/*
- *
- * Alchemy Au1x00 ethernet driver include file
- *
- * Author: Pete Popov <ppopov@mvista.com>
- *
- * Copyright 2001 MontaVista Software Inc.
- *
- * ########################################################################
- *
- *  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.
- *
- * ########################################################################
- *
- *
- */
-
-
-#define MAC_IOSIZE 0x10000
-#define NUM_RX_DMA 4       /* Au1x00 has 4 rx hardware descriptors */
-#define NUM_TX_DMA 4       /* Au1x00 has 4 tx hardware descriptors */
-
-#define NUM_RX_BUFFS 4
-#define NUM_TX_BUFFS 4
-#define MAX_BUF_SIZE 2048
-
-#define ETH_TX_TIMEOUT (HZ/4)
-#define MAC_MIN_PKT_SIZE 64
-
-#define MULTICAST_FILTER_LIMIT 64
-
-/*
- * Data Buffer Descriptor. Data buffers must be aligned on 32 byte
- * boundary for both, receive and transmit.
- */
-struct db_dest {
-	struct db_dest *pnext;
-	u32 *vaddr;
-	dma_addr_t dma_addr;
-};
-
-/*
- * The transmit and receive descriptors are memory
- * mapped registers.
- */
-struct tx_dma {
-	u32 status;
-	u32 buff_stat;
-	u32 len;
-	u32 pad;
-};
-
-struct rx_dma {
-	u32 status;
-	u32 buff_stat;
-	u32 pad[2];
-};
-
-
-/*
- * MAC control registers, memory mapped.
- */
-struct mac_reg {
-	u32 control;
-	u32 mac_addr_high;
-	u32 mac_addr_low;
-	u32 multi_hash_high;
-	u32 multi_hash_low;
-	u32 mii_control;
-	u32 mii_data;
-	u32 flow_control;
-	u32 vlan1_tag;
-	u32 vlan2_tag;
-};
-
-
-struct au1000_private {
-	struct db_dest *pDBfree;
-	struct db_dest db[NUM_RX_BUFFS+NUM_TX_BUFFS];
-	struct rx_dma *rx_dma_ring[NUM_RX_DMA];
-	struct tx_dma *tx_dma_ring[NUM_TX_DMA];
-	struct db_dest *rx_db_inuse[NUM_RX_DMA];
-	struct db_dest *tx_db_inuse[NUM_TX_DMA];
-	u32 rx_head;
-	u32 tx_head;
-	u32 tx_tail;
-	u32 tx_full;
-
-	int mac_id;
-
-	int mac_enabled;       /* whether MAC is currently enabled and running
-				* (req. for mdio)
-				*/
-
-	int old_link;          /* used by au1000_adjust_link */
-	int old_speed;
-	int old_duplex;
-
-	struct phy_device *phy_dev;
-	struct mii_bus *mii_bus;
-
-	/* PHY configuration */
-	int phy_static_config;
-	int phy_search_highest_addr;
-	int phy1_search_mac0;
-
-	int phy_addr;
-	int phy_busid;
-	int phy_irq;
-
-	/* These variables are just for quick access
-	 * to certain regs addresses.
-	 */
-	struct mac_reg *mac;  /* mac registers                      */
-	u32 *enable;     /* address of MAC Enable Register     */
-
-	u32 vaddr;                /* virtual address of rx/tx buffers   */
-	dma_addr_t dma_addr;      /* dma address of rx/tx buffers       */
-
-	spinlock_t lock;       /* Serialise access to device */
-
-	u32 msg_enable;
-};
diff -druN linux-libre-3.1-gnu/drivers/net/ax88796.c linux-libre-3.2-gnu/drivers/net/ax88796.c
--- linux-libre-3.1-gnu/drivers/net/ax88796.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/ax88796.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1010 +0,0 @@
-/* drivers/net/ax88796.c
- *
- * Copyright 2005,2007 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Asix AX88796 10/100 Ethernet controller support
- *	Based on ne.c, by Donald Becker, et-al.
- *
- * This program is free software; you can 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/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/mdio-bitbang.h>
-#include <linux/phy.h>
-#include <linux/eeprom_93cx6.h>
-#include <linux/slab.h>
-
-#include <net/ax88796.h>
-
-#include <asm/system.h>
-
-/* 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_start_xmit ax_ei_start_xmit
-#define __ei_tx_timeout ax_ei_tx_timeout
-#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 ____alloc_ei_netdev ax__alloc_ei_netdev
-#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_outb(_v, _a) writeb(_v, ax_convert_addr(_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)])
-
-/* Ensure we have our RCR base value */
-#define AX88796_PLATFORM
-
-static unsigned char version[] = "ax88796.c: Copyright 2005,2007 Simtec Electronics\n";
-
-#include "lib8390.c"
-
-#define DRV_NAME "ax88796"
-#define DRV_VERSION "1.00"
-
-/* from ne.c */
-#define NE_CMD		EI_SHIFT(0x00)
-#define NE_RESET	EI_SHIFT(0x1f)
-#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 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 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;
-
-	void __iomem *map2;
-	const struct ax_plat_data *plat;
-
-	unsigned char running;
-	unsigned char resume_open;
-	unsigned int irqflags;
-
-	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);
-}
-
-/*
- * 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);
-	void __iomem *ioaddr = ei_local->mem;
-	int reg0;
-	int regd;
-
-	reg0 = ei_inb(ioaddr);
-	if (reg0 == 0xFF)
-		return -ENODEV;
-
-	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_inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
-	if (ei_inb(ioaddr + EN0_COUNTER0) != 0) {
-		ei_outb(reg0, ioaddr);
-		ei_outb(regd, ioaddr + 0x0d);	/* Restore the old values. */
-		return -ENODEV;
-	}
-
-	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.
- */
-static void ax_reset_8390(struct net_device *dev)
-{
-	struct ei_device *ei_local = netdev_priv(dev);
-	unsigned long reset_start_time = jiffies;
-	void __iomem *addr = (void __iomem *)dev->base_addr;
-
-	if (ei_debug > 1)
-		netdev_dbg(dev, "resetting the 8390 t=%ld\n", jiffies);
-
-	ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
-
-	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) {
-			netdev_warn(dev, "%s: did not complete.\n", __func__);
-			break;
-		}
-	}
-
-	ei_outb(ENISR_RESET, addr + EN0_ISR);	/* Ack intr. */
-}
-
-
-static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-			    int ring_page)
-{
-	struct ei_device *ei_local = netdev_priv(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_local->dmaing) {
-		netdev_err(dev, "DMAing conflict in %s "
-			"[DMAstat:%d][irqlock:%d].\n",
-			__func__,
-			ei_local->dmaing, ei_local->irqlock);
-		return;
-	}
-
-	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_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));
-
-	ei_outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
-	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.
- */
-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);
-	void __iomem *nic_base = ei_local->mem;
-	char *buf = skb->data;
-
-	if (ei_local->dmaing) {
-		netdev_err(dev,
-			"DMAing conflict in %s "
-			"[DMAstat:%d][irqlock:%d].\n",
-			__func__,
-			ei_local->dmaing, ei_local->irqlock);
-		return;
-	}
-
-	ei_local->dmaing |= 0x01;
-
-	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_local->word16) {
-		readsw(nic_base + NE_DATAPORT, buf, count >> 1);
-		if (count & 0x01)
-			buf[count-1] = ei_inb(nic_base + NE_DATAPORT);
-
-	} else {
-		readsb(nic_base + NE_DATAPORT, buf, count);
-	}
-
-	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);
-	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_local->word16 && (count & 0x01))
-		count++;
-
-	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
-	if (ei_local->dmaing) {
-		netdev_err(dev, "DMAing conflict in %s."
-			"[DMAstat:%d][irqlock:%d]\n",
-			__func__,
-		       ei_local->dmaing, ei_local->irqlock);
-		return;
-	}
-
-	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);
-
-	ei_outb(ENISR_RDC, nic_base + EN0_ISR);
-
-	/* Now the normal output. */
-	ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
-	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_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 */
-			netdev_warn(dev, "timeout waiting for Tx RDC.\n");
-			ax_reset_8390(dev);
-			ax_NS8390_init(dev, 1);
-			break;
-		}
-	}
-
-	ei_outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
-	ei_local->dmaing &= ~0x01;
-}
-
-/* definitions for accessing MII/EEPROM interface */
-
-#define AX_MEMR			EI_SHIFT(0x14)
-#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_handle_link_change(struct net_device *dev)
-{
-	struct ax_device  *ax = to_ax_dev(dev);
-	struct phy_device *phy_dev = ax->phy_dev;
-	int status_change = 0;
-
-	if (phy_dev->link && ((ax->speed != phy_dev->speed) ||
-			     (ax->duplex != phy_dev->duplex))) {
-
-		ax->speed = phy_dev->speed;
-		ax->duplex = phy_dev->duplex;
-		status_change = 1;
-	}
-
-	if (phy_dev->link != ax->link) {
-		if (!phy_dev->link) {
-			ax->speed = 0;
-			ax->duplex = -1;
-		}
-		ax->link = phy_dev->link;
-
-		status_change = 1;
-	}
-
-	if (status_change)
-		phy_print_status(phy_dev);
-}
-
-static int ax_mii_probe(struct net_device *dev)
-{
-	struct ax_device  *ax = to_ax_dev(dev);
-	struct phy_device *phy_dev = NULL;
-	int ret;
-
-	/* find the first phy */
-	phy_dev = phy_find_first(ax->mii_bus);
-	if (!phy_dev) {
-		netdev_err(dev, "no PHY found\n");
-		return -ENODEV;
-	}
-
-	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;
-	}
-
-	/* mask with MAC supported features */
-	phy_dev->supported &= PHY_BASIC_FEATURES;
-	phy_dev->advertising = phy_dev->supported;
-
-	ax->phy_dev = phy_dev;
-
-	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);
-
-	return 0;
-}
-
-static void ax_phy_switch(struct net_device *dev, int on)
-{
-	struct ei_device *ei_local = netdev_priv(dev);
-	struct ax_device *ax = to_ax_dev(dev);
-
-	u8 reg_gpoc =  ax->plat->gpoc_val;
-
-	if (!!on)
-		reg_gpoc &= ~AX_GPOC_PPDSET;
-	else
-		reg_gpoc |= AX_GPOC_PPDSET;
-
-	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);
-	int ret;
-
-	netdev_dbg(dev, "open\n");
-
-	ret = request_irq(dev->irq, ax_ei_interrupt, ax->irqflags,
-			  dev->name, dev);
-	if (ret)
-		goto failed_request_irq;
-
-	/* turn the phy on (if turned off) */
-	ax_phy_switch(dev, 1);
-
-	ret = ax_mii_probe(dev);
-	if (ret)
-		goto failed_mii_probe;
-	phy_start(ax->phy_dev);
-
-	ret = ax_ei_open(dev);
-	if (ret)
-		goto failed_ax_ei_open;
-
-	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);
-
-	netdev_dbg(dev, "close\n");
-
-	ax->running = 0;
-	wmb();
-
-	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;
-}
-
-static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
-{
-	struct ax_device *ax = to_ax_dev(dev);
-	struct phy_device *phy_dev = ax->phy_dev;
-
-	if (!netif_running(dev))
-		return -EINVAL;
-
-	if (!phy_dev)
-		return -ENODEV;
-
-	return phy_mii_ioctl(phy_dev, req, cmd);
-}
-
-/* ethtool ops */
-
-static void ax_get_drvinfo(struct net_device *dev,
-			   struct ethtool_drvinfo *info)
-{
-	struct platform_device *pdev = to_platform_device(dev->dev.parent);
-
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-	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);
-	struct phy_device *phy_dev = ax->phy_dev;
-
-	if (!phy_dev)
-		return -ENODEV;
-
-	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);
-	struct phy_device *phy_dev = ax->phy_dev;
-
-	if (!phy_dev)
-		return -ENODEV;
-
-	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,
-	.get_link		= ethtool_op_get_link,
-};
-
-#ifdef CONFIG_AX88796_93CX6
-static void ax_eeprom_register_read(struct eeprom_93cx6 *eeprom)
-{
-	struct ei_device *ei_local = eeprom->data;
-	u8 reg = ei_inb(ei_local->mem + AX_MEMR);
-
-	eeprom->reg_data_in = reg & AX_MEMR_EEI;
-	eeprom->reg_data_out = reg & AX_MEMR_EEO; /* Input pin */
-	eeprom->reg_data_clock = reg & AX_MEMR_EECLK;
-	eeprom->reg_chip_select = reg & AX_MEMR_EECS;
-}
-
-static void ax_eeprom_register_write(struct eeprom_93cx6 *eeprom)
-{
-	struct ei_device *ei_local = eeprom->data;
-	u8 reg = ei_inb(ei_local->mem + AX_MEMR);
-
-	reg &= ~(AX_MEMR_EEI | AX_MEMR_EECLK | AX_MEMR_EECS);
-
-	if (eeprom->reg_data_in)
-		reg |= AX_MEMR_EEI;
-	if (eeprom->reg_data_clock)
-		reg |= AX_MEMR_EECLK;
-	if (eeprom->reg_chip_select)
-		reg |= AX_MEMR_EECS;
-
-	ei_outb(reg, ei_local->mem + AX_MEMR);
-	udelay(10);
-}
-#endif
-
-static const struct net_device_ops ax_netdev_ops = {
-	.ndo_open		= ax_open,
-	.ndo_stop		= ax_close,
-	.ndo_do_ioctl		= ax_ioctl,
-
-	.ndo_start_xmit		= ax_ei_start_xmit,
-	.ndo_tx_timeout		= ax_ei_tx_timeout,
-	.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_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);
-
-	/* 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
- *
- * 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)
-{
-	struct ei_device *ei_local = netdev_priv(dev);
-	struct ax_device *ax = to_ax_dev(dev);
-	void __iomem *ioaddr = ei_local->mem;
-	unsigned int start_page;
-	unsigned int stop_page;
-	int ret;
-	int i;
-
-	ret = ax_initial_check(dev);
-	if (ret)
-		goto err_out;
-
-	/* setup goes here */
-
-	ax_initial_setup(dev, ei_local);
-
-	/* read the mac from the card prom if we need it */
-
-	if (ax->plat->flags & AXFLG_HAS_EEPROM) {
-		unsigned char SA_prom[32];
-
-		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);
-		}
-
-		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);
-	}
-
-#ifdef CONFIG_AX88796_93CX6
-	if (ax->plat->flags & AXFLG_HAS_93CX6) {
-		unsigned char mac_addr[6];
-		struct eeprom_93cx6 eeprom;
-
-		eeprom.data = ei_local;
-		eeprom.register_read = ax_eeprom_register_read;
-		eeprom.register_write = ax_eeprom_register_write;
-		eeprom.width = PCI_EEPROM_WIDTH_93C56;
-
-		eeprom_93cx6_multiread(&eeprom, 0,
-				       (__le16 __force *)mac_addr,
-				       sizeof(mac_addr) >> 1);
-
-		memcpy(dev->dev_addr, mac_addr, 6);
-	}
-#endif
-	if (ax->plat->wordlength == 2) {
-		/* We must set the 8390 for word mode. */
-		ei_outb(ax->plat->dcr_val, ei_local->mem + EN0_DCFG);
-		start_page = NESM_START_PG;
-		stop_page = NESM_STOP_PG;
-	} else {
-		start_page = NE1SM_START_PG;
-		stop_page = NE1SM_STOP_PG;
-	}
-
-	/* 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_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_local->stop_page = ei_local->tx_start_page + PACKETBUF_MEMSIZE;
-#endif
-
-	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;
-
-	ret = ax_mii_init(dev);
-	if (ret)
-		goto out_irq;
-
-	ax_NS8390_init(dev, 0);
-
-	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:
-	/* cleanup irq */
-	free_irq(dev->irq, dev);
- err_out:
-	return ret;
-}
-
-static int ax_remove(struct platform_device *pdev)
-{
-	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_local->mem);
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(mem->start, resource_size(mem));
-
-	if (ax->map2) {
-		iounmap(ax->map2);
-		mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-		release_mem_region(mem->start, resource_size(mem));
-	}
-
-	free_netdev(dev);
-
-	return 0;
-}
-
-/*
- * 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.
- */
-static int ax_probe(struct platform_device *pdev)
-{
-	struct net_device *dev;
-	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));
-	if (dev == NULL)
-		return -ENOMEM;
-
-	/* ok, let's setup our device */
-	SET_NETDEV_DEV(dev, &pdev->dev);
-	ei_local = netdev_priv(dev);
-	ax = to_ax_dev(dev);
-
-	ax->plat = pdev->dev.platform_data;
-	platform_set_drvdata(pdev, dev);
-
-	ei_local->rxcr_base = ax->plat->rcr_val;
-
-	/* find the platform resources */
-	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 = irq->start;
-	ax->irqflags = irq->flags & IRQF_TRIGGER_MASK;
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem) {
-		dev_err(&pdev->dev, "no MEM specified\n");
-		ret = -ENXIO;
-		goto exit_mem;
-	}
-
-	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_local->reg_offset = ax->plat->reg_offsets;
-	else {
-		ei_local->reg_offset = ax->reg_offsets;
-		for (ret = 0; ret < 0x18; ret++)
-			ax->reg_offsets[ret] = (mem_size / 0x18) * ret;
-	}
-
-	if (!request_mem_region(mem->start, mem_size, pdev->name)) {
-		dev_err(&pdev->dev, "cannot reserve registers\n");
-		ret = -ENXIO;
-		goto exit_mem;
-	}
-
-	ei_local->mem = ioremap(mem->start, mem_size);
-	dev->base_addr = (unsigned long)ei_local->mem;
-
-	if (ei_local->mem == NULL) {
-		dev_err(&pdev->dev, "Cannot ioremap area %pR\n", mem);
-
-		ret = -ENXIO;
-		goto exit_req;
-	}
-
-	/* look for reset area */
-	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] = (mem_size / 0x20) * ret;
-		}
-	} else {
-		mem2_size = resource_size(mem2);
-
-		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(mem2->start, mem2_size);
-		if (!ax->map2) {
-			dev_err(&pdev->dev, "cannot map reset register\n");
-			ret = -ENXIO;
-			goto exit_mem2;
-		}
-
-		ei_local->reg_offset[0x1f] = ax->map2 - ei_local->mem;
-	}
-
-	/* got resources, now initialise and register device */
-	ret = ax_init_dev(dev);
-	if (!ret)
-		return 0;
-
-	if (!ax->map2)
-		goto exit_mem1;
-
-	iounmap(ax->map2);
-
- exit_mem2:
-	release_mem_region(mem2->start, mem2_size);
-
- exit_mem1:
-	iounmap(ei_local->mem);
-
- exit_req:
-	release_mem_region(mem->start, mem_size);
-
- exit_mem:
-	free_netdev(dev);
-
-	return ret;
-}
-
-/* suspend and resume */
-
-#ifdef CONFIG_PM
-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);
-
-	ax->resume_open = ax->running;
-
-	netif_device_detach(ndev);
-	ax_close(ndev);
-
-	return 0;
-}
-
-static int ax_resume(struct platform_device *pdev)
-{
-	struct net_device *ndev = platform_get_drvdata(pdev);
-	struct ax_device *ax = to_ax_dev(ndev);
-
-	ax_initial_setup(ndev, netdev_priv(ndev));
-	ax_NS8390_init(ndev, ax->resume_open);
-	netif_device_attach(ndev);
-
-	if (ax->resume_open)
-		ax_open(ndev);
-
-	return 0;
-}
-
-#else
-#define ax_suspend NULL
-#define ax_resume NULL
-#endif
-
-static struct platform_driver axdrv = {
-	.driver	= {
-		.name		= "ax88796",
-		.owner		= THIS_MODULE,
-	},
-	.probe		= ax_probe,
-	.remove		= ax_remove,
-	.suspend	= ax_suspend,
-	.resume		= ax_resume,
-};
-
-static int __init axdrv_init(void)
-{
-	return platform_driver_register(&axdrv);
-}
-
-static void __exit axdrv_exit(void)
-{
-	platform_driver_unregister(&axdrv);
-}
-
-module_init(axdrv_init);
-module_exit(axdrv_exit);
-
-MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
-MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:ax88796");
diff -druN linux-libre-3.1-gnu/drivers/net/b44.c linux-libre-3.2-gnu/drivers/net/b44.c
--- linux-libre-3.1-gnu/drivers/net/b44.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/b44.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2374 +0,0 @@
-/* b44.c: Broadcom 44xx/47xx Fast Ethernet device driver.
- *
- * Copyright (C) 2002 David S. Miller (davem@redhat.com)
- * Copyright (C) 2004 Pekka Pietikainen (pp@ee.oulu.fi)
- * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
- * Copyright (C) 2006 Felix Fietkau (nbd@openwrt.org)
- * Copyright (C) 2006 Broadcom Corporation.
- * Copyright (C) 2007 Michael Buesch <m@bues.ch>
- *
- * Distribute under GPL.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-#include <linux/if_ether.h>
-#include <linux/if_vlan.h>
-#include <linux/etherdevice.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/ssb/ssb.h>
-#include <linux/slab.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-
-#include "b44.h"
-
-#define DRV_MODULE_NAME		"b44"
-#define DRV_MODULE_VERSION	"2.0"
-#define DRV_DESCRIPTION		"Broadcom 44xx/47xx 10/100 PCI ethernet driver"
-
-#define B44_DEF_MSG_ENABLE	  \
-	(NETIF_MSG_DRV		| \
-	 NETIF_MSG_PROBE	| \
-	 NETIF_MSG_LINK		| \
-	 NETIF_MSG_TIMER	| \
-	 NETIF_MSG_IFDOWN	| \
-	 NETIF_MSG_IFUP		| \
-	 NETIF_MSG_RX_ERR	| \
-	 NETIF_MSG_TX_ERR)
-
-/* length of time before we decide the hardware is borked,
- * and dev->tx_timeout() should be called to fix the problem
- */
-#define B44_TX_TIMEOUT			(5 * HZ)
-
-/* hardware minimum and maximum for a single frame's data payload */
-#define B44_MIN_MTU			60
-#define B44_MAX_MTU			1500
-
-#define B44_RX_RING_SIZE		512
-#define B44_DEF_RX_RING_PENDING		200
-#define B44_RX_RING_BYTES	(sizeof(struct dma_desc) * \
-				 B44_RX_RING_SIZE)
-#define B44_TX_RING_SIZE		512
-#define B44_DEF_TX_RING_PENDING		(B44_TX_RING_SIZE - 1)
-#define B44_TX_RING_BYTES	(sizeof(struct dma_desc) * \
-				 B44_TX_RING_SIZE)
-
-#define TX_RING_GAP(BP)	\
-	(B44_TX_RING_SIZE - (BP)->tx_pending)
-#define TX_BUFFS_AVAIL(BP)						\
-	(((BP)->tx_cons <= (BP)->tx_prod) ?				\
-	  (BP)->tx_cons + (BP)->tx_pending - (BP)->tx_prod :		\
-	  (BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP))
-#define NEXT_TX(N)		(((N) + 1) & (B44_TX_RING_SIZE - 1))
-
-#define RX_PKT_OFFSET		(RX_HEADER_LEN + 2)
-#define RX_PKT_BUF_SZ		(1536 + RX_PKT_OFFSET)
-
-/* minimum number of free TX descriptors required to wake up TX process */
-#define B44_TX_WAKEUP_THRESH		(B44_TX_RING_SIZE / 4)
-
-/* b44 internal pattern match filter info */
-#define B44_PATTERN_BASE	0x400
-#define B44_PATTERN_SIZE	0x80
-#define B44_PMASK_BASE		0x600
-#define B44_PMASK_SIZE		0x10
-#define B44_MAX_PATTERNS	16
-#define B44_ETHIPV6UDP_HLEN	62
-#define B44_ETHIPV4UDP_HLEN	42
-
-MODULE_AUTHOR("Felix Fietkau, Florian Schirmer, Pekka Pietikainen, David S. Miller");
-MODULE_DESCRIPTION(DRV_DESCRIPTION);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_MODULE_VERSION);
-
-static int b44_debug = -1;	/* -1 == use B44_DEF_MSG_ENABLE as value */
-module_param(b44_debug, int, 0);
-MODULE_PARM_DESC(b44_debug, "B44 bitmapped debugging message enable value");
-
-
-#ifdef CONFIG_B44_PCI
-static DEFINE_PCI_DEVICE_TABLE(b44_pci_tbl) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B1) },
-	{ 0 } /* terminate list with empty entry */
-};
-MODULE_DEVICE_TABLE(pci, b44_pci_tbl);
-
-static struct pci_driver b44_pci_driver = {
-	.name		= DRV_MODULE_NAME,
-	.id_table	= b44_pci_tbl,
-};
-#endif /* CONFIG_B44_PCI */
-
-static const struct ssb_device_id b44_ssb_tbl[] = {
-	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_ETHERNET, SSB_ANY_REV),
-	SSB_DEVTABLE_END
-};
-MODULE_DEVICE_TABLE(ssb, b44_ssb_tbl);
-
-static void b44_halt(struct b44 *);
-static void b44_init_rings(struct b44 *);
-
-#define B44_FULL_RESET		1
-#define B44_FULL_RESET_SKIP_PHY	2
-#define B44_PARTIAL_RESET	3
-#define B44_CHIP_RESET_FULL	4
-#define B44_CHIP_RESET_PARTIAL	5
-
-static void b44_init_hw(struct b44 *, int);
-
-static int dma_desc_sync_size;
-static int instance;
-
-static const char b44_gstrings[][ETH_GSTRING_LEN] = {
-#define _B44(x...)	# x,
-B44_STAT_REG_DECLARE
-#undef _B44
-};
-
-static inline void b44_sync_dma_desc_for_device(struct ssb_device *sdev,
-						dma_addr_t dma_base,
-						unsigned long offset,
-						enum dma_data_direction dir)
-{
-	dma_sync_single_for_device(sdev->dma_dev, dma_base + offset,
-				   dma_desc_sync_size, dir);
-}
-
-static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
-					     dma_addr_t dma_base,
-					     unsigned long offset,
-					     enum dma_data_direction dir)
-{
-	dma_sync_single_for_cpu(sdev->dma_dev, dma_base + offset,
-				dma_desc_sync_size, dir);
-}
-
-static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
-{
-	return ssb_read32(bp->sdev, reg);
-}
-
-static inline void bw32(const struct b44 *bp,
-			unsigned long reg, unsigned long val)
-{
-	ssb_write32(bp->sdev, reg, val);
-}
-
-static int b44_wait_bit(struct b44 *bp, unsigned long reg,
-			u32 bit, unsigned long timeout, const int clear)
-{
-	unsigned long i;
-
-	for (i = 0; i < timeout; i++) {
-		u32 val = br32(bp, reg);
-
-		if (clear && !(val & bit))
-			break;
-		if (!clear && (val & bit))
-			break;
-		udelay(10);
-	}
-	if (i == timeout) {
-		if (net_ratelimit())
-			netdev_err(bp->dev, "BUG!  Timeout waiting for bit %08x of register %lx to %s\n",
-				   bit, reg, clear ? "clear" : "set");
-
-		return -ENODEV;
-	}
-	return 0;
-}
-
-static inline void __b44_cam_read(struct b44 *bp, unsigned char *data, int index)
-{
-	u32 val;
-
-	bw32(bp, B44_CAM_CTRL, (CAM_CTRL_READ |
-			    (index << CAM_CTRL_INDEX_SHIFT)));
-
-	b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
-
-	val = br32(bp, B44_CAM_DATA_LO);
-
-	data[2] = (val >> 24) & 0xFF;
-	data[3] = (val >> 16) & 0xFF;
-	data[4] = (val >> 8) & 0xFF;
-	data[5] = (val >> 0) & 0xFF;
-
-	val = br32(bp, B44_CAM_DATA_HI);
-
-	data[0] = (val >> 8) & 0xFF;
-	data[1] = (val >> 0) & 0xFF;
-}
-
-static inline void __b44_cam_write(struct b44 *bp, unsigned char *data, int index)
-{
-	u32 val;
-
-	val  = ((u32) data[2]) << 24;
-	val |= ((u32) data[3]) << 16;
-	val |= ((u32) data[4]) <<  8;
-	val |= ((u32) data[5]) <<  0;
-	bw32(bp, B44_CAM_DATA_LO, val);
-	val = (CAM_DATA_HI_VALID |
-	       (((u32) data[0]) << 8) |
-	       (((u32) data[1]) << 0));
-	bw32(bp, B44_CAM_DATA_HI, val);
-	bw32(bp, B44_CAM_CTRL, (CAM_CTRL_WRITE |
-			    (index << CAM_CTRL_INDEX_SHIFT)));
-	b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
-}
-
-static inline void __b44_disable_ints(struct b44 *bp)
-{
-	bw32(bp, B44_IMASK, 0);
-}
-
-static void b44_disable_ints(struct b44 *bp)
-{
-	__b44_disable_ints(bp);
-
-	/* Flush posted writes. */
-	br32(bp, B44_IMASK);
-}
-
-static void b44_enable_ints(struct b44 *bp)
-{
-	bw32(bp, B44_IMASK, bp->imask);
-}
-
-static int __b44_readphy(struct b44 *bp, int phy_addr, int reg, u32 *val)
-{
-	int err;
-
-	bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
-	bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START |
-			     (MDIO_OP_READ << MDIO_DATA_OP_SHIFT) |
-			     (phy_addr << MDIO_DATA_PMD_SHIFT) |
-			     (reg << MDIO_DATA_RA_SHIFT) |
-			     (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT)));
-	err = b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
-	*val = br32(bp, B44_MDIO_DATA) & MDIO_DATA_DATA;
-
-	return err;
-}
-
-static int __b44_writephy(struct b44 *bp, int phy_addr, int reg, u32 val)
-{
-	bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
-	bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START |
-			     (MDIO_OP_WRITE << MDIO_DATA_OP_SHIFT) |
-			     (phy_addr << MDIO_DATA_PMD_SHIFT) |
-			     (reg << MDIO_DATA_RA_SHIFT) |
-			     (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT) |
-			     (val & MDIO_DATA_DATA)));
-	return b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
-}
-
-static inline int b44_readphy(struct b44 *bp, int reg, u32 *val)
-{
-	if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
-		return 0;
-
-	return __b44_readphy(bp, bp->phy_addr, reg, val);
-}
-
-static inline int b44_writephy(struct b44 *bp, int reg, u32 val)
-{
-	if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
-		return 0;
-
-	return __b44_writephy(bp, bp->phy_addr, reg, val);
-}
-
-/* miilib interface */
-static int b44_mii_read(struct net_device *dev, int phy_id, int location)
-{
-	u32 val;
-	struct b44 *bp = netdev_priv(dev);
-	int rc = __b44_readphy(bp, phy_id, location, &val);
-	if (rc)
-		return 0xffffffff;
-	return val;
-}
-
-static void b44_mii_write(struct net_device *dev, int phy_id, int location,
-			 int val)
-{
-	struct b44 *bp = netdev_priv(dev);
-	__b44_writephy(bp, phy_id, location, val);
-}
-
-static int b44_phy_reset(struct b44 *bp)
-{
-	u32 val;
-	int err;
-
-	if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
-		return 0;
-	err = b44_writephy(bp, MII_BMCR, BMCR_RESET);
-	if (err)
-		return err;
-	udelay(100);
-	err = b44_readphy(bp, MII_BMCR, &val);
-	if (!err) {
-		if (val & BMCR_RESET) {
-			netdev_err(bp->dev, "PHY Reset would not complete\n");
-			err = -ENODEV;
-		}
-	}
-
-	return err;
-}
-
-static void __b44_set_flow_ctrl(struct b44 *bp, u32 pause_flags)
-{
-	u32 val;
-
-	bp->flags &= ~(B44_FLAG_TX_PAUSE | B44_FLAG_RX_PAUSE);
-	bp->flags |= pause_flags;
-
-	val = br32(bp, B44_RXCONFIG);
-	if (pause_flags & B44_FLAG_RX_PAUSE)
-		val |= RXCONFIG_FLOW;
-	else
-		val &= ~RXCONFIG_FLOW;
-	bw32(bp, B44_RXCONFIG, val);
-
-	val = br32(bp, B44_MAC_FLOW);
-	if (pause_flags & B44_FLAG_TX_PAUSE)
-		val |= (MAC_FLOW_PAUSE_ENAB |
-			(0xc0 & MAC_FLOW_RX_HI_WATER));
-	else
-		val &= ~MAC_FLOW_PAUSE_ENAB;
-	bw32(bp, B44_MAC_FLOW, val);
-}
-
-static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote)
-{
-	u32 pause_enab = 0;
-
-	/* The driver supports only rx pause by default because
-	   the b44 mac tx pause mechanism generates excessive
-	   pause frames.
-	   Use ethtool to turn on b44 tx pause if necessary.
-	 */
-	if ((local & ADVERTISE_PAUSE_CAP) &&
-	    (local & ADVERTISE_PAUSE_ASYM)){
-		if ((remote & LPA_PAUSE_ASYM) &&
-		    !(remote & LPA_PAUSE_CAP))
-			pause_enab |= B44_FLAG_RX_PAUSE;
-	}
-
-	__b44_set_flow_ctrl(bp, pause_enab);
-}
-
-#ifdef CONFIG_BCM47XX
-#include <asm/mach-bcm47xx/nvram.h>
-static void b44_wap54g10_workaround(struct b44 *bp)
-{
-	char buf[20];
-	u32 val;
-	int err;
-
-	/*
-	 * workaround for bad hardware design in Linksys WAP54G v1.0
-	 * see https://dev.openwrt.org/ticket/146
-	 * check and reset bit "isolate"
-	 */
-	if (nvram_getenv("boardnum", buf, sizeof(buf)) < 0)
-		return;
-	if (simple_strtoul(buf, NULL, 0) == 2) {
-		err = __b44_readphy(bp, 0, MII_BMCR, &val);
-		if (err)
-			goto error;
-		if (!(val & BMCR_ISOLATE))
-			return;
-		val &= ~BMCR_ISOLATE;
-		err = __b44_writephy(bp, 0, MII_BMCR, val);
-		if (err)
-			goto error;
-	}
-	return;
-error:
-	pr_warning("PHY: cannot reset MII transceiver isolate bit\n");
-}
-#else
-static inline void b44_wap54g10_workaround(struct b44 *bp)
-{
-}
-#endif
-
-static int b44_setup_phy(struct b44 *bp)
-{
-	u32 val;
-	int err;
-
-	b44_wap54g10_workaround(bp);
-
-	if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
-		return 0;
-	if ((err = b44_readphy(bp, B44_MII_ALEDCTRL, &val)) != 0)
-		goto out;
-	if ((err = b44_writephy(bp, B44_MII_ALEDCTRL,
-				val & MII_ALEDCTRL_ALLMSK)) != 0)
-		goto out;
-	if ((err = b44_readphy(bp, B44_MII_TLEDCTRL, &val)) != 0)
-		goto out;
-	if ((err = b44_writephy(bp, B44_MII_TLEDCTRL,
-				val | MII_TLEDCTRL_ENABLE)) != 0)
-		goto out;
-
-	if (!(bp->flags & B44_FLAG_FORCE_LINK)) {
-		u32 adv = ADVERTISE_CSMA;
-
-		if (bp->flags & B44_FLAG_ADV_10HALF)
-			adv |= ADVERTISE_10HALF;
-		if (bp->flags & B44_FLAG_ADV_10FULL)
-			adv |= ADVERTISE_10FULL;
-		if (bp->flags & B44_FLAG_ADV_100HALF)
-			adv |= ADVERTISE_100HALF;
-		if (bp->flags & B44_FLAG_ADV_100FULL)
-			adv |= ADVERTISE_100FULL;
-
-		if (bp->flags & B44_FLAG_PAUSE_AUTO)
-			adv |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
-
-		if ((err = b44_writephy(bp, MII_ADVERTISE, adv)) != 0)
-			goto out;
-		if ((err = b44_writephy(bp, MII_BMCR, (BMCR_ANENABLE |
-						       BMCR_ANRESTART))) != 0)
-			goto out;
-	} else {
-		u32 bmcr;
-
-		if ((err = b44_readphy(bp, MII_BMCR, &bmcr)) != 0)
-			goto out;
-		bmcr &= ~(BMCR_FULLDPLX | BMCR_ANENABLE | BMCR_SPEED100);
-		if (bp->flags & B44_FLAG_100_BASE_T)
-			bmcr |= BMCR_SPEED100;
-		if (bp->flags & B44_FLAG_FULL_DUPLEX)
-			bmcr |= BMCR_FULLDPLX;
-		if ((err = b44_writephy(bp, MII_BMCR, bmcr)) != 0)
-			goto out;
-
-		/* Since we will not be negotiating there is no safe way
-		 * to determine if the link partner supports flow control
-		 * or not.  So just disable it completely in this case.
-		 */
-		b44_set_flow_ctrl(bp, 0, 0);
-	}
-
-out:
-	return err;
-}
-
-static void b44_stats_update(struct b44 *bp)
-{
-	unsigned long reg;
-	u32 *val;
-
-	val = &bp->hw_stats.tx_good_octets;
-	for (reg = B44_TX_GOOD_O; reg <= B44_TX_PAUSE; reg += 4UL) {
-		*val++ += br32(bp, reg);
-	}
-
-	/* Pad */
-	reg += 8*4UL;
-
-	for (reg = B44_RX_GOOD_O; reg <= B44_RX_NPAUSE; reg += 4UL) {
-		*val++ += br32(bp, reg);
-	}
-}
-
-static void b44_link_report(struct b44 *bp)
-{
-	if (!netif_carrier_ok(bp->dev)) {
-		netdev_info(bp->dev, "Link is down\n");
-	} else {
-		netdev_info(bp->dev, "Link is up at %d Mbps, %s duplex\n",
-			    (bp->flags & B44_FLAG_100_BASE_T) ? 100 : 10,
-			    (bp->flags & B44_FLAG_FULL_DUPLEX) ? "full" : "half");
-
-		netdev_info(bp->dev, "Flow control is %s for TX and %s for RX\n",
-			    (bp->flags & B44_FLAG_TX_PAUSE) ? "on" : "off",
-			    (bp->flags & B44_FLAG_RX_PAUSE) ? "on" : "off");
-	}
-}
-
-static void b44_check_phy(struct b44 *bp)
-{
-	u32 bmsr, aux;
-
-	if (bp->phy_addr == B44_PHY_ADDR_NO_PHY) {
-		bp->flags |= B44_FLAG_100_BASE_T;
-		bp->flags |= B44_FLAG_FULL_DUPLEX;
-		if (!netif_carrier_ok(bp->dev)) {
-			u32 val = br32(bp, B44_TX_CTRL);
-			val |= TX_CTRL_DUPLEX;
-			bw32(bp, B44_TX_CTRL, val);
-			netif_carrier_on(bp->dev);
-			b44_link_report(bp);
-		}
-		return;
-	}
-
-	if (!b44_readphy(bp, MII_BMSR, &bmsr) &&
-	    !b44_readphy(bp, B44_MII_AUXCTRL, &aux) &&
-	    (bmsr != 0xffff)) {
-		if (aux & MII_AUXCTRL_SPEED)
-			bp->flags |= B44_FLAG_100_BASE_T;
-		else
-			bp->flags &= ~B44_FLAG_100_BASE_T;
-		if (aux & MII_AUXCTRL_DUPLEX)
-			bp->flags |= B44_FLAG_FULL_DUPLEX;
-		else
-			bp->flags &= ~B44_FLAG_FULL_DUPLEX;
-
-		if (!netif_carrier_ok(bp->dev) &&
-		    (bmsr & BMSR_LSTATUS)) {
-			u32 val = br32(bp, B44_TX_CTRL);
-			u32 local_adv, remote_adv;
-
-			if (bp->flags & B44_FLAG_FULL_DUPLEX)
-				val |= TX_CTRL_DUPLEX;
-			else
-				val &= ~TX_CTRL_DUPLEX;
-			bw32(bp, B44_TX_CTRL, val);
-
-			if (!(bp->flags & B44_FLAG_FORCE_LINK) &&
-			    !b44_readphy(bp, MII_ADVERTISE, &local_adv) &&
-			    !b44_readphy(bp, MII_LPA, &remote_adv))
-				b44_set_flow_ctrl(bp, local_adv, remote_adv);
-
-			/* Link now up */
-			netif_carrier_on(bp->dev);
-			b44_link_report(bp);
-		} else if (netif_carrier_ok(bp->dev) && !(bmsr & BMSR_LSTATUS)) {
-			/* Link now down */
-			netif_carrier_off(bp->dev);
-			b44_link_report(bp);
-		}
-
-		if (bmsr & BMSR_RFAULT)
-			netdev_warn(bp->dev, "Remote fault detected in PHY\n");
-		if (bmsr & BMSR_JCD)
-			netdev_warn(bp->dev, "Jabber detected in PHY\n");
-	}
-}
-
-static void b44_timer(unsigned long __opaque)
-{
-	struct b44 *bp = (struct b44 *) __opaque;
-
-	spin_lock_irq(&bp->lock);
-
-	b44_check_phy(bp);
-
-	b44_stats_update(bp);
-
-	spin_unlock_irq(&bp->lock);
-
-	mod_timer(&bp->timer, round_jiffies(jiffies + HZ));
-}
-
-static void b44_tx(struct b44 *bp)
-{
-	u32 cur, cons;
-
-	cur  = br32(bp, B44_DMATX_STAT) & DMATX_STAT_CDMASK;
-	cur /= sizeof(struct dma_desc);
-
-	/* XXX needs updating when NETIF_F_SG is supported */
-	for (cons = bp->tx_cons; cons != cur; cons = NEXT_TX(cons)) {
-		struct ring_info *rp = &bp->tx_buffers[cons];
-		struct sk_buff *skb = rp->skb;
-
-		BUG_ON(skb == NULL);
-
-		dma_unmap_single(bp->sdev->dma_dev,
-				 rp->mapping,
-				 skb->len,
-				 DMA_TO_DEVICE);
-		rp->skb = NULL;
-		dev_kfree_skb(skb);
-	}
-
-	bp->tx_cons = cons;
-	if (netif_queue_stopped(bp->dev) &&
-	    TX_BUFFS_AVAIL(bp) > B44_TX_WAKEUP_THRESH)
-		netif_wake_queue(bp->dev);
-
-	bw32(bp, B44_GPTIMER, 0);
-}
-
-/* Works like this.  This chip writes a 'struct rx_header" 30 bytes
- * before the DMA address you give it.  So we allocate 30 more bytes
- * for the RX buffer, DMA map all of it, skb_reserve the 30 bytes, then
- * point the chip at 30 bytes past where the rx_header will go.
- */
-static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
-{
-	struct dma_desc *dp;
-	struct ring_info *src_map, *map;
-	struct rx_header *rh;
-	struct sk_buff *skb;
-	dma_addr_t mapping;
-	int dest_idx;
-	u32 ctrl;
-
-	src_map = NULL;
-	if (src_idx >= 0)
-		src_map = &bp->rx_buffers[src_idx];
-	dest_idx = dest_idx_unmasked & (B44_RX_RING_SIZE - 1);
-	map = &bp->rx_buffers[dest_idx];
-	skb = netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ);
-	if (skb == NULL)
-		return -ENOMEM;
-
-	mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
-				 RX_PKT_BUF_SZ,
-				 DMA_FROM_DEVICE);
-
-	/* Hardware bug work-around, the chip is unable to do PCI DMA
-	   to/from anything above 1GB :-( */
-	if (dma_mapping_error(bp->sdev->dma_dev, mapping) ||
-		mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
-		/* Sigh... */
-		if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
-			dma_unmap_single(bp->sdev->dma_dev, mapping,
-					     RX_PKT_BUF_SZ, DMA_FROM_DEVICE);
-		dev_kfree_skb_any(skb);
-		skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
-		if (skb == NULL)
-			return -ENOMEM;
-		mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
-					 RX_PKT_BUF_SZ,
-					 DMA_FROM_DEVICE);
-		if (dma_mapping_error(bp->sdev->dma_dev, mapping) ||
-		    mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
-			if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
-				dma_unmap_single(bp->sdev->dma_dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
-			dev_kfree_skb_any(skb);
-			return -ENOMEM;
-		}
-		bp->force_copybreak = 1;
-	}
-
-	rh = (struct rx_header *) skb->data;
-
-	rh->len = 0;
-	rh->flags = 0;
-
-	map->skb = skb;
-	map->mapping = mapping;
-
-	if (src_map != NULL)
-		src_map->skb = NULL;
-
-	ctrl = (DESC_CTRL_LEN & RX_PKT_BUF_SZ);
-	if (dest_idx == (B44_RX_RING_SIZE - 1))
-		ctrl |= DESC_CTRL_EOT;
-
-	dp = &bp->rx_ring[dest_idx];
-	dp->ctrl = cpu_to_le32(ctrl);
-	dp->addr = cpu_to_le32((u32) mapping + bp->dma_offset);
-
-	if (bp->flags & B44_FLAG_RX_RING_HACK)
-		b44_sync_dma_desc_for_device(bp->sdev, bp->rx_ring_dma,
-			                    dest_idx * sizeof(*dp),
-			                    DMA_BIDIRECTIONAL);
-
-	return RX_PKT_BUF_SZ;
-}
-
-static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
-{
-	struct dma_desc *src_desc, *dest_desc;
-	struct ring_info *src_map, *dest_map;
-	struct rx_header *rh;
-	int dest_idx;
-	__le32 ctrl;
-
-	dest_idx = dest_idx_unmasked & (B44_RX_RING_SIZE - 1);
-	dest_desc = &bp->rx_ring[dest_idx];
-	dest_map = &bp->rx_buffers[dest_idx];
-	src_desc = &bp->rx_ring[src_idx];
-	src_map = &bp->rx_buffers[src_idx];
-
-	dest_map->skb = src_map->skb;
-	rh = (struct rx_header *) src_map->skb->data;
-	rh->len = 0;
-	rh->flags = 0;
-	dest_map->mapping = src_map->mapping;
-
-	if (bp->flags & B44_FLAG_RX_RING_HACK)
-		b44_sync_dma_desc_for_cpu(bp->sdev, bp->rx_ring_dma,
-			                 src_idx * sizeof(*src_desc),
-			                 DMA_BIDIRECTIONAL);
-
-	ctrl = src_desc->ctrl;
-	if (dest_idx == (B44_RX_RING_SIZE - 1))
-		ctrl |= cpu_to_le32(DESC_CTRL_EOT);
-	else
-		ctrl &= cpu_to_le32(~DESC_CTRL_EOT);
-
-	dest_desc->ctrl = ctrl;
-	dest_desc->addr = src_desc->addr;
-
-	src_map->skb = NULL;
-
-	if (bp->flags & B44_FLAG_RX_RING_HACK)
-		b44_sync_dma_desc_for_device(bp->sdev, bp->rx_ring_dma,
-					     dest_idx * sizeof(*dest_desc),
-					     DMA_BIDIRECTIONAL);
-
-	dma_sync_single_for_device(bp->sdev->dma_dev, dest_map->mapping,
-				   RX_PKT_BUF_SZ,
-				   DMA_FROM_DEVICE);
-}
-
-static int b44_rx(struct b44 *bp, int budget)
-{
-	int received;
-	u32 cons, prod;
-
-	received = 0;
-	prod  = br32(bp, B44_DMARX_STAT) & DMARX_STAT_CDMASK;
-	prod /= sizeof(struct dma_desc);
-	cons = bp->rx_cons;
-
-	while (cons != prod && budget > 0) {
-		struct ring_info *rp = &bp->rx_buffers[cons];
-		struct sk_buff *skb = rp->skb;
-		dma_addr_t map = rp->mapping;
-		struct rx_header *rh;
-		u16 len;
-
-		dma_sync_single_for_cpu(bp->sdev->dma_dev, map,
-					RX_PKT_BUF_SZ,
-					DMA_FROM_DEVICE);
-		rh = (struct rx_header *) skb->data;
-		len = le16_to_cpu(rh->len);
-		if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) ||
-		    (rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
-		drop_it:
-			b44_recycle_rx(bp, cons, bp->rx_prod);
-		drop_it_no_recycle:
-			bp->dev->stats.rx_dropped++;
-			goto next_pkt;
-		}
-
-		if (len == 0) {
-			int i = 0;
-
-			do {
-				udelay(2);
-				barrier();
-				len = le16_to_cpu(rh->len);
-			} while (len == 0 && i++ < 5);
-			if (len == 0)
-				goto drop_it;
-		}
-
-		/* Omit CRC. */
-		len -= 4;
-
-		if (!bp->force_copybreak && len > RX_COPY_THRESHOLD) {
-			int skb_size;
-			skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod);
-			if (skb_size < 0)
-				goto drop_it;
-			dma_unmap_single(bp->sdev->dma_dev, map,
-					 skb_size, DMA_FROM_DEVICE);
-			/* Leave out rx_header */
-			skb_put(skb, len + RX_PKT_OFFSET);
-			skb_pull(skb, RX_PKT_OFFSET);
-		} else {
-			struct sk_buff *copy_skb;
-
-			b44_recycle_rx(bp, cons, bp->rx_prod);
-			copy_skb = netdev_alloc_skb(bp->dev, len + 2);
-			if (copy_skb == NULL)
-				goto drop_it_no_recycle;
-
-			skb_reserve(copy_skb, 2);
-			skb_put(copy_skb, len);
-			/* DMA sync done above, copy just the actual packet */
-			skb_copy_from_linear_data_offset(skb, RX_PKT_OFFSET,
-							 copy_skb->data, len);
-			skb = copy_skb;
-		}
-		skb_checksum_none_assert(skb);
-		skb->protocol = eth_type_trans(skb, bp->dev);
-		netif_receive_skb(skb);
-		received++;
-		budget--;
-	next_pkt:
-		bp->rx_prod = (bp->rx_prod + 1) &
-			(B44_RX_RING_SIZE - 1);
-		cons = (cons + 1) & (B44_RX_RING_SIZE - 1);
-	}
-
-	bp->rx_cons = cons;
-	bw32(bp, B44_DMARX_PTR, cons * sizeof(struct dma_desc));
-
-	return received;
-}
-
-static int b44_poll(struct napi_struct *napi, int budget)
-{
-	struct b44 *bp = container_of(napi, struct b44, napi);
-	int work_done;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bp->lock, flags);
-
-	if (bp->istat & (ISTAT_TX | ISTAT_TO)) {
-		/* spin_lock(&bp->tx_lock); */
-		b44_tx(bp);
-		/* spin_unlock(&bp->tx_lock); */
-	}
-	if (bp->istat & ISTAT_RFO) {	/* fast recovery, in ~20msec */
-		bp->istat &= ~ISTAT_RFO;
-		b44_disable_ints(bp);
-		ssb_device_enable(bp->sdev, 0); /* resets ISTAT_RFO */
-		b44_init_rings(bp);
-		b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
-		netif_wake_queue(bp->dev);
-	}
-
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	work_done = 0;
-	if (bp->istat & ISTAT_RX)
-		work_done += b44_rx(bp, budget);
-
-	if (bp->istat & ISTAT_ERRORS) {
-		spin_lock_irqsave(&bp->lock, flags);
-		b44_halt(bp);
-		b44_init_rings(bp);
-		b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
-		netif_wake_queue(bp->dev);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		work_done = 0;
-	}
-
-	if (work_done < budget) {
-		napi_complete(napi);
-		b44_enable_ints(bp);
-	}
-
-	return work_done;
-}
-
-static irqreturn_t b44_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct b44 *bp = netdev_priv(dev);
-	u32 istat, imask;
-	int handled = 0;
-
-	spin_lock(&bp->lock);
-
-	istat = br32(bp, B44_ISTAT);
-	imask = br32(bp, B44_IMASK);
-
-	/* The interrupt mask register controls which interrupt bits
-	 * will actually raise an interrupt to the CPU when set by hw/firmware,
-	 * but doesn't mask off the bits.
-	 */
-	istat &= imask;
-	if (istat) {
-		handled = 1;
-
-		if (unlikely(!netif_running(dev))) {
-			netdev_info(dev, "late interrupt\n");
-			goto irq_ack;
-		}
-
-		if (napi_schedule_prep(&bp->napi)) {
-			/* NOTE: These writes are posted by the readback of
-			 *       the ISTAT register below.
-			 */
-			bp->istat = istat;
-			__b44_disable_ints(bp);
-			__napi_schedule(&bp->napi);
-		}
-
-irq_ack:
-		bw32(bp, B44_ISTAT, istat);
-		br32(bp, B44_ISTAT);
-	}
-	spin_unlock(&bp->lock);
-	return IRQ_RETVAL(handled);
-}
-
-static void b44_tx_timeout(struct net_device *dev)
-{
-	struct b44 *bp = netdev_priv(dev);
-
-	netdev_err(dev, "transmit timed out, resetting\n");
-
-	spin_lock_irq(&bp->lock);
-
-	b44_halt(bp);
-	b44_init_rings(bp);
-	b44_init_hw(bp, B44_FULL_RESET);
-
-	spin_unlock_irq(&bp->lock);
-
-	b44_enable_ints(bp);
-
-	netif_wake_queue(dev);
-}
-
-static netdev_tx_t b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct b44 *bp = netdev_priv(dev);
-	int rc = NETDEV_TX_OK;
-	dma_addr_t mapping;
-	u32 len, entry, ctrl;
-	unsigned long flags;
-
-	len = skb->len;
-	spin_lock_irqsave(&bp->lock, flags);
-
-	/* This is a hard error, log it. */
-	if (unlikely(TX_BUFFS_AVAIL(bp) < 1)) {
-		netif_stop_queue(dev);
-		netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
-		goto err_out;
-	}
-
-	mapping = dma_map_single(bp->sdev->dma_dev, skb->data, len, DMA_TO_DEVICE);
-	if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
-		struct sk_buff *bounce_skb;
-
-		/* Chip can't handle DMA to/from >1GB, use bounce buffer */
-		if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
-			dma_unmap_single(bp->sdev->dma_dev, mapping, len,
-					     DMA_TO_DEVICE);
-
-		bounce_skb = __netdev_alloc_skb(dev, len, GFP_ATOMIC | GFP_DMA);
-		if (!bounce_skb)
-			goto err_out;
-
-		mapping = dma_map_single(bp->sdev->dma_dev, bounce_skb->data,
-					 len, DMA_TO_DEVICE);
-		if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
-			if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
-				dma_unmap_single(bp->sdev->dma_dev, mapping,
-						     len, DMA_TO_DEVICE);
-			dev_kfree_skb_any(bounce_skb);
-			goto err_out;
-		}
-
-		skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), len);
-		dev_kfree_skb_any(skb);
-		skb = bounce_skb;
-	}
-
-	entry = bp->tx_prod;
-	bp->tx_buffers[entry].skb = skb;
-	bp->tx_buffers[entry].mapping = mapping;
-
-	ctrl  = (len & DESC_CTRL_LEN);
-	ctrl |= DESC_CTRL_IOC | DESC_CTRL_SOF | DESC_CTRL_EOF;
-	if (entry == (B44_TX_RING_SIZE - 1))
-		ctrl |= DESC_CTRL_EOT;
-
-	bp->tx_ring[entry].ctrl = cpu_to_le32(ctrl);
-	bp->tx_ring[entry].addr = cpu_to_le32((u32) mapping+bp->dma_offset);
-
-	if (bp->flags & B44_FLAG_TX_RING_HACK)
-		b44_sync_dma_desc_for_device(bp->sdev, bp->tx_ring_dma,
-			                    entry * sizeof(bp->tx_ring[0]),
-			                    DMA_TO_DEVICE);
-
-	entry = NEXT_TX(entry);
-
-	bp->tx_prod = entry;
-
-	wmb();
-
-	bw32(bp, B44_DMATX_PTR, entry * sizeof(struct dma_desc));
-	if (bp->flags & B44_FLAG_BUGGY_TXPTR)
-		bw32(bp, B44_DMATX_PTR, entry * sizeof(struct dma_desc));
-	if (bp->flags & B44_FLAG_REORDER_BUG)
-		br32(bp, B44_DMATX_PTR);
-
-	if (TX_BUFFS_AVAIL(bp) < 1)
-		netif_stop_queue(dev);
-
-out_unlock:
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	return rc;
-
-err_out:
-	rc = NETDEV_TX_BUSY;
-	goto out_unlock;
-}
-
-static int b44_change_mtu(struct net_device *dev, int new_mtu)
-{
-	struct b44 *bp = netdev_priv(dev);
-
-	if (new_mtu < B44_MIN_MTU || new_mtu > B44_MAX_MTU)
-		return -EINVAL;
-
-	if (!netif_running(dev)) {
-		/* We'll just catch it later when the
-		 * device is up'd.
-		 */
-		dev->mtu = new_mtu;
-		return 0;
-	}
-
-	spin_lock_irq(&bp->lock);
-	b44_halt(bp);
-	dev->mtu = new_mtu;
-	b44_init_rings(bp);
-	b44_init_hw(bp, B44_FULL_RESET);
-	spin_unlock_irq(&bp->lock);
-
-	b44_enable_ints(bp);
-
-	return 0;
-}
-
-/* Free up pending packets in all rx/tx rings.
- *
- * The chip has been shut down and the driver detached from
- * the networking, so no interrupts or new tx packets will
- * end up in the driver.  bp->lock is not held and we are not
- * in an interrupt context and thus may sleep.
- */
-static void b44_free_rings(struct b44 *bp)
-{
-	struct ring_info *rp;
-	int i;
-
-	for (i = 0; i < B44_RX_RING_SIZE; i++) {
-		rp = &bp->rx_buffers[i];
-
-		if (rp->skb == NULL)
-			continue;
-		dma_unmap_single(bp->sdev->dma_dev, rp->mapping, RX_PKT_BUF_SZ,
-				 DMA_FROM_DEVICE);
-		dev_kfree_skb_any(rp->skb);
-		rp->skb = NULL;
-	}
-
-	/* XXX needs changes once NETIF_F_SG is set... */
-	for (i = 0; i < B44_TX_RING_SIZE; i++) {
-		rp = &bp->tx_buffers[i];
-
-		if (rp->skb == NULL)
-			continue;
-		dma_unmap_single(bp->sdev->dma_dev, rp->mapping, rp->skb->len,
-				 DMA_TO_DEVICE);
-		dev_kfree_skb_any(rp->skb);
-		rp->skb = NULL;
-	}
-}
-
-/* Initialize tx/rx rings for packet processing.
- *
- * The chip has been shut down and the driver detached from
- * the networking, so no interrupts or new tx packets will
- * end up in the driver.
- */
-static void b44_init_rings(struct b44 *bp)
-{
-	int i;
-
-	b44_free_rings(bp);
-
-	memset(bp->rx_ring, 0, B44_RX_RING_BYTES);
-	memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
-
-	if (bp->flags & B44_FLAG_RX_RING_HACK)
-		dma_sync_single_for_device(bp->sdev->dma_dev, bp->rx_ring_dma,
-					   DMA_TABLE_BYTES, DMA_BIDIRECTIONAL);
-
-	if (bp->flags & B44_FLAG_TX_RING_HACK)
-		dma_sync_single_for_device(bp->sdev->dma_dev, bp->tx_ring_dma,
-					   DMA_TABLE_BYTES, DMA_TO_DEVICE);
-
-	for (i = 0; i < bp->rx_pending; i++) {
-		if (b44_alloc_rx_skb(bp, -1, i) < 0)
-			break;
-	}
-}
-
-/*
- * Must not be invoked with interrupt sources disabled and
- * the hardware shutdown down.
- */
-static void b44_free_consistent(struct b44 *bp)
-{
-	kfree(bp->rx_buffers);
-	bp->rx_buffers = NULL;
-	kfree(bp->tx_buffers);
-	bp->tx_buffers = NULL;
-	if (bp->rx_ring) {
-		if (bp->flags & B44_FLAG_RX_RING_HACK) {
-			dma_unmap_single(bp->sdev->dma_dev, bp->rx_ring_dma,
-					 DMA_TABLE_BYTES, DMA_BIDIRECTIONAL);
-			kfree(bp->rx_ring);
-		} else
-			dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
-					  bp->rx_ring, bp->rx_ring_dma);
-		bp->rx_ring = NULL;
-		bp->flags &= ~B44_FLAG_RX_RING_HACK;
-	}
-	if (bp->tx_ring) {
-		if (bp->flags & B44_FLAG_TX_RING_HACK) {
-			dma_unmap_single(bp->sdev->dma_dev, bp->tx_ring_dma,
-					 DMA_TABLE_BYTES, DMA_TO_DEVICE);
-			kfree(bp->tx_ring);
-		} else
-			dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
-					  bp->tx_ring, bp->tx_ring_dma);
-		bp->tx_ring = NULL;
-		bp->flags &= ~B44_FLAG_TX_RING_HACK;
-	}
-}
-
-/*
- * Must not be invoked with interrupt sources disabled and
- * the hardware shutdown down.  Can sleep.
- */
-static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
-{
-	int size;
-
-	size  = B44_RX_RING_SIZE * sizeof(struct ring_info);
-	bp->rx_buffers = kzalloc(size, gfp);
-	if (!bp->rx_buffers)
-		goto out_err;
-
-	size = B44_TX_RING_SIZE * sizeof(struct ring_info);
-	bp->tx_buffers = kzalloc(size, gfp);
-	if (!bp->tx_buffers)
-		goto out_err;
-
-	size = DMA_TABLE_BYTES;
-	bp->rx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size,
-					 &bp->rx_ring_dma, gfp);
-	if (!bp->rx_ring) {
-		/* Allocation may have failed due to pci_alloc_consistent
-		   insisting on use of GFP_DMA, which is more restrictive
-		   than necessary...  */
-		struct dma_desc *rx_ring;
-		dma_addr_t rx_ring_dma;
-
-		rx_ring = kzalloc(size, gfp);
-		if (!rx_ring)
-			goto out_err;
-
-		rx_ring_dma = dma_map_single(bp->sdev->dma_dev, rx_ring,
-					     DMA_TABLE_BYTES,
-					     DMA_BIDIRECTIONAL);
-
-		if (dma_mapping_error(bp->sdev->dma_dev, rx_ring_dma) ||
-			rx_ring_dma + size > DMA_BIT_MASK(30)) {
-			kfree(rx_ring);
-			goto out_err;
-		}
-
-		bp->rx_ring = rx_ring;
-		bp->rx_ring_dma = rx_ring_dma;
-		bp->flags |= B44_FLAG_RX_RING_HACK;
-	}
-
-	bp->tx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size,
-					 &bp->tx_ring_dma, gfp);
-	if (!bp->tx_ring) {
-		/* Allocation may have failed due to ssb_dma_alloc_consistent
-		   insisting on use of GFP_DMA, which is more restrictive
-		   than necessary...  */
-		struct dma_desc *tx_ring;
-		dma_addr_t tx_ring_dma;
-
-		tx_ring = kzalloc(size, gfp);
-		if (!tx_ring)
-			goto out_err;
-
-		tx_ring_dma = dma_map_single(bp->sdev->dma_dev, tx_ring,
-					     DMA_TABLE_BYTES,
-					     DMA_TO_DEVICE);
-
-		if (dma_mapping_error(bp->sdev->dma_dev, tx_ring_dma) ||
-			tx_ring_dma + size > DMA_BIT_MASK(30)) {
-			kfree(tx_ring);
-			goto out_err;
-		}
-
-		bp->tx_ring = tx_ring;
-		bp->tx_ring_dma = tx_ring_dma;
-		bp->flags |= B44_FLAG_TX_RING_HACK;
-	}
-
-	return 0;
-
-out_err:
-	b44_free_consistent(bp);
-	return -ENOMEM;
-}
-
-/* bp->lock is held. */
-static void b44_clear_stats(struct b44 *bp)
-{
-	unsigned long reg;
-
-	bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
-	for (reg = B44_TX_GOOD_O; reg <= B44_TX_PAUSE; reg += 4UL)
-		br32(bp, reg);
-	for (reg = B44_RX_GOOD_O; reg <= B44_RX_NPAUSE; reg += 4UL)
-		br32(bp, reg);
-}
-
-/* bp->lock is held. */
-static void b44_chip_reset(struct b44 *bp, int reset_kind)
-{
-	struct ssb_device *sdev = bp->sdev;
-	bool was_enabled;
-
-	was_enabled = ssb_device_is_enabled(bp->sdev);
-
-	ssb_device_enable(bp->sdev, 0);
-	ssb_pcicore_dev_irqvecs_enable(&sdev->bus->pcicore, sdev);
-
-	if (was_enabled) {
-		bw32(bp, B44_RCV_LAZY, 0);
-		bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE);
-		b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1);
-		bw32(bp, B44_DMATX_CTRL, 0);
-		bp->tx_prod = bp->tx_cons = 0;
-		if (br32(bp, B44_DMARX_STAT) & DMARX_STAT_EMASK) {
-			b44_wait_bit(bp, B44_DMARX_STAT, DMARX_STAT_SIDLE,
-				     100, 0);
-		}
-		bw32(bp, B44_DMARX_CTRL, 0);
-		bp->rx_prod = bp->rx_cons = 0;
-	}
-
-	b44_clear_stats(bp);
-
-	/*
-	 * Don't enable PHY if we are doing a partial reset
-	 * we are probably going to power down
-	 */
-	if (reset_kind == B44_CHIP_RESET_PARTIAL)
-		return;
-
-	switch (sdev->bus->bustype) {
-	case SSB_BUSTYPE_SSB:
-		bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
-		     (DIV_ROUND_CLOSEST(ssb_clockspeed(sdev->bus),
-					B44_MDC_RATIO)
-		     & MDIO_CTRL_MAXF_MASK)));
-		break;
-	case SSB_BUSTYPE_PCI:
-		bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
-		     (0x0d & MDIO_CTRL_MAXF_MASK)));
-		break;
-	case SSB_BUSTYPE_PCMCIA:
-	case SSB_BUSTYPE_SDIO:
-		WARN_ON(1); /* A device with this bus does not exist. */
-		break;
-	}
-
-	br32(bp, B44_MDIO_CTRL);
-
-	if (!(br32(bp, B44_DEVCTRL) & DEVCTRL_IPP)) {
-		bw32(bp, B44_ENET_CTRL, ENET_CTRL_EPSEL);
-		br32(bp, B44_ENET_CTRL);
-		bp->flags &= ~B44_FLAG_INTERNAL_PHY;
-	} else {
-		u32 val = br32(bp, B44_DEVCTRL);
-
-		if (val & DEVCTRL_EPR) {
-			bw32(bp, B44_DEVCTRL, (val & ~DEVCTRL_EPR));
-			br32(bp, B44_DEVCTRL);
-			udelay(100);
-		}
-		bp->flags |= B44_FLAG_INTERNAL_PHY;
-	}
-}
-
-/* bp->lock is held. */
-static void b44_halt(struct b44 *bp)
-{
-	b44_disable_ints(bp);
-	/* reset PHY */
-	b44_phy_reset(bp);
-	/* power down PHY */
-	netdev_info(bp->dev, "powering down PHY\n");
-	bw32(bp, B44_MAC_CTRL, MAC_CTRL_PHY_PDOWN);
-	/* now reset the chip, but without enabling the MAC&PHY
-	 * part of it. This has to be done _after_ we shut down the PHY */
-	b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL);
-}
-
-/* bp->lock is held. */
-static void __b44_set_mac_addr(struct b44 *bp)
-{
-	bw32(bp, B44_CAM_CTRL, 0);
-	if (!(bp->dev->flags & IFF_PROMISC)) {
-		u32 val;
-
-		__b44_cam_write(bp, bp->dev->dev_addr, 0);
-		val = br32(bp, B44_CAM_CTRL);
-		bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
-	}
-}
-
-static int b44_set_mac_addr(struct net_device *dev, void *p)
-{
-	struct b44 *bp = netdev_priv(dev);
-	struct sockaddr *addr = p;
-	u32 val;
-
-	if (netif_running(dev))
-		return -EBUSY;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EINVAL;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
-	spin_lock_irq(&bp->lock);
-
-	val = br32(bp, B44_RXCONFIG);
-	if (!(val & RXCONFIG_CAM_ABSENT))
-		__b44_set_mac_addr(bp);
-
-	spin_unlock_irq(&bp->lock);
-
-	return 0;
-}
-
-/* Called at device open time to get the chip ready for
- * packet processing.  Invoked with bp->lock held.
- */
-static void __b44_set_rx_mode(struct net_device *);
-static void b44_init_hw(struct b44 *bp, int reset_kind)
-{
-	u32 val;
-
-	b44_chip_reset(bp, B44_CHIP_RESET_FULL);
-	if (reset_kind == B44_FULL_RESET) {
-		b44_phy_reset(bp);
-		b44_setup_phy(bp);
-	}
-
-	/* Enable CRC32, set proper LED modes and power on PHY */
-	bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
-	bw32(bp, B44_RCV_LAZY, (1 << RCV_LAZY_FC_SHIFT));
-
-	/* This sets the MAC address too.  */
-	__b44_set_rx_mode(bp->dev);
-
-	/* MTU + eth header + possible VLAN tag + struct rx_header */
-	bw32(bp, B44_RXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
-	bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
-
-	bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
-	if (reset_kind == B44_PARTIAL_RESET) {
-		bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
-				      (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT)));
-	} else {
-		bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
-		bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
-		bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
-				      (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT)));
-		bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
-
-		bw32(bp, B44_DMARX_PTR, bp->rx_pending);
-		bp->rx_prod = bp->rx_pending;
-
-		bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
-	}
-
-	val = br32(bp, B44_ENET_CTRL);
-	bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
-}
-
-static int b44_open(struct net_device *dev)
-{
-	struct b44 *bp = netdev_priv(dev);
-	int err;
-
-	err = b44_alloc_consistent(bp, GFP_KERNEL);
-	if (err)
-		goto out;
-
-	napi_enable(&bp->napi);
-
-	b44_init_rings(bp);
-	b44_init_hw(bp, B44_FULL_RESET);
-
-	b44_check_phy(bp);
-
-	err = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev);
-	if (unlikely(err < 0)) {
-		napi_disable(&bp->napi);
-		b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL);
-		b44_free_rings(bp);
-		b44_free_consistent(bp);
-		goto out;
-	}
-
-	init_timer(&bp->timer);
-	bp->timer.expires = jiffies + HZ;
-	bp->timer.data = (unsigned long) bp;
-	bp->timer.function = b44_timer;
-	add_timer(&bp->timer);
-
-	b44_enable_ints(bp);
-	netif_start_queue(dev);
-out:
-	return err;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Polling receive - used by netconsole and other diagnostic tools
- * to allow network i/o with interrupts disabled.
- */
-static void b44_poll_controller(struct net_device *dev)
-{
-	disable_irq(dev->irq);
-	b44_interrupt(dev->irq, dev);
-	enable_irq(dev->irq);
-}
-#endif
-
-static void bwfilter_table(struct b44 *bp, u8 *pp, u32 bytes, u32 table_offset)
-{
-	u32 i;
-	u32 *pattern = (u32 *) pp;
-
-	for (i = 0; i < bytes; i += sizeof(u32)) {
-		bw32(bp, B44_FILT_ADDR, table_offset + i);
-		bw32(bp, B44_FILT_DATA, pattern[i / sizeof(u32)]);
-	}
-}
-
-static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset)
-{
-	int magicsync = 6;
-	int k, j, len = offset;
-	int ethaddr_bytes = ETH_ALEN;
-
-	memset(ppattern + offset, 0xff, magicsync);
-	for (j = 0; j < magicsync; j++)
-		set_bit(len++, (unsigned long *) pmask);
-
-	for (j = 0; j < B44_MAX_PATTERNS; j++) {
-		if ((B44_PATTERN_SIZE - len) >= ETH_ALEN)
-			ethaddr_bytes = ETH_ALEN;
-		else
-			ethaddr_bytes = B44_PATTERN_SIZE - len;
-		if (ethaddr_bytes <=0)
-			break;
-		for (k = 0; k< ethaddr_bytes; k++) {
-			ppattern[offset + magicsync +
-				(j * ETH_ALEN) + k] = macaddr[k];
-			set_bit(len++, (unsigned long *) pmask);
-		}
-	}
-	return len - 1;
-}
-
-/* Setup magic packet patterns in the b44 WOL
- * pattern matching filter.
- */
-static void b44_setup_pseudo_magicp(struct b44 *bp)
-{
-
-	u32 val;
-	int plen0, plen1, plen2;
-	u8 *pwol_pattern;
-	u8 pwol_mask[B44_PMASK_SIZE];
-
-	pwol_pattern = kzalloc(B44_PATTERN_SIZE, GFP_KERNEL);
-	if (!pwol_pattern) {
-		pr_err("Memory not available for WOL\n");
-		return;
-	}
-
-	/* Ipv4 magic packet pattern - pattern 0.*/
-	memset(pwol_mask, 0, B44_PMASK_SIZE);
-	plen0 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask,
-				  B44_ETHIPV4UDP_HLEN);
-
-   	bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE, B44_PATTERN_BASE);
-   	bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE, B44_PMASK_BASE);
-
-	/* Raw ethernet II magic packet pattern - pattern 1 */
-	memset(pwol_pattern, 0, B44_PATTERN_SIZE);
-	memset(pwol_mask, 0, B44_PMASK_SIZE);
-	plen1 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask,
-				  ETH_HLEN);
-
-   	bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE,
-		       B44_PATTERN_BASE + B44_PATTERN_SIZE);
-  	bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE,
-		       B44_PMASK_BASE + B44_PMASK_SIZE);
-
-	/* Ipv6 magic packet pattern - pattern 2 */
-	memset(pwol_pattern, 0, B44_PATTERN_SIZE);
-	memset(pwol_mask, 0, B44_PMASK_SIZE);
-	plen2 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask,
-				  B44_ETHIPV6UDP_HLEN);
-
-   	bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE,
-		       B44_PATTERN_BASE + B44_PATTERN_SIZE + B44_PATTERN_SIZE);
-  	bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE,
-		       B44_PMASK_BASE + B44_PMASK_SIZE + B44_PMASK_SIZE);
-
-	kfree(pwol_pattern);
-
-	/* set these pattern's lengths: one less than each real length */
-	val = plen0 | (plen1 << 8) | (plen2 << 16) | WKUP_LEN_ENABLE_THREE;
-	bw32(bp, B44_WKUP_LEN, val);
-
-	/* enable wakeup pattern matching */
-	val = br32(bp, B44_DEVCTRL);
-	bw32(bp, B44_DEVCTRL, val | DEVCTRL_PFE);
-
-}
-
-#ifdef CONFIG_B44_PCI
-static void b44_setup_wol_pci(struct b44 *bp)
-{
-	u16 val;
-
-	if (bp->sdev->bus->bustype != SSB_BUSTYPE_SSB) {
-		bw32(bp, SSB_TMSLOW, br32(bp, SSB_TMSLOW) | SSB_TMSLOW_PE);
-		pci_read_config_word(bp->sdev->bus->host_pci, SSB_PMCSR, &val);
-		pci_write_config_word(bp->sdev->bus->host_pci, SSB_PMCSR, val | SSB_PE);
-	}
-}
-#else
-static inline void b44_setup_wol_pci(struct b44 *bp) { }
-#endif /* CONFIG_B44_PCI */
-
-static void b44_setup_wol(struct b44 *bp)
-{
-	u32 val;
-
-	bw32(bp, B44_RXCONFIG, RXCONFIG_ALLMULTI);
-
-	if (bp->flags & B44_FLAG_B0_ANDLATER) {
-
-		bw32(bp, B44_WKUP_LEN, WKUP_LEN_DISABLE);
-
-		val = bp->dev->dev_addr[2] << 24 |
-			bp->dev->dev_addr[3] << 16 |
-			bp->dev->dev_addr[4] << 8 |
-			bp->dev->dev_addr[5];
-		bw32(bp, B44_ADDR_LO, val);
-
-		val = bp->dev->dev_addr[0] << 8 |
-			bp->dev->dev_addr[1];
-		bw32(bp, B44_ADDR_HI, val);
-
-		val = br32(bp, B44_DEVCTRL);
-		bw32(bp, B44_DEVCTRL, val | DEVCTRL_MPM | DEVCTRL_PFE);
-
- 	} else {
- 		b44_setup_pseudo_magicp(bp);
- 	}
-	b44_setup_wol_pci(bp);
-}
-
-static int b44_close(struct net_device *dev)
-{
-	struct b44 *bp = netdev_priv(dev);
-
-	netif_stop_queue(dev);
-
-	napi_disable(&bp->napi);
-
-	del_timer_sync(&bp->timer);
-
-	spin_lock_irq(&bp->lock);
-
-	b44_halt(bp);
-	b44_free_rings(bp);
-	netif_carrier_off(dev);
-
-	spin_unlock_irq(&bp->lock);
-
-	free_irq(dev->irq, dev);
-
-	if (bp->flags & B44_FLAG_WOL_ENABLE) {
-		b44_init_hw(bp, B44_PARTIAL_RESET);
-		b44_setup_wol(bp);
-	}
-
-	b44_free_consistent(bp);
-
-	return 0;
-}
-
-static struct net_device_stats *b44_get_stats(struct net_device *dev)
-{
-	struct b44 *bp = netdev_priv(dev);
-	struct net_device_stats *nstat = &dev->stats;
-	struct b44_hw_stats *hwstat = &bp->hw_stats;
-
-	/* Convert HW stats into netdevice stats. */
-	nstat->rx_packets = hwstat->rx_pkts;
-	nstat->tx_packets = hwstat->tx_pkts;
-	nstat->rx_bytes   = hwstat->rx_octets;
-	nstat->tx_bytes   = hwstat->tx_octets;
-	nstat->tx_errors  = (hwstat->tx_jabber_pkts +
-			     hwstat->tx_oversize_pkts +
-			     hwstat->tx_underruns +
-			     hwstat->tx_excessive_cols +
-			     hwstat->tx_late_cols);
-	nstat->multicast  = hwstat->tx_multicast_pkts;
-	nstat->collisions = hwstat->tx_total_cols;
-
-	nstat->rx_length_errors = (hwstat->rx_oversize_pkts +
-				   hwstat->rx_undersize);
-	nstat->rx_over_errors   = hwstat->rx_missed_pkts;
-	nstat->rx_frame_errors  = hwstat->rx_align_errs;
-	nstat->rx_crc_errors    = hwstat->rx_crc_errs;
-	nstat->rx_errors        = (hwstat->rx_jabber_pkts +
-				   hwstat->rx_oversize_pkts +
-				   hwstat->rx_missed_pkts +
-				   hwstat->rx_crc_align_errs +
-				   hwstat->rx_undersize +
-				   hwstat->rx_crc_errs +
-				   hwstat->rx_align_errs +
-				   hwstat->rx_symbol_errs);
-
-	nstat->tx_aborted_errors = hwstat->tx_underruns;
-#if 0
-	/* Carrier lost counter seems to be broken for some devices */
-	nstat->tx_carrier_errors = hwstat->tx_carrier_lost;
-#endif
-
-	return nstat;
-}
-
-static int __b44_load_mcast(struct b44 *bp, struct net_device *dev)
-{
-	struct netdev_hw_addr *ha;
-	int i, num_ents;
-
-	num_ents = min_t(int, netdev_mc_count(dev), B44_MCAST_TABLE_SIZE);
-	i = 0;
-	netdev_for_each_mc_addr(ha, dev) {
-		if (i == num_ents)
-			break;
-		__b44_cam_write(bp, ha->addr, i++ + 1);
-	}
-	return i+1;
-}
-
-static void __b44_set_rx_mode(struct net_device *dev)
-{
-	struct b44 *bp = netdev_priv(dev);
-	u32 val;
-
-	val = br32(bp, B44_RXCONFIG);
-	val &= ~(RXCONFIG_PROMISC | RXCONFIG_ALLMULTI);
-	if ((dev->flags & IFF_PROMISC) || (val & RXCONFIG_CAM_ABSENT)) {
-		val |= RXCONFIG_PROMISC;
-		bw32(bp, B44_RXCONFIG, val);
-	} else {
-		unsigned char zero[6] = {0, 0, 0, 0, 0, 0};
-		int i = 1;
-
-		__b44_set_mac_addr(bp);
-
-		if ((dev->flags & IFF_ALLMULTI) ||
-		    (netdev_mc_count(dev) > B44_MCAST_TABLE_SIZE))
-			val |= RXCONFIG_ALLMULTI;
-		else
-			i = __b44_load_mcast(bp, dev);
-
-		for (; i < 64; i++)
-			__b44_cam_write(bp, zero, i);
-
-		bw32(bp, B44_RXCONFIG, val);
-        	val = br32(bp, B44_CAM_CTRL);
-	        bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
-	}
-}
-
-static void b44_set_rx_mode(struct net_device *dev)
-{
-	struct b44 *bp = netdev_priv(dev);
-
-	spin_lock_irq(&bp->lock);
-	__b44_set_rx_mode(dev);
-	spin_unlock_irq(&bp->lock);
-}
-
-static u32 b44_get_msglevel(struct net_device *dev)
-{
-	struct b44 *bp = netdev_priv(dev);
-	return bp->msg_enable;
-}
-
-static void b44_set_msglevel(struct net_device *dev, u32 value)
-{
-	struct b44 *bp = netdev_priv(dev);
-	bp->msg_enable = value;
-}
-
-static void b44_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct b44 *bp = netdev_priv(dev);
-	struct ssb_bus *bus = bp->sdev->bus;
-
-	strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
-	strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
-	switch (bus->bustype) {
-	case SSB_BUSTYPE_PCI:
-		strlcpy(info->bus_info, pci_name(bus->host_pci), sizeof(info->bus_info));
-		break;
-	case SSB_BUSTYPE_SSB:
-		strlcpy(info->bus_info, "SSB", sizeof(info->bus_info));
-		break;
-	case SSB_BUSTYPE_PCMCIA:
-	case SSB_BUSTYPE_SDIO:
-		WARN_ON(1); /* A device with this bus does not exist. */
-		break;
-	}
-}
-
-static int b44_nway_reset(struct net_device *dev)
-{
-	struct b44 *bp = netdev_priv(dev);
-	u32 bmcr;
-	int r;
-
-	spin_lock_irq(&bp->lock);
-	b44_readphy(bp, MII_BMCR, &bmcr);
-	b44_readphy(bp, MII_BMCR, &bmcr);
-	r = -EINVAL;
-	if (bmcr & BMCR_ANENABLE) {
-		b44_writephy(bp, MII_BMCR,
-			     bmcr | BMCR_ANRESTART);
-		r = 0;
-	}
-	spin_unlock_irq(&bp->lock);
-
-	return r;
-}
-
-static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct b44 *bp = netdev_priv(dev);
-
-	cmd->supported = (SUPPORTED_Autoneg);
-	cmd->supported |= (SUPPORTED_100baseT_Half |
-			  SUPPORTED_100baseT_Full |
-			  SUPPORTED_10baseT_Half |
-			  SUPPORTED_10baseT_Full |
-			  SUPPORTED_MII);
-
-	cmd->advertising = 0;
-	if (bp->flags & B44_FLAG_ADV_10HALF)
-		cmd->advertising |= ADVERTISED_10baseT_Half;
-	if (bp->flags & B44_FLAG_ADV_10FULL)
-		cmd->advertising |= ADVERTISED_10baseT_Full;
-	if (bp->flags & B44_FLAG_ADV_100HALF)
-		cmd->advertising |= ADVERTISED_100baseT_Half;
-	if (bp->flags & B44_FLAG_ADV_100FULL)
-		cmd->advertising |= ADVERTISED_100baseT_Full;
-	cmd->advertising |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
-	ethtool_cmd_speed_set(cmd, ((bp->flags & B44_FLAG_100_BASE_T) ?
-				    SPEED_100 : SPEED_10));
-	cmd->duplex = (bp->flags & B44_FLAG_FULL_DUPLEX) ?
-		DUPLEX_FULL : DUPLEX_HALF;
-	cmd->port = 0;
-	cmd->phy_address = bp->phy_addr;
-	cmd->transceiver = (bp->flags & B44_FLAG_INTERNAL_PHY) ?
-		XCVR_INTERNAL : XCVR_EXTERNAL;
-	cmd->autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ?
-		AUTONEG_DISABLE : AUTONEG_ENABLE;
-	if (cmd->autoneg == AUTONEG_ENABLE)
-		cmd->advertising |= ADVERTISED_Autoneg;
-	if (!netif_running(dev)){
-		ethtool_cmd_speed_set(cmd, 0);
-		cmd->duplex = 0xff;
-	}
-	cmd->maxtxpkt = 0;
-	cmd->maxrxpkt = 0;
-	return 0;
-}
-
-static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct b44 *bp = netdev_priv(dev);
-	u32 speed = ethtool_cmd_speed(cmd);
-
-	/* We do not support gigabit. */
-	if (cmd->autoneg == AUTONEG_ENABLE) {
-		if (cmd->advertising &
-		    (ADVERTISED_1000baseT_Half |
-		     ADVERTISED_1000baseT_Full))
-			return -EINVAL;
-	} else if ((speed != SPEED_100 &&
-		    speed != SPEED_10) ||
-		   (cmd->duplex != DUPLEX_HALF &&
-		    cmd->duplex != DUPLEX_FULL)) {
-			return -EINVAL;
-	}
-
-	spin_lock_irq(&bp->lock);
-
-	if (cmd->autoneg == AUTONEG_ENABLE) {
-		bp->flags &= ~(B44_FLAG_FORCE_LINK |
-			       B44_FLAG_100_BASE_T |
-			       B44_FLAG_FULL_DUPLEX |
-			       B44_FLAG_ADV_10HALF |
-			       B44_FLAG_ADV_10FULL |
-			       B44_FLAG_ADV_100HALF |
-			       B44_FLAG_ADV_100FULL);
-		if (cmd->advertising == 0) {
-			bp->flags |= (B44_FLAG_ADV_10HALF |
-				      B44_FLAG_ADV_10FULL |
-				      B44_FLAG_ADV_100HALF |
-				      B44_FLAG_ADV_100FULL);
-		} else {
-			if (cmd->advertising & ADVERTISED_10baseT_Half)
-				bp->flags |= B44_FLAG_ADV_10HALF;
-			if (cmd->advertising & ADVERTISED_10baseT_Full)
-				bp->flags |= B44_FLAG_ADV_10FULL;
-			if (cmd->advertising & ADVERTISED_100baseT_Half)
-				bp->flags |= B44_FLAG_ADV_100HALF;
-			if (cmd->advertising & ADVERTISED_100baseT_Full)
-				bp->flags |= B44_FLAG_ADV_100FULL;
-		}
-	} else {
-		bp->flags |= B44_FLAG_FORCE_LINK;
-		bp->flags &= ~(B44_FLAG_100_BASE_T | B44_FLAG_FULL_DUPLEX);
-		if (speed == SPEED_100)
-			bp->flags |= B44_FLAG_100_BASE_T;
-		if (cmd->duplex == DUPLEX_FULL)
-			bp->flags |= B44_FLAG_FULL_DUPLEX;
-	}
-
-	if (netif_running(dev))
-		b44_setup_phy(bp);
-
-	spin_unlock_irq(&bp->lock);
-
-	return 0;
-}
-
-static void b44_get_ringparam(struct net_device *dev,
-			      struct ethtool_ringparam *ering)
-{
-	struct b44 *bp = netdev_priv(dev);
-
-	ering->rx_max_pending = B44_RX_RING_SIZE - 1;
-	ering->rx_pending = bp->rx_pending;
-
-	/* XXX ethtool lacks a tx_max_pending, oops... */
-}
-
-static int b44_set_ringparam(struct net_device *dev,
-			     struct ethtool_ringparam *ering)
-{
-	struct b44 *bp = netdev_priv(dev);
-
-	if ((ering->rx_pending > B44_RX_RING_SIZE - 1) ||
-	    (ering->rx_mini_pending != 0) ||
-	    (ering->rx_jumbo_pending != 0) ||
-	    (ering->tx_pending > B44_TX_RING_SIZE - 1))
-		return -EINVAL;
-
-	spin_lock_irq(&bp->lock);
-
-	bp->rx_pending = ering->rx_pending;
-	bp->tx_pending = ering->tx_pending;
-
-	b44_halt(bp);
-	b44_init_rings(bp);
-	b44_init_hw(bp, B44_FULL_RESET);
-	netif_wake_queue(bp->dev);
-	spin_unlock_irq(&bp->lock);
-
-	b44_enable_ints(bp);
-
-	return 0;
-}
-
-static void b44_get_pauseparam(struct net_device *dev,
-				struct ethtool_pauseparam *epause)
-{
-	struct b44 *bp = netdev_priv(dev);
-
-	epause->autoneg =
-		(bp->flags & B44_FLAG_PAUSE_AUTO) != 0;
-	epause->rx_pause =
-		(bp->flags & B44_FLAG_RX_PAUSE) != 0;
-	epause->tx_pause =
-		(bp->flags & B44_FLAG_TX_PAUSE) != 0;
-}
-
-static int b44_set_pauseparam(struct net_device *dev,
-				struct ethtool_pauseparam *epause)
-{
-	struct b44 *bp = netdev_priv(dev);
-
-	spin_lock_irq(&bp->lock);
-	if (epause->autoneg)
-		bp->flags |= B44_FLAG_PAUSE_AUTO;
-	else
-		bp->flags &= ~B44_FLAG_PAUSE_AUTO;
-	if (epause->rx_pause)
-		bp->flags |= B44_FLAG_RX_PAUSE;
-	else
-		bp->flags &= ~B44_FLAG_RX_PAUSE;
-	if (epause->tx_pause)
-		bp->flags |= B44_FLAG_TX_PAUSE;
-	else
-		bp->flags &= ~B44_FLAG_TX_PAUSE;
-	if (bp->flags & B44_FLAG_PAUSE_AUTO) {
-		b44_halt(bp);
-		b44_init_rings(bp);
-		b44_init_hw(bp, B44_FULL_RESET);
-	} else {
-		__b44_set_flow_ctrl(bp, bp->flags);
-	}
-	spin_unlock_irq(&bp->lock);
-
-	b44_enable_ints(bp);
-
-	return 0;
-}
-
-static void b44_get_strings(struct net_device *dev, u32 stringset, u8 *data)
-{
-	switch(stringset) {
-	case ETH_SS_STATS:
-		memcpy(data, *b44_gstrings, sizeof(b44_gstrings));
-		break;
-	}
-}
-
-static int b44_get_sset_count(struct net_device *dev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		return ARRAY_SIZE(b44_gstrings);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void b44_get_ethtool_stats(struct net_device *dev,
-				  struct ethtool_stats *stats, u64 *data)
-{
-	struct b44 *bp = netdev_priv(dev);
-	u32 *val = &bp->hw_stats.tx_good_octets;
-	u32 i;
-
-	spin_lock_irq(&bp->lock);
-
-	b44_stats_update(bp);
-
-	for (i = 0; i < ARRAY_SIZE(b44_gstrings); i++)
-		*data++ = *val++;
-
-	spin_unlock_irq(&bp->lock);
-}
-
-static void b44_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-	struct b44 *bp = netdev_priv(dev);
-
-	wol->supported = WAKE_MAGIC;
-	if (bp->flags & B44_FLAG_WOL_ENABLE)
-		wol->wolopts = WAKE_MAGIC;
-	else
-		wol->wolopts = 0;
-	memset(&wol->sopass, 0, sizeof(wol->sopass));
-}
-
-static int b44_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-	struct b44 *bp = netdev_priv(dev);
-
-	spin_lock_irq(&bp->lock);
-	if (wol->wolopts & WAKE_MAGIC)
-		bp->flags |= B44_FLAG_WOL_ENABLE;
-	else
-		bp->flags &= ~B44_FLAG_WOL_ENABLE;
-	spin_unlock_irq(&bp->lock);
-
-	return 0;
-}
-
-static const struct ethtool_ops b44_ethtool_ops = {
-	.get_drvinfo		= b44_get_drvinfo,
-	.get_settings		= b44_get_settings,
-	.set_settings		= b44_set_settings,
-	.nway_reset		= b44_nway_reset,
-	.get_link		= ethtool_op_get_link,
-	.get_wol		= b44_get_wol,
-	.set_wol		= b44_set_wol,
-	.get_ringparam		= b44_get_ringparam,
-	.set_ringparam		= b44_set_ringparam,
-	.get_pauseparam		= b44_get_pauseparam,
-	.set_pauseparam		= b44_set_pauseparam,
-	.get_msglevel		= b44_get_msglevel,
-	.set_msglevel		= b44_set_msglevel,
-	.get_strings		= b44_get_strings,
-	.get_sset_count		= b44_get_sset_count,
-	.get_ethtool_stats	= b44_get_ethtool_stats,
-};
-
-static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	struct mii_ioctl_data *data = if_mii(ifr);
-	struct b44 *bp = netdev_priv(dev);
-	int err = -EINVAL;
-
-	if (!netif_running(dev))
-		goto out;
-
-	spin_lock_irq(&bp->lock);
-	err = generic_mii_ioctl(&bp->mii_if, data, cmd, NULL);
-	spin_unlock_irq(&bp->lock);
-out:
-	return err;
-}
-
-static int __devinit b44_get_invariants(struct b44 *bp)
-{
-	struct ssb_device *sdev = bp->sdev;
-	int err = 0;
-	u8 *addr;
-
-	bp->dma_offset = ssb_dma_translation(sdev);
-
-	if (sdev->bus->bustype == SSB_BUSTYPE_SSB &&
-	    instance > 1) {
-		addr = sdev->bus->sprom.et1mac;
-		bp->phy_addr = sdev->bus->sprom.et1phyaddr;
-	} else {
-		addr = sdev->bus->sprom.et0mac;
-		bp->phy_addr = sdev->bus->sprom.et0phyaddr;
-	}
-	/* Some ROMs have buggy PHY addresses with the high
-	 * bits set (sign extension?). Truncate them to a
-	 * valid PHY address. */
-	bp->phy_addr &= 0x1F;
-
-	memcpy(bp->dev->dev_addr, addr, 6);
-
-	if (!is_valid_ether_addr(&bp->dev->dev_addr[0])){
-		pr_err("Invalid MAC address found in EEPROM\n");
-		return -EINVAL;
-	}
-
-	memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len);
-
-	bp->imask = IMASK_DEF;
-
-	/* XXX - really required?
-	   bp->flags |= B44_FLAG_BUGGY_TXPTR;
-	*/
-
-	if (bp->sdev->id.revision >= 7)
-		bp->flags |= B44_FLAG_B0_ANDLATER;
-
-	return err;
-}
-
-static const struct net_device_ops b44_netdev_ops = {
-	.ndo_open		= b44_open,
-	.ndo_stop		= b44_close,
-	.ndo_start_xmit		= b44_start_xmit,
-	.ndo_get_stats		= b44_get_stats,
-	.ndo_set_multicast_list = b44_set_rx_mode,
-	.ndo_set_mac_address	= b44_set_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_do_ioctl		= b44_ioctl,
-	.ndo_tx_timeout		= b44_tx_timeout,
-	.ndo_change_mtu		= b44_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= b44_poll_controller,
-#endif
-};
-
-static int __devinit b44_init_one(struct ssb_device *sdev,
-				  const struct ssb_device_id *ent)
-{
-	struct net_device *dev;
-	struct b44 *bp;
-	int err;
-
-	instance++;
-
-	pr_info_once("%s version %s\n", DRV_DESCRIPTION, DRV_MODULE_VERSION);
-
-	dev = alloc_etherdev(sizeof(*bp));
-	if (!dev) {
-		dev_err(sdev->dev, "Etherdev alloc failed, aborting\n");
-		err = -ENOMEM;
-		goto out;
-	}
-
-	SET_NETDEV_DEV(dev, sdev->dev);
-
-	/* No interesting netdevice features in this card... */
-	dev->features |= 0;
-
-	bp = netdev_priv(dev);
-	bp->sdev = sdev;
-	bp->dev = dev;
-	bp->force_copybreak = 0;
-
-	bp->msg_enable = netif_msg_init(b44_debug, B44_DEF_MSG_ENABLE);
-
-	spin_lock_init(&bp->lock);
-
-	bp->rx_pending = B44_DEF_RX_RING_PENDING;
-	bp->tx_pending = B44_DEF_TX_RING_PENDING;
-
-	dev->netdev_ops = &b44_netdev_ops;
-	netif_napi_add(dev, &bp->napi, b44_poll, 64);
-	dev->watchdog_timeo = B44_TX_TIMEOUT;
-	dev->irq = sdev->irq;
-	SET_ETHTOOL_OPS(dev, &b44_ethtool_ops);
-
-	err = ssb_bus_powerup(sdev->bus, 0);
-	if (err) {
-		dev_err(sdev->dev,
-			"Failed to powerup the bus\n");
-		goto err_out_free_dev;
-	}
-
-	if (dma_set_mask(sdev->dma_dev, DMA_BIT_MASK(30)) ||
-	    dma_set_coherent_mask(sdev->dma_dev, DMA_BIT_MASK(30))) {
-		dev_err(sdev->dev,
-			"Required 30BIT DMA mask unsupported by the system\n");
-		goto err_out_powerdown;
-	}
-
-	err = b44_get_invariants(bp);
-	if (err) {
-		dev_err(sdev->dev,
-			"Problem fetching invariants of chip, aborting\n");
-		goto err_out_powerdown;
-	}
-
-	bp->mii_if.dev = dev;
-	bp->mii_if.mdio_read = b44_mii_read;
-	bp->mii_if.mdio_write = b44_mii_write;
-	bp->mii_if.phy_id = bp->phy_addr;
-	bp->mii_if.phy_id_mask = 0x1f;
-	bp->mii_if.reg_num_mask = 0x1f;
-
-	/* By default, advertise all speed/duplex settings. */
-	bp->flags |= (B44_FLAG_ADV_10HALF | B44_FLAG_ADV_10FULL |
-		      B44_FLAG_ADV_100HALF | B44_FLAG_ADV_100FULL);
-
-	/* By default, auto-negotiate PAUSE. */
-	bp->flags |= B44_FLAG_PAUSE_AUTO;
-
-	err = register_netdev(dev);
-	if (err) {
-		dev_err(sdev->dev, "Cannot register net device, aborting\n");
-		goto err_out_powerdown;
-	}
-
-	netif_carrier_off(dev);
-
-	ssb_set_drvdata(sdev, dev);
-
-	/* Chip reset provides power to the b44 MAC & PCI cores, which
-	 * is necessary for MAC register access.
-	 */
-	b44_chip_reset(bp, B44_CHIP_RESET_FULL);
-
-	/* do a phy reset to test if there is an active phy */
-	if (b44_phy_reset(bp) < 0)
-		bp->phy_addr = B44_PHY_ADDR_NO_PHY;
-
-	netdev_info(dev, "%s %pM\n", DRV_DESCRIPTION, dev->dev_addr);
-
-	return 0;
-
-err_out_powerdown:
-	ssb_bus_may_powerdown(sdev->bus);
-
-err_out_free_dev:
-	free_netdev(dev);
-
-out:
-	return err;
-}
-
-static void __devexit b44_remove_one(struct ssb_device *sdev)
-{
-	struct net_device *dev = ssb_get_drvdata(sdev);
-
-	unregister_netdev(dev);
-	ssb_device_disable(sdev, 0);
-	ssb_bus_may_powerdown(sdev->bus);
-	free_netdev(dev);
-	ssb_pcihost_set_power_state(sdev, PCI_D3hot);
-	ssb_set_drvdata(sdev, NULL);
-}
-
-static int b44_suspend(struct ssb_device *sdev, pm_message_t state)
-{
-	struct net_device *dev = ssb_get_drvdata(sdev);
-	struct b44 *bp = netdev_priv(dev);
-
-	if (!netif_running(dev))
-		return 0;
-
-	del_timer_sync(&bp->timer);
-
-	spin_lock_irq(&bp->lock);
-
-	b44_halt(bp);
-	netif_carrier_off(bp->dev);
-	netif_device_detach(bp->dev);
-	b44_free_rings(bp);
-
-	spin_unlock_irq(&bp->lock);
-
-	free_irq(dev->irq, dev);
-	if (bp->flags & B44_FLAG_WOL_ENABLE) {
-		b44_init_hw(bp, B44_PARTIAL_RESET);
-		b44_setup_wol(bp);
-	}
-
-	ssb_pcihost_set_power_state(sdev, PCI_D3hot);
-	return 0;
-}
-
-static int b44_resume(struct ssb_device *sdev)
-{
-	struct net_device *dev = ssb_get_drvdata(sdev);
-	struct b44 *bp = netdev_priv(dev);
-	int rc = 0;
-
-	rc = ssb_bus_powerup(sdev->bus, 0);
-	if (rc) {
-		dev_err(sdev->dev,
-			"Failed to powerup the bus\n");
-		return rc;
-	}
-
-	if (!netif_running(dev))
-		return 0;
-
-	spin_lock_irq(&bp->lock);
-	b44_init_rings(bp);
-	b44_init_hw(bp, B44_FULL_RESET);
-	spin_unlock_irq(&bp->lock);
-
-	/*
-	 * As a shared interrupt, the handler can be called immediately. To be
-	 * able to check the interrupt status the hardware must already be
-	 * powered back on (b44_init_hw).
-	 */
-	rc = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev);
-	if (rc) {
-		netdev_err(dev, "request_irq failed\n");
-		spin_lock_irq(&bp->lock);
-		b44_halt(bp);
-		b44_free_rings(bp);
-		spin_unlock_irq(&bp->lock);
-		return rc;
-	}
-
-	netif_device_attach(bp->dev);
-
-	b44_enable_ints(bp);
-	netif_wake_queue(dev);
-
-	mod_timer(&bp->timer, jiffies + 1);
-
-	return 0;
-}
-
-static struct ssb_driver b44_ssb_driver = {
-	.name		= DRV_MODULE_NAME,
-	.id_table	= b44_ssb_tbl,
-	.probe		= b44_init_one,
-	.remove		= __devexit_p(b44_remove_one),
-	.suspend	= b44_suspend,
-	.resume		= b44_resume,
-};
-
-static inline int __init b44_pci_init(void)
-{
-	int err = 0;
-#ifdef CONFIG_B44_PCI
-	err = ssb_pcihost_register(&b44_pci_driver);
-#endif
-	return err;
-}
-
-static inline void __exit b44_pci_exit(void)
-{
-#ifdef CONFIG_B44_PCI
-	ssb_pcihost_unregister(&b44_pci_driver);
-#endif
-}
-
-static int __init b44_init(void)
-{
-	unsigned int dma_desc_align_size = dma_get_cache_alignment();
-	int err;
-
-	/* Setup paramaters for syncing RX/TX DMA descriptors */
-	dma_desc_sync_size = max_t(unsigned int, dma_desc_align_size, sizeof(struct dma_desc));
-
-	err = b44_pci_init();
-	if (err)
-		return err;
-	err = ssb_driver_register(&b44_ssb_driver);
-	if (err)
-		b44_pci_exit();
-	return err;
-}
-
-static void __exit b44_cleanup(void)
-{
-	ssb_driver_unregister(&b44_ssb_driver);
-	b44_pci_exit();
-}
-
-module_init(b44_init);
-module_exit(b44_cleanup);
-
diff -druN linux-libre-3.1-gnu/drivers/net/b44.h linux-libre-3.2-gnu/drivers/net/b44.h
--- linux-libre-3.1-gnu/drivers/net/b44.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/b44.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,401 +0,0 @@
-#ifndef _B44_H
-#define _B44_H
-
-/* Register layout. (These correspond to struct _bcmenettregs in bcm4400.) */
-#define	B44_DEVCTRL	0x0000UL /* Device Control */
-#define  DEVCTRL_MPM		0x00000040 /* Magic Packet PME Enable (B0 only) */
-#define  DEVCTRL_PFE		0x00000080 /* Pattern Filtering Enable */
-#define  DEVCTRL_IPP		0x00000400 /* Internal EPHY Present */
-#define  DEVCTRL_EPR		0x00008000 /* EPHY Reset */
-#define  DEVCTRL_PME		0x00001000 /* PHY Mode Enable */
-#define  DEVCTRL_PMCE		0x00002000 /* PHY Mode Clocks Enable */
-#define  DEVCTRL_PADDR		0x0007c000 /* PHY Address */
-#define  DEVCTRL_PADDR_SHIFT	18
-#define B44_BIST_STAT	0x000CUL /* Built-In Self-Test Status */
-#define B44_WKUP_LEN	0x0010UL /* Wakeup Length */
-#define  WKUP_LEN_P0_MASK	0x0000007f /* Pattern 0 */
-#define  WKUP_LEN_D0		0x00000080
-#define  WKUP_LEN_P1_MASK	0x00007f00 /* Pattern 1 */
-#define  WKUP_LEN_P1_SHIFT	8
-#define  WKUP_LEN_D1		0x00008000
-#define  WKUP_LEN_P2_MASK	0x007f0000 /* Pattern 2 */
-#define  WKUP_LEN_P2_SHIFT	16
-#define  WKUP_LEN_D2		0x00000000
-#define  WKUP_LEN_P3_MASK	0x7f000000 /* Pattern 3 */
-#define  WKUP_LEN_P3_SHIFT	24
-#define  WKUP_LEN_D3		0x80000000
-#define  WKUP_LEN_DISABLE	0x80808080
-#define  WKUP_LEN_ENABLE_TWO	0x80800000
-#define  WKUP_LEN_ENABLE_THREE	0x80000000
-#define B44_ISTAT	0x0020UL /* Interrupt Status */
-#define  ISTAT_LS		0x00000020 /* Link Change (B0 only) */
-#define  ISTAT_PME		0x00000040 /* Power Management Event */
-#define  ISTAT_TO		0x00000080 /* General Purpose Timeout */
-#define  ISTAT_DSCE		0x00000400 /* Descriptor Error */
-#define  ISTAT_DATAE		0x00000800 /* Data Error */
-#define  ISTAT_DPE		0x00001000 /* Descr. Protocol Error */
-#define  ISTAT_RDU		0x00002000 /* Receive Descr. Underflow */
-#define  ISTAT_RFO		0x00004000 /* Receive FIFO Overflow */
-#define  ISTAT_TFU		0x00008000 /* Transmit FIFO Underflow */
-#define  ISTAT_RX		0x00010000 /* RX Interrupt */
-#define  ISTAT_TX		0x01000000 /* TX Interrupt */
-#define  ISTAT_EMAC		0x04000000 /* EMAC Interrupt */
-#define  ISTAT_MII_WRITE	0x08000000 /* MII Write Interrupt */
-#define  ISTAT_MII_READ		0x10000000 /* MII Read Interrupt */
-#define  ISTAT_ERRORS (ISTAT_DSCE|ISTAT_DATAE|ISTAT_DPE|ISTAT_RDU|ISTAT_RFO|ISTAT_TFU)
-#define B44_IMASK	0x0024UL /* Interrupt Mask */
-#define  IMASK_DEF		(ISTAT_ERRORS | ISTAT_TO | ISTAT_RX | ISTAT_TX)
-#define B44_GPTIMER	0x0028UL /* General Purpose Timer */
-#define B44_ADDR_LO	0x0088UL /* ENET Address Lo (B0 only) */
-#define B44_ADDR_HI	0x008CUL /* ENET Address Hi (B0 only) */
-#define B44_FILT_ADDR	0x0090UL /* ENET Filter Address */
-#define B44_FILT_DATA	0x0094UL /* ENET Filter Data */
-#define B44_TXBURST	0x00A0UL /* TX Max Burst Length */
-#define B44_RXBURST	0x00A4UL /* RX Max Burst Length */
-#define B44_MAC_CTRL	0x00A8UL /* MAC Control */
-#define  MAC_CTRL_CRC32_ENAB	0x00000001 /* CRC32 Generation Enable */
-#define  MAC_CTRL_PHY_PDOWN	0x00000004 /* Onchip EPHY Powerdown */
-#define  MAC_CTRL_PHY_EDET	0x00000008 /* Onchip EPHY Energy Detected */
-#define  MAC_CTRL_PHY_LEDCTRL	0x000000e0 /* Onchip EPHY LED Control */
-#define  MAC_CTRL_PHY_LEDCTRL_SHIFT 5
-#define B44_MAC_FLOW	0x00ACUL /* MAC Flow Control */
-#define  MAC_FLOW_RX_HI_WATER	0x000000ff /* Receive FIFO HI Water Mark */
-#define  MAC_FLOW_PAUSE_ENAB	0x00008000 /* Enable Pause Frame Generation */
-#define B44_RCV_LAZY	0x0100UL /* Lazy Interrupt Control */
-#define  RCV_LAZY_TO_MASK	0x00ffffff /* Timeout */
-#define  RCV_LAZY_FC_MASK	0xff000000 /* Frame Count */
-#define  RCV_LAZY_FC_SHIFT	24
-#define B44_DMATX_CTRL	0x0200UL /* DMA TX Control */
-#define  DMATX_CTRL_ENABLE	0x00000001 /* Enable */
-#define  DMATX_CTRL_SUSPEND	0x00000002 /* Suepend Request */
-#define  DMATX_CTRL_LPBACK	0x00000004 /* Loopback Enable */
-#define  DMATX_CTRL_FAIRPRIOR	0x00000008 /* Fair Priority */
-#define  DMATX_CTRL_FLUSH	0x00000010 /* Flush Request */
-#define B44_DMATX_ADDR	0x0204UL /* DMA TX Descriptor Ring Address */
-#define B44_DMATX_PTR	0x0208UL /* DMA TX Last Posted Descriptor */
-#define B44_DMATX_STAT	0x020CUL /* DMA TX Current Active Desc. + Status */
-#define  DMATX_STAT_CDMASK	0x00000fff /* Current Descriptor Mask */
-#define  DMATX_STAT_SMASK	0x0000f000 /* State Mask */
-#define  DMATX_STAT_SDISABLED	0x00000000 /* State Disabled */
-#define  DMATX_STAT_SACTIVE	0x00001000 /* State Active */
-#define  DMATX_STAT_SIDLE	0x00002000 /* State Idle Wait */
-#define  DMATX_STAT_SSTOPPED	0x00003000 /* State Stopped */
-#define  DMATX_STAT_SSUSP	0x00004000 /* State Suspend Pending */
-#define  DMATX_STAT_EMASK	0x000f0000 /* Error Mask */
-#define  DMATX_STAT_ENONE	0x00000000 /* Error None */
-#define  DMATX_STAT_EDPE	0x00010000 /* Error Desc. Protocol Error */
-#define  DMATX_STAT_EDFU	0x00020000 /* Error Data FIFO Underrun */
-#define  DMATX_STAT_EBEBR	0x00030000 /* Error Bus Error on Buffer Read */
-#define  DMATX_STAT_EBEDA	0x00040000 /* Error Bus Error on Desc. Access */
-#define  DMATX_STAT_FLUSHED	0x00100000 /* Flushed */
-#define B44_DMARX_CTRL	0x0210UL /* DMA RX Control */
-#define  DMARX_CTRL_ENABLE	0x00000001 /* Enable */
-#define  DMARX_CTRL_ROMASK	0x000000fe /* Receive Offset Mask */
-#define  DMARX_CTRL_ROSHIFT	1 	   /* Receive Offset Shift */
-#define B44_DMARX_ADDR	0x0214UL /* DMA RX Descriptor Ring Address */
-#define B44_DMARX_PTR	0x0218UL /* DMA RX Last Posted Descriptor */
-#define B44_DMARX_STAT	0x021CUL /* DMA RX Current Active Desc. + Status */
-#define  DMARX_STAT_CDMASK	0x00000fff /* Current Descriptor Mask */
-#define  DMARX_STAT_SMASK	0x0000f000 /* State Mask */
-#define  DMARX_STAT_SDISABLED	0x00000000 /* State Disabled */
-#define  DMARX_STAT_SACTIVE	0x00001000 /* State Active */
-#define  DMARX_STAT_SIDLE	0x00002000 /* State Idle Wait */
-#define  DMARX_STAT_SSTOPPED	0x00003000 /* State Stopped */
-#define  DMARX_STAT_EMASK	0x000f0000 /* Error Mask */
-#define  DMARX_STAT_ENONE	0x00000000 /* Error None */
-#define  DMARX_STAT_EDPE	0x00010000 /* Error Desc. Protocol Error */
-#define  DMARX_STAT_EDFO	0x00020000 /* Error Data FIFO Overflow */
-#define  DMARX_STAT_EBEBW	0x00030000 /* Error Bus Error on Buffer Write */
-#define  DMARX_STAT_EBEDA	0x00040000 /* Error Bus Error on Desc. Access */
-#define B44_DMAFIFO_AD	0x0220UL /* DMA FIFO Diag Address */
-#define  DMAFIFO_AD_OMASK	0x0000ffff /* Offset Mask */
-#define  DMAFIFO_AD_SMASK	0x000f0000 /* Select Mask */
-#define  DMAFIFO_AD_SXDD	0x00000000 /* Select Transmit DMA Data */
-#define  DMAFIFO_AD_SXDP	0x00010000 /* Select Transmit DMA Pointers */
-#define  DMAFIFO_AD_SRDD	0x00040000 /* Select Receive DMA Data */
-#define  DMAFIFO_AD_SRDP	0x00050000 /* Select Receive DMA Pointers */
-#define  DMAFIFO_AD_SXFD	0x00080000 /* Select Transmit FIFO Data */
-#define  DMAFIFO_AD_SXFP	0x00090000 /* Select Transmit FIFO Pointers */
-#define  DMAFIFO_AD_SRFD	0x000c0000 /* Select Receive FIFO Data */
-#define  DMAFIFO_AD_SRFP	0x000c0000 /* Select Receive FIFO Pointers */
-#define B44_DMAFIFO_LO	0x0224UL /* DMA FIFO Diag Low Data */
-#define B44_DMAFIFO_HI	0x0228UL /* DMA FIFO Diag High Data */
-#define B44_RXCONFIG	0x0400UL /* EMAC RX Config */
-#define  RXCONFIG_DBCAST	0x00000001 /* Disable Broadcast */
-#define  RXCONFIG_ALLMULTI	0x00000002 /* Accept All Multicast */
-#define  RXCONFIG_NORX_WHILE_TX	0x00000004 /* Receive Disable While Transmitting */
-#define  RXCONFIG_PROMISC	0x00000008 /* Promiscuous Enable */
-#define  RXCONFIG_LPBACK	0x00000010 /* Loopback Enable */
-#define  RXCONFIG_FLOW		0x00000020 /* Flow Control Enable */
-#define  RXCONFIG_FLOW_ACCEPT	0x00000040 /* Accept Unicast Flow Control Frame */
-#define  RXCONFIG_RFILT		0x00000080 /* Reject Filter */
-#define  RXCONFIG_CAM_ABSENT	0x00000100 /* CAM Absent */
-#define B44_RXMAXLEN	0x0404UL /* EMAC RX Max Packet Length */
-#define B44_TXMAXLEN	0x0408UL /* EMAC TX Max Packet Length */
-#define B44_MDIO_CTRL	0x0410UL /* EMAC MDIO Control */
-#define  MDIO_CTRL_MAXF_MASK	0x0000007f /* MDC Frequency */
-#define  MDIO_CTRL_PREAMBLE	0x00000080 /* MII Preamble Enable */
-#define B44_MDIO_DATA	0x0414UL /* EMAC MDIO Data */
-#define  MDIO_DATA_DATA		0x0000ffff /* R/W Data */
-#define  MDIO_DATA_TA_MASK	0x00030000 /* Turnaround Value */
-#define  MDIO_DATA_TA_SHIFT	16
-#define  MDIO_TA_VALID		2
-#define  MDIO_DATA_RA_MASK	0x007c0000 /* Register Address */
-#define  MDIO_DATA_RA_SHIFT	18
-#define  MDIO_DATA_PMD_MASK	0x0f800000 /* Physical Media Device */
-#define  MDIO_DATA_PMD_SHIFT	23
-#define  MDIO_DATA_OP_MASK	0x30000000 /* Opcode */
-#define  MDIO_DATA_OP_SHIFT	28
-#define  MDIO_OP_WRITE		1
-#define  MDIO_OP_READ		2
-#define  MDIO_DATA_SB_MASK	0xc0000000 /* Start Bits */
-#define  MDIO_DATA_SB_SHIFT	30
-#define  MDIO_DATA_SB_START	0x40000000 /* Start Of Frame */
-#define B44_EMAC_IMASK	0x0418UL /* EMAC Interrupt Mask */
-#define B44_EMAC_ISTAT	0x041CUL /* EMAC Interrupt Status */
-#define  EMAC_INT_MII		0x00000001 /* MII MDIO Interrupt */
-#define  EMAC_INT_MIB		0x00000002 /* MIB Interrupt */
-#define  EMAC_INT_FLOW		0x00000003 /* Flow Control Interrupt */
-#define B44_CAM_DATA_LO	0x0420UL /* EMAC CAM Data Low */
-#define B44_CAM_DATA_HI	0x0424UL /* EMAC CAM Data High */
-#define  CAM_DATA_HI_VALID	0x00010000 /* Valid Bit */
-#define B44_CAM_CTRL	0x0428UL /* EMAC CAM Control */
-#define  CAM_CTRL_ENABLE	0x00000001 /* CAM Enable */
-#define  CAM_CTRL_MSEL		0x00000002 /* Mask Select */
-#define  CAM_CTRL_READ		0x00000004 /* Read */
-#define  CAM_CTRL_WRITE		0x00000008 /* Read */
-#define  CAM_CTRL_INDEX_MASK	0x003f0000 /* Index Mask */
-#define  CAM_CTRL_INDEX_SHIFT	16
-#define  CAM_CTRL_BUSY		0x80000000 /* CAM Busy */
-#define B44_ENET_CTRL	0x042CUL /* EMAC ENET Control */
-#define  ENET_CTRL_ENABLE	0x00000001 /* EMAC Enable */
-#define  ENET_CTRL_DISABLE	0x00000002 /* EMAC Disable */
-#define  ENET_CTRL_SRST		0x00000004 /* EMAC Soft Reset */
-#define  ENET_CTRL_EPSEL	0x00000008 /* External PHY Select */
-#define B44_TX_CTRL	0x0430UL /* EMAC TX Control */
-#define  TX_CTRL_DUPLEX		0x00000001 /* Full Duplex */
-#define  TX_CTRL_FMODE		0x00000002 /* Flow Mode */
-#define  TX_CTRL_SBENAB		0x00000004 /* Single Backoff Enable */
-#define  TX_CTRL_SMALL_SLOT	0x00000008 /* Small Slottime */
-#define B44_TX_WMARK	0x0434UL /* EMAC TX Watermark */
-#define B44_MIB_CTRL	0x0438UL /* EMAC MIB Control */
-#define  MIB_CTRL_CLR_ON_READ	0x00000001 /* Autoclear on Read */
-#define B44_TX_GOOD_O	0x0500UL /* MIB TX Good Octets */
-#define B44_TX_GOOD_P	0x0504UL /* MIB TX Good Packets */
-#define B44_TX_O	0x0508UL /* MIB TX Octets */
-#define B44_TX_P	0x050CUL /* MIB TX Packets */
-#define B44_TX_BCAST	0x0510UL /* MIB TX Broadcast Packets */
-#define B44_TX_MCAST	0x0514UL /* MIB TX Multicast Packets */
-#define B44_TX_64	0x0518UL /* MIB TX <= 64 byte Packets */
-#define B44_TX_65_127	0x051CUL /* MIB TX 65 to 127 byte Packets */
-#define B44_TX_128_255	0x0520UL /* MIB TX 128 to 255 byte Packets */
-#define B44_TX_256_511	0x0524UL /* MIB TX 256 to 511 byte Packets */
-#define B44_TX_512_1023	0x0528UL /* MIB TX 512 to 1023 byte Packets */
-#define B44_TX_1024_MAX	0x052CUL /* MIB TX 1024 to max byte Packets */
-#define B44_TX_JABBER	0x0530UL /* MIB TX Jabber Packets */
-#define B44_TX_OSIZE	0x0534UL /* MIB TX Oversize Packets */
-#define B44_TX_FRAG	0x0538UL /* MIB TX Fragment Packets */
-#define B44_TX_URUNS	0x053CUL /* MIB TX Underruns */
-#define B44_TX_TCOLS	0x0540UL /* MIB TX Total Collisions */
-#define B44_TX_SCOLS	0x0544UL /* MIB TX Single Collisions */
-#define B44_TX_MCOLS	0x0548UL /* MIB TX Multiple Collisions */
-#define B44_TX_ECOLS	0x054CUL /* MIB TX Excessive Collisions */
-#define B44_TX_LCOLS	0x0550UL /* MIB TX Late Collisions */
-#define B44_TX_DEFERED	0x0554UL /* MIB TX Defered Packets */
-#define B44_TX_CLOST	0x0558UL /* MIB TX Carrier Lost */
-#define B44_TX_PAUSE	0x055CUL /* MIB TX Pause Packets */
-#define B44_RX_GOOD_O	0x0580UL /* MIB RX Good Octets */
-#define B44_RX_GOOD_P	0x0584UL /* MIB RX Good Packets */
-#define B44_RX_O	0x0588UL /* MIB RX Octets */
-#define B44_RX_P	0x058CUL /* MIB RX Packets */
-#define B44_RX_BCAST	0x0590UL /* MIB RX Broadcast Packets */
-#define B44_RX_MCAST	0x0594UL /* MIB RX Multicast Packets */
-#define B44_RX_64	0x0598UL /* MIB RX <= 64 byte Packets */
-#define B44_RX_65_127	0x059CUL /* MIB RX 65 to 127 byte Packets */
-#define B44_RX_128_255	0x05A0UL /* MIB RX 128 to 255 byte Packets */
-#define B44_RX_256_511	0x05A4UL /* MIB RX 256 to 511 byte Packets */
-#define B44_RX_512_1023	0x05A8UL /* MIB RX 512 to 1023 byte Packets */
-#define B44_RX_1024_MAX	0x05ACUL /* MIB RX 1024 to max byte Packets */
-#define B44_RX_JABBER	0x05B0UL /* MIB RX Jabber Packets */
-#define B44_RX_OSIZE	0x05B4UL /* MIB RX Oversize Packets */
-#define B44_RX_FRAG	0x05B8UL /* MIB RX Fragment Packets */
-#define B44_RX_MISS	0x05BCUL /* MIB RX Missed Packets */
-#define B44_RX_CRCA	0x05C0UL /* MIB RX CRC Align Errors */
-#define B44_RX_USIZE	0x05C4UL /* MIB RX Undersize Packets */
-#define B44_RX_CRC	0x05C8UL /* MIB RX CRC Errors */
-#define B44_RX_ALIGN	0x05CCUL /* MIB RX Align Errors */
-#define B44_RX_SYM	0x05D0UL /* MIB RX Symbol Errors */
-#define B44_RX_PAUSE	0x05D4UL /* MIB RX Pause Packets */
-#define B44_RX_NPAUSE	0x05D8UL /* MIB RX Non-Pause Packets */
-
-/* 4400 PHY registers */
-#define B44_MII_AUXCTRL		24	/* Auxiliary Control */
-#define  MII_AUXCTRL_DUPLEX	0x0001  /* Full Duplex */
-#define  MII_AUXCTRL_SPEED	0x0002  /* 1=100Mbps, 0=10Mbps */
-#define  MII_AUXCTRL_FORCED	0x0004	/* Forced 10/100 */
-#define B44_MII_ALEDCTRL	26	/* Activity LED */
-#define  MII_ALEDCTRL_ALLMSK	0x7fff
-#define B44_MII_TLEDCTRL	27	/* Traffic Meter LED */
-#define  MII_TLEDCTRL_ENABLE	0x0040
-
-struct dma_desc {
-	__le32	ctrl;
-	__le32	addr;
-};
-
-/* There are only 12 bits in the DMA engine for descriptor offsetting
- * so the table must be aligned on a boundary of this.
- */
-#define DMA_TABLE_BYTES		4096
-
-#define DESC_CTRL_LEN	0x00001fff
-#define DESC_CTRL_CMASK	0x0ff00000 /* Core specific bits */
-#define DESC_CTRL_EOT	0x10000000 /* End of Table */
-#define DESC_CTRL_IOC	0x20000000 /* Interrupt On Completion */
-#define DESC_CTRL_EOF	0x40000000 /* End of Frame */
-#define DESC_CTRL_SOF	0x80000000 /* Start of Frame */
-
-#define RX_COPY_THRESHOLD  	256
-
-struct rx_header {
-	__le16	len;
-	__le16	flags;
-	__le16	pad[12];
-};
-#define RX_HEADER_LEN	28
-
-#define RX_FLAG_OFIFO	0x00000001 /* FIFO Overflow */
-#define RX_FLAG_CRCERR	0x00000002 /* CRC Error */
-#define RX_FLAG_SERR	0x00000004 /* Receive Symbol Error */
-#define RX_FLAG_ODD	0x00000008 /* Frame has odd number of nibbles */
-#define RX_FLAG_LARGE	0x00000010 /* Frame is > RX MAX Length */
-#define RX_FLAG_MCAST	0x00000020 /* Dest is Multicast Address */
-#define RX_FLAG_BCAST	0x00000040 /* Dest is Broadcast Address */
-#define RX_FLAG_MISS	0x00000080 /* Received due to promisc mode */
-#define RX_FLAG_LAST	0x00000800 /* Last buffer in frame */
-#define RX_FLAG_ERRORS	(RX_FLAG_ODD | RX_FLAG_SERR | RX_FLAG_CRCERR | RX_FLAG_OFIFO)
-
-struct ring_info {
-	struct sk_buff		*skb;
-	dma_addr_t	mapping;
-};
-
-#define B44_MCAST_TABLE_SIZE	32
-#define B44_PHY_ADDR_NO_PHY	30
-#define B44_MDC_RATIO		5000000
-
-#define	B44_STAT_REG_DECLARE		\
-	_B44(tx_good_octets)		\
-	_B44(tx_good_pkts)		\
-	_B44(tx_octets)			\
-	_B44(tx_pkts)			\
-	_B44(tx_broadcast_pkts)		\
-	_B44(tx_multicast_pkts)		\
-	_B44(tx_len_64)			\
-	_B44(tx_len_65_to_127)		\
-	_B44(tx_len_128_to_255)		\
-	_B44(tx_len_256_to_511)		\
-	_B44(tx_len_512_to_1023)	\
-	_B44(tx_len_1024_to_max)	\
-	_B44(tx_jabber_pkts)		\
-	_B44(tx_oversize_pkts)		\
-	_B44(tx_fragment_pkts)		\
-	_B44(tx_underruns)		\
-	_B44(tx_total_cols)		\
-	_B44(tx_single_cols)		\
-	_B44(tx_multiple_cols)		\
-	_B44(tx_excessive_cols)		\
-	_B44(tx_late_cols)		\
-	_B44(tx_defered)		\
-	_B44(tx_carrier_lost)		\
-	_B44(tx_pause_pkts)		\
-	_B44(rx_good_octets)		\
-	_B44(rx_good_pkts)		\
-	_B44(rx_octets)			\
-	_B44(rx_pkts)			\
-	_B44(rx_broadcast_pkts)		\
-	_B44(rx_multicast_pkts)		\
-	_B44(rx_len_64)			\
-	_B44(rx_len_65_to_127)		\
-	_B44(rx_len_128_to_255)		\
-	_B44(rx_len_256_to_511)		\
-	_B44(rx_len_512_to_1023)	\
-	_B44(rx_len_1024_to_max)	\
-	_B44(rx_jabber_pkts)		\
-	_B44(rx_oversize_pkts)		\
-	_B44(rx_fragment_pkts)		\
-	_B44(rx_missed_pkts)		\
-	_B44(rx_crc_align_errs)		\
-	_B44(rx_undersize)		\
-	_B44(rx_crc_errs)		\
-	_B44(rx_align_errs)		\
-	_B44(rx_symbol_errs)		\
-	_B44(rx_pause_pkts)		\
-	_B44(rx_nonpause_pkts)
-
-/* SW copy of device statistics, kept up to date by periodic timer
- * which probes HW values. Check b44_stats_update if you mess with
- * the layout
- */
-struct b44_hw_stats {
-#define _B44(x)	u32 x;
-B44_STAT_REG_DECLARE
-#undef _B44
-};
-
-struct ssb_device;
-
-struct b44 {
-	spinlock_t		lock;
-
-	u32			imask, istat;
-
-	struct dma_desc		*rx_ring, *tx_ring;
-
-	u32			tx_prod, tx_cons;
-	u32			rx_prod, rx_cons;
-
-	struct ring_info	*rx_buffers;
-	struct ring_info	*tx_buffers;
-
-	struct napi_struct	napi;
-
-	u32			dma_offset;
-	u32			flags;
-#define B44_FLAG_B0_ANDLATER	0x00000001
-#define B44_FLAG_BUGGY_TXPTR	0x00000002
-#define B44_FLAG_REORDER_BUG	0x00000004
-#define B44_FLAG_PAUSE_AUTO	0x00008000
-#define B44_FLAG_FULL_DUPLEX	0x00010000
-#define B44_FLAG_100_BASE_T	0x00020000
-#define B44_FLAG_TX_PAUSE	0x00040000
-#define B44_FLAG_RX_PAUSE	0x00080000
-#define B44_FLAG_FORCE_LINK	0x00100000
-#define B44_FLAG_ADV_10HALF	0x01000000
-#define B44_FLAG_ADV_10FULL	0x02000000
-#define B44_FLAG_ADV_100HALF	0x04000000
-#define B44_FLAG_ADV_100FULL	0x08000000
-#define B44_FLAG_INTERNAL_PHY	0x10000000
-#define B44_FLAG_RX_RING_HACK	0x20000000
-#define B44_FLAG_TX_RING_HACK	0x40000000
-#define B44_FLAG_WOL_ENABLE	0x80000000
-
-	u32			msg_enable;
-
-	struct timer_list	timer;
-
-	struct b44_hw_stats	hw_stats;
-
-	struct ssb_device	*sdev;
-	struct net_device	*dev;
-
-	dma_addr_t		rx_ring_dma, tx_ring_dma;
-
-	u32			rx_pending;
-	u32			tx_pending;
-	u8			phy_addr;
-	u8			force_copybreak;
-	struct mii_if_info	mii_if;
-};
-
-#endif /* _B44_H */
diff -druN linux-libre-3.1-gnu/drivers/net/bcm63xx_enet.c linux-libre-3.2-gnu/drivers/net/bcm63xx_enet.c
--- linux-libre-3.1-gnu/drivers/net/bcm63xx_enet.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bcm63xx_enet.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1966 +0,0 @@
-/*
- * Driver for BCM963xx builtin Ethernet mac
- *
- * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/etherdevice.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/ethtool.h>
-#include <linux/crc32.h>
-#include <linux/err.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/if_vlan.h>
-
-#include <bcm63xx_dev_enet.h>
-#include "bcm63xx_enet.h"
-
-static char bcm_enet_driver_name[] = "bcm63xx_enet";
-static char bcm_enet_driver_version[] = "1.0";
-
-static int copybreak __read_mostly = 128;
-module_param(copybreak, int, 0);
-MODULE_PARM_DESC(copybreak, "Receive copy threshold");
-
-/* io memory shared between all devices */
-static void __iomem *bcm_enet_shared_base;
-
-/*
- * io helpers to access mac registers
- */
-static inline u32 enet_readl(struct bcm_enet_priv *priv, u32 off)
-{
-	return bcm_readl(priv->base + off);
-}
-
-static inline void enet_writel(struct bcm_enet_priv *priv,
-			       u32 val, u32 off)
-{
-	bcm_writel(val, priv->base + off);
-}
-
-/*
- * io helpers to access shared registers
- */
-static inline u32 enet_dma_readl(struct bcm_enet_priv *priv, u32 off)
-{
-	return bcm_readl(bcm_enet_shared_base + off);
-}
-
-static inline void enet_dma_writel(struct bcm_enet_priv *priv,
-				       u32 val, u32 off)
-{
-	bcm_writel(val, bcm_enet_shared_base + off);
-}
-
-/*
- * write given data into mii register and wait for transfer to end
- * with timeout (average measured transfer time is 25us)
- */
-static int do_mdio_op(struct bcm_enet_priv *priv, unsigned int data)
-{
-	int limit;
-
-	/* make sure mii interrupt status is cleared */
-	enet_writel(priv, ENET_IR_MII, ENET_IR_REG);
-
-	enet_writel(priv, data, ENET_MIIDATA_REG);
-	wmb();
-
-	/* busy wait on mii interrupt bit, with timeout */
-	limit = 1000;
-	do {
-		if (enet_readl(priv, ENET_IR_REG) & ENET_IR_MII)
-			break;
-		udelay(1);
-	} while (limit-- > 0);
-
-	return (limit < 0) ? 1 : 0;
-}
-
-/*
- * MII internal read callback
- */
-static int bcm_enet_mdio_read(struct bcm_enet_priv *priv, int mii_id,
-			      int regnum)
-{
-	u32 tmp, val;
-
-	tmp = regnum << ENET_MIIDATA_REG_SHIFT;
-	tmp |= 0x2 << ENET_MIIDATA_TA_SHIFT;
-	tmp |= mii_id << ENET_MIIDATA_PHYID_SHIFT;
-	tmp |= ENET_MIIDATA_OP_READ_MASK;
-
-	if (do_mdio_op(priv, tmp))
-		return -1;
-
-	val = enet_readl(priv, ENET_MIIDATA_REG);
-	val &= 0xffff;
-	return val;
-}
-
-/*
- * MII internal write callback
- */
-static int bcm_enet_mdio_write(struct bcm_enet_priv *priv, int mii_id,
-			       int regnum, u16 value)
-{
-	u32 tmp;
-
-	tmp = (value & 0xffff) << ENET_MIIDATA_DATA_SHIFT;
-	tmp |= 0x2 << ENET_MIIDATA_TA_SHIFT;
-	tmp |= regnum << ENET_MIIDATA_REG_SHIFT;
-	tmp |= mii_id << ENET_MIIDATA_PHYID_SHIFT;
-	tmp |= ENET_MIIDATA_OP_WRITE_MASK;
-
-	(void)do_mdio_op(priv, tmp);
-	return 0;
-}
-
-/*
- * MII read callback from phylib
- */
-static int bcm_enet_mdio_read_phylib(struct mii_bus *bus, int mii_id,
-				     int regnum)
-{
-	return bcm_enet_mdio_read(bus->priv, mii_id, regnum);
-}
-
-/*
- * MII write callback from phylib
- */
-static int bcm_enet_mdio_write_phylib(struct mii_bus *bus, int mii_id,
-				      int regnum, u16 value)
-{
-	return bcm_enet_mdio_write(bus->priv, mii_id, regnum, value);
-}
-
-/*
- * MII read callback from mii core
- */
-static int bcm_enet_mdio_read_mii(struct net_device *dev, int mii_id,
-				  int regnum)
-{
-	return bcm_enet_mdio_read(netdev_priv(dev), mii_id, regnum);
-}
-
-/*
- * MII write callback from mii core
- */
-static void bcm_enet_mdio_write_mii(struct net_device *dev, int mii_id,
-				    int regnum, int value)
-{
-	bcm_enet_mdio_write(netdev_priv(dev), mii_id, regnum, value);
-}
-
-/*
- * refill rx queue
- */
-static int bcm_enet_refill_rx(struct net_device *dev)
-{
-	struct bcm_enet_priv *priv;
-
-	priv = netdev_priv(dev);
-
-	while (priv->rx_desc_count < priv->rx_ring_size) {
-		struct bcm_enet_desc *desc;
-		struct sk_buff *skb;
-		dma_addr_t p;
-		int desc_idx;
-		u32 len_stat;
-
-		desc_idx = priv->rx_dirty_desc;
-		desc = &priv->rx_desc_cpu[desc_idx];
-
-		if (!priv->rx_skb[desc_idx]) {
-			skb = netdev_alloc_skb(dev, priv->rx_skb_size);
-			if (!skb)
-				break;
-			priv->rx_skb[desc_idx] = skb;
-
-			p = dma_map_single(&priv->pdev->dev, skb->data,
-					   priv->rx_skb_size,
-					   DMA_FROM_DEVICE);
-			desc->address = p;
-		}
-
-		len_stat = priv->rx_skb_size << DMADESC_LENGTH_SHIFT;
-		len_stat |= DMADESC_OWNER_MASK;
-		if (priv->rx_dirty_desc == priv->rx_ring_size - 1) {
-			len_stat |= DMADESC_WRAP_MASK;
-			priv->rx_dirty_desc = 0;
-		} else {
-			priv->rx_dirty_desc++;
-		}
-		wmb();
-		desc->len_stat = len_stat;
-
-		priv->rx_desc_count++;
-
-		/* tell dma engine we allocated one buffer */
-		enet_dma_writel(priv, 1, ENETDMA_BUFALLOC_REG(priv->rx_chan));
-	}
-
-	/* If rx ring is still empty, set a timer to try allocating
-	 * again at a later time. */
-	if (priv->rx_desc_count == 0 && netif_running(dev)) {
-		dev_warn(&priv->pdev->dev, "unable to refill rx ring\n");
-		priv->rx_timeout.expires = jiffies + HZ;
-		add_timer(&priv->rx_timeout);
-	}
-
-	return 0;
-}
-
-/*
- * timer callback to defer refill rx queue in case we're OOM
- */
-static void bcm_enet_refill_rx_timer(unsigned long data)
-{
-	struct net_device *dev;
-	struct bcm_enet_priv *priv;
-
-	dev = (struct net_device *)data;
-	priv = netdev_priv(dev);
-
-	spin_lock(&priv->rx_lock);
-	bcm_enet_refill_rx((struct net_device *)data);
-	spin_unlock(&priv->rx_lock);
-}
-
-/*
- * extract packet from rx queue
- */
-static int bcm_enet_receive_queue(struct net_device *dev, int budget)
-{
-	struct bcm_enet_priv *priv;
-	struct device *kdev;
-	int processed;
-
-	priv = netdev_priv(dev);
-	kdev = &priv->pdev->dev;
-	processed = 0;
-
-	/* don't scan ring further than number of refilled
-	 * descriptor */
-	if (budget > priv->rx_desc_count)
-		budget = priv->rx_desc_count;
-
-	do {
-		struct bcm_enet_desc *desc;
-		struct sk_buff *skb;
-		int desc_idx;
-		u32 len_stat;
-		unsigned int len;
-
-		desc_idx = priv->rx_curr_desc;
-		desc = &priv->rx_desc_cpu[desc_idx];
-
-		/* make sure we actually read the descriptor status at
-		 * each loop */
-		rmb();
-
-		len_stat = desc->len_stat;
-
-		/* break if dma ownership belongs to hw */
-		if (len_stat & DMADESC_OWNER_MASK)
-			break;
-
-		processed++;
-		priv->rx_curr_desc++;
-		if (priv->rx_curr_desc == priv->rx_ring_size)
-			priv->rx_curr_desc = 0;
-		priv->rx_desc_count--;
-
-		/* if the packet does not have start of packet _and_
-		 * end of packet flag set, then just recycle it */
-		if ((len_stat & DMADESC_ESOP_MASK) != DMADESC_ESOP_MASK) {
-			dev->stats.rx_dropped++;
-			continue;
-		}
-
-		/* recycle packet if it's marked as bad */
-		if (unlikely(len_stat & DMADESC_ERR_MASK)) {
-			dev->stats.rx_errors++;
-
-			if (len_stat & DMADESC_OVSIZE_MASK)
-				dev->stats.rx_length_errors++;
-			if (len_stat & DMADESC_CRC_MASK)
-				dev->stats.rx_crc_errors++;
-			if (len_stat & DMADESC_UNDER_MASK)
-				dev->stats.rx_frame_errors++;
-			if (len_stat & DMADESC_OV_MASK)
-				dev->stats.rx_fifo_errors++;
-			continue;
-		}
-
-		/* valid packet */
-		skb = priv->rx_skb[desc_idx];
-		len = (len_stat & DMADESC_LENGTH_MASK) >> DMADESC_LENGTH_SHIFT;
-		/* don't include FCS */
-		len -= 4;
-
-		if (len < copybreak) {
-			struct sk_buff *nskb;
-
-			nskb = netdev_alloc_skb_ip_align(dev, len);
-			if (!nskb) {
-				/* forget packet, just rearm desc */
-				dev->stats.rx_dropped++;
-				continue;
-			}
-
-			dma_sync_single_for_cpu(kdev, desc->address,
-						len, DMA_FROM_DEVICE);
-			memcpy(nskb->data, skb->data, len);
-			dma_sync_single_for_device(kdev, desc->address,
-						   len, DMA_FROM_DEVICE);
-			skb = nskb;
-		} else {
-			dma_unmap_single(&priv->pdev->dev, desc->address,
-					 priv->rx_skb_size, DMA_FROM_DEVICE);
-			priv->rx_skb[desc_idx] = NULL;
-		}
-
-		skb_put(skb, len);
-		skb->protocol = eth_type_trans(skb, dev);
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += len;
-		netif_receive_skb(skb);
-
-	} while (--budget > 0);
-
-	if (processed || !priv->rx_desc_count) {
-		bcm_enet_refill_rx(dev);
-
-		/* kick rx dma */
-		enet_dma_writel(priv, ENETDMA_CHANCFG_EN_MASK,
-				ENETDMA_CHANCFG_REG(priv->rx_chan));
-	}
-
-	return processed;
-}
-
-
-/*
- * try to or force reclaim of transmitted buffers
- */
-static int bcm_enet_tx_reclaim(struct net_device *dev, int force)
-{
-	struct bcm_enet_priv *priv;
-	int released;
-
-	priv = netdev_priv(dev);
-	released = 0;
-
-	while (priv->tx_desc_count < priv->tx_ring_size) {
-		struct bcm_enet_desc *desc;
-		struct sk_buff *skb;
-
-		/* We run in a bh and fight against start_xmit, which
-		 * is called with bh disabled  */
-		spin_lock(&priv->tx_lock);
-
-		desc = &priv->tx_desc_cpu[priv->tx_dirty_desc];
-
-		if (!force && (desc->len_stat & DMADESC_OWNER_MASK)) {
-			spin_unlock(&priv->tx_lock);
-			break;
-		}
-
-		/* ensure other field of the descriptor were not read
-		 * before we checked ownership */
-		rmb();
-
-		skb = priv->tx_skb[priv->tx_dirty_desc];
-		priv->tx_skb[priv->tx_dirty_desc] = NULL;
-		dma_unmap_single(&priv->pdev->dev, desc->address, skb->len,
-				 DMA_TO_DEVICE);
-
-		priv->tx_dirty_desc++;
-		if (priv->tx_dirty_desc == priv->tx_ring_size)
-			priv->tx_dirty_desc = 0;
-		priv->tx_desc_count++;
-
-		spin_unlock(&priv->tx_lock);
-
-		if (desc->len_stat & DMADESC_UNDER_MASK)
-			dev->stats.tx_errors++;
-
-		dev_kfree_skb(skb);
-		released++;
-	}
-
-	if (netif_queue_stopped(dev) && released)
-		netif_wake_queue(dev);
-
-	return released;
-}
-
-/*
- * poll func, called by network core
- */
-static int bcm_enet_poll(struct napi_struct *napi, int budget)
-{
-	struct bcm_enet_priv *priv;
-	struct net_device *dev;
-	int tx_work_done, rx_work_done;
-
-	priv = container_of(napi, struct bcm_enet_priv, napi);
-	dev = priv->net_dev;
-
-	/* ack interrupts */
-	enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
-			ENETDMA_IR_REG(priv->rx_chan));
-	enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
-			ENETDMA_IR_REG(priv->tx_chan));
-
-	/* reclaim sent skb */
-	tx_work_done = bcm_enet_tx_reclaim(dev, 0);
-
-	spin_lock(&priv->rx_lock);
-	rx_work_done = bcm_enet_receive_queue(dev, budget);
-	spin_unlock(&priv->rx_lock);
-
-	if (rx_work_done >= budget || tx_work_done > 0) {
-		/* rx/tx queue is not yet empty/clean */
-		return rx_work_done;
-	}
-
-	/* no more packet in rx/tx queue, remove device from poll
-	 * queue */
-	napi_complete(napi);
-
-	/* restore rx/tx interrupt */
-	enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
-			ENETDMA_IRMASK_REG(priv->rx_chan));
-	enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
-			ENETDMA_IRMASK_REG(priv->tx_chan));
-
-	return rx_work_done;
-}
-
-/*
- * mac interrupt handler
- */
-static irqreturn_t bcm_enet_isr_mac(int irq, void *dev_id)
-{
-	struct net_device *dev;
-	struct bcm_enet_priv *priv;
-	u32 stat;
-
-	dev = dev_id;
-	priv = netdev_priv(dev);
-
-	stat = enet_readl(priv, ENET_IR_REG);
-	if (!(stat & ENET_IR_MIB))
-		return IRQ_NONE;
-
-	/* clear & mask interrupt */
-	enet_writel(priv, ENET_IR_MIB, ENET_IR_REG);
-	enet_writel(priv, 0, ENET_IRMASK_REG);
-
-	/* read mib registers in workqueue */
-	schedule_work(&priv->mib_update_task);
-
-	return IRQ_HANDLED;
-}
-
-/*
- * rx/tx dma interrupt handler
- */
-static irqreturn_t bcm_enet_isr_dma(int irq, void *dev_id)
-{
-	struct net_device *dev;
-	struct bcm_enet_priv *priv;
-
-	dev = dev_id;
-	priv = netdev_priv(dev);
-
-	/* mask rx/tx interrupts */
-	enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan));
-	enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan));
-
-	napi_schedule(&priv->napi);
-
-	return IRQ_HANDLED;
-}
-
-/*
- * tx request callback
- */
-static int bcm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct bcm_enet_priv *priv;
-	struct bcm_enet_desc *desc;
-	u32 len_stat;
-	int ret;
-
-	priv = netdev_priv(dev);
-
-	/* lock against tx reclaim */
-	spin_lock(&priv->tx_lock);
-
-	/* make sure  the tx hw queue  is not full,  should not happen
-	 * since we stop queue before it's the case */
-	if (unlikely(!priv->tx_desc_count)) {
-		netif_stop_queue(dev);
-		dev_err(&priv->pdev->dev, "xmit called with no tx desc "
-			"available?\n");
-		ret = NETDEV_TX_BUSY;
-		goto out_unlock;
-	}
-
-	/* point to the next available desc */
-	desc = &priv->tx_desc_cpu[priv->tx_curr_desc];
-	priv->tx_skb[priv->tx_curr_desc] = skb;
-
-	/* fill descriptor */
-	desc->address = dma_map_single(&priv->pdev->dev, skb->data, skb->len,
-				       DMA_TO_DEVICE);
-
-	len_stat = (skb->len << DMADESC_LENGTH_SHIFT) & DMADESC_LENGTH_MASK;
-	len_stat |= DMADESC_ESOP_MASK |
-		DMADESC_APPEND_CRC |
-		DMADESC_OWNER_MASK;
-
-	priv->tx_curr_desc++;
-	if (priv->tx_curr_desc == priv->tx_ring_size) {
-		priv->tx_curr_desc = 0;
-		len_stat |= DMADESC_WRAP_MASK;
-	}
-	priv->tx_desc_count--;
-
-	/* dma might be already polling, make sure we update desc
-	 * fields in correct order */
-	wmb();
-	desc->len_stat = len_stat;
-	wmb();
-
-	/* kick tx dma */
-	enet_dma_writel(priv, ENETDMA_CHANCFG_EN_MASK,
-			ENETDMA_CHANCFG_REG(priv->tx_chan));
-
-	/* stop queue if no more desc available */
-	if (!priv->tx_desc_count)
-		netif_stop_queue(dev);
-
-	dev->stats.tx_bytes += skb->len;
-	dev->stats.tx_packets++;
-	ret = NETDEV_TX_OK;
-
-out_unlock:
-	spin_unlock(&priv->tx_lock);
-	return ret;
-}
-
-/*
- * Change the interface's mac address.
- */
-static int bcm_enet_set_mac_address(struct net_device *dev, void *p)
-{
-	struct bcm_enet_priv *priv;
-	struct sockaddr *addr = p;
-	u32 val;
-
-	priv = netdev_priv(dev);
-	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
-
-	/* use perfect match register 0 to store my mac address */
-	val = (dev->dev_addr[2] << 24) | (dev->dev_addr[3] << 16) |
-		(dev->dev_addr[4] << 8) | dev->dev_addr[5];
-	enet_writel(priv, val, ENET_PML_REG(0));
-
-	val = (dev->dev_addr[0] << 8 | dev->dev_addr[1]);
-	val |= ENET_PMH_DATAVALID_MASK;
-	enet_writel(priv, val, ENET_PMH_REG(0));
-
-	return 0;
-}
-
-/*
- * Change rx mode (promiscuous/allmulti) and update multicast list
- */
-static void bcm_enet_set_multicast_list(struct net_device *dev)
-{
-	struct bcm_enet_priv *priv;
-	struct netdev_hw_addr *ha;
-	u32 val;
-	int i;
-
-	priv = netdev_priv(dev);
-
-	val = enet_readl(priv, ENET_RXCFG_REG);
-
-	if (dev->flags & IFF_PROMISC)
-		val |= ENET_RXCFG_PROMISC_MASK;
-	else
-		val &= ~ENET_RXCFG_PROMISC_MASK;
-
-	/* only 3 perfect match registers left, first one is used for
-	 * own mac address */
-	if ((dev->flags & IFF_ALLMULTI) || netdev_mc_count(dev) > 3)
-		val |= ENET_RXCFG_ALLMCAST_MASK;
-	else
-		val &= ~ENET_RXCFG_ALLMCAST_MASK;
-
-	/* no need to set perfect match registers if we catch all
-	 * multicast */
-	if (val & ENET_RXCFG_ALLMCAST_MASK) {
-		enet_writel(priv, val, ENET_RXCFG_REG);
-		return;
-	}
-
-	i = 0;
-	netdev_for_each_mc_addr(ha, dev) {
-		u8 *dmi_addr;
-		u32 tmp;
-
-		if (i == 3)
-			break;
-		/* update perfect match registers */
-		dmi_addr = ha->addr;
-		tmp = (dmi_addr[2] << 24) | (dmi_addr[3] << 16) |
-			(dmi_addr[4] << 8) | dmi_addr[5];
-		enet_writel(priv, tmp, ENET_PML_REG(i + 1));
-
-		tmp = (dmi_addr[0] << 8 | dmi_addr[1]);
-		tmp |= ENET_PMH_DATAVALID_MASK;
-		enet_writel(priv, tmp, ENET_PMH_REG(i++ + 1));
-	}
-
-	for (; i < 3; i++) {
-		enet_writel(priv, 0, ENET_PML_REG(i + 1));
-		enet_writel(priv, 0, ENET_PMH_REG(i + 1));
-	}
-
-	enet_writel(priv, val, ENET_RXCFG_REG);
-}
-
-/*
- * set mac duplex parameters
- */
-static void bcm_enet_set_duplex(struct bcm_enet_priv *priv, int fullduplex)
-{
-	u32 val;
-
-	val = enet_readl(priv, ENET_TXCTL_REG);
-	if (fullduplex)
-		val |= ENET_TXCTL_FD_MASK;
-	else
-		val &= ~ENET_TXCTL_FD_MASK;
-	enet_writel(priv, val, ENET_TXCTL_REG);
-}
-
-/*
- * set mac flow control parameters
- */
-static void bcm_enet_set_flow(struct bcm_enet_priv *priv, int rx_en, int tx_en)
-{
-	u32 val;
-
-	/* rx flow control (pause frame handling) */
-	val = enet_readl(priv, ENET_RXCFG_REG);
-	if (rx_en)
-		val |= ENET_RXCFG_ENFLOW_MASK;
-	else
-		val &= ~ENET_RXCFG_ENFLOW_MASK;
-	enet_writel(priv, val, ENET_RXCFG_REG);
-
-	/* tx flow control (pause frame generation) */
-	val = enet_dma_readl(priv, ENETDMA_CFG_REG);
-	if (tx_en)
-		val |= ENETDMA_CFG_FLOWCH_MASK(priv->rx_chan);
-	else
-		val &= ~ENETDMA_CFG_FLOWCH_MASK(priv->rx_chan);
-	enet_dma_writel(priv, val, ENETDMA_CFG_REG);
-}
-
-/*
- * link changed callback (from phylib)
- */
-static void bcm_enet_adjust_phy_link(struct net_device *dev)
-{
-	struct bcm_enet_priv *priv;
-	struct phy_device *phydev;
-	int status_changed;
-
-	priv = netdev_priv(dev);
-	phydev = priv->phydev;
-	status_changed = 0;
-
-	if (priv->old_link != phydev->link) {
-		status_changed = 1;
-		priv->old_link = phydev->link;
-	}
-
-	/* reflect duplex change in mac configuration */
-	if (phydev->link && phydev->duplex != priv->old_duplex) {
-		bcm_enet_set_duplex(priv,
-				    (phydev->duplex == DUPLEX_FULL) ? 1 : 0);
-		status_changed = 1;
-		priv->old_duplex = phydev->duplex;
-	}
-
-	/* enable flow control if remote advertise it (trust phylib to
-	 * check that duplex is full */
-	if (phydev->link && phydev->pause != priv->old_pause) {
-		int rx_pause_en, tx_pause_en;
-
-		if (phydev->pause) {
-			/* pause was advertised by lpa and us */
-			rx_pause_en = 1;
-			tx_pause_en = 1;
-		} else if (!priv->pause_auto) {
-			/* pause setting overrided by user */
-			rx_pause_en = priv->pause_rx;
-			tx_pause_en = priv->pause_tx;
-		} else {
-			rx_pause_en = 0;
-			tx_pause_en = 0;
-		}
-
-		bcm_enet_set_flow(priv, rx_pause_en, tx_pause_en);
-		status_changed = 1;
-		priv->old_pause = phydev->pause;
-	}
-
-	if (status_changed) {
-		pr_info("%s: link %s", dev->name, phydev->link ?
-			"UP" : "DOWN");
-		if (phydev->link)
-			pr_cont(" - %d/%s - flow control %s", phydev->speed,
-			       DUPLEX_FULL == phydev->duplex ? "full" : "half",
-			       phydev->pause == 1 ? "rx&tx" : "off");
-
-		pr_cont("\n");
-	}
-}
-
-/*
- * link changed callback (if phylib is not used)
- */
-static void bcm_enet_adjust_link(struct net_device *dev)
-{
-	struct bcm_enet_priv *priv;
-
-	priv = netdev_priv(dev);
-	bcm_enet_set_duplex(priv, priv->force_duplex_full);
-	bcm_enet_set_flow(priv, priv->pause_rx, priv->pause_tx);
-	netif_carrier_on(dev);
-
-	pr_info("%s: link forced UP - %d/%s - flow control %s/%s\n",
-		dev->name,
-		priv->force_speed_100 ? 100 : 10,
-		priv->force_duplex_full ? "full" : "half",
-		priv->pause_rx ? "rx" : "off",
-		priv->pause_tx ? "tx" : "off");
-}
-
-/*
- * open callback, allocate dma rings & buffers and start rx operation
- */
-static int bcm_enet_open(struct net_device *dev)
-{
-	struct bcm_enet_priv *priv;
-	struct sockaddr addr;
-	struct device *kdev;
-	struct phy_device *phydev;
-	int i, ret;
-	unsigned int size;
-	char phy_id[MII_BUS_ID_SIZE + 3];
-	void *p;
-	u32 val;
-
-	priv = netdev_priv(dev);
-	kdev = &priv->pdev->dev;
-
-	if (priv->has_phy) {
-		/* connect to PHY */
-		snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
-			 priv->mac_id ? "1" : "0", priv->phy_id);
-
-		phydev = phy_connect(dev, phy_id, bcm_enet_adjust_phy_link, 0,
-				     PHY_INTERFACE_MODE_MII);
-
-		if (IS_ERR(phydev)) {
-			dev_err(kdev, "could not attach to PHY\n");
-			return PTR_ERR(phydev);
-		}
-
-		/* mask with MAC supported features */
-		phydev->supported &= (SUPPORTED_10baseT_Half |
-				      SUPPORTED_10baseT_Full |
-				      SUPPORTED_100baseT_Half |
-				      SUPPORTED_100baseT_Full |
-				      SUPPORTED_Autoneg |
-				      SUPPORTED_Pause |
-				      SUPPORTED_MII);
-		phydev->advertising = phydev->supported;
-
-		if (priv->pause_auto && priv->pause_rx && priv->pause_tx)
-			phydev->advertising |= SUPPORTED_Pause;
-		else
-			phydev->advertising &= ~SUPPORTED_Pause;
-
-		dev_info(kdev, "attached PHY at address %d [%s]\n",
-			 phydev->addr, phydev->drv->name);
-
-		priv->old_link = 0;
-		priv->old_duplex = -1;
-		priv->old_pause = -1;
-		priv->phydev = phydev;
-	}
-
-	/* mask all interrupts and request them */
-	enet_writel(priv, 0, ENET_IRMASK_REG);
-	enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan));
-	enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan));
-
-	ret = request_irq(dev->irq, bcm_enet_isr_mac, 0, dev->name, dev);
-	if (ret)
-		goto out_phy_disconnect;
-
-	ret = request_irq(priv->irq_rx, bcm_enet_isr_dma, IRQF_DISABLED,
-			  dev->name, dev);
-	if (ret)
-		goto out_freeirq;
-
-	ret = request_irq(priv->irq_tx, bcm_enet_isr_dma,
-			  IRQF_DISABLED, dev->name, dev);
-	if (ret)
-		goto out_freeirq_rx;
-
-	/* initialize perfect match registers */
-	for (i = 0; i < 4; i++) {
-		enet_writel(priv, 0, ENET_PML_REG(i));
-		enet_writel(priv, 0, ENET_PMH_REG(i));
-	}
-
-	/* write device mac address */
-	memcpy(addr.sa_data, dev->dev_addr, ETH_ALEN);
-	bcm_enet_set_mac_address(dev, &addr);
-
-	/* allocate rx dma ring */
-	size = priv->rx_ring_size * sizeof(struct bcm_enet_desc);
-	p = dma_alloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
-	if (!p) {
-		dev_err(kdev, "cannot allocate rx ring %u\n", size);
-		ret = -ENOMEM;
-		goto out_freeirq_tx;
-	}
-
-	memset(p, 0, size);
-	priv->rx_desc_alloc_size = size;
-	priv->rx_desc_cpu = p;
-
-	/* allocate tx dma ring */
-	size = priv->tx_ring_size * sizeof(struct bcm_enet_desc);
-	p = dma_alloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
-	if (!p) {
-		dev_err(kdev, "cannot allocate tx ring\n");
-		ret = -ENOMEM;
-		goto out_free_rx_ring;
-	}
-
-	memset(p, 0, size);
-	priv->tx_desc_alloc_size = size;
-	priv->tx_desc_cpu = p;
-
-	priv->tx_skb = kzalloc(sizeof(struct sk_buff *) * priv->tx_ring_size,
-			       GFP_KERNEL);
-	if (!priv->tx_skb) {
-		dev_err(kdev, "cannot allocate rx skb queue\n");
-		ret = -ENOMEM;
-		goto out_free_tx_ring;
-	}
-
-	priv->tx_desc_count = priv->tx_ring_size;
-	priv->tx_dirty_desc = 0;
-	priv->tx_curr_desc = 0;
-	spin_lock_init(&priv->tx_lock);
-
-	/* init & fill rx ring with skbs */
-	priv->rx_skb = kzalloc(sizeof(struct sk_buff *) * priv->rx_ring_size,
-			       GFP_KERNEL);
-	if (!priv->rx_skb) {
-		dev_err(kdev, "cannot allocate rx skb queue\n");
-		ret = -ENOMEM;
-		goto out_free_tx_skb;
-	}
-
-	priv->rx_desc_count = 0;
-	priv->rx_dirty_desc = 0;
-	priv->rx_curr_desc = 0;
-
-	/* initialize flow control buffer allocation */
-	enet_dma_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0,
-			ENETDMA_BUFALLOC_REG(priv->rx_chan));
-
-	if (bcm_enet_refill_rx(dev)) {
-		dev_err(kdev, "cannot allocate rx skb queue\n");
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	/* write rx & tx ring addresses */
-	enet_dma_writel(priv, priv->rx_desc_dma,
-			ENETDMA_RSTART_REG(priv->rx_chan));
-	enet_dma_writel(priv, priv->tx_desc_dma,
-			ENETDMA_RSTART_REG(priv->tx_chan));
-
-	/* clear remaining state ram for rx & tx channel */
-	enet_dma_writel(priv, 0, ENETDMA_SRAM2_REG(priv->rx_chan));
-	enet_dma_writel(priv, 0, ENETDMA_SRAM2_REG(priv->tx_chan));
-	enet_dma_writel(priv, 0, ENETDMA_SRAM3_REG(priv->rx_chan));
-	enet_dma_writel(priv, 0, ENETDMA_SRAM3_REG(priv->tx_chan));
-	enet_dma_writel(priv, 0, ENETDMA_SRAM4_REG(priv->rx_chan));
-	enet_dma_writel(priv, 0, ENETDMA_SRAM4_REG(priv->tx_chan));
-
-	/* set max rx/tx length */
-	enet_writel(priv, priv->hw_mtu, ENET_RXMAXLEN_REG);
-	enet_writel(priv, priv->hw_mtu, ENET_TXMAXLEN_REG);
-
-	/* set dma maximum burst len */
-	enet_dma_writel(priv, BCMENET_DMA_MAXBURST,
-			ENETDMA_MAXBURST_REG(priv->rx_chan));
-	enet_dma_writel(priv, BCMENET_DMA_MAXBURST,
-			ENETDMA_MAXBURST_REG(priv->tx_chan));
-
-	/* set correct transmit fifo watermark */
-	enet_writel(priv, BCMENET_TX_FIFO_TRESH, ENET_TXWMARK_REG);
-
-	/* set flow control low/high threshold to 1/3 / 2/3 */
-	val = priv->rx_ring_size / 3;
-	enet_dma_writel(priv, val, ENETDMA_FLOWCL_REG(priv->rx_chan));
-	val = (priv->rx_ring_size * 2) / 3;
-	enet_dma_writel(priv, val, ENETDMA_FLOWCH_REG(priv->rx_chan));
-
-	/* all set, enable mac and interrupts, start dma engine and
-	 * kick rx dma channel */
-	wmb();
-	val = enet_readl(priv, ENET_CTL_REG);
-	val |= ENET_CTL_ENABLE_MASK;
-	enet_writel(priv, val, ENET_CTL_REG);
-	enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG);
-	enet_dma_writel(priv, ENETDMA_CHANCFG_EN_MASK,
-			ENETDMA_CHANCFG_REG(priv->rx_chan));
-
-	/* watch "mib counters about to overflow" interrupt */
-	enet_writel(priv, ENET_IR_MIB, ENET_IR_REG);
-	enet_writel(priv, ENET_IR_MIB, ENET_IRMASK_REG);
-
-	/* watch "packet transferred" interrupt in rx and tx */
-	enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
-			ENETDMA_IR_REG(priv->rx_chan));
-	enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
-			ENETDMA_IR_REG(priv->tx_chan));
-
-	/* make sure we enable napi before rx interrupt  */
-	napi_enable(&priv->napi);
-
-	enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
-			ENETDMA_IRMASK_REG(priv->rx_chan));
-	enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
-			ENETDMA_IRMASK_REG(priv->tx_chan));
-
-	if (priv->has_phy)
-		phy_start(priv->phydev);
-	else
-		bcm_enet_adjust_link(dev);
-
-	netif_start_queue(dev);
-	return 0;
-
-out:
-	for (i = 0; i < priv->rx_ring_size; i++) {
-		struct bcm_enet_desc *desc;
-
-		if (!priv->rx_skb[i])
-			continue;
-
-		desc = &priv->rx_desc_cpu[i];
-		dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
-				 DMA_FROM_DEVICE);
-		kfree_skb(priv->rx_skb[i]);
-	}
-	kfree(priv->rx_skb);
-
-out_free_tx_skb:
-	kfree(priv->tx_skb);
-
-out_free_tx_ring:
-	dma_free_coherent(kdev, priv->tx_desc_alloc_size,
-			  priv->tx_desc_cpu, priv->tx_desc_dma);
-
-out_free_rx_ring:
-	dma_free_coherent(kdev, priv->rx_desc_alloc_size,
-			  priv->rx_desc_cpu, priv->rx_desc_dma);
-
-out_freeirq_tx:
-	free_irq(priv->irq_tx, dev);
-
-out_freeirq_rx:
-	free_irq(priv->irq_rx, dev);
-
-out_freeirq:
-	free_irq(dev->irq, dev);
-
-out_phy_disconnect:
-	phy_disconnect(priv->phydev);
-
-	return ret;
-}
-
-/*
- * disable mac
- */
-static void bcm_enet_disable_mac(struct bcm_enet_priv *priv)
-{
-	int limit;
-	u32 val;
-
-	val = enet_readl(priv, ENET_CTL_REG);
-	val |= ENET_CTL_DISABLE_MASK;
-	enet_writel(priv, val, ENET_CTL_REG);
-
-	limit = 1000;
-	do {
-		u32 val;
-
-		val = enet_readl(priv, ENET_CTL_REG);
-		if (!(val & ENET_CTL_DISABLE_MASK))
-			break;
-		udelay(1);
-	} while (limit--);
-}
-
-/*
- * disable dma in given channel
- */
-static void bcm_enet_disable_dma(struct bcm_enet_priv *priv, int chan)
-{
-	int limit;
-
-	enet_dma_writel(priv, 0, ENETDMA_CHANCFG_REG(chan));
-
-	limit = 1000;
-	do {
-		u32 val;
-
-		val = enet_dma_readl(priv, ENETDMA_CHANCFG_REG(chan));
-		if (!(val & ENETDMA_CHANCFG_EN_MASK))
-			break;
-		udelay(1);
-	} while (limit--);
-}
-
-/*
- * stop callback
- */
-static int bcm_enet_stop(struct net_device *dev)
-{
-	struct bcm_enet_priv *priv;
-	struct device *kdev;
-	int i;
-
-	priv = netdev_priv(dev);
-	kdev = &priv->pdev->dev;
-
-	netif_stop_queue(dev);
-	napi_disable(&priv->napi);
-	if (priv->has_phy)
-		phy_stop(priv->phydev);
-	del_timer_sync(&priv->rx_timeout);
-
-	/* mask all interrupts */
-	enet_writel(priv, 0, ENET_IRMASK_REG);
-	enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan));
-	enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan));
-
-	/* make sure no mib update is scheduled */
-	cancel_work_sync(&priv->mib_update_task);
-
-	/* disable dma & mac */
-	bcm_enet_disable_dma(priv, priv->tx_chan);
-	bcm_enet_disable_dma(priv, priv->rx_chan);
-	bcm_enet_disable_mac(priv);
-
-	/* force reclaim of all tx buffers */
-	bcm_enet_tx_reclaim(dev, 1);
-
-	/* free the rx skb ring */
-	for (i = 0; i < priv->rx_ring_size; i++) {
-		struct bcm_enet_desc *desc;
-
-		if (!priv->rx_skb[i])
-			continue;
-
-		desc = &priv->rx_desc_cpu[i];
-		dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
-				 DMA_FROM_DEVICE);
-		kfree_skb(priv->rx_skb[i]);
-	}
-
-	/* free remaining allocated memory */
-	kfree(priv->rx_skb);
-	kfree(priv->tx_skb);
-	dma_free_coherent(kdev, priv->rx_desc_alloc_size,
-			  priv->rx_desc_cpu, priv->rx_desc_dma);
-	dma_free_coherent(kdev, priv->tx_desc_alloc_size,
-			  priv->tx_desc_cpu, priv->tx_desc_dma);
-	free_irq(priv->irq_tx, dev);
-	free_irq(priv->irq_rx, dev);
-	free_irq(dev->irq, dev);
-
-	/* release phy */
-	if (priv->has_phy) {
-		phy_disconnect(priv->phydev);
-		priv->phydev = NULL;
-	}
-
-	return 0;
-}
-
-/*
- * ethtool callbacks
- */
-struct bcm_enet_stats {
-	char stat_string[ETH_GSTRING_LEN];
-	int sizeof_stat;
-	int stat_offset;
-	int mib_reg;
-};
-
-#define GEN_STAT(m) sizeof(((struct bcm_enet_priv *)0)->m),		\
-		     offsetof(struct bcm_enet_priv, m)
-#define DEV_STAT(m) sizeof(((struct net_device_stats *)0)->m),		\
-		     offsetof(struct net_device_stats, m)
-
-static const struct bcm_enet_stats bcm_enet_gstrings_stats[] = {
-	{ "rx_packets", DEV_STAT(rx_packets), -1 },
-	{ "tx_packets",	DEV_STAT(tx_packets), -1 },
-	{ "rx_bytes", DEV_STAT(rx_bytes), -1 },
-	{ "tx_bytes", DEV_STAT(tx_bytes), -1 },
-	{ "rx_errors", DEV_STAT(rx_errors), -1 },
-	{ "tx_errors", DEV_STAT(tx_errors), -1 },
-	{ "rx_dropped",	DEV_STAT(rx_dropped), -1 },
-	{ "tx_dropped",	DEV_STAT(tx_dropped), -1 },
-
-	{ "rx_good_octets", GEN_STAT(mib.rx_gd_octets), ETH_MIB_RX_GD_OCTETS},
-	{ "rx_good_pkts", GEN_STAT(mib.rx_gd_pkts), ETH_MIB_RX_GD_PKTS },
-	{ "rx_broadcast", GEN_STAT(mib.rx_brdcast), ETH_MIB_RX_BRDCAST },
-	{ "rx_multicast", GEN_STAT(mib.rx_mult), ETH_MIB_RX_MULT },
-	{ "rx_64_octets", GEN_STAT(mib.rx_64), ETH_MIB_RX_64 },
-	{ "rx_65_127_oct", GEN_STAT(mib.rx_65_127), ETH_MIB_RX_65_127 },
-	{ "rx_128_255_oct", GEN_STAT(mib.rx_128_255), ETH_MIB_RX_128_255 },
-	{ "rx_256_511_oct", GEN_STAT(mib.rx_256_511), ETH_MIB_RX_256_511 },
-	{ "rx_512_1023_oct", GEN_STAT(mib.rx_512_1023), ETH_MIB_RX_512_1023 },
-	{ "rx_1024_max_oct", GEN_STAT(mib.rx_1024_max), ETH_MIB_RX_1024_MAX },
-	{ "rx_jabber", GEN_STAT(mib.rx_jab), ETH_MIB_RX_JAB },
-	{ "rx_oversize", GEN_STAT(mib.rx_ovr), ETH_MIB_RX_OVR },
-	{ "rx_fragment", GEN_STAT(mib.rx_frag), ETH_MIB_RX_FRAG },
-	{ "rx_dropped",	GEN_STAT(mib.rx_drop), ETH_MIB_RX_DROP },
-	{ "rx_crc_align", GEN_STAT(mib.rx_crc_align), ETH_MIB_RX_CRC_ALIGN },
-	{ "rx_undersize", GEN_STAT(mib.rx_und), ETH_MIB_RX_UND },
-	{ "rx_crc", GEN_STAT(mib.rx_crc), ETH_MIB_RX_CRC },
-	{ "rx_align", GEN_STAT(mib.rx_align), ETH_MIB_RX_ALIGN },
-	{ "rx_symbol_error", GEN_STAT(mib.rx_sym), ETH_MIB_RX_SYM },
-	{ "rx_pause", GEN_STAT(mib.rx_pause), ETH_MIB_RX_PAUSE },
-	{ "rx_control", GEN_STAT(mib.rx_cntrl), ETH_MIB_RX_CNTRL },
-
-	{ "tx_good_octets", GEN_STAT(mib.tx_gd_octets), ETH_MIB_TX_GD_OCTETS },
-	{ "tx_good_pkts", GEN_STAT(mib.tx_gd_pkts), ETH_MIB_TX_GD_PKTS },
-	{ "tx_broadcast", GEN_STAT(mib.tx_brdcast), ETH_MIB_TX_BRDCAST },
-	{ "tx_multicast", GEN_STAT(mib.tx_mult), ETH_MIB_TX_MULT },
-	{ "tx_64_oct", GEN_STAT(mib.tx_64), ETH_MIB_TX_64 },
-	{ "tx_65_127_oct", GEN_STAT(mib.tx_65_127), ETH_MIB_TX_65_127 },
-	{ "tx_128_255_oct", GEN_STAT(mib.tx_128_255), ETH_MIB_TX_128_255 },
-	{ "tx_256_511_oct", GEN_STAT(mib.tx_256_511), ETH_MIB_TX_256_511 },
-	{ "tx_512_1023_oct", GEN_STAT(mib.tx_512_1023), ETH_MIB_TX_512_1023},
-	{ "tx_1024_max_oct", GEN_STAT(mib.tx_1024_max), ETH_MIB_TX_1024_MAX },
-	{ "tx_jabber", GEN_STAT(mib.tx_jab), ETH_MIB_TX_JAB },
-	{ "tx_oversize", GEN_STAT(mib.tx_ovr), ETH_MIB_TX_OVR },
-	{ "tx_fragment", GEN_STAT(mib.tx_frag), ETH_MIB_TX_FRAG },
-	{ "tx_underrun", GEN_STAT(mib.tx_underrun), ETH_MIB_TX_UNDERRUN },
-	{ "tx_collisions", GEN_STAT(mib.tx_col), ETH_MIB_TX_COL },
-	{ "tx_single_collision", GEN_STAT(mib.tx_1_col), ETH_MIB_TX_1_COL },
-	{ "tx_multiple_collision", GEN_STAT(mib.tx_m_col), ETH_MIB_TX_M_COL },
-	{ "tx_excess_collision", GEN_STAT(mib.tx_ex_col), ETH_MIB_TX_EX_COL },
-	{ "tx_late_collision", GEN_STAT(mib.tx_late), ETH_MIB_TX_LATE },
-	{ "tx_deferred", GEN_STAT(mib.tx_def), ETH_MIB_TX_DEF },
-	{ "tx_carrier_sense", GEN_STAT(mib.tx_crs), ETH_MIB_TX_CRS },
-	{ "tx_pause", GEN_STAT(mib.tx_pause), ETH_MIB_TX_PAUSE },
-
-};
-
-#define BCM_ENET_STATS_LEN	\
-	(sizeof(bcm_enet_gstrings_stats) / sizeof(struct bcm_enet_stats))
-
-static const u32 unused_mib_regs[] = {
-	ETH_MIB_TX_ALL_OCTETS,
-	ETH_MIB_TX_ALL_PKTS,
-	ETH_MIB_RX_ALL_OCTETS,
-	ETH_MIB_RX_ALL_PKTS,
-};
-
-
-static void bcm_enet_get_drvinfo(struct net_device *netdev,
-				 struct ethtool_drvinfo *drvinfo)
-{
-	strncpy(drvinfo->driver, bcm_enet_driver_name, 32);
-	strncpy(drvinfo->version, bcm_enet_driver_version, 32);
-	strncpy(drvinfo->fw_version, "N/A", 32);
-	strncpy(drvinfo->bus_info, "bcm63xx", 32);
-	drvinfo->n_stats = BCM_ENET_STATS_LEN;
-}
-
-static int bcm_enet_get_sset_count(struct net_device *netdev,
-					int string_set)
-{
-	switch (string_set) {
-	case ETH_SS_STATS:
-		return BCM_ENET_STATS_LEN;
-	default:
-		return -EINVAL;
-	}
-}
-
-static void bcm_enet_get_strings(struct net_device *netdev,
-				 u32 stringset, u8 *data)
-{
-	int i;
-
-	switch (stringset) {
-	case ETH_SS_STATS:
-		for (i = 0; i < BCM_ENET_STATS_LEN; i++) {
-			memcpy(data + i * ETH_GSTRING_LEN,
-			       bcm_enet_gstrings_stats[i].stat_string,
-			       ETH_GSTRING_LEN);
-		}
-		break;
-	}
-}
-
-static void update_mib_counters(struct bcm_enet_priv *priv)
-{
-	int i;
-
-	for (i = 0; i < BCM_ENET_STATS_LEN; i++) {
-		const struct bcm_enet_stats *s;
-		u32 val;
-		char *p;
-
-		s = &bcm_enet_gstrings_stats[i];
-		if (s->mib_reg == -1)
-			continue;
-
-		val = enet_readl(priv, ENET_MIB_REG(s->mib_reg));
-		p = (char *)priv + s->stat_offset;
-
-		if (s->sizeof_stat == sizeof(u64))
-			*(u64 *)p += val;
-		else
-			*(u32 *)p += val;
-	}
-
-	/* also empty unused mib counters to make sure mib counter
-	 * overflow interrupt is cleared */
-	for (i = 0; i < ARRAY_SIZE(unused_mib_regs); i++)
-		(void)enet_readl(priv, ENET_MIB_REG(unused_mib_regs[i]));
-}
-
-static void bcm_enet_update_mib_counters_defer(struct work_struct *t)
-{
-	struct bcm_enet_priv *priv;
-
-	priv = container_of(t, struct bcm_enet_priv, mib_update_task);
-	mutex_lock(&priv->mib_update_lock);
-	update_mib_counters(priv);
-	mutex_unlock(&priv->mib_update_lock);
-
-	/* reenable mib interrupt */
-	if (netif_running(priv->net_dev))
-		enet_writel(priv, ENET_IR_MIB, ENET_IRMASK_REG);
-}
-
-static void bcm_enet_get_ethtool_stats(struct net_device *netdev,
-				       struct ethtool_stats *stats,
-				       u64 *data)
-{
-	struct bcm_enet_priv *priv;
-	int i;
-
-	priv = netdev_priv(netdev);
-
-	mutex_lock(&priv->mib_update_lock);
-	update_mib_counters(priv);
-
-	for (i = 0; i < BCM_ENET_STATS_LEN; i++) {
-		const struct bcm_enet_stats *s;
-		char *p;
-
-		s = &bcm_enet_gstrings_stats[i];
-		if (s->mib_reg == -1)
-			p = (char *)&netdev->stats;
-		else
-			p = (char *)priv;
-		p += s->stat_offset;
-		data[i] = (s->sizeof_stat == sizeof(u64)) ?
-			*(u64 *)p : *(u32 *)p;
-	}
-	mutex_unlock(&priv->mib_update_lock);
-}
-
-static int bcm_enet_get_settings(struct net_device *dev,
-				 struct ethtool_cmd *cmd)
-{
-	struct bcm_enet_priv *priv;
-
-	priv = netdev_priv(dev);
-
-	cmd->maxrxpkt = 0;
-	cmd->maxtxpkt = 0;
-
-	if (priv->has_phy) {
-		if (!priv->phydev)
-			return -ENODEV;
-		return phy_ethtool_gset(priv->phydev, cmd);
-	} else {
-		cmd->autoneg = 0;
-		ethtool_cmd_speed_set(cmd, ((priv->force_speed_100)
-					    ? SPEED_100 : SPEED_10));
-		cmd->duplex = (priv->force_duplex_full) ?
-			DUPLEX_FULL : DUPLEX_HALF;
-		cmd->supported = ADVERTISED_10baseT_Half  |
-			ADVERTISED_10baseT_Full |
-			ADVERTISED_100baseT_Half |
-			ADVERTISED_100baseT_Full;
-		cmd->advertising = 0;
-		cmd->port = PORT_MII;
-		cmd->transceiver = XCVR_EXTERNAL;
-	}
-	return 0;
-}
-
-static int bcm_enet_set_settings(struct net_device *dev,
-				 struct ethtool_cmd *cmd)
-{
-	struct bcm_enet_priv *priv;
-
-	priv = netdev_priv(dev);
-	if (priv->has_phy) {
-		if (!priv->phydev)
-			return -ENODEV;
-		return phy_ethtool_sset(priv->phydev, cmd);
-	} else {
-
-		if (cmd->autoneg ||
-		    (cmd->speed != SPEED_100 && cmd->speed != SPEED_10) ||
-		    cmd->port != PORT_MII)
-			return -EINVAL;
-
-		priv->force_speed_100 = (cmd->speed == SPEED_100) ? 1 : 0;
-		priv->force_duplex_full = (cmd->duplex == DUPLEX_FULL) ? 1 : 0;
-
-		if (netif_running(dev))
-			bcm_enet_adjust_link(dev);
-		return 0;
-	}
-}
-
-static void bcm_enet_get_ringparam(struct net_device *dev,
-				   struct ethtool_ringparam *ering)
-{
-	struct bcm_enet_priv *priv;
-
-	priv = netdev_priv(dev);
-
-	/* rx/tx ring is actually only limited by memory */
-	ering->rx_max_pending = 8192;
-	ering->tx_max_pending = 8192;
-	ering->rx_mini_max_pending = 0;
-	ering->rx_jumbo_max_pending = 0;
-	ering->rx_pending = priv->rx_ring_size;
-	ering->tx_pending = priv->tx_ring_size;
-}
-
-static int bcm_enet_set_ringparam(struct net_device *dev,
-				  struct ethtool_ringparam *ering)
-{
-	struct bcm_enet_priv *priv;
-	int was_running;
-
-	priv = netdev_priv(dev);
-
-	was_running = 0;
-	if (netif_running(dev)) {
-		bcm_enet_stop(dev);
-		was_running = 1;
-	}
-
-	priv->rx_ring_size = ering->rx_pending;
-	priv->tx_ring_size = ering->tx_pending;
-
-	if (was_running) {
-		int err;
-
-		err = bcm_enet_open(dev);
-		if (err)
-			dev_close(dev);
-		else
-			bcm_enet_set_multicast_list(dev);
-	}
-	return 0;
-}
-
-static void bcm_enet_get_pauseparam(struct net_device *dev,
-				    struct ethtool_pauseparam *ecmd)
-{
-	struct bcm_enet_priv *priv;
-
-	priv = netdev_priv(dev);
-	ecmd->autoneg = priv->pause_auto;
-	ecmd->rx_pause = priv->pause_rx;
-	ecmd->tx_pause = priv->pause_tx;
-}
-
-static int bcm_enet_set_pauseparam(struct net_device *dev,
-				   struct ethtool_pauseparam *ecmd)
-{
-	struct bcm_enet_priv *priv;
-
-	priv = netdev_priv(dev);
-
-	if (priv->has_phy) {
-		if (ecmd->autoneg && (ecmd->rx_pause != ecmd->tx_pause)) {
-			/* asymetric pause mode not supported,
-			 * actually possible but integrated PHY has RO
-			 * asym_pause bit */
-			return -EINVAL;
-		}
-	} else {
-		/* no pause autoneg on direct mii connection */
-		if (ecmd->autoneg)
-			return -EINVAL;
-	}
-
-	priv->pause_auto = ecmd->autoneg;
-	priv->pause_rx = ecmd->rx_pause;
-	priv->pause_tx = ecmd->tx_pause;
-
-	return 0;
-}
-
-static struct ethtool_ops bcm_enet_ethtool_ops = {
-	.get_strings		= bcm_enet_get_strings,
-	.get_sset_count		= bcm_enet_get_sset_count,
-	.get_ethtool_stats      = bcm_enet_get_ethtool_stats,
-	.get_settings		= bcm_enet_get_settings,
-	.set_settings		= bcm_enet_set_settings,
-	.get_drvinfo		= bcm_enet_get_drvinfo,
-	.get_link		= ethtool_op_get_link,
-	.get_ringparam		= bcm_enet_get_ringparam,
-	.set_ringparam		= bcm_enet_set_ringparam,
-	.get_pauseparam		= bcm_enet_get_pauseparam,
-	.set_pauseparam		= bcm_enet_set_pauseparam,
-};
-
-static int bcm_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct bcm_enet_priv *priv;
-
-	priv = netdev_priv(dev);
-	if (priv->has_phy) {
-		if (!priv->phydev)
-			return -ENODEV;
-		return phy_mii_ioctl(priv->phydev, rq, cmd);
-	} else {
-		struct mii_if_info mii;
-
-		mii.dev = dev;
-		mii.mdio_read = bcm_enet_mdio_read_mii;
-		mii.mdio_write = bcm_enet_mdio_write_mii;
-		mii.phy_id = 0;
-		mii.phy_id_mask = 0x3f;
-		mii.reg_num_mask = 0x1f;
-		return generic_mii_ioctl(&mii, if_mii(rq), cmd, NULL);
-	}
-}
-
-/*
- * calculate actual hardware mtu
- */
-static int compute_hw_mtu(struct bcm_enet_priv *priv, int mtu)
-{
-	int actual_mtu;
-
-	actual_mtu = mtu;
-
-	/* add ethernet header + vlan tag size */
-	actual_mtu += VLAN_ETH_HLEN;
-
-	if (actual_mtu < 64 || actual_mtu > BCMENET_MAX_MTU)
-		return -EINVAL;
-
-	/*
-	 * setup maximum size before we get overflow mark in
-	 * descriptor, note that this will not prevent reception of
-	 * big frames, they will be split into multiple buffers
-	 * anyway
-	 */
-	priv->hw_mtu = actual_mtu;
-
-	/*
-	 * align rx buffer size to dma burst len, account FCS since
-	 * it's appended
-	 */
-	priv->rx_skb_size = ALIGN(actual_mtu + ETH_FCS_LEN,
-				  BCMENET_DMA_MAXBURST * 4);
-	return 0;
-}
-
-/*
- * adjust mtu, can't be called while device is running
- */
-static int bcm_enet_change_mtu(struct net_device *dev, int new_mtu)
-{
-	int ret;
-
-	if (netif_running(dev))
-		return -EBUSY;
-
-	ret = compute_hw_mtu(netdev_priv(dev), new_mtu);
-	if (ret)
-		return ret;
-	dev->mtu = new_mtu;
-	return 0;
-}
-
-/*
- * preinit hardware to allow mii operation while device is down
- */
-static void bcm_enet_hw_preinit(struct bcm_enet_priv *priv)
-{
-	u32 val;
-	int limit;
-
-	/* make sure mac is disabled */
-	bcm_enet_disable_mac(priv);
-
-	/* soft reset mac */
-	val = ENET_CTL_SRESET_MASK;
-	enet_writel(priv, val, ENET_CTL_REG);
-	wmb();
-
-	limit = 1000;
-	do {
-		val = enet_readl(priv, ENET_CTL_REG);
-		if (!(val & ENET_CTL_SRESET_MASK))
-			break;
-		udelay(1);
-	} while (limit--);
-
-	/* select correct mii interface */
-	val = enet_readl(priv, ENET_CTL_REG);
-	if (priv->use_external_mii)
-		val |= ENET_CTL_EPHYSEL_MASK;
-	else
-		val &= ~ENET_CTL_EPHYSEL_MASK;
-	enet_writel(priv, val, ENET_CTL_REG);
-
-	/* turn on mdc clock */
-	enet_writel(priv, (0x1f << ENET_MIISC_MDCFREQDIV_SHIFT) |
-		    ENET_MIISC_PREAMBLEEN_MASK, ENET_MIISC_REG);
-
-	/* set mib counters to self-clear when read */
-	val = enet_readl(priv, ENET_MIBCTL_REG);
-	val |= ENET_MIBCTL_RDCLEAR_MASK;
-	enet_writel(priv, val, ENET_MIBCTL_REG);
-}
-
-static const struct net_device_ops bcm_enet_ops = {
-	.ndo_open		= bcm_enet_open,
-	.ndo_stop		= bcm_enet_stop,
-	.ndo_start_xmit		= bcm_enet_start_xmit,
-	.ndo_set_mac_address	= bcm_enet_set_mac_address,
-	.ndo_set_multicast_list = bcm_enet_set_multicast_list,
-	.ndo_do_ioctl		= bcm_enet_ioctl,
-	.ndo_change_mtu		= bcm_enet_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller = bcm_enet_netpoll,
-#endif
-};
-
-/*
- * allocate netdevice, request register memory and register device.
- */
-static int __devinit bcm_enet_probe(struct platform_device *pdev)
-{
-	struct bcm_enet_priv *priv;
-	struct net_device *dev;
-	struct bcm63xx_enet_platform_data *pd;
-	struct resource *res_mem, *res_irq, *res_irq_rx, *res_irq_tx;
-	struct mii_bus *bus;
-	const char *clk_name;
-	unsigned int iomem_size;
-	int i, ret;
-
-	/* stop if shared driver failed, assume driver->probe will be
-	 * called in the same order we register devices (correct ?) */
-	if (!bcm_enet_shared_base)
-		return -ENODEV;
-
-	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	res_irq_rx = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
-	res_irq_tx = platform_get_resource(pdev, IORESOURCE_IRQ, 2);
-	if (!res_mem || !res_irq || !res_irq_rx || !res_irq_tx)
-		return -ENODEV;
-
-	ret = 0;
-	dev = alloc_etherdev(sizeof(*priv));
-	if (!dev)
-		return -ENOMEM;
-	priv = netdev_priv(dev);
-
-	ret = compute_hw_mtu(priv, dev->mtu);
-	if (ret)
-		goto out;
-
-	iomem_size = resource_size(res_mem);
-	if (!request_mem_region(res_mem->start, iomem_size, "bcm63xx_enet")) {
-		ret = -EBUSY;
-		goto out;
-	}
-
-	priv->base = ioremap(res_mem->start, iomem_size);
-	if (priv->base == NULL) {
-		ret = -ENOMEM;
-		goto out_release_mem;
-	}
-	dev->irq = priv->irq = res_irq->start;
-	priv->irq_rx = res_irq_rx->start;
-	priv->irq_tx = res_irq_tx->start;
-	priv->mac_id = pdev->id;
-
-	/* get rx & tx dma channel id for this mac */
-	if (priv->mac_id == 0) {
-		priv->rx_chan = 0;
-		priv->tx_chan = 1;
-		clk_name = "enet0";
-	} else {
-		priv->rx_chan = 2;
-		priv->tx_chan = 3;
-		clk_name = "enet1";
-	}
-
-	priv->mac_clk = clk_get(&pdev->dev, clk_name);
-	if (IS_ERR(priv->mac_clk)) {
-		ret = PTR_ERR(priv->mac_clk);
-		goto out_unmap;
-	}
-	clk_enable(priv->mac_clk);
-
-	/* initialize default and fetch platform data */
-	priv->rx_ring_size = BCMENET_DEF_RX_DESC;
-	priv->tx_ring_size = BCMENET_DEF_TX_DESC;
-
-	pd = pdev->dev.platform_data;
-	if (pd) {
-		memcpy(dev->dev_addr, pd->mac_addr, ETH_ALEN);
-		priv->has_phy = pd->has_phy;
-		priv->phy_id = pd->phy_id;
-		priv->has_phy_interrupt = pd->has_phy_interrupt;
-		priv->phy_interrupt = pd->phy_interrupt;
-		priv->use_external_mii = !pd->use_internal_phy;
-		priv->pause_auto = pd->pause_auto;
-		priv->pause_rx = pd->pause_rx;
-		priv->pause_tx = pd->pause_tx;
-		priv->force_duplex_full = pd->force_duplex_full;
-		priv->force_speed_100 = pd->force_speed_100;
-	}
-
-	if (priv->mac_id == 0 && priv->has_phy && !priv->use_external_mii) {
-		/* using internal PHY, enable clock */
-		priv->phy_clk = clk_get(&pdev->dev, "ephy");
-		if (IS_ERR(priv->phy_clk)) {
-			ret = PTR_ERR(priv->phy_clk);
-			priv->phy_clk = NULL;
-			goto out_put_clk_mac;
-		}
-		clk_enable(priv->phy_clk);
-	}
-
-	/* do minimal hardware init to be able to probe mii bus */
-	bcm_enet_hw_preinit(priv);
-
-	/* MII bus registration */
-	if (priv->has_phy) {
-
-		priv->mii_bus = mdiobus_alloc();
-		if (!priv->mii_bus) {
-			ret = -ENOMEM;
-			goto out_uninit_hw;
-		}
-
-		bus = priv->mii_bus;
-		bus->name = "bcm63xx_enet MII bus";
-		bus->parent = &pdev->dev;
-		bus->priv = priv;
-		bus->read = bcm_enet_mdio_read_phylib;
-		bus->write = bcm_enet_mdio_write_phylib;
-		sprintf(bus->id, "%d", priv->mac_id);
-
-		/* only probe bus where we think the PHY is, because
-		 * the mdio read operation return 0 instead of 0xffff
-		 * if a slave is not present on hw */
-		bus->phy_mask = ~(1 << priv->phy_id);
-
-		bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
-		if (!bus->irq) {
-			ret = -ENOMEM;
-			goto out_free_mdio;
-		}
-
-		if (priv->has_phy_interrupt)
-			bus->irq[priv->phy_id] = priv->phy_interrupt;
-		else
-			bus->irq[priv->phy_id] = PHY_POLL;
-
-		ret = mdiobus_register(bus);
-		if (ret) {
-			dev_err(&pdev->dev, "unable to register mdio bus\n");
-			goto out_free_mdio;
-		}
-	} else {
-
-		/* run platform code to initialize PHY device */
-		if (pd->mii_config &&
-		    pd->mii_config(dev, 1, bcm_enet_mdio_read_mii,
-				   bcm_enet_mdio_write_mii)) {
-			dev_err(&pdev->dev, "unable to configure mdio bus\n");
-			goto out_uninit_hw;
-		}
-	}
-
-	spin_lock_init(&priv->rx_lock);
-
-	/* init rx timeout (used for oom) */
-	init_timer(&priv->rx_timeout);
-	priv->rx_timeout.function = bcm_enet_refill_rx_timer;
-	priv->rx_timeout.data = (unsigned long)dev;
-
-	/* init the mib update lock&work */
-	mutex_init(&priv->mib_update_lock);
-	INIT_WORK(&priv->mib_update_task, bcm_enet_update_mib_counters_defer);
-
-	/* zero mib counters */
-	for (i = 0; i < ENET_MIB_REG_COUNT; i++)
-		enet_writel(priv, 0, ENET_MIB_REG(i));
-
-	/* register netdevice */
-	dev->netdev_ops = &bcm_enet_ops;
-	netif_napi_add(dev, &priv->napi, bcm_enet_poll, 16);
-
-	SET_ETHTOOL_OPS(dev, &bcm_enet_ethtool_ops);
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-	ret = register_netdev(dev);
-	if (ret)
-		goto out_unregister_mdio;
-
-	netif_carrier_off(dev);
-	platform_set_drvdata(pdev, dev);
-	priv->pdev = pdev;
-	priv->net_dev = dev;
-
-	return 0;
-
-out_unregister_mdio:
-	if (priv->mii_bus) {
-		mdiobus_unregister(priv->mii_bus);
-		kfree(priv->mii_bus->irq);
-	}
-
-out_free_mdio:
-	if (priv->mii_bus)
-		mdiobus_free(priv->mii_bus);
-
-out_uninit_hw:
-	/* turn off mdc clock */
-	enet_writel(priv, 0, ENET_MIISC_REG);
-	if (priv->phy_clk) {
-		clk_disable(priv->phy_clk);
-		clk_put(priv->phy_clk);
-	}
-
-out_put_clk_mac:
-	clk_disable(priv->mac_clk);
-	clk_put(priv->mac_clk);
-
-out_unmap:
-	iounmap(priv->base);
-
-out_release_mem:
-	release_mem_region(res_mem->start, iomem_size);
-out:
-	free_netdev(dev);
-	return ret;
-}
-
-
-/*
- * exit func, stops hardware and unregisters netdevice
- */
-static int __devexit bcm_enet_remove(struct platform_device *pdev)
-{
-	struct bcm_enet_priv *priv;
-	struct net_device *dev;
-	struct resource *res;
-
-	/* stop netdevice */
-	dev = platform_get_drvdata(pdev);
-	priv = netdev_priv(dev);
-	unregister_netdev(dev);
-
-	/* turn off mdc clock */
-	enet_writel(priv, 0, ENET_MIISC_REG);
-
-	if (priv->has_phy) {
-		mdiobus_unregister(priv->mii_bus);
-		kfree(priv->mii_bus->irq);
-		mdiobus_free(priv->mii_bus);
-	} else {
-		struct bcm63xx_enet_platform_data *pd;
-
-		pd = pdev->dev.platform_data;
-		if (pd && pd->mii_config)
-			pd->mii_config(dev, 0, bcm_enet_mdio_read_mii,
-				       bcm_enet_mdio_write_mii);
-	}
-
-	/* release device resources */
-	iounmap(priv->base);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-
-	/* disable hw block clocks */
-	if (priv->phy_clk) {
-		clk_disable(priv->phy_clk);
-		clk_put(priv->phy_clk);
-	}
-	clk_disable(priv->mac_clk);
-	clk_put(priv->mac_clk);
-
-	platform_set_drvdata(pdev, NULL);
-	free_netdev(dev);
-	return 0;
-}
-
-struct platform_driver bcm63xx_enet_driver = {
-	.probe	= bcm_enet_probe,
-	.remove	= __devexit_p(bcm_enet_remove),
-	.driver	= {
-		.name	= "bcm63xx_enet",
-		.owner  = THIS_MODULE,
-	},
-};
-
-/*
- * reserve & remap memory space shared between all macs
- */
-static int __devinit bcm_enet_shared_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	unsigned int iomem_size;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
-
-	iomem_size = resource_size(res);
-	if (!request_mem_region(res->start, iomem_size, "bcm63xx_enet_dma"))
-		return -EBUSY;
-
-	bcm_enet_shared_base = ioremap(res->start, iomem_size);
-	if (!bcm_enet_shared_base) {
-		release_mem_region(res->start, iomem_size);
-		return -ENOMEM;
-	}
-	return 0;
-}
-
-static int __devexit bcm_enet_shared_remove(struct platform_device *pdev)
-{
-	struct resource *res;
-
-	iounmap(bcm_enet_shared_base);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-	return 0;
-}
-
-/*
- * this "shared" driver is needed because both macs share a single
- * address space
- */
-struct platform_driver bcm63xx_enet_shared_driver = {
-	.probe	= bcm_enet_shared_probe,
-	.remove	= __devexit_p(bcm_enet_shared_remove),
-	.driver	= {
-		.name	= "bcm63xx_enet_shared",
-		.owner  = THIS_MODULE,
-	},
-};
-
-/*
- * entry point
- */
-static int __init bcm_enet_init(void)
-{
-	int ret;
-
-	ret = platform_driver_register(&bcm63xx_enet_shared_driver);
-	if (ret)
-		return ret;
-
-	ret = platform_driver_register(&bcm63xx_enet_driver);
-	if (ret)
-		platform_driver_unregister(&bcm63xx_enet_shared_driver);
-
-	return ret;
-}
-
-static void __exit bcm_enet_exit(void)
-{
-	platform_driver_unregister(&bcm63xx_enet_driver);
-	platform_driver_unregister(&bcm63xx_enet_shared_driver);
-}
-
-
-module_init(bcm_enet_init);
-module_exit(bcm_enet_exit);
-
-MODULE_DESCRIPTION("BCM63xx internal ethernet mac driver");
-MODULE_AUTHOR("Maxime Bizon <mbizon@freebox.fr>");
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/bcm63xx_enet.h linux-libre-3.2-gnu/drivers/net/bcm63xx_enet.h
--- linux-libre-3.1-gnu/drivers/net/bcm63xx_enet.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bcm63xx_enet.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,302 +0,0 @@
-#ifndef BCM63XX_ENET_H_
-#define BCM63XX_ENET_H_
-
-#include <linux/types.h>
-#include <linux/mii.h>
-#include <linux/mutex.h>
-#include <linux/phy.h>
-#include <linux/platform_device.h>
-
-#include <bcm63xx_regs.h>
-#include <bcm63xx_irq.h>
-#include <bcm63xx_io.h>
-
-/* default number of descriptor */
-#define BCMENET_DEF_RX_DESC	64
-#define BCMENET_DEF_TX_DESC	32
-
-/* maximum burst len for dma (4 bytes unit) */
-#define BCMENET_DMA_MAXBURST	16
-
-/* tx transmit threshold (4 bytes unit), fifo is 256 bytes, the value
- * must be low enough so that a DMA transfer of above burst length can
- * not overflow the fifo  */
-#define BCMENET_TX_FIFO_TRESH	32
-
-/*
- * hardware maximum rx/tx packet size including FCS, max mtu is
- * actually 2047, but if we set max rx size register to 2047 we won't
- * get overflow information if packet size is 2048 or above
- */
-#define BCMENET_MAX_MTU		2046
-
-/*
- * rx/tx dma descriptor
- */
-struct bcm_enet_desc {
-	u32 len_stat;
-	u32 address;
-};
-
-#define DMADESC_LENGTH_SHIFT	16
-#define DMADESC_LENGTH_MASK	(0xfff << DMADESC_LENGTH_SHIFT)
-#define DMADESC_OWNER_MASK	(1 << 15)
-#define DMADESC_EOP_MASK	(1 << 14)
-#define DMADESC_SOP_MASK	(1 << 13)
-#define DMADESC_ESOP_MASK	(DMADESC_EOP_MASK | DMADESC_SOP_MASK)
-#define DMADESC_WRAP_MASK	(1 << 12)
-
-#define DMADESC_UNDER_MASK	(1 << 9)
-#define DMADESC_APPEND_CRC	(1 << 8)
-#define DMADESC_OVSIZE_MASK	(1 << 4)
-#define DMADESC_RXER_MASK	(1 << 2)
-#define DMADESC_CRC_MASK	(1 << 1)
-#define DMADESC_OV_MASK		(1 << 0)
-#define DMADESC_ERR_MASK	(DMADESC_UNDER_MASK | \
-				DMADESC_OVSIZE_MASK | \
-				DMADESC_RXER_MASK | \
-				DMADESC_CRC_MASK | \
-				DMADESC_OV_MASK)
-
-
-/*
- * MIB Counters register definitions
-*/
-#define ETH_MIB_TX_GD_OCTETS			0
-#define ETH_MIB_TX_GD_PKTS			1
-#define ETH_MIB_TX_ALL_OCTETS			2
-#define ETH_MIB_TX_ALL_PKTS			3
-#define ETH_MIB_TX_BRDCAST			4
-#define ETH_MIB_TX_MULT				5
-#define ETH_MIB_TX_64				6
-#define ETH_MIB_TX_65_127			7
-#define ETH_MIB_TX_128_255			8
-#define ETH_MIB_TX_256_511			9
-#define ETH_MIB_TX_512_1023			10
-#define ETH_MIB_TX_1024_MAX			11
-#define ETH_MIB_TX_JAB				12
-#define ETH_MIB_TX_OVR				13
-#define ETH_MIB_TX_FRAG				14
-#define ETH_MIB_TX_UNDERRUN			15
-#define ETH_MIB_TX_COL				16
-#define ETH_MIB_TX_1_COL			17
-#define ETH_MIB_TX_M_COL			18
-#define ETH_MIB_TX_EX_COL			19
-#define ETH_MIB_TX_LATE				20
-#define ETH_MIB_TX_DEF				21
-#define ETH_MIB_TX_CRS				22
-#define ETH_MIB_TX_PAUSE			23
-
-#define ETH_MIB_RX_GD_OCTETS			32
-#define ETH_MIB_RX_GD_PKTS			33
-#define ETH_MIB_RX_ALL_OCTETS			34
-#define ETH_MIB_RX_ALL_PKTS			35
-#define ETH_MIB_RX_BRDCAST			36
-#define ETH_MIB_RX_MULT				37
-#define ETH_MIB_RX_64				38
-#define ETH_MIB_RX_65_127			39
-#define ETH_MIB_RX_128_255			40
-#define ETH_MIB_RX_256_511			41
-#define ETH_MIB_RX_512_1023			42
-#define ETH_MIB_RX_1024_MAX			43
-#define ETH_MIB_RX_JAB				44
-#define ETH_MIB_RX_OVR				45
-#define ETH_MIB_RX_FRAG				46
-#define ETH_MIB_RX_DROP				47
-#define ETH_MIB_RX_CRC_ALIGN			48
-#define ETH_MIB_RX_UND				49
-#define ETH_MIB_RX_CRC				50
-#define ETH_MIB_RX_ALIGN			51
-#define ETH_MIB_RX_SYM				52
-#define ETH_MIB_RX_PAUSE			53
-#define ETH_MIB_RX_CNTRL			54
-
-
-struct bcm_enet_mib_counters {
-	u64 tx_gd_octets;
-	u32 tx_gd_pkts;
-	u32 tx_all_octets;
-	u32 tx_all_pkts;
-	u32 tx_brdcast;
-	u32 tx_mult;
-	u32 tx_64;
-	u32 tx_65_127;
-	u32 tx_128_255;
-	u32 tx_256_511;
-	u32 tx_512_1023;
-	u32 tx_1024_max;
-	u32 tx_jab;
-	u32 tx_ovr;
-	u32 tx_frag;
-	u32 tx_underrun;
-	u32 tx_col;
-	u32 tx_1_col;
-	u32 tx_m_col;
-	u32 tx_ex_col;
-	u32 tx_late;
-	u32 tx_def;
-	u32 tx_crs;
-	u32 tx_pause;
-	u64 rx_gd_octets;
-	u32 rx_gd_pkts;
-	u32 rx_all_octets;
-	u32 rx_all_pkts;
-	u32 rx_brdcast;
-	u32 rx_mult;
-	u32 rx_64;
-	u32 rx_65_127;
-	u32 rx_128_255;
-	u32 rx_256_511;
-	u32 rx_512_1023;
-	u32 rx_1024_max;
-	u32 rx_jab;
-	u32 rx_ovr;
-	u32 rx_frag;
-	u32 rx_drop;
-	u32 rx_crc_align;
-	u32 rx_und;
-	u32 rx_crc;
-	u32 rx_align;
-	u32 rx_sym;
-	u32 rx_pause;
-	u32 rx_cntrl;
-};
-
-
-struct bcm_enet_priv {
-
-	/* mac id (from platform device id) */
-	int mac_id;
-
-	/* base remapped address of device */
-	void __iomem *base;
-
-	/* mac irq, rx_dma irq, tx_dma irq */
-	int irq;
-	int irq_rx;
-	int irq_tx;
-
-	/* hw view of rx & tx dma ring */
-	dma_addr_t rx_desc_dma;
-	dma_addr_t tx_desc_dma;
-
-	/* allocated size (in bytes) for rx & tx dma ring */
-	unsigned int rx_desc_alloc_size;
-	unsigned int tx_desc_alloc_size;
-
-
-	struct napi_struct napi;
-
-	/* dma channel id for rx */
-	int rx_chan;
-
-	/* number of dma desc in rx ring */
-	int rx_ring_size;
-
-	/* cpu view of rx dma ring */
-	struct bcm_enet_desc *rx_desc_cpu;
-
-	/* current number of armed descriptor given to hardware for rx */
-	int rx_desc_count;
-
-	/* next rx descriptor to fetch from hardware */
-	int rx_curr_desc;
-
-	/* next dirty rx descriptor to refill */
-	int rx_dirty_desc;
-
-	/* size of allocated rx skbs */
-	unsigned int rx_skb_size;
-
-	/* list of skb given to hw for rx */
-	struct sk_buff **rx_skb;
-
-	/* used when rx skb allocation failed, so we defer rx queue
-	 * refill */
-	struct timer_list rx_timeout;
-
-	/* lock rx_timeout against rx normal operation */
-	spinlock_t rx_lock;
-
-
-	/* dma channel id for tx */
-	int tx_chan;
-
-	/* number of dma desc in tx ring */
-	int tx_ring_size;
-
-	/* cpu view of rx dma ring */
-	struct bcm_enet_desc *tx_desc_cpu;
-
-	/* number of available descriptor for tx */
-	int tx_desc_count;
-
-	/* next tx descriptor avaiable */
-	int tx_curr_desc;
-
-	/* next dirty tx descriptor to reclaim */
-	int tx_dirty_desc;
-
-	/* list of skb given to hw for tx */
-	struct sk_buff **tx_skb;
-
-	/* lock used by tx reclaim and xmit */
-	spinlock_t tx_lock;
-
-
-	/* set if internal phy is ignored and external mii interface
-	 * is selected */
-	int use_external_mii;
-
-	/* set if a phy is connected, phy address must be known,
-	 * probing is not possible */
-	int has_phy;
-	int phy_id;
-
-	/* set if connected phy has an associated irq */
-	int has_phy_interrupt;
-	int phy_interrupt;
-
-	/* used when a phy is connected (phylib used) */
-	struct mii_bus *mii_bus;
-	struct phy_device *phydev;
-	int old_link;
-	int old_duplex;
-	int old_pause;
-
-	/* used when no phy is connected */
-	int force_speed_100;
-	int force_duplex_full;
-
-	/* pause parameters */
-	int pause_auto;
-	int pause_rx;
-	int pause_tx;
-
-	/* stats */
-	struct bcm_enet_mib_counters mib;
-
-	/* after mib interrupt, mib registers update is done in this
-	 * work queue */
-	struct work_struct mib_update_task;
-
-	/* lock mib update between userspace request and workqueue */
-	struct mutex mib_update_lock;
-
-	/* mac clock */
-	struct clk *mac_clk;
-
-	/* phy clock if internal phy is used */
-	struct clk *phy_clk;
-
-	/* network device reference */
-	struct net_device *net_dev;
-
-	/* platform device reference */
-	struct platform_device *pdev;
-
-	/* maximum hardware transmit/receive size */
-	unsigned int hw_mtu;
-};
-
-#endif /* ! BCM63XX_ENET_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/benet/be_cmds.c linux-libre-3.2-gnu/drivers/net/benet/be_cmds.c
--- linux-libre-3.1-gnu/drivers/net/benet/be_cmds.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/benet/be_cmds.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2429 +0,0 @@
-/*
- * Copyright (C) 2005 - 2011 Emulex
- * 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@emulex.com
- *
- * 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;
-
-	wmb();
-	iowrite32(val, adapter->db + DB_MCCQ_OFFSET);
-}
-
-/* To check if valid bit is set, check the entire word as we don't know
- * the endianness of the data (old entry is host endian while a new entry is
- * little endian) */
-static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl)
-{
-	if (compl->flags != 0) {
-		compl->flags = le32_to_cpu(compl->flags);
-		BUG_ON((compl->flags & CQE_FLAGS_VALID_MASK) == 0);
-		return true;
-	} else {
-		return false;
-	}
-}
-
-/* Need to reset the entire word that houses the valid bit */
-static inline void be_mcc_compl_use(struct be_mcc_compl *compl)
-{
-	compl->flags = 0;
-}
-
-static int be_mcc_compl_process(struct be_adapter *adapter,
-	struct be_mcc_compl *compl)
-{
-	u16 compl_status, extd_status;
-
-	/* Just swap the status to host endian; mcc tag is opaquely copied
-	 * from mcc_wrb */
-	be_dws_le_to_cpu(compl, 4);
-
-	compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
-				CQE_STATUS_COMPL_MASK;
-
-	if (((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) ||
-		(compl->tag0 == OPCODE_COMMON_WRITE_OBJECT)) &&
-		(compl->tag1 == CMD_SUBSYSTEM_COMMON)) {
-		adapter->flash_status = compl_status;
-		complete(&adapter->flash_compl);
-	}
-
-	if (compl_status == MCC_STATUS_SUCCESS) {
-		if (((compl->tag0 == OPCODE_ETH_GET_STATISTICS) ||
-			 (compl->tag0 == OPCODE_ETH_GET_PPORT_STATS)) &&
-			(compl->tag1 == CMD_SUBSYSTEM_ETH)) {
-			if (adapter->generation == BE_GEN3) {
-				if (lancer_chip(adapter)) {
-					struct lancer_cmd_resp_pport_stats
-						*resp = adapter->stats_cmd.va;
-					be_dws_le_to_cpu(&resp->pport_stats,
-						sizeof(resp->pport_stats));
-				} else {
-					struct be_cmd_resp_get_stats_v1 *resp =
-							adapter->stats_cmd.va;
-
-				be_dws_le_to_cpu(&resp->hw_stats,
-							sizeof(resp->hw_stats));
-				}
-			} else {
-				struct be_cmd_resp_get_stats_v0 *resp =
-							adapter->stats_cmd.va;
-
-				be_dws_le_to_cpu(&resp->hw_stats,
-							sizeof(resp->hw_stats));
-			}
-			be_parse_stats(adapter);
-			netdev_stats_update(adapter);
-			adapter->stats_cmd_sent = false;
-		}
-	} else {
-		if (compl_status == MCC_STATUS_NOT_SUPPORTED ||
-			compl_status == MCC_STATUS_ILLEGAL_REQUEST)
-			goto done;
-
-		if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) {
-			dev_warn(&adapter->pdev->dev, "This domain(VM) is not "
-				"permitted to execute this cmd (opcode %d)\n",
-				compl->tag0);
-		} else {
-			extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
-					CQE_STATUS_EXTD_MASK;
-			dev_err(&adapter->pdev->dev, "Cmd (opcode %d) failed:"
-				"status %d, extd-status %d\n",
-				compl->tag0, compl_status, extd_status);
-		}
-	}
-done:
-	return compl_status;
-}
-
-/* Link state evt is a string of bytes; no need for endian swapping */
-static void be_async_link_state_process(struct be_adapter *adapter,
-		struct be_async_event_link_state *evt)
-{
-	be_link_status_update(adapter,
-		evt->port_link_status == ASYNC_EVENT_LINK_UP);
-}
-
-/* Grp5 CoS Priority evt */
-static void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
-		struct be_async_event_grp5_cos_priority *evt)
-{
-	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;
-	}
-}
-
-/* Grp5 QOS Speed evt */
-static void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
-		struct be_async_event_grp5_qos_link_speed *evt)
-{
-	if (evt->physical_port == adapter->port_num) {
-		/* qos_link_speed is in units of 10 Mbps */
-		adapter->link_speed = evt->qos_link_speed * 10;
-	}
-}
-
-/*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)
-{
-	u8 event_type = 0;
-
-	event_type = (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) &
-		ASYNC_TRAILER_EVENT_TYPE_MASK;
-
-	switch (event_type) {
-	case ASYNC_EVENT_COS_PRIORITY:
-		be_async_grp5_cos_priority_process(adapter,
-		(struct be_async_event_grp5_cos_priority *)evt);
-	break;
-	case ASYNC_EVENT_QOS_SPEED:
-		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;
-	}
-}
-
-static inline bool is_link_state_evt(u32 trailer)
-{
-	return ((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
-		ASYNC_TRAILER_EVENT_CODE_MASK) ==
-				ASYNC_EVENT_CODE_LINK_STATE;
-}
-
-static inline bool is_grp5_evt(u32 trailer)
-{
-	return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
-		ASYNC_TRAILER_EVENT_CODE_MASK) ==
-				ASYNC_EVENT_CODE_GRP_5);
-}
-
-static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
-{
-	struct be_queue_info *mcc_cq = &adapter->mcc_obj.cq;
-	struct be_mcc_compl *compl = queue_tail_node(mcc_cq);
-
-	if (be_mcc_compl_is_new(compl)) {
-		queue_tail_inc(mcc_cq);
-		return compl;
-	}
-	return NULL;
-}
-
-void be_async_mcc_enable(struct be_adapter *adapter)
-{
-	spin_lock_bh(&adapter->mcc_cq_lock);
-
-	be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, 0);
-	adapter->mcc_obj.rearm_cq = true;
-
-	spin_unlock_bh(&adapter->mcc_cq_lock);
-}
-
-void be_async_mcc_disable(struct be_adapter *adapter)
-{
-	adapter->mcc_obj.rearm_cq = false;
-}
-
-int be_process_mcc(struct be_adapter *adapter, int *status)
-{
-	struct be_mcc_compl *compl;
-	int num = 0;
-	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
-
-	spin_lock_bh(&adapter->mcc_cq_lock);
-	while ((compl = be_mcc_compl_get(adapter))) {
-		if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
-			/* Interpret flags as an async trailer */
-			if (is_link_state_evt(compl->flags))
-				be_async_link_state_process(adapter,
-				(struct be_async_event_link_state *) compl);
-			else if (is_grp5_evt(compl->flags))
-				be_async_grp5_evt_process(adapter,
-				compl->flags, compl);
-		} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
-				*status = be_mcc_compl_process(adapter, compl);
-				atomic_dec(&mcc_obj->q.used);
-		}
-		be_mcc_compl_use(compl);
-		num++;
-	}
-
-	spin_unlock_bh(&adapter->mcc_cq_lock);
-	return num;
-}
-
-/* Wait till no more pending mcc requests are present */
-static int be_mcc_wait_compl(struct be_adapter *adapter)
-{
-#define mcc_timeout		120000 /* 12s timeout */
-	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)
-			be_cq_notify(adapter, mcc_obj->cq.id,
-				mcc_obj->rearm_cq, num);
-
-		if (atomic_read(&mcc_obj->q.used) == 0)
-			break;
-		udelay(100);
-	}
-	if (i == mcc_timeout) {
-		dev_err(&adapter->pdev->dev, "mccq poll timed out\n");
-		return -1;
-	}
-	return status;
-}
-
-/* Notify MCC requests and wait for completion */
-static int be_mcc_notify_wait(struct be_adapter *adapter)
-{
-	be_mcc_notify(adapter);
-	return be_mcc_wait_compl(adapter);
-}
-
-static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
-{
-	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) {
-			dev_err(&adapter->pdev->dev,
-				"pci slot disconnected\n");
-			return -1;
-		}
-
-		ready &= MPU_MAILBOX_DB_RDY_MASK;
-		if (ready)
-			break;
-
-		if (msecs > 4000) {
-			dev_err(&adapter->pdev->dev, "mbox poll timed out\n");
-			if (!lancer_chip(adapter))
-				be_detect_dump_ue(adapter);
-			return -1;
-		}
-
-		msleep(1);
-		msecs++;
-	} while (true);
-
-	return 0;
-}
-
-/*
- * Insert the mailbox address into the doorbell in two steps
- * Polls on the mbox doorbell till a command completion (or a timeout) occurs
- */
-static int be_mbox_notify_wait(struct be_adapter *adapter)
-{
-	int status;
-	u32 val = 0;
-	void __iomem *db = adapter->db + MPU_MAILBOX_DB_OFFSET;
-	struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
-	struct be_mcc_mailbox *mbox = mbox_mem->va;
-	struct be_mcc_compl *compl = &mbox->compl;
-
-	/* wait for ready to be set */
-	status = be_mbox_db_ready_wait(adapter, db);
-	if (status != 0)
-		return status;
-
-	val |= MPU_MAILBOX_DB_HI_MASK;
-	/* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */
-	val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
-	iowrite32(val, db);
-
-	/* wait for ready to be set */
-	status = be_mbox_db_ready_wait(adapter, db);
-	if (status != 0)
-		return status;
-
-	val = 0;
-	/* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */
-	val |= (u32)(mbox_mem->dma >> 4) << 2;
-	iowrite32(val, db);
-
-	status = be_mbox_db_ready_wait(adapter, db);
-	if (status != 0)
-		return status;
-
-	/* A cq entry has been made now */
-	if (be_mcc_compl_is_new(compl)) {
-		status = be_mcc_compl_process(adapter, &mbox->compl);
-		be_mcc_compl_use(compl);
-		if (status)
-			return status;
-	} else {
-		dev_err(&adapter->pdev->dev, "invalid mailbox completion\n");
-		return -1;
-	}
-	return 0;
-}
-
-static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage)
-{
-	u32 sem;
-
-	if (lancer_chip(adapter))
-		sem  = ioread32(adapter->db + MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET);
-	else
-		sem  = ioread32(adapter->csr + MPU_EP_SEMAPHORE_OFFSET);
-
-	*stage = sem & EP_SEMAPHORE_POST_STAGE_MASK;
-	if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) & EP_SEMAPHORE_POST_ERR_MASK)
-		return -1;
-	else
-		return 0;
-}
-
-int be_cmd_POST(struct be_adapter *adapter)
-{
-	u16 stage;
-	int status, timeout = 0;
-	struct device *dev = &adapter->pdev->dev;
-
-	do {
-		status = be_POST_stage_get(adapter, &stage);
-		if (status) {
-			dev_err(dev, "POST error; stage=0x%x\n", stage);
-			return -1;
-		} else if (stage != POST_STAGE_ARMFW_RDY) {
-			if (msleep_interruptible(2000)) {
-				dev_err(dev, "Waiting for POST aborted\n");
-				return -EINTR;
-			}
-			timeout += 2;
-		} else {
-			return 0;
-		}
-	} while (timeout < 40);
-
-	dev_err(dev, "POST timeout; stage=0x%x\n", stage);
-	return -1;
-}
-
-static inline void *embedded_payload(struct be_mcc_wrb *wrb)
-{
-	return wrb->payload.embedded_payload;
-}
-
-static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb)
-{
-	return &wrb->payload.sgl[0];
-}
-
-/* Don't touch the hdr after it's prepared */
-static void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
-				bool embedded, u8 sge_cnt, u32 opcode)
-{
-	if (embedded)
-		wrb->embedded |= MCC_WRB_EMBEDDED_MASK;
-	else
-		wrb->embedded |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) <<
-				MCC_WRB_SGE_CNT_SHIFT;
-	wrb->payload_length = payload_len;
-	wrb->tag0 = opcode;
-	be_dws_cpu_to_le(wrb, 8);
-}
-
-/* Don't touch the hdr after it's prepared */
-static void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
-				u8 subsystem, u8 opcode, int cmd_len)
-{
-	req_hdr->opcode = opcode;
-	req_hdr->subsystem = subsystem;
-	req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
-	req_hdr->version = 0;
-}
-
-static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages,
-			struct be_dma_mem *mem)
-{
-	int i, buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages);
-	u64 dma = (u64)mem->dma;
-
-	for (i = 0; i < buf_pages; i++) {
-		pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF);
-		pages[i].hi = cpu_to_le32(upper_32_bits(dma));
-		dma += PAGE_SIZE_4K;
-	}
-}
-
-/* Converts interrupt delay in microseconds to multiplier value */
-static u32 eq_delay_to_mult(u32 usec_delay)
-{
-#define MAX_INTR_RATE			651042
-	const u32 round = 10;
-	u32 multiplier;
-
-	if (usec_delay == 0)
-		multiplier = 0;
-	else {
-		u32 interrupt_rate = 1000000 / usec_delay;
-		/* Max delay, corresponding to the lowest interrupt rate */
-		if (interrupt_rate == 0)
-			multiplier = 1023;
-		else {
-			multiplier = (MAX_INTR_RATE - interrupt_rate) * round;
-			multiplier /= interrupt_rate;
-			/* Round the multiplier to the closest value.*/
-			multiplier = (multiplier + round/2) / round;
-			multiplier = min(multiplier, (u32)1023);
-		}
-	}
-	return multiplier;
-}
-
-static inline struct be_mcc_wrb *wrb_from_mbox(struct be_adapter *adapter)
-{
-	struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
-	struct be_mcc_wrb *wrb
-		= &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
-	memset(wrb, 0, sizeof(*wrb));
-	return wrb;
-}
-
-static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter)
-{
-	struct be_queue_info *mccq = &adapter->mcc_obj.q;
-	struct be_mcc_wrb *wrb;
-
-	if (atomic_read(&mccq->used) >= mccq->len) {
-		dev_err(&adapter->pdev->dev, "Out of MCCQ wrbs\n");
-		return NULL;
-	}
-
-	wrb = queue_head_node(mccq);
-	queue_head_inc(mccq);
-	atomic_inc(&mccq->used);
-	memset(wrb, 0, sizeof(*wrb));
-	return wrb;
-}
-
-/* Tell fw we're about to start firing cmds by writing a
- * special pattern across the wrb hdr; uses mbox
- */
-int be_cmd_fw_init(struct be_adapter *adapter)
-{
-	u8 *wrb;
-	int status;
-
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
-
-	wrb = (u8 *)wrb_from_mbox(adapter);
-	*wrb++ = 0xFF;
-	*wrb++ = 0x12;
-	*wrb++ = 0x34;
-	*wrb++ = 0xFF;
-	*wrb++ = 0xFF;
-	*wrb++ = 0x56;
-	*wrb++ = 0x78;
-	*wrb = 0xFF;
-
-	status = be_mbox_notify_wait(adapter);
-
-	mutex_unlock(&adapter->mbox_lock);
-	return status;
-}
-
-/* Tell fw we're done with firing cmds by writing a
- * special pattern across the wrb hdr; uses mbox
- */
-int be_cmd_fw_clean(struct be_adapter *adapter)
-{
-	u8 *wrb;
-	int status;
-
-	if (adapter->eeh_err)
-		return -EIO;
-
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
-
-	wrb = (u8 *)wrb_from_mbox(adapter);
-	*wrb++ = 0xFF;
-	*wrb++ = 0xAA;
-	*wrb++ = 0xBB;
-	*wrb++ = 0xFF;
-	*wrb++ = 0xFF;
-	*wrb++ = 0xCC;
-	*wrb++ = 0xDD;
-	*wrb = 0xFF;
-
-	status = be_mbox_notify_wait(adapter);
-
-	mutex_unlock(&adapter->mbox_lock);
-	return status;
-}
-int be_cmd_eq_create(struct be_adapter *adapter,
-		struct be_queue_info *eq, int eq_delay)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_eq_create *req;
-	struct be_dma_mem *q_mem = &eq->dma_mem;
-	int status;
-
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
-
-	wrb = wrb_from_mbox(adapter);
-	req = embedded_payload(wrb);
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_COMMON_EQ_CREATE);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_EQ_CREATE, sizeof(*req));
-
-	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
-
-	AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1);
-	/* 4byte eqe*/
-	AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0);
-	AMAP_SET_BITS(struct amap_eq_context, count, req->context,
-			__ilog2_u32(eq->len/256));
-	AMAP_SET_BITS(struct amap_eq_context, delaymult, req->context,
-			eq_delay_to_mult(eq_delay));
-	be_dws_cpu_to_le(req->context, sizeof(req->context));
-
-	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
-
-	status = be_mbox_notify_wait(adapter);
-	if (!status) {
-		struct be_cmd_resp_eq_create *resp = embedded_payload(wrb);
-		eq->id = le16_to_cpu(resp->eq_id);
-		eq->created = true;
-	}
-
-	mutex_unlock(&adapter->mbox_lock);
-	return status;
-}
-
-/* Uses mbox */
-int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
-			u8 type, bool permanent, u32 if_handle)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_mac_query *req;
-	int status;
-
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
-
-	wrb = wrb_from_mbox(adapter);
-	req = embedded_payload(wrb);
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
-			OPCODE_COMMON_NTWK_MAC_QUERY);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req));
-
-	req->type = type;
-	if (permanent) {
-		req->permanent = 1;
-	} else {
-		req->if_id = cpu_to_le16((u16) if_handle);
-		req->permanent = 0;
-	}
-
-	status = be_mbox_notify_wait(adapter);
-	if (!status) {
-		struct be_cmd_resp_mac_query *resp = embedded_payload(wrb);
-		memcpy(mac_addr, resp->mac.addr, ETH_ALEN);
-	}
-
-	mutex_unlock(&adapter->mbox_lock);
-	return status;
-}
-
-/* Uses synchronous MCCQ */
-int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
-		u32 if_id, u32 *pmac_id, u32 domain)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_pmac_add *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_NTWK_PMAC_ADD);
-
-	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);
-
-	status = be_mcc_notify_wait(adapter);
-	if (!status) {
-		struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb);
-		*pmac_id = le32_to_cpu(resp->pmac_id);
-	}
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-/* Uses synchronous MCCQ */
-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;
-	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_NTWK_PMAC_DEL);
-
-	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);
-
-	status = be_mcc_notify_wait(adapter);
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-/* Uses Mbox */
-int be_cmd_cq_create(struct be_adapter *adapter,
-		struct be_queue_info *cq, struct be_queue_info *eq,
-		bool sol_evts, bool no_delay, int coalesce_wm)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_cq_create *req;
-	struct be_dma_mem *q_mem = &cq->dma_mem;
-	void *ctxt;
-	int status;
-
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
-
-	wrb = wrb_from_mbox(adapter);
-	req = embedded_payload(wrb);
-	ctxt = &req->context;
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
-			OPCODE_COMMON_CQ_CREATE);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_CQ_CREATE, sizeof(*req));
-
-	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
-	if (lancer_chip(adapter)) {
-		req->hdr.version = 2;
-		req->page_size = 1; /* 1 for 4K */
-		AMAP_SET_BITS(struct amap_cq_context_lancer, nodelay, ctxt,
-								no_delay);
-		AMAP_SET_BITS(struct amap_cq_context_lancer, count, ctxt,
-						__ilog2_u32(cq->len/256));
-		AMAP_SET_BITS(struct amap_cq_context_lancer, valid, ctxt, 1);
-		AMAP_SET_BITS(struct amap_cq_context_lancer, eventable,
-								ctxt, 1);
-		AMAP_SET_BITS(struct amap_cq_context_lancer, eqid,
-								ctxt, eq->id);
-		AMAP_SET_BITS(struct amap_cq_context_lancer, armed, ctxt, 1);
-	} else {
-		AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt,
-								coalesce_wm);
-		AMAP_SET_BITS(struct amap_cq_context_be, nodelay,
-								ctxt, no_delay);
-		AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt,
-						__ilog2_u32(cq->len/256));
-		AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1);
-		AMAP_SET_BITS(struct amap_cq_context_be, solevent,
-								ctxt, sol_evts);
-		AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1);
-		AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id);
-		AMAP_SET_BITS(struct amap_cq_context_be, armed, ctxt, 1);
-	}
-
-	be_dws_cpu_to_le(ctxt, sizeof(req->context));
-
-	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
-
-	status = be_mbox_notify_wait(adapter);
-	if (!status) {
-		struct be_cmd_resp_cq_create *resp = embedded_payload(wrb);
-		cq->id = le16_to_cpu(resp->cq_id);
-		cq->created = true;
-	}
-
-	mutex_unlock(&adapter->mbox_lock);
-
-	return status;
-}
-
-static u32 be_encoded_q_len(int q_len)
-{
-	u32 len_encoded = fls(q_len); /* log2(len) + 1 */
-	if (len_encoded == 16)
-		len_encoded = 0;
-	return len_encoded;
-}
-
-int be_cmd_mccq_ext_create(struct be_adapter *adapter,
-			struct be_queue_info *mccq,
-			struct be_queue_info *cq)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_mcc_ext_create *req;
-	struct be_dma_mem *q_mem = &mccq->dma_mem;
-	void *ctxt;
-	int status;
-
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
-
-	wrb = wrb_from_mbox(adapter);
-	req = embedded_payload(wrb);
-	ctxt = &req->context;
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
-			OPCODE_COMMON_MCC_CREATE_EXT);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-			OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req));
-
-	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
-	if (lancer_chip(adapter)) {
-		req->hdr.version = 1;
-		req->cq_id = cpu_to_le16(cq->id);
-
-		AMAP_SET_BITS(struct amap_mcc_context_lancer, ring_size, ctxt,
-						be_encoded_q_len(mccq->len));
-		AMAP_SET_BITS(struct amap_mcc_context_lancer, valid, ctxt, 1);
-		AMAP_SET_BITS(struct amap_mcc_context_lancer, async_cq_id,
-								ctxt, cq->id);
-		AMAP_SET_BITS(struct amap_mcc_context_lancer, async_cq_valid,
-								 ctxt, 1);
-
-	} else {
-		AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
-		AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
-						be_encoded_q_len(mccq->len));
-		AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
-	}
-
-	/* Subscribe to Link State and Group 5 Events(bits 1 and 5 set) */
-	req->async_event_bitmap[0] = cpu_to_le32(0x00000022);
-	be_dws_cpu_to_le(ctxt, sizeof(req->context));
-
-	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
-
-	status = be_mbox_notify_wait(adapter);
-	if (!status) {
-		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
-		mccq->id = le16_to_cpu(resp->id);
-		mccq->created = true;
-	}
-	mutex_unlock(&adapter->mbox_lock);
-
-	return status;
-}
-
-int be_cmd_mccq_org_create(struct be_adapter *adapter,
-			struct be_queue_info *mccq,
-			struct be_queue_info *cq)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_mcc_create *req;
-	struct be_dma_mem *q_mem = &mccq->dma_mem;
-	void *ctxt;
-	int status;
-
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
-
-	wrb = wrb_from_mbox(adapter);
-	req = embedded_payload(wrb);
-	ctxt = &req->context;
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
-			OPCODE_COMMON_MCC_CREATE);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-			OPCODE_COMMON_MCC_CREATE, sizeof(*req));
-
-	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
-
-	AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
-	AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
-			be_encoded_q_len(mccq->len));
-	AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
-
-	be_dws_cpu_to_le(ctxt, sizeof(req->context));
-
-	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
-
-	status = be_mbox_notify_wait(adapter);
-	if (!status) {
-		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
-		mccq->id = le16_to_cpu(resp->id);
-		mccq->created = true;
-	}
-
-	mutex_unlock(&adapter->mbox_lock);
-	return status;
-}
-
-int be_cmd_mccq_create(struct be_adapter *adapter,
-			struct be_queue_info *mccq,
-			struct be_queue_info *cq)
-{
-	int status;
-
-	status = be_cmd_mccq_ext_create(adapter, mccq, cq);
-	if (status && !lancer_chip(adapter)) {
-		dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 "
-			"or newer to avoid conflicting priorities between NIC "
-			"and FCoE traffic");
-		status = be_cmd_mccq_org_create(adapter, mccq, cq);
-	}
-	return status;
-}
-
-int be_cmd_txq_create(struct be_adapter *adapter,
-			struct be_queue_info *txq,
-			struct be_queue_info *cq)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_eth_tx_create *req;
-	struct be_dma_mem *q_mem = &txq->dma_mem;
-	void *ctxt;
-	int status;
-
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
-
-	wrb = wrb_from_mbox(adapter);
-	req = embedded_payload(wrb);
-	ctxt = &req->context;
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
-			OPCODE_ETH_TX_CREATE);
-
-	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;
-
-	AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt,
-		be_encoded_q_len(txq->len));
-	AMAP_SET_BITS(struct amap_tx_context, ctx_valid, ctxt, 1);
-	AMAP_SET_BITS(struct amap_tx_context, cq_id_send, ctxt, cq->id);
-
-	be_dws_cpu_to_le(ctxt, sizeof(req->context));
-
-	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
-
-	status = be_mbox_notify_wait(adapter);
-	if (!status) {
-		struct be_cmd_resp_eth_tx_create *resp = embedded_payload(wrb);
-		txq->id = le16_to_cpu(resp->cid);
-		txq->created = true;
-	}
-
-	mutex_unlock(&adapter->mbox_lock);
-
-	return status;
-}
-
-/* Uses MCC */
-int be_cmd_rxq_create(struct be_adapter *adapter,
-		struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
-		u16 max_frame_size, u32 if_id, u32 rss, u8 *rss_id)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_eth_rx_create *req;
-	struct be_dma_mem *q_mem = &rxq->dma_mem;
-	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_ETH_RX_CREATE);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_RX_CREATE,
-		sizeof(*req));
-
-	req->cq_id = cpu_to_le16(cq_id);
-	req->frag_size = fls(frag_size) - 1;
-	req->num_pages = 2;
-	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
-	req->interface_id = cpu_to_le32(if_id);
-	req->max_frame_size = cpu_to_le16(max_frame_size);
-	req->rss_queue = cpu_to_le32(rss);
-
-	status = be_mcc_notify_wait(adapter);
-	if (!status) {
-		struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb);
-		rxq->id = le16_to_cpu(resp->id);
-		rxq->created = true;
-		*rss_id = resp->rss_id;
-	}
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-/* Generic destroyer function for all types of queues
- * Uses Mbox
- */
-int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
-		int queue_type)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_q_destroy *req;
-	u8 subsys = 0, opcode = 0;
-	int status;
-
-	if (adapter->eeh_err)
-		return -EIO;
-
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
-
-	wrb = wrb_from_mbox(adapter);
-	req = embedded_payload(wrb);
-
-	switch (queue_type) {
-	case QTYPE_EQ:
-		subsys = CMD_SUBSYSTEM_COMMON;
-		opcode = OPCODE_COMMON_EQ_DESTROY;
-		break;
-	case QTYPE_CQ:
-		subsys = CMD_SUBSYSTEM_COMMON;
-		opcode = OPCODE_COMMON_CQ_DESTROY;
-		break;
-	case QTYPE_TXQ:
-		subsys = CMD_SUBSYSTEM_ETH;
-		opcode = OPCODE_ETH_TX_DESTROY;
-		break;
-	case QTYPE_RXQ:
-		subsys = CMD_SUBSYSTEM_ETH;
-		opcode = OPCODE_ETH_RX_DESTROY;
-		break;
-	case QTYPE_MCCQ:
-		subsys = CMD_SUBSYSTEM_COMMON;
-		opcode = OPCODE_COMMON_MCC_DESTROY;
-		break;
-	default:
-		BUG();
-	}
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, opcode);
-
-	be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req));
-	req->id = cpu_to_le16(q->id);
-
-	status = be_mbox_notify_wait(adapter);
-	if (!status)
-		q->created = false;
-
-	mutex_unlock(&adapter->mbox_lock);
-	return status;
-}
-
-/* Uses MCC */
-int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_q_destroy *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_ETH_RX_DESTROY);
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_RX_DESTROY,
-		sizeof(*req));
-	req->id = cpu_to_le16(q->id);
-
-	status = be_mcc_notify_wait(adapter);
-	if (!status)
-		q->created = false;
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-/* Create an rx filtering policy configuration on an i/f
- * Uses mbox
- */
-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)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_if_create *req;
-	int status;
-
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
-
-	wrb = wrb_from_mbox(adapter);
-	req = embedded_payload(wrb);
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
-			OPCODE_COMMON_NTWK_INTERFACE_CREATE);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_NTWK_INTERFACE_CREATE, sizeof(*req));
-
-	req->hdr.domain = domain;
-	req->capability_flags = cpu_to_le32(cap_flags);
-	req->enable_flags = cpu_to_le32(en_flags);
-	req->pmac_invalid = pmac_invalid;
-	if (!pmac_invalid)
-		memcpy(req->mac_addr, mac, ETH_ALEN);
-
-	status = be_mbox_notify_wait(adapter);
-	if (!status) {
-		struct be_cmd_resp_if_create *resp = embedded_payload(wrb);
-		*if_handle = le32_to_cpu(resp->interface_id);
-		if (!pmac_invalid)
-			*pmac_id = le32_to_cpu(resp->pmac_id);
-	}
-
-	mutex_unlock(&adapter->mbox_lock);
-	return status;
-}
-
-/* Uses mbox */
-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;
-	int status;
-
-	if (adapter->eeh_err)
-		return -EIO;
-
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
-
-	wrb = wrb_from_mbox(adapter);
-	req = embedded_payload(wrb);
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
-			OPCODE_COMMON_NTWK_INTERFACE_DESTROY);
-
-	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);
-
-	mutex_unlock(&adapter->mbox_lock);
-
-	return status;
-}
-
-/* Get stats is a non embedded command: the request is not embedded inside
- * WRB but is a separate dma memory block
- * Uses asynchronous MCC
- */
-int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_hdr *hdr;
-	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);
-	if (!wrb) {
-		status = -EBUSY;
-		goto err;
-	}
-	hdr = nonemb_cmd->va;
-	sge = nonembedded_sgl(wrb);
-
-	be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1,
-			OPCODE_ETH_GET_STATISTICS);
-
-	be_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH,
-		OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size);
-
-	if (adapter->generation == BE_GEN3)
-		hdr->version = 1;
-
-	wrb->tag1 = CMD_SUBSYSTEM_ETH;
-	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
-	sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
-	sge->len = cpu_to_le32(nonemb_cmd->size);
-
-	be_mcc_notify(adapter);
-	adapter->stats_cmd_sent = true;
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-/* Lancer Stats */
-int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
-				struct be_dma_mem *nonemb_cmd)
-{
-
-	struct be_mcc_wrb *wrb;
-	struct lancer_cmd_req_pport_stats *req;
-	struct be_sge *sge;
-	int status = 0;
-
-	spin_lock_bh(&adapter->mcc_lock);
-
-	wrb = wrb_from_mccq(adapter);
-	if (!wrb) {
-		status = -EBUSY;
-		goto err;
-	}
-	req = nonemb_cmd->va;
-	sge = nonembedded_sgl(wrb);
-
-	be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1,
-			OPCODE_ETH_GET_PPORT_STATS);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
-			OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size);
-
-
-	req->cmd_params.params.pport_num = cpu_to_le16(adapter->port_num);
-	req->cmd_params.params.reset_stats = 0;
-
-	wrb->tag1 = CMD_SUBSYSTEM_ETH;
-	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
-	sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
-	sge->len = cpu_to_le32(nonemb_cmd->size);
-
-	be_mcc_notify(adapter);
-	adapter->stats_cmd_sent = true;
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-/* Uses synchronous mcc */
-int be_cmd_link_status_query(struct be_adapter *adapter,
-			bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_link_status *req;
-	int status;
-
-	spin_lock_bh(&adapter->mcc_lock);
-
-	wrb = wrb_from_mccq(adapter);
-	if (!wrb) {
-		status = -EBUSY;
-		goto err;
-	}
-	req = embedded_payload(wrb);
-
-	*link_up = false;
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
-			OPCODE_COMMON_NTWK_LINK_STATUS_QUERY);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req));
-
-	status = be_mcc_notify_wait(adapter);
-	if (!status) {
-		struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
-		if (resp->mac_speed != PHY_LINK_SPEED_ZERO) {
-			*link_up = true;
-			*link_speed = le16_to_cpu(resp->link_speed);
-			*mac_speed = resp->mac_speed;
-		}
-	}
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	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 synchronous mcc */
-int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_get_fat *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_MANAGE_FAT);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_MANAGE_FAT, sizeof(*req));
-	req->fat_operation = cpu_to_le32(QUERY_FAT);
-	status = be_mcc_notify_wait(adapter);
-	if (!status) {
-		struct be_cmd_resp_get_fat *resp = embedded_payload(wrb);
-		if (log_size && resp->log_size)
-			*log_size = le32_to_cpu(resp->log_size) -
-					sizeof(u32);
-	}
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf)
-{
-	struct be_dma_mem get_fat_cmd;
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_get_fat *req;
-	struct be_sge *sge;
-	u32 offset = 0, total_size, buf_size,
-				log_offset = sizeof(u32), payload_len;
-	int status;
-
-	if (buf_len == 0)
-		return;
-
-	total_size = buf_len;
-
-	get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024;
-	get_fat_cmd.va = pci_alloc_consistent(adapter->pdev,
-			get_fat_cmd.size,
-			&get_fat_cmd.dma);
-	if (!get_fat_cmd.va) {
-		status = -ENOMEM;
-		dev_err(&adapter->pdev->dev,
-		"Memory allocation failure while retrieving FAT data\n");
-		return;
-	}
-
-	spin_lock_bh(&adapter->mcc_lock);
-
-	while (total_size) {
-		buf_size = min(total_size, (u32)60*1024);
-		total_size -= buf_size;
-
-		wrb = wrb_from_mccq(adapter);
-		if (!wrb) {
-			status = -EBUSY;
-			goto err;
-		}
-		req = get_fat_cmd.va;
-		sge = nonembedded_sgl(wrb);
-
-		payload_len = sizeof(struct be_cmd_req_get_fat) + buf_size;
-		be_wrb_hdr_prepare(wrb, payload_len, false, 1,
-				OPCODE_COMMON_MANAGE_FAT);
-
-		be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-				OPCODE_COMMON_MANAGE_FAT, payload_len);
-
-		sge->pa_hi = cpu_to_le32(upper_32_bits(get_fat_cmd.dma));
-		sge->pa_lo = cpu_to_le32(get_fat_cmd.dma & 0xFFFFFFFF);
-		sge->len = cpu_to_le32(get_fat_cmd.size);
-
-		req->fat_operation = cpu_to_le32(RETRIEVE_FAT);
-		req->read_log_offset = cpu_to_le32(log_offset);
-		req->read_log_length = cpu_to_le32(buf_size);
-		req->data_buffer_size = cpu_to_le32(buf_size);
-
-		status = be_mcc_notify_wait(adapter);
-		if (!status) {
-			struct be_cmd_resp_get_fat *resp = get_fat_cmd.va;
-			memcpy(buf + offset,
-				resp->data_buffer,
-				resp->read_log_length);
-		} else {
-			dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n");
-			goto err;
-		}
-		offset += buf_size;
-		log_offset += buf_size;
-	}
-err:
-	pci_free_consistent(adapter->pdev, get_fat_cmd.size,
-			get_fat_cmd.va,
-			get_fat_cmd.dma);
-	spin_unlock_bh(&adapter->mcc_lock);
-}
-
-/* Uses Mbox */
-int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_get_fw_version *req;
-	int status;
-
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
-
-	wrb = wrb_from_mbox(adapter);
-	req = embedded_payload(wrb);
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
-			OPCODE_COMMON_GET_FW_VERSION);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_GET_FW_VERSION, sizeof(*req));
-
-	status = be_mbox_notify_wait(adapter);
-	if (!status) {
-		struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb);
-		strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN);
-	}
-
-	mutex_unlock(&adapter->mbox_lock);
-	return status;
-}
-
-/* set the EQ delay interval of an EQ to specified value
- * Uses async mcc
- */
-int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_modify_eq_delay *req;
-	int status = 0;
-
-	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_MODIFY_EQ_DELAY);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req));
-
-	req->num_eq = cpu_to_le32(1);
-	req->delay[0].eq_id = cpu_to_le32(eq_id);
-	req->delay[0].phase = 0;
-	req->delay[0].delay_multiplier = cpu_to_le32(eqd);
-
-	be_mcc_notify(adapter);
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-/* Uses sycnhronous mcc */
-int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
-			u32 num, bool untagged, bool promiscuous)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_vlan_config *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_NTWK_VLAN_CONFIG);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req));
-
-	req->interface_id = if_id;
-	req->promiscuous = promiscuous;
-	req->untagged = untagged;
-	req->num_vlan = num;
-	if (!promiscuous) {
-		memcpy(req->normal_vlan, vtag_array,
-			req->num_vlan * sizeof(vtag_array[0]));
-	}
-
-	status = be_mcc_notify_wait(adapter);
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-/* Uses MCC for this command as it may be called in BH context
- * Uses synchronous mcc
- */
-int be_cmd_promiscuous_config(struct be_adapter *adapter, bool en)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_rx_filter *req;
-	struct be_dma_mem promiscous_cmd;
-	struct be_sge *sge;
-	int status;
-
-	memset(&promiscous_cmd, 0, sizeof(struct be_dma_mem));
-	promiscous_cmd.size = sizeof(struct be_cmd_req_rx_filter);
-	promiscous_cmd.va = pci_alloc_consistent(adapter->pdev,
-				promiscous_cmd.size, &promiscous_cmd.dma);
-	if (!promiscous_cmd.va) {
-		dev_err(&adapter->pdev->dev,
-				"Memory allocation failure\n");
-		return -ENOMEM;
-	}
-
-	spin_lock_bh(&adapter->mcc_lock);
-
-	wrb = wrb_from_mccq(adapter);
-	if (!wrb) {
-		status = -EBUSY;
-		goto err;
-	}
-
-	req = promiscous_cmd.va;
-	sge = nonembedded_sgl(wrb);
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
-					OPCODE_COMMON_NTWK_RX_FILTER);
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-			OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req));
-
-	req->if_id = cpu_to_le32(adapter->if_handle);
-	req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS);
-	if (en)
-		req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS);
-
-	sge->pa_hi = cpu_to_le32(upper_32_bits(promiscous_cmd.dma));
-	sge->pa_lo = cpu_to_le32(promiscous_cmd.dma & 0xFFFFFFFF);
-	sge->len = cpu_to_le32(promiscous_cmd.size);
-
-	status = be_mcc_notify_wait(adapter);
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	pci_free_consistent(adapter->pdev, promiscous_cmd.size,
-			promiscous_cmd.va, promiscous_cmd.dma);
-	return status;
-}
-
-/*
- * Uses MCC for this command as it may be called in BH context
- * (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)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_mcast_mac_config *req = mem->va;
-	struct be_sge *sge;
-	int status;
-
-	spin_lock_bh(&adapter->mcc_lock);
-
-	wrb = wrb_from_mccq(adapter);
-	if (!wrb) {
-		status = -EBUSY;
-		goto err;
-	}
-	sge = nonembedded_sgl(wrb);
-	memset(req, 0, sizeof(*req));
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
-			OPCODE_COMMON_NTWK_MULTICAST_SET);
-	sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma));
-	sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF);
-	sge->len = cpu_to_le32(mem->size);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req));
-
-	req->interface_id = if_id;
-	if (netdev) {
-		int i;
-		struct netdev_hw_addr *ha;
-
-		req->num_mac = cpu_to_le16(netdev_mc_count(netdev));
-
-		i = 0;
-		netdev_for_each_mc_addr(ha, netdev)
-			memcpy(req->mac[i++].byte, ha->addr, ETH_ALEN);
-	} else {
-		req->promiscuous = 1;
-	}
-
-	status = be_mcc_notify_wait(adapter);
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-/* Uses synchrounous mcc */
-int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_set_flow_control *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_SET_FLOW_CONTROL);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req));
-
-	req->tx_flow_control = cpu_to_le16((u16)tx_fc);
-	req->rx_flow_control = cpu_to_le16((u16)rx_fc);
-
-	status = be_mcc_notify_wait(adapter);
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-/* Uses sycn mcc */
-int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_get_flow_control *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_FLOW_CONTROL);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req));
-
-	status = be_mcc_notify_wait(adapter);
-	if (!status) {
-		struct be_cmd_resp_get_flow_control *resp =
-						embedded_payload(wrb);
-		*tx_fc = le16_to_cpu(resp->tx_flow_control);
-		*rx_fc = le16_to_cpu(resp->rx_flow_control);
-	}
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-/* Uses mbox */
-int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
-		u32 *mode, u32 *caps)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_query_fw_cfg *req;
-	int status;
-
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
-
-	wrb = wrb_from_mbox(adapter);
-	req = embedded_payload(wrb);
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
-			OPCODE_COMMON_QUERY_FIRMWARE_CONFIG);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req));
-
-	status = be_mbox_notify_wait(adapter);
-	if (!status) {
-		struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb);
-		*port_num = le32_to_cpu(resp->phys_port);
-		*mode = le32_to_cpu(resp->function_mode);
-		*caps = le32_to_cpu(resp->function_caps);
-	}
-
-	mutex_unlock(&adapter->mbox_lock);
-	return status;
-}
-
-/* Uses mbox */
-int be_cmd_reset_function(struct be_adapter *adapter)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_hdr *req;
-	int status;
-
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
-
-	wrb = wrb_from_mbox(adapter);
-	req = embedded_payload(wrb);
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
-			OPCODE_COMMON_FUNCTION_RESET);
-
-	be_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_FUNCTION_RESET, sizeof(*req));
-
-	status = be_mbox_notify_wait(adapter);
-
-	mutex_unlock(&adapter->mbox_lock);
-	return status;
-}
-
-int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_rss_config *req;
-	u32 myhash[10] = {0x0123, 0x4567, 0x89AB, 0xCDEF, 0x01EF,
-			0x0123, 0x4567, 0x89AB, 0xCDEF, 0x01EF};
-	int status;
-
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
-
-	wrb = wrb_from_mbox(adapter);
-	req = embedded_payload(wrb);
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
-		OPCODE_ETH_RSS_CONFIG);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
-		OPCODE_ETH_RSS_CONFIG, sizeof(*req));
-
-	req->if_id = cpu_to_le32(adapter->if_handle);
-	req->enable_rss = cpu_to_le16(RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4);
-	req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1);
-	memcpy(req->cpu_table, rsstable, table_size);
-	memcpy(req->hash, myhash, sizeof(myhash));
-	be_dws_cpu_to_le(req->hash, sizeof(req->hash));
-
-	status = be_mbox_notify_wait(adapter);
-
-	mutex_unlock(&adapter->mbox_lock);
-	return status;
-}
-
-/* Uses sync mcc */
-int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num,
-			u8 bcn, u8 sts, u8 state)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_enable_disable_beacon *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_ENABLE_DISABLE_BEACON);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_ENABLE_DISABLE_BEACON, sizeof(*req));
-
-	req->port_num = port_num;
-	req->beacon_state = state;
-	req->beacon_duration = bcn;
-	req->status_duration = sts;
-
-	status = be_mcc_notify_wait(adapter);
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-/* Uses sync mcc */
-int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_get_beacon_state *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_BEACON_STATE);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_GET_BEACON_STATE, sizeof(*req));
-
-	req->port_num = port_num;
-
-	status = be_mcc_notify_wait(adapter);
-	if (!status) {
-		struct be_cmd_resp_get_beacon_state *resp =
-						embedded_payload(wrb);
-		*state = resp->beacon_state;
-	}
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
-			u32 data_size, u32 data_offset, const char *obj_name,
-			u32 *data_written, u8 *addn_status)
-{
-	struct be_mcc_wrb *wrb;
-	struct lancer_cmd_req_write_object *req;
-	struct lancer_cmd_resp_write_object *resp;
-	void *ctxt = NULL;
-	int status;
-
-	spin_lock_bh(&adapter->mcc_lock);
-	adapter->flash_status = 0;
-
-	wrb = wrb_from_mccq(adapter);
-	if (!wrb) {
-		status = -EBUSY;
-		goto err_unlock;
-	}
-
-	req = embedded_payload(wrb);
-
-	be_wrb_hdr_prepare(wrb, sizeof(struct lancer_cmd_req_write_object),
-			true, 1, OPCODE_COMMON_WRITE_OBJECT);
-	wrb->tag1 = CMD_SUBSYSTEM_COMMON;
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-				OPCODE_COMMON_WRITE_OBJECT,
-				sizeof(struct lancer_cmd_req_write_object));
-
-	ctxt = &req->context;
-	AMAP_SET_BITS(struct amap_lancer_write_obj_context,
-			write_length, ctxt, data_size);
-
-	if (data_size == 0)
-		AMAP_SET_BITS(struct amap_lancer_write_obj_context,
-				eof, ctxt, 1);
-	else
-		AMAP_SET_BITS(struct amap_lancer_write_obj_context,
-				eof, ctxt, 0);
-
-	be_dws_cpu_to_le(ctxt, sizeof(req->context));
-	req->write_offset = cpu_to_le32(data_offset);
-	strcpy(req->object_name, obj_name);
-	req->descriptor_count = cpu_to_le32(1);
-	req->buf_len = cpu_to_le32(data_size);
-	req->addr_low = cpu_to_le32((cmd->dma +
-				sizeof(struct lancer_cmd_req_write_object))
-				& 0xFFFFFFFF);
-	req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma +
-				sizeof(struct lancer_cmd_req_write_object)));
-
-	be_mcc_notify(adapter);
-	spin_unlock_bh(&adapter->mcc_lock);
-
-	if (!wait_for_completion_timeout(&adapter->flash_compl,
-			msecs_to_jiffies(12000)))
-		status = -1;
-	else
-		status = adapter->flash_status;
-
-	resp = embedded_payload(wrb);
-	if (!status) {
-		*data_written = le32_to_cpu(resp->actual_write_len);
-	} else {
-		*addn_status = resp->additional_status;
-		status = resp->status;
-	}
-
-	return status;
-
-err_unlock:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
-			u32 flash_type, u32 flash_opcode, u32 buf_size)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_write_flashrom *req;
-	struct be_sge *sge;
-	int status;
-
-	spin_lock_bh(&adapter->mcc_lock);
-	adapter->flash_status = 0;
-
-	wrb = wrb_from_mccq(adapter);
-	if (!wrb) {
-		status = -EBUSY;
-		goto err_unlock;
-	}
-	req = cmd->va;
-	sge = nonembedded_sgl(wrb);
-
-	be_wrb_hdr_prepare(wrb, cmd->size, false, 1,
-			OPCODE_COMMON_WRITE_FLASHROM);
-	wrb->tag1 = CMD_SUBSYSTEM_COMMON;
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_WRITE_FLASHROM, cmd->size);
-	sge->pa_hi = cpu_to_le32(upper_32_bits(cmd->dma));
-	sge->pa_lo = cpu_to_le32(cmd->dma & 0xFFFFFFFF);
-	sge->len = cpu_to_le32(cmd->size);
-
-	req->params.op_type = cpu_to_le32(flash_type);
-	req->params.op_code = cpu_to_le32(flash_opcode);
-	req->params.data_buf_size = cpu_to_le32(buf_size);
-
-	be_mcc_notify(adapter);
-	spin_unlock_bh(&adapter->mcc_lock);
-
-	if (!wait_for_completion_timeout(&adapter->flash_compl,
-			msecs_to_jiffies(12000)))
-		status = -1;
-	else
-		status = adapter->flash_status;
-
-	return status;
-
-err_unlock:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
-			 int offset)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_write_flashrom *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)+4, true, 0,
-			OPCODE_COMMON_READ_FLASHROM);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4);
-
-	req->params.op_type = cpu_to_le32(IMG_TYPE_REDBOOT);
-	req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
-	req->params.offset = cpu_to_le32(offset);
-	req->params.data_buf_size = cpu_to_le32(0x4);
-
-	status = be_mcc_notify_wait(adapter);
-	if (!status)
-		memcpy(flashed_crc, req->params.data_buf, 4);
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
-				struct be_dma_mem *nonemb_cmd)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_acpi_wol_magic_config *req;
-	struct be_sge *sge;
-	int status;
-
-	spin_lock_bh(&adapter->mcc_lock);
-
-	wrb = wrb_from_mccq(adapter);
-	if (!wrb) {
-		status = -EBUSY;
-		goto err;
-	}
-	req = nonemb_cmd->va;
-	sge = nonembedded_sgl(wrb);
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
-			OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
-		OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req));
-	memcpy(req->magic_mac, mac, ETH_ALEN);
-
-	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
-	sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
-	sge->len = cpu_to_le32(nonemb_cmd->size);
-
-	status = be_mcc_notify_wait(adapter);
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
-			u8 loopback_type, u8 enable)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_set_lmode *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_LOWLEVEL_SET_LOOPBACK_MODE);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
-			OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
-			sizeof(*req));
-
-	req->src_port = port_num;
-	req->dest_port = port_num;
-	req->loopback_type = loopback_type;
-	req->loopback_state = enable;
-
-	status = be_mcc_notify_wait(adapter);
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
-		u32 loopback_type, u32 pkt_size, u32 num_pkts, u64 pattern)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_loopback_test *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_LOWLEVEL_LOOPBACK_TEST);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
-			OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req));
-	req->hdr.timeout = cpu_to_le32(4);
-
-	req->pattern = cpu_to_le64(pattern);
-	req->src_port = cpu_to_le32(port_num);
-	req->dest_port = cpu_to_le32(port_num);
-	req->pkt_size = cpu_to_le32(pkt_size);
-	req->num_pkts = cpu_to_le32(num_pkts);
-	req->loopback_type = cpu_to_le32(loopback_type);
-
-	status = be_mcc_notify_wait(adapter);
-	if (!status) {
-		struct be_cmd_resp_loopback_test *resp = embedded_payload(wrb);
-		status = le32_to_cpu(resp->status);
-	}
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
-				u32 byte_cnt, struct be_dma_mem *cmd)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_ddrdma_test *req;
-	struct be_sge *sge;
-	int status;
-	int i, j = 0;
-
-	spin_lock_bh(&adapter->mcc_lock);
-
-	wrb = wrb_from_mccq(adapter);
-	if (!wrb) {
-		status = -EBUSY;
-		goto err;
-	}
-	req = cmd->va;
-	sge = nonembedded_sgl(wrb);
-	be_wrb_hdr_prepare(wrb, cmd->size, false, 1,
-				OPCODE_LOWLEVEL_HOST_DDR_DMA);
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
-			OPCODE_LOWLEVEL_HOST_DDR_DMA, cmd->size);
-
-	sge->pa_hi = cpu_to_le32(upper_32_bits(cmd->dma));
-	sge->pa_lo = cpu_to_le32(cmd->dma & 0xFFFFFFFF);
-	sge->len = cpu_to_le32(cmd->size);
-
-	req->pattern = cpu_to_le64(pattern);
-	req->byte_count = cpu_to_le32(byte_cnt);
-	for (i = 0; i < byte_cnt; i++) {
-		req->snd_buff[i] = (u8)(pattern >> (j*8));
-		j++;
-		if (j > 7)
-			j = 0;
-	}
-
-	status = be_mcc_notify_wait(adapter);
-
-	if (!status) {
-		struct be_cmd_resp_ddrdma_test *resp;
-		resp = cmd->va;
-		if ((memcmp(resp->rcv_buff, req->snd_buff, byte_cnt) != 0) ||
-				resp->snd_err) {
-			status = -1;
-		}
-	}
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-int be_cmd_get_seeprom_data(struct be_adapter *adapter,
-				struct be_dma_mem *nonemb_cmd)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_seeprom_read *req;
-	struct be_sge *sge;
-	int status;
-
-	spin_lock_bh(&adapter->mcc_lock);
-
-	wrb = wrb_from_mccq(adapter);
-	if (!wrb) {
-		status = -EBUSY;
-		goto err;
-	}
-	req = nonemb_cmd->va;
-	sge = nonembedded_sgl(wrb);
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
-			OPCODE_COMMON_SEEPROM_READ);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-			OPCODE_COMMON_SEEPROM_READ, sizeof(*req));
-
-	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
-	sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
-	sge->len = cpu_to_le32(nonemb_cmd->size);
-
-	status = be_mcc_notify_wait(adapter);
-
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-int be_cmd_get_phy_info(struct be_adapter *adapter, struct be_dma_mem *cmd)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_get_phy_info *req;
-	struct be_sge *sge;
-	int status;
-
-	spin_lock_bh(&adapter->mcc_lock);
-
-	wrb = wrb_from_mccq(adapter);
-	if (!wrb) {
-		status = -EBUSY;
-		goto err;
-	}
-
-	req = cmd->va;
-	sge = nonembedded_sgl(wrb);
-
-	be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
-				OPCODE_COMMON_GET_PHY_DETAILS);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-			OPCODE_COMMON_GET_PHY_DETAILS,
-			sizeof(*req));
-
-	sge->pa_hi = cpu_to_le32(upper_32_bits(cmd->dma));
-	sge->pa_lo = cpu_to_le32(cmd->dma & 0xFFFFFFFF);
-	sge->len = cpu_to_le32(cmd->size);
-
-	status = be_mcc_notify_wait(adapter);
-err:
-	spin_unlock_bh(&adapter->mcc_lock);
-	return status;
-}
-
-int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain)
-{
-	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_set_qos *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_SET_QOS);
-
-	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-			OPCODE_COMMON_SET_QOS, sizeof(*req));
-
-	req->hdr.domain = domain;
-	req->valid_bits = cpu_to_le32(BE_QOS_BITS_NIC);
-	req->max_bps_nic = cpu_to_le32(bps);
-
-	status = be_mcc_notify_wait(adapter);
-
-err:
-	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 = 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_req_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-3.1-gnu/drivers/net/benet/be_cmds.h linux-libre-3.2-gnu/drivers/net/benet/be_cmds.h
--- linux-libre-3.1-gnu/drivers/net/benet/be_cmds.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/benet/be_cmds.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1551 +0,0 @@
-/*
- * Copyright (C) 2005 - 2011 Emulex
- * 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@emulex.com
- *
- * Emulex
- * 3333 Susan Street
- * Costa Mesa, CA 92626
- */
-
-/*
- * The driver sends configuration and managements command requests to the
- * firmware in the BE. These requests are communicated to the processor
- * using Work Request Blocks (WRBs) submitted to the MCC-WRB ring or via one
- * WRB inside a MAILBOX.
- * The commands are serviced by the ARM processor in the BladeEngine's MPU.
- */
-
-struct be_sge {
-	u32 pa_lo;
-	u32 pa_hi;
-	u32 len;
-};
-
-#define MCC_WRB_EMBEDDED_MASK	1 	/* bit 0 of dword 0*/
-#define MCC_WRB_SGE_CNT_SHIFT	3	/* bits 3 - 7 of dword 0 */
-#define MCC_WRB_SGE_CNT_MASK	0x1F	/* bits 3 - 7 of dword 0 */
-struct be_mcc_wrb {
-	u32 embedded;		/* dword 0 */
-	u32 payload_length;	/* dword 1 */
-	u32 tag0;		/* dword 2 */
-	u32 tag1;		/* dword 3 */
-	u32 rsvd;		/* dword 4 */
-	union {
-		u8 embedded_payload[236]; /* used by embedded cmds */
-		struct be_sge sgl[19];    /* used by non-embedded cmds */
-	} payload;
-};
-
-#define CQE_FLAGS_VALID_MASK 		(1 << 31)
-#define CQE_FLAGS_ASYNC_MASK 		(1 << 30)
-#define CQE_FLAGS_COMPLETED_MASK 	(1 << 28)
-#define CQE_FLAGS_CONSUMED_MASK 	(1 << 27)
-
-/* Completion Status */
-enum {
-	MCC_STATUS_SUCCESS = 0,
-	MCC_STATUS_FAILED = 1,
-	MCC_STATUS_ILLEGAL_REQUEST = 2,
-	MCC_STATUS_ILLEGAL_FIELD = 3,
-	MCC_STATUS_INSUFFICIENT_BUFFER = 4,
-	MCC_STATUS_UNAUTHORIZED_REQUEST = 5,
-	MCC_STATUS_NOT_SUPPORTED = 66
-};
-
-#define CQE_STATUS_COMPL_MASK		0xFFFF
-#define CQE_STATUS_COMPL_SHIFT		0	/* bits 0 - 15 */
-#define CQE_STATUS_EXTD_MASK		0xFFFF
-#define CQE_STATUS_EXTD_SHIFT		16	/* bits 16 - 31 */
-
-struct be_mcc_compl {
-	u32 status;		/* dword 0 */
-	u32 tag0;		/* dword 1 */
-	u32 tag1;		/* dword 2 */
-	u32 flags;		/* dword 3 */
-};
-
-/* When the async bit of mcc_compl is set, the last 4 bytes of
- * mcc_compl is interpreted as follows:
- */
-#define ASYNC_TRAILER_EVENT_CODE_SHIFT	8	/* bits 8 - 15 */
-#define ASYNC_TRAILER_EVENT_CODE_MASK	0xFF
-#define ASYNC_TRAILER_EVENT_TYPE_SHIFT	16
-#define ASYNC_TRAILER_EVENT_TYPE_MASK	0xFF
-#define ASYNC_EVENT_CODE_LINK_STATE	0x1
-#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;
-};
-
-enum {
-	ASYNC_EVENT_LINK_DOWN 	= 0x0,
-	ASYNC_EVENT_LINK_UP 	= 0x1
-};
-
-/* When the event code of an async trailer is link-state, the mcc_compl
- * must be interpreted as follows
- */
-struct be_async_event_link_state {
-	u8 physical_port;
-	u8 port_link_status;
-	u8 port_duplex;
-	u8 port_speed;
-	u8 port_fault;
-	u8 rsvd0[7];
-	struct be_async_event_trailer trailer;
-} __packed;
-
-/* When the event code of an async trailer is GRP-5 and event_type is QOS_SPEED
- * the mcc_compl must be interpreted as follows
- */
-struct be_async_event_grp5_qos_link_speed {
-	u8 physical_port;
-	u8 rsvd[5];
-	u16 qos_link_speed;
-	u32 event_tag;
-	struct be_async_event_trailer trailer;
-} __packed;
-
-/* When the event code of an async trailer is GRP5 and event type is
- * CoS-Priority, the mcc_compl must be interpreted as follows
- */
-struct be_async_event_grp5_cos_priority {
-	u8 physical_port;
-	u8 available_priority_bmap;
-	u8 reco_default_priority;
-	u8 valid;
-	u8 rsvd0;
-	u8 event_tag;
-	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;
-};
-
-#define CMD_SUBSYSTEM_COMMON	0x1
-#define CMD_SUBSYSTEM_ETH 	0x3
-#define CMD_SUBSYSTEM_LOWLEVEL  0xb
-
-#define OPCODE_COMMON_NTWK_MAC_QUERY			1
-#define OPCODE_COMMON_NTWK_MAC_SET			2
-#define OPCODE_COMMON_NTWK_MULTICAST_SET		3
-#define OPCODE_COMMON_NTWK_VLAN_CONFIG  		4
-#define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY		5
-#define OPCODE_COMMON_READ_FLASHROM			6
-#define OPCODE_COMMON_WRITE_FLASHROM			7
-#define OPCODE_COMMON_CQ_CREATE				12
-#define OPCODE_COMMON_EQ_CREATE				13
-#define OPCODE_COMMON_MCC_CREATE			21
-#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
-#define OPCODE_COMMON_GET_FLOW_CONTROL			37
-#define OPCODE_COMMON_SET_FRAME_SIZE			39
-#define OPCODE_COMMON_MODIFY_EQ_DELAY			41
-#define OPCODE_COMMON_FIRMWARE_CONFIG			42
-#define OPCODE_COMMON_NTWK_INTERFACE_CREATE 		50
-#define OPCODE_COMMON_NTWK_INTERFACE_DESTROY 		51
-#define OPCODE_COMMON_MCC_DESTROY        		53
-#define OPCODE_COMMON_CQ_DESTROY        		54
-#define OPCODE_COMMON_EQ_DESTROY        		55
-#define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG		58
-#define OPCODE_COMMON_NTWK_PMAC_ADD			59
-#define OPCODE_COMMON_NTWK_PMAC_DEL			60
-#define OPCODE_COMMON_FUNCTION_RESET			61
-#define OPCODE_COMMON_MANAGE_FAT			68
-#define OPCODE_COMMON_ENABLE_DISABLE_BEACON		69
-#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_COMMON_WRITE_OBJECT			172
-
-#define OPCODE_ETH_RSS_CONFIG				1
-#define OPCODE_ETH_ACPI_CONFIG				2
-#define OPCODE_ETH_PROMISCUOUS				3
-#define OPCODE_ETH_GET_STATISTICS			4
-#define OPCODE_ETH_TX_CREATE				7
-#define OPCODE_ETH_RX_CREATE            		8
-#define OPCODE_ETH_TX_DESTROY           		9
-#define OPCODE_ETH_RX_DESTROY           		10
-#define OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG		12
-#define OPCODE_ETH_GET_PPORT_STATS			18
-
-#define OPCODE_LOWLEVEL_HOST_DDR_DMA                    17
-#define OPCODE_LOWLEVEL_LOOPBACK_TEST                   18
-#define OPCODE_LOWLEVEL_SET_LOOPBACK_MODE		19
-
-struct be_cmd_req_hdr {
-	u8 opcode;		/* dword 0 */
-	u8 subsystem;		/* dword 0 */
-	u8 port_number;		/* dword 0 */
-	u8 domain;		/* dword 0 */
-	u32 timeout;		/* dword 1 */
-	u32 request_length;	/* dword 2 */
-	u8 version;		/* dword 3 */
-	u8 rsvd[3];		/* dword 3 */
-};
-
-#define RESP_HDR_INFO_OPCODE_SHIFT	0	/* bits 0 - 7 */
-#define RESP_HDR_INFO_SUBSYS_SHIFT	8 	/* bits 8 - 15 */
-struct be_cmd_resp_hdr {
-	u32 info;		/* dword 0 */
-	u32 status;		/* dword 1 */
-	u32 response_length;	/* dword 2 */
-	u32 actual_resp_len;	/* dword 3 */
-};
-
-struct phys_addr {
-	u32 lo;
-	u32 hi;
-};
-
-/**************************
- * BE Command definitions *
- **************************/
-
-/* 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_eq_context {
-	u8 cidx[13];		/* dword 0*/
-	u8 rsvd0[3];		/* dword 0*/
-	u8 epidx[13];		/* dword 0*/
-	u8 valid;		/* dword 0*/
-	u8 rsvd1;		/* dword 0*/
-	u8 size;		/* dword 0*/
-	u8 pidx[13];		/* dword 1*/
-	u8 rsvd2[3];		/* dword 1*/
-	u8 pd[10];		/* dword 1*/
-	u8 count[3];		/* dword 1*/
-	u8 solevent;		/* dword 1*/
-	u8 stalled;		/* dword 1*/
-	u8 armed;		/* dword 1*/
-	u8 rsvd3[4];		/* dword 2*/
-	u8 func[8];		/* dword 2*/
-	u8 rsvd4;		/* dword 2*/
-	u8 delaymult[10];	/* dword 2*/
-	u8 rsvd5[2];		/* dword 2*/
-	u8 phase[2];		/* dword 2*/
-	u8 nodelay;		/* dword 2*/
-	u8 rsvd6[4];		/* dword 2*/
-	u8 rsvd7[32];		/* dword 3*/
-} __packed;
-
-struct be_cmd_req_eq_create {
-	struct be_cmd_req_hdr hdr;
-	u16 num_pages;		/* sword */
-	u16 rsvd0;		/* sword */
-	u8 context[sizeof(struct amap_eq_context) / 8];
-	struct phys_addr pages[8];
-} __packed;
-
-struct be_cmd_resp_eq_create {
-	struct be_cmd_resp_hdr resp_hdr;
-	u16 eq_id;		/* sword */
-	u16 rsvd0;		/* sword */
-} __packed;
-
-/******************** Mac query ***************************/
-enum {
-	MAC_ADDRESS_TYPE_STORAGE = 0x0,
-	MAC_ADDRESS_TYPE_NETWORK = 0x1,
-	MAC_ADDRESS_TYPE_PD = 0x2,
-	MAC_ADDRESS_TYPE_MANAGEMENT = 0x3
-};
-
-struct mac_addr {
-	u16 size_of_struct;
-	u8 addr[ETH_ALEN];
-} __packed;
-
-struct be_cmd_req_mac_query {
-	struct be_cmd_req_hdr hdr;
-	u8 type;
-	u8 permanent;
-	u16 if_id;
-} __packed;
-
-struct be_cmd_resp_mac_query {
-	struct be_cmd_resp_hdr hdr;
-	struct mac_addr mac;
-};
-
-/******************** PMac Add ***************************/
-struct be_cmd_req_pmac_add {
-	struct be_cmd_req_hdr hdr;
-	u32 if_id;
-	u8 mac_address[ETH_ALEN];
-	u8 rsvd0[2];
-} __packed;
-
-struct be_cmd_resp_pmac_add {
-	struct be_cmd_resp_hdr hdr;
-	u32 pmac_id;
-};
-
-/******************** PMac Del ***************************/
-struct be_cmd_req_pmac_del {
-	struct be_cmd_req_hdr hdr;
-	u32 if_id;
-	u32 pmac_id;
-};
-
-/******************** Create CQ ***************************/
-/* 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_cq_context_be {
-	u8 cidx[11];		/* dword 0*/
-	u8 rsvd0;		/* dword 0*/
-	u8 coalescwm[2];	/* dword 0*/
-	u8 nodelay;		/* dword 0*/
-	u8 epidx[11];		/* dword 0*/
-	u8 rsvd1;		/* dword 0*/
-	u8 count[2];		/* dword 0*/
-	u8 valid;		/* dword 0*/
-	u8 solevent;		/* dword 0*/
-	u8 eventable;		/* dword 0*/
-	u8 pidx[11];		/* dword 1*/
-	u8 rsvd2;		/* dword 1*/
-	u8 pd[10];		/* dword 1*/
-	u8 eqid[8];		/* dword 1*/
-	u8 stalled;		/* dword 1*/
-	u8 armed;		/* dword 1*/
-	u8 rsvd3[4];		/* dword 2*/
-	u8 func[8];		/* dword 2*/
-	u8 rsvd4[20];		/* dword 2*/
-	u8 rsvd5[32];		/* dword 3*/
-} __packed;
-
-struct amap_cq_context_lancer {
-	u8 rsvd0[12];		/* dword 0*/
-	u8 coalescwm[2];	/* dword 0*/
-	u8 nodelay;		/* dword 0*/
-	u8 rsvd1[12];		/* dword 0*/
-	u8 count[2];		/* dword 0*/
-	u8 valid;		/* dword 0*/
-	u8 rsvd2;		/* dword 0*/
-	u8 eventable;		/* dword 0*/
-	u8 eqid[16];		/* dword 1*/
-	u8 rsvd3[15];		/* dword 1*/
-	u8 armed;		/* dword 1*/
-	u8 rsvd4[32];		/* dword 2*/
-	u8 rsvd5[32];		/* dword 3*/
-} __packed;
-
-struct be_cmd_req_cq_create {
-	struct be_cmd_req_hdr hdr;
-	u16 num_pages;
-	u8 page_size;
-	u8 rsvd0;
-	u8 context[sizeof(struct amap_cq_context_be) / 8];
-	struct phys_addr pages[8];
-} __packed;
-
-
-struct be_cmd_resp_cq_create {
-	struct be_cmd_resp_hdr hdr;
-	u16 cq_id;
-	u16 rsvd0;
-} __packed;
-
-struct be_cmd_req_get_fat {
-	struct be_cmd_req_hdr hdr;
-	u32 fat_operation;
-	u32 read_log_offset;
-	u32 read_log_length;
-	u32 data_buffer_size;
-	u32 data_buffer[1];
-} __packed;
-
-struct be_cmd_resp_get_fat {
-	struct be_cmd_resp_hdr hdr;
-	u32 log_size;
-	u32 read_log_length;
-	u32 rsvd[2];
-	u32 data_buffer[1];
-} __packed;
-
-
-/******************** Create MCCQ ***************************/
-/* Pseudo amap definition in which each bit of the actual structure is defined
- * as a byte: used to calculate offset/shift/mask of each field */
-struct amap_mcc_context_be {
-	u8 con_index[14];
-	u8 rsvd0[2];
-	u8 ring_size[4];
-	u8 fetch_wrb;
-	u8 fetch_r2t;
-	u8 cq_id[10];
-	u8 prod_index[14];
-	u8 fid[8];
-	u8 pdid[9];
-	u8 valid;
-	u8 rsvd1[32];
-	u8 rsvd2[32];
-} __packed;
-
-struct amap_mcc_context_lancer {
-	u8 async_cq_id[16];
-	u8 ring_size[4];
-	u8 rsvd0[12];
-	u8 rsvd1[31];
-	u8 valid;
-	u8 async_cq_valid[1];
-	u8 rsvd2[31];
-	u8 rsvd3[32];
-} __packed;
-
-struct be_cmd_req_mcc_create {
-	struct be_cmd_req_hdr hdr;
-	u16 num_pages;
-	u16 cq_id;
-	u8 context[sizeof(struct amap_mcc_context_be) / 8];
-	struct phys_addr pages[8];
-} __packed;
-
-struct be_cmd_req_mcc_ext_create {
-	struct be_cmd_req_hdr hdr;
-	u16 num_pages;
-	u16 cq_id;
-	u32 async_event_bitmap[1];
-	u8 context[sizeof(struct amap_mcc_context_be) / 8];
-	struct phys_addr pages[8];
-} __packed;
-
-struct be_cmd_resp_mcc_create {
-	struct be_cmd_resp_hdr hdr;
-	u16 id;
-	u16 rsvd0;
-} __packed;
-
-/******************** Create TxQ ***************************/
-#define BE_ETH_TX_RING_TYPE_STANDARD    	2
-#define BE_ULP1_NUM				1
-
-/* 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 if_id[16];		/* dword 0 */
-	u8 tx_ring_size[4];	/* dword 0 */
-	u8 rsvd1[26];		/* dword 0 */
-	u8 pci_func_id[8];	/* dword 1 */
-	u8 rsvd2[9];		/* dword 1 */
-	u8 ctx_valid;		/* dword 1 */
-	u8 cq_id_send[16];	/* dword 2 */
-	u8 rsvd3[16];		/* dword 2 */
-	u8 rsvd4[32];		/* dword 3 */
-	u8 rsvd5[32];		/* dword 4 */
-	u8 rsvd6[32];		/* dword 5 */
-	u8 rsvd7[32];		/* dword 6 */
-	u8 rsvd8[32];		/* dword 7 */
-	u8 rsvd9[32];		/* dword 8 */
-	u8 rsvd10[32];		/* dword 9 */
-	u8 rsvd11[32];		/* dword 10 */
-	u8 rsvd12[32];		/* dword 11 */
-	u8 rsvd13[32];		/* dword 12 */
-	u8 rsvd14[32];		/* dword 13 */
-	u8 rsvd15[32];		/* dword 14 */
-	u8 rsvd16[32];		/* dword 15 */
-} __packed;
-
-struct be_cmd_req_eth_tx_create {
-	struct be_cmd_req_hdr hdr;
-	u8 num_pages;
-	u8 ulp_num;
-	u8 type;
-	u8 bound_port;
-	u8 context[sizeof(struct amap_tx_context) / 8];
-	struct phys_addr pages[8];
-} __packed;
-
-struct be_cmd_resp_eth_tx_create {
-	struct be_cmd_resp_hdr hdr;
-	u16 cid;
-	u16 rsvd0;
-} __packed;
-
-/******************** Create RxQ ***************************/
-struct be_cmd_req_eth_rx_create {
-	struct be_cmd_req_hdr hdr;
-	u16 cq_id;
-	u8 frag_size;
-	u8 num_pages;
-	struct phys_addr pages[2];
-	u32 interface_id;
-	u16 max_frame_size;
-	u16 rsvd0;
-	u32 rss_queue;
-} __packed;
-
-struct be_cmd_resp_eth_rx_create {
-	struct be_cmd_resp_hdr hdr;
-	u16 id;
-	u8 rss_id;
-	u8 rsvd0;
-} __packed;
-
-/******************** Q Destroy  ***************************/
-/* Type of Queue to be destroyed */
-enum {
-	QTYPE_EQ = 1,
-	QTYPE_CQ,
-	QTYPE_TXQ,
-	QTYPE_RXQ,
-	QTYPE_MCCQ
-};
-
-struct be_cmd_req_q_destroy {
-	struct be_cmd_req_hdr hdr;
-	u16 id;
-	u16 bypass_flush;	/* valid only for rx q destroy */
-} __packed;
-
-/************ I/f Create (it's actually I/f Config Create)**********/
-
-/* Capability flags for the i/f */
-enum be_if_flags {
-	BE_IF_FLAGS_RSS = 0x4,
-	BE_IF_FLAGS_PROMISCUOUS = 0x8,
-	BE_IF_FLAGS_BROADCAST = 0x10,
-	BE_IF_FLAGS_UNTAGGED = 0x20,
-	BE_IF_FLAGS_ULP = 0x40,
-	BE_IF_FLAGS_VLAN_PROMISCUOUS = 0x80,
-	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_MULTICAST = 0x1000
-};
-
-/* An RX interface is an object with one or more MAC addresses and
- * filtering capabilities. */
-struct be_cmd_req_if_create {
-	struct be_cmd_req_hdr hdr;
-	u32 version;		/* ignore currently */
-	u32 capability_flags;
-	u32 enable_flags;
-	u8 mac_addr[ETH_ALEN];
-	u8 rsvd0;
-	u8 pmac_invalid; /* if set, don't attach the mac addr to the i/f */
-	u32 vlan_tag;	 /* not used currently */
-} __packed;
-
-struct be_cmd_resp_if_create {
-	struct be_cmd_resp_hdr hdr;
-	u32 interface_id;
-	u32 pmac_id;
-};
-
-/****** I/f Destroy(it's actually I/f Config Destroy )**********/
-struct be_cmd_req_if_destroy {
-	struct be_cmd_req_hdr hdr;
-	u32 interface_id;
-};
-
-/*************** HW Stats Get **********************************/
-struct be_port_rxf_stats_v0 {
-	u32 rx_bytes_lsd;	/* dword 0*/
-	u32 rx_bytes_msd;	/* dword 1*/
-	u32 rx_total_frames;	/* dword 2*/
-	u32 rx_unicast_frames;	/* dword 3*/
-	u32 rx_multicast_frames;	/* dword 4*/
-	u32 rx_broadcast_frames;	/* dword 5*/
-	u32 rx_crc_errors;	/* dword 6*/
-	u32 rx_alignment_symbol_errors;	/* dword 7*/
-	u32 rx_pause_frames;	/* dword 8*/
-	u32 rx_control_frames;	/* dword 9*/
-	u32 rx_in_range_errors;	/* dword 10*/
-	u32 rx_out_range_errors;	/* dword 11*/
-	u32 rx_frame_too_long;	/* dword 12*/
-	u32 rx_address_match_errors;	/* dword 13*/
-	u32 rx_vlan_mismatch;	/* dword 14*/
-	u32 rx_dropped_too_small;	/* dword 15*/
-	u32 rx_dropped_too_short;	/* dword 16*/
-	u32 rx_dropped_header_too_small;	/* dword 17*/
-	u32 rx_dropped_tcp_length;	/* dword 18*/
-	u32 rx_dropped_runt;	/* dword 19*/
-	u32 rx_64_byte_packets;	/* dword 20*/
-	u32 rx_65_127_byte_packets;	/* dword 21*/
-	u32 rx_128_256_byte_packets;	/* dword 22*/
-	u32 rx_256_511_byte_packets;	/* dword 23*/
-	u32 rx_512_1023_byte_packets;	/* dword 24*/
-	u32 rx_1024_1518_byte_packets;	/* dword 25*/
-	u32 rx_1519_2047_byte_packets;	/* dword 26*/
-	u32 rx_2048_4095_byte_packets;	/* dword 27*/
-	u32 rx_4096_8191_byte_packets;	/* dword 28*/
-	u32 rx_8192_9216_byte_packets;	/* dword 29*/
-	u32 rx_ip_checksum_errs;	/* dword 30*/
-	u32 rx_tcp_checksum_errs;	/* dword 31*/
-	u32 rx_udp_checksum_errs;	/* dword 32*/
-	u32 rx_non_rss_packets;	/* dword 33*/
-	u32 rx_ipv4_packets;	/* dword 34*/
-	u32 rx_ipv6_packets;	/* dword 35*/
-	u32 rx_ipv4_bytes_lsd;	/* dword 36*/
-	u32 rx_ipv4_bytes_msd;	/* dword 37*/
-	u32 rx_ipv6_bytes_lsd;	/* dword 38*/
-	u32 rx_ipv6_bytes_msd;	/* dword 39*/
-	u32 rx_chute1_packets;	/* dword 40*/
-	u32 rx_chute2_packets;	/* dword 41*/
-	u32 rx_chute3_packets;	/* dword 42*/
-	u32 rx_management_packets;	/* dword 43*/
-	u32 rx_switched_unicast_packets;	/* dword 44*/
-	u32 rx_switched_multicast_packets;	/* dword 45*/
-	u32 rx_switched_broadcast_packets;	/* dword 46*/
-	u32 tx_bytes_lsd;	/* dword 47*/
-	u32 tx_bytes_msd;	/* dword 48*/
-	u32 tx_unicastframes;	/* dword 49*/
-	u32 tx_multicastframes;	/* dword 50*/
-	u32 tx_broadcastframes;	/* dword 51*/
-	u32 tx_pauseframes;	/* dword 52*/
-	u32 tx_controlframes;	/* dword 53*/
-	u32 tx_64_byte_packets;	/* dword 54*/
-	u32 tx_65_127_byte_packets;	/* dword 55*/
-	u32 tx_128_256_byte_packets;	/* dword 56*/
-	u32 tx_256_511_byte_packets;	/* dword 57*/
-	u32 tx_512_1023_byte_packets;	/* dword 58*/
-	u32 tx_1024_1518_byte_packets;	/* dword 59*/
-	u32 tx_1519_2047_byte_packets;	/* dword 60*/
-	u32 tx_2048_4095_byte_packets;	/* dword 61*/
-	u32 tx_4096_8191_byte_packets;	/* dword 62*/
-	u32 tx_8192_9216_byte_packets;	/* dword 63*/
-	u32 rx_fifo_overflow;	/* dword 64*/
-	u32 rx_input_fifo_overflow;	/* dword 65*/
-};
-
-struct be_rxf_stats_v0 {
-	struct be_port_rxf_stats_v0 port[2];
-	u32 rx_drops_no_pbuf;	/* dword 132*/
-	u32 rx_drops_no_txpb;	/* dword 133*/
-	u32 rx_drops_no_erx_descr;	/* dword 134*/
-	u32 rx_drops_no_tpre_descr;	/* dword 135*/
-	u32 management_rx_port_packets;	/* dword 136*/
-	u32 management_rx_port_bytes;	/* dword 137*/
-	u32 management_rx_port_pause_frames;	/* dword 138*/
-	u32 management_rx_port_errors;	/* dword 139*/
-	u32 management_tx_port_packets;	/* dword 140*/
-	u32 management_tx_port_bytes;	/* dword 141*/
-	u32 management_tx_port_pause;	/* dword 142*/
-	u32 management_rx_port_rxfifo_overflow;	/* dword 143*/
-	u32 rx_drops_too_many_frags;	/* dword 144*/
-	u32 rx_drops_invalid_ring;	/* dword 145*/
-	u32 forwarded_packets;	/* dword 146*/
-	u32 rx_drops_mtu;	/* dword 147*/
-	u32 rsvd0[7];
-	u32 port0_jabber_events;
-	u32 port1_jabber_events;
-	u32 rsvd1[6];
-};
-
-struct be_erx_stats_v0 {
-	u32 rx_drops_no_fragments[44];     /* dwordS 0 to 43*/
-	u32 rsvd[4];
-};
-
-struct be_pmem_stats {
-	u32 eth_red_drops;
-	u32 rsvd[5];
-};
-
-struct be_hw_stats_v0 {
-	struct be_rxf_stats_v0 rxf;
-	u32 rsvd[48];
-	struct be_erx_stats_v0 erx;
-	struct be_pmem_stats pmem;
-};
-
-struct be_cmd_req_get_stats_v0 {
-	struct be_cmd_req_hdr hdr;
-	u8 rsvd[sizeof(struct be_hw_stats_v0)];
-};
-
-struct be_cmd_resp_get_stats_v0 {
-	struct be_cmd_resp_hdr hdr;
-	struct be_hw_stats_v0 hw_stats;
-};
-
-#define make_64bit_val(hi_32, lo_32)	(((u64)hi_32<<32) | lo_32)
-struct lancer_cmd_pport_stats {
-	u32 tx_packets_lo;
-	u32 tx_packets_hi;
-	u32 tx_unicast_packets_lo;
-	u32 tx_unicast_packets_hi;
-	u32 tx_multicast_packets_lo;
-	u32 tx_multicast_packets_hi;
-	u32 tx_broadcast_packets_lo;
-	u32 tx_broadcast_packets_hi;
-	u32 tx_bytes_lo;
-	u32 tx_bytes_hi;
-	u32 tx_unicast_bytes_lo;
-	u32 tx_unicast_bytes_hi;
-	u32 tx_multicast_bytes_lo;
-	u32 tx_multicast_bytes_hi;
-	u32 tx_broadcast_bytes_lo;
-	u32 tx_broadcast_bytes_hi;
-	u32 tx_discards_lo;
-	u32 tx_discards_hi;
-	u32 tx_errors_lo;
-	u32 tx_errors_hi;
-	u32 tx_pause_frames_lo;
-	u32 tx_pause_frames_hi;
-	u32 tx_pause_on_frames_lo;
-	u32 tx_pause_on_frames_hi;
-	u32 tx_pause_off_frames_lo;
-	u32 tx_pause_off_frames_hi;
-	u32 tx_internal_mac_errors_lo;
-	u32 tx_internal_mac_errors_hi;
-	u32 tx_control_frames_lo;
-	u32 tx_control_frames_hi;
-	u32 tx_packets_64_bytes_lo;
-	u32 tx_packets_64_bytes_hi;
-	u32 tx_packets_65_to_127_bytes_lo;
-	u32 tx_packets_65_to_127_bytes_hi;
-	u32 tx_packets_128_to_255_bytes_lo;
-	u32 tx_packets_128_to_255_bytes_hi;
-	u32 tx_packets_256_to_511_bytes_lo;
-	u32 tx_packets_256_to_511_bytes_hi;
-	u32 tx_packets_512_to_1023_bytes_lo;
-	u32 tx_packets_512_to_1023_bytes_hi;
-	u32 tx_packets_1024_to_1518_bytes_lo;
-	u32 tx_packets_1024_to_1518_bytes_hi;
-	u32 tx_packets_1519_to_2047_bytes_lo;
-	u32 tx_packets_1519_to_2047_bytes_hi;
-	u32 tx_packets_2048_to_4095_bytes_lo;
-	u32 tx_packets_2048_to_4095_bytes_hi;
-	u32 tx_packets_4096_to_8191_bytes_lo;
-	u32 tx_packets_4096_to_8191_bytes_hi;
-	u32 tx_packets_8192_to_9216_bytes_lo;
-	u32 tx_packets_8192_to_9216_bytes_hi;
-	u32 tx_lso_packets_lo;
-	u32 tx_lso_packets_hi;
-	u32 rx_packets_lo;
-	u32 rx_packets_hi;
-	u32 rx_unicast_packets_lo;
-	u32 rx_unicast_packets_hi;
-	u32 rx_multicast_packets_lo;
-	u32 rx_multicast_packets_hi;
-	u32 rx_broadcast_packets_lo;
-	u32 rx_broadcast_packets_hi;
-	u32 rx_bytes_lo;
-	u32 rx_bytes_hi;
-	u32 rx_unicast_bytes_lo;
-	u32 rx_unicast_bytes_hi;
-	u32 rx_multicast_bytes_lo;
-	u32 rx_multicast_bytes_hi;
-	u32 rx_broadcast_bytes_lo;
-	u32 rx_broadcast_bytes_hi;
-	u32 rx_unknown_protos;
-	u32 rsvd_69; /* Word 69 is reserved */
-	u32 rx_discards_lo;
-	u32 rx_discards_hi;
-	u32 rx_errors_lo;
-	u32 rx_errors_hi;
-	u32 rx_crc_errors_lo;
-	u32 rx_crc_errors_hi;
-	u32 rx_alignment_errors_lo;
-	u32 rx_alignment_errors_hi;
-	u32 rx_symbol_errors_lo;
-	u32 rx_symbol_errors_hi;
-	u32 rx_pause_frames_lo;
-	u32 rx_pause_frames_hi;
-	u32 rx_pause_on_frames_lo;
-	u32 rx_pause_on_frames_hi;
-	u32 rx_pause_off_frames_lo;
-	u32 rx_pause_off_frames_hi;
-	u32 rx_frames_too_long_lo;
-	u32 rx_frames_too_long_hi;
-	u32 rx_internal_mac_errors_lo;
-	u32 rx_internal_mac_errors_hi;
-	u32 rx_undersize_packets;
-	u32 rx_oversize_packets;
-	u32 rx_fragment_packets;
-	u32 rx_jabbers;
-	u32 rx_control_frames_lo;
-	u32 rx_control_frames_hi;
-	u32 rx_control_frames_unknown_opcode_lo;
-	u32 rx_control_frames_unknown_opcode_hi;
-	u32 rx_in_range_errors;
-	u32 rx_out_of_range_errors;
-	u32 rx_address_match_errors;
-	u32 rx_vlan_mismatch_errors;
-	u32 rx_dropped_too_small;
-	u32 rx_dropped_too_short;
-	u32 rx_dropped_header_too_small;
-	u32 rx_dropped_invalid_tcp_length;
-	u32 rx_dropped_runt;
-	u32 rx_ip_checksum_errors;
-	u32 rx_tcp_checksum_errors;
-	u32 rx_udp_checksum_errors;
-	u32 rx_non_rss_packets;
-	u32 rsvd_111;
-	u32 rx_ipv4_packets_lo;
-	u32 rx_ipv4_packets_hi;
-	u32 rx_ipv6_packets_lo;
-	u32 rx_ipv6_packets_hi;
-	u32 rx_ipv4_bytes_lo;
-	u32 rx_ipv4_bytes_hi;
-	u32 rx_ipv6_bytes_lo;
-	u32 rx_ipv6_bytes_hi;
-	u32 rx_nic_packets_lo;
-	u32 rx_nic_packets_hi;
-	u32 rx_tcp_packets_lo;
-	u32 rx_tcp_packets_hi;
-	u32 rx_iscsi_packets_lo;
-	u32 rx_iscsi_packets_hi;
-	u32 rx_management_packets_lo;
-	u32 rx_management_packets_hi;
-	u32 rx_switched_unicast_packets_lo;
-	u32 rx_switched_unicast_packets_hi;
-	u32 rx_switched_multicast_packets_lo;
-	u32 rx_switched_multicast_packets_hi;
-	u32 rx_switched_broadcast_packets_lo;
-	u32 rx_switched_broadcast_packets_hi;
-	u32 num_forwards_lo;
-	u32 num_forwards_hi;
-	u32 rx_fifo_overflow;
-	u32 rx_input_fifo_overflow;
-	u32 rx_drops_too_many_frags_lo;
-	u32 rx_drops_too_many_frags_hi;
-	u32 rx_drops_invalid_queue;
-	u32 rsvd_141;
-	u32 rx_drops_mtu_lo;
-	u32 rx_drops_mtu_hi;
-	u32 rx_packets_64_bytes_lo;
-	u32 rx_packets_64_bytes_hi;
-	u32 rx_packets_65_to_127_bytes_lo;
-	u32 rx_packets_65_to_127_bytes_hi;
-	u32 rx_packets_128_to_255_bytes_lo;
-	u32 rx_packets_128_to_255_bytes_hi;
-	u32 rx_packets_256_to_511_bytes_lo;
-	u32 rx_packets_256_to_511_bytes_hi;
-	u32 rx_packets_512_to_1023_bytes_lo;
-	u32 rx_packets_512_to_1023_bytes_hi;
-	u32 rx_packets_1024_to_1518_bytes_lo;
-	u32 rx_packets_1024_to_1518_bytes_hi;
-	u32 rx_packets_1519_to_2047_bytes_lo;
-	u32 rx_packets_1519_to_2047_bytes_hi;
-	u32 rx_packets_2048_to_4095_bytes_lo;
-	u32 rx_packets_2048_to_4095_bytes_hi;
-	u32 rx_packets_4096_to_8191_bytes_lo;
-	u32 rx_packets_4096_to_8191_bytes_hi;
-	u32 rx_packets_8192_to_9216_bytes_lo;
-	u32 rx_packets_8192_to_9216_bytes_hi;
-};
-
-struct pport_stats_params {
-	u16 pport_num;
-	u8 rsvd;
-	u8 reset_stats;
-};
-
-struct lancer_cmd_req_pport_stats {
-	struct be_cmd_req_hdr hdr;
-	union {
-		struct pport_stats_params params;
-		u8 rsvd[sizeof(struct lancer_cmd_pport_stats)];
-	} cmd_params;
-};
-
-struct lancer_cmd_resp_pport_stats {
-	struct be_cmd_resp_hdr hdr;
-	struct lancer_cmd_pport_stats pport_stats;
-};
-
-static inline  struct lancer_cmd_pport_stats*
-	pport_stats_from_cmd(struct be_adapter *adapter)
-{
-	struct lancer_cmd_resp_pport_stats *cmd = adapter->stats_cmd.va;
-	return &cmd->pport_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;
-	u8 promiscuous;
-	u8 untagged;
-	u8 num_vlan;
-	u16 normal_vlan[64];
-} __packed;
-
-/******************** Multicast MAC Config *******************/
-#define BE_MAX_MC		64 /* set mcast promisc if > 64 */
-struct macaddr {
-	u8 byte[ETH_ALEN];
-};
-
-struct be_cmd_req_mcast_mac_config {
-	struct be_cmd_req_hdr hdr;
-	u16 num_mac;
-	u8 promiscuous;
-	u8 interface_id;
-	struct macaddr mac[BE_MAX_MC];
-} __packed;
-
-/******************* RX FILTER ******************************/
-struct be_cmd_req_rx_filter {
-	struct be_cmd_req_hdr hdr;
-	u32 global_flags_mask;
-	u32 global_flags;
-	u32 if_flags_mask;
-	u32 if_flags;
-	u32 if_id;
-	u32 multicast_num;
-	struct macaddr mac[BE_MAX_MC];
-};
-
-
-/******************** Link Status Query *******************/
-struct be_cmd_req_link_status {
-	struct be_cmd_req_hdr hdr;
-	u32 rsvd;
-};
-
-enum {
-	PHY_LINK_DUPLEX_NONE = 0x0,
-	PHY_LINK_DUPLEX_HALF = 0x1,
-	PHY_LINK_DUPLEX_FULL = 0x2
-};
-
-enum {
-	PHY_LINK_SPEED_ZERO = 0x0, 	/* => No link */
-	PHY_LINK_SPEED_10MBPS = 0x1,
-	PHY_LINK_SPEED_100MBPS = 0x2,
-	PHY_LINK_SPEED_1GBPS = 0x3,
-	PHY_LINK_SPEED_10GBPS = 0x4
-};
-
-struct be_cmd_resp_link_status {
-	struct be_cmd_resp_hdr hdr;
-	u8 physical_port;
-	u8 mac_duplex;
-	u8 mac_speed;
-	u8 mac_fault;
-	u8 mgmt_mac_duplex;
-	u8 mgmt_mac_speed;
-	u16 link_speed;
-	u32 rsvd0;
-} __packed;
-
-/******************** Port Identification ***************************/
-/*    Identifies the type of port attached to NIC     */
-struct be_cmd_req_port_type {
-	struct be_cmd_req_hdr hdr;
-	u32 page_num;
-	u32 port;
-};
-
-enum {
-	TR_PAGE_A0 = 0xa0,
-	TR_PAGE_A2 = 0xa2
-};
-
-struct be_cmd_resp_port_type {
-	struct be_cmd_resp_hdr hdr;
-	u32 page_num;
-	u32 port;
-	struct data {
-		u8 identifier;
-		u8 identifier_ext;
-		u8 connector;
-		u8 transceiver[8];
-		u8 rsvd0[3];
-		u8 length_km;
-		u8 length_hm;
-		u8 length_om1;
-		u8 length_om2;
-		u8 length_cu;
-		u8 length_cu_m;
-		u8 vendor_name[16];
-		u8 rsvd;
-		u8 vendor_oui[3];
-		u8 vendor_pn[16];
-		u8 vendor_rev[4];
-	} data;
-};
-
-/******************** Get FW Version *******************/
-struct be_cmd_req_get_fw_version {
-	struct be_cmd_req_hdr hdr;
-	u8 rsvd0[FW_VER_LEN];
-	u8 rsvd1[FW_VER_LEN];
-} __packed;
-
-struct be_cmd_resp_get_fw_version {
-	struct be_cmd_resp_hdr hdr;
-	u8 firmware_version_string[FW_VER_LEN];
-	u8 fw_on_flash_version_string[FW_VER_LEN];
-} __packed;
-
-/******************** Set Flow Contrl *******************/
-struct be_cmd_req_set_flow_control {
-	struct be_cmd_req_hdr hdr;
-	u16 tx_flow_control;
-	u16 rx_flow_control;
-} __packed;
-
-/******************** Get Flow Contrl *******************/
-struct be_cmd_req_get_flow_control {
-	struct be_cmd_req_hdr hdr;
-	u32 rsvd;
-};
-
-struct be_cmd_resp_get_flow_control {
-	struct be_cmd_resp_hdr hdr;
-	u16 tx_flow_control;
-	u16 rx_flow_control;
-} __packed;
-
-/******************** Modify EQ Delay *******************/
-struct be_cmd_req_modify_eq_delay {
-	struct be_cmd_req_hdr hdr;
-	u32 num_eq;
-	struct {
-		u32 eq_id;
-		u32 phase;
-		u32 delay_multiplier;
-	} delay[8];
-} __packed;
-
-struct be_cmd_resp_modify_eq_delay {
-	struct be_cmd_resp_hdr hdr;
-	u32 rsvd0;
-} __packed;
-
-/******************** Get FW Config *******************/
-#define BE_FUNCTION_CAPS_RSS			0x2
-struct be_cmd_req_query_fw_cfg {
-	struct be_cmd_req_hdr hdr;
-	u32 rsvd[31];
-};
-
-struct be_cmd_resp_query_fw_cfg {
-	struct be_cmd_resp_hdr hdr;
-	u32 be_config_number;
-	u32 asic_revision;
-	u32 phys_port;
-	u32 function_mode;
-	u32 rsvd[26];
-	u32 function_caps;
-};
-
-/******************** RSS Config *******************/
-/* RSS types */
-#define RSS_ENABLE_NONE				0x0
-#define RSS_ENABLE_IPV4				0x1
-#define RSS_ENABLE_TCP_IPV4			0x2
-#define RSS_ENABLE_IPV6				0x4
-#define RSS_ENABLE_TCP_IPV6			0x8
-
-struct be_cmd_req_rss_config {
-	struct be_cmd_req_hdr hdr;
-	u32 if_id;
-	u16 enable_rss;
-	u16 cpu_table_size_log2;
-	u32 hash[10];
-	u8 cpu_table[128];
-	u8 flush;
-	u8 rsvd0[3];
-};
-
-/******************** Port Beacon ***************************/
-
-#define BEACON_STATE_ENABLED		0x1
-#define BEACON_STATE_DISABLED		0x0
-
-struct be_cmd_req_enable_disable_beacon {
-	struct be_cmd_req_hdr hdr;
-	u8  port_num;
-	u8  beacon_state;
-	u8  beacon_duration;
-	u8  status_duration;
-} __packed;
-
-struct be_cmd_resp_enable_disable_beacon {
-	struct be_cmd_resp_hdr resp_hdr;
-	u32 rsvd0;
-} __packed;
-
-struct be_cmd_req_get_beacon_state {
-	struct be_cmd_req_hdr hdr;
-	u8  port_num;
-	u8  rsvd0;
-	u16 rsvd1;
-} __packed;
-
-struct be_cmd_resp_get_beacon_state {
-	struct be_cmd_resp_hdr resp_hdr;
-	u8 beacon_state;
-	u8 rsvd0[3];
-} __packed;
-
-/****************** Firmware Flash ******************/
-struct flashrom_params {
-	u32 op_code;
-	u32 op_type;
-	u32 data_buf_size;
-	u32 offset;
-	u8 data_buf[4];
-};
-
-struct be_cmd_write_flashrom {
-	struct be_cmd_req_hdr hdr;
-	struct flashrom_params params;
-};
-
-/**************** Lancer Firmware Flash ************/
-struct amap_lancer_write_obj_context {
-	u8 write_length[24];
-	u8 reserved1[7];
-	u8 eof;
-} __packed;
-
-struct lancer_cmd_req_write_object {
-	struct be_cmd_req_hdr hdr;
-	u8 context[sizeof(struct amap_lancer_write_obj_context) / 8];
-	u32 write_offset;
-	u8 object_name[104];
-	u32 descriptor_count;
-	u32 buf_len;
-	u32 addr_low;
-	u32 addr_high;
-};
-
-struct lancer_cmd_resp_write_object {
-	u8 opcode;
-	u8 subsystem;
-	u8 rsvd1[2];
-	u8 status;
-	u8 additional_status;
-	u8 rsvd2[2];
-	u32 resp_len;
-	u32 actual_resp_len;
-	u32 actual_write_len;
-};
-
-/************************ WOL *******************************/
-struct be_cmd_req_acpi_wol_magic_config{
-	struct be_cmd_req_hdr hdr;
-	u32 rsvd0[145];
-	u8 magic_mac[6];
-	u8 rsvd2[2];
-} __packed;
-
-/********************** LoopBack test *********************/
-struct be_cmd_req_loopback_test {
-	struct be_cmd_req_hdr hdr;
-	u32 loopback_type;
-	u32 num_pkts;
-	u64 pattern;
-	u32 src_port;
-	u32 dest_port;
-	u32 pkt_size;
-};
-
-struct be_cmd_resp_loopback_test {
-	struct be_cmd_resp_hdr resp_hdr;
-	u32    status;
-	u32    num_txfer;
-	u32    num_rx;
-	u32    miscomp_off;
-	u32    ticks_compl;
-};
-
-struct be_cmd_req_set_lmode {
-	struct be_cmd_req_hdr hdr;
-	u8 src_port;
-	u8 dest_port;
-	u8 loopback_type;
-	u8 loopback_state;
-};
-
-struct be_cmd_resp_set_lmode {
-	struct be_cmd_resp_hdr resp_hdr;
-	u8 rsvd0[4];
-};
-
-/********************** DDR DMA test *********************/
-struct be_cmd_req_ddrdma_test {
-	struct be_cmd_req_hdr hdr;
-	u64 pattern;
-	u32 byte_count;
-	u32 rsvd0;
-	u8  snd_buff[4096];
-	u8  rsvd1[4096];
-};
-
-struct be_cmd_resp_ddrdma_test {
-	struct be_cmd_resp_hdr hdr;
-	u64 pattern;
-	u32 byte_cnt;
-	u32 snd_err;
-	u8  rsvd0[4096];
-	u8  rcv_buff[4096];
-};
-
-/*********************** SEEPROM Read ***********************/
-
-#define BE_READ_SEEPROM_LEN 1024
-struct be_cmd_req_seeprom_read {
-	struct be_cmd_req_hdr hdr;
-	u8 rsvd0[BE_READ_SEEPROM_LEN];
-};
-
-struct be_cmd_resp_seeprom_read {
-	struct be_cmd_req_hdr hdr;
-	u8 seeprom_data[BE_READ_SEEPROM_LEN];
-};
-
-enum {
-	PHY_TYPE_CX4_10GB = 0,
-	PHY_TYPE_XFP_10GB,
-	PHY_TYPE_SFP_1GB,
-	PHY_TYPE_SFP_PLUS_10GB,
-	PHY_TYPE_KR_10GB,
-	PHY_TYPE_KX4_10GB,
-	PHY_TYPE_BASET_10GB,
-	PHY_TYPE_BASET_1GB,
-	PHY_TYPE_DISABLED = 255
-};
-
-struct be_cmd_req_get_phy_info {
-	struct be_cmd_req_hdr hdr;
-	u8 rsvd0[24];
-};
-struct be_cmd_resp_get_phy_info {
-	struct be_cmd_req_hdr hdr;
-	u16 phy_type;
-	u16 interface_type;
-	u32 misc_params;
-	u32 future_use[4];
-};
-
-/*********************** Set QOS ***********************/
-
-#define BE_QOS_BITS_NIC				1
-
-struct be_cmd_req_set_qos {
-	struct be_cmd_req_hdr hdr;
-	u32 valid_bits;
-	u32 max_bps_nic;
-	u32 rsvd[7];
-};
-
-struct be_cmd_resp_set_qos {
-	struct be_cmd_resp_hdr hdr;
-	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];
-};
-
-/*************** HW Stats Get v1 **********************************/
-#define BE_TXP_SW_SZ			48
-struct be_port_rxf_stats_v1 {
-	u32 rsvd0[12];
-	u32 rx_crc_errors;
-	u32 rx_alignment_symbol_errors;
-	u32 rx_pause_frames;
-	u32 rx_priority_pause_frames;
-	u32 rx_control_frames;
-	u32 rx_in_range_errors;
-	u32 rx_out_range_errors;
-	u32 rx_frame_too_long;
-	u32 rx_address_match_errors;
-	u32 rx_dropped_too_small;
-	u32 rx_dropped_too_short;
-	u32 rx_dropped_header_too_small;
-	u32 rx_dropped_tcp_length;
-	u32 rx_dropped_runt;
-	u32 rsvd1[10];
-	u32 rx_ip_checksum_errs;
-	u32 rx_tcp_checksum_errs;
-	u32 rx_udp_checksum_errs;
-	u32 rsvd2[7];
-	u32 rx_switched_unicast_packets;
-	u32 rx_switched_multicast_packets;
-	u32 rx_switched_broadcast_packets;
-	u32 rsvd3[3];
-	u32 tx_pauseframes;
-	u32 tx_priority_pauseframes;
-	u32 tx_controlframes;
-	u32 rsvd4[10];
-	u32 rxpp_fifo_overflow_drop;
-	u32 rx_input_fifo_overflow_drop;
-	u32 pmem_fifo_overflow_drop;
-	u32 jabber_events;
-	u32 rsvd5[3];
-};
-
-
-struct be_rxf_stats_v1 {
-	struct be_port_rxf_stats_v1 port[4];
-	u32 rsvd0[2];
-	u32 rx_drops_no_pbuf;
-	u32 rx_drops_no_txpb;
-	u32 rx_drops_no_erx_descr;
-	u32 rx_drops_no_tpre_descr;
-	u32 rsvd1[6];
-	u32 rx_drops_too_many_frags;
-	u32 rx_drops_invalid_ring;
-	u32 forwarded_packets;
-	u32 rx_drops_mtu;
-	u32 rsvd2[14];
-};
-
-struct be_erx_stats_v1 {
-	u32 rx_drops_no_fragments[68];     /* dwordS 0 to 67*/
-	u32 rsvd[4];
-};
-
-struct be_hw_stats_v1 {
-	struct be_rxf_stats_v1 rxf;
-	u32 rsvd0[BE_TXP_SW_SZ];
-	struct be_erx_stats_v1 erx;
-	struct be_pmem_stats pmem;
-	u32 rsvd1[3];
-};
-
-struct be_cmd_req_get_stats_v1 {
-	struct be_cmd_req_hdr hdr;
-	u8 rsvd[sizeof(struct be_hw_stats_v1)];
-};
-
-struct be_cmd_resp_get_stats_v1 {
-	struct be_cmd_resp_hdr hdr;
-	struct be_hw_stats_v1 hw_stats;
-};
-
-static inline void *
-hw_stats_from_cmd(struct be_adapter *adapter)
-{
-	if (adapter->generation == BE_GEN3) {
-		struct be_cmd_resp_get_stats_v1 *cmd = adapter->stats_cmd.va;
-
-		return &cmd->hw_stats;
-	} else {
-		struct be_cmd_resp_get_stats_v0 *cmd = adapter->stats_cmd.va;
-
-		return &cmd->hw_stats;
-	}
-}
-
-static inline void *be_port_rxf_stats_from_cmd(struct be_adapter *adapter)
-{
-	if (adapter->generation == BE_GEN3) {
-		struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
-		struct be_rxf_stats_v1 *rxf_stats = &hw_stats->rxf;
-
-		return &rxf_stats->port[adapter->port_num];
-	} else {
-		struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
-		struct be_rxf_stats_v0 *rxf_stats = &hw_stats->rxf;
-
-		return &rxf_stats->port[adapter->port_num];
-	}
-}
-
-static inline void *be_rxf_stats_from_cmd(struct be_adapter *adapter)
-{
-	if (adapter->generation == BE_GEN3) {
-		struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
-
-		return &hw_stats->rxf;
-	} else {
-		struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
-
-		return &hw_stats->rxf;
-	}
-}
-
-static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter)
-{
-	if (adapter->generation == BE_GEN3) {
-		struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
-
-		return &hw_stats->erx;
-	} else {
-		struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
-
-		return &hw_stats->erx;
-	}
-}
-
-static inline void *be_pmem_stats_from_cmd(struct be_adapter *adapter)
-{
-	if (adapter->generation == BE_GEN3) {
-		struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
-
-		return &hw_stats->pmem;
-	} else {
-		struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
-
-		return &hw_stats->pmem;
-	}
-}
-
-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, 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,
-			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,
-			struct be_queue_info *cq, struct be_queue_info *eq,
-			bool sol_evts, bool no_delay,
-			int num_cqe_dma_coalesce);
-extern int be_cmd_mccq_create(struct be_adapter *adapter,
-			struct be_queue_info *mccq,
-			struct be_queue_info *cq);
-extern int be_cmd_txq_create(struct be_adapter *adapter,
-			struct be_queue_info *txq,
-			struct be_queue_info *cq);
-extern int be_cmd_rxq_create(struct be_adapter *adapter,
-			struct be_queue_info *rxq, u16 cq_id,
-			u16 frag_size, u16 max_frame_size, u32 if_id,
-			u32 rss, u8 *rss_id);
-extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
-			int type);
-extern int be_cmd_rxq_destroy(struct be_adapter *adapter,
-			struct be_queue_info *q);
-extern int be_cmd_link_status_query(struct be_adapter *adapter,
-			bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom);
-extern int be_cmd_reset(struct be_adapter *adapter);
-extern int be_cmd_get_stats(struct be_adapter *adapter,
-			struct be_dma_mem *nonemb_cmd);
-extern int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
-			struct be_dma_mem *nonemb_cmd);
-extern int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver);
-
-extern int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd);
-extern int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id,
-			u16 *vtag_array, u32 num, bool untagged,
-			bool promiscuous);
-extern int be_cmd_promiscuous_config(struct be_adapter *adapter, bool en);
-extern int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
-			struct net_device *netdev, struct be_dma_mem *mem);
-extern int be_cmd_set_flow_control(struct be_adapter *adapter,
-			u32 tx_fc, u32 rx_fc);
-extern int be_cmd_get_flow_control(struct be_adapter *adapter,
-			u32 *tx_fc, u32 *rx_fc);
-extern int be_cmd_query_fw_cfg(struct be_adapter *adapter,
-			u32 *port_num, u32 *function_mode, u32 *function_caps);
-extern int be_cmd_reset_function(struct be_adapter *adapter);
-extern int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
-			u16 table_size);
-extern int be_process_mcc(struct be_adapter *adapter, int *status);
-extern int be_cmd_set_beacon_state(struct be_adapter *adapter,
-			u8 port_num, u8 beacon, u8 status, u8 state);
-extern int be_cmd_get_beacon_state(struct be_adapter *adapter,
-			u8 port_num, u32 *state);
-extern int be_cmd_write_flashrom(struct be_adapter *adapter,
-			struct be_dma_mem *cmd, u32 flash_oper,
-			u32 flash_opcode, u32 buf_size);
-extern int lancer_cmd_write_object(struct be_adapter *adapter,
-				struct be_dma_mem *cmd,
-				u32 data_size, u32 data_offset,
-				const char *obj_name,
-				u32 *data_written, u8 *addn_status);
-int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
-				int offset);
-extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
-				struct be_dma_mem *nonemb_cmd);
-extern int be_cmd_fw_init(struct be_adapter *adapter);
-extern int be_cmd_fw_clean(struct be_adapter *adapter);
-extern void be_async_mcc_enable(struct be_adapter *adapter);
-extern void be_async_mcc_disable(struct be_adapter *adapter);
-extern int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
-				u32 loopback_type, u32 pkt_size,
-				u32 num_pkts, u64 pattern);
-extern int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
-			u32 byte_cnt, struct be_dma_mem *cmd);
-extern int be_cmd_get_seeprom_data(struct be_adapter *adapter,
-				struct be_dma_mem *nonemb_cmd);
-extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
-				u8 loopback_type, u8 enable);
-extern int be_cmd_get_phy_info(struct be_adapter *adapter,
-		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_req_native_mode(struct be_adapter *adapter);
-extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size);
-extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf);
-
diff -druN linux-libre-3.1-gnu/drivers/net/benet/be_ethtool.c linux-libre-3.2-gnu/drivers/net/benet/be_ethtool.c
--- linux-libre-3.1-gnu/drivers/net/benet/be_ethtool.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/benet/be_ethtool.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,746 +0,0 @@
-/*
- * Copyright (C) 2005 - 2011 Emulex
- * 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@emulex.com
- *
- * Emulex
- * 3333 Susan Street
- * Costa Mesa, CA 92626
- */
-
-#include "be.h"
-#include "be_cmds.h"
-#include <linux/ethtool.h>
-
-struct be_ethtool_stat {
-	char desc[ETH_GSTRING_LEN];
-	int type;
-	int size;
-	int offset;
-};
-
-enum {NETSTAT, DRVSTAT_TX, DRVSTAT_RX, ERXSTAT,
-			DRVSTAT};
-#define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \
-					offsetof(_struct, field)
-#define NETSTAT_INFO(field) 	#field, NETSTAT,\
-					FIELDINFO(struct net_device_stats,\
-						field)
-#define DRVSTAT_TX_INFO(field)	#field, DRVSTAT_TX,\
-					FIELDINFO(struct be_tx_stats, field)
-#define DRVSTAT_RX_INFO(field)	#field, DRVSTAT_RX,\
-					FIELDINFO(struct be_rx_stats, field)
-#define ERXSTAT_INFO(field)	#field, ERXSTAT,\
-					FIELDINFO(struct be_erx_stats_v1, 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)},
-	{NETSTAT_INFO(tx_packets)},
-	{NETSTAT_INFO(rx_bytes)},
-	{NETSTAT_INFO(tx_bytes)},
-	{NETSTAT_INFO(rx_errors)},
-	{NETSTAT_INFO(tx_errors)},
-	{NETSTAT_INFO(rx_dropped)},
-	{NETSTAT_INFO(tx_dropped)},
-	{DRVSTAT_INFO(be_tx_events)},
-	{DRVSTAT_INFO(rx_crc_errors)},
-	{DRVSTAT_INFO(rx_alignment_symbol_errors)},
-	{DRVSTAT_INFO(rx_pause_frames)},
-	{DRVSTAT_INFO(rx_control_frames)},
-	{DRVSTAT_INFO(rx_in_range_errors)},
-	{DRVSTAT_INFO(rx_out_range_errors)},
-	{DRVSTAT_INFO(rx_frame_too_long)},
-	{DRVSTAT_INFO(rx_address_match_errors)},
-	{DRVSTAT_INFO(rx_dropped_too_small)},
-	{DRVSTAT_INFO(rx_dropped_too_short)},
-	{DRVSTAT_INFO(rx_dropped_header_too_small)},
-	{DRVSTAT_INFO(rx_dropped_tcp_length)},
-	{DRVSTAT_INFO(rx_dropped_runt)},
-	{DRVSTAT_INFO(rxpp_fifo_overflow_drop)},
-	{DRVSTAT_INFO(rx_input_fifo_overflow_drop)},
-	{DRVSTAT_INFO(rx_ip_checksum_errs)},
-	{DRVSTAT_INFO(rx_tcp_checksum_errs)},
-	{DRVSTAT_INFO(rx_udp_checksum_errs)},
-	{DRVSTAT_INFO(rx_switched_unicast_packets)},
-	{DRVSTAT_INFO(rx_switched_multicast_packets)},
-	{DRVSTAT_INFO(rx_switched_broadcast_packets)},
-	{DRVSTAT_INFO(tx_pauseframes)},
-	{DRVSTAT_INFO(tx_controlframes)},
-	{DRVSTAT_INFO(rx_priority_pause_frames)},
-	{DRVSTAT_INFO(pmem_fifo_overflow_drop)},
-	{DRVSTAT_INFO(jabber_events)},
-	{DRVSTAT_INFO(rx_drops_no_pbuf)},
-	{DRVSTAT_INFO(rx_drops_no_txpb)},
-	{DRVSTAT_INFO(rx_drops_no_erx_descr)},
-	{DRVSTAT_INFO(rx_drops_no_tpre_descr)},
-	{DRVSTAT_INFO(rx_drops_too_many_frags)},
-	{DRVSTAT_INFO(rx_drops_invalid_ring)},
-	{DRVSTAT_INFO(forwarded_packets)},
-	{DRVSTAT_INFO(rx_drops_mtu)},
-	{DRVSTAT_INFO(eth_red_drops)},
-	{DRVSTAT_INFO(be_on_die_temperature)}
-};
-#define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats)
-
-/* Stats related to multi RX queues */
-static const struct be_ethtool_stat et_rx_stats[] = {
-	{DRVSTAT_RX_INFO(rx_bytes)},
-	{DRVSTAT_RX_INFO(rx_pkts)},
-	{DRVSTAT_RX_INFO(rx_rate)},
-	{DRVSTAT_RX_INFO(rx_polls)},
-	{DRVSTAT_RX_INFO(rx_events)},
-	{DRVSTAT_RX_INFO(rx_compl)},
-	{DRVSTAT_RX_INFO(rx_mcast_pkts)},
-	{DRVSTAT_RX_INFO(rx_post_fail)},
-	{DRVSTAT_RX_INFO(rx_dropped)},
-	{ERXSTAT_INFO(rx_drops_no_fragments)}
-};
-#define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats))
-
-/* Stats related to multi TX queues */
-static const struct be_ethtool_stat et_tx_stats[] = {
-	{DRVSTAT_TX_INFO(be_tx_rate)},
-	{DRVSTAT_TX_INFO(be_tx_reqs)},
-	{DRVSTAT_TX_INFO(be_tx_wrbs)},
-	{DRVSTAT_TX_INFO(be_tx_stops)},
-	{DRVSTAT_TX_INFO(be_tx_compl)}
-};
-#define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats))
-
-static const char et_self_tests[][ETH_GSTRING_LEN] = {
-	"MAC Loopback test",
-	"PHY Loopback test",
-	"External Loopback test",
-	"DDR DMA test",
-	"Link test"
-};
-
-#define ETHTOOL_TESTS_NUM ARRAY_SIZE(et_self_tests)
-#define BE_MAC_LOOPBACK 0x0
-#define BE_PHY_LOOPBACK 0x1
-#define BE_ONE_PORT_EXT_LOOPBACK 0x2
-#define BE_NO_LOOPBACK 0xff
-
-static void
-be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-
-	strcpy(drvinfo->driver, DRV_NAME);
-	strcpy(drvinfo->version, DRV_VER);
-	strncpy(drvinfo->fw_version, adapter->fw_ver, FW_VER_LEN);
-	strcpy(drvinfo->bus_info, pci_name(adapter->pdev));
-	drvinfo->testinfo_len = 0;
-	drvinfo->regdump_len = 0;
-	drvinfo->eedump_len = 0;
-}
-
-static int
-be_get_reg_len(struct net_device *netdev)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	u32 log_size = 0;
-
-	if (be_physfn(adapter))
-		be_cmd_get_reg_len(adapter, &log_size);
-
-	return log_size;
-}
-
-static void
-be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-
-	if (be_physfn(adapter)) {
-		memset(buf, 0, regs->len);
-		be_cmd_get_regs(adapter, regs->len, buf);
-	}
-}
-
-static int
-be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_eq_obj *rx_eq = &adapter->rx_obj[0].rx_eq;
-	struct be_eq_obj *tx_eq = &adapter->tx_eq;
-
-	coalesce->rx_coalesce_usecs = rx_eq->cur_eqd;
-	coalesce->rx_coalesce_usecs_high = rx_eq->max_eqd;
-	coalesce->rx_coalesce_usecs_low = rx_eq->min_eqd;
-
-	coalesce->tx_coalesce_usecs = tx_eq->cur_eqd;
-	coalesce->tx_coalesce_usecs_high = tx_eq->max_eqd;
-	coalesce->tx_coalesce_usecs_low = tx_eq->min_eqd;
-
-	coalesce->use_adaptive_rx_coalesce = rx_eq->enable_aic;
-	coalesce->use_adaptive_tx_coalesce = tx_eq->enable_aic;
-
-	return 0;
-}
-
-/*
- * This routine is used to set interrup coalescing delay
- */
-static int
-be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_rx_obj *rxo;
-	struct be_eq_obj *rx_eq;
-	struct be_eq_obj *tx_eq = &adapter->tx_eq;
-	u32 rx_max, rx_min, rx_cur;
-	int status = 0, i;
-	u32 tx_cur;
-
-	if (coalesce->use_adaptive_tx_coalesce == 1)
-		return -EINVAL;
-
-	for_all_rx_queues(adapter, rxo, i) {
-		rx_eq = &rxo->rx_eq;
-
-		if (!rx_eq->enable_aic && coalesce->use_adaptive_rx_coalesce)
-			rx_eq->cur_eqd = 0;
-		rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce;
-
-		rx_max = coalesce->rx_coalesce_usecs_high;
-		rx_min = coalesce->rx_coalesce_usecs_low;
-		rx_cur = coalesce->rx_coalesce_usecs;
-
-		if (rx_eq->enable_aic) {
-			if (rx_max > BE_MAX_EQD)
-				rx_max = BE_MAX_EQD;
-			if (rx_min > rx_max)
-				rx_min = rx_max;
-			rx_eq->max_eqd = rx_max;
-			rx_eq->min_eqd = rx_min;
-			if (rx_eq->cur_eqd > rx_max)
-				rx_eq->cur_eqd = rx_max;
-			if (rx_eq->cur_eqd < rx_min)
-				rx_eq->cur_eqd = rx_min;
-		} else {
-			if (rx_cur > BE_MAX_EQD)
-				rx_cur = BE_MAX_EQD;
-			if (rx_eq->cur_eqd != rx_cur) {
-				status = be_cmd_modify_eqd(adapter, rx_eq->q.id,
-						rx_cur);
-				if (!status)
-					rx_eq->cur_eqd = rx_cur;
-			}
-		}
-	}
-
-	tx_cur = coalesce->tx_coalesce_usecs;
-
-	if (tx_cur > BE_MAX_EQD)
-		tx_cur = BE_MAX_EQD;
-	if (tx_eq->cur_eqd != tx_cur) {
-		status = be_cmd_modify_eqd(adapter, tx_eq->q.id, tx_cur);
-		if (!status)
-			tx_eq->cur_eqd = tx_cur;
-	}
-
-	return 0;
-}
-
-static void
-be_get_ethtool_stats(struct net_device *netdev,
-		struct ethtool_stats *stats, uint64_t *data)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_rx_obj *rxo;
-	struct be_tx_obj *txo;
-	void *p = NULL;
-	int i, j, base;
-
-	for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
-		switch (et_stats[i].type) {
-		case NETSTAT:
-			p = &netdev->stats;
-			break;
-		case DRVSTAT:
-			p = &adapter->drv_stats;
-			break;
-		}
-
-		p = (u8 *)p + et_stats[i].offset;
-		data[i] = (et_stats[i].size == sizeof(u64)) ?
-				*(u64 *)p: *(u32 *)p;
-	}
-
-	base = ETHTOOL_STATS_NUM;
-	for_all_rx_queues(adapter, rxo, j) {
-		for (i = 0; i < ETHTOOL_RXSTATS_NUM; i++) {
-			switch (et_rx_stats[i].type) {
-			case DRVSTAT_RX:
-				p = (u8 *)&rxo->stats + et_rx_stats[i].offset;
-				break;
-			case ERXSTAT:
-				p = (u32 *)be_erx_stats_from_cmd(adapter) +
-								rxo->q.id;
-				break;
-			}
-			data[base + j * ETHTOOL_RXSTATS_NUM + i] =
-				(et_rx_stats[i].size == sizeof(u64)) ?
-					*(u64 *)p: *(u32 *)p;
-		}
-	}
-
-	base = ETHTOOL_STATS_NUM + adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM;
-	for_all_tx_queues(adapter, txo, j) {
-		for (i = 0; i < ETHTOOL_TXSTATS_NUM; i++) {
-			p = (u8 *)&txo->stats + et_tx_stats[i].offset;
-			data[base + j * ETHTOOL_TXSTATS_NUM + i] =
-				(et_tx_stats[i].size == sizeof(u64)) ?
-					*(u64 *)p: *(u32 *)p;
-		}
-	}
-}
-
-static void
-be_get_stat_strings(struct net_device *netdev, uint32_t stringset,
-		uint8_t *data)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	int i, j;
-
-	switch (stringset) {
-	case ETH_SS_STATS:
-		for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
-			memcpy(data, et_stats[i].desc, ETH_GSTRING_LEN);
-			data += ETH_GSTRING_LEN;
-		}
-		for (i = 0; i < adapter->num_rx_qs; i++) {
-			for (j = 0; j < ETHTOOL_RXSTATS_NUM; j++) {
-				sprintf(data, "rxq%d: %s", i,
-					et_rx_stats[j].desc);
-				data += ETH_GSTRING_LEN;
-			}
-		}
-		for (i = 0; i < adapter->num_tx_qs; i++) {
-			for (j = 0; j < ETHTOOL_TXSTATS_NUM; j++) {
-				sprintf(data, "txq%d: %s", i,
-					et_tx_stats[j].desc);
-				data += ETH_GSTRING_LEN;
-			}
-		}
-		break;
-	case ETH_SS_TEST:
-		for (i = 0; i < ETHTOOL_TESTS_NUM; i++) {
-			memcpy(data, et_self_tests[i], ETH_GSTRING_LEN);
-			data += ETH_GSTRING_LEN;
-		}
-		break;
-	}
-}
-
-static int be_get_sset_count(struct net_device *netdev, int stringset)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-
-	switch (stringset) {
-	case ETH_SS_TEST:
-		return ETHTOOL_TESTS_NUM;
-	case ETH_SS_STATS:
-		return ETHTOOL_STATS_NUM +
-			adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM +
-			adapter->num_tx_qs * ETHTOOL_TXSTATS_NUM;
-	default:
-		return -EINVAL;
-	}
-}
-
-static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_dma_mem phy_cmd;
-	struct be_cmd_resp_get_phy_info *resp;
-	u8 mac_speed = 0;
-	u16 link_speed = 0;
-	bool link_up = false;
-	int status;
-	u16 intf_type;
-
-	if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) {
-		status = be_cmd_link_status_query(adapter, &link_up,
-						&mac_speed, &link_speed, 0);
-
-		be_link_status_update(adapter, link_up);
-		/* link_speed is in units of 10 Mbps */
-		if (link_speed) {
-			ethtool_cmd_speed_set(ecmd, link_speed*10);
-		} else {
-			switch (mac_speed) {
-			case PHY_LINK_SPEED_10MBPS:
-				ethtool_cmd_speed_set(ecmd, SPEED_10);
-				break;
-			case PHY_LINK_SPEED_100MBPS:
-				ethtool_cmd_speed_set(ecmd, SPEED_100);
-				break;
-			case PHY_LINK_SPEED_1GBPS:
-				ethtool_cmd_speed_set(ecmd, SPEED_1000);
-				break;
-			case PHY_LINK_SPEED_10GBPS:
-				ethtool_cmd_speed_set(ecmd, SPEED_10000);
-				break;
-			case PHY_LINK_SPEED_ZERO:
-				ethtool_cmd_speed_set(ecmd, 0);
-				break;
-			}
-		}
-
-		phy_cmd.size = sizeof(struct be_cmd_req_get_phy_info);
-		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;
-		}
-		status = be_cmd_get_phy_info(adapter, &phy_cmd);
-		if (!status) {
-			resp = phy_cmd.va;
-			intf_type = le16_to_cpu(resp->interface_type);
-
-			switch (intf_type) {
-			case PHY_TYPE_XFP_10GB:
-			case PHY_TYPE_SFP_1GB:
-			case PHY_TYPE_SFP_PLUS_10GB:
-				ecmd->port = PORT_FIBRE;
-				break;
-			default:
-				ecmd->port = PORT_TP;
-				break;
-			}
-
-			switch (intf_type) {
-			case PHY_TYPE_KR_10GB:
-			case PHY_TYPE_KX4_10GB:
-				ecmd->autoneg = AUTONEG_ENABLE;
-			ecmd->transceiver = XCVR_INTERNAL;
-				break;
-			default:
-				ecmd->autoneg = AUTONEG_DISABLE;
-				ecmd->transceiver = XCVR_EXTERNAL;
-				break;
-			}
-		}
-
-		/* Save for future use */
-		adapter->link_speed = ethtool_cmd_speed(ecmd);
-		adapter->port_type = ecmd->port;
-		adapter->transceiver = ecmd->transceiver;
-		adapter->autoneg = ecmd->autoneg;
-		dma_free_coherent(&adapter->pdev->dev, phy_cmd.size, phy_cmd.va,
-				  phy_cmd.dma);
-	} else {
-		ethtool_cmd_speed_set(ecmd, adapter->link_speed);
-		ecmd->port = adapter->port_type;
-		ecmd->transceiver = adapter->transceiver;
-		ecmd->autoneg = adapter->autoneg;
-	}
-
-	ecmd->duplex = DUPLEX_FULL;
-	ecmd->phy_address = adapter->port_num;
-	switch (ecmd->port) {
-	case PORT_FIBRE:
-		ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
-		break;
-	case PORT_TP:
-		ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_TP);
-		break;
-	case PORT_AUI:
-		ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_AUI);
-		break;
-	}
-
-	if (ecmd->autoneg) {
-		ecmd->supported |= SUPPORTED_1000baseT_Full;
-		ecmd->supported |= SUPPORTED_Autoneg;
-		ecmd->advertising |= (ADVERTISED_10000baseT_Full |
-				ADVERTISED_1000baseT_Full);
-	}
-
-	return 0;
-}
-
-static void
-be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-
-	ring->rx_max_pending = adapter->rx_obj[0].q.len;
-	ring->tx_max_pending = adapter->tx_obj[0].q.len;
-
-	ring->rx_pending = atomic_read(&adapter->rx_obj[0].q.used);
-	ring->tx_pending = atomic_read(&adapter->tx_obj[0].q.used);
-}
-
-static void
-be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-
-	be_cmd_get_flow_control(adapter, &ecmd->tx_pause, &ecmd->rx_pause);
-	ecmd->autoneg = 0;
-}
-
-static int
-be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	int status;
-
-	if (ecmd->autoneg != 0)
-		return -EINVAL;
-	adapter->tx_fc = ecmd->tx_pause;
-	adapter->rx_fc = ecmd->rx_pause;
-
-	status = be_cmd_set_flow_control(adapter,
-					adapter->tx_fc, adapter->rx_fc);
-	if (status)
-		dev_warn(&adapter->pdev->dev, "Pause param set failed.\n");
-
-	return status;
-}
-
-static int
-be_set_phys_id(struct net_device *netdev,
-	       enum ethtool_phys_id_state state)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-
-	switch (state) {
-	case ETHTOOL_ID_ACTIVE:
-		be_cmd_get_beacon_state(adapter, adapter->hba_port_num,
-					&adapter->beacon_state);
-		return 1;	/* cycle on/off once per second */
-
-	case ETHTOOL_ID_ON:
-		be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
-					BEACON_STATE_ENABLED);
-		break;
-
-	case ETHTOOL_ID_OFF:
-		be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
-					BEACON_STATE_DISABLED);
-		break;
-
-	case ETHTOOL_ID_INACTIVE:
-		be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
-					adapter->beacon_state);
-	}
-
-	return 0;
-}
-
-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);
-
-	if (be_is_wol_supported(adapter))
-		wol->supported = WAKE_MAGIC;
-
-	if (adapter->wol)
-		wol->wolopts = WAKE_MAGIC;
-	else
-		wol->wolopts = 0;
-	memset(&wol->sopass, 0, sizeof(wol->sopass));
-}
-
-static int
-be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-
-	if (wol->wolopts & ~WAKE_MAGIC)
-		return -EINVAL;
-
-	if ((wol->wolopts & WAKE_MAGIC) && be_is_wol_supported(adapter))
-		adapter->wol = true;
-	else
-		adapter->wol = false;
-
-	return 0;
-}
-
-static int
-be_test_ddr_dma(struct be_adapter *adapter)
-{
-	int ret, i;
-	struct be_dma_mem ddrdma_cmd;
-	static const u64 pattern[2] = {
-		0x5a5a5a5a5a5a5a5aULL, 0xa5a5a5a5a5a5a5a5ULL
-	};
-
-	ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test);
-	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;
-	}
-
-	for (i = 0; i < 2; i++) {
-		ret = be_cmd_ddr_dma_test(adapter, pattern[i],
-					4096, &ddrdma_cmd);
-		if (ret != 0)
-			goto err;
-	}
-
-err:
-	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->hba_port_num,
-				loopback_type, 1);
-	*status = be_cmd_loopback_test(adapter, adapter->hba_port_num,
-				loopback_type, 1500,
-				2, 0xabc);
-	be_cmd_set_loopback(adapter, adapter->hba_port_num,
-				BE_NO_LOOPBACK, 1);
-	return *status;
-}
-
-static void
-be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	bool link_up;
-	u8 mac_speed = 0;
-	u16 qos_link_speed = 0;
-
-	memset(data, 0, sizeof(u64) * ETHTOOL_TESTS_NUM);
-
-	if (test->flags & ETH_TEST_FL_OFFLINE) {
-		if (be_loopback_test(adapter, BE_MAC_LOOPBACK,
-						&data[0]) != 0) {
-			test->flags |= ETH_TEST_FL_FAILED;
-		}
-		if (be_loopback_test(adapter, BE_PHY_LOOPBACK,
-						&data[1]) != 0) {
-			test->flags |= ETH_TEST_FL_FAILED;
-		}
-		if (be_loopback_test(adapter, BE_ONE_PORT_EXT_LOOPBACK,
-						&data[2]) != 0) {
-			test->flags |= ETH_TEST_FL_FAILED;
-		}
-	}
-
-	if (be_test_ddr_dma(adapter) != 0) {
-		data[3] = 1;
-		test->flags |= ETH_TEST_FL_FAILED;
-	}
-
-	if (be_cmd_link_status_query(adapter, &link_up, &mac_speed,
-				&qos_link_speed, 0) != 0) {
-		test->flags |= ETH_TEST_FL_FAILED;
-		data[4] = -1;
-	} else if (!mac_speed) {
-		test->flags |= ETH_TEST_FL_FAILED;
-		data[4] = 1;
-	}
-}
-
-static int
-be_do_flash(struct net_device *netdev, struct ethtool_flash *efl)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	char file_name[ETHTOOL_FLASH_MAX_FILENAME];
-
-	file_name[ETHTOOL_FLASH_MAX_FILENAME - 1] = 0;
-	strcpy(file_name, efl->data);
-
-	return be_load_fw(adapter, file_name);
-}
-
-static int
-be_get_eeprom_len(struct net_device *netdev)
-{
-	return BE_READ_SEEPROM_LEN;
-}
-
-static int
-be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
-			uint8_t *data)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_dma_mem eeprom_cmd;
-	struct be_cmd_resp_seeprom_read *resp;
-	int status;
-
-	if (!eeprom->len)
-		return -EINVAL;
-
-	eeprom->magic = BE_VENDOR_ID | (adapter->pdev->device<<16);
-
-	memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem));
-	eeprom_cmd.size = sizeof(struct be_cmd_req_seeprom_read);
-	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,
-			"Memory allocation failure. Could not read eeprom\n");
-		return -ENOMEM;
-	}
-
-	status = be_cmd_get_seeprom_data(adapter, &eeprom_cmd);
-
-	if (!status) {
-		resp = eeprom_cmd.va;
-		memcpy(data, resp->seeprom_data + eeprom->offset, eeprom->len);
-	}
-	dma_free_coherent(&adapter->pdev->dev, eeprom_cmd.size, eeprom_cmd.va,
-			  eeprom_cmd.dma);
-
-	return status;
-}
-
-const struct ethtool_ops be_ethtool_ops = {
-	.get_settings = be_get_settings,
-	.get_drvinfo = be_get_drvinfo,
-	.get_wol = be_get_wol,
-	.set_wol = be_set_wol,
-	.get_link = ethtool_op_get_link,
-	.get_eeprom_len = be_get_eeprom_len,
-	.get_eeprom = be_read_eeprom,
-	.get_coalesce = be_get_coalesce,
-	.set_coalesce = be_set_coalesce,
-	.get_ringparam = be_get_ringparam,
-	.get_pauseparam = be_get_pauseparam,
-	.set_pauseparam = be_set_pauseparam,
-	.get_strings = be_get_stat_strings,
-	.set_phys_id = be_set_phys_id,
-	.get_sset_count = be_get_sset_count,
-	.get_ethtool_stats = be_get_ethtool_stats,
-	.get_regs_len = be_get_reg_len,
-	.get_regs = be_get_regs,
-	.flash_device = be_do_flash,
-	.self_test = be_self_test,
-};
diff -druN linux-libre-3.1-gnu/drivers/net/benet/be.h linux-libre-3.2-gnu/drivers/net/benet/be.h
--- linux-libre-3.1-gnu/drivers/net/benet/be.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/benet/be.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,532 +0,0 @@
-/*
- * Copyright (C) 2005 - 2011 Emulex
- * 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@emulex.com
- *
- * Emulex
- * 3333 Susan Street
- * Costa Mesa, CA 92626
- */
-
-#ifndef BE_H
-#define BE_H
-
-#include <linux/pci.h>
-#include <linux/etherdevice.h>
-#include <linux/delay.h>
-#include <net/tcp.h>
-#include <net/ip.h>
-#include <net/ipv6.h>
-#include <linux/if_vlan.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/firmware.h>
-#include <linux/slab.h>
-
-#include "be_hw.h"
-
-#define DRV_VER			"4.0.100u"
-#define DRV_NAME		"be2net"
-#define BE_NAME			"ServerEngines BladeEngine2 10Gbps NIC"
-#define BE3_NAME		"ServerEngines BladeEngine3 10Gbps NIC"
-#define OC_NAME			"Emulex OneConnect 10Gbps NIC"
-#define OC_NAME_BE		OC_NAME	"(be3)"
-#define OC_NAME_LANCER		OC_NAME "(Lancer)"
-#define DRV_DESC		"ServerEngines BladeEngine 10Gbps NIC Driver"
-
-#define BE_VENDOR_ID 		0x19a2
-#define EMULEX_VENDOR_ID	0x10df
-#define BE_DEVICE_ID1		0x211
-#define BE_DEVICE_ID2		0x221
-#define OC_DEVICE_ID1		0x700	/* Device Id for BE2 cards */
-#define OC_DEVICE_ID2		0x710	/* Device Id for BE3 cards */
-#define OC_DEVICE_ID3		0xe220	/* Device id for Lancer cards */
-#define OC_DEVICE_ID4           0xe228   /* Device id for VF in Lancer */
-
-static inline char *nic_name(struct pci_dev *pdev)
-{
-	switch (pdev->device) {
-	case OC_DEVICE_ID1:
-		return OC_NAME;
-	case OC_DEVICE_ID2:
-		return OC_NAME_BE;
-	case OC_DEVICE_ID3:
-	case OC_DEVICE_ID4:
-		return OC_NAME_LANCER;
-	case BE_DEVICE_ID2:
-		return BE3_NAME;
-	default:
-		return BE_NAME;
-	}
-}
-
-/* Number of bytes of an RX frame that are copied to skb->data */
-#define BE_HDR_LEN		((u16) 64)
-#define BE_MAX_JUMBO_FRAME_SIZE	9018
-#define BE_MIN_MTU		256
-
-#define BE_NUM_VLANS_SUPPORTED	64
-#define BE_MAX_EQD		96
-#define	BE_MAX_TX_FRAG_COUNT	30
-
-#define EVNT_Q_LEN		1024
-#define TX_Q_LEN		2048
-#define TX_CQ_LEN		1024
-#define RX_Q_LEN		1024	/* Does not support any other value */
-#define RX_CQ_LEN		1024
-#define MCC_Q_LEN		128	/* total size not to exceed 8 pages */
-#define MCC_CQ_LEN		256
-
-#define MAX_RSS_QS		4	/* BE limit is 4 queues/port */
-#define MAX_RX_QS		(MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */
-#define MAX_TX_QS		8
-#define BE_MAX_MSIX_VECTORS	(MAX_RX_QS + 1)/* RX + TX */
-#define BE_NAPI_WEIGHT		64
-#define MAX_RX_POST 		BE_NAPI_WEIGHT /* Frags posted at a time */
-#define RX_FRAGS_REFILL_WM	(RX_Q_LEN - MAX_RX_POST)
-
-#define FW_VER_LEN		32
-
-struct be_dma_mem {
-	void *va;
-	dma_addr_t dma;
-	u32 size;
-};
-
-struct be_queue_info {
-	struct be_dma_mem dma_mem;
-	u16 len;
-	u16 entry_size;	/* Size of an element in the queue */
-	u16 id;
-	u16 tail, head;
-	bool created;
-	atomic_t used;	/* Number of valid elements in the queue */
-};
-
-static inline u32 MODULO(u16 val, u16 limit)
-{
-	BUG_ON(limit & (limit - 1));
-	return val & (limit - 1);
-}
-
-static inline void index_adv(u16 *index, u16 val, u16 limit)
-{
-	*index = MODULO((*index + val), limit);
-}
-
-static inline void index_inc(u16 *index, u16 limit)
-{
-	*index = MODULO((*index + 1), limit);
-}
-
-static inline void *queue_head_node(struct be_queue_info *q)
-{
-	return q->dma_mem.va + q->head * q->entry_size;
-}
-
-static inline void *queue_tail_node(struct be_queue_info *q)
-{
-	return q->dma_mem.va + q->tail * q->entry_size;
-}
-
-static inline void queue_head_inc(struct be_queue_info *q)
-{
-	index_inc(&q->head, q->len);
-}
-
-static inline void queue_tail_inc(struct be_queue_info *q)
-{
-	index_inc(&q->tail, q->len);
-}
-
-struct be_eq_obj {
-	struct be_queue_info q;
-	char desc[32];
-
-	/* Adaptive interrupt coalescing (AIC) info */
-	bool enable_aic;
-	u16 min_eqd;		/* in usecs */
-	u16 max_eqd;		/* in usecs */
-	u16 cur_eqd;		/* in usecs */
-	u8  eq_idx;
-
-	struct napi_struct napi;
-};
-
-struct be_mcc_obj {
-	struct be_queue_info q;
-	struct be_queue_info cq;
-	bool rearm_cq;
-};
-
-struct be_tx_stats {
-	u32 be_tx_reqs;		/* number of TX requests initiated */
-	u32 be_tx_stops;	/* number of times TX Q was stopped */
-	u32 be_tx_wrbs;		/* number of tx WRBs used */
-	u32 be_tx_compl;	/* number of tx completion entries processed */
-	ulong be_tx_jiffies;
-	u64 be_tx_bytes;
-	u64 be_tx_bytes_prev;
-	u64 be_tx_pkts;
-	u32 be_tx_rate;
-};
-
-struct be_tx_obj {
-	struct be_queue_info q;
-	struct be_queue_info cq;
-	/* Remember the skbs that were transmitted */
-	struct sk_buff *sent_skb_list[TX_Q_LEN];
-	struct be_tx_stats stats;
-};
-
-/* Struct to remember the pages posted for rx frags */
-struct be_rx_page_info {
-	struct page *page;
-	DEFINE_DMA_UNMAP_ADDR(bus);
-	u16 page_offset;
-	bool last_page_user;
-};
-
-struct be_rx_stats {
-	u32 rx_post_fail;/* number of ethrx buffer alloc failures */
-	u32 rx_polls;	/* number of times NAPI called poll function */
-	u32 rx_events;	/* number of ucast rx completion events  */
-	u32 rx_compl;	/* number of rx completion entries processed */
-	ulong rx_dropped; /* number of skb allocation errors */
-	ulong rx_jiffies;
-	u64 rx_bytes;
-	u64 rx_bytes_prev;
-	u64 rx_pkts;
-	u32 rx_rate;
-	u32 rx_mcast_pkts;
-	u32 rxcp_err;	/* Num rx completion entries w/ err set. */
-	ulong rx_fps_jiffies;	/* jiffies at last FPS calc */
-	u32 rx_frags;
-	u32 prev_rx_frags;
-	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 */
-	u32 cache_line_barrier[16];
-};
-
-struct be_drv_stats {
-	u8 be_on_die_temperature;
-	u64 be_tx_events;
-	u64 eth_red_drops;
-	u64 rx_drops_no_pbuf;
-	u64 rx_drops_no_txpb;
-	u64 rx_drops_no_erx_descr;
-	u64 rx_drops_no_tpre_descr;
-	u64 rx_drops_too_many_frags;
-	u64 rx_drops_invalid_ring;
-	u64 forwarded_packets;
-	u64 rx_drops_mtu;
-	u64 rx_crc_errors;
-	u64 rx_alignment_symbol_errors;
-	u64 rx_pause_frames;
-	u64 rx_priority_pause_frames;
-	u64 rx_control_frames;
-	u64 rx_in_range_errors;
-	u64 rx_out_range_errors;
-	u64 rx_frame_too_long;
-	u64 rx_address_match_errors;
-	u64 rx_dropped_too_small;
-	u64 rx_dropped_too_short;
-	u64 rx_dropped_header_too_small;
-	u64 rx_dropped_tcp_length;
-	u64 rx_dropped_runt;
-	u64 rx_ip_checksum_errs;
-	u64 rx_tcp_checksum_errs;
-	u64 rx_udp_checksum_errs;
-	u64 rx_switched_unicast_packets;
-	u64 rx_switched_multicast_packets;
-	u64 rx_switched_broadcast_packets;
-	u64 tx_pauseframes;
-	u64 tx_priority_pauseframes;
-	u64 tx_controlframes;
-	u64 rxpp_fifo_overflow_drop;
-	u64 rx_input_fifo_overflow_drop;
-	u64 pmem_fifo_overflow_drop;
-	u64 jabber_events;
-};
-
-struct be_vf_cfg {
-	unsigned char vf_mac_addr[ETH_ALEN];
-	u32 vf_if_handle;
-	u32 vf_pmac_id;
-	u16 vf_vlan_tag;
-	u32 vf_tx_rate;
-};
-
-#define BE_INVALID_PMAC_ID		0xffffffff
-
-struct be_adapter {
-	struct pci_dev *pdev;
-	struct net_device *netdev;
-
-	u8 __iomem *csr;
-	u8 __iomem *db;		/* Door Bell */
-	u8 __iomem *pcicfg;	/* PCI config space */
-
-	struct mutex mbox_lock; /* For serializing mbox cmds to BE card */
-	struct be_dma_mem mbox_mem;
-	/* Mbox mem is adjusted to align to 16 bytes. The allocated addr
-	 * is stored for freeing purpose */
-	struct be_dma_mem mbox_mem_alloced;
-
-	struct be_mcc_obj mcc_obj;
-	spinlock_t mcc_lock;	/* For serializing mcc cmds to BE card */
-	spinlock_t mcc_cq_lock;
-
-	struct msix_entry msix_entries[BE_MAX_MSIX_VECTORS];
-	u32 num_msix_vec;
-	bool isr_registered;
-
-	/* TX Rings */
-	struct be_eq_obj tx_eq;
-	struct be_tx_obj tx_obj[MAX_TX_QS];
-	u8 num_tx_qs;
-
-	u32 cache_line_break[8];
-
-	/* Rx rings */
-	struct be_rx_obj rx_obj[MAX_RX_QS];
-	u32 num_rx_qs;
-	u32 big_page_size;	/* Compounded page size shared by rx wrbs */
-
-	u8 eq_next_idx;
-	struct be_drv_stats drv_stats;
-
-	u16 vlans_added;
-	u16 max_vlans;	/* Number of vlans supported */
-	u8 vlan_tag[VLAN_N_VID];
-	u8 vlan_prio_bmap;	/* Available Priority BitMap */
-	u16 recommended_prio;	/* Recommended Priority */
-	struct be_dma_mem mc_cmd_mem;
-
-	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 */
-	char fw_ver[FW_VER_LEN];
-	u32 if_handle;		/* Used to configure filtering */
-	u32 pmac_id;		/* MAC addr handle used by BE card */
-	u32 beacon_state;	/* for set_phys_id */
-
-	bool eeh_err;
-	bool link_up;
-	u32 port_num;
-	bool promiscuous;
-	bool wol;
-	u32 function_mode;
-	u32 function_caps;
-	u32 rx_fc;		/* Rx flow control */
-	u32 tx_fc;		/* Tx flow control */
-	bool ue_detected;
-	bool stats_cmd_sent;
-	int link_speed;
-	u8 port_type;
-	u8 transceiver;
-	u8 autoneg;
-	u8 generation;		/* BladeEngine ASIC generation */
-	u32 flash_status;
-	struct completion flash_compl;
-
-	bool be3_native;
-	bool sriov_enabled;
-	struct be_vf_cfg *vf_cfg;
-	u8 is_virtfn;
-	u32 sli_family;
-	u8 hba_port_num;
-	u16 pvid;
-};
-
-#define be_physfn(adapter) (!adapter->is_virtfn)
-
-/* BladeEngine Generation numbers */
-#define BE_GEN2 2
-#define BE_GEN3 3
-
-#define lancer_chip(adapter)	((adapter->pdev->device == OC_DEVICE_ID3) || \
-				 (adapter->pdev->device == OC_DEVICE_ID4))
-
-extern const struct ethtool_ops be_ethtool_ops;
-
-#define msix_enabled(adapter)		(adapter->num_msix_vec > 0)
-#define tx_stats(txo)			(&txo->stats)
-#define rx_stats(rxo)			(&rxo->stats)
-
-#define BE_SET_NETDEV_OPS(netdev, ops)	(netdev->netdev_ops = ops)
-
-#define for_all_rx_queues(adapter, rxo, i)				\
-	for (i = 0, rxo = &adapter->rx_obj[i]; i < adapter->num_rx_qs;	\
-		i++, rxo++)
-
-/* Just skip the first default non-rss queue */
-#define for_all_rss_queues(adapter, rxo, i)				\
-	for (i = 0, rxo = &adapter->rx_obj[i+1]; i < (adapter->num_rx_qs - 1);\
-		i++, rxo++)
-
-#define for_all_tx_queues(adapter, txo, i)				\
-	for (i = 0, txo = &adapter->tx_obj[i]; i < adapter->num_tx_qs;	\
-		i++, txo++)
-
-#define PAGE_SHIFT_4K		12
-#define PAGE_SIZE_4K		(1 << PAGE_SHIFT_4K)
-
-/* Returns number of pages spanned by the data starting at the given addr */
-#define PAGES_4K_SPANNED(_address, size) 				\
-		((u32)((((size_t)(_address) & (PAGE_SIZE_4K - 1)) + 	\
-			(size) + (PAGE_SIZE_4K - 1)) >> PAGE_SHIFT_4K))
-
-/* Byte offset into the page corresponding to given address */
-#define OFFSET_IN_PAGE(addr)						\
-		 ((size_t)(addr) & (PAGE_SIZE_4K-1))
-
-/* Returns bit offset within a DWORD of a bitfield */
-#define AMAP_BIT_OFFSET(_struct, field)  				\
-		(((size_t)&(((_struct *)0)->field))%32)
-
-/* Returns the bit mask of the field that is NOT shifted into location. */
-static inline u32 amap_mask(u32 bitsize)
-{
-	return (bitsize == 32 ? 0xFFFFFFFF : (1 << bitsize) - 1);
-}
-
-static inline void
-amap_set(void *ptr, u32 dw_offset, u32 mask, u32 offset, u32 value)
-{
-	u32 *dw = (u32 *) ptr + dw_offset;
-	*dw &= ~(mask << offset);
-	*dw |= (mask & value) << offset;
-}
-
-#define AMAP_SET_BITS(_struct, field, ptr, val)				\
-		amap_set(ptr,						\
-			offsetof(_struct, field)/32,			\
-			amap_mask(sizeof(((_struct *)0)->field)),	\
-			AMAP_BIT_OFFSET(_struct, field),		\
-			val)
-
-static inline u32 amap_get(void *ptr, u32 dw_offset, u32 mask, u32 offset)
-{
-	u32 *dw = (u32 *) ptr;
-	return mask & (*(dw + dw_offset) >> offset);
-}
-
-#define AMAP_GET_BITS(_struct, field, ptr)				\
-		amap_get(ptr,						\
-			offsetof(_struct, field)/32,			\
-			amap_mask(sizeof(((_struct *)0)->field)),	\
-			AMAP_BIT_OFFSET(_struct, field))
-
-#define be_dws_cpu_to_le(wrb, len)	swap_dws(wrb, len)
-#define be_dws_le_to_cpu(wrb, len)	swap_dws(wrb, len)
-static inline void swap_dws(void *wrb, int len)
-{
-#ifdef __BIG_ENDIAN
-	u32 *dw = wrb;
-	BUG_ON(len % 4);
-	do {
-		*dw = cpu_to_le32(*dw);
-		dw++;
-		len -= 4;
-	} while (len);
-#endif				/* __BIG_ENDIAN */
-}
-
-static inline u8 is_tcp_pkt(struct sk_buff *skb)
-{
-	u8 val = 0;
-
-	if (ip_hdr(skb)->version == 4)
-		val = (ip_hdr(skb)->protocol == IPPROTO_TCP);
-	else if (ip_hdr(skb)->version == 6)
-		val = (ipv6_hdr(skb)->nexthdr == NEXTHDR_TCP);
-
-	return val;
-}
-
-static inline u8 is_udp_pkt(struct sk_buff *skb)
-{
-	u8 val = 0;
-
-	if (ip_hdr(skb)->version == 4)
-		val = (ip_hdr(skb)->protocol == IPPROTO_UDP);
-	else if (ip_hdr(skb)->version == 6)
-		val = (ipv6_hdr(skb)->nexthdr == NEXTHDR_UDP);
-
-	return val;
-}
-
-static inline void be_check_sriov_fn_type(struct be_adapter *adapter)
-{
-	u32 sli_intf;
-
-	pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
-	adapter->is_virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0;
-}
-
-static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac)
-{
-	u32 addr;
-
-	addr = jhash(adapter->netdev->dev_addr, ETH_ALEN, 0);
-
-	mac[5] = (u8)(addr & 0xFF);
-	mac[4] = (u8)((addr >> 8) & 0xFF);
-	mac[3] = (u8)((addr >> 16) & 0xFF);
-	/* Use the OUI from the current MAC address */
-	memcpy(mac, adapter->netdev->dev_addr, 3);
-}
-
-static inline bool be_multi_rxq(const struct be_adapter *adapter)
-{
-	return adapter->num_rx_qs > 1;
-}
-
-extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
-		u16 num_popped);
-extern void be_link_status_update(struct be_adapter *adapter, bool link_up);
-extern void netdev_stats_update(struct be_adapter *adapter);
-extern void be_parse_stats(struct be_adapter *adapter);
-extern int be_load_fw(struct be_adapter *adapter, u8 *func);
-#endif				/* BE_H */
diff -druN linux-libre-3.1-gnu/drivers/net/benet/be_hw.h linux-libre-3.2-gnu/drivers/net/benet/be_hw.h
--- linux-libre-3.1-gnu/drivers/net/benet/be_hw.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/benet/be_hw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,503 +0,0 @@
-/*
- * Copyright (C) 2005 - 2011 Emulex
- * 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@emulex.com
- *
- * Emulex
- * 3333 Susan Street
- * Costa Mesa, CA 92626
- */
-
-/********* Mailbox door bell *************/
-/* Used for driver communication with the FW.
- * The software must write this register twice to post any command. First,
- * it writes the register with hi=1 and the upper bits of the physical address
- * for the MAILBOX structure. Software must poll the ready bit until this
- * is acknowledged. Then, sotware writes the register with hi=0 with the lower
- * bits in the address. It must poll the ready bit until the command is
- * complete. Upon completion, the MAILBOX will contain a valid completion
- * queue entry.
- */
-#define MPU_MAILBOX_DB_OFFSET	0x160
-#define MPU_MAILBOX_DB_RDY_MASK	0x1 	/* bit 0 */
-#define MPU_MAILBOX_DB_HI_MASK	0x2	/* bit 1 */
-
-#define MPU_EP_CONTROL 		0
-
-/********** MPU semphore ******************/
-#define MPU_EP_SEMAPHORE_OFFSET		0xac
-#define MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET	0x400
-#define EP_SEMAPHORE_POST_STAGE_MASK		0x0000FFFF
-#define EP_SEMAPHORE_POST_ERR_MASK		0x1
-#define EP_SEMAPHORE_POST_ERR_SHIFT		31
-
-/* MPU semphore POST stage values */
-#define POST_STAGE_AWAITING_HOST_RDY 	0x1 /* FW awaiting goahead from host */
-#define POST_STAGE_HOST_RDY 		0x2 /* Host has given go-ahed to FW */
-#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
- * Disable" may still globally block interrupts in addition to individual
- * interrupt masks; a mechanism for the device driver to block all interrupts
- * atomically without having to arbitrate for the PCI Interrupt Disable bit
- * with the OS.
- */
-#define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK	(1 << 29) /* bit 29 */
-
-/********* Power management (WOL) **********/
-#define PCICFG_PM_CONTROL_OFFSET		0x44
-#define PCICFG_PM_CONTROL_MASK			0x108	/* bits 3 & 8 */
-
-/********* Online Control Registers *******/
-#define PCICFG_ONLINE0				0xB0
-#define PCICFG_ONLINE1				0xB4
-
-/********* UE Status and Mask Registers ***/
-#define PCICFG_UE_STATUS_LOW			0xA0
-#define PCICFG_UE_STATUS_HIGH			0xA4
-#define PCICFG_UE_STATUS_LOW_MASK		0xA8
-#define PCICFG_UE_STATUS_HI_MASK		0xAC
-
-/******** SLI_INTF ***********************/
-#define SLI_INTF_REG_OFFSET			0x58
-#define SLI_INTF_VALID_MASK			0xE0000000
-#define SLI_INTF_VALID				0xC0000000
-#define SLI_INTF_HINT2_MASK			0x1F000000
-#define SLI_INTF_HINT2_SHIFT			24
-#define SLI_INTF_HINT1_MASK			0x00FF0000
-#define SLI_INTF_HINT1_SHIFT			16
-#define SLI_INTF_FAMILY_MASK			0x00000F00
-#define SLI_INTF_FAMILY_SHIFT			8
-#define SLI_INTF_IF_TYPE_MASK			0x0000F000
-#define SLI_INTF_IF_TYPE_SHIFT			12
-#define SLI_INTF_REV_MASK			0x000000F0
-#define SLI_INTF_REV_SHIFT			4
-#define SLI_INTF_FT_MASK			0x00000001
-
-
-/* SLI family */
-#define BE_SLI_FAMILY		0x0
-#define LANCER_A0_SLI_FAMILY	0xA
-
-
-/********* ISR0 Register offset **********/
-#define CEV_ISR0_OFFSET 			0xC18
-#define CEV_ISR_SIZE				4
-
-/********* Event Q door bell *************/
-#define DB_EQ_OFFSET			DB_CQ_OFFSET
-#define DB_EQ_RING_ID_MASK		0x1FF	/* bits 0 - 8 */
-#define DB_EQ_RING_ID_EXT_MASK		0x3e00  /* bits 9-13 */
-#define DB_EQ_RING_ID_EXT_MASK_SHIFT	(2) /* qid bits 9-13 placing at 11-15 */
-
-/* Clear the interrupt for this eq */
-#define DB_EQ_CLR_SHIFT			(9)	/* bit 9 */
-/* Must be 1 */
-#define DB_EQ_EVNT_SHIFT		(10)	/* bit 10 */
-/* Number of event entries processed */
-#define DB_EQ_NUM_POPPED_SHIFT		(16)	/* bits 16 - 28 */
-/* Rearm bit */
-#define DB_EQ_REARM_SHIFT		(29)	/* bit 29 */
-
-/********* Compl Q door bell *************/
-#define DB_CQ_OFFSET 			0x120
-#define DB_CQ_RING_ID_MASK		0x3FF	/* bits 0 - 9 */
-#define DB_CQ_RING_ID_EXT_MASK		0x7C00	/* bits 10-14 */
-#define DB_CQ_RING_ID_EXT_MASK_SHIFT	(1)	/* qid bits 10-14
-						 placing at 11-15 */
-
-/* Number of event entries processed */
-#define DB_CQ_NUM_POPPED_SHIFT		(16) 	/* bits 16 - 28 */
-/* Rearm bit */
-#define DB_CQ_REARM_SHIFT		(29) 	/* bit 29 */
-
-/********** TX ULP door bell *************/
-#define DB_TXULP1_OFFSET		0x60
-#define DB_TXULP_RING_ID_MASK		0x7FF	/* bits 0 - 10 */
-/* Number of tx entries posted */
-#define DB_TXULP_NUM_POSTED_SHIFT	(16)	/* bits 16 - 29 */
-#define DB_TXULP_NUM_POSTED_MASK	0x3FFF	/* bits 16 - 29 */
-
-/********** RQ(erx) door bell ************/
-#define DB_RQ_OFFSET 			0x100
-#define DB_RQ_RING_ID_MASK		0x3FF	/* bits 0 - 9 */
-/* Number of rx frags posted */
-#define DB_RQ_NUM_POSTED_SHIFT		(24)	/* bits 24 - 31 */
-
-/********** MCC door bell ************/
-#define DB_MCCQ_OFFSET 			0x140
-#define DB_MCCQ_RING_ID_MASK		0x7FF	/* bits 0 - 10 */
-/* Number of entries posted */
-#define DB_MCCQ_NUM_POSTED_SHIFT	(16)	/* bits 16 - 29 */
-
-/********** SRIOV VF PCICFG OFFSET ********/
-#define SRIOV_VF_PCICFG_OFFSET		(4096)
-
-/********** FAT TABLE  ********/
-#define RETRIEVE_FAT	0
-#define QUERY_FAT	1
-
-/* Flashrom related descriptors */
-#define IMAGE_TYPE_FIRMWARE		160
-#define IMAGE_TYPE_BOOTCODE		224
-#define IMAGE_TYPE_OPTIONROM		32
-
-#define NUM_FLASHDIR_ENTRIES		32
-
-#define IMG_TYPE_ISCSI_ACTIVE		0
-#define IMG_TYPE_REDBOOT		1
-#define IMG_TYPE_BIOS			2
-#define IMG_TYPE_PXE_BIOS		3
-#define IMG_TYPE_FCOE_BIOS		8
-#define IMG_TYPE_ISCSI_BACKUP		9
-#define IMG_TYPE_FCOE_FW_ACTIVE		10
-#define IMG_TYPE_FCOE_FW_BACKUP 	11
-#define IMG_TYPE_NCSI_FW		13
-
-#define FLASHROM_OPER_FLASH		1
-#define FLASHROM_OPER_SAVE		2
-#define FLASHROM_OPER_REPORT		4
-
-#define FLASH_IMAGE_MAX_SIZE_g2            (1310720) /* Max firmware image sz */
-#define FLASH_BIOS_IMAGE_MAX_SIZE_g2       (262144)  /* Max OPTION ROM img sz */
-#define FLASH_REDBOOT_IMAGE_MAX_SIZE_g2	  (262144)  /* Max Redboot image sz */
-#define FLASH_IMAGE_MAX_SIZE_g3            (2097152) /* Max fw image size */
-#define FLASH_BIOS_IMAGE_MAX_SIZE_g3       (524288)  /* Max OPTION ROM img sz */
-#define FLASH_REDBOOT_IMAGE_MAX_SIZE_g3	  (1048576)  /* Max Redboot image sz */
-#define FLASH_NCSI_IMAGE_MAX_SIZE_g3       (262144)  /* Max NSCI image sz */
-
-#define FLASH_NCSI_MAGIC		(0x16032009)
-#define FLASH_NCSI_DISABLED		(0)
-#define FLASH_NCSI_ENABLED		(1)
-
-#define FLASH_NCSI_BITFILE_HDR_OFFSET	(0x600000)
-
-/* Offsets for components on Flash. */
-#define FLASH_iSCSI_PRIMARY_IMAGE_START_g2 (1048576)
-#define FLASH_iSCSI_BACKUP_IMAGE_START_g2  (2359296)
-#define FLASH_FCoE_PRIMARY_IMAGE_START_g2  (3670016)
-#define FLASH_FCoE_BACKUP_IMAGE_START_g2   (4980736)
-#define FLASH_iSCSI_BIOS_START_g2          (7340032)
-#define FLASH_PXE_BIOS_START_g2            (7864320)
-#define FLASH_FCoE_BIOS_START_g2           (524288)
-#define FLASH_REDBOOT_START_g2		  (0)
-
-#define FLASH_NCSI_START_g3		   (15990784)
-#define FLASH_iSCSI_PRIMARY_IMAGE_START_g3 (2097152)
-#define FLASH_iSCSI_BACKUP_IMAGE_START_g3  (4194304)
-#define FLASH_FCoE_PRIMARY_IMAGE_START_g3  (6291456)
-#define FLASH_FCoE_BACKUP_IMAGE_START_g3   (8388608)
-#define FLASH_iSCSI_BIOS_START_g3          (12582912)
-#define FLASH_PXE_BIOS_START_g3            (13107200)
-#define FLASH_FCoE_BIOS_START_g3           (13631488)
-#define FLASH_REDBOOT_START_g3             (262144)
-
-/************* Rx Packet Type Encoding **************/
-#define BE_UNICAST_PACKET		0
-#define BE_MULTICAST_PACKET		1
-#define BE_BROADCAST_PACKET		2
-#define BE_RSVD_PACKET			3
-
-/*
- * BE descriptors: host memory data structures whose formats
- * are hardwired in BE silicon.
- */
-/* Event Queue Descriptor */
-#define EQ_ENTRY_VALID_MASK 		0x1	/* bit 0 */
-#define EQ_ENTRY_RES_ID_MASK 		0xFFFF	/* bits 16 - 31 */
-#define EQ_ENTRY_RES_ID_SHIFT 		16
-
-struct be_eq_entry {
-	u32 evt;
-};
-
-/* TX Queue Descriptor */
-#define ETH_WRB_FRAG_LEN_MASK		0xFFFF
-struct be_eth_wrb {
-	u32 frag_pa_hi;		/* dword 0 */
-	u32 frag_pa_lo;		/* dword 1 */
-	u32 rsvd0;		/* dword 2 */
-	u32 frag_len;		/* dword 3: bits 0 - 15 */
-} __packed;
-
-/* Pseudo amap definition for eth_hdr_wrb 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_hdr_wrb {
-	u8 rsvd0[32];		/* dword 0 */
-	u8 rsvd1[32];		/* dword 1 */
-	u8 complete;		/* dword 2 */
-	u8 event;
-	u8 crc;
-	u8 forward;
-	u8 lso6;
-	u8 mgmt;
-	u8 ipcs;
-	u8 udpcs;
-	u8 tcpcs;
-	u8 lso;
-	u8 vlan;
-	u8 gso[2];
-	u8 num_wrb[5];
-	u8 lso_mss[14];
-	u8 len[16];		/* dword 3 */
-	u8 vlan_tag[16];
-} __packed;
-
-struct be_eth_hdr_wrb {
-	u32 dw[4];
-};
-
-/* TX Compl Queue Descriptor */
-
-/* Pseudo amap definition for eth_tx_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_tx_compl {
-	u8 wrb_index[16];	/* dword 0 */
-	u8 ct[2]; 		/* dword 0 */
-	u8 port[2];		/* dword 0 */
-	u8 rsvd0[8];		/* dword 0 */
-	u8 status[4];		/* dword 0 */
-	u8 user_bytes[16];	/* dword 1 */
-	u8 nwh_bytes[8];	/* dword 1 */
-	u8 lso;			/* dword 1 */
-	u8 cast_enc[2];		/* dword 1 */
-	u8 rsvd1[5];		/* dword 1 */
-	u8 rsvd2[32];		/* dword 2 */
-	u8 pkts[16];		/* dword 3 */
-	u8 ringid[11];		/* dword 3 */
-	u8 hash_val[4];		/* dword 3 */
-	u8 valid;		/* dword 3 */
-} __packed;
-
-struct be_eth_tx_compl {
-	u32 dw[4];
-};
-
-/* RX Queue Descriptor */
-struct be_eth_rx_d {
-	u32 fragpa_hi;
-	u32 fragpa_lo;
-};
-
-/* RX Compl Queue Descriptor */
-
-/* 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_v0 {
-	u8 vlan_tag[16];	/* dword 0 */
-	u8 pktsize[14];		/* dword 0 */
-	u8 port;		/* 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[6];		/* dword 1 */
-	u8 vtp;			/* 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 rsvd1[23];		/* dword 2 */
-	u8 lro_pkt;		/* dword 2 */
-	u8 rsvd2[2];		/* dword 2 */
-	u8 valid;		/* dword 2 */
-	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;
-	u32 subvendor;
-	u32 subdevice;
-};
-
-struct flash_comp {
-	unsigned long offset;
-	int optype;
-	int size;
-};
-
-struct image_hdr {
-	u32 imageid;
-	u32 imageoffset;
-	u32 imagelength;
-	u32 image_checksum;
-	u8 image_version[32];
-};
-struct flash_file_hdr_g2 {
-	u8 sign[32];
-	u32 cksum;
-	u32 antidote;
-	struct controller_id cont_id;
-	u32 file_len;
-	u32 chunk_num;
-	u32 total_chunks;
-	u32 num_imgs;
-	u8 build[24];
-};
-
-struct flash_file_hdr_g3 {
-	u8 sign[52];
-	u8 ufi_version[4];
-	u32 file_len;
-	u32 cksum;
-	u32 antidote;
-	u32 num_imgs;
-	u8 build[24];
-	u8 rsvd[32];
-};
-
-struct flash_section_hdr {
-	u32 format_rev;
-	u32 cksum;
-	u32 antidote;
-	u32 build_no;
-	u8 id_string[64];
-	u32 active_entry_mask;
-	u32 valid_entry_mask;
-	u32 org_content_mask;
-	u32 rsvd0;
-	u32 rsvd1;
-	u32 rsvd2;
-	u32 rsvd3;
-	u32 rsvd4;
-};
-
-struct flash_section_entry {
-	u32 type;
-	u32 offset;
-	u32 pad_size;
-	u32 image_size;
-	u32 cksum;
-	u32 entry_point;
-	u32 rsvd0;
-	u32 rsvd1;
-	u8 ver_data[32];
-};
-
-struct flash_section_info {
-	u8 cookie[32];
-	struct flash_section_hdr fsec_hdr;
-	struct flash_section_entry fsec_entry[32];
-};
diff -druN linux-libre-3.1-gnu/drivers/net/benet/be_main.c linux-libre-3.2-gnu/drivers/net/benet/be_main.c
--- linux-libre-3.1-gnu/drivers/net/benet/be_main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/benet/be_main.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3676 +0,0 @@
-/*
- * Copyright (C) 2005 - 2011 Emulex
- * 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.  The full GNU General
- * Public License is included in this distribution in the file called COPYING.
- *
- * Contact Information:
- * linux-drivers@emulex.com
- *
- * Emulex
- * 3333 Susan Street
- * Costa Mesa, CA 92626
- */
-
-#include <linux/prefetch.h>
-#include "be.h"
-#include "be_cmds.h"
-#include <asm/div64.h>
-
-MODULE_VERSION(DRV_VER);
-MODULE_DEVICE_TABLE(pci, be_dev_ids);
-MODULE_DESCRIPTION(DRV_DESC " " DRV_VER);
-MODULE_AUTHOR("ServerEngines Corporation");
-MODULE_LICENSE("GPL");
-
-static ushort rx_frag_size = 2048;
-static unsigned int num_vfs;
-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");
-
-static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
-	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
-	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
-	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
-	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) },
-	{ PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID3)},
-	{ PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID4)},
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, be_dev_ids);
-/* UE Status Low CSR */
-static const char * const ue_status_low_desc[] = {
-	"CEV",
-	"CTX",
-	"DBUF",
-	"ERX",
-	"Host",
-	"MPU",
-	"NDMA",
-	"PTC ",
-	"RDMA ",
-	"RXF ",
-	"RXIPS ",
-	"RXULP0 ",
-	"RXULP1 ",
-	"RXULP2 ",
-	"TIM ",
-	"TPOST ",
-	"TPRE ",
-	"TXIPS ",
-	"TXULP0 ",
-	"TXULP1 ",
-	"UC ",
-	"WDMA ",
-	"TXULP2 ",
-	"HOST1 ",
-	"P0_OB_LINK ",
-	"P1_OB_LINK ",
-	"HOST_GPIO ",
-	"MBOX ",
-	"AXGMAC0",
-	"AXGMAC1",
-	"JTAG",
-	"MPU_INTPEND"
-};
-/* UE Status High CSR */
-static const char * const ue_status_hi_desc[] = {
-	"LPCMEMHOST",
-	"MGMT_MAC",
-	"PCS0ONLINE",
-	"MPU_IRAM",
-	"PCS1ONLINE",
-	"PCTL0",
-	"PCTL1",
-	"PMEM",
-	"RR",
-	"TXPB",
-	"RXPP",
-	"XAUI",
-	"TXP",
-	"ARM",
-	"IPC",
-	"HOST2",
-	"HOST3",
-	"HOST4",
-	"HOST5",
-	"HOST6",
-	"HOST7",
-	"HOST8",
-	"HOST9",
-	"NETC",
-	"Unknown",
-	"Unknown",
-	"Unknown",
-	"Unknown",
-	"Unknown",
-	"Unknown",
-	"Unknown",
-	"Unknown"
-};
-
-static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q)
-{
-	struct be_dma_mem *mem = &q->dma_mem;
-	if (mem->va)
-		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,
-		u16 len, u16 entry_size)
-{
-	struct be_dma_mem *mem = &q->dma_mem;
-
-	memset(q, 0, sizeof(*q));
-	q->len = len;
-	q->entry_size = entry_size;
-	mem->size = len * entry_size;
-	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);
-	return 0;
-}
-
-static void be_intr_set(struct be_adapter *adapter, bool enable)
-{
-	u8 __iomem *addr = adapter->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET;
-	u32 reg = ioread32(addr);
-	u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
-
-	if (adapter->eeh_err)
-		return;
-
-	if (!enabled && enable)
-		reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
-	else if (enabled && !enable)
-		reg &= ~MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
-	else
-		return;
-
-	iowrite32(reg, addr);
-}
-
-static void be_rxq_notify(struct be_adapter *adapter, u16 qid, u16 posted)
-{
-	u32 val = 0;
-	val |= qid & DB_RQ_RING_ID_MASK;
-	val |= posted << DB_RQ_NUM_POSTED_SHIFT;
-
-	wmb();
-	iowrite32(val, adapter->db + DB_RQ_OFFSET);
-}
-
-static void be_txq_notify(struct be_adapter *adapter, u16 qid, u16 posted)
-{
-	u32 val = 0;
-	val |= qid & DB_TXULP_RING_ID_MASK;
-	val |= (posted & DB_TXULP_NUM_POSTED_MASK) << DB_TXULP_NUM_POSTED_SHIFT;
-
-	wmb();
-	iowrite32(val, adapter->db + DB_TXULP1_OFFSET);
-}
-
-static void be_eq_notify(struct be_adapter *adapter, u16 qid,
-		bool arm, bool clear_int, u16 num_popped)
-{
-	u32 val = 0;
-	val |= qid & DB_EQ_RING_ID_MASK;
-	val |= ((qid & DB_EQ_RING_ID_EXT_MASK) <<
-			DB_EQ_RING_ID_EXT_MASK_SHIFT);
-
-	if (adapter->eeh_err)
-		return;
-
-	if (arm)
-		val |= 1 << DB_EQ_REARM_SHIFT;
-	if (clear_int)
-		val |= 1 << DB_EQ_CLR_SHIFT;
-	val |= 1 << DB_EQ_EVNT_SHIFT;
-	val |= num_popped << DB_EQ_NUM_POPPED_SHIFT;
-	iowrite32(val, adapter->db + DB_EQ_OFFSET);
-}
-
-void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped)
-{
-	u32 val = 0;
-	val |= qid & DB_CQ_RING_ID_MASK;
-	val |= ((qid & DB_CQ_RING_ID_EXT_MASK) <<
-			DB_CQ_RING_ID_EXT_MASK_SHIFT);
-
-	if (adapter->eeh_err)
-		return;
-
-	if (arm)
-		val |= 1 << DB_CQ_REARM_SHIFT;
-	val |= num_popped << DB_CQ_NUM_POPPED_SHIFT;
-	iowrite32(val, adapter->db + DB_CQ_OFFSET);
-}
-
-static int be_mac_addr_set(struct net_device *netdev, void *p)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	struct sockaddr *addr = p;
-	int status = 0;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	/* MAC addr configuration will be done in hardware for VFs
-	 * by their corresponding PFs. Just copy to netdev addr here
-	 */
-	if (!be_physfn(adapter))
-		goto netdev_addr;
-
-	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, 0);
-netdev_addr:
-	if (!status)
-		memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-
-	return status;
-}
-
-static void populate_be2_stats(struct be_adapter *adapter)
-{
-
-	struct be_drv_stats *drvs = &adapter->drv_stats;
-	struct be_pmem_stats *pmem_sts = be_pmem_stats_from_cmd(adapter);
-	struct be_port_rxf_stats_v0 *port_stats =
-		be_port_rxf_stats_from_cmd(adapter);
-	struct be_rxf_stats_v0 *rxf_stats =
-		be_rxf_stats_from_cmd(adapter);
-
-	drvs->rx_pause_frames = port_stats->rx_pause_frames;
-	drvs->rx_crc_errors = port_stats->rx_crc_errors;
-	drvs->rx_control_frames = port_stats->rx_control_frames;
-	drvs->rx_in_range_errors = port_stats->rx_in_range_errors;
-	drvs->rx_frame_too_long = port_stats->rx_frame_too_long;
-	drvs->rx_dropped_runt = port_stats->rx_dropped_runt;
-	drvs->rx_ip_checksum_errs = port_stats->rx_ip_checksum_errs;
-	drvs->rx_tcp_checksum_errs = port_stats->rx_tcp_checksum_errs;
-	drvs->rx_udp_checksum_errs = port_stats->rx_udp_checksum_errs;
-	drvs->rxpp_fifo_overflow_drop = port_stats->rx_fifo_overflow;
-	drvs->rx_dropped_tcp_length = port_stats->rx_dropped_tcp_length;
-	drvs->rx_dropped_too_small = port_stats->rx_dropped_too_small;
-	drvs->rx_dropped_too_short = port_stats->rx_dropped_too_short;
-	drvs->rx_out_range_errors = port_stats->rx_out_range_errors;
-	drvs->rx_input_fifo_overflow_drop =
-		port_stats->rx_input_fifo_overflow;
-	drvs->rx_dropped_header_too_small =
-		port_stats->rx_dropped_header_too_small;
-	drvs->rx_address_match_errors =
-		port_stats->rx_address_match_errors;
-	drvs->rx_alignment_symbol_errors =
-		port_stats->rx_alignment_symbol_errors;
-
-	drvs->tx_pauseframes = port_stats->tx_pauseframes;
-	drvs->tx_controlframes = port_stats->tx_controlframes;
-
-	if (adapter->port_num)
-		drvs->jabber_events =
-			rxf_stats->port1_jabber_events;
-	else
-		drvs->jabber_events =
-			rxf_stats->port0_jabber_events;
-	drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf;
-	drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb;
-	drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr;
-	drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring;
-	drvs->forwarded_packets = rxf_stats->forwarded_packets;
-	drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu;
-	drvs->rx_drops_no_tpre_descr =
-		rxf_stats->rx_drops_no_tpre_descr;
-	drvs->rx_drops_too_many_frags =
-		rxf_stats->rx_drops_too_many_frags;
-	adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops;
-}
-
-static void populate_be3_stats(struct be_adapter *adapter)
-{
-	struct be_drv_stats *drvs = &adapter->drv_stats;
-	struct be_pmem_stats *pmem_sts = be_pmem_stats_from_cmd(adapter);
-
-	struct be_rxf_stats_v1 *rxf_stats =
-		be_rxf_stats_from_cmd(adapter);
-	struct be_port_rxf_stats_v1 *port_stats =
-		be_port_rxf_stats_from_cmd(adapter);
-
-	drvs->rx_priority_pause_frames = 0;
-	drvs->pmem_fifo_overflow_drop = 0;
-	drvs->rx_pause_frames = port_stats->rx_pause_frames;
-	drvs->rx_crc_errors = port_stats->rx_crc_errors;
-	drvs->rx_control_frames = port_stats->rx_control_frames;
-	drvs->rx_in_range_errors = port_stats->rx_in_range_errors;
-	drvs->rx_frame_too_long = port_stats->rx_frame_too_long;
-	drvs->rx_dropped_runt = port_stats->rx_dropped_runt;
-	drvs->rx_ip_checksum_errs = port_stats->rx_ip_checksum_errs;
-	drvs->rx_tcp_checksum_errs = port_stats->rx_tcp_checksum_errs;
-	drvs->rx_udp_checksum_errs = port_stats->rx_udp_checksum_errs;
-	drvs->rx_dropped_tcp_length = port_stats->rx_dropped_tcp_length;
-	drvs->rx_dropped_too_small = port_stats->rx_dropped_too_small;
-	drvs->rx_dropped_too_short = port_stats->rx_dropped_too_short;
-	drvs->rx_out_range_errors = port_stats->rx_out_range_errors;
-	drvs->rx_dropped_header_too_small =
-		port_stats->rx_dropped_header_too_small;
-	drvs->rx_input_fifo_overflow_drop =
-		port_stats->rx_input_fifo_overflow_drop;
-	drvs->rx_address_match_errors =
-		port_stats->rx_address_match_errors;
-	drvs->rx_alignment_symbol_errors =
-		port_stats->rx_alignment_symbol_errors;
-	drvs->rxpp_fifo_overflow_drop =
-		port_stats->rxpp_fifo_overflow_drop;
-	drvs->tx_pauseframes = port_stats->tx_pauseframes;
-	drvs->tx_controlframes = port_stats->tx_controlframes;
-	drvs->jabber_events = port_stats->jabber_events;
-	drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf;
-	drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb;
-	drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr;
-	drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring;
-	drvs->forwarded_packets = rxf_stats->forwarded_packets;
-	drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu;
-	drvs->rx_drops_no_tpre_descr =
-		rxf_stats->rx_drops_no_tpre_descr;
-	drvs->rx_drops_too_many_frags =
-		rxf_stats->rx_drops_too_many_frags;
-	adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops;
-}
-
-static void populate_lancer_stats(struct be_adapter *adapter)
-{
-
-	struct be_drv_stats *drvs = &adapter->drv_stats;
-	struct lancer_cmd_pport_stats *pport_stats = pport_stats_from_cmd
-						(adapter);
-	drvs->rx_priority_pause_frames = 0;
-	drvs->pmem_fifo_overflow_drop = 0;
-	drvs->rx_pause_frames =
-		make_64bit_val(pport_stats->rx_pause_frames_hi,
-				 pport_stats->rx_pause_frames_lo);
-	drvs->rx_crc_errors = make_64bit_val(pport_stats->rx_crc_errors_hi,
-						pport_stats->rx_crc_errors_lo);
-	drvs->rx_control_frames =
-			make_64bit_val(pport_stats->rx_control_frames_hi,
-			pport_stats->rx_control_frames_lo);
-	drvs->rx_in_range_errors = pport_stats->rx_in_range_errors;
-	drvs->rx_frame_too_long =
-		make_64bit_val(pport_stats->rx_internal_mac_errors_hi,
-					pport_stats->rx_frames_too_long_lo);
-	drvs->rx_dropped_runt = pport_stats->rx_dropped_runt;
-	drvs->rx_ip_checksum_errs = pport_stats->rx_ip_checksum_errors;
-	drvs->rx_tcp_checksum_errs = pport_stats->rx_tcp_checksum_errors;
-	drvs->rx_udp_checksum_errs = pport_stats->rx_udp_checksum_errors;
-	drvs->rx_dropped_tcp_length =
-				pport_stats->rx_dropped_invalid_tcp_length;
-	drvs->rx_dropped_too_small = pport_stats->rx_dropped_too_small;
-	drvs->rx_dropped_too_short = pport_stats->rx_dropped_too_short;
-	drvs->rx_out_range_errors = pport_stats->rx_out_of_range_errors;
-	drvs->rx_dropped_header_too_small =
-				pport_stats->rx_dropped_header_too_small;
-	drvs->rx_input_fifo_overflow_drop = pport_stats->rx_fifo_overflow;
-	drvs->rx_address_match_errors = pport_stats->rx_address_match_errors;
-	drvs->rx_alignment_symbol_errors =
-		make_64bit_val(pport_stats->rx_symbol_errors_hi,
-				pport_stats->rx_symbol_errors_lo);
-	drvs->rxpp_fifo_overflow_drop = pport_stats->rx_fifo_overflow;
-	drvs->tx_pauseframes = make_64bit_val(pport_stats->tx_pause_frames_hi,
-					pport_stats->tx_pause_frames_lo);
-	drvs->tx_controlframes =
-		make_64bit_val(pport_stats->tx_control_frames_hi,
-				pport_stats->tx_control_frames_lo);
-	drvs->jabber_events = pport_stats->rx_jabbers;
-	drvs->rx_drops_no_pbuf = 0;
-	drvs->rx_drops_no_txpb = 0;
-	drvs->rx_drops_no_erx_descr = 0;
-	drvs->rx_drops_invalid_ring = pport_stats->rx_drops_invalid_queue;
-	drvs->forwarded_packets = make_64bit_val(pport_stats->num_forwards_hi,
-						pport_stats->num_forwards_lo);
-	drvs->rx_drops_mtu = make_64bit_val(pport_stats->rx_drops_mtu_hi,
-						pport_stats->rx_drops_mtu_lo);
-	drvs->rx_drops_no_tpre_descr = 0;
-	drvs->rx_drops_too_many_frags =
-		make_64bit_val(pport_stats->rx_drops_too_many_frags_hi,
-				pport_stats->rx_drops_too_many_frags_lo);
-}
-
-void be_parse_stats(struct be_adapter *adapter)
-{
-	if (adapter->generation == BE_GEN3) {
-		if (lancer_chip(adapter))
-			populate_lancer_stats(adapter);
-		 else
-			populate_be3_stats(adapter);
-	} else {
-		populate_be2_stats(adapter);
-	}
-}
-
-void netdev_stats_update(struct be_adapter *adapter)
-{
-	struct be_drv_stats *drvs = &adapter->drv_stats;
-	struct net_device_stats *dev_stats = &adapter->netdev->stats;
-	struct be_rx_obj *rxo;
-	struct be_tx_obj *txo;
-	unsigned long pkts = 0, bytes = 0, mcast = 0, drops = 0;
-	int i;
-
-	for_all_rx_queues(adapter, rxo, i) {
-		pkts += rx_stats(rxo)->rx_pkts;
-		bytes += rx_stats(rxo)->rx_bytes;
-		mcast += rx_stats(rxo)->rx_mcast_pkts;
-		drops += rx_stats(rxo)->rx_dropped;
-		/*  no space in linux buffers: best possible approximation */
-		if (adapter->generation == BE_GEN3) {
-			if (!(lancer_chip(adapter))) {
-				struct be_erx_stats_v1 *erx =
-					be_erx_stats_from_cmd(adapter);
-				drops += erx->rx_drops_no_fragments[rxo->q.id];
-			}
-		} else {
-			struct be_erx_stats_v0 *erx =
-					be_erx_stats_from_cmd(adapter);
-			drops += erx->rx_drops_no_fragments[rxo->q.id];
-		}
-	}
-	dev_stats->rx_packets = pkts;
-	dev_stats->rx_bytes = bytes;
-	dev_stats->multicast = mcast;
-	dev_stats->rx_dropped = drops;
-
-	pkts = bytes = 0;
-	for_all_tx_queues(adapter, txo, i) {
-		pkts += tx_stats(txo)->be_tx_pkts;
-		bytes += tx_stats(txo)->be_tx_bytes;
-	}
-	dev_stats->tx_packets = pkts;
-	dev_stats->tx_bytes = bytes;
-
-	/* bad pkts received */
-	dev_stats->rx_errors = drvs->rx_crc_errors +
-		drvs->rx_alignment_symbol_errors +
-		drvs->rx_in_range_errors +
-		drvs->rx_out_range_errors +
-		drvs->rx_frame_too_long +
-		drvs->rx_dropped_too_small +
-		drvs->rx_dropped_too_short +
-		drvs->rx_dropped_header_too_small +
-		drvs->rx_dropped_tcp_length +
-		drvs->rx_dropped_runt +
-		drvs->rx_tcp_checksum_errs +
-		drvs->rx_ip_checksum_errs +
-		drvs->rx_udp_checksum_errs;
-
-	/* detailed rx errors */
-	dev_stats->rx_length_errors = drvs->rx_in_range_errors +
-		drvs->rx_out_range_errors +
-		drvs->rx_frame_too_long;
-
-	dev_stats->rx_crc_errors = drvs->rx_crc_errors;
-
-	/* frame alignment errors */
-	dev_stats->rx_frame_errors = drvs->rx_alignment_symbol_errors;
-
-	/* receiver fifo overrun */
-	/* drops_no_pbuf is no per i/f, it's per BE card */
-	dev_stats->rx_fifo_errors = drvs->rxpp_fifo_overflow_drop +
-				drvs->rx_input_fifo_overflow_drop +
-				drvs->rx_drops_no_pbuf;
-}
-
-void be_link_status_update(struct be_adapter *adapter, bool link_up)
-{
-	struct net_device *netdev = adapter->netdev;
-
-	/* If link came up or went down */
-	if (adapter->link_up != link_up) {
-		adapter->link_speed = -1;
-		if (link_up) {
-			netif_carrier_on(netdev);
-			printk(KERN_INFO "%s: Link up\n", netdev->name);
-		} else {
-			netif_carrier_off(netdev);
-			printk(KERN_INFO "%s: Link down\n", netdev->name);
-		}
-		adapter->link_up = link_up;
-	}
-}
-
-/* Update the EQ delay n BE based on the RX frags consumed / sec */
-static void be_rx_eqd_update(struct be_adapter *adapter, struct be_rx_obj *rxo)
-{
-	struct be_eq_obj *rx_eq = &rxo->rx_eq;
-	struct be_rx_stats *stats = &rxo->stats;
-	ulong now = jiffies;
-	u32 eqd;
-
-	if (!rx_eq->enable_aic)
-		return;
-
-	/* Wrapped around */
-	if (time_before(now, stats->rx_fps_jiffies)) {
-		stats->rx_fps_jiffies = now;
-		return;
-	}
-
-	/* Update once a second */
-	if ((now - stats->rx_fps_jiffies) < HZ)
-		return;
-
-	stats->rx_fps = (stats->rx_frags - stats->prev_rx_frags) /
-			((now - stats->rx_fps_jiffies) / HZ);
-
-	stats->rx_fps_jiffies = now;
-	stats->prev_rx_frags = stats->rx_frags;
-	eqd = stats->rx_fps / 110000;
-	eqd = eqd << 3;
-	if (eqd > rx_eq->max_eqd)
-		eqd = rx_eq->max_eqd;
-	if (eqd < rx_eq->min_eqd)
-		eqd = rx_eq->min_eqd;
-	if (eqd < 10)
-		eqd = 0;
-	if (eqd != rx_eq->cur_eqd)
-		be_cmd_modify_eqd(adapter, rx_eq->q.id, eqd);
-
-	rx_eq->cur_eqd = eqd;
-}
-
-static u32 be_calc_rate(u64 bytes, unsigned long ticks)
-{
-	u64 rate = bytes;
-
-	do_div(rate, ticks / HZ);
-	rate <<= 3;			/* bytes/sec -> bits/sec */
-	do_div(rate, 1000000ul);	/* MB/Sec */
-
-	return rate;
-}
-
-static void be_tx_rate_update(struct be_tx_obj *txo)
-{
-	struct be_tx_stats *stats = tx_stats(txo);
-	ulong now = jiffies;
-
-	/* Wrapped around? */
-	if (time_before(now, stats->be_tx_jiffies)) {
-		stats->be_tx_jiffies = now;
-		return;
-	}
-
-	/* Update tx rate once in two seconds */
-	if ((now - stats->be_tx_jiffies) > 2 * HZ) {
-		stats->be_tx_rate = be_calc_rate(stats->be_tx_bytes
-						  - stats->be_tx_bytes_prev,
-						 now - stats->be_tx_jiffies);
-		stats->be_tx_jiffies = now;
-		stats->be_tx_bytes_prev = stats->be_tx_bytes;
-	}
-}
-
-static void be_tx_stats_update(struct be_tx_obj *txo,
-			u32 wrb_cnt, u32 copied, u32 gso_segs, bool stopped)
-{
-	struct be_tx_stats *stats = tx_stats(txo);
-
-	stats->be_tx_reqs++;
-	stats->be_tx_wrbs += wrb_cnt;
-	stats->be_tx_bytes += copied;
-	stats->be_tx_pkts += (gso_segs ? gso_segs : 1);
-	if (stopped)
-		stats->be_tx_stops++;
-}
-
-/* Determine number of WRB entries needed to xmit data in an skb */
-static u32 wrb_cnt_for_skb(struct be_adapter *adapter, struct sk_buff *skb,
-								bool *dummy)
-{
-	int cnt = (skb->len > skb->data_len);
-
-	cnt += skb_shinfo(skb)->nr_frags;
-
-	/* to account for hdr wrb */
-	cnt++;
-	if (lancer_chip(adapter) || !(cnt & 1)) {
-		*dummy = false;
-	} else {
-		/* add a dummy to make it an even num */
-		cnt++;
-		*dummy = true;
-	}
-	BUG_ON(cnt > BE_MAX_TX_FRAG_COUNT);
-	return cnt;
-}
-
-static inline void wrb_fill(struct be_eth_wrb *wrb, u64 addr, int len)
-{
-	wrb->frag_pa_hi = upper_32_bits(addr);
-	wrb->frag_pa_lo = addr & 0xFFFFFFFF;
-	wrb->frag_len = len & ETH_WRB_FRAG_LEN_MASK;
-}
-
-static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr,
-		struct sk_buff *skb, u32 wrb_cnt, u32 len)
-{
-	u8 vlan_prio = 0;
-	u16 vlan_tag = 0;
-
-	memset(hdr, 0, sizeof(*hdr));
-
-	AMAP_SET_BITS(struct amap_eth_hdr_wrb, crc, hdr, 1);
-
-	if (skb_is_gso(skb)) {
-		AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso, hdr, 1);
-		AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso_mss,
-			hdr, skb_shinfo(skb)->gso_size);
-		if (skb_is_gso_v6(skb) && !lancer_chip(adapter))
-			AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso6, hdr, 1);
-		if (lancer_chip(adapter) && adapter->sli_family  ==
-							LANCER_A0_SLI_FAMILY) {
-			AMAP_SET_BITS(struct amap_eth_hdr_wrb, ipcs, hdr, 1);
-			if (is_tcp_pkt(skb))
-				AMAP_SET_BITS(struct amap_eth_hdr_wrb,
-								tcpcs, hdr, 1);
-			else if (is_udp_pkt(skb))
-				AMAP_SET_BITS(struct amap_eth_hdr_wrb,
-								udpcs, hdr, 1);
-		}
-	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		if (is_tcp_pkt(skb))
-			AMAP_SET_BITS(struct amap_eth_hdr_wrb, tcpcs, hdr, 1);
-		else if (is_udp_pkt(skb))
-			AMAP_SET_BITS(struct amap_eth_hdr_wrb, udpcs, hdr, 1);
-	}
-
-	if (vlan_tx_tag_present(skb)) {
-		AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1);
-		vlan_tag = vlan_tx_tag_get(skb);
-		vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
-		/* If vlan priority provided by OS is NOT in available bmap */
-		if (!(adapter->vlan_prio_bmap & (1 << vlan_prio)))
-			vlan_tag = (vlan_tag & ~VLAN_PRIO_MASK) |
-					adapter->recommended_prio;
-		AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan_tag, hdr, vlan_tag);
-	}
-
-	AMAP_SET_BITS(struct amap_eth_hdr_wrb, event, hdr, 1);
-	AMAP_SET_BITS(struct amap_eth_hdr_wrb, complete, hdr, 1);
-	AMAP_SET_BITS(struct amap_eth_hdr_wrb, num_wrb, hdr, wrb_cnt);
-	AMAP_SET_BITS(struct amap_eth_hdr_wrb, len, hdr, len);
-}
-
-static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb,
-		bool unmap_single)
-{
-	dma_addr_t dma;
-
-	be_dws_le_to_cpu(wrb, sizeof(*wrb));
-
-	dma = (u64)wrb->frag_pa_hi << 32 | (u64)wrb->frag_pa_lo;
-	if (wrb->frag_len) {
-		if (unmap_single)
-			dma_unmap_single(dev, dma, wrb->frag_len,
-					 DMA_TO_DEVICE);
-		else
-			dma_unmap_page(dev, dma, wrb->frag_len, DMA_TO_DEVICE);
-	}
-}
-
-static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq,
-		struct sk_buff *skb, u32 wrb_cnt, bool dummy_wrb)
-{
-	dma_addr_t busaddr;
-	int i, copied = 0;
-	struct device *dev = &adapter->pdev->dev;
-	struct sk_buff *first_skb = skb;
-	struct be_eth_wrb *wrb;
-	struct be_eth_hdr_wrb *hdr;
-	bool map_single = false;
-	u16 map_head;
-
-	hdr = queue_head_node(txq);
-	queue_head_inc(txq);
-	map_head = txq->head;
-
-	if (skb->len > skb->data_len) {
-		int len = skb_headlen(skb);
-		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);
-		wrb_fill(wrb, busaddr, len);
-		be_dws_cpu_to_le(wrb, sizeof(*wrb));
-		queue_head_inc(txq);
-		copied += len;
-	}
-
-	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-		struct skb_frag_struct *frag =
-			&skb_shinfo(skb)->frags[i];
-		busaddr = 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);
-		be_dws_cpu_to_le(wrb, sizeof(*wrb));
-		queue_head_inc(txq);
-		copied += frag->size;
-	}
-
-	if (dummy_wrb) {
-		wrb = queue_head_node(txq);
-		wrb_fill(wrb, 0, 0);
-		be_dws_cpu_to_le(wrb, sizeof(*wrb));
-		queue_head_inc(txq);
-	}
-
-	wrb_fill_hdr(adapter, hdr, first_skb, wrb_cnt, copied);
-	be_dws_cpu_to_le(hdr, sizeof(*hdr));
-
-	return copied;
-dma_err:
-	txq->head = map_head;
-	while (copied) {
-		wrb = queue_head_node(txq);
-		unmap_tx_frag(dev, wrb, map_single);
-		map_single = false;
-		copied -= wrb->frag_len;
-		queue_head_inc(txq);
-	}
-	return 0;
-}
-
-static netdev_tx_t be_xmit(struct sk_buff *skb,
-			struct net_device *netdev)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)];
-	struct be_queue_info *txq = &txo->q;
-	u32 wrb_cnt = 0, copied = 0;
-	u32 start = txq->head;
-	bool dummy_wrb, stopped = false;
-
-	wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb);
-
-	copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb);
-	if (copied) {
-		/* record the sent skb in the sent_skb table */
-		BUG_ON(txo->sent_skb_list[start]);
-		txo->sent_skb_list[start] = skb;
-
-		/* Ensure txq has space for the next skb; Else stop the queue
-		 * *BEFORE* ringing the tx doorbell, so that we serialze the
-		 * tx compls of the current transmit which'll wake up the queue
-		 */
-		atomic_add(wrb_cnt, &txq->used);
-		if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >=
-								txq->len) {
-			netif_stop_subqueue(netdev, skb_get_queue_mapping(skb));
-			stopped = true;
-		}
-
-		be_txq_notify(adapter, txq->id, wrb_cnt);
-
-		be_tx_stats_update(txo, wrb_cnt, copied,
-				skb_shinfo(skb)->gso_segs, stopped);
-	} else {
-		txq->head = start;
-		dev_kfree_skb_any(skb);
-	}
-	return NETDEV_TX_OK;
-}
-
-static int be_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	if (new_mtu < BE_MIN_MTU ||
-			new_mtu > (BE_MAX_JUMBO_FRAME_SIZE -
-					(ETH_HLEN + ETH_FCS_LEN))) {
-		dev_info(&adapter->pdev->dev,
-			"MTU must be between %d and %d bytes\n",
-			BE_MIN_MTU,
-			(BE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN)));
-		return -EINVAL;
-	}
-	dev_info(&adapter->pdev->dev, "MTU changed from %d to %d bytes\n",
-			netdev->mtu, new_mtu);
-	netdev->mtu = new_mtu;
-	return 0;
-}
-
-/*
- * A max of 64 (BE_NUM_VLANS_SUPPORTED) vlans can be configured in BE.
- * If the user configures more, place BE in vlan promiscuous mode.
- */
-static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num)
-{
-	u16 vtag[BE_NUM_VLANS_SUPPORTED];
-	u16 ntags = 0, i;
-	int status = 0;
-	u32 if_handle;
-
-	if (vf) {
-		if_handle = adapter->vf_cfg[vf_num].vf_if_handle;
-		vtag[0] = cpu_to_le16(adapter->vf_cfg[vf_num].vf_vlan_tag);
-		status = be_cmd_vlan_config(adapter, if_handle, vtag, 1, 1, 0);
-	}
-
-	if (adapter->vlans_added <= adapter->max_vlans)  {
-		/* Construct VLAN Table to give to HW */
-		for (i = 0; i < VLAN_N_VID; i++) {
-			if (adapter->vlan_tag[i]) {
-				vtag[ntags] = cpu_to_le16(i);
-				ntags++;
-			}
-		}
-		status = be_cmd_vlan_config(adapter, adapter->if_handle,
-					vtag, ntags, 1, 0);
-	} else {
-		status = be_cmd_vlan_config(adapter, adapter->if_handle,
-					NULL, 0, 1, 1);
-	}
-
-	return status;
-}
-
-static void be_vlan_add_vid(struct net_device *netdev, u16 vid)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-
-	adapter->vlans_added++;
-	if (!be_physfn(adapter))
-		return;
-
-	adapter->vlan_tag[vid] = 1;
-	if (adapter->vlans_added <= (adapter->max_vlans + 1))
-		be_vid_config(adapter, false, 0);
-}
-
-static void be_vlan_rem_vid(struct net_device *netdev, u16 vid)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-
-	adapter->vlans_added--;
-
-	if (!be_physfn(adapter))
-		return;
-
-	adapter->vlan_tag[vid] = 0;
-	if (adapter->vlans_added <= adapter->max_vlans)
-		be_vid_config(adapter, false, 0);
-}
-
-static void be_set_multicast_list(struct net_device *netdev)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-
-	if (netdev->flags & IFF_PROMISC) {
-		be_cmd_promiscuous_config(adapter, true);
-		adapter->promiscuous = true;
-		goto done;
-	}
-
-	/* BE was previously in promiscuous mode; disable it */
-	if (adapter->promiscuous) {
-		adapter->promiscuous = false;
-		be_cmd_promiscuous_config(adapter, false);
-	}
-
-	/* Enable multicast promisc if num configured exceeds what we support */
-	if (netdev->flags & IFF_ALLMULTI ||
-	    netdev_mc_count(netdev) > BE_MAX_MC) {
-		be_cmd_multicast_set(adapter, adapter->if_handle, NULL,
-				&adapter->mc_cmd_mem);
-		goto done;
-	}
-
-	be_cmd_multicast_set(adapter, adapter->if_handle, netdev,
-		&adapter->mc_cmd_mem);
-done:
-	return;
-}
-
-static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	int status;
-
-	if (!adapter->sriov_enabled)
-		return -EPERM;
-
-	if (!is_valid_ether_addr(mac) || (vf >= num_vfs))
-		return -EINVAL;
-
-	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, vf + 1);
-
-	status = be_cmd_pmac_add(adapter, mac,
-				adapter->vf_cfg[vf].vf_if_handle,
-				&adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
-
-	if (status)
-		dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed\n",
-				mac, vf);
-	else
-		memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN);
-
-	return status;
-}
-
-static int be_get_vf_config(struct net_device *netdev, int vf,
-			struct ifla_vf_info *vi)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-
-	if (!adapter->sriov_enabled)
-		return -EPERM;
-
-	if (vf >= num_vfs)
-		return -EINVAL;
-
-	vi->vf = vf;
-	vi->tx_rate = adapter->vf_cfg[vf].vf_tx_rate;
-	vi->vlan = adapter->vf_cfg[vf].vf_vlan_tag;
-	vi->qos = 0;
-	memcpy(&vi->mac, adapter->vf_cfg[vf].vf_mac_addr, ETH_ALEN);
-
-	return 0;
-}
-
-static int be_set_vf_vlan(struct net_device *netdev,
-			int vf, u16 vlan, u8 qos)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	int status = 0;
-
-	if (!adapter->sriov_enabled)
-		return -EPERM;
-
-	if ((vf >= num_vfs) || (vlan > 4095))
-		return -EINVAL;
-
-	if (vlan) {
-		adapter->vf_cfg[vf].vf_vlan_tag = vlan;
-		adapter->vlans_added++;
-	} else {
-		adapter->vf_cfg[vf].vf_vlan_tag = 0;
-		adapter->vlans_added--;
-	}
-
-	status = be_vid_config(adapter, true, vf);
-
-	if (status)
-		dev_info(&adapter->pdev->dev,
-				"VLAN %d config on VF %d failed\n", vlan, vf);
-	return status;
-}
-
-static int be_set_vf_tx_rate(struct net_device *netdev,
-			int vf, int rate)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	int status = 0;
-
-	if (!adapter->sriov_enabled)
-		return -EPERM;
-
-	if ((vf >= num_vfs) || (rate < 0))
-		return -EINVAL;
-
-	if (rate > 10000)
-		rate = 10000;
-
-	adapter->vf_cfg[vf].vf_tx_rate = rate;
-	status = be_cmd_set_qos(adapter, rate / 10, vf + 1);
-
-	if (status)
-		dev_info(&adapter->pdev->dev,
-				"tx rate %d on VF %d failed\n", rate, vf);
-	return status;
-}
-
-static void be_rx_rate_update(struct be_rx_obj *rxo)
-{
-	struct be_rx_stats *stats = &rxo->stats;
-	ulong now = jiffies;
-
-	/* Wrapped around */
-	if (time_before(now, stats->rx_jiffies)) {
-		stats->rx_jiffies = now;
-		return;
-	}
-
-	/* Update the rate once in two seconds */
-	if ((now - stats->rx_jiffies) < 2 * HZ)
-		return;
-
-	stats->rx_rate = be_calc_rate(stats->rx_bytes - stats->rx_bytes_prev,
-				now - stats->rx_jiffies);
-	stats->rx_jiffies = now;
-	stats->rx_bytes_prev = stats->rx_bytes;
-}
-
-static void be_rx_stats_update(struct be_rx_obj *rxo,
-		struct be_rx_compl_info *rxcp)
-{
-	struct be_rx_stats *stats = &rxo->stats;
-
-	stats->rx_compl++;
-	stats->rx_frags += rxcp->num_rcvd;
-	stats->rx_bytes += rxcp->pkt_size;
-	stats->rx_pkts++;
-	if (rxcp->pkt_type == BE_MULTICAST_PACKET)
-		stats->rx_mcast_pkts++;
-	if (rxcp->err)
-		stats->rxcp_err++;
-}
-
-static inline bool csum_passed(struct be_rx_compl_info *rxcp)
-{
-	/* 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 *
-get_rx_page_info(struct be_adapter *adapter,
-		struct be_rx_obj *rxo,
-		u16 frag_idx)
-{
-	struct be_rx_page_info *rx_page_info;
-	struct be_queue_info *rxq = &rxo->q;
-
-	rx_page_info = &rxo->page_info_tbl[frag_idx];
-	BUG_ON(!rx_page_info->page);
-
-	if (rx_page_info->last_page_user) {
-		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;
-	}
-
-	atomic_dec(&rxq->used);
-	return rx_page_info;
-}
-
-/* Throwaway the data in the Rx completion */
-static void be_rx_compl_discard(struct be_adapter *adapter,
-		struct be_rx_obj *rxo,
-		struct be_rx_compl_info *rxcp)
-{
-	struct be_queue_info *rxq = &rxo->q;
-	struct be_rx_page_info *page_info;
-	u16 i, num_rcvd = rxcp->num_rcvd;
-
-	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);
-	}
-}
-
-/*
- * skb_fill_rx_data forms a complete skb for an ether frame
- * indicated by rxcp.
- */
-static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo,
-			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 i, j;
-	u16 hdr_len, curr_frag_len, remaining;
-	u8 *start;
-
-	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(rxcp->pkt_size, rx_frag_size);
-
-	/* Copy the header portion into skb_data */
-	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 */
-		/* Complete packet has now been moved to data */
-		put_page(page_info->page);
-		skb->data_len = 0;
-		skb->tail += curr_frag_len;
-	} else {
-		skb_shinfo(skb)->nr_frags = 1;
-		skb_shinfo(skb)->frags[0].page = page_info->page;
-		skb_shinfo(skb)->frags[0].page_offset =
-					page_info->page_offset + hdr_len;
-		skb_shinfo(skb)->frags[0].size = curr_frag_len - hdr_len;
-		skb->data_len = curr_frag_len - hdr_len;
-		skb->tail += hdr_len;
-	}
-	page_info->page = NULL;
-
-	if (rxcp->pkt_size <= rx_frag_size) {
-		BUG_ON(rxcp->num_rcvd != 1);
-		return;
-	}
-
-	/* More frags present for this completion */
-	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) {
-			/* Fresh page */
-			j++;
-			skb_shinfo(skb)->frags[j].page = page_info->page;
-			skb_shinfo(skb)->frags[j].page_offset =
-							page_info->page_offset;
-			skb_shinfo(skb)->frags[j].size = 0;
-			skb_shinfo(skb)->nr_frags++;
-		} else {
-			put_page(page_info->page);
-		}
-
-		skb_shinfo(skb)->frags[j].size += curr_frag_len;
-		skb->len += curr_frag_len;
-		skb->data_len += curr_frag_len;
-
-		remaining -= curr_frag_len;
-		index_inc(&rxcp->rxq_idx, rxq->len);
-		page_info->page = NULL;
-	}
-	BUG_ON(j > MAX_SKB_FRAGS);
-}
-
-/* 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_rx_compl_info *rxcp)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct sk_buff *skb;
-
-	skb = netdev_alloc_skb_ip_align(netdev, BE_HDR_LEN);
-	if (unlikely(!skb)) {
-		rxo->stats.rx_dropped++;
-		be_rx_compl_discard(adapter, rxo, rxcp);
-		return;
-	}
-
-	skb_fill_rx_data(adapter, rxo, skb, rxcp);
-
-	if (likely((netdev->features & NETIF_F_RXCSUM) && csum_passed(rxcp)))
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	else
-		skb_checksum_none_assert(skb);
-
-	skb->truesize = skb->len + sizeof(struct sk_buff);
-	skb->protocol = eth_type_trans(skb, netdev);
-	if (adapter->netdev->features & NETIF_F_RXHASH)
-		skb->rxhash = rxcp->rss_hash;
-
-
-	if (unlikely(rxcp->vlanf))
-		__vlan_hwaccel_put_tag(skb, rxcp->vlan_tag);
-
-	netif_receive_skb(skb);
-}
-
-/* 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_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;
-	u16 remaining, curr_frag_len;
-	u16 i, j;
-
-	skb = napi_get_frags(&eq_obj->napi);
-	if (!skb) {
-		be_rx_compl_discard(adapter, rxo, rxcp);
-		return;
-	}
-
-	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);
-
-		/* Coalesce all frags from the same physical page in one slot */
-		if (i == 0 || page_info->page_offset == 0) {
-			/* First frag or Fresh page */
-			j++;
-			skb_shinfo(skb)->frags[j].page = page_info->page;
-			skb_shinfo(skb)->frags[j].page_offset =
-							page_info->page_offset;
-			skb_shinfo(skb)->frags[j].size = 0;
-		} else {
-			put_page(page_info->page);
-		}
-		skb_shinfo(skb)->frags[j].size += curr_frag_len;
-
-		remaining -= curr_frag_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 = rxcp->pkt_size;
-	skb->data_len = rxcp->pkt_size;
-	skb->truesize += rxcp->pkt_size;
-	skb->ip_summed = CHECKSUM_UNNECESSARY;
-	if (adapter->netdev->features & NETIF_F_RXHASH)
-		skb->rxhash = rxcp->rss_hash;
-
-	if (unlikely(rxcp->vlanf))
-		__vlan_hwaccel_put_tag(skb, rxcp->vlan_tag);
-
-	napi_gro_frags(&eq_obj->napi);
-}
-
-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->rss_hash =
-		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, rsshash, rxcp);
-	if (rxcp->vlanf) {
-		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);
-	}
-}
-
-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->rss_hash =
-		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, rsshash, rxcp);
-	if (rxcp->vlanf) {
-		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_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
-{
-	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;
-
-	/* 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(compl, sizeof(*compl));
-
-	if (adapter->be3_native)
-		be_parse_rx_compl_v1(adapter, compl, rxcp);
-	else
-		be_parse_rx_compl_v0(adapter, compl, rxcp);
-
-	if (rxcp->vlanf) {
-		/* 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;
-}
-
-static inline struct page *be_alloc_pages(u32 size, gfp_t gfp)
-{
-	u32 order = get_order(size);
-
-	if (order > 0)
-		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, gfp_t gfp)
-{
-	struct be_adapter *adapter = rxo->adapter;
-	struct be_rx_page_info *page_info_tbl = rxo->page_info_tbl;
-	struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL;
-	struct be_queue_info *rxq = &rxo->q;
-	struct page *pagep = NULL;
-	struct be_eth_rx_d *rxd;
-	u64 page_dmaaddr = 0, frag_dmaaddr;
-	u32 posted, page_offset = 0;
-
-	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, gfp);
-			if (unlikely(!pagep)) {
-				rxo->stats.rx_post_fail++;
-				break;
-			}
-			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);
-			page_info->page_offset = page_offset + rx_frag_size;
-		}
-		page_offset = page_info->page_offset;
-		page_info->page = pagep;
-		dma_unmap_addr_set(page_info, bus, page_dmaaddr);
-		frag_dmaaddr = page_dmaaddr + page_info->page_offset;
-
-		rxd = queue_head_node(rxq);
-		rxd->fragpa_lo = cpu_to_le32(frag_dmaaddr & 0xFFFFFFFF);
-		rxd->fragpa_hi = cpu_to_le32(upper_32_bits(frag_dmaaddr));
-
-		/* Any space left in the current big page for another frag? */
-		if ((page_offset + rx_frag_size + rx_frag_size) >
-					adapter->big_page_size) {
-			pagep = NULL;
-			page_info->last_page_user = true;
-		}
-
-		prev_page_info = page_info;
-		queue_head_inc(rxq);
-		page_info = &page_info_tbl[rxq->head];
-	}
-	if (pagep)
-		prev_page_info->last_page_user = true;
-
-	if (posted) {
-		atomic_add(posted, &rxq->used);
-		be_rxq_notify(adapter, rxq->id, posted);
-	} else if (atomic_read(&rxq->used) == 0) {
-		/* Let be_worker replenish when memory is available */
-		rxo->rx_post_starved = true;
-	}
-}
-
-static struct be_eth_tx_compl *be_tx_compl_get(struct be_queue_info *tx_cq)
-{
-	struct be_eth_tx_compl *txcp = queue_tail_node(tx_cq);
-
-	if (txcp->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] == 0)
-		return NULL;
-
-	rmb();
-	be_dws_le_to_cpu(txcp, sizeof(*txcp));
-
-	txcp->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] = 0;
-
-	queue_tail_inc(tx_cq);
-	return txcp;
-}
-
-static u16 be_tx_compl_process(struct be_adapter *adapter,
-		struct be_tx_obj *txo, u16 last_index)
-{
-	struct be_queue_info *txq = &txo->q;
-	struct be_eth_wrb *wrb;
-	struct sk_buff **sent_skbs = txo->sent_skb_list;
-	struct sk_buff *sent_skb;
-	u16 cur_index, num_wrbs = 1; /* account for hdr wrb */
-	bool unmap_skb_hdr = true;
-
-	sent_skb = sent_skbs[txq->tail];
-	BUG_ON(!sent_skb);
-	sent_skbs[txq->tail] = NULL;
-
-	/* skip header wrb */
-	queue_tail_inc(txq);
-
-	do {
-		cur_index = txq->tail;
-		wrb = queue_tail_node(txq);
-		unmap_tx_frag(&adapter->pdev->dev, wrb,
-			      (unmap_skb_hdr && skb_headlen(sent_skb)));
-		unmap_skb_hdr = false;
-
-		num_wrbs++;
-		queue_tail_inc(txq);
-	} while (cur_index != last_index);
-
-	kfree_skb(sent_skb);
-	return num_wrbs;
-}
-
-static inline struct be_eq_entry *event_get(struct be_eq_obj *eq_obj)
-{
-	struct be_eq_entry *eqe = queue_tail_node(&eq_obj->q);
-
-	if (!eqe->evt)
-		return NULL;
-
-	rmb();
-	eqe->evt = le32_to_cpu(eqe->evt);
-	queue_tail_inc(&eq_obj->q);
-	return eqe;
-}
-
-static int event_handle(struct be_adapter *adapter,
-			struct be_eq_obj *eq_obj,
-			bool rearm)
-{
-	struct be_eq_entry *eqe;
-	u16 num = 0;
-
-	while ((eqe = event_get(eq_obj)) != NULL) {
-		eqe->evt = 0;
-		num++;
-	}
-
-	/* Deal with any spurious interrupts that come
-	 * without events
-	 */
-	if (!num)
-		rearm = true;
-
-	be_eq_notify(adapter, eq_obj->q.id, rearm, true, num);
-	if (num)
-		napi_schedule(&eq_obj->napi);
-
-	return num;
-}
-
-/* Just read and notify events without processing them.
- * Used at the time of destroying event queues */
-static void be_eq_clean(struct be_adapter *adapter,
-			struct be_eq_obj *eq_obj)
-{
-	struct be_eq_entry *eqe;
-	u16 num = 0;
-
-	while ((eqe = event_get(eq_obj)) != NULL) {
-		eqe->evt = 0;
-		num++;
-	}
-
-	if (num)
-		be_eq_notify(adapter, eq_obj->q.id, false, true, num);
-}
-
-static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo)
-{
-	struct be_rx_page_info *page_info;
-	struct be_queue_info *rxq = &rxo->q;
-	struct be_queue_info *rx_cq = &rxo->cq;
-	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_cq_notify(adapter, rx_cq->id, false, 1);
-	}
-
-	/* Then free posted rx buffer that were not used */
-	tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len;
-	for (; atomic_read(&rxq->used) > 0; index_inc(&tail, rxq->len)) {
-		page_info = get_rx_page_info(adapter, rxo, tail);
-		put_page(page_info->page);
-		memset(page_info, 0, sizeof(*page_info));
-	}
-	BUG_ON(atomic_read(&rxq->used));
-	rxq->tail = rxq->head = 0;
-}
-
-static void be_tx_compl_clean(struct be_adapter *adapter,
-				struct be_tx_obj *txo)
-{
-	struct be_queue_info *tx_cq = &txo->cq;
-	struct be_queue_info *txq = &txo->q;
-	struct be_eth_tx_compl *txcp;
-	u16 end_idx, cmpl = 0, timeo = 0, num_wrbs = 0;
-	struct sk_buff **sent_skbs = txo->sent_skb_list;
-	struct sk_buff *sent_skb;
-	bool dummy_wrb;
-
-	/* Wait for a max of 200ms for all the tx-completions to arrive. */
-	do {
-		while ((txcp = be_tx_compl_get(tx_cq))) {
-			end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl,
-					wrb_index, txcp);
-			num_wrbs += be_tx_compl_process(adapter, txo, end_idx);
-			cmpl++;
-		}
-		if (cmpl) {
-			be_cq_notify(adapter, tx_cq->id, false, cmpl);
-			atomic_sub(num_wrbs, &txq->used);
-			cmpl = 0;
-			num_wrbs = 0;
-		}
-
-		if (atomic_read(&txq->used) == 0 || ++timeo > 200)
-			break;
-
-		mdelay(1);
-	} while (true);
-
-	if (atomic_read(&txq->used))
-		dev_err(&adapter->pdev->dev, "%d pending tx-completions\n",
-			atomic_read(&txq->used));
-
-	/* free posted tx for which compls will never arrive */
-	while (atomic_read(&txq->used)) {
-		sent_skb = sent_skbs[txq->tail];
-		end_idx = txq->tail;
-		index_adv(&end_idx,
-			wrb_cnt_for_skb(adapter, sent_skb, &dummy_wrb) - 1,
-			txq->len);
-		num_wrbs = be_tx_compl_process(adapter, txo, end_idx);
-		atomic_sub(num_wrbs, &txq->used);
-	}
-}
-
-static void be_mcc_queues_destroy(struct be_adapter *adapter)
-{
-	struct be_queue_info *q;
-
-	q = &adapter->mcc_obj.q;
-	if (q->created)
-		be_cmd_q_destroy(adapter, q, QTYPE_MCCQ);
-	be_queue_free(adapter, q);
-
-	q = &adapter->mcc_obj.cq;
-	if (q->created)
-		be_cmd_q_destroy(adapter, q, QTYPE_CQ);
-	be_queue_free(adapter, q);
-}
-
-/* Must be called only after TX qs are created as MCC shares TX EQ */
-static int be_mcc_queues_create(struct be_adapter *adapter)
-{
-	struct be_queue_info *q, *cq;
-
-	/* Alloc MCC compl queue */
-	cq = &adapter->mcc_obj.cq;
-	if (be_queue_alloc(adapter, cq, MCC_CQ_LEN,
-			sizeof(struct be_mcc_compl)))
-		goto err;
-
-	/* Ask BE to create MCC compl queue; share TX's eq */
-	if (be_cmd_cq_create(adapter, cq, &adapter->tx_eq.q, false, true, 0))
-		goto mcc_cq_free;
-
-	/* Alloc MCC queue */
-	q = &adapter->mcc_obj.q;
-	if (be_queue_alloc(adapter, q, MCC_Q_LEN, sizeof(struct be_mcc_wrb)))
-		goto mcc_cq_destroy;
-
-	/* Ask BE to create MCC queue */
-	if (be_cmd_mccq_create(adapter, q, cq))
-		goto mcc_q_free;
-
-	return 0;
-
-mcc_q_free:
-	be_queue_free(adapter, q);
-mcc_cq_destroy:
-	be_cmd_q_destroy(adapter, cq, QTYPE_CQ);
-mcc_cq_free:
-	be_queue_free(adapter, cq);
-err:
-	return -1;
-}
-
-static void be_tx_queues_destroy(struct be_adapter *adapter)
-{
-	struct be_queue_info *q;
-	struct be_tx_obj *txo;
-	u8 i;
-
-	for_all_tx_queues(adapter, txo, i) {
-		q = &txo->q;
-		if (q->created)
-			be_cmd_q_destroy(adapter, q, QTYPE_TXQ);
-		be_queue_free(adapter, q);
-
-		q = &txo->cq;
-		if (q->created)
-			be_cmd_q_destroy(adapter, q, QTYPE_CQ);
-		be_queue_free(adapter, q);
-	}
-
-	/* Clear any residual events */
-	be_eq_clean(adapter, &adapter->tx_eq);
-
-	q = &adapter->tx_eq.q;
-	if (q->created)
-		be_cmd_q_destroy(adapter, q, QTYPE_EQ);
-	be_queue_free(adapter, q);
-}
-
-/* One TX event queue is shared by all TX compl qs */
-static int be_tx_queues_create(struct be_adapter *adapter)
-{
-	struct be_queue_info *eq, *q, *cq;
-	struct be_tx_obj *txo;
-	u8 i;
-
-	adapter->tx_eq.max_eqd = 0;
-	adapter->tx_eq.min_eqd = 0;
-	adapter->tx_eq.cur_eqd = 96;
-	adapter->tx_eq.enable_aic = false;
-
-	eq = &adapter->tx_eq.q;
-	if (be_queue_alloc(adapter, eq, EVNT_Q_LEN,
-		sizeof(struct be_eq_entry)))
-		return -1;
-
-	if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd))
-		goto err;
-	adapter->tx_eq.eq_idx = adapter->eq_next_idx++;
-
-	for_all_tx_queues(adapter, txo, i) {
-		cq = &txo->cq;
-		if (be_queue_alloc(adapter, cq, TX_CQ_LEN,
-			sizeof(struct be_eth_tx_compl)))
-			goto err;
-
-		if (be_cmd_cq_create(adapter, cq, eq, false, false, 3))
-			goto err;
-
-		q = &txo->q;
-		if (be_queue_alloc(adapter, q, TX_Q_LEN,
-			sizeof(struct be_eth_wrb)))
-			goto err;
-
-		if (be_cmd_txq_create(adapter, q, cq))
-			goto err;
-	}
-	return 0;
-
-err:
-	be_tx_queues_destroy(adapter);
-	return -1;
-}
-
-static void be_rx_queues_destroy(struct be_adapter *adapter)
-{
-	struct be_queue_info *q;
-	struct be_rx_obj *rxo;
-	int i;
-
-	for_all_rx_queues(adapter, rxo, i) {
-		be_queue_free(adapter, &rxo->q);
-
-		q = &rxo->cq;
-		if (q->created)
-			be_cmd_q_destroy(adapter, q, QTYPE_CQ);
-		be_queue_free(adapter, q);
-
-		q = &rxo->rx_eq.q;
-		if (q->created)
-			be_cmd_q_destroy(adapter, q, QTYPE_EQ);
-		be_queue_free(adapter, q);
-	}
-}
-
-static u32 be_num_rxqs_want(struct be_adapter *adapter)
-{
-	if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
-		!adapter->sriov_enabled && !(adapter->function_mode & 0x400)) {
-		return 1 + MAX_RSS_QS; /* one default non-RSS queue */
-	} else {
-		dev_warn(&adapter->pdev->dev,
-			"No support for multiple RX queues\n");
-		return 1;
-	}
-}
-
-static int be_rx_queues_create(struct be_adapter *adapter)
-{
-	struct be_queue_info *eq, *q, *cq;
-	struct be_rx_obj *rxo;
-	int rc, i;
-
-	adapter->num_rx_qs = min(be_num_rxqs_want(adapter),
-				msix_enabled(adapter) ?
-					adapter->num_msix_vec - 1 : 1);
-	if (adapter->num_rx_qs != MAX_RX_QS)
-		dev_warn(&adapter->pdev->dev,
-			"Can create only %d RX queues", adapter->num_rx_qs);
-
-	adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE;
-	for_all_rx_queues(adapter, rxo, i) {
-		rxo->adapter = adapter;
-		rxo->rx_eq.max_eqd = BE_MAX_EQD;
-		rxo->rx_eq.enable_aic = true;
-
-		/* EQ */
-		eq = &rxo->rx_eq.q;
-		rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN,
-					sizeof(struct be_eq_entry));
-		if (rc)
-			goto err;
-
-		rc = be_cmd_eq_create(adapter, eq, rxo->rx_eq.cur_eqd);
-		if (rc)
-			goto err;
-
-		rxo->rx_eq.eq_idx = adapter->eq_next_idx++;
-
-		/* CQ */
-		cq = &rxo->cq;
-		rc = be_queue_alloc(adapter, cq, RX_CQ_LEN,
-				sizeof(struct be_eth_rx_compl));
-		if (rc)
-			goto err;
-
-		rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3);
-		if (rc)
-			goto err;
-
-		/* Rx Q - will be created in be_open() */
-		q = &rxo->q;
-		rc = be_queue_alloc(adapter, q, RX_Q_LEN,
-				sizeof(struct be_eth_rx_d));
-		if (rc)
-			goto err;
-
-	}
-
-	return 0;
-err:
-	be_rx_queues_destroy(adapter);
-	return -1;
-}
-
-static bool event_peek(struct be_eq_obj *eq_obj)
-{
-	struct be_eq_entry *eqe = queue_tail_node(&eq_obj->q);
-	if (!eqe->evt)
-		return false;
-	else
-		return true;
-}
-
-static irqreturn_t be_intx(int irq, void *dev)
-{
-	struct be_adapter *adapter = dev;
-	struct be_rx_obj *rxo;
-	int isr, i, tx = 0 , rx = 0;
-
-	if (lancer_chip(adapter)) {
-		if (event_peek(&adapter->tx_eq))
-			tx = event_handle(adapter, &adapter->tx_eq, false);
-		for_all_rx_queues(adapter, rxo, i) {
-			if (event_peek(&rxo->rx_eq))
-				rx |= event_handle(adapter, &rxo->rx_eq, true);
-		}
-
-		if (!(tx || rx))
-			return IRQ_NONE;
-
-	} else {
-		isr = ioread32(adapter->csr + CEV_ISR0_OFFSET +
-			(adapter->tx_eq.q.id / 8) * CEV_ISR_SIZE);
-		if (!isr)
-			return IRQ_NONE;
-
-		if ((1 << adapter->tx_eq.eq_idx & isr))
-			event_handle(adapter, &adapter->tx_eq, false);
-
-		for_all_rx_queues(adapter, rxo, i) {
-			if ((1 << rxo->rx_eq.eq_idx & isr))
-				event_handle(adapter, &rxo->rx_eq, true);
-		}
-	}
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t be_msix_rx(int irq, void *dev)
-{
-	struct be_rx_obj *rxo = dev;
-	struct be_adapter *adapter = rxo->adapter;
-
-	event_handle(adapter, &rxo->rx_eq, true);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t be_msix_tx_mcc(int irq, void *dev)
-{
-	struct be_adapter *adapter = dev;
-
-	event_handle(adapter, &adapter->tx_eq, false);
-
-	return IRQ_HANDLED;
-}
-
-static inline bool do_gro(struct be_rx_compl_info *rxcp)
-{
-	return (rxcp->tcpf && !rxcp->err) ? true : false;
-}
-
-static int be_poll_rx(struct napi_struct *napi, int budget)
-{
-	struct be_eq_obj *rx_eq = container_of(napi, struct be_eq_obj, napi);
-	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_rx_compl_info *rxcp;
-	u32 work_done;
-
-	rxo->stats.rx_polls++;
-	for (work_done = 0; work_done < budget; work_done++) {
-		rxcp = be_rx_compl_get(rxo);
-		if (!rxcp)
-			break;
-
-		/* Ignore flush completions */
-		if (rxcp->num_rcvd && rxcp->pkt_size) {
-			if (do_gro(rxcp))
-				be_rx_compl_process_gro(adapter, rxo, rxcp);
-			else
-				be_rx_compl_process(adapter, rxo, rxcp);
-		} else if (rxcp->pkt_size == 0) {
-			be_rx_compl_discard(adapter, rxo, 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, GFP_ATOMIC);
-
-	/* All consumed */
-	if (work_done < budget) {
-		napi_complete(napi);
-		be_cq_notify(adapter, rx_cq->id, true, work_done);
-	} else {
-		/* More to be consumed; continue with interrupts disabled */
-		be_cq_notify(adapter, rx_cq->id, false, work_done);
-	}
-	return work_done;
-}
-
-/* As TX and MCC share the same EQ check for both TX and MCC completions.
- * For TX/MCC we don't honour budget; consume everything
- */
-static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
-{
-	struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi);
-	struct be_adapter *adapter =
-		container_of(tx_eq, struct be_adapter, tx_eq);
-	struct be_tx_obj *txo;
-	struct be_eth_tx_compl *txcp;
-	int tx_compl, mcc_compl, status = 0;
-	u8 i;
-	u16 num_wrbs;
-
-	for_all_tx_queues(adapter, txo, i) {
-		tx_compl = 0;
-		num_wrbs = 0;
-		while ((txcp = be_tx_compl_get(&txo->cq))) {
-			num_wrbs += be_tx_compl_process(adapter, txo,
-				AMAP_GET_BITS(struct amap_eth_tx_compl,
-					wrb_index, txcp));
-			tx_compl++;
-		}
-		if (tx_compl) {
-			be_cq_notify(adapter, txo->cq.id, true, tx_compl);
-
-			atomic_sub(num_wrbs, &txo->q.used);
-
-			/* As Tx wrbs have been freed up, wake up netdev queue
-			 * if it was stopped due to lack of tx wrbs.  */
-			if (__netif_subqueue_stopped(adapter->netdev, i) &&
-				atomic_read(&txo->q.used) < txo->q.len / 2) {
-				netif_wake_subqueue(adapter->netdev, i);
-			}
-
-			adapter->drv_stats.be_tx_events++;
-			txo->stats.be_tx_compl += tx_compl;
-		}
-	}
-
-	mcc_compl = be_process_mcc(adapter, &status);
-
-	if (mcc_compl) {
-		struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
-		be_cq_notify(adapter, mcc_obj->cq.id, true, mcc_compl);
-	}
-
-	napi_complete(napi);
-
-	be_eq_notify(adapter, tx_eq->q.id, true, false, 0);
-	return 1;
-}
-
-void be_detect_dump_ue(struct be_adapter *adapter)
-{
-	u32 ue_status_lo, ue_status_hi, ue_status_lo_mask, ue_status_hi_mask;
-	u32 i;
-
-	pci_read_config_dword(adapter->pdev,
-				PCICFG_UE_STATUS_LOW, &ue_status_lo);
-	pci_read_config_dword(adapter->pdev,
-				PCICFG_UE_STATUS_HIGH, &ue_status_hi);
-	pci_read_config_dword(adapter->pdev,
-				PCICFG_UE_STATUS_LOW_MASK, &ue_status_lo_mask);
-	pci_read_config_dword(adapter->pdev,
-				PCICFG_UE_STATUS_HI_MASK, &ue_status_hi_mask);
-
-	ue_status_lo = (ue_status_lo & (~ue_status_lo_mask));
-	ue_status_hi = (ue_status_hi & (~ue_status_hi_mask));
-
-	if (ue_status_lo || ue_status_hi) {
-		adapter->ue_detected = true;
-		adapter->eeh_err = true;
-		dev_err(&adapter->pdev->dev, "UE Detected!!\n");
-	}
-
-	if (ue_status_lo) {
-		for (i = 0; ue_status_lo; ue_status_lo >>= 1, i++) {
-			if (ue_status_lo & 1)
-				dev_err(&adapter->pdev->dev,
-				"UE: %s bit set\n", ue_status_low_desc[i]);
-		}
-	}
-	if (ue_status_hi) {
-		for (i = 0; ue_status_hi; ue_status_hi >>= 1, i++) {
-			if (ue_status_hi & 1)
-				dev_err(&adapter->pdev->dev,
-				"UE: %s bit set\n", ue_status_hi_desc[i]);
-		}
-	}
-
-}
-
-static void be_worker(struct work_struct *work)
-{
-	struct be_adapter *adapter =
-		container_of(work, struct be_adapter, work.work);
-	struct be_rx_obj *rxo;
-	struct be_tx_obj *txo;
-	int i;
-
-	if (!adapter->ue_detected && !lancer_chip(adapter))
-		be_detect_dump_ue(adapter);
-
-	/* when interrupts are not yet enabled, just reap any pending
-	* mcc completions */
-	if (!netif_running(adapter->netdev)) {
-		int mcc_compl, status = 0;
-
-		mcc_compl = be_process_mcc(adapter, &status);
-
-		if (mcc_compl) {
-			struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
-			be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl);
-		}
-
-		goto reschedule;
-	}
-
-	if (!adapter->stats_cmd_sent) {
-		if (lancer_chip(adapter))
-			lancer_cmd_get_pport_stats(adapter,
-						&adapter->stats_cmd);
-		else
-			be_cmd_get_stats(adapter, &adapter->stats_cmd);
-	}
-
-	for_all_tx_queues(adapter, txo, i)
-		be_tx_rate_update(txo);
-
-	for_all_rx_queues(adapter, rxo, i) {
-		be_rx_rate_update(rxo);
-		be_rx_eqd_update(adapter, rxo);
-
-		if (rxo->rx_post_starved) {
-			rxo->rx_post_starved = false;
-			be_post_rx_frags(rxo, GFP_KERNEL);
-		}
-	}
-
-reschedule:
-	adapter->work_counter++;
-	schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
-}
-
-static void be_msix_disable(struct be_adapter *adapter)
-{
-	if (msix_enabled(adapter)) {
-		pci_disable_msix(adapter->pdev);
-		adapter->num_msix_vec = 0;
-	}
-}
-
-static void be_msix_enable(struct be_adapter *adapter)
-{
-#define BE_MIN_MSIX_VECTORS	(1 + 1) /* Rx + Tx */
-	int i, status, num_vec;
-
-	num_vec = be_num_rxqs_want(adapter) + 1;
-
-	for (i = 0; i < num_vec; i++)
-		adapter->msix_entries[i].entry = i;
-
-	status = pci_enable_msix(adapter->pdev, adapter->msix_entries, num_vec);
-	if (status == 0) {
-		goto done;
-	} else if (status >= BE_MIN_MSIX_VECTORS) {
-		num_vec = status;
-		if (pci_enable_msix(adapter->pdev, adapter->msix_entries,
-				num_vec) == 0)
-			goto done;
-	}
-	return;
-done:
-	adapter->num_msix_vec = num_vec;
-	return;
-}
-
-static void be_sriov_enable(struct be_adapter *adapter)
-{
-	be_check_sriov_fn_type(adapter);
-#ifdef CONFIG_PCI_IOV
-	if (be_physfn(adapter) && num_vfs) {
-		int status, pos;
-		u16 nvfs;
-
-		pos = pci_find_ext_capability(adapter->pdev,
-						PCI_EXT_CAP_ID_SRIOV);
-		pci_read_config_word(adapter->pdev,
-					pos + PCI_SRIOV_TOTAL_VF, &nvfs);
-
-		if (num_vfs > nvfs) {
-			dev_info(&adapter->pdev->dev,
-					"Device supports %d VFs and not %d\n",
-					nvfs, num_vfs);
-			num_vfs = nvfs;
-		}
-
-		status = pci_enable_sriov(adapter->pdev, num_vfs);
-		adapter->sriov_enabled = status ? false : true;
-	}
-#endif
-}
-
-static void be_sriov_disable(struct be_adapter *adapter)
-{
-#ifdef CONFIG_PCI_IOV
-	if (adapter->sriov_enabled) {
-		pci_disable_sriov(adapter->pdev);
-		adapter->sriov_enabled = false;
-	}
-#endif
-}
-
-static inline int be_msix_vec_get(struct be_adapter *adapter,
-					struct be_eq_obj *eq_obj)
-{
-	return adapter->msix_entries[eq_obj->eq_idx].vector;
-}
-
-static int be_request_irq(struct be_adapter *adapter,
-		struct be_eq_obj *eq_obj,
-		void *handler, char *desc, void *context)
-{
-	struct net_device *netdev = adapter->netdev;
-	int vec;
-
-	sprintf(eq_obj->desc, "%s-%s", netdev->name, desc);
-	vec = be_msix_vec_get(adapter, eq_obj);
-	return request_irq(vec, handler, 0, eq_obj->desc, context);
-}
-
-static void be_free_irq(struct be_adapter *adapter, struct be_eq_obj *eq_obj,
-			void *context)
-{
-	int vec = be_msix_vec_get(adapter, eq_obj);
-	free_irq(vec, context);
-}
-
-static int be_msix_register(struct be_adapter *adapter)
-{
-	struct be_rx_obj *rxo;
-	int status, i;
-	char qname[10];
-
-	status = be_request_irq(adapter, &adapter->tx_eq, be_msix_tx_mcc, "tx",
-				adapter);
-	if (status)
-		goto err;
-
-	for_all_rx_queues(adapter, rxo, i) {
-		sprintf(qname, "rxq%d", i);
-		status = be_request_irq(adapter, &rxo->rx_eq, be_msix_rx,
-				qname, rxo);
-		if (status)
-			goto err_msix;
-	}
-
-	return 0;
-
-err_msix:
-	be_free_irq(adapter, &adapter->tx_eq, adapter);
-
-	for (i--, rxo = &adapter->rx_obj[i]; i >= 0; i--, rxo--)
-		be_free_irq(adapter, &rxo->rx_eq, rxo);
-
-err:
-	dev_warn(&adapter->pdev->dev,
-		"MSIX Request IRQ failed - err %d\n", status);
-	be_msix_disable(adapter);
-	return status;
-}
-
-static int be_irq_register(struct be_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	int status;
-
-	if (msix_enabled(adapter)) {
-		status = be_msix_register(adapter);
-		if (status == 0)
-			goto done;
-		/* INTx is not supported for VF */
-		if (!be_physfn(adapter))
-			return status;
-	}
-
-	/* INTx */
-	netdev->irq = adapter->pdev->irq;
-	status = request_irq(netdev->irq, be_intx, IRQF_SHARED, netdev->name,
-			adapter);
-	if (status) {
-		dev_err(&adapter->pdev->dev,
-			"INTx request IRQ failed - err %d\n", status);
-		return status;
-	}
-done:
-	adapter->isr_registered = true;
-	return 0;
-}
-
-static void be_irq_unregister(struct be_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct be_rx_obj *rxo;
-	int i;
-
-	if (!adapter->isr_registered)
-		return;
-
-	/* INTx */
-	if (!msix_enabled(adapter)) {
-		free_irq(netdev->irq, adapter);
-		goto done;
-	}
-
-	/* MSIx */
-	be_free_irq(adapter, &adapter->tx_eq, adapter);
-
-	for_all_rx_queues(adapter, rxo, i)
-		be_free_irq(adapter, &rxo->rx_eq, rxo);
-
-done:
-	adapter->isr_registered = false;
-}
-
-static void be_rx_queues_clear(struct be_adapter *adapter)
-{
-	struct be_queue_info *q;
-	struct be_rx_obj *rxo;
-	int i;
-
-	for_all_rx_queues(adapter, rxo, i) {
-		q = &rxo->q;
-		if (q->created) {
-			be_cmd_rxq_destroy(adapter, q);
-			/* After the rxq is invalidated, wait for a grace time
-			 * of 1ms for all dma to end and the flush compl to
-			 * arrive
-			 */
-			mdelay(1);
-			be_rx_q_clean(adapter, rxo);
-		}
-
-		/* Clear any residual events */
-		q = &rxo->rx_eq.q;
-		if (q->created)
-			be_eq_clean(adapter, &rxo->rx_eq);
-	}
-}
-
-static int be_close(struct net_device *netdev)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_rx_obj *rxo;
-	struct be_tx_obj *txo;
-	struct be_eq_obj *tx_eq = &adapter->tx_eq;
-	int vec, i;
-
-	be_async_mcc_disable(adapter);
-
-	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->mcc_obj.cq.id, false, 0);
-		for_all_rx_queues(adapter, rxo, i)
-			 be_cq_notify(adapter, rxo->cq.id, false, 0);
-		for_all_tx_queues(adapter, txo, i)
-			 be_cq_notify(adapter, txo->cq.id, false, 0);
-	}
-
-	if (msix_enabled(adapter)) {
-		vec = be_msix_vec_get(adapter, tx_eq);
-		synchronize_irq(vec);
-
-		for_all_rx_queues(adapter, rxo, i) {
-			vec = be_msix_vec_get(adapter, &rxo->rx_eq);
-			synchronize_irq(vec);
-		}
-	} else {
-		synchronize_irq(netdev->irq);
-	}
-	be_irq_unregister(adapter);
-
-	/* Wait for all pending tx completions to arrive so that
-	 * all tx skbs are freed.
-	 */
-	for_all_tx_queues(adapter, txo, i)
-		be_tx_compl_clean(adapter, txo);
-
-	be_rx_queues_clear(adapter);
-	return 0;
-}
-
-static int be_rx_queues_setup(struct be_adapter *adapter)
-{
-	struct be_rx_obj *rxo;
-	int rc, i;
-	u8 rsstable[MAX_RSS_QS];
-
-	for_all_rx_queues(adapter, rxo, i) {
-		rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id,
-			rx_frag_size, BE_MAX_JUMBO_FRAME_SIZE,
-			adapter->if_handle,
-			(i > 0) ? 1 : 0/* rss enable */, &rxo->rss_id);
-		if (rc)
-			return rc;
-	}
-
-	if (be_multi_rxq(adapter)) {
-		for_all_rss_queues(adapter, rxo, i)
-			rsstable[i] = rxo->rss_id;
-
-		rc = be_cmd_rss_config(adapter, rsstable,
-			adapter->num_rx_qs - 1);
-		if (rc)
-			return rc;
-	}
-
-	/* First time posting */
-	for_all_rx_queues(adapter, rxo, i) {
-		be_post_rx_frags(rxo, GFP_KERNEL);
-		napi_enable(&rxo->rx_eq.napi);
-	}
-	return 0;
-}
-
-static int be_open(struct net_device *netdev)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_eq_obj *tx_eq = &adapter->tx_eq;
-	struct be_rx_obj *rxo;
-	bool link_up;
-	int status, i;
-	u8 mac_speed;
-	u16 link_speed;
-
-	status = be_rx_queues_setup(adapter);
-	if (status)
-		goto err;
-
-	napi_enable(&tx_eq->napi);
-
-	be_irq_register(adapter);
-
-	if (!lancer_chip(adapter))
-		be_intr_set(adapter, true);
-
-	/* The evt queues are created in unarmed state; arm them */
-	for_all_rx_queues(adapter, rxo, i) {
-		be_eq_notify(adapter, rxo->rx_eq.q.id, true, false, 0);
-		be_cq_notify(adapter, rxo->cq.id, true, 0);
-	}
-	be_eq_notify(adapter, tx_eq->q.id, true, false, 0);
-
-	/* Now that interrupts are on we can process async mcc */
-	be_async_mcc_enable(adapter);
-
-	status = be_cmd_link_status_query(adapter, &link_up, &mac_speed,
-			&link_speed, 0);
-	if (status)
-		goto err;
-	be_link_status_update(adapter, link_up);
-
-	if (be_physfn(adapter)) {
-		status = be_vid_config(adapter, false, 0);
-		if (status)
-			goto err;
-
-		status = be_cmd_set_flow_control(adapter,
-				adapter->tx_fc, adapter->rx_fc);
-		if (status)
-			goto err;
-	}
-
-	return 0;
-err:
-	be_close(adapter->netdev);
-	return -EIO;
-}
-
-static int be_setup_wol(struct be_adapter *adapter, bool enable)
-{
-	struct be_dma_mem cmd;
-	int status = 0;
-	u8 mac[ETH_ALEN];
-
-	memset(mac, 0, ETH_ALEN);
-
-	cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);
-	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);
-
-	if (enable) {
-		status = pci_write_config_dword(adapter->pdev,
-			PCICFG_PM_CONTROL_OFFSET, PCICFG_PM_CONTROL_MASK);
-		if (status) {
-			dev_err(&adapter->pdev->dev,
-				"Could not enable Wake-on-lan\n");
-			dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
-					  cmd.dma);
-			return status;
-		}
-		status = be_cmd_enable_magic_wol(adapter,
-				adapter->netdev->dev_addr, &cmd);
-		pci_enable_wake(adapter->pdev, PCI_D3hot, 1);
-		pci_enable_wake(adapter->pdev, PCI_D3cold, 1);
-	} else {
-		status = be_cmd_enable_magic_wol(adapter, mac, &cmd);
-		pci_enable_wake(adapter->pdev, PCI_D3hot, 0);
-		pci_enable_wake(adapter->pdev, PCI_D3cold, 0);
-	}
-
-	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
-	return status;
-}
-
-/*
- * Generate a seed MAC address from the PF MAC Address using jhash.
- * MAC Address for VFs are assigned incrementally starting from the seed.
- * These addresses are programmed in the ASIC by the PF and the VF driver
- * queries for the MAC address during its probe.
- */
-static inline int be_vf_eth_addr_config(struct be_adapter *adapter)
-{
-	u32 vf = 0;
-	int status = 0;
-	u8 mac[ETH_ALEN];
-
-	be_vf_eth_addr_generate(adapter, mac);
-
-	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,
-					vf + 1);
-		if (status)
-			dev_err(&adapter->pdev->dev,
-				"Mac address add failed for VF %d\n", vf);
-		else
-			memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN);
-
-		mac[5] += 1;
-	}
-	return status;
-}
-
-static inline void be_vf_eth_addr_rem(struct be_adapter *adapter)
-{
-	u32 vf;
-
-	for (vf = 0; vf < num_vfs; vf++) {
-		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, vf + 1);
-	}
-}
-
-static int be_setup(struct be_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	u32 cap_flags, en_flags, vf = 0;
-	int status;
-	u8 mac[ETH_ALEN];
-
-	be_cmd_req_native_mode(adapter);
-
-	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 |
-				BE_IF_FLAGS_PROMISCUOUS |
-				BE_IF_FLAGS_PASS_L3L4_ERRORS;
-		en_flags |= BE_IF_FLAGS_PASS_L3L4_ERRORS;
-
-		if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) {
-			cap_flags |= BE_IF_FLAGS_RSS;
-			en_flags |= BE_IF_FLAGS_RSS;
-		}
-	}
-
-	status = be_cmd_if_create(adapter, cap_flags, en_flags,
-			netdev->dev_addr, false/* pmac_invalid */,
-			&adapter->if_handle, &adapter->pmac_id, 0);
-	if (status != 0)
-		goto do_none;
-
-	if (be_physfn(adapter)) {
-		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;
-				}
-				adapter->vf_cfg[vf].vf_pmac_id =
-							BE_INVALID_PMAC_ID;
-				vf++;
-			}
-		}
-	} else {
-		status = be_cmd_mac_addr_query(adapter, mac,
-			MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle);
-		if (!status) {
-			memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
-			memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
-		}
-	}
-
-	status = be_tx_queues_create(adapter);
-	if (status != 0)
-		goto if_destroy;
-
-	status = be_rx_queues_create(adapter);
-	if (status != 0)
-		goto tx_qs_destroy;
-
-	/* Allow all priorities by default. A GRP5 evt may modify this */
-	adapter->vlan_prio_bmap = 0xff;
-
-	status = be_mcc_queues_create(adapter);
-	if (status != 0)
-		goto rx_qs_destroy;
-
-	adapter->link_speed = -1;
-
-	return 0;
-
-rx_qs_destroy:
-	be_rx_queues_destroy(adapter);
-tx_qs_destroy:
-	be_tx_queues_destroy(adapter);
-if_destroy:
-	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)
-{
-	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;
-
-	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);
-
-	adapter->be3_native = 0;
-
-	/* tell fw we're done with firing cmds */
-	be_cmd_fw_clean(adapter);
-	return 0;
-}
-
-
-#define FW_FILE_HDR_SIGN 	"ServerEngines Corp. "
-static bool be_flash_redboot(struct be_adapter *adapter,
-			const u8 *p, u32 img_start, int image_size,
-			int hdr_size)
-{
-	u32 crc_offset;
-	u8 flashed_crc[4];
-	int status;
-
-	crc_offset = hdr_size + img_start + image_size - 4;
-
-	p += crc_offset;
-
-	status = be_cmd_get_flash_crc(adapter, flashed_crc,
-			(image_size - 4));
-	if (status) {
-		dev_err(&adapter->pdev->dev,
-		"could not get crc from flash, not flashing redboot\n");
-		return false;
-	}
-
-	/*update redboot only if crc does not match*/
-	if (!memcmp(flashed_crc, p, 4))
-		return false;
-	else
-		return true;
-}
-
-static int be_flash_data(struct be_adapter *adapter,
-			const struct firmware *fw,
-			struct be_dma_mem *flash_cmd, int num_of_images)
-
-{
-	int status = 0, i, filehdr_size = 0;
-	u32 total_bytes = 0, flash_op;
-	int num_bytes;
-	const u8 *p = fw->data;
-	struct be_cmd_write_flashrom *req = flash_cmd->va;
-	const struct flash_comp *pflashcomp;
-	int num_comp;
-
-	static const struct flash_comp gen3_flash_types[9] = {
-		{ FLASH_iSCSI_PRIMARY_IMAGE_START_g3, IMG_TYPE_ISCSI_ACTIVE,
-			FLASH_IMAGE_MAX_SIZE_g3},
-		{ FLASH_REDBOOT_START_g3, IMG_TYPE_REDBOOT,
-			FLASH_REDBOOT_IMAGE_MAX_SIZE_g3},
-		{ FLASH_iSCSI_BIOS_START_g3, IMG_TYPE_BIOS,
-			FLASH_BIOS_IMAGE_MAX_SIZE_g3},
-		{ FLASH_PXE_BIOS_START_g3, IMG_TYPE_PXE_BIOS,
-			FLASH_BIOS_IMAGE_MAX_SIZE_g3},
-		{ FLASH_FCoE_BIOS_START_g3, IMG_TYPE_FCOE_BIOS,
-			FLASH_BIOS_IMAGE_MAX_SIZE_g3},
-		{ FLASH_iSCSI_BACKUP_IMAGE_START_g3, IMG_TYPE_ISCSI_BACKUP,
-			FLASH_IMAGE_MAX_SIZE_g3},
-		{ FLASH_FCoE_PRIMARY_IMAGE_START_g3, IMG_TYPE_FCOE_FW_ACTIVE,
-			FLASH_IMAGE_MAX_SIZE_g3},
-		{ FLASH_FCoE_BACKUP_IMAGE_START_g3, IMG_TYPE_FCOE_FW_BACKUP,
-			FLASH_IMAGE_MAX_SIZE_g3},
-		{ FLASH_NCSI_START_g3, IMG_TYPE_NCSI_FW,
-			FLASH_NCSI_IMAGE_MAX_SIZE_g3}
-	};
-	static const struct flash_comp gen2_flash_types[8] = {
-		{ FLASH_iSCSI_PRIMARY_IMAGE_START_g2, IMG_TYPE_ISCSI_ACTIVE,
-			FLASH_IMAGE_MAX_SIZE_g2},
-		{ FLASH_REDBOOT_START_g2, IMG_TYPE_REDBOOT,
-			FLASH_REDBOOT_IMAGE_MAX_SIZE_g2},
-		{ FLASH_iSCSI_BIOS_START_g2, IMG_TYPE_BIOS,
-			FLASH_BIOS_IMAGE_MAX_SIZE_g2},
-		{ FLASH_PXE_BIOS_START_g2, IMG_TYPE_PXE_BIOS,
-			FLASH_BIOS_IMAGE_MAX_SIZE_g2},
-		{ FLASH_FCoE_BIOS_START_g2, IMG_TYPE_FCOE_BIOS,
-			FLASH_BIOS_IMAGE_MAX_SIZE_g2},
-		{ FLASH_iSCSI_BACKUP_IMAGE_START_g2, IMG_TYPE_ISCSI_BACKUP,
-			FLASH_IMAGE_MAX_SIZE_g2},
-		{ FLASH_FCoE_PRIMARY_IMAGE_START_g2, IMG_TYPE_FCOE_FW_ACTIVE,
-			FLASH_IMAGE_MAX_SIZE_g2},
-		{ FLASH_FCoE_BACKUP_IMAGE_START_g2, IMG_TYPE_FCOE_FW_BACKUP,
-			 FLASH_IMAGE_MAX_SIZE_g2}
-	};
-
-	if (adapter->generation == BE_GEN3) {
-		pflashcomp = gen3_flash_types;
-		filehdr_size = sizeof(struct flash_file_hdr_g3);
-		num_comp = ARRAY_SIZE(gen3_flash_types);
-	} else {
-		pflashcomp = gen2_flash_types;
-		filehdr_size = sizeof(struct flash_file_hdr_g2);
-		num_comp = ARRAY_SIZE(gen2_flash_types);
-	}
-	for (i = 0; i < num_comp; i++) {
-		if ((pflashcomp[i].optype == IMG_TYPE_NCSI_FW) &&
-				memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0)
-			continue;
-		if ((pflashcomp[i].optype == IMG_TYPE_REDBOOT) &&
-			(!be_flash_redboot(adapter, fw->data,
-			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
-			+ (num_of_images * sizeof(struct image_hdr));
-	if (p + pflashcomp[i].size > fw->data + fw->size)
-		return -1;
-	total_bytes = pflashcomp[i].size;
-		while (total_bytes) {
-			if (total_bytes > 32*1024)
-				num_bytes = 32*1024;
-			else
-				num_bytes = total_bytes;
-			total_bytes -= num_bytes;
-
-			if (!total_bytes)
-				flash_op = FLASHROM_OPER_FLASH;
-			else
-				flash_op = FLASHROM_OPER_SAVE;
-			memcpy(req->params.data_buf, p, num_bytes);
-			p += num_bytes;
-			status = be_cmd_write_flashrom(adapter, flash_cmd,
-				pflashcomp[i].optype, flash_op, num_bytes);
-			if (status) {
-				dev_err(&adapter->pdev->dev,
-					"cmd to write to flash rom failed.\n");
-				return -1;
-			}
-		}
-	}
-	return 0;
-}
-
-static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr)
-{
-	if (fhdr == NULL)
-		return 0;
-	if (fhdr->build[0] == '3')
-		return BE_GEN3;
-	else if (fhdr->build[0] == '2')
-		return BE_GEN2;
-	else
-		return 0;
-}
-
-static int lancer_fw_download(struct be_adapter *adapter,
-				const struct firmware *fw)
-{
-#define LANCER_FW_DOWNLOAD_CHUNK      (32 * 1024)
-#define LANCER_FW_DOWNLOAD_LOCATION   "/prg"
-	struct be_dma_mem flash_cmd;
-	const u8 *data_ptr = NULL;
-	u8 *dest_image_ptr = NULL;
-	size_t image_size = 0;
-	u32 chunk_size = 0;
-	u32 data_written = 0;
-	u32 offset = 0;
-	int status = 0;
-	u8 add_status = 0;
-
-	if (!IS_ALIGNED(fw->size, sizeof(u32))) {
-		dev_err(&adapter->pdev->dev,
-			"FW Image not properly aligned. "
-			"Length must be 4 byte aligned.\n");
-		status = -EINVAL;
-		goto lancer_fw_exit;
-	}
-
-	flash_cmd.size = sizeof(struct lancer_cmd_req_write_object)
-				+ LANCER_FW_DOWNLOAD_CHUNK;
-	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,
-			"Memory allocation failure while flashing\n");
-		goto lancer_fw_exit;
-	}
-
-	dest_image_ptr = flash_cmd.va +
-				sizeof(struct lancer_cmd_req_write_object);
-	image_size = fw->size;
-	data_ptr = fw->data;
-
-	while (image_size) {
-		chunk_size = min_t(u32, image_size, LANCER_FW_DOWNLOAD_CHUNK);
-
-		/* Copy the image chunk content. */
-		memcpy(dest_image_ptr, data_ptr, chunk_size);
-
-		status = lancer_cmd_write_object(adapter, &flash_cmd,
-				chunk_size, offset, LANCER_FW_DOWNLOAD_LOCATION,
-				&data_written, &add_status);
-
-		if (status)
-			break;
-
-		offset += data_written;
-		data_ptr += data_written;
-		image_size -= data_written;
-	}
-
-	if (!status) {
-		/* Commit the FW written */
-		status = lancer_cmd_write_object(adapter, &flash_cmd,
-					0, offset, LANCER_FW_DOWNLOAD_LOCATION,
-					&data_written, &add_status);
-	}
-
-	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. "
-			"Status code: 0x%x Additional Status: 0x%x\n",
-			status, add_status);
-		goto lancer_fw_exit;
-	}
-
-	dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n");
-lancer_fw_exit:
-	return status;
-}
-
-static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
-{
-	struct flash_file_hdr_g2 *fhdr;
-	struct flash_file_hdr_g3 *fhdr3;
-	struct image_hdr *img_hdr_ptr = NULL;
-	struct be_dma_mem flash_cmd;
-	const u8 *p;
-	int status = 0, i = 0, num_imgs = 0;
-
-	p = fw->data;
-	fhdr = (struct flash_file_hdr_g2 *) p;
-
-	flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024;
-	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,
-			"Memory allocation failure while flashing\n");
-		goto be_fw_exit;
-	}
-
-	if ((adapter->generation == BE_GEN3) &&
-			(get_ufigen_type(fhdr) == BE_GEN3)) {
-		fhdr3 = (struct flash_file_hdr_g3 *) fw->data;
-		num_imgs = le32_to_cpu(fhdr3->num_imgs);
-		for (i = 0; i < num_imgs; i++) {
-			img_hdr_ptr = (struct image_hdr *) (fw->data +
-					(sizeof(struct flash_file_hdr_g3) +
-					 i * sizeof(struct image_hdr)));
-			if (le32_to_cpu(img_hdr_ptr->imageid) == 1)
-				status = be_flash_data(adapter, fw, &flash_cmd,
-							num_imgs);
-		}
-	} else if ((adapter->generation == BE_GEN2) &&
-			(get_ufigen_type(fhdr) == BE_GEN2)) {
-		status = be_flash_data(adapter, fw, &flash_cmd, 0);
-	} else {
-		dev_err(&adapter->pdev->dev,
-			"UFI and Interface are not compatible for flashing\n");
-		status = -1;
-	}
-
-	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 be_fw_exit;
-	}
-
-	dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n");
-
-be_fw_exit:
-	return status;
-}
-
-int be_load_fw(struct be_adapter *adapter, u8 *fw_file)
-{
-	const struct firmware *fw;
-	int status;
-
-	if (!netif_running(adapter->netdev)) {
-		dev_err(&adapter->pdev->dev,
-			"Firmware load not allowed (interface is down)\n");
-		return -1;
-	}
-
-	status = request_firmware(&fw, fw_file, &adapter->pdev->dev);
-	if (status)
-		goto fw_exit;
-
-	dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file);
-
-	if (lancer_chip(adapter))
-		status = lancer_fw_download(adapter, fw);
-	else
-		status = be_fw_download(adapter, fw);
-
-fw_exit:
-	release_firmware(fw);
-	return status;
-}
-
-static struct net_device_ops be_netdev_ops = {
-	.ndo_open		= be_open,
-	.ndo_stop		= be_close,
-	.ndo_start_xmit		= be_xmit,
-	.ndo_set_rx_mode	= be_set_multicast_list,
-	.ndo_set_mac_address	= be_mac_addr_set,
-	.ndo_change_mtu		= be_change_mtu,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_vlan_rx_add_vid	= be_vlan_add_vid,
-	.ndo_vlan_rx_kill_vid	= be_vlan_rem_vid,
-	.ndo_set_vf_mac		= be_set_vf_mac,
-	.ndo_set_vf_vlan	= be_set_vf_vlan,
-	.ndo_set_vf_tx_rate	= be_set_vf_tx_rate,
-	.ndo_get_vf_config	= be_get_vf_config
-};
-
-static void be_netdev_init(struct net_device *netdev)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_rx_obj *rxo;
-	int i;
-
-	netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
-		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |
-		NETIF_F_HW_VLAN_TX;
-	if (be_multi_rxq(adapter))
-		netdev->hw_features |= NETIF_F_RXHASH;
-
-	netdev->features |= netdev->hw_features |
-		NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
-
-	netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
-		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
-
-	netdev->flags |= IFF_MULTICAST;
-
-	/* Default settings for Rx and Tx flow control */
-	adapter->rx_fc = true;
-	adapter->tx_fc = true;
-
-	netif_set_gso_max_size(netdev, 65535);
-
-	BE_SET_NETDEV_OPS(netdev, &be_netdev_ops);
-
-	SET_ETHTOOL_OPS(netdev, &be_ethtool_ops);
-
-	for_all_rx_queues(adapter, rxo, i)
-		netif_napi_add(netdev, &rxo->rx_eq.napi, be_poll_rx,
-				BE_NAPI_WEIGHT);
-
-	netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc,
-		BE_NAPI_WEIGHT);
-}
-
-static void be_unmap_pci_bars(struct be_adapter *adapter)
-{
-	if (adapter->csr)
-		iounmap(adapter->csr);
-	if (adapter->db)
-		iounmap(adapter->db);
-	if (adapter->pcicfg && be_physfn(adapter))
-		iounmap(adapter->pcicfg);
-}
-
-static int be_map_pci_bars(struct be_adapter *adapter)
-{
-	u8 __iomem *addr;
-	int pcicfg_reg, db_reg;
-
-	if (lancer_chip(adapter)) {
-		addr = ioremap_nocache(pci_resource_start(adapter->pdev, 0),
-			pci_resource_len(adapter->pdev, 0));
-		if (addr == NULL)
-			return -ENOMEM;
-		adapter->db = addr;
-		return 0;
-	}
-
-	if (be_physfn(adapter)) {
-		addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2),
-				pci_resource_len(adapter->pdev, 2));
-		if (addr == NULL)
-			return -ENOMEM;
-		adapter->csr = addr;
-	}
-
-	if (adapter->generation == BE_GEN2) {
-		pcicfg_reg = 1;
-		db_reg = 4;
-	} else {
-		pcicfg_reg = 0;
-		if (be_physfn(adapter))
-			db_reg = 4;
-		else
-			db_reg = 0;
-	}
-	addr = ioremap_nocache(pci_resource_start(adapter->pdev, db_reg),
-				pci_resource_len(adapter->pdev, db_reg));
-	if (addr == NULL)
-		goto pci_map_err;
-	adapter->db = addr;
-
-	if (be_physfn(adapter)) {
-		addr = ioremap_nocache(
-				pci_resource_start(adapter->pdev, pcicfg_reg),
-				pci_resource_len(adapter->pdev, pcicfg_reg));
-		if (addr == NULL)
-			goto pci_map_err;
-		adapter->pcicfg = addr;
-	} else
-		adapter->pcicfg = adapter->db + SRIOV_VF_PCICFG_OFFSET;
-
-	return 0;
-pci_map_err:
-	be_unmap_pci_bars(adapter);
-	return -ENOMEM;
-}
-
-
-static void be_ctrl_cleanup(struct be_adapter *adapter)
-{
-	struct be_dma_mem *mem = &adapter->mbox_mem_alloced;
-
-	be_unmap_pci_bars(adapter);
-
-	if (mem->va)
-		dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
-				  mem->dma);
-
-	mem = &adapter->mc_cmd_mem;
-	if (mem->va)
-		dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
-				  mem->dma);
-}
-
-static int be_ctrl_init(struct be_adapter *adapter)
-{
-	struct be_dma_mem *mbox_mem_alloc = &adapter->mbox_mem_alloced;
-	struct be_dma_mem *mbox_mem_align = &adapter->mbox_mem;
-	struct be_dma_mem *mc_cmd_mem = &adapter->mc_cmd_mem;
-	int status;
-
-	status = be_map_pci_bars(adapter);
-	if (status)
-		goto done;
-
-	mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16;
-	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;
-	}
-
-	mbox_mem_align->size = sizeof(struct be_mcc_mailbox);
-	mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16);
-	mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
-	memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox));
-
-	mc_cmd_mem->size = sizeof(struct be_cmd_req_mcast_mac_config);
-	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;
-	}
-	memset(mc_cmd_mem->va, 0, mc_cmd_mem->size);
-
-	mutex_init(&adapter->mbox_lock);
-	spin_lock_init(&adapter->mcc_lock);
-	spin_lock_init(&adapter->mcc_cq_lock);
-
-	init_completion(&adapter->flash_compl);
-	pci_save_state(adapter->pdev);
-	return 0;
-
-free_mbox:
-	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);
-
-done:
-	return status;
-}
-
-static void be_stats_cleanup(struct be_adapter *adapter)
-{
-	struct be_dma_mem *cmd = &adapter->stats_cmd;
-
-	if (cmd->va)
-		dma_free_coherent(&adapter->pdev->dev, cmd->size,
-				  cmd->va, cmd->dma);
-}
-
-static int be_stats_init(struct be_adapter *adapter)
-{
-	struct be_dma_mem *cmd = &adapter->stats_cmd;
-
-	if (adapter->generation == BE_GEN2) {
-		cmd->size = sizeof(struct be_cmd_req_get_stats_v0);
-	} else {
-		if (lancer_chip(adapter))
-			cmd->size = sizeof(struct lancer_cmd_req_pport_stats);
-		else
-			cmd->size = sizeof(struct be_cmd_req_get_stats_v1);
-	}
-	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);
-	return 0;
-}
-
-static void __devexit be_remove(struct pci_dev *pdev)
-{
-	struct be_adapter *adapter = pci_get_drvdata(pdev);
-
-	if (!adapter)
-		return;
-
-	cancel_delayed_work_sync(&adapter->work);
-
-	unregister_netdev(adapter->netdev);
-
-	be_clear(adapter);
-
-	be_stats_cleanup(adapter);
-
-	be_ctrl_cleanup(adapter);
-
-	kfree(adapter->vf_cfg);
-	be_sriov_disable(adapter);
-
-	be_msix_disable(adapter);
-
-	pci_set_drvdata(pdev, NULL);
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-
-	free_netdev(adapter->netdev);
-}
-
-static int be_get_config(struct be_adapter *adapter)
-{
-	int status;
-	u8 mac[ETH_ALEN];
-
-	status = be_cmd_get_fw_ver(adapter, adapter->fw_ver);
-	if (status)
-		return status;
-
-	status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
-			&adapter->function_mode, &adapter->function_caps);
-	if (status)
-		return status;
-
-	memset(mac, 0, ETH_ALEN);
-
-	/* A default permanent address is given to each VF for Lancer*/
-	if (be_physfn(adapter) || lancer_chip(adapter)) {
-		status = be_cmd_mac_addr_query(adapter, mac,
-			MAC_ADDRESS_TYPE_NETWORK, true /*permanent */, 0);
-
-		if (status)
-			return status;
-
-		if (!is_valid_ether_addr(mac))
-			return -EADDRNOTAVAIL;
-
-		memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
-		memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
-	}
-
-	if (adapter->function_mode & 0x400)
-		adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/4;
-	else
-		adapter->max_vlans = BE_NUM_VLANS_SUPPORTED;
-
-	status = be_cmd_get_cntl_attributes(adapter);
-	if (status)
-		return status;
-
-	if ((num_vfs && adapter->sriov_enabled) ||
-		(adapter->function_mode & 0x400) ||
-		lancer_chip(adapter) || !be_physfn(adapter)) {
-		adapter->num_tx_qs = 1;
-		netif_set_real_num_tx_queues(adapter->netdev,
-			adapter->num_tx_qs);
-	} else {
-		adapter->num_tx_qs = MAX_TX_QS;
-	}
-
-	return 0;
-}
-
-static int be_dev_family_check(struct be_adapter *adapter)
-{
-	struct pci_dev *pdev = adapter->pdev;
-	u32 sli_intf = 0, if_type;
-
-	switch (pdev->device) {
-	case BE_DEVICE_ID1:
-	case OC_DEVICE_ID1:
-		adapter->generation = BE_GEN2;
-		break;
-	case BE_DEVICE_ID2:
-	case OC_DEVICE_ID2:
-		adapter->generation = BE_GEN3;
-		break;
-	case OC_DEVICE_ID3:
-	case OC_DEVICE_ID4:
-		pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
-		if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
-						SLI_INTF_IF_TYPE_SHIFT;
-
-		if (((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) ||
-			if_type != 0x02) {
-			dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
-			return -EINVAL;
-		}
-		adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >>
-					 SLI_INTF_FAMILY_SHIFT);
-		adapter->generation = BE_GEN3;
-		break;
-	default:
-		adapter->generation = 0;
-	}
-	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)
-{
-	int status = 0;
-	struct be_adapter *adapter;
-	struct net_device *netdev;
-
-	status = pci_enable_device(pdev);
-	if (status)
-		goto do_none;
-
-	status = pci_request_regions(pdev, DRV_NAME);
-	if (status)
-		goto disable_dev;
-	pci_set_master(pdev);
-
-	netdev = alloc_etherdev_mq(sizeof(struct be_adapter), MAX_TX_QS);
-	if (netdev == NULL) {
-		status = -ENOMEM;
-		goto rel_reg;
-	}
-	adapter = netdev_priv(netdev);
-	adapter->pdev = pdev;
-	pci_set_drvdata(pdev, adapter);
-
-	status = be_dev_family_check(adapter);
-	if (status)
-		goto free_netdev;
-
-	adapter->netdev = netdev;
-	SET_NETDEV_DEV(netdev, &pdev->dev);
-
-	status = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
-	if (!status) {
-		netdev->features |= NETIF_F_HIGHDMA;
-	} else {
-		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;
-		}
-	}
-
-	be_sriov_enable(adapter);
-	if (adapter->sriov_enabled) {
-		adapter->vf_cfg = kcalloc(num_vfs,
-			sizeof(struct be_vf_cfg), GFP_KERNEL);
-
-		if (!adapter->vf_cfg)
-			goto free_netdev;
-	}
-
-	status = be_ctrl_init(adapter);
-	if (status)
-		goto free_vf_cfg;
-
-	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 ctrl_clean;
-		}
-	}
-
-	/* sync up with fw's ready state */
-	if (be_physfn(adapter)) {
-		status = be_cmd_POST(adapter);
-		if (status)
-			goto ctrl_clean;
-	}
-
-	/* tell fw we're ready to fire cmds */
-	status = be_cmd_fw_init(adapter);
-	if (status)
-		goto ctrl_clean;
-
-	status = be_cmd_reset_function(adapter);
-	if (status)
-		goto ctrl_clean;
-
-	status = be_stats_init(adapter);
-	if (status)
-		goto ctrl_clean;
-
-	status = be_get_config(adapter);
-	if (status)
-		goto stats_clean;
-
-	/* The INTR bit may be set in the card when probed by a kdump kernel
-	 * after a crash.
-	 */
-	if (!lancer_chip(adapter))
-		be_intr_set(adapter, false);
-
-	be_msix_enable(adapter);
-
-	INIT_DELAYED_WORK(&adapter->work, be_worker);
-
-	status = be_setup(adapter);
-	if (status)
-		goto msix_disable;
-
-	be_netdev_init(netdev);
-	status = register_netdev(netdev);
-	if (status != 0)
-		goto unsetup;
-	netif_carrier_off(netdev);
-
-	if (be_physfn(adapter) && adapter->sriov_enabled) {
-		u8 mac_speed;
-		bool link_up;
-		u16 vf, lnk_speed;
-
-		if (!lancer_chip(adapter)) {
-			status = be_vf_eth_addr_config(adapter);
-			if (status)
-				goto unreg_netdev;
-		}
-
-		for (vf = 0; vf < num_vfs; vf++) {
-			status = be_cmd_link_status_query(adapter, &link_up,
-					&mac_speed, &lnk_speed, vf + 1);
-			if (!status)
-				adapter->vf_cfg[vf].vf_tx_rate = lnk_speed * 10;
-			else
-				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:
-	be_msix_disable(adapter);
-stats_clean:
-	be_stats_cleanup(adapter);
-ctrl_clean:
-	be_ctrl_cleanup(adapter);
-free_vf_cfg:
-	kfree(adapter->vf_cfg);
-free_netdev:
-	be_sriov_disable(adapter);
-	free_netdev(netdev);
-	pci_set_drvdata(pdev, NULL);
-rel_reg:
-	pci_release_regions(pdev);
-disable_dev:
-	pci_disable_device(pdev);
-do_none:
-	dev_err(&pdev->dev, "%s initialization failed\n", nic_name(pdev));
-	return status;
-}
-
-static int be_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	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);
-
-	netif_device_detach(netdev);
-	if (netif_running(netdev)) {
-		rtnl_lock();
-		be_close(netdev);
-		rtnl_unlock();
-	}
-	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));
-	return 0;
-}
-
-static int be_resume(struct pci_dev *pdev)
-{
-	int status = 0;
-	struct be_adapter *adapter = pci_get_drvdata(pdev);
-	struct net_device *netdev =  adapter->netdev;
-
-	netif_device_detach(netdev);
-
-	status = pci_enable_device(pdev);
-	if (status)
-		return status;
-
-	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)
-		return status;
-
-	be_setup(adapter);
-	if (netif_running(netdev)) {
-		rtnl_lock();
-		be_open(netdev);
-		rtnl_unlock();
-	}
-	netif_device_attach(netdev);
-
-	if (adapter->wol)
-		be_setup_wol(adapter, false);
-
-	schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
-	return 0;
-}
-
-/*
- * An FLR will stop BE from DMAing any data.
- */
-static void be_shutdown(struct pci_dev *pdev)
-{
-	struct be_adapter *adapter = pci_get_drvdata(pdev);
-
-	if (!adapter)
-		return;
-
-	cancel_delayed_work_sync(&adapter->work);
-
-	netif_device_detach(adapter->netdev);
-
-	if (adapter->wol)
-		be_setup_wol(adapter, true);
-
-	be_cmd_reset_function(adapter);
-
-	pci_disable_device(pdev);
-}
-
-static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev,
-				pci_channel_state_t state)
-{
-	struct be_adapter *adapter = pci_get_drvdata(pdev);
-	struct net_device *netdev =  adapter->netdev;
-
-	dev_err(&adapter->pdev->dev, "EEH error detected\n");
-
-	adapter->eeh_err = true;
-
-	netif_device_detach(netdev);
-
-	if (netif_running(netdev)) {
-		rtnl_lock();
-		be_close(netdev);
-		rtnl_unlock();
-	}
-	be_clear(adapter);
-
-	if (state == pci_channel_io_perm_failure)
-		return PCI_ERS_RESULT_DISCONNECT;
-
-	pci_disable_device(pdev);
-
-	return PCI_ERS_RESULT_NEED_RESET;
-}
-
-static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev)
-{
-	struct be_adapter *adapter = pci_get_drvdata(pdev);
-	int status;
-
-	dev_info(&adapter->pdev->dev, "EEH reset\n");
-	adapter->eeh_err = false;
-
-	status = pci_enable_device(pdev);
-	if (status)
-		return PCI_ERS_RESULT_DISCONNECT;
-
-	pci_set_master(pdev);
-	pci_set_power_state(pdev, 0);
-	pci_restore_state(pdev);
-
-	/* Check if card is ok and fw is ready */
-	status = be_cmd_POST(adapter);
-	if (status)
-		return PCI_ERS_RESULT_DISCONNECT;
-
-	return PCI_ERS_RESULT_RECOVERED;
-}
-
-static void be_eeh_resume(struct pci_dev *pdev)
-{
-	int status = 0;
-	struct be_adapter *adapter = pci_get_drvdata(pdev);
-	struct net_device *netdev =  adapter->netdev;
-
-	dev_info(&adapter->pdev->dev, "EEH resume\n");
-
-	pci_save_state(pdev);
-
-	/* tell fw we're ready to fire cmds */
-	status = be_cmd_fw_init(adapter);
-	if (status)
-		goto err;
-
-	status = be_setup(adapter);
-	if (status)
-		goto err;
-
-	if (netif_running(netdev)) {
-		status = be_open(netdev);
-		if (status)
-			goto err;
-	}
-	netif_device_attach(netdev);
-	return;
-err:
-	dev_err(&adapter->pdev->dev, "EEH resume failed\n");
-}
-
-static struct pci_error_handlers be_eeh_handlers = {
-	.error_detected = be_eeh_err_detected,
-	.slot_reset = be_eeh_reset,
-	.resume = be_eeh_resume,
-};
-
-static struct pci_driver be_driver = {
-	.name = DRV_NAME,
-	.id_table = be_dev_ids,
-	.probe = be_probe,
-	.remove = be_remove,
-	.suspend = be_suspend,
-	.resume = be_resume,
-	.shutdown = be_shutdown,
-	.err_handler = &be_eeh_handlers
-};
-
-static int __init be_init_module(void)
-{
-	if (rx_frag_size != 8192 && rx_frag_size != 4096 &&
-	    rx_frag_size != 2048) {
-		printk(KERN_WARNING DRV_NAME
-			" : Module param rx_frag_size must be 2048/4096/8192."
-			" Using 2048\n");
-		rx_frag_size = 2048;
-	}
-
-	return pci_register_driver(&be_driver);
-}
-module_init(be_init_module);
-
-static void __exit be_exit_module(void)
-{
-	pci_unregister_driver(&be_driver);
-}
-module_exit(be_exit_module);
diff -druN linux-libre-3.1-gnu/drivers/net/benet/Kconfig linux-libre-3.2-gnu/drivers/net/benet/Kconfig
--- linux-libre-3.1-gnu/drivers/net/benet/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/benet/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-config BE2NET
-	tristate "ServerEngines' 10Gbps NIC - BladeEngine"
-	depends on PCI && INET
-	help
-	This driver implements the NIC functionality for ServerEngines'
-	10Gbps network adapter - BladeEngine.
diff -druN linux-libre-3.1-gnu/drivers/net/benet/Makefile linux-libre-3.2-gnu/drivers/net/benet/Makefile
--- linux-libre-3.1-gnu/drivers/net/benet/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/benet/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#
-# Makefile to build the network driver for ServerEngine's BladeEngine.
-#
-
-obj-$(CONFIG_BE2NET) += be2net.o
-
-be2net-y :=  be_main.o be_cmds.o be_ethtool.o
diff -druN linux-libre-3.1-gnu/drivers/net/bfin_mac.c linux-libre-3.2-gnu/drivers/net/bfin_mac.c
--- linux-libre-3.1-gnu/drivers/net/bfin_mac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bfin_mac.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1767 +0,0 @@
-/*
- * Blackfin On-Chip MAC Driver
- *
- * Copyright 2004-2010 Analog Devices Inc.
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Licensed under the GPL-2 or later.
- */
-
-#define DRV_VERSION	"1.1"
-#define DRV_DESC	"Blackfin on-chip Ethernet MAC driver"
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/errno.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/crc32.h>
-#include <linux/device.h>
-#include <linux/spinlock.h>
-#include <linux/mii.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/skbuff.h>
-#include <linux/platform_device.h>
-
-#include <asm/dma.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/div64.h>
-#include <asm/dpmc.h>
-#include <asm/blackfin.h>
-#include <asm/cacheflush.h>
-#include <asm/portmux.h>
-#include <mach/pll.h>
-
-#include "bfin_mac.h"
-
-MODULE_AUTHOR("Bryan Wu, Luke Yang");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(DRV_DESC);
-MODULE_ALIAS("platform:bfin_mac");
-
-#if defined(CONFIG_BFIN_MAC_USE_L1)
-# define bfin_mac_alloc(dma_handle, size, num)  l1_data_sram_zalloc(size*num)
-# define bfin_mac_free(dma_handle, ptr, num)    l1_data_sram_free(ptr)
-#else
-# define bfin_mac_alloc(dma_handle, size, num) \
-	dma_alloc_coherent(NULL, size*num, dma_handle, GFP_KERNEL)
-# define bfin_mac_free(dma_handle, ptr, num) \
-	dma_free_coherent(NULL, sizeof(*ptr)*num, ptr, dma_handle)
-#endif
-
-#define PKT_BUF_SZ 1580
-
-#define MAX_TIMEOUT_CNT	500
-
-/* pointers to maintain transmit list */
-static struct net_dma_desc_tx *tx_list_head;
-static struct net_dma_desc_tx *tx_list_tail;
-static struct net_dma_desc_rx *rx_list_head;
-static struct net_dma_desc_rx *rx_list_tail;
-static struct net_dma_desc_rx *current_rx_ptr;
-static struct net_dma_desc_tx *current_tx_ptr;
-static struct net_dma_desc_tx *tx_desc;
-static struct net_dma_desc_rx *rx_desc;
-
-static void desc_list_free(void)
-{
-	struct net_dma_desc_rx *r;
-	struct net_dma_desc_tx *t;
-	int i;
-#if !defined(CONFIG_BFIN_MAC_USE_L1)
-	dma_addr_t dma_handle = 0;
-#endif
-
-	if (tx_desc) {
-		t = tx_list_head;
-		for (i = 0; i < CONFIG_BFIN_TX_DESC_NUM; i++) {
-			if (t) {
-				if (t->skb) {
-					dev_kfree_skb(t->skb);
-					t->skb = NULL;
-				}
-				t = t->next;
-			}
-		}
-		bfin_mac_free(dma_handle, tx_desc, CONFIG_BFIN_TX_DESC_NUM);
-	}
-
-	if (rx_desc) {
-		r = rx_list_head;
-		for (i = 0; i < CONFIG_BFIN_RX_DESC_NUM; i++) {
-			if (r) {
-				if (r->skb) {
-					dev_kfree_skb(r->skb);
-					r->skb = NULL;
-				}
-				r = r->next;
-			}
-		}
-		bfin_mac_free(dma_handle, rx_desc, CONFIG_BFIN_RX_DESC_NUM);
-	}
-}
-
-static int desc_list_init(void)
-{
-	int i;
-	struct sk_buff *new_skb;
-#if !defined(CONFIG_BFIN_MAC_USE_L1)
-	/*
-	 * This dma_handle is useless in Blackfin dma_alloc_coherent().
-	 * The real dma handler is the return value of dma_alloc_coherent().
-	 */
-	dma_addr_t dma_handle;
-#endif
-
-	tx_desc = bfin_mac_alloc(&dma_handle,
-				sizeof(struct net_dma_desc_tx),
-				CONFIG_BFIN_TX_DESC_NUM);
-	if (tx_desc == NULL)
-		goto init_error;
-
-	rx_desc = bfin_mac_alloc(&dma_handle,
-				sizeof(struct net_dma_desc_rx),
-				CONFIG_BFIN_RX_DESC_NUM);
-	if (rx_desc == NULL)
-		goto init_error;
-
-	/* init tx_list */
-	tx_list_head = tx_list_tail = tx_desc;
-
-	for (i = 0; i < CONFIG_BFIN_TX_DESC_NUM; i++) {
-		struct net_dma_desc_tx *t = tx_desc + i;
-		struct dma_descriptor *a = &(t->desc_a);
-		struct dma_descriptor *b = &(t->desc_b);
-
-		/*
-		 * disable DMA
-		 * read from memory WNR = 0
-		 * wordsize is 32 bits
-		 * 6 half words is desc size
-		 * large desc flow
-		 */
-		a->config = WDSIZE_32 | NDSIZE_6 | DMAFLOW_LARGE;
-		a->start_addr = (unsigned long)t->packet;
-		a->x_count = 0;
-		a->next_dma_desc = b;
-
-		/*
-		 * enabled DMA
-		 * write to memory WNR = 1
-		 * wordsize is 32 bits
-		 * disable interrupt
-		 * 6 half words is desc size
-		 * large desc flow
-		 */
-		b->config = DMAEN | WNR | WDSIZE_32 | NDSIZE_6 | DMAFLOW_LARGE;
-		b->start_addr = (unsigned long)(&(t->status));
-		b->x_count = 0;
-
-		t->skb = NULL;
-		tx_list_tail->desc_b.next_dma_desc = a;
-		tx_list_tail->next = t;
-		tx_list_tail = t;
-	}
-	tx_list_tail->next = tx_list_head;	/* tx_list is a circle */
-	tx_list_tail->desc_b.next_dma_desc = &(tx_list_head->desc_a);
-	current_tx_ptr = tx_list_head;
-
-	/* init rx_list */
-	rx_list_head = rx_list_tail = rx_desc;
-
-	for (i = 0; i < CONFIG_BFIN_RX_DESC_NUM; i++) {
-		struct net_dma_desc_rx *r = rx_desc + i;
-		struct dma_descriptor *a = &(r->desc_a);
-		struct dma_descriptor *b = &(r->desc_b);
-
-		/* allocate a new skb for next time receive */
-		new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN);
-		if (!new_skb) {
-			pr_notice("init: low on mem - packet dropped\n");
-			goto init_error;
-		}
-		skb_reserve(new_skb, NET_IP_ALIGN);
-		/* Invidate the data cache of skb->data range when it is write back
-		 * cache. It will prevent overwritting the new data from DMA
-		 */
-		blackfin_dcache_invalidate_range((unsigned long)new_skb->head,
-					 (unsigned long)new_skb->end);
-		r->skb = new_skb;
-
-		/*
-		 * enabled DMA
-		 * write to memory WNR = 1
-		 * wordsize is 32 bits
-		 * disable interrupt
-		 * 6 half words is desc size
-		 * large desc flow
-		 */
-		a->config = DMAEN | WNR | WDSIZE_32 | NDSIZE_6 | DMAFLOW_LARGE;
-		/* since RXDWA is enabled */
-		a->start_addr = (unsigned long)new_skb->data - 2;
-		a->x_count = 0;
-		a->next_dma_desc = b;
-
-		/*
-		 * enabled DMA
-		 * write to memory WNR = 1
-		 * wordsize is 32 bits
-		 * enable interrupt
-		 * 6 half words is desc size
-		 * large desc flow
-		 */
-		b->config = DMAEN | WNR | WDSIZE_32 | DI_EN |
-				NDSIZE_6 | DMAFLOW_LARGE;
-		b->start_addr = (unsigned long)(&(r->status));
-		b->x_count = 0;
-
-		rx_list_tail->desc_b.next_dma_desc = a;
-		rx_list_tail->next = r;
-		rx_list_tail = r;
-	}
-	rx_list_tail->next = rx_list_head;	/* rx_list is a circle */
-	rx_list_tail->desc_b.next_dma_desc = &(rx_list_head->desc_a);
-	current_rx_ptr = rx_list_head;
-
-	return 0;
-
-init_error:
-	desc_list_free();
-	pr_err("kmalloc failed\n");
-	return -ENOMEM;
-}
-
-
-/*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/
-
-/*
- * MII operations
- */
-/* Wait until the previous MDC/MDIO transaction has completed */
-static int bfin_mdio_poll(void)
-{
-	int timeout_cnt = MAX_TIMEOUT_CNT;
-
-	/* poll the STABUSY bit */
-	while ((bfin_read_EMAC_STAADD()) & STABUSY) {
-		udelay(1);
-		if (timeout_cnt-- < 0) {
-			pr_err("wait MDC/MDIO transaction to complete timeout\n");
-			return -ETIMEDOUT;
-		}
-	}
-
-	return 0;
-}
-
-/* Read an off-chip register in a PHY through the MDC/MDIO port */
-static int bfin_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
-{
-	int ret;
-
-	ret = bfin_mdio_poll();
-	if (ret)
-		return ret;
-
-	/* read mode */
-	bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) |
-				SET_REGAD((u16) regnum) |
-				STABUSY);
-
-	ret = bfin_mdio_poll();
-	if (ret)
-		return ret;
-
-	return (int) bfin_read_EMAC_STADAT();
-}
-
-/* Write an off-chip register in a PHY through the MDC/MDIO port */
-static int bfin_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
-			      u16 value)
-{
-	int ret;
-
-	ret = bfin_mdio_poll();
-	if (ret)
-		return ret;
-
-	bfin_write_EMAC_STADAT((u32) value);
-
-	/* write mode */
-	bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) |
-				SET_REGAD((u16) regnum) |
-				STAOP |
-				STABUSY);
-
-	return bfin_mdio_poll();
-}
-
-static int bfin_mdiobus_reset(struct mii_bus *bus)
-{
-	return 0;
-}
-
-static void bfin_mac_adjust_link(struct net_device *dev)
-{
-	struct bfin_mac_local *lp = netdev_priv(dev);
-	struct phy_device *phydev = lp->phydev;
-	unsigned long flags;
-	int new_state = 0;
-
-	spin_lock_irqsave(&lp->lock, flags);
-	if (phydev->link) {
-		/* Now we make sure that we can be in full duplex mode.
-		 * If not, we operate in half-duplex mode. */
-		if (phydev->duplex != lp->old_duplex) {
-			u32 opmode = bfin_read_EMAC_OPMODE();
-			new_state = 1;
-
-			if (phydev->duplex)
-				opmode |= FDMODE;
-			else
-				opmode &= ~(FDMODE);
-
-			bfin_write_EMAC_OPMODE(opmode);
-			lp->old_duplex = phydev->duplex;
-		}
-
-		if (phydev->speed != lp->old_speed) {
-			if (phydev->interface == PHY_INTERFACE_MODE_RMII) {
-				u32 opmode = bfin_read_EMAC_OPMODE();
-				switch (phydev->speed) {
-				case 10:
-					opmode |= RMII_10;
-					break;
-				case 100:
-					opmode &= ~RMII_10;
-					break;
-				default:
-					netdev_warn(dev,
-						"Ack! Speed (%d) is not 10/100!\n",
-						phydev->speed);
-					break;
-				}
-				bfin_write_EMAC_OPMODE(opmode);
-			}
-
-			new_state = 1;
-			lp->old_speed = phydev->speed;
-		}
-
-		if (!lp->old_link) {
-			new_state = 1;
-			lp->old_link = 1;
-		}
-	} else if (lp->old_link) {
-		new_state = 1;
-		lp->old_link = 0;
-		lp->old_speed = 0;
-		lp->old_duplex = -1;
-	}
-
-	if (new_state) {
-		u32 opmode = bfin_read_EMAC_OPMODE();
-		phy_print_status(phydev);
-		pr_debug("EMAC_OPMODE = 0x%08x\n", opmode);
-	}
-
-	spin_unlock_irqrestore(&lp->lock, flags);
-}
-
-/* MDC  = 2.5 MHz */
-#define MDC_CLK 2500000
-
-static int mii_probe(struct net_device *dev, int phy_mode)
-{
-	struct bfin_mac_local *lp = netdev_priv(dev);
-	struct phy_device *phydev = NULL;
-	unsigned short sysctl;
-	int i;
-	u32 sclk, mdc_div;
-
-	/* Enable PHY output early */
-	if (!(bfin_read_VR_CTL() & CLKBUFOE))
-		bfin_write_VR_CTL(bfin_read_VR_CTL() | CLKBUFOE);
-
-	sclk = get_sclk();
-	mdc_div = ((sclk / MDC_CLK) / 2) - 1;
-
-	sysctl = bfin_read_EMAC_SYSCTL();
-	sysctl = (sysctl & ~MDCDIV) | SET_MDCDIV(mdc_div);
-	bfin_write_EMAC_SYSCTL(sysctl);
-
-	/* search for connected PHY device */
-	for (i = 0; i < PHY_MAX_ADDR; ++i) {
-		struct phy_device *const tmp_phydev = lp->mii_bus->phy_map[i];
-
-		if (!tmp_phydev)
-			continue; /* no PHY here... */
-
-		phydev = tmp_phydev;
-		break; /* found it */
-	}
-
-	/* now we are supposed to have a proper phydev, to attach to... */
-	if (!phydev) {
-		netdev_err(dev, "no phy device found\n");
-		return -ENODEV;
-	}
-
-	if (phy_mode != PHY_INTERFACE_MODE_RMII &&
-		phy_mode != PHY_INTERFACE_MODE_MII) {
-		netdev_err(dev, "invalid phy interface mode\n");
-		return -EINVAL;
-	}
-
-	phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link,
-			0, phy_mode);
-
-	if (IS_ERR(phydev)) {
-		netdev_err(dev, "could not attach PHY\n");
-		return PTR_ERR(phydev);
-	}
-
-	/* mask with MAC supported features */
-	phydev->supported &= (SUPPORTED_10baseT_Half
-			      | SUPPORTED_10baseT_Full
-			      | SUPPORTED_100baseT_Half
-			      | SUPPORTED_100baseT_Full
-			      | SUPPORTED_Autoneg
-			      | SUPPORTED_Pause | SUPPORTED_Asym_Pause
-			      | SUPPORTED_MII
-			      | SUPPORTED_TP);
-
-	phydev->advertising = phydev->supported;
-
-	lp->old_link = 0;
-	lp->old_speed = 0;
-	lp->old_duplex = -1;
-	lp->phydev = phydev;
-
-	pr_info("attached PHY driver [%s] "
-	        "(mii_bus:phy_addr=%s, irq=%d, mdc_clk=%dHz(mdc_div=%d)@sclk=%dMHz)\n",
-	        phydev->drv->name, dev_name(&phydev->dev), phydev->irq,
-	        MDC_CLK, mdc_div, sclk/1000000);
-
-	return 0;
-}
-
-/*
- * Ethtool support
- */
-
-/*
- * interrupt routine for magic packet wakeup
- */
-static irqreturn_t bfin_mac_wake_interrupt(int irq, void *dev_id)
-{
-	return IRQ_HANDLED;
-}
-
-static int
-bfin_mac_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct bfin_mac_local *lp = netdev_priv(dev);
-
-	if (lp->phydev)
-		return phy_ethtool_gset(lp->phydev, cmd);
-
-	return -EINVAL;
-}
-
-static int
-bfin_mac_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct bfin_mac_local *lp = netdev_priv(dev);
-
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	if (lp->phydev)
-		return phy_ethtool_sset(lp->phydev, cmd);
-
-	return -EINVAL;
-}
-
-static void bfin_mac_ethtool_getdrvinfo(struct net_device *dev,
-					struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, KBUILD_MODNAME);
-	strcpy(info->version, DRV_VERSION);
-	strcpy(info->fw_version, "N/A");
-	strcpy(info->bus_info, dev_name(&dev->dev));
-}
-
-static void bfin_mac_ethtool_getwol(struct net_device *dev,
-	struct ethtool_wolinfo *wolinfo)
-{
-	struct bfin_mac_local *lp = netdev_priv(dev);
-
-	wolinfo->supported = WAKE_MAGIC;
-	wolinfo->wolopts = lp->wol;
-}
-
-static int bfin_mac_ethtool_setwol(struct net_device *dev,
-	struct ethtool_wolinfo *wolinfo)
-{
-	struct bfin_mac_local *lp = netdev_priv(dev);
-	int rc;
-
-	if (wolinfo->wolopts & (WAKE_MAGICSECURE |
-				WAKE_UCAST |
-				WAKE_MCAST |
-				WAKE_BCAST |
-				WAKE_ARP))
-		return -EOPNOTSUPP;
-
-	lp->wol = wolinfo->wolopts;
-
-	if (lp->wol && !lp->irq_wake_requested) {
-		/* register wake irq handler */
-		rc = request_irq(IRQ_MAC_WAKEDET, bfin_mac_wake_interrupt,
-				 IRQF_DISABLED, "EMAC_WAKE", dev);
-		if (rc)
-			return rc;
-		lp->irq_wake_requested = true;
-	}
-
-	if (!lp->wol && lp->irq_wake_requested) {
-		free_irq(IRQ_MAC_WAKEDET, dev);
-		lp->irq_wake_requested = false;
-	}
-
-	/* Make sure the PHY driver doesn't suspend */
-	device_init_wakeup(&dev->dev, lp->wol);
-
-	return 0;
-}
-
-static const struct ethtool_ops bfin_mac_ethtool_ops = {
-	.get_settings = bfin_mac_ethtool_getsettings,
-	.set_settings = bfin_mac_ethtool_setsettings,
-	.get_link = ethtool_op_get_link,
-	.get_drvinfo = bfin_mac_ethtool_getdrvinfo,
-	.get_wol = bfin_mac_ethtool_getwol,
-	.set_wol = bfin_mac_ethtool_setwol,
-};
-
-/**************************************************************************/
-static void setup_system_regs(struct net_device *dev)
-{
-	struct bfin_mac_local *lp = netdev_priv(dev);
-	int i;
-	unsigned short sysctl;
-
-	/*
-	 * Odd word alignment for Receive Frame DMA word
-	 * Configure checksum support and rcve frame word alignment
-	 */
-	sysctl = bfin_read_EMAC_SYSCTL();
-	/*
-	 * check if interrupt is requested for any PHY,
-	 * enable PHY interrupt only if needed
-	 */
-	for (i = 0; i < PHY_MAX_ADDR; ++i)
-		if (lp->mii_bus->irq[i] != PHY_POLL)
-			break;
-	if (i < PHY_MAX_ADDR)
-		sysctl |= PHYIE;
-	sysctl |= RXDWA;
-#if defined(BFIN_MAC_CSUM_OFFLOAD)
-	sysctl |= RXCKS;
-#else
-	sysctl &= ~RXCKS;
-#endif
-	bfin_write_EMAC_SYSCTL(sysctl);
-
-	bfin_write_EMAC_MMC_CTL(RSTC | CROLL);
-
-	/* Set vlan regs to let 1522 bytes long packets pass through */
-	bfin_write_EMAC_VLAN1(lp->vlan1_mask);
-	bfin_write_EMAC_VLAN2(lp->vlan2_mask);
-
-	/* Initialize the TX DMA channel registers */
-	bfin_write_DMA2_X_COUNT(0);
-	bfin_write_DMA2_X_MODIFY(4);
-	bfin_write_DMA2_Y_COUNT(0);
-	bfin_write_DMA2_Y_MODIFY(0);
-
-	/* Initialize the RX DMA channel registers */
-	bfin_write_DMA1_X_COUNT(0);
-	bfin_write_DMA1_X_MODIFY(4);
-	bfin_write_DMA1_Y_COUNT(0);
-	bfin_write_DMA1_Y_MODIFY(0);
-}
-
-static void setup_mac_addr(u8 *mac_addr)
-{
-	u32 addr_low = le32_to_cpu(*(__le32 *) & mac_addr[0]);
-	u16 addr_hi = le16_to_cpu(*(__le16 *) & mac_addr[4]);
-
-	/* this depends on a little-endian machine */
-	bfin_write_EMAC_ADDRLO(addr_low);
-	bfin_write_EMAC_ADDRHI(addr_hi);
-}
-
-static int bfin_mac_set_mac_address(struct net_device *dev, void *p)
-{
-	struct sockaddr *addr = p;
-	if (netif_running(dev))
-		return -EBUSY;
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-	setup_mac_addr(dev->dev_addr);
-	return 0;
-}
-
-#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP
-#define bfin_mac_hwtstamp_is_none(cfg) ((cfg) == HWTSTAMP_FILTER_NONE)
-
-static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
-		struct ifreq *ifr, int cmd)
-{
-	struct hwtstamp_config config;
-	struct bfin_mac_local *lp = netdev_priv(netdev);
-	u16 ptpctl;
-	u32 ptpfv1, ptpfv2, ptpfv3, ptpfoff;
-
-	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
-		return -EFAULT;
-
-	pr_debug("%s config flag:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
-			__func__, config.flags, config.tx_type, config.rx_filter);
-
-	/* reserved for future extensions */
-	if (config.flags)
-		return -EINVAL;
-
-	if ((config.tx_type != HWTSTAMP_TX_OFF) &&
-			(config.tx_type != HWTSTAMP_TX_ON))
-		return -ERANGE;
-
-	ptpctl = bfin_read_EMAC_PTP_CTL();
-
-	switch (config.rx_filter) {
-	case HWTSTAMP_FILTER_NONE:
-		/*
-		 * Dont allow any timestamping
-		 */
-		ptpfv3 = 0xFFFFFFFF;
-		bfin_write_EMAC_PTP_FV3(ptpfv3);
-		break;
-	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
-	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
-	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
-		/*
-		 * Clear the five comparison mask bits (bits[12:8]) in EMAC_PTP_CTL)
-		 * to enable all the field matches.
-		 */
-		ptpctl &= ~0x1F00;
-		bfin_write_EMAC_PTP_CTL(ptpctl);
-		/*
-		 * Keep the default values of the EMAC_PTP_FOFF register.
-		 */
-		ptpfoff = 0x4A24170C;
-		bfin_write_EMAC_PTP_FOFF(ptpfoff);
-		/*
-		 * Keep the default values of the EMAC_PTP_FV1 and EMAC_PTP_FV2
-		 * registers.
-		 */
-		ptpfv1 = 0x11040800;
-		bfin_write_EMAC_PTP_FV1(ptpfv1);
-		ptpfv2 = 0x0140013F;
-		bfin_write_EMAC_PTP_FV2(ptpfv2);
-		/*
-		 * The default value (0xFFFC) allows the timestamping of both
-		 * received Sync messages and Delay_Req messages.
-		 */
-		ptpfv3 = 0xFFFFFFFC;
-		bfin_write_EMAC_PTP_FV3(ptpfv3);
-
-		config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
-		break;
-	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
-	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
-	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
-		/* Clear all five comparison mask bits (bits[12:8]) in the
-		 * EMAC_PTP_CTL register to enable all the field matches.
-		 */
-		ptpctl &= ~0x1F00;
-		bfin_write_EMAC_PTP_CTL(ptpctl);
-		/*
-		 * Keep the default values of the EMAC_PTP_FOFF register, except set
-		 * the PTPCOF field to 0x2A.
-		 */
-		ptpfoff = 0x2A24170C;
-		bfin_write_EMAC_PTP_FOFF(ptpfoff);
-		/*
-		 * Keep the default values of the EMAC_PTP_FV1 and EMAC_PTP_FV2
-		 * registers.
-		 */
-		ptpfv1 = 0x11040800;
-		bfin_write_EMAC_PTP_FV1(ptpfv1);
-		ptpfv2 = 0x0140013F;
-		bfin_write_EMAC_PTP_FV2(ptpfv2);
-		/*
-		 * To allow the timestamping of Pdelay_Req and Pdelay_Resp, set
-		 * the value to 0xFFF0.
-		 */
-		ptpfv3 = 0xFFFFFFF0;
-		bfin_write_EMAC_PTP_FV3(ptpfv3);
-
-		config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
-		break;
-	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
-	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
-	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
-		/*
-		 * Clear bits 8 and 12 of the EMAC_PTP_CTL register to enable only the
-		 * EFTM and PTPCM field comparison.
-		 */
-		ptpctl &= ~0x1100;
-		bfin_write_EMAC_PTP_CTL(ptpctl);
-		/*
-		 * Keep the default values of all the fields of the EMAC_PTP_FOFF
-		 * register, except set the PTPCOF field to 0x0E.
-		 */
-		ptpfoff = 0x0E24170C;
-		bfin_write_EMAC_PTP_FOFF(ptpfoff);
-		/*
-		 * Program bits [15:0] of the EMAC_PTP_FV1 register to 0x88F7, which
-		 * corresponds to PTP messages on the MAC layer.
-		 */
-		ptpfv1 = 0x110488F7;
-		bfin_write_EMAC_PTP_FV1(ptpfv1);
-		ptpfv2 = 0x0140013F;
-		bfin_write_EMAC_PTP_FV2(ptpfv2);
-		/*
-		 * To allow the timestamping of Pdelay_Req and Pdelay_Resp
-		 * messages, set the value to 0xFFF0.
-		 */
-		ptpfv3 = 0xFFFFFFF0;
-		bfin_write_EMAC_PTP_FV3(ptpfv3);
-
-		config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
-		break;
-	default:
-		return -ERANGE;
-	}
-
-	if (config.tx_type == HWTSTAMP_TX_OFF &&
-	    bfin_mac_hwtstamp_is_none(config.rx_filter)) {
-		ptpctl &= ~PTP_EN;
-		bfin_write_EMAC_PTP_CTL(ptpctl);
-
-		SSYNC();
-	} else {
-		ptpctl |= PTP_EN;
-		bfin_write_EMAC_PTP_CTL(ptpctl);
-
-		/*
-		 * clear any existing timestamp
-		 */
-		bfin_read_EMAC_PTP_RXSNAPLO();
-		bfin_read_EMAC_PTP_RXSNAPHI();
-
-		bfin_read_EMAC_PTP_TXSNAPLO();
-		bfin_read_EMAC_PTP_TXSNAPHI();
-
-		/*
-		 * Set registers so that rollover occurs soon to test this.
-		 */
-		bfin_write_EMAC_PTP_TIMELO(0x00000000);
-		bfin_write_EMAC_PTP_TIMEHI(0xFF800000);
-
-		SSYNC();
-
-		lp->compare.last_update = 0;
-		timecounter_init(&lp->clock,
-				&lp->cycles,
-				ktime_to_ns(ktime_get_real()));
-		timecompare_update(&lp->compare, 0);
-	}
-
-	lp->stamp_cfg = config;
-	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
-		-EFAULT : 0;
-}
-
-static void bfin_dump_hwtamp(char *s, ktime_t *hw, ktime_t *ts, struct timecompare *cmp)
-{
-	ktime_t sys = ktime_get_real();
-
-	pr_debug("%s %s hardware:%d,%d transform system:%d,%d system:%d,%d, cmp:%lld, %lld\n",
-			__func__, s, hw->tv.sec, hw->tv.nsec, ts->tv.sec, ts->tv.nsec, sys.tv.sec,
-			sys.tv.nsec, cmp->offset, cmp->skew);
-}
-
-static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
-{
-	struct bfin_mac_local *lp = netdev_priv(netdev);
-
-	if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
-		int timeout_cnt = MAX_TIMEOUT_CNT;
-
-		/* When doing time stamping, keep the connection to the socket
-		 * a while longer
-		 */
-		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
-
-		/*
-		 * The timestamping is done at the EMAC module's MII/RMII interface
-		 * when the module sees the Start of Frame of an event message packet. This
-		 * interface is the closest possible place to the physical Ethernet transmission
-		 * medium, providing the best timing accuracy.
-		 */
-		while ((!(bfin_read_EMAC_PTP_ISTAT() & TXTL)) && (--timeout_cnt))
-			udelay(1);
-		if (timeout_cnt == 0)
-			netdev_err(netdev, "timestamp the TX packet failed\n");
-		else {
-			struct skb_shared_hwtstamps shhwtstamps;
-			u64 ns;
-			u64 regval;
-
-			regval = bfin_read_EMAC_PTP_TXSNAPLO();
-			regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32;
-			memset(&shhwtstamps, 0, sizeof(shhwtstamps));
-			ns = timecounter_cyc2time(&lp->clock,
-					regval);
-			timecompare_update(&lp->compare, ns);
-			shhwtstamps.hwtstamp = ns_to_ktime(ns);
-			shhwtstamps.syststamp =
-				timecompare_transform(&lp->compare, ns);
-			skb_tstamp_tx(skb, &shhwtstamps);
-
-			bfin_dump_hwtamp("TX", &shhwtstamps.hwtstamp, &shhwtstamps.syststamp, &lp->compare);
-		}
-	}
-}
-
-static void bfin_rx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
-{
-	struct bfin_mac_local *lp = netdev_priv(netdev);
-	u32 valid;
-	u64 regval, ns;
-	struct skb_shared_hwtstamps *shhwtstamps;
-
-	if (bfin_mac_hwtstamp_is_none(lp->stamp_cfg.rx_filter))
-		return;
-
-	valid = bfin_read_EMAC_PTP_ISTAT() & RXEL;
-	if (!valid)
-		return;
-
-	shhwtstamps = skb_hwtstamps(skb);
-
-	regval = bfin_read_EMAC_PTP_RXSNAPLO();
-	regval |= (u64)bfin_read_EMAC_PTP_RXSNAPHI() << 32;
-	ns = timecounter_cyc2time(&lp->clock, regval);
-	timecompare_update(&lp->compare, ns);
-	memset(shhwtstamps, 0, sizeof(*shhwtstamps));
-	shhwtstamps->hwtstamp = ns_to_ktime(ns);
-	shhwtstamps->syststamp = timecompare_transform(&lp->compare, ns);
-
-	bfin_dump_hwtamp("RX", &shhwtstamps->hwtstamp, &shhwtstamps->syststamp, &lp->compare);
-}
-
-/*
- * bfin_read_clock - read raw cycle counter (to be used by time counter)
- */
-static cycle_t bfin_read_clock(const struct cyclecounter *tc)
-{
-	u64 stamp;
-
-	stamp =  bfin_read_EMAC_PTP_TIMELO();
-	stamp |= (u64)bfin_read_EMAC_PTP_TIMEHI() << 32ULL;
-
-	return stamp;
-}
-
-#define PTP_CLK 25000000
-
-static void bfin_mac_hwtstamp_init(struct net_device *netdev)
-{
-	struct bfin_mac_local *lp = netdev_priv(netdev);
-	u64 append;
-
-	/* Initialize hardware timer */
-	append = PTP_CLK * (1ULL << 32);
-	do_div(append, get_sclk());
-	bfin_write_EMAC_PTP_ADDEND((u32)append);
-
-	memset(&lp->cycles, 0, sizeof(lp->cycles));
-	lp->cycles.read = bfin_read_clock;
-	lp->cycles.mask = CLOCKSOURCE_MASK(64);
-	lp->cycles.mult = 1000000000 / PTP_CLK;
-	lp->cycles.shift = 0;
-
-	/* Synchronize our NIC clock against system wall clock */
-	memset(&lp->compare, 0, sizeof(lp->compare));
-	lp->compare.source = &lp->clock;
-	lp->compare.target = ktime_get_real;
-	lp->compare.num_samples = 10;
-
-	/* Initialize hwstamp config */
-	lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE;
-	lp->stamp_cfg.tx_type = HWTSTAMP_TX_OFF;
-}
-
-#else
-# define bfin_mac_hwtstamp_is_none(cfg) 0
-# define bfin_mac_hwtstamp_init(dev)
-# define bfin_mac_hwtstamp_ioctl(dev, ifr, cmd) (-EOPNOTSUPP)
-# define bfin_rx_hwtstamp(dev, skb)
-# define bfin_tx_hwtstamp(dev, skb)
-#endif
-
-static inline void _tx_reclaim_skb(void)
-{
-	do {
-		tx_list_head->desc_a.config &= ~DMAEN;
-		tx_list_head->status.status_word = 0;
-		if (tx_list_head->skb) {
-			dev_kfree_skb(tx_list_head->skb);
-			tx_list_head->skb = NULL;
-		}
-		tx_list_head = tx_list_head->next;
-
-	} while (tx_list_head->status.status_word != 0);
-}
-
-static void tx_reclaim_skb(struct bfin_mac_local *lp)
-{
-	int timeout_cnt = MAX_TIMEOUT_CNT;
-
-	if (tx_list_head->status.status_word != 0)
-		_tx_reclaim_skb();
-
-	if (current_tx_ptr->next == tx_list_head) {
-		while (tx_list_head->status.status_word == 0) {
-			/* slow down polling to avoid too many queue stop. */
-			udelay(10);
-			/* reclaim skb if DMA is not running. */
-			if (!(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN))
-				break;
-			if (timeout_cnt-- < 0)
-				break;
-		}
-
-		if (timeout_cnt >= 0)
-			_tx_reclaim_skb();
-		else
-			netif_stop_queue(lp->ndev);
-	}
-
-	if (current_tx_ptr->next != tx_list_head &&
-		netif_queue_stopped(lp->ndev))
-		netif_wake_queue(lp->ndev);
-
-	if (tx_list_head != current_tx_ptr) {
-		/* shorten the timer interval if tx queue is stopped */
-		if (netif_queue_stopped(lp->ndev))
-			lp->tx_reclaim_timer.expires =
-				jiffies + (TX_RECLAIM_JIFFIES >> 4);
-		else
-			lp->tx_reclaim_timer.expires =
-				jiffies + TX_RECLAIM_JIFFIES;
-
-		mod_timer(&lp->tx_reclaim_timer,
-			lp->tx_reclaim_timer.expires);
-	}
-
-	return;
-}
-
-static void tx_reclaim_skb_timeout(unsigned long lp)
-{
-	tx_reclaim_skb((struct bfin_mac_local *)lp);
-}
-
-static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
-				struct net_device *dev)
-{
-	struct bfin_mac_local *lp = netdev_priv(dev);
-	u16 *data;
-	u32 data_align = (unsigned long)(skb->data) & 0x3;
-
-	current_tx_ptr->skb = skb;
-
-	if (data_align == 0x2) {
-		/* move skb->data to current_tx_ptr payload */
-		data = (u16 *)(skb->data) - 1;
-		*data = (u16)(skb->len);
-		/*
-		 * When transmitting an Ethernet packet, the PTP_TSYNC module requires
-		 * a DMA_Length_Word field associated with the packet. The lower 12 bits
-		 * of this field are the length of the packet payload in bytes and the higher
-		 * 4 bits are the timestamping enable field.
-		 */
-		if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
-			*data |= 0x1000;
-
-		current_tx_ptr->desc_a.start_addr = (u32)data;
-		/* this is important! */
-		blackfin_dcache_flush_range((u32)data,
-				(u32)((u8 *)data + skb->len + 4));
-	} else {
-		*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
-		/* enable timestamping for the sent packet */
-		if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
-			*((u16 *)(current_tx_ptr->packet)) |= 0x1000;
-		memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
-			skb->len);
-		current_tx_ptr->desc_a.start_addr =
-			(u32)current_tx_ptr->packet;
-		blackfin_dcache_flush_range(
-			(u32)current_tx_ptr->packet,
-			(u32)(current_tx_ptr->packet + skb->len + 2));
-	}
-
-	/* make sure the internal data buffers in the core are drained
-	 * so that the DMA descriptors are completely written when the
-	 * DMA engine goes to fetch them below
-	 */
-	SSYNC();
-
-	/* always clear status buffer before start tx dma */
-	current_tx_ptr->status.status_word = 0;
-
-	/* enable this packet's dma */
-	current_tx_ptr->desc_a.config |= DMAEN;
-
-	/* tx dma is running, just return */
-	if (bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)
-		goto out;
-
-	/* tx dma is not running */
-	bfin_write_DMA2_NEXT_DESC_PTR(&(current_tx_ptr->desc_a));
-	/* dma enabled, read from memory, size is 6 */
-	bfin_write_DMA2_CONFIG(current_tx_ptr->desc_a.config);
-	/* Turn on the EMAC tx */
-	bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE);
-
-out:
-	bfin_tx_hwtstamp(dev, skb);
-
-	current_tx_ptr = current_tx_ptr->next;
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += (skb->len);
-
-	tx_reclaim_skb(lp);
-
-	return NETDEV_TX_OK;
-}
-
-#define IP_HEADER_OFF  0
-#define RX_ERROR_MASK (RX_LONG | RX_ALIGN | RX_CRC | RX_LEN | \
-	RX_FRAG | RX_ADDR | RX_DMAO | RX_PHY | RX_LATE | RX_RANGE)
-
-static void bfin_mac_rx(struct net_device *dev)
-{
-	struct sk_buff *skb, *new_skb;
-	unsigned short len;
-	struct bfin_mac_local *lp __maybe_unused = netdev_priv(dev);
-#if defined(BFIN_MAC_CSUM_OFFLOAD)
-	unsigned int i;
-	unsigned char fcs[ETH_FCS_LEN + 1];
-#endif
-
-	/* check if frame status word reports an error condition
-	 * we which case we simply drop the packet
-	 */
-	if (current_rx_ptr->status.status_word & RX_ERROR_MASK) {
-		netdev_notice(dev, "rx: receive error - packet dropped\n");
-		dev->stats.rx_dropped++;
-		goto out;
-	}
-
-	/* allocate a new skb for next time receive */
-	skb = current_rx_ptr->skb;
-
-	new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN);
-	if (!new_skb) {
-		netdev_notice(dev, "rx: low on mem - packet dropped\n");
-		dev->stats.rx_dropped++;
-		goto out;
-	}
-	/* reserve 2 bytes for RXDWA padding */
-	skb_reserve(new_skb, NET_IP_ALIGN);
-	/* Invidate the data cache of skb->data range when it is write back
-	 * cache. It will prevent overwritting the new data from DMA
-	 */
-	blackfin_dcache_invalidate_range((unsigned long)new_skb->head,
-					 (unsigned long)new_skb->end);
-
-	current_rx_ptr->skb = new_skb;
-	current_rx_ptr->desc_a.start_addr = (unsigned long)new_skb->data - 2;
-
-	len = (unsigned short)((current_rx_ptr->status.status_word) & RX_FRLEN);
-	/* Deduce Ethernet FCS length from Ethernet payload length */
-	len -= ETH_FCS_LEN;
-	skb_put(skb, len);
-
-	skb->protocol = eth_type_trans(skb, dev);
-
-	bfin_rx_hwtstamp(dev, skb);
-
-#if defined(BFIN_MAC_CSUM_OFFLOAD)
-	/* Checksum offloading only works for IPv4 packets with the standard IP header
-	 * length of 20 bytes, because the blackfin MAC checksum calculation is
-	 * based on that assumption. We must NOT use the calculated checksum if our
-	 * IP version or header break that assumption.
-	 */
-	if (skb->data[IP_HEADER_OFF] == 0x45) {
-		skb->csum = current_rx_ptr->status.ip_payload_csum;
-		/*
-		 * Deduce Ethernet FCS from hardware generated IP payload checksum.
-		 * IP checksum is based on 16-bit one's complement algorithm.
-		 * To deduce a value from checksum is equal to add its inversion.
-		 * If the IP payload len is odd, the inversed FCS should also
-		 * begin from odd address and leave first byte zero.
-		 */
-		if (skb->len % 2) {
-			fcs[0] = 0;
-			for (i = 0; i < ETH_FCS_LEN; i++)
-				fcs[i + 1] = ~skb->data[skb->len + i];
-			skb->csum = csum_partial(fcs, ETH_FCS_LEN + 1, skb->csum);
-		} else {
-			for (i = 0; i < ETH_FCS_LEN; i++)
-				fcs[i] = ~skb->data[skb->len + i];
-			skb->csum = csum_partial(fcs, ETH_FCS_LEN, skb->csum);
-		}
-		skb->ip_summed = CHECKSUM_COMPLETE;
-	}
-#endif
-
-	netif_rx(skb);
-	dev->stats.rx_packets++;
-	dev->stats.rx_bytes += len;
-out:
-	current_rx_ptr->status.status_word = 0x00000000;
-	current_rx_ptr = current_rx_ptr->next;
-}
-
-/* interrupt routine to handle rx and error signal */
-static irqreturn_t bfin_mac_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	int number = 0;
-
-get_one_packet:
-	if (current_rx_ptr->status.status_word == 0) {
-		/* no more new packet received */
-		if (number == 0) {
-			if (current_rx_ptr->next->status.status_word != 0) {
-				current_rx_ptr = current_rx_ptr->next;
-				goto real_rx;
-			}
-		}
-		bfin_write_DMA1_IRQ_STATUS(bfin_read_DMA1_IRQ_STATUS() |
-					   DMA_DONE | DMA_ERR);
-		return IRQ_HANDLED;
-	}
-
-real_rx:
-	bfin_mac_rx(dev);
-	number++;
-	goto get_one_packet;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void bfin_mac_poll(struct net_device *dev)
-{
-	struct bfin_mac_local *lp = netdev_priv(dev);
-
-	disable_irq(IRQ_MAC_RX);
-	bfin_mac_interrupt(IRQ_MAC_RX, dev);
-	tx_reclaim_skb(lp);
-	enable_irq(IRQ_MAC_RX);
-}
-#endif				/* CONFIG_NET_POLL_CONTROLLER */
-
-static void bfin_mac_disable(void)
-{
-	unsigned int opmode;
-
-	opmode = bfin_read_EMAC_OPMODE();
-	opmode &= (~RE);
-	opmode &= (~TE);
-	/* Turn off the EMAC */
-	bfin_write_EMAC_OPMODE(opmode);
-}
-
-/*
- * Enable Interrupts, Receive, and Transmit
- */
-static int bfin_mac_enable(struct phy_device *phydev)
-{
-	int ret;
-	u32 opmode;
-
-	pr_debug("%s\n", __func__);
-
-	/* Set RX DMA */
-	bfin_write_DMA1_NEXT_DESC_PTR(&(rx_list_head->desc_a));
-	bfin_write_DMA1_CONFIG(rx_list_head->desc_a.config);
-
-	/* Wait MII done */
-	ret = bfin_mdio_poll();
-	if (ret)
-		return ret;
-
-	/* We enable only RX here */
-	/* ASTP   : Enable Automatic Pad Stripping
-	   PR     : Promiscuous Mode for test
-	   PSF    : Receive frames with total length less than 64 bytes.
-	   FDMODE : Full Duplex Mode
-	   LB     : Internal Loopback for test
-	   RE     : Receiver Enable */
-	opmode = bfin_read_EMAC_OPMODE();
-	if (opmode & FDMODE)
-		opmode |= PSF;
-	else
-		opmode |= DRO | DC | PSF;
-	opmode |= RE;
-
-	if (phydev->interface == PHY_INTERFACE_MODE_RMII) {
-		opmode |= RMII; /* For Now only 100MBit are supported */
-#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
-	}
-
-	/* Turn on the EMAC rx */
-	bfin_write_EMAC_OPMODE(opmode);
-
-	return 0;
-}
-
-/* Our watchdog timed out. Called by the networking layer */
-static void bfin_mac_timeout(struct net_device *dev)
-{
-	struct bfin_mac_local *lp = netdev_priv(dev);
-
-	pr_debug("%s: %s\n", dev->name, __func__);
-
-	bfin_mac_disable();
-
-	del_timer(&lp->tx_reclaim_timer);
-
-	/* reset tx queue and free skb */
-	while (tx_list_head != current_tx_ptr) {
-		tx_list_head->desc_a.config &= ~DMAEN;
-		tx_list_head->status.status_word = 0;
-		if (tx_list_head->skb) {
-			dev_kfree_skb(tx_list_head->skb);
-			tx_list_head->skb = NULL;
-		}
-		tx_list_head = tx_list_head->next;
-	}
-
-	if (netif_queue_stopped(lp->ndev))
-		netif_wake_queue(lp->ndev);
-
-	bfin_mac_enable(lp->phydev);
-
-	/* We can accept TX packets again */
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	netif_wake_queue(dev);
-}
-
-static void bfin_mac_multicast_hash(struct net_device *dev)
-{
-	u32 emac_hashhi, emac_hashlo;
-	struct netdev_hw_addr *ha;
-	u32 crc;
-
-	emac_hashhi = emac_hashlo = 0;
-
-	netdev_for_each_mc_addr(ha, dev) {
-		crc = ether_crc(ETH_ALEN, ha->addr);
-		crc >>= 26;
-
-		if (crc & 0x20)
-			emac_hashhi |= 1 << (crc & 0x1f);
-		else
-			emac_hashlo |= 1 << (crc & 0x1f);
-	}
-
-	bfin_write_EMAC_HASHHI(emac_hashhi);
-	bfin_write_EMAC_HASHLO(emac_hashlo);
-}
-
-/*
- * This routine will, depending on the values passed to it,
- * either make it accept multicast packets, go into
- * promiscuous mode (for TCPDUMP and cousins) or accept
- * a select set of multicast packets
- */
-static void bfin_mac_set_multicast_list(struct net_device *dev)
-{
-	u32 sysctl;
-
-	if (dev->flags & IFF_PROMISC) {
-		netdev_info(dev, "set promisc mode\n");
-		sysctl = bfin_read_EMAC_OPMODE();
-		sysctl |= PR;
-		bfin_write_EMAC_OPMODE(sysctl);
-	} else if (dev->flags & IFF_ALLMULTI) {
-		/* accept all multicast */
-		sysctl = bfin_read_EMAC_OPMODE();
-		sysctl |= PAM;
-		bfin_write_EMAC_OPMODE(sysctl);
-	} else if (!netdev_mc_empty(dev)) {
-		/* set up multicast hash table */
-		sysctl = bfin_read_EMAC_OPMODE();
-		sysctl |= HM;
-		bfin_write_EMAC_OPMODE(sysctl);
-		bfin_mac_multicast_hash(dev);
-	} else {
-		/* clear promisc or multicast mode */
-		sysctl = bfin_read_EMAC_OPMODE();
-		sysctl &= ~(RAF | PAM);
-		bfin_write_EMAC_OPMODE(sysctl);
-	}
-}
-
-static int bfin_mac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	struct bfin_mac_local *lp = netdev_priv(netdev);
-
-	if (!netif_running(netdev))
-		return -EINVAL;
-
-	switch (cmd) {
-	case SIOCSHWTSTAMP:
-		return bfin_mac_hwtstamp_ioctl(netdev, ifr, cmd);
-	default:
-		if (lp->phydev)
-			return phy_mii_ioctl(lp->phydev, ifr, cmd);
-		else
-			return -EOPNOTSUPP;
-	}
-}
-
-/*
- * this puts the device in an inactive state
- */
-static void bfin_mac_shutdown(struct net_device *dev)
-{
-	/* Turn off the EMAC */
-	bfin_write_EMAC_OPMODE(0x00000000);
-	/* Turn off the EMAC RX DMA */
-	bfin_write_DMA1_CONFIG(0x0000);
-	bfin_write_DMA2_CONFIG(0x0000);
-}
-
-/*
- * Open and Initialize the interface
- *
- * Set up everything, reset the card, etc..
- */
-static int bfin_mac_open(struct net_device *dev)
-{
-	struct bfin_mac_local *lp = netdev_priv(dev);
-	int ret;
-	pr_debug("%s: %s\n", dev->name, __func__);
-
-	/*
-	 * Check that the address is valid.  If its not, refuse
-	 * to bring the device up.  The user must specify an
-	 * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
-	 */
-	if (!is_valid_ether_addr(dev->dev_addr)) {
-		netdev_warn(dev, "no valid ethernet hw addr\n");
-		return -EINVAL;
-	}
-
-	/* initial rx and tx list */
-	ret = desc_list_init();
-	if (ret)
-		return ret;
-
-	phy_start(lp->phydev);
-	phy_write(lp->phydev, MII_BMCR, BMCR_RESET);
-	setup_system_regs(dev);
-	setup_mac_addr(dev->dev_addr);
-
-	bfin_mac_disable();
-	ret = bfin_mac_enable(lp->phydev);
-	if (ret)
-		return ret;
-	pr_debug("hardware init finished\n");
-
-	netif_start_queue(dev);
-	netif_carrier_on(dev);
-
-	return 0;
-}
-
-/*
- * this makes the board clean up everything that it can
- * and not talk to the outside world.   Caused by
- * an 'ifconfig ethX down'
- */
-static int bfin_mac_close(struct net_device *dev)
-{
-	struct bfin_mac_local *lp = netdev_priv(dev);
-	pr_debug("%s: %s\n", dev->name, __func__);
-
-	netif_stop_queue(dev);
-	netif_carrier_off(dev);
-
-	phy_stop(lp->phydev);
-	phy_write(lp->phydev, MII_BMCR, BMCR_PDOWN);
-
-	/* clear everything */
-	bfin_mac_shutdown(dev);
-
-	/* free the rx/tx buffers */
-	desc_list_free();
-
-	return 0;
-}
-
-static const struct net_device_ops bfin_mac_netdev_ops = {
-	.ndo_open		= bfin_mac_open,
-	.ndo_stop		= bfin_mac_close,
-	.ndo_start_xmit		= bfin_mac_hard_start_xmit,
-	.ndo_set_mac_address	= bfin_mac_set_mac_address,
-	.ndo_tx_timeout		= bfin_mac_timeout,
-	.ndo_set_multicast_list	= bfin_mac_set_multicast_list,
-	.ndo_do_ioctl           = bfin_mac_ioctl,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= bfin_mac_poll,
-#endif
-};
-
-static int __devinit bfin_mac_probe(struct platform_device *pdev)
-{
-	struct net_device *ndev;
-	struct bfin_mac_local *lp;
-	struct platform_device *pd;
-	struct bfin_mii_bus_platform_data *mii_bus_data;
-	int rc;
-
-	ndev = alloc_etherdev(sizeof(struct bfin_mac_local));
-	if (!ndev) {
-		dev_err(&pdev->dev, "Cannot allocate net device!\n");
-		return -ENOMEM;
-	}
-
-	SET_NETDEV_DEV(ndev, &pdev->dev);
-	platform_set_drvdata(pdev, ndev);
-	lp = netdev_priv(ndev);
-	lp->ndev = ndev;
-
-	/* Grab the MAC address in the MAC */
-	*(__le32 *) (&(ndev->dev_addr[0])) = cpu_to_le32(bfin_read_EMAC_ADDRLO());
-	*(__le16 *) (&(ndev->dev_addr[4])) = cpu_to_le16((u16) bfin_read_EMAC_ADDRHI());
-
-	/* probe mac */
-	/*todo: how to proble? which is revision_register */
-	bfin_write_EMAC_ADDRLO(0x12345678);
-	if (bfin_read_EMAC_ADDRLO() != 0x12345678) {
-		dev_err(&pdev->dev, "Cannot detect Blackfin on-chip ethernet MAC controller!\n");
-		rc = -ENODEV;
-		goto out_err_probe_mac;
-	}
-
-
-	/*
-	 * Is it valid? (Did bootloader initialize it?)
-	 * Grab the MAC from the board somehow
-	 * this is done in the arch/blackfin/mach-bfxxx/boards/eth_mac.c
-	 */
-	if (!is_valid_ether_addr(ndev->dev_addr))
-		bfin_get_ether_addr(ndev->dev_addr);
-
-	/* If still not valid, get a random one */
-	if (!is_valid_ether_addr(ndev->dev_addr))
-		random_ether_addr(ndev->dev_addr);
-
-	setup_mac_addr(ndev->dev_addr);
-
-	if (!pdev->dev.platform_data) {
-		dev_err(&pdev->dev, "Cannot get platform device bfin_mii_bus!\n");
-		rc = -ENODEV;
-		goto out_err_probe_mac;
-	}
-	pd = pdev->dev.platform_data;
-	lp->mii_bus = platform_get_drvdata(pd);
-	if (!lp->mii_bus) {
-		dev_err(&pdev->dev, "Cannot get mii_bus!\n");
-		rc = -ENODEV;
-		goto out_err_probe_mac;
-	}
-	lp->mii_bus->priv = ndev;
-	mii_bus_data = pd->dev.platform_data;
-
-	rc = mii_probe(ndev, mii_bus_data->phy_mode);
-	if (rc) {
-		dev_err(&pdev->dev, "MII Probe failed!\n");
-		goto out_err_mii_probe;
-	}
-
-	lp->vlan1_mask = ETH_P_8021Q | mii_bus_data->vlan1_mask;
-	lp->vlan2_mask = ETH_P_8021Q | mii_bus_data->vlan2_mask;
-
-	/* Fill in the fields of the device structure with ethernet values. */
-	ether_setup(ndev);
-
-	ndev->netdev_ops = &bfin_mac_netdev_ops;
-	ndev->ethtool_ops = &bfin_mac_ethtool_ops;
-
-	init_timer(&lp->tx_reclaim_timer);
-	lp->tx_reclaim_timer.data = (unsigned long)lp;
-	lp->tx_reclaim_timer.function = tx_reclaim_skb_timeout;
-
-	spin_lock_init(&lp->lock);
-
-	/* now, enable interrupts */
-	/* register irq handler */
-	rc = request_irq(IRQ_MAC_RX, bfin_mac_interrupt,
-			IRQF_DISABLED, "EMAC_RX", ndev);
-	if (rc) {
-		dev_err(&pdev->dev, "Cannot request Blackfin MAC RX IRQ!\n");
-		rc = -EBUSY;
-		goto out_err_request_irq;
-	}
-
-	rc = register_netdev(ndev);
-	if (rc) {
-		dev_err(&pdev->dev, "Cannot register net device!\n");
-		goto out_err_reg_ndev;
-	}
-
-	bfin_mac_hwtstamp_init(ndev);
-
-	/* now, print out the card info, in a short format.. */
-	netdev_info(ndev, "%s, Version %s\n", DRV_DESC, DRV_VERSION);
-
-	return 0;
-
-out_err_reg_ndev:
-	free_irq(IRQ_MAC_RX, ndev);
-out_err_request_irq:
-out_err_mii_probe:
-	mdiobus_unregister(lp->mii_bus);
-	mdiobus_free(lp->mii_bus);
-out_err_probe_mac:
-	platform_set_drvdata(pdev, NULL);
-	free_netdev(ndev);
-
-	return rc;
-}
-
-static int __devexit bfin_mac_remove(struct platform_device *pdev)
-{
-	struct net_device *ndev = platform_get_drvdata(pdev);
-	struct bfin_mac_local *lp = netdev_priv(ndev);
-
-	platform_set_drvdata(pdev, NULL);
-
-	lp->mii_bus->priv = NULL;
-
-	unregister_netdev(ndev);
-
-	free_irq(IRQ_MAC_RX, ndev);
-
-	free_netdev(ndev);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int bfin_mac_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-	struct net_device *net_dev = platform_get_drvdata(pdev);
-	struct bfin_mac_local *lp = netdev_priv(net_dev);
-
-	if (lp->wol) {
-		bfin_write_EMAC_OPMODE((bfin_read_EMAC_OPMODE() & ~TE) | RE);
-		bfin_write_EMAC_WKUP_CTL(MPKE);
-		enable_irq_wake(IRQ_MAC_WAKEDET);
-	} else {
-		if (netif_running(net_dev))
-			bfin_mac_close(net_dev);
-	}
-
-	return 0;
-}
-
-static int bfin_mac_resume(struct platform_device *pdev)
-{
-	struct net_device *net_dev = platform_get_drvdata(pdev);
-	struct bfin_mac_local *lp = netdev_priv(net_dev);
-
-	if (lp->wol) {
-		bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE);
-		bfin_write_EMAC_WKUP_CTL(0);
-		disable_irq_wake(IRQ_MAC_WAKEDET);
-	} else {
-		if (netif_running(net_dev))
-			bfin_mac_open(net_dev);
-	}
-
-	return 0;
-}
-#else
-#define bfin_mac_suspend NULL
-#define bfin_mac_resume NULL
-#endif	/* CONFIG_PM */
-
-static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
-{
-	struct mii_bus *miibus;
-	struct bfin_mii_bus_platform_data *mii_bus_pd;
-	const unsigned short *pin_req;
-	int rc, i;
-
-	mii_bus_pd = dev_get_platdata(&pdev->dev);
-	if (!mii_bus_pd) {
-		dev_err(&pdev->dev, "No peripherals in platform data!\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * We are setting up a network card,
-	 * so set the GPIO pins to Ethernet mode
-	 */
-	pin_req = mii_bus_pd->mac_peripherals;
-	rc = peripheral_request_list(pin_req, KBUILD_MODNAME);
-	if (rc) {
-		dev_err(&pdev->dev, "Requesting peripherals failed!\n");
-		return rc;
-	}
-
-	rc = -ENOMEM;
-	miibus = mdiobus_alloc();
-	if (miibus == NULL)
-		goto out_err_alloc;
-	miibus->read = bfin_mdiobus_read;
-	miibus->write = bfin_mdiobus_write;
-	miibus->reset = bfin_mdiobus_reset;
-
-	miibus->parent = &pdev->dev;
-	miibus->name = "bfin_mii_bus";
-	miibus->phy_mask = mii_bus_pd->phy_mask;
-
-	snprintf(miibus->id, MII_BUS_ID_SIZE, "0");
-	miibus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
-	if (!miibus->irq)
-		goto out_err_irq_alloc;
-
-	for (i = rc; i < PHY_MAX_ADDR; ++i)
-		miibus->irq[i] = PHY_POLL;
-
-	rc = clamp(mii_bus_pd->phydev_number, 0, PHY_MAX_ADDR);
-	if (rc != mii_bus_pd->phydev_number)
-		dev_err(&pdev->dev, "Invalid number (%i) of phydevs\n",
-			mii_bus_pd->phydev_number);
-	for (i = 0; i < rc; ++i) {
-		unsigned short phyaddr = mii_bus_pd->phydev_data[i].addr;
-		if (phyaddr < PHY_MAX_ADDR)
-			miibus->irq[phyaddr] = mii_bus_pd->phydev_data[i].irq;
-		else
-			dev_err(&pdev->dev,
-				"Invalid PHY address %i for phydev %i\n",
-				phyaddr, i);
-	}
-
-	rc = mdiobus_register(miibus);
-	if (rc) {
-		dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
-		goto out_err_mdiobus_register;
-	}
-
-	platform_set_drvdata(pdev, miibus);
-	return 0;
-
-out_err_mdiobus_register:
-	kfree(miibus->irq);
-out_err_irq_alloc:
-	mdiobus_free(miibus);
-out_err_alloc:
-	peripheral_free_list(pin_req);
-
-	return rc;
-}
-
-static int __devexit bfin_mii_bus_remove(struct platform_device *pdev)
-{
-	struct mii_bus *miibus = platform_get_drvdata(pdev);
-	struct bfin_mii_bus_platform_data *mii_bus_pd =
-		dev_get_platdata(&pdev->dev);
-
-	platform_set_drvdata(pdev, NULL);
-	mdiobus_unregister(miibus);
-	kfree(miibus->irq);
-	mdiobus_free(miibus);
-	peripheral_free_list(mii_bus_pd->mac_peripherals);
-
-	return 0;
-}
-
-static struct platform_driver bfin_mii_bus_driver = {
-	.probe = bfin_mii_bus_probe,
-	.remove = __devexit_p(bfin_mii_bus_remove),
-	.driver = {
-		.name = "bfin_mii_bus",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static struct platform_driver bfin_mac_driver = {
-	.probe = bfin_mac_probe,
-	.remove = __devexit_p(bfin_mac_remove),
-	.resume = bfin_mac_resume,
-	.suspend = bfin_mac_suspend,
-	.driver = {
-		.name = KBUILD_MODNAME,
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init bfin_mac_init(void)
-{
-	int ret;
-	ret = platform_driver_register(&bfin_mii_bus_driver);
-	if (!ret)
-		return platform_driver_register(&bfin_mac_driver);
-	return -ENODEV;
-}
-
-module_init(bfin_mac_init);
-
-static void __exit bfin_mac_cleanup(void)
-{
-	platform_driver_unregister(&bfin_mac_driver);
-	platform_driver_unregister(&bfin_mii_bus_driver);
-}
-
-module_exit(bfin_mac_cleanup);
-
diff -druN linux-libre-3.1-gnu/drivers/net/bfin_mac.h linux-libre-3.2-gnu/drivers/net/bfin_mac.h
--- linux-libre-3.1-gnu/drivers/net/bfin_mac.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bfin_mac.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,106 +0,0 @@
-/*
- * Blackfin On-Chip MAC Driver
- *
- * Copyright 2004-2007 Analog Devices Inc.
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Licensed under the GPL-2 or later.
- */
-#ifndef _BFIN_MAC_H_
-#define _BFIN_MAC_H_
-
-#include <linux/net_tstamp.h>
-#include <linux/clocksource.h>
-#include <linux/timecompare.h>
-#include <linux/timer.h>
-#include <linux/etherdevice.h>
-#include <linux/bfin_mac.h>
-
-/*
- * Disable hardware checksum for bug #5600 if writeback cache is
- * enabled. Otherwize, corrupted RX packet will be sent up stack
- * without error mark.
- */
-#ifndef CONFIG_BFIN_EXTMEM_WRITEBACK
-#define BFIN_MAC_CSUM_OFFLOAD
-#endif
-
-#define TX_RECLAIM_JIFFIES (HZ / 5)
-
-struct dma_descriptor {
-	struct dma_descriptor *next_dma_desc;
-	unsigned long start_addr;
-	unsigned short config;
-	unsigned short x_count;
-};
-
-struct status_area_rx {
-#if defined(BFIN_MAC_CSUM_OFFLOAD)
-	unsigned short ip_hdr_csum;	/* ip header checksum */
-	/* ip payload(udp or tcp or others) checksum */
-	unsigned short ip_payload_csum;
-#endif
-	unsigned long status_word;	/* the frame status word */
-};
-
-struct status_area_tx {
-	unsigned long status_word;	/* the frame status word */
-};
-
-/* use two descriptors for a packet */
-struct net_dma_desc_rx {
-	struct net_dma_desc_rx *next;
-	struct sk_buff *skb;
-	struct dma_descriptor desc_a;
-	struct dma_descriptor desc_b;
-	struct status_area_rx status;
-};
-
-/* use two descriptors for a packet */
-struct net_dma_desc_tx {
-	struct net_dma_desc_tx *next;
-	struct sk_buff *skb;
-	struct dma_descriptor desc_a;
-	struct dma_descriptor desc_b;
-	unsigned char packet[1560];
-	struct status_area_tx status;
-};
-
-struct bfin_mac_local {
-	/*
-	 * these are things that the kernel wants me to keep, so users
-	 * can find out semi-useless statistics of how well the card is
-	 * performing
-	 */
-	struct net_device_stats stats;
-
-	spinlock_t lock;
-
-	int wol;		/* Wake On Lan */
-	int irq_wake_requested;
-	struct timer_list tx_reclaim_timer;
-	struct net_device *ndev;
-
-	/* Data for EMAC_VLAN1 regs */
-	u16 vlan1_mask, vlan2_mask;
-
-	/* MII and PHY stuffs */
-	int old_link;          /* used by bf537_adjust_link */
-	int old_speed;
-	int old_duplex;
-
-	struct phy_device *phydev;
-	struct mii_bus *mii_bus;
-
-#if defined(CONFIG_BFIN_MAC_USE_HWSTAMP)
-	struct cyclecounter cycles;
-	struct timecounter clock;
-	struct timecompare compare;
-	struct hwtstamp_config stamp_cfg;
-#endif
-};
-
-extern void bfin_get_ether_addr(char *addr);
-
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/bmac.c linux-libre-3.2-gnu/drivers/net/bmac.c
--- linux-libre-3.1-gnu/drivers/net/bmac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bmac.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1685 +0,0 @@
-/*
- * Network device driver for the BMAC ethernet controller on
- * Apple Powermacs.  Assumes it's under a DBDMA controller.
- *
- * Copyright (C) 1998 Randy Gobbel.
- *
- * May 1999, Al Viro: proper release of /proc/net/bmac entry, switched to
- * dynamic procfs inode.
- */
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/crc32.h>
-#include <linux/bitrev.h>
-#include <linux/ethtool.h>
-#include <linux/slab.h>
-#include <asm/prom.h>
-#include <asm/dbdma.h>
-#include <asm/io.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/macio.h>
-#include <asm/irq.h>
-
-#include "bmac.h"
-
-#define trunc_page(x)	((void *)(((unsigned long)(x)) & ~((unsigned long)(PAGE_SIZE - 1))))
-#define round_page(x)	trunc_page(((unsigned long)(x)) + ((unsigned long)(PAGE_SIZE - 1)))
-
-/*
- * CRC polynomial - used in working out multicast filter bits.
- */
-#define ENET_CRCPOLY 0x04c11db7
-
-/* switch to use multicast code lifted from sunhme driver */
-#define SUNHME_MULTICAST
-
-#define N_RX_RING	64
-#define N_TX_RING	32
-#define MAX_TX_ACTIVE	1
-#define ETHERCRC	4
-#define ETHERMINPACKET	64
-#define ETHERMTU	1500
-#define RX_BUFLEN	(ETHERMTU + 14 + ETHERCRC + 2)
-#define TX_TIMEOUT	HZ	/* 1 second */
-
-/* Bits in transmit DMA status */
-#define TX_DMA_ERR	0x80
-
-#define XXDEBUG(args)
-
-struct bmac_data {
-	/* volatile struct bmac *bmac; */
-	struct sk_buff_head *queue;
-	volatile struct dbdma_regs __iomem *tx_dma;
-	int tx_dma_intr;
-	volatile struct dbdma_regs __iomem *rx_dma;
-	int rx_dma_intr;
-	volatile struct dbdma_cmd *tx_cmds;	/* xmit dma command list */
-	volatile struct dbdma_cmd *rx_cmds;	/* recv dma command list */
-	struct macio_dev *mdev;
-	int is_bmac_plus;
-	struct sk_buff *rx_bufs[N_RX_RING];
-	int rx_fill;
-	int rx_empty;
-	struct sk_buff *tx_bufs[N_TX_RING];
-	int tx_fill;
-	int tx_empty;
-	unsigned char tx_fullup;
-	struct timer_list tx_timeout;
-	int timeout_active;
-	int sleeping;
-	int opened;
-	unsigned short hash_use_count[64];
-	unsigned short hash_table_mask[4];
-	spinlock_t lock;
-};
-
-#if 0 /* Move that to ethtool */
-
-typedef struct bmac_reg_entry {
-	char *name;
-	unsigned short reg_offset;
-} bmac_reg_entry_t;
-
-#define N_REG_ENTRIES 31
-
-static bmac_reg_entry_t reg_entries[N_REG_ENTRIES] = {
-	{"MEMADD", MEMADD},
-	{"MEMDATAHI", MEMDATAHI},
-	{"MEMDATALO", MEMDATALO},
-	{"TXPNTR", TXPNTR},
-	{"RXPNTR", RXPNTR},
-	{"IPG1", IPG1},
-	{"IPG2", IPG2},
-	{"ALIMIT", ALIMIT},
-	{"SLOT", SLOT},
-	{"PALEN", PALEN},
-	{"PAPAT", PAPAT},
-	{"TXSFD", TXSFD},
-	{"JAM", JAM},
-	{"TXCFG", TXCFG},
-	{"TXMAX", TXMAX},
-	{"TXMIN", TXMIN},
-	{"PAREG", PAREG},
-	{"DCNT", DCNT},
-	{"NCCNT", NCCNT},
-	{"NTCNT", NTCNT},
-	{"EXCNT", EXCNT},
-	{"LTCNT", LTCNT},
-	{"TXSM", TXSM},
-	{"RXCFG", RXCFG},
-	{"RXMAX", RXMAX},
-	{"RXMIN", RXMIN},
-	{"FRCNT", FRCNT},
-	{"AECNT", AECNT},
-	{"FECNT", FECNT},
-	{"RXSM", RXSM},
-	{"RXCV", RXCV}
-};
-
-#endif
-
-static unsigned char *bmac_emergency_rxbuf;
-
-/*
- * Number of bytes of private data per BMAC: allow enough for
- * the rx and tx dma commands plus a branch dma command each,
- * and another 16 bytes to allow us to align the dma command
- * buffers on a 16 byte boundary.
- */
-#define PRIV_BYTES	(sizeof(struct bmac_data) \
-	+ (N_RX_RING + N_TX_RING + 4) * sizeof(struct dbdma_cmd) \
-	+ sizeof(struct sk_buff_head))
-
-static int bmac_open(struct net_device *dev);
-static int bmac_close(struct net_device *dev);
-static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev);
-static void bmac_set_multicast(struct net_device *dev);
-static void bmac_reset_and_enable(struct net_device *dev);
-static void bmac_start_chip(struct net_device *dev);
-static void bmac_init_chip(struct net_device *dev);
-static void bmac_init_registers(struct net_device *dev);
-static void bmac_enable_and_reset_chip(struct net_device *dev);
-static int bmac_set_address(struct net_device *dev, void *addr);
-static irqreturn_t bmac_misc_intr(int irq, void *dev_id);
-static irqreturn_t bmac_txdma_intr(int irq, void *dev_id);
-static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id);
-static void bmac_set_timeout(struct net_device *dev);
-static void bmac_tx_timeout(unsigned long data);
-static int bmac_output(struct sk_buff *skb, struct net_device *dev);
-static void bmac_start(struct net_device *dev);
-
-#define	DBDMA_SET(x)	( ((x) | (x) << 16) )
-#define	DBDMA_CLEAR(x)	( (x) << 16)
-
-static inline void
-dbdma_st32(volatile __u32 __iomem *a, unsigned long x)
-{
-	__asm__ volatile( "stwbrx %0,0,%1" : : "r" (x), "r" (a) : "memory");
-}
-
-static inline unsigned long
-dbdma_ld32(volatile __u32 __iomem *a)
-{
-	__u32 swap;
-	__asm__ volatile ("lwbrx %0,0,%1" :  "=r" (swap) : "r" (a));
-	return swap;
-}
-
-static void
-dbdma_continue(volatile struct dbdma_regs __iomem *dmap)
-{
-	dbdma_st32(&dmap->control,
-		   DBDMA_SET(RUN|WAKE) | DBDMA_CLEAR(PAUSE|DEAD));
-	eieio();
-}
-
-static void
-dbdma_reset(volatile struct dbdma_regs __iomem *dmap)
-{
-	dbdma_st32(&dmap->control,
-		   DBDMA_CLEAR(ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN));
-	eieio();
-	while (dbdma_ld32(&dmap->status) & RUN)
-		eieio();
-}
-
-static void
-dbdma_setcmd(volatile struct dbdma_cmd *cp,
-	     unsigned short cmd, unsigned count, unsigned long addr,
-	     unsigned long cmd_dep)
-{
-	out_le16(&cp->command, cmd);
-	out_le16(&cp->req_count, count);
-	out_le32(&cp->phy_addr, addr);
-	out_le32(&cp->cmd_dep, cmd_dep);
-	out_le16(&cp->xfer_status, 0);
-	out_le16(&cp->res_count, 0);
-}
-
-static inline
-void bmwrite(struct net_device *dev, unsigned long reg_offset, unsigned data )
-{
-	out_le16((void __iomem *)dev->base_addr + reg_offset, data);
-}
-
-
-static inline
-unsigned short bmread(struct net_device *dev, unsigned long reg_offset )
-{
-	return in_le16((void __iomem *)dev->base_addr + reg_offset);
-}
-
-static void
-bmac_enable_and_reset_chip(struct net_device *dev)
-{
-	struct bmac_data *bp = netdev_priv(dev);
-	volatile struct dbdma_regs __iomem *rd = bp->rx_dma;
-	volatile struct dbdma_regs __iomem *td = bp->tx_dma;
-
-	if (rd)
-		dbdma_reset(rd);
-	if (td)
-		dbdma_reset(td);
-
-	pmac_call_feature(PMAC_FTR_BMAC_ENABLE, macio_get_of_node(bp->mdev), 0, 1);
-}
-
-#define MIFDELAY	udelay(10)
-
-static unsigned int
-bmac_mif_readbits(struct net_device *dev, int nb)
-{
-	unsigned int val = 0;
-
-	while (--nb >= 0) {
-		bmwrite(dev, MIFCSR, 0);
-		MIFDELAY;
-		if (bmread(dev, MIFCSR) & 8)
-			val |= 1 << nb;
-		bmwrite(dev, MIFCSR, 1);
-		MIFDELAY;
-	}
-	bmwrite(dev, MIFCSR, 0);
-	MIFDELAY;
-	bmwrite(dev, MIFCSR, 1);
-	MIFDELAY;
-	return val;
-}
-
-static void
-bmac_mif_writebits(struct net_device *dev, unsigned int val, int nb)
-{
-	int b;
-
-	while (--nb >= 0) {
-		b = (val & (1 << nb))? 6: 4;
-		bmwrite(dev, MIFCSR, b);
-		MIFDELAY;
-		bmwrite(dev, MIFCSR, b|1);
-		MIFDELAY;
-	}
-}
-
-static unsigned int
-bmac_mif_read(struct net_device *dev, unsigned int addr)
-{
-	unsigned int val;
-
-	bmwrite(dev, MIFCSR, 4);
-	MIFDELAY;
-	bmac_mif_writebits(dev, ~0U, 32);
-	bmac_mif_writebits(dev, 6, 4);
-	bmac_mif_writebits(dev, addr, 10);
-	bmwrite(dev, MIFCSR, 2);
-	MIFDELAY;
-	bmwrite(dev, MIFCSR, 1);
-	MIFDELAY;
-	val = bmac_mif_readbits(dev, 17);
-	bmwrite(dev, MIFCSR, 4);
-	MIFDELAY;
-	return val;
-}
-
-static void
-bmac_mif_write(struct net_device *dev, unsigned int addr, unsigned int val)
-{
-	bmwrite(dev, MIFCSR, 4);
-	MIFDELAY;
-	bmac_mif_writebits(dev, ~0U, 32);
-	bmac_mif_writebits(dev, 5, 4);
-	bmac_mif_writebits(dev, addr, 10);
-	bmac_mif_writebits(dev, 2, 2);
-	bmac_mif_writebits(dev, val, 16);
-	bmac_mif_writebits(dev, 3, 2);
-}
-
-static void
-bmac_init_registers(struct net_device *dev)
-{
-	struct bmac_data *bp = netdev_priv(dev);
-	volatile unsigned short regValue;
-	unsigned short *pWord16;
-	int i;
-
-	/* XXDEBUG(("bmac: enter init_registers\n")); */
-
-	bmwrite(dev, RXRST, RxResetValue);
-	bmwrite(dev, TXRST, TxResetBit);
-
-	i = 100;
-	do {
-		--i;
-		udelay(10000);
-		regValue = bmread(dev, TXRST); /* wait for reset to clear..acknowledge */
-	} while ((regValue & TxResetBit) && i > 0);
-
-	if (!bp->is_bmac_plus) {
-		regValue = bmread(dev, XCVRIF);
-		regValue |= ClkBit | SerialMode | COLActiveLow;
-		bmwrite(dev, XCVRIF, regValue);
-		udelay(10000);
-	}
-
-	bmwrite(dev, RSEED, (unsigned short)0x1968);
-
-	regValue = bmread(dev, XIFC);
-	regValue |= TxOutputEnable;
-	bmwrite(dev, XIFC, regValue);
-
-	bmread(dev, PAREG);
-
-	/* set collision counters to 0 */
-	bmwrite(dev, NCCNT, 0);
-	bmwrite(dev, NTCNT, 0);
-	bmwrite(dev, EXCNT, 0);
-	bmwrite(dev, LTCNT, 0);
-
-	/* set rx counters to 0 */
-	bmwrite(dev, FRCNT, 0);
-	bmwrite(dev, LECNT, 0);
-	bmwrite(dev, AECNT, 0);
-	bmwrite(dev, FECNT, 0);
-	bmwrite(dev, RXCV, 0);
-
-	/* set tx fifo information */
-	bmwrite(dev, TXTH, 4);	/* 4 octets before tx starts */
-
-	bmwrite(dev, TXFIFOCSR, 0);	/* first disable txFIFO */
-	bmwrite(dev, TXFIFOCSR, TxFIFOEnable );
-
-	/* set rx fifo information */
-	bmwrite(dev, RXFIFOCSR, 0);	/* first disable rxFIFO */
-	bmwrite(dev, RXFIFOCSR, RxFIFOEnable );
-
-	//bmwrite(dev, TXCFG, TxMACEnable);	       	/* TxNeverGiveUp maybe later */
-	bmread(dev, STATUS);		/* read it just to clear it */
-
-	/* zero out the chip Hash Filter registers */
-	for (i=0; i<4; i++) bp->hash_table_mask[i] = 0;
-	bmwrite(dev, BHASH3, bp->hash_table_mask[0]); 	/* bits 15 - 0 */
-	bmwrite(dev, BHASH2, bp->hash_table_mask[1]); 	/* bits 31 - 16 */
-	bmwrite(dev, BHASH1, bp->hash_table_mask[2]); 	/* bits 47 - 32 */
-	bmwrite(dev, BHASH0, bp->hash_table_mask[3]); 	/* bits 63 - 48 */
-
-	pWord16 = (unsigned short *)dev->dev_addr;
-	bmwrite(dev, MADD0, *pWord16++);
-	bmwrite(dev, MADD1, *pWord16++);
-	bmwrite(dev, MADD2, *pWord16);
-
-	bmwrite(dev, RXCFG, RxCRCNoStrip | RxHashFilterEnable | RxRejectOwnPackets);
-
-	bmwrite(dev, INTDISABLE, EnableNormal);
-}
-
-#if 0
-static void
-bmac_disable_interrupts(struct net_device *dev)
-{
-	bmwrite(dev, INTDISABLE, DisableAll);
-}
-
-static void
-bmac_enable_interrupts(struct net_device *dev)
-{
-	bmwrite(dev, INTDISABLE, EnableNormal);
-}
-#endif
-
-
-static void
-bmac_start_chip(struct net_device *dev)
-{
-	struct bmac_data *bp = netdev_priv(dev);
-	volatile struct dbdma_regs __iomem *rd = bp->rx_dma;
-	unsigned short	oldConfig;
-
-	/* enable rx dma channel */
-	dbdma_continue(rd);
-
-	oldConfig = bmread(dev, TXCFG);
-	bmwrite(dev, TXCFG, oldConfig | TxMACEnable );
-
-	/* turn on rx plus any other bits already on (promiscuous possibly) */
-	oldConfig = bmread(dev, RXCFG);
-	bmwrite(dev, RXCFG, oldConfig | RxMACEnable );
-	udelay(20000);
-}
-
-static void
-bmac_init_phy(struct net_device *dev)
-{
-	unsigned int addr;
-	struct bmac_data *bp = netdev_priv(dev);
-
-	printk(KERN_DEBUG "phy registers:");
-	for (addr = 0; addr < 32; ++addr) {
-		if ((addr & 7) == 0)
-			printk(KERN_DEBUG);
-		printk(KERN_CONT " %.4x", bmac_mif_read(dev, addr));
-	}
-	printk(KERN_CONT "\n");
-
-	if (bp->is_bmac_plus) {
-		unsigned int capable, ctrl;
-
-		ctrl = bmac_mif_read(dev, 0);
-		capable = ((bmac_mif_read(dev, 1) & 0xf800) >> 6) | 1;
-		if (bmac_mif_read(dev, 4) != capable ||
-		    (ctrl & 0x1000) == 0) {
-			bmac_mif_write(dev, 4, capable);
-			bmac_mif_write(dev, 0, 0x1200);
-		} else
-			bmac_mif_write(dev, 0, 0x1000);
-	}
-}
-
-static void bmac_init_chip(struct net_device *dev)
-{
-	bmac_init_phy(dev);
-	bmac_init_registers(dev);
-}
-
-#ifdef CONFIG_PM
-static int bmac_suspend(struct macio_dev *mdev, pm_message_t state)
-{
-	struct net_device* dev = macio_get_drvdata(mdev);
-	struct bmac_data *bp = netdev_priv(dev);
-	unsigned long flags;
-	unsigned short config;
-	int i;
-
-	netif_device_detach(dev);
-	/* prolly should wait for dma to finish & turn off the chip */
-	spin_lock_irqsave(&bp->lock, flags);
-	if (bp->timeout_active) {
-		del_timer(&bp->tx_timeout);
-		bp->timeout_active = 0;
-	}
-	disable_irq(dev->irq);
-	disable_irq(bp->tx_dma_intr);
-	disable_irq(bp->rx_dma_intr);
-	bp->sleeping = 1;
-	spin_unlock_irqrestore(&bp->lock, flags);
-	if (bp->opened) {
-		volatile struct dbdma_regs __iomem *rd = bp->rx_dma;
-		volatile struct dbdma_regs __iomem *td = bp->tx_dma;
-
-		config = bmread(dev, RXCFG);
-		bmwrite(dev, RXCFG, (config & ~RxMACEnable));
-		config = bmread(dev, TXCFG);
-       		bmwrite(dev, TXCFG, (config & ~TxMACEnable));
-		bmwrite(dev, INTDISABLE, DisableAll); /* disable all intrs */
-       		/* disable rx and tx dma */
-       		st_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE));	/* clear run bit */
-       		st_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE));	/* clear run bit */
-       		/* free some skb's */
-       		for (i=0; i<N_RX_RING; i++) {
-       			if (bp->rx_bufs[i] != NULL) {
-       				dev_kfree_skb(bp->rx_bufs[i]);
-       				bp->rx_bufs[i] = NULL;
-       			}
-       		}
-       		for (i = 0; i<N_TX_RING; i++) {
-			if (bp->tx_bufs[i] != NULL) {
-		       		dev_kfree_skb(bp->tx_bufs[i]);
-	       			bp->tx_bufs[i] = NULL;
-		       	}
-		}
-	}
-       	pmac_call_feature(PMAC_FTR_BMAC_ENABLE, macio_get_of_node(bp->mdev), 0, 0);
-	return 0;
-}
-
-static int bmac_resume(struct macio_dev *mdev)
-{
-	struct net_device* dev = macio_get_drvdata(mdev);
-	struct bmac_data *bp = netdev_priv(dev);
-
-	/* see if this is enough */
-	if (bp->opened)
-		bmac_reset_and_enable(dev);
-
-	enable_irq(dev->irq);
-       	enable_irq(bp->tx_dma_intr);
-       	enable_irq(bp->rx_dma_intr);
-       	netif_device_attach(dev);
-
-	return 0;
-}
-#endif /* CONFIG_PM */
-
-static int bmac_set_address(struct net_device *dev, void *addr)
-{
-	struct bmac_data *bp = netdev_priv(dev);
-	unsigned char *p = addr;
-	unsigned short *pWord16;
-	unsigned long flags;
-	int i;
-
-	XXDEBUG(("bmac: enter set_address\n"));
-	spin_lock_irqsave(&bp->lock, flags);
-
-	for (i = 0; i < 6; ++i) {
-		dev->dev_addr[i] = p[i];
-	}
-	/* load up the hardware address */
-	pWord16  = (unsigned short *)dev->dev_addr;
-	bmwrite(dev, MADD0, *pWord16++);
-	bmwrite(dev, MADD1, *pWord16++);
-	bmwrite(dev, MADD2, *pWord16);
-
-	spin_unlock_irqrestore(&bp->lock, flags);
-	XXDEBUG(("bmac: exit set_address\n"));
-	return 0;
-}
-
-static inline void bmac_set_timeout(struct net_device *dev)
-{
-	struct bmac_data *bp = netdev_priv(dev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&bp->lock, flags);
-	if (bp->timeout_active)
-		del_timer(&bp->tx_timeout);
-	bp->tx_timeout.expires = jiffies + TX_TIMEOUT;
-	bp->tx_timeout.function = bmac_tx_timeout;
-	bp->tx_timeout.data = (unsigned long) dev;
-	add_timer(&bp->tx_timeout);
-	bp->timeout_active = 1;
-	spin_unlock_irqrestore(&bp->lock, flags);
-}
-
-static void
-bmac_construct_xmt(struct sk_buff *skb, volatile struct dbdma_cmd *cp)
-{
-	void *vaddr;
-	unsigned long baddr;
-	unsigned long len;
-
-	len = skb->len;
-	vaddr = skb->data;
-	baddr = virt_to_bus(vaddr);
-
-	dbdma_setcmd(cp, (OUTPUT_LAST | INTR_ALWAYS | WAIT_IFCLR), len, baddr, 0);
-}
-
-static void
-bmac_construct_rxbuff(struct sk_buff *skb, volatile struct dbdma_cmd *cp)
-{
-	unsigned char *addr = skb? skb->data: bmac_emergency_rxbuf;
-
-	dbdma_setcmd(cp, (INPUT_LAST | INTR_ALWAYS), RX_BUFLEN,
-		     virt_to_bus(addr), 0);
-}
-
-static void
-bmac_init_tx_ring(struct bmac_data *bp)
-{
-	volatile struct dbdma_regs __iomem *td = bp->tx_dma;
-
-	memset((char *)bp->tx_cmds, 0, (N_TX_RING+1) * sizeof(struct dbdma_cmd));
-
-	bp->tx_empty = 0;
-	bp->tx_fill = 0;
-	bp->tx_fullup = 0;
-
-	/* put a branch at the end of the tx command list */
-	dbdma_setcmd(&bp->tx_cmds[N_TX_RING],
-		     (DBDMA_NOP | BR_ALWAYS), 0, 0, virt_to_bus(bp->tx_cmds));
-
-	/* reset tx dma */
-	dbdma_reset(td);
-	out_le32(&td->wait_sel, 0x00200020);
-	out_le32(&td->cmdptr, virt_to_bus(bp->tx_cmds));
-}
-
-static int
-bmac_init_rx_ring(struct bmac_data *bp)
-{
-	volatile struct dbdma_regs __iomem *rd = bp->rx_dma;
-	int i;
-	struct sk_buff *skb;
-
-	/* initialize list of sk_buffs for receiving and set up recv dma */
-	memset((char *)bp->rx_cmds, 0,
-	       (N_RX_RING + 1) * sizeof(struct dbdma_cmd));
-	for (i = 0; i < N_RX_RING; i++) {
-		if ((skb = bp->rx_bufs[i]) == NULL) {
-			bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2);
-			if (skb != NULL)
-				skb_reserve(skb, 2);
-		}
-		bmac_construct_rxbuff(skb, &bp->rx_cmds[i]);
-	}
-
-	bp->rx_empty = 0;
-	bp->rx_fill = i;
-
-	/* Put a branch back to the beginning of the receive command list */
-	dbdma_setcmd(&bp->rx_cmds[N_RX_RING],
-		     (DBDMA_NOP | BR_ALWAYS), 0, 0, virt_to_bus(bp->rx_cmds));
-
-	/* start rx dma */
-	dbdma_reset(rd);
-	out_le32(&rd->cmdptr, virt_to_bus(bp->rx_cmds));
-
-	return 1;
-}
-
-
-static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev)
-{
-	struct bmac_data *bp = netdev_priv(dev);
-	volatile struct dbdma_regs __iomem *td = bp->tx_dma;
-	int i;
-
-	/* see if there's a free slot in the tx ring */
-	/* XXDEBUG(("bmac_xmit_start: empty=%d fill=%d\n", */
-	/* 	     bp->tx_empty, bp->tx_fill)); */
-	i = bp->tx_fill + 1;
-	if (i >= N_TX_RING)
-		i = 0;
-	if (i == bp->tx_empty) {
-		netif_stop_queue(dev);
-		bp->tx_fullup = 1;
-		XXDEBUG(("bmac_transmit_packet: tx ring full\n"));
-		return -1;		/* can't take it at the moment */
-	}
-
-	dbdma_setcmd(&bp->tx_cmds[i], DBDMA_STOP, 0, 0, 0);
-
-	bmac_construct_xmt(skb, &bp->tx_cmds[bp->tx_fill]);
-
-	bp->tx_bufs[bp->tx_fill] = skb;
-	bp->tx_fill = i;
-
-	dev->stats.tx_bytes += skb->len;
-
-	dbdma_continue(td);
-
-	return 0;
-}
-
-static int rxintcount;
-
-static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id)
-{
-	struct net_device *dev = (struct net_device *) dev_id;
-	struct bmac_data *bp = netdev_priv(dev);
-	volatile struct dbdma_regs __iomem *rd = bp->rx_dma;
-	volatile struct dbdma_cmd *cp;
-	int i, nb, stat;
-	struct sk_buff *skb;
-	unsigned int residual;
-	int last;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bp->lock, flags);
-
-	if (++rxintcount < 10) {
-		XXDEBUG(("bmac_rxdma_intr\n"));
-	}
-
-	last = -1;
-	i = bp->rx_empty;
-
-	while (1) {
-		cp = &bp->rx_cmds[i];
-		stat = ld_le16(&cp->xfer_status);
-		residual = ld_le16(&cp->res_count);
-		if ((stat & ACTIVE) == 0)
-			break;
-		nb = RX_BUFLEN - residual - 2;
-		if (nb < (ETHERMINPACKET - ETHERCRC)) {
-			skb = NULL;
-			dev->stats.rx_length_errors++;
-			dev->stats.rx_errors++;
-		} else {
-			skb = bp->rx_bufs[i];
-			bp->rx_bufs[i] = NULL;
-		}
-		if (skb != NULL) {
-			nb -= ETHERCRC;
-			skb_put(skb, nb);
-			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
-			++dev->stats.rx_packets;
-			dev->stats.rx_bytes += nb;
-		} else {
-			++dev->stats.rx_dropped;
-		}
-		if ((skb = bp->rx_bufs[i]) == NULL) {
-			bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2);
-			if (skb != NULL)
-				skb_reserve(bp->rx_bufs[i], 2);
-		}
-		bmac_construct_rxbuff(skb, &bp->rx_cmds[i]);
-		st_le16(&cp->res_count, 0);
-		st_le16(&cp->xfer_status, 0);
-		last = i;
-		if (++i >= N_RX_RING) i = 0;
-	}
-
-	if (last != -1) {
-		bp->rx_fill = last;
-		bp->rx_empty = i;
-	}
-
-	dbdma_continue(rd);
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	if (rxintcount < 10) {
-		XXDEBUG(("bmac_rxdma_intr done\n"));
-	}
-	return IRQ_HANDLED;
-}
-
-static int txintcount;
-
-static irqreturn_t bmac_txdma_intr(int irq, void *dev_id)
-{
-	struct net_device *dev = (struct net_device *) dev_id;
-	struct bmac_data *bp = netdev_priv(dev);
-	volatile struct dbdma_cmd *cp;
-	int stat;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bp->lock, flags);
-
-	if (txintcount++ < 10) {
-		XXDEBUG(("bmac_txdma_intr\n"));
-	}
-
-	/*     del_timer(&bp->tx_timeout); */
-	/*     bp->timeout_active = 0; */
-
-	while (1) {
-		cp = &bp->tx_cmds[bp->tx_empty];
-		stat = ld_le16(&cp->xfer_status);
-		if (txintcount < 10) {
-			XXDEBUG(("bmac_txdma_xfer_stat=%#0x\n", stat));
-		}
-		if (!(stat & ACTIVE)) {
-			/*
-			 * status field might not have been filled by DBDMA
-			 */
-			if (cp == bus_to_virt(in_le32(&bp->tx_dma->cmdptr)))
-				break;
-		}
-
-		if (bp->tx_bufs[bp->tx_empty]) {
-			++dev->stats.tx_packets;
-			dev_kfree_skb_irq(bp->tx_bufs[bp->tx_empty]);
-		}
-		bp->tx_bufs[bp->tx_empty] = NULL;
-		bp->tx_fullup = 0;
-		netif_wake_queue(dev);
-		if (++bp->tx_empty >= N_TX_RING)
-			bp->tx_empty = 0;
-		if (bp->tx_empty == bp->tx_fill)
-			break;
-	}
-
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	if (txintcount < 10) {
-		XXDEBUG(("bmac_txdma_intr done->bmac_start\n"));
-	}
-
-	bmac_start(dev);
-	return IRQ_HANDLED;
-}
-
-#ifndef SUNHME_MULTICAST
-/* Real fast bit-reversal algorithm, 6-bit values */
-static int reverse6[64] = {
-	0x0,0x20,0x10,0x30,0x8,0x28,0x18,0x38,
-	0x4,0x24,0x14,0x34,0xc,0x2c,0x1c,0x3c,
-	0x2,0x22,0x12,0x32,0xa,0x2a,0x1a,0x3a,
-	0x6,0x26,0x16,0x36,0xe,0x2e,0x1e,0x3e,
-	0x1,0x21,0x11,0x31,0x9,0x29,0x19,0x39,
-	0x5,0x25,0x15,0x35,0xd,0x2d,0x1d,0x3d,
-	0x3,0x23,0x13,0x33,0xb,0x2b,0x1b,0x3b,
-	0x7,0x27,0x17,0x37,0xf,0x2f,0x1f,0x3f
-};
-
-static unsigned int
-crc416(unsigned int curval, unsigned short nxtval)
-{
-	register unsigned int counter, cur = curval, next = nxtval;
-	register int high_crc_set, low_data_set;
-
-	/* Swap bytes */
-	next = ((next & 0x00FF) << 8) | (next >> 8);
-
-	/* Compute bit-by-bit */
-	for (counter = 0; counter < 16; ++counter) {
-		/* is high CRC bit set? */
-		if ((cur & 0x80000000) == 0) high_crc_set = 0;
-		else high_crc_set = 1;
-
-		cur = cur << 1;
-
-		if ((next & 0x0001) == 0) low_data_set = 0;
-		else low_data_set = 1;
-
-		next = next >> 1;
-
-		/* do the XOR */
-		if (high_crc_set ^ low_data_set) cur = cur ^ ENET_CRCPOLY;
-	}
-	return cur;
-}
-
-static unsigned int
-bmac_crc(unsigned short *address)
-{
-	unsigned int newcrc;
-
-	XXDEBUG(("bmac_crc: addr=%#04x, %#04x, %#04x\n", *address, address[1], address[2]));
-	newcrc = crc416(0xffffffff, *address);	/* address bits 47 - 32 */
-	newcrc = crc416(newcrc, address[1]);	/* address bits 31 - 16 */
-	newcrc = crc416(newcrc, address[2]);	/* address bits 15 - 0  */
-
-	return(newcrc);
-}
-
-/*
- * Add requested mcast addr to BMac's hash table filter.
- *
- */
-
-static void
-bmac_addhash(struct bmac_data *bp, unsigned char *addr)
-{
-	unsigned int	 crc;
-	unsigned short	 mask;
-
-	if (!(*addr)) return;
-	crc = bmac_crc((unsigned short *)addr) & 0x3f; /* Big-endian alert! */
-	crc = reverse6[crc];	/* Hyperfast bit-reversing algorithm */
-	if (bp->hash_use_count[crc]++) return; /* This bit is already set */
-	mask = crc % 16;
-	mask = (unsigned char)1 << mask;
-	bp->hash_use_count[crc/16] |= mask;
-}
-
-static void
-bmac_removehash(struct bmac_data *bp, unsigned char *addr)
-{
-	unsigned int crc;
-	unsigned char mask;
-
-	/* Now, delete the address from the filter copy, as indicated */
-	crc = bmac_crc((unsigned short *)addr) & 0x3f; /* Big-endian alert! */
-	crc = reverse6[crc];	/* Hyperfast bit-reversing algorithm */
-	if (bp->hash_use_count[crc] == 0) return; /* That bit wasn't in use! */
-	if (--bp->hash_use_count[crc]) return; /* That bit is still in use */
-	mask = crc % 16;
-	mask = ((unsigned char)1 << mask) ^ 0xffff; /* To turn off bit */
-	bp->hash_table_mask[crc/16] &= mask;
-}
-
-/*
- * Sync the adapter with the software copy of the multicast mask
- *  (logical address filter).
- */
-
-static void
-bmac_rx_off(struct net_device *dev)
-{
-	unsigned short rx_cfg;
-
-	rx_cfg = bmread(dev, RXCFG);
-	rx_cfg &= ~RxMACEnable;
-	bmwrite(dev, RXCFG, rx_cfg);
-	do {
-		rx_cfg = bmread(dev, RXCFG);
-	}  while (rx_cfg & RxMACEnable);
-}
-
-unsigned short
-bmac_rx_on(struct net_device *dev, int hash_enable, int promisc_enable)
-{
-	unsigned short rx_cfg;
-
-	rx_cfg = bmread(dev, RXCFG);
-	rx_cfg |= RxMACEnable;
-	if (hash_enable) rx_cfg |= RxHashFilterEnable;
-	else rx_cfg &= ~RxHashFilterEnable;
-	if (promisc_enable) rx_cfg |= RxPromiscEnable;
-	else rx_cfg &= ~RxPromiscEnable;
-	bmwrite(dev, RXRST, RxResetValue);
-	bmwrite(dev, RXFIFOCSR, 0);	/* first disable rxFIFO */
-	bmwrite(dev, RXFIFOCSR, RxFIFOEnable );
-	bmwrite(dev, RXCFG, rx_cfg );
-	return rx_cfg;
-}
-
-static void
-bmac_update_hash_table_mask(struct net_device *dev, struct bmac_data *bp)
-{
-	bmwrite(dev, BHASH3, bp->hash_table_mask[0]); /* bits 15 - 0 */
-	bmwrite(dev, BHASH2, bp->hash_table_mask[1]); /* bits 31 - 16 */
-	bmwrite(dev, BHASH1, bp->hash_table_mask[2]); /* bits 47 - 32 */
-	bmwrite(dev, BHASH0, bp->hash_table_mask[3]); /* bits 63 - 48 */
-}
-
-#if 0
-static void
-bmac_add_multi(struct net_device *dev,
-	       struct bmac_data *bp, unsigned char *addr)
-{
-	/* XXDEBUG(("bmac: enter bmac_add_multi\n")); */
-	bmac_addhash(bp, addr);
-	bmac_rx_off(dev);
-	bmac_update_hash_table_mask(dev, bp);
-	bmac_rx_on(dev, 1, (dev->flags & IFF_PROMISC)? 1 : 0);
-	/* XXDEBUG(("bmac: exit bmac_add_multi\n")); */
-}
-
-static void
-bmac_remove_multi(struct net_device *dev,
-		  struct bmac_data *bp, unsigned char *addr)
-{
-	bmac_removehash(bp, addr);
-	bmac_rx_off(dev);
-	bmac_update_hash_table_mask(dev, bp);
-	bmac_rx_on(dev, 1, (dev->flags & IFF_PROMISC)? 1 : 0);
-}
-#endif
-
-/* Set or clear the multicast filter for this adaptor.
-    num_addrs == -1	Promiscuous mode, receive all packets
-    num_addrs == 0	Normal mode, clear multicast list
-    num_addrs > 0	Multicast mode, receive normal and MC packets, and do
-			best-effort filtering.
- */
-static void bmac_set_multicast(struct net_device *dev)
-{
-	struct netdev_hw_addr *ha;
-	struct bmac_data *bp = netdev_priv(dev);
-	int num_addrs = netdev_mc_count(dev);
-	unsigned short rx_cfg;
-	int i;
-
-	if (bp->sleeping)
-		return;
-
-	XXDEBUG(("bmac: enter bmac_set_multicast, n_addrs=%d\n", num_addrs));
-
-	if((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > 64)) {
-		for (i=0; i<4; i++) bp->hash_table_mask[i] = 0xffff;
-		bmac_update_hash_table_mask(dev, bp);
-		rx_cfg = bmac_rx_on(dev, 1, 0);
-		XXDEBUG(("bmac: all multi, rx_cfg=%#08x\n"));
-	} else if ((dev->flags & IFF_PROMISC) || (num_addrs < 0)) {
-		rx_cfg = bmread(dev, RXCFG);
-		rx_cfg |= RxPromiscEnable;
-		bmwrite(dev, RXCFG, rx_cfg);
-		rx_cfg = bmac_rx_on(dev, 0, 1);
-		XXDEBUG(("bmac: promisc mode enabled, rx_cfg=%#08x\n", rx_cfg));
-	} else {
-		for (i=0; i<4; i++) bp->hash_table_mask[i] = 0;
-		for (i=0; i<64; i++) bp->hash_use_count[i] = 0;
-		if (num_addrs == 0) {
-			rx_cfg = bmac_rx_on(dev, 0, 0);
-			XXDEBUG(("bmac: multi disabled, rx_cfg=%#08x\n", rx_cfg));
-		} else {
-			netdev_for_each_mc_addr(ha, dev)
-				bmac_addhash(bp, ha->addr);
-			bmac_update_hash_table_mask(dev, bp);
-			rx_cfg = bmac_rx_on(dev, 1, 0);
-			XXDEBUG(("bmac: multi enabled, rx_cfg=%#08x\n", rx_cfg));
-		}
-	}
-	/* XXDEBUG(("bmac: exit bmac_set_multicast\n")); */
-}
-#else /* ifdef SUNHME_MULTICAST */
-
-/* The version of set_multicast below was lifted from sunhme.c */
-
-static void bmac_set_multicast(struct net_device *dev)
-{
-	struct netdev_hw_addr *ha;
-	int i;
-	unsigned short rx_cfg;
-	u32 crc;
-
-	if((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > 64)) {
-		bmwrite(dev, BHASH0, 0xffff);
-		bmwrite(dev, BHASH1, 0xffff);
-		bmwrite(dev, BHASH2, 0xffff);
-		bmwrite(dev, BHASH3, 0xffff);
-	} else if(dev->flags & IFF_PROMISC) {
-		rx_cfg = bmread(dev, RXCFG);
-		rx_cfg |= RxPromiscEnable;
-		bmwrite(dev, RXCFG, rx_cfg);
-	} else {
-		u16 hash_table[4];
-
-		rx_cfg = bmread(dev, RXCFG);
-		rx_cfg &= ~RxPromiscEnable;
-		bmwrite(dev, RXCFG, rx_cfg);
-
-		for(i = 0; i < 4; i++) hash_table[i] = 0;
-
-		netdev_for_each_mc_addr(ha, dev) {
-			crc = ether_crc_le(6, ha->addr);
-			crc >>= 26;
-			hash_table[crc >> 4] |= 1 << (crc & 0xf);
-		}
-		bmwrite(dev, BHASH0, hash_table[0]);
-		bmwrite(dev, BHASH1, hash_table[1]);
-		bmwrite(dev, BHASH2, hash_table[2]);
-		bmwrite(dev, BHASH3, hash_table[3]);
-	}
-}
-#endif /* SUNHME_MULTICAST */
-
-static int miscintcount;
-
-static irqreturn_t bmac_misc_intr(int irq, void *dev_id)
-{
-	struct net_device *dev = (struct net_device *) dev_id;
-	unsigned int status = bmread(dev, STATUS);
-	if (miscintcount++ < 10) {
-		XXDEBUG(("bmac_misc_intr\n"));
-	}
-	/* XXDEBUG(("bmac_misc_intr, status=%#08x\n", status)); */
-	/*     bmac_txdma_intr_inner(irq, dev_id); */
-	/*   if (status & FrameReceived) dev->stats.rx_dropped++; */
-	if (status & RxErrorMask) dev->stats.rx_errors++;
-	if (status & RxCRCCntExp) dev->stats.rx_crc_errors++;
-	if (status & RxLenCntExp) dev->stats.rx_length_errors++;
-	if (status & RxOverFlow) dev->stats.rx_over_errors++;
-	if (status & RxAlignCntExp) dev->stats.rx_frame_errors++;
-
-	/*   if (status & FrameSent) dev->stats.tx_dropped++; */
-	if (status & TxErrorMask) dev->stats.tx_errors++;
-	if (status & TxUnderrun) dev->stats.tx_fifo_errors++;
-	if (status & TxNormalCollExp) dev->stats.collisions++;
-	return IRQ_HANDLED;
-}
-
-/*
- * Procedure for reading EEPROM
- */
-#define SROMAddressLength	5
-#define DataInOn		0x0008
-#define DataInOff		0x0000
-#define Clk			0x0002
-#define ChipSelect		0x0001
-#define SDIShiftCount		3
-#define SD0ShiftCount		2
-#define	DelayValue		1000	/* number of microseconds */
-#define SROMStartOffset		10	/* this is in words */
-#define SROMReadCount		3	/* number of words to read from SROM */
-#define SROMAddressBits		6
-#define EnetAddressOffset	20
-
-static unsigned char
-bmac_clock_out_bit(struct net_device *dev)
-{
-	unsigned short         data;
-	unsigned short         val;
-
-	bmwrite(dev, SROMCSR, ChipSelect | Clk);
-	udelay(DelayValue);
-
-	data = bmread(dev, SROMCSR);
-	udelay(DelayValue);
-	val = (data >> SD0ShiftCount) & 1;
-
-	bmwrite(dev, SROMCSR, ChipSelect);
-	udelay(DelayValue);
-
-	return val;
-}
-
-static void
-bmac_clock_in_bit(struct net_device *dev, unsigned int val)
-{
-	unsigned short data;
-
-	if (val != 0 && val != 1) return;
-
-	data = (val << SDIShiftCount);
-	bmwrite(dev, SROMCSR, data | ChipSelect  );
-	udelay(DelayValue);
-
-	bmwrite(dev, SROMCSR, data | ChipSelect | Clk );
-	udelay(DelayValue);
-
-	bmwrite(dev, SROMCSR, data | ChipSelect);
-	udelay(DelayValue);
-}
-
-static void
-reset_and_select_srom(struct net_device *dev)
-{
-	/* first reset */
-	bmwrite(dev, SROMCSR, 0);
-	udelay(DelayValue);
-
-	/* send it the read command (110) */
-	bmac_clock_in_bit(dev, 1);
-	bmac_clock_in_bit(dev, 1);
-	bmac_clock_in_bit(dev, 0);
-}
-
-static unsigned short
-read_srom(struct net_device *dev, unsigned int addr, unsigned int addr_len)
-{
-	unsigned short data, val;
-	int i;
-
-	/* send out the address we want to read from */
-	for (i = 0; i < addr_len; i++)	{
-		val = addr >> (addr_len-i-1);
-		bmac_clock_in_bit(dev, val & 1);
-	}
-
-	/* Now read in the 16-bit data */
-	data = 0;
-	for (i = 0; i < 16; i++)	{
-		val = bmac_clock_out_bit(dev);
-		data <<= 1;
-		data |= val;
-	}
-	bmwrite(dev, SROMCSR, 0);
-
-	return data;
-}
-
-/*
- * It looks like Cogent and SMC use different methods for calculating
- * checksums. What a pain..
- */
-
-static int
-bmac_verify_checksum(struct net_device *dev)
-{
-	unsigned short data, storedCS;
-
-	reset_and_select_srom(dev);
-	data = read_srom(dev, 3, SROMAddressBits);
-	storedCS = ((data >> 8) & 0x0ff) | ((data << 8) & 0xff00);
-
-	return 0;
-}
-
-
-static void
-bmac_get_station_address(struct net_device *dev, unsigned char *ea)
-{
-	int i;
-	unsigned short data;
-
-	for (i = 0; i < 6; i++)
-		{
-			reset_and_select_srom(dev);
-			data = read_srom(dev, i + EnetAddressOffset/2, SROMAddressBits);
-			ea[2*i]   = bitrev8(data & 0x0ff);
-			ea[2*i+1] = bitrev8((data >> 8) & 0x0ff);
-		}
-}
-
-static void bmac_reset_and_enable(struct net_device *dev)
-{
-	struct bmac_data *bp = netdev_priv(dev);
-	unsigned long flags;
-	struct sk_buff *skb;
-	unsigned char *data;
-
-	spin_lock_irqsave(&bp->lock, flags);
-	bmac_enable_and_reset_chip(dev);
-	bmac_init_tx_ring(bp);
-	bmac_init_rx_ring(bp);
-	bmac_init_chip(dev);
-	bmac_start_chip(dev);
-	bmwrite(dev, INTDISABLE, EnableNormal);
-	bp->sleeping = 0;
-
-	/*
-	 * It seems that the bmac can't receive until it's transmitted
-	 * a packet.  So we give it a dummy packet to transmit.
-	 */
-	skb = dev_alloc_skb(ETHERMINPACKET);
-	if (skb != NULL) {
-		data = skb_put(skb, ETHERMINPACKET);
-		memset(data, 0, ETHERMINPACKET);
-		memcpy(data, dev->dev_addr, 6);
-		memcpy(data+6, dev->dev_addr, 6);
-		bmac_transmit_packet(skb, dev);
-	}
-	spin_unlock_irqrestore(&bp->lock, flags);
-}
-
-static const struct ethtool_ops bmac_ethtool_ops = {
-	.get_link		= ethtool_op_get_link,
-};
-
-static const struct net_device_ops bmac_netdev_ops = {
-	.ndo_open		= bmac_open,
-	.ndo_stop		= bmac_close,
-	.ndo_start_xmit		= bmac_output,
-	.ndo_set_multicast_list	= bmac_set_multicast,
-	.ndo_set_mac_address	= bmac_set_address,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_id *match)
-{
-	int j, rev, ret;
-	struct bmac_data *bp;
-	const unsigned char *prop_addr;
-	unsigned char addr[6];
-	struct net_device *dev;
-	int is_bmac_plus = ((int)match->data) != 0;
-
-	if (macio_resource_count(mdev) != 3 || macio_irq_count(mdev) != 3) {
-		printk(KERN_ERR "BMAC: can't use, need 3 addrs and 3 intrs\n");
-		return -ENODEV;
-	}
-	prop_addr = of_get_property(macio_get_of_node(mdev),
-			"mac-address", NULL);
-	if (prop_addr == NULL) {
-		prop_addr = of_get_property(macio_get_of_node(mdev),
-				"local-mac-address", NULL);
-		if (prop_addr == NULL) {
-			printk(KERN_ERR "BMAC: Can't get mac-address\n");
-			return -ENODEV;
-		}
-	}
-	memcpy(addr, prop_addr, sizeof(addr));
-
-	dev = alloc_etherdev(PRIV_BYTES);
-	if (!dev) {
-		printk(KERN_ERR "BMAC: alloc_etherdev failed, out of memory\n");
-		return -ENOMEM;
-	}
-
-	bp = netdev_priv(dev);
-	SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
-	macio_set_drvdata(mdev, dev);
-
-	bp->mdev = mdev;
-	spin_lock_init(&bp->lock);
-
-	if (macio_request_resources(mdev, "bmac")) {
-		printk(KERN_ERR "BMAC: can't request IO resource !\n");
-		goto out_free;
-	}
-
-	dev->base_addr = (unsigned long)
-		ioremap(macio_resource_start(mdev, 0), macio_resource_len(mdev, 0));
-	if (dev->base_addr == 0)
-		goto out_release;
-
-	dev->irq = macio_irq(mdev, 0);
-
-	bmac_enable_and_reset_chip(dev);
-	bmwrite(dev, INTDISABLE, DisableAll);
-
-	rev = addr[0] == 0 && addr[1] == 0xA0;
-	for (j = 0; j < 6; ++j)
-		dev->dev_addr[j] = rev ? bitrev8(addr[j]): addr[j];
-
-	/* Enable chip without interrupts for now */
-	bmac_enable_and_reset_chip(dev);
-	bmwrite(dev, INTDISABLE, DisableAll);
-
-	dev->netdev_ops = &bmac_netdev_ops;
-	dev->ethtool_ops = &bmac_ethtool_ops;
-
-	bmac_get_station_address(dev, addr);
-	if (bmac_verify_checksum(dev) != 0)
-		goto err_out_iounmap;
-
-	bp->is_bmac_plus = is_bmac_plus;
-	bp->tx_dma = ioremap(macio_resource_start(mdev, 1), macio_resource_len(mdev, 1));
-	if (!bp->tx_dma)
-		goto err_out_iounmap;
-	bp->tx_dma_intr = macio_irq(mdev, 1);
-	bp->rx_dma = ioremap(macio_resource_start(mdev, 2), macio_resource_len(mdev, 2));
-	if (!bp->rx_dma)
-		goto err_out_iounmap_tx;
-	bp->rx_dma_intr = macio_irq(mdev, 2);
-
-	bp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(bp + 1);
-	bp->rx_cmds = bp->tx_cmds + N_TX_RING + 1;
-
-	bp->queue = (struct sk_buff_head *)(bp->rx_cmds + N_RX_RING + 1);
-	skb_queue_head_init(bp->queue);
-
-	init_timer(&bp->tx_timeout);
-
-	ret = request_irq(dev->irq, bmac_misc_intr, 0, "BMAC-misc", dev);
-	if (ret) {
-		printk(KERN_ERR "BMAC: can't get irq %d\n", dev->irq);
-		goto err_out_iounmap_rx;
-	}
-	ret = request_irq(bp->tx_dma_intr, bmac_txdma_intr, 0, "BMAC-txdma", dev);
-	if (ret) {
-		printk(KERN_ERR "BMAC: can't get irq %d\n", bp->tx_dma_intr);
-		goto err_out_irq0;
-	}
-	ret = request_irq(bp->rx_dma_intr, bmac_rxdma_intr, 0, "BMAC-rxdma", dev);
-	if (ret) {
-		printk(KERN_ERR "BMAC: can't get irq %d\n", bp->rx_dma_intr);
-		goto err_out_irq1;
-	}
-
-	/* Mask chip interrupts and disable chip, will be
-	 * re-enabled on open()
-	 */
-	disable_irq(dev->irq);
-	pmac_call_feature(PMAC_FTR_BMAC_ENABLE, macio_get_of_node(bp->mdev), 0, 0);
-
-	if (register_netdev(dev) != 0) {
-		printk(KERN_ERR "BMAC: Ethernet registration failed\n");
-		goto err_out_irq2;
-	}
-
-	printk(KERN_INFO "%s: BMAC%s at %pM",
-	       dev->name, (is_bmac_plus ? "+" : ""), dev->dev_addr);
-	XXDEBUG((", base_addr=%#0lx", dev->base_addr));
-	printk("\n");
-
-	return 0;
-
-err_out_irq2:
-	free_irq(bp->rx_dma_intr, dev);
-err_out_irq1:
-	free_irq(bp->tx_dma_intr, dev);
-err_out_irq0:
-	free_irq(dev->irq, dev);
-err_out_iounmap_rx:
-	iounmap(bp->rx_dma);
-err_out_iounmap_tx:
-	iounmap(bp->tx_dma);
-err_out_iounmap:
-	iounmap((void __iomem *)dev->base_addr);
-out_release:
-	macio_release_resources(mdev);
-out_free:
-	pmac_call_feature(PMAC_FTR_BMAC_ENABLE, macio_get_of_node(bp->mdev), 0, 0);
-	free_netdev(dev);
-
-	return -ENODEV;
-}
-
-static int bmac_open(struct net_device *dev)
-{
-	struct bmac_data *bp = netdev_priv(dev);
-	/* XXDEBUG(("bmac: enter open\n")); */
-	/* reset the chip */
-	bp->opened = 1;
-	bmac_reset_and_enable(dev);
-	enable_irq(dev->irq);
-	return 0;
-}
-
-static int bmac_close(struct net_device *dev)
-{
-	struct bmac_data *bp = netdev_priv(dev);
-	volatile struct dbdma_regs __iomem *rd = bp->rx_dma;
-	volatile struct dbdma_regs __iomem *td = bp->tx_dma;
-	unsigned short config;
-	int i;
-
-	bp->sleeping = 1;
-
-	/* disable rx and tx */
-	config = bmread(dev, RXCFG);
-	bmwrite(dev, RXCFG, (config & ~RxMACEnable));
-
-	config = bmread(dev, TXCFG);
-	bmwrite(dev, TXCFG, (config & ~TxMACEnable));
-
-	bmwrite(dev, INTDISABLE, DisableAll); /* disable all intrs */
-
-	/* disable rx and tx dma */
-	st_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE));	/* clear run bit */
-	st_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE));	/* clear run bit */
-
-	/* free some skb's */
-	XXDEBUG(("bmac: free rx bufs\n"));
-	for (i=0; i<N_RX_RING; i++) {
-		if (bp->rx_bufs[i] != NULL) {
-			dev_kfree_skb(bp->rx_bufs[i]);
-			bp->rx_bufs[i] = NULL;
-		}
-	}
-	XXDEBUG(("bmac: free tx bufs\n"));
-	for (i = 0; i<N_TX_RING; i++) {
-		if (bp->tx_bufs[i] != NULL) {
-			dev_kfree_skb(bp->tx_bufs[i]);
-			bp->tx_bufs[i] = NULL;
-		}
-	}
-	XXDEBUG(("bmac: all bufs freed\n"));
-
-	bp->opened = 0;
-	disable_irq(dev->irq);
-	pmac_call_feature(PMAC_FTR_BMAC_ENABLE, macio_get_of_node(bp->mdev), 0, 0);
-
-	return 0;
-}
-
-static void
-bmac_start(struct net_device *dev)
-{
-	struct bmac_data *bp = netdev_priv(dev);
-	int i;
-	struct sk_buff *skb;
-	unsigned long flags;
-
-	if (bp->sleeping)
-		return;
-
-	spin_lock_irqsave(&bp->lock, flags);
-	while (1) {
-		i = bp->tx_fill + 1;
-		if (i >= N_TX_RING)
-			i = 0;
-		if (i == bp->tx_empty)
-			break;
-		skb = skb_dequeue(bp->queue);
-		if (skb == NULL)
-			break;
-		bmac_transmit_packet(skb, dev);
-	}
-	spin_unlock_irqrestore(&bp->lock, flags);
-}
-
-static int
-bmac_output(struct sk_buff *skb, struct net_device *dev)
-{
-	struct bmac_data *bp = netdev_priv(dev);
-	skb_queue_tail(bp->queue, skb);
-	bmac_start(dev);
-	return NETDEV_TX_OK;
-}
-
-static void bmac_tx_timeout(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *) data;
-	struct bmac_data *bp = netdev_priv(dev);
-	volatile struct dbdma_regs __iomem *td = bp->tx_dma;
-	volatile struct dbdma_regs __iomem *rd = bp->rx_dma;
-	volatile struct dbdma_cmd *cp;
-	unsigned long flags;
-	unsigned short config, oldConfig;
-	int i;
-
-	XXDEBUG(("bmac: tx_timeout called\n"));
-	spin_lock_irqsave(&bp->lock, flags);
-	bp->timeout_active = 0;
-
-	/* update various counters */
-/*     	bmac_handle_misc_intrs(bp, 0); */
-
-	cp = &bp->tx_cmds[bp->tx_empty];
-/*	XXDEBUG((KERN_DEBUG "bmac: tx dmastat=%x %x runt=%d pr=%x fs=%x fc=%x\n", */
-/* 	   ld_le32(&td->status), ld_le16(&cp->xfer_status), bp->tx_bad_runt, */
-/* 	   mb->pr, mb->xmtfs, mb->fifofc)); */
-
-	/* turn off both tx and rx and reset the chip */
-	config = bmread(dev, RXCFG);
-	bmwrite(dev, RXCFG, (config & ~RxMACEnable));
-	config = bmread(dev, TXCFG);
-	bmwrite(dev, TXCFG, (config & ~TxMACEnable));
-	out_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE|ACTIVE|DEAD));
-	printk(KERN_ERR "bmac: transmit timeout - resetting\n");
-	bmac_enable_and_reset_chip(dev);
-
-	/* restart rx dma */
-	cp = bus_to_virt(ld_le32(&rd->cmdptr));
-	out_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE|ACTIVE|DEAD));
-	out_le16(&cp->xfer_status, 0);
-	out_le32(&rd->cmdptr, virt_to_bus(cp));
-	out_le32(&rd->control, DBDMA_SET(RUN|WAKE));
-
-	/* fix up the transmit side */
-	XXDEBUG((KERN_DEBUG "bmac: tx empty=%d fill=%d fullup=%d\n",
-		 bp->tx_empty, bp->tx_fill, bp->tx_fullup));
-	i = bp->tx_empty;
-	++dev->stats.tx_errors;
-	if (i != bp->tx_fill) {
-		dev_kfree_skb(bp->tx_bufs[i]);
-		bp->tx_bufs[i] = NULL;
-		if (++i >= N_TX_RING) i = 0;
-		bp->tx_empty = i;
-	}
-	bp->tx_fullup = 0;
-	netif_wake_queue(dev);
-	if (i != bp->tx_fill) {
-		cp = &bp->tx_cmds[i];
-		out_le16(&cp->xfer_status, 0);
-		out_le16(&cp->command, OUTPUT_LAST);
-		out_le32(&td->cmdptr, virt_to_bus(cp));
-		out_le32(&td->control, DBDMA_SET(RUN));
-		/* 	bmac_set_timeout(dev); */
-		XXDEBUG((KERN_DEBUG "bmac: starting %d\n", i));
-	}
-
-	/* turn it back on */
-	oldConfig = bmread(dev, RXCFG);
-	bmwrite(dev, RXCFG, oldConfig | RxMACEnable );
-	oldConfig = bmread(dev, TXCFG);
-	bmwrite(dev, TXCFG, oldConfig | TxMACEnable );
-
-	spin_unlock_irqrestore(&bp->lock, flags);
-}
-
-#if 0
-static void dump_dbdma(volatile struct dbdma_cmd *cp,int count)
-{
-	int i,*ip;
-
-	for (i=0;i< count;i++) {
-		ip = (int*)(cp+i);
-
-		printk("dbdma req 0x%x addr 0x%x baddr 0x%x xfer/res 0x%x\n",
-		       ld_le32(ip+0),
-		       ld_le32(ip+1),
-		       ld_le32(ip+2),
-		       ld_le32(ip+3));
-	}
-
-}
-#endif
-
-#if 0
-static int
-bmac_proc_info(char *buffer, char **start, off_t offset, int length)
-{
-	int len = 0;
-	off_t pos   = 0;
-	off_t begin = 0;
-	int i;
-
-	if (bmac_devs == NULL)
-		return -ENOSYS;
-
-	len += sprintf(buffer, "BMAC counters & registers\n");
-
-	for (i = 0; i<N_REG_ENTRIES; i++) {
-		len += sprintf(buffer + len, "%s: %#08x\n",
-			       reg_entries[i].name,
-			       bmread(bmac_devs, reg_entries[i].reg_offset));
-		pos = begin + len;
-
-		if (pos < offset) {
-			len = 0;
-			begin = pos;
-		}
-
-		if (pos > offset+length) break;
-	}
-
-	*start = buffer + (offset - begin);
-	len -= (offset - begin);
-
-	if (len > length) len = length;
-
-	return len;
-}
-#endif
-
-static int __devexit bmac_remove(struct macio_dev *mdev)
-{
-	struct net_device *dev = macio_get_drvdata(mdev);
-	struct bmac_data *bp = netdev_priv(dev);
-
-	unregister_netdev(dev);
-
-       	free_irq(dev->irq, dev);
-	free_irq(bp->tx_dma_intr, dev);
-	free_irq(bp->rx_dma_intr, dev);
-
-	iounmap((void __iomem *)dev->base_addr);
-	iounmap(bp->tx_dma);
-	iounmap(bp->rx_dma);
-
-	macio_release_resources(mdev);
-
-	free_netdev(dev);
-
-	return 0;
-}
-
-static struct of_device_id bmac_match[] =
-{
-	{
-	.name 		= "bmac",
-	.data		= (void *)0,
-	},
-	{
-	.type		= "network",
-	.compatible	= "bmac+",
-	.data		= (void *)1,
-	},
-	{},
-};
-MODULE_DEVICE_TABLE (of, bmac_match);
-
-static struct macio_driver bmac_driver =
-{
-	.driver = {
-		.name 		= "bmac",
-		.owner		= THIS_MODULE,
-		.of_match_table	= bmac_match,
-	},
-	.probe		= bmac_probe,
-	.remove		= bmac_remove,
-#ifdef CONFIG_PM
-	.suspend	= bmac_suspend,
-	.resume		= bmac_resume,
-#endif
-};
-
-
-static int __init bmac_init(void)
-{
-	if (bmac_emergency_rxbuf == NULL) {
-		bmac_emergency_rxbuf = kmalloc(RX_BUFLEN, GFP_KERNEL);
-		if (bmac_emergency_rxbuf == NULL) {
-			printk(KERN_ERR "BMAC: can't allocate emergency RX buffer\n");
-			return -ENOMEM;
-		}
-	}
-
-	return macio_register_driver(&bmac_driver);
-}
-
-static void __exit bmac_exit(void)
-{
-	macio_unregister_driver(&bmac_driver);
-
-	kfree(bmac_emergency_rxbuf);
-	bmac_emergency_rxbuf = NULL;
-}
-
-MODULE_AUTHOR("Randy Gobbel/Paul Mackerras");
-MODULE_DESCRIPTION("PowerMac BMAC ethernet driver.");
-MODULE_LICENSE("GPL");
-
-module_init(bmac_init);
-module_exit(bmac_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/bmac.h linux-libre-3.2-gnu/drivers/net/bmac.h
--- linux-libre-3.1-gnu/drivers/net/bmac.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bmac.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,164 +0,0 @@
-/*
- * mace.h - definitions for the registers in the "Big Mac"
- *  Ethernet controller found in PowerMac G3 models.
- *
- * Copyright (C) 1998 Randy Gobbel.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-/* The "Big MAC" appears to have some parts in common with the Sun "Happy Meal"
- * (HME) controller.  See sunhme.h
- */
-
-
-/* register offsets */
-
-/* global status and control */
-#define	XIFC		0x000   /* low-level interface control */
-#	define	TxOutputEnable	0x0001 /* output driver enable */
-#	define	XIFLoopback	0x0002 /* Loopback-mode XIF enable */
-#	define	MIILoopback	0x0004 /* Loopback-mode MII enable */
-#	define	MIILoopbackBits	0x0006
-#	define	MIIBuffDisable	0x0008 /* MII receive buffer disable */
-#	define	SQETestEnable	0x0010 /* SQE test enable */
-#	define	SQETimeWindow	0x03e0 /* SQE time window */
-#	define	XIFLanceMode	0x0010 /* Lance mode enable */
-#	define	XIFLanceIPG0	0x03e0 /* Lance mode IPG0 */
-#define	TXFIFOCSR	0x100   /* transmit FIFO control */
-#	define	TxFIFOEnable	0x0001
-#define	TXTH		0x110   /* transmit threshold */
-#	define	TxThreshold	0x0004
-#define RXFIFOCSR	0x120   /* receive FIFO control */
-#	define	RxFIFOEnable	0x0001
-#define MEMADD		0x130   /* memory address, unknown function */
-#define MEMDATAHI	0x140   /* memory data high, presently unused in driver */
-#define MEMDATALO	0x150   /* memory data low, presently unused in driver */
-#define XCVRIF		0x160   /* transceiver interface control */
-#	define	COLActiveLow	0x0002
-#	define	SerialMode	0x0004
-#	define	ClkBit		0x0008
-#	define	LinkStatus	0x0100
-#define CHIPID          0x170   /* chip ID */
-#define	MIFCSR		0x180   /* ??? */
-#define	SROMCSR		0x190   /* SROM control */
-#	define	ChipSelect	0x0001
-#	define	Clk		0x0002
-#define TXPNTR		0x1a0   /* transmit pointer */
-#define	RXPNTR		0x1b0   /* receive pointer */
-#define	STATUS		0x200   /* status--reading this clears it */
-#define	INTDISABLE	0x210   /* interrupt enable/disable control */
-/* bits below are the same in both STATUS and INTDISABLE registers */
-#	define	FrameReceived	0x00000001 /* Received a frame */
-#	define	RxFrameCntExp	0x00000002 /* Receive frame counter expired */
-#	define	RxAlignCntExp	0x00000004 /* Align-error counter expired */
-#	define	RxCRCCntExp	0x00000008 /* CRC-error counter expired */
-#	define	RxLenCntExp	0x00000010 /* Length-error counter expired */
-#	define	RxOverFlow	0x00000020 /* Receive FIFO overflow */
-#	define	RxCodeViolation	0x00000040 /* Code-violation counter expired */
-#	define	SQETestError	0x00000080 /* Test error in XIF for SQE */
-#	define	FrameSent	0x00000100 /* Transmitted a frame */
-#	define	TxUnderrun	0x00000200 /* Transmit FIFO underrun */
-#	define	TxMaxSizeError	0x00000400 /* Max-packet size error */
-#	define	TxNormalCollExp	0x00000800 /* Normal-collision counter expired */
-#	define	TxExcessCollExp	0x00001000 /* Excess-collision counter expired */
-#	define	TxLateCollExp	0x00002000 /* Late-collision counter expired */
-#	define	TxNetworkCollExp 0x00004000 /* First-collision counter expired */
-#	define	TxDeferTimerExp	0x00008000 /* Defer-timer expired */
-#	define	RxFIFOToHost	0x00010000 /* Data moved from FIFO to host */
-#	define	RxNoDescriptors	0x00020000 /* No more receive descriptors */
-#	define	RxDMAError	0x00040000 /* Error during receive DMA */
-#	define	RxDMALateErr	0x00080000 /* Receive DMA, data late */
-#	define	RxParityErr	0x00100000 /* Parity error during receive DMA */
-#	define	RxTagError	0x00200000 /* Tag error during receive DMA */
-#	define	TxEOPError	0x00400000 /* Tx descriptor did not have EOP set */
-#	define	MIFIntrEvent	0x00800000 /* MIF is signaling an interrupt */
-#	define	TxHostToFIFO	0x01000000 /* Data moved from host to FIFO  */
-#	define	TxFIFOAllSent	0x02000000 /* Transmitted all packets in FIFO */
-#	define	TxDMAError	0x04000000 /* Error during transmit DMA */
-#	define	TxDMALateError	0x08000000 /* Late error during transmit DMA */
-#	define	TxParityError	0x10000000 /* Parity error during transmit DMA */
-#	define	TxTagError	0x20000000 /* Tag error during transmit DMA */
-#	define	PIOError	0x40000000 /* PIO access got an error */
-#	define	PIOParityError	0x80000000 /* PIO access got a parity error  */
-#	define	DisableAll	0xffffffff
-#	define	EnableAll	0x00000000
-/* #	define	NormalIntEvents	~(FrameReceived | FrameSent | TxUnderrun) */
-#	define	EnableNormal	~(FrameReceived | FrameSent)
-#	define	EnableErrors	(FrameReceived | FrameSent)
-#	define	RxErrorMask	(RxFrameCntExp | RxAlignCntExp | RxCRCCntExp | \
-				 RxLenCntExp | RxOverFlow | RxCodeViolation)
-#	define	TxErrorMask	(TxUnderrun | TxMaxSizeError | TxExcessCollExp | \
-				 TxLateCollExp | TxNetworkCollExp | TxDeferTimerExp)
-
-/* transmit control */
-#define	TXRST		0x420   /* transmit reset */
-#	define	TxResetBit	0x0001
-#define	TXCFG		0x430   /* transmit configuration control*/
-#	define	TxMACEnable	0x0001 /* output driver enable */
-#	define	TxSlowMode	0x0020 /* enable slow mode */
-#	define	TxIgnoreColl	0x0040 /* ignore transmit collisions */
-#	define	TxNoFCS		0x0080 /* do not emit FCS */
-#	define	TxNoBackoff	0x0100 /* no backoff in case of collisions */
-#	define	TxFullDuplex	0x0200 /* enable full-duplex */
-#	define	TxNeverGiveUp	0x0400 /* don't give up on transmits */
-#define IPG1		0x440   /* Inter-packet gap 1 */
-#define IPG2		0x450   /* Inter-packet gap 2 */
-#define ALIMIT		0x460   /* Transmit attempt limit */
-#define SLOT		0x470   /* Transmit slot time */
-#define PALEN		0x480   /* Size of transmit preamble */
-#define PAPAT		0x490   /* Pattern for transmit preamble */
-#define TXSFD		0x4a0   /* Transmit frame delimiter */
-#define JAM		0x4b0   /* Jam size */
-#define TXMAX		0x4c0   /* Transmit max pkt size */
-#define TXMIN		0x4d0   /* Transmit min pkt size */
-#define PAREG		0x4e0   /* Count of transmit peak attempts */
-#define DCNT		0x4f0   /* Transmit defer timer */
-#define NCCNT		0x500   /* Transmit normal-collision counter */
-#define NTCNT		0x510   /* Transmit first-collision counter */
-#define EXCNT		0x520   /* Transmit excess-collision counter */
-#define LTCNT		0x530   /* Transmit late-collision counter */
-#define RSEED		0x540   /* Transmit random number seed */
-#define TXSM		0x550   /* Transmit state machine */
-
-/* receive control */
-#define RXRST		0x620   /* receive reset */
-#	define	RxResetValue	0x0000
-#define RXCFG		0x630   /* receive configuration control */
-#	define	RxMACEnable	0x0001 /* receiver overall enable */
-#	define	RxCFGReserved	0x0004
-#	define	RxPadStripEnab	0x0020 /* enable pad byte stripping */
-#	define	RxPromiscEnable	0x0040 /* turn on promiscuous mode */
-#	define	RxNoErrCheck	0x0080 /* disable receive error checking */
-#	define	RxCRCNoStrip	0x0100 /* disable auto-CRC-stripping */
-#	define	RxRejectOwnPackets 0x0200 /* don't receive our own packets */
-#	define	RxGrpPromisck	0x0400 /* enable group promiscuous mode */
-#	define	RxHashFilterEnable 0x0800 /* enable hash filter */
-#	define	RxAddrFilterEnable 0x1000 /* enable address filter */
-#define RXMAX		0x640   /* Max receive packet size */
-#define RXMIN		0x650   /* Min receive packet size */
-#define MADD2		0x660   /* our enet address, high part */
-#define MADD1		0x670   /* our enet address, middle part */
-#define MADD0		0x680   /* our enet address, low part */
-#define FRCNT		0x690   /* receive frame counter */
-#define LECNT		0x6a0   /* Receive excess length error counter */
-#define AECNT		0x6b0   /* Receive misaligned error counter */
-#define FECNT		0x6c0   /* Receive CRC error counter */
-#define RXSM		0x6d0   /* Receive state machine */
-#define RXCV		0x6e0   /* Receive code violation */
-
-#define BHASH3		0x700   /* multicast hash register */
-#define BHASH2		0x710   /* multicast hash register */
-#define BHASH1		0x720   /* multicast hash register */
-#define BHASH0		0x730   /* multicast hash register */
-
-#define AFR2		0x740   /* address filtering setup? */
-#define AFR1		0x750   /* address filtering setup? */
-#define AFR0		0x760   /* address filtering setup? */
-#define AFCR		0x770   /* address filter compare register? */
-#	define	EnableAllCompares 0x0fff
-
-/* bits in XIFC */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bfa_cee.c linux-libre-3.2-gnu/drivers/net/bna/bfa_cee.c
--- linux-libre-3.1-gnu/drivers/net/bna/bfa_cee.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bfa_cee.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,304 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-#include "bfa_defs_cna.h"
-#include "cna.h"
-#include "bfa_cee.h"
-#include "bfi_cna.h"
-#include "bfa_ioc.h"
-
-#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
-#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
-
-static void bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg *lldp_cfg);
-static void bfa_cee_format_cee_cfg(void *buffer);
-
-static void
-bfa_cee_format_cee_cfg(void *buffer)
-{
-	struct bfa_cee_attr *cee_cfg = buffer;
-	bfa_cee_format_lldp_cfg(&cee_cfg->lldp_remote);
-}
-
-static void
-bfa_cee_stats_swap(struct bfa_cee_stats *stats)
-{
-	u32 *buffer = (u32 *)stats;
-	int i;
-
-	for (i = 0; i < (sizeof(struct bfa_cee_stats) / sizeof(u32));
-		i++) {
-		buffer[i] = ntohl(buffer[i]);
-	}
-}
-
-static void
-bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg *lldp_cfg)
-{
-	lldp_cfg->time_to_live =
-			ntohs(lldp_cfg->time_to_live);
-	lldp_cfg->enabled_system_cap =
-			ntohs(lldp_cfg->enabled_system_cap);
-}
-
-/**
- * bfa_cee_attr_meminfo()
- *
- * @brief Returns the size of the DMA memory needed by CEE attributes
- *
- * @param[in] void
- *
- * @return Size of DMA region
- */
-static u32
-bfa_cee_attr_meminfo(void)
-{
-	return roundup(sizeof(struct bfa_cee_attr), BFA_DMA_ALIGN_SZ);
-}
-/**
- * bfa_cee_stats_meminfo()
- *
- * @brief Returns the size of the DMA memory needed by CEE stats
- *
- * @param[in] void
- *
- * @return Size of DMA region
- */
-static u32
-bfa_cee_stats_meminfo(void)
-{
-	return roundup(sizeof(struct bfa_cee_stats), BFA_DMA_ALIGN_SZ);
-}
-
-/**
- * bfa_cee_get_attr_isr()
- *
- * @brief CEE ISR for get-attributes responses from f/w
- *
- * @param[in] cee - Pointer to the CEE module
- *            status - Return status from the f/w
- *
- * @return void
- */
-static void
-bfa_cee_get_attr_isr(struct bfa_cee *cee, enum bfa_status status)
-{
-	cee->get_attr_status = status;
-	if (status == BFA_STATUS_OK) {
-		memcpy(cee->attr, cee->attr_dma.kva,
-		    sizeof(struct bfa_cee_attr));
-		bfa_cee_format_cee_cfg(cee->attr);
-	}
-	cee->get_attr_pending = false;
-	if (cee->cbfn.get_attr_cbfn)
-		cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status);
-}
-
-/**
- * bfa_cee_get_attr_isr()
- *
- * @brief CEE ISR for get-stats responses from f/w
- *
- * @param[in] cee - Pointer to the CEE module
- *            status - Return status from the f/w
- *
- * @return void
- */
-static void
-bfa_cee_get_stats_isr(struct bfa_cee *cee, enum bfa_status status)
-{
-	cee->get_stats_status = status;
-	if (status == BFA_STATUS_OK) {
-		memcpy(cee->stats, cee->stats_dma.kva,
-			sizeof(struct bfa_cee_stats));
-		bfa_cee_stats_swap(cee->stats);
-	}
-	cee->get_stats_pending = false;
-	if (cee->cbfn.get_stats_cbfn)
-		cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status);
-}
-
-/**
- * bfa_cee_get_attr_isr()
- *
- * @brief CEE ISR for reset-stats responses from f/w
- *
- * @param[in] cee - Pointer to the CEE module
- *            status - Return status from the f/w
- *
- * @return void
- */
-static void
-bfa_cee_reset_stats_isr(struct bfa_cee *cee, enum bfa_status status)
-{
-	cee->reset_stats_status = status;
-	cee->reset_stats_pending = false;
-	if (cee->cbfn.reset_stats_cbfn)
-		cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status);
-}
-/**
- * bfa_nw_cee_meminfo()
- *
- * @brief Returns the size of the DMA memory needed by CEE module
- *
- * @param[in] void
- *
- * @return Size of DMA region
- */
-u32
-bfa_nw_cee_meminfo(void)
-{
-	return bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo();
-}
-
-/**
- * bfa_nw_cee_mem_claim()
- *
- * @brief Initialized CEE DMA Memory
- *
- * @param[in] cee CEE module pointer
- *	      dma_kva Kernel Virtual Address of CEE DMA Memory
- *	      dma_pa  Physical Address of CEE DMA Memory
- *
- * @return void
- */
-void
-bfa_nw_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva, u64 dma_pa)
-{
-	cee->attr_dma.kva = dma_kva;
-	cee->attr_dma.pa = dma_pa;
-	cee->stats_dma.kva = dma_kva + bfa_cee_attr_meminfo();
-	cee->stats_dma.pa = dma_pa + bfa_cee_attr_meminfo();
-	cee->attr = (struct bfa_cee_attr *) dma_kva;
-	cee->stats = (struct bfa_cee_stats *)
-		(dma_kva + bfa_cee_attr_meminfo());
-}
-
-/**
- * bfa_cee_isrs()
- *
- * @brief Handles Mail-box interrupts for CEE module.
- *
- * @param[in] Pointer to the CEE module data structure.
- *
- * @return void
- */
-
-static void
-bfa_cee_isr(void *cbarg, struct bfi_mbmsg *m)
-{
-	union bfi_cee_i2h_msg_u *msg;
-	struct bfi_cee_get_rsp *get_rsp;
-	struct bfa_cee *cee = (struct bfa_cee *) cbarg;
-	msg = (union bfi_cee_i2h_msg_u *) m;
-	get_rsp = (struct bfi_cee_get_rsp *) m;
-	switch (msg->mh.msg_id) {
-	case BFI_CEE_I2H_GET_CFG_RSP:
-		bfa_cee_get_attr_isr(cee, get_rsp->cmd_status);
-		break;
-	case BFI_CEE_I2H_GET_STATS_RSP:
-		bfa_cee_get_stats_isr(cee, get_rsp->cmd_status);
-		break;
-	case BFI_CEE_I2H_RESET_STATS_RSP:
-		bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status);
-		break;
-	default:
-		BUG_ON(1);
-	}
-}
-
-/**
- * bfa_cee_notify()
- *
- * @brief CEE module heart-beat failure handler.
- * @brief CEE module IOC event handler.
- *
- * @param[in] IOC event type
- *
- * @return void
- */
-
-static void
-bfa_cee_notify(void *arg, enum bfa_ioc_event event)
-{
-	struct bfa_cee *cee;
-	cee = (struct bfa_cee *) arg;
-
-	switch (event) {
-	case BFA_IOC_E_DISABLED:
-	case BFA_IOC_E_FAILED:
-		if (cee->get_attr_pending == true) {
-			cee->get_attr_status = BFA_STATUS_FAILED;
-			cee->get_attr_pending  = false;
-			if (cee->cbfn.get_attr_cbfn) {
-				cee->cbfn.get_attr_cbfn(
-					cee->cbfn.get_attr_cbarg,
-					BFA_STATUS_FAILED);
-			}
-		}
-		if (cee->get_stats_pending == true) {
-			cee->get_stats_status = BFA_STATUS_FAILED;
-			cee->get_stats_pending  = false;
-			if (cee->cbfn.get_stats_cbfn) {
-				cee->cbfn.get_stats_cbfn(
-					cee->cbfn.get_stats_cbarg,
-					BFA_STATUS_FAILED);
-			}
-		}
-		if (cee->reset_stats_pending == true) {
-			cee->reset_stats_status = BFA_STATUS_FAILED;
-			cee->reset_stats_pending  = false;
-			if (cee->cbfn.reset_stats_cbfn) {
-				cee->cbfn.reset_stats_cbfn(
-					cee->cbfn.reset_stats_cbarg,
-					BFA_STATUS_FAILED);
-			}
-		}
-		break;
-
-	default:
-		break;
-	}
-}
-
-/**
- * bfa_nw_cee_attach()
- *
- * @brief CEE module-attach API
- *
- * @param[in] cee - Pointer to the CEE module data structure
- *            ioc - Pointer to the ioc module data structure
- *            dev - Pointer to the device driver module data structure
- *                  The device driver specific mbox ISR functions have
- *                  this pointer as one of the parameters.
- *
- * @return void
- */
-void
-bfa_nw_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc,
-		void *dev)
-{
-	BUG_ON(!(cee != NULL));
-	cee->dev = dev;
-	cee->ioc = ioc;
-
-	bfa_nw_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee);
-	bfa_q_qe_init(&cee->ioc_notify);
-	bfa_ioc_notify_init(&cee->ioc_notify, bfa_cee_notify, cee);
-	bfa_nw_ioc_notify_register(cee->ioc, &cee->ioc_notify);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bfa_cee.h linux-libre-3.2-gnu/drivers/net/bna/bfa_cee.h
--- linux-libre-3.1-gnu/drivers/net/bna/bfa_cee.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bfa_cee.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,63 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-#ifndef __BFA_CEE_H__
-#define __BFA_CEE_H__
-
-#include "bfa_defs_cna.h"
-#include "bfa_ioc.h"
-
-typedef void (*bfa_cee_get_attr_cbfn_t) (void *dev, enum bfa_status status);
-typedef void (*bfa_cee_get_stats_cbfn_t) (void *dev, enum bfa_status status);
-typedef void (*bfa_cee_reset_stats_cbfn_t) (void *dev, enum bfa_status status);
-
-struct bfa_cee_cbfn {
-	bfa_cee_get_attr_cbfn_t    get_attr_cbfn;
-	void *get_attr_cbarg;
-	bfa_cee_get_stats_cbfn_t   get_stats_cbfn;
-	void *get_stats_cbarg;
-	bfa_cee_reset_stats_cbfn_t reset_stats_cbfn;
-	void *reset_stats_cbarg;
-};
-
-struct bfa_cee {
-	void *dev;
-	bool get_attr_pending;
-	bool get_stats_pending;
-	bool reset_stats_pending;
-	enum bfa_status get_attr_status;
-	enum bfa_status get_stats_status;
-	enum bfa_status reset_stats_status;
-	struct bfa_cee_cbfn cbfn;
-	struct bfa_ioc_notify ioc_notify;
-	struct bfa_cee_attr *attr;
-	struct bfa_cee_stats *stats;
-	struct bfa_dma attr_dma;
-	struct bfa_dma stats_dma;
-	struct bfa_ioc *ioc;
-	struct bfa_mbox_cmd get_cfg_mb;
-	struct bfa_mbox_cmd get_stats_mb;
-	struct bfa_mbox_cmd reset_stats_mb;
-};
-
-u32 bfa_nw_cee_meminfo(void);
-void bfa_nw_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva,
-	u64 dma_pa);
-void bfa_nw_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc, void *dev);
-
-#endif /* __BFA_CEE_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bfa_cs.h linux-libre-3.2-gnu/drivers/net/bna/bfa_cs.h
--- linux-libre-3.1-gnu/drivers/net/bna/bfa_cs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bfa_cs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,140 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2011 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-/**
- * @file bfa_cs.h BFA common services
- */
-
-#ifndef __BFA_CS_H__
-#define __BFA_CS_H__
-
-#include "cna.h"
-
-/**
- * @ BFA state machine interfaces
- */
-
-typedef void (*bfa_sm_t)(void *sm, int event);
-
-/**
- * oc - object class eg. bfa_ioc
- * st - state, eg. reset
- * otype - object type, eg. struct bfa_ioc
- * etype - object type, eg. enum ioc_event
- */
-#define bfa_sm_state_decl(oc, st, otype, etype)			\
-	static void oc ## _sm_ ## st(otype * fsm, etype event)
-
-#define bfa_sm_set_state(_sm, _state)	((_sm)->sm = (bfa_sm_t)(_state))
-#define bfa_sm_send_event(_sm, _event)	((_sm)->sm((_sm), (_event)))
-#define bfa_sm_get_state(_sm)		((_sm)->sm)
-#define bfa_sm_cmp_state(_sm, _state)	((_sm)->sm == (bfa_sm_t)(_state))
-
-/**
- * For converting from state machine function to state encoding.
- */
-struct bfa_sm_table {
-	bfa_sm_t	sm;	/*!< state machine function	*/
-	int		state;	/*!< state machine encoding	*/
-	char		*name;	/*!< state name for display	*/
-};
-#define BFA_SM(_sm)		((bfa_sm_t)(_sm))
-
-/**
- * State machine with entry actions.
- */
-typedef void (*bfa_fsm_t)(void *fsm, int event);
-
-/**
- * oc - object class eg. bfa_ioc
- * st - state, eg. reset
- * otype - object type, eg. struct bfa_ioc
- * etype - object type, eg. enum ioc_event
- */
-#define bfa_fsm_state_decl(oc, st, otype, etype)			\
-	static void oc ## _sm_ ## st(otype * fsm, etype event);		\
-	static void oc ## _sm_ ## st ## _entry(otype * fsm)
-
-#define bfa_fsm_set_state(_fsm, _state) do {				\
-	(_fsm)->fsm = (bfa_fsm_t)(_state);				\
-	_state ## _entry(_fsm);						\
-} while (0)
-
-#define bfa_fsm_send_event(_fsm, _event)	((_fsm)->fsm((_fsm), (_event)))
-#define bfa_fsm_get_state(_fsm)			((_fsm)->fsm)
-#define bfa_fsm_cmp_state(_fsm, _state)					\
-	((_fsm)->fsm == (bfa_fsm_t)(_state))
-
-static inline int
-bfa_sm_to_state(const struct bfa_sm_table *smt, bfa_sm_t sm)
-{
-	int	i = 0;
-
-	while (smt[i].sm && smt[i].sm != sm)
-		i++;
-	return smt[i].state;
-}
-
-/**
- * @ Generic wait counter.
- */
-
-typedef void (*bfa_wc_resume_t) (void *cbarg);
-
-struct bfa_wc {
-	bfa_wc_resume_t wc_resume;
-	void		*wc_cbarg;
-	int		wc_count;
-};
-
-static inline void
-bfa_wc_up(struct bfa_wc *wc)
-{
-	wc->wc_count++;
-}
-
-static inline void
-bfa_wc_down(struct bfa_wc *wc)
-{
-	wc->wc_count--;
-	if (wc->wc_count == 0)
-		wc->wc_resume(wc->wc_cbarg);
-}
-
-/**
- * Initialize a waiting counter.
- */
-static inline void
-bfa_wc_init(struct bfa_wc *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
-{
-	wc->wc_resume = wc_resume;
-	wc->wc_cbarg = wc_cbarg;
-	wc->wc_count = 0;
-	bfa_wc_up(wc);
-}
-
-/**
- * Wait for counter to reach zero
- */
-static inline void
-bfa_wc_wait(struct bfa_wc *wc)
-{
-	bfa_wc_down(wc);
-}
-
-#endif /* __BFA_CS_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bfa_defs_cna.h linux-libre-3.2-gnu/drivers/net/bna/bfa_defs_cna.h
--- linux-libre-3.1-gnu/drivers/net/bna/bfa_defs_cna.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bfa_defs_cna.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,223 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-#ifndef __BFA_DEFS_CNA_H__
-#define __BFA_DEFS_CNA_H__
-
-#include "bfa_defs.h"
-
-/**
- * @brief
- * FC physical port statistics.
- */
-struct bfa_port_fc_stats {
-	u64	secs_reset;	/*!< Seconds since stats is reset */
-	u64	tx_frames;	/*!< Tx frames			*/
-	u64	tx_words;	/*!< Tx words			*/
-	u64	tx_lip;		/*!< Tx LIP			*/
-	u64	tx_nos;		/*!< Tx NOS			*/
-	u64	tx_ols;		/*!< Tx OLS			*/
-	u64	tx_lr;		/*!< Tx LR			*/
-	u64	tx_lrr;		/*!< Tx LRR			*/
-	u64	rx_frames;	/*!< Rx frames			*/
-	u64	rx_words;	/*!< Rx words			*/
-	u64	lip_count;	/*!< Rx LIP			*/
-	u64	nos_count;	/*!< Rx NOS			*/
-	u64	ols_count;	/*!< Rx OLS			*/
-	u64	lr_count;	/*!< Rx LR			*/
-	u64	lrr_count;	/*!< Rx LRR			*/
-	u64	invalid_crcs;	/*!< Rx CRC err frames		*/
-	u64	invalid_crc_gd_eof; /*!< Rx CRC err good EOF frames */
-	u64	undersized_frm; /*!< Rx undersized frames	*/
-	u64	oversized_frm;	/*!< Rx oversized frames	*/
-	u64	bad_eof_frm;	/*!< Rx frames with bad EOF	*/
-	u64	error_frames;	/*!< Errored frames		*/
-	u64	dropped_frames;	/*!< Dropped frames		*/
-	u64	link_failures;	/*!< Link Failure (LF) count	*/
-	u64	loss_of_syncs;	/*!< Loss of sync count		*/
-	u64	loss_of_signals; /*!< Loss of signal count	*/
-	u64	primseq_errs;	/*!< Primitive sequence protocol err. */
-	u64	bad_os_count;	/*!< Invalid ordered sets	*/
-	u64	err_enc_out;	/*!< Encoding err nonframe_8b10b */
-	u64	err_enc;	/*!< Encoding err frame_8b10b	*/
-};
-
-/**
- * @brief
- * Eth Physical Port statistics.
- */
-struct bfa_port_eth_stats {
-	u64	secs_reset;	/*!< Seconds since stats is reset */
-	u64	frame_64;	/*!< Frames 64 bytes		*/
-	u64	frame_65_127;	/*!< Frames 65-127 bytes	*/
-	u64	frame_128_255;	/*!< Frames 128-255 bytes	*/
-	u64	frame_256_511;	/*!< Frames 256-511 bytes	*/
-	u64	frame_512_1023;	/*!< Frames 512-1023 bytes	*/
-	u64	frame_1024_1518; /*!< Frames 1024-1518 bytes	*/
-	u64	frame_1519_1522; /*!< Frames 1519-1522 bytes	*/
-	u64	tx_bytes;	/*!< Tx bytes			*/
-	u64	tx_packets;	 /*!< Tx packets		*/
-	u64	tx_mcast_packets; /*!< Tx multicast packets	*/
-	u64	tx_bcast_packets; /*!< Tx broadcast packets	*/
-	u64	tx_control_frame; /*!< Tx control frame		*/
-	u64	tx_drop;	/*!< Tx drops			*/
-	u64	tx_jabber;	/*!< Tx jabber			*/
-	u64	tx_fcs_error;	/*!< Tx FCS errors		*/
-	u64	tx_fragments;	/*!< Tx fragments		*/
-	u64	rx_bytes;	/*!< Rx bytes			*/
-	u64	rx_packets;	/*!< Rx packets			*/
-	u64	rx_mcast_packets; /*!< Rx multicast packets	*/
-	u64	rx_bcast_packets; /*!< Rx broadcast packets	*/
-	u64	rx_control_frames; /*!< Rx control frames	*/
-	u64	rx_unknown_opcode; /*!< Rx unknown opcode	*/
-	u64	rx_drop;	/*!< Rx drops			*/
-	u64	rx_jabber;	/*!< Rx jabber			*/
-	u64	rx_fcs_error;	/*!< Rx FCS errors		*/
-	u64	rx_alignment_error; /*!< Rx alignment errors	*/
-	u64	rx_frame_length_error; /*!< Rx frame len errors	*/
-	u64	rx_code_error;	/*!< Rx code errors		*/
-	u64	rx_fragments;	/*!< Rx fragments		*/
-	u64	rx_pause;	/*!< Rx pause			*/
-	u64	rx_zero_pause;	/*!< Rx zero pause		*/
-	u64	tx_pause;	/*!< Tx pause			*/
-	u64	tx_zero_pause;	/*!< Tx zero pause		*/
-	u64	rx_fcoe_pause;	/*!< Rx FCoE pause		*/
-	u64	rx_fcoe_zero_pause; /*!< Rx FCoE zero pause	*/
-	u64	tx_fcoe_pause;	/*!< Tx FCoE pause		*/
-	u64	tx_fcoe_zero_pause; /*!< Tx FCoE zero pause	*/
-};
-
-/**
- * @brief
- *		Port statistics.
- */
-union bfa_port_stats_u {
-	struct bfa_port_fc_stats fc;
-	struct bfa_port_eth_stats eth;
-};
-
-#pragma pack(1)
-
-#define BFA_CEE_LLDP_MAX_STRING_LEN (128)
-#define BFA_CEE_DCBX_MAX_PRIORITY	(8)
-#define BFA_CEE_DCBX_MAX_PGID		(8)
-
-#define BFA_CEE_LLDP_SYS_CAP_OTHER	0x0001
-#define BFA_CEE_LLDP_SYS_CAP_REPEATER	0x0002
-#define BFA_CEE_LLDP_SYS_CAP_MAC_BRIDGE	0x0004
-#define BFA_CEE_LLDP_SYS_CAP_WLAN_AP	0x0008
-#define BFA_CEE_LLDP_SYS_CAP_ROUTER	0x0010
-#define BFA_CEE_LLDP_SYS_CAP_TELEPHONE	0x0020
-#define BFA_CEE_LLDP_SYS_CAP_DOCSIS_CD	0x0040
-#define BFA_CEE_LLDP_SYS_CAP_STATION	0x0080
-#define BFA_CEE_LLDP_SYS_CAP_CVLAN	0x0100
-#define BFA_CEE_LLDP_SYS_CAP_SVLAN	0x0200
-#define BFA_CEE_LLDP_SYS_CAP_TPMR	0x0400
-
-/* LLDP string type */
-struct bfa_cee_lldp_str {
-	u8 sub_type;
-	u8 len;
-	u8 rsvd[2];
-	u8 value[BFA_CEE_LLDP_MAX_STRING_LEN];
-};
-
-/* LLDP paramters */
-struct bfa_cee_lldp_cfg {
-	struct bfa_cee_lldp_str chassis_id;
-	struct bfa_cee_lldp_str port_id;
-	struct bfa_cee_lldp_str port_desc;
-	struct bfa_cee_lldp_str sys_name;
-	struct bfa_cee_lldp_str sys_desc;
-	struct bfa_cee_lldp_str mgmt_addr;
-	u16 time_to_live;
-	u16 enabled_system_cap;
-};
-
-enum bfa_cee_dcbx_version {
-	DCBX_PROTOCOL_PRECEE	= 1,
-	DCBX_PROTOCOL_CEE	= 2,
-};
-
-enum bfa_cee_lls {
-	/* LLS is down because the TLV not sent by the peer */
-	CEE_LLS_DOWN_NO_TLV = 0,
-	/* LLS is down as advertised by the peer */
-	CEE_LLS_DOWN	= 1,
-	CEE_LLS_UP	= 2,
-};
-
-/* CEE/DCBX parameters */
-struct bfa_cee_dcbx_cfg {
-	u8 pgid[BFA_CEE_DCBX_MAX_PRIORITY];
-	u8 pg_percentage[BFA_CEE_DCBX_MAX_PGID];
-	u8 pfc_primap; /* bitmap of priorties with PFC enabled */
-	u8 fcoe_primap; /* bitmap of priorities used for FcoE traffic */
-	u8 iscsi_primap; /* bitmap of priorities used for iSCSI traffic */
-	u8 dcbx_version; /* operating version:CEE or preCEE */
-	u8 lls_fcoe; /* FCoE Logical Link Status */
-	u8 lls_lan; /* LAN Logical Link Status */
-	u8 rsvd[2];
-};
-
-/* CEE status */
-/* Making this to tri-state for the benefit of port list command */
-enum bfa_cee_status {
-	CEE_UP = 0,
-	CEE_PHY_UP = 1,
-	CEE_LOOPBACK = 2,
-	CEE_PHY_DOWN = 3,
-};
-
-/* CEE Query */
-struct bfa_cee_attr {
-	u8	cee_status;
-	u8 error_reason;
-	struct bfa_cee_lldp_cfg lldp_remote;
-	struct bfa_cee_dcbx_cfg dcbx_remote;
-	mac_t src_mac;
-	u8 link_speed;
-	u8 nw_priority;
-	u8 filler[2];
-};
-
-/* LLDP/DCBX/CEE Statistics */
-struct bfa_cee_stats {
-	u32	lldp_tx_frames;		/*!< LLDP Tx Frames */
-	u32	lldp_rx_frames;		/*!< LLDP Rx Frames */
-	u32	lldp_rx_frames_invalid;	/*!< LLDP Rx Frames invalid */
-	u32	lldp_rx_frames_new;	/*!< LLDP Rx Frames new */
-	u32	lldp_tlvs_unrecognized;	/*!< LLDP Rx unrecognized TLVs */
-	u32	lldp_rx_shutdown_tlvs;	/*!< LLDP Rx shutdown TLVs */
-	u32	lldp_info_aged_out;	/*!< LLDP remote info aged out */
-	u32	dcbx_phylink_ups;	/*!< DCBX phy link ups */
-	u32	dcbx_phylink_downs;	/*!< DCBX phy link downs */
-	u32	dcbx_rx_tlvs;		/*!< DCBX Rx TLVs */
-	u32	dcbx_rx_tlvs_invalid;	/*!< DCBX Rx TLVs invalid */
-	u32	dcbx_control_tlv_error;	/*!< DCBX control TLV errors */
-	u32	dcbx_feature_tlv_error;	/*!< DCBX feature TLV errors */
-	u32	dcbx_cee_cfg_new;	/*!< DCBX new CEE cfg rcvd */
-	u32	cee_status_down;	/*!< CEE status down */
-	u32	cee_status_up;		/*!< CEE status up */
-	u32	cee_hw_cfg_changed;	/*!< CEE hw cfg changed */
-	u32	cee_rx_invalid_cfg;	/*!< CEE invalid cfg */
-};
-
-#pragma pack()
-
-#endif	/* __BFA_DEFS_CNA_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bfa_defs.h linux-libre-3.2-gnu/drivers/net/bna/bfa_defs.h
--- linux-libre-3.1-gnu/drivers/net/bna/bfa_defs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bfa_defs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,246 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-#ifndef __BFA_DEFS_H__
-#define __BFA_DEFS_H__
-
-#include "cna.h"
-#include "bfa_defs_status.h"
-#include "bfa_defs_mfg_comm.h"
-
-#define BFA_STRING_32	32
-#define BFA_VERSION_LEN 64
-
-/**
- * ---------------------- adapter definitions ------------
- */
-
-/**
- * BFA adapter level attributes.
- */
-enum {
-	BFA_ADAPTER_SERIAL_NUM_LEN = STRSZ(BFA_MFG_SERIALNUM_SIZE),
-					/*
-					 *!< adapter serial num length
-					 */
-	BFA_ADAPTER_MODEL_NAME_LEN  = 16,  /*!< model name length */
-	BFA_ADAPTER_MODEL_DESCR_LEN = 128, /*!< model description length */
-	BFA_ADAPTER_MFG_NAME_LEN    = 8,   /*!< manufacturer name length */
-	BFA_ADAPTER_SYM_NAME_LEN    = 64,  /*!< adapter symbolic name length */
-	BFA_ADAPTER_OS_TYPE_LEN	    = 64,  /*!< adapter os type length */
-};
-
-struct bfa_adapter_attr {
-	char		manufacturer[BFA_ADAPTER_MFG_NAME_LEN];
-	char		serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
-	u32	card_type;
-	char		model[BFA_ADAPTER_MODEL_NAME_LEN];
-	char		model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
-	u64		pwwn;
-	char		node_symname[FC_SYMNAME_MAX];
-	char		hw_ver[BFA_VERSION_LEN];
-	char		fw_ver[BFA_VERSION_LEN];
-	char		optrom_ver[BFA_VERSION_LEN];
-	char		os_type[BFA_ADAPTER_OS_TYPE_LEN];
-	struct bfa_mfg_vpd vpd;
-	struct mac mac;
-
-	u8		nports;
-	u8		max_speed;
-	u8		prototype;
-	char	        asic_rev;
-
-	u8		pcie_gen;
-	u8		pcie_lanes_orig;
-	u8		pcie_lanes;
-	u8	        cna_capable;
-
-	u8		is_mezz;
-	u8		trunk_capable;
-};
-
-/**
- * ---------------------- IOC definitions ------------
- */
-
-enum {
-	BFA_IOC_DRIVER_LEN	= 16,
-	BFA_IOC_CHIP_REV_LEN	= 8,
-};
-
-/**
- * Driver and firmware versions.
- */
-struct bfa_ioc_driver_attr {
-	char		driver[BFA_IOC_DRIVER_LEN];	/*!< driver name */
-	char		driver_ver[BFA_VERSION_LEN];	/*!< driver version */
-	char		fw_ver[BFA_VERSION_LEN];	/*!< firmware version */
-	char		bios_ver[BFA_VERSION_LEN];	/*!< bios version */
-	char		efi_ver[BFA_VERSION_LEN];	/*!< EFI version */
-	char		ob_ver[BFA_VERSION_LEN];	/*!< openboot version */
-};
-
-/**
- * IOC PCI device attributes
- */
-struct bfa_ioc_pci_attr {
-	u16	vendor_id;	/*!< PCI vendor ID */
-	u16	device_id;	/*!< PCI device ID */
-	u16	ssid;		/*!< subsystem ID */
-	u16	ssvid;		/*!< subsystem vendor ID */
-	u32	pcifn;		/*!< PCI device function */
-	u32	rsvd;		/* padding */
-	char		chip_rev[BFA_IOC_CHIP_REV_LEN];	 /*!< chip revision */
-};
-
-/**
- * IOC states
- */
-enum bfa_ioc_state {
-	BFA_IOC_UNINIT		= 1,	/*!< IOC is in uninit state */
-	BFA_IOC_RESET		= 2,	/*!< IOC is in reset state */
-	BFA_IOC_SEMWAIT		= 3,	/*!< Waiting for IOC h/w semaphore */
-	BFA_IOC_HWINIT		= 4,	/*!< IOC h/w is being initialized */
-	BFA_IOC_GETATTR		= 5,	/*!< IOC is being configured */
-	BFA_IOC_OPERATIONAL	= 6,	/*!< IOC is operational */
-	BFA_IOC_INITFAIL	= 7,	/*!< IOC hardware failure */
-	BFA_IOC_FAIL		= 8,	/*!< IOC heart-beat failure */
-	BFA_IOC_DISABLING	= 9,	/*!< IOC is being disabled */
-	BFA_IOC_DISABLED	= 10,	/*!< IOC is disabled */
-	BFA_IOC_FWMISMATCH	= 11,	/*!< IOC f/w different from drivers */
-	BFA_IOC_ENABLING	= 12,	/*!< IOC is being enabled */
-};
-
-/**
- * IOC firmware stats
- */
-struct bfa_fw_ioc_stats {
-	u32	enable_reqs;
-	u32	disable_reqs;
-	u32	get_attr_reqs;
-	u32	dbg_sync;
-	u32	dbg_dump;
-	u32	unknown_reqs;
-};
-
-/**
- * IOC driver stats
- */
-struct bfa_ioc_drv_stats {
-	u32	ioc_isrs;
-	u32	ioc_enables;
-	u32	ioc_disables;
-	u32	ioc_hbfails;
-	u32	ioc_boots;
-	u32	stats_tmos;
-	u32	hb_count;
-	u32	disable_reqs;
-	u32	enable_reqs;
-	u32	disable_replies;
-	u32	enable_replies;
-	u32	rsvd;
-};
-
-/**
- * IOC statistics
- */
-struct bfa_ioc_stats {
-	struct bfa_ioc_drv_stats drv_stats; /*!< driver IOC stats */
-	struct bfa_fw_ioc_stats fw_stats;  /*!< firmware IOC stats */
-};
-
-enum bfa_ioc_type {
-	BFA_IOC_TYPE_FC		= 1,
-	BFA_IOC_TYPE_FCoE	= 2,
-	BFA_IOC_TYPE_LL		= 3,
-};
-
-/**
- * IOC attributes returned in queries
- */
-struct bfa_ioc_attr {
-	enum bfa_ioc_type ioc_type;
-	enum bfa_ioc_state		state;		/*!< IOC state      */
-	struct bfa_adapter_attr adapter_attr;	/*!< HBA attributes */
-	struct bfa_ioc_driver_attr driver_attr;	/*!< driver attr    */
-	struct bfa_ioc_pci_attr pci_attr;
-	u8				port_id;	/*!< port number    */
-	u8				rsvd[7];	/*!< 64bit align    */
-};
-
-/**
- * ---------------------- mfg definitions ------------
- */
-
-/**
- * Checksum size
- */
-#define BFA_MFG_CHKSUM_SIZE			16
-
-#define BFA_MFG_PARTNUM_SIZE			14
-#define BFA_MFG_SUPPLIER_ID_SIZE		10
-#define BFA_MFG_SUPPLIER_PARTNUM_SIZE		20
-#define BFA_MFG_SUPPLIER_SERIALNUM_SIZE		20
-#define BFA_MFG_SUPPLIER_REVISION_SIZE		4
-
-#pragma pack(1)
-
-/**
- * @brief BFA adapter manufacturing block definition.
- *
- * All numerical fields are in big-endian format.
- */
-struct bfa_mfg_block {
-	u8		version;	/*!< manufacturing block version */
-	u8		mfg_sig[3];	/*!< characters 'M', 'F', 'G' */
-	u16	mfgsize;	/*!< mfg block size */
-	u16	u16_chksum;	/*!< old u16 checksum */
-	char		brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
-	char		brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)];
-	u8		mfg_day;	/*!< manufacturing day */
-	u8		mfg_month;	/*!< manufacturing month */
-	u16	mfg_year;	/*!< manufacturing year */
-	u64		mfg_wwn;	/*!< wwn base for this adapter */
-	u8		num_wwn;	/*!< number of wwns assigned */
-	u8		mfg_speeds;	/*!< speeds allowed for this adapter */
-	u8		rsv[2];
-	char		supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)];
-	char		supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)];
-	char
-		supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
-	char
-		supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
-	mac_t		mfg_mac;	/*!< mac address */
-	u8		num_mac;	/*!< number of mac addresses */
-	u8		rsv2;
-	u32	mfg_type;	/*!< card type */
-	u8		rsv3[108];
-	u8		md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*!< md5 checksum */
-};
-
-#pragma pack()
-
-/**
- * ---------------------- pci definitions ------------
- */
-
-#define bfa_asic_id_ct(devid)			\
-	((devid) == PCI_DEVICE_ID_BROCADE_CT ||	\
-	(devid) == PCI_DEVICE_ID_BROCADE_CT_FC)
-
-#endif /* __BFA_DEFS_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bfa_defs_mfg_comm.h linux-libre-3.2-gnu/drivers/net/bna/bfa_defs_mfg_comm.h
--- linux-libre-3.1-gnu/drivers/net/bna/bfa_defs_mfg_comm.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bfa_defs_mfg_comm.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,222 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-#ifndef __BFA_DEFS_MFG_COMM_H__
-#define __BFA_DEFS_MFG_COMM_H__
-
-#include "cna.h"
-
-/**
- * Manufacturing block version
- */
-#define BFA_MFG_VERSION				2
-#define BFA_MFG_VERSION_UNINIT			0xFF
-
-/**
- * Manufacturing block encrypted version
- */
-#define BFA_MFG_ENC_VER				2
-
-/**
- * Manufacturing block version 1 length
- */
-#define BFA_MFG_VER1_LEN			128
-
-/**
- * Manufacturing block header length
- */
-#define BFA_MFG_HDR_LEN				4
-
-#define BFA_MFG_SERIALNUM_SIZE			11
-#define STRSZ(_n)				(((_n) + 4) & ~3)
-
-/**
- * Manufacturing card type
- */
-enum {
-	BFA_MFG_TYPE_CB_MAX  = 825,      /*!< Crossbow card type max	*/
-	BFA_MFG_TYPE_FC8P2   = 825,      /*!< 8G 2port FC card		*/
-	BFA_MFG_TYPE_FC8P1   = 815,      /*!< 8G 1port FC card		*/
-	BFA_MFG_TYPE_FC4P2   = 425,      /*!< 4G 2port FC card		*/
-	BFA_MFG_TYPE_FC4P1   = 415,      /*!< 4G 1port FC card		*/
-	BFA_MFG_TYPE_CNA10P2 = 1020,     /*!< 10G 2port CNA card	*/
-	BFA_MFG_TYPE_CNA10P1 = 1010,     /*!< 10G 1port CNA card	*/
-	BFA_MFG_TYPE_JAYHAWK = 804,	 /*!< Jayhawk mezz card		*/
-	BFA_MFG_TYPE_WANCHESE = 1007,	 /*!< Wanchese mezz card	*/
-	BFA_MFG_TYPE_ASTRA    = 807,	 /*!< Astra mezz card		*/
-	BFA_MFG_TYPE_LIGHTNING_P0 = 902, /*!< Lightning mezz card - old	*/
-	BFA_MFG_TYPE_LIGHTNING = 1741,	 /*!< Lightning mezz card	*/
-	BFA_MFG_TYPE_INVALID = 0,	 /*!< Invalid card type		*/
-};
-
-#pragma pack(1)
-
-/**
- * Check if 1-port card
- */
-#define bfa_mfg_is_1port(type) (( \
-	(type) == BFA_MFG_TYPE_FC8P1 || \
-	(type) == BFA_MFG_TYPE_FC4P1 || \
-	(type) == BFA_MFG_TYPE_CNA10P1))
-
-/**
- * Check if Mezz card
- */
-#define bfa_mfg_is_mezz(type) (( \
-	(type) == BFA_MFG_TYPE_JAYHAWK || \
-	(type) == BFA_MFG_TYPE_WANCHESE || \
-	(type) == BFA_MFG_TYPE_ASTRA || \
-	(type) == BFA_MFG_TYPE_LIGHTNING_P0 || \
-	(type) == BFA_MFG_TYPE_LIGHTNING))
-
-/**
- * Check if card type valid
- */
-#define bfa_mfg_is_card_type_valid(type) (( \
-	(type) == BFA_MFG_TYPE_FC8P2 || \
-	(type) == BFA_MFG_TYPE_FC8P1 || \
-	(type) == BFA_MFG_TYPE_FC4P2 || \
-	(type) == BFA_MFG_TYPE_FC4P1 || \
-	(type) == BFA_MFG_TYPE_CNA10P2 || \
-	(type) == BFA_MFG_TYPE_CNA10P1 || \
-	bfa_mfg_is_mezz(type)))
-
-#define bfa_mfg_adapter_prop_init_flash(card_type, prop)	\
-do {								\
-	switch ((card_type)) {					\
-	case BFA_MFG_TYPE_FC8P2:				\
-	case BFA_MFG_TYPE_JAYHAWK:				\
-	case BFA_MFG_TYPE_ASTRA:				\
-		(prop) = BFI_ADAPTER_SETP(NPORTS, 2) |		\
-			BFI_ADAPTER_SETP(SPEED, 8);		\
-		break;						\
-	case BFA_MFG_TYPE_FC8P1:				\
-		(prop) = BFI_ADAPTER_SETP(NPORTS, 1) |		\
-			BFI_ADAPTER_SETP(SPEED, 8);		\
-		break;						\
-	case BFA_MFG_TYPE_FC4P2:				\
-		(prop) = BFI_ADAPTER_SETP(NPORTS, 2) |		\
-			BFI_ADAPTER_SETP(SPEED, 4);		\
-		break;						\
-	case BFA_MFG_TYPE_FC4P1:				\
-		(prop) = BFI_ADAPTER_SETP(NPORTS, 1) |		\
-			BFI_ADAPTER_SETP(SPEED, 4);		\
-		break;						\
-	case BFA_MFG_TYPE_CNA10P2:				\
-	case BFA_MFG_TYPE_WANCHESE:				\
-	case BFA_MFG_TYPE_LIGHTNING_P0:				\
-	case BFA_MFG_TYPE_LIGHTNING:				\
-		(prop) = BFI_ADAPTER_SETP(NPORTS, 2);		\
-		(prop) |= BFI_ADAPTER_SETP(SPEED, 10);		\
-		break;						\
-	case BFA_MFG_TYPE_CNA10P1:				\
-		(prop) = BFI_ADAPTER_SETP(NPORTS, 1);		\
-		(prop) |= BFI_ADAPTER_SETP(SPEED, 10);		\
-		break;						\
-	default:						\
-		(prop) = BFI_ADAPTER_UNSUPP;			\
-	}							\
-} while (0)
-
-enum {
-	CB_GPIO_TTV	= (1),		/*!< TTV debug capable cards	*/
-	CB_GPIO_FC8P2   = (2),		/*!< 8G 2port FC card		*/
-	CB_GPIO_FC8P1   = (3),		/*!< 8G 1port FC card		*/
-	CB_GPIO_FC4P2   = (4),		/*!< 4G 2port FC card		*/
-	CB_GPIO_FC4P1   = (5),		/*!< 4G 1port FC card		*/
-	CB_GPIO_DFLY    = (6),		/*!< 8G 2port FC mezzanine card	*/
-	CB_GPIO_PROTO   = (1 << 7)	/*!< 8G 2port FC prototypes	*/
-};
-
-#define bfa_mfg_adapter_prop_init_gpio(gpio, card_type, prop)	\
-do {								\
-	if ((gpio) & CB_GPIO_PROTO) {				\
-		(prop) |= BFI_ADAPTER_PROTO;			\
-		(gpio) &= ~CB_GPIO_PROTO;			\
-	}							\
-	switch ((gpio)) {					\
-	case CB_GPIO_TTV:					\
-		(prop) |= BFI_ADAPTER_TTV;			\
-	case CB_GPIO_DFLY:					\
-	case CB_GPIO_FC8P2:					\
-		(prop) |= BFI_ADAPTER_SETP(NPORTS, 2);		\
-		(prop) |= BFI_ADAPTER_SETP(SPEED, 8);		\
-		(card_type) = BFA_MFG_TYPE_FC8P2;		\
-		break;						\
-	case CB_GPIO_FC8P1:					\
-		(prop) |= BFI_ADAPTER_SETP(NPORTS, 1);		\
-		(prop) |= BFI_ADAPTER_SETP(SPEED, 8);		\
-		(card_type) = BFA_MFG_TYPE_FC8P1;		\
-		break;						\
-	case CB_GPIO_FC4P2:					\
-		(prop) |= BFI_ADAPTER_SETP(NPORTS, 2);		\
-		(prop) |= BFI_ADAPTER_SETP(SPEED, 4);		\
-		(card_type) = BFA_MFG_TYPE_FC4P2;		\
-		break;						\
-	case CB_GPIO_FC4P1:					\
-		(prop) |= BFI_ADAPTER_SETP(NPORTS, 1);		\
-		(prop) |= BFI_ADAPTER_SETP(SPEED, 4);		\
-		(card_type) = BFA_MFG_TYPE_FC4P1;		\
-		break;						\
-	default:						\
-		(prop) |= BFI_ADAPTER_UNSUPP;			\
-		(card_type) = BFA_MFG_TYPE_INVALID;		\
-	}							\
-} while (0)
-
-/**
- * VPD data length
- */
-#define BFA_MFG_VPD_LEN			512
-#define BFA_MFG_VPD_LEN_INVALID		0
-
-#define BFA_MFG_VPD_PCI_HDR_OFF		137
-#define BFA_MFG_VPD_PCI_VER_MASK	0x07	/*!< version mask 3 bits */
-#define BFA_MFG_VPD_PCI_VDR_MASK	0xf8	/*!< vendor mask 5 bits */
-
-/**
- * VPD vendor tag
- */
-enum {
-	BFA_MFG_VPD_UNKNOWN	= 0,     /*!< vendor unknown		*/
-	BFA_MFG_VPD_IBM		= 1,     /*!< vendor IBM		*/
-	BFA_MFG_VPD_HP		= 2,     /*!< vendor HP			*/
-	BFA_MFG_VPD_DELL	= 3,     /*!< vendor DELL		*/
-	BFA_MFG_VPD_PCI_IBM	= 0x08,  /*!< PCI VPD IBM		*/
-	BFA_MFG_VPD_PCI_HP	= 0x10,  /*!< PCI VPD HP		*/
-	BFA_MFG_VPD_PCI_DELL	= 0x20,  /*!< PCI VPD DELL		*/
-	BFA_MFG_VPD_PCI_BRCD	= 0xf8,  /*!< PCI VPD Brocade		*/
-};
-
-/**
- * @brief BFA adapter flash vpd data definition.
- *
- * All numerical fields are in big-endian format.
- */
-struct bfa_mfg_vpd {
-	u8		version;	/*!< vpd data version */
-	u8		vpd_sig[3];	/*!< characters 'V', 'P', 'D' */
-	u8		chksum;		/*!< u8 checksum */
-	u8		vendor;		/*!< vendor */
-	u8	len;		/*!< vpd data length excluding header */
-	u8	rsv;
-	u8		data[BFA_MFG_VPD_LEN];	/*!< vpd data */
-};
-
-#pragma pack()
-
-#endif /* __BFA_DEFS_MFG_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bfa_defs_status.h linux-libre-3.2-gnu/drivers/net/bna/bfa_defs_status.h
--- linux-libre-3.1-gnu/drivers/net/bna/bfa_defs_status.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bfa_defs_status.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,216 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-#ifndef __BFA_DEFS_STATUS_H__
-#define __BFA_DEFS_STATUS_H__
-
-/**
- * API status return values
- *
- * NOTE: The error msgs are auto generated from the comments. Only singe line
- * comments are supported
- */
-enum bfa_status {
-	BFA_STATUS_OK = 0,
-	BFA_STATUS_FAILED = 1,
-	BFA_STATUS_EINVAL = 2,
-	BFA_STATUS_ENOMEM = 3,
-	BFA_STATUS_ENOSYS = 4,
-	BFA_STATUS_ETIMER = 5,
-	BFA_STATUS_EPROTOCOL = 6,
-	BFA_STATUS_ENOFCPORTS = 7,
-	BFA_STATUS_NOFLASH = 8,
-	BFA_STATUS_BADFLASH = 9,
-	BFA_STATUS_SFP_UNSUPP = 10,
-	BFA_STATUS_UNKNOWN_VFID = 11,
-	BFA_STATUS_DATACORRUPTED = 12,
-	BFA_STATUS_DEVBUSY = 13,
-	BFA_STATUS_ABORTED = 14,
-	BFA_STATUS_NODEV = 15,
-	BFA_STATUS_HDMA_FAILED = 16,
-	BFA_STATUS_FLASH_BAD_LEN = 17,
-	BFA_STATUS_UNKNOWN_LWWN = 18,
-	BFA_STATUS_UNKNOWN_RWWN = 19,
-	BFA_STATUS_FCPT_LS_RJT = 20,
-	BFA_STATUS_VPORT_EXISTS = 21,
-	BFA_STATUS_VPORT_MAX = 22,
-	BFA_STATUS_UNSUPP_SPEED = 23,
-	BFA_STATUS_INVLD_DFSZ = 24,
-	BFA_STATUS_CNFG_FAILED = 25,
-	BFA_STATUS_CMD_NOTSUPP = 26,
-	BFA_STATUS_NO_ADAPTER = 27,
-	BFA_STATUS_LINKDOWN = 28,
-	BFA_STATUS_FABRIC_RJT = 29,
-	BFA_STATUS_UNKNOWN_VWWN = 30,
-	BFA_STATUS_NSLOGIN_FAILED = 31,
-	BFA_STATUS_NO_RPORTS = 32,
-	BFA_STATUS_NSQUERY_FAILED = 33,
-	BFA_STATUS_PORT_OFFLINE = 34,
-	BFA_STATUS_RPORT_OFFLINE = 35,
-	BFA_STATUS_TGTOPEN_FAILED = 36,
-	BFA_STATUS_BAD_LUNS = 37,
-	BFA_STATUS_IO_FAILURE = 38,
-	BFA_STATUS_NO_FABRIC = 39,
-	BFA_STATUS_EBADF = 40,
-	BFA_STATUS_EINTR = 41,
-	BFA_STATUS_EIO = 42,
-	BFA_STATUS_ENOTTY = 43,
-	BFA_STATUS_ENXIO = 44,
-	BFA_STATUS_EFOPEN = 45,
-	BFA_STATUS_VPORT_WWN_BP = 46,
-	BFA_STATUS_PORT_NOT_DISABLED = 47,
-	BFA_STATUS_BADFRMHDR = 48,
-	BFA_STATUS_BADFRMSZ = 49,
-	BFA_STATUS_MISSINGFRM = 50,
-	BFA_STATUS_LINKTIMEOUT = 51,
-	BFA_STATUS_NO_FCPIM_NEXUS = 52,
-	BFA_STATUS_CHECKSUM_FAIL = 53,
-	BFA_STATUS_GZME_FAILED = 54,
-	BFA_STATUS_SCSISTART_REQD = 55,
-	BFA_STATUS_IOC_FAILURE = 56,
-	BFA_STATUS_INVALID_WWN = 57,
-	BFA_STATUS_MISMATCH = 58,
-	BFA_STATUS_IOC_ENABLED = 59,
-	BFA_STATUS_ADAPTER_ENABLED = 60,
-	BFA_STATUS_IOC_NON_OP = 61,
-	BFA_STATUS_ADDR_MAP_FAILURE = 62,
-	BFA_STATUS_SAME_NAME = 63,
-	BFA_STATUS_PENDING = 64,
-	BFA_STATUS_8G_SPD = 65,
-	BFA_STATUS_4G_SPD = 66,
-	BFA_STATUS_AD_IS_ENABLE = 67,
-	BFA_STATUS_EINVAL_TOV = 68,
-	BFA_STATUS_EINVAL_QDEPTH = 69,
-	BFA_STATUS_VERSION_FAIL = 70,
-	BFA_STATUS_DIAG_BUSY = 71,
-	BFA_STATUS_BEACON_ON = 72,
-	BFA_STATUS_BEACON_OFF = 73,
-	BFA_STATUS_LBEACON_ON = 74,
-	BFA_STATUS_LBEACON_OFF = 75,
-	BFA_STATUS_PORT_NOT_INITED = 76,
-	BFA_STATUS_RPSC_ENABLED = 77,
-	BFA_STATUS_ENOFSAVE = 78,
-	BFA_STATUS_BAD_FILE = 79,
-	BFA_STATUS_RLIM_EN = 80,
-	BFA_STATUS_RLIM_DIS = 81,
-	BFA_STATUS_IOC_DISABLED = 82,
-	BFA_STATUS_ADAPTER_DISABLED = 83,
-	BFA_STATUS_BIOS_DISABLED = 84,
-	BFA_STATUS_AUTH_ENABLED = 85,
-	BFA_STATUS_AUTH_DISABLED = 86,
-	BFA_STATUS_ERROR_TRL_ENABLED = 87,
-	BFA_STATUS_ERROR_QOS_ENABLED = 88,
-	BFA_STATUS_NO_SFP_DEV = 89,
-	BFA_STATUS_MEMTEST_FAILED = 90,
-	BFA_STATUS_INVALID_DEVID = 91,
-	BFA_STATUS_QOS_ENABLED = 92,
-	BFA_STATUS_QOS_DISABLED = 93,
-	BFA_STATUS_INCORRECT_DRV_CONFIG = 94,
-	BFA_STATUS_REG_FAIL = 95,
-	BFA_STATUS_IM_INV_CODE = 96,
-	BFA_STATUS_IM_INV_VLAN = 97,
-	BFA_STATUS_IM_INV_ADAPT_NAME = 98,
-	BFA_STATUS_IM_LOW_RESOURCES = 99,
-	BFA_STATUS_IM_VLANID_IS_PVID = 100,
-	BFA_STATUS_IM_VLANID_EXISTS = 101,
-	BFA_STATUS_IM_FW_UPDATE_FAIL = 102,
-	BFA_STATUS_PORTLOG_ENABLED = 103,
-	BFA_STATUS_PORTLOG_DISABLED = 104,
-	BFA_STATUS_FILE_NOT_FOUND = 105,
-	BFA_STATUS_QOS_FC_ONLY = 106,
-	BFA_STATUS_RLIM_FC_ONLY = 107,
-	BFA_STATUS_CT_SPD = 108,
-	BFA_STATUS_LEDTEST_OP = 109,
-	BFA_STATUS_CEE_NOT_DN = 110,
-	BFA_STATUS_10G_SPD = 111,
-	BFA_STATUS_IM_INV_TEAM_NAME = 112,
-	BFA_STATUS_IM_DUP_TEAM_NAME = 113,
-	BFA_STATUS_IM_ADAPT_ALREADY_IN_TEAM = 114,
-	BFA_STATUS_IM_ADAPT_HAS_VLANS = 115,
-	BFA_STATUS_IM_PVID_MISMATCH = 116,
-	BFA_STATUS_IM_LINK_SPEED_MISMATCH = 117,
-	BFA_STATUS_IM_MTU_MISMATCH = 118,
-	BFA_STATUS_IM_RSS_MISMATCH = 119,
-	BFA_STATUS_IM_HDS_MISMATCH = 120,
-	BFA_STATUS_IM_OFFLOAD_MISMATCH = 121,
-	BFA_STATUS_IM_PORT_PARAMS = 122,
-	BFA_STATUS_IM_PORT_NOT_IN_TEAM = 123,
-	BFA_STATUS_IM_CANNOT_REM_PRI = 124,
-	BFA_STATUS_IM_MAX_PORTS_REACHED = 125,
-	BFA_STATUS_IM_LAST_PORT_DELETE = 126,
-	BFA_STATUS_IM_NO_DRIVER = 127,
-	BFA_STATUS_IM_MAX_VLANS_REACHED = 128,
-	BFA_STATUS_TOMCAT_SPD_NOT_ALLOWED = 129,
-	BFA_STATUS_NO_MINPORT_DRIVER = 130,
-	BFA_STATUS_CARD_TYPE_MISMATCH = 131,
-	BFA_STATUS_BAD_ASICBLK = 132,
-	BFA_STATUS_NO_DRIVER = 133,
-	BFA_STATUS_INVALID_MAC = 134,
-	BFA_STATUS_IM_NO_VLAN = 135,
-	BFA_STATUS_IM_ETH_LB_FAILED = 136,
-	BFA_STATUS_IM_PVID_REMOVE = 137,
-	BFA_STATUS_IM_PVID_EDIT = 138,
-	BFA_STATUS_CNA_NO_BOOT = 139,
-	BFA_STATUS_IM_PVID_NON_ZERO = 140,
-	BFA_STATUS_IM_INETCFG_LOCK_FAILED = 141,
-	BFA_STATUS_IM_GET_INETCFG_FAILED = 142,
-	BFA_STATUS_IM_NOT_BOUND = 143,
-	BFA_STATUS_INSUFFICIENT_PERMS = 144,
-	BFA_STATUS_IM_INV_VLAN_NAME = 145,
-	BFA_STATUS_CMD_NOTSUPP_CNA = 146,
-	BFA_STATUS_IM_PASSTHRU_EDIT = 147,
-	BFA_STATUS_IM_BIND_FAILED = 148,
-	BFA_STATUS_IM_UNBIND_FAILED = 149,
-	BFA_STATUS_IM_PORT_IN_TEAM = 150,
-	BFA_STATUS_IM_VLAN_NOT_FOUND = 151,
-	BFA_STATUS_IM_TEAM_NOT_FOUND = 152,
-	BFA_STATUS_IM_TEAM_CFG_NOT_ALLOWED = 153,
-	BFA_STATUS_PBC = 154,
-	BFA_STATUS_DEVID_MISSING = 155,
-	BFA_STATUS_BAD_FWCFG = 156,
-	BFA_STATUS_CREATE_FILE = 157,
-	BFA_STATUS_INVALID_VENDOR = 158,
-	BFA_STATUS_SFP_NOT_READY = 159,
-	BFA_STATUS_FLASH_UNINIT = 160,
-	BFA_STATUS_FLASH_EMPTY = 161,
-	BFA_STATUS_FLASH_CKFAIL = 162,
-	BFA_STATUS_TRUNK_UNSUPP = 163,
-	BFA_STATUS_TRUNK_ENABLED = 164,
-	BFA_STATUS_TRUNK_DISABLED = 165,
-	BFA_STATUS_TRUNK_ERROR_TRL_ENABLED = 166,
-	BFA_STATUS_BOOT_CODE_UPDATED = 167,
-	BFA_STATUS_BOOT_VERSION = 168,
-	BFA_STATUS_CARDTYPE_MISSING = 169,
-	BFA_STATUS_INVALID_CARDTYPE = 170,
-	BFA_STATUS_NO_TOPOLOGY_FOR_CNA = 171,
-	BFA_STATUS_IM_VLAN_OVER_TEAM_DELETE_FAILED = 172,
-	BFA_STATUS_ETHBOOT_ENABLED = 173,
-	BFA_STATUS_ETHBOOT_DISABLED = 174,
-	BFA_STATUS_IOPROFILE_OFF = 175,
-	BFA_STATUS_NO_PORT_INSTANCE = 176,
-	BFA_STATUS_BOOT_CODE_TIMEDOUT = 177,
-	BFA_STATUS_NO_VPORT_LOCK = 178,
-	BFA_STATUS_VPORT_NO_CNFG = 179,
-	BFA_STATUS_MAX_VAL
-};
-
-enum bfa_eproto_status {
-	BFA_EPROTO_BAD_ACCEPT = 0,
-	BFA_EPROTO_UNKNOWN_RSP = 1
-};
-
-#endif /* __BFA_DEFS_STATUS_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bfa_ioc.c linux-libre-3.2-gnu/drivers/net/bna/bfa_ioc.c
--- linux-libre-3.1-gnu/drivers/net/bna/bfa_ioc.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bfa_ioc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2326 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-#include "bfa_ioc.h"
-#include "cna.h"
-#include "bfi.h"
-#include "bfi_ctreg.h"
-#include "bfa_defs.h"
-
-/**
- * IOC local definitions
- */
-
-/**
- * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
- */
-
-#define bfa_ioc_firmware_lock(__ioc)			\
-			((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc))
-#define bfa_ioc_firmware_unlock(__ioc)			\
-			((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))
-#define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))
-#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)			\
-			((__ioc)->ioc_hwif->ioc_sync_leave(__ioc))
-#define bfa_ioc_sync_ack(__ioc)				\
-			((__ioc)->ioc_hwif->ioc_sync_ack(__ioc))
-#define bfa_ioc_sync_complete(__ioc)			\
-			((__ioc)->ioc_hwif->ioc_sync_complete(__ioc))
-
-#define bfa_ioc_mbox_cmd_pending(__ioc)		\
-			(!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
-			readl((__ioc)->ioc_regs.hfn_mbox_cmd))
-
-static bool bfa_nw_auto_recover = true;
-
-/*
- * forward declarations
- */
-static void bfa_ioc_hw_sem_init(struct bfa_ioc *ioc);
-static void bfa_ioc_hw_sem_get(struct bfa_ioc *ioc);
-static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc);
-static void bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force);
-static void bfa_ioc_send_enable(struct bfa_ioc *ioc);
-static void bfa_ioc_send_disable(struct bfa_ioc *ioc);
-static void bfa_ioc_send_getattr(struct bfa_ioc *ioc);
-static void bfa_ioc_hb_monitor(struct bfa_ioc *ioc);
-static void bfa_ioc_hb_stop(struct bfa_ioc *ioc);
-static void bfa_ioc_reset(struct bfa_ioc *ioc, bool force);
-static void bfa_ioc_mbox_poll(struct bfa_ioc *ioc);
-static void bfa_ioc_mbox_flush(struct bfa_ioc *ioc);
-static void bfa_ioc_recover(struct bfa_ioc *ioc);
-static void bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc);
-static void bfa_ioc_event_notify(struct bfa_ioc *, enum bfa_ioc_event);
-static void bfa_ioc_disable_comp(struct bfa_ioc *ioc);
-static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc);
-static void bfa_ioc_fail_notify(struct bfa_ioc *ioc);
-static void bfa_ioc_pf_enabled(struct bfa_ioc *ioc);
-static void bfa_ioc_pf_disabled(struct bfa_ioc *ioc);
-static void bfa_ioc_pf_initfailed(struct bfa_ioc *ioc);
-static void bfa_ioc_pf_failed(struct bfa_ioc *ioc);
-static void bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc);
-static void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type,
-			 u32 boot_param);
-static u32 bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr);
-static void bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc,
-						char *serial_num);
-static void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc,
-						char *fw_ver);
-static void bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc,
-						char *chip_rev);
-static void bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc,
-						char *optrom_ver);
-static void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc,
-						char *manufacturer);
-static void bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model);
-static u64 bfa_ioc_get_pwwn(struct bfa_ioc *ioc);
-
-/**
- * IOC state machine definitions/declarations
- */
-enum ioc_event {
-	IOC_E_RESET		= 1,	/*!< IOC reset request		*/
-	IOC_E_ENABLE		= 2,	/*!< IOC enable request		*/
-	IOC_E_DISABLE		= 3,	/*!< IOC disable request	*/
-	IOC_E_DETACH		= 4,	/*!< driver detach cleanup	*/
-	IOC_E_ENABLED		= 5,	/*!< f/w enabled		*/
-	IOC_E_FWRSP_GETATTR	= 6,	/*!< IOC get attribute response	*/
-	IOC_E_DISABLED		= 7,	/*!< f/w disabled		*/
-	IOC_E_INITFAILED	= 8,	/*!< failure notice by iocpf sm	*/
-	IOC_E_PFFAILED		= 9,	/*!< failure notice by iocpf sm	*/
-	IOC_E_HBFAIL		= 10,	/*!< heartbeat failure		*/
-	IOC_E_HWERROR		= 11,	/*!< hardware error interrupt	*/
-	IOC_E_TIMEOUT		= 12,	/*!< timeout			*/
-};
-
-bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc, enum ioc_event);
-
-static struct bfa_sm_table ioc_sm_table[] = {
-	{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
-	{BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
-	{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},
-	{BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
-	{BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
-	{BFA_SM(bfa_ioc_sm_fail_retry), BFA_IOC_INITFAIL},
-	{BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
-	{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
-	{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
-};
-
-/**
- * IOCPF state machine definitions/declarations
- */
-
-/*
- * Forward declareations for iocpf state machine
- */
-static void bfa_iocpf_enable(struct bfa_ioc *ioc);
-static void bfa_iocpf_disable(struct bfa_ioc *ioc);
-static void bfa_iocpf_fail(struct bfa_ioc *ioc);
-static void bfa_iocpf_initfail(struct bfa_ioc *ioc);
-static void bfa_iocpf_getattrfail(struct bfa_ioc *ioc);
-static void bfa_iocpf_stop(struct bfa_ioc *ioc);
-
-/**
- * IOCPF state machine events
- */
-enum iocpf_event {
-	IOCPF_E_ENABLE		= 1,	/*!< IOCPF enable request	*/
-	IOCPF_E_DISABLE		= 2,	/*!< IOCPF disable request	*/
-	IOCPF_E_STOP		= 3,	/*!< stop on driver detach	*/
-	IOCPF_E_FWREADY		= 4,	/*!< f/w initialization done	*/
-	IOCPF_E_FWRSP_ENABLE	= 5,	/*!< enable f/w response	*/
-	IOCPF_E_FWRSP_DISABLE	= 6,	/*!< disable f/w response	*/
-	IOCPF_E_FAIL		= 7,	/*!< failure notice by ioc sm	*/
-	IOCPF_E_INITFAIL	= 8,	/*!< init fail notice by ioc sm	*/
-	IOCPF_E_GETATTRFAIL	= 9,	/*!< init fail notice by ioc sm	*/
-	IOCPF_E_SEMLOCKED	= 10,   /*!< h/w semaphore is locked	*/
-	IOCPF_E_TIMEOUT		= 11,   /*!< f/w response timeout	*/
-};
-
-/**
- * IOCPF states
- */
-enum bfa_iocpf_state {
-	BFA_IOCPF_RESET		= 1,	/*!< IOC is in reset state */
-	BFA_IOCPF_SEMWAIT	= 2,	/*!< Waiting for IOC h/w semaphore */
-	BFA_IOCPF_HWINIT	= 3,	/*!< IOC h/w is being initialized */
-	BFA_IOCPF_READY		= 4,	/*!< IOCPF is initialized */
-	BFA_IOCPF_INITFAIL	= 5,	/*!< IOCPF failed */
-	BFA_IOCPF_FAIL		= 6,	/*!< IOCPF failed */
-	BFA_IOCPF_DISABLING	= 7,	/*!< IOCPF is being disabled */
-	BFA_IOCPF_DISABLED	= 8,	/*!< IOCPF is disabled */
-	BFA_IOCPF_FWMISMATCH	= 9,	/*!< IOC f/w different from drivers */
-};
-
-bfa_fsm_state_decl(bfa_iocpf, reset, struct bfa_iocpf, enum iocpf_event);
-bfa_fsm_state_decl(bfa_iocpf, fwcheck, struct bfa_iocpf, enum iocpf_event);
-bfa_fsm_state_decl(bfa_iocpf, mismatch, struct bfa_iocpf, enum iocpf_event);
-bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf, enum iocpf_event);
-bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf, enum iocpf_event);
-bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf, enum iocpf_event);
-bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf, enum iocpf_event);
-bfa_fsm_state_decl(bfa_iocpf, initfail_sync, struct bfa_iocpf,
-						enum iocpf_event);
-bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf, enum iocpf_event);
-bfa_fsm_state_decl(bfa_iocpf, fail_sync, struct bfa_iocpf, enum iocpf_event);
-bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf, enum iocpf_event);
-bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf, enum iocpf_event);
-bfa_fsm_state_decl(bfa_iocpf, disabling_sync, struct bfa_iocpf,
-						enum iocpf_event);
-bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf, enum iocpf_event);
-
-static struct bfa_sm_table iocpf_sm_table[] = {
-	{BFA_SM(bfa_iocpf_sm_reset), BFA_IOCPF_RESET},
-	{BFA_SM(bfa_iocpf_sm_fwcheck), BFA_IOCPF_FWMISMATCH},
-	{BFA_SM(bfa_iocpf_sm_mismatch), BFA_IOCPF_FWMISMATCH},
-	{BFA_SM(bfa_iocpf_sm_semwait), BFA_IOCPF_SEMWAIT},
-	{BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},
-	{BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},
-	{BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY},
-	{BFA_SM(bfa_iocpf_sm_initfail_sync), BFA_IOCPF_INITFAIL},
-	{BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL},
-	{BFA_SM(bfa_iocpf_sm_fail_sync), BFA_IOCPF_FAIL},
-	{BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},
-	{BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING},
-	{BFA_SM(bfa_iocpf_sm_disabling_sync), BFA_IOCPF_DISABLING},
-	{BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},
-};
-
-/**
- * IOC State Machine
- */
-
-/**
- * Beginning state. IOC uninit state.
- */
-static void
-bfa_ioc_sm_uninit_entry(struct bfa_ioc *ioc)
-{
-}
-
-/**
- * IOC is in uninit state.
- */
-static void
-bfa_ioc_sm_uninit(struct bfa_ioc *ioc, enum ioc_event event)
-{
-	switch (event) {
-	case IOC_E_RESET:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-/**
- * Reset entry actions -- initialize state machine
- */
-static void
-bfa_ioc_sm_reset_entry(struct bfa_ioc *ioc)
-{
-	bfa_fsm_set_state(&ioc->iocpf, bfa_iocpf_sm_reset);
-}
-
-/**
- * IOC is in reset state.
- */
-static void
-bfa_ioc_sm_reset(struct bfa_ioc *ioc, enum ioc_event event)
-{
-	switch (event) {
-	case IOC_E_ENABLE:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
-		break;
-
-	case IOC_E_DISABLE:
-		bfa_ioc_disable_comp(ioc);
-		break;
-
-	case IOC_E_DETACH:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bfa_ioc_sm_enabling_entry(struct bfa_ioc *ioc)
-{
-	bfa_iocpf_enable(ioc);
-}
-
-/**
- * Host IOC function is being enabled, awaiting response from firmware.
- * Semaphore is acquired.
- */
-static void
-bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
-{
-	switch (event) {
-	case IOC_E_ENABLED:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
-		break;
-
-	case IOC_E_PFFAILED:
-		/* !!! fall through !!! */
-	case IOC_E_HWERROR:
-		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
-		if (event != IOC_E_PFFAILED)
-			bfa_iocpf_initfail(ioc);
-		break;
-
-	case IOC_E_DISABLE:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
-		break;
-
-	case IOC_E_DETACH:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
-		bfa_iocpf_stop(ioc);
-		break;
-
-	case IOC_E_ENABLE:
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-/**
- * Semaphore should be acquired for version check.
- */
-static void
-bfa_ioc_sm_getattr_entry(struct bfa_ioc *ioc)
-{
-	mod_timer(&ioc->ioc_timer, jiffies +
-		msecs_to_jiffies(BFA_IOC_TOV));
-	bfa_ioc_send_getattr(ioc);
-}
-
-/**
- * IOC configuration in progress. Timer is active.
- */
-static void
-bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
-{
-	switch (event) {
-	case IOC_E_FWRSP_GETATTR:
-		del_timer(&ioc->ioc_timer);
-		bfa_ioc_check_attr_wwns(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
-		break;
-
-	case IOC_E_PFFAILED:
-	case IOC_E_HWERROR:
-		del_timer(&ioc->ioc_timer);
-		/* fall through */
-	case IOC_E_TIMEOUT:
-		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
-		if (event != IOC_E_PFFAILED)
-			bfa_iocpf_getattrfail(ioc);
-		break;
-
-	case IOC_E_DISABLE:
-		del_timer(&ioc->ioc_timer);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
-		break;
-
-	case IOC_E_ENABLE:
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bfa_ioc_sm_op_entry(struct bfa_ioc *ioc)
-{
-	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
-	bfa_ioc_hb_monitor(ioc);
-}
-
-static void
-bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
-{
-	switch (event) {
-	case IOC_E_ENABLE:
-		break;
-
-	case IOC_E_DISABLE:
-		bfa_ioc_hb_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
-		break;
-
-	case IOC_E_PFFAILED:
-	case IOC_E_HWERROR:
-		bfa_ioc_hb_stop(ioc);
-		/* !!! fall through !!! */
-	case IOC_E_HBFAIL:
-		bfa_ioc_fail_notify(ioc);
-		if (ioc->iocpf.auto_recover)
-			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
-		else
-			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
-
-		if (event != IOC_E_PFFAILED)
-			bfa_iocpf_fail(ioc);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bfa_ioc_sm_disabling_entry(struct bfa_ioc *ioc)
-{
-	bfa_iocpf_disable(ioc);
-}
-
-/**
- * IOC is being desabled
- */
-static void
-bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
-{
-	switch (event) {
-	case IOC_E_DISABLED:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
-		break;
-
-	case IOC_E_HWERROR:
-		/*
-		 * No state change.  Will move to disabled state
-		 * after iocpf sm completes failure processing and
-		 * moves to disabled state.
-		 */
-		bfa_iocpf_fail(ioc);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-/**
- * IOC desable completion entry.
- */
-static void
-bfa_ioc_sm_disabled_entry(struct bfa_ioc *ioc)
-{
-	bfa_ioc_disable_comp(ioc);
-}
-
-static void
-bfa_ioc_sm_disabled(struct bfa_ioc *ioc, enum ioc_event event)
-{
-	switch (event) {
-	case IOC_E_ENABLE:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
-		break;
-
-	case IOC_E_DISABLE:
-		ioc->cbfn->disable_cbfn(ioc->bfa);
-		break;
-
-	case IOC_E_DETACH:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
-		bfa_iocpf_stop(ioc);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bfa_ioc_sm_fail_retry_entry(struct bfa_ioc *ioc)
-{
-}
-
-/**
- * Hardware initialization retry.
- */
-static void
-bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event)
-{
-	switch (event) {
-	case IOC_E_ENABLED:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
-		break;
-
-	case IOC_E_PFFAILED:
-	case IOC_E_HWERROR:
-		/**
-		 * Initialization retry failed.
-		 */
-		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-		if (event != IOC_E_PFFAILED)
-			bfa_iocpf_initfail(ioc);
-		break;
-
-	case IOC_E_INITFAILED:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
-		break;
-
-	case IOC_E_ENABLE:
-		break;
-
-	case IOC_E_DISABLE:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
-		break;
-
-	case IOC_E_DETACH:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
-		bfa_iocpf_stop(ioc);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bfa_ioc_sm_fail_entry(struct bfa_ioc *ioc)
-{
-}
-
-/**
- * IOC failure.
- */
-static void
-bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event)
-{
-	switch (event) {
-	case IOC_E_ENABLE:
-		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-		break;
-
-	case IOC_E_DISABLE:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
-		break;
-
-	case IOC_E_DETACH:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
-		bfa_iocpf_stop(ioc);
-		break;
-
-	case IOC_E_HWERROR:
-		/* HB failure notification, ignore. */
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-/**
- * IOCPF State Machine
- */
-
-/**
- * Reset entry actions -- initialize state machine
- */
-static void
-bfa_iocpf_sm_reset_entry(struct bfa_iocpf *iocpf)
-{
-	iocpf->retry_count = 0;
-	iocpf->auto_recover = bfa_nw_auto_recover;
-}
-
-/**
- * Beginning state. IOC is in reset state.
- */
-static void
-bfa_iocpf_sm_reset(struct bfa_iocpf *iocpf, enum iocpf_event event)
-{
-	switch (event) {
-	case IOCPF_E_ENABLE:
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
-		break;
-
-	case IOCPF_E_STOP:
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-/**
- * Semaphore should be acquired for version check.
- */
-static void
-bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf *iocpf)
-{
-	bfa_ioc_hw_sem_init(iocpf->ioc);
-	bfa_ioc_hw_sem_get(iocpf->ioc);
-}
-
-/**
- * Awaiting h/w semaphore to continue with version check.
- */
-static void
-bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event)
-{
-	struct bfa_ioc *ioc = iocpf->ioc;
-
-	switch (event) {
-	case IOCPF_E_SEMLOCKED:
-		if (bfa_ioc_firmware_lock(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);
-			} else {
-				bfa_ioc_firmware_unlock(ioc);
-				bfa_nw_ioc_hw_sem_release(ioc);
-				mod_timer(&ioc->sem_timer, jiffies +
-					msecs_to_jiffies(BFA_IOC_HWSEM_TOV));
-			}
-		} else {
-			bfa_nw_ioc_hw_sem_release(ioc);
-			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);
-		}
-		break;
-
-	case IOCPF_E_DISABLE:
-		bfa_ioc_hw_sem_get_cancel(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
-		bfa_ioc_pf_disabled(ioc);
-		break;
-
-	case IOCPF_E_STOP:
-		bfa_ioc_hw_sem_get_cancel(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-/**
- * Notify enable completion callback
- */
-static void
-bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf *iocpf)
-{
-	/* Call only the first time sm enters fwmismatch state. */
-	if (iocpf->retry_count == 0)
-		bfa_ioc_pf_fwmismatch(iocpf->ioc);
-
-	iocpf->retry_count++;
-	mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
-		msecs_to_jiffies(BFA_IOC_TOV));
-}
-
-/**
- * Awaiting firmware version match.
- */
-static void
-bfa_iocpf_sm_mismatch(struct bfa_iocpf *iocpf, enum iocpf_event event)
-{
-	struct bfa_ioc *ioc = iocpf->ioc;
-
-	switch (event) {
-	case IOCPF_E_TIMEOUT:
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
-		break;
-
-	case IOCPF_E_DISABLE:
-		del_timer(&ioc->iocpf_timer);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
-		bfa_ioc_pf_disabled(ioc);
-		break;
-
-	case IOCPF_E_STOP:
-		del_timer(&ioc->iocpf_timer);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-/**
- * Request for semaphore.
- */
-static void
-bfa_iocpf_sm_semwait_entry(struct bfa_iocpf *iocpf)
-{
-	bfa_ioc_hw_sem_get(iocpf->ioc);
-}
-
-/**
- * Awaiting semaphore for h/w initialzation.
- */
-static void
-bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event)
-{
-	struct bfa_ioc *ioc = iocpf->ioc;
-
-	switch (event) {
-	case IOCPF_E_SEMLOCKED:
-		if (bfa_ioc_sync_complete(ioc)) {
-			bfa_ioc_sync_join(ioc);
-			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
-		} else {
-			bfa_nw_ioc_hw_sem_release(ioc);
-			mod_timer(&ioc->sem_timer, jiffies +
-				msecs_to_jiffies(BFA_IOC_HWSEM_TOV));
-		}
-		break;
-
-	case IOCPF_E_DISABLE:
-		bfa_ioc_hw_sem_get_cancel(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf *iocpf)
-{
-	mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
-		msecs_to_jiffies(BFA_IOC_TOV));
-	bfa_ioc_reset(iocpf->ioc, 0);
-}
-
-/**
- * Hardware is being initialized. Interrupts are enabled.
- * Holding hardware semaphore lock.
- */
-static void
-bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event)
-{
-	struct bfa_ioc *ioc = iocpf->ioc;
-
-	switch (event) {
-	case IOCPF_E_FWREADY:
-		del_timer(&ioc->iocpf_timer);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
-		break;
-
-	case IOCPF_E_INITFAIL:
-		del_timer(&ioc->iocpf_timer);
-		/*
-		 * !!! fall through !!!
-		 */
-
-	case IOCPF_E_TIMEOUT:
-		bfa_nw_ioc_hw_sem_release(ioc);
-		if (event == IOCPF_E_TIMEOUT)
-			bfa_ioc_pf_failed(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
-		break;
-
-	case IOCPF_E_DISABLE:
-		del_timer(&ioc->iocpf_timer);
-		bfa_ioc_sync_leave(ioc);
-		bfa_nw_ioc_hw_sem_release(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bfa_iocpf_sm_enabling_entry(struct bfa_iocpf *iocpf)
-{
-	mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
-		msecs_to_jiffies(BFA_IOC_TOV));
-	bfa_ioc_send_enable(iocpf->ioc);
-}
-
-/**
- * Host IOC function is being enabled, awaiting response from firmware.
- * Semaphore is acquired.
- */
-static void
-bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
-{
-	struct bfa_ioc *ioc = iocpf->ioc;
-
-	switch (event) {
-	case IOCPF_E_FWRSP_ENABLE:
-		del_timer(&ioc->iocpf_timer);
-		bfa_nw_ioc_hw_sem_release(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);
-		break;
-
-	case IOCPF_E_INITFAIL:
-		del_timer(&ioc->iocpf_timer);
-		/*
-		 * !!! fall through !!!
-		 */
-	case IOCPF_E_TIMEOUT:
-		bfa_nw_ioc_hw_sem_release(ioc);
-		if (event == IOCPF_E_TIMEOUT)
-			bfa_ioc_pf_failed(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
-		break;
-
-	case IOCPF_E_DISABLE:
-		del_timer(&ioc->iocpf_timer);
-		bfa_nw_ioc_hw_sem_release(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
-		break;
-
-	case IOCPF_E_FWREADY:
-		bfa_ioc_send_enable(ioc);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static bool
-bfa_nw_ioc_is_operational(struct bfa_ioc *ioc)
-{
-	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
-}
-
-static void
-bfa_iocpf_sm_ready_entry(struct bfa_iocpf *iocpf)
-{
-	bfa_ioc_pf_enabled(iocpf->ioc);
-}
-
-static void
-bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event)
-{
-	struct bfa_ioc *ioc = iocpf->ioc;
-
-	switch (event) {
-	case IOCPF_E_DISABLE:
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
-		break;
-
-	case IOCPF_E_GETATTRFAIL:
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
-		break;
-
-	case IOCPF_E_FAIL:
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
-		break;
-
-	case IOCPF_E_FWREADY:
-		bfa_ioc_pf_failed(ioc);
-		if (bfa_nw_ioc_is_operational(ioc))
-			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
-		else
-			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bfa_iocpf_sm_disabling_entry(struct bfa_iocpf *iocpf)
-{
-	mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
-		msecs_to_jiffies(BFA_IOC_TOV));
-	bfa_ioc_send_disable(iocpf->ioc);
-}
-
-/**
- * IOC is being disabled
- */
-static void
-bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
-{
-	struct bfa_ioc *ioc = iocpf->ioc;
-
-	switch (event) {
-	case IOCPF_E_FWRSP_DISABLE:
-	case IOCPF_E_FWREADY:
-		del_timer(&ioc->iocpf_timer);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
-		break;
-
-	case IOCPF_E_FAIL:
-		del_timer(&ioc->iocpf_timer);
-		/*
-		 * !!! fall through !!!
-		 */
-
-	case IOCPF_E_TIMEOUT:
-		writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
-		break;
-
-	case IOCPF_E_FWRSP_ENABLE:
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bfa_iocpf_sm_disabling_sync_entry(struct bfa_iocpf *iocpf)
-{
-	bfa_ioc_hw_sem_get(iocpf->ioc);
-}
-
-/**
- * IOC hb ack request is being removed.
- */
-static void
-bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
-{
-	struct bfa_ioc *ioc = iocpf->ioc;
-
-	switch (event) {
-	case IOCPF_E_SEMLOCKED:
-		bfa_ioc_sync_leave(ioc);
-		bfa_nw_ioc_hw_sem_release(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
-		break;
-
-	case IOCPF_E_FAIL:
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-/**
- * IOC disable completion entry.
- */
-static void
-bfa_iocpf_sm_disabled_entry(struct bfa_iocpf *iocpf)
-{
-	bfa_ioc_mbox_flush(iocpf->ioc);
-	bfa_ioc_pf_disabled(iocpf->ioc);
-}
-
-static void
-bfa_iocpf_sm_disabled(struct bfa_iocpf *iocpf, enum iocpf_event event)
-{
-	struct bfa_ioc *ioc = iocpf->ioc;
-
-	switch (event) {
-	case IOCPF_E_ENABLE:
-		iocpf->retry_count = 0;
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
-		break;
-
-	case IOCPF_E_STOP:
-		bfa_ioc_firmware_unlock(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf *iocpf)
-{
-	bfa_ioc_hw_sem_get(iocpf->ioc);
-}
-
-/**
- * Hardware initialization failed.
- */
-static void
-bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
-{
-	struct bfa_ioc *ioc = iocpf->ioc;
-
-	switch (event) {
-	case IOCPF_E_SEMLOCKED:
-		bfa_ioc_notify_fail(ioc);
-		bfa_ioc_sync_ack(ioc);
-		iocpf->retry_count++;
-		if (iocpf->retry_count >= BFA_IOC_HWINIT_MAX) {
-			bfa_ioc_sync_leave(ioc);
-			bfa_nw_ioc_hw_sem_release(ioc);
-			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
-		} else {
-			if (bfa_ioc_sync_complete(ioc))
-				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
-			else {
-				bfa_nw_ioc_hw_sem_release(ioc);
-				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
-			}
-		}
-		break;
-
-	case IOCPF_E_DISABLE:
-		bfa_ioc_hw_sem_get_cancel(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
-		break;
-
-	case IOCPF_E_STOP:
-		bfa_ioc_hw_sem_get_cancel(ioc);
-		bfa_ioc_firmware_unlock(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
-		break;
-
-	case IOCPF_E_FAIL:
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bfa_iocpf_sm_initfail_entry(struct bfa_iocpf *iocpf)
-{
-	bfa_ioc_pf_initfailed(iocpf->ioc);
-}
-
-/**
- * Hardware initialization failed.
- */
-static void
-bfa_iocpf_sm_initfail(struct bfa_iocpf *iocpf, enum iocpf_event event)
-{
-	struct bfa_ioc *ioc = iocpf->ioc;
-
-	switch (event) {
-	case IOCPF_E_DISABLE:
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
-		break;
-
-	case IOCPF_E_STOP:
-		bfa_ioc_firmware_unlock(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf *iocpf)
-{
-	/**
-	 * Mark IOC as failed in hardware and stop firmware.
-	 */
-	bfa_ioc_lpu_stop(iocpf->ioc);
-
-	/**
-	 * Flush any queued up mailbox requests.
-	 */
-	bfa_ioc_mbox_flush(iocpf->ioc);
-	bfa_ioc_hw_sem_get(iocpf->ioc);
-}
-
-/**
- * IOC is in failed state.
- */
-static void
-bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
-{
-	struct bfa_ioc *ioc = iocpf->ioc;
-
-	switch (event) {
-	case IOCPF_E_SEMLOCKED:
-		iocpf->retry_count = 0;
-		bfa_ioc_sync_ack(ioc);
-		bfa_ioc_notify_fail(ioc);
-		if (!iocpf->auto_recover) {
-			bfa_ioc_sync_leave(ioc);
-			bfa_nw_ioc_hw_sem_release(ioc);
-			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
-		} else {
-			if (bfa_ioc_sync_complete(ioc))
-				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
-			else {
-				bfa_nw_ioc_hw_sem_release(ioc);
-				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
-			}
-		}
-		break;
-
-	case IOCPF_E_DISABLE:
-		bfa_ioc_hw_sem_get_cancel(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
-		break;
-
-	case IOCPF_E_FAIL:
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bfa_iocpf_sm_fail_entry(struct bfa_iocpf *iocpf)
-{
-}
-
-/**
- * @brief
- * IOC is in failed state.
- */
-static void
-bfa_iocpf_sm_fail(struct bfa_iocpf *iocpf, enum iocpf_event event)
-{
-	switch (event) {
-	case IOCPF_E_DISABLE:
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-/**
- * BFA IOC private functions
- */
-
-/**
- * Notify common modules registered for notification.
- */
-static void
-bfa_ioc_event_notify(struct bfa_ioc *ioc, enum bfa_ioc_event event)
-{
-	struct bfa_ioc_notify *notify;
-	struct list_head			*qe;
-
-	list_for_each(qe, &ioc->notify_q) {
-		notify = (struct bfa_ioc_notify *)qe;
-		notify->cbfn(notify->cbarg, event);
-	}
-}
-
-static void
-bfa_ioc_disable_comp(struct bfa_ioc *ioc)
-{
-	ioc->cbfn->disable_cbfn(ioc->bfa);
-	bfa_ioc_event_notify(ioc, BFA_IOC_E_DISABLED);
-}
-
-bool
-bfa_nw_ioc_sem_get(void __iomem *sem_reg)
-{
-	u32 r32;
-	int cnt = 0;
-#define BFA_SEM_SPINCNT	3000
-
-	r32 = readl(sem_reg);
-
-	while (r32 && (cnt < BFA_SEM_SPINCNT)) {
-		cnt++;
-		udelay(2);
-		r32 = readl(sem_reg);
-	}
-
-	if (r32 == 0)
-		return true;
-
-	BUG_ON(!(cnt < BFA_SEM_SPINCNT));
-	return false;
-}
-
-void
-bfa_nw_ioc_sem_release(void __iomem *sem_reg)
-{
-	writel(1, sem_reg);
-}
-
-static void
-bfa_ioc_hw_sem_init(struct bfa_ioc *ioc)
-{
-	struct bfi_ioc_image_hdr fwhdr;
-	u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
-
-	if (fwstate == BFI_IOC_UNINIT)
-		return;
-
-	bfa_nw_ioc_fwver_get(ioc, &fwhdr);
-
-	if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL)
-		return;
-
-	writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
-
-	/*
-	 * Try to lock and then unlock the semaphore.
-	 */
-	readl(ioc->ioc_regs.ioc_sem_reg);
-	writel(1, ioc->ioc_regs.ioc_sem_reg);
-}
-
-static void
-bfa_ioc_hw_sem_get(struct bfa_ioc *ioc)
-{
-	u32	r32;
-
-	/**
-	 * First read to the semaphore register will return 0, subsequent reads
-	 * will return 1. Semaphore is released by writing 1 to the register
-	 */
-	r32 = readl(ioc->ioc_regs.ioc_sem_reg);
-	if (r32 == 0) {
-		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
-		return;
-	}
-
-	mod_timer(&ioc->sem_timer, jiffies +
-		msecs_to_jiffies(BFA_IOC_HWSEM_TOV));
-}
-
-void
-bfa_nw_ioc_hw_sem_release(struct bfa_ioc *ioc)
-{
-	writel(1, ioc->ioc_regs.ioc_sem_reg);
-}
-
-static void
-bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc)
-{
-	del_timer(&ioc->sem_timer);
-}
-
-/**
- * @brief
- * Initialize LPU local memory (aka secondary memory / SRAM)
- */
-static void
-bfa_ioc_lmem_init(struct bfa_ioc *ioc)
-{
-	u32	pss_ctl;
-	int		i;
-#define PSS_LMEM_INIT_TIME  10000
-
-	pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
-	pss_ctl &= ~__PSS_LMEM_RESET;
-	pss_ctl |= __PSS_LMEM_INIT_EN;
-
-	/*
-	 * i2c workaround 12.5khz clock
-	 */
-	pss_ctl |= __PSS_I2C_CLK_DIV(3UL);
-	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
-
-	/**
-	 * wait for memory initialization to be complete
-	 */
-	i = 0;
-	do {
-		pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
-		i++;
-	} while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME));
-
-	/**
-	 * If memory initialization is not successful, IOC timeout will catch
-	 * such failures.
-	 */
-	BUG_ON(!(pss_ctl & __PSS_LMEM_INIT_DONE));
-
-	pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);
-	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
-}
-
-static void
-bfa_ioc_lpu_start(struct bfa_ioc *ioc)
-{
-	u32	pss_ctl;
-
-	/**
-	 * Take processor out of reset.
-	 */
-	pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
-	pss_ctl &= ~__PSS_LPU0_RESET;
-
-	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
-}
-
-static void
-bfa_ioc_lpu_stop(struct bfa_ioc *ioc)
-{
-	u32	pss_ctl;
-
-	/**
-	 * Put processors in reset.
-	 */
-	pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
-	pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
-
-	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
-}
-
-/**
- * Get driver and firmware versions.
- */
-void
-bfa_nw_ioc_fwver_get(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
-{
-	u32	pgnum;
-	u32	loff = 0;
-	int		i;
-	u32	*fwsig = (u32 *) fwhdr;
-
-	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
-	writel(pgnum, ioc->ioc_regs.host_page_num_fn);
-
-	for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr) / sizeof(u32));
-	     i++) {
-		fwsig[i] =
-			swab32(readl((loff) + (ioc->ioc_regs.smem_page_start)));
-		loff += sizeof(u32);
-	}
-}
-
-/**
- * Returns TRUE if same.
- */
-bool
-bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
-{
-	struct bfi_ioc_image_hdr *drv_fwhdr;
-	int i;
-
-	drv_fwhdr = (struct bfi_ioc_image_hdr *)
-		bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
-
-	for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
-		if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i])
-			return false;
-	}
-
-	return true;
-}
-
-/**
- * Return true if current running version is valid. Firmware signature and
- * execution context (driver/bios) must match.
- */
-static bool
-bfa_ioc_fwver_valid(struct bfa_ioc *ioc, u32 boot_env)
-{
-	struct bfi_ioc_image_hdr fwhdr, *drv_fwhdr;
-
-	bfa_nw_ioc_fwver_get(ioc, &fwhdr);
-	drv_fwhdr = (struct bfi_ioc_image_hdr *)
-		bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
-
-	if (fwhdr.signature != drv_fwhdr->signature)
-		return false;
-
-	if (swab32(fwhdr.param) != boot_env)
-		return false;
-
-	return bfa_nw_ioc_fwver_cmp(ioc, &fwhdr);
-}
-
-/**
- * Conditionally flush any pending message from firmware at start.
- */
-static void
-bfa_ioc_msgflush(struct bfa_ioc *ioc)
-{
-	u32	r32;
-
-	r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
-	if (r32)
-		writel(1, ioc->ioc_regs.lpu_mbox_cmd);
-}
-
-/**
- * @img ioc_init_logic.jpg
- */
-static void
-bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
-{
-	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;
-
-	/**
-	 * check if firmware is valid
-	 */
-	fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
-		false : bfa_ioc_fwver_valid(ioc, boot_env);
-
-	if (!fwvalid) {
-		bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, boot_env);
-		return;
-	}
-
-	/**
-	 * If hardware initialization is in progress (initialized by other IOC),
-	 * just wait for an initialization completion interrupt.
-	 */
-	if (ioc_fwstate == BFI_IOC_INITING) {
-		ioc->cbfn->reset_cbfn(ioc->bfa);
-		return;
-	}
-
-	/**
-	 * If IOC function is disabled and firmware version is same,
-	 * just re-enable IOC.
-	 */
-	if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) {
-		/**
-		 * When using MSI-X any pending firmware ready event should
-		 * be flushed. Otherwise MSI-X interrupts are not delivered.
-		 */
-		bfa_ioc_msgflush(ioc);
-		ioc->cbfn->reset_cbfn(ioc->bfa);
-		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
-		return;
-	}
-
-	/**
-	 * Initialize the h/w for any other states.
-	 */
-	bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, boot_env);
-}
-
-void
-bfa_nw_ioc_timeout(void *ioc_arg)
-{
-	struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg;
-
-	bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
-}
-
-static void
-bfa_ioc_mbox_send(struct bfa_ioc *ioc, void *ioc_msg, int len)
-{
-	u32 *msgp = (u32 *) ioc_msg;
-	u32 i;
-
-	BUG_ON(!(len <= BFI_IOC_MSGLEN_MAX));
-
-	/*
-	 * first write msg to mailbox registers
-	 */
-	for (i = 0; i < len / sizeof(u32); i++)
-		writel(cpu_to_le32(msgp[i]),
-			      ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
-
-	for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++)
-		writel(0, ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
-
-	/*
-	 * write 1 to mailbox CMD to trigger LPU event
-	 */
-	writel(1, ioc->ioc_regs.hfn_mbox_cmd);
-	(void) readl(ioc->ioc_regs.hfn_mbox_cmd);
-}
-
-static void
-bfa_ioc_send_enable(struct bfa_ioc *ioc)
-{
-	struct bfi_ioc_ctrl_req enable_req;
-	struct timeval tv;
-
-	bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
-		    bfa_ioc_portid(ioc));
-	enable_req.ioc_class = ioc->ioc_mc;
-	do_gettimeofday(&tv);
-	enable_req.tv_sec = ntohl(tv.tv_sec);
-	bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req));
-}
-
-static void
-bfa_ioc_send_disable(struct bfa_ioc *ioc)
-{
-	struct bfi_ioc_ctrl_req disable_req;
-
-	bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ,
-		    bfa_ioc_portid(ioc));
-	bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req));
-}
-
-static void
-bfa_ioc_send_getattr(struct bfa_ioc *ioc)
-{
-	struct bfi_ioc_getattr_req attr_req;
-
-	bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
-		    bfa_ioc_portid(ioc));
-	bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa);
-	bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req));
-}
-
-void
-bfa_nw_ioc_hb_check(void *cbarg)
-{
-	struct bfa_ioc *ioc = cbarg;
-	u32	hb_count;
-
-	hb_count = readl(ioc->ioc_regs.heartbeat);
-	if (ioc->hb_count == hb_count) {
-		bfa_ioc_recover(ioc);
-		return;
-	} else {
-		ioc->hb_count = hb_count;
-	}
-
-	bfa_ioc_mbox_poll(ioc);
-	mod_timer(&ioc->hb_timer, jiffies +
-		msecs_to_jiffies(BFA_IOC_HB_TOV));
-}
-
-static void
-bfa_ioc_hb_monitor(struct bfa_ioc *ioc)
-{
-	ioc->hb_count = readl(ioc->ioc_regs.heartbeat);
-	mod_timer(&ioc->hb_timer, jiffies +
-		msecs_to_jiffies(BFA_IOC_HB_TOV));
-}
-
-static void
-bfa_ioc_hb_stop(struct bfa_ioc *ioc)
-{
-	del_timer(&ioc->hb_timer);
-}
-
-/**
- * @brief
- *	Initiate a full firmware download.
- */
-static void
-bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
-		    u32 boot_env)
-{
-	u32 *fwimg;
-	u32 pgnum;
-	u32 loff = 0;
-	u32 chunkno = 0;
-	u32 i;
-
-	/**
-	 * Initialize LMEM first before code download
-	 */
-	bfa_ioc_lmem_init(ioc);
-
-	fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
-
-	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
-
-	writel(pgnum, ioc->ioc_regs.host_page_num_fn);
-
-	for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
-		if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
-			chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
-			fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
-					BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
-		}
-
-		/**
-		 * write smem
-		 */
-		writel((swab32(fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)])),
-			      ((ioc->ioc_regs.smem_page_start) + (loff)));
-
-		loff += sizeof(u32);
-
-		/**
-		 * handle page offset wrap around
-		 */
-		loff = PSS_SMEM_PGOFF(loff);
-		if (loff == 0) {
-			pgnum++;
-			writel(pgnum,
-				      ioc->ioc_regs.host_page_num_fn);
-		}
-	}
-
-	writel(bfa_ioc_smem_pgnum(ioc, 0),
-		      ioc->ioc_regs.host_page_num_fn);
-
-	/*
-	 * Set boot type and boot param at the end.
-	*/
-	writel(boot_type, ((ioc->ioc_regs.smem_page_start)
-			+ (BFI_BOOT_TYPE_OFF)));
-	writel(boot_env, ((ioc->ioc_regs.smem_page_start)
-			+ (BFI_BOOT_LOADER_OFF)));
-}
-
-static void
-bfa_ioc_reset(struct bfa_ioc *ioc, bool force)
-{
-	bfa_ioc_hwinit(ioc, force);
-}
-
-/**
- * @brief
- * Update BFA configuration from firmware configuration.
- */
-static void
-bfa_ioc_getattr_reply(struct bfa_ioc *ioc)
-{
-	struct bfi_ioc_attr *attr = ioc->attr;
-
-	attr->adapter_prop  = ntohl(attr->adapter_prop);
-	attr->card_type     = ntohl(attr->card_type);
-	attr->maxfrsize	    = ntohs(attr->maxfrsize);
-
-	bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
-}
-
-/**
- * Attach time initialization of mbox logic.
- */
-static void
-bfa_ioc_mbox_attach(struct bfa_ioc *ioc)
-{
-	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
-	int	mc;
-
-	INIT_LIST_HEAD(&mod->cmd_q);
-	for (mc = 0; mc < BFI_MC_MAX; mc++) {
-		mod->mbhdlr[mc].cbfn = NULL;
-		mod->mbhdlr[mc].cbarg = ioc->bfa;
-	}
-}
-
-/**
- * Mbox poll timer -- restarts any pending mailbox requests.
- */
-static void
-bfa_ioc_mbox_poll(struct bfa_ioc *ioc)
-{
-	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
-	struct bfa_mbox_cmd *cmd;
-	u32			stat;
-
-	/**
-	 * If no command pending, do nothing
-	 */
-	if (list_empty(&mod->cmd_q))
-		return;
-
-	/**
-	 * If previous command is not yet fetched by firmware, do nothing
-	 */
-	stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
-	if (stat)
-		return;
-
-	/**
-	 * Enqueue command to firmware.
-	 */
-	bfa_q_deq(&mod->cmd_q, &cmd);
-	bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
-}
-
-/**
- * Cleanup any pending requests.
- */
-static void
-bfa_ioc_mbox_flush(struct bfa_ioc *ioc)
-{
-	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
-	struct bfa_mbox_cmd *cmd;
-
-	while (!list_empty(&mod->cmd_q))
-		bfa_q_deq(&mod->cmd_q, &cmd);
-}
-
-static void
-bfa_ioc_fail_notify(struct bfa_ioc *ioc)
-{
-	/**
-	 * Notify driver and common modules registered for notification.
-	 */
-	ioc->cbfn->hbfail_cbfn(ioc->bfa);
-	bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED);
-}
-
-static void
-bfa_ioc_pf_enabled(struct bfa_ioc *ioc)
-{
-	bfa_fsm_send_event(ioc, IOC_E_ENABLED);
-}
-
-static void
-bfa_ioc_pf_disabled(struct bfa_ioc *ioc)
-{
-	bfa_fsm_send_event(ioc, IOC_E_DISABLED);
-}
-
-static void
-bfa_ioc_pf_initfailed(struct bfa_ioc *ioc)
-{
-	bfa_fsm_send_event(ioc, IOC_E_INITFAILED);
-}
-
-static void
-bfa_ioc_pf_failed(struct bfa_ioc *ioc)
-{
-	bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
-}
-
-static void
-bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc)
-{
-	/**
-	 * Provide enable completion callback and AEN notification.
-	 */
-	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-}
-
-/**
- * IOC public
- */
-static enum bfa_status
-bfa_ioc_pll_init(struct bfa_ioc *ioc)
-{
-	/*
-	 *  Hold semaphore so that nobody can access the chip during init.
-	 */
-	bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
-
-	bfa_ioc_pll_init_asic(ioc);
-
-	ioc->pllinit = true;
-	/*
-	 *  release semaphore.
-	 */
-	bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- * Interface used by diag module to do firmware boot with memory test
- * as the entry vector.
- */
-static void
-bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_env)
-{
-	void __iomem *rb;
-
-	bfa_ioc_stats(ioc, ioc_boots);
-
-	if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
-		return;
-
-	/**
-	 * Initialize IOC state of all functions on a chip reset.
-	 */
-	rb = ioc->pcidev.pci_bar_kva;
-	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 {
-		writel(BFI_IOC_INITING, (rb + BFA_IOC0_STATE_REG));
-		writel(BFI_IOC_INITING, (rb + BFA_IOC1_STATE_REG));
-	}
-
-	bfa_ioc_msgflush(ioc);
-	bfa_ioc_download_fw(ioc, boot_type, boot_env);
-
-	/**
-	 * Enable interrupts just before starting LPU
-	 */
-	ioc->cbfn->reset_cbfn(ioc->bfa);
-	bfa_ioc_lpu_start(ioc);
-}
-
-/**
- * Enable/disable IOC failure auto recovery.
- */
-void
-bfa_nw_ioc_auto_recover(bool auto_recover)
-{
-	bfa_nw_auto_recover = auto_recover;
-}
-
-static void
-bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg)
-{
-	u32	*msgp = mbmsg;
-	u32	r32;
-	int		i;
-
-	/**
-	 * read the MBOX msg
-	 */
-	for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32));
-	     i++) {
-		r32 = readl(ioc->ioc_regs.lpu_mbox +
-				   i * sizeof(u32));
-		msgp[i] = htonl(r32);
-	}
-
-	/**
-	 * turn off mailbox interrupt by clearing mailbox status
-	 */
-	writel(1, ioc->ioc_regs.lpu_mbox_cmd);
-	readl(ioc->ioc_regs.lpu_mbox_cmd);
-}
-
-static void
-bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m)
-{
-	union bfi_ioc_i2h_msg_u	*msg;
-	struct bfa_iocpf *iocpf = &ioc->iocpf;
-
-	msg = (union bfi_ioc_i2h_msg_u *) m;
-
-	bfa_ioc_stats(ioc, ioc_isrs);
-
-	switch (msg->mh.msg_id) {
-	case BFI_IOC_I2H_HBEAT:
-		break;
-
-	case BFI_IOC_I2H_READY_EVENT:
-		bfa_fsm_send_event(iocpf, IOCPF_E_FWREADY);
-		break;
-
-	case BFI_IOC_I2H_ENABLE_REPLY:
-		bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
-		break;
-
-	case BFI_IOC_I2H_DISABLE_REPLY:
-		bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_DISABLE);
-		break;
-
-	case BFI_IOC_I2H_GETATTR_REPLY:
-		bfa_ioc_getattr_reply(ioc);
-		break;
-
-	default:
-		BUG_ON(1);
-	}
-}
-
-/**
- * IOC attach time initialization and setup.
- *
- * @param[in]	ioc	memory for IOC
- * @param[in]	bfa	driver instance structure
- */
-void
-bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn)
-{
-	ioc->bfa	= bfa;
-	ioc->cbfn	= cbfn;
-	ioc->fcmode	= false;
-	ioc->pllinit	= false;
-	ioc->dbg_fwsave_once = true;
-	ioc->iocpf.ioc  = ioc;
-
-	bfa_ioc_mbox_attach(ioc);
-	INIT_LIST_HEAD(&ioc->notify_q);
-
-	bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
-	bfa_fsm_send_event(ioc, IOC_E_RESET);
-}
-
-/**
- * Driver detach time IOC cleanup.
- */
-void
-bfa_nw_ioc_detach(struct bfa_ioc *ioc)
-{
-	bfa_fsm_send_event(ioc, IOC_E_DETACH);
-}
-
-/**
- * Setup IOC PCI properties.
- *
- * @param[in]	pcidev	PCI device information for this IOC
- */
-void
-bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
-		 enum bfi_mclass mc)
-{
-	ioc->ioc_mc	= mc;
-	ioc->pcidev	= *pcidev;
-	ioc->ctdev	= bfa_asic_id_ct(ioc->pcidev.device_id);
-	ioc->cna	= ioc->ctdev && !ioc->fcmode;
-
-	bfa_nw_ioc_set_ct_hwif(ioc);
-
-	bfa_ioc_map_port(ioc);
-	bfa_ioc_reg_init(ioc);
-}
-
-/**
- * Initialize IOC dma memory
- *
- * @param[in]	dm_kva	kernel virtual address of IOC dma memory
- * @param[in]	dm_pa	physical address of IOC dma memory
- */
-void
-bfa_nw_ioc_mem_claim(struct bfa_ioc *ioc,  u8 *dm_kva, u64 dm_pa)
-{
-	/**
-	 * dma memory for firmware attribute
-	 */
-	ioc->attr_dma.kva = dm_kva;
-	ioc->attr_dma.pa = dm_pa;
-	ioc->attr = (struct bfi_ioc_attr *) dm_kva;
-}
-
-/**
- * Return size of dma memory required.
- */
-u32
-bfa_nw_ioc_meminfo(void)
-{
-	return roundup(sizeof(struct bfi_ioc_attr), BFA_DMA_ALIGN_SZ);
-}
-
-void
-bfa_nw_ioc_enable(struct bfa_ioc *ioc)
-{
-	bfa_ioc_stats(ioc, ioc_enables);
-	ioc->dbg_fwsave_once = true;
-
-	bfa_fsm_send_event(ioc, IOC_E_ENABLE);
-}
-
-void
-bfa_nw_ioc_disable(struct bfa_ioc *ioc)
-{
-	bfa_ioc_stats(ioc, ioc_disables);
-	bfa_fsm_send_event(ioc, IOC_E_DISABLE);
-}
-
-static u32
-bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr)
-{
-	return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr);
-}
-
-/**
- * Register mailbox message handler function, to be called by common modules
- */
-void
-bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
-		    bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
-{
-	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
-
-	mod->mbhdlr[mc].cbfn	= cbfn;
-	mod->mbhdlr[mc].cbarg = cbarg;
-}
-
-/**
- * Queue a mailbox command request to firmware. Waits if mailbox is busy.
- * Responsibility of caller to serialize
- *
- * @param[in]	ioc	IOC instance
- * @param[i]	cmd	Mailbox command
- */
-void
-bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd)
-{
-	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
-	u32			stat;
-
-	/**
-	 * If a previous command is pending, queue new command
-	 */
-	if (!list_empty(&mod->cmd_q)) {
-		list_add_tail(&cmd->qe, &mod->cmd_q);
-		return;
-	}
-
-	/**
-	 * If mailbox is busy, queue command for poll timer
-	 */
-	stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
-	if (stat) {
-		list_add_tail(&cmd->qe, &mod->cmd_q);
-		return;
-	}
-
-	/**
-	 * mailbox is free -- queue command to firmware
-	 */
-	bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
-
-	return;
-}
-
-/**
- * Handle mailbox interrupts
- */
-void
-bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc)
-{
-	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
-	struct bfi_mbmsg m;
-	int				mc;
-
-	bfa_ioc_msgget(ioc, &m);
-
-	/**
-	 * Treat IOC message class as special.
-	 */
-	mc = m.mh.msg_class;
-	if (mc == BFI_MC_IOC) {
-		bfa_ioc_isr(ioc, &m);
-		return;
-	}
-
-	if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
-		return;
-
-	mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
-}
-
-void
-bfa_nw_ioc_error_isr(struct bfa_ioc *ioc)
-{
-	bfa_ioc_stats(ioc, ioc_hbfails);
-	bfa_ioc_stats_hb_count(ioc, ioc->hb_count);
-	bfa_fsm_send_event(ioc, IOC_E_HWERROR);
-}
-
-/**
- * return true if IOC is disabled
- */
-bool
-bfa_nw_ioc_is_disabled(struct bfa_ioc *ioc)
-{
-	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) ||
-		bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
-}
-
-/**
- * Add to IOC heartbeat failure notification queue. To be used by common
- * modules such as cee, port, diag.
- */
-void
-bfa_nw_ioc_notify_register(struct bfa_ioc *ioc,
-			struct bfa_ioc_notify *notify)
-{
-	list_add_tail(&notify->qe, &ioc->notify_q);
-}
-
-#define BFA_MFG_NAME "Brocade"
-static void
-bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc,
-			 struct bfa_adapter_attr *ad_attr)
-{
-	struct bfi_ioc_attr *ioc_attr;
-
-	ioc_attr = ioc->attr;
-
-	bfa_ioc_get_adapter_serial_num(ioc, ad_attr->serial_num);
-	bfa_ioc_get_adapter_fw_ver(ioc, ad_attr->fw_ver);
-	bfa_ioc_get_adapter_optrom_ver(ioc, ad_attr->optrom_ver);
-	bfa_ioc_get_adapter_manufacturer(ioc, ad_attr->manufacturer);
-	memcpy(&ad_attr->vpd, &ioc_attr->vpd,
-		      sizeof(struct bfa_mfg_vpd));
-
-	ad_attr->nports = bfa_ioc_get_nports(ioc);
-	ad_attr->max_speed = bfa_ioc_speed_sup(ioc);
-
-	bfa_ioc_get_adapter_model(ioc, ad_attr->model);
-	/* For now, model descr uses same model string */
-	bfa_ioc_get_adapter_model(ioc, ad_attr->model_descr);
-
-	ad_attr->card_type = ioc_attr->card_type;
-	ad_attr->is_mezz = bfa_mfg_is_mezz(ioc_attr->card_type);
-
-	if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop))
-		ad_attr->prototype = 1;
-	else
-		ad_attr->prototype = 0;
-
-	ad_attr->pwwn = bfa_ioc_get_pwwn(ioc);
-	ad_attr->mac  = bfa_nw_ioc_get_mac(ioc);
-
-	ad_attr->pcie_gen = ioc_attr->pcie_gen;
-	ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
-	ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig;
-	ad_attr->asic_rev = ioc_attr->asic_rev;
-
-	bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
-
-	ad_attr->cna_capable = ioc->cna;
-	ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna;
-}
-
-static enum bfa_ioc_type
-bfa_ioc_get_type(struct bfa_ioc *ioc)
-{
-	if (!ioc->ctdev || ioc->fcmode)
-		return BFA_IOC_TYPE_FC;
-	else if (ioc->ioc_mc == BFI_MC_IOCFC)
-		return BFA_IOC_TYPE_FCoE;
-	else if (ioc->ioc_mc == BFI_MC_LL)
-		return BFA_IOC_TYPE_LL;
-	else {
-		BUG_ON(!(ioc->ioc_mc == BFI_MC_LL));
-		return BFA_IOC_TYPE_LL;
-	}
-}
-
-static void
-bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num)
-{
-	memset(serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN);
-	memcpy(serial_num,
-			(void *)ioc->attr->brcd_serialnum,
-			BFA_ADAPTER_SERIAL_NUM_LEN);
-}
-
-static void
-bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc, char *fw_ver)
-{
-	memset(fw_ver, 0, BFA_VERSION_LEN);
-	memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN);
-}
-
-static void
-bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc, char *chip_rev)
-{
-	BUG_ON(!(chip_rev));
-
-	memset(chip_rev, 0, BFA_IOC_CHIP_REV_LEN);
-
-	chip_rev[0] = 'R';
-	chip_rev[1] = 'e';
-	chip_rev[2] = 'v';
-	chip_rev[3] = '-';
-	chip_rev[4] = ioc->attr->asic_rev;
-	chip_rev[5] = '\0';
-}
-
-static void
-bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver)
-{
-	memset(optrom_ver, 0, BFA_VERSION_LEN);
-	memcpy(optrom_ver, ioc->attr->optrom_version,
-		      BFA_VERSION_LEN);
-}
-
-static void
-bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, char *manufacturer)
-{
-	memset(manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN);
-	memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
-}
-
-static void
-bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model)
-{
-	struct bfi_ioc_attr *ioc_attr;
-
-	BUG_ON(!(model));
-	memset(model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
-
-	ioc_attr = ioc->attr;
-
-	/**
-	 * model name
-	 */
-	snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
-		BFA_MFG_NAME, ioc_attr->card_type);
-}
-
-static enum bfa_ioc_state
-bfa_ioc_get_state(struct bfa_ioc *ioc)
-{
-	enum bfa_iocpf_state iocpf_st;
-	enum bfa_ioc_state ioc_st = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
-
-	if (ioc_st == BFA_IOC_ENABLING ||
-		ioc_st == BFA_IOC_FAIL || ioc_st == BFA_IOC_INITFAIL) {
-
-		iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
-
-		switch (iocpf_st) {
-		case BFA_IOCPF_SEMWAIT:
-			ioc_st = BFA_IOC_SEMWAIT;
-			break;
-
-		case BFA_IOCPF_HWINIT:
-			ioc_st = BFA_IOC_HWINIT;
-			break;
-
-		case BFA_IOCPF_FWMISMATCH:
-			ioc_st = BFA_IOC_FWMISMATCH;
-			break;
-
-		case BFA_IOCPF_FAIL:
-			ioc_st = BFA_IOC_FAIL;
-			break;
-
-		case BFA_IOCPF_INITFAIL:
-			ioc_st = BFA_IOC_INITFAIL;
-			break;
-
-		default:
-			break;
-		}
-	}
-	return ioc_st;
-}
-
-void
-bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr)
-{
-	memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr));
-
-	ioc_attr->state = bfa_ioc_get_state(ioc);
-	ioc_attr->port_id = ioc->port_id;
-
-	ioc_attr->ioc_type = bfa_ioc_get_type(ioc);
-
-	bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
-
-	ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
-	ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
-	bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);
-}
-
-/**
- * WWN public
- */
-static u64
-bfa_ioc_get_pwwn(struct bfa_ioc *ioc)
-{
-	return ioc->attr->pwwn;
-}
-
-mac_t
-bfa_nw_ioc_get_mac(struct bfa_ioc *ioc)
-{
-	return ioc->attr->mac;
-}
-
-/**
- * Firmware failure detected. Start recovery actions.
- */
-static void
-bfa_ioc_recover(struct bfa_ioc *ioc)
-{
-	pr_crit("Heart Beat of IOC has failed\n");
-	bfa_ioc_stats(ioc, ioc_hbfails);
-	bfa_ioc_stats_hb_count(ioc, ioc->hb_count);
-	bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
-}
-
-static void
-bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc)
-{
-	if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
-		return;
-}
-
-/**
- * @dg hal_iocpf_pvt BFA IOC PF private functions
- * @{
- */
-
-static void
-bfa_iocpf_enable(struct bfa_ioc *ioc)
-{
-	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
-}
-
-static void
-bfa_iocpf_disable(struct bfa_ioc *ioc)
-{
-	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
-}
-
-static void
-bfa_iocpf_fail(struct bfa_ioc *ioc)
-{
-	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
-}
-
-static void
-bfa_iocpf_initfail(struct bfa_ioc *ioc)
-{
-	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
-}
-
-static void
-bfa_iocpf_getattrfail(struct bfa_ioc *ioc)
-{
-	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
-}
-
-static void
-bfa_iocpf_stop(struct bfa_ioc *ioc)
-{
-	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
-}
-
-void
-bfa_nw_iocpf_timeout(void *ioc_arg)
-{
-	struct bfa_ioc  *ioc = (struct bfa_ioc *) ioc_arg;
-
-	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
-}
-
-void
-bfa_nw_iocpf_sem_timeout(void *ioc_arg)
-{
-	struct bfa_ioc  *ioc = (struct bfa_ioc *) ioc_arg;
-
-	bfa_ioc_hw_sem_get(ioc);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bfa_ioc_ct.c linux-libre-3.2-gnu/drivers/net/bna/bfa_ioc_ct.c
--- linux-libre-3.1-gnu/drivers/net/bna/bfa_ioc_ct.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bfa_ioc_ct.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,516 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-#include "bfa_ioc.h"
-#include "cna.h"
-#include "bfi.h"
-#include "bfi_ctreg.h"
-#include "bfa_defs.h"
-
-#define bfa_ioc_ct_sync_pos(__ioc)	\
-		((u32) (1 << bfa_ioc_pcifn(__ioc)))
-#define BFA_IOC_SYNC_REQD_SH		16
-#define bfa_ioc_ct_get_sync_ackd(__val) (__val & 0x0000ffff)
-#define bfa_ioc_ct_clear_sync_ackd(__val) (__val & 0xffff0000)
-#define bfa_ioc_ct_get_sync_reqd(__val) (__val >> BFA_IOC_SYNC_REQD_SH)
-#define bfa_ioc_ct_sync_reqd_pos(__ioc) \
-		(bfa_ioc_ct_sync_pos(__ioc) << BFA_IOC_SYNC_REQD_SH)
-
-/*
- * forward declarations
- */
-static bool bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc);
-static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc);
-static void bfa_ioc_ct_reg_init(struct bfa_ioc *ioc);
-static void bfa_ioc_ct_map_port(struct bfa_ioc *ioc);
-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);
-static bool bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc);
-static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode);
-
-static struct bfa_ioc_hwif nw_hwif_ct;
-
-/**
- * Called from bfa_ioc_attach() to map asic specific calls.
- */
-void
-bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc)
-{
-	nw_hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init;
-	nw_hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock;
-	nw_hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock;
-	nw_hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init;
-	nw_hwif_ct.ioc_map_port = bfa_ioc_ct_map_port;
-	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;
-	nw_hwif_ct.ioc_sync_complete = bfa_ioc_ct_sync_complete;
-
-	ioc->ioc_hwif = &nw_hwif_ct;
-}
-
-/**
- * Return true if firmware of current driver matches the running firmware.
- */
-static bool
-bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc)
-{
-	enum bfi_ioc_state ioc_fwstate;
-	u32 usecnt;
-	struct bfi_ioc_image_hdr fwhdr;
-
-	/**
-	 * Firmware match check is relevant only for CNA.
-	 */
-	if (!ioc->cna)
-		return true;
-
-	/**
-	 * If bios boot (flash based) -- do not increment usage count
-	 */
-	if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
-						BFA_IOC_FWIMG_MINSZ)
-		return true;
-
-	bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
-	usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
-
-	/**
-	 * If usage count is 0, always return TRUE.
-	 */
-	if (usecnt == 0) {
-		writel(1, ioc->ioc_regs.ioc_usage_reg);
-		bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
-		writel(0, ioc->ioc_regs.ioc_fail_sync);
-		return true;
-	}
-
-	ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
-
-	/**
-	 * Use count cannot be non-zero and chip in uninitialized state.
-	 */
-	BUG_ON(!(ioc_fwstate != BFI_IOC_UNINIT));
-
-	/**
-	 * Check if another driver with a different firmware is active
-	 */
-	bfa_nw_ioc_fwver_get(ioc, &fwhdr);
-	if (!bfa_nw_ioc_fwver_cmp(ioc, &fwhdr)) {
-		bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
-		return false;
-	}
-
-	/**
-	 * Same firmware version. Increment the reference count.
-	 */
-	usecnt++;
-	writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
-	bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
-	return true;
-}
-
-static void
-bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc)
-{
-	u32 usecnt;
-
-	/**
-	 * Firmware lock is relevant only for CNA.
-	 */
-	if (!ioc->cna)
-		return;
-
-	/**
-	 * If bios boot (flash based) -- do not decrement usage count
-	 */
-	if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
-						BFA_IOC_FWIMG_MINSZ)
-		return;
-
-	/**
-	 * decrement usage count
-	 */
-	bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
-	usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
-	BUG_ON(!(usecnt > 0));
-
-	usecnt--;
-	writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
-
-	bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
-}
-
-/**
- * Notify other functions on HB failure.
- */
-static void
-bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc)
-{
-	if (ioc->cna) {
-		writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt);
-		writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt);
-		/* Wait for halt to take effect */
-		readl(ioc->ioc_regs.ll_halt);
-		readl(ioc->ioc_regs.alt_ll_halt);
-	} else {
-		writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set);
-		readl(ioc->ioc_regs.err_set);
-	}
-}
-
-/**
- * Host to LPU mailbox message addresses
- */
-static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
-	{ HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },
-	{ HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 },
-	{ HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 },
-	{ HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3 }
-};
-
-/**
- * Host <-> LPU mailbox command/status registers - port 0
- */
-static struct { u32 hfn, lpu; } iocreg_mbcmd_p0[] = {
-	{ HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT },
-	{ HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT },
-	{ HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT },
-	{ HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT }
-};
-
-/**
- * Host <-> LPU mailbox command/status registers - port 1
- */
-static struct { u32 hfn, lpu; } iocreg_mbcmd_p1[] = {
-	{ HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT },
-	{ HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT },
-	{ HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT },
-	{ HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT }
-};
-
-static void
-bfa_ioc_ct_reg_init(struct bfa_ioc *ioc)
-{
-	void __iomem *rb;
-	int		pcifn = bfa_ioc_pcifn(ioc);
-
-	rb = bfa_ioc_bar0(ioc);
-
-	ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox;
-	ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox;
-	ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn;
-
-	if (ioc->port_id == 0) {
-		ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
-		ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
-		ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG;
-		ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn;
-		ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu;
-		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
-		ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1;
-	} else {
-		ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
-		ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
-		ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC0_STATE_REG;
-		ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn;
-		ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu;
-		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
-		ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0;
-	}
-
-	/*
-	 * PSS control registers
-	 */
-	ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
-	ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG);
-	ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG);
-	ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG);
-
-	/*
-	 * IOC semaphore registers and serialization
-	 */
-	ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG);
-	ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG);
-	ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG);
-	ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT);
-	ioc->ioc_regs.ioc_fail_sync = (rb + BFA_IOC_FAIL_SYNC);
-
-	/**
-	 * sram memory access
-	 */
-	ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
-	ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT;
-
-	/*
-	 * err set reg : for notification of hb failure in fcmode
-	 */
-	ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
-}
-
-/**
- * Initialize IOC to port mapping.
- */
-
-#define FNC_PERS_FN_SHIFT(__fn)	((__fn) * 8)
-static void
-bfa_ioc_ct_map_port(struct bfa_ioc *ioc)
-{
-	void __iomem *rb = ioc->pcidev.pci_bar_kva;
-	u32	r32;
-
-	/**
-	 * For catapult, base port id on personality register and IOC type
-	 */
-	r32 = readl(rb + FNC_PERS_REG);
-	r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc));
-	ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH;
-
-}
-
-/**
- * Set interrupt mode for a function: INTX or MSIX
- */
-static void
-bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix)
-{
-	void __iomem *rb = ioc->pcidev.pci_bar_kva;
-	u32	r32, mode;
-
-	r32 = readl(rb + FNC_PERS_REG);
-
-	mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) &
-		__F0_INTX_STATUS;
-
-	/**
-	 * If already in desired mode, do not change anything
-	 */
-	if (!msix && mode)
-		return;
-
-	if (msix)
-		mode = __F0_INTX_STATUS_MSIX;
-	else
-		mode = __F0_INTX_STATUS_INTA;
-
-	r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
-	r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
-
-	writel(r32, rb + FNC_PERS_REG);
-}
-
-/**
- * Cleanup hw semaphore and usecnt registers
- */
-static void
-bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc)
-{
-	if (ioc->cna) {
-		bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
-		writel(0, ioc->ioc_regs.ioc_usage_reg);
-		bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
-	}
-
-	/*
-	 * Read the hw sem reg to make sure that it is locked
-	 * before we clear it. If it is not locked, writing 1
-	 * will lock it instead of clearing it.
-	 */
-	readl(ioc->ioc_regs.ioc_sem_reg);
-	bfa_nw_ioc_hw_sem_release(ioc);
-}
-
-/**
- * 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)
-{
-	u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
-	u32 sync_pos = bfa_ioc_ct_sync_reqd_pos(ioc);
-
-	writel((r32 | sync_pos), ioc->ioc_regs.ioc_fail_sync);
-}
-
-static void
-bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc)
-{
-	u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
-	u32 sync_msk = bfa_ioc_ct_sync_reqd_pos(ioc) |
-					bfa_ioc_ct_sync_pos(ioc);
-
-	writel((r32 & ~sync_msk), ioc->ioc_regs.ioc_fail_sync);
-}
-
-static void
-bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc)
-{
-	u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
-
-	writel((r32 | bfa_ioc_ct_sync_pos(ioc)), ioc->ioc_regs.ioc_fail_sync);
-}
-
-static bool
-bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc)
-{
-	u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
-	u32 sync_reqd = bfa_ioc_ct_get_sync_reqd(r32);
-	u32 sync_ackd = bfa_ioc_ct_get_sync_ackd(r32);
-	u32 tmp_ackd;
-
-	if (sync_ackd == 0)
-		return true;
-
-	/**
-	 * The check below is to see whether any other PCI fn
-	 * has reinitialized the ASIC (reset sync_ackd bits)
-	 * and failed again while this IOC was waiting for hw
-	 * semaphore (in bfa_iocpf_sm_semwait()).
-	 */
-	tmp_ackd = sync_ackd;
-	if ((sync_reqd &  bfa_ioc_ct_sync_pos(ioc)) &&
-			!(sync_ackd & bfa_ioc_ct_sync_pos(ioc)))
-		sync_ackd |= bfa_ioc_ct_sync_pos(ioc);
-
-	if (sync_reqd == sync_ackd) {
-		writel(bfa_ioc_ct_clear_sync_ackd(r32),
-				ioc->ioc_regs.ioc_fail_sync);
-		writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
-		writel(BFI_IOC_FAIL, ioc->ioc_regs.alt_ioc_fwstate);
-		return true;
-	}
-
-	/**
-	 * If another PCI fn reinitialized and failed again while
-	 * this IOC was waiting for hw sem, the sync_ackd bit for
-	 * this IOC need to be set again to allow reinitialization.
-	 */
-	if (tmp_ackd != sync_ackd)
-		writel((r32 | sync_ackd), ioc->ioc_regs.ioc_fail_sync);
-
-	return false;
-}
-
-static enum bfa_status
-bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode)
-{
-	u32	pll_sclk, pll_fclk, r32;
-
-	pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST |
-		__APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) |
-		__APP_PLL_312_JITLMT0_1(3U) |
-		__APP_PLL_312_CNTLMT0_1(1U);
-	pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST |
-		__APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) |
-		__APP_PLL_425_JITLMT0_1(3U) |
-		__APP_PLL_425_CNTLMT0_1(1U);
-	if (fcmode) {
-		writel(0, (rb + OP_MODE));
-		writel(__APP_EMS_CMLCKSEL |
-				__APP_EMS_REFCKBUFEN2 |
-				__APP_EMS_CHANNEL_SEL,
-				(rb + ETH_MAC_SER_REG));
-	} else {
-		writel(__GLOBAL_FCOE_MODE, (rb + OP_MODE));
-		writel(__APP_EMS_REFCKBUFEN1,
-				(rb + ETH_MAC_SER_REG));
-	}
-	writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG));
-	writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG));
-	writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
-	writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
-	writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
-	writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
-	writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
-	writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
-	writel(pll_sclk |
-		__APP_PLL_312_LOGIC_SOFT_RESET,
-		rb + APP_PLL_312_CTL_REG);
-	writel(pll_fclk |
-		__APP_PLL_425_LOGIC_SOFT_RESET,
-		rb + APP_PLL_425_CTL_REG);
-	writel(pll_sclk |
-		__APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE,
-		rb + APP_PLL_312_CTL_REG);
-	writel(pll_fclk |
-		__APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE,
-		rb + APP_PLL_425_CTL_REG);
-	readl(rb + HOSTFN0_INT_MSK);
-	udelay(2000);
-	writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
-	writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
-	writel(pll_sclk |
-		__APP_PLL_312_ENABLE,
-		rb + APP_PLL_312_CTL_REG);
-	writel(pll_fclk |
-		__APP_PLL_425_ENABLE,
-		rb + APP_PLL_425_CTL_REG);
-	if (!fcmode) {
-		writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P0));
-		writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P1));
-	}
-	r32 = readl((rb + PSS_CTL_REG));
-	r32 &= ~__PSS_LMEM_RESET;
-	writel(r32, (rb + PSS_CTL_REG));
-	udelay(1000);
-	if (!fcmode) {
-		writel(0, (rb + PMM_1T_RESET_REG_P0));
-		writel(0, (rb + PMM_1T_RESET_REG_P1));
-	}
-
-	writel(__EDRAM_BISTR_START, (rb + MBIST_CTL_REG));
-	udelay(1000);
-	r32 = readl((rb + MBIST_STAT_REG));
-	writel(0, (rb + MBIST_CTL_REG));
-	return BFA_STATUS_OK;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bfa_ioc.h linux-libre-3.2-gnu/drivers/net/bna/bfa_ioc.h
--- linux-libre-3.1-gnu/drivers/net/bna/bfa_ioc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bfa_ioc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,315 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-#ifndef __BFA_IOC_H__
-#define __BFA_IOC_H__
-
-#include "bfa_cs.h"
-#include "bfi.h"
-#include "cna.h"
-
-#define BFA_IOC_TOV		3000	/* msecs */
-#define BFA_IOC_HWSEM_TOV	500	/* msecs */
-#define BFA_IOC_HB_TOV		500	/* msecs */
-#define BFA_IOC_HWINIT_MAX	5
-
-/**
- * PCI device information required by IOC
- */
-struct bfa_pcidev {
-	int	pci_slot;
-	u8	pci_func;
-	u16	device_id;
-	void	__iomem *pci_bar_kva;
-};
-
-/**
- * Structure used to remember the DMA-able memory block's KVA and Physical
- * Address
- */
-struct bfa_dma {
-	void	*kva;	/* ! Kernel virtual address	*/
-	u64	pa;	/* ! Physical address		*/
-};
-
-#define BFA_DMA_ALIGN_SZ	256
-
-/**
- * smem size for Crossbow and Catapult
- */
-#define BFI_SMEM_CB_SIZE	0x200000U	/* ! 2MB for crossbow	*/
-#define BFI_SMEM_CT_SIZE	0x280000U	/* ! 2.5MB for catapult	*/
-
-/**
- * @brief BFA dma address assignment macro. (big endian format)
- */
-#define bfa_dma_be_addr_set(dma_addr, pa)	\
-		__bfa_dma_be_addr_set(&dma_addr, (u64)pa)
-static inline void
-__bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa)
-{
-	dma_addr->a32.addr_lo = (u32) htonl(pa);
-	dma_addr->a32.addr_hi = (u32) htonl(upper_32_bits(pa));
-}
-
-struct bfa_ioc_regs {
-	void __iomem *hfn_mbox_cmd;
-	void __iomem *hfn_mbox;
-	void __iomem *lpu_mbox_cmd;
-	void __iomem *lpu_mbox;
-	void __iomem *pss_ctl_reg;
-	void __iomem *pss_err_status_reg;
-	void __iomem *app_pll_fast_ctl_reg;
-	void __iomem *app_pll_slow_ctl_reg;
-	void __iomem *ioc_sem_reg;
-	void __iomem *ioc_usage_sem_reg;
-	void __iomem *ioc_init_sem_reg;
-	void __iomem *ioc_usage_reg;
-	void __iomem *host_page_num_fn;
-	void __iomem *heartbeat;
-	void __iomem *ioc_fwstate;
-	void __iomem *alt_ioc_fwstate;
-	void __iomem *ll_halt;
-	void __iomem *alt_ll_halt;
-	void __iomem *err_set;
-	void __iomem *ioc_fail_sync;
-	void __iomem *shirq_isr_next;
-	void __iomem *shirq_msk_next;
-	void __iomem *smem_page_start;
-	u32	smem_pg0;
-};
-
-/**
- * IOC Mailbox structures
- */
-typedef void (*bfa_mbox_cmd_cbfn_t)(void *cbarg);
-struct bfa_mbox_cmd {
-	struct list_head	qe;
-	bfa_mbox_cmd_cbfn_t     cbfn;
-	void		    *cbarg;
-	u32     msg[BFI_IOC_MSGSZ];
-};
-
-/**
- * IOC mailbox module
- */
-typedef void (*bfa_ioc_mbox_mcfunc_t)(void *cbarg, struct bfi_mbmsg *m);
-struct bfa_ioc_mbox_mod {
-	struct list_head	cmd_q;		/*!< pending mbox queue	*/
-	int			nmclass;	/*!< number of handlers */
-	struct {
-		bfa_ioc_mbox_mcfunc_t	cbfn;	/*!< message handlers	*/
-		void			*cbarg;
-	} mbhdlr[BFI_MC_MAX];
-};
-
-/**
- * IOC callback function interfaces
- */
-typedef void (*bfa_ioc_enable_cbfn_t)(void *bfa, enum bfa_status status);
-typedef void (*bfa_ioc_disable_cbfn_t)(void *bfa);
-typedef void (*bfa_ioc_hbfail_cbfn_t)(void *bfa);
-typedef void (*bfa_ioc_reset_cbfn_t)(void *bfa);
-struct bfa_ioc_cbfn {
-	bfa_ioc_enable_cbfn_t	enable_cbfn;
-	bfa_ioc_disable_cbfn_t	disable_cbfn;
-	bfa_ioc_hbfail_cbfn_t	hbfail_cbfn;
-	bfa_ioc_reset_cbfn_t	reset_cbfn;
-};
-
-/**
- * IOC event notification mechanism.
- */
-enum bfa_ioc_event {
-	BFA_IOC_E_ENABLED	= 1,
-	BFA_IOC_E_DISABLED	= 2,
-	BFA_IOC_E_FAILED	= 3,
-};
-
-typedef void (*bfa_ioc_notify_cbfn_t)(void *, enum bfa_ioc_event);
-
-struct bfa_ioc_notify {
-	struct list_head	qe;
-	bfa_ioc_notify_cbfn_t	cbfn;
-	void			*cbarg;
-};
-
-/**
- * Heartbeat failure notification queue element.
- */
-struct bfa_ioc_hbfail_notify {
-	struct list_head	qe;
-	bfa_ioc_hbfail_cbfn_t	cbfn;
-	void			*cbarg;
-};
-
-/**
- * Initialize a heartbeat failure notification structure
- */
-#define bfa_ioc_notify_init(__notify, __cbfn, __cbarg) do {	\
-	(__notify)->cbfn = (__cbfn);				\
-	(__notify)->cbarg = (__cbarg);				\
-} while (0)
-
-struct bfa_iocpf {
-	bfa_fsm_t		fsm;
-	struct bfa_ioc		*ioc;
-	u32			retry_count;
-	bool			auto_recover;
-};
-
-struct bfa_ioc {
-	bfa_fsm_t		fsm;
-	struct bfa		*bfa;
-	struct bfa_pcidev	pcidev;
-	struct timer_list	ioc_timer;
-	struct timer_list	iocpf_timer;
-	struct timer_list	sem_timer;
-	struct timer_list	hb_timer;
-	u32			hb_count;
-	struct list_head	notify_q;
-	void			*dbg_fwsave;
-	int			dbg_fwsave_len;
-	bool			dbg_fwsave_once;
-	enum bfi_mclass		ioc_mc;
-	struct bfa_ioc_regs	ioc_regs;
-	struct bfa_ioc_drv_stats stats;
-	bool			fcmode;
-	bool			ctdev;
-	bool			cna;
-	bool			pllinit;
-	bool			stats_busy;	/*!< outstanding stats */
-	u8			port_id;
-
-	struct bfa_dma		attr_dma;
-	struct bfi_ioc_attr	*attr;
-	struct bfa_ioc_cbfn	*cbfn;
-	struct bfa_ioc_mbox_mod	mbox_mod;
-	struct bfa_ioc_hwif	*ioc_hwif;
-	struct bfa_iocpf	iocpf;
-};
-
-struct bfa_ioc_hwif {
-	enum bfa_status (*ioc_pll_init) (void __iomem *rb, bool fcmode);
-	bool		(*ioc_firmware_lock)	(struct bfa_ioc *ioc);
-	void		(*ioc_firmware_unlock)	(struct bfa_ioc *ioc);
-	void		(*ioc_reg_init)	(struct bfa_ioc *ioc);
-	void		(*ioc_map_port)	(struct bfa_ioc *ioc);
-	void		(*ioc_isr_mode_set)	(struct bfa_ioc *ioc,
-					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);
-	bool		(*ioc_sync_complete)	(struct bfa_ioc *ioc);
-};
-
-#define bfa_ioc_pcifn(__ioc)		((__ioc)->pcidev.pci_func)
-#define bfa_ioc_devid(__ioc)		((__ioc)->pcidev.device_id)
-#define bfa_ioc_bar0(__ioc)		((__ioc)->pcidev.pci_bar_kva)
-#define bfa_ioc_portid(__ioc)		((__ioc)->port_id)
-#define bfa_ioc_fetch_stats(__ioc, __stats) \
-		(((__stats)->drv_stats) = (__ioc)->stats)
-#define bfa_ioc_clr_stats(__ioc)	\
-		memset(&(__ioc)->stats, 0, sizeof((__ioc)->stats))
-#define bfa_ioc_maxfrsize(__ioc)	((__ioc)->attr->maxfrsize)
-#define bfa_ioc_rx_bbcredit(__ioc)	((__ioc)->attr->rx_bbcredit)
-#define bfa_ioc_speed_sup(__ioc)	\
-	BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop)
-#define bfa_ioc_get_nports(__ioc)	\
-	BFI_ADAPTER_GETP(NPORTS, (__ioc)->attr->adapter_prop)
-
-#define bfa_ioc_stats(_ioc, _stats)	((_ioc)->stats._stats++)
-#define bfa_ioc_stats_hb_count(_ioc, _hb_count)	\
-	((_ioc)->stats.hb_count = (_hb_count))
-#define BFA_IOC_FWIMG_MINSZ	(16 * 1024)
-#define BFA_IOC_FWIMG_TYPE(__ioc)					\
-	(((__ioc)->ctdev) ?						\
-	 (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) :	\
-	 BFI_IMAGE_CB_FC)
-#define BFA_IOC_FW_SMEM_SIZE(__ioc)					\
-	(((__ioc)->ctdev) ? BFI_SMEM_CT_SIZE : BFI_SMEM_CB_SIZE)
-#define BFA_IOC_FLASH_CHUNK_NO(off)		(off / BFI_FLASH_CHUNK_SZ_WORDS)
-#define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off)	(off % BFI_FLASH_CHUNK_SZ_WORDS)
-#define BFA_IOC_FLASH_CHUNK_ADDR(chunkno)  (chunkno * BFI_FLASH_CHUNK_SZ_WORDS)
-
-/**
- * IOC mailbox interface
- */
-void bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd);
-void bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc);
-void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
-		bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg);
-
-/**
- * IOC interfaces
- */
-
-#define bfa_ioc_pll_init_asic(__ioc) \
-	((__ioc)->ioc_hwif->ioc_pll_init((__ioc)->pcidev.pci_bar_kva, \
-			   (__ioc)->fcmode))
-
-#define	bfa_ioc_isr_mode_set(__ioc, __msix)			\
-			((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix))
-#define	bfa_ioc_ownership_reset(__ioc)				\
-			((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc))
-
-void bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc);
-
-void bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa,
-		struct bfa_ioc_cbfn *cbfn);
-void bfa_nw_ioc_auto_recover(bool auto_recover);
-void bfa_nw_ioc_detach(struct bfa_ioc *ioc);
-void bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
-		enum bfi_mclass mc);
-u32 bfa_nw_ioc_meminfo(void);
-void bfa_nw_ioc_mem_claim(struct bfa_ioc *ioc,  u8 *dm_kva, u64 dm_pa);
-void bfa_nw_ioc_enable(struct bfa_ioc *ioc);
-void bfa_nw_ioc_disable(struct bfa_ioc *ioc);
-
-void bfa_nw_ioc_error_isr(struct bfa_ioc *ioc);
-bool bfa_nw_ioc_is_disabled(struct bfa_ioc *ioc);
-void bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr);
-void bfa_nw_ioc_notify_register(struct bfa_ioc *ioc,
-	struct bfa_ioc_notify *notify);
-bool bfa_nw_ioc_sem_get(void __iomem *sem_reg);
-void bfa_nw_ioc_sem_release(void __iomem *sem_reg);
-void bfa_nw_ioc_hw_sem_release(struct bfa_ioc *ioc);
-void bfa_nw_ioc_fwver_get(struct bfa_ioc *ioc,
-			struct bfi_ioc_image_hdr *fwhdr);
-bool bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc,
-			struct bfi_ioc_image_hdr *fwhdr);
-mac_t bfa_nw_ioc_get_mac(struct bfa_ioc *ioc);
-
-/*
- * Timeout APIs
- */
-void bfa_nw_ioc_timeout(void *ioc);
-void bfa_nw_ioc_hb_check(void *ioc);
-void bfa_nw_iocpf_timeout(void *ioc);
-void bfa_nw_iocpf_sem_timeout(void *ioc);
-
-/*
- * F/W Image Size & Chunk
- */
-u32 *bfa_cb_image_get_chunk(int type, u32 off);
-u32 bfa_cb_image_get_size(int type);
-
-#endif /* __BFA_IOC_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bfi_cna.h linux-libre-3.2-gnu/drivers/net/bna/bfi_cna.h
--- linux-libre-3.1-gnu/drivers/net/bna/bfi_cna.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bfi_cna.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,199 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-#ifndef __BFI_CNA_H__
-#define __BFI_CNA_H__
-
-#include "bfi.h"
-#include "bfa_defs_cna.h"
-
-#pragma pack(1)
-
-enum bfi_port_h2i {
-	BFI_PORT_H2I_ENABLE_REQ		= (1),
-	BFI_PORT_H2I_DISABLE_REQ	= (2),
-	BFI_PORT_H2I_GET_STATS_REQ	= (3),
-	BFI_PORT_H2I_CLEAR_STATS_REQ	= (4),
-};
-
-enum bfi_port_i2h {
-	BFI_PORT_I2H_ENABLE_RSP		= BFA_I2HM(1),
-	BFI_PORT_I2H_DISABLE_RSP	= BFA_I2HM(2),
-	BFI_PORT_I2H_GET_STATS_RSP	= BFA_I2HM(3),
-	BFI_PORT_I2H_CLEAR_STATS_RSP	= BFA_I2HM(4),
-};
-
-/**
- * Generic REQ type
- */
-struct bfi_port_generic_req {
-	struct bfi_mhdr mh;		/*!< msg header			    */
-	u32	msgtag;		/*!< msgtag for reply		    */
-	u32	rsvd;
-};
-
-/**
- * Generic RSP type
- */
-struct bfi_port_generic_rsp {
-	struct bfi_mhdr mh;		/*!< common msg header		    */
-	u8		status;		/*!< port enable status		    */
-	u8		rsvd[3];
-	u32	msgtag;		/*!< msgtag for reply		    */
-};
-
-/**
- * @todo
- * BFI_PORT_H2I_ENABLE_REQ
- */
-
-/**
- * @todo
- * BFI_PORT_I2H_ENABLE_RSP
- */
-
-/**
- * BFI_PORT_H2I_DISABLE_REQ
- */
-
-/**
- * BFI_PORT_I2H_DISABLE_RSP
- */
-
-/**
- * BFI_PORT_H2I_GET_STATS_REQ
- */
-struct bfi_port_get_stats_req {
-	struct bfi_mhdr mh;		/*!< common msg header		    */
-	union bfi_addr_u   dma_addr;
-};
-
-/**
- * BFI_PORT_I2H_GET_STATS_RSP
- */
-
-/**
- * BFI_PORT_H2I_CLEAR_STATS_REQ
- */
-
-/**
- * BFI_PORT_I2H_CLEAR_STATS_RSP
- */
-
-union bfi_port_h2i_msg_u {
-	struct bfi_mhdr mh;
-	struct bfi_port_generic_req enable_req;
-	struct bfi_port_generic_req disable_req;
-	struct bfi_port_get_stats_req getstats_req;
-	struct bfi_port_generic_req clearstats_req;
-};
-
-union bfi_port_i2h_msg_u {
-	struct bfi_mhdr mh;
-	struct bfi_port_generic_rsp enable_rsp;
-	struct bfi_port_generic_rsp disable_rsp;
-	struct bfi_port_generic_rsp getstats_rsp;
-	struct bfi_port_generic_rsp clearstats_rsp;
-};
-
-/* @brief Mailbox commands from host to (DCBX/LLDP) firmware */
-enum bfi_cee_h2i_msgs {
-	BFI_CEE_H2I_GET_CFG_REQ = 1,
-	BFI_CEE_H2I_RESET_STATS = 2,
-	BFI_CEE_H2I_GET_STATS_REQ = 3,
-};
-
-/* @brief Mailbox reply and AEN messages from DCBX/LLDP firmware to host */
-enum bfi_cee_i2h_msgs {
-	BFI_CEE_I2H_GET_CFG_RSP = BFA_I2HM(1),
-	BFI_CEE_I2H_RESET_STATS_RSP = BFA_I2HM(2),
-	BFI_CEE_I2H_GET_STATS_RSP = BFA_I2HM(3),
-};
-
-/* Data structures */
-
-/*
- * @brief H2I command structure for resetting the stats.
- * BFI_CEE_H2I_RESET_STATS
- */
-struct bfi_lldp_reset_stats {
-	struct bfi_mhdr mh;
-};
-
-/*
- * @brief H2I command structure for resetting the stats.
- * BFI_CEE_H2I_RESET_STATS
- */
-struct bfi_cee_reset_stats {
-	struct bfi_mhdr mh;
-};
-
-/*
- * @brief  get configuration  command from host
- * BFI_CEE_H2I_GET_CFG_REQ
- */
-struct bfi_cee_get_req {
-	struct bfi_mhdr mh;
-	union bfi_addr_u   dma_addr;
-};
-
-/*
- * @brief reply message from firmware
- * BFI_CEE_I2H_GET_CFG_RSP
- */
-struct bfi_cee_get_rsp {
-	struct bfi_mhdr mh;
-	u8			cmd_status;
-	u8			rsvd[3];
-};
-
-/*
- * @brief  get configuration  command from host
- * BFI_CEE_H2I_GET_STATS_REQ
- */
-struct bfi_cee_stats_req {
-	struct bfi_mhdr mh;
-	union bfi_addr_u   dma_addr;
-};
-
-/*
- * @brief reply message from firmware
- * BFI_CEE_I2H_GET_STATS_RSP
- */
-struct bfi_cee_stats_rsp {
-	struct bfi_mhdr mh;
-	u8			cmd_status;
-	u8			rsvd[3];
-};
-
-/* @brief mailbox command structures from host to firmware */
-union bfi_cee_h2i_msg_u {
-	struct bfi_mhdr mh;
-	struct bfi_cee_get_req get_req;
-	struct bfi_cee_stats_req stats_req;
-};
-
-/* @brief mailbox message structures from firmware to host	*/
-union bfi_cee_i2h_msg_u {
-	struct bfi_mhdr mh;
-	struct bfi_cee_get_rsp get_rsp;
-	struct bfi_cee_stats_rsp stats_rsp;
-};
-
-#pragma pack()
-
-#endif /* __BFI_CNA_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bfi_ctreg.h linux-libre-3.2-gnu/drivers/net/bna/bfi_ctreg.h
--- linux-libre-3.1-gnu/drivers/net/bna/bfi_ctreg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bfi_ctreg.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,646 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-/*
- * bfi_ctreg.h catapult host block register definitions
- *
- * !!! Do not edit. Auto generated. !!!
- */
-
-#ifndef __BFI_CTREG_H__
-#define __BFI_CTREG_H__
-
-#define HOSTFN0_LPU_MBOX0_0		0x00019200
-#define HOSTFN1_LPU_MBOX0_8		0x00019260
-#define LPU_HOSTFN0_MBOX0_0		0x00019280
-#define LPU_HOSTFN1_MBOX0_8		0x000192e0
-#define HOSTFN2_LPU_MBOX0_0		0x00019400
-#define HOSTFN3_LPU_MBOX0_8		0x00019460
-#define LPU_HOSTFN2_MBOX0_0		0x00019480
-#define LPU_HOSTFN3_MBOX0_8		0x000194e0
-#define HOSTFN0_INT_STATUS		0x00014000
-#define __HOSTFN0_HALT_OCCURRED		0x01000000
-#define __HOSTFN0_INT_STATUS_LVL_MK	0x00f00000
-#define __HOSTFN0_INT_STATUS_LVL_SH	20
-#define __HOSTFN0_INT_STATUS_LVL(_v)	((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
-#define __HOSTFN0_INT_STATUS_P_MK	0x000f0000
-#define __HOSTFN0_INT_STATUS_P_SH	16
-#define __HOSTFN0_INT_STATUS_P(_v)	((_v) << __HOSTFN0_INT_STATUS_P_SH)
-#define __HOSTFN0_INT_STATUS_F		0x0000ffff
-#define HOSTFN0_INT_MSK			0x00014004
-#define HOST_PAGE_NUM_FN0		0x00014008
-#define __HOST_PAGE_NUM_FN		0x000001ff
-#define HOST_MSIX_ERR_INDEX_FN0		0x0001400c
-#define __MSIX_ERR_INDEX_FN		0x000001ff
-#define HOSTFN1_INT_STATUS		0x00014100
-#define __HOSTFN1_HALT_OCCURRED		0x01000000
-#define __HOSTFN1_INT_STATUS_LVL_MK	0x00f00000
-#define __HOSTFN1_INT_STATUS_LVL_SH	20
-#define __HOSTFN1_INT_STATUS_LVL(_v)	((_v) << __HOSTFN1_INT_STATUS_LVL_SH)
-#define __HOSTFN1_INT_STATUS_P_MK	0x000f0000
-#define __HOSTFN1_INT_STATUS_P_SH	16
-#define __HOSTFN1_INT_STATUS_P(_v)	((_v) << __HOSTFN1_INT_STATUS_P_SH)
-#define __HOSTFN1_INT_STATUS_F		0x0000ffff
-#define HOSTFN1_INT_MSK			0x00014104
-#define HOST_PAGE_NUM_FN1		0x00014108
-#define HOST_MSIX_ERR_INDEX_FN1		0x0001410c
-#define APP_PLL_425_CTL_REG		0x00014204
-#define __P_425_PLL_LOCK		0x80000000
-#define __APP_PLL_425_SRAM_USE_100MHZ	0x00100000
-#define __APP_PLL_425_RESET_TIMER_MK	0x000e0000
-#define __APP_PLL_425_RESET_TIMER_SH	17
-#define __APP_PLL_425_RESET_TIMER(_v)	((_v) << __APP_PLL_425_RESET_TIMER_SH)
-#define __APP_PLL_425_LOGIC_SOFT_RESET	0x00010000
-#define __APP_PLL_425_CNTLMT0_1_MK	0x0000c000
-#define __APP_PLL_425_CNTLMT0_1_SH	14
-#define __APP_PLL_425_CNTLMT0_1(_v)	((_v) << __APP_PLL_425_CNTLMT0_1_SH)
-#define __APP_PLL_425_JITLMT0_1_MK	0x00003000
-#define __APP_PLL_425_JITLMT0_1_SH	12
-#define __APP_PLL_425_JITLMT0_1(_v)	((_v) << __APP_PLL_425_JITLMT0_1_SH)
-#define __APP_PLL_425_HREF		0x00000800
-#define __APP_PLL_425_HDIV		0x00000400
-#define __APP_PLL_425_P0_1_MK		0x00000300
-#define __APP_PLL_425_P0_1_SH		8
-#define __APP_PLL_425_P0_1(_v)		((_v) << __APP_PLL_425_P0_1_SH)
-#define __APP_PLL_425_Z0_2_MK		0x000000e0
-#define __APP_PLL_425_Z0_2_SH		5
-#define __APP_PLL_425_Z0_2(_v)		((_v) << __APP_PLL_425_Z0_2_SH)
-#define __APP_PLL_425_RSEL200500	0x00000010
-#define __APP_PLL_425_ENARST		0x00000008
-#define __APP_PLL_425_BYPASS		0x00000004
-#define __APP_PLL_425_LRESETN		0x00000002
-#define __APP_PLL_425_ENABLE		0x00000001
-#define APP_PLL_312_CTL_REG		0x00014208
-#define __P_312_PLL_LOCK		0x80000000
-#define __ENABLE_MAC_AHB_1		0x00800000
-#define __ENABLE_MAC_AHB_0		0x00400000
-#define __ENABLE_MAC_1			0x00200000
-#define __ENABLE_MAC_0			0x00100000
-#define __APP_PLL_312_RESET_TIMER_MK	0x000e0000
-#define __APP_PLL_312_RESET_TIMER_SH	17
-#define __APP_PLL_312_RESET_TIMER(_v)	((_v) << __APP_PLL_312_RESET_TIMER_SH)
-#define __APP_PLL_312_LOGIC_SOFT_RESET	0x00010000
-#define __APP_PLL_312_CNTLMT0_1_MK	0x0000c000
-#define __APP_PLL_312_CNTLMT0_1_SH	14
-#define __APP_PLL_312_CNTLMT0_1(_v)	((_v) << __APP_PLL_312_CNTLMT0_1_SH)
-#define __APP_PLL_312_JITLMT0_1_MK	0x00003000
-#define __APP_PLL_312_JITLMT0_1_SH	12
-#define __APP_PLL_312_JITLMT0_1(_v)	((_v) << __APP_PLL_312_JITLMT0_1_SH)
-#define __APP_PLL_312_HREF		0x00000800
-#define __APP_PLL_312_HDIV		0x00000400
-#define __APP_PLL_312_P0_1_MK		0x00000300
-#define __APP_PLL_312_P0_1_SH		8
-#define __APP_PLL_312_P0_1(_v)		((_v) << __APP_PLL_312_P0_1_SH)
-#define __APP_PLL_312_Z0_2_MK		0x000000e0
-#define __APP_PLL_312_Z0_2_SH		5
-#define __APP_PLL_312_Z0_2(_v)		((_v) << __APP_PLL_312_Z0_2_SH)
-#define __APP_PLL_312_RSEL200500	0x00000010
-#define __APP_PLL_312_ENARST		0x00000008
-#define __APP_PLL_312_BYPASS		0x00000004
-#define __APP_PLL_312_LRESETN		0x00000002
-#define __APP_PLL_312_ENABLE		0x00000001
-#define MBIST_CTL_REG			0x00014220
-#define __EDRAM_BISTR_START		0x00000004
-#define __MBIST_RESET			0x00000002
-#define __MBIST_START			0x00000001
-#define MBIST_STAT_REG			0x00014224
-#define __EDRAM_BISTR_STATUS		0x00000008
-#define __EDRAM_BISTR_DONE		0x00000004
-#define __MEM_BIT_STATUS		0x00000002
-#define __MBIST_DONE			0x00000001
-#define HOST_SEM0_REG			0x00014230
-#define __HOST_SEMAPHORE		0x00000001
-#define HOST_SEM1_REG			0x00014234
-#define HOST_SEM2_REG			0x00014238
-#define HOST_SEM3_REG			0x0001423c
-#define HOST_SEM0_INFO_REG		0x00014240
-#define HOST_SEM1_INFO_REG		0x00014244
-#define HOST_SEM2_INFO_REG		0x00014248
-#define HOST_SEM3_INFO_REG		0x0001424c
-#define ETH_MAC_SER_REG			0x00014288
-#define __APP_EMS_CKBUFAMPIN		0x00000020
-#define __APP_EMS_REFCLKSEL		0x00000010
-#define __APP_EMS_CMLCKSEL		0x00000008
-#define __APP_EMS_REFCKBUFEN2		0x00000004
-#define __APP_EMS_REFCKBUFEN1		0x00000002
-#define __APP_EMS_CHANNEL_SEL		0x00000001
-#define HOSTFN2_INT_STATUS		0x00014300
-#define __HOSTFN2_HALT_OCCURRED		0x01000000
-#define __HOSTFN2_INT_STATUS_LVL_MK	0x00f00000
-#define __HOSTFN2_INT_STATUS_LVL_SH	20
-#define __HOSTFN2_INT_STATUS_LVL(_v)	((_v) << __HOSTFN2_INT_STATUS_LVL_SH)
-#define __HOSTFN2_INT_STATUS_P_MK	0x000f0000
-#define __HOSTFN2_INT_STATUS_P_SH	16
-#define __HOSTFN2_INT_STATUS_P(_v)	((_v) << __HOSTFN2_INT_STATUS_P_SH)
-#define __HOSTFN2_INT_STATUS_F		0x0000ffff
-#define HOSTFN2_INT_MSK			0x00014304
-#define HOST_PAGE_NUM_FN2		0x00014308
-#define HOST_MSIX_ERR_INDEX_FN2		0x0001430c
-#define HOSTFN3_INT_STATUS		0x00014400
-#define __HALT_OCCURRED			0x01000000
-#define __HOSTFN3_INT_STATUS_LVL_MK	0x00f00000
-#define __HOSTFN3_INT_STATUS_LVL_SH	20
-#define __HOSTFN3_INT_STATUS_LVL(_v)	((_v) << __HOSTFN3_INT_STATUS_LVL_SH)
-#define __HOSTFN3_INT_STATUS_P_MK	0x000f0000
-#define __HOSTFN3_INT_STATUS_P_SH	16
-#define __HOSTFN3_INT_STATUS_P(_v)	((_v) << __HOSTFN3_INT_STATUS_P_SH)
-#define __HOSTFN3_INT_STATUS_F		0x0000ffff
-#define HOSTFN3_INT_MSK			0x00014404
-#define HOST_PAGE_NUM_FN3		0x00014408
-#define HOST_MSIX_ERR_INDEX_FN3		0x0001440c
-#define FNC_ID_REG			0x00014600
-#define __FUNCTION_NUMBER		0x00000007
-#define FNC_PERS_REG			0x00014604
-#define __F3_FUNCTION_ACTIVE		0x80000000
-#define __F3_FUNCTION_MODE		0x40000000
-#define __F3_PORT_MAP_MK		0x30000000
-#define __F3_PORT_MAP_SH		28
-#define __F3_PORT_MAP(_v)		((_v) << __F3_PORT_MAP_SH)
-#define __F3_VM_MODE			0x08000000
-#define __F3_INTX_STATUS_MK		0x07000000
-#define __F3_INTX_STATUS_SH		24
-#define __F3_INTX_STATUS(_v)		((_v) << __F3_INTX_STATUS_SH)
-#define __F2_FUNCTION_ACTIVE		0x00800000
-#define __F2_FUNCTION_MODE		0x00400000
-#define __F2_PORT_MAP_MK		0x00300000
-#define __F2_PORT_MAP_SH		20
-#define __F2_PORT_MAP(_v)		((_v) << __F2_PORT_MAP_SH)
-#define __F2_VM_MODE			0x00080000
-#define __F2_INTX_STATUS_MK		0x00070000
-#define __F2_INTX_STATUS_SH		16
-#define __F2_INTX_STATUS(_v)		((_v) << __F2_INTX_STATUS_SH)
-#define __F1_FUNCTION_ACTIVE		0x00008000
-#define __F1_FUNCTION_MODE		0x00004000
-#define __F1_PORT_MAP_MK		0x00003000
-#define __F1_PORT_MAP_SH		12
-#define __F1_PORT_MAP(_v)		((_v) << __F1_PORT_MAP_SH)
-#define __F1_VM_MODE			0x00000800
-#define __F1_INTX_STATUS_MK		0x00000700
-#define __F1_INTX_STATUS_SH		8
-#define __F1_INTX_STATUS(_v)		((_v) << __F1_INTX_STATUS_SH)
-#define __F0_FUNCTION_ACTIVE		0x00000080
-#define __F0_FUNCTION_MODE		0x00000040
-#define __F0_PORT_MAP_MK		0x00000030
-#define __F0_PORT_MAP_SH		4
-#define __F0_PORT_MAP(_v)		((_v) << __F0_PORT_MAP_SH)
-#define __F0_VM_MODE		0x00000008
-#define __F0_INTX_STATUS		0x00000007
-enum {
-	__F0_INTX_STATUS_MSIX		= 0x0,
-	__F0_INTX_STATUS_INTA		= 0x1,
-	__F0_INTX_STATUS_INTB		= 0x2,
-	__F0_INTX_STATUS_INTC		= 0x3,
-	__F0_INTX_STATUS_INTD		= 0x4,
-};
-#define OP_MODE				0x0001460c
-#define __APP_ETH_CLK_LOWSPEED		0x00000004
-#define __GLOBAL_CORECLK_HALFSPEED	0x00000002
-#define __GLOBAL_FCOE_MODE		0x00000001
-#define HOST_SEM4_REG			0x00014610
-#define HOST_SEM5_REG			0x00014614
-#define HOST_SEM6_REG			0x00014618
-#define HOST_SEM7_REG			0x0001461c
-#define HOST_SEM4_INFO_REG		0x00014620
-#define HOST_SEM5_INFO_REG		0x00014624
-#define HOST_SEM6_INFO_REG		0x00014628
-#define HOST_SEM7_INFO_REG		0x0001462c
-#define HOSTFN0_LPU0_MBOX0_CMD_STAT	0x00019000
-#define __HOSTFN0_LPU0_MBOX0_INFO_MK	0xfffffffe
-#define __HOSTFN0_LPU0_MBOX0_INFO_SH	1
-#define __HOSTFN0_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN0_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN0_LPU1_MBOX0_CMD_STAT	0x00019004
-#define __HOSTFN0_LPU1_MBOX0_INFO_MK	0xfffffffe
-#define __HOSTFN0_LPU1_MBOX0_INFO_SH	1
-#define __HOSTFN0_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN0_LPU1_MBOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN0_MBOX0_CMD_STAT	0x00019008
-#define __LPU0_HOSTFN0_MBOX0_INFO_MK	0xfffffffe
-#define __LPU0_HOSTFN0_MBOX0_INFO_SH	1
-#define __LPU0_HOSTFN0_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN0_MBOX0_CMD_STAT	0x0001900c
-#define __LPU1_HOSTFN0_MBOX0_INFO_MK	0xfffffffe
-#define __LPU1_HOSTFN0_MBOX0_INFO_SH	1
-#define __LPU1_HOSTFN0_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN1_LPU0_MBOX0_CMD_STAT	0x00019010
-#define __HOSTFN1_LPU0_MBOX0_INFO_MK	0xfffffffe
-#define __HOSTFN1_LPU0_MBOX0_INFO_SH	1
-#define __HOSTFN1_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN1_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN1_LPU1_MBOX0_CMD_STAT	0x00019014
-#define __HOSTFN1_LPU1_MBOX0_INFO_MK	0xfffffffe
-#define __HOSTFN1_LPU1_MBOX0_INFO_SH	1
-#define __HOSTFN1_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN1_LPU1_MBOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN1_MBOX0_CMD_STAT	0x00019018
-#define __LPU0_HOSTFN1_MBOX0_INFO_MK	0xfffffffe
-#define __LPU0_HOSTFN1_MBOX0_INFO_SH	1
-#define __LPU0_HOSTFN1_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN1_MBOX0_CMD_STAT	0x0001901c
-#define __LPU1_HOSTFN1_MBOX0_INFO_MK	0xfffffffe
-#define __LPU1_HOSTFN1_MBOX0_INFO_SH	1
-#define __LPU1_HOSTFN1_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN2_LPU0_MBOX0_CMD_STAT	0x00019150
-#define __HOSTFN2_LPU0_MBOX0_INFO_MK	0xfffffffe
-#define __HOSTFN2_LPU0_MBOX0_INFO_SH	1
-#define __HOSTFN2_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN2_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN2_LPU1_MBOX0_CMD_STAT	0x00019154
-#define __HOSTFN2_LPU1_MBOX0_INFO_MK	0xfffffffe
-#define __HOSTFN2_LPU1_MBOX0_INFO_SH	1
-#define __HOSTFN2_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN2_MBOX0_CMD_STAT	0x00019158
-#define __LPU0_HOSTFN2_MBOX0_INFO_MK	0xfffffffe
-#define __LPU0_HOSTFN2_MBOX0_INFO_SH	1
-#define __LPU0_HOSTFN2_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN2_MBOX0_CMD_STAT	0x0001915c
-#define __LPU1_HOSTFN2_MBOX0_INFO_MK	0xfffffffe
-#define __LPU1_HOSTFN2_MBOX0_INFO_SH	1
-#define __LPU1_HOSTFN2_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN3_LPU0_MBOX0_CMD_STAT	0x00019160
-#define __HOSTFN3_LPU0_MBOX0_INFO_MK	0xfffffffe
-#define __HOSTFN3_LPU0_MBOX0_INFO_SH	1
-#define __HOSTFN3_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN3_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN3_LPU1_MBOX0_CMD_STAT	0x00019164
-#define __HOSTFN3_LPU1_MBOX0_INFO_MK	0xfffffffe
-#define __HOSTFN3_LPU1_MBOX0_INFO_SH	1
-#define __HOSTFN3_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN3_LPU1_MBOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN3_MBOX0_CMD_STAT	0x00019168
-#define __LPU0_HOSTFN3_MBOX0_INFO_MK	0xfffffffe
-#define __LPU0_HOSTFN3_MBOX0_INFO_SH	1
-#define __LPU0_HOSTFN3_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN3_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN3_MBOX0_CMD_STAT	0x0001916c
-#define __LPU1_HOSTFN3_MBOX0_INFO_MK	0xfffffffe
-#define __LPU1_HOSTFN3_MBOX0_INFO_SH	1
-#define __LPU1_HOSTFN3_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN3_MBOX0_CMD_STATUS	0x00000001
-#define FW_INIT_HALT_P0			0x000191ac
-#define __FW_INIT_HALT_P		0x00000001
-#define FW_INIT_HALT_P1			0x000191bc
-#define CPE_PI_PTR_Q0			0x00038000
-#define __CPE_PI_UNUSED_MK		0xffff0000
-#define __CPE_PI_UNUSED_SH		16
-#define __CPE_PI_UNUSED(_v)		((_v) << __CPE_PI_UNUSED_SH)
-#define __CPE_PI_PTR			0x0000ffff
-#define CPE_PI_PTR_Q1			0x00038040
-#define CPE_CI_PTR_Q0			0x00038004
-#define __CPE_CI_UNUSED_MK		0xffff0000
-#define __CPE_CI_UNUSED_SH		16
-#define __CPE_CI_UNUSED(_v)		((_v) << __CPE_CI_UNUSED_SH)
-#define __CPE_CI_PTR			0x0000ffff
-#define CPE_CI_PTR_Q1			0x00038044
-#define CPE_DEPTH_Q0			0x00038008
-#define __CPE_DEPTH_UNUSED_MK		0xf8000000
-#define __CPE_DEPTH_UNUSED_SH		27
-#define __CPE_DEPTH_UNUSED(_v)		((_v) << __CPE_DEPTH_UNUSED_SH)
-#define __CPE_MSIX_VEC_INDEX_MK		0x07ff0000
-#define __CPE_MSIX_VEC_INDEX_SH		16
-#define __CPE_MSIX_VEC_INDEX(_v)	((_v) << __CPE_MSIX_VEC_INDEX_SH)
-#define __CPE_DEPTH			0x0000ffff
-#define CPE_DEPTH_Q1			0x00038048
-#define CPE_QCTRL_Q0			0x0003800c
-#define __CPE_CTRL_UNUSED30_MK		0xfc000000
-#define __CPE_CTRL_UNUSED30_SH		26
-#define __CPE_CTRL_UNUSED30(_v)		((_v) << __CPE_CTRL_UNUSED30_SH)
-#define __CPE_FUNC_INT_CTRL_MK		0x03000000
-#define __CPE_FUNC_INT_CTRL_SH		24
-#define __CPE_FUNC_INT_CTRL(_v)		((_v) << __CPE_FUNC_INT_CTRL_SH)
-enum {
-	__CPE_FUNC_INT_CTRL_DISABLE		= 0x0,
-	__CPE_FUNC_INT_CTRL_F2NF		= 0x1,
-	__CPE_FUNC_INT_CTRL_3QUART		= 0x2,
-	__CPE_FUNC_INT_CTRL_HALF		= 0x3,
-};
-#define __CPE_CTRL_UNUSED20_MK		0x00f00000
-#define __CPE_CTRL_UNUSED20_SH		20
-#define __CPE_CTRL_UNUSED20(_v)		((_v) << __CPE_CTRL_UNUSED20_SH)
-#define __CPE_SCI_TH_MK			0x000f0000
-#define __CPE_SCI_TH_SH			16
-#define __CPE_SCI_TH(_v)		((_v) << __CPE_SCI_TH_SH)
-#define __CPE_CTRL_UNUSED10_MK		0x0000c000
-#define __CPE_CTRL_UNUSED10_SH		14
-#define __CPE_CTRL_UNUSED10(_v)		((_v) << __CPE_CTRL_UNUSED10_SH)
-#define __CPE_ACK_PENDING		0x00002000
-#define __CPE_CTRL_UNUSED40_MK		0x00001c00
-#define __CPE_CTRL_UNUSED40_SH		10
-#define __CPE_CTRL_UNUSED40(_v)		((_v) << __CPE_CTRL_UNUSED40_SH)
-#define __CPE_PCIEID_MK			0x00000300
-#define __CPE_PCIEID_SH			8
-#define __CPE_PCIEID(_v)		((_v) << __CPE_PCIEID_SH)
-#define __CPE_CTRL_UNUSED00_MK		0x000000fe
-#define __CPE_CTRL_UNUSED00_SH		1
-#define __CPE_CTRL_UNUSED00(_v)		((_v) << __CPE_CTRL_UNUSED00_SH)
-#define __CPE_ESIZE			0x00000001
-#define CPE_QCTRL_Q1			0x0003804c
-#define __CPE_CTRL_UNUSED31_MK		0xfc000000
-#define __CPE_CTRL_UNUSED31_SH		26
-#define __CPE_CTRL_UNUSED31(_v)		((_v) << __CPE_CTRL_UNUSED31_SH)
-#define __CPE_CTRL_UNUSED21_MK		0x00f00000
-#define __CPE_CTRL_UNUSED21_SH		20
-#define __CPE_CTRL_UNUSED21(_v)		((_v) << __CPE_CTRL_UNUSED21_SH)
-#define __CPE_CTRL_UNUSED11_MK		0x0000c000
-#define __CPE_CTRL_UNUSED11_SH		14
-#define __CPE_CTRL_UNUSED11(_v)		((_v) << __CPE_CTRL_UNUSED11_SH)
-#define __CPE_CTRL_UNUSED41_MK		0x00001c00
-#define __CPE_CTRL_UNUSED41_SH		10
-#define __CPE_CTRL_UNUSED41(_v)		((_v) << __CPE_CTRL_UNUSED41_SH)
-#define __CPE_CTRL_UNUSED01_MK		0x000000fe
-#define __CPE_CTRL_UNUSED01_SH		1
-#define __CPE_CTRL_UNUSED01(_v)		((_v) << __CPE_CTRL_UNUSED01_SH)
-#define RME_PI_PTR_Q0			0x00038020
-#define __LATENCY_TIME_STAMP_MK		0xffff0000
-#define __LATENCY_TIME_STAMP_SH		16
-#define __LATENCY_TIME_STAMP(_v)	((_v) << __LATENCY_TIME_STAMP_SH)
-#define __RME_PI_PTR			0x0000ffff
-#define RME_PI_PTR_Q1			0x00038060
-#define RME_CI_PTR_Q0			0x00038024
-#define __DELAY_TIME_STAMP_MK		0xffff0000
-#define __DELAY_TIME_STAMP_SH		16
-#define __DELAY_TIME_STAMP(_v)		((_v) << __DELAY_TIME_STAMP_SH)
-#define __RME_CI_PTR			0x0000ffff
-#define RME_CI_PTR_Q1			0x00038064
-#define RME_DEPTH_Q0			0x00038028
-#define __RME_DEPTH_UNUSED_MK		0xf8000000
-#define __RME_DEPTH_UNUSED_SH		27
-#define __RME_DEPTH_UNUSED(_v)		((_v) << __RME_DEPTH_UNUSED_SH)
-#define __RME_MSIX_VEC_INDEX_MK		0x07ff0000
-#define __RME_MSIX_VEC_INDEX_SH		16
-#define __RME_MSIX_VEC_INDEX(_v)	((_v) << __RME_MSIX_VEC_INDEX_SH)
-#define __RME_DEPTH			0x0000ffff
-#define RME_DEPTH_Q1			0x00038068
-#define RME_QCTRL_Q0			0x0003802c
-#define __RME_INT_LATENCY_TIMER_MK	0xff000000
-#define __RME_INT_LATENCY_TIMER_SH	24
-#define __RME_INT_LATENCY_TIMER(_v)	((_v) << __RME_INT_LATENCY_TIMER_SH)
-#define __RME_INT_DELAY_TIMER_MK	0x00ff0000
-#define __RME_INT_DELAY_TIMER_SH	16
-#define __RME_INT_DELAY_TIMER(_v)	((_v) << __RME_INT_DELAY_TIMER_SH)
-#define __RME_INT_DELAY_DISABLE		0x00008000
-#define __RME_DLY_DELAY_DISABLE		0x00004000
-#define __RME_ACK_PENDING		0x00002000
-#define __RME_FULL_INTERRUPT_DISABLE	0x00001000
-#define __RME_CTRL_UNUSED10_MK		0x00000c00
-#define __RME_CTRL_UNUSED10_SH		10
-#define __RME_CTRL_UNUSED10(_v)		((_v) << __RME_CTRL_UNUSED10_SH)
-#define __RME_PCIEID_MK			0x00000300
-#define __RME_PCIEID_SH			8
-#define __RME_PCIEID(_v)		((_v) << __RME_PCIEID_SH)
-#define __RME_CTRL_UNUSED00_MK		0x000000fe
-#define __RME_CTRL_UNUSED00_SH		1
-#define __RME_CTRL_UNUSED00(_v)		((_v) << __RME_CTRL_UNUSED00_SH)
-#define __RME_ESIZE			0x00000001
-#define RME_QCTRL_Q1			0x0003806c
-#define __RME_CTRL_UNUSED11_MK		0x00000c00
-#define __RME_CTRL_UNUSED11_SH		10
-#define __RME_CTRL_UNUSED11(_v)		((_v) << __RME_CTRL_UNUSED11_SH)
-#define __RME_CTRL_UNUSED01_MK		0x000000fe
-#define __RME_CTRL_UNUSED01_SH		1
-#define __RME_CTRL_UNUSED01(_v)		((_v) << __RME_CTRL_UNUSED01_SH)
-#define PSS_CTL_REG			0x00018800
-#define __PSS_I2C_CLK_DIV_MK		0x007f0000
-#define __PSS_I2C_CLK_DIV_SH		16
-#define __PSS_I2C_CLK_DIV(_v)		((_v) << __PSS_I2C_CLK_DIV_SH)
-#define __PSS_LMEM_INIT_DONE		0x00001000
-#define __PSS_LMEM_RESET		0x00000200
-#define __PSS_LMEM_INIT_EN		0x00000100
-#define __PSS_LPU1_RESET		0x00000002
-#define __PSS_LPU0_RESET		0x00000001
-#define PSS_ERR_STATUS_REG		0x00018810
-#define __PSS_LPU1_TCM_READ_ERR		0x00200000
-#define __PSS_LPU0_TCM_READ_ERR		0x00100000
-#define __PSS_LMEM5_CORR_ERR		0x00080000
-#define __PSS_LMEM4_CORR_ERR		0x00040000
-#define __PSS_LMEM3_CORR_ERR		0x00020000
-#define __PSS_LMEM2_CORR_ERR		0x00010000
-#define __PSS_LMEM1_CORR_ERR		0x00008000
-#define __PSS_LMEM0_CORR_ERR		0x00004000
-#define __PSS_LMEM5_UNCORR_ERR		0x00002000
-#define __PSS_LMEM4_UNCORR_ERR		0x00001000
-#define __PSS_LMEM3_UNCORR_ERR		0x00000800
-#define __PSS_LMEM2_UNCORR_ERR		0x00000400
-#define __PSS_LMEM1_UNCORR_ERR		0x00000200
-#define __PSS_LMEM0_UNCORR_ERR		0x00000100
-#define __PSS_BAL_PERR			0x00000080
-#define __PSS_DIP_IF_ERR		0x00000040
-#define __PSS_IOH_IF_ERR		0x00000020
-#define __PSS_TDS_IF_ERR		0x00000010
-#define __PSS_RDS_IF_ERR		0x00000008
-#define __PSS_SGM_IF_ERR		0x00000004
-#define __PSS_LPU1_RAM_ERR		0x00000002
-#define __PSS_LPU0_RAM_ERR		0x00000001
-#define ERR_SET_REG			0x00018818
-#define __PSS_ERR_STATUS_SET		0x003fffff
-#define PMM_1T_RESET_REG_P0		0x0002381c
-#define __PMM_1T_RESET_P		0x00000001
-#define PMM_1T_RESET_REG_P1		0x00023c1c
-#define HQM_QSET0_RXQ_DRBL_P0		0x00038000
-#define __RXQ0_ADD_VECTORS_P		0x80000000
-#define __RXQ0_STOP_P			0x40000000
-#define __RXQ0_PRD_PTR_P		0x0000ffff
-#define HQM_QSET1_RXQ_DRBL_P0		0x00038080
-#define __RXQ1_ADD_VECTORS_P		0x80000000
-#define __RXQ1_STOP_P			0x40000000
-#define __RXQ1_PRD_PTR_P		0x0000ffff
-#define HQM_QSET0_RXQ_DRBL_P1		0x0003c000
-#define HQM_QSET1_RXQ_DRBL_P1		0x0003c080
-#define HQM_QSET0_TXQ_DRBL_P0		0x00038020
-#define __TXQ0_ADD_VECTORS_P		0x80000000
-#define __TXQ0_STOP_P			0x40000000
-#define __TXQ0_PRD_PTR_P		0x0000ffff
-#define HQM_QSET1_TXQ_DRBL_P0		0x000380a0
-#define __TXQ1_ADD_VECTORS_P		0x80000000
-#define __TXQ1_STOP_P			0x40000000
-#define __TXQ1_PRD_PTR_P		0x0000ffff
-#define HQM_QSET0_TXQ_DRBL_P1		0x0003c020
-#define HQM_QSET1_TXQ_DRBL_P1		0x0003c0a0
-#define HQM_QSET0_IB_DRBL_1_P0		0x00038040
-#define __IB1_0_ACK_P			0x80000000
-#define __IB1_0_DISABLE_P		0x40000000
-#define __IB1_0_COALESCING_CFG_P_MK	0x00ff0000
-#define __IB1_0_COALESCING_CFG_P_SH	16
-#define __IB1_0_COALESCING_CFG_P(_v)	((_v) << __IB1_0_COALESCING_CFG_P_SH)
-#define __IB1_0_NUM_OF_ACKED_EVENTS_P	0x0000ffff
-#define HQM_QSET1_IB_DRBL_1_P0		0x000380c0
-#define __IB1_1_ACK_P			0x80000000
-#define __IB1_1_DISABLE_P		0x40000000
-#define __IB1_1_COALESCING_CFG_P_MK	0x00ff0000
-#define __IB1_1_COALESCING_CFG_P_SH	16
-#define __IB1_1_COALESCING_CFG_P(_v)	((_v) << __IB1_1_COALESCING_CFG_P_SH)
-#define __IB1_1_NUM_OF_ACKED_EVENTS_P	0x0000ffff
-#define HQM_QSET0_IB_DRBL_1_P1		0x0003c040
-#define HQM_QSET1_IB_DRBL_1_P1		0x0003c0c0
-#define HQM_QSET0_IB_DRBL_2_P0		0x00038060
-#define __IB2_0_ACK_P			0x80000000
-#define __IB2_0_DISABLE_P		0x40000000
-#define __IB2_0_COALESCING_CFG_P_MK	0x00ff0000
-#define __IB2_0_COALESCING_CFG_P_SH	16
-#define __IB2_0_COALESCING_CFG_P(_v)	((_v) << __IB2_0_COALESCING_CFG_P_SH)
-#define __IB2_0_NUM_OF_ACKED_EVENTS_P	0x0000ffff
-#define HQM_QSET1_IB_DRBL_2_P0		0x000380e0
-#define __IB2_1_ACK_P			0x80000000
-#define __IB2_1_DISABLE_P		0x40000000
-#define __IB2_1_COALESCING_CFG_P_MK	0x00ff0000
-#define __IB2_1_COALESCING_CFG_P_SH	16
-#define __IB2_1_COALESCING_CFG_P(_v)	((_v) << __IB2_1_COALESCING_CFG_P_SH)
-#define __IB2_1_NUM_OF_ACKED_EVENTS_P	0x0000ffff
-#define HQM_QSET0_IB_DRBL_2_P1		0x0003c060
-#define HQM_QSET1_IB_DRBL_2_P1		0x0003c0e0
-
-/*
- * These definitions are either in error/missing in spec. Its auto-generated
- * from hard coded values in regparse.pl.
- */
-#define __EMPHPOST_AT_4G_MK_FIX		0x0000001c
-#define __EMPHPOST_AT_4G_SH_FIX		0x00000002
-#define __EMPHPRE_AT_4G_FIX		0x00000003
-#define __SFP_TXRATE_EN_FIX		0x00000100
-#define __SFP_RXRATE_EN_FIX		0x00000080
-
-/*
- * These register definitions are auto-generated from hard coded values
- * in regparse.pl.
- */
-
-/*
- * These register mapping definitions are auto-generated from mapping tables
- * in regparse.pl.
- */
-#define BFA_IOC0_HBEAT_REG		HOST_SEM0_INFO_REG
-#define BFA_IOC0_STATE_REG		HOST_SEM1_INFO_REG
-#define BFA_IOC1_HBEAT_REG		HOST_SEM2_INFO_REG
-#define BFA_IOC1_STATE_REG		HOST_SEM3_INFO_REG
-#define BFA_FW_USE_COUNT		 HOST_SEM4_INFO_REG
-#define BFA_IOC_FAIL_SYNC		HOST_SEM5_INFO_REG
-
-#define CPE_DEPTH_Q(__n) \
-	(CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
-#define CPE_QCTRL_Q(__n) \
-	(CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0))
-#define CPE_PI_PTR_Q(__n) \
-	(CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0))
-#define CPE_CI_PTR_Q(__n) \
-	(CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0))
-#define RME_DEPTH_Q(__n) \
-	(RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0))
-#define RME_QCTRL_Q(__n) \
-	(RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0))
-#define RME_PI_PTR_Q(__n) \
-	(RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
-#define RME_CI_PTR_Q(__n) \
-	(RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
-#define HQM_QSET_RXQ_DRBL_P0(__n) \
-	(HQM_QSET0_RXQ_DRBL_P0 + (__n) * \
-		(HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0))
-#define HQM_QSET_TXQ_DRBL_P0(__n) \
-	(HQM_QSET0_TXQ_DRBL_P0 + (__n) * \
-		(HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0))
-#define HQM_QSET_IB_DRBL_1_P0(__n) \
-	(HQM_QSET0_IB_DRBL_1_P0 + (__n) * \
-		(HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0))
-#define HQM_QSET_IB_DRBL_2_P0(__n) \
-	(HQM_QSET0_IB_DRBL_2_P0 + (__n) * \
-		(HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0))
-#define HQM_QSET_RXQ_DRBL_P1(__n) \
-	(HQM_QSET0_RXQ_DRBL_P1 + (__n) * \
-		(HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1))
-#define HQM_QSET_TXQ_DRBL_P1(__n) \
-	(HQM_QSET0_TXQ_DRBL_P1 + (__n) * \
-		(HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1))
-#define HQM_QSET_IB_DRBL_1_P1(__n) \
-	(HQM_QSET0_IB_DRBL_1_P1 + (__n) * \
-		(HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1))
-#define HQM_QSET_IB_DRBL_2_P1(__n) \
-	(HQM_QSET0_IB_DRBL_2_P1 + (__n) * \
-		(HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1))
-
-#define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
-#define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
-#define CPE_Q_MASK(__q) ((__q) & 0x3)
-#define RME_Q_MASK(__q) ((__q) & 0x3)
-
-/*
- * PCI MSI-X vector defines
- */
-enum {
-	BFA_MSIX_CPE_Q0 = 0,
-	BFA_MSIX_CPE_Q1 = 1,
-	BFA_MSIX_CPE_Q2 = 2,
-	BFA_MSIX_CPE_Q3 = 3,
-	BFA_MSIX_RME_Q0 = 4,
-	BFA_MSIX_RME_Q1 = 5,
-	BFA_MSIX_RME_Q2 = 6,
-	BFA_MSIX_RME_Q3 = 7,
-	BFA_MSIX_LPU_ERR = 8,
-	BFA_MSIX_CT_MAX = 9,
-};
-
-/*
- * And corresponding host interrupt status bit field defines
- */
-#define __HFN_INT_CPE_Q0		0x00000001U
-#define __HFN_INT_CPE_Q1		0x00000002U
-#define __HFN_INT_CPE_Q2		0x00000004U
-#define __HFN_INT_CPE_Q3		0x00000008U
-#define __HFN_INT_CPE_Q4		0x00000010U
-#define __HFN_INT_CPE_Q5		0x00000020U
-#define __HFN_INT_CPE_Q6		0x00000040U
-#define __HFN_INT_CPE_Q7		0x00000080U
-#define __HFN_INT_RME_Q0		0x00000100U
-#define __HFN_INT_RME_Q1		0x00000200U
-#define __HFN_INT_RME_Q2		0x00000400U
-#define __HFN_INT_RME_Q3		0x00000800U
-#define __HFN_INT_RME_Q4		0x00001000U
-#define __HFN_INT_RME_Q5		0x00002000U
-#define __HFN_INT_RME_Q6		0x00004000U
-#define __HFN_INT_RME_Q7		0x00008000U
-#define __HFN_INT_ERR_EMC		0x00010000U
-#define __HFN_INT_ERR_LPU0		0x00020000U
-#define __HFN_INT_ERR_LPU1		0x00040000U
-#define __HFN_INT_ERR_PSS		0x00080000U
-#define __HFN_INT_MBOX_LPU0		0x00100000U
-#define __HFN_INT_MBOX_LPU1		0x00200000U
-#define __HFN_INT_MBOX1_LPU0		0x00400000U
-#define __HFN_INT_MBOX1_LPU1		0x00800000U
-#define __HFN_INT_LL_HALT		0x01000000U
-#define __HFN_INT_CPE_MASK		0x000000ffU
-#define __HFN_INT_RME_MASK		0x0000ff00U
-
-/*
- * catapult memory map.
- */
-#define LL_PGN_HQM0		0x0096
-#define LL_PGN_HQM1		0x0097
-#define PSS_SMEM_PAGE_START	0x8000
-#define PSS_SMEM_PGNUM(_pg0, _ma)	((_pg0) + ((_ma) >> 15))
-#define PSS_SMEM_PGOFF(_ma)	((_ma) & 0x7fff)
-
-/*
- * End of catapult memory map
- */
-
-#endif /* __BFI_CTREG_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bfi.h linux-libre-3.2-gnu/drivers/net/bna/bfi.h
--- linux-libre-3.1-gnu/drivers/net/bna/bfi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bfi.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,400 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-#ifndef __BFI_H__
-#define __BFI_H__
-
-#include "bfa_defs.h"
-
-#pragma pack(1)
-
-/**
- * BFI FW image type
- */
-#define	BFI_FLASH_CHUNK_SZ			256	/*!< Flash chunk size */
-#define	BFI_FLASH_CHUNK_SZ_WORDS	(BFI_FLASH_CHUNK_SZ/sizeof(u32))
-enum {
-	BFI_IMAGE_CB_FC,
-	BFI_IMAGE_CT_FC,
-	BFI_IMAGE_CT_CNA,
-	BFI_IMAGE_MAX,
-};
-
-/**
- * Msg header common to all msgs
- */
-struct bfi_mhdr {
-	u8		msg_class;	/*!< @ref enum bfi_mclass	    */
-	u8		msg_id;		/*!< msg opcode with in the class   */
-	union {
-		struct {
-			u8	rsvd;
-			u8	lpu_id;	/*!< msg destination		    */
-		} h2i;
-		u16	i2htok;	/*!< token in msgs to host	    */
-	} mtag;
-};
-
-#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do {		\
-	(_mh).msg_class			= (_mc);		\
-	(_mh).msg_id			= (_op);		\
-	(_mh).mtag.h2i.lpu_id	= (_lpuid);			\
-} while (0)
-
-#define bfi_i2h_set(_mh, _mc, _op, _i2htok) do {		\
-	(_mh).msg_class			= (_mc);		\
-	(_mh).msg_id			= (_op);		\
-	(_mh).mtag.i2htok		= (_i2htok);		\
-} while (0)
-
-/*
- * Message opcodes: 0-127 to firmware, 128-255 to host
- */
-#define BFI_I2H_OPCODE_BASE	128
-#define BFA_I2HM(_x)			((_x) + BFI_I2H_OPCODE_BASE)
-
-/**
- ****************************************************************************
- *
- * Scatter Gather Element and Page definition
- *
- ****************************************************************************
- */
-
-#define BFI_SGE_INLINE	1
-#define BFI_SGE_INLINE_MAX	(BFI_SGE_INLINE + 1)
-
-/**
- * SG Flags
- */
-enum {
-	BFI_SGE_DATA		= 0,	/*!< data address, not last	     */
-	BFI_SGE_DATA_CPL	= 1,	/*!< data addr, last in current page */
-	BFI_SGE_DATA_LAST	= 3,	/*!< data address, last		     */
-	BFI_SGE_LINK		= 2,	/*!< link address		     */
-	BFI_SGE_PGDLEN		= 2,	/*!< cumulative data length for page */
-};
-
-/**
- * DMA addresses
- */
-union bfi_addr_u {
-	struct {
-		u32	addr_lo;
-		u32	addr_hi;
-	} a32;
-};
-
-/**
- * Scatter Gather Element
- */
-struct bfi_sge {
-#ifdef __BIGENDIAN
-	u32	flags:2,
-			rsvd:2,
-			sg_len:28;
-#else
-	u32	sg_len:28,
-			rsvd:2,
-			flags:2;
-#endif
-	union bfi_addr_u sga;
-};
-
-/**
- * Scatter Gather Page
- */
-#define BFI_SGPG_DATA_SGES		7
-#define BFI_SGPG_SGES_MAX		(BFI_SGPG_DATA_SGES + 1)
-#define BFI_SGPG_RSVD_WD_LEN	8
-struct bfi_sgpg {
-	struct bfi_sge sges[BFI_SGPG_SGES_MAX];
-	u32	rsvd[BFI_SGPG_RSVD_WD_LEN];
-};
-
-/*
- * Large Message structure - 128 Bytes size Msgs
- */
-#define BFI_LMSG_SZ		128
-#define BFI_LMSG_PL_WSZ	\
-			((BFI_LMSG_SZ - sizeof(struct bfi_mhdr)) / 4)
-
-struct bfi_msg {
-	struct bfi_mhdr mhdr;
-	u32	pl[BFI_LMSG_PL_WSZ];
-};
-
-/**
- * Mailbox message structure
- */
-#define BFI_MBMSG_SZ		7
-struct bfi_mbmsg {
-	struct bfi_mhdr mh;
-	u32		pl[BFI_MBMSG_SZ];
-};
-
-/**
- * Message Classes
- */
-enum bfi_mclass {
-	BFI_MC_IOC		= 1,	/*!< IO Controller (IOC)	    */
-	BFI_MC_DIAG		= 2,	/*!< Diagnostic Msgs		    */
-	BFI_MC_FLASH		= 3,	/*!< Flash message class	    */
-	BFI_MC_CEE		= 4,	/*!< CEE			    */
-	BFI_MC_FCPORT		= 5,	/*!< FC port			    */
-	BFI_MC_IOCFC		= 6,	/*!< FC - IO Controller (IOC)	    */
-	BFI_MC_LL		= 7,	/*!< Link Layer			    */
-	BFI_MC_UF		= 8,	/*!< Unsolicited frame receive	    */
-	BFI_MC_FCXP		= 9,	/*!< FC Transport		    */
-	BFI_MC_LPS		= 10,	/*!< lport fc login services	    */
-	BFI_MC_RPORT		= 11,	/*!< Remote port		    */
-	BFI_MC_ITNIM		= 12,	/*!< I-T nexus (Initiator mode)	    */
-	BFI_MC_IOIM_READ	= 13,	/*!< read IO (Initiator mode)	    */
-	BFI_MC_IOIM_WRITE	= 14,	/*!< write IO (Initiator mode)	    */
-	BFI_MC_IOIM_IO		= 15,	/*!< IO (Initiator mode)	    */
-	BFI_MC_IOIM		= 16,	/*!< IO (Initiator mode)	    */
-	BFI_MC_IOIM_IOCOM	= 17,	/*!< good IO completion		    */
-	BFI_MC_TSKIM		= 18,	/*!< Initiator Task management	    */
-	BFI_MC_SBOOT		= 19,	/*!< SAN boot services		    */
-	BFI_MC_IPFC		= 20,	/*!< IP over FC Msgs		    */
-	BFI_MC_PORT		= 21,	/*!< Physical port		    */
-	BFI_MC_SFP		= 22,	/*!< SFP module			    */
-	BFI_MC_MSGQ		= 23,	/*!< MSGQ			    */
-	BFI_MC_ENET		= 24,	/*!< ENET commands/responses	    */
-	BFI_MC_MAX		= 32
-};
-
-#define BFI_IOC_MAX_CQS		4
-#define BFI_IOC_MAX_CQS_ASIC	8
-#define BFI_IOC_MSGLEN_MAX	32	/* 32 bytes */
-
-#define BFI_BOOT_TYPE_OFF		8
-#define BFI_BOOT_LOADER_OFF		12
-
-#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
-
-/**
- *----------------------------------------------------------------------
- *				IOC
- *----------------------------------------------------------------------
- */
-
-enum bfi_ioc_h2i_msgs {
-	BFI_IOC_H2I_ENABLE_REQ		= 1,
-	BFI_IOC_H2I_DISABLE_REQ		= 2,
-	BFI_IOC_H2I_GETATTR_REQ		= 3,
-	BFI_IOC_H2I_DBG_SYNC		= 4,
-	BFI_IOC_H2I_DBG_DUMP		= 5,
-};
-
-enum bfi_ioc_i2h_msgs {
-	BFI_IOC_I2H_ENABLE_REPLY	= BFA_I2HM(1),
-	BFI_IOC_I2H_DISABLE_REPLY	= BFA_I2HM(2),
-	BFI_IOC_I2H_GETATTR_REPLY	= BFA_I2HM(3),
-	BFI_IOC_I2H_READY_EVENT		= BFA_I2HM(4),
-	BFI_IOC_I2H_HBEAT		= BFA_I2HM(5),
-};
-
-/**
- * BFI_IOC_H2I_GETATTR_REQ message
- */
-struct bfi_ioc_getattr_req {
-	struct bfi_mhdr mh;
-	union bfi_addr_u	attr_addr;
-};
-
-struct bfi_ioc_attr {
-	u64		mfg_pwwn;	/*!< Mfg port wwn	   */
-	u64		mfg_nwwn;	/*!< Mfg node wwn	   */
-	mac_t		mfg_mac;	/*!< Mfg mac		   */
-	u16	rsvd_a;
-	u64		pwwn;
-	u64		nwwn;
-	mac_t		mac;		/*!< PBC or Mfg mac	   */
-	u16	rsvd_b;
-	mac_t		fcoe_mac;
-	u16	rsvd_c;
-	char		brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
-	u8		pcie_gen;
-	u8		pcie_lanes_orig;
-	u8		pcie_lanes;
-	u8		rx_bbcredit;	/*!< receive buffer credits */
-	u32	adapter_prop;	/*!< adapter properties     */
-	u16	maxfrsize;	/*!< max receive frame size */
-	char		asic_rev;
-	u8		rsvd_d;
-	char		fw_version[BFA_VERSION_LEN];
-	char		optrom_version[BFA_VERSION_LEN];
-	struct bfa_mfg_vpd vpd;
-	u32	card_type;	/*!< card type			*/
-};
-
-/**
- * BFI_IOC_I2H_GETATTR_REPLY message
- */
-struct bfi_ioc_getattr_reply {
-	struct bfi_mhdr mh;	/*!< Common msg header		*/
-	u8			status;	/*!< cfg reply status		*/
-	u8			rsvd[3];
-};
-
-/**
- * Firmware memory page offsets
- */
-#define BFI_IOC_SMEM_PG0_CB	(0x40)
-#define BFI_IOC_SMEM_PG0_CT	(0x180)
-
-/**
- * Firmware statistic offset
- */
-#define BFI_IOC_FWSTATS_OFF	(0x6B40)
-#define BFI_IOC_FWSTATS_SZ	(4096)
-
-/**
- * Firmware trace offset
- */
-#define BFI_IOC_TRC_OFF		(0x4b00)
-#define BFI_IOC_TRC_ENTS	256
-
-#define BFI_IOC_FW_SIGNATURE	(0xbfadbfad)
-#define BFI_IOC_MD5SUM_SZ	4
-struct bfi_ioc_image_hdr {
-	u32	signature;	/*!< constant signature */
-	u32	rsvd_a;
-	u32	exec;		/*!< exec vector	*/
-	u32	param;		/*!< parameters		*/
-	u32	rsvd_b[4];
-	u32	md5sum[BFI_IOC_MD5SUM_SZ];
-};
-
-enum bfi_fwboot_type {
-	BFI_FWBOOT_TYPE_NORMAL	= 0,
-	BFI_FWBOOT_TYPE_FLASH	= 1,
-	BFI_FWBOOT_TYPE_MEMTEST	= 2,
-};
-
-/**
- *  BFI_IOC_I2H_READY_EVENT message
- */
-struct bfi_ioc_rdy_event {
-	struct bfi_mhdr mh;		/*!< common msg header */
-	u8			init_status;	/*!< init event status */
-	u8			rsvd[3];
-};
-
-struct bfi_ioc_hbeat {
-	struct bfi_mhdr mh;		/*!< common msg header		*/
-	u32	   hb_count;	/*!< current heart beat count	*/
-};
-
-/**
- * IOC hardware/firmware state
- */
-enum bfi_ioc_state {
-	BFI_IOC_UNINIT		= 0,	/*!< not initialized		     */
-	BFI_IOC_INITING		= 1,	/*!< h/w is being initialized	     */
-	BFI_IOC_HWINIT		= 2,	/*!< h/w is initialized		     */
-	BFI_IOC_CFG		= 3,	/*!< IOC configuration in progress   */
-	BFI_IOC_OP		= 4,	/*!< IOC is operational		     */
-	BFI_IOC_DISABLING	= 5,	/*!< IOC is being disabled	     */
-	BFI_IOC_DISABLED	= 6,	/*!< IOC is disabled		     */
-	BFI_IOC_CFG_DISABLED	= 7,	/*!< IOC is being disabled;transient */
-	BFI_IOC_FAIL		= 8,	/*!< IOC heart-beat failure	     */
-	BFI_IOC_MEMTEST		= 9,	/*!< IOC is doing memtest	     */
-};
-
-#define BFI_IOC_ENDIAN_SIG  0x12345678
-
-enum {
-	BFI_ADAPTER_TYPE_FC	= 0x01,		/*!< FC adapters	   */
-	BFI_ADAPTER_TYPE_MK	= 0x0f0000,	/*!< adapter type mask     */
-	BFI_ADAPTER_TYPE_SH	= 16,	        /*!< adapter type shift    */
-	BFI_ADAPTER_NPORTS_MK	= 0xff00,	/*!< number of ports mask  */
-	BFI_ADAPTER_NPORTS_SH	= 8,	        /*!< number of ports shift */
-	BFI_ADAPTER_SPEED_MK	= 0xff,		/*!< adapter speed mask    */
-	BFI_ADAPTER_SPEED_SH	= 0,	        /*!< adapter speed shift   */
-	BFI_ADAPTER_PROTO	= 0x100000,	/*!< prototype adapaters   */
-	BFI_ADAPTER_TTV		= 0x200000,	/*!< TTV debug capable     */
-	BFI_ADAPTER_UNSUPP	= 0x400000,	/*!< unknown adapter type  */
-};
-
-#define BFI_ADAPTER_GETP(__prop, __adap_prop)			\
-	(((__adap_prop) & BFI_ADAPTER_ ## __prop ## _MK) >>	\
-		BFI_ADAPTER_ ## __prop ## _SH)
-#define BFI_ADAPTER_SETP(__prop, __val)				\
-	((__val) << BFI_ADAPTER_ ## __prop ## _SH)
-#define BFI_ADAPTER_IS_PROTO(__adap_type)			\
-	((__adap_type) & BFI_ADAPTER_PROTO)
-#define BFI_ADAPTER_IS_TTV(__adap_type)				\
-	((__adap_type) & BFI_ADAPTER_TTV)
-#define BFI_ADAPTER_IS_UNSUPP(__adap_type)			\
-	((__adap_type) & BFI_ADAPTER_UNSUPP)
-#define BFI_ADAPTER_IS_SPECIAL(__adap_type)			\
-	((__adap_type) & (BFI_ADAPTER_TTV | BFI_ADAPTER_PROTO |	\
-			BFI_ADAPTER_UNSUPP))
-
-/**
- * BFI_IOC_H2I_ENABLE_REQ & BFI_IOC_H2I_DISABLE_REQ messages
- */
-struct bfi_ioc_ctrl_req {
-	struct bfi_mhdr mh;
-	u8			ioc_class;
-	u8			rsvd[3];
-	u32		tv_sec;
-};
-
-/**
- * BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages
- */
-struct bfi_ioc_ctrl_reply {
-	struct bfi_mhdr mh;		/*!< Common msg header     */
-	u8			status;		/*!< enable/disable status */
-	u8			rsvd[3];
-};
-
-#define BFI_IOC_MSGSZ   8
-/**
- * H2I Messages
- */
-union bfi_ioc_h2i_msg_u {
-	struct bfi_mhdr mh;
-	struct bfi_ioc_ctrl_req enable_req;
-	struct bfi_ioc_ctrl_req disable_req;
-	struct bfi_ioc_getattr_req getattr_req;
-	u32			mboxmsg[BFI_IOC_MSGSZ];
-};
-
-/**
- * I2H Messages
- */
-union bfi_ioc_i2h_msg_u {
-	struct bfi_mhdr mh;
-	struct bfi_ioc_rdy_event rdy_event;
-	u32			mboxmsg[BFI_IOC_MSGSZ];
-};
-
-#pragma pack()
-
-#endif /* __BFI_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bfi_ll.h linux-libre-3.2-gnu/drivers/net/bna/bfi_ll.h
--- linux-libre-3.1-gnu/drivers/net/bna/bfi_ll.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bfi_ll.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,438 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-#ifndef __BFI_LL_H__
-#define __BFI_LL_H__
-
-#include "bfi.h"
-
-#pragma pack(1)
-
-/**
- * @brief
- *	"enums" for all LL mailbox messages other than IOC
- */
-enum {
-	BFI_LL_H2I_MAC_UCAST_SET_REQ = 1,
-	BFI_LL_H2I_MAC_UCAST_ADD_REQ = 2,
-	BFI_LL_H2I_MAC_UCAST_DEL_REQ = 3,
-
-	BFI_LL_H2I_MAC_MCAST_ADD_REQ = 4,
-	BFI_LL_H2I_MAC_MCAST_DEL_REQ = 5,
-	BFI_LL_H2I_MAC_MCAST_FILTER_REQ = 6,
-	BFI_LL_H2I_MAC_MCAST_DEL_ALL_REQ = 7,
-
-	BFI_LL_H2I_PORT_ADMIN_REQ = 8,
-	BFI_LL_H2I_STATS_GET_REQ = 9,
-	BFI_LL_H2I_STATS_CLEAR_REQ = 10,
-
-	BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ = 11,
-	BFI_LL_H2I_RXF_DEFAULT_SET_REQ = 12,
-
-	BFI_LL_H2I_TXQ_STOP_REQ = 13,
-	BFI_LL_H2I_RXQ_STOP_REQ = 14,
-
-	BFI_LL_H2I_DIAG_LOOPBACK_REQ = 15,
-
-	BFI_LL_H2I_SET_PAUSE_REQ = 16,
-	BFI_LL_H2I_MTU_INFO_REQ = 17,
-
-	BFI_LL_H2I_RX_REQ = 18,
-} ;
-
-enum {
-	BFI_LL_I2H_MAC_UCAST_SET_RSP = BFA_I2HM(1),
-	BFI_LL_I2H_MAC_UCAST_ADD_RSP = BFA_I2HM(2),
-	BFI_LL_I2H_MAC_UCAST_DEL_RSP = BFA_I2HM(3),
-
-	BFI_LL_I2H_MAC_MCAST_ADD_RSP = BFA_I2HM(4),
-	BFI_LL_I2H_MAC_MCAST_DEL_RSP = BFA_I2HM(5),
-	BFI_LL_I2H_MAC_MCAST_FILTER_RSP = BFA_I2HM(6),
-	BFI_LL_I2H_MAC_MCAST_DEL_ALL_RSP = BFA_I2HM(7),
-
-	BFI_LL_I2H_PORT_ADMIN_RSP = BFA_I2HM(8),
-	BFI_LL_I2H_STATS_GET_RSP = BFA_I2HM(9),
-	BFI_LL_I2H_STATS_CLEAR_RSP = BFA_I2HM(10),
-
-	BFI_LL_I2H_RXF_PROMISCUOUS_SET_RSP = BFA_I2HM(11),
-	BFI_LL_I2H_RXF_DEFAULT_SET_RSP = BFA_I2HM(12),
-
-	BFI_LL_I2H_TXQ_STOP_RSP = BFA_I2HM(13),
-	BFI_LL_I2H_RXQ_STOP_RSP = BFA_I2HM(14),
-
-	BFI_LL_I2H_DIAG_LOOPBACK_RSP = BFA_I2HM(15),
-
-	BFI_LL_I2H_SET_PAUSE_RSP = BFA_I2HM(16),
-
-	BFI_LL_I2H_MTU_INFO_RSP = BFA_I2HM(17),
-	BFI_LL_I2H_RX_RSP = BFA_I2HM(18),
-
-	BFI_LL_I2H_LINK_DOWN_AEN = BFA_I2HM(19),
-	BFI_LL_I2H_LINK_UP_AEN = BFA_I2HM(20),
-
-	BFI_LL_I2H_PORT_ENABLE_AEN = BFA_I2HM(21),
-	BFI_LL_I2H_PORT_DISABLE_AEN = BFA_I2HM(22),
-} ;
-
-/**
- * @brief bfi_ll_mac_addr_req is used by:
- *        BFI_LL_H2I_MAC_UCAST_SET_REQ
- *        BFI_LL_H2I_MAC_UCAST_ADD_REQ
- *        BFI_LL_H2I_MAC_UCAST_DEL_REQ
- *        BFI_LL_H2I_MAC_MCAST_ADD_REQ
- *        BFI_LL_H2I_MAC_MCAST_DEL_REQ
- */
-struct bfi_ll_mac_addr_req {
-	struct bfi_mhdr mh;		/*!< common msg header */
-	u8		rxf_id;
-	u8		rsvd1[3];
-	mac_t		mac_addr;
-	u8		rsvd2[2];
-};
-
-/**
- * @brief bfi_ll_mcast_filter_req is used by:
- *	  BFI_LL_H2I_MAC_MCAST_FILTER_REQ
- */
-struct bfi_ll_mcast_filter_req {
-	struct bfi_mhdr mh;		/*!< common msg header */
-	u8		rxf_id;
-	u8		enable;
-	u8		rsvd[2];
-};
-
-/**
- * @brief bfi_ll_mcast_del_all is used by:
- *	  BFI_LL_H2I_MAC_MCAST_DEL_ALL_REQ
- */
-struct bfi_ll_mcast_del_all_req {
-	struct bfi_mhdr mh;		/*!< common msg header */
-	u8		   rxf_id;
-	u8		   rsvd[3];
-};
-
-/**
- * @brief bfi_ll_q_stop_req is used by:
- *	BFI_LL_H2I_TXQ_STOP_REQ
- *	BFI_LL_H2I_RXQ_STOP_REQ
- */
-struct bfi_ll_q_stop_req {
-	struct bfi_mhdr mh;		/*!< common msg header */
-	u32	q_id_mask[2];	/* !< bit-mask for queue ids */
-};
-
-/**
- * @brief bfi_ll_stats_req is used by:
- *    BFI_LL_I2H_STATS_GET_REQ
- *    BFI_LL_I2H_STATS_CLEAR_REQ
- */
-struct bfi_ll_stats_req {
-	struct bfi_mhdr mh;	/*!< common msg header */
-	u16 stats_mask;	/* !< bit-mask for non-function statistics */
-	u8	rsvd[2];
-	u32 rxf_id_mask[2];	/* !< bit-mask for RxF Statistics */
-	u32 txf_id_mask[2];	/* !< bit-mask for TxF Statistics */
-	union bfi_addr_u  host_buffer;	/* !< where statistics are returned */
-};
-
-/**
- * @brief defines for "stats_mask" above.
- */
-#define BFI_LL_STATS_MAC	(1 << 0)	/* !< MAC Statistics */
-#define BFI_LL_STATS_BPC	(1 << 1)	/* !< Pause Stats from BPC */
-#define BFI_LL_STATS_RAD	(1 << 2)	/* !< Rx Admission Statistics */
-#define BFI_LL_STATS_RX_FC	(1 << 3)	/* !< Rx FC Stats from RxA */
-#define BFI_LL_STATS_TX_FC	(1 << 4)	/* !< Tx FC Stats from TxA */
-
-#define BFI_LL_STATS_ALL	0x1f
-
-/**
- * @brief bfi_ll_port_admin_req
- */
-struct bfi_ll_port_admin_req {
-	struct bfi_mhdr mh;		/*!< common msg header */
-	u8		 up;
-	u8		 rsvd[3];
-};
-
-/**
- * @brief bfi_ll_rxf_req is used by:
- *      BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ
- *      BFI_LL_H2I_RXF_DEFAULT_SET_REQ
- */
-struct bfi_ll_rxf_req {
-	struct bfi_mhdr mh;		/*!< common msg header */
-	u8		rxf_id;
-	u8		enable;
-	u8		rsvd[2];
-};
-
-/**
- * @brief bfi_ll_rxf_multi_req is used by:
- *	BFI_LL_H2I_RX_REQ
- */
-struct bfi_ll_rxf_multi_req {
-	struct bfi_mhdr mh;		/*!< common msg header */
-	u32	rxf_id_mask[2];
-	u8		enable;
-	u8		rsvd[3];
-};
-
-/**
- * @brief enum for Loopback opmodes
- */
-enum {
-	BFI_LL_DIAG_LB_OPMODE_EXT = 0,
-	BFI_LL_DIAG_LB_OPMODE_CBL = 1,
-};
-
-/**
- * @brief bfi_ll_set_pause_req is used by:
- *	BFI_LL_H2I_SET_PAUSE_REQ
- */
-struct bfi_ll_set_pause_req {
-	struct bfi_mhdr mh;
-	u8		tx_pause; /* 1 = enable, 0 =  disable */
-	u8		rx_pause; /* 1 = enable, 0 =  disable */
-	u8		rsvd[2];
-};
-
-/**
- * @brief bfi_ll_mtu_info_req is used by:
- *	BFI_LL_H2I_MTU_INFO_REQ
- */
-struct bfi_ll_mtu_info_req {
-	struct bfi_mhdr mh;
-	u16	mtu;
-	u8		rsvd[2];
-};
-
-/**
- * @brief
- *	  Response header format used by all responses
- *	  For both responses and asynchronous notifications
- */
-struct bfi_ll_rsp {
-	struct bfi_mhdr mh;		/*!< common msg header */
-	u8		error;
-	u8		rsvd[3];
-};
-
-/**
- * @brief bfi_ll_cee_aen is used by:
- *	BFI_LL_I2H_LINK_DOWN_AEN
- *	BFI_LL_I2H_LINK_UP_AEN
- */
-struct bfi_ll_aen {
-	struct bfi_mhdr mh;		/*!< common msg header */
-	u32	reason;
-	u8		cee_linkup;
-	u8		prio_map;    /*!< LL priority bit-map */
-	u8		rsvd[2];
-};
-
-/**
- * @brief
- * 	The following error codes can be returned
- *	by the mbox commands
- */
-enum {
-	BFI_LL_CMD_OK 		= 0,
-	BFI_LL_CMD_FAIL 	= 1,
-	BFI_LL_CMD_DUP_ENTRY	= 2,	/* !< Duplicate entry in CAM */
-	BFI_LL_CMD_CAM_FULL	= 3,	/* !< CAM is full */
-	BFI_LL_CMD_NOT_OWNER	= 4,   	/* !< Not permitted, b'cos not owner */
-	BFI_LL_CMD_NOT_EXEC	= 5,   	/* !< Was not sent to f/w at all */
-	BFI_LL_CMD_WAITING	= 6,	/* !< Waiting for completion (VMware) */
-	BFI_LL_CMD_PORT_DISABLED	= 7,	/* !< port in disabled state */
-} ;
-
-/* Statistics */
-#define BFI_LL_TXF_ID_MAX  	64
-#define BFI_LL_RXF_ID_MAX  	64
-
-/* TxF Frame Statistics */
-struct bfi_ll_stats_txf {
-	u64 ucast_octets;
-	u64 ucast;
-	u64 ucast_vlan;
-
-	u64 mcast_octets;
-	u64 mcast;
-	u64 mcast_vlan;
-
-	u64 bcast_octets;
-	u64 bcast;
-	u64 bcast_vlan;
-
-	u64 errors;
-	u64 filter_vlan;      /* frames filtered due to VLAN */
-	u64 filter_mac_sa;    /* frames filtered due to SA check */
-};
-
-/* RxF Frame Statistics */
-struct bfi_ll_stats_rxf {
-	u64 ucast_octets;
-	u64 ucast;
-	u64 ucast_vlan;
-
-	u64 mcast_octets;
-	u64 mcast;
-	u64 mcast_vlan;
-
-	u64 bcast_octets;
-	u64 bcast;
-	u64 bcast_vlan;
-	u64 frame_drops;
-};
-
-/* FC Tx Frame Statistics */
-struct bfi_ll_stats_fc_tx {
-	u64 txf_ucast_octets;
-	u64 txf_ucast;
-	u64 txf_ucast_vlan;
-
-	u64 txf_mcast_octets;
-	u64 txf_mcast;
-	u64 txf_mcast_vlan;
-
-	u64 txf_bcast_octets;
-	u64 txf_bcast;
-	u64 txf_bcast_vlan;
-
-	u64 txf_parity_errors;
-	u64 txf_timeout;
-	u64 txf_fid_parity_errors;
-};
-
-/* FC Rx Frame Statistics */
-struct bfi_ll_stats_fc_rx {
-	u64 rxf_ucast_octets;
-	u64 rxf_ucast;
-	u64 rxf_ucast_vlan;
-
-	u64 rxf_mcast_octets;
-	u64 rxf_mcast;
-	u64 rxf_mcast_vlan;
-
-	u64 rxf_bcast_octets;
-	u64 rxf_bcast;
-	u64 rxf_bcast_vlan;
-};
-
-/* RAD Frame Statistics */
-struct bfi_ll_stats_rad {
-	u64 rx_frames;
-	u64 rx_octets;
-	u64 rx_vlan_frames;
-
-	u64 rx_ucast;
-	u64 rx_ucast_octets;
-	u64 rx_ucast_vlan;
-
-	u64 rx_mcast;
-	u64 rx_mcast_octets;
-	u64 rx_mcast_vlan;
-
-	u64 rx_bcast;
-	u64 rx_bcast_octets;
-	u64 rx_bcast_vlan;
-
-	u64 rx_drops;
-};
-
-/* BPC Tx Registers */
-struct bfi_ll_stats_bpc {
-	/* transmit stats */
-	u64 tx_pause[8];
-	u64 tx_zero_pause[8];	/*!< Pause cancellation */
-	/*!<Pause initiation rather than retention */
-	u64 tx_first_pause[8];
-
-	/* receive stats */
-	u64 rx_pause[8];
-	u64 rx_zero_pause[8];	/*!< Pause cancellation */
-	/*!<Pause initiation rather than retention */
-	u64 rx_first_pause[8];
-};
-
-/* MAC Rx Statistics */
-struct bfi_ll_stats_mac {
-	u64 frame_64;		/* both rx and tx counter */
-	u64 frame_65_127;		/* both rx and tx counter */
-	u64 frame_128_255;		/* both rx and tx counter */
-	u64 frame_256_511;		/* both rx and tx counter */
-	u64 frame_512_1023;	/* both rx and tx counter */
-	u64 frame_1024_1518;	/* both rx and tx counter */
-	u64 frame_1519_1522;	/* both rx and tx counter */
-
-	/* receive stats */
-	u64 rx_bytes;
-	u64 rx_packets;
-	u64 rx_fcs_error;
-	u64 rx_multicast;
-	u64 rx_broadcast;
-	u64 rx_control_frames;
-	u64 rx_pause;
-	u64 rx_unknown_opcode;
-	u64 rx_alignment_error;
-	u64 rx_frame_length_error;
-	u64 rx_code_error;
-	u64 rx_carrier_sense_error;
-	u64 rx_undersize;
-	u64 rx_oversize;
-	u64 rx_fragments;
-	u64 rx_jabber;
-	u64 rx_drop;
-
-	/* transmit stats */
-	u64 tx_bytes;
-	u64 tx_packets;
-	u64 tx_multicast;
-	u64 tx_broadcast;
-	u64 tx_pause;
-	u64 tx_deferral;
-	u64 tx_excessive_deferral;
-	u64 tx_single_collision;
-	u64 tx_muliple_collision;
-	u64 tx_late_collision;
-	u64 tx_excessive_collision;
-	u64 tx_total_collision;
-	u64 tx_pause_honored;
-	u64 tx_drop;
-	u64 tx_jabber;
-	u64 tx_fcs_error;
-	u64 tx_control_frame;
-	u64 tx_oversize;
-	u64 tx_undersize;
-	u64 tx_fragments;
-};
-
-/* Complete statistics */
-struct bfi_ll_stats {
-	struct bfi_ll_stats_mac		mac_stats;
-	struct bfi_ll_stats_bpc		bpc_stats;
-	struct bfi_ll_stats_rad		rad_stats;
-	struct bfi_ll_stats_fc_rx	fc_rx_stats;
-	struct bfi_ll_stats_fc_tx	fc_tx_stats;
-	struct bfi_ll_stats_rxf	rxf_stats[BFI_LL_RXF_ID_MAX];
-	struct bfi_ll_stats_txf	txf_stats[BFI_LL_TXF_ID_MAX];
-};
-
-#pragma pack()
-
-#endif  /* __BFI_LL_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bna_ctrl.c linux-libre-3.2-gnu/drivers/net/bna/bna_ctrl.c
--- linux-libre-3.1-gnu/drivers/net/bna/bna_ctrl.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bna_ctrl.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3076 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-#include "bna.h"
-#include "bfa_cs.h"
-
-static void bna_device_cb_port_stopped(void *arg, enum bna_cb_status status);
-
-static void
-bna_port_cb_link_up(struct bna_port *port, struct bfi_ll_aen *aen,
-			int status)
-{
-	int i;
-	u8 prio_map;
-
-	port->llport.link_status = BNA_LINK_UP;
-	if (aen->cee_linkup)
-		port->llport.link_status = BNA_CEE_UP;
-
-	/* Compute the priority */
-	prio_map = aen->prio_map;
-	if (prio_map) {
-		for (i = 0; i < 8; i++) {
-			if ((prio_map >> i) & 0x1)
-				break;
-		}
-		port->priority = i;
-	} else
-		port->priority = 0;
-
-	/* Dispatch events */
-	bna_tx_mod_cee_link_status(&port->bna->tx_mod, aen->cee_linkup);
-	bna_tx_mod_prio_changed(&port->bna->tx_mod, port->priority);
-	port->link_cbfn(port->bna->bnad, port->llport.link_status);
-}
-
-static void
-bna_port_cb_link_down(struct bna_port *port, int status)
-{
-	port->llport.link_status = BNA_LINK_DOWN;
-
-	/* Dispatch events */
-	bna_tx_mod_cee_link_status(&port->bna->tx_mod, BNA_LINK_DOWN);
-	port->link_cbfn(port->bna->bnad, BNA_LINK_DOWN);
-}
-
-static inline int
-llport_can_be_up(struct bna_llport *llport)
-{
-	int ready = 0;
-	if (llport->type == BNA_PORT_T_REGULAR)
-		ready = ((llport->flags & BNA_LLPORT_F_ADMIN_UP) &&
-			 (llport->flags & BNA_LLPORT_F_RX_STARTED) &&
-			 (llport->flags & BNA_LLPORT_F_PORT_ENABLED));
-	else
-		ready = ((llport->flags & BNA_LLPORT_F_ADMIN_UP) &&
-			 (llport->flags & BNA_LLPORT_F_RX_STARTED) &&
-			 !(llport->flags & BNA_LLPORT_F_PORT_ENABLED));
-	return ready;
-}
-
-#define llport_is_up llport_can_be_up
-
-enum bna_llport_event {
-	LLPORT_E_START			= 1,
-	LLPORT_E_STOP			= 2,
-	LLPORT_E_FAIL			= 3,
-	LLPORT_E_UP			= 4,
-	LLPORT_E_DOWN			= 5,
-	LLPORT_E_FWRESP_UP_OK		= 6,
-	LLPORT_E_FWRESP_UP_FAIL		= 7,
-	LLPORT_E_FWRESP_DOWN		= 8
-};
-
-static void
-bna_llport_cb_port_enabled(struct bna_llport *llport)
-{
-	llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
-
-	if (llport_can_be_up(llport))
-		bfa_fsm_send_event(llport, LLPORT_E_UP);
-}
-
-static void
-bna_llport_cb_port_disabled(struct bna_llport *llport)
-{
-	int llport_up = llport_is_up(llport);
-
-	llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
-
-	if (llport_up)
-		bfa_fsm_send_event(llport, LLPORT_E_DOWN);
-}
-
-/**
- * MBOX
- */
-static int
-bna_is_aen(u8 msg_id)
-{
-	switch (msg_id) {
-	case BFI_LL_I2H_LINK_DOWN_AEN:
-	case BFI_LL_I2H_LINK_UP_AEN:
-	case BFI_LL_I2H_PORT_ENABLE_AEN:
-	case BFI_LL_I2H_PORT_DISABLE_AEN:
-		return 1;
-
-	default:
-		return 0;
-	}
-}
-
-static void
-bna_mbox_aen_callback(struct bna *bna, struct bfi_mbmsg *msg)
-{
-	struct bfi_ll_aen *aen = (struct bfi_ll_aen *)(msg);
-
-	switch (aen->mh.msg_id) {
-	case BFI_LL_I2H_LINK_UP_AEN:
-		bna_port_cb_link_up(&bna->port, aen, aen->reason);
-		break;
-	case BFI_LL_I2H_LINK_DOWN_AEN:
-		bna_port_cb_link_down(&bna->port, aen->reason);
-		break;
-	case BFI_LL_I2H_PORT_ENABLE_AEN:
-		bna_llport_cb_port_enabled(&bna->port.llport);
-		break;
-	case BFI_LL_I2H_PORT_DISABLE_AEN:
-		bna_llport_cb_port_disabled(&bna->port.llport);
-		break;
-	default:
-		break;
-	}
-}
-
-static void
-bna_ll_isr(void *llarg, struct bfi_mbmsg *msg)
-{
-	struct bna *bna = (struct bna *)(llarg);
-	struct bfi_ll_rsp *mb_rsp = (struct bfi_ll_rsp *)(msg);
-	struct bfi_mhdr *cmd_h, *rsp_h;
-	struct bna_mbox_qe *mb_qe = NULL;
-	int to_post = 0;
-	u8 aen = 0;
-	char message[BNA_MESSAGE_SIZE];
-
-	aen = bna_is_aen(mb_rsp->mh.msg_id);
-
-	if (!aen) {
-		mb_qe = bfa_q_first(&bna->mbox_mod.posted_q);
-		cmd_h = (struct bfi_mhdr *)(&mb_qe->cmd.msg[0]);
-		rsp_h = (struct bfi_mhdr *)(&mb_rsp->mh);
-
-		if ((BFA_I2HM(cmd_h->msg_id) == rsp_h->msg_id) &&
-		    (cmd_h->mtag.i2htok == rsp_h->mtag.i2htok)) {
-			/* Remove the request from posted_q, update state  */
-			list_del(&mb_qe->qe);
-			bna->mbox_mod.msg_pending--;
-			if (list_empty(&bna->mbox_mod.posted_q))
-				bna->mbox_mod.state = BNA_MBOX_FREE;
-			else
-				to_post = 1;
-
-			/* Dispatch the cbfn */
-			if (mb_qe->cbfn)
-				mb_qe->cbfn(mb_qe->cbarg, mb_rsp->error);
-
-			/* Post the next entry, if needed */
-			if (to_post) {
-				mb_qe = bfa_q_first(&bna->mbox_mod.posted_q);
-				bfa_nw_ioc_mbox_queue(&bna->device.ioc,
-							&mb_qe->cmd);
-			}
-		} else {
-			snprintf(message, BNA_MESSAGE_SIZE,
-				       "No matching rsp for [%d:%d:%d]\n",
-				       mb_rsp->mh.msg_class, mb_rsp->mh.msg_id,
-				       mb_rsp->mh.mtag.i2htok);
-		pr_info("%s", message);
-		}
-
-	} else
-		bna_mbox_aen_callback(bna, msg);
-}
-
-static void
-bna_err_handler(struct bna *bna, u32 intr_status)
-{
-	u32 init_halt;
-
-	if (intr_status & __HALT_STATUS_BITS) {
-		init_halt = readl(bna->device.ioc.ioc_regs.ll_halt);
-		init_halt &= ~__FW_INIT_HALT_P;
-		writel(init_halt, bna->device.ioc.ioc_regs.ll_halt);
-	}
-
-	bfa_nw_ioc_error_isr(&bna->device.ioc);
-}
-
-void
-bna_mbox_handler(struct bna *bna, u32 intr_status)
-{
-	if (BNA_IS_ERR_INTR(intr_status)) {
-		bna_err_handler(bna, intr_status);
-		return;
-	}
-	if (BNA_IS_MBOX_INTR(intr_status))
-		bfa_nw_ioc_mbox_isr(&bna->device.ioc);
-}
-
-void
-bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe)
-{
-	struct bfi_mhdr *mh;
-
-	mh = (struct bfi_mhdr *)(&mbox_qe->cmd.msg[0]);
-
-	mh->mtag.i2htok = htons(bna->mbox_mod.msg_ctr);
-	bna->mbox_mod.msg_ctr++;
-	bna->mbox_mod.msg_pending++;
-	if (bna->mbox_mod.state == BNA_MBOX_FREE) {
-		list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q);
-		bfa_nw_ioc_mbox_queue(&bna->device.ioc, &mbox_qe->cmd);
-		bna->mbox_mod.state = BNA_MBOX_POSTED;
-	} else {
-		list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q);
-	}
-}
-
-static void
-bna_mbox_flush_q(struct bna *bna, struct list_head *q)
-{
-	struct bna_mbox_qe *mb_qe = NULL;
-	struct list_head			*mb_q;
-	void 			(*cbfn)(void *arg, int status);
-	void 			*cbarg;
-
-	mb_q = &bna->mbox_mod.posted_q;
-
-	while (!list_empty(mb_q)) {
-		bfa_q_deq(mb_q, &mb_qe);
-		cbfn = mb_qe->cbfn;
-		cbarg = mb_qe->cbarg;
-		bfa_q_qe_init(mb_qe);
-		bna->mbox_mod.msg_pending--;
-
-		if (cbfn)
-			cbfn(cbarg, BNA_CB_NOT_EXEC);
-	}
-
-	bna->mbox_mod.state = BNA_MBOX_FREE;
-}
-
-static void
-bna_mbox_mod_start(struct bna_mbox_mod *mbox_mod)
-{
-}
-
-static void
-bna_mbox_mod_stop(struct bna_mbox_mod *mbox_mod)
-{
-	bna_mbox_flush_q(mbox_mod->bna, &mbox_mod->posted_q);
-}
-
-static void
-bna_mbox_mod_init(struct bna_mbox_mod *mbox_mod, struct bna *bna)
-{
-	bfa_nw_ioc_mbox_regisr(&bna->device.ioc, BFI_MC_LL, bna_ll_isr, bna);
-	mbox_mod->state = BNA_MBOX_FREE;
-	mbox_mod->msg_ctr = mbox_mod->msg_pending = 0;
-	INIT_LIST_HEAD(&mbox_mod->posted_q);
-	mbox_mod->bna = bna;
-}
-
-static void
-bna_mbox_mod_uninit(struct bna_mbox_mod *mbox_mod)
-{
-	mbox_mod->bna = NULL;
-}
-
-/**
- * LLPORT
- */
-#define call_llport_stop_cbfn(llport, status)\
-do {\
-	if ((llport)->stop_cbfn)\
-		(llport)->stop_cbfn(&(llport)->bna->port, status);\
-	(llport)->stop_cbfn = NULL;\
-} while (0)
-
-static void bna_fw_llport_up(struct bna_llport *llport);
-static void bna_fw_cb_llport_up(void *arg, int status);
-static void bna_fw_llport_down(struct bna_llport *llport);
-static void bna_fw_cb_llport_down(void *arg, int status);
-static void bna_llport_start(struct bna_llport *llport);
-static void bna_llport_stop(struct bna_llport *llport);
-static void bna_llport_fail(struct bna_llport *llport);
-
-enum bna_llport_state {
-	BNA_LLPORT_STOPPED		= 1,
-	BNA_LLPORT_DOWN			= 2,
-	BNA_LLPORT_UP_RESP_WAIT		= 3,
-	BNA_LLPORT_DOWN_RESP_WAIT	= 4,
-	BNA_LLPORT_UP			= 5,
-	BNA_LLPORT_LAST_RESP_WAIT 	= 6
-};
-
-bfa_fsm_state_decl(bna_llport, stopped, struct bna_llport,
-			enum bna_llport_event);
-bfa_fsm_state_decl(bna_llport, down, struct bna_llport,
-			enum bna_llport_event);
-bfa_fsm_state_decl(bna_llport, up_resp_wait, struct bna_llport,
-			enum bna_llport_event);
-bfa_fsm_state_decl(bna_llport, down_resp_wait, struct bna_llport,
-			enum bna_llport_event);
-bfa_fsm_state_decl(bna_llport, up, struct bna_llport,
-			enum bna_llport_event);
-bfa_fsm_state_decl(bna_llport, last_resp_wait, struct bna_llport,
-			enum bna_llport_event);
-
-static struct bfa_sm_table llport_sm_table[] = {
-	{BFA_SM(bna_llport_sm_stopped), BNA_LLPORT_STOPPED},
-	{BFA_SM(bna_llport_sm_down), BNA_LLPORT_DOWN},
-	{BFA_SM(bna_llport_sm_up_resp_wait), BNA_LLPORT_UP_RESP_WAIT},
-	{BFA_SM(bna_llport_sm_down_resp_wait), BNA_LLPORT_DOWN_RESP_WAIT},
-	{BFA_SM(bna_llport_sm_up), BNA_LLPORT_UP},
-	{BFA_SM(bna_llport_sm_last_resp_wait), BNA_LLPORT_LAST_RESP_WAIT}
-};
-
-static void
-bna_llport_sm_stopped_entry(struct bna_llport *llport)
-{
-	llport->bna->port.link_cbfn((llport)->bna->bnad, BNA_LINK_DOWN);
-	call_llport_stop_cbfn(llport, BNA_CB_SUCCESS);
-}
-
-static void
-bna_llport_sm_stopped(struct bna_llport *llport,
-			enum bna_llport_event event)
-{
-	switch (event) {
-	case LLPORT_E_START:
-		bfa_fsm_set_state(llport, bna_llport_sm_down);
-		break;
-
-	case LLPORT_E_STOP:
-		call_llport_stop_cbfn(llport, BNA_CB_SUCCESS);
-		break;
-
-	case LLPORT_E_FAIL:
-		break;
-
-	case LLPORT_E_DOWN:
-		/* This event is received due to Rx objects failing */
-		/* No-op */
-		break;
-
-	case LLPORT_E_FWRESP_UP_OK:
-	case LLPORT_E_FWRESP_DOWN:
-		/**
-		 * These events are received due to flushing of mbox when
-		 * device fails
-		 */
-		/* No-op */
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_llport_sm_down_entry(struct bna_llport *llport)
-{
-	bnad_cb_port_link_status((llport)->bna->bnad, BNA_LINK_DOWN);
-}
-
-static void
-bna_llport_sm_down(struct bna_llport *llport,
-			enum bna_llport_event event)
-{
-	switch (event) {
-	case LLPORT_E_STOP:
-		bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-		break;
-
-	case LLPORT_E_FAIL:
-		bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-		break;
-
-	case LLPORT_E_UP:
-		bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait);
-		bna_fw_llport_up(llport);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_llport_sm_up_resp_wait_entry(struct bna_llport *llport)
-{
-	BUG_ON(!llport_can_be_up(llport));
-	/**
-	 * NOTE: Do not call bna_fw_llport_up() here. That will over step
-	 * mbox due to down_resp_wait -> up_resp_wait transition on event
-	 * LLPORT_E_UP
-	 */
-}
-
-static void
-bna_llport_sm_up_resp_wait(struct bna_llport *llport,
-			enum bna_llport_event event)
-{
-	switch (event) {
-	case LLPORT_E_STOP:
-		bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait);
-		break;
-
-	case LLPORT_E_FAIL:
-		bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-		break;
-
-	case LLPORT_E_DOWN:
-		bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait);
-		break;
-
-	case LLPORT_E_FWRESP_UP_OK:
-		bfa_fsm_set_state(llport, bna_llport_sm_up);
-		break;
-
-	case LLPORT_E_FWRESP_UP_FAIL:
-		bfa_fsm_set_state(llport, bna_llport_sm_down);
-		break;
-
-	case LLPORT_E_FWRESP_DOWN:
-		/* down_resp_wait -> up_resp_wait transition on LLPORT_E_UP */
-		bna_fw_llport_up(llport);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_llport_sm_down_resp_wait_entry(struct bna_llport *llport)
-{
-	/**
-	 * NOTE: Do not call bna_fw_llport_down() here. That will over step
-	 * mbox due to up_resp_wait -> down_resp_wait transition on event
-	 * LLPORT_E_DOWN
-	 */
-}
-
-static void
-bna_llport_sm_down_resp_wait(struct bna_llport *llport,
-			enum bna_llport_event event)
-{
-	switch (event) {
-	case LLPORT_E_STOP:
-		bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait);
-		break;
-
-	case LLPORT_E_FAIL:
-		bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-		break;
-
-	case LLPORT_E_UP:
-		bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait);
-		break;
-
-	case LLPORT_E_FWRESP_UP_OK:
-		/* up_resp_wait->down_resp_wait transition on LLPORT_E_DOWN */
-		bna_fw_llport_down(llport);
-		break;
-
-	case LLPORT_E_FWRESP_UP_FAIL:
-	case LLPORT_E_FWRESP_DOWN:
-		bfa_fsm_set_state(llport, bna_llport_sm_down);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_llport_sm_up_entry(struct bna_llport *llport)
-{
-}
-
-static void
-bna_llport_sm_up(struct bna_llport *llport,
-			enum bna_llport_event event)
-{
-	switch (event) {
-	case LLPORT_E_STOP:
-		bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait);
-		bna_fw_llport_down(llport);
-		break;
-
-	case LLPORT_E_FAIL:
-		bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-		break;
-
-	case LLPORT_E_DOWN:
-		bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait);
-		bna_fw_llport_down(llport);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_llport_sm_last_resp_wait_entry(struct bna_llport *llport)
-{
-}
-
-static void
-bna_llport_sm_last_resp_wait(struct bna_llport *llport,
-			enum bna_llport_event event)
-{
-	switch (event) {
-	case LLPORT_E_FAIL:
-		bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-		break;
-
-	case LLPORT_E_DOWN:
-		/**
-		 * This event is received due to Rx objects stopping in
-		 * parallel to llport
-		 */
-		/* No-op */
-		break;
-
-	case LLPORT_E_FWRESP_UP_OK:
-		/* up_resp_wait->last_resp_wait transition on LLPORT_T_STOP */
-		bna_fw_llport_down(llport);
-		break;
-
-	case LLPORT_E_FWRESP_UP_FAIL:
-	case LLPORT_E_FWRESP_DOWN:
-		bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_fw_llport_admin_up(struct bna_llport *llport)
-{
-	struct bfi_ll_port_admin_req ll_req;
-
-	memset(&ll_req, 0, sizeof(ll_req));
-	ll_req.mh.msg_class = BFI_MC_LL;
-	ll_req.mh.msg_id = BFI_LL_H2I_PORT_ADMIN_REQ;
-	ll_req.mh.mtag.h2i.lpu_id = 0;
-
-	ll_req.up = BNA_STATUS_T_ENABLED;
-
-	bna_mbox_qe_fill(&llport->mbox_qe, &ll_req, sizeof(ll_req),
-			bna_fw_cb_llport_up, llport);
-
-	bna_mbox_send(llport->bna, &llport->mbox_qe);
-}
-
-static void
-bna_fw_llport_up(struct bna_llport *llport)
-{
-	if (llport->type == BNA_PORT_T_REGULAR)
-		bna_fw_llport_admin_up(llport);
-}
-
-static void
-bna_fw_cb_llport_up(void *arg, int status)
-{
-	struct bna_llport *llport = (struct bna_llport *)arg;
-
-	bfa_q_qe_init(&llport->mbox_qe.qe);
-	if (status == BFI_LL_CMD_FAIL) {
-		if (llport->type == BNA_PORT_T_REGULAR)
-			llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
-		else
-			llport->flags &= ~BNA_LLPORT_F_ADMIN_UP;
-		bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP_FAIL);
-	} else
-		bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP_OK);
-}
-
-static void
-bna_fw_llport_admin_down(struct bna_llport *llport)
-{
-	struct bfi_ll_port_admin_req ll_req;
-
-	memset(&ll_req, 0, sizeof(ll_req));
-	ll_req.mh.msg_class = BFI_MC_LL;
-	ll_req.mh.msg_id = BFI_LL_H2I_PORT_ADMIN_REQ;
-	ll_req.mh.mtag.h2i.lpu_id = 0;
-
-	ll_req.up = BNA_STATUS_T_DISABLED;
-
-	bna_mbox_qe_fill(&llport->mbox_qe, &ll_req, sizeof(ll_req),
-			bna_fw_cb_llport_down, llport);
-
-	bna_mbox_send(llport->bna, &llport->mbox_qe);
-}
-
-static void
-bna_fw_llport_down(struct bna_llport *llport)
-{
-	if (llport->type == BNA_PORT_T_REGULAR)
-		bna_fw_llport_admin_down(llport);
-}
-
-static void
-bna_fw_cb_llport_down(void *arg, int status)
-{
-	struct bna_llport *llport = (struct bna_llport *)arg;
-
-	bfa_q_qe_init(&llport->mbox_qe.qe);
-	bfa_fsm_send_event(llport, LLPORT_E_FWRESP_DOWN);
-}
-
-static void
-bna_port_cb_llport_stopped(struct bna_port *port,
-				enum bna_cb_status status)
-{
-	bfa_wc_down(&port->chld_stop_wc);
-}
-
-static void
-bna_llport_init(struct bna_llport *llport, struct bna *bna)
-{
-	llport->flags |= BNA_LLPORT_F_ADMIN_UP;
-	llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
-	llport->type = BNA_PORT_T_REGULAR;
-	llport->bna = bna;
-
-	llport->link_status = BNA_LINK_DOWN;
-
-	llport->rx_started_count = 0;
-
-	llport->stop_cbfn = NULL;
-
-	bfa_q_qe_init(&llport->mbox_qe.qe);
-
-	bfa_fsm_set_state(llport, bna_llport_sm_stopped);
-}
-
-static void
-bna_llport_uninit(struct bna_llport *llport)
-{
-	llport->flags &= ~BNA_LLPORT_F_ADMIN_UP;
-	llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED;
-
-	llport->bna = NULL;
-}
-
-static void
-bna_llport_start(struct bna_llport *llport)
-{
-	bfa_fsm_send_event(llport, LLPORT_E_START);
-}
-
-static void
-bna_llport_stop(struct bna_llport *llport)
-{
-	llport->stop_cbfn = bna_port_cb_llport_stopped;
-
-	bfa_fsm_send_event(llport, LLPORT_E_STOP);
-}
-
-static void
-bna_llport_fail(struct bna_llport *llport)
-{
-	/* Reset the physical port status to enabled */
-	llport->flags |= BNA_LLPORT_F_PORT_ENABLED;
-	bfa_fsm_send_event(llport, LLPORT_E_FAIL);
-}
-
-static int
-bna_llport_state_get(struct bna_llport *llport)
-{
-	return bfa_sm_to_state(llport_sm_table, llport->fsm);
-}
-
-void
-bna_llport_rx_started(struct bna_llport *llport)
-{
-	llport->rx_started_count++;
-
-	if (llport->rx_started_count == 1) {
-
-		llport->flags |= BNA_LLPORT_F_RX_STARTED;
-
-		if (llport_can_be_up(llport))
-			bfa_fsm_send_event(llport, LLPORT_E_UP);
-	}
-}
-
-void
-bna_llport_rx_stopped(struct bna_llport *llport)
-{
-	int llport_up = llport_is_up(llport);
-
-	llport->rx_started_count--;
-
-	if (llport->rx_started_count == 0) {
-
-		llport->flags &= ~BNA_LLPORT_F_RX_STARTED;
-
-		if (llport_up)
-			bfa_fsm_send_event(llport, LLPORT_E_DOWN);
-	}
-}
-
-/**
- * PORT
- */
-#define bna_port_chld_start(port)\
-do {\
-	enum bna_tx_type tx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
-					BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK;\
-	enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
-					BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
-	bna_llport_start(&(port)->llport);\
-	bna_tx_mod_start(&(port)->bna->tx_mod, tx_type);\
-	bna_rx_mod_start(&(port)->bna->rx_mod, rx_type);\
-} while (0)
-
-#define bna_port_chld_stop(port)\
-do {\
-	enum bna_tx_type tx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
-					BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK;\
-	enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
-					BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
-	bfa_wc_up(&(port)->chld_stop_wc);\
-	bfa_wc_up(&(port)->chld_stop_wc);\
-	bfa_wc_up(&(port)->chld_stop_wc);\
-	bna_llport_stop(&(port)->llport);\
-	bna_tx_mod_stop(&(port)->bna->tx_mod, tx_type);\
-	bna_rx_mod_stop(&(port)->bna->rx_mod, rx_type);\
-} while (0)
-
-#define bna_port_chld_fail(port)\
-do {\
-	bna_llport_fail(&(port)->llport);\
-	bna_tx_mod_fail(&(port)->bna->tx_mod);\
-	bna_rx_mod_fail(&(port)->bna->rx_mod);\
-} while (0)
-
-#define bna_port_rx_start(port)\
-do {\
-	enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
-					BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
-	bna_rx_mod_start(&(port)->bna->rx_mod, rx_type);\
-} while (0)
-
-#define bna_port_rx_stop(port)\
-do {\
-	enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
-					BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
-	bfa_wc_up(&(port)->chld_stop_wc);\
-	bna_rx_mod_stop(&(port)->bna->rx_mod, rx_type);\
-} while (0)
-
-#define call_port_stop_cbfn(port, status)\
-do {\
-	if ((port)->stop_cbfn)\
-		(port)->stop_cbfn((port)->stop_cbarg, status);\
-	(port)->stop_cbfn = NULL;\
-	(port)->stop_cbarg = NULL;\
-} while (0)
-
-#define call_port_pause_cbfn(port, status)\
-do {\
-	if ((port)->pause_cbfn)\
-		(port)->pause_cbfn((port)->bna->bnad, status);\
-	(port)->pause_cbfn = NULL;\
-} while (0)
-
-#define call_port_mtu_cbfn(port, status)\
-do {\
-	if ((port)->mtu_cbfn)\
-		(port)->mtu_cbfn((port)->bna->bnad, status);\
-	(port)->mtu_cbfn = NULL;\
-} while (0)
-
-static void bna_fw_pause_set(struct bna_port *port);
-static void bna_fw_cb_pause_set(void *arg, int status);
-static void bna_fw_mtu_set(struct bna_port *port);
-static void bna_fw_cb_mtu_set(void *arg, int status);
-
-enum bna_port_event {
-	PORT_E_START			= 1,
-	PORT_E_STOP			= 2,
-	PORT_E_FAIL			= 3,
-	PORT_E_PAUSE_CFG		= 4,
-	PORT_E_MTU_CFG			= 5,
-	PORT_E_CHLD_STOPPED		= 6,
-	PORT_E_FWRESP_PAUSE		= 7,
-	PORT_E_FWRESP_MTU		= 8
-};
-
-enum bna_port_state {
-	BNA_PORT_STOPPED		= 1,
-	BNA_PORT_MTU_INIT_WAIT		= 2,
-	BNA_PORT_PAUSE_INIT_WAIT	= 3,
-	BNA_PORT_LAST_RESP_WAIT		= 4,
-	BNA_PORT_STARTED		= 5,
-	BNA_PORT_PAUSE_CFG_WAIT		= 6,
-	BNA_PORT_RX_STOP_WAIT		= 7,
-	BNA_PORT_MTU_CFG_WAIT 		= 8,
-	BNA_PORT_CHLD_STOP_WAIT		= 9
-};
-
-bfa_fsm_state_decl(bna_port, stopped, struct bna_port,
-			enum bna_port_event);
-bfa_fsm_state_decl(bna_port, mtu_init_wait, struct bna_port,
-			enum bna_port_event);
-bfa_fsm_state_decl(bna_port, pause_init_wait, struct bna_port,
-			enum bna_port_event);
-bfa_fsm_state_decl(bna_port, last_resp_wait, struct bna_port,
-			enum bna_port_event);
-bfa_fsm_state_decl(bna_port, started, struct bna_port,
-			enum bna_port_event);
-bfa_fsm_state_decl(bna_port, pause_cfg_wait, struct bna_port,
-			enum bna_port_event);
-bfa_fsm_state_decl(bna_port, rx_stop_wait, struct bna_port,
-			enum bna_port_event);
-bfa_fsm_state_decl(bna_port, mtu_cfg_wait, struct bna_port,
-			enum bna_port_event);
-bfa_fsm_state_decl(bna_port, chld_stop_wait, struct bna_port,
-			enum bna_port_event);
-
-static struct bfa_sm_table port_sm_table[] = {
-	{BFA_SM(bna_port_sm_stopped), BNA_PORT_STOPPED},
-	{BFA_SM(bna_port_sm_mtu_init_wait), BNA_PORT_MTU_INIT_WAIT},
-	{BFA_SM(bna_port_sm_pause_init_wait), BNA_PORT_PAUSE_INIT_WAIT},
-	{BFA_SM(bna_port_sm_last_resp_wait), BNA_PORT_LAST_RESP_WAIT},
-	{BFA_SM(bna_port_sm_started), BNA_PORT_STARTED},
-	{BFA_SM(bna_port_sm_pause_cfg_wait), BNA_PORT_PAUSE_CFG_WAIT},
-	{BFA_SM(bna_port_sm_rx_stop_wait), BNA_PORT_RX_STOP_WAIT},
-	{BFA_SM(bna_port_sm_mtu_cfg_wait), BNA_PORT_MTU_CFG_WAIT},
-	{BFA_SM(bna_port_sm_chld_stop_wait), BNA_PORT_CHLD_STOP_WAIT}
-};
-
-static void
-bna_port_sm_stopped_entry(struct bna_port *port)
-{
-	call_port_pause_cbfn(port, BNA_CB_SUCCESS);
-	call_port_mtu_cbfn(port, BNA_CB_SUCCESS);
-	call_port_stop_cbfn(port, BNA_CB_SUCCESS);
-}
-
-static void
-bna_port_sm_stopped(struct bna_port *port, enum bna_port_event event)
-{
-	switch (event) {
-	case PORT_E_START:
-		bfa_fsm_set_state(port, bna_port_sm_mtu_init_wait);
-		break;
-
-	case PORT_E_STOP:
-		call_port_stop_cbfn(port, BNA_CB_SUCCESS);
-		break;
-
-	case PORT_E_FAIL:
-		/* No-op */
-		break;
-
-	case PORT_E_PAUSE_CFG:
-		call_port_pause_cbfn(port, BNA_CB_SUCCESS);
-		break;
-
-	case PORT_E_MTU_CFG:
-		call_port_mtu_cbfn(port, BNA_CB_SUCCESS);
-		break;
-
-	case PORT_E_CHLD_STOPPED:
-		/**
-		 * This event is received due to LLPort, Tx and Rx objects
-		 * failing
-		 */
-		/* No-op */
-		break;
-
-	case PORT_E_FWRESP_PAUSE:
-	case PORT_E_FWRESP_MTU:
-		/**
-		 * These events are received due to flushing of mbox when
-		 * device fails
-		 */
-		/* No-op */
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_port_sm_mtu_init_wait_entry(struct bna_port *port)
-{
-	bna_fw_mtu_set(port);
-}
-
-static void
-bna_port_sm_mtu_init_wait(struct bna_port *port, enum bna_port_event event)
-{
-	switch (event) {
-	case PORT_E_STOP:
-		bfa_fsm_set_state(port, bna_port_sm_last_resp_wait);
-		break;
-
-	case PORT_E_FAIL:
-		bfa_fsm_set_state(port, bna_port_sm_stopped);
-		break;
-
-	case PORT_E_PAUSE_CFG:
-		/* No-op */
-		break;
-
-	case PORT_E_MTU_CFG:
-		port->flags |= BNA_PORT_F_MTU_CHANGED;
-		break;
-
-	case PORT_E_FWRESP_MTU:
-		if (port->flags & BNA_PORT_F_MTU_CHANGED) {
-			port->flags &= ~BNA_PORT_F_MTU_CHANGED;
-			bna_fw_mtu_set(port);
-		} else {
-			bfa_fsm_set_state(port, bna_port_sm_pause_init_wait);
-		}
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_port_sm_pause_init_wait_entry(struct bna_port *port)
-{
-	bna_fw_pause_set(port);
-}
-
-static void
-bna_port_sm_pause_init_wait(struct bna_port *port,
-				enum bna_port_event event)
-{
-	switch (event) {
-	case PORT_E_STOP:
-		bfa_fsm_set_state(port, bna_port_sm_last_resp_wait);
-		break;
-
-	case PORT_E_FAIL:
-		bfa_fsm_set_state(port, bna_port_sm_stopped);
-		break;
-
-	case PORT_E_PAUSE_CFG:
-		port->flags |= BNA_PORT_F_PAUSE_CHANGED;
-		break;
-
-	case PORT_E_MTU_CFG:
-		port->flags |= BNA_PORT_F_MTU_CHANGED;
-		break;
-
-	case PORT_E_FWRESP_PAUSE:
-		if (port->flags & BNA_PORT_F_PAUSE_CHANGED) {
-			port->flags &= ~BNA_PORT_F_PAUSE_CHANGED;
-			bna_fw_pause_set(port);
-		} else if (port->flags & BNA_PORT_F_MTU_CHANGED) {
-			port->flags &= ~BNA_PORT_F_MTU_CHANGED;
-			bfa_fsm_set_state(port, bna_port_sm_mtu_init_wait);
-		} else {
-			bfa_fsm_set_state(port, bna_port_sm_started);
-			bna_port_chld_start(port);
-		}
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_port_sm_last_resp_wait_entry(struct bna_port *port)
-{
-}
-
-static void
-bna_port_sm_last_resp_wait(struct bna_port *port,
-				enum bna_port_event event)
-{
-	switch (event) {
-	case PORT_E_FAIL:
-	case PORT_E_FWRESP_PAUSE:
-	case PORT_E_FWRESP_MTU:
-		bfa_fsm_set_state(port, bna_port_sm_stopped);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_port_sm_started_entry(struct bna_port *port)
-{
-	/**
-	 * NOTE: Do not call bna_port_chld_start() here, since it will be
-	 * inadvertently called during pause_cfg_wait->started transition
-	 * as well
-	 */
-	call_port_pause_cbfn(port, BNA_CB_SUCCESS);
-	call_port_mtu_cbfn(port, BNA_CB_SUCCESS);
-}
-
-static void
-bna_port_sm_started(struct bna_port *port,
-			enum bna_port_event event)
-{
-	switch (event) {
-	case PORT_E_STOP:
-		bfa_fsm_set_state(port, bna_port_sm_chld_stop_wait);
-		break;
-
-	case PORT_E_FAIL:
-		bfa_fsm_set_state(port, bna_port_sm_stopped);
-		bna_port_chld_fail(port);
-		break;
-
-	case PORT_E_PAUSE_CFG:
-		bfa_fsm_set_state(port, bna_port_sm_pause_cfg_wait);
-		break;
-
-	case PORT_E_MTU_CFG:
-		bfa_fsm_set_state(port, bna_port_sm_rx_stop_wait);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_port_sm_pause_cfg_wait_entry(struct bna_port *port)
-{
-	bna_fw_pause_set(port);
-}
-
-static void
-bna_port_sm_pause_cfg_wait(struct bna_port *port,
-				enum bna_port_event event)
-{
-	switch (event) {
-	case PORT_E_FAIL:
-		bfa_fsm_set_state(port, bna_port_sm_stopped);
-		bna_port_chld_fail(port);
-		break;
-
-	case PORT_E_FWRESP_PAUSE:
-		bfa_fsm_set_state(port, bna_port_sm_started);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_port_sm_rx_stop_wait_entry(struct bna_port *port)
-{
-	bna_port_rx_stop(port);
-}
-
-static void
-bna_port_sm_rx_stop_wait(struct bna_port *port,
-				enum bna_port_event event)
-{
-	switch (event) {
-	case PORT_E_FAIL:
-		bfa_fsm_set_state(port, bna_port_sm_stopped);
-		bna_port_chld_fail(port);
-		break;
-
-	case PORT_E_CHLD_STOPPED:
-		bfa_fsm_set_state(port, bna_port_sm_mtu_cfg_wait);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_port_sm_mtu_cfg_wait_entry(struct bna_port *port)
-{
-	bna_fw_mtu_set(port);
-}
-
-static void
-bna_port_sm_mtu_cfg_wait(struct bna_port *port, enum bna_port_event event)
-{
-	switch (event) {
-	case PORT_E_FAIL:
-		bfa_fsm_set_state(port, bna_port_sm_stopped);
-		bna_port_chld_fail(port);
-		break;
-
-	case PORT_E_FWRESP_MTU:
-		bfa_fsm_set_state(port, bna_port_sm_started);
-		bna_port_rx_start(port);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_port_sm_chld_stop_wait_entry(struct bna_port *port)
-{
-	bna_port_chld_stop(port);
-}
-
-static void
-bna_port_sm_chld_stop_wait(struct bna_port *port,
-				enum bna_port_event event)
-{
-	switch (event) {
-	case PORT_E_FAIL:
-		bfa_fsm_set_state(port, bna_port_sm_stopped);
-		bna_port_chld_fail(port);
-		break;
-
-	case PORT_E_CHLD_STOPPED:
-		bfa_fsm_set_state(port, bna_port_sm_stopped);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_fw_pause_set(struct bna_port *port)
-{
-	struct bfi_ll_set_pause_req ll_req;
-
-	memset(&ll_req, 0, sizeof(ll_req));
-	ll_req.mh.msg_class = BFI_MC_LL;
-	ll_req.mh.msg_id = BFI_LL_H2I_SET_PAUSE_REQ;
-	ll_req.mh.mtag.h2i.lpu_id = 0;
-
-	ll_req.tx_pause = port->pause_config.tx_pause;
-	ll_req.rx_pause = port->pause_config.rx_pause;
-
-	bna_mbox_qe_fill(&port->mbox_qe, &ll_req, sizeof(ll_req),
-			bna_fw_cb_pause_set, port);
-
-	bna_mbox_send(port->bna, &port->mbox_qe);
-}
-
-static void
-bna_fw_cb_pause_set(void *arg, int status)
-{
-	struct bna_port *port = (struct bna_port *)arg;
-
-	bfa_q_qe_init(&port->mbox_qe.qe);
-	bfa_fsm_send_event(port, PORT_E_FWRESP_PAUSE);
-}
-
-void
-bna_fw_mtu_set(struct bna_port *port)
-{
-	struct bfi_ll_mtu_info_req ll_req;
-
-	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_MTU_INFO_REQ, 0);
-	ll_req.mtu = htons((u16)port->mtu);
-
-	bna_mbox_qe_fill(&port->mbox_qe, &ll_req, sizeof(ll_req),
-				bna_fw_cb_mtu_set, port);
-	bna_mbox_send(port->bna, &port->mbox_qe);
-}
-
-void
-bna_fw_cb_mtu_set(void *arg, int status)
-{
-	struct bna_port *port = (struct bna_port *)arg;
-
-	bfa_q_qe_init(&port->mbox_qe.qe);
-	bfa_fsm_send_event(port, PORT_E_FWRESP_MTU);
-}
-
-static void
-bna_port_cb_chld_stopped(void *arg)
-{
-	struct bna_port *port = (struct bna_port *)arg;
-
-	bfa_fsm_send_event(port, PORT_E_CHLD_STOPPED);
-}
-
-static void
-bna_port_init(struct bna_port *port, struct bna *bna)
-{
-	port->bna = bna;
-	port->flags = 0;
-	port->mtu = 0;
-	port->type = BNA_PORT_T_REGULAR;
-
-	port->link_cbfn = bnad_cb_port_link_status;
-
-	port->chld_stop_wc.wc_resume = bna_port_cb_chld_stopped;
-	port->chld_stop_wc.wc_cbarg = port;
-	port->chld_stop_wc.wc_count = 0;
-
-	port->stop_cbfn = NULL;
-	port->stop_cbarg = NULL;
-
-	port->pause_cbfn = NULL;
-
-	port->mtu_cbfn = NULL;
-
-	bfa_q_qe_init(&port->mbox_qe.qe);
-
-	bfa_fsm_set_state(port, bna_port_sm_stopped);
-
-	bna_llport_init(&port->llport, bna);
-}
-
-static void
-bna_port_uninit(struct bna_port *port)
-{
-	bna_llport_uninit(&port->llport);
-
-	port->flags = 0;
-
-	port->bna = NULL;
-}
-
-static int
-bna_port_state_get(struct bna_port *port)
-{
-	return bfa_sm_to_state(port_sm_table, port->fsm);
-}
-
-static void
-bna_port_start(struct bna_port *port)
-{
-	port->flags |= BNA_PORT_F_DEVICE_READY;
-	if (port->flags & BNA_PORT_F_ENABLED)
-		bfa_fsm_send_event(port, PORT_E_START);
-}
-
-static void
-bna_port_stop(struct bna_port *port)
-{
-	port->stop_cbfn = bna_device_cb_port_stopped;
-	port->stop_cbarg = &port->bna->device;
-
-	port->flags &= ~BNA_PORT_F_DEVICE_READY;
-	bfa_fsm_send_event(port, PORT_E_STOP);
-}
-
-static void
-bna_port_fail(struct bna_port *port)
-{
-	port->flags &= ~BNA_PORT_F_DEVICE_READY;
-	bfa_fsm_send_event(port, PORT_E_FAIL);
-}
-
-void
-bna_port_cb_tx_stopped(struct bna_port *port, enum bna_cb_status status)
-{
-	bfa_wc_down(&port->chld_stop_wc);
-}
-
-void
-bna_port_cb_rx_stopped(struct bna_port *port, enum bna_cb_status status)
-{
-	bfa_wc_down(&port->chld_stop_wc);
-}
-
-int
-bna_port_mtu_get(struct bna_port *port)
-{
-	return port->mtu;
-}
-
-void
-bna_port_enable(struct bna_port *port)
-{
-	if (port->fsm != (bfa_sm_t)bna_port_sm_stopped)
-		return;
-
-	port->flags |= BNA_PORT_F_ENABLED;
-
-	if (port->flags & BNA_PORT_F_DEVICE_READY)
-		bfa_fsm_send_event(port, PORT_E_START);
-}
-
-void
-bna_port_disable(struct bna_port *port, enum bna_cleanup_type type,
-		 void (*cbfn)(void *, enum bna_cb_status))
-{
-	if (type == BNA_SOFT_CLEANUP) {
-		(*cbfn)(port->bna->bnad, BNA_CB_SUCCESS);
-		return;
-	}
-
-	port->stop_cbfn = cbfn;
-	port->stop_cbarg = port->bna->bnad;
-
-	port->flags &= ~BNA_PORT_F_ENABLED;
-
-	bfa_fsm_send_event(port, PORT_E_STOP);
-}
-
-void
-bna_port_pause_config(struct bna_port *port,
-		      struct bna_pause_config *pause_config,
-		      void (*cbfn)(struct bnad *, enum bna_cb_status))
-{
-	port->pause_config = *pause_config;
-
-	port->pause_cbfn = cbfn;
-
-	bfa_fsm_send_event(port, PORT_E_PAUSE_CFG);
-}
-
-void
-bna_port_mtu_set(struct bna_port *port, int mtu,
-		 void (*cbfn)(struct bnad *, enum bna_cb_status))
-{
-	port->mtu = mtu;
-
-	port->mtu_cbfn = cbfn;
-
-	bfa_fsm_send_event(port, PORT_E_MTU_CFG);
-}
-
-void
-bna_port_mac_get(struct bna_port *port, mac_t *mac)
-{
-	*mac = bfa_nw_ioc_get_mac(&port->bna->device.ioc);
-}
-
-/**
- * DEVICE
- */
-#define enable_mbox_intr(_device)\
-do {\
-	u32 intr_status;\
-	bna_intr_status_get((_device)->bna, intr_status);\
-	bnad_cb_device_enable_mbox_intr((_device)->bna->bnad);\
-	bna_mbox_intr_enable((_device)->bna);\
-} while (0)
-
-#define disable_mbox_intr(_device)\
-do {\
-	bna_mbox_intr_disable((_device)->bna);\
-	bnad_cb_device_disable_mbox_intr((_device)->bna->bnad);\
-} while (0)
-
-static const struct bna_chip_regs_offset reg_offset[] =
-{{HOST_PAGE_NUM_FN0, HOSTFN0_INT_STATUS,
-	HOSTFN0_INT_MASK, HOST_MSIX_ERR_INDEX_FN0},
-{HOST_PAGE_NUM_FN1, HOSTFN1_INT_STATUS,
-	HOSTFN1_INT_MASK, HOST_MSIX_ERR_INDEX_FN1},
-{HOST_PAGE_NUM_FN2, HOSTFN2_INT_STATUS,
-	HOSTFN2_INT_MASK, HOST_MSIX_ERR_INDEX_FN2},
-{HOST_PAGE_NUM_FN3, HOSTFN3_INT_STATUS,
-	HOSTFN3_INT_MASK, HOST_MSIX_ERR_INDEX_FN3},
-};
-
-enum bna_device_event {
-	DEVICE_E_ENABLE			= 1,
-	DEVICE_E_DISABLE		= 2,
-	DEVICE_E_IOC_READY		= 3,
-	DEVICE_E_IOC_FAILED		= 4,
-	DEVICE_E_IOC_DISABLED		= 5,
-	DEVICE_E_IOC_RESET		= 6,
-	DEVICE_E_PORT_STOPPED		= 7,
-};
-
-enum bna_device_state {
-	BNA_DEVICE_STOPPED		= 1,
-	BNA_DEVICE_IOC_READY_WAIT 	= 2,
-	BNA_DEVICE_READY		= 3,
-	BNA_DEVICE_PORT_STOP_WAIT 	= 4,
-	BNA_DEVICE_IOC_DISABLE_WAIT 	= 5,
-	BNA_DEVICE_FAILED		= 6
-};
-
-bfa_fsm_state_decl(bna_device, stopped, struct bna_device,
-			enum bna_device_event);
-bfa_fsm_state_decl(bna_device, ioc_ready_wait, struct bna_device,
-			enum bna_device_event);
-bfa_fsm_state_decl(bna_device, ready, struct bna_device,
-			enum bna_device_event);
-bfa_fsm_state_decl(bna_device, port_stop_wait, struct bna_device,
-			enum bna_device_event);
-bfa_fsm_state_decl(bna_device, ioc_disable_wait, struct bna_device,
-			enum bna_device_event);
-bfa_fsm_state_decl(bna_device, failed, struct bna_device,
-			enum bna_device_event);
-
-static struct bfa_sm_table device_sm_table[] = {
-	{BFA_SM(bna_device_sm_stopped), BNA_DEVICE_STOPPED},
-	{BFA_SM(bna_device_sm_ioc_ready_wait), BNA_DEVICE_IOC_READY_WAIT},
-	{BFA_SM(bna_device_sm_ready), BNA_DEVICE_READY},
-	{BFA_SM(bna_device_sm_port_stop_wait), BNA_DEVICE_PORT_STOP_WAIT},
-	{BFA_SM(bna_device_sm_ioc_disable_wait), BNA_DEVICE_IOC_DISABLE_WAIT},
-	{BFA_SM(bna_device_sm_failed), BNA_DEVICE_FAILED},
-};
-
-static void
-bna_device_sm_stopped_entry(struct bna_device *device)
-{
-	if (device->stop_cbfn)
-		device->stop_cbfn(device->stop_cbarg, BNA_CB_SUCCESS);
-
-	device->stop_cbfn = NULL;
-	device->stop_cbarg = NULL;
-}
-
-static void
-bna_device_sm_stopped(struct bna_device *device,
-			enum bna_device_event event)
-{
-	switch (event) {
-	case DEVICE_E_ENABLE:
-		if (device->intr_type == BNA_INTR_T_MSIX)
-			bna_mbox_msix_idx_set(device);
-		bfa_nw_ioc_enable(&device->ioc);
-		bfa_fsm_set_state(device, bna_device_sm_ioc_ready_wait);
-		break;
-
-	case DEVICE_E_DISABLE:
-		bfa_fsm_set_state(device, bna_device_sm_stopped);
-		break;
-
-	case DEVICE_E_IOC_RESET:
-		enable_mbox_intr(device);
-		break;
-
-	case DEVICE_E_IOC_FAILED:
-		bfa_fsm_set_state(device, bna_device_sm_failed);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_device_sm_ioc_ready_wait_entry(struct bna_device *device)
-{
-	/**
-	 * Do not call bfa_ioc_enable() here. It must be called in the
-	 * previous state due to failed -> ioc_ready_wait transition.
-	 */
-}
-
-static void
-bna_device_sm_ioc_ready_wait(struct bna_device *device,
-				enum bna_device_event event)
-{
-	switch (event) {
-	case DEVICE_E_DISABLE:
-		if (device->ready_cbfn)
-			device->ready_cbfn(device->ready_cbarg,
-						BNA_CB_INTERRUPT);
-		device->ready_cbfn = NULL;
-		device->ready_cbarg = NULL;
-		bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait);
-		break;
-
-	case DEVICE_E_IOC_READY:
-		bfa_fsm_set_state(device, bna_device_sm_ready);
-		break;
-
-	case DEVICE_E_IOC_FAILED:
-		bfa_fsm_set_state(device, bna_device_sm_failed);
-		break;
-
-	case DEVICE_E_IOC_RESET:
-		enable_mbox_intr(device);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_device_sm_ready_entry(struct bna_device *device)
-{
-	bna_mbox_mod_start(&device->bna->mbox_mod);
-	bna_port_start(&device->bna->port);
-
-	if (device->ready_cbfn)
-		device->ready_cbfn(device->ready_cbarg,
-					BNA_CB_SUCCESS);
-	device->ready_cbfn = NULL;
-	device->ready_cbarg = NULL;
-}
-
-static void
-bna_device_sm_ready(struct bna_device *device, enum bna_device_event event)
-{
-	switch (event) {
-	case DEVICE_E_DISABLE:
-		bfa_fsm_set_state(device, bna_device_sm_port_stop_wait);
-		break;
-
-	case DEVICE_E_IOC_FAILED:
-		bfa_fsm_set_state(device, bna_device_sm_failed);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_device_sm_port_stop_wait_entry(struct bna_device *device)
-{
-	bna_port_stop(&device->bna->port);
-}
-
-static void
-bna_device_sm_port_stop_wait(struct bna_device *device,
-				enum bna_device_event event)
-{
-	switch (event) {
-	case DEVICE_E_PORT_STOPPED:
-		bna_mbox_mod_stop(&device->bna->mbox_mod);
-		bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait);
-		break;
-
-	case DEVICE_E_IOC_FAILED:
-		disable_mbox_intr(device);
-		bna_port_fail(&device->bna->port);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_device_sm_ioc_disable_wait_entry(struct bna_device *device)
-{
-	bfa_nw_ioc_disable(&device->ioc);
-}
-
-static void
-bna_device_sm_ioc_disable_wait(struct bna_device *device,
-				enum bna_device_event event)
-{
-	switch (event) {
-	case DEVICE_E_IOC_DISABLED:
-		disable_mbox_intr(device);
-		bfa_fsm_set_state(device, bna_device_sm_stopped);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_device_sm_failed_entry(struct bna_device *device)
-{
-	disable_mbox_intr(device);
-	bna_port_fail(&device->bna->port);
-	bna_mbox_mod_stop(&device->bna->mbox_mod);
-
-	if (device->ready_cbfn)
-		device->ready_cbfn(device->ready_cbarg,
-					BNA_CB_FAIL);
-	device->ready_cbfn = NULL;
-	device->ready_cbarg = NULL;
-}
-
-static void
-bna_device_sm_failed(struct bna_device *device,
-			enum bna_device_event event)
-{
-	switch (event) {
-	case DEVICE_E_DISABLE:
-		bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait);
-		break;
-
-	case DEVICE_E_IOC_RESET:
-		enable_mbox_intr(device);
-		bfa_fsm_set_state(device, bna_device_sm_ioc_ready_wait);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-/* IOC callback functions */
-
-static void
-bna_device_cb_iocll_ready(void *dev, enum bfa_status error)
-{
-	struct bna_device *device = (struct bna_device *)dev;
-
-	if (error)
-		bfa_fsm_send_event(device, DEVICE_E_IOC_FAILED);
-	else
-		bfa_fsm_send_event(device, DEVICE_E_IOC_READY);
-}
-
-static void
-bna_device_cb_iocll_disabled(void *dev)
-{
-	struct bna_device *device = (struct bna_device *)dev;
-
-	bfa_fsm_send_event(device, DEVICE_E_IOC_DISABLED);
-}
-
-static void
-bna_device_cb_iocll_failed(void *dev)
-{
-	struct bna_device *device = (struct bna_device *)dev;
-
-	bfa_fsm_send_event(device, DEVICE_E_IOC_FAILED);
-}
-
-static void
-bna_device_cb_iocll_reset(void *dev)
-{
-	struct bna_device *device = (struct bna_device *)dev;
-
-	bfa_fsm_send_event(device, DEVICE_E_IOC_RESET);
-}
-
-static struct bfa_ioc_cbfn bfa_iocll_cbfn = {
-	bna_device_cb_iocll_ready,
-	bna_device_cb_iocll_disabled,
-	bna_device_cb_iocll_failed,
-	bna_device_cb_iocll_reset
-};
-
-/* device */
-static void
-bna_adv_device_init(struct bna_device *device, struct bna *bna,
-		struct bna_res_info *res_info)
-{
-	u8 *kva;
-	u64 dma;
-
-	device->bna = bna;
-
-	kva = res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.mdl[0].kva;
-
-	/**
-	 * Attach common modules (Diag, SFP, CEE, Port) and claim respective
-	 * DMA memory.
-	 */
-	BNA_GET_DMA_ADDR(
-		&res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].dma, dma);
-	kva = res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].kva;
-
-	bfa_nw_cee_attach(&bna->cee, &device->ioc, bna);
-	bfa_nw_cee_mem_claim(&bna->cee, kva, dma);
-	kva += bfa_nw_cee_meminfo();
-	dma += bfa_nw_cee_meminfo();
-
-}
-
-static void
-bna_device_init(struct bna_device *device, struct bna *bna,
-		struct bna_res_info *res_info)
-{
-	u64 dma;
-
-	device->bna = bna;
-
-	/**
-	 * Attach IOC and claim:
-	 *	1. DMA memory for IOC attributes
-	 *	2. Kernel memory for FW trace
-	 */
-	bfa_nw_ioc_attach(&device->ioc, device, &bfa_iocll_cbfn);
-	bfa_nw_ioc_pci_init(&device->ioc, &bna->pcidev, BFI_MC_LL);
-
-	BNA_GET_DMA_ADDR(
-		&res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].dma, dma);
-	bfa_nw_ioc_mem_claim(&device->ioc,
-		res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].kva,
-			  dma);
-
-	bna_adv_device_init(device, bna, res_info);
-	/*
-	 * Initialize mbox_mod only after IOC, so that mbox handler
-	 * registration goes through
-	 */
-	device->intr_type =
-		res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.intr_type;
-	device->vector =
-		res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.idl[0].vector;
-	bna_mbox_mod_init(&bna->mbox_mod, bna);
-
-	device->ready_cbfn = device->stop_cbfn = NULL;
-	device->ready_cbarg = device->stop_cbarg = NULL;
-
-	bfa_fsm_set_state(device, bna_device_sm_stopped);
-}
-
-static void
-bna_device_uninit(struct bna_device *device)
-{
-	bna_mbox_mod_uninit(&device->bna->mbox_mod);
-
-	bfa_nw_ioc_detach(&device->ioc);
-
-	device->bna = NULL;
-}
-
-static void
-bna_device_cb_port_stopped(void *arg, enum bna_cb_status status)
-{
-	struct bna_device *device = (struct bna_device *)arg;
-
-	bfa_fsm_send_event(device, DEVICE_E_PORT_STOPPED);
-}
-
-static int
-bna_device_status_get(struct bna_device *device)
-{
-	return device->fsm == (bfa_fsm_t)bna_device_sm_ready;
-}
-
-void
-bna_device_enable(struct bna_device *device)
-{
-	if (device->fsm != (bfa_fsm_t)bna_device_sm_stopped) {
-		bnad_cb_device_enabled(device->bna->bnad, BNA_CB_BUSY);
-		return;
-	}
-
-	device->ready_cbfn = bnad_cb_device_enabled;
-	device->ready_cbarg = device->bna->bnad;
-
-	bfa_fsm_send_event(device, DEVICE_E_ENABLE);
-}
-
-void
-bna_device_disable(struct bna_device *device, enum bna_cleanup_type type)
-{
-	if (type == BNA_SOFT_CLEANUP) {
-		bnad_cb_device_disabled(device->bna->bnad, BNA_CB_SUCCESS);
-		return;
-	}
-
-	device->stop_cbfn = bnad_cb_device_disabled;
-	device->stop_cbarg = device->bna->bnad;
-
-	bfa_fsm_send_event(device, DEVICE_E_DISABLE);
-}
-
-static int
-bna_device_state_get(struct bna_device *device)
-{
-	return bfa_sm_to_state(device_sm_table, device->fsm);
-}
-
-const u32 bna_napi_dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX] = {
-	{12, 12},
-	{6, 10},
-	{5, 10},
-	{4, 8},
-	{3, 6},
-	{3, 6},
-	{2, 4},
-	{1, 2},
-};
-
-/* utils */
-
-static void
-bna_adv_res_req(struct bna_res_info *res_info)
-{
-	/* DMA memory for COMMON_MODULE */
-	res_info[BNA_RES_MEM_T_COM].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
-	res_info[BNA_RES_MEM_T_COM].res_u.mem_info.num = 1;
-	res_info[BNA_RES_MEM_T_COM].res_u.mem_info.len = ALIGN(
-				bfa_nw_cee_meminfo(), PAGE_SIZE);
-
-	/* Virtual memory for retreiving fw_trc */
-	res_info[BNA_RES_MEM_T_FWTRC].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.mem_type = BNA_MEM_T_KVA;
-	res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.num = 0;
-	res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.len = 0;
-
-	/* DMA memory for retreiving stats */
-	res_info[BNA_RES_MEM_T_STATS].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
-	res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.num = 1;
-	res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.len =
-				ALIGN(BFI_HW_STATS_SIZE, PAGE_SIZE);
-
-	/* Virtual memory for soft stats */
-	res_info[BNA_RES_MEM_T_SWSTATS].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.mem_type = BNA_MEM_T_KVA;
-	res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.num = 1;
-	res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.len =
-				sizeof(struct bna_sw_stats);
-}
-
-static void
-bna_sw_stats_get(struct bna *bna, struct bna_sw_stats *sw_stats)
-{
-	struct bna_tx *tx;
-	struct bna_txq *txq;
-	struct bna_rx *rx;
-	struct bna_rxp *rxp;
-	struct list_head *qe;
-	struct list_head *txq_qe;
-	struct list_head *rxp_qe;
-	struct list_head *mac_qe;
-	int i;
-
-	sw_stats->device_state = bna_device_state_get(&bna->device);
-	sw_stats->port_state = bna_port_state_get(&bna->port);
-	sw_stats->port_flags = bna->port.flags;
-	sw_stats->llport_state = bna_llport_state_get(&bna->port.llport);
-	sw_stats->priority = bna->port.priority;
-
-	i = 0;
-	list_for_each(qe, &bna->tx_mod.tx_active_q) {
-		tx = (struct bna_tx *)qe;
-		sw_stats->tx_stats[i].tx_state = bna_tx_state_get(tx);
-		sw_stats->tx_stats[i].tx_flags = tx->flags;
-
-		sw_stats->tx_stats[i].num_txqs = 0;
-		sw_stats->tx_stats[i].txq_bmap[0] = 0;
-		sw_stats->tx_stats[i].txq_bmap[1] = 0;
-		list_for_each(txq_qe, &tx->txq_q) {
-			txq = (struct bna_txq *)txq_qe;
-			if (txq->txq_id < 32)
-				sw_stats->tx_stats[i].txq_bmap[0] |=
-						((u32)1 << txq->txq_id);
-			else
-				sw_stats->tx_stats[i].txq_bmap[1] |=
-						((u32)
-						 1 << (txq->txq_id - 32));
-			sw_stats->tx_stats[i].num_txqs++;
-		}
-
-		sw_stats->tx_stats[i].txf_id = tx->txf.txf_id;
-
-		i++;
-	}
-	sw_stats->num_active_tx = i;
-
-	i = 0;
-	list_for_each(qe, &bna->rx_mod.rx_active_q) {
-		rx = (struct bna_rx *)qe;
-		sw_stats->rx_stats[i].rx_state = bna_rx_state_get(rx);
-		sw_stats->rx_stats[i].rx_flags = rx->rx_flags;
-
-		sw_stats->rx_stats[i].num_rxps = 0;
-		sw_stats->rx_stats[i].num_rxqs = 0;
-		sw_stats->rx_stats[i].rxq_bmap[0] = 0;
-		sw_stats->rx_stats[i].rxq_bmap[1] = 0;
-		sw_stats->rx_stats[i].cq_bmap[0] = 0;
-		sw_stats->rx_stats[i].cq_bmap[1] = 0;
-		list_for_each(rxp_qe, &rx->rxp_q) {
-			rxp = (struct bna_rxp *)rxp_qe;
-
-			sw_stats->rx_stats[i].num_rxqs += 1;
-
-			if (rxp->type == BNA_RXP_SINGLE) {
-				if (rxp->rxq.single.only->rxq_id < 32) {
-					sw_stats->rx_stats[i].rxq_bmap[0] |=
-					((u32)1 <<
-					rxp->rxq.single.only->rxq_id);
-				} else {
-					sw_stats->rx_stats[i].rxq_bmap[1] |=
-					((u32)1 <<
-					(rxp->rxq.single.only->rxq_id - 32));
-				}
-			} else {
-				if (rxp->rxq.slr.large->rxq_id < 32) {
-					sw_stats->rx_stats[i].rxq_bmap[0] |=
-					((u32)1 <<
-					rxp->rxq.slr.large->rxq_id);
-				} else {
-					sw_stats->rx_stats[i].rxq_bmap[1] |=
-					((u32)1 <<
-					(rxp->rxq.slr.large->rxq_id - 32));
-				}
-
-				if (rxp->rxq.slr.small->rxq_id < 32) {
-					sw_stats->rx_stats[i].rxq_bmap[0] |=
-					((u32)1 <<
-					rxp->rxq.slr.small->rxq_id);
-				} else {
-					sw_stats->rx_stats[i].rxq_bmap[1] |=
-				((u32)1 <<
-				 (rxp->rxq.slr.small->rxq_id - 32));
-				}
-				sw_stats->rx_stats[i].num_rxqs += 1;
-			}
-
-			if (rxp->cq.cq_id < 32)
-				sw_stats->rx_stats[i].cq_bmap[0] |=
-					(1 << rxp->cq.cq_id);
-			else
-				sw_stats->rx_stats[i].cq_bmap[1] |=
-					(1 << (rxp->cq.cq_id - 32));
-
-			sw_stats->rx_stats[i].num_rxps++;
-		}
-
-		sw_stats->rx_stats[i].rxf_id = rx->rxf.rxf_id;
-		sw_stats->rx_stats[i].rxf_state = bna_rxf_state_get(&rx->rxf);
-		sw_stats->rx_stats[i].rxf_oper_state = rx->rxf.rxf_oper_state;
-
-		sw_stats->rx_stats[i].num_active_ucast = 0;
-		if (rx->rxf.ucast_active_mac)
-			sw_stats->rx_stats[i].num_active_ucast++;
-		list_for_each(mac_qe, &rx->rxf.ucast_active_q)
-			sw_stats->rx_stats[i].num_active_ucast++;
-
-		sw_stats->rx_stats[i].num_active_mcast = 0;
-		list_for_each(mac_qe, &rx->rxf.mcast_active_q)
-			sw_stats->rx_stats[i].num_active_mcast++;
-
-		sw_stats->rx_stats[i].rxmode_active = rx->rxf.rxmode_active;
-		sw_stats->rx_stats[i].vlan_filter_status =
-						rx->rxf.vlan_filter_status;
-		memcpy(sw_stats->rx_stats[i].vlan_filter_table,
-				rx->rxf.vlan_filter_table,
-				sizeof(u32) * ((BFI_MAX_VLAN + 1) / 32));
-
-		sw_stats->rx_stats[i].rss_status = rx->rxf.rss_status;
-		sw_stats->rx_stats[i].hds_status = rx->rxf.hds_status;
-
-		i++;
-	}
-	sw_stats->num_active_rx = i;
-}
-
-static void
-bna_fw_cb_stats_get(void *arg, int status)
-{
-	struct bna *bna = (struct bna *)arg;
-	u64 *p_stats;
-	int i, count;
-	int rxf_count, txf_count;
-	u64 rxf_bmap, txf_bmap;
-
-	bfa_q_qe_init(&bna->mbox_qe.qe);
-
-	if (status == 0) {
-		p_stats = (u64 *)bna->stats.hw_stats;
-		count = sizeof(struct bfi_ll_stats) / sizeof(u64);
-		for (i = 0; i < count; i++)
-			p_stats[i] = cpu_to_be64(p_stats[i]);
-
-		rxf_count = 0;
-		rxf_bmap = (u64)bna->stats.rxf_bmap[0] |
-			((u64)bna->stats.rxf_bmap[1] << 32);
-		for (i = 0; i < BFI_LL_RXF_ID_MAX; i++)
-			if (rxf_bmap & ((u64)1 << i))
-				rxf_count++;
-
-		txf_count = 0;
-		txf_bmap = (u64)bna->stats.txf_bmap[0] |
-			((u64)bna->stats.txf_bmap[1] << 32);
-		for (i = 0; i < BFI_LL_TXF_ID_MAX; i++)
-			if (txf_bmap & ((u64)1 << i))
-				txf_count++;
-
-		p_stats = (u64 *)&bna->stats.hw_stats->rxf_stats[0] +
-				((rxf_count * sizeof(struct bfi_ll_stats_rxf) +
-				txf_count * sizeof(struct bfi_ll_stats_txf))/
-				sizeof(u64));
-
-		/* Populate the TXF stats from the firmware DMAed copy */
-		for (i = (BFI_LL_TXF_ID_MAX - 1); i >= 0; i--)
-			if (txf_bmap & ((u64)1 << i)) {
-				p_stats -= sizeof(struct bfi_ll_stats_txf)/
-						sizeof(u64);
-				memcpy(&bna->stats.hw_stats->txf_stats[i],
-					p_stats,
-					sizeof(struct bfi_ll_stats_txf));
-			}
-
-		/* Populate the RXF stats from the firmware DMAed copy */
-		for (i = (BFI_LL_RXF_ID_MAX - 1); i >= 0; i--)
-			if (rxf_bmap & ((u64)1 << i)) {
-				p_stats -= sizeof(struct bfi_ll_stats_rxf)/
-						sizeof(u64);
-				memcpy(&bna->stats.hw_stats->rxf_stats[i],
-					p_stats,
-					sizeof(struct bfi_ll_stats_rxf));
-			}
-
-		bna_sw_stats_get(bna, bna->stats.sw_stats);
-		bnad_cb_stats_get(bna->bnad, BNA_CB_SUCCESS, &bna->stats);
-	} else
-		bnad_cb_stats_get(bna->bnad, BNA_CB_FAIL, &bna->stats);
-}
-
-static void
-bna_fw_stats_get(struct bna *bna)
-{
-	struct bfi_ll_stats_req ll_req;
-
-	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_GET_REQ, 0);
-	ll_req.stats_mask = htons(BFI_LL_STATS_ALL);
-
-	ll_req.rxf_id_mask[0] = htonl(bna->rx_mod.rxf_bmap[0]);
-	ll_req.rxf_id_mask[1] =	htonl(bna->rx_mod.rxf_bmap[1]);
-	ll_req.txf_id_mask[0] =	htonl(bna->tx_mod.txf_bmap[0]);
-	ll_req.txf_id_mask[1] =	htonl(bna->tx_mod.txf_bmap[1]);
-
-	ll_req.host_buffer.a32.addr_hi = bna->hw_stats_dma.msb;
-	ll_req.host_buffer.a32.addr_lo = bna->hw_stats_dma.lsb;
-
-	bna_mbox_qe_fill(&bna->mbox_qe, &ll_req, sizeof(ll_req),
-				bna_fw_cb_stats_get, bna);
-	bna_mbox_send(bna, &bna->mbox_qe);
-
-	bna->stats.rxf_bmap[0] = bna->rx_mod.rxf_bmap[0];
-	bna->stats.rxf_bmap[1] = bna->rx_mod.rxf_bmap[1];
-	bna->stats.txf_bmap[0] = bna->tx_mod.txf_bmap[0];
-	bna->stats.txf_bmap[1] = bna->tx_mod.txf_bmap[1];
-}
-
-void
-bna_stats_get(struct bna *bna)
-{
-	if (bna_device_status_get(&bna->device))
-		bna_fw_stats_get(bna);
-	else
-		bnad_cb_stats_get(bna->bnad, BNA_CB_FAIL, &bna->stats);
-}
-
-/* IB */
-static void
-bna_ib_coalescing_timeo_set(struct bna_ib *ib, u8 coalescing_timeo)
-{
-	ib->ib_config.coalescing_timeo = coalescing_timeo;
-
-	if (ib->start_count)
-		ib->door_bell.doorbell_ack = BNA_DOORBELL_IB_INT_ACK(
-				(u32)ib->ib_config.coalescing_timeo, 0);
-}
-
-/* RxF */
-void
-bna_rxf_adv_init(struct bna_rxf *rxf,
-		struct bna_rx *rx,
-		struct bna_rx_config *q_config)
-{
-	switch (q_config->rxp_type) {
-	case BNA_RXP_SINGLE:
-		/* No-op */
-		break;
-	case BNA_RXP_SLR:
-		rxf->ctrl_flags |= BNA_RXF_CF_SM_LG_RXQ;
-		break;
-	case BNA_RXP_HDS:
-		rxf->hds_cfg.hdr_type = q_config->hds_config.hdr_type;
-		rxf->hds_cfg.header_size =
-				q_config->hds_config.header_size;
-		rxf->forced_offset = 0;
-		break;
-	default:
-		break;
-	}
-
-	if (q_config->rss_status == BNA_STATUS_T_ENABLED) {
-		rxf->ctrl_flags |= BNA_RXF_CF_RSS_ENABLE;
-		rxf->rss_cfg.hash_type = q_config->rss_config.hash_type;
-		rxf->rss_cfg.hash_mask = q_config->rss_config.hash_mask;
-		memcpy(&rxf->rss_cfg.toeplitz_hash_key[0],
-			&q_config->rss_config.toeplitz_hash_key[0],
-			sizeof(rxf->rss_cfg.toeplitz_hash_key));
-	}
-}
-
-static void
-rxf_fltr_mbox_cmd(struct bna_rxf *rxf, u8 cmd, enum bna_status status)
-{
-	struct bfi_ll_rxf_req req;
-
-	bfi_h2i_set(req.mh, BFI_MC_LL, cmd, 0);
-
-	req.rxf_id = rxf->rxf_id;
-	req.enable = status;
-
-	bna_mbox_qe_fill(&rxf->mbox_qe, &req, sizeof(req),
-			rxf_cb_cam_fltr_mbox_cmd, rxf);
-
-	bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
-}
-
-int
-rxf_process_packet_filter_ucast(struct bna_rxf *rxf)
-{
-	struct bna_mac *mac = NULL;
-	struct list_head *qe;
-
-	/* Add additional MAC entries */
-	if (!list_empty(&rxf->ucast_pending_add_q)) {
-		bfa_q_deq(&rxf->ucast_pending_add_q, &qe);
-		bfa_q_qe_init(qe);
-		mac = (struct bna_mac *)qe;
-		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_ADD_REQ, mac);
-		list_add_tail(&mac->qe, &rxf->ucast_active_q);
-		return 1;
-	}
-
-	/* Delete MAC addresses previousely added */
-	if (!list_empty(&rxf->ucast_pending_del_q)) {
-		bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
-		bfa_q_qe_init(qe);
-		mac = (struct bna_mac *)qe;
-		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac);
-		bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
-		return 1;
-	}
-
-	return 0;
-}
-
-int
-rxf_process_packet_filter_promisc(struct bna_rxf *rxf)
-{
-	struct bna *bna = rxf->rx->bna;
-
-	/* Enable/disable promiscuous mode */
-	if (is_promisc_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask)) {
-		/* move promisc configuration from pending -> active */
-		promisc_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active |= BNA_RXMODE_PROMISC;
-
-		/* Disable VLAN filter to allow all VLANs */
-		__rxf_vlan_filter_set(rxf, BNA_STATUS_T_DISABLED);
-		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
-				BNA_STATUS_T_ENABLED);
-		return 1;
-	} else if (is_promisc_disable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask)) {
-		/* move promisc configuration from pending -> active */
-		promisc_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
-		bna->rxf_promisc_id = BFI_MAX_RXF;
-
-		/* Revert VLAN filter */
-		__rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
-		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
-				BNA_STATUS_T_DISABLED);
-		return 1;
-	}
-
-	return 0;
-}
-
-int
-rxf_process_packet_filter_allmulti(struct bna_rxf *rxf)
-{
-	/* Enable/disable allmulti mode */
-	if (is_allmulti_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask)) {
-		/* move allmulti configuration from pending -> active */
-		allmulti_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active |= BNA_RXMODE_ALLMULTI;
-
-		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
-				BNA_STATUS_T_ENABLED);
-		return 1;
-	} else if (is_allmulti_disable(rxf->rxmode_pending,
-					rxf->rxmode_pending_bitmask)) {
-		/* move allmulti configuration from pending -> active */
-		allmulti_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
-
-		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
-				BNA_STATUS_T_DISABLED);
-		return 1;
-	}
-
-	return 0;
-}
-
-int
-rxf_clear_packet_filter_ucast(struct bna_rxf *rxf)
-{
-	struct bna_mac *mac = NULL;
-	struct list_head *qe;
-
-	/* 1. delete pending ucast entries */
-	if (!list_empty(&rxf->ucast_pending_del_q)) {
-		bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
-		bfa_q_qe_init(qe);
-		mac = (struct bna_mac *)qe;
-		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac);
-		bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
-		return 1;
-	}
-
-	/* 2. clear active ucast entries; move them to pending_add_q */
-	if (!list_empty(&rxf->ucast_active_q)) {
-		bfa_q_deq(&rxf->ucast_active_q, &qe);
-		bfa_q_qe_init(qe);
-		mac = (struct bna_mac *)qe;
-		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac);
-		list_add_tail(&mac->qe, &rxf->ucast_pending_add_q);
-		return 1;
-	}
-
-	return 0;
-}
-
-int
-rxf_clear_packet_filter_promisc(struct bna_rxf *rxf)
-{
-	struct bna *bna = rxf->rx->bna;
-
-	/* 6. Execute pending promisc mode disable command */
-	if (is_promisc_disable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask)) {
-		/* move promisc configuration from pending -> active */
-		promisc_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
-		bna->rxf_promisc_id = BFI_MAX_RXF;
-
-		/* Revert VLAN filter */
-		__rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
-		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
-				BNA_STATUS_T_DISABLED);
-		return 1;
-	}
-
-	/* 7. Clear active promisc mode; move it to pending enable */
-	if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
-		/* move promisc configuration from active -> pending */
-		promisc_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
-
-		/* Revert VLAN filter */
-		__rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
-		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
-				BNA_STATUS_T_DISABLED);
-		return 1;
-	}
-
-	return 0;
-}
-
-int
-rxf_clear_packet_filter_allmulti(struct bna_rxf *rxf)
-{
-	/* 10. Execute pending allmulti mode disable command */
-	if (is_allmulti_disable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask)) {
-		/* move allmulti configuration from pending -> active */
-		allmulti_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
-		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
-				BNA_STATUS_T_DISABLED);
-		return 1;
-	}
-
-	/* 11. Clear active allmulti mode; move it to pending enable */
-	if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
-		/* move allmulti configuration from active -> pending */
-		allmulti_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
-		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
-				BNA_STATUS_T_DISABLED);
-		return 1;
-	}
-
-	return 0;
-}
-
-void
-rxf_reset_packet_filter_ucast(struct bna_rxf *rxf)
-{
-	struct list_head *qe;
-	struct bna_mac *mac;
-
-	/* 1. Move active ucast entries to pending_add_q */
-	while (!list_empty(&rxf->ucast_active_q)) {
-		bfa_q_deq(&rxf->ucast_active_q, &qe);
-		bfa_q_qe_init(qe);
-		list_add_tail(qe, &rxf->ucast_pending_add_q);
-	}
-
-	/* 2. Throw away delete pending ucast entries */
-	while (!list_empty(&rxf->ucast_pending_del_q)) {
-		bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
-		bfa_q_qe_init(qe);
-		mac = (struct bna_mac *)qe;
-		bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
-	}
-}
-
-void
-rxf_reset_packet_filter_promisc(struct bna_rxf *rxf)
-{
-	struct bna *bna = rxf->rx->bna;
-
-	/* 6. Clear pending promisc mode disable */
-	if (is_promisc_disable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask)) {
-		promisc_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
-		bna->rxf_promisc_id = BFI_MAX_RXF;
-	}
-
-	/* 7. Move promisc mode config from active -> pending */
-	if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
-		promisc_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
-	}
-
-}
-
-void
-rxf_reset_packet_filter_allmulti(struct bna_rxf *rxf)
-{
-	/* 10. Clear pending allmulti mode disable */
-	if (is_allmulti_disable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask)) {
-		allmulti_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
-	}
-
-	/* 11. Move allmulti mode config from active -> pending */
-	if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
-		allmulti_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
-	}
-}
-
-/**
- * Should only be called by bna_rxf_mode_set.
- * Helps deciding if h/w configuration is needed or not.
- *  Returns:
- *	0 = no h/w change
- *	1 = need h/w change
- */
-static int
-rxf_promisc_enable(struct bna_rxf *rxf)
-{
-	struct bna *bna = rxf->rx->bna;
-	int ret = 0;
-
-	/* There can not be any pending disable command */
-
-	/* Do nothing if pending enable or already enabled */
-	if (is_promisc_enable(rxf->rxmode_pending,
-			rxf->rxmode_pending_bitmask) ||
-			(rxf->rxmode_active & BNA_RXMODE_PROMISC)) {
-		/* Schedule enable */
-	} else {
-		/* Promisc mode should not be active in the system */
-		promisc_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		bna->rxf_promisc_id = rxf->rxf_id;
-		ret = 1;
-	}
-
-	return ret;
-}
-
-/**
- * Should only be called by bna_rxf_mode_set.
- * Helps deciding if h/w configuration is needed or not.
- *  Returns:
- *	0 = no h/w change
- *	1 = need h/w change
- */
-static int
-rxf_promisc_disable(struct bna_rxf *rxf)
-{
-	struct bna *bna = rxf->rx->bna;
-	int ret = 0;
-
-	/* There can not be any pending disable */
-
-	/* Turn off pending enable command , if any */
-	if (is_promisc_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask)) {
-		/* Promisc mode should not be active */
-		/* system promisc state should be pending */
-		promisc_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		/* Remove the promisc state from the system */
-		bna->rxf_promisc_id = BFI_MAX_RXF;
-
-		/* Schedule disable */
-	} else if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
-		/* Promisc mode should be active in the system */
-		promisc_disable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		ret = 1;
-
-	/* Do nothing if already disabled */
-	} else {
-	}
-
-	return ret;
-}
-
-/**
- * Should only be called by bna_rxf_mode_set.
- * Helps deciding if h/w configuration is needed or not.
- *  Returns:
- *	0 = no h/w change
- *	1 = need h/w change
- */
-static int
-rxf_allmulti_enable(struct bna_rxf *rxf)
-{
-	int ret = 0;
-
-	/* There can not be any pending disable command */
-
-	/* Do nothing if pending enable or already enabled */
-	if (is_allmulti_enable(rxf->rxmode_pending,
-			rxf->rxmode_pending_bitmask) ||
-			(rxf->rxmode_active & BNA_RXMODE_ALLMULTI)) {
-		/* Schedule enable */
-	} else {
-		allmulti_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		ret = 1;
-	}
-
-	return ret;
-}
-
-/**
- * Should only be called by bna_rxf_mode_set.
- * Helps deciding if h/w configuration is needed or not.
- *  Returns:
- *	0 = no h/w change
- *	1 = need h/w change
- */
-static int
-rxf_allmulti_disable(struct bna_rxf *rxf)
-{
-	int ret = 0;
-
-	/* There can not be any pending disable */
-
-	/* Turn off pending enable command , if any */
-	if (is_allmulti_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask)) {
-		/* Allmulti mode should not be active */
-		allmulti_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-
-	/* Schedule disable */
-	} else if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
-		allmulti_disable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		ret = 1;
-	}
-
-	return ret;
-}
-
-/* RxF <- bnad */
-enum bna_cb_status
-bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode new_mode,
-		enum bna_rxmode bitmask,
-		void (*cbfn)(struct bnad *, struct bna_rx *,
-			     enum bna_cb_status))
-{
-	struct bna_rxf *rxf = &rx->rxf;
-	int need_hw_config = 0;
-
-	/* Process the commands */
-
-	if (is_promisc_enable(new_mode, bitmask)) {
-		/* If promisc mode is already enabled elsewhere in the system */
-		if ((rx->bna->rxf_promisc_id != BFI_MAX_RXF) &&
-			(rx->bna->rxf_promisc_id != rxf->rxf_id))
-			goto err_return;
-		if (rxf_promisc_enable(rxf))
-			need_hw_config = 1;
-	} else if (is_promisc_disable(new_mode, bitmask)) {
-		if (rxf_promisc_disable(rxf))
-			need_hw_config = 1;
-	}
-
-	if (is_allmulti_enable(new_mode, bitmask)) {
-		if (rxf_allmulti_enable(rxf))
-			need_hw_config = 1;
-	} else if (is_allmulti_disable(new_mode, bitmask)) {
-		if (rxf_allmulti_disable(rxf))
-			need_hw_config = 1;
-	}
-
-	/* Trigger h/w if needed */
-
-	if (need_hw_config) {
-		rxf->cam_fltr_cbfn = cbfn;
-		rxf->cam_fltr_cbarg = rx->bna->bnad;
-		bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
-	} else if (cbfn)
-		(*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
-
-	return BNA_CB_SUCCESS;
-
-err_return:
-	return BNA_CB_FAIL;
-}
-
-void
-/* RxF <- bnad */
-bna_rx_vlanfilter_enable(struct bna_rx *rx)
-{
-	struct bna_rxf *rxf = &rx->rxf;
-
-	if (rxf->vlan_filter_status == BNA_STATUS_T_DISABLED) {
-		rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
-		rxf->vlan_filter_status = BNA_STATUS_T_ENABLED;
-		bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
-	}
-}
-
-/* Rx */
-
-/* Rx <- bnad */
-void
-bna_rx_coalescing_timeo_set(struct bna_rx *rx, int coalescing_timeo)
-{
-	struct bna_rxp *rxp;
-	struct list_head *qe;
-
-	list_for_each(qe, &rx->rxp_q) {
-		rxp = (struct bna_rxp *)qe;
-		rxp->cq.ccb->rx_coalescing_timeo = coalescing_timeo;
-		bna_ib_coalescing_timeo_set(rxp->cq.ib, coalescing_timeo);
-	}
-}
-
-/* Rx <- bnad */
-void
-bna_rx_dim_reconfig(struct bna *bna, const u32 vector[][BNA_BIAS_T_MAX])
-{
-	int i, j;
-
-	for (i = 0; i < BNA_LOAD_T_MAX; i++)
-		for (j = 0; j < BNA_BIAS_T_MAX; j++)
-			bna->rx_mod.dim_vector[i][j] = vector[i][j];
-}
-
-/* Rx <- bnad */
-void
-bna_rx_dim_update(struct bna_ccb *ccb)
-{
-	struct bna *bna = ccb->cq->rx->bna;
-	u32 load, bias;
-	u32 pkt_rt, small_rt, large_rt;
-	u8 coalescing_timeo;
-
-	if ((ccb->pkt_rate.small_pkt_cnt == 0) &&
-		(ccb->pkt_rate.large_pkt_cnt == 0))
-		return;
-
-	/* Arrive at preconfigured coalescing timeo value based on pkt rate */
-
-	small_rt = ccb->pkt_rate.small_pkt_cnt;
-	large_rt = ccb->pkt_rate.large_pkt_cnt;
-
-	pkt_rt = small_rt + large_rt;
-
-	if (pkt_rt < BNA_PKT_RATE_10K)
-		load = BNA_LOAD_T_LOW_4;
-	else if (pkt_rt < BNA_PKT_RATE_20K)
-		load = BNA_LOAD_T_LOW_3;
-	else if (pkt_rt < BNA_PKT_RATE_30K)
-		load = BNA_LOAD_T_LOW_2;
-	else if (pkt_rt < BNA_PKT_RATE_40K)
-		load = BNA_LOAD_T_LOW_1;
-	else if (pkt_rt < BNA_PKT_RATE_50K)
-		load = BNA_LOAD_T_HIGH_1;
-	else if (pkt_rt < BNA_PKT_RATE_60K)
-		load = BNA_LOAD_T_HIGH_2;
-	else if (pkt_rt < BNA_PKT_RATE_80K)
-		load = BNA_LOAD_T_HIGH_3;
-	else
-		load = BNA_LOAD_T_HIGH_4;
-
-	if (small_rt > (large_rt << 1))
-		bias = 0;
-	else
-		bias = 1;
-
-	ccb->pkt_rate.small_pkt_cnt = 0;
-	ccb->pkt_rate.large_pkt_cnt = 0;
-
-	coalescing_timeo = bna->rx_mod.dim_vector[load][bias];
-	ccb->rx_coalescing_timeo = coalescing_timeo;
-
-	/* Set it to IB */
-	bna_ib_coalescing_timeo_set(ccb->cq->ib, coalescing_timeo);
-}
-
-/* Tx */
-/* TX <- bnad */
-void
-bna_tx_coalescing_timeo_set(struct bna_tx *tx, int coalescing_timeo)
-{
-	struct bna_txq *txq;
-	struct list_head *qe;
-
-	list_for_each(qe, &tx->txq_q) {
-		txq = (struct bna_txq *)qe;
-		bna_ib_coalescing_timeo_set(txq->ib, coalescing_timeo);
-	}
-}
-
-/*
- * Private data
- */
-
-struct bna_ritseg_pool_cfg {
-	u32	pool_size;
-	u32	pool_entry_size;
-};
-init_ritseg_pool(ritseg_pool_cfg);
-
-/*
- * Private functions
- */
-static void
-bna_ucam_mod_init(struct bna_ucam_mod *ucam_mod, struct bna *bna,
-		  struct bna_res_info *res_info)
-{
-	int i;
-
-	ucam_mod->ucmac = (struct bna_mac *)
-		res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.mdl[0].kva;
-
-	INIT_LIST_HEAD(&ucam_mod->free_q);
-	for (i = 0; i < BFI_MAX_UCMAC; i++) {
-		bfa_q_qe_init(&ucam_mod->ucmac[i].qe);
-		list_add_tail(&ucam_mod->ucmac[i].qe, &ucam_mod->free_q);
-	}
-
-	ucam_mod->bna = bna;
-}
-
-static void
-bna_ucam_mod_uninit(struct bna_ucam_mod *ucam_mod)
-{
-	struct list_head *qe;
-	int i = 0;
-
-	list_for_each(qe, &ucam_mod->free_q)
-		i++;
-
-	ucam_mod->bna = NULL;
-}
-
-static void
-bna_mcam_mod_init(struct bna_mcam_mod *mcam_mod, struct bna *bna,
-		  struct bna_res_info *res_info)
-{
-	int i;
-
-	mcam_mod->mcmac = (struct bna_mac *)
-		res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.mdl[0].kva;
-
-	INIT_LIST_HEAD(&mcam_mod->free_q);
-	for (i = 0; i < BFI_MAX_MCMAC; i++) {
-		bfa_q_qe_init(&mcam_mod->mcmac[i].qe);
-		list_add_tail(&mcam_mod->mcmac[i].qe, &mcam_mod->free_q);
-	}
-
-	mcam_mod->bna = bna;
-}
-
-static void
-bna_mcam_mod_uninit(struct bna_mcam_mod *mcam_mod)
-{
-	struct list_head *qe;
-	int i = 0;
-
-	list_for_each(qe, &mcam_mod->free_q)
-		i++;
-
-	mcam_mod->bna = NULL;
-}
-
-static void
-bna_rit_mod_init(struct bna_rit_mod *rit_mod,
-		struct bna_res_info *res_info)
-{
-	int i;
-	int j;
-	int count;
-	int offset;
-
-	rit_mod->rit = (struct bna_rit_entry *)
-		res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.mdl[0].kva;
-	rit_mod->rit_segment = (struct bna_rit_segment *)
-		res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.mdl[0].kva;
-
-	count = 0;
-	offset = 0;
-	for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
-		INIT_LIST_HEAD(&rit_mod->rit_seg_pool[i]);
-		for (j = 0; j < ritseg_pool_cfg[i].pool_size; j++) {
-			bfa_q_qe_init(&rit_mod->rit_segment[count].qe);
-			rit_mod->rit_segment[count].max_rit_size =
-					ritseg_pool_cfg[i].pool_entry_size;
-			rit_mod->rit_segment[count].rit_offset = offset;
-			rit_mod->rit_segment[count].rit =
-					&rit_mod->rit[offset];
-			list_add_tail(&rit_mod->rit_segment[count].qe,
-				&rit_mod->rit_seg_pool[i]);
-			count++;
-			offset += ritseg_pool_cfg[i].pool_entry_size;
-		}
-	}
-}
-
-/*
- * Public functions
- */
-
-/* Called during probe(), before calling bna_init() */
-void
-bna_res_req(struct bna_res_info *res_info)
-{
-	bna_adv_res_req(res_info);
-
-	/* DMA memory for retrieving IOC attributes */
-	res_info[BNA_RES_MEM_T_ATTR].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
-	res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.num = 1;
-	res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.len =
-				ALIGN(bfa_nw_ioc_meminfo(), PAGE_SIZE);
-
-	/* DMA memory for index segment of an IB */
-	res_info[BNA_RES_MEM_T_IBIDX].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
-	res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.len =
-				BFI_IBIDX_SIZE * BFI_IBIDX_MAX_SEGSIZE;
-	res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.num = BFI_MAX_IB;
-
-	/* Virtual memory for IB objects - stored by IB module */
-	res_info[BNA_RES_MEM_T_IB_ARRAY].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.mem_type =
-								BNA_MEM_T_KVA;
-	res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.num = 1;
-	res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.len =
-				BFI_MAX_IB * sizeof(struct bna_ib);
-
-	/* Virtual memory for intr objects - stored by IB module */
-	res_info[BNA_RES_MEM_T_INTR_ARRAY].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.mem_type =
-								BNA_MEM_T_KVA;
-	res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.num = 1;
-	res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.len =
-				BFI_MAX_IB * sizeof(struct bna_intr);
-
-	/* Virtual memory for idx_seg objects - stored by IB module */
-	res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.mem_type =
-								BNA_MEM_T_KVA;
-	res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.num = 1;
-	res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.len =
-			BFI_IBIDX_TOTAL_SEGS * sizeof(struct bna_ibidx_seg);
-
-	/* Virtual memory for Tx objects - stored by Tx module */
-	res_info[BNA_RES_MEM_T_TX_ARRAY].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.mem_type =
-								BNA_MEM_T_KVA;
-	res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.num = 1;
-	res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.len =
-			BFI_MAX_TXQ * sizeof(struct bna_tx);
-
-	/* Virtual memory for TxQ - stored by Tx module */
-	res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.mem_type =
-								BNA_MEM_T_KVA;
-	res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.num = 1;
-	res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.len =
-			BFI_MAX_TXQ * sizeof(struct bna_txq);
-
-	/* Virtual memory for Rx objects - stored by Rx module */
-	res_info[BNA_RES_MEM_T_RX_ARRAY].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.mem_type =
-								BNA_MEM_T_KVA;
-	res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.num = 1;
-	res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.len =
-			BFI_MAX_RXQ * sizeof(struct bna_rx);
-
-	/* Virtual memory for RxPath - stored by Rx module */
-	res_info[BNA_RES_MEM_T_RXP_ARRAY].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.mem_type =
-								BNA_MEM_T_KVA;
-	res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.num = 1;
-	res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.len =
-			BFI_MAX_RXQ * sizeof(struct bna_rxp);
-
-	/* Virtual memory for RxQ - stored by Rx module */
-	res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.mem_type =
-								BNA_MEM_T_KVA;
-	res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.num = 1;
-	res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.len =
-			BFI_MAX_RXQ * sizeof(struct bna_rxq);
-
-	/* Virtual memory for Unicast MAC address - stored by ucam module */
-	res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.mem_type =
-								BNA_MEM_T_KVA;
-	res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.num = 1;
-	res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.len =
-			BFI_MAX_UCMAC * sizeof(struct bna_mac);
-
-	/* Virtual memory for Multicast MAC address - stored by mcam module */
-	res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.mem_type =
-								BNA_MEM_T_KVA;
-	res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.num = 1;
-	res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.len =
-			BFI_MAX_MCMAC * sizeof(struct bna_mac);
-
-	/* Virtual memory for RIT entries */
-	res_info[BNA_RES_MEM_T_RIT_ENTRY].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.mem_type =
-								BNA_MEM_T_KVA;
-	res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.num = 1;
-	res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.len =
-			BFI_MAX_RIT_SIZE * sizeof(struct bna_rit_entry);
-
-	/* Virtual memory for RIT segment table */
-	res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_type = BNA_RES_T_MEM;
-	res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.mem_type =
-								BNA_MEM_T_KVA;
-	res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.num = 1;
-	res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.len =
-			BFI_RIT_TOTAL_SEGS * sizeof(struct bna_rit_segment);
-
-	/* Interrupt resource for mailbox interrupt */
-	res_info[BNA_RES_INTR_T_MBOX].res_type = BNA_RES_T_INTR;
-	res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.intr_type =
-							BNA_INTR_T_MSIX;
-	res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.num = 1;
-}
-
-/* Called during probe() */
-void
-bna_init(struct bna *bna, struct bnad *bnad, struct bfa_pcidev *pcidev,
-		struct bna_res_info *res_info)
-{
-	bna->bnad = bnad;
-	bna->pcidev = *pcidev;
-
-	bna->stats.hw_stats = (struct bfi_ll_stats *)
-		res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].kva;
-	bna->hw_stats_dma.msb =
-		res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].dma.msb;
-	bna->hw_stats_dma.lsb =
-		res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].dma.lsb;
-	bna->stats.sw_stats = (struct bna_sw_stats *)
-		res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.mdl[0].kva;
-
-	bna->regs.page_addr = bna->pcidev.pci_bar_kva +
-				reg_offset[bna->pcidev.pci_func].page_addr;
-	bna->regs.fn_int_status = bna->pcidev.pci_bar_kva +
-				reg_offset[bna->pcidev.pci_func].fn_int_status;
-	bna->regs.fn_int_mask = bna->pcidev.pci_bar_kva +
-				reg_offset[bna->pcidev.pci_func].fn_int_mask;
-
-	if (bna->pcidev.pci_func < 3)
-		bna->port_num = 0;
-	else
-		bna->port_num = 1;
-
-	/* Also initializes diag, cee, sfp, phy_port and mbox_mod */
-	bna_device_init(&bna->device, bna, res_info);
-
-	bna_port_init(&bna->port, bna);
-
-	bna_tx_mod_init(&bna->tx_mod, bna, res_info);
-
-	bna_rx_mod_init(&bna->rx_mod, bna, res_info);
-
-	bna_ib_mod_init(&bna->ib_mod, bna, res_info);
-
-	bna_rit_mod_init(&bna->rit_mod, res_info);
-
-	bna_ucam_mod_init(&bna->ucam_mod, bna, res_info);
-
-	bna_mcam_mod_init(&bna->mcam_mod, bna, res_info);
-
-	bna->rxf_promisc_id = BFI_MAX_RXF;
-
-	/* Mbox q element for posting stat request to f/w */
-	bfa_q_qe_init(&bna->mbox_qe.qe);
-}
-
-void
-bna_uninit(struct bna *bna)
-{
-	bna_mcam_mod_uninit(&bna->mcam_mod);
-
-	bna_ucam_mod_uninit(&bna->ucam_mod);
-
-	bna_ib_mod_uninit(&bna->ib_mod);
-
-	bna_rx_mod_uninit(&bna->rx_mod);
-
-	bna_tx_mod_uninit(&bna->tx_mod);
-
-	bna_port_uninit(&bna->port);
-
-	bna_device_uninit(&bna->device);
-
-	bna->bnad = NULL;
-}
-
-struct bna_mac *
-bna_ucam_mod_mac_get(struct bna_ucam_mod *ucam_mod)
-{
-	struct list_head *qe;
-
-	if (list_empty(&ucam_mod->free_q))
-		return NULL;
-
-	bfa_q_deq(&ucam_mod->free_q, &qe);
-
-	return (struct bna_mac *)qe;
-}
-
-void
-bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod, struct bna_mac *mac)
-{
-	list_add_tail(&mac->qe, &ucam_mod->free_q);
-}
-
-struct bna_mac *
-bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod)
-{
-	struct list_head *qe;
-
-	if (list_empty(&mcam_mod->free_q))
-		return NULL;
-
-	bfa_q_deq(&mcam_mod->free_q, &qe);
-
-	return (struct bna_mac *)qe;
-}
-
-void
-bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod, struct bna_mac *mac)
-{
-	list_add_tail(&mac->qe, &mcam_mod->free_q);
-}
-
-/**
- * Note: This should be called in the same locking context as the call to
- * bna_rit_mod_seg_get()
- */
-int
-bna_rit_mod_can_satisfy(struct bna_rit_mod *rit_mod, int seg_size)
-{
-	int i;
-
-	/* Select the pool for seg_size */
-	for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
-		if (seg_size <= ritseg_pool_cfg[i].pool_entry_size)
-			break;
-	}
-
-	if (i == BFI_RIT_SEG_TOTAL_POOLS)
-		return 0;
-
-	if (list_empty(&rit_mod->rit_seg_pool[i]))
-		return 0;
-
-	return 1;
-}
-
-struct bna_rit_segment *
-bna_rit_mod_seg_get(struct bna_rit_mod *rit_mod, int seg_size)
-{
-	struct bna_rit_segment *seg;
-	struct list_head *qe;
-	int i;
-
-	/* Select the pool for seg_size */
-	for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
-		if (seg_size <= ritseg_pool_cfg[i].pool_entry_size)
-			break;
-	}
-
-	if (i == BFI_RIT_SEG_TOTAL_POOLS)
-		return NULL;
-
-	if (list_empty(&rit_mod->rit_seg_pool[i]))
-		return NULL;
-
-	bfa_q_deq(&rit_mod->rit_seg_pool[i], &qe);
-	seg = (struct bna_rit_segment *)qe;
-	bfa_q_qe_init(&seg->qe);
-	seg->rit_size = seg_size;
-
-	return seg;
-}
-
-void
-bna_rit_mod_seg_put(struct bna_rit_mod *rit_mod,
-			struct bna_rit_segment *seg)
-{
-	int i;
-
-	/* Select the pool for seg->max_rit_size */
-	for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
-		if (seg->max_rit_size == ritseg_pool_cfg[i].pool_entry_size)
-			break;
-	}
-
-	seg->rit_size = 0;
-	list_add_tail(&seg->qe, &rit_mod->rit_seg_pool[i]);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bnad.c linux-libre-3.2-gnu/drivers/net/bna/bnad.c
--- linux-libre-3.1-gnu/drivers/net/bna/bnad.c	2012-03-19 21:42:14.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bnad.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3266 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-#include <linux/bitops.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/etherdevice.h>
-#include <linux/in.h>
-#include <linux/ethtool.h>
-#include <linux/if_vlan.h>
-#include <linux/if_ether.h>
-#include <linux/ip.h>
-#include <linux/prefetch.h>
-
-#include "bnad.h"
-#include "bna.h"
-#include "cna.h"
-
-static DEFINE_MUTEX(bnad_fwimg_mutex);
-
-/*
- * Module params
- */
-static uint bnad_msix_disable;
-module_param(bnad_msix_disable, uint, 0444);
-MODULE_PARM_DESC(bnad_msix_disable, "Disable MSIX mode");
-
-static uint bnad_ioc_auto_recover = 1;
-module_param(bnad_ioc_auto_recover, uint, 0444);
-MODULE_PARM_DESC(bnad_ioc_auto_recover, "Enable / Disable auto recovery");
-
-/*
- * Global variables
- */
-u32 bnad_rxqs_per_cq = 2;
-
-static const u8 bnad_bcast_addr[] =  {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
-/*
- * Local MACROS
- */
-#define BNAD_TX_UNMAPQ_DEPTH (bnad->txq_depth * 2)
-
-#define BNAD_RX_UNMAPQ_DEPTH (bnad->rxq_depth)
-
-#define BNAD_GET_MBOX_IRQ(_bnad)				\
-	(((_bnad)->cfg_flags & BNAD_CF_MSIX) ?			\
-	 ((_bnad)->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector) : \
-	 ((_bnad)->pcidev->irq))
-
-#define BNAD_FILL_UNMAPQ_MEM_REQ(_res_info, _num, _depth)	\
-do {								\
-	(_res_info)->res_type = BNA_RES_T_MEM;			\
-	(_res_info)->res_u.mem_info.mem_type = BNA_MEM_T_KVA;	\
-	(_res_info)->res_u.mem_info.num = (_num);		\
-	(_res_info)->res_u.mem_info.len =			\
-	sizeof(struct bnad_unmap_q) +				\
-	(sizeof(struct bnad_skb_unmap) * ((_depth) - 1));	\
-} while (0)
-
-#define BNAD_TXRX_SYNC_MDELAY	250	/* 250 msecs */
-
-/*
- * Reinitialize completions in CQ, once Rx is taken down
- */
-static void
-bnad_cq_cmpl_init(struct bnad *bnad, struct bna_ccb *ccb)
-{
-	struct bna_cq_entry *cmpl, *next_cmpl;
-	unsigned int wi_range, wis = 0, ccb_prod = 0;
-	int i;
-
-	BNA_CQ_QPGE_PTR_GET(ccb_prod, ccb->sw_qpt, cmpl,
-			    wi_range);
-
-	for (i = 0; i < ccb->q_depth; i++) {
-		wis++;
-		if (likely(--wi_range))
-			next_cmpl = cmpl + 1;
-		else {
-			BNA_QE_INDX_ADD(ccb_prod, wis, ccb->q_depth);
-			wis = 0;
-			BNA_CQ_QPGE_PTR_GET(ccb_prod, ccb->sw_qpt,
-						next_cmpl, wi_range);
-		}
-		cmpl->valid = 0;
-		cmpl = next_cmpl;
-	}
-}
-
-/*
- * Frees all pending Tx Bufs
- * At this point no activity is expected on the Q,
- * so DMA unmap & freeing is fine.
- */
-static void
-bnad_free_all_txbufs(struct bnad *bnad,
-		 struct bna_tcb *tcb)
-{
-	u32		unmap_cons;
-	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
-	struct bnad_skb_unmap *unmap_array;
-	struct sk_buff		*skb = NULL;
-	int			i;
-
-	unmap_array = unmap_q->unmap_array;
-
-	unmap_cons = 0;
-	while (unmap_cons < unmap_q->q_depth) {
-		skb = unmap_array[unmap_cons].skb;
-		if (!skb) {
-			unmap_cons++;
-			continue;
-		}
-		unmap_array[unmap_cons].skb = NULL;
-
-		dma_unmap_single(&bnad->pcidev->dev,
-				 dma_unmap_addr(&unmap_array[unmap_cons],
-						dma_addr), skb_headlen(skb),
-						DMA_TO_DEVICE);
-
-		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++) {
-			dma_unmap_page(&bnad->pcidev->dev,
-				       dma_unmap_addr(&unmap_array[unmap_cons],
-						      dma_addr),
-				       skb_shinfo(skb)->frags[i].size,
-				       DMA_TO_DEVICE);
-			dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
-					   0);
-			if (++unmap_cons >= unmap_q->q_depth)
-				break;
-		}
-		dev_kfree_skb_any(skb);
-	}
-}
-
-/* Data Path Handlers */
-
-/*
- * bnad_free_txbufs : Frees the Tx bufs on Tx completion
- * Can be called in a) Interrupt context
- *		    b) Sending context
- *		    c) Tasklet context
- */
-static u32
-bnad_free_txbufs(struct bnad *bnad,
-		 struct bna_tcb *tcb)
-{
-	u32		sent_packets = 0, sent_bytes = 0;
-	u16		wis, unmap_cons, updated_hw_cons;
-	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
-	struct bnad_skb_unmap *unmap_array;
-	struct sk_buff		*skb;
-	int i;
-
-	/*
-	 * Just return if TX is stopped. This check is useful
-	 * when bnad_free_txbufs() runs out of a tasklet scheduled
-	 * before bnad_cb_tx_cleanup() cleared BNAD_TXQ_TX_STARTED bit
-	 * but this routine runs actually after the cleanup has been
-	 * executed.
-	 */
-	if (!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
-		return 0;
-
-	updated_hw_cons = *(tcb->hw_consumer_index);
-
-	wis = BNA_Q_INDEX_CHANGE(tcb->consumer_index,
-				  updated_hw_cons, tcb->q_depth);
-
-	BUG_ON(!(wis <= BNA_QE_IN_USE_CNT(tcb, tcb->q_depth)));
-
-	unmap_array = unmap_q->unmap_array;
-	unmap_cons = unmap_q->consumer_index;
-
-	prefetch(&unmap_array[unmap_cons + 1]);
-	while (wis) {
-		skb = unmap_array[unmap_cons].skb;
-
-		unmap_array[unmap_cons].skb = NULL;
-
-		sent_packets++;
-		sent_bytes += skb->len;
-		wis -= BNA_TXQ_WI_NEEDED(1 + skb_shinfo(skb)->nr_frags);
-
-		dma_unmap_single(&bnad->pcidev->dev,
-				 dma_unmap_addr(&unmap_array[unmap_cons],
-						dma_addr), skb_headlen(skb),
-				 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]);
-
-			dma_unmap_page(&bnad->pcidev->dev,
-				       dma_unmap_addr(&unmap_array[unmap_cons],
-						      dma_addr),
-				       skb_shinfo(skb)->frags[i].size,
-				       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);
-		}
-		dev_kfree_skb_any(skb);
-	}
-
-	/* Update consumer pointers. */
-	tcb->consumer_index = updated_hw_cons;
-	unmap_q->consumer_index = unmap_cons;
-
-	tcb->txq->tx_packets += sent_packets;
-	tcb->txq->tx_bytes += sent_bytes;
-
-	return sent_packets;
-}
-
-/* Tx Free Tasklet function */
-/* Frees for all the tcb's in all the Tx's */
-/*
- * Scheduled from sending context, so that
- * the fat Tx lock is not held for too long
- * in the sending context.
- */
-static void
-bnad_tx_free_tasklet(unsigned long bnad_ptr)
-{
-	struct bnad *bnad = (struct bnad *)bnad_ptr;
-	struct bna_tcb *tcb;
-	u32		acked = 0;
-	int			i, j;
-
-	for (i = 0; i < bnad->num_tx; i++) {
-		for (j = 0; j < bnad->num_txq_per_tx; j++) {
-			tcb = bnad->tx_info[i].tcb[j];
-			if (!tcb)
-				continue;
-			if (((u16) (*tcb->hw_consumer_index) !=
-				tcb->consumer_index) &&
-				(!test_and_set_bit(BNAD_TXQ_FREE_SENT,
-						  &tcb->flags))) {
-				acked = bnad_free_txbufs(bnad, tcb);
-				if (likely(test_bit(BNAD_TXQ_TX_STARTED,
-					&tcb->flags)))
-					bna_ib_ack(tcb->i_dbell, acked);
-				smp_mb__before_clear_bit();
-				clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
-			}
-			if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED,
-						&tcb->flags)))
-				continue;
-			if (netif_queue_stopped(bnad->netdev)) {
-				if (acked && netif_carrier_ok(bnad->netdev) &&
-					BNA_QE_FREE_CNT(tcb, tcb->q_depth) >=
-						BNAD_NETIF_WAKE_THRESHOLD) {
-					netif_wake_queue(bnad->netdev);
-					/* TODO */
-					/* Counters for individual TxQs? */
-					BNAD_UPDATE_CTR(bnad,
-						netif_queue_wakeup);
-				}
-			}
-		}
-	}
-}
-
-static u32
-bnad_tx(struct bnad *bnad, struct bna_tcb *tcb)
-{
-	struct net_device *netdev = bnad->netdev;
-	u32 sent = 0;
-
-	if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
-		return 0;
-
-	sent = bnad_free_txbufs(bnad, tcb);
-	if (sent) {
-		if (netif_queue_stopped(netdev) &&
-		    netif_carrier_ok(netdev) &&
-		    BNA_QE_FREE_CNT(tcb, tcb->q_depth) >=
-				    BNAD_NETIF_WAKE_THRESHOLD) {
-			if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) {
-				netif_wake_queue(netdev);
-				BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
-			}
-		}
-	}
-
-	if (likely(test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)))
-		bna_ib_ack(tcb->i_dbell, sent);
-
-	smp_mb__before_clear_bit();
-	clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
-
-	return sent;
-}
-
-/* MSIX Tx Completion Handler */
-static irqreturn_t
-bnad_msix_tx(int irq, void *data)
-{
-	struct bna_tcb *tcb = (struct bna_tcb *)data;
-	struct bnad *bnad = tcb->bnad;
-
-	bnad_tx(bnad, tcb);
-
-	return IRQ_HANDLED;
-}
-
-static void
-bnad_reset_rcb(struct bnad *bnad, struct bna_rcb *rcb)
-{
-	struct bnad_unmap_q *unmap_q = rcb->unmap_q;
-
-	rcb->producer_index = 0;
-	rcb->consumer_index = 0;
-
-	unmap_q->producer_index = 0;
-	unmap_q->consumer_index = 0;
-}
-
-static void
-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_array[unmap_cons].skb;
-		if (!skb)
-			continue;
-		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);
-}
-
-static void
-bnad_alloc_n_post_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
-{
-	u16 to_alloc, alloced, unmap_prod, wi_range;
-	struct bnad_unmap_q *unmap_q = rcb->unmap_q;
-	struct bnad_skb_unmap *unmap_array;
-	struct bna_rxq_entry *rxent;
-	struct sk_buff *skb;
-	dma_addr_t dma_addr;
-
-	alloced = 0;
-	to_alloc =
-		BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth);
-
-	unmap_array = unmap_q->unmap_array;
-	unmap_prod = unmap_q->producer_index;
-
-	BNA_RXQ_QPGE_PTR_GET(unmap_prod, rcb->sw_qpt, rxent, wi_range);
-
-	while (to_alloc--) {
-		if (!wi_range) {
-			BNA_RXQ_QPGE_PTR_GET(unmap_prod, rcb->sw_qpt, rxent,
-					     wi_range);
-		}
-		skb = netdev_alloc_skb_ip_align(bnad->netdev,
-						rcb->rxq->buffer_size);
-		if (unlikely(!skb)) {
-			BNAD_UPDATE_CTR(bnad, rxbuf_alloc_failed);
-			goto finishing;
-		}
-		unmap_array[unmap_prod].skb = skb;
-		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);
-
-		rxent++;
-		wi_range--;
-		alloced++;
-	}
-
-finishing:
-	if (likely(alloced)) {
-		unmap_q->producer_index = unmap_prod;
-		rcb->producer_index = unmap_prod;
-		smp_mb();
-		if (likely(test_bit(BNAD_RXQ_STARTED, &rcb->flags)))
-			bna_rxq_prod_indx_doorbell(rcb);
-	}
-}
-
-static inline void
-bnad_refill_rxq(struct bnad *bnad, struct bna_rcb *rcb)
-{
-	struct bnad_unmap_q *unmap_q = rcb->unmap_q;
-
-	if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) {
-		if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth)
-			 >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT)
-			bnad_alloc_n_post_rxbufs(bnad, rcb);
-		smp_mb__before_clear_bit();
-		clear_bit(BNAD_RXQ_REFILL, &rcb->flags);
-	}
-}
-
-static u32
-bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
-{
-	struct bna_cq_entry *cmpl, *next_cmpl;
-	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, unmap_cons;
-	u32 qid0 = ccb->rcb[0]->rxq->rxq_id;
-	struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate;
-
-	if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))
-		return 0;
-
-	prefetch(bnad->netdev);
-	BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, cmpl,
-			    wi_range);
-	BUG_ON(!(wi_range <= ccb->q_depth));
-	while (cmpl->valid && packets < budget) {
-		packets++;
-		BNA_UPDATE_PKT_CNT(pkt_rt, ntohs(cmpl->length));
-
-		if (qid0 == cmpl->rxq_id)
-			rcb = ccb->rcb[0];
-		else
-			rcb = ccb->rcb[1];
-
-		unmap_q = rcb->unmap_q;
-		unmap_array = unmap_q->unmap_array;
-		unmap_cons = unmap_q->consumer_index;
-
-		skb = unmap_array[unmap_cons].skb;
-		BUG_ON(!(skb));
-		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);
-		BNA_QE_INDX_ADD(unmap_q->consumer_index, 1, unmap_q->q_depth);
-
-		/* Should be more efficient ? Performance ? */
-		BNA_QE_INDX_ADD(rcb->consumer_index, 1, rcb->q_depth);
-
-		wis++;
-		if (likely(--wi_range))
-			next_cmpl = cmpl + 1;
-		else {
-			BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth);
-			wis = 0;
-			BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt,
-						next_cmpl, wi_range);
-			BUG_ON(!(wi_range <= ccb->q_depth));
-		}
-		prefetch(next_cmpl);
-
-		flags = ntohl(cmpl->flags);
-		if (unlikely
-		    (flags &
-		     (BNA_CQ_EF_MAC_ERROR | BNA_CQ_EF_FCS_ERROR |
-		      BNA_CQ_EF_TOO_LONG))) {
-			dev_kfree_skb_any(skb);
-			rcb->rxq->rx_packets_with_error++;
-			goto next;
-		}
-
-		skb_put(skb, ntohs(cmpl->length));
-		if (likely
-		    ((bnad->netdev->features & NETIF_F_RXCSUM) &&
-		     (((flags & BNA_CQ_EF_IPV4) &&
-		      (flags & BNA_CQ_EF_L3_CKSUM_OK)) ||
-		      (flags & BNA_CQ_EF_IPV6)) &&
-		      (flags & (BNA_CQ_EF_TCP | BNA_CQ_EF_UDP)) &&
-		      (flags & BNA_CQ_EF_L4_CKSUM_OK)))
-			skb->ip_summed = CHECKSUM_UNNECESSARY;
-		else
-			skb_checksum_none_assert(skb);
-
-		rcb->rxq->rx_packets++;
-		rcb->rxq->rx_bytes += skb->len;
-		skb->protocol = eth_type_trans(skb, bnad->netdev);
-
-		if (flags & BNA_CQ_EF_VLAN)
-			__vlan_hwaccel_put_tag(skb, ntohs(cmpl->vlan_tag));
-
-		if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
-			struct bnad_rx_ctrl *rx_ctrl;
-
-			rx_ctrl = (struct bnad_rx_ctrl *) ccb->ctrl;
-			napi_gro_receive(&rx_ctrl->napi, skb);
-		} else {
-			netif_receive_skb(skb);
-		}
-
-next:
-		cmpl->valid = 0;
-		cmpl = next_cmpl;
-	}
-
-	BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth);
-
-	if (likely(ccb)) {
-		if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
-			bna_ib_ack(ccb->i_dbell, packets);
-		bnad_refill_rxq(bnad, ccb->rcb[0]);
-		if (ccb->rcb[1])
-			bnad_refill_rxq(bnad, ccb->rcb[1]);
-	} else {
-		if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
-			bna_ib_ack(ccb->i_dbell, 0);
-	}
-
-	return packets;
-}
-
-static void
-bnad_disable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb)
-{
-	if (unlikely(!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)))
-		return;
-
-	bna_ib_coalescing_timer_set(ccb->i_dbell, 0);
-	bna_ib_ack(ccb->i_dbell, 0);
-}
-
-static void
-bnad_enable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb)
-{
-	unsigned long flags;
-
-	/* Because of polling context */
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bnad_enable_rx_irq_unsafe(ccb);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-}
-
-static void
-bnad_netif_rx_schedule_poll(struct bnad *bnad, struct bna_ccb *ccb)
-{
-	struct bnad_rx_ctrl *rx_ctrl = (struct bnad_rx_ctrl *)(ccb->ctrl);
-	struct napi_struct *napi = &rx_ctrl->napi;
-
-	if (likely(napi_schedule_prep(napi))) {
-		bnad_disable_rx_irq(bnad, ccb);
-		__napi_schedule(napi);
-	}
-	BNAD_UPDATE_CTR(bnad, netif_rx_schedule);
-}
-
-/* MSIX Rx Path Handler */
-static irqreturn_t
-bnad_msix_rx(int irq, void *data)
-{
-	struct bna_ccb *ccb = (struct bna_ccb *)data;
-	struct bnad *bnad = ccb->bnad;
-
-	bnad_netif_rx_schedule_poll(bnad, ccb);
-
-	return IRQ_HANDLED;
-}
-
-/* Interrupt handlers */
-
-/* Mbox Interrupt Handlers */
-static irqreturn_t
-bnad_msix_mbox_handler(int irq, void *data)
-{
-	u32 intr_status;
-	unsigned long flags;
-	struct bnad *bnad = (struct bnad *)data;
-
-	if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)))
-		return IRQ_HANDLED;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-
-	bna_intr_status_get(&bnad->bna, intr_status);
-
-	if (BNA_IS_MBOX_ERR_INTR(intr_status))
-		bna_mbox_handler(&bnad->bna, intr_status);
-
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t
-bnad_isr(int irq, void *data)
-{
-	int i, j;
-	u32 intr_status;
-	unsigned long flags;
-	struct bnad *bnad = (struct bnad *)data;
-	struct bnad_rx_info *rx_info;
-	struct bnad_rx_ctrl *rx_ctrl;
-
-	if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)))
-		return IRQ_NONE;
-
-	bna_intr_status_get(&bnad->bna, intr_status);
-
-	if (unlikely(!intr_status))
-		return IRQ_NONE;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-
-	if (BNA_IS_MBOX_ERR_INTR(intr_status))
-		bna_mbox_handler(&bnad->bna, intr_status);
-
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	if (!BNA_IS_INTX_DATA_INTR(intr_status))
-		return IRQ_HANDLED;
-
-	/* Process data interrupts */
-	/* Tx processing */
-	for (i = 0; i < bnad->num_tx; i++) {
-		for (j = 0; j < bnad->num_txq_per_tx; j++)
-			bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
-	}
-	/* Rx processing */
-	for (i = 0; i < bnad->num_rx; i++) {
-		rx_info = &bnad->rx_info[i];
-		if (!rx_info->rx)
-			continue;
-		for (j = 0; j < bnad->num_rxp_per_rx; j++) {
-			rx_ctrl = &rx_info->rx_ctrl[j];
-			if (rx_ctrl->ccb)
-				bnad_netif_rx_schedule_poll(bnad,
-							    rx_ctrl->ccb);
-		}
-	}
-	return IRQ_HANDLED;
-}
-
-/*
- * Called in interrupt / callback context
- * with bna_lock held, so cfg_flags access is OK
- */
-static void
-bnad_enable_mbox_irq(struct bnad *bnad)
-{
-	clear_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags);
-
-	BNAD_UPDATE_CTR(bnad, mbox_intr_enabled);
-}
-
-/*
- * Called with bnad->bna_lock held b'cos of
- * bnad->cfg_flags access.
- */
-static void
-bnad_disable_mbox_irq(struct bnad *bnad)
-{
-	set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags);
-
-	BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
-}
-
-static void
-bnad_set_netdev_perm_addr(struct bnad *bnad)
-{
-	struct net_device *netdev = bnad->netdev;
-
-	memcpy(netdev->perm_addr, &bnad->perm_addr, netdev->addr_len);
-	if (is_zero_ether_addr(netdev->dev_addr))
-		memcpy(netdev->dev_addr, &bnad->perm_addr, netdev->addr_len);
-}
-
-/* Control Path Handlers */
-
-/* Callbacks */
-void
-bnad_cb_device_enable_mbox_intr(struct bnad *bnad)
-{
-	bnad_enable_mbox_irq(bnad);
-}
-
-void
-bnad_cb_device_disable_mbox_intr(struct bnad *bnad)
-{
-	bnad_disable_mbox_irq(bnad);
-}
-
-void
-bnad_cb_device_enabled(struct bnad *bnad, enum bna_cb_status status)
-{
-	complete(&bnad->bnad_completions.ioc_comp);
-	bnad->bnad_completions.ioc_comp_status = status;
-}
-
-void
-bnad_cb_device_disabled(struct bnad *bnad, enum bna_cb_status status)
-{
-	complete(&bnad->bnad_completions.ioc_comp);
-	bnad->bnad_completions.ioc_comp_status = status;
-}
-
-static void
-bnad_cb_port_disabled(void *arg, enum bna_cb_status status)
-{
-	struct bnad *bnad = (struct bnad *)arg;
-
-	complete(&bnad->bnad_completions.port_comp);
-
-	netif_carrier_off(bnad->netdev);
-}
-
-void
-bnad_cb_port_link_status(struct bnad *bnad,
-			enum bna_link_status link_status)
-{
-	bool link_up = 0;
-
-	link_up = (link_status == BNA_LINK_UP) || (link_status == BNA_CEE_UP);
-
-	if (link_status == BNA_CEE_UP) {
-		set_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags);
-		BNAD_UPDATE_CTR(bnad, cee_up);
-	} else
-		clear_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags);
-
-	if (link_up) {
-		if (!netif_carrier_ok(bnad->netdev)) {
-			struct bna_tcb *tcb = bnad->tx_info[0].tcb[0];
-			if (!tcb)
-				return;
-			pr_warn("bna: %s link up\n",
-				bnad->netdev->name);
-			netif_carrier_on(bnad->netdev);
-			BNAD_UPDATE_CTR(bnad, link_toggle);
-			if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) {
-				/* Force an immediate Transmit Schedule */
-				pr_info("bna: %s TX_STARTED\n",
-					bnad->netdev->name);
-				netif_wake_queue(bnad->netdev);
-				BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
-			} else {
-				netif_stop_queue(bnad->netdev);
-				BNAD_UPDATE_CTR(bnad, netif_queue_stop);
-			}
-		}
-	} else {
-		if (netif_carrier_ok(bnad->netdev)) {
-			pr_warn("bna: %s link down\n",
-				bnad->netdev->name);
-			netif_carrier_off(bnad->netdev);
-			BNAD_UPDATE_CTR(bnad, link_toggle);
-		}
-	}
-}
-
-static void
-bnad_cb_tx_disabled(void *arg, struct bna_tx *tx,
-			enum bna_cb_status status)
-{
-	struct bnad *bnad = (struct bnad *)arg;
-
-	complete(&bnad->bnad_completions.tx_comp);
-}
-
-static void
-bnad_cb_tcb_setup(struct bnad *bnad, struct bna_tcb *tcb)
-{
-	struct bnad_tx_info *tx_info =
-			(struct bnad_tx_info *)tcb->txq->tx->priv;
-	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
-
-	tx_info->tcb[tcb->id] = tcb;
-	unmap_q->producer_index = 0;
-	unmap_q->consumer_index = 0;
-	unmap_q->q_depth = BNAD_TX_UNMAPQ_DEPTH;
-}
-
-static void
-bnad_cb_tcb_destroy(struct bnad *bnad, struct bna_tcb *tcb)
-{
-	struct bnad_tx_info *tx_info =
-			(struct bnad_tx_info *)tcb->txq->tx->priv;
-	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
-
-	while (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
-		cpu_relax();
-
-	bnad_free_all_txbufs(bnad, tcb);
-
-	unmap_q->producer_index = 0;
-	unmap_q->consumer_index = 0;
-
-	smp_mb__before_clear_bit();
-	clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
-
-	tx_info->tcb[tcb->id] = NULL;
-}
-
-static void
-bnad_cb_rcb_setup(struct bnad *bnad, struct bna_rcb *rcb)
-{
-	struct bnad_unmap_q *unmap_q = rcb->unmap_q;
-
-	unmap_q->producer_index = 0;
-	unmap_q->consumer_index = 0;
-	unmap_q->q_depth = BNAD_RX_UNMAPQ_DEPTH;
-}
-
-static void
-bnad_cb_rcb_destroy(struct bnad *bnad, struct bna_rcb *rcb)
-{
-	bnad_free_all_rxbufs(bnad, rcb);
-}
-
-static void
-bnad_cb_ccb_setup(struct bnad *bnad, struct bna_ccb *ccb)
-{
-	struct bnad_rx_info *rx_info =
-			(struct bnad_rx_info *)ccb->cq->rx->priv;
-
-	rx_info->rx_ctrl[ccb->id].ccb = ccb;
-	ccb->ctrl = &rx_info->rx_ctrl[ccb->id];
-}
-
-static void
-bnad_cb_ccb_destroy(struct bnad *bnad, struct bna_ccb *ccb)
-{
-	struct bnad_rx_info *rx_info =
-			(struct bnad_rx_info *)ccb->cq->rx->priv;
-
-	rx_info->rx_ctrl[ccb->id].ccb = NULL;
-}
-
-static void
-bnad_cb_tx_stall(struct bnad *bnad, struct bna_tcb *tcb)
-{
-	struct bnad_tx_info *tx_info =
-			(struct bnad_tx_info *)tcb->txq->tx->priv;
-
-	if (tx_info != &bnad->tx_info[0])
-		return;
-
-	clear_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
-	netif_stop_queue(bnad->netdev);
-	pr_info("bna: %s TX_STOPPED\n", bnad->netdev->name);
-}
-
-static void
-bnad_cb_tx_resume(struct bnad *bnad, struct bna_tcb *tcb)
-{
-	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
-
-	if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
-		return;
-
-	clear_bit(BNAD_RF_TX_SHUTDOWN_DELAYED, &bnad->run_flags);
-
-	while (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
-		cpu_relax();
-
-	bnad_free_all_txbufs(bnad, tcb);
-
-	unmap_q->producer_index = 0;
-	unmap_q->consumer_index = 0;
-
-	smp_mb__before_clear_bit();
-	clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
-
-	/*
-	 * Workaround for first device enable failure & we
-	 * get a 0 MAC address. We try to get the MAC address
-	 * again here.
-	 */
-	if (is_zero_ether_addr(&bnad->perm_addr.mac[0])) {
-		bna_port_mac_get(&bnad->bna.port, &bnad->perm_addr);
-		bnad_set_netdev_perm_addr(bnad);
-	}
-
-	set_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
-
-	if (netif_carrier_ok(bnad->netdev)) {
-		pr_info("bna: %s TX_STARTED\n", bnad->netdev->name);
-		netif_wake_queue(bnad->netdev);
-		BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
-	}
-}
-
-static void
-bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tcb *tcb)
-{
-	/* Delay only once for the whole Tx Path Shutdown */
-	if (!test_and_set_bit(BNAD_RF_TX_SHUTDOWN_DELAYED, &bnad->run_flags))
-		mdelay(BNAD_TXRX_SYNC_MDELAY);
-}
-
-static void
-bnad_cb_rx_cleanup(struct bnad *bnad,
-			struct bna_ccb *ccb)
-{
-	clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags);
-
-	if (ccb->rcb[1])
-		clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[1]->flags);
-
-	if (!test_and_set_bit(BNAD_RF_RX_SHUTDOWN_DELAYED, &bnad->run_flags))
-		mdelay(BNAD_TXRX_SYNC_MDELAY);
-}
-
-static void
-bnad_cb_rx_post(struct bnad *bnad, struct bna_rcb *rcb)
-{
-	struct bnad_unmap_q *unmap_q = rcb->unmap_q;
-
-	clear_bit(BNAD_RF_RX_SHUTDOWN_DELAYED, &bnad->run_flags);
-
-	if (rcb == rcb->cq->ccb->rcb[0])
-		bnad_cq_cmpl_init(bnad, rcb->cq->ccb);
-
-	bnad_free_all_rxbufs(bnad, rcb);
-
-	set_bit(BNAD_RXQ_STARTED, &rcb->flags);
-
-	/* Now allocate & post buffers for this RCB */
-	/* !!Allocation in callback context */
-	if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) {
-		if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth)
-			 >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT)
-			bnad_alloc_n_post_rxbufs(bnad, rcb);
-		smp_mb__before_clear_bit();
-		clear_bit(BNAD_RXQ_REFILL, &rcb->flags);
-	}
-}
-
-static void
-bnad_cb_rx_disabled(void *arg, struct bna_rx *rx,
-			enum bna_cb_status status)
-{
-	struct bnad *bnad = (struct bnad *)arg;
-
-	complete(&bnad->bnad_completions.rx_comp);
-}
-
-static void
-bnad_cb_rx_mcast_add(struct bnad *bnad, struct bna_rx *rx,
-				enum bna_cb_status status)
-{
-	bnad->bnad_completions.mcast_comp_status = status;
-	complete(&bnad->bnad_completions.mcast_comp);
-}
-
-void
-bnad_cb_stats_get(struct bnad *bnad, enum bna_cb_status status,
-		       struct bna_stats *stats)
-{
-	if (status == BNA_CB_SUCCESS)
-		BNAD_UPDATE_CTR(bnad, hw_stats_updates);
-
-	if (!netif_running(bnad->netdev) ||
-		!test_bit(BNAD_RF_STATS_TIMER_RUNNING, &bnad->run_flags))
-		return;
-
-	mod_timer(&bnad->stats_timer,
-		  jiffies + msecs_to_jiffies(BNAD_STATS_TIMER_FREQ));
-}
-
-/* Resource allocation, free functions */
-
-static void
-bnad_mem_free(struct bnad *bnad,
-	      struct bna_mem_info *mem_info)
-{
-	int i;
-	dma_addr_t dma_pa;
-
-	if (mem_info->mdl == NULL)
-		return;
-
-	for (i = 0; i < mem_info->num; i++) {
-		if (mem_info->mdl[i].kva != NULL) {
-			if (mem_info->mem_type == BNA_MEM_T_DMA) {
-				BNA_GET_DMA_ADDR(&(mem_info->mdl[i].dma),
-						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);
-		}
-	}
-	kfree(mem_info->mdl);
-	mem_info->mdl = NULL;
-}
-
-static int
-bnad_mem_alloc(struct bnad *bnad,
-	       struct bna_mem_info *mem_info)
-{
-	int i;
-	dma_addr_t dma_pa;
-
-	if ((mem_info->num == 0) || (mem_info->len == 0)) {
-		mem_info->mdl = NULL;
-		return 0;
-	}
-
-	mem_info->mdl = kcalloc(mem_info->num, sizeof(struct bna_mem_descr),
-				GFP_KERNEL);
-	if (mem_info->mdl == NULL)
-		return -ENOMEM;
-
-	if (mem_info->mem_type == BNA_MEM_T_DMA) {
-		for (i = 0; i < mem_info->num; i++) {
-			mem_info->mdl[i].len = mem_info->len;
-			mem_info->mdl[i].kva =
-				dma_alloc_coherent(&bnad->pcidev->dev,
-						mem_info->len, &dma_pa,
-						GFP_KERNEL);
-
-			if (mem_info->mdl[i].kva == NULL)
-				goto err_return;
-
-			BNA_SET_DMA_ADDR(dma_pa,
-					 &(mem_info->mdl[i].dma));
-		}
-	} else {
-		for (i = 0; i < mem_info->num; i++) {
-			mem_info->mdl[i].len = mem_info->len;
-			mem_info->mdl[i].kva = kzalloc(mem_info->len,
-							GFP_KERNEL);
-			if (mem_info->mdl[i].kva == NULL)
-				goto err_return;
-		}
-	}
-
-	return 0;
-
-err_return:
-	bnad_mem_free(bnad, mem_info);
-	return -ENOMEM;
-}
-
-/* Free IRQ for Mailbox */
-static void
-bnad_mbox_irq_free(struct bnad *bnad,
-		   struct bna_intr_info *intr_info)
-{
-	int irq;
-	unsigned long flags;
-
-	if (intr_info->idl == NULL)
-		return;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bnad_disable_mbox_irq(bnad);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	irq = BNAD_GET_MBOX_IRQ(bnad);
-	free_irq(irq, bnad);
-
-	kfree(intr_info->idl);
-}
-
-/*
- * Allocates IRQ for Mailbox, but keep it disabled
- * This will be enabled once we get the mbox enable callback
- * from bna
- */
-static int
-bnad_mbox_irq_alloc(struct bnad *bnad,
-		    struct bna_intr_info *intr_info)
-{
-	int		err = 0;
-	unsigned long	irq_flags, flags;
-	u32	irq;
-	irq_handler_t	irq_handler;
-
-	/* Mbox should use only 1 vector */
-
-	intr_info->idl = kzalloc(sizeof(*(intr_info->idl)), GFP_KERNEL);
-	if (!intr_info->idl)
-		return -ENOMEM;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	if (bnad->cfg_flags & BNAD_CF_MSIX) {
-		irq_handler = (irq_handler_t)bnad_msix_mbox_handler;
-		irq = bnad->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector;
-		irq_flags = 0;
-		intr_info->intr_type = BNA_INTR_T_MSIX;
-		intr_info->idl[0].vector = BNAD_MAILBOX_MSIX_INDEX;
-	} else {
-		irq_handler = (irq_handler_t)bnad_isr;
-		irq = bnad->pcidev->irq;
-		irq_flags = IRQF_SHARED;
-		intr_info->intr_type = BNA_INTR_T_INTX;
-	}
-
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	sprintf(bnad->mbox_irq_name, "%s", BNAD_NAME);
-
-	/*
-	 * Set the Mbox IRQ disable flag, so that the IRQ handler
-	 * called from request_irq() for SHARED IRQs do not execute
-	 */
-	set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags);
-
-	BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
-
-	err = request_irq(irq, irq_handler, irq_flags,
-			  bnad->mbox_irq_name, bnad);
-
-	if (err) {
-		kfree(intr_info->idl);
-		intr_info->idl = NULL;
-	}
-
-	return err;
-}
-
-static void
-bnad_txrx_irq_free(struct bnad *bnad, struct bna_intr_info *intr_info)
-{
-	kfree(intr_info->idl);
-	intr_info->idl = NULL;
-}
-
-/* Allocates Interrupt Descriptor List for MSIX/INT-X vectors */
-static int
-bnad_txrx_irq_alloc(struct bnad *bnad, enum bnad_intr_source src,
-		    uint txrx_id, struct bna_intr_info *intr_info)
-{
-	int i, vector_start = 0;
-	u32 cfg_flags;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	cfg_flags = bnad->cfg_flags;
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	if (cfg_flags & BNAD_CF_MSIX) {
-		intr_info->intr_type = BNA_INTR_T_MSIX;
-		intr_info->idl = kcalloc(intr_info->num,
-					sizeof(struct bna_intr_descr),
-					GFP_KERNEL);
-		if (!intr_info->idl)
-			return -ENOMEM;
-
-		switch (src) {
-		case BNAD_INTR_TX:
-			vector_start = BNAD_MAILBOX_MSIX_VECTORS + txrx_id;
-			break;
-
-		case BNAD_INTR_RX:
-			vector_start = BNAD_MAILBOX_MSIX_VECTORS +
-					(bnad->num_tx * bnad->num_txq_per_tx) +
-					txrx_id;
-			break;
-
-		default:
-			BUG();
-		}
-
-		for (i = 0; i < intr_info->num; i++)
-			intr_info->idl[i].vector = vector_start + i;
-	} else {
-		intr_info->intr_type = BNA_INTR_T_INTX;
-		intr_info->num = 1;
-		intr_info->idl = kcalloc(intr_info->num,
-					sizeof(struct bna_intr_descr),
-					GFP_KERNEL);
-		if (!intr_info->idl)
-			return -ENOMEM;
-
-		switch (src) {
-		case BNAD_INTR_TX:
-			intr_info->idl[0].vector = BNAD_INTX_TX_IB_BITMASK;
-			break;
-
-		case BNAD_INTR_RX:
-			intr_info->idl[0].vector = BNAD_INTX_RX_IB_BITMASK;
-			break;
-		}
-	}
-	return 0;
-}
-
-/**
- * NOTE: Should be called for MSIX only
- * Unregisters Tx MSIX vector(s) from the kernel
- */
-static void
-bnad_tx_msix_unregister(struct bnad *bnad, struct bnad_tx_info *tx_info,
-			int num_txqs)
-{
-	int i;
-	int vector_num;
-
-	for (i = 0; i < num_txqs; i++) {
-		if (tx_info->tcb[i] == NULL)
-			continue;
-
-		vector_num = tx_info->tcb[i]->intr_vector;
-		free_irq(bnad->msix_table[vector_num].vector, tx_info->tcb[i]);
-	}
-}
-
-/**
- * NOTE: Should be called for MSIX only
- * Registers Tx MSIX vector(s) and ISR(s), cookie with the kernel
- */
-static int
-bnad_tx_msix_register(struct bnad *bnad, struct bnad_tx_info *tx_info,
-			uint tx_id, int num_txqs)
-{
-	int i;
-	int err;
-	int vector_num;
-
-	for (i = 0; i < num_txqs; i++) {
-		vector_num = tx_info->tcb[i]->intr_vector;
-		sprintf(tx_info->tcb[i]->name, "%s TXQ %d", bnad->netdev->name,
-				tx_id + tx_info->tcb[i]->id);
-		err = request_irq(bnad->msix_table[vector_num].vector,
-				  (irq_handler_t)bnad_msix_tx, 0,
-				  tx_info->tcb[i]->name,
-				  tx_info->tcb[i]);
-		if (err)
-			goto err_return;
-	}
-
-	return 0;
-
-err_return:
-	if (i > 0)
-		bnad_tx_msix_unregister(bnad, tx_info, (i - 1));
-	return -1;
-}
-
-/**
- * NOTE: Should be called for MSIX only
- * Unregisters Rx MSIX vector(s) from the kernel
- */
-static void
-bnad_rx_msix_unregister(struct bnad *bnad, struct bnad_rx_info *rx_info,
-			int num_rxps)
-{
-	int i;
-	int vector_num;
-
-	for (i = 0; i < num_rxps; i++) {
-		if (rx_info->rx_ctrl[i].ccb == NULL)
-			continue;
-
-		vector_num = rx_info->rx_ctrl[i].ccb->intr_vector;
-		free_irq(bnad->msix_table[vector_num].vector,
-			 rx_info->rx_ctrl[i].ccb);
-	}
-}
-
-/**
- * NOTE: Should be called for MSIX only
- * Registers Tx MSIX vector(s) and ISR(s), cookie with the kernel
- */
-static int
-bnad_rx_msix_register(struct bnad *bnad, struct bnad_rx_info *rx_info,
-			uint rx_id, int num_rxps)
-{
-	int i;
-	int err;
-	int vector_num;
-
-	for (i = 0; i < num_rxps; i++) {
-		vector_num = rx_info->rx_ctrl[i].ccb->intr_vector;
-		sprintf(rx_info->rx_ctrl[i].ccb->name, "%s CQ %d",
-			bnad->netdev->name,
-			rx_id + rx_info->rx_ctrl[i].ccb->id);
-		err = request_irq(bnad->msix_table[vector_num].vector,
-				  (irq_handler_t)bnad_msix_rx, 0,
-				  rx_info->rx_ctrl[i].ccb->name,
-				  rx_info->rx_ctrl[i].ccb);
-		if (err)
-			goto err_return;
-	}
-
-	return 0;
-
-err_return:
-	if (i > 0)
-		bnad_rx_msix_unregister(bnad, rx_info, (i - 1));
-	return -1;
-}
-
-/* Free Tx object Resources */
-static void
-bnad_tx_res_free(struct bnad *bnad, struct bna_res_info *res_info)
-{
-	int i;
-
-	for (i = 0; i < BNA_TX_RES_T_MAX; i++) {
-		if (res_info[i].res_type == BNA_RES_T_MEM)
-			bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
-		else if (res_info[i].res_type == BNA_RES_T_INTR)
-			bnad_txrx_irq_free(bnad, &res_info[i].res_u.intr_info);
-	}
-}
-
-/* Allocates memory and interrupt resources for Tx object */
-static int
-bnad_tx_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
-		  uint tx_id)
-{
-	int i, err = 0;
-
-	for (i = 0; i < BNA_TX_RES_T_MAX; i++) {
-		if (res_info[i].res_type == BNA_RES_T_MEM)
-			err = bnad_mem_alloc(bnad,
-					&res_info[i].res_u.mem_info);
-		else if (res_info[i].res_type == BNA_RES_T_INTR)
-			err = bnad_txrx_irq_alloc(bnad, BNAD_INTR_TX, tx_id,
-					&res_info[i].res_u.intr_info);
-		if (err)
-			goto err_return;
-	}
-	return 0;
-
-err_return:
-	bnad_tx_res_free(bnad, res_info);
-	return err;
-}
-
-/* Free Rx object Resources */
-static void
-bnad_rx_res_free(struct bnad *bnad, struct bna_res_info *res_info)
-{
-	int i;
-
-	for (i = 0; i < BNA_RX_RES_T_MAX; i++) {
-		if (res_info[i].res_type == BNA_RES_T_MEM)
-			bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
-		else if (res_info[i].res_type == BNA_RES_T_INTR)
-			bnad_txrx_irq_free(bnad, &res_info[i].res_u.intr_info);
-	}
-}
-
-/* Allocates memory and interrupt resources for Rx object */
-static int
-bnad_rx_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
-		  uint rx_id)
-{
-	int i, err = 0;
-
-	/* All memory needs to be allocated before setup_ccbs */
-	for (i = 0; i < BNA_RX_RES_T_MAX; i++) {
-		if (res_info[i].res_type == BNA_RES_T_MEM)
-			err = bnad_mem_alloc(bnad,
-					&res_info[i].res_u.mem_info);
-		else if (res_info[i].res_type == BNA_RES_T_INTR)
-			err = bnad_txrx_irq_alloc(bnad, BNAD_INTR_RX, rx_id,
-					&res_info[i].res_u.intr_info);
-		if (err)
-			goto err_return;
-	}
-	return 0;
-
-err_return:
-	bnad_rx_res_free(bnad, res_info);
-	return err;
-}
-
-/* Timer callbacks */
-/* a) IOC timer */
-static void
-bnad_ioc_timeout(unsigned long data)
-{
-	struct bnad *bnad = (struct bnad *)data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bfa_nw_ioc_timeout((void *) &bnad->bna.device.ioc);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-}
-
-static void
-bnad_ioc_hb_check(unsigned long data)
-{
-	struct bnad *bnad = (struct bnad *)data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bfa_nw_ioc_hb_check((void *) &bnad->bna.device.ioc);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-}
-
-static void
-bnad_iocpf_timeout(unsigned long data)
-{
-	struct bnad *bnad = (struct bnad *)data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bfa_nw_iocpf_timeout((void *) &bnad->bna.device.ioc);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-}
-
-static void
-bnad_iocpf_sem_timeout(unsigned long data)
-{
-	struct bnad *bnad = (struct bnad *)data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bfa_nw_iocpf_sem_timeout((void *) &bnad->bna.device.ioc);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-}
-
-/*
- * All timer routines use bnad->bna_lock to protect against
- * the following race, which may occur in case of no locking:
- *	Time	CPU m	CPU n
- *	0       1 = test_bit
- *	1			clear_bit
- *	2			del_timer_sync
- *	3	mod_timer
- */
-
-/* b) Dynamic Interrupt Moderation Timer */
-static void
-bnad_dim_timeout(unsigned long data)
-{
-	struct bnad *bnad = (struct bnad *)data;
-	struct bnad_rx_info *rx_info;
-	struct bnad_rx_ctrl *rx_ctrl;
-	int i, j;
-	unsigned long flags;
-
-	if (!netif_carrier_ok(bnad->netdev))
-		return;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	for (i = 0; i < bnad->num_rx; i++) {
-		rx_info = &bnad->rx_info[i];
-		if (!rx_info->rx)
-			continue;
-		for (j = 0; j < bnad->num_rxp_per_rx; j++) {
-			rx_ctrl = &rx_info->rx_ctrl[j];
-			if (!rx_ctrl->ccb)
-				continue;
-			bna_rx_dim_update(rx_ctrl->ccb);
-		}
-	}
-
-	/* Check for BNAD_CF_DIM_ENABLED, does not eleminate a race */
-	if (test_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags))
-		mod_timer(&bnad->dim_timer,
-			  jiffies + msecs_to_jiffies(BNAD_DIM_TIMER_FREQ));
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-}
-
-/* c)  Statistics Timer */
-static void
-bnad_stats_timeout(unsigned long data)
-{
-	struct bnad *bnad = (struct bnad *)data;
-	unsigned long flags;
-
-	if (!netif_running(bnad->netdev) ||
-		!test_bit(BNAD_RF_STATS_TIMER_RUNNING, &bnad->run_flags))
-		return;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_stats_get(&bnad->bna);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-}
-
-/*
- * Set up timer for DIM
- * Called with bnad->bna_lock held
- */
-void
-bnad_dim_timer_start(struct bnad *bnad)
-{
-	if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED &&
-	    !test_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags)) {
-		setup_timer(&bnad->dim_timer, bnad_dim_timeout,
-			    (unsigned long)bnad);
-		set_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags);
-		mod_timer(&bnad->dim_timer,
-			  jiffies + msecs_to_jiffies(BNAD_DIM_TIMER_FREQ));
-	}
-}
-
-/*
- * Set up timer for statistics
- * Called with mutex_lock(&bnad->conf_mutex) held
- */
-static void
-bnad_stats_timer_start(struct bnad *bnad)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	if (!test_and_set_bit(BNAD_RF_STATS_TIMER_RUNNING, &bnad->run_flags)) {
-		setup_timer(&bnad->stats_timer, bnad_stats_timeout,
-			    (unsigned long)bnad);
-		mod_timer(&bnad->stats_timer,
-			  jiffies + msecs_to_jiffies(BNAD_STATS_TIMER_FREQ));
-	}
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-}
-
-/*
- * Stops the stats timer
- * Called with mutex_lock(&bnad->conf_mutex) held
- */
-static void
-bnad_stats_timer_stop(struct bnad *bnad)
-{
-	int to_del = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	if (test_and_clear_bit(BNAD_RF_STATS_TIMER_RUNNING, &bnad->run_flags))
-		to_del = 1;
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	if (to_del)
-		del_timer_sync(&bnad->stats_timer);
-}
-
-/* Utilities */
-
-static void
-bnad_netdev_mc_list_get(struct net_device *netdev, u8 *mc_list)
-{
-	int i = 1; /* Index 0 has broadcast address */
-	struct netdev_hw_addr *mc_addr;
-
-	netdev_for_each_mc_addr(mc_addr, netdev) {
-		memcpy(&mc_list[i * ETH_ALEN], &mc_addr->addr[0],
-							ETH_ALEN);
-		i++;
-	}
-}
-
-static int
-bnad_napi_poll_rx(struct napi_struct *napi, int budget)
-{
-	struct bnad_rx_ctrl *rx_ctrl =
-		container_of(napi, struct bnad_rx_ctrl, napi);
-	struct bna_ccb *ccb;
-	struct bnad *bnad;
-	int rcvd = 0;
-
-	ccb = rx_ctrl->ccb;
-
-	bnad = ccb->bnad;
-
-	if (!netif_carrier_ok(bnad->netdev))
-		goto poll_exit;
-
-	rcvd = bnad_poll_cq(bnad, ccb, budget);
-	if (rcvd == budget)
-		return rcvd;
-
-poll_exit:
-	napi_complete((napi));
-
-	BNAD_UPDATE_CTR(bnad, netif_rx_complete);
-
-	bnad_enable_rx_irq(bnad, ccb);
-	return rcvd;
-}
-
-static void
-bnad_napi_enable(struct bnad *bnad, u32 rx_id)
-{
-	struct bnad_rx_ctrl *rx_ctrl;
-	int i;
-
-	/* Initialize & enable NAPI */
-	for (i = 0; i <	bnad->num_rxp_per_rx; i++) {
-		rx_ctrl = &bnad->rx_info[rx_id].rx_ctrl[i];
-
-		netif_napi_add(bnad->netdev, &rx_ctrl->napi,
-			       bnad_napi_poll_rx, 64);
-
-		napi_enable(&rx_ctrl->napi);
-	}
-}
-
-static void
-bnad_napi_disable(struct bnad *bnad, u32 rx_id)
-{
-	int i;
-
-	/* First disable and then clean up */
-	for (i = 0; i < bnad->num_rxp_per_rx; i++) {
-		napi_disable(&bnad->rx_info[rx_id].rx_ctrl[i].napi);
-		netif_napi_del(&bnad->rx_info[rx_id].rx_ctrl[i].napi);
-	}
-}
-
-/* Should be held with conf_lock held */
-void
-bnad_cleanup_tx(struct bnad *bnad, uint tx_id)
-{
-	struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id];
-	struct bna_res_info *res_info = &bnad->tx_res_info[tx_id].res_info[0];
-	unsigned long flags;
-
-	if (!tx_info->tx)
-		return;
-
-	init_completion(&bnad->bnad_completions.tx_comp);
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_tx_disable(tx_info->tx, BNA_HARD_CLEANUP, bnad_cb_tx_disabled);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	wait_for_completion(&bnad->bnad_completions.tx_comp);
-
-	if (tx_info->tcb[0]->intr_type == BNA_INTR_T_MSIX)
-		bnad_tx_msix_unregister(bnad, tx_info,
-			bnad->num_txq_per_tx);
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_tx_destroy(tx_info->tx);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	tx_info->tx = NULL;
-
-	if (0 == tx_id)
-		tasklet_kill(&bnad->tx_free_tasklet);
-
-	bnad_tx_res_free(bnad, res_info);
-}
-
-/* Should be held with conf_lock held */
-int
-bnad_setup_tx(struct bnad *bnad, uint tx_id)
-{
-	int err;
-	struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id];
-	struct bna_res_info *res_info = &bnad->tx_res_info[tx_id].res_info[0];
-	struct bna_intr_info *intr_info =
-			&res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info;
-	struct bna_tx_config *tx_config = &bnad->tx_config[tx_id];
-	struct bna_tx_event_cbfn tx_cbfn;
-	struct bna_tx *tx;
-	unsigned long flags;
-
-	/* Initialize the Tx object configuration */
-	tx_config->num_txq = bnad->num_txq_per_tx;
-	tx_config->txq_depth = bnad->txq_depth;
-	tx_config->tx_type = BNA_TX_T_REGULAR;
-
-	/* Initialize the tx event handlers */
-	tx_cbfn.tcb_setup_cbfn = bnad_cb_tcb_setup;
-	tx_cbfn.tcb_destroy_cbfn = bnad_cb_tcb_destroy;
-	tx_cbfn.tx_stall_cbfn = bnad_cb_tx_stall;
-	tx_cbfn.tx_resume_cbfn = bnad_cb_tx_resume;
-	tx_cbfn.tx_cleanup_cbfn = bnad_cb_tx_cleanup;
-
-	/* Get BNA's resource requirement for one tx object */
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_tx_res_req(bnad->num_txq_per_tx,
-		bnad->txq_depth, res_info);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	/* Fill Unmap Q memory requirements */
-	BNAD_FILL_UNMAPQ_MEM_REQ(
-			&res_info[BNA_TX_RES_MEM_T_UNMAPQ],
-			bnad->num_txq_per_tx,
-			BNAD_TX_UNMAPQ_DEPTH);
-
-	/* Allocate resources */
-	err = bnad_tx_res_alloc(bnad, res_info, tx_id);
-	if (err)
-		return err;
-
-	/* Ask BNA to create one Tx object, supplying required resources */
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	tx = bna_tx_create(&bnad->bna, bnad, tx_config, &tx_cbfn, res_info,
-			tx_info);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	if (!tx)
-		goto err_return;
-	tx_info->tx = tx;
-
-	/* Register ISR for the Tx object */
-	if (intr_info->intr_type == BNA_INTR_T_MSIX) {
-		err = bnad_tx_msix_register(bnad, tx_info,
-			tx_id, bnad->num_txq_per_tx);
-		if (err)
-			goto err_return;
-	}
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_tx_enable(tx);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	return 0;
-
-err_return:
-	bnad_tx_res_free(bnad, res_info);
-	return err;
-}
-
-/* Setup the rx config for bna_rx_create */
-/* bnad decides the configuration */
-static void
-bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config)
-{
-	rx_config->rx_type = BNA_RX_T_REGULAR;
-	rx_config->num_paths = bnad->num_rxp_per_rx;
-
-	if (bnad->num_rxp_per_rx > 1) {
-		rx_config->rss_status = BNA_STATUS_T_ENABLED;
-		rx_config->rss_config.hash_type =
-				(BFI_RSS_T_V4_TCP |
-				 BFI_RSS_T_V6_TCP |
-				 BFI_RSS_T_V4_IP  |
-				 BFI_RSS_T_V6_IP);
-		rx_config->rss_config.hash_mask =
-				bnad->num_rxp_per_rx - 1;
-		get_random_bytes(rx_config->rss_config.toeplitz_hash_key,
-			sizeof(rx_config->rss_config.toeplitz_hash_key));
-	} else {
-		rx_config->rss_status = BNA_STATUS_T_DISABLED;
-		memset(&rx_config->rss_config, 0,
-		       sizeof(rx_config->rss_config));
-	}
-	rx_config->rxp_type = BNA_RXP_SLR;
-	rx_config->q_depth = bnad->rxq_depth;
-
-	rx_config->small_buff_size = BFI_SMALL_RXBUF_SIZE;
-
-	rx_config->vlan_strip_status = BNA_STATUS_T_ENABLED;
-}
-
-/* Called with mutex_lock(&bnad->conf_mutex) held */
-void
-bnad_cleanup_rx(struct bnad *bnad, uint rx_id)
-{
-	struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
-	struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
-	struct bna_res_info *res_info = &bnad->rx_res_info[rx_id].res_info[0];
-	unsigned long flags;
-	int dim_timer_del = 0;
-
-	if (!rx_info->rx)
-		return;
-
-	if (0 == rx_id) {
-		spin_lock_irqsave(&bnad->bna_lock, flags);
-		dim_timer_del = bnad_dim_timer_running(bnad);
-		if (dim_timer_del)
-			clear_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags);
-		spin_unlock_irqrestore(&bnad->bna_lock, flags);
-		if (dim_timer_del)
-			del_timer_sync(&bnad->dim_timer);
-	}
-
-	bnad_napi_disable(bnad, rx_id);
-
-	init_completion(&bnad->bnad_completions.rx_comp);
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_rx_disable(rx_info->rx, BNA_HARD_CLEANUP, bnad_cb_rx_disabled);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	wait_for_completion(&bnad->bnad_completions.rx_comp);
-
-	if (rx_info->rx_ctrl[0].ccb->intr_type == BNA_INTR_T_MSIX)
-		bnad_rx_msix_unregister(bnad, rx_info, rx_config->num_paths);
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_rx_destroy(rx_info->rx);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	rx_info->rx = NULL;
-
-	bnad_rx_res_free(bnad, res_info);
-}
-
-/* Called with mutex_lock(&bnad->conf_mutex) held */
-int
-bnad_setup_rx(struct bnad *bnad, uint rx_id)
-{
-	int err;
-	struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
-	struct bna_res_info *res_info = &bnad->rx_res_info[rx_id].res_info[0];
-	struct bna_intr_info *intr_info =
-			&res_info[BNA_RX_RES_T_INTR].res_u.intr_info;
-	struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
-	struct bna_rx_event_cbfn rx_cbfn;
-	struct bna_rx *rx;
-	unsigned long flags;
-
-	/* Initialize the Rx object configuration */
-	bnad_init_rx_config(bnad, rx_config);
-
-	/* 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.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;
-	rx_cbfn.rx_post_cbfn = bnad_cb_rx_post;
-
-	/* Get BNA's resource requirement for one Rx object */
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_rx_res_req(rx_config, res_info);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	/* Fill Unmap Q memory requirements */
-	BNAD_FILL_UNMAPQ_MEM_REQ(
-			&res_info[BNA_RX_RES_MEM_T_UNMAPQ],
-			rx_config->num_paths +
-			((rx_config->rxp_type == BNA_RXP_SINGLE) ? 0 :
-				rx_config->num_paths), BNAD_RX_UNMAPQ_DEPTH);
-
-	/* Allocate resource */
-	err = bnad_rx_res_alloc(bnad, res_info, rx_id);
-	if (err)
-		return err;
-
-	/* Ask BNA to create one Rx object, supplying required resources */
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	rx = bna_rx_create(&bnad->bna, bnad, rx_config, &rx_cbfn, res_info,
-			rx_info);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	if (!rx)
-		goto err_return;
-	rx_info->rx = rx;
-
-	/* Register ISR for the Rx object */
-	if (intr_info->intr_type == BNA_INTR_T_MSIX) {
-		err = bnad_rx_msix_register(bnad, rx_info, rx_id,
-						rx_config->num_paths);
-		if (err)
-			goto err_return;
-	}
-
-	/* Enable NAPI */
-	bnad_napi_enable(bnad, rx_id);
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	if (0 == rx_id) {
-		/* Set up Dynamic Interrupt Moderation Vector */
-		if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED)
-			bna_rx_dim_reconfig(&bnad->bna, bna_napi_dim_vector);
-
-		/* Enable VLAN filtering only on the default Rx */
-		bna_rx_vlanfilter_enable(rx);
-
-		/* Start the DIM timer */
-		bnad_dim_timer_start(bnad);
-	}
-
-	bna_rx_enable(rx);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	return 0;
-
-err_return:
-	bnad_cleanup_rx(bnad, rx_id);
-	return err;
-}
-
-/* Called with conf_lock & bnad->bna_lock held */
-void
-bnad_tx_coalescing_timeo_set(struct bnad *bnad)
-{
-	struct bnad_tx_info *tx_info;
-
-	tx_info = &bnad->tx_info[0];
-	if (!tx_info->tx)
-		return;
-
-	bna_tx_coalescing_timeo_set(tx_info->tx, bnad->tx_coalescing_timeo);
-}
-
-/* Called with conf_lock & bnad->bna_lock held */
-void
-bnad_rx_coalescing_timeo_set(struct bnad *bnad)
-{
-	struct bnad_rx_info *rx_info;
-	int	i;
-
-	for (i = 0; i < bnad->num_rx; i++) {
-		rx_info = &bnad->rx_info[i];
-		if (!rx_info->rx)
-			continue;
-		bna_rx_coalescing_timeo_set(rx_info->rx,
-				bnad->rx_coalescing_timeo);
-	}
-}
-
-/*
- * Called with bnad->bna_lock held
- */
-static int
-bnad_mac_addr_set_locked(struct bnad *bnad, u8 *mac_addr)
-{
-	int ret;
-
-	if (!is_valid_ether_addr(mac_addr))
-		return -EADDRNOTAVAIL;
-
-	/* If datapath is down, pretend everything went through */
-	if (!bnad->rx_info[0].rx)
-		return 0;
-
-	ret = bna_rx_ucast_set(bnad->rx_info[0].rx, mac_addr, NULL);
-	if (ret != BNA_CB_SUCCESS)
-		return -EADDRNOTAVAIL;
-
-	return 0;
-}
-
-/* Should be called with conf_lock held */
-static int
-bnad_enable_default_bcast(struct bnad *bnad)
-{
-	struct bnad_rx_info *rx_info = &bnad->rx_info[0];
-	int ret;
-	unsigned long flags;
-
-	init_completion(&bnad->bnad_completions.mcast_comp);
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	ret = bna_rx_mcast_add(rx_info->rx, (u8 *)bnad_bcast_addr,
-				bnad_cb_rx_mcast_add);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	if (ret == BNA_CB_SUCCESS)
-		wait_for_completion(&bnad->bnad_completions.mcast_comp);
-	else
-		return -ENODEV;
-
-	if (bnad->bnad_completions.mcast_comp_status != BNA_CB_SUCCESS)
-		return -ENODEV;
-
-	return 0;
-}
-
-/* Called with bnad_conf_lock() held */
-static void
-bnad_restore_vlans(struct bnad *bnad, u32 rx_id)
-{
-	u16 vid;
-	unsigned long flags;
-
-	BUG_ON(!(VLAN_N_VID == (BFI_MAX_VLAN + 1)));
-
-	for_each_set_bit(vid, bnad->active_vlans, VLAN_N_VID) {
-		spin_lock_irqsave(&bnad->bna_lock, flags);
-		bna_rx_vlan_add(bnad->rx_info[rx_id].rx, vid);
-		spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	}
-}
-
-/* Statistics utilities */
-void
-bnad_netdev_qstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats)
-{
-	int i, j;
-
-	for (i = 0; i < bnad->num_rx; i++) {
-		for (j = 0; j < bnad->num_rxp_per_rx; j++) {
-			if (bnad->rx_info[i].rx_ctrl[j].ccb) {
-				stats->rx_packets += bnad->rx_info[i].
-				rx_ctrl[j].ccb->rcb[0]->rxq->rx_packets;
-				stats->rx_bytes += bnad->rx_info[i].
-					rx_ctrl[j].ccb->rcb[0]->rxq->rx_bytes;
-				if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] &&
-					bnad->rx_info[i].rx_ctrl[j].ccb->
-					rcb[1]->rxq) {
-					stats->rx_packets +=
-						bnad->rx_info[i].rx_ctrl[j].
-						ccb->rcb[1]->rxq->rx_packets;
-					stats->rx_bytes +=
-						bnad->rx_info[i].rx_ctrl[j].
-						ccb->rcb[1]->rxq->rx_bytes;
-				}
-			}
-		}
-	}
-	for (i = 0; i < bnad->num_tx; i++) {
-		for (j = 0; j < bnad->num_txq_per_tx; j++) {
-			if (bnad->tx_info[i].tcb[j]) {
-				stats->tx_packets +=
-				bnad->tx_info[i].tcb[j]->txq->tx_packets;
-				stats->tx_bytes +=
-					bnad->tx_info[i].tcb[j]->txq->tx_bytes;
-			}
-		}
-	}
-}
-
-/*
- * Must be called with the bna_lock held.
- */
-void
-bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats)
-{
-	struct bfi_ll_stats_mac *mac_stats;
-	u64 bmap;
-	int i;
-
-	mac_stats = &bnad->stats.bna_stats->hw_stats->mac_stats;
-	stats->rx_errors =
-		mac_stats->rx_fcs_error + mac_stats->rx_alignment_error +
-		mac_stats->rx_frame_length_error + mac_stats->rx_code_error +
-		mac_stats->rx_undersize;
-	stats->tx_errors = mac_stats->tx_fcs_error +
-					mac_stats->tx_undersize;
-	stats->rx_dropped = mac_stats->rx_drop;
-	stats->tx_dropped = mac_stats->tx_drop;
-	stats->multicast = mac_stats->rx_multicast;
-	stats->collisions = mac_stats->tx_total_collision;
-
-	stats->rx_length_errors = mac_stats->rx_frame_length_error;
-
-	/* receive ring buffer overflow  ?? */
-
-	stats->rx_crc_errors = mac_stats->rx_fcs_error;
-	stats->rx_frame_errors = mac_stats->rx_alignment_error;
-	/* recv'r fifo overrun */
-	bmap = (u64)bnad->stats.bna_stats->rxf_bmap[0] |
-		((u64)bnad->stats.bna_stats->rxf_bmap[1] << 32);
-	for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
-		if (bmap & 1) {
-			stats->rx_fifo_errors +=
-				bnad->stats.bna_stats->
-					hw_stats->rxf_stats[i].frame_drops;
-			break;
-		}
-		bmap >>= 1;
-	}
-}
-
-static void
-bnad_mbox_irq_sync(struct bnad *bnad)
-{
-	u32 irq;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	if (bnad->cfg_flags & BNAD_CF_MSIX)
-		irq = bnad->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector;
-	else
-		irq = bnad->pcidev->irq;
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	synchronize_irq(irq);
-}
-
-/* Utility used by bnad_start_xmit, for doing TSO */
-static int
-bnad_tso_prepare(struct bnad *bnad, struct sk_buff *skb)
-{
-	int err;
-
-	/* SKB_GSO_TCPV4 and SKB_GSO_TCPV6 is defined since 2.6.18. */
-	BUG_ON(!(skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4 ||
-		   skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6));
-	if (skb_header_cloned(skb)) {
-		err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
-		if (err) {
-			BNAD_UPDATE_CTR(bnad, tso_err);
-			return err;
-		}
-	}
-
-	/*
-	 * For TSO, the TCP checksum field is seeded with pseudo-header sum
-	 * excluding the length field.
-	 */
-	if (skb->protocol == htons(ETH_P_IP)) {
-		struct iphdr *iph = ip_hdr(skb);
-
-		/* Do we really need these? */
-		iph->tot_len = 0;
-		iph->check = 0;
-
-		tcp_hdr(skb)->check =
-			~csum_tcpudp_magic(iph->saddr, iph->daddr, 0,
-					   IPPROTO_TCP, 0);
-		BNAD_UPDATE_CTR(bnad, tso4);
-	} else {
-		struct ipv6hdr *ipv6h = ipv6_hdr(skb);
-
-		BUG_ON(!(skb->protocol == htons(ETH_P_IPV6)));
-		ipv6h->payload_len = 0;
-		tcp_hdr(skb)->check =
-			~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, 0,
-					 IPPROTO_TCP, 0);
-		BNAD_UPDATE_CTR(bnad, tso6);
-	}
-
-	return 0;
-}
-
-/*
- * Initialize Q numbers depending on Rx Paths
- * Called with bnad->bna_lock held, because of cfg_flags
- * access.
- */
-static void
-bnad_q_num_init(struct bnad *bnad)
-{
-	int rxps;
-
-	rxps = min((uint)num_online_cpus(),
-			(uint)(BNAD_MAX_RXS * BNAD_MAX_RXPS_PER_RX));
-
-	if (!(bnad->cfg_flags & BNAD_CF_MSIX))
-		rxps = 1;	/* INTx */
-
-	bnad->num_rx = 1;
-	bnad->num_tx = 1;
-	bnad->num_rxp_per_rx = rxps;
-	bnad->num_txq_per_tx = BNAD_TXQ_NUM;
-}
-
-/*
- * Adjusts the Q numbers, given a number of msix vectors
- * Give preference to RSS as opposed to Tx priority Queues,
- * in such a case, just use 1 Tx Q
- * Called with bnad->bna_lock held b'cos of cfg_flags access
- */
-static void
-bnad_q_num_adjust(struct bnad *bnad, int msix_vectors)
-{
-	bnad->num_txq_per_tx = 1;
-	if ((msix_vectors >= (bnad->num_tx * bnad->num_txq_per_tx)  +
-	     bnad_rxqs_per_cq + BNAD_MAILBOX_MSIX_VECTORS) &&
-	    (bnad->cfg_flags & BNAD_CF_MSIX)) {
-		bnad->num_rxp_per_rx = msix_vectors -
-			(bnad->num_tx * bnad->num_txq_per_tx) -
-			BNAD_MAILBOX_MSIX_VECTORS;
-	} else
-		bnad->num_rxp_per_rx = 1;
-}
-
-/* Enable / disable device */
-static void
-bnad_device_disable(struct bnad *bnad)
-{
-	unsigned long flags;
-
-	init_completion(&bnad->bnad_completions.ioc_comp);
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_device_disable(&bnad->bna.device, BNA_HARD_CLEANUP);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	wait_for_completion(&bnad->bnad_completions.ioc_comp);
-}
-
-static int
-bnad_device_enable(struct bnad *bnad)
-{
-	int err = 0;
-	unsigned long flags;
-
-	init_completion(&bnad->bnad_completions.ioc_comp);
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_device_enable(&bnad->bna.device);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	wait_for_completion(&bnad->bnad_completions.ioc_comp);
-
-	if (bnad->bnad_completions.ioc_comp_status)
-		err = bnad->bnad_completions.ioc_comp_status;
-
-	return err;
-}
-
-/* Free BNA resources */
-static void
-bnad_res_free(struct bnad *bnad)
-{
-	int i;
-	struct bna_res_info *res_info = &bnad->res_info[0];
-
-	for (i = 0; i < BNA_RES_T_MAX; i++) {
-		if (res_info[i].res_type == BNA_RES_T_MEM)
-			bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
-		else
-			bnad_mbox_irq_free(bnad, &res_info[i].res_u.intr_info);
-	}
-}
-
-/* Allocates memory and interrupt resources for BNA */
-static int
-bnad_res_alloc(struct bnad *bnad)
-{
-	int i, err;
-	struct bna_res_info *res_info = &bnad->res_info[0];
-
-	for (i = 0; i < BNA_RES_T_MAX; i++) {
-		if (res_info[i].res_type == BNA_RES_T_MEM)
-			err = bnad_mem_alloc(bnad, &res_info[i].res_u.mem_info);
-		else
-			err = bnad_mbox_irq_alloc(bnad,
-						  &res_info[i].res_u.intr_info);
-		if (err)
-			goto err_return;
-	}
-	return 0;
-
-err_return:
-	bnad_res_free(bnad);
-	return err;
-}
-
-/* Interrupt enable / disable */
-static void
-bnad_enable_msix(struct bnad *bnad)
-{
-	int i, ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	if (!(bnad->cfg_flags & BNAD_CF_MSIX)) {
-		spin_unlock_irqrestore(&bnad->bna_lock, flags);
-		return;
-	}
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	if (bnad->msix_table)
-		return;
-
-	bnad->msix_table =
-		kcalloc(bnad->msix_num, sizeof(struct msix_entry), GFP_KERNEL);
-
-	if (!bnad->msix_table)
-		goto intx_mode;
-
-	for (i = 0; i < bnad->msix_num; i++)
-		bnad->msix_table[i].entry = i;
-
-	ret = pci_enable_msix(bnad->pcidev, bnad->msix_table, bnad->msix_num);
-	if (ret > 0) {
-		/* Not enough MSI-X vectors. */
-
-		spin_lock_irqsave(&bnad->bna_lock, flags);
-		/* ret = #of vectors that we got */
-		bnad_q_num_adjust(bnad, ret);
-		spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-		bnad->msix_num = (bnad->num_tx * bnad->num_txq_per_tx)
-			+ (bnad->num_rx
-			* bnad->num_rxp_per_rx) +
-			 BNAD_MAILBOX_MSIX_VECTORS;
-
-		/* Try once more with adjusted numbers */
-		/* If this fails, fall back to INTx */
-		ret = pci_enable_msix(bnad->pcidev, bnad->msix_table,
-				      bnad->msix_num);
-		if (ret)
-			goto intx_mode;
-
-	} else if (ret < 0)
-		goto intx_mode;
-	return;
-
-intx_mode:
-
-	kfree(bnad->msix_table);
-	bnad->msix_table = NULL;
-	bnad->msix_num = 0;
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bnad->cfg_flags &= ~BNAD_CF_MSIX;
-	bnad_q_num_init(bnad);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-}
-
-static void
-bnad_disable_msix(struct bnad *bnad)
-{
-	u32 cfg_flags;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	cfg_flags = bnad->cfg_flags;
-	if (bnad->cfg_flags & BNAD_CF_MSIX)
-		bnad->cfg_flags &= ~BNAD_CF_MSIX;
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	if (cfg_flags & BNAD_CF_MSIX) {
-		pci_disable_msix(bnad->pcidev);
-		kfree(bnad->msix_table);
-		bnad->msix_table = NULL;
-	}
-}
-
-/* Netdev entry points */
-static int
-bnad_open(struct net_device *netdev)
-{
-	int err;
-	struct bnad *bnad = netdev_priv(netdev);
-	struct bna_pause_config pause_config;
-	int mtu;
-	unsigned long flags;
-
-	mutex_lock(&bnad->conf_mutex);
-
-	/* Tx */
-	err = bnad_setup_tx(bnad, 0);
-	if (err)
-		goto err_return;
-
-	/* Rx */
-	err = bnad_setup_rx(bnad, 0);
-	if (err)
-		goto cleanup_tx;
-
-	/* Port */
-	pause_config.tx_pause = 0;
-	pause_config.rx_pause = 0;
-
-	mtu = ETH_HLEN + bnad->netdev->mtu + ETH_FCS_LEN;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_port_mtu_set(&bnad->bna.port, mtu, NULL);
-	bna_port_pause_config(&bnad->bna.port, &pause_config, NULL);
-	bna_port_enable(&bnad->bna.port);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	/* Enable broadcast */
-	bnad_enable_default_bcast(bnad);
-
-	/* Restore VLANs, if any */
-	bnad_restore_vlans(bnad, 0);
-
-	/* Set the UCAST address */
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bnad_mac_addr_set_locked(bnad, netdev->dev_addr);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	/* Start the stats timer */
-	bnad_stats_timer_start(bnad);
-
-	mutex_unlock(&bnad->conf_mutex);
-
-	return 0;
-
-cleanup_tx:
-	bnad_cleanup_tx(bnad, 0);
-
-err_return:
-	mutex_unlock(&bnad->conf_mutex);
-	return err;
-}
-
-static int
-bnad_stop(struct net_device *netdev)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-	unsigned long flags;
-
-	mutex_lock(&bnad->conf_mutex);
-
-	/* Stop the stats timer */
-	bnad_stats_timer_stop(bnad);
-
-	init_completion(&bnad->bnad_completions.port_comp);
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_port_disable(&bnad->bna.port, BNA_HARD_CLEANUP,
-			bnad_cb_port_disabled);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	wait_for_completion(&bnad->bnad_completions.port_comp);
-
-	bnad_cleanup_tx(bnad, 0);
-	bnad_cleanup_rx(bnad, 0);
-
-	/* Synchronize mailbox IRQ */
-	bnad_mbox_irq_sync(bnad);
-
-	mutex_unlock(&bnad->conf_mutex);
-
-	return 0;
-}
-
-/* TX */
-/*
- * bnad_start_xmit : Netdev entry point for Transmit
- *		     Called under lock held by net_device
- */
-static netdev_tx_t
-bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-
-	u16		txq_prod, vlan_tag = 0;
-	u32		unmap_prod, wis, wis_used, wi_range;
-	u32		vectors, vect_id, i, acked;
-	u32		tx_id;
-	int			err;
-
-	struct bnad_tx_info *tx_info;
-	struct bna_tcb *tcb;
-	struct bnad_unmap_q *unmap_q;
-	dma_addr_t		dma_addr;
-	struct bna_txq_entry *txqent;
-	bna_txq_wi_ctrl_flag_t	flags;
-
-	if (unlikely
-	    (skb->len <= ETH_HLEN || skb->len > BFI_TX_MAX_DATA_PER_PKT)) {
-		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-
-	tx_id = 0;
-
-	tx_info = &bnad->tx_info[tx_id];
-	tcb = tx_info->tcb[tx_id];
-	unmap_q = tcb->unmap_q;
-
-	/*
-	 * Takes care of the Tx that is scheduled between clearing the flag
-	 * and the netif_stop_queue() call.
-	 */
-	if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))) {
-		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-
-	vectors = 1 + skb_shinfo(skb)->nr_frags;
-	if (vectors > BFI_TX_MAX_VECTORS_PER_PKT) {
-		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-	wis = BNA_TXQ_WI_NEEDED(vectors);	/* 4 vectors per work item */
-	acked = 0;
-	if (unlikely
-	    (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
-	     vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
-		if ((u16) (*tcb->hw_consumer_index) !=
-		    tcb->consumer_index &&
-		    !test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) {
-			acked = bnad_free_txbufs(bnad, tcb);
-			if (likely(test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)))
-				bna_ib_ack(tcb->i_dbell, acked);
-			smp_mb__before_clear_bit();
-			clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
-		} else {
-			netif_stop_queue(netdev);
-			BNAD_UPDATE_CTR(bnad, netif_queue_stop);
-		}
-
-		smp_mb();
-		/*
-		 * Check again to deal with race condition between
-		 * netif_stop_queue here, and netif_wake_queue in
-		 * interrupt handler which is not inside netif tx lock.
-		 */
-		if (likely
-		    (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
-		     vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
-			BNAD_UPDATE_CTR(bnad, netif_queue_stop);
-			return NETDEV_TX_BUSY;
-		} else {
-			netif_wake_queue(netdev);
-			BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
-		}
-	}
-
-	unmap_prod = unmap_q->producer_index;
-	wis_used = 1;
-	vect_id = 0;
-	flags = 0;
-
-	txq_prod = tcb->producer_index;
-	BNA_TXQ_QPGE_PTR_GET(txq_prod, tcb->sw_qpt, txqent, wi_range);
-	BUG_ON(!(wi_range <= tcb->q_depth));
-	txqent->hdr.wi.reserved = 0;
-	txqent->hdr.wi.num_vectors = vectors;
-	txqent->hdr.wi.opcode =
-		htons((skb_is_gso(skb) ? BNA_TXQ_WI_SEND_LSO :
-		       BNA_TXQ_WI_SEND));
-
-	if (vlan_tx_tag_present(skb)) {
-		vlan_tag = (u16) vlan_tx_tag_get(skb);
-		flags |= (BNA_TXQ_WI_CF_INS_PRIO | BNA_TXQ_WI_CF_INS_VLAN);
-	}
-	if (test_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags)) {
-		vlan_tag =
-			(tcb->priority & 0x7) << 13 | (vlan_tag & 0x1fff);
-		flags |= (BNA_TXQ_WI_CF_INS_PRIO | BNA_TXQ_WI_CF_INS_VLAN);
-	}
-
-	txqent->hdr.wi.vlan_tag = htons(vlan_tag);
-
-	if (skb_is_gso(skb)) {
-		err = bnad_tso_prepare(bnad, skb);
-		if (err) {
-			dev_kfree_skb(skb);
-			return NETDEV_TX_OK;
-		}
-		txqent->hdr.wi.lso_mss = htons(skb_is_gso(skb));
-		flags |= (BNA_TXQ_WI_CF_IP_CKSUM | BNA_TXQ_WI_CF_TCP_CKSUM);
-		txqent->hdr.wi.l4_hdr_size_n_offset =
-			htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
-			      (tcp_hdrlen(skb) >> 2,
-			       skb_transport_offset(skb)));
-	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		u8 proto = 0;
-
-		txqent->hdr.wi.lso_mss = 0;
-
-		if (skb->protocol == htons(ETH_P_IP))
-			proto = ip_hdr(skb)->protocol;
-		else if (skb->protocol == htons(ETH_P_IPV6)) {
-			/* nexthdr may not be TCP immediately. */
-			proto = ipv6_hdr(skb)->nexthdr;
-		}
-		if (proto == IPPROTO_TCP) {
-			flags |= BNA_TXQ_WI_CF_TCP_CKSUM;
-			txqent->hdr.wi.l4_hdr_size_n_offset =
-				htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
-				      (0, skb_transport_offset(skb)));
-
-			BNAD_UPDATE_CTR(bnad, tcpcsum_offload);
-
-			BUG_ON(!(skb_headlen(skb) >=
-				skb_transport_offset(skb) + tcp_hdrlen(skb)));
-
-		} else if (proto == IPPROTO_UDP) {
-			flags |= BNA_TXQ_WI_CF_UDP_CKSUM;
-			txqent->hdr.wi.l4_hdr_size_n_offset =
-				htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
-				      (0, skb_transport_offset(skb)));
-
-			BNAD_UPDATE_CTR(bnad, udpcsum_offload);
-
-			BUG_ON(!(skb_headlen(skb) >=
-				   skb_transport_offset(skb) +
-				   sizeof(struct udphdr)));
-		} else {
-			err = skb_checksum_help(skb);
-			BNAD_UPDATE_CTR(bnad, csum_help);
-			if (err) {
-				dev_kfree_skb(skb);
-				BNAD_UPDATE_CTR(bnad, csum_help_err);
-				return NETDEV_TX_OK;
-			}
-		}
-	} else {
-		txqent->hdr.wi.lso_mss = 0;
-		txqent->hdr.wi.l4_hdr_size_n_offset = 0;
-	}
-
-	txqent->hdr.wi.flags = htons(flags);
-
-	txqent->hdr.wi.frame_length = htonl(skb->len);
-
-	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 = 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);
-	BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
-
-	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-		struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
-		u32		size = frag->size;
-
-		if (++vect_id == BFI_TX_MAX_VECTORS_PER_WI) {
-			vect_id = 0;
-			if (--wi_range)
-				txqent++;
-			else {
-				BNA_QE_INDX_ADD(txq_prod, wis_used,
-						tcb->q_depth);
-				wis_used = 0;
-				BNA_TXQ_QPGE_PTR_GET(txq_prod, tcb->sw_qpt,
-						     txqent, wi_range);
-				BUG_ON(!(wi_range <= tcb->q_depth));
-			}
-			wis_used++;
-			txqent->hdr.wi_ext.opcode = htons(BNA_TXQ_WI_EXTENSION);
-		}
-
-		BUG_ON(!(size <= BFI_TX_MAX_DATA_PER_VECTOR));
-		txqent->vector[vect_id].length = htons(size);
-		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);
-	}
-
-	unmap_q->producer_index = unmap_prod;
-	BNA_QE_INDX_ADD(txq_prod, wis_used, tcb->q_depth);
-	tcb->producer_index = txq_prod;
-
-	smp_mb();
-
-	if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)))
-		return NETDEV_TX_OK;
-
-	bna_txq_prod_indx_doorbell(tcb);
-
-	if ((u16) (*tcb->hw_consumer_index) != tcb->consumer_index)
-		tasklet_schedule(&bnad->tx_free_tasklet);
-
-	return NETDEV_TX_OK;
-}
-
-/*
- * Used spin_lock to synchronize reading of stats structures, which
- * is written by BNA under the same lock.
- */
-static struct rtnl_link_stats64 *
-bnad_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-
-	bnad_netdev_qstats_fill(bnad, stats);
-	bnad_netdev_hwstats_fill(bnad, stats);
-
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	return stats;
-}
-
-static void
-bnad_set_rx_mode(struct net_device *netdev)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-	u32	new_mask, valid_mask;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-
-	new_mask = valid_mask = 0;
-
-	if (netdev->flags & IFF_PROMISC) {
-		if (!(bnad->cfg_flags & BNAD_CF_PROMISC)) {
-			new_mask = BNAD_RXMODE_PROMISC_DEFAULT;
-			valid_mask = BNAD_RXMODE_PROMISC_DEFAULT;
-			bnad->cfg_flags |= BNAD_CF_PROMISC;
-		}
-	} else {
-		if (bnad->cfg_flags & BNAD_CF_PROMISC) {
-			new_mask = ~BNAD_RXMODE_PROMISC_DEFAULT;
-			valid_mask = BNAD_RXMODE_PROMISC_DEFAULT;
-			bnad->cfg_flags &= ~BNAD_CF_PROMISC;
-		}
-	}
-
-	if (netdev->flags & IFF_ALLMULTI) {
-		if (!(bnad->cfg_flags & BNAD_CF_ALLMULTI)) {
-			new_mask |= BNA_RXMODE_ALLMULTI;
-			valid_mask |= BNA_RXMODE_ALLMULTI;
-			bnad->cfg_flags |= BNAD_CF_ALLMULTI;
-		}
-	} else {
-		if (bnad->cfg_flags & BNAD_CF_ALLMULTI) {
-			new_mask &= ~BNA_RXMODE_ALLMULTI;
-			valid_mask |= BNA_RXMODE_ALLMULTI;
-			bnad->cfg_flags &= ~BNAD_CF_ALLMULTI;
-		}
-	}
-
-	bna_rx_mode_set(bnad->rx_info[0].rx, new_mask, valid_mask, NULL);
-
-	if (!netdev_mc_empty(netdev)) {
-		u8 *mcaddr_list;
-		int mc_count = netdev_mc_count(netdev);
-
-		/* Index 0 holds the broadcast address */
-		mcaddr_list =
-			kzalloc((mc_count + 1) * ETH_ALEN,
-				GFP_ATOMIC);
-		if (!mcaddr_list)
-			goto unlock;
-
-		memcpy(&mcaddr_list[0], &bnad_bcast_addr[0], ETH_ALEN);
-
-		/* Copy rest of the MC addresses */
-		bnad_netdev_mc_list_get(netdev, mcaddr_list);
-
-		bna_rx_mcast_listset(bnad->rx_info[0].rx, mc_count + 1,
-					mcaddr_list, NULL);
-
-		/* Should we enable BNAD_CF_ALLMULTI for err != 0 ? */
-		kfree(mcaddr_list);
-	}
-unlock:
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-}
-
-/*
- * bna_lock is used to sync writes to netdev->addr
- * conf_lock cannot be used since this call may be made
- * in a non-blocking context.
- */
-static int
-bnad_set_mac_address(struct net_device *netdev, void *mac_addr)
-{
-	int err;
-	struct bnad *bnad = netdev_priv(netdev);
-	struct sockaddr *sa = (struct sockaddr *)mac_addr;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-
-	err = bnad_mac_addr_set_locked(bnad, sa->sa_data);
-
-	if (!err)
-		memcpy(netdev->dev_addr, sa->sa_data, netdev->addr_len);
-
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	return err;
-}
-
-static int
-bnad_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	int mtu, err = 0;
-	unsigned long flags;
-
-	struct bnad *bnad = netdev_priv(netdev);
-
-	if (new_mtu + ETH_HLEN < ETH_ZLEN || new_mtu > BNAD_JUMBO_MTU)
-		return -EINVAL;
-
-	mutex_lock(&bnad->conf_mutex);
-
-	netdev->mtu = new_mtu;
-
-	mtu = ETH_HLEN + new_mtu + ETH_FCS_LEN;
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_port_mtu_set(&bnad->bna.port, mtu, NULL);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	mutex_unlock(&bnad->conf_mutex);
-	return err;
-}
-
-static void
-bnad_vlan_rx_add_vid(struct net_device *netdev,
-				 unsigned short vid)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-	unsigned long flags;
-
-	if (!bnad->rx_info[0].rx)
-		return;
-
-	mutex_lock(&bnad->conf_mutex);
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_rx_vlan_add(bnad->rx_info[0].rx, vid);
-	set_bit(vid, bnad->active_vlans);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	mutex_unlock(&bnad->conf_mutex);
-}
-
-static void
-bnad_vlan_rx_kill_vid(struct net_device *netdev,
-				  unsigned short vid)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-	unsigned long flags;
-
-	if (!bnad->rx_info[0].rx)
-		return;
-
-	mutex_lock(&bnad->conf_mutex);
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	clear_bit(vid, bnad->active_vlans);
-	bna_rx_vlan_del(bnad->rx_info[0].rx, vid);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	mutex_unlock(&bnad->conf_mutex);
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void
-bnad_netpoll(struct net_device *netdev)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-	struct bnad_rx_info *rx_info;
-	struct bnad_rx_ctrl *rx_ctrl;
-	u32 curr_mask;
-	int i, j;
-
-	if (!(bnad->cfg_flags & BNAD_CF_MSIX)) {
-		bna_intx_disable(&bnad->bna, curr_mask);
-		bnad_isr(bnad->pcidev->irq, netdev);
-		bna_intx_enable(&bnad->bna, curr_mask);
-	} else {
-		for (i = 0; i < bnad->num_rx; i++) {
-			rx_info = &bnad->rx_info[i];
-			if (!rx_info->rx)
-				continue;
-			for (j = 0; j < bnad->num_rxp_per_rx; j++) {
-				rx_ctrl = &rx_info->rx_ctrl[j];
-				if (rx_ctrl->ccb) {
-					bnad_disable_rx_irq(bnad,
-							    rx_ctrl->ccb);
-					bnad_netif_rx_schedule_poll(bnad,
-							    rx_ctrl->ccb);
-				}
-			}
-		}
-	}
-}
-#endif
-
-static const struct net_device_ops bnad_netdev_ops = {
-	.ndo_open		= bnad_open,
-	.ndo_stop		= bnad_stop,
-	.ndo_start_xmit		= bnad_start_xmit,
-	.ndo_get_stats64		= bnad_get_stats64,
-	.ndo_set_rx_mode	= bnad_set_rx_mode,
-	.ndo_set_multicast_list = bnad_set_rx_mode,
-	.ndo_validate_addr      = eth_validate_addr,
-	.ndo_set_mac_address    = bnad_set_mac_address,
-	.ndo_change_mtu		= bnad_change_mtu,
-	.ndo_vlan_rx_add_vid    = bnad_vlan_rx_add_vid,
-	.ndo_vlan_rx_kill_vid   = bnad_vlan_rx_kill_vid,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller    = bnad_netpoll
-#endif
-};
-
-static void
-bnad_netdev_init(struct bnad *bnad, bool using_dac)
-{
-	struct net_device *netdev = bnad->netdev;
-
-	netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
-		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_HW_VLAN_TX;
-
-	netdev->vlan_features = NETIF_F_SG | NETIF_F_HIGHDMA |
-		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		NETIF_F_TSO | NETIF_F_TSO6;
-
-	netdev->features |= netdev->hw_features |
-		NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
-
-	if (using_dac)
-		netdev->features |= NETIF_F_HIGHDMA;
-
-	netdev->mem_start = bnad->mmio_start;
-	netdev->mem_end = bnad->mmio_start + bnad->mmio_len - 1;
-
-	netdev->netdev_ops = &bnad_netdev_ops;
-	bnad_set_ethtool_ops(netdev);
-}
-
-/*
- * 1. Initialize the bnad structure
- * 2. Setup netdev pointer in pci_dev
- * 3. Initialze Tx free tasklet
- * 4. Initialize no. of TxQ & CQs & MSIX vectors
- */
-static int
-bnad_init(struct bnad *bnad,
-	  struct pci_dev *pdev, struct net_device *netdev)
-{
-	unsigned long flags;
-
-	SET_NETDEV_DEV(netdev, &pdev->dev);
-	pci_set_drvdata(pdev, netdev);
-
-	bnad->netdev = netdev;
-	bnad->pcidev = pdev;
-	bnad->mmio_start = pci_resource_start(pdev, 0);
-	bnad->mmio_len = pci_resource_len(pdev, 0);
-	bnad->bar0 = ioremap_nocache(bnad->mmio_start, bnad->mmio_len);
-	if (!bnad->bar0) {
-		dev_err(&pdev->dev, "ioremap for bar0 failed\n");
-		pci_set_drvdata(pdev, NULL);
-		return -ENOMEM;
-	}
-	pr_info("bar0 mapped to %p, len %llu\n", bnad->bar0,
-	       (unsigned long long) bnad->mmio_len);
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	if (!bnad_msix_disable)
-		bnad->cfg_flags = BNAD_CF_MSIX;
-
-	bnad->cfg_flags |= BNAD_CF_DIM_ENABLED;
-
-	bnad_q_num_init(bnad);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	bnad->msix_num = (bnad->num_tx * bnad->num_txq_per_tx) +
-		(bnad->num_rx * bnad->num_rxp_per_rx) +
-			 BNAD_MAILBOX_MSIX_VECTORS;
-
-	bnad->txq_depth = BNAD_TXQ_DEPTH;
-	bnad->rxq_depth = BNAD_RXQ_DEPTH;
-
-	bnad->tx_coalescing_timeo = BFI_TX_COALESCING_TIMEO;
-	bnad->rx_coalescing_timeo = BFI_RX_COALESCING_TIMEO;
-
-	tasklet_init(&bnad->tx_free_tasklet, bnad_tx_free_tasklet,
-		     (unsigned long)bnad);
-
-	return 0;
-}
-
-/*
- * Must be called after bnad_pci_uninit()
- * so that iounmap() and pci_set_drvdata(NULL)
- * happens only after PCI uninitialization.
- */
-static void
-bnad_uninit(struct bnad *bnad)
-{
-	if (bnad->bar0)
-		iounmap(bnad->bar0);
-	pci_set_drvdata(bnad->pcidev, NULL);
-}
-
-/*
- * Initialize locks
-	a) Per device mutes used for serializing configuration
-	   changes from OS interface
-	b) spin lock used to protect bna state machine
- */
-static void
-bnad_lock_init(struct bnad *bnad)
-{
-	spin_lock_init(&bnad->bna_lock);
-	mutex_init(&bnad->conf_mutex);
-}
-
-static void
-bnad_lock_uninit(struct bnad *bnad)
-{
-	mutex_destroy(&bnad->conf_mutex);
-}
-
-/* PCI Initialization */
-static int
-bnad_pci_init(struct bnad *bnad,
-	      struct pci_dev *pdev, bool *using_dac)
-{
-	int err;
-
-	err = pci_enable_device(pdev);
-	if (err)
-		return err;
-	err = pci_request_regions(pdev, BNAD_NAME);
-	if (err)
-		goto disable_device;
-	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 = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
-		if (err) {
-			err = dma_set_coherent_mask(&pdev->dev,
-						    DMA_BIT_MASK(32));
-			if (err)
-				goto release_regions;
-		}
-		*using_dac = 0;
-	}
-	pci_set_master(pdev);
-	return 0;
-
-release_regions:
-	pci_release_regions(pdev);
-disable_device:
-	pci_disable_device(pdev);
-
-	return err;
-}
-
-static void
-bnad_pci_uninit(struct pci_dev *pdev)
-{
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-}
-
-static int __devinit
-bnad_pci_probe(struct pci_dev *pdev,
-		const struct pci_device_id *pcidev_id)
-{
-	bool	using_dac = false;
-	int	err;
-	struct bnad *bnad;
-	struct bna *bna;
-	struct net_device *netdev;
-	struct bfa_pcidev pcidev_info;
-	unsigned long flags;
-
-	pr_info("bnad_pci_probe : (0x%p, 0x%p) PCI Func : (%d)\n",
-	       pdev, pcidev_id, PCI_FUNC(pdev->devfn));
-
-	mutex_lock(&bnad_fwimg_mutex);
-	if (!cna_get_firmware_buf(pdev)) {
-		mutex_unlock(&bnad_fwimg_mutex);
-		pr_warn("Failed to load Firmware Image!\n");
-		return -ENODEV;
-	}
-	mutex_unlock(&bnad_fwimg_mutex);
-
-	/*
-	 * Allocates sizeof(struct net_device + struct bnad)
-	 * bnad = netdev->priv
-	 */
-	netdev = alloc_etherdev(sizeof(struct bnad));
-	if (!netdev) {
-		dev_err(&pdev->dev, "alloc_etherdev failed\n");
-		err = -ENOMEM;
-		return err;
-	}
-	bnad = netdev_priv(netdev);
-
-	/*
-	 * PCI initialization
-	 *	Output : using_dac = 1 for 64 bit DMA
-	 *			   = 0 for 32 bit DMA
-	 */
-	err = bnad_pci_init(bnad, pdev, &using_dac);
-	if (err)
-		goto free_netdev;
-
-	bnad_lock_init(bnad);
-	/*
-	 * Initialize bnad structure
-	 * Setup relation between pci_dev & netdev
-	 * Init Tx free tasklet
-	 */
-	err = bnad_init(bnad, pdev, netdev);
-	if (err)
-		goto pci_uninit;
-	/* Initialize netdev structure, set up ethtool ops */
-	bnad_netdev_init(bnad, using_dac);
-
-	/* Set link to down state */
-	netif_carrier_off(netdev);
-
-	bnad_enable_msix(bnad);
-
-	/* Get resource requirement form bna */
-	bna_res_req(&bnad->res_info[0]);
-
-	/* Allocate resources from bna */
-	err = bnad_res_alloc(bnad);
-	if (err)
-		goto free_netdev;
-
-	bna = &bnad->bna;
-
-	/* Setup pcidev_info for bna_init() */
-	pcidev_info.pci_slot = PCI_SLOT(bnad->pcidev->devfn);
-	pcidev_info.pci_func = PCI_FUNC(bnad->pcidev->devfn);
-	pcidev_info.device_id = bnad->pcidev->device;
-	pcidev_info.pci_bar_kva = bnad->bar0;
-
-	mutex_lock(&bnad->conf_mutex);
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_init(bna, bnad, &pcidev_info, &bnad->res_info[0]);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	bnad->stats.bna_stats = &bna->stats;
-
-	/* Set up timers */
-	setup_timer(&bnad->bna.device.ioc.ioc_timer, bnad_ioc_timeout,
-				((unsigned long)bnad));
-	setup_timer(&bnad->bna.device.ioc.hb_timer, bnad_ioc_hb_check,
-				((unsigned long)bnad));
-	setup_timer(&bnad->bna.device.ioc.iocpf_timer, bnad_iocpf_timeout,
-				((unsigned long)bnad));
-	setup_timer(&bnad->bna.device.ioc.sem_timer, bnad_iocpf_sem_timeout,
-				((unsigned long)bnad));
-
-	/* Now start the timer before calling IOC */
-	mod_timer(&bnad->bna.device.ioc.iocpf_timer,
-		  jiffies + msecs_to_jiffies(BNA_IOC_TIMER_FREQ));
-
-	/*
-	 * Start the chip
-	 * Don't care even if err != 0, bna state machine will
-	 * deal with it
-	 */
-	err = bnad_device_enable(bnad);
-
-	/* Get the burnt-in mac */
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_port_mac_get(&bna->port, &bnad->perm_addr);
-	bnad_set_netdev_perm_addr(bnad);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	mutex_unlock(&bnad->conf_mutex);
-
-	/* Finally, reguister with net_device layer */
-	err = register_netdev(netdev);
-	if (err) {
-		pr_err("BNA : Registering with netdev failed\n");
-		goto disable_device;
-	}
-
-	return 0;
-
-disable_device:
-	mutex_lock(&bnad->conf_mutex);
-	bnad_device_disable(bnad);
-	del_timer_sync(&bnad->bna.device.ioc.ioc_timer);
-	del_timer_sync(&bnad->bna.device.ioc.sem_timer);
-	del_timer_sync(&bnad->bna.device.ioc.hb_timer);
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_uninit(bna);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	mutex_unlock(&bnad->conf_mutex);
-
-	bnad_res_free(bnad);
-	bnad_disable_msix(bnad);
-pci_uninit:
-	bnad_pci_uninit(pdev);
-	bnad_lock_uninit(bnad);
-	bnad_uninit(bnad);
-free_netdev:
-	free_netdev(netdev);
-	return err;
-}
-
-static void __devexit
-bnad_pci_remove(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct bnad *bnad;
-	struct bna *bna;
-	unsigned long flags;
-
-	if (!netdev)
-		return;
-
-	pr_info("%s bnad_pci_remove\n", netdev->name);
-	bnad = netdev_priv(netdev);
-	bna = &bnad->bna;
-
-	unregister_netdev(netdev);
-
-	mutex_lock(&bnad->conf_mutex);
-	bnad_device_disable(bnad);
-	del_timer_sync(&bnad->bna.device.ioc.ioc_timer);
-	del_timer_sync(&bnad->bna.device.ioc.sem_timer);
-	del_timer_sync(&bnad->bna.device.ioc.hb_timer);
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bna_uninit(bna);
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	mutex_unlock(&bnad->conf_mutex);
-
-	bnad_res_free(bnad);
-	bnad_disable_msix(bnad);
-	bnad_pci_uninit(pdev);
-	bnad_lock_uninit(bnad);
-	bnad_uninit(bnad);
-	free_netdev(netdev);
-}
-
-static DEFINE_PCI_DEVICE_TABLE(bnad_pci_id_table) = {
-	{
-		PCI_DEVICE(PCI_VENDOR_ID_BROCADE,
-			PCI_DEVICE_ID_BROCADE_CT),
-		.class = PCI_CLASS_NETWORK_ETHERNET << 8,
-		.class_mask =  0xffff00
-	}, {0,  }
-};
-
-MODULE_DEVICE_TABLE(pci, bnad_pci_id_table);
-
-static struct pci_driver bnad_pci_driver = {
-	.name = BNAD_NAME,
-	.id_table = bnad_pci_id_table,
-	.probe = bnad_pci_probe,
-	.remove = __devexit_p(bnad_pci_remove),
-};
-
-static int __init
-bnad_module_init(void)
-{
-	int err;
-
-	pr_info("Brocade 10G Ethernet driver - version: %s\n",
-			BNAD_VERSION);
-
-	bfa_nw_ioc_auto_recover(bnad_ioc_auto_recover);
-
-	err = pci_register_driver(&bnad_pci_driver);
-	if (err < 0) {
-		pr_err("bna : PCI registration failed in module init "
-		       "(%d)\n", err);
-		return err;
-	}
-
-	return 0;
-}
-
-static void __exit
-bnad_module_exit(void)
-{
-	pci_unregister_driver(&bnad_pci_driver);
-
-	if (bfi_fw)
-		release_firmware(bfi_fw);
-}
-
-module_init(bnad_module_init);
-module_exit(bnad_module_exit);
-
-MODULE_AUTHOR("Brocade");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Brocade 10G PCIe Ethernet driver");
-MODULE_VERSION(BNAD_VERSION);
-/*(DEBLOBBED)*/
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bnad_ethtool.c linux-libre-3.2-gnu/drivers/net/bna/bnad_ethtool.c
--- linux-libre-3.1-gnu/drivers/net/bna/bnad_ethtool.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bnad_ethtool.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1214 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-#include "cna.h"
-
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/ethtool.h>
-#include <linux/rtnetlink.h>
-
-#include "bna.h"
-
-#include "bnad.h"
-
-#define BNAD_NUM_TXF_COUNTERS 12
-#define BNAD_NUM_RXF_COUNTERS 10
-#define BNAD_NUM_CQ_COUNTERS 3
-#define BNAD_NUM_RXQ_COUNTERS 6
-#define BNAD_NUM_TXQ_COUNTERS 5
-
-#define BNAD_ETHTOOL_STATS_NUM						\
-	(sizeof(struct rtnl_link_stats64) / sizeof(u64) +	\
-	sizeof(struct bnad_drv_stats) / sizeof(u64) +		\
-	offsetof(struct bfi_ll_stats, rxf_stats[0]) / sizeof(u64))
-
-static char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
-	"rx_packets",
-	"tx_packets",
-	"rx_bytes",
-	"tx_bytes",
-	"rx_errors",
-	"tx_errors",
-	"rx_dropped",
-	"tx_dropped",
-	"multicast",
-	"collisions",
-
-	"rx_length_errors",
-	"rx_over_errors",
-	"rx_crc_errors",
-	"rx_frame_errors",
-	"rx_fifo_errors",
-	"rx_missed_errors",
-
-	"tx_aborted_errors",
-	"tx_carrier_errors",
-	"tx_fifo_errors",
-	"tx_heartbeat_errors",
-	"tx_window_errors",
-
-	"rx_compressed",
-	"tx_compressed",
-
-	"netif_queue_stop",
-	"netif_queue_wakeup",
-	"netif_queue_stopped",
-	"tso4",
-	"tso6",
-	"tso_err",
-	"tcpcsum_offload",
-	"udpcsum_offload",
-	"csum_help",
-	"csum_help_err",
-	"hw_stats_updates",
-	"netif_rx_schedule",
-	"netif_rx_complete",
-	"netif_rx_dropped",
-
-	"link_toggle",
-	"cee_up",
-
-	"rxp_info_alloc_failed",
-	"mbox_intr_disabled",
-	"mbox_intr_enabled",
-	"tx_unmap_q_alloc_failed",
-	"rx_unmap_q_alloc_failed",
-	"rxbuf_alloc_failed",
-
-	"mac_frame_64",
-	"mac_frame_65_127",
-	"mac_frame_128_255",
-	"mac_frame_256_511",
-	"mac_frame_512_1023",
-	"mac_frame_1024_1518",
-	"mac_frame_1518_1522",
-	"mac_rx_bytes",
-	"mac_rx_packets",
-	"mac_rx_fcs_error",
-	"mac_rx_multicast",
-	"mac_rx_broadcast",
-	"mac_rx_control_frames",
-	"mac_rx_pause",
-	"mac_rx_unknown_opcode",
-	"mac_rx_alignment_error",
-	"mac_rx_frame_length_error",
-	"mac_rx_code_error",
-	"mac_rx_carrier_sense_error",
-	"mac_rx_undersize",
-	"mac_rx_oversize",
-	"mac_rx_fragments",
-	"mac_rx_jabber",
-	"mac_rx_drop",
-
-	"mac_tx_bytes",
-	"mac_tx_packets",
-	"mac_tx_multicast",
-	"mac_tx_broadcast",
-	"mac_tx_pause",
-	"mac_tx_deferral",
-	"mac_tx_excessive_deferral",
-	"mac_tx_single_collision",
-	"mac_tx_muliple_collision",
-	"mac_tx_late_collision",
-	"mac_tx_excessive_collision",
-	"mac_tx_total_collision",
-	"mac_tx_pause_honored",
-	"mac_tx_drop",
-	"mac_tx_jabber",
-	"mac_tx_fcs_error",
-	"mac_tx_control_frame",
-	"mac_tx_oversize",
-	"mac_tx_undersize",
-	"mac_tx_fragments",
-
-	"bpc_tx_pause_0",
-	"bpc_tx_pause_1",
-	"bpc_tx_pause_2",
-	"bpc_tx_pause_3",
-	"bpc_tx_pause_4",
-	"bpc_tx_pause_5",
-	"bpc_tx_pause_6",
-	"bpc_tx_pause_7",
-	"bpc_tx_zero_pause_0",
-	"bpc_tx_zero_pause_1",
-	"bpc_tx_zero_pause_2",
-	"bpc_tx_zero_pause_3",
-	"bpc_tx_zero_pause_4",
-	"bpc_tx_zero_pause_5",
-	"bpc_tx_zero_pause_6",
-	"bpc_tx_zero_pause_7",
-	"bpc_tx_first_pause_0",
-	"bpc_tx_first_pause_1",
-	"bpc_tx_first_pause_2",
-	"bpc_tx_first_pause_3",
-	"bpc_tx_first_pause_4",
-	"bpc_tx_first_pause_5",
-	"bpc_tx_first_pause_6",
-	"bpc_tx_first_pause_7",
-
-	"bpc_rx_pause_0",
-	"bpc_rx_pause_1",
-	"bpc_rx_pause_2",
-	"bpc_rx_pause_3",
-	"bpc_rx_pause_4",
-	"bpc_rx_pause_5",
-	"bpc_rx_pause_6",
-	"bpc_rx_pause_7",
-	"bpc_rx_zero_pause_0",
-	"bpc_rx_zero_pause_1",
-	"bpc_rx_zero_pause_2",
-	"bpc_rx_zero_pause_3",
-	"bpc_rx_zero_pause_4",
-	"bpc_rx_zero_pause_5",
-	"bpc_rx_zero_pause_6",
-	"bpc_rx_zero_pause_7",
-	"bpc_rx_first_pause_0",
-	"bpc_rx_first_pause_1",
-	"bpc_rx_first_pause_2",
-	"bpc_rx_first_pause_3",
-	"bpc_rx_first_pause_4",
-	"bpc_rx_first_pause_5",
-	"bpc_rx_first_pause_6",
-	"bpc_rx_first_pause_7",
-
-	"rad_rx_frames",
-	"rad_rx_octets",
-	"rad_rx_vlan_frames",
-	"rad_rx_ucast",
-	"rad_rx_ucast_octets",
-	"rad_rx_ucast_vlan",
-	"rad_rx_mcast",
-	"rad_rx_mcast_octets",
-	"rad_rx_mcast_vlan",
-	"rad_rx_bcast",
-	"rad_rx_bcast_octets",
-	"rad_rx_bcast_vlan",
-	"rad_rx_drops",
-
-	"fc_rx_ucast_octets",
-	"fc_rx_ucast",
-	"fc_rx_ucast_vlan",
-	"fc_rx_mcast_octets",
-	"fc_rx_mcast",
-	"fc_rx_mcast_vlan",
-	"fc_rx_bcast_octets",
-	"fc_rx_bcast",
-	"fc_rx_bcast_vlan",
-
-	"fc_tx_ucast_octets",
-	"fc_tx_ucast",
-	"fc_tx_ucast_vlan",
-	"fc_tx_mcast_octets",
-	"fc_tx_mcast",
-	"fc_tx_mcast_vlan",
-	"fc_tx_bcast_octets",
-	"fc_tx_bcast",
-	"fc_tx_bcast_vlan",
-	"fc_tx_parity_errors",
-	"fc_tx_timeout",
-	"fc_tx_fid_parity_errors",
-};
-
-static int
-bnad_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
-{
-	cmd->supported = SUPPORTED_10000baseT_Full;
-	cmd->advertising = ADVERTISED_10000baseT_Full;
-	cmd->autoneg = AUTONEG_DISABLE;
-	cmd->supported |= SUPPORTED_FIBRE;
-	cmd->advertising |= ADVERTISED_FIBRE;
-	cmd->port = PORT_FIBRE;
-	cmd->phy_address = 0;
-
-	if (netif_carrier_ok(netdev)) {
-		ethtool_cmd_speed_set(cmd, SPEED_10000);
-		cmd->duplex = DUPLEX_FULL;
-	} else {
-		ethtool_cmd_speed_set(cmd, -1);
-		cmd->duplex = -1;
-	}
-	cmd->transceiver = XCVR_EXTERNAL;
-	cmd->maxtxpkt = 0;
-	cmd->maxrxpkt = 0;
-
-	return 0;
-}
-
-static int
-bnad_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
-{
-	/* 10G full duplex setting supported only */
-	if (cmd->autoneg == AUTONEG_ENABLE)
-		return -EOPNOTSUPP; else {
-		if ((ethtool_cmd_speed(cmd) == SPEED_10000)
-		    && (cmd->duplex == DUPLEX_FULL))
-			return 0;
-	}
-
-	return -EOPNOTSUPP;
-}
-
-static void
-bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-	struct bfa_ioc_attr *ioc_attr;
-	unsigned long flags;
-
-	strcpy(drvinfo->driver, BNAD_NAME);
-	strcpy(drvinfo->version, BNAD_VERSION);
-
-	ioc_attr = kzalloc(sizeof(*ioc_attr), GFP_KERNEL);
-	if (ioc_attr) {
-		spin_lock_irqsave(&bnad->bna_lock, flags);
-		bfa_nw_ioc_get_attr(&bnad->bna.device.ioc, ioc_attr);
-		spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-		strncpy(drvinfo->fw_version, ioc_attr->adapter_attr.fw_ver,
-			sizeof(drvinfo->fw_version) - 1);
-		kfree(ioc_attr);
-	}
-
-	strncpy(drvinfo->bus_info, pci_name(bnad->pcidev), ETHTOOL_BUSINFO_LEN);
-}
-
-static int
-get_regs(struct bnad *bnad, u32 * regs)
-{
-	int num = 0, i;
-	u32 reg_addr;
-	unsigned long flags;
-
-#define BNAD_GET_REG(addr)					\
-do {								\
-	if (regs)						\
-		regs[num++] = readl(bnad->bar0 + (addr));	\
-	else							\
-		num++;						\
-} while (0)
-
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-
-	/* DMA Block Internal Registers */
-	BNAD_GET_REG(DMA_CTRL_REG0);
-	BNAD_GET_REG(DMA_CTRL_REG1);
-	BNAD_GET_REG(DMA_ERR_INT_STATUS);
-	BNAD_GET_REG(DMA_ERR_INT_ENABLE);
-	BNAD_GET_REG(DMA_ERR_INT_STATUS_SET);
-
-	/* APP Block Register Address Offset from BAR0 */
-	BNAD_GET_REG(HOSTFN0_INT_STATUS);
-	BNAD_GET_REG(HOSTFN0_INT_MASK);
-	BNAD_GET_REG(HOST_PAGE_NUM_FN0);
-	BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN0);
-	BNAD_GET_REG(FN0_PCIE_ERR_REG);
-	BNAD_GET_REG(FN0_ERR_TYPE_STATUS_REG);
-	BNAD_GET_REG(FN0_ERR_TYPE_MSK_STATUS_REG);
-
-	BNAD_GET_REG(HOSTFN1_INT_STATUS);
-	BNAD_GET_REG(HOSTFN1_INT_MASK);
-	BNAD_GET_REG(HOST_PAGE_NUM_FN1);
-	BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN1);
-	BNAD_GET_REG(FN1_PCIE_ERR_REG);
-	BNAD_GET_REG(FN1_ERR_TYPE_STATUS_REG);
-	BNAD_GET_REG(FN1_ERR_TYPE_MSK_STATUS_REG);
-
-	BNAD_GET_REG(PCIE_MISC_REG);
-
-	BNAD_GET_REG(HOST_SEM0_INFO_REG);
-	BNAD_GET_REG(HOST_SEM1_INFO_REG);
-	BNAD_GET_REG(HOST_SEM2_INFO_REG);
-	BNAD_GET_REG(HOST_SEM3_INFO_REG);
-
-	BNAD_GET_REG(TEMPSENSE_CNTL_REG);
-	BNAD_GET_REG(TEMPSENSE_STAT_REG);
-
-	BNAD_GET_REG(APP_LOCAL_ERR_STAT);
-	BNAD_GET_REG(APP_LOCAL_ERR_MSK);
-
-	BNAD_GET_REG(PCIE_LNK_ERR_STAT);
-	BNAD_GET_REG(PCIE_LNK_ERR_MSK);
-
-	BNAD_GET_REG(FCOE_FIP_ETH_TYPE);
-	BNAD_GET_REG(RESV_ETH_TYPE);
-
-	BNAD_GET_REG(HOSTFN2_INT_STATUS);
-	BNAD_GET_REG(HOSTFN2_INT_MASK);
-	BNAD_GET_REG(HOST_PAGE_NUM_FN2);
-	BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN2);
-	BNAD_GET_REG(FN2_PCIE_ERR_REG);
-	BNAD_GET_REG(FN2_ERR_TYPE_STATUS_REG);
-	BNAD_GET_REG(FN2_ERR_TYPE_MSK_STATUS_REG);
-
-	BNAD_GET_REG(HOSTFN3_INT_STATUS);
-	BNAD_GET_REG(HOSTFN3_INT_MASK);
-	BNAD_GET_REG(HOST_PAGE_NUM_FN3);
-	BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN3);
-	BNAD_GET_REG(FN3_PCIE_ERR_REG);
-	BNAD_GET_REG(FN3_ERR_TYPE_STATUS_REG);
-	BNAD_GET_REG(FN3_ERR_TYPE_MSK_STATUS_REG);
-
-	/* Host Command Status Registers */
-	reg_addr = HOST_CMDSTS0_CLR_REG;
-	for (i = 0; i < 16; i++) {
-		BNAD_GET_REG(reg_addr);
-		BNAD_GET_REG(reg_addr + 4);
-		BNAD_GET_REG(reg_addr + 8);
-		reg_addr += 0x10;
-	}
-
-	/* Function ID register */
-	BNAD_GET_REG(FNC_ID_REG);
-
-	/* Function personality register */
-	BNAD_GET_REG(FNC_PERS_REG);
-
-	/* Operation mode register */
-	BNAD_GET_REG(OP_MODE);
-
-	/* LPU0 Registers */
-	BNAD_GET_REG(LPU0_MBOX_CTL_REG);
-	BNAD_GET_REG(LPU0_MBOX_CMD_REG);
-	BNAD_GET_REG(LPU0_MBOX_LINK_0REG);
-	BNAD_GET_REG(LPU1_MBOX_LINK_0REG);
-	BNAD_GET_REG(LPU0_MBOX_STATUS_0REG);
-	BNAD_GET_REG(LPU1_MBOX_STATUS_0REG);
-	BNAD_GET_REG(LPU0_ERR_STATUS_REG);
-	BNAD_GET_REG(LPU0_ERR_SET_REG);
-
-	/* LPU1 Registers */
-	BNAD_GET_REG(LPU1_MBOX_CTL_REG);
-	BNAD_GET_REG(LPU1_MBOX_CMD_REG);
-	BNAD_GET_REG(LPU0_MBOX_LINK_1REG);
-	BNAD_GET_REG(LPU1_MBOX_LINK_1REG);
-	BNAD_GET_REG(LPU0_MBOX_STATUS_1REG);
-	BNAD_GET_REG(LPU1_MBOX_STATUS_1REG);
-	BNAD_GET_REG(LPU1_ERR_STATUS_REG);
-	BNAD_GET_REG(LPU1_ERR_SET_REG);
-
-	/* PSS Registers */
-	BNAD_GET_REG(PSS_CTL_REG);
-	BNAD_GET_REG(PSS_ERR_STATUS_REG);
-	BNAD_GET_REG(ERR_STATUS_SET);
-	BNAD_GET_REG(PSS_RAM_ERR_STATUS_REG);
-
-	/* Catapult CPQ Registers */
-	BNAD_GET_REG(HOSTFN0_LPU0_MBOX0_CMD_STAT);
-	BNAD_GET_REG(HOSTFN0_LPU1_MBOX0_CMD_STAT);
-	BNAD_GET_REG(LPU0_HOSTFN0_MBOX0_CMD_STAT);
-	BNAD_GET_REG(LPU1_HOSTFN0_MBOX0_CMD_STAT);
-
-	BNAD_GET_REG(HOSTFN0_LPU0_MBOX1_CMD_STAT);
-	BNAD_GET_REG(HOSTFN0_LPU1_MBOX1_CMD_STAT);
-	BNAD_GET_REG(LPU0_HOSTFN0_MBOX1_CMD_STAT);
-	BNAD_GET_REG(LPU1_HOSTFN0_MBOX1_CMD_STAT);
-
-	BNAD_GET_REG(HOSTFN1_LPU0_MBOX0_CMD_STAT);
-	BNAD_GET_REG(HOSTFN1_LPU1_MBOX0_CMD_STAT);
-	BNAD_GET_REG(LPU0_HOSTFN1_MBOX0_CMD_STAT);
-	BNAD_GET_REG(LPU1_HOSTFN1_MBOX0_CMD_STAT);
-
-	BNAD_GET_REG(HOSTFN1_LPU0_MBOX1_CMD_STAT);
-	BNAD_GET_REG(HOSTFN1_LPU1_MBOX1_CMD_STAT);
-	BNAD_GET_REG(LPU0_HOSTFN1_MBOX1_CMD_STAT);
-	BNAD_GET_REG(LPU1_HOSTFN1_MBOX1_CMD_STAT);
-
-	BNAD_GET_REG(HOSTFN2_LPU0_MBOX0_CMD_STAT);
-	BNAD_GET_REG(HOSTFN2_LPU1_MBOX0_CMD_STAT);
-	BNAD_GET_REG(LPU0_HOSTFN2_MBOX0_CMD_STAT);
-	BNAD_GET_REG(LPU1_HOSTFN2_MBOX0_CMD_STAT);
-
-	BNAD_GET_REG(HOSTFN2_LPU0_MBOX1_CMD_STAT);
-	BNAD_GET_REG(HOSTFN2_LPU1_MBOX1_CMD_STAT);
-	BNAD_GET_REG(LPU0_HOSTFN2_MBOX1_CMD_STAT);
-	BNAD_GET_REG(LPU1_HOSTFN2_MBOX1_CMD_STAT);
-
-	BNAD_GET_REG(HOSTFN3_LPU0_MBOX0_CMD_STAT);
-	BNAD_GET_REG(HOSTFN3_LPU1_MBOX0_CMD_STAT);
-	BNAD_GET_REG(LPU0_HOSTFN3_MBOX0_CMD_STAT);
-	BNAD_GET_REG(LPU1_HOSTFN3_MBOX0_CMD_STAT);
-
-	BNAD_GET_REG(HOSTFN3_LPU0_MBOX1_CMD_STAT);
-	BNAD_GET_REG(HOSTFN3_LPU1_MBOX1_CMD_STAT);
-	BNAD_GET_REG(LPU0_HOSTFN3_MBOX1_CMD_STAT);
-	BNAD_GET_REG(LPU1_HOSTFN3_MBOX1_CMD_STAT);
-
-	/* Host Function Force Parity Error Registers */
-	BNAD_GET_REG(HOSTFN0_LPU_FORCE_PERR);
-	BNAD_GET_REG(HOSTFN1_LPU_FORCE_PERR);
-	BNAD_GET_REG(HOSTFN2_LPU_FORCE_PERR);
-	BNAD_GET_REG(HOSTFN3_LPU_FORCE_PERR);
-
-	/* LL Port[0|1] Halt Mask Registers */
-	BNAD_GET_REG(LL_HALT_MSK_P0);
-	BNAD_GET_REG(LL_HALT_MSK_P1);
-
-	/* LL Port[0|1] Error Mask Registers */
-	BNAD_GET_REG(LL_ERR_MSK_P0);
-	BNAD_GET_REG(LL_ERR_MSK_P1);
-
-	/* EMC FLI Registers */
-	BNAD_GET_REG(FLI_CMD_REG);
-	BNAD_GET_REG(FLI_ADDR_REG);
-	BNAD_GET_REG(FLI_CTL_REG);
-	BNAD_GET_REG(FLI_WRDATA_REG);
-	BNAD_GET_REG(FLI_RDDATA_REG);
-	BNAD_GET_REG(FLI_DEV_STATUS_REG);
-	BNAD_GET_REG(FLI_SIG_WD_REG);
-
-	BNAD_GET_REG(FLI_DEV_VENDOR_REG);
-	BNAD_GET_REG(FLI_ERR_STATUS_REG);
-
-	/* RxAdm 0 Registers */
-	BNAD_GET_REG(RAD0_CTL_REG);
-	BNAD_GET_REG(RAD0_PE_PARM_REG);
-	BNAD_GET_REG(RAD0_BCN_REG);
-	BNAD_GET_REG(RAD0_DEFAULT_REG);
-	BNAD_GET_REG(RAD0_PROMISC_REG);
-	BNAD_GET_REG(RAD0_BCNQ_REG);
-	BNAD_GET_REG(RAD0_DEFAULTQ_REG);
-
-	BNAD_GET_REG(RAD0_ERR_STS);
-	BNAD_GET_REG(RAD0_SET_ERR_STS);
-	BNAD_GET_REG(RAD0_ERR_INT_EN);
-	BNAD_GET_REG(RAD0_FIRST_ERR);
-	BNAD_GET_REG(RAD0_FORCE_ERR);
-
-	BNAD_GET_REG(RAD0_MAC_MAN_1H);
-	BNAD_GET_REG(RAD0_MAC_MAN_1L);
-	BNAD_GET_REG(RAD0_MAC_MAN_2H);
-	BNAD_GET_REG(RAD0_MAC_MAN_2L);
-	BNAD_GET_REG(RAD0_MAC_MAN_3H);
-	BNAD_GET_REG(RAD0_MAC_MAN_3L);
-	BNAD_GET_REG(RAD0_MAC_MAN_4H);
-	BNAD_GET_REG(RAD0_MAC_MAN_4L);
-
-	BNAD_GET_REG(RAD0_LAST4_IP);
-
-	/* RxAdm 1 Registers */
-	BNAD_GET_REG(RAD1_CTL_REG);
-	BNAD_GET_REG(RAD1_PE_PARM_REG);
-	BNAD_GET_REG(RAD1_BCN_REG);
-	BNAD_GET_REG(RAD1_DEFAULT_REG);
-	BNAD_GET_REG(RAD1_PROMISC_REG);
-	BNAD_GET_REG(RAD1_BCNQ_REG);
-	BNAD_GET_REG(RAD1_DEFAULTQ_REG);
-
-	BNAD_GET_REG(RAD1_ERR_STS);
-	BNAD_GET_REG(RAD1_SET_ERR_STS);
-	BNAD_GET_REG(RAD1_ERR_INT_EN);
-
-	/* TxA0 Registers */
-	BNAD_GET_REG(TXA0_CTRL_REG);
-	/* TxA0 TSO Sequence # Registers (RO) */
-	for (i = 0; i < 8; i++) {
-		BNAD_GET_REG(TXA0_TSO_TCP_SEQ_REG(i));
-		BNAD_GET_REG(TXA0_TSO_IP_INFO_REG(i));
-	}
-
-	/* TxA1 Registers */
-	BNAD_GET_REG(TXA1_CTRL_REG);
-	/* TxA1 TSO Sequence # Registers (RO) */
-	for (i = 0; i < 8; i++) {
-		BNAD_GET_REG(TXA1_TSO_TCP_SEQ_REG(i));
-		BNAD_GET_REG(TXA1_TSO_IP_INFO_REG(i));
-	}
-
-	/* RxA Registers */
-	BNAD_GET_REG(RXA0_CTL_REG);
-	BNAD_GET_REG(RXA1_CTL_REG);
-
-	/* PLB0 Registers */
-	BNAD_GET_REG(PLB0_ECM_TIMER_REG);
-	BNAD_GET_REG(PLB0_RL_CTL);
-	for (i = 0; i < 8; i++)
-		BNAD_GET_REG(PLB0_RL_MAX_BC(i));
-	BNAD_GET_REG(PLB0_RL_TU_PRIO);
-	for (i = 0; i < 8; i++)
-		BNAD_GET_REG(PLB0_RL_BYTE_CNT(i));
-	BNAD_GET_REG(PLB0_RL_MIN_REG);
-	BNAD_GET_REG(PLB0_RL_MAX_REG);
-	BNAD_GET_REG(PLB0_EMS_ADD_REG);
-
-	/* PLB1 Registers */
-	BNAD_GET_REG(PLB1_ECM_TIMER_REG);
-	BNAD_GET_REG(PLB1_RL_CTL);
-	for (i = 0; i < 8; i++)
-		BNAD_GET_REG(PLB1_RL_MAX_BC(i));
-	BNAD_GET_REG(PLB1_RL_TU_PRIO);
-	for (i = 0; i < 8; i++)
-		BNAD_GET_REG(PLB1_RL_BYTE_CNT(i));
-	BNAD_GET_REG(PLB1_RL_MIN_REG);
-	BNAD_GET_REG(PLB1_RL_MAX_REG);
-	BNAD_GET_REG(PLB1_EMS_ADD_REG);
-
-	/* HQM Control Register */
-	BNAD_GET_REG(HQM0_CTL_REG);
-	BNAD_GET_REG(HQM0_RXQ_STOP_SEM);
-	BNAD_GET_REG(HQM0_TXQ_STOP_SEM);
-	BNAD_GET_REG(HQM1_CTL_REG);
-	BNAD_GET_REG(HQM1_RXQ_STOP_SEM);
-	BNAD_GET_REG(HQM1_TXQ_STOP_SEM);
-
-	/* LUT Registers */
-	BNAD_GET_REG(LUT0_ERR_STS);
-	BNAD_GET_REG(LUT0_SET_ERR_STS);
-	BNAD_GET_REG(LUT1_ERR_STS);
-	BNAD_GET_REG(LUT1_SET_ERR_STS);
-
-	/* TRC Registers */
-	BNAD_GET_REG(TRC_CTL_REG);
-	BNAD_GET_REG(TRC_MODS_REG);
-	BNAD_GET_REG(TRC_TRGC_REG);
-	BNAD_GET_REG(TRC_CNT1_REG);
-	BNAD_GET_REG(TRC_CNT2_REG);
-	BNAD_GET_REG(TRC_NXTS_REG);
-	BNAD_GET_REG(TRC_DIRR_REG);
-	for (i = 0; i < 10; i++)
-		BNAD_GET_REG(TRC_TRGM_REG(i));
-	for (i = 0; i < 10; i++)
-		BNAD_GET_REG(TRC_NXTM_REG(i));
-	for (i = 0; i < 10; i++)
-		BNAD_GET_REG(TRC_STRM_REG(i));
-
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-#undef BNAD_GET_REG
-	return num;
-}
-static int
-bnad_get_regs_len(struct net_device *netdev)
-{
-	int ret = get_regs(netdev_priv(netdev), NULL) * sizeof(u32);
-	return ret;
-}
-
-static void
-bnad_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf)
-{
-	memset(buf, 0, bnad_get_regs_len(netdev));
-	get_regs(netdev_priv(netdev), buf);
-}
-
-static void
-bnad_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wolinfo)
-{
-	wolinfo->supported = 0;
-	wolinfo->wolopts = 0;
-}
-
-static int
-bnad_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-	unsigned long flags;
-
-	/* Lock rqd. to access bnad->bna_lock */
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	coalesce->use_adaptive_rx_coalesce =
-		(bnad->cfg_flags & BNAD_CF_DIM_ENABLED) ? true : false;
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	coalesce->rx_coalesce_usecs = bnad->rx_coalescing_timeo *
-					BFI_COALESCING_TIMER_UNIT;
-	coalesce->tx_coalesce_usecs = bnad->tx_coalescing_timeo *
-					BFI_COALESCING_TIMER_UNIT;
-	coalesce->tx_max_coalesced_frames = BFI_TX_INTERPKT_COUNT;
-
-	return 0;
-}
-
-static int
-bnad_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-	unsigned long flags;
-	int dim_timer_del = 0;
-
-	if (coalesce->rx_coalesce_usecs == 0 ||
-	    coalesce->rx_coalesce_usecs >
-	    BFI_MAX_COALESCING_TIMEO * BFI_COALESCING_TIMER_UNIT)
-		return -EINVAL;
-
-	if (coalesce->tx_coalesce_usecs == 0 ||
-	    coalesce->tx_coalesce_usecs >
-	    BFI_MAX_COALESCING_TIMEO * BFI_COALESCING_TIMER_UNIT)
-		return -EINVAL;
-
-	mutex_lock(&bnad->conf_mutex);
-	/*
-	 * Do not need to store rx_coalesce_usecs here
-	 * Every time DIM is disabled, we can get it from the
-	 * stack.
-	 */
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	if (coalesce->use_adaptive_rx_coalesce) {
-		if (!(bnad->cfg_flags & BNAD_CF_DIM_ENABLED)) {
-			bnad->cfg_flags |= BNAD_CF_DIM_ENABLED;
-			bnad_dim_timer_start(bnad);
-		}
-	} else {
-		if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED) {
-			bnad->cfg_flags &= ~BNAD_CF_DIM_ENABLED;
-			dim_timer_del = bnad_dim_timer_running(bnad);
-			if (dim_timer_del) {
-				clear_bit(BNAD_RF_DIM_TIMER_RUNNING,
-							&bnad->run_flags);
-				spin_unlock_irqrestore(&bnad->bna_lock, flags);
-				del_timer_sync(&bnad->dim_timer);
-				spin_lock_irqsave(&bnad->bna_lock, flags);
-			}
-			bnad_rx_coalescing_timeo_set(bnad);
-		}
-	}
-	if (bnad->tx_coalescing_timeo != coalesce->tx_coalesce_usecs /
-					BFI_COALESCING_TIMER_UNIT) {
-		bnad->tx_coalescing_timeo = coalesce->tx_coalesce_usecs /
-						BFI_COALESCING_TIMER_UNIT;
-		bnad_tx_coalescing_timeo_set(bnad);
-	}
-
-	if (bnad->rx_coalescing_timeo != coalesce->rx_coalesce_usecs /
-					BFI_COALESCING_TIMER_UNIT) {
-		bnad->rx_coalescing_timeo = coalesce->rx_coalesce_usecs /
-						BFI_COALESCING_TIMER_UNIT;
-
-		if (!(bnad->cfg_flags & BNAD_CF_DIM_ENABLED))
-			bnad_rx_coalescing_timeo_set(bnad);
-
-	}
-
-	/* Add Tx Inter-pkt DMA count?  */
-
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	mutex_unlock(&bnad->conf_mutex);
-	return 0;
-}
-
-static void
-bnad_get_ringparam(struct net_device *netdev,
-		   struct ethtool_ringparam *ringparam)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-
-	ringparam->rx_max_pending = BNAD_MAX_Q_DEPTH / bnad_rxqs_per_cq;
-	ringparam->rx_mini_max_pending = 0;
-	ringparam->rx_jumbo_max_pending = 0;
-	ringparam->tx_max_pending = BNAD_MAX_Q_DEPTH;
-
-	ringparam->rx_pending = bnad->rxq_depth;
-	ringparam->rx_mini_max_pending = 0;
-	ringparam->rx_jumbo_max_pending = 0;
-	ringparam->tx_pending = bnad->txq_depth;
-}
-
-static int
-bnad_set_ringparam(struct net_device *netdev,
-		   struct ethtool_ringparam *ringparam)
-{
-	int i, current_err, err = 0;
-	struct bnad *bnad = netdev_priv(netdev);
-
-	mutex_lock(&bnad->conf_mutex);
-	if (ringparam->rx_pending == bnad->rxq_depth &&
-	    ringparam->tx_pending == bnad->txq_depth) {
-		mutex_unlock(&bnad->conf_mutex);
-		return 0;
-	}
-
-	if (ringparam->rx_pending < BNAD_MIN_Q_DEPTH ||
-	    ringparam->rx_pending > BNAD_MAX_Q_DEPTH / bnad_rxqs_per_cq ||
-	    !BNA_POWER_OF_2(ringparam->rx_pending)) {
-		mutex_unlock(&bnad->conf_mutex);
-		return -EINVAL;
-	}
-	if (ringparam->tx_pending < BNAD_MIN_Q_DEPTH ||
-	    ringparam->tx_pending > BNAD_MAX_Q_DEPTH ||
-	    !BNA_POWER_OF_2(ringparam->tx_pending)) {
-		mutex_unlock(&bnad->conf_mutex);
-		return -EINVAL;
-	}
-
-	if (ringparam->rx_pending != bnad->rxq_depth) {
-		bnad->rxq_depth = ringparam->rx_pending;
-		for (i = 0; i < bnad->num_rx; i++) {
-			if (!bnad->rx_info[i].rx)
-				continue;
-			bnad_cleanup_rx(bnad, i);
-			current_err = bnad_setup_rx(bnad, i);
-			if (current_err && !err)
-				err = current_err;
-		}
-	}
-	if (ringparam->tx_pending != bnad->txq_depth) {
-		bnad->txq_depth = ringparam->tx_pending;
-		for (i = 0; i < bnad->num_tx; i++) {
-			if (!bnad->tx_info[i].tx)
-				continue;
-			bnad_cleanup_tx(bnad, i);
-			current_err = bnad_setup_tx(bnad, i);
-			if (current_err && !err)
-				err = current_err;
-		}
-	}
-
-	mutex_unlock(&bnad->conf_mutex);
-	return err;
-}
-
-static void
-bnad_get_pauseparam(struct net_device *netdev,
-		    struct ethtool_pauseparam *pauseparam)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-
-	pauseparam->autoneg = 0;
-	pauseparam->rx_pause = bnad->bna.port.pause_config.rx_pause;
-	pauseparam->tx_pause = bnad->bna.port.pause_config.tx_pause;
-}
-
-static int
-bnad_set_pauseparam(struct net_device *netdev,
-		    struct ethtool_pauseparam *pauseparam)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-	struct bna_pause_config pause_config;
-	unsigned long flags;
-
-	if (pauseparam->autoneg == AUTONEG_ENABLE)
-		return -EINVAL;
-
-	mutex_lock(&bnad->conf_mutex);
-	if (pauseparam->rx_pause != bnad->bna.port.pause_config.rx_pause ||
-	    pauseparam->tx_pause != bnad->bna.port.pause_config.tx_pause) {
-		pause_config.rx_pause = pauseparam->rx_pause;
-		pause_config.tx_pause = pauseparam->tx_pause;
-		spin_lock_irqsave(&bnad->bna_lock, flags);
-		bna_port_pause_config(&bnad->bna.port, &pause_config, NULL);
-		spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	}
-	mutex_unlock(&bnad->conf_mutex);
-	return 0;
-}
-
-static void
-bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-	int i, j, q_num;
-	u64 bmap;
-
-	mutex_lock(&bnad->conf_mutex);
-
-	switch (stringset) {
-	case ETH_SS_STATS:
-		for (i = 0; i < BNAD_ETHTOOL_STATS_NUM; i++) {
-			BUG_ON(!(strlen(bnad_net_stats_strings[i]) <
-				   ETH_GSTRING_LEN));
-			memcpy(string, bnad_net_stats_strings[i],
-			       ETH_GSTRING_LEN);
-			string += ETH_GSTRING_LEN;
-		}
-		bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] |
-			((u64)bnad->bna.tx_mod.txf_bmap[1] << 32);
-		for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) {
-			if (bmap & 1) {
-				sprintf(string, "txf%d_ucast_octets", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "txf%d_ucast", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "txf%d_ucast_vlan", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "txf%d_mcast_octets", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "txf%d_mcast", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "txf%d_mcast_vlan", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "txf%d_bcast_octets", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "txf%d_bcast", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "txf%d_bcast_vlan", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "txf%d_errors", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "txf%d_filter_vlan", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "txf%d_filter_mac_sa", i);
-				string += ETH_GSTRING_LEN;
-			}
-			bmap >>= 1;
-		}
-
-		bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] |
-			((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32);
-		for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
-			if (bmap & 1) {
-				sprintf(string, "rxf%d_ucast_octets", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "rxf%d_ucast", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "rxf%d_ucast_vlan", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "rxf%d_mcast_octets", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "rxf%d_mcast", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "rxf%d_mcast_vlan", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "rxf%d_bcast_octets", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "rxf%d_bcast", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "rxf%d_bcast_vlan", i);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "rxf%d_frame_drops", i);
-				string += ETH_GSTRING_LEN;
-			}
-			bmap >>= 1;
-		}
-
-		q_num = 0;
-		for (i = 0; i < bnad->num_rx; i++) {
-			if (!bnad->rx_info[i].rx)
-				continue;
-			for (j = 0; j < bnad->num_rxp_per_rx; j++) {
-				sprintf(string, "cq%d_producer_index", q_num);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "cq%d_consumer_index", q_num);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "cq%d_hw_producer_index",
-					q_num);
-				string += ETH_GSTRING_LEN;
-				q_num++;
-			}
-		}
-
-		q_num = 0;
-		for (i = 0; i < bnad->num_rx; i++) {
-			if (!bnad->rx_info[i].rx)
-				continue;
-			for (j = 0; j < bnad->num_rxp_per_rx; j++) {
-				sprintf(string, "rxq%d_packets", q_num);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "rxq%d_bytes", q_num);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "rxq%d_packets_with_error",
-								q_num);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "rxq%d_allocbuf_failed", q_num);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "rxq%d_producer_index", q_num);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "rxq%d_consumer_index", q_num);
-				string += ETH_GSTRING_LEN;
-				q_num++;
-				if (bnad->rx_info[i].rx_ctrl[j].ccb &&
-					bnad->rx_info[i].rx_ctrl[j].ccb->
-					rcb[1] &&
-					bnad->rx_info[i].rx_ctrl[j].ccb->
-					rcb[1]->rxq) {
-					sprintf(string, "rxq%d_packets", q_num);
-					string += ETH_GSTRING_LEN;
-					sprintf(string, "rxq%d_bytes", q_num);
-					string += ETH_GSTRING_LEN;
-					sprintf(string,
-					"rxq%d_packets_with_error", q_num);
-					string += ETH_GSTRING_LEN;
-					sprintf(string, "rxq%d_allocbuf_failed",
-								q_num);
-					string += ETH_GSTRING_LEN;
-					sprintf(string, "rxq%d_producer_index",
-								q_num);
-					string += ETH_GSTRING_LEN;
-					sprintf(string, "rxq%d_consumer_index",
-								q_num);
-					string += ETH_GSTRING_LEN;
-					q_num++;
-				}
-			}
-		}
-
-		q_num = 0;
-		for (i = 0; i < bnad->num_tx; i++) {
-			if (!bnad->tx_info[i].tx)
-				continue;
-			for (j = 0; j < bnad->num_txq_per_tx; j++) {
-				sprintf(string, "txq%d_packets", q_num);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "txq%d_bytes", q_num);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "txq%d_producer_index", q_num);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "txq%d_consumer_index", q_num);
-				string += ETH_GSTRING_LEN;
-				sprintf(string, "txq%d_hw_consumer_index",
-									q_num);
-				string += ETH_GSTRING_LEN;
-				q_num++;
-			}
-		}
-
-		break;
-
-	default:
-		break;
-	}
-
-	mutex_unlock(&bnad->conf_mutex);
-}
-
-static int
-bnad_get_stats_count_locked(struct net_device *netdev)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-	int i, j, count, rxf_active_num = 0, txf_active_num = 0;
-	u64 bmap;
-
-	bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] |
-			((u64)bnad->bna.tx_mod.txf_bmap[1] << 32);
-	for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) {
-		if (bmap & 1)
-			txf_active_num++;
-		bmap >>= 1;
-	}
-	bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] |
-			((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32);
-	for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
-		if (bmap & 1)
-			rxf_active_num++;
-		bmap >>= 1;
-	}
-	count = BNAD_ETHTOOL_STATS_NUM +
-		txf_active_num * BNAD_NUM_TXF_COUNTERS +
-		rxf_active_num * BNAD_NUM_RXF_COUNTERS;
-
-	for (i = 0; i < bnad->num_rx; i++) {
-		if (!bnad->rx_info[i].rx)
-			continue;
-		count += bnad->num_rxp_per_rx * BNAD_NUM_CQ_COUNTERS;
-		count += bnad->num_rxp_per_rx * BNAD_NUM_RXQ_COUNTERS;
-		for (j = 0; j < bnad->num_rxp_per_rx; j++)
-			if (bnad->rx_info[i].rx_ctrl[j].ccb &&
-				bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] &&
-				bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1]->rxq)
-				count +=  BNAD_NUM_RXQ_COUNTERS;
-	}
-
-	for (i = 0; i < bnad->num_tx; i++) {
-		if (!bnad->tx_info[i].tx)
-			continue;
-		count += bnad->num_txq_per_tx * BNAD_NUM_TXQ_COUNTERS;
-	}
-	return count;
-}
-
-static int
-bnad_per_q_stats_fill(struct bnad *bnad, u64 *buf, int bi)
-{
-	int i, j;
-	struct bna_rcb *rcb = NULL;
-	struct bna_tcb *tcb = NULL;
-
-	for (i = 0; i < bnad->num_rx; i++) {
-		if (!bnad->rx_info[i].rx)
-			continue;
-		for (j = 0; j < bnad->num_rxp_per_rx; j++)
-			if (bnad->rx_info[i].rx_ctrl[j].ccb &&
-				bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0] &&
-				bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0]->rxq) {
-				buf[bi++] = bnad->rx_info[i].rx_ctrl[j].
-						ccb->producer_index;
-				buf[bi++] = 0; /* ccb->consumer_index */
-				buf[bi++] = *(bnad->rx_info[i].rx_ctrl[j].
-						ccb->hw_producer_index);
-			}
-	}
-	for (i = 0; i < bnad->num_rx; i++) {
-		if (!bnad->rx_info[i].rx)
-			continue;
-		for (j = 0; j < bnad->num_rxp_per_rx; j++)
-			if (bnad->rx_info[i].rx_ctrl[j].ccb) {
-				if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0] &&
-					bnad->rx_info[i].rx_ctrl[j].ccb->
-					rcb[0]->rxq) {
-					rcb = bnad->rx_info[i].rx_ctrl[j].
-							ccb->rcb[0];
-					buf[bi++] = rcb->rxq->rx_packets;
-					buf[bi++] = rcb->rxq->rx_bytes;
-					buf[bi++] = rcb->rxq->
-							rx_packets_with_error;
-					buf[bi++] = rcb->rxq->
-							rxbuf_alloc_failed;
-					buf[bi++] = rcb->producer_index;
-					buf[bi++] = rcb->consumer_index;
-				}
-				if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] &&
-					bnad->rx_info[i].rx_ctrl[j].ccb->
-					rcb[1]->rxq) {
-					rcb = bnad->rx_info[i].rx_ctrl[j].
-								ccb->rcb[1];
-					buf[bi++] = rcb->rxq->rx_packets;
-					buf[bi++] = rcb->rxq->rx_bytes;
-					buf[bi++] = rcb->rxq->
-							rx_packets_with_error;
-					buf[bi++] = rcb->rxq->
-							rxbuf_alloc_failed;
-					buf[bi++] = rcb->producer_index;
-					buf[bi++] = rcb->consumer_index;
-				}
-			}
-	}
-
-	for (i = 0; i < bnad->num_tx; i++) {
-		if (!bnad->tx_info[i].tx)
-			continue;
-		for (j = 0; j < bnad->num_txq_per_tx; j++)
-			if (bnad->tx_info[i].tcb[j] &&
-				bnad->tx_info[i].tcb[j]->txq) {
-				tcb = bnad->tx_info[i].tcb[j];
-				buf[bi++] = tcb->txq->tx_packets;
-				buf[bi++] = tcb->txq->tx_bytes;
-				buf[bi++] = tcb->producer_index;
-				buf[bi++] = tcb->consumer_index;
-				buf[bi++] = *(tcb->hw_consumer_index);
-			}
-	}
-
-	return bi;
-}
-
-static void
-bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats,
-		       u64 *buf)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-	int i, j, bi;
-	unsigned long flags;
-	struct rtnl_link_stats64 *net_stats64;
-	u64 *stats64;
-	u64 bmap;
-
-	mutex_lock(&bnad->conf_mutex);
-	if (bnad_get_stats_count_locked(netdev) != stats->n_stats) {
-		mutex_unlock(&bnad->conf_mutex);
-		return;
-	}
-
-	/*
-	 * Used bna_lock to sync reads from bna_stats, which is written
-	 * under the same lock
-	 */
-	spin_lock_irqsave(&bnad->bna_lock, flags);
-	bi = 0;
-	memset(buf, 0, stats->n_stats * sizeof(u64));
-
-	net_stats64 = (struct rtnl_link_stats64 *)buf;
-	bnad_netdev_qstats_fill(bnad, net_stats64);
-	bnad_netdev_hwstats_fill(bnad, net_stats64);
-
-	bi = sizeof(*net_stats64) / sizeof(u64);
-
-	/* Get netif_queue_stopped from stack */
-	bnad->stats.drv_stats.netif_queue_stopped = netif_queue_stopped(netdev);
-
-	/* Fill driver stats into ethtool buffers */
-	stats64 = (u64 *)&bnad->stats.drv_stats;
-	for (i = 0; i < sizeof(struct bnad_drv_stats) / sizeof(u64); i++)
-		buf[bi++] = stats64[i];
-
-	/* Fill hardware stats excluding the rxf/txf into ethtool bufs */
-	stats64 = (u64 *) bnad->stats.bna_stats->hw_stats;
-	for (i = 0;
-	     i < offsetof(struct bfi_ll_stats, rxf_stats[0]) / sizeof(u64);
-	     i++)
-		buf[bi++] = stats64[i];
-
-	/* Fill txf stats into ethtool buffers */
-	bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] |
-			((u64)bnad->bna.tx_mod.txf_bmap[1] << 32);
-	for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) {
-		if (bmap & 1) {
-			stats64 = (u64 *)&bnad->stats.bna_stats->
-						hw_stats->txf_stats[i];
-			for (j = 0; j < sizeof(struct bfi_ll_stats_txf) /
-					sizeof(u64); j++)
-				buf[bi++] = stats64[j];
-		}
-		bmap >>= 1;
-	}
-
-	/*  Fill rxf stats into ethtool buffers */
-	bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] |
-			((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32);
-	for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
-		if (bmap & 1) {
-			stats64 = (u64 *)&bnad->stats.bna_stats->
-						hw_stats->rxf_stats[i];
-			for (j = 0; j < sizeof(struct bfi_ll_stats_rxf) /
-					sizeof(u64); j++)
-				buf[bi++] = stats64[j];
-		}
-		bmap >>= 1;
-	}
-
-	/* Fill per Q stats into ethtool buffers */
-	bi = bnad_per_q_stats_fill(bnad, buf, bi);
-
-	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-
-	mutex_unlock(&bnad->conf_mutex);
-}
-
-static int
-bnad_get_sset_count(struct net_device *netdev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		return bnad_get_stats_count_locked(netdev);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static struct ethtool_ops bnad_ethtool_ops = {
-	.get_settings = bnad_get_settings,
-	.set_settings = bnad_set_settings,
-	.get_drvinfo = bnad_get_drvinfo,
-	.get_regs_len = bnad_get_regs_len,
-	.get_regs = bnad_get_regs,
-	.get_wol = bnad_get_wol,
-	.get_link = ethtool_op_get_link,
-	.get_coalesce = bnad_get_coalesce,
-	.set_coalesce = bnad_set_coalesce,
-	.get_ringparam = bnad_get_ringparam,
-	.set_ringparam = bnad_set_ringparam,
-	.get_pauseparam = bnad_get_pauseparam,
-	.set_pauseparam = bnad_set_pauseparam,
-	.get_strings = bnad_get_strings,
-	.get_ethtool_stats = bnad_get_ethtool_stats,
-	.get_sset_count = bnad_get_sset_count
-};
-
-void
-bnad_set_ethtool_ops(struct net_device *netdev)
-{
-	SET_ETHTOOL_OPS(netdev, &bnad_ethtool_ops);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bnad.h linux-libre-3.2-gnu/drivers/net/bna/bnad.h
--- linux-libre-3.1-gnu/drivers/net/bna/bnad.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bnad.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,341 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-#ifndef __BNAD_H__
-#define __BNAD_H__
-
-#include <linux/rtnetlink.h>
-#include <linux/workqueue.h>
-#include <linux/ipv6.h>
-#include <linux/etherdevice.h>
-#include <linux/mutex.h>
-#include <linux/firmware.h>
-#include <linux/if_vlan.h>
-
-/* Fix for IA64 */
-#include <asm/checksum.h>
-#include <net/ip6_checksum.h>
-
-#include <net/ip.h>
-#include <net/tcp.h>
-
-#include "bna.h"
-
-#define BNAD_TXQ_DEPTH		2048
-#define BNAD_RXQ_DEPTH		2048
-
-#define BNAD_MAX_TXS		1
-#define BNAD_MAX_TXQ_PER_TX	8	/* 8 priority queues */
-#define BNAD_TXQ_NUM		1
-
-#define BNAD_MAX_RXS		1
-#define BNAD_MAX_RXPS_PER_RX	16
-
-/*
- * Control structure pointed to ccb->ctrl, which
- * determines the NAPI / LRO behavior CCB
- * There is 1:1 corres. between ccb & ctrl
- */
-struct bnad_rx_ctrl {
-	struct bna_ccb *ccb;
-	unsigned long  flags;
-	struct napi_struct	napi;
-};
-
-#define BNAD_RXMODE_PROMISC_DEFAULT	BNA_RXMODE_PROMISC
-
-#define BNAD_GET_TX_ID(_skb)	(0)
-
-/*
- * GLOBAL #defines (CONSTANTS)
- */
-#define BNAD_NAME			"bna"
-#define BNAD_NAME_LEN			64
-
-#define BNAD_VERSION			"2.3.2.3"
-
-#define BNAD_MAILBOX_MSIX_INDEX		0
-#define BNAD_MAILBOX_MSIX_VECTORS	1
-#define BNAD_INTX_TX_IB_BITMASK		0x1
-#define BNAD_INTX_RX_IB_BITMASK		0x2
-
-#define BNAD_STATS_TIMER_FREQ		1000	/* in msecs */
-#define BNAD_DIM_TIMER_FREQ		1000	/* in msecs */
-
-#define BNAD_MAX_Q_DEPTH		0x10000
-#define BNAD_MIN_Q_DEPTH		0x200
-
-#define BNAD_JUMBO_MTU			9000
-
-#define BNAD_NETIF_WAKE_THRESHOLD	8
-
-#define BNAD_RXQ_REFILL_THRESHOLD_SHIFT	3
-
-/* Bit positions for tcb->flags */
-#define BNAD_TXQ_FREE_SENT		0
-#define BNAD_TXQ_TX_STARTED		1
-
-/* Bit positions for rcb->flags */
-#define BNAD_RXQ_REFILL			0
-#define BNAD_RXQ_STARTED		1
-
-/*
- * DATA STRUCTURES
- */
-
-/* enums */
-enum bnad_intr_source {
-	BNAD_INTR_TX		= 1,
-	BNAD_INTR_RX		= 2
-};
-
-enum bnad_link_state {
-	BNAD_LS_DOWN		= 0,
-	BNAD_LS_UP		= 1
-};
-
-struct bnad_completion {
-	struct completion	ioc_comp;
-	struct completion	ucast_comp;
-	struct completion	mcast_comp;
-	struct completion	tx_comp;
-	struct completion	rx_comp;
-	struct completion	stats_comp;
-	struct completion	port_comp;
-
-	u8			ioc_comp_status;
-	u8			ucast_comp_status;
-	u8			mcast_comp_status;
-	u8			tx_comp_status;
-	u8			rx_comp_status;
-	u8			stats_comp_status;
-	u8			port_comp_status;
-};
-
-/* Tx Rx Control Stats */
-struct bnad_drv_stats {
-	u64		netif_queue_stop;
-	u64		netif_queue_wakeup;
-	u64		netif_queue_stopped;
-	u64		tso4;
-	u64		tso6;
-	u64		tso_err;
-	u64		tcpcsum_offload;
-	u64		udpcsum_offload;
-	u64		csum_help;
-	u64		csum_help_err;
-
-	u64		hw_stats_updates;
-	u64		netif_rx_schedule;
-	u64		netif_rx_complete;
-	u64		netif_rx_dropped;
-
-	u64		link_toggle;
-	u64		cee_up;
-
-	u64		rxp_info_alloc_failed;
-	u64		mbox_intr_disabled;
-	u64		mbox_intr_enabled;
-	u64		tx_unmap_q_alloc_failed;
-	u64		rx_unmap_q_alloc_failed;
-
-	u64		rxbuf_alloc_failed;
-};
-
-/* Complete driver stats */
-struct bnad_stats {
-	struct bnad_drv_stats drv_stats;
-	struct bna_stats *bna_stats;
-};
-
-/* Tx / Rx Resources */
-struct bnad_tx_res_info {
-	struct bna_res_info res_info[BNA_TX_RES_T_MAX];
-};
-
-struct bnad_rx_res_info {
-	struct bna_res_info res_info[BNA_RX_RES_T_MAX];
-};
-
-struct bnad_tx_info {
-	struct bna_tx *tx; /* 1:1 between tx_info & tx */
-	struct bna_tcb *tcb[BNAD_MAX_TXQ_PER_TX];
-} ____cacheline_aligned;
-
-struct bnad_rx_info {
-	struct bna_rx *rx; /* 1:1 between rx_info & rx */
-
-	struct bnad_rx_ctrl rx_ctrl[BNAD_MAX_RXPS_PER_RX];
-} ____cacheline_aligned;
-
-/* Unmap queues for Tx / Rx cleanup */
-struct bnad_skb_unmap {
-	struct sk_buff		*skb;
-	DEFINE_DMA_UNMAP_ADDR(dma_addr);
-};
-
-struct bnad_unmap_q {
-	u32		producer_index;
-	u32		consumer_index;
-	u32		q_depth;
-	/* This should be the last one */
-	struct bnad_skb_unmap unmap_array[1];
-};
-
-/* Bit mask values for bnad->cfg_flags */
-#define	BNAD_CF_DIM_ENABLED		0x01	/* DIM */
-#define	BNAD_CF_PROMISC			0x02
-#define BNAD_CF_ALLMULTI		0x04
-#define	BNAD_CF_MSIX			0x08	/* If in MSIx mode */
-
-/* Defines for run_flags bit-mask */
-/* Set, tested & cleared using xxx_bit() functions */
-/* Values indicated bit positions */
-#define	BNAD_RF_CEE_RUNNING		1
-#define BNAD_RF_MBOX_IRQ_DISABLED	2
-#define BNAD_RF_RX_STARTED		3
-#define BNAD_RF_DIM_TIMER_RUNNING	4
-#define BNAD_RF_STATS_TIMER_RUNNING	5
-#define BNAD_RF_TX_SHUTDOWN_DELAYED	6
-#define BNAD_RF_RX_SHUTDOWN_DELAYED	7
-
-struct bnad {
-	struct net_device	*netdev;
-
-	/* Data path */
-	struct bnad_tx_info tx_info[BNAD_MAX_TXS];
-	struct bnad_rx_info rx_info[BNAD_MAX_RXS];
-
-	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
-	/*
-	 * These q numbers are global only because
-	 * they are used to calculate MSIx vectors.
-	 * Actually the exact # of queues are per Tx/Rx
-	 * object.
-	 */
-	u32		num_tx;
-	u32		num_rx;
-	u32		num_txq_per_tx;
-	u32		num_rxp_per_rx;
-
-	u32		txq_depth;
-	u32		rxq_depth;
-
-	u8			tx_coalescing_timeo;
-	u8			rx_coalescing_timeo;
-
-	struct bna_rx_config rx_config[BNAD_MAX_RXS];
-	struct bna_tx_config tx_config[BNAD_MAX_TXS];
-
-	void __iomem		*bar0;	/* BAR0 address */
-
-	struct bna bna;
-
-	u32		cfg_flags;
-	unsigned long		run_flags;
-
-	struct pci_dev		*pcidev;
-	u64		mmio_start;
-	u64		mmio_len;
-
-	u32		msix_num;
-	struct msix_entry	*msix_table;
-
-	struct mutex		conf_mutex;
-	spinlock_t		bna_lock ____cacheline_aligned;
-
-	/* Timers */
-	struct timer_list	ioc_timer;
-	struct timer_list	dim_timer;
-	struct timer_list	stats_timer;
-
-	/* Control path resources, memory & irq */
-	struct bna_res_info res_info[BNA_RES_T_MAX];
-	struct bnad_tx_res_info tx_res_info[BNAD_MAX_TXS];
-	struct bnad_rx_res_info rx_res_info[BNAD_MAX_RXS];
-
-	struct bnad_completion bnad_completions;
-
-	/* Burnt in MAC address */
-	mac_t			perm_addr;
-
-	struct tasklet_struct	tx_free_tasklet;
-
-	/* Statistics */
-	struct bnad_stats stats;
-
-	struct bnad_diag *diag;
-
-	char			adapter_name[BNAD_NAME_LEN];
-	char			port_name[BNAD_NAME_LEN];
-	char			mbox_irq_name[BNAD_NAME_LEN];
-};
-
-/*
- * EXTERN VARIABLES
- */
-extern struct firmware *bfi_fw;
-extern u32		bnad_rxqs_per_cq;
-
-/*
- * EXTERN PROTOTYPES
- */
-extern u32 *cna_get_firmware_buf(struct pci_dev *pdev);
-/* Netdev entry point prototypes */
-extern void bnad_set_ethtool_ops(struct net_device *netdev);
-
-/* Configuration & setup */
-extern void bnad_tx_coalescing_timeo_set(struct bnad *bnad);
-extern void bnad_rx_coalescing_timeo_set(struct bnad *bnad);
-
-extern int bnad_setup_rx(struct bnad *bnad, uint rx_id);
-extern int bnad_setup_tx(struct bnad *bnad, uint tx_id);
-extern void bnad_cleanup_tx(struct bnad *bnad, uint tx_id);
-extern void bnad_cleanup_rx(struct bnad *bnad, uint rx_id);
-
-/* Timer start/stop protos */
-extern void bnad_dim_timer_start(struct bnad *bnad);
-
-/* Statistics */
-extern void bnad_netdev_qstats_fill(struct bnad *bnad,
-		struct rtnl_link_stats64 *stats);
-extern void bnad_netdev_hwstats_fill(struct bnad *bnad,
-		struct rtnl_link_stats64 *stats);
-
-/**
- * MACROS
- */
-/* To set & get the stats counters */
-#define BNAD_UPDATE_CTR(_bnad, _ctr)				\
-				(((_bnad)->stats.drv_stats._ctr)++)
-
-#define BNAD_GET_CTR(_bnad, _ctr) ((_bnad)->stats.drv_stats._ctr)
-
-#define bnad_enable_rx_irq_unsafe(_ccb)			\
-{							\
-	if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))) {\
-		bna_ib_coalescing_timer_set((_ccb)->i_dbell,	\
-			(_ccb)->rx_coalescing_timeo);		\
-		bna_ib_ack((_ccb)->i_dbell, 0);			\
-	}							\
-}
-
-#define bnad_dim_timer_running(_bnad)				\
-	(((_bnad)->cfg_flags & BNAD_CF_DIM_ENABLED) &&		\
-	(test_bit(BNAD_RF_DIM_TIMER_RUNNING, &((_bnad)->run_flags))))
-
-#endif /* __BNAD_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bna.h linux-libre-3.2-gnu/drivers/net/bna/bna.h
--- linux-libre-3.1-gnu/drivers/net/bna/bna.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bna.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,548 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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 __BNA_H__
-#define __BNA_H__
-
-#include "bfa_cs.h"
-#include "bfa_ioc.h"
-#include "cna.h"
-#include "bfi_ll.h"
-#include "bna_types.h"
-
-extern const u32 bna_napi_dim_vector[][BNA_BIAS_T_MAX];
-
-/**
- *
- *  Macros and constants
- *
- */
-
-#define BNA_IOC_TIMER_FREQ		200
-
-/* Log string size */
-#define BNA_MESSAGE_SIZE		256
-
-/* MBOX API for PORT, TX, RX */
-#define bna_mbox_qe_fill(_qe, _cmd, _cmd_len, _cbfn, _cbarg)		\
-do {									\
-	memcpy(&((_qe)->cmd.msg[0]), (_cmd), (_cmd_len));	\
-	(_qe)->cbfn = (_cbfn);						\
-	(_qe)->cbarg = (_cbarg);					\
-} while (0)
-
-#define bna_is_small_rxq(rcb) ((rcb)->id == 1)
-
-#define BNA_MAC_IS_EQUAL(_mac1, _mac2)					\
-	(!memcmp((_mac1), (_mac2), sizeof(mac_t)))
-
-#define BNA_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
-
-#define BNA_TO_POWER_OF_2(x)						\
-do {									\
-	int _shift = 0;							\
-	while ((x) && (x) != 1) {					\
-		(x) >>= 1;						\
-		_shift++;						\
-	}								\
-	(x) <<= _shift;							\
-} while (0)
-
-#define BNA_TO_POWER_OF_2_HIGH(x)					\
-do {									\
-	int n = 1;							\
-	while (n < (x))							\
-		n <<= 1;						\
-	(x) = n;							\
-} while (0)
-
-/*
- * input : _addr-> os dma addr in host endian format,
- * output : _bna_dma_addr-> pointer to hw dma addr
- */
-#define BNA_SET_DMA_ADDR(_addr, _bna_dma_addr)				\
-do {									\
-	u64 tmp_addr =						\
-	cpu_to_be64((u64)(_addr));				\
-	(_bna_dma_addr)->msb = ((struct bna_dma_addr *)&tmp_addr)->msb; \
-	(_bna_dma_addr)->lsb = ((struct bna_dma_addr *)&tmp_addr)->lsb; \
-} while (0)
-
-/*
- * input : _bna_dma_addr-> pointer to hw dma addr
- * output : _addr-> os dma addr in host endian format
- */
-#define BNA_GET_DMA_ADDR(_bna_dma_addr, _addr)			\
-do {								\
-	(_addr) = ((((u64)ntohl((_bna_dma_addr)->msb))) << 32)		\
-	| ((ntohl((_bna_dma_addr)->lsb) & 0xffffffff));	\
-} while (0)
-
-#define	containing_rec(addr, type, field)				\
-	((type *)((unsigned char *)(addr) -				\
-	(unsigned char *)(&((type *)0)->field)))
-
-#define BNA_TXQ_WI_NEEDED(_vectors)	(((_vectors) + 3) >> 2)
-
-/* TxQ element is 64 bytes */
-#define BNA_TXQ_PAGE_INDEX_MAX		(PAGE_SIZE >> 6)
-#define BNA_TXQ_PAGE_INDEX_MAX_SHIFT	(PAGE_SHIFT - 6)
-
-#define BNA_TXQ_QPGE_PTR_GET(_qe_idx, _qpt_ptr, _qe_ptr, _qe_ptr_range) \
-{									\
-	unsigned int page_index;	/* index within a page */	\
-	void *page_addr;						\
-	page_index = (_qe_idx) & (BNA_TXQ_PAGE_INDEX_MAX - 1);		\
-	(_qe_ptr_range) = (BNA_TXQ_PAGE_INDEX_MAX - page_index);	\
-	page_addr = (_qpt_ptr)[((_qe_idx) >>  BNA_TXQ_PAGE_INDEX_MAX_SHIFT)];\
-	(_qe_ptr) = &((struct bna_txq_entry *)(page_addr))[page_index]; \
-}
-
-/* RxQ element is 8 bytes */
-#define BNA_RXQ_PAGE_INDEX_MAX		(PAGE_SIZE >> 3)
-#define BNA_RXQ_PAGE_INDEX_MAX_SHIFT	(PAGE_SHIFT - 3)
-
-#define BNA_RXQ_QPGE_PTR_GET(_qe_idx, _qpt_ptr, _qe_ptr, _qe_ptr_range) \
-{									\
-	unsigned int page_index;	/* index within a page */	\
-	void *page_addr;						\
-	page_index = (_qe_idx) & (BNA_RXQ_PAGE_INDEX_MAX - 1);		\
-	(_qe_ptr_range) = (BNA_RXQ_PAGE_INDEX_MAX - page_index);	\
-	page_addr = (_qpt_ptr)[((_qe_idx) >>				\
-				BNA_RXQ_PAGE_INDEX_MAX_SHIFT)];		\
-	(_qe_ptr) = &((struct bna_rxq_entry *)(page_addr))[page_index]; \
-}
-
-/* CQ element is 16 bytes */
-#define BNA_CQ_PAGE_INDEX_MAX		(PAGE_SIZE >> 4)
-#define BNA_CQ_PAGE_INDEX_MAX_SHIFT	(PAGE_SHIFT - 4)
-
-#define BNA_CQ_QPGE_PTR_GET(_qe_idx, _qpt_ptr, _qe_ptr, _qe_ptr_range)	\
-{									\
-	unsigned int page_index;	  /* index within a page */	\
-	void *page_addr;						\
-									\
-	page_index = (_qe_idx) & (BNA_CQ_PAGE_INDEX_MAX - 1);		\
-	(_qe_ptr_range) = (BNA_CQ_PAGE_INDEX_MAX - page_index);		\
-	page_addr = (_qpt_ptr)[((_qe_idx) >>				\
-				    BNA_CQ_PAGE_INDEX_MAX_SHIFT)];	\
-	(_qe_ptr) = &((struct bna_cq_entry *)(page_addr))[page_index];\
-}
-
-#define BNA_QE_INDX_2_PTR(_cast, _qe_idx, _q_base)			\
-	(&((_cast *)(_q_base))[(_qe_idx)])
-
-#define BNA_QE_INDX_RANGE(_qe_idx, _q_depth) ((_q_depth) - (_qe_idx))
-
-#define BNA_QE_INDX_ADD(_qe_idx, _qe_num, _q_depth)			\
-	((_qe_idx) = ((_qe_idx) + (_qe_num)) & ((_q_depth) - 1))
-
-#define BNA_Q_INDEX_CHANGE(_old_idx, _updated_idx, _q_depth)		\
-	(((_updated_idx) - (_old_idx)) & ((_q_depth) - 1))
-
-#define BNA_QE_FREE_CNT(_q_ptr, _q_depth)				\
-	(((_q_ptr)->consumer_index - (_q_ptr)->producer_index - 1) &	\
-	 ((_q_depth) - 1))
-
-#define BNA_QE_IN_USE_CNT(_q_ptr, _q_depth)				\
-	((((_q_ptr)->producer_index - (_q_ptr)->consumer_index)) &	\
-	 (_q_depth - 1))
-
-#define BNA_Q_GET_CI(_q_ptr)		((_q_ptr)->q.consumer_index)
-
-#define BNA_Q_GET_PI(_q_ptr)		((_q_ptr)->q.producer_index)
-
-#define BNA_Q_PI_ADD(_q_ptr, _num)					\
-	(_q_ptr)->q.producer_index =					\
-		(((_q_ptr)->q.producer_index + (_num)) &		\
-		((_q_ptr)->q.q_depth - 1))
-
-#define BNA_Q_CI_ADD(_q_ptr, _num)					\
-	(_q_ptr)->q.consumer_index =					\
-		(((_q_ptr)->q.consumer_index + (_num))			\
-		& ((_q_ptr)->q.q_depth - 1))
-
-#define BNA_Q_FREE_COUNT(_q_ptr)					\
-	(BNA_QE_FREE_CNT(&((_q_ptr)->q), (_q_ptr)->q.q_depth))
-
-#define BNA_Q_IN_USE_COUNT(_q_ptr)					\
-	(BNA_QE_IN_USE_CNT(&(_q_ptr)->q, (_q_ptr)->q.q_depth))
-
-/* These macros build the data portion of the TxQ/RxQ doorbell */
-#define BNA_DOORBELL_Q_PRD_IDX(_pi)	(0x80000000 | (_pi))
-#define BNA_DOORBELL_Q_STOP		(0x40000000)
-
-/* These macros build the data portion of the IB doorbell */
-#define BNA_DOORBELL_IB_INT_ACK(_timeout, _events) \
-	(0x80000000 | ((_timeout) << 16) | (_events))
-#define BNA_DOORBELL_IB_INT_DISABLE	(0x40000000)
-
-/* Set the coalescing timer for the given ib */
-#define bna_ib_coalescing_timer_set(_i_dbell, _cls_timer)		\
-	((_i_dbell)->doorbell_ack = BNA_DOORBELL_IB_INT_ACK((_cls_timer), 0));
-
-/* Acks 'events' # of events for a given ib */
-#define bna_ib_ack(_i_dbell, _events)					\
-	(writel(((_i_dbell)->doorbell_ack | (_events)), \
-		(_i_dbell)->doorbell_addr));
-
-#define bna_txq_prod_indx_doorbell(_tcb)				\
-	(writel(BNA_DOORBELL_Q_PRD_IDX((_tcb)->producer_index), \
-		(_tcb)->q_dbell));
-
-#define bna_rxq_prod_indx_doorbell(_rcb)				\
-	(writel(BNA_DOORBELL_Q_PRD_IDX((_rcb)->producer_index), \
-		(_rcb)->q_dbell));
-
-#define BNA_LARGE_PKT_SIZE		1000
-
-#define BNA_UPDATE_PKT_CNT(_pkt, _len)					\
-do {									\
-	if ((_len) > BNA_LARGE_PKT_SIZE) {				\
-		(_pkt)->large_pkt_cnt++;				\
-	} else {							\
-		(_pkt)->small_pkt_cnt++;				\
-	}								\
-} while (0)
-
-#define	call_rxf_stop_cbfn(rxf, status)					\
-	if ((rxf)->stop_cbfn) {						\
-		(*(rxf)->stop_cbfn)((rxf)->stop_cbarg, (status));	\
-		(rxf)->stop_cbfn = NULL;				\
-		(rxf)->stop_cbarg = NULL;				\
-	}
-
-#define	call_rxf_start_cbfn(rxf, status)				\
-	if ((rxf)->start_cbfn) {					\
-		(*(rxf)->start_cbfn)((rxf)->start_cbarg, (status));	\
-		(rxf)->start_cbfn = NULL;				\
-		(rxf)->start_cbarg = NULL;				\
-	}
-
-#define	call_rxf_cam_fltr_cbfn(rxf, status)				\
-	if ((rxf)->cam_fltr_cbfn) {					\
-		(*(rxf)->cam_fltr_cbfn)((rxf)->cam_fltr_cbarg, rxf->rx,	\
-					(status));			\
-		(rxf)->cam_fltr_cbfn = NULL;				\
-		(rxf)->cam_fltr_cbarg = NULL;				\
-	}
-
-#define	call_rxf_pause_cbfn(rxf, status)				\
-	if ((rxf)->oper_state_cbfn) {					\
-		(*(rxf)->oper_state_cbfn)((rxf)->oper_state_cbarg, rxf->rx,\
-					(status));			\
-		(rxf)->rxf_flags &= ~BNA_RXF_FL_OPERSTATE_CHANGED;	\
-		(rxf)->oper_state_cbfn = NULL;				\
-		(rxf)->oper_state_cbarg = NULL;				\
-	}
-
-#define	call_rxf_resume_cbfn(rxf, status) call_rxf_pause_cbfn(rxf, status)
-
-#define is_xxx_enable(mode, bitmask, xxx) ((bitmask & xxx) && (mode & xxx))
-
-#define is_xxx_disable(mode, bitmask, xxx) ((bitmask & xxx) && !(mode & xxx))
-
-#define xxx_enable(mode, bitmask, xxx)					\
-do {									\
-	bitmask |= xxx;							\
-	mode |= xxx;							\
-} while (0)
-
-#define xxx_disable(mode, bitmask, xxx)					\
-do {									\
-	bitmask |= xxx;							\
-	mode &= ~xxx;							\
-} while (0)
-
-#define xxx_inactive(mode, bitmask, xxx)				\
-do {									\
-	bitmask &= ~xxx;						\
-	mode &= ~xxx;							\
-} while (0)
-
-#define is_promisc_enable(mode, bitmask)				\
-	is_xxx_enable(mode, bitmask, BNA_RXMODE_PROMISC)
-
-#define is_promisc_disable(mode, bitmask)				\
-	is_xxx_disable(mode, bitmask, BNA_RXMODE_PROMISC)
-
-#define promisc_enable(mode, bitmask)					\
-	xxx_enable(mode, bitmask, BNA_RXMODE_PROMISC)
-
-#define promisc_disable(mode, bitmask)					\
-	xxx_disable(mode, bitmask, BNA_RXMODE_PROMISC)
-
-#define promisc_inactive(mode, bitmask)					\
-	xxx_inactive(mode, bitmask, BNA_RXMODE_PROMISC)
-
-#define is_default_enable(mode, bitmask)				\
-	is_xxx_enable(mode, bitmask, BNA_RXMODE_DEFAULT)
-
-#define is_default_disable(mode, bitmask)				\
-	is_xxx_disable(mode, bitmask, BNA_RXMODE_DEFAULT)
-
-#define default_enable(mode, bitmask)					\
-	xxx_enable(mode, bitmask, BNA_RXMODE_DEFAULT)
-
-#define default_disable(mode, bitmask)					\
-	xxx_disable(mode, bitmask, BNA_RXMODE_DEFAULT)
-
-#define default_inactive(mode, bitmask)					\
-	xxx_inactive(mode, bitmask, BNA_RXMODE_DEFAULT)
-
-#define is_allmulti_enable(mode, bitmask)				\
-	is_xxx_enable(mode, bitmask, BNA_RXMODE_ALLMULTI)
-
-#define is_allmulti_disable(mode, bitmask)				\
-	is_xxx_disable(mode, bitmask, BNA_RXMODE_ALLMULTI)
-
-#define allmulti_enable(mode, bitmask)					\
-	xxx_enable(mode, bitmask, BNA_RXMODE_ALLMULTI)
-
-#define allmulti_disable(mode, bitmask)					\
-	xxx_disable(mode, bitmask, BNA_RXMODE_ALLMULTI)
-
-#define allmulti_inactive(mode, bitmask)				\
-	xxx_inactive(mode, bitmask, BNA_RXMODE_ALLMULTI)
-
-#define	GET_RXQS(rxp, q0, q1)	do {					\
-	switch ((rxp)->type) {						\
-	case BNA_RXP_SINGLE:						\
-		(q0) = rxp->rxq.single.only;				\
-		(q1) = NULL;						\
-		break;							\
-	case BNA_RXP_SLR:						\
-		(q0) = rxp->rxq.slr.large;				\
-		(q1) = rxp->rxq.slr.small;				\
-		break;							\
-	case BNA_RXP_HDS:						\
-		(q0) = rxp->rxq.hds.data;				\
-		(q1) = rxp->rxq.hds.hdr;				\
-		break;							\
-	}								\
-} while (0)
-
-/**
- *
- * Function prototypes
- *
- */
-
-/**
- * BNA
- */
-
-/* APIs for BNAD */
-void bna_res_req(struct bna_res_info *res_info);
-void bna_init(struct bna *bna, struct bnad *bnad,
-			struct bfa_pcidev *pcidev,
-			struct bna_res_info *res_info);
-void bna_uninit(struct bna *bna);
-void bna_stats_get(struct bna *bna);
-void bna_get_perm_mac(struct bna *bna, u8 *mac);
-
-/* APIs for Rx */
-int bna_rit_mod_can_satisfy(struct bna_rit_mod *rit_mod, int seg_size);
-
-/* APIs for RxF */
-struct bna_mac *bna_ucam_mod_mac_get(struct bna_ucam_mod *ucam_mod);
-void bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod,
-			  struct bna_mac *mac);
-struct bna_mac *bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod);
-void bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod,
-			  struct bna_mac *mac);
-struct bna_rit_segment *
-bna_rit_mod_seg_get(struct bna_rit_mod *rit_mod, int seg_size);
-void bna_rit_mod_seg_put(struct bna_rit_mod *rit_mod,
-			struct bna_rit_segment *seg);
-
-/**
- * DEVICE
- */
-
-/* APIs for BNAD */
-void bna_device_enable(struct bna_device *device);
-void bna_device_disable(struct bna_device *device,
-			enum bna_cleanup_type type);
-
-/**
- * MBOX
- */
-
-/* APIs for PORT, TX, RX */
-void bna_mbox_handler(struct bna *bna, u32 intr_status);
-void bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe);
-
-/**
- * PORT
- */
-
-/* API for RX */
-int bna_port_mtu_get(struct bna_port *port);
-void bna_llport_rx_started(struct bna_llport *llport);
-void bna_llport_rx_stopped(struct bna_llport *llport);
-
-/* API for BNAD */
-void bna_port_enable(struct bna_port *port);
-void bna_port_disable(struct bna_port *port, enum bna_cleanup_type type,
-		      void (*cbfn)(void *, enum bna_cb_status));
-void bna_port_pause_config(struct bna_port *port,
-			   struct bna_pause_config *pause_config,
-			   void (*cbfn)(struct bnad *, enum bna_cb_status));
-void bna_port_mtu_set(struct bna_port *port, int mtu,
-		      void (*cbfn)(struct bnad *, enum bna_cb_status));
-void bna_port_mac_get(struct bna_port *port, mac_t *mac);
-
-/* Callbacks for TX, RX */
-void bna_port_cb_tx_stopped(struct bna_port *port,
-			    enum bna_cb_status status);
-void bna_port_cb_rx_stopped(struct bna_port *port,
-			    enum bna_cb_status status);
-
-/**
- * IB
- */
-
-/* APIs for BNA */
-void bna_ib_mod_init(struct bna_ib_mod *ib_mod, struct bna *bna,
-		     struct bna_res_info *res_info);
-void bna_ib_mod_uninit(struct bna_ib_mod *ib_mod);
-
-/**
- * TX MODULE AND TX
- */
-
-/* APIs for BNA */
-void bna_tx_mod_init(struct bna_tx_mod *tx_mod, struct bna *bna,
-		     struct bna_res_info *res_info);
-void bna_tx_mod_uninit(struct bna_tx_mod *tx_mod);
-int bna_tx_state_get(struct bna_tx *tx);
-
-/* APIs for PORT */
-void bna_tx_mod_start(struct bna_tx_mod *tx_mod, enum bna_tx_type type);
-void bna_tx_mod_stop(struct bna_tx_mod *tx_mod, enum bna_tx_type type);
-void bna_tx_mod_fail(struct bna_tx_mod *tx_mod);
-void bna_tx_mod_prio_changed(struct bna_tx_mod *tx_mod, int prio);
-void bna_tx_mod_cee_link_status(struct bna_tx_mod *tx_mod, int cee_link);
-
-/* APIs for BNAD */
-void bna_tx_res_req(int num_txq, int txq_depth,
-		    struct bna_res_info *res_info);
-struct bna_tx *bna_tx_create(struct bna *bna, struct bnad *bnad,
-			       struct bna_tx_config *tx_cfg,
-			       struct bna_tx_event_cbfn *tx_cbfn,
-			       struct bna_res_info *res_info, void *priv);
-void bna_tx_destroy(struct bna_tx *tx);
-void bna_tx_enable(struct bna_tx *tx);
-void bna_tx_disable(struct bna_tx *tx, enum bna_cleanup_type type,
-		    void (*cbfn)(void *, struct bna_tx *,
-				 enum bna_cb_status));
-void bna_tx_coalescing_timeo_set(struct bna_tx *tx, int coalescing_timeo);
-
-/**
- * RX MODULE, RX, RXF
- */
-
-/* Internal APIs */
-void rxf_cb_cam_fltr_mbox_cmd(void *arg, int status);
-void rxf_cam_mbox_cmd(struct bna_rxf *rxf, u8 cmd,
-		const struct bna_mac *mac_addr);
-void __rxf_vlan_filter_set(struct bna_rxf *rxf, enum bna_status status);
-void bna_rxf_adv_init(struct bna_rxf *rxf,
-		struct bna_rx *rx,
-		struct bna_rx_config *q_config);
-int rxf_process_packet_filter_ucast(struct bna_rxf *rxf);
-int rxf_process_packet_filter_promisc(struct bna_rxf *rxf);
-int rxf_process_packet_filter_default(struct bna_rxf *rxf);
-int rxf_process_packet_filter_allmulti(struct bna_rxf *rxf);
-int rxf_clear_packet_filter_ucast(struct bna_rxf *rxf);
-int rxf_clear_packet_filter_promisc(struct bna_rxf *rxf);
-int rxf_clear_packet_filter_default(struct bna_rxf *rxf);
-int rxf_clear_packet_filter_allmulti(struct bna_rxf *rxf);
-void rxf_reset_packet_filter_ucast(struct bna_rxf *rxf);
-void rxf_reset_packet_filter_promisc(struct bna_rxf *rxf);
-void rxf_reset_packet_filter_default(struct bna_rxf *rxf);
-void rxf_reset_packet_filter_allmulti(struct bna_rxf *rxf);
-
-/* APIs for BNA */
-void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna,
-		     struct bna_res_info *res_info);
-void bna_rx_mod_uninit(struct bna_rx_mod *rx_mod);
-int bna_rx_state_get(struct bna_rx *rx);
-int bna_rxf_state_get(struct bna_rxf *rxf);
-
-/* APIs for PORT */
-void bna_rx_mod_start(struct bna_rx_mod *rx_mod, enum bna_rx_type type);
-void bna_rx_mod_stop(struct bna_rx_mod *rx_mod, enum bna_rx_type type);
-void bna_rx_mod_fail(struct bna_rx_mod *rx_mod);
-
-/* APIs for BNAD */
-void bna_rx_res_req(struct bna_rx_config *rx_config,
-		    struct bna_res_info *res_info);
-struct bna_rx *bna_rx_create(struct bna *bna, struct bnad *bnad,
-			       struct bna_rx_config *rx_cfg,
-			       struct bna_rx_event_cbfn *rx_cbfn,
-			       struct bna_res_info *res_info, void *priv);
-void bna_rx_destroy(struct bna_rx *rx);
-void bna_rx_enable(struct bna_rx *rx);
-void bna_rx_disable(struct bna_rx *rx, enum bna_cleanup_type type,
-		    void (*cbfn)(void *, struct bna_rx *,
-				 enum bna_cb_status));
-void bna_rx_coalescing_timeo_set(struct bna_rx *rx, int coalescing_timeo);
-void bna_rx_dim_reconfig(struct bna *bna, const u32 vector[][BNA_BIAS_T_MAX]);
-void bna_rx_dim_update(struct bna_ccb *ccb);
-enum bna_cb_status
-bna_rx_ucast_set(struct bna_rx *rx, u8 *ucmac,
-		 void (*cbfn)(struct bnad *, struct bna_rx *,
-			      enum bna_cb_status));
-enum bna_cb_status
-bna_rx_mcast_add(struct bna_rx *rx, u8 *mcmac,
-		 void (*cbfn)(struct bnad *, struct bna_rx *,
-			      enum bna_cb_status));
-enum bna_cb_status
-bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mcmac,
-		     void (*cbfn)(struct bnad *, struct bna_rx *,
-				  enum bna_cb_status));
-enum bna_cb_status
-bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode rxmode,
-		enum bna_rxmode bitmask,
-		void (*cbfn)(struct bnad *, struct bna_rx *,
-			     enum bna_cb_status));
-void bna_rx_vlan_add(struct bna_rx *rx, int vlan_id);
-void bna_rx_vlan_del(struct bna_rx *rx, int vlan_id);
-void bna_rx_vlanfilter_enable(struct bna_rx *rx);
-void bna_rx_hds_enable(struct bna_rx *rx, struct bna_rxf_hds *hds_config,
-		       void (*cbfn)(struct bnad *, struct bna_rx *,
-				    enum bna_cb_status));
-void bna_rx_hds_disable(struct bna_rx *rx,
-			void (*cbfn)(struct bnad *, struct bna_rx *,
-				     enum bna_cb_status));
-
-/**
- * BNAD
- */
-
-/* Callbacks for BNA */
-void bnad_cb_stats_get(struct bnad *bnad, enum bna_cb_status status,
-		       struct bna_stats *stats);
-
-/* Callbacks for DEVICE */
-void bnad_cb_device_enabled(struct bnad *bnad, enum bna_cb_status status);
-void bnad_cb_device_disabled(struct bnad *bnad, enum bna_cb_status status);
-void bnad_cb_device_enable_mbox_intr(struct bnad *bnad);
-void bnad_cb_device_disable_mbox_intr(struct bnad *bnad);
-
-/* Callbacks for port */
-void bnad_cb_port_link_status(struct bnad *bnad,
-			      enum bna_link_status status);
-
-#endif  /* __BNA_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bna_hw.h linux-libre-3.2-gnu/drivers/net/bna/bna_hw.h
--- linux-libre-3.1-gnu/drivers/net/bna/bna_hw.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bna_hw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1490 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * File for interrupt macros and functions
- */
-
-#ifndef __BNA_HW_H__
-#define __BNA_HW_H__
-
-#include "bfi_ctreg.h"
-
-/**
- *
- * SW imposed limits
- *
- */
-
-#ifndef BNA_BIOS_BUILD
-
-#define BFI_MAX_TXQ			64
-#define BFI_MAX_RXQ			64
-#define	BFI_MAX_RXF			64
-#define BFI_MAX_IB			128
-#define	BFI_MAX_RIT_SIZE		256
-#define	BFI_RSS_RIT_SIZE		64
-#define	BFI_NONRSS_RIT_SIZE		1
-#define BFI_MAX_UCMAC			256
-#define BFI_MAX_MCMAC			512
-#define BFI_IBIDX_SIZE			4
-#define BFI_MAX_VLAN			4095
-
-/**
- * There are 2 free IB index pools:
- *	pool1: 120 segments of 1 index each
- *	pool8: 1 segment of 8 indexes
- */
-#define BFI_IBIDX_POOL1_SIZE		116
-#define	BFI_IBIDX_POOL1_ENTRY_SIZE	1
-#define BFI_IBIDX_POOL2_SIZE		2
-#define	BFI_IBIDX_POOL2_ENTRY_SIZE	2
-#define	BFI_IBIDX_POOL8_SIZE		1
-#define	BFI_IBIDX_POOL8_ENTRY_SIZE	8
-#define	BFI_IBIDX_TOTAL_POOLS		3
-#define	BFI_IBIDX_TOTAL_SEGS		119 /* (POOL1 + POOL2 + POOL8)_SIZE */
-#define	BFI_IBIDX_MAX_SEGSIZE		8
-#define init_ibidx_pool(name)						\
-static struct bna_ibidx_pool name[BFI_IBIDX_TOTAL_POOLS] =		\
-{									\
-	{ BFI_IBIDX_POOL1_SIZE, BFI_IBIDX_POOL1_ENTRY_SIZE },		\
-	{ BFI_IBIDX_POOL2_SIZE, BFI_IBIDX_POOL2_ENTRY_SIZE },		\
-	{ BFI_IBIDX_POOL8_SIZE, BFI_IBIDX_POOL8_ENTRY_SIZE }		\
-}
-
-/**
- * There are 2 free RIT segment pools:
- *	Pool1: 192 segments of 1 RIT entry each
- *	Pool2: 1 segment of 64 RIT entry
- */
-#define BFI_RIT_SEG_POOL1_SIZE		192
-#define BFI_RIT_SEG_POOL1_ENTRY_SIZE	1
-#define BFI_RIT_SEG_POOLRSS_SIZE	1
-#define BFI_RIT_SEG_POOLRSS_ENTRY_SIZE	64
-#define BFI_RIT_SEG_TOTAL_POOLS		2
-#define BFI_RIT_TOTAL_SEGS		193 /* POOL1_SIZE + POOLRSS_SIZE */
-#define init_ritseg_pool(name)						\
-static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] =	\
-{									\
-	{ BFI_RIT_SEG_POOL1_SIZE, BFI_RIT_SEG_POOL1_ENTRY_SIZE },	\
-	{ BFI_RIT_SEG_POOLRSS_SIZE, BFI_RIT_SEG_POOLRSS_ENTRY_SIZE }	\
-}
-
-#else /* BNA_BIOS_BUILD */
-
-#define BFI_MAX_TXQ			1
-#define BFI_MAX_RXQ			1
-#define	BFI_MAX_RXF			1
-#define BFI_MAX_IB			2
-#define	BFI_MAX_RIT_SIZE		2
-#define	BFI_RSS_RIT_SIZE		64
-#define	BFI_NONRSS_RIT_SIZE		1
-#define BFI_MAX_UCMAC			1
-#define BFI_MAX_MCMAC			8
-#define BFI_IBIDX_SIZE			4
-#define BFI_MAX_VLAN			4095
-/* There is one free pool: 2 segments of 1 index each */
-#define BFI_IBIDX_POOL1_SIZE		2
-#define	BFI_IBIDX_POOL1_ENTRY_SIZE	1
-#define	BFI_IBIDX_TOTAL_POOLS		1
-#define	BFI_IBIDX_TOTAL_SEGS		2 /* POOL1_SIZE */
-#define	BFI_IBIDX_MAX_SEGSIZE		1
-#define init_ibidx_pool(name)						\
-static struct bna_ibidx_pool name[BFI_IBIDX_TOTAL_POOLS] =		\
-{									\
-	{ BFI_IBIDX_POOL1_SIZE, BFI_IBIDX_POOL1_ENTRY_SIZE }		\
-}
-
-#define BFI_RIT_SEG_POOL1_SIZE		1
-#define BFI_RIT_SEG_POOL1_ENTRY_SIZE	1
-#define BFI_RIT_SEG_TOTAL_POOLS		1
-#define BFI_RIT_TOTAL_SEGS		1 /* POOL1_SIZE */
-#define init_ritseg_pool(name)						\
-static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] =	\
-{									\
-	{ BFI_RIT_SEG_POOL1_SIZE, BFI_RIT_SEG_POOL1_ENTRY_SIZE }	\
-}
-
-#endif /* BNA_BIOS_BUILD */
-
-#define BFI_RSS_HASH_KEY_LEN		10
-
-#define BFI_COALESCING_TIMER_UNIT	5	/* 5us */
-#define BFI_MAX_COALESCING_TIMEO	0xFF	/* in 5us units */
-#define BFI_MAX_INTERPKT_COUNT		0xFF
-#define BFI_MAX_INTERPKT_TIMEO		0xF	/* in 0.5us units */
-#define BFI_TX_COALESCING_TIMEO		20	/* 20 * 5 = 100us */
-#define BFI_TX_INTERPKT_COUNT		32
-#define	BFI_RX_COALESCING_TIMEO		12	/* 12 * 5 = 60us */
-#define	BFI_RX_INTERPKT_COUNT		6	/* Pkt Cnt = 6 */
-#define	BFI_RX_INTERPKT_TIMEO		3	/* 3 * 0.5 = 1.5us */
-
-#define BFI_TXQ_WI_SIZE			64	/* bytes */
-#define BFI_RXQ_WI_SIZE			8	/* bytes */
-#define BFI_CQ_WI_SIZE			16	/* bytes */
-#define BFI_TX_MAX_WRR_QUOTA		0xFFF
-
-#define BFI_TX_MAX_VECTORS_PER_WI	4
-#define BFI_TX_MAX_VECTORS_PER_PKT	0xFF
-#define BFI_TX_MAX_DATA_PER_VECTOR	0xFFFF
-#define BFI_TX_MAX_DATA_PER_PKT		0xFFFFFF
-
-/* Small Q buffer size */
-#define BFI_SMALL_RXBUF_SIZE		128
-
-/* Defined separately since BFA_FLASH_DMA_BUF_SZ is in bfa_flash.c */
-#define BFI_FLASH_DMA_BUF_SZ		0x010000 /* 64K DMA */
-#define BFI_HW_STATS_SIZE		0x4000 /* 16K DMA */
-
-/**
- *
- * HW register offsets, macros
- *
- */
-
-/* DMA Block Register Host Window Start Address */
-#define DMA_BLK_REG_ADDR		0x00013000
-
-/* DMA Block Internal Registers */
-#define DMA_CTRL_REG0			(DMA_BLK_REG_ADDR + 0x000)
-#define DMA_CTRL_REG1			(DMA_BLK_REG_ADDR + 0x004)
-#define DMA_ERR_INT_STATUS		(DMA_BLK_REG_ADDR + 0x008)
-#define DMA_ERR_INT_ENABLE		(DMA_BLK_REG_ADDR + 0x00c)
-#define DMA_ERR_INT_STATUS_SET		(DMA_BLK_REG_ADDR + 0x010)
-
-/* APP Block Register Address Offset from BAR0 */
-#define APP_BLK_REG_ADDR		0x00014000
-
-/* Host Function Interrupt Mask Registers */
-#define HOSTFN0_INT_MASK		(APP_BLK_REG_ADDR + 0x004)
-#define HOSTFN1_INT_MASK		(APP_BLK_REG_ADDR + 0x104)
-#define HOSTFN2_INT_MASK		(APP_BLK_REG_ADDR + 0x304)
-#define HOSTFN3_INT_MASK		(APP_BLK_REG_ADDR + 0x404)
-
-/**
- * Host Function PCIe Error Registers
- * Duplicates "Correctable" & "Uncorrectable"
- * registers in PCIe Config space.
- */
-#define FN0_PCIE_ERR_REG		(APP_BLK_REG_ADDR + 0x014)
-#define FN1_PCIE_ERR_REG		(APP_BLK_REG_ADDR + 0x114)
-#define FN2_PCIE_ERR_REG		(APP_BLK_REG_ADDR + 0x314)
-#define FN3_PCIE_ERR_REG		(APP_BLK_REG_ADDR + 0x414)
-
-/* Host Function Error Type Status Registers */
-#define FN0_ERR_TYPE_STATUS_REG		(APP_BLK_REG_ADDR + 0x018)
-#define FN1_ERR_TYPE_STATUS_REG		(APP_BLK_REG_ADDR + 0x118)
-#define FN2_ERR_TYPE_STATUS_REG		(APP_BLK_REG_ADDR + 0x318)
-#define FN3_ERR_TYPE_STATUS_REG		(APP_BLK_REG_ADDR + 0x418)
-
-/* Host Function Error Type Mask Registers */
-#define FN0_ERR_TYPE_MSK_STATUS_REG	(APP_BLK_REG_ADDR + 0x01c)
-#define FN1_ERR_TYPE_MSK_STATUS_REG	(APP_BLK_REG_ADDR + 0x11c)
-#define FN2_ERR_TYPE_MSK_STATUS_REG	(APP_BLK_REG_ADDR + 0x31c)
-#define FN3_ERR_TYPE_MSK_STATUS_REG	(APP_BLK_REG_ADDR + 0x41c)
-
-/* Catapult Host Semaphore Status Registers (App block) */
-#define HOST_SEM_STS0_REG		(APP_BLK_REG_ADDR + 0x630)
-#define HOST_SEM_STS1_REG		(APP_BLK_REG_ADDR + 0x634)
-#define HOST_SEM_STS2_REG		(APP_BLK_REG_ADDR + 0x638)
-#define HOST_SEM_STS3_REG		(APP_BLK_REG_ADDR + 0x63c)
-#define HOST_SEM_STS4_REG		(APP_BLK_REG_ADDR + 0x640)
-#define HOST_SEM_STS5_REG		(APP_BLK_REG_ADDR + 0x644)
-#define HOST_SEM_STS6_REG		(APP_BLK_REG_ADDR + 0x648)
-#define HOST_SEM_STS7_REG		(APP_BLK_REG_ADDR + 0x64c)
-
-/* PCIe Misc Register */
-#define PCIE_MISC_REG			(APP_BLK_REG_ADDR + 0x200)
-
-/* Temp Sensor Control Registers */
-#define TEMPSENSE_CNTL_REG		(APP_BLK_REG_ADDR + 0x250)
-#define TEMPSENSE_STAT_REG		(APP_BLK_REG_ADDR + 0x254)
-
-/* APP Block local error registers */
-#define APP_LOCAL_ERR_STAT		(APP_BLK_REG_ADDR + 0x258)
-#define APP_LOCAL_ERR_MSK		(APP_BLK_REG_ADDR + 0x25c)
-
-/* PCIe Link Error registers */
-#define PCIE_LNK_ERR_STAT		(APP_BLK_REG_ADDR + 0x260)
-#define PCIE_LNK_ERR_MSK		(APP_BLK_REG_ADDR + 0x264)
-
-/**
- * FCoE/FIP Ethertype Register
- * 31:16 -- Chip wide value for FIP type
- * 15:0  -- Chip wide value for FCoE type
- */
-#define FCOE_FIP_ETH_TYPE		(APP_BLK_REG_ADDR + 0x280)
-
-/**
- * Reserved Ethertype Register
- * 31:16 -- Reserved
- * 15:0  -- Other ethertype
- */
-#define RESV_ETH_TYPE			(APP_BLK_REG_ADDR + 0x284)
-
-/**
- * Host Command Status Registers
- * Each set consists of 3 registers :
- * clear, set, cmd
- * 16 such register sets in all
- * See catapult_spec.pdf for detailed functionality
- * Put each type in a single macro accessed by _num ?
- */
-#define HOST_CMDSTS0_CLR_REG		(APP_BLK_REG_ADDR + 0x500)
-#define HOST_CMDSTS0_SET_REG		(APP_BLK_REG_ADDR + 0x504)
-#define HOST_CMDSTS0_REG		(APP_BLK_REG_ADDR + 0x508)
-#define HOST_CMDSTS1_CLR_REG		(APP_BLK_REG_ADDR + 0x510)
-#define HOST_CMDSTS1_SET_REG		(APP_BLK_REG_ADDR + 0x514)
-#define HOST_CMDSTS1_REG		(APP_BLK_REG_ADDR + 0x518)
-#define HOST_CMDSTS2_CLR_REG		(APP_BLK_REG_ADDR + 0x520)
-#define HOST_CMDSTS2_SET_REG		(APP_BLK_REG_ADDR + 0x524)
-#define HOST_CMDSTS2_REG		(APP_BLK_REG_ADDR + 0x528)
-#define HOST_CMDSTS3_CLR_REG		(APP_BLK_REG_ADDR + 0x530)
-#define HOST_CMDSTS3_SET_REG		(APP_BLK_REG_ADDR + 0x534)
-#define HOST_CMDSTS3_REG		(APP_BLK_REG_ADDR + 0x538)
-#define HOST_CMDSTS4_CLR_REG		(APP_BLK_REG_ADDR + 0x540)
-#define HOST_CMDSTS4_SET_REG		(APP_BLK_REG_ADDR + 0x544)
-#define HOST_CMDSTS4_REG		(APP_BLK_REG_ADDR + 0x548)
-#define HOST_CMDSTS5_CLR_REG		(APP_BLK_REG_ADDR + 0x550)
-#define HOST_CMDSTS5_SET_REG		(APP_BLK_REG_ADDR + 0x554)
-#define HOST_CMDSTS5_REG		(APP_BLK_REG_ADDR + 0x558)
-#define HOST_CMDSTS6_CLR_REG		(APP_BLK_REG_ADDR + 0x560)
-#define HOST_CMDSTS6_SET_REG		(APP_BLK_REG_ADDR + 0x564)
-#define HOST_CMDSTS6_REG		(APP_BLK_REG_ADDR + 0x568)
-#define HOST_CMDSTS7_CLR_REG		(APP_BLK_REG_ADDR + 0x570)
-#define HOST_CMDSTS7_SET_REG		(APP_BLK_REG_ADDR + 0x574)
-#define HOST_CMDSTS7_REG		(APP_BLK_REG_ADDR + 0x578)
-#define HOST_CMDSTS8_CLR_REG		(APP_BLK_REG_ADDR + 0x580)
-#define HOST_CMDSTS8_SET_REG		(APP_BLK_REG_ADDR + 0x584)
-#define HOST_CMDSTS8_REG		(APP_BLK_REG_ADDR + 0x588)
-#define HOST_CMDSTS9_CLR_REG		(APP_BLK_REG_ADDR + 0x590)
-#define HOST_CMDSTS9_SET_REG		(APP_BLK_REG_ADDR + 0x594)
-#define HOST_CMDSTS9_REG		(APP_BLK_REG_ADDR + 0x598)
-#define HOST_CMDSTS10_CLR_REG		(APP_BLK_REG_ADDR + 0x5A0)
-#define HOST_CMDSTS10_SET_REG		(APP_BLK_REG_ADDR + 0x5A4)
-#define HOST_CMDSTS10_REG		(APP_BLK_REG_ADDR + 0x5A8)
-#define HOST_CMDSTS11_CLR_REG		(APP_BLK_REG_ADDR + 0x5B0)
-#define HOST_CMDSTS11_SET_REG		(APP_BLK_REG_ADDR + 0x5B4)
-#define HOST_CMDSTS11_REG		(APP_BLK_REG_ADDR + 0x5B8)
-#define HOST_CMDSTS12_CLR_REG		(APP_BLK_REG_ADDR + 0x5C0)
-#define HOST_CMDSTS12_SET_REG		(APP_BLK_REG_ADDR + 0x5C4)
-#define HOST_CMDSTS12_REG		(APP_BLK_REG_ADDR + 0x5C8)
-#define HOST_CMDSTS13_CLR_REG		(APP_BLK_REG_ADDR + 0x5D0)
-#define HOST_CMDSTS13_SET_REG		(APP_BLK_REG_ADDR + 0x5D4)
-#define HOST_CMDSTS13_REG		(APP_BLK_REG_ADDR + 0x5D8)
-#define HOST_CMDSTS14_CLR_REG		(APP_BLK_REG_ADDR + 0x5E0)
-#define HOST_CMDSTS14_SET_REG		(APP_BLK_REG_ADDR + 0x5E4)
-#define HOST_CMDSTS14_REG		(APP_BLK_REG_ADDR + 0x5E8)
-#define HOST_CMDSTS15_CLR_REG		(APP_BLK_REG_ADDR + 0x5F0)
-#define HOST_CMDSTS15_SET_REG		(APP_BLK_REG_ADDR + 0x5F4)
-#define HOST_CMDSTS15_REG		(APP_BLK_REG_ADDR + 0x5F8)
-
-/**
- * LPU0 Block Register Address Offset from BAR0
- * Range 0x18000 - 0x18033
- */
-#define LPU0_BLK_REG_ADDR		0x00018000
-
-/**
- * LPU0 Registers
- * Should they be directly used from host,
- * except for diagnostics ?
- * CTL_REG : Control register
- * CMD_REG : Triggers exec. of cmd. in
- *           Mailbox memory
- */
-#define LPU0_MBOX_CTL_REG		(LPU0_BLK_REG_ADDR + 0x000)
-#define LPU0_MBOX_CMD_REG		(LPU0_BLK_REG_ADDR + 0x004)
-#define LPU0_MBOX_LINK_0REG		(LPU0_BLK_REG_ADDR + 0x008)
-#define LPU1_MBOX_LINK_0REG		(LPU0_BLK_REG_ADDR + 0x00c)
-#define LPU0_MBOX_STATUS_0REG		(LPU0_BLK_REG_ADDR + 0x010)
-#define LPU1_MBOX_STATUS_0REG		(LPU0_BLK_REG_ADDR + 0x014)
-#define LPU0_ERR_STATUS_REG		(LPU0_BLK_REG_ADDR + 0x018)
-#define LPU0_ERR_SET_REG		(LPU0_BLK_REG_ADDR + 0x020)
-
-/**
- * LPU1 Block Register Address Offset from BAR0
- * Range 0x18400 - 0x18433
- */
-#define LPU1_BLK_REG_ADDR		0x00018400
-
-/**
- * LPU1 Registers
- * Same as LPU0 registers above
- */
-#define LPU1_MBOX_CTL_REG		(LPU1_BLK_REG_ADDR + 0x000)
-#define LPU1_MBOX_CMD_REG		(LPU1_BLK_REG_ADDR + 0x004)
-#define LPU0_MBOX_LINK_1REG		(LPU1_BLK_REG_ADDR + 0x008)
-#define LPU1_MBOX_LINK_1REG		(LPU1_BLK_REG_ADDR + 0x00c)
-#define LPU0_MBOX_STATUS_1REG		(LPU1_BLK_REG_ADDR + 0x010)
-#define LPU1_MBOX_STATUS_1REG		(LPU1_BLK_REG_ADDR + 0x014)
-#define LPU1_ERR_STATUS_REG		(LPU1_BLK_REG_ADDR + 0x018)
-#define LPU1_ERR_SET_REG		(LPU1_BLK_REG_ADDR + 0x020)
-
-/**
- * PSS Block Register Address Offset from BAR0
- * Range 0x18800 - 0x188DB
- */
-#define PSS_BLK_REG_ADDR		0x00018800
-
-/**
- * PSS Registers
- * For details, see catapult_spec.pdf
- * ERR_STATUS_REG : Indicates error in PSS module
- * RAM_ERR_STATUS_REG : Indicates RAM module that detected error
- */
-#define ERR_STATUS_SET			(PSS_BLK_REG_ADDR + 0x018)
-#define PSS_RAM_ERR_STATUS_REG		(PSS_BLK_REG_ADDR + 0x01C)
-
-/**
- * PSS Semaphore Lock Registers, total 16
- * First read when unlocked returns 0,
- * and is set to 1, atomically.
- * Subsequent reads returns 1.
- * To clear set the value to 0.
- * Range : 0x20 to 0x5c
- */
-#define PSS_SEM_LOCK_REG(_num)		\
-	(PSS_BLK_REG_ADDR + 0x020 + ((_num) << 2))
-
-/**
- * PSS Semaphore Status Registers,
- * corresponding to the lock registers above
- */
-#define PSS_SEM_STATUS_REG(_num)		\
-	(PSS_BLK_REG_ADDR + 0x060 + ((_num) << 2))
-
-/**
- * Catapult CPQ Registers
- * Defines for Mailbox Registers
- * Used to send mailbox commands to firmware from
- * host. The data part is written to the MBox
- * memory, registers are used to indicate that
- * a commnad is resident in memory.
- *
- * Note : LPU0<->LPU1 mailboxes are not listed here
- */
-#define CPQ_BLK_REG_ADDR		0x00019000
-
-#define HOSTFN0_LPU0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x130)
-#define HOSTFN0_LPU1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x134)
-#define LPU0_HOSTFN0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x138)
-#define LPU1_HOSTFN0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x13C)
-
-#define HOSTFN1_LPU0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x140)
-#define HOSTFN1_LPU1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x144)
-#define LPU0_HOSTFN1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x148)
-#define LPU1_HOSTFN1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x14C)
-
-#define HOSTFN2_LPU0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x170)
-#define HOSTFN2_LPU1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x174)
-#define LPU0_HOSTFN2_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x178)
-#define LPU1_HOSTFN2_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x17C)
-
-#define HOSTFN3_LPU0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x180)
-#define HOSTFN3_LPU1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x184)
-#define LPU0_HOSTFN3_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x188)
-#define LPU1_HOSTFN3_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x18C)
-
-/* Host Function Force Parity Error Registers */
-#define HOSTFN0_LPU_FORCE_PERR		(CPQ_BLK_REG_ADDR + 0x120)
-#define HOSTFN1_LPU_FORCE_PERR		(CPQ_BLK_REG_ADDR + 0x124)
-#define HOSTFN2_LPU_FORCE_PERR		(CPQ_BLK_REG_ADDR + 0x128)
-#define HOSTFN3_LPU_FORCE_PERR		(CPQ_BLK_REG_ADDR + 0x12C)
-
-/* LL Port[0|1] Halt Mask Registers */
-#define LL_HALT_MSK_P0			(CPQ_BLK_REG_ADDR + 0x1A0)
-#define LL_HALT_MSK_P1			(CPQ_BLK_REG_ADDR + 0x1B0)
-
-/* LL Port[0|1] Error Mask Registers */
-#define LL_ERR_MSK_P0			(CPQ_BLK_REG_ADDR + 0x1D0)
-#define LL_ERR_MSK_P1			(CPQ_BLK_REG_ADDR + 0x1D4)
-
-/* EMC FLI (Flash Controller) Block Register Address Offset from BAR0 */
-#define FLI_BLK_REG_ADDR		0x0001D000
-
-/* EMC FLI Registers */
-#define FLI_CMD_REG			(FLI_BLK_REG_ADDR + 0x000)
-#define FLI_ADDR_REG			(FLI_BLK_REG_ADDR + 0x004)
-#define FLI_CTL_REG			(FLI_BLK_REG_ADDR + 0x008)
-#define FLI_WRDATA_REG			(FLI_BLK_REG_ADDR + 0x00C)
-#define FLI_RDDATA_REG			(FLI_BLK_REG_ADDR + 0x010)
-#define FLI_DEV_STATUS_REG		(FLI_BLK_REG_ADDR + 0x014)
-#define FLI_SIG_WD_REG			(FLI_BLK_REG_ADDR + 0x018)
-
-/**
- * RO register
- * 31:16 -- Vendor Id
- * 15:0  -- Device Id
- */
-#define FLI_DEV_VENDOR_REG		(FLI_BLK_REG_ADDR + 0x01C)
-#define FLI_ERR_STATUS_REG		(FLI_BLK_REG_ADDR + 0x020)
-
-/**
- * RAD (RxAdm) Block Register Address Offset from BAR0
- * RAD0 Range : 0x20000 - 0x203FF
- * RAD1 Range : 0x20400 - 0x207FF
- */
-#define RAD0_BLK_REG_ADDR		0x00020000
-#define RAD1_BLK_REG_ADDR		0x00020400
-
-/* RAD0 Registers */
-#define RAD0_CTL_REG			(RAD0_BLK_REG_ADDR + 0x000)
-#define RAD0_PE_PARM_REG		(RAD0_BLK_REG_ADDR + 0x004)
-#define RAD0_BCN_REG			(RAD0_BLK_REG_ADDR + 0x008)
-
-/* Default function ID register */
-#define RAD0_DEFAULT_REG		(RAD0_BLK_REG_ADDR + 0x00C)
-
-/* Default promiscuous ID register */
-#define RAD0_PROMISC_REG		(RAD0_BLK_REG_ADDR + 0x010)
-
-#define RAD0_BCNQ_REG			(RAD0_BLK_REG_ADDR + 0x014)
-
-/*
- * This register selects 1 of 8 PM Q's using
- * VLAN pri, for non-BCN packets without a VLAN tag
- */
-#define RAD0_DEFAULTQ_REG		(RAD0_BLK_REG_ADDR + 0x018)
-
-#define RAD0_ERR_STS			(RAD0_BLK_REG_ADDR + 0x01C)
-#define RAD0_SET_ERR_STS		(RAD0_BLK_REG_ADDR + 0x020)
-#define RAD0_ERR_INT_EN			(RAD0_BLK_REG_ADDR + 0x024)
-#define RAD0_FIRST_ERR			(RAD0_BLK_REG_ADDR + 0x028)
-#define RAD0_FORCE_ERR			(RAD0_BLK_REG_ADDR + 0x02C)
-
-#define RAD0_IF_RCVD			(RAD0_BLK_REG_ADDR + 0x030)
-#define RAD0_IF_RCVD_OCTETS_HIGH	(RAD0_BLK_REG_ADDR + 0x034)
-#define RAD0_IF_RCVD_OCTETS_LOW		(RAD0_BLK_REG_ADDR + 0x038)
-#define RAD0_IF_RCVD_VLAN		(RAD0_BLK_REG_ADDR + 0x03C)
-#define RAD0_IF_RCVD_UCAST		(RAD0_BLK_REG_ADDR + 0x040)
-#define RAD0_IF_RCVD_UCAST_OCTETS_HIGH	(RAD0_BLK_REG_ADDR + 0x044)
-#define RAD0_IF_RCVD_UCAST_OCTETS_LOW   (RAD0_BLK_REG_ADDR + 0x048)
-#define RAD0_IF_RCVD_UCAST_VLAN		(RAD0_BLK_REG_ADDR + 0x04C)
-#define RAD0_IF_RCVD_MCAST		(RAD0_BLK_REG_ADDR + 0x050)
-#define RAD0_IF_RCVD_MCAST_OCTETS_HIGH  (RAD0_BLK_REG_ADDR + 0x054)
-#define RAD0_IF_RCVD_MCAST_OCTETS_LOW   (RAD0_BLK_REG_ADDR + 0x058)
-#define RAD0_IF_RCVD_MCAST_VLAN		(RAD0_BLK_REG_ADDR + 0x05C)
-#define RAD0_IF_RCVD_BCAST		(RAD0_BLK_REG_ADDR + 0x060)
-#define RAD0_IF_RCVD_BCAST_OCTETS_HIGH  (RAD0_BLK_REG_ADDR + 0x064)
-#define RAD0_IF_RCVD_BCAST_OCTETS_LOW   (RAD0_BLK_REG_ADDR + 0x068)
-#define RAD0_IF_RCVD_BCAST_VLAN		(RAD0_BLK_REG_ADDR + 0x06C)
-#define RAD0_DROPPED_FRAMES		(RAD0_BLK_REG_ADDR + 0x070)
-
-#define RAD0_MAC_MAN_1H			(RAD0_BLK_REG_ADDR + 0x080)
-#define RAD0_MAC_MAN_1L			(RAD0_BLK_REG_ADDR + 0x084)
-#define RAD0_MAC_MAN_2H			(RAD0_BLK_REG_ADDR + 0x088)
-#define RAD0_MAC_MAN_2L			(RAD0_BLK_REG_ADDR + 0x08C)
-#define RAD0_MAC_MAN_3H			(RAD0_BLK_REG_ADDR + 0x090)
-#define RAD0_MAC_MAN_3L			(RAD0_BLK_REG_ADDR + 0x094)
-#define RAD0_MAC_MAN_4H			(RAD0_BLK_REG_ADDR + 0x098)
-#define RAD0_MAC_MAN_4L			(RAD0_BLK_REG_ADDR + 0x09C)
-
-#define RAD0_LAST4_IP			(RAD0_BLK_REG_ADDR + 0x100)
-
-/* RAD1 Registers */
-#define RAD1_CTL_REG			(RAD1_BLK_REG_ADDR + 0x000)
-#define RAD1_PE_PARM_REG		(RAD1_BLK_REG_ADDR + 0x004)
-#define RAD1_BCN_REG			(RAD1_BLK_REG_ADDR + 0x008)
-
-/* Default function ID register */
-#define RAD1_DEFAULT_REG		(RAD1_BLK_REG_ADDR + 0x00C)
-
-/* Promiscuous function ID register */
-#define RAD1_PROMISC_REG		(RAD1_BLK_REG_ADDR + 0x010)
-
-#define RAD1_BCNQ_REG			(RAD1_BLK_REG_ADDR + 0x014)
-
-/*
- * This register selects 1 of 8 PM Q's using
- * VLAN pri, for non-BCN packets without a VLAN tag
- */
-#define RAD1_DEFAULTQ_REG		(RAD1_BLK_REG_ADDR + 0x018)
-
-#define RAD1_ERR_STS			(RAD1_BLK_REG_ADDR + 0x01C)
-#define RAD1_SET_ERR_STS		(RAD1_BLK_REG_ADDR + 0x020)
-#define RAD1_ERR_INT_EN			(RAD1_BLK_REG_ADDR + 0x024)
-
-/**
- * TXA Block Register Address Offset from BAR0
- * TXA0 Range : 0x21000 - 0x213FF
- * TXA1 Range : 0x21400 - 0x217FF
- */
-#define TXA0_BLK_REG_ADDR		0x00021000
-#define TXA1_BLK_REG_ADDR		0x00021400
-
-/* TXA Registers */
-#define TXA0_CTRL_REG			(TXA0_BLK_REG_ADDR + 0x000)
-#define TXA1_CTRL_REG			(TXA1_BLK_REG_ADDR + 0x000)
-
-/**
- * TSO Sequence # Registers (RO)
- * Total 8 (for 8 queues)
- * Holds the last seq.# for TSO frames
- * See catapult_spec.pdf for more details
- */
-#define TXA0_TSO_TCP_SEQ_REG(_num)		\
-	(TXA0_BLK_REG_ADDR + 0x020 + ((_num) << 2))
-
-#define TXA1_TSO_TCP_SEQ_REG(_num)		\
-	(TXA1_BLK_REG_ADDR + 0x020 + ((_num) << 2))
-
-/**
- * TSO IP ID # Registers (RO)
- * Total 8 (for 8 queues)
- * Holds the last IP ID for TSO frames
- * See catapult_spec.pdf for more details
- */
-#define TXA0_TSO_IP_INFO_REG(_num)		\
-	(TXA0_BLK_REG_ADDR + 0x040 + ((_num) << 2))
-
-#define TXA1_TSO_IP_INFO_REG(_num)		\
-	(TXA1_BLK_REG_ADDR + 0x040 + ((_num) << 2))
-
-/**
- * RXA Block Register Address Offset from BAR0
- * RXA0 Range : 0x21800 - 0x21BFF
- * RXA1 Range : 0x21C00 - 0x21FFF
- */
-#define RXA0_BLK_REG_ADDR		0x00021800
-#define RXA1_BLK_REG_ADDR		0x00021C00
-
-/* RXA Registers */
-#define RXA0_CTL_REG			(RXA0_BLK_REG_ADDR + 0x040)
-#define RXA1_CTL_REG			(RXA1_BLK_REG_ADDR + 0x040)
-
-/**
- * PPLB Block Register Address Offset from BAR0
- * PPLB0 Range : 0x22000 - 0x223FF
- * PPLB1 Range : 0x22400 - 0x227FF
- */
-#define PLB0_BLK_REG_ADDR		0x00022000
-#define PLB1_BLK_REG_ADDR		0x00022400
-
-/**
- * PLB Registers
- * Holds RL timer used time stamps in RLT tagged frames
- */
-#define PLB0_ECM_TIMER_REG		(PLB0_BLK_REG_ADDR + 0x05C)
-#define PLB1_ECM_TIMER_REG		(PLB1_BLK_REG_ADDR + 0x05C)
-
-/* Controls the rate-limiter on each of the priority class */
-#define PLB0_RL_CTL			(PLB0_BLK_REG_ADDR + 0x060)
-#define PLB1_RL_CTL			(PLB1_BLK_REG_ADDR + 0x060)
-
-/**
- * Max byte register, total 8, 0-7
- * see catapult_spec.pdf for details
- */
-#define PLB0_RL_MAX_BC(_num)			\
-	(PLB0_BLK_REG_ADDR + 0x064 + ((_num) << 2))
-#define PLB1_RL_MAX_BC(_num)			\
-	(PLB1_BLK_REG_ADDR + 0x064 + ((_num) << 2))
-
-/**
- * RL Time Unit Register for priority 0-7
- * 4 bits per priority
- * (2^rl_unit)*1us is the actual time period
- */
-#define PLB0_RL_TU_PRIO			(PLB0_BLK_REG_ADDR + 0x084)
-#define PLB1_RL_TU_PRIO			(PLB1_BLK_REG_ADDR + 0x084)
-
-/**
- * RL byte count register,
- * bytes transmitted in (rl_unit*1)us time period
- * 1 per priority, 8 in all, 0-7.
- */
-#define PLB0_RL_BYTE_CNT(_num)			\
-	(PLB0_BLK_REG_ADDR + 0x088 + ((_num) << 2))
-#define PLB1_RL_BYTE_CNT(_num)			\
-	(PLB1_BLK_REG_ADDR + 0x088 + ((_num) << 2))
-
-/**
- * RL Min factor register
- * 2 bits per priority,
- * 4 factors possible: 1, 0.5, 0.25, 0
- * 2'b00 - 0; 2'b01 - 0.25; 2'b10 - 0.5; 2'b11 - 1
- */
-#define PLB0_RL_MIN_REG			(PLB0_BLK_REG_ADDR + 0x0A8)
-#define PLB1_RL_MIN_REG			(PLB1_BLK_REG_ADDR + 0x0A8)
-
-/**
- * RL Max factor register
- * 2 bits per priority,
- * 4 factors possible: 1, 0.5, 0.25, 0
- * 2'b00 - 0; 2'b01 - 0.25; 2'b10 - 0.5; 2'b11 - 1
- */
-#define PLB0_RL_MAX_REG			(PLB0_BLK_REG_ADDR + 0x0AC)
-#define PLB1_RL_MAX_REG			(PLB1_BLK_REG_ADDR + 0x0AC)
-
-/* MAC SERDES Address Paging register */
-#define PLB0_EMS_ADD_REG		(PLB0_BLK_REG_ADDR + 0xD0)
-#define PLB1_EMS_ADD_REG		(PLB1_BLK_REG_ADDR + 0xD0)
-
-/* LL EMS Registers */
-#define LL_EMS0_BLK_REG_ADDR		0x00026800
-#define LL_EMS1_BLK_REG_ADDR		0x00026C00
-
-/**
- * BPC Block Register Address Offset from BAR0
- * BPC0 Range : 0x23000 - 0x233FF
- * BPC1 Range : 0x23400 - 0x237FF
- */
-#define BPC0_BLK_REG_ADDR		0x00023000
-#define BPC1_BLK_REG_ADDR		0x00023400
-
-/**
- * PMM Block Register Address Offset from BAR0
- * PMM0 Range : 0x23800 - 0x23BFF
- * PMM1 Range : 0x23C00 - 0x23FFF
- */
-#define PMM0_BLK_REG_ADDR		0x00023800
-#define PMM1_BLK_REG_ADDR		0x00023C00
-
-/**
- * HQM Block Register Address Offset from BAR0
- * HQM0 Range : 0x24000 - 0x243FF
- * HQM1 Range : 0x24400 - 0x247FF
- */
-#define HQM0_BLK_REG_ADDR		0x00024000
-#define HQM1_BLK_REG_ADDR		0x00024400
-
-/**
- * HQM Control Register
- * Controls some aspects of IB
- * See catapult_spec.pdf for details
- */
-#define HQM0_CTL_REG			(HQM0_BLK_REG_ADDR + 0x000)
-#define HQM1_CTL_REG			(HQM1_BLK_REG_ADDR + 0x000)
-
-/**
- * HQM Stop Q Semaphore Registers.
- * Only one Queue resource can be stopped at
- * any given time. This register controls access
- * to the single stop Q resource.
- * See catapult_spec.pdf for details
- */
-#define HQM0_RXQ_STOP_SEM		(HQM0_BLK_REG_ADDR + 0x028)
-#define HQM0_TXQ_STOP_SEM		(HQM0_BLK_REG_ADDR + 0x02C)
-#define HQM1_RXQ_STOP_SEM		(HQM1_BLK_REG_ADDR + 0x028)
-#define HQM1_TXQ_STOP_SEM		(HQM1_BLK_REG_ADDR + 0x02C)
-
-/**
- * LUT Block Register Address Offset from BAR0
- * LUT0 Range : 0x25800 - 0x25BFF
- * LUT1 Range : 0x25C00 - 0x25FFF
- */
-#define LUT0_BLK_REG_ADDR		0x00025800
-#define LUT1_BLK_REG_ADDR		0x00025C00
-
-/**
- * LUT Registers
- * See catapult_spec.pdf for details
- */
-#define LUT0_ERR_STS			(LUT0_BLK_REG_ADDR + 0x000)
-#define LUT1_ERR_STS			(LUT1_BLK_REG_ADDR + 0x000)
-#define LUT0_SET_ERR_STS		(LUT0_BLK_REG_ADDR + 0x004)
-#define LUT1_SET_ERR_STS		(LUT1_BLK_REG_ADDR + 0x004)
-
-/**
- * TRC (Debug/Trace) Register Offset from BAR0
- * Range : 0x26000 -- 0x263FFF
- */
-#define TRC_BLK_REG_ADDR		0x00026000
-
-/**
- * TRC Registers
- * See catapult_spec.pdf for details of each
- */
-#define TRC_CTL_REG			(TRC_BLK_REG_ADDR + 0x000)
-#define TRC_MODS_REG			(TRC_BLK_REG_ADDR + 0x004)
-#define TRC_TRGC_REG			(TRC_BLK_REG_ADDR + 0x008)
-#define TRC_CNT1_REG			(TRC_BLK_REG_ADDR + 0x010)
-#define TRC_CNT2_REG			(TRC_BLK_REG_ADDR + 0x014)
-#define TRC_NXTS_REG			(TRC_BLK_REG_ADDR + 0x018)
-#define TRC_DIRR_REG			(TRC_BLK_REG_ADDR + 0x01C)
-
-/**
- * TRC Trigger match filters, total 10
- * Determines the trigger condition
- */
-#define TRC_TRGM_REG(_num)		\
-	(TRC_BLK_REG_ADDR + 0x040 + ((_num) << 2))
-
-/**
- * TRC Next State filters, total 10
- * Determines the next state conditions
- */
-#define TRC_NXTM_REG(_num)		\
-	(TRC_BLK_REG_ADDR + 0x080 + ((_num) << 2))
-
-/**
- * TRC Store Match filters, total 10
- * Determines the store conditions
- */
-#define TRC_STRM_REG(_num)		\
-	(TRC_BLK_REG_ADDR + 0x0C0 + ((_num) << 2))
-
-/* DOORBELLS ACCESS */
-
-/**
- * Catapult doorbells
- * Each doorbell-queue set has
- * 1 RxQ, 1 TxQ, 2 IBs in that order
- * Size of each entry in 32 bytes, even though only 1 word
- * is used. For Non-VM case each doorbell-q set is
- * separated by 128 bytes, for VM case it is separated
- * by 4K bytes
- * Non VM case Range : 0x38000 - 0x39FFF
- * VM case Range     : 0x100000 - 0x11FFFF
- * The range applies to both HQMs
- */
-#define HQM_DOORBELL_BLK_BASE_ADDR	0x00038000
-#define HQM_DOORBELL_VM_BLK_BASE_ADDR	0x00100000
-
-/* MEMORY ACCESS */
-
-/**
- * Catapult H/W Block Memory Access Address
- * To the host a memory space of 32K (page) is visible
- * at a time. The address range is from 0x08000 to 0x0FFFF
- */
-#define HW_BLK_HOST_MEM_ADDR		0x08000
-
-/**
- * Catapult LUT Memory Access Page Numbers
- * Range : LUT0 0xa0-0xa1
- *         LUT1 0xa2-0xa3
- */
-#define LUT0_MEM_BLK_BASE_PG_NUM	0x000000A0
-#define LUT1_MEM_BLK_BASE_PG_NUM	0x000000A2
-
-/**
- * Catapult RxFn Database Memory Block Base Offset
- *
- * The Rx function database exists in LUT block.
- * In PCIe space this is accessible as a 256x32
- * bit block. Each entry in this database is 4
- * (4 byte) words. Max. entries is 64.
- * Address of an entry corresponding to a function
- * = base_addr + (function_no. * 16)
- */
-#define RX_FNDB_RAM_BASE_OFFSET		0x0000B400
-
-/**
- * Catapult TxFn Database Memory Block Base Offset Address
- *
- * The Tx function database exists in LUT block.
- * In PCIe space this is accessible as a 64x32
- * bit block. Each entry in this database is 1
- * (4 byte) word. Max. entries is 64.
- * Address of an entry corresponding to a function
- * = base_addr + (function_no. * 4)
- */
-#define TX_FNDB_RAM_BASE_OFFSET		0x0000B800
-
-/**
- * Catapult Unicast CAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Shared by both the LL & FCoE driver.
- * Size is 256x48 bits; mapped to PCIe space
- * 512x32 bit blocks. For each address, bits
- * are written in the order : [47:32] and then
- * [31:0].
- */
-#define UCAST_CAM_BASE_OFFSET		0x0000A800
-
-/**
- * Catapult Unicast RAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Shared by both the LL & FCoE driver.
- * Size is 256x9 bits.
- */
-#define UCAST_RAM_BASE_OFFSET		0x0000B000
-
-/**
- * Catapult Mulicast CAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Shared by both the LL & FCoE driver.
- * Size is 256x48 bits; mapped to PCIe space
- * 512x32 bit blocks. For each address, bits
- * are written in the order : [47:32] and then
- * [31:0].
- */
-#define MCAST_CAM_BASE_OFFSET		0x0000A000
-
-/**
- * Catapult VLAN RAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Size is 4096x66 bits; mapped to PCIe space as
- * 8192x32 bit blocks.
- * All the 4K entries are within the address range
- * 0x0000 to 0x8000, so in the first LUT page.
- */
-#define VLAN_RAM_BASE_OFFSET		0x00000000
-
-/**
- * Catapult Tx Stats RAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Size is 1024x33 bits;
- * Each Tx function has 64 bytes of space
- */
-#define TX_STATS_RAM_BASE_OFFSET	0x00009000
-
-/**
- * Catapult Rx Stats RAM Base Offset Address
- *
- * Exists in LUT memory space.
- * Size is 1024x33 bits;
- * Each Rx function has 64 bytes of space
- */
-#define RX_STATS_RAM_BASE_OFFSET	0x00008000
-
-/* Catapult RXA Memory Access Page Numbers */
-#define RXA0_MEM_BLK_BASE_PG_NUM	0x0000008C
-#define RXA1_MEM_BLK_BASE_PG_NUM	0x0000008D
-
-/**
- * Catapult Multicast Vector Table Base Offset Address
- *
- * Exists in RxA memory space.
- * Organized as 512x65 bit block.
- * However for each entry 16 bytes allocated (power of 2)
- * Total size 512*16 bytes.
- * There are two logical divisions, 256 entries each :
- * a) Entries 0x00 to 0xff (256) -- Approx. MVT
- *    Offset 0x000 to 0xFFF
- * b) Entries 0x100 to 0x1ff (256) -- Exact MVT
- *    Offsets 0x1000 to 0x1FFF
- */
-#define MCAST_APPROX_MVT_BASE_OFFSET	0x00000000
-#define MCAST_EXACT_MVT_BASE_OFFSET	0x00001000
-
-/**
- * Catapult RxQ Translate Table (RIT) Base Offset Address
- *
- * Exists in RxA memory space
- * Total no. of entries 64
- * Each entry is 1 (4 byte) word.
- * 31:12 -- Reserved
- * 11:0  -- Two 6 bit RxQ Ids
- */
-#define FUNCTION_TO_RXQ_TRANSLATE	0x00002000
-
-/* Catapult RxAdm (RAD) Memory Access Page Numbers */
-#define RAD0_MEM_BLK_BASE_PG_NUM	0x00000086
-#define RAD1_MEM_BLK_BASE_PG_NUM	0x00000087
-
-/**
- * Catapult RSS Table Base Offset Address
- *
- * Exists in RAD memory space.
- * 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.
- */
-#define RSS_TABLE_BASE_OFFSET		0x00000800
-
-/**
- * Catapult CPQ Block Page Number
- * This value is written to the page number registers
- * to access the memory associated with the mailboxes.
- */
-#define CPQ_BLK_PG_NUM			0x00000005
-
-/**
- * Clarification :
- * LL functions are 2 & 3; can HostFn0/HostFn1
- * <-> LPU0/LPU1 memories be used ?
- */
-/**
- * Catapult HostFn0/HostFn1 to LPU0/LPU1 Mbox memory
- * Per catapult_spec.pdf, the offset of the mbox
- * memory is in the register space at an offset of 0x200
- */
-#define CPQ_BLK_REG_MBOX_ADDR		(CPQ_BLK_REG_ADDR + 0x200)
-
-#define HOSTFN_LPU_MBOX			(CPQ_BLK_REG_MBOX_ADDR + 0x000)
-
-/* Catapult LPU0/LPU1 to HostFn0/HostFn1 Mbox memory */
-#define LPU_HOSTFN_MBOX			(CPQ_BLK_REG_MBOX_ADDR + 0x080)
-
-/**
- * Catapult HQM Block Page Number
- * This is written to the page number register for
- * the appropriate function to access the memory
- * associated with HQM
- */
-#define HQM0_BLK_PG_NUM			0x00000096
-#define HQM1_BLK_PG_NUM			0x00000097
-
-/**
- * Note that TxQ and RxQ entries are interlaced
- * the HQM memory, i.e RXQ0, TXQ0, RXQ1, TXQ1.. etc.
- */
-
-#define HQM_RXTX_Q_RAM_BASE_OFFSET	0x00004000
-
-/**
- * CQ Memory
- * Exists in HQM Memory space
- * Each entry is 16 (4 byte) words of which
- * only 12 words are used for configuration
- * Total 64 entries per HQM memory space
- */
-#define HQM_CQ_RAM_BASE_OFFSET		0x00006000
-
-/**
- * Interrupt Block (IB) Memory
- * Exists in HQM Memory space
- * Each entry is 8 (4 byte) words of which
- * only 5 words are used for configuration
- * Total 128 entries per HQM memory space
- */
-#define HQM_IB_RAM_BASE_OFFSET		0x00001000
-
-/**
- * Index Table (IT) Memory
- * Exists in HQM Memory space
- * Each entry is 1 (4 byte) word which
- * is used for configuration
- * Total 128 entries per HQM memory space
- */
-#define HQM_INDX_TBL_RAM_BASE_OFFSET	0x00002000
-
-/**
- * PSS Block Memory Page Number
- * This is written to the appropriate page number
- * register to access the CPU memory.
- * Also known as the PSS secondary memory (SMEM).
- * Range : 0x180 to 0x1CF
- * See catapult_spec.pdf for details
- */
-#define PSS_BLK_PG_NUM			0x00000180
-
-/**
- * Offsets of different instances of PSS SMEM
- * 2.5M of continuous 1T memory space : 2 blocks
- * of 1M each (32 pages each, page=32KB) and 4 smaller
- * blocks of 128K each (4 pages each, page=32KB)
- * PSS_LMEM_INST0 is used for firmware download
- */
-#define PSS_LMEM_INST0			0x00000000
-#define PSS_LMEM_INST1			0x00100000
-#define PSS_LMEM_INST2			0x00200000
-#define PSS_LMEM_INST3			0x00220000
-#define PSS_LMEM_INST4			0x00240000
-#define PSS_LMEM_INST5			0x00260000
-
-#define BNA_PCI_REG_CT_ADDRSZ		(0x40000)
-
-#define BNA_GET_PAGE_NUM(_base_page, _offset)   \
-	((_base_page) + ((_offset) >> 15))
-
-#define BNA_GET_PAGE_OFFSET(_offset)    \
-	((_offset) & 0x7fff)
-
-#define BNA_GET_MEM_BASE_ADDR(_bar0, _base_offset)	\
-	((_bar0) + HW_BLK_HOST_MEM_ADDR		\
-	  + BNA_GET_PAGE_OFFSET((_base_offset)))
-
-#define BNA_GET_VLAN_MEM_ENTRY_ADDR(_bar0, _fn_id, _vlan_id)\
-	(_bar0 + (HW_BLK_HOST_MEM_ADDR)  \
-	+ (BNA_GET_PAGE_OFFSET(VLAN_RAM_BASE_OFFSET))	\
-	+ (((_fn_id) & 0x3f) << 9)	  \
-	+ (((_vlan_id) & 0xfe0) >> 3))
-
-/**
- *
- *  Interrupt related bits, flags and macros
- *
- */
-
-#define __LPU02HOST_MBOX0_STATUS_BITS 0x00100000
-#define __LPU12HOST_MBOX0_STATUS_BITS 0x00200000
-#define __LPU02HOST_MBOX1_STATUS_BITS 0x00400000
-#define __LPU12HOST_MBOX1_STATUS_BITS 0x00800000
-
-#define __LPU02HOST_MBOX0_MASK_BITS	0x00100000
-#define __LPU12HOST_MBOX0_MASK_BITS	0x00200000
-#define __LPU02HOST_MBOX1_MASK_BITS	0x00400000
-#define __LPU12HOST_MBOX1_MASK_BITS	0x00800000
-
-#define __LPU2HOST_MBOX_MASK_BITS			 \
-	(__LPU02HOST_MBOX0_MASK_BITS | __LPU02HOST_MBOX1_MASK_BITS |	\
-	  __LPU12HOST_MBOX0_MASK_BITS | __LPU12HOST_MBOX1_MASK_BITS)
-
-#define __LPU2HOST_IB_STATUS_BITS	0x0000ffff
-
-#define BNA_IS_LPU0_MBOX_INTR(_intr_status) \
-	((_intr_status) & (__LPU02HOST_MBOX0_STATUS_BITS | \
-			__LPU02HOST_MBOX1_STATUS_BITS))
-
-#define BNA_IS_LPU1_MBOX_INTR(_intr_status) \
-	((_intr_status) & (__LPU12HOST_MBOX0_STATUS_BITS | \
-		__LPU12HOST_MBOX1_STATUS_BITS))
-
-#define BNA_IS_MBOX_INTR(_intr_status)		\
-	((_intr_status) &			\
-	(__LPU02HOST_MBOX0_STATUS_BITS |	\
-	 __LPU02HOST_MBOX1_STATUS_BITS |	\
-	 __LPU12HOST_MBOX0_STATUS_BITS |	\
-	 __LPU12HOST_MBOX1_STATUS_BITS))
-
-#define __EMC_ERROR_STATUS_BITS		0x00010000
-#define __LPU0_ERROR_STATUS_BITS	0x00020000
-#define __LPU1_ERROR_STATUS_BITS	0x00040000
-#define __PSS_ERROR_STATUS_BITS		0x00080000
-
-#define __HALT_STATUS_BITS		0x01000000
-
-#define __EMC_ERROR_MASK_BITS		0x00010000
-#define __LPU0_ERROR_MASK_BITS		0x00020000
-#define __LPU1_ERROR_MASK_BITS		0x00040000
-#define __PSS_ERROR_MASK_BITS		0x00080000
-
-#define __HALT_MASK_BITS		0x01000000
-
-#define __ERROR_MASK_BITS		\
-	(__EMC_ERROR_MASK_BITS | __LPU0_ERROR_MASK_BITS | \
-	  __LPU1_ERROR_MASK_BITS | __PSS_ERROR_MASK_BITS | \
-	  __HALT_MASK_BITS)
-
-#define BNA_IS_ERR_INTR(_intr_status)	\
-	((_intr_status) &		\
-	(__EMC_ERROR_STATUS_BITS |	\
-	 __LPU0_ERROR_STATUS_BITS |	\
-	 __LPU1_ERROR_STATUS_BITS |	\
-	 __PSS_ERROR_STATUS_BITS  |	\
-	 __HALT_STATUS_BITS))
-
-#define BNA_IS_MBOX_ERR_INTR(_intr_status)	\
-	(BNA_IS_MBOX_INTR((_intr_status)) |	\
-	 BNA_IS_ERR_INTR((_intr_status)))
-
-#define BNA_IS_INTX_DATA_INTR(_intr_status)	\
-	((_intr_status) & __LPU2HOST_IB_STATUS_BITS)
-
-#define BNA_INTR_STATUS_MBOX_CLR(_intr_status)			\
-do {								\
-	(_intr_status) &= ~(__LPU02HOST_MBOX0_STATUS_BITS |	\
-			__LPU02HOST_MBOX1_STATUS_BITS |		\
-			__LPU12HOST_MBOX0_STATUS_BITS |		\
-			__LPU12HOST_MBOX1_STATUS_BITS);		\
-} while (0)
-
-#define BNA_INTR_STATUS_ERR_CLR(_intr_status)		\
-do {							\
-	(_intr_status) &= ~(__EMC_ERROR_STATUS_BITS |	\
-		__LPU0_ERROR_STATUS_BITS |		\
-		__LPU1_ERROR_STATUS_BITS |		\
-		__PSS_ERROR_STATUS_BITS  |		\
-		__HALT_STATUS_BITS);			\
-} while (0)
-
-#define bna_intx_disable(_bna, _cur_mask)		\
-{							\
-	(_cur_mask) = readl((_bna)->regs.fn_int_mask);\
-	writel(0xffffffff, (_bna)->regs.fn_int_mask);\
-}
-
-#define bna_intx_enable(bna, new_mask)			\
-	writel((new_mask), (bna)->regs.fn_int_mask)
-
-#define bna_mbox_intr_disable(bna)		\
-	writel((readl((bna)->regs.fn_int_mask) | \
-	     (__LPU2HOST_MBOX_MASK_BITS | __ERROR_MASK_BITS)), \
-	     (bna)->regs.fn_int_mask)
-
-#define bna_mbox_intr_enable(bna)		\
-	writel((readl((bna)->regs.fn_int_mask) & \
-	     ~(__LPU2HOST_MBOX_MASK_BITS | __ERROR_MASK_BITS)), \
-	     (bna)->regs.fn_int_mask)
-
-#define bna_intr_status_get(_bna, _status)				\
-{									\
-	(_status) = readl((_bna)->regs.fn_int_status);		\
-	if ((_status)) {						\
-		writel((_status) & ~(__LPU02HOST_MBOX0_STATUS_BITS |\
-					  __LPU02HOST_MBOX1_STATUS_BITS |\
-					  __LPU12HOST_MBOX0_STATUS_BITS |\
-					  __LPU12HOST_MBOX1_STATUS_BITS), \
-			      (_bna)->regs.fn_int_status);\
-	}								\
-}
-
-#define bna_intr_status_get_no_clr(_bna, _status)		\
-	(_status) = readl((_bna)->regs.fn_int_status)
-
-#define bna_intr_mask_get(bna, mask)		\
-	(*mask) = readl((bna)->regs.fn_int_mask)
-
-#define bna_intr_ack(bna, intr_bmap)		\
-	writel((intr_bmap), (bna)->regs.fn_int_status)
-
-#define bna_ib_intx_disable(bna, ib_id)		\
-	writel(readl((bna)->regs.fn_int_mask) | \
-	    (1 << (ib_id)), \
-	    (bna)->regs.fn_int_mask)
-
-#define bna_ib_intx_enable(bna, ib_id)		\
-	writel(readl((bna)->regs.fn_int_mask) & \
-	    ~(1 << (ib_id)), \
-	    (bna)->regs.fn_int_mask)
-
-#define bna_mbox_msix_idx_set(_device) \
-do {\
-	writel(((_device)->vector & 0x000001FF), \
-		(_device)->bna->pcidev.pci_bar_kva + \
-		reg_offset[(_device)->bna->pcidev.pci_func].msix_idx);\
-} while (0)
-
-/**
- *
- * TxQ, RxQ, CQ related bits, offsets, macros
- *
- */
-
-#define	BNA_Q_IDLE_STATE	0x00008001
-
-#define BNA_GET_DOORBELL_BASE_ADDR(_bar0)	\
-	((_bar0) + HQM_DOORBELL_BLK_BASE_ADDR)
-
-#define BNA_GET_DOORBELL_ENTRY_OFFSET(_entry)		\
-	((HQM_DOORBELL_BLK_BASE_ADDR)		\
-	+ (_entry << 7))
-
-#define BNA_DOORBELL_IB_INT_ACK(_timeout, _events) \
-		(0x80000000 | ((_timeout) << 16) | (_events))
-
-#define BNA_DOORBELL_IB_INT_DISABLE		(0x40000000)
-
-/* TxQ Entry Opcodes */
-#define BNA_TXQ_WI_SEND			(0x402)	/* Single Frame Transmission */
-#define BNA_TXQ_WI_SEND_LSO		(0x403)	/* Multi-Frame Transmission */
-#define BNA_TXQ_WI_EXTENSION		(0x104)	/* Extension WI */
-
-/* TxQ Entry Control Flags */
-#define BNA_TXQ_WI_CF_FCOE_CRC		(1 << 8)
-#define BNA_TXQ_WI_CF_IPID_MODE		(1 << 5)
-#define BNA_TXQ_WI_CF_INS_PRIO		(1 << 4)
-#define BNA_TXQ_WI_CF_INS_VLAN		(1 << 3)
-#define BNA_TXQ_WI_CF_UDP_CKSUM		(1 << 2)
-#define BNA_TXQ_WI_CF_TCP_CKSUM		(1 << 1)
-#define BNA_TXQ_WI_CF_IP_CKSUM		(1 << 0)
-
-#define BNA_TXQ_WI_L4_HDR_N_OFFSET(_hdr_size, _offset) \
-		(((_hdr_size) << 10) | ((_offset) & 0x3FF))
-
-/*
- * Completion Q defines
- */
-/* CQ Entry Flags */
-#define	BNA_CQ_EF_MAC_ERROR	(1 <<  0)
-#define	BNA_CQ_EF_FCS_ERROR	(1 <<  1)
-#define	BNA_CQ_EF_TOO_LONG	(1 <<  2)
-#define	BNA_CQ_EF_FC_CRC_OK	(1 <<  3)
-
-#define	BNA_CQ_EF_RSVD1		(1 <<  4)
-#define	BNA_CQ_EF_L4_CKSUM_OK	(1 <<  5)
-#define	BNA_CQ_EF_L3_CKSUM_OK	(1 <<  6)
-#define	BNA_CQ_EF_HDS_HEADER	(1 <<  7)
-
-#define	BNA_CQ_EF_UDP		(1 <<  8)
-#define	BNA_CQ_EF_TCP		(1 <<  9)
-#define	BNA_CQ_EF_IP_OPTIONS	(1 << 10)
-#define	BNA_CQ_EF_IPV6		(1 << 11)
-
-#define	BNA_CQ_EF_IPV4		(1 << 12)
-#define	BNA_CQ_EF_VLAN		(1 << 13)
-#define	BNA_CQ_EF_RSS		(1 << 14)
-#define	BNA_CQ_EF_RSVD2		(1 << 15)
-
-#define	BNA_CQ_EF_MCAST_MATCH   (1 << 16)
-#define	BNA_CQ_EF_MCAST		(1 << 17)
-#define BNA_CQ_EF_BCAST		(1 << 18)
-#define	BNA_CQ_EF_REMOTE	(1 << 19)
-
-#define	BNA_CQ_EF_LOCAL		(1 << 20)
-
-/**
- *
- * Data structures
- *
- */
-
-enum txf_flags {
-	BFI_TXF_CF_ENABLE		= 1 << 0,
-	BFI_TXF_CF_VLAN_FILTER		= 1 << 8,
-	BFI_TXF_CF_VLAN_ADMIT		= 1 << 9,
-	BFI_TXF_CF_VLAN_INSERT		= 1 << 10,
-	BFI_TXF_CF_RSVD1		= 1 << 11,
-	BFI_TXF_CF_MAC_SA_CHECK		= 1 << 12,
-	BFI_TXF_CF_VLAN_WI_BASED	= 1 << 13,
-	BFI_TXF_CF_VSWITCH_MCAST	= 1 << 14,
-	BFI_TXF_CF_VSWITCH_UCAST	= 1 << 15,
-	BFI_TXF_CF_RSVD2		= 0x7F << 1
-};
-
-enum ib_flags {
-	BFI_IB_CF_MASTER_ENABLE		= (1 << 0),
-	BFI_IB_CF_MSIX_MODE		= (1 << 1),
-	BFI_IB_CF_COALESCING_MODE	= (1 << 2),
-	BFI_IB_CF_INTER_PKT_ENABLE	= (1 << 3),
-	BFI_IB_CF_INT_ENABLE		= (1 << 4),
-	BFI_IB_CF_INTER_PKT_DMA		= (1 << 5),
-	BFI_IB_CF_ACK_PENDING		= (1 << 6),
-	BFI_IB_CF_RESERVED1		= (1 << 7)
-};
-
-enum rss_hash_type {
-	BFI_RSS_T_V4_TCP		= (1 << 11),
-	BFI_RSS_T_V4_IP			= (1 << 10),
-	BFI_RSS_T_V6_TCP		= (1 <<  9),
-	BFI_RSS_T_V6_IP			= (1 <<  8)
-};
-enum hds_header_type {
-	BNA_HDS_T_V4_TCP	= (1 << 11),
-	BNA_HDS_T_V4_UDP	= (1 << 10),
-	BNA_HDS_T_V6_TCP	= (1 << 9),
-	BNA_HDS_T_V6_UDP	= (1 << 8),
-	BNA_HDS_FORCED		= (1 << 7),
-};
-enum rxf_flags {
-	BNA_RXF_CF_SM_LG_RXQ			= (1 << 15),
-	BNA_RXF_CF_DEFAULT_VLAN			= (1 << 14),
-	BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE	= (1 << 13),
-	BNA_RXF_CF_VLAN_STRIP			= (1 << 12),
-	BNA_RXF_CF_RSS_ENABLE			= (1 <<  8)
-};
-struct bna_chip_regs_offset {
-	u32 page_addr;
-	u32 fn_int_status;
-	u32 fn_int_mask;
-	u32 msix_idx;
-};
-
-struct bna_chip_regs {
-	void __iomem *page_addr;
-	void __iomem *fn_int_status;
-	void __iomem *fn_int_mask;
-};
-
-struct bna_txq_mem {
-	u32 pg_tbl_addr_lo;
-	u32 pg_tbl_addr_hi;
-	u32 cur_q_entry_lo;
-	u32 cur_q_entry_hi;
-	u32 reserved1;
-	u32 reserved2;
-	u32 pg_cnt_n_prd_ptr;	/* 31:16->total page count */
-					/* 15:0 ->producer pointer (index?) */
-	u32 entry_n_pg_size;	/* 31:16->entry size */
-					/* 15:0 ->page size */
-	u32 int_blk_n_cns_ptr;	/* 31:24->Int Blk Id;  */
-					/* 23:16->Int Blk Offset */
-					/* 15:0 ->consumer pointer(index?) */
-	u32 cns_ptr2_n_q_state;	/* 31:16->cons. ptr 2; 15:0-> Q state */
-	u32 nxt_qid_n_fid_n_pri;	/* 17:10->next */
-					/* QId;9:3->FID;2:0->Priority */
-	u32 wvc_n_cquota_n_rquota; /* 31:24->WI Vector Count; */
-					/* 23:12->Cfg Quota; */
-					/* 11:0 ->Run Quota */
-	u32 reserved3[4];
-};
-
-struct bna_rxq_mem {
-	u32 pg_tbl_addr_lo;
-	u32 pg_tbl_addr_hi;
-	u32 cur_q_entry_lo;
-	u32 cur_q_entry_hi;
-	u32 reserved1;
-	u32 reserved2;
-	u32 pg_cnt_n_prd_ptr;	/* 31:16->total page count */
-					/* 15:0 ->producer pointer (index?) */
-	u32 entry_n_pg_size;	/* 31:16->entry size */
-					/* 15:0 ->page size */
-	u32 sg_n_cq_n_cns_ptr;	/* 31:28->reserved; 27:24->sg count */
-					/* 23:16->CQ; */
-					/* 15:0->consumer pointer(index?) */
-	u32 buf_sz_n_q_state;	/* 31:16->buffer size; 15:0-> Q state */
-	u32 next_qid;		/* 17:10->next QId */
-	u32 reserved3;
-	u32 reserved4[4];
-};
-
-struct bna_rxtx_q_mem {
-	struct bna_rxq_mem rxq;
-	struct bna_txq_mem txq;
-};
-
-struct bna_cq_mem {
-	u32 pg_tbl_addr_lo;
-	u32 pg_tbl_addr_hi;
-	u32 cur_q_entry_lo;
-	u32 cur_q_entry_hi;
-
-	u32 reserved1;
-	u32 reserved2;
-	u32 pg_cnt_n_prd_ptr;	/* 31:16->total page count */
-					/* 15:0 ->producer pointer (index?) */
-	u32 entry_n_pg_size;	/* 31:16->entry size */
-					/* 15:0 ->page size */
-	u32 int_blk_n_cns_ptr;	/* 31:24->Int Blk Id; */
-					/* 23:16->Int Blk Offset */
-					/* 15:0 ->consumer pointer(index?) */
-	u32 q_state;		/* 31:16->reserved; 15:0-> Q state */
-	u32 reserved3[2];
-	u32 reserved4[4];
-};
-
-struct bna_ib_blk_mem {
-	u32 host_addr_lo;
-	u32 host_addr_hi;
-	u32 clsc_n_ctrl_n_msix;	/* 31:24->coalescing; */
-					/* 23:16->coalescing cfg; */
-					/* 15:8 ->control; */
-					/* 7:0 ->msix; */
-	u32 ipkt_n_ent_n_idxof;
-	u32 ipkt_cnt_cfg_n_unacked;
-
-	u32 reserved[3];
-};
-
-struct bna_idx_tbl_mem {
-	u32 idx;	  /* !< 31:16->res;15:0->idx; */
-};
-
-struct bna_doorbell_qset {
-	u32 rxq[0x20 >> 2];
-	u32 txq[0x20 >> 2];
-	u32 ib0[0x20 >> 2];
-	u32 ib1[0x20 >> 2];
-};
-
-struct bna_rx_fndb_ram {
-	u32 rss_prop;
-	u32 size_routing_props;
-	u32 rit_hds_mcastq;
-	u32 control_flags;
-};
-
-struct bna_tx_fndb_ram {
-	u32 vlan_n_ctrl_flags;
-};
-
-/**
- * @brief
- *  Structure which maps to RxFn Indirection Table (RIT)
- *  Size : 1 word
- *  See catapult_spec.pdf, RxA for details
- */
-struct bna_rit_mem {
-	u32 rxq_ids;	/* !< 31:12->res;11:0->two 6 bit RxQ Ids */
-};
-
-/**
- * @brief
- *  Structure which maps to RSS Table entry
- *  Size : 16 words
- *  See catapult_spec.pdf, RAD for details
- */
-struct bna_rss_mem {
-	/*
-	 * 31:12-> res
-	 * 11:8 -> protocol type
-	 *  7:0 -> hash index
-	 */
-	u32 type_n_hash;
-	u32 hash_key[10];  /* !< 40 byte Toeplitz hash key */
-	u32 reserved[5];
-};
-
-/* TxQ Vector (a.k.a. Tx-Buffer Descriptor) */
-struct bna_dma_addr {
-	u32		msb;
-	u32		lsb;
-};
-
-struct bna_txq_wi_vector {
-	u16		reserved;
-	u16		length;		/* Only 14 LSB are valid */
-	struct bna_dma_addr host_addr; /* Tx-Buf DMA addr */
-};
-
-typedef u16 bna_txq_wi_opcode_t;
-
-typedef u16 bna_txq_wi_ctrl_flag_t;
-
-/**
- *  TxQ Entry Structure
- *
- *  BEWARE:  Load values into this structure with correct endianess.
- */
-struct bna_txq_entry {
-	union {
-		struct {
-			u8 reserved;
-			u8 num_vectors;	/* number of vectors present */
-			bna_txq_wi_opcode_t opcode; /* Either */
-						    /* BNA_TXQ_WI_SEND or */
-						    /* BNA_TXQ_WI_SEND_LSO */
-			bna_txq_wi_ctrl_flag_t flags; /* OR of all the flags */
-			u16 l4_hdr_size_n_offset;
-			u16 vlan_tag;
-			u16 lso_mss;	/* Only 14 LSB are valid */
-			u32 frame_length;	/* Only 24 LSB are valid */
-		} wi;
-
-		struct {
-			u16 reserved;
-			bna_txq_wi_opcode_t opcode; /* Must be */
-						    /* BNA_TXQ_WI_EXTENSION */
-			u32 reserved2[3];	/* Place holder for */
-						/* removed vector (12 bytes) */
-		} wi_ext;
-	} hdr;
-	struct bna_txq_wi_vector vector[4];
-};
-#define wi_hdr		hdr.wi
-#define wi_ext_hdr  hdr.wi_ext
-
-/* RxQ Entry Structure */
-struct bna_rxq_entry {		/* Rx-Buffer */
-	struct bna_dma_addr host_addr; /* Rx-Buffer DMA address */
-};
-
-typedef u32 bna_cq_e_flag_t;
-
-/* CQ Entry Structure */
-struct bna_cq_entry {
-	bna_cq_e_flag_t flags;
-	u16 vlan_tag;
-	u16 length;
-	u32 rss_hash;
-	u8 valid;
-	u8 reserved1;
-	u8 reserved2;
-	u8 rxq_id;
-};
-
-#endif /* __BNA_HW_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bna_txrx.c linux-libre-3.2-gnu/drivers/net/bna/bna_txrx.c
--- linux-libre-3.1-gnu/drivers/net/bna/bna_txrx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bna_txrx.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,4185 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
-  */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-#include "bna.h"
-#include "bfa_cs.h"
-#include "bfi.h"
-
-/**
- * IB
- */
-#define bna_ib_find_free_ibidx(_mask, _pos)\
-do {\
-	(_pos) = 0;\
-	while (((_pos) < (BFI_IBIDX_MAX_SEGSIZE)) &&\
-		((1 << (_pos)) & (_mask)))\
-		(_pos)++;\
-} while (0)
-
-#define bna_ib_count_ibidx(_mask, _count)\
-do {\
-	int pos = 0;\
-	(_count) = 0;\
-	while (pos < (BFI_IBIDX_MAX_SEGSIZE)) {\
-		if ((1 << pos) & (_mask))\
-			(_count) = pos + 1;\
-		pos++;\
-	} \
-} while (0)
-
-#define bna_ib_select_segpool(_count, _q_idx)\
-do {\
-	int i;\
-	(_q_idx) = -1;\
-	for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) {\
-		if ((_count <= ibidx_pool[i].pool_entry_size)) {\
-			(_q_idx) = i;\
-			break;\
-		} \
-	} \
-} while (0)
-
-struct bna_ibidx_pool {
-	int	pool_size;
-	int	pool_entry_size;
-};
-init_ibidx_pool(ibidx_pool);
-
-static struct bna_intr *
-bna_intr_get(struct bna_ib_mod *ib_mod, enum bna_intr_type intr_type,
-		int vector)
-{
-	struct bna_intr *intr;
-	struct list_head *qe;
-
-	list_for_each(qe, &ib_mod->intr_active_q) {
-		intr = (struct bna_intr *)qe;
-
-		if ((intr->intr_type == intr_type) &&
-			(intr->vector == vector)) {
-			intr->ref_count++;
-			return intr;
-		}
-	}
-
-	if (list_empty(&ib_mod->intr_free_q))
-		return NULL;
-
-	bfa_q_deq(&ib_mod->intr_free_q, &intr);
-	bfa_q_qe_init(&intr->qe);
-
-	intr->ref_count = 1;
-	intr->intr_type = intr_type;
-	intr->vector = vector;
-
-	list_add_tail(&intr->qe, &ib_mod->intr_active_q);
-
-	return intr;
-}
-
-static void
-bna_intr_put(struct bna_ib_mod *ib_mod,
-		struct bna_intr *intr)
-{
-	intr->ref_count--;
-
-	if (intr->ref_count == 0) {
-		intr->ib = NULL;
-		list_del(&intr->qe);
-		bfa_q_qe_init(&intr->qe);
-		list_add_tail(&intr->qe, &ib_mod->intr_free_q);
-	}
-}
-
-void
-bna_ib_mod_init(struct bna_ib_mod *ib_mod, struct bna *bna,
-		struct bna_res_info *res_info)
-{
-	int i;
-	int j;
-	int count;
-	u8 offset;
-	struct bna_doorbell_qset *qset;
-	unsigned long off;
-
-	ib_mod->bna = bna;
-
-	ib_mod->ib = (struct bna_ib *)
-		res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.mdl[0].kva;
-	ib_mod->intr = (struct bna_intr *)
-		res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.mdl[0].kva;
-	ib_mod->idx_seg = (struct bna_ibidx_seg *)
-		res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.mdl[0].kva;
-
-	INIT_LIST_HEAD(&ib_mod->ib_free_q);
-	INIT_LIST_HEAD(&ib_mod->intr_free_q);
-	INIT_LIST_HEAD(&ib_mod->intr_active_q);
-
-	for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++)
-		INIT_LIST_HEAD(&ib_mod->ibidx_seg_pool[i]);
-
-	for (i = 0; i < BFI_MAX_IB; i++) {
-		ib_mod->ib[i].ib_id = i;
-
-		ib_mod->ib[i].ib_seg_host_addr_kva =
-		res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].kva;
-		ib_mod->ib[i].ib_seg_host_addr.lsb =
-		res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.lsb;
-		ib_mod->ib[i].ib_seg_host_addr.msb =
-		res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.msb;
-
-		qset = (struct bna_doorbell_qset *)0;
-		off = (unsigned long)(&qset[i >> 1].ib0[(i & 0x1)
-					* (0x20 >> 2)]);
-		ib_mod->ib[i].door_bell.doorbell_addr = off +
-			BNA_GET_DOORBELL_BASE_ADDR(bna->pcidev.pci_bar_kva);
-
-		bfa_q_qe_init(&ib_mod->ib[i].qe);
-		list_add_tail(&ib_mod->ib[i].qe, &ib_mod->ib_free_q);
-
-		bfa_q_qe_init(&ib_mod->intr[i].qe);
-		list_add_tail(&ib_mod->intr[i].qe, &ib_mod->intr_free_q);
-	}
-
-	count = 0;
-	offset = 0;
-	for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) {
-		for (j = 0; j < ibidx_pool[i].pool_size; j++) {
-			bfa_q_qe_init(&ib_mod->idx_seg[count]);
-			ib_mod->idx_seg[count].ib_seg_size =
-					ibidx_pool[i].pool_entry_size;
-			ib_mod->idx_seg[count].ib_idx_tbl_offset = offset;
-			list_add_tail(&ib_mod->idx_seg[count].qe,
-				&ib_mod->ibidx_seg_pool[i]);
-			count++;
-			offset += ibidx_pool[i].pool_entry_size;
-		}
-	}
-}
-
-void
-bna_ib_mod_uninit(struct bna_ib_mod *ib_mod)
-{
-	int i;
-	int j;
-	struct list_head *qe;
-
-	i = 0;
-	list_for_each(qe, &ib_mod->ib_free_q)
-		i++;
-
-	i = 0;
-	list_for_each(qe, &ib_mod->intr_free_q)
-		i++;
-
-	for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) {
-		j = 0;
-		list_for_each(qe, &ib_mod->ibidx_seg_pool[i])
-			j++;
-	}
-
-	ib_mod->bna = NULL;
-}
-
-static struct bna_ib *
-bna_ib_get(struct bna_ib_mod *ib_mod,
-		enum bna_intr_type intr_type,
-		int vector)
-{
-	struct bna_ib *ib;
-	struct bna_intr *intr;
-
-	if (intr_type == BNA_INTR_T_INTX)
-		vector = (1 << vector);
-
-	intr = bna_intr_get(ib_mod, intr_type, vector);
-	if (intr == NULL)
-		return NULL;
-
-	if (intr->ib) {
-		if (intr->ib->ref_count == BFI_IBIDX_MAX_SEGSIZE) {
-			bna_intr_put(ib_mod, intr);
-			return NULL;
-		}
-		intr->ib->ref_count++;
-		return intr->ib;
-	}
-
-	if (list_empty(&ib_mod->ib_free_q)) {
-		bna_intr_put(ib_mod, intr);
-		return NULL;
-	}
-
-	bfa_q_deq(&ib_mod->ib_free_q, &ib);
-	bfa_q_qe_init(&ib->qe);
-
-	ib->ref_count = 1;
-	ib->start_count = 0;
-	ib->idx_mask = 0;
-
-	ib->intr = intr;
-	ib->idx_seg = NULL;
-	intr->ib = ib;
-
-	ib->bna = ib_mod->bna;
-
-	return ib;
-}
-
-static void
-bna_ib_put(struct bna_ib_mod *ib_mod, struct bna_ib *ib)
-{
-	bna_intr_put(ib_mod, ib->intr);
-
-	ib->ref_count--;
-
-	if (ib->ref_count == 0) {
-		ib->intr = NULL;
-		ib->bna = NULL;
-		list_add_tail(&ib->qe, &ib_mod->ib_free_q);
-	}
-}
-
-/* Returns index offset - starting from 0 */
-static int
-bna_ib_reserve_idx(struct bna_ib *ib)
-{
-	struct bna_ib_mod *ib_mod = &ib->bna->ib_mod;
-	struct bna_ibidx_seg *idx_seg;
-	int idx;
-	int num_idx;
-	int q_idx;
-
-	/* Find the first free index position */
-	bna_ib_find_free_ibidx(ib->idx_mask, idx);
-	if (idx == BFI_IBIDX_MAX_SEGSIZE)
-		return -1;
-
-	/*
-	 * Calculate the total number of indexes held by this IB,
-	 * including the index newly reserved above.
-	 */
-	bna_ib_count_ibidx((ib->idx_mask | (1 << idx)), num_idx);
-
-	/* See if there is a free space in the index segment held by this IB */
-	if (ib->idx_seg && (num_idx <= ib->idx_seg->ib_seg_size)) {
-		ib->idx_mask |= (1 << idx);
-		return idx;
-	}
-
-	if (ib->start_count)
-		return -1;
-
-	/* Allocate a new segment */
-	bna_ib_select_segpool(num_idx, q_idx);
-	while (1) {
-		if (q_idx == BFI_IBIDX_TOTAL_POOLS)
-			return -1;
-		if (!list_empty(&ib_mod->ibidx_seg_pool[q_idx]))
-			break;
-		q_idx++;
-	}
-	bfa_q_deq(&ib_mod->ibidx_seg_pool[q_idx], &idx_seg);
-	bfa_q_qe_init(&idx_seg->qe);
-
-	/* Free the old segment */
-	if (ib->idx_seg) {
-		bna_ib_select_segpool(ib->idx_seg->ib_seg_size, q_idx);
-		list_add_tail(&ib->idx_seg->qe, &ib_mod->ibidx_seg_pool[q_idx]);
-	}
-
-	ib->idx_seg = idx_seg;
-
-	ib->idx_mask |= (1 << idx);
-
-	return idx;
-}
-
-static void
-bna_ib_release_idx(struct bna_ib *ib, int idx)
-{
-	struct bna_ib_mod *ib_mod = &ib->bna->ib_mod;
-	struct bna_ibidx_seg *idx_seg;
-	int num_idx;
-	int cur_q_idx;
-	int new_q_idx;
-
-	ib->idx_mask &= ~(1 << idx);
-
-	if (ib->start_count)
-		return;
-
-	bna_ib_count_ibidx(ib->idx_mask, num_idx);
-
-	/*
-	 * Free the segment, if there are no more indexes in the segment
-	 * held by this IB
-	 */
-	if (!num_idx) {
-		bna_ib_select_segpool(ib->idx_seg->ib_seg_size, cur_q_idx);
-		list_add_tail(&ib->idx_seg->qe,
-			&ib_mod->ibidx_seg_pool[cur_q_idx]);
-		ib->idx_seg = NULL;
-		return;
-	}
-
-	/* See if we can move to a smaller segment */
-	bna_ib_select_segpool(num_idx, new_q_idx);
-	bna_ib_select_segpool(ib->idx_seg->ib_seg_size, cur_q_idx);
-	while (new_q_idx < cur_q_idx) {
-		if (!list_empty(&ib_mod->ibidx_seg_pool[new_q_idx]))
-			break;
-		new_q_idx++;
-	}
-	if (new_q_idx < cur_q_idx) {
-		/* Select the new smaller segment */
-		bfa_q_deq(&ib_mod->ibidx_seg_pool[new_q_idx], &idx_seg);
-		bfa_q_qe_init(&idx_seg->qe);
-		/* Free the old segment */
-		list_add_tail(&ib->idx_seg->qe,
-			&ib_mod->ibidx_seg_pool[cur_q_idx]);
-		ib->idx_seg = idx_seg;
-	}
-}
-
-static int
-bna_ib_config(struct bna_ib *ib, struct bna_ib_config *ib_config)
-{
-	if (ib->start_count)
-		return -1;
-
-	ib->ib_config.coalescing_timeo = ib_config->coalescing_timeo;
-	ib->ib_config.interpkt_timeo = ib_config->interpkt_timeo;
-	ib->ib_config.interpkt_count = ib_config->interpkt_count;
-	ib->ib_config.ctrl_flags = ib_config->ctrl_flags;
-
-	ib->ib_config.ctrl_flags |= BFI_IB_CF_MASTER_ENABLE;
-	if (ib->intr->intr_type == BNA_INTR_T_MSIX)
-		ib->ib_config.ctrl_flags |= BFI_IB_CF_MSIX_MODE;
-
-	return 0;
-}
-
-static void
-bna_ib_start(struct bna_ib *ib)
-{
-	struct bna_ib_blk_mem ib_cfg;
-	struct bna_ib_blk_mem *ib_mem;
-	u32 pg_num;
-	u32 intx_mask;
-	int i;
-	void __iomem *base_addr;
-	unsigned long off;
-
-	ib->start_count++;
-
-	if (ib->start_count > 1)
-		return;
-
-	ib_cfg.host_addr_lo = (u32)(ib->ib_seg_host_addr.lsb);
-	ib_cfg.host_addr_hi = (u32)(ib->ib_seg_host_addr.msb);
-
-	ib_cfg.clsc_n_ctrl_n_msix = (((u32)
-				     ib->ib_config.coalescing_timeo << 16) |
-				((u32)ib->ib_config.ctrl_flags << 8) |
-				(ib->intr->vector));
-	ib_cfg.ipkt_n_ent_n_idxof =
-				((u32)
-				 (ib->ib_config.interpkt_timeo & 0xf) << 16) |
-				((u32)ib->idx_seg->ib_seg_size << 8) |
-				(ib->idx_seg->ib_idx_tbl_offset);
-	ib_cfg.ipkt_cnt_cfg_n_unacked = ((u32)
-					 ib->ib_config.interpkt_count << 24);
-
-	pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + ib->bna->port_num,
-				HQM_IB_RAM_BASE_OFFSET);
-	writel(pg_num, ib->bna->regs.page_addr);
-
-	base_addr = BNA_GET_MEM_BASE_ADDR(ib->bna->pcidev.pci_bar_kva,
-					HQM_IB_RAM_BASE_OFFSET);
-
-	ib_mem = (struct bna_ib_blk_mem *)0;
-	off = (unsigned long)&ib_mem[ib->ib_id].host_addr_lo;
-	writel(htonl(ib_cfg.host_addr_lo), base_addr + off);
-
-	off = (unsigned long)&ib_mem[ib->ib_id].host_addr_hi;
-	writel(htonl(ib_cfg.host_addr_hi), base_addr + off);
-
-	off = (unsigned long)&ib_mem[ib->ib_id].clsc_n_ctrl_n_msix;
-	writel(ib_cfg.clsc_n_ctrl_n_msix, base_addr + off);
-
-	off = (unsigned long)&ib_mem[ib->ib_id].ipkt_n_ent_n_idxof;
-	writel(ib_cfg.ipkt_n_ent_n_idxof, base_addr + off);
-
-	off = (unsigned long)&ib_mem[ib->ib_id].ipkt_cnt_cfg_n_unacked;
-	writel(ib_cfg.ipkt_cnt_cfg_n_unacked, base_addr + off);
-
-	ib->door_bell.doorbell_ack = BNA_DOORBELL_IB_INT_ACK(
-				(u32)ib->ib_config.coalescing_timeo, 0);
-
-	pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + ib->bna->port_num,
-				HQM_INDX_TBL_RAM_BASE_OFFSET);
-	writel(pg_num, ib->bna->regs.page_addr);
-
-	base_addr = BNA_GET_MEM_BASE_ADDR(ib->bna->pcidev.pci_bar_kva,
-					HQM_INDX_TBL_RAM_BASE_OFFSET);
-	for (i = 0; i < ib->idx_seg->ib_seg_size; i++) {
-		off = (unsigned long)
-		((ib->idx_seg->ib_idx_tbl_offset + i) * BFI_IBIDX_SIZE);
-		writel(0, base_addr + off);
-	}
-
-	if (ib->intr->intr_type == BNA_INTR_T_INTX) {
-		bna_intx_disable(ib->bna, intx_mask);
-		intx_mask &= ~(ib->intr->vector);
-		bna_intx_enable(ib->bna, intx_mask);
-	}
-}
-
-static void
-bna_ib_stop(struct bna_ib *ib)
-{
-	u32 intx_mask;
-
-	ib->start_count--;
-
-	if (ib->start_count == 0) {
-		writel(BNA_DOORBELL_IB_INT_DISABLE,
-				ib->door_bell.doorbell_addr);
-		if (ib->intr->intr_type == BNA_INTR_T_INTX) {
-			bna_intx_disable(ib->bna, intx_mask);
-			intx_mask |= (ib->intr->vector);
-			bna_intx_enable(ib->bna, intx_mask);
-		}
-	}
-}
-
-static void
-bna_ib_fail(struct bna_ib *ib)
-{
-	ib->start_count = 0;
-}
-
-/**
- * RXF
- */
-static void rxf_enable(struct bna_rxf *rxf);
-static void rxf_disable(struct bna_rxf *rxf);
-static void __rxf_config_set(struct bna_rxf *rxf);
-static void __rxf_rit_set(struct bna_rxf *rxf);
-static void __bna_rxf_stat_clr(struct bna_rxf *rxf);
-static int rxf_process_packet_filter(struct bna_rxf *rxf);
-static int rxf_clear_packet_filter(struct bna_rxf *rxf);
-static void rxf_reset_packet_filter(struct bna_rxf *rxf);
-static void rxf_cb_enabled(void *arg, int status);
-static void rxf_cb_disabled(void *arg, int status);
-static void bna_rxf_cb_stats_cleared(void *arg, int status);
-static void __rxf_enable(struct bna_rxf *rxf);
-static void __rxf_disable(struct bna_rxf *rxf);
-
-bfa_fsm_state_decl(bna_rxf, stopped, struct bna_rxf,
-			enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, start_wait, struct bna_rxf,
-			enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, cam_fltr_mod_wait, struct bna_rxf,
-			enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, started, struct bna_rxf,
-			enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, cam_fltr_clr_wait, struct bna_rxf,
-			enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, stop_wait, struct bna_rxf,
-			enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, pause_wait, struct bna_rxf,
-			enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, resume_wait, struct bna_rxf,
-			enum bna_rxf_event);
-bfa_fsm_state_decl(bna_rxf, stat_clr_wait, struct bna_rxf,
-			enum bna_rxf_event);
-
-static struct bfa_sm_table rxf_sm_table[] = {
-	{BFA_SM(bna_rxf_sm_stopped), BNA_RXF_STOPPED},
-	{BFA_SM(bna_rxf_sm_start_wait), BNA_RXF_START_WAIT},
-	{BFA_SM(bna_rxf_sm_cam_fltr_mod_wait), BNA_RXF_CAM_FLTR_MOD_WAIT},
-	{BFA_SM(bna_rxf_sm_started), BNA_RXF_STARTED},
-	{BFA_SM(bna_rxf_sm_cam_fltr_clr_wait), BNA_RXF_CAM_FLTR_CLR_WAIT},
-	{BFA_SM(bna_rxf_sm_stop_wait), BNA_RXF_STOP_WAIT},
-	{BFA_SM(bna_rxf_sm_pause_wait), BNA_RXF_PAUSE_WAIT},
-	{BFA_SM(bna_rxf_sm_resume_wait), BNA_RXF_RESUME_WAIT},
-	{BFA_SM(bna_rxf_sm_stat_clr_wait), BNA_RXF_STAT_CLR_WAIT}
-};
-
-static void
-bna_rxf_sm_stopped_entry(struct bna_rxf *rxf)
-{
-	call_rxf_stop_cbfn(rxf, BNA_CB_SUCCESS);
-}
-
-static void
-bna_rxf_sm_stopped(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-	switch (event) {
-	case RXF_E_START:
-		bfa_fsm_set_state(rxf, bna_rxf_sm_start_wait);
-		break;
-
-	case RXF_E_STOP:
-		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-		break;
-
-	case RXF_E_FAIL:
-		/* No-op */
-		break;
-
-	case RXF_E_CAM_FLTR_MOD:
-		call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
-		break;
-
-	case RXF_E_STARTED:
-	case RXF_E_STOPPED:
-	case RXF_E_CAM_FLTR_RESP:
-		/**
-		 * These events are received due to flushing of mbox
-		 * when device fails
-		 */
-		/* No-op */
-		break;
-
-	case RXF_E_PAUSE:
-		rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED;
-		call_rxf_pause_cbfn(rxf, BNA_CB_SUCCESS);
-		break;
-
-	case RXF_E_RESUME:
-		rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING;
-		call_rxf_resume_cbfn(rxf, BNA_CB_SUCCESS);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_rxf_sm_start_wait_entry(struct bna_rxf *rxf)
-{
-	__rxf_config_set(rxf);
-	__rxf_rit_set(rxf);
-	rxf_enable(rxf);
-}
-
-static void
-bna_rxf_sm_start_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-	switch (event) {
-	case RXF_E_STOP:
-		/**
-		 * STOP is originated from bnad. When this happens,
-		 * it can not be waiting for filter update
-		 */
-		call_rxf_start_cbfn(rxf, BNA_CB_INTERRUPT);
-		bfa_fsm_set_state(rxf, bna_rxf_sm_stop_wait);
-		break;
-
-	case RXF_E_FAIL:
-		call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
-		call_rxf_start_cbfn(rxf, BNA_CB_FAIL);
-		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-		break;
-
-	case RXF_E_CAM_FLTR_MOD:
-		/* No-op */
-		break;
-
-	case RXF_E_STARTED:
-		/**
-		 * Force rxf_process_filter() to go through initial
-		 * config
-		 */
-		if ((rxf->ucast_active_mac != NULL) &&
-			(rxf->ucast_pending_set == 0))
-			rxf->ucast_pending_set = 1;
-
-		if (rxf->rss_status == BNA_STATUS_T_ENABLED)
-			rxf->rxf_flags |= BNA_RXF_FL_RSS_CONFIG_PENDING;
-
-		rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
-
-		bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_mod_wait);
-		break;
-
-	case RXF_E_PAUSE:
-	case RXF_E_RESUME:
-		rxf->rxf_flags |= BNA_RXF_FL_OPERSTATE_CHANGED;
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_rxf_sm_cam_fltr_mod_wait_entry(struct bna_rxf *rxf)
-{
-	if (!rxf_process_packet_filter(rxf)) {
-		/* No more pending CAM entries to update */
-		bfa_fsm_set_state(rxf, bna_rxf_sm_started);
-	}
-}
-
-static void
-bna_rxf_sm_cam_fltr_mod_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-	switch (event) {
-	case RXF_E_STOP:
-		/**
-		 * STOP is originated from bnad. When this happens,
-		 * it can not be waiting for filter update
-		 */
-		call_rxf_start_cbfn(rxf, BNA_CB_INTERRUPT);
-		bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_clr_wait);
-		break;
-
-	case RXF_E_FAIL:
-		rxf_reset_packet_filter(rxf);
-		call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
-		call_rxf_start_cbfn(rxf, BNA_CB_FAIL);
-		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-		break;
-
-	case RXF_E_CAM_FLTR_MOD:
-		/* No-op */
-		break;
-
-	case RXF_E_CAM_FLTR_RESP:
-		if (!rxf_process_packet_filter(rxf)) {
-			/* No more pending CAM entries to update */
-			call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
-			bfa_fsm_set_state(rxf, bna_rxf_sm_started);
-		}
-		break;
-
-	case RXF_E_PAUSE:
-	case RXF_E_RESUME:
-		rxf->rxf_flags |= BNA_RXF_FL_OPERSTATE_CHANGED;
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_rxf_sm_started_entry(struct bna_rxf *rxf)
-{
-	call_rxf_start_cbfn(rxf, BNA_CB_SUCCESS);
-
-	if (rxf->rxf_flags & BNA_RXF_FL_OPERSTATE_CHANGED) {
-		if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED)
-			bfa_fsm_send_event(rxf, RXF_E_PAUSE);
-		else
-			bfa_fsm_send_event(rxf, RXF_E_RESUME);
-	}
-
-}
-
-static void
-bna_rxf_sm_started(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-	switch (event) {
-	case RXF_E_STOP:
-		bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_clr_wait);
-		/* Hack to get FSM start clearing CAM entries */
-		bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_RESP);
-		break;
-
-	case RXF_E_FAIL:
-		rxf_reset_packet_filter(rxf);
-		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-		break;
-
-	case RXF_E_CAM_FLTR_MOD:
-		bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_mod_wait);
-		break;
-
-	case RXF_E_PAUSE:
-		bfa_fsm_set_state(rxf, bna_rxf_sm_pause_wait);
-		break;
-
-	case RXF_E_RESUME:
-		bfa_fsm_set_state(rxf, bna_rxf_sm_resume_wait);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_rxf_sm_cam_fltr_clr_wait_entry(struct bna_rxf *rxf)
-{
-	/**
-	 *  Note: Do not add rxf_clear_packet_filter here.
-	 * It will overstep mbox when this transition happens:
-	 *	cam_fltr_mod_wait -> cam_fltr_clr_wait on RXF_E_STOP event
-	 */
-}
-
-static void
-bna_rxf_sm_cam_fltr_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-	switch (event) {
-	case RXF_E_FAIL:
-		/**
-		 * FSM was in the process of stopping, initiated by
-		 * bnad. When this happens, no one can be waiting for
-		 * start or filter update
-		 */
-		rxf_reset_packet_filter(rxf);
-		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-		break;
-
-	case RXF_E_CAM_FLTR_RESP:
-		if (!rxf_clear_packet_filter(rxf)) {
-			/* No more pending CAM entries to clear */
-			bfa_fsm_set_state(rxf, bna_rxf_sm_stop_wait);
-			rxf_disable(rxf);
-		}
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_rxf_sm_stop_wait_entry(struct bna_rxf *rxf)
-{
-	/**
-	 * NOTE: Do not add  rxf_disable here.
-	 * It will overstep mbox when this transition happens:
-	 *	start_wait -> stop_wait on RXF_E_STOP event
-	 */
-}
-
-static void
-bna_rxf_sm_stop_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-	switch (event) {
-	case RXF_E_FAIL:
-		/**
-		 * FSM was in the process of stopping, initiated by
-		 * bnad. When this happens, no one can be waiting for
-		 * start or filter update
-		 */
-		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-		break;
-
-	case RXF_E_STARTED:
-		/**
-		 * This event is received due to abrupt transition from
-		 * bna_rxf_sm_start_wait state on receiving
-		 * RXF_E_STOP event
-		 */
-		rxf_disable(rxf);
-		break;
-
-	case RXF_E_STOPPED:
-		/**
-		 * FSM was in the process of stopping, initiated by
-		 * bnad. When this happens, no one can be waiting for
-		 * start or filter update
-		 */
-		bfa_fsm_set_state(rxf, bna_rxf_sm_stat_clr_wait);
-		break;
-
-	case RXF_E_PAUSE:
-		rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED;
-		break;
-
-	case RXF_E_RESUME:
-		rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING;
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_rxf_sm_pause_wait_entry(struct bna_rxf *rxf)
-{
-	rxf->rxf_flags &=
-		~(BNA_RXF_FL_OPERSTATE_CHANGED | BNA_RXF_FL_RXF_ENABLED);
-	__rxf_disable(rxf);
-}
-
-static void
-bna_rxf_sm_pause_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-	switch (event) {
-	case RXF_E_FAIL:
-		/**
-		 * FSM was in the process of disabling rxf, initiated by
-		 * bnad.
-		 */
-		call_rxf_pause_cbfn(rxf, BNA_CB_FAIL);
-		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-		break;
-
-	case RXF_E_STOPPED:
-		rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED;
-		call_rxf_pause_cbfn(rxf, BNA_CB_SUCCESS);
-		bfa_fsm_set_state(rxf, bna_rxf_sm_started);
-		break;
-
-	/*
-	 * Since PAUSE/RESUME can only be sent by bnad, we don't expect
-	 * any other event during these states
-	 */
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_rxf_sm_resume_wait_entry(struct bna_rxf *rxf)
-{
-	rxf->rxf_flags &= ~(BNA_RXF_FL_OPERSTATE_CHANGED);
-	rxf->rxf_flags |= BNA_RXF_FL_RXF_ENABLED;
-	__rxf_enable(rxf);
-}
-
-static void
-bna_rxf_sm_resume_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-	switch (event) {
-	case RXF_E_FAIL:
-		/**
-		 * FSM was in the process of disabling rxf, initiated by
-		 * bnad.
-		 */
-		call_rxf_resume_cbfn(rxf, BNA_CB_FAIL);
-		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-		break;
-
-	case RXF_E_STARTED:
-		rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING;
-		call_rxf_resume_cbfn(rxf, BNA_CB_SUCCESS);
-		bfa_fsm_set_state(rxf, bna_rxf_sm_started);
-		break;
-
-	/*
-	 * Since PAUSE/RESUME can only be sent by bnad, we don't expect
-	 * any other event during these states
-	 */
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_rxf_sm_stat_clr_wait_entry(struct bna_rxf *rxf)
-{
-	__bna_rxf_stat_clr(rxf);
-}
-
-static void
-bna_rxf_sm_stat_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
-{
-	switch (event) {
-	case RXF_E_FAIL:
-	case RXF_E_STAT_CLEARED:
-		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-__rxf_enable(struct bna_rxf *rxf)
-{
-	struct bfi_ll_rxf_multi_req ll_req;
-	u32 bm[2] = {0, 0};
-
-	if (rxf->rxf_id < 32)
-		bm[0] = 1 << rxf->rxf_id;
-	else
-		bm[1] = 1 << (rxf->rxf_id - 32);
-
-	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RX_REQ, 0);
-	ll_req.rxf_id_mask[0] = htonl(bm[0]);
-	ll_req.rxf_id_mask[1] = htonl(bm[1]);
-	ll_req.enable = 1;
-
-	bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req),
-			rxf_cb_enabled, rxf);
-
-	bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
-}
-
-static void
-__rxf_disable(struct bna_rxf *rxf)
-{
-	struct bfi_ll_rxf_multi_req ll_req;
-	u32 bm[2] = {0, 0};
-
-	if (rxf->rxf_id < 32)
-		bm[0] = 1 << rxf->rxf_id;
-	else
-		bm[1] = 1 << (rxf->rxf_id - 32);
-
-	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RX_REQ, 0);
-	ll_req.rxf_id_mask[0] = htonl(bm[0]);
-	ll_req.rxf_id_mask[1] = htonl(bm[1]);
-	ll_req.enable = 0;
-
-	bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req),
-			rxf_cb_disabled, rxf);
-
-	bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
-}
-
-static void
-__rxf_config_set(struct bna_rxf *rxf)
-{
-	u32 i;
-	struct bna_rss_mem *rss_mem;
-	struct bna_rx_fndb_ram *rx_fndb_ram;
-	struct bna *bna = rxf->rx->bna;
-	void __iomem *base_addr;
-	unsigned long off;
-
-	base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
-			RSS_TABLE_BASE_OFFSET);
-
-	rss_mem = (struct bna_rss_mem *)0;
-
-	/* Configure RSS if required */
-	if (rxf->ctrl_flags & BNA_RXF_CF_RSS_ENABLE) {
-		/* configure RSS Table */
-		writel(BNA_GET_PAGE_NUM(RAD0_MEM_BLK_BASE_PG_NUM +
-			bna->port_num, RSS_TABLE_BASE_OFFSET),
-					bna->regs.page_addr);
-
-		/* temporarily disable RSS, while hash value is written */
-		off = (unsigned long)&rss_mem[0].type_n_hash;
-		writel(0, base_addr + off);
-
-		for (i = 0; i < BFI_RSS_HASH_KEY_LEN; i++) {
-			off = (unsigned long)
-			&rss_mem[0].hash_key[(BFI_RSS_HASH_KEY_LEN - 1) - i];
-			writel(htonl(rxf->rss_cfg.toeplitz_hash_key[i]),
-			base_addr + off);
-		}
-
-		off = (unsigned long)&rss_mem[0].type_n_hash;
-		writel(rxf->rss_cfg.hash_type | rxf->rss_cfg.hash_mask,
-			base_addr + off);
-	}
-
-	/* Configure RxF */
-	writel(BNA_GET_PAGE_NUM(
-		LUT0_MEM_BLK_BASE_PG_NUM + (bna->port_num * 2),
-		RX_FNDB_RAM_BASE_OFFSET),
-		bna->regs.page_addr);
-
-	base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
-		RX_FNDB_RAM_BASE_OFFSET);
-
-	rx_fndb_ram = (struct bna_rx_fndb_ram *)0;
-
-	/* We always use RSS table 0 */
-	off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].rss_prop;
-	writel(rxf->ctrl_flags & BNA_RXF_CF_RSS_ENABLE,
-		base_addr + off);
-
-	/* small large buffer enable/disable */
-	off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].size_routing_props;
-	writel((rxf->ctrl_flags & BNA_RXF_CF_SM_LG_RXQ) | 0x80,
-		base_addr + off);
-
-	/* RIT offset,  HDS forced offset, multicast RxQ Id */
-	off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].rit_hds_mcastq;
-	writel((rxf->rit_segment->rit_offset << 16) |
-		(rxf->forced_offset << 8) |
-		(rxf->hds_cfg.hdr_type & BNA_HDS_FORCED) | rxf->mcast_rxq_id,
-		base_addr + off);
-
-	/*
-	 * default vlan tag, default function enable, strip vlan bytes,
-	 * HDS type, header size
-	 */
-
-	off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].control_flags;
-	 writel(((u32)rxf->default_vlan_tag << 16) |
-		(rxf->ctrl_flags &
-			(BNA_RXF_CF_DEFAULT_VLAN |
-			BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE |
-			BNA_RXF_CF_VLAN_STRIP)) |
-		(rxf->hds_cfg.hdr_type & ~BNA_HDS_FORCED) |
-		rxf->hds_cfg.header_size,
-		base_addr + off);
-}
-
-void
-__rxf_vlan_filter_set(struct bna_rxf *rxf, enum bna_status status)
-{
-	struct bna *bna = rxf->rx->bna;
-	int i;
-
-	writel(BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
-			(bna->port_num * 2), VLAN_RAM_BASE_OFFSET),
-			bna->regs.page_addr);
-
-	if (status == BNA_STATUS_T_ENABLED) {
-		/* enable VLAN filtering on this function */
-		for (i = 0; i <= BFI_MAX_VLAN / 32; i++) {
-			writel(rxf->vlan_filter_table[i],
-					BNA_GET_VLAN_MEM_ENTRY_ADDR
-					(bna->pcidev.pci_bar_kva, rxf->rxf_id,
-						i * 32));
-		}
-	} else {
-		/* disable VLAN filtering on this function */
-		for (i = 0; i <= BFI_MAX_VLAN / 32; i++) {
-			writel(0xffffffff,
-					BNA_GET_VLAN_MEM_ENTRY_ADDR
-					(bna->pcidev.pci_bar_kva, rxf->rxf_id,
-						i * 32));
-		}
-	}
-}
-
-static void
-__rxf_rit_set(struct bna_rxf *rxf)
-{
-	struct bna *bna = rxf->rx->bna;
-	struct bna_rit_mem *rit_mem;
-	int i;
-	void __iomem *base_addr;
-	unsigned long off;
-
-	base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
-			FUNCTION_TO_RXQ_TRANSLATE);
-
-	rit_mem = (struct bna_rit_mem *)0;
-
-	writel(BNA_GET_PAGE_NUM(RXA0_MEM_BLK_BASE_PG_NUM + bna->port_num,
-		FUNCTION_TO_RXQ_TRANSLATE),
-		bna->regs.page_addr);
-
-	for (i = 0; i < rxf->rit_segment->rit_size; i++) {
-		off = (unsigned long)&rit_mem[i + rxf->rit_segment->rit_offset];
-		writel(rxf->rit_segment->rit[i].large_rxq_id << 6 |
-			rxf->rit_segment->rit[i].small_rxq_id,
-			base_addr + off);
-	}
-}
-
-static void
-__bna_rxf_stat_clr(struct bna_rxf *rxf)
-{
-	struct bfi_ll_stats_req ll_req;
-	u32 bm[2] = {0, 0};
-
-	if (rxf->rxf_id < 32)
-		bm[0] = 1 << rxf->rxf_id;
-	else
-		bm[1] = 1 << (rxf->rxf_id - 32);
-
-	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_CLEAR_REQ, 0);
-	ll_req.stats_mask = 0;
-	ll_req.txf_id_mask[0] = 0;
-	ll_req.txf_id_mask[1] =	0;
-
-	ll_req.rxf_id_mask[0] = htonl(bm[0]);
-	ll_req.rxf_id_mask[1] = htonl(bm[1]);
-
-	bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req),
-			bna_rxf_cb_stats_cleared, rxf);
-	bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
-}
-
-static void
-rxf_enable(struct bna_rxf *rxf)
-{
-	if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED)
-		bfa_fsm_send_event(rxf, RXF_E_STARTED);
-	else {
-		rxf->rxf_flags |= BNA_RXF_FL_RXF_ENABLED;
-		__rxf_enable(rxf);
-	}
-}
-
-static void
-rxf_cb_enabled(void *arg, int status)
-{
-	struct bna_rxf *rxf = (struct bna_rxf *)arg;
-
-	bfa_q_qe_init(&rxf->mbox_qe.qe);
-	bfa_fsm_send_event(rxf, RXF_E_STARTED);
-}
-
-static void
-rxf_disable(struct bna_rxf *rxf)
-{
-	if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED)
-		bfa_fsm_send_event(rxf, RXF_E_STOPPED);
-	else
-		rxf->rxf_flags &= ~BNA_RXF_FL_RXF_ENABLED;
-		__rxf_disable(rxf);
-}
-
-static void
-rxf_cb_disabled(void *arg, int status)
-{
-	struct bna_rxf *rxf = (struct bna_rxf *)arg;
-
-	bfa_q_qe_init(&rxf->mbox_qe.qe);
-	bfa_fsm_send_event(rxf, RXF_E_STOPPED);
-}
-
-void
-rxf_cb_cam_fltr_mbox_cmd(void *arg, int status)
-{
-	struct bna_rxf *rxf = (struct bna_rxf *)arg;
-
-	bfa_q_qe_init(&rxf->mbox_qe.qe);
-
-	bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_RESP);
-}
-
-static void
-bna_rxf_cb_stats_cleared(void *arg, int status)
-{
-	struct bna_rxf *rxf = (struct bna_rxf *)arg;
-
-	bfa_q_qe_init(&rxf->mbox_qe.qe);
-	bfa_fsm_send_event(rxf, RXF_E_STAT_CLEARED);
-}
-
-void
-rxf_cam_mbox_cmd(struct bna_rxf *rxf, u8 cmd,
-		const struct bna_mac *mac_addr)
-{
-	struct bfi_ll_mac_addr_req req;
-
-	bfi_h2i_set(req.mh, BFI_MC_LL, cmd, 0);
-
-	req.rxf_id = rxf->rxf_id;
-	memcpy(&req.mac_addr, (void *)&mac_addr->addr, ETH_ALEN);
-
-	bna_mbox_qe_fill(&rxf->mbox_qe, &req, sizeof(req),
-				rxf_cb_cam_fltr_mbox_cmd, rxf);
-
-	bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
-}
-
-static int
-rxf_process_packet_filter_mcast(struct bna_rxf *rxf)
-{
-	struct bna_mac *mac = NULL;
-	struct list_head *qe;
-
-	/* Add multicast entries */
-	if (!list_empty(&rxf->mcast_pending_add_q)) {
-		bfa_q_deq(&rxf->mcast_pending_add_q, &qe);
-		bfa_q_qe_init(qe);
-		mac = (struct bna_mac *)qe;
-		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_ADD_REQ, mac);
-		list_add_tail(&mac->qe, &rxf->mcast_active_q);
-		return 1;
-	}
-
-	/* Delete multicast entries previousely added */
-	if (!list_empty(&rxf->mcast_pending_del_q)) {
-		bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
-		bfa_q_qe_init(qe);
-		mac = (struct bna_mac *)qe;
-		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac);
-		bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
-		return 1;
-	}
-
-	return 0;
-}
-
-static int
-rxf_process_packet_filter_vlan(struct bna_rxf *rxf)
-{
-	/* Apply the VLAN filter */
-	if (rxf->rxf_flags & BNA_RXF_FL_VLAN_CONFIG_PENDING) {
-		rxf->rxf_flags &= ~BNA_RXF_FL_VLAN_CONFIG_PENDING;
-		if (!(rxf->rxmode_active & BNA_RXMODE_PROMISC))
-			__rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
-	}
-
-	/* Apply RSS configuration */
-	if (rxf->rxf_flags & BNA_RXF_FL_RSS_CONFIG_PENDING) {
-		rxf->rxf_flags &= ~BNA_RXF_FL_RSS_CONFIG_PENDING;
-		if (rxf->rss_status == BNA_STATUS_T_DISABLED) {
-			/* RSS is being disabled */
-			rxf->ctrl_flags &= ~BNA_RXF_CF_RSS_ENABLE;
-			__rxf_rit_set(rxf);
-			__rxf_config_set(rxf);
-		} else {
-			/* RSS is being enabled or reconfigured */
-			rxf->ctrl_flags |= BNA_RXF_CF_RSS_ENABLE;
-			__rxf_rit_set(rxf);
-			__rxf_config_set(rxf);
-		}
-	}
-
-	return 0;
-}
-
-/**
- * Processes pending ucast, mcast entry addition/deletion and issues mailbox
- * command. Also processes pending filter configuration - promiscuous mode,
- * default mode, allmutli mode and issues mailbox command or directly applies
- * to h/w
- */
-static int
-rxf_process_packet_filter(struct bna_rxf *rxf)
-{
-	/* Set the default MAC first */
-	if (rxf->ucast_pending_set > 0) {
-		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_SET_REQ,
-				rxf->ucast_active_mac);
-		rxf->ucast_pending_set--;
-		return 1;
-	}
-
-	if (rxf_process_packet_filter_ucast(rxf))
-		return 1;
-
-	if (rxf_process_packet_filter_mcast(rxf))
-		return 1;
-
-	if (rxf_process_packet_filter_promisc(rxf))
-		return 1;
-
-	if (rxf_process_packet_filter_allmulti(rxf))
-		return 1;
-
-	if (rxf_process_packet_filter_vlan(rxf))
-		return 1;
-
-	return 0;
-}
-
-static int
-rxf_clear_packet_filter_mcast(struct bna_rxf *rxf)
-{
-	struct bna_mac *mac = NULL;
-	struct list_head *qe;
-
-	/* 3. delete pending mcast entries */
-	if (!list_empty(&rxf->mcast_pending_del_q)) {
-		bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
-		bfa_q_qe_init(qe);
-		mac = (struct bna_mac *)qe;
-		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac);
-		bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
-		return 1;
-	}
-
-	/* 4. clear active mcast entries; move them to pending_add_q */
-	if (!list_empty(&rxf->mcast_active_q)) {
-		bfa_q_deq(&rxf->mcast_active_q, &qe);
-		bfa_q_qe_init(qe);
-		mac = (struct bna_mac *)qe;
-		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac);
-		list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
-		return 1;
-	}
-
-	return 0;
-}
-
-/**
- * In the rxf stop path, processes pending ucast/mcast delete queue and issues
- * the mailbox command. Moves the active ucast/mcast entries to pending add q,
- * so that they are added to CAM again in the rxf start path. Moves the current
- * filter settings - promiscuous, default, allmutli - to pending filter
- * configuration
- */
-static int
-rxf_clear_packet_filter(struct bna_rxf *rxf)
-{
-	if (rxf_clear_packet_filter_ucast(rxf))
-		return 1;
-
-	if (rxf_clear_packet_filter_mcast(rxf))
-		return 1;
-
-	/* 5. clear active default MAC in the CAM */
-	if (rxf->ucast_pending_set > 0)
-		rxf->ucast_pending_set = 0;
-
-	if (rxf_clear_packet_filter_promisc(rxf))
-		return 1;
-
-	if (rxf_clear_packet_filter_allmulti(rxf))
-		return 1;
-
-	return 0;
-}
-
-static void
-rxf_reset_packet_filter_mcast(struct bna_rxf *rxf)
-{
-	struct list_head *qe;
-	struct bna_mac *mac;
-
-	/* 3. Move active mcast entries to pending_add_q */
-	while (!list_empty(&rxf->mcast_active_q)) {
-		bfa_q_deq(&rxf->mcast_active_q, &qe);
-		bfa_q_qe_init(qe);
-		list_add_tail(qe, &rxf->mcast_pending_add_q);
-	}
-
-	/* 4. Throw away delete pending mcast entries */
-	while (!list_empty(&rxf->mcast_pending_del_q)) {
-		bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
-		bfa_q_qe_init(qe);
-		mac = (struct bna_mac *)qe;
-		bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
-	}
-}
-
-/**
- * In the rxf fail path, throws away the ucast/mcast entries pending for
- * deletion, moves all active ucast/mcast entries to pending queue so that
- * they are added back to CAM in the rxf start path. Also moves the current
- * filter configuration to pending filter configuration.
- */
-static void
-rxf_reset_packet_filter(struct bna_rxf *rxf)
-{
-	rxf_reset_packet_filter_ucast(rxf);
-
-	rxf_reset_packet_filter_mcast(rxf);
-
-	/* 5. Turn off ucast set flag */
-	rxf->ucast_pending_set = 0;
-
-	rxf_reset_packet_filter_promisc(rxf);
-
-	rxf_reset_packet_filter_allmulti(rxf);
-}
-
-static void
-bna_rxf_init(struct bna_rxf *rxf,
-		struct bna_rx *rx,
-		struct bna_rx_config *q_config)
-{
-	struct list_head *qe;
-	struct bna_rxp *rxp;
-
-	/* rxf_id is initialized during rx_mod init */
-	rxf->rx = rx;
-
-	INIT_LIST_HEAD(&rxf->ucast_pending_add_q);
-	INIT_LIST_HEAD(&rxf->ucast_pending_del_q);
-	rxf->ucast_pending_set = 0;
-	INIT_LIST_HEAD(&rxf->ucast_active_q);
-	rxf->ucast_active_mac = NULL;
-
-	INIT_LIST_HEAD(&rxf->mcast_pending_add_q);
-	INIT_LIST_HEAD(&rxf->mcast_pending_del_q);
-	INIT_LIST_HEAD(&rxf->mcast_active_q);
-
-	bfa_q_qe_init(&rxf->mbox_qe.qe);
-
-	if (q_config->vlan_strip_status == BNA_STATUS_T_ENABLED)
-		rxf->ctrl_flags |= BNA_RXF_CF_VLAN_STRIP;
-
-	rxf->rxf_oper_state = (q_config->paused) ?
-		BNA_RXF_OPER_STATE_PAUSED : BNA_RXF_OPER_STATE_RUNNING;
-
-	bna_rxf_adv_init(rxf, rx, q_config);
-
-	rxf->rit_segment = bna_rit_mod_seg_get(&rxf->rx->bna->rit_mod,
-					q_config->num_paths);
-
-	list_for_each(qe, &rx->rxp_q) {
-		rxp = (struct bna_rxp *)qe;
-		if (q_config->rxp_type == BNA_RXP_SINGLE)
-			rxf->mcast_rxq_id = rxp->rxq.single.only->rxq_id;
-		else
-			rxf->mcast_rxq_id = rxp->rxq.slr.large->rxq_id;
-		break;
-	}
-
-	rxf->vlan_filter_status = BNA_STATUS_T_DISABLED;
-	memset(rxf->vlan_filter_table, 0,
-			(sizeof(u32) * ((BFI_MAX_VLAN + 1) / 32)));
-
-	/* Set up VLAN 0 for pure priority tagged packets */
-	rxf->vlan_filter_table[0] |= 1;
-
-	bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
-}
-
-static void
-bna_rxf_uninit(struct bna_rxf *rxf)
-{
-	struct bna *bna = rxf->rx->bna;
-	struct bna_mac *mac;
-
-	bna_rit_mod_seg_put(&rxf->rx->bna->rit_mod, rxf->rit_segment);
-	rxf->rit_segment = NULL;
-
-	rxf->ucast_pending_set = 0;
-
-	while (!list_empty(&rxf->ucast_pending_add_q)) {
-		bfa_q_deq(&rxf->ucast_pending_add_q, &mac);
-		bfa_q_qe_init(&mac->qe);
-		bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
-	}
-
-	if (rxf->ucast_active_mac) {
-		bfa_q_qe_init(&rxf->ucast_active_mac->qe);
-		bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod,
-			rxf->ucast_active_mac);
-		rxf->ucast_active_mac = NULL;
-	}
-
-	while (!list_empty(&rxf->mcast_pending_add_q)) {
-		bfa_q_deq(&rxf->mcast_pending_add_q, &mac);
-		bfa_q_qe_init(&mac->qe);
-		bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
-	}
-
-	/* Turn off pending promisc mode */
-	if (is_promisc_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask)) {
-		/* system promisc state should be pending */
-		BUG_ON(!(bna->rxf_promisc_id == rxf->rxf_id));
-		promisc_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-		 bna->rxf_promisc_id = BFI_MAX_RXF;
-	}
-	/* Promisc mode should not be active */
-	BUG_ON(rxf->rxmode_active & BNA_RXMODE_PROMISC);
-
-	/* Turn off pending all-multi mode */
-	if (is_allmulti_enable(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask)) {
-		allmulti_inactive(rxf->rxmode_pending,
-				rxf->rxmode_pending_bitmask);
-	}
-	/* Allmulti mode should not be active */
-	BUG_ON(rxf->rxmode_active & BNA_RXMODE_ALLMULTI);
-
-	rxf->rx = NULL;
-}
-
-static void
-bna_rx_cb_rxf_started(struct bna_rx *rx, enum bna_cb_status status)
-{
-	bfa_fsm_send_event(rx, RX_E_RXF_STARTED);
-	if (rx->rxf.rxf_id < 32)
-		rx->bna->rx_mod.rxf_bmap[0] |= ((u32)1 << rx->rxf.rxf_id);
-	else
-		rx->bna->rx_mod.rxf_bmap[1] |= ((u32)
-				1 << (rx->rxf.rxf_id - 32));
-}
-
-static void
-bna_rxf_start(struct bna_rxf *rxf)
-{
-	rxf->start_cbfn = bna_rx_cb_rxf_started;
-	rxf->start_cbarg = rxf->rx;
-	rxf->rxf_flags &= ~BNA_RXF_FL_FAILED;
-	bfa_fsm_send_event(rxf, RXF_E_START);
-}
-
-static void
-bna_rx_cb_rxf_stopped(struct bna_rx *rx, enum bna_cb_status status)
-{
-	bfa_fsm_send_event(rx, RX_E_RXF_STOPPED);
-	if (rx->rxf.rxf_id < 32)
-		rx->bna->rx_mod.rxf_bmap[0] &= ~(u32)1 << rx->rxf.rxf_id;
-	else
-		rx->bna->rx_mod.rxf_bmap[1] &= ~(u32)
-				1 << (rx->rxf.rxf_id - 32);
-}
-
-static void
-bna_rxf_stop(struct bna_rxf *rxf)
-{
-	rxf->stop_cbfn = bna_rx_cb_rxf_stopped;
-	rxf->stop_cbarg = rxf->rx;
-	bfa_fsm_send_event(rxf, RXF_E_STOP);
-}
-
-static void
-bna_rxf_fail(struct bna_rxf *rxf)
-{
-	rxf->rxf_flags |= BNA_RXF_FL_FAILED;
-	bfa_fsm_send_event(rxf, RXF_E_FAIL);
-}
-
-int
-bna_rxf_state_get(struct bna_rxf *rxf)
-{
-	return bfa_sm_to_state(rxf_sm_table, rxf->fsm);
-}
-
-enum bna_cb_status
-bna_rx_ucast_set(struct bna_rx *rx, u8 *ucmac,
-		 void (*cbfn)(struct bnad *, struct bna_rx *,
-			      enum bna_cb_status))
-{
-	struct bna_rxf *rxf = &rx->rxf;
-
-	if (rxf->ucast_active_mac == NULL) {
-		rxf->ucast_active_mac =
-				bna_ucam_mod_mac_get(&rxf->rx->bna->ucam_mod);
-		if (rxf->ucast_active_mac == NULL)
-			return BNA_CB_UCAST_CAM_FULL;
-		bfa_q_qe_init(&rxf->ucast_active_mac->qe);
-	}
-
-	memcpy(rxf->ucast_active_mac->addr, ucmac, ETH_ALEN);
-	rxf->ucast_pending_set++;
-	rxf->cam_fltr_cbfn = cbfn;
-	rxf->cam_fltr_cbarg = rx->bna->bnad;
-
-	bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
-
-	return BNA_CB_SUCCESS;
-}
-
-enum bna_cb_status
-bna_rx_mcast_add(struct bna_rx *rx, u8 *addr,
-		 void (*cbfn)(struct bnad *, struct bna_rx *,
-			      enum bna_cb_status))
-{
-	struct bna_rxf *rxf = &rx->rxf;
-	struct list_head	*qe;
-	struct bna_mac *mac;
-
-	/* Check if already added */
-	list_for_each(qe, &rxf->mcast_active_q) {
-		mac = (struct bna_mac *)qe;
-		if (BNA_MAC_IS_EQUAL(mac->addr, addr)) {
-			if (cbfn)
-				(*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
-			return BNA_CB_SUCCESS;
-		}
-	}
-
-	/* Check if pending addition */
-	list_for_each(qe, &rxf->mcast_pending_add_q) {
-		mac = (struct bna_mac *)qe;
-		if (BNA_MAC_IS_EQUAL(mac->addr, addr)) {
-			if (cbfn)
-				(*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
-			return BNA_CB_SUCCESS;
-		}
-	}
-
-	mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod);
-	if (mac == NULL)
-		return BNA_CB_MCAST_LIST_FULL;
-	bfa_q_qe_init(&mac->qe);
-	memcpy(mac->addr, addr, ETH_ALEN);
-	list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
-
-	rxf->cam_fltr_cbfn = cbfn;
-	rxf->cam_fltr_cbarg = rx->bna->bnad;
-
-	bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
-
-	return BNA_CB_SUCCESS;
-}
-
-enum bna_cb_status
-bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mclist,
-		     void (*cbfn)(struct bnad *, struct bna_rx *,
-				  enum bna_cb_status))
-{
-	struct bna_rxf *rxf = &rx->rxf;
-	struct list_head list_head;
-	struct list_head *qe;
-	u8 *mcaddr;
-	struct bna_mac *mac;
-	struct bna_mac *mac1;
-	int skip;
-	int delete;
-	int need_hw_config = 0;
-	int i;
-
-	/* Allocate nodes */
-	INIT_LIST_HEAD(&list_head);
-	for (i = 0, mcaddr = mclist; i < count; i++) {
-		mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod);
-		if (mac == NULL)
-			goto err_return;
-		bfa_q_qe_init(&mac->qe);
-		memcpy(mac->addr, mcaddr, ETH_ALEN);
-		list_add_tail(&mac->qe, &list_head);
-
-		mcaddr += ETH_ALEN;
-	}
-
-	/* Schedule for addition */
-	while (!list_empty(&list_head)) {
-		bfa_q_deq(&list_head, &qe);
-		mac = (struct bna_mac *)qe;
-		bfa_q_qe_init(&mac->qe);
-
-		skip = 0;
-
-		/* Skip if already added */
-		list_for_each(qe, &rxf->mcast_active_q) {
-			mac1 = (struct bna_mac *)qe;
-			if (BNA_MAC_IS_EQUAL(mac1->addr, mac->addr)) {
-				bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod,
-							mac);
-				skip = 1;
-				break;
-			}
-		}
-
-		if (skip)
-			continue;
-
-		/* Skip if pending addition */
-		list_for_each(qe, &rxf->mcast_pending_add_q) {
-			mac1 = (struct bna_mac *)qe;
-			if (BNA_MAC_IS_EQUAL(mac1->addr, mac->addr)) {
-				bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod,
-							mac);
-				skip = 1;
-				break;
-			}
-		}
-
-		if (skip)
-			continue;
-
-		need_hw_config = 1;
-		list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
-	}
-
-	/**
-	 * Delete the entries that are in the pending_add_q but not
-	 * in the new list
-	 */
-	while (!list_empty(&rxf->mcast_pending_add_q)) {
-		bfa_q_deq(&rxf->mcast_pending_add_q, &qe);
-		mac = (struct bna_mac *)qe;
-		bfa_q_qe_init(&mac->qe);
-		for (i = 0, mcaddr = mclist, delete = 1; i < count; i++) {
-			if (BNA_MAC_IS_EQUAL(mcaddr, mac->addr)) {
-				delete = 0;
-				break;
-			}
-			mcaddr += ETH_ALEN;
-		}
-		if (delete)
-			bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
-		else
-			list_add_tail(&mac->qe, &list_head);
-	}
-	while (!list_empty(&list_head)) {
-		bfa_q_deq(&list_head, &qe);
-		mac = (struct bna_mac *)qe;
-		bfa_q_qe_init(&mac->qe);
-		list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
-	}
-
-	/**
-	 * Schedule entries for deletion that are in the active_q but not
-	 * in the new list
-	 */
-	while (!list_empty(&rxf->mcast_active_q)) {
-		bfa_q_deq(&rxf->mcast_active_q, &qe);
-		mac = (struct bna_mac *)qe;
-		bfa_q_qe_init(&mac->qe);
-		for (i = 0, mcaddr = mclist, delete = 1; i < count; i++) {
-			if (BNA_MAC_IS_EQUAL(mcaddr, mac->addr)) {
-				delete = 0;
-				break;
-			}
-			mcaddr += ETH_ALEN;
-		}
-		if (delete) {
-			list_add_tail(&mac->qe, &rxf->mcast_pending_del_q);
-			need_hw_config = 1;
-		} else {
-			list_add_tail(&mac->qe, &list_head);
-		}
-	}
-	while (!list_empty(&list_head)) {
-		bfa_q_deq(&list_head, &qe);
-		mac = (struct bna_mac *)qe;
-		bfa_q_qe_init(&mac->qe);
-		list_add_tail(&mac->qe, &rxf->mcast_active_q);
-	}
-
-	if (need_hw_config) {
-		rxf->cam_fltr_cbfn = cbfn;
-		rxf->cam_fltr_cbarg = rx->bna->bnad;
-		bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
-	} else if (cbfn)
-		(*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
-
-	return BNA_CB_SUCCESS;
-
-err_return:
-	while (!list_empty(&list_head)) {
-		bfa_q_deq(&list_head, &qe);
-		mac = (struct bna_mac *)qe;
-		bfa_q_qe_init(&mac->qe);
-		bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
-	}
-
-	return BNA_CB_MCAST_LIST_FULL;
-}
-
-void
-bna_rx_vlan_add(struct bna_rx *rx, int vlan_id)
-{
-	struct bna_rxf *rxf = &rx->rxf;
-	int index = (vlan_id >> 5);
-	int bit = (1 << (vlan_id & 0x1F));
-
-	rxf->vlan_filter_table[index] |= bit;
-	if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) {
-		rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
-		bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
-	}
-}
-
-void
-bna_rx_vlan_del(struct bna_rx *rx, int vlan_id)
-{
-	struct bna_rxf *rxf = &rx->rxf;
-	int index = (vlan_id >> 5);
-	int bit = (1 << (vlan_id & 0x1F));
-
-	rxf->vlan_filter_table[index] &= ~bit;
-	if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) {
-		rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
-		bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
-	}
-}
-
-/**
- * RX
- */
-#define	RXQ_RCB_INIT(q, rxp, qdepth, bna, _id, unmapq_mem)	do {	\
-	struct bna_doorbell_qset *_qset;				\
-	unsigned long off;						\
-	(q)->rcb->producer_index = (q)->rcb->consumer_index = 0;	\
-	(q)->rcb->q_depth = (qdepth);					\
-	(q)->rcb->unmap_q = unmapq_mem;					\
-	(q)->rcb->rxq = (q);						\
-	(q)->rcb->cq = &(rxp)->cq;					\
-	(q)->rcb->bnad = (bna)->bnad;					\
-	_qset = (struct bna_doorbell_qset *)0;			\
-	off = (unsigned long)&_qset[(q)->rxq_id].rxq[0];		\
-	(q)->rcb->q_dbell = off +					\
-		BNA_GET_DOORBELL_BASE_ADDR((bna)->pcidev.pci_bar_kva);	\
-	(q)->rcb->id = _id;						\
-} while (0)
-
-#define	BNA_GET_RXQS(qcfg)	(((qcfg)->rxp_type == BNA_RXP_SINGLE) ?	\
-	(qcfg)->num_paths : ((qcfg)->num_paths * 2))
-
-#define	SIZE_TO_PAGES(size)	(((size) >> PAGE_SHIFT) + ((((size) &\
-	(PAGE_SIZE - 1)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
-
-#define	call_rx_stop_callback(rx, status)				\
-	if ((rx)->stop_cbfn) {						\
-		(*(rx)->stop_cbfn)((rx)->stop_cbarg, rx, (status));	\
-		(rx)->stop_cbfn = NULL;					\
-		(rx)->stop_cbarg = NULL;				\
-	}
-
-/*
- * Since rx_enable is synchronous callback, there is no start_cbfn required.
- * Instead, we'll call bnad_rx_post(rxp) so that bnad can post the buffers
- * for each rxpath.
- */
-
-#define	call_rx_disable_cbfn(rx, status)				\
-		if ((rx)->disable_cbfn)	{				\
-			(*(rx)->disable_cbfn)((rx)->disable_cbarg,	\
-					status);			\
-			(rx)->disable_cbfn = NULL;			\
-			(rx)->disable_cbarg = NULL;			\
-		}							\
-
-#define	rxqs_reqd(type, num_rxqs)					\
-	(((type) == BNA_RXP_SINGLE) ? (num_rxqs) : ((num_rxqs) * 2))
-
-#define rx_ib_fail(rx)						\
-do {								\
-	struct bna_rxp *rxp;					\
-	struct list_head *qe;						\
-	list_for_each(qe, &(rx)->rxp_q) {				\
-		rxp = (struct bna_rxp *)qe;			\
-		bna_ib_fail(rxp->cq.ib);			\
-	}							\
-} while (0)
-
-static void __bna_multi_rxq_stop(struct bna_rxp *, u32 *);
-static void __bna_rxq_start(struct bna_rxq *rxq);
-static void __bna_cq_start(struct bna_cq *cq);
-static void bna_rit_create(struct bna_rx *rx);
-static void bna_rx_cb_multi_rxq_stopped(void *arg, int status);
-static void bna_rx_cb_rxq_stopped_all(void *arg);
-
-bfa_fsm_state_decl(bna_rx, stopped,
-	struct bna_rx, enum bna_rx_event);
-bfa_fsm_state_decl(bna_rx, rxf_start_wait,
-	struct bna_rx, enum bna_rx_event);
-bfa_fsm_state_decl(bna_rx, started,
-	struct bna_rx, enum bna_rx_event);
-bfa_fsm_state_decl(bna_rx, rxf_stop_wait,
-	struct bna_rx, enum bna_rx_event);
-bfa_fsm_state_decl(bna_rx, rxq_stop_wait,
-	struct bna_rx, enum bna_rx_event);
-
-static const struct bfa_sm_table rx_sm_table[] = {
-	{BFA_SM(bna_rx_sm_stopped), BNA_RX_STOPPED},
-	{BFA_SM(bna_rx_sm_rxf_start_wait), BNA_RX_RXF_START_WAIT},
-	{BFA_SM(bna_rx_sm_started), BNA_RX_STARTED},
-	{BFA_SM(bna_rx_sm_rxf_stop_wait), BNA_RX_RXF_STOP_WAIT},
-	{BFA_SM(bna_rx_sm_rxq_stop_wait), BNA_RX_RXQ_STOP_WAIT},
-};
-
-static void bna_rx_sm_stopped_entry(struct bna_rx *rx)
-{
-	struct bna_rxp *rxp;
-	struct list_head *qe_rxp;
-
-	list_for_each(qe_rxp, &rx->rxp_q) {
-		rxp = (struct bna_rxp *)qe_rxp;
-		rx->rx_cleanup_cbfn(rx->bna->bnad, rxp->cq.ccb);
-	}
-
-	call_rx_stop_callback(rx, BNA_CB_SUCCESS);
-}
-
-static void bna_rx_sm_stopped(struct bna_rx *rx,
-				enum bna_rx_event event)
-{
-	switch (event) {
-	case RX_E_START:
-		bfa_fsm_set_state(rx, bna_rx_sm_rxf_start_wait);
-		break;
-	case RX_E_STOP:
-		call_rx_stop_callback(rx, BNA_CB_SUCCESS);
-		break;
-	case RX_E_FAIL:
-		/* no-op */
-		break;
-	default:
-		bfa_sm_fault(event);
-		break;
-	}
-
-}
-
-static void bna_rx_sm_rxf_start_wait_entry(struct bna_rx *rx)
-{
-	struct bna_rxp *rxp;
-	struct list_head *qe_rxp;
-	struct bna_rxq *q0 = NULL, *q1 = NULL;
-
-	/* Setup the RIT */
-	bna_rit_create(rx);
-
-	list_for_each(qe_rxp, &rx->rxp_q) {
-		rxp = (struct bna_rxp *)qe_rxp;
-		bna_ib_start(rxp->cq.ib);
-		GET_RXQS(rxp, q0, q1);
-		q0->buffer_size = bna_port_mtu_get(&rx->bna->port);
-		__bna_rxq_start(q0);
-		rx->rx_post_cbfn(rx->bna->bnad, q0->rcb);
-		if (q1)  {
-			__bna_rxq_start(q1);
-			rx->rx_post_cbfn(rx->bna->bnad, q1->rcb);
-		}
-		__bna_cq_start(&rxp->cq);
-	}
-
-	bna_rxf_start(&rx->rxf);
-}
-
-static void bna_rx_sm_rxf_start_wait(struct bna_rx *rx,
-				enum bna_rx_event event)
-{
-	switch (event) {
-	case RX_E_STOP:
-		bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
-		break;
-	case RX_E_FAIL:
-		bfa_fsm_set_state(rx, bna_rx_sm_stopped);
-		rx_ib_fail(rx);
-		bna_rxf_fail(&rx->rxf);
-		break;
-	case RX_E_RXF_STARTED:
-		bfa_fsm_set_state(rx, bna_rx_sm_started);
-		break;
-	default:
-		bfa_sm_fault(event);
-		break;
-	}
-}
-
-void
-bna_rx_sm_started_entry(struct bna_rx *rx)
-{
-	struct bna_rxp *rxp;
-	struct list_head *qe_rxp;
-
-	/* Start IB */
-	list_for_each(qe_rxp, &rx->rxp_q) {
-		rxp = (struct bna_rxp *)qe_rxp;
-		bna_ib_ack(&rxp->cq.ib->door_bell, 0);
-	}
-
-	bna_llport_rx_started(&rx->bna->port.llport);
-}
-
-void
-bna_rx_sm_started(struct bna_rx *rx, enum bna_rx_event event)
-{
-	switch (event) {
-	case RX_E_FAIL:
-		bna_llport_rx_stopped(&rx->bna->port.llport);
-		bfa_fsm_set_state(rx, bna_rx_sm_stopped);
-		rx_ib_fail(rx);
-		bna_rxf_fail(&rx->rxf);
-		break;
-	case RX_E_STOP:
-		bna_llport_rx_stopped(&rx->bna->port.llport);
-		bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
-		break;
-	default:
-		bfa_sm_fault(event);
-		break;
-	}
-}
-
-void
-bna_rx_sm_rxf_stop_wait_entry(struct bna_rx *rx)
-{
-	bna_rxf_stop(&rx->rxf);
-}
-
-void
-bna_rx_sm_rxf_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
-{
-	switch (event) {
-	case RX_E_RXF_STOPPED:
-		bfa_fsm_set_state(rx, bna_rx_sm_rxq_stop_wait);
-		break;
-	case RX_E_RXF_STARTED:
-		/**
-		 * RxF was in the process of starting up when
-		 * RXF_E_STOP was issued. Ignore this event
-		 */
-		break;
-	case RX_E_FAIL:
-		bfa_fsm_set_state(rx, bna_rx_sm_stopped);
-		rx_ib_fail(rx);
-		bna_rxf_fail(&rx->rxf);
-		break;
-	default:
-		bfa_sm_fault(event);
-		break;
-	}
-
-}
-
-void
-bna_rx_sm_rxq_stop_wait_entry(struct bna_rx *rx)
-{
-	struct bna_rxp *rxp = NULL;
-	struct bna_rxq *q0 = NULL;
-	struct bna_rxq *q1 = NULL;
-	struct list_head	*qe;
-	u32 rxq_mask[2] = {0, 0};
-
-	/* Only one call to multi-rxq-stop for all RXPs in this RX */
-	bfa_wc_up(&rx->rxq_stop_wc);
-	list_for_each(qe, &rx->rxp_q) {
-		rxp = (struct bna_rxp *)qe;
-		GET_RXQS(rxp, q0, q1);
-		if (q0->rxq_id < 32)
-			rxq_mask[0] |= ((u32)1 << q0->rxq_id);
-		else
-			rxq_mask[1] |= ((u32)1 << (q0->rxq_id - 32));
-		if (q1) {
-			if (q1->rxq_id < 32)
-				rxq_mask[0] |= ((u32)1 << q1->rxq_id);
-			else
-				rxq_mask[1] |= ((u32)
-						1 << (q1->rxq_id - 32));
-		}
-	}
-
-	__bna_multi_rxq_stop(rxp, rxq_mask);
-}
-
-void
-bna_rx_sm_rxq_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
-{
-	struct bna_rxp *rxp = NULL;
-	struct list_head	*qe;
-
-	switch (event) {
-	case RX_E_RXQ_STOPPED:
-		list_for_each(qe, &rx->rxp_q) {
-			rxp = (struct bna_rxp *)qe;
-			bna_ib_stop(rxp->cq.ib);
-		}
-		/* Fall through */
-	case RX_E_FAIL:
-		bfa_fsm_set_state(rx, bna_rx_sm_stopped);
-		break;
-	default:
-		bfa_sm_fault(event);
-		break;
-	}
-}
-
-void
-__bna_multi_rxq_stop(struct bna_rxp *rxp, u32 * rxq_id_mask)
-{
-	struct bfi_ll_q_stop_req ll_req;
-
-	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RXQ_STOP_REQ, 0);
-	ll_req.q_id_mask[0] = htonl(rxq_id_mask[0]);
-	ll_req.q_id_mask[1] = htonl(rxq_id_mask[1]);
-	bna_mbox_qe_fill(&rxp->mbox_qe, &ll_req, sizeof(ll_req),
-		bna_rx_cb_multi_rxq_stopped, rxp);
-	bna_mbox_send(rxp->rx->bna, &rxp->mbox_qe);
-}
-
-void
-__bna_rxq_start(struct bna_rxq *rxq)
-{
-	struct bna_rxtx_q_mem *q_mem;
-	struct bna_rxq_mem rxq_cfg, *rxq_mem;
-	struct bna_dma_addr cur_q_addr;
-	/* struct bna_doorbell_qset *qset; */
-	struct bna_qpt *qpt;
-	u32 pg_num;
-	struct bna *bna = rxq->rx->bna;
-	void __iomem *base_addr;
-	unsigned long off;
-
-	qpt = &rxq->qpt;
-	cur_q_addr = *((struct bna_dma_addr *)(qpt->kv_qpt_ptr));
-
-	rxq_cfg.pg_tbl_addr_lo = qpt->hw_qpt_ptr.lsb;
-	rxq_cfg.pg_tbl_addr_hi = qpt->hw_qpt_ptr.msb;
-	rxq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
-	rxq_cfg.cur_q_entry_hi = cur_q_addr.msb;
-
-	rxq_cfg.pg_cnt_n_prd_ptr = ((u32)qpt->page_count << 16) | 0x0;
-	rxq_cfg.entry_n_pg_size = ((u32)(BFI_RXQ_WI_SIZE >> 2) << 16) |
-		(qpt->page_size >> 2);
-	rxq_cfg.sg_n_cq_n_cns_ptr =
-		((u32)(rxq->rxp->cq.cq_id & 0xff) << 16) | 0x0;
-	rxq_cfg.buf_sz_n_q_state = ((u32)rxq->buffer_size << 16) |
-		BNA_Q_IDLE_STATE;
-	rxq_cfg.next_qid = 0x0 | (0x3 << 8);
-
-	/* Write the page number register */
-	pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + bna->port_num,
-			HQM_RXTX_Q_RAM_BASE_OFFSET);
-	writel(pg_num, bna->regs.page_addr);
-
-	/* Write to h/w */
-	base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
-					HQM_RXTX_Q_RAM_BASE_OFFSET);
-
-	q_mem = (struct bna_rxtx_q_mem *)0;
-	rxq_mem = &q_mem[rxq->rxq_id].rxq;
-
-	off = (unsigned long)&rxq_mem->pg_tbl_addr_lo;
-	writel(htonl(rxq_cfg.pg_tbl_addr_lo), base_addr + off);
-
-	off = (unsigned long)&rxq_mem->pg_tbl_addr_hi;
-	writel(htonl(rxq_cfg.pg_tbl_addr_hi), base_addr + off);
-
-	off = (unsigned long)&rxq_mem->cur_q_entry_lo;
-	writel(htonl(rxq_cfg.cur_q_entry_lo), base_addr + off);
-
-	off = (unsigned long)&rxq_mem->cur_q_entry_hi;
-	writel(htonl(rxq_cfg.cur_q_entry_hi), base_addr + off);
-
-	off = (unsigned long)&rxq_mem->pg_cnt_n_prd_ptr;
-	writel(rxq_cfg.pg_cnt_n_prd_ptr, base_addr + off);
-
-	off = (unsigned long)&rxq_mem->entry_n_pg_size;
-	writel(rxq_cfg.entry_n_pg_size, base_addr + off);
-
-	off = (unsigned long)&rxq_mem->sg_n_cq_n_cns_ptr;
-	writel(rxq_cfg.sg_n_cq_n_cns_ptr, base_addr + off);
-
-	off = (unsigned long)&rxq_mem->buf_sz_n_q_state;
-	writel(rxq_cfg.buf_sz_n_q_state, base_addr + off);
-
-	off = (unsigned long)&rxq_mem->next_qid;
-	writel(rxq_cfg.next_qid, base_addr + off);
-
-	rxq->rcb->producer_index = 0;
-	rxq->rcb->consumer_index = 0;
-}
-
-void
-__bna_cq_start(struct bna_cq *cq)
-{
-	struct bna_cq_mem cq_cfg, *cq_mem;
-	const struct bna_qpt *qpt;
-	struct bna_dma_addr cur_q_addr;
-	u32 pg_num;
-	struct bna *bna = cq->rx->bna;
-	void __iomem *base_addr;
-	unsigned long off;
-
-	qpt = &cq->qpt;
-	cur_q_addr = *((struct bna_dma_addr *)(qpt->kv_qpt_ptr));
-
-	/*
-	 * Fill out structure, to be subsequently written
-	 * to hardware
-	 */
-	cq_cfg.pg_tbl_addr_lo = qpt->hw_qpt_ptr.lsb;
-	cq_cfg.pg_tbl_addr_hi = qpt->hw_qpt_ptr.msb;
-	cq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
-	cq_cfg.cur_q_entry_hi = cur_q_addr.msb;
-
-	cq_cfg.pg_cnt_n_prd_ptr = (qpt->page_count << 16) | 0x0;
-	cq_cfg.entry_n_pg_size =
-		((u32)(BFI_CQ_WI_SIZE >> 2) << 16) | (qpt->page_size >> 2);
-	cq_cfg.int_blk_n_cns_ptr = ((((u32)cq->ib_seg_offset) << 24) |
-			((u32)(cq->ib->ib_id & 0xff)  << 16) | 0x0);
-	cq_cfg.q_state = BNA_Q_IDLE_STATE;
-
-	/* Write the page number register */
-	pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + bna->port_num,
-				  HQM_CQ_RAM_BASE_OFFSET);
-
-	writel(pg_num, bna->regs.page_addr);
-
-	/* H/W write */
-	base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
-					HQM_CQ_RAM_BASE_OFFSET);
-
-	cq_mem = (struct bna_cq_mem *)0;
-
-	off = (unsigned long)&cq_mem[cq->cq_id].pg_tbl_addr_lo;
-	writel(htonl(cq_cfg.pg_tbl_addr_lo), base_addr + off);
-
-	off = (unsigned long)&cq_mem[cq->cq_id].pg_tbl_addr_hi;
-	writel(htonl(cq_cfg.pg_tbl_addr_hi), base_addr + off);
-
-	off = (unsigned long)&cq_mem[cq->cq_id].cur_q_entry_lo;
-	writel(htonl(cq_cfg.cur_q_entry_lo), base_addr + off);
-
-	off = (unsigned long)&cq_mem[cq->cq_id].cur_q_entry_hi;
-	writel(htonl(cq_cfg.cur_q_entry_hi), base_addr + off);
-
-	off = (unsigned long)&cq_mem[cq->cq_id].pg_cnt_n_prd_ptr;
-	writel(cq_cfg.pg_cnt_n_prd_ptr, base_addr + off);
-
-	off = (unsigned long)&cq_mem[cq->cq_id].entry_n_pg_size;
-	writel(cq_cfg.entry_n_pg_size, base_addr + off);
-
-	off = (unsigned long)&cq_mem[cq->cq_id].int_blk_n_cns_ptr;
-	writel(cq_cfg.int_blk_n_cns_ptr, base_addr + off);
-
-	off = (unsigned long)&cq_mem[cq->cq_id].q_state;
-	writel(cq_cfg.q_state, base_addr + off);
-
-	cq->ccb->producer_index = 0;
-	*(cq->ccb->hw_producer_index) = 0;
-}
-
-void
-bna_rit_create(struct bna_rx *rx)
-{
-	struct list_head	*qe_rxp;
-	struct bna_rxp *rxp;
-	struct bna_rxq *q0 = NULL;
-	struct bna_rxq *q1 = NULL;
-	int offset;
-
-	offset = 0;
-	list_for_each(qe_rxp, &rx->rxp_q) {
-		rxp = (struct bna_rxp *)qe_rxp;
-		GET_RXQS(rxp, q0, q1);
-		rx->rxf.rit_segment->rit[offset].large_rxq_id = q0->rxq_id;
-		rx->rxf.rit_segment->rit[offset].small_rxq_id =
-						(q1 ? q1->rxq_id : 0);
-		offset++;
-	}
-}
-
-static int
-_rx_can_satisfy(struct bna_rx_mod *rx_mod,
-		struct bna_rx_config *rx_cfg)
-{
-	if ((rx_mod->rx_free_count == 0) ||
-		(rx_mod->rxp_free_count == 0) ||
-		(rx_mod->rxq_free_count == 0))
-		return 0;
-
-	if (rx_cfg->rxp_type == BNA_RXP_SINGLE) {
-		if ((rx_mod->rxp_free_count < rx_cfg->num_paths) ||
-			(rx_mod->rxq_free_count < rx_cfg->num_paths))
-				return 0;
-	} else {
-		if ((rx_mod->rxp_free_count < rx_cfg->num_paths) ||
-			(rx_mod->rxq_free_count < (2 * rx_cfg->num_paths)))
-			return 0;
-	}
-
-	if (!bna_rit_mod_can_satisfy(&rx_mod->bna->rit_mod, rx_cfg->num_paths))
-		return 0;
-
-	return 1;
-}
-
-static struct bna_rxq *
-_get_free_rxq(struct bna_rx_mod *rx_mod)
-{
-	struct bna_rxq *rxq = NULL;
-	struct list_head	*qe = NULL;
-
-	bfa_q_deq(&rx_mod->rxq_free_q, &qe);
-	if (qe) {
-		rx_mod->rxq_free_count--;
-		rxq = (struct bna_rxq *)qe;
-	}
-	return rxq;
-}
-
-static void
-_put_free_rxq(struct bna_rx_mod *rx_mod, struct bna_rxq *rxq)
-{
-	bfa_q_qe_init(&rxq->qe);
-	list_add_tail(&rxq->qe, &rx_mod->rxq_free_q);
-	rx_mod->rxq_free_count++;
-}
-
-static struct bna_rxp *
-_get_free_rxp(struct bna_rx_mod *rx_mod)
-{
-	struct list_head	*qe = NULL;
-	struct bna_rxp *rxp = NULL;
-
-	bfa_q_deq(&rx_mod->rxp_free_q, &qe);
-	if (qe) {
-		rx_mod->rxp_free_count--;
-
-		rxp = (struct bna_rxp *)qe;
-	}
-
-	return rxp;
-}
-
-static void
-_put_free_rxp(struct bna_rx_mod *rx_mod, struct bna_rxp *rxp)
-{
-	bfa_q_qe_init(&rxp->qe);
-	list_add_tail(&rxp->qe, &rx_mod->rxp_free_q);
-	rx_mod->rxp_free_count++;
-}
-
-static struct bna_rx *
-_get_free_rx(struct bna_rx_mod *rx_mod)
-{
-	struct list_head	*qe = NULL;
-	struct bna_rx *rx = NULL;
-
-	bfa_q_deq(&rx_mod->rx_free_q, &qe);
-	if (qe) {
-		rx_mod->rx_free_count--;
-
-		rx = (struct bna_rx *)qe;
-		bfa_q_qe_init(qe);
-		list_add_tail(&rx->qe, &rx_mod->rx_active_q);
-	}
-
-	return rx;
-}
-
-static void
-_put_free_rx(struct bna_rx_mod *rx_mod, struct bna_rx *rx)
-{
-	bfa_q_qe_init(&rx->qe);
-	list_add_tail(&rx->qe, &rx_mod->rx_free_q);
-	rx_mod->rx_free_count++;
-}
-
-static void
-_rx_init(struct bna_rx *rx, struct bna *bna)
-{
-	rx->bna = bna;
-	rx->rx_flags = 0;
-
-	INIT_LIST_HEAD(&rx->rxp_q);
-
-	rx->rxq_stop_wc.wc_resume = bna_rx_cb_rxq_stopped_all;
-	rx->rxq_stop_wc.wc_cbarg = rx;
-	rx->rxq_stop_wc.wc_count = 0;
-
-	rx->stop_cbfn = NULL;
-	rx->stop_cbarg = NULL;
-}
-
-static void
-_rxp_add_rxqs(struct bna_rxp *rxp,
-		struct bna_rxq *q0,
-		struct bna_rxq *q1)
-{
-	switch (rxp->type) {
-	case BNA_RXP_SINGLE:
-		rxp->rxq.single.only = q0;
-		rxp->rxq.single.reserved = NULL;
-		break;
-	case BNA_RXP_SLR:
-		rxp->rxq.slr.large = q0;
-		rxp->rxq.slr.small = q1;
-		break;
-	case BNA_RXP_HDS:
-		rxp->rxq.hds.data = q0;
-		rxp->rxq.hds.hdr = q1;
-		break;
-	default:
-		break;
-	}
-}
-
-static void
-_rxq_qpt_init(struct bna_rxq *rxq,
-		struct bna_rxp *rxp,
-		u32 page_count,
-		u32 page_size,
-		struct bna_mem_descr *qpt_mem,
-		struct bna_mem_descr *swqpt_mem,
-		struct bna_mem_descr *page_mem)
-{
-	int	i;
-
-	rxq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
-	rxq->qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
-	rxq->qpt.kv_qpt_ptr = qpt_mem->kva;
-	rxq->qpt.page_count = page_count;
-	rxq->qpt.page_size = page_size;
-
-	rxq->rcb->sw_qpt = (void **) swqpt_mem->kva;
-
-	for (i = 0; i < rxq->qpt.page_count; i++) {
-		rxq->rcb->sw_qpt[i] = page_mem[i].kva;
-		((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].lsb =
-			page_mem[i].dma.lsb;
-		((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].msb =
-			page_mem[i].dma.msb;
-
-	}
-}
-
-static void
-_rxp_cqpt_setup(struct bna_rxp *rxp,
-		u32 page_count,
-		u32 page_size,
-		struct bna_mem_descr *qpt_mem,
-		struct bna_mem_descr *swqpt_mem,
-		struct bna_mem_descr *page_mem)
-{
-	int	i;
-
-	rxp->cq.qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
-	rxp->cq.qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
-	rxp->cq.qpt.kv_qpt_ptr = qpt_mem->kva;
-	rxp->cq.qpt.page_count = page_count;
-	rxp->cq.qpt.page_size = page_size;
-
-	rxp->cq.ccb->sw_qpt = (void **) swqpt_mem->kva;
-
-	for (i = 0; i < rxp->cq.qpt.page_count; i++) {
-		rxp->cq.ccb->sw_qpt[i] = page_mem[i].kva;
-
-		((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].lsb =
-			page_mem[i].dma.lsb;
-		((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].msb =
-			page_mem[i].dma.msb;
-
-	}
-}
-
-static void
-_rx_add_rxp(struct bna_rx *rx, struct bna_rxp *rxp)
-{
-	list_add_tail(&rxp->qe, &rx->rxp_q);
-}
-
-static void
-_init_rxmod_queues(struct bna_rx_mod *rx_mod)
-{
-	INIT_LIST_HEAD(&rx_mod->rx_free_q);
-	INIT_LIST_HEAD(&rx_mod->rxq_free_q);
-	INIT_LIST_HEAD(&rx_mod->rxp_free_q);
-	INIT_LIST_HEAD(&rx_mod->rx_active_q);
-
-	rx_mod->rx_free_count = 0;
-	rx_mod->rxq_free_count = 0;
-	rx_mod->rxp_free_count = 0;
-}
-
-static void
-_rx_ctor(struct bna_rx *rx, int id)
-{
-	bfa_q_qe_init(&rx->qe);
-	INIT_LIST_HEAD(&rx->rxp_q);
-	rx->bna = NULL;
-
-	rx->rxf.rxf_id = id;
-
-	/* FIXME: mbox_qe ctor()?? */
-	bfa_q_qe_init(&rx->mbox_qe.qe);
-
-	rx->stop_cbfn = NULL;
-	rx->stop_cbarg = NULL;
-}
-
-void
-bna_rx_cb_multi_rxq_stopped(void *arg, int status)
-{
-	struct bna_rxp *rxp = (struct bna_rxp *)arg;
-
-	bfa_wc_down(&rxp->rx->rxq_stop_wc);
-}
-
-void
-bna_rx_cb_rxq_stopped_all(void *arg)
-{
-	struct bna_rx *rx = (struct bna_rx *)arg;
-
-	bfa_fsm_send_event(rx, RX_E_RXQ_STOPPED);
-}
-
-static void
-bna_rx_mod_cb_rx_stopped(void *arg, struct bna_rx *rx,
-			 enum bna_cb_status status)
-{
-	struct bna_rx_mod *rx_mod = (struct bna_rx_mod *)arg;
-
-	bfa_wc_down(&rx_mod->rx_stop_wc);
-}
-
-static void
-bna_rx_mod_cb_rx_stopped_all(void *arg)
-{
-	struct bna_rx_mod *rx_mod = (struct bna_rx_mod *)arg;
-
-	if (rx_mod->stop_cbfn)
-		rx_mod->stop_cbfn(&rx_mod->bna->port, BNA_CB_SUCCESS);
-	rx_mod->stop_cbfn = NULL;
-}
-
-static void
-bna_rx_start(struct bna_rx *rx)
-{
-	rx->rx_flags |= BNA_RX_F_PORT_ENABLED;
-	if (rx->rx_flags & BNA_RX_F_ENABLE)
-		bfa_fsm_send_event(rx, RX_E_START);
-}
-
-static void
-bna_rx_stop(struct bna_rx *rx)
-{
-	rx->rx_flags &= ~BNA_RX_F_PORT_ENABLED;
-	if (rx->fsm == (bfa_fsm_t) bna_rx_sm_stopped)
-		bna_rx_mod_cb_rx_stopped(&rx->bna->rx_mod, rx, BNA_CB_SUCCESS);
-	else {
-		rx->stop_cbfn = bna_rx_mod_cb_rx_stopped;
-		rx->stop_cbarg = &rx->bna->rx_mod;
-		bfa_fsm_send_event(rx, RX_E_STOP);
-	}
-}
-
-static void
-bna_rx_fail(struct bna_rx *rx)
-{
-	/* Indicate port is not enabled, and failed */
-	rx->rx_flags &= ~BNA_RX_F_PORT_ENABLED;
-	rx->rx_flags |= BNA_RX_F_PORT_FAILED;
-	bfa_fsm_send_event(rx, RX_E_FAIL);
-}
-
-void
-bna_rx_mod_start(struct bna_rx_mod *rx_mod, enum bna_rx_type type)
-{
-	struct bna_rx *rx;
-	struct list_head *qe;
-
-	rx_mod->flags |= BNA_RX_MOD_F_PORT_STARTED;
-	if (type == BNA_RX_T_LOOPBACK)
-		rx_mod->flags |= BNA_RX_MOD_F_PORT_LOOPBACK;
-
-	list_for_each(qe, &rx_mod->rx_active_q) {
-		rx = (struct bna_rx *)qe;
-		if (rx->type == type)
-			bna_rx_start(rx);
-	}
-}
-
-void
-bna_rx_mod_stop(struct bna_rx_mod *rx_mod, enum bna_rx_type type)
-{
-	struct bna_rx *rx;
-	struct list_head *qe;
-
-	rx_mod->flags &= ~BNA_RX_MOD_F_PORT_STARTED;
-	rx_mod->flags &= ~BNA_RX_MOD_F_PORT_LOOPBACK;
-
-	rx_mod->stop_cbfn = bna_port_cb_rx_stopped;
-
-	/**
-	 * Before calling bna_rx_stop(), increment rx_stop_wc as many times
-	 * as we are going to call bna_rx_stop
-	 */
-	list_for_each(qe, &rx_mod->rx_active_q) {
-		rx = (struct bna_rx *)qe;
-		if (rx->type == type)
-			bfa_wc_up(&rx_mod->rx_stop_wc);
-	}
-
-	if (rx_mod->rx_stop_wc.wc_count == 0) {
-		rx_mod->stop_cbfn(&rx_mod->bna->port, BNA_CB_SUCCESS);
-		rx_mod->stop_cbfn = NULL;
-		return;
-	}
-
-	list_for_each(qe, &rx_mod->rx_active_q) {
-		rx = (struct bna_rx *)qe;
-		if (rx->type == type)
-			bna_rx_stop(rx);
-	}
-}
-
-void
-bna_rx_mod_fail(struct bna_rx_mod *rx_mod)
-{
-	struct bna_rx *rx;
-	struct list_head *qe;
-
-	rx_mod->flags &= ~BNA_RX_MOD_F_PORT_STARTED;
-	rx_mod->flags &= ~BNA_RX_MOD_F_PORT_LOOPBACK;
-
-	list_for_each(qe, &rx_mod->rx_active_q) {
-		rx = (struct bna_rx *)qe;
-		bna_rx_fail(rx);
-	}
-}
-
-void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna,
-			struct bna_res_info *res_info)
-{
-	int	index;
-	struct bna_rx *rx_ptr;
-	struct bna_rxp *rxp_ptr;
-	struct bna_rxq *rxq_ptr;
-
-	rx_mod->bna = bna;
-	rx_mod->flags = 0;
-
-	rx_mod->rx = (struct bna_rx *)
-		res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.mdl[0].kva;
-	rx_mod->rxp = (struct bna_rxp *)
-		res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.mdl[0].kva;
-	rx_mod->rxq = (struct bna_rxq *)
-		res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.mdl[0].kva;
-
-	/* Initialize the queues */
-	_init_rxmod_queues(rx_mod);
-
-	/* Build RX queues */
-	for (index = 0; index < BFI_MAX_RXQ; index++) {
-		rx_ptr = &rx_mod->rx[index];
-		_rx_ctor(rx_ptr, index);
-		list_add_tail(&rx_ptr->qe, &rx_mod->rx_free_q);
-		rx_mod->rx_free_count++;
-	}
-
-	/* build RX-path queue */
-	for (index = 0; index < BFI_MAX_RXQ; index++) {
-		rxp_ptr = &rx_mod->rxp[index];
-		rxp_ptr->cq.cq_id = index;
-		bfa_q_qe_init(&rxp_ptr->qe);
-		list_add_tail(&rxp_ptr->qe, &rx_mod->rxp_free_q);
-		rx_mod->rxp_free_count++;
-	}
-
-	/* build RXQ queue */
-	for (index = 0; index < BFI_MAX_RXQ; index++) {
-		rxq_ptr = &rx_mod->rxq[index];
-		rxq_ptr->rxq_id = index;
-
-		bfa_q_qe_init(&rxq_ptr->qe);
-		list_add_tail(&rxq_ptr->qe, &rx_mod->rxq_free_q);
-		rx_mod->rxq_free_count++;
-	}
-
-	rx_mod->rx_stop_wc.wc_resume = bna_rx_mod_cb_rx_stopped_all;
-	rx_mod->rx_stop_wc.wc_cbarg = rx_mod;
-	rx_mod->rx_stop_wc.wc_count = 0;
-}
-
-void
-bna_rx_mod_uninit(struct bna_rx_mod *rx_mod)
-{
-	struct list_head		*qe;
-	int i;
-
-	i = 0;
-	list_for_each(qe, &rx_mod->rx_free_q)
-		i++;
-
-	i = 0;
-	list_for_each(qe, &rx_mod->rxp_free_q)
-		i++;
-
-	i = 0;
-	list_for_each(qe, &rx_mod->rxq_free_q)
-		i++;
-
-	rx_mod->bna = NULL;
-}
-
-int
-bna_rx_state_get(struct bna_rx *rx)
-{
-	return bfa_sm_to_state(rx_sm_table, rx->fsm);
-}
-
-void
-bna_rx_res_req(struct bna_rx_config *q_cfg, struct bna_res_info *res_info)
-{
-	u32 cq_size, hq_size, dq_size;
-	u32 cpage_count, hpage_count, dpage_count;
-	struct bna_mem_info *mem_info;
-	u32 cq_depth;
-	u32 hq_depth;
-	u32 dq_depth;
-
-	dq_depth = q_cfg->q_depth;
-	hq_depth = ((q_cfg->rxp_type == BNA_RXP_SINGLE) ? 0 : q_cfg->q_depth);
-	cq_depth = dq_depth + hq_depth;
-
-	BNA_TO_POWER_OF_2_HIGH(cq_depth);
-	cq_size = cq_depth * BFI_CQ_WI_SIZE;
-	cq_size = ALIGN(cq_size, PAGE_SIZE);
-	cpage_count = SIZE_TO_PAGES(cq_size);
-
-	BNA_TO_POWER_OF_2_HIGH(dq_depth);
-	dq_size = dq_depth * BFI_RXQ_WI_SIZE;
-	dq_size = ALIGN(dq_size, PAGE_SIZE);
-	dpage_count = SIZE_TO_PAGES(dq_size);
-
-	if (BNA_RXP_SINGLE != q_cfg->rxp_type) {
-		BNA_TO_POWER_OF_2_HIGH(hq_depth);
-		hq_size = hq_depth * BFI_RXQ_WI_SIZE;
-		hq_size = ALIGN(hq_size, PAGE_SIZE);
-		hpage_count = SIZE_TO_PAGES(hq_size);
-	} else {
-		hpage_count = 0;
-	}
-
-	/* CCB structures */
-	res_info[BNA_RX_RES_MEM_T_CCB].res_type = BNA_RES_T_MEM;
-	mem_info = &res_info[BNA_RX_RES_MEM_T_CCB].res_u.mem_info;
-	mem_info->mem_type = BNA_MEM_T_KVA;
-	mem_info->len = sizeof(struct bna_ccb);
-	mem_info->num = q_cfg->num_paths;
-
-	/* RCB structures */
-	res_info[BNA_RX_RES_MEM_T_RCB].res_type = BNA_RES_T_MEM;
-	mem_info = &res_info[BNA_RX_RES_MEM_T_RCB].res_u.mem_info;
-	mem_info->mem_type = BNA_MEM_T_KVA;
-	mem_info->len = sizeof(struct bna_rcb);
-	mem_info->num = BNA_GET_RXQS(q_cfg);
-
-	/* Completion QPT */
-	res_info[BNA_RX_RES_MEM_T_CQPT].res_type = BNA_RES_T_MEM;
-	mem_info = &res_info[BNA_RX_RES_MEM_T_CQPT].res_u.mem_info;
-	mem_info->mem_type = BNA_MEM_T_DMA;
-	mem_info->len = cpage_count * sizeof(struct bna_dma_addr);
-	mem_info->num = q_cfg->num_paths;
-
-	/* Completion s/w QPT */
-	res_info[BNA_RX_RES_MEM_T_CSWQPT].res_type = BNA_RES_T_MEM;
-	mem_info = &res_info[BNA_RX_RES_MEM_T_CSWQPT].res_u.mem_info;
-	mem_info->mem_type = BNA_MEM_T_KVA;
-	mem_info->len = cpage_count * sizeof(void *);
-	mem_info->num = q_cfg->num_paths;
-
-	/* Completion QPT pages */
-	res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_type = BNA_RES_T_MEM;
-	mem_info = &res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info;
-	mem_info->mem_type = BNA_MEM_T_DMA;
-	mem_info->len = PAGE_SIZE;
-	mem_info->num = cpage_count * q_cfg->num_paths;
-
-	/* Data QPTs */
-	res_info[BNA_RX_RES_MEM_T_DQPT].res_type = BNA_RES_T_MEM;
-	mem_info = &res_info[BNA_RX_RES_MEM_T_DQPT].res_u.mem_info;
-	mem_info->mem_type = BNA_MEM_T_DMA;
-	mem_info->len = dpage_count * sizeof(struct bna_dma_addr);
-	mem_info->num = q_cfg->num_paths;
-
-	/* Data s/w QPTs */
-	res_info[BNA_RX_RES_MEM_T_DSWQPT].res_type = BNA_RES_T_MEM;
-	mem_info = &res_info[BNA_RX_RES_MEM_T_DSWQPT].res_u.mem_info;
-	mem_info->mem_type = BNA_MEM_T_KVA;
-	mem_info->len = dpage_count * sizeof(void *);
-	mem_info->num = q_cfg->num_paths;
-
-	/* Data QPT pages */
-	res_info[BNA_RX_RES_MEM_T_DPAGE].res_type = BNA_RES_T_MEM;
-	mem_info = &res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info;
-	mem_info->mem_type = BNA_MEM_T_DMA;
-	mem_info->len = PAGE_SIZE;
-	mem_info->num = dpage_count * q_cfg->num_paths;
-
-	/* Hdr QPTs */
-	res_info[BNA_RX_RES_MEM_T_HQPT].res_type = BNA_RES_T_MEM;
-	mem_info = &res_info[BNA_RX_RES_MEM_T_HQPT].res_u.mem_info;
-	mem_info->mem_type = BNA_MEM_T_DMA;
-	mem_info->len = hpage_count * sizeof(struct bna_dma_addr);
-	mem_info->num = (hpage_count ? q_cfg->num_paths : 0);
-
-	/* Hdr s/w QPTs */
-	res_info[BNA_RX_RES_MEM_T_HSWQPT].res_type = BNA_RES_T_MEM;
-	mem_info = &res_info[BNA_RX_RES_MEM_T_HSWQPT].res_u.mem_info;
-	mem_info->mem_type = BNA_MEM_T_KVA;
-	mem_info->len = hpage_count * sizeof(void *);
-	mem_info->num = (hpage_count ? q_cfg->num_paths : 0);
-
-	/* Hdr QPT pages */
-	res_info[BNA_RX_RES_MEM_T_HPAGE].res_type = BNA_RES_T_MEM;
-	mem_info = &res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info;
-	mem_info->mem_type = BNA_MEM_T_DMA;
-	mem_info->len = (hpage_count ? PAGE_SIZE : 0);
-	mem_info->num = (hpage_count ? (hpage_count * q_cfg->num_paths) : 0);
-
-	/* RX Interrupts */
-	res_info[BNA_RX_RES_T_INTR].res_type = BNA_RES_T_INTR;
-	res_info[BNA_RX_RES_T_INTR].res_u.intr_info.intr_type = BNA_INTR_T_MSIX;
-	res_info[BNA_RX_RES_T_INTR].res_u.intr_info.num = q_cfg->num_paths;
-}
-
-struct bna_rx *
-bna_rx_create(struct bna *bna, struct bnad *bnad,
-		struct bna_rx_config *rx_cfg,
-		struct bna_rx_event_cbfn *rx_cbfn,
-		struct bna_res_info *res_info,
-		void *priv)
-{
-	struct bna_rx_mod *rx_mod = &bna->rx_mod;
-	struct bna_rx *rx;
-	struct bna_rxp *rxp;
-	struct bna_rxq *q0;
-	struct bna_rxq *q1;
-	struct bna_intr_info *intr_info;
-	u32 page_count;
-	struct bna_mem_descr *ccb_mem;
-	struct bna_mem_descr *rcb_mem;
-	struct bna_mem_descr *unmapq_mem;
-	struct bna_mem_descr *cqpt_mem;
-	struct bna_mem_descr *cswqpt_mem;
-	struct bna_mem_descr *cpage_mem;
-	struct bna_mem_descr *hqpt_mem;	/* Header/Small Q qpt */
-	struct bna_mem_descr *dqpt_mem;	/* Data/Large Q qpt */
-	struct bna_mem_descr *hsqpt_mem;	/* s/w qpt for hdr */
-	struct bna_mem_descr *dsqpt_mem;	/* s/w qpt for data */
-	struct bna_mem_descr *hpage_mem;	/* hdr page mem */
-	struct bna_mem_descr *dpage_mem;	/* data page mem */
-	int i, cpage_idx = 0, dpage_idx = 0, hpage_idx = 0;
-	int dpage_count, hpage_count, rcb_idx;
-	struct bna_ib_config ibcfg;
-	/* Fail if we don't have enough RXPs, RXQs */
-	if (!_rx_can_satisfy(rx_mod, rx_cfg))
-		return NULL;
-
-	/* Initialize resource pointers */
-	intr_info = &res_info[BNA_RX_RES_T_INTR].res_u.intr_info;
-	ccb_mem = &res_info[BNA_RX_RES_MEM_T_CCB].res_u.mem_info.mdl[0];
-	rcb_mem = &res_info[BNA_RX_RES_MEM_T_RCB].res_u.mem_info.mdl[0];
-	unmapq_mem = &res_info[BNA_RX_RES_MEM_T_UNMAPQ].res_u.mem_info.mdl[0];
-	cqpt_mem = &res_info[BNA_RX_RES_MEM_T_CQPT].res_u.mem_info.mdl[0];
-	cswqpt_mem = &res_info[BNA_RX_RES_MEM_T_CSWQPT].res_u.mem_info.mdl[0];
-	cpage_mem = &res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.mdl[0];
-	hqpt_mem = &res_info[BNA_RX_RES_MEM_T_HQPT].res_u.mem_info.mdl[0];
-	dqpt_mem = &res_info[BNA_RX_RES_MEM_T_DQPT].res_u.mem_info.mdl[0];
-	hsqpt_mem = &res_info[BNA_RX_RES_MEM_T_HSWQPT].res_u.mem_info.mdl[0];
-	dsqpt_mem = &res_info[BNA_RX_RES_MEM_T_DSWQPT].res_u.mem_info.mdl[0];
-	hpage_mem = &res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.mdl[0];
-	dpage_mem = &res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.mdl[0];
-
-	/* Compute q depth & page count */
-	page_count = res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.num /
-			rx_cfg->num_paths;
-
-	dpage_count = res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.num /
-			rx_cfg->num_paths;
-
-	hpage_count = res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.num /
-			rx_cfg->num_paths;
-	/* Get RX pointer */
-	rx = _get_free_rx(rx_mod);
-	_rx_init(rx, bna);
-	rx->priv = priv;
-	rx->type = rx_cfg->rx_type;
-
-	rx->rcb_setup_cbfn = rx_cbfn->rcb_setup_cbfn;
-	rx->rcb_destroy_cbfn = rx_cbfn->rcb_destroy_cbfn;
-	rx->ccb_setup_cbfn = rx_cbfn->ccb_setup_cbfn;
-	rx->ccb_destroy_cbfn = rx_cbfn->ccb_destroy_cbfn;
-	/* Following callbacks are mandatory */
-	rx->rx_cleanup_cbfn = rx_cbfn->rx_cleanup_cbfn;
-	rx->rx_post_cbfn = rx_cbfn->rx_post_cbfn;
-
-	if (rx->bna->rx_mod.flags & BNA_RX_MOD_F_PORT_STARTED) {
-		switch (rx->type) {
-		case BNA_RX_T_REGULAR:
-			if (!(rx->bna->rx_mod.flags &
-				BNA_RX_MOD_F_PORT_LOOPBACK))
-				rx->rx_flags |= BNA_RX_F_PORT_ENABLED;
-			break;
-		case BNA_RX_T_LOOPBACK:
-			if (rx->bna->rx_mod.flags & BNA_RX_MOD_F_PORT_LOOPBACK)
-				rx->rx_flags |= BNA_RX_F_PORT_ENABLED;
-			break;
-		}
-	}
-
-	for (i = 0, rcb_idx = 0; i < rx_cfg->num_paths; i++) {
-		rxp = _get_free_rxp(rx_mod);
-		rxp->type = rx_cfg->rxp_type;
-		rxp->rx = rx;
-		rxp->cq.rx = rx;
-
-		/* Get required RXQs, and queue them to rx-path */
-		q0 = _get_free_rxq(rx_mod);
-		if (BNA_RXP_SINGLE == rx_cfg->rxp_type)
-			q1 = NULL;
-		else
-			q1 = _get_free_rxq(rx_mod);
-
-		/* Initialize IB */
-		if (1 == intr_info->num) {
-			rxp->cq.ib = bna_ib_get(&bna->ib_mod,
-					intr_info->intr_type,
-					intr_info->idl[0].vector);
-			rxp->vector = intr_info->idl[0].vector;
-		} else {
-			rxp->cq.ib = bna_ib_get(&bna->ib_mod,
-					intr_info->intr_type,
-					intr_info->idl[i].vector);
-
-			/* Map the MSI-x vector used for this RXP */
-			rxp->vector = intr_info->idl[i].vector;
-		}
-
-		rxp->cq.ib_seg_offset = bna_ib_reserve_idx(rxp->cq.ib);
-
-		ibcfg.coalescing_timeo = BFI_RX_COALESCING_TIMEO;
-		ibcfg.interpkt_count = BFI_RX_INTERPKT_COUNT;
-		ibcfg.interpkt_timeo = BFI_RX_INTERPKT_TIMEO;
-		ibcfg.ctrl_flags = BFI_IB_CF_INT_ENABLE;
-
-		bna_ib_config(rxp->cq.ib, &ibcfg);
-
-		/* Link rxqs to rxp */
-		_rxp_add_rxqs(rxp, q0, q1);
-
-		/* Link rxp to rx */
-		_rx_add_rxp(rx, rxp);
-
-		q0->rx = rx;
-		q0->rxp = rxp;
-
-		/* Initialize RCB for the large / data q */
-		q0->rcb = (struct bna_rcb *) rcb_mem[rcb_idx].kva;
-		RXQ_RCB_INIT(q0, rxp, rx_cfg->q_depth, bna, 0,
-			(void *)unmapq_mem[rcb_idx].kva);
-		rcb_idx++;
-		(q0)->rx_packets = (q0)->rx_bytes = 0;
-		(q0)->rx_packets_with_error = (q0)->rxbuf_alloc_failed = 0;
-
-		/* Initialize RXQs */
-		_rxq_qpt_init(q0, rxp, dpage_count, PAGE_SIZE,
-			&dqpt_mem[i], &dsqpt_mem[i], &dpage_mem[dpage_idx]);
-		q0->rcb->page_idx = dpage_idx;
-		q0->rcb->page_count = dpage_count;
-		dpage_idx += dpage_count;
-
-		/* Call bnad to complete rcb setup */
-		if (rx->rcb_setup_cbfn)
-			rx->rcb_setup_cbfn(bnad, q0->rcb);
-
-		if (q1) {
-			q1->rx = rx;
-			q1->rxp = rxp;
-
-			q1->rcb = (struct bna_rcb *) rcb_mem[rcb_idx].kva;
-			RXQ_RCB_INIT(q1, rxp, rx_cfg->q_depth, bna, 1,
-				(void *)unmapq_mem[rcb_idx].kva);
-			rcb_idx++;
-			(q1)->buffer_size = (rx_cfg)->small_buff_size;
-			(q1)->rx_packets = (q1)->rx_bytes = 0;
-			(q1)->rx_packets_with_error =
-				(q1)->rxbuf_alloc_failed = 0;
-
-			_rxq_qpt_init(q1, rxp, hpage_count, PAGE_SIZE,
-				&hqpt_mem[i], &hsqpt_mem[i],
-				&hpage_mem[hpage_idx]);
-			q1->rcb->page_idx = hpage_idx;
-			q1->rcb->page_count = hpage_count;
-			hpage_idx += hpage_count;
-
-			/* Call bnad to complete rcb setup */
-			if (rx->rcb_setup_cbfn)
-				rx->rcb_setup_cbfn(bnad, q1->rcb);
-		}
-		/* Setup RXP::CQ */
-		rxp->cq.ccb = (struct bna_ccb *) ccb_mem[i].kva;
-		_rxp_cqpt_setup(rxp, page_count, PAGE_SIZE,
-			&cqpt_mem[i], &cswqpt_mem[i], &cpage_mem[cpage_idx]);
-		rxp->cq.ccb->page_idx = cpage_idx;
-		rxp->cq.ccb->page_count = page_count;
-		cpage_idx += page_count;
-
-		rxp->cq.ccb->pkt_rate.small_pkt_cnt = 0;
-		rxp->cq.ccb->pkt_rate.large_pkt_cnt = 0;
-
-		rxp->cq.ccb->producer_index = 0;
-		rxp->cq.ccb->q_depth =	rx_cfg->q_depth +
-					((rx_cfg->rxp_type == BNA_RXP_SINGLE) ?
-					0 : rx_cfg->q_depth);
-		rxp->cq.ccb->i_dbell = &rxp->cq.ib->door_bell;
-		rxp->cq.ccb->rcb[0] = q0->rcb;
-		if (q1)
-			rxp->cq.ccb->rcb[1] = q1->rcb;
-		rxp->cq.ccb->cq = &rxp->cq;
-		rxp->cq.ccb->bnad = bna->bnad;
-		rxp->cq.ccb->hw_producer_index =
-			((volatile u32 *)rxp->cq.ib->ib_seg_host_addr_kva +
-				      (rxp->cq.ib_seg_offset * BFI_IBIDX_SIZE));
-		*(rxp->cq.ccb->hw_producer_index) = 0;
-		rxp->cq.ccb->intr_type = intr_info->intr_type;
-		rxp->cq.ccb->intr_vector = (intr_info->num == 1) ?
-						intr_info->idl[0].vector :
-						intr_info->idl[i].vector;
-		rxp->cq.ccb->rx_coalescing_timeo =
-					rxp->cq.ib->ib_config.coalescing_timeo;
-		rxp->cq.ccb->id = i;
-
-		/* Call bnad to complete CCB setup */
-		if (rx->ccb_setup_cbfn)
-			rx->ccb_setup_cbfn(bnad, rxp->cq.ccb);
-
-	} /* for each rx-path */
-
-	bna_rxf_init(&rx->rxf, rx, rx_cfg);
-
-	bfa_fsm_set_state(rx, bna_rx_sm_stopped);
-
-	return rx;
-}
-
-void
-bna_rx_destroy(struct bna_rx *rx)
-{
-	struct bna_rx_mod *rx_mod = &rx->bna->rx_mod;
-	struct bna_ib_mod *ib_mod = &rx->bna->ib_mod;
-	struct bna_rxq *q0 = NULL;
-	struct bna_rxq *q1 = NULL;
-	struct bna_rxp *rxp;
-	struct list_head *qe;
-
-	bna_rxf_uninit(&rx->rxf);
-
-	while (!list_empty(&rx->rxp_q)) {
-		bfa_q_deq(&rx->rxp_q, &rxp);
-		GET_RXQS(rxp, q0, q1);
-		/* Callback to bnad for destroying RCB */
-		if (rx->rcb_destroy_cbfn)
-			rx->rcb_destroy_cbfn(rx->bna->bnad, q0->rcb);
-		q0->rcb = NULL;
-		q0->rxp = NULL;
-		q0->rx = NULL;
-		_put_free_rxq(rx_mod, q0);
-		if (q1) {
-			/* Callback to bnad for destroying RCB */
-			if (rx->rcb_destroy_cbfn)
-				rx->rcb_destroy_cbfn(rx->bna->bnad, q1->rcb);
-			q1->rcb = NULL;
-			q1->rxp = NULL;
-			q1->rx = NULL;
-			_put_free_rxq(rx_mod, q1);
-		}
-		rxp->rxq.slr.large = NULL;
-		rxp->rxq.slr.small = NULL;
-		if (rxp->cq.ib) {
-			if (rxp->cq.ib_seg_offset != 0xff)
-				bna_ib_release_idx(rxp->cq.ib,
-						rxp->cq.ib_seg_offset);
-			bna_ib_put(ib_mod, rxp->cq.ib);
-			rxp->cq.ib = NULL;
-		}
-		/* Callback to bnad for destroying CCB */
-		if (rx->ccb_destroy_cbfn)
-			rx->ccb_destroy_cbfn(rx->bna->bnad, rxp->cq.ccb);
-		rxp->cq.ccb = NULL;
-		rxp->rx = NULL;
-		_put_free_rxp(rx_mod, rxp);
-	}
-
-	list_for_each(qe, &rx_mod->rx_active_q) {
-		if (qe == &rx->qe) {
-			list_del(&rx->qe);
-			bfa_q_qe_init(&rx->qe);
-			break;
-		}
-	}
-
-	rx->bna = NULL;
-	rx->priv = NULL;
-	_put_free_rx(rx_mod, rx);
-}
-
-void
-bna_rx_enable(struct bna_rx *rx)
-{
-	if (rx->fsm != (bfa_sm_t)bna_rx_sm_stopped)
-		return;
-
-	rx->rx_flags |= BNA_RX_F_ENABLE;
-	if (rx->rx_flags & BNA_RX_F_PORT_ENABLED)
-		bfa_fsm_send_event(rx, RX_E_START);
-}
-
-void
-bna_rx_disable(struct bna_rx *rx, enum bna_cleanup_type type,
-		void (*cbfn)(void *, struct bna_rx *,
-				enum bna_cb_status))
-{
-	if (type == BNA_SOFT_CLEANUP) {
-		/* h/w should not be accessed. Treat we're stopped */
-		(*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
-	} else {
-		rx->stop_cbfn = cbfn;
-		rx->stop_cbarg = rx->bna->bnad;
-
-		rx->rx_flags &= ~BNA_RX_F_ENABLE;
-
-		bfa_fsm_send_event(rx, RX_E_STOP);
-	}
-}
-
-/**
- * TX
- */
-#define call_tx_stop_cbfn(tx, status)\
-do {\
-	if ((tx)->stop_cbfn)\
-		(tx)->stop_cbfn((tx)->stop_cbarg, (tx), status);\
-	(tx)->stop_cbfn = NULL;\
-	(tx)->stop_cbarg = NULL;\
-} while (0)
-
-#define call_tx_prio_change_cbfn(tx, status)\
-do {\
-	if ((tx)->prio_change_cbfn)\
-		(tx)->prio_change_cbfn((tx)->bna->bnad, (tx), status);\
-	(tx)->prio_change_cbfn = NULL;\
-} while (0)
-
-static void bna_tx_mod_cb_tx_stopped(void *tx_mod, struct bna_tx *tx,
-					enum bna_cb_status status);
-static void bna_tx_cb_txq_stopped(void *arg, int status);
-static void bna_tx_cb_stats_cleared(void *arg, int status);
-static void __bna_tx_stop(struct bna_tx *tx);
-static void __bna_tx_start(struct bna_tx *tx);
-static void __bna_txf_stat_clr(struct bna_tx *tx);
-
-enum bna_tx_event {
-	TX_E_START			= 1,
-	TX_E_STOP			= 2,
-	TX_E_FAIL			= 3,
-	TX_E_TXQ_STOPPED		= 4,
-	TX_E_PRIO_CHANGE		= 5,
-	TX_E_STAT_CLEARED		= 6,
-};
-
-enum bna_tx_state {
-	BNA_TX_STOPPED			= 1,
-	BNA_TX_STARTED			= 2,
-	BNA_TX_TXQ_STOP_WAIT		= 3,
-	BNA_TX_PRIO_STOP_WAIT		= 4,
-	BNA_TX_STAT_CLR_WAIT		= 5,
-};
-
-bfa_fsm_state_decl(bna_tx, stopped, struct bna_tx,
-			enum bna_tx_event);
-bfa_fsm_state_decl(bna_tx, started, struct bna_tx,
-			enum bna_tx_event);
-bfa_fsm_state_decl(bna_tx, txq_stop_wait, struct bna_tx,
-			enum bna_tx_event);
-bfa_fsm_state_decl(bna_tx, prio_stop_wait, struct bna_tx,
-			enum bna_tx_event);
-bfa_fsm_state_decl(bna_tx, stat_clr_wait, struct bna_tx,
-			enum bna_tx_event);
-
-static struct bfa_sm_table tx_sm_table[] = {
-	{BFA_SM(bna_tx_sm_stopped), BNA_TX_STOPPED},
-	{BFA_SM(bna_tx_sm_started), BNA_TX_STARTED},
-	{BFA_SM(bna_tx_sm_txq_stop_wait), BNA_TX_TXQ_STOP_WAIT},
-	{BFA_SM(bna_tx_sm_prio_stop_wait), BNA_TX_PRIO_STOP_WAIT},
-	{BFA_SM(bna_tx_sm_stat_clr_wait), BNA_TX_STAT_CLR_WAIT},
-};
-
-static void
-bna_tx_sm_stopped_entry(struct bna_tx *tx)
-{
-	struct bna_txq *txq;
-	struct list_head		 *qe;
-
-	list_for_each(qe, &tx->txq_q) {
-		txq = (struct bna_txq *)qe;
-		(tx->tx_cleanup_cbfn)(tx->bna->bnad, txq->tcb);
-	}
-
-	call_tx_stop_cbfn(tx, BNA_CB_SUCCESS);
-}
-
-static void
-bna_tx_sm_stopped(struct bna_tx *tx, enum bna_tx_event event)
-{
-	switch (event) {
-	case TX_E_START:
-		bfa_fsm_set_state(tx, bna_tx_sm_started);
-		break;
-
-	case TX_E_STOP:
-		bfa_fsm_set_state(tx, bna_tx_sm_stopped);
-		break;
-
-	case TX_E_FAIL:
-		/* No-op */
-		break;
-
-	case TX_E_PRIO_CHANGE:
-		call_tx_prio_change_cbfn(tx, BNA_CB_SUCCESS);
-		break;
-
-	case TX_E_TXQ_STOPPED:
-		/**
-		 * This event is received due to flushing of mbox when
-		 * device fails
-		 */
-		/* No-op */
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_tx_sm_started_entry(struct bna_tx *tx)
-{
-	struct bna_txq *txq;
-	struct list_head		 *qe;
-
-	__bna_tx_start(tx);
-
-	/* Start IB */
-	list_for_each(qe, &tx->txq_q) {
-		txq = (struct bna_txq *)qe;
-		bna_ib_ack(&txq->ib->door_bell, 0);
-	}
-}
-
-static void
-bna_tx_sm_started(struct bna_tx *tx, enum bna_tx_event event)
-{
-	struct bna_txq *txq;
-	struct list_head		 *qe;
-
-	switch (event) {
-	case TX_E_STOP:
-		bfa_fsm_set_state(tx, bna_tx_sm_txq_stop_wait);
-		__bna_tx_stop(tx);
-		break;
-
-	case TX_E_FAIL:
-		list_for_each(qe, &tx->txq_q) {
-			txq = (struct bna_txq *)qe;
-			bna_ib_fail(txq->ib);
-			(tx->tx_stall_cbfn)(tx->bna->bnad, txq->tcb);
-		}
-		bfa_fsm_set_state(tx, bna_tx_sm_stopped);
-		break;
-
-	case TX_E_PRIO_CHANGE:
-		bfa_fsm_set_state(tx, bna_tx_sm_prio_stop_wait);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_tx_sm_txq_stop_wait_entry(struct bna_tx *tx)
-{
-}
-
-static void
-bna_tx_sm_txq_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
-{
-	struct bna_txq *txq;
-	struct list_head		 *qe;
-
-	switch (event) {
-	case TX_E_FAIL:
-		bfa_fsm_set_state(tx, bna_tx_sm_stopped);
-		break;
-
-	case TX_E_TXQ_STOPPED:
-		list_for_each(qe, &tx->txq_q) {
-			txq = (struct bna_txq *)qe;
-			bna_ib_stop(txq->ib);
-		}
-		bfa_fsm_set_state(tx, bna_tx_sm_stat_clr_wait);
-		break;
-
-	case TX_E_PRIO_CHANGE:
-		/* No-op */
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_tx_sm_prio_stop_wait_entry(struct bna_tx *tx)
-{
-	__bna_tx_stop(tx);
-}
-
-static void
-bna_tx_sm_prio_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
-{
-	struct bna_txq *txq;
-	struct list_head		 *qe;
-
-	switch (event) {
-	case TX_E_STOP:
-		bfa_fsm_set_state(tx, bna_tx_sm_txq_stop_wait);
-		break;
-
-	case TX_E_FAIL:
-		call_tx_prio_change_cbfn(tx, BNA_CB_FAIL);
-		bfa_fsm_set_state(tx, bna_tx_sm_stopped);
-		break;
-
-	case TX_E_TXQ_STOPPED:
-		list_for_each(qe, &tx->txq_q) {
-			txq = (struct bna_txq *)qe;
-			bna_ib_stop(txq->ib);
-			(tx->tx_cleanup_cbfn)(tx->bna->bnad, txq->tcb);
-		}
-		call_tx_prio_change_cbfn(tx, BNA_CB_SUCCESS);
-		bfa_fsm_set_state(tx, bna_tx_sm_started);
-		break;
-
-	case TX_E_PRIO_CHANGE:
-		/* No-op */
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-bna_tx_sm_stat_clr_wait_entry(struct bna_tx *tx)
-{
-	__bna_txf_stat_clr(tx);
-}
-
-static void
-bna_tx_sm_stat_clr_wait(struct bna_tx *tx, enum bna_tx_event event)
-{
-	switch (event) {
-	case TX_E_FAIL:
-	case TX_E_STAT_CLEARED:
-		bfa_fsm_set_state(tx, bna_tx_sm_stopped);
-		break;
-
-	default:
-		bfa_sm_fault(event);
-	}
-}
-
-static void
-__bna_txq_start(struct bna_tx *tx, struct bna_txq *txq)
-{
-	struct bna_rxtx_q_mem *q_mem;
-	struct bna_txq_mem txq_cfg;
-	struct bna_txq_mem *txq_mem;
-	struct bna_dma_addr cur_q_addr;
-	u32 pg_num;
-	void __iomem *base_addr;
-	unsigned long off;
-
-	/* Fill out structure, to be subsequently written to hardware */
-	txq_cfg.pg_tbl_addr_lo = txq->qpt.hw_qpt_ptr.lsb;
-	txq_cfg.pg_tbl_addr_hi = txq->qpt.hw_qpt_ptr.msb;
-	cur_q_addr = *((struct bna_dma_addr *)(txq->qpt.kv_qpt_ptr));
-	txq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
-	txq_cfg.cur_q_entry_hi = cur_q_addr.msb;
-
-	txq_cfg.pg_cnt_n_prd_ptr = (txq->qpt.page_count << 16) | 0x0;
-
-	txq_cfg.entry_n_pg_size = ((u32)(BFI_TXQ_WI_SIZE >> 2) << 16) |
-			(txq->qpt.page_size >> 2);
-	txq_cfg.int_blk_n_cns_ptr = ((((u32)txq->ib_seg_offset) << 24) |
-			((u32)(txq->ib->ib_id & 0xff) << 16) | 0x0);
-
-	txq_cfg.cns_ptr2_n_q_state = BNA_Q_IDLE_STATE;
-	txq_cfg.nxt_qid_n_fid_n_pri = (((tx->txf.txf_id & 0x3f) << 3) |
-			(txq->priority & 0x7));
-	txq_cfg.wvc_n_cquota_n_rquota =
-			((((u32)BFI_TX_MAX_WRR_QUOTA & 0xfff) << 12) |
-			(BFI_TX_MAX_WRR_QUOTA & 0xfff));
-
-	/* Setup the page and write to H/W */
-
-	pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + tx->bna->port_num,
-			HQM_RXTX_Q_RAM_BASE_OFFSET);
-	writel(pg_num, tx->bna->regs.page_addr);
-
-	base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva,
-					HQM_RXTX_Q_RAM_BASE_OFFSET);
-	q_mem = (struct bna_rxtx_q_mem *)0;
-	txq_mem = &q_mem[txq->txq_id].txq;
-
-	/*
-	 * The following 4 lines, is a hack b'cos the H/W needs to read
-	 * these DMA addresses as little endian
-	 */
-
-	off = (unsigned long)&txq_mem->pg_tbl_addr_lo;
-	writel(htonl(txq_cfg.pg_tbl_addr_lo), base_addr + off);
-
-	off = (unsigned long)&txq_mem->pg_tbl_addr_hi;
-	writel(htonl(txq_cfg.pg_tbl_addr_hi), base_addr + off);
-
-	off = (unsigned long)&txq_mem->cur_q_entry_lo;
-	writel(htonl(txq_cfg.cur_q_entry_lo), base_addr + off);
-
-	off = (unsigned long)&txq_mem->cur_q_entry_hi;
-	writel(htonl(txq_cfg.cur_q_entry_hi), base_addr + off);
-
-	off = (unsigned long)&txq_mem->pg_cnt_n_prd_ptr;
-	writel(txq_cfg.pg_cnt_n_prd_ptr, base_addr + off);
-
-	off = (unsigned long)&txq_mem->entry_n_pg_size;
-	writel(txq_cfg.entry_n_pg_size, base_addr + off);
-
-	off = (unsigned long)&txq_mem->int_blk_n_cns_ptr;
-	writel(txq_cfg.int_blk_n_cns_ptr, base_addr + off);
-
-	off = (unsigned long)&txq_mem->cns_ptr2_n_q_state;
-	writel(txq_cfg.cns_ptr2_n_q_state, base_addr + off);
-
-	off = (unsigned long)&txq_mem->nxt_qid_n_fid_n_pri;
-	writel(txq_cfg.nxt_qid_n_fid_n_pri, base_addr + off);
-
-	off = (unsigned long)&txq_mem->wvc_n_cquota_n_rquota;
-	writel(txq_cfg.wvc_n_cquota_n_rquota, base_addr + off);
-
-	txq->tcb->producer_index = 0;
-	txq->tcb->consumer_index = 0;
-	*(txq->tcb->hw_consumer_index) = 0;
-
-}
-
-static void
-__bna_txq_stop(struct bna_tx *tx, struct bna_txq *txq)
-{
-	struct bfi_ll_q_stop_req ll_req;
-	u32 bit_mask[2] = {0, 0};
-	if (txq->txq_id < 32)
-		bit_mask[0] = (u32)1 << txq->txq_id;
-	else
-		bit_mask[1] = (u32)1 << (txq->txq_id - 32);
-
-	memset(&ll_req, 0, sizeof(ll_req));
-	ll_req.mh.msg_class = BFI_MC_LL;
-	ll_req.mh.msg_id = BFI_LL_H2I_TXQ_STOP_REQ;
-	ll_req.mh.mtag.h2i.lpu_id = 0;
-	ll_req.q_id_mask[0] = htonl(bit_mask[0]);
-	ll_req.q_id_mask[1] = htonl(bit_mask[1]);
-
-	bna_mbox_qe_fill(&tx->mbox_qe, &ll_req, sizeof(ll_req),
-			bna_tx_cb_txq_stopped, tx);
-
-	bna_mbox_send(tx->bna, &tx->mbox_qe);
-}
-
-static void
-__bna_txf_start(struct bna_tx *tx)
-{
-	struct bna_tx_fndb_ram *tx_fndb;
-	struct bna_txf *txf = &tx->txf;
-	void __iomem *base_addr;
-	unsigned long off;
-
-	writel(BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
-			(tx->bna->port_num * 2), TX_FNDB_RAM_BASE_OFFSET),
-			tx->bna->regs.page_addr);
-
-	base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva,
-					TX_FNDB_RAM_BASE_OFFSET);
-
-	tx_fndb = (struct bna_tx_fndb_ram *)0;
-	off = (unsigned long)&tx_fndb[txf->txf_id].vlan_n_ctrl_flags;
-
-	writel(((u32)txf->vlan << 16) | txf->ctrl_flags,
-			base_addr + off);
-
-	if (tx->txf.txf_id < 32)
-		tx->bna->tx_mod.txf_bmap[0] |= ((u32)1 << tx->txf.txf_id);
-	else
-		tx->bna->tx_mod.txf_bmap[1] |= ((u32)
-						 1 << (tx->txf.txf_id - 32));
-}
-
-static void
-__bna_txf_stop(struct bna_tx *tx)
-{
-	struct bna_tx_fndb_ram *tx_fndb;
-	u32 page_num;
-	u32 ctl_flags;
-	struct bna_txf *txf = &tx->txf;
-	void __iomem *base_addr;
-	unsigned long off;
-
-	/* retrieve the running txf_flags & turn off enable bit */
-	page_num = BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
-			(tx->bna->port_num * 2), TX_FNDB_RAM_BASE_OFFSET);
-	writel(page_num, tx->bna->regs.page_addr);
-
-	base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva,
-					TX_FNDB_RAM_BASE_OFFSET);
-	tx_fndb = (struct bna_tx_fndb_ram *)0;
-	off = (unsigned long)&tx_fndb[txf->txf_id].vlan_n_ctrl_flags;
-
-	ctl_flags = readl(base_addr + off);
-	ctl_flags &= ~BFI_TXF_CF_ENABLE;
-
-	writel(ctl_flags, base_addr + off);
-
-	if (tx->txf.txf_id < 32)
-		tx->bna->tx_mod.txf_bmap[0] &= ~((u32)1 << tx->txf.txf_id);
-	else
-		tx->bna->tx_mod.txf_bmap[0] &= ~((u32)
-						 1 << (tx->txf.txf_id - 32));
-}
-
-static void
-__bna_txf_stat_clr(struct bna_tx *tx)
-{
-	struct bfi_ll_stats_req ll_req;
-	u32 txf_bmap[2] = {0, 0};
-	if (tx->txf.txf_id < 32)
-		txf_bmap[0] = ((u32)1 << tx->txf.txf_id);
-	else
-		txf_bmap[1] = ((u32)1 << (tx->txf.txf_id - 32));
-	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_CLEAR_REQ, 0);
-	ll_req.stats_mask = 0;
-	ll_req.rxf_id_mask[0] = 0;
-	ll_req.rxf_id_mask[1] =	0;
-	ll_req.txf_id_mask[0] =	htonl(txf_bmap[0]);
-	ll_req.txf_id_mask[1] =	htonl(txf_bmap[1]);
-
-	bna_mbox_qe_fill(&tx->mbox_qe, &ll_req, sizeof(ll_req),
-			bna_tx_cb_stats_cleared, tx);
-	bna_mbox_send(tx->bna, &tx->mbox_qe);
-}
-
-static void
-__bna_tx_start(struct bna_tx *tx)
-{
-	struct bna_txq *txq;
-	struct list_head		 *qe;
-
-	list_for_each(qe, &tx->txq_q) {
-		txq = (struct bna_txq *)qe;
-		bna_ib_start(txq->ib);
-		__bna_txq_start(tx, txq);
-	}
-
-	__bna_txf_start(tx);
-
-	list_for_each(qe, &tx->txq_q) {
-		txq = (struct bna_txq *)qe;
-		txq->tcb->priority = txq->priority;
-		(tx->tx_resume_cbfn)(tx->bna->bnad, txq->tcb);
-	}
-}
-
-static void
-__bna_tx_stop(struct bna_tx *tx)
-{
-	struct bna_txq *txq;
-	struct list_head		 *qe;
-
-	list_for_each(qe, &tx->txq_q) {
-		txq = (struct bna_txq *)qe;
-		(tx->tx_stall_cbfn)(tx->bna->bnad, txq->tcb);
-	}
-
-	__bna_txf_stop(tx);
-
-	list_for_each(qe, &tx->txq_q) {
-		txq = (struct bna_txq *)qe;
-		bfa_wc_up(&tx->txq_stop_wc);
-	}
-
-	list_for_each(qe, &tx->txq_q) {
-		txq = (struct bna_txq *)qe;
-		__bna_txq_stop(tx, txq);
-	}
-}
-
-static void
-bna_txq_qpt_setup(struct bna_txq *txq, int page_count, int page_size,
-		struct bna_mem_descr *qpt_mem,
-		struct bna_mem_descr *swqpt_mem,
-		struct bna_mem_descr *page_mem)
-{
-	int i;
-
-	txq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
-	txq->qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
-	txq->qpt.kv_qpt_ptr = qpt_mem->kva;
-	txq->qpt.page_count = page_count;
-	txq->qpt.page_size = page_size;
-
-	txq->tcb->sw_qpt = (void **) swqpt_mem->kva;
-
-	for (i = 0; i < page_count; i++) {
-		txq->tcb->sw_qpt[i] = page_mem[i].kva;
-
-		((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].lsb =
-			page_mem[i].dma.lsb;
-		((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].msb =
-			page_mem[i].dma.msb;
-
-	}
-}
-
-static void
-bna_tx_free(struct bna_tx *tx)
-{
-	struct bna_tx_mod *tx_mod = &tx->bna->tx_mod;
-	struct bna_txq *txq;
-	struct bna_ib_mod *ib_mod = &tx->bna->ib_mod;
-	struct list_head *qe;
-
-	while (!list_empty(&tx->txq_q)) {
-		bfa_q_deq(&tx->txq_q, &txq);
-		bfa_q_qe_init(&txq->qe);
-		if (txq->ib) {
-			if (txq->ib_seg_offset != -1)
-				bna_ib_release_idx(txq->ib,
-						txq->ib_seg_offset);
-			bna_ib_put(ib_mod, txq->ib);
-			txq->ib = NULL;
-		}
-		txq->tcb = NULL;
-		txq->tx = NULL;
-		list_add_tail(&txq->qe, &tx_mod->txq_free_q);
-	}
-
-	list_for_each(qe, &tx_mod->tx_active_q) {
-		if (qe == &tx->qe) {
-			list_del(&tx->qe);
-			bfa_q_qe_init(&tx->qe);
-			break;
-		}
-	}
-
-	tx->bna = NULL;
-	tx->priv = NULL;
-	list_add_tail(&tx->qe, &tx_mod->tx_free_q);
-}
-
-static void
-bna_tx_cb_txq_stopped(void *arg, int status)
-{
-	struct bna_tx *tx = (struct bna_tx *)arg;
-
-	bfa_q_qe_init(&tx->mbox_qe.qe);
-	bfa_wc_down(&tx->txq_stop_wc);
-}
-
-static void
-bna_tx_cb_txq_stopped_all(void *arg)
-{
-	struct bna_tx *tx = (struct bna_tx *)arg;
-
-	bfa_fsm_send_event(tx, TX_E_TXQ_STOPPED);
-}
-
-static void
-bna_tx_cb_stats_cleared(void *arg, int status)
-{
-	struct bna_tx *tx = (struct bna_tx *)arg;
-
-	bfa_q_qe_init(&tx->mbox_qe.qe);
-
-	bfa_fsm_send_event(tx, TX_E_STAT_CLEARED);
-}
-
-static void
-bna_tx_start(struct bna_tx *tx)
-{
-	tx->flags |= BNA_TX_F_PORT_STARTED;
-	if (tx->flags & BNA_TX_F_ENABLED)
-		bfa_fsm_send_event(tx, TX_E_START);
-}
-
-static void
-bna_tx_stop(struct bna_tx *tx)
-{
-	tx->stop_cbfn = bna_tx_mod_cb_tx_stopped;
-	tx->stop_cbarg = &tx->bna->tx_mod;
-
-	tx->flags &= ~BNA_TX_F_PORT_STARTED;
-	bfa_fsm_send_event(tx, TX_E_STOP);
-}
-
-static void
-bna_tx_fail(struct bna_tx *tx)
-{
-	tx->flags &= ~BNA_TX_F_PORT_STARTED;
-	bfa_fsm_send_event(tx, TX_E_FAIL);
-}
-
-static void
-bna_tx_prio_changed(struct bna_tx *tx, int prio)
-{
-	struct bna_txq *txq;
-	struct list_head		 *qe;
-
-	list_for_each(qe, &tx->txq_q) {
-		txq = (struct bna_txq *)qe;
-		txq->priority = prio;
-	}
-
-	bfa_fsm_send_event(tx, TX_E_PRIO_CHANGE);
-}
-
-static void
-bna_tx_cee_link_status(struct bna_tx *tx, int cee_link)
-{
-	if (cee_link)
-		tx->flags |= BNA_TX_F_PRIO_LOCK;
-	else
-		tx->flags &= ~BNA_TX_F_PRIO_LOCK;
-}
-
-static void
-bna_tx_mod_cb_tx_stopped(void *arg, struct bna_tx *tx,
-			enum bna_cb_status status)
-{
-	struct bna_tx_mod *tx_mod = (struct bna_tx_mod *)arg;
-
-	bfa_wc_down(&tx_mod->tx_stop_wc);
-}
-
-static void
-bna_tx_mod_cb_tx_stopped_all(void *arg)
-{
-	struct bna_tx_mod *tx_mod = (struct bna_tx_mod *)arg;
-
-	if (tx_mod->stop_cbfn)
-		tx_mod->stop_cbfn(&tx_mod->bna->port, BNA_CB_SUCCESS);
-	tx_mod->stop_cbfn = NULL;
-}
-
-void
-bna_tx_res_req(int num_txq, int txq_depth, struct bna_res_info *res_info)
-{
-	u32 q_size;
-	u32 page_count;
-	struct bna_mem_info *mem_info;
-
-	res_info[BNA_TX_RES_MEM_T_TCB].res_type = BNA_RES_T_MEM;
-	mem_info = &res_info[BNA_TX_RES_MEM_T_TCB].res_u.mem_info;
-	mem_info->mem_type = BNA_MEM_T_KVA;
-	mem_info->len = sizeof(struct bna_tcb);
-	mem_info->num = num_txq;
-
-	q_size = txq_depth * BFI_TXQ_WI_SIZE;
-	q_size = ALIGN(q_size, PAGE_SIZE);
-	page_count = q_size >> PAGE_SHIFT;
-
-	res_info[BNA_TX_RES_MEM_T_QPT].res_type = BNA_RES_T_MEM;
-	mem_info = &res_info[BNA_TX_RES_MEM_T_QPT].res_u.mem_info;
-	mem_info->mem_type = BNA_MEM_T_DMA;
-	mem_info->len = page_count * sizeof(struct bna_dma_addr);
-	mem_info->num = num_txq;
-
-	res_info[BNA_TX_RES_MEM_T_SWQPT].res_type = BNA_RES_T_MEM;
-	mem_info = &res_info[BNA_TX_RES_MEM_T_SWQPT].res_u.mem_info;
-	mem_info->mem_type = BNA_MEM_T_KVA;
-	mem_info->len = page_count * sizeof(void *);
-	mem_info->num = num_txq;
-
-	res_info[BNA_TX_RES_MEM_T_PAGE].res_type = BNA_RES_T_MEM;
-	mem_info = &res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info;
-	mem_info->mem_type = BNA_MEM_T_DMA;
-	mem_info->len = PAGE_SIZE;
-	mem_info->num = num_txq * page_count;
-
-	res_info[BNA_TX_RES_INTR_T_TXCMPL].res_type = BNA_RES_T_INTR;
-	res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info.intr_type =
-			BNA_INTR_T_MSIX;
-	res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info.num = num_txq;
-}
-
-struct bna_tx *
-bna_tx_create(struct bna *bna, struct bnad *bnad,
-		struct bna_tx_config *tx_cfg,
-		struct bna_tx_event_cbfn *tx_cbfn,
-		struct bna_res_info *res_info, void *priv)
-{
-	struct bna_intr_info *intr_info;
-	struct bna_tx_mod *tx_mod = &bna->tx_mod;
-	struct bna_tx *tx;
-	struct bna_txq *txq;
-	struct list_head *qe;
-	struct bna_ib_mod *ib_mod = &bna->ib_mod;
-	struct bna_doorbell_qset *qset;
-	struct bna_ib_config ib_config;
-	int page_count;
-	int page_size;
-	int page_idx;
-	int i;
-	unsigned long off;
-
-	intr_info = &res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info;
-	page_count = (res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.num) /
-			tx_cfg->num_txq;
-	page_size = res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.len;
-
-	/**
-	 * Get resources
-	 */
-
-	if ((intr_info->num != 1) && (intr_info->num != tx_cfg->num_txq))
-		return NULL;
-
-	/* Tx */
-
-	if (list_empty(&tx_mod->tx_free_q))
-		return NULL;
-	bfa_q_deq(&tx_mod->tx_free_q, &tx);
-	bfa_q_qe_init(&tx->qe);
-
-	/* TxQs */
-
-	INIT_LIST_HEAD(&tx->txq_q);
-	for (i = 0; i < tx_cfg->num_txq; i++) {
-		if (list_empty(&tx_mod->txq_free_q))
-			goto err_return;
-
-		bfa_q_deq(&tx_mod->txq_free_q, &txq);
-		bfa_q_qe_init(&txq->qe);
-		list_add_tail(&txq->qe, &tx->txq_q);
-		txq->ib = NULL;
-		txq->ib_seg_offset = -1;
-		txq->tx = tx;
-	}
-
-	/* IBs */
-	i = 0;
-	list_for_each(qe, &tx->txq_q) {
-		txq = (struct bna_txq *)qe;
-
-		if (intr_info->num == 1)
-			txq->ib = bna_ib_get(ib_mod, intr_info->intr_type,
-						intr_info->idl[0].vector);
-		else
-			txq->ib = bna_ib_get(ib_mod, intr_info->intr_type,
-						intr_info->idl[i].vector);
-
-		if (txq->ib == NULL)
-			goto err_return;
-
-		txq->ib_seg_offset = bna_ib_reserve_idx(txq->ib);
-		if (txq->ib_seg_offset == -1)
-			goto err_return;
-
-		i++;
-	}
-
-	/*
-	 * Initialize
-	 */
-
-	/* Tx */
-
-	tx->tcb_setup_cbfn = tx_cbfn->tcb_setup_cbfn;
-	tx->tcb_destroy_cbfn = tx_cbfn->tcb_destroy_cbfn;
-	/* Following callbacks are mandatory */
-	tx->tx_stall_cbfn = tx_cbfn->tx_stall_cbfn;
-	tx->tx_resume_cbfn = tx_cbfn->tx_resume_cbfn;
-	tx->tx_cleanup_cbfn = tx_cbfn->tx_cleanup_cbfn;
-
-	list_add_tail(&tx->qe, &tx_mod->tx_active_q);
-	tx->bna = bna;
-	tx->priv = priv;
-	tx->txq_stop_wc.wc_resume = bna_tx_cb_txq_stopped_all;
-	tx->txq_stop_wc.wc_cbarg = tx;
-	tx->txq_stop_wc.wc_count = 0;
-
-	tx->type = tx_cfg->tx_type;
-
-	tx->flags = 0;
-	if (tx->bna->tx_mod.flags & BNA_TX_MOD_F_PORT_STARTED) {
-		switch (tx->type) {
-		case BNA_TX_T_REGULAR:
-			if (!(tx->bna->tx_mod.flags &
-				BNA_TX_MOD_F_PORT_LOOPBACK))
-				tx->flags |= BNA_TX_F_PORT_STARTED;
-			break;
-		case BNA_TX_T_LOOPBACK:
-			if (tx->bna->tx_mod.flags & BNA_TX_MOD_F_PORT_LOOPBACK)
-				tx->flags |= BNA_TX_F_PORT_STARTED;
-			break;
-		}
-	}
-	if (tx->bna->tx_mod.cee_link)
-		tx->flags |= BNA_TX_F_PRIO_LOCK;
-
-	/* TxQ */
-
-	i = 0;
-	page_idx = 0;
-	list_for_each(qe, &tx->txq_q) {
-		txq = (struct bna_txq *)qe;
-		txq->priority = tx_mod->priority;
-		txq->tcb = (struct bna_tcb *)
-		  res_info[BNA_TX_RES_MEM_T_TCB].res_u.mem_info.mdl[i].kva;
-		txq->tx_packets = 0;
-		txq->tx_bytes = 0;
-
-		/* IB */
-
-		ib_config.coalescing_timeo = BFI_TX_COALESCING_TIMEO;
-		ib_config.interpkt_timeo = 0; /* Not used */
-		ib_config.interpkt_count = BFI_TX_INTERPKT_COUNT;
-		ib_config.ctrl_flags = (BFI_IB_CF_INTER_PKT_DMA |
-					BFI_IB_CF_INT_ENABLE |
-					BFI_IB_CF_COALESCING_MODE);
-		bna_ib_config(txq->ib, &ib_config);
-
-		/* TCB */
-
-		txq->tcb->producer_index = 0;
-		txq->tcb->consumer_index = 0;
-		txq->tcb->hw_consumer_index = (volatile u32 *)
-			((volatile u8 *)txq->ib->ib_seg_host_addr_kva +
-			 (txq->ib_seg_offset * BFI_IBIDX_SIZE));
-		*(txq->tcb->hw_consumer_index) = 0;
-		txq->tcb->q_depth = tx_cfg->txq_depth;
-		txq->tcb->unmap_q = (void *)
-		res_info[BNA_TX_RES_MEM_T_UNMAPQ].res_u.mem_info.mdl[i].kva;
-		qset = (struct bna_doorbell_qset *)0;
-		off = (unsigned long)&qset[txq->txq_id].txq[0];
-		txq->tcb->q_dbell = off +
-			BNA_GET_DOORBELL_BASE_ADDR(bna->pcidev.pci_bar_kva);
-		txq->tcb->i_dbell = &txq->ib->door_bell;
-		txq->tcb->intr_type = intr_info->intr_type;
-		txq->tcb->intr_vector = (intr_info->num == 1) ?
-					intr_info->idl[0].vector :
-					intr_info->idl[i].vector;
-		txq->tcb->txq = txq;
-		txq->tcb->bnad = bnad;
-		txq->tcb->id = i;
-
-		/* QPT, SWQPT, Pages */
-		bna_txq_qpt_setup(txq, page_count, page_size,
-			&res_info[BNA_TX_RES_MEM_T_QPT].res_u.mem_info.mdl[i],
-			&res_info[BNA_TX_RES_MEM_T_SWQPT].res_u.mem_info.mdl[i],
-			&res_info[BNA_TX_RES_MEM_T_PAGE].
-				  res_u.mem_info.mdl[page_idx]);
-		txq->tcb->page_idx = page_idx;
-		txq->tcb->page_count = page_count;
-		page_idx += page_count;
-
-		/* Callback to bnad for setting up TCB */
-		if (tx->tcb_setup_cbfn)
-			(tx->tcb_setup_cbfn)(bna->bnad, txq->tcb);
-
-		i++;
-	}
-
-	/* TxF */
-
-	tx->txf.ctrl_flags = BFI_TXF_CF_ENABLE | BFI_TXF_CF_VLAN_WI_BASED;
-	tx->txf.vlan = 0;
-
-	/* Mbox element */
-	bfa_q_qe_init(&tx->mbox_qe.qe);
-
-	bfa_fsm_set_state(tx, bna_tx_sm_stopped);
-
-	return tx;
-
-err_return:
-	bna_tx_free(tx);
-	return NULL;
-}
-
-void
-bna_tx_destroy(struct bna_tx *tx)
-{
-	/* Callback to bnad for destroying TCB */
-	if (tx->tcb_destroy_cbfn) {
-		struct bna_txq *txq;
-		struct list_head *qe;
-
-		list_for_each(qe, &tx->txq_q) {
-			txq = (struct bna_txq *)qe;
-			(tx->tcb_destroy_cbfn)(tx->bna->bnad, txq->tcb);
-		}
-	}
-
-	bna_tx_free(tx);
-}
-
-void
-bna_tx_enable(struct bna_tx *tx)
-{
-	if (tx->fsm != (bfa_sm_t)bna_tx_sm_stopped)
-		return;
-
-	tx->flags |= BNA_TX_F_ENABLED;
-
-	if (tx->flags & BNA_TX_F_PORT_STARTED)
-		bfa_fsm_send_event(tx, TX_E_START);
-}
-
-void
-bna_tx_disable(struct bna_tx *tx, enum bna_cleanup_type type,
-		void (*cbfn)(void *, struct bna_tx *, enum bna_cb_status))
-{
-	if (type == BNA_SOFT_CLEANUP) {
-		(*cbfn)(tx->bna->bnad, tx, BNA_CB_SUCCESS);
-		return;
-	}
-
-	tx->stop_cbfn = cbfn;
-	tx->stop_cbarg = tx->bna->bnad;
-
-	tx->flags &= ~BNA_TX_F_ENABLED;
-
-	bfa_fsm_send_event(tx, TX_E_STOP);
-}
-
-int
-bna_tx_state_get(struct bna_tx *tx)
-{
-	return bfa_sm_to_state(tx_sm_table, tx->fsm);
-}
-
-void
-bna_tx_mod_init(struct bna_tx_mod *tx_mod, struct bna *bna,
-		struct bna_res_info *res_info)
-{
-	int i;
-
-	tx_mod->bna = bna;
-	tx_mod->flags = 0;
-
-	tx_mod->tx = (struct bna_tx *)
-		res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.mdl[0].kva;
-	tx_mod->txq = (struct bna_txq *)
-		res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.mdl[0].kva;
-
-	INIT_LIST_HEAD(&tx_mod->tx_free_q);
-	INIT_LIST_HEAD(&tx_mod->tx_active_q);
-
-	INIT_LIST_HEAD(&tx_mod->txq_free_q);
-
-	for (i = 0; i < BFI_MAX_TXQ; i++) {
-		tx_mod->tx[i].txf.txf_id = i;
-		bfa_q_qe_init(&tx_mod->tx[i].qe);
-		list_add_tail(&tx_mod->tx[i].qe, &tx_mod->tx_free_q);
-
-		tx_mod->txq[i].txq_id = i;
-		bfa_q_qe_init(&tx_mod->txq[i].qe);
-		list_add_tail(&tx_mod->txq[i].qe, &tx_mod->txq_free_q);
-	}
-
-	tx_mod->tx_stop_wc.wc_resume = bna_tx_mod_cb_tx_stopped_all;
-	tx_mod->tx_stop_wc.wc_cbarg = tx_mod;
-	tx_mod->tx_stop_wc.wc_count = 0;
-}
-
-void
-bna_tx_mod_uninit(struct bna_tx_mod *tx_mod)
-{
-	struct list_head		*qe;
-	int i;
-
-	i = 0;
-	list_for_each(qe, &tx_mod->tx_free_q)
-		i++;
-
-	i = 0;
-	list_for_each(qe, &tx_mod->txq_free_q)
-		i++;
-
-	tx_mod->bna = NULL;
-}
-
-void
-bna_tx_mod_start(struct bna_tx_mod *tx_mod, enum bna_tx_type type)
-{
-	struct bna_tx *tx;
-	struct list_head		*qe;
-
-	tx_mod->flags |= BNA_TX_MOD_F_PORT_STARTED;
-	if (type == BNA_TX_T_LOOPBACK)
-		tx_mod->flags |= BNA_TX_MOD_F_PORT_LOOPBACK;
-
-	list_for_each(qe, &tx_mod->tx_active_q) {
-		tx = (struct bna_tx *)qe;
-		if (tx->type == type)
-			bna_tx_start(tx);
-	}
-}
-
-void
-bna_tx_mod_stop(struct bna_tx_mod *tx_mod, enum bna_tx_type type)
-{
-	struct bna_tx *tx;
-	struct list_head		*qe;
-
-	tx_mod->flags &= ~BNA_TX_MOD_F_PORT_STARTED;
-	tx_mod->flags &= ~BNA_TX_MOD_F_PORT_LOOPBACK;
-
-	tx_mod->stop_cbfn = bna_port_cb_tx_stopped;
-
-	/**
-	 * Before calling bna_tx_stop(), increment tx_stop_wc as many times
-	 * as we are going to call bna_tx_stop
-	 */
-	list_for_each(qe, &tx_mod->tx_active_q) {
-		tx = (struct bna_tx *)qe;
-		if (tx->type == type)
-			bfa_wc_up(&tx_mod->tx_stop_wc);
-	}
-
-	if (tx_mod->tx_stop_wc.wc_count == 0) {
-		tx_mod->stop_cbfn(&tx_mod->bna->port, BNA_CB_SUCCESS);
-		tx_mod->stop_cbfn = NULL;
-		return;
-	}
-
-	list_for_each(qe, &tx_mod->tx_active_q) {
-		tx = (struct bna_tx *)qe;
-		if (tx->type == type)
-			bna_tx_stop(tx);
-	}
-}
-
-void
-bna_tx_mod_fail(struct bna_tx_mod *tx_mod)
-{
-	struct bna_tx *tx;
-	struct list_head		*qe;
-
-	tx_mod->flags &= ~BNA_TX_MOD_F_PORT_STARTED;
-	tx_mod->flags &= ~BNA_TX_MOD_F_PORT_LOOPBACK;
-
-	list_for_each(qe, &tx_mod->tx_active_q) {
-		tx = (struct bna_tx *)qe;
-		bna_tx_fail(tx);
-	}
-}
-
-void
-bna_tx_mod_prio_changed(struct bna_tx_mod *tx_mod, int prio)
-{
-	struct bna_tx *tx;
-	struct list_head		*qe;
-
-	if (prio != tx_mod->priority) {
-		tx_mod->priority = prio;
-
-		list_for_each(qe, &tx_mod->tx_active_q) {
-			tx = (struct bna_tx *)qe;
-			bna_tx_prio_changed(tx, prio);
-		}
-	}
-}
-
-void
-bna_tx_mod_cee_link_status(struct bna_tx_mod *tx_mod, int cee_link)
-{
-	struct bna_tx *tx;
-	struct list_head		*qe;
-
-	tx_mod->cee_link = cee_link;
-
-	list_for_each(qe, &tx_mod->tx_active_q) {
-		tx = (struct bna_tx *)qe;
-		bna_tx_cee_link_status(tx, cee_link);
-	}
-}
diff -druN linux-libre-3.1-gnu/drivers/net/bna/bna_types.h linux-libre-3.2-gnu/drivers/net/bna/bna_types.h
--- linux-libre-3.1-gnu/drivers/net/bna/bna_types.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/bna_types.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1127 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-#ifndef __BNA_TYPES_H__
-#define __BNA_TYPES_H__
-
-#include "cna.h"
-#include "bna_hw.h"
-#include "bfa_cee.h"
-
-/**
- *
- * Forward declarations
- *
- */
-
-struct bna_txq;
-struct bna_tx;
-struct bna_rxq;
-struct bna_cq;
-struct bna_rx;
-struct bna_rxf;
-struct bna_port;
-struct bna;
-struct bnad;
-
-/**
- *
- * Enums, primitive data types
- *
- */
-
-enum bna_status {
-	BNA_STATUS_T_DISABLED	= 0,
-	BNA_STATUS_T_ENABLED	= 1
-};
-
-enum bna_cleanup_type {
-	BNA_HARD_CLEANUP	= 0,
-	BNA_SOFT_CLEANUP	= 1
-};
-
-enum bna_cb_status {
-	BNA_CB_SUCCESS		= 0,
-	BNA_CB_FAIL		= 1,
-	BNA_CB_INTERRUPT	= 2,
-	BNA_CB_BUSY		= 3,
-	BNA_CB_INVALID_MAC	= 4,
-	BNA_CB_MCAST_LIST_FULL	= 5,
-	BNA_CB_UCAST_CAM_FULL	= 6,
-	BNA_CB_WAITING		= 7,
-	BNA_CB_NOT_EXEC		= 8
-};
-
-enum bna_res_type {
-	BNA_RES_T_MEM		= 1,
-	BNA_RES_T_INTR		= 2
-};
-
-enum bna_mem_type {
-	BNA_MEM_T_KVA		= 1,
-	BNA_MEM_T_DMA		= 2
-};
-
-enum bna_intr_type {
-	BNA_INTR_T_INTX		= 1,
-	BNA_INTR_T_MSIX		= 2
-};
-
-enum bna_res_req_type {
-	BNA_RES_MEM_T_COM		= 0,
-	BNA_RES_MEM_T_ATTR		= 1,
-	BNA_RES_MEM_T_FWTRC		= 2,
-	BNA_RES_MEM_T_STATS		= 3,
-	BNA_RES_MEM_T_SWSTATS		= 4,
-	BNA_RES_MEM_T_IBIDX		= 5,
-	BNA_RES_MEM_T_IB_ARRAY		= 6,
-	BNA_RES_MEM_T_INTR_ARRAY	= 7,
-	BNA_RES_MEM_T_IDXSEG_ARRAY	= 8,
-	BNA_RES_MEM_T_TX_ARRAY		= 9,
-	BNA_RES_MEM_T_TXQ_ARRAY		= 10,
-	BNA_RES_MEM_T_RX_ARRAY		= 11,
-	BNA_RES_MEM_T_RXP_ARRAY		= 12,
-	BNA_RES_MEM_T_RXQ_ARRAY		= 13,
-	BNA_RES_MEM_T_UCMAC_ARRAY	= 14,
-	BNA_RES_MEM_T_MCMAC_ARRAY	= 15,
-	BNA_RES_MEM_T_RIT_ENTRY		= 16,
-	BNA_RES_MEM_T_RIT_SEGMENT	= 17,
-	BNA_RES_INTR_T_MBOX		= 18,
-	BNA_RES_T_MAX
-};
-
-enum bna_tx_res_req_type {
-	BNA_TX_RES_MEM_T_TCB	= 0,
-	BNA_TX_RES_MEM_T_UNMAPQ	= 1,
-	BNA_TX_RES_MEM_T_QPT	= 2,
-	BNA_TX_RES_MEM_T_SWQPT	= 3,
-	BNA_TX_RES_MEM_T_PAGE	= 4,
-	BNA_TX_RES_INTR_T_TXCMPL = 5,
-	BNA_TX_RES_T_MAX,
-};
-
-enum bna_rx_mem_type {
-	BNA_RX_RES_MEM_T_CCB		= 0,	/* CQ context */
-	BNA_RX_RES_MEM_T_RCB		= 1,	/* CQ context */
-	BNA_RX_RES_MEM_T_UNMAPQ		= 2,	/* UnmapQ for RxQs */
-	BNA_RX_RES_MEM_T_CQPT		= 3,	/* CQ QPT */
-	BNA_RX_RES_MEM_T_CSWQPT		= 4,	/* S/W QPT */
-	BNA_RX_RES_MEM_T_CQPT_PAGE	= 5,	/* CQPT page */
-	BNA_RX_RES_MEM_T_HQPT		= 6,	/* RX QPT */
-	BNA_RX_RES_MEM_T_DQPT		= 7,	/* RX QPT */
-	BNA_RX_RES_MEM_T_HSWQPT		= 8,	/* RX s/w QPT */
-	BNA_RX_RES_MEM_T_DSWQPT		= 9,	/* RX s/w QPT */
-	BNA_RX_RES_MEM_T_DPAGE		= 10,	/* RX s/w QPT */
-	BNA_RX_RES_MEM_T_HPAGE		= 11,	/* RX s/w QPT */
-	BNA_RX_RES_T_INTR		= 12,	/* Rx interrupts */
-	BNA_RX_RES_T_MAX		= 13
-};
-
-enum bna_mbox_state {
-	BNA_MBOX_FREE		= 0,
-	BNA_MBOX_POSTED		= 1
-};
-
-enum bna_tx_type {
-	BNA_TX_T_REGULAR	= 0,
-	BNA_TX_T_LOOPBACK	= 1,
-};
-
-enum bna_tx_flags {
-	BNA_TX_F_PORT_STARTED	= 1,
-	BNA_TX_F_ENABLED	= 2,
-	BNA_TX_F_PRIO_LOCK	= 4,
-};
-
-enum bna_tx_mod_flags {
-	BNA_TX_MOD_F_PORT_STARTED	= 1,
-	BNA_TX_MOD_F_PORT_LOOPBACK	= 2,
-};
-
-enum bna_rx_type {
-	BNA_RX_T_REGULAR	= 0,
-	BNA_RX_T_LOOPBACK	= 1,
-};
-
-enum bna_rxp_type {
-	BNA_RXP_SINGLE		= 1,
-	BNA_RXP_SLR		= 2,
-	BNA_RXP_HDS		= 3
-};
-
-enum bna_rxmode {
-	BNA_RXMODE_PROMISC	= 1,
-	BNA_RXMODE_ALLMULTI	= 2
-};
-
-enum bna_rx_event {
-	RX_E_START			= 1,
-	RX_E_STOP			= 2,
-	RX_E_FAIL			= 3,
-	RX_E_RXF_STARTED		= 4,
-	RX_E_RXF_STOPPED		= 5,
-	RX_E_RXQ_STOPPED		= 6,
-};
-
-enum bna_rx_state {
-	BNA_RX_STOPPED			= 1,
-	BNA_RX_RXF_START_WAIT		= 2,
-	BNA_RX_STARTED			= 3,
-	BNA_RX_RXF_STOP_WAIT		= 4,
-	BNA_RX_RXQ_STOP_WAIT		= 5,
-};
-
-enum bna_rx_flags {
-	BNA_RX_F_ENABLE		= 0x01,		/* bnad enabled rxf */
-	BNA_RX_F_PORT_ENABLED	= 0x02,		/* Port object is enabled */
-	BNA_RX_F_PORT_FAILED	= 0x04,		/* Port in failed state */
-};
-
-enum bna_rx_mod_flags {
-	BNA_RX_MOD_F_PORT_STARTED	= 1,
-	BNA_RX_MOD_F_PORT_LOOPBACK	= 2,
-};
-
-enum bna_rxf_oper_state {
-	BNA_RXF_OPER_STATE_RUNNING	= 0x01, /* rxf operational */
-	BNA_RXF_OPER_STATE_PAUSED	= 0x02,	/* rxf in PAUSED state */
-};
-
-enum bna_rxf_flags {
-	BNA_RXF_FL_STOP_PENDING		= 0x01,
-	BNA_RXF_FL_FAILED		= 0x02,
-	BNA_RXF_FL_RSS_CONFIG_PENDING	= 0x04,
-	BNA_RXF_FL_OPERSTATE_CHANGED	= 0x08,
-	BNA_RXF_FL_RXF_ENABLED		= 0x10,
-	BNA_RXF_FL_VLAN_CONFIG_PENDING	= 0x20,
-};
-
-enum bna_rxf_event {
-	RXF_E_START			= 1,
-	RXF_E_STOP			= 2,
-	RXF_E_FAIL			= 3,
-	RXF_E_CAM_FLTR_MOD		= 4,
-	RXF_E_STARTED			= 5,
-	RXF_E_STOPPED			= 6,
-	RXF_E_CAM_FLTR_RESP		= 7,
-	RXF_E_PAUSE			= 8,
-	RXF_E_RESUME			= 9,
-	RXF_E_STAT_CLEARED		= 10,
-};
-
-enum bna_rxf_state {
-	BNA_RXF_STOPPED			= 1,
-	BNA_RXF_START_WAIT		= 2,
-	BNA_RXF_CAM_FLTR_MOD_WAIT	= 3,
-	BNA_RXF_STARTED			= 4,
-	BNA_RXF_CAM_FLTR_CLR_WAIT	= 5,
-	BNA_RXF_STOP_WAIT		= 6,
-	BNA_RXF_PAUSE_WAIT		= 7,
-	BNA_RXF_RESUME_WAIT		= 8,
-	BNA_RXF_STAT_CLR_WAIT		= 9,
-};
-
-enum bna_port_type {
-	BNA_PORT_T_REGULAR		= 0,
-	BNA_PORT_T_LOOPBACK_INTERNAL	= 1,
-	BNA_PORT_T_LOOPBACK_EXTERNAL	= 2,
-};
-
-enum bna_link_status {
-	BNA_LINK_DOWN		= 0,
-	BNA_LINK_UP		= 1,
-	BNA_CEE_UP		= 2
-};
-
-enum bna_llport_flags {
-	BNA_LLPORT_F_ADMIN_UP		= 1,
-	BNA_LLPORT_F_PORT_ENABLED	= 2,
-	BNA_LLPORT_F_RX_STARTED		= 4
-};
-
-enum bna_port_flags {
-	BNA_PORT_F_DEVICE_READY	= 1,
-	BNA_PORT_F_ENABLED	= 2,
-	BNA_PORT_F_PAUSE_CHANGED = 4,
-	BNA_PORT_F_MTU_CHANGED	= 8
-};
-
-enum bna_pkt_rates {
-	BNA_PKT_RATE_10K		= 10000,
-	BNA_PKT_RATE_20K		= 20000,
-	BNA_PKT_RATE_30K		= 30000,
-	BNA_PKT_RATE_40K		= 40000,
-	BNA_PKT_RATE_50K		= 50000,
-	BNA_PKT_RATE_60K		= 60000,
-	BNA_PKT_RATE_70K		= 70000,
-	BNA_PKT_RATE_80K		= 80000,
-};
-
-enum bna_dim_load_types {
-	BNA_LOAD_T_HIGH_4		= 0, /* 80K <= r */
-	BNA_LOAD_T_HIGH_3		= 1, /* 60K <= r < 80K */
-	BNA_LOAD_T_HIGH_2		= 2, /* 50K <= r < 60K */
-	BNA_LOAD_T_HIGH_1		= 3, /* 40K <= r < 50K */
-	BNA_LOAD_T_LOW_1		= 4, /* 30K <= r < 40K */
-	BNA_LOAD_T_LOW_2		= 5, /* 20K <= r < 30K */
-	BNA_LOAD_T_LOW_3		= 6, /* 10K <= r < 20K */
-	BNA_LOAD_T_LOW_4		= 7, /* r < 10K */
-	BNA_LOAD_T_MAX			= 8
-};
-
-enum bna_dim_bias_types {
-	BNA_BIAS_T_SMALL		= 0, /* small pkts > (large pkts * 2) */
-	BNA_BIAS_T_LARGE		= 1, /* Not BNA_BIAS_T_SMALL */
-	BNA_BIAS_T_MAX			= 2
-};
-
-struct bna_mac {
-	/* This should be the first one */
-	struct list_head			qe;
-	u8			addr[ETH_ALEN];
-};
-
-struct bna_mem_descr {
-	u32		len;
-	void		*kva;
-	struct bna_dma_addr dma;
-};
-
-struct bna_mem_info {
-	enum bna_mem_type mem_type;
-	u32		len;
-	u32		num;
-	u32		align_sz; /* 0/1 = no alignment */
-	struct bna_mem_descr *mdl;
-	void			*cookie; /* For bnad to unmap dma later */
-};
-
-struct bna_intr_descr {
-	int			vector;
-};
-
-struct bna_intr_info {
-	enum bna_intr_type intr_type;
-	int			num;
-	struct bna_intr_descr *idl;
-};
-
-union bna_res_u {
-	struct bna_mem_info mem_info;
-	struct bna_intr_info intr_info;
-};
-
-struct bna_res_info {
-	enum bna_res_type res_type;
-	union bna_res_u		res_u;
-};
-
-/* HW QPT */
-struct bna_qpt {
-	struct bna_dma_addr hw_qpt_ptr;
-	void		*kv_qpt_ptr;
-	u32		page_count;
-	u32		page_size;
-};
-
-/**
- *
- * Device
- *
- */
-
-struct bna_device {
-	bfa_fsm_t		fsm;
-	struct bfa_ioc ioc;
-
-	enum bna_intr_type intr_type;
-	int			vector;
-
-	void (*ready_cbfn)(struct bnad *bnad, enum bna_cb_status status);
-	struct bnad *ready_cbarg;
-
-	void (*stop_cbfn)(struct bnad *bnad, enum bna_cb_status status);
-	struct bnad *stop_cbarg;
-
-	struct bna *bna;
-};
-
-/**
- *
- * Mail box
- *
- */
-
-struct bna_mbox_qe {
-	/* This should be the first one */
-	struct list_head			qe;
-
-	struct bfa_mbox_cmd cmd;
-	u32		cmd_len;
-	/* Callback for port, tx, rx, rxf */
-	void (*cbfn)(void *arg, int status);
-	void			*cbarg;
-};
-
-struct bna_mbox_mod {
-	enum bna_mbox_state state;
-	struct list_head			posted_q;
-	u32		msg_pending;
-	u32		msg_ctr;
-	struct bna *bna;
-};
-
-/**
- *
- * Port
- *
- */
-
-/* Pause configuration */
-struct bna_pause_config {
-	enum bna_status tx_pause;
-	enum bna_status rx_pause;
-};
-
-struct bna_llport {
-	bfa_fsm_t		fsm;
-	enum bna_llport_flags flags;
-
-	enum bna_port_type type;
-
-	enum bna_link_status link_status;
-
-	int			rx_started_count;
-
-	void (*stop_cbfn)(struct bna_port *, enum bna_cb_status);
-
-	struct bna_mbox_qe mbox_qe;
-
-	struct bna *bna;
-};
-
-struct bna_port {
-	bfa_fsm_t		fsm;
-	enum bna_port_flags flags;
-
-	enum bna_port_type type;
-
-	struct bna_llport llport;
-
-	struct bna_pause_config pause_config;
-	u8			priority;
-	int			mtu;
-
-	/* Callback for bna_port_disable(), port_stop() */
-	void (*stop_cbfn)(void *, enum bna_cb_status);
-	void			*stop_cbarg;
-
-	/* Callback for bna_port_pause_config() */
-	void (*pause_cbfn)(struct bnad *, enum bna_cb_status);
-
-	/* Callback for bna_port_mtu_set() */
-	void (*mtu_cbfn)(struct bnad *, enum bna_cb_status);
-
-	void (*link_cbfn)(struct bnad *, enum bna_link_status);
-
-	struct bfa_wc		chld_stop_wc;
-
-	struct bna_mbox_qe mbox_qe;
-
-	struct bna *bna;
-};
-
-/**
- *
- * Interrupt Block
- *
- */
-
-/* IB index segment structure */
-struct bna_ibidx_seg {
-	/* This should be the first one */
-	struct list_head			qe;
-
-	u8			ib_seg_size;
-	u8			ib_idx_tbl_offset;
-};
-
-/* Interrupt structure */
-struct bna_intr {
-	/* This should be the first one */
-	struct list_head			qe;
-	int			ref_count;
-
-	enum bna_intr_type intr_type;
-	int			vector;
-
-	struct bna_ib *ib;
-};
-
-/* Doorbell structure */
-struct bna_ib_dbell {
-	void *__iomem doorbell_addr;
-	u32		doorbell_ack;
-};
-
-/* Interrupt timer configuration */
-struct bna_ib_config {
-	u8		coalescing_timeo;    /* Unit is 5usec. */
-
-	int			interpkt_count;
-	int			interpkt_timeo;
-
-	enum ib_flags ctrl_flags;
-};
-
-/* IB structure */
-struct bna_ib {
-	/* This should be the first one */
-	struct list_head			qe;
-
-	int			ib_id;
-
-	int			ref_count;
-	int			start_count;
-
-	struct bna_dma_addr ib_seg_host_addr;
-	void		*ib_seg_host_addr_kva;
-	u32		idx_mask; /* Size >= BNA_IBIDX_MAX_SEGSIZE */
-
-	struct bna_ibidx_seg *idx_seg;
-
-	struct bna_ib_dbell door_bell;
-
-	struct bna_intr *intr;
-
-	struct bna_ib_config ib_config;
-
-	struct bna *bna;
-};
-
-/* IB module - keeps track of IBs and interrupts */
-struct bna_ib_mod {
-	struct bna_ib *ib;		/* BFI_MAX_IB entries */
-	struct bna_intr *intr;		/* BFI_MAX_IB entries */
-	struct bna_ibidx_seg *idx_seg;	/* BNA_IBIDX_TOTAL_SEGS */
-
-	struct list_head			ib_free_q;
-
-	struct list_head		ibidx_seg_pool[BFI_IBIDX_TOTAL_POOLS];
-
-	struct list_head			intr_free_q;
-	struct list_head			intr_active_q;
-
-	struct bna *bna;
-};
-
-/**
- *
- * Tx object
- *
- */
-
-/* Tx datapath control structure */
-#define BNA_Q_NAME_SIZE		16
-struct bna_tcb {
-	/* Fast path */
-	void			**sw_qpt;
-	void			*unmap_q;
-	u32		producer_index;
-	u32		consumer_index;
-	volatile u32	*hw_consumer_index;
-	u32		q_depth;
-	void *__iomem q_dbell;
-	struct bna_ib_dbell *i_dbell;
-	int			page_idx;
-	int			page_count;
-	/* Control path */
-	struct bna_txq *txq;
-	struct bnad *bnad;
-	enum bna_intr_type intr_type;
-	int			intr_vector;
-	u8			priority; /* Current priority */
-	unsigned long		flags; /* Used by bnad as required */
-	int			id;
-	char			name[BNA_Q_NAME_SIZE];
-};
-
-/* TxQ QPT and configuration */
-struct bna_txq {
-	/* This should be the first one */
-	struct list_head			qe;
-
-	int			txq_id;
-
-	u8			priority;
-
-	struct bna_qpt qpt;
-	struct bna_tcb *tcb;
-	struct bna_ib *ib;
-	int			ib_seg_offset;
-
-	struct bna_tx *tx;
-
-	u64		tx_packets;
-	u64		tx_bytes;
-};
-
-/* TxF structure (hardware Tx Function) */
-struct bna_txf {
-	int			txf_id;
-	enum txf_flags ctrl_flags;
-	u16		vlan;
-};
-
-/* Tx object */
-struct bna_tx {
-	/* This should be the first one */
-	struct list_head			qe;
-
-	bfa_fsm_t		fsm;
-	enum bna_tx_flags flags;
-
-	enum bna_tx_type type;
-
-	struct list_head			txq_q;
-	struct bna_txf txf;
-
-	/* Tx event handlers */
-	void (*tcb_setup_cbfn)(struct bnad *, struct bna_tcb *);
-	void (*tcb_destroy_cbfn)(struct bnad *, struct bna_tcb *);
-	void (*tx_stall_cbfn)(struct bnad *, struct bna_tcb *);
-	void (*tx_resume_cbfn)(struct bnad *, struct bna_tcb *);
-	void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tcb *);
-
-	/* callback for bna_tx_disable(), bna_tx_stop() */
-	void (*stop_cbfn)(void *arg, struct bna_tx *tx,
-				enum bna_cb_status status);
-	void			*stop_cbarg;
-
-	/* callback for bna_tx_prio_set() */
-	void (*prio_change_cbfn)(struct bnad *bnad, struct bna_tx *tx,
-				enum bna_cb_status status);
-
-	struct bfa_wc		txq_stop_wc;
-
-	struct bna_mbox_qe mbox_qe;
-
-	struct bna *bna;
-	void			*priv;	/* bnad's cookie */
-};
-
-struct bna_tx_config {
-	int			num_txq;
-	int			txq_depth;
-	enum bna_tx_type tx_type;
-};
-
-struct bna_tx_event_cbfn {
-	/* Optional */
-	void (*tcb_setup_cbfn)(struct bnad *, struct bna_tcb *);
-	void (*tcb_destroy_cbfn)(struct bnad *, struct bna_tcb *);
-	/* Mandatory */
-	void (*tx_stall_cbfn)(struct bnad *, struct bna_tcb *);
-	void (*tx_resume_cbfn)(struct bnad *, struct bna_tcb *);
-	void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tcb *);
-};
-
-/* Tx module - keeps track of free, active tx objects */
-struct bna_tx_mod {
-	struct bna_tx *tx;		/* BFI_MAX_TXQ entries */
-	struct bna_txq *txq;		/* BFI_MAX_TXQ entries */
-
-	struct list_head			tx_free_q;
-	struct list_head			tx_active_q;
-
-	struct list_head			txq_free_q;
-
-	/* callback for bna_tx_mod_stop() */
-	void (*stop_cbfn)(struct bna_port *port,
-				enum bna_cb_status status);
-
-	struct bfa_wc		tx_stop_wc;
-
-	enum bna_tx_mod_flags flags;
-
-	int			priority;
-	int			cee_link;
-
-	u32		txf_bmap[2];
-
-	struct bna *bna;
-};
-
-/**
- *
- * Receive Indirection Table
- *
- */
-
-/* One row of RIT table */
-struct bna_rit_entry {
-	u8 large_rxq_id;	/* used for either large or data buffers */
-	u8 small_rxq_id;	/* used for either small or header buffers */
-};
-
-/* RIT segment */
-struct bna_rit_segment {
-	struct list_head			qe;
-
-	u32		rit_offset;
-	u32		rit_size;
-	/**
-	 * max_rit_size: Varies per RIT segment depending on how RIT is
-	 * partitioned
-	 */
-	u32		max_rit_size;
-
-	struct bna_rit_entry *rit;
-};
-
-struct bna_rit_mod {
-	struct bna_rit_entry *rit;
-	struct bna_rit_segment *rit_segment;
-
-	struct list_head		rit_seg_pool[BFI_RIT_SEG_TOTAL_POOLS];
-};
-
-/**
- *
- * Rx object
- *
- */
-
-/* Rx datapath control structure */
-struct bna_rcb {
-	/* Fast path */
-	void			**sw_qpt;
-	void			*unmap_q;
-	u32		producer_index;
-	u32		consumer_index;
-	u32		q_depth;
-	void *__iomem q_dbell;
-	int			page_idx;
-	int			page_count;
-	/* Control path */
-	struct bna_rxq *rxq;
-	struct bna_cq *cq;
-	struct bnad *bnad;
-	unsigned long		flags;
-	int			id;
-};
-
-/* RxQ structure - QPT, configuration */
-struct bna_rxq {
-	struct list_head			qe;
-	int			rxq_id;
-
-	int			buffer_size;
-	int			q_depth;
-
-	struct bna_qpt qpt;
-	struct bna_rcb *rcb;
-
-	struct bna_rxp *rxp;
-	struct bna_rx *rx;
-
-	u64		rx_packets;
-	u64		rx_bytes;
-	u64		rx_packets_with_error;
-	u64		rxbuf_alloc_failed;
-};
-
-/* RxQ pair */
-union bna_rxq_u {
-	struct {
-		struct bna_rxq *hdr;
-		struct bna_rxq *data;
-	} hds;
-	struct {
-		struct bna_rxq *small;
-		struct bna_rxq *large;
-	} slr;
-	struct {
-		struct bna_rxq *only;
-		struct bna_rxq *reserved;
-	} single;
-};
-
-/* Packet rate for Dynamic Interrupt Moderation */
-struct bna_pkt_rate {
-	u32		small_pkt_cnt;
-	u32		large_pkt_cnt;
-};
-
-/* Completion control structure */
-struct bna_ccb {
-	/* Fast path */
-	void			**sw_qpt;
-	u32		producer_index;
-	volatile u32	*hw_producer_index;
-	u32		q_depth;
-	struct bna_ib_dbell *i_dbell;
-	struct bna_rcb *rcb[2];
-	void			*ctrl; /* For bnad */
-	struct bna_pkt_rate pkt_rate;
-	int			page_idx;
-	int			page_count;
-
-	/* Control path */
-	struct bna_cq *cq;
-	struct bnad *bnad;
-	enum bna_intr_type intr_type;
-	int			intr_vector;
-	u8			rx_coalescing_timeo; /* For NAPI */
-	int			id;
-	char			name[BNA_Q_NAME_SIZE];
-};
-
-/* CQ QPT, configuration  */
-struct bna_cq {
-	int			cq_id;
-
-	struct bna_qpt qpt;
-	struct bna_ccb *ccb;
-
-	struct bna_ib *ib;
-	u8			ib_seg_offset;
-
-	struct bna_rx *rx;
-};
-
-struct bna_rss_config {
-	enum rss_hash_type hash_type;
-	u8			hash_mask;
-	u32		toeplitz_hash_key[BFI_RSS_HASH_KEY_LEN];
-};
-
-struct bna_hds_config {
-	enum hds_header_type hdr_type;
-	int			header_size;
-};
-
-/* This structure is used during RX creation */
-struct bna_rx_config {
-	enum bna_rx_type rx_type;
-	int			num_paths;
-	enum bna_rxp_type rxp_type;
-	int			paused;
-	int			q_depth;
-	/*
-	 * Small/Large (or Header/Data) buffer size to be configured
-	 * for SLR and HDS queue type. Large buffer size comes from
-	 * port->mtu.
-	 */
-	int			small_buff_size;
-
-	enum bna_status rss_status;
-	struct bna_rss_config rss_config;
-
-	enum bna_status hds_status;
-	struct bna_hds_config hds_config;
-
-	enum bna_status vlan_strip_status;
-};
-
-/* Rx Path structure - one per MSIX vector/CPU */
-struct bna_rxp {
-	/* This should be the first one */
-	struct list_head			qe;
-
-	enum bna_rxp_type type;
-	union	bna_rxq_u	rxq;
-	struct bna_cq cq;
-
-	struct bna_rx *rx;
-
-	/* MSI-x vector number for configuring RSS */
-	int			vector;
-
-	struct bna_mbox_qe mbox_qe;
-};
-
-/* HDS configuration structure */
-struct bna_rxf_hds {
-	enum hds_header_type hdr_type;
-	int			header_size;
-};
-
-/* RSS configuration structure */
-struct bna_rxf_rss {
-	enum rss_hash_type hash_type;
-	u8			hash_mask;
-	u32		toeplitz_hash_key[BFI_RSS_HASH_KEY_LEN];
-};
-
-/* RxF structure (hardware Rx Function) */
-struct bna_rxf {
-	bfa_fsm_t		fsm;
-	int			rxf_id;
-	enum rxf_flags ctrl_flags;
-	u16		default_vlan_tag;
-	enum bna_rxf_oper_state rxf_oper_state;
-	enum bna_status hds_status;
-	struct bna_rxf_hds hds_cfg;
-	enum bna_status rss_status;
-	struct bna_rxf_rss rss_cfg;
-	struct bna_rit_segment *rit_segment;
-	struct bna_rx *rx;
-	u32		forced_offset;
-	struct bna_mbox_qe mbox_qe;
-	int			mcast_rxq_id;
-
-	/* callback for bna_rxf_start() */
-	void (*start_cbfn) (struct bna_rx *rx, enum bna_cb_status status);
-	struct bna_rx *start_cbarg;
-
-	/* callback for bna_rxf_stop() */
-	void (*stop_cbfn) (struct bna_rx *rx, enum bna_cb_status status);
-	struct bna_rx *stop_cbarg;
-
-	/* callback for bna_rxf_receive_enable() / bna_rxf_receive_disable() */
-	void (*oper_state_cbfn) (struct bnad *bnad, struct bna_rx *rx,
-			enum bna_cb_status status);
-	struct bnad *oper_state_cbarg;
-
-	/**
-	 * callback for:
-	 *	bna_rxf_ucast_set()
-	 *	bna_rxf_{ucast/mcast}_add(),
-	 *	bna_rxf_{ucast/mcast}_del(),
-	 *	bna_rxf_mode_set()
-	 */
-	void (*cam_fltr_cbfn)(struct bnad *bnad, struct bna_rx *rx,
-				enum bna_cb_status status);
-	struct bnad *cam_fltr_cbarg;
-
-	enum bna_rxf_flags rxf_flags;
-
-	/* List of unicast addresses yet to be applied to h/w */
-	struct list_head			ucast_pending_add_q;
-	struct list_head			ucast_pending_del_q;
-	int			ucast_pending_set;
-	/* ucast addresses applied to the h/w */
-	struct list_head			ucast_active_q;
-	struct bna_mac *ucast_active_mac;
-
-	/* List of multicast addresses yet to be applied to h/w */
-	struct list_head			mcast_pending_add_q;
-	struct list_head			mcast_pending_del_q;
-	/* multicast addresses applied to the h/w */
-	struct list_head			mcast_active_q;
-
-	/* Rx modes yet to be applied to h/w */
-	enum bna_rxmode rxmode_pending;
-	enum bna_rxmode rxmode_pending_bitmask;
-	/* Rx modes applied to h/w */
-	enum bna_rxmode rxmode_active;
-
-	enum bna_status vlan_filter_status;
-	u32		vlan_filter_table[(BFI_MAX_VLAN + 1) / 32];
-};
-
-/* Rx object */
-struct bna_rx {
-	/* This should be the first one */
-	struct list_head			qe;
-
-	bfa_fsm_t		fsm;
-
-	enum bna_rx_type type;
-
-	/* list-head for RX path objects */
-	struct list_head			rxp_q;
-
-	struct bna_rxf rxf;
-
-	enum bna_rx_flags rx_flags;
-
-	struct bna_mbox_qe mbox_qe;
-
-	struct bfa_wc		rxq_stop_wc;
-
-	/* Rx event handlers */
-	void (*rcb_setup_cbfn)(struct bnad *, struct bna_rcb *);
-	void (*rcb_destroy_cbfn)(struct bnad *, struct bna_rcb *);
-	void (*ccb_setup_cbfn)(struct bnad *, struct bna_ccb *);
-	void (*ccb_destroy_cbfn)(struct bnad *, struct bna_ccb *);
-	void (*rx_cleanup_cbfn)(struct bnad *, struct bna_ccb *);
-	void (*rx_post_cbfn)(struct bnad *, struct bna_rcb *);
-
-	/* callback for bna_rx_disable(), bna_rx_stop() */
-	void (*stop_cbfn)(void *arg, struct bna_rx *rx,
-				enum bna_cb_status status);
-	void			*stop_cbarg;
-
-	struct bna *bna;
-	void			*priv; /* bnad's cookie */
-};
-
-struct bna_rx_event_cbfn {
-	/* Optional */
-	void (*rcb_setup_cbfn)(struct bnad *, struct bna_rcb *);
-	void (*rcb_destroy_cbfn)(struct bnad *, struct bna_rcb *);
-	void (*ccb_setup_cbfn)(struct bnad *, struct bna_ccb *);
-	void (*ccb_destroy_cbfn)(struct bnad *, struct bna_ccb *);
-	/* Mandatory */
-	void (*rx_cleanup_cbfn)(struct bnad *, struct bna_ccb *);
-	void (*rx_post_cbfn)(struct bnad *, struct bna_rcb *);
-};
-
-/* Rx module - keeps track of free, active rx objects */
-struct bna_rx_mod {
-	struct bna *bna;		/* back pointer to parent */
-	struct bna_rx *rx;		/* BFI_MAX_RXQ entries */
-	struct bna_rxp *rxp;		/* BFI_MAX_RXQ entries */
-	struct bna_rxq *rxq;		/* BFI_MAX_RXQ entries */
-
-	struct list_head			rx_free_q;
-	struct list_head			rx_active_q;
-	int			rx_free_count;
-
-	struct list_head			rxp_free_q;
-	int			rxp_free_count;
-
-	struct list_head			rxq_free_q;
-	int			rxq_free_count;
-
-	enum bna_rx_mod_flags flags;
-
-	/* callback for bna_rx_mod_stop() */
-	void (*stop_cbfn)(struct bna_port *port,
-				enum bna_cb_status status);
-
-	struct bfa_wc		rx_stop_wc;
-	u32		dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX];
-	u32		rxf_bmap[2];
-};
-
-/**
- *
- * CAM
- *
- */
-
-struct bna_ucam_mod {
-	struct bna_mac *ucmac;		/* BFI_MAX_UCMAC entries */
-	struct list_head			free_q;
-
-	struct bna *bna;
-};
-
-struct bna_mcam_mod {
-	struct bna_mac *mcmac;		/* BFI_MAX_MCMAC entries */
-	struct list_head			free_q;
-
-	struct bna *bna;
-};
-
-/**
- *
- * Statistics
- *
- */
-
-struct bna_tx_stats {
-	int			tx_state;
-	int			tx_flags;
-	int			num_txqs;
-	u32		txq_bmap[2];
-	int			txf_id;
-};
-
-struct bna_rx_stats {
-	int			rx_state;
-	int			rx_flags;
-	int			num_rxps;
-	int			num_rxqs;
-	u32		rxq_bmap[2];
-	u32		cq_bmap[2];
-	int			rxf_id;
-	int			rxf_state;
-	int			rxf_oper_state;
-	int			num_active_ucast;
-	int			num_active_mcast;
-	int			rxmode_active;
-	int			vlan_filter_status;
-	u32		vlan_filter_table[(BFI_MAX_VLAN + 1) / 32];
-	int			rss_status;
-	int			hds_status;
-};
-
-struct bna_sw_stats {
-	int			device_state;
-	int			port_state;
-	int			port_flags;
-	int			llport_state;
-	int			priority;
-	int			num_active_tx;
-	int			num_active_rx;
-	struct bna_tx_stats tx_stats[BFI_MAX_TXQ];
-	struct bna_rx_stats rx_stats[BFI_MAX_RXQ];
-};
-
-struct bna_stats {
-	u32		txf_bmap[2];
-	u32		rxf_bmap[2];
-	struct bfi_ll_stats	*hw_stats;
-	struct bna_sw_stats *sw_stats;
-};
-
-/**
- *
- * BNA
- *
- */
-
-struct bna {
-	struct bfa_pcidev pcidev;
-
-	int			port_num;
-
-	struct bna_chip_regs regs;
-
-	struct bna_dma_addr hw_stats_dma;
-	struct bna_stats stats;
-
-	struct bna_device device;
-	struct bfa_cee cee;
-
-	struct bna_mbox_mod mbox_mod;
-
-	struct bna_port port;
-
-	struct bna_tx_mod tx_mod;
-
-	struct bna_rx_mod rx_mod;
-
-	struct bna_ib_mod ib_mod;
-
-	struct bna_ucam_mod ucam_mod;
-	struct bna_mcam_mod mcam_mod;
-
-	struct bna_rit_mod rit_mod;
-
-	int			rxf_promisc_id;
-
-	struct bna_mbox_qe mbox_qe;
-
-	struct bnad *bnad;
-};
-
-#endif	/* __BNA_TYPES_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/cna_fwimg.c linux-libre-3.2-gnu/drivers/net/bna/cna_fwimg.c
--- linux-libre-3.1-gnu/drivers/net/bna/cna_fwimg.c	2012-03-19 21:42:20.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/cna_fwimg.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,64 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-#include <linux/firmware.h>
-#include "cna.h"
-
-const struct firmware *bfi_fw;
-static u32 *bfi_image_ct_cna;
-static u32 bfi_image_ct_cna_size;
-
-static u32 *
-cna_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
-			u32 *bfi_image_size, char *fw_name)
-{
-	const struct firmware *fw;
-
-	if (reject_firmware(&fw, fw_name, &pdev->dev)) {
-		pr_alert("Can't locate firmware %s\n", fw_name);
-		goto error;
-	}
-
-	*bfi_image = (u32 *)fw->data;
-	*bfi_image_size = fw->size/sizeof(u32);
-	bfi_fw = fw;
-
-	return *bfi_image;
-error:
-	return NULL;
-}
-
-u32 *
-cna_get_firmware_buf(struct pci_dev *pdev)
-{
-	if (bfi_image_ct_cna_size == 0)
-		cna_read_firmware(pdev, &bfi_image_ct_cna,
-			&bfi_image_ct_cna_size, CNA_FW_FILE_CT);
-	return bfi_image_ct_cna;
-}
-
-u32 *
-bfa_cb_image_get_chunk(int type, u32 off)
-{
-	return (u32 *)(bfi_image_ct_cna + off);
-}
-
-u32
-bfa_cb_image_get_size(int type)
-{
-	return bfi_image_ct_cna_size;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/bna/cna.h linux-libre-3.2-gnu/drivers/net/bna/cna.h
--- linux-libre-3.1-gnu/drivers/net/bna/cna.h	2012-03-19 21:42:20.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/cna.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,80 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * Copyright (c) 2006-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-#ifndef __CNA_H__
-#define __CNA_H__
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/string.h>
-
-#include <linux/list.h>
-
-#define bfa_sm_fault(__event)    do {                            \
-	pr_err("SM Assertion failure: %s: %d: event = %d", __FILE__, __LINE__, \
-		__event); \
-} while (0)
-
-extern char bfa_version[];
-
-#define	CNA_FW_FILE_CT	"/*(DEBLOBBED)*/"
-#define FC_SYMNAME_MAX	256	/*!< max name server symbolic name size */
-
-#pragma pack(1)
-
-#define MAC_ADDRLEN	(6)
-typedef struct mac { u8 mac[MAC_ADDRLEN]; } mac_t;
-
-#pragma pack()
-
-#define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next))
-#define bfa_q_next(_qe)	(((struct list_head *) (_qe))->next)
-#define bfa_q_prev(_qe) (((struct list_head *) (_qe))->prev)
-
-/*
- * bfa_q_qe_init - to initialize a queue element
- */
-#define bfa_q_qe_init(_qe) {						\
-	bfa_q_next(_qe) = (struct list_head *) NULL;			\
-	bfa_q_prev(_qe) = (struct list_head *) NULL;			\
-}
-
-/*
- * bfa_q_deq - dequeue an element from head of the queue
- */
-#define bfa_q_deq(_q, _qe) {						\
-	if (!list_empty(_q)) {						\
-		(*((struct list_head **) (_qe))) = bfa_q_next(_q);	\
-		bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) =	\
-						(struct list_head *) (_q); \
-		bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe)); \
-		bfa_q_qe_init(*((struct list_head **) _qe));		\
-	} else {							\
-		*((struct list_head **)(_qe)) = NULL;			\
-	}								\
-}
-
-#endif /* __CNA_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/bna/Makefile linux-libre-3.2-gnu/drivers/net/bna/Makefile
--- linux-libre-3.1-gnu/drivers/net/bna/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bna/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,11 +0,0 @@
-#
-# Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
-# All rights reserved.
-#
-
-obj-$(CONFIG_BNA) += bna.o
-
-bna-objs := bnad.o bnad_ethtool.o bna_ctrl.o bna_txrx.o
-bna-objs += bfa_ioc.o bfa_ioc_ct.o bfa_cee.o cna_fwimg.o
-
-EXTRA_CFLAGS := -Idrivers/net/bna
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2.c linux-libre-3.2-gnu/drivers/net/bnx2.c
--- linux-libre-3.1-gnu/drivers/net/bnx2.c	2012-03-19 21:42:38.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,8603 +0,0 @@
-/* bnx2.c: Broadcom NX2 network driver.
- *
- * 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
- * the Free Software Foundation.
- *
- * Written by: Michael Chan  (mchan@broadcom.com)
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/dma-mapping.h>
-#include <linux/bitops.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <linux/delay.h>
-#include <asm/byteorder.h>
-#include <asm/page.h>
-#include <linux/time.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-#include <linux/if_vlan.h>
-#include <net/ip.h>
-#include <net/tcp.h>
-#include <net/checksum.h>
-#include <linux/workqueue.h>
-#include <linux/crc32.h>
-#include <linux/prefetch.h>
-#include <linux/cache.h>
-#include <linux/firmware.h>
-#include <linux/log2.h>
-#include <linux/aer.h>
-
-#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
-#define BCM_CNIC 1
-#include "cnic_if.h"
-#endif
-#include "bnx2.h"
-#include "bnx2_fw.h"
-
-#define DRV_MODULE_NAME		"bnx2"
-#define DRV_MODULE_VERSION	"2.1.11"
-#define DRV_MODULE_RELDATE	"July 20, 2011"
-#define FW_MIPS_FILE_06		"/*(DEBLOBBED)*/"
-#define FW_RV2P_FILE_06		"/*(DEBLOBBED)*/"
-#define FW_MIPS_FILE_09		"/*(DEBLOBBED)*/"
-#define FW_RV2P_FILE_09_Ax	"/*(DEBLOBBED)*/"
-#define FW_RV2P_FILE_09		"/*(DEBLOBBED)*/"
-
-#define RUN_AT(x) (jiffies + (x))
-
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  (5*HZ)
-
-static char version[] __devinitdata =
-	"Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
-
-MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/5716 Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_MODULE_VERSION);
-/*(DEBLOBBED)*/
-
-static int disable_msi = 0;
-
-module_param(disable_msi, int, 0);
-MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
-
-typedef enum {
-	BCM5706 = 0,
-	NC370T,
-	NC370I,
-	BCM5706S,
-	NC370F,
-	BCM5708,
-	BCM5708S,
-	BCM5709,
-	BCM5709S,
-	BCM5716,
-	BCM5716S,
-} board_t;
-
-/* indexed by board_t, above */
-static struct {
-	char *name;
-} board_info[] __devinitdata = {
-	{ "Broadcom NetXtreme II BCM5706 1000Base-T" },
-	{ "HP NC370T Multifunction Gigabit Server Adapter" },
-	{ "HP NC370i Multifunction Gigabit Server Adapter" },
-	{ "Broadcom NetXtreme II BCM5706 1000Base-SX" },
-	{ "HP NC370F Multifunction Gigabit Server Adapter" },
-	{ "Broadcom NetXtreme II BCM5708 1000Base-T" },
-	{ "Broadcom NetXtreme II BCM5708 1000Base-SX" },
-	{ "Broadcom NetXtreme II BCM5709 1000Base-T" },
-	{ "Broadcom NetXtreme II BCM5709 1000Base-SX" },
-	{ "Broadcom NetXtreme II BCM5716 1000Base-T" },
-	{ "Broadcom NetXtreme II BCM5716 1000Base-SX" },
-	};
-
-static DEFINE_PCI_DEVICE_TABLE(bnx2_pci_tbl) = {
-	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
-	  PCI_VENDOR_ID_HP, 0x3101, 0, 0, NC370T },
-	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
-	  PCI_VENDOR_ID_HP, 0x3106, 0, 0, NC370I },
-	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706 },
-	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708 },
-	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S,
-	  PCI_VENDOR_ID_HP, 0x3102, 0, 0, NC370F },
-	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706S },
-	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708S,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708S },
-	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709 },
-	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709S,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709S },
-	{ PCI_VENDOR_ID_BROADCOM, 0x163b,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5716 },
-	{ PCI_VENDOR_ID_BROADCOM, 0x163c,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5716S },
-	{ 0, }
-};
-
-static const struct flash_spec flash_table[] =
-{
-#define BUFFERED_FLAGS		(BNX2_NV_BUFFERED | BNX2_NV_TRANSLATE)
-#define NONBUFFERED_FLAGS	(BNX2_NV_WREN)
-	/* Slow EEPROM */
-	{0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400,
-	 BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
-	 SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
-	 "EEPROM - slow"},
-	/* Expansion entry 0001 */
-	{0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406,
-	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
-	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
-	 "Entry 0001"},
-	/* Saifun SA25F010 (non-buffered flash) */
-	/* strap, cfg1, & write1 need updates */
-	{0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406,
-	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
-	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2,
-	 "Non-buffered flash (128kB)"},
-	/* Saifun SA25F020 (non-buffered flash) */
-	/* strap, cfg1, & write1 need updates */
-	{0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406,
-	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
-	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4,
-	 "Non-buffered flash (256kB)"},
-	/* Expansion entry 0100 */
-	{0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406,
-	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
-	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
-	 "Entry 0100"},
-	/* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */
-	{0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406,
-	 NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
-	 ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2,
-	 "Entry 0101: ST M45PE10 (128kB non-bufferred)"},
-	/* Entry 0110: ST M45PE20 (non-buffered flash)*/
-	{0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406,
-	 NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
-	 ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4,
-	 "Entry 0110: ST M45PE20 (256kB non-bufferred)"},
-	/* Saifun SA25F005 (non-buffered flash) */
-	/* strap, cfg1, & write1 need updates */
-	{0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406,
-	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
-	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE,
-	 "Non-buffered flash (64kB)"},
-	/* Fast EEPROM */
-	{0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400,
-	 BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
-	 SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
-	 "EEPROM - fast"},
-	/* Expansion entry 1001 */
-	{0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406,
-	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
-	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
-	 "Entry 1001"},
-	/* Expansion entry 1010 */
-	{0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406,
-	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
-	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
-	 "Entry 1010"},
-	/* ATMEL AT45DB011B (buffered flash) */
-	{0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400,
-	 BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
-	 BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE,
-	 "Buffered flash (128kB)"},
-	/* Expansion entry 1100 */
-	{0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406,
-	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
-	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
-	 "Entry 1100"},
-	/* Expansion entry 1101 */
-	{0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406,
-	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
-	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
-	 "Entry 1101"},
-	/* Ateml Expansion entry 1110 */
-	{0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400,
-	 BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
-	 BUFFERED_FLASH_BYTE_ADDR_MASK, 0,
-	 "Entry 1110 (Atmel)"},
-	/* ATMEL AT45DB021B (buffered flash) */
-	{0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400,
-	 BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
-	 BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2,
-	 "Buffered flash (256kB)"},
-};
-
-static const struct flash_spec flash_5709 = {
-	.flags		= BNX2_NV_BUFFERED,
-	.page_bits	= BCM5709_FLASH_PAGE_BITS,
-	.page_size	= BCM5709_FLASH_PAGE_SIZE,
-	.addr_mask	= BCM5709_FLASH_BYTE_ADDR_MASK,
-	.total_size	= BUFFERED_FLASH_TOTAL_SIZE*2,
-	.name		= "5709 Buffered flash (256kB)",
-};
-
-MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
-
-static void bnx2_init_napi(struct bnx2 *bp);
-static void bnx2_del_napi(struct bnx2 *bp);
-
-static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr)
-{
-	u32 diff;
-
-	/* Tell compiler to fetch tx_prod and tx_cons from memory. */
-	barrier();
-
-	/* The ring uses 256 indices for 255 entries, one of them
-	 * needs to be skipped.
-	 */
-	diff = txr->tx_prod - txr->tx_cons;
-	if (unlikely(diff >= TX_DESC_CNT)) {
-		diff &= 0xffff;
-		if (diff == TX_DESC_CNT)
-			diff = MAX_TX_DESC_CNT;
-	}
-	return bp->tx_ring_size - diff;
-}
-
-static u32
-bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset)
-{
-	u32 val;
-
-	spin_lock_bh(&bp->indirect_lock);
-	REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
-	val = REG_RD(bp, BNX2_PCICFG_REG_WINDOW);
-	spin_unlock_bh(&bp->indirect_lock);
-	return val;
-}
-
-static void
-bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val)
-{
-	spin_lock_bh(&bp->indirect_lock);
-	REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
-	REG_WR(bp, BNX2_PCICFG_REG_WINDOW, val);
-	spin_unlock_bh(&bp->indirect_lock);
-}
-
-static void
-bnx2_shmem_wr(struct bnx2 *bp, u32 offset, u32 val)
-{
-	bnx2_reg_wr_ind(bp, bp->shmem_base + offset, val);
-}
-
-static u32
-bnx2_shmem_rd(struct bnx2 *bp, u32 offset)
-{
-	return bnx2_reg_rd_ind(bp, bp->shmem_base + offset);
-}
-
-static void
-bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
-{
-	offset += cid_addr;
-	spin_lock_bh(&bp->indirect_lock);
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		int i;
-
-		REG_WR(bp, BNX2_CTX_CTX_DATA, val);
-		REG_WR(bp, BNX2_CTX_CTX_CTRL,
-		       offset | BNX2_CTX_CTX_CTRL_WRITE_REQ);
-		for (i = 0; i < 5; i++) {
-			val = REG_RD(bp, BNX2_CTX_CTX_CTRL);
-			if ((val & BNX2_CTX_CTX_CTRL_WRITE_REQ) == 0)
-				break;
-			udelay(5);
-		}
-	} else {
-		REG_WR(bp, BNX2_CTX_DATA_ADR, offset);
-		REG_WR(bp, BNX2_CTX_DATA, val);
-	}
-	spin_unlock_bh(&bp->indirect_lock);
-}
-
-#ifdef BCM_CNIC
-static int
-bnx2_drv_ctl(struct net_device *dev, struct drv_ctl_info *info)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-	struct drv_ctl_io *io = &info->data.io;
-
-	switch (info->cmd) {
-	case DRV_CTL_IO_WR_CMD:
-		bnx2_reg_wr_ind(bp, io->offset, io->data);
-		break;
-	case DRV_CTL_IO_RD_CMD:
-		io->data = bnx2_reg_rd_ind(bp, io->offset);
-		break;
-	case DRV_CTL_CTX_WR_CMD:
-		bnx2_ctx_wr(bp, io->cid_addr, io->offset, io->data);
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static void bnx2_setup_cnic_irq_info(struct bnx2 *bp)
-{
-	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
-	struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
-	int sb_id;
-
-	if (bp->flags & BNX2_FLAG_USING_MSIX) {
-		cp->drv_state |= CNIC_DRV_STATE_USING_MSIX;
-		bnapi->cnic_present = 0;
-		sb_id = bp->irq_nvecs;
-		cp->irq_arr[0].irq_flags |= CNIC_IRQ_FL_MSIX;
-	} else {
-		cp->drv_state &= ~CNIC_DRV_STATE_USING_MSIX;
-		bnapi->cnic_tag = bnapi->last_status_idx;
-		bnapi->cnic_present = 1;
-		sb_id = 0;
-		cp->irq_arr[0].irq_flags &= ~CNIC_IRQ_FL_MSIX;
-	}
-
-	cp->irq_arr[0].vector = bp->irq_tbl[sb_id].vector;
-	cp->irq_arr[0].status_blk = (void *)
-		((unsigned long) bnapi->status_blk.msi +
-		(BNX2_SBLK_MSIX_ALIGN_SIZE * sb_id));
-	cp->irq_arr[0].status_blk_num = sb_id;
-	cp->num_irq = 1;
-}
-
-static int bnx2_register_cnic(struct net_device *dev, struct cnic_ops *ops,
-			      void *data)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
-
-	if (ops == NULL)
-		return -EINVAL;
-
-	if (cp->drv_state & CNIC_DRV_STATE_REGD)
-		return -EBUSY;
-
-	if (!bnx2_reg_rd_ind(bp, BNX2_FW_MAX_ISCSI_CONN))
-		return -ENODEV;
-
-	bp->cnic_data = data;
-	rcu_assign_pointer(bp->cnic_ops, ops);
-
-	cp->num_irq = 0;
-	cp->drv_state = CNIC_DRV_STATE_REGD;
-
-	bnx2_setup_cnic_irq_info(bp);
-
-	return 0;
-}
-
-static int bnx2_unregister_cnic(struct net_device *dev)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-	struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
-	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
-
-	mutex_lock(&bp->cnic_lock);
-	cp->drv_state = 0;
-	bnapi->cnic_present = 0;
-	rcu_assign_pointer(bp->cnic_ops, NULL);
-	mutex_unlock(&bp->cnic_lock);
-	synchronize_rcu();
-	return 0;
-}
-
-struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
-
-	if (!cp->max_iscsi_conn)
-		return NULL;
-
-	cp->drv_owner = THIS_MODULE;
-	cp->chip_id = bp->chip_id;
-	cp->pdev = bp->pdev;
-	cp->io_base = bp->regview;
-	cp->drv_ctl = bnx2_drv_ctl;
-	cp->drv_register_cnic = bnx2_register_cnic;
-	cp->drv_unregister_cnic = bnx2_unregister_cnic;
-
-	return cp;
-}
-EXPORT_SYMBOL(bnx2_cnic_probe);
-
-static void
-bnx2_cnic_stop(struct bnx2 *bp)
-{
-	struct cnic_ops *c_ops;
-	struct cnic_ctl_info info;
-
-	mutex_lock(&bp->cnic_lock);
-	c_ops = 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);
-	}
-	mutex_unlock(&bp->cnic_lock);
-}
-
-static void
-bnx2_cnic_start(struct bnx2 *bp)
-{
-	struct cnic_ops *c_ops;
-	struct cnic_ctl_info info;
-
-	mutex_lock(&bp->cnic_lock);
-	c_ops = 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];
-
-			bnapi->cnic_tag = bnapi->last_status_idx;
-		}
-		info.cmd = CNIC_CTL_START_CMD;
-		c_ops->cnic_ctl(bp->cnic_data, &info);
-	}
-	mutex_unlock(&bp->cnic_lock);
-}
-
-#else
-
-static void
-bnx2_cnic_stop(struct bnx2 *bp)
-{
-}
-
-static void
-bnx2_cnic_start(struct bnx2 *bp)
-{
-}
-
-#endif
-
-static int
-bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val)
-{
-	u32 val1;
-	int i, ret;
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) {
-		val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
-		val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL;
-
-		REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
-		REG_RD(bp, BNX2_EMAC_MDIO_MODE);
-
-		udelay(40);
-	}
-
-	val1 = (bp->phy_addr << 21) | (reg << 16) |
-		BNX2_EMAC_MDIO_COMM_COMMAND_READ | BNX2_EMAC_MDIO_COMM_DISEXT |
-		BNX2_EMAC_MDIO_COMM_START_BUSY;
-	REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
-
-	for (i = 0; i < 50; i++) {
-		udelay(10);
-
-		val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
-		if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) {
-			udelay(5);
-
-			val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
-			val1 &= BNX2_EMAC_MDIO_COMM_DATA;
-
-			break;
-		}
-	}
-
-	if (val1 & BNX2_EMAC_MDIO_COMM_START_BUSY) {
-		*val = 0x0;
-		ret = -EBUSY;
-	}
-	else {
-		*val = val1;
-		ret = 0;
-	}
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) {
-		val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
-		val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL;
-
-		REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
-		REG_RD(bp, BNX2_EMAC_MDIO_MODE);
-
-		udelay(40);
-	}
-
-	return ret;
-}
-
-static int
-bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val)
-{
-	u32 val1;
-	int i, ret;
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) {
-		val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
-		val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL;
-
-		REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
-		REG_RD(bp, BNX2_EMAC_MDIO_MODE);
-
-		udelay(40);
-	}
-
-	val1 = (bp->phy_addr << 21) | (reg << 16) | val |
-		BNX2_EMAC_MDIO_COMM_COMMAND_WRITE |
-		BNX2_EMAC_MDIO_COMM_START_BUSY | BNX2_EMAC_MDIO_COMM_DISEXT;
-	REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
-
-	for (i = 0; i < 50; i++) {
-		udelay(10);
-
-		val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
-		if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) {
-			udelay(5);
-			break;
-		}
-	}
-
-	if (val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)
-        	ret = -EBUSY;
-	else
-		ret = 0;
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) {
-		val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
-		val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL;
-
-		REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
-		REG_RD(bp, BNX2_EMAC_MDIO_MODE);
-
-		udelay(40);
-	}
-
-	return ret;
-}
-
-static void
-bnx2_disable_int(struct bnx2 *bp)
-{
-	int i;
-	struct bnx2_napi *bnapi;
-
-	for (i = 0; i < bp->irq_nvecs; i++) {
-		bnapi = &bp->bnx2_napi[i];
-		REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
-		       BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
-	}
-	REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
-}
-
-static void
-bnx2_enable_int(struct bnx2 *bp)
-{
-	int i;
-	struct bnx2_napi *bnapi;
-
-	for (i = 0; i < bp->irq_nvecs; i++) {
-		bnapi = &bp->bnx2_napi[i];
-
-		REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
-		       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
-		       BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
-		       bnapi->last_status_idx);
-
-		REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
-		       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
-		       bnapi->last_status_idx);
-	}
-	REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
-}
-
-static void
-bnx2_disable_int_sync(struct bnx2 *bp)
-{
-	int i;
-
-	atomic_inc(&bp->intr_sem);
-	if (!netif_running(bp->dev))
-		return;
-
-	bnx2_disable_int(bp);
-	for (i = 0; i < bp->irq_nvecs; i++)
-		synchronize_irq(bp->irq_tbl[i].vector);
-}
-
-static void
-bnx2_napi_disable(struct bnx2 *bp)
-{
-	int i;
-
-	for (i = 0; i < bp->irq_nvecs; i++)
-		napi_disable(&bp->bnx2_napi[i].napi);
-}
-
-static void
-bnx2_napi_enable(struct bnx2 *bp)
-{
-	int i;
-
-	for (i = 0; i < bp->irq_nvecs; i++)
-		napi_enable(&bp->bnx2_napi[i].napi);
-}
-
-static void
-bnx2_netif_stop(struct bnx2 *bp, bool stop_cnic)
-{
-	if (stop_cnic)
-		bnx2_cnic_stop(bp);
-	if (netif_running(bp->dev)) {
-		bnx2_napi_disable(bp);
-		netif_tx_disable(bp->dev);
-	}
-	bnx2_disable_int_sync(bp);
-	netif_carrier_off(bp->dev);	/* prevent tx timeout */
-}
-
-static void
-bnx2_netif_start(struct bnx2 *bp, bool start_cnic)
-{
-	if (atomic_dec_and_test(&bp->intr_sem)) {
-		if (netif_running(bp->dev)) {
-			netif_tx_wake_all_queues(bp->dev);
-			spin_lock_bh(&bp->phy_lock);
-			if (bp->link_up)
-				netif_carrier_on(bp->dev);
-			spin_unlock_bh(&bp->phy_lock);
-			bnx2_napi_enable(bp);
-			bnx2_enable_int(bp);
-			if (start_cnic)
-				bnx2_cnic_start(bp);
-		}
-	}
-}
-
-static void
-bnx2_free_tx_mem(struct bnx2 *bp)
-{
-	int i;
-
-	for (i = 0; i < bp->num_tx_rings; i++) {
-		struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
-		struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
-
-		if (txr->tx_desc_ring) {
-			dma_free_coherent(&bp->pdev->dev, TXBD_RING_SIZE,
-					  txr->tx_desc_ring,
-					  txr->tx_desc_mapping);
-			txr->tx_desc_ring = NULL;
-		}
-		kfree(txr->tx_buf_ring);
-		txr->tx_buf_ring = NULL;
-	}
-}
-
-static void
-bnx2_free_rx_mem(struct bnx2 *bp)
-{
-	int i;
-
-	for (i = 0; i < bp->num_rx_rings; i++) {
-		struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
-		struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
-		int j;
-
-		for (j = 0; j < bp->rx_max_ring; j++) {
-			if (rxr->rx_desc_ring[j])
-				dma_free_coherent(&bp->pdev->dev, RXBD_RING_SIZE,
-						  rxr->rx_desc_ring[j],
-						  rxr->rx_desc_mapping[j]);
-			rxr->rx_desc_ring[j] = NULL;
-		}
-		vfree(rxr->rx_buf_ring);
-		rxr->rx_buf_ring = NULL;
-
-		for (j = 0; j < bp->rx_max_pg_ring; j++) {
-			if (rxr->rx_pg_desc_ring[j])
-				dma_free_coherent(&bp->pdev->dev, RXBD_RING_SIZE,
-						  rxr->rx_pg_desc_ring[j],
-						  rxr->rx_pg_desc_mapping[j]);
-			rxr->rx_pg_desc_ring[j] = NULL;
-		}
-		vfree(rxr->rx_pg_ring);
-		rxr->rx_pg_ring = NULL;
-	}
-}
-
-static int
-bnx2_alloc_tx_mem(struct bnx2 *bp)
-{
-	int i;
-
-	for (i = 0; i < bp->num_tx_rings; i++) {
-		struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
-		struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
-
-		txr->tx_buf_ring = kzalloc(SW_TXBD_RING_SIZE, GFP_KERNEL);
-		if (txr->tx_buf_ring == NULL)
-			return -ENOMEM;
-
-		txr->tx_desc_ring =
-			dma_alloc_coherent(&bp->pdev->dev, TXBD_RING_SIZE,
-					   &txr->tx_desc_mapping, GFP_KERNEL);
-		if (txr->tx_desc_ring == NULL)
-			return -ENOMEM;
-	}
-	return 0;
-}
-
-static int
-bnx2_alloc_rx_mem(struct bnx2 *bp)
-{
-	int i;
-
-	for (i = 0; i < bp->num_rx_rings; i++) {
-		struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
-		struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
-		int j;
-
-		rxr->rx_buf_ring =
-			vzalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring);
-		if (rxr->rx_buf_ring == NULL)
-			return -ENOMEM;
-
-		for (j = 0; j < bp->rx_max_ring; j++) {
-			rxr->rx_desc_ring[j] =
-				dma_alloc_coherent(&bp->pdev->dev,
-						   RXBD_RING_SIZE,
-						   &rxr->rx_desc_mapping[j],
-						   GFP_KERNEL);
-			if (rxr->rx_desc_ring[j] == NULL)
-				return -ENOMEM;
-
-		}
-
-		if (bp->rx_pg_ring_size) {
-			rxr->rx_pg_ring = vzalloc(SW_RXPG_RING_SIZE *
-						  bp->rx_max_pg_ring);
-			if (rxr->rx_pg_ring == NULL)
-				return -ENOMEM;
-
-		}
-
-		for (j = 0; j < bp->rx_max_pg_ring; j++) {
-			rxr->rx_pg_desc_ring[j] =
-				dma_alloc_coherent(&bp->pdev->dev,
-						   RXBD_RING_SIZE,
-						   &rxr->rx_pg_desc_mapping[j],
-						   GFP_KERNEL);
-			if (rxr->rx_pg_desc_ring[j] == NULL)
-				return -ENOMEM;
-
-		}
-	}
-	return 0;
-}
-
-static void
-bnx2_free_mem(struct bnx2 *bp)
-{
-	int i;
-	struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
-
-	bnx2_free_tx_mem(bp);
-	bnx2_free_rx_mem(bp);
-
-	for (i = 0; i < bp->ctx_pages; i++) {
-		if (bp->ctx_blk[i]) {
-			dma_free_coherent(&bp->pdev->dev, BCM_PAGE_SIZE,
-					  bp->ctx_blk[i],
-					  bp->ctx_blk_mapping[i]);
-			bp->ctx_blk[i] = NULL;
-		}
-	}
-	if (bnapi->status_blk.msi) {
-		dma_free_coherent(&bp->pdev->dev, bp->status_stats_size,
-				  bnapi->status_blk.msi,
-				  bp->status_blk_mapping);
-		bnapi->status_blk.msi = NULL;
-		bp->stats_blk = NULL;
-	}
-}
-
-static int
-bnx2_alloc_mem(struct bnx2 *bp)
-{
-	int i, status_blk_size, err;
-	struct bnx2_napi *bnapi;
-	void *status_blk;
-
-	/* Combine status and statistics blocks into one allocation. */
-	status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block));
-	if (bp->flags & BNX2_FLAG_MSIX_CAP)
-		status_blk_size = L1_CACHE_ALIGN(BNX2_MAX_MSIX_HW_VEC *
-						 BNX2_SBLK_MSIX_ALIGN_SIZE);
-	bp->status_stats_size = status_blk_size +
-				sizeof(struct statistics_block);
-
-	status_blk = dma_alloc_coherent(&bp->pdev->dev, bp->status_stats_size,
-					&bp->status_blk_mapping, GFP_KERNEL);
-	if (status_blk == NULL)
-		goto alloc_mem_err;
-
-	memset(status_blk, 0, bp->status_stats_size);
-
-	bnapi = &bp->bnx2_napi[0];
-	bnapi->status_blk.msi = status_blk;
-	bnapi->hw_tx_cons_ptr =
-		&bnapi->status_blk.msi->status_tx_quick_consumer_index0;
-	bnapi->hw_rx_cons_ptr =
-		&bnapi->status_blk.msi->status_rx_quick_consumer_index0;
-	if (bp->flags & BNX2_FLAG_MSIX_CAP) {
-		for (i = 1; i < bp->irq_nvecs; i++) {
-			struct status_block_msix *sblk;
-
-			bnapi = &bp->bnx2_napi[i];
-
-			sblk = (void *) (status_blk +
-					 BNX2_SBLK_MSIX_ALIGN_SIZE * i);
-			bnapi->status_blk.msix = sblk;
-			bnapi->hw_tx_cons_ptr =
-				&sblk->status_tx_quick_consumer_index;
-			bnapi->hw_rx_cons_ptr =
-				&sblk->status_rx_quick_consumer_index;
-			bnapi->int_num = i << 24;
-		}
-	}
-
-	bp->stats_blk = status_blk + status_blk_size;
-
-	bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size;
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		bp->ctx_pages = 0x2000 / BCM_PAGE_SIZE;
-		if (bp->ctx_pages == 0)
-			bp->ctx_pages = 1;
-		for (i = 0; i < bp->ctx_pages; i++) {
-			bp->ctx_blk[i] = dma_alloc_coherent(&bp->pdev->dev,
-						BCM_PAGE_SIZE,
-						&bp->ctx_blk_mapping[i],
-						GFP_KERNEL);
-			if (bp->ctx_blk[i] == NULL)
-				goto alloc_mem_err;
-		}
-	}
-
-	err = bnx2_alloc_rx_mem(bp);
-	if (err)
-		goto alloc_mem_err;
-
-	err = bnx2_alloc_tx_mem(bp);
-	if (err)
-		goto alloc_mem_err;
-
-	return 0;
-
-alloc_mem_err:
-	bnx2_free_mem(bp);
-	return -ENOMEM;
-}
-
-static void
-bnx2_report_fw_link(struct bnx2 *bp)
-{
-	u32 fw_link_status = 0;
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
-		return;
-
-	if (bp->link_up) {
-		u32 bmsr;
-
-		switch (bp->line_speed) {
-		case SPEED_10:
-			if (bp->duplex == DUPLEX_HALF)
-				fw_link_status = BNX2_LINK_STATUS_10HALF;
-			else
-				fw_link_status = BNX2_LINK_STATUS_10FULL;
-			break;
-		case SPEED_100:
-			if (bp->duplex == DUPLEX_HALF)
-				fw_link_status = BNX2_LINK_STATUS_100HALF;
-			else
-				fw_link_status = BNX2_LINK_STATUS_100FULL;
-			break;
-		case SPEED_1000:
-			if (bp->duplex == DUPLEX_HALF)
-				fw_link_status = BNX2_LINK_STATUS_1000HALF;
-			else
-				fw_link_status = BNX2_LINK_STATUS_1000FULL;
-			break;
-		case SPEED_2500:
-			if (bp->duplex == DUPLEX_HALF)
-				fw_link_status = BNX2_LINK_STATUS_2500HALF;
-			else
-				fw_link_status = BNX2_LINK_STATUS_2500FULL;
-			break;
-		}
-
-		fw_link_status |= BNX2_LINK_STATUS_LINK_UP;
-
-		if (bp->autoneg) {
-			fw_link_status |= BNX2_LINK_STATUS_AN_ENABLED;
-
-			bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
-			bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
-
-			if (!(bmsr & BMSR_ANEGCOMPLETE) ||
-			    bp->phy_flags & BNX2_PHY_FLAG_PARALLEL_DETECT)
-				fw_link_status |= BNX2_LINK_STATUS_PARALLEL_DET;
-			else
-				fw_link_status |= BNX2_LINK_STATUS_AN_COMPLETE;
-		}
-	}
-	else
-		fw_link_status = BNX2_LINK_STATUS_LINK_DOWN;
-
-	bnx2_shmem_wr(bp, BNX2_LINK_STATUS, fw_link_status);
-}
-
-static char *
-bnx2_xceiver_str(struct bnx2 *bp)
-{
-	return (bp->phy_port == PORT_FIBRE) ? "SerDes" :
-		((bp->phy_flags & BNX2_PHY_FLAG_SERDES) ? "Remote Copper" :
-		 "Copper");
-}
-
-static void
-bnx2_report_link(struct bnx2 *bp)
-{
-	if (bp->link_up) {
-		netif_carrier_on(bp->dev);
-		netdev_info(bp->dev, "NIC %s Link is Up, %d Mbps %s duplex",
-			    bnx2_xceiver_str(bp),
-			    bp->line_speed,
-			    bp->duplex == DUPLEX_FULL ? "full" : "half");
-
-		if (bp->flow_ctrl) {
-			if (bp->flow_ctrl & FLOW_CTRL_RX) {
-				pr_cont(", receive ");
-				if (bp->flow_ctrl & FLOW_CTRL_TX)
-					pr_cont("& transmit ");
-			}
-			else {
-				pr_cont(", transmit ");
-			}
-			pr_cont("flow control ON");
-		}
-		pr_cont("\n");
-	} else {
-		netif_carrier_off(bp->dev);
-		netdev_err(bp->dev, "NIC %s Link is Down\n",
-			   bnx2_xceiver_str(bp));
-	}
-
-	bnx2_report_fw_link(bp);
-}
-
-static void
-bnx2_resolve_flow_ctrl(struct bnx2 *bp)
-{
-	u32 local_adv, remote_adv;
-
-	bp->flow_ctrl = 0;
-	if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) !=
-		(AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) {
-
-		if (bp->duplex == DUPLEX_FULL) {
-			bp->flow_ctrl = bp->req_flow_ctrl;
-		}
-		return;
-	}
-
-	if (bp->duplex != DUPLEX_FULL) {
-		return;
-	}
-
-	if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
-	    (CHIP_NUM(bp) == CHIP_NUM_5708)) {
-		u32 val;
-
-		bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val);
-		if (val & BCM5708S_1000X_STAT1_TX_PAUSE)
-			bp->flow_ctrl |= FLOW_CTRL_TX;
-		if (val & BCM5708S_1000X_STAT1_RX_PAUSE)
-			bp->flow_ctrl |= FLOW_CTRL_RX;
-		return;
-	}
-
-	bnx2_read_phy(bp, bp->mii_adv, &local_adv);
-	bnx2_read_phy(bp, bp->mii_lpa, &remote_adv);
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
-		u32 new_local_adv = 0;
-		u32 new_remote_adv = 0;
-
-		if (local_adv & ADVERTISE_1000XPAUSE)
-			new_local_adv |= ADVERTISE_PAUSE_CAP;
-		if (local_adv & ADVERTISE_1000XPSE_ASYM)
-			new_local_adv |= ADVERTISE_PAUSE_ASYM;
-		if (remote_adv & ADVERTISE_1000XPAUSE)
-			new_remote_adv |= ADVERTISE_PAUSE_CAP;
-		if (remote_adv & ADVERTISE_1000XPSE_ASYM)
-			new_remote_adv |= ADVERTISE_PAUSE_ASYM;
-
-		local_adv = new_local_adv;
-		remote_adv = new_remote_adv;
-	}
-
-	/* See Table 28B-3 of 802.3ab-1999 spec. */
-	if (local_adv & ADVERTISE_PAUSE_CAP) {
-		if(local_adv & ADVERTISE_PAUSE_ASYM) {
-	                if (remote_adv & ADVERTISE_PAUSE_CAP) {
-				bp->flow_ctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
-			}
-			else if (remote_adv & ADVERTISE_PAUSE_ASYM) {
-				bp->flow_ctrl = FLOW_CTRL_RX;
-			}
-		}
-		else {
-			if (remote_adv & ADVERTISE_PAUSE_CAP) {
-				bp->flow_ctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
-			}
-		}
-	}
-	else if (local_adv & ADVERTISE_PAUSE_ASYM) {
-		if ((remote_adv & ADVERTISE_PAUSE_CAP) &&
-			(remote_adv & ADVERTISE_PAUSE_ASYM)) {
-
-			bp->flow_ctrl = FLOW_CTRL_TX;
-		}
-	}
-}
-
-static int
-bnx2_5709s_linkup(struct bnx2 *bp)
-{
-	u32 val, speed;
-
-	bp->link_up = 1;
-
-	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_GP_STATUS);
-	bnx2_read_phy(bp, MII_BNX2_GP_TOP_AN_STATUS1, &val);
-	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
-
-	if ((bp->autoneg & AUTONEG_SPEED) == 0) {
-		bp->line_speed = bp->req_line_speed;
-		bp->duplex = bp->req_duplex;
-		return 0;
-	}
-	speed = val & MII_BNX2_GP_TOP_AN_SPEED_MSK;
-	switch (speed) {
-		case MII_BNX2_GP_TOP_AN_SPEED_10:
-			bp->line_speed = SPEED_10;
-			break;
-		case MII_BNX2_GP_TOP_AN_SPEED_100:
-			bp->line_speed = SPEED_100;
-			break;
-		case MII_BNX2_GP_TOP_AN_SPEED_1G:
-		case MII_BNX2_GP_TOP_AN_SPEED_1GKV:
-			bp->line_speed = SPEED_1000;
-			break;
-		case MII_BNX2_GP_TOP_AN_SPEED_2_5G:
-			bp->line_speed = SPEED_2500;
-			break;
-	}
-	if (val & MII_BNX2_GP_TOP_AN_FD)
-		bp->duplex = DUPLEX_FULL;
-	else
-		bp->duplex = DUPLEX_HALF;
-	return 0;
-}
-
-static int
-bnx2_5708s_linkup(struct bnx2 *bp)
-{
-	u32 val;
-
-	bp->link_up = 1;
-	bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val);
-	switch (val & BCM5708S_1000X_STAT1_SPEED_MASK) {
-		case BCM5708S_1000X_STAT1_SPEED_10:
-			bp->line_speed = SPEED_10;
-			break;
-		case BCM5708S_1000X_STAT1_SPEED_100:
-			bp->line_speed = SPEED_100;
-			break;
-		case BCM5708S_1000X_STAT1_SPEED_1G:
-			bp->line_speed = SPEED_1000;
-			break;
-		case BCM5708S_1000X_STAT1_SPEED_2G5:
-			bp->line_speed = SPEED_2500;
-			break;
-	}
-	if (val & BCM5708S_1000X_STAT1_FD)
-		bp->duplex = DUPLEX_FULL;
-	else
-		bp->duplex = DUPLEX_HALF;
-
-	return 0;
-}
-
-static int
-bnx2_5706s_linkup(struct bnx2 *bp)
-{
-	u32 bmcr, local_adv, remote_adv, common;
-
-	bp->link_up = 1;
-	bp->line_speed = SPEED_1000;
-
-	bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
-	if (bmcr & BMCR_FULLDPLX) {
-		bp->duplex = DUPLEX_FULL;
-	}
-	else {
-		bp->duplex = DUPLEX_HALF;
-	}
-
-	if (!(bmcr & BMCR_ANENABLE)) {
-		return 0;
-	}
-
-	bnx2_read_phy(bp, bp->mii_adv, &local_adv);
-	bnx2_read_phy(bp, bp->mii_lpa, &remote_adv);
-
-	common = local_adv & remote_adv;
-	if (common & (ADVERTISE_1000XHALF | ADVERTISE_1000XFULL)) {
-
-		if (common & ADVERTISE_1000XFULL) {
-			bp->duplex = DUPLEX_FULL;
-		}
-		else {
-			bp->duplex = DUPLEX_HALF;
-		}
-	}
-
-	return 0;
-}
-
-static int
-bnx2_copper_linkup(struct bnx2 *bp)
-{
-	u32 bmcr;
-
-	bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
-	if (bmcr & BMCR_ANENABLE) {
-		u32 local_adv, remote_adv, common;
-
-		bnx2_read_phy(bp, MII_CTRL1000, &local_adv);
-		bnx2_read_phy(bp, MII_STAT1000, &remote_adv);
-
-		common = local_adv & (remote_adv >> 2);
-		if (common & ADVERTISE_1000FULL) {
-			bp->line_speed = SPEED_1000;
-			bp->duplex = DUPLEX_FULL;
-		}
-		else if (common & ADVERTISE_1000HALF) {
-			bp->line_speed = SPEED_1000;
-			bp->duplex = DUPLEX_HALF;
-		}
-		else {
-			bnx2_read_phy(bp, bp->mii_adv, &local_adv);
-			bnx2_read_phy(bp, bp->mii_lpa, &remote_adv);
-
-			common = local_adv & remote_adv;
-			if (common & ADVERTISE_100FULL) {
-				bp->line_speed = SPEED_100;
-				bp->duplex = DUPLEX_FULL;
-			}
-			else if (common & ADVERTISE_100HALF) {
-				bp->line_speed = SPEED_100;
-				bp->duplex = DUPLEX_HALF;
-			}
-			else if (common & ADVERTISE_10FULL) {
-				bp->line_speed = SPEED_10;
-				bp->duplex = DUPLEX_FULL;
-			}
-			else if (common & ADVERTISE_10HALF) {
-				bp->line_speed = SPEED_10;
-				bp->duplex = DUPLEX_HALF;
-			}
-			else {
-				bp->line_speed = 0;
-				bp->link_up = 0;
-			}
-		}
-	}
-	else {
-		if (bmcr & BMCR_SPEED100) {
-			bp->line_speed = SPEED_100;
-		}
-		else {
-			bp->line_speed = SPEED_10;
-		}
-		if (bmcr & BMCR_FULLDPLX) {
-			bp->duplex = DUPLEX_FULL;
-		}
-		else {
-			bp->duplex = DUPLEX_HALF;
-		}
-	}
-
-	return 0;
-}
-
-static void
-bnx2_init_rx_context(struct bnx2 *bp, u32 cid)
-{
-	u32 val, rx_cid_addr = GET_CID_ADDR(cid);
-
-	val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
-	val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2;
-	val |= 0x02 << 8;
-
-	if (bp->flow_ctrl & FLOW_CTRL_TX)
-		val |= BNX2_L2CTX_FLOW_CTRL_ENABLE;
-
-	bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_CTX_TYPE, val);
-}
-
-static void
-bnx2_init_all_rx_contexts(struct bnx2 *bp)
-{
-	int i;
-	u32 cid;
-
-	for (i = 0, cid = RX_CID; i < bp->num_rx_rings; i++, cid++) {
-		if (i == 1)
-			cid = RX_RSS_CID;
-		bnx2_init_rx_context(bp, cid);
-	}
-}
-
-static void
-bnx2_set_mac_link(struct bnx2 *bp)
-{
-	u32 val;
-
-	REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x2620);
-	if (bp->link_up && (bp->line_speed == SPEED_1000) &&
-		(bp->duplex == DUPLEX_HALF)) {
-		REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x26ff);
-	}
-
-	/* Configure the EMAC mode register. */
-	val = REG_RD(bp, BNX2_EMAC_MODE);
-
-	val &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX |
-		BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK |
-		BNX2_EMAC_MODE_25G_MODE);
-
-	if (bp->link_up) {
-		switch (bp->line_speed) {
-			case SPEED_10:
-				if (CHIP_NUM(bp) != CHIP_NUM_5706) {
-					val |= BNX2_EMAC_MODE_PORT_MII_10M;
-					break;
-				}
-				/* fall through */
-			case SPEED_100:
-				val |= BNX2_EMAC_MODE_PORT_MII;
-				break;
-			case SPEED_2500:
-				val |= BNX2_EMAC_MODE_25G_MODE;
-				/* fall through */
-			case SPEED_1000:
-				val |= BNX2_EMAC_MODE_PORT_GMII;
-				break;
-		}
-	}
-	else {
-		val |= BNX2_EMAC_MODE_PORT_GMII;
-	}
-
-	/* Set the MAC to operate in the appropriate duplex mode. */
-	if (bp->duplex == DUPLEX_HALF)
-		val |= BNX2_EMAC_MODE_HALF_DUPLEX;
-	REG_WR(bp, BNX2_EMAC_MODE, val);
-
-	/* Enable/disable rx PAUSE. */
-	bp->rx_mode &= ~BNX2_EMAC_RX_MODE_FLOW_EN;
-
-	if (bp->flow_ctrl & FLOW_CTRL_RX)
-		bp->rx_mode |= BNX2_EMAC_RX_MODE_FLOW_EN;
-	REG_WR(bp, BNX2_EMAC_RX_MODE, bp->rx_mode);
-
-	/* Enable/disable tx PAUSE. */
-	val = REG_RD(bp, BNX2_EMAC_TX_MODE);
-	val &= ~BNX2_EMAC_TX_MODE_FLOW_EN;
-
-	if (bp->flow_ctrl & FLOW_CTRL_TX)
-		val |= BNX2_EMAC_TX_MODE_FLOW_EN;
-	REG_WR(bp, BNX2_EMAC_TX_MODE, val);
-
-	/* Acknowledge the interrupt. */
-	REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
-
-	bnx2_init_all_rx_contexts(bp);
-}
-
-static void
-bnx2_enable_bmsr1(struct bnx2 *bp)
-{
-	if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
-	    (CHIP_NUM(bp) == CHIP_NUM_5709))
-		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
-			       MII_BNX2_BLK_ADDR_GP_STATUS);
-}
-
-static void
-bnx2_disable_bmsr1(struct bnx2 *bp)
-{
-	if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
-	    (CHIP_NUM(bp) == CHIP_NUM_5709))
-		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
-			       MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
-}
-
-static int
-bnx2_test_and_enable_2g5(struct bnx2 *bp)
-{
-	u32 up1;
-	int ret = 1;
-
-	if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
-		return 0;
-
-	if (bp->autoneg & AUTONEG_SPEED)
-		bp->advertising |= ADVERTISED_2500baseX_Full;
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G);
-
-	bnx2_read_phy(bp, bp->mii_up1, &up1);
-	if (!(up1 & BCM5708S_UP1_2G5)) {
-		up1 |= BCM5708S_UP1_2G5;
-		bnx2_write_phy(bp, bp->mii_up1, up1);
-		ret = 0;
-	}
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
-			       MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
-
-	return ret;
-}
-
-static int
-bnx2_test_and_disable_2g5(struct bnx2 *bp)
-{
-	u32 up1;
-	int ret = 0;
-
-	if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
-		return 0;
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G);
-
-	bnx2_read_phy(bp, bp->mii_up1, &up1);
-	if (up1 & BCM5708S_UP1_2G5) {
-		up1 &= ~BCM5708S_UP1_2G5;
-		bnx2_write_phy(bp, bp->mii_up1, up1);
-		ret = 1;
-	}
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
-			       MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
-
-	return ret;
-}
-
-static void
-bnx2_enable_forced_2g5(struct bnx2 *bp)
-{
-	u32 uninitialized_var(bmcr);
-	int err;
-
-	if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
-		return;
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		u32 val;
-
-		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
-			       MII_BNX2_BLK_ADDR_SERDES_DIG);
-		if (!bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val)) {
-			val &= ~MII_BNX2_SD_MISC1_FORCE_MSK;
-			val |= MII_BNX2_SD_MISC1_FORCE |
-				MII_BNX2_SD_MISC1_FORCE_2_5G;
-			bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val);
-		}
-
-		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
-			       MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
-		err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
-
-	} else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
-		err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
-		if (!err)
-			bmcr |= BCM5708S_BMCR_FORCE_2500;
-	} else {
-		return;
-	}
-
-	if (err)
-		return;
-
-	if (bp->autoneg & AUTONEG_SPEED) {
-		bmcr &= ~BMCR_ANENABLE;
-		if (bp->req_duplex == DUPLEX_FULL)
-			bmcr |= BMCR_FULLDPLX;
-	}
-	bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
-}
-
-static void
-bnx2_disable_forced_2g5(struct bnx2 *bp)
-{
-	u32 uninitialized_var(bmcr);
-	int err;
-
-	if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
-		return;
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		u32 val;
-
-		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
-			       MII_BNX2_BLK_ADDR_SERDES_DIG);
-		if (!bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val)) {
-			val &= ~MII_BNX2_SD_MISC1_FORCE;
-			bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val);
-		}
-
-		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
-			       MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
-		err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
-
-	} else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
-		err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
-		if (!err)
-			bmcr &= ~BCM5708S_BMCR_FORCE_2500;
-	} else {
-		return;
-	}
-
-	if (err)
-		return;
-
-	if (bp->autoneg & AUTONEG_SPEED)
-		bmcr |= BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_ANRESTART;
-	bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
-}
-
-static void
-bnx2_5706s_force_link_dn(struct bnx2 *bp, int start)
-{
-	u32 val;
-
-	bnx2_write_phy(bp, MII_BNX2_DSP_ADDRESS, MII_EXPAND_SERDES_CTL);
-	bnx2_read_phy(bp, MII_BNX2_DSP_RW_PORT, &val);
-	if (start)
-		bnx2_write_phy(bp, MII_BNX2_DSP_RW_PORT, val & 0xff0f);
-	else
-		bnx2_write_phy(bp, MII_BNX2_DSP_RW_PORT, val | 0xc0);
-}
-
-static int
-bnx2_set_link(struct bnx2 *bp)
-{
-	u32 bmsr;
-	u8 link_up;
-
-	if (bp->loopback == MAC_LOOPBACK || bp->loopback == PHY_LOOPBACK) {
-		bp->link_up = 1;
-		return 0;
-	}
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
-		return 0;
-
-	link_up = bp->link_up;
-
-	bnx2_enable_bmsr1(bp);
-	bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
-	bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
-	bnx2_disable_bmsr1(bp);
-
-	if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
-	    (CHIP_NUM(bp) == CHIP_NUM_5706)) {
-		u32 val, an_dbg;
-
-		if (bp->phy_flags & BNX2_PHY_FLAG_FORCED_DOWN) {
-			bnx2_5706s_force_link_dn(bp, 0);
-			bp->phy_flags &= ~BNX2_PHY_FLAG_FORCED_DOWN;
-		}
-		val = REG_RD(bp, BNX2_EMAC_STATUS);
-
-		bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_AN_DBG);
-		bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg);
-		bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg);
-
-		if ((val & BNX2_EMAC_STATUS_LINK) &&
-		    !(an_dbg & MISC_SHDW_AN_DBG_NOSYNC))
-			bmsr |= BMSR_LSTATUS;
-		else
-			bmsr &= ~BMSR_LSTATUS;
-	}
-
-	if (bmsr & BMSR_LSTATUS) {
-		bp->link_up = 1;
-
-		if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
-			if (CHIP_NUM(bp) == CHIP_NUM_5706)
-				bnx2_5706s_linkup(bp);
-			else if (CHIP_NUM(bp) == CHIP_NUM_5708)
-				bnx2_5708s_linkup(bp);
-			else if (CHIP_NUM(bp) == CHIP_NUM_5709)
-				bnx2_5709s_linkup(bp);
-		}
-		else {
-			bnx2_copper_linkup(bp);
-		}
-		bnx2_resolve_flow_ctrl(bp);
-	}
-	else {
-		if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
-		    (bp->autoneg & AUTONEG_SPEED))
-			bnx2_disable_forced_2g5(bp);
-
-		if (bp->phy_flags & BNX2_PHY_FLAG_PARALLEL_DETECT) {
-			u32 bmcr;
-
-			bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
-			bmcr |= BMCR_ANENABLE;
-			bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
-
-			bp->phy_flags &= ~BNX2_PHY_FLAG_PARALLEL_DETECT;
-		}
-		bp->link_up = 0;
-	}
-
-	if (bp->link_up != link_up) {
-		bnx2_report_link(bp);
-	}
-
-	bnx2_set_mac_link(bp);
-
-	return 0;
-}
-
-static int
-bnx2_reset_phy(struct bnx2 *bp)
-{
-	int i;
-	u32 reg;
-
-        bnx2_write_phy(bp, bp->mii_bmcr, BMCR_RESET);
-
-#define PHY_RESET_MAX_WAIT 100
-	for (i = 0; i < PHY_RESET_MAX_WAIT; i++) {
-		udelay(10);
-
-		bnx2_read_phy(bp, bp->mii_bmcr, &reg);
-		if (!(reg & BMCR_RESET)) {
-			udelay(20);
-			break;
-		}
-	}
-	if (i == PHY_RESET_MAX_WAIT) {
-		return -EBUSY;
-	}
-	return 0;
-}
-
-static u32
-bnx2_phy_get_pause_adv(struct bnx2 *bp)
-{
-	u32 adv = 0;
-
-	if ((bp->req_flow_ctrl & (FLOW_CTRL_RX | FLOW_CTRL_TX)) ==
-		(FLOW_CTRL_RX | FLOW_CTRL_TX)) {
-
-		if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
-			adv = ADVERTISE_1000XPAUSE;
-		}
-		else {
-			adv = ADVERTISE_PAUSE_CAP;
-		}
-	}
-	else if (bp->req_flow_ctrl & FLOW_CTRL_TX) {
-		if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
-			adv = ADVERTISE_1000XPSE_ASYM;
-		}
-		else {
-			adv = ADVERTISE_PAUSE_ASYM;
-		}
-	}
-	else if (bp->req_flow_ctrl & FLOW_CTRL_RX) {
-		if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
-			adv = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
-		}
-		else {
-			adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
-		}
-	}
-	return adv;
-}
-
-static int bnx2_fw_sync(struct bnx2 *, u32, int, int);
-
-static int
-bnx2_setup_remote_phy(struct bnx2 *bp, u8 port)
-__releases(&bp->phy_lock)
-__acquires(&bp->phy_lock)
-{
-	u32 speed_arg = 0, pause_adv;
-
-	pause_adv = bnx2_phy_get_pause_adv(bp);
-
-	if (bp->autoneg & AUTONEG_SPEED) {
-		speed_arg |= BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG;
-		if (bp->advertising & ADVERTISED_10baseT_Half)
-			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10HALF;
-		if (bp->advertising & ADVERTISED_10baseT_Full)
-			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10FULL;
-		if (bp->advertising & ADVERTISED_100baseT_Half)
-			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100HALF;
-		if (bp->advertising & ADVERTISED_100baseT_Full)
-			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100FULL;
-		if (bp->advertising & ADVERTISED_1000baseT_Full)
-			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_1GFULL;
-		if (bp->advertising & ADVERTISED_2500baseX_Full)
-			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_2G5FULL;
-	} else {
-		if (bp->req_line_speed == SPEED_2500)
-			speed_arg = BNX2_NETLINK_SET_LINK_SPEED_2G5FULL;
-		else if (bp->req_line_speed == SPEED_1000)
-			speed_arg = BNX2_NETLINK_SET_LINK_SPEED_1GFULL;
-		else if (bp->req_line_speed == SPEED_100) {
-			if (bp->req_duplex == DUPLEX_FULL)
-				speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100FULL;
-			else
-				speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100HALF;
-		} else if (bp->req_line_speed == SPEED_10) {
-			if (bp->req_duplex == DUPLEX_FULL)
-				speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10FULL;
-			else
-				speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10HALF;
-		}
-	}
-
-	if (pause_adv & (ADVERTISE_1000XPAUSE | ADVERTISE_PAUSE_CAP))
-		speed_arg |= BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE;
-	if (pause_adv & (ADVERTISE_1000XPSE_ASYM | ADVERTISE_PAUSE_ASYM))
-		speed_arg |= BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE;
-
-	if (port == PORT_TP)
-		speed_arg |= BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE |
-			     BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED;
-
-	bnx2_shmem_wr(bp, BNX2_DRV_MB_ARG0, speed_arg);
-
-	spin_unlock_bh(&bp->phy_lock);
-	bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_CMD_SET_LINK, 1, 0);
-	spin_lock_bh(&bp->phy_lock);
-
-	return 0;
-}
-
-static int
-bnx2_setup_serdes_phy(struct bnx2 *bp, u8 port)
-__releases(&bp->phy_lock)
-__acquires(&bp->phy_lock)
-{
-	u32 adv, bmcr;
-	u32 new_adv = 0;
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
-		return bnx2_setup_remote_phy(bp, port);
-
-	if (!(bp->autoneg & AUTONEG_SPEED)) {
-		u32 new_bmcr;
-		int force_link_down = 0;
-
-		if (bp->req_line_speed == SPEED_2500) {
-			if (!bnx2_test_and_enable_2g5(bp))
-				force_link_down = 1;
-		} else if (bp->req_line_speed == SPEED_1000) {
-			if (bnx2_test_and_disable_2g5(bp))
-				force_link_down = 1;
-		}
-		bnx2_read_phy(bp, bp->mii_adv, &adv);
-		adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF);
-
-		bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
-		new_bmcr = bmcr & ~BMCR_ANENABLE;
-		new_bmcr |= BMCR_SPEED1000;
-
-		if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-			if (bp->req_line_speed == SPEED_2500)
-				bnx2_enable_forced_2g5(bp);
-			else if (bp->req_line_speed == SPEED_1000) {
-				bnx2_disable_forced_2g5(bp);
-				new_bmcr &= ~0x2000;
-			}
-
-		} else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
-			if (bp->req_line_speed == SPEED_2500)
-				new_bmcr |= BCM5708S_BMCR_FORCE_2500;
-			else
-				new_bmcr = bmcr & ~BCM5708S_BMCR_FORCE_2500;
-		}
-
-		if (bp->req_duplex == DUPLEX_FULL) {
-			adv |= ADVERTISE_1000XFULL;
-			new_bmcr |= BMCR_FULLDPLX;
-		}
-		else {
-			adv |= ADVERTISE_1000XHALF;
-			new_bmcr &= ~BMCR_FULLDPLX;
-		}
-		if ((new_bmcr != bmcr) || (force_link_down)) {
-			/* Force a link down visible on the other side */
-			if (bp->link_up) {
-				bnx2_write_phy(bp, bp->mii_adv, adv &
-					       ~(ADVERTISE_1000XFULL |
-						 ADVERTISE_1000XHALF));
-				bnx2_write_phy(bp, bp->mii_bmcr, bmcr |
-					BMCR_ANRESTART | BMCR_ANENABLE);
-
-				bp->link_up = 0;
-				netif_carrier_off(bp->dev);
-				bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr);
-				bnx2_report_link(bp);
-			}
-			bnx2_write_phy(bp, bp->mii_adv, adv);
-			bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr);
-		} else {
-			bnx2_resolve_flow_ctrl(bp);
-			bnx2_set_mac_link(bp);
-		}
-		return 0;
-	}
-
-	bnx2_test_and_enable_2g5(bp);
-
-	if (bp->advertising & ADVERTISED_1000baseT_Full)
-		new_adv |= ADVERTISE_1000XFULL;
-
-	new_adv |= bnx2_phy_get_pause_adv(bp);
-
-	bnx2_read_phy(bp, bp->mii_adv, &adv);
-	bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
-
-	bp->serdes_an_pending = 0;
-	if ((adv != new_adv) || ((bmcr & BMCR_ANENABLE) == 0)) {
-		/* Force a link down visible on the other side */
-		if (bp->link_up) {
-			bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK);
-			spin_unlock_bh(&bp->phy_lock);
-			msleep(20);
-			spin_lock_bh(&bp->phy_lock);
-		}
-
-		bnx2_write_phy(bp, bp->mii_adv, new_adv);
-		bnx2_write_phy(bp, bp->mii_bmcr, bmcr | BMCR_ANRESTART |
-			BMCR_ANENABLE);
-		/* Speed up link-up time when the link partner
-		 * does not autonegotiate which is very common
-		 * in blade servers. Some blade servers use
-		 * IPMI for kerboard input and it's important
-		 * to minimize link disruptions. Autoneg. involves
-		 * exchanging base pages plus 3 next pages and
-		 * normally completes in about 120 msec.
-		 */
-		bp->current_interval = BNX2_SERDES_AN_TIMEOUT;
-		bp->serdes_an_pending = 1;
-		mod_timer(&bp->timer, jiffies + bp->current_interval);
-	} else {
-		bnx2_resolve_flow_ctrl(bp);
-		bnx2_set_mac_link(bp);
-	}
-
-	return 0;
-}
-
-#define ETHTOOL_ALL_FIBRE_SPEED						\
-	(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE) ?			\
-		(ADVERTISED_2500baseX_Full | ADVERTISED_1000baseT_Full) :\
-		(ADVERTISED_1000baseT_Full)
-
-#define ETHTOOL_ALL_COPPER_SPEED					\
-	(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |		\
-	ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |		\
-	ADVERTISED_1000baseT_Full)
-
-#define PHY_ALL_10_100_SPEED (ADVERTISE_10HALF | ADVERTISE_10FULL | \
-	ADVERTISE_100HALF | ADVERTISE_100FULL | ADVERTISE_CSMA)
-
-#define PHY_ALL_1000_SPEED (ADVERTISE_1000HALF | ADVERTISE_1000FULL)
-
-static void
-bnx2_set_default_remote_link(struct bnx2 *bp)
-{
-	u32 link;
-
-	if (bp->phy_port == PORT_TP)
-		link = bnx2_shmem_rd(bp, BNX2_RPHY_COPPER_LINK);
-	else
-		link = bnx2_shmem_rd(bp, BNX2_RPHY_SERDES_LINK);
-
-	if (link & BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG) {
-		bp->req_line_speed = 0;
-		bp->autoneg |= AUTONEG_SPEED;
-		bp->advertising = ADVERTISED_Autoneg;
-		if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF)
-			bp->advertising |= ADVERTISED_10baseT_Half;
-		if (link & BNX2_NETLINK_SET_LINK_SPEED_10FULL)
-			bp->advertising |= ADVERTISED_10baseT_Full;
-		if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF)
-			bp->advertising |= ADVERTISED_100baseT_Half;
-		if (link & BNX2_NETLINK_SET_LINK_SPEED_100FULL)
-			bp->advertising |= ADVERTISED_100baseT_Full;
-		if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL)
-			bp->advertising |= ADVERTISED_1000baseT_Full;
-		if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL)
-			bp->advertising |= ADVERTISED_2500baseX_Full;
-	} else {
-		bp->autoneg = 0;
-		bp->advertising = 0;
-		bp->req_duplex = DUPLEX_FULL;
-		if (link & BNX2_NETLINK_SET_LINK_SPEED_10) {
-			bp->req_line_speed = SPEED_10;
-			if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF)
-				bp->req_duplex = DUPLEX_HALF;
-		}
-		if (link & BNX2_NETLINK_SET_LINK_SPEED_100) {
-			bp->req_line_speed = SPEED_100;
-			if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF)
-				bp->req_duplex = DUPLEX_HALF;
-		}
-		if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL)
-			bp->req_line_speed = SPEED_1000;
-		if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL)
-			bp->req_line_speed = SPEED_2500;
-	}
-}
-
-static void
-bnx2_set_default_link(struct bnx2 *bp)
-{
-	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) {
-		bnx2_set_default_remote_link(bp);
-		return;
-	}
-
-	bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL;
-	bp->req_line_speed = 0;
-	if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
-		u32 reg;
-
-		bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg;
-
-		reg = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_CONFIG);
-		reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK;
-		if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) {
-			bp->autoneg = 0;
-			bp->req_line_speed = bp->line_speed = SPEED_1000;
-			bp->req_duplex = DUPLEX_FULL;
-		}
-	} else
-		bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg;
-}
-
-static void
-bnx2_send_heart_beat(struct bnx2 *bp)
-{
-	u32 msg;
-	u32 addr;
-
-	spin_lock(&bp->indirect_lock);
-	msg = (u32) (++bp->fw_drv_pulse_wr_seq & BNX2_DRV_PULSE_SEQ_MASK);
-	addr = bp->shmem_base + BNX2_DRV_PULSE_MB;
-	REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, addr);
-	REG_WR(bp, BNX2_PCICFG_REG_WINDOW, msg);
-	spin_unlock(&bp->indirect_lock);
-}
-
-static void
-bnx2_remote_phy_event(struct bnx2 *bp)
-{
-	u32 msg;
-	u8 link_up = bp->link_up;
-	u8 old_port;
-
-	msg = bnx2_shmem_rd(bp, BNX2_LINK_STATUS);
-
-	if (msg & BNX2_LINK_STATUS_HEART_BEAT_EXPIRED)
-		bnx2_send_heart_beat(bp);
-
-	msg &= ~BNX2_LINK_STATUS_HEART_BEAT_EXPIRED;
-
-	if ((msg & BNX2_LINK_STATUS_LINK_UP) == BNX2_LINK_STATUS_LINK_DOWN)
-		bp->link_up = 0;
-	else {
-		u32 speed;
-
-		bp->link_up = 1;
-		speed = msg & BNX2_LINK_STATUS_SPEED_MASK;
-		bp->duplex = DUPLEX_FULL;
-		switch (speed) {
-			case BNX2_LINK_STATUS_10HALF:
-				bp->duplex = DUPLEX_HALF;
-			case BNX2_LINK_STATUS_10FULL:
-				bp->line_speed = SPEED_10;
-				break;
-			case BNX2_LINK_STATUS_100HALF:
-				bp->duplex = DUPLEX_HALF;
-			case BNX2_LINK_STATUS_100BASE_T4:
-			case BNX2_LINK_STATUS_100FULL:
-				bp->line_speed = SPEED_100;
-				break;
-			case BNX2_LINK_STATUS_1000HALF:
-				bp->duplex = DUPLEX_HALF;
-			case BNX2_LINK_STATUS_1000FULL:
-				bp->line_speed = SPEED_1000;
-				break;
-			case BNX2_LINK_STATUS_2500HALF:
-				bp->duplex = DUPLEX_HALF;
-			case BNX2_LINK_STATUS_2500FULL:
-				bp->line_speed = SPEED_2500;
-				break;
-			default:
-				bp->line_speed = 0;
-				break;
-		}
-
-		bp->flow_ctrl = 0;
-		if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) !=
-		    (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) {
-			if (bp->duplex == DUPLEX_FULL)
-				bp->flow_ctrl = bp->req_flow_ctrl;
-		} else {
-			if (msg & BNX2_LINK_STATUS_TX_FC_ENABLED)
-				bp->flow_ctrl |= FLOW_CTRL_TX;
-			if (msg & BNX2_LINK_STATUS_RX_FC_ENABLED)
-				bp->flow_ctrl |= FLOW_CTRL_RX;
-		}
-
-		old_port = bp->phy_port;
-		if (msg & BNX2_LINK_STATUS_SERDES_LINK)
-			bp->phy_port = PORT_FIBRE;
-		else
-			bp->phy_port = PORT_TP;
-
-		if (old_port != bp->phy_port)
-			bnx2_set_default_link(bp);
-
-	}
-	if (bp->link_up != link_up)
-		bnx2_report_link(bp);
-
-	bnx2_set_mac_link(bp);
-}
-
-static int
-bnx2_set_remote_link(struct bnx2 *bp)
-{
-	u32 evt_code;
-
-	evt_code = bnx2_shmem_rd(bp, BNX2_FW_EVT_CODE_MB);
-	switch (evt_code) {
-		case BNX2_FW_EVT_CODE_LINK_EVENT:
-			bnx2_remote_phy_event(bp);
-			break;
-		case BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT:
-		default:
-			bnx2_send_heart_beat(bp);
-			break;
-	}
-	return 0;
-}
-
-static int
-bnx2_setup_copper_phy(struct bnx2 *bp)
-__releases(&bp->phy_lock)
-__acquires(&bp->phy_lock)
-{
-	u32 bmcr;
-	u32 new_bmcr;
-
-	bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
-
-	if (bp->autoneg & AUTONEG_SPEED) {
-		u32 adv_reg, adv1000_reg;
-		u32 new_adv_reg = 0;
-		u32 new_adv1000_reg = 0;
-
-		bnx2_read_phy(bp, bp->mii_adv, &adv_reg);
-		adv_reg &= (PHY_ALL_10_100_SPEED | ADVERTISE_PAUSE_CAP |
-			ADVERTISE_PAUSE_ASYM);
-
-		bnx2_read_phy(bp, MII_CTRL1000, &adv1000_reg);
-		adv1000_reg &= PHY_ALL_1000_SPEED;
-
-		if (bp->advertising & ADVERTISED_10baseT_Half)
-			new_adv_reg |= ADVERTISE_10HALF;
-		if (bp->advertising & ADVERTISED_10baseT_Full)
-			new_adv_reg |= ADVERTISE_10FULL;
-		if (bp->advertising & ADVERTISED_100baseT_Half)
-			new_adv_reg |= ADVERTISE_100HALF;
-		if (bp->advertising & ADVERTISED_100baseT_Full)
-			new_adv_reg |= ADVERTISE_100FULL;
-		if (bp->advertising & ADVERTISED_1000baseT_Full)
-			new_adv1000_reg |= ADVERTISE_1000FULL;
-
-		new_adv_reg |= ADVERTISE_CSMA;
-
-		new_adv_reg |= bnx2_phy_get_pause_adv(bp);
-
-		if ((adv1000_reg != new_adv1000_reg) ||
-			(adv_reg != new_adv_reg) ||
-			((bmcr & BMCR_ANENABLE) == 0)) {
-
-			bnx2_write_phy(bp, bp->mii_adv, new_adv_reg);
-			bnx2_write_phy(bp, MII_CTRL1000, new_adv1000_reg);
-			bnx2_write_phy(bp, bp->mii_bmcr, BMCR_ANRESTART |
-				BMCR_ANENABLE);
-		}
-		else if (bp->link_up) {
-			/* Flow ctrl may have changed from auto to forced */
-			/* or vice-versa. */
-
-			bnx2_resolve_flow_ctrl(bp);
-			bnx2_set_mac_link(bp);
-		}
-		return 0;
-	}
-
-	new_bmcr = 0;
-	if (bp->req_line_speed == SPEED_100) {
-		new_bmcr |= BMCR_SPEED100;
-	}
-	if (bp->req_duplex == DUPLEX_FULL) {
-		new_bmcr |= BMCR_FULLDPLX;
-	}
-	if (new_bmcr != bmcr) {
-		u32 bmsr;
-
-		bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
-		bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
-
-		if (bmsr & BMSR_LSTATUS) {
-			/* Force link down */
-			bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK);
-			spin_unlock_bh(&bp->phy_lock);
-			msleep(50);
-			spin_lock_bh(&bp->phy_lock);
-
-			bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
-			bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
-		}
-
-		bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr);
-
-		/* Normally, the new speed is setup after the link has
-		 * gone down and up again. In some cases, link will not go
-		 * down so we need to set up the new speed here.
-		 */
-		if (bmsr & BMSR_LSTATUS) {
-			bp->line_speed = bp->req_line_speed;
-			bp->duplex = bp->req_duplex;
-			bnx2_resolve_flow_ctrl(bp);
-			bnx2_set_mac_link(bp);
-		}
-	} else {
-		bnx2_resolve_flow_ctrl(bp);
-		bnx2_set_mac_link(bp);
-	}
-	return 0;
-}
-
-static int
-bnx2_setup_phy(struct bnx2 *bp, u8 port)
-__releases(&bp->phy_lock)
-__acquires(&bp->phy_lock)
-{
-	if (bp->loopback == MAC_LOOPBACK)
-		return 0;
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
-		return bnx2_setup_serdes_phy(bp, port);
-	}
-	else {
-		return bnx2_setup_copper_phy(bp);
-	}
-}
-
-static int
-bnx2_init_5709s_phy(struct bnx2 *bp, int reset_phy)
-{
-	u32 val;
-
-	bp->mii_bmcr = MII_BMCR + 0x10;
-	bp->mii_bmsr = MII_BMSR + 0x10;
-	bp->mii_bmsr1 = MII_BNX2_GP_TOP_AN_STATUS1;
-	bp->mii_adv = MII_ADVERTISE + 0x10;
-	bp->mii_lpa = MII_LPA + 0x10;
-	bp->mii_up1 = MII_BNX2_OVER1G_UP1;
-
-	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_AER);
-	bnx2_write_phy(bp, MII_BNX2_AER_AER, MII_BNX2_AER_AER_AN_MMD);
-
-	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
-	if (reset_phy)
-		bnx2_reset_phy(bp);
-
-	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_SERDES_DIG);
-
-	bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_1000XCTL1, &val);
-	val &= ~MII_BNX2_SD_1000XCTL1_AUTODET;
-	val |= MII_BNX2_SD_1000XCTL1_FIBER;
-	bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_1000XCTL1, val);
-
-	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G);
-	bnx2_read_phy(bp, MII_BNX2_OVER1G_UP1, &val);
-	if (bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)
-		val |= BCM5708S_UP1_2G5;
-	else
-		val &= ~BCM5708S_UP1_2G5;
-	bnx2_write_phy(bp, MII_BNX2_OVER1G_UP1, val);
-
-	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_BAM_NXTPG);
-	bnx2_read_phy(bp, MII_BNX2_BAM_NXTPG_CTL, &val);
-	val |= MII_BNX2_NXTPG_CTL_T2 | MII_BNX2_NXTPG_CTL_BAM;
-	bnx2_write_phy(bp, MII_BNX2_BAM_NXTPG_CTL, val);
-
-	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_CL73_USERB0);
-
-	val = MII_BNX2_CL73_BAM_EN | MII_BNX2_CL73_BAM_STA_MGR_EN |
-	      MII_BNX2_CL73_BAM_NP_AFT_BP_EN;
-	bnx2_write_phy(bp, MII_BNX2_CL73_BAM_CTL1, val);
-
-	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
-
-	return 0;
-}
-
-static int
-bnx2_init_5708s_phy(struct bnx2 *bp, int reset_phy)
-{
-	u32 val;
-
-	if (reset_phy)
-		bnx2_reset_phy(bp);
-
-	bp->mii_up1 = BCM5708S_UP1;
-
-	bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG3);
-	bnx2_write_phy(bp, BCM5708S_DIG_3_0, BCM5708S_DIG_3_0_USE_IEEE);
-	bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG);
-
-	bnx2_read_phy(bp, BCM5708S_1000X_CTL1, &val);
-	val |= BCM5708S_1000X_CTL1_FIBER_MODE | BCM5708S_1000X_CTL1_AUTODET_EN;
-	bnx2_write_phy(bp, BCM5708S_1000X_CTL1, val);
-
-	bnx2_read_phy(bp, BCM5708S_1000X_CTL2, &val);
-	val |= BCM5708S_1000X_CTL2_PLLEL_DET_EN;
-	bnx2_write_phy(bp, BCM5708S_1000X_CTL2, val);
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE) {
-		bnx2_read_phy(bp, BCM5708S_UP1, &val);
-		val |= BCM5708S_UP1_2G5;
-		bnx2_write_phy(bp, BCM5708S_UP1, val);
-	}
-
-	if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
-	    (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
-	    (CHIP_ID(bp) == CHIP_ID_5708_B1)) {
-		/* increase tx signal amplitude */
-		bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
-			       BCM5708S_BLK_ADDR_TX_MISC);
-		bnx2_read_phy(bp, BCM5708S_TX_ACTL1, &val);
-		val &= ~BCM5708S_TX_ACTL1_DRIVER_VCM;
-		bnx2_write_phy(bp, BCM5708S_TX_ACTL1, val);
-		bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG);
-	}
-
-	val = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_CONFIG) &
-	      BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK;
-
-	if (val) {
-		u32 is_backplane;
-
-		is_backplane = bnx2_shmem_rd(bp, BNX2_SHARED_HW_CFG_CONFIG);
-		if (is_backplane & BNX2_SHARED_HW_CFG_PHY_BACKPLANE) {
-			bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
-				       BCM5708S_BLK_ADDR_TX_MISC);
-			bnx2_write_phy(bp, BCM5708S_TX_ACTL3, val);
-			bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
-				       BCM5708S_BLK_ADDR_DIG);
-		}
-	}
-	return 0;
-}
-
-static int
-bnx2_init_5706s_phy(struct bnx2 *bp, int reset_phy)
-{
-	if (reset_phy)
-		bnx2_reset_phy(bp);
-
-	bp->phy_flags &= ~BNX2_PHY_FLAG_PARALLEL_DETECT;
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5706)
-        	REG_WR(bp, BNX2_MISC_GP_HW_CTL0, 0x300);
-
-	if (bp->dev->mtu > 1500) {
-		u32 val;
-
-		/* Set extended packet length bit */
-		bnx2_write_phy(bp, 0x18, 0x7);
-		bnx2_read_phy(bp, 0x18, &val);
-		bnx2_write_phy(bp, 0x18, (val & 0xfff8) | 0x4000);
-
-		bnx2_write_phy(bp, 0x1c, 0x6c00);
-		bnx2_read_phy(bp, 0x1c, &val);
-		bnx2_write_phy(bp, 0x1c, (val & 0x3ff) | 0xec02);
-	}
-	else {
-		u32 val;
-
-		bnx2_write_phy(bp, 0x18, 0x7);
-		bnx2_read_phy(bp, 0x18, &val);
-		bnx2_write_phy(bp, 0x18, val & ~0x4007);
-
-		bnx2_write_phy(bp, 0x1c, 0x6c00);
-		bnx2_read_phy(bp, 0x1c, &val);
-		bnx2_write_phy(bp, 0x1c, (val & 0x3fd) | 0xec00);
-	}
-
-	return 0;
-}
-
-static int
-bnx2_init_copper_phy(struct bnx2 *bp, int reset_phy)
-{
-	u32 val;
-
-	if (reset_phy)
-		bnx2_reset_phy(bp);
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_CRC_FIX) {
-		bnx2_write_phy(bp, 0x18, 0x0c00);
-		bnx2_write_phy(bp, 0x17, 0x000a);
-		bnx2_write_phy(bp, 0x15, 0x310b);
-		bnx2_write_phy(bp, 0x17, 0x201f);
-		bnx2_write_phy(bp, 0x15, 0x9506);
-		bnx2_write_phy(bp, 0x17, 0x401f);
-		bnx2_write_phy(bp, 0x15, 0x14e2);
-		bnx2_write_phy(bp, 0x18, 0x0400);
-	}
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_DIS_EARLY_DAC) {
-		bnx2_write_phy(bp, MII_BNX2_DSP_ADDRESS,
-			       MII_BNX2_DSP_EXPAND_REG | 0x8);
-		bnx2_read_phy(bp, MII_BNX2_DSP_RW_PORT, &val);
-		val &= ~(1 << 8);
-		bnx2_write_phy(bp, MII_BNX2_DSP_RW_PORT, val);
-	}
-
-	if (bp->dev->mtu > 1500) {
-		/* Set extended packet length bit */
-		bnx2_write_phy(bp, 0x18, 0x7);
-		bnx2_read_phy(bp, 0x18, &val);
-		bnx2_write_phy(bp, 0x18, val | 0x4000);
-
-		bnx2_read_phy(bp, 0x10, &val);
-		bnx2_write_phy(bp, 0x10, val | 0x1);
-	}
-	else {
-		bnx2_write_phy(bp, 0x18, 0x7);
-		bnx2_read_phy(bp, 0x18, &val);
-		bnx2_write_phy(bp, 0x18, val & ~0x4007);
-
-		bnx2_read_phy(bp, 0x10, &val);
-		bnx2_write_phy(bp, 0x10, val & ~0x1);
-	}
-
-	/* ethernet@wirespeed */
-	bnx2_write_phy(bp, 0x18, 0x7007);
-	bnx2_read_phy(bp, 0x18, &val);
-	bnx2_write_phy(bp, 0x18, val | (1 << 15) | (1 << 4));
-	return 0;
-}
-
-
-static int
-bnx2_init_phy(struct bnx2 *bp, int reset_phy)
-__releases(&bp->phy_lock)
-__acquires(&bp->phy_lock)
-{
-	u32 val;
-	int rc = 0;
-
-	bp->phy_flags &= ~BNX2_PHY_FLAG_INT_MODE_MASK;
-	bp->phy_flags |= BNX2_PHY_FLAG_INT_MODE_LINK_READY;
-
-	bp->mii_bmcr = MII_BMCR;
-	bp->mii_bmsr = MII_BMSR;
-	bp->mii_bmsr1 = MII_BMSR;
-	bp->mii_adv = MII_ADVERTISE;
-	bp->mii_lpa = MII_LPA;
-
-        REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
-		goto setup_phy;
-
-	bnx2_read_phy(bp, MII_PHYSID1, &val);
-	bp->phy_id = val << 16;
-	bnx2_read_phy(bp, MII_PHYSID2, &val);
-	bp->phy_id |= val & 0xffff;
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
-		if (CHIP_NUM(bp) == CHIP_NUM_5706)
-			rc = bnx2_init_5706s_phy(bp, reset_phy);
-		else if (CHIP_NUM(bp) == CHIP_NUM_5708)
-			rc = bnx2_init_5708s_phy(bp, reset_phy);
-		else if (CHIP_NUM(bp) == CHIP_NUM_5709)
-			rc = bnx2_init_5709s_phy(bp, reset_phy);
-	}
-	else {
-		rc = bnx2_init_copper_phy(bp, reset_phy);
-	}
-
-setup_phy:
-	if (!rc)
-		rc = bnx2_setup_phy(bp, bp->phy_port);
-
-	return rc;
-}
-
-static int
-bnx2_set_mac_loopback(struct bnx2 *bp)
-{
-	u32 mac_mode;
-
-	mac_mode = REG_RD(bp, BNX2_EMAC_MODE);
-	mac_mode &= ~BNX2_EMAC_MODE_PORT;
-	mac_mode |= BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK;
-	REG_WR(bp, BNX2_EMAC_MODE, mac_mode);
-	bp->link_up = 1;
-	return 0;
-}
-
-static int bnx2_test_link(struct bnx2 *);
-
-static int
-bnx2_set_phy_loopback(struct bnx2 *bp)
-{
-	u32 mac_mode;
-	int rc, i;
-
-	spin_lock_bh(&bp->phy_lock);
-	rc = bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK | BMCR_FULLDPLX |
-			    BMCR_SPEED1000);
-	spin_unlock_bh(&bp->phy_lock);
-	if (rc)
-		return rc;
-
-	for (i = 0; i < 10; i++) {
-		if (bnx2_test_link(bp) == 0)
-			break;
-		msleep(100);
-	}
-
-	mac_mode = REG_RD(bp, BNX2_EMAC_MODE);
-	mac_mode &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX |
-		      BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK |
-		      BNX2_EMAC_MODE_25G_MODE);
-
-	mac_mode |= BNX2_EMAC_MODE_PORT_GMII;
-	REG_WR(bp, BNX2_EMAC_MODE, mac_mode);
-	bp->link_up = 1;
-	return 0;
-}
-
-static void
-bnx2_dump_mcp_state(struct bnx2 *bp)
-{
-	struct net_device *dev = bp->dev;
-	u32 mcp_p0, mcp_p1;
-
-	netdev_err(dev, "<--- start MCP states dump --->\n");
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		mcp_p0 = BNX2_MCP_STATE_P0;
-		mcp_p1 = BNX2_MCP_STATE_P1;
-	} else {
-		mcp_p0 = BNX2_MCP_STATE_P0_5708;
-		mcp_p1 = BNX2_MCP_STATE_P1_5708;
-	}
-	netdev_err(dev, "DEBUG: MCP_STATE_P0[%08x] MCP_STATE_P1[%08x]\n",
-		   bnx2_reg_rd_ind(bp, mcp_p0), bnx2_reg_rd_ind(bp, mcp_p1));
-	netdev_err(dev, "DEBUG: MCP mode[%08x] state[%08x] evt_mask[%08x]\n",
-		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_MODE),
-		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_STATE),
-		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_EVENT_MASK));
-	netdev_err(dev, "DEBUG: pc[%08x] pc[%08x] instr[%08x]\n",
-		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_PROGRAM_COUNTER),
-		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_PROGRAM_COUNTER),
-		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_INSTRUCTION));
-	netdev_err(dev, "DEBUG: shmem states:\n");
-	netdev_err(dev, "DEBUG: drv_mb[%08x] fw_mb[%08x] link_status[%08x]",
-		   bnx2_shmem_rd(bp, BNX2_DRV_MB),
-		   bnx2_shmem_rd(bp, BNX2_FW_MB),
-		   bnx2_shmem_rd(bp, BNX2_LINK_STATUS));
-	pr_cont(" drv_pulse_mb[%08x]\n", bnx2_shmem_rd(bp, BNX2_DRV_PULSE_MB));
-	netdev_err(dev, "DEBUG: dev_info_signature[%08x] reset_type[%08x]",
-		   bnx2_shmem_rd(bp, BNX2_DEV_INFO_SIGNATURE),
-		   bnx2_shmem_rd(bp, BNX2_BC_STATE_RESET_TYPE));
-	pr_cont(" condition[%08x]\n",
-		bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION));
-	DP_SHMEM_LINE(bp, 0x3cc);
-	DP_SHMEM_LINE(bp, 0x3dc);
-	DP_SHMEM_LINE(bp, 0x3ec);
-	netdev_err(dev, "DEBUG: 0x3fc[%08x]\n", bnx2_shmem_rd(bp, 0x3fc));
-	netdev_err(dev, "<--- end MCP states dump --->\n");
-}
-
-static int
-bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int ack, int silent)
-{
-	int i;
-	u32 val;
-
-	bp->fw_wr_seq++;
-	msg_data |= bp->fw_wr_seq;
-
-	bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data);
-
-	if (!ack)
-		return 0;
-
-	/* wait for an acknowledgement. */
-	for (i = 0; i < (BNX2_FW_ACK_TIME_OUT_MS / 10); i++) {
-		msleep(10);
-
-		val = bnx2_shmem_rd(bp, BNX2_FW_MB);
-
-		if ((val & BNX2_FW_MSG_ACK) == (msg_data & BNX2_DRV_MSG_SEQ))
-			break;
-	}
-	if ((msg_data & BNX2_DRV_MSG_DATA) == BNX2_DRV_MSG_DATA_WAIT0)
-		return 0;
-
-	/* If we timed out, inform the firmware that this is the case. */
-	if ((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) {
-		msg_data &= ~BNX2_DRV_MSG_CODE;
-		msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT;
-
-		bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data);
-		if (!silent) {
-			pr_err("fw sync timeout, reset code = %x\n", msg_data);
-			bnx2_dump_mcp_state(bp);
-		}
-
-		return -EBUSY;
-	}
-
-	if ((val & BNX2_FW_MSG_STATUS_MASK) != BNX2_FW_MSG_STATUS_OK)
-		return -EIO;
-
-	return 0;
-}
-
-static int
-bnx2_init_5709_context(struct bnx2 *bp)
-{
-	int i, ret = 0;
-	u32 val;
-
-	val = BNX2_CTX_COMMAND_ENABLED | BNX2_CTX_COMMAND_MEM_INIT | (1 << 12);
-	val |= (BCM_PAGE_BITS - 8) << 16;
-	REG_WR(bp, BNX2_CTX_COMMAND, val);
-	for (i = 0; i < 10; i++) {
-		val = REG_RD(bp, BNX2_CTX_COMMAND);
-		if (!(val & BNX2_CTX_COMMAND_MEM_INIT))
-			break;
-		udelay(2);
-	}
-	if (val & BNX2_CTX_COMMAND_MEM_INIT)
-		return -EBUSY;
-
-	for (i = 0; i < bp->ctx_pages; i++) {
-		int j;
-
-		if (bp->ctx_blk[i])
-			memset(bp->ctx_blk[i], 0, BCM_PAGE_SIZE);
-		else
-			return -ENOMEM;
-
-		REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA0,
-		       (bp->ctx_blk_mapping[i] & 0xffffffff) |
-		       BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID);
-		REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA1,
-		       (u64) bp->ctx_blk_mapping[i] >> 32);
-		REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL, i |
-		       BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ);
-		for (j = 0; j < 10; j++) {
-
-			val = REG_RD(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL);
-			if (!(val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ))
-				break;
-			udelay(5);
-		}
-		if (val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ) {
-			ret = -EBUSY;
-			break;
-		}
-	}
-	return ret;
-}
-
-static void
-bnx2_init_context(struct bnx2 *bp)
-{
-	u32 vcid;
-
-	vcid = 96;
-	while (vcid) {
-		u32 vcid_addr, pcid_addr, offset;
-		int i;
-
-		vcid--;
-
-		if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
-			u32 new_vcid;
-
-			vcid_addr = GET_PCID_ADDR(vcid);
-			if (vcid & 0x8) {
-				new_vcid = 0x60 + (vcid & 0xf0) + (vcid & 0x7);
-			}
-			else {
-				new_vcid = vcid;
-			}
-			pcid_addr = GET_PCID_ADDR(new_vcid);
-		}
-		else {
-	    		vcid_addr = GET_CID_ADDR(vcid);
-			pcid_addr = vcid_addr;
-		}
-
-		for (i = 0; i < (CTX_SIZE / PHY_CTX_SIZE); i++) {
-			vcid_addr += (i << PHY_CTX_SHIFT);
-			pcid_addr += (i << PHY_CTX_SHIFT);
-
-			REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
-			REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
-
-			/* Zero out the context. */
-			for (offset = 0; offset < PHY_CTX_SIZE; offset += 4)
-				bnx2_ctx_wr(bp, vcid_addr, offset, 0);
-		}
-	}
-}
-
-static int
-bnx2_alloc_bad_rbuf(struct bnx2 *bp)
-{
-	u16 *good_mbuf;
-	u32 good_mbuf_cnt;
-	u32 val;
-
-	good_mbuf = kmalloc(512 * sizeof(u16), GFP_KERNEL);
-	if (good_mbuf == NULL) {
-		pr_err("Failed to allocate memory in %s\n", __func__);
-		return -ENOMEM;
-	}
-
-	REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
-		BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE);
-
-	good_mbuf_cnt = 0;
-
-	/* Allocate a bunch of mbufs and save the good ones in an array. */
-	val = bnx2_reg_rd_ind(bp, BNX2_RBUF_STATUS1);
-	while (val & BNX2_RBUF_STATUS1_FREE_COUNT) {
-		bnx2_reg_wr_ind(bp, BNX2_RBUF_COMMAND,
-				BNX2_RBUF_COMMAND_ALLOC_REQ);
-
-		val = bnx2_reg_rd_ind(bp, BNX2_RBUF_FW_BUF_ALLOC);
-
-		val &= BNX2_RBUF_FW_BUF_ALLOC_VALUE;
-
-		/* The addresses with Bit 9 set are bad memory blocks. */
-		if (!(val & (1 << 9))) {
-			good_mbuf[good_mbuf_cnt] = (u16) val;
-			good_mbuf_cnt++;
-		}
-
-		val = bnx2_reg_rd_ind(bp, BNX2_RBUF_STATUS1);
-	}
-
-	/* Free the good ones back to the mbuf pool thus discarding
-	 * all the bad ones. */
-	while (good_mbuf_cnt) {
-		good_mbuf_cnt--;
-
-		val = good_mbuf[good_mbuf_cnt];
-		val = (val << 9) | val | 1;
-
-		bnx2_reg_wr_ind(bp, BNX2_RBUF_FW_BUF_FREE, val);
-	}
-	kfree(good_mbuf);
-	return 0;
-}
-
-static void
-bnx2_set_mac_addr(struct bnx2 *bp, u8 *mac_addr, u32 pos)
-{
-	u32 val;
-
-	val = (mac_addr[0] << 8) | mac_addr[1];
-
-	REG_WR(bp, BNX2_EMAC_MAC_MATCH0 + (pos * 8), val);
-
-	val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
-		(mac_addr[4] << 8) | mac_addr[5];
-
-	REG_WR(bp, BNX2_EMAC_MAC_MATCH1 + (pos * 8), val);
-}
-
-static inline int
-bnx2_alloc_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index, gfp_t gfp)
-{
-	dma_addr_t mapping;
-	struct sw_pg *rx_pg = &rxr->rx_pg_ring[index];
-	struct rx_bd *rxbd =
-		&rxr->rx_pg_desc_ring[RX_RING(index)][RX_IDX(index)];
-	struct page *page = alloc_page(gfp);
-
-	if (!page)
-		return -ENOMEM;
-	mapping = dma_map_page(&bp->pdev->dev, page, 0, PAGE_SIZE,
-			       PCI_DMA_FROMDEVICE);
-	if (dma_mapping_error(&bp->pdev->dev, mapping)) {
-		__free_page(page);
-		return -EIO;
-	}
-
-	rx_pg->page = page;
-	dma_unmap_addr_set(rx_pg, mapping, mapping);
-	rxbd->rx_bd_haddr_hi = (u64) mapping >> 32;
-	rxbd->rx_bd_haddr_lo = (u64) mapping & 0xffffffff;
-	return 0;
-}
-
-static void
-bnx2_free_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index)
-{
-	struct sw_pg *rx_pg = &rxr->rx_pg_ring[index];
-	struct page *page = rx_pg->page;
-
-	if (!page)
-		return;
-
-	dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(rx_pg, mapping),
-		       PAGE_SIZE, PCI_DMA_FROMDEVICE);
-
-	__free_page(page);
-	rx_pg->page = NULL;
-}
-
-static inline int
-bnx2_alloc_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index, gfp_t gfp)
-{
-	struct sk_buff *skb;
-	struct sw_bd *rx_buf = &rxr->rx_buf_ring[index];
-	dma_addr_t mapping;
-	struct rx_bd *rxbd = &rxr->rx_desc_ring[RX_RING(index)][RX_IDX(index)];
-	unsigned long align;
-
-	skb = __netdev_alloc_skb(bp->dev, bp->rx_buf_size, gfp);
-	if (skb == NULL) {
-		return -ENOMEM;
-	}
-
-	if (unlikely((align = (unsigned long) skb->data & (BNX2_RX_ALIGN - 1))))
-		skb_reserve(skb, BNX2_RX_ALIGN - align);
-
-	mapping = dma_map_single(&bp->pdev->dev, skb->data, bp->rx_buf_use_size,
-				 PCI_DMA_FROMDEVICE);
-	if (dma_mapping_error(&bp->pdev->dev, mapping)) {
-		dev_kfree_skb(skb);
-		return -EIO;
-	}
-
-	rx_buf->skb = skb;
-	rx_buf->desc = (struct l2_fhdr *) skb->data;
-	dma_unmap_addr_set(rx_buf, mapping, mapping);
-
-	rxbd->rx_bd_haddr_hi = (u64) mapping >> 32;
-	rxbd->rx_bd_haddr_lo = (u64) mapping & 0xffffffff;
-
-	rxr->rx_prod_bseq += bp->rx_buf_use_size;
-
-	return 0;
-}
-
-static int
-bnx2_phy_event_is_set(struct bnx2 *bp, struct bnx2_napi *bnapi, u32 event)
-{
-	struct status_block *sblk = bnapi->status_blk.msi;
-	u32 new_link_state, old_link_state;
-	int is_set = 1;
-
-	new_link_state = sblk->status_attn_bits & event;
-	old_link_state = sblk->status_attn_bits_ack & event;
-	if (new_link_state != old_link_state) {
-		if (new_link_state)
-			REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD, event);
-		else
-			REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD, event);
-	} else
-		is_set = 0;
-
-	return is_set;
-}
-
-static void
-bnx2_phy_int(struct bnx2 *bp, struct bnx2_napi *bnapi)
-{
-	spin_lock(&bp->phy_lock);
-
-	if (bnx2_phy_event_is_set(bp, bnapi, STATUS_ATTN_BITS_LINK_STATE))
-		bnx2_set_link(bp);
-	if (bnx2_phy_event_is_set(bp, bnapi, STATUS_ATTN_BITS_TIMER_ABORT))
-		bnx2_set_remote_link(bp);
-
-	spin_unlock(&bp->phy_lock);
-
-}
-
-static inline u16
-bnx2_get_hw_tx_cons(struct bnx2_napi *bnapi)
-{
-	u16 cons;
-
-	/* Tell compiler that status block fields can change. */
-	barrier();
-	cons = *bnapi->hw_tx_cons_ptr;
-	barrier();
-	if (unlikely((cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT))
-		cons++;
-	return cons;
-}
-
-static int
-bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
-{
-	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
-	u16 hw_cons, sw_cons, sw_ring_cons;
-	int tx_pkt = 0, index;
-	struct netdev_queue *txq;
-
-	index = (bnapi - bp->bnx2_napi);
-	txq = netdev_get_tx_queue(bp->dev, index);
-
-	hw_cons = bnx2_get_hw_tx_cons(bnapi);
-	sw_cons = txr->tx_cons;
-
-	while (sw_cons != hw_cons) {
-		struct sw_tx_bd *tx_buf;
-		struct sk_buff *skb;
-		int i, last;
-
-		sw_ring_cons = TX_RING_IDX(sw_cons);
-
-		tx_buf = &txr->tx_buf_ring[sw_ring_cons];
-		skb = tx_buf->skb;
-
-		/* prefetch skb_end_pointer() to speedup skb_shinfo(skb) */
-		prefetch(&skb->end);
-
-		/* partial BD completions possible with TSO packets */
-		if (tx_buf->is_gso) {
-			u16 last_idx, last_ring_idx;
-
-			last_idx = sw_cons + tx_buf->nr_frags + 1;
-			last_ring_idx = sw_ring_cons + tx_buf->nr_frags + 1;
-			if (unlikely(last_ring_idx >= MAX_TX_DESC_CNT)) {
-				last_idx++;
-			}
-			if (((s16) ((s16) last_idx - (s16) hw_cons)) > 0) {
-				break;
-			}
-		}
-
-		dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping),
-			skb_headlen(skb), PCI_DMA_TODEVICE);
-
-		tx_buf->skb = NULL;
-		last = tx_buf->nr_frags;
-
-		for (i = 0; i < last; i++) {
-			sw_cons = NEXT_TX_BD(sw_cons);
-
-			dma_unmap_page(&bp->pdev->dev,
-				dma_unmap_addr(
-					&txr->tx_buf_ring[TX_RING_IDX(sw_cons)],
-					mapping),
-				skb_shinfo(skb)->frags[i].size,
-				PCI_DMA_TODEVICE);
-		}
-
-		sw_cons = NEXT_TX_BD(sw_cons);
-
-		dev_kfree_skb(skb);
-		tx_pkt++;
-		if (tx_pkt == budget)
-			break;
-
-		if (hw_cons == sw_cons)
-			hw_cons = bnx2_get_hw_tx_cons(bnapi);
-	}
-
-	txr->hw_tx_cons = hw_cons;
-	txr->tx_cons = sw_cons;
-
-	/* Need to make the tx_cons update visible to bnx2_start_xmit()
-	 * before checking for netif_tx_queue_stopped().  Without the
-	 * memory barrier, there is a small possibility that bnx2_start_xmit()
-	 * will miss it and cause the queue to be stopped forever.
-	 */
-	smp_mb();
-
-	if (unlikely(netif_tx_queue_stopped(txq)) &&
-		     (bnx2_tx_avail(bp, txr) > bp->tx_wake_thresh)) {
-		__netif_tx_lock(txq, smp_processor_id());
-		if ((netif_tx_queue_stopped(txq)) &&
-		    (bnx2_tx_avail(bp, txr) > bp->tx_wake_thresh))
-			netif_tx_wake_queue(txq);
-		__netif_tx_unlock(txq);
-	}
-
-	return tx_pkt;
-}
-
-static void
-bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
-			struct sk_buff *skb, int count)
-{
-	struct sw_pg *cons_rx_pg, *prod_rx_pg;
-	struct rx_bd *cons_bd, *prod_bd;
-	int i;
-	u16 hw_prod, prod;
-	u16 cons = rxr->rx_pg_cons;
-
-	cons_rx_pg = &rxr->rx_pg_ring[cons];
-
-	/* The caller was unable to allocate a new page to replace the
-	 * last one in the frags array, so we need to recycle that page
-	 * and then free the skb.
-	 */
-	if (skb) {
-		struct page *page;
-		struct skb_shared_info *shinfo;
-
-		shinfo = skb_shinfo(skb);
-		shinfo->nr_frags--;
-		page = shinfo->frags[shinfo->nr_frags].page;
-		shinfo->frags[shinfo->nr_frags].page = NULL;
-
-		cons_rx_pg->page = page;
-		dev_kfree_skb(skb);
-	}
-
-	hw_prod = rxr->rx_pg_prod;
-
-	for (i = 0; i < count; i++) {
-		prod = RX_PG_RING_IDX(hw_prod);
-
-		prod_rx_pg = &rxr->rx_pg_ring[prod];
-		cons_rx_pg = &rxr->rx_pg_ring[cons];
-		cons_bd = &rxr->rx_pg_desc_ring[RX_RING(cons)][RX_IDX(cons)];
-		prod_bd = &rxr->rx_pg_desc_ring[RX_RING(prod)][RX_IDX(prod)];
-
-		if (prod != cons) {
-			prod_rx_pg->page = cons_rx_pg->page;
-			cons_rx_pg->page = NULL;
-			dma_unmap_addr_set(prod_rx_pg, mapping,
-				dma_unmap_addr(cons_rx_pg, mapping));
-
-			prod_bd->rx_bd_haddr_hi = cons_bd->rx_bd_haddr_hi;
-			prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
-
-		}
-		cons = RX_PG_RING_IDX(NEXT_RX_BD(cons));
-		hw_prod = NEXT_RX_BD(hw_prod);
-	}
-	rxr->rx_pg_prod = hw_prod;
-	rxr->rx_pg_cons = cons;
-}
-
-static inline void
-bnx2_reuse_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
-		  struct sk_buff *skb, u16 cons, u16 prod)
-{
-	struct sw_bd *cons_rx_buf, *prod_rx_buf;
-	struct rx_bd *cons_bd, *prod_bd;
-
-	cons_rx_buf = &rxr->rx_buf_ring[cons];
-	prod_rx_buf = &rxr->rx_buf_ring[prod];
-
-	dma_sync_single_for_device(&bp->pdev->dev,
-		dma_unmap_addr(cons_rx_buf, mapping),
-		BNX2_RX_OFFSET + BNX2_RX_COPY_THRESH, PCI_DMA_FROMDEVICE);
-
-	rxr->rx_prod_bseq += bp->rx_buf_use_size;
-
-	prod_rx_buf->skb = skb;
-	prod_rx_buf->desc = (struct l2_fhdr *) skb->data;
-
-	if (cons == prod)
-		return;
-
-	dma_unmap_addr_set(prod_rx_buf, mapping,
-			dma_unmap_addr(cons_rx_buf, mapping));
-
-	cons_bd = &rxr->rx_desc_ring[RX_RING(cons)][RX_IDX(cons)];
-	prod_bd = &rxr->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)];
-	prod_bd->rx_bd_haddr_hi = cons_bd->rx_bd_haddr_hi;
-	prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
-}
-
-static int
-bnx2_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, struct sk_buff *skb,
-	    unsigned int len, unsigned int hdr_len, dma_addr_t dma_addr,
-	    u32 ring_idx)
-{
-	int err;
-	u16 prod = ring_idx & 0xffff;
-
-	err = bnx2_alloc_rx_skb(bp, rxr, prod, GFP_ATOMIC);
-	if (unlikely(err)) {
-		bnx2_reuse_rx_skb(bp, rxr, skb, (u16) (ring_idx >> 16), prod);
-		if (hdr_len) {
-			unsigned int raw_len = len + 4;
-			int pages = PAGE_ALIGN(raw_len - hdr_len) >> PAGE_SHIFT;
-
-			bnx2_reuse_rx_skb_pages(bp, rxr, NULL, pages);
-		}
-		return err;
-	}
-
-	skb_reserve(skb, BNX2_RX_OFFSET);
-	dma_unmap_single(&bp->pdev->dev, dma_addr, bp->rx_buf_use_size,
-			 PCI_DMA_FROMDEVICE);
-
-	if (hdr_len == 0) {
-		skb_put(skb, len);
-		return 0;
-	} else {
-		unsigned int i, frag_len, frag_size, pages;
-		struct sw_pg *rx_pg;
-		u16 pg_cons = rxr->rx_pg_cons;
-		u16 pg_prod = rxr->rx_pg_prod;
-
-		frag_size = len + 4 - hdr_len;
-		pages = PAGE_ALIGN(frag_size) >> PAGE_SHIFT;
-		skb_put(skb, hdr_len);
-
-		for (i = 0; i < pages; i++) {
-			dma_addr_t mapping_old;
-
-			frag_len = min(frag_size, (unsigned int) PAGE_SIZE);
-			if (unlikely(frag_len <= 4)) {
-				unsigned int tail = 4 - frag_len;
-
-				rxr->rx_pg_cons = pg_cons;
-				rxr->rx_pg_prod = pg_prod;
-				bnx2_reuse_rx_skb_pages(bp, rxr, NULL,
-							pages - i);
-				skb->len -= tail;
-				if (i == 0) {
-					skb->tail -= tail;
-				} else {
-					skb_frag_t *frag =
-						&skb_shinfo(skb)->frags[i - 1];
-					frag->size -= tail;
-					skb->data_len -= tail;
-					skb->truesize -= tail;
-				}
-				return 0;
-			}
-			rx_pg = &rxr->rx_pg_ring[pg_cons];
-
-			/* Don't unmap yet.  If we're unable to allocate a new
-			 * page, we need to recycle the page and the DMA addr.
-			 */
-			mapping_old = dma_unmap_addr(rx_pg, mapping);
-			if (i == pages - 1)
-				frag_len -= 4;
-
-			skb_fill_page_desc(skb, i, rx_pg->page, 0, frag_len);
-			rx_pg->page = NULL;
-
-			err = bnx2_alloc_rx_page(bp, rxr,
-						 RX_PG_RING_IDX(pg_prod),
-						 GFP_ATOMIC);
-			if (unlikely(err)) {
-				rxr->rx_pg_cons = pg_cons;
-				rxr->rx_pg_prod = pg_prod;
-				bnx2_reuse_rx_skb_pages(bp, rxr, skb,
-							pages - i);
-				return err;
-			}
-
-			dma_unmap_page(&bp->pdev->dev, mapping_old,
-				       PAGE_SIZE, PCI_DMA_FROMDEVICE);
-
-			frag_size -= frag_len;
-			skb->data_len += frag_len;
-			skb->truesize += frag_len;
-			skb->len += frag_len;
-
-			pg_prod = NEXT_RX_BD(pg_prod);
-			pg_cons = RX_PG_RING_IDX(NEXT_RX_BD(pg_cons));
-		}
-		rxr->rx_pg_prod = pg_prod;
-		rxr->rx_pg_cons = pg_cons;
-	}
-	return 0;
-}
-
-static inline u16
-bnx2_get_hw_rx_cons(struct bnx2_napi *bnapi)
-{
-	u16 cons;
-
-	/* Tell compiler that status block fields can change. */
-	barrier();
-	cons = *bnapi->hw_rx_cons_ptr;
-	barrier();
-	if (unlikely((cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT))
-		cons++;
-	return cons;
-}
-
-static int
-bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
-{
-	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
-	u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod;
-	struct l2_fhdr *rx_hdr;
-	int rx_pkt = 0, pg_ring_used = 0;
-
-	hw_cons = bnx2_get_hw_rx_cons(bnapi);
-	sw_cons = rxr->rx_cons;
-	sw_prod = rxr->rx_prod;
-
-	/* Memory barrier necessary as speculative reads of the rx
-	 * buffer can be ahead of the index in the status block
-	 */
-	rmb();
-	while (sw_cons != hw_cons) {
-		unsigned int len, hdr_len;
-		u32 status;
-		struct sw_bd *rx_buf, *next_rx_buf;
-		struct sk_buff *skb;
-		dma_addr_t dma_addr;
-
-		sw_ring_cons = RX_RING_IDX(sw_cons);
-		sw_ring_prod = RX_RING_IDX(sw_prod);
-
-		rx_buf = &rxr->rx_buf_ring[sw_ring_cons];
-		skb = rx_buf->skb;
-		prefetchw(skb);
-
-		next_rx_buf =
-			&rxr->rx_buf_ring[RX_RING_IDX(NEXT_RX_BD(sw_cons))];
-		prefetch(next_rx_buf->desc);
-
-		rx_buf->skb = NULL;
-
-		dma_addr = dma_unmap_addr(rx_buf, mapping);
-
-		dma_sync_single_for_cpu(&bp->pdev->dev, dma_addr,
-			BNX2_RX_OFFSET + BNX2_RX_COPY_THRESH,
-			PCI_DMA_FROMDEVICE);
-
-		rx_hdr = rx_buf->desc;
-		len = rx_hdr->l2_fhdr_pkt_len;
-		status = rx_hdr->l2_fhdr_status;
-
-		hdr_len = 0;
-		if (status & L2_FHDR_STATUS_SPLIT) {
-			hdr_len = rx_hdr->l2_fhdr_ip_xsum;
-			pg_ring_used = 1;
-		} else if (len > bp->rx_jumbo_thresh) {
-			hdr_len = bp->rx_jumbo_thresh;
-			pg_ring_used = 1;
-		}
-
-		if (unlikely(status & (L2_FHDR_ERRORS_BAD_CRC |
-				       L2_FHDR_ERRORS_PHY_DECODE |
-				       L2_FHDR_ERRORS_ALIGNMENT |
-				       L2_FHDR_ERRORS_TOO_SHORT |
-				       L2_FHDR_ERRORS_GIANT_FRAME))) {
-
-			bnx2_reuse_rx_skb(bp, rxr, skb, sw_ring_cons,
-					  sw_ring_prod);
-			if (pg_ring_used) {
-				int pages;
-
-				pages = PAGE_ALIGN(len - hdr_len) >> PAGE_SHIFT;
-
-				bnx2_reuse_rx_skb_pages(bp, rxr, NULL, pages);
-			}
-			goto next_rx;
-		}
-
-		len -= 4;
-
-		if (len <= bp->rx_copy_thresh) {
-			struct sk_buff *new_skb;
-
-			new_skb = netdev_alloc_skb(bp->dev, len + 6);
-			if (new_skb == NULL) {
-				bnx2_reuse_rx_skb(bp, rxr, skb, sw_ring_cons,
-						  sw_ring_prod);
-				goto next_rx;
-			}
-
-			/* aligned copy */
-			skb_copy_from_linear_data_offset(skb,
-							 BNX2_RX_OFFSET - 6,
-				      new_skb->data, len + 6);
-			skb_reserve(new_skb, 6);
-			skb_put(new_skb, len);
-
-			bnx2_reuse_rx_skb(bp, rxr, skb,
-				sw_ring_cons, sw_ring_prod);
-
-			skb = new_skb;
-		} else if (unlikely(bnx2_rx_skb(bp, rxr, skb, len, hdr_len,
-			   dma_addr, (sw_ring_cons << 16) | sw_ring_prod)))
-			goto next_rx;
-
-		if ((status & L2_FHDR_STATUS_L2_VLAN_TAG) &&
-		    !(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG))
-			__vlan_hwaccel_put_tag(skb, rx_hdr->l2_fhdr_vlan_tag);
-
-		skb->protocol = eth_type_trans(skb, bp->dev);
-
-		if ((len > (bp->dev->mtu + ETH_HLEN)) &&
-			(ntohs(skb->protocol) != 0x8100)) {
-
-			dev_kfree_skb(skb);
-			goto next_rx;
-
-		}
-
-		skb_checksum_none_assert(skb);
-		if ((bp->dev->features & NETIF_F_RXCSUM) &&
-			(status & (L2_FHDR_STATUS_TCP_SEGMENT |
-			L2_FHDR_STATUS_UDP_DATAGRAM))) {
-
-			if (likely((status & (L2_FHDR_ERRORS_TCP_XSUM |
-					      L2_FHDR_ERRORS_UDP_XSUM)) == 0))
-				skb->ip_summed = CHECKSUM_UNNECESSARY;
-		}
-		if ((bp->dev->features & NETIF_F_RXHASH) &&
-		    ((status & L2_FHDR_STATUS_USE_RXHASH) ==
-		     L2_FHDR_STATUS_USE_RXHASH))
-			skb->rxhash = rx_hdr->l2_fhdr_hash;
-
-		skb_record_rx_queue(skb, bnapi - &bp->bnx2_napi[0]);
-		napi_gro_receive(&bnapi->napi, skb);
-		rx_pkt++;
-
-next_rx:
-		sw_cons = NEXT_RX_BD(sw_cons);
-		sw_prod = NEXT_RX_BD(sw_prod);
-
-		if ((rx_pkt == budget))
-			break;
-
-		/* Refresh hw_cons to see if there is new work */
-		if (sw_cons == hw_cons) {
-			hw_cons = bnx2_get_hw_rx_cons(bnapi);
-			rmb();
-		}
-	}
-	rxr->rx_cons = sw_cons;
-	rxr->rx_prod = sw_prod;
-
-	if (pg_ring_used)
-		REG_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod);
-
-	REG_WR16(bp, rxr->rx_bidx_addr, sw_prod);
-
-	REG_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq);
-
-	mmiowb();
-
-	return rx_pkt;
-
-}
-
-/* MSI ISR - The only difference between this and the INTx ISR
- * is that the MSI interrupt is always serviced.
- */
-static irqreturn_t
-bnx2_msi(int irq, void *dev_instance)
-{
-	struct bnx2_napi *bnapi = dev_instance;
-	struct bnx2 *bp = bnapi->bp;
-
-	prefetch(bnapi->status_blk.msi);
-	REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
-		BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
-		BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
-
-	/* Return here if interrupt is disabled. */
-	if (unlikely(atomic_read(&bp->intr_sem) != 0))
-		return IRQ_HANDLED;
-
-	napi_schedule(&bnapi->napi);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t
-bnx2_msi_1shot(int irq, void *dev_instance)
-{
-	struct bnx2_napi *bnapi = dev_instance;
-	struct bnx2 *bp = bnapi->bp;
-
-	prefetch(bnapi->status_blk.msi);
-
-	/* Return here if interrupt is disabled. */
-	if (unlikely(atomic_read(&bp->intr_sem) != 0))
-		return IRQ_HANDLED;
-
-	napi_schedule(&bnapi->napi);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t
-bnx2_interrupt(int irq, void *dev_instance)
-{
-	struct bnx2_napi *bnapi = dev_instance;
-	struct bnx2 *bp = bnapi->bp;
-	struct status_block *sblk = bnapi->status_blk.msi;
-
-	/* When using INTx, it is possible for the interrupt to arrive
-	 * at the CPU before the status block posted prior to the
-	 * interrupt. Reading a register will flush the status block.
-	 * When using MSI, the MSI message will always complete after
-	 * the status block write.
-	 */
-	if ((sblk->status_idx == bnapi->last_status_idx) &&
-	    (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) &
-	     BNX2_PCICFG_MISC_STATUS_INTA_VALUE))
-		return IRQ_NONE;
-
-	REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
-		BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
-		BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
-
-	/* Read back to deassert IRQ immediately to avoid too many
-	 * spurious interrupts.
-	 */
-	REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
-
-	/* Return here if interrupt is shared and is disabled. */
-	if (unlikely(atomic_read(&bp->intr_sem) != 0))
-		return IRQ_HANDLED;
-
-	if (napi_schedule_prep(&bnapi->napi)) {
-		bnapi->last_status_idx = sblk->status_idx;
-		__napi_schedule(&bnapi->napi);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static inline int
-bnx2_has_fast_work(struct bnx2_napi *bnapi)
-{
-	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
-	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
-
-	if ((bnx2_get_hw_rx_cons(bnapi) != rxr->rx_cons) ||
-	    (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons))
-		return 1;
-	return 0;
-}
-
-#define STATUS_ATTN_EVENTS	(STATUS_ATTN_BITS_LINK_STATE | \
-				 STATUS_ATTN_BITS_TIMER_ABORT)
-
-static inline int
-bnx2_has_work(struct bnx2_napi *bnapi)
-{
-	struct status_block *sblk = bnapi->status_blk.msi;
-
-	if (bnx2_has_fast_work(bnapi))
-		return 1;
-
-#ifdef BCM_CNIC
-	if (bnapi->cnic_present && (bnapi->cnic_tag != sblk->status_idx))
-		return 1;
-#endif
-
-	if ((sblk->status_attn_bits & STATUS_ATTN_EVENTS) !=
-	    (sblk->status_attn_bits_ack & STATUS_ATTN_EVENTS))
-		return 1;
-
-	return 0;
-}
-
-static void
-bnx2_chk_missed_msi(struct bnx2 *bp)
-{
-	struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
-	u32 msi_ctrl;
-
-	if (bnx2_has_work(bnapi)) {
-		msi_ctrl = REG_RD(bp, BNX2_PCICFG_MSI_CONTROL);
-		if (!(msi_ctrl & BNX2_PCICFG_MSI_CONTROL_ENABLE))
-			return;
-
-		if (bnapi->last_status_idx == bp->idle_chk_status_idx) {
-			REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl &
-			       ~BNX2_PCICFG_MSI_CONTROL_ENABLE);
-			REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl);
-			bnx2_msi(bp->irq_tbl[0].vector, bnapi);
-		}
-	}
-
-	bp->idle_chk_status_idx = bnapi->last_status_idx;
-}
-
-#ifdef BCM_CNIC
-static void bnx2_poll_cnic(struct bnx2 *bp, struct bnx2_napi *bnapi)
-{
-	struct cnic_ops *c_ops;
-
-	if (!bnapi->cnic_present)
-		return;
-
-	rcu_read_lock();
-	c_ops = rcu_dereference(bp->cnic_ops);
-	if (c_ops)
-		bnapi->cnic_tag = c_ops->cnic_handler(bp->cnic_data,
-						      bnapi->status_blk.msi);
-	rcu_read_unlock();
-}
-#endif
-
-static void bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi)
-{
-	struct status_block *sblk = bnapi->status_blk.msi;
-	u32 status_attn_bits = sblk->status_attn_bits;
-	u32 status_attn_bits_ack = sblk->status_attn_bits_ack;
-
-	if ((status_attn_bits & STATUS_ATTN_EVENTS) !=
-	    (status_attn_bits_ack & STATUS_ATTN_EVENTS)) {
-
-		bnx2_phy_int(bp, bnapi);
-
-		/* This is needed to take care of transient status
-		 * during link changes.
-		 */
-		REG_WR(bp, BNX2_HC_COMMAND,
-		       bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
-		REG_RD(bp, BNX2_HC_COMMAND);
-	}
-}
-
-static int bnx2_poll_work(struct bnx2 *bp, struct bnx2_napi *bnapi,
-			  int work_done, int budget)
-{
-	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
-	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
-
-	if (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons)
-		bnx2_tx_int(bp, bnapi, 0);
-
-	if (bnx2_get_hw_rx_cons(bnapi) != rxr->rx_cons)
-		work_done += bnx2_rx_int(bp, bnapi, budget - work_done);
-
-	return work_done;
-}
-
-static int bnx2_poll_msix(struct napi_struct *napi, int budget)
-{
-	struct bnx2_napi *bnapi = container_of(napi, struct bnx2_napi, napi);
-	struct bnx2 *bp = bnapi->bp;
-	int work_done = 0;
-	struct status_block_msix *sblk = bnapi->status_blk.msix;
-
-	while (1) {
-		work_done = bnx2_poll_work(bp, bnapi, work_done, budget);
-		if (unlikely(work_done >= budget))
-			break;
-
-		bnapi->last_status_idx = sblk->status_idx;
-		/* status idx must be read before checking for more work. */
-		rmb();
-		if (likely(!bnx2_has_fast_work(bnapi))) {
-
-			napi_complete(napi);
-			REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
-			       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
-			       bnapi->last_status_idx);
-			break;
-		}
-	}
-	return work_done;
-}
-
-static int bnx2_poll(struct napi_struct *napi, int budget)
-{
-	struct bnx2_napi *bnapi = container_of(napi, struct bnx2_napi, napi);
-	struct bnx2 *bp = bnapi->bp;
-	int work_done = 0;
-	struct status_block *sblk = bnapi->status_blk.msi;
-
-	while (1) {
-		bnx2_poll_link(bp, bnapi);
-
-		work_done = bnx2_poll_work(bp, bnapi, work_done, budget);
-
-#ifdef BCM_CNIC
-		bnx2_poll_cnic(bp, bnapi);
-#endif
-
-		/* bnapi->last_status_idx is used below to tell the hw how
-		 * much work has been processed, so we must read it before
-		 * checking for more work.
-		 */
-		bnapi->last_status_idx = sblk->status_idx;
-
-		if (unlikely(work_done >= budget))
-			break;
-
-		rmb();
-		if (likely(!bnx2_has_work(bnapi))) {
-			napi_complete(napi);
-			if (likely(bp->flags & BNX2_FLAG_USING_MSI_OR_MSIX)) {
-				REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
-				       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
-				       bnapi->last_status_idx);
-				break;
-			}
-			REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
-			       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
-			       BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
-			       bnapi->last_status_idx);
-
-			REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
-			       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
-			       bnapi->last_status_idx);
-			break;
-		}
-	}
-
-	return work_done;
-}
-
-/* Called with rtnl_lock from vlan functions and also netif_tx_lock
- * from set_multicast.
- */
-static void
-bnx2_set_rx_mode(struct net_device *dev)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-	u32 rx_mode, sort_mode;
-	struct netdev_hw_addr *ha;
-	int i;
-
-	if (!netif_running(dev))
-		return;
-
-	spin_lock_bh(&bp->phy_lock);
-
-	rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS |
-				  BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG);
-	sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN;
-	if (!(dev->features & NETIF_F_HW_VLAN_RX) &&
-	     (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
-		rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
-	if (dev->flags & IFF_PROMISC) {
-		/* Promiscuous mode. */
-		rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS;
-		sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN |
-			     BNX2_RPM_SORT_USER0_PROM_VLAN;
-	}
-	else if (dev->flags & IFF_ALLMULTI) {
-		for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
-			REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
-			       0xffffffff);
-        	}
-		sort_mode |= BNX2_RPM_SORT_USER0_MC_EN;
-	}
-	else {
-		/* Accept one or more multicast(s). */
-		u32 mc_filter[NUM_MC_HASH_REGISTERS];
-		u32 regidx;
-		u32 bit;
-		u32 crc;
-
-		memset(mc_filter, 0, 4 * NUM_MC_HASH_REGISTERS);
-
-		netdev_for_each_mc_addr(ha, dev) {
-			crc = ether_crc_le(ETH_ALEN, ha->addr);
-			bit = crc & 0xff;
-			regidx = (bit & 0xe0) >> 5;
-			bit &= 0x1f;
-			mc_filter[regidx] |= (1 << bit);
-		}
-
-		for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
-			REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
-			       mc_filter[i]);
-		}
-
-		sort_mode |= BNX2_RPM_SORT_USER0_MC_HSH_EN;
-	}
-
-	if (netdev_uc_count(dev) > BNX2_MAX_UNICAST_ADDRESSES) {
-		rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS;
-		sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN |
-			     BNX2_RPM_SORT_USER0_PROM_VLAN;
-	} else if (!(dev->flags & IFF_PROMISC)) {
-		/* Add all entries into to the match filter list */
-		i = 0;
-		netdev_for_each_uc_addr(ha, dev) {
-			bnx2_set_mac_addr(bp, ha->addr,
-					  i + BNX2_START_UNICAST_ADDRESS_INDEX);
-			sort_mode |= (1 <<
-				      (i + BNX2_START_UNICAST_ADDRESS_INDEX));
-			i++;
-		}
-
-	}
-
-	if (rx_mode != bp->rx_mode) {
-		bp->rx_mode = rx_mode;
-		REG_WR(bp, BNX2_EMAC_RX_MODE, rx_mode);
-	}
-
-	REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
-	REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode);
-	REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA);
-
-	spin_unlock_bh(&bp->phy_lock);
-}
-
-static int __devinit
-check_fw_section(const struct firmware *fw,
-		 const struct bnx2_fw_file_section *section,
-		 u32 alignment, bool non_empty)
-{
-	u32 offset = be32_to_cpu(section->offset);
-	u32 len = be32_to_cpu(section->len);
-
-	if ((offset == 0 && len != 0) || offset >= fw->size || offset & 3)
-		return -EINVAL;
-	if ((non_empty && len == 0) || len > fw->size - offset ||
-	    len & (alignment - 1))
-		return -EINVAL;
-	return 0;
-}
-
-static int __devinit
-check_mips_fw_entry(const struct firmware *fw,
-		    const struct bnx2_mips_fw_file_entry *entry)
-{
-	if (check_fw_section(fw, &entry->text, 4, true) ||
-	    check_fw_section(fw, &entry->data, 4, false) ||
-	    check_fw_section(fw, &entry->rodata, 4, false))
-		return -EINVAL;
-	return 0;
-}
-
-static int __devinit
-bnx2_reject_firmware(struct bnx2 *bp)
-{
-	const char *mips_fw_file, *rv2p_fw_file;
-	const struct bnx2_mips_fw_file *mips_fw;
-	const struct bnx2_rv2p_fw_file *rv2p_fw;
-	int rc;
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		mips_fw_file = FW_MIPS_FILE_09;
-		if ((CHIP_ID(bp) == CHIP_ID_5709_A0) ||
-		    (CHIP_ID(bp) == CHIP_ID_5709_A1))
-			rv2p_fw_file = FW_RV2P_FILE_09_Ax;
-		else
-			rv2p_fw_file = FW_RV2P_FILE_09;
-	} else {
-		mips_fw_file = FW_MIPS_FILE_06;
-		rv2p_fw_file = FW_RV2P_FILE_06;
-	}
-
-	rc = reject_firmware(&bp->mips_firmware, mips_fw_file, &bp->pdev->dev);
-	if (rc) {
-		pr_err("Can't load firmware file \"%s\"\n", mips_fw_file);
-		return rc;
-	}
-
-	rc = reject_firmware(&bp->rv2p_firmware, rv2p_fw_file, &bp->pdev->dev);
-	if (rc) {
-		pr_err("Can't load firmware file \"%s\"\n", rv2p_fw_file);
-		return rc;
-	}
-	mips_fw = (const struct bnx2_mips_fw_file *) bp->mips_firmware->data;
-	rv2p_fw = (const struct bnx2_rv2p_fw_file *) bp->rv2p_firmware->data;
-	if (bp->mips_firmware->size < sizeof(*mips_fw) ||
-	    check_mips_fw_entry(bp->mips_firmware, &mips_fw->com) ||
-	    check_mips_fw_entry(bp->mips_firmware, &mips_fw->cp) ||
-	    check_mips_fw_entry(bp->mips_firmware, &mips_fw->rxp) ||
-	    check_mips_fw_entry(bp->mips_firmware, &mips_fw->tpat) ||
-	    check_mips_fw_entry(bp->mips_firmware, &mips_fw->txp)) {
-		pr_err("Firmware file \"%s\" is invalid\n", mips_fw_file);
-		return -EINVAL;
-	}
-	if (bp->rv2p_firmware->size < sizeof(*rv2p_fw) ||
-	    check_fw_section(bp->rv2p_firmware, &rv2p_fw->proc1.rv2p, 8, true) ||
-	    check_fw_section(bp->rv2p_firmware, &rv2p_fw->proc2.rv2p, 8, true)) {
-		pr_err("Firmware file \"%s\" is invalid\n", rv2p_fw_file);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static u32
-rv2p_fw_fixup(u32 rv2p_proc, int idx, u32 loc, u32 rv2p_code)
-{
-	switch (idx) {
-	case RV2P_P1_FIXUP_PAGE_SIZE_IDX:
-		rv2p_code &= ~RV2P_BD_PAGE_SIZE_MSK;
-		rv2p_code |= RV2P_BD_PAGE_SIZE;
-		break;
-	}
-	return rv2p_code;
-}
-
-static int
-load_rv2p_fw(struct bnx2 *bp, u32 rv2p_proc,
-	     const struct bnx2_rv2p_fw_file_entry *fw_entry)
-{
-	u32 rv2p_code_len, file_offset;
-	__be32 *rv2p_code;
-	int i;
-	u32 val, cmd, addr;
-
-	rv2p_code_len = be32_to_cpu(fw_entry->rv2p.len);
-	file_offset = be32_to_cpu(fw_entry->rv2p.offset);
-
-	rv2p_code = (__be32 *)(bp->rv2p_firmware->data + file_offset);
-
-	if (rv2p_proc == RV2P_PROC1) {
-		cmd = BNX2_RV2P_PROC1_ADDR_CMD_RDWR;
-		addr = BNX2_RV2P_PROC1_ADDR_CMD;
-	} else {
-		cmd = BNX2_RV2P_PROC2_ADDR_CMD_RDWR;
-		addr = BNX2_RV2P_PROC2_ADDR_CMD;
-	}
-
-	for (i = 0; i < rv2p_code_len; i += 8) {
-		REG_WR(bp, BNX2_RV2P_INSTR_HIGH, be32_to_cpu(*rv2p_code));
-		rv2p_code++;
-		REG_WR(bp, BNX2_RV2P_INSTR_LOW, be32_to_cpu(*rv2p_code));
-		rv2p_code++;
-
-		val = (i / 8) | cmd;
-		REG_WR(bp, addr, val);
-	}
-
-	rv2p_code = (__be32 *)(bp->rv2p_firmware->data + file_offset);
-	for (i = 0; i < 8; i++) {
-		u32 loc, code;
-
-		loc = be32_to_cpu(fw_entry->fixup[i]);
-		if (loc && ((loc * 4) < rv2p_code_len)) {
-			code = be32_to_cpu(*(rv2p_code + loc - 1));
-			REG_WR(bp, BNX2_RV2P_INSTR_HIGH, code);
-			code = be32_to_cpu(*(rv2p_code + loc));
-			code = rv2p_fw_fixup(rv2p_proc, i, loc, code);
-			REG_WR(bp, BNX2_RV2P_INSTR_LOW, code);
-
-			val = (loc / 2) | cmd;
-			REG_WR(bp, addr, val);
-		}
-	}
-
-	/* Reset the processor, un-stall is done later. */
-	if (rv2p_proc == RV2P_PROC1) {
-		REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC1_RESET);
-	}
-	else {
-		REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC2_RESET);
-	}
-
-	return 0;
-}
-
-static int
-load_cpu_fw(struct bnx2 *bp, const struct cpu_reg *cpu_reg,
-	    const struct bnx2_mips_fw_file_entry *fw_entry)
-{
-	u32 addr, len, file_offset;
-	__be32 *data;
-	u32 offset;
-	u32 val;
-
-	/* Halt the CPU. */
-	val = bnx2_reg_rd_ind(bp, cpu_reg->mode);
-	val |= cpu_reg->mode_value_halt;
-	bnx2_reg_wr_ind(bp, cpu_reg->mode, val);
-	bnx2_reg_wr_ind(bp, cpu_reg->state, cpu_reg->state_value_clear);
-
-	/* Load the Text area. */
-	addr = be32_to_cpu(fw_entry->text.addr);
-	len = be32_to_cpu(fw_entry->text.len);
-	file_offset = be32_to_cpu(fw_entry->text.offset);
-	data = (__be32 *)(bp->mips_firmware->data + file_offset);
-
-	offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base);
-	if (len) {
-		int j;
-
-		for (j = 0; j < (len / 4); j++, offset += 4)
-			bnx2_reg_wr_ind(bp, offset, be32_to_cpu(data[j]));
-	}
-
-	/* Load the Data area. */
-	addr = be32_to_cpu(fw_entry->data.addr);
-	len = be32_to_cpu(fw_entry->data.len);
-	file_offset = be32_to_cpu(fw_entry->data.offset);
-	data = (__be32 *)(bp->mips_firmware->data + file_offset);
-
-	offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base);
-	if (len) {
-		int j;
-
-		for (j = 0; j < (len / 4); j++, offset += 4)
-			bnx2_reg_wr_ind(bp, offset, be32_to_cpu(data[j]));
-	}
-
-	/* Load the Read-Only area. */
-	addr = be32_to_cpu(fw_entry->rodata.addr);
-	len = be32_to_cpu(fw_entry->rodata.len);
-	file_offset = be32_to_cpu(fw_entry->rodata.offset);
-	data = (__be32 *)(bp->mips_firmware->data + file_offset);
-
-	offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base);
-	if (len) {
-		int j;
-
-		for (j = 0; j < (len / 4); j++, offset += 4)
-			bnx2_reg_wr_ind(bp, offset, be32_to_cpu(data[j]));
-	}
-
-	/* Clear the pre-fetch instruction. */
-	bnx2_reg_wr_ind(bp, cpu_reg->inst, 0);
-
-	val = be32_to_cpu(fw_entry->start_addr);
-	bnx2_reg_wr_ind(bp, cpu_reg->pc, val);
-
-	/* Start the CPU. */
-	val = bnx2_reg_rd_ind(bp, cpu_reg->mode);
-	val &= ~cpu_reg->mode_value_halt;
-	bnx2_reg_wr_ind(bp, cpu_reg->state, cpu_reg->state_value_clear);
-	bnx2_reg_wr_ind(bp, cpu_reg->mode, val);
-
-	return 0;
-}
-
-static int
-bnx2_init_cpus(struct bnx2 *bp)
-{
-	const struct bnx2_mips_fw_file *mips_fw =
-		(const struct bnx2_mips_fw_file *) bp->mips_firmware->data;
-	const struct bnx2_rv2p_fw_file *rv2p_fw =
-		(const struct bnx2_rv2p_fw_file *) bp->rv2p_firmware->data;
-	int rc;
-
-	/* Initialize the RV2P processor. */
-	load_rv2p_fw(bp, RV2P_PROC1, &rv2p_fw->proc1);
-	load_rv2p_fw(bp, RV2P_PROC2, &rv2p_fw->proc2);
-
-	/* Initialize the RX Processor. */
-	rc = load_cpu_fw(bp, &cpu_reg_rxp, &mips_fw->rxp);
-	if (rc)
-		goto init_cpu_err;
-
-	/* Initialize the TX Processor. */
-	rc = load_cpu_fw(bp, &cpu_reg_txp, &mips_fw->txp);
-	if (rc)
-		goto init_cpu_err;
-
-	/* Initialize the TX Patch-up Processor. */
-	rc = load_cpu_fw(bp, &cpu_reg_tpat, &mips_fw->tpat);
-	if (rc)
-		goto init_cpu_err;
-
-	/* Initialize the Completion Processor. */
-	rc = load_cpu_fw(bp, &cpu_reg_com, &mips_fw->com);
-	if (rc)
-		goto init_cpu_err;
-
-	/* Initialize the Command Processor. */
-	rc = load_cpu_fw(bp, &cpu_reg_cp, &mips_fw->cp);
-
-init_cpu_err:
-	return rc;
-}
-
-static int
-bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
-{
-	u16 pmcsr;
-
-	pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr);
-
-	switch (state) {
-	case PCI_D0: {
-		u32 val;
-
-		pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
-			(pmcsr & ~PCI_PM_CTRL_STATE_MASK) |
-			PCI_PM_CTRL_PME_STATUS);
-
-		if (pmcsr & PCI_PM_CTRL_STATE_MASK)
-			/* delay required during transition out of D3hot */
-			msleep(20);
-
-		val = REG_RD(bp, BNX2_EMAC_MODE);
-		val |= BNX2_EMAC_MODE_MPKT_RCVD | BNX2_EMAC_MODE_ACPI_RCVD;
-		val &= ~BNX2_EMAC_MODE_MPKT;
-		REG_WR(bp, BNX2_EMAC_MODE, val);
-
-		val = REG_RD(bp, BNX2_RPM_CONFIG);
-		val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
-		REG_WR(bp, BNX2_RPM_CONFIG, val);
-		break;
-	}
-	case PCI_D3hot: {
-		int i;
-		u32 val, wol_msg;
-
-		if (bp->wol) {
-			u32 advertising;
-			u8 autoneg;
-
-			autoneg = bp->autoneg;
-			advertising = bp->advertising;
-
-			if (bp->phy_port == PORT_TP) {
-				bp->autoneg = AUTONEG_SPEED;
-				bp->advertising = ADVERTISED_10baseT_Half |
-					ADVERTISED_10baseT_Full |
-					ADVERTISED_100baseT_Half |
-					ADVERTISED_100baseT_Full |
-					ADVERTISED_Autoneg;
-			}
-
-			spin_lock_bh(&bp->phy_lock);
-			bnx2_setup_phy(bp, bp->phy_port);
-			spin_unlock_bh(&bp->phy_lock);
-
-			bp->autoneg = autoneg;
-			bp->advertising = advertising;
-
-			bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0);
-
-			val = REG_RD(bp, BNX2_EMAC_MODE);
-
-			/* Enable port mode. */
-			val &= ~BNX2_EMAC_MODE_PORT;
-			val |= BNX2_EMAC_MODE_MPKT_RCVD |
-			       BNX2_EMAC_MODE_ACPI_RCVD |
-			       BNX2_EMAC_MODE_MPKT;
-			if (bp->phy_port == PORT_TP)
-				val |= BNX2_EMAC_MODE_PORT_MII;
-			else {
-				val |= BNX2_EMAC_MODE_PORT_GMII;
-				if (bp->line_speed == SPEED_2500)
-					val |= BNX2_EMAC_MODE_25G_MODE;
-			}
-
-			REG_WR(bp, BNX2_EMAC_MODE, val);
-
-			/* receive all multicast */
-			for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
-				REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
-				       0xffffffff);
-			}
-			REG_WR(bp, BNX2_EMAC_RX_MODE,
-			       BNX2_EMAC_RX_MODE_SORT_MODE);
-
-			val = 1 | BNX2_RPM_SORT_USER0_BC_EN |
-			      BNX2_RPM_SORT_USER0_MC_EN;
-			REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
-			REG_WR(bp, BNX2_RPM_SORT_USER0, val);
-			REG_WR(bp, BNX2_RPM_SORT_USER0, val |
-			       BNX2_RPM_SORT_USER0_ENA);
-
-			/* Need to enable EMAC and RPM for WOL. */
-			REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
-			       BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE |
-			       BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE |
-			       BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE);
-
-			val = REG_RD(bp, BNX2_RPM_CONFIG);
-			val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
-			REG_WR(bp, BNX2_RPM_CONFIG, val);
-
-			wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
-		}
-		else {
-			wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
-		}
-
-		if (!(bp->flags & BNX2_FLAG_NO_WOL))
-			bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg,
-				     1, 0);
-
-		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
-		if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
-		    (CHIP_ID(bp) == CHIP_ID_5706_A1)) {
-
-			if (bp->wol)
-				pmcsr |= 3;
-		}
-		else {
-			pmcsr |= 3;
-		}
-		if (bp->wol) {
-			pmcsr |= PCI_PM_CTRL_PME_ENABLE;
-		}
-		pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
-				      pmcsr);
-
-		/* No more memory access after this point until
-		 * device is brought back to D0.
-		 */
-		udelay(50);
-		break;
-	}
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int
-bnx2_acquire_nvram_lock(struct bnx2 *bp)
-{
-	u32 val;
-	int j;
-
-	/* Request access to the flash interface. */
-	REG_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_SET2);
-	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
-		val = REG_RD(bp, BNX2_NVM_SW_ARB);
-		if (val & BNX2_NVM_SW_ARB_ARB_ARB2)
-			break;
-
-		udelay(5);
-	}
-
-	if (j >= NVRAM_TIMEOUT_COUNT)
-		return -EBUSY;
-
-	return 0;
-}
-
-static int
-bnx2_release_nvram_lock(struct bnx2 *bp)
-{
-	int j;
-	u32 val;
-
-	/* Relinquish nvram interface. */
-	REG_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_CLR2);
-
-	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
-		val = REG_RD(bp, BNX2_NVM_SW_ARB);
-		if (!(val & BNX2_NVM_SW_ARB_ARB_ARB2))
-			break;
-
-		udelay(5);
-	}
-
-	if (j >= NVRAM_TIMEOUT_COUNT)
-		return -EBUSY;
-
-	return 0;
-}
-
-
-static int
-bnx2_enable_nvram_write(struct bnx2 *bp)
-{
-	u32 val;
-
-	val = REG_RD(bp, BNX2_MISC_CFG);
-	REG_WR(bp, BNX2_MISC_CFG, val | BNX2_MISC_CFG_NVM_WR_EN_PCI);
-
-	if (bp->flash_info->flags & BNX2_NV_WREN) {
-		int j;
-
-		REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
-		REG_WR(bp, BNX2_NVM_COMMAND,
-		       BNX2_NVM_COMMAND_WREN | BNX2_NVM_COMMAND_DOIT);
-
-		for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
-			udelay(5);
-
-			val = REG_RD(bp, BNX2_NVM_COMMAND);
-			if (val & BNX2_NVM_COMMAND_DONE)
-				break;
-		}
-
-		if (j >= NVRAM_TIMEOUT_COUNT)
-			return -EBUSY;
-	}
-	return 0;
-}
-
-static void
-bnx2_disable_nvram_write(struct bnx2 *bp)
-{
-	u32 val;
-
-	val = REG_RD(bp, BNX2_MISC_CFG);
-	REG_WR(bp, BNX2_MISC_CFG, val & ~BNX2_MISC_CFG_NVM_WR_EN);
-}
-
-
-static void
-bnx2_enable_nvram_access(struct bnx2 *bp)
-{
-	u32 val;
-
-	val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE);
-	/* Enable both bits, even on read. */
-	REG_WR(bp, BNX2_NVM_ACCESS_ENABLE,
-	       val | BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN);
-}
-
-static void
-bnx2_disable_nvram_access(struct bnx2 *bp)
-{
-	u32 val;
-
-	val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE);
-	/* Disable both bits, even after read. */
-	REG_WR(bp, BNX2_NVM_ACCESS_ENABLE,
-		val & ~(BNX2_NVM_ACCESS_ENABLE_EN |
-			BNX2_NVM_ACCESS_ENABLE_WR_EN));
-}
-
-static int
-bnx2_nvram_erase_page(struct bnx2 *bp, u32 offset)
-{
-	u32 cmd;
-	int j;
-
-	if (bp->flash_info->flags & BNX2_NV_BUFFERED)
-		/* Buffered flash, no erase needed */
-		return 0;
-
-	/* Build an erase command */
-	cmd = BNX2_NVM_COMMAND_ERASE | BNX2_NVM_COMMAND_WR |
-	      BNX2_NVM_COMMAND_DOIT;
-
-	/* Need to clear DONE bit separately. */
-	REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
-
-	/* Address of the NVRAM to read from. */
-	REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
-
-	/* Issue an erase command. */
-	REG_WR(bp, BNX2_NVM_COMMAND, cmd);
-
-	/* Wait for completion. */
-	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
-		u32 val;
-
-		udelay(5);
-
-		val = REG_RD(bp, BNX2_NVM_COMMAND);
-		if (val & BNX2_NVM_COMMAND_DONE)
-			break;
-	}
-
-	if (j >= NVRAM_TIMEOUT_COUNT)
-		return -EBUSY;
-
-	return 0;
-}
-
-static int
-bnx2_nvram_read_dword(struct bnx2 *bp, u32 offset, u8 *ret_val, u32 cmd_flags)
-{
-	u32 cmd;
-	int j;
-
-	/* Build the command word. */
-	cmd = BNX2_NVM_COMMAND_DOIT | cmd_flags;
-
-	/* Calculate an offset of a buffered flash, not needed for 5709. */
-	if (bp->flash_info->flags & BNX2_NV_TRANSLATE) {
-		offset = ((offset / bp->flash_info->page_size) <<
-			   bp->flash_info->page_bits) +
-			  (offset % bp->flash_info->page_size);
-	}
-
-	/* Need to clear DONE bit separately. */
-	REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
-
-	/* Address of the NVRAM to read from. */
-	REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
-
-	/* Issue a read command. */
-	REG_WR(bp, BNX2_NVM_COMMAND, cmd);
-
-	/* Wait for completion. */
-	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
-		u32 val;
-
-		udelay(5);
-
-		val = REG_RD(bp, BNX2_NVM_COMMAND);
-		if (val & BNX2_NVM_COMMAND_DONE) {
-			__be32 v = cpu_to_be32(REG_RD(bp, BNX2_NVM_READ));
-			memcpy(ret_val, &v, 4);
-			break;
-		}
-	}
-	if (j >= NVRAM_TIMEOUT_COUNT)
-		return -EBUSY;
-
-	return 0;
-}
-
-
-static int
-bnx2_nvram_write_dword(struct bnx2 *bp, u32 offset, u8 *val, u32 cmd_flags)
-{
-	u32 cmd;
-	__be32 val32;
-	int j;
-
-	/* Build the command word. */
-	cmd = BNX2_NVM_COMMAND_DOIT | BNX2_NVM_COMMAND_WR | cmd_flags;
-
-	/* Calculate an offset of a buffered flash, not needed for 5709. */
-	if (bp->flash_info->flags & BNX2_NV_TRANSLATE) {
-		offset = ((offset / bp->flash_info->page_size) <<
-			  bp->flash_info->page_bits) +
-			 (offset % bp->flash_info->page_size);
-	}
-
-	/* Need to clear DONE bit separately. */
-	REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
-
-	memcpy(&val32, val, 4);
-
-	/* Write the data. */
-	REG_WR(bp, BNX2_NVM_WRITE, be32_to_cpu(val32));
-
-	/* Address of the NVRAM to write to. */
-	REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
-
-	/* Issue the write command. */
-	REG_WR(bp, BNX2_NVM_COMMAND, cmd);
-
-	/* Wait for completion. */
-	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
-		udelay(5);
-
-		if (REG_RD(bp, BNX2_NVM_COMMAND) & BNX2_NVM_COMMAND_DONE)
-			break;
-	}
-	if (j >= NVRAM_TIMEOUT_COUNT)
-		return -EBUSY;
-
-	return 0;
-}
-
-static int
-bnx2_init_nvram(struct bnx2 *bp)
-{
-	u32 val;
-	int j, entry_count, rc = 0;
-	const struct flash_spec *flash;
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		bp->flash_info = &flash_5709;
-		goto get_flash_size;
-	}
-
-	/* Determine the selected interface. */
-	val = REG_RD(bp, BNX2_NVM_CFG1);
-
-	entry_count = ARRAY_SIZE(flash_table);
-
-	if (val & 0x40000000) {
-
-		/* Flash interface has been reconfigured */
-		for (j = 0, flash = &flash_table[0]; j < entry_count;
-		     j++, flash++) {
-			if ((val & FLASH_BACKUP_STRAP_MASK) ==
-			    (flash->config1 & FLASH_BACKUP_STRAP_MASK)) {
-				bp->flash_info = flash;
-				break;
-			}
-		}
-	}
-	else {
-		u32 mask;
-		/* Not yet been reconfigured */
-
-		if (val & (1 << 23))
-			mask = FLASH_BACKUP_STRAP_MASK;
-		else
-			mask = FLASH_STRAP_MASK;
-
-		for (j = 0, flash = &flash_table[0]; j < entry_count;
-			j++, flash++) {
-
-			if ((val & mask) == (flash->strapping & mask)) {
-				bp->flash_info = flash;
-
-				/* Request access to the flash interface. */
-				if ((rc = bnx2_acquire_nvram_lock(bp)) != 0)
-					return rc;
-
-				/* Enable access to flash interface */
-				bnx2_enable_nvram_access(bp);
-
-				/* Reconfigure the flash interface */
-				REG_WR(bp, BNX2_NVM_CFG1, flash->config1);
-				REG_WR(bp, BNX2_NVM_CFG2, flash->config2);
-				REG_WR(bp, BNX2_NVM_CFG3, flash->config3);
-				REG_WR(bp, BNX2_NVM_WRITE1, flash->write1);
-
-				/* Disable access to flash interface */
-				bnx2_disable_nvram_access(bp);
-				bnx2_release_nvram_lock(bp);
-
-				break;
-			}
-		}
-	} /* if (val & 0x40000000) */
-
-	if (j == entry_count) {
-		bp->flash_info = NULL;
-		pr_alert("Unknown flash/EEPROM type\n");
-		return -ENODEV;
-	}
-
-get_flash_size:
-	val = bnx2_shmem_rd(bp, BNX2_SHARED_HW_CFG_CONFIG2);
-	val &= BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK;
-	if (val)
-		bp->flash_size = val;
-	else
-		bp->flash_size = bp->flash_info->total_size;
-
-	return rc;
-}
-
-static int
-bnx2_nvram_read(struct bnx2 *bp, u32 offset, u8 *ret_buf,
-		int buf_size)
-{
-	int rc = 0;
-	u32 cmd_flags, offset32, len32, extra;
-
-	if (buf_size == 0)
-		return 0;
-
-	/* Request access to the flash interface. */
-	if ((rc = bnx2_acquire_nvram_lock(bp)) != 0)
-		return rc;
-
-	/* Enable access to flash interface */
-	bnx2_enable_nvram_access(bp);
-
-	len32 = buf_size;
-	offset32 = offset;
-	extra = 0;
-
-	cmd_flags = 0;
-
-	if (offset32 & 3) {
-		u8 buf[4];
-		u32 pre_len;
-
-		offset32 &= ~3;
-		pre_len = 4 - (offset & 3);
-
-		if (pre_len >= len32) {
-			pre_len = len32;
-			cmd_flags = BNX2_NVM_COMMAND_FIRST |
-				    BNX2_NVM_COMMAND_LAST;
-		}
-		else {
-			cmd_flags = BNX2_NVM_COMMAND_FIRST;
-		}
-
-		rc = bnx2_nvram_read_dword(bp, offset32, buf, cmd_flags);
-
-		if (rc)
-			return rc;
-
-		memcpy(ret_buf, buf + (offset & 3), pre_len);
-
-		offset32 += 4;
-		ret_buf += pre_len;
-		len32 -= pre_len;
-	}
-	if (len32 & 3) {
-		extra = 4 - (len32 & 3);
-		len32 = (len32 + 4) & ~3;
-	}
-
-	if (len32 == 4) {
-		u8 buf[4];
-
-		if (cmd_flags)
-			cmd_flags = BNX2_NVM_COMMAND_LAST;
-		else
-			cmd_flags = BNX2_NVM_COMMAND_FIRST |
-				    BNX2_NVM_COMMAND_LAST;
-
-		rc = bnx2_nvram_read_dword(bp, offset32, buf, cmd_flags);
-
-		memcpy(ret_buf, buf, 4 - extra);
-	}
-	else if (len32 > 0) {
-		u8 buf[4];
-
-		/* Read the first word. */
-		if (cmd_flags)
-			cmd_flags = 0;
-		else
-			cmd_flags = BNX2_NVM_COMMAND_FIRST;
-
-		rc = bnx2_nvram_read_dword(bp, offset32, ret_buf, cmd_flags);
-
-		/* Advance to the next dword. */
-		offset32 += 4;
-		ret_buf += 4;
-		len32 -= 4;
-
-		while (len32 > 4 && rc == 0) {
-			rc = bnx2_nvram_read_dword(bp, offset32, ret_buf, 0);
-
-			/* Advance to the next dword. */
-			offset32 += 4;
-			ret_buf += 4;
-			len32 -= 4;
-		}
-
-		if (rc)
-			return rc;
-
-		cmd_flags = BNX2_NVM_COMMAND_LAST;
-		rc = bnx2_nvram_read_dword(bp, offset32, buf, cmd_flags);
-
-		memcpy(ret_buf, buf, 4 - extra);
-	}
-
-	/* Disable access to flash interface */
-	bnx2_disable_nvram_access(bp);
-
-	bnx2_release_nvram_lock(bp);
-
-	return rc;
-}
-
-static int
-bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
-		int buf_size)
-{
-	u32 written, offset32, len32;
-	u8 *buf, start[4], end[4], *align_buf = NULL, *flash_buffer = NULL;
-	int rc = 0;
-	int align_start, align_end;
-
-	buf = data_buf;
-	offset32 = offset;
-	len32 = buf_size;
-	align_start = align_end = 0;
-
-	if ((align_start = (offset32 & 3))) {
-		offset32 &= ~3;
-		len32 += align_start;
-		if (len32 < 4)
-			len32 = 4;
-		if ((rc = bnx2_nvram_read(bp, offset32, start, 4)))
-			return rc;
-	}
-
-	if (len32 & 3) {
-		align_end = 4 - (len32 & 3);
-		len32 += align_end;
-		if ((rc = bnx2_nvram_read(bp, offset32 + len32 - 4, end, 4)))
-			return rc;
-	}
-
-	if (align_start || align_end) {
-		align_buf = kmalloc(len32, GFP_KERNEL);
-		if (align_buf == NULL)
-			return -ENOMEM;
-		if (align_start) {
-			memcpy(align_buf, start, 4);
-		}
-		if (align_end) {
-			memcpy(align_buf + len32 - 4, end, 4);
-		}
-		memcpy(align_buf + align_start, data_buf, buf_size);
-		buf = align_buf;
-	}
-
-	if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) {
-		flash_buffer = kmalloc(264, GFP_KERNEL);
-		if (flash_buffer == NULL) {
-			rc = -ENOMEM;
-			goto nvram_write_end;
-		}
-	}
-
-	written = 0;
-	while ((written < len32) && (rc == 0)) {
-		u32 page_start, page_end, data_start, data_end;
-		u32 addr, cmd_flags;
-		int i;
-
-	        /* Find the page_start addr */
-		page_start = offset32 + written;
-		page_start -= (page_start % bp->flash_info->page_size);
-		/* Find the page_end addr */
-		page_end = page_start + bp->flash_info->page_size;
-		/* Find the data_start addr */
-		data_start = (written == 0) ? offset32 : page_start;
-		/* Find the data_end addr */
-		data_end = (page_end > offset32 + len32) ?
-			(offset32 + len32) : page_end;
-
-		/* Request access to the flash interface. */
-		if ((rc = bnx2_acquire_nvram_lock(bp)) != 0)
-			goto nvram_write_end;
-
-		/* Enable access to flash interface */
-		bnx2_enable_nvram_access(bp);
-
-		cmd_flags = BNX2_NVM_COMMAND_FIRST;
-		if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) {
-			int j;
-
-			/* Read the whole page into the buffer
-			 * (non-buffer flash only) */
-			for (j = 0; j < bp->flash_info->page_size; j += 4) {
-				if (j == (bp->flash_info->page_size - 4)) {
-					cmd_flags |= BNX2_NVM_COMMAND_LAST;
-				}
-				rc = bnx2_nvram_read_dword(bp,
-					page_start + j,
-					&flash_buffer[j],
-					cmd_flags);
-
-				if (rc)
-					goto nvram_write_end;
-
-				cmd_flags = 0;
-			}
-		}
-
-		/* Enable writes to flash interface (unlock write-protect) */
-		if ((rc = bnx2_enable_nvram_write(bp)) != 0)
-			goto nvram_write_end;
-
-		/* Loop to write back the buffer data from page_start to
-		 * data_start */
-		i = 0;
-		if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) {
-			/* Erase the page */
-			if ((rc = bnx2_nvram_erase_page(bp, page_start)) != 0)
-				goto nvram_write_end;
-
-			/* Re-enable the write again for the actual write */
-			bnx2_enable_nvram_write(bp);
-
-			for (addr = page_start; addr < data_start;
-				addr += 4, i += 4) {
-
-				rc = bnx2_nvram_write_dword(bp, addr,
-					&flash_buffer[i], cmd_flags);
-
-				if (rc != 0)
-					goto nvram_write_end;
-
-				cmd_flags = 0;
-			}
-		}
-
-		/* Loop to write the new data from data_start to data_end */
-		for (addr = data_start; addr < data_end; addr += 4, i += 4) {
-			if ((addr == page_end - 4) ||
-				((bp->flash_info->flags & BNX2_NV_BUFFERED) &&
-				 (addr == data_end - 4))) {
-
-				cmd_flags |= BNX2_NVM_COMMAND_LAST;
-			}
-			rc = bnx2_nvram_write_dword(bp, addr, buf,
-				cmd_flags);
-
-			if (rc != 0)
-				goto nvram_write_end;
-
-			cmd_flags = 0;
-			buf += 4;
-		}
-
-		/* Loop to write back the buffer data from data_end
-		 * to page_end */
-		if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) {
-			for (addr = data_end; addr < page_end;
-				addr += 4, i += 4) {
-
-				if (addr == page_end-4) {
-					cmd_flags = BNX2_NVM_COMMAND_LAST;
-                		}
-				rc = bnx2_nvram_write_dword(bp, addr,
-					&flash_buffer[i], cmd_flags);
-
-				if (rc != 0)
-					goto nvram_write_end;
-
-				cmd_flags = 0;
-			}
-		}
-
-		/* Disable writes to flash interface (lock write-protect) */
-		bnx2_disable_nvram_write(bp);
-
-		/* Disable access to flash interface */
-		bnx2_disable_nvram_access(bp);
-		bnx2_release_nvram_lock(bp);
-
-		/* Increment written */
-		written += data_end - data_start;
-	}
-
-nvram_write_end:
-	kfree(flash_buffer);
-	kfree(align_buf);
-	return rc;
-}
-
-static void
-bnx2_init_fw_cap(struct bnx2 *bp)
-{
-	u32 val, sig = 0;
-
-	bp->phy_flags &= ~BNX2_PHY_FLAG_REMOTE_PHY_CAP;
-	bp->flags &= ~BNX2_FLAG_CAN_KEEP_VLAN;
-
-	if (!(bp->flags & BNX2_FLAG_ASF_ENABLE))
-		bp->flags |= BNX2_FLAG_CAN_KEEP_VLAN;
-
-	val = bnx2_shmem_rd(bp, BNX2_FW_CAP_MB);
-	if ((val & BNX2_FW_CAP_SIGNATURE_MASK) != BNX2_FW_CAP_SIGNATURE)
-		return;
-
-	if ((val & BNX2_FW_CAP_CAN_KEEP_VLAN) == BNX2_FW_CAP_CAN_KEEP_VLAN) {
-		bp->flags |= BNX2_FLAG_CAN_KEEP_VLAN;
-		sig |= BNX2_DRV_ACK_CAP_SIGNATURE | BNX2_FW_CAP_CAN_KEEP_VLAN;
-	}
-
-	if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
-	    (val & BNX2_FW_CAP_REMOTE_PHY_CAPABLE)) {
-		u32 link;
-
-		bp->phy_flags |= BNX2_PHY_FLAG_REMOTE_PHY_CAP;
-
-		link = bnx2_shmem_rd(bp, BNX2_LINK_STATUS);
-		if (link & BNX2_LINK_STATUS_SERDES_LINK)
-			bp->phy_port = PORT_FIBRE;
-		else
-			bp->phy_port = PORT_TP;
-
-		sig |= BNX2_DRV_ACK_CAP_SIGNATURE |
-		       BNX2_FW_CAP_REMOTE_PHY_CAPABLE;
-	}
-
-	if (netif_running(bp->dev) && sig)
-		bnx2_shmem_wr(bp, BNX2_DRV_ACK_CAP_MB, sig);
-}
-
-static void
-bnx2_setup_msix_tbl(struct bnx2 *bp)
-{
-	REG_WR(bp, BNX2_PCI_GRC_WINDOW_ADDR, BNX2_PCI_GRC_WINDOW_ADDR_SEP_WIN);
-
-	REG_WR(bp, BNX2_PCI_GRC_WINDOW2_ADDR, BNX2_MSIX_TABLE_ADDR);
-	REG_WR(bp, BNX2_PCI_GRC_WINDOW3_ADDR, BNX2_MSIX_PBA_ADDR);
-}
-
-static int
-bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
-{
-	u32 val;
-	int i, rc = 0;
-	u8 old_port;
-
-	/* Wait for the current PCI transaction to complete before
-	 * issuing a reset. */
-	if ((CHIP_NUM(bp) == CHIP_NUM_5706) ||
-	    (CHIP_NUM(bp) == CHIP_NUM_5708)) {
-		REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS,
-		       BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
-		       BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
-		       BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
-		       BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
-		val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS);
-		udelay(5);
-	} else {  /* 5709 */
-		val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
-		val &= ~BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE;
-		REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
-		val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
-
-		for (i = 0; i < 100; i++) {
-			msleep(1);
-			val = REG_RD(bp, BNX2_PCICFG_DEVICE_CONTROL);
-			if (!(val & BNX2_PCICFG_DEVICE_STATUS_NO_PEND))
-				break;
-		}
-	}
-
-	/* Wait for the firmware to tell us it is ok to issue a reset. */
-	bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code, 1, 1);
-
-	/* Deposit a driver reset signature so the firmware knows that
-	 * this is a soft reset. */
-	bnx2_shmem_wr(bp, BNX2_DRV_RESET_SIGNATURE,
-		      BNX2_DRV_RESET_SIGNATURE_MAGIC);
-
-	/* Do a dummy read to force the chip to complete all current transaction
-	 * before we issue a reset. */
-	val = REG_RD(bp, BNX2_MISC_ID);
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		REG_WR(bp, BNX2_MISC_COMMAND, BNX2_MISC_COMMAND_SW_RESET);
-		REG_RD(bp, BNX2_MISC_COMMAND);
-		udelay(5);
-
-		val = BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
-		      BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
-
-		REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
-
-	} else {
-		val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
-		      BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
-		      BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
-
-		/* Chip reset. */
-		REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
-
-		/* Reading back any register after chip reset will hang the
-		 * bus on 5706 A0 and A1.  The msleep below provides plenty
-		 * of margin for write posting.
-		 */
-		if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
-		    (CHIP_ID(bp) == CHIP_ID_5706_A1))
-			msleep(20);
-
-		/* Reset takes approximate 30 usec */
-		for (i = 0; i < 10; i++) {
-			val = REG_RD(bp, BNX2_PCICFG_MISC_CONFIG);
-			if ((val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
-				    BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0)
-				break;
-			udelay(10);
-		}
-
-		if (val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
-			   BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) {
-			pr_err("Chip reset did not complete\n");
-			return -EBUSY;
-		}
-	}
-
-	/* Make sure byte swapping is properly configured. */
-	val = REG_RD(bp, BNX2_PCI_SWAP_DIAG0);
-	if (val != 0x01020304) {
-		pr_err("Chip not in correct endian mode\n");
-		return -ENODEV;
-	}
-
-	/* Wait for the firmware to finish its initialization. */
-	rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT1 | reset_code, 1, 0);
-	if (rc)
-		return rc;
-
-	spin_lock_bh(&bp->phy_lock);
-	old_port = bp->phy_port;
-	bnx2_init_fw_cap(bp);
-	if ((bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) &&
-	    old_port != bp->phy_port)
-		bnx2_set_default_remote_link(bp);
-	spin_unlock_bh(&bp->phy_lock);
-
-	if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
-		/* Adjust the voltage regular to two steps lower.  The default
-		 * of this register is 0x0000000e. */
-		REG_WR(bp, BNX2_MISC_VREG_CONTROL, 0x000000fa);
-
-		/* Remove bad rbuf memory from the free pool. */
-		rc = bnx2_alloc_bad_rbuf(bp);
-	}
-
-	if (bp->flags & BNX2_FLAG_USING_MSIX) {
-		bnx2_setup_msix_tbl(bp);
-		/* Prevent MSIX table reads and write from timing out */
-		REG_WR(bp, BNX2_MISC_ECO_HW_CTL,
-			BNX2_MISC_ECO_HW_CTL_LARGE_GRC_TMOUT_EN);
-	}
-
-	return rc;
-}
-
-static int
-bnx2_init_chip(struct bnx2 *bp)
-{
-	u32 val, mtu;
-	int rc, i;
-
-	/* Make sure the interrupt is not active. */
-	REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
-
-	val = BNX2_DMA_CONFIG_DATA_BYTE_SWAP |
-	      BNX2_DMA_CONFIG_DATA_WORD_SWAP |
-#ifdef __BIG_ENDIAN
-	      BNX2_DMA_CONFIG_CNTL_BYTE_SWAP |
-#endif
-	      BNX2_DMA_CONFIG_CNTL_WORD_SWAP |
-	      DMA_READ_CHANS << 12 |
-	      DMA_WRITE_CHANS << 16;
-
-	val |= (0x2 << 20) | (1 << 11);
-
-	if ((bp->flags & BNX2_FLAG_PCIX) && (bp->bus_speed_mhz == 133))
-		val |= (1 << 23);
-
-	if ((CHIP_NUM(bp) == CHIP_NUM_5706) &&
-	    (CHIP_ID(bp) != CHIP_ID_5706_A0) && !(bp->flags & BNX2_FLAG_PCIX))
-		val |= BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA;
-
-	REG_WR(bp, BNX2_DMA_CONFIG, val);
-
-	if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
-		val = REG_RD(bp, BNX2_TDMA_CONFIG);
-		val |= BNX2_TDMA_CONFIG_ONE_DMA;
-		REG_WR(bp, BNX2_TDMA_CONFIG, val);
-	}
-
-	if (bp->flags & BNX2_FLAG_PCIX) {
-		u16 val16;
-
-		pci_read_config_word(bp->pdev, bp->pcix_cap + PCI_X_CMD,
-				     &val16);
-		pci_write_config_word(bp->pdev, bp->pcix_cap + PCI_X_CMD,
-				      val16 & ~PCI_X_CMD_ERO);
-	}
-
-	REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
-	       BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE |
-	       BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE |
-	       BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE);
-
-	/* Initialize context mapping and zero out the quick contexts.  The
-	 * context block must have already been enabled. */
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		rc = bnx2_init_5709_context(bp);
-		if (rc)
-			return rc;
-	} else
-		bnx2_init_context(bp);
-
-	if ((rc = bnx2_init_cpus(bp)) != 0)
-		return rc;
-
-	bnx2_init_nvram(bp);
-
-	bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0);
-
-	val = REG_RD(bp, BNX2_MQ_CONFIG);
-	val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE;
-	val |= BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256;
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		val |= BNX2_MQ_CONFIG_BIN_MQ_MODE;
-		if (CHIP_REV(bp) == CHIP_REV_Ax)
-			val |= BNX2_MQ_CONFIG_HALT_DIS;
-	}
-
-	REG_WR(bp, BNX2_MQ_CONFIG, val);
-
-	val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE);
-	REG_WR(bp, BNX2_MQ_KNL_BYP_WIND_START, val);
-	REG_WR(bp, BNX2_MQ_KNL_WIND_END, val);
-
-	val = (BCM_PAGE_BITS - 8) << 24;
-	REG_WR(bp, BNX2_RV2P_CONFIG, val);
-
-	/* Configure page size. */
-	val = REG_RD(bp, BNX2_TBDR_CONFIG);
-	val &= ~BNX2_TBDR_CONFIG_PAGE_SIZE;
-	val |= (BCM_PAGE_BITS - 8) << 24 | 0x40;
-	REG_WR(bp, BNX2_TBDR_CONFIG, val);
-
-	val = bp->mac_addr[0] +
-	      (bp->mac_addr[1] << 8) +
-	      (bp->mac_addr[2] << 16) +
-	      bp->mac_addr[3] +
-	      (bp->mac_addr[4] << 8) +
-	      (bp->mac_addr[5] << 16);
-	REG_WR(bp, BNX2_EMAC_BACKOFF_SEED, val);
-
-	/* Program the MTU.  Also include 4 bytes for CRC32. */
-	mtu = bp->dev->mtu;
-	val = mtu + ETH_HLEN + ETH_FCS_LEN;
-	if (val > (MAX_ETHERNET_PACKET_SIZE + 4))
-		val |= BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA;
-	REG_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val);
-
-	if (mtu < 1500)
-		mtu = 1500;
-
-	bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG, BNX2_RBUF_CONFIG_VAL(mtu));
-	bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG2, BNX2_RBUF_CONFIG2_VAL(mtu));
-	bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG3, BNX2_RBUF_CONFIG3_VAL(mtu));
-
-	memset(bp->bnx2_napi[0].status_blk.msi, 0, bp->status_stats_size);
-	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++)
-		bp->bnx2_napi[i].last_status_idx = 0;
-
-	bp->idle_chk_status_idx = 0xffff;
-
-	bp->rx_mode = BNX2_EMAC_RX_MODE_SORT_MODE;
-
-	/* Set up how to generate a link change interrupt. */
-	REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
-
-	REG_WR(bp, BNX2_HC_STATUS_ADDR_L,
-	       (u64) bp->status_blk_mapping & 0xffffffff);
-	REG_WR(bp, BNX2_HC_STATUS_ADDR_H, (u64) bp->status_blk_mapping >> 32);
-
-	REG_WR(bp, BNX2_HC_STATISTICS_ADDR_L,
-	       (u64) bp->stats_blk_mapping & 0xffffffff);
-	REG_WR(bp, BNX2_HC_STATISTICS_ADDR_H,
-	       (u64) bp->stats_blk_mapping >> 32);
-
-	REG_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP,
-	       (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip);
-
-	REG_WR(bp, BNX2_HC_RX_QUICK_CONS_TRIP,
-	       (bp->rx_quick_cons_trip_int << 16) | bp->rx_quick_cons_trip);
-
-	REG_WR(bp, BNX2_HC_COMP_PROD_TRIP,
-	       (bp->comp_prod_trip_int << 16) | bp->comp_prod_trip);
-
-	REG_WR(bp, BNX2_HC_TX_TICKS, (bp->tx_ticks_int << 16) | bp->tx_ticks);
-
-	REG_WR(bp, BNX2_HC_RX_TICKS, (bp->rx_ticks_int << 16) | bp->rx_ticks);
-
-	REG_WR(bp, BNX2_HC_COM_TICKS,
-	       (bp->com_ticks_int << 16) | bp->com_ticks);
-
-	REG_WR(bp, BNX2_HC_CMD_TICKS,
-	       (bp->cmd_ticks_int << 16) | bp->cmd_ticks);
-
-	if (bp->flags & BNX2_FLAG_BROKEN_STATS)
-		REG_WR(bp, BNX2_HC_STATS_TICKS, 0);
-	else
-		REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks);
-	REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8);  /* 3ms */
-
-	if (CHIP_ID(bp) == CHIP_ID_5706_A1)
-		val = BNX2_HC_CONFIG_COLLECT_STATS;
-	else {
-		val = BNX2_HC_CONFIG_RX_TMR_MODE | BNX2_HC_CONFIG_TX_TMR_MODE |
-		      BNX2_HC_CONFIG_COLLECT_STATS;
-	}
-
-	if (bp->flags & BNX2_FLAG_USING_MSIX) {
-		REG_WR(bp, BNX2_HC_MSIX_BIT_VECTOR,
-		       BNX2_HC_MSIX_BIT_VECTOR_VAL);
-
-		val |= BNX2_HC_CONFIG_SB_ADDR_INC_128B;
-	}
-
-	if (bp->flags & BNX2_FLAG_ONE_SHOT_MSI)
-		val |= BNX2_HC_CONFIG_ONE_SHOT | BNX2_HC_CONFIG_USE_INT_PARAM;
-
-	REG_WR(bp, BNX2_HC_CONFIG, val);
-
-	if (bp->rx_ticks < 25)
-		bnx2_reg_wr_ind(bp, BNX2_FW_RX_LOW_LATENCY, 1);
-	else
-		bnx2_reg_wr_ind(bp, BNX2_FW_RX_LOW_LATENCY, 0);
-
-	for (i = 1; i < bp->irq_nvecs; i++) {
-		u32 base = ((i - 1) * BNX2_HC_SB_CONFIG_SIZE) +
-			   BNX2_HC_SB_CONFIG_1;
-
-		REG_WR(bp, base,
-			BNX2_HC_SB_CONFIG_1_TX_TMR_MODE |
-			BNX2_HC_SB_CONFIG_1_RX_TMR_MODE |
-			BNX2_HC_SB_CONFIG_1_ONE_SHOT);
-
-		REG_WR(bp, base + BNX2_HC_TX_QUICK_CONS_TRIP_OFF,
-			(bp->tx_quick_cons_trip_int << 16) |
-			 bp->tx_quick_cons_trip);
-
-		REG_WR(bp, base + BNX2_HC_TX_TICKS_OFF,
-			(bp->tx_ticks_int << 16) | bp->tx_ticks);
-
-		REG_WR(bp, base + BNX2_HC_RX_QUICK_CONS_TRIP_OFF,
-		       (bp->rx_quick_cons_trip_int << 16) |
-			bp->rx_quick_cons_trip);
-
-		REG_WR(bp, base + BNX2_HC_RX_TICKS_OFF,
-			(bp->rx_ticks_int << 16) | bp->rx_ticks);
-	}
-
-	/* Clear internal stats counters. */
-	REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW);
-
-	REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_EVENTS);
-
-	/* Initialize the receive filter. */
-	bnx2_set_rx_mode(bp->dev);
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
-		val |= BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE;
-		REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
-	}
-	rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET,
-			  1, 0);
-
-	REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_DEFAULT);
-	REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS);
-
-	udelay(20);
-
-	bp->hc_cmd = REG_RD(bp, BNX2_HC_COMMAND);
-
-	return rc;
-}
-
-static void
-bnx2_clear_ring_states(struct bnx2 *bp)
-{
-	struct bnx2_napi *bnapi;
-	struct bnx2_tx_ring_info *txr;
-	struct bnx2_rx_ring_info *rxr;
-	int i;
-
-	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {
-		bnapi = &bp->bnx2_napi[i];
-		txr = &bnapi->tx_ring;
-		rxr = &bnapi->rx_ring;
-
-		txr->tx_cons = 0;
-		txr->hw_tx_cons = 0;
-		rxr->rx_prod_bseq = 0;
-		rxr->rx_prod = 0;
-		rxr->rx_cons = 0;
-		rxr->rx_pg_prod = 0;
-		rxr->rx_pg_cons = 0;
-	}
-}
-
-static void
-bnx2_init_tx_context(struct bnx2 *bp, u32 cid, struct bnx2_tx_ring_info *txr)
-{
-	u32 val, offset0, offset1, offset2, offset3;
-	u32 cid_addr = GET_CID_ADDR(cid);
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		offset0 = BNX2_L2CTX_TYPE_XI;
-		offset1 = BNX2_L2CTX_CMD_TYPE_XI;
-		offset2 = BNX2_L2CTX_TBDR_BHADDR_HI_XI;
-		offset3 = BNX2_L2CTX_TBDR_BHADDR_LO_XI;
-	} else {
-		offset0 = BNX2_L2CTX_TYPE;
-		offset1 = BNX2_L2CTX_CMD_TYPE;
-		offset2 = BNX2_L2CTX_TBDR_BHADDR_HI;
-		offset3 = BNX2_L2CTX_TBDR_BHADDR_LO;
-	}
-	val = BNX2_L2CTX_TYPE_TYPE_L2 | BNX2_L2CTX_TYPE_SIZE_L2;
-	bnx2_ctx_wr(bp, cid_addr, offset0, val);
-
-	val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16);
-	bnx2_ctx_wr(bp, cid_addr, offset1, val);
-
-	val = (u64) txr->tx_desc_mapping >> 32;
-	bnx2_ctx_wr(bp, cid_addr, offset2, val);
-
-	val = (u64) txr->tx_desc_mapping & 0xffffffff;
-	bnx2_ctx_wr(bp, cid_addr, offset3, val);
-}
-
-static void
-bnx2_init_tx_ring(struct bnx2 *bp, int ring_num)
-{
-	struct tx_bd *txbd;
-	u32 cid = TX_CID;
-	struct bnx2_napi *bnapi;
-	struct bnx2_tx_ring_info *txr;
-
-	bnapi = &bp->bnx2_napi[ring_num];
-	txr = &bnapi->tx_ring;
-
-	if (ring_num == 0)
-		cid = TX_CID;
-	else
-		cid = TX_TSS_CID + ring_num - 1;
-
-	bp->tx_wake_thresh = bp->tx_ring_size / 2;
-
-	txbd = &txr->tx_desc_ring[MAX_TX_DESC_CNT];
-
-	txbd->tx_bd_haddr_hi = (u64) txr->tx_desc_mapping >> 32;
-	txbd->tx_bd_haddr_lo = (u64) txr->tx_desc_mapping & 0xffffffff;
-
-	txr->tx_prod = 0;
-	txr->tx_prod_bseq = 0;
-
-	txr->tx_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_TX_HOST_BIDX;
-	txr->tx_bseq_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_TX_HOST_BSEQ;
-
-	bnx2_init_tx_context(bp, cid, txr);
-}
-
-static void
-bnx2_init_rxbd_rings(struct rx_bd *rx_ring[], dma_addr_t dma[], u32 buf_size,
-		     int num_rings)
-{
-	int i;
-	struct rx_bd *rxbd;
-
-	for (i = 0; i < num_rings; i++) {
-		int j;
-
-		rxbd = &rx_ring[i][0];
-		for (j = 0; j < MAX_RX_DESC_CNT; j++, rxbd++) {
-			rxbd->rx_bd_len = buf_size;
-			rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
-		}
-		if (i == (num_rings - 1))
-			j = 0;
-		else
-			j = i + 1;
-		rxbd->rx_bd_haddr_hi = (u64) dma[j] >> 32;
-		rxbd->rx_bd_haddr_lo = (u64) dma[j] & 0xffffffff;
-	}
-}
-
-static void
-bnx2_init_rx_ring(struct bnx2 *bp, int ring_num)
-{
-	int i;
-	u16 prod, ring_prod;
-	u32 cid, rx_cid_addr, val;
-	struct bnx2_napi *bnapi = &bp->bnx2_napi[ring_num];
-	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
-
-	if (ring_num == 0)
-		cid = RX_CID;
-	else
-		cid = RX_RSS_CID + ring_num - 1;
-
-	rx_cid_addr = GET_CID_ADDR(cid);
-
-	bnx2_init_rxbd_rings(rxr->rx_desc_ring, rxr->rx_desc_mapping,
-			     bp->rx_buf_use_size, bp->rx_max_ring);
-
-	bnx2_init_rx_context(bp, cid);
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		val = REG_RD(bp, BNX2_MQ_MAP_L2_5);
-		REG_WR(bp, BNX2_MQ_MAP_L2_5, val | BNX2_MQ_MAP_L2_5_ARM);
-	}
-
-	bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, 0);
-	if (bp->rx_pg_ring_size) {
-		bnx2_init_rxbd_rings(rxr->rx_pg_desc_ring,
-				     rxr->rx_pg_desc_mapping,
-				     PAGE_SIZE, bp->rx_max_pg_ring);
-		val = (bp->rx_buf_use_size << 16) | PAGE_SIZE;
-		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, val);
-		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_RBDC_KEY,
-		       BNX2_L2CTX_RBDC_JUMBO_KEY - ring_num);
-
-		val = (u64) rxr->rx_pg_desc_mapping[0] >> 32;
-		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_HI, val);
-
-		val = (u64) rxr->rx_pg_desc_mapping[0] & 0xffffffff;
-		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_LO, val);
-
-		if (CHIP_NUM(bp) == CHIP_NUM_5709)
-			REG_WR(bp, BNX2_MQ_MAP_L2_3, BNX2_MQ_MAP_L2_3_DEFAULT);
-	}
-
-	val = (u64) rxr->rx_desc_mapping[0] >> 32;
-	bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val);
-
-	val = (u64) rxr->rx_desc_mapping[0] & 0xffffffff;
-	bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val);
-
-	ring_prod = prod = rxr->rx_pg_prod;
-	for (i = 0; i < bp->rx_pg_ring_size; i++) {
-		if (bnx2_alloc_rx_page(bp, rxr, ring_prod, GFP_KERNEL) < 0) {
-			netdev_warn(bp->dev, "init'ed rx page ring %d with %d/%d pages only\n",
-				    ring_num, i, bp->rx_pg_ring_size);
-			break;
-		}
-		prod = NEXT_RX_BD(prod);
-		ring_prod = RX_PG_RING_IDX(prod);
-	}
-	rxr->rx_pg_prod = prod;
-
-	ring_prod = prod = rxr->rx_prod;
-	for (i = 0; i < bp->rx_ring_size; i++) {
-		if (bnx2_alloc_rx_skb(bp, rxr, ring_prod, GFP_KERNEL) < 0) {
-			netdev_warn(bp->dev, "init'ed rx ring %d with %d/%d skbs only\n",
-				    ring_num, i, bp->rx_ring_size);
-			break;
-		}
-		prod = NEXT_RX_BD(prod);
-		ring_prod = RX_RING_IDX(prod);
-	}
-	rxr->rx_prod = prod;
-
-	rxr->rx_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_BDIDX;
-	rxr->rx_bseq_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_BSEQ;
-	rxr->rx_pg_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_PG_BDIDX;
-
-	REG_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod);
-	REG_WR16(bp, rxr->rx_bidx_addr, prod);
-
-	REG_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq);
-}
-
-static void
-bnx2_init_all_rings(struct bnx2 *bp)
-{
-	int i;
-	u32 val;
-
-	bnx2_clear_ring_states(bp);
-
-	REG_WR(bp, BNX2_TSCH_TSS_CFG, 0);
-	for (i = 0; i < bp->num_tx_rings; i++)
-		bnx2_init_tx_ring(bp, i);
-
-	if (bp->num_tx_rings > 1)
-		REG_WR(bp, BNX2_TSCH_TSS_CFG, ((bp->num_tx_rings - 1) << 24) |
-		       (TX_TSS_CID << 7));
-
-	REG_WR(bp, BNX2_RLUP_RSS_CONFIG, 0);
-	bnx2_reg_wr_ind(bp, BNX2_RXP_SCRATCH_RSS_TBL_SZ, 0);
-
-	for (i = 0; i < bp->num_rx_rings; i++)
-		bnx2_init_rx_ring(bp, i);
-
-	if (bp->num_rx_rings > 1) {
-		u32 tbl_32 = 0;
-
-		for (i = 0; i < BNX2_RXP_SCRATCH_RSS_TBL_MAX_ENTRIES; i++) {
-			int shift = (i % 8) << 2;
-
-			tbl_32 |= (i % (bp->num_rx_rings - 1)) << shift;
-			if ((i % 8) == 7) {
-				REG_WR(bp, BNX2_RLUP_RSS_DATA, tbl_32);
-				REG_WR(bp, BNX2_RLUP_RSS_COMMAND, (i >> 3) |
-					BNX2_RLUP_RSS_COMMAND_RSS_WRITE_MASK |
-					BNX2_RLUP_RSS_COMMAND_WRITE |
-					BNX2_RLUP_RSS_COMMAND_HASH_MASK);
-				tbl_32 = 0;
-			}
-		}
-
-		val = BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_ALL_XI |
-		      BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_ALL_XI;
-
-		REG_WR(bp, BNX2_RLUP_RSS_CONFIG, val);
-
-	}
-}
-
-static u32 bnx2_find_max_ring(u32 ring_size, u32 max_size)
-{
-	u32 max, num_rings = 1;
-
-	while (ring_size > MAX_RX_DESC_CNT) {
-		ring_size -= MAX_RX_DESC_CNT;
-		num_rings++;
-	}
-	/* round to next power of 2 */
-	max = max_size;
-	while ((max & num_rings) == 0)
-		max >>= 1;
-
-	if (num_rings != max)
-		max <<= 1;
-
-	return max;
-}
-
-static void
-bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size)
-{
-	u32 rx_size, rx_space, jumbo_size;
-
-	/* 8 for CRC and VLAN */
-	rx_size = bp->dev->mtu + ETH_HLEN + BNX2_RX_OFFSET + 8;
-
-	rx_space = SKB_DATA_ALIGN(rx_size + BNX2_RX_ALIGN) + NET_SKB_PAD +
-		sizeof(struct skb_shared_info);
-
-	bp->rx_copy_thresh = BNX2_RX_COPY_THRESH;
-	bp->rx_pg_ring_size = 0;
-	bp->rx_max_pg_ring = 0;
-	bp->rx_max_pg_ring_idx = 0;
-	if ((rx_space > PAGE_SIZE) && !(bp->flags & BNX2_FLAG_JUMBO_BROKEN)) {
-		int pages = PAGE_ALIGN(bp->dev->mtu - 40) >> PAGE_SHIFT;
-
-		jumbo_size = size * pages;
-		if (jumbo_size > MAX_TOTAL_RX_PG_DESC_CNT)
-			jumbo_size = MAX_TOTAL_RX_PG_DESC_CNT;
-
-		bp->rx_pg_ring_size = jumbo_size;
-		bp->rx_max_pg_ring = bnx2_find_max_ring(jumbo_size,
-							MAX_RX_PG_RINGS);
-		bp->rx_max_pg_ring_idx = (bp->rx_max_pg_ring * RX_DESC_CNT) - 1;
-		rx_size = BNX2_RX_COPY_THRESH + BNX2_RX_OFFSET;
-		bp->rx_copy_thresh = 0;
-	}
-
-	bp->rx_buf_use_size = rx_size;
-	/* hw alignment */
-	bp->rx_buf_size = bp->rx_buf_use_size + BNX2_RX_ALIGN;
-	bp->rx_jumbo_thresh = rx_size - BNX2_RX_OFFSET;
-	bp->rx_ring_size = size;
-	bp->rx_max_ring = bnx2_find_max_ring(size, MAX_RX_RINGS);
-	bp->rx_max_ring_idx = (bp->rx_max_ring * RX_DESC_CNT) - 1;
-}
-
-static void
-bnx2_free_tx_skbs(struct bnx2 *bp)
-{
-	int i;
-
-	for (i = 0; i < bp->num_tx_rings; i++) {
-		struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
-		struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
-		int j;
-
-		if (txr->tx_buf_ring == NULL)
-			continue;
-
-		for (j = 0; j < TX_DESC_CNT; ) {
-			struct sw_tx_bd *tx_buf = &txr->tx_buf_ring[j];
-			struct sk_buff *skb = tx_buf->skb;
-			int k, last;
-
-			if (skb == NULL) {
-				j++;
-				continue;
-			}
-
-			dma_unmap_single(&bp->pdev->dev,
-					 dma_unmap_addr(tx_buf, mapping),
-					 skb_headlen(skb),
-					 PCI_DMA_TODEVICE);
-
-			tx_buf->skb = NULL;
-
-			last = tx_buf->nr_frags;
-			j++;
-			for (k = 0; k < last; k++, j++) {
-				tx_buf = &txr->tx_buf_ring[TX_RING_IDX(j)];
-				dma_unmap_page(&bp->pdev->dev,
-					dma_unmap_addr(tx_buf, mapping),
-					skb_shinfo(skb)->frags[k].size,
-					PCI_DMA_TODEVICE);
-			}
-			dev_kfree_skb(skb);
-		}
-	}
-}
-
-static void
-bnx2_free_rx_skbs(struct bnx2 *bp)
-{
-	int i;
-
-	for (i = 0; i < bp->num_rx_rings; i++) {
-		struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
-		struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
-		int j;
-
-		if (rxr->rx_buf_ring == NULL)
-			return;
-
-		for (j = 0; j < bp->rx_max_ring_idx; j++) {
-			struct sw_bd *rx_buf = &rxr->rx_buf_ring[j];
-			struct sk_buff *skb = rx_buf->skb;
-
-			if (skb == NULL)
-				continue;
-
-			dma_unmap_single(&bp->pdev->dev,
-					 dma_unmap_addr(rx_buf, mapping),
-					 bp->rx_buf_use_size,
-					 PCI_DMA_FROMDEVICE);
-
-			rx_buf->skb = NULL;
-
-			dev_kfree_skb(skb);
-		}
-		for (j = 0; j < bp->rx_max_pg_ring_idx; j++)
-			bnx2_free_rx_page(bp, rxr, j);
-	}
-}
-
-static void
-bnx2_free_skbs(struct bnx2 *bp)
-{
-	bnx2_free_tx_skbs(bp);
-	bnx2_free_rx_skbs(bp);
-}
-
-static int
-bnx2_reset_nic(struct bnx2 *bp, u32 reset_code)
-{
-	int rc;
-
-	rc = bnx2_reset_chip(bp, reset_code);
-	bnx2_free_skbs(bp);
-	if (rc)
-		return rc;
-
-	if ((rc = bnx2_init_chip(bp)) != 0)
-		return rc;
-
-	bnx2_init_all_rings(bp);
-	return 0;
-}
-
-static int
-bnx2_init_nic(struct bnx2 *bp, int reset_phy)
-{
-	int rc;
-
-	if ((rc = bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET)) != 0)
-		return rc;
-
-	spin_lock_bh(&bp->phy_lock);
-	bnx2_init_phy(bp, reset_phy);
-	bnx2_set_link(bp);
-	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
-		bnx2_remote_phy_event(bp);
-	spin_unlock_bh(&bp->phy_lock);
-	return 0;
-}
-
-static int
-bnx2_shutdown_chip(struct bnx2 *bp)
-{
-	u32 reset_code;
-
-	if (bp->flags & BNX2_FLAG_NO_WOL)
-		reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN;
-	else if (bp->wol)
-		reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
-	else
-		reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
-
-	return bnx2_reset_chip(bp, reset_code);
-}
-
-static int
-bnx2_test_registers(struct bnx2 *bp)
-{
-	int ret;
-	int i, is_5709;
-	static const struct {
-		u16   offset;
-		u16   flags;
-#define BNX2_FL_NOT_5709	1
-		u32   rw_mask;
-		u32   ro_mask;
-	} reg_tbl[] = {
-		{ 0x006c, 0, 0x00000000, 0x0000003f },
-		{ 0x0090, 0, 0xffffffff, 0x00000000 },
-		{ 0x0094, 0, 0x00000000, 0x00000000 },
-
-		{ 0x0404, BNX2_FL_NOT_5709, 0x00003f00, 0x00000000 },
-		{ 0x0418, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
-		{ 0x041c, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
-		{ 0x0420, BNX2_FL_NOT_5709, 0x00000000, 0x80ffffff },
-		{ 0x0424, BNX2_FL_NOT_5709, 0x00000000, 0x00000000 },
-		{ 0x0428, BNX2_FL_NOT_5709, 0x00000000, 0x00000001 },
-		{ 0x0450, BNX2_FL_NOT_5709, 0x00000000, 0x0000ffff },
-		{ 0x0454, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
-		{ 0x0458, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
-
-		{ 0x0808, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
-		{ 0x0854, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
-		{ 0x0868, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 },
-		{ 0x086c, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 },
-		{ 0x0870, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 },
-		{ 0x0874, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 },
-
-		{ 0x0c00, BNX2_FL_NOT_5709, 0x00000000, 0x00000001 },
-		{ 0x0c04, BNX2_FL_NOT_5709, 0x00000000, 0x03ff0001 },
-		{ 0x0c08, BNX2_FL_NOT_5709,  0x0f0ff073, 0x00000000 },
-
-		{ 0x1000, 0, 0x00000000, 0x00000001 },
-		{ 0x1004, BNX2_FL_NOT_5709, 0x00000000, 0x000f0001 },
-
-		{ 0x1408, 0, 0x01c00800, 0x00000000 },
-		{ 0x149c, 0, 0x8000ffff, 0x00000000 },
-		{ 0x14a8, 0, 0x00000000, 0x000001ff },
-		{ 0x14ac, 0, 0x0fffffff, 0x10000000 },
-		{ 0x14b0, 0, 0x00000002, 0x00000001 },
-		{ 0x14b8, 0, 0x00000000, 0x00000000 },
-		{ 0x14c0, 0, 0x00000000, 0x00000009 },
-		{ 0x14c4, 0, 0x00003fff, 0x00000000 },
-		{ 0x14cc, 0, 0x00000000, 0x00000001 },
-		{ 0x14d0, 0, 0xffffffff, 0x00000000 },
-
-		{ 0x1800, 0, 0x00000000, 0x00000001 },
-		{ 0x1804, 0, 0x00000000, 0x00000003 },
-
-		{ 0x2800, 0, 0x00000000, 0x00000001 },
-		{ 0x2804, 0, 0x00000000, 0x00003f01 },
-		{ 0x2808, 0, 0x0f3f3f03, 0x00000000 },
-		{ 0x2810, 0, 0xffff0000, 0x00000000 },
-		{ 0x2814, 0, 0xffff0000, 0x00000000 },
-		{ 0x2818, 0, 0xffff0000, 0x00000000 },
-		{ 0x281c, 0, 0xffff0000, 0x00000000 },
-		{ 0x2834, 0, 0xffffffff, 0x00000000 },
-		{ 0x2840, 0, 0x00000000, 0xffffffff },
-		{ 0x2844, 0, 0x00000000, 0xffffffff },
-		{ 0x2848, 0, 0xffffffff, 0x00000000 },
-		{ 0x284c, 0, 0xf800f800, 0x07ff07ff },
-
-		{ 0x2c00, 0, 0x00000000, 0x00000011 },
-		{ 0x2c04, 0, 0x00000000, 0x00030007 },
-
-		{ 0x3c00, 0, 0x00000000, 0x00000001 },
-		{ 0x3c04, 0, 0x00000000, 0x00070000 },
-		{ 0x3c08, 0, 0x00007f71, 0x07f00000 },
-		{ 0x3c0c, 0, 0x1f3ffffc, 0x00000000 },
-		{ 0x3c10, 0, 0xffffffff, 0x00000000 },
-		{ 0x3c14, 0, 0x00000000, 0xffffffff },
-		{ 0x3c18, 0, 0x00000000, 0xffffffff },
-		{ 0x3c1c, 0, 0xfffff000, 0x00000000 },
-		{ 0x3c20, 0, 0xffffff00, 0x00000000 },
-
-		{ 0x5004, 0, 0x00000000, 0x0000007f },
-		{ 0x5008, 0, 0x0f0007ff, 0x00000000 },
-
-		{ 0x5c00, 0, 0x00000000, 0x00000001 },
-		{ 0x5c04, 0, 0x00000000, 0x0003000f },
-		{ 0x5c08, 0, 0x00000003, 0x00000000 },
-		{ 0x5c0c, 0, 0x0000fff8, 0x00000000 },
-		{ 0x5c10, 0, 0x00000000, 0xffffffff },
-		{ 0x5c80, 0, 0x00000000, 0x0f7113f1 },
-		{ 0x5c84, 0, 0x00000000, 0x0000f333 },
-		{ 0x5c88, 0, 0x00000000, 0x00077373 },
-		{ 0x5c8c, 0, 0x00000000, 0x0007f737 },
-
-		{ 0x6808, 0, 0x0000ff7f, 0x00000000 },
-		{ 0x680c, 0, 0xffffffff, 0x00000000 },
-		{ 0x6810, 0, 0xffffffff, 0x00000000 },
-		{ 0x6814, 0, 0xffffffff, 0x00000000 },
-		{ 0x6818, 0, 0xffffffff, 0x00000000 },
-		{ 0x681c, 0, 0xffffffff, 0x00000000 },
-		{ 0x6820, 0, 0x00ff00ff, 0x00000000 },
-		{ 0x6824, 0, 0x00ff00ff, 0x00000000 },
-		{ 0x6828, 0, 0x00ff00ff, 0x00000000 },
-		{ 0x682c, 0, 0x03ff03ff, 0x00000000 },
-		{ 0x6830, 0, 0x03ff03ff, 0x00000000 },
-		{ 0x6834, 0, 0x03ff03ff, 0x00000000 },
-		{ 0x6838, 0, 0x03ff03ff, 0x00000000 },
-		{ 0x683c, 0, 0x0000ffff, 0x00000000 },
-		{ 0x6840, 0, 0x00000ff0, 0x00000000 },
-		{ 0x6844, 0, 0x00ffff00, 0x00000000 },
-		{ 0x684c, 0, 0xffffffff, 0x00000000 },
-		{ 0x6850, 0, 0x7f7f7f7f, 0x00000000 },
-		{ 0x6854, 0, 0x7f7f7f7f, 0x00000000 },
-		{ 0x6858, 0, 0x7f7f7f7f, 0x00000000 },
-		{ 0x685c, 0, 0x7f7f7f7f, 0x00000000 },
-		{ 0x6908, 0, 0x00000000, 0x0001ff0f },
-		{ 0x690c, 0, 0x00000000, 0x0ffe00f0 },
-
-		{ 0xffff, 0, 0x00000000, 0x00000000 },
-	};
-
-	ret = 0;
-	is_5709 = 0;
-	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		is_5709 = 1;
-
-	for (i = 0; reg_tbl[i].offset != 0xffff; i++) {
-		u32 offset, rw_mask, ro_mask, save_val, val;
-		u16 flags = reg_tbl[i].flags;
-
-		if (is_5709 && (flags & BNX2_FL_NOT_5709))
-			continue;
-
-		offset = (u32) reg_tbl[i].offset;
-		rw_mask = reg_tbl[i].rw_mask;
-		ro_mask = reg_tbl[i].ro_mask;
-
-		save_val = readl(bp->regview + offset);
-
-		writel(0, bp->regview + offset);
-
-		val = readl(bp->regview + offset);
-		if ((val & rw_mask) != 0) {
-			goto reg_test_err;
-		}
-
-		if ((val & ro_mask) != (save_val & ro_mask)) {
-			goto reg_test_err;
-		}
-
-		writel(0xffffffff, bp->regview + offset);
-
-		val = readl(bp->regview + offset);
-		if ((val & rw_mask) != rw_mask) {
-			goto reg_test_err;
-		}
-
-		if ((val & ro_mask) != (save_val & ro_mask)) {
-			goto reg_test_err;
-		}
-
-		writel(save_val, bp->regview + offset);
-		continue;
-
-reg_test_err:
-		writel(save_val, bp->regview + offset);
-		ret = -ENODEV;
-		break;
-	}
-	return ret;
-}
-
-static int
-bnx2_do_mem_test(struct bnx2 *bp, u32 start, u32 size)
-{
-	static const u32 test_pattern[] = { 0x00000000, 0xffffffff, 0x55555555,
-		0xaaaaaaaa , 0xaa55aa55, 0x55aa55aa };
-	int i;
-
-	for (i = 0; i < sizeof(test_pattern) / 4; i++) {
-		u32 offset;
-
-		for (offset = 0; offset < size; offset += 4) {
-
-			bnx2_reg_wr_ind(bp, start + offset, test_pattern[i]);
-
-			if (bnx2_reg_rd_ind(bp, start + offset) !=
-				test_pattern[i]) {
-				return -ENODEV;
-			}
-		}
-	}
-	return 0;
-}
-
-static int
-bnx2_test_memory(struct bnx2 *bp)
-{
-	int ret = 0;
-	int i;
-	static struct mem_entry {
-		u32   offset;
-		u32   len;
-	} mem_tbl_5706[] = {
-		{ 0x60000,  0x4000 },
-		{ 0xa0000,  0x3000 },
-		{ 0xe0000,  0x4000 },
-		{ 0x120000, 0x4000 },
-		{ 0x1a0000, 0x4000 },
-		{ 0x160000, 0x4000 },
-		{ 0xffffffff, 0    },
-	},
-	mem_tbl_5709[] = {
-		{ 0x60000,  0x4000 },
-		{ 0xa0000,  0x3000 },
-		{ 0xe0000,  0x4000 },
-		{ 0x120000, 0x4000 },
-		{ 0x1a0000, 0x4000 },
-		{ 0xffffffff, 0    },
-	};
-	struct mem_entry *mem_tbl;
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		mem_tbl = mem_tbl_5709;
-	else
-		mem_tbl = mem_tbl_5706;
-
-	for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) {
-		if ((ret = bnx2_do_mem_test(bp, mem_tbl[i].offset,
-			mem_tbl[i].len)) != 0) {
-			return ret;
-		}
-	}
-
-	return ret;
-}
-
-#define BNX2_MAC_LOOPBACK	0
-#define BNX2_PHY_LOOPBACK	1
-
-static int
-bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
-{
-	unsigned int pkt_size, num_pkts, i;
-	struct sk_buff *skb, *rx_skb;
-	unsigned char *packet;
-	u16 rx_start_idx, rx_idx;
-	dma_addr_t map;
-	struct tx_bd *txbd;
-	struct sw_bd *rx_buf;
-	struct l2_fhdr *rx_hdr;
-	int ret = -ENODEV;
-	struct bnx2_napi *bnapi = &bp->bnx2_napi[0], *tx_napi;
-	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
-	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
-
-	tx_napi = bnapi;
-
-	txr = &tx_napi->tx_ring;
-	rxr = &bnapi->rx_ring;
-	if (loopback_mode == BNX2_MAC_LOOPBACK) {
-		bp->loopback = MAC_LOOPBACK;
-		bnx2_set_mac_loopback(bp);
-	}
-	else if (loopback_mode == BNX2_PHY_LOOPBACK) {
-		if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
-			return 0;
-
-		bp->loopback = PHY_LOOPBACK;
-		bnx2_set_phy_loopback(bp);
-	}
-	else
-		return -EINVAL;
-
-	pkt_size = min(bp->dev->mtu + ETH_HLEN, bp->rx_jumbo_thresh - 4);
-	skb = netdev_alloc_skb(bp->dev, pkt_size);
-	if (!skb)
-		return -ENOMEM;
-	packet = skb_put(skb, pkt_size);
-	memcpy(packet, bp->dev->dev_addr, 6);
-	memset(packet + 6, 0x0, 8);
-	for (i = 14; i < pkt_size; i++)
-		packet[i] = (unsigned char) (i & 0xff);
-
-	map = dma_map_single(&bp->pdev->dev, skb->data, pkt_size,
-			     PCI_DMA_TODEVICE);
-	if (dma_mapping_error(&bp->pdev->dev, map)) {
-		dev_kfree_skb(skb);
-		return -EIO;
-	}
-
-	REG_WR(bp, BNX2_HC_COMMAND,
-	       bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
-
-	REG_RD(bp, BNX2_HC_COMMAND);
-
-	udelay(5);
-	rx_start_idx = bnx2_get_hw_rx_cons(bnapi);
-
-	num_pkts = 0;
-
-	txbd = &txr->tx_desc_ring[TX_RING_IDX(txr->tx_prod)];
-
-	txbd->tx_bd_haddr_hi = (u64) map >> 32;
-	txbd->tx_bd_haddr_lo = (u64) map & 0xffffffff;
-	txbd->tx_bd_mss_nbytes = pkt_size;
-	txbd->tx_bd_vlan_tag_flags = TX_BD_FLAGS_START | TX_BD_FLAGS_END;
-
-	num_pkts++;
-	txr->tx_prod = NEXT_TX_BD(txr->tx_prod);
-	txr->tx_prod_bseq += pkt_size;
-
-	REG_WR16(bp, txr->tx_bidx_addr, txr->tx_prod);
-	REG_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq);
-
-	udelay(100);
-
-	REG_WR(bp, BNX2_HC_COMMAND,
-	       bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
-
-	REG_RD(bp, BNX2_HC_COMMAND);
-
-	udelay(5);
-
-	dma_unmap_single(&bp->pdev->dev, map, pkt_size, PCI_DMA_TODEVICE);
-	dev_kfree_skb(skb);
-
-	if (bnx2_get_hw_tx_cons(tx_napi) != txr->tx_prod)
-		goto loopback_test_done;
-
-	rx_idx = bnx2_get_hw_rx_cons(bnapi);
-	if (rx_idx != rx_start_idx + num_pkts) {
-		goto loopback_test_done;
-	}
-
-	rx_buf = &rxr->rx_buf_ring[rx_start_idx];
-	rx_skb = rx_buf->skb;
-
-	rx_hdr = rx_buf->desc;
-	skb_reserve(rx_skb, BNX2_RX_OFFSET);
-
-	dma_sync_single_for_cpu(&bp->pdev->dev,
-		dma_unmap_addr(rx_buf, mapping),
-		bp->rx_buf_size, PCI_DMA_FROMDEVICE);
-
-	if (rx_hdr->l2_fhdr_status &
-		(L2_FHDR_ERRORS_BAD_CRC |
-		L2_FHDR_ERRORS_PHY_DECODE |
-		L2_FHDR_ERRORS_ALIGNMENT |
-		L2_FHDR_ERRORS_TOO_SHORT |
-		L2_FHDR_ERRORS_GIANT_FRAME)) {
-
-		goto loopback_test_done;
-	}
-
-	if ((rx_hdr->l2_fhdr_pkt_len - 4) != pkt_size) {
-		goto loopback_test_done;
-	}
-
-	for (i = 14; i < pkt_size; i++) {
-		if (*(rx_skb->data + i) != (unsigned char) (i & 0xff)) {
-			goto loopback_test_done;
-		}
-	}
-
-	ret = 0;
-
-loopback_test_done:
-	bp->loopback = 0;
-	return ret;
-}
-
-#define BNX2_MAC_LOOPBACK_FAILED	1
-#define BNX2_PHY_LOOPBACK_FAILED	2
-#define BNX2_LOOPBACK_FAILED		(BNX2_MAC_LOOPBACK_FAILED |	\
-					 BNX2_PHY_LOOPBACK_FAILED)
-
-static int
-bnx2_test_loopback(struct bnx2 *bp)
-{
-	int rc = 0;
-
-	if (!netif_running(bp->dev))
-		return BNX2_LOOPBACK_FAILED;
-
-	bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET);
-	spin_lock_bh(&bp->phy_lock);
-	bnx2_init_phy(bp, 1);
-	spin_unlock_bh(&bp->phy_lock);
-	if (bnx2_run_loopback(bp, BNX2_MAC_LOOPBACK))
-		rc |= BNX2_MAC_LOOPBACK_FAILED;
-	if (bnx2_run_loopback(bp, BNX2_PHY_LOOPBACK))
-		rc |= BNX2_PHY_LOOPBACK_FAILED;
-	return rc;
-}
-
-#define NVRAM_SIZE 0x200
-#define CRC32_RESIDUAL 0xdebb20e3
-
-static int
-bnx2_test_nvram(struct bnx2 *bp)
-{
-	__be32 buf[NVRAM_SIZE / 4];
-	u8 *data = (u8 *) buf;
-	int rc = 0;
-	u32 magic, csum;
-
-	if ((rc = bnx2_nvram_read(bp, 0, data, 4)) != 0)
-		goto test_nvram_done;
-
-        magic = be32_to_cpu(buf[0]);
-	if (magic != 0x669955aa) {
-		rc = -ENODEV;
-		goto test_nvram_done;
-	}
-
-	if ((rc = bnx2_nvram_read(bp, 0x100, data, NVRAM_SIZE)) != 0)
-		goto test_nvram_done;
-
-	csum = ether_crc_le(0x100, data);
-	if (csum != CRC32_RESIDUAL) {
-		rc = -ENODEV;
-		goto test_nvram_done;
-	}
-
-	csum = ether_crc_le(0x100, data + 0x100);
-	if (csum != CRC32_RESIDUAL) {
-		rc = -ENODEV;
-	}
-
-test_nvram_done:
-	return rc;
-}
-
-static int
-bnx2_test_link(struct bnx2 *bp)
-{
-	u32 bmsr;
-
-	if (!netif_running(bp->dev))
-		return -ENODEV;
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) {
-		if (bp->link_up)
-			return 0;
-		return -ENODEV;
-	}
-	spin_lock_bh(&bp->phy_lock);
-	bnx2_enable_bmsr1(bp);
-	bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
-	bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
-	bnx2_disable_bmsr1(bp);
-	spin_unlock_bh(&bp->phy_lock);
-
-	if (bmsr & BMSR_LSTATUS) {
-		return 0;
-	}
-	return -ENODEV;
-}
-
-static int
-bnx2_test_intr(struct bnx2 *bp)
-{
-	int i;
-	u16 status_idx;
-
-	if (!netif_running(bp->dev))
-		return -ENODEV;
-
-	status_idx = REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff;
-
-	/* This register is not touched during run-time. */
-	REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
-	REG_RD(bp, BNX2_HC_COMMAND);
-
-	for (i = 0; i < 10; i++) {
-		if ((REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff) !=
-			status_idx) {
-
-			break;
-		}
-
-		msleep_interruptible(10);
-	}
-	if (i < 10)
-		return 0;
-
-	return -ENODEV;
-}
-
-/* Determining link for parallel detection. */
-static int
-bnx2_5706_serdes_has_link(struct bnx2 *bp)
-{
-	u32 mode_ctl, an_dbg, exp;
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_NO_PARALLEL)
-		return 0;
-
-	bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_MODE_CTL);
-	bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &mode_ctl);
-
-	if (!(mode_ctl & MISC_SHDW_MODE_CTL_SIG_DET))
-		return 0;
-
-	bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_AN_DBG);
-	bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg);
-	bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg);
-
-	if (an_dbg & (MISC_SHDW_AN_DBG_NOSYNC | MISC_SHDW_AN_DBG_RUDI_INVALID))
-		return 0;
-
-	bnx2_write_phy(bp, MII_BNX2_DSP_ADDRESS, MII_EXPAND_REG1);
-	bnx2_read_phy(bp, MII_BNX2_DSP_RW_PORT, &exp);
-	bnx2_read_phy(bp, MII_BNX2_DSP_RW_PORT, &exp);
-
-	if (exp & MII_EXPAND_REG1_RUDI_C)	/* receiving CONFIG */
-		return 0;
-
-	return 1;
-}
-
-static void
-bnx2_5706_serdes_timer(struct bnx2 *bp)
-{
-	int check_link = 1;
-
-	spin_lock(&bp->phy_lock);
-	if (bp->serdes_an_pending) {
-		bp->serdes_an_pending--;
-		check_link = 0;
-	} else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) {
-		u32 bmcr;
-
-		bp->current_interval = BNX2_TIMER_INTERVAL;
-
-		bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
-
-		if (bmcr & BMCR_ANENABLE) {
-			if (bnx2_5706_serdes_has_link(bp)) {
-				bmcr &= ~BMCR_ANENABLE;
-				bmcr |= BMCR_SPEED1000 | BMCR_FULLDPLX;
-				bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
-				bp->phy_flags |= BNX2_PHY_FLAG_PARALLEL_DETECT;
-			}
-		}
-	}
-	else if ((bp->link_up) && (bp->autoneg & AUTONEG_SPEED) &&
-		 (bp->phy_flags & BNX2_PHY_FLAG_PARALLEL_DETECT)) {
-		u32 phy2;
-
-		bnx2_write_phy(bp, 0x17, 0x0f01);
-		bnx2_read_phy(bp, 0x15, &phy2);
-		if (phy2 & 0x20) {
-			u32 bmcr;
-
-			bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
-			bmcr |= BMCR_ANENABLE;
-			bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
-
-			bp->phy_flags &= ~BNX2_PHY_FLAG_PARALLEL_DETECT;
-		}
-	} else
-		bp->current_interval = BNX2_TIMER_INTERVAL;
-
-	if (check_link) {
-		u32 val;
-
-		bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_AN_DBG);
-		bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &val);
-		bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &val);
-
-		if (bp->link_up && (val & MISC_SHDW_AN_DBG_NOSYNC)) {
-			if (!(bp->phy_flags & BNX2_PHY_FLAG_FORCED_DOWN)) {
-				bnx2_5706s_force_link_dn(bp, 1);
-				bp->phy_flags |= BNX2_PHY_FLAG_FORCED_DOWN;
-			} else
-				bnx2_set_link(bp);
-		} else if (!bp->link_up && !(val & MISC_SHDW_AN_DBG_NOSYNC))
-			bnx2_set_link(bp);
-	}
-	spin_unlock(&bp->phy_lock);
-}
-
-static void
-bnx2_5708_serdes_timer(struct bnx2 *bp)
-{
-	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
-		return;
-
-	if ((bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE) == 0) {
-		bp->serdes_an_pending = 0;
-		return;
-	}
-
-	spin_lock(&bp->phy_lock);
-	if (bp->serdes_an_pending)
-		bp->serdes_an_pending--;
-	else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) {
-		u32 bmcr;
-
-		bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
-		if (bmcr & BMCR_ANENABLE) {
-			bnx2_enable_forced_2g5(bp);
-			bp->current_interval = BNX2_SERDES_FORCED_TIMEOUT;
-		} else {
-			bnx2_disable_forced_2g5(bp);
-			bp->serdes_an_pending = 2;
-			bp->current_interval = BNX2_TIMER_INTERVAL;
-		}
-
-	} else
-		bp->current_interval = BNX2_TIMER_INTERVAL;
-
-	spin_unlock(&bp->phy_lock);
-}
-
-static void
-bnx2_timer(unsigned long data)
-{
-	struct bnx2 *bp = (struct bnx2 *) data;
-
-	if (!netif_running(bp->dev))
-		return;
-
-	if (atomic_read(&bp->intr_sem) != 0)
-		goto bnx2_restart_timer;
-
-	if ((bp->flags & (BNX2_FLAG_USING_MSI | BNX2_FLAG_ONE_SHOT_MSI)) ==
-	     BNX2_FLAG_USING_MSI)
-		bnx2_chk_missed_msi(bp);
-
-	bnx2_send_heart_beat(bp);
-
-	bp->stats_blk->stat_FwRxDrop =
-		bnx2_reg_rd_ind(bp, BNX2_FW_RX_DROP_COUNT);
-
-	/* workaround occasional corrupted counters */
-	if ((bp->flags & BNX2_FLAG_BROKEN_STATS) && bp->stats_ticks)
-		REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd |
-					    BNX2_HC_COMMAND_STATS_NOW);
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
-		if (CHIP_NUM(bp) == CHIP_NUM_5706)
-			bnx2_5706_serdes_timer(bp);
-		else
-			bnx2_5708_serdes_timer(bp);
-	}
-
-bnx2_restart_timer:
-	mod_timer(&bp->timer, jiffies + bp->current_interval);
-}
-
-static int
-bnx2_request_irq(struct bnx2 *bp)
-{
-	unsigned long flags;
-	struct bnx2_irq *irq;
-	int rc = 0, i;
-
-	if (bp->flags & BNX2_FLAG_USING_MSI_OR_MSIX)
-		flags = 0;
-	else
-		flags = IRQF_SHARED;
-
-	for (i = 0; i < bp->irq_nvecs; i++) {
-		irq = &bp->irq_tbl[i];
-		rc = request_irq(irq->vector, irq->handler, flags, irq->name,
-				 &bp->bnx2_napi[i]);
-		if (rc)
-			break;
-		irq->requested = 1;
-	}
-	return rc;
-}
-
-static void
-__bnx2_free_irq(struct bnx2 *bp)
-{
-	struct bnx2_irq *irq;
-	int i;
-
-	for (i = 0; i < bp->irq_nvecs; i++) {
-		irq = &bp->irq_tbl[i];
-		if (irq->requested)
-			free_irq(irq->vector, &bp->bnx2_napi[i]);
-		irq->requested = 0;
-	}
-}
-
-static void
-bnx2_free_irq(struct bnx2 *bp)
-{
-
-	__bnx2_free_irq(bp);
-	if (bp->flags & BNX2_FLAG_USING_MSI)
-		pci_disable_msi(bp->pdev);
-	else if (bp->flags & BNX2_FLAG_USING_MSIX)
-		pci_disable_msix(bp->pdev);
-
-	bp->flags &= ~(BNX2_FLAG_USING_MSI_OR_MSIX | BNX2_FLAG_ONE_SHOT_MSI);
-}
-
-static void
-bnx2_enable_msix(struct bnx2 *bp, int msix_vecs)
-{
-	int i, total_vecs, rc;
-	struct msix_entry msix_ent[BNX2_MAX_MSIX_VEC];
-	struct net_device *dev = bp->dev;
-	const int len = sizeof(bp->irq_tbl[0].name);
-
-	bnx2_setup_msix_tbl(bp);
-	REG_WR(bp, BNX2_PCI_MSIX_CONTROL, BNX2_MAX_MSIX_HW_VEC - 1);
-	REG_WR(bp, BNX2_PCI_MSIX_TBL_OFF_BIR, BNX2_PCI_GRC_WINDOW2_BASE);
-	REG_WR(bp, BNX2_PCI_MSIX_PBA_OFF_BIT, BNX2_PCI_GRC_WINDOW3_BASE);
-
-	/*  Need to flush the previous three writes to ensure MSI-X
-	 *  is setup properly */
-	REG_RD(bp, BNX2_PCI_MSIX_CONTROL);
-
-	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {
-		msix_ent[i].entry = i;
-		msix_ent[i].vector = 0;
-	}
-
-	total_vecs = msix_vecs;
-#ifdef BCM_CNIC
-	total_vecs++;
-#endif
-	rc = -ENOSPC;
-	while (total_vecs >= BNX2_MIN_MSIX_VEC) {
-		rc = pci_enable_msix(bp->pdev, msix_ent, total_vecs);
-		if (rc <= 0)
-			break;
-		if (rc > 0)
-			total_vecs = rc;
-	}
-
-	if (rc != 0)
-		return;
-
-	msix_vecs = total_vecs;
-#ifdef BCM_CNIC
-	msix_vecs--;
-#endif
-	bp->irq_nvecs = msix_vecs;
-	bp->flags |= BNX2_FLAG_USING_MSIX | BNX2_FLAG_ONE_SHOT_MSI;
-	for (i = 0; i < total_vecs; i++) {
-		bp->irq_tbl[i].vector = msix_ent[i].vector;
-		snprintf(bp->irq_tbl[i].name, len, "%s-%d", dev->name, i);
-		bp->irq_tbl[i].handler = bnx2_msi_1shot;
-	}
-}
-
-static int
-bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
-{
-	int cpus = num_online_cpus();
-	int msix_vecs = min(cpus + 1, RX_MAX_RINGS);
-
-	bp->irq_tbl[0].handler = bnx2_interrupt;
-	strcpy(bp->irq_tbl[0].name, bp->dev->name);
-	bp->irq_nvecs = 1;
-	bp->irq_tbl[0].vector = bp->pdev->irq;
-
-	if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !dis_msi)
-		bnx2_enable_msix(bp, msix_vecs);
-
-	if ((bp->flags & BNX2_FLAG_MSI_CAP) && !dis_msi &&
-	    !(bp->flags & BNX2_FLAG_USING_MSIX)) {
-		if (pci_enable_msi(bp->pdev) == 0) {
-			bp->flags |= BNX2_FLAG_USING_MSI;
-			if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-				bp->flags |= BNX2_FLAG_ONE_SHOT_MSI;
-				bp->irq_tbl[0].handler = bnx2_msi_1shot;
-			} else
-				bp->irq_tbl[0].handler = bnx2_msi;
-
-			bp->irq_tbl[0].vector = bp->pdev->irq;
-		}
-	}
-
-	bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs);
-	netif_set_real_num_tx_queues(bp->dev, bp->num_tx_rings);
-
-	bp->num_rx_rings = bp->irq_nvecs;
-	return netif_set_real_num_rx_queues(bp->dev, bp->num_rx_rings);
-}
-
-/* Called with rtnl_lock */
-static int
-bnx2_open(struct net_device *dev)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-	int rc;
-
-	netif_carrier_off(dev);
-
-	bnx2_set_power_state(bp, PCI_D0);
-	bnx2_disable_int(bp);
-
-	rc = bnx2_setup_int_mode(bp, disable_msi);
-	if (rc)
-		goto open_err;
-	bnx2_init_napi(bp);
-	bnx2_napi_enable(bp);
-	rc = bnx2_alloc_mem(bp);
-	if (rc)
-		goto open_err;
-
-	rc = bnx2_request_irq(bp);
-	if (rc)
-		goto open_err;
-
-	rc = bnx2_init_nic(bp, 1);
-	if (rc)
-		goto open_err;
-
-	mod_timer(&bp->timer, jiffies + bp->current_interval);
-
-	atomic_set(&bp->intr_sem, 0);
-
-	memset(bp->temp_stats_blk, 0, sizeof(struct statistics_block));
-
-	bnx2_enable_int(bp);
-
-	if (bp->flags & BNX2_FLAG_USING_MSI) {
-		/* Test MSI to make sure it is working
-		 * If MSI test fails, go back to INTx mode
-		 */
-		if (bnx2_test_intr(bp) != 0) {
-			netdev_warn(bp->dev, "No interrupt was generated using MSI, switching to INTx mode. Please report this failure to the PCI maintainer and include system chipset information.\n");
-
-			bnx2_disable_int(bp);
-			bnx2_free_irq(bp);
-
-			bnx2_setup_int_mode(bp, 1);
-
-			rc = bnx2_init_nic(bp, 0);
-
-			if (!rc)
-				rc = bnx2_request_irq(bp);
-
-			if (rc) {
-				del_timer_sync(&bp->timer);
-				goto open_err;
-			}
-			bnx2_enable_int(bp);
-		}
-	}
-	if (bp->flags & BNX2_FLAG_USING_MSI)
-		netdev_info(dev, "using MSI\n");
-	else if (bp->flags & BNX2_FLAG_USING_MSIX)
-		netdev_info(dev, "using MSIX\n");
-
-	netif_tx_start_all_queues(dev);
-
-	return 0;
-
-open_err:
-	bnx2_napi_disable(bp);
-	bnx2_free_skbs(bp);
-	bnx2_free_irq(bp);
-	bnx2_free_mem(bp);
-	bnx2_del_napi(bp);
-	return rc;
-}
-
-static void
-bnx2_reset_task(struct work_struct *work)
-{
-	struct bnx2 *bp = container_of(work, struct bnx2, reset_task);
-	int rc;
-
-	rtnl_lock();
-	if (!netif_running(bp->dev)) {
-		rtnl_unlock();
-		return;
-	}
-
-	bnx2_netif_stop(bp, true);
-
-	rc = bnx2_init_nic(bp, 1);
-	if (rc) {
-		netdev_err(bp->dev, "failed to reset NIC, closing\n");
-		bnx2_napi_enable(bp);
-		dev_close(bp->dev);
-		rtnl_unlock();
-		return;
-	}
-
-	atomic_set(&bp->intr_sem, 1);
-	bnx2_netif_start(bp, true);
-	rtnl_unlock();
-}
-
-static void
-bnx2_dump_state(struct bnx2 *bp)
-{
-	struct net_device *dev = bp->dev;
-	u32 val1, val2;
-
-	pci_read_config_dword(bp->pdev, PCI_COMMAND, &val1);
-	netdev_err(dev, "DEBUG: intr_sem[%x] PCI_CMD[%08x]\n",
-		   atomic_read(&bp->intr_sem), val1);
-	pci_read_config_dword(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &val1);
-	pci_read_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG, &val2);
-	netdev_err(dev, "DEBUG: PCI_PM[%08x] PCI_MISC_CFG[%08x]\n", val1, val2);
-	netdev_err(dev, "DEBUG: EMAC_TX_STATUS[%08x] EMAC_RX_STATUS[%08x]\n",
-		   REG_RD(bp, BNX2_EMAC_TX_STATUS),
-		   REG_RD(bp, BNX2_EMAC_RX_STATUS));
-	netdev_err(dev, "DEBUG: RPM_MGMT_PKT_CTRL[%08x]\n",
-		   REG_RD(bp, BNX2_RPM_MGMT_PKT_CTRL));
-	netdev_err(dev, "DEBUG: HC_STATS_INTERRUPT_STATUS[%08x]\n",
-		   REG_RD(bp, BNX2_HC_STATS_INTERRUPT_STATUS));
-	if (bp->flags & BNX2_FLAG_USING_MSIX)
-		netdev_err(dev, "DEBUG: PBA[%08x]\n",
-			   REG_RD(bp, BNX2_PCI_GRC_WINDOW3_BASE));
-}
-
-static void
-bnx2_tx_timeout(struct net_device *dev)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	bnx2_dump_state(bp);
-	bnx2_dump_mcp_state(bp);
-
-	/* This allows the netif to be shutdown gracefully before resetting */
-	schedule_work(&bp->reset_task);
-}
-
-/* Called with netif_tx_lock.
- * bnx2_tx_int() runs without netif_tx_lock unless it needs to call
- * netif_wake_queue().
- */
-static netdev_tx_t
-bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-	dma_addr_t mapping;
-	struct tx_bd *txbd;
-	struct sw_tx_bd *tx_buf;
-	u32 len, vlan_tag_flags, last_frag, mss;
-	u16 prod, ring_prod;
-	int i;
-	struct bnx2_napi *bnapi;
-	struct bnx2_tx_ring_info *txr;
-	struct netdev_queue *txq;
-
-	/*  Determine which tx ring we will be placed on */
-	i = skb_get_queue_mapping(skb);
-	bnapi = &bp->bnx2_napi[i];
-	txr = &bnapi->tx_ring;
-	txq = netdev_get_tx_queue(dev, i);
-
-	if (unlikely(bnx2_tx_avail(bp, txr) <
-	    (skb_shinfo(skb)->nr_frags + 1))) {
-		netif_tx_stop_queue(txq);
-		netdev_err(dev, "BUG! Tx ring full when queue awake!\n");
-
-		return NETDEV_TX_BUSY;
-	}
-	len = skb_headlen(skb);
-	prod = txr->tx_prod;
-	ring_prod = TX_RING_IDX(prod);
-
-	vlan_tag_flags = 0;
-	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM;
-	}
-
-	if (vlan_tx_tag_present(skb)) {
-		vlan_tag_flags |=
-			(TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
-	}
-
-	if ((mss = skb_shinfo(skb)->gso_size)) {
-		u32 tcp_opt_len;
-		struct iphdr *iph;
-
-		vlan_tag_flags |= TX_BD_FLAGS_SW_LSO;
-
-		tcp_opt_len = tcp_optlen(skb);
-
-		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) {
-			u32 tcp_off = skb_transport_offset(skb) -
-				      sizeof(struct ipv6hdr) - ETH_HLEN;
-
-			vlan_tag_flags |= ((tcp_opt_len >> 2) << 8) |
-					  TX_BD_FLAGS_SW_FLAGS;
-			if (likely(tcp_off == 0))
-				vlan_tag_flags &= ~TX_BD_FLAGS_TCP6_OFF0_MSK;
-			else {
-				tcp_off >>= 3;
-				vlan_tag_flags |= ((tcp_off & 0x3) <<
-						   TX_BD_FLAGS_TCP6_OFF0_SHL) |
-						  ((tcp_off & 0x10) <<
-						   TX_BD_FLAGS_TCP6_OFF4_SHL);
-				mss |= (tcp_off & 0xc) << TX_BD_TCP6_OFF2_SHL;
-			}
-		} else {
-			iph = ip_hdr(skb);
-			if (tcp_opt_len || (iph->ihl > 5)) {
-				vlan_tag_flags |= ((iph->ihl - 5) +
-						   (tcp_opt_len >> 2)) << 8;
-			}
-		}
-	} else
-		mss = 0;
-
-	mapping = dma_map_single(&bp->pdev->dev, skb->data, len, PCI_DMA_TODEVICE);
-	if (dma_mapping_error(&bp->pdev->dev, mapping)) {
-		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-
-	tx_buf = &txr->tx_buf_ring[ring_prod];
-	tx_buf->skb = skb;
-	dma_unmap_addr_set(tx_buf, mapping, mapping);
-
-	txbd = &txr->tx_desc_ring[ring_prod];
-
-	txbd->tx_bd_haddr_hi = (u64) mapping >> 32;
-	txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff;
-	txbd->tx_bd_mss_nbytes = len | (mss << 16);
-	txbd->tx_bd_vlan_tag_flags = vlan_tag_flags | TX_BD_FLAGS_START;
-
-	last_frag = skb_shinfo(skb)->nr_frags;
-	tx_buf->nr_frags = last_frag;
-	tx_buf->is_gso = skb_is_gso(skb);
-
-	for (i = 0; i < last_frag; i++) {
-		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
-		prod = NEXT_TX_BD(prod);
-		ring_prod = TX_RING_IDX(prod);
-		txbd = &txr->tx_desc_ring[ring_prod];
-
-		len = frag->size;
-		mapping = dma_map_page(&bp->pdev->dev, frag->page, frag->page_offset,
-				       len, PCI_DMA_TODEVICE);
-		if (dma_mapping_error(&bp->pdev->dev, mapping))
-			goto dma_error;
-		dma_unmap_addr_set(&txr->tx_buf_ring[ring_prod], mapping,
-				   mapping);
-
-		txbd->tx_bd_haddr_hi = (u64) mapping >> 32;
-		txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff;
-		txbd->tx_bd_mss_nbytes = len | (mss << 16);
-		txbd->tx_bd_vlan_tag_flags = vlan_tag_flags;
-
-	}
-	txbd->tx_bd_vlan_tag_flags |= TX_BD_FLAGS_END;
-
-	prod = NEXT_TX_BD(prod);
-	txr->tx_prod_bseq += skb->len;
-
-	REG_WR16(bp, txr->tx_bidx_addr, prod);
-	REG_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq);
-
-	mmiowb();
-
-	txr->tx_prod = prod;
-
-	if (unlikely(bnx2_tx_avail(bp, txr) <= MAX_SKB_FRAGS)) {
-		netif_tx_stop_queue(txq);
-
-		/* netif_tx_stop_queue() must be done before checking
-		 * tx index in bnx2_tx_avail() below, because in
-		 * bnx2_tx_int(), we update tx index before checking for
-		 * netif_tx_queue_stopped().
-		 */
-		smp_mb();
-		if (bnx2_tx_avail(bp, txr) > bp->tx_wake_thresh)
-			netif_tx_wake_queue(txq);
-	}
-
-	return NETDEV_TX_OK;
-dma_error:
-	/* save value of frag that failed */
-	last_frag = i;
-
-	/* start back at beginning and unmap skb */
-	prod = txr->tx_prod;
-	ring_prod = TX_RING_IDX(prod);
-	tx_buf = &txr->tx_buf_ring[ring_prod];
-	tx_buf->skb = NULL;
-	dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping),
-			 skb_headlen(skb), PCI_DMA_TODEVICE);
-
-	/* unmap remaining mapped pages */
-	for (i = 0; i < last_frag; i++) {
-		prod = NEXT_TX_BD(prod);
-		ring_prod = TX_RING_IDX(prod);
-		tx_buf = &txr->tx_buf_ring[ring_prod];
-		dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping),
-			       skb_shinfo(skb)->frags[i].size,
-			       PCI_DMA_TODEVICE);
-	}
-
-	dev_kfree_skb(skb);
-	return NETDEV_TX_OK;
-}
-
-/* Called with rtnl_lock */
-static int
-bnx2_close(struct net_device *dev)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	bnx2_disable_int_sync(bp);
-	bnx2_napi_disable(bp);
-	del_timer_sync(&bp->timer);
-	bnx2_shutdown_chip(bp);
-	bnx2_free_irq(bp);
-	bnx2_free_skbs(bp);
-	bnx2_free_mem(bp);
-	bnx2_del_napi(bp);
-	bp->link_up = 0;
-	netif_carrier_off(bp->dev);
-	bnx2_set_power_state(bp, PCI_D3hot);
-	return 0;
-}
-
-static void
-bnx2_save_stats(struct bnx2 *bp)
-{
-	u32 *hw_stats = (u32 *) bp->stats_blk;
-	u32 *temp_stats = (u32 *) bp->temp_stats_blk;
-	int i;
-
-	/* The 1st 10 counters are 64-bit counters */
-	for (i = 0; i < 20; i += 2) {
-		u32 hi;
-		u64 lo;
-
-		hi = temp_stats[i] + hw_stats[i];
-		lo = (u64) temp_stats[i + 1] + (u64) hw_stats[i + 1];
-		if (lo > 0xffffffff)
-			hi++;
-		temp_stats[i] = hi;
-		temp_stats[i + 1] = lo & 0xffffffff;
-	}
-
-	for ( ; i < sizeof(struct statistics_block) / 4; i++)
-		temp_stats[i] += hw_stats[i];
-}
-
-#define GET_64BIT_NET_STATS64(ctr)		\
-	(((u64) (ctr##_hi) << 32) + (u64) (ctr##_lo))
-
-#define GET_64BIT_NET_STATS(ctr)				\
-	GET_64BIT_NET_STATS64(bp->stats_blk->ctr) +		\
-	GET_64BIT_NET_STATS64(bp->temp_stats_blk->ctr)
-
-#define GET_32BIT_NET_STATS(ctr)				\
-	(unsigned long) (bp->stats_blk->ctr +			\
-			 bp->temp_stats_blk->ctr)
-
-static struct rtnl_link_stats64 *
-bnx2_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	if (bp->stats_blk == NULL)
-		return net_stats;
-
-	net_stats->rx_packets =
-		GET_64BIT_NET_STATS(stat_IfHCInUcastPkts) +
-		GET_64BIT_NET_STATS(stat_IfHCInMulticastPkts) +
-		GET_64BIT_NET_STATS(stat_IfHCInBroadcastPkts);
-
-	net_stats->tx_packets =
-		GET_64BIT_NET_STATS(stat_IfHCOutUcastPkts) +
-		GET_64BIT_NET_STATS(stat_IfHCOutMulticastPkts) +
-		GET_64BIT_NET_STATS(stat_IfHCOutBroadcastPkts);
-
-	net_stats->rx_bytes =
-		GET_64BIT_NET_STATS(stat_IfHCInOctets);
-
-	net_stats->tx_bytes =
-		GET_64BIT_NET_STATS(stat_IfHCOutOctets);
-
-	net_stats->multicast =
-		GET_64BIT_NET_STATS(stat_IfHCInMulticastPkts);
-
-	net_stats->collisions =
-		GET_32BIT_NET_STATS(stat_EtherStatsCollisions);
-
-	net_stats->rx_length_errors =
-		GET_32BIT_NET_STATS(stat_EtherStatsUndersizePkts) +
-		GET_32BIT_NET_STATS(stat_EtherStatsOverrsizePkts);
-
-	net_stats->rx_over_errors =
-		GET_32BIT_NET_STATS(stat_IfInFTQDiscards) +
-		GET_32BIT_NET_STATS(stat_IfInMBUFDiscards);
-
-	net_stats->rx_frame_errors =
-		GET_32BIT_NET_STATS(stat_Dot3StatsAlignmentErrors);
-
-	net_stats->rx_crc_errors =
-		GET_32BIT_NET_STATS(stat_Dot3StatsFCSErrors);
-
-	net_stats->rx_errors = net_stats->rx_length_errors +
-		net_stats->rx_over_errors + net_stats->rx_frame_errors +
-		net_stats->rx_crc_errors;
-
-	net_stats->tx_aborted_errors =
-		GET_32BIT_NET_STATS(stat_Dot3StatsExcessiveCollisions) +
-		GET_32BIT_NET_STATS(stat_Dot3StatsLateCollisions);
-
-	if ((CHIP_NUM(bp) == CHIP_NUM_5706) ||
-	    (CHIP_ID(bp) == CHIP_ID_5708_A0))
-		net_stats->tx_carrier_errors = 0;
-	else {
-		net_stats->tx_carrier_errors =
-			GET_32BIT_NET_STATS(stat_Dot3StatsCarrierSenseErrors);
-	}
-
-	net_stats->tx_errors =
-		GET_32BIT_NET_STATS(stat_emac_tx_stat_dot3statsinternalmactransmiterrors) +
-		net_stats->tx_aborted_errors +
-		net_stats->tx_carrier_errors;
-
-	net_stats->rx_missed_errors =
-		GET_32BIT_NET_STATS(stat_IfInFTQDiscards) +
-		GET_32BIT_NET_STATS(stat_IfInMBUFDiscards) +
-		GET_32BIT_NET_STATS(stat_FwRxDrop);
-
-	return net_stats;
-}
-
-/* All ethtool functions called with rtnl_lock */
-
-static int
-bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-	int support_serdes = 0, support_copper = 0;
-
-	cmd->supported = SUPPORTED_Autoneg;
-	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) {
-		support_serdes = 1;
-		support_copper = 1;
-	} else if (bp->phy_port == PORT_FIBRE)
-		support_serdes = 1;
-	else
-		support_copper = 1;
-
-	if (support_serdes) {
-		cmd->supported |= SUPPORTED_1000baseT_Full |
-			SUPPORTED_FIBRE;
-		if (bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)
-			cmd->supported |= SUPPORTED_2500baseX_Full;
-
-	}
-	if (support_copper) {
-		cmd->supported |= SUPPORTED_10baseT_Half |
-			SUPPORTED_10baseT_Full |
-			SUPPORTED_100baseT_Half |
-			SUPPORTED_100baseT_Full |
-			SUPPORTED_1000baseT_Full |
-			SUPPORTED_TP;
-
-	}
-
-	spin_lock_bh(&bp->phy_lock);
-	cmd->port = bp->phy_port;
-	cmd->advertising = bp->advertising;
-
-	if (bp->autoneg & AUTONEG_SPEED) {
-		cmd->autoneg = AUTONEG_ENABLE;
-	} else {
-		cmd->autoneg = AUTONEG_DISABLE;
-	}
-
-	if (netif_carrier_ok(dev)) {
-		ethtool_cmd_speed_set(cmd, bp->line_speed);
-		cmd->duplex = bp->duplex;
-	}
-	else {
-		ethtool_cmd_speed_set(cmd, -1);
-		cmd->duplex = -1;
-	}
-	spin_unlock_bh(&bp->phy_lock);
-
-	cmd->transceiver = XCVR_INTERNAL;
-	cmd->phy_address = bp->phy_addr;
-
-	return 0;
-}
-
-static int
-bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-	u8 autoneg = bp->autoneg;
-	u8 req_duplex = bp->req_duplex;
-	u16 req_line_speed = bp->req_line_speed;
-	u32 advertising = bp->advertising;
-	int err = -EINVAL;
-
-	spin_lock_bh(&bp->phy_lock);
-
-	if (cmd->port != PORT_TP && cmd->port != PORT_FIBRE)
-		goto err_out_unlock;
-
-	if (cmd->port != bp->phy_port &&
-	    !(bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP))
-		goto err_out_unlock;
-
-	/* If device is down, we can store the settings only if the user
-	 * is setting the currently active port.
-	 */
-	if (!netif_running(dev) && cmd->port != bp->phy_port)
-		goto err_out_unlock;
-
-	if (cmd->autoneg == AUTONEG_ENABLE) {
-		autoneg |= AUTONEG_SPEED;
-
-		advertising = cmd->advertising;
-		if (cmd->port == PORT_TP) {
-			advertising &= ETHTOOL_ALL_COPPER_SPEED;
-			if (!advertising)
-				advertising = ETHTOOL_ALL_COPPER_SPEED;
-		} else {
-			advertising &= ETHTOOL_ALL_FIBRE_SPEED;
-			if (!advertising)
-				advertising = ETHTOOL_ALL_FIBRE_SPEED;
-		}
-		advertising |= ADVERTISED_Autoneg;
-	}
-	else {
-		u32 speed = ethtool_cmd_speed(cmd);
-		if (cmd->port == PORT_FIBRE) {
-			if ((speed != SPEED_1000 &&
-			     speed != SPEED_2500) ||
-			    (cmd->duplex != DUPLEX_FULL))
-				goto err_out_unlock;
-
-			if (speed == SPEED_2500 &&
-			    !(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
-				goto err_out_unlock;
-		} else if (speed == SPEED_1000 || speed == SPEED_2500)
-			goto err_out_unlock;
-
-		autoneg &= ~AUTONEG_SPEED;
-		req_line_speed = speed;
-		req_duplex = cmd->duplex;
-		advertising = 0;
-	}
-
-	bp->autoneg = autoneg;
-	bp->advertising = advertising;
-	bp->req_line_speed = req_line_speed;
-	bp->req_duplex = req_duplex;
-
-	err = 0;
-	/* If device is down, the new settings will be picked up when it is
-	 * brought up.
-	 */
-	if (netif_running(dev))
-		err = bnx2_setup_phy(bp, cmd->port);
-
-err_out_unlock:
-	spin_unlock_bh(&bp->phy_lock);
-
-	return err;
-}
-
-static void
-bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	strcpy(info->driver, DRV_MODULE_NAME);
-	strcpy(info->version, DRV_MODULE_VERSION);
-	strcpy(info->bus_info, pci_name(bp->pdev));
-	strcpy(info->fw_version, bp->fw_version);
-}
-
-#define BNX2_REGDUMP_LEN		(32 * 1024)
-
-static int
-bnx2_get_regs_len(struct net_device *dev)
-{
-	return BNX2_REGDUMP_LEN;
-}
-
-static void
-bnx2_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *_p)
-{
-	u32 *p = _p, i, offset;
-	u8 *orig_p = _p;
-	struct bnx2 *bp = netdev_priv(dev);
-	static const u32 reg_boundaries[] = {
-		0x0000, 0x0098, 0x0400, 0x045c,
-		0x0800, 0x0880, 0x0c00, 0x0c10,
-		0x0c30, 0x0d08, 0x1000, 0x101c,
-		0x1040, 0x1048, 0x1080, 0x10a4,
-		0x1400, 0x1490, 0x1498, 0x14f0,
-		0x1500, 0x155c, 0x1580, 0x15dc,
-		0x1600, 0x1658, 0x1680, 0x16d8,
-		0x1800, 0x1820, 0x1840, 0x1854,
-		0x1880, 0x1894, 0x1900, 0x1984,
-		0x1c00, 0x1c0c, 0x1c40, 0x1c54,
-		0x1c80, 0x1c94, 0x1d00, 0x1d84,
-		0x2000, 0x2030, 0x23c0, 0x2400,
-		0x2800, 0x2820, 0x2830, 0x2850,
-		0x2b40, 0x2c10, 0x2fc0, 0x3058,
-		0x3c00, 0x3c94, 0x4000, 0x4010,
-		0x4080, 0x4090, 0x43c0, 0x4458,
-		0x4c00, 0x4c18, 0x4c40, 0x4c54,
-		0x4fc0, 0x5010, 0x53c0, 0x5444,
-		0x5c00, 0x5c18, 0x5c80, 0x5c90,
-		0x5fc0, 0x6000, 0x6400, 0x6428,
-		0x6800, 0x6848, 0x684c, 0x6860,
-		0x6888, 0x6910, 0x8000
-	};
-
-	regs->version = 0;
-
-	memset(p, 0, BNX2_REGDUMP_LEN);
-
-	if (!netif_running(bp->dev))
-		return;
-
-	i = 0;
-	offset = reg_boundaries[0];
-	p += offset;
-	while (offset < BNX2_REGDUMP_LEN) {
-		*p++ = REG_RD(bp, offset);
-		offset += 4;
-		if (offset == reg_boundaries[i + 1]) {
-			offset = reg_boundaries[i + 2];
-			p = (u32 *) (orig_p + offset);
-			i += 2;
-		}
-	}
-}
-
-static void
-bnx2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	if (bp->flags & BNX2_FLAG_NO_WOL) {
-		wol->supported = 0;
-		wol->wolopts = 0;
-	}
-	else {
-		wol->supported = WAKE_MAGIC;
-		if (bp->wol)
-			wol->wolopts = WAKE_MAGIC;
-		else
-			wol->wolopts = 0;
-	}
-	memset(&wol->sopass, 0, sizeof(wol->sopass));
-}
-
-static int
-bnx2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	if (wol->wolopts & ~WAKE_MAGIC)
-		return -EINVAL;
-
-	if (wol->wolopts & WAKE_MAGIC) {
-		if (bp->flags & BNX2_FLAG_NO_WOL)
-			return -EINVAL;
-
-		bp->wol = 1;
-	}
-	else {
-		bp->wol = 0;
-	}
-	return 0;
-}
-
-static int
-bnx2_nway_reset(struct net_device *dev)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-	u32 bmcr;
-
-	if (!netif_running(dev))
-		return -EAGAIN;
-
-	if (!(bp->autoneg & AUTONEG_SPEED)) {
-		return -EINVAL;
-	}
-
-	spin_lock_bh(&bp->phy_lock);
-
-	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) {
-		int rc;
-
-		rc = bnx2_setup_remote_phy(bp, bp->phy_port);
-		spin_unlock_bh(&bp->phy_lock);
-		return rc;
-	}
-
-	/* Force a link down visible on the other side */
-	if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
-		bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK);
-		spin_unlock_bh(&bp->phy_lock);
-
-		msleep(20);
-
-		spin_lock_bh(&bp->phy_lock);
-
-		bp->current_interval = BNX2_SERDES_AN_TIMEOUT;
-		bp->serdes_an_pending = 1;
-		mod_timer(&bp->timer, jiffies + bp->current_interval);
-	}
-
-	bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
-	bmcr &= ~BMCR_LOOPBACK;
-	bnx2_write_phy(bp, bp->mii_bmcr, bmcr | BMCR_ANRESTART | BMCR_ANENABLE);
-
-	spin_unlock_bh(&bp->phy_lock);
-
-	return 0;
-}
-
-static u32
-bnx2_get_link(struct net_device *dev)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	return bp->link_up;
-}
-
-static int
-bnx2_get_eeprom_len(struct net_device *dev)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	if (bp->flash_info == NULL)
-		return 0;
-
-	return (int) bp->flash_size;
-}
-
-static int
-bnx2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
-		u8 *eebuf)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-	int rc;
-
-	if (!netif_running(dev))
-		return -EAGAIN;
-
-	/* parameters already validated in ethtool_get_eeprom */
-
-	rc = bnx2_nvram_read(bp, eeprom->offset, eebuf, eeprom->len);
-
-	return rc;
-}
-
-static int
-bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
-		u8 *eebuf)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-	int rc;
-
-	if (!netif_running(dev))
-		return -EAGAIN;
-
-	/* parameters already validated in ethtool_set_eeprom */
-
-	rc = bnx2_nvram_write(bp, eeprom->offset, eebuf, eeprom->len);
-
-	return rc;
-}
-
-static int
-bnx2_get_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	memset(coal, 0, sizeof(struct ethtool_coalesce));
-
-	coal->rx_coalesce_usecs = bp->rx_ticks;
-	coal->rx_max_coalesced_frames = bp->rx_quick_cons_trip;
-	coal->rx_coalesce_usecs_irq = bp->rx_ticks_int;
-	coal->rx_max_coalesced_frames_irq = bp->rx_quick_cons_trip_int;
-
-	coal->tx_coalesce_usecs = bp->tx_ticks;
-	coal->tx_max_coalesced_frames = bp->tx_quick_cons_trip;
-	coal->tx_coalesce_usecs_irq = bp->tx_ticks_int;
-	coal->tx_max_coalesced_frames_irq = bp->tx_quick_cons_trip_int;
-
-	coal->stats_block_coalesce_usecs = bp->stats_ticks;
-
-	return 0;
-}
-
-static int
-bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	bp->rx_ticks = (u16) coal->rx_coalesce_usecs;
-	if (bp->rx_ticks > 0x3ff) bp->rx_ticks = 0x3ff;
-
-	bp->rx_quick_cons_trip = (u16) coal->rx_max_coalesced_frames;
-	if (bp->rx_quick_cons_trip > 0xff) bp->rx_quick_cons_trip = 0xff;
-
-	bp->rx_ticks_int = (u16) coal->rx_coalesce_usecs_irq;
-	if (bp->rx_ticks_int > 0x3ff) bp->rx_ticks_int = 0x3ff;
-
-	bp->rx_quick_cons_trip_int = (u16) coal->rx_max_coalesced_frames_irq;
-	if (bp->rx_quick_cons_trip_int > 0xff)
-		bp->rx_quick_cons_trip_int = 0xff;
-
-	bp->tx_ticks = (u16) coal->tx_coalesce_usecs;
-	if (bp->tx_ticks > 0x3ff) bp->tx_ticks = 0x3ff;
-
-	bp->tx_quick_cons_trip = (u16) coal->tx_max_coalesced_frames;
-	if (bp->tx_quick_cons_trip > 0xff) bp->tx_quick_cons_trip = 0xff;
-
-	bp->tx_ticks_int = (u16) coal->tx_coalesce_usecs_irq;
-	if (bp->tx_ticks_int > 0x3ff) bp->tx_ticks_int = 0x3ff;
-
-	bp->tx_quick_cons_trip_int = (u16) coal->tx_max_coalesced_frames_irq;
-	if (bp->tx_quick_cons_trip_int > 0xff) bp->tx_quick_cons_trip_int =
-		0xff;
-
-	bp->stats_ticks = coal->stats_block_coalesce_usecs;
-	if (bp->flags & BNX2_FLAG_BROKEN_STATS) {
-		if (bp->stats_ticks != 0 && bp->stats_ticks != USEC_PER_SEC)
-			bp->stats_ticks = USEC_PER_SEC;
-	}
-	if (bp->stats_ticks > BNX2_HC_STATS_TICKS_HC_STAT_TICKS)
-		bp->stats_ticks = BNX2_HC_STATS_TICKS_HC_STAT_TICKS;
-	bp->stats_ticks &= BNX2_HC_STATS_TICKS_HC_STAT_TICKS;
-
-	if (netif_running(bp->dev)) {
-		bnx2_netif_stop(bp, true);
-		bnx2_init_nic(bp, 0);
-		bnx2_netif_start(bp, true);
-	}
-
-	return 0;
-}
-
-static void
-bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	ering->rx_max_pending = MAX_TOTAL_RX_DESC_CNT;
-	ering->rx_mini_max_pending = 0;
-	ering->rx_jumbo_max_pending = MAX_TOTAL_RX_PG_DESC_CNT;
-
-	ering->rx_pending = bp->rx_ring_size;
-	ering->rx_mini_pending = 0;
-	ering->rx_jumbo_pending = bp->rx_pg_ring_size;
-
-	ering->tx_max_pending = MAX_TX_DESC_CNT;
-	ering->tx_pending = bp->tx_ring_size;
-}
-
-static int
-bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
-{
-	if (netif_running(bp->dev)) {
-		/* Reset will erase chipset stats; save them */
-		bnx2_save_stats(bp);
-
-		bnx2_netif_stop(bp, true);
-		bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
-		__bnx2_free_irq(bp);
-		bnx2_free_skbs(bp);
-		bnx2_free_mem(bp);
-	}
-
-	bnx2_set_rx_ring_size(bp, rx);
-	bp->tx_ring_size = tx;
-
-	if (netif_running(bp->dev)) {
-		int rc;
-
-		rc = bnx2_alloc_mem(bp);
-		if (!rc)
-			rc = bnx2_request_irq(bp);
-
-		if (!rc)
-			rc = bnx2_init_nic(bp, 0);
-
-		if (rc) {
-			bnx2_napi_enable(bp);
-			dev_close(bp->dev);
-			return rc;
-		}
-#ifdef BCM_CNIC
-		mutex_lock(&bp->cnic_lock);
-		/* Let cnic know about the new status block. */
-		if (bp->cnic_eth_dev.drv_state & CNIC_DRV_STATE_REGD)
-			bnx2_setup_cnic_irq_info(bp);
-		mutex_unlock(&bp->cnic_lock);
-#endif
-		bnx2_netif_start(bp, true);
-	}
-	return 0;
-}
-
-static int
-bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-	int rc;
-
-	if ((ering->rx_pending > MAX_TOTAL_RX_DESC_CNT) ||
-		(ering->tx_pending > MAX_TX_DESC_CNT) ||
-		(ering->tx_pending <= MAX_SKB_FRAGS)) {
-
-		return -EINVAL;
-	}
-	rc = bnx2_change_ring_size(bp, ering->rx_pending, ering->tx_pending);
-	return rc;
-}
-
-static void
-bnx2_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	epause->autoneg = ((bp->autoneg & AUTONEG_FLOW_CTRL) != 0);
-	epause->rx_pause = ((bp->flow_ctrl & FLOW_CTRL_RX) != 0);
-	epause->tx_pause = ((bp->flow_ctrl & FLOW_CTRL_TX) != 0);
-}
-
-static int
-bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	bp->req_flow_ctrl = 0;
-	if (epause->rx_pause)
-		bp->req_flow_ctrl |= FLOW_CTRL_RX;
-	if (epause->tx_pause)
-		bp->req_flow_ctrl |= FLOW_CTRL_TX;
-
-	if (epause->autoneg) {
-		bp->autoneg |= AUTONEG_FLOW_CTRL;
-	}
-	else {
-		bp->autoneg &= ~AUTONEG_FLOW_CTRL;
-	}
-
-	if (netif_running(dev)) {
-		spin_lock_bh(&bp->phy_lock);
-		bnx2_setup_phy(bp, bp->phy_port);
-		spin_unlock_bh(&bp->phy_lock);
-	}
-
-	return 0;
-}
-
-static struct {
-	char string[ETH_GSTRING_LEN];
-} bnx2_stats_str_arr[] = {
-	{ "rx_bytes" },
-	{ "rx_error_bytes" },
-	{ "tx_bytes" },
-	{ "tx_error_bytes" },
-	{ "rx_ucast_packets" },
-	{ "rx_mcast_packets" },
-	{ "rx_bcast_packets" },
-	{ "tx_ucast_packets" },
-	{ "tx_mcast_packets" },
-	{ "tx_bcast_packets" },
-	{ "tx_mac_errors" },
-	{ "tx_carrier_errors" },
-	{ "rx_crc_errors" },
-	{ "rx_align_errors" },
-	{ "tx_single_collisions" },
-	{ "tx_multi_collisions" },
-	{ "tx_deferred" },
-	{ "tx_excess_collisions" },
-	{ "tx_late_collisions" },
-	{ "tx_total_collisions" },
-	{ "rx_fragments" },
-	{ "rx_jabbers" },
-	{ "rx_undersize_packets" },
-	{ "rx_oversize_packets" },
-	{ "rx_64_byte_packets" },
-	{ "rx_65_to_127_byte_packets" },
-	{ "rx_128_to_255_byte_packets" },
-	{ "rx_256_to_511_byte_packets" },
-	{ "rx_512_to_1023_byte_packets" },
-	{ "rx_1024_to_1522_byte_packets" },
-	{ "rx_1523_to_9022_byte_packets" },
-	{ "tx_64_byte_packets" },
-	{ "tx_65_to_127_byte_packets" },
-	{ "tx_128_to_255_byte_packets" },
-	{ "tx_256_to_511_byte_packets" },
-	{ "tx_512_to_1023_byte_packets" },
-	{ "tx_1024_to_1522_byte_packets" },
-	{ "tx_1523_to_9022_byte_packets" },
-	{ "rx_xon_frames" },
-	{ "rx_xoff_frames" },
-	{ "tx_xon_frames" },
-	{ "tx_xoff_frames" },
-	{ "rx_mac_ctrl_frames" },
-	{ "rx_filtered_packets" },
-	{ "rx_ftq_discards" },
-	{ "rx_discards" },
-	{ "rx_fw_discards" },
-};
-
-#define BNX2_NUM_STATS (sizeof(bnx2_stats_str_arr)/\
-			sizeof(bnx2_stats_str_arr[0]))
-
-#define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4)
-
-static const unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = {
-    STATS_OFFSET32(stat_IfHCInOctets_hi),
-    STATS_OFFSET32(stat_IfHCInBadOctets_hi),
-    STATS_OFFSET32(stat_IfHCOutOctets_hi),
-    STATS_OFFSET32(stat_IfHCOutBadOctets_hi),
-    STATS_OFFSET32(stat_IfHCInUcastPkts_hi),
-    STATS_OFFSET32(stat_IfHCInMulticastPkts_hi),
-    STATS_OFFSET32(stat_IfHCInBroadcastPkts_hi),
-    STATS_OFFSET32(stat_IfHCOutUcastPkts_hi),
-    STATS_OFFSET32(stat_IfHCOutMulticastPkts_hi),
-    STATS_OFFSET32(stat_IfHCOutBroadcastPkts_hi),
-    STATS_OFFSET32(stat_emac_tx_stat_dot3statsinternalmactransmiterrors),
-    STATS_OFFSET32(stat_Dot3StatsCarrierSenseErrors),
-    STATS_OFFSET32(stat_Dot3StatsFCSErrors),
-    STATS_OFFSET32(stat_Dot3StatsAlignmentErrors),
-    STATS_OFFSET32(stat_Dot3StatsSingleCollisionFrames),
-    STATS_OFFSET32(stat_Dot3StatsMultipleCollisionFrames),
-    STATS_OFFSET32(stat_Dot3StatsDeferredTransmissions),
-    STATS_OFFSET32(stat_Dot3StatsExcessiveCollisions),
-    STATS_OFFSET32(stat_Dot3StatsLateCollisions),
-    STATS_OFFSET32(stat_EtherStatsCollisions),
-    STATS_OFFSET32(stat_EtherStatsFragments),
-    STATS_OFFSET32(stat_EtherStatsJabbers),
-    STATS_OFFSET32(stat_EtherStatsUndersizePkts),
-    STATS_OFFSET32(stat_EtherStatsOverrsizePkts),
-    STATS_OFFSET32(stat_EtherStatsPktsRx64Octets),
-    STATS_OFFSET32(stat_EtherStatsPktsRx65Octetsto127Octets),
-    STATS_OFFSET32(stat_EtherStatsPktsRx128Octetsto255Octets),
-    STATS_OFFSET32(stat_EtherStatsPktsRx256Octetsto511Octets),
-    STATS_OFFSET32(stat_EtherStatsPktsRx512Octetsto1023Octets),
-    STATS_OFFSET32(stat_EtherStatsPktsRx1024Octetsto1522Octets),
-    STATS_OFFSET32(stat_EtherStatsPktsRx1523Octetsto9022Octets),
-    STATS_OFFSET32(stat_EtherStatsPktsTx64Octets),
-    STATS_OFFSET32(stat_EtherStatsPktsTx65Octetsto127Octets),
-    STATS_OFFSET32(stat_EtherStatsPktsTx128Octetsto255Octets),
-    STATS_OFFSET32(stat_EtherStatsPktsTx256Octetsto511Octets),
-    STATS_OFFSET32(stat_EtherStatsPktsTx512Octetsto1023Octets),
-    STATS_OFFSET32(stat_EtherStatsPktsTx1024Octetsto1522Octets),
-    STATS_OFFSET32(stat_EtherStatsPktsTx1523Octetsto9022Octets),
-    STATS_OFFSET32(stat_XonPauseFramesReceived),
-    STATS_OFFSET32(stat_XoffPauseFramesReceived),
-    STATS_OFFSET32(stat_OutXonSent),
-    STATS_OFFSET32(stat_OutXoffSent),
-    STATS_OFFSET32(stat_MacControlFramesReceived),
-    STATS_OFFSET32(stat_IfInFramesL2FilterDiscards),
-    STATS_OFFSET32(stat_IfInFTQDiscards),
-    STATS_OFFSET32(stat_IfInMBUFDiscards),
-    STATS_OFFSET32(stat_FwRxDrop),
-};
-
-/* stat_IfHCInBadOctets and stat_Dot3StatsCarrierSenseErrors are
- * skipped because of errata.
- */
-static u8 bnx2_5706_stats_len_arr[BNX2_NUM_STATS] = {
-	8,0,8,8,8,8,8,8,8,8,
-	4,0,4,4,4,4,4,4,4,4,
-	4,4,4,4,4,4,4,4,4,4,
-	4,4,4,4,4,4,4,4,4,4,
-	4,4,4,4,4,4,4,
-};
-
-static u8 bnx2_5708_stats_len_arr[BNX2_NUM_STATS] = {
-	8,0,8,8,8,8,8,8,8,8,
-	4,4,4,4,4,4,4,4,4,4,
-	4,4,4,4,4,4,4,4,4,4,
-	4,4,4,4,4,4,4,4,4,4,
-	4,4,4,4,4,4,4,
-};
-
-#define BNX2_NUM_TESTS 6
-
-static struct {
-	char string[ETH_GSTRING_LEN];
-} bnx2_tests_str_arr[BNX2_NUM_TESTS] = {
-	{ "register_test (offline)" },
-	{ "memory_test (offline)" },
-	{ "loopback_test (offline)" },
-	{ "nvram_test (online)" },
-	{ "interrupt_test (online)" },
-	{ "link_test (online)" },
-};
-
-static int
-bnx2_get_sset_count(struct net_device *dev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_TEST:
-		return BNX2_NUM_TESTS;
-	case ETH_SS_STATS:
-		return BNX2_NUM_STATS;
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void
-bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	bnx2_set_power_state(bp, PCI_D0);
-
-	memset(buf, 0, sizeof(u64) * BNX2_NUM_TESTS);
-	if (etest->flags & ETH_TEST_FL_OFFLINE) {
-		int i;
-
-		bnx2_netif_stop(bp, true);
-		bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_DIAG);
-		bnx2_free_skbs(bp);
-
-		if (bnx2_test_registers(bp) != 0) {
-			buf[0] = 1;
-			etest->flags |= ETH_TEST_FL_FAILED;
-		}
-		if (bnx2_test_memory(bp) != 0) {
-			buf[1] = 1;
-			etest->flags |= ETH_TEST_FL_FAILED;
-		}
-		if ((buf[2] = bnx2_test_loopback(bp)) != 0)
-			etest->flags |= ETH_TEST_FL_FAILED;
-
-		if (!netif_running(bp->dev))
-			bnx2_shutdown_chip(bp);
-		else {
-			bnx2_init_nic(bp, 1);
-			bnx2_netif_start(bp, true);
-		}
-
-		/* wait for link up */
-		for (i = 0; i < 7; i++) {
-			if (bp->link_up)
-				break;
-			msleep_interruptible(1000);
-		}
-	}
-
-	if (bnx2_test_nvram(bp) != 0) {
-		buf[3] = 1;
-		etest->flags |= ETH_TEST_FL_FAILED;
-	}
-	if (bnx2_test_intr(bp) != 0) {
-		buf[4] = 1;
-		etest->flags |= ETH_TEST_FL_FAILED;
-	}
-
-	if (bnx2_test_link(bp) != 0) {
-		buf[5] = 1;
-		etest->flags |= ETH_TEST_FL_FAILED;
-
-	}
-	if (!netif_running(bp->dev))
-		bnx2_set_power_state(bp, PCI_D3hot);
-}
-
-static void
-bnx2_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
-{
-	switch (stringset) {
-	case ETH_SS_STATS:
-		memcpy(buf, bnx2_stats_str_arr,
-			sizeof(bnx2_stats_str_arr));
-		break;
-	case ETH_SS_TEST:
-		memcpy(buf, bnx2_tests_str_arr,
-			sizeof(bnx2_tests_str_arr));
-		break;
-	}
-}
-
-static void
-bnx2_get_ethtool_stats(struct net_device *dev,
-		struct ethtool_stats *stats, u64 *buf)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-	int i;
-	u32 *hw_stats = (u32 *) bp->stats_blk;
-	u32 *temp_stats = (u32 *) bp->temp_stats_blk;
-	u8 *stats_len_arr = NULL;
-
-	if (hw_stats == NULL) {
-		memset(buf, 0, sizeof(u64) * BNX2_NUM_STATS);
-		return;
-	}
-
-	if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
-	    (CHIP_ID(bp) == CHIP_ID_5706_A1) ||
-	    (CHIP_ID(bp) == CHIP_ID_5706_A2) ||
-	    (CHIP_ID(bp) == CHIP_ID_5708_A0))
-		stats_len_arr = bnx2_5706_stats_len_arr;
-	else
-		stats_len_arr = bnx2_5708_stats_len_arr;
-
-	for (i = 0; i < BNX2_NUM_STATS; i++) {
-		unsigned long offset;
-
-		if (stats_len_arr[i] == 0) {
-			/* skip this counter */
-			buf[i] = 0;
-			continue;
-		}
-
-		offset = bnx2_stats_offset_arr[i];
-		if (stats_len_arr[i] == 4) {
-			/* 4-byte counter */
-			buf[i] = (u64) *(hw_stats + offset) +
-				 *(temp_stats + offset);
-			continue;
-		}
-		/* 8-byte counter */
-		buf[i] = (((u64) *(hw_stats + offset)) << 32) +
-			 *(hw_stats + offset + 1) +
-			 (((u64) *(temp_stats + offset)) << 32) +
-			 *(temp_stats + offset + 1);
-	}
-}
-
-static int
-bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	switch (state) {
-	case ETHTOOL_ID_ACTIVE:
-		bnx2_set_power_state(bp, PCI_D0);
-
-		bp->leds_save = REG_RD(bp, BNX2_MISC_CFG);
-		REG_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC);
-		return 1;	/* cycle on/off once per second */
-
-	case ETHTOOL_ID_ON:
-		REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE |
-		       BNX2_EMAC_LED_1000MB_OVERRIDE |
-		       BNX2_EMAC_LED_100MB_OVERRIDE |
-		       BNX2_EMAC_LED_10MB_OVERRIDE |
-		       BNX2_EMAC_LED_TRAFFIC_OVERRIDE |
-		       BNX2_EMAC_LED_TRAFFIC);
-		break;
-
-	case ETHTOOL_ID_OFF:
-		REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE);
-		break;
-
-	case ETHTOOL_ID_INACTIVE:
-		REG_WR(bp, BNX2_EMAC_LED, 0);
-		REG_WR(bp, BNX2_MISC_CFG, bp->leds_save);
-
-		if (!netif_running(dev))
-			bnx2_set_power_state(bp, PCI_D3hot);
-		break;
-	}
-
-	return 0;
-}
-
-static u32
-bnx2_fix_features(struct net_device *dev, u32 features)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	if (!(bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
-		features |= NETIF_F_HW_VLAN_RX;
-
-	return features;
-}
-
-static int
-bnx2_set_features(struct net_device *dev, u32 features)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	/* TSO with VLAN tag won't work with current firmware */
-	if (features & NETIF_F_HW_VLAN_TX)
-		dev->vlan_features |= (dev->hw_features & NETIF_F_ALL_TSO);
-	else
-		dev->vlan_features &= ~NETIF_F_ALL_TSO;
-
-	if ((!!(features & NETIF_F_HW_VLAN_RX) !=
-	    !!(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) &&
-	    netif_running(dev)) {
-		bnx2_netif_stop(bp, false);
-		dev->features = features;
-		bnx2_set_rx_mode(dev);
-		bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1);
-		bnx2_netif_start(bp, false);
-		return 1;
-	}
-
-	return 0;
-}
-
-static const struct ethtool_ops bnx2_ethtool_ops = {
-	.get_settings		= bnx2_get_settings,
-	.set_settings		= bnx2_set_settings,
-	.get_drvinfo		= bnx2_get_drvinfo,
-	.get_regs_len		= bnx2_get_regs_len,
-	.get_regs		= bnx2_get_regs,
-	.get_wol		= bnx2_get_wol,
-	.set_wol		= bnx2_set_wol,
-	.nway_reset		= bnx2_nway_reset,
-	.get_link		= bnx2_get_link,
-	.get_eeprom_len		= bnx2_get_eeprom_len,
-	.get_eeprom		= bnx2_get_eeprom,
-	.set_eeprom		= bnx2_set_eeprom,
-	.get_coalesce		= bnx2_get_coalesce,
-	.set_coalesce		= bnx2_set_coalesce,
-	.get_ringparam		= bnx2_get_ringparam,
-	.set_ringparam		= bnx2_set_ringparam,
-	.get_pauseparam		= bnx2_get_pauseparam,
-	.set_pauseparam		= bnx2_set_pauseparam,
-	.self_test		= bnx2_self_test,
-	.get_strings		= bnx2_get_strings,
-	.set_phys_id		= bnx2_set_phys_id,
-	.get_ethtool_stats	= bnx2_get_ethtool_stats,
-	.get_sset_count		= bnx2_get_sset_count,
-};
-
-/* Called with rtnl_lock */
-static int
-bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	struct mii_ioctl_data *data = if_mii(ifr);
-	struct bnx2 *bp = netdev_priv(dev);
-	int err;
-
-	switch(cmd) {
-	case SIOCGMIIPHY:
-		data->phy_id = bp->phy_addr;
-
-		/* fallthru */
-	case SIOCGMIIREG: {
-		u32 mii_regval;
-
-		if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
-			return -EOPNOTSUPP;
-
-		if (!netif_running(dev))
-			return -EAGAIN;
-
-		spin_lock_bh(&bp->phy_lock);
-		err = bnx2_read_phy(bp, data->reg_num & 0x1f, &mii_regval);
-		spin_unlock_bh(&bp->phy_lock);
-
-		data->val_out = mii_regval;
-
-		return err;
-	}
-
-	case SIOCSMIIREG:
-		if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
-			return -EOPNOTSUPP;
-
-		if (!netif_running(dev))
-			return -EAGAIN;
-
-		spin_lock_bh(&bp->phy_lock);
-		err = bnx2_write_phy(bp, data->reg_num & 0x1f, data->val_in);
-		spin_unlock_bh(&bp->phy_lock);
-
-		return err;
-
-	default:
-		/* do nothing */
-		break;
-	}
-	return -EOPNOTSUPP;
-}
-
-/* Called with rtnl_lock */
-static int
-bnx2_change_mac_addr(struct net_device *dev, void *p)
-{
-	struct sockaddr *addr = p;
-	struct bnx2 *bp = netdev_priv(dev);
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EINVAL;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-	if (netif_running(dev))
-		bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0);
-
-	return 0;
-}
-
-/* Called with rtnl_lock */
-static int
-bnx2_change_mtu(struct net_device *dev, int new_mtu)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) ||
-		((new_mtu + ETH_HLEN) < MIN_ETHERNET_PACKET_SIZE))
-		return -EINVAL;
-
-	dev->mtu = new_mtu;
-	return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size);
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void
-poll_bnx2(struct net_device *dev)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-	int i;
-
-	for (i = 0; i < bp->irq_nvecs; i++) {
-		struct bnx2_irq *irq = &bp->irq_tbl[i];
-
-		disable_irq(irq->vector);
-		irq->handler(irq->vector, &bp->bnx2_napi[i]);
-		enable_irq(irq->vector);
-	}
-}
-#endif
-
-static void __devinit
-bnx2_get_5709_media(struct bnx2 *bp)
-{
-	u32 val = REG_RD(bp, BNX2_MISC_DUAL_MEDIA_CTRL);
-	u32 bond_id = val & BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID;
-	u32 strap;
-
-	if (bond_id == BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_C)
-		return;
-	else if (bond_id == BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_S) {
-		bp->phy_flags |= BNX2_PHY_FLAG_SERDES;
-		return;
-	}
-
-	if (val & BNX2_MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE)
-		strap = (val & BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL) >> 21;
-	else
-		strap = (val & BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP) >> 8;
-
-	if (PCI_FUNC(bp->pdev->devfn) == 0) {
-		switch (strap) {
-		case 0x4:
-		case 0x5:
-		case 0x6:
-			bp->phy_flags |= BNX2_PHY_FLAG_SERDES;
-			return;
-		}
-	} else {
-		switch (strap) {
-		case 0x1:
-		case 0x2:
-		case 0x4:
-			bp->phy_flags |= BNX2_PHY_FLAG_SERDES;
-			return;
-		}
-	}
-}
-
-static void __devinit
-bnx2_get_pci_speed(struct bnx2 *bp)
-{
-	u32 reg;
-
-	reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS);
-	if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) {
-		u32 clkreg;
-
-		bp->flags |= BNX2_FLAG_PCIX;
-
-		clkreg = REG_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS);
-
-		clkreg &= BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET;
-		switch (clkreg) {
-		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ:
-			bp->bus_speed_mhz = 133;
-			break;
-
-		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ:
-			bp->bus_speed_mhz = 100;
-			break;
-
-		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ:
-		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ:
-			bp->bus_speed_mhz = 66;
-			break;
-
-		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ:
-		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ:
-			bp->bus_speed_mhz = 50;
-			break;
-
-		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW:
-		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ:
-		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ:
-			bp->bus_speed_mhz = 33;
-			break;
-		}
-	}
-	else {
-		if (reg & BNX2_PCICFG_MISC_STATUS_M66EN)
-			bp->bus_speed_mhz = 66;
-		else
-			bp->bus_speed_mhz = 33;
-	}
-
-	if (reg & BNX2_PCICFG_MISC_STATUS_32BIT_DET)
-		bp->flags |= BNX2_FLAG_PCI_32BIT;
-
-}
-
-static void __devinit
-bnx2_read_vpd_fw_ver(struct bnx2 *bp)
-{
-	int rc, i, j;
-	u8 *data;
-	unsigned int block_end, rosize, len;
-
-#define BNX2_VPD_NVRAM_OFFSET	0x300
-#define BNX2_VPD_LEN		128
-#define BNX2_MAX_VER_SLEN	30
-
-	data = kmalloc(256, GFP_KERNEL);
-	if (!data)
-		return;
-
-	rc = bnx2_nvram_read(bp, BNX2_VPD_NVRAM_OFFSET, data + BNX2_VPD_LEN,
-			     BNX2_VPD_LEN);
-	if (rc)
-		goto vpd_done;
-
-	for (i = 0; i < BNX2_VPD_LEN; i += 4) {
-		data[i] = data[i + BNX2_VPD_LEN + 3];
-		data[i + 1] = data[i + BNX2_VPD_LEN + 2];
-		data[i + 2] = data[i + BNX2_VPD_LEN + 1];
-		data[i + 3] = data[i + BNX2_VPD_LEN];
-	}
-
-	i = pci_vpd_find_tag(data, 0, BNX2_VPD_LEN, PCI_VPD_LRDT_RO_DATA);
-	if (i < 0)
-		goto vpd_done;
-
-	rosize = pci_vpd_lrdt_size(&data[i]);
-	i += PCI_VPD_LRDT_TAG_SIZE;
-	block_end = i + rosize;
-
-	if (block_end > BNX2_VPD_LEN)
-		goto vpd_done;
-
-	j = pci_vpd_find_info_keyword(data, i, rosize,
-				      PCI_VPD_RO_KEYWORD_MFR_ID);
-	if (j < 0)
-		goto vpd_done;
-
-	len = pci_vpd_info_field_size(&data[j]);
-
-	j += PCI_VPD_INFO_FLD_HDR_SIZE;
-	if (j + len > block_end || len != 4 ||
-	    memcmp(&data[j], "1028", 4))
-		goto vpd_done;
-
-	j = pci_vpd_find_info_keyword(data, i, rosize,
-				      PCI_VPD_RO_KEYWORD_VENDOR0);
-	if (j < 0)
-		goto vpd_done;
-
-	len = pci_vpd_info_field_size(&data[j]);
-
-	j += PCI_VPD_INFO_FLD_HDR_SIZE;
-	if (j + len > block_end || len > BNX2_MAX_VER_SLEN)
-		goto vpd_done;
-
-	memcpy(bp->fw_version, &data[j], len);
-	bp->fw_version[len] = ' ';
-
-vpd_done:
-	kfree(data);
-}
-
-static int __devinit
-bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
-{
-	struct bnx2 *bp;
-	unsigned long mem_len;
-	int rc, i, j;
-	u32 reg;
-	u64 dma_mask, persist_dma_mask;
-	int err;
-
-	SET_NETDEV_DEV(dev, &pdev->dev);
-	bp = netdev_priv(dev);
-
-	bp->flags = 0;
-	bp->phy_flags = 0;
-
-	bp->temp_stats_blk =
-		kzalloc(sizeof(struct statistics_block), GFP_KERNEL);
-
-	if (bp->temp_stats_blk == NULL) {
-		rc = -ENOMEM;
-		goto err_out;
-	}
-
-	/* enable device (incl. PCI PM wakeup), and bus-mastering */
-	rc = pci_enable_device(pdev);
-	if (rc) {
-		dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n");
-		goto err_out;
-	}
-
-	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
-		dev_err(&pdev->dev,
-			"Cannot find PCI device base address, aborting\n");
-		rc = -ENODEV;
-		goto err_out_disable;
-	}
-
-	rc = pci_request_regions(pdev, DRV_MODULE_NAME);
-	if (rc) {
-		dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting\n");
-		goto err_out_disable;
-	}
-
-	pci_set_master(pdev);
-
-	bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
-	if (bp->pm_cap == 0) {
-		dev_err(&pdev->dev,
-			"Cannot find power management capability, aborting\n");
-		rc = -EIO;
-		goto err_out_release;
-	}
-
-	bp->dev = dev;
-	bp->pdev = pdev;
-
-	spin_lock_init(&bp->phy_lock);
-	spin_lock_init(&bp->indirect_lock);
-#ifdef BCM_CNIC
-	mutex_init(&bp->cnic_lock);
-#endif
-	INIT_WORK(&bp->reset_task, bnx2_reset_task);
-
-	dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
-	mem_len = MB_GET_CID_ADDR(TX_TSS_CID + TX_MAX_TSS_RINGS + 1);
-	dev->mem_end = dev->mem_start + mem_len;
-	dev->irq = pdev->irq;
-
-	bp->regview = ioremap_nocache(dev->base_addr, mem_len);
-
-	if (!bp->regview) {
-		dev_err(&pdev->dev, "Cannot map register space, aborting\n");
-		rc = -ENOMEM;
-		goto err_out_release;
-	}
-
-	bnx2_set_power_state(bp, PCI_D0);
-
-	/* Configure byte swap and enable write to the reg_window registers.
-	 * Rely on CPU to do target byte swapping on big endian systems
-	 * The chip's target access swapping will not swap all accesses
-	 */
-	REG_WR(bp, BNX2_PCICFG_MISC_CONFIG,
-		   BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
-		   BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
-
-	bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		if (!pci_is_pcie(pdev)) {
-			dev_err(&pdev->dev, "Not PCIE, aborting\n");
-			rc = -EIO;
-			goto err_out_unmap;
-		}
-		bp->flags |= BNX2_FLAG_PCIE;
-		if (CHIP_REV(bp) == CHIP_REV_Ax)
-			bp->flags |= BNX2_FLAG_JUMBO_BROKEN;
-
-		/* AER (Advanced Error Reporting) hooks */
-		err = pci_enable_pcie_error_reporting(pdev);
-		if (!err)
-			bp->flags |= BNX2_FLAG_AER_ENABLED;
-
-	} else {
-		bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
-		if (bp->pcix_cap == 0) {
-			dev_err(&pdev->dev,
-				"Cannot find PCIX capability, aborting\n");
-			rc = -EIO;
-			goto err_out_unmap;
-		}
-		bp->flags |= BNX2_FLAG_BROKEN_STATS;
-	}
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709 && CHIP_REV(bp) != CHIP_REV_Ax) {
-		if (pci_find_capability(pdev, PCI_CAP_ID_MSIX))
-			bp->flags |= BNX2_FLAG_MSIX_CAP;
-	}
-
-	if (CHIP_ID(bp) != CHIP_ID_5706_A0 && CHIP_ID(bp) != CHIP_ID_5706_A1) {
-		if (pci_find_capability(pdev, PCI_CAP_ID_MSI))
-			bp->flags |= BNX2_FLAG_MSI_CAP;
-	}
-
-	/* 5708 cannot support DMA addresses > 40-bit.  */
-	if (CHIP_NUM(bp) == CHIP_NUM_5708)
-		persist_dma_mask = dma_mask = DMA_BIT_MASK(40);
-	else
-		persist_dma_mask = dma_mask = DMA_BIT_MASK(64);
-
-	/* Configure DMA attributes. */
-	if (pci_set_dma_mask(pdev, dma_mask) == 0) {
-		dev->features |= NETIF_F_HIGHDMA;
-		rc = pci_set_consistent_dma_mask(pdev, persist_dma_mask);
-		if (rc) {
-			dev_err(&pdev->dev,
-				"pci_set_consistent_dma_mask failed, aborting\n");
-			goto err_out_unmap;
-		}
-	} else if ((rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) {
-		dev_err(&pdev->dev, "System does not support DMA, aborting\n");
-		goto err_out_unmap;
-	}
-
-	if (!(bp->flags & BNX2_FLAG_PCIE))
-		bnx2_get_pci_speed(bp);
-
-	/* 5706A0 may falsely detect SERR and PERR. */
-	if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
-		reg = REG_RD(bp, PCI_COMMAND);
-		reg &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
-		REG_WR(bp, PCI_COMMAND, reg);
-	}
-	else if ((CHIP_ID(bp) == CHIP_ID_5706_A1) &&
-		!(bp->flags & BNX2_FLAG_PCIX)) {
-
-		dev_err(&pdev->dev,
-			"5706 A1 can only be used in a PCIX bus, aborting\n");
-		goto err_out_unmap;
-	}
-
-	bnx2_init_nvram(bp);
-
-	reg = bnx2_reg_rd_ind(bp, BNX2_SHM_HDR_SIGNATURE);
-
-	if ((reg & BNX2_SHM_HDR_SIGNATURE_SIG_MASK) ==
-	    BNX2_SHM_HDR_SIGNATURE_SIG) {
-		u32 off = PCI_FUNC(pdev->devfn) << 2;
-
-		bp->shmem_base = bnx2_reg_rd_ind(bp, BNX2_SHM_HDR_ADDR_0 + off);
-	} else
-		bp->shmem_base = HOST_VIEW_SHMEM_BASE;
-
-	/* Get the permanent MAC address.  First we need to make sure the
-	 * firmware is actually running.
-	 */
-	reg = bnx2_shmem_rd(bp, BNX2_DEV_INFO_SIGNATURE);
-
-	if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) !=
-	    BNX2_DEV_INFO_SIGNATURE_MAGIC) {
-		dev_err(&pdev->dev, "Firmware not running, aborting\n");
-		rc = -ENODEV;
-		goto err_out_unmap;
-	}
-
-	bnx2_read_vpd_fw_ver(bp);
-
-	j = strlen(bp->fw_version);
-	reg = bnx2_shmem_rd(bp, BNX2_DEV_INFO_BC_REV);
-	for (i = 0; i < 3 && j < 24; i++) {
-		u8 num, k, skip0;
-
-		if (i == 0) {
-			bp->fw_version[j++] = 'b';
-			bp->fw_version[j++] = 'c';
-			bp->fw_version[j++] = ' ';
-		}
-		num = (u8) (reg >> (24 - (i * 8)));
-		for (k = 100, skip0 = 1; k >= 1; num %= k, k /= 10) {
-			if (num >= k || !skip0 || k == 1) {
-				bp->fw_version[j++] = (num / k) + '0';
-				skip0 = 0;
-			}
-		}
-		if (i != 2)
-			bp->fw_version[j++] = '.';
-	}
-	reg = bnx2_shmem_rd(bp, BNX2_PORT_FEATURE);
-	if (reg & BNX2_PORT_FEATURE_WOL_ENABLED)
-		bp->wol = 1;
-
-	if (reg & BNX2_PORT_FEATURE_ASF_ENABLED) {
-		bp->flags |= BNX2_FLAG_ASF_ENABLE;
-
-		for (i = 0; i < 30; i++) {
-			reg = bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION);
-			if (reg & BNX2_CONDITION_MFW_RUN_MASK)
-				break;
-			msleep(10);
-		}
-	}
-	reg = bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION);
-	reg &= BNX2_CONDITION_MFW_RUN_MASK;
-	if (reg != BNX2_CONDITION_MFW_RUN_UNKNOWN &&
-	    reg != BNX2_CONDITION_MFW_RUN_NONE) {
-		u32 addr = bnx2_shmem_rd(bp, BNX2_MFW_VER_PTR);
-
-		if (j < 32)
-			bp->fw_version[j++] = ' ';
-		for (i = 0; i < 3 && j < 28; i++) {
-			reg = bnx2_reg_rd_ind(bp, addr + i * 4);
-			reg = be32_to_cpu(reg);
-			memcpy(&bp->fw_version[j], &reg, 4);
-			j += 4;
-		}
-	}
-
-	reg = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_MAC_UPPER);
-	bp->mac_addr[0] = (u8) (reg >> 8);
-	bp->mac_addr[1] = (u8) reg;
-
-	reg = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_MAC_LOWER);
-	bp->mac_addr[2] = (u8) (reg >> 24);
-	bp->mac_addr[3] = (u8) (reg >> 16);
-	bp->mac_addr[4] = (u8) (reg >> 8);
-	bp->mac_addr[5] = (u8) reg;
-
-	bp->tx_ring_size = MAX_TX_DESC_CNT;
-	bnx2_set_rx_ring_size(bp, 255);
-
-	bp->tx_quick_cons_trip_int = 2;
-	bp->tx_quick_cons_trip = 20;
-	bp->tx_ticks_int = 18;
-	bp->tx_ticks = 80;
-
-	bp->rx_quick_cons_trip_int = 2;
-	bp->rx_quick_cons_trip = 12;
-	bp->rx_ticks_int = 18;
-	bp->rx_ticks = 18;
-
-	bp->stats_ticks = USEC_PER_SEC & BNX2_HC_STATS_TICKS_HC_STAT_TICKS;
-
-	bp->current_interval = BNX2_TIMER_INTERVAL;
-
-	bp->phy_addr = 1;
-
-	/* Disable WOL support if we are running on a SERDES chip. */
-	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		bnx2_get_5709_media(bp);
-	else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT)
-		bp->phy_flags |= BNX2_PHY_FLAG_SERDES;
-
-	bp->phy_port = PORT_TP;
-	if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
-		bp->phy_port = PORT_FIBRE;
-		reg = bnx2_shmem_rd(bp, BNX2_SHARED_HW_CFG_CONFIG);
-		if (!(reg & BNX2_SHARED_HW_CFG_GIG_LINK_ON_VAUX)) {
-			bp->flags |= BNX2_FLAG_NO_WOL;
-			bp->wol = 0;
-		}
-		if (CHIP_NUM(bp) == CHIP_NUM_5706) {
-			/* Don't do parallel detect on this board because of
-			 * some board problems.  The link will not go down
-			 * if we do parallel detect.
-			 */
-			if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP &&
-			    pdev->subsystem_device == 0x310c)
-				bp->phy_flags |= BNX2_PHY_FLAG_NO_PARALLEL;
-		} else {
-			bp->phy_addr = 2;
-			if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G)
-				bp->phy_flags |= BNX2_PHY_FLAG_2_5G_CAPABLE;
-		}
-	} else if (CHIP_NUM(bp) == CHIP_NUM_5706 ||
-		   CHIP_NUM(bp) == CHIP_NUM_5708)
-		bp->phy_flags |= BNX2_PHY_FLAG_CRC_FIX;
-	else if (CHIP_NUM(bp) == CHIP_NUM_5709 &&
-		 (CHIP_REV(bp) == CHIP_REV_Ax ||
-		  CHIP_REV(bp) == CHIP_REV_Bx))
-		bp->phy_flags |= BNX2_PHY_FLAG_DIS_EARLY_DAC;
-
-	bnx2_init_fw_cap(bp);
-
-	if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
-	    (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
-	    (CHIP_ID(bp) == CHIP_ID_5708_B1) ||
-	    !(REG_RD(bp, BNX2_PCI_CONFIG_3) & BNX2_PCI_CONFIG_3_VAUX_PRESET)) {
-		bp->flags |= BNX2_FLAG_NO_WOL;
-		bp->wol = 0;
-	}
-
-	if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
-		bp->tx_quick_cons_trip_int =
-			bp->tx_quick_cons_trip;
-		bp->tx_ticks_int = bp->tx_ticks;
-		bp->rx_quick_cons_trip_int =
-			bp->rx_quick_cons_trip;
-		bp->rx_ticks_int = bp->rx_ticks;
-		bp->comp_prod_trip_int = bp->comp_prod_trip;
-		bp->com_ticks_int = bp->com_ticks;
-		bp->cmd_ticks_int = bp->cmd_ticks;
-	}
-
-	/* Disable MSI on 5706 if AMD 8132 bridge is found.
-	 *
-	 * MSI is defined to be 32-bit write.  The 5706 does 64-bit MSI writes
-	 * with byte enables disabled on the unused 32-bit word.  This is legal
-	 * but causes problems on the AMD 8132 which will eventually stop
-	 * responding after a while.
-	 *
-	 * AMD believes this incompatibility is unique to the 5706, and
-	 * prefers to locally disable MSI rather than globally disabling it.
-	 */
-	if (CHIP_NUM(bp) == CHIP_NUM_5706 && disable_msi == 0) {
-		struct pci_dev *amd_8132 = NULL;
-
-		while ((amd_8132 = pci_get_device(PCI_VENDOR_ID_AMD,
-						  PCI_DEVICE_ID_AMD_8132_BRIDGE,
-						  amd_8132))) {
-
-			if (amd_8132->revision >= 0x10 &&
-			    amd_8132->revision <= 0x13) {
-				disable_msi = 1;
-				pci_dev_put(amd_8132);
-				break;
-			}
-		}
-	}
-
-	bnx2_set_default_link(bp);
-	bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX;
-
-	init_timer(&bp->timer);
-	bp->timer.expires = RUN_AT(BNX2_TIMER_INTERVAL);
-	bp->timer.data = (unsigned long) bp;
-	bp->timer.function = bnx2_timer;
-
-#ifdef BCM_CNIC
-	if (bnx2_shmem_rd(bp, BNX2_ISCSI_INITIATOR) & BNX2_ISCSI_INITIATOR_EN)
-		bp->cnic_eth_dev.max_iscsi_conn =
-			(bnx2_shmem_rd(bp, BNX2_ISCSI_MAX_CONN) &
-			 BNX2_ISCSI_MAX_CONN_MASK) >> BNX2_ISCSI_MAX_CONN_SHIFT;
-#endif
-	pci_save_state(pdev);
-
-	return 0;
-
-err_out_unmap:
-	if (bp->flags & BNX2_FLAG_AER_ENABLED) {
-		pci_disable_pcie_error_reporting(pdev);
-		bp->flags &= ~BNX2_FLAG_AER_ENABLED;
-	}
-
-	if (bp->regview) {
-		iounmap(bp->regview);
-		bp->regview = NULL;
-	}
-
-err_out_release:
-	pci_release_regions(pdev);
-
-err_out_disable:
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-
-err_out:
-	return rc;
-}
-
-static char * __devinit
-bnx2_bus_string(struct bnx2 *bp, char *str)
-{
-	char *s = str;
-
-	if (bp->flags & BNX2_FLAG_PCIE) {
-		s += sprintf(s, "PCI Express");
-	} else {
-		s += sprintf(s, "PCI");
-		if (bp->flags & BNX2_FLAG_PCIX)
-			s += sprintf(s, "-X");
-		if (bp->flags & BNX2_FLAG_PCI_32BIT)
-			s += sprintf(s, " 32-bit");
-		else
-			s += sprintf(s, " 64-bit");
-		s += sprintf(s, " %dMHz", bp->bus_speed_mhz);
-	}
-	return str;
-}
-
-static void
-bnx2_del_napi(struct bnx2 *bp)
-{
-	int i;
-
-	for (i = 0; i < bp->irq_nvecs; i++)
-		netif_napi_del(&bp->bnx2_napi[i].napi);
-}
-
-static void
-bnx2_init_napi(struct bnx2 *bp)
-{
-	int i;
-
-	for (i = 0; i < bp->irq_nvecs; i++) {
-		struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
-		int (*poll)(struct napi_struct *, int);
-
-		if (i == 0)
-			poll = bnx2_poll;
-		else
-			poll = bnx2_poll_msix;
-
-		netif_napi_add(bp->dev, &bp->bnx2_napi[i].napi, poll, 64);
-		bnapi->bp = bp;
-	}
-}
-
-static const struct net_device_ops bnx2_netdev_ops = {
-	.ndo_open		= bnx2_open,
-	.ndo_start_xmit		= bnx2_start_xmit,
-	.ndo_stop		= bnx2_close,
-	.ndo_get_stats64	= bnx2_get_stats64,
-	.ndo_set_rx_mode	= bnx2_set_rx_mode,
-	.ndo_do_ioctl		= bnx2_ioctl,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address	= bnx2_change_mac_addr,
-	.ndo_change_mtu		= bnx2_change_mtu,
-	.ndo_fix_features	= bnx2_fix_features,
-	.ndo_set_features	= bnx2_set_features,
-	.ndo_tx_timeout		= bnx2_tx_timeout,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= poll_bnx2,
-#endif
-};
-
-static int __devinit
-bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	static int version_printed = 0;
-	struct net_device *dev = NULL;
-	struct bnx2 *bp;
-	int rc;
-	char str[40];
-
-	if (version_printed++ == 0)
-		pr_info("%s", version);
-
-	/* dev zeroed in init_etherdev */
-	dev = alloc_etherdev_mq(sizeof(*bp), TX_MAX_RINGS);
-
-	if (!dev)
-		return -ENOMEM;
-
-	rc = bnx2_init_board(pdev, dev);
-	if (rc < 0) {
-		free_netdev(dev);
-		return rc;
-	}
-
-	dev->netdev_ops = &bnx2_netdev_ops;
-	dev->watchdog_timeo = TX_TIMEOUT;
-	dev->ethtool_ops = &bnx2_ethtool_ops;
-
-	bp = netdev_priv(dev);
-
-	pci_set_drvdata(pdev, dev);
-
-	rc = bnx2_reject_firmware(bp);
-	if (rc)
-		goto error;
-
-	memcpy(dev->dev_addr, bp->mac_addr, 6);
-	memcpy(dev->perm_addr, bp->mac_addr, 6);
-
-	dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
-		NETIF_F_TSO | NETIF_F_TSO_ECN |
-		NETIF_F_RXHASH | NETIF_F_RXCSUM;
-
-	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
-
-	dev->vlan_features = dev->hw_features;
-	dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-	dev->features |= dev->hw_features;
-
-	if ((rc = register_netdev(dev))) {
-		dev_err(&pdev->dev, "Cannot register net device\n");
-		goto error;
-	}
-
-	netdev_info(dev, "%s (%c%d) %s found at mem %lx, IRQ %d, node addr %pM\n",
-		    board_info[ent->driver_data].name,
-		    ((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
-		    ((CHIP_ID(bp) & 0x0ff0) >> 4),
-		    bnx2_bus_string(bp, str),
-		    dev->base_addr,
-		    bp->pdev->irq, dev->dev_addr);
-
-	return 0;
-
-error:
-	if (bp->mips_firmware)
-		release_firmware(bp->mips_firmware);
-	if (bp->rv2p_firmware)
-		release_firmware(bp->rv2p_firmware);
-
-	if (bp->regview)
-		iounmap(bp->regview);
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-	free_netdev(dev);
-	return rc;
-}
-
-static void __devexit
-bnx2_remove_one(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct bnx2 *bp = netdev_priv(dev);
-
-	unregister_netdev(dev);
-
-	del_timer_sync(&bp->timer);
-	cancel_work_sync(&bp->reset_task);
-
-	if (bp->mips_firmware)
-		release_firmware(bp->mips_firmware);
-	if (bp->rv2p_firmware)
-		release_firmware(bp->rv2p_firmware);
-
-	if (bp->regview)
-		iounmap(bp->regview);
-
-	kfree(bp->temp_stats_blk);
-
-	if (bp->flags & BNX2_FLAG_AER_ENABLED) {
-		pci_disable_pcie_error_reporting(pdev);
-		bp->flags &= ~BNX2_FLAG_AER_ENABLED;
-	}
-
-	free_netdev(dev);
-
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-}
-
-static int
-bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct bnx2 *bp = netdev_priv(dev);
-
-	/* PCI register 4 needs to be saved whether netif_running() or not.
-	 * MSI address and data need to be saved if using MSI and
-	 * netif_running().
-	 */
-	pci_save_state(pdev);
-	if (!netif_running(dev))
-		return 0;
-
-	cancel_work_sync(&bp->reset_task);
-	bnx2_netif_stop(bp, true);
-	netif_device_detach(dev);
-	del_timer_sync(&bp->timer);
-	bnx2_shutdown_chip(bp);
-	bnx2_free_skbs(bp);
-	bnx2_set_power_state(bp, pci_choose_state(pdev, state));
-	return 0;
-}
-
-static int
-bnx2_resume(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct bnx2 *bp = netdev_priv(dev);
-
-	pci_restore_state(pdev);
-	if (!netif_running(dev))
-		return 0;
-
-	bnx2_set_power_state(bp, PCI_D0);
-	netif_device_attach(dev);
-	bnx2_init_nic(bp, 1);
-	bnx2_netif_start(bp, true);
-	return 0;
-}
-
-/**
- * bnx2_io_error_detected - called when PCI error is detected
- * @pdev: Pointer to PCI device
- * @state: The current pci connection state
- *
- * This function is called after a PCI bus error affecting
- * this device has been detected.
- */
-static pci_ers_result_t bnx2_io_error_detected(struct pci_dev *pdev,
-					       pci_channel_state_t state)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct bnx2 *bp = netdev_priv(dev);
-
-	rtnl_lock();
-	netif_device_detach(dev);
-
-	if (state == pci_channel_io_perm_failure) {
-		rtnl_unlock();
-		return PCI_ERS_RESULT_DISCONNECT;
-	}
-
-	if (netif_running(dev)) {
-		bnx2_netif_stop(bp, true);
-		del_timer_sync(&bp->timer);
-		bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET);
-	}
-
-	pci_disable_device(pdev);
-	rtnl_unlock();
-
-	/* Request a slot slot reset. */
-	return PCI_ERS_RESULT_NEED_RESET;
-}
-
-/**
- * bnx2_io_slot_reset - called after the pci bus has been reset.
- * @pdev: Pointer to PCI device
- *
- * Restart the card from scratch, as if from a cold-boot.
- */
-static pci_ers_result_t bnx2_io_slot_reset(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct bnx2 *bp = netdev_priv(dev);
-	pci_ers_result_t result;
-	int err;
-
-	rtnl_lock();
-	if (pci_enable_device(pdev)) {
-		dev_err(&pdev->dev,
-			"Cannot re-enable PCI device after reset\n");
-		result = PCI_ERS_RESULT_DISCONNECT;
-	} else {
-		pci_set_master(pdev);
-		pci_restore_state(pdev);
-		pci_save_state(pdev);
-
-		if (netif_running(dev)) {
-			bnx2_set_power_state(bp, PCI_D0);
-			bnx2_init_nic(bp, 1);
-		}
-		result = PCI_ERS_RESULT_RECOVERED;
-	}
-	rtnl_unlock();
-
-	if (!(bp->flags & BNX2_FLAG_AER_ENABLED))
-		return result;
-
-	err = pci_cleanup_aer_uncorrect_error_status(pdev);
-	if (err) {
-		dev_err(&pdev->dev,
-			"pci_cleanup_aer_uncorrect_error_status failed 0x%0x\n",
-			 err); /* non-fatal, continue */
-	}
-
-	return result;
-}
-
-/**
- * bnx2_io_resume - called when traffic can start flowing again.
- * @pdev: Pointer to PCI device
- *
- * This callback is called when the error recovery driver tells us that
- * its OK to resume normal operation.
- */
-static void bnx2_io_resume(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct bnx2 *bp = netdev_priv(dev);
-
-	rtnl_lock();
-	if (netif_running(dev))
-		bnx2_netif_start(bp, true);
-
-	netif_device_attach(dev);
-	rtnl_unlock();
-}
-
-static struct pci_error_handlers bnx2_err_handler = {
-	.error_detected	= bnx2_io_error_detected,
-	.slot_reset	= bnx2_io_slot_reset,
-	.resume		= bnx2_io_resume,
-};
-
-static struct pci_driver bnx2_pci_driver = {
-	.name		= DRV_MODULE_NAME,
-	.id_table	= bnx2_pci_tbl,
-	.probe		= bnx2_init_one,
-	.remove		= __devexit_p(bnx2_remove_one),
-	.suspend	= bnx2_suspend,
-	.resume		= bnx2_resume,
-	.err_handler	= &bnx2_err_handler,
-};
-
-static int __init bnx2_init(void)
-{
-	return pci_register_driver(&bnx2_pci_driver);
-}
-
-static void __exit bnx2_cleanup(void)
-{
-	pci_unregister_driver(&bnx2_pci_driver);
-}
-
-module_init(bnx2_init);
-module_exit(bnx2_cleanup);
-
-
-
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2_fw.h linux-libre-3.2-gnu/drivers/net/bnx2_fw.h
--- linux-libre-3.1-gnu/drivers/net/bnx2_fw.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2_fw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,88 +0,0 @@
-/* bnx2_fw.h: Broadcom NX2 network driver.
- *
- * Copyright (c) 2004, 2005, 2006, 2007 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.
- */
-
-/* Initialized Values for the Completion Processor. */
-static const struct cpu_reg cpu_reg_com = {
-	.mode = BNX2_COM_CPU_MODE,
-	.mode_value_halt = BNX2_COM_CPU_MODE_SOFT_HALT,
-	.mode_value_sstep = BNX2_COM_CPU_MODE_STEP_ENA,
-	.state = BNX2_COM_CPU_STATE,
-	.state_value_clear = 0xffffff,
-	.gpr0 = BNX2_COM_CPU_REG_FILE,
-	.evmask = BNX2_COM_CPU_EVENT_MASK,
-	.pc = BNX2_COM_CPU_PROGRAM_COUNTER,
-	.inst = BNX2_COM_CPU_INSTRUCTION,
-	.bp = BNX2_COM_CPU_HW_BREAKPOINT,
-	.spad_base = BNX2_COM_SCRATCH,
-	.mips_view_base = 0x8000000,
-};
-
-/* Initialized Values the Command Processor. */
-static const struct cpu_reg cpu_reg_cp = {
-	.mode = BNX2_CP_CPU_MODE,
-	.mode_value_halt = BNX2_CP_CPU_MODE_SOFT_HALT,
-	.mode_value_sstep = BNX2_CP_CPU_MODE_STEP_ENA,
-	.state = BNX2_CP_CPU_STATE,
-	.state_value_clear = 0xffffff,
-	.gpr0 = BNX2_CP_CPU_REG_FILE,
-	.evmask = BNX2_CP_CPU_EVENT_MASK,
-	.pc = BNX2_CP_CPU_PROGRAM_COUNTER,
-	.inst = BNX2_CP_CPU_INSTRUCTION,
-	.bp = BNX2_CP_CPU_HW_BREAKPOINT,
-	.spad_base = BNX2_CP_SCRATCH,
-	.mips_view_base = 0x8000000,
-};
-
-/* Initialized Values for the RX Processor. */
-static const struct cpu_reg cpu_reg_rxp = {
-	.mode = BNX2_RXP_CPU_MODE,
-	.mode_value_halt = BNX2_RXP_CPU_MODE_SOFT_HALT,
-	.mode_value_sstep = BNX2_RXP_CPU_MODE_STEP_ENA,
-	.state = BNX2_RXP_CPU_STATE,
-	.state_value_clear = 0xffffff,
-	.gpr0 = BNX2_RXP_CPU_REG_FILE,
-	.evmask = BNX2_RXP_CPU_EVENT_MASK,
-	.pc = BNX2_RXP_CPU_PROGRAM_COUNTER,
-	.inst = BNX2_RXP_CPU_INSTRUCTION,
-	.bp = BNX2_RXP_CPU_HW_BREAKPOINT,
-	.spad_base = BNX2_RXP_SCRATCH,
-	.mips_view_base = 0x8000000,
-};
-
-/* Initialized Values for the TX Patch-up Processor. */
-static const struct cpu_reg cpu_reg_tpat = {
-	.mode = BNX2_TPAT_CPU_MODE,
-	.mode_value_halt = BNX2_TPAT_CPU_MODE_SOFT_HALT,
-	.mode_value_sstep = BNX2_TPAT_CPU_MODE_STEP_ENA,
-	.state = BNX2_TPAT_CPU_STATE,
-	.state_value_clear = 0xffffff,
-	.gpr0 = BNX2_TPAT_CPU_REG_FILE,
-	.evmask = BNX2_TPAT_CPU_EVENT_MASK,
-	.pc = BNX2_TPAT_CPU_PROGRAM_COUNTER,
-	.inst = BNX2_TPAT_CPU_INSTRUCTION,
-	.bp = BNX2_TPAT_CPU_HW_BREAKPOINT,
-	.spad_base = BNX2_TPAT_SCRATCH,
-	.mips_view_base = 0x8000000,
-};
-
-/* Initialized Values for the TX Processor. */
-static const struct cpu_reg cpu_reg_txp = {
-	.mode = BNX2_TXP_CPU_MODE,
-	.mode_value_halt = BNX2_TXP_CPU_MODE_SOFT_HALT,
-	.mode_value_sstep = BNX2_TXP_CPU_MODE_STEP_ENA,
-	.state = BNX2_TXP_CPU_STATE,
-	.state_value_clear = 0xffffff,
-	.gpr0 = BNX2_TXP_CPU_REG_FILE,
-	.evmask = BNX2_TXP_CPU_EVENT_MASK,
-	.pc = BNX2_TXP_CPU_PROGRAM_COUNTER,
-	.inst = BNX2_TXP_CPU_INSTRUCTION,
-	.bp = BNX2_TXP_CPU_HW_BREAKPOINT,
-	.spad_base = BNX2_TXP_SCRATCH,
-	.mips_view_base = 0x8000000,
-};
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2.h linux-libre-3.2-gnu/drivers/net/bnx2.h
--- linux-libre-3.1-gnu/drivers/net/bnx2.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7388 +0,0 @@
-/* bnx2.h: Broadcom NX2 network driver.
- *
- * 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
- * the Free Software Foundation.
- *
- * Written by: Michael Chan  (mchan@broadcom.com)
- */
-
-
-#ifndef BNX2_H
-#define BNX2_H
-
-/* Hardware data structures and register definitions automatically
- * generated from RTL code. Do not modify.
- */
-
-/*
- *  tx_bd definition
- */
-struct tx_bd {
-	u32 tx_bd_haddr_hi;
-	u32 tx_bd_haddr_lo;
-	u32 tx_bd_mss_nbytes;
-		#define TX_BD_TCP6_OFF2_SHL		(14)
-	u32 tx_bd_vlan_tag_flags;
-		#define TX_BD_FLAGS_CONN_FAULT		(1<<0)
-		#define TX_BD_FLAGS_TCP6_OFF0_MSK	(3<<1)
-		#define TX_BD_FLAGS_TCP6_OFF0_SHL	(1)
-		#define TX_BD_FLAGS_TCP_UDP_CKSUM	(1<<1)
-		#define TX_BD_FLAGS_IP_CKSUM		(1<<2)
-		#define TX_BD_FLAGS_VLAN_TAG		(1<<3)
-		#define TX_BD_FLAGS_COAL_NOW		(1<<4)
-		#define TX_BD_FLAGS_DONT_GEN_CRC	(1<<5)
-		#define TX_BD_FLAGS_END			(1<<6)
-		#define TX_BD_FLAGS_START		(1<<7)
-		#define TX_BD_FLAGS_SW_OPTION_WORD	(0x1f<<8)
-		#define TX_BD_FLAGS_TCP6_OFF4_SHL	(12)
-		#define TX_BD_FLAGS_SW_FLAGS		(1<<13)
-		#define TX_BD_FLAGS_SW_SNAP		(1<<14)
-		#define TX_BD_FLAGS_SW_LSO		(1<<15)
-
-};
-
-
-/*
- *  rx_bd definition
- */
-struct rx_bd {
-	u32 rx_bd_haddr_hi;
-	u32 rx_bd_haddr_lo;
-	u32 rx_bd_len;
-	u32 rx_bd_flags;
-		#define RX_BD_FLAGS_NOPUSH		(1<<0)
-		#define RX_BD_FLAGS_DUMMY		(1<<1)
-		#define RX_BD_FLAGS_END			(1<<2)
-		#define RX_BD_FLAGS_START		(1<<3)
-
-};
-
-#define BNX2_RX_ALIGN			16
-
-/*
- *  status_block definition
- */
-struct status_block {
-	u32 status_attn_bits;
-		#define STATUS_ATTN_BITS_LINK_STATE		(1L<<0)
-		#define STATUS_ATTN_BITS_TX_SCHEDULER_ABORT	(1L<<1)
-		#define STATUS_ATTN_BITS_TX_BD_READ_ABORT	(1L<<2)
-		#define STATUS_ATTN_BITS_TX_BD_CACHE_ABORT	(1L<<3)
-		#define STATUS_ATTN_BITS_TX_PROCESSOR_ABORT	(1L<<4)
-		#define STATUS_ATTN_BITS_TX_DMA_ABORT		(1L<<5)
-		#define STATUS_ATTN_BITS_TX_PATCHUP_ABORT	(1L<<6)
-		#define STATUS_ATTN_BITS_TX_ASSEMBLER_ABORT	(1L<<7)
-		#define STATUS_ATTN_BITS_RX_PARSER_MAC_ABORT	(1L<<8)
-		#define STATUS_ATTN_BITS_RX_PARSER_CATCHUP_ABORT	(1L<<9)
-		#define STATUS_ATTN_BITS_RX_MBUF_ABORT		(1L<<10)
-		#define STATUS_ATTN_BITS_RX_LOOKUP_ABORT	(1L<<11)
-		#define STATUS_ATTN_BITS_RX_PROCESSOR_ABORT	(1L<<12)
-		#define STATUS_ATTN_BITS_RX_V2P_ABORT		(1L<<13)
-		#define STATUS_ATTN_BITS_RX_BD_CACHE_ABORT	(1L<<14)
-		#define STATUS_ATTN_BITS_RX_DMA_ABORT		(1L<<15)
-		#define STATUS_ATTN_BITS_COMPLETION_ABORT	(1L<<16)
-		#define STATUS_ATTN_BITS_HOST_COALESCE_ABORT	(1L<<17)
-		#define STATUS_ATTN_BITS_MAILBOX_QUEUE_ABORT	(1L<<18)
-		#define STATUS_ATTN_BITS_CONTEXT_ABORT		(1L<<19)
-		#define STATUS_ATTN_BITS_CMD_SCHEDULER_ABORT	(1L<<20)
-		#define STATUS_ATTN_BITS_CMD_PROCESSOR_ABORT	(1L<<21)
-		#define STATUS_ATTN_BITS_MGMT_PROCESSOR_ABORT	(1L<<22)
-		#define STATUS_ATTN_BITS_MAC_ABORT		(1L<<23)
-		#define STATUS_ATTN_BITS_TIMER_ABORT		(1L<<24)
-		#define STATUS_ATTN_BITS_DMAE_ABORT		(1L<<25)
-		#define STATUS_ATTN_BITS_FLSH_ABORT		(1L<<26)
-		#define STATUS_ATTN_BITS_GRC_ABORT		(1L<<27)
-		#define STATUS_ATTN_BITS_EPB_ERROR		(1L<<30)
-		#define STATUS_ATTN_BITS_PARITY_ERROR		(1L<<31)
-
-	u32 status_attn_bits_ack;
-#if defined(__BIG_ENDIAN)
-	u16 status_tx_quick_consumer_index0;
-	u16 status_tx_quick_consumer_index1;
-	u16 status_tx_quick_consumer_index2;
-	u16 status_tx_quick_consumer_index3;
-	u16 status_rx_quick_consumer_index0;
-	u16 status_rx_quick_consumer_index1;
-	u16 status_rx_quick_consumer_index2;
-	u16 status_rx_quick_consumer_index3;
-	u16 status_rx_quick_consumer_index4;
-	u16 status_rx_quick_consumer_index5;
-	u16 status_rx_quick_consumer_index6;
-	u16 status_rx_quick_consumer_index7;
-	u16 status_rx_quick_consumer_index8;
-	u16 status_rx_quick_consumer_index9;
-	u16 status_rx_quick_consumer_index10;
-	u16 status_rx_quick_consumer_index11;
-	u16 status_rx_quick_consumer_index12;
-	u16 status_rx_quick_consumer_index13;
-	u16 status_rx_quick_consumer_index14;
-	u16 status_rx_quick_consumer_index15;
-	u16 status_completion_producer_index;
-	u16 status_cmd_consumer_index;
-	u16 status_idx;
-	u8 status_unused;
-	u8 status_blk_num;
-#elif defined(__LITTLE_ENDIAN)
-	u16 status_tx_quick_consumer_index1;
-	u16 status_tx_quick_consumer_index0;
-	u16 status_tx_quick_consumer_index3;
-	u16 status_tx_quick_consumer_index2;
-	u16 status_rx_quick_consumer_index1;
-	u16 status_rx_quick_consumer_index0;
-	u16 status_rx_quick_consumer_index3;
-	u16 status_rx_quick_consumer_index2;
-	u16 status_rx_quick_consumer_index5;
-	u16 status_rx_quick_consumer_index4;
-	u16 status_rx_quick_consumer_index7;
-	u16 status_rx_quick_consumer_index6;
-	u16 status_rx_quick_consumer_index9;
-	u16 status_rx_quick_consumer_index8;
-	u16 status_rx_quick_consumer_index11;
-	u16 status_rx_quick_consumer_index10;
-	u16 status_rx_quick_consumer_index13;
-	u16 status_rx_quick_consumer_index12;
-	u16 status_rx_quick_consumer_index15;
-	u16 status_rx_quick_consumer_index14;
-	u16 status_cmd_consumer_index;
-	u16 status_completion_producer_index;
-	u8 status_blk_num;
-	u8 status_unused;
-	u16 status_idx;
-#endif
-};
-
-/*
- *  status_block definition
- */
-struct status_block_msix {
-#if defined(__BIG_ENDIAN)
-	u16 status_tx_quick_consumer_index;
-	u16 status_rx_quick_consumer_index;
-	u16 status_completion_producer_index;
-	u16 status_cmd_consumer_index;
-	u32 status_unused;
-	u16 status_idx;
-	u8 status_unused2;
-	u8 status_blk_num;
-#elif defined(__LITTLE_ENDIAN)
-	u16 status_rx_quick_consumer_index;
-	u16 status_tx_quick_consumer_index;
-	u16 status_cmd_consumer_index;
-	u16 status_completion_producer_index;
-	u32 status_unused;
-	u8 status_blk_num;
-	u8 status_unused2;
-	u16 status_idx;
-#endif
-};
-
-#define BNX2_SBLK_MSIX_ALIGN_SIZE	128
-
-
-/*
- *  statistics_block definition
- */
-struct statistics_block {
-	u32 stat_IfHCInOctets_hi;
-	u32 stat_IfHCInOctets_lo;
-	u32 stat_IfHCInBadOctets_hi;
-	u32 stat_IfHCInBadOctets_lo;
-	u32 stat_IfHCOutOctets_hi;
-	u32 stat_IfHCOutOctets_lo;
-	u32 stat_IfHCOutBadOctets_hi;
-	u32 stat_IfHCOutBadOctets_lo;
-	u32 stat_IfHCInUcastPkts_hi;
-	u32 stat_IfHCInUcastPkts_lo;
-	u32 stat_IfHCInMulticastPkts_hi;
-	u32 stat_IfHCInMulticastPkts_lo;
-	u32 stat_IfHCInBroadcastPkts_hi;
-	u32 stat_IfHCInBroadcastPkts_lo;
-	u32 stat_IfHCOutUcastPkts_hi;
-	u32 stat_IfHCOutUcastPkts_lo;
-	u32 stat_IfHCOutMulticastPkts_hi;
-	u32 stat_IfHCOutMulticastPkts_lo;
-	u32 stat_IfHCOutBroadcastPkts_hi;
-	u32 stat_IfHCOutBroadcastPkts_lo;
-	u32 stat_emac_tx_stat_dot3statsinternalmactransmiterrors;
-	u32 stat_Dot3StatsCarrierSenseErrors;
-	u32 stat_Dot3StatsFCSErrors;
-	u32 stat_Dot3StatsAlignmentErrors;
-	u32 stat_Dot3StatsSingleCollisionFrames;
-	u32 stat_Dot3StatsMultipleCollisionFrames;
-	u32 stat_Dot3StatsDeferredTransmissions;
-	u32 stat_Dot3StatsExcessiveCollisions;
-	u32 stat_Dot3StatsLateCollisions;
-	u32 stat_EtherStatsCollisions;
-	u32 stat_EtherStatsFragments;
-	u32 stat_EtherStatsJabbers;
-	u32 stat_EtherStatsUndersizePkts;
-	u32 stat_EtherStatsOverrsizePkts;
-	u32 stat_EtherStatsPktsRx64Octets;
-	u32 stat_EtherStatsPktsRx65Octetsto127Octets;
-	u32 stat_EtherStatsPktsRx128Octetsto255Octets;
-	u32 stat_EtherStatsPktsRx256Octetsto511Octets;
-	u32 stat_EtherStatsPktsRx512Octetsto1023Octets;
-	u32 stat_EtherStatsPktsRx1024Octetsto1522Octets;
-	u32 stat_EtherStatsPktsRx1523Octetsto9022Octets;
-	u32 stat_EtherStatsPktsTx64Octets;
-	u32 stat_EtherStatsPktsTx65Octetsto127Octets;
-	u32 stat_EtherStatsPktsTx128Octetsto255Octets;
-	u32 stat_EtherStatsPktsTx256Octetsto511Octets;
-	u32 stat_EtherStatsPktsTx512Octetsto1023Octets;
-	u32 stat_EtherStatsPktsTx1024Octetsto1522Octets;
-	u32 stat_EtherStatsPktsTx1523Octetsto9022Octets;
-	u32 stat_XonPauseFramesReceived;
-	u32 stat_XoffPauseFramesReceived;
-	u32 stat_OutXonSent;
-	u32 stat_OutXoffSent;
-	u32 stat_FlowControlDone;
-	u32 stat_MacControlFramesReceived;
-	u32 stat_XoffStateEntered;
-	u32 stat_IfInFramesL2FilterDiscards;
-	u32 stat_IfInRuleCheckerDiscards;
-	u32 stat_IfInFTQDiscards;
-	u32 stat_IfInMBUFDiscards;
-	u32 stat_IfInRuleCheckerP4Hit;
-	u32 stat_CatchupInRuleCheckerDiscards;
-	u32 stat_CatchupInFTQDiscards;
-	u32 stat_CatchupInMBUFDiscards;
-	u32 stat_CatchupInRuleCheckerP4Hit;
-	u32 stat_GenStat00;
-	u32 stat_GenStat01;
-	u32 stat_GenStat02;
-	u32 stat_GenStat03;
-	u32 stat_GenStat04;
-	u32 stat_GenStat05;
-	u32 stat_GenStat06;
-	u32 stat_GenStat07;
-	u32 stat_GenStat08;
-	u32 stat_GenStat09;
-	u32 stat_GenStat10;
-	u32 stat_GenStat11;
-	u32 stat_GenStat12;
-	u32 stat_GenStat13;
-	u32 stat_GenStat14;
-	u32 stat_GenStat15;
-	u32 stat_FwRxDrop;
-};
-
-
-/*
- *  l2_fhdr definition
- */
-struct l2_fhdr {
-	u32 l2_fhdr_status;
-		#define L2_FHDR_STATUS_RULE_CLASS	(0x7<<0)
-		#define L2_FHDR_STATUS_RULE_P2		(1<<3)
-		#define L2_FHDR_STATUS_RULE_P3		(1<<4)
-		#define L2_FHDR_STATUS_RULE_P4		(1<<5)
-		#define L2_FHDR_STATUS_L2_VLAN_TAG	(1<<6)
-		#define L2_FHDR_STATUS_L2_LLC_SNAP	(1<<7)
-		#define L2_FHDR_STATUS_RSS_HASH		(1<<8)
-		#define L2_FHDR_STATUS_IP_DATAGRAM	(1<<13)
-		#define L2_FHDR_STATUS_TCP_SEGMENT	(1<<14)
-		#define L2_FHDR_STATUS_UDP_DATAGRAM	(1<<15)
-
-		#define L2_FHDR_STATUS_SPLIT		(1<<16)
-		#define L2_FHDR_ERRORS_BAD_CRC		(1<<17)
-		#define L2_FHDR_ERRORS_PHY_DECODE	(1<<18)
-		#define L2_FHDR_ERRORS_ALIGNMENT	(1<<19)
-		#define L2_FHDR_ERRORS_TOO_SHORT	(1<<20)
-		#define L2_FHDR_ERRORS_GIANT_FRAME	(1<<21)
-		#define L2_FHDR_ERRORS_TCP_XSUM		(1<<28)
-		#define L2_FHDR_ERRORS_UDP_XSUM		(1<<31)
-
-		#define L2_FHDR_STATUS_USE_RXHASH	\
-			(L2_FHDR_STATUS_TCP_SEGMENT | L2_FHDR_STATUS_RSS_HASH)
-
-	u32 l2_fhdr_hash;
-#if defined(__BIG_ENDIAN)
-	u16 l2_fhdr_pkt_len;
-	u16 l2_fhdr_vlan_tag;
-	u16 l2_fhdr_ip_xsum;
-	u16 l2_fhdr_tcp_udp_xsum;
-#elif defined(__LITTLE_ENDIAN)
-	u16 l2_fhdr_vlan_tag;
-	u16 l2_fhdr_pkt_len;
-	u16 l2_fhdr_tcp_udp_xsum;
-	u16 l2_fhdr_ip_xsum;
-#endif
-};
-
-#define BNX2_RX_OFFSET		(sizeof(struct l2_fhdr) + 2)
-
-/*
- *  l2_context definition
- */
-#define BNX2_L2CTX_TYPE					0x00000000
-#define BNX2_L2CTX_TYPE_SIZE_L2				 ((0xc0/0x20)<<16)
-#define BNX2_L2CTX_TYPE_TYPE				 (0xf<<28)
-#define BNX2_L2CTX_TYPE_TYPE_EMPTY			 (0<<28)
-#define BNX2_L2CTX_TYPE_TYPE_L2				 (1<<28)
-
-#define BNX2_L2CTX_TX_HOST_BIDX				0x00000088
-#define BNX2_L2CTX_EST_NBD				0x00000088
-#define BNX2_L2CTX_CMD_TYPE				0x00000088
-#define BNX2_L2CTX_CMD_TYPE_TYPE			 (0xf<<24)
-#define BNX2_L2CTX_CMD_TYPE_TYPE_L2			 (0<<24)
-#define BNX2_L2CTX_CMD_TYPE_TYPE_TCP			 (1<<24)
-
-#define BNX2_L2CTX_TX_HOST_BSEQ				0x00000090
-#define BNX2_L2CTX_TSCH_BSEQ				0x00000094
-#define BNX2_L2CTX_TBDR_BSEQ				0x00000098
-#define BNX2_L2CTX_TBDR_BOFF				0x0000009c
-#define BNX2_L2CTX_TBDR_BIDX				0x0000009c
-#define BNX2_L2CTX_TBDR_BHADDR_HI			0x000000a0
-#define BNX2_L2CTX_TBDR_BHADDR_LO			0x000000a4
-#define BNX2_L2CTX_TXP_BOFF				0x000000a8
-#define BNX2_L2CTX_TXP_BIDX				0x000000a8
-#define BNX2_L2CTX_TXP_BSEQ				0x000000ac
-
-#define BNX2_L2CTX_TYPE_XI				0x00000080
-#define BNX2_L2CTX_CMD_TYPE_XI				0x00000240
-#define BNX2_L2CTX_TBDR_BHADDR_HI_XI			0x00000258
-#define BNX2_L2CTX_TBDR_BHADDR_LO_XI			0x0000025c
-
-/*
- *  l2_bd_chain_context definition
- */
-#define BNX2_L2CTX_BD_PRE_READ				0x00000000
-#define BNX2_L2CTX_CTX_SIZE				0x00000000
-#define BNX2_L2CTX_CTX_TYPE				0x00000000
-#define BNX2_L2CTX_FLOW_CTRL_ENABLE			 0x000000ff
-#define BNX2_L2CTX_CTX_TYPE_SIZE_L2			 ((0x20/20)<<16)
-#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE		 (0xf<<28)
-#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_UNDEFINED	 (0<<28)
-#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE	 (1<<28)
-
-#define BNX2_L2CTX_HOST_BDIDX				0x00000004
-#define BNX2_L2CTX_L5_STATUSB_NUM_SHIFT			 16
-#define BNX2_L2CTX_L2_STATUSB_NUM_SHIFT			 24
-#define BNX2_L2CTX_L5_STATUSB_NUM(sb_id)		\
-	(((sb_id) > 0) ? (((sb_id) + 7) << BNX2_L2CTX_L5_STATUSB_NUM_SHIFT) : 0)
-#define BNX2_L2CTX_L2_STATUSB_NUM(sb_id)		\
-	(((sb_id) > 0) ? (((sb_id) + 7) << BNX2_L2CTX_L2_STATUSB_NUM_SHIFT) : 0)
-#define BNX2_L2CTX_HOST_BSEQ				0x00000008
-#define BNX2_L2CTX_NX_BSEQ				0x0000000c
-#define BNX2_L2CTX_NX_BDHADDR_HI			0x00000010
-#define BNX2_L2CTX_NX_BDHADDR_LO			0x00000014
-#define BNX2_L2CTX_NX_BDIDX				0x00000018
-
-#define BNX2_L2CTX_HOST_PG_BDIDX			0x00000044
-#define BNX2_L2CTX_PG_BUF_SIZE				0x00000048
-#define BNX2_L2CTX_RBDC_KEY				0x0000004c
-#define BNX2_L2CTX_RBDC_JUMBO_KEY			 0x3ffe
-#define BNX2_L2CTX_NX_PG_BDHADDR_HI			0x00000050
-#define BNX2_L2CTX_NX_PG_BDHADDR_LO			0x00000054
-
-/*
- *  pci_config_l definition
- *  offset: 0000
- */
-#define BNX2_PCICFG_MSI_CONTROL				0x00000058
-#define BNX2_PCICFG_MSI_CONTROL_ENABLE			 (1L<<16)
-
-#define BNX2_PCICFG_MISC_CONFIG				0x00000068
-#define BNX2_PCICFG_MISC_CONFIG_TARGET_BYTE_SWAP	 (1L<<2)
-#define BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP	 (1L<<3)
-#define BNX2_PCICFG_MISC_CONFIG_RESERVED1		 (1L<<4)
-#define BNX2_PCICFG_MISC_CONFIG_CLOCK_CTL_ENA		 (1L<<5)
-#define BNX2_PCICFG_MISC_CONFIG_TARGET_GRC_WORD_SWAP	 (1L<<6)
-#define BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA		 (1L<<7)
-#define BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ		 (1L<<8)
-#define BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY		 (1L<<9)
-#define BNX2_PCICFG_MISC_CONFIG_GRC_WIN1_SWAP_EN	 (1L<<10)
-#define BNX2_PCICFG_MISC_CONFIG_GRC_WIN2_SWAP_EN	 (1L<<11)
-#define BNX2_PCICFG_MISC_CONFIG_GRC_WIN3_SWAP_EN	 (1L<<12)
-#define BNX2_PCICFG_MISC_CONFIG_ASIC_METAL_REV		 (0xffL<<16)
-#define BNX2_PCICFG_MISC_CONFIG_ASIC_BASE_REV		 (0xfL<<24)
-#define BNX2_PCICFG_MISC_CONFIG_ASIC_ID			 (0xfL<<28)
-
-#define BNX2_PCICFG_MISC_STATUS				0x0000006c
-#define BNX2_PCICFG_MISC_STATUS_INTA_VALUE		 (1L<<0)
-#define BNX2_PCICFG_MISC_STATUS_32BIT_DET		 (1L<<1)
-#define BNX2_PCICFG_MISC_STATUS_M66EN			 (1L<<2)
-#define BNX2_PCICFG_MISC_STATUS_PCIX_DET		 (1L<<3)
-#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED		 (0x3L<<4)
-#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_66		 (0L<<4)
-#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_100		 (1L<<4)
-#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_133		 (2L<<4)
-#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_PCI_MODE	 (3L<<4)
-#define BNX2_PCICFG_MISC_STATUS_BAD_MEM_WRITE_BE	 (1L<<8)
-
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS		0x00000070
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET	 (0xfL<<0)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ	 (0L<<0)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ	 (1L<<0)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ	 (2L<<0)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ	 (3L<<0)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ	 (4L<<0)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ	 (5L<<0)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ	 (6L<<0)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ	 (7L<<0)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW	 (0xfL<<0)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_DISABLE	 (1L<<6)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT	 (1L<<7)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC	 (0x7L<<8)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_UNDEF	 (0L<<8)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12	 (1L<<8)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6	 (2L<<8)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62	 (4L<<8)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_MIN_POWER	 (1L<<11)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED	 (0xfL<<12)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100	 (0L<<12)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80	 (1L<<12)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_50	 (2L<<12)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40	 (4L<<12)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25	 (8L<<12)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP	 (1L<<16)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_17	 (1L<<17)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_18	 (1L<<18)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_19	 (1L<<19)
-#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED	 (0xfffL<<20)
-
-#define BNX2_PCICFG_REG_WINDOW_ADDRESS			0x00000078
-#define BNX2_PCICFG_REG_WINDOW_ADDRESS_VAL		 (0xfffffL<<2)
-
-#define BNX2_PCICFG_REG_WINDOW				0x00000080
-#define BNX2_PCICFG_INT_ACK_CMD				0x00000084
-#define BNX2_PCICFG_INT_ACK_CMD_INDEX			 (0xffffL<<0)
-#define BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID		 (1L<<16)
-#define BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM	 (1L<<17)
-#define BNX2_PCICFG_INT_ACK_CMD_MASK_INT		 (1L<<18)
-#define BNX2_PCICFG_INT_ACK_CMD_INTERRUPT_NUM		 (0xfL<<24)
-#define BNX2_PCICFG_INT_ACK_CMD_INT_NUM_SHIFT		 24
-
-#define BNX2_PCICFG_STATUS_BIT_SET_CMD			0x00000088
-#define BNX2_PCICFG_STATUS_BIT_CLEAR_CMD		0x0000008c
-#define BNX2_PCICFG_MAILBOX_QUEUE_ADDR			0x00000090
-#define BNX2_PCICFG_MAILBOX_QUEUE_DATA			0x00000094
-
-#define BNX2_PCICFG_DEVICE_CONTROL			0x000000b4
-#define BNX2_PCICFG_DEVICE_STATUS_NO_PEND		 ((1L<<5)<<16)
-
-/*
- *  pci_reg definition
- *  offset: 0x400
- */
-#define BNX2_PCI_GRC_WINDOW_ADDR			0x00000400
-#define BNX2_PCI_GRC_WINDOW_ADDR_VALUE			 (0x1ffL<<13)
-#define BNX2_PCI_GRC_WINDOW_ADDR_SEP_WIN		 (1L<<31)
-
-#define BNX2_PCI_GRC_WINDOW2_BASE		 	 0xc000
-#define BNX2_PCI_GRC_WINDOW3_BASE		 	 0xe000
-
-#define BNX2_PCI_CONFIG_1				0x00000404
-#define BNX2_PCI_CONFIG_1_RESERVED0			 (0xffL<<0)
-#define BNX2_PCI_CONFIG_1_READ_BOUNDARY			 (0x7L<<8)
-#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_OFF		 (0L<<8)
-#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_16		 (1L<<8)
-#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_32		 (2L<<8)
-#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_64		 (3L<<8)
-#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_128		 (4L<<8)
-#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_256		 (5L<<8)
-#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_512		 (6L<<8)
-#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_1024		 (7L<<8)
-#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY		 (0x7L<<11)
-#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_OFF		 (0L<<11)
-#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_16		 (1L<<11)
-#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_32		 (2L<<11)
-#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_64		 (3L<<11)
-#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_128		 (4L<<11)
-#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_256		 (5L<<11)
-#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_512		 (6L<<11)
-#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_1024		 (7L<<11)
-#define BNX2_PCI_CONFIG_1_RESERVED1			 (0x3ffffL<<14)
-
-#define BNX2_PCI_CONFIG_2				0x00000408
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE			 (0xfL<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE_DISABLED		 (0L<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE_64K			 (1L<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE_128K		 (2L<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE_256K		 (3L<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE_512K		 (4L<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE_1M			 (5L<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE_2M			 (6L<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE_4M			 (7L<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE_8M			 (8L<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE_16M			 (9L<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE_32M			 (10L<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE_64M			 (11L<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE_128M		 (12L<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE_256M		 (13L<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE_512M		 (14L<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_SIZE_1G			 (15L<<0)
-#define BNX2_PCI_CONFIG_2_BAR1_64ENA			 (1L<<4)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_RETRY			 (1L<<5)
-#define BNX2_PCI_CONFIG_2_CFG_CYCLE_RETRY		 (1L<<6)
-#define BNX2_PCI_CONFIG_2_FIRST_CFG_DONE		 (1L<<7)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE			 (0xffL<<8)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_DISABLED		 (0L<<8)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_1K		 (1L<<8)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_2K		 (2L<<8)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_4K		 (3L<<8)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_8K		 (4L<<8)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_16K		 (5L<<8)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_32K		 (6L<<8)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_64K		 (7L<<8)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_128K		 (8L<<8)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_256K		 (9L<<8)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_512K		 (10L<<8)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_1M		 (11L<<8)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_2M		 (12L<<8)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_4M		 (13L<<8)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_8M		 (14L<<8)
-#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_16M		 (15L<<8)
-#define BNX2_PCI_CONFIG_2_MAX_SPLIT_LIMIT		 (0x1fL<<16)
-#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT		 (0x3L<<21)
-#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_512		 (0L<<21)
-#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_1K		 (1L<<21)
-#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_2K		 (2L<<21)
-#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_4K		 (3L<<21)
-#define BNX2_PCI_CONFIG_2_FORCE_32_BIT_MSTR		 (1L<<23)
-#define BNX2_PCI_CONFIG_2_FORCE_32_BIT_TGT		 (1L<<24)
-#define BNX2_PCI_CONFIG_2_KEEP_REQ_ASSERT		 (1L<<25)
-#define BNX2_PCI_CONFIG_2_RESERVED0			 (0x3fL<<26)
-#define BNX2_PCI_CONFIG_2_BAR_PREFETCH_XI		 (1L<<16)
-#define BNX2_PCI_CONFIG_2_RESERVED0_XI			 (0x7fffL<<17)
-
-#define BNX2_PCI_CONFIG_3				0x0000040c
-#define BNX2_PCI_CONFIG_3_STICKY_BYTE			 (0xffL<<0)
-#define BNX2_PCI_CONFIG_3_REG_STICKY_BYTE		 (0xffL<<8)
-#define BNX2_PCI_CONFIG_3_FORCE_PME			 (1L<<24)
-#define BNX2_PCI_CONFIG_3_PME_STATUS			 (1L<<25)
-#define BNX2_PCI_CONFIG_3_PME_ENABLE			 (1L<<26)
-#define BNX2_PCI_CONFIG_3_PM_STATE			 (0x3L<<27)
-#define BNX2_PCI_CONFIG_3_VAUX_PRESET			 (1L<<30)
-#define BNX2_PCI_CONFIG_3_PCI_POWER			 (1L<<31)
-
-#define BNX2_PCI_PM_DATA_A				0x00000410
-#define BNX2_PCI_PM_DATA_A_PM_DATA_0_PRG		 (0xffL<<0)
-#define BNX2_PCI_PM_DATA_A_PM_DATA_1_PRG		 (0xffL<<8)
-#define BNX2_PCI_PM_DATA_A_PM_DATA_2_PRG		 (0xffL<<16)
-#define BNX2_PCI_PM_DATA_A_PM_DATA_3_PRG		 (0xffL<<24)
-
-#define BNX2_PCI_PM_DATA_B				0x00000414
-#define BNX2_PCI_PM_DATA_B_PM_DATA_4_PRG		 (0xffL<<0)
-#define BNX2_PCI_PM_DATA_B_PM_DATA_5_PRG		 (0xffL<<8)
-#define BNX2_PCI_PM_DATA_B_PM_DATA_6_PRG		 (0xffL<<16)
-#define BNX2_PCI_PM_DATA_B_PM_DATA_7_PRG		 (0xffL<<24)
-
-#define BNX2_PCI_SWAP_DIAG0				0x00000418
-#define BNX2_PCI_SWAP_DIAG1				0x0000041c
-#define BNX2_PCI_EXP_ROM_ADDR				0x00000420
-#define BNX2_PCI_EXP_ROM_ADDR_ADDRESS			 (0x3fffffL<<2)
-#define BNX2_PCI_EXP_ROM_ADDR_REQ			 (1L<<31)
-
-#define BNX2_PCI_EXP_ROM_DATA				0x00000424
-#define BNX2_PCI_VPD_INTF				0x00000428
-#define BNX2_PCI_VPD_INTF_INTF_REQ			 (1L<<0)
-
-#define BNX2_PCI_VPD_ADDR_FLAG				0x0000042c
-#define BNX2_PCI_VPD_ADDR_FLAG_MSK			0x0000ffff
-#define BNX2_PCI_VPD_ADDR_FLAG_SL			0L
-#define BNX2_PCI_VPD_ADDR_FLAG_ADDRESS			 (0x1fffL<<2)
-#define BNX2_PCI_VPD_ADDR_FLAG_WR			 (1L<<15)
-
-#define BNX2_PCI_VPD_DATA				0x00000430
-#define BNX2_PCI_ID_VAL1				0x00000434
-#define BNX2_PCI_ID_VAL1_DEVICE_ID			 (0xffffL<<0)
-#define BNX2_PCI_ID_VAL1_VENDOR_ID			 (0xffffL<<16)
-
-#define BNX2_PCI_ID_VAL2				0x00000438
-#define BNX2_PCI_ID_VAL2_SUBSYSTEM_VENDOR_ID		 (0xffffL<<0)
-#define BNX2_PCI_ID_VAL2_SUBSYSTEM_ID			 (0xffffL<<16)
-
-#define BNX2_PCI_ID_VAL3				0x0000043c
-#define BNX2_PCI_ID_VAL3_CLASS_CODE			 (0xffffffL<<0)
-#define BNX2_PCI_ID_VAL3_REVISION_ID			 (0xffL<<24)
-
-#define BNX2_PCI_ID_VAL4				0x00000440
-#define BNX2_PCI_ID_VAL4_CAP_ENA			 (0xfL<<0)
-#define BNX2_PCI_ID_VAL4_CAP_ENA_0			 (0L<<0)
-#define BNX2_PCI_ID_VAL4_CAP_ENA_1			 (1L<<0)
-#define BNX2_PCI_ID_VAL4_CAP_ENA_2			 (2L<<0)
-#define BNX2_PCI_ID_VAL4_CAP_ENA_3			 (3L<<0)
-#define BNX2_PCI_ID_VAL4_CAP_ENA_4			 (4L<<0)
-#define BNX2_PCI_ID_VAL4_CAP_ENA_5			 (5L<<0)
-#define BNX2_PCI_ID_VAL4_CAP_ENA_6			 (6L<<0)
-#define BNX2_PCI_ID_VAL4_CAP_ENA_7			 (7L<<0)
-#define BNX2_PCI_ID_VAL4_CAP_ENA_8			 (8L<<0)
-#define BNX2_PCI_ID_VAL4_CAP_ENA_9			 (9L<<0)
-#define BNX2_PCI_ID_VAL4_CAP_ENA_10			 (10L<<0)
-#define BNX2_PCI_ID_VAL4_CAP_ENA_11			 (11L<<0)
-#define BNX2_PCI_ID_VAL4_CAP_ENA_12			 (12L<<0)
-#define BNX2_PCI_ID_VAL4_CAP_ENA_13			 (13L<<0)
-#define BNX2_PCI_ID_VAL4_CAP_ENA_14			 (14L<<0)
-#define BNX2_PCI_ID_VAL4_CAP_ENA_15			 (15L<<0)
-#define BNX2_PCI_ID_VAL4_RESERVED0			 (0x3L<<4)
-#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG			 (0x3L<<6)
-#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_0			 (0L<<6)
-#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_1			 (1L<<6)
-#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_2			 (2L<<6)
-#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_3			 (3L<<6)
-#define BNX2_PCI_ID_VAL4_MSI_PV_MASK_CAP		 (1L<<8)
-#define BNX2_PCI_ID_VAL4_MSI_LIMIT			 (0x7L<<9)
-#define BNX2_PCI_ID_VAL4_MULTI_MSG_CAP			 (0x7L<<12)
-#define BNX2_PCI_ID_VAL4_MSI_ENABLE			 (1L<<15)
-#define BNX2_PCI_ID_VAL4_MAX_64_ADVERTIZE		 (1L<<16)
-#define BNX2_PCI_ID_VAL4_MAX_133_ADVERTIZE		 (1L<<17)
-#define BNX2_PCI_ID_VAL4_RESERVED2			 (0x7L<<18)
-#define BNX2_PCI_ID_VAL4_MAX_CUMULATIVE_SIZE_B21	 (0x3L<<21)
-#define BNX2_PCI_ID_VAL4_MAX_SPLIT_SIZE_B21		 (0x3L<<23)
-#define BNX2_PCI_ID_VAL4_MAX_CUMULATIVE_SIZE_B0		 (1L<<25)
-#define BNX2_PCI_ID_VAL4_MAX_MEM_READ_SIZE_B10		 (0x3L<<26)
-#define BNX2_PCI_ID_VAL4_MAX_SPLIT_SIZE_B0		 (1L<<28)
-#define BNX2_PCI_ID_VAL4_RESERVED3			 (0x7L<<29)
-#define BNX2_PCI_ID_VAL4_RESERVED3_XI			 (0xffffL<<16)
-
-#define BNX2_PCI_ID_VAL5				0x00000444
-#define BNX2_PCI_ID_VAL5_D1_SUPPORT			 (1L<<0)
-#define BNX2_PCI_ID_VAL5_D2_SUPPORT			 (1L<<1)
-#define BNX2_PCI_ID_VAL5_PME_IN_D0			 (1L<<2)
-#define BNX2_PCI_ID_VAL5_PME_IN_D1			 (1L<<3)
-#define BNX2_PCI_ID_VAL5_PME_IN_D2			 (1L<<4)
-#define BNX2_PCI_ID_VAL5_PME_IN_D3_HOT			 (1L<<5)
-#define BNX2_PCI_ID_VAL5_RESERVED0_TE			 (0x3ffffffL<<6)
-#define BNX2_PCI_ID_VAL5_PM_VERSION_XI			 (0x7L<<6)
-#define BNX2_PCI_ID_VAL5_NO_SOFT_RESET_XI		 (1L<<9)
-#define BNX2_PCI_ID_VAL5_RESERVED0_XI			 (0x3fffffL<<10)
-
-#define BNX2_PCI_PCIX_EXTENDED_STATUS			0x00000448
-#define BNX2_PCI_PCIX_EXTENDED_STATUS_NO_SNOOP		 (1L<<8)
-#define BNX2_PCI_PCIX_EXTENDED_STATUS_LONG_BURST	 (1L<<9)
-#define BNX2_PCI_PCIX_EXTENDED_STATUS_SPLIT_COMP_MSG_CLASS	 (0xfL<<16)
-#define BNX2_PCI_PCIX_EXTENDED_STATUS_SPLIT_COMP_MSG_IDX	 (0xffL<<24)
-
-#define BNX2_PCI_ID_VAL6				0x0000044c
-#define BNX2_PCI_ID_VAL6_MAX_LAT			 (0xffL<<0)
-#define BNX2_PCI_ID_VAL6_MIN_GNT			 (0xffL<<8)
-#define BNX2_PCI_ID_VAL6_BIST				 (0xffL<<16)
-#define BNX2_PCI_ID_VAL6_RESERVED0			 (0xffL<<24)
-
-#define BNX2_PCI_MSI_DATA				0x00000450
-#define BNX2_PCI_MSI_DATA_MSI_DATA			 (0xffffL<<0)
-
-#define BNX2_PCI_MSI_ADDR_H				0x00000454
-#define BNX2_PCI_MSI_ADDR_L				0x00000458
-#define BNX2_PCI_MSI_ADDR_L_VAL				 (0x3fffffffL<<2)
-
-#define BNX2_PCI_CFG_ACCESS_CMD				0x0000045c
-#define BNX2_PCI_CFG_ACCESS_CMD_ADR			 (0x3fL<<2)
-#define BNX2_PCI_CFG_ACCESS_CMD_RD_REQ			 (1L<<27)
-#define BNX2_PCI_CFG_ACCESS_CMD_WR_REQ			 (0xfL<<28)
-
-#define BNX2_PCI_CFG_ACCESS_DATA			0x00000460
-#define BNX2_PCI_MSI_MASK				0x00000464
-#define BNX2_PCI_MSI_MASK_MSI_MASK			 (0xffffffffL<<0)
-
-#define BNX2_PCI_MSI_PEND				0x00000468
-#define BNX2_PCI_MSI_PEND_MSI_PEND			 (0xffffffffL<<0)
-
-#define BNX2_PCI_PM_DATA_C				0x0000046c
-#define BNX2_PCI_PM_DATA_C_PM_DATA_8_PRG		 (0xffL<<0)
-#define BNX2_PCI_PM_DATA_C_RESERVED0			 (0xffffffL<<8)
-
-#define BNX2_PCI_MSIX_CONTROL				0x000004c0
-#define BNX2_PCI_MSIX_CONTROL_MSIX_TBL_SIZ		 (0x7ffL<<0)
-#define BNX2_PCI_MSIX_CONTROL_RESERVED0			 (0x1fffffL<<11)
-
-#define BNX2_PCI_MSIX_TBL_OFF_BIR			0x000004c4
-#define BNX2_PCI_MSIX_TBL_OFF_BIR_MSIX_TBL_BIR		 (0x7L<<0)
-#define BNX2_PCI_MSIX_TBL_OFF_BIR_MSIX_TBL_OFF		 (0x1fffffffL<<3)
-
-#define BNX2_PCI_MSIX_PBA_OFF_BIT			0x000004c8
-#define BNX2_PCI_MSIX_PBA_OFF_BIT_MSIX_PBA_BIR		 (0x7L<<0)
-#define BNX2_PCI_MSIX_PBA_OFF_BIT_MSIX_PBA_OFF		 (0x1fffffffL<<3)
-
-#define BNX2_PCI_PCIE_CAPABILITY			0x000004d0
-#define BNX2_PCI_PCIE_CAPABILITY_INTERRUPT_MSG_NUM	 (0x1fL<<0)
-#define BNX2_PCI_PCIE_CAPABILITY_COMPLY_PCIE_1_1	 (1L<<5)
-
-#define BNX2_PCI_DEVICE_CAPABILITY			0x000004d4
-#define BNX2_PCI_DEVICE_CAPABILITY_MAX_PL_SIZ_SUPPORTED	 (0x7L<<0)
-#define BNX2_PCI_DEVICE_CAPABILITY_EXTENDED_TAG_SUPPORT	 (1L<<5)
-#define BNX2_PCI_DEVICE_CAPABILITY_L0S_ACCEPTABLE_LATENCY	 (0x7L<<6)
-#define BNX2_PCI_DEVICE_CAPABILITY_L1_ACCEPTABLE_LATENCY	 (0x7L<<9)
-#define BNX2_PCI_DEVICE_CAPABILITY_ROLE_BASED_ERR_RPT	 (1L<<15)
-
-#define BNX2_PCI_LINK_CAPABILITY			0x000004dc
-#define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_SPEED		 (0xfL<<0)
-#define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_SPEED_0001	 (1L<<0)
-#define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_SPEED_0010	 (1L<<0)
-#define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_WIDTH		 (0x1fL<<4)
-#define BNX2_PCI_LINK_CAPABILITY_CLK_POWER_MGMT		 (1L<<9)
-#define BNX2_PCI_LINK_CAPABILITY_ASPM_SUPPORT		 (0x3L<<10)
-#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_LAT		 (0x7L<<12)
-#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_LAT_101	 (5L<<12)
-#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_LAT_110	 (6L<<12)
-#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_LAT		 (0x7L<<15)
-#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_LAT_001	 (1L<<15)
-#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_LAT_010	 (2L<<15)
-#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_COMM_LAT	 (0x7L<<18)
-#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_COMM_LAT_101	 (5L<<18)
-#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_COMM_LAT_110	 (6L<<18)
-#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_COMM_LAT	 (0x7L<<21)
-#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_COMM_LAT_001	 (1L<<21)
-#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_COMM_LAT_010	 (2L<<21)
-#define BNX2_PCI_LINK_CAPABILITY_PORT_NUM		 (0xffL<<24)
-
-#define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2		0x000004e4
-#define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2_CMPL_TO_RANGE_SUPP	 (0xfL<<0)
-#define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2_CMPL_TO_DISABL_SUPP	 (1L<<4)
-#define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2_RESERVED	 (0x7ffffffL<<5)
-
-#define BNX2_PCI_PCIE_LINK_CAPABILITY_2			0x000004e8
-#define BNX2_PCI_PCIE_LINK_CAPABILITY_2_RESERVED	 (0xffffffffL<<0)
-
-#define BNX2_PCI_GRC_WINDOW1_ADDR			0x00000610
-#define BNX2_PCI_GRC_WINDOW1_ADDR_VALUE			 (0x1ffL<<13)
-
-#define BNX2_PCI_GRC_WINDOW2_ADDR			0x00000614
-#define BNX2_PCI_GRC_WINDOW2_ADDR_VALUE			 (0x1ffL<<13)
-
-#define BNX2_PCI_GRC_WINDOW3_ADDR			0x00000618
-#define BNX2_PCI_GRC_WINDOW3_ADDR_VALUE			 (0x1ffL<<13)
-
-#define BNX2_MSIX_TABLE_ADDR				 0x318000
-#define BNX2_MSIX_PBA_ADDR				 0x31c000
-
-/*
- *  misc_reg definition
- *  offset: 0x800
- */
-#define BNX2_MISC_COMMAND				0x00000800
-#define BNX2_MISC_COMMAND_ENABLE_ALL			 (1L<<0)
-#define BNX2_MISC_COMMAND_DISABLE_ALL			 (1L<<1)
-#define BNX2_MISC_COMMAND_SW_RESET			 (1L<<4)
-#define BNX2_MISC_COMMAND_POR_RESET			 (1L<<5)
-#define BNX2_MISC_COMMAND_HD_RESET			 (1L<<6)
-#define BNX2_MISC_COMMAND_CMN_SW_RESET			 (1L<<7)
-#define BNX2_MISC_COMMAND_PAR_ERROR			 (1L<<8)
-#define BNX2_MISC_COMMAND_CS16_ERR			 (1L<<9)
-#define BNX2_MISC_COMMAND_CS16_ERR_LOC			 (0xfL<<12)
-#define BNX2_MISC_COMMAND_PAR_ERR_RAM			 (0x7fL<<16)
-#define BNX2_MISC_COMMAND_POWERDOWN_EVENT		 (1L<<23)
-#define BNX2_MISC_COMMAND_SW_SHUTDOWN			 (1L<<24)
-#define BNX2_MISC_COMMAND_SHUTDOWN_EN			 (1L<<25)
-#define BNX2_MISC_COMMAND_DINTEG_ATTN_EN		 (1L<<26)
-#define BNX2_MISC_COMMAND_PCIE_LINK_IN_L23		 (1L<<27)
-#define BNX2_MISC_COMMAND_PCIE_DIS			 (1L<<28)
-
-#define BNX2_MISC_CFG					0x00000804
-#define BNX2_MISC_CFG_GRC_TMOUT				 (1L<<0)
-#define BNX2_MISC_CFG_NVM_WR_EN				 (0x3L<<1)
-#define BNX2_MISC_CFG_NVM_WR_EN_PROTECT			 (0L<<1)
-#define BNX2_MISC_CFG_NVM_WR_EN_PCI			 (1L<<1)
-#define BNX2_MISC_CFG_NVM_WR_EN_ALLOW			 (2L<<1)
-#define BNX2_MISC_CFG_NVM_WR_EN_ALLOW2			 (3L<<1)
-#define BNX2_MISC_CFG_BIST_EN				 (1L<<3)
-#define BNX2_MISC_CFG_CK25_OUT_ALT_SRC			 (1L<<4)
-#define BNX2_MISC_CFG_RESERVED5_TE			 (1L<<5)
-#define BNX2_MISC_CFG_RESERVED6_TE			 (1L<<6)
-#define BNX2_MISC_CFG_CLK_CTL_OVERRIDE			 (1L<<7)
-#define BNX2_MISC_CFG_LEDMODE				 (0x7L<<8)
-#define BNX2_MISC_CFG_LEDMODE_MAC			 (0L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY1_TE			 (1L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY2_TE			 (2L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY3_TE			 (3L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY4_TE			 (4L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY5_TE			 (5L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY6_TE			 (6L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY7_TE			 (7L<<8)
-#define BNX2_MISC_CFG_MCP_GRC_TMOUT_TE			 (1L<<11)
-#define BNX2_MISC_CFG_DBU_GRC_TMOUT_TE			 (1L<<12)
-#define BNX2_MISC_CFG_LEDMODE_XI			 (0xfL<<8)
-#define BNX2_MISC_CFG_LEDMODE_MAC_XI			 (0L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY1_XI			 (1L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY2_XI			 (2L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY3_XI			 (3L<<8)
-#define BNX2_MISC_CFG_LEDMODE_MAC2_XI			 (4L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY4_XI			 (5L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY5_XI			 (6L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY6_XI			 (7L<<8)
-#define BNX2_MISC_CFG_LEDMODE_MAC3_XI			 (8L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY7_XI			 (9L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY8_XI			 (10L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY9_XI			 (11L<<8)
-#define BNX2_MISC_CFG_LEDMODE_MAC4_XI			 (12L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY10_XI			 (13L<<8)
-#define BNX2_MISC_CFG_LEDMODE_PHY11_XI			 (14L<<8)
-#define BNX2_MISC_CFG_LEDMODE_UNUSED_XI			 (15L<<8)
-#define BNX2_MISC_CFG_PORT_SELECT_XI			 (1L<<13)
-#define BNX2_MISC_CFG_PARITY_MODE_XI			 (1L<<14)
-
-#define BNX2_MISC_ID					0x00000808
-#define BNX2_MISC_ID_BOND_ID				 (0xfL<<0)
-#define BNX2_MISC_ID_BOND_ID_X				 (0L<<0)
-#define BNX2_MISC_ID_BOND_ID_C				 (3L<<0)
-#define BNX2_MISC_ID_BOND_ID_S				 (12L<<0)
-#define BNX2_MISC_ID_CHIP_METAL				 (0xffL<<4)
-#define BNX2_MISC_ID_CHIP_REV				 (0xfL<<12)
-#define BNX2_MISC_ID_CHIP_NUM				 (0xffffL<<16)
-
-#define BNX2_MISC_ENABLE_STATUS_BITS			0x0000080c
-#define BNX2_MISC_ENABLE_STATUS_BITS_TX_SCHEDULER_ENABLE	 (1L<<0)
-#define BNX2_MISC_ENABLE_STATUS_BITS_TX_BD_READ_ENABLE	 (1L<<1)
-#define BNX2_MISC_ENABLE_STATUS_BITS_TX_BD_CACHE_ENABLE	 (1L<<2)
-#define BNX2_MISC_ENABLE_STATUS_BITS_TX_PROCESSOR_ENABLE	 (1L<<3)
-#define BNX2_MISC_ENABLE_STATUS_BITS_TX_DMA_ENABLE	 (1L<<4)
-#define BNX2_MISC_ENABLE_STATUS_BITS_TX_PATCHUP_ENABLE	 (1L<<5)
-#define BNX2_MISC_ENABLE_STATUS_BITS_TX_PAYLOAD_Q_ENABLE	 (1L<<6)
-#define BNX2_MISC_ENABLE_STATUS_BITS_TX_HEADER_Q_ENABLE	 (1L<<7)
-#define BNX2_MISC_ENABLE_STATUS_BITS_TX_ASSEMBLER_ENABLE	 (1L<<8)
-#define BNX2_MISC_ENABLE_STATUS_BITS_EMAC_ENABLE	 (1L<<9)
-#define BNX2_MISC_ENABLE_STATUS_BITS_RX_PARSER_MAC_ENABLE	 (1L<<10)
-#define BNX2_MISC_ENABLE_STATUS_BITS_RX_PARSER_CATCHUP_ENABLE	 (1L<<11)
-#define BNX2_MISC_ENABLE_STATUS_BITS_RX_MBUF_ENABLE	 (1L<<12)
-#define BNX2_MISC_ENABLE_STATUS_BITS_RX_LOOKUP_ENABLE	 (1L<<13)
-#define BNX2_MISC_ENABLE_STATUS_BITS_RX_PROCESSOR_ENABLE	 (1L<<14)
-#define BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE	 (1L<<15)
-#define BNX2_MISC_ENABLE_STATUS_BITS_RX_BD_CACHE_ENABLE	 (1L<<16)
-#define BNX2_MISC_ENABLE_STATUS_BITS_RX_DMA_ENABLE	 (1L<<17)
-#define BNX2_MISC_ENABLE_STATUS_BITS_COMPLETION_ENABLE	 (1L<<18)
-#define BNX2_MISC_ENABLE_STATUS_BITS_HOST_COALESCE_ENABLE	 (1L<<19)
-#define BNX2_MISC_ENABLE_STATUS_BITS_MAILBOX_QUEUE_ENABLE	 (1L<<20)
-#define BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE	 (1L<<21)
-#define BNX2_MISC_ENABLE_STATUS_BITS_CMD_SCHEDULER_ENABLE	 (1L<<22)
-#define BNX2_MISC_ENABLE_STATUS_BITS_CMD_PROCESSOR_ENABLE	 (1L<<23)
-#define BNX2_MISC_ENABLE_STATUS_BITS_MGMT_PROCESSOR_ENABLE	 (1L<<24)
-#define BNX2_MISC_ENABLE_STATUS_BITS_TIMER_ENABLE	 (1L<<25)
-#define BNX2_MISC_ENABLE_STATUS_BITS_DMA_ENGINE_ENABLE	 (1L<<26)
-#define BNX2_MISC_ENABLE_STATUS_BITS_UMP_ENABLE		 (1L<<27)
-#define BNX2_MISC_ENABLE_STATUS_BITS_RV2P_CMD_SCHEDULER_ENABLE	 (1L<<28)
-#define BNX2_MISC_ENABLE_STATUS_BITS_RSVD_FUTURE_ENABLE	 (0x7L<<29)
-
-#define BNX2_MISC_ENABLE_SET_BITS			0x00000810
-#define BNX2_MISC_ENABLE_SET_BITS_TX_SCHEDULER_ENABLE	 (1L<<0)
-#define BNX2_MISC_ENABLE_SET_BITS_TX_BD_READ_ENABLE	 (1L<<1)
-#define BNX2_MISC_ENABLE_SET_BITS_TX_BD_CACHE_ENABLE	 (1L<<2)
-#define BNX2_MISC_ENABLE_SET_BITS_TX_PROCESSOR_ENABLE	 (1L<<3)
-#define BNX2_MISC_ENABLE_SET_BITS_TX_DMA_ENABLE		 (1L<<4)
-#define BNX2_MISC_ENABLE_SET_BITS_TX_PATCHUP_ENABLE	 (1L<<5)
-#define BNX2_MISC_ENABLE_SET_BITS_TX_PAYLOAD_Q_ENABLE	 (1L<<6)
-#define BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE	 (1L<<7)
-#define BNX2_MISC_ENABLE_SET_BITS_TX_ASSEMBLER_ENABLE	 (1L<<8)
-#define BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE		 (1L<<9)
-#define BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE	 (1L<<10)
-#define BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_CATCHUP_ENABLE	 (1L<<11)
-#define BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE	 (1L<<12)
-#define BNX2_MISC_ENABLE_SET_BITS_RX_LOOKUP_ENABLE	 (1L<<13)
-#define BNX2_MISC_ENABLE_SET_BITS_RX_PROCESSOR_ENABLE	 (1L<<14)
-#define BNX2_MISC_ENABLE_SET_BITS_RX_V2P_ENABLE		 (1L<<15)
-#define BNX2_MISC_ENABLE_SET_BITS_RX_BD_CACHE_ENABLE	 (1L<<16)
-#define BNX2_MISC_ENABLE_SET_BITS_RX_DMA_ENABLE		 (1L<<17)
-#define BNX2_MISC_ENABLE_SET_BITS_COMPLETION_ENABLE	 (1L<<18)
-#define BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE	 (1L<<19)
-#define BNX2_MISC_ENABLE_SET_BITS_MAILBOX_QUEUE_ENABLE	 (1L<<20)
-#define BNX2_MISC_ENABLE_SET_BITS_CONTEXT_ENABLE	 (1L<<21)
-#define BNX2_MISC_ENABLE_SET_BITS_CMD_SCHEDULER_ENABLE	 (1L<<22)
-#define BNX2_MISC_ENABLE_SET_BITS_CMD_PROCESSOR_ENABLE	 (1L<<23)
-#define BNX2_MISC_ENABLE_SET_BITS_MGMT_PROCESSOR_ENABLE	 (1L<<24)
-#define BNX2_MISC_ENABLE_SET_BITS_TIMER_ENABLE		 (1L<<25)
-#define BNX2_MISC_ENABLE_SET_BITS_DMA_ENGINE_ENABLE	 (1L<<26)
-#define BNX2_MISC_ENABLE_SET_BITS_UMP_ENABLE		 (1L<<27)
-#define BNX2_MISC_ENABLE_SET_BITS_RV2P_CMD_SCHEDULER_ENABLE	 (1L<<28)
-#define BNX2_MISC_ENABLE_SET_BITS_RSVD_FUTURE_ENABLE	 (0x7L<<29)
-
-#define BNX2_MISC_ENABLE_CLR_BITS			0x00000814
-#define BNX2_MISC_ENABLE_CLR_BITS_TX_SCHEDULER_ENABLE	 (1L<<0)
-#define BNX2_MISC_ENABLE_CLR_BITS_TX_BD_READ_ENABLE	 (1L<<1)
-#define BNX2_MISC_ENABLE_CLR_BITS_TX_BD_CACHE_ENABLE	 (1L<<2)
-#define BNX2_MISC_ENABLE_CLR_BITS_TX_PROCESSOR_ENABLE	 (1L<<3)
-#define BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE		 (1L<<4)
-#define BNX2_MISC_ENABLE_CLR_BITS_TX_PATCHUP_ENABLE	 (1L<<5)
-#define BNX2_MISC_ENABLE_CLR_BITS_TX_PAYLOAD_Q_ENABLE	 (1L<<6)
-#define BNX2_MISC_ENABLE_CLR_BITS_TX_HEADER_Q_ENABLE	 (1L<<7)
-#define BNX2_MISC_ENABLE_CLR_BITS_TX_ASSEMBLER_ENABLE	 (1L<<8)
-#define BNX2_MISC_ENABLE_CLR_BITS_EMAC_ENABLE		 (1L<<9)
-#define BNX2_MISC_ENABLE_CLR_BITS_RX_PARSER_MAC_ENABLE	 (1L<<10)
-#define BNX2_MISC_ENABLE_CLR_BITS_RX_PARSER_CATCHUP_ENABLE	 (1L<<11)
-#define BNX2_MISC_ENABLE_CLR_BITS_RX_MBUF_ENABLE	 (1L<<12)
-#define BNX2_MISC_ENABLE_CLR_BITS_RX_LOOKUP_ENABLE	 (1L<<13)
-#define BNX2_MISC_ENABLE_CLR_BITS_RX_PROCESSOR_ENABLE	 (1L<<14)
-#define BNX2_MISC_ENABLE_CLR_BITS_RX_V2P_ENABLE		 (1L<<15)
-#define BNX2_MISC_ENABLE_CLR_BITS_RX_BD_CACHE_ENABLE	 (1L<<16)
-#define BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE		 (1L<<17)
-#define BNX2_MISC_ENABLE_CLR_BITS_COMPLETION_ENABLE	 (1L<<18)
-#define BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE	 (1L<<19)
-#define BNX2_MISC_ENABLE_CLR_BITS_MAILBOX_QUEUE_ENABLE	 (1L<<20)
-#define BNX2_MISC_ENABLE_CLR_BITS_CONTEXT_ENABLE	 (1L<<21)
-#define BNX2_MISC_ENABLE_CLR_BITS_CMD_SCHEDULER_ENABLE	 (1L<<22)
-#define BNX2_MISC_ENABLE_CLR_BITS_CMD_PROCESSOR_ENABLE	 (1L<<23)
-#define BNX2_MISC_ENABLE_CLR_BITS_MGMT_PROCESSOR_ENABLE	 (1L<<24)
-#define BNX2_MISC_ENABLE_CLR_BITS_TIMER_ENABLE		 (1L<<25)
-#define BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE	 (1L<<26)
-#define BNX2_MISC_ENABLE_CLR_BITS_UMP_ENABLE		 (1L<<27)
-#define BNX2_MISC_ENABLE_CLR_BITS_RV2P_CMD_SCHEDULER_ENABLE	 (1L<<28)
-#define BNX2_MISC_ENABLE_CLR_BITS_RSVD_FUTURE_ENABLE	 (0x7L<<29)
-
-#define BNX2_MISC_CLOCK_CONTROL_BITS			0x00000818
-#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET	 (0xfL<<0)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ	 (0L<<0)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ	 (1L<<0)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ	 (2L<<0)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ	 (3L<<0)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ	 (4L<<0)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ	 (5L<<0)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ	 (6L<<0)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ	 (7L<<0)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW	 (0xfL<<0)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_DISABLE	 (1L<<6)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT	 (1L<<7)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC	 (0x7L<<8)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_UNDEF	 (0L<<8)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12	 (1L<<8)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6	 (2L<<8)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62	 (4L<<8)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED0_XI	 (0x7L<<8)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_MIN_POWER		 (1L<<11)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED	 (0xfL<<12)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100	 (0L<<12)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80	 (1L<<12)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_50	 (2L<<12)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40	 (4L<<12)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25	 (8L<<12)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED1_XI	 (0xfL<<12)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP	 (1L<<16)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_17_TE	 (1L<<17)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_18_TE	 (1L<<18)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_19_TE	 (1L<<19)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_TE	 (0xfffL<<20)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_MGMT_XI	 (1L<<17)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED2_XI	 (0x3fL<<18)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_VCO_XI	 (0x7L<<24)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED3_XI	 (1L<<27)
-#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_XI	 (0xfL<<28)
-
-#define BNX2_MISC_SPIO					0x0000081c
-#define BNX2_MISC_SPIO_VALUE				 (0xffL<<0)
-#define BNX2_MISC_SPIO_SET				 (0xffL<<8)
-#define BNX2_MISC_SPIO_CLR				 (0xffL<<16)
-#define BNX2_MISC_SPIO_FLOAT				 (0xffL<<24)
-
-#define BNX2_MISC_SPIO_INT				0x00000820
-#define BNX2_MISC_SPIO_INT_INT_STATE_TE			 (0xfL<<0)
-#define BNX2_MISC_SPIO_INT_OLD_VALUE_TE			 (0xfL<<8)
-#define BNX2_MISC_SPIO_INT_OLD_SET_TE			 (0xfL<<16)
-#define BNX2_MISC_SPIO_INT_OLD_CLR_TE			 (0xfL<<24)
-#define BNX2_MISC_SPIO_INT_INT_STATE_XI			 (0xffL<<0)
-#define BNX2_MISC_SPIO_INT_OLD_VALUE_XI			 (0xffL<<8)
-#define BNX2_MISC_SPIO_INT_OLD_SET_XI			 (0xffL<<16)
-#define BNX2_MISC_SPIO_INT_OLD_CLR_XI			 (0xffL<<24)
-
-#define BNX2_MISC_CONFIG_LFSR				0x00000824
-#define BNX2_MISC_CONFIG_LFSR_DIV			 (0xffffL<<0)
-
-#define BNX2_MISC_LFSR_MASK_BITS			0x00000828
-#define BNX2_MISC_LFSR_MASK_BITS_TX_SCHEDULER_ENABLE	 (1L<<0)
-#define BNX2_MISC_LFSR_MASK_BITS_TX_BD_READ_ENABLE	 (1L<<1)
-#define BNX2_MISC_LFSR_MASK_BITS_TX_BD_CACHE_ENABLE	 (1L<<2)
-#define BNX2_MISC_LFSR_MASK_BITS_TX_PROCESSOR_ENABLE	 (1L<<3)
-#define BNX2_MISC_LFSR_MASK_BITS_TX_DMA_ENABLE		 (1L<<4)
-#define BNX2_MISC_LFSR_MASK_BITS_TX_PATCHUP_ENABLE	 (1L<<5)
-#define BNX2_MISC_LFSR_MASK_BITS_TX_PAYLOAD_Q_ENABLE	 (1L<<6)
-#define BNX2_MISC_LFSR_MASK_BITS_TX_HEADER_Q_ENABLE	 (1L<<7)
-#define BNX2_MISC_LFSR_MASK_BITS_TX_ASSEMBLER_ENABLE	 (1L<<8)
-#define BNX2_MISC_LFSR_MASK_BITS_EMAC_ENABLE		 (1L<<9)
-#define BNX2_MISC_LFSR_MASK_BITS_RX_PARSER_MAC_ENABLE	 (1L<<10)
-#define BNX2_MISC_LFSR_MASK_BITS_RX_PARSER_CATCHUP_ENABLE	 (1L<<11)
-#define BNX2_MISC_LFSR_MASK_BITS_RX_MBUF_ENABLE		 (1L<<12)
-#define BNX2_MISC_LFSR_MASK_BITS_RX_LOOKUP_ENABLE	 (1L<<13)
-#define BNX2_MISC_LFSR_MASK_BITS_RX_PROCESSOR_ENABLE	 (1L<<14)
-#define BNX2_MISC_LFSR_MASK_BITS_RX_V2P_ENABLE		 (1L<<15)
-#define BNX2_MISC_LFSR_MASK_BITS_RX_BD_CACHE_ENABLE	 (1L<<16)
-#define BNX2_MISC_LFSR_MASK_BITS_RX_DMA_ENABLE		 (1L<<17)
-#define BNX2_MISC_LFSR_MASK_BITS_COMPLETION_ENABLE	 (1L<<18)
-#define BNX2_MISC_LFSR_MASK_BITS_HOST_COALESCE_ENABLE	 (1L<<19)
-#define BNX2_MISC_LFSR_MASK_BITS_MAILBOX_QUEUE_ENABLE	 (1L<<20)
-#define BNX2_MISC_LFSR_MASK_BITS_CONTEXT_ENABLE		 (1L<<21)
-#define BNX2_MISC_LFSR_MASK_BITS_CMD_SCHEDULER_ENABLE	 (1L<<22)
-#define BNX2_MISC_LFSR_MASK_BITS_CMD_PROCESSOR_ENABLE	 (1L<<23)
-#define BNX2_MISC_LFSR_MASK_BITS_MGMT_PROCESSOR_ENABLE	 (1L<<24)
-#define BNX2_MISC_LFSR_MASK_BITS_TIMER_ENABLE		 (1L<<25)
-#define BNX2_MISC_LFSR_MASK_BITS_DMA_ENGINE_ENABLE	 (1L<<26)
-#define BNX2_MISC_LFSR_MASK_BITS_UMP_ENABLE		 (1L<<27)
-#define BNX2_MISC_LFSR_MASK_BITS_RV2P_CMD_SCHEDULER_ENABLE	 (1L<<28)
-#define BNX2_MISC_LFSR_MASK_BITS_RSVD_FUTURE_ENABLE	 (0x7L<<29)
-
-#define BNX2_MISC_ARB_REQ0				0x0000082c
-#define BNX2_MISC_ARB_REQ1				0x00000830
-#define BNX2_MISC_ARB_REQ2				0x00000834
-#define BNX2_MISC_ARB_REQ3				0x00000838
-#define BNX2_MISC_ARB_REQ4				0x0000083c
-#define BNX2_MISC_ARB_FREE0				0x00000840
-#define BNX2_MISC_ARB_FREE1				0x00000844
-#define BNX2_MISC_ARB_FREE2				0x00000848
-#define BNX2_MISC_ARB_FREE3				0x0000084c
-#define BNX2_MISC_ARB_FREE4				0x00000850
-#define BNX2_MISC_ARB_REQ_STATUS0			0x00000854
-#define BNX2_MISC_ARB_REQ_STATUS1			0x00000858
-#define BNX2_MISC_ARB_REQ_STATUS2			0x0000085c
-#define BNX2_MISC_ARB_REQ_STATUS3			0x00000860
-#define BNX2_MISC_ARB_REQ_STATUS4			0x00000864
-#define BNX2_MISC_ARB_GNT0				0x00000868
-#define BNX2_MISC_ARB_GNT0_0				 (0x7L<<0)
-#define BNX2_MISC_ARB_GNT0_1				 (0x7L<<4)
-#define BNX2_MISC_ARB_GNT0_2				 (0x7L<<8)
-#define BNX2_MISC_ARB_GNT0_3				 (0x7L<<12)
-#define BNX2_MISC_ARB_GNT0_4				 (0x7L<<16)
-#define BNX2_MISC_ARB_GNT0_5				 (0x7L<<20)
-#define BNX2_MISC_ARB_GNT0_6				 (0x7L<<24)
-#define BNX2_MISC_ARB_GNT0_7				 (0x7L<<28)
-
-#define BNX2_MISC_ARB_GNT1				0x0000086c
-#define BNX2_MISC_ARB_GNT1_8				 (0x7L<<0)
-#define BNX2_MISC_ARB_GNT1_9				 (0x7L<<4)
-#define BNX2_MISC_ARB_GNT1_10				 (0x7L<<8)
-#define BNX2_MISC_ARB_GNT1_11				 (0x7L<<12)
-#define BNX2_MISC_ARB_GNT1_12				 (0x7L<<16)
-#define BNX2_MISC_ARB_GNT1_13				 (0x7L<<20)
-#define BNX2_MISC_ARB_GNT1_14				 (0x7L<<24)
-#define BNX2_MISC_ARB_GNT1_15				 (0x7L<<28)
-
-#define BNX2_MISC_ARB_GNT2				0x00000870
-#define BNX2_MISC_ARB_GNT2_16				 (0x7L<<0)
-#define BNX2_MISC_ARB_GNT2_17				 (0x7L<<4)
-#define BNX2_MISC_ARB_GNT2_18				 (0x7L<<8)
-#define BNX2_MISC_ARB_GNT2_19				 (0x7L<<12)
-#define BNX2_MISC_ARB_GNT2_20				 (0x7L<<16)
-#define BNX2_MISC_ARB_GNT2_21				 (0x7L<<20)
-#define BNX2_MISC_ARB_GNT2_22				 (0x7L<<24)
-#define BNX2_MISC_ARB_GNT2_23				 (0x7L<<28)
-
-#define BNX2_MISC_ARB_GNT3				0x00000874
-#define BNX2_MISC_ARB_GNT3_24				 (0x7L<<0)
-#define BNX2_MISC_ARB_GNT3_25				 (0x7L<<4)
-#define BNX2_MISC_ARB_GNT3_26				 (0x7L<<8)
-#define BNX2_MISC_ARB_GNT3_27				 (0x7L<<12)
-#define BNX2_MISC_ARB_GNT3_28				 (0x7L<<16)
-#define BNX2_MISC_ARB_GNT3_29				 (0x7L<<20)
-#define BNX2_MISC_ARB_GNT3_30				 (0x7L<<24)
-#define BNX2_MISC_ARB_GNT3_31				 (0x7L<<28)
-
-#define BNX2_MISC_RESERVED1				0x00000878
-#define BNX2_MISC_RESERVED1_MISC_RESERVED1_VALUE	 (0x3fL<<0)
-
-#define BNX2_MISC_RESERVED2				0x0000087c
-#define BNX2_MISC_RESERVED2_PCIE_DIS			 (1L<<0)
-#define BNX2_MISC_RESERVED2_LINK_IN_L23			 (1L<<1)
-
-#define BNX2_MISC_SM_ASF_CONTROL			0x00000880
-#define BNX2_MISC_SM_ASF_CONTROL_ASF_RST		 (1L<<0)
-#define BNX2_MISC_SM_ASF_CONTROL_TSC_EN			 (1L<<1)
-#define BNX2_MISC_SM_ASF_CONTROL_WG_TO			 (1L<<2)
-#define BNX2_MISC_SM_ASF_CONTROL_HB_TO			 (1L<<3)
-#define BNX2_MISC_SM_ASF_CONTROL_PA_TO			 (1L<<4)
-#define BNX2_MISC_SM_ASF_CONTROL_PL_TO			 (1L<<5)
-#define BNX2_MISC_SM_ASF_CONTROL_RT_TO			 (1L<<6)
-#define BNX2_MISC_SM_ASF_CONTROL_SMB_EVENT		 (1L<<7)
-#define BNX2_MISC_SM_ASF_CONTROL_STRETCH_EN		 (1L<<8)
-#define BNX2_MISC_SM_ASF_CONTROL_STRETCH_PULSE		 (1L<<9)
-#define BNX2_MISC_SM_ASF_CONTROL_RES			 (0x3L<<10)
-#define BNX2_MISC_SM_ASF_CONTROL_SMB_EN			 (1L<<12)
-#define BNX2_MISC_SM_ASF_CONTROL_SMB_BB_EN		 (1L<<13)
-#define BNX2_MISC_SM_ASF_CONTROL_SMB_NO_ADDR_FILT	 (1L<<14)
-#define BNX2_MISC_SM_ASF_CONTROL_SMB_AUTOREAD		 (1L<<15)
-#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR1		 (0x7fL<<16)
-#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR2		 (0x7fL<<23)
-#define BNX2_MISC_SM_ASF_CONTROL_EN_NIC_SMB_ADDR_0	 (1L<<30)
-#define BNX2_MISC_SM_ASF_CONTROL_SMB_EARLY_ATTN		 (1L<<31)
-
-#define BNX2_MISC_SMB_IN				0x00000884
-#define BNX2_MISC_SMB_IN_DAT_IN				 (0xffL<<0)
-#define BNX2_MISC_SMB_IN_RDY				 (1L<<8)
-#define BNX2_MISC_SMB_IN_DONE				 (1L<<9)
-#define BNX2_MISC_SMB_IN_FIRSTBYTE			 (1L<<10)
-#define BNX2_MISC_SMB_IN_STATUS				 (0x7L<<11)
-#define BNX2_MISC_SMB_IN_STATUS_OK			 (0x0L<<11)
-#define BNX2_MISC_SMB_IN_STATUS_PEC			 (0x1L<<11)
-#define BNX2_MISC_SMB_IN_STATUS_OFLOW			 (0x2L<<11)
-#define BNX2_MISC_SMB_IN_STATUS_STOP			 (0x3L<<11)
-#define BNX2_MISC_SMB_IN_STATUS_TIMEOUT			 (0x4L<<11)
-
-#define BNX2_MISC_SMB_OUT				0x00000888
-#define BNX2_MISC_SMB_OUT_DAT_OUT			 (0xffL<<0)
-#define BNX2_MISC_SMB_OUT_RDY				 (1L<<8)
-#define BNX2_MISC_SMB_OUT_START				 (1L<<9)
-#define BNX2_MISC_SMB_OUT_LAST				 (1L<<10)
-#define BNX2_MISC_SMB_OUT_ACC_TYPE			 (1L<<11)
-#define BNX2_MISC_SMB_OUT_ENB_PEC			 (1L<<12)
-#define BNX2_MISC_SMB_OUT_GET_RX_LEN			 (1L<<13)
-#define BNX2_MISC_SMB_OUT_SMB_READ_LEN			 (0x3fL<<14)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS		 (0xfL<<20)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_OK		 (0L<<20)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_NACK	 (1L<<20)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_UFLOW		 (2L<<20)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_STOP		 (3L<<20)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_TIMEOUT	 (4L<<20)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_LOST	 (5L<<20)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_BADACK		 (6L<<20)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_NACK	 (9L<<20)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_LOST	 (0xdL<<20)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_SLAVEMODE		 (1L<<24)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_EN		 (1L<<25)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_IN		 (1L<<26)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_CLK_EN		 (1L<<27)
-#define BNX2_MISC_SMB_OUT_SMB_OUT_CLK_IN		 (1L<<28)
-
-#define BNX2_MISC_SMB_WATCHDOG				0x0000088c
-#define BNX2_MISC_SMB_WATCHDOG_WATCHDOG			 (0xffffL<<0)
-
-#define BNX2_MISC_SMB_HEARTBEAT				0x00000890
-#define BNX2_MISC_SMB_HEARTBEAT_HEARTBEAT		 (0xffffL<<0)
-
-#define BNX2_MISC_SMB_POLL_ASF				0x00000894
-#define BNX2_MISC_SMB_POLL_ASF_POLL_ASF			 (0xffffL<<0)
-
-#define BNX2_MISC_SMB_POLL_LEGACY			0x00000898
-#define BNX2_MISC_SMB_POLL_LEGACY_POLL_LEGACY		 (0xffffL<<0)
-
-#define BNX2_MISC_SMB_RETRAN				0x0000089c
-#define BNX2_MISC_SMB_RETRAN_RETRAN			 (0xffL<<0)
-
-#define BNX2_MISC_SMB_TIMESTAMP				0x000008a0
-#define BNX2_MISC_SMB_TIMESTAMP_TIMESTAMP		 (0xffffffffL<<0)
-
-#define BNX2_MISC_PERR_ENA0				0x000008a4
-#define BNX2_MISC_PERR_ENA0_COM_MISC_CTXC		 (1L<<0)
-#define BNX2_MISC_PERR_ENA0_COM_MISC_REGF		 (1L<<1)
-#define BNX2_MISC_PERR_ENA0_COM_MISC_SCPAD		 (1L<<2)
-#define BNX2_MISC_PERR_ENA0_CP_MISC_CTXC		 (1L<<3)
-#define BNX2_MISC_PERR_ENA0_CP_MISC_REGF		 (1L<<4)
-#define BNX2_MISC_PERR_ENA0_CP_MISC_SCPAD		 (1L<<5)
-#define BNX2_MISC_PERR_ENA0_CS_MISC_TMEM		 (1L<<6)
-#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM0		 (1L<<7)
-#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM1		 (1L<<8)
-#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM2		 (1L<<9)
-#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM3		 (1L<<10)
-#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM4		 (1L<<11)
-#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM5		 (1L<<12)
-#define BNX2_MISC_PERR_ENA0_CTX_MISC_PGTBL		 (1L<<13)
-#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR0		 (1L<<14)
-#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR1		 (1L<<15)
-#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR2		 (1L<<16)
-#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR3		 (1L<<17)
-#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR4		 (1L<<18)
-#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW0		 (1L<<19)
-#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW1		 (1L<<20)
-#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW2		 (1L<<21)
-#define BNX2_MISC_PERR_ENA0_HC_MISC_DMA			 (1L<<22)
-#define BNX2_MISC_PERR_ENA0_MCP_MISC_REGF		 (1L<<23)
-#define BNX2_MISC_PERR_ENA0_MCP_MISC_SCPAD		 (1L<<24)
-#define BNX2_MISC_PERR_ENA0_MQ_MISC_CTX			 (1L<<25)
-#define BNX2_MISC_PERR_ENA0_RBDC_MISC			 (1L<<26)
-#define BNX2_MISC_PERR_ENA0_RBUF_MISC_MB		 (1L<<27)
-#define BNX2_MISC_PERR_ENA0_RBUF_MISC_PTR		 (1L<<28)
-#define BNX2_MISC_PERR_ENA0_RDE_MISC_RPC		 (1L<<29)
-#define BNX2_MISC_PERR_ENA0_RDE_MISC_RPM		 (1L<<30)
-#define BNX2_MISC_PERR_ENA0_RV2P_MISC_CB0REGS		 (1L<<31)
-#define BNX2_MISC_PERR_ENA0_COM_DMAE_PERR_EN_XI		 (1L<<0)
-#define BNX2_MISC_PERR_ENA0_CP_DMAE_PERR_EN_XI		 (1L<<1)
-#define BNX2_MISC_PERR_ENA0_RPM_ACPIBEMEM_PERR_EN_XI	 (1L<<2)
-#define BNX2_MISC_PERR_ENA0_CTX_USAGE_CNT_PERR_EN_XI	 (1L<<3)
-#define BNX2_MISC_PERR_ENA0_CTX_PGTBL_PERR_EN_XI	 (1L<<4)
-#define BNX2_MISC_PERR_ENA0_CTX_CACHE_PERR_EN_XI	 (1L<<5)
-#define BNX2_MISC_PERR_ENA0_CTX_MIRROR_PERR_EN_XI	 (1L<<6)
-#define BNX2_MISC_PERR_ENA0_COM_CTXC_PERR_EN_XI		 (1L<<7)
-#define BNX2_MISC_PERR_ENA0_COM_SCPAD_PERR_EN_XI	 (1L<<8)
-#define BNX2_MISC_PERR_ENA0_CP_CTXC_PERR_EN_XI		 (1L<<9)
-#define BNX2_MISC_PERR_ENA0_CP_SCPAD_PERR_EN_XI		 (1L<<10)
-#define BNX2_MISC_PERR_ENA0_RXP_RBUFC_PERR_EN_XI	 (1L<<11)
-#define BNX2_MISC_PERR_ENA0_RXP_CTXC_PERR_EN_XI		 (1L<<12)
-#define BNX2_MISC_PERR_ENA0_RXP_SCPAD_PERR_EN_XI	 (1L<<13)
-#define BNX2_MISC_PERR_ENA0_TPAT_SCPAD_PERR_EN_XI	 (1L<<14)
-#define BNX2_MISC_PERR_ENA0_TXP_CTXC_PERR_EN_XI		 (1L<<15)
-#define BNX2_MISC_PERR_ENA0_TXP_SCPAD_PERR_EN_XI	 (1L<<16)
-#define BNX2_MISC_PERR_ENA0_CS_TMEM_PERR_EN_XI		 (1L<<17)
-#define BNX2_MISC_PERR_ENA0_MQ_CTX_PERR_EN_XI		 (1L<<18)
-#define BNX2_MISC_PERR_ENA0_RPM_DFIFOMEM_PERR_EN_XI	 (1L<<19)
-#define BNX2_MISC_PERR_ENA0_RPC_DFIFOMEM_PERR_EN_XI	 (1L<<20)
-#define BNX2_MISC_PERR_ENA0_RBUF_PTRMEM_PERR_EN_XI	 (1L<<21)
-#define BNX2_MISC_PERR_ENA0_RBUF_DATAMEM_PERR_EN_XI	 (1L<<22)
-#define BNX2_MISC_PERR_ENA0_RV2P_P2IRAM_PERR_EN_XI	 (1L<<23)
-#define BNX2_MISC_PERR_ENA0_RV2P_P1IRAM_PERR_EN_XI	 (1L<<24)
-#define BNX2_MISC_PERR_ENA0_RV2P_CB1REGS_PERR_EN_XI	 (1L<<25)
-#define BNX2_MISC_PERR_ENA0_RV2P_CB0REGS_PERR_EN_XI	 (1L<<26)
-#define BNX2_MISC_PERR_ENA0_TPBUF_PERR_EN_XI		 (1L<<27)
-#define BNX2_MISC_PERR_ENA0_THBUF_PERR_EN_XI		 (1L<<28)
-#define BNX2_MISC_PERR_ENA0_TDMA_PERR_EN_XI		 (1L<<29)
-#define BNX2_MISC_PERR_ENA0_TBDC_PERR_EN_XI		 (1L<<30)
-#define BNX2_MISC_PERR_ENA0_TSCH_LR_PERR_EN_XI		 (1L<<31)
-
-#define BNX2_MISC_PERR_ENA1				0x000008a8
-#define BNX2_MISC_PERR_ENA1_RV2P_MISC_CB1REGS		 (1L<<0)
-#define BNX2_MISC_PERR_ENA1_RV2P_MISC_P1IRAM		 (1L<<1)
-#define BNX2_MISC_PERR_ENA1_RV2P_MISC_P2IRAM		 (1L<<2)
-#define BNX2_MISC_PERR_ENA1_RXP_MISC_CTXC		 (1L<<3)
-#define BNX2_MISC_PERR_ENA1_RXP_MISC_REGF		 (1L<<4)
-#define BNX2_MISC_PERR_ENA1_RXP_MISC_SCPAD		 (1L<<5)
-#define BNX2_MISC_PERR_ENA1_RXP_MISC_RBUFC		 (1L<<6)
-#define BNX2_MISC_PERR_ENA1_TBDC_MISC			 (1L<<7)
-#define BNX2_MISC_PERR_ENA1_TDMA_MISC			 (1L<<8)
-#define BNX2_MISC_PERR_ENA1_THBUF_MISC_MB0		 (1L<<9)
-#define BNX2_MISC_PERR_ENA1_THBUF_MISC_MB1		 (1L<<10)
-#define BNX2_MISC_PERR_ENA1_TPAT_MISC_REGF		 (1L<<11)
-#define BNX2_MISC_PERR_ENA1_TPAT_MISC_SCPAD		 (1L<<12)
-#define BNX2_MISC_PERR_ENA1_TPBUF_MISC_MB		 (1L<<13)
-#define BNX2_MISC_PERR_ENA1_TSCH_MISC_LR		 (1L<<14)
-#define BNX2_MISC_PERR_ENA1_TXP_MISC_CTXC		 (1L<<15)
-#define BNX2_MISC_PERR_ENA1_TXP_MISC_REGF		 (1L<<16)
-#define BNX2_MISC_PERR_ENA1_TXP_MISC_SCPAD		 (1L<<17)
-#define BNX2_MISC_PERR_ENA1_UMP_MISC_FIORX		 (1L<<18)
-#define BNX2_MISC_PERR_ENA1_UMP_MISC_FIOTX		 (1L<<19)
-#define BNX2_MISC_PERR_ENA1_UMP_MISC_RX			 (1L<<20)
-#define BNX2_MISC_PERR_ENA1_UMP_MISC_TX			 (1L<<21)
-#define BNX2_MISC_PERR_ENA1_RDMAQ_MISC			 (1L<<22)
-#define BNX2_MISC_PERR_ENA1_CSQ_MISC			 (1L<<23)
-#define BNX2_MISC_PERR_ENA1_CPQ_MISC			 (1L<<24)
-#define BNX2_MISC_PERR_ENA1_MCPQ_MISC			 (1L<<25)
-#define BNX2_MISC_PERR_ENA1_RV2PMQ_MISC			 (1L<<26)
-#define BNX2_MISC_PERR_ENA1_RV2PPQ_MISC			 (1L<<27)
-#define BNX2_MISC_PERR_ENA1_RV2PTQ_MISC			 (1L<<28)
-#define BNX2_MISC_PERR_ENA1_RXPQ_MISC			 (1L<<29)
-#define BNX2_MISC_PERR_ENA1_RXPCQ_MISC			 (1L<<30)
-#define BNX2_MISC_PERR_ENA1_RLUPQ_MISC			 (1L<<31)
-#define BNX2_MISC_PERR_ENA1_RBDC_PERR_EN_XI		 (1L<<0)
-#define BNX2_MISC_PERR_ENA1_RDMA_DFIFO_PERR_EN_XI	 (1L<<2)
-#define BNX2_MISC_PERR_ENA1_HC_STATS_PERR_EN_XI		 (1L<<3)
-#define BNX2_MISC_PERR_ENA1_HC_MSIX_PERR_EN_XI		 (1L<<4)
-#define BNX2_MISC_PERR_ENA1_HC_PRODUCSTB_PERR_EN_XI	 (1L<<5)
-#define BNX2_MISC_PERR_ENA1_HC_CONSUMSTB_PERR_EN_XI	 (1L<<6)
-#define BNX2_MISC_PERR_ENA1_TPATQ_PERR_EN_XI		 (1L<<7)
-#define BNX2_MISC_PERR_ENA1_MCPQ_PERR_EN_XI		 (1L<<8)
-#define BNX2_MISC_PERR_ENA1_TDMAQ_PERR_EN_XI		 (1L<<9)
-#define BNX2_MISC_PERR_ENA1_TXPQ_PERR_EN_XI		 (1L<<10)
-#define BNX2_MISC_PERR_ENA1_COMTQ_PERR_EN_XI		 (1L<<11)
-#define BNX2_MISC_PERR_ENA1_COMQ_PERR_EN_XI		 (1L<<12)
-#define BNX2_MISC_PERR_ENA1_RLUPQ_PERR_EN_XI		 (1L<<13)
-#define BNX2_MISC_PERR_ENA1_RXPQ_PERR_EN_XI		 (1L<<14)
-#define BNX2_MISC_PERR_ENA1_RV2PPQ_PERR_EN_XI		 (1L<<15)
-#define BNX2_MISC_PERR_ENA1_RDMAQ_PERR_EN_XI		 (1L<<16)
-#define BNX2_MISC_PERR_ENA1_TASQ_PERR_EN_XI		 (1L<<17)
-#define BNX2_MISC_PERR_ENA1_TBDRQ_PERR_EN_XI		 (1L<<18)
-#define BNX2_MISC_PERR_ENA1_TSCHQ_PERR_EN_XI		 (1L<<19)
-#define BNX2_MISC_PERR_ENA1_COMXQ_PERR_EN_XI		 (1L<<20)
-#define BNX2_MISC_PERR_ENA1_RXPCQ_PERR_EN_XI		 (1L<<21)
-#define BNX2_MISC_PERR_ENA1_RV2PTQ_PERR_EN_XI		 (1L<<22)
-#define BNX2_MISC_PERR_ENA1_RV2PMQ_PERR_EN_XI		 (1L<<23)
-#define BNX2_MISC_PERR_ENA1_CPQ_PERR_EN_XI		 (1L<<24)
-#define BNX2_MISC_PERR_ENA1_CSQ_PERR_EN_XI		 (1L<<25)
-#define BNX2_MISC_PERR_ENA1_RLUP_CID_PERR_EN_XI		 (1L<<26)
-#define BNX2_MISC_PERR_ENA1_RV2PCS_TMEM_PERR_EN_XI	 (1L<<27)
-#define BNX2_MISC_PERR_ENA1_RV2PCSQ_PERR_EN_XI		 (1L<<28)
-#define BNX2_MISC_PERR_ENA1_MQ_IDX_PERR_EN_XI		 (1L<<29)
-
-#define BNX2_MISC_PERR_ENA2				0x000008ac
-#define BNX2_MISC_PERR_ENA2_COMQ_MISC			 (1L<<0)
-#define BNX2_MISC_PERR_ENA2_COMXQ_MISC			 (1L<<1)
-#define BNX2_MISC_PERR_ENA2_COMTQ_MISC			 (1L<<2)
-#define BNX2_MISC_PERR_ENA2_TSCHQ_MISC			 (1L<<3)
-#define BNX2_MISC_PERR_ENA2_TBDRQ_MISC			 (1L<<4)
-#define BNX2_MISC_PERR_ENA2_TXPQ_MISC			 (1L<<5)
-#define BNX2_MISC_PERR_ENA2_TDMAQ_MISC			 (1L<<6)
-#define BNX2_MISC_PERR_ENA2_TPATQ_MISC			 (1L<<7)
-#define BNX2_MISC_PERR_ENA2_TASQ_MISC			 (1L<<8)
-#define BNX2_MISC_PERR_ENA2_TGT_FIFO_PERR_EN_XI		 (1L<<0)
-#define BNX2_MISC_PERR_ENA2_UMP_TX_PERR_EN_XI		 (1L<<1)
-#define BNX2_MISC_PERR_ENA2_UMP_RX_PERR_EN_XI		 (1L<<2)
-#define BNX2_MISC_PERR_ENA2_MCP_ROM_PERR_EN_XI		 (1L<<3)
-#define BNX2_MISC_PERR_ENA2_MCP_SCPAD_PERR_EN_XI	 (1L<<4)
-#define BNX2_MISC_PERR_ENA2_HB_MEM_PERR_EN_XI		 (1L<<5)
-#define BNX2_MISC_PERR_ENA2_PCIE_REPLAY_PERR_EN_XI	 (1L<<6)
-
-#define BNX2_MISC_DEBUG_VECTOR_SEL			0x000008b0
-#define BNX2_MISC_DEBUG_VECTOR_SEL_0			 (0xfffL<<0)
-#define BNX2_MISC_DEBUG_VECTOR_SEL_1			 (0xfffL<<12)
-#define BNX2_MISC_DEBUG_VECTOR_SEL_1_XI			 (0xfffL<<15)
-
-#define BNX2_MISC_VREG_CONTROL				0x000008b4
-#define BNX2_MISC_VREG_CONTROL_1_2			 (0xfL<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_XI		 (0xfL<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS14_XI	 (0L<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS12_XI	 (1L<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS10_XI	 (2L<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS8_XI	 (3L<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS6_XI	 (4L<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS4_XI	 (5L<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS2_XI	 (6L<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_NOM_XI		 (7L<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS2_XI	 (8L<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS4_XI	 (9L<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS6_XI	 (10L<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS8_XI	 (11L<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS10_XI	 (12L<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS12_XI	 (13L<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS14_XI	 (14L<<0)
-#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS16_XI	 (15L<<0)
-#define BNX2_MISC_VREG_CONTROL_2_5			 (0xfL<<4)
-#define BNX2_MISC_VREG_CONTROL_2_5_PLUS14		 (0L<<4)
-#define BNX2_MISC_VREG_CONTROL_2_5_PLUS12		 (1L<<4)
-#define BNX2_MISC_VREG_CONTROL_2_5_PLUS10		 (2L<<4)
-#define BNX2_MISC_VREG_CONTROL_2_5_PLUS8		 (3L<<4)
-#define BNX2_MISC_VREG_CONTROL_2_5_PLUS6		 (4L<<4)
-#define BNX2_MISC_VREG_CONTROL_2_5_PLUS4		 (5L<<4)
-#define BNX2_MISC_VREG_CONTROL_2_5_PLUS2		 (6L<<4)
-#define BNX2_MISC_VREG_CONTROL_2_5_NOM			 (7L<<4)
-#define BNX2_MISC_VREG_CONTROL_2_5_MINUS2		 (8L<<4)
-#define BNX2_MISC_VREG_CONTROL_2_5_MINUS4		 (9L<<4)
-#define BNX2_MISC_VREG_CONTROL_2_5_MINUS6		 (10L<<4)
-#define BNX2_MISC_VREG_CONTROL_2_5_MINUS8		 (11L<<4)
-#define BNX2_MISC_VREG_CONTROL_2_5_MINUS10		 (12L<<4)
-#define BNX2_MISC_VREG_CONTROL_2_5_MINUS12		 (13L<<4)
-#define BNX2_MISC_VREG_CONTROL_2_5_MINUS14		 (14L<<4)
-#define BNX2_MISC_VREG_CONTROL_2_5_MINUS16		 (15L<<4)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT			 (0xfL<<8)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS14		 (0L<<8)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS12		 (1L<<8)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS10		 (2L<<8)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS8		 (3L<<8)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS6		 (4L<<8)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS4		 (5L<<8)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS2		 (6L<<8)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_NOM		 (7L<<8)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS2		 (8L<<8)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS4		 (9L<<8)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS6		 (10L<<8)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS8		 (11L<<8)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS10		 (12L<<8)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS12		 (13L<<8)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS14		 (14L<<8)
-#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS16		 (15L<<8)
-
-#define BNX2_MISC_FINAL_CLK_CTL_VAL			0x000008b8
-#define BNX2_MISC_FINAL_CLK_CTL_VAL_MISC_FINAL_CLK_CTL_VAL	 (0x3ffffffL<<6)
-
-#define BNX2_MISC_GP_HW_CTL0				0x000008bc
-#define BNX2_MISC_GP_HW_CTL0_TX_DRIVE			 (1L<<0)
-#define BNX2_MISC_GP_HW_CTL0_RMII_MODE			 (1L<<1)
-#define BNX2_MISC_GP_HW_CTL0_RMII_CRSDV_SEL		 (1L<<2)
-#define BNX2_MISC_GP_HW_CTL0_RVMII_MODE			 (1L<<3)
-#define BNX2_MISC_GP_HW_CTL0_FLASH_SAMP_SCLK_NEGEDGE_TE	 (1L<<4)
-#define BNX2_MISC_GP_HW_CTL0_HIDDEN_REVISION_ID_TE	 (1L<<5)
-#define BNX2_MISC_GP_HW_CTL0_HC_CNTL_TMOUT_CTR_RST_TE	 (1L<<6)
-#define BNX2_MISC_GP_HW_CTL0_RESERVED1_XI		 (0x7L<<4)
-#define BNX2_MISC_GP_HW_CTL0_ENA_CORE_RST_ON_MAIN_PWR_GOING_AWAY	 (1L<<7)
-#define BNX2_MISC_GP_HW_CTL0_ENA_SEL_VAUX_B_IN_L2_TE	 (1L<<8)
-#define BNX2_MISC_GP_HW_CTL0_GRC_BNK_FREE_FIX_TE	 (1L<<9)
-#define BNX2_MISC_GP_HW_CTL0_LED_ACT_SEL_TE		 (1L<<10)
-#define BNX2_MISC_GP_HW_CTL0_RESERVED2_XI		 (0x7L<<8)
-#define BNX2_MISC_GP_HW_CTL0_UP1_DEF0			 (1L<<11)
-#define BNX2_MISC_GP_HW_CTL0_FIBER_MODE_DIS_DEF		 (1L<<12)
-#define BNX2_MISC_GP_HW_CTL0_FORCE2500_DEF		 (1L<<13)
-#define BNX2_MISC_GP_HW_CTL0_AUTODETECT_DIS_DEF		 (1L<<14)
-#define BNX2_MISC_GP_HW_CTL0_PARALLEL_DETECT_DEF	 (1L<<15)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI		 (0xfL<<16)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_3MA		 (0L<<16)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_2P5MA		 (1L<<16)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_2P0MA		 (3L<<16)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_1P5MA		 (5L<<16)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_1P0MA		 (7L<<16)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_PWRDN		 (15L<<16)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PRE2DIS		 (1L<<20)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PRE1DIS		 (1L<<21)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT		 (0x3L<<22)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_M6P		 (0L<<22)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_M0P		 (1L<<22)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_P0P		 (2L<<22)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_P6P		 (3L<<22)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT		 (0x3L<<24)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_M6P		 (0L<<24)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_M0P		 (1L<<24)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_P0P		 (2L<<24)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_P6P		 (3L<<24)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ		 (0x3L<<26)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_240UA	 (0L<<26)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_160UA	 (1L<<26)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_400UA	 (2L<<26)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_320UA	 (3L<<26)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ		 (0x3L<<28)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_240UA	 (0L<<28)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_160UA	 (1L<<28)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_400UA	 (2L<<28)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_320UA	 (3L<<28)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ		 (0x3L<<30)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P57	 (0L<<30)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P45	 (1L<<30)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P62	 (2L<<30)
-#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P66	 (3L<<30)
-
-#define BNX2_MISC_GP_HW_CTL1				0x000008c0
-#define BNX2_MISC_GP_HW_CTL1_1_ATTN_BTN_PRSNT_TE	 (1L<<0)
-#define BNX2_MISC_GP_HW_CTL1_1_ATTN_IND_PRSNT_TE	 (1L<<1)
-#define BNX2_MISC_GP_HW_CTL1_1_PWR_IND_PRSNT_TE		 (1L<<2)
-#define BNX2_MISC_GP_HW_CTL1_0_PCIE_LOOPBACK_TE		 (1L<<3)
-#define BNX2_MISC_GP_HW_CTL1_RESERVED_SOFT_XI		 (0xffffL<<0)
-#define BNX2_MISC_GP_HW_CTL1_RESERVED_HARD_XI		 (0xffffL<<16)
-
-#define BNX2_MISC_NEW_HW_CTL				0x000008c4
-#define BNX2_MISC_NEW_HW_CTL_MAIN_POR_BYPASS		 (1L<<0)
-#define BNX2_MISC_NEW_HW_CTL_RINGOSC_ENABLE		 (1L<<1)
-#define BNX2_MISC_NEW_HW_CTL_RINGOSC_SEL0		 (1L<<2)
-#define BNX2_MISC_NEW_HW_CTL_RINGOSC_SEL1		 (1L<<3)
-#define BNX2_MISC_NEW_HW_CTL_RESERVED_SHARED		 (0xfffL<<4)
-#define BNX2_MISC_NEW_HW_CTL_RESERVED_SPLIT		 (0xffffL<<16)
-
-#define BNX2_MISC_NEW_CORE_CTL				0x000008c8
-#define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_SUCCESS	 (1L<<0)
-#define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_REQ		 (1L<<1)
-#define BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE		 (1L<<16)
-#define BNX2_MISC_NEW_CORE_CTL_RESERVED_CMN		 (0x3fffL<<2)
-#define BNX2_MISC_NEW_CORE_CTL_RESERVED_TC		 (0xffffL<<16)
-
-#define BNX2_MISC_ECO_HW_CTL				0x000008cc
-#define BNX2_MISC_ECO_HW_CTL_LARGE_GRC_TMOUT_EN		 (1L<<0)
-#define BNX2_MISC_ECO_HW_CTL_RESERVED_SOFT		 (0x7fffL<<1)
-#define BNX2_MISC_ECO_HW_CTL_RESERVED_HARD		 (0xffffL<<16)
-
-#define BNX2_MISC_ECO_CORE_CTL				0x000008d0
-#define BNX2_MISC_ECO_CORE_CTL_RESERVED_SOFT		 (0xffffL<<0)
-#define BNX2_MISC_ECO_CORE_CTL_RESERVED_HARD		 (0xffffL<<16)
-
-#define BNX2_MISC_PPIO					0x000008d4
-#define BNX2_MISC_PPIO_VALUE				 (0xfL<<0)
-#define BNX2_MISC_PPIO_SET				 (0xfL<<8)
-#define BNX2_MISC_PPIO_CLR				 (0xfL<<16)
-#define BNX2_MISC_PPIO_FLOAT				 (0xfL<<24)
-
-#define BNX2_MISC_PPIO_INT				0x000008d8
-#define BNX2_MISC_PPIO_INT_INT_STATE			 (0xfL<<0)
-#define BNX2_MISC_PPIO_INT_OLD_VALUE			 (0xfL<<8)
-#define BNX2_MISC_PPIO_INT_OLD_SET			 (0xfL<<16)
-#define BNX2_MISC_PPIO_INT_OLD_CLR			 (0xfL<<24)
-
-#define BNX2_MISC_RESET_NUMS				0x000008dc
-#define BNX2_MISC_RESET_NUMS_NUM_HARD_RESETS		 (0x7L<<0)
-#define BNX2_MISC_RESET_NUMS_NUM_PCIE_RESETS		 (0x7L<<4)
-#define BNX2_MISC_RESET_NUMS_NUM_PERSTB_RESETS		 (0x7L<<8)
-#define BNX2_MISC_RESET_NUMS_NUM_CMN_RESETS		 (0x7L<<12)
-#define BNX2_MISC_RESET_NUMS_NUM_PORT_RESETS		 (0x7L<<16)
-
-#define BNX2_MISC_CS16_ERR				0x000008e0
-#define BNX2_MISC_CS16_ERR_ENA_PCI			 (1L<<0)
-#define BNX2_MISC_CS16_ERR_ENA_RDMA			 (1L<<1)
-#define BNX2_MISC_CS16_ERR_ENA_TDMA			 (1L<<2)
-#define BNX2_MISC_CS16_ERR_ENA_EMAC			 (1L<<3)
-#define BNX2_MISC_CS16_ERR_ENA_CTX			 (1L<<4)
-#define BNX2_MISC_CS16_ERR_ENA_TBDR			 (1L<<5)
-#define BNX2_MISC_CS16_ERR_ENA_RBDC			 (1L<<6)
-#define BNX2_MISC_CS16_ERR_ENA_COM			 (1L<<7)
-#define BNX2_MISC_CS16_ERR_ENA_CP			 (1L<<8)
-#define BNX2_MISC_CS16_ERR_STA_PCI			 (1L<<16)
-#define BNX2_MISC_CS16_ERR_STA_RDMA			 (1L<<17)
-#define BNX2_MISC_CS16_ERR_STA_TDMA			 (1L<<18)
-#define BNX2_MISC_CS16_ERR_STA_EMAC			 (1L<<19)
-#define BNX2_MISC_CS16_ERR_STA_CTX			 (1L<<20)
-#define BNX2_MISC_CS16_ERR_STA_TBDR			 (1L<<21)
-#define BNX2_MISC_CS16_ERR_STA_RBDC			 (1L<<22)
-#define BNX2_MISC_CS16_ERR_STA_COM			 (1L<<23)
-#define BNX2_MISC_CS16_ERR_STA_CP			 (1L<<24)
-
-#define BNX2_MISC_SPIO_EVENT				0x000008e4
-#define BNX2_MISC_SPIO_EVENT_ENABLE			 (0xffL<<0)
-
-#define BNX2_MISC_PPIO_EVENT				0x000008e8
-#define BNX2_MISC_PPIO_EVENT_ENABLE			 (0xfL<<0)
-
-#define BNX2_MISC_DUAL_MEDIA_CTRL			0x000008ec
-#define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID		 (0xffL<<0)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_X		 (0L<<0)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_C		 (3L<<0)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_S		 (12L<<0)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP	 (0x7L<<8)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_PORT_SWAP_PIN		 (1L<<11)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES1_SIGDET	 (1L<<12)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES0_SIGDET	 (1L<<13)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY1_SIGDET		 (1L<<14)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY0_SIGDET		 (1L<<15)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_LCPLL_RST		 (1L<<16)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES1_RST		 (1L<<17)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES0_RST		 (1L<<18)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY1_RST		 (1L<<19)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY0_RST		 (1L<<20)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL		 (0x7L<<21)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_PORT_SWAP		 (1L<<24)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE	 (1L<<25)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ	 (0xfL<<26)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_SER1_IDDQ	 (1L<<26)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_SER0_IDDQ	 (2L<<26)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_PHY1_IDDQ	 (4L<<26)
-#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_PHY0_IDDQ	 (8L<<26)
-
-#define BNX2_MISC_OTP_CMD1				0x000008f0
-#define BNX2_MISC_OTP_CMD1_FMODE			 (0x7L<<0)
-#define BNX2_MISC_OTP_CMD1_FMODE_IDLE			 (0L<<0)
-#define BNX2_MISC_OTP_CMD1_FMODE_WRITE			 (1L<<0)
-#define BNX2_MISC_OTP_CMD1_FMODE_INIT			 (2L<<0)
-#define BNX2_MISC_OTP_CMD1_FMODE_SET			 (3L<<0)
-#define BNX2_MISC_OTP_CMD1_FMODE_RST			 (4L<<0)
-#define BNX2_MISC_OTP_CMD1_FMODE_VERIFY			 (5L<<0)
-#define BNX2_MISC_OTP_CMD1_FMODE_RESERVED0		 (6L<<0)
-#define BNX2_MISC_OTP_CMD1_FMODE_RESERVED1		 (7L<<0)
-#define BNX2_MISC_OTP_CMD1_USEPINS			 (1L<<8)
-#define BNX2_MISC_OTP_CMD1_PROGSEL			 (1L<<9)
-#define BNX2_MISC_OTP_CMD1_PROGSTART			 (1L<<10)
-#define BNX2_MISC_OTP_CMD1_PCOUNT			 (0x7L<<16)
-#define BNX2_MISC_OTP_CMD1_PBYP				 (1L<<19)
-#define BNX2_MISC_OTP_CMD1_VSEL				 (0xfL<<20)
-#define BNX2_MISC_OTP_CMD1_TM				 (0x7L<<27)
-#define BNX2_MISC_OTP_CMD1_SADBYP			 (1L<<30)
-#define BNX2_MISC_OTP_CMD1_DEBUG			 (1L<<31)
-
-#define BNX2_MISC_OTP_CMD2				0x000008f4
-#define BNX2_MISC_OTP_CMD2_OTP_ROM_ADDR			 (0x3ffL<<0)
-#define BNX2_MISC_OTP_CMD2_DOSEL			 (0x7fL<<16)
-#define BNX2_MISC_OTP_CMD2_DOSEL_0			 (0L<<16)
-#define BNX2_MISC_OTP_CMD2_DOSEL_1			 (1L<<16)
-#define BNX2_MISC_OTP_CMD2_DOSEL_127			 (127L<<16)
-
-#define BNX2_MISC_OTP_STATUS				0x000008f8
-#define BNX2_MISC_OTP_STATUS_DATA			 (0xffL<<0)
-#define BNX2_MISC_OTP_STATUS_VALID			 (1L<<8)
-#define BNX2_MISC_OTP_STATUS_BUSY			 (1L<<9)
-#define BNX2_MISC_OTP_STATUS_BUSYSM			 (1L<<10)
-#define BNX2_MISC_OTP_STATUS_DONE			 (1L<<11)
-
-#define BNX2_MISC_OTP_SHIFT1_CMD			0x000008fc
-#define BNX2_MISC_OTP_SHIFT1_CMD_RESET_MODE_N		 (1L<<0)
-#define BNX2_MISC_OTP_SHIFT1_CMD_SHIFT_DONE		 (1L<<1)
-#define BNX2_MISC_OTP_SHIFT1_CMD_SHIFT_START		 (1L<<2)
-#define BNX2_MISC_OTP_SHIFT1_CMD_LOAD_DATA		 (1L<<3)
-#define BNX2_MISC_OTP_SHIFT1_CMD_SHIFT_SELECT		 (0x1fL<<8)
-
-#define BNX2_MISC_OTP_SHIFT1_DATA			0x00000900
-#define BNX2_MISC_OTP_SHIFT2_CMD			0x00000904
-#define BNX2_MISC_OTP_SHIFT2_CMD_RESET_MODE_N		 (1L<<0)
-#define BNX2_MISC_OTP_SHIFT2_CMD_SHIFT_DONE		 (1L<<1)
-#define BNX2_MISC_OTP_SHIFT2_CMD_SHIFT_START		 (1L<<2)
-#define BNX2_MISC_OTP_SHIFT2_CMD_LOAD_DATA		 (1L<<3)
-#define BNX2_MISC_OTP_SHIFT2_CMD_SHIFT_SELECT		 (0x1fL<<8)
-
-#define BNX2_MISC_OTP_SHIFT2_DATA			0x00000908
-#define BNX2_MISC_BIST_CS0				0x0000090c
-#define BNX2_MISC_BIST_CS0_MBIST_EN			 (1L<<0)
-#define BNX2_MISC_BIST_CS0_BIST_SETUP			 (0x3L<<1)
-#define BNX2_MISC_BIST_CS0_MBIST_ASYNC_RESET		 (1L<<3)
-#define BNX2_MISC_BIST_CS0_MBIST_DONE			 (1L<<8)
-#define BNX2_MISC_BIST_CS0_MBIST_GO			 (1L<<9)
-#define BNX2_MISC_BIST_CS0_BIST_OVERRIDE		 (1L<<31)
-
-#define BNX2_MISC_BIST_MEMSTATUS0			0x00000910
-#define BNX2_MISC_BIST_CS1				0x00000914
-#define BNX2_MISC_BIST_CS1_MBIST_EN			 (1L<<0)
-#define BNX2_MISC_BIST_CS1_BIST_SETUP			 (0x3L<<1)
-#define BNX2_MISC_BIST_CS1_MBIST_ASYNC_RESET		 (1L<<3)
-#define BNX2_MISC_BIST_CS1_MBIST_DONE			 (1L<<8)
-#define BNX2_MISC_BIST_CS1_MBIST_GO			 (1L<<9)
-
-#define BNX2_MISC_BIST_MEMSTATUS1			0x00000918
-#define BNX2_MISC_BIST_CS2				0x0000091c
-#define BNX2_MISC_BIST_CS2_MBIST_EN			 (1L<<0)
-#define BNX2_MISC_BIST_CS2_BIST_SETUP			 (0x3L<<1)
-#define BNX2_MISC_BIST_CS2_MBIST_ASYNC_RESET		 (1L<<3)
-#define BNX2_MISC_BIST_CS2_MBIST_DONE			 (1L<<8)
-#define BNX2_MISC_BIST_CS2_MBIST_GO			 (1L<<9)
-
-#define BNX2_MISC_BIST_MEMSTATUS2			0x00000920
-#define BNX2_MISC_BIST_CS3				0x00000924
-#define BNX2_MISC_BIST_CS3_MBIST_EN			 (1L<<0)
-#define BNX2_MISC_BIST_CS3_BIST_SETUP			 (0x3L<<1)
-#define BNX2_MISC_BIST_CS3_MBIST_ASYNC_RESET		 (1L<<3)
-#define BNX2_MISC_BIST_CS3_MBIST_DONE			 (1L<<8)
-#define BNX2_MISC_BIST_CS3_MBIST_GO			 (1L<<9)
-
-#define BNX2_MISC_BIST_MEMSTATUS3			0x00000928
-#define BNX2_MISC_BIST_CS4				0x0000092c
-#define BNX2_MISC_BIST_CS4_MBIST_EN			 (1L<<0)
-#define BNX2_MISC_BIST_CS4_BIST_SETUP			 (0x3L<<1)
-#define BNX2_MISC_BIST_CS4_MBIST_ASYNC_RESET		 (1L<<3)
-#define BNX2_MISC_BIST_CS4_MBIST_DONE			 (1L<<8)
-#define BNX2_MISC_BIST_CS4_MBIST_GO			 (1L<<9)
-
-#define BNX2_MISC_BIST_MEMSTATUS4			0x00000930
-#define BNX2_MISC_BIST_CS5				0x00000934
-#define BNX2_MISC_BIST_CS5_MBIST_EN			 (1L<<0)
-#define BNX2_MISC_BIST_CS5_BIST_SETUP			 (0x3L<<1)
-#define BNX2_MISC_BIST_CS5_MBIST_ASYNC_RESET		 (1L<<3)
-#define BNX2_MISC_BIST_CS5_MBIST_DONE			 (1L<<8)
-#define BNX2_MISC_BIST_CS5_MBIST_GO			 (1L<<9)
-
-#define BNX2_MISC_BIST_MEMSTATUS5			0x00000938
-#define BNX2_MISC_MEM_TM0				0x0000093c
-#define BNX2_MISC_MEM_TM0_PCIE_REPLAY_TM		 (0xfL<<0)
-#define BNX2_MISC_MEM_TM0_MCP_SCPAD			 (0xfL<<8)
-#define BNX2_MISC_MEM_TM0_UMP_TM			 (0xffL<<16)
-#define BNX2_MISC_MEM_TM0_HB_MEM_TM			 (0xfL<<24)
-
-#define BNX2_MISC_USPLL_CTRL				0x00000940
-#define BNX2_MISC_USPLL_CTRL_PH_DET_DIS			 (1L<<0)
-#define BNX2_MISC_USPLL_CTRL_FREQ_DET_DIS		 (1L<<1)
-#define BNX2_MISC_USPLL_CTRL_LCPX			 (0x3fL<<2)
-#define BNX2_MISC_USPLL_CTRL_RX				 (0x3L<<8)
-#define BNX2_MISC_USPLL_CTRL_VC_EN			 (1L<<10)
-#define BNX2_MISC_USPLL_CTRL_VCO_MG			 (0x3L<<11)
-#define BNX2_MISC_USPLL_CTRL_KVCO_XF			 (0x7L<<13)
-#define BNX2_MISC_USPLL_CTRL_KVCO_XS			 (0x7L<<16)
-#define BNX2_MISC_USPLL_CTRL_TESTD_EN			 (1L<<19)
-#define BNX2_MISC_USPLL_CTRL_TESTD_SEL			 (0x7L<<20)
-#define BNX2_MISC_USPLL_CTRL_TESTA_EN			 (1L<<23)
-#define BNX2_MISC_USPLL_CTRL_TESTA_SEL			 (0x3L<<24)
-#define BNX2_MISC_USPLL_CTRL_ATTEN_FREF			 (1L<<26)
-#define BNX2_MISC_USPLL_CTRL_DIGITAL_RST		 (1L<<27)
-#define BNX2_MISC_USPLL_CTRL_ANALOG_RST			 (1L<<28)
-#define BNX2_MISC_USPLL_CTRL_LOCK			 (1L<<29)
-
-#define BNX2_MISC_PERR_STATUS0				0x00000944
-#define BNX2_MISC_PERR_STATUS0_COM_DMAE_PERR		 (1L<<0)
-#define BNX2_MISC_PERR_STATUS0_CP_DMAE_PERR		 (1L<<1)
-#define BNX2_MISC_PERR_STATUS0_RPM_ACPIBEMEM_PERR	 (1L<<2)
-#define BNX2_MISC_PERR_STATUS0_CTX_USAGE_CNT_PERR	 (1L<<3)
-#define BNX2_MISC_PERR_STATUS0_CTX_PGTBL_PERR		 (1L<<4)
-#define BNX2_MISC_PERR_STATUS0_CTX_CACHE_PERR		 (1L<<5)
-#define BNX2_MISC_PERR_STATUS0_CTX_MIRROR_PERR		 (1L<<6)
-#define BNX2_MISC_PERR_STATUS0_COM_CTXC_PERR		 (1L<<7)
-#define BNX2_MISC_PERR_STATUS0_COM_SCPAD_PERR		 (1L<<8)
-#define BNX2_MISC_PERR_STATUS0_CP_CTXC_PERR		 (1L<<9)
-#define BNX2_MISC_PERR_STATUS0_CP_SCPAD_PERR		 (1L<<10)
-#define BNX2_MISC_PERR_STATUS0_RXP_RBUFC_PERR		 (1L<<11)
-#define BNX2_MISC_PERR_STATUS0_RXP_CTXC_PERR		 (1L<<12)
-#define BNX2_MISC_PERR_STATUS0_RXP_SCPAD_PERR		 (1L<<13)
-#define BNX2_MISC_PERR_STATUS0_TPAT_SCPAD_PERR		 (1L<<14)
-#define BNX2_MISC_PERR_STATUS0_TXP_CTXC_PERR		 (1L<<15)
-#define BNX2_MISC_PERR_STATUS0_TXP_SCPAD_PERR		 (1L<<16)
-#define BNX2_MISC_PERR_STATUS0_CS_TMEM_PERR		 (1L<<17)
-#define BNX2_MISC_PERR_STATUS0_MQ_CTX_PERR		 (1L<<18)
-#define BNX2_MISC_PERR_STATUS0_RPM_DFIFOMEM_PERR	 (1L<<19)
-#define BNX2_MISC_PERR_STATUS0_RPC_DFIFOMEM_PERR	 (1L<<20)
-#define BNX2_MISC_PERR_STATUS0_RBUF_PTRMEM_PERR		 (1L<<21)
-#define BNX2_MISC_PERR_STATUS0_RBUF_DATAMEM_PERR	 (1L<<22)
-#define BNX2_MISC_PERR_STATUS0_RV2P_P2IRAM_PERR		 (1L<<23)
-#define BNX2_MISC_PERR_STATUS0_RV2P_P1IRAM_PERR		 (1L<<24)
-#define BNX2_MISC_PERR_STATUS0_RV2P_CB1REGS_PERR	 (1L<<25)
-#define BNX2_MISC_PERR_STATUS0_RV2P_CB0REGS_PERR	 (1L<<26)
-#define BNX2_MISC_PERR_STATUS0_TPBUF_PERR		 (1L<<27)
-#define BNX2_MISC_PERR_STATUS0_THBUF_PERR		 (1L<<28)
-#define BNX2_MISC_PERR_STATUS0_TDMA_PERR		 (1L<<29)
-#define BNX2_MISC_PERR_STATUS0_TBDC_PERR		 (1L<<30)
-#define BNX2_MISC_PERR_STATUS0_TSCH_LR_PERR		 (1L<<31)
-
-#define BNX2_MISC_PERR_STATUS1				0x00000948
-#define BNX2_MISC_PERR_STATUS1_RBDC_PERR		 (1L<<0)
-#define BNX2_MISC_PERR_STATUS1_RDMA_DFIFO_PERR		 (1L<<2)
-#define BNX2_MISC_PERR_STATUS1_HC_STATS_PERR		 (1L<<3)
-#define BNX2_MISC_PERR_STATUS1_HC_MSIX_PERR		 (1L<<4)
-#define BNX2_MISC_PERR_STATUS1_HC_PRODUCSTB_PERR	 (1L<<5)
-#define BNX2_MISC_PERR_STATUS1_HC_CONSUMSTB_PERR	 (1L<<6)
-#define BNX2_MISC_PERR_STATUS1_TPATQ_PERR		 (1L<<7)
-#define BNX2_MISC_PERR_STATUS1_MCPQ_PERR		 (1L<<8)
-#define BNX2_MISC_PERR_STATUS1_TDMAQ_PERR		 (1L<<9)
-#define BNX2_MISC_PERR_STATUS1_TXPQ_PERR		 (1L<<10)
-#define BNX2_MISC_PERR_STATUS1_COMTQ_PERR		 (1L<<11)
-#define BNX2_MISC_PERR_STATUS1_COMQ_PERR		 (1L<<12)
-#define BNX2_MISC_PERR_STATUS1_RLUPQ_PERR		 (1L<<13)
-#define BNX2_MISC_PERR_STATUS1_RXPQ_PERR		 (1L<<14)
-#define BNX2_MISC_PERR_STATUS1_RV2PPQ_PERR		 (1L<<15)
-#define BNX2_MISC_PERR_STATUS1_RDMAQ_PERR		 (1L<<16)
-#define BNX2_MISC_PERR_STATUS1_TASQ_PERR		 (1L<<17)
-#define BNX2_MISC_PERR_STATUS1_TBDRQ_PERR		 (1L<<18)
-#define BNX2_MISC_PERR_STATUS1_TSCHQ_PERR		 (1L<<19)
-#define BNX2_MISC_PERR_STATUS1_COMXQ_PERR		 (1L<<20)
-#define BNX2_MISC_PERR_STATUS1_RXPCQ_PERR		 (1L<<21)
-#define BNX2_MISC_PERR_STATUS1_RV2PTQ_PERR		 (1L<<22)
-#define BNX2_MISC_PERR_STATUS1_RV2PMQ_PERR		 (1L<<23)
-#define BNX2_MISC_PERR_STATUS1_CPQ_PERR			 (1L<<24)
-#define BNX2_MISC_PERR_STATUS1_CSQ_PERR			 (1L<<25)
-#define BNX2_MISC_PERR_STATUS1_RLUP_CID_PERR		 (1L<<26)
-#define BNX2_MISC_PERR_STATUS1_RV2PCS_TMEM_PERR		 (1L<<27)
-#define BNX2_MISC_PERR_STATUS1_RV2PCSQ_PERR		 (1L<<28)
-#define BNX2_MISC_PERR_STATUS1_MQ_IDX_PERR		 (1L<<29)
-
-#define BNX2_MISC_PERR_STATUS2				0x0000094c
-#define BNX2_MISC_PERR_STATUS2_TGT_FIFO_PERR		 (1L<<0)
-#define BNX2_MISC_PERR_STATUS2_UMP_TX_PERR		 (1L<<1)
-#define BNX2_MISC_PERR_STATUS2_UMP_RX_PERR		 (1L<<2)
-#define BNX2_MISC_PERR_STATUS2_MCP_ROM_PERR		 (1L<<3)
-#define BNX2_MISC_PERR_STATUS2_MCP_SCPAD_PERR		 (1L<<4)
-#define BNX2_MISC_PERR_STATUS2_HB_MEM_PERR		 (1L<<5)
-#define BNX2_MISC_PERR_STATUS2_PCIE_REPLAY_PERR		 (1L<<6)
-
-#define BNX2_MISC_LCPLL_CTRL0				0x00000950
-#define BNX2_MISC_LCPLL_CTRL0_OAC			 (0x7L<<0)
-#define BNX2_MISC_LCPLL_CTRL0_OAC_NEGTWENTY		 (0L<<0)
-#define BNX2_MISC_LCPLL_CTRL0_OAC_ZERO			 (1L<<0)
-#define BNX2_MISC_LCPLL_CTRL0_OAC_TWENTY		 (3L<<0)
-#define BNX2_MISC_LCPLL_CTRL0_OAC_FORTY			 (7L<<0)
-#define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL			 (0x7L<<3)
-#define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_360		 (0L<<3)
-#define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_480		 (1L<<3)
-#define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_600		 (3L<<3)
-#define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_720		 (7L<<3)
-#define BNX2_MISC_LCPLL_CTRL0_BIAS_CTRL			 (0x3L<<6)
-#define BNX2_MISC_LCPLL_CTRL0_PLL_OBSERVE		 (0x7L<<8)
-#define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL			 (0x3L<<11)
-#define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL_0		 (0L<<11)
-#define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL_1		 (1L<<11)
-#define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL_2		 (2L<<11)
-#define BNX2_MISC_LCPLL_CTRL0_PLLSEQSTART		 (1L<<13)
-#define BNX2_MISC_LCPLL_CTRL0_RESERVED			 (1L<<14)
-#define BNX2_MISC_LCPLL_CTRL0_CAPRETRY_EN		 (1L<<15)
-#define BNX2_MISC_LCPLL_CTRL0_FREQMONITOR_EN		 (1L<<16)
-#define BNX2_MISC_LCPLL_CTRL0_FREQDETRESTART_EN		 (1L<<17)
-#define BNX2_MISC_LCPLL_CTRL0_FREQDETRETRY_EN		 (1L<<18)
-#define BNX2_MISC_LCPLL_CTRL0_PLLFORCEFDONE_EN		 (1L<<19)
-#define BNX2_MISC_LCPLL_CTRL0_PLLFORCEFDONE		 (1L<<20)
-#define BNX2_MISC_LCPLL_CTRL0_PLLFORCEFPASS		 (1L<<21)
-#define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPDONE_EN	 (1L<<22)
-#define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPDONE		 (1L<<23)
-#define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPPASS_EN	 (1L<<24)
-#define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPPASS		 (1L<<25)
-#define BNX2_MISC_LCPLL_CTRL0_CAPRESTART		 (1L<<26)
-#define BNX2_MISC_LCPLL_CTRL0_CAPSELECTM_EN		 (1L<<27)
-
-#define BNX2_MISC_LCPLL_CTRL1				0x00000954
-#define BNX2_MISC_LCPLL_CTRL1_CAPSELECTM		 (0x1fL<<0)
-#define BNX2_MISC_LCPLL_CTRL1_CAPFORCESLOWDOWN_EN	 (1L<<5)
-#define BNX2_MISC_LCPLL_CTRL1_CAPFORCESLOWDOWN		 (1L<<6)
-#define BNX2_MISC_LCPLL_CTRL1_SLOWDN_XOR		 (1L<<7)
-
-#define BNX2_MISC_LCPLL_STATUS				0x00000958
-#define BNX2_MISC_LCPLL_STATUS_FREQDONE_SM		 (1L<<0)
-#define BNX2_MISC_LCPLL_STATUS_FREQPASS_SM		 (1L<<1)
-#define BNX2_MISC_LCPLL_STATUS_PLLSEQDONE		 (1L<<2)
-#define BNX2_MISC_LCPLL_STATUS_PLLSEQPASS		 (1L<<3)
-#define BNX2_MISC_LCPLL_STATUS_PLLSTATE			 (0x7L<<4)
-#define BNX2_MISC_LCPLL_STATUS_CAPSTATE			 (0x7L<<7)
-#define BNX2_MISC_LCPLL_STATUS_CAPSELECT		 (0x1fL<<10)
-#define BNX2_MISC_LCPLL_STATUS_SLOWDN_INDICATOR		 (1L<<15)
-#define BNX2_MISC_LCPLL_STATUS_SLOWDN_INDICATOR_0	 (0L<<15)
-#define BNX2_MISC_LCPLL_STATUS_SLOWDN_INDICATOR_1	 (1L<<15)
-
-#define BNX2_MISC_OSCFUNDS_CTRL				0x0000095c
-#define BNX2_MISC_OSCFUNDS_CTRL_FREQ_MON		 (1L<<5)
-#define BNX2_MISC_OSCFUNDS_CTRL_FREQ_MON_OFF		 (0L<<5)
-#define BNX2_MISC_OSCFUNDS_CTRL_FREQ_MON_ON		 (1L<<5)
-#define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM		 (0x3L<<6)
-#define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_0		 (0L<<6)
-#define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_1		 (1L<<6)
-#define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_2		 (2L<<6)
-#define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_3		 (3L<<6)
-#define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ		 (0x3L<<8)
-#define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_0		 (0L<<8)
-#define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_1		 (1L<<8)
-#define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_2		 (2L<<8)
-#define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_3		 (3L<<8)
-#define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ		 (0x3L<<10)
-#define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_0		 (0L<<10)
-#define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_1		 (1L<<10)
-#define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_2		 (2L<<10)
-#define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_3		 (3L<<10)
-
-
-/*
- *  nvm_reg definition
- *  offset: 0x6400
- */
-#define BNX2_NVM_COMMAND				0x00006400
-#define BNX2_NVM_COMMAND_RST				 (1L<<0)
-#define BNX2_NVM_COMMAND_DONE				 (1L<<3)
-#define BNX2_NVM_COMMAND_DOIT				 (1L<<4)
-#define BNX2_NVM_COMMAND_WR				 (1L<<5)
-#define BNX2_NVM_COMMAND_ERASE				 (1L<<6)
-#define BNX2_NVM_COMMAND_FIRST				 (1L<<7)
-#define BNX2_NVM_COMMAND_LAST				 (1L<<8)
-#define BNX2_NVM_COMMAND_WREN				 (1L<<16)
-#define BNX2_NVM_COMMAND_WRDI				 (1L<<17)
-#define BNX2_NVM_COMMAND_EWSR				 (1L<<18)
-#define BNX2_NVM_COMMAND_WRSR				 (1L<<19)
-#define BNX2_NVM_COMMAND_RD_ID				 (1L<<20)
-#define BNX2_NVM_COMMAND_RD_STATUS			 (1L<<21)
-#define BNX2_NVM_COMMAND_MODE_256			 (1L<<22)
-
-#define BNX2_NVM_STATUS					0x00006404
-#define BNX2_NVM_STATUS_PI_FSM_STATE			 (0xfL<<0)
-#define BNX2_NVM_STATUS_EE_FSM_STATE			 (0xfL<<4)
-#define BNX2_NVM_STATUS_EQ_FSM_STATE			 (0xfL<<8)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_XI		 (0x1fL<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_IDLE_XI	 (0L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD0_XI	 (1L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD1_XI	 (2L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD_FINISH0_XI	 (3L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD_FINISH1_XI	 (4L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_ADDR0_XI	 (5L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WRITE_DATA0_XI	 (6L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WRITE_DATA1_XI	 (7L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WRITE_DATA2_XI	 (8L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_DATA0_XI	 (9L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_DATA1_XI	 (10L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_DATA2_XI	 (11L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID0_XI	 (12L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID1_XI	 (13L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID2_XI	 (14L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID3_XI	 (15L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID4_XI	 (16L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CHECK_BUSY0_XI	 (17L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_ST_WREN_XI	 (18L<<0)
-#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WAIT_XI	 (19L<<0)
-
-#define BNX2_NVM_WRITE					0x00006408
-#define BNX2_NVM_WRITE_NVM_WRITE_VALUE			 (0xffffffffL<<0)
-#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_BIT_BANG		 (0L<<0)
-#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_EECLK		 (1L<<0)
-#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_EEDATA		 (2L<<0)
-#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SCLK		 (4L<<0)
-#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_CS_B		 (8L<<0)
-#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SO		 (16L<<0)
-#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SI		 (32L<<0)
-#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SI_XI		 (1L<<0)
-#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SO_XI		 (2L<<0)
-#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_CS_B_XI		 (4L<<0)
-#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SCLK_XI		 (8L<<0)
-
-#define BNX2_NVM_ADDR					0x0000640c
-#define BNX2_NVM_ADDR_NVM_ADDR_VALUE			 (0xffffffL<<0)
-#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_BIT_BANG		 (0L<<0)
-#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_EECLK		 (1L<<0)
-#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_EEDATA		 (2L<<0)
-#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SCLK		 (4L<<0)
-#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_CS_B		 (8L<<0)
-#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SO			 (16L<<0)
-#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SI			 (32L<<0)
-#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SI_XI		 (1L<<0)
-#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SO_XI		 (2L<<0)
-#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_CS_B_XI		 (4L<<0)
-#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SCLK_XI		 (8L<<0)
-
-#define BNX2_NVM_READ					0x00006410
-#define BNX2_NVM_READ_NVM_READ_VALUE			 (0xffffffffL<<0)
-#define BNX2_NVM_READ_NVM_READ_VALUE_BIT_BANG		 (0L<<0)
-#define BNX2_NVM_READ_NVM_READ_VALUE_EECLK		 (1L<<0)
-#define BNX2_NVM_READ_NVM_READ_VALUE_EEDATA		 (2L<<0)
-#define BNX2_NVM_READ_NVM_READ_VALUE_SCLK		 (4L<<0)
-#define BNX2_NVM_READ_NVM_READ_VALUE_CS_B		 (8L<<0)
-#define BNX2_NVM_READ_NVM_READ_VALUE_SO			 (16L<<0)
-#define BNX2_NVM_READ_NVM_READ_VALUE_SI			 (32L<<0)
-#define BNX2_NVM_READ_NVM_READ_VALUE_SI_XI		 (1L<<0)
-#define BNX2_NVM_READ_NVM_READ_VALUE_SO_XI		 (2L<<0)
-#define BNX2_NVM_READ_NVM_READ_VALUE_CS_B_XI		 (4L<<0)
-#define BNX2_NVM_READ_NVM_READ_VALUE_SCLK_XI		 (8L<<0)
-
-#define BNX2_NVM_CFG1					0x00006414
-#define BNX2_NVM_CFG1_FLASH_MODE			 (1L<<0)
-#define BNX2_NVM_CFG1_BUFFER_MODE			 (1L<<1)
-#define BNX2_NVM_CFG1_PASS_MODE				 (1L<<2)
-#define BNX2_NVM_CFG1_BITBANG_MODE			 (1L<<3)
-#define BNX2_NVM_CFG1_STATUS_BIT			 (0x7L<<4)
-#define BNX2_NVM_CFG1_STATUS_BIT_FLASH_RDY		 (0L<<4)
-#define BNX2_NVM_CFG1_STATUS_BIT_BUFFER_RDY		 (7L<<4)
-#define BNX2_NVM_CFG1_SPI_CLK_DIV			 (0xfL<<7)
-#define BNX2_NVM_CFG1_SEE_CLK_DIV			 (0x7ffL<<11)
-#define BNX2_NVM_CFG1_STRAP_CONTROL_0			 (1L<<23)
-#define BNX2_NVM_CFG1_PROTECT_MODE			 (1L<<24)
-#define BNX2_NVM_CFG1_FLASH_SIZE			 (1L<<25)
-#define BNX2_NVM_CFG1_FW_USTRAP_1			 (1L<<26)
-#define BNX2_NVM_CFG1_FW_USTRAP_0			 (1L<<27)
-#define BNX2_NVM_CFG1_FW_USTRAP_2			 (1L<<28)
-#define BNX2_NVM_CFG1_FW_USTRAP_3			 (1L<<29)
-#define BNX2_NVM_CFG1_FW_FLASH_TYPE_EN			 (1L<<30)
-#define BNX2_NVM_CFG1_COMPAT_BYPASSS			 (1L<<31)
-
-#define BNX2_NVM_CFG2					0x00006418
-#define BNX2_NVM_CFG2_ERASE_CMD				 (0xffL<<0)
-#define BNX2_NVM_CFG2_DUMMY				 (0xffL<<8)
-#define BNX2_NVM_CFG2_STATUS_CMD			 (0xffL<<16)
-#define BNX2_NVM_CFG2_READ_ID				 (0xffL<<24)
-
-#define BNX2_NVM_CFG3					0x0000641c
-#define BNX2_NVM_CFG3_BUFFER_RD_CMD			 (0xffL<<0)
-#define BNX2_NVM_CFG3_WRITE_CMD				 (0xffL<<8)
-#define BNX2_NVM_CFG3_BUFFER_WRITE_CMD			 (0xffL<<16)
-#define BNX2_NVM_CFG3_READ_CMD				 (0xffL<<24)
-
-#define BNX2_NVM_SW_ARB					0x00006420
-#define BNX2_NVM_SW_ARB_ARB_REQ_SET0			 (1L<<0)
-#define BNX2_NVM_SW_ARB_ARB_REQ_SET1			 (1L<<1)
-#define BNX2_NVM_SW_ARB_ARB_REQ_SET2			 (1L<<2)
-#define BNX2_NVM_SW_ARB_ARB_REQ_SET3			 (1L<<3)
-#define BNX2_NVM_SW_ARB_ARB_REQ_CLR0			 (1L<<4)
-#define BNX2_NVM_SW_ARB_ARB_REQ_CLR1			 (1L<<5)
-#define BNX2_NVM_SW_ARB_ARB_REQ_CLR2			 (1L<<6)
-#define BNX2_NVM_SW_ARB_ARB_REQ_CLR3			 (1L<<7)
-#define BNX2_NVM_SW_ARB_ARB_ARB0			 (1L<<8)
-#define BNX2_NVM_SW_ARB_ARB_ARB1			 (1L<<9)
-#define BNX2_NVM_SW_ARB_ARB_ARB2			 (1L<<10)
-#define BNX2_NVM_SW_ARB_ARB_ARB3			 (1L<<11)
-#define BNX2_NVM_SW_ARB_REQ0				 (1L<<12)
-#define BNX2_NVM_SW_ARB_REQ1				 (1L<<13)
-#define BNX2_NVM_SW_ARB_REQ2				 (1L<<14)
-#define BNX2_NVM_SW_ARB_REQ3				 (1L<<15)
-
-#define BNX2_NVM_ACCESS_ENABLE				0x00006424
-#define BNX2_NVM_ACCESS_ENABLE_EN			 (1L<<0)
-#define BNX2_NVM_ACCESS_ENABLE_WR_EN			 (1L<<1)
-
-#define BNX2_NVM_WRITE1					0x00006428
-#define BNX2_NVM_WRITE1_WREN_CMD			 (0xffL<<0)
-#define BNX2_NVM_WRITE1_WRDI_CMD			 (0xffL<<8)
-#define BNX2_NVM_WRITE1_SR_DATA				 (0xffL<<16)
-
-#define BNX2_NVM_CFG4					0x0000642c
-#define BNX2_NVM_CFG4_FLASH_SIZE			 (0x7L<<0)
-#define BNX2_NVM_CFG4_FLASH_SIZE_1MBIT			 (0L<<0)
-#define BNX2_NVM_CFG4_FLASH_SIZE_2MBIT			 (1L<<0)
-#define BNX2_NVM_CFG4_FLASH_SIZE_4MBIT			 (2L<<0)
-#define BNX2_NVM_CFG4_FLASH_SIZE_8MBIT			 (3L<<0)
-#define BNX2_NVM_CFG4_FLASH_SIZE_16MBIT			 (4L<<0)
-#define BNX2_NVM_CFG4_FLASH_SIZE_32MBIT			 (5L<<0)
-#define BNX2_NVM_CFG4_FLASH_SIZE_64MBIT			 (6L<<0)
-#define BNX2_NVM_CFG4_FLASH_SIZE_128MBIT		 (7L<<0)
-#define BNX2_NVM_CFG4_FLASH_VENDOR			 (1L<<3)
-#define BNX2_NVM_CFG4_FLASH_VENDOR_ST			 (0L<<3)
-#define BNX2_NVM_CFG4_FLASH_VENDOR_ATMEL		 (1L<<3)
-#define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC		 (0x3L<<4)
-#define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT8	 (0L<<4)
-#define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT9	 (1L<<4)
-#define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT10	 (2L<<4)
-#define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT11	 (3L<<4)
-#define BNX2_NVM_CFG4_STATUS_BIT_POLARITY		 (1L<<6)
-#define BNX2_NVM_CFG4_RESERVED				 (0x1ffffffL<<7)
-
-#define BNX2_NVM_RECONFIG				0x00006430
-#define BNX2_NVM_RECONFIG_ORIG_STRAP_VALUE		 (0xfL<<0)
-#define BNX2_NVM_RECONFIG_ORIG_STRAP_VALUE_ST		 (0L<<0)
-#define BNX2_NVM_RECONFIG_ORIG_STRAP_VALUE_ATMEL	 (1L<<0)
-#define BNX2_NVM_RECONFIG_RECONFIG_STRAP_VALUE		 (0xfL<<4)
-#define BNX2_NVM_RECONFIG_RESERVED			 (0x7fffffL<<8)
-#define BNX2_NVM_RECONFIG_RECONFIG_DONE			 (1L<<31)
-
-
-
-/*
- *  dma_reg definition
- *  offset: 0xc00
- */
-#define BNX2_DMA_COMMAND				0x00000c00
-#define BNX2_DMA_COMMAND_ENABLE				 (1L<<0)
-
-#define BNX2_DMA_STATUS					0x00000c04
-#define BNX2_DMA_STATUS_PAR_ERROR_STATE			 (1L<<0)
-#define BNX2_DMA_STATUS_READ_TRANSFERS_STAT		 (1L<<16)
-#define BNX2_DMA_STATUS_READ_DELAY_PCI_CLKS_STAT	 (1L<<17)
-#define BNX2_DMA_STATUS_BIG_READ_TRANSFERS_STAT		 (1L<<18)
-#define BNX2_DMA_STATUS_BIG_READ_DELAY_PCI_CLKS_STAT	 (1L<<19)
-#define BNX2_DMA_STATUS_BIG_READ_RETRY_AFTER_DATA_STAT	 (1L<<20)
-#define BNX2_DMA_STATUS_WRITE_TRANSFERS_STAT		 (1L<<21)
-#define BNX2_DMA_STATUS_WRITE_DELAY_PCI_CLKS_STAT	 (1L<<22)
-#define BNX2_DMA_STATUS_BIG_WRITE_TRANSFERS_STAT	 (1L<<23)
-#define BNX2_DMA_STATUS_BIG_WRITE_DELAY_PCI_CLKS_STAT	 (1L<<24)
-#define BNX2_DMA_STATUS_BIG_WRITE_RETRY_AFTER_DATA_STAT	 (1L<<25)
-#define BNX2_DMA_STATUS_GLOBAL_ERR_XI			 (1L<<0)
-#define BNX2_DMA_STATUS_BME_XI				 (1L<<4)
-
-#define BNX2_DMA_CONFIG					0x00000c08
-#define BNX2_DMA_CONFIG_DATA_BYTE_SWAP			 (1L<<0)
-#define BNX2_DMA_CONFIG_DATA_WORD_SWAP			 (1L<<1)
-#define BNX2_DMA_CONFIG_CNTL_BYTE_SWAP			 (1L<<4)
-#define BNX2_DMA_CONFIG_CNTL_WORD_SWAP			 (1L<<5)
-#define BNX2_DMA_CONFIG_ONE_DMA				 (1L<<6)
-#define BNX2_DMA_CONFIG_CNTL_TWO_DMA			 (1L<<7)
-#define BNX2_DMA_CONFIG_CNTL_FPGA_MODE			 (1L<<8)
-#define BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA		 (1L<<10)
-#define BNX2_DMA_CONFIG_CNTL_PCI_COMP_DLY		 (1L<<11)
-#define BNX2_DMA_CONFIG_NO_RCHANS_IN_USE		 (0xfL<<12)
-#define BNX2_DMA_CONFIG_NO_WCHANS_IN_USE		 (0xfL<<16)
-#define BNX2_DMA_CONFIG_PCI_CLK_CMP_BITS		 (0x7L<<20)
-#define BNX2_DMA_CONFIG_PCI_FAST_CLK_CMP		 (1L<<23)
-#define BNX2_DMA_CONFIG_BIG_SIZE			 (0xfL<<24)
-#define BNX2_DMA_CONFIG_BIG_SIZE_NONE			 (0x0L<<24)
-#define BNX2_DMA_CONFIG_BIG_SIZE_64			 (0x1L<<24)
-#define BNX2_DMA_CONFIG_BIG_SIZE_128			 (0x2L<<24)
-#define BNX2_DMA_CONFIG_BIG_SIZE_256			 (0x4L<<24)
-#define BNX2_DMA_CONFIG_BIG_SIZE_512			 (0x8L<<24)
-#define BNX2_DMA_CONFIG_DAT_WBSWAP_MODE_XI		 (0x3L<<0)
-#define BNX2_DMA_CONFIG_CTL_WBSWAP_MODE_XI		 (0x3L<<4)
-#define BNX2_DMA_CONFIG_MAX_PL_XI			 (0x7L<<12)
-#define BNX2_DMA_CONFIG_MAX_PL_128B_XI			 (0L<<12)
-#define BNX2_DMA_CONFIG_MAX_PL_256B_XI			 (1L<<12)
-#define BNX2_DMA_CONFIG_MAX_PL_512B_XI			 (2L<<12)
-#define BNX2_DMA_CONFIG_MAX_PL_EN_XI			 (1L<<15)
-#define BNX2_DMA_CONFIG_MAX_RRS_XI			 (0x7L<<16)
-#define BNX2_DMA_CONFIG_MAX_RRS_128B_XI			 (0L<<16)
-#define BNX2_DMA_CONFIG_MAX_RRS_256B_XI			 (1L<<16)
-#define BNX2_DMA_CONFIG_MAX_RRS_512B_XI			 (2L<<16)
-#define BNX2_DMA_CONFIG_MAX_RRS_1024B_XI		 (3L<<16)
-#define BNX2_DMA_CONFIG_MAX_RRS_2048B_XI		 (4L<<16)
-#define BNX2_DMA_CONFIG_MAX_RRS_4096B_XI		 (5L<<16)
-#define BNX2_DMA_CONFIG_MAX_RRS_EN_XI			 (1L<<19)
-#define BNX2_DMA_CONFIG_NO_64SWAP_EN_XI			 (1L<<31)
-
-#define BNX2_DMA_BLACKOUT				0x00000c0c
-#define BNX2_DMA_BLACKOUT_RD_RETRY_BLACKOUT		 (0xffL<<0)
-#define BNX2_DMA_BLACKOUT_2ND_RD_RETRY_BLACKOUT		 (0xffL<<8)
-#define BNX2_DMA_BLACKOUT_WR_RETRY_BLACKOUT		 (0xffL<<16)
-
-#define BNX2_DMA_READ_MASTER_SETTING_0			0x00000c10
-#define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_NO_SNOOP	 (1L<<0)
-#define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_RELAX_ORDER	 (1L<<1)
-#define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_PRIORITY	 (1L<<2)
-#define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_TRAFFIC_CLASS	 (0x7L<<4)
-#define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_PARAM_EN	 (1L<<7)
-#define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_NO_SNOOP	 (1L<<8)
-#define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_RELAX_ORDER	 (1L<<9)
-#define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_PRIORITY	 (1L<<10)
-#define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_TRAFFIC_CLASS	 (0x7L<<12)
-#define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_PARAM_EN	 (1L<<15)
-#define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_NO_SNOOP	 (1L<<16)
-#define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_RELAX_ORDER	 (1L<<17)
-#define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_PRIORITY	 (1L<<18)
-#define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_TRAFFIC_CLASS	 (0x7L<<20)
-#define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_PARAM_EN	 (1L<<23)
-#define BNX2_DMA_READ_MASTER_SETTING_0_CTX_NO_SNOOP	 (1L<<24)
-#define BNX2_DMA_READ_MASTER_SETTING_0_CTX_RELAX_ORDER	 (1L<<25)
-#define BNX2_DMA_READ_MASTER_SETTING_0_CTX_PRIORITY	 (1L<<26)
-#define BNX2_DMA_READ_MASTER_SETTING_0_CTX_TRAFFIC_CLASS	 (0x7L<<28)
-#define BNX2_DMA_READ_MASTER_SETTING_0_CTX_PARAM_EN	 (1L<<31)
-
-#define BNX2_DMA_READ_MASTER_SETTING_1			0x00000c14
-#define BNX2_DMA_READ_MASTER_SETTING_1_COM_NO_SNOOP	 (1L<<0)
-#define BNX2_DMA_READ_MASTER_SETTING_1_COM_RELAX_ORDER	 (1L<<1)
-#define BNX2_DMA_READ_MASTER_SETTING_1_COM_PRIORITY	 (1L<<2)
-#define BNX2_DMA_READ_MASTER_SETTING_1_COM_TRAFFIC_CLASS	 (0x7L<<4)
-#define BNX2_DMA_READ_MASTER_SETTING_1_COM_PARAM_EN	 (1L<<7)
-#define BNX2_DMA_READ_MASTER_SETTING_1_CP_NO_SNOOP	 (1L<<8)
-#define BNX2_DMA_READ_MASTER_SETTING_1_CP_RELAX_ORDER	 (1L<<9)
-#define BNX2_DMA_READ_MASTER_SETTING_1_CP_PRIORITY	 (1L<<10)
-#define BNX2_DMA_READ_MASTER_SETTING_1_CP_TRAFFIC_CLASS	 (0x7L<<12)
-#define BNX2_DMA_READ_MASTER_SETTING_1_CP_PARAM_EN	 (1L<<15)
-
-#define BNX2_DMA_WRITE_MASTER_SETTING_0			0x00000c18
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_NO_SNOOP	 (1L<<0)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_RELAX_ORDER	 (1L<<1)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_PRIORITY	 (1L<<2)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_CS_VLD	 (1L<<3)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_TRAFFIC_CLASS	 (0x7L<<4)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_PARAM_EN	 (1L<<7)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_NO_SNOOP	 (1L<<8)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_RELAX_ORDER	 (1L<<9)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_PRIORITY	 (1L<<10)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_CS_VLD	 (1L<<11)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_TRAFFIC_CLASS	 (0x7L<<12)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_PARAM_EN	 (1L<<15)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_NO_SNOOP	 (1L<<24)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_RELAX_ORDER	 (1L<<25)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_PRIORITY	 (1L<<26)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_CS_VLD	 (1L<<27)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_TRAFFIC_CLASS	 (0x7L<<28)
-#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_PARAM_EN	 (1L<<31)
-
-#define BNX2_DMA_WRITE_MASTER_SETTING_1			0x00000c1c
-#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_NO_SNOOP	 (1L<<0)
-#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_RELAX_ORDER	 (1L<<1)
-#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_PRIORITY	 (1L<<2)
-#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_CS_VLD	 (1L<<3)
-#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_TRAFFIC_CLASS	 (0x7L<<4)
-#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_PARAM_EN	 (1L<<7)
-#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_NO_SNOOP	 (1L<<8)
-#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_RELAX_ORDER	 (1L<<9)
-#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_PRIORITY	 (1L<<10)
-#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_CS_VLD	 (1L<<11)
-#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_TRAFFIC_CLASS	 (0x7L<<12)
-#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_PARAM_EN	 (1L<<15)
-
-#define BNX2_DMA_ARBITER				0x00000c20
-#define BNX2_DMA_ARBITER_NUM_READS			 (0x7L<<0)
-#define BNX2_DMA_ARBITER_WR_ARB_MODE			 (1L<<4)
-#define BNX2_DMA_ARBITER_WR_ARB_MODE_STRICT		 (0L<<4)
-#define BNX2_DMA_ARBITER_WR_ARB_MODE_RND_RBN		 (1L<<4)
-#define BNX2_DMA_ARBITER_RD_ARB_MODE			 (0x3L<<5)
-#define BNX2_DMA_ARBITER_RD_ARB_MODE_STRICT		 (0L<<5)
-#define BNX2_DMA_ARBITER_RD_ARB_MODE_RND_RBN		 (1L<<5)
-#define BNX2_DMA_ARBITER_RD_ARB_MODE_WGT_RND_RBN	 (2L<<5)
-#define BNX2_DMA_ARBITER_ALT_MODE_EN			 (1L<<8)
-#define BNX2_DMA_ARBITER_RR_MODE			 (1L<<9)
-#define BNX2_DMA_ARBITER_TIMER_MODE			 (1L<<10)
-#define BNX2_DMA_ARBITER_OUSTD_READ_REQ			 (0xfL<<12)
-
-#define BNX2_DMA_ARB_TIMERS				0x00000c24
-#define BNX2_DMA_ARB_TIMERS_RD_DRR_WAIT_TIME		 (0xffL<<0)
-#define BNX2_DMA_ARB_TIMERS_TM_MIN_TIMEOUT		 (0xffL<<12)
-#define BNX2_DMA_ARB_TIMERS_TM_MAX_TIMEOUT		 (0xfffL<<20)
-
-#define BNX2_DMA_DEBUG_VECT_PEEK			0x00000c2c
-#define BNX2_DMA_DEBUG_VECT_PEEK_1_VALUE		 (0x7ffL<<0)
-#define BNX2_DMA_DEBUG_VECT_PEEK_1_PEEK_EN		 (1L<<11)
-#define BNX2_DMA_DEBUG_VECT_PEEK_1_SEL			 (0xfL<<12)
-#define BNX2_DMA_DEBUG_VECT_PEEK_2_VALUE		 (0x7ffL<<16)
-#define BNX2_DMA_DEBUG_VECT_PEEK_2_PEEK_EN		 (1L<<27)
-#define BNX2_DMA_DEBUG_VECT_PEEK_2_SEL			 (0xfL<<28)
-
-#define BNX2_DMA_TAG_RAM_00				0x00000c30
-#define BNX2_DMA_TAG_RAM_00_CHANNEL			 (0xfL<<0)
-#define BNX2_DMA_TAG_RAM_00_MASTER			 (0x7L<<4)
-#define BNX2_DMA_TAG_RAM_00_MASTER_CTX			 (0L<<4)
-#define BNX2_DMA_TAG_RAM_00_MASTER_RBDC			 (1L<<4)
-#define BNX2_DMA_TAG_RAM_00_MASTER_TBDC			 (2L<<4)
-#define BNX2_DMA_TAG_RAM_00_MASTER_COM			 (3L<<4)
-#define BNX2_DMA_TAG_RAM_00_MASTER_CP			 (4L<<4)
-#define BNX2_DMA_TAG_RAM_00_MASTER_TDMA			 (5L<<4)
-#define BNX2_DMA_TAG_RAM_00_SWAP			 (0x3L<<7)
-#define BNX2_DMA_TAG_RAM_00_SWAP_CONFIG			 (0L<<7)
-#define BNX2_DMA_TAG_RAM_00_SWAP_DATA			 (1L<<7)
-#define BNX2_DMA_TAG_RAM_00_SWAP_CONTROL		 (2L<<7)
-#define BNX2_DMA_TAG_RAM_00_FUNCTION			 (1L<<9)
-#define BNX2_DMA_TAG_RAM_00_VALID			 (1L<<10)
-
-#define BNX2_DMA_TAG_RAM_01				0x00000c34
-#define BNX2_DMA_TAG_RAM_01_CHANNEL			 (0xfL<<0)
-#define BNX2_DMA_TAG_RAM_01_MASTER			 (0x7L<<4)
-#define BNX2_DMA_TAG_RAM_01_MASTER_CTX			 (0L<<4)
-#define BNX2_DMA_TAG_RAM_01_MASTER_RBDC			 (1L<<4)
-#define BNX2_DMA_TAG_RAM_01_MASTER_TBDC			 (2L<<4)
-#define BNX2_DMA_TAG_RAM_01_MASTER_COM			 (3L<<4)
-#define BNX2_DMA_TAG_RAM_01_MASTER_CP			 (4L<<4)
-#define BNX2_DMA_TAG_RAM_01_MASTER_TDMA			 (5L<<4)
-#define BNX2_DMA_TAG_RAM_01_SWAP			 (0x3L<<7)
-#define BNX2_DMA_TAG_RAM_01_SWAP_CONFIG			 (0L<<7)
-#define BNX2_DMA_TAG_RAM_01_SWAP_DATA			 (1L<<7)
-#define BNX2_DMA_TAG_RAM_01_SWAP_CONTROL		 (2L<<7)
-#define BNX2_DMA_TAG_RAM_01_FUNCTION			 (1L<<9)
-#define BNX2_DMA_TAG_RAM_01_VALID			 (1L<<10)
-
-#define BNX2_DMA_TAG_RAM_02				0x00000c38
-#define BNX2_DMA_TAG_RAM_02_CHANNEL			 (0xfL<<0)
-#define BNX2_DMA_TAG_RAM_02_MASTER			 (0x7L<<4)
-#define BNX2_DMA_TAG_RAM_02_MASTER_CTX			 (0L<<4)
-#define BNX2_DMA_TAG_RAM_02_MASTER_RBDC			 (1L<<4)
-#define BNX2_DMA_TAG_RAM_02_MASTER_TBDC			 (2L<<4)
-#define BNX2_DMA_TAG_RAM_02_MASTER_COM			 (3L<<4)
-#define BNX2_DMA_TAG_RAM_02_MASTER_CP			 (4L<<4)
-#define BNX2_DMA_TAG_RAM_02_MASTER_TDMA			 (5L<<4)
-#define BNX2_DMA_TAG_RAM_02_SWAP			 (0x3L<<7)
-#define BNX2_DMA_TAG_RAM_02_SWAP_CONFIG			 (0L<<7)
-#define BNX2_DMA_TAG_RAM_02_SWAP_DATA			 (1L<<7)
-#define BNX2_DMA_TAG_RAM_02_SWAP_CONTROL		 (2L<<7)
-#define BNX2_DMA_TAG_RAM_02_FUNCTION			 (1L<<9)
-#define BNX2_DMA_TAG_RAM_02_VALID			 (1L<<10)
-
-#define BNX2_DMA_TAG_RAM_03				0x00000c3c
-#define BNX2_DMA_TAG_RAM_03_CHANNEL			 (0xfL<<0)
-#define BNX2_DMA_TAG_RAM_03_MASTER			 (0x7L<<4)
-#define BNX2_DMA_TAG_RAM_03_MASTER_CTX			 (0L<<4)
-#define BNX2_DMA_TAG_RAM_03_MASTER_RBDC			 (1L<<4)
-#define BNX2_DMA_TAG_RAM_03_MASTER_TBDC			 (2L<<4)
-#define BNX2_DMA_TAG_RAM_03_MASTER_COM			 (3L<<4)
-#define BNX2_DMA_TAG_RAM_03_MASTER_CP			 (4L<<4)
-#define BNX2_DMA_TAG_RAM_03_MASTER_TDMA			 (5L<<4)
-#define BNX2_DMA_TAG_RAM_03_SWAP			 (0x3L<<7)
-#define BNX2_DMA_TAG_RAM_03_SWAP_CONFIG			 (0L<<7)
-#define BNX2_DMA_TAG_RAM_03_SWAP_DATA			 (1L<<7)
-#define BNX2_DMA_TAG_RAM_03_SWAP_CONTROL		 (2L<<7)
-#define BNX2_DMA_TAG_RAM_03_FUNCTION			 (1L<<9)
-#define BNX2_DMA_TAG_RAM_03_VALID			 (1L<<10)
-
-#define BNX2_DMA_TAG_RAM_04				0x00000c40
-#define BNX2_DMA_TAG_RAM_04_CHANNEL			 (0xfL<<0)
-#define BNX2_DMA_TAG_RAM_04_MASTER			 (0x7L<<4)
-#define BNX2_DMA_TAG_RAM_04_MASTER_CTX			 (0L<<4)
-#define BNX2_DMA_TAG_RAM_04_MASTER_RBDC			 (1L<<4)
-#define BNX2_DMA_TAG_RAM_04_MASTER_TBDC			 (2L<<4)
-#define BNX2_DMA_TAG_RAM_04_MASTER_COM			 (3L<<4)
-#define BNX2_DMA_TAG_RAM_04_MASTER_CP			 (4L<<4)
-#define BNX2_DMA_TAG_RAM_04_MASTER_TDMA			 (5L<<4)
-#define BNX2_DMA_TAG_RAM_04_SWAP			 (0x3L<<7)
-#define BNX2_DMA_TAG_RAM_04_SWAP_CONFIG			 (0L<<7)
-#define BNX2_DMA_TAG_RAM_04_SWAP_DATA			 (1L<<7)
-#define BNX2_DMA_TAG_RAM_04_SWAP_CONTROL		 (2L<<7)
-#define BNX2_DMA_TAG_RAM_04_FUNCTION			 (1L<<9)
-#define BNX2_DMA_TAG_RAM_04_VALID			 (1L<<10)
-
-#define BNX2_DMA_TAG_RAM_05				0x00000c44
-#define BNX2_DMA_TAG_RAM_05_CHANNEL			 (0xfL<<0)
-#define BNX2_DMA_TAG_RAM_05_MASTER			 (0x7L<<4)
-#define BNX2_DMA_TAG_RAM_05_MASTER_CTX			 (0L<<4)
-#define BNX2_DMA_TAG_RAM_05_MASTER_RBDC			 (1L<<4)
-#define BNX2_DMA_TAG_RAM_05_MASTER_TBDC			 (2L<<4)
-#define BNX2_DMA_TAG_RAM_05_MASTER_COM			 (3L<<4)
-#define BNX2_DMA_TAG_RAM_05_MASTER_CP			 (4L<<4)
-#define BNX2_DMA_TAG_RAM_05_MASTER_TDMA			 (5L<<4)
-#define BNX2_DMA_TAG_RAM_05_SWAP			 (0x3L<<7)
-#define BNX2_DMA_TAG_RAM_05_SWAP_CONFIG			 (0L<<7)
-#define BNX2_DMA_TAG_RAM_05_SWAP_DATA			 (1L<<7)
-#define BNX2_DMA_TAG_RAM_05_SWAP_CONTROL		 (2L<<7)
-#define BNX2_DMA_TAG_RAM_05_FUNCTION			 (1L<<9)
-#define BNX2_DMA_TAG_RAM_05_VALID			 (1L<<10)
-
-#define BNX2_DMA_TAG_RAM_06				0x00000c48
-#define BNX2_DMA_TAG_RAM_06_CHANNEL			 (0xfL<<0)
-#define BNX2_DMA_TAG_RAM_06_MASTER			 (0x7L<<4)
-#define BNX2_DMA_TAG_RAM_06_MASTER_CTX			 (0L<<4)
-#define BNX2_DMA_TAG_RAM_06_MASTER_RBDC			 (1L<<4)
-#define BNX2_DMA_TAG_RAM_06_MASTER_TBDC			 (2L<<4)
-#define BNX2_DMA_TAG_RAM_06_MASTER_COM			 (3L<<4)
-#define BNX2_DMA_TAG_RAM_06_MASTER_CP			 (4L<<4)
-#define BNX2_DMA_TAG_RAM_06_MASTER_TDMA			 (5L<<4)
-#define BNX2_DMA_TAG_RAM_06_SWAP			 (0x3L<<7)
-#define BNX2_DMA_TAG_RAM_06_SWAP_CONFIG			 (0L<<7)
-#define BNX2_DMA_TAG_RAM_06_SWAP_DATA			 (1L<<7)
-#define BNX2_DMA_TAG_RAM_06_SWAP_CONTROL		 (2L<<7)
-#define BNX2_DMA_TAG_RAM_06_FUNCTION			 (1L<<9)
-#define BNX2_DMA_TAG_RAM_06_VALID			 (1L<<10)
-
-#define BNX2_DMA_TAG_RAM_07				0x00000c4c
-#define BNX2_DMA_TAG_RAM_07_CHANNEL			 (0xfL<<0)
-#define BNX2_DMA_TAG_RAM_07_MASTER			 (0x7L<<4)
-#define BNX2_DMA_TAG_RAM_07_MASTER_CTX			 (0L<<4)
-#define BNX2_DMA_TAG_RAM_07_MASTER_RBDC			 (1L<<4)
-#define BNX2_DMA_TAG_RAM_07_MASTER_TBDC			 (2L<<4)
-#define BNX2_DMA_TAG_RAM_07_MASTER_COM			 (3L<<4)
-#define BNX2_DMA_TAG_RAM_07_MASTER_CP			 (4L<<4)
-#define BNX2_DMA_TAG_RAM_07_MASTER_TDMA			 (5L<<4)
-#define BNX2_DMA_TAG_RAM_07_SWAP			 (0x3L<<7)
-#define BNX2_DMA_TAG_RAM_07_SWAP_CONFIG			 (0L<<7)
-#define BNX2_DMA_TAG_RAM_07_SWAP_DATA			 (1L<<7)
-#define BNX2_DMA_TAG_RAM_07_SWAP_CONTROL		 (2L<<7)
-#define BNX2_DMA_TAG_RAM_07_FUNCTION			 (1L<<9)
-#define BNX2_DMA_TAG_RAM_07_VALID			 (1L<<10)
-
-#define BNX2_DMA_TAG_RAM_08				0x00000c50
-#define BNX2_DMA_TAG_RAM_08_CHANNEL			 (0xfL<<0)
-#define BNX2_DMA_TAG_RAM_08_MASTER			 (0x7L<<4)
-#define BNX2_DMA_TAG_RAM_08_MASTER_CTX			 (0L<<4)
-#define BNX2_DMA_TAG_RAM_08_MASTER_RBDC			 (1L<<4)
-#define BNX2_DMA_TAG_RAM_08_MASTER_TBDC			 (2L<<4)
-#define BNX2_DMA_TAG_RAM_08_MASTER_COM			 (3L<<4)
-#define BNX2_DMA_TAG_RAM_08_MASTER_CP			 (4L<<4)
-#define BNX2_DMA_TAG_RAM_08_MASTER_TDMA			 (5L<<4)
-#define BNX2_DMA_TAG_RAM_08_SWAP			 (0x3L<<7)
-#define BNX2_DMA_TAG_RAM_08_SWAP_CONFIG			 (0L<<7)
-#define BNX2_DMA_TAG_RAM_08_SWAP_DATA			 (1L<<7)
-#define BNX2_DMA_TAG_RAM_08_SWAP_CONTROL		 (2L<<7)
-#define BNX2_DMA_TAG_RAM_08_FUNCTION			 (1L<<9)
-#define BNX2_DMA_TAG_RAM_08_VALID			 (1L<<10)
-
-#define BNX2_DMA_TAG_RAM_09				0x00000c54
-#define BNX2_DMA_TAG_RAM_09_CHANNEL			 (0xfL<<0)
-#define BNX2_DMA_TAG_RAM_09_MASTER			 (0x7L<<4)
-#define BNX2_DMA_TAG_RAM_09_MASTER_CTX			 (0L<<4)
-#define BNX2_DMA_TAG_RAM_09_MASTER_RBDC			 (1L<<4)
-#define BNX2_DMA_TAG_RAM_09_MASTER_TBDC			 (2L<<4)
-#define BNX2_DMA_TAG_RAM_09_MASTER_COM			 (3L<<4)
-#define BNX2_DMA_TAG_RAM_09_MASTER_CP			 (4L<<4)
-#define BNX2_DMA_TAG_RAM_09_MASTER_TDMA			 (5L<<4)
-#define BNX2_DMA_TAG_RAM_09_SWAP			 (0x3L<<7)
-#define BNX2_DMA_TAG_RAM_09_SWAP_CONFIG			 (0L<<7)
-#define BNX2_DMA_TAG_RAM_09_SWAP_DATA			 (1L<<7)
-#define BNX2_DMA_TAG_RAM_09_SWAP_CONTROL		 (2L<<7)
-#define BNX2_DMA_TAG_RAM_09_FUNCTION			 (1L<<9)
-#define BNX2_DMA_TAG_RAM_09_VALID			 (1L<<10)
-
-#define BNX2_DMA_TAG_RAM_10				0x00000c58
-#define BNX2_DMA_TAG_RAM_10_CHANNEL			 (0xfL<<0)
-#define BNX2_DMA_TAG_RAM_10_MASTER			 (0x7L<<4)
-#define BNX2_DMA_TAG_RAM_10_MASTER_CTX			 (0L<<4)
-#define BNX2_DMA_TAG_RAM_10_MASTER_RBDC			 (1L<<4)
-#define BNX2_DMA_TAG_RAM_10_MASTER_TBDC			 (2L<<4)
-#define BNX2_DMA_TAG_RAM_10_MASTER_COM			 (3L<<4)
-#define BNX2_DMA_TAG_RAM_10_MASTER_CP			 (4L<<4)
-#define BNX2_DMA_TAG_RAM_10_MASTER_TDMA			 (5L<<4)
-#define BNX2_DMA_TAG_RAM_10_SWAP			 (0x3L<<7)
-#define BNX2_DMA_TAG_RAM_10_SWAP_CONFIG			 (0L<<7)
-#define BNX2_DMA_TAG_RAM_10_SWAP_DATA			 (1L<<7)
-#define BNX2_DMA_TAG_RAM_10_SWAP_CONTROL		 (2L<<7)
-#define BNX2_DMA_TAG_RAM_10_FUNCTION			 (1L<<9)
-#define BNX2_DMA_TAG_RAM_10_VALID			 (1L<<10)
-
-#define BNX2_DMA_TAG_RAM_11				0x00000c5c
-#define BNX2_DMA_TAG_RAM_11_CHANNEL			 (0xfL<<0)
-#define BNX2_DMA_TAG_RAM_11_MASTER			 (0x7L<<4)
-#define BNX2_DMA_TAG_RAM_11_MASTER_CTX			 (0L<<4)
-#define BNX2_DMA_TAG_RAM_11_MASTER_RBDC			 (1L<<4)
-#define BNX2_DMA_TAG_RAM_11_MASTER_TBDC			 (2L<<4)
-#define BNX2_DMA_TAG_RAM_11_MASTER_COM			 (3L<<4)
-#define BNX2_DMA_TAG_RAM_11_MASTER_CP			 (4L<<4)
-#define BNX2_DMA_TAG_RAM_11_MASTER_TDMA			 (5L<<4)
-#define BNX2_DMA_TAG_RAM_11_SWAP			 (0x3L<<7)
-#define BNX2_DMA_TAG_RAM_11_SWAP_CONFIG			 (0L<<7)
-#define BNX2_DMA_TAG_RAM_11_SWAP_DATA			 (1L<<7)
-#define BNX2_DMA_TAG_RAM_11_SWAP_CONTROL		 (2L<<7)
-#define BNX2_DMA_TAG_RAM_11_FUNCTION			 (1L<<9)
-#define BNX2_DMA_TAG_RAM_11_VALID			 (1L<<10)
-
-#define BNX2_DMA_RCHAN_STAT_22				0x00000c60
-#define BNX2_DMA_RCHAN_STAT_30				0x00000c64
-#define BNX2_DMA_RCHAN_STAT_31				0x00000c68
-#define BNX2_DMA_RCHAN_STAT_32				0x00000c6c
-#define BNX2_DMA_RCHAN_STAT_40				0x00000c70
-#define BNX2_DMA_RCHAN_STAT_41				0x00000c74
-#define BNX2_DMA_RCHAN_STAT_42				0x00000c78
-#define BNX2_DMA_RCHAN_STAT_50				0x00000c7c
-#define BNX2_DMA_RCHAN_STAT_51				0x00000c80
-#define BNX2_DMA_RCHAN_STAT_52				0x00000c84
-#define BNX2_DMA_RCHAN_STAT_60				0x00000c88
-#define BNX2_DMA_RCHAN_STAT_61				0x00000c8c
-#define BNX2_DMA_RCHAN_STAT_62				0x00000c90
-#define BNX2_DMA_RCHAN_STAT_70				0x00000c94
-#define BNX2_DMA_RCHAN_STAT_71				0x00000c98
-#define BNX2_DMA_RCHAN_STAT_72				0x00000c9c
-#define BNX2_DMA_WCHAN_STAT_00				0x00000ca0
-#define BNX2_DMA_WCHAN_STAT_00_WCHAN_STA_HOST_ADDR_LOW	 (0xffffffffL<<0)
-
-#define BNX2_DMA_WCHAN_STAT_01				0x00000ca4
-#define BNX2_DMA_WCHAN_STAT_01_WCHAN_STA_HOST_ADDR_HIGH	 (0xffffffffL<<0)
-
-#define BNX2_DMA_WCHAN_STAT_02				0x00000ca8
-#define BNX2_DMA_WCHAN_STAT_02_LENGTH			 (0xffffL<<0)
-#define BNX2_DMA_WCHAN_STAT_02_WORD_SWAP		 (1L<<16)
-#define BNX2_DMA_WCHAN_STAT_02_BYTE_SWAP		 (1L<<17)
-#define BNX2_DMA_WCHAN_STAT_02_PRIORITY_LVL		 (1L<<18)
-
-#define BNX2_DMA_WCHAN_STAT_10				0x00000cac
-#define BNX2_DMA_WCHAN_STAT_11				0x00000cb0
-#define BNX2_DMA_WCHAN_STAT_12				0x00000cb4
-#define BNX2_DMA_WCHAN_STAT_20				0x00000cb8
-#define BNX2_DMA_WCHAN_STAT_21				0x00000cbc
-#define BNX2_DMA_WCHAN_STAT_22				0x00000cc0
-#define BNX2_DMA_WCHAN_STAT_30				0x00000cc4
-#define BNX2_DMA_WCHAN_STAT_31				0x00000cc8
-#define BNX2_DMA_WCHAN_STAT_32				0x00000ccc
-#define BNX2_DMA_WCHAN_STAT_40				0x00000cd0
-#define BNX2_DMA_WCHAN_STAT_41				0x00000cd4
-#define BNX2_DMA_WCHAN_STAT_42				0x00000cd8
-#define BNX2_DMA_WCHAN_STAT_50				0x00000cdc
-#define BNX2_DMA_WCHAN_STAT_51				0x00000ce0
-#define BNX2_DMA_WCHAN_STAT_52				0x00000ce4
-#define BNX2_DMA_WCHAN_STAT_60				0x00000ce8
-#define BNX2_DMA_WCHAN_STAT_61				0x00000cec
-#define BNX2_DMA_WCHAN_STAT_62				0x00000cf0
-#define BNX2_DMA_WCHAN_STAT_70				0x00000cf4
-#define BNX2_DMA_WCHAN_STAT_71				0x00000cf8
-#define BNX2_DMA_WCHAN_STAT_72				0x00000cfc
-#define BNX2_DMA_ARB_STAT_00				0x00000d00
-#define BNX2_DMA_ARB_STAT_00_MASTER			 (0xffffL<<0)
-#define BNX2_DMA_ARB_STAT_00_MASTER_ENC			 (0xffL<<16)
-#define BNX2_DMA_ARB_STAT_00_CUR_BINMSTR		 (0xffL<<24)
-
-#define BNX2_DMA_ARB_STAT_01				0x00000d04
-#define BNX2_DMA_ARB_STAT_01_LPR_RPTR			 (0xfL<<0)
-#define BNX2_DMA_ARB_STAT_01_LPR_WPTR			 (0xfL<<4)
-#define BNX2_DMA_ARB_STAT_01_LPB_RPTR			 (0xfL<<8)
-#define BNX2_DMA_ARB_STAT_01_LPB_WPTR			 (0xfL<<12)
-#define BNX2_DMA_ARB_STAT_01_HPR_RPTR			 (0xfL<<16)
-#define BNX2_DMA_ARB_STAT_01_HPR_WPTR			 (0xfL<<20)
-#define BNX2_DMA_ARB_STAT_01_HPB_RPTR			 (0xfL<<24)
-#define BNX2_DMA_ARB_STAT_01_HPB_WPTR			 (0xfL<<28)
-
-#define BNX2_DMA_FUSE_CTRL0_CMD				0x00000f00
-#define BNX2_DMA_FUSE_CTRL0_CMD_PWRUP_DONE		 (1L<<0)
-#define BNX2_DMA_FUSE_CTRL0_CMD_SHIFT_DONE		 (1L<<1)
-#define BNX2_DMA_FUSE_CTRL0_CMD_SHIFT			 (1L<<2)
-#define BNX2_DMA_FUSE_CTRL0_CMD_LOAD			 (1L<<3)
-#define BNX2_DMA_FUSE_CTRL0_CMD_SEL			 (0xfL<<8)
-
-#define BNX2_DMA_FUSE_CTRL0_DATA			0x00000f04
-#define BNX2_DMA_FUSE_CTRL1_CMD				0x00000f08
-#define BNX2_DMA_FUSE_CTRL1_CMD_PWRUP_DONE		 (1L<<0)
-#define BNX2_DMA_FUSE_CTRL1_CMD_SHIFT_DONE		 (1L<<1)
-#define BNX2_DMA_FUSE_CTRL1_CMD_SHIFT			 (1L<<2)
-#define BNX2_DMA_FUSE_CTRL1_CMD_LOAD			 (1L<<3)
-#define BNX2_DMA_FUSE_CTRL1_CMD_SEL			 (0xfL<<8)
-
-#define BNX2_DMA_FUSE_CTRL1_DATA			0x00000f0c
-#define BNX2_DMA_FUSE_CTRL2_CMD				0x00000f10
-#define BNX2_DMA_FUSE_CTRL2_CMD_PWRUP_DONE		 (1L<<0)
-#define BNX2_DMA_FUSE_CTRL2_CMD_SHIFT_DONE		 (1L<<1)
-#define BNX2_DMA_FUSE_CTRL2_CMD_SHIFT			 (1L<<2)
-#define BNX2_DMA_FUSE_CTRL2_CMD_LOAD			 (1L<<3)
-#define BNX2_DMA_FUSE_CTRL2_CMD_SEL			 (0xfL<<8)
-
-#define BNX2_DMA_FUSE_CTRL2_DATA			0x00000f14
-
-
-/*
- *  context_reg definition
- *  offset: 0x1000
- */
-#define BNX2_CTX_COMMAND				0x00001000
-#define BNX2_CTX_COMMAND_ENABLED			 (1L<<0)
-#define BNX2_CTX_COMMAND_DISABLE_USAGE_CNT		 (1L<<1)
-#define BNX2_CTX_COMMAND_DISABLE_PLRU			 (1L<<2)
-#define BNX2_CTX_COMMAND_DISABLE_COMBINE_READ		 (1L<<3)
-#define BNX2_CTX_COMMAND_FLUSH_AHEAD			 (0x1fL<<8)
-#define BNX2_CTX_COMMAND_MEM_INIT			 (1L<<13)
-#define BNX2_CTX_COMMAND_PAGE_SIZE			 (0xfL<<16)
-#define BNX2_CTX_COMMAND_PAGE_SIZE_256			 (0L<<16)
-#define BNX2_CTX_COMMAND_PAGE_SIZE_512			 (1L<<16)
-#define BNX2_CTX_COMMAND_PAGE_SIZE_1K			 (2L<<16)
-#define BNX2_CTX_COMMAND_PAGE_SIZE_2K			 (3L<<16)
-#define BNX2_CTX_COMMAND_PAGE_SIZE_4K			 (4L<<16)
-#define BNX2_CTX_COMMAND_PAGE_SIZE_8K			 (5L<<16)
-#define BNX2_CTX_COMMAND_PAGE_SIZE_16K			 (6L<<16)
-#define BNX2_CTX_COMMAND_PAGE_SIZE_32K			 (7L<<16)
-#define BNX2_CTX_COMMAND_PAGE_SIZE_64K			 (8L<<16)
-#define BNX2_CTX_COMMAND_PAGE_SIZE_128K			 (9L<<16)
-#define BNX2_CTX_COMMAND_PAGE_SIZE_256K			 (10L<<16)
-#define BNX2_CTX_COMMAND_PAGE_SIZE_512K			 (11L<<16)
-#define BNX2_CTX_COMMAND_PAGE_SIZE_1M			 (12L<<16)
-
-#define BNX2_CTX_STATUS					0x00001004
-#define BNX2_CTX_STATUS_LOCK_WAIT			 (1L<<0)
-#define BNX2_CTX_STATUS_READ_STAT			 (1L<<16)
-#define BNX2_CTX_STATUS_WRITE_STAT			 (1L<<17)
-#define BNX2_CTX_STATUS_ACC_STALL_STAT			 (1L<<18)
-#define BNX2_CTX_STATUS_LOCK_STALL_STAT			 (1L<<19)
-#define BNX2_CTX_STATUS_EXT_READ_STAT			 (1L<<20)
-#define BNX2_CTX_STATUS_EXT_WRITE_STAT			 (1L<<21)
-#define BNX2_CTX_STATUS_MISS_STAT			 (1L<<22)
-#define BNX2_CTX_STATUS_HIT_STAT			 (1L<<23)
-#define BNX2_CTX_STATUS_DEAD_LOCK			 (1L<<24)
-#define BNX2_CTX_STATUS_USAGE_CNT_ERR			 (1L<<25)
-#define BNX2_CTX_STATUS_INVALID_PAGE			 (1L<<26)
-
-#define BNX2_CTX_VIRT_ADDR				0x00001008
-#define BNX2_CTX_VIRT_ADDR_VIRT_ADDR			 (0x7fffL<<6)
-
-#define BNX2_CTX_PAGE_TBL				0x0000100c
-#define BNX2_CTX_PAGE_TBL_PAGE_TBL			 (0x3fffL<<6)
-
-#define BNX2_CTX_DATA_ADR				0x00001010
-#define BNX2_CTX_DATA_ADR_DATA_ADR			 (0x7ffffL<<2)
-
-#define BNX2_CTX_DATA					0x00001014
-#define BNX2_CTX_LOCK					0x00001018
-#define BNX2_CTX_LOCK_TYPE				 (0x7L<<0)
-#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_VOID		 (0x0L<<0)
-#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_PROTOCOL		 (0x1L<<0)
-#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TX			 (0x2L<<0)
-#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TIMER		 (0x4L<<0)
-#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_COMPLETE		 (0x7L<<0)
-#define BNX2_CTX_LOCK_TYPE_VOID_XI			 (0L<<0)
-#define BNX2_CTX_LOCK_TYPE_PROTOCOL_XI			 (1L<<0)
-#define BNX2_CTX_LOCK_TYPE_TX_XI			 (2L<<0)
-#define BNX2_CTX_LOCK_TYPE_TIMER_XI			 (4L<<0)
-#define BNX2_CTX_LOCK_TYPE_COMPLETE_XI			 (7L<<0)
-#define BNX2_CTX_LOCK_CID_VALUE				 (0x3fffL<<7)
-#define BNX2_CTX_LOCK_GRANTED				 (1L<<26)
-#define BNX2_CTX_LOCK_MODE				 (0x7L<<27)
-#define BNX2_CTX_LOCK_MODE_UNLOCK			 (0x0L<<27)
-#define BNX2_CTX_LOCK_MODE_IMMEDIATE			 (0x1L<<27)
-#define BNX2_CTX_LOCK_MODE_SURE				 (0x2L<<27)
-#define BNX2_CTX_LOCK_STATUS				 (1L<<30)
-#define BNX2_CTX_LOCK_REQ				 (1L<<31)
-
-#define BNX2_CTX_CTX_CTRL				0x0000101c
-#define BNX2_CTX_CTX_CTRL_CTX_ADDR			 (0x7ffffL<<2)
-#define BNX2_CTX_CTX_CTRL_MOD_USAGE_CNT			 (0x3L<<21)
-#define BNX2_CTX_CTX_CTRL_NO_RAM_ACC			 (1L<<23)
-#define BNX2_CTX_CTX_CTRL_PREFETCH_SIZE			 (0x3L<<24)
-#define BNX2_CTX_CTX_CTRL_ATTR				 (1L<<26)
-#define BNX2_CTX_CTX_CTRL_WRITE_REQ			 (1L<<30)
-#define BNX2_CTX_CTX_CTRL_READ_REQ			 (1L<<31)
-
-#define BNX2_CTX_CTX_DATA				0x00001020
-#define BNX2_CTX_ACCESS_STATUS				0x00001040
-#define BNX2_CTX_ACCESS_STATUS_MASTERENCODED		 (0xfL<<0)
-#define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYSM		 (0x3L<<10)
-#define BNX2_CTX_ACCESS_STATUS_PAGETABLEINITSM		 (0x3L<<12)
-#define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYINITSM	 (0x3L<<14)
-#define BNX2_CTX_ACCESS_STATUS_QUALIFIED_REQUEST	 (0x7ffL<<17)
-#define BNX2_CTX_ACCESS_STATUS_CAMMASTERENCODED_XI	 (0x1fL<<0)
-#define BNX2_CTX_ACCESS_STATUS_CACHEMASTERENCODED_XI	 (0x1fL<<5)
-#define BNX2_CTX_ACCESS_STATUS_REQUEST_XI		 (0x3fffffL<<10)
-
-#define BNX2_CTX_DBG_LOCK_STATUS			0x00001044
-#define BNX2_CTX_DBG_LOCK_STATUS_SM			 (0x3ffL<<0)
-#define BNX2_CTX_DBG_LOCK_STATUS_MATCH			 (0x3ffL<<22)
-
-#define BNX2_CTX_CACHE_CTRL_STATUS			0x00001048
-#define BNX2_CTX_CACHE_CTRL_STATUS_RFIFO_OVERFLOW	 (1L<<0)
-#define BNX2_CTX_CACHE_CTRL_STATUS_INVALID_READ_COMP	 (1L<<1)
-#define BNX2_CTX_CACHE_CTRL_STATUS_FLUSH_START		 (1L<<6)
-#define BNX2_CTX_CACHE_CTRL_STATUS_FREE_ENTRY_CNT	 (0x3fL<<7)
-#define BNX2_CTX_CACHE_CTRL_STATUS_CACHE_ENTRY_NEEDED	 (0x3fL<<13)
-#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN0_ACTIVE	 (1L<<19)
-#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN1_ACTIVE	 (1L<<20)
-#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN2_ACTIVE	 (1L<<21)
-#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN3_ACTIVE	 (1L<<22)
-#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN4_ACTIVE	 (1L<<23)
-#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN5_ACTIVE	 (1L<<24)
-#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN6_ACTIVE	 (1L<<25)
-#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN7_ACTIVE	 (1L<<26)
-#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN8_ACTIVE	 (1L<<27)
-#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN9_ACTIVE	 (1L<<28)
-#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN10_ACTIVE	 (1L<<29)
-
-#define BNX2_CTX_CACHE_CTRL_SM_STATUS			0x0000104c
-#define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_DWC		 (0x7L<<0)
-#define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_WFIFOC		 (0x7L<<3)
-#define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_RTAGC		 (0x7L<<6)
-#define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_RFIFOC		 (0x7L<<9)
-#define BNX2_CTX_CACHE_CTRL_SM_STATUS_INVALID_BLK_ADDR	 (0x7fffL<<16)
-
-#define BNX2_CTX_CACHE_STATUS				0x00001050
-#define BNX2_CTX_CACHE_STATUS_HELD_ENTRIES		 (0x3ffL<<0)
-#define BNX2_CTX_CACHE_STATUS_MAX_HELD_ENTRIES		 (0x3ffL<<16)
-
-#define BNX2_CTX_DMA_STATUS				0x00001054
-#define BNX2_CTX_DMA_STATUS_RD_CHAN0_STATUS		 (0x3L<<0)
-#define BNX2_CTX_DMA_STATUS_RD_CHAN1_STATUS		 (0x3L<<2)
-#define BNX2_CTX_DMA_STATUS_RD_CHAN2_STATUS		 (0x3L<<4)
-#define BNX2_CTX_DMA_STATUS_RD_CHAN3_STATUS		 (0x3L<<6)
-#define BNX2_CTX_DMA_STATUS_RD_CHAN4_STATUS		 (0x3L<<8)
-#define BNX2_CTX_DMA_STATUS_RD_CHAN5_STATUS		 (0x3L<<10)
-#define BNX2_CTX_DMA_STATUS_RD_CHAN6_STATUS		 (0x3L<<12)
-#define BNX2_CTX_DMA_STATUS_RD_CHAN7_STATUS		 (0x3L<<14)
-#define BNX2_CTX_DMA_STATUS_RD_CHAN8_STATUS		 (0x3L<<16)
-#define BNX2_CTX_DMA_STATUS_RD_CHAN9_STATUS		 (0x3L<<18)
-#define BNX2_CTX_DMA_STATUS_RD_CHAN10_STATUS		 (0x3L<<20)
-
-#define BNX2_CTX_REP_STATUS				0x00001058
-#define BNX2_CTX_REP_STATUS_ERROR_ENTRY			 (0x3ffL<<0)
-#define BNX2_CTX_REP_STATUS_ERROR_CLIENT_ID		 (0x1fL<<10)
-#define BNX2_CTX_REP_STATUS_USAGE_CNT_MAX_ERR		 (1L<<16)
-#define BNX2_CTX_REP_STATUS_USAGE_CNT_MIN_ERR		 (1L<<17)
-#define BNX2_CTX_REP_STATUS_USAGE_CNT_MISS_ERR		 (1L<<18)
-
-#define BNX2_CTX_CKSUM_ERROR_STATUS			0x0000105c
-#define BNX2_CTX_CKSUM_ERROR_STATUS_CALCULATED		 (0xffffL<<0)
-#define BNX2_CTX_CKSUM_ERROR_STATUS_EXPECTED		 (0xffffL<<16)
-
-#define BNX2_CTX_CHNL_LOCK_STATUS_0			0x00001080
-#define BNX2_CTX_CHNL_LOCK_STATUS_0_CID			 (0x3fffL<<0)
-#define BNX2_CTX_CHNL_LOCK_STATUS_0_TYPE		 (0x3L<<14)
-#define BNX2_CTX_CHNL_LOCK_STATUS_0_MODE		 (1L<<16)
-#define BNX2_CTX_CHNL_LOCK_STATUS_0_MODE_XI		 (1L<<14)
-#define BNX2_CTX_CHNL_LOCK_STATUS_0_TYPE_XI		 (0x7L<<15)
-
-#define BNX2_CTX_CHNL_LOCK_STATUS_1			0x00001084
-#define BNX2_CTX_CHNL_LOCK_STATUS_2			0x00001088
-#define BNX2_CTX_CHNL_LOCK_STATUS_3			0x0000108c
-#define BNX2_CTX_CHNL_LOCK_STATUS_4			0x00001090
-#define BNX2_CTX_CHNL_LOCK_STATUS_5			0x00001094
-#define BNX2_CTX_CHNL_LOCK_STATUS_6			0x00001098
-#define BNX2_CTX_CHNL_LOCK_STATUS_7			0x0000109c
-#define BNX2_CTX_CHNL_LOCK_STATUS_8			0x000010a0
-#define BNX2_CTX_CHNL_LOCK_STATUS_9			0x000010a4
-
-#define BNX2_CTX_CACHE_DATA				0x000010c4
-#define BNX2_CTX_HOST_PAGE_TBL_CTRL			0x000010c8
-#define BNX2_CTX_HOST_PAGE_TBL_CTRL_PAGE_TBL_ADDR	 (0x1ffL<<0)
-#define BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ		 (1L<<30)
-#define BNX2_CTX_HOST_PAGE_TBL_CTRL_READ_REQ		 (1L<<31)
-
-#define BNX2_CTX_HOST_PAGE_TBL_DATA0			0x000010cc
-#define BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID		 (1L<<0)
-#define BNX2_CTX_HOST_PAGE_TBL_DATA0_VALUE		 (0xffffffL<<8)
-
-#define BNX2_CTX_HOST_PAGE_TBL_DATA1			0x000010d0
-#define BNX2_CTX_CAM_CTRL				0x000010d4
-#define BNX2_CTX_CAM_CTRL_CAM_ADDR			 (0x3ffL<<0)
-#define BNX2_CTX_CAM_CTRL_RESET				 (1L<<27)
-#define BNX2_CTX_CAM_CTRL_INVALIDATE			 (1L<<28)
-#define BNX2_CTX_CAM_CTRL_SEARCH			 (1L<<29)
-#define BNX2_CTX_CAM_CTRL_WRITE_REQ			 (1L<<30)
-#define BNX2_CTX_CAM_CTRL_READ_REQ			 (1L<<31)
-
-
-/*
- *  emac_reg definition
- *  offset: 0x1400
- */
-#define BNX2_EMAC_MODE					0x00001400
-#define BNX2_EMAC_MODE_RESET				 (1L<<0)
-#define BNX2_EMAC_MODE_HALF_DUPLEX			 (1L<<1)
-#define BNX2_EMAC_MODE_PORT				 (0x3L<<2)
-#define BNX2_EMAC_MODE_PORT_NONE			 (0L<<2)
-#define BNX2_EMAC_MODE_PORT_MII				 (1L<<2)
-#define BNX2_EMAC_MODE_PORT_GMII			 (2L<<2)
-#define BNX2_EMAC_MODE_PORT_MII_10M			 (3L<<2)
-#define BNX2_EMAC_MODE_MAC_LOOP				 (1L<<4)
-#define BNX2_EMAC_MODE_25G_MODE				 (1L<<5)
-#define BNX2_EMAC_MODE_TAGGED_MAC_CTL			 (1L<<7)
-#define BNX2_EMAC_MODE_TX_BURST				 (1L<<8)
-#define BNX2_EMAC_MODE_MAX_DEFER_DROP_ENA		 (1L<<9)
-#define BNX2_EMAC_MODE_EXT_LINK_POL			 (1L<<10)
-#define BNX2_EMAC_MODE_FORCE_LINK			 (1L<<11)
-#define BNX2_EMAC_MODE_SERDES_MODE			 (1L<<12)
-#define BNX2_EMAC_MODE_BOND_OVRD			 (1L<<13)
-#define BNX2_EMAC_MODE_MPKT				 (1L<<18)
-#define BNX2_EMAC_MODE_MPKT_RCVD			 (1L<<19)
-#define BNX2_EMAC_MODE_ACPI_RCVD			 (1L<<20)
-
-#define BNX2_EMAC_STATUS				0x00001404
-#define BNX2_EMAC_STATUS_LINK				 (1L<<11)
-#define BNX2_EMAC_STATUS_LINK_CHANGE			 (1L<<12)
-#define BNX2_EMAC_STATUS_SERDES_AUTONEG_COMPLETE	 (1L<<13)
-#define BNX2_EMAC_STATUS_SERDES_AUTONEG_CHANGE		 (1L<<14)
-#define BNX2_EMAC_STATUS_SERDES_NXT_PG_CHANGE		 (1L<<16)
-#define BNX2_EMAC_STATUS_SERDES_RX_CONFIG_IS_0		 (1L<<17)
-#define BNX2_EMAC_STATUS_SERDES_RX_CONFIG_IS_0_CHANGE	 (1L<<18)
-#define BNX2_EMAC_STATUS_MI_COMPLETE			 (1L<<22)
-#define BNX2_EMAC_STATUS_MI_INT				 (1L<<23)
-#define BNX2_EMAC_STATUS_AP_ERROR			 (1L<<24)
-#define BNX2_EMAC_STATUS_PARITY_ERROR_STATE		 (1L<<31)
-
-#define BNX2_EMAC_ATTENTION_ENA				0x00001408
-#define BNX2_EMAC_ATTENTION_ENA_LINK			 (1L<<11)
-#define BNX2_EMAC_ATTENTION_ENA_AUTONEG_CHANGE		 (1L<<14)
-#define BNX2_EMAC_ATTENTION_ENA_NXT_PG_CHANGE		 (1L<<16)
-#define BNX2_EMAC_ATTENTION_ENA_SERDES_RX_CONFIG_IS_0_CHANGE	 (1L<<18)
-#define BNX2_EMAC_ATTENTION_ENA_MI_COMPLETE		 (1L<<22)
-#define BNX2_EMAC_ATTENTION_ENA_MI_INT			 (1L<<23)
-#define BNX2_EMAC_ATTENTION_ENA_AP_ERROR		 (1L<<24)
-
-#define BNX2_EMAC_LED					0x0000140c
-#define BNX2_EMAC_LED_OVERRIDE				 (1L<<0)
-#define BNX2_EMAC_LED_1000MB_OVERRIDE			 (1L<<1)
-#define BNX2_EMAC_LED_100MB_OVERRIDE			 (1L<<2)
-#define BNX2_EMAC_LED_10MB_OVERRIDE			 (1L<<3)
-#define BNX2_EMAC_LED_TRAFFIC_OVERRIDE			 (1L<<4)
-#define BNX2_EMAC_LED_BLNK_TRAFFIC			 (1L<<5)
-#define BNX2_EMAC_LED_TRAFFIC				 (1L<<6)
-#define BNX2_EMAC_LED_1000MB				 (1L<<7)
-#define BNX2_EMAC_LED_100MB				 (1L<<8)
-#define BNX2_EMAC_LED_10MB				 (1L<<9)
-#define BNX2_EMAC_LED_TRAFFIC_STAT			 (1L<<10)
-#define BNX2_EMAC_LED_2500MB				 (1L<<11)
-#define BNX2_EMAC_LED_2500MB_OVERRIDE			 (1L<<12)
-#define BNX2_EMAC_LED_ACTIVITY_SEL			 (0x3L<<17)
-#define BNX2_EMAC_LED_ACTIVITY_SEL_0			 (0L<<17)
-#define BNX2_EMAC_LED_ACTIVITY_SEL_1			 (1L<<17)
-#define BNX2_EMAC_LED_ACTIVITY_SEL_2			 (2L<<17)
-#define BNX2_EMAC_LED_ACTIVITY_SEL_3			 (3L<<17)
-#define BNX2_EMAC_LED_BLNK_RATE				 (0xfffL<<19)
-#define BNX2_EMAC_LED_BLNK_RATE_ENA			 (1L<<31)
-
-#define BNX2_EMAC_MAC_MATCH0				0x00001410
-#define BNX2_EMAC_MAC_MATCH1				0x00001414
-#define BNX2_EMAC_MAC_MATCH2				0x00001418
-#define BNX2_EMAC_MAC_MATCH3				0x0000141c
-#define BNX2_EMAC_MAC_MATCH4				0x00001420
-#define BNX2_EMAC_MAC_MATCH5				0x00001424
-#define BNX2_EMAC_MAC_MATCH6				0x00001428
-#define BNX2_EMAC_MAC_MATCH7				0x0000142c
-#define BNX2_EMAC_MAC_MATCH8				0x00001430
-#define BNX2_EMAC_MAC_MATCH9				0x00001434
-#define BNX2_EMAC_MAC_MATCH10				0x00001438
-#define BNX2_EMAC_MAC_MATCH11				0x0000143c
-#define BNX2_EMAC_MAC_MATCH12				0x00001440
-#define BNX2_EMAC_MAC_MATCH13				0x00001444
-#define BNX2_EMAC_MAC_MATCH14				0x00001448
-#define BNX2_EMAC_MAC_MATCH15				0x0000144c
-#define BNX2_EMAC_MAC_MATCH16				0x00001450
-#define BNX2_EMAC_MAC_MATCH17				0x00001454
-#define BNX2_EMAC_MAC_MATCH18				0x00001458
-#define BNX2_EMAC_MAC_MATCH19				0x0000145c
-#define BNX2_EMAC_MAC_MATCH20				0x00001460
-#define BNX2_EMAC_MAC_MATCH21				0x00001464
-#define BNX2_EMAC_MAC_MATCH22				0x00001468
-#define BNX2_EMAC_MAC_MATCH23				0x0000146c
-#define BNX2_EMAC_MAC_MATCH24				0x00001470
-#define BNX2_EMAC_MAC_MATCH25				0x00001474
-#define BNX2_EMAC_MAC_MATCH26				0x00001478
-#define BNX2_EMAC_MAC_MATCH27				0x0000147c
-#define BNX2_EMAC_MAC_MATCH28				0x00001480
-#define BNX2_EMAC_MAC_MATCH29				0x00001484
-#define BNX2_EMAC_MAC_MATCH30				0x00001488
-#define BNX2_EMAC_MAC_MATCH31				0x0000148c
-#define BNX2_EMAC_BACKOFF_SEED				0x00001498
-#define BNX2_EMAC_BACKOFF_SEED_EMAC_BACKOFF_SEED	 (0x3ffL<<0)
-
-#define BNX2_EMAC_RX_MTU_SIZE				0x0000149c
-#define BNX2_EMAC_RX_MTU_SIZE_MTU_SIZE			 (0xffffL<<0)
-#define BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA			 (1L<<31)
-
-#define BNX2_EMAC_SERDES_CNTL				0x000014a4
-#define BNX2_EMAC_SERDES_CNTL_RXR			 (0x7L<<0)
-#define BNX2_EMAC_SERDES_CNTL_RXG			 (0x3L<<3)
-#define BNX2_EMAC_SERDES_CNTL_RXCKSEL			 (1L<<6)
-#define BNX2_EMAC_SERDES_CNTL_TXBIAS			 (0x7L<<7)
-#define BNX2_EMAC_SERDES_CNTL_BGMAX			 (1L<<10)
-#define BNX2_EMAC_SERDES_CNTL_BGMIN			 (1L<<11)
-#define BNX2_EMAC_SERDES_CNTL_TXMODE			 (1L<<12)
-#define BNX2_EMAC_SERDES_CNTL_TXEDGE			 (1L<<13)
-#define BNX2_EMAC_SERDES_CNTL_SERDES_MODE		 (1L<<14)
-#define BNX2_EMAC_SERDES_CNTL_PLLTEST			 (1L<<15)
-#define BNX2_EMAC_SERDES_CNTL_CDET_EN			 (1L<<16)
-#define BNX2_EMAC_SERDES_CNTL_TBI_LBK			 (1L<<17)
-#define BNX2_EMAC_SERDES_CNTL_REMOTE_LBK		 (1L<<18)
-#define BNX2_EMAC_SERDES_CNTL_REV_PHASE			 (1L<<19)
-#define BNX2_EMAC_SERDES_CNTL_REGCTL12			 (0x3L<<20)
-#define BNX2_EMAC_SERDES_CNTL_REGCTL25			 (0x3L<<22)
-
-#define BNX2_EMAC_SERDES_STATUS				0x000014a8
-#define BNX2_EMAC_SERDES_STATUS_RX_STAT			 (0xffL<<0)
-#define BNX2_EMAC_SERDES_STATUS_COMMA_DET		 (1L<<8)
-
-#define BNX2_EMAC_MDIO_COMM				0x000014ac
-#define BNX2_EMAC_MDIO_COMM_DATA			 (0xffffL<<0)
-#define BNX2_EMAC_MDIO_COMM_REG_ADDR			 (0x1fL<<16)
-#define BNX2_EMAC_MDIO_COMM_PHY_ADDR			 (0x1fL<<21)
-#define BNX2_EMAC_MDIO_COMM_COMMAND			 (0x3L<<26)
-#define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_0		 (0L<<26)
-#define BNX2_EMAC_MDIO_COMM_COMMAND_ADDRESS		 (0L<<26)
-#define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE		 (1L<<26)
-#define BNX2_EMAC_MDIO_COMM_COMMAND_READ		 (2L<<26)
-#define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE_22_XI		 (1L<<26)
-#define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE_45_XI		 (1L<<26)
-#define BNX2_EMAC_MDIO_COMM_COMMAND_READ_22_XI		 (2L<<26)
-#define BNX2_EMAC_MDIO_COMM_COMMAND_READ_INC_45_XI	 (2L<<26)
-#define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_3		 (3L<<26)
-#define BNX2_EMAC_MDIO_COMM_COMMAND_READ_45		 (3L<<26)
-#define BNX2_EMAC_MDIO_COMM_FAIL			 (1L<<28)
-#define BNX2_EMAC_MDIO_COMM_START_BUSY			 (1L<<29)
-#define BNX2_EMAC_MDIO_COMM_DISEXT			 (1L<<30)
-
-#define BNX2_EMAC_MDIO_STATUS				0x000014b0
-#define BNX2_EMAC_MDIO_STATUS_LINK			 (1L<<0)
-#define BNX2_EMAC_MDIO_STATUS_10MB			 (1L<<1)
-
-#define BNX2_EMAC_MDIO_MODE				0x000014b4
-#define BNX2_EMAC_MDIO_MODE_SHORT_PREAMBLE		 (1L<<1)
-#define BNX2_EMAC_MDIO_MODE_AUTO_POLL			 (1L<<4)
-#define BNX2_EMAC_MDIO_MODE_BIT_BANG			 (1L<<8)
-#define BNX2_EMAC_MDIO_MODE_MDIO			 (1L<<9)
-#define BNX2_EMAC_MDIO_MODE_MDIO_OE			 (1L<<10)
-#define BNX2_EMAC_MDIO_MODE_MDC				 (1L<<11)
-#define BNX2_EMAC_MDIO_MODE_MDINT			 (1L<<12)
-#define BNX2_EMAC_MDIO_MODE_EXT_MDINT			 (1L<<13)
-#define BNX2_EMAC_MDIO_MODE_CLOCK_CNT			 (0x1fL<<16)
-#define BNX2_EMAC_MDIO_MODE_CLOCK_CNT_XI		 (0x3fL<<16)
-#define BNX2_EMAC_MDIO_MODE_CLAUSE_45_XI		 (1L<<31)
-
-#define BNX2_EMAC_MDIO_AUTO_STATUS			0x000014b8
-#define BNX2_EMAC_MDIO_AUTO_STATUS_AUTO_ERR		 (1L<<0)
-
-#define BNX2_EMAC_TX_MODE				0x000014bc
-#define BNX2_EMAC_TX_MODE_RESET				 (1L<<0)
-#define BNX2_EMAC_TX_MODE_CS16_TEST			 (1L<<2)
-#define BNX2_EMAC_TX_MODE_EXT_PAUSE_EN			 (1L<<3)
-#define BNX2_EMAC_TX_MODE_FLOW_EN			 (1L<<4)
-#define BNX2_EMAC_TX_MODE_BIG_BACKOFF			 (1L<<5)
-#define BNX2_EMAC_TX_MODE_LONG_PAUSE			 (1L<<6)
-#define BNX2_EMAC_TX_MODE_LINK_AWARE			 (1L<<7)
-
-#define BNX2_EMAC_TX_STATUS				0x000014c0
-#define BNX2_EMAC_TX_STATUS_XOFFED			 (1L<<0)
-#define BNX2_EMAC_TX_STATUS_XOFF_SENT			 (1L<<1)
-#define BNX2_EMAC_TX_STATUS_XON_SENT			 (1L<<2)
-#define BNX2_EMAC_TX_STATUS_LINK_UP			 (1L<<3)
-#define BNX2_EMAC_TX_STATUS_UNDERRUN			 (1L<<4)
-#define BNX2_EMAC_TX_STATUS_CS16_ERROR			 (1L<<5)
-
-#define BNX2_EMAC_TX_LENGTHS				0x000014c4
-#define BNX2_EMAC_TX_LENGTHS_SLOT			 (0xffL<<0)
-#define BNX2_EMAC_TX_LENGTHS_IPG			 (0xfL<<8)
-#define BNX2_EMAC_TX_LENGTHS_IPG_CRS			 (0x3L<<12)
-
-#define BNX2_EMAC_RX_MODE				0x000014c8
-#define BNX2_EMAC_RX_MODE_RESET				 (1L<<0)
-#define BNX2_EMAC_RX_MODE_FLOW_EN			 (1L<<2)
-#define BNX2_EMAC_RX_MODE_KEEP_MAC_CONTROL		 (1L<<3)
-#define BNX2_EMAC_RX_MODE_KEEP_PAUSE			 (1L<<4)
-#define BNX2_EMAC_RX_MODE_ACCEPT_OVERSIZE		 (1L<<5)
-#define BNX2_EMAC_RX_MODE_ACCEPT_RUNTS			 (1L<<6)
-#define BNX2_EMAC_RX_MODE_LLC_CHK			 (1L<<7)
-#define BNX2_EMAC_RX_MODE_PROMISCUOUS			 (1L<<8)
-#define BNX2_EMAC_RX_MODE_NO_CRC_CHK			 (1L<<9)
-#define BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG			 (1L<<10)
-#define BNX2_EMAC_RX_MODE_FILT_BROADCAST		 (1L<<11)
-#define BNX2_EMAC_RX_MODE_SORT_MODE			 (1L<<12)
-
-#define BNX2_EMAC_RX_STATUS				0x000014cc
-#define BNX2_EMAC_RX_STATUS_FFED			 (1L<<0)
-#define BNX2_EMAC_RX_STATUS_FF_RECEIVED			 (1L<<1)
-#define BNX2_EMAC_RX_STATUS_N_RECEIVED			 (1L<<2)
-
-#define BNX2_EMAC_MULTICAST_HASH0			0x000014d0
-#define BNX2_EMAC_MULTICAST_HASH1			0x000014d4
-#define BNX2_EMAC_MULTICAST_HASH2			0x000014d8
-#define BNX2_EMAC_MULTICAST_HASH3			0x000014dc
-#define BNX2_EMAC_MULTICAST_HASH4			0x000014e0
-#define BNX2_EMAC_MULTICAST_HASH5			0x000014e4
-#define BNX2_EMAC_MULTICAST_HASH6			0x000014e8
-#define BNX2_EMAC_MULTICAST_HASH7			0x000014ec
-#define BNX2_EMAC_CKSUM_ERROR_STATUS			0x000014f0
-#define BNX2_EMAC_CKSUM_ERROR_STATUS_CALCULATED		 (0xffffL<<0)
-#define BNX2_EMAC_CKSUM_ERROR_STATUS_EXPECTED		 (0xffffL<<16)
-
-#define BNX2_EMAC_RX_STAT_IFHCINOCTETS			0x00001500
-#define BNX2_EMAC_RX_STAT_IFHCINBADOCTETS		0x00001504
-#define BNX2_EMAC_RX_STAT_ETHERSTATSFRAGMENTS		0x00001508
-#define BNX2_EMAC_RX_STAT_IFHCINUCASTPKTS		0x0000150c
-#define BNX2_EMAC_RX_STAT_IFHCINMULTICASTPKTS		0x00001510
-#define BNX2_EMAC_RX_STAT_IFHCINBROADCASTPKTS		0x00001514
-#define BNX2_EMAC_RX_STAT_DOT3STATSFCSERRORS		0x00001518
-#define BNX2_EMAC_RX_STAT_DOT3STATSALIGNMENTERRORS	0x0000151c
-#define BNX2_EMAC_RX_STAT_DOT3STATSCARRIERSENSEERRORS	0x00001520
-#define BNX2_EMAC_RX_STAT_XONPAUSEFRAMESRECEIVED	0x00001524
-#define BNX2_EMAC_RX_STAT_XOFFPAUSEFRAMESRECEIVED	0x00001528
-#define BNX2_EMAC_RX_STAT_MACCONTROLFRAMESRECEIVED	0x0000152c
-#define BNX2_EMAC_RX_STAT_XOFFSTATEENTERED		0x00001530
-#define BNX2_EMAC_RX_STAT_DOT3STATSFRAMESTOOLONG	0x00001534
-#define BNX2_EMAC_RX_STAT_ETHERSTATSJABBERS		0x00001538
-#define BNX2_EMAC_RX_STAT_ETHERSTATSUNDERSIZEPKTS	0x0000153c
-#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS64OCTETS	0x00001540
-#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS65OCTETSTO127OCTETS	0x00001544
-#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS128OCTETSTO255OCTETS	0x00001548
-#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS	0x0000154c
-#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS	0x00001550
-#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS	0x00001554
-#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTSOVER1522OCTETS	0x00001558
-#define BNX2_EMAC_RXMAC_DEBUG0				0x0000155c
-#define BNX2_EMAC_RXMAC_DEBUG1				0x00001560
-#define BNX2_EMAC_RXMAC_DEBUG1_LENGTH_NE_BYTE_COUNT	 (1L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG1_LENGTH_OUT_RANGE		 (1L<<1)
-#define BNX2_EMAC_RXMAC_DEBUG1_BAD_CRC			 (1L<<2)
-#define BNX2_EMAC_RXMAC_DEBUG1_RX_ERROR			 (1L<<3)
-#define BNX2_EMAC_RXMAC_DEBUG1_ALIGN_ERROR		 (1L<<4)
-#define BNX2_EMAC_RXMAC_DEBUG1_LAST_DATA		 (1L<<5)
-#define BNX2_EMAC_RXMAC_DEBUG1_ODD_BYTE_START		 (1L<<6)
-#define BNX2_EMAC_RXMAC_DEBUG1_BYTE_COUNT		 (0xffffL<<7)
-#define BNX2_EMAC_RXMAC_DEBUG1_SLOT_TIME		 (0xffL<<23)
-
-#define BNX2_EMAC_RXMAC_DEBUG2				0x00001564
-#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE			 (0x7L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_IDLE		 (0x0L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SFD		 (0x1L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_DATA		 (0x2L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SKEEP		 (0x3L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_EXT		 (0x4L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_DROP		 (0x5L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SDROP		 (0x6L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_FC		 (0x7L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE		 (0xfL<<3)
-#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_IDLE		 (0x0L<<3)
-#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA0		 (0x1L<<3)
-#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA1		 (0x2L<<3)
-#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA2		 (0x3L<<3)
-#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA3		 (0x4L<<3)
-#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_ABORT		 (0x5L<<3)
-#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_WAIT		 (0x6L<<3)
-#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_STATUS		 (0x7L<<3)
-#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_LAST		 (0x8L<<3)
-#define BNX2_EMAC_RXMAC_DEBUG2_BYTE_IN			 (0xffL<<7)
-#define BNX2_EMAC_RXMAC_DEBUG2_FALSEC			 (1L<<15)
-#define BNX2_EMAC_RXMAC_DEBUG2_TAGGED			 (1L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE		 (1L<<18)
-#define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE_IDLE		 (0L<<18)
-#define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE_PAUSED	 (1L<<18)
-#define BNX2_EMAC_RXMAC_DEBUG2_SE_COUNTER		 (0xfL<<19)
-#define BNX2_EMAC_RXMAC_DEBUG2_QUANTA			 (0x1fL<<23)
-
-#define BNX2_EMAC_RXMAC_DEBUG3				0x00001568
-#define BNX2_EMAC_RXMAC_DEBUG3_PAUSE_CTR		 (0xffffL<<0)
-#define BNX2_EMAC_RXMAC_DEBUG3_TMP_PAUSE_CTR		 (0xffffL<<16)
-
-#define BNX2_EMAC_RXMAC_DEBUG4				0x0000156c
-#define BNX2_EMAC_RXMAC_DEBUG4_TYPE_FIELD		 (0xffffL<<0)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE		 (0x3fL<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_IDLE		 (0x0L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC2		 (0x1L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC3		 (0x2L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UNI		 (0x3L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC3		 (0x5L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA1		 (0x6L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC2		 (0x7L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA2		 (0x7L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA3		 (0x8L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC2		 (0x9L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC3		 (0xaL<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MWAIT1	 (0xeL<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MWAIT2	 (0xfL<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MCHECK	 (0x10L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC		 (0x11L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC2		 (0x12L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC3		 (0x13L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA1		 (0x14L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA2		 (0x15L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA3		 (0x16L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BTYPE		 (0x17L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC		 (0x18L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PTYPE		 (0x19L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_CMD		 (0x1aL<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MAC		 (0x1bL<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_LATCH		 (0x1cL<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_XOFF		 (0x1dL<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_XON		 (0x1eL<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PAUSED	 (0x1fL<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_NPAUSED	 (0x20L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_TTYPE		 (0x21L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_TVAL		 (0x22L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA1		 (0x23L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA2		 (0x24L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA3		 (0x25L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTYPE		 (0x26L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTTYPE	 (0x27L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTVAL		 (0x28L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MTYPE		 (0x29L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_DROP		 (0x2aL<<16)
-#define BNX2_EMAC_RXMAC_DEBUG4_DROP_PKT			 (1L<<22)
-#define BNX2_EMAC_RXMAC_DEBUG4_SLOT_FILLED		 (1L<<23)
-#define BNX2_EMAC_RXMAC_DEBUG4_FALSE_CARRIER		 (1L<<24)
-#define BNX2_EMAC_RXMAC_DEBUG4_LAST_DATA		 (1L<<25)
-#define BNX2_EMAC_RXMAC_DEBUG4_SFD_FOUND		 (1L<<26)
-#define BNX2_EMAC_RXMAC_DEBUG4_ADVANCE			 (1L<<27)
-#define BNX2_EMAC_RXMAC_DEBUG4_START			 (1L<<28)
-
-#define BNX2_EMAC_RXMAC_DEBUG5				0x00001570
-#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM			 (0x7L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_IDLE		 (0L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_WAIT_EOF	 (1L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_WAIT_STAT	 (2L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4FCRC	 (3L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4RDE	 (4L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4ALL	 (5L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_1WD_WAIT_STAT	 (6L<<0)
-#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1		 (0x7L<<4)
-#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_VDW		 (0x0L<<4)
-#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_STAT		 (0x1L<<4)
-#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_AEOF		 (0x2L<<4)
-#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_NEOF		 (0x3L<<4)
-#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SOF		 (0x4L<<4)
-#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SAEOF		 (0x6L<<4)
-#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SNEOF		 (0x7L<<4)
-#define BNX2_EMAC_RXMAC_DEBUG5_EOF_DETECTED		 (1L<<7)
-#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF0		 (0x7L<<8)
-#define BNX2_EMAC_RXMAC_DEBUG5_RPM_IDI_FIFO_FULL	 (1L<<11)
-#define BNX2_EMAC_RXMAC_DEBUG5_LOAD_CCODE		 (1L<<12)
-#define BNX2_EMAC_RXMAC_DEBUG5_LOAD_DATA		 (1L<<13)
-#define BNX2_EMAC_RXMAC_DEBUG5_LOAD_STAT		 (1L<<14)
-#define BNX2_EMAC_RXMAC_DEBUG5_CLR_STAT			 (1L<<15)
-#define BNX2_EMAC_RXMAC_DEBUG5_IDI_RPM_CCODE		 (0x3L<<16)
-#define BNX2_EMAC_RXMAC_DEBUG5_IDI_RPM_ACCEPT		 (1L<<19)
-#define BNX2_EMAC_RXMAC_DEBUG5_FMLEN			 (0xfffL<<20)
-
-#define BNX2_EMAC_RX_STAT_FALSECARRIERERRORS		0x00001574
-#define BNX2_EMAC_RX_STAT_AC0				0x00001580
-#define BNX2_EMAC_RX_STAT_AC1				0x00001584
-#define BNX2_EMAC_RX_STAT_AC2				0x00001588
-#define BNX2_EMAC_RX_STAT_AC3				0x0000158c
-#define BNX2_EMAC_RX_STAT_AC4				0x00001590
-#define BNX2_EMAC_RX_STAT_AC5				0x00001594
-#define BNX2_EMAC_RX_STAT_AC6				0x00001598
-#define BNX2_EMAC_RX_STAT_AC7				0x0000159c
-#define BNX2_EMAC_RX_STAT_AC8				0x000015a0
-#define BNX2_EMAC_RX_STAT_AC9				0x000015a4
-#define BNX2_EMAC_RX_STAT_AC10				0x000015a8
-#define BNX2_EMAC_RX_STAT_AC11				0x000015ac
-#define BNX2_EMAC_RX_STAT_AC12				0x000015b0
-#define BNX2_EMAC_RX_STAT_AC13				0x000015b4
-#define BNX2_EMAC_RX_STAT_AC14				0x000015b8
-#define BNX2_EMAC_RX_STAT_AC15				0x000015bc
-#define BNX2_EMAC_RX_STAT_AC16				0x000015c0
-#define BNX2_EMAC_RX_STAT_AC17				0x000015c4
-#define BNX2_EMAC_RX_STAT_AC18				0x000015c8
-#define BNX2_EMAC_RX_STAT_AC19				0x000015cc
-#define BNX2_EMAC_RX_STAT_AC20				0x000015d0
-#define BNX2_EMAC_RX_STAT_AC21				0x000015d4
-#define BNX2_EMAC_RX_STAT_AC22				0x000015d8
-#define BNX2_EMAC_RXMAC_SUC_DBG_OVERRUNVEC		0x000015dc
-#define BNX2_EMAC_RX_STAT_AC_28				0x000015f4
-#define BNX2_EMAC_TX_STAT_IFHCOUTOCTETS			0x00001600
-#define BNX2_EMAC_TX_STAT_IFHCOUTBADOCTETS		0x00001604
-#define BNX2_EMAC_TX_STAT_ETHERSTATSCOLLISIONS		0x00001608
-#define BNX2_EMAC_TX_STAT_OUTXONSENT			0x0000160c
-#define BNX2_EMAC_TX_STAT_OUTXOFFSENT			0x00001610
-#define BNX2_EMAC_TX_STAT_FLOWCONTROLDONE		0x00001614
-#define BNX2_EMAC_TX_STAT_DOT3STATSSINGLECOLLISIONFRAMES	0x00001618
-#define BNX2_EMAC_TX_STAT_DOT3STATSMULTIPLECOLLISIONFRAMES	0x0000161c
-#define BNX2_EMAC_TX_STAT_DOT3STATSDEFERREDTRANSMISSIONS	0x00001620
-#define BNX2_EMAC_TX_STAT_DOT3STATSEXCESSIVECOLLISIONS	0x00001624
-#define BNX2_EMAC_TX_STAT_DOT3STATSLATECOLLISIONS	0x00001628
-#define BNX2_EMAC_TX_STAT_IFHCOUTUCASTPKTS		0x0000162c
-#define BNX2_EMAC_TX_STAT_IFHCOUTMULTICASTPKTS		0x00001630
-#define BNX2_EMAC_TX_STAT_IFHCOUTBROADCASTPKTS		0x00001634
-#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS64OCTETS	0x00001638
-#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS65OCTETSTO127OCTETS	0x0000163c
-#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS128OCTETSTO255OCTETS	0x00001640
-#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS	0x00001644
-#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS	0x00001648
-#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS	0x0000164c
-#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTSOVER1522OCTETS	0x00001650
-#define BNX2_EMAC_TX_STAT_DOT3STATSINTERNALMACTRANSMITERRORS	0x00001654
-#define BNX2_EMAC_TXMAC_DEBUG0				0x00001658
-#define BNX2_EMAC_TXMAC_DEBUG1				0x0000165c
-#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE		 (0xfL<<0)
-#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_IDLE		 (0x0L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_START0		 (0x1L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA0		 (0x4L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA1		 (0x5L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA2		 (0x6L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA3		 (0x7L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_WAIT0		 (0x8L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_WAIT1		 (0x9L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG1_CRS_ENABLE		 (1L<<4)
-#define BNX2_EMAC_TXMAC_DEBUG1_BAD_CRC			 (1L<<5)
-#define BNX2_EMAC_TXMAC_DEBUG1_SE_COUNTER		 (0xfL<<6)
-#define BNX2_EMAC_TXMAC_DEBUG1_SEND_PAUSE		 (1L<<10)
-#define BNX2_EMAC_TXMAC_DEBUG1_LATE_COLLISION		 (1L<<11)
-#define BNX2_EMAC_TXMAC_DEBUG1_MAX_DEFER		 (1L<<12)
-#define BNX2_EMAC_TXMAC_DEBUG1_DEFERRED			 (1L<<13)
-#define BNX2_EMAC_TXMAC_DEBUG1_ONE_BYTE			 (1L<<14)
-#define BNX2_EMAC_TXMAC_DEBUG1_IPG_TIME			 (0xfL<<15)
-#define BNX2_EMAC_TXMAC_DEBUG1_SLOT_TIME		 (0xffL<<19)
-
-#define BNX2_EMAC_TXMAC_DEBUG2				0x00001660
-#define BNX2_EMAC_TXMAC_DEBUG2_BACK_OFF			 (0x3ffL<<0)
-#define BNX2_EMAC_TXMAC_DEBUG2_BYTE_COUNT		 (0xffffL<<10)
-#define BNX2_EMAC_TXMAC_DEBUG2_COL_COUNT		 (0x1fL<<26)
-#define BNX2_EMAC_TXMAC_DEBUG2_COL_BIT			 (1L<<31)
-
-#define BNX2_EMAC_TXMAC_DEBUG3				0x00001664
-#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE			 (0xfL<<0)
-#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_IDLE		 (0x0L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_PRE1		 (0x1L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_PRE2		 (0x2L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_SFD		 (0x3L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_DATA		 (0x4L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_CRC1		 (0x5L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_CRC2		 (0x6L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_EXT		 (0x7L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_STATB		 (0x8L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_STATG		 (0x9L<<0)
-#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_JAM		 (0xaL<<0)
-#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_EJAM		 (0xbL<<0)
-#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_BJAM		 (0xcL<<0)
-#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_SWAIT		 (0xdL<<0)
-#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_BACKOFF		 (0xeL<<0)
-#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE		 (0x7L<<4)
-#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_IDLE		 (0x0L<<4)
-#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_WAIT		 (0x1L<<4)
-#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_UNI		 (0x2L<<4)
-#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_MC		 (0x3L<<4)
-#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC2		 (0x4L<<4)
-#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC3		 (0x5L<<4)
-#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC		 (0x6L<<4)
-#define BNX2_EMAC_TXMAC_DEBUG3_CRS_DONE			 (1L<<7)
-#define BNX2_EMAC_TXMAC_DEBUG3_XOFF			 (1L<<8)
-#define BNX2_EMAC_TXMAC_DEBUG3_SE_COUNTER		 (0xfL<<9)
-#define BNX2_EMAC_TXMAC_DEBUG3_QUANTA_COUNTER		 (0x1fL<<13)
-
-#define BNX2_EMAC_TXMAC_DEBUG4				0x00001668
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_COUNTER		 (0xffffL<<0)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE		 (0xfL<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_IDLE		 (0x0L<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA1		 (0x2L<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA2		 (0x3L<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC3		 (0x4L<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC2		 (0x5L<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA3		 (0x6L<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC1		 (0x7L<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC1		 (0x8L<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC2		 (0x9L<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TIME		 (0xaL<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TYPE		 (0xcL<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_WAIT		 (0xdL<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CMD		 (0xeL<<16)
-#define BNX2_EMAC_TXMAC_DEBUG4_STATS0_VALID		 (1L<<20)
-#define BNX2_EMAC_TXMAC_DEBUG4_APPEND_CRC		 (1L<<21)
-#define BNX2_EMAC_TXMAC_DEBUG4_SLOT_FILLED		 (1L<<22)
-#define BNX2_EMAC_TXMAC_DEBUG4_MAX_DEFER		 (1L<<23)
-#define BNX2_EMAC_TXMAC_DEBUG4_SEND_EXTEND		 (1L<<24)
-#define BNX2_EMAC_TXMAC_DEBUG4_SEND_PADDING		 (1L<<25)
-#define BNX2_EMAC_TXMAC_DEBUG4_EOF_LOC			 (1L<<26)
-#define BNX2_EMAC_TXMAC_DEBUG4_COLLIDING		 (1L<<27)
-#define BNX2_EMAC_TXMAC_DEBUG4_COL_IN			 (1L<<28)
-#define BNX2_EMAC_TXMAC_DEBUG4_BURSTING			 (1L<<29)
-#define BNX2_EMAC_TXMAC_DEBUG4_ADVANCE			 (1L<<30)
-#define BNX2_EMAC_TXMAC_DEBUG4_GO			 (1L<<31)
-
-#define BNX2_EMAC_TX_STAT_AC0				0x00001680
-#define BNX2_EMAC_TX_STAT_AC1				0x00001684
-#define BNX2_EMAC_TX_STAT_AC2				0x00001688
-#define BNX2_EMAC_TX_STAT_AC3				0x0000168c
-#define BNX2_EMAC_TX_STAT_AC4				0x00001690
-#define BNX2_EMAC_TX_STAT_AC5				0x00001694
-#define BNX2_EMAC_TX_STAT_AC6				0x00001698
-#define BNX2_EMAC_TX_STAT_AC7				0x0000169c
-#define BNX2_EMAC_TX_STAT_AC8				0x000016a0
-#define BNX2_EMAC_TX_STAT_AC9				0x000016a4
-#define BNX2_EMAC_TX_STAT_AC10				0x000016a8
-#define BNX2_EMAC_TX_STAT_AC11				0x000016ac
-#define BNX2_EMAC_TX_STAT_AC12				0x000016b0
-#define BNX2_EMAC_TX_STAT_AC13				0x000016b4
-#define BNX2_EMAC_TX_STAT_AC14				0x000016b8
-#define BNX2_EMAC_TX_STAT_AC15				0x000016bc
-#define BNX2_EMAC_TX_STAT_AC16				0x000016c0
-#define BNX2_EMAC_TX_STAT_AC17				0x000016c4
-#define BNX2_EMAC_TX_STAT_AC18				0x000016c8
-#define BNX2_EMAC_TX_STAT_AC19				0x000016cc
-#define BNX2_EMAC_TX_STAT_AC20				0x000016d0
-#define BNX2_EMAC_TXMAC_SUC_DBG_OVERRUNVEC		0x000016d8
-#define BNX2_EMAC_TX_RATE_LIMIT_CTRL			0x000016fc
-#define BNX2_EMAC_TX_RATE_LIMIT_CTRL_TX_THROTTLE_INC	 (0x7fL<<0)
-#define BNX2_EMAC_TX_RATE_LIMIT_CTRL_TX_THROTTLE_NUM	 (0x7fL<<16)
-#define BNX2_EMAC_TX_RATE_LIMIT_CTRL_RATE_LIMITER_EN	 (1L<<31)
-
-
-/*
- *  rpm_reg definition
- *  offset: 0x1800
- */
-#define BNX2_RPM_COMMAND				0x00001800
-#define BNX2_RPM_COMMAND_ENABLED			 (1L<<0)
-#define BNX2_RPM_COMMAND_OVERRUN_ABORT			 (1L<<4)
-
-#define BNX2_RPM_STATUS					0x00001804
-#define BNX2_RPM_STATUS_MBUF_WAIT			 (1L<<0)
-#define BNX2_RPM_STATUS_FREE_WAIT			 (1L<<1)
-
-#define BNX2_RPM_CONFIG					0x00001808
-#define BNX2_RPM_CONFIG_NO_PSD_HDR_CKSUM		 (1L<<0)
-#define BNX2_RPM_CONFIG_ACPI_ENA			 (1L<<1)
-#define BNX2_RPM_CONFIG_ACPI_KEEP			 (1L<<2)
-#define BNX2_RPM_CONFIG_MP_KEEP				 (1L<<3)
-#define BNX2_RPM_CONFIG_SORT_VECT_VAL			 (0xfL<<4)
-#define BNX2_RPM_CONFIG_DISABLE_WOL_ASSERT		 (1L<<30)
-#define BNX2_RPM_CONFIG_IGNORE_VLAN			 (1L<<31)
-
-#define BNX2_RPM_MGMT_PKT_CTRL				0x0000180c
-#define BNX2_RPM_MGMT_PKT_CTRL_MGMT_SORT		 (0xfL<<0)
-#define BNX2_RPM_MGMT_PKT_CTRL_MGMT_RULE		 (0xfL<<4)
-#define BNX2_RPM_MGMT_PKT_CTRL_MGMT_DISCARD_EN		 (1L<<30)
-#define BNX2_RPM_MGMT_PKT_CTRL_MGMT_EN			 (1L<<31)
-
-#define BNX2_RPM_VLAN_MATCH0				0x00001810
-#define BNX2_RPM_VLAN_MATCH0_RPM_VLAN_MTCH0_VALUE	 (0xfffL<<0)
-
-#define BNX2_RPM_VLAN_MATCH1				0x00001814
-#define BNX2_RPM_VLAN_MATCH1_RPM_VLAN_MTCH1_VALUE	 (0xfffL<<0)
-
-#define BNX2_RPM_VLAN_MATCH2				0x00001818
-#define BNX2_RPM_VLAN_MATCH2_RPM_VLAN_MTCH2_VALUE	 (0xfffL<<0)
-
-#define BNX2_RPM_VLAN_MATCH3				0x0000181c
-#define BNX2_RPM_VLAN_MATCH3_RPM_VLAN_MTCH3_VALUE	 (0xfffL<<0)
-
-#define BNX2_RPM_SORT_USER0				0x00001820
-#define BNX2_RPM_SORT_USER0_PM_EN			 (0xffffL<<0)
-#define BNX2_RPM_SORT_USER0_BC_EN			 (1L<<16)
-#define BNX2_RPM_SORT_USER0_MC_EN			 (1L<<17)
-#define BNX2_RPM_SORT_USER0_MC_HSH_EN			 (1L<<18)
-#define BNX2_RPM_SORT_USER0_PROM_EN			 (1L<<19)
-#define BNX2_RPM_SORT_USER0_VLAN_EN			 (0xfL<<20)
-#define BNX2_RPM_SORT_USER0_PROM_VLAN			 (1L<<24)
-#define BNX2_RPM_SORT_USER0_VLAN_NOTMATCH		 (1L<<25)
-#define BNX2_RPM_SORT_USER0_ENA				 (1L<<31)
-
-#define BNX2_RPM_SORT_USER1				0x00001824
-#define BNX2_RPM_SORT_USER1_PM_EN			 (0xffffL<<0)
-#define BNX2_RPM_SORT_USER1_BC_EN			 (1L<<16)
-#define BNX2_RPM_SORT_USER1_MC_EN			 (1L<<17)
-#define BNX2_RPM_SORT_USER1_MC_HSH_EN			 (1L<<18)
-#define BNX2_RPM_SORT_USER1_PROM_EN			 (1L<<19)
-#define BNX2_RPM_SORT_USER1_VLAN_EN			 (0xfL<<20)
-#define BNX2_RPM_SORT_USER1_PROM_VLAN			 (1L<<24)
-#define BNX2_RPM_SORT_USER1_ENA				 (1L<<31)
-
-#define BNX2_RPM_SORT_USER2				0x00001828
-#define BNX2_RPM_SORT_USER2_PM_EN			 (0xffffL<<0)
-#define BNX2_RPM_SORT_USER2_BC_EN			 (1L<<16)
-#define BNX2_RPM_SORT_USER2_MC_EN			 (1L<<17)
-#define BNX2_RPM_SORT_USER2_MC_HSH_EN			 (1L<<18)
-#define BNX2_RPM_SORT_USER2_PROM_EN			 (1L<<19)
-#define BNX2_RPM_SORT_USER2_VLAN_EN			 (0xfL<<20)
-#define BNX2_RPM_SORT_USER2_PROM_VLAN			 (1L<<24)
-#define BNX2_RPM_SORT_USER2_ENA				 (1L<<31)
-
-#define BNX2_RPM_SORT_USER3				0x0000182c
-#define BNX2_RPM_SORT_USER3_PM_EN			 (0xffffL<<0)
-#define BNX2_RPM_SORT_USER3_BC_EN			 (1L<<16)
-#define BNX2_RPM_SORT_USER3_MC_EN			 (1L<<17)
-#define BNX2_RPM_SORT_USER3_MC_HSH_EN			 (1L<<18)
-#define BNX2_RPM_SORT_USER3_PROM_EN			 (1L<<19)
-#define BNX2_RPM_SORT_USER3_VLAN_EN			 (0xfL<<20)
-#define BNX2_RPM_SORT_USER3_PROM_VLAN			 (1L<<24)
-#define BNX2_RPM_SORT_USER3_ENA				 (1L<<31)
-
-#define BNX2_RPM_STAT_L2_FILTER_DISCARDS		0x00001840
-#define BNX2_RPM_STAT_RULE_CHECKER_DISCARDS		0x00001844
-#define BNX2_RPM_STAT_IFINFTQDISCARDS			0x00001848
-#define BNX2_RPM_STAT_IFINMBUFDISCARD			0x0000184c
-#define BNX2_RPM_STAT_RULE_CHECKER_P4_HIT		0x00001850
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0		0x00001854
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER_LEN	 (0xffL<<0)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER	 (0xffL<<16)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER_LEN_TYPE	 (1L<<30)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER_EN	 (1L<<31)
-
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1		0x00001858
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER_LEN	 (0xffL<<0)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER	 (0xffL<<16)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER_LEN_TYPE	 (1L<<30)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER_EN	 (1L<<31)
-
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2		0x0000185c
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER_LEN	 (0xffL<<0)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER	 (0xffL<<16)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER_LEN_TYPE	 (1L<<30)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER_EN	 (1L<<31)
-
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3		0x00001860
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER_LEN	 (0xffL<<0)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER	 (0xffL<<16)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER_LEN_TYPE	 (1L<<30)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER_EN	 (1L<<31)
-
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4		0x00001864
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER_LEN	 (0xffL<<0)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER	 (0xffL<<16)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER_LEN_TYPE	 (1L<<30)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER_EN	 (1L<<31)
-
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5		0x00001868
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER_LEN	 (0xffL<<0)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER	 (0xffL<<16)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER_LEN_TYPE	 (1L<<30)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER_EN	 (1L<<31)
-
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6		0x0000186c
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER_LEN	 (0xffL<<0)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER	 (0xffL<<16)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER_LEN_TYPE	 (1L<<30)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER_EN	 (1L<<31)
-
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7		0x00001870
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER_LEN	 (0xffL<<0)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER	 (0xffL<<16)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER_LEN_TYPE	 (1L<<30)
-#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER_EN	 (1L<<31)
-
-#define BNX2_RPM_STAT_AC0				0x00001880
-#define BNX2_RPM_STAT_AC1				0x00001884
-#define BNX2_RPM_STAT_AC2				0x00001888
-#define BNX2_RPM_STAT_AC3				0x0000188c
-#define BNX2_RPM_STAT_AC4				0x00001890
-#define BNX2_RPM_RC_CNTL_16				0x000018e0
-#define BNX2_RPM_RC_CNTL_16_OFFSET			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_16_CLASS			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_16_PRIORITY			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_16_P4				 (1L<<12)
-#define BNX2_RPM_RC_CNTL_16_HDR_TYPE			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_START		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_IP			 (1L<<13)
-#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_TCP		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_UDP		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_DATA		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_TCP_UDP		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_ICMPV6		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_16_COMP			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_16_COMP_EQUAL			 (0L<<16)
-#define BNX2_RPM_RC_CNTL_16_COMP_NEQUAL			 (1L<<16)
-#define BNX2_RPM_RC_CNTL_16_COMP_GREATER		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_16_COMP_LESS			 (3L<<16)
-#define BNX2_RPM_RC_CNTL_16_MAP				 (1L<<18)
-#define BNX2_RPM_RC_CNTL_16_SBIT			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_16_CMDSEL			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_16_DISCARD			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_16_MASK			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_16_P1				 (1L<<27)
-#define BNX2_RPM_RC_CNTL_16_P2				 (1L<<28)
-#define BNX2_RPM_RC_CNTL_16_P3				 (1L<<29)
-#define BNX2_RPM_RC_CNTL_16_NBIT			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_16			0x000018e4
-#define BNX2_RPM_RC_VALUE_MASK_16_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_16_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_17				0x000018e8
-#define BNX2_RPM_RC_CNTL_17_OFFSET			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_17_CLASS			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_17_PRIORITY			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_17_P4				 (1L<<12)
-#define BNX2_RPM_RC_CNTL_17_HDR_TYPE			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_START		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_IP			 (1L<<13)
-#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_TCP		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_UDP		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_DATA		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_TCP_UDP		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_ICMPV6		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_17_COMP			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_17_COMP_EQUAL			 (0L<<16)
-#define BNX2_RPM_RC_CNTL_17_COMP_NEQUAL			 (1L<<16)
-#define BNX2_RPM_RC_CNTL_17_COMP_GREATER		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_17_COMP_LESS			 (3L<<16)
-#define BNX2_RPM_RC_CNTL_17_MAP				 (1L<<18)
-#define BNX2_RPM_RC_CNTL_17_SBIT			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_17_CMDSEL			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_17_DISCARD			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_17_MASK			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_17_P1				 (1L<<27)
-#define BNX2_RPM_RC_CNTL_17_P2				 (1L<<28)
-#define BNX2_RPM_RC_CNTL_17_P3				 (1L<<29)
-#define BNX2_RPM_RC_CNTL_17_NBIT			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_17			0x000018ec
-#define BNX2_RPM_RC_VALUE_MASK_17_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_17_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_18				0x000018f0
-#define BNX2_RPM_RC_CNTL_18_OFFSET			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_18_CLASS			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_18_PRIORITY			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_18_P4				 (1L<<12)
-#define BNX2_RPM_RC_CNTL_18_HDR_TYPE			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_START		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_IP			 (1L<<13)
-#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_TCP		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_UDP		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_DATA		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_TCP_UDP		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_ICMPV6		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_18_COMP			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_18_COMP_EQUAL			 (0L<<16)
-#define BNX2_RPM_RC_CNTL_18_COMP_NEQUAL			 (1L<<16)
-#define BNX2_RPM_RC_CNTL_18_COMP_GREATER		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_18_COMP_LESS			 (3L<<16)
-#define BNX2_RPM_RC_CNTL_18_MAP				 (1L<<18)
-#define BNX2_RPM_RC_CNTL_18_SBIT			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_18_CMDSEL			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_18_DISCARD			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_18_MASK			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_18_P1				 (1L<<27)
-#define BNX2_RPM_RC_CNTL_18_P2				 (1L<<28)
-#define BNX2_RPM_RC_CNTL_18_P3				 (1L<<29)
-#define BNX2_RPM_RC_CNTL_18_NBIT			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_18			0x000018f4
-#define BNX2_RPM_RC_VALUE_MASK_18_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_18_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_19				0x000018f8
-#define BNX2_RPM_RC_CNTL_19_OFFSET			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_19_CLASS			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_19_PRIORITY			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_19_P4				 (1L<<12)
-#define BNX2_RPM_RC_CNTL_19_HDR_TYPE			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_START		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_IP			 (1L<<13)
-#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_TCP		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_UDP		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_DATA		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_TCP_UDP		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_ICMPV6		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_19_COMP			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_19_COMP_EQUAL			 (0L<<16)
-#define BNX2_RPM_RC_CNTL_19_COMP_NEQUAL			 (1L<<16)
-#define BNX2_RPM_RC_CNTL_19_COMP_GREATER		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_19_COMP_LESS			 (3L<<16)
-#define BNX2_RPM_RC_CNTL_19_MAP				 (1L<<18)
-#define BNX2_RPM_RC_CNTL_19_SBIT			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_19_CMDSEL			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_19_DISCARD			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_19_MASK			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_19_P1				 (1L<<27)
-#define BNX2_RPM_RC_CNTL_19_P2				 (1L<<28)
-#define BNX2_RPM_RC_CNTL_19_P3				 (1L<<29)
-#define BNX2_RPM_RC_CNTL_19_NBIT			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_19			0x000018fc
-#define BNX2_RPM_RC_VALUE_MASK_19_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_19_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_0				0x00001900
-#define BNX2_RPM_RC_CNTL_0_OFFSET			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_0_CLASS			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_0_PRIORITY			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_0_P4				 (1L<<12)
-#define BNX2_RPM_RC_CNTL_0_HDR_TYPE			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_START		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_IP			 (1L<<13)
-#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_TCP			 (2L<<13)
-#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_UDP			 (3L<<13)
-#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_DATA		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_TCP_UDP		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_ICMPV6		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_0_COMP				 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_0_COMP_EQUAL			 (0L<<16)
-#define BNX2_RPM_RC_CNTL_0_COMP_NEQUAL			 (1L<<16)
-#define BNX2_RPM_RC_CNTL_0_COMP_GREATER			 (2L<<16)
-#define BNX2_RPM_RC_CNTL_0_COMP_LESS			 (3L<<16)
-#define BNX2_RPM_RC_CNTL_0_MAP_XI			 (1L<<18)
-#define BNX2_RPM_RC_CNTL_0_SBIT				 (1L<<19)
-#define BNX2_RPM_RC_CNTL_0_CMDSEL			 (0xfL<<20)
-#define BNX2_RPM_RC_CNTL_0_MAP				 (1L<<24)
-#define BNX2_RPM_RC_CNTL_0_CMDSEL_XI			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_0_DISCARD			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_0_MASK				 (1L<<26)
-#define BNX2_RPM_RC_CNTL_0_P1				 (1L<<27)
-#define BNX2_RPM_RC_CNTL_0_P2				 (1L<<28)
-#define BNX2_RPM_RC_CNTL_0_P3				 (1L<<29)
-#define BNX2_RPM_RC_CNTL_0_NBIT				 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_0			0x00001904
-#define BNX2_RPM_RC_VALUE_MASK_0_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_0_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_1				0x00001908
-#define BNX2_RPM_RC_CNTL_1_A				 (0x3ffffL<<0)
-#define BNX2_RPM_RC_CNTL_1_B				 (0xfffL<<19)
-#define BNX2_RPM_RC_CNTL_1_OFFSET_XI			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_1_CLASS_XI			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_1_PRIORITY_XI			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_1_P4_XI			 (1L<<12)
-#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_XI			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_START_XI		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_IP_XI		 (1L<<13)
-#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_TCP_XI		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_UDP_XI		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_DATA_XI		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_TCP_UDP_XI		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_ICMPV6_XI		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_1_COMP_XI			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_1_COMP_EQUAL_XI		 (0L<<16)
-#define BNX2_RPM_RC_CNTL_1_COMP_NEQUAL_XI		 (1L<<16)
-#define BNX2_RPM_RC_CNTL_1_COMP_GREATER_XI		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_1_COMP_LESS_XI			 (3L<<16)
-#define BNX2_RPM_RC_CNTL_1_MAP_XI			 (1L<<18)
-#define BNX2_RPM_RC_CNTL_1_SBIT_XI			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_1_CMDSEL_XI			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_1_DISCARD_XI			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_1_MASK_XI			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_1_P1_XI			 (1L<<27)
-#define BNX2_RPM_RC_CNTL_1_P2_XI			 (1L<<28)
-#define BNX2_RPM_RC_CNTL_1_P3_XI			 (1L<<29)
-#define BNX2_RPM_RC_CNTL_1_NBIT_XI			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_1			0x0000190c
-#define BNX2_RPM_RC_VALUE_MASK_1_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_1_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_2				0x00001910
-#define BNX2_RPM_RC_CNTL_2_A				 (0x3ffffL<<0)
-#define BNX2_RPM_RC_CNTL_2_B				 (0xfffL<<19)
-#define BNX2_RPM_RC_CNTL_2_OFFSET_XI			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_2_CLASS_XI			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_2_PRIORITY_XI			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_2_P4_XI			 (1L<<12)
-#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_XI			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_START_XI		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_IP_XI		 (1L<<13)
-#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_TCP_XI		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_UDP_XI		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_DATA_XI		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_TCP_UDP_XI		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_ICMPV6_XI		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_2_COMP_XI			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_2_COMP_EQUAL_XI		 (0L<<16)
-#define BNX2_RPM_RC_CNTL_2_COMP_NEQUAL_XI		 (1L<<16)
-#define BNX2_RPM_RC_CNTL_2_COMP_GREATER_XI		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_2_COMP_LESS_XI			 (3L<<16)
-#define BNX2_RPM_RC_CNTL_2_MAP_XI			 (1L<<18)
-#define BNX2_RPM_RC_CNTL_2_SBIT_XI			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_2_CMDSEL_XI			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_2_DISCARD_XI			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_2_MASK_XI			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_2_P1_XI			 (1L<<27)
-#define BNX2_RPM_RC_CNTL_2_P2_XI			 (1L<<28)
-#define BNX2_RPM_RC_CNTL_2_P3_XI			 (1L<<29)
-#define BNX2_RPM_RC_CNTL_2_NBIT_XI			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_2			0x00001914
-#define BNX2_RPM_RC_VALUE_MASK_2_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_2_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_3				0x00001918
-#define BNX2_RPM_RC_CNTL_3_A				 (0x3ffffL<<0)
-#define BNX2_RPM_RC_CNTL_3_B				 (0xfffL<<19)
-#define BNX2_RPM_RC_CNTL_3_OFFSET_XI			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_3_CLASS_XI			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_3_PRIORITY_XI			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_3_P4_XI			 (1L<<12)
-#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_XI			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_START_XI		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_IP_XI		 (1L<<13)
-#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_TCP_XI		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_UDP_XI		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_DATA_XI		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_TCP_UDP_XI		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_ICMPV6_XI		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_3_COMP_XI			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_3_COMP_EQUAL_XI		 (0L<<16)
-#define BNX2_RPM_RC_CNTL_3_COMP_NEQUAL_XI		 (1L<<16)
-#define BNX2_RPM_RC_CNTL_3_COMP_GREATER_XI		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_3_COMP_LESS_XI			 (3L<<16)
-#define BNX2_RPM_RC_CNTL_3_MAP_XI			 (1L<<18)
-#define BNX2_RPM_RC_CNTL_3_SBIT_XI			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_3_CMDSEL_XI			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_3_DISCARD_XI			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_3_MASK_XI			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_3_P1_XI			 (1L<<27)
-#define BNX2_RPM_RC_CNTL_3_P2_XI			 (1L<<28)
-#define BNX2_RPM_RC_CNTL_3_P3_XI			 (1L<<29)
-#define BNX2_RPM_RC_CNTL_3_NBIT_XI			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_3			0x0000191c
-#define BNX2_RPM_RC_VALUE_MASK_3_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_3_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_4				0x00001920
-#define BNX2_RPM_RC_CNTL_4_A				 (0x3ffffL<<0)
-#define BNX2_RPM_RC_CNTL_4_B				 (0xfffL<<19)
-#define BNX2_RPM_RC_CNTL_4_OFFSET_XI			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_4_CLASS_XI			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_4_PRIORITY_XI			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_4_P4_XI			 (1L<<12)
-#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_XI			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_START_XI		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_IP_XI		 (1L<<13)
-#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_TCP_XI		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_UDP_XI		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_DATA_XI		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_TCP_UDP_XI		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_ICMPV6_XI		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_4_COMP_XI			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_4_COMP_EQUAL_XI		 (0L<<16)
-#define BNX2_RPM_RC_CNTL_4_COMP_NEQUAL_XI		 (1L<<16)
-#define BNX2_RPM_RC_CNTL_4_COMP_GREATER_XI		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_4_COMP_LESS_XI			 (3L<<16)
-#define BNX2_RPM_RC_CNTL_4_MAP_XI			 (1L<<18)
-#define BNX2_RPM_RC_CNTL_4_SBIT_XI			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_4_CMDSEL_XI			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_4_DISCARD_XI			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_4_MASK_XI			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_4_P1_XI			 (1L<<27)
-#define BNX2_RPM_RC_CNTL_4_P2_XI			 (1L<<28)
-#define BNX2_RPM_RC_CNTL_4_P3_XI			 (1L<<29)
-#define BNX2_RPM_RC_CNTL_4_NBIT_XI			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_4			0x00001924
-#define BNX2_RPM_RC_VALUE_MASK_4_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_4_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_5				0x00001928
-#define BNX2_RPM_RC_CNTL_5_A				 (0x3ffffL<<0)
-#define BNX2_RPM_RC_CNTL_5_B				 (0xfffL<<19)
-#define BNX2_RPM_RC_CNTL_5_OFFSET_XI			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_5_CLASS_XI			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_5_PRIORITY_XI			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_5_P4_XI			 (1L<<12)
-#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_XI			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_START_XI		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_IP_XI		 (1L<<13)
-#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_TCP_XI		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_UDP_XI		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_DATA_XI		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_TCP_UDP_XI		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_ICMPV6_XI		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_5_COMP_XI			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_5_COMP_EQUAL_XI		 (0L<<16)
-#define BNX2_RPM_RC_CNTL_5_COMP_NEQUAL_XI		 (1L<<16)
-#define BNX2_RPM_RC_CNTL_5_COMP_GREATER_XI		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_5_COMP_LESS_XI			 (3L<<16)
-#define BNX2_RPM_RC_CNTL_5_MAP_XI			 (1L<<18)
-#define BNX2_RPM_RC_CNTL_5_SBIT_XI			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_5_CMDSEL_XI			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_5_DISCARD_XI			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_5_MASK_XI			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_5_P1_XI			 (1L<<27)
-#define BNX2_RPM_RC_CNTL_5_P2_XI			 (1L<<28)
-#define BNX2_RPM_RC_CNTL_5_P3_XI			 (1L<<29)
-#define BNX2_RPM_RC_CNTL_5_NBIT_XI			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_5			0x0000192c
-#define BNX2_RPM_RC_VALUE_MASK_5_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_5_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_6				0x00001930
-#define BNX2_RPM_RC_CNTL_6_A				 (0x3ffffL<<0)
-#define BNX2_RPM_RC_CNTL_6_B				 (0xfffL<<19)
-#define BNX2_RPM_RC_CNTL_6_OFFSET_XI			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_6_CLASS_XI			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_6_PRIORITY_XI			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_6_P4_XI			 (1L<<12)
-#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_XI			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_START_XI		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_IP_XI		 (1L<<13)
-#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_TCP_XI		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_UDP_XI		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_DATA_XI		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_TCP_UDP_XI		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_ICMPV6_XI		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_6_COMP_XI			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_6_COMP_EQUAL_XI		 (0L<<16)
-#define BNX2_RPM_RC_CNTL_6_COMP_NEQUAL_XI		 (1L<<16)
-#define BNX2_RPM_RC_CNTL_6_COMP_GREATER_XI		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_6_COMP_LESS_XI			 (3L<<16)
-#define BNX2_RPM_RC_CNTL_6_MAP_XI			 (1L<<18)
-#define BNX2_RPM_RC_CNTL_6_SBIT_XI			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_6_CMDSEL_XI			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_6_DISCARD_XI			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_6_MASK_XI			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_6_P1_XI			 (1L<<27)
-#define BNX2_RPM_RC_CNTL_6_P2_XI			 (1L<<28)
-#define BNX2_RPM_RC_CNTL_6_P3_XI			 (1L<<29)
-#define BNX2_RPM_RC_CNTL_6_NBIT_XI			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_6			0x00001934
-#define BNX2_RPM_RC_VALUE_MASK_6_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_6_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_7				0x00001938
-#define BNX2_RPM_RC_CNTL_7_A				 (0x3ffffL<<0)
-#define BNX2_RPM_RC_CNTL_7_B				 (0xfffL<<19)
-#define BNX2_RPM_RC_CNTL_7_OFFSET_XI			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_7_CLASS_XI			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_7_PRIORITY_XI			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_7_P4_XI			 (1L<<12)
-#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_XI			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_START_XI		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_IP_XI		 (1L<<13)
-#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_TCP_XI		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_UDP_XI		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_DATA_XI		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_TCP_UDP_XI		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_ICMPV6_XI		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_7_COMP_XI			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_7_COMP_EQUAL_XI		 (0L<<16)
-#define BNX2_RPM_RC_CNTL_7_COMP_NEQUAL_XI		 (1L<<16)
-#define BNX2_RPM_RC_CNTL_7_COMP_GREATER_XI		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_7_COMP_LESS_XI			 (3L<<16)
-#define BNX2_RPM_RC_CNTL_7_MAP_XI			 (1L<<18)
-#define BNX2_RPM_RC_CNTL_7_SBIT_XI			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_7_CMDSEL_XI			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_7_DISCARD_XI			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_7_MASK_XI			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_7_P1_XI			 (1L<<27)
-#define BNX2_RPM_RC_CNTL_7_P2_XI			 (1L<<28)
-#define BNX2_RPM_RC_CNTL_7_P3_XI			 (1L<<29)
-#define BNX2_RPM_RC_CNTL_7_NBIT_XI			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_7			0x0000193c
-#define BNX2_RPM_RC_VALUE_MASK_7_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_7_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_8				0x00001940
-#define BNX2_RPM_RC_CNTL_8_A				 (0x3ffffL<<0)
-#define BNX2_RPM_RC_CNTL_8_B				 (0xfffL<<19)
-#define BNX2_RPM_RC_CNTL_8_OFFSET_XI			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_8_CLASS_XI			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_8_PRIORITY_XI			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_8_P4_XI			 (1L<<12)
-#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_XI			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_START_XI		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_IP_XI		 (1L<<13)
-#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_TCP_XI		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_UDP_XI		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_DATA_XI		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_TCP_UDP_XI		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_ICMPV6_XI		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_8_COMP_XI			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_8_COMP_EQUAL_XI		 (0L<<16)
-#define BNX2_RPM_RC_CNTL_8_COMP_NEQUAL_XI		 (1L<<16)
-#define BNX2_RPM_RC_CNTL_8_COMP_GREATER_XI		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_8_COMP_LESS_XI			 (3L<<16)
-#define BNX2_RPM_RC_CNTL_8_MAP_XI			 (1L<<18)
-#define BNX2_RPM_RC_CNTL_8_SBIT_XI			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_8_CMDSEL_XI			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_8_DISCARD_XI			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_8_MASK_XI			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_8_P1_XI			 (1L<<27)
-#define BNX2_RPM_RC_CNTL_8_P2_XI			 (1L<<28)
-#define BNX2_RPM_RC_CNTL_8_P3_XI			 (1L<<29)
-#define BNX2_RPM_RC_CNTL_8_NBIT_XI			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_8			0x00001944
-#define BNX2_RPM_RC_VALUE_MASK_8_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_8_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_9				0x00001948
-#define BNX2_RPM_RC_CNTL_9_A				 (0x3ffffL<<0)
-#define BNX2_RPM_RC_CNTL_9_B				 (0xfffL<<19)
-#define BNX2_RPM_RC_CNTL_9_OFFSET_XI			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_9_CLASS_XI			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_9_PRIORITY_XI			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_9_P4_XI			 (1L<<12)
-#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_XI			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_START_XI		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_IP_XI		 (1L<<13)
-#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_TCP_XI		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_UDP_XI		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_DATA_XI		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_TCP_UDP_XI		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_ICMPV6_XI		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_9_COMP_XI			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_9_COMP_EQUAL_XI		 (0L<<16)
-#define BNX2_RPM_RC_CNTL_9_COMP_NEQUAL_XI		 (1L<<16)
-#define BNX2_RPM_RC_CNTL_9_COMP_GREATER_XI		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_9_COMP_LESS_XI			 (3L<<16)
-#define BNX2_RPM_RC_CNTL_9_MAP_XI			 (1L<<18)
-#define BNX2_RPM_RC_CNTL_9_SBIT_XI			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_9_CMDSEL_XI			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_9_DISCARD_XI			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_9_MASK_XI			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_9_P1_XI			 (1L<<27)
-#define BNX2_RPM_RC_CNTL_9_P2_XI			 (1L<<28)
-#define BNX2_RPM_RC_CNTL_9_P3_XI			 (1L<<29)
-#define BNX2_RPM_RC_CNTL_9_NBIT_XI			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_9			0x0000194c
-#define BNX2_RPM_RC_VALUE_MASK_9_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_9_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_10				0x00001950
-#define BNX2_RPM_RC_CNTL_10_A				 (0x3ffffL<<0)
-#define BNX2_RPM_RC_CNTL_10_B				 (0xfffL<<19)
-#define BNX2_RPM_RC_CNTL_10_OFFSET_XI			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_10_CLASS_XI			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_10_PRIORITY_XI			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_10_P4_XI			 (1L<<12)
-#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_XI			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_START_XI		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_IP_XI		 (1L<<13)
-#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_TCP_XI		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_UDP_XI		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_DATA_XI		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_TCP_UDP_XI		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_ICMPV6_XI		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_10_COMP_XI			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_10_COMP_EQUAL_XI		 (0L<<16)
-#define BNX2_RPM_RC_CNTL_10_COMP_NEQUAL_XI		 (1L<<16)
-#define BNX2_RPM_RC_CNTL_10_COMP_GREATER_XI		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_10_COMP_LESS_XI		 (3L<<16)
-#define BNX2_RPM_RC_CNTL_10_MAP_XI			 (1L<<18)
-#define BNX2_RPM_RC_CNTL_10_SBIT_XI			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_10_CMDSEL_XI			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_10_DISCARD_XI			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_10_MASK_XI			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_10_P1_XI			 (1L<<27)
-#define BNX2_RPM_RC_CNTL_10_P2_XI			 (1L<<28)
-#define BNX2_RPM_RC_CNTL_10_P3_XI			 (1L<<29)
-#define BNX2_RPM_RC_CNTL_10_NBIT_XI			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_10			0x00001954
-#define BNX2_RPM_RC_VALUE_MASK_10_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_10_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_11				0x00001958
-#define BNX2_RPM_RC_CNTL_11_A				 (0x3ffffL<<0)
-#define BNX2_RPM_RC_CNTL_11_B				 (0xfffL<<19)
-#define BNX2_RPM_RC_CNTL_11_OFFSET_XI			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_11_CLASS_XI			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_11_PRIORITY_XI			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_11_P4_XI			 (1L<<12)
-#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_XI			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_START_XI		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_IP_XI		 (1L<<13)
-#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_TCP_XI		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_UDP_XI		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_DATA_XI		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_TCP_UDP_XI		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_ICMPV6_XI		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_11_COMP_XI			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_11_COMP_EQUAL_XI		 (0L<<16)
-#define BNX2_RPM_RC_CNTL_11_COMP_NEQUAL_XI		 (1L<<16)
-#define BNX2_RPM_RC_CNTL_11_COMP_GREATER_XI		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_11_COMP_LESS_XI		 (3L<<16)
-#define BNX2_RPM_RC_CNTL_11_MAP_XI			 (1L<<18)
-#define BNX2_RPM_RC_CNTL_11_SBIT_XI			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_11_CMDSEL_XI			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_11_DISCARD_XI			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_11_MASK_XI			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_11_P1_XI			 (1L<<27)
-#define BNX2_RPM_RC_CNTL_11_P2_XI			 (1L<<28)
-#define BNX2_RPM_RC_CNTL_11_P3_XI			 (1L<<29)
-#define BNX2_RPM_RC_CNTL_11_NBIT_XI			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_11			0x0000195c
-#define BNX2_RPM_RC_VALUE_MASK_11_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_11_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_12				0x00001960
-#define BNX2_RPM_RC_CNTL_12_A				 (0x3ffffL<<0)
-#define BNX2_RPM_RC_CNTL_12_B				 (0xfffL<<19)
-#define BNX2_RPM_RC_CNTL_12_OFFSET_XI			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_12_CLASS_XI			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_12_PRIORITY_XI			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_12_P4_XI			 (1L<<12)
-#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_XI			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_START_XI		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_IP_XI		 (1L<<13)
-#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_TCP_XI		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_UDP_XI		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_DATA_XI		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_TCP_UDP_XI		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_ICMPV6_XI		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_12_COMP_XI			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_12_COMP_EQUAL_XI		 (0L<<16)
-#define BNX2_RPM_RC_CNTL_12_COMP_NEQUAL_XI		 (1L<<16)
-#define BNX2_RPM_RC_CNTL_12_COMP_GREATER_XI		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_12_COMP_LESS_XI		 (3L<<16)
-#define BNX2_RPM_RC_CNTL_12_MAP_XI			 (1L<<18)
-#define BNX2_RPM_RC_CNTL_12_SBIT_XI			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_12_CMDSEL_XI			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_12_DISCARD_XI			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_12_MASK_XI			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_12_P1_XI			 (1L<<27)
-#define BNX2_RPM_RC_CNTL_12_P2_XI			 (1L<<28)
-#define BNX2_RPM_RC_CNTL_12_P3_XI			 (1L<<29)
-#define BNX2_RPM_RC_CNTL_12_NBIT_XI			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_12			0x00001964
-#define BNX2_RPM_RC_VALUE_MASK_12_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_12_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_13				0x00001968
-#define BNX2_RPM_RC_CNTL_13_A				 (0x3ffffL<<0)
-#define BNX2_RPM_RC_CNTL_13_B				 (0xfffL<<19)
-#define BNX2_RPM_RC_CNTL_13_OFFSET_XI			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_13_CLASS_XI			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_13_PRIORITY_XI			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_13_P4_XI			 (1L<<12)
-#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_XI			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_START_XI		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_IP_XI		 (1L<<13)
-#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_TCP_XI		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_UDP_XI		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_DATA_XI		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_TCP_UDP_XI		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_ICMPV6_XI		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_13_COMP_XI			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_13_COMP_EQUAL_XI		 (0L<<16)
-#define BNX2_RPM_RC_CNTL_13_COMP_NEQUAL_XI		 (1L<<16)
-#define BNX2_RPM_RC_CNTL_13_COMP_GREATER_XI		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_13_COMP_LESS_XI		 (3L<<16)
-#define BNX2_RPM_RC_CNTL_13_MAP_XI			 (1L<<18)
-#define BNX2_RPM_RC_CNTL_13_SBIT_XI			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_13_CMDSEL_XI			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_13_DISCARD_XI			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_13_MASK_XI			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_13_P1_XI			 (1L<<27)
-#define BNX2_RPM_RC_CNTL_13_P2_XI			 (1L<<28)
-#define BNX2_RPM_RC_CNTL_13_P3_XI			 (1L<<29)
-#define BNX2_RPM_RC_CNTL_13_NBIT_XI			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_13			0x0000196c
-#define BNX2_RPM_RC_VALUE_MASK_13_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_13_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_14				0x00001970
-#define BNX2_RPM_RC_CNTL_14_A				 (0x3ffffL<<0)
-#define BNX2_RPM_RC_CNTL_14_B				 (0xfffL<<19)
-#define BNX2_RPM_RC_CNTL_14_OFFSET_XI			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_14_CLASS_XI			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_14_PRIORITY_XI			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_14_P4_XI			 (1L<<12)
-#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_XI			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_START_XI		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_IP_XI		 (1L<<13)
-#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_TCP_XI		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_UDP_XI		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_DATA_XI		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_TCP_UDP_XI		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_ICMPV6_XI		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_14_COMP_XI			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_14_COMP_EQUAL_XI		 (0L<<16)
-#define BNX2_RPM_RC_CNTL_14_COMP_NEQUAL_XI		 (1L<<16)
-#define BNX2_RPM_RC_CNTL_14_COMP_GREATER_XI		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_14_COMP_LESS_XI		 (3L<<16)
-#define BNX2_RPM_RC_CNTL_14_MAP_XI			 (1L<<18)
-#define BNX2_RPM_RC_CNTL_14_SBIT_XI			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_14_CMDSEL_XI			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_14_DISCARD_XI			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_14_MASK_XI			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_14_P1_XI			 (1L<<27)
-#define BNX2_RPM_RC_CNTL_14_P2_XI			 (1L<<28)
-#define BNX2_RPM_RC_CNTL_14_P3_XI			 (1L<<29)
-#define BNX2_RPM_RC_CNTL_14_NBIT_XI			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_14			0x00001974
-#define BNX2_RPM_RC_VALUE_MASK_14_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_14_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CNTL_15				0x00001978
-#define BNX2_RPM_RC_CNTL_15_A				 (0x3ffffL<<0)
-#define BNX2_RPM_RC_CNTL_15_B				 (0xfffL<<19)
-#define BNX2_RPM_RC_CNTL_15_OFFSET_XI			 (0xffL<<0)
-#define BNX2_RPM_RC_CNTL_15_CLASS_XI			 (0x7L<<8)
-#define BNX2_RPM_RC_CNTL_15_PRIORITY_XI			 (1L<<11)
-#define BNX2_RPM_RC_CNTL_15_P4_XI			 (1L<<12)
-#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_XI			 (0x7L<<13)
-#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_START_XI		 (0L<<13)
-#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_IP_XI		 (1L<<13)
-#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_TCP_XI		 (2L<<13)
-#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_UDP_XI		 (3L<<13)
-#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_DATA_XI		 (4L<<13)
-#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_TCP_UDP_XI		 (5L<<13)
-#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_ICMPV6_XI		 (6L<<13)
-#define BNX2_RPM_RC_CNTL_15_COMP_XI			 (0x3L<<16)
-#define BNX2_RPM_RC_CNTL_15_COMP_EQUAL_XI		 (0L<<16)
-#define BNX2_RPM_RC_CNTL_15_COMP_NEQUAL_XI		 (1L<<16)
-#define BNX2_RPM_RC_CNTL_15_COMP_GREATER_XI		 (2L<<16)
-#define BNX2_RPM_RC_CNTL_15_COMP_LESS_XI		 (3L<<16)
-#define BNX2_RPM_RC_CNTL_15_MAP_XI			 (1L<<18)
-#define BNX2_RPM_RC_CNTL_15_SBIT_XI			 (1L<<19)
-#define BNX2_RPM_RC_CNTL_15_CMDSEL_XI			 (0x1fL<<20)
-#define BNX2_RPM_RC_CNTL_15_DISCARD_XI			 (1L<<25)
-#define BNX2_RPM_RC_CNTL_15_MASK_XI			 (1L<<26)
-#define BNX2_RPM_RC_CNTL_15_P1_XI			 (1L<<27)
-#define BNX2_RPM_RC_CNTL_15_P2_XI			 (1L<<28)
-#define BNX2_RPM_RC_CNTL_15_P3_XI			 (1L<<29)
-#define BNX2_RPM_RC_CNTL_15_NBIT_XI			 (1L<<30)
-
-#define BNX2_RPM_RC_VALUE_MASK_15			0x0000197c
-#define BNX2_RPM_RC_VALUE_MASK_15_VALUE			 (0xffffL<<0)
-#define BNX2_RPM_RC_VALUE_MASK_15_MASK			 (0xffffL<<16)
-
-#define BNX2_RPM_RC_CONFIG				0x00001980
-#define BNX2_RPM_RC_CONFIG_RULE_ENABLE			 (0xffffL<<0)
-#define BNX2_RPM_RC_CONFIG_RULE_ENABLE_XI		 (0xfffffL<<0)
-#define BNX2_RPM_RC_CONFIG_DEF_CLASS			 (0x7L<<24)
-#define BNX2_RPM_RC_CONFIG_KNUM_OVERWRITE		 (1L<<31)
-
-#define BNX2_RPM_DEBUG0					0x00001984
-#define BNX2_RPM_DEBUG0_FM_BCNT				 (0xffffL<<0)
-#define BNX2_RPM_DEBUG0_T_DATA_OFST_VLD			 (1L<<16)
-#define BNX2_RPM_DEBUG0_T_UDP_OFST_VLD			 (1L<<17)
-#define BNX2_RPM_DEBUG0_T_TCP_OFST_VLD			 (1L<<18)
-#define BNX2_RPM_DEBUG0_T_IP_OFST_VLD			 (1L<<19)
-#define BNX2_RPM_DEBUG0_IP_MORE_FRGMT			 (1L<<20)
-#define BNX2_RPM_DEBUG0_T_IP_NO_TCP_UDP_HDR		 (1L<<21)
-#define BNX2_RPM_DEBUG0_LLC_SNAP			 (1L<<22)
-#define BNX2_RPM_DEBUG0_FM_STARTED			 (1L<<23)
-#define BNX2_RPM_DEBUG0_DONE				 (1L<<24)
-#define BNX2_RPM_DEBUG0_WAIT_4_DONE			 (1L<<25)
-#define BNX2_RPM_DEBUG0_USE_TPBUF_CKSUM			 (1L<<26)
-#define BNX2_RPM_DEBUG0_RX_NO_PSD_HDR_CKSUM		 (1L<<27)
-#define BNX2_RPM_DEBUG0_IGNORE_VLAN			 (1L<<28)
-#define BNX2_RPM_DEBUG0_RP_ENA_ACTIVE			 (1L<<31)
-
-#define BNX2_RPM_DEBUG1					0x00001988
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST			 (0xffffL<<0)
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST_IDLE			 (0L<<0)
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B6_ALL		 (1L<<0)
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B2_IPLLC	 (2L<<0)
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B6_IP		 (4L<<0)
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B2_IP		 (8L<<0)
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST_IP_START		 (16L<<0)
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST_IP			 (32L<<0)
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST_TCP			 (64L<<0)
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST_UDP			 (128L<<0)
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST_AH			 (256L<<0)
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ESP			 (512L<<0)
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ESP_PAYLOAD		 (1024L<<0)
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST_DATA			 (2048L<<0)
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ADD_CARRY		 (0x2000L<<0)
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ADD_CARRYOUT		 (0x4000L<<0)
-#define BNX2_RPM_DEBUG1_FSM_CUR_ST_LATCH_RESULT		 (0x8000L<<0)
-#define BNX2_RPM_DEBUG1_HDR_BCNT			 (0x7ffL<<16)
-#define BNX2_RPM_DEBUG1_UNKNOWN_ETYPE_D			 (1L<<28)
-#define BNX2_RPM_DEBUG1_VLAN_REMOVED_D2			 (1L<<29)
-#define BNX2_RPM_DEBUG1_VLAN_REMOVED_D1			 (1L<<30)
-#define BNX2_RPM_DEBUG1_EOF_0XTRA_WD			 (1L<<31)
-
-#define BNX2_RPM_DEBUG2					0x0000198c
-#define BNX2_RPM_DEBUG2_CMD_HIT_VEC			 (0xffffL<<0)
-#define BNX2_RPM_DEBUG2_IP_BCNT				 (0xffL<<16)
-#define BNX2_RPM_DEBUG2_THIS_CMD_M4			 (1L<<24)
-#define BNX2_RPM_DEBUG2_THIS_CMD_M3			 (1L<<25)
-#define BNX2_RPM_DEBUG2_THIS_CMD_M2			 (1L<<26)
-#define BNX2_RPM_DEBUG2_THIS_CMD_M1			 (1L<<27)
-#define BNX2_RPM_DEBUG2_IPIPE_EMPTY			 (1L<<28)
-#define BNX2_RPM_DEBUG2_FM_DISCARD			 (1L<<29)
-#define BNX2_RPM_DEBUG2_LAST_RULE_IN_FM_D2		 (1L<<30)
-#define BNX2_RPM_DEBUG2_LAST_RULE_IN_FM_D1		 (1L<<31)
-
-#define BNX2_RPM_DEBUG3					0x00001990
-#define BNX2_RPM_DEBUG3_AVAIL_MBUF_PTR			 (0x1ffL<<0)
-#define BNX2_RPM_DEBUG3_RDE_RLUPQ_WR_REQ_INT		 (1L<<9)
-#define BNX2_RPM_DEBUG3_RDE_RBUF_WR_LAST_INT		 (1L<<10)
-#define BNX2_RPM_DEBUG3_RDE_RBUF_WR_REQ_INT		 (1L<<11)
-#define BNX2_RPM_DEBUG3_RDE_RBUF_FREE_REQ		 (1L<<12)
-#define BNX2_RPM_DEBUG3_RDE_RBUF_ALLOC_REQ		 (1L<<13)
-#define BNX2_RPM_DEBUG3_DFSM_MBUF_NOTAVAIL		 (1L<<14)
-#define BNX2_RPM_DEBUG3_RBUF_RDE_SOF_DROP		 (1L<<15)
-#define BNX2_RPM_DEBUG3_DFIFO_VLD_ENTRY_CT		 (0xfL<<16)
-#define BNX2_RPM_DEBUG3_RDE_SRC_FIFO_ALMFULL		 (1L<<21)
-#define BNX2_RPM_DEBUG3_DROP_NXT_VLD			 (1L<<22)
-#define BNX2_RPM_DEBUG3_DROP_NXT			 (1L<<23)
-#define BNX2_RPM_DEBUG3_FTQ_FSM				 (0x3L<<24)
-#define BNX2_RPM_DEBUG3_FTQ_FSM_IDLE			 (0x0L<<24)
-#define BNX2_RPM_DEBUG3_FTQ_FSM_WAIT_ACK		 (0x1L<<24)
-#define BNX2_RPM_DEBUG3_FTQ_FSM_WAIT_FREE		 (0x2L<<24)
-#define BNX2_RPM_DEBUG3_MBWRITE_FSM			 (0x3L<<26)
-#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_SOF		 (0x0L<<26)
-#define BNX2_RPM_DEBUG3_MBWRITE_FSM_GET_MBUF		 (0x1L<<26)
-#define BNX2_RPM_DEBUG3_MBWRITE_FSM_DMA_DATA		 (0x2L<<26)
-#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_DATA		 (0x3L<<26)
-#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_EOF		 (0x4L<<26)
-#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_MF_ACK		 (0x5L<<26)
-#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_DROP_NXT_VLD	 (0x6L<<26)
-#define BNX2_RPM_DEBUG3_MBWRITE_FSM_DONE		 (0x7L<<26)
-#define BNX2_RPM_DEBUG3_MBFREE_FSM			 (1L<<29)
-#define BNX2_RPM_DEBUG3_MBFREE_FSM_IDLE			 (0L<<29)
-#define BNX2_RPM_DEBUG3_MBFREE_FSM_WAIT_ACK		 (1L<<29)
-#define BNX2_RPM_DEBUG3_MBALLOC_FSM			 (1L<<30)
-#define BNX2_RPM_DEBUG3_MBALLOC_FSM_ET_MBUF		 (0x0L<<30)
-#define BNX2_RPM_DEBUG3_MBALLOC_FSM_IVE_MBUF		 (0x1L<<30)
-#define BNX2_RPM_DEBUG3_CCODE_EOF_ERROR			 (1L<<31)
-
-#define BNX2_RPM_DEBUG4					0x00001994
-#define BNX2_RPM_DEBUG4_DFSM_MBUF_CLUSTER		 (0x1ffffffL<<0)
-#define BNX2_RPM_DEBUG4_DFIFO_CUR_CCODE			 (0x7L<<25)
-#define BNX2_RPM_DEBUG4_MBWRITE_FSM			 (0x7L<<28)
-#define BNX2_RPM_DEBUG4_DFIFO_EMPTY			 (1L<<31)
-
-#define BNX2_RPM_DEBUG5					0x00001998
-#define BNX2_RPM_DEBUG5_RDROP_WPTR			 (0x1fL<<0)
-#define BNX2_RPM_DEBUG5_RDROP_ACPI_RPTR			 (0x1fL<<5)
-#define BNX2_RPM_DEBUG5_RDROP_MC_RPTR			 (0x1fL<<10)
-#define BNX2_RPM_DEBUG5_RDROP_RC_RPTR			 (0x1fL<<15)
-#define BNX2_RPM_DEBUG5_RDROP_ACPI_EMPTY		 (1L<<20)
-#define BNX2_RPM_DEBUG5_RDROP_MC_EMPTY			 (1L<<21)
-#define BNX2_RPM_DEBUG5_RDROP_AEOF_VEC_AT_RDROP_MC_RPTR	 (1L<<22)
-#define BNX2_RPM_DEBUG5_HOLDREG_WOL_DROP_INT		 (1L<<23)
-#define BNX2_RPM_DEBUG5_HOLDREG_DISCARD			 (1L<<24)
-#define BNX2_RPM_DEBUG5_HOLDREG_MBUF_NOTAVAIL		 (1L<<25)
-#define BNX2_RPM_DEBUG5_HOLDREG_MC_EMPTY		 (1L<<26)
-#define BNX2_RPM_DEBUG5_HOLDREG_RC_EMPTY		 (1L<<27)
-#define BNX2_RPM_DEBUG5_HOLDREG_FC_EMPTY		 (1L<<28)
-#define BNX2_RPM_DEBUG5_HOLDREG_ACPI_EMPTY		 (1L<<29)
-#define BNX2_RPM_DEBUG5_HOLDREG_FULL_T			 (1L<<30)
-#define BNX2_RPM_DEBUG5_HOLDREG_RD			 (1L<<31)
-
-#define BNX2_RPM_DEBUG6					0x0000199c
-#define BNX2_RPM_DEBUG6_ACPI_VEC			 (0xffffL<<0)
-#define BNX2_RPM_DEBUG6_VEC				 (0xffffL<<16)
-
-#define BNX2_RPM_DEBUG7					0x000019a0
-#define BNX2_RPM_DEBUG7_RPM_DBG7_LAST_CRC		 (0xffffffffL<<0)
-
-#define BNX2_RPM_DEBUG8					0x000019a4
-#define BNX2_RPM_DEBUG8_PS_ACPI_FSM			 (0xfL<<0)
-#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_IDLE		 (0L<<0)
-#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W1_ADDR		 (1L<<0)
-#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W2_ADDR		 (2L<<0)
-#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W3_ADDR		 (3L<<0)
-#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_WAIT_THBUF	 (4L<<0)
-#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W3_DATA		 (5L<<0)
-#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W0_ADDR		 (6L<<0)
-#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W1_ADDR		 (7L<<0)
-#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W2_ADDR		 (8L<<0)
-#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W3_ADDR		 (9L<<0)
-#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_WAIT_THBUF		 (10L<<0)
-#define BNX2_RPM_DEBUG8_COMPARE_AT_W0			 (1L<<4)
-#define BNX2_RPM_DEBUG8_COMPARE_AT_W3_DATA		 (1L<<5)
-#define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_WAIT		 (1L<<6)
-#define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_W3		 (1L<<7)
-#define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_W2		 (1L<<8)
-#define BNX2_RPM_DEBUG8_EOF_W_LTEQ6_VLDBYTES		 (1L<<9)
-#define BNX2_RPM_DEBUG8_EOF_W_LTEQ4_VLDBYTES		 (1L<<10)
-#define BNX2_RPM_DEBUG8_NXT_EOF_W_12_VLDBYTES		 (1L<<11)
-#define BNX2_RPM_DEBUG8_EOF_DET				 (1L<<12)
-#define BNX2_RPM_DEBUG8_SOF_DET				 (1L<<13)
-#define BNX2_RPM_DEBUG8_WAIT_4_SOF			 (1L<<14)
-#define BNX2_RPM_DEBUG8_ALL_DONE			 (1L<<15)
-#define BNX2_RPM_DEBUG8_THBUF_ADDR			 (0x7fL<<16)
-#define BNX2_RPM_DEBUG8_BYTE_CTR			 (0xffL<<24)
-
-#define BNX2_RPM_DEBUG9					0x000019a8
-#define BNX2_RPM_DEBUG9_OUTFIFO_COUNT			 (0x7L<<0)
-#define BNX2_RPM_DEBUG9_RDE_ACPI_RDY			 (1L<<3)
-#define BNX2_RPM_DEBUG9_VLD_RD_ENTRY_CT			 (0x7L<<4)
-#define BNX2_RPM_DEBUG9_OUTFIFO_OVERRUN_OCCURRED	 (1L<<28)
-#define BNX2_RPM_DEBUG9_INFIFO_OVERRUN_OCCURRED		 (1L<<29)
-#define BNX2_RPM_DEBUG9_ACPI_MATCH_INT			 (1L<<30)
-#define BNX2_RPM_DEBUG9_ACPI_ENABLE_SYN			 (1L<<31)
-#define BNX2_RPM_DEBUG9_BEMEM_R_XI			 (0x1fL<<0)
-#define BNX2_RPM_DEBUG9_EO_XI				 (1L<<5)
-#define BNX2_RPM_DEBUG9_AEOF_DE_XI			 (1L<<6)
-#define BNX2_RPM_DEBUG9_SO_XI				 (1L<<7)
-#define BNX2_RPM_DEBUG9_WD64_CT_XI			 (0x1fL<<8)
-#define BNX2_RPM_DEBUG9_EOF_VLDBYTE_XI			 (0x7L<<13)
-#define BNX2_RPM_DEBUG9_ACPI_RDE_PAT_ID_XI		 (0xfL<<16)
-#define BNX2_RPM_DEBUG9_CALCRC_RESULT_XI		 (0x3ffL<<20)
-#define BNX2_RPM_DEBUG9_DATA_IN_VL_XI			 (1L<<30)
-#define BNX2_RPM_DEBUG9_CALCRC_BUFFER_VLD_XI		 (1L<<31)
-
-#define BNX2_RPM_ACPI_DBG_BUF_W00			0x000019c0
-#define BNX2_RPM_ACPI_DBG_BUF_W01			0x000019c4
-#define BNX2_RPM_ACPI_DBG_BUF_W02			0x000019c8
-#define BNX2_RPM_ACPI_DBG_BUF_W03			0x000019cc
-#define BNX2_RPM_ACPI_DBG_BUF_W10			0x000019d0
-#define BNX2_RPM_ACPI_DBG_BUF_W11			0x000019d4
-#define BNX2_RPM_ACPI_DBG_BUF_W12			0x000019d8
-#define BNX2_RPM_ACPI_DBG_BUF_W13			0x000019dc
-#define BNX2_RPM_ACPI_DBG_BUF_W20			0x000019e0
-#define BNX2_RPM_ACPI_DBG_BUF_W21			0x000019e4
-#define BNX2_RPM_ACPI_DBG_BUF_W22			0x000019e8
-#define BNX2_RPM_ACPI_DBG_BUF_W23			0x000019ec
-#define BNX2_RPM_ACPI_DBG_BUF_W30			0x000019f0
-#define BNX2_RPM_ACPI_DBG_BUF_W31			0x000019f4
-#define BNX2_RPM_ACPI_DBG_BUF_W32			0x000019f8
-#define BNX2_RPM_ACPI_DBG_BUF_W33			0x000019fc
-#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL			0x00001a00
-#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_BYTE_ADDRESS	 (0xffffL<<0)
-#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_DEBUGRD		 (1L<<28)
-#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_MODE		 (1L<<29)
-#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_INIT		 (1L<<30)
-#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_WR		 (1L<<31)
-
-#define BNX2_RPM_ACPI_PATTERN_CTRL			0x00001a04
-#define BNX2_RPM_ACPI_PATTERN_CTRL_PATTERN_ID		 (0xfL<<0)
-#define BNX2_RPM_ACPI_PATTERN_CTRL_CRC_SM_CLR		 (1L<<30)
-#define BNX2_RPM_ACPI_PATTERN_CTRL_WR			 (1L<<31)
-
-#define BNX2_RPM_ACPI_DATA				0x00001a08
-#define BNX2_RPM_ACPI_DATA_PATTERN_BE			 (0xffffffffL<<0)
-
-#define BNX2_RPM_ACPI_PATTERN_LEN0			0x00001a0c
-#define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN3		 (0xffL<<0)
-#define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN2		 (0xffL<<8)
-#define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN1		 (0xffL<<16)
-#define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN0		 (0xffL<<24)
-
-#define BNX2_RPM_ACPI_PATTERN_LEN1			0x00001a10
-#define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN7		 (0xffL<<0)
-#define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN6		 (0xffL<<8)
-#define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN5		 (0xffL<<16)
-#define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN4		 (0xffL<<24)
-
-#define BNX2_RPM_ACPI_PATTERN_CRC0			0x00001a18
-#define BNX2_RPM_ACPI_PATTERN_CRC0_PATTERN_CRC0		 (0xffffffffL<<0)
-
-#define BNX2_RPM_ACPI_PATTERN_CRC1			0x00001a1c
-#define BNX2_RPM_ACPI_PATTERN_CRC1_PATTERN_CRC1		 (0xffffffffL<<0)
-
-#define BNX2_RPM_ACPI_PATTERN_CRC2			0x00001a20
-#define BNX2_RPM_ACPI_PATTERN_CRC2_PATTERN_CRC2		 (0xffffffffL<<0)
-
-#define BNX2_RPM_ACPI_PATTERN_CRC3			0x00001a24
-#define BNX2_RPM_ACPI_PATTERN_CRC3_PATTERN_CRC3		 (0xffffffffL<<0)
-
-#define BNX2_RPM_ACPI_PATTERN_CRC4			0x00001a28
-#define BNX2_RPM_ACPI_PATTERN_CRC4_PATTERN_CRC4		 (0xffffffffL<<0)
-
-#define BNX2_RPM_ACPI_PATTERN_CRC5			0x00001a2c
-#define BNX2_RPM_ACPI_PATTERN_CRC5_PATTERN_CRC5		 (0xffffffffL<<0)
-
-#define BNX2_RPM_ACPI_PATTERN_CRC6			0x00001a30
-#define BNX2_RPM_ACPI_PATTERN_CRC6_PATTERN_CRC6		 (0xffffffffL<<0)
-
-#define BNX2_RPM_ACPI_PATTERN_CRC7			0x00001a34
-#define BNX2_RPM_ACPI_PATTERN_CRC7_PATTERN_CRC7		 (0xffffffffL<<0)
-
-
-/*
- *  rlup_reg definition
- *  offset: 0x2000
- */
-#define BNX2_RLUP_RSS_CONFIG				0x0000201c
-#define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_XI		 (0x3L<<0)
-#define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_OFF_XI	 (0L<<0)
-#define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_ALL_XI	 (1L<<0)
-#define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_IP_ONLY_XI	 (2L<<0)
-#define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_RES_XI	 (3L<<0)
-#define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_XI		 (0x3L<<2)
-#define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_OFF_XI	 (0L<<2)
-#define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_ALL_XI	 (1L<<2)
-#define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_IP_ONLY_XI	 (2L<<2)
-#define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_RES_XI	 (3L<<2)
-
-#define BNX2_RLUP_RSS_COMMAND				0x00002048
-#define BNX2_RLUP_RSS_COMMAND_RSS_IND_TABLE_ADDR	 (0xfUL<<0)
-#define BNX2_RLUP_RSS_COMMAND_RSS_WRITE_MASK		 (0xffUL<<4)
-#define BNX2_RLUP_RSS_COMMAND_WRITE			 (1UL<<12)
-#define BNX2_RLUP_RSS_COMMAND_READ			 (1UL<<13)
-#define BNX2_RLUP_RSS_COMMAND_HASH_MASK			 (0x7UL<<14)
-
-#define BNX2_RLUP_RSS_DATA				0x0000204c
-
-
-/*
- *  rbuf_reg definition
- *  offset: 0x200000
- */
-#define BNX2_RBUF_COMMAND				0x00200000
-#define BNX2_RBUF_COMMAND_ENABLED			 (1L<<0)
-#define BNX2_RBUF_COMMAND_FREE_INIT			 (1L<<1)
-#define BNX2_RBUF_COMMAND_RAM_INIT			 (1L<<2)
-#define BNX2_RBUF_COMMAND_PKT_OFFSET_OVFL		 (1L<<3)
-#define BNX2_RBUF_COMMAND_OVER_FREE			 (1L<<4)
-#define BNX2_RBUF_COMMAND_ALLOC_REQ			 (1L<<5)
-#define BNX2_RBUF_COMMAND_EN_PRI_CHNGE_TE		 (1L<<6)
-#define BNX2_RBUF_COMMAND_CU_ISOLATE_XI			 (1L<<5)
-#define BNX2_RBUF_COMMAND_EN_PRI_CHANGE_XI		 (1L<<6)
-#define BNX2_RBUF_COMMAND_GRC_ENDIAN_CONV_DIS_XI	 (1L<<7)
-
-#define BNX2_RBUF_STATUS1				0x00200004
-#define BNX2_RBUF_STATUS1_FREE_COUNT			 (0x3ffL<<0)
-
-#define BNX2_RBUF_STATUS2				0x00200008
-#define BNX2_RBUF_STATUS2_FREE_TAIL			 (0x1ffL<<0)
-#define BNX2_RBUF_STATUS2_FREE_HEAD			 (0x1ffL<<16)
-
-#define BNX2_RBUF_CONFIG				0x0020000c
-#define BNX2_RBUF_CONFIG_XOFF_TRIP			 (0x3ffL<<0)
-#define BNX2_RBUF_CONFIG_XOFF_TRIP_VAL(mtu)		 \
-	((((mtu) - 1500) * 31 / 1000) + 54)
-#define BNX2_RBUF_CONFIG_XON_TRIP			 (0x3ffL<<16)
-#define BNX2_RBUF_CONFIG_XON_TRIP_VAL(mtu)		 \
-	((((mtu) - 1500) * 39 / 1000) + 66)
-#define BNX2_RBUF_CONFIG_VAL(mtu)			 \
-	(BNX2_RBUF_CONFIG_XOFF_TRIP_VAL(mtu) |		 \
-	(BNX2_RBUF_CONFIG_XON_TRIP_VAL(mtu) << 16))
-
-#define BNX2_RBUF_FW_BUF_ALLOC				0x00200010
-#define BNX2_RBUF_FW_BUF_ALLOC_VALUE			 (0x1ffL<<7)
-#define BNX2_RBUF_FW_BUF_ALLOC_TYPE			 (1L<<16)
-#define BNX2_RBUF_FW_BUF_ALLOC_ALLOC_REQ		 (1L<<31)
-
-#define BNX2_RBUF_FW_BUF_FREE				0x00200014
-#define BNX2_RBUF_FW_BUF_FREE_COUNT			 (0x7fL<<0)
-#define BNX2_RBUF_FW_BUF_FREE_TAIL			 (0x1ffL<<7)
-#define BNX2_RBUF_FW_BUF_FREE_HEAD			 (0x1ffL<<16)
-#define BNX2_RBUF_FW_BUF_FREE_TYPE			 (1L<<25)
-#define BNX2_RBUF_FW_BUF_FREE_FREE_REQ			 (1L<<31)
-
-#define BNX2_RBUF_FW_BUF_SEL				0x00200018
-#define BNX2_RBUF_FW_BUF_SEL_COUNT			 (0x7fL<<0)
-#define BNX2_RBUF_FW_BUF_SEL_TAIL			 (0x1ffL<<7)
-#define BNX2_RBUF_FW_BUF_SEL_HEAD			 (0x1ffL<<16)
-#define BNX2_RBUF_FW_BUF_SEL_SEL_REQ			 (1L<<31)
-
-#define BNX2_RBUF_CONFIG2				0x0020001c
-#define BNX2_RBUF_CONFIG2_MAC_DROP_TRIP			 (0x3ffL<<0)
-#define BNX2_RBUF_CONFIG2_MAC_DROP_TRIP_VAL(mtu)	 \
-	((((mtu) - 1500) * 4 / 1000) + 5)
-#define BNX2_RBUF_CONFIG2_MAC_KEEP_TRIP			 (0x3ffL<<16)
-#define BNX2_RBUF_CONFIG2_MAC_KEEP_TRIP_VAL(mtu)	 \
-	((((mtu) - 1500) * 2 / 100) + 30)
-#define BNX2_RBUF_CONFIG2_VAL(mtu)			 \
-	(BNX2_RBUF_CONFIG2_MAC_DROP_TRIP_VAL(mtu) |	 \
-	(BNX2_RBUF_CONFIG2_MAC_KEEP_TRIP_VAL(mtu) << 16))
-
-#define BNX2_RBUF_CONFIG3				0x00200020
-#define BNX2_RBUF_CONFIG3_CU_DROP_TRIP			 (0x3ffL<<0)
-#define BNX2_RBUF_CONFIG3_CU_DROP_TRIP_VAL(mtu)		 \
-	((((mtu) - 1500) * 12 / 1000) + 18)
-#define BNX2_RBUF_CONFIG3_CU_KEEP_TRIP			 (0x3ffL<<16)
-#define BNX2_RBUF_CONFIG3_CU_KEEP_TRIP_VAL(mtu)		 \
-	((((mtu) - 1500) * 2 / 100) + 30)
-#define BNX2_RBUF_CONFIG3_VAL(mtu)			 \
-	(BNX2_RBUF_CONFIG3_CU_DROP_TRIP_VAL(mtu) |	 \
-	(BNX2_RBUF_CONFIG3_CU_KEEP_TRIP_VAL(mtu) << 16))
-
-#define BNX2_RBUF_PKT_DATA				0x00208000
-#define BNX2_RBUF_CLIST_DATA				0x00210000
-#define BNX2_RBUF_BUF_DATA				0x00220000
-
-
-/*
- *  rv2p_reg definition
- *  offset: 0x2800
- */
-#define BNX2_RV2P_COMMAND				0x00002800
-#define BNX2_RV2P_COMMAND_ENABLED			 (1L<<0)
-#define BNX2_RV2P_COMMAND_PROC1_INTRPT			 (1L<<1)
-#define BNX2_RV2P_COMMAND_PROC2_INTRPT			 (1L<<2)
-#define BNX2_RV2P_COMMAND_ABORT0			 (1L<<4)
-#define BNX2_RV2P_COMMAND_ABORT1			 (1L<<5)
-#define BNX2_RV2P_COMMAND_ABORT2			 (1L<<6)
-#define BNX2_RV2P_COMMAND_ABORT3			 (1L<<7)
-#define BNX2_RV2P_COMMAND_ABORT4			 (1L<<8)
-#define BNX2_RV2P_COMMAND_ABORT5			 (1L<<9)
-#define BNX2_RV2P_COMMAND_PROC1_RESET			 (1L<<16)
-#define BNX2_RV2P_COMMAND_PROC2_RESET			 (1L<<17)
-#define BNX2_RV2P_COMMAND_CTXIF_RESET			 (1L<<18)
-
-#define BNX2_RV2P_STATUS				0x00002804
-#define BNX2_RV2P_STATUS_ALWAYS_0			 (1L<<0)
-#define BNX2_RV2P_STATUS_RV2P_GEN_STAT0_CNT		 (1L<<8)
-#define BNX2_RV2P_STATUS_RV2P_GEN_STAT1_CNT		 (1L<<9)
-#define BNX2_RV2P_STATUS_RV2P_GEN_STAT2_CNT		 (1L<<10)
-#define BNX2_RV2P_STATUS_RV2P_GEN_STAT3_CNT		 (1L<<11)
-#define BNX2_RV2P_STATUS_RV2P_GEN_STAT4_CNT		 (1L<<12)
-#define BNX2_RV2P_STATUS_RV2P_GEN_STAT5_CNT		 (1L<<13)
-
-#define BNX2_RV2P_CONFIG				0x00002808
-#define BNX2_RV2P_CONFIG_STALL_PROC1			 (1L<<0)
-#define BNX2_RV2P_CONFIG_STALL_PROC2			 (1L<<1)
-#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT0		 (1L<<8)
-#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT1		 (1L<<9)
-#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT2		 (1L<<10)
-#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT3		 (1L<<11)
-#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT4		 (1L<<12)
-#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT5		 (1L<<13)
-#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT0		 (1L<<16)
-#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT1		 (1L<<17)
-#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT2		 (1L<<18)
-#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT3		 (1L<<19)
-#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT4		 (1L<<20)
-#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT5		 (1L<<21)
-#define BNX2_RV2P_CONFIG_PAGE_SIZE			 (0xfL<<24)
-#define BNX2_RV2P_CONFIG_PAGE_SIZE_256			 (0L<<24)
-#define BNX2_RV2P_CONFIG_PAGE_SIZE_512			 (1L<<24)
-#define BNX2_RV2P_CONFIG_PAGE_SIZE_1K			 (2L<<24)
-#define BNX2_RV2P_CONFIG_PAGE_SIZE_2K			 (3L<<24)
-#define BNX2_RV2P_CONFIG_PAGE_SIZE_4K			 (4L<<24)
-#define BNX2_RV2P_CONFIG_PAGE_SIZE_8K			 (5L<<24)
-#define BNX2_RV2P_CONFIG_PAGE_SIZE_16K			 (6L<<24)
-#define BNX2_RV2P_CONFIG_PAGE_SIZE_32K			 (7L<<24)
-#define BNX2_RV2P_CONFIG_PAGE_SIZE_64K			 (8L<<24)
-#define BNX2_RV2P_CONFIG_PAGE_SIZE_128K			 (9L<<24)
-#define BNX2_RV2P_CONFIG_PAGE_SIZE_256K			 (10L<<24)
-#define BNX2_RV2P_CONFIG_PAGE_SIZE_512K			 (11L<<24)
-#define BNX2_RV2P_CONFIG_PAGE_SIZE_1M			 (12L<<24)
-
-#define BNX2_RV2P_GEN_BFR_ADDR_0			0x00002810
-#define BNX2_RV2P_GEN_BFR_ADDR_0_VALUE			 (0xffffL<<16)
-
-#define BNX2_RV2P_GEN_BFR_ADDR_1			0x00002814
-#define BNX2_RV2P_GEN_BFR_ADDR_1_VALUE			 (0xffffL<<16)
-
-#define BNX2_RV2P_GEN_BFR_ADDR_2			0x00002818
-#define BNX2_RV2P_GEN_BFR_ADDR_2_VALUE			 (0xffffL<<16)
-
-#define BNX2_RV2P_GEN_BFR_ADDR_3			0x0000281c
-#define BNX2_RV2P_GEN_BFR_ADDR_3_VALUE			 (0xffffL<<16)
-
-#define BNX2_RV2P_INSTR_HIGH				0x00002830
-#define BNX2_RV2P_INSTR_HIGH_HIGH			 (0x1fL<<0)
-
-#define BNX2_RV2P_INSTR_LOW				0x00002834
-#define BNX2_RV2P_INSTR_LOW_LOW				 (0xffffffffL<<0)
-
-#define BNX2_RV2P_PROC1_ADDR_CMD			0x00002838
-#define BNX2_RV2P_PROC1_ADDR_CMD_ADD			 (0x3ffL<<0)
-#define BNX2_RV2P_PROC1_ADDR_CMD_RDWR			 (1L<<31)
-
-#define BNX2_RV2P_PROC2_ADDR_CMD			0x0000283c
-#define BNX2_RV2P_PROC2_ADDR_CMD_ADD			 (0x3ffL<<0)
-#define BNX2_RV2P_PROC2_ADDR_CMD_RDWR			 (1L<<31)
-
-#define BNX2_RV2P_PROC1_GRC_DEBUG			0x00002840
-#define BNX2_RV2P_PROC2_GRC_DEBUG			0x00002844
-#define BNX2_RV2P_GRC_PROC_DEBUG			0x00002848
-#define BNX2_RV2P_DEBUG_VECT_PEEK			0x0000284c
-#define BNX2_RV2P_DEBUG_VECT_PEEK_1_VALUE		 (0x7ffL<<0)
-#define BNX2_RV2P_DEBUG_VECT_PEEK_1_PEEK_EN		 (1L<<11)
-#define BNX2_RV2P_DEBUG_VECT_PEEK_1_SEL			 (0xfL<<12)
-#define BNX2_RV2P_DEBUG_VECT_PEEK_2_VALUE		 (0x7ffL<<16)
-#define BNX2_RV2P_DEBUG_VECT_PEEK_2_PEEK_EN		 (1L<<27)
-#define BNX2_RV2P_DEBUG_VECT_PEEK_2_SEL			 (0xfL<<28)
-
-#define BNX2_RV2P_MPFE_PFE_CTL				0x00002afc
-#define BNX2_RV2P_MPFE_PFE_CTL_INC_USAGE_CNT		 (1L<<0)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE			 (0xfL<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_0		 (0L<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_1		 (1L<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_2		 (2L<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_3		 (3L<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_4		 (4L<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_5		 (5L<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_6		 (6L<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_7		 (7L<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_8		 (8L<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_9		 (9L<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_10		 (10L<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_11		 (11L<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_12		 (12L<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_13		 (13L<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_14		 (14L<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_15		 (15L<<4)
-#define BNX2_RV2P_MPFE_PFE_CTL_PFE_COUNT		 (0xfL<<12)
-#define BNX2_RV2P_MPFE_PFE_CTL_OFFSET			 (0x1ffL<<16)
-
-#define BNX2_RV2P_RV2PPQ				0x00002b40
-#define BNX2_RV2P_PFTQ_CMD				0x00002b78
-#define BNX2_RV2P_PFTQ_CMD_OFFSET			 (0x3ffL<<0)
-#define BNX2_RV2P_PFTQ_CMD_WR_TOP			 (1L<<10)
-#define BNX2_RV2P_PFTQ_CMD_WR_TOP_0			 (0L<<10)
-#define BNX2_RV2P_PFTQ_CMD_WR_TOP_1			 (1L<<10)
-#define BNX2_RV2P_PFTQ_CMD_SFT_RESET			 (1L<<25)
-#define BNX2_RV2P_PFTQ_CMD_RD_DATA			 (1L<<26)
-#define BNX2_RV2P_PFTQ_CMD_ADD_INTERVEN			 (1L<<27)
-#define BNX2_RV2P_PFTQ_CMD_ADD_DATA			 (1L<<28)
-#define BNX2_RV2P_PFTQ_CMD_INTERVENE_CLR		 (1L<<29)
-#define BNX2_RV2P_PFTQ_CMD_POP				 (1L<<30)
-#define BNX2_RV2P_PFTQ_CMD_BUSY				 (1L<<31)
-
-#define BNX2_RV2P_PFTQ_CTL				0x00002b7c
-#define BNX2_RV2P_PFTQ_CTL_INTERVENE			 (1L<<0)
-#define BNX2_RV2P_PFTQ_CTL_OVERFLOW			 (1L<<1)
-#define BNX2_RV2P_PFTQ_CTL_FORCE_INTERVENE		 (1L<<2)
-#define BNX2_RV2P_PFTQ_CTL_MAX_DEPTH			 (0x3ffL<<12)
-#define BNX2_RV2P_PFTQ_CTL_CUR_DEPTH			 (0x3ffL<<22)
-
-#define BNX2_RV2P_RV2PTQ				0x00002b80
-#define BNX2_RV2P_TFTQ_CMD				0x00002bb8
-#define BNX2_RV2P_TFTQ_CMD_OFFSET			 (0x3ffL<<0)
-#define BNX2_RV2P_TFTQ_CMD_WR_TOP			 (1L<<10)
-#define BNX2_RV2P_TFTQ_CMD_WR_TOP_0			 (0L<<10)
-#define BNX2_RV2P_TFTQ_CMD_WR_TOP_1			 (1L<<10)
-#define BNX2_RV2P_TFTQ_CMD_SFT_RESET			 (1L<<25)
-#define BNX2_RV2P_TFTQ_CMD_RD_DATA			 (1L<<26)
-#define BNX2_RV2P_TFTQ_CMD_ADD_INTERVEN			 (1L<<27)
-#define BNX2_RV2P_TFTQ_CMD_ADD_DATA			 (1L<<28)
-#define BNX2_RV2P_TFTQ_CMD_INTERVENE_CLR		 (1L<<29)
-#define BNX2_RV2P_TFTQ_CMD_POP				 (1L<<30)
-#define BNX2_RV2P_TFTQ_CMD_BUSY				 (1L<<31)
-
-#define BNX2_RV2P_TFTQ_CTL				0x00002bbc
-#define BNX2_RV2P_TFTQ_CTL_INTERVENE			 (1L<<0)
-#define BNX2_RV2P_TFTQ_CTL_OVERFLOW			 (1L<<1)
-#define BNX2_RV2P_TFTQ_CTL_FORCE_INTERVENE		 (1L<<2)
-#define BNX2_RV2P_TFTQ_CTL_MAX_DEPTH			 (0x3ffL<<12)
-#define BNX2_RV2P_TFTQ_CTL_CUR_DEPTH			 (0x3ffL<<22)
-
-#define BNX2_RV2P_RV2PMQ				0x00002bc0
-#define BNX2_RV2P_MFTQ_CMD				0x00002bf8
-#define BNX2_RV2P_MFTQ_CMD_OFFSET			 (0x3ffL<<0)
-#define BNX2_RV2P_MFTQ_CMD_WR_TOP			 (1L<<10)
-#define BNX2_RV2P_MFTQ_CMD_WR_TOP_0			 (0L<<10)
-#define BNX2_RV2P_MFTQ_CMD_WR_TOP_1			 (1L<<10)
-#define BNX2_RV2P_MFTQ_CMD_SFT_RESET			 (1L<<25)
-#define BNX2_RV2P_MFTQ_CMD_RD_DATA			 (1L<<26)
-#define BNX2_RV2P_MFTQ_CMD_ADD_INTERVEN			 (1L<<27)
-#define BNX2_RV2P_MFTQ_CMD_ADD_DATA			 (1L<<28)
-#define BNX2_RV2P_MFTQ_CMD_INTERVENE_CLR		 (1L<<29)
-#define BNX2_RV2P_MFTQ_CMD_POP				 (1L<<30)
-#define BNX2_RV2P_MFTQ_CMD_BUSY				 (1L<<31)
-
-#define BNX2_RV2P_MFTQ_CTL				0x00002bfc
-#define BNX2_RV2P_MFTQ_CTL_INTERVENE			 (1L<<0)
-#define BNX2_RV2P_MFTQ_CTL_OVERFLOW			 (1L<<1)
-#define BNX2_RV2P_MFTQ_CTL_FORCE_INTERVENE		 (1L<<2)
-#define BNX2_RV2P_MFTQ_CTL_MAX_DEPTH			 (0x3ffL<<12)
-#define BNX2_RV2P_MFTQ_CTL_CUR_DEPTH			 (0x3ffL<<22)
-
-
-
-/*
- *  mq_reg definition
- *  offset: 0x3c00
- */
-#define BNX2_MQ_COMMAND					0x00003c00
-#define BNX2_MQ_COMMAND_ENABLED				 (1L<<0)
-#define BNX2_MQ_COMMAND_INIT				 (1L<<1)
-#define BNX2_MQ_COMMAND_OVERFLOW			 (1L<<4)
-#define BNX2_MQ_COMMAND_WR_ERROR			 (1L<<5)
-#define BNX2_MQ_COMMAND_RD_ERROR			 (1L<<6)
-#define BNX2_MQ_COMMAND_IDB_CFG_ERROR			 (1L<<7)
-#define BNX2_MQ_COMMAND_IDB_OVERFLOW			 (1L<<10)
-#define BNX2_MQ_COMMAND_NO_BIN_ERROR			 (1L<<11)
-#define BNX2_MQ_COMMAND_NO_MAP_ERROR			 (1L<<12)
-
-#define BNX2_MQ_STATUS					0x00003c04
-#define BNX2_MQ_STATUS_CTX_ACCESS_STAT			 (1L<<16)
-#define BNX2_MQ_STATUS_CTX_ACCESS64_STAT		 (1L<<17)
-#define BNX2_MQ_STATUS_PCI_STALL_STAT			 (1L<<18)
-#define BNX2_MQ_STATUS_IDB_OFLOW_STAT			 (1L<<19)
-
-#define BNX2_MQ_CONFIG					0x00003c08
-#define BNX2_MQ_CONFIG_TX_HIGH_PRI			 (1L<<0)
-#define BNX2_MQ_CONFIG_HALT_DIS				 (1L<<1)
-#define BNX2_MQ_CONFIG_BIN_MQ_MODE			 (1L<<2)
-#define BNX2_MQ_CONFIG_DIS_IDB_DROP			 (1L<<3)
-#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE			 (0x7L<<4)
-#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256		 (0L<<4)
-#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_512		 (1L<<4)
-#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_1K		 (2L<<4)
-#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_2K		 (3L<<4)
-#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_4K		 (4L<<4)
-#define BNX2_MQ_CONFIG_MAX_DEPTH			 (0x7fL<<8)
-#define BNX2_MQ_CONFIG_CUR_DEPTH			 (0x7fL<<20)
-
-#define BNX2_MQ_ENQUEUE1				0x00003c0c
-#define BNX2_MQ_ENQUEUE1_OFFSET				 (0x3fL<<2)
-#define BNX2_MQ_ENQUEUE1_CID				 (0x3fffL<<8)
-#define BNX2_MQ_ENQUEUE1_BYTE_MASK			 (0xfL<<24)
-#define BNX2_MQ_ENQUEUE1_KNL_MODE			 (1L<<28)
-
-#define BNX2_MQ_ENQUEUE2				0x00003c10
-#define BNX2_MQ_BAD_WR_ADDR				0x00003c14
-#define BNX2_MQ_BAD_RD_ADDR				0x00003c18
-#define BNX2_MQ_KNL_BYP_WIND_START			0x00003c1c
-#define BNX2_MQ_KNL_BYP_WIND_START_VALUE		 (0xfffffL<<12)
-
-#define BNX2_MQ_KNL_WIND_END				0x00003c20
-#define BNX2_MQ_KNL_WIND_END_VALUE			 (0xffffffL<<8)
-
-#define BNX2_MQ_KNL_WRITE_MASK1				0x00003c24
-#define BNX2_MQ_KNL_TX_MASK1				0x00003c28
-#define BNX2_MQ_KNL_CMD_MASK1				0x00003c2c
-#define BNX2_MQ_KNL_COND_ENQUEUE_MASK1			0x00003c30
-#define BNX2_MQ_KNL_RX_V2P_MASK1			0x00003c34
-#define BNX2_MQ_KNL_WRITE_MASK2				0x00003c38
-#define BNX2_MQ_KNL_TX_MASK2				0x00003c3c
-#define BNX2_MQ_KNL_CMD_MASK2				0x00003c40
-#define BNX2_MQ_KNL_COND_ENQUEUE_MASK2			0x00003c44
-#define BNX2_MQ_KNL_RX_V2P_MASK2			0x00003c48
-#define BNX2_MQ_KNL_BYP_WRITE_MASK1			0x00003c4c
-#define BNX2_MQ_KNL_BYP_TX_MASK1			0x00003c50
-#define BNX2_MQ_KNL_BYP_CMD_MASK1			0x00003c54
-#define BNX2_MQ_KNL_BYP_COND_ENQUEUE_MASK1		0x00003c58
-#define BNX2_MQ_KNL_BYP_RX_V2P_MASK1			0x00003c5c
-#define BNX2_MQ_KNL_BYP_WRITE_MASK2			0x00003c60
-#define BNX2_MQ_KNL_BYP_TX_MASK2			0x00003c64
-#define BNX2_MQ_KNL_BYP_CMD_MASK2			0x00003c68
-#define BNX2_MQ_KNL_BYP_COND_ENQUEUE_MASK2		0x00003c6c
-#define BNX2_MQ_KNL_BYP_RX_V2P_MASK2			0x00003c70
-#define BNX2_MQ_MEM_WR_ADDR				0x00003c74
-#define BNX2_MQ_MEM_WR_ADDR_VALUE			 (0x3fL<<0)
-
-#define BNX2_MQ_MEM_WR_DATA0				0x00003c78
-#define BNX2_MQ_MEM_WR_DATA0_VALUE			 (0xffffffffL<<0)
-
-#define BNX2_MQ_MEM_WR_DATA1				0x00003c7c
-#define BNX2_MQ_MEM_WR_DATA1_VALUE			 (0xffffffffL<<0)
-
-#define BNX2_MQ_MEM_WR_DATA2				0x00003c80
-#define BNX2_MQ_MEM_WR_DATA2_VALUE			 (0x3fffffffL<<0)
-#define BNX2_MQ_MEM_WR_DATA2_VALUE_XI			 (0x7fffffffL<<0)
-
-#define BNX2_MQ_MEM_RD_ADDR				0x00003c84
-#define BNX2_MQ_MEM_RD_ADDR_VALUE			 (0x3fL<<0)
-
-#define BNX2_MQ_MEM_RD_DATA0				0x00003c88
-#define BNX2_MQ_MEM_RD_DATA0_VALUE			 (0xffffffffL<<0)
-
-#define BNX2_MQ_MEM_RD_DATA1				0x00003c8c
-#define BNX2_MQ_MEM_RD_DATA1_VALUE			 (0xffffffffL<<0)
-
-#define BNX2_MQ_MEM_RD_DATA2				0x00003c90
-#define BNX2_MQ_MEM_RD_DATA2_VALUE			 (0x3fffffffL<<0)
-#define BNX2_MQ_MEM_RD_DATA2_VALUE_XI			 (0x7fffffffL<<0)
-
-#define BNX2_MQ_MAP_L2_3				0x00003d2c
-#define BNX2_MQ_MAP_L2_3_MQ_OFFSET			 (0xffL<<0)
-#define BNX2_MQ_MAP_L2_3_SZ				 (0x3L<<8)
-#define BNX2_MQ_MAP_L2_3_CTX_OFFSET			 (0x2ffL<<10)
-#define BNX2_MQ_MAP_L2_3_BIN_OFFSET			 (0x7L<<23)
-#define BNX2_MQ_MAP_L2_3_ARM				 (0x3L<<26)
-#define BNX2_MQ_MAP_L2_3_ENA				 (0x1L<<31)
-#define BNX2_MQ_MAP_L2_3_DEFAULT			 0x82004646
-
-#define BNX2_MQ_MAP_L2_5				0x00003d34
-#define BNX2_MQ_MAP_L2_5_ARM				 (0x3L<<26)
-
-/*
- *  tsch_reg definition
- *  offset: 0x4c00
- */
-#define BNX2_TSCH_TSS_CFG				0x00004c1c
-#define BNX2_TSCH_TSS_CFG_TSS_START_CID			 (0x7ffL<<8)
-#define BNX2_TSCH_TSS_CFG_NUM_OF_TSS_CON		 (0xfL<<24)
-
-
-
-/*
- *  tbdr_reg definition
- *  offset: 0x5000
- */
-#define BNX2_TBDR_COMMAND				0x00005000
-#define BNX2_TBDR_COMMAND_ENABLE			 (1L<<0)
-#define BNX2_TBDR_COMMAND_SOFT_RST			 (1L<<1)
-#define BNX2_TBDR_COMMAND_MSTR_ABORT			 (1L<<4)
-
-#define BNX2_TBDR_STATUS				0x00005004
-#define BNX2_TBDR_STATUS_DMA_WAIT			 (1L<<0)
-#define BNX2_TBDR_STATUS_FTQ_WAIT			 (1L<<1)
-#define BNX2_TBDR_STATUS_FIFO_OVERFLOW			 (1L<<2)
-#define BNX2_TBDR_STATUS_FIFO_UNDERFLOW			 (1L<<3)
-#define BNX2_TBDR_STATUS_SEARCHMISS_ERROR		 (1L<<4)
-#define BNX2_TBDR_STATUS_FTQ_ENTRY_CNT			 (1L<<5)
-#define BNX2_TBDR_STATUS_BURST_CNT			 (1L<<6)
-
-#define BNX2_TBDR_CONFIG				0x00005008
-#define BNX2_TBDR_CONFIG_MAX_BDS			 (0xffL<<0)
-#define BNX2_TBDR_CONFIG_SWAP_MODE			 (1L<<8)
-#define BNX2_TBDR_CONFIG_PRIORITY			 (1L<<9)
-#define BNX2_TBDR_CONFIG_CACHE_NEXT_PAGE_PTRS		 (1L<<10)
-#define BNX2_TBDR_CONFIG_PAGE_SIZE			 (0xfL<<24)
-#define BNX2_TBDR_CONFIG_PAGE_SIZE_256			 (0L<<24)
-#define BNX2_TBDR_CONFIG_PAGE_SIZE_512			 (1L<<24)
-#define BNX2_TBDR_CONFIG_PAGE_SIZE_1K			 (2L<<24)
-#define BNX2_TBDR_CONFIG_PAGE_SIZE_2K			 (3L<<24)
-#define BNX2_TBDR_CONFIG_PAGE_SIZE_4K			 (4L<<24)
-#define BNX2_TBDR_CONFIG_PAGE_SIZE_8K			 (5L<<24)
-#define BNX2_TBDR_CONFIG_PAGE_SIZE_16K			 (6L<<24)
-#define BNX2_TBDR_CONFIG_PAGE_SIZE_32K			 (7L<<24)
-#define BNX2_TBDR_CONFIG_PAGE_SIZE_64K			 (8L<<24)
-#define BNX2_TBDR_CONFIG_PAGE_SIZE_128K			 (9L<<24)
-#define BNX2_TBDR_CONFIG_PAGE_SIZE_256K			 (10L<<24)
-#define BNX2_TBDR_CONFIG_PAGE_SIZE_512K			 (11L<<24)
-#define BNX2_TBDR_CONFIG_PAGE_SIZE_1M			 (12L<<24)
-
-#define BNX2_TBDR_DEBUG_VECT_PEEK			0x0000500c
-#define BNX2_TBDR_DEBUG_VECT_PEEK_1_VALUE		 (0x7ffL<<0)
-#define BNX2_TBDR_DEBUG_VECT_PEEK_1_PEEK_EN		 (1L<<11)
-#define BNX2_TBDR_DEBUG_VECT_PEEK_1_SEL			 (0xfL<<12)
-#define BNX2_TBDR_DEBUG_VECT_PEEK_2_VALUE		 (0x7ffL<<16)
-#define BNX2_TBDR_DEBUG_VECT_PEEK_2_PEEK_EN		 (1L<<27)
-#define BNX2_TBDR_DEBUG_VECT_PEEK_2_SEL			 (0xfL<<28)
-
-#define BNX2_TBDR_CKSUM_ERROR_STATUS			0x00005010
-#define BNX2_TBDR_CKSUM_ERROR_STATUS_CALCULATED		 (0xffffL<<0)
-#define BNX2_TBDR_CKSUM_ERROR_STATUS_EXPECTED		 (0xffffL<<16)
-
-#define BNX2_TBDR_TBDRQ					0x000053c0
-#define BNX2_TBDR_FTQ_CMD				0x000053f8
-#define BNX2_TBDR_FTQ_CMD_OFFSET			 (0x3ffL<<0)
-#define BNX2_TBDR_FTQ_CMD_WR_TOP			 (1L<<10)
-#define BNX2_TBDR_FTQ_CMD_WR_TOP_0			 (0L<<10)
-#define BNX2_TBDR_FTQ_CMD_WR_TOP_1			 (1L<<10)
-#define BNX2_TBDR_FTQ_CMD_SFT_RESET			 (1L<<25)
-#define BNX2_TBDR_FTQ_CMD_RD_DATA			 (1L<<26)
-#define BNX2_TBDR_FTQ_CMD_ADD_INTERVEN			 (1L<<27)
-#define BNX2_TBDR_FTQ_CMD_ADD_DATA			 (1L<<28)
-#define BNX2_TBDR_FTQ_CMD_INTERVENE_CLR			 (1L<<29)
-#define BNX2_TBDR_FTQ_CMD_POP				 (1L<<30)
-#define BNX2_TBDR_FTQ_CMD_BUSY				 (1L<<31)
-
-#define BNX2_TBDR_FTQ_CTL				0x000053fc
-#define BNX2_TBDR_FTQ_CTL_INTERVENE			 (1L<<0)
-#define BNX2_TBDR_FTQ_CTL_OVERFLOW			 (1L<<1)
-#define BNX2_TBDR_FTQ_CTL_FORCE_INTERVENE		 (1L<<2)
-#define BNX2_TBDR_FTQ_CTL_MAX_DEPTH			 (0x3ffL<<12)
-#define BNX2_TBDR_FTQ_CTL_CUR_DEPTH			 (0x3ffL<<22)
-
-
-
-/*
- *  tdma_reg definition
- *  offset: 0x5c00
- */
-#define BNX2_TDMA_COMMAND				0x00005c00
-#define BNX2_TDMA_COMMAND_ENABLED			 (1L<<0)
-#define BNX2_TDMA_COMMAND_MASTER_ABORT			 (1L<<4)
-#define BNX2_TDMA_COMMAND_CS16_ERR			 (1L<<5)
-#define BNX2_TDMA_COMMAND_BAD_L2_LENGTH_ABORT		 (1L<<7)
-#define BNX2_TDMA_COMMAND_MASK_CS1			 (1L<<20)
-#define BNX2_TDMA_COMMAND_MASK_CS2			 (1L<<21)
-#define BNX2_TDMA_COMMAND_MASK_CS3			 (1L<<22)
-#define BNX2_TDMA_COMMAND_MASK_CS4			 (1L<<23)
-#define BNX2_TDMA_COMMAND_FORCE_ILOCK_CKERR		 (1L<<24)
-#define BNX2_TDMA_COMMAND_OFIFO_CLR			 (1L<<30)
-#define BNX2_TDMA_COMMAND_IFIFO_CLR			 (1L<<31)
-
-#define BNX2_TDMA_STATUS				0x00005c04
-#define BNX2_TDMA_STATUS_DMA_WAIT			 (1L<<0)
-#define BNX2_TDMA_STATUS_PAYLOAD_WAIT			 (1L<<1)
-#define BNX2_TDMA_STATUS_PATCH_FTQ_WAIT			 (1L<<2)
-#define BNX2_TDMA_STATUS_LOCK_WAIT			 (1L<<3)
-#define BNX2_TDMA_STATUS_FTQ_ENTRY_CNT			 (1L<<16)
-#define BNX2_TDMA_STATUS_BURST_CNT			 (1L<<17)
-#define BNX2_TDMA_STATUS_MAX_IFIFO_DEPTH		 (0x3fL<<20)
-#define BNX2_TDMA_STATUS_OFIFO_OVERFLOW			 (1L<<30)
-#define BNX2_TDMA_STATUS_IFIFO_OVERFLOW			 (1L<<31)
-
-#define BNX2_TDMA_CONFIG				0x00005c08
-#define BNX2_TDMA_CONFIG_ONE_DMA			 (1L<<0)
-#define BNX2_TDMA_CONFIG_ONE_RECORD			 (1L<<1)
-#define BNX2_TDMA_CONFIG_NUM_DMA_CHAN			 (0x3L<<2)
-#define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_0			 (0L<<2)
-#define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_1			 (1L<<2)
-#define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_2			 (2L<<2)
-#define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_3			 (3L<<2)
-#define BNX2_TDMA_CONFIG_LIMIT_SZ			 (0xfL<<4)
-#define BNX2_TDMA_CONFIG_LIMIT_SZ_64			 (0L<<4)
-#define BNX2_TDMA_CONFIG_LIMIT_SZ_128			 (0x4L<<4)
-#define BNX2_TDMA_CONFIG_LIMIT_SZ_256			 (0x6L<<4)
-#define BNX2_TDMA_CONFIG_LIMIT_SZ_512			 (0x8L<<4)
-#define BNX2_TDMA_CONFIG_LINE_SZ			 (0xfL<<8)
-#define BNX2_TDMA_CONFIG_LINE_SZ_64			 (0L<<8)
-#define BNX2_TDMA_CONFIG_LINE_SZ_128			 (4L<<8)
-#define BNX2_TDMA_CONFIG_LINE_SZ_256			 (6L<<8)
-#define BNX2_TDMA_CONFIG_LINE_SZ_512			 (8L<<8)
-#define BNX2_TDMA_CONFIG_ALIGN_ENA			 (1L<<15)
-#define BNX2_TDMA_CONFIG_CHK_L2_BD			 (1L<<16)
-#define BNX2_TDMA_CONFIG_CMPL_ENTRY			 (1L<<17)
-#define BNX2_TDMA_CONFIG_OFIFO_CMP			 (1L<<19)
-#define BNX2_TDMA_CONFIG_OFIFO_CMP_3			 (0L<<19)
-#define BNX2_TDMA_CONFIG_OFIFO_CMP_2			 (1L<<19)
-#define BNX2_TDMA_CONFIG_FIFO_CMP			 (0xfL<<20)
-#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_XI			 (0x7L<<20)
-#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_0_XI		 (0L<<20)
-#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_4_XI		 (1L<<20)
-#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_8_XI		 (2L<<20)
-#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_16_XI		 (3L<<20)
-#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_32_XI		 (4L<<20)
-#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_64_XI		 (5L<<20)
-#define BNX2_TDMA_CONFIG_FIFO_CMP_EN_XI			 (1L<<23)
-#define BNX2_TDMA_CONFIG_BYTES_OST_XI			 (0x7L<<24)
-#define BNX2_TDMA_CONFIG_BYTES_OST_512_XI		 (0L<<24)
-#define BNX2_TDMA_CONFIG_BYTES_OST_1024_XI		 (1L<<24)
-#define BNX2_TDMA_CONFIG_BYTES_OST_2048_XI		 (2L<<24)
-#define BNX2_TDMA_CONFIG_BYTES_OST_4096_XI		 (3L<<24)
-#define BNX2_TDMA_CONFIG_BYTES_OST_8192_XI		 (4L<<24)
-#define BNX2_TDMA_CONFIG_BYTES_OST_16384_XI		 (5L<<24)
-#define BNX2_TDMA_CONFIG_HC_BYPASS_XI			 (1L<<27)
-#define BNX2_TDMA_CONFIG_LCL_MRRS_XI			 (0x7L<<28)
-#define BNX2_TDMA_CONFIG_LCL_MRRS_128_XI		 (0L<<28)
-#define BNX2_TDMA_CONFIG_LCL_MRRS_256_XI		 (1L<<28)
-#define BNX2_TDMA_CONFIG_LCL_MRRS_512_XI		 (2L<<28)
-#define BNX2_TDMA_CONFIG_LCL_MRRS_1024_XI		 (3L<<28)
-#define BNX2_TDMA_CONFIG_LCL_MRRS_2048_XI		 (4L<<28)
-#define BNX2_TDMA_CONFIG_LCL_MRRS_4096_XI		 (5L<<28)
-#define BNX2_TDMA_CONFIG_LCL_MRRS_EN_XI			 (1L<<31)
-
-#define BNX2_TDMA_PAYLOAD_PROD				0x00005c0c
-#define BNX2_TDMA_PAYLOAD_PROD_VALUE			 (0x1fffL<<3)
-
-#define BNX2_TDMA_DBG_WATCHDOG				0x00005c10
-#define BNX2_TDMA_DBG_TRIGGER				0x00005c14
-#define BNX2_TDMA_DMAD_FSM				0x00005c80
-#define BNX2_TDMA_DMAD_FSM_BD_INVLD			 (1L<<0)
-#define BNX2_TDMA_DMAD_FSM_PUSH				 (0xfL<<4)
-#define BNX2_TDMA_DMAD_FSM_ARB_TBDC			 (0x3L<<8)
-#define BNX2_TDMA_DMAD_FSM_ARB_CTX			 (1L<<12)
-#define BNX2_TDMA_DMAD_FSM_DR_INTF			 (1L<<16)
-#define BNX2_TDMA_DMAD_FSM_DMAD				 (0x7L<<20)
-#define BNX2_TDMA_DMAD_FSM_BD				 (0xfL<<24)
-
-#define BNX2_TDMA_DMAD_STATUS				0x00005c84
-#define BNX2_TDMA_DMAD_STATUS_RHOLD_PUSH_ENTRY		 (0x3L<<0)
-#define BNX2_TDMA_DMAD_STATUS_RHOLD_DMAD_ENTRY		 (0x3L<<4)
-#define BNX2_TDMA_DMAD_STATUS_RHOLD_BD_ENTRY		 (0x3L<<8)
-#define BNX2_TDMA_DMAD_STATUS_IFTQ_ENUM			 (0xfL<<12)
-
-#define BNX2_TDMA_DR_INTF_FSM				0x00005c88
-#define BNX2_TDMA_DR_INTF_FSM_L2_COMP			 (0x3L<<0)
-#define BNX2_TDMA_DR_INTF_FSM_TPATQ			 (0x7L<<4)
-#define BNX2_TDMA_DR_INTF_FSM_TPBUF			 (0x3L<<8)
-#define BNX2_TDMA_DR_INTF_FSM_DR_BUF			 (0x7L<<12)
-#define BNX2_TDMA_DR_INTF_FSM_DMAD			 (0x7L<<16)
-
-#define BNX2_TDMA_DR_INTF_STATUS			0x00005c8c
-#define BNX2_TDMA_DR_INTF_STATUS_HOLE_PHASE		 (0x7L<<0)
-#define BNX2_TDMA_DR_INTF_STATUS_DATA_AVAIL		 (0x3L<<4)
-#define BNX2_TDMA_DR_INTF_STATUS_SHIFT_ADDR		 (0x7L<<8)
-#define BNX2_TDMA_DR_INTF_STATUS_NXT_PNTR		 (0xfL<<12)
-#define BNX2_TDMA_DR_INTF_STATUS_BYTE_COUNT		 (0x7L<<16)
-
-#define BNX2_TDMA_PUSH_FSM				0x00005c90
-#define BNX2_TDMA_BD_IF_DEBUG				0x00005c94
-#define BNX2_TDMA_DMAD_IF_DEBUG				0x00005c98
-#define BNX2_TDMA_CTX_IF_DEBUG				0x00005c9c
-#define BNX2_TDMA_TPBUF_IF_DEBUG			0x00005ca0
-#define BNX2_TDMA_DR_IF_DEBUG				0x00005ca4
-#define BNX2_TDMA_TPATQ_IF_DEBUG			0x00005ca8
-#define BNX2_TDMA_TDMA_ILOCK_CKSUM			0x00005cac
-#define BNX2_TDMA_TDMA_ILOCK_CKSUM_CALCULATED		 (0xffffL<<0)
-#define BNX2_TDMA_TDMA_ILOCK_CKSUM_EXPECTED		 (0xffffL<<16)
-
-#define BNX2_TDMA_TDMA_PCIE_CKSUM			0x00005cb0
-#define BNX2_TDMA_TDMA_PCIE_CKSUM_CALCULATED		 (0xffffL<<0)
-#define BNX2_TDMA_TDMA_PCIE_CKSUM_EXPECTED		 (0xffffL<<16)
-
-#define BNX2_TDMA_TDMAQ					0x00005fc0
-#define BNX2_TDMA_FTQ_CMD				0x00005ff8
-#define BNX2_TDMA_FTQ_CMD_OFFSET			 (0x3ffL<<0)
-#define BNX2_TDMA_FTQ_CMD_WR_TOP			 (1L<<10)
-#define BNX2_TDMA_FTQ_CMD_WR_TOP_0			 (0L<<10)
-#define BNX2_TDMA_FTQ_CMD_WR_TOP_1			 (1L<<10)
-#define BNX2_TDMA_FTQ_CMD_SFT_RESET			 (1L<<25)
-#define BNX2_TDMA_FTQ_CMD_RD_DATA			 (1L<<26)
-#define BNX2_TDMA_FTQ_CMD_ADD_INTERVEN			 (1L<<27)
-#define BNX2_TDMA_FTQ_CMD_ADD_DATA			 (1L<<28)
-#define BNX2_TDMA_FTQ_CMD_INTERVENE_CLR			 (1L<<29)
-#define BNX2_TDMA_FTQ_CMD_POP				 (1L<<30)
-#define BNX2_TDMA_FTQ_CMD_BUSY				 (1L<<31)
-
-#define BNX2_TDMA_FTQ_CTL				0x00005ffc
-#define BNX2_TDMA_FTQ_CTL_INTERVENE			 (1L<<0)
-#define BNX2_TDMA_FTQ_CTL_OVERFLOW			 (1L<<1)
-#define BNX2_TDMA_FTQ_CTL_FORCE_INTERVENE		 (1L<<2)
-#define BNX2_TDMA_FTQ_CTL_MAX_DEPTH			 (0x3ffL<<12)
-#define BNX2_TDMA_FTQ_CTL_CUR_DEPTH			 (0x3ffL<<22)
-
-
-
-/*
- *  hc_reg definition
- *  offset: 0x6800
- */
-#define BNX2_HC_COMMAND					0x00006800
-#define BNX2_HC_COMMAND_ENABLE				 (1L<<0)
-#define BNX2_HC_COMMAND_SKIP_ABORT			 (1L<<4)
-#define BNX2_HC_COMMAND_COAL_NOW			 (1L<<16)
-#define BNX2_HC_COMMAND_COAL_NOW_WO_INT			 (1L<<17)
-#define BNX2_HC_COMMAND_STATS_NOW			 (1L<<18)
-#define BNX2_HC_COMMAND_FORCE_INT			 (0x3L<<19)
-#define BNX2_HC_COMMAND_FORCE_INT_NULL			 (0L<<19)
-#define BNX2_HC_COMMAND_FORCE_INT_HIGH			 (1L<<19)
-#define BNX2_HC_COMMAND_FORCE_INT_LOW			 (2L<<19)
-#define BNX2_HC_COMMAND_FORCE_INT_FREE			 (3L<<19)
-#define BNX2_HC_COMMAND_CLR_STAT_NOW			 (1L<<21)
-#define BNX2_HC_COMMAND_MAIN_PWR_INT			 (1L<<22)
-#define BNX2_HC_COMMAND_COAL_ON_NEXT_EVENT		 (1L<<27)
-
-#define BNX2_HC_STATUS					0x00006804
-#define BNX2_HC_STATUS_MASTER_ABORT			 (1L<<0)
-#define BNX2_HC_STATUS_PARITY_ERROR_STATE		 (1L<<1)
-#define BNX2_HC_STATUS_PCI_CLK_CNT_STAT			 (1L<<16)
-#define BNX2_HC_STATUS_CORE_CLK_CNT_STAT		 (1L<<17)
-#define BNX2_HC_STATUS_NUM_STATUS_BLOCKS_STAT		 (1L<<18)
-#define BNX2_HC_STATUS_NUM_INT_GEN_STAT			 (1L<<19)
-#define BNX2_HC_STATUS_NUM_INT_MBOX_WR_STAT		 (1L<<20)
-#define BNX2_HC_STATUS_CORE_CLKS_TO_HW_INTACK_STAT	 (1L<<23)
-#define BNX2_HC_STATUS_CORE_CLKS_TO_SW_INTACK_STAT	 (1L<<24)
-#define BNX2_HC_STATUS_CORE_CLKS_DURING_SW_INTACK_STAT	 (1L<<25)
-
-#define BNX2_HC_CONFIG					0x00006808
-#define BNX2_HC_CONFIG_COLLECT_STATS			 (1L<<0)
-#define BNX2_HC_CONFIG_RX_TMR_MODE			 (1L<<1)
-#define BNX2_HC_CONFIG_TX_TMR_MODE			 (1L<<2)
-#define BNX2_HC_CONFIG_COM_TMR_MODE			 (1L<<3)
-#define BNX2_HC_CONFIG_CMD_TMR_MODE			 (1L<<4)
-#define BNX2_HC_CONFIG_STATISTIC_PRIORITY		 (1L<<5)
-#define BNX2_HC_CONFIG_STATUS_PRIORITY			 (1L<<6)
-#define BNX2_HC_CONFIG_STAT_MEM_ADDR			 (0xffL<<8)
-#define BNX2_HC_CONFIG_PER_MODE				 (1L<<16)
-#define BNX2_HC_CONFIG_ONE_SHOT				 (1L<<17)
-#define BNX2_HC_CONFIG_USE_INT_PARAM			 (1L<<18)
-#define BNX2_HC_CONFIG_SET_MASK_AT_RD			 (1L<<19)
-#define BNX2_HC_CONFIG_PER_COLLECT_LIMIT		 (0xfL<<20)
-#define BNX2_HC_CONFIG_SB_ADDR_INC			 (0x7L<<24)
-#define BNX2_HC_CONFIG_SB_ADDR_INC_64B			 (0L<<24)
-#define BNX2_HC_CONFIG_SB_ADDR_INC_128B			 (1L<<24)
-#define BNX2_HC_CONFIG_SB_ADDR_INC_256B			 (2L<<24)
-#define BNX2_HC_CONFIG_SB_ADDR_INC_512B			 (3L<<24)
-#define BNX2_HC_CONFIG_SB_ADDR_INC_1024B		 (4L<<24)
-#define BNX2_HC_CONFIG_SB_ADDR_INC_2048B		 (5L<<24)
-#define BNX2_HC_CONFIG_SB_ADDR_INC_4096B		 (6L<<24)
-#define BNX2_HC_CONFIG_SB_ADDR_INC_8192B		 (7L<<24)
-#define BNX2_HC_CONFIG_GEN_STAT_AVG_INTR		 (1L<<29)
-#define BNX2_HC_CONFIG_UNMASK_ALL			 (1L<<30)
-#define BNX2_HC_CONFIG_TX_SEL				 (1L<<31)
-
-#define BNX2_HC_ATTN_BITS_ENABLE			0x0000680c
-#define BNX2_HC_STATUS_ADDR_L				0x00006810
-#define BNX2_HC_STATUS_ADDR_H				0x00006814
-#define BNX2_HC_STATISTICS_ADDR_L			0x00006818
-#define BNX2_HC_STATISTICS_ADDR_H			0x0000681c
-#define BNX2_HC_TX_QUICK_CONS_TRIP			0x00006820
-#define BNX2_HC_TX_QUICK_CONS_TRIP_VALUE		 (0xffL<<0)
-#define BNX2_HC_TX_QUICK_CONS_TRIP_INT			 (0xffL<<16)
-
-#define BNX2_HC_COMP_PROD_TRIP				0x00006824
-#define BNX2_HC_COMP_PROD_TRIP_VALUE			 (0xffL<<0)
-#define BNX2_HC_COMP_PROD_TRIP_INT			 (0xffL<<16)
-
-#define BNX2_HC_RX_QUICK_CONS_TRIP			0x00006828
-#define BNX2_HC_RX_QUICK_CONS_TRIP_VALUE		 (0xffL<<0)
-#define BNX2_HC_RX_QUICK_CONS_TRIP_INT			 (0xffL<<16)
-
-#define BNX2_HC_RX_TICKS				0x0000682c
-#define BNX2_HC_RX_TICKS_VALUE				 (0x3ffL<<0)
-#define BNX2_HC_RX_TICKS_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_TX_TICKS				0x00006830
-#define BNX2_HC_TX_TICKS_VALUE				 (0x3ffL<<0)
-#define BNX2_HC_TX_TICKS_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_COM_TICKS				0x00006834
-#define BNX2_HC_COM_TICKS_VALUE				 (0x3ffL<<0)
-#define BNX2_HC_COM_TICKS_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_CMD_TICKS				0x00006838
-#define BNX2_HC_CMD_TICKS_VALUE				 (0x3ffL<<0)
-#define BNX2_HC_CMD_TICKS_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_PERIODIC_TICKS				0x0000683c
-#define BNX2_HC_PERIODIC_TICKS_HC_PERIODIC_TICKS	 (0xffffL<<0)
-#define BNX2_HC_PERIODIC_TICKS_HC_INT_PERIODIC_TICKS	 (0xffffL<<16)
-
-#define BNX2_HC_STAT_COLLECT_TICKS			0x00006840
-#define BNX2_HC_STAT_COLLECT_TICKS_HC_STAT_COLL_TICKS	 (0xffL<<4)
-
-#define BNX2_HC_STATS_TICKS				0x00006844
-#define BNX2_HC_STATS_TICKS_HC_STAT_TICKS		 (0xffffL<<8)
-
-#define BNX2_HC_STATS_INTERRUPT_STATUS			0x00006848
-#define BNX2_HC_STATS_INTERRUPT_STATUS_SB_STATUS	 (0x1ffL<<0)
-#define BNX2_HC_STATS_INTERRUPT_STATUS_INT_STATUS	 (0x1ffL<<16)
-
-#define BNX2_HC_STAT_MEM_DATA				0x0000684c
-#define BNX2_HC_STAT_GEN_SEL_0				0x00006850
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0		 (0x7fL<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT0	 (0L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT1	 (1L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT2	 (2L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT3	 (3L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT4	 (4L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT5	 (5L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT6	 (6L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT7	 (7L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT8	 (8L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT9	 (9L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT10	 (10L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT11	 (11L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT0	 (12L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT1	 (13L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT2	 (14L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT3	 (15L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT4	 (16L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT5	 (17L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT6	 (18L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT7	 (19L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT0	 (20L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT1	 (21L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT2	 (22L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT3	 (23L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT4	 (24L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT5	 (25L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT6	 (26L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT7	 (27L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT8	 (28L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT9	 (29L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT10	 (30L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT11	 (31L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT0	 (32L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT1	 (33L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT2	 (34L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT3	 (35L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT0	 (36L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT1	 (37L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT2	 (38L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT3	 (39L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT4	 (40L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT5	 (41L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT6	 (42L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT7	 (43L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT0	 (44L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT1	 (45L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT2	 (46L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT3	 (47L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT4	 (48L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT5	 (49L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT6	 (50L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT7	 (51L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_PCI_CLK_CNT	 (52L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CORE_CLK_CNT	 (53L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS	 (54L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN	 (55L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR	 (56L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK	 (59L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK	 (60L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK	 (61L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCH_CMD_CNT	 (62L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCH_SLOT_CNT	 (63L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSCH_CMD_CNT	 (64L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSCH_SLOT_CNT	 (65L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RLUPQ_VALID_CNT	 (66L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPQ_VALID_CNT	 (67L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPCQ_VALID_CNT	 (68L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PPQ_VALID_CNT	 (69L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PMQ_VALID_CNT	 (70L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PTQ_VALID_CNT	 (71L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMAQ_VALID_CNT	 (72L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCHQ_VALID_CNT	 (73L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDRQ_VALID_CNT	 (74L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXPQ_VALID_CNT	 (75L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMAQ_VALID_CNT	 (76L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPATQ_VALID_CNT	 (77L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TASQ_VALID_CNT	 (78L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSQ_VALID_CNT	 (79L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CPQ_VALID_CNT	 (80L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMXQ_VALID_CNT	 (81L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMTQ_VALID_CNT	 (82L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMQ_VALID_CNT	 (83L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MGMQ_VALID_CNT	 (84L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_READ_TRANSFERS_CNT	 (85L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_READ_DELAY_PCI_CLKS_CNT	 (86L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_TRANSFERS_CNT	 (87L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_DELAY_PCI_CLKS_CNT	 (88L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_RETRY_AFTER_DATA_CNT	 (89L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_WRITE_TRANSFERS_CNT	 (90L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_WRITE_DELAY_PCI_CLKS_CNT	 (91L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_TRANSFERS_CNT	 (92L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_DELAY_PCI_CLKS_CNT	 (93L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_RETRY_AFTER_DATA_CNT	 (94L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_WR_CNT64	 (95L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_RD_CNT64	 (96L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_ACC_STALL_CLKS	 (97L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_LOCK_STALL_CLKS	 (98L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_CTX_ACCESS_STAT	 (99L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_CTX_ACCESS64_STAT	 (100L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_PCI_STALL_STAT	 (101L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDR_FTQ_ENTRY_CNT	 (102L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDR_BURST_CNT	 (103L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMA_FTQ_ENTRY_CNT	 (104L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMA_BURST_CNT	 (105L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMA_FTQ_ENTRY_CNT	 (106L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMA_BURST_CNT	 (107L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RLUP_MATCH_CNT	 (108L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_POLL_PASS_CNT	 (109L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR1_CNT	 (110L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR2_CNT	 (111L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR3_CNT	 (112L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR4_CNT	 (113L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR5_CNT	 (114L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT0	 (115L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT1	 (116L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT2	 (117L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT3	 (118L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT4	 (119L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT5	 (120L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_PROC1_MISS	 (121L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_PROC2_MISS	 (122L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_BURST_CNT	 (127L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_1		 (0x7fL<<8)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_2		 (0x7fL<<16)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_3		 (0x7fL<<24)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_XI		 (0xffL<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UMP_RX_FRAME_DROP_XI	 (52L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S0_XI	 (57L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S1_XI	 (58L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S2_XI	 (85L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S3_XI	 (86L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S4_XI	 (87L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S5_XI	 (88L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S6_XI	 (89L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S7_XI	 (90L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S8_XI	 (91L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S9_XI	 (92L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S10_XI	 (93L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MQ_IDB_OFLOW_XI	 (94L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_BLK_RD_CNT_XI	 (123L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_BLK_WR_CNT_XI	 (124L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_HITS_XI	 (125L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_MISSES_XI	 (126L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC1_XI	 (128L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC1_XI	 (129L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC1_XI	 (130L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC1_XI	 (131L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC1_XI	 (132L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC1_XI	 (133L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC2_XI	 (134L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC2_XI	 (135L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC2_XI	 (136L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC2_XI	 (137L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC2_XI	 (138L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC2_XI	 (139L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC3_XI	 (140L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC3_XI	 (141L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC3_XI	 (142L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC3_XI	 (143L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC3_XI	 (144L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC3_XI	 (145L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC4_XI	 (146L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC4_XI	 (147L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC4_XI	 (148L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC4_XI	 (149L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC4_XI	 (150L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC4_XI	 (151L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC5_XI	 (152L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC5_XI	 (153L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC5_XI	 (154L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC5_XI	 (155L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC5_XI	 (156L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC5_XI	 (157L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC6_XI	 (158L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC6_XI	 (159L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC6_XI	 (160L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC6_XI	 (161L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC6_XI	 (162L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC6_XI	 (163L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC7_XI	 (164L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC7_XI	 (165L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC7_XI	 (166L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC7_XI	 (167L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC7_XI	 (168L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC7_XI	 (169L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC8_XI	 (170L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC8_XI	 (171L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC8_XI	 (172L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC8_XI	 (173L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC8_XI	 (174L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC8_XI	 (175L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCS_CMD_CNT_XI	 (176L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCS_SLOT_CNT_XI	 (177L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCSQ_VALID_CNT_XI	 (178L<<0)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_1_XI		 (0xffL<<8)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_2_XI		 (0xffL<<16)
-#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_3_XI		 (0xffL<<24)
-
-#define BNX2_HC_STAT_GEN_SEL_1				0x00006854
-#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_4		 (0x7fL<<0)
-#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_5		 (0x7fL<<8)
-#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_6		 (0x7fL<<16)
-#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_7		 (0x7fL<<24)
-#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_4_XI		 (0xffL<<0)
-#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_5_XI		 (0xffL<<8)
-#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_6_XI		 (0xffL<<16)
-#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_7_XI		 (0xffL<<24)
-
-#define BNX2_HC_STAT_GEN_SEL_2				0x00006858
-#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_8		 (0x7fL<<0)
-#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_9		 (0x7fL<<8)
-#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_10		 (0x7fL<<16)
-#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_11		 (0x7fL<<24)
-#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_8_XI		 (0xffL<<0)
-#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_9_XI		 (0xffL<<8)
-#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_10_XI		 (0xffL<<16)
-#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_11_XI		 (0xffL<<24)
-
-#define BNX2_HC_STAT_GEN_SEL_3				0x0000685c
-#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_12		 (0x7fL<<0)
-#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_13		 (0x7fL<<8)
-#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_14		 (0x7fL<<16)
-#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_15		 (0x7fL<<24)
-#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_12_XI		 (0xffL<<0)
-#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_13_XI		 (0xffL<<8)
-#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_14_XI		 (0xffL<<16)
-#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_15_XI		 (0xffL<<24)
-
-#define BNX2_HC_STAT_GEN_STAT0				0x00006888
-#define BNX2_HC_STAT_GEN_STAT1				0x0000688c
-#define BNX2_HC_STAT_GEN_STAT2				0x00006890
-#define BNX2_HC_STAT_GEN_STAT3				0x00006894
-#define BNX2_HC_STAT_GEN_STAT4				0x00006898
-#define BNX2_HC_STAT_GEN_STAT5				0x0000689c
-#define BNX2_HC_STAT_GEN_STAT6				0x000068a0
-#define BNX2_HC_STAT_GEN_STAT7				0x000068a4
-#define BNX2_HC_STAT_GEN_STAT8				0x000068a8
-#define BNX2_HC_STAT_GEN_STAT9				0x000068ac
-#define BNX2_HC_STAT_GEN_STAT10				0x000068b0
-#define BNX2_HC_STAT_GEN_STAT11				0x000068b4
-#define BNX2_HC_STAT_GEN_STAT12				0x000068b8
-#define BNX2_HC_STAT_GEN_STAT13				0x000068bc
-#define BNX2_HC_STAT_GEN_STAT14				0x000068c0
-#define BNX2_HC_STAT_GEN_STAT15				0x000068c4
-#define BNX2_HC_STAT_GEN_STAT_AC0			0x000068c8
-#define BNX2_HC_STAT_GEN_STAT_AC1			0x000068cc
-#define BNX2_HC_STAT_GEN_STAT_AC2			0x000068d0
-#define BNX2_HC_STAT_GEN_STAT_AC3			0x000068d4
-#define BNX2_HC_STAT_GEN_STAT_AC4			0x000068d8
-#define BNX2_HC_STAT_GEN_STAT_AC5			0x000068dc
-#define BNX2_HC_STAT_GEN_STAT_AC6			0x000068e0
-#define BNX2_HC_STAT_GEN_STAT_AC7			0x000068e4
-#define BNX2_HC_STAT_GEN_STAT_AC8			0x000068e8
-#define BNX2_HC_STAT_GEN_STAT_AC9			0x000068ec
-#define BNX2_HC_STAT_GEN_STAT_AC10			0x000068f0
-#define BNX2_HC_STAT_GEN_STAT_AC11			0x000068f4
-#define BNX2_HC_STAT_GEN_STAT_AC12			0x000068f8
-#define BNX2_HC_STAT_GEN_STAT_AC13			0x000068fc
-#define BNX2_HC_STAT_GEN_STAT_AC14			0x00006900
-#define BNX2_HC_STAT_GEN_STAT_AC15			0x00006904
-#define BNX2_HC_STAT_GEN_STAT_AC			0x000068c8
-#define BNX2_HC_VIS					0x00006908
-#define BNX2_HC_VIS_STAT_BUILD_STATE			 (0xfL<<0)
-#define BNX2_HC_VIS_STAT_BUILD_STATE_IDLE		 (0L<<0)
-#define BNX2_HC_VIS_STAT_BUILD_STATE_START		 (1L<<0)
-#define BNX2_HC_VIS_STAT_BUILD_STATE_REQUEST		 (2L<<0)
-#define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE64		 (3L<<0)
-#define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE32		 (4L<<0)
-#define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE_DONE	 (5L<<0)
-#define BNX2_HC_VIS_STAT_BUILD_STATE_DMA		 (6L<<0)
-#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_CONTROL	 (7L<<0)
-#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_LOW		 (8L<<0)
-#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_HIGH		 (9L<<0)
-#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_DATA		 (10L<<0)
-#define BNX2_HC_VIS_DMA_STAT_STATE			 (0xfL<<8)
-#define BNX2_HC_VIS_DMA_STAT_STATE_IDLE			 (0L<<8)
-#define BNX2_HC_VIS_DMA_STAT_STATE_STATUS_PARAM		 (1L<<8)
-#define BNX2_HC_VIS_DMA_STAT_STATE_STATUS_DMA		 (2L<<8)
-#define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP		 (3L<<8)
-#define BNX2_HC_VIS_DMA_STAT_STATE_COMP			 (4L<<8)
-#define BNX2_HC_VIS_DMA_STAT_STATE_STATISTIC_PARAM	 (5L<<8)
-#define BNX2_HC_VIS_DMA_STAT_STATE_STATISTIC_DMA	 (6L<<8)
-#define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP_1		 (7L<<8)
-#define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP_2		 (8L<<8)
-#define BNX2_HC_VIS_DMA_STAT_STATE_WAIT			 (9L<<8)
-#define BNX2_HC_VIS_DMA_STAT_STATE_ABORT		 (15L<<8)
-#define BNX2_HC_VIS_DMA_MSI_STATE			 (0x7L<<12)
-#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE		 (0x3L<<15)
-#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_IDLE		 (0L<<15)
-#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_COUNT	 (1L<<15)
-#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_START	 (2L<<15)
-
-#define BNX2_HC_VIS_1					0x0000690c
-#define BNX2_HC_VIS_1_HW_INTACK_STATE			 (1L<<4)
-#define BNX2_HC_VIS_1_HW_INTACK_STATE_IDLE		 (0L<<4)
-#define BNX2_HC_VIS_1_HW_INTACK_STATE_COUNT		 (1L<<4)
-#define BNX2_HC_VIS_1_SW_INTACK_STATE			 (1L<<5)
-#define BNX2_HC_VIS_1_SW_INTACK_STATE_IDLE		 (0L<<5)
-#define BNX2_HC_VIS_1_SW_INTACK_STATE_COUNT		 (1L<<5)
-#define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE		 (1L<<6)
-#define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE_IDLE	 (0L<<6)
-#define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE_COUNT	 (1L<<6)
-#define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE		 (1L<<7)
-#define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE_IDLE		 (0L<<7)
-#define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE_COUNT		 (1L<<7)
-#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE			 (0xfL<<17)
-#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_IDLE		 (0L<<17)
-#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_DMA		 (1L<<17)
-#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_UPDATE		 (2L<<17)
-#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_ASSIGN		 (3L<<17)
-#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_WAIT		 (4L<<17)
-#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_UPDATE	 (5L<<17)
-#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_ASSIGN	 (6L<<17)
-#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_WAIT		 (7L<<17)
-#define BNX2_HC_VIS_1_RAM_WR_ARB_STATE			 (0x3L<<21)
-#define BNX2_HC_VIS_1_RAM_WR_ARB_STATE_NORMAL		 (0L<<21)
-#define BNX2_HC_VIS_1_RAM_WR_ARB_STATE_CLEAR		 (1L<<21)
-#define BNX2_HC_VIS_1_INT_GEN_STATE			 (1L<<23)
-#define BNX2_HC_VIS_1_INT_GEN_STATE_DLE			 (0L<<23)
-#define BNX2_HC_VIS_1_INT_GEN_STATE_NTERRUPT		 (1L<<23)
-#define BNX2_HC_VIS_1_STAT_CHAN_ID			 (0x7L<<24)
-#define BNX2_HC_VIS_1_INT_B				 (1L<<27)
-
-#define BNX2_HC_DEBUG_VECT_PEEK				0x00006910
-#define BNX2_HC_DEBUG_VECT_PEEK_1_VALUE			 (0x7ffL<<0)
-#define BNX2_HC_DEBUG_VECT_PEEK_1_PEEK_EN		 (1L<<11)
-#define BNX2_HC_DEBUG_VECT_PEEK_1_SEL			 (0xfL<<12)
-#define BNX2_HC_DEBUG_VECT_PEEK_2_VALUE			 (0x7ffL<<16)
-#define BNX2_HC_DEBUG_VECT_PEEK_2_PEEK_EN		 (1L<<27)
-#define BNX2_HC_DEBUG_VECT_PEEK_2_SEL			 (0xfL<<28)
-
-#define BNX2_HC_COALESCE_NOW				0x00006914
-#define BNX2_HC_COALESCE_NOW_COAL_NOW			 (0x1ffL<<1)
-#define BNX2_HC_COALESCE_NOW_COAL_NOW_WO_INT		 (0x1ffL<<11)
-#define BNX2_HC_COALESCE_NOW_COAL_ON_NXT_EVENT		 (0x1ffL<<21)
-
-#define BNX2_HC_MSIX_BIT_VECTOR				0x00006918
-#define BNX2_HC_MSIX_BIT_VECTOR_VAL			 (0x1ffL<<0)
-
-#define BNX2_HC_SB_CONFIG_1				0x00006a00
-#define BNX2_HC_SB_CONFIG_1_RX_TMR_MODE			 (1L<<1)
-#define BNX2_HC_SB_CONFIG_1_TX_TMR_MODE			 (1L<<2)
-#define BNX2_HC_SB_CONFIG_1_COM_TMR_MODE		 (1L<<3)
-#define BNX2_HC_SB_CONFIG_1_CMD_TMR_MODE		 (1L<<4)
-#define BNX2_HC_SB_CONFIG_1_PER_MODE			 (1L<<16)
-#define BNX2_HC_SB_CONFIG_1_ONE_SHOT			 (1L<<17)
-#define BNX2_HC_SB_CONFIG_1_USE_INT_PARAM		 (1L<<18)
-#define BNX2_HC_SB_CONFIG_1_PER_COLLECT_LIMIT		 (0xfL<<20)
-
-#define BNX2_HC_TX_QUICK_CONS_TRIP_1			0x00006a04
-#define BNX2_HC_TX_QUICK_CONS_TRIP_1_VALUE		 (0xffL<<0)
-#define BNX2_HC_TX_QUICK_CONS_TRIP_1_INT		 (0xffL<<16)
-
-#define BNX2_HC_COMP_PROD_TRIP_1			0x00006a08
-#define BNX2_HC_COMP_PROD_TRIP_1_VALUE			 (0xffL<<0)
-#define BNX2_HC_COMP_PROD_TRIP_1_INT			 (0xffL<<16)
-
-#define BNX2_HC_RX_QUICK_CONS_TRIP_1			0x00006a0c
-#define BNX2_HC_RX_QUICK_CONS_TRIP_1_VALUE		 (0xffL<<0)
-#define BNX2_HC_RX_QUICK_CONS_TRIP_1_INT		 (0xffL<<16)
-
-#define BNX2_HC_RX_TICKS_1				0x00006a10
-#define BNX2_HC_RX_TICKS_1_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_RX_TICKS_1_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_TX_TICKS_1				0x00006a14
-#define BNX2_HC_TX_TICKS_1_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_TX_TICKS_1_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_COM_TICKS_1				0x00006a18
-#define BNX2_HC_COM_TICKS_1_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_COM_TICKS_1_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_CMD_TICKS_1				0x00006a1c
-#define BNX2_HC_CMD_TICKS_1_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_CMD_TICKS_1_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_PERIODIC_TICKS_1			0x00006a20
-#define BNX2_HC_PERIODIC_TICKS_1_HC_PERIODIC_TICKS	 (0xffffL<<0)
-#define BNX2_HC_PERIODIC_TICKS_1_HC_INT_PERIODIC_TICKS	 (0xffffL<<16)
-
-#define BNX2_HC_SB_CONFIG_2				0x00006a24
-#define BNX2_HC_SB_CONFIG_2_RX_TMR_MODE			 (1L<<1)
-#define BNX2_HC_SB_CONFIG_2_TX_TMR_MODE			 (1L<<2)
-#define BNX2_HC_SB_CONFIG_2_COM_TMR_MODE		 (1L<<3)
-#define BNX2_HC_SB_CONFIG_2_CMD_TMR_MODE		 (1L<<4)
-#define BNX2_HC_SB_CONFIG_2_PER_MODE			 (1L<<16)
-#define BNX2_HC_SB_CONFIG_2_ONE_SHOT			 (1L<<17)
-#define BNX2_HC_SB_CONFIG_2_USE_INT_PARAM		 (1L<<18)
-#define BNX2_HC_SB_CONFIG_2_PER_COLLECT_LIMIT		 (0xfL<<20)
-
-#define BNX2_HC_TX_QUICK_CONS_TRIP_2			0x00006a28
-#define BNX2_HC_TX_QUICK_CONS_TRIP_2_VALUE		 (0xffL<<0)
-#define BNX2_HC_TX_QUICK_CONS_TRIP_2_INT		 (0xffL<<16)
-
-#define BNX2_HC_COMP_PROD_TRIP_2			0x00006a2c
-#define BNX2_HC_COMP_PROD_TRIP_2_VALUE			 (0xffL<<0)
-#define BNX2_HC_COMP_PROD_TRIP_2_INT			 (0xffL<<16)
-
-#define BNX2_HC_RX_QUICK_CONS_TRIP_2			0x00006a30
-#define BNX2_HC_RX_QUICK_CONS_TRIP_2_VALUE		 (0xffL<<0)
-#define BNX2_HC_RX_QUICK_CONS_TRIP_2_INT		 (0xffL<<16)
-
-#define BNX2_HC_RX_TICKS_2				0x00006a34
-#define BNX2_HC_RX_TICKS_2_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_RX_TICKS_2_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_TX_TICKS_2				0x00006a38
-#define BNX2_HC_TX_TICKS_2_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_TX_TICKS_2_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_COM_TICKS_2				0x00006a3c
-#define BNX2_HC_COM_TICKS_2_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_COM_TICKS_2_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_CMD_TICKS_2				0x00006a40
-#define BNX2_HC_CMD_TICKS_2_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_CMD_TICKS_2_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_PERIODIC_TICKS_2			0x00006a44
-#define BNX2_HC_PERIODIC_TICKS_2_HC_PERIODIC_TICKS	 (0xffffL<<0)
-#define BNX2_HC_PERIODIC_TICKS_2_HC_INT_PERIODIC_TICKS	 (0xffffL<<16)
-
-#define BNX2_HC_SB_CONFIG_3				0x00006a48
-#define BNX2_HC_SB_CONFIG_3_RX_TMR_MODE			 (1L<<1)
-#define BNX2_HC_SB_CONFIG_3_TX_TMR_MODE			 (1L<<2)
-#define BNX2_HC_SB_CONFIG_3_COM_TMR_MODE		 (1L<<3)
-#define BNX2_HC_SB_CONFIG_3_CMD_TMR_MODE		 (1L<<4)
-#define BNX2_HC_SB_CONFIG_3_PER_MODE			 (1L<<16)
-#define BNX2_HC_SB_CONFIG_3_ONE_SHOT			 (1L<<17)
-#define BNX2_HC_SB_CONFIG_3_USE_INT_PARAM		 (1L<<18)
-#define BNX2_HC_SB_CONFIG_3_PER_COLLECT_LIMIT		 (0xfL<<20)
-
-#define BNX2_HC_TX_QUICK_CONS_TRIP_3			0x00006a4c
-#define BNX2_HC_TX_QUICK_CONS_TRIP_3_VALUE		 (0xffL<<0)
-#define BNX2_HC_TX_QUICK_CONS_TRIP_3_INT		 (0xffL<<16)
-
-#define BNX2_HC_COMP_PROD_TRIP_3			0x00006a50
-#define BNX2_HC_COMP_PROD_TRIP_3_VALUE			 (0xffL<<0)
-#define BNX2_HC_COMP_PROD_TRIP_3_INT			 (0xffL<<16)
-
-#define BNX2_HC_RX_QUICK_CONS_TRIP_3			0x00006a54
-#define BNX2_HC_RX_QUICK_CONS_TRIP_3_VALUE		 (0xffL<<0)
-#define BNX2_HC_RX_QUICK_CONS_TRIP_3_INT		 (0xffL<<16)
-
-#define BNX2_HC_RX_TICKS_3				0x00006a58
-#define BNX2_HC_RX_TICKS_3_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_RX_TICKS_3_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_TX_TICKS_3				0x00006a5c
-#define BNX2_HC_TX_TICKS_3_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_TX_TICKS_3_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_COM_TICKS_3				0x00006a60
-#define BNX2_HC_COM_TICKS_3_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_COM_TICKS_3_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_CMD_TICKS_3				0x00006a64
-#define BNX2_HC_CMD_TICKS_3_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_CMD_TICKS_3_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_PERIODIC_TICKS_3			0x00006a68
-#define BNX2_HC_PERIODIC_TICKS_3_HC_PERIODIC_TICKS	 (0xffffL<<0)
-#define BNX2_HC_PERIODIC_TICKS_3_HC_INT_PERIODIC_TICKS	 (0xffffL<<16)
-
-#define BNX2_HC_SB_CONFIG_4				0x00006a6c
-#define BNX2_HC_SB_CONFIG_4_RX_TMR_MODE			 (1L<<1)
-#define BNX2_HC_SB_CONFIG_4_TX_TMR_MODE			 (1L<<2)
-#define BNX2_HC_SB_CONFIG_4_COM_TMR_MODE		 (1L<<3)
-#define BNX2_HC_SB_CONFIG_4_CMD_TMR_MODE		 (1L<<4)
-#define BNX2_HC_SB_CONFIG_4_PER_MODE			 (1L<<16)
-#define BNX2_HC_SB_CONFIG_4_ONE_SHOT			 (1L<<17)
-#define BNX2_HC_SB_CONFIG_4_USE_INT_PARAM		 (1L<<18)
-#define BNX2_HC_SB_CONFIG_4_PER_COLLECT_LIMIT		 (0xfL<<20)
-
-#define BNX2_HC_TX_QUICK_CONS_TRIP_4			0x00006a70
-#define BNX2_HC_TX_QUICK_CONS_TRIP_4_VALUE		 (0xffL<<0)
-#define BNX2_HC_TX_QUICK_CONS_TRIP_4_INT		 (0xffL<<16)
-
-#define BNX2_HC_COMP_PROD_TRIP_4			0x00006a74
-#define BNX2_HC_COMP_PROD_TRIP_4_VALUE			 (0xffL<<0)
-#define BNX2_HC_COMP_PROD_TRIP_4_INT			 (0xffL<<16)
-
-#define BNX2_HC_RX_QUICK_CONS_TRIP_4			0x00006a78
-#define BNX2_HC_RX_QUICK_CONS_TRIP_4_VALUE		 (0xffL<<0)
-#define BNX2_HC_RX_QUICK_CONS_TRIP_4_INT		 (0xffL<<16)
-
-#define BNX2_HC_RX_TICKS_4				0x00006a7c
-#define BNX2_HC_RX_TICKS_4_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_RX_TICKS_4_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_TX_TICKS_4				0x00006a80
-#define BNX2_HC_TX_TICKS_4_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_TX_TICKS_4_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_COM_TICKS_4				0x00006a84
-#define BNX2_HC_COM_TICKS_4_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_COM_TICKS_4_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_CMD_TICKS_4				0x00006a88
-#define BNX2_HC_CMD_TICKS_4_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_CMD_TICKS_4_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_PERIODIC_TICKS_4			0x00006a8c
-#define BNX2_HC_PERIODIC_TICKS_4_HC_PERIODIC_TICKS	 (0xffffL<<0)
-#define BNX2_HC_PERIODIC_TICKS_4_HC_INT_PERIODIC_TICKS	 (0xffffL<<16)
-
-#define BNX2_HC_SB_CONFIG_5				0x00006a90
-#define BNX2_HC_SB_CONFIG_5_RX_TMR_MODE			 (1L<<1)
-#define BNX2_HC_SB_CONFIG_5_TX_TMR_MODE			 (1L<<2)
-#define BNX2_HC_SB_CONFIG_5_COM_TMR_MODE		 (1L<<3)
-#define BNX2_HC_SB_CONFIG_5_CMD_TMR_MODE		 (1L<<4)
-#define BNX2_HC_SB_CONFIG_5_PER_MODE			 (1L<<16)
-#define BNX2_HC_SB_CONFIG_5_ONE_SHOT			 (1L<<17)
-#define BNX2_HC_SB_CONFIG_5_USE_INT_PARAM		 (1L<<18)
-#define BNX2_HC_SB_CONFIG_5_PER_COLLECT_LIMIT		 (0xfL<<20)
-
-#define BNX2_HC_TX_QUICK_CONS_TRIP_5			0x00006a94
-#define BNX2_HC_TX_QUICK_CONS_TRIP_5_VALUE		 (0xffL<<0)
-#define BNX2_HC_TX_QUICK_CONS_TRIP_5_INT		 (0xffL<<16)
-
-#define BNX2_HC_COMP_PROD_TRIP_5			0x00006a98
-#define BNX2_HC_COMP_PROD_TRIP_5_VALUE			 (0xffL<<0)
-#define BNX2_HC_COMP_PROD_TRIP_5_INT			 (0xffL<<16)
-
-#define BNX2_HC_RX_QUICK_CONS_TRIP_5			0x00006a9c
-#define BNX2_HC_RX_QUICK_CONS_TRIP_5_VALUE		 (0xffL<<0)
-#define BNX2_HC_RX_QUICK_CONS_TRIP_5_INT		 (0xffL<<16)
-
-#define BNX2_HC_RX_TICKS_5				0x00006aa0
-#define BNX2_HC_RX_TICKS_5_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_RX_TICKS_5_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_TX_TICKS_5				0x00006aa4
-#define BNX2_HC_TX_TICKS_5_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_TX_TICKS_5_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_COM_TICKS_5				0x00006aa8
-#define BNX2_HC_COM_TICKS_5_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_COM_TICKS_5_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_CMD_TICKS_5				0x00006aac
-#define BNX2_HC_CMD_TICKS_5_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_CMD_TICKS_5_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_PERIODIC_TICKS_5			0x00006ab0
-#define BNX2_HC_PERIODIC_TICKS_5_HC_PERIODIC_TICKS	 (0xffffL<<0)
-#define BNX2_HC_PERIODIC_TICKS_5_HC_INT_PERIODIC_TICKS	 (0xffffL<<16)
-
-#define BNX2_HC_SB_CONFIG_6				0x00006ab4
-#define BNX2_HC_SB_CONFIG_6_RX_TMR_MODE			 (1L<<1)
-#define BNX2_HC_SB_CONFIG_6_TX_TMR_MODE			 (1L<<2)
-#define BNX2_HC_SB_CONFIG_6_COM_TMR_MODE		 (1L<<3)
-#define BNX2_HC_SB_CONFIG_6_CMD_TMR_MODE		 (1L<<4)
-#define BNX2_HC_SB_CONFIG_6_PER_MODE			 (1L<<16)
-#define BNX2_HC_SB_CONFIG_6_ONE_SHOT			 (1L<<17)
-#define BNX2_HC_SB_CONFIG_6_USE_INT_PARAM		 (1L<<18)
-#define BNX2_HC_SB_CONFIG_6_PER_COLLECT_LIMIT		 (0xfL<<20)
-
-#define BNX2_HC_TX_QUICK_CONS_TRIP_6			0x00006ab8
-#define BNX2_HC_TX_QUICK_CONS_TRIP_6_VALUE		 (0xffL<<0)
-#define BNX2_HC_TX_QUICK_CONS_TRIP_6_INT		 (0xffL<<16)
-
-#define BNX2_HC_COMP_PROD_TRIP_6			0x00006abc
-#define BNX2_HC_COMP_PROD_TRIP_6_VALUE			 (0xffL<<0)
-#define BNX2_HC_COMP_PROD_TRIP_6_INT			 (0xffL<<16)
-
-#define BNX2_HC_RX_QUICK_CONS_TRIP_6			0x00006ac0
-#define BNX2_HC_RX_QUICK_CONS_TRIP_6_VALUE		 (0xffL<<0)
-#define BNX2_HC_RX_QUICK_CONS_TRIP_6_INT		 (0xffL<<16)
-
-#define BNX2_HC_RX_TICKS_6				0x00006ac4
-#define BNX2_HC_RX_TICKS_6_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_RX_TICKS_6_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_TX_TICKS_6				0x00006ac8
-#define BNX2_HC_TX_TICKS_6_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_TX_TICKS_6_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_COM_TICKS_6				0x00006acc
-#define BNX2_HC_COM_TICKS_6_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_COM_TICKS_6_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_CMD_TICKS_6				0x00006ad0
-#define BNX2_HC_CMD_TICKS_6_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_CMD_TICKS_6_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_PERIODIC_TICKS_6			0x00006ad4
-#define BNX2_HC_PERIODIC_TICKS_6_HC_PERIODIC_TICKS	 (0xffffL<<0)
-#define BNX2_HC_PERIODIC_TICKS_6_HC_INT_PERIODIC_TICKS	 (0xffffL<<16)
-
-#define BNX2_HC_SB_CONFIG_7				0x00006ad8
-#define BNX2_HC_SB_CONFIG_7_RX_TMR_MODE			 (1L<<1)
-#define BNX2_HC_SB_CONFIG_7_TX_TMR_MODE			 (1L<<2)
-#define BNX2_HC_SB_CONFIG_7_COM_TMR_MODE		 (1L<<3)
-#define BNX2_HC_SB_CONFIG_7_CMD_TMR_MODE		 (1L<<4)
-#define BNX2_HC_SB_CONFIG_7_PER_MODE			 (1L<<16)
-#define BNX2_HC_SB_CONFIG_7_ONE_SHOT			 (1L<<17)
-#define BNX2_HC_SB_CONFIG_7_USE_INT_PARAM		 (1L<<18)
-#define BNX2_HC_SB_CONFIG_7_PER_COLLECT_LIMIT		 (0xfL<<20)
-
-#define BNX2_HC_TX_QUICK_CONS_TRIP_7			0x00006adc
-#define BNX2_HC_TX_QUICK_CONS_TRIP_7_VALUE		 (0xffL<<0)
-#define BNX2_HC_TX_QUICK_CONS_TRIP_7_INT		 (0xffL<<16)
-
-#define BNX2_HC_COMP_PROD_TRIP_7			0x00006ae0
-#define BNX2_HC_COMP_PROD_TRIP_7_VALUE			 (0xffL<<0)
-#define BNX2_HC_COMP_PROD_TRIP_7_INT			 (0xffL<<16)
-
-#define BNX2_HC_RX_QUICK_CONS_TRIP_7			0x00006ae4
-#define BNX2_HC_RX_QUICK_CONS_TRIP_7_VALUE		 (0xffL<<0)
-#define BNX2_HC_RX_QUICK_CONS_TRIP_7_INT		 (0xffL<<16)
-
-#define BNX2_HC_RX_TICKS_7				0x00006ae8
-#define BNX2_HC_RX_TICKS_7_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_RX_TICKS_7_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_TX_TICKS_7				0x00006aec
-#define BNX2_HC_TX_TICKS_7_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_TX_TICKS_7_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_COM_TICKS_7				0x00006af0
-#define BNX2_HC_COM_TICKS_7_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_COM_TICKS_7_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_CMD_TICKS_7				0x00006af4
-#define BNX2_HC_CMD_TICKS_7_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_CMD_TICKS_7_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_PERIODIC_TICKS_7			0x00006af8
-#define BNX2_HC_PERIODIC_TICKS_7_HC_PERIODIC_TICKS	 (0xffffL<<0)
-#define BNX2_HC_PERIODIC_TICKS_7_HC_INT_PERIODIC_TICKS	 (0xffffL<<16)
-
-#define BNX2_HC_SB_CONFIG_8				0x00006afc
-#define BNX2_HC_SB_CONFIG_8_RX_TMR_MODE			 (1L<<1)
-#define BNX2_HC_SB_CONFIG_8_TX_TMR_MODE			 (1L<<2)
-#define BNX2_HC_SB_CONFIG_8_COM_TMR_MODE		 (1L<<3)
-#define BNX2_HC_SB_CONFIG_8_CMD_TMR_MODE		 (1L<<4)
-#define BNX2_HC_SB_CONFIG_8_PER_MODE			 (1L<<16)
-#define BNX2_HC_SB_CONFIG_8_ONE_SHOT			 (1L<<17)
-#define BNX2_HC_SB_CONFIG_8_USE_INT_PARAM		 (1L<<18)
-#define BNX2_HC_SB_CONFIG_8_PER_COLLECT_LIMIT		 (0xfL<<20)
-
-#define BNX2_HC_TX_QUICK_CONS_TRIP_8			0x00006b00
-#define BNX2_HC_TX_QUICK_CONS_TRIP_8_VALUE		 (0xffL<<0)
-#define BNX2_HC_TX_QUICK_CONS_TRIP_8_INT		 (0xffL<<16)
-
-#define BNX2_HC_COMP_PROD_TRIP_8			0x00006b04
-#define BNX2_HC_COMP_PROD_TRIP_8_VALUE			 (0xffL<<0)
-#define BNX2_HC_COMP_PROD_TRIP_8_INT			 (0xffL<<16)
-
-#define BNX2_HC_RX_QUICK_CONS_TRIP_8			0x00006b08
-#define BNX2_HC_RX_QUICK_CONS_TRIP_8_VALUE		 (0xffL<<0)
-#define BNX2_HC_RX_QUICK_CONS_TRIP_8_INT		 (0xffL<<16)
-
-#define BNX2_HC_RX_TICKS_8				0x00006b0c
-#define BNX2_HC_RX_TICKS_8_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_RX_TICKS_8_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_TX_TICKS_8				0x00006b10
-#define BNX2_HC_TX_TICKS_8_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_TX_TICKS_8_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_COM_TICKS_8				0x00006b14
-#define BNX2_HC_COM_TICKS_8_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_COM_TICKS_8_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_CMD_TICKS_8				0x00006b18
-#define BNX2_HC_CMD_TICKS_8_VALUE			 (0x3ffL<<0)
-#define BNX2_HC_CMD_TICKS_8_INT				 (0x3ffL<<16)
-
-#define BNX2_HC_PERIODIC_TICKS_8			0x00006b1c
-#define BNX2_HC_PERIODIC_TICKS_8_HC_PERIODIC_TICKS	 (0xffffL<<0)
-#define BNX2_HC_PERIODIC_TICKS_8_HC_INT_PERIODIC_TICKS	 (0xffffL<<16)
-
-#define BNX2_HC_SB_CONFIG_SIZE	(BNX2_HC_SB_CONFIG_2 - BNX2_HC_SB_CONFIG_1)
-#define BNX2_HC_COMP_PROD_TRIP_OFF	(BNX2_HC_COMP_PROD_TRIP_1 -	\
-					 BNX2_HC_SB_CONFIG_1)
-#define BNX2_HC_COM_TICKS_OFF	(BNX2_HC_COM_TICKS_1 - BNX2_HC_SB_CONFIG_1)
-#define BNX2_HC_CMD_TICKS_OFF	(BNX2_HC_CMD_TICKS_1 - BNX2_HC_SB_CONFIG_1)
-#define BNX2_HC_TX_QUICK_CONS_TRIP_OFF	(BNX2_HC_TX_QUICK_CONS_TRIP_1 -	\
-					 BNX2_HC_SB_CONFIG_1)
-#define BNX2_HC_TX_TICKS_OFF	(BNX2_HC_TX_TICKS_1 - BNX2_HC_SB_CONFIG_1)
-#define BNX2_HC_RX_QUICK_CONS_TRIP_OFF	(BNX2_HC_RX_QUICK_CONS_TRIP_1 - \
-					 BNX2_HC_SB_CONFIG_1)
-#define BNX2_HC_RX_TICKS_OFF	(BNX2_HC_RX_TICKS_1 - BNX2_HC_SB_CONFIG_1)
-
-
-/*
- *  txp_reg definition
- *  offset: 0x40000
- */
-#define BNX2_TXP_CPU_MODE				0x00045000
-#define BNX2_TXP_CPU_MODE_LOCAL_RST			 (1L<<0)
-#define BNX2_TXP_CPU_MODE_STEP_ENA			 (1L<<1)
-#define BNX2_TXP_CPU_MODE_PAGE_0_DATA_ENA		 (1L<<2)
-#define BNX2_TXP_CPU_MODE_PAGE_0_INST_ENA		 (1L<<3)
-#define BNX2_TXP_CPU_MODE_MSG_BIT1			 (1L<<6)
-#define BNX2_TXP_CPU_MODE_INTERRUPT_ENA			 (1L<<7)
-#define BNX2_TXP_CPU_MODE_SOFT_HALT			 (1L<<10)
-#define BNX2_TXP_CPU_MODE_BAD_DATA_HALT_ENA		 (1L<<11)
-#define BNX2_TXP_CPU_MODE_BAD_INST_HALT_ENA		 (1L<<12)
-#define BNX2_TXP_CPU_MODE_FIO_ABORT_HALT_ENA		 (1L<<13)
-#define BNX2_TXP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA	 (1L<<15)
-
-#define BNX2_TXP_CPU_STATE				0x00045004
-#define BNX2_TXP_CPU_STATE_BREAKPOINT			 (1L<<0)
-#define BNX2_TXP_CPU_STATE_BAD_INST_HALTED		 (1L<<2)
-#define BNX2_TXP_CPU_STATE_PAGE_0_DATA_HALTED		 (1L<<3)
-#define BNX2_TXP_CPU_STATE_PAGE_0_INST_HALTED		 (1L<<4)
-#define BNX2_TXP_CPU_STATE_BAD_DATA_ADDR_HALTED		 (1L<<5)
-#define BNX2_TXP_CPU_STATE_BAD_PC_HALTED		 (1L<<6)
-#define BNX2_TXP_CPU_STATE_ALIGN_HALTED			 (1L<<7)
-#define BNX2_TXP_CPU_STATE_FIO_ABORT_HALTED		 (1L<<8)
-#define BNX2_TXP_CPU_STATE_SOFT_HALTED			 (1L<<10)
-#define BNX2_TXP_CPU_STATE_SPAD_UNDERFLOW		 (1L<<11)
-#define BNX2_TXP_CPU_STATE_INTERRRUPT			 (1L<<12)
-#define BNX2_TXP_CPU_STATE_DATA_ACCESS_STALL		 (1L<<14)
-#define BNX2_TXP_CPU_STATE_INST_FETCH_STALL		 (1L<<15)
-#define BNX2_TXP_CPU_STATE_BLOCKED_READ			 (1L<<31)
-
-#define BNX2_TXP_CPU_EVENT_MASK				0x00045008
-#define BNX2_TXP_CPU_EVENT_MASK_BREAKPOINT_MASK		 (1L<<0)
-#define BNX2_TXP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK	 (1L<<2)
-#define BNX2_TXP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK	 (1L<<3)
-#define BNX2_TXP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK	 (1L<<4)
-#define BNX2_TXP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK	 (1L<<5)
-#define BNX2_TXP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK	 (1L<<6)
-#define BNX2_TXP_CPU_EVENT_MASK_ALIGN_HALTED_MASK	 (1L<<7)
-#define BNX2_TXP_CPU_EVENT_MASK_FIO_ABORT_MASK		 (1L<<8)
-#define BNX2_TXP_CPU_EVENT_MASK_SOFT_HALTED_MASK	 (1L<<10)
-#define BNX2_TXP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK	 (1L<<11)
-#define BNX2_TXP_CPU_EVENT_MASK_INTERRUPT_MASK		 (1L<<12)
-
-#define BNX2_TXP_CPU_PROGRAM_COUNTER			0x0004501c
-#define BNX2_TXP_CPU_INSTRUCTION			0x00045020
-#define BNX2_TXP_CPU_DATA_ACCESS			0x00045024
-#define BNX2_TXP_CPU_INTERRUPT_ENABLE			0x00045028
-#define BNX2_TXP_CPU_INTERRUPT_VECTOR			0x0004502c
-#define BNX2_TXP_CPU_INTERRUPT_SAVED_PC			0x00045030
-#define BNX2_TXP_CPU_HW_BREAKPOINT			0x00045034
-#define BNX2_TXP_CPU_HW_BREAKPOINT_DISABLE		 (1L<<0)
-#define BNX2_TXP_CPU_HW_BREAKPOINT_ADDRESS		 (0x3fffffffL<<2)
-
-#define BNX2_TXP_CPU_DEBUG_VECT_PEEK			0x00045038
-#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_VALUE		 (0x7ffL<<0)
-#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN		 (1L<<11)
-#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_SEL		 (0xfL<<12)
-#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_VALUE		 (0x7ffL<<16)
-#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN		 (1L<<27)
-#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_SEL		 (0xfL<<28)
-
-#define BNX2_TXP_CPU_LAST_BRANCH_ADDR			0x00045048
-#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE		 (1L<<1)
-#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP		 (0L<<1)
-#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH	 (1L<<1)
-#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_LBA		 (0x3fffffffL<<2)
-
-#define BNX2_TXP_CPU_REG_FILE				0x00045200
-#define BNX2_TXP_TXPQ					0x000453c0
-#define BNX2_TXP_FTQ_CMD				0x000453f8
-#define BNX2_TXP_FTQ_CMD_OFFSET				 (0x3ffL<<0)
-#define BNX2_TXP_FTQ_CMD_WR_TOP				 (1L<<10)
-#define BNX2_TXP_FTQ_CMD_WR_TOP_0			 (0L<<10)
-#define BNX2_TXP_FTQ_CMD_WR_TOP_1			 (1L<<10)
-#define BNX2_TXP_FTQ_CMD_SFT_RESET			 (1L<<25)
-#define BNX2_TXP_FTQ_CMD_RD_DATA			 (1L<<26)
-#define BNX2_TXP_FTQ_CMD_ADD_INTERVEN			 (1L<<27)
-#define BNX2_TXP_FTQ_CMD_ADD_DATA			 (1L<<28)
-#define BNX2_TXP_FTQ_CMD_INTERVENE_CLR			 (1L<<29)
-#define BNX2_TXP_FTQ_CMD_POP				 (1L<<30)
-#define BNX2_TXP_FTQ_CMD_BUSY				 (1L<<31)
-
-#define BNX2_TXP_FTQ_CTL				0x000453fc
-#define BNX2_TXP_FTQ_CTL_INTERVENE			 (1L<<0)
-#define BNX2_TXP_FTQ_CTL_OVERFLOW			 (1L<<1)
-#define BNX2_TXP_FTQ_CTL_FORCE_INTERVENE		 (1L<<2)
-#define BNX2_TXP_FTQ_CTL_MAX_DEPTH			 (0x3ffL<<12)
-#define BNX2_TXP_FTQ_CTL_CUR_DEPTH			 (0x3ffL<<22)
-
-#define BNX2_TXP_SCRATCH				0x00060000
-
-
-/*
- *  tpat_reg definition
- *  offset: 0x80000
- */
-#define BNX2_TPAT_CPU_MODE				0x00085000
-#define BNX2_TPAT_CPU_MODE_LOCAL_RST			 (1L<<0)
-#define BNX2_TPAT_CPU_MODE_STEP_ENA			 (1L<<1)
-#define BNX2_TPAT_CPU_MODE_PAGE_0_DATA_ENA		 (1L<<2)
-#define BNX2_TPAT_CPU_MODE_PAGE_0_INST_ENA		 (1L<<3)
-#define BNX2_TPAT_CPU_MODE_MSG_BIT1			 (1L<<6)
-#define BNX2_TPAT_CPU_MODE_INTERRUPT_ENA		 (1L<<7)
-#define BNX2_TPAT_CPU_MODE_SOFT_HALT			 (1L<<10)
-#define BNX2_TPAT_CPU_MODE_BAD_DATA_HALT_ENA		 (1L<<11)
-#define BNX2_TPAT_CPU_MODE_BAD_INST_HALT_ENA		 (1L<<12)
-#define BNX2_TPAT_CPU_MODE_FIO_ABORT_HALT_ENA		 (1L<<13)
-#define BNX2_TPAT_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA	 (1L<<15)
-
-#define BNX2_TPAT_CPU_STATE				0x00085004
-#define BNX2_TPAT_CPU_STATE_BREAKPOINT			 (1L<<0)
-#define BNX2_TPAT_CPU_STATE_BAD_INST_HALTED		 (1L<<2)
-#define BNX2_TPAT_CPU_STATE_PAGE_0_DATA_HALTED		 (1L<<3)
-#define BNX2_TPAT_CPU_STATE_PAGE_0_INST_HALTED		 (1L<<4)
-#define BNX2_TPAT_CPU_STATE_BAD_DATA_ADDR_HALTED	 (1L<<5)
-#define BNX2_TPAT_CPU_STATE_BAD_PC_HALTED		 (1L<<6)
-#define BNX2_TPAT_CPU_STATE_ALIGN_HALTED		 (1L<<7)
-#define BNX2_TPAT_CPU_STATE_FIO_ABORT_HALTED		 (1L<<8)
-#define BNX2_TPAT_CPU_STATE_SOFT_HALTED			 (1L<<10)
-#define BNX2_TPAT_CPU_STATE_SPAD_UNDERFLOW		 (1L<<11)
-#define BNX2_TPAT_CPU_STATE_INTERRRUPT			 (1L<<12)
-#define BNX2_TPAT_CPU_STATE_DATA_ACCESS_STALL		 (1L<<14)
-#define BNX2_TPAT_CPU_STATE_INST_FETCH_STALL		 (1L<<15)
-#define BNX2_TPAT_CPU_STATE_BLOCKED_READ		 (1L<<31)
-
-#define BNX2_TPAT_CPU_EVENT_MASK			0x00085008
-#define BNX2_TPAT_CPU_EVENT_MASK_BREAKPOINT_MASK	 (1L<<0)
-#define BNX2_TPAT_CPU_EVENT_MASK_BAD_INST_HALTED_MASK	 (1L<<2)
-#define BNX2_TPAT_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK	 (1L<<3)
-#define BNX2_TPAT_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK	 (1L<<4)
-#define BNX2_TPAT_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK	 (1L<<5)
-#define BNX2_TPAT_CPU_EVENT_MASK_BAD_PC_HALTED_MASK	 (1L<<6)
-#define BNX2_TPAT_CPU_EVENT_MASK_ALIGN_HALTED_MASK	 (1L<<7)
-#define BNX2_TPAT_CPU_EVENT_MASK_FIO_ABORT_MASK		 (1L<<8)
-#define BNX2_TPAT_CPU_EVENT_MASK_SOFT_HALTED_MASK	 (1L<<10)
-#define BNX2_TPAT_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK	 (1L<<11)
-#define BNX2_TPAT_CPU_EVENT_MASK_INTERRUPT_MASK		 (1L<<12)
-
-#define BNX2_TPAT_CPU_PROGRAM_COUNTER			0x0008501c
-#define BNX2_TPAT_CPU_INSTRUCTION			0x00085020
-#define BNX2_TPAT_CPU_DATA_ACCESS			0x00085024
-#define BNX2_TPAT_CPU_INTERRUPT_ENABLE			0x00085028
-#define BNX2_TPAT_CPU_INTERRUPT_VECTOR			0x0008502c
-#define BNX2_TPAT_CPU_INTERRUPT_SAVED_PC		0x00085030
-#define BNX2_TPAT_CPU_HW_BREAKPOINT			0x00085034
-#define BNX2_TPAT_CPU_HW_BREAKPOINT_DISABLE		 (1L<<0)
-#define BNX2_TPAT_CPU_HW_BREAKPOINT_ADDRESS		 (0x3fffffffL<<2)
-
-#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK			0x00085038
-#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_VALUE		 (0x7ffL<<0)
-#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_PEEK_EN		 (1L<<11)
-#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_SEL		 (0xfL<<12)
-#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_VALUE		 (0x7ffL<<16)
-#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_PEEK_EN		 (1L<<27)
-#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_SEL		 (0xfL<<28)
-
-#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR			0x00085048
-#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE		 (1L<<1)
-#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE_JUMP	 (0L<<1)
-#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH	 (1L<<1)
-#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_LBA		 (0x3fffffffL<<2)
-
-#define BNX2_TPAT_CPU_REG_FILE				0x00085200
-#define BNX2_TPAT_TPATQ					0x000853c0
-#define BNX2_TPAT_FTQ_CMD				0x000853f8
-#define BNX2_TPAT_FTQ_CMD_OFFSET			 (0x3ffL<<0)
-#define BNX2_TPAT_FTQ_CMD_WR_TOP			 (1L<<10)
-#define BNX2_TPAT_FTQ_CMD_WR_TOP_0			 (0L<<10)
-#define BNX2_TPAT_FTQ_CMD_WR_TOP_1			 (1L<<10)
-#define BNX2_TPAT_FTQ_CMD_SFT_RESET			 (1L<<25)
-#define BNX2_TPAT_FTQ_CMD_RD_DATA			 (1L<<26)
-#define BNX2_TPAT_FTQ_CMD_ADD_INTERVEN			 (1L<<27)
-#define BNX2_TPAT_FTQ_CMD_ADD_DATA			 (1L<<28)
-#define BNX2_TPAT_FTQ_CMD_INTERVENE_CLR			 (1L<<29)
-#define BNX2_TPAT_FTQ_CMD_POP				 (1L<<30)
-#define BNX2_TPAT_FTQ_CMD_BUSY				 (1L<<31)
-
-#define BNX2_TPAT_FTQ_CTL				0x000853fc
-#define BNX2_TPAT_FTQ_CTL_INTERVENE			 (1L<<0)
-#define BNX2_TPAT_FTQ_CTL_OVERFLOW			 (1L<<1)
-#define BNX2_TPAT_FTQ_CTL_FORCE_INTERVENE		 (1L<<2)
-#define BNX2_TPAT_FTQ_CTL_MAX_DEPTH			 (0x3ffL<<12)
-#define BNX2_TPAT_FTQ_CTL_CUR_DEPTH			 (0x3ffL<<22)
-
-#define BNX2_TPAT_SCRATCH				0x000a0000
-
-
-/*
- *  rxp_reg definition
- *  offset: 0xc0000
- */
-#define BNX2_RXP_CPU_MODE				0x000c5000
-#define BNX2_RXP_CPU_MODE_LOCAL_RST			 (1L<<0)
-#define BNX2_RXP_CPU_MODE_STEP_ENA			 (1L<<1)
-#define BNX2_RXP_CPU_MODE_PAGE_0_DATA_ENA		 (1L<<2)
-#define BNX2_RXP_CPU_MODE_PAGE_0_INST_ENA		 (1L<<3)
-#define BNX2_RXP_CPU_MODE_MSG_BIT1			 (1L<<6)
-#define BNX2_RXP_CPU_MODE_INTERRUPT_ENA			 (1L<<7)
-#define BNX2_RXP_CPU_MODE_SOFT_HALT			 (1L<<10)
-#define BNX2_RXP_CPU_MODE_BAD_DATA_HALT_ENA		 (1L<<11)
-#define BNX2_RXP_CPU_MODE_BAD_INST_HALT_ENA		 (1L<<12)
-#define BNX2_RXP_CPU_MODE_FIO_ABORT_HALT_ENA		 (1L<<13)
-#define BNX2_RXP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA	 (1L<<15)
-
-#define BNX2_RXP_CPU_STATE				0x000c5004
-#define BNX2_RXP_CPU_STATE_BREAKPOINT			 (1L<<0)
-#define BNX2_RXP_CPU_STATE_BAD_INST_HALTED		 (1L<<2)
-#define BNX2_RXP_CPU_STATE_PAGE_0_DATA_HALTED		 (1L<<3)
-#define BNX2_RXP_CPU_STATE_PAGE_0_INST_HALTED		 (1L<<4)
-#define BNX2_RXP_CPU_STATE_BAD_DATA_ADDR_HALTED		 (1L<<5)
-#define BNX2_RXP_CPU_STATE_BAD_PC_HALTED		 (1L<<6)
-#define BNX2_RXP_CPU_STATE_ALIGN_HALTED			 (1L<<7)
-#define BNX2_RXP_CPU_STATE_FIO_ABORT_HALTED		 (1L<<8)
-#define BNX2_RXP_CPU_STATE_SOFT_HALTED			 (1L<<10)
-#define BNX2_RXP_CPU_STATE_SPAD_UNDERFLOW		 (1L<<11)
-#define BNX2_RXP_CPU_STATE_INTERRRUPT			 (1L<<12)
-#define BNX2_RXP_CPU_STATE_DATA_ACCESS_STALL		 (1L<<14)
-#define BNX2_RXP_CPU_STATE_INST_FETCH_STALL		 (1L<<15)
-#define BNX2_RXP_CPU_STATE_BLOCKED_READ			 (1L<<31)
-
-#define BNX2_RXP_CPU_EVENT_MASK				0x000c5008
-#define BNX2_RXP_CPU_EVENT_MASK_BREAKPOINT_MASK		 (1L<<0)
-#define BNX2_RXP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK	 (1L<<2)
-#define BNX2_RXP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK	 (1L<<3)
-#define BNX2_RXP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK	 (1L<<4)
-#define BNX2_RXP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK	 (1L<<5)
-#define BNX2_RXP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK	 (1L<<6)
-#define BNX2_RXP_CPU_EVENT_MASK_ALIGN_HALTED_MASK	 (1L<<7)
-#define BNX2_RXP_CPU_EVENT_MASK_FIO_ABORT_MASK		 (1L<<8)
-#define BNX2_RXP_CPU_EVENT_MASK_SOFT_HALTED_MASK	 (1L<<10)
-#define BNX2_RXP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK	 (1L<<11)
-#define BNX2_RXP_CPU_EVENT_MASK_INTERRUPT_MASK		 (1L<<12)
-
-#define BNX2_RXP_CPU_PROGRAM_COUNTER			0x000c501c
-#define BNX2_RXP_CPU_INSTRUCTION			0x000c5020
-#define BNX2_RXP_CPU_DATA_ACCESS			0x000c5024
-#define BNX2_RXP_CPU_INTERRUPT_ENABLE			0x000c5028
-#define BNX2_RXP_CPU_INTERRUPT_VECTOR			0x000c502c
-#define BNX2_RXP_CPU_INTERRUPT_SAVED_PC			0x000c5030
-#define BNX2_RXP_CPU_HW_BREAKPOINT			0x000c5034
-#define BNX2_RXP_CPU_HW_BREAKPOINT_DISABLE		 (1L<<0)
-#define BNX2_RXP_CPU_HW_BREAKPOINT_ADDRESS		 (0x3fffffffL<<2)
-
-#define BNX2_RXP_CPU_DEBUG_VECT_PEEK			0x000c5038
-#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_VALUE		 (0x7ffL<<0)
-#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN		 (1L<<11)
-#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_SEL		 (0xfL<<12)
-#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_VALUE		 (0x7ffL<<16)
-#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN		 (1L<<27)
-#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_SEL		 (0xfL<<28)
-
-#define BNX2_RXP_CPU_LAST_BRANCH_ADDR			0x000c5048
-#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE		 (1L<<1)
-#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP		 (0L<<1)
-#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH	 (1L<<1)
-#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_LBA		 (0x3fffffffL<<2)
-
-#define BNX2_RXP_CPU_REG_FILE				0x000c5200
-#define BNX2_RXP_PFE_PFE_CTL				0x000c537c
-#define BNX2_RXP_PFE_PFE_CTL_INC_USAGE_CNT		 (1L<<0)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE			 (0xfL<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_0			 (0L<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_1			 (1L<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_2			 (2L<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_3			 (3L<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_4			 (4L<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_5			 (5L<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_6			 (6L<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_7			 (7L<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_8			 (8L<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_9			 (9L<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_10		 (10L<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_11		 (11L<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_12		 (12L<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_13		 (13L<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_14		 (14L<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_15		 (15L<<4)
-#define BNX2_RXP_PFE_PFE_CTL_PFE_COUNT			 (0xfL<<12)
-#define BNX2_RXP_PFE_PFE_CTL_OFFSET			 (0x1ffL<<16)
-
-#define BNX2_RXP_RXPCQ					0x000c5380
-#define BNX2_RXP_CFTQ_CMD				0x000c53b8
-#define BNX2_RXP_CFTQ_CMD_OFFSET			 (0x3ffL<<0)
-#define BNX2_RXP_CFTQ_CMD_WR_TOP			 (1L<<10)
-#define BNX2_RXP_CFTQ_CMD_WR_TOP_0			 (0L<<10)
-#define BNX2_RXP_CFTQ_CMD_WR_TOP_1			 (1L<<10)
-#define BNX2_RXP_CFTQ_CMD_SFT_RESET			 (1L<<25)
-#define BNX2_RXP_CFTQ_CMD_RD_DATA			 (1L<<26)
-#define BNX2_RXP_CFTQ_CMD_ADD_INTERVEN			 (1L<<27)
-#define BNX2_RXP_CFTQ_CMD_ADD_DATA			 (1L<<28)
-#define BNX2_RXP_CFTQ_CMD_INTERVENE_CLR			 (1L<<29)
-#define BNX2_RXP_CFTQ_CMD_POP				 (1L<<30)
-#define BNX2_RXP_CFTQ_CMD_BUSY				 (1L<<31)
-
-#define BNX2_RXP_CFTQ_CTL				0x000c53bc
-#define BNX2_RXP_CFTQ_CTL_INTERVENE			 (1L<<0)
-#define BNX2_RXP_CFTQ_CTL_OVERFLOW			 (1L<<1)
-#define BNX2_RXP_CFTQ_CTL_FORCE_INTERVENE		 (1L<<2)
-#define BNX2_RXP_CFTQ_CTL_MAX_DEPTH			 (0x3ffL<<12)
-#define BNX2_RXP_CFTQ_CTL_CUR_DEPTH			 (0x3ffL<<22)
-
-#define BNX2_RXP_RXPQ					0x000c53c0
-#define BNX2_RXP_FTQ_CMD				0x000c53f8
-#define BNX2_RXP_FTQ_CMD_OFFSET				 (0x3ffL<<0)
-#define BNX2_RXP_FTQ_CMD_WR_TOP				 (1L<<10)
-#define BNX2_RXP_FTQ_CMD_WR_TOP_0			 (0L<<10)
-#define BNX2_RXP_FTQ_CMD_WR_TOP_1			 (1L<<10)
-#define BNX2_RXP_FTQ_CMD_SFT_RESET			 (1L<<25)
-#define BNX2_RXP_FTQ_CMD_RD_DATA			 (1L<<26)
-#define BNX2_RXP_FTQ_CMD_ADD_INTERVEN			 (1L<<27)
-#define BNX2_RXP_FTQ_CMD_ADD_DATA			 (1L<<28)
-#define BNX2_RXP_FTQ_CMD_INTERVENE_CLR			 (1L<<29)
-#define BNX2_RXP_FTQ_CMD_POP				 (1L<<30)
-#define BNX2_RXP_FTQ_CMD_BUSY				 (1L<<31)
-
-#define BNX2_RXP_FTQ_CTL				0x000c53fc
-#define BNX2_RXP_FTQ_CTL_INTERVENE			 (1L<<0)
-#define BNX2_RXP_FTQ_CTL_OVERFLOW			 (1L<<1)
-#define BNX2_RXP_FTQ_CTL_FORCE_INTERVENE		 (1L<<2)
-#define BNX2_RXP_FTQ_CTL_MAX_DEPTH			 (0x3ffL<<12)
-#define BNX2_RXP_FTQ_CTL_CUR_DEPTH			 (0x3ffL<<22)
-
-#define BNX2_RXP_SCRATCH				0x000e0000
-#define BNX2_RXP_SCRATCH_RXP_FLOOD			 0x000e0024
-#define BNX2_RXP_SCRATCH_RSS_TBL_SZ			 0x000e0038
-#define BNX2_RXP_SCRATCH_RSS_TBL			 0x000e003c
-#define BNX2_RXP_SCRATCH_RSS_TBL_MAX_ENTRIES		 128
-
-
-/*
- *  com_reg definition
- *  offset: 0x100000
- */
-#define BNX2_COM_CKSUM_ERROR_STATUS			0x00100000
-#define BNX2_COM_CKSUM_ERROR_STATUS_CALCULATED		 (0xffffL<<0)
-#define BNX2_COM_CKSUM_ERROR_STATUS_EXPECTED		 (0xffffL<<16)
-
-#define BNX2_COM_CPU_MODE				0x00105000
-#define BNX2_COM_CPU_MODE_LOCAL_RST			 (1L<<0)
-#define BNX2_COM_CPU_MODE_STEP_ENA			 (1L<<1)
-#define BNX2_COM_CPU_MODE_PAGE_0_DATA_ENA		 (1L<<2)
-#define BNX2_COM_CPU_MODE_PAGE_0_INST_ENA		 (1L<<3)
-#define BNX2_COM_CPU_MODE_MSG_BIT1			 (1L<<6)
-#define BNX2_COM_CPU_MODE_INTERRUPT_ENA			 (1L<<7)
-#define BNX2_COM_CPU_MODE_SOFT_HALT			 (1L<<10)
-#define BNX2_COM_CPU_MODE_BAD_DATA_HALT_ENA		 (1L<<11)
-#define BNX2_COM_CPU_MODE_BAD_INST_HALT_ENA		 (1L<<12)
-#define BNX2_COM_CPU_MODE_FIO_ABORT_HALT_ENA		 (1L<<13)
-#define BNX2_COM_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA	 (1L<<15)
-
-#define BNX2_COM_CPU_STATE				0x00105004
-#define BNX2_COM_CPU_STATE_BREAKPOINT			 (1L<<0)
-#define BNX2_COM_CPU_STATE_BAD_INST_HALTED		 (1L<<2)
-#define BNX2_COM_CPU_STATE_PAGE_0_DATA_HALTED		 (1L<<3)
-#define BNX2_COM_CPU_STATE_PAGE_0_INST_HALTED		 (1L<<4)
-#define BNX2_COM_CPU_STATE_BAD_DATA_ADDR_HALTED		 (1L<<5)
-#define BNX2_COM_CPU_STATE_BAD_PC_HALTED		 (1L<<6)
-#define BNX2_COM_CPU_STATE_ALIGN_HALTED			 (1L<<7)
-#define BNX2_COM_CPU_STATE_FIO_ABORT_HALTED		 (1L<<8)
-#define BNX2_COM_CPU_STATE_SOFT_HALTED			 (1L<<10)
-#define BNX2_COM_CPU_STATE_SPAD_UNDERFLOW		 (1L<<11)
-#define BNX2_COM_CPU_STATE_INTERRRUPT			 (1L<<12)
-#define BNX2_COM_CPU_STATE_DATA_ACCESS_STALL		 (1L<<14)
-#define BNX2_COM_CPU_STATE_INST_FETCH_STALL		 (1L<<15)
-#define BNX2_COM_CPU_STATE_BLOCKED_READ			 (1L<<31)
-
-#define BNX2_COM_CPU_EVENT_MASK				0x00105008
-#define BNX2_COM_CPU_EVENT_MASK_BREAKPOINT_MASK		 (1L<<0)
-#define BNX2_COM_CPU_EVENT_MASK_BAD_INST_HALTED_MASK	 (1L<<2)
-#define BNX2_COM_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK	 (1L<<3)
-#define BNX2_COM_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK	 (1L<<4)
-#define BNX2_COM_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK	 (1L<<5)
-#define BNX2_COM_CPU_EVENT_MASK_BAD_PC_HALTED_MASK	 (1L<<6)
-#define BNX2_COM_CPU_EVENT_MASK_ALIGN_HALTED_MASK	 (1L<<7)
-#define BNX2_COM_CPU_EVENT_MASK_FIO_ABORT_MASK		 (1L<<8)
-#define BNX2_COM_CPU_EVENT_MASK_SOFT_HALTED_MASK	 (1L<<10)
-#define BNX2_COM_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK	 (1L<<11)
-#define BNX2_COM_CPU_EVENT_MASK_INTERRUPT_MASK		 (1L<<12)
-
-#define BNX2_COM_CPU_PROGRAM_COUNTER			0x0010501c
-#define BNX2_COM_CPU_INSTRUCTION			0x00105020
-#define BNX2_COM_CPU_DATA_ACCESS			0x00105024
-#define BNX2_COM_CPU_INTERRUPT_ENABLE			0x00105028
-#define BNX2_COM_CPU_INTERRUPT_VECTOR			0x0010502c
-#define BNX2_COM_CPU_INTERRUPT_SAVED_PC			0x00105030
-#define BNX2_COM_CPU_HW_BREAKPOINT			0x00105034
-#define BNX2_COM_CPU_HW_BREAKPOINT_DISABLE		 (1L<<0)
-#define BNX2_COM_CPU_HW_BREAKPOINT_ADDRESS		 (0x3fffffffL<<2)
-
-#define BNX2_COM_CPU_DEBUG_VECT_PEEK			0x00105038
-#define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_VALUE		 (0x7ffL<<0)
-#define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_PEEK_EN		 (1L<<11)
-#define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_SEL		 (0xfL<<12)
-#define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_VALUE		 (0x7ffL<<16)
-#define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_PEEK_EN		 (1L<<27)
-#define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_SEL		 (0xfL<<28)
-
-#define BNX2_COM_CPU_LAST_BRANCH_ADDR			0x00105048
-#define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE		 (1L<<1)
-#define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE_JUMP		 (0L<<1)
-#define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH	 (1L<<1)
-#define BNX2_COM_CPU_LAST_BRANCH_ADDR_LBA		 (0x3fffffffL<<2)
-
-#define BNX2_COM_CPU_REG_FILE				0x00105200
-#define BNX2_COM_COMTQ_PFE_PFE_CTL			0x001052bc
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_INC_USAGE_CNT	 (1L<<0)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE		 (0xfL<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_0		 (0L<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_1		 (1L<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_2		 (2L<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_3		 (3L<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_4		 (4L<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_5		 (5L<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_6		 (6L<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_7		 (7L<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_8		 (8L<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_9		 (9L<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_10		 (10L<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_11		 (11L<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_12		 (12L<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_13		 (13L<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_14		 (14L<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_15		 (15L<<4)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_COUNT		 (0xfL<<12)
-#define BNX2_COM_COMTQ_PFE_PFE_CTL_OFFSET		 (0x1ffL<<16)
-
-#define BNX2_COM_COMXQ					0x00105340
-#define BNX2_COM_COMXQ_FTQ_CMD				0x00105378
-#define BNX2_COM_COMXQ_FTQ_CMD_OFFSET			 (0x3ffL<<0)
-#define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP			 (1L<<10)
-#define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP_0			 (0L<<10)
-#define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP_1			 (1L<<10)
-#define BNX2_COM_COMXQ_FTQ_CMD_SFT_RESET		 (1L<<25)
-#define BNX2_COM_COMXQ_FTQ_CMD_RD_DATA			 (1L<<26)
-#define BNX2_COM_COMXQ_FTQ_CMD_ADD_INTERVEN		 (1L<<27)
-#define BNX2_COM_COMXQ_FTQ_CMD_ADD_DATA			 (1L<<28)
-#define BNX2_COM_COMXQ_FTQ_CMD_INTERVENE_CLR		 (1L<<29)
-#define BNX2_COM_COMXQ_FTQ_CMD_POP			 (1L<<30)
-#define BNX2_COM_COMXQ_FTQ_CMD_BUSY			 (1L<<31)
-
-#define BNX2_COM_COMXQ_FTQ_CTL				0x0010537c
-#define BNX2_COM_COMXQ_FTQ_CTL_INTERVENE		 (1L<<0)
-#define BNX2_COM_COMXQ_FTQ_CTL_OVERFLOW			 (1L<<1)
-#define BNX2_COM_COMXQ_FTQ_CTL_FORCE_INTERVENE		 (1L<<2)
-#define BNX2_COM_COMXQ_FTQ_CTL_MAX_DEPTH		 (0x3ffL<<12)
-#define BNX2_COM_COMXQ_FTQ_CTL_CUR_DEPTH		 (0x3ffL<<22)
-
-#define BNX2_COM_COMTQ					0x00105380
-#define BNX2_COM_COMTQ_FTQ_CMD				0x001053b8
-#define BNX2_COM_COMTQ_FTQ_CMD_OFFSET			 (0x3ffL<<0)
-#define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP			 (1L<<10)
-#define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP_0			 (0L<<10)
-#define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP_1			 (1L<<10)
-#define BNX2_COM_COMTQ_FTQ_CMD_SFT_RESET		 (1L<<25)
-#define BNX2_COM_COMTQ_FTQ_CMD_RD_DATA			 (1L<<26)
-#define BNX2_COM_COMTQ_FTQ_CMD_ADD_INTERVEN		 (1L<<27)
-#define BNX2_COM_COMTQ_FTQ_CMD_ADD_DATA			 (1L<<28)
-#define BNX2_COM_COMTQ_FTQ_CMD_INTERVENE_CLR		 (1L<<29)
-#define BNX2_COM_COMTQ_FTQ_CMD_POP			 (1L<<30)
-#define BNX2_COM_COMTQ_FTQ_CMD_BUSY			 (1L<<31)
-
-#define BNX2_COM_COMTQ_FTQ_CTL				0x001053bc
-#define BNX2_COM_COMTQ_FTQ_CTL_INTERVENE		 (1L<<0)
-#define BNX2_COM_COMTQ_FTQ_CTL_OVERFLOW			 (1L<<1)
-#define BNX2_COM_COMTQ_FTQ_CTL_FORCE_INTERVENE		 (1L<<2)
-#define BNX2_COM_COMTQ_FTQ_CTL_MAX_DEPTH		 (0x3ffL<<12)
-#define BNX2_COM_COMTQ_FTQ_CTL_CUR_DEPTH		 (0x3ffL<<22)
-
-#define BNX2_COM_COMQ					0x001053c0
-#define BNX2_COM_COMQ_FTQ_CMD				0x001053f8
-#define BNX2_COM_COMQ_FTQ_CMD_OFFSET			 (0x3ffL<<0)
-#define BNX2_COM_COMQ_FTQ_CMD_WR_TOP			 (1L<<10)
-#define BNX2_COM_COMQ_FTQ_CMD_WR_TOP_0			 (0L<<10)
-#define BNX2_COM_COMQ_FTQ_CMD_WR_TOP_1			 (1L<<10)
-#define BNX2_COM_COMQ_FTQ_CMD_SFT_RESET			 (1L<<25)
-#define BNX2_COM_COMQ_FTQ_CMD_RD_DATA			 (1L<<26)
-#define BNX2_COM_COMQ_FTQ_CMD_ADD_INTERVEN		 (1L<<27)
-#define BNX2_COM_COMQ_FTQ_CMD_ADD_DATA			 (1L<<28)
-#define BNX2_COM_COMQ_FTQ_CMD_INTERVENE_CLR		 (1L<<29)
-#define BNX2_COM_COMQ_FTQ_CMD_POP			 (1L<<30)
-#define BNX2_COM_COMQ_FTQ_CMD_BUSY			 (1L<<31)
-
-#define BNX2_COM_COMQ_FTQ_CTL				0x001053fc
-#define BNX2_COM_COMQ_FTQ_CTL_INTERVENE			 (1L<<0)
-#define BNX2_COM_COMQ_FTQ_CTL_OVERFLOW			 (1L<<1)
-#define BNX2_COM_COMQ_FTQ_CTL_FORCE_INTERVENE		 (1L<<2)
-#define BNX2_COM_COMQ_FTQ_CTL_MAX_DEPTH			 (0x3ffL<<12)
-#define BNX2_COM_COMQ_FTQ_CTL_CUR_DEPTH			 (0x3ffL<<22)
-
-#define BNX2_COM_SCRATCH				0x00120000
-
-#define BNX2_FW_RX_LOW_LATENCY				 0x00120058
-#define BNX2_FW_RX_DROP_COUNT				 0x00120084
-
-
-/*
- *  cp_reg definition
- *  offset: 0x180000
- */
-#define BNX2_CP_CKSUM_ERROR_STATUS			0x00180000
-#define BNX2_CP_CKSUM_ERROR_STATUS_CALCULATED		 (0xffffL<<0)
-#define BNX2_CP_CKSUM_ERROR_STATUS_EXPECTED		 (0xffffL<<16)
-
-#define BNX2_CP_CPU_MODE				0x00185000
-#define BNX2_CP_CPU_MODE_LOCAL_RST			 (1L<<0)
-#define BNX2_CP_CPU_MODE_STEP_ENA			 (1L<<1)
-#define BNX2_CP_CPU_MODE_PAGE_0_DATA_ENA		 (1L<<2)
-#define BNX2_CP_CPU_MODE_PAGE_0_INST_ENA		 (1L<<3)
-#define BNX2_CP_CPU_MODE_MSG_BIT1			 (1L<<6)
-#define BNX2_CP_CPU_MODE_INTERRUPT_ENA			 (1L<<7)
-#define BNX2_CP_CPU_MODE_SOFT_HALT			 (1L<<10)
-#define BNX2_CP_CPU_MODE_BAD_DATA_HALT_ENA		 (1L<<11)
-#define BNX2_CP_CPU_MODE_BAD_INST_HALT_ENA		 (1L<<12)
-#define BNX2_CP_CPU_MODE_FIO_ABORT_HALT_ENA		 (1L<<13)
-#define BNX2_CP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA	 (1L<<15)
-
-#define BNX2_CP_CPU_STATE				0x00185004
-#define BNX2_CP_CPU_STATE_BREAKPOINT			 (1L<<0)
-#define BNX2_CP_CPU_STATE_BAD_INST_HALTED		 (1L<<2)
-#define BNX2_CP_CPU_STATE_PAGE_0_DATA_HALTED		 (1L<<3)
-#define BNX2_CP_CPU_STATE_PAGE_0_INST_HALTED		 (1L<<4)
-#define BNX2_CP_CPU_STATE_BAD_DATA_ADDR_HALTED		 (1L<<5)
-#define BNX2_CP_CPU_STATE_BAD_PC_HALTED			 (1L<<6)
-#define BNX2_CP_CPU_STATE_ALIGN_HALTED			 (1L<<7)
-#define BNX2_CP_CPU_STATE_FIO_ABORT_HALTED		 (1L<<8)
-#define BNX2_CP_CPU_STATE_SOFT_HALTED			 (1L<<10)
-#define BNX2_CP_CPU_STATE_SPAD_UNDERFLOW		 (1L<<11)
-#define BNX2_CP_CPU_STATE_INTERRRUPT			 (1L<<12)
-#define BNX2_CP_CPU_STATE_DATA_ACCESS_STALL		 (1L<<14)
-#define BNX2_CP_CPU_STATE_INST_FETCH_STALL		 (1L<<15)
-#define BNX2_CP_CPU_STATE_BLOCKED_READ			 (1L<<31)
-
-#define BNX2_CP_CPU_EVENT_MASK				0x00185008
-#define BNX2_CP_CPU_EVENT_MASK_BREAKPOINT_MASK		 (1L<<0)
-#define BNX2_CP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK	 (1L<<2)
-#define BNX2_CP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK	 (1L<<3)
-#define BNX2_CP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK	 (1L<<4)
-#define BNX2_CP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK	 (1L<<5)
-#define BNX2_CP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK	 (1L<<6)
-#define BNX2_CP_CPU_EVENT_MASK_ALIGN_HALTED_MASK	 (1L<<7)
-#define BNX2_CP_CPU_EVENT_MASK_FIO_ABORT_MASK		 (1L<<8)
-#define BNX2_CP_CPU_EVENT_MASK_SOFT_HALTED_MASK		 (1L<<10)
-#define BNX2_CP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK	 (1L<<11)
-#define BNX2_CP_CPU_EVENT_MASK_INTERRUPT_MASK		 (1L<<12)
-
-#define BNX2_CP_CPU_PROGRAM_COUNTER			0x0018501c
-#define BNX2_CP_CPU_INSTRUCTION				0x00185020
-#define BNX2_CP_CPU_DATA_ACCESS				0x00185024
-#define BNX2_CP_CPU_INTERRUPT_ENABLE			0x00185028
-#define BNX2_CP_CPU_INTERRUPT_VECTOR			0x0018502c
-#define BNX2_CP_CPU_INTERRUPT_SAVED_PC			0x00185030
-#define BNX2_CP_CPU_HW_BREAKPOINT			0x00185034
-#define BNX2_CP_CPU_HW_BREAKPOINT_DISABLE		 (1L<<0)
-#define BNX2_CP_CPU_HW_BREAKPOINT_ADDRESS		 (0x3fffffffL<<2)
-
-#define BNX2_CP_CPU_DEBUG_VECT_PEEK			0x00185038
-#define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_VALUE		 (0x7ffL<<0)
-#define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN		 (1L<<11)
-#define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_SEL		 (0xfL<<12)
-#define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_VALUE		 (0x7ffL<<16)
-#define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN		 (1L<<27)
-#define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_SEL		 (0xfL<<28)
-
-#define BNX2_CP_CPU_LAST_BRANCH_ADDR			0x00185048
-#define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE		 (1L<<1)
-#define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP		 (0L<<1)
-#define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH	 (1L<<1)
-#define BNX2_CP_CPU_LAST_BRANCH_ADDR_LBA		 (0x3fffffffL<<2)
-
-#define BNX2_CP_CPU_REG_FILE				0x00185200
-#define BNX2_CP_CPQ_PFE_PFE_CTL				0x001853bc
-#define BNX2_CP_CPQ_PFE_PFE_CTL_INC_USAGE_CNT		 (1L<<0)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE		 (0xfL<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_0		 (0L<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_1		 (1L<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_2		 (2L<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_3		 (3L<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_4		 (4L<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_5		 (5L<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_6		 (6L<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_7		 (7L<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_8		 (8L<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_9		 (9L<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_10		 (10L<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_11		 (11L<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_12		 (12L<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_13		 (13L<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_14		 (14L<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_15		 (15L<<4)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_COUNT		 (0xfL<<12)
-#define BNX2_CP_CPQ_PFE_PFE_CTL_OFFSET			 (0x1ffL<<16)
-
-#define BNX2_CP_CPQ					0x001853c0
-#define BNX2_CP_CPQ_FTQ_CMD				0x001853f8
-#define BNX2_CP_CPQ_FTQ_CMD_OFFSET			 (0x3ffL<<0)
-#define BNX2_CP_CPQ_FTQ_CMD_WR_TOP			 (1L<<10)
-#define BNX2_CP_CPQ_FTQ_CMD_WR_TOP_0			 (0L<<10)
-#define BNX2_CP_CPQ_FTQ_CMD_WR_TOP_1			 (1L<<10)
-#define BNX2_CP_CPQ_FTQ_CMD_SFT_RESET			 (1L<<25)
-#define BNX2_CP_CPQ_FTQ_CMD_RD_DATA			 (1L<<26)
-#define BNX2_CP_CPQ_FTQ_CMD_ADD_INTERVEN		 (1L<<27)
-#define BNX2_CP_CPQ_FTQ_CMD_ADD_DATA			 (1L<<28)
-#define BNX2_CP_CPQ_FTQ_CMD_INTERVENE_CLR		 (1L<<29)
-#define BNX2_CP_CPQ_FTQ_CMD_POP				 (1L<<30)
-#define BNX2_CP_CPQ_FTQ_CMD_BUSY			 (1L<<31)
-
-#define BNX2_CP_CPQ_FTQ_CTL				0x001853fc
-#define BNX2_CP_CPQ_FTQ_CTL_INTERVENE			 (1L<<0)
-#define BNX2_CP_CPQ_FTQ_CTL_OVERFLOW			 (1L<<1)
-#define BNX2_CP_CPQ_FTQ_CTL_FORCE_INTERVENE		 (1L<<2)
-#define BNX2_CP_CPQ_FTQ_CTL_MAX_DEPTH			 (0x3ffL<<12)
-#define BNX2_CP_CPQ_FTQ_CTL_CUR_DEPTH			 (0x3ffL<<22)
-
-#define BNX2_CP_SCRATCH					0x001a0000
-
-#define BNX2_FW_MAX_ISCSI_CONN				 0x001a0080
-
-
-/*
- *  mcp_reg definition
- *  offset: 0x140000
- */
-#define BNX2_MCP_MCP_CONTROL				0x00140080
-#define BNX2_MCP_MCP_CONTROL_SMBUS_SEL			 (1L<<30)
-#define BNX2_MCP_MCP_CONTROL_MCP_ISOLATE		 (1L<<31)
-
-#define BNX2_MCP_MCP_ATTENTION_STATUS			0x00140084
-#define BNX2_MCP_MCP_ATTENTION_STATUS_DRV_DOORBELL	 (1L<<29)
-#define BNX2_MCP_MCP_ATTENTION_STATUS_WATCHDOG_TIMEOUT	 (1L<<30)
-#define BNX2_MCP_MCP_ATTENTION_STATUS_CPU_EVENT		 (1L<<31)
-
-#define BNX2_MCP_MCP_HEARTBEAT_CONTROL			0x00140088
-#define BNX2_MCP_MCP_HEARTBEAT_CONTROL_MCP_HEARTBEAT_ENABLE	 (1L<<31)
-
-#define BNX2_MCP_MCP_HEARTBEAT_STATUS			0x0014008c
-#define BNX2_MCP_MCP_HEARTBEAT_STATUS_MCP_HEARTBEAT_PERIOD	 (0x7ffL<<0)
-#define BNX2_MCP_MCP_HEARTBEAT_STATUS_VALID		 (1L<<31)
-
-#define BNX2_MCP_MCP_HEARTBEAT				0x00140090
-#define BNX2_MCP_MCP_HEARTBEAT_MCP_HEARTBEAT_COUNT	 (0x3fffffffL<<0)
-#define BNX2_MCP_MCP_HEARTBEAT_MCP_HEARTBEAT_INC	 (1L<<30)
-#define BNX2_MCP_MCP_HEARTBEAT_MCP_HEARTBEAT_RESET	 (1L<<31)
-
-#define BNX2_MCP_WATCHDOG_RESET				0x00140094
-#define BNX2_MCP_WATCHDOG_RESET_WATCHDOG_RESET		 (1L<<31)
-
-#define BNX2_MCP_WATCHDOG_CONTROL			0x00140098
-#define BNX2_MCP_WATCHDOG_CONTROL_WATCHDOG_TIMEOUT	 (0xfffffffL<<0)
-#define BNX2_MCP_WATCHDOG_CONTROL_WATCHDOG_ATTN		 (1L<<29)
-#define BNX2_MCP_WATCHDOG_CONTROL_MCP_RST_ENABLE	 (1L<<30)
-#define BNX2_MCP_WATCHDOG_CONTROL_WATCHDOG_ENABLE	 (1L<<31)
-
-#define BNX2_MCP_ACCESS_LOCK				0x0014009c
-#define BNX2_MCP_ACCESS_LOCK_LOCK			 (1L<<31)
-
-#define BNX2_MCP_TOE_ID					0x001400a0
-#define BNX2_MCP_TOE_ID_FUNCTION_ID			 (1L<<31)
-
-#define BNX2_MCP_MAILBOX_CFG				0x001400a4
-#define BNX2_MCP_MAILBOX_CFG_MAILBOX_OFFSET		 (0x3fffL<<0)
-#define BNX2_MCP_MAILBOX_CFG_MAILBOX_SIZE		 (0xfffL<<20)
-
-#define BNX2_MCP_MAILBOX_CFG_OTHER_FUNC			0x001400a8
-#define BNX2_MCP_MAILBOX_CFG_OTHER_FUNC_MAILBOX_OFFSET	 (0x3fffL<<0)
-#define BNX2_MCP_MAILBOX_CFG_OTHER_FUNC_MAILBOX_SIZE	 (0xfffL<<20)
-
-#define BNX2_MCP_MCP_DOORBELL				0x001400ac
-#define BNX2_MCP_MCP_DOORBELL_MCP_DOORBELL		 (1L<<31)
-
-#define BNX2_MCP_DRIVER_DOORBELL			0x001400b0
-#define BNX2_MCP_DRIVER_DOORBELL_DRIVER_DOORBELL	 (1L<<31)
-
-#define BNX2_MCP_DRIVER_DOORBELL_OTHER_FUNC		0x001400b4
-#define BNX2_MCP_DRIVER_DOORBELL_OTHER_FUNC_DRIVER_DOORBELL	 (1L<<31)
-
-#define BNX2_MCP_CPU_MODE				0x00145000
-#define BNX2_MCP_CPU_MODE_LOCAL_RST			 (1L<<0)
-#define BNX2_MCP_CPU_MODE_STEP_ENA			 (1L<<1)
-#define BNX2_MCP_CPU_MODE_PAGE_0_DATA_ENA		 (1L<<2)
-#define BNX2_MCP_CPU_MODE_PAGE_0_INST_ENA		 (1L<<3)
-#define BNX2_MCP_CPU_MODE_MSG_BIT1			 (1L<<6)
-#define BNX2_MCP_CPU_MODE_INTERRUPT_ENA			 (1L<<7)
-#define BNX2_MCP_CPU_MODE_SOFT_HALT			 (1L<<10)
-#define BNX2_MCP_CPU_MODE_BAD_DATA_HALT_ENA		 (1L<<11)
-#define BNX2_MCP_CPU_MODE_BAD_INST_HALT_ENA		 (1L<<12)
-#define BNX2_MCP_CPU_MODE_FIO_ABORT_HALT_ENA		 (1L<<13)
-#define BNX2_MCP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA	 (1L<<15)
-
-#define BNX2_MCP_CPU_STATE				0x00145004
-#define BNX2_MCP_CPU_STATE_BREAKPOINT			 (1L<<0)
-#define BNX2_MCP_CPU_STATE_BAD_INST_HALTED		 (1L<<2)
-#define BNX2_MCP_CPU_STATE_PAGE_0_DATA_HALTED		 (1L<<3)
-#define BNX2_MCP_CPU_STATE_PAGE_0_INST_HALTED		 (1L<<4)
-#define BNX2_MCP_CPU_STATE_BAD_DATA_ADDR_HALTED		 (1L<<5)
-#define BNX2_MCP_CPU_STATE_BAD_PC_HALTED		 (1L<<6)
-#define BNX2_MCP_CPU_STATE_ALIGN_HALTED			 (1L<<7)
-#define BNX2_MCP_CPU_STATE_FIO_ABORT_HALTED		 (1L<<8)
-#define BNX2_MCP_CPU_STATE_SOFT_HALTED			 (1L<<10)
-#define BNX2_MCP_CPU_STATE_SPAD_UNDERFLOW		 (1L<<11)
-#define BNX2_MCP_CPU_STATE_INTERRRUPT			 (1L<<12)
-#define BNX2_MCP_CPU_STATE_DATA_ACCESS_STALL		 (1L<<14)
-#define BNX2_MCP_CPU_STATE_INST_FETCH_STALL		 (1L<<15)
-#define BNX2_MCP_CPU_STATE_BLOCKED_READ			 (1L<<31)
-
-#define BNX2_MCP_CPU_EVENT_MASK				0x00145008
-#define BNX2_MCP_CPU_EVENT_MASK_BREAKPOINT_MASK		 (1L<<0)
-#define BNX2_MCP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK	 (1L<<2)
-#define BNX2_MCP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK	 (1L<<3)
-#define BNX2_MCP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK	 (1L<<4)
-#define BNX2_MCP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK	 (1L<<5)
-#define BNX2_MCP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK	 (1L<<6)
-#define BNX2_MCP_CPU_EVENT_MASK_ALIGN_HALTED_MASK	 (1L<<7)
-#define BNX2_MCP_CPU_EVENT_MASK_FIO_ABORT_MASK		 (1L<<8)
-#define BNX2_MCP_CPU_EVENT_MASK_SOFT_HALTED_MASK	 (1L<<10)
-#define BNX2_MCP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK	 (1L<<11)
-#define BNX2_MCP_CPU_EVENT_MASK_INTERRUPT_MASK		 (1L<<12)
-
-#define BNX2_MCP_CPU_PROGRAM_COUNTER			0x0014501c
-#define BNX2_MCP_CPU_INSTRUCTION			0x00145020
-#define BNX2_MCP_CPU_DATA_ACCESS			0x00145024
-#define BNX2_MCP_CPU_INTERRUPT_ENABLE			0x00145028
-#define BNX2_MCP_CPU_INTERRUPT_VECTOR			0x0014502c
-#define BNX2_MCP_CPU_INTERRUPT_SAVED_PC			0x00145030
-#define BNX2_MCP_CPU_HW_BREAKPOINT			0x00145034
-#define BNX2_MCP_CPU_HW_BREAKPOINT_DISABLE		 (1L<<0)
-#define BNX2_MCP_CPU_HW_BREAKPOINT_ADDRESS		 (0x3fffffffL<<2)
-
-#define BNX2_MCP_CPU_DEBUG_VECT_PEEK			0x00145038
-#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_VALUE		 (0x7ffL<<0)
-#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN		 (1L<<11)
-#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_SEL		 (0xfL<<12)
-#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_VALUE		 (0x7ffL<<16)
-#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN		 (1L<<27)
-#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_SEL		 (0xfL<<28)
-
-#define BNX2_MCP_CPU_LAST_BRANCH_ADDR			0x00145048
-#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE		 (1L<<1)
-#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP		 (0L<<1)
-#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH	 (1L<<1)
-#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_LBA		 (0x3fffffffL<<2)
-
-#define BNX2_MCP_CPU_REG_FILE				0x00145200
-#define BNX2_MCP_MCPQ					0x001453c0
-#define BNX2_MCP_MCPQ_FTQ_CMD				0x001453f8
-#define BNX2_MCP_MCPQ_FTQ_CMD_OFFSET			 (0x3ffL<<0)
-#define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP			 (1L<<10)
-#define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP_0			 (0L<<10)
-#define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP_1			 (1L<<10)
-#define BNX2_MCP_MCPQ_FTQ_CMD_SFT_RESET			 (1L<<25)
-#define BNX2_MCP_MCPQ_FTQ_CMD_RD_DATA			 (1L<<26)
-#define BNX2_MCP_MCPQ_FTQ_CMD_ADD_INTERVEN		 (1L<<27)
-#define BNX2_MCP_MCPQ_FTQ_CMD_ADD_DATA			 (1L<<28)
-#define BNX2_MCP_MCPQ_FTQ_CMD_INTERVENE_CLR		 (1L<<29)
-#define BNX2_MCP_MCPQ_FTQ_CMD_POP			 (1L<<30)
-#define BNX2_MCP_MCPQ_FTQ_CMD_BUSY			 (1L<<31)
-
-#define BNX2_MCP_MCPQ_FTQ_CTL				0x001453fc
-#define BNX2_MCP_MCPQ_FTQ_CTL_INTERVENE			 (1L<<0)
-#define BNX2_MCP_MCPQ_FTQ_CTL_OVERFLOW			 (1L<<1)
-#define BNX2_MCP_MCPQ_FTQ_CTL_FORCE_INTERVENE		 (1L<<2)
-#define BNX2_MCP_MCPQ_FTQ_CTL_MAX_DEPTH			 (0x3ffL<<12)
-#define BNX2_MCP_MCPQ_FTQ_CTL_CUR_DEPTH			 (0x3ffL<<22)
-
-#define BNX2_MCP_ROM					0x00150000
-#define BNX2_MCP_SCRATCH				0x00160000
-#define BNX2_MCP_STATE_P1				 0x0016f9c8
-#define BNX2_MCP_STATE_P0				 0x0016fdc8
-#define BNX2_MCP_STATE_P1_5708				 0x001699c8
-#define BNX2_MCP_STATE_P0_5708				 0x00169dc8
-
-#define BNX2_SHM_HDR_SIGNATURE				BNX2_MCP_SCRATCH
-#define BNX2_SHM_HDR_SIGNATURE_SIG_MASK			 0xffff0000
-#define BNX2_SHM_HDR_SIGNATURE_SIG			 0x53530000
-#define BNX2_SHM_HDR_SIGNATURE_VER_MASK			 0x000000ff
-#define BNX2_SHM_HDR_SIGNATURE_VER_ONE			 0x00000001
-
-#define BNX2_SHM_HDR_ADDR_0				BNX2_MCP_SCRATCH + 4
-#define BNX2_SHM_HDR_ADDR_1				BNX2_MCP_SCRATCH + 8
-
-
-#define NUM_MC_HASH_REGISTERS   8
-
-
-/* PHY_ID1: bits 31-16; PHY_ID2: bits 15-0.  */
-#define PHY_BCM5706_PHY_ID                          0x00206160
-
-#define PHY_ID(id)                                  ((id) & 0xfffffff0)
-#define PHY_REV_ID(id)                              ((id) & 0xf)
-
-/* 5708 Serdes PHY registers */
-
-#define BCM5708S_BMCR_FORCE_2500		0x20
-
-#define BCM5708S_UP1				0xb
-
-#define BCM5708S_UP1_2G5			0x1
-
-#define BCM5708S_BLK_ADDR			0x1f
-
-#define BCM5708S_BLK_ADDR_DIG			0x0000
-#define BCM5708S_BLK_ADDR_DIG3			0x0002
-#define BCM5708S_BLK_ADDR_TX_MISC		0x0005
-
-/* Digital Block */
-#define BCM5708S_1000X_CTL1			0x10
-
-#define BCM5708S_1000X_CTL1_FIBER_MODE		0x0001
-#define BCM5708S_1000X_CTL1_AUTODET_EN		0x0010
-
-#define BCM5708S_1000X_CTL2			0x11
-
-#define BCM5708S_1000X_CTL2_PLLEL_DET_EN	0x0001
-
-#define BCM5708S_1000X_STAT1			0x14
-
-#define BCM5708S_1000X_STAT1_SGMII		0x0001
-#define BCM5708S_1000X_STAT1_LINK		0x0002
-#define BCM5708S_1000X_STAT1_FD			0x0004
-#define BCM5708S_1000X_STAT1_SPEED_MASK		0x0018
-#define BCM5708S_1000X_STAT1_SPEED_10		0x0000
-#define BCM5708S_1000X_STAT1_SPEED_100		0x0008
-#define BCM5708S_1000X_STAT1_SPEED_1G		0x0010
-#define BCM5708S_1000X_STAT1_SPEED_2G5		0x0018
-#define BCM5708S_1000X_STAT1_TX_PAUSE		0x0020
-#define BCM5708S_1000X_STAT1_RX_PAUSE		0x0040
-
-/* Digital3 Block */
-#define BCM5708S_DIG_3_0			0x10
-
-#define BCM5708S_DIG_3_0_USE_IEEE		0x0001
-
-/* Tx/Misc Block */
-#define BCM5708S_TX_ACTL1			0x15
-
-#define BCM5708S_TX_ACTL1_DRIVER_VCM		0x30
-
-#define BCM5708S_TX_ACTL3			0x17
-
-#define MII_BNX2_DSP_RW_PORT			0x15
-#define MII_BNX2_DSP_ADDRESS			0x17
-#define MII_BNX2_DSP_EXPAND_REG			 0x0f00
-#define MII_EXPAND_REG1				  (MII_BNX2_DSP_EXPAND_REG | 1)
-#define MII_EXPAND_REG1_RUDI_C			   0x20
-#define MII_EXPAND_SERDES_CTL			  (MII_BNX2_DSP_EXPAND_REG | 3)
-
-#define MII_BNX2_MISC_SHADOW			0x1c
-#define MISC_SHDW_AN_DBG			 0x6800
-#define MISC_SHDW_AN_DBG_NOSYNC			  0x0002
-#define MISC_SHDW_AN_DBG_RUDI_INVALID		  0x0100
-#define MISC_SHDW_MODE_CTL			 0x7c00
-#define MISC_SHDW_MODE_CTL_SIG_DET		  0x0010
-
-#define MII_BNX2_BLK_ADDR			0x1f
-#define MII_BNX2_BLK_ADDR_IEEE0			 0x0000
-#define MII_BNX2_BLK_ADDR_GP_STATUS		 0x8120
-#define MII_BNX2_GP_TOP_AN_STATUS1		  0x1b
-#define MII_BNX2_GP_TOP_AN_SPEED_MSK		   0x3f00
-#define MII_BNX2_GP_TOP_AN_SPEED_10		   0x0000
-#define MII_BNX2_GP_TOP_AN_SPEED_100		   0x0100
-#define MII_BNX2_GP_TOP_AN_SPEED_1G		   0x0200
-#define MII_BNX2_GP_TOP_AN_SPEED_2_5G		   0x0300
-#define MII_BNX2_GP_TOP_AN_SPEED_1GKV		   0x0d00
-#define MII_BNX2_GP_TOP_AN_FD			   0x8
-#define MII_BNX2_BLK_ADDR_SERDES_DIG		 0x8300
-#define MII_BNX2_SERDES_DIG_1000XCTL1		  0x10
-#define MII_BNX2_SD_1000XCTL1_FIBER		   0x01
-#define MII_BNX2_SD_1000XCTL1_AUTODET		   0x10
-#define MII_BNX2_SERDES_DIG_MISC1		  0x18
-#define MII_BNX2_SD_MISC1_FORCE_MSK		   0xf
-#define MII_BNX2_SD_MISC1_FORCE_2_5G		   0x0
-#define MII_BNX2_SD_MISC1_FORCE			   0x10
-#define MII_BNX2_BLK_ADDR_OVER1G		 0x8320
-#define MII_BNX2_OVER1G_UP1			  0x19
-#define MII_BNX2_BLK_ADDR_BAM_NXTPG		 0x8350
-#define MII_BNX2_BAM_NXTPG_CTL			  0x10
-#define MII_BNX2_NXTPG_CTL_BAM			   0x1
-#define MII_BNX2_NXTPG_CTL_T2			   0x2
-#define MII_BNX2_BLK_ADDR_CL73_USERB0		 0x8370
-#define MII_BNX2_CL73_BAM_CTL1			  0x12
-#define MII_BNX2_CL73_BAM_EN			   0x8000
-#define MII_BNX2_CL73_BAM_STA_MGR_EN		   0x4000
-#define MII_BNX2_CL73_BAM_NP_AFT_BP_EN		   0x2000
-#define MII_BNX2_BLK_ADDR_AER			 0xffd0
-#define MII_BNX2_AER_AER			  0x1e
-#define MII_BNX2_AER_AER_AN_MMD			   0x3800
-#define MII_BNX2_BLK_ADDR_COMBO_IEEEB0		 0xffe0
-
-#define MIN_ETHERNET_PACKET_SIZE	60
-#define MAX_ETHERNET_PACKET_SIZE	1514
-#define MAX_ETHERNET_JUMBO_PACKET_SIZE	9014
-
-#define BNX2_RX_COPY_THRESH		128
-
-#define BNX2_MISC_ENABLE_DEFAULT	0x17ffffff
-
-#define BNX2_START_UNICAST_ADDRESS_INDEX	4
-#define BNX2_END_UNICAST_ADDRESS_INDEX		7
-#define BNX2_MAX_UNICAST_ADDRESSES     	(BNX2_END_UNICAST_ADDRESS_INDEX - \
-					 BNX2_START_UNICAST_ADDRESS_INDEX + 1)
-
-#define DMA_READ_CHANS	5
-#define DMA_WRITE_CHANS	3
-
-/* Use CPU native page size up to 16K for the ring sizes.  */
-#if (PAGE_SHIFT > 14)
-#define BCM_PAGE_BITS	14
-#else
-#define BCM_PAGE_BITS	PAGE_SHIFT
-#endif
-#define BCM_PAGE_SIZE	(1 << BCM_PAGE_BITS)
-
-#define TX_DESC_CNT  (BCM_PAGE_SIZE / sizeof(struct tx_bd))
-#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
-
-#define MAX_RX_RINGS	8
-#define MAX_RX_PG_RINGS	32
-#define RX_DESC_CNT  (BCM_PAGE_SIZE / sizeof(struct rx_bd))
-#define MAX_RX_DESC_CNT (RX_DESC_CNT - 1)
-#define MAX_TOTAL_RX_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_RINGS)
-#define MAX_TOTAL_RX_PG_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_PG_RINGS)
-
-#define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) ==			\
-		(MAX_TX_DESC_CNT - 1)) ?				\
-	(x) + 2 : (x) + 1
-
-#define TX_RING_IDX(x) ((x) & MAX_TX_DESC_CNT)
-
-#define NEXT_RX_BD(x) (((x) & (MAX_RX_DESC_CNT - 1)) ==			\
-		(MAX_RX_DESC_CNT - 1)) ?				\
-	(x) + 2 : (x) + 1
-
-#define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx)
-#define RX_PG_RING_IDX(x) ((x) & bp->rx_max_pg_ring_idx)
-
-#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> (BCM_PAGE_BITS - 4))
-#define RX_IDX(x) ((x) & MAX_RX_DESC_CNT)
-
-/* Context size. */
-#define CTX_SHIFT                   7
-#define CTX_SIZE                    (1 << CTX_SHIFT)
-#define CTX_MASK                    (CTX_SIZE - 1)
-#define GET_CID_ADDR(_cid)          ((_cid) << CTX_SHIFT)
-#define GET_CID(_cid_addr)          ((_cid_addr) >> CTX_SHIFT)
-
-#define PHY_CTX_SHIFT               6
-#define PHY_CTX_SIZE                (1 << PHY_CTX_SHIFT)
-#define PHY_CTX_MASK                (PHY_CTX_SIZE - 1)
-#define GET_PCID_ADDR(_pcid)        ((_pcid) << PHY_CTX_SHIFT)
-#define GET_PCID(_pcid_addr)        ((_pcid_addr) >> PHY_CTX_SHIFT)
-
-#define MB_KERNEL_CTX_SHIFT         8
-#define MB_KERNEL_CTX_SIZE          (1 << MB_KERNEL_CTX_SHIFT)
-#define MB_KERNEL_CTX_MASK          (MB_KERNEL_CTX_SIZE - 1)
-#define MB_GET_CID_ADDR(_cid)       (0x10000 + ((_cid) << MB_KERNEL_CTX_SHIFT))
-
-#define MAX_CID_CNT                 0x4000
-#define MAX_CID_ADDR                (GET_CID_ADDR(MAX_CID_CNT))
-#define INVALID_CID_ADDR            0xffffffff
-
-#define TX_CID		16
-#define TX_TSS_CID	32
-#define RX_CID		0
-#define RX_RSS_CID	4
-#define RX_MAX_RSS_RINGS	7
-#define RX_MAX_RINGS		(RX_MAX_RSS_RINGS + 1)
-#define TX_MAX_TSS_RINGS	7
-#define TX_MAX_RINGS		(TX_MAX_TSS_RINGS + 1)
-
-#define MB_TX_CID_ADDR	MB_GET_CID_ADDR(TX_CID)
-#define MB_RX_CID_ADDR	MB_GET_CID_ADDR(RX_CID)
-
-struct sw_bd {
-	struct sk_buff		*skb;
-	struct l2_fhdr		*desc;
-	DEFINE_DMA_UNMAP_ADDR(mapping);
-};
-
-struct sw_pg {
-	struct page		*page;
-	DEFINE_DMA_UNMAP_ADDR(mapping);
-};
-
-struct sw_tx_bd {
-	struct sk_buff		*skb;
-	DEFINE_DMA_UNMAP_ADDR(mapping);
-	unsigned short		is_gso;
-	unsigned short		nr_frags;
-};
-
-#define SW_RXBD_RING_SIZE (sizeof(struct sw_bd) * RX_DESC_CNT)
-#define SW_RXPG_RING_SIZE (sizeof(struct sw_pg) * RX_DESC_CNT)
-#define RXBD_RING_SIZE (sizeof(struct rx_bd) * RX_DESC_CNT)
-#define SW_TXBD_RING_SIZE (sizeof(struct sw_tx_bd) * TX_DESC_CNT)
-#define TXBD_RING_SIZE (sizeof(struct tx_bd) * TX_DESC_CNT)
-
-/* Buffered flash (Atmel: AT45DB011B) specific information */
-#define SEEPROM_PAGE_BITS			2
-#define SEEPROM_PHY_PAGE_SIZE			(1 << SEEPROM_PAGE_BITS)
-#define SEEPROM_BYTE_ADDR_MASK			(SEEPROM_PHY_PAGE_SIZE-1)
-#define SEEPROM_PAGE_SIZE			4
-#define SEEPROM_TOTAL_SIZE			65536
-
-#define BUFFERED_FLASH_PAGE_BITS		9
-#define BUFFERED_FLASH_PHY_PAGE_SIZE		(1 << BUFFERED_FLASH_PAGE_BITS)
-#define BUFFERED_FLASH_BYTE_ADDR_MASK		(BUFFERED_FLASH_PHY_PAGE_SIZE-1)
-#define BUFFERED_FLASH_PAGE_SIZE		264
-#define BUFFERED_FLASH_TOTAL_SIZE		0x21000
-
-#define SAIFUN_FLASH_PAGE_BITS			8
-#define SAIFUN_FLASH_PHY_PAGE_SIZE		(1 << SAIFUN_FLASH_PAGE_BITS)
-#define SAIFUN_FLASH_BYTE_ADDR_MASK		(SAIFUN_FLASH_PHY_PAGE_SIZE-1)
-#define SAIFUN_FLASH_PAGE_SIZE			256
-#define SAIFUN_FLASH_BASE_TOTAL_SIZE		65536
-
-#define ST_MICRO_FLASH_PAGE_BITS		8
-#define ST_MICRO_FLASH_PHY_PAGE_SIZE		(1 << ST_MICRO_FLASH_PAGE_BITS)
-#define ST_MICRO_FLASH_BYTE_ADDR_MASK		(ST_MICRO_FLASH_PHY_PAGE_SIZE-1)
-#define ST_MICRO_FLASH_PAGE_SIZE		256
-#define ST_MICRO_FLASH_BASE_TOTAL_SIZE		65536
-
-#define BCM5709_FLASH_PAGE_BITS			8
-#define BCM5709_FLASH_PHY_PAGE_SIZE		(1 << BCM5709_FLASH_PAGE_BITS)
-#define BCM5709_FLASH_BYTE_ADDR_MASK		(BCM5709_FLASH_PHY_PAGE_SIZE-1)
-#define BCM5709_FLASH_PAGE_SIZE			256
-
-#define NVRAM_TIMEOUT_COUNT			30000
-
-
-#define FLASH_STRAP_MASK			(BNX2_NVM_CFG1_FLASH_MODE   | \
-						 BNX2_NVM_CFG1_BUFFER_MODE  | \
-						 BNX2_NVM_CFG1_PROTECT_MODE | \
-						 BNX2_NVM_CFG1_FLASH_SIZE)
-
-#define FLASH_BACKUP_STRAP_MASK			(0xf << 26)
-
-struct flash_spec {
-	u32 strapping;
-	u32 config1;
-	u32 config2;
-	u32 config3;
-	u32 write1;
-	u32 flags;
-#define BNX2_NV_BUFFERED	0x00000001
-#define BNX2_NV_TRANSLATE	0x00000002
-#define BNX2_NV_WREN		0x00000004
-	u32 page_bits;
-	u32 page_size;
-	u32 addr_mask;
-	u32 total_size;
-	u8  *name;
-};
-
-#define BNX2_MAX_MSIX_HW_VEC	9
-#define BNX2_MAX_MSIX_VEC	9
-#ifdef BCM_CNIC
-#define BNX2_MIN_MSIX_VEC	2
-#else
-#define BNX2_MIN_MSIX_VEC	1
-#endif
-
-
-struct bnx2_irq {
-	irq_handler_t	handler;
-	unsigned int	vector;
-	u8		requested;
-	char		name[IFNAMSIZ + 2];
-};
-
-struct bnx2_tx_ring_info {
-	u32			tx_prod_bseq;
-	u16			tx_prod;
-	u32			tx_bidx_addr;
-	u32			tx_bseq_addr;
-
-	struct tx_bd		*tx_desc_ring;
-	struct sw_tx_bd		*tx_buf_ring;
-
-	u16			tx_cons;
-	u16			hw_tx_cons;
-
-	dma_addr_t		tx_desc_mapping;
-};
-
-struct bnx2_rx_ring_info {
-	u32			rx_prod_bseq;
-	u16			rx_prod;
-	u16			rx_cons;
-
-	u32			rx_bidx_addr;
-	u32			rx_bseq_addr;
-	u32			rx_pg_bidx_addr;
-
-	u16			rx_pg_prod;
-	u16			rx_pg_cons;
-
-	struct sw_bd		*rx_buf_ring;
-	struct rx_bd		*rx_desc_ring[MAX_RX_RINGS];
-	struct sw_pg		*rx_pg_ring;
-	struct rx_bd		*rx_pg_desc_ring[MAX_RX_PG_RINGS];
-
-	dma_addr_t		rx_desc_mapping[MAX_RX_RINGS];
-	dma_addr_t		rx_pg_desc_mapping[MAX_RX_PG_RINGS];
-};
-
-struct bnx2_napi {
-	struct napi_struct	napi		____cacheline_aligned;
-	struct bnx2		*bp;
-	union {
-		struct status_block		*msi;
-		struct status_block_msix	*msix;
-	} status_blk;
-	u16			*hw_tx_cons_ptr;
-	u16			*hw_rx_cons_ptr;
-	u32 			last_status_idx;
-	u32			int_num;
-
-#ifdef BCM_CNIC
-	u32			cnic_tag;
-	int			cnic_present;
-#endif
-
-	struct bnx2_rx_ring_info	rx_ring;
-	struct bnx2_tx_ring_info	tx_ring;
-};
-
-struct bnx2 {
-	/* Fields used in the tx and intr/napi performance paths are grouped */
-	/* together in the beginning of the structure. */
-	void __iomem		*regview;
-
-	struct net_device	*dev;
-	struct pci_dev		*pdev;
-
-	atomic_t		intr_sem;
-
-	u32			flags;
-#define BNX2_FLAG_PCIX			0x00000001
-#define BNX2_FLAG_PCI_32BIT		0x00000002
-#define BNX2_FLAG_MSIX_CAP		0x00000004
-#define BNX2_FLAG_NO_WOL		0x00000008
-#define BNX2_FLAG_USING_MSI		0x00000020
-#define BNX2_FLAG_ASF_ENABLE		0x00000040
-#define BNX2_FLAG_MSI_CAP		0x00000080
-#define BNX2_FLAG_ONE_SHOT_MSI		0x00000100
-#define BNX2_FLAG_PCIE			0x00000200
-#define BNX2_FLAG_USING_MSIX		0x00000400
-#define BNX2_FLAG_USING_MSI_OR_MSIX	(BNX2_FLAG_USING_MSI | \
-					 BNX2_FLAG_USING_MSIX)
-#define BNX2_FLAG_JUMBO_BROKEN		0x00000800
-#define BNX2_FLAG_CAN_KEEP_VLAN		0x00001000
-#define BNX2_FLAG_BROKEN_STATS		0x00002000
-#define BNX2_FLAG_AER_ENABLED		0x00004000
-
-	struct bnx2_napi	bnx2_napi[BNX2_MAX_MSIX_VEC];
-
-	u32			rx_buf_use_size;	/* useable size */
-	u32			rx_buf_size;		/* with alignment */
-	u32			rx_copy_thresh;
-	u32			rx_jumbo_thresh;
-	u32			rx_max_ring_idx;
-	u32			rx_max_pg_ring_idx;
-
-	/* TX constants */
-	int		tx_ring_size;
-	u32		tx_wake_thresh;
-
-#ifdef BCM_CNIC
-	struct cnic_ops	__rcu	*cnic_ops;
-	void			*cnic_data;
-#endif
-
-	/* End of fields used in the performance code paths. */
-
-	unsigned int		current_interval;
-#define BNX2_TIMER_INTERVAL		HZ
-#define BNX2_SERDES_AN_TIMEOUT		(HZ / 3)
-#define BNX2_SERDES_FORCED_TIMEOUT	(HZ / 10)
-
-	struct			timer_list timer;
-	struct work_struct	reset_task;
-
-	/* Used to synchronize phy accesses. */
-	spinlock_t		phy_lock;
-	spinlock_t		indirect_lock;
-
-	u32			phy_flags;
-#define BNX2_PHY_FLAG_SERDES			0x00000001
-#define BNX2_PHY_FLAG_CRC_FIX			0x00000002
-#define BNX2_PHY_FLAG_PARALLEL_DETECT		0x00000004
-#define BNX2_PHY_FLAG_2_5G_CAPABLE		0x00000008
-#define BNX2_PHY_FLAG_INT_MODE_MASK		0x00000300
-#define BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING	0x00000100
-#define BNX2_PHY_FLAG_INT_MODE_LINK_READY	0x00000200
-#define BNX2_PHY_FLAG_DIS_EARLY_DAC		0x00000400
-#define BNX2_PHY_FLAG_REMOTE_PHY_CAP		0x00000800
-#define BNX2_PHY_FLAG_FORCED_DOWN		0x00001000
-#define BNX2_PHY_FLAG_NO_PARALLEL		0x00002000
-
-	u32			mii_bmcr;
-	u32			mii_bmsr;
-	u32			mii_bmsr1;
-	u32			mii_adv;
-	u32			mii_lpa;
-	u32			mii_up1;
-
-	u32			chip_id;
-	/* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
-#define CHIP_NUM(bp)			(((bp)->chip_id) & 0xffff0000)
-#define CHIP_NUM_5706			0x57060000
-#define CHIP_NUM_5708			0x57080000
-#define CHIP_NUM_5709			0x57090000
-
-#define CHIP_REV(bp)			(((bp)->chip_id) & 0x0000f000)
-#define CHIP_REV_Ax			0x00000000
-#define CHIP_REV_Bx			0x00001000
-#define CHIP_REV_Cx			0x00002000
-
-#define CHIP_METAL(bp)			(((bp)->chip_id) & 0x00000ff0)
-#define CHIP_BONDING(bp)		(((bp)->chip_id) & 0x0000000f)
-
-#define CHIP_ID(bp)			(((bp)->chip_id) & 0xfffffff0)
-#define CHIP_ID_5706_A0			0x57060000
-#define CHIP_ID_5706_A1			0x57060010
-#define CHIP_ID_5706_A2			0x57060020
-#define CHIP_ID_5708_A0			0x57080000
-#define CHIP_ID_5708_B0			0x57081000
-#define CHIP_ID_5708_B1			0x57081010
-#define CHIP_ID_5709_A0			0x57090000
-#define CHIP_ID_5709_A1			0x57090010
-
-#define CHIP_BOND_ID(bp)		(((bp)->chip_id) & 0xf)
-
-/* A serdes chip will have the first bit of the bond id set. */
-#define CHIP_BOND_ID_SERDES_BIT		0x01
-
-	u32			phy_addr;
-	u32			phy_id;
-
-	u16			bus_speed_mhz;
-	u8			wol;
-
-	u8			pad;
-
-	u16			fw_wr_seq;
-	u16			fw_drv_pulse_wr_seq;
-
-	int			rx_max_ring;
-	int			rx_ring_size;
-
-	int			rx_max_pg_ring;
-	int			rx_pg_ring_size;
-
-	u16			tx_quick_cons_trip;
-	u16			tx_quick_cons_trip_int;
-	u16			rx_quick_cons_trip;
-	u16			rx_quick_cons_trip_int;
-	u16			comp_prod_trip;
-	u16			comp_prod_trip_int;
-	u16			tx_ticks;
-	u16			tx_ticks_int;
-	u16			com_ticks;
-	u16			com_ticks_int;
-	u16			cmd_ticks;
-	u16			cmd_ticks_int;
-	u16			rx_ticks;
-	u16			rx_ticks_int;
-
-	u32			stats_ticks;
-
-	dma_addr_t		status_blk_mapping;
-
-	struct statistics_block	*stats_blk;
-	struct statistics_block	*temp_stats_blk;
-	dma_addr_t		stats_blk_mapping;
-
-	int			ctx_pages;
-	void			*ctx_blk[4];
-	dma_addr_t		ctx_blk_mapping[4];
-
-	u32			hc_cmd;
-	u32			rx_mode;
-
-	u16			req_line_speed;
-	u8			req_duplex;
-
-	u8			phy_port;
-	u8			link_up;
-
-	u16			line_speed;
-	u8			duplex;
-	u8			flow_ctrl;	/* actual flow ctrl settings */
-						/* may be different from     */
-						/* req_flow_ctrl if autoneg  */
-	u32			advertising;
-
-	u8			req_flow_ctrl;	/* flow ctrl advertisement */
-						/* settings or forced      */
-						/* settings                */
-	u8			autoneg;
-#define AUTONEG_SPEED		1
-#define AUTONEG_FLOW_CTRL	2
-
-	u8			loopback;
-#define MAC_LOOPBACK		1
-#define PHY_LOOPBACK		2
-
-	u8			serdes_an_pending;
-
-	u8			mac_addr[8];
-
-	u32			shmem_base;
-
-	char			fw_version[32];
-
-	int			pm_cap;
-	int			pcix_cap;
-
-	const struct flash_spec	*flash_info;
-	u32			flash_size;
-
-	int			status_stats_size;
-
-	struct bnx2_irq		irq_tbl[BNX2_MAX_MSIX_VEC];
-	int			irq_nvecs;
-
-	u8			num_tx_rings;
-	u8			num_rx_rings;
-
-	u32 			leds_save;
-	u32			idle_chk_status_idx;
-
-#ifdef BCM_CNIC
-	struct mutex		cnic_lock;
-	struct cnic_eth_dev	cnic_eth_dev;
-#endif
-
-	const struct firmware	*mips_firmware;
-	const struct firmware	*rv2p_firmware;
-};
-
-#define REG_RD(bp, offset)					\
-	readl(bp->regview + offset)
-
-#define REG_WR(bp, offset, val)					\
-	writel(val, bp->regview + offset)
-
-#define REG_WR16(bp, offset, val)				\
-	writew(val, bp->regview + offset)
-
-struct cpu_reg {
-	u32 mode;
-	u32 mode_value_halt;
-	u32 mode_value_sstep;
-
-	u32 state;
-	u32 state_value_clear;
-
-	u32 gpr0;
-	u32 evmask;
-	u32 pc;
-	u32 inst;
-	u32 bp;
-
-	u32 spad_base;
-
-	u32 mips_view_base;
-};
-
-struct bnx2_fw_file_section {
-	__be32 addr;
-	__be32 len;
-	__be32 offset;
-};
-
-struct bnx2_mips_fw_file_entry {
-	__be32 start_addr;
-	struct bnx2_fw_file_section text;
-	struct bnx2_fw_file_section data;
-	struct bnx2_fw_file_section rodata;
-};
-
-struct bnx2_rv2p_fw_file_entry {
-	struct bnx2_fw_file_section rv2p;
-	__be32 fixup[8];
-};
-
-struct bnx2_mips_fw_file {
-	struct bnx2_mips_fw_file_entry com;
-	struct bnx2_mips_fw_file_entry cp;
-	struct bnx2_mips_fw_file_entry rxp;
-	struct bnx2_mips_fw_file_entry tpat;
-	struct bnx2_mips_fw_file_entry txp;
-};
-
-struct bnx2_rv2p_fw_file {
-	struct bnx2_rv2p_fw_file_entry proc1;
-	struct bnx2_rv2p_fw_file_entry proc2;
-};
-
-#define RV2P_P1_FIXUP_PAGE_SIZE_IDX		0
-#define RV2P_BD_PAGE_SIZE_MSK			0xffff
-#define RV2P_BD_PAGE_SIZE			((BCM_PAGE_SIZE / 16) - 1)
-
-#define RV2P_PROC1                              0
-#define RV2P_PROC2                              1
-
-
-/* This value (in milliseconds) determines the frequency of the driver
- * issuing the PULSE message code.  The firmware monitors this periodic
- * pulse to determine when to switch to an OS-absent mode. */
-#define BNX2_DRV_PULSE_PERIOD_MS                 250
-
-/* This value (in milliseconds) determines how long the driver should
- * wait for an acknowledgement from the firmware before timing out.  Once
- * the firmware has timed out, the driver will assume there is no firmware
- * running and there won't be any firmware-driver synchronization during a
- * driver reset. */
-#define BNX2_FW_ACK_TIME_OUT_MS                  1000
-
-
-#define BNX2_DRV_RESET_SIGNATURE		0x00000000
-#define BNX2_DRV_RESET_SIGNATURE_MAGIC		 0x4841564b /* HAVK */
-//#define DRV_RESET_SIGNATURE_MAGIC		 0x47495352 /* RSIG */
-
-#define BNX2_DRV_MB				0x00000004
-#define BNX2_DRV_MSG_CODE			 0xff000000
-#define BNX2_DRV_MSG_CODE_RESET			 0x01000000
-#define BNX2_DRV_MSG_CODE_UNLOAD		 0x02000000
-#define BNX2_DRV_MSG_CODE_SHUTDOWN		 0x03000000
-#define BNX2_DRV_MSG_CODE_SUSPEND_WOL		 0x04000000
-#define BNX2_DRV_MSG_CODE_FW_TIMEOUT		 0x05000000
-#define BNX2_DRV_MSG_CODE_PULSE			 0x06000000
-#define BNX2_DRV_MSG_CODE_DIAG			 0x07000000
-#define BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL	 0x09000000
-#define BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN		 0x0b000000
-#define BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE	 0x0d000000
-#define BNX2_DRV_MSG_CODE_CMD_SET_LINK		 0x10000000
-
-#define BNX2_DRV_MSG_DATA			 0x00ff0000
-#define BNX2_DRV_MSG_DATA_WAIT0			 0x00010000
-#define BNX2_DRV_MSG_DATA_WAIT1			 0x00020000
-#define BNX2_DRV_MSG_DATA_WAIT2			 0x00030000
-#define BNX2_DRV_MSG_DATA_WAIT3			 0x00040000
-
-#define BNX2_DRV_MSG_SEQ			 0x0000ffff
-
-#define BNX2_FW_MB				0x00000008
-#define BNX2_FW_MSG_ACK				 0x0000ffff
-#define BNX2_FW_MSG_STATUS_MASK			 0x00ff0000
-#define BNX2_FW_MSG_STATUS_OK			 0x00000000
-#define BNX2_FW_MSG_STATUS_FAILURE		 0x00ff0000
-
-#define BNX2_LINK_STATUS			0x0000000c
-#define BNX2_LINK_STATUS_INIT_VALUE		 0xffffffff
-#define BNX2_LINK_STATUS_LINK_UP		 0x1
-#define BNX2_LINK_STATUS_LINK_DOWN		 0x0
-#define BNX2_LINK_STATUS_SPEED_MASK		 0x1e
-#define BNX2_LINK_STATUS_AN_INCOMPLETE		 (0<<1)
-#define BNX2_LINK_STATUS_10HALF			 (1<<1)
-#define BNX2_LINK_STATUS_10FULL			 (2<<1)
-#define BNX2_LINK_STATUS_100HALF		 (3<<1)
-#define BNX2_LINK_STATUS_100BASE_T4		 (4<<1)
-#define BNX2_LINK_STATUS_100FULL		 (5<<1)
-#define BNX2_LINK_STATUS_1000HALF		 (6<<1)
-#define BNX2_LINK_STATUS_1000FULL		 (7<<1)
-#define BNX2_LINK_STATUS_2500HALF		 (8<<1)
-#define BNX2_LINK_STATUS_2500FULL		 (9<<1)
-#define BNX2_LINK_STATUS_AN_ENABLED		 (1<<5)
-#define BNX2_LINK_STATUS_AN_COMPLETE		 (1<<6)
-#define BNX2_LINK_STATUS_PARALLEL_DET		 (1<<7)
-#define BNX2_LINK_STATUS_RESERVED		 (1<<8)
-#define BNX2_LINK_STATUS_PARTNER_AD_1000FULL	 (1<<9)
-#define BNX2_LINK_STATUS_PARTNER_AD_1000HALF	 (1<<10)
-#define BNX2_LINK_STATUS_PARTNER_AD_100BT4	 (1<<11)
-#define BNX2_LINK_STATUS_PARTNER_AD_100FULL	 (1<<12)
-#define BNX2_LINK_STATUS_PARTNER_AD_100HALF	 (1<<13)
-#define BNX2_LINK_STATUS_PARTNER_AD_10FULL	 (1<<14)
-#define BNX2_LINK_STATUS_PARTNER_AD_10HALF	 (1<<15)
-#define BNX2_LINK_STATUS_TX_FC_ENABLED		 (1<<16)
-#define BNX2_LINK_STATUS_RX_FC_ENABLED		 (1<<17)
-#define BNX2_LINK_STATUS_PARTNER_SYM_PAUSE_CAP	 (1<<18)
-#define BNX2_LINK_STATUS_PARTNER_ASYM_PAUSE_CAP	 (1<<19)
-#define BNX2_LINK_STATUS_SERDES_LINK		 (1<<20)
-#define BNX2_LINK_STATUS_PARTNER_AD_2500FULL	 (1<<21)
-#define BNX2_LINK_STATUS_PARTNER_AD_2500HALF	 (1<<22)
-#define BNX2_LINK_STATUS_HEART_BEAT_EXPIRED	 (1<<31)
-
-#define BNX2_DRV_PULSE_MB			0x00000010
-#define BNX2_DRV_PULSE_SEQ_MASK			 0x00007fff
-
-/* Indicate to the firmware not to go into the
- * OS absent when it is not getting driver pulse.
- * This is used for debugging. */
-#define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE	 0x00080000
-
-#define BNX2_DRV_MB_ARG0			0x00000014
-#define BNX2_NETLINK_SET_LINK_SPEED_10HALF	 (1<<0)
-#define BNX2_NETLINK_SET_LINK_SPEED_10FULL	 (1<<1)
-#define BNX2_NETLINK_SET_LINK_SPEED_10		 \
-	(BNX2_NETLINK_SET_LINK_SPEED_10HALF |	 \
-	 BNX2_NETLINK_SET_LINK_SPEED_10FULL)
-#define BNX2_NETLINK_SET_LINK_SPEED_100HALF	 (1<<2)
-#define BNX2_NETLINK_SET_LINK_SPEED_100FULL	 (1<<3)
-#define BNX2_NETLINK_SET_LINK_SPEED_100		 \
-	(BNX2_NETLINK_SET_LINK_SPEED_100HALF |	 \
-	 BNX2_NETLINK_SET_LINK_SPEED_100FULL)
-#define BNX2_NETLINK_SET_LINK_SPEED_1GHALF	 (1<<4)
-#define BNX2_NETLINK_SET_LINK_SPEED_1GFULL	 (1<<5)
-#define BNX2_NETLINK_SET_LINK_SPEED_2G5HALF	 (1<<6)
-#define BNX2_NETLINK_SET_LINK_SPEED_2G5FULL	 (1<<7)
-#define BNX2_NETLINK_SET_LINK_SPEED_10GHALF	 (1<<8)
-#define BNX2_NETLINK_SET_LINK_SPEED_10GFULL	 (1<<9)
-#define BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG	 (1<<10)
-#define BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE	 (1<<11)
-#define BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE	 (1<<12)
-#define BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE	 (1<<13)
-#define BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED	 (1<<14)
-#define BNX2_NETLINK_SET_LINK_PHY_RESET		 (1<<15)
-
-#define BNX2_DEV_INFO_SIGNATURE			0x00000020
-#define BNX2_DEV_INFO_SIGNATURE_MAGIC		 0x44564900
-#define BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK	 0xffffff00
-#define BNX2_DEV_INFO_FEATURE_CFG_VALID		 0x01
-#define BNX2_DEV_INFO_SECONDARY_PORT		 0x80
-#define BNX2_DEV_INFO_DRV_ALWAYS_ALIVE		 0x40
-
-#define BNX2_SHARED_HW_CFG_PART_NUM		0x00000024
-
-#define BNX2_SHARED_HW_CFG_POWER_DISSIPATED	0x00000034
-#define BNX2_SHARED_HW_CFG_POWER_STATE_D3_MASK	 0xff000000
-#define BNX2_SHARED_HW_CFG_POWER_STATE_D2_MASK	 0xff0000
-#define BNX2_SHARED_HW_CFG_POWER_STATE_D1_MASK	 0xff00
-#define BNX2_SHARED_HW_CFG_POWER_STATE_D0_MASK	 0xff
-
-#define BNX2_SHARED_HW_CFG POWER_CONSUMED	0x00000038
-#define BNX2_SHARED_HW_CFG_CONFIG		0x0000003c
-#define BNX2_SHARED_HW_CFG_DESIGN_NIC		 0
-#define BNX2_SHARED_HW_CFG_DESIGN_LOM		 0x1
-#define BNX2_SHARED_HW_CFG_PHY_COPPER		 0
-#define BNX2_SHARED_HW_CFG_PHY_FIBER		 0x2
-#define BNX2_SHARED_HW_CFG_PHY_2_5G		 0x20
-#define BNX2_SHARED_HW_CFG_PHY_BACKPLANE	 0x40
-#define BNX2_SHARED_HW_CFG_LED_MODE_SHIFT_BITS	 8
-#define BNX2_SHARED_HW_CFG_LED_MODE_MASK	 0x300
-#define BNX2_SHARED_HW_CFG_LED_MODE_MAC		 0
-#define BNX2_SHARED_HW_CFG_LED_MODE_GPHY1	 0x100
-#define BNX2_SHARED_HW_CFG_LED_MODE_GPHY2	 0x200
-#define BNX2_SHARED_HW_CFG_GIG_LINK_ON_VAUX	 0x8000
-
-#define BNX2_SHARED_HW_CFG_CONFIG2		0x00000040
-#define BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK	 0x00fff000
-
-#define BNX2_DEV_INFO_BC_REV			0x0000004c
-
-#define BNX2_PORT_HW_CFG_MAC_UPPER		0x00000050
-#define BNX2_PORT_HW_CFG_UPPERMAC_MASK		 0xffff
-
-#define BNX2_PORT_HW_CFG_MAC_LOWER		0x00000054
-#define BNX2_PORT_HW_CFG_CONFIG			0x00000058
-#define BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK	 0x0000ffff
-#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK	 0x001f0000
-#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_AN	 0x00000000
-#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G	 0x00030000
-#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_2_5G	 0x00040000
-
-#define BNX2_PORT_HW_CFG_IMD_MAC_A_UPPER	0x00000068
-#define BNX2_PORT_HW_CFG_IMD_MAC_A_LOWER	0x0000006c
-#define BNX2_PORT_HW_CFG_IMD_MAC_B_UPPER	0x00000070
-#define BNX2_PORT_HW_CFG_IMD_MAC_B_LOWER	0x00000074
-#define BNX2_PORT_HW_CFG_ISCSI_MAC_UPPER	0x00000078
-#define BNX2_PORT_HW_CFG_ISCSI_MAC_LOWER	0x0000007c
-
-#define BNX2_DEV_INFO_PER_PORT_HW_CONFIG2	0x000000b4
-
-#define BNX2_DEV_INFO_FORMAT_REV		0x000000c4
-#define BNX2_DEV_INFO_FORMAT_REV_MASK		 0xff000000
-#define BNX2_DEV_INFO_FORMAT_REV_ID		 ('A' << 24)
-
-#define BNX2_SHARED_FEATURE			0x000000c8
-#define BNX2_SHARED_FEATURE_MASK		 0xffffffff
-
-#define BNX2_PORT_FEATURE			0x000000d8
-#define BNX2_PORT2_FEATURE			0x00000014c
-#define BNX2_PORT_FEATURE_WOL_ENABLED		 0x01000000
-#define BNX2_PORT_FEATURE_MBA_ENABLED		 0x02000000
-#define BNX2_PORT_FEATURE_ASF_ENABLED		 0x04000000
-#define BNX2_PORT_FEATURE_IMD_ENABLED		 0x08000000
-#define BNX2_PORT_FEATURE_BAR1_SIZE_MASK	 0xf
-#define BNX2_PORT_FEATURE_BAR1_SIZE_DISABLED	 0x0
-#define BNX2_PORT_FEATURE_BAR1_SIZE_64K		 0x1
-#define BNX2_PORT_FEATURE_BAR1_SIZE_128K	 0x2
-#define BNX2_PORT_FEATURE_BAR1_SIZE_256K	 0x3
-#define BNX2_PORT_FEATURE_BAR1_SIZE_512K	 0x4
-#define BNX2_PORT_FEATURE_BAR1_SIZE_1M		 0x5
-#define BNX2_PORT_FEATURE_BAR1_SIZE_2M		 0x6
-#define BNX2_PORT_FEATURE_BAR1_SIZE_4M		 0x7
-#define BNX2_PORT_FEATURE_BAR1_SIZE_8M		 0x8
-#define BNX2_PORT_FEATURE_BAR1_SIZE_16M		 0x9
-#define BNX2_PORT_FEATURE_BAR1_SIZE_32M		 0xa
-#define BNX2_PORT_FEATURE_BAR1_SIZE_64M		 0xb
-#define BNX2_PORT_FEATURE_BAR1_SIZE_128M	 0xc
-#define BNX2_PORT_FEATURE_BAR1_SIZE_256M	 0xd
-#define BNX2_PORT_FEATURE_BAR1_SIZE_512M	 0xe
-#define BNX2_PORT_FEATURE_BAR1_SIZE_1G		 0xf
-
-#define BNX2_PORT_FEATURE_WOL			0xdc
-#define BNX2_PORT2_FEATURE_WOL			0x150
-#define BNX2_PORT_FEATURE_WOL_DEFAULT_SHIFT_BITS	 4
-#define BNX2_PORT_FEATURE_WOL_DEFAULT_MASK	 0x30
-#define BNX2_PORT_FEATURE_WOL_DEFAULT_DISABLE	 0
-#define BNX2_PORT_FEATURE_WOL_DEFAULT_MAGIC	 0x10
-#define BNX2_PORT_FEATURE_WOL_DEFAULT_ACPI	 0x20
-#define BNX2_PORT_FEATURE_WOL_DEFAULT_MAGIC_AND_ACPI	 0x30
-#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_MASK	 0xf
-#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_AUTONEG	 0
-#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_10HALF	 1
-#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_10FULL	 2
-#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_100HALF 3
-#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_100FULL 4
-#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_1000HALF	 5
-#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_1000FULL	 6
-#define BNX2_PORT_FEATURE_WOL_AUTONEG_ADVERTISE_1000	 0x40
-#define BNX2_PORT_FEATURE_WOL_RESERVED_PAUSE_CAP 0x400
-#define BNX2_PORT_FEATURE_WOL_RESERVED_ASYM_PAUSE_CAP	 0x800
-
-#define BNX2_PORT_FEATURE_MBA			0xe0
-#define BNX2_PORT2_FEATURE_MBA			0x154
-#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_SHIFT_BITS	 0
-#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK	 0x3
-#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_PXE	 0
-#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_RPL	 1
-#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_BOOTP	 2
-#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_SHIFT_BITS	 2
-#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_MASK	 0x3c
-#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_AUTONEG	 0
-#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_10HALF	 0x4
-#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_10FULL	 0x8
-#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_100HALF	 0xc
-#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_100FULL	 0x10
-#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_1000HALF	 0x14
-#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_1000FULL	 0x18
-#define BNX2_PORT_FEATURE_MBA_SETUP_PROMPT_ENABLE	 0x40
-#define BNX2_PORT_FEATURE_MBA_HOTKEY_CTRL_S	 0
-#define BNX2_PORT_FEATURE_MBA_HOTKEY_CTRL_B	 0x80
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_SHIFT_BITS	 8
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_MASK	 0xff00
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_DISABLED	 0
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_1K	 0x100
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_2K	 0x200
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_4K	 0x300
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_8K	 0x400
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_16K	 0x500
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_32K	 0x600
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_64K	 0x700
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_128K	 0x800
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_256K	 0x900
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_512K	 0xa00
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_1M	 0xb00
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_2M	 0xc00
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_4M	 0xd00
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_8M	 0xe00
-#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_16M	 0xf00
-#define BNX2_PORT_FEATURE_MBA_MSG_TIMEOUT_SHIFT_BITS	 16
-#define BNX2_PORT_FEATURE_MBA_MSG_TIMEOUT_MASK	 0xf0000
-#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_SHIFT_BITS	 20
-#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_MASK	 0x300000
-#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_AUTO	 0
-#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_BBS	 0x100000
-#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT18H	 0x200000
-#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT19H	 0x300000
-
-#define BNX2_PORT_FEATURE_IMD			0xe4
-#define BNX2_PORT2_FEATURE_IMD			0x158
-#define BNX2_PORT_FEATURE_IMD_LINK_OVERRIDE_DEFAULT	 0
-#define BNX2_PORT_FEATURE_IMD_LINK_OVERRIDE_ENABLE	 1
-
-#define BNX2_PORT_FEATURE_VLAN			0xe8
-#define BNX2_PORT2_FEATURE_VLAN			0x15c
-#define BNX2_PORT_FEATURE_MBA_VLAN_TAG_MASK	 0xffff
-#define BNX2_PORT_FEATURE_MBA_VLAN_ENABLE	 0x10000
-
-#define BNX2_MFW_VER_PTR			0x00000014c
-
-#define BNX2_BC_STATE_RESET_TYPE		0x000001c0
-#define BNX2_BC_STATE_RESET_TYPE_SIG		 0x00005254
-#define BNX2_BC_STATE_RESET_TYPE_SIG_MASK	 0x0000ffff
-#define BNX2_BC_STATE_RESET_TYPE_NONE	 (BNX2_BC_STATE_RESET_TYPE_SIG | \
-					  0x00010000)
-#define BNX2_BC_STATE_RESET_TYPE_PCI	 (BNX2_BC_STATE_RESET_TYPE_SIG | \
-					  0x00020000)
-#define BNX2_BC_STATE_RESET_TYPE_VAUX	 (BNX2_BC_STATE_RESET_TYPE_SIG | \
-					  0x00030000)
-#define BNX2_BC_STATE_RESET_TYPE_DRV_MASK	 DRV_MSG_CODE
-#define BNX2_BC_STATE_RESET_TYPE_DRV_RESET (BNX2_BC_STATE_RESET_TYPE_SIG | \
-					    DRV_MSG_CODE_RESET)
-#define BNX2_BC_STATE_RESET_TYPE_DRV_UNLOAD (BNX2_BC_STATE_RESET_TYPE_SIG | \
-					     DRV_MSG_CODE_UNLOAD)
-#define BNX2_BC_STATE_RESET_TYPE_DRV_SHUTDOWN (BNX2_BC_STATE_RESET_TYPE_SIG | \
-					       DRV_MSG_CODE_SHUTDOWN)
-#define BNX2_BC_STATE_RESET_TYPE_DRV_WOL (BNX2_BC_STATE_RESET_TYPE_SIG | \
-					  DRV_MSG_CODE_WOL)
-#define BNX2_BC_STATE_RESET_TYPE_DRV_DIAG (BNX2_BC_STATE_RESET_TYPE_SIG | \
-					   DRV_MSG_CODE_DIAG)
-#define BNX2_BC_STATE_RESET_TYPE_VALUE(msg) (BNX2_BC_STATE_RESET_TYPE_SIG | \
-					     (msg))
-
-#define BNX2_BC_STATE				0x000001c4
-#define BNX2_BC_STATE_ERR_MASK			 0x0000ff00
-#define BNX2_BC_STATE_SIGN			 0x42530000
-#define BNX2_BC_STATE_SIGN_MASK			 0xffff0000
-#define BNX2_BC_STATE_BC1_START			 (BNX2_BC_STATE_SIGN | 0x1)
-#define BNX2_BC_STATE_GET_NVM_CFG1		 (BNX2_BC_STATE_SIGN | 0x2)
-#define BNX2_BC_STATE_PROG_BAR			 (BNX2_BC_STATE_SIGN | 0x3)
-#define BNX2_BC_STATE_INIT_VID			 (BNX2_BC_STATE_SIGN | 0x4)
-#define BNX2_BC_STATE_GET_NVM_CFG2		 (BNX2_BC_STATE_SIGN | 0x5)
-#define BNX2_BC_STATE_APPLY_WKARND		 (BNX2_BC_STATE_SIGN | 0x6)
-#define BNX2_BC_STATE_LOAD_BC2			 (BNX2_BC_STATE_SIGN | 0x7)
-#define BNX2_BC_STATE_GOING_BC2			 (BNX2_BC_STATE_SIGN | 0x8)
-#define BNX2_BC_STATE_GOING_DIAG		 (BNX2_BC_STATE_SIGN | 0x9)
-#define BNX2_BC_STATE_RT_FINAL_INIT		 (BNX2_BC_STATE_SIGN | 0x81)
-#define BNX2_BC_STATE_RT_WKARND			 (BNX2_BC_STATE_SIGN | 0x82)
-#define BNX2_BC_STATE_RT_DRV_PULSE		 (BNX2_BC_STATE_SIGN | 0x83)
-#define BNX2_BC_STATE_RT_FIOEVTS		 (BNX2_BC_STATE_SIGN | 0x84)
-#define BNX2_BC_STATE_RT_DRV_CMD		 (BNX2_BC_STATE_SIGN | 0x85)
-#define BNX2_BC_STATE_RT_LOW_POWER		 (BNX2_BC_STATE_SIGN | 0x86)
-#define BNX2_BC_STATE_RT_SET_WOL		 (BNX2_BC_STATE_SIGN | 0x87)
-#define BNX2_BC_STATE_RT_OTHER_FW		 (BNX2_BC_STATE_SIGN | 0x88)
-#define BNX2_BC_STATE_RT_GOING_D3		 (BNX2_BC_STATE_SIGN | 0x89)
-#define BNX2_BC_STATE_ERR_BAD_VERSION		 (BNX2_BC_STATE_SIGN | 0x0100)
-#define BNX2_BC_STATE_ERR_BAD_BC2_CRC		 (BNX2_BC_STATE_SIGN | 0x0200)
-#define BNX2_BC_STATE_ERR_BC1_LOOP		 (BNX2_BC_STATE_SIGN | 0x0300)
-#define BNX2_BC_STATE_ERR_UNKNOWN_CMD		 (BNX2_BC_STATE_SIGN | 0x0400)
-#define BNX2_BC_STATE_ERR_DRV_DEAD		 (BNX2_BC_STATE_SIGN | 0x0500)
-#define BNX2_BC_STATE_ERR_NO_RXP		 (BNX2_BC_STATE_SIGN | 0x0600)
-#define BNX2_BC_STATE_ERR_TOO_MANY_RBUF		 (BNX2_BC_STATE_SIGN | 0x0700)
-
-#define BNX2_BC_STATE_CONDITION			0x000001c8
-#define BNX2_CONDITION_MFW_RUN_UNKNOWN		 0x00000000
-#define BNX2_CONDITION_MFW_RUN_IPMI		 0x00002000
-#define BNX2_CONDITION_MFW_RUN_UMP		 0x00004000
-#define BNX2_CONDITION_MFW_RUN_NCSI		 0x00006000
-#define BNX2_CONDITION_MFW_RUN_NONE		 0x0000e000
-#define BNX2_CONDITION_MFW_RUN_MASK		 0x0000e000
-
-#define BNX2_BC_STATE_DEBUG_CMD			0x1dc
-#define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE	 0x42440000
-#define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE_MASK	 0xffff0000
-#define BNX2_BC_STATE_BC_DBG_CMD_LOOP_CNT_MASK	 0xffff
-#define BNX2_BC_STATE_BC_DBG_CMD_LOOP_INFINITE	 0xffff
-
-#define BNX2_FW_EVT_CODE_MB			0x354
-#define BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT 0x00000000
-#define BNX2_FW_EVT_CODE_LINK_EVENT		 0x00000001
-
-#define BNX2_DRV_ACK_CAP_MB			0x364
-#define BNX2_DRV_ACK_CAP_SIGNATURE		 0x35450000
-#define BNX2_CAPABILITY_SIGNATURE_MASK		 0xFFFF0000
-
-#define BNX2_FW_CAP_MB				0x368
-#define BNX2_FW_CAP_SIGNATURE			 0xaa550000
-#define BNX2_FW_ACK_DRV_SIGNATURE		 0x52500000
-#define BNX2_FW_CAP_SIGNATURE_MASK		 0xffff0000
-#define BNX2_FW_CAP_REMOTE_PHY_CAPABLE		 0x00000001
-#define BNX2_FW_CAP_REMOTE_PHY_PRESENT		 0x00000002
-#define BNX2_FW_CAP_MFW_CAN_KEEP_VLAN		 0x00000008
-#define BNX2_FW_CAP_BC_CAN_KEEP_VLAN		 0x00000010
-#define BNX2_FW_CAP_CAN_KEEP_VLAN	(BNX2_FW_CAP_BC_CAN_KEEP_VLAN | \
-					 BNX2_FW_CAP_MFW_CAN_KEEP_VLAN)
-
-#define BNX2_RPHY_SIGNATURE			0x36c
-#define BNX2_RPHY_LOAD_SIGNATURE		 0x5a5a5a5a
-
-#define BNX2_RPHY_FLAGS				0x370
-#define BNX2_RPHY_SERDES_LINK			0x374
-#define BNX2_RPHY_COPPER_LINK			0x378
-
-#define BNX2_ISCSI_INITIATOR			0x3dc
-#define BNX2_ISCSI_INITIATOR_EN			 0x00080000
-
-#define BNX2_ISCSI_MAX_CONN			0x3e4
-#define BNX2_ISCSI_MAX_CONN_MASK		 0xffff0000
-#define BNX2_ISCSI_MAX_CONN_SHIFT		 16
-
-#define HOST_VIEW_SHMEM_BASE			0x167c00
-
-#define DP_SHMEM_LINE(bp, offset)					\
-	netdev_err(bp->dev, "DEBUG: %08x: %08x %08x %08x %08x\n",	\
-		   offset,						\
-		   bnx2_shmem_rd(bp, offset),				\
-		   bnx2_shmem_rd(bp, offset + 4),			\
-		   bnx2_shmem_rd(bp, offset + 8),			\
-		   bnx2_shmem_rd(bp, offset + 12))
-
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_cmn.c linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_cmn.c
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_cmn.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_cmn.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3593 +0,0 @@
-/* bnx2x_cmn.c: Broadcom Everest network driver.
- *
- * Copyright (c) 2007-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
- * the Free Software Foundation.
- *
- * Maintained by: Eilon Greenstein <eilong@broadcom.com>
- * Written by: Eliezer Tamir
- * Based on code from Michael Chan's bnx2 driver
- * UDP CSUM errata workaround by Arik Gendelman
- * Slowpath and fastpath rework by Vladislav Zolotarov
- * Statistics and Link management by Yitchak Gertner
- *
- */
-
-#include <linux/etherdevice.h>
-#include <linux/if_vlan.h>
-#include <linux/interrupt.h>
-#include <linux/ip.h>
-#include <net/ipv6.h>
-#include <net/ip6_checksum.h>
-#include <linux/firmware.h>
-#include <linux/prefetch.h>
-#include "bnx2x_cmn.h"
-#include "bnx2x_init.h"
-#include "bnx2x_sp.h"
-
-
-
-/**
- * bnx2x_bz_fp - zero content of the fastpath structure.
- *
- * @bp:		driver handle
- * @index:	fastpath index to be zeroed
- *
- * Makes sure the contents of the bp->fp[index].napi is kept
- * intact.
- */
-static inline void bnx2x_bz_fp(struct bnx2x *bp, int index)
-{
-	struct bnx2x_fastpath *fp = &bp->fp[index];
-	struct napi_struct orig_napi = fp->napi;
-	/* bzero bnx2x_fastpath contents */
-	memset(fp, 0, sizeof(*fp));
-
-	/* Restore the NAPI object as it has been already initialized */
-	fp->napi = orig_napi;
-
-	fp->bp = bp;
-	fp->index = index;
-	if (IS_ETH_FP(fp))
-		fp->max_cos = bp->max_cos;
-	else
-		/* Special queues support only one CoS */
-		fp->max_cos = 1;
-
-	/*
-	 * set the tpa flag for each queue. The tpa flag determines the queue
-	 * minimal size so it must be set prior to queue memory allocation
-	 */
-	fp->disable_tpa = ((bp->flags & TPA_ENABLE_FLAG) == 0);
-
-#ifdef BCM_CNIC
-	/* We don't want TPA on an FCoE L2 ring */
-	if (IS_FCOE_FP(fp))
-		fp->disable_tpa = 1;
-#endif
-}
-
-/**
- * bnx2x_move_fp - move content of the fastpath structure.
- *
- * @bp:		driver handle
- * @from:	source FP index
- * @to:		destination FP index
- *
- * Makes sure the contents of the bp->fp[to].napi is kept
- * intact.
- */
-static inline void bnx2x_move_fp(struct bnx2x *bp, int from, int to)
-{
-	struct bnx2x_fastpath *from_fp = &bp->fp[from];
-	struct bnx2x_fastpath *to_fp = &bp->fp[to];
-	struct napi_struct orig_napi = to_fp->napi;
-	/* Move bnx2x_fastpath contents */
-	memcpy(to_fp, from_fp, sizeof(*to_fp));
-	to_fp->index = to;
-
-	/* Restore the NAPI object as it has been already initialized */
-	to_fp->napi = orig_napi;
-}
-
-int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */
-
-/* free skb in the packet ring at pos idx
- * return idx of last bd freed
- */
-static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
-			     u16 idx)
-{
-	struct sw_tx_bd *tx_buf = &txdata->tx_buf_ring[idx];
-	struct eth_tx_start_bd *tx_start_bd;
-	struct eth_tx_bd *tx_data_bd;
-	struct sk_buff *skb = tx_buf->skb;
-	u16 bd_idx = TX_BD(tx_buf->first_bd), new_cons;
-	int nbd;
-
-	/* prefetch skb end pointer to speedup dev_kfree_skb() */
-	prefetch(&skb->end);
-
-	DP(BNX2X_MSG_FP, "fp[%d]: pkt_idx %d  buff @(%p)->skb %p\n",
-	   txdata->txq_index, idx, tx_buf, skb);
-
-	/* unmap first bd */
-	DP(BNX2X_MSG_OFF, "free bd_idx %d\n", bd_idx);
-	tx_start_bd = &txdata->tx_desc_ring[bd_idx].start_bd;
-	dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd),
-			 BD_UNMAP_LEN(tx_start_bd), DMA_TO_DEVICE);
-
-
-	nbd = le16_to_cpu(tx_start_bd->nbd) - 1;
-#ifdef BNX2X_STOP_ON_ERROR
-	if ((nbd - 1) > (MAX_SKB_FRAGS + 2)) {
-		BNX2X_ERR("BAD nbd!\n");
-		bnx2x_panic();
-	}
-#endif
-	new_cons = nbd + tx_buf->first_bd;
-
-	/* Get the next bd */
-	bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
-
-	/* Skip a parse bd... */
-	--nbd;
-	bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
-
-	/* ...and the TSO split header bd since they have no mapping */
-	if (tx_buf->flags & BNX2X_TSO_SPLIT_BD) {
-		--nbd;
-		bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
-	}
-
-	/* now free frags */
-	while (nbd > 0) {
-
-		DP(BNX2X_MSG_OFF, "free frag bd_idx %d\n", bd_idx);
-		tx_data_bd = &txdata->tx_desc_ring[bd_idx].reg_bd;
-		dma_unmap_page(&bp->pdev->dev, BD_UNMAP_ADDR(tx_data_bd),
-			       BD_UNMAP_LEN(tx_data_bd), DMA_TO_DEVICE);
-		if (--nbd)
-			bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
-	}
-
-	/* release skb */
-	WARN_ON(!skb);
-	dev_kfree_skb_any(skb);
-	tx_buf->first_bd = 0;
-	tx_buf->skb = NULL;
-
-	return new_cons;
-}
-
-int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata)
-{
-	struct netdev_queue *txq;
-	u16 hw_cons, sw_cons, bd_cons = txdata->tx_bd_cons;
-
-#ifdef BNX2X_STOP_ON_ERROR
-	if (unlikely(bp->panic))
-		return -1;
-#endif
-
-	txq = netdev_get_tx_queue(bp->dev, txdata->txq_index);
-	hw_cons = le16_to_cpu(*txdata->tx_cons_sb);
-	sw_cons = txdata->tx_pkt_cons;
-
-	while (sw_cons != hw_cons) {
-		u16 pkt_cons;
-
-		pkt_cons = TX_BD(sw_cons);
-
-		DP(NETIF_MSG_TX_DONE, "queue[%d]: hw_cons %u  sw_cons %u "
-				      " pkt_cons %u\n",
-		   txdata->txq_index, hw_cons, sw_cons, pkt_cons);
-
-		bd_cons = bnx2x_free_tx_pkt(bp, txdata, pkt_cons);
-		sw_cons++;
-	}
-
-	txdata->tx_pkt_cons = sw_cons;
-	txdata->tx_bd_cons = bd_cons;
-
-	/* Need to make the tx_bd_cons update visible to start_xmit()
-	 * before checking for netif_tx_queue_stopped().  Without the
-	 * memory barrier, there is a small possibility that
-	 * start_xmit() will miss it and cause the queue to be stopped
-	 * forever.
-	 * On the other hand we need an rmb() here to ensure the proper
-	 * ordering of bit testing in the following
-	 * netif_tx_queue_stopped(txq) call.
-	 */
-	smp_mb();
-
-	if (unlikely(netif_tx_queue_stopped(txq))) {
-		/* Taking tx_lock() is needed to prevent reenabling the queue
-		 * while it's empty. This could have happen if rx_action() gets
-		 * suspended in bnx2x_tx_int() after the condition before
-		 * netif_tx_wake_queue(), while tx_action (bnx2x_start_xmit()):
-		 *
-		 * stops the queue->sees fresh tx_bd_cons->releases the queue->
-		 * sends some packets consuming the whole queue again->
-		 * stops the queue
-		 */
-
-		__netif_tx_lock(txq, smp_processor_id());
-
-		if ((netif_tx_queue_stopped(txq)) &&
-		    (bp->state == BNX2X_STATE_OPEN) &&
-		    (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 3))
-			netif_tx_wake_queue(txq);
-
-		__netif_tx_unlock(txq);
-	}
-	return 0;
-}
-
-static inline void bnx2x_update_last_max_sge(struct bnx2x_fastpath *fp,
-					     u16 idx)
-{
-	u16 last_max = fp->last_max_sge;
-
-	if (SUB_S16(idx, last_max) > 0)
-		fp->last_max_sge = idx;
-}
-
-static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp,
-				  struct eth_fast_path_rx_cqe *fp_cqe)
-{
-	struct bnx2x *bp = fp->bp;
-	u16 sge_len = SGE_PAGE_ALIGN(le16_to_cpu(fp_cqe->pkt_len) -
-				     le16_to_cpu(fp_cqe->len_on_bd)) >>
-		      SGE_PAGE_SHIFT;
-	u16 last_max, last_elem, first_elem;
-	u16 delta = 0;
-	u16 i;
-
-	if (!sge_len)
-		return;
-
-	/* First mark all used pages */
-	for (i = 0; i < sge_len; i++)
-		BIT_VEC64_CLEAR_BIT(fp->sge_mask,
-			RX_SGE(le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[i])));
-
-	DP(NETIF_MSG_RX_STATUS, "fp_cqe->sgl[%d] = %d\n",
-	   sge_len - 1, le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[sge_len - 1]));
-
-	/* Here we assume that the last SGE index is the biggest */
-	prefetch((void *)(fp->sge_mask));
-	bnx2x_update_last_max_sge(fp,
-		le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[sge_len - 1]));
-
-	last_max = RX_SGE(fp->last_max_sge);
-	last_elem = last_max >> BIT_VEC64_ELEM_SHIFT;
-	first_elem = RX_SGE(fp->rx_sge_prod) >> BIT_VEC64_ELEM_SHIFT;
-
-	/* If ring is not full */
-	if (last_elem + 1 != first_elem)
-		last_elem++;
-
-	/* Now update the prod */
-	for (i = first_elem; i != last_elem; i = NEXT_SGE_MASK_ELEM(i)) {
-		if (likely(fp->sge_mask[i]))
-			break;
-
-		fp->sge_mask[i] = BIT_VEC64_ELEM_ONE_MASK;
-		delta += BIT_VEC64_ELEM_SZ;
-	}
-
-	if (delta > 0) {
-		fp->rx_sge_prod += delta;
-		/* clear page-end entries */
-		bnx2x_clear_sge_mask_next_elems(fp);
-	}
-
-	DP(NETIF_MSG_RX_STATUS,
-	   "fp->last_max_sge = %d  fp->rx_sge_prod = %d\n",
-	   fp->last_max_sge, fp->rx_sge_prod);
-}
-
-static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue,
-			    struct sk_buff *skb, u16 cons, u16 prod,
-			    struct eth_fast_path_rx_cqe *cqe)
-{
-	struct bnx2x *bp = fp->bp;
-	struct sw_rx_bd *cons_rx_buf = &fp->rx_buf_ring[cons];
-	struct sw_rx_bd *prod_rx_buf = &fp->rx_buf_ring[prod];
-	struct eth_rx_bd *prod_bd = &fp->rx_desc_ring[prod];
-	dma_addr_t mapping;
-	struct bnx2x_agg_info *tpa_info = &fp->tpa_info[queue];
-	struct sw_rx_bd *first_buf = &tpa_info->first_buf;
-
-	/* print error if current state != stop */
-	if (tpa_info->tpa_state != BNX2X_TPA_STOP)
-		BNX2X_ERR("start of bin not in stop [%d]\n", queue);
-
-	/* Try to map an empty skb from the aggregation info  */
-	mapping = dma_map_single(&bp->pdev->dev,
-				 first_buf->skb->data,
-				 fp->rx_buf_size, DMA_FROM_DEVICE);
-	/*
-	 *  ...if it fails - move the skb from the consumer to the producer
-	 *  and set the current aggregation state as ERROR to drop it
-	 *  when TPA_STOP arrives.
-	 */
-
-	if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
-		/* Move the BD from the consumer to the producer */
-		bnx2x_reuse_rx_skb(fp, cons, prod);
-		tpa_info->tpa_state = BNX2X_TPA_ERROR;
-		return;
-	}
-
-	/* move empty skb from pool to prod */
-	prod_rx_buf->skb = first_buf->skb;
-	dma_unmap_addr_set(prod_rx_buf, mapping, mapping);
-	/* point prod_bd to new skb */
-	prod_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
-	prod_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
-
-	/* move partial skb from cons to pool (don't unmap yet) */
-	*first_buf = *cons_rx_buf;
-
-	/* mark bin state as START */
-	tpa_info->parsing_flags =
-		le16_to_cpu(cqe->pars_flags.flags);
-	tpa_info->vlan_tag = le16_to_cpu(cqe->vlan_tag);
-	tpa_info->tpa_state = BNX2X_TPA_START;
-	tpa_info->len_on_bd = le16_to_cpu(cqe->len_on_bd);
-	tpa_info->placement_offset = cqe->placement_offset;
-
-#ifdef BNX2X_STOP_ON_ERROR
-	fp->tpa_queue_used |= (1 << queue);
-#ifdef _ASM_GENERIC_INT_L64_H
-	DP(NETIF_MSG_RX_STATUS, "fp->tpa_queue_used = 0x%lx\n",
-#else
-	DP(NETIF_MSG_RX_STATUS, "fp->tpa_queue_used = 0x%llx\n",
-#endif
-	   fp->tpa_queue_used);
-#endif
-}
-
-/* Timestamp option length allowed for TPA aggregation:
- *
- *		nop nop kind length echo val
- */
-#define TPA_TSTAMP_OPT_LEN	12
-/**
- * bnx2x_set_lro_mss - calculate the approximate value of the MSS
- *
- * @bp:			driver handle
- * @parsing_flags:	parsing flags from the START CQE
- * @len_on_bd:		total length of the first packet for the
- *			aggregation.
- *
- * Approximate value of the MSS for this aggregation calculated using
- * the first packet of it.
- */
-static inline u16 bnx2x_set_lro_mss(struct bnx2x *bp, u16 parsing_flags,
-				    u16 len_on_bd)
-{
-	/*
-	 * TPA arrgregation won't have either IP options or TCP options
-	 * other than timestamp or IPv6 extension headers.
-	 */
-	u16 hdrs_len = ETH_HLEN + sizeof(struct tcphdr);
-
-	if (GET_FLAG(parsing_flags, PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) ==
-	    PRS_FLAG_OVERETH_IPV6)
-		hdrs_len += sizeof(struct ipv6hdr);
-	else /* IPv4 */
-		hdrs_len += sizeof(struct iphdr);
-
-
-	/* Check if there was a TCP timestamp, if there is it's will
-	 * always be 12 bytes length: nop nop kind length echo val.
-	 *
-	 * Otherwise FW would close the aggregation.
-	 */
-	if (parsing_flags & PARSING_FLAGS_TIME_STAMP_EXIST_FLAG)
-		hdrs_len += TPA_TSTAMP_OPT_LEN;
-
-	return len_on_bd - hdrs_len;
-}
-
-static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
-			       u16 queue, struct sk_buff *skb,
-			       struct eth_end_agg_rx_cqe *cqe,
-			       u16 cqe_idx)
-{
-	struct sw_rx_page *rx_pg, old_rx_pg;
-	u32 i, frag_len, frag_size, pages;
-	int err;
-	int j;
-	struct bnx2x_agg_info *tpa_info = &fp->tpa_info[queue];
-	u16 len_on_bd = tpa_info->len_on_bd;
-
-	frag_size = le16_to_cpu(cqe->pkt_len) - len_on_bd;
-	pages = SGE_PAGE_ALIGN(frag_size) >> SGE_PAGE_SHIFT;
-
-	/* This is needed in order to enable forwarding support */
-	if (frag_size)
-		skb_shinfo(skb)->gso_size = bnx2x_set_lro_mss(bp,
-					tpa_info->parsing_flags, len_on_bd);
-
-#ifdef BNX2X_STOP_ON_ERROR
-	if (pages > min_t(u32, 8, MAX_SKB_FRAGS)*SGE_PAGE_SIZE*PAGES_PER_SGE) {
-		BNX2X_ERR("SGL length is too long: %d. CQE index is %d\n",
-			  pages, cqe_idx);
-		BNX2X_ERR("cqe->pkt_len = %d\n", cqe->pkt_len);
-		bnx2x_panic();
-		return -EINVAL;
-	}
-#endif
-
-	/* Run through the SGL and compose the fragmented skb */
-	for (i = 0, j = 0; i < pages; i += PAGES_PER_SGE, j++) {
-		u16 sge_idx = RX_SGE(le16_to_cpu(cqe->sgl_or_raw_data.sgl[j]));
-
-		/* FW gives the indices of the SGE as if the ring is an array
-		   (meaning that "next" element will consume 2 indices) */
-		frag_len = min(frag_size, (u32)(SGE_PAGE_SIZE*PAGES_PER_SGE));
-		rx_pg = &fp->rx_page_ring[sge_idx];
-		old_rx_pg = *rx_pg;
-
-		/* If we fail to allocate a substitute page, we simply stop
-		   where we are and drop the whole packet */
-		err = bnx2x_alloc_rx_sge(bp, fp, sge_idx);
-		if (unlikely(err)) {
-			fp->eth_q_stats.rx_skb_alloc_failed++;
-			return err;
-		}
-
-		/* Unmap the page as we r going to pass it to the stack */
-		dma_unmap_page(&bp->pdev->dev,
-			       dma_unmap_addr(&old_rx_pg, mapping),
-			       SGE_PAGE_SIZE*PAGES_PER_SGE, DMA_FROM_DEVICE);
-
-		/* Add one frag and update the appropriate fields in the skb */
-		skb_fill_page_desc(skb, j, old_rx_pg.page, 0, frag_len);
-
-		skb->data_len += frag_len;
-		skb->truesize += frag_len;
-		skb->len += frag_len;
-
-		frag_size -= frag_len;
-	}
-
-	return 0;
-}
-
-static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
-			   u16 queue, struct eth_end_agg_rx_cqe *cqe,
-			   u16 cqe_idx)
-{
-	struct bnx2x_agg_info *tpa_info = &fp->tpa_info[queue];
-	struct sw_rx_bd *rx_buf = &tpa_info->first_buf;
-	u8 pad = tpa_info->placement_offset;
-	u16 len = tpa_info->len_on_bd;
-	struct sk_buff *skb = rx_buf->skb;
-	/* alloc new skb */
-	struct sk_buff *new_skb;
-	u8 old_tpa_state = tpa_info->tpa_state;
-
-	tpa_info->tpa_state = BNX2X_TPA_STOP;
-
-	/* If we there was an error during the handling of the TPA_START -
-	 * drop this aggregation.
-	 */
-	if (old_tpa_state == BNX2X_TPA_ERROR)
-		goto drop;
-
-	/* Try to allocate the new skb */
-	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),
-			 fp->rx_buf_size, DMA_FROM_DEVICE);
-
-	if (likely(new_skb)) {
-		prefetch(skb);
-		prefetch(((char *)(skb)) + L1_CACHE_BYTES);
-
-#ifdef BNX2X_STOP_ON_ERROR
-		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, fp->rx_buf_size);
-			bnx2x_panic();
-			return;
-		}
-#endif
-
-		skb_reserve(skb, pad);
-		skb_put(skb, len);
-
-		skb->protocol = eth_type_trans(skb, bp->dev);
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-
-		if (!bnx2x_fill_frag_skb(bp, fp, queue, skb, cqe, cqe_idx)) {
-			if (tpa_info->parsing_flags & PARSING_FLAGS_VLAN)
-				__vlan_hwaccel_put_tag(skb, tpa_info->vlan_tag);
-			napi_gro_receive(&fp->napi, skb);
-		} else {
-			DP(NETIF_MSG_RX_STATUS, "Failed to allocate new pages"
-			   " - dropping packet!\n");
-			dev_kfree_skb_any(skb);
-		}
-
-
-		/* put new skb in bin */
-		rx_buf->skb = new_skb;
-
-		return;
-	}
-
-drop:
-	/* drop the packet and keep the buffer in the bin */
-	DP(NETIF_MSG_RX_STATUS,
-	   "Failed to allocate or map a new skb - dropping packet!\n");
-	fp->eth_q_stats.rx_skb_alloc_failed++;
-}
-
-/* Set Toeplitz hash value in the skb using the value from the
- * CQE (calculated by HW).
- */
-static inline void bnx2x_set_skb_rxhash(struct bnx2x *bp, union eth_rx_cqe *cqe,
-					struct sk_buff *skb)
-{
-	/* Set Toeplitz hash from CQE */
-	if ((bp->dev->features & NETIF_F_RXHASH) &&
-	    (cqe->fast_path_cqe.status_flags &
-	     ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG))
-		skb->rxhash =
-		le32_to_cpu(cqe->fast_path_cqe.rss_hash_result);
-}
-
-int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
-{
-	struct bnx2x *bp = fp->bp;
-	u16 bd_cons, bd_prod, bd_prod_fw, comp_ring_cons;
-	u16 hw_comp_cons, sw_comp_cons, sw_comp_prod;
-	int rx_pkt = 0;
-
-#ifdef BNX2X_STOP_ON_ERROR
-	if (unlikely(bp->panic))
-		return 0;
-#endif
-
-	/* CQ "next element" is of the size of the regular element,
-	   that's why it's ok here */
-	hw_comp_cons = le16_to_cpu(*fp->rx_cons_sb);
-	if ((hw_comp_cons & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
-		hw_comp_cons++;
-
-	bd_cons = fp->rx_bd_cons;
-	bd_prod = fp->rx_bd_prod;
-	bd_prod_fw = bd_prod;
-	sw_comp_cons = fp->rx_comp_cons;
-	sw_comp_prod = fp->rx_comp_prod;
-
-	/* Memory barrier necessary as speculative reads of the rx
-	 * buffer can be ahead of the index in the status block
-	 */
-	rmb();
-
-	DP(NETIF_MSG_RX_STATUS,
-	   "queue[%d]:  hw_comp_cons %u  sw_comp_cons %u\n",
-	   fp->index, hw_comp_cons, sw_comp_cons);
-
-	while (sw_comp_cons != hw_comp_cons) {
-		struct sw_rx_bd *rx_buf = NULL;
-		struct sk_buff *skb;
-		union eth_rx_cqe *cqe;
-		struct eth_fast_path_rx_cqe *cqe_fp;
-		u8 cqe_fp_flags;
-		enum eth_rx_cqe_type cqe_fp_type;
-		u16 len, pad;
-
-#ifdef BNX2X_STOP_ON_ERROR
-		if (unlikely(bp->panic))
-			return 0;
-#endif
-
-		comp_ring_cons = RCQ_BD(sw_comp_cons);
-		bd_prod = RX_BD(bd_prod);
-		bd_cons = RX_BD(bd_cons);
-
-		/* Prefetch the page containing the BD descriptor
-		   at producer's index. It will be needed when new skb is
-		   allocated */
-		prefetch((void *)(PAGE_ALIGN((unsigned long)
-					     (&fp->rx_desc_ring[bd_prod])) -
-				  PAGE_SIZE + 1));
-
-		cqe = &fp->rx_comp_ring[comp_ring_cons];
-		cqe_fp = &cqe->fast_path_cqe;
-		cqe_fp_flags = cqe_fp->type_error_flags;
-		cqe_fp_type = cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE;
-
-		DP(NETIF_MSG_RX_STATUS, "CQE type %x  err %x  status %x"
-		   "  queue %x  vlan %x  len %u\n", CQE_TYPE(cqe_fp_flags),
-		   cqe_fp_flags, cqe_fp->status_flags,
-		   le32_to_cpu(cqe_fp->rss_hash_result),
-		   le16_to_cpu(cqe_fp->vlan_tag), le16_to_cpu(cqe_fp->pkt_len));
-
-		/* is this a slowpath msg? */
-		if (unlikely(CQE_TYPE_SLOW(cqe_fp_type))) {
-			bnx2x_sp_event(fp, cqe);
-			goto next_cqe;
-
-		/* this is an rx packet */
-		} else {
-			rx_buf = &fp->rx_buf_ring[bd_cons];
-			skb = rx_buf->skb;
-			prefetch(skb);
-
-			if (!CQE_TYPE_FAST(cqe_fp_type)) {
-#ifdef BNX2X_STOP_ON_ERROR
-				/* sanity check */
-				if (fp->disable_tpa &&
-				    (CQE_TYPE_START(cqe_fp_type) ||
-				     CQE_TYPE_STOP(cqe_fp_type)))
-					BNX2X_ERR("START/STOP packet while "
-						  "disable_tpa type %x\n",
-						  CQE_TYPE(cqe_fp_type));
-#endif
-
-				if (CQE_TYPE_START(cqe_fp_type)) {
-					u16 queue = cqe_fp->queue_index;
-					DP(NETIF_MSG_RX_STATUS,
-					   "calling tpa_start on queue %d\n",
-					   queue);
-
-					bnx2x_tpa_start(fp, queue, skb,
-							bd_cons, bd_prod,
-							cqe_fp);
-
-					/* Set Toeplitz hash for LRO skb */
-					bnx2x_set_skb_rxhash(bp, cqe, skb);
-
-					goto next_rx;
-
-				} else {
-					u16 queue =
-						cqe->end_agg_cqe.queue_index;
-					DP(NETIF_MSG_RX_STATUS,
-					   "calling tpa_stop on queue %d\n",
-					   queue);
-
-					bnx2x_tpa_stop(bp, fp, queue,
-						       &cqe->end_agg_cqe,
-						       comp_ring_cons);
-#ifdef BNX2X_STOP_ON_ERROR
-					if (bp->panic)
-						return 0;
-#endif
-
-					bnx2x_update_sge_prod(fp, cqe_fp);
-					goto next_cqe;
-				}
-			}
-			/* non TPA */
-			len = le16_to_cpu(cqe_fp->pkt_len);
-			pad = cqe_fp->placement_offset;
-			dma_sync_single_for_cpu(&bp->pdev->dev,
-					dma_unmap_addr(rx_buf, mapping),
-						       pad + RX_COPY_THRESH,
-						       DMA_FROM_DEVICE);
-			prefetch(((char *)(skb)) + L1_CACHE_BYTES);
-
-			/* is this an error packet? */
-			if (unlikely(cqe_fp_flags & ETH_RX_ERROR_FALGS)) {
-				DP(NETIF_MSG_RX_ERR,
-				   "ERROR  flags %x  rx packet %u\n",
-				   cqe_fp_flags, sw_comp_cons);
-				fp->eth_q_stats.rx_err_discard_pkt++;
-				goto reuse_rx;
-			}
-
-			/* Since we don't have a jumbo ring
-			 * copy small packets if mtu > 1500
-			 */
-			if ((bp->dev->mtu > ETH_MAX_PACKET_SIZE) &&
-			    (len <= RX_COPY_THRESH)) {
-				struct sk_buff *new_skb;
-
-				new_skb = netdev_alloc_skb(bp->dev, len + pad);
-				if (new_skb == NULL) {
-					DP(NETIF_MSG_RX_ERR,
-					   "ERROR  packet dropped "
-					   "because of alloc failure\n");
-					fp->eth_q_stats.rx_skb_alloc_failed++;
-					goto reuse_rx;
-				}
-
-				/* aligned copy */
-				skb_copy_from_linear_data_offset(skb, pad,
-						    new_skb->data + pad, len);
-				skb_reserve(new_skb, pad);
-				skb_put(new_skb, len);
-
-				bnx2x_reuse_rx_skb(fp, bd_cons, bd_prod);
-
-				skb = new_skb;
-
-			} else
-			if (likely(bnx2x_alloc_rx_skb(bp, fp, bd_prod) == 0)) {
-				dma_unmap_single(&bp->pdev->dev,
-					dma_unmap_addr(rx_buf, mapping),
-						 fp->rx_buf_size,
-						 DMA_FROM_DEVICE);
-				skb_reserve(skb, pad);
-				skb_put(skb, len);
-
-			} else {
-				DP(NETIF_MSG_RX_ERR,
-				   "ERROR  packet dropped because "
-				   "of alloc failure\n");
-				fp->eth_q_stats.rx_skb_alloc_failed++;
-reuse_rx:
-				bnx2x_reuse_rx_skb(fp, bd_cons, bd_prod);
-				goto next_rx;
-			}
-
-			skb->protocol = eth_type_trans(skb, bp->dev);
-
-			/* Set Toeplitz hash for a none-LRO skb */
-			bnx2x_set_skb_rxhash(bp, cqe, skb);
-
-			skb_checksum_none_assert(skb);
-
-			if (bp->dev->features & NETIF_F_RXCSUM) {
-
-				if (likely(BNX2X_RX_CSUM_OK(cqe)))
-					skb->ip_summed = CHECKSUM_UNNECESSARY;
-				else
-					fp->eth_q_stats.hw_csum_err++;
-			}
-		}
-
-		skb_record_rx_queue(skb, fp->index);
-
-		if (le16_to_cpu(cqe_fp->pars_flags.flags) &
-		    PARSING_FLAGS_VLAN)
-			__vlan_hwaccel_put_tag(skb,
-					       le16_to_cpu(cqe_fp->vlan_tag));
-		napi_gro_receive(&fp->napi, skb);
-
-
-next_rx:
-		rx_buf->skb = NULL;
-
-		bd_cons = NEXT_RX_IDX(bd_cons);
-		bd_prod = NEXT_RX_IDX(bd_prod);
-		bd_prod_fw = NEXT_RX_IDX(bd_prod_fw);
-		rx_pkt++;
-next_cqe:
-		sw_comp_prod = NEXT_RCQ_IDX(sw_comp_prod);
-		sw_comp_cons = NEXT_RCQ_IDX(sw_comp_cons);
-
-		if (rx_pkt == budget)
-			break;
-	} /* while */
-
-	fp->rx_bd_cons = bd_cons;
-	fp->rx_bd_prod = bd_prod_fw;
-	fp->rx_comp_cons = sw_comp_cons;
-	fp->rx_comp_prod = sw_comp_prod;
-
-	/* Update producers */
-	bnx2x_update_rx_prod(bp, fp, bd_prod_fw, sw_comp_prod,
-			     fp->rx_sge_prod);
-
-	fp->rx_pkt += rx_pkt;
-	fp->rx_calls++;
-
-	return rx_pkt;
-}
-
-static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
-{
-	struct bnx2x_fastpath *fp = fp_cookie;
-	struct bnx2x *bp = fp->bp;
-	u8 cos;
-
-	DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB "
-			 "[fp %d fw_sd %d igusb %d]\n",
-	   fp->index, fp->fw_sb_id, fp->igu_sb_id);
-	bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, 0, IGU_INT_DISABLE, 0);
-
-#ifdef BNX2X_STOP_ON_ERROR
-	if (unlikely(bp->panic))
-		return IRQ_HANDLED;
-#endif
-
-	/* Handle Rx and Tx according to MSI-X vector */
-	prefetch(fp->rx_cons_sb);
-
-	for_each_cos_in_tx_queue(fp, cos)
-		prefetch(fp->txdata[cos].tx_cons_sb);
-
-	prefetch(&fp->sb_running_index[SM_RX_ID]);
-	napi_schedule(&bnx2x_fp(bp, fp->index, napi));
-
-	return IRQ_HANDLED;
-}
-
-/* HW Lock for shared dual port PHYs */
-void bnx2x_acquire_phy_lock(struct bnx2x *bp)
-{
-	mutex_lock(&bp->port.phy_mutex);
-
-	if (bp->port.need_hw_lock)
-		bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_MDIO);
-}
-
-void bnx2x_release_phy_lock(struct bnx2x *bp)
-{
-	if (bp->port.need_hw_lock)
-		bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_MDIO);
-
-	mutex_unlock(&bp->port.phy_mutex);
-}
-
-/* calculates MF speed according to current linespeed and MF configuration */
-u16 bnx2x_get_mf_speed(struct bnx2x *bp)
-{
-	u16 line_speed = bp->link_vars.line_speed;
-	if (IS_MF(bp)) {
-		u16 maxCfg = bnx2x_extract_max_cfg(bp,
-						   bp->mf_config[BP_VN(bp)]);
-
-		/* Calculate the current MAX line speed limit for the MF
-		 * devices
-		 */
-		if (IS_MF_SI(bp))
-			line_speed = (line_speed * maxCfg) / 100;
-		else { /* SD mode */
-			u16 vn_max_rate = maxCfg * 100;
-
-			if (vn_max_rate < line_speed)
-				line_speed = vn_max_rate;
-		}
-	}
-
-	return line_speed;
-}
-
-/**
- * bnx2x_fill_report_data - fill link report data to report
- *
- * @bp:		driver handle
- * @data:	link state to update
- *
- * It uses a none-atomic bit operations because is called under the mutex.
- */
-static inline void bnx2x_fill_report_data(struct bnx2x *bp,
-					  struct bnx2x_link_report_data *data)
-{
-	u16 line_speed = bnx2x_get_mf_speed(bp);
-
-	memset(data, 0, sizeof(*data));
-
-	/* Fill the report data: efective line speed */
-	data->line_speed = line_speed;
-
-	/* Link is down */
-	if (!bp->link_vars.link_up || (bp->flags & MF_FUNC_DIS))
-		__set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
-			  &data->link_report_flags);
-
-	/* Full DUPLEX */
-	if (bp->link_vars.duplex == DUPLEX_FULL)
-		__set_bit(BNX2X_LINK_REPORT_FD, &data->link_report_flags);
-
-	/* Rx Flow Control is ON */
-	if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX)
-		__set_bit(BNX2X_LINK_REPORT_RX_FC_ON, &data->link_report_flags);
-
-	/* Tx Flow Control is ON */
-	if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
-		__set_bit(BNX2X_LINK_REPORT_TX_FC_ON, &data->link_report_flags);
-}
-
-/**
- * bnx2x_link_report - report link status to OS.
- *
- * @bp:		driver handle
- *
- * Calls the __bnx2x_link_report() under the same locking scheme
- * as a link/PHY state managing code to ensure a consistent link
- * reporting.
- */
-
-void bnx2x_link_report(struct bnx2x *bp)
-{
-	bnx2x_acquire_phy_lock(bp);
-	__bnx2x_link_report(bp);
-	bnx2x_release_phy_lock(bp);
-}
-
-/**
- * __bnx2x_link_report - report link status to OS.
- *
- * @bp:		driver handle
- *
- * None atomic inmlementation.
- * Should be called under the phy_lock.
- */
-void __bnx2x_link_report(struct bnx2x *bp)
-{
-	struct bnx2x_link_report_data cur_data;
-
-	/* reread mf_cfg */
-	if (!CHIP_IS_E1(bp))
-		bnx2x_read_mf_cfg(bp);
-
-	/* Read the current link report info */
-	bnx2x_fill_report_data(bp, &cur_data);
-
-	/* Don't report link down or exactly the same link status twice */
-	if (!memcmp(&cur_data, &bp->last_reported_link, sizeof(cur_data)) ||
-	    (test_bit(BNX2X_LINK_REPORT_LINK_DOWN,
-		      &bp->last_reported_link.link_report_flags) &&
-	     test_bit(BNX2X_LINK_REPORT_LINK_DOWN,
-		      &cur_data.link_report_flags)))
-		return;
-
-	bp->link_cnt++;
-
-	/* We are going to report a new link parameters now -
-	 * remember the current data for the next time.
-	 */
-	memcpy(&bp->last_reported_link, &cur_data, sizeof(cur_data));
-
-	if (test_bit(BNX2X_LINK_REPORT_LINK_DOWN,
-		     &cur_data.link_report_flags)) {
-		netif_carrier_off(bp->dev);
-		netdev_err(bp->dev, "NIC Link is Down\n");
-		return;
-	} else {
-		netif_carrier_on(bp->dev);
-		netdev_info(bp->dev, "NIC Link is Up, ");
-		pr_cont("%d Mbps ", cur_data.line_speed);
-
-		if (test_and_clear_bit(BNX2X_LINK_REPORT_FD,
-				       &cur_data.link_report_flags))
-			pr_cont("full duplex");
-		else
-			pr_cont("half duplex");
-
-		/* Handle the FC at the end so that only these flags would be
-		 * possibly set. This way we may easily check if there is no FC
-		 * enabled.
-		 */
-		if (cur_data.link_report_flags) {
-			if (test_bit(BNX2X_LINK_REPORT_RX_FC_ON,
-				     &cur_data.link_report_flags)) {
-				pr_cont(", receive ");
-				if (test_bit(BNX2X_LINK_REPORT_TX_FC_ON,
-				     &cur_data.link_report_flags))
-					pr_cont("& transmit ");
-			} else {
-				pr_cont(", transmit ");
-			}
-			pr_cont("flow control ON");
-		}
-		pr_cont("\n");
-	}
-}
-
-void bnx2x_init_rx_rings(struct bnx2x *bp)
-{
-	int func = BP_FUNC(bp);
-	u16 ring_prod;
-	int i, j;
-
-	/* Allocate TPA resources */
-	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) {
-			/* Fill the per-aggregtion pool */
-			for (i = 0; i < MAX_AGG_QS(bp); i++) {
-				struct bnx2x_agg_info *tpa_info =
-					&fp->tpa_info[i];
-				struct sw_rx_bd *first_buf =
-					&tpa_info->first_buf;
-
-				first_buf->skb = netdev_alloc_skb(bp->dev,
-						       fp->rx_buf_size);
-				if (!first_buf->skb) {
-					BNX2X_ERR("Failed to allocate TPA "
-						  "skb pool for queue[%d] - "
-						  "disabling TPA on this "
-						  "queue!\n", j);
-					bnx2x_free_tpa_pool(bp, fp, i);
-					fp->disable_tpa = 1;
-					break;
-				}
-				dma_unmap_addr_set(first_buf, mapping, 0);
-				tpa_info->tpa_state = BNX2X_TPA_STOP;
-			}
-
-			/* "next page" elements initialization */
-			bnx2x_set_next_page_sgl(fp);
-
-			/* set SGEs bit mask */
-			bnx2x_init_sge_ring_bit_mask(fp);
-
-			/* Allocate SGEs and initialize the ring elements */
-			for (i = 0, ring_prod = 0;
-			     i < MAX_RX_SGE_CNT*NUM_RX_SGE_PAGES; i++) {
-
-				if (bnx2x_alloc_rx_sge(bp, fp, ring_prod) < 0) {
-					BNX2X_ERR("was only able to allocate "
-						  "%d rx sges\n", i);
-					BNX2X_ERR("disabling TPA for "
-						  "queue[%d]\n", j);
-					/* Cleanup already allocated elements */
-					bnx2x_free_rx_sge_range(bp, fp,
-								ring_prod);
-					bnx2x_free_tpa_pool(bp, fp,
-							    MAX_AGG_QS(bp));
-					fp->disable_tpa = 1;
-					ring_prod = 0;
-					break;
-				}
-				ring_prod = NEXT_SGE_IDX(ring_prod);
-			}
-
-			fp->rx_sge_prod = ring_prod;
-		}
-	}
-
-	for_each_rx_queue(bp, j) {
-		struct bnx2x_fastpath *fp = &bp->fp[j];
-
-		fp->rx_bd_cons = 0;
-
-		/* Activate BD ring */
-		/* Warning!
-		 * this will generate an interrupt (to the TSTORM)
-		 * must only be done after chip is initialized
-		 */
-		bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod,
-				     fp->rx_sge_prod);
-
-		if (j != 0)
-			continue;
-
-		if (CHIP_IS_E1(bp)) {
-			REG_WR(bp, BAR_USTRORM_INTMEM +
-			       USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func),
-			       U64_LO(fp->rx_comp_mapping));
-			REG_WR(bp, BAR_USTRORM_INTMEM +
-			       USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func) + 4,
-			       U64_HI(fp->rx_comp_mapping));
-		}
-	}
-}
-
-static void bnx2x_free_tx_skbs(struct bnx2x *bp)
-{
-	int i;
-	u8 cos;
-
-	for_each_tx_queue(bp, i) {
-		struct bnx2x_fastpath *fp = &bp->fp[i];
-		for_each_cos_in_tx_queue(fp, cos) {
-			struct bnx2x_fp_txdata *txdata = &fp->txdata[cos];
-
-			u16 bd_cons = txdata->tx_bd_cons;
-			u16 sw_prod = txdata->tx_pkt_prod;
-			u16 sw_cons = txdata->tx_pkt_cons;
-
-			while (sw_cons != sw_prod) {
-				bd_cons = bnx2x_free_tx_pkt(bp, txdata,
-							    TX_BD(sw_cons));
-				sw_cons++;
-			}
-		}
-	}
-}
-
-static void bnx2x_free_rx_bds(struct bnx2x_fastpath *fp)
-{
-	struct bnx2x *bp = fp->bp;
-	int i;
-
-	/* ring wasn't allocated */
-	if (fp->rx_buf_ring == NULL)
-		return;
-
-	for (i = 0; i < NUM_RX_BD; i++) {
-		struct sw_rx_bd *rx_buf = &fp->rx_buf_ring[i];
-		struct sk_buff *skb = rx_buf->skb;
-
-		if (skb == NULL)
-			continue;
-		dma_unmap_single(&bp->pdev->dev,
-				 dma_unmap_addr(rx_buf, mapping),
-				 fp->rx_buf_size, DMA_FROM_DEVICE);
-
-		rx_buf->skb = NULL;
-		dev_kfree_skb(skb);
-	}
-}
-
-static void bnx2x_free_rx_skbs(struct bnx2x *bp)
-{
-	int j;
-
-	for_each_rx_queue(bp, j) {
-		struct bnx2x_fastpath *fp = &bp->fp[j];
-
-		bnx2x_free_rx_bds(fp);
-
-		if (!fp->disable_tpa)
-			bnx2x_free_tpa_pool(bp, fp, MAX_AGG_QS(bp));
-	}
-}
-
-void bnx2x_free_skbs(struct bnx2x *bp)
-{
-	bnx2x_free_tx_skbs(bp);
-	bnx2x_free_rx_skbs(bp);
-}
-
-void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value)
-{
-	/* load old values */
-	u32 mf_cfg = bp->mf_config[BP_VN(bp)];
-
-	if (value != bnx2x_extract_max_cfg(bp, mf_cfg)) {
-		/* leave all but MAX value */
-		mf_cfg &= ~FUNC_MF_CFG_MAX_BW_MASK;
-
-		/* set new MAX value */
-		mf_cfg |= (value << FUNC_MF_CFG_MAX_BW_SHIFT)
-				& FUNC_MF_CFG_MAX_BW_MASK;
-
-		bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW, mf_cfg);
-	}
-}
-
-/**
- * bnx2x_free_msix_irqs - free previously requested MSI-X IRQ vectors
- *
- * @bp:		driver handle
- * @nvecs:	number of vectors to be released
- */
-static void bnx2x_free_msix_irqs(struct bnx2x *bp, int nvecs)
-{
-	int i, offset = 0;
-
-	if (nvecs == offset)
-		return;
-	free_irq(bp->msix_table[offset].vector, bp->dev);
-	DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n",
-	   bp->msix_table[offset].vector);
-	offset++;
-#ifdef BCM_CNIC
-	if (nvecs == offset)
-		return;
-	offset++;
-#endif
-
-	for_each_eth_queue(bp, i) {
-		if (nvecs == offset)
-			return;
-		DP(NETIF_MSG_IFDOWN, "about to release fp #%d->%d "
-		   "irq\n", i, bp->msix_table[offset].vector);
-
-		free_irq(bp->msix_table[offset++].vector, &bp->fp[i]);
-	}
-}
-
-void bnx2x_free_irq(struct bnx2x *bp)
-{
-	if (bp->flags & USING_MSIX_FLAG)
-		bnx2x_free_msix_irqs(bp, BNX2X_NUM_ETH_QUEUES(bp) +
-				     CNIC_PRESENT + 1);
-	else if (bp->flags & USING_MSI_FLAG)
-		free_irq(bp->pdev->irq, bp->dev);
-	else
-		free_irq(bp->pdev->irq, bp->dev);
-}
-
-int bnx2x_enable_msix(struct bnx2x *bp)
-{
-	int msix_vec = 0, i, rc, req_cnt;
-
-	bp->msix_table[msix_vec].entry = msix_vec;
-	DP(NETIF_MSG_IFUP, "msix_table[0].entry = %d (slowpath)\n",
-	   bp->msix_table[0].entry);
-	msix_vec++;
-
-#ifdef BCM_CNIC
-	bp->msix_table[msix_vec].entry = msix_vec;
-	DP(NETIF_MSG_IFUP, "msix_table[%d].entry = %d (CNIC)\n",
-	   bp->msix_table[msix_vec].entry, bp->msix_table[msix_vec].entry);
-	msix_vec++;
-#endif
-	/* We need separate vectors for ETH queues only (not FCoE) */
-	for_each_eth_queue(bp, i) {
-		bp->msix_table[msix_vec].entry = msix_vec;
-		DP(NETIF_MSG_IFUP, "msix_table[%d].entry = %d "
-		   "(fastpath #%u)\n", msix_vec, msix_vec, i);
-		msix_vec++;
-	}
-
-	req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_PRESENT + 1;
-
-	rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], req_cnt);
-
-	/*
-	 * reconfigure number of tx/rx queues according to available
-	 * MSI-X vectors
-	 */
-	if (rc >= BNX2X_MIN_MSIX_VEC_CNT) {
-		/* how less vectors we will have? */
-		int diff = req_cnt - rc;
-
-		DP(NETIF_MSG_IFUP,
-		   "Trying to use less MSI-X vectors: %d\n", rc);
-
-		rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], rc);
-
-		if (rc) {
-			DP(NETIF_MSG_IFUP,
-			   "MSI-X is not attainable  rc %d\n", rc);
-			return rc;
-		}
-		/*
-		 * decrease number of queues by number of unallocated entries
-		 */
-		bp->num_queues -= diff;
-
-		DP(NETIF_MSG_IFUP, "New queue configuration set: %d\n",
-				  bp->num_queues);
-	} else if (rc) {
-		/* fall to INTx if not enough memory */
-		if (rc == -ENOMEM)
-			bp->flags |= DISABLE_MSI_FLAG;
-		DP(NETIF_MSG_IFUP, "MSI-X is not attainable  rc %d\n", rc);
-		return rc;
-	}
-
-	bp->flags |= USING_MSIX_FLAG;
-
-	return 0;
-}
-
-static int bnx2x_req_msix_irqs(struct bnx2x *bp)
-{
-	int i, rc, offset = 0;
-
-	rc = request_irq(bp->msix_table[offset++].vector,
-			 bnx2x_msix_sp_int, 0,
-			 bp->dev->name, bp->dev);
-	if (rc) {
-		BNX2X_ERR("request sp irq failed\n");
-		return -EBUSY;
-	}
-
-#ifdef BCM_CNIC
-	offset++;
-#endif
-	for_each_eth_queue(bp, i) {
-		struct bnx2x_fastpath *fp = &bp->fp[i];
-		snprintf(fp->name, sizeof(fp->name), "%s-fp-%d",
-			 bp->dev->name, i);
-
-		rc = request_irq(bp->msix_table[offset].vector,
-				 bnx2x_msix_fp_int, 0, fp->name, fp);
-		if (rc) {
-			BNX2X_ERR("request fp #%d irq (%d) failed  rc %d\n", i,
-			      bp->msix_table[offset].vector, rc);
-			bnx2x_free_msix_irqs(bp, offset);
-			return -EBUSY;
-		}
-
-		offset++;
-	}
-
-	i = BNX2X_NUM_ETH_QUEUES(bp);
-	offset = 1 + CNIC_PRESENT;
-	netdev_info(bp->dev, "using MSI-X  IRQs: sp %d  fp[%d] %d"
-	       " ... fp[%d] %d\n",
-	       bp->msix_table[0].vector,
-	       0, bp->msix_table[offset].vector,
-	       i - 1, bp->msix_table[offset + i - 1].vector);
-
-	return 0;
-}
-
-int bnx2x_enable_msi(struct bnx2x *bp)
-{
-	int rc;
-
-	rc = pci_enable_msi(bp->pdev);
-	if (rc) {
-		DP(NETIF_MSG_IFUP, "MSI is not attainable\n");
-		return -1;
-	}
-	bp->flags |= USING_MSI_FLAG;
-
-	return 0;
-}
-
-static int bnx2x_req_irq(struct bnx2x *bp)
-{
-	unsigned long flags;
-	int rc;
-
-	if (bp->flags & USING_MSI_FLAG)
-		flags = 0;
-	else
-		flags = IRQF_SHARED;
-
-	rc = request_irq(bp->pdev->irq, bnx2x_interrupt, flags,
-			 bp->dev->name, bp->dev);
-	return rc;
-}
-
-static inline int bnx2x_setup_irqs(struct bnx2x *bp)
-{
-	int rc = 0;
-	if (bp->flags & USING_MSIX_FLAG) {
-		rc = bnx2x_req_msix_irqs(bp);
-		if (rc)
-			return rc;
-	} else {
-		bnx2x_ack_int(bp);
-		rc = bnx2x_req_irq(bp);
-		if (rc) {
-			BNX2X_ERR("IRQ request failed  rc %d, aborting\n", rc);
-			return rc;
-		}
-		if (bp->flags & USING_MSI_FLAG) {
-			bp->dev->irq = bp->pdev->irq;
-			netdev_info(bp->dev, "using MSI  IRQ %d\n",
-			       bp->pdev->irq);
-		}
-	}
-
-	return 0;
-}
-
-static inline void bnx2x_napi_enable(struct bnx2x *bp)
-{
-	int i;
-
-	for_each_rx_queue(bp, i)
-		napi_enable(&bnx2x_fp(bp, i, napi));
-}
-
-static inline void bnx2x_napi_disable(struct bnx2x *bp)
-{
-	int i;
-
-	for_each_rx_queue(bp, i)
-		napi_disable(&bnx2x_fp(bp, i, napi));
-}
-
-void bnx2x_netif_start(struct bnx2x *bp)
-{
-	if (netif_running(bp->dev)) {
-		bnx2x_napi_enable(bp);
-		bnx2x_int_enable(bp);
-		if (bp->state == BNX2X_STATE_OPEN)
-			netif_tx_wake_all_queues(bp->dev);
-	}
-}
-
-void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
-{
-	bnx2x_int_disable_sync(bp, disable_hw);
-	bnx2x_napi_disable(bp);
-}
-
-u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-#ifdef BCM_CNIC
-	if (!NO_FCOE(bp)) {
-		struct ethhdr *hdr = (struct ethhdr *)skb->data;
-		u16 ether_type = ntohs(hdr->h_proto);
-
-		/* Skip VLAN tag if present */
-		if (ether_type == ETH_P_8021Q) {
-			struct vlan_ethhdr *vhdr =
-				(struct vlan_ethhdr *)skb->data;
-
-			ether_type = ntohs(vhdr->h_vlan_encapsulated_proto);
-		}
-
-		/* If ethertype is FCoE or FIP - use FCoE ring */
-		if ((ether_type == ETH_P_FCOE) || (ether_type == ETH_P_FIP))
-			return bnx2x_fcoe_tx(bp, txq_index);
-	}
-#endif
-	/* select a non-FCoE queue */
-	return __skb_tx_hash(dev, skb, BNX2X_NUM_ETH_QUEUES(bp));
-}
-
-void bnx2x_set_num_queues(struct bnx2x *bp)
-{
-	switch (bp->multi_mode) {
-	case ETH_RSS_MODE_DISABLED:
-		bp->num_queues = 1;
-		break;
-	case ETH_RSS_MODE_REGULAR:
-		bp->num_queues = bnx2x_calc_num_queues(bp);
-		break;
-
-	default:
-		bp->num_queues = 1;
-		break;
-	}
-
-	/* Add special queues */
-	bp->num_queues += NON_ETH_CONTEXT_USE;
-}
-
-/**
- * bnx2x_set_real_num_queues - configure netdev->real_num_[tx,rx]_queues
- *
- * @bp:		Driver handle
- *
- * We currently support for at most 16 Tx queues for each CoS thus we will
- * allocate a multiple of 16 for ETH L2 rings according to the value of the
- * bp->max_cos.
- *
- * If there is an FCoE L2 queue the appropriate Tx queue will have the next
- * index after all ETH L2 indices.
- *
- * If the actual number of Tx queues (for each CoS) is less than 16 then there
- * will be the holes at the end of each group of 16 ETh L2 indices (0..15,
- * 16..31,...) with indicies that are not coupled with any real Tx queue.
- *
- * The proper configuration of skb->queue_mapping is handled by
- * bnx2x_select_queue() and __skb_tx_hash().
- *
- * bnx2x_setup_tc() takes care of the proper TC mappings so that __skb_tx_hash()
- * will return a proper Tx index if TC is enabled (netdev->num_tc > 0).
- */
-static inline int bnx2x_set_real_num_queues(struct bnx2x *bp)
-{
-	int rc, tx, rx;
-
-	tx = MAX_TXQS_PER_COS * bp->max_cos;
-	rx = BNX2X_NUM_ETH_QUEUES(bp);
-
-/* account for fcoe queue */
-#ifdef BCM_CNIC
-	if (!NO_FCOE(bp)) {
-		rx += FCOE_PRESENT;
-		tx += FCOE_PRESENT;
-	}
-#endif
-
-	rc = netif_set_real_num_tx_queues(bp->dev, tx);
-	if (rc) {
-		BNX2X_ERR("Failed to set real number of Tx queues: %d\n", rc);
-		return rc;
-	}
-	rc = netif_set_real_num_rx_queues(bp->dev, rx);
-	if (rc) {
-		BNX2X_ERR("Failed to set real number of Rx queues: %d\n", rc);
-		return rc;
-	}
-
-	DP(NETIF_MSG_DRV, "Setting real num queues to (tx, rx) (%d, %d)\n",
-			  tx, rx);
-
-	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_FW_RX_ALIGN + IP_HEADER_ALIGNMENT_PADDING;
-		else
-			fp->rx_buf_size =
-				bp->dev->mtu + ETH_OVREHEAD +
-				BNX2X_FW_RX_ALIGN + IP_HEADER_ALIGNMENT_PADDING;
-	}
-}
-
-static inline int bnx2x_init_rss_pf(struct bnx2x *bp)
-{
-	int i;
-	u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
-	u8 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp);
-
-	/*
-	 * Prepare the inital contents fo the indirection table if RSS is
-	 * enabled
-	 */
-	if (bp->multi_mode != ETH_RSS_MODE_DISABLED) {
-		for (i = 0; i < sizeof(ind_table); i++)
-			ind_table[i] =
-				bp->fp->cl_id +	(i % num_eth_queues);
-	}
-
-	/*
-	 * For 57710 and 57711 SEARCHER configuration (rss_keys) is
-	 * per-port, so if explicit configuration is needed , do it only
-	 * for a PMF.
-	 *
-	 * For 57712 and newer on the other hand it's a per-function
-	 * configuration.
-	 */
-	return bnx2x_config_rss_pf(bp, ind_table,
-				   bp->port.pmf || !CHIP_IS_E1x(bp));
-}
-
-int bnx2x_config_rss_pf(struct bnx2x *bp, u8 *ind_table, bool config_hash)
-{
-	struct bnx2x_config_rss_params params = {0};
-	int i;
-
-	/* Although RSS is meaningless when there is a single HW queue we
-	 * still need it enabled in order to have HW Rx hash generated.
-	 *
-	 * if (!is_eth_multi(bp))
-	 *      bp->multi_mode = ETH_RSS_MODE_DISABLED;
-	 */
-
-	params.rss_obj = &bp->rss_conf_obj;
-
-	__set_bit(RAMROD_COMP_WAIT, &params.ramrod_flags);
-
-	/* RSS mode */
-	switch (bp->multi_mode) {
-	case ETH_RSS_MODE_DISABLED:
-		__set_bit(BNX2X_RSS_MODE_DISABLED, &params.rss_flags);
-		break;
-	case ETH_RSS_MODE_REGULAR:
-		__set_bit(BNX2X_RSS_MODE_REGULAR, &params.rss_flags);
-		break;
-	case ETH_RSS_MODE_VLAN_PRI:
-		__set_bit(BNX2X_RSS_MODE_VLAN_PRI, &params.rss_flags);
-		break;
-	case ETH_RSS_MODE_E1HOV_PRI:
-		__set_bit(BNX2X_RSS_MODE_E1HOV_PRI, &params.rss_flags);
-		break;
-	case ETH_RSS_MODE_IP_DSCP:
-		__set_bit(BNX2X_RSS_MODE_IP_DSCP, &params.rss_flags);
-		break;
-	default:
-		BNX2X_ERR("Unknown multi_mode: %d\n", bp->multi_mode);
-		return -EINVAL;
-	}
-
-	/* If RSS is enabled */
-	if (bp->multi_mode != ETH_RSS_MODE_DISABLED) {
-		/* RSS configuration */
-		__set_bit(BNX2X_RSS_IPV4, &params.rss_flags);
-		__set_bit(BNX2X_RSS_IPV4_TCP, &params.rss_flags);
-		__set_bit(BNX2X_RSS_IPV6, &params.rss_flags);
-		__set_bit(BNX2X_RSS_IPV6_TCP, &params.rss_flags);
-
-		/* Hash bits */
-		params.rss_result_mask = MULTI_MASK;
-
-		memcpy(params.ind_table, ind_table, sizeof(params.ind_table));
-
-		if (config_hash) {
-			/* RSS keys */
-			for (i = 0; i < sizeof(params.rss_key) / 4; i++)
-				params.rss_key[i] = random32();
-
-			__set_bit(BNX2X_RSS_SET_SRCH, &params.rss_flags);
-		}
-	}
-
-	return bnx2x_config_rss(bp, &params);
-}
-
-static inline int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
-{
-	struct bnx2x_func_state_params func_params = {0};
-
-	/* Prepare parameters for function state transitions */
-	__set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
-
-	func_params.f_obj = &bp->func_obj;
-	func_params.cmd = BNX2X_F_CMD_HW_INIT;
-
-	func_params.params.hw_init.load_phase = load_code;
-
-	return bnx2x_func_state_change(bp, &func_params);
-}
-
-/*
- * Cleans the object that have internal lists without sending
- * ramrods. Should be run when interrutps are disabled.
- */
-static void bnx2x_squeeze_objects(struct bnx2x *bp)
-{
-	int rc;
-	unsigned long ramrod_flags = 0, vlan_mac_flags = 0;
-	struct bnx2x_mcast_ramrod_params rparam = {0};
-	struct bnx2x_vlan_mac_obj *mac_obj = &bp->fp->mac_obj;
-
-	/***************** Cleanup MACs' object first *************************/
-
-	/* Wait for completion of requested */
-	__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
-	/* Perform a dry cleanup */
-	__set_bit(RAMROD_DRV_CLR_ONLY, &ramrod_flags);
-
-	/* Clean ETH primary MAC */
-	__set_bit(BNX2X_ETH_MAC, &vlan_mac_flags);
-	rc = mac_obj->delete_all(bp, &bp->fp->mac_obj, &vlan_mac_flags,
-				 &ramrod_flags);
-	if (rc != 0)
-		BNX2X_ERR("Failed to clean ETH MACs: %d\n", rc);
-
-	/* Cleanup UC list */
-	vlan_mac_flags = 0;
-	__set_bit(BNX2X_UC_LIST_MAC, &vlan_mac_flags);
-	rc = mac_obj->delete_all(bp, mac_obj, &vlan_mac_flags,
-				 &ramrod_flags);
-	if (rc != 0)
-		BNX2X_ERR("Failed to clean UC list MACs: %d\n", rc);
-
-	/***************** Now clean mcast object *****************************/
-	rparam.mcast_obj = &bp->mcast_obj;
-	__set_bit(RAMROD_DRV_CLR_ONLY, &rparam.ramrod_flags);
-
-	/* Add a DEL command... */
-	rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
-	if (rc < 0)
-		BNX2X_ERR("Failed to add a new DEL command to a multi-cast "
-			  "object: %d\n", rc);
-
-	/* ...and wait until all pending commands are cleared */
-	rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_CONT);
-	while (rc != 0) {
-		if (rc < 0) {
-			BNX2X_ERR("Failed to clean multi-cast object: %d\n",
-				  rc);
-			return;
-		}
-
-		rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_CONT);
-	}
-}
-
-#ifndef BNX2X_STOP_ON_ERROR
-#define LOAD_ERROR_EXIT(bp, label) \
-	do { \
-		(bp)->state = BNX2X_STATE_ERROR; \
-		goto label; \
-	} while (0)
-#else
-#define LOAD_ERROR_EXIT(bp, label) \
-	do { \
-		(bp)->state = BNX2X_STATE_ERROR; \
-		(bp)->panic = 1; \
-		return -EBUSY; \
-	} while (0)
-#endif
-
-/* must be called with rtnl_lock */
-int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
-{
-	int port = BP_PORT(bp);
-	u32 load_code;
-	int i, rc;
-
-#ifdef BNX2X_STOP_ON_ERROR
-	if (unlikely(bp->panic))
-		return -EPERM;
-#endif
-
-	bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD;
-
-	/* Set the initial link reported state to link down */
-	bnx2x_acquire_phy_lock(bp);
-	memset(&bp->last_reported_link, 0, sizeof(bp->last_reported_link));
-	__set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
-		&bp->last_reported_link.link_report_flags);
-	bnx2x_release_phy_lock(bp);
-
-	/* must be called before memory allocation and HW init */
-	bnx2x_ilt_set_info(bp);
-
-	/*
-	 * Zero fastpath structures preserving invariants like napi, which are
-	 * allocated only once, fp index, max_cos, bp pointer.
-	 * Also set fp->disable_tpa.
-	 */
-	for_each_queue(bp, i)
-		bnx2x_bz_fp(bp, i);
-
-
-	/* Set the receive queues buffer size */
-	bnx2x_set_rx_buf_size(bp);
-
-	if (bnx2x_alloc_mem(bp))
-		return -ENOMEM;
-
-	/* As long as bnx2x_alloc_mem() may possibly update
-	 * bp->num_queues, bnx2x_set_real_num_queues() should always
-	 * come after it.
-	 */
-	rc = bnx2x_set_real_num_queues(bp);
-	if (rc) {
-		BNX2X_ERR("Unable to set real_num_queues\n");
-		LOAD_ERROR_EXIT(bp, load_error0);
-	}
-
-	/* configure multi cos mappings in kernel.
-	 * this configuration may be overriden by a multi class queue discipline
-	 * or by a dcbx negotiation result.
-	 */
-	bnx2x_setup_tc(bp->dev, bp->max_cos);
-
-	bnx2x_napi_enable(bp);
-
-	/* Send LOAD_REQUEST command to MCP
-	 * Returns the type of LOAD command:
-	 * if it is the first port to be initialized
-	 * common blocks should be initialized, otherwise - not
-	 */
-	if (!BP_NOMCP(bp)) {
-		load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0);
-		if (!load_code) {
-			BNX2X_ERR("MCP response failure, aborting\n");
-			rc = -EBUSY;
-			LOAD_ERROR_EXIT(bp, load_error1);
-		}
-		if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) {
-			rc = -EBUSY; /* other port in diagnostic mode */
-			LOAD_ERROR_EXIT(bp, load_error1);
-		}
-
-	} else {
-		int path = BP_PATH(bp);
-
-		DP(NETIF_MSG_IFUP, "NO MCP - load counts[%d]      %d, %d, %d\n",
-		   path, load_count[path][0], load_count[path][1],
-		   load_count[path][2]);
-		load_count[path][0]++;
-		load_count[path][1 + port]++;
-		DP(NETIF_MSG_IFUP, "NO MCP - new load counts[%d]  %d, %d, %d\n",
-		   path, load_count[path][0], load_count[path][1],
-		   load_count[path][2]);
-		if (load_count[path][0] == 1)
-			load_code = FW_MSG_CODE_DRV_LOAD_COMMON;
-		else if (load_count[path][1 + port] == 1)
-			load_code = FW_MSG_CODE_DRV_LOAD_PORT;
-		else
-			load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION;
-	}
-
-	if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
-	    (load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) ||
-	    (load_code == FW_MSG_CODE_DRV_LOAD_PORT)) {
-		bp->port.pmf = 1;
-		/*
-		 * We need the barrier to ensure the ordering between the
-		 * writing to bp->port.pmf here and reading it from the
-		 * bnx2x_periodic_task().
-		 */
-		smp_mb();
-		queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
-	} else
-		bp->port.pmf = 0;
-
-	DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);
-
-	/* Init Function state controlling object */
-	bnx2x__init_func_obj(bp);
-
-	/* Initialize HW */
-	rc = bnx2x_init_hw(bp, load_code);
-	if (rc) {
-		BNX2X_ERR("HW init failed, aborting\n");
-		bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
-		LOAD_ERROR_EXIT(bp, load_error2);
-	}
-
-	/* Connect to IRQs */
-	rc = bnx2x_setup_irqs(bp);
-	if (rc) {
-		bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
-		LOAD_ERROR_EXIT(bp, load_error2);
-	}
-
-	/* Setup NIC internals and enable interrupts */
-	bnx2x_nic_init(bp, load_code);
-
-	/* Init per-function objects */
-	bnx2x_init_bp_objs(bp);
-
-	if (((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
-	    (load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP)) &&
-	    (bp->common.shmem2_base)) {
-		if (SHMEM2_HAS(bp, dcc_support))
-			SHMEM2_WR(bp, dcc_support,
-				  (SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV |
-				   SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV));
-	}
-
-	bp->state = BNX2X_STATE_OPENING_WAIT4_PORT;
-	rc = bnx2x_func_start(bp);
-	if (rc) {
-		BNX2X_ERR("Function start failed!\n");
-		bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
-		LOAD_ERROR_EXIT(bp, load_error3);
-	}
-
-	/* Send LOAD_DONE command to MCP */
-	if (!BP_NOMCP(bp)) {
-		load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
-		if (!load_code) {
-			BNX2X_ERR("MCP response failure, aborting\n");
-			rc = -EBUSY;
-			LOAD_ERROR_EXIT(bp, load_error3);
-		}
-	}
-
-	rc = bnx2x_setup_leading(bp);
-	if (rc) {
-		BNX2X_ERR("Setup leading failed!\n");
-		LOAD_ERROR_EXIT(bp, load_error3);
-	}
-
-#ifdef BCM_CNIC
-	/* Enable Timer scan */
-	REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 1);
-#endif
-
-	for_each_nondefault_queue(bp, i) {
-		rc = bnx2x_setup_queue(bp, &bp->fp[i], 0);
-		if (rc)
-			LOAD_ERROR_EXIT(bp, load_error4);
-	}
-
-	rc = bnx2x_init_rss_pf(bp);
-	if (rc)
-		LOAD_ERROR_EXIT(bp, load_error4);
-
-	/* Now when Clients are configured we are ready to work */
-	bp->state = BNX2X_STATE_OPEN;
-
-	/* Configure a ucast MAC */
-	rc = bnx2x_set_eth_mac(bp, true);
-	if (rc)
-		LOAD_ERROR_EXIT(bp, load_error4);
-
-	if (bp->pending_max) {
-		bnx2x_update_max_mf_config(bp, bp->pending_max);
-		bp->pending_max = 0;
-	}
-
-	if (bp->port.pmf)
-		bnx2x_initial_phy_init(bp, load_mode);
-
-	/* Start fast path */
-
-	/* Initialize Rx filter. */
-	netif_addr_lock_bh(bp->dev);
-	bnx2x_set_rx_mode(bp->dev);
-	netif_addr_unlock_bh(bp->dev);
-
-	/* Start the Tx */
-	switch (load_mode) {
-	case LOAD_NORMAL:
-		/* Tx queue should be only reenabled */
-		netif_tx_wake_all_queues(bp->dev);
-		break;
-
-	case LOAD_OPEN:
-		netif_tx_start_all_queues(bp->dev);
-		smp_mb__after_clear_bit();
-		break;
-
-	case LOAD_DIAG:
-		bp->state = BNX2X_STATE_DIAG;
-		break;
-
-	default:
-		break;
-	}
-
-	if (!bp->port.pmf)
-		bnx2x__link_status_update(bp);
-
-	/* start the timer */
-	mod_timer(&bp->timer, jiffies + bp->current_interval);
-
-#ifdef BCM_CNIC
-	bnx2x_setup_cnic_irq_info(bp);
-	if (bp->state == BNX2X_STATE_OPEN)
-		bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD);
-#endif
-	bnx2x_inc_load_cnt(bp);
-
-	/* Wait for all pending SP commands to complete */
-	if (!bnx2x_wait_sp_comp(bp, ~0x0UL)) {
-		BNX2X_ERR("Timeout waiting for SP elements to complete\n");
-		bnx2x_nic_unload(bp, UNLOAD_CLOSE);
-		return -EBUSY;
-	}
-
-	bnx2x_dcbx_init(bp);
-	return 0;
-
-#ifndef BNX2X_STOP_ON_ERROR
-load_error4:
-#ifdef BCM_CNIC
-	/* Disable Timer scan */
-	REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
-#endif
-load_error3:
-	bnx2x_int_disable_sync(bp, 1);
-
-	/* Clean queueable objects */
-	bnx2x_squeeze_objects(bp);
-
-	/* Free SKBs, SGEs, TPA pool and driver internals */
-	bnx2x_free_skbs(bp);
-	for_each_rx_queue(bp, i)
-		bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
-
-	/* Release IRQs */
-	bnx2x_free_irq(bp);
-load_error2:
-	if (!BP_NOMCP(bp)) {
-		bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP, 0);
-		bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
-	}
-
-	bp->port.pmf = 0;
-load_error1:
-	bnx2x_napi_disable(bp);
-load_error0:
-	bnx2x_free_mem(bp);
-
-	return rc;
-#endif /* ! BNX2X_STOP_ON_ERROR */
-}
-
-/* must be called with rtnl_lock */
-int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
-{
-	int i;
-	bool global = false;
-
-	if ((bp->state == BNX2X_STATE_CLOSED) ||
-	    (bp->state == BNX2X_STATE_ERROR)) {
-		/* We can get here if the driver has been unloaded
-		 * during parity error recovery and is either waiting for a
-		 * leader to complete or for other functions to unload and
-		 * then ifdown has been issued. In this case we want to
-		 * unload and let other functions to complete a recovery
-		 * process.
-		 */
-		bp->recovery_state = BNX2X_RECOVERY_DONE;
-		bp->is_leader = 0;
-		bnx2x_release_leader_lock(bp);
-		smp_mb();
-
-		DP(NETIF_MSG_HW, "Releasing a leadership...\n");
-
-		return -EINVAL;
-	}
-
-	/*
-	 * It's important to set the bp->state to the value different from
-	 * BNX2X_STATE_OPEN and only then stop the Tx. Otherwise bnx2x_tx_int()
-	 * may restart the Tx from the NAPI context (see bnx2x_tx_int()).
-	 */
-	bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
-	smp_mb();
-
-	/* Stop Tx */
-	bnx2x_tx_disable(bp);
-
-#ifdef BCM_CNIC
-	bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
-#endif
-
-	bp->rx_mode = BNX2X_RX_MODE_NONE;
-
-	del_timer_sync(&bp->timer);
-
-	/* Set ALWAYS_ALIVE bit in shmem */
-	bp->fw_drv_pulse_wr_seq |= DRV_PULSE_ALWAYS_ALIVE;
-
-	bnx2x_drv_pulse(bp);
-
-	bnx2x_stats_handle(bp, STATS_EVENT_STOP);
-
-	/* Cleanup the chip if needed */
-	if (unload_mode != UNLOAD_RECOVERY)
-		bnx2x_chip_cleanup(bp, unload_mode);
-	else {
-		/* Send the UNLOAD_REQUEST to the MCP */
-		bnx2x_send_unload_req(bp, unload_mode);
-
-		/*
-		 * Prevent transactions to host from the functions on the
-		 * engine that doesn't reset global blocks in case of global
-		 * attention once gloabl blocks are reset and gates are opened
-		 * (the engine which leader will perform the recovery
-		 * last).
-		 */
-		if (!CHIP_IS_E1x(bp))
-			bnx2x_pf_disable(bp);
-
-		/* Disable HW interrupts, NAPI */
-		bnx2x_netif_stop(bp, 1);
-
-		/* Release IRQs */
-		bnx2x_free_irq(bp);
-
-		/* Report UNLOAD_DONE to MCP */
-		bnx2x_send_unload_done(bp);
-	}
-
-	/*
-	 * At this stage no more interrupts will arrive so we may safly clean
-	 * the queueable objects here in case they failed to get cleaned so far.
-	 */
-	bnx2x_squeeze_objects(bp);
-
-	/* There should be no more pending SP commands at this stage */
-	bp->sp_state = 0;
-
-	bp->port.pmf = 0;
-
-	/* Free SKBs, SGEs, TPA pool and driver internals */
-	bnx2x_free_skbs(bp);
-	for_each_rx_queue(bp, i)
-		bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
-
-	bnx2x_free_mem(bp);
-
-	bp->state = BNX2X_STATE_CLOSED;
-
-	/* Check if there are pending parity attentions. If there are - set
-	 * RECOVERY_IN_PROGRESS.
-	 */
-	if (bnx2x_chk_parity_attn(bp, &global, false)) {
-		bnx2x_set_reset_in_progress(bp);
-
-		/* Set RESET_IS_GLOBAL if needed */
-		if (global)
-			bnx2x_set_reset_global(bp);
-	}
-
-
-	/* The last driver must disable a "close the gate" if there is no
-	 * parity attention or "process kill" pending.
-	 */
-	if (!bnx2x_dec_load_cnt(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp)))
-		bnx2x_disable_close_the_gate(bp);
-
-	return 0;
-}
-
-int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state)
-{
-	u16 pmcsr;
-
-	/* If there is no power capability, silently succeed */
-	if (!bp->pm_cap) {
-		DP(NETIF_MSG_HW, "No power capability. Breaking.\n");
-		return 0;
-	}
-
-	pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr);
-
-	switch (state) {
-	case PCI_D0:
-		pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
-				      ((pmcsr & ~PCI_PM_CTRL_STATE_MASK) |
-				       PCI_PM_CTRL_PME_STATUS));
-
-		if (pmcsr & PCI_PM_CTRL_STATE_MASK)
-			/* delay required during transition out of D3hot */
-			msleep(20);
-		break;
-
-	case PCI_D3hot:
-		/* If there are other clients above don't
-		   shut down the power */
-		if (atomic_read(&bp->pdev->enable_cnt) != 1)
-			return 0;
-		/* Don't shut down the power for emulation and FPGA */
-		if (CHIP_REV_IS_SLOW(bp))
-			return 0;
-
-		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
-		pmcsr |= 3;
-
-		if (bp->wol)
-			pmcsr |= PCI_PM_CTRL_PME_ENABLE;
-
-		pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
-				      pmcsr);
-
-		/* No more memory access after this point until
-		* device is brought back to D0.
-		*/
-		break;
-
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-/*
- * net_device service functions
- */
-int bnx2x_poll(struct napi_struct *napi, int budget)
-{
-	int work_done = 0;
-	u8 cos;
-	struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath,
-						 napi);
-	struct bnx2x *bp = fp->bp;
-
-	while (1) {
-#ifdef BNX2X_STOP_ON_ERROR
-		if (unlikely(bp->panic)) {
-			napi_complete(napi);
-			return 0;
-		}
-#endif
-
-		for_each_cos_in_tx_queue(fp, cos)
-			if (bnx2x_tx_queue_has_work(&fp->txdata[cos]))
-				bnx2x_tx_int(bp, &fp->txdata[cos]);
-
-
-		if (bnx2x_has_rx_work(fp)) {
-			work_done += bnx2x_rx_int(fp, budget - work_done);
-
-			/* must not complete if we consumed full budget */
-			if (work_done >= budget)
-				break;
-		}
-
-		/* Fall out from the NAPI loop if needed */
-		if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
-#ifdef BCM_CNIC
-			/* No need to update SB for FCoE L2 ring as long as
-			 * it's connected to the default SB and the SB
-			 * has been updated when NAPI was scheduled.
-			 */
-			if (IS_FCOE_FP(fp)) {
-				napi_complete(napi);
-				break;
-			}
-#endif
-
-			bnx2x_update_fpsb_idx(fp);
-			/* bnx2x_has_rx_work() reads the status block,
-			 * thus we need to ensure that status block indices
-			 * have been actually read (bnx2x_update_fpsb_idx)
-			 * prior to this check (bnx2x_has_rx_work) so that
-			 * we won't write the "newer" value of the status block
-			 * to IGU (if there was a DMA right after
-			 * bnx2x_has_rx_work and if there is no rmb, the memory
-			 * reading (bnx2x_update_fpsb_idx) may be postponed
-			 * to right before bnx2x_ack_sb). In this case there
-			 * will never be another interrupt until there is
-			 * another update of the status block, while there
-			 * is still unhandled work.
-			 */
-			rmb();
-
-			if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
-				napi_complete(napi);
-				/* Re-enable interrupts */
-				DP(NETIF_MSG_HW,
-				   "Update index to %d\n", fp->fp_hc_idx);
-				bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID,
-					     le16_to_cpu(fp->fp_hc_idx),
-					     IGU_INT_ENABLE, 1);
-				break;
-			}
-		}
-	}
-
-	return work_done;
-}
-
-/* we split the first BD into headers and data BDs
- * to ease the pain of our fellow microcode engineers
- * we use one mapping for both BDs
- * So far this has only been observed to happen
- * in Other Operating Systems(TM)
- */
-static noinline u16 bnx2x_tx_split(struct bnx2x *bp,
-				   struct bnx2x_fp_txdata *txdata,
-				   struct sw_tx_bd *tx_buf,
-				   struct eth_tx_start_bd **tx_bd, u16 hlen,
-				   u16 bd_prod, int nbd)
-{
-	struct eth_tx_start_bd *h_tx_bd = *tx_bd;
-	struct eth_tx_bd *d_tx_bd;
-	dma_addr_t mapping;
-	int old_len = le16_to_cpu(h_tx_bd->nbytes);
-
-	/* first fix first BD */
-	h_tx_bd->nbd = cpu_to_le16(nbd);
-	h_tx_bd->nbytes = cpu_to_le16(hlen);
-
-	DP(NETIF_MSG_TX_QUEUED,	"TSO split header size is %d "
-	   "(%x:%x) nbd %d\n", h_tx_bd->nbytes, h_tx_bd->addr_hi,
-	   h_tx_bd->addr_lo, h_tx_bd->nbd);
-
-	/* now get a new data BD
-	 * (after the pbd) and fill it */
-	bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
-	d_tx_bd = &txdata->tx_desc_ring[bd_prod].reg_bd;
-
-	mapping = HILO_U64(le32_to_cpu(h_tx_bd->addr_hi),
-			   le32_to_cpu(h_tx_bd->addr_lo)) + hlen;
-
-	d_tx_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
-	d_tx_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
-	d_tx_bd->nbytes = cpu_to_le16(old_len - hlen);
-
-	/* this marks the BD as one that has no individual mapping */
-	tx_buf->flags |= BNX2X_TSO_SPLIT_BD;
-
-	DP(NETIF_MSG_TX_QUEUED,
-	   "TSO split data size is %d (%x:%x)\n",
-	   d_tx_bd->nbytes, d_tx_bd->addr_hi, d_tx_bd->addr_lo);
-
-	/* update tx_bd */
-	*tx_bd = (struct eth_tx_start_bd *)d_tx_bd;
-
-	return bd_prod;
-}
-
-static inline u16 bnx2x_csum_fix(unsigned char *t_header, u16 csum, s8 fix)
-{
-	if (fix > 0)
-		csum = (u16) ~csum_fold(csum_sub(csum,
-				csum_partial(t_header - fix, fix, 0)));
-
-	else if (fix < 0)
-		csum = (u16) ~csum_fold(csum_add(csum,
-				csum_partial(t_header, -fix, 0)));
-
-	return swab16(csum);
-}
-
-static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb)
-{
-	u32 rc;
-
-	if (skb->ip_summed != CHECKSUM_PARTIAL)
-		rc = XMIT_PLAIN;
-
-	else {
-		if (vlan_get_protocol(skb) == htons(ETH_P_IPV6)) {
-			rc = XMIT_CSUM_V6;
-			if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
-				rc |= XMIT_CSUM_TCP;
-
-		} else {
-			rc = XMIT_CSUM_V4;
-			if (ip_hdr(skb)->protocol == IPPROTO_TCP)
-				rc |= XMIT_CSUM_TCP;
-		}
-	}
-
-	if (skb_is_gso_v6(skb))
-		rc |= XMIT_GSO_V6 | XMIT_CSUM_TCP | XMIT_CSUM_V6;
-	else if (skb_is_gso(skb))
-		rc |= XMIT_GSO_V4 | XMIT_CSUM_V4 | XMIT_CSUM_TCP;
-
-	return rc;
-}
-
-#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - 3)
-/* check if packet requires linearization (packet is too fragmented)
-   no need to check fragmentation if page size > 8K (there will be no
-   violation to FW restrictions) */
-static int bnx2x_pkt_req_lin(struct bnx2x *bp, struct sk_buff *skb,
-			     u32 xmit_type)
-{
-	int to_copy = 0;
-	int hlen = 0;
-	int first_bd_sz = 0;
-
-	/* 3 = 1 (for linear data BD) + 2 (for PBD and last BD) */
-	if (skb_shinfo(skb)->nr_frags >= (MAX_FETCH_BD - 3)) {
-
-		if (xmit_type & XMIT_GSO) {
-			unsigned short lso_mss = skb_shinfo(skb)->gso_size;
-			/* Check if LSO packet needs to be copied:
-			   3 = 1 (for headers BD) + 2 (for PBD and last BD) */
-			int wnd_size = MAX_FETCH_BD - 3;
-			/* Number of windows to check */
-			int num_wnds = skb_shinfo(skb)->nr_frags - wnd_size;
-			int wnd_idx = 0;
-			int frag_idx = 0;
-			u32 wnd_sum = 0;
-
-			/* Headers length */
-			hlen = (int)(skb_transport_header(skb) - skb->data) +
-				tcp_hdrlen(skb);
-
-			/* Amount of data (w/o headers) on linear part of SKB*/
-			first_bd_sz = skb_headlen(skb) - hlen;
-
-			wnd_sum  = first_bd_sz;
-
-			/* Calculate the first sum - it's special */
-			for (frag_idx = 0; frag_idx < wnd_size - 1; frag_idx++)
-				wnd_sum +=
-					skb_shinfo(skb)->frags[frag_idx].size;
-
-			/* If there was data on linear skb data - check it */
-			if (first_bd_sz > 0) {
-				if (unlikely(wnd_sum < lso_mss)) {
-					to_copy = 1;
-					goto exit_lbl;
-				}
-
-				wnd_sum -= first_bd_sz;
-			}
-
-			/* Others are easier: run through the frag list and
-			   check all windows */
-			for (wnd_idx = 0; wnd_idx <= num_wnds; wnd_idx++) {
-				wnd_sum +=
-			  skb_shinfo(skb)->frags[wnd_idx + wnd_size - 1].size;
-
-				if (unlikely(wnd_sum < lso_mss)) {
-					to_copy = 1;
-					break;
-				}
-				wnd_sum -=
-					skb_shinfo(skb)->frags[wnd_idx].size;
-			}
-		} else {
-			/* in non-LSO too fragmented packet should always
-			   be linearized */
-			to_copy = 1;
-		}
-	}
-
-exit_lbl:
-	if (unlikely(to_copy))
-		DP(NETIF_MSG_TX_QUEUED,
-		   "Linearization IS REQUIRED for %s packet. "
-		   "num_frags %d  hlen %d  first_bd_sz %d\n",
-		   (xmit_type & XMIT_GSO) ? "LSO" : "non-LSO",
-		   skb_shinfo(skb)->nr_frags, hlen, first_bd_sz);
-
-	return to_copy;
-}
-#endif
-
-static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb, u32 *parsing_data,
-					u32 xmit_type)
-{
-	*parsing_data |= (skb_shinfo(skb)->gso_size <<
-			      ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT) &
-			      ETH_TX_PARSE_BD_E2_LSO_MSS;
-	if ((xmit_type & XMIT_GSO_V6) &&
-	    (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6))
-		*parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR;
-}
-
-/**
- * bnx2x_set_pbd_gso - update PBD in GSO case.
- *
- * @skb:	packet skb
- * @pbd:	parse BD
- * @xmit_type:	xmit flags
- */
-static inline void bnx2x_set_pbd_gso(struct sk_buff *skb,
-				     struct eth_tx_parse_bd_e1x *pbd,
-				     u32 xmit_type)
-{
-	pbd->lso_mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
-	pbd->tcp_send_seq = swab32(tcp_hdr(skb)->seq);
-	pbd->tcp_flags = pbd_tcp_flags(skb);
-
-	if (xmit_type & XMIT_GSO_V4) {
-		pbd->ip_id = swab16(ip_hdr(skb)->id);
-		pbd->tcp_pseudo_csum =
-			swab16(~csum_tcpudp_magic(ip_hdr(skb)->saddr,
-						  ip_hdr(skb)->daddr,
-						  0, IPPROTO_TCP, 0));
-
-	} else
-		pbd->tcp_pseudo_csum =
-			swab16(~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
-						&ipv6_hdr(skb)->daddr,
-						0, IPPROTO_TCP, 0));
-
-	pbd->global_data |= ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN;
-}
-
-/**
- * bnx2x_set_pbd_csum_e2 - update PBD with checksum and return header length
- *
- * @bp:			driver handle
- * @skb:		packet skb
- * @parsing_data:	data to be updated
- * @xmit_type:		xmit flags
- *
- * 57712 related
- */
-static inline  u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
-	u32 *parsing_data, u32 xmit_type)
-{
-	*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;
-
-	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;
-	} 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;
-}
-
-static inline void bnx2x_set_sbd_csum(struct bnx2x *bp, struct sk_buff *skb,
-	struct eth_tx_start_bd *tx_start_bd, u32 xmit_type)
-{
-	tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_L4_CSUM;
-
-	if (xmit_type & XMIT_CSUM_V4)
-		tx_start_bd->bd_flags.as_bitfield |=
-					ETH_TX_BD_FLAGS_IP_CSUM;
-	else
-		tx_start_bd->bd_flags.as_bitfield |=
-					ETH_TX_BD_FLAGS_IPV6;
-
-	if (!(xmit_type & XMIT_CSUM_TCP))
-		tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_IS_UDP;
-}
-
-/**
- * bnx2x_set_pbd_csum - update PBD with checksum and return header length
- *
- * @bp:		driver handle
- * @skb:	packet skb
- * @pbd:	parse BD to be updated
- * @xmit_type:	xmit flags
- */
-static inline u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb,
-	struct eth_tx_parse_bd_e1x *pbd,
-	u32 xmit_type)
-{
-	u8 hlen = (skb_network_header(skb) - skb->data) >> 1;
-
-	/* for now NS flag is not used in Linux */
-	pbd->global_data =
-		(hlen | ((skb->protocol == cpu_to_be16(ETH_P_8021Q)) <<
-			 ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT));
-
-	pbd->ip_hlen_w = (skb_transport_header(skb) -
-			skb_network_header(skb)) >> 1;
-
-	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;
-
-	if (xmit_type & XMIT_CSUM_TCP) {
-		pbd->tcp_pseudo_csum = swab16(tcp_hdr(skb)->check);
-
-	} else {
-		s8 fix = SKB_CS_OFF(skb); /* signed! */
-
-		DP(NETIF_MSG_TX_QUEUED,
-		   "hlen %d  fix %d  csum before fix %x\n",
-		   le16_to_cpu(pbd->total_hlen_w), fix, SKB_CS(skb));
-
-		/* HW bug: fixup the CSUM */
-		pbd->tcp_pseudo_csum =
-			bnx2x_csum_fix(skb_transport_header(skb),
-				       SKB_CS(skb), fix);
-
-		DP(NETIF_MSG_TX_QUEUED, "csum after fix %x\n",
-		   pbd->tcp_pseudo_csum);
-	}
-
-	return hlen;
-}
-
-/* called with netif_tx_lock
- * bnx2x_tx_int() runs without netif_tx_lock unless it needs to call
- * netif_wake_queue()
- */
-netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	struct bnx2x_fastpath *fp;
-	struct netdev_queue *txq;
-	struct bnx2x_fp_txdata *txdata;
-	struct sw_tx_bd *tx_buf;
-	struct eth_tx_start_bd *tx_start_bd, *first_bd;
-	struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL;
-	struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
-	struct eth_tx_parse_bd_e2 *pbd_e2 = NULL;
-	u32 pbd_e2_parsing_data = 0;
-	u16 pkt_prod, bd_prod;
-	int nbd, txq_index, fp_index, txdata_index;
-	dma_addr_t mapping;
-	u32 xmit_type = bnx2x_xmit_type(bp, skb);
-	int i;
-	u8 hlen = 0;
-	__le16 pkt_size = 0;
-	struct ethhdr *eth;
-	u8 mac_type = UNICAST_ADDRESS;
-
-#ifdef BNX2X_STOP_ON_ERROR
-	if (unlikely(bp->panic))
-		return NETDEV_TX_BUSY;
-#endif
-
-	txq_index = skb_get_queue_mapping(skb);
-	txq = netdev_get_tx_queue(dev, txq_index);
-
-	BUG_ON(txq_index >= MAX_ETH_TXQ_IDX(bp) + FCOE_PRESENT);
-
-	/* decode the fastpath index and the cos index from the txq */
-	fp_index = TXQ_TO_FP(txq_index);
-	txdata_index = TXQ_TO_COS(txq_index);
-
-#ifdef BCM_CNIC
-	/*
-	 * Override the above for the FCoE queue:
-	 *   - FCoE fp entry is right after the ETH entries.
-	 *   - FCoE L2 queue uses bp->txdata[0] only.
-	 */
-	if (unlikely(!NO_FCOE(bp) && (txq_index ==
-				      bnx2x_fcoe_tx(bp, txq_index)))) {
-		fp_index = FCOE_IDX;
-		txdata_index = 0;
-	}
-#endif
-
-	/* enable this debug print to view the transmission queue being used
-	DP(BNX2X_MSG_FP, "indices: txq %d, fp %d, txdata %d",
-	   txq_index, fp_index, txdata_index); */
-
-	/* locate the fastpath and the txdata */
-	fp = &bp->fp[fp_index];
-	txdata = &fp->txdata[txdata_index];
-
-	/* enable this debug print to view the tranmission details
-	DP(BNX2X_MSG_FP,"transmitting packet cid %d fp index %d txdata_index %d"
-			" tx_data ptr %p fp pointer %p",
-	   txdata->cid, fp_index, txdata_index, txdata, fp); */
-
-	if (unlikely(bnx2x_tx_avail(bp, txdata) <
-		     (skb_shinfo(skb)->nr_frags + 3))) {
-		fp->eth_q_stats.driver_xoff++;
-		netif_tx_stop_queue(txq);
-		BNX2X_ERR("BUG! Tx ring full when queue awake!\n");
-		return NETDEV_TX_BUSY;
-	}
-
-	DP(NETIF_MSG_TX_QUEUED, "queue[%d]: SKB: summed %x  protocol %x  "
-				"protocol(%x,%x) gso type %x  xmit_type %x\n",
-	   txq_index, skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr,
-	   ip_hdr(skb)->protocol, skb_shinfo(skb)->gso_type, xmit_type);
-
-	eth = (struct ethhdr *)skb->data;
-
-	/* set flag according to packet type (UNICAST_ADDRESS is default)*/
-	if (unlikely(is_multicast_ether_addr(eth->h_dest))) {
-		if (is_broadcast_ether_addr(eth->h_dest))
-			mac_type = BROADCAST_ADDRESS;
-		else
-			mac_type = MULTICAST_ADDRESS;
-	}
-
-#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - 3)
-	/* First, check if we need to linearize the skb (due to FW
-	   restrictions). No need to check fragmentation if page size > 8K
-	   (there will be no violation to FW restrictions) */
-	if (bnx2x_pkt_req_lin(bp, skb, xmit_type)) {
-		/* Statistics of linearization */
-		bp->lin_cnt++;
-		if (skb_linearize(skb) != 0) {
-			DP(NETIF_MSG_TX_QUEUED, "SKB linearization failed - "
-			   "silently dropping this SKB\n");
-			dev_kfree_skb_any(skb);
-			return NETDEV_TX_OK;
-		}
-	}
-#endif
-	/* Map skb linear data for DMA */
-	mapping = dma_map_single(&bp->pdev->dev, skb->data,
-				 skb_headlen(skb), DMA_TO_DEVICE);
-	if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
-		DP(NETIF_MSG_TX_QUEUED, "SKB mapping failed - "
-		   "silently dropping this SKB\n");
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-	/*
-	Please read carefully. First we use one BD which we mark as start,
-	then we have a parsing info BD (used for TSO or xsum),
-	and only then we have the rest of the TSO BDs.
-	(don't forget to mark the last one as last,
-	and to unmap only AFTER you write to the BD ...)
-	And above all, all pdb sizes are in words - NOT DWORDS!
-	*/
-
-	/* get current pkt produced now - advance it just before sending packet
-	 * since mapping of pages may fail and cause packet to be dropped
-	 */
-	pkt_prod = txdata->tx_pkt_prod;
-	bd_prod = TX_BD(txdata->tx_bd_prod);
-
-	/* get a tx_buf and first BD
-	 * tx_start_bd may be changed during SPLIT,
-	 * but first_bd will always stay first
-	 */
-	tx_buf = &txdata->tx_buf_ring[TX_BD(pkt_prod)];
-	tx_start_bd = &txdata->tx_desc_ring[bd_prod].start_bd;
-	first_bd = tx_start_bd;
-
-	tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD;
-	SET_FLAG(tx_start_bd->general_data, ETH_TX_START_BD_ETH_ADDR_TYPE,
-		 mac_type);
-
-	/* header nbd */
-	SET_FLAG(tx_start_bd->general_data, ETH_TX_START_BD_HDR_NBDS, 1);
-
-	/* remember the first BD of the packet */
-	tx_buf->first_bd = txdata->tx_bd_prod;
-	tx_buf->skb = skb;
-	tx_buf->flags = 0;
-
-	DP(NETIF_MSG_TX_QUEUED,
-	   "sending pkt %u @%p  next_idx %u  bd %u @%p\n",
-	   pkt_prod, tx_buf, txdata->tx_pkt_prod, bd_prod, tx_start_bd);
-
-	if (vlan_tx_tag_present(skb)) {
-		tx_start_bd->vlan_or_ethertype =
-		    cpu_to_le16(vlan_tx_tag_get(skb));
-		tx_start_bd->bd_flags.as_bitfield |=
-		    (X_ETH_OUTBAND_VLAN << ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT);
-	} else
-		tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod);
-
-	/* turn on parsing and get a BD */
-	bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
-
-	if (xmit_type & XMIT_CSUM)
-		bnx2x_set_sbd_csum(bp, skb, tx_start_bd, xmit_type);
-
-	if (!CHIP_IS_E1x(bp)) {
-		pbd_e2 = &txdata->tx_desc_ring[bd_prod].parse_bd_e2;
-		memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
-		/* Set PBD in checksum offload case */
-		if (xmit_type & XMIT_CSUM)
-			hlen = bnx2x_set_pbd_csum_e2(bp, skb,
-						     &pbd_e2_parsing_data,
-						     xmit_type);
-		if (IS_MF_SI(bp)) {
-			/*
-			 * fill in the MAC addresses in the PBD - for local
-			 * switching
-			 */
-			bnx2x_set_fw_mac_addr(&pbd_e2->src_mac_addr_hi,
-					      &pbd_e2->src_mac_addr_mid,
-					      &pbd_e2->src_mac_addr_lo,
-					      eth->h_source);
-			bnx2x_set_fw_mac_addr(&pbd_e2->dst_mac_addr_hi,
-					      &pbd_e2->dst_mac_addr_mid,
-					      &pbd_e2->dst_mac_addr_lo,
-					      eth->h_dest);
-		}
-	} else {
-		pbd_e1x = &txdata->tx_desc_ring[bd_prod].parse_bd_e1x;
-		memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
-		/* Set PBD in checksum offload case */
-		if (xmit_type & XMIT_CSUM)
-			hlen = bnx2x_set_pbd_csum(bp, skb, pbd_e1x, xmit_type);
-
-	}
-
-	/* Setup the data pointer of the first BD of the packet */
-	tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
-	tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
-	nbd = 2; /* start_bd + pbd + frags (updated when pages are mapped) */
-	tx_start_bd->nbytes = cpu_to_le16(skb_headlen(skb));
-	pkt_size = tx_start_bd->nbytes;
-
-	DP(NETIF_MSG_TX_QUEUED, "first bd @%p  addr (%x:%x)  nbd %d"
-	   "  nbytes %d  flags %x  vlan %x\n",
-	   tx_start_bd, tx_start_bd->addr_hi, tx_start_bd->addr_lo,
-	   le16_to_cpu(tx_start_bd->nbd), le16_to_cpu(tx_start_bd->nbytes),
-	   tx_start_bd->bd_flags.as_bitfield,
-	   le16_to_cpu(tx_start_bd->vlan_or_ethertype));
-
-	if (xmit_type & XMIT_GSO) {
-
-		DP(NETIF_MSG_TX_QUEUED,
-		   "TSO packet len %d  hlen %d  total len %d  tso size %d\n",
-		   skb->len, hlen, skb_headlen(skb),
-		   skb_shinfo(skb)->gso_size);
-
-		tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_SW_LSO;
-
-		if (unlikely(skb_headlen(skb) > hlen))
-			bd_prod = bnx2x_tx_split(bp, txdata, tx_buf,
-						 &tx_start_bd, hlen,
-						 bd_prod, ++nbd);
-		if (!CHIP_IS_E1x(bp))
-			bnx2x_set_pbd_gso_e2(skb, &pbd_e2_parsing_data,
-					     xmit_type);
-		else
-			bnx2x_set_pbd_gso(skb, pbd_e1x, xmit_type);
-	}
-
-	/* Set the PBD's parsing_data field if not zero
-	 * (for the chips newer than 57711).
-	 */
-	if (pbd_e2_parsing_data)
-		pbd_e2->parsing_data = cpu_to_le32(pbd_e2_parsing_data);
-
-	tx_data_bd = (struct eth_tx_bd *)tx_start_bd;
-
-	/* Handle fragmented skb */
-	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
-		mapping = dma_map_page(&bp->pdev->dev, frag->page,
-				       frag->page_offset, frag->size,
-				       DMA_TO_DEVICE);
-		if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
-
-			DP(NETIF_MSG_TX_QUEUED, "Unable to map page - "
-						"dropping packet...\n");
-
-			/* we need unmap all buffers already mapped
-			 * for this SKB;
-			 * first_bd->nbd need to be properly updated
-			 * before call to bnx2x_free_tx_pkt
-			 */
-			first_bd->nbd = cpu_to_le16(nbd);
-			bnx2x_free_tx_pkt(bp, txdata,
-					  TX_BD(txdata->tx_pkt_prod));
-			return NETDEV_TX_OK;
-		}
-
-		bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
-		tx_data_bd = &txdata->tx_desc_ring[bd_prod].reg_bd;
-		if (total_pkt_bd == NULL)
-			total_pkt_bd = &txdata->tx_desc_ring[bd_prod].reg_bd;
-
-		tx_data_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
-		tx_data_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
-		tx_data_bd->nbytes = cpu_to_le16(frag->size);
-		le16_add_cpu(&pkt_size, frag->size);
-		nbd++;
-
-		DP(NETIF_MSG_TX_QUEUED,
-		   "frag %d  bd @%p  addr (%x:%x)  nbytes %d\n",
-		   i, tx_data_bd, tx_data_bd->addr_hi, tx_data_bd->addr_lo,
-		   le16_to_cpu(tx_data_bd->nbytes));
-	}
-
-	DP(NETIF_MSG_TX_QUEUED, "last bd @%p\n", tx_data_bd);
-
-	/* update with actual num BDs */
-	first_bd->nbd = cpu_to_le16(nbd);
-
-	bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
-
-	/* now send a tx doorbell, counting the next BD
-	 * if the packet contains or ends with it
-	 */
-	if (TX_BD_POFF(bd_prod) < nbd)
-		nbd++;
-
-	/* total_pkt_bytes should be set on the first data BD if
-	 * it's not an LSO packet and there is more than one
-	 * data BD. In this case pkt_size is limited by an MTU value.
-	 * However we prefer to set it for an LSO packet (while we don't
-	 * have to) in order to save some CPU cycles in a none-LSO
-	 * case, when we much more care about them.
-	 */
-	if (total_pkt_bd != NULL)
-		total_pkt_bd->total_pkt_bytes = pkt_size;
-
-	if (pbd_e1x)
-		DP(NETIF_MSG_TX_QUEUED,
-		   "PBD (E1X) @%p  ip_data %x  ip_hlen %u  ip_id %u  lso_mss %u"
-		   "  tcp_flags %x  xsum %x  seq %u  hlen %u\n",
-		   pbd_e1x, pbd_e1x->global_data, pbd_e1x->ip_hlen_w,
-		   pbd_e1x->ip_id, pbd_e1x->lso_mss, pbd_e1x->tcp_flags,
-		   pbd_e1x->tcp_pseudo_csum, pbd_e1x->tcp_send_seq,
-		    le16_to_cpu(pbd_e1x->total_hlen_w));
-	if (pbd_e2)
-		DP(NETIF_MSG_TX_QUEUED,
-		   "PBD (E2) @%p  dst %x %x %x src %x %x %x parsing_data %x\n",
-		   pbd_e2, pbd_e2->dst_mac_addr_hi, pbd_e2->dst_mac_addr_mid,
-		   pbd_e2->dst_mac_addr_lo, pbd_e2->src_mac_addr_hi,
-		   pbd_e2->src_mac_addr_mid, pbd_e2->src_mac_addr_lo,
-		   pbd_e2->parsing_data);
-	DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d  bd %u\n", nbd, bd_prod);
-
-	txdata->tx_pkt_prod++;
-	/*
-	 * Make sure that the BD data is updated before updating the producer
-	 * since FW might read the BD right after the producer is updated.
-	 * This is only applicable for weak-ordered memory model archs such
-	 * as IA-64. The following barrier is also mandatory since FW will
-	 * assumes packets must have BDs.
-	 */
-	wmb();
-
-	txdata->tx_db.data.prod += nbd;
-	barrier();
-
-	DOORBELL(bp, txdata->cid, txdata->tx_db.raw);
-
-	mmiowb();
-
-	txdata->tx_bd_prod += nbd;
-
-	if (unlikely(bnx2x_tx_avail(bp, txdata) < MAX_SKB_FRAGS + 3)) {
-		netif_tx_stop_queue(txq);
-
-		/* paired memory barrier is in bnx2x_tx_int(), we have to keep
-		 * ordering of set_bit() in netif_tx_stop_queue() and read of
-		 * fp->bd_tx_cons */
-		smp_mb();
-
-		fp->eth_q_stats.driver_xoff++;
-		if (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 3)
-			netif_tx_wake_queue(txq);
-	}
-	txdata->tx_pkt++;
-
-	return NETDEV_TX_OK;
-}
-
-/**
- * bnx2x_setup_tc - routine to configure net_device for multi tc
- *
- * @netdev: net device to configure
- * @tc: number of traffic classes to enable
- *
- * callback connected to the ndo_setup_tc function pointer
- */
-int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
-{
-	int cos, prio, count, offset;
-	struct bnx2x *bp = netdev_priv(dev);
-
-	/* setup tc must be called under rtnl lock */
-	ASSERT_RTNL();
-
-	/* no traffic classes requested. aborting */
-	if (!num_tc) {
-		netdev_reset_tc(dev);
-		return 0;
-	}
-
-	/* requested to support too many traffic classes */
-	if (num_tc > bp->max_cos) {
-		DP(NETIF_MSG_TX_ERR, "support for too many traffic classes"
-				     " requested: %d. max supported is %d",
-				     num_tc, bp->max_cos);
-		return -EINVAL;
-	}
-
-	/* declare amount of supported traffic classes */
-	if (netdev_set_num_tc(dev, num_tc)) {
-		DP(NETIF_MSG_TX_ERR, "failed to declare %d traffic classes",
-				     num_tc);
-		return -EINVAL;
-	}
-
-	/* configure priority to traffic class mapping */
-	for (prio = 0; prio < BNX2X_MAX_PRIORITY; prio++) {
-		netdev_set_prio_tc_map(dev, prio, bp->prio_to_cos[prio]);
-		DP(BNX2X_MSG_SP, "mapping priority %d to tc %d",
-		   prio, bp->prio_to_cos[prio]);
-	}
-
-
-	/* Use this configuration to diffrentiate tc0 from other COSes
-	   This can be used for ets or pfc, and save the effort of setting
-	   up a multio class queue disc or negotiating DCBX with a switch
-	netdev_set_prio_tc_map(dev, 0, 0);
-	DP(BNX2X_MSG_SP, "mapping priority %d to tc %d", 0, 0);
-	for (prio = 1; prio < 16; prio++) {
-		netdev_set_prio_tc_map(dev, prio, 1);
-		DP(BNX2X_MSG_SP, "mapping priority %d to tc %d", prio, 1);
-	} */
-
-	/* configure traffic class to transmission queue mapping */
-	for (cos = 0; cos < bp->max_cos; cos++) {
-		count = BNX2X_NUM_ETH_QUEUES(bp);
-		offset = cos * MAX_TXQS_PER_COS;
-		netdev_set_tc_queue(dev, cos, count, offset);
-		DP(BNX2X_MSG_SP, "mapping tc %d to offset %d count %d",
-		   cos, offset, count);
-	}
-
-	return 0;
-}
-
-/* called with rtnl_lock */
-int bnx2x_change_mac_addr(struct net_device *dev, void *p)
-{
-	struct sockaddr *addr = p;
-	struct bnx2x *bp = netdev_priv(dev);
-	int rc = 0;
-
-	if (!is_valid_ether_addr((u8 *)(addr->sa_data)))
-		return -EINVAL;
-
-	if (netif_running(dev))  {
-		rc = bnx2x_set_eth_mac(bp, false);
-		if (rc)
-			return rc;
-	}
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
-	if (netif_running(dev))
-		rc = bnx2x_set_eth_mac(bp, true);
-
-	return rc;
-}
-
-static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
-{
-	union host_hc_status_block *sb = &bnx2x_fp(bp, fp_index, status_blk);
-	struct bnx2x_fastpath *fp = &bp->fp[fp_index];
-	u8 cos;
-
-	/* Common */
-#ifdef BCM_CNIC
-	if (IS_FCOE_IDX(fp_index)) {
-		memset(sb, 0, sizeof(union host_hc_status_block));
-		fp->status_blk_mapping = 0;
-
-	} else {
-#endif
-		/* status blocks */
-		if (!CHIP_IS_E1x(bp))
-			BNX2X_PCI_FREE(sb->e2_sb,
-				       bnx2x_fp(bp, fp_index,
-						status_blk_mapping),
-				       sizeof(struct host_hc_status_block_e2));
-		else
-			BNX2X_PCI_FREE(sb->e1x_sb,
-				       bnx2x_fp(bp, fp_index,
-						status_blk_mapping),
-				       sizeof(struct host_hc_status_block_e1x));
-#ifdef BCM_CNIC
-	}
-#endif
-	/* Rx */
-	if (!skip_rx_queue(bp, fp_index)) {
-		bnx2x_free_rx_bds(fp);
-
-		/* fastpath rx rings: rx_buf rx_desc rx_comp */
-		BNX2X_FREE(bnx2x_fp(bp, fp_index, rx_buf_ring));
-		BNX2X_PCI_FREE(bnx2x_fp(bp, fp_index, rx_desc_ring),
-			       bnx2x_fp(bp, fp_index, rx_desc_mapping),
-			       sizeof(struct eth_rx_bd) * NUM_RX_BD);
-
-		BNX2X_PCI_FREE(bnx2x_fp(bp, fp_index, rx_comp_ring),
-			       bnx2x_fp(bp, fp_index, rx_comp_mapping),
-			       sizeof(struct eth_fast_path_rx_cqe) *
-			       NUM_RCQ_BD);
-
-		/* SGE ring */
-		BNX2X_FREE(bnx2x_fp(bp, fp_index, rx_page_ring));
-		BNX2X_PCI_FREE(bnx2x_fp(bp, fp_index, rx_sge_ring),
-			       bnx2x_fp(bp, fp_index, rx_sge_mapping),
-			       BCM_PAGE_SIZE * NUM_RX_SGE_PAGES);
-	}
-
-	/* Tx */
-	if (!skip_tx_queue(bp, fp_index)) {
-		/* fastpath tx rings: tx_buf tx_desc */
-		for_each_cos_in_tx_queue(fp, cos) {
-			struct bnx2x_fp_txdata *txdata = &fp->txdata[cos];
-
-			DP(BNX2X_MSG_SP,
-			   "freeing tx memory of fp %d cos %d cid %d",
-			   fp_index, cos, txdata->cid);
-
-			BNX2X_FREE(txdata->tx_buf_ring);
-			BNX2X_PCI_FREE(txdata->tx_desc_ring,
-				txdata->tx_desc_mapping,
-				sizeof(union eth_tx_bd_types) * NUM_TX_BD);
-		}
-	}
-	/* end of fastpath */
-}
-
-void bnx2x_free_fp_mem(struct bnx2x *bp)
-{
-	int i;
-	for_each_queue(bp, i)
-		bnx2x_free_fp_mem_at(bp, i);
-}
-
-static inline void set_sb_shortcuts(struct bnx2x *bp, int index)
-{
-	union host_hc_status_block status_blk = bnx2x_fp(bp, index, status_blk);
-	if (!CHIP_IS_E1x(bp)) {
-		bnx2x_fp(bp, index, sb_index_values) =
-			(__le16 *)status_blk.e2_sb->sb.index_values;
-		bnx2x_fp(bp, index, sb_running_index) =
-			(__le16 *)status_blk.e2_sb->sb.running_index;
-	} else {
-		bnx2x_fp(bp, index, sb_index_values) =
-			(__le16 *)status_blk.e1x_sb->sb.index_values;
-		bnx2x_fp(bp, index, sb_running_index) =
-			(__le16 *)status_blk.e1x_sb->sb.running_index;
-	}
-}
-
-static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
-{
-	union host_hc_status_block *sb;
-	struct bnx2x_fastpath *fp = &bp->fp[index];
-	int ring_size = 0;
-	u8 cos;
-	int rx_ring_size = 0;
-
-	/* if rx_ring_size specified - use it */
-	if (!bp->rx_ring_size) {
-
-		rx_ring_size = MAX_RX_AVAIL/BNX2X_NUM_RX_QUEUES(bp);
-
-		/* allocate at least number of buffers required by FW */
-		rx_ring_size = max_t(int, bp->disable_tpa ? MIN_RX_SIZE_NONTPA :
-				     MIN_RX_SIZE_TPA, rx_ring_size);
-
-		bp->rx_ring_size = rx_ring_size;
-	} else
-		rx_ring_size = bp->rx_ring_size;
-
-	/* Common */
-	sb = &bnx2x_fp(bp, index, status_blk);
-#ifdef BCM_CNIC
-	if (!IS_FCOE_IDX(index)) {
-#endif
-		/* status blocks */
-		if (!CHIP_IS_E1x(bp))
-			BNX2X_PCI_ALLOC(sb->e2_sb,
-				&bnx2x_fp(bp, index, status_blk_mapping),
-				sizeof(struct host_hc_status_block_e2));
-		else
-			BNX2X_PCI_ALLOC(sb->e1x_sb,
-				&bnx2x_fp(bp, index, status_blk_mapping),
-			    sizeof(struct host_hc_status_block_e1x));
-#ifdef BCM_CNIC
-	}
-#endif
-
-	/* FCoE Queue uses Default SB and doesn't ACK the SB, thus no need to
-	 * set shortcuts for it.
-	 */
-	if (!IS_FCOE_IDX(index))
-		set_sb_shortcuts(bp, index);
-
-	/* Tx */
-	if (!skip_tx_queue(bp, index)) {
-		/* fastpath tx rings: tx_buf tx_desc */
-		for_each_cos_in_tx_queue(fp, cos) {
-			struct bnx2x_fp_txdata *txdata = &fp->txdata[cos];
-
-			DP(BNX2X_MSG_SP, "allocating tx memory of "
-					 "fp %d cos %d",
-			   index, cos);
-
-			BNX2X_ALLOC(txdata->tx_buf_ring,
-				sizeof(struct sw_tx_bd) * NUM_TX_BD);
-			BNX2X_PCI_ALLOC(txdata->tx_desc_ring,
-				&txdata->tx_desc_mapping,
-				sizeof(union eth_tx_bd_types) * NUM_TX_BD);
-		}
-	}
-
-	/* Rx */
-	if (!skip_rx_queue(bp, index)) {
-		/* fastpath rx rings: rx_buf rx_desc rx_comp */
-		BNX2X_ALLOC(bnx2x_fp(bp, index, rx_buf_ring),
-				sizeof(struct sw_rx_bd) * NUM_RX_BD);
-		BNX2X_PCI_ALLOC(bnx2x_fp(bp, index, rx_desc_ring),
-				&bnx2x_fp(bp, index, rx_desc_mapping),
-				sizeof(struct eth_rx_bd) * NUM_RX_BD);
-
-		BNX2X_PCI_ALLOC(bnx2x_fp(bp, index, rx_comp_ring),
-				&bnx2x_fp(bp, index, rx_comp_mapping),
-				sizeof(struct eth_fast_path_rx_cqe) *
-				NUM_RCQ_BD);
-
-		/* SGE ring */
-		BNX2X_ALLOC(bnx2x_fp(bp, index, rx_page_ring),
-				sizeof(struct sw_rx_page) * NUM_RX_SGE);
-		BNX2X_PCI_ALLOC(bnx2x_fp(bp, index, rx_sge_ring),
-				&bnx2x_fp(bp, index, rx_sge_mapping),
-				BCM_PAGE_SIZE * NUM_RX_SGE_PAGES);
-		/* RX BD ring */
-		bnx2x_set_next_page_rx_bd(fp);
-
-		/* CQ ring */
-		bnx2x_set_next_page_rx_cq(fp);
-
-		/* BDs */
-		ring_size = bnx2x_alloc_rx_bds(fp, rx_ring_size);
-		if (ring_size < rx_ring_size)
-			goto alloc_mem_err;
-	}
-
-	return 0;
-
-/* handles low memory cases */
-alloc_mem_err:
-	BNX2X_ERR("Unable to allocate full memory for queue %d (size %d)\n",
-						index, ring_size);
-	/* FW will drop all packets if queue is not big enough,
-	 * In these cases we disable the queue
-	 * Min size is different for OOO, TPA and non-TPA queues
-	 */
-	if (ring_size < (fp->disable_tpa ?
-				MIN_RX_SIZE_NONTPA : MIN_RX_SIZE_TPA)) {
-			/* release memory allocated for this queue */
-			bnx2x_free_fp_mem_at(bp, index);
-			return -ENOMEM;
-	}
-	return 0;
-}
-
-int bnx2x_alloc_fp_mem(struct bnx2x *bp)
-{
-	int i;
-
-	/**
-	 * 1. Allocate FP for leading - fatal if error
-	 * 2. {CNIC} Allocate FCoE FP - fatal if error
-	 * 3. {CNIC} Allocate OOO + FWD - disable OOO if error
-	 * 4. Allocate RSS - fix number of queues if error
-	 */
-
-	/* leading */
-	if (bnx2x_alloc_fp_mem_at(bp, 0))
-		return -ENOMEM;
-
-#ifdef BCM_CNIC
-	if (!NO_FCOE(bp))
-		/* FCoE */
-		if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX))
-			/* we will fail load process instead of mark
-			 * NO_FCOE_FLAG
-			 */
-			return -ENOMEM;
-#endif
-
-	/* RSS */
-	for_each_nondefault_eth_queue(bp, i)
-		if (bnx2x_alloc_fp_mem_at(bp, i))
-			break;
-
-	/* handle memory failures */
-	if (i != BNX2X_NUM_ETH_QUEUES(bp)) {
-		int delta = BNX2X_NUM_ETH_QUEUES(bp) - i;
-
-		WARN_ON(delta < 0);
-#ifdef BCM_CNIC
-		/**
-		 * move non eth FPs next to last eth FP
-		 * must be done in that order
-		 * FCOE_IDX < FWD_IDX < OOO_IDX
-		 */
-
-		/* move FCoE fp even NO_FCOE_FLAG is on */
-		bnx2x_move_fp(bp, FCOE_IDX, FCOE_IDX - delta);
-#endif
-		bp->num_queues -= delta;
-		BNX2X_ERR("Adjusted num of queues from %d to %d\n",
-			  bp->num_queues + delta, bp->num_queues);
-	}
-
-	return 0;
-}
-
-void bnx2x_free_mem_bp(struct bnx2x *bp)
-{
-	kfree(bp->fp);
-	kfree(bp->msix_table);
-	kfree(bp->ilt);
-}
-
-int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
-{
-	struct bnx2x_fastpath *fp;
-	struct msix_entry *tbl;
-	struct bnx2x_ilt *ilt;
-	int msix_table_size = 0;
-
-	/*
-	 * The biggest MSI-X table we might need is as a maximum number of fast
-	 * path IGU SBs plus default SB (for PF).
-	 */
-	msix_table_size = bp->igu_sb_cnt + 1;
-
-	/* fp array: RSS plus CNIC related L2 queues */
-	fp = kzalloc((BNX2X_MAX_RSS_COUNT(bp) + NON_ETH_CONTEXT_USE) *
-		     sizeof(*fp), GFP_KERNEL);
-	if (!fp)
-		goto alloc_err;
-	bp->fp = fp;
-
-	/* msix table */
-	tbl = kzalloc(msix_table_size * sizeof(*tbl), GFP_KERNEL);
-	if (!tbl)
-		goto alloc_err;
-	bp->msix_table = tbl;
-
-	/* ilt */
-	ilt = kzalloc(sizeof(*ilt), GFP_KERNEL);
-	if (!ilt)
-		goto alloc_err;
-	bp->ilt = ilt;
-
-	return 0;
-alloc_err:
-	bnx2x_free_mem_bp(bp);
-	return -ENOMEM;
-
-}
-
-int bnx2x_reload_if_running(struct net_device *dev)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	if (unlikely(!netif_running(dev)))
-		return 0;
-
-	bnx2x_nic_unload(bp, UNLOAD_NORMAL);
-	return bnx2x_nic_load(bp, LOAD_NORMAL);
-}
-
-int bnx2x_get_cur_phy_idx(struct bnx2x *bp)
-{
-	u32 sel_phy_idx = 0;
-	if (bp->link_params.num_phys <= 1)
-		return INT_PHY;
-
-	if (bp->link_vars.link_up) {
-		sel_phy_idx = EXT_PHY1;
-		/* In case link is SERDES, check if the EXT_PHY2 is the one */
-		if ((bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) &&
-		    (bp->link_params.phy[EXT_PHY2].supported & SUPPORTED_FIBRE))
-			sel_phy_idx = EXT_PHY2;
-	} else {
-
-		switch (bnx2x_phy_selection(&bp->link_params)) {
-		case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
-		case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
-		case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
-		       sel_phy_idx = EXT_PHY1;
-		       break;
-		case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
-		case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
-		       sel_phy_idx = EXT_PHY2;
-		       break;
-		}
-	}
-
-	return sel_phy_idx;
-
-}
-int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
-{
-	u32 sel_phy_idx = bnx2x_get_cur_phy_idx(bp);
-	/*
-	 * The selected actived PHY is always after swapping (in case PHY
-	 * swapping is enabled). So when swapping is enabled, we need to reverse
-	 * the configuration
-	 */
-
-	if (bp->link_params.multi_phy_config &
-	    PORT_HW_CFG_PHY_SWAPPED_ENABLED) {
-		if (sel_phy_idx == EXT_PHY1)
-			sel_phy_idx = EXT_PHY2;
-		else if (sel_phy_idx == EXT_PHY2)
-			sel_phy_idx = EXT_PHY1;
-	}
-	return LINK_CONFIG_IDX(sel_phy_idx);
-}
-
-#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
-int bnx2x_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
-
-	switch (type) {
-	case NETDEV_FCOE_WWNN:
-		*wwn = HILO_U64(cp->fcoe_wwn_node_name_hi,
-				cp->fcoe_wwn_node_name_lo);
-		break;
-	case NETDEV_FCOE_WWPN:
-		*wwn = HILO_U64(cp->fcoe_wwn_port_name_hi,
-				cp->fcoe_wwn_port_name_lo);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-#endif
-
-/* called with rtnl_lock */
-int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
-		printk(KERN_ERR "Handling parity error recovery. Try again later\n");
-		return -EAGAIN;
-	}
-
-	if ((new_mtu > ETH_MAX_JUMBO_PACKET_SIZE) ||
-	    ((new_mtu + ETH_HLEN) < ETH_MIN_PACKET_SIZE))
-		return -EINVAL;
-
-	/* This does not race with packet allocation
-	 * because the actual alloc size is
-	 * only updated as part of load
-	 */
-	dev->mtu = new_mtu;
-
-	return bnx2x_reload_if_running(dev);
-}
-
-u32 bnx2x_fix_features(struct net_device *dev, u32 features)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	/* TPA requires Rx CSUM offloading */
-	if (!(features & NETIF_F_RXCSUM) || bp->disable_tpa)
-		features &= ~NETIF_F_LRO;
-
-	return features;
-}
-
-int bnx2x_set_features(struct net_device *dev, u32 features)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	u32 flags = bp->flags;
-	bool bnx2x_reload = false;
-
-	if (features & NETIF_F_LRO)
-		flags |= TPA_ENABLE_FLAG;
-	else
-		flags &= ~TPA_ENABLE_FLAG;
-
-	if (features & NETIF_F_LOOPBACK) {
-		if (bp->link_params.loopback_mode != LOOPBACK_BMAC) {
-			bp->link_params.loopback_mode = LOOPBACK_BMAC;
-			bnx2x_reload = true;
-		}
-	} else {
-		if (bp->link_params.loopback_mode != LOOPBACK_NONE) {
-			bp->link_params.loopback_mode = LOOPBACK_NONE;
-			bnx2x_reload = true;
-		}
-	}
-
-	if (flags ^ bp->flags) {
-		bp->flags = flags;
-		bnx2x_reload = true;
-	}
-
-	if (bnx2x_reload) {
-		if (bp->recovery_state == BNX2X_RECOVERY_DONE)
-			return bnx2x_reload_if_running(dev);
-		/* else: bnx2x_nic_load() will be called at end of recovery */
-	}
-
-	return 0;
-}
-
-void bnx2x_tx_timeout(struct net_device *dev)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-#ifdef BNX2X_STOP_ON_ERROR
-	if (!bp->panic)
-		bnx2x_panic();
-#endif
-
-	smp_mb__before_clear_bit();
-	set_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state);
-	smp_mb__after_clear_bit();
-
-	/* This allows the netif to be shutdown gracefully before resetting */
-	schedule_delayed_work(&bp->sp_rtnl_task, 0);
-}
-
-int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct bnx2x *bp;
-
-	if (!dev) {
-		dev_err(&pdev->dev, "BAD net device from bnx2x_init_one\n");
-		return -ENODEV;
-	}
-	bp = netdev_priv(dev);
-
-	rtnl_lock();
-
-	pci_save_state(pdev);
-
-	if (!netif_running(dev)) {
-		rtnl_unlock();
-		return 0;
-	}
-
-	netif_device_detach(dev);
-
-	bnx2x_nic_unload(bp, UNLOAD_CLOSE);
-
-	bnx2x_set_power_state(bp, pci_choose_state(pdev, state));
-
-	rtnl_unlock();
-
-	return 0;
-}
-
-int bnx2x_resume(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct bnx2x *bp;
-	int rc;
-
-	if (!dev) {
-		dev_err(&pdev->dev, "BAD net device from bnx2x_init_one\n");
-		return -ENODEV;
-	}
-	bp = netdev_priv(dev);
-
-	if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
-		printk(KERN_ERR "Handling parity error recovery. Try again later\n");
-		return -EAGAIN;
-	}
-
-	rtnl_lock();
-
-	pci_restore_state(pdev);
-
-	if (!netif_running(dev)) {
-		rtnl_unlock();
-		return 0;
-	}
-
-	bnx2x_set_power_state(bp, PCI_D0);
-	netif_device_attach(dev);
-
-	/* Since the chip was reset, clear the FW sequence number */
-	bp->fw_seq = 0;
-	rc = bnx2x_nic_load(bp, LOAD_OPEN);
-
-	rtnl_unlock();
-
-	return rc;
-}
-
-
-void bnx2x_set_ctx_validation(struct bnx2x *bp, struct eth_context *cxt,
-			      u32 cid)
-{
-	/* ustorm cxt validation */
-	cxt->ustorm_ag_context.cdu_usage =
-		CDU_RSRVD_VALUE_TYPE_A(HW_CID(bp, cid),
-			CDU_REGION_NUMBER_UCM_AG, ETH_CONNECTION_TYPE);
-	/* xcontext validation */
-	cxt->xstorm_ag_context.cdu_reserved =
-		CDU_RSRVD_VALUE_TYPE_A(HW_CID(bp, cid),
-			CDU_REGION_NUMBER_XCM_AG, ETH_CONNECTION_TYPE);
-}
-
-static inline void storm_memset_hc_timeout(struct bnx2x *bp, u8 port,
-					     u8 fw_sb_id, u8 sb_index,
-					     u8 ticks)
-{
-
-	u32 addr = BAR_CSTRORM_INTMEM +
-		   CSTORM_STATUS_BLOCK_DATA_TIMEOUT_OFFSET(fw_sb_id, sb_index);
-	REG_WR8(bp, addr, ticks);
-	DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d ticks %d\n",
-			  port, fw_sb_id, sb_index, ticks);
-}
-
-static inline void storm_memset_hc_disable(struct bnx2x *bp, u8 port,
-					     u16 fw_sb_id, u8 sb_index,
-					     u8 disable)
-{
-	u32 enable_flag = disable ? 0 : (1 << HC_INDEX_DATA_HC_ENABLED_SHIFT);
-	u32 addr = BAR_CSTRORM_INTMEM +
-		   CSTORM_STATUS_BLOCK_DATA_FLAGS_OFFSET(fw_sb_id, sb_index);
-	u16 flags = REG_RD16(bp, addr);
-	/* clear and set */
-	flags &= ~HC_INDEX_DATA_HC_ENABLED;
-	flags |= enable_flag;
-	REG_WR16(bp, addr, flags);
-	DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d disable %d\n",
-			  port, fw_sb_id, sb_index, disable);
-}
-
-void bnx2x_update_coalesce_sb_index(struct bnx2x *bp, u8 fw_sb_id,
-				    u8 sb_index, u8 disable, u16 usec)
-{
-	int port = BP_PORT(bp);
-	u8 ticks = usec / BNX2X_BTR;
-
-	storm_memset_hc_timeout(bp, port, fw_sb_id, sb_index, ticks);
-
-	disable = disable ? 1 : (usec ? 0 : 1);
-	storm_memset_hc_disable(bp, port, fw_sb_id, sb_index, disable);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_cmn.h linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_cmn.h
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_cmn.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_cmn.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1491 +0,0 @@
-/* bnx2x_cmn.h: Broadcom Everest network driver.
- *
- * Copyright (c) 2007-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
- * the Free Software Foundation.
- *
- * Maintained by: Eilon Greenstein <eilong@broadcom.com>
- * Written by: Eliezer Tamir
- * Based on code from Michael Chan's bnx2 driver
- * UDP CSUM errata workaround by Arik Gendelman
- * Slowpath and fastpath rework by Vladislav Zolotarov
- * Statistics and Link management by Yitchak Gertner
- *
- */
-#ifndef BNX2X_CMN_H
-#define BNX2X_CMN_H
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-
-
-#include "bnx2x.h"
-
-/* This is used as a replacement for an MCP if it's not present */
-extern int load_count[2][3]; /* per-path: 0-common, 1-port0, 2-port1 */
-
-extern int num_queues;
-
-/************************ Macros ********************************/
-#define BNX2X_PCI_FREE(x, y, size) \
-	do { \
-		if (x) { \
-			dma_free_coherent(&bp->pdev->dev, size, (void *)x, y); \
-			x = NULL; \
-			y = 0; \
-		} \
-	} while (0)
-
-#define BNX2X_FREE(x) \
-	do { \
-		if (x) { \
-			kfree((void *)x); \
-			x = NULL; \
-		} \
-	} while (0)
-
-#define BNX2X_PCI_ALLOC(x, y, size) \
-	do { \
-		x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
-		if (x == NULL) \
-			goto alloc_mem_err; \
-		memset((void *)x, 0, size); \
-	} while (0)
-
-#define BNX2X_ALLOC(x, size) \
-	do { \
-		x = kzalloc(size, GFP_KERNEL); \
-		if (x == NULL) \
-			goto alloc_mem_err; \
-	} while (0)
-
-/*********************** Interfaces ****************************
- *  Functions that need to be implemented by each driver version
- */
-/* Init */
-
-/**
- * bnx2x_send_unload_req - request unload mode from the MCP.
- *
- * @bp:			driver handle
- * @unload_mode:	requested function's unload mode
- *
- * Return unload mode returned by the MCP: COMMON, PORT or FUNC.
- */
-u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode);
-
-/**
- * bnx2x_send_unload_done - send UNLOAD_DONE command to the MCP.
- *
- * @bp:		driver handle
- */
-void bnx2x_send_unload_done(struct bnx2x *bp);
-
-/**
- * bnx2x_config_rss_pf - configure RSS parameters.
- *
- * @bp:			driver handle
- * @ind_table:		indirection table to configure
- * @config_hash:	re-configure RSS hash keys configuration
- */
-int bnx2x_config_rss_pf(struct bnx2x *bp, u8 *ind_table, bool config_hash);
-
-/**
- * bnx2x__init_func_obj - init function object
- *
- * @bp:			driver handle
- *
- * Initializes the Function Object with the appropriate
- * parameters which include a function slow path driver
- * interface.
- */
-void bnx2x__init_func_obj(struct bnx2x *bp);
-
-/**
- * bnx2x_setup_queue - setup eth queue.
- *
- * @bp:		driver handle
- * @fp:		pointer to the fastpath structure
- * @leading:	boolean
- *
- */
-int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
-		       bool leading);
-
-/**
- * bnx2x_setup_leading - bring up a leading eth queue.
- *
- * @bp:		driver handle
- */
-int bnx2x_setup_leading(struct bnx2x *bp);
-
-/**
- * bnx2x_fw_command - send the MCP a request
- *
- * @bp:		driver handle
- * @command:	request
- * @param:	request's parameter
- *
- * block until there is a reply
- */
-u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param);
-
-/**
- * bnx2x_initial_phy_init - initialize link parameters structure variables.
- *
- * @bp:		driver handle
- * @load_mode:	current mode
- */
-u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode);
-
-/**
- * bnx2x_link_set - configure hw according to link parameters structure.
- *
- * @bp:		driver handle
- */
-void bnx2x_link_set(struct bnx2x *bp);
-
-/**
- * bnx2x_link_test - query link status.
- *
- * @bp:		driver handle
- * @is_serdes:	bool
- *
- * Returns 0 if link is UP.
- */
-u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes);
-
-/**
- * bnx2x_drv_pulse - write driver pulse to shmem
- *
- * @bp:		driver handle
- *
- * writes the value in bp->fw_drv_pulse_wr_seq to drv_pulse mbox
- * in the shmem.
- */
-void bnx2x_drv_pulse(struct bnx2x *bp);
-
-/**
- * bnx2x_igu_ack_sb - update IGU with current SB value
- *
- * @bp:		driver handle
- * @igu_sb_id:	SB id
- * @segment:	SB segment
- * @index:	SB index
- * @op:		SB operation
- * @update:	is HW update required
- */
-void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment,
-		      u16 index, u8 op, u8 update);
-
-/* Disable transactions from chip to host */
-void bnx2x_pf_disable(struct bnx2x *bp);
-
-/**
- * bnx2x__link_status_update - handles link status change.
- *
- * @bp:		driver handle
- */
-void bnx2x__link_status_update(struct bnx2x *bp);
-
-/**
- * bnx2x_link_report - report link status to upper layer.
- *
- * @bp:		driver handle
- */
-void bnx2x_link_report(struct bnx2x *bp);
-
-/* None-atomic version of bnx2x_link_report() */
-void __bnx2x_link_report(struct bnx2x *bp);
-
-/**
- * bnx2x_get_mf_speed - calculate MF speed.
- *
- * @bp:		driver handle
- *
- * Takes into account current linespeed and MF configuration.
- */
-u16 bnx2x_get_mf_speed(struct bnx2x *bp);
-
-/**
- * bnx2x_msix_sp_int - MSI-X slowpath interrupt handler
- *
- * @irq:		irq number
- * @dev_instance:	private instance
- */
-irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance);
-
-/**
- * bnx2x_interrupt - non MSI-X interrupt handler
- *
- * @irq:		irq number
- * @dev_instance:	private instance
- */
-irqreturn_t bnx2x_interrupt(int irq, void *dev_instance);
-#ifdef BCM_CNIC
-
-/**
- * bnx2x_cnic_notify - send command to cnic driver
- *
- * @bp:		driver handle
- * @cmd:	command
- */
-int bnx2x_cnic_notify(struct bnx2x *bp, int cmd);
-
-/**
- * bnx2x_setup_cnic_irq_info - provides cnic with IRQ information
- *
- * @bp:		driver handle
- */
-void bnx2x_setup_cnic_irq_info(struct bnx2x *bp);
-#endif
-
-/**
- * bnx2x_int_enable - enable HW interrupts.
- *
- * @bp:		driver handle
- */
-void bnx2x_int_enable(struct bnx2x *bp);
-
-/**
- * bnx2x_int_disable_sync - disable interrupts.
- *
- * @bp:		driver handle
- * @disable_hw:	true, disable HW interrupts.
- *
- * This function ensures that there are no
- * ISRs or SP DPCs (sp_task) are running after it returns.
- */
-void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw);
-
-/**
- * bnx2x_nic_init - init driver internals.
- *
- * @bp:		driver handle
- * @load_code:	COMMON, PORT or FUNCTION
- *
- * Initializes:
- *  - rings
- *  - status blocks
- *  - etc.
- */
-void bnx2x_nic_init(struct bnx2x *bp, u32 load_code);
-
-/**
- * bnx2x_alloc_mem - allocate driver's memory.
- *
- * @bp:		driver handle
- */
-int bnx2x_alloc_mem(struct bnx2x *bp);
-
-/**
- * bnx2x_free_mem - release driver's memory.
- *
- * @bp:		driver handle
- */
-void bnx2x_free_mem(struct bnx2x *bp);
-
-/**
- * bnx2x_set_num_queues - set number of queues according to mode.
- *
- * @bp:		driver handle
- */
-void bnx2x_set_num_queues(struct bnx2x *bp);
-
-/**
- * bnx2x_chip_cleanup - cleanup chip internals.
- *
- * @bp:			driver handle
- * @unload_mode:	COMMON, PORT, FUNCTION
- *
- * - Cleanup MAC configuration.
- * - Closes clients.
- * - etc.
- */
-void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode);
-
-/**
- * bnx2x_acquire_hw_lock - acquire HW lock.
- *
- * @bp:		driver handle
- * @resource:	resource bit which was locked
- */
-int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource);
-
-/**
- * bnx2x_release_hw_lock - release HW lock.
- *
- * @bp:		driver handle
- * @resource:	resource bit which was locked
- */
-int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource);
-
-/**
- * bnx2x_release_leader_lock - release recovery leader lock
- *
- * @bp:		driver handle
- */
-int bnx2x_release_leader_lock(struct bnx2x *bp);
-
-/**
- * bnx2x_set_eth_mac - configure eth MAC address in the HW
- *
- * @bp:		driver handle
- * @set:	set or clear
- *
- * Configures according to the value in netdev->dev_addr.
- */
-int bnx2x_set_eth_mac(struct bnx2x *bp, bool set);
-
-/**
- * bnx2x_set_rx_mode - set MAC filtering configurations.
- *
- * @dev:	netdevice
- *
- * called with netif_tx_lock from dev_mcast.c
- * If bp->state is OPEN, should be called with
- * netif_addr_lock_bh()
- */
-void bnx2x_set_rx_mode(struct net_device *dev);
-
-/**
- * bnx2x_set_storm_rx_mode - configure MAC filtering rules in a FW.
- *
- * @bp:		driver handle
- *
- * If bp->state is OPEN, should be called with
- * netif_addr_lock_bh().
- */
-void bnx2x_set_storm_rx_mode(struct bnx2x *bp);
-
-/**
- * bnx2x_set_q_rx_mode - configures rx_mode for a single queue.
- *
- * @bp:			driver handle
- * @cl_id:		client id
- * @rx_mode_flags:	rx mode configuration
- * @rx_accept_flags:	rx accept configuration
- * @tx_accept_flags:	tx accept configuration (tx switch)
- * @ramrod_flags:	ramrod configuration
- */
-void bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
-			 unsigned long rx_mode_flags,
-			 unsigned long rx_accept_flags,
-			 unsigned long tx_accept_flags,
-			 unsigned long ramrod_flags);
-
-/* Parity errors related */
-void bnx2x_inc_load_cnt(struct bnx2x *bp);
-u32 bnx2x_dec_load_cnt(struct bnx2x *bp);
-bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print);
-bool bnx2x_reset_is_done(struct bnx2x *bp, int engine);
-void bnx2x_set_reset_in_progress(struct bnx2x *bp);
-void bnx2x_set_reset_global(struct bnx2x *bp);
-void bnx2x_disable_close_the_gate(struct bnx2x *bp);
-
-/**
- * bnx2x_sp_event - handle ramrods completion.
- *
- * @fp:		fastpath handle for the event
- * @rr_cqe:	eth_rx_cqe
- */
-void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe);
-
-/**
- * bnx2x_ilt_set_info - prepare ILT configurations.
- *
- * @bp:		driver handle
- */
-void bnx2x_ilt_set_info(struct bnx2x *bp);
-
-/**
- * bnx2x_dcbx_init - initialize dcbx protocol.
- *
- * @bp:		driver handle
- */
-void bnx2x_dcbx_init(struct bnx2x *bp);
-
-/**
- * bnx2x_set_power_state - set power state to the requested value.
- *
- * @bp:		driver handle
- * @state:	required state D0 or D3hot
- *
- * Currently only D0 and D3hot are supported.
- */
-int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state);
-
-/**
- * bnx2x_update_max_mf_config - update MAX part of MF configuration in HW.
- *
- * @bp:		driver handle
- * @value:	new value
- */
-void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value);
-/* Error handling */
-void bnx2x_panic_dump(struct bnx2x *bp);
-
-void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl);
-
-/* dev_close main block */
-int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode);
-
-/* dev_open main block */
-int bnx2x_nic_load(struct bnx2x *bp, int load_mode);
-
-/* hard_xmit callback */
-netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev);
-
-/* setup_tc callback */
-int bnx2x_setup_tc(struct net_device *dev, u8 num_tc);
-
-/* select_queue callback */
-u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb);
-
-/* reload helper */
-int bnx2x_reload_if_running(struct net_device *dev);
-
-int bnx2x_change_mac_addr(struct net_device *dev, void *p);
-
-/* NAPI poll Rx part */
-int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget);
-
-void bnx2x_update_rx_prod(struct bnx2x *bp, struct bnx2x_fastpath *fp,
-			u16 bd_prod, u16 rx_comp_prod, u16 rx_sge_prod);
-
-/* NAPI poll Tx part */
-int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata);
-
-/* suspend/resume callbacks */
-int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state);
-int bnx2x_resume(struct pci_dev *pdev);
-
-/* Release IRQ vectors */
-void bnx2x_free_irq(struct bnx2x *bp);
-
-void bnx2x_free_fp_mem(struct bnx2x *bp);
-int bnx2x_alloc_fp_mem(struct bnx2x *bp);
-void bnx2x_init_rx_rings(struct bnx2x *bp);
-void bnx2x_free_skbs(struct bnx2x *bp);
-void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw);
-void bnx2x_netif_start(struct bnx2x *bp);
-
-/**
- * bnx2x_enable_msix - set msix configuration.
- *
- * @bp:		driver handle
- *
- * fills msix_table, requests vectors, updates num_queues
- * according to number of available vectors.
- */
-int bnx2x_enable_msix(struct bnx2x *bp);
-
-/**
- * bnx2x_enable_msi - request msi mode from OS, updated internals accordingly
- *
- * @bp:		driver handle
- */
-int bnx2x_enable_msi(struct bnx2x *bp);
-
-/**
- * bnx2x_poll - NAPI callback
- *
- * @napi:	napi structure
- * @budget:
- *
- */
-int bnx2x_poll(struct napi_struct *napi, int budget);
-
-/**
- * bnx2x_alloc_mem_bp - allocate memories outsize main driver structure
- *
- * @bp:		driver handle
- */
-int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp);
-
-/**
- * bnx2x_free_mem_bp - release memories outsize main driver structure
- *
- * @bp:		driver handle
- */
-void bnx2x_free_mem_bp(struct bnx2x *bp);
-
-/**
- * bnx2x_change_mtu - change mtu netdev callback
- *
- * @dev:	net device
- * @new_mtu:	requested mtu
- *
- */
-int bnx2x_change_mtu(struct net_device *dev, int new_mtu);
-
-#if defined(BCM_CNIC) && (defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE))
-/**
- * bnx2x_fcoe_get_wwn - return the requested WWN value for this port
- *
- * @dev:	net_device
- * @wwn:	output buffer
- * @type:	WWN type: NETDEV_FCOE_WWNN (node) or NETDEV_FCOE_WWPN (port)
- *
- */
-int bnx2x_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type);
-#endif
-u32 bnx2x_fix_features(struct net_device *dev, u32 features);
-int bnx2x_set_features(struct net_device *dev, u32 features);
-
-/**
- * bnx2x_tx_timeout - tx timeout netdev callback
- *
- * @dev:	net device
- */
-void bnx2x_tx_timeout(struct net_device *dev);
-
-/*********************** Inlines **********************************/
-/*********************** Fast path ********************************/
-static inline void bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp)
-{
-	barrier(); /* status block is written to by the chip */
-	fp->fp_hc_idx = fp->sb_running_index[SM_RX_ID];
-}
-
-static inline void bnx2x_update_rx_prod_gen(struct bnx2x *bp,
-			struct bnx2x_fastpath *fp, u16 bd_prod,
-			u16 rx_comp_prod, u16 rx_sge_prod, u32 start)
-{
-	struct ustorm_eth_rx_producers rx_prods = {0};
-	u32 i;
-
-	/* Update producers */
-	rx_prods.bd_prod = bd_prod;
-	rx_prods.cqe_prod = rx_comp_prod;
-	rx_prods.sge_prod = rx_sge_prod;
-
-	/*
-	 * Make sure that the BD and SGE data is updated before updating the
-	 * producers since FW might read the BD/SGE right after the producer
-	 * is updated.
-	 * This is only applicable for weak-ordered memory model archs such
-	 * as IA-64. The following barrier is also mandatory since FW will
-	 * assumes BDs must have buffers.
-	 */
-	wmb();
-
-	for (i = 0; i < sizeof(rx_prods)/4; i++)
-		REG_WR(bp, start + i*4, ((u32 *)&rx_prods)[i]);
-
-	mmiowb(); /* keep prod updates ordered */
-
-	DP(NETIF_MSG_RX_STATUS,
-	   "queue[%d]:  wrote  bd_prod %u  cqe_prod %u  sge_prod %u\n",
-	   fp->index, bd_prod, rx_comp_prod, rx_sge_prod);
-}
-
-static inline void bnx2x_igu_ack_sb_gen(struct bnx2x *bp, u8 igu_sb_id,
-					u8 segment, u16 index, u8 op,
-					u8 update, u32 igu_addr)
-{
-	struct igu_regular cmd_data = {0};
-
-	cmd_data.sb_id_and_flags =
-			((index << IGU_REGULAR_SB_INDEX_SHIFT) |
-			 (segment << IGU_REGULAR_SEGMENT_ACCESS_SHIFT) |
-			 (update << IGU_REGULAR_BUPDATE_SHIFT) |
-			 (op << IGU_REGULAR_ENABLE_INT_SHIFT));
-
-	DP(NETIF_MSG_HW, "write 0x%08x to IGU addr 0x%x\n",
-	   cmd_data.sb_id_and_flags, igu_addr);
-	REG_WR(bp, igu_addr, cmd_data.sb_id_and_flags);
-
-	/* Make sure that ACK is written */
-	mmiowb();
-	barrier();
-}
-
-static inline void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func,
-					  u8 idu_sb_id, bool is_Pf)
-{
-	u32 data, ctl, cnt = 100;
-	u32 igu_addr_data = IGU_REG_COMMAND_REG_32LSB_DATA;
-	u32 igu_addr_ctl = IGU_REG_COMMAND_REG_CTRL;
-	u32 igu_addr_ack = IGU_REG_CSTORM_TYPE_0_SB_CLEANUP + (idu_sb_id/32)*4;
-	u32 sb_bit =  1 << (idu_sb_id%32);
-	u32 func_encode = func |
-			((is_Pf == true ? 1 : 0) << IGU_FID_ENCODE_IS_PF_SHIFT);
-	u32 addr_encode = IGU_CMD_E2_PROD_UPD_BASE + idu_sb_id;
-
-	/* Not supported in BC mode */
-	if (CHIP_INT_MODE_IS_BC(bp))
-		return;
-
-	data = (IGU_USE_REGISTER_cstorm_type_0_sb_cleanup
-			<< IGU_REGULAR_CLEANUP_TYPE_SHIFT)	|
-		IGU_REGULAR_CLEANUP_SET				|
-		IGU_REGULAR_BCLEANUP;
-
-	ctl = addr_encode << IGU_CTRL_REG_ADDRESS_SHIFT		|
-	      func_encode << IGU_CTRL_REG_FID_SHIFT		|
-	      IGU_CTRL_CMD_TYPE_WR << IGU_CTRL_REG_TYPE_SHIFT;
-
-	DP(NETIF_MSG_HW, "write 0x%08x to IGU(via GRC) addr 0x%x\n",
-			 data, igu_addr_data);
-	REG_WR(bp, igu_addr_data, data);
-	mmiowb();
-	barrier();
-	DP(NETIF_MSG_HW, "write 0x%08x to IGU(via GRC) addr 0x%x\n",
-			  ctl, igu_addr_ctl);
-	REG_WR(bp, igu_addr_ctl, ctl);
-	mmiowb();
-	barrier();
-
-	/* wait for clean up to finish */
-	while (!(REG_RD(bp, igu_addr_ack) & sb_bit) && --cnt)
-		msleep(20);
-
-
-	if (!(REG_RD(bp, igu_addr_ack) & sb_bit)) {
-		DP(NETIF_MSG_HW, "Unable to finish IGU cleanup: "
-			  "idu_sb_id %d offset %d bit %d (cnt %d)\n",
-			  idu_sb_id, idu_sb_id/32, idu_sb_id%32, cnt);
-	}
-}
-
-static inline void bnx2x_hc_ack_sb(struct bnx2x *bp, u8 sb_id,
-				   u8 storm, u16 index, u8 op, u8 update)
-{
-	u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp)*32 +
-		       COMMAND_REG_INT_ACK);
-	struct igu_ack_register igu_ack;
-
-	igu_ack.status_block_index = index;
-	igu_ack.sb_id_and_flags =
-			((sb_id << IGU_ACK_REGISTER_STATUS_BLOCK_ID_SHIFT) |
-			 (storm << IGU_ACK_REGISTER_STORM_ID_SHIFT) |
-			 (update << IGU_ACK_REGISTER_UPDATE_INDEX_SHIFT) |
-			 (op << IGU_ACK_REGISTER_INTERRUPT_MODE_SHIFT));
-
-	DP(BNX2X_MSG_OFF, "write 0x%08x to HC addr 0x%x\n",
-	   (*(u32 *)&igu_ack), hc_addr);
-	REG_WR(bp, hc_addr, (*(u32 *)&igu_ack));
-
-	/* Make sure that ACK is written */
-	mmiowb();
-	barrier();
-}
-
-static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 storm,
-				u16 index, u8 op, u8 update)
-{
-	if (bp->common.int_block == INT_BLOCK_HC)
-		bnx2x_hc_ack_sb(bp, igu_sb_id, storm, index, op, update);
-	else {
-		u8 segment;
-
-		if (CHIP_INT_MODE_IS_BC(bp))
-			segment = storm;
-		else if (igu_sb_id != bp->igu_dsb_id)
-			segment = IGU_SEG_ACCESS_DEF;
-		else if (storm == ATTENTION_ID)
-			segment = IGU_SEG_ACCESS_ATTN;
-		else
-			segment = IGU_SEG_ACCESS_DEF;
-		bnx2x_igu_ack_sb(bp, igu_sb_id, segment, index, op, update);
-	}
-}
-
-static inline u16 bnx2x_hc_ack_int(struct bnx2x *bp)
-{
-	u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp)*32 +
-		       COMMAND_REG_SIMD_MASK);
-	u32 result = REG_RD(bp, hc_addr);
-
-	DP(BNX2X_MSG_OFF, "read 0x%08x from HC addr 0x%x\n",
-	   result, hc_addr);
-
-	barrier();
-	return result;
-}
-
-static inline u16 bnx2x_igu_ack_int(struct bnx2x *bp)
-{
-	u32 igu_addr = (BAR_IGU_INTMEM + IGU_REG_SISR_MDPC_WMASK_LSB_UPPER*8);
-	u32 result = REG_RD(bp, igu_addr);
-
-	DP(NETIF_MSG_HW, "read 0x%08x from IGU addr 0x%x\n",
-	   result, igu_addr);
-
-	barrier();
-	return result;
-}
-
-static inline u16 bnx2x_ack_int(struct bnx2x *bp)
-{
-	barrier();
-	if (bp->common.int_block == INT_BLOCK_HC)
-		return bnx2x_hc_ack_int(bp);
-	else
-		return bnx2x_igu_ack_int(bp);
-}
-
-static inline int bnx2x_has_tx_work_unload(struct bnx2x_fp_txdata *txdata)
-{
-	/* Tell compiler that consumer and producer can change */
-	barrier();
-	return txdata->tx_pkt_prod != txdata->tx_pkt_cons;
-}
-
-static inline u16 bnx2x_tx_avail(struct bnx2x *bp,
-				 struct bnx2x_fp_txdata *txdata)
-{
-	s16 used;
-	u16 prod;
-	u16 cons;
-
-	prod = txdata->tx_bd_prod;
-	cons = txdata->tx_bd_cons;
-
-	/* NUM_TX_RINGS = number of "next-page" entries
-	   It will be used as a threshold */
-	used = SUB_S16(prod, cons) + (s16)NUM_TX_RINGS;
-
-#ifdef BNX2X_STOP_ON_ERROR
-	WARN_ON(used < 0);
-	WARN_ON(used > bp->tx_ring_size);
-	WARN_ON((bp->tx_ring_size - used) > MAX_TX_AVAIL);
-#endif
-
-	return (s16)(bp->tx_ring_size) - used;
-}
-
-static inline int bnx2x_tx_queue_has_work(struct bnx2x_fp_txdata *txdata)
-{
-	u16 hw_cons;
-
-	/* Tell compiler that status block fields can change */
-	barrier();
-	hw_cons = le16_to_cpu(*txdata->tx_cons_sb);
-	return hw_cons != txdata->tx_pkt_cons;
-}
-
-static inline bool bnx2x_has_tx_work(struct bnx2x_fastpath *fp)
-{
-	u8 cos;
-	for_each_cos_in_tx_queue(fp, cos)
-		if (bnx2x_tx_queue_has_work(&fp->txdata[cos]))
-			return true;
-	return false;
-}
-
-static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp)
-{
-	u16 rx_cons_sb;
-
-	/* Tell compiler that status block fields can change */
-	barrier();
-	rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb);
-	if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
-		rx_cons_sb++;
-	return (fp->rx_comp_cons != rx_cons_sb);
-}
-
-/**
- * bnx2x_tx_disable - disables tx from stack point of view
- *
- * @bp:		driver handle
- */
-static inline void bnx2x_tx_disable(struct bnx2x *bp)
-{
-	netif_tx_disable(bp->dev);
-	netif_carrier_off(bp->dev);
-}
-
-static inline void bnx2x_free_rx_sge(struct bnx2x *bp,
-				     struct bnx2x_fastpath *fp, u16 index)
-{
-	struct sw_rx_page *sw_buf = &fp->rx_page_ring[index];
-	struct page *page = sw_buf->page;
-	struct eth_rx_sge *sge = &fp->rx_sge_ring[index];
-
-	/* Skip "next page" elements */
-	if (!page)
-		return;
-
-	dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(sw_buf, mapping),
-		       SGE_PAGE_SIZE*PAGES_PER_SGE, DMA_FROM_DEVICE);
-	__free_pages(page, PAGES_PER_SGE_SHIFT);
-
-	sw_buf->page = NULL;
-	sge->addr_hi = 0;
-	sge->addr_lo = 0;
-}
-
-static inline void bnx2x_add_all_napi(struct bnx2x *bp)
-{
-	int i;
-
-	/* Add NAPI objects */
-	for_each_rx_queue(bp, i)
-		netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
-			       bnx2x_poll, BNX2X_NAPI_WEIGHT);
-}
-
-static inline void bnx2x_del_all_napi(struct bnx2x *bp)
-{
-	int i;
-
-	for_each_rx_queue(bp, i)
-		netif_napi_del(&bnx2x_fp(bp, i, napi));
-}
-
-static inline void bnx2x_disable_msi(struct bnx2x *bp)
-{
-	if (bp->flags & USING_MSIX_FLAG) {
-		pci_disable_msix(bp->pdev);
-		bp->flags &= ~USING_MSIX_FLAG;
-	} else if (bp->flags & USING_MSI_FLAG) {
-		pci_disable_msi(bp->pdev);
-		bp->flags &= ~USING_MSI_FLAG;
-	}
-}
-
-static inline int bnx2x_calc_num_queues(struct bnx2x *bp)
-{
-	return  num_queues ?
-		 min_t(int, num_queues, BNX2X_MAX_QUEUES(bp)) :
-		 min_t(int, num_online_cpus(), BNX2X_MAX_QUEUES(bp));
-}
-
-static inline void bnx2x_clear_sge_mask_next_elems(struct bnx2x_fastpath *fp)
-{
-	int i, j;
-
-	for (i = 1; i <= NUM_RX_SGE_PAGES; i++) {
-		int idx = RX_SGE_CNT * i - 1;
-
-		for (j = 0; j < 2; j++) {
-			BIT_VEC64_CLEAR_BIT(fp->sge_mask, idx);
-			idx--;
-		}
-	}
-}
-
-static inline void bnx2x_init_sge_ring_bit_mask(struct bnx2x_fastpath *fp)
-{
-	/* Set the mask to all 1-s: it's faster to compare to 0 than to 0xf-s */
-	memset(fp->sge_mask, 0xff,
-	       (NUM_RX_SGE >> BIT_VEC64_ELEM_SHIFT)*sizeof(u64));
-
-	/* Clear the two last indices in the page to 1:
-	   these are the indices that correspond to the "next" element,
-	   hence will never be indicated and should be removed from
-	   the calculations. */
-	bnx2x_clear_sge_mask_next_elems(fp);
-}
-
-static inline int bnx2x_alloc_rx_sge(struct bnx2x *bp,
-				     struct bnx2x_fastpath *fp, u16 index)
-{
-	struct page *page = alloc_pages(GFP_ATOMIC, PAGES_PER_SGE_SHIFT);
-	struct sw_rx_page *sw_buf = &fp->rx_page_ring[index];
-	struct eth_rx_sge *sge = &fp->rx_sge_ring[index];
-	dma_addr_t mapping;
-
-	if (unlikely(page == NULL))
-		return -ENOMEM;
-
-	mapping = dma_map_page(&bp->pdev->dev, page, 0,
-			       SGE_PAGE_SIZE*PAGES_PER_SGE, DMA_FROM_DEVICE);
-	if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
-		__free_pages(page, PAGES_PER_SGE_SHIFT);
-		return -ENOMEM;
-	}
-
-	sw_buf->page = page;
-	dma_unmap_addr_set(sw_buf, mapping, mapping);
-
-	sge->addr_hi = cpu_to_le32(U64_HI(mapping));
-	sge->addr_lo = cpu_to_le32(U64_LO(mapping));
-
-	return 0;
-}
-
-static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp,
-				     struct bnx2x_fastpath *fp, u16 index)
-{
-	struct sk_buff *skb;
-	struct sw_rx_bd *rx_buf = &fp->rx_buf_ring[index];
-	struct eth_rx_bd *rx_bd = &fp->rx_desc_ring[index];
-	dma_addr_t mapping;
-
-	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, fp->rx_buf_size,
-				 DMA_FROM_DEVICE);
-	if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
-		dev_kfree_skb_any(skb);
-		return -ENOMEM;
-	}
-
-	rx_buf->skb = skb;
-	dma_unmap_addr_set(rx_buf, mapping, mapping);
-
-	rx_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
-	rx_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
-
-	return 0;
-}
-
-/* note that we are not allocating a new skb,
- * we are just moving one from cons to prod
- * we are not creating a new mapping,
- * so there is no need to check for dma_mapping_error().
- */
-static inline void bnx2x_reuse_rx_skb(struct bnx2x_fastpath *fp,
-				      u16 cons, u16 prod)
-{
-	struct sw_rx_bd *cons_rx_buf = &fp->rx_buf_ring[cons];
-	struct sw_rx_bd *prod_rx_buf = &fp->rx_buf_ring[prod];
-	struct eth_rx_bd *cons_bd = &fp->rx_desc_ring[cons];
-	struct eth_rx_bd *prod_bd = &fp->rx_desc_ring[prod];
-
-	dma_unmap_addr_set(prod_rx_buf, mapping,
-			   dma_unmap_addr(cons_rx_buf, mapping));
-	prod_rx_buf->skb = cons_rx_buf->skb;
-	*prod_bd = *cons_bd;
-}
-
-/************************* Init ******************************************/
-
-/**
- * bnx2x_func_start - init function
- *
- * @bp:		driver handle
- *
- * Must be called before sending CLIENT_SETUP for the first client.
- */
-static inline int bnx2x_func_start(struct bnx2x *bp)
-{
-	struct bnx2x_func_state_params func_params = {0};
-	struct bnx2x_func_start_params *start_params =
-		&func_params.params.start;
-
-	/* Prepare parameters for function state transitions */
-	__set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
-
-	func_params.f_obj = &bp->func_obj;
-	func_params.cmd = BNX2X_F_CMD_START;
-
-	/* Function parameters */
-	start_params->mf_mode = bp->mf_mode;
-	start_params->sd_vlan_tag = bp->mf_ov;
-	if (CHIP_IS_E1x(bp))
-		start_params->network_cos_mode = OVERRIDE_COS;
-	else
-		start_params->network_cos_mode = STATIC_COS;
-
-	return bnx2x_func_state_change(bp, &func_params);
-}
-
-
-/**
- * bnx2x_set_fw_mac_addr - fill in a MAC address in FW format
- *
- * @fw_hi:	pointer to upper part
- * @fw_mid:	pointer to middle part
- * @fw_lo:	pointer to lower part
- * @mac:	pointer to MAC address
- */
-static inline void bnx2x_set_fw_mac_addr(u16 *fw_hi, u16 *fw_mid, u16 *fw_lo,
-					 u8 *mac)
-{
-	((u8 *)fw_hi)[0]  = mac[1];
-	((u8 *)fw_hi)[1]  = mac[0];
-	((u8 *)fw_mid)[0] = mac[3];
-	((u8 *)fw_mid)[1] = mac[2];
-	((u8 *)fw_lo)[0]  = mac[5];
-	((u8 *)fw_lo)[1]  = mac[4];
-}
-
-static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp,
-					   struct bnx2x_fastpath *fp, int last)
-{
-	int i;
-
-	if (fp->disable_tpa)
-		return;
-
-	for (i = 0; i < last; i++)
-		bnx2x_free_rx_sge(bp, fp, i);
-}
-
-static inline void bnx2x_free_tpa_pool(struct bnx2x *bp,
-				       struct bnx2x_fastpath *fp, int last)
-{
-	int i;
-
-	for (i = 0; i < last; i++) {
-		struct bnx2x_agg_info *tpa_info = &fp->tpa_info[i];
-		struct sw_rx_bd *first_buf = &tpa_info->first_buf;
-		struct sk_buff *skb = first_buf->skb;
-
-		if (skb == NULL) {
-			DP(NETIF_MSG_IFDOWN, "tpa bin %d empty on free\n", i);
-			continue;
-		}
-		if (tpa_info->tpa_state == BNX2X_TPA_START)
-			dma_unmap_single(&bp->pdev->dev,
-					 dma_unmap_addr(first_buf, mapping),
-					 fp->rx_buf_size, DMA_FROM_DEVICE);
-		dev_kfree_skb(skb);
-		first_buf->skb = NULL;
-	}
-}
-
-static inline void bnx2x_init_tx_ring_one(struct bnx2x_fp_txdata *txdata)
-{
-	int i;
-
-	for (i = 1; i <= NUM_TX_RINGS; i++) {
-		struct eth_tx_next_bd *tx_next_bd =
-			&txdata->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd;
-
-		tx_next_bd->addr_hi =
-			cpu_to_le32(U64_HI(txdata->tx_desc_mapping +
-				    BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
-		tx_next_bd->addr_lo =
-			cpu_to_le32(U64_LO(txdata->tx_desc_mapping +
-				    BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
-	}
-
-	SET_FLAG(txdata->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1);
-	txdata->tx_db.data.zero_fill1 = 0;
-	txdata->tx_db.data.prod = 0;
-
-	txdata->tx_pkt_prod = 0;
-	txdata->tx_pkt_cons = 0;
-	txdata->tx_bd_prod = 0;
-	txdata->tx_bd_cons = 0;
-	txdata->tx_pkt = 0;
-}
-
-static inline void bnx2x_init_tx_rings(struct bnx2x *bp)
-{
-	int i;
-	u8 cos;
-
-	for_each_tx_queue(bp, i)
-		for_each_cos_in_tx_queue(&bp->fp[i], cos)
-			bnx2x_init_tx_ring_one(&bp->fp[i].txdata[cos]);
-}
-
-static inline void bnx2x_set_next_page_rx_bd(struct bnx2x_fastpath *fp)
-{
-	int i;
-
-	for (i = 1; i <= NUM_RX_RINGS; i++) {
-		struct eth_rx_bd *rx_bd;
-
-		rx_bd = &fp->rx_desc_ring[RX_DESC_CNT * i - 2];
-		rx_bd->addr_hi =
-			cpu_to_le32(U64_HI(fp->rx_desc_mapping +
-				    BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
-		rx_bd->addr_lo =
-			cpu_to_le32(U64_LO(fp->rx_desc_mapping +
-				    BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
-	}
-}
-
-static inline void bnx2x_set_next_page_sgl(struct bnx2x_fastpath *fp)
-{
-	int i;
-
-	for (i = 1; i <= NUM_RX_SGE_PAGES; i++) {
-		struct eth_rx_sge *sge;
-
-		sge = &fp->rx_sge_ring[RX_SGE_CNT * i - 2];
-		sge->addr_hi =
-			cpu_to_le32(U64_HI(fp->rx_sge_mapping +
-			BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES)));
-
-		sge->addr_lo =
-			cpu_to_le32(U64_LO(fp->rx_sge_mapping +
-			BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES)));
-	}
-}
-
-static inline void bnx2x_set_next_page_rx_cq(struct bnx2x_fastpath *fp)
-{
-	int i;
-	for (i = 1; i <= NUM_RCQ_RINGS; i++) {
-		struct eth_rx_cqe_next_page *nextpg;
-
-		nextpg = (struct eth_rx_cqe_next_page *)
-			&fp->rx_comp_ring[RCQ_DESC_CNT * i - 1];
-		nextpg->addr_hi =
-			cpu_to_le32(U64_HI(fp->rx_comp_mapping +
-				   BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
-		nextpg->addr_lo =
-			cpu_to_le32(U64_LO(fp->rx_comp_mapping +
-				   BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
-	}
-}
-
-/* Returns the number of actually allocated BDs */
-static inline int bnx2x_alloc_rx_bds(struct bnx2x_fastpath *fp,
-				      int rx_ring_size)
-{
-	struct bnx2x *bp = fp->bp;
-	u16 ring_prod, cqe_ring_prod;
-	int i;
-
-	fp->rx_comp_cons = 0;
-	cqe_ring_prod = ring_prod = 0;
-
-	/* This routine is called only during fo init so
-	 * fp->eth_q_stats.rx_skb_alloc_failed = 0
-	 */
-	for (i = 0; i < rx_ring_size; i++) {
-		if (bnx2x_alloc_rx_skb(bp, fp, ring_prod) < 0) {
-			fp->eth_q_stats.rx_skb_alloc_failed++;
-			continue;
-		}
-		ring_prod = NEXT_RX_IDX(ring_prod);
-		cqe_ring_prod = NEXT_RCQ_IDX(cqe_ring_prod);
-		WARN_ON(ring_prod <= (i - fp->eth_q_stats.rx_skb_alloc_failed));
-	}
-
-	if (fp->eth_q_stats.rx_skb_alloc_failed)
-		BNX2X_ERR("was only able to allocate "
-			  "%d rx skbs on queue[%d]\n",
-			  (i - fp->eth_q_stats.rx_skb_alloc_failed), fp->index);
-
-	fp->rx_bd_prod = ring_prod;
-	/* Limit the CQE producer by the CQE ring size */
-	fp->rx_comp_prod = min_t(u16, NUM_RCQ_RINGS*RCQ_DESC_CNT,
-			       cqe_ring_prod);
-	fp->rx_pkt = fp->rx_calls = 0;
-
-	return i - fp->eth_q_stats.rx_skb_alloc_failed;
-}
-
-/* Statistics ID are global per chip/path, while Client IDs for E1x are per
- * port.
- */
-static inline u8 bnx2x_stats_id(struct bnx2x_fastpath *fp)
-{
-	if (!CHIP_IS_E1x(fp->bp))
-		return fp->cl_id;
-	else
-		return fp->cl_id + BP_PORT(fp->bp) * FP_SB_MAX_E1x;
-}
-
-static inline void bnx2x_init_vlan_mac_fp_objs(struct bnx2x_fastpath *fp,
-					       bnx2x_obj_type obj_type)
-{
-	struct bnx2x *bp = fp->bp;
-
-	/* Configure classification DBs */
-	bnx2x_init_mac_obj(bp, &fp->mac_obj, fp->cl_id, fp->cid,
-			   BP_FUNC(bp), bnx2x_sp(bp, mac_rdata),
-			   bnx2x_sp_mapping(bp, mac_rdata),
-			   BNX2X_FILTER_MAC_PENDING,
-			   &bp->sp_state, obj_type,
-			   &bp->macs_pool);
-}
-
-/**
- * bnx2x_get_path_func_num - get number of active functions
- *
- * @bp:		driver handle
- *
- * Calculates the number of active (not hidden) functions on the
- * current path.
- */
-static inline u8 bnx2x_get_path_func_num(struct bnx2x *bp)
-{
-	u8 func_num = 0, i;
-
-	/* 57710 has only one function per-port */
-	if (CHIP_IS_E1(bp))
-		return 1;
-
-	/* Calculate a number of functions enabled on the current
-	 * PATH/PORT.
-	 */
-	if (CHIP_REV_IS_SLOW(bp)) {
-		if (IS_MF(bp))
-			func_num = 4;
-		else
-			func_num = 2;
-	} else {
-		for (i = 0; i < E1H_FUNC_MAX / 2; i++) {
-			u32 func_config =
-				MF_CFG_RD(bp,
-					  func_mf_config[BP_PORT(bp) + 2 * i].
-					  config);
-			func_num +=
-				((func_config & FUNC_MF_CFG_FUNC_HIDE) ? 0 : 1);
-		}
-	}
-
-	WARN_ON(!func_num);
-
-	return func_num;
-}
-
-static inline void bnx2x_init_bp_objs(struct bnx2x *bp)
-{
-	/* RX_MODE controlling object */
-	bnx2x_init_rx_mode_obj(bp, &bp->rx_mode_obj);
-
-	/* multicast configuration controlling object */
-	bnx2x_init_mcast_obj(bp, &bp->mcast_obj, bp->fp->cl_id, bp->fp->cid,
-			     BP_FUNC(bp), BP_FUNC(bp),
-			     bnx2x_sp(bp, mcast_rdata),
-			     bnx2x_sp_mapping(bp, mcast_rdata),
-			     BNX2X_FILTER_MCAST_PENDING, &bp->sp_state,
-			     BNX2X_OBJ_TYPE_RX);
-
-	/* Setup CAM credit pools */
-	bnx2x_init_mac_credit_pool(bp, &bp->macs_pool, BP_FUNC(bp),
-				   bnx2x_get_path_func_num(bp));
-
-	/* RSS configuration object */
-	bnx2x_init_rss_config_obj(bp, &bp->rss_conf_obj, bp->fp->cl_id,
-				  bp->fp->cid, BP_FUNC(bp), BP_FUNC(bp),
-				  bnx2x_sp(bp, rss_rdata),
-				  bnx2x_sp_mapping(bp, rss_rdata),
-				  BNX2X_FILTER_RSS_CONF_PENDING, &bp->sp_state,
-				  BNX2X_OBJ_TYPE_RX);
-}
-
-static inline u8 bnx2x_fp_qzone_id(struct bnx2x_fastpath *fp)
-{
-	if (CHIP_IS_E1x(fp->bp))
-		return fp->cl_id + BP_PORT(fp->bp) * ETH_MAX_RX_CLIENTS_E1H;
-	else
-		return fp->cl_id;
-}
-
-static inline u32 bnx2x_rx_ustorm_prods_offset(struct bnx2x_fastpath *fp)
-{
-	struct bnx2x *bp = fp->bp;
-
-	if (!CHIP_IS_E1x(bp))
-		return USTORM_RX_PRODS_E2_OFFSET(fp->cl_qzone_id);
-	else
-		return USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), fp->cl_id);
-}
-
-static inline void bnx2x_init_txdata(struct bnx2x *bp,
-	struct bnx2x_fp_txdata *txdata, u32 cid, int txq_index,
-	__le16 *tx_cons_sb)
-{
-	txdata->cid = cid;
-	txdata->txq_index = txq_index;
-	txdata->tx_cons_sb = tx_cons_sb;
-
-	DP(BNX2X_MSG_SP, "created tx data cid %d, txq %d",
-	   txdata->cid, txdata->txq_index);
-}
-
-#ifdef BCM_CNIC
-static inline u8 bnx2x_cnic_eth_cl_id(struct bnx2x *bp, u8 cl_idx)
-{
-	return bp->cnic_base_cl_id + cl_idx +
-		(bp->pf_num >> 1) * BNX2X_MAX_CNIC_ETH_CL_ID_IDX;
-}
-
-static inline u8 bnx2x_cnic_fw_sb_id(struct bnx2x *bp)
-{
-
-	/* the 'first' id is allocated for the cnic */
-	return bp->base_fw_ndsb;
-}
-
-static inline u8 bnx2x_cnic_igu_sb_id(struct bnx2x *bp)
-{
-	return bp->igu_base_sb;
-}
-
-
-static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
-{
-	struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
-	unsigned long q_type = 0;
-
-	bnx2x_fcoe(bp, cl_id) = bnx2x_cnic_eth_cl_id(bp,
-						     BNX2X_FCOE_ETH_CL_ID_IDX);
-	/** Current BNX2X_FCOE_ETH_CID deffinition implies not more than
-	 *  16 ETH clients per function when CNIC is enabled!
-	 *
-	 *  Fix it ASAP!!!
-	 */
-	bnx2x_fcoe(bp, cid) = BNX2X_FCOE_ETH_CID;
-	bnx2x_fcoe(bp, fw_sb_id) = DEF_SB_ID;
-	bnx2x_fcoe(bp, igu_sb_id) = bp->igu_dsb_id;
-	bnx2x_fcoe(bp, rx_cons_sb) = BNX2X_FCOE_L2_RX_INDEX;
-
-	bnx2x_init_txdata(bp, &bnx2x_fcoe(bp, txdata[0]),
-			  fp->cid, FCOE_TXQ_IDX(bp), BNX2X_FCOE_L2_TX_INDEX);
-
-	DP(BNX2X_MSG_SP, "created fcoe tx data (fp index %d)", fp->index);
-
-	/* qZone id equals to FW (per path) client id */
-	bnx2x_fcoe(bp, cl_qzone_id) = bnx2x_fp_qzone_id(fp);
-	/* init shortcut */
-	bnx2x_fcoe(bp, ustorm_rx_prods_offset) =
-		bnx2x_rx_ustorm_prods_offset(fp);
-
-	/* Configure Queue State object */
-	__set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type);
-	__set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type);
-
-	/* No multi-CoS for FCoE L2 client */
-	BUG_ON(fp->max_cos != 1);
-
-	bnx2x_init_queue_obj(bp, &fp->q_obj, fp->cl_id, &fp->cid, 1,
-			     BP_FUNC(bp), bnx2x_sp(bp, q_rdata),
-			     bnx2x_sp_mapping(bp, q_rdata), q_type);
-
-	DP(NETIF_MSG_IFUP, "queue[%d]: bnx2x_init_sb(%p,%p) cl_id %d fw_sb %d "
-			   "igu_sb %d\n",
-	   fp->index, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id,
-	   fp->igu_sb_id);
-}
-#endif
-
-static inline int bnx2x_clean_tx_queue(struct bnx2x *bp,
-				       struct bnx2x_fp_txdata *txdata)
-{
-	int cnt = 1000;
-
-	while (bnx2x_has_tx_work_unload(txdata)) {
-		if (!cnt) {
-			BNX2X_ERR("timeout waiting for queue[%d]: "
-				 "txdata->tx_pkt_prod(%d) != txdata->tx_pkt_cons(%d)\n",
-				  txdata->txq_index, txdata->tx_pkt_prod,
-				  txdata->tx_pkt_cons);
-#ifdef BNX2X_STOP_ON_ERROR
-			bnx2x_panic();
-			return -EBUSY;
-#else
-			break;
-#endif
-		}
-		cnt--;
-		usleep_range(1000, 1000);
-	}
-
-	return 0;
-}
-
-int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
-
-static inline void __storm_memset_struct(struct bnx2x *bp,
-					 u32 addr, size_t size, u32 *data)
-{
-	int i;
-	for (i = 0; i < size/4; i++)
-		REG_WR(bp, addr + (i * 4), data[i]);
-}
-
-static inline void storm_memset_func_cfg(struct bnx2x *bp,
-				struct tstorm_eth_function_common_config *tcfg,
-				u16 abs_fid)
-{
-	size_t size = sizeof(struct tstorm_eth_function_common_config);
-
-	u32 addr = BAR_TSTRORM_INTMEM +
-			TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(abs_fid);
-
-	__storm_memset_struct(bp, addr, size, (u32 *)tcfg);
-}
-
-static inline void storm_memset_cmng(struct bnx2x *bp,
-				struct cmng_struct_per_port *cmng,
-				u8 port)
-{
-	size_t size = sizeof(struct cmng_struct_per_port);
-
-	u32 addr = BAR_XSTRORM_INTMEM +
-			XSTORM_CMNG_PER_PORT_VARS_OFFSET(port);
-
-	__storm_memset_struct(bp, addr, size, (u32 *)cmng);
-}
-
-/**
- * bnx2x_wait_sp_comp - wait for the outstanding SP commands.
- *
- * @bp:		driver handle
- * @mask:	bits that need to be cleared
- */
-static inline bool bnx2x_wait_sp_comp(struct bnx2x *bp, unsigned long mask)
-{
-	int tout = 5000; /* Wait for 5 secs tops */
-
-	while (tout--) {
-		smp_mb();
-		netif_addr_lock_bh(bp->dev);
-		if (!(bp->sp_state & mask)) {
-			netif_addr_unlock_bh(bp->dev);
-			return true;
-		}
-		netif_addr_unlock_bh(bp->dev);
-
-		usleep_range(1000, 1000);
-	}
-
-	smp_mb();
-
-	netif_addr_lock_bh(bp->dev);
-	if (bp->sp_state & mask) {
-		BNX2X_ERR("Filtering completion timed out. sp_state 0x%lx, "
-			  "mask 0x%lx\n", bp->sp_state, mask);
-		netif_addr_unlock_bh(bp->dev);
-		return false;
-	}
-	netif_addr_unlock_bh(bp->dev);
-
-	return true;
-}
-
-/**
- * bnx2x_set_ctx_validation - set CDU context validation values
- *
- * @bp:		driver handle
- * @cxt:	context of the connection on the host memory
- * @cid:	SW CID of the connection to be configured
- */
-void bnx2x_set_ctx_validation(struct bnx2x *bp, struct eth_context *cxt,
-			      u32 cid);
-
-void bnx2x_update_coalesce_sb_index(struct bnx2x *bp, u8 fw_sb_id,
-				    u8 sb_index, u8 disable, u16 usec);
-void bnx2x_acquire_phy_lock(struct bnx2x *bp);
-void bnx2x_release_phy_lock(struct bnx2x *bp);
-
-/**
- * bnx2x_extract_max_cfg - extract MAX BW part from MF configuration.
- *
- * @bp:		driver handle
- * @mf_cfg:	MF configuration
- *
- */
-static inline u16 bnx2x_extract_max_cfg(struct bnx2x *bp, u32 mf_cfg)
-{
-	u16 max_cfg = (mf_cfg & FUNC_MF_CFG_MAX_BW_MASK) >>
-			      FUNC_MF_CFG_MAX_BW_SHIFT;
-	if (!max_cfg) {
-		BNX2X_ERR("Illegal configuration detected for Max BW - "
-			  "using 100 instead\n");
-		max_cfg = 100;
-	}
-	return max_cfg;
-}
-
-#endif /* BNX2X_CMN_H */
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_dcb.c linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_dcb.c
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_dcb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_dcb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2508 +0,0 @@
-/* bnx2x_dcb.c: Broadcom Everest network driver.
- *
- * Copyright 2009-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
- * under the terms of the GNU General Public License version 2, available
- * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
- *
- * Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a
- * license other than the GPL, without Broadcom's express prior written
- * consent.
- *
- * Maintained by: Eilon Greenstein <eilong@broadcom.com>
- * Written by: Dmitry Kravkov
- *
- */
-#include <linux/netdevice.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/rtnetlink.h>
-#include <net/dcbnl.h>
-
-#include "bnx2x.h"
-#include "bnx2x_cmn.h"
-#include "bnx2x_dcb.h"
-
-/* forward declarations of dcbx related functions */
-static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
-static void bnx2x_pfc_set_pfc(struct bnx2x *bp);
-static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp);
-static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
-static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
-					  u32 *set_configuration_ets_pg,
-					  u32 *pri_pg_tbl);
-static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x *bp,
-					    u32 *pg_pri_orginal_spread,
-					    struct pg_help_data *help_data);
-static void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
-				       struct pg_help_data *help_data,
-				       struct dcbx_ets_feature *ets,
-				       u32 *pg_pri_orginal_spread);
-static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
-				struct cos_help_data *cos_data,
-				u32 *pg_pri_orginal_spread,
-				struct dcbx_ets_feature *ets);
-static void bnx2x_dcbx_fw_struct(struct bnx2x *bp,
-				 struct bnx2x_func_tx_start_params*);
-
-/* helpers: read/write len bytes from addr into buff by REG_RD/REG_WR */
-static void bnx2x_read_data(struct bnx2x *bp, u32 *buff,
-				   u32 addr, u32 len)
-{
-	int i;
-	for (i = 0; i < len; i += 4, buff++)
-		*buff = REG_RD(bp, addr + i);
-}
-
-static void bnx2x_write_data(struct bnx2x *bp, u32 *buff,
-				    u32 addr, u32 len)
-{
-	int i;
-	for (i = 0; i < len; i += 4, buff++)
-		REG_WR(bp, addr + i, *buff);
-}
-
-static void bnx2x_pfc_set(struct bnx2x *bp)
-{
-	struct bnx2x_nig_brb_pfc_port_params pfc_params = {0};
-	u32 pri_bit, val = 0;
-	int i;
-
-	pfc_params.num_of_rx_cos_priority_mask =
-					bp->dcbx_port_params.ets.num_of_cos;
-
-	/* Tx COS configuration */
-	for (i = 0; i < bp->dcbx_port_params.ets.num_of_cos; i++)
-		/*
-		 * We configure only the pauseable bits (non pauseable aren't
-		 * configured at all) it's done to avoid false pauses from
-		 * network
-		 */
-		pfc_params.rx_cos_priority_mask[i] =
-			bp->dcbx_port_params.ets.cos_params[i].pri_bitmask
-				& DCBX_PFC_PRI_PAUSE_MASK(bp);
-
-	/*
-	 * Rx COS configuration
-	 * Changing PFC RX configuration .
-	 * In RX COS0 will always be configured to lossy and COS1 to lossless
-	 */
-	for (i = 0 ; i < MAX_PFC_PRIORITIES ; i++) {
-		pri_bit = 1 << i;
-
-		if (pri_bit & DCBX_PFC_PRI_PAUSE_MASK(bp))
-			val |= 1 << (i * 4);
-	}
-
-	pfc_params.pkt_priority_to_cos = val;
-
-	/* RX COS0 */
-	pfc_params.llfc_low_priority_classes = 0;
-	/* RX COS1 */
-	pfc_params.llfc_high_priority_classes = DCBX_PFC_PRI_PAUSE_MASK(bp);
-
-	/* BRB configuration */
-	pfc_params.cos0_pauseable = false;
-	pfc_params.cos1_pauseable = true;
-
-	bnx2x_acquire_phy_lock(bp);
-	bp->link_params.feature_config_flags |= FEATURE_CONFIG_PFC_ENABLED;
-	bnx2x_update_pfc(&bp->link_params, &bp->link_vars, &pfc_params);
-	bnx2x_release_phy_lock(bp);
-}
-
-static void bnx2x_pfc_clear(struct bnx2x *bp)
-{
-	struct bnx2x_nig_brb_pfc_port_params nig_params = {0};
-	nig_params.pause_enable = 1;
-#ifdef BNX2X_SAFC
-	if (bp->flags & SAFC_TX_FLAG) {
-		u32 high = 0, low = 0;
-		int i;
-
-		for (i = 0; i < BNX2X_MAX_PRIORITY; i++) {
-			if (bp->pri_map[i] == 1)
-				high |= (1 << i);
-			if (bp->pri_map[i] == 0)
-				low |= (1 << i);
-		}
-
-		nig_params.llfc_low_priority_classes = high;
-		nig_params.llfc_low_priority_classes = low;
-
-		nig_params.pause_enable = 0;
-		nig_params.llfc_enable = 1;
-		nig_params.llfc_out_en = 1;
-	}
-#endif /* BNX2X_SAFC */
-	bnx2x_acquire_phy_lock(bp);
-	bp->link_params.feature_config_flags &= ~FEATURE_CONFIG_PFC_ENABLED;
-	bnx2x_update_pfc(&bp->link_params, &bp->link_vars, &nig_params);
-	bnx2x_release_phy_lock(bp);
-}
-
-static void  bnx2x_dump_dcbx_drv_param(struct bnx2x *bp,
-				       struct dcbx_features *features,
-				       u32 error)
-{
-	u8 i = 0;
-	DP(NETIF_MSG_LINK, "local_mib.error %x\n", error);
-
-	/* PG */
-	DP(NETIF_MSG_LINK,
-	   "local_mib.features.ets.enabled %x\n", features->ets.enabled);
-	for (i = 0; i < DCBX_MAX_NUM_PG_BW_ENTRIES; i++)
-		DP(NETIF_MSG_LINK,
-		   "local_mib.features.ets.pg_bw_tbl[%d] %d\n", i,
-		   DCBX_PG_BW_GET(features->ets.pg_bw_tbl, i));
-	for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++)
-		DP(NETIF_MSG_LINK,
-		   "local_mib.features.ets.pri_pg_tbl[%d] %d\n", i,
-		   DCBX_PRI_PG_GET(features->ets.pri_pg_tbl, i));
-
-	/* pfc */
-	DP(NETIF_MSG_LINK, "dcbx_features.pfc.pri_en_bitmap %x\n",
-					features->pfc.pri_en_bitmap);
-	DP(NETIF_MSG_LINK, "dcbx_features.pfc.pfc_caps %x\n",
-					features->pfc.pfc_caps);
-	DP(NETIF_MSG_LINK, "dcbx_features.pfc.enabled %x\n",
-					features->pfc.enabled);
-
-	DP(NETIF_MSG_LINK, "dcbx_features.app.default_pri %x\n",
-					features->app.default_pri);
-	DP(NETIF_MSG_LINK, "dcbx_features.app.tc_supported %x\n",
-					features->app.tc_supported);
-	DP(NETIF_MSG_LINK, "dcbx_features.app.enabled %x\n",
-					features->app.enabled);
-	for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++) {
-		DP(NETIF_MSG_LINK,
-		   "dcbx_features.app.app_pri_tbl[%x].app_id %x\n",
-		   i, features->app.app_pri_tbl[i].app_id);
-		DP(NETIF_MSG_LINK,
-		   "dcbx_features.app.app_pri_tbl[%x].pri_bitmap %x\n",
-		   i, features->app.app_pri_tbl[i].pri_bitmap);
-		DP(NETIF_MSG_LINK,
-		   "dcbx_features.app.app_pri_tbl[%x].appBitfield %x\n",
-		   i, features->app.app_pri_tbl[i].appBitfield);
-	}
-}
-
-static void bnx2x_dcbx_get_ap_priority(struct bnx2x *bp,
-				       u8 pri_bitmap,
-				       u8 llfc_traf_type)
-{
-	u32 pri = MAX_PFC_PRIORITIES;
-	u32 index = MAX_PFC_PRIORITIES - 1;
-	u32 pri_mask;
-	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
-
-	/* Choose the highest priority */
-	while ((MAX_PFC_PRIORITIES == pri) && (0 != index)) {
-		pri_mask = 1 << index;
-		if (GET_FLAGS(pri_bitmap, pri_mask))
-			pri = index ;
-		index--;
-	}
-
-	if (pri < MAX_PFC_PRIORITIES)
-		ttp[llfc_traf_type] = max_t(u32, ttp[llfc_traf_type], pri);
-}
-
-static void bnx2x_dcbx_get_ap_feature(struct bnx2x *bp,
-				   struct dcbx_app_priority_feature *app,
-				   u32 error) {
-	u8 index;
-	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
-
-	if (GET_FLAGS(error, DCBX_LOCAL_APP_ERROR))
-		DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_ERROR\n");
-
-	if (GET_FLAGS(error, DCBX_LOCAL_APP_MISMATCH))
-		DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_MISMATCH\n");
-
-	if (app->enabled &&
-	    !GET_FLAGS(error, DCBX_LOCAL_APP_ERROR | DCBX_LOCAL_APP_MISMATCH)) {
-
-		bp->dcbx_port_params.app.enabled = true;
-
-		for (index = 0 ; index < LLFC_DRIVER_TRAFFIC_TYPE_MAX; index++)
-			ttp[index] = 0;
-
-		if (app->default_pri < MAX_PFC_PRIORITIES)
-			ttp[LLFC_TRAFFIC_TYPE_NW] = app->default_pri;
-
-		for (index = 0 ; index < DCBX_MAX_APP_PROTOCOL; index++) {
-			struct dcbx_app_priority_entry *entry =
-							app->app_pri_tbl;
-
-			if (GET_FLAGS(entry[index].appBitfield,
-				     DCBX_APP_SF_ETH_TYPE) &&
-			   ETH_TYPE_FCOE == entry[index].app_id)
-				bnx2x_dcbx_get_ap_priority(bp,
-						entry[index].pri_bitmap,
-						LLFC_TRAFFIC_TYPE_FCOE);
-
-			if (GET_FLAGS(entry[index].appBitfield,
-				     DCBX_APP_SF_PORT) &&
-			   TCP_PORT_ISCSI == entry[index].app_id)
-				bnx2x_dcbx_get_ap_priority(bp,
-						entry[index].pri_bitmap,
-						LLFC_TRAFFIC_TYPE_ISCSI);
-		}
-	} else {
-		DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_DISABLED\n");
-		bp->dcbx_port_params.app.enabled = false;
-		for (index = 0 ; index < LLFC_DRIVER_TRAFFIC_TYPE_MAX; index++)
-			ttp[index] = INVALID_TRAFFIC_TYPE_PRIORITY;
-	}
-}
-
-static void bnx2x_dcbx_get_ets_feature(struct bnx2x *bp,
-				       struct dcbx_ets_feature *ets,
-				       u32 error) {
-	int i = 0;
-	u32 pg_pri_orginal_spread[DCBX_MAX_NUM_PG_BW_ENTRIES] = {0};
-	struct pg_help_data pg_help_data;
-	struct bnx2x_dcbx_cos_params *cos_params =
-			bp->dcbx_port_params.ets.cos_params;
-
-	memset(&pg_help_data, 0, sizeof(struct pg_help_data));
-
-
-	if (GET_FLAGS(error, DCBX_LOCAL_ETS_ERROR))
-		DP(NETIF_MSG_LINK, "DCBX_LOCAL_ETS_ERROR\n");
-
-
-	/* Clean up old settings of ets on COS */
-	for (i = 0; i < ARRAY_SIZE(bp->dcbx_port_params.ets.cos_params) ; i++) {
-		cos_params[i].pauseable = false;
-		cos_params[i].strict = BNX2X_DCBX_STRICT_INVALID;
-		cos_params[i].bw_tbl = DCBX_INVALID_COS_BW;
-		cos_params[i].pri_bitmask = 0;
-	}
-
-	if (bp->dcbx_port_params.app.enabled &&
-	   !GET_FLAGS(error, DCBX_LOCAL_ETS_ERROR) &&
-	   ets->enabled) {
-		DP(NETIF_MSG_LINK, "DCBX_LOCAL_ETS_ENABLE\n");
-		bp->dcbx_port_params.ets.enabled = true;
-
-		bnx2x_dcbx_get_ets_pri_pg_tbl(bp,
-					      pg_pri_orginal_spread,
-					      ets->pri_pg_tbl);
-
-		bnx2x_dcbx_get_num_pg_traf_type(bp,
-						pg_pri_orginal_spread,
-						&pg_help_data);
-
-		bnx2x_dcbx_fill_cos_params(bp, &pg_help_data,
-					   ets, pg_pri_orginal_spread);
-
-	} else {
-		DP(NETIF_MSG_LINK, "DCBX_LOCAL_ETS_DISABLED\n");
-		bp->dcbx_port_params.ets.enabled = false;
-		ets->pri_pg_tbl[0] = 0;
-
-		for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES ; i++)
-			DCBX_PG_BW_SET(ets->pg_bw_tbl, i, 1);
-	}
-}
-
-static void  bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp,
-					struct dcbx_pfc_feature *pfc, u32 error)
-{
-
-	if (GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR))
-		DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_ERROR\n");
-
-	if (bp->dcbx_port_params.app.enabled &&
-	   !GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR | DCBX_LOCAL_PFC_MISMATCH) &&
-	   pfc->enabled) {
-		bp->dcbx_port_params.pfc.enabled = true;
-		bp->dcbx_port_params.pfc.priority_non_pauseable_mask =
-			~(pfc->pri_en_bitmap);
-	} else {
-		DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_DISABLED\n");
-		bp->dcbx_port_params.pfc.enabled = false;
-		bp->dcbx_port_params.pfc.priority_non_pauseable_mask = 0;
-	}
-}
-
-/* maps unmapped priorities to to the same COS as L2 */
-static void bnx2x_dcbx_map_nw(struct bnx2x *bp)
-{
-	int i;
-	u32 unmapped = (1 << MAX_PFC_PRIORITIES) - 1; /* all ones */
-	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
-	u32 nw_prio = 1 << ttp[LLFC_TRAFFIC_TYPE_NW];
-	struct bnx2x_dcbx_cos_params *cos_params =
-			bp->dcbx_port_params.ets.cos_params;
-
-	/* get unmapped priorities by clearing mapped bits */
-	for (i = 0; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++)
-		unmapped &= ~(1 << ttp[i]);
-
-	/* find cos for nw prio and extend it with unmapped */
-	for (i = 0; i < ARRAY_SIZE(bp->dcbx_port_params.ets.cos_params); i++) {
-		if (cos_params[i].pri_bitmask & nw_prio) {
-			/* extend the bitmask with unmapped */
-			DP(NETIF_MSG_LINK,
-			   "cos %d extended with 0x%08x", i, unmapped);
-			cos_params[i].pri_bitmask |= unmapped;
-			break;
-		}
-	}
-}
-
-static void bnx2x_get_dcbx_drv_param(struct bnx2x *bp,
-				     struct dcbx_features *features,
-				     u32 error)
-{
-	bnx2x_dcbx_get_ap_feature(bp, &features->app, error);
-
-	bnx2x_dcbx_get_pfc_feature(bp, &features->pfc, error);
-
-	bnx2x_dcbx_get_ets_feature(bp, &features->ets, error);
-
-	bnx2x_dcbx_map_nw(bp);
-}
-
-#define DCBX_LOCAL_MIB_MAX_TRY_READ		(100)
-static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
-			       u32 *base_mib_addr,
-			       u32 offset,
-			       int read_mib_type)
-{
-	int max_try_read = 0;
-	u32 mib_size, prefix_seq_num, suffix_seq_num;
-	struct lldp_remote_mib *remote_mib ;
-	struct lldp_local_mib  *local_mib;
-
-
-	switch (read_mib_type) {
-	case DCBX_READ_LOCAL_MIB:
-		mib_size = sizeof(struct lldp_local_mib);
-		break;
-	case DCBX_READ_REMOTE_MIB:
-		mib_size = sizeof(struct lldp_remote_mib);
-		break;
-	default:
-		return 1; /*error*/
-	}
-
-	offset += BP_PORT(bp) * mib_size;
-
-	do {
-		bnx2x_read_data(bp, base_mib_addr, offset, mib_size);
-
-		max_try_read++;
-
-		switch (read_mib_type) {
-		case DCBX_READ_LOCAL_MIB:
-			local_mib = (struct lldp_local_mib *) base_mib_addr;
-			prefix_seq_num = local_mib->prefix_seq_num;
-			suffix_seq_num = local_mib->suffix_seq_num;
-			break;
-		case DCBX_READ_REMOTE_MIB:
-			remote_mib = (struct lldp_remote_mib *) base_mib_addr;
-			prefix_seq_num = remote_mib->prefix_seq_num;
-			suffix_seq_num = remote_mib->suffix_seq_num;
-			break;
-		default:
-			return 1; /*error*/
-		}
-	} while ((prefix_seq_num != suffix_seq_num) &&
-	       (max_try_read < DCBX_LOCAL_MIB_MAX_TRY_READ));
-
-	if (max_try_read >= DCBX_LOCAL_MIB_MAX_TRY_READ) {
-		BNX2X_ERR("MIB could not be read\n");
-		return 1;
-	}
-
-	return 0;
-}
-
-static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
-{
-	if (bp->dcbx_port_params.pfc.enabled &&
-	    !(bp->dcbx_error & DCBX_REMOTE_MIB_ERROR))
-		/*
-		 * 1. Fills up common PFC structures if required
-		 * 2. Configure NIG, MAC and BRB via the elink
-		 */
-		bnx2x_pfc_set(bp);
-	else
-		bnx2x_pfc_clear(bp);
-}
-
-static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
-{
-	struct bnx2x_func_state_params func_params = {0};
-
-	func_params.f_obj = &bp->func_obj;
-	func_params.cmd = BNX2X_F_CMD_TX_STOP;
-
-	DP(NETIF_MSG_LINK, "STOP TRAFFIC\n");
-	return bnx2x_func_state_change(bp, &func_params);
-}
-
-static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
-{
-	struct bnx2x_func_state_params func_params = {0};
-	struct bnx2x_func_tx_start_params *tx_params =
-		&func_params.params.tx_start;
-
-	func_params.f_obj = &bp->func_obj;
-	func_params.cmd = BNX2X_F_CMD_TX_START;
-
-	bnx2x_dcbx_fw_struct(bp, tx_params);
-
-	DP(NETIF_MSG_LINK, "START TRAFFIC\n");
-	return bnx2x_func_state_change(bp, &func_params);
-}
-
-static void bnx2x_dcbx_2cos_limit_update_ets_config(struct bnx2x *bp)
-{
-	struct bnx2x_dcbx_pg_params *ets = &(bp->dcbx_port_params.ets);
-	int rc = 0;
-
-	if (ets->num_of_cos == 0 || ets->num_of_cos > DCBX_COS_MAX_NUM_E2) {
-		BNX2X_ERR("Illegal number of COSes %d\n", ets->num_of_cos);
-		return;
-	}
-
-	/* valid COS entries */
-	if (ets->num_of_cos == 1)   /* no ETS */
-		return;
-
-	/* sanity */
-	if (((BNX2X_DCBX_STRICT_INVALID == ets->cos_params[0].strict) &&
-	     (DCBX_INVALID_COS_BW == ets->cos_params[0].bw_tbl)) ||
-	    ((BNX2X_DCBX_STRICT_INVALID == ets->cos_params[1].strict) &&
-	     (DCBX_INVALID_COS_BW == ets->cos_params[1].bw_tbl))) {
-		BNX2X_ERR("all COS should have at least bw_limit or strict"
-			    "ets->cos_params[0].strict= %x"
-			    "ets->cos_params[0].bw_tbl= %x"
-			    "ets->cos_params[1].strict= %x"
-			    "ets->cos_params[1].bw_tbl= %x",
-			  ets->cos_params[0].strict,
-			  ets->cos_params[0].bw_tbl,
-			  ets->cos_params[1].strict,
-			  ets->cos_params[1].bw_tbl);
-		return;
-	}
-	/* If we join a group and there is bw_tbl and strict then bw rules */
-	if ((DCBX_INVALID_COS_BW != ets->cos_params[0].bw_tbl) &&
-	    (DCBX_INVALID_COS_BW != ets->cos_params[1].bw_tbl)) {
-		u32 bw_tbl_0 = ets->cos_params[0].bw_tbl;
-		u32 bw_tbl_1 = ets->cos_params[1].bw_tbl;
-		/* Do not allow 0-100 configuration
-		 * since PBF does not support it
-		 * force 1-99 instead
-		 */
-		if (bw_tbl_0 == 0) {
-			bw_tbl_0 = 1;
-			bw_tbl_1 = 99;
-		} else if (bw_tbl_1 == 0) {
-			bw_tbl_1 = 1;
-			bw_tbl_0 = 99;
-		}
-
-		bnx2x_ets_bw_limit(&bp->link_params, bw_tbl_0, bw_tbl_1);
-	} else {
-		if (ets->cos_params[0].strict == BNX2X_DCBX_STRICT_COS_HIGHEST)
-			rc = bnx2x_ets_strict(&bp->link_params, 0);
-		else if (ets->cos_params[1].strict
-					== BNX2X_DCBX_STRICT_COS_HIGHEST)
-			rc = bnx2x_ets_strict(&bp->link_params, 1);
-		if (rc)
-			BNX2X_ERR("update_ets_params failed\n");
-	}
-}
-
-/*
- * In E3B0 the configuration may have more than 2 COS.
- */
-void bnx2x_dcbx_update_ets_config(struct bnx2x *bp)
-{
-	struct bnx2x_dcbx_pg_params *ets = &(bp->dcbx_port_params.ets);
-	struct bnx2x_ets_params ets_params = { 0 };
-	u8 i;
-
-	ets_params.num_of_cos = ets->num_of_cos;
-
-	for (i = 0; i < ets->num_of_cos; i++) {
-		/* COS is SP */
-		if (ets->cos_params[i].strict != BNX2X_DCBX_STRICT_INVALID) {
-			if (ets->cos_params[i].bw_tbl != DCBX_INVALID_COS_BW) {
-				BNX2X_ERR("COS can't be not BW and not SP\n");
-				return;
-			}
-
-			ets_params.cos[i].state = bnx2x_cos_state_strict;
-			ets_params.cos[i].params.sp_params.pri =
-						ets->cos_params[i].strict;
-		} else { /* COS is BW */
-			if (ets->cos_params[i].bw_tbl == DCBX_INVALID_COS_BW) {
-				BNX2X_ERR("COS can't be not BW and not SP\n");
-				return;
-			}
-			ets_params.cos[i].state = bnx2x_cos_state_bw;
-			ets_params.cos[i].params.bw_params.bw =
-						(u8)ets->cos_params[i].bw_tbl;
-		}
-	}
-
-	/* Configure the ETS in HW */
-	if (bnx2x_ets_e3b0_config(&bp->link_params, &bp->link_vars,
-				  &ets_params)) {
-		BNX2X_ERR("bnx2x_ets_e3b0_config failed\n");
-		bnx2x_ets_disabled(&bp->link_params, &bp->link_vars);
-	}
-}
-
-static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
-{
-	bnx2x_ets_disabled(&bp->link_params, &bp->link_vars);
-
-	if (!bp->dcbx_port_params.ets.enabled ||
-	    (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR))
-		return;
-
-	if (CHIP_IS_E3B0(bp))
-		bnx2x_dcbx_update_ets_config(bp);
-	else
-		bnx2x_dcbx_2cos_limit_update_ets_config(bp);
-}
-
-#ifdef BCM_DCBNL
-static int bnx2x_dcbx_read_shmem_remote_mib(struct bnx2x *bp)
-{
-	struct lldp_remote_mib remote_mib = {0};
-	u32 dcbx_remote_mib_offset = SHMEM2_RD(bp, dcbx_remote_mib_offset);
-	int rc;
-
-	DP(NETIF_MSG_LINK, "dcbx_remote_mib_offset 0x%x\n",
-	   dcbx_remote_mib_offset);
-
-	if (SHMEM_DCBX_REMOTE_MIB_NONE == dcbx_remote_mib_offset) {
-		BNX2X_ERR("FW doesn't support dcbx_remote_mib_offset\n");
-		return -EINVAL;
-	}
-
-	rc = bnx2x_dcbx_read_mib(bp, (u32 *)&remote_mib, dcbx_remote_mib_offset,
-				 DCBX_READ_REMOTE_MIB);
-
-	if (rc) {
-		BNX2X_ERR("Faild to read remote mib from FW\n");
-		return rc;
-	}
-
-	/* save features and flags */
-	bp->dcbx_remote_feat = remote_mib.features;
-	bp->dcbx_remote_flags = remote_mib.flags;
-	return 0;
-}
-#endif
-
-static int bnx2x_dcbx_read_shmem_neg_results(struct bnx2x *bp)
-{
-	struct lldp_local_mib local_mib = {0};
-	u32 dcbx_neg_res_offset = SHMEM2_RD(bp, dcbx_neg_res_offset);
-	int rc;
-
-	DP(NETIF_MSG_LINK, "dcbx_neg_res_offset 0x%x\n", dcbx_neg_res_offset);
-
-	if (SHMEM_DCBX_NEG_RES_NONE == dcbx_neg_res_offset) {
-		BNX2X_ERR("FW doesn't support dcbx_neg_res_offset\n");
-		return -EINVAL;
-	}
-
-	rc = bnx2x_dcbx_read_mib(bp, (u32 *)&local_mib, dcbx_neg_res_offset,
-				 DCBX_READ_LOCAL_MIB);
-
-	if (rc) {
-		BNX2X_ERR("Faild to read local mib from FW\n");
-		return rc;
-	}
-
-	/* save features and error */
-	bp->dcbx_local_feat = local_mib.features;
-	bp->dcbx_error = local_mib.error;
-	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;
-}
-
-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
-
-static inline void bnx2x_update_drv_flags(struct bnx2x *bp, u32 flags, u32 set)
-{
-	if (SHMEM2_HAS(bp, drv_flags)) {
-		u32 drv_flags;
-		bnx2x_acquire_hw_lock(bp, HW_LOCK_DRV_FLAGS);
-		drv_flags = SHMEM2_RD(bp, drv_flags);
-
-		if (set)
-			SET_FLAGS(drv_flags, flags);
-		else
-			RESET_FLAGS(drv_flags, flags);
-
-		SHMEM2_WR(bp, drv_flags, drv_flags);
-		DP(NETIF_MSG_HW, "drv_flags 0x%08x\n", drv_flags);
-		bnx2x_release_hw_lock(bp, HW_LOCK_DRV_FLAGS);
-	}
-}
-
-static inline void bnx2x_dcbx_update_tc_mapping(struct bnx2x *bp)
-{
-	u8 prio, cos;
-	for (cos = 0; cos < bp->dcbx_port_params.ets.num_of_cos; cos++) {
-		for (prio = 0; prio < BNX2X_MAX_PRIORITY; prio++) {
-			if (bp->dcbx_port_params.ets.cos_params[cos].pri_bitmask
-			    & (1 << prio)) {
-				bp->prio_to_cos[prio] = cos;
-				DP(NETIF_MSG_LINK,
-				   "tx_mapping %d --> %d\n", prio, cos);
-			}
-		}
-	}
-
-	/* setup tc must be called under rtnl lock, but we can't take it here
-	 * as we are handling an attetntion on a work queue which must be
-	 * flushed at some rtnl-locked contexts (e.g. if down)
-	 */
-	if (!test_and_set_bit(BNX2X_SP_RTNL_SETUP_TC, &bp->sp_rtnl_state))
-		schedule_delayed_work(&bp->sp_rtnl_task, 0);
-}
-
-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);
-
-			/* Read rmeote mib if dcbx is in the FW */
-			if (bnx2x_dcbx_read_shmem_remote_mib(bp))
-				return;
-#endif
-			/* Read neg results if dcbx is in the FW */
-			if (bnx2x_dcbx_read_shmem_neg_results(bp))
-				return;
-
-			bnx2x_dump_dcbx_drv_param(bp, &bp->dcbx_local_feat,
-						  bp->dcbx_error);
-
-			bnx2x_get_dcbx_drv_param(bp, &bp->dcbx_local_feat,
-						 bp->dcbx_error);
-
-			/* mark DCBX result for PMF migration */
-			bnx2x_update_drv_flags(bp, DRV_FLAGS_DCB_CONFIGURED, 1);
-#ifdef BCM_DCBNL
-			/**
-			 * Add new app tlvs to dcbnl
-			 */
-			bnx2x_dcbnl_update_applist(bp, false);
-#endif
-			bnx2x_dcbx_stop_hw_tx(bp);
-
-			/* reconfigure the netdevice with the results of the new
-			 * dcbx negotiation.
-			 */
-			bnx2x_dcbx_update_tc_mapping(bp);
-
-			return;
-		}
-	case BNX2X_DCBX_STATE_TX_PAUSED:
-		DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_PAUSED\n");
-		bnx2x_pfc_set_pfc(bp);
-
-		bnx2x_dcbx_update_ets_params(bp);
-		bnx2x_dcbx_resume_hw_tx(bp);
-		return;
-	case BNX2X_DCBX_STATE_TX_RELEASED:
-		DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_RELEASED\n");
-		bnx2x_fw_command(bp, DRV_MSG_CODE_DCBX_PMF_DRV_OK, 0);
-#ifdef BCM_DCBNL
-		/*
-		 * Send a notification for the new negotiated parameters
-		 */
-		dcbnl_cee_notify(bp->dev, RTM_GETDCB, DCB_CMD_CEE_GET, 0, 0);
-#endif
-		return;
-	default:
-		BNX2X_ERR("Unknown DCBX_STATE\n");
-	}
-}
-
-#define LLDP_ADMIN_MIB_OFFSET(bp)	(PORT_MAX*sizeof(struct lldp_params) + \
-				      BP_PORT(bp)*sizeof(struct lldp_admin_mib))
-
-static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
-				u32 dcbx_lldp_params_offset)
-{
-	struct lldp_admin_mib admin_mib;
-	u32 i, other_traf_type = PREDEFINED_APP_IDX_MAX, traf_type = 0;
-	u32 offset = dcbx_lldp_params_offset + LLDP_ADMIN_MIB_OFFSET(bp);
-
-	/*shortcuts*/
-	struct dcbx_features *af = &admin_mib.features;
-	struct bnx2x_config_dcbx_params *dp = &bp->dcbx_config_params;
-
-	memset(&admin_mib, 0, sizeof(struct lldp_admin_mib));
-
-	/* Read the data first */
-	bnx2x_read_data(bp, (u32 *)&admin_mib, offset,
-			sizeof(struct lldp_admin_mib));
-
-	if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON)
-		SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
-	else
-		RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
-
-	if (dp->overwrite_settings == BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE) {
-
-		RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_CEE_VERSION_MASK);
-		admin_mib.ver_cfg_flags |=
-			(dp->admin_dcbx_version << DCBX_CEE_VERSION_SHIFT) &
-			 DCBX_CEE_VERSION_MASK;
-
-		af->ets.enabled = (u8)dp->admin_ets_enable;
-
-		af->pfc.enabled = (u8)dp->admin_pfc_enable;
-
-		/* FOR IEEE dp->admin_tc_supported_tx_enable */
-		if (dp->admin_ets_configuration_tx_enable)
-			SET_FLAGS(admin_mib.ver_cfg_flags,
-				  DCBX_ETS_CONFIG_TX_ENABLED);
-		else
-			RESET_FLAGS(admin_mib.ver_cfg_flags,
-				    DCBX_ETS_CONFIG_TX_ENABLED);
-		/* For IEEE admin_ets_recommendation_tx_enable */
-		if (dp->admin_pfc_tx_enable)
-			SET_FLAGS(admin_mib.ver_cfg_flags,
-				  DCBX_PFC_CONFIG_TX_ENABLED);
-		else
-			RESET_FLAGS(admin_mib.ver_cfg_flags,
-				  DCBX_PFC_CONFIG_TX_ENABLED);
-
-		if (dp->admin_application_priority_tx_enable)
-			SET_FLAGS(admin_mib.ver_cfg_flags,
-				  DCBX_APP_CONFIG_TX_ENABLED);
-		else
-			RESET_FLAGS(admin_mib.ver_cfg_flags,
-				  DCBX_APP_CONFIG_TX_ENABLED);
-
-		if (dp->admin_ets_willing)
-			SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_ETS_WILLING);
-		else
-			RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_ETS_WILLING);
-		/* For IEEE admin_ets_reco_valid */
-		if (dp->admin_pfc_willing)
-			SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_PFC_WILLING);
-		else
-			RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_PFC_WILLING);
-
-		if (dp->admin_app_priority_willing)
-			SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_APP_WILLING);
-		else
-			RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_APP_WILLING);
-
-		for (i = 0 ; i < DCBX_MAX_NUM_PG_BW_ENTRIES; i++) {
-			DCBX_PG_BW_SET(af->ets.pg_bw_tbl, i,
-				(u8)dp->admin_configuration_bw_precentage[i]);
-
-			DP(NETIF_MSG_LINK, "pg_bw_tbl[%d] = %02x\n",
-			   i, DCBX_PG_BW_GET(af->ets.pg_bw_tbl, i));
-		}
-
-		for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++) {
-			DCBX_PRI_PG_SET(af->ets.pri_pg_tbl, i,
-					(u8)dp->admin_configuration_ets_pg[i]);
-
-			DP(NETIF_MSG_LINK, "pri_pg_tbl[%d] = %02x\n",
-			   i, DCBX_PRI_PG_GET(af->ets.pri_pg_tbl, i));
-		}
-
-		/*For IEEE admin_recommendation_bw_precentage
-		 *For IEEE admin_recommendation_ets_pg */
-		af->pfc.pri_en_bitmap = (u8)dp->admin_pfc_bitmap;
-		for (i = 0; i < 4; i++) {
-			if (dp->admin_priority_app_table[i].valid) {
-				struct bnx2x_admin_priority_app_table *table =
-					dp->admin_priority_app_table;
-				if ((ETH_TYPE_FCOE == table[i].app_id) &&
-				   (TRAFFIC_TYPE_ETH == table[i].traffic_type))
-					traf_type = FCOE_APP_IDX;
-				else if ((TCP_PORT_ISCSI == table[i].app_id) &&
-				   (TRAFFIC_TYPE_PORT == table[i].traffic_type))
-					traf_type = ISCSI_APP_IDX;
-				else
-					traf_type = other_traf_type++;
-
-				af->app.app_pri_tbl[traf_type].app_id =
-					table[i].app_id;
-
-				af->app.app_pri_tbl[traf_type].pri_bitmap =
-					(u8)(1 << table[i].priority);
-
-				af->app.app_pri_tbl[traf_type].appBitfield =
-				    (DCBX_APP_ENTRY_VALID);
-
-				af->app.app_pri_tbl[traf_type].appBitfield |=
-				   (TRAFFIC_TYPE_ETH == table[i].traffic_type) ?
-					DCBX_APP_SF_ETH_TYPE : DCBX_APP_SF_PORT;
-			}
-		}
-
-		af->app.default_pri = (u8)dp->admin_default_priority;
-
-	}
-
-	/* Write the data. */
-	bnx2x_write_data(bp, (u32 *)&admin_mib, offset,
-			 sizeof(struct lldp_admin_mib));
-
-}
-
-void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled)
-{
-	if (!CHIP_IS_E1x(bp) && !CHIP_IS_E3(bp)) {
-		bp->dcb_state = dcb_on;
-		bp->dcbx_enabled = dcbx_enabled;
-	} else {
-		bp->dcb_state = false;
-		bp->dcbx_enabled = BNX2X_DCBX_ENABLED_INVALID;
-	}
-	DP(NETIF_MSG_LINK, "DCB state [%s:%s]\n",
-	   dcb_on ? "ON" : "OFF",
-	   dcbx_enabled == BNX2X_DCBX_ENABLED_OFF ? "user-mode" :
-	   dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_OFF ? "on-chip static" :
-	   dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON ?
-	   "on-chip with negotiation" : "invalid");
-}
-
-void bnx2x_dcbx_init_params(struct bnx2x *bp)
-{
-	bp->dcbx_config_params.admin_dcbx_version = 0x0; /* 0 - CEE; 1 - IEEE */
-	bp->dcbx_config_params.admin_ets_willing = 1;
-	bp->dcbx_config_params.admin_pfc_willing = 1;
-	bp->dcbx_config_params.overwrite_settings = 1;
-	bp->dcbx_config_params.admin_ets_enable = 1;
-	bp->dcbx_config_params.admin_pfc_enable = 1;
-	bp->dcbx_config_params.admin_tc_supported_tx_enable = 1;
-	bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
-	bp->dcbx_config_params.admin_pfc_tx_enable = 1;
-	bp->dcbx_config_params.admin_application_priority_tx_enable = 1;
-	bp->dcbx_config_params.admin_ets_reco_valid = 1;
-	bp->dcbx_config_params.admin_app_priority_willing = 1;
-	bp->dcbx_config_params.admin_configuration_bw_precentage[0] = 00;
-	bp->dcbx_config_params.admin_configuration_bw_precentage[1] = 50;
-	bp->dcbx_config_params.admin_configuration_bw_precentage[2] = 50;
-	bp->dcbx_config_params.admin_configuration_bw_precentage[3] = 0;
-	bp->dcbx_config_params.admin_configuration_bw_precentage[4] = 0;
-	bp->dcbx_config_params.admin_configuration_bw_precentage[5] = 0;
-	bp->dcbx_config_params.admin_configuration_bw_precentage[6] = 0;
-	bp->dcbx_config_params.admin_configuration_bw_precentage[7] = 0;
-	bp->dcbx_config_params.admin_configuration_ets_pg[0] = 1;
-	bp->dcbx_config_params.admin_configuration_ets_pg[1] = 0;
-	bp->dcbx_config_params.admin_configuration_ets_pg[2] = 0;
-	bp->dcbx_config_params.admin_configuration_ets_pg[3] = 2;
-	bp->dcbx_config_params.admin_configuration_ets_pg[4] = 0;
-	bp->dcbx_config_params.admin_configuration_ets_pg[5] = 0;
-	bp->dcbx_config_params.admin_configuration_ets_pg[6] = 0;
-	bp->dcbx_config_params.admin_configuration_ets_pg[7] = 0;
-	bp->dcbx_config_params.admin_recommendation_bw_precentage[0] = 0;
-	bp->dcbx_config_params.admin_recommendation_bw_precentage[1] = 1;
-	bp->dcbx_config_params.admin_recommendation_bw_precentage[2] = 2;
-	bp->dcbx_config_params.admin_recommendation_bw_precentage[3] = 0;
-	bp->dcbx_config_params.admin_recommendation_bw_precentage[4] = 7;
-	bp->dcbx_config_params.admin_recommendation_bw_precentage[5] = 5;
-	bp->dcbx_config_params.admin_recommendation_bw_precentage[6] = 6;
-	bp->dcbx_config_params.admin_recommendation_bw_precentage[7] = 7;
-	bp->dcbx_config_params.admin_recommendation_ets_pg[0] = 0;
-	bp->dcbx_config_params.admin_recommendation_ets_pg[1] = 1;
-	bp->dcbx_config_params.admin_recommendation_ets_pg[2] = 2;
-	bp->dcbx_config_params.admin_recommendation_ets_pg[3] = 3;
-	bp->dcbx_config_params.admin_recommendation_ets_pg[4] = 4;
-	bp->dcbx_config_params.admin_recommendation_ets_pg[5] = 5;
-	bp->dcbx_config_params.admin_recommendation_ets_pg[6] = 6;
-	bp->dcbx_config_params.admin_recommendation_ets_pg[7] = 7;
-	bp->dcbx_config_params.admin_pfc_bitmap = 0x8; /* FCoE(3) enable */
-	bp->dcbx_config_params.admin_priority_app_table[0].valid = 1;
-	bp->dcbx_config_params.admin_priority_app_table[1].valid = 1;
-	bp->dcbx_config_params.admin_priority_app_table[2].valid = 0;
-	bp->dcbx_config_params.admin_priority_app_table[3].valid = 0;
-	bp->dcbx_config_params.admin_priority_app_table[0].priority = 3;
-	bp->dcbx_config_params.admin_priority_app_table[1].priority = 0;
-	bp->dcbx_config_params.admin_priority_app_table[2].priority = 0;
-	bp->dcbx_config_params.admin_priority_app_table[3].priority = 0;
-	bp->dcbx_config_params.admin_priority_app_table[0].traffic_type = 0;
-	bp->dcbx_config_params.admin_priority_app_table[1].traffic_type = 1;
-	bp->dcbx_config_params.admin_priority_app_table[2].traffic_type = 0;
-	bp->dcbx_config_params.admin_priority_app_table[3].traffic_type = 0;
-	bp->dcbx_config_params.admin_priority_app_table[0].app_id = 0x8906;
-	bp->dcbx_config_params.admin_priority_app_table[1].app_id = 3260;
-	bp->dcbx_config_params.admin_priority_app_table[2].app_id = 0;
-	bp->dcbx_config_params.admin_priority_app_table[3].app_id = 0;
-	bp->dcbx_config_params.admin_default_priority =
-		bp->dcbx_config_params.admin_priority_app_table[1].priority;
-}
-
-void bnx2x_dcbx_init(struct bnx2x *bp)
-{
-	u32 dcbx_lldp_params_offset = SHMEM_LLDP_DCBX_PARAMS_NONE;
-
-	if (bp->dcbx_enabled <= 0)
-		return;
-
-	/* validate:
-	 * chip of good for dcbx version,
-	 * dcb is wanted
-	 * the function is pmf
-	 * shmem2 contains DCBX support fields
-	 */
-	DP(NETIF_MSG_LINK, "dcb_state %d bp->port.pmf %d\n",
-	   bp->dcb_state, bp->port.pmf);
-
-	if (bp->dcb_state == BNX2X_DCB_STATE_ON && bp->port.pmf &&
-	    SHMEM2_HAS(bp, dcbx_lldp_params_offset)) {
-		dcbx_lldp_params_offset =
-			SHMEM2_RD(bp, dcbx_lldp_params_offset);
-
-		DP(NETIF_MSG_LINK, "dcbx_lldp_params_offset 0x%x\n",
-		   dcbx_lldp_params_offset);
-
-		bnx2x_update_drv_flags(bp, DRV_FLAGS_DCB_CONFIGURED, 0);
-
-		if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) {
-			bnx2x_dcbx_admin_mib_updated_params(bp,
-				dcbx_lldp_params_offset);
-
-			/* Let HW start negotiation */
-			bnx2x_fw_command(bp,
-					 DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG, 0);
-		}
-	}
-}
-static void
-bnx2x_dcbx_print_cos_params(struct bnx2x *bp,
-			    struct bnx2x_func_tx_start_params *pfc_fw_cfg)
-{
-	u8 pri = 0;
-	u8 cos = 0;
-
-	DP(NETIF_MSG_LINK,
-	   "pfc_fw_cfg->dcb_version %x\n", pfc_fw_cfg->dcb_version);
-	DP(NETIF_MSG_LINK,
-	   "pdev->params.dcbx_port_params.pfc."
-	   "priority_non_pauseable_mask %x\n",
-	   bp->dcbx_port_params.pfc.priority_non_pauseable_mask);
-
-	for (cos = 0 ; cos < bp->dcbx_port_params.ets.num_of_cos ; cos++) {
-		DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
-		   "cos_params[%d].pri_bitmask %x\n", cos,
-		   bp->dcbx_port_params.ets.cos_params[cos].pri_bitmask);
-
-		DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
-		   "cos_params[%d].bw_tbl %x\n", cos,
-		   bp->dcbx_port_params.ets.cos_params[cos].bw_tbl);
-
-		DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
-		   "cos_params[%d].strict %x\n", cos,
-		   bp->dcbx_port_params.ets.cos_params[cos].strict);
-
-		DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
-		   "cos_params[%d].pauseable %x\n", cos,
-		   bp->dcbx_port_params.ets.cos_params[cos].pauseable);
-	}
-
-	for (pri = 0; pri < LLFC_DRIVER_TRAFFIC_TYPE_MAX; pri++) {
-		DP(NETIF_MSG_LINK,
-		   "pfc_fw_cfg->traffic_type_to_priority_cos[%d]."
-		   "priority %x\n", pri,
-		   pfc_fw_cfg->traffic_type_to_priority_cos[pri].priority);
-
-		DP(NETIF_MSG_LINK,
-		   "pfc_fw_cfg->traffic_type_to_priority_cos[%d].cos %x\n",
-		   pri, pfc_fw_cfg->traffic_type_to_priority_cos[pri].cos);
-	}
-}
-
-/* fills help_data according to pg_info */
-static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x *bp,
-					    u32 *pg_pri_orginal_spread,
-					    struct pg_help_data *help_data)
-{
-	bool pg_found  = false;
-	u32 i, traf_type, add_traf_type, add_pg;
-	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
-	struct pg_entry_help_data *data = help_data->data; /*shotcut*/
-
-	/* Set to invalid */
-	for (i = 0; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++)
-		data[i].pg = DCBX_ILLEGAL_PG;
-
-	for (add_traf_type = 0;
-	     add_traf_type < LLFC_DRIVER_TRAFFIC_TYPE_MAX; add_traf_type++) {
-		pg_found = false;
-		if (ttp[add_traf_type] < MAX_PFC_PRIORITIES) {
-			add_pg = (u8)pg_pri_orginal_spread[ttp[add_traf_type]];
-			for (traf_type = 0;
-			     traf_type < LLFC_DRIVER_TRAFFIC_TYPE_MAX;
-			     traf_type++) {
-				if (data[traf_type].pg == add_pg) {
-					if (!(data[traf_type].pg_priority &
-					     (1 << ttp[add_traf_type])))
-						data[traf_type].
-							num_of_dif_pri++;
-					data[traf_type].pg_priority |=
-						(1 << ttp[add_traf_type]);
-					pg_found = true;
-					break;
-				}
-			}
-			if (false == pg_found) {
-				data[help_data->num_of_pg].pg = add_pg;
-				data[help_data->num_of_pg].pg_priority =
-						(1 << ttp[add_traf_type]);
-				data[help_data->num_of_pg].num_of_dif_pri = 1;
-				help_data->num_of_pg++;
-			}
-		}
-		DP(NETIF_MSG_LINK,
-		   "add_traf_type %d pg_found %s num_of_pg %d\n",
-		   add_traf_type, (false == pg_found) ? "NO" : "YES",
-		   help_data->num_of_pg);
-	}
-}
-
-static void bnx2x_dcbx_ets_disabled_entry_data(struct bnx2x *bp,
-					       struct cos_help_data *cos_data,
-					       u32 pri_join_mask)
-{
-	/* Only one priority than only one COS */
-	cos_data->data[0].pausable =
-		IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
-	cos_data->data[0].pri_join_mask = pri_join_mask;
-	cos_data->data[0].cos_bw = 100;
-	cos_data->num_of_cos = 1;
-}
-
-static inline void bnx2x_dcbx_add_to_cos_bw(struct bnx2x *bp,
-					    struct cos_entry_help_data *data,
-					    u8 pg_bw)
-{
-	if (data->cos_bw == DCBX_INVALID_COS_BW)
-		data->cos_bw = pg_bw;
-	else
-		data->cos_bw += pg_bw;
-}
-
-static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
-			struct cos_help_data *cos_data,
-			u32 *pg_pri_orginal_spread,
-			struct dcbx_ets_feature *ets)
-{
-	u32	pri_tested	= 0;
-	u8	i		= 0;
-	u8	entry		= 0;
-	u8	pg_entry	= 0;
-	u8	num_of_pri	= LLFC_DRIVER_TRAFFIC_TYPE_MAX;
-
-	cos_data->data[0].pausable = true;
-	cos_data->data[1].pausable = false;
-	cos_data->data[0].pri_join_mask = cos_data->data[1].pri_join_mask = 0;
-
-	for (i = 0 ; i < num_of_pri ; i++) {
-		pri_tested = 1 << bp->dcbx_port_params.
-					app.traffic_type_priority[i];
-
-		if (pri_tested & DCBX_PFC_PRI_NON_PAUSE_MASK(bp)) {
-			cos_data->data[1].pri_join_mask |= pri_tested;
-			entry = 1;
-		} else {
-			cos_data->data[0].pri_join_mask |= pri_tested;
-			entry = 0;
-		}
-		pg_entry = (u8)pg_pri_orginal_spread[bp->dcbx_port_params.
-						app.traffic_type_priority[i]];
-		/* There can be only one strict pg */
-		if (pg_entry < DCBX_MAX_NUM_PG_BW_ENTRIES)
-			bnx2x_dcbx_add_to_cos_bw(bp, &cos_data->data[entry],
-				DCBX_PG_BW_GET(ets->pg_bw_tbl, pg_entry));
-		else
-			/* If we join a group and one is strict
-			 * than the bw rulls */
-			cos_data->data[entry].strict =
-						BNX2X_DCBX_STRICT_COS_HIGHEST;
-	}
-	if ((0 == cos_data->data[0].pri_join_mask) &&
-	    (0 == cos_data->data[1].pri_join_mask))
-		BNX2X_ERR("dcbx error: Both groups must have priorities\n");
-}
-
-
-#ifndef POWER_OF_2
-#define POWER_OF_2(x)	((0 != x) && (0 == (x & (x-1))))
-#endif
-
-static void bnx2x_dcbx_2cos_limit_cee_single_pg_to_cos_params(struct bnx2x *bp,
-					      struct pg_help_data *pg_help_data,
-					      struct cos_help_data *cos_data,
-					      u32 pri_join_mask,
-					      u8 num_of_dif_pri)
-{
-	u8 i = 0;
-	u32 pri_tested = 0;
-	u32 pri_mask_without_pri = 0;
-	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
-	/*debug*/
-	if (num_of_dif_pri == 1) {
-		bnx2x_dcbx_ets_disabled_entry_data(bp, cos_data, pri_join_mask);
-		return;
-	}
-	/* single priority group */
-	if (pg_help_data->data[0].pg < DCBX_MAX_NUM_PG_BW_ENTRIES) {
-		/* If there are both pauseable and non-pauseable priorities,
-		 * the pauseable priorities go to the first queue and
-		 * the non-pauseable priorities go to the second queue.
-		 */
-		if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
-			/* Pauseable */
-			cos_data->data[0].pausable = true;
-			/* Non pauseable.*/
-			cos_data->data[1].pausable = false;
-
-			if (2 == num_of_dif_pri) {
-				cos_data->data[0].cos_bw = 50;
-				cos_data->data[1].cos_bw = 50;
-			}
-
-			if (3 == num_of_dif_pri) {
-				if (POWER_OF_2(DCBX_PFC_PRI_GET_PAUSE(bp,
-							pri_join_mask))) {
-					cos_data->data[0].cos_bw = 33;
-					cos_data->data[1].cos_bw = 67;
-				} else {
-					cos_data->data[0].cos_bw = 67;
-					cos_data->data[1].cos_bw = 33;
-				}
-			}
-
-		} else if (IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask)) {
-			/* If there are only pauseable priorities,
-			 * then one/two priorities go to the first queue
-			 * and one priority goes to the second queue.
-			 */
-			if (2 == num_of_dif_pri) {
-				cos_data->data[0].cos_bw = 50;
-				cos_data->data[1].cos_bw = 50;
-			} else {
-				cos_data->data[0].cos_bw = 67;
-				cos_data->data[1].cos_bw = 33;
-			}
-			cos_data->data[1].pausable = true;
-			cos_data->data[0].pausable = true;
-			/* All priorities except FCOE */
-			cos_data->data[0].pri_join_mask = (pri_join_mask &
-				((u8)~(1 << ttp[LLFC_TRAFFIC_TYPE_FCOE])));
-			/* Only FCOE priority.*/
-			cos_data->data[1].pri_join_mask =
-				(1 << ttp[LLFC_TRAFFIC_TYPE_FCOE]);
-		} else
-			/* If there are only non-pauseable priorities,
-			 * they will all go to the same queue.
-			 */
-			bnx2x_dcbx_ets_disabled_entry_data(bp,
-						cos_data, pri_join_mask);
-	} else {
-		/* priority group which is not BW limited (PG#15):*/
-		if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
-			/* If there are both pauseable and non-pauseable
-			 * priorities, the pauseable priorities go to the first
-			 * queue and the non-pauseable priorities
-			 * go to the second queue.
-			 */
-			if (DCBX_PFC_PRI_GET_PAUSE(bp, pri_join_mask) >
-			    DCBX_PFC_PRI_GET_NON_PAUSE(bp, pri_join_mask)) {
-				cos_data->data[0].strict =
-					BNX2X_DCBX_STRICT_COS_HIGHEST;
-				cos_data->data[1].strict =
-					BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
-						BNX2X_DCBX_STRICT_COS_HIGHEST);
-			} else {
-				cos_data->data[0].strict =
-					BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
-						BNX2X_DCBX_STRICT_COS_HIGHEST);
-				cos_data->data[1].strict =
-					BNX2X_DCBX_STRICT_COS_HIGHEST;
-			}
-			/* Pauseable */
-			cos_data->data[0].pausable = true;
-			/* Non pause-able.*/
-			cos_data->data[1].pausable = false;
-		} else {
-			/* If there are only pauseable priorities or
-			 * only non-pauseable,* the lower priorities go
-			 * to the first queue and the higherpriorities go
-			 * to the second queue.
-			 */
-			cos_data->data[0].pausable =
-				cos_data->data[1].pausable =
-				IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
-
-			for (i = 0 ; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++) {
-				pri_tested = 1 << bp->dcbx_port_params.
-					app.traffic_type_priority[i];
-				/* Remove priority tested */
-				pri_mask_without_pri =
-					(pri_join_mask & ((u8)(~pri_tested)));
-				if (pri_mask_without_pri < pri_tested)
-					break;
-			}
-
-			if (i == LLFC_DRIVER_TRAFFIC_TYPE_MAX)
-				BNX2X_ERR("Invalid value for pri_join_mask -"
-					  " could not find a priority\n");
-
-			cos_data->data[0].pri_join_mask = pri_mask_without_pri;
-			cos_data->data[1].pri_join_mask = pri_tested;
-			/* Both queues are strict priority,
-			 * and that with the highest priority
-			 * gets the highest strict priority in the arbiter.
-			 */
-			cos_data->data[0].strict =
-					BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
-						BNX2X_DCBX_STRICT_COS_HIGHEST);
-			cos_data->data[1].strict =
-					BNX2X_DCBX_STRICT_COS_HIGHEST;
-		}
-	}
-}
-
-static void bnx2x_dcbx_2cos_limit_cee_two_pg_to_cos_params(
-			    struct bnx2x		*bp,
-			    struct  pg_help_data	*pg_help_data,
-			    struct dcbx_ets_feature	*ets,
-			    struct cos_help_data	*cos_data,
-			    u32			*pg_pri_orginal_spread,
-			    u32				pri_join_mask,
-			    u8				num_of_dif_pri)
-{
-	u8 i = 0;
-	u8 pg[DCBX_COS_MAX_NUM_E2] = { 0 };
-
-	/* If there are both pauseable and non-pauseable priorities,
-	 * the pauseable priorities go to the first queue and
-	 * the non-pauseable priorities go to the second queue.
-	 */
-	if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
-		if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp,
-					 pg_help_data->data[0].pg_priority) ||
-		    IS_DCBX_PFC_PRI_MIX_PAUSE(bp,
-					 pg_help_data->data[1].pg_priority)) {
-			/* If one PG contains both pauseable and
-			 * non-pauseable priorities then ETS is disabled.
-			 */
-			bnx2x_dcbx_separate_pauseable_from_non(bp, cos_data,
-					pg_pri_orginal_spread, ets);
-			bp->dcbx_port_params.ets.enabled = false;
-			return;
-		}
-
-		/* Pauseable */
-		cos_data->data[0].pausable = true;
-		/* Non pauseable. */
-		cos_data->data[1].pausable = false;
-		if (IS_DCBX_PFC_PRI_ONLY_PAUSE(bp,
-				pg_help_data->data[0].pg_priority)) {
-			/* 0 is pauseable */
-			cos_data->data[0].pri_join_mask =
-				pg_help_data->data[0].pg_priority;
-			pg[0] = pg_help_data->data[0].pg;
-			cos_data->data[1].pri_join_mask =
-				pg_help_data->data[1].pg_priority;
-			pg[1] = pg_help_data->data[1].pg;
-		} else {/* 1 is pauseable */
-			cos_data->data[0].pri_join_mask =
-				pg_help_data->data[1].pg_priority;
-			pg[0] = pg_help_data->data[1].pg;
-			cos_data->data[1].pri_join_mask =
-				pg_help_data->data[0].pg_priority;
-			pg[1] = pg_help_data->data[0].pg;
-		}
-	} else {
-		/* If there are only pauseable priorities or
-		 * only non-pauseable, each PG goes to a queue.
-		 */
-		cos_data->data[0].pausable = cos_data->data[1].pausable =
-			IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
-		cos_data->data[0].pri_join_mask =
-			pg_help_data->data[0].pg_priority;
-		pg[0] = pg_help_data->data[0].pg;
-		cos_data->data[1].pri_join_mask =
-			pg_help_data->data[1].pg_priority;
-		pg[1] = pg_help_data->data[1].pg;
-	}
-
-	/* There can be only one strict pg */
-	for (i = 0 ; i < ARRAY_SIZE(pg); i++) {
-		if (pg[i] < DCBX_MAX_NUM_PG_BW_ENTRIES)
-			cos_data->data[i].cos_bw =
-				DCBX_PG_BW_GET(ets->pg_bw_tbl, pg[i]);
-		else
-			cos_data->data[i].strict =
-						BNX2X_DCBX_STRICT_COS_HIGHEST;
-	}
-}
-
-static int bnx2x_dcbx_join_pgs(
-			      struct bnx2x            *bp,
-			      struct dcbx_ets_feature *ets,
-			      struct pg_help_data     *pg_help_data,
-			      u8                      required_num_of_pg)
-{
-	u8 entry_joined    = pg_help_data->num_of_pg - 1;
-	u8 entry_removed   = entry_joined + 1;
-	u8 pg_joined       = 0;
-
-	if (required_num_of_pg == 0 || ARRAY_SIZE(pg_help_data->data)
-						<= pg_help_data->num_of_pg) {
-
-		BNX2X_ERR("required_num_of_pg can't be zero\n");
-		return -EINVAL;
-	}
-
-	while (required_num_of_pg < pg_help_data->num_of_pg) {
-		entry_joined = pg_help_data->num_of_pg - 2;
-		entry_removed = entry_joined + 1;
-		/* protect index */
-		entry_removed %= ARRAY_SIZE(pg_help_data->data);
-
-		pg_help_data->data[entry_joined].pg_priority |=
-			pg_help_data->data[entry_removed].pg_priority;
-
-		pg_help_data->data[entry_joined].num_of_dif_pri +=
-			pg_help_data->data[entry_removed].num_of_dif_pri;
-
-		if (pg_help_data->data[entry_joined].pg == DCBX_STRICT_PRI_PG ||
-		    pg_help_data->data[entry_removed].pg == DCBX_STRICT_PRI_PG)
-			/* Entries joined strict priority rules */
-			pg_help_data->data[entry_joined].pg =
-							DCBX_STRICT_PRI_PG;
-		else {
-			/* Entries can be joined join BW */
-			pg_joined = DCBX_PG_BW_GET(ets->pg_bw_tbl,
-					pg_help_data->data[entry_joined].pg) +
-				    DCBX_PG_BW_GET(ets->pg_bw_tbl,
-					pg_help_data->data[entry_removed].pg);
-
-			DCBX_PG_BW_SET(ets->pg_bw_tbl,
-				pg_help_data->data[entry_joined].pg, pg_joined);
-		}
-		/* Joined the entries */
-		pg_help_data->num_of_pg--;
-	}
-
-	return 0;
-}
-
-static void bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
-			      struct bnx2x		*bp,
-			      struct pg_help_data	*pg_help_data,
-			      struct dcbx_ets_feature	*ets,
-			      struct cos_help_data	*cos_data,
-			      u32			*pg_pri_orginal_spread,
-			      u32			pri_join_mask,
-			      u8			num_of_dif_pri)
-{
-	u8 i = 0;
-	u32 pri_tested = 0;
-	u8 entry = 0;
-	u8 pg_entry = 0;
-	bool b_found_strict = false;
-	u8 num_of_pri = LLFC_DRIVER_TRAFFIC_TYPE_MAX;
-
-	cos_data->data[0].pri_join_mask = cos_data->data[1].pri_join_mask = 0;
-	/* If there are both pauseable and non-pauseable priorities,
-	 * the pauseable priorities go to the first queue and the
-	 * non-pauseable priorities go to the second queue.
-	 */
-	if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask))
-		bnx2x_dcbx_separate_pauseable_from_non(bp,
-				cos_data, pg_pri_orginal_spread, ets);
-	else {
-		/* If two BW-limited PG-s were combined to one queue,
-		 * the BW is their sum.
-		 *
-		 * If there are only pauseable priorities or only non-pauseable,
-		 * and there are both BW-limited and non-BW-limited PG-s,
-		 * the BW-limited PG/s go to one queue and the non-BW-limited
-		 * PG/s go to the second queue.
-		 *
-		 * If there are only pauseable priorities or only non-pauseable
-		 * and all are BW limited, then	two priorities go to the first
-		 * queue and one priority goes to the second queue.
-		 *
-		 * We will join this two cases:
-		 * if one is BW limited it will go to the secoend queue
-		 * otherwise the last priority will get it
-		 */
-
-		cos_data->data[0].pausable = cos_data->data[1].pausable =
-			IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
-
-		for (i = 0 ; i < num_of_pri; i++) {
-			pri_tested = 1 << bp->dcbx_port_params.
-				app.traffic_type_priority[i];
-			pg_entry = (u8)pg_pri_orginal_spread[bp->
-				dcbx_port_params.app.traffic_type_priority[i]];
-
-			if (pg_entry < DCBX_MAX_NUM_PG_BW_ENTRIES) {
-				entry = 0;
-
-				if (i == (num_of_pri-1) &&
-				    false == b_found_strict)
-					/* last entry will be handled separately
-					 * If no priority is strict than last
-					 * enty goes to last queue.*/
-					entry = 1;
-				cos_data->data[entry].pri_join_mask |=
-								pri_tested;
-				bnx2x_dcbx_add_to_cos_bw(bp,
-					&cos_data->data[entry],
-					DCBX_PG_BW_GET(ets->pg_bw_tbl,
-						       pg_entry));
-			} else {
-				b_found_strict = true;
-				cos_data->data[1].pri_join_mask |= pri_tested;
-				/* If we join a group and one is strict
-				 * than the bw rulls */
-				cos_data->data[1].strict =
-					BNX2X_DCBX_STRICT_COS_HIGHEST;
-			}
-		}
-	}
-}
-
-
-static void bnx2x_dcbx_2cos_limit_cee_fill_cos_params(struct bnx2x *bp,
-				       struct pg_help_data *help_data,
-				       struct dcbx_ets_feature *ets,
-				       struct cos_help_data *cos_data,
-				       u32 *pg_pri_orginal_spread,
-				       u32 pri_join_mask,
-				       u8 num_of_dif_pri)
-{
-
-	/* default E2 settings */
-	cos_data->num_of_cos = DCBX_COS_MAX_NUM_E2;
-
-	switch (help_data->num_of_pg) {
-	case 1:
-		bnx2x_dcbx_2cos_limit_cee_single_pg_to_cos_params(
-					       bp,
-					       help_data,
-					       cos_data,
-					       pri_join_mask,
-					       num_of_dif_pri);
-		break;
-	case 2:
-		bnx2x_dcbx_2cos_limit_cee_two_pg_to_cos_params(
-					    bp,
-					    help_data,
-					    ets,
-					    cos_data,
-					    pg_pri_orginal_spread,
-					    pri_join_mask,
-					    num_of_dif_pri);
-		break;
-
-	case 3:
-		bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
-					      bp,
-					      help_data,
-					      ets,
-					      cos_data,
-					      pg_pri_orginal_spread,
-					      pri_join_mask,
-					      num_of_dif_pri);
-		break;
-	default:
-		BNX2X_ERR("Wrong pg_help_data.num_of_pg\n");
-		bnx2x_dcbx_ets_disabled_entry_data(bp,
-						   cos_data, pri_join_mask);
-	}
-}
-
-static int bnx2x_dcbx_spread_strict_pri(struct bnx2x *bp,
-					struct cos_help_data *cos_data,
-					u8 entry,
-					u8 num_spread_of_entries,
-					u8 strict_app_pris)
-{
-	u8 strict_pri = BNX2X_DCBX_STRICT_COS_HIGHEST;
-	u8 num_of_app_pri = MAX_PFC_PRIORITIES;
-	u8 app_pri_bit = 0;
-
-	while (num_spread_of_entries && num_of_app_pri > 0) {
-		app_pri_bit = 1 << (num_of_app_pri - 1);
-		if (app_pri_bit & strict_app_pris) {
-			struct cos_entry_help_data *data = &cos_data->
-								data[entry];
-			num_spread_of_entries--;
-			if (num_spread_of_entries == 0) {
-				/* last entry needed put all the entries left */
-				data->cos_bw = DCBX_INVALID_COS_BW;
-				data->strict = strict_pri;
-				data->pri_join_mask = strict_app_pris;
-				data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
-							data->pri_join_mask);
-			} else {
-				strict_app_pris &= ~app_pri_bit;
-
-				data->cos_bw = DCBX_INVALID_COS_BW;
-				data->strict = strict_pri;
-				data->pri_join_mask = app_pri_bit;
-				data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
-							data->pri_join_mask);
-			}
-
-			strict_pri =
-			    BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(strict_pri);
-			entry++;
-		}
-
-		num_of_app_pri--;
-	}
-
-	if (num_spread_of_entries)
-		return -EINVAL;
-
-	return 0;
-}
-
-static u8 bnx2x_dcbx_cee_fill_strict_pri(struct bnx2x *bp,
-					 struct cos_help_data *cos_data,
-					 u8 entry,
-					 u8 num_spread_of_entries,
-					 u8 strict_app_pris)
-{
-
-	if (bnx2x_dcbx_spread_strict_pri(bp, cos_data, entry,
-					 num_spread_of_entries,
-					 strict_app_pris)) {
-		struct cos_entry_help_data *data = &cos_data->
-						    data[entry];
-		/* Fill BW entry */
-		data->cos_bw = DCBX_INVALID_COS_BW;
-		data->strict = BNX2X_DCBX_STRICT_COS_HIGHEST;
-		data->pri_join_mask = strict_app_pris;
-		data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
-				 data->pri_join_mask);
-		return 1;
-	}
-
-	return num_spread_of_entries;
-}
-
-static void bnx2x_dcbx_cee_fill_cos_params(struct bnx2x *bp,
-					   struct pg_help_data *help_data,
-					   struct dcbx_ets_feature *ets,
-					   struct cos_help_data *cos_data,
-					   u32 pri_join_mask)
-
-{
-	u8 need_num_of_entries = 0;
-	u8 i = 0;
-	u8 entry = 0;
-
-	/*
-	 * if the number of requested PG-s in CEE is greater than 3
-	 * then the results are not determined since this is a violation
-	 * of the standard.
-	 */
-	if (help_data->num_of_pg > DCBX_COS_MAX_NUM_E3B0) {
-		if (bnx2x_dcbx_join_pgs(bp, ets, help_data,
-					DCBX_COS_MAX_NUM_E3B0)) {
-			BNX2X_ERR("Unable to reduce the number of PGs -"
-				  "we will disables ETS\n");
-			bnx2x_dcbx_ets_disabled_entry_data(bp, cos_data,
-							   pri_join_mask);
-			return;
-		}
-	}
-
-	for (i = 0 ; i < help_data->num_of_pg; i++) {
-		struct pg_entry_help_data *pg =  &help_data->data[i];
-		if (pg->pg < DCBX_MAX_NUM_PG_BW_ENTRIES) {
-			struct cos_entry_help_data *data = &cos_data->
-							    data[entry];
-			/* Fill BW entry */
-			data->cos_bw = DCBX_PG_BW_GET(ets->pg_bw_tbl, pg->pg);
-			data->strict = BNX2X_DCBX_STRICT_INVALID;
-			data->pri_join_mask = pg->pg_priority;
-			data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
-						data->pri_join_mask);
-
-			entry++;
-		} else {
-			need_num_of_entries =  min_t(u8,
-				(u8)pg->num_of_dif_pri,
-				(u8)DCBX_COS_MAX_NUM_E3B0 -
-						 help_data->num_of_pg + 1);
-			/*
-			 * If there are still VOQ-s which have no associated PG,
-			 * then associate these VOQ-s to PG15. These PG-s will
-			 * be used for SP between priorities on PG15.
-			 */
-			entry += bnx2x_dcbx_cee_fill_strict_pri(bp, cos_data,
-				entry, need_num_of_entries, pg->pg_priority);
-		}
-	}
-
-	/* the entry will represent the number of COSes used */
-	cos_data->num_of_cos = entry;
-}
-static void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
-				       struct pg_help_data *help_data,
-				       struct dcbx_ets_feature *ets,
-				       u32 *pg_pri_orginal_spread)
-{
-	struct cos_help_data         cos_data;
-	u8                    i                           = 0;
-	u32                   pri_join_mask               = 0;
-	u8                    num_of_dif_pri              = 0;
-
-	memset(&cos_data, 0, sizeof(cos_data));
-
-	/* Validate the pg value */
-	for (i = 0; i < help_data->num_of_pg ; i++) {
-		if (DCBX_STRICT_PRIORITY != help_data->data[i].pg &&
-		    DCBX_MAX_NUM_PG_BW_ENTRIES <= help_data->data[i].pg)
-			BNX2X_ERR("Invalid pg[%d] data %x\n", i,
-				  help_data->data[i].pg);
-		pri_join_mask   |=  help_data->data[i].pg_priority;
-		num_of_dif_pri  += help_data->data[i].num_of_dif_pri;
-	}
-
-	/* defaults */
-	cos_data.num_of_cos = 1;
-	for (i = 0; i < ARRAY_SIZE(cos_data.data); i++) {
-		cos_data.data[i].pri_join_mask = 0;
-		cos_data.data[i].pausable = false;
-		cos_data.data[i].strict = BNX2X_DCBX_STRICT_INVALID;
-		cos_data.data[i].cos_bw = DCBX_INVALID_COS_BW;
-	}
-
-	if (CHIP_IS_E3B0(bp))
-		bnx2x_dcbx_cee_fill_cos_params(bp, help_data, ets,
-					       &cos_data, pri_join_mask);
-	else /* E2 + E3A0 */
-		bnx2x_dcbx_2cos_limit_cee_fill_cos_params(bp,
-							  help_data, ets,
-							  &cos_data,
-							  pg_pri_orginal_spread,
-							  pri_join_mask,
-							  num_of_dif_pri);
-
-	for (i = 0; i < cos_data.num_of_cos ; i++) {
-		struct bnx2x_dcbx_cos_params *p =
-			&bp->dcbx_port_params.ets.cos_params[i];
-
-		p->strict = cos_data.data[i].strict;
-		p->bw_tbl = cos_data.data[i].cos_bw;
-		p->pri_bitmask = cos_data.data[i].pri_join_mask;
-		p->pauseable = cos_data.data[i].pausable;
-
-		/* sanity */
-		if (p->bw_tbl != DCBX_INVALID_COS_BW ||
-		    p->strict != BNX2X_DCBX_STRICT_INVALID) {
-			if (p->pri_bitmask == 0)
-				BNX2X_ERR("Invalid pri_bitmask for %d\n", i);
-
-			if (CHIP_IS_E2(bp) || CHIP_IS_E3A0(bp)) {
-
-				if (p->pauseable &&
-				    DCBX_PFC_PRI_GET_NON_PAUSE(bp,
-						p->pri_bitmask) != 0)
-					BNX2X_ERR("Inconsistent config for "
-						  "pausable COS %d\n", i);
-
-				if (!p->pauseable &&
-				    DCBX_PFC_PRI_GET_PAUSE(bp,
-						p->pri_bitmask) != 0)
-					BNX2X_ERR("Inconsistent config for "
-						  "nonpausable COS %d\n", i);
-			}
-		}
-
-		if (p->pauseable)
-			DP(NETIF_MSG_LINK, "COS %d PAUSABLE prijoinmask 0x%x\n",
-				  i, cos_data.data[i].pri_join_mask);
-		else
-			DP(NETIF_MSG_LINK, "COS %d NONPAUSABLE prijoinmask "
-					  "0x%x\n",
-				  i, cos_data.data[i].pri_join_mask);
-	}
-
-	bp->dcbx_port_params.ets.num_of_cos = cos_data.num_of_cos ;
-}
-
-static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
-				u32 *set_configuration_ets_pg,
-				u32 *pri_pg_tbl)
-{
-	int i;
-
-	for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++) {
-		set_configuration_ets_pg[i] = DCBX_PRI_PG_GET(pri_pg_tbl, i);
-
-		DP(NETIF_MSG_LINK, "set_configuration_ets_pg[%d] = 0x%x\n",
-		   i, set_configuration_ets_pg[i]);
-	}
-}
-
-static void bnx2x_dcbx_fw_struct(struct bnx2x *bp,
-				 struct bnx2x_func_tx_start_params *pfc_fw_cfg)
-{
-	u16 pri_bit = 0;
-	u8 cos = 0, pri = 0;
-	struct priority_cos *tt2cos;
-	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
-
-	memset(pfc_fw_cfg, 0, sizeof(*pfc_fw_cfg));
-
-	/* to disable DCB - the structure must be zeroed */
-	if (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR)
-		return;
-
-	/*shortcut*/
-	tt2cos = pfc_fw_cfg->traffic_type_to_priority_cos;
-
-	/* Fw version should be incremented each update */
-	pfc_fw_cfg->dcb_version = ++bp->dcb_version;
-	pfc_fw_cfg->dcb_enabled = 1;
-
-	/* Fill priority parameters */
-	for (pri = 0; pri < LLFC_DRIVER_TRAFFIC_TYPE_MAX; pri++) {
-		tt2cos[pri].priority = ttp[pri];
-		pri_bit = 1 << tt2cos[pri].priority;
-
-		/* Fill COS parameters based on COS calculated to
-		 * make it more general for future use */
-		for (cos = 0; cos < bp->dcbx_port_params.ets.num_of_cos; cos++)
-			if (bp->dcbx_port_params.ets.cos_params[cos].
-						pri_bitmask & pri_bit)
-					tt2cos[pri].cos = cos;
-	}
-
-	/* we never want the FW to add a 0 vlan tag */
-	pfc_fw_cfg->dont_add_pri_0_en = 1;
-
-	bnx2x_dcbx_print_cos_params(bp,	pfc_fw_cfg);
-}
-
-void bnx2x_dcbx_pmf_update(struct bnx2x *bp)
-{
-	/* if we need to syncronize DCBX result from prev PMF
-	 * read it from shmem and update bp accordingly
-	 */
-	if (SHMEM2_HAS(bp, drv_flags) &&
-	   GET_FLAGS(SHMEM2_RD(bp, drv_flags), DRV_FLAGS_DCB_CONFIGURED)) {
-		/* Read neg results if dcbx is in the FW */
-		if (bnx2x_dcbx_read_shmem_neg_results(bp))
-			return;
-
-		bnx2x_dump_dcbx_drv_param(bp, &bp->dcbx_local_feat,
-					  bp->dcbx_error);
-		bnx2x_get_dcbx_drv_param(bp, &bp->dcbx_local_feat,
-					 bp->dcbx_error);
-	}
-}
-
-/* DCB netlink */
-#ifdef BCM_DCBNL
-
-#define BNX2X_DCBX_CAPS		(DCB_CAP_DCBX_LLD_MANAGED | \
-				DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_STATIC)
-
-static inline bool bnx2x_dcbnl_set_valid(struct bnx2x *bp)
-{
-	/* validate dcbnl call that may change HW state:
-	 * DCB is on and DCBX mode was SUCCESSFULLY set by the user.
-	 */
-	return bp->dcb_state && bp->dcbx_mode_uset;
-}
-
-static u8 bnx2x_dcbnl_get_state(struct net_device *netdev)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "state = %d\n", bp->dcb_state);
-	return bp->dcb_state;
-}
-
-static u8 bnx2x_dcbnl_set_state(struct net_device *netdev, u8 state)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "state = %s\n", state ? "on" : "off");
-
-	bnx2x_dcbx_set_state(bp, (state ? true : false), bp->dcbx_enabled);
-	return 0;
-}
-
-static void bnx2x_dcbnl_get_perm_hw_addr(struct net_device *netdev,
-					 u8 *perm_addr)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "GET-PERM-ADDR\n");
-
-	/* first the HW mac address */
-	memcpy(perm_addr, netdev->dev_addr, netdev->addr_len);
-
-#ifdef BCM_CNIC
-	/* second SAN address */
-	memcpy(perm_addr+netdev->addr_len, bp->fip_mac, netdev->addr_len);
-#endif
-}
-
-static void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device *netdev, int prio,
-					u8 prio_type, u8 pgid, u8 bw_pct,
-					u8 up_map)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-
-	DP(NETIF_MSG_LINK, "prio[%d] = %d\n", prio, pgid);
-	if (!bnx2x_dcbnl_set_valid(bp) || prio >= DCBX_MAX_NUM_PRI_PG_ENTRIES)
-		return;
-
-	/**
-	 * bw_pct ingnored -	band-width percentage devision between user
-	 *			priorities within the same group is not
-	 *			standard and hence not supported
-	 *
-	 * prio_type igonred -	priority levels within the same group are not
-	 *			standard and hence are not supported. According
-	 *			to the standard pgid 15 is dedicated to strict
-	 *			prioirty traffic (on the port level).
-	 *
-	 * up_map ignored
-	 */
-
-	bp->dcbx_config_params.admin_configuration_ets_pg[prio] = pgid;
-	bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
-}
-
-static void bnx2x_dcbnl_set_pg_bwgcfg_tx(struct net_device *netdev,
-					 int pgid, u8 bw_pct)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "pgid[%d] = %d\n", pgid, bw_pct);
-
-	if (!bnx2x_dcbnl_set_valid(bp) || pgid >= DCBX_MAX_NUM_PG_BW_ENTRIES)
-		return;
-
-	bp->dcbx_config_params.admin_configuration_bw_precentage[pgid] = bw_pct;
-	bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
-}
-
-static void bnx2x_dcbnl_set_pg_tccfg_rx(struct net_device *netdev, int prio,
-					u8 prio_type, u8 pgid, u8 bw_pct,
-					u8 up_map)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "Nothing to set; No RX support\n");
-}
-
-static void bnx2x_dcbnl_set_pg_bwgcfg_rx(struct net_device *netdev,
-					 int pgid, u8 bw_pct)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "Nothing to set; No RX support\n");
-}
-
-static void bnx2x_dcbnl_get_pg_tccfg_tx(struct net_device *netdev, int prio,
-					u8 *prio_type, u8 *pgid, u8 *bw_pct,
-					u8 *up_map)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "prio = %d\n", prio);
-
-	/**
-	 * bw_pct ingnored -	band-width percentage devision between user
-	 *			priorities within the same group is not
-	 *			standard and hence not supported
-	 *
-	 * prio_type igonred -	priority levels within the same group are not
-	 *			standard and hence are not supported. According
-	 *			to the standard pgid 15 is dedicated to strict
-	 *			prioirty traffic (on the port level).
-	 *
-	 * up_map ignored
-	 */
-	*up_map = *bw_pct = *prio_type = *pgid = 0;
-
-	if (!bp->dcb_state || prio >= DCBX_MAX_NUM_PRI_PG_ENTRIES)
-		return;
-
-	*pgid = DCBX_PRI_PG_GET(bp->dcbx_local_feat.ets.pri_pg_tbl, prio);
-}
-
-static void bnx2x_dcbnl_get_pg_bwgcfg_tx(struct net_device *netdev,
-					 int pgid, u8 *bw_pct)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "pgid = %d\n", pgid);
-
-	*bw_pct = 0;
-
-	if (!bp->dcb_state || pgid >= DCBX_MAX_NUM_PG_BW_ENTRIES)
-		return;
-
-	*bw_pct = DCBX_PG_BW_GET(bp->dcbx_local_feat.ets.pg_bw_tbl, pgid);
-}
-
-static void bnx2x_dcbnl_get_pg_tccfg_rx(struct net_device *netdev, int prio,
-					u8 *prio_type, u8 *pgid, u8 *bw_pct,
-					u8 *up_map)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "Nothing to get; No RX support\n");
-
-	*prio_type = *pgid = *bw_pct = *up_map = 0;
-}
-
-static void bnx2x_dcbnl_get_pg_bwgcfg_rx(struct net_device *netdev,
-					 int pgid, u8 *bw_pct)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "Nothing to get; No RX support\n");
-
-	*bw_pct = 0;
-}
-
-static void bnx2x_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio,
-				    u8 setting)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "prio[%d] = %d\n", prio, setting);
-
-	if (!bnx2x_dcbnl_set_valid(bp) || prio >= MAX_PFC_PRIORITIES)
-		return;
-
-	bp->dcbx_config_params.admin_pfc_bitmap |= ((setting ? 1 : 0) << prio);
-
-	if (setting)
-		bp->dcbx_config_params.admin_pfc_tx_enable = 1;
-}
-
-static void bnx2x_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio,
-				    u8 *setting)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "prio = %d\n", prio);
-
-	*setting = 0;
-
-	if (!bp->dcb_state || prio >= MAX_PFC_PRIORITIES)
-		return;
-
-	*setting = (bp->dcbx_local_feat.pfc.pri_en_bitmap >> prio) & 0x1;
-}
-
-static u8 bnx2x_dcbnl_set_all(struct net_device *netdev)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	int rc = 0;
-
-	DP(NETIF_MSG_LINK, "SET-ALL\n");
-
-	if (!bnx2x_dcbnl_set_valid(bp))
-		return 1;
-
-	if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
-		netdev_err(bp->dev, "Handling parity error recovery. "
-				"Try again later\n");
-		return 1;
-	}
-	if (netif_running(bp->dev)) {
-		bnx2x_nic_unload(bp, UNLOAD_NORMAL);
-		rc = bnx2x_nic_load(bp, LOAD_NORMAL);
-	}
-	DP(NETIF_MSG_LINK, "set_dcbx_params done (%d)\n", rc);
-	if (rc)
-		return 1;
-
-	return 0;
-}
-
-static u8 bnx2x_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	u8 rval = 0;
-
-	if (bp->dcb_state) {
-		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;	/* 8 priorities for PGs */
-			break;
-		case DCB_CAP_ATTR_PFC_TCS:
-			*cap = 0x80;	/* 8 priorities for PFC */
-			break;
-		case DCB_CAP_ATTR_GSP:
-			*cap = true;
-			break;
-		case DCB_CAP_ATTR_BCN:
-			*cap = false;
-			break;
-		case DCB_CAP_ATTR_DCBX:
-			*cap = BNX2X_DCBX_CAPS;
-			break;
-		default:
-			rval = -EINVAL;
-			break;
-		}
-	} else
-		rval = -EINVAL;
-
-	DP(NETIF_MSG_LINK, "capid %d:%x\n", capid, *cap);
-	return rval;
-}
-
-static u8 bnx2x_dcbnl_get_numtcs(struct net_device *netdev, int tcid, u8 *num)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	u8 rval = 0;
-
-	DP(NETIF_MSG_LINK, "tcid %d\n", tcid);
-
-	if (bp->dcb_state) {
-		switch (tcid) {
-		case DCB_NUMTCS_ATTR_PG:
-			*num = CHIP_IS_E3B0(bp) ? DCBX_COS_MAX_NUM_E3B0 :
-						  DCBX_COS_MAX_NUM_E2;
-			break;
-		case DCB_NUMTCS_ATTR_PFC:
-			*num = CHIP_IS_E3B0(bp) ? DCBX_COS_MAX_NUM_E3B0 :
-						  DCBX_COS_MAX_NUM_E2;
-			break;
-		default:
-			rval = -EINVAL;
-			break;
-		}
-	} else
-		rval = -EINVAL;
-
-	return rval;
-}
-
-static u8 bnx2x_dcbnl_set_numtcs(struct net_device *netdev, int tcid, u8 num)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "num tcs = %d; Not supported\n", num);
-	return -EINVAL;
-}
-
-static u8  bnx2x_dcbnl_get_pfc_state(struct net_device *netdev)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "state = %d\n", bp->dcbx_local_feat.pfc.enabled);
-
-	if (!bp->dcb_state)
-		return 0;
-
-	return bp->dcbx_local_feat.pfc.enabled;
-}
-
-static void bnx2x_dcbnl_set_pfc_state(struct net_device *netdev, u8 state)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "state = %s\n", state ? "on" : "off");
-
-	if (!bnx2x_dcbnl_set_valid(bp))
-		return;
-
-	bp->dcbx_config_params.admin_pfc_tx_enable =
-	bp->dcbx_config_params.admin_pfc_enable = (state ? 1 : 0);
-}
-
-static void bnx2x_admin_app_set_ent(
-	struct bnx2x_admin_priority_app_table *app_ent,
-	u8 idtype, u16 idval, u8 up)
-{
-	app_ent->valid = 1;
-
-	switch (idtype) {
-	case DCB_APP_IDTYPE_ETHTYPE:
-		app_ent->traffic_type = TRAFFIC_TYPE_ETH;
-		break;
-	case DCB_APP_IDTYPE_PORTNUM:
-		app_ent->traffic_type = TRAFFIC_TYPE_PORT;
-		break;
-	default:
-		break; /* never gets here */
-	}
-	app_ent->app_id = idval;
-	app_ent->priority = up;
-}
-
-static bool bnx2x_admin_app_is_equal(
-	struct bnx2x_admin_priority_app_table *app_ent,
-	u8 idtype, u16 idval)
-{
-	if (!app_ent->valid)
-		return false;
-
-	switch (idtype) {
-	case DCB_APP_IDTYPE_ETHTYPE:
-		if (app_ent->traffic_type != TRAFFIC_TYPE_ETH)
-			return false;
-		break;
-	case DCB_APP_IDTYPE_PORTNUM:
-		if (app_ent->traffic_type != TRAFFIC_TYPE_PORT)
-			return false;
-		break;
-	default:
-		return false;
-	}
-	if (app_ent->app_id != idval)
-		return false;
-
-	return true;
-}
-
-static int bnx2x_set_admin_app_up(struct bnx2x *bp, u8 idtype, u16 idval, u8 up)
-{
-	int i, ff;
-
-	/* iterate over the app entries looking for idtype and idval */
-	for (i = 0, ff = -1; i < 4; i++) {
-		struct bnx2x_admin_priority_app_table *app_ent =
-			&bp->dcbx_config_params.admin_priority_app_table[i];
-		if (bnx2x_admin_app_is_equal(app_ent, idtype, idval))
-			break;
-
-		if (ff < 0 && !app_ent->valid)
-			ff = i;
-	}
-	if (i < 4)
-		/* if found overwrite up */
-		bp->dcbx_config_params.
-			admin_priority_app_table[i].priority = up;
-	else if (ff >= 0)
-		/* not found use first-free */
-		bnx2x_admin_app_set_ent(
-			&bp->dcbx_config_params.admin_priority_app_table[ff],
-			idtype, idval, up);
-	else
-		/* app table is full */
-		return -EBUSY;
-
-	/* up configured, if not 0 make sure feature is enabled */
-	if (up)
-		bp->dcbx_config_params.admin_application_priority_tx_enable = 1;
-
-	return 0;
-}
-
-static u8 bnx2x_dcbnl_set_app_up(struct net_device *netdev, u8 idtype,
-				 u16 idval, u8 up)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-
-	DP(NETIF_MSG_LINK, "app_type %d, app_id %x, prio bitmap %d\n",
-	   idtype, idval, up);
-
-	if (!bnx2x_dcbnl_set_valid(bp))
-		return -EINVAL;
-
-	/* verify idtype */
-	switch (idtype) {
-	case DCB_APP_IDTYPE_ETHTYPE:
-	case DCB_APP_IDTYPE_PORTNUM:
-		break;
-	default:
-		return -EINVAL;
-	}
-	return bnx2x_set_admin_app_up(bp, idtype, idval, up);
-}
-
-static u8 bnx2x_dcbnl_get_dcbx(struct net_device *netdev)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	u8 state;
-
-	state = DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_CEE;
-
-	if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_OFF)
-		state |= DCB_CAP_DCBX_STATIC;
-
-	return state;
-}
-
-static u8 bnx2x_dcbnl_set_dcbx(struct net_device *netdev, u8 state)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "state = %02x\n", state);
-
-	/* set dcbx mode */
-
-	if ((state & BNX2X_DCBX_CAPS) != state) {
-		BNX2X_ERR("Requested DCBX mode %x is beyond advertised "
-			  "capabilities\n", state);
-		return 1;
-	}
-
-	if (bp->dcb_state != BNX2X_DCB_STATE_ON) {
-		BNX2X_ERR("DCB turned off, DCBX configuration is invalid\n");
-		return 1;
-	}
-
-	if (state & DCB_CAP_DCBX_STATIC)
-		bp->dcbx_enabled = BNX2X_DCBX_ENABLED_ON_NEG_OFF;
-	else
-		bp->dcbx_enabled = BNX2X_DCBX_ENABLED_ON_NEG_ON;
-
-	bp->dcbx_mode_uset = true;
-	return 0;
-}
-
-static u8 bnx2x_dcbnl_get_featcfg(struct net_device *netdev, int featid,
-				  u8 *flags)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	u8 rval = 0;
-
-	DP(NETIF_MSG_LINK, "featid %d\n", featid);
-
-	if (bp->dcb_state) {
-		*flags = 0;
-		switch (featid) {
-		case DCB_FEATCFG_ATTR_PG:
-			if (bp->dcbx_local_feat.ets.enabled)
-				*flags |= DCB_FEATCFG_ENABLE;
-			if (bp->dcbx_error & DCBX_LOCAL_ETS_ERROR)
-				*flags |= DCB_FEATCFG_ERROR;
-			break;
-		case DCB_FEATCFG_ATTR_PFC:
-			if (bp->dcbx_local_feat.pfc.enabled)
-				*flags |= DCB_FEATCFG_ENABLE;
-			if (bp->dcbx_error & (DCBX_LOCAL_PFC_ERROR |
-			    DCBX_LOCAL_PFC_MISMATCH))
-				*flags |= DCB_FEATCFG_ERROR;
-			break;
-		case DCB_FEATCFG_ATTR_APP:
-			if (bp->dcbx_local_feat.app.enabled)
-				*flags |= DCB_FEATCFG_ENABLE;
-			if (bp->dcbx_error & (DCBX_LOCAL_APP_ERROR |
-			    DCBX_LOCAL_APP_MISMATCH))
-				*flags |= DCB_FEATCFG_ERROR;
-			break;
-		default:
-			rval = -EINVAL;
-			break;
-		}
-	} else
-		rval = -EINVAL;
-
-	return rval;
-}
-
-static u8 bnx2x_dcbnl_set_featcfg(struct net_device *netdev, int featid,
-				  u8 flags)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	u8 rval = 0;
-
-	DP(NETIF_MSG_LINK, "featid = %d flags = %02x\n", featid, flags);
-
-	/* ignore the 'advertise' flag */
-	if (bnx2x_dcbnl_set_valid(bp)) {
-		switch (featid) {
-		case DCB_FEATCFG_ATTR_PG:
-			bp->dcbx_config_params.admin_ets_enable =
-				flags & DCB_FEATCFG_ENABLE ? 1 : 0;
-			bp->dcbx_config_params.admin_ets_willing =
-				flags & DCB_FEATCFG_WILLING ? 1 : 0;
-			break;
-		case DCB_FEATCFG_ATTR_PFC:
-			bp->dcbx_config_params.admin_pfc_enable =
-				flags & DCB_FEATCFG_ENABLE ? 1 : 0;
-			bp->dcbx_config_params.admin_pfc_willing =
-				flags & DCB_FEATCFG_WILLING ? 1 : 0;
-			break;
-		case DCB_FEATCFG_ATTR_APP:
-			/* ignore enable, always enabled */
-			bp->dcbx_config_params.admin_app_priority_willing =
-				flags & DCB_FEATCFG_WILLING ? 1 : 0;
-			break;
-		default:
-			rval = -EINVAL;
-			break;
-		}
-	} else
-		rval = -EINVAL;
-
-	return rval;
-}
-
-static int bnx2x_peer_appinfo(struct net_device *netdev,
-			      struct dcb_peer_app_info *info, u16* app_count)
-{
-	int i;
-	struct bnx2x *bp = netdev_priv(netdev);
-
-	DP(NETIF_MSG_LINK, "APP-INFO\n");
-
-	info->willing = (bp->dcbx_remote_flags & DCBX_APP_REM_WILLING) ?: 0;
-	info->error = (bp->dcbx_remote_flags & DCBX_APP_RX_ERROR) ?: 0;
-	*app_count = 0;
-
-	for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++)
-		if (bp->dcbx_remote_feat.app.app_pri_tbl[i].appBitfield &
-		    DCBX_APP_ENTRY_VALID)
-			(*app_count)++;
-	return 0;
-}
-
-static int bnx2x_peer_apptable(struct net_device *netdev,
-			       struct dcb_app *table)
-{
-	int i, j;
-	struct bnx2x *bp = netdev_priv(netdev);
-
-	DP(NETIF_MSG_LINK, "APP-TABLE\n");
-
-	for (i = 0, j = 0; i < DCBX_MAX_APP_PROTOCOL; i++) {
-		struct dcbx_app_priority_entry *ent =
-			&bp->dcbx_remote_feat.app.app_pri_tbl[i];
-
-		if (ent->appBitfield & DCBX_APP_ENTRY_VALID) {
-			table[j].selector = bnx2x_dcbx_dcbnl_app_idtype(ent);
-			table[j].priority = bnx2x_dcbx_dcbnl_app_up(ent);
-			table[j++].protocol = ent->app_id;
-		}
-	}
-	return 0;
-}
-
-static int bnx2x_cee_peer_getpg(struct net_device *netdev, struct cee_pg *pg)
-{
-	int i;
-	struct bnx2x *bp = netdev_priv(netdev);
-
-	pg->willing = (bp->dcbx_remote_flags & DCBX_ETS_REM_WILLING) ?: 0;
-
-	for (i = 0; i < CEE_DCBX_MAX_PGS; i++) {
-		pg->pg_bw[i] =
-			DCBX_PG_BW_GET(bp->dcbx_remote_feat.ets.pg_bw_tbl, i);
-		pg->prio_pg[i] =
-			DCBX_PRI_PG_GET(bp->dcbx_remote_feat.ets.pri_pg_tbl, i);
-	}
-	return 0;
-}
-
-static int bnx2x_cee_peer_getpfc(struct net_device *netdev,
-				 struct cee_pfc *pfc)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	pfc->tcs_supported = bp->dcbx_remote_feat.pfc.pfc_caps;
-	pfc->pfc_en = bp->dcbx_remote_feat.pfc.pri_en_bitmap;
-	return 0;
-}
-
-const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops = {
-	.getstate		= bnx2x_dcbnl_get_state,
-	.setstate		= bnx2x_dcbnl_set_state,
-	.getpermhwaddr		= bnx2x_dcbnl_get_perm_hw_addr,
-	.setpgtccfgtx		= bnx2x_dcbnl_set_pg_tccfg_tx,
-	.setpgbwgcfgtx		= bnx2x_dcbnl_set_pg_bwgcfg_tx,
-	.setpgtccfgrx		= bnx2x_dcbnl_set_pg_tccfg_rx,
-	.setpgbwgcfgrx		= bnx2x_dcbnl_set_pg_bwgcfg_rx,
-	.getpgtccfgtx		= bnx2x_dcbnl_get_pg_tccfg_tx,
-	.getpgbwgcfgtx		= bnx2x_dcbnl_get_pg_bwgcfg_tx,
-	.getpgtccfgrx		= bnx2x_dcbnl_get_pg_tccfg_rx,
-	.getpgbwgcfgrx		= bnx2x_dcbnl_get_pg_bwgcfg_rx,
-	.setpfccfg		= bnx2x_dcbnl_set_pfc_cfg,
-	.getpfccfg		= bnx2x_dcbnl_get_pfc_cfg,
-	.setall			= bnx2x_dcbnl_set_all,
-	.getcap			= bnx2x_dcbnl_get_cap,
-	.getnumtcs		= bnx2x_dcbnl_get_numtcs,
-	.setnumtcs		= bnx2x_dcbnl_set_numtcs,
-	.getpfcstate		= bnx2x_dcbnl_get_pfc_state,
-	.setpfcstate		= bnx2x_dcbnl_set_pfc_state,
-	.setapp			= bnx2x_dcbnl_set_app_up,
-	.getdcbx		= bnx2x_dcbnl_get_dcbx,
-	.setdcbx		= bnx2x_dcbnl_set_dcbx,
-	.getfeatcfg		= bnx2x_dcbnl_get_featcfg,
-	.setfeatcfg		= bnx2x_dcbnl_set_featcfg,
-	.peer_getappinfo	= bnx2x_peer_appinfo,
-	.peer_getapptable	= bnx2x_peer_apptable,
-	.cee_peer_getpg		= bnx2x_cee_peer_getpg,
-	.cee_peer_getpfc	= bnx2x_cee_peer_getpfc,
-};
-
-#endif /* BCM_DCBNL */
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_dcb.h linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_dcb.h
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_dcb.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_dcb.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,203 +0,0 @@
-/* bnx2x_dcb.h: Broadcom Everest network driver.
- *
- * Copyright 2009-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
- * under the terms of the GNU General Public License version 2, available
- * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
- *
- * Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a
- * license other than the GPL, without Broadcom's express prior written
- * consent.
- *
- * Maintained by: Eilon Greenstein <eilong@broadcom.com>
- * Written by: Dmitry Kravkov
- *
- */
-#ifndef BNX2X_DCB_H
-#define BNX2X_DCB_H
-
-#include "bnx2x_hsi.h"
-
-#define LLFC_DRIVER_TRAFFIC_TYPE_MAX 3 /* NW, iSCSI, FCoE */
-struct bnx2x_dcbx_app_params {
-	u32 enabled;
-	u32 traffic_type_priority[LLFC_DRIVER_TRAFFIC_TYPE_MAX];
-};
-
-#define DCBX_COS_MAX_NUM_E2	DCBX_E2E3_MAX_NUM_COS
-/* bnx2x currently limits numbers of supported COSes to 3 to be extended to 6 */
-#define BNX2X_MAX_COS_SUPPORT	3
-#define DCBX_COS_MAX_NUM_E3B0	BNX2X_MAX_COS_SUPPORT
-#define DCBX_COS_MAX_NUM	BNX2X_MAX_COS_SUPPORT
-
-struct bnx2x_dcbx_cos_params {
-	u32	bw_tbl;
-	u32	pri_bitmask;
-	/*
-	 * strict priority: valid values are 0..5; 0 is highest priority.
-	 * There can't be two COSes with the same priority.
-	 */
-	u8	strict;
-#define BNX2X_DCBX_STRICT_INVALID			DCBX_COS_MAX_NUM
-#define BNX2X_DCBX_STRICT_COS_HIGHEST			0
-#define BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(sp)	((sp) + 1)
-	u8	pauseable;
-};
-
-struct bnx2x_dcbx_pg_params {
-	u32 enabled;
-	u8 num_of_cos; /* valid COS entries */
-	struct bnx2x_dcbx_cos_params	cos_params[DCBX_COS_MAX_NUM];
-};
-
-struct bnx2x_dcbx_pfc_params {
-	u32 enabled;
-	u32 priority_non_pauseable_mask;
-};
-
-struct bnx2x_dcbx_port_params {
-	struct bnx2x_dcbx_pfc_params pfc;
-	struct bnx2x_dcbx_pg_params  ets;
-	struct bnx2x_dcbx_app_params app;
-};
-
-#define BNX2X_DCBX_CONFIG_INV_VALUE			(0xFFFFFFFF)
-#define BNX2X_DCBX_OVERWRITE_SETTINGS_DISABLE		0
-#define BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE		1
-#define BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID	(BNX2X_DCBX_CONFIG_INV_VALUE)
-#define BNX2X_IS_ETS_ENABLED(bp) ((bp)->dcb_state == BNX2X_DCB_STATE_ON &&\
-				  (bp)->dcbx_port_params.ets.enabled)
-
-struct bnx2x_config_lldp_params {
-	u32 overwrite_settings;
-	u32 msg_tx_hold;
-	u32 msg_fast_tx;
-	u32 tx_credit_max;
-	u32 msg_tx_interval;
-	u32 tx_fast;
-};
-
-struct bnx2x_admin_priority_app_table {
-		u32 valid;
-		u32 priority;
-#define INVALID_TRAFFIC_TYPE_PRIORITY	(0xFFFFFFFF)
-		u32 traffic_type;
-#define TRAFFIC_TYPE_ETH		0
-#define TRAFFIC_TYPE_PORT		1
-		u32 app_id;
-};
-
-struct bnx2x_config_dcbx_params {
-	u32 overwrite_settings;
-	u32 admin_dcbx_version;
-	u32 admin_ets_enable;
-	u32 admin_pfc_enable;
-	u32 admin_tc_supported_tx_enable;
-	u32 admin_ets_configuration_tx_enable;
-	u32 admin_ets_recommendation_tx_enable;
-	u32 admin_pfc_tx_enable;
-	u32 admin_application_priority_tx_enable;
-	u32 admin_ets_willing;
-	u32 admin_ets_reco_valid;
-	u32 admin_pfc_willing;
-	u32 admin_app_priority_willing;
-	u32 admin_configuration_bw_precentage[8];
-	u32 admin_configuration_ets_pg[8];
-	u32 admin_recommendation_bw_precentage[8];
-	u32 admin_recommendation_ets_pg[8];
-	u32 admin_pfc_bitmap;
-	struct bnx2x_admin_priority_app_table admin_priority_app_table[4];
-	u32 admin_default_priority;
-};
-
-#define GET_FLAGS(flags, bits)		((flags) & (bits))
-#define SET_FLAGS(flags, bits)		((flags) |= (bits))
-#define RESET_FLAGS(flags, bits)	((flags) &= ~(bits))
-
-enum {
-	DCBX_READ_LOCAL_MIB,
-	DCBX_READ_REMOTE_MIB
-};
-
-#define ETH_TYPE_FCOE		(0x8906)
-#define TCP_PORT_ISCSI		(0xCBC)
-
-#define PFC_VALUE_FRAME_SIZE				(512)
-#define PFC_QUANTA_IN_NANOSEC_FROM_SPEED_MEGA(mega_speed)  \
-				((1000 * PFC_VALUE_FRAME_SIZE)/(mega_speed))
-
-#define PFC_BRB1_REG_HIGH_LLFC_LOW_THRESHOLD			130
-#define PFC_BRB1_REG_HIGH_LLFC_HIGH_THRESHOLD			170
-
-
-
-struct cos_entry_help_data {
-	u32			pri_join_mask;
-	u32			cos_bw;
-	u8			strict;
-	bool			pausable;
-};
-
-struct cos_help_data {
-	struct cos_entry_help_data	data[DCBX_COS_MAX_NUM];
-	u8				num_of_cos;
-};
-
-#define DCBX_ILLEGAL_PG				(0xFF)
-#define DCBX_PFC_PRI_MASK			(0xFF)
-#define DCBX_STRICT_PRIORITY			(15)
-#define DCBX_INVALID_COS_BW			(0xFFFFFFFF)
-#define DCBX_PFC_PRI_NON_PAUSE_MASK(bp)		\
-			((bp)->dcbx_port_params.pfc.priority_non_pauseable_mask)
-#define DCBX_PFC_PRI_PAUSE_MASK(bp)		\
-					((u8)~DCBX_PFC_PRI_NON_PAUSE_MASK(bp))
-#define DCBX_PFC_PRI_GET_PAUSE(bp, pg_pri)	\
-				((pg_pri) & (DCBX_PFC_PRI_PAUSE_MASK(bp)))
-#define DCBX_PFC_PRI_GET_NON_PAUSE(bp, pg_pri)	\
-			(DCBX_PFC_PRI_NON_PAUSE_MASK(bp) & (pg_pri))
-#define DCBX_IS_PFC_PRI_SOME_PAUSE(bp, pg_pri)	\
-			(0 != DCBX_PFC_PRI_GET_PAUSE(bp, pg_pri))
-#define IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pg_pri)	\
-			(pg_pri == DCBX_PFC_PRI_GET_PAUSE((bp), (pg_pri)))
-#define IS_DCBX_PFC_PRI_ONLY_NON_PAUSE(bp, pg_pri)\
-			((pg_pri) == DCBX_PFC_PRI_GET_NON_PAUSE((bp), (pg_pri)))
-#define IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pg_pri)	\
-			(!(IS_DCBX_PFC_PRI_ONLY_NON_PAUSE((bp), (pg_pri)) || \
-			 IS_DCBX_PFC_PRI_ONLY_PAUSE((bp), (pg_pri))))
-
-
-struct pg_entry_help_data {
-	u8	num_of_dif_pri;
-	u8	pg;
-	u32	pg_priority;
-};
-
-struct pg_help_data {
-	struct pg_entry_help_data	data[LLFC_DRIVER_TRAFFIC_TYPE_MAX];
-	u8				num_of_pg;
-};
-
-/* forward DCB/PFC related declarations */
-struct bnx2x;
-void bnx2x_dcbx_update(struct work_struct *work);
-void bnx2x_dcbx_init_params(struct bnx2x *bp);
-void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled);
-
-enum {
-	BNX2X_DCBX_STATE_NEG_RECEIVED = 0x1,
-	BNX2X_DCBX_STATE_TX_PAUSED,
-	BNX2X_DCBX_STATE_TX_RELEASED
-};
-
-void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state);
-void bnx2x_dcbx_pmf_update(struct bnx2x *bp);
-/* DCB netlink */
-#ifdef BCM_DCBNL
-extern const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops;
-int bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall);
-#endif /* BCM_DCBNL */
-
-#endif /* BNX2X_DCB_H */
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_dump.h linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_dump.h
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_dump.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_dump.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1156 +0,0 @@
-/* bnx2x_dump.h: Broadcom Everest network driver.
- *
- * Copyright (c) 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
- * under the terms of the GNU General Public License version 2, available
- * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
- *
- * Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a
- * license other than the GPL, without Broadcom's express prior written
- * consent.
- */
-
-
-/* This struct holds a signature to ensure the dump returned from the driver
- * match the meta data file inserted to grc_dump.tcl
- * The signature is time stamp, diag version and grc_dump version
- */
-
-#ifndef BNX2X_DUMP_H
-#define BNX2X_DUMP_H
-
-
-
-/*definitions */
-#define XSTORM_WAITP_ADDR	0x2b8a80
-#define TSTORM_WAITP_ADDR	0x1b8a80
-#define USTORM_WAITP_ADDR	0x338a80
-#define CSTORM_WAITP_ADDR	0x238a80
-#define TSTORM_CAM_MODE	0x1B1440
-
-#define MAX_TIMER_PENDING	200
-#define TIMER_SCAN_DONT_CARE	0xFF
-#define RI_E1				0x1
-#define RI_E1H				0x2
-#define RI_E2				0x4
-#define RI_E3				0x8
-#define RI_E3B0				0x10
-#define RI_ONLINE			0x100
-#define RI_OFFLINE			0x0
-#define RI_PATH0_DUMP			0x200
-#define RI_PATH1_DUMP			0x400
-
-#define RI_E1_ONLINE		(RI_E1 | RI_ONLINE)
-#define RI_E1H_ONLINE		(RI_E1H | RI_ONLINE)
-#define RI_E1E1H_ONLINE		(RI_E1 | RI_E1H | RI_ONLINE)
-#define RI_E2_ONLINE		(RI_E2 | RI_ONLINE)
-#define RI_E1E2_ONLINE		(RI_E1 | RI_E2 | RI_ONLINE)
-#define RI_E1HE2_ONLINE		(RI_E1H | RI_E2 | RI_ONLINE)
-#define RI_E1E1HE2_ONLINE	(RI_E1 | RI_E1H | RI_E2 | RI_ONLINE)
-#define RI_E3_ONLINE		(RI_E3 | RI_ONLINE)
-#define RI_E1E3_ONLINE		(RI_E1 | RI_E3 | RI_ONLINE)
-#define RI_E1HE3_ONLINE		(RI_E1H | RI_E3 | RI_ONLINE)
-#define RI_E1E1HE3_ONLINE	(RI_E1 | RI_E1H | RI_E3 | RI_ONLINE)
-#define RI_E2E3_ONLINE		(RI_E2 | RI_E3 | RI_ONLINE)
-#define RI_E1E2E3_ONLINE	(RI_E1 | RI_E2 | RI_E3 | RI_ONLINE)
-#define RI_E1HE2E3_ONLINE	(RI_E1H | RI_E2 | RI_E3 | RI_ONLINE)
-#define RI_E1E1HE2E3_ONLINE	(RI_E1 | RI_E1H | RI_E2 | RI_E3 | RI_ONLINE)
-#define RI_E3B0_ONLINE		(RI_E3B0 | RI_ONLINE)
-#define RI_E1E3B0_ONLINE	(RI_E1 | RI_E3B0 | RI_ONLINE)
-#define RI_E1HE3B0_ONLINE	(RI_E1H | RI_E3B0 | RI_ONLINE)
-#define RI_E1E1HE3B0_ONLINE	(RI_E1 | RI_E1H | RI_E3B0 | RI_ONLINE)
-#define RI_E2E3B0_ONLINE	(RI_E2 | RI_E3B0 | RI_ONLINE)
-#define RI_E1E2E3B0_ONLINE	(RI_E1 | RI_E2 | RI_E3B0 | RI_ONLINE)
-#define RI_E1HE2E3B0_ONLINE	(RI_E1H | RI_E2 | RI_E3B0 | RI_ONLINE)
-#define RI_E1E1HE2E3B0_ONLINE	(RI_E1 | RI_E1H | RI_E2 | RI_E3B0 | RI_ONLINE)
-#define RI_E3E3B0_ONLINE	(RI_E3 | RI_E3B0 | RI_ONLINE)
-#define RI_E1E3E3B0_ONLINE	(RI_E1 | RI_E3 | RI_E3B0 | RI_ONLINE)
-#define RI_E1HE3E3B0_ONLINE	(RI_E1H | RI_E3 | RI_E3B0 | RI_ONLINE)
-#define RI_E1E1HE3E3B0_ONLINE	(RI_E1 | RI_E1H | RI_E3 | RI_E3B0 | RI_ONLINE)
-#define RI_E2E3E3B0_ONLINE	(RI_E2 | RI_E3 | RI_E3B0 | RI_ONLINE)
-#define RI_E1E2E3E3B0_ONLINE	(RI_E1 | RI_E2 | RI_E3 | RI_E3B0 | RI_ONLINE)
-#define RI_E1HE2E3E3B0_ONLINE	(RI_E1H | RI_E2 | RI_E3 | RI_E3B0 | RI_ONLINE)
-#define RI_E1E1HE2E3E3B0_ONLINE	\
-	(RI_E1 | RI_E1H | RI_E2 | RI_E3 | RI_E3B0 | RI_ONLINE)
-#define RI_E1_OFFLINE		(RI_E1 | RI_OFFLINE)
-#define RI_E1H_OFFLINE		(RI_E1H | RI_OFFLINE)
-#define RI_E1E1H_OFFLINE	(RI_E1 | RI_E1H | RI_OFFLINE)
-#define RI_E2_OFFLINE		(RI_E2 | RI_OFFLINE)
-#define RI_E1E2_OFFLINE		(RI_E1 | RI_E2 | RI_OFFLINE)
-#define RI_E1HE2_OFFLINE	(RI_E1H | RI_E2 | RI_OFFLINE)
-#define RI_E1E1HE2_OFFLINE	(RI_E1 | RI_E1H | RI_E2 | RI_OFFLINE)
-#define RI_E3_OFFLINE		(RI_E3 | RI_OFFLINE)
-#define RI_E1E3_OFFLINE		(RI_E1 | RI_E3 | RI_OFFLINE)
-#define RI_E1HE3_OFFLINE	(RI_E1H | RI_E3 | RI_OFFLINE)
-#define RI_E1E1HE3_OFFLINE	(RI_E1 | RI_E1H | RI_E3 | RI_OFFLINE)
-#define RI_E2E3_OFFLINE		(RI_E2 | RI_E3 | RI_OFFLINE)
-#define RI_E1E2E3_OFFLINE	(RI_E1 | RI_E2 | RI_E3 | RI_OFFLINE)
-#define RI_E1HE2E3_OFFLINE	(RI_E1H | RI_E2 | RI_E3 | RI_OFFLINE)
-#define RI_E1E1HE2E3_OFFLINE	(RI_E1 | RI_E1H | RI_E2 | RI_E3 | RI_OFFLINE)
-#define RI_E3B0_OFFLINE		(RI_E3B0 | RI_OFFLINE)
-#define RI_E1E3B0_OFFLINE	(RI_E1 | RI_E3B0 | RI_OFFLINE)
-#define RI_E1HE3B0_OFFLINE	(RI_E1H | RI_E3B0 | RI_OFFLINE)
-#define RI_E1E1HE3B0_OFFLINE	(RI_E1 | RI_E1H | RI_E3B0 | RI_OFFLINE)
-#define RI_E2E3B0_OFFLINE	(RI_E2 | RI_E3B0 | RI_OFFLINE)
-#define RI_E1E2E3B0_OFFLINE	(RI_E1 | RI_E2 | RI_E3B0 | RI_OFFLINE)
-#define RI_E1HE2E3B0_OFFLINE	(RI_E1H | RI_E2 | RI_E3B0 | RI_OFFLINE)
-#define RI_E1E1HE2E3B0_OFFLINE	(RI_E1 | RI_E1H | RI_E2 | RI_E3B0 | RI_OFFLINE)
-#define RI_E3E3B0_OFFLINE	(RI_E3 | RI_E3B0 | RI_OFFLINE)
-#define RI_E1E3E3B0_OFFLINE	(RI_E1 | RI_E3 | RI_E3B0 | RI_OFFLINE)
-#define RI_E1HE3E3B0_OFFLINE	(RI_E1H | RI_E3 | RI_E3B0 | RI_OFFLINE)
-#define RI_E1E1HE3E3B0_OFFLINE	(RI_E1 | RI_E1H | RI_E3 | RI_E3B0 | RI_OFFLINE)
-#define RI_E2E3E3B0_OFFLINE	(RI_E2 | RI_E3 | RI_E3B0 | RI_OFFLINE)
-#define RI_E1E2E3E3B0_OFFLINE	(RI_E1 | RI_E2 | RI_E3 | RI_E3B0 | RI_OFFLINE)
-#define RI_E1HE2E3E3B0_OFFLINE	(RI_E1H | RI_E2 | RI_E3 | RI_E3B0 | RI_OFFLINE)
-#define RI_E1E1HE2E3E3B0_OFFLINE	\
-	(RI_E1 | RI_E1H | RI_E2 | RI_E3 | RI_E3B0 | RI_OFFLINE)
-#define RI_ALL_ONLINE		RI_E1E1HE2E3E3B0_ONLINE
-#define RI_ALL_OFFLINE		RI_E1E1HE2E3E3B0_OFFLINE
-
-#define DBG_DMP_TRACE_BUFFER_SIZE	0x800
-#define DBG_DMP_TRACE_BUFFER_OFFSET(shmem0_offset) \
-	((shmem0_offset) - DBG_DMP_TRACE_BUFFER_SIZE)
-
-struct dump_sign {
-	u32 time_stamp;
-	u32 diag_ver;
-	u32 grc_dump_ver;
-};
-
-struct dump_hdr {
-	u32  hdr_size;	/* in dwords, excluding this field */
-	struct dump_sign	dump_sign;
-	u32  xstorm_waitp;
-	u32  tstorm_waitp;
-	u32  ustorm_waitp;
-	u32  cstorm_waitp;
-	u16  info;
-	u8   idle_chk;
-	u8   reserved;
-};
-
-struct reg_addr {
-	u32 addr;
-	u32 size;
-	u16 info;
-};
-
-struct wreg_addr {
-	u32 addr;
-	u32 size;
-	u32 read_regs_count;
-	const u32 *read_regs;
-	u16 info;
-};
-
-static const struct reg_addr reg_addrs[] = {
-	{ 0x2000, 341, RI_ALL_ONLINE },
-	{ 0x2800, 103, RI_ALL_ONLINE },
-	{ 0x3000, 287, RI_ALL_ONLINE },
-	{ 0x3800, 331, RI_ALL_ONLINE },
-	{ 0x8800, 6, RI_ALL_ONLINE },
-	{ 0x8818, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x9000, 147, RI_E2E3E3B0_ONLINE },
-	{ 0x924c, 1, RI_E2_ONLINE },
-	{ 0x9250, 16, RI_E2E3E3B0_ONLINE },
-	{ 0x9400, 33, RI_E2E3E3B0_ONLINE },
-	{ 0x9484, 5, RI_E3E3B0_ONLINE },
-	{ 0xa000, 27, RI_ALL_ONLINE },
-	{ 0xa06c, 1, RI_E1E1H_ONLINE },
-	{ 0xa070, 71, RI_ALL_ONLINE },
-	{ 0xa18c, 4, RI_E1E1H_ONLINE },
-	{ 0xa19c, 62, RI_ALL_ONLINE },
-	{ 0xa294, 2, RI_E1E1H_ONLINE },
-	{ 0xa29c, 2, RI_ALL_ONLINE },
-	{ 0xa2a4, 2, RI_E1E1HE2_ONLINE },
-	{ 0xa2ac, 52, RI_ALL_ONLINE },
-	{ 0xa39c, 7, RI_E1HE2E3E3B0_ONLINE },
-	{ 0xa3b8, 2, RI_E3E3B0_ONLINE },
-	{ 0xa3c0, 3, RI_E1HE2E3E3B0_ONLINE },
-	{ 0xa3d0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0xa3d8, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0xa3e0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0xa3e8, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0xa3f0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0xa3f8, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0xa400, 40, RI_ALL_ONLINE },
-	{ 0xa4a0, 1, RI_E1E1HE2_ONLINE },
-	{ 0xa4a4, 2, RI_ALL_ONLINE },
-	{ 0xa4ac, 2, RI_E1E1H_ONLINE },
-	{ 0xa4b4, 1, RI_E1E1HE2_ONLINE },
-	{ 0xa4b8, 2, RI_E1E1H_ONLINE },
-	{ 0xa4c0, 3, RI_ALL_ONLINE },
-	{ 0xa4cc, 5, RI_E1E1H_ONLINE },
-	{ 0xa4e0, 3, RI_ALL_ONLINE },
-	{ 0xa4fc, 2, RI_ALL_ONLINE },
-	{ 0xa504, 1, RI_E1E1H_ONLINE },
-	{ 0xa508, 3, RI_ALL_ONLINE },
-	{ 0xa518, 1, RI_ALL_ONLINE },
-	{ 0xa520, 1, RI_ALL_ONLINE },
-	{ 0xa528, 1, RI_ALL_ONLINE },
-	{ 0xa530, 1, RI_ALL_ONLINE },
-	{ 0xa538, 1, RI_ALL_ONLINE },
-	{ 0xa540, 1, RI_ALL_ONLINE },
-	{ 0xa548, 1, RI_E1E1H_ONLINE },
-	{ 0xa550, 1, RI_E1E1H_ONLINE },
-	{ 0xa558, 1, RI_E1E1H_ONLINE },
-	{ 0xa560, 1, RI_E1E1H_ONLINE },
-	{ 0xa568, 1, RI_E1E1H_ONLINE },
-	{ 0xa570, 1, RI_ALL_ONLINE },
-	{ 0xa580, 1, RI_ALL_ONLINE },
-	{ 0xa590, 1, RI_ALL_ONLINE },
-	{ 0xa5a0, 1, RI_E1E1HE2_ONLINE },
-	{ 0xa5c0, 1, RI_ALL_ONLINE },
-	{ 0xa5e0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0xa5e8, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0xa5f0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0xa5f8, 1, RI_E1HE2_ONLINE },
-	{ 0xa5fc, 9, RI_E1HE2E3E3B0_ONLINE },
-	{ 0xa620, 6, RI_E2E3E3B0_ONLINE },
-	{ 0xa638, 20, RI_E2_ONLINE },
-	{ 0xa688, 42, RI_E2E3E3B0_ONLINE },
-	{ 0xa730, 1, RI_E2_ONLINE },
-	{ 0xa734, 2, RI_E2E3E3B0_ONLINE },
-	{ 0xa73c, 4, RI_E2_ONLINE },
-	{ 0xa74c, 5, RI_E2E3E3B0_ONLINE },
-	{ 0xa760, 5, RI_E2_ONLINE },
-	{ 0xa774, 7, RI_E2E3E3B0_ONLINE },
-	{ 0xa790, 15, RI_E2_ONLINE },
-	{ 0xa7cc, 4, RI_E2E3E3B0_ONLINE },
-	{ 0xa7e0, 6, RI_E3E3B0_ONLINE },
-	{ 0xa800, 18, RI_E2_ONLINE },
-	{ 0xa848, 33, RI_E2E3E3B0_ONLINE },
-	{ 0xa8cc, 2, RI_E3E3B0_ONLINE },
-	{ 0xa8d4, 4, RI_E2E3E3B0_ONLINE },
-	{ 0xa8e4, 1, RI_E3E3B0_ONLINE },
-	{ 0xa8e8, 1, RI_E2E3E3B0_ONLINE },
-	{ 0xa8f0, 1, RI_E2E3E3B0_ONLINE },
-	{ 0xa8f8, 30, RI_E3E3B0_ONLINE },
-	{ 0xa974, 73, RI_E3E3B0_ONLINE },
-	{ 0xac30, 1, RI_E3E3B0_ONLINE },
-	{ 0xac40, 1, RI_E3E3B0_ONLINE },
-	{ 0xac50, 1, RI_E3E3B0_ONLINE },
-	{ 0xac60, 1, RI_E3B0_ONLINE },
-	{ 0x10000, 9, RI_ALL_ONLINE },
-	{ 0x10024, 1, RI_E1E1HE2_ONLINE },
-	{ 0x10028, 5, RI_ALL_ONLINE },
-	{ 0x1003c, 6, RI_E1E1HE2_ONLINE },
-	{ 0x10054, 20, RI_ALL_ONLINE },
-	{ 0x100a4, 4, RI_E1E1HE2_ONLINE },
-	{ 0x100b4, 11, RI_ALL_ONLINE },
-	{ 0x100e0, 4, RI_E1E1HE2_ONLINE },
-	{ 0x100f0, 8, RI_ALL_ONLINE },
-	{ 0x10110, 6, RI_E1E1HE2_ONLINE },
-	{ 0x10128, 110, RI_ALL_ONLINE },
-	{ 0x102e0, 4, RI_E1E1HE2_ONLINE },
-	{ 0x102f0, 18, RI_ALL_ONLINE },
-	{ 0x10338, 20, RI_E1E1HE2_ONLINE },
-	{ 0x10388, 10, RI_ALL_ONLINE },
-	{ 0x10400, 6, RI_E1E1HE2_ONLINE },
-	{ 0x10418, 6, RI_ALL_ONLINE },
-	{ 0x10430, 10, RI_E1E1HE2_ONLINE },
-	{ 0x10458, 22, RI_ALL_ONLINE },
-	{ 0x104b0, 12, RI_E1E1HE2_ONLINE },
-	{ 0x104e0, 1, RI_ALL_ONLINE },
-	{ 0x104e8, 2, RI_ALL_ONLINE },
-	{ 0x104f4, 2, RI_ALL_ONLINE },
-	{ 0x10500, 146, RI_ALL_ONLINE },
-	{ 0x10750, 2, RI_E1E1HE2_ONLINE },
-	{ 0x10760, 2, RI_E1E1HE2_ONLINE },
-	{ 0x10770, 2, RI_E1E1HE2_ONLINE },
-	{ 0x10780, 2, RI_E1E1HE2_ONLINE },
-	{ 0x10790, 2, RI_ALL_ONLINE },
-	{ 0x107a0, 2, RI_E1E1HE2_ONLINE },
-	{ 0x107b0, 2, RI_E1E1HE2_ONLINE },
-	{ 0x107c0, 2, RI_E1E1HE2_ONLINE },
-	{ 0x107d0, 2, RI_E1E1HE2_ONLINE },
-	{ 0x107e0, 2, RI_ALL_ONLINE },
-	{ 0x10880, 2, RI_ALL_ONLINE },
-	{ 0x10900, 2, RI_ALL_ONLINE },
-	{ 0x16000, 1, RI_E1HE2_ONLINE },
-	{ 0x16004, 25, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x16070, 8, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x16090, 4, RI_E1HE2E3_ONLINE },
-	{ 0x160a0, 6, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x160c0, 7, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x160dc, 2, RI_E1HE2_ONLINE },
-	{ 0x160e4, 10, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1610c, 2, RI_E1HE2_ONLINE },
-	{ 0x16114, 6, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x16140, 48, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x16204, 5, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x18000, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x18008, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x18010, 35, RI_E2E3E3B0_ONLINE },
-	{ 0x180a4, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x180c0, 9, RI_E2E3E3B0_ONLINE },
-	{ 0x180e4, 1, RI_E2E3_ONLINE },
-	{ 0x180e8, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x180f0, 1, RI_E2E3_ONLINE },
-	{ 0x180f4, 79, RI_E2E3E3B0_ONLINE },
-	{ 0x18230, 1, RI_E2E3_ONLINE },
-	{ 0x18234, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x1823c, 1, RI_E2E3_ONLINE },
-	{ 0x18240, 13, RI_E2E3E3B0_ONLINE },
-	{ 0x18274, 1, RI_E2_ONLINE },
-	{ 0x18278, 81, RI_E2E3E3B0_ONLINE },
-	{ 0x18440, 63, RI_E2E3E3B0_ONLINE },
-	{ 0x18570, 42, RI_E3E3B0_ONLINE },
-	{ 0x18618, 25, RI_E3B0_ONLINE },
-	{ 0x18680, 44, RI_E3B0_ONLINE },
-	{ 0x18748, 12, RI_E3B0_ONLINE },
-	{ 0x18788, 1, RI_E3B0_ONLINE },
-	{ 0x1879c, 6, RI_E3B0_ONLINE },
-	{ 0x187c4, 51, RI_E3B0_ONLINE },
-	{ 0x18a00, 48, RI_E3B0_ONLINE },
-	{ 0x20000, 24, RI_ALL_ONLINE },
-	{ 0x20060, 8, RI_ALL_ONLINE },
-	{ 0x20080, 94, RI_ALL_ONLINE },
-	{ 0x201f8, 1, RI_E1E1H_ONLINE },
-	{ 0x201fc, 1, RI_ALL_ONLINE },
-	{ 0x20200, 1, RI_E1E1H_ONLINE },
-	{ 0x20204, 1, RI_ALL_ONLINE },
-	{ 0x20208, 1, RI_E1E1H_ONLINE },
-	{ 0x2020c, 39, RI_ALL_ONLINE },
-	{ 0x202c8, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x202d8, 4, RI_E2E3E3B0_ONLINE },
-	{ 0x202f0, 1, RI_E3B0_ONLINE },
-	{ 0x20400, 2, RI_ALL_ONLINE },
-	{ 0x2040c, 8, RI_ALL_ONLINE },
-	{ 0x2042c, 18, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x20480, 1, RI_ALL_ONLINE },
-	{ 0x20500, 1, RI_ALL_ONLINE },
-	{ 0x20600, 1, RI_ALL_ONLINE },
-	{ 0x28000, 1, RI_ALL_ONLINE },
-	{ 0x28004, 8191, RI_ALL_OFFLINE },
-	{ 0x30000, 1, RI_ALL_ONLINE },
-	{ 0x30004, 16383, RI_ALL_OFFLINE },
-	{ 0x40000, 98, RI_ALL_ONLINE },
-	{ 0x401a8, 8, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x401c8, 1, RI_E1H_ONLINE },
-	{ 0x401cc, 2, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x401d4, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x40200, 4, RI_ALL_ONLINE },
-	{ 0x40220, 6, RI_E2E3E3B0_ONLINE },
-	{ 0x40238, 8, RI_E2E3_ONLINE },
-	{ 0x40258, 4, RI_E2E3E3B0_ONLINE },
-	{ 0x40268, 2, RI_E3E3B0_ONLINE },
-	{ 0x40270, 17, RI_E3B0_ONLINE },
-	{ 0x40400, 43, RI_ALL_ONLINE },
-	{ 0x404cc, 3, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x404e0, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x40500, 2, RI_ALL_ONLINE },
-	{ 0x40510, 2, RI_ALL_ONLINE },
-	{ 0x40520, 2, RI_ALL_ONLINE },
-	{ 0x40530, 2, RI_ALL_ONLINE },
-	{ 0x40540, 2, RI_ALL_ONLINE },
-	{ 0x40550, 10, RI_E2E3E3B0_ONLINE },
-	{ 0x40610, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x42000, 164, RI_ALL_ONLINE },
-	{ 0x422c0, 4, RI_E2E3E3B0_ONLINE },
-	{ 0x422d4, 5, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x422e8, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x42400, 49, RI_ALL_ONLINE },
-	{ 0x424c8, 38, RI_ALL_ONLINE },
-	{ 0x42568, 2, RI_ALL_ONLINE },
-	{ 0x42640, 5, RI_E2E3E3B0_ONLINE },
-	{ 0x42800, 1, RI_ALL_ONLINE },
-	{ 0x50000, 1, RI_ALL_ONLINE },
-	{ 0x50004, 19, RI_ALL_ONLINE },
-	{ 0x50050, 8, RI_ALL_ONLINE },
-	{ 0x50070, 88, RI_ALL_ONLINE },
-	{ 0x501f0, 4, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x50200, 2, RI_ALL_ONLINE },
-	{ 0x5020c, 7, RI_ALL_ONLINE },
-	{ 0x50228, 6, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x50240, 1, RI_ALL_ONLINE },
-	{ 0x50280, 1, RI_ALL_ONLINE },
-	{ 0x50300, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x5030c, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x50318, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x5031c, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x50320, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x50330, 1, RI_E3B0_ONLINE },
-	{ 0x52000, 1, RI_ALL_ONLINE },
-	{ 0x54000, 1, RI_ALL_ONLINE },
-	{ 0x54004, 3327, RI_ALL_OFFLINE },
-	{ 0x58000, 1, RI_ALL_ONLINE },
-	{ 0x58004, 8191, RI_E1E1H_OFFLINE },
-	{ 0x60000, 26, RI_ALL_ONLINE },
-	{ 0x60068, 8, RI_E1E1H_ONLINE },
-	{ 0x60088, 12, RI_ALL_ONLINE },
-	{ 0x600b8, 9, RI_E1E1H_ONLINE },
-	{ 0x600dc, 1, RI_ALL_ONLINE },
-	{ 0x600e0, 5, RI_E1E1H_ONLINE },
-	{ 0x600f4, 1, RI_E1E1HE2_ONLINE },
-	{ 0x600f8, 1, RI_E1E1H_ONLINE },
-	{ 0x600fc, 8, RI_ALL_ONLINE },
-	{ 0x6013c, 24, RI_E1H_ONLINE },
-	{ 0x6019c, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x601ac, 18, RI_E2E3E3B0_ONLINE },
-	{ 0x60200, 1, RI_ALL_ONLINE },
-	{ 0x60204, 2, RI_ALL_OFFLINE },
-	{ 0x60210, 13, RI_E2E3E3B0_ONLINE },
-	{ 0x60244, 16, RI_E3B0_ONLINE },
-	{ 0x61000, 1, RI_ALL_ONLINE },
-	{ 0x61004, 511, RI_ALL_OFFLINE },
-	{ 0x61800, 512, RI_E3E3B0_OFFLINE },
-	{ 0x70000, 8, RI_ALL_ONLINE },
-	{ 0x70020, 8184, RI_ALL_OFFLINE },
-	{ 0x78000, 8192, RI_E3E3B0_OFFLINE },
-	{ 0x85000, 3, RI_ALL_ONLINE },
-	{ 0x8501c, 7, RI_ALL_ONLINE },
-	{ 0x85048, 1, RI_ALL_ONLINE },
-	{ 0x85200, 32, RI_ALL_ONLINE },
-	{ 0xb0000, 16384, RI_E1H_ONLINE },
-	{ 0xc1000, 7, RI_ALL_ONLINE },
-	{ 0xc103c, 2, RI_E2E3E3B0_ONLINE },
-	{ 0xc1800, 2, RI_ALL_ONLINE },
-	{ 0xc2000, 164, RI_ALL_ONLINE },
-	{ 0xc22c0, 5, RI_E2E3E3B0_ONLINE },
-	{ 0xc22d8, 4, RI_E2E3E3B0_ONLINE },
-	{ 0xc2400, 49, RI_ALL_ONLINE },
-	{ 0xc24c8, 38, RI_ALL_ONLINE },
-	{ 0xc2568, 2, RI_ALL_ONLINE },
-	{ 0xc2600, 1, RI_ALL_ONLINE },
-	{ 0xc4000, 165, RI_ALL_ONLINE },
-	{ 0xc42d8, 2, RI_E2E3E3B0_ONLINE },
-	{ 0xc42e0, 7, RI_E1HE2E3E3B0_ONLINE },
-	{ 0xc42fc, 1, RI_E2E3E3B0_ONLINE },
-	{ 0xc4400, 51, RI_ALL_ONLINE },
-	{ 0xc44d0, 38, RI_ALL_ONLINE },
-	{ 0xc4570, 2, RI_ALL_ONLINE },
-	{ 0xc4578, 5, RI_E2E3E3B0_ONLINE },
-	{ 0xc4600, 1, RI_ALL_ONLINE },
-	{ 0xd0000, 19, RI_ALL_ONLINE },
-	{ 0xd004c, 8, RI_ALL_ONLINE },
-	{ 0xd006c, 91, RI_ALL_ONLINE },
-	{ 0xd01fc, 1, RI_E2E3E3B0_ONLINE },
-	{ 0xd0200, 2, RI_ALL_ONLINE },
-	{ 0xd020c, 7, RI_ALL_ONLINE },
-	{ 0xd0228, 18, RI_E1HE2E3E3B0_ONLINE },
-	{ 0xd0280, 1, RI_ALL_ONLINE },
-	{ 0xd0300, 1, RI_ALL_ONLINE },
-	{ 0xd0400, 1, RI_ALL_ONLINE },
-	{ 0xd0818, 1, RI_E3B0_ONLINE },
-	{ 0xd4000, 1, RI_ALL_ONLINE },
-	{ 0xd4004, 2559, RI_ALL_OFFLINE },
-	{ 0xd8000, 1, RI_ALL_ONLINE },
-	{ 0xd8004, 8191, RI_ALL_OFFLINE },
-	{ 0xe0000, 21, RI_ALL_ONLINE },
-	{ 0xe0054, 8, RI_ALL_ONLINE },
-	{ 0xe0074, 49, RI_ALL_ONLINE },
-	{ 0xe0138, 1, RI_E1E1H_ONLINE },
-	{ 0xe013c, 35, RI_ALL_ONLINE },
-	{ 0xe01f4, 1, RI_E2_ONLINE },
-	{ 0xe01f8, 1, RI_E2E3E3B0_ONLINE },
-	{ 0xe0200, 2, RI_ALL_ONLINE },
-	{ 0xe020c, 8, RI_ALL_ONLINE },
-	{ 0xe022c, 18, RI_E1HE2E3E3B0_ONLINE },
-	{ 0xe0280, 1, RI_ALL_ONLINE },
-	{ 0xe0300, 1, RI_ALL_ONLINE },
-	{ 0xe0400, 1, RI_E3B0_ONLINE },
-	{ 0xe1000, 1, RI_ALL_ONLINE },
-	{ 0xe2000, 1, RI_ALL_ONLINE },
-	{ 0xe2004, 2047, RI_ALL_OFFLINE },
-	{ 0xf0000, 1, RI_ALL_ONLINE },
-	{ 0xf0004, 16383, RI_ALL_OFFLINE },
-	{ 0x101000, 12, RI_ALL_ONLINE },
-	{ 0x101050, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x101054, 3, RI_E2E3E3B0_ONLINE },
-	{ 0x101100, 1, RI_ALL_ONLINE },
-	{ 0x101800, 8, RI_ALL_ONLINE },
-	{ 0x102000, 18, RI_ALL_ONLINE },
-	{ 0x102068, 6, RI_E2E3E3B0_ONLINE },
-	{ 0x102080, 17, RI_ALL_ONLINE },
-	{ 0x1020c8, 8, RI_E1H_ONLINE },
-	{ 0x1020e8, 9, RI_E2E3E3B0_ONLINE },
-	{ 0x102400, 1, RI_ALL_ONLINE },
-	{ 0x103000, 26, RI_ALL_ONLINE },
-	{ 0x103098, 5, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1030ac, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x1030b4, 1, RI_E2_ONLINE },
-	{ 0x1030b8, 7, RI_E2E3E3B0_ONLINE },
-	{ 0x1030d8, 8, RI_E2E3E3B0_ONLINE },
-	{ 0x103400, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x103404, 135, RI_E2E3E3B0_OFFLINE },
-	{ 0x103800, 8, RI_ALL_ONLINE },
-	{ 0x104000, 63, RI_ALL_ONLINE },
-	{ 0x10411c, 16, RI_E2E3E3B0_ONLINE },
-	{ 0x104200, 17, RI_ALL_ONLINE },
-	{ 0x104400, 64, RI_ALL_ONLINE },
-	{ 0x104500, 192, RI_ALL_OFFLINE },
-	{ 0x104800, 64, RI_ALL_ONLINE },
-	{ 0x104900, 192, RI_ALL_OFFLINE },
-	{ 0x105000, 256, RI_ALL_ONLINE },
-	{ 0x105400, 768, RI_ALL_OFFLINE },
-	{ 0x107000, 7, RI_E2E3E3B0_ONLINE },
-	{ 0x10701c, 1, RI_E3E3B0_ONLINE },
-	{ 0x108000, 33, RI_E1E1H_ONLINE },
-	{ 0x1080ac, 5, RI_E1H_ONLINE },
-	{ 0x108100, 5, RI_E1E1H_ONLINE },
-	{ 0x108120, 5, RI_E1E1H_ONLINE },
-	{ 0x108200, 74, RI_E1E1H_ONLINE },
-	{ 0x108400, 74, RI_E1E1H_ONLINE },
-	{ 0x108800, 152, RI_E1E1H_ONLINE },
-	{ 0x110000, 111, RI_E2E3E3B0_ONLINE },
-	{ 0x1101dc, 1, RI_E3E3B0_ONLINE },
-	{ 0x110200, 4, RI_E2E3E3B0_ONLINE },
-	{ 0x120000, 2, RI_ALL_ONLINE },
-	{ 0x120008, 4, RI_ALL_ONLINE },
-	{ 0x120018, 3, RI_ALL_ONLINE },
-	{ 0x120024, 4, RI_ALL_ONLINE },
-	{ 0x120034, 3, RI_ALL_ONLINE },
-	{ 0x120040, 4, RI_ALL_ONLINE },
-	{ 0x120050, 3, RI_ALL_ONLINE },
-	{ 0x12005c, 4, RI_ALL_ONLINE },
-	{ 0x12006c, 3, RI_ALL_ONLINE },
-	{ 0x120078, 4, RI_ALL_ONLINE },
-	{ 0x120088, 3, RI_ALL_ONLINE },
-	{ 0x120094, 4, RI_ALL_ONLINE },
-	{ 0x1200a4, 3, RI_ALL_ONLINE },
-	{ 0x1200b0, 4, RI_ALL_ONLINE },
-	{ 0x1200c0, 3, RI_ALL_ONLINE },
-	{ 0x1200cc, 4, RI_ALL_ONLINE },
-	{ 0x1200dc, 3, RI_ALL_ONLINE },
-	{ 0x1200e8, 4, RI_ALL_ONLINE },
-	{ 0x1200f8, 3, RI_ALL_ONLINE },
-	{ 0x120104, 4, RI_ALL_ONLINE },
-	{ 0x120114, 1, RI_ALL_ONLINE },
-	{ 0x120118, 22, RI_ALL_ONLINE },
-	{ 0x120170, 2, RI_E1E1H_ONLINE },
-	{ 0x120178, 243, RI_ALL_ONLINE },
-	{ 0x120544, 4, RI_E1E1H_ONLINE },
-	{ 0x120554, 6, RI_ALL_ONLINE },
-	{ 0x12059c, 6, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1205b4, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1205b8, 15, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1205f4, 1, RI_E1HE2_ONLINE },
-	{ 0x1205f8, 4, RI_E2E3E3B0_ONLINE },
-	{ 0x120618, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x12061c, 20, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x12066c, 11, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x120698, 3, RI_E2E3E3B0_ONLINE },
-	{ 0x1206a4, 1, RI_E2_ONLINE },
-	{ 0x1206a8, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x1206b0, 75, RI_E2E3E3B0_ONLINE },
-	{ 0x1207dc, 1, RI_E2_ONLINE },
-	{ 0x1207fc, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x12080c, 65, RI_ALL_ONLINE },
-	{ 0x120910, 7, RI_E2E3E3B0_ONLINE },
-	{ 0x120930, 9, RI_E2E3E3B0_ONLINE },
-	{ 0x12095c, 37, RI_E3E3B0_ONLINE },
-	{ 0x120a00, 2, RI_E1E1HE2_ONLINE },
-	{ 0x120b00, 1, RI_E3E3B0_ONLINE },
-	{ 0x122000, 2, RI_ALL_ONLINE },
-	{ 0x122008, 2046, RI_E1_OFFLINE },
-	{ 0x128000, 2, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x128008, 6142, RI_E1HE2E3E3B0_OFFLINE },
-	{ 0x130000, 35, RI_E2E3E3B0_ONLINE },
-	{ 0x130100, 29, RI_E2E3E3B0_ONLINE },
-	{ 0x130180, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x130200, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x130280, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x130300, 5, RI_E2E3E3B0_ONLINE },
-	{ 0x130380, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x130400, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x130480, 5, RI_E2E3E3B0_ONLINE },
-	{ 0x130800, 72, RI_E2E3E3B0_ONLINE },
-	{ 0x131000, 136, RI_E2E3E3B0_ONLINE },
-	{ 0x132000, 148, RI_E2E3E3B0_ONLINE },
-	{ 0x134000, 544, RI_E2E3E3B0_ONLINE },
-	{ 0x140000, 1, RI_ALL_ONLINE },
-	{ 0x140004, 9, RI_E1E1HE2E3_ONLINE },
-	{ 0x140028, 8, RI_ALL_ONLINE },
-	{ 0x140048, 10, RI_E1E1HE2E3_ONLINE },
-	{ 0x140070, 1, RI_ALL_ONLINE },
-	{ 0x140074, 10, RI_E1E1HE2E3_ONLINE },
-	{ 0x14009c, 1, RI_ALL_ONLINE },
-	{ 0x1400a0, 5, RI_E1E1HE2E3_ONLINE },
-	{ 0x1400b4, 7, RI_ALL_ONLINE },
-	{ 0x1400d0, 10, RI_E1E1HE2E3_ONLINE },
-	{ 0x1400f8, 2, RI_ALL_ONLINE },
-	{ 0x140100, 5, RI_E1E1H_ONLINE },
-	{ 0x140114, 5, RI_E1E1HE2E3_ONLINE },
-	{ 0x140128, 7, RI_ALL_ONLINE },
-	{ 0x140144, 9, RI_E1E1HE2E3_ONLINE },
-	{ 0x140168, 8, RI_ALL_ONLINE },
-	{ 0x140188, 3, RI_E1E1HE2E3_ONLINE },
-	{ 0x140194, 13, RI_ALL_ONLINE },
-	{ 0x140200, 6, RI_E1E1HE2E3_ONLINE },
-	{ 0x140220, 4, RI_E2E3_ONLINE },
-	{ 0x140240, 4, RI_E2E3_ONLINE },
-	{ 0x140260, 4, RI_E2E3_ONLINE },
-	{ 0x140280, 4, RI_E2E3_ONLINE },
-	{ 0x1402a0, 4, RI_E2E3_ONLINE },
-	{ 0x1402c0, 4, RI_E2E3_ONLINE },
-	{ 0x1402e0, 2, RI_E2E3_ONLINE },
-	{ 0x1402e8, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x1402f0, 9, RI_E2E3_ONLINE },
-	{ 0x140314, 44, RI_E3B0_ONLINE },
-	{ 0x1403d0, 70, RI_E3B0_ONLINE },
-	{ 0x144000, 4, RI_E1E1H_ONLINE },
-	{ 0x148000, 4, RI_E1E1H_ONLINE },
-	{ 0x14c000, 4, RI_E1E1H_ONLINE },
-	{ 0x150000, 4, RI_E1E1H_ONLINE },
-	{ 0x154000, 4, RI_E1E1H_ONLINE },
-	{ 0x158000, 4, RI_E1E1H_ONLINE },
-	{ 0x15c000, 2, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x15c008, 5, RI_E1H_ONLINE },
-	{ 0x15c020, 8, RI_E2E3E3B0_ONLINE },
-	{ 0x15c040, 1, RI_E2E3_ONLINE },
-	{ 0x15c044, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x15c04c, 8, RI_E2E3_ONLINE },
-	{ 0x15c06c, 8, RI_E2E3E3B0_ONLINE },
-	{ 0x15c090, 13, RI_E2E3E3B0_ONLINE },
-	{ 0x15c0c8, 24, RI_E2E3E3B0_ONLINE },
-	{ 0x15c128, 2, RI_E2E3_ONLINE },
-	{ 0x15c130, 8, RI_E2E3E3B0_ONLINE },
-	{ 0x15c150, 2, RI_E3E3B0_ONLINE },
-	{ 0x15c158, 2, RI_E3_ONLINE },
-	{ 0x15c160, 149, RI_E3B0_ONLINE },
-	{ 0x161000, 7, RI_ALL_ONLINE },
-	{ 0x16103c, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x161800, 2, RI_ALL_ONLINE },
-	{ 0x162000, 54, RI_E3E3B0_ONLINE },
-	{ 0x162200, 60, RI_E3E3B0_ONLINE },
-	{ 0x162400, 54, RI_E3E3B0_ONLINE },
-	{ 0x162600, 60, RI_E3E3B0_ONLINE },
-	{ 0x162800, 54, RI_E3E3B0_ONLINE },
-	{ 0x162a00, 60, RI_E3E3B0_ONLINE },
-	{ 0x162c00, 54, RI_E3E3B0_ONLINE },
-	{ 0x162e00, 60, RI_E3E3B0_ONLINE },
-	{ 0x164000, 60, RI_ALL_ONLINE },
-	{ 0x164110, 2, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x164118, 15, RI_E2E3E3B0_ONLINE },
-	{ 0x164200, 1, RI_ALL_ONLINE },
-	{ 0x164208, 1, RI_ALL_ONLINE },
-	{ 0x164210, 1, RI_ALL_ONLINE },
-	{ 0x164218, 1, RI_ALL_ONLINE },
-	{ 0x164220, 1, RI_ALL_ONLINE },
-	{ 0x164228, 1, RI_ALL_ONLINE },
-	{ 0x164230, 1, RI_ALL_ONLINE },
-	{ 0x164238, 1, RI_ALL_ONLINE },
-	{ 0x164240, 1, RI_ALL_ONLINE },
-	{ 0x164248, 1, RI_ALL_ONLINE },
-	{ 0x164250, 1, RI_ALL_ONLINE },
-	{ 0x164258, 1, RI_ALL_ONLINE },
-	{ 0x164260, 1, RI_ALL_ONLINE },
-	{ 0x164270, 2, RI_ALL_ONLINE },
-	{ 0x164280, 2, RI_ALL_ONLINE },
-	{ 0x164800, 2, RI_ALL_ONLINE },
-	{ 0x165000, 2, RI_ALL_ONLINE },
-	{ 0x166000, 164, RI_ALL_ONLINE },
-	{ 0x1662cc, 7, RI_E2E3E3B0_ONLINE },
-	{ 0x166400, 49, RI_ALL_ONLINE },
-	{ 0x1664c8, 38, RI_ALL_ONLINE },
-	{ 0x166568, 2, RI_ALL_ONLINE },
-	{ 0x166570, 5, RI_E2E3E3B0_ONLINE },
-	{ 0x166800, 1, RI_ALL_ONLINE },
-	{ 0x168000, 137, RI_ALL_ONLINE },
-	{ 0x168224, 2, RI_E1E1H_ONLINE },
-	{ 0x16822c, 29, RI_ALL_ONLINE },
-	{ 0x1682a0, 12, RI_E1E1H_ONLINE },
-	{ 0x1682d0, 12, RI_ALL_ONLINE },
-	{ 0x168300, 2, RI_E1E1H_ONLINE },
-	{ 0x168308, 68, RI_ALL_ONLINE },
-	{ 0x168418, 2, RI_E1E1H_ONLINE },
-	{ 0x168420, 6, RI_ALL_ONLINE },
-	{ 0x168800, 19, RI_ALL_ONLINE },
-	{ 0x168900, 1, RI_ALL_ONLINE },
-	{ 0x168a00, 128, RI_ALL_ONLINE },
-	{ 0x16a000, 1, RI_ALL_ONLINE },
-	{ 0x16a004, 1535, RI_ALL_OFFLINE },
-	{ 0x16c000, 1, RI_ALL_ONLINE },
-	{ 0x16c004, 1535, RI_ALL_OFFLINE },
-	{ 0x16e000, 16, RI_E1H_ONLINE },
-	{ 0x16e040, 8, RI_E2E3E3B0_ONLINE },
-	{ 0x16e100, 1, RI_E1H_ONLINE },
-	{ 0x16e200, 2, RI_E1H_ONLINE },
-	{ 0x16e400, 161, RI_E1H_ONLINE },
-	{ 0x16e684, 2, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x16e68c, 12, RI_E1H_ONLINE },
-	{ 0x16e6bc, 4, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x16e6cc, 4, RI_E1H_ONLINE },
-	{ 0x16e6e0, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x16e6e8, 5, RI_E2E3_ONLINE },
-	{ 0x16e6fc, 5, RI_E2E3E3B0_ONLINE },
-	{ 0x16e768, 17, RI_E2E3E3B0_ONLINE },
-	{ 0x16e7ac, 12, RI_E3B0_ONLINE },
-	{ 0x170000, 24, RI_ALL_ONLINE },
-	{ 0x170060, 4, RI_E1E1H_ONLINE },
-	{ 0x170070, 65, RI_ALL_ONLINE },
-	{ 0x170194, 11, RI_E2E3E3B0_ONLINE },
-	{ 0x1701c4, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x1701cc, 7, RI_E2E3E3B0_ONLINE },
-	{ 0x1701e8, 1, RI_E3E3B0_ONLINE },
-	{ 0x1701ec, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x1701f4, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x170200, 4, RI_ALL_ONLINE },
-	{ 0x170214, 1, RI_ALL_ONLINE },
-	{ 0x170218, 77, RI_E2E3E3B0_ONLINE },
-	{ 0x170400, 64, RI_E2E3E3B0_ONLINE },
-	{ 0x178000, 1, RI_ALL_ONLINE },
-	{ 0x180000, 61, RI_ALL_ONLINE },
-	{ 0x18013c, 2, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x180200, 58, RI_ALL_ONLINE },
-	{ 0x180340, 4, RI_ALL_ONLINE },
-	{ 0x180380, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x180388, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x180390, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x180398, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x1803a0, 5, RI_E2E3E3B0_ONLINE },
-	{ 0x1803b4, 2, RI_E3E3B0_ONLINE },
-	{ 0x180400, 1, RI_ALL_ONLINE },
-	{ 0x180404, 255, RI_E1E1H_OFFLINE },
-	{ 0x181000, 4, RI_ALL_ONLINE },
-	{ 0x181010, 1020, RI_ALL_OFFLINE },
-	{ 0x182000, 4, RI_E3E3B0_ONLINE },
-	{ 0x1a0000, 1, RI_ALL_ONLINE },
-	{ 0x1a0004, 5631, RI_ALL_OFFLINE },
-	{ 0x1a5800, 2560, RI_E1HE2E3E3B0_OFFLINE },
-	{ 0x1a8000, 1, RI_ALL_ONLINE },
-	{ 0x1a8004, 8191, RI_E1HE2E3E3B0_OFFLINE },
-	{ 0x1b0000, 1, RI_ALL_ONLINE },
-	{ 0x1b0004, 15, RI_E1H_OFFLINE },
-	{ 0x1b0040, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1b0044, 239, RI_E1H_OFFLINE },
-	{ 0x1b0400, 1, RI_ALL_ONLINE },
-	{ 0x1b0404, 255, RI_E1H_OFFLINE },
-	{ 0x1b0800, 1, RI_ALL_ONLINE },
-	{ 0x1b0840, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1b0c00, 1, RI_ALL_ONLINE },
-	{ 0x1b1000, 1, RI_ALL_ONLINE },
-	{ 0x1b1040, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1b1400, 1, RI_ALL_ONLINE },
-	{ 0x1b1440, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1b1480, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1b14c0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1b1800, 128, RI_ALL_OFFLINE },
-	{ 0x1b1c00, 128, RI_ALL_OFFLINE },
-	{ 0x1b2000, 1, RI_ALL_ONLINE },
-	{ 0x1b2400, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1b2404, 5631, RI_E2E3E3B0_OFFLINE },
-	{ 0x1b8000, 1, RI_ALL_ONLINE },
-	{ 0x1b8040, 1, RI_ALL_ONLINE },
-	{ 0x1b8080, 1, RI_ALL_ONLINE },
-	{ 0x1b80c0, 1, RI_ALL_ONLINE },
-	{ 0x1b8100, 1, RI_ALL_ONLINE },
-	{ 0x1b8140, 1, RI_ALL_ONLINE },
-	{ 0x1b8180, 1, RI_ALL_ONLINE },
-	{ 0x1b81c0, 1, RI_ALL_ONLINE },
-	{ 0x1b8200, 1, RI_ALL_ONLINE },
-	{ 0x1b8240, 1, RI_ALL_ONLINE },
-	{ 0x1b8280, 1, RI_ALL_ONLINE },
-	{ 0x1b82c0, 1, RI_ALL_ONLINE },
-	{ 0x1b8300, 1, RI_ALL_ONLINE },
-	{ 0x1b8340, 1, RI_ALL_ONLINE },
-	{ 0x1b8380, 1, RI_ALL_ONLINE },
-	{ 0x1b83c0, 1, RI_ALL_ONLINE },
-	{ 0x1b8400, 1, RI_ALL_ONLINE },
-	{ 0x1b8440, 1, RI_ALL_ONLINE },
-	{ 0x1b8480, 1, RI_ALL_ONLINE },
-	{ 0x1b84c0, 1, RI_ALL_ONLINE },
-	{ 0x1b8500, 1, RI_ALL_ONLINE },
-	{ 0x1b8540, 1, RI_ALL_ONLINE },
-	{ 0x1b8580, 1, RI_ALL_ONLINE },
-	{ 0x1b85c0, 19, RI_E2E3E3B0_ONLINE },
-	{ 0x1b8800, 1, RI_ALL_ONLINE },
-	{ 0x1b8840, 1, RI_ALL_ONLINE },
-	{ 0x1b8880, 1, RI_ALL_ONLINE },
-	{ 0x1b88c0, 1, RI_ALL_ONLINE },
-	{ 0x1b8900, 1, RI_ALL_ONLINE },
-	{ 0x1b8940, 1, RI_ALL_ONLINE },
-	{ 0x1b8980, 1, RI_ALL_ONLINE },
-	{ 0x1b89c0, 1, RI_ALL_ONLINE },
-	{ 0x1b8a00, 1, RI_ALL_ONLINE },
-	{ 0x1b8a40, 1, RI_ALL_ONLINE },
-	{ 0x1b8a80, 1, RI_ALL_ONLINE },
-	{ 0x1b8ac0, 1, RI_ALL_ONLINE },
-	{ 0x1b8b00, 1, RI_ALL_ONLINE },
-	{ 0x1b8b40, 1, RI_ALL_ONLINE },
-	{ 0x1b8b80, 1, RI_ALL_ONLINE },
-	{ 0x1b8bc0, 1, RI_ALL_ONLINE },
-	{ 0x1b8c00, 1, RI_ALL_ONLINE },
-	{ 0x1b8c40, 1, RI_ALL_ONLINE },
-	{ 0x1b8c80, 1, RI_ALL_ONLINE },
-	{ 0x1b8cc0, 1, RI_ALL_ONLINE },
-	{ 0x1b8cc4, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x1b8d00, 1, RI_ALL_ONLINE },
-	{ 0x1b8d40, 1, RI_ALL_ONLINE },
-	{ 0x1b8d80, 1, RI_ALL_ONLINE },
-	{ 0x1b8dc0, 1, RI_ALL_ONLINE },
-	{ 0x1b8e00, 1, RI_ALL_ONLINE },
-	{ 0x1b8e40, 1, RI_ALL_ONLINE },
-	{ 0x1b8e80, 1, RI_ALL_ONLINE },
-	{ 0x1b8e84, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x1b8ec0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1b8f00, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1b8f40, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1b8f80, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1b8fc0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x1b8fc4, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x1b8fd0, 6, RI_E2E3E3B0_ONLINE },
-	{ 0x1b8fe8, 2, RI_E3E3B0_ONLINE },
-	{ 0x1b9000, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x1b9040, 3, RI_E2E3E3B0_ONLINE },
-	{ 0x1b905c, 1, RI_E3E3B0_ONLINE },
-	{ 0x1b9064, 1, RI_E3B0_ONLINE },
-	{ 0x1b9080, 10, RI_E3B0_ONLINE },
-	{ 0x1b9400, 14, RI_E2E3E3B0_ONLINE },
-	{ 0x1b943c, 19, RI_E2E3E3B0_ONLINE },
-	{ 0x1b9490, 10, RI_E2E3E3B0_ONLINE },
-	{ 0x1c0000, 2, RI_ALL_ONLINE },
-	{ 0x200000, 65, RI_ALL_ONLINE },
-	{ 0x20014c, 2, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x200200, 58, RI_ALL_ONLINE },
-	{ 0x200340, 4, RI_ALL_ONLINE },
-	{ 0x200380, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x200388, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x200390, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x200398, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x2003a0, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x2003a8, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x200400, 1, RI_ALL_ONLINE },
-	{ 0x200404, 255, RI_E1E1H_OFFLINE },
-	{ 0x202000, 4, RI_ALL_ONLINE },
-	{ 0x202010, 2044, RI_ALL_OFFLINE },
-	{ 0x204000, 4, RI_E3E3B0_ONLINE },
-	{ 0x220000, 1, RI_ALL_ONLINE },
-	{ 0x220004, 5631, RI_ALL_OFFLINE },
-	{ 0x225800, 2560, RI_E1HE2E3E3B0_OFFLINE },
-	{ 0x228000, 1, RI_ALL_ONLINE },
-	{ 0x228004, 8191, RI_E1HE2E3E3B0_OFFLINE },
-	{ 0x230000, 1, RI_ALL_ONLINE },
-	{ 0x230004, 15, RI_E1H_OFFLINE },
-	{ 0x230040, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x230044, 239, RI_E1H_OFFLINE },
-	{ 0x230400, 1, RI_ALL_ONLINE },
-	{ 0x230404, 255, RI_E1H_OFFLINE },
-	{ 0x230800, 1, RI_ALL_ONLINE },
-	{ 0x230840, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x230c00, 1, RI_ALL_ONLINE },
-	{ 0x231000, 1, RI_ALL_ONLINE },
-	{ 0x231040, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x231400, 1, RI_ALL_ONLINE },
-	{ 0x231440, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x231480, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x2314c0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x231800, 128, RI_ALL_OFFLINE },
-	{ 0x231c00, 128, RI_ALL_OFFLINE },
-	{ 0x232000, 1, RI_ALL_ONLINE },
-	{ 0x232400, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x232404, 5631, RI_E2E3E3B0_OFFLINE },
-	{ 0x238000, 1, RI_ALL_ONLINE },
-	{ 0x238040, 1, RI_ALL_ONLINE },
-	{ 0x238080, 1, RI_ALL_ONLINE },
-	{ 0x2380c0, 1, RI_ALL_ONLINE },
-	{ 0x238100, 1, RI_ALL_ONLINE },
-	{ 0x238140, 1, RI_ALL_ONLINE },
-	{ 0x238180, 1, RI_ALL_ONLINE },
-	{ 0x2381c0, 1, RI_ALL_ONLINE },
-	{ 0x238200, 1, RI_ALL_ONLINE },
-	{ 0x238240, 1, RI_ALL_ONLINE },
-	{ 0x238280, 1, RI_ALL_ONLINE },
-	{ 0x2382c0, 1, RI_ALL_ONLINE },
-	{ 0x238300, 1, RI_ALL_ONLINE },
-	{ 0x238340, 1, RI_ALL_ONLINE },
-	{ 0x238380, 1, RI_ALL_ONLINE },
-	{ 0x2383c0, 1, RI_ALL_ONLINE },
-	{ 0x238400, 1, RI_ALL_ONLINE },
-	{ 0x238440, 1, RI_ALL_ONLINE },
-	{ 0x238480, 1, RI_ALL_ONLINE },
-	{ 0x2384c0, 1, RI_ALL_ONLINE },
-	{ 0x238500, 1, RI_ALL_ONLINE },
-	{ 0x238540, 1, RI_ALL_ONLINE },
-	{ 0x238580, 1, RI_ALL_ONLINE },
-	{ 0x2385c0, 19, RI_E2E3E3B0_ONLINE },
-	{ 0x238800, 1, RI_ALL_ONLINE },
-	{ 0x238840, 1, RI_ALL_ONLINE },
-	{ 0x238880, 1, RI_ALL_ONLINE },
-	{ 0x2388c0, 1, RI_ALL_ONLINE },
-	{ 0x238900, 1, RI_ALL_ONLINE },
-	{ 0x238940, 1, RI_ALL_ONLINE },
-	{ 0x238980, 1, RI_ALL_ONLINE },
-	{ 0x2389c0, 1, RI_ALL_ONLINE },
-	{ 0x238a00, 1, RI_ALL_ONLINE },
-	{ 0x238a40, 1, RI_ALL_ONLINE },
-	{ 0x238a80, 1, RI_ALL_ONLINE },
-	{ 0x238ac0, 1, RI_ALL_ONLINE },
-	{ 0x238b00, 1, RI_ALL_ONLINE },
-	{ 0x238b40, 1, RI_ALL_ONLINE },
-	{ 0x238b80, 1, RI_ALL_ONLINE },
-	{ 0x238bc0, 1, RI_ALL_ONLINE },
-	{ 0x238c00, 1, RI_ALL_ONLINE },
-	{ 0x238c40, 1, RI_ALL_ONLINE },
-	{ 0x238c80, 1, RI_ALL_ONLINE },
-	{ 0x238cc0, 1, RI_ALL_ONLINE },
-	{ 0x238cc4, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x238d00, 1, RI_ALL_ONLINE },
-	{ 0x238d40, 1, RI_ALL_ONLINE },
-	{ 0x238d80, 1, RI_ALL_ONLINE },
-	{ 0x238dc0, 1, RI_ALL_ONLINE },
-	{ 0x238e00, 1, RI_ALL_ONLINE },
-	{ 0x238e40, 1, RI_ALL_ONLINE },
-	{ 0x238e80, 1, RI_ALL_ONLINE },
-	{ 0x238e84, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x238ec0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x238f00, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x238f40, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x238f80, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x238fc0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x238fc4, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x238fd0, 6, RI_E2E3E3B0_ONLINE },
-	{ 0x238fe8, 2, RI_E3E3B0_ONLINE },
-	{ 0x239000, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x239040, 3, RI_E2E3E3B0_ONLINE },
-	{ 0x23905c, 1, RI_E3E3B0_ONLINE },
-	{ 0x239064, 1, RI_E3B0_ONLINE },
-	{ 0x239080, 10, RI_E3B0_ONLINE },
-	{ 0x240000, 2, RI_ALL_ONLINE },
-	{ 0x280000, 65, RI_ALL_ONLINE },
-	{ 0x28014c, 2, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x280200, 58, RI_ALL_ONLINE },
-	{ 0x280340, 4, RI_ALL_ONLINE },
-	{ 0x280380, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x280388, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x280390, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x280398, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x2803a0, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x2803a8, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x280400, 1, RI_ALL_ONLINE },
-	{ 0x280404, 255, RI_E1E1H_OFFLINE },
-	{ 0x282000, 4, RI_ALL_ONLINE },
-	{ 0x282010, 2044, RI_ALL_OFFLINE },
-	{ 0x284000, 4, RI_E3E3B0_ONLINE },
-	{ 0x2a0000, 1, RI_ALL_ONLINE },
-	{ 0x2a0004, 5631, RI_ALL_OFFLINE },
-	{ 0x2a5800, 2560, RI_E1HE2E3E3B0_OFFLINE },
-	{ 0x2a8000, 1, RI_ALL_ONLINE },
-	{ 0x2a8004, 8191, RI_E1HE2E3E3B0_OFFLINE },
-	{ 0x2b0000, 1, RI_ALL_ONLINE },
-	{ 0x2b0004, 15, RI_E1H_OFFLINE },
-	{ 0x2b0040, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x2b0044, 239, RI_E1H_OFFLINE },
-	{ 0x2b0400, 1, RI_ALL_ONLINE },
-	{ 0x2b0404, 255, RI_E1H_OFFLINE },
-	{ 0x2b0800, 1, RI_ALL_ONLINE },
-	{ 0x2b0840, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x2b0c00, 1, RI_ALL_ONLINE },
-	{ 0x2b1000, 1, RI_ALL_ONLINE },
-	{ 0x2b1040, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x2b1400, 1, RI_ALL_ONLINE },
-	{ 0x2b1440, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x2b1480, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x2b14c0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x2b1800, 128, RI_ALL_OFFLINE },
-	{ 0x2b1c00, 128, RI_ALL_OFFLINE },
-	{ 0x2b2000, 1, RI_ALL_ONLINE },
-	{ 0x2b2400, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x2b2404, 5631, RI_E2E3E3B0_OFFLINE },
-	{ 0x2b8000, 1, RI_ALL_ONLINE },
-	{ 0x2b8040, 1, RI_ALL_ONLINE },
-	{ 0x2b8080, 1, RI_ALL_ONLINE },
-	{ 0x2b80c0, 1, RI_ALL_ONLINE },
-	{ 0x2b8100, 1, RI_ALL_ONLINE },
-	{ 0x2b8140, 1, RI_ALL_ONLINE },
-	{ 0x2b8180, 1, RI_ALL_ONLINE },
-	{ 0x2b81c0, 1, RI_ALL_ONLINE },
-	{ 0x2b8200, 1, RI_ALL_ONLINE },
-	{ 0x2b8240, 1, RI_ALL_ONLINE },
-	{ 0x2b8280, 1, RI_ALL_ONLINE },
-	{ 0x2b82c0, 1, RI_ALL_ONLINE },
-	{ 0x2b8300, 1, RI_ALL_ONLINE },
-	{ 0x2b8340, 1, RI_ALL_ONLINE },
-	{ 0x2b8380, 1, RI_ALL_ONLINE },
-	{ 0x2b83c0, 1, RI_ALL_ONLINE },
-	{ 0x2b8400, 1, RI_ALL_ONLINE },
-	{ 0x2b8440, 1, RI_ALL_ONLINE },
-	{ 0x2b8480, 1, RI_ALL_ONLINE },
-	{ 0x2b84c0, 1, RI_ALL_ONLINE },
-	{ 0x2b8500, 1, RI_ALL_ONLINE },
-	{ 0x2b8540, 1, RI_ALL_ONLINE },
-	{ 0x2b8580, 1, RI_ALL_ONLINE },
-	{ 0x2b85c0, 19, RI_E2E3E3B0_ONLINE },
-	{ 0x2b8800, 1, RI_ALL_ONLINE },
-	{ 0x2b8840, 1, RI_ALL_ONLINE },
-	{ 0x2b8880, 1, RI_ALL_ONLINE },
-	{ 0x2b88c0, 1, RI_ALL_ONLINE },
-	{ 0x2b8900, 1, RI_ALL_ONLINE },
-	{ 0x2b8940, 1, RI_ALL_ONLINE },
-	{ 0x2b8980, 1, RI_ALL_ONLINE },
-	{ 0x2b89c0, 1, RI_ALL_ONLINE },
-	{ 0x2b8a00, 1, RI_ALL_ONLINE },
-	{ 0x2b8a40, 1, RI_ALL_ONLINE },
-	{ 0x2b8a80, 1, RI_ALL_ONLINE },
-	{ 0x2b8ac0, 1, RI_ALL_ONLINE },
-	{ 0x2b8b00, 1, RI_ALL_ONLINE },
-	{ 0x2b8b40, 1, RI_ALL_ONLINE },
-	{ 0x2b8b80, 1, RI_ALL_ONLINE },
-	{ 0x2b8bc0, 1, RI_ALL_ONLINE },
-	{ 0x2b8c00, 1, RI_ALL_ONLINE },
-	{ 0x2b8c40, 1, RI_ALL_ONLINE },
-	{ 0x2b8c80, 1, RI_ALL_ONLINE },
-	{ 0x2b8cc0, 1, RI_ALL_ONLINE },
-	{ 0x2b8cc4, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x2b8d00, 1, RI_ALL_ONLINE },
-	{ 0x2b8d40, 1, RI_ALL_ONLINE },
-	{ 0x2b8d80, 1, RI_ALL_ONLINE },
-	{ 0x2b8dc0, 1, RI_ALL_ONLINE },
-	{ 0x2b8e00, 1, RI_ALL_ONLINE },
-	{ 0x2b8e40, 1, RI_ALL_ONLINE },
-	{ 0x2b8e80, 1, RI_ALL_ONLINE },
-	{ 0x2b8e84, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x2b8ec0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x2b8f00, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x2b8f40, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x2b8f80, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x2b8fc0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x2b8fc4, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x2b8fd0, 6, RI_E2E3E3B0_ONLINE },
-	{ 0x2b8fe8, 2, RI_E3E3B0_ONLINE },
-	{ 0x2b9000, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x2b9040, 3, RI_E2E3E3B0_ONLINE },
-	{ 0x2b905c, 1, RI_E3E3B0_ONLINE },
-	{ 0x2b9064, 1, RI_E3B0_ONLINE },
-	{ 0x2b9080, 10, RI_E3B0_ONLINE },
-	{ 0x2b9400, 14, RI_E2E3E3B0_ONLINE },
-	{ 0x2b943c, 19, RI_E2E3E3B0_ONLINE },
-	{ 0x2b9490, 10, RI_E2E3E3B0_ONLINE },
-	{ 0x2c0000, 2, RI_ALL_ONLINE },
-	{ 0x300000, 65, RI_ALL_ONLINE },
-	{ 0x30014c, 2, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x300200, 58, RI_ALL_ONLINE },
-	{ 0x300340, 4, RI_ALL_ONLINE },
-	{ 0x300380, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x300388, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x300390, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x300398, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x3003a0, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x3003a8, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x300400, 1, RI_ALL_ONLINE },
-	{ 0x300404, 255, RI_E1E1H_OFFLINE },
-	{ 0x302000, 4, RI_ALL_ONLINE },
-	{ 0x302010, 2044, RI_ALL_OFFLINE },
-	{ 0x304000, 4, RI_E3E3B0_ONLINE },
-	{ 0x320000, 1, RI_ALL_ONLINE },
-	{ 0x320004, 5631, RI_ALL_OFFLINE },
-	{ 0x325800, 2560, RI_E1HE2E3E3B0_OFFLINE },
-	{ 0x328000, 1, RI_ALL_ONLINE },
-	{ 0x328004, 8191, RI_E1HE2E3E3B0_OFFLINE },
-	{ 0x330000, 1, RI_ALL_ONLINE },
-	{ 0x330004, 15, RI_E1H_OFFLINE },
-	{ 0x330040, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x330044, 239, RI_E1H_OFFLINE },
-	{ 0x330400, 1, RI_ALL_ONLINE },
-	{ 0x330404, 255, RI_E1H_OFFLINE },
-	{ 0x330800, 1, RI_ALL_ONLINE },
-	{ 0x330840, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x330c00, 1, RI_ALL_ONLINE },
-	{ 0x331000, 1, RI_ALL_ONLINE },
-	{ 0x331040, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x331400, 1, RI_ALL_ONLINE },
-	{ 0x331440, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x331480, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x3314c0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x331800, 128, RI_ALL_OFFLINE },
-	{ 0x331c00, 128, RI_ALL_OFFLINE },
-	{ 0x332000, 1, RI_ALL_ONLINE },
-	{ 0x332400, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x332404, 5631, RI_E2E3E3B0_OFFLINE },
-	{ 0x338000, 1, RI_ALL_ONLINE },
-	{ 0x338040, 1, RI_ALL_ONLINE },
-	{ 0x338080, 1, RI_ALL_ONLINE },
-	{ 0x3380c0, 1, RI_ALL_ONLINE },
-	{ 0x338100, 1, RI_ALL_ONLINE },
-	{ 0x338140, 1, RI_ALL_ONLINE },
-	{ 0x338180, 1, RI_ALL_ONLINE },
-	{ 0x3381c0, 1, RI_ALL_ONLINE },
-	{ 0x338200, 1, RI_ALL_ONLINE },
-	{ 0x338240, 1, RI_ALL_ONLINE },
-	{ 0x338280, 1, RI_ALL_ONLINE },
-	{ 0x3382c0, 1, RI_ALL_ONLINE },
-	{ 0x338300, 1, RI_ALL_ONLINE },
-	{ 0x338340, 1, RI_ALL_ONLINE },
-	{ 0x338380, 1, RI_ALL_ONLINE },
-	{ 0x3383c0, 1, RI_ALL_ONLINE },
-	{ 0x338400, 1, RI_ALL_ONLINE },
-	{ 0x338440, 1, RI_ALL_ONLINE },
-	{ 0x338480, 1, RI_ALL_ONLINE },
-	{ 0x3384c0, 1, RI_ALL_ONLINE },
-	{ 0x338500, 1, RI_ALL_ONLINE },
-	{ 0x338540, 1, RI_ALL_ONLINE },
-	{ 0x338580, 1, RI_ALL_ONLINE },
-	{ 0x3385c0, 19, RI_E2E3E3B0_ONLINE },
-	{ 0x338800, 1, RI_ALL_ONLINE },
-	{ 0x338840, 1, RI_ALL_ONLINE },
-	{ 0x338880, 1, RI_ALL_ONLINE },
-	{ 0x3388c0, 1, RI_ALL_ONLINE },
-	{ 0x338900, 1, RI_ALL_ONLINE },
-	{ 0x338940, 1, RI_ALL_ONLINE },
-	{ 0x338980, 1, RI_ALL_ONLINE },
-	{ 0x3389c0, 1, RI_ALL_ONLINE },
-	{ 0x338a00, 1, RI_ALL_ONLINE },
-	{ 0x338a40, 1, RI_ALL_ONLINE },
-	{ 0x338a80, 1, RI_ALL_ONLINE },
-	{ 0x338ac0, 1, RI_ALL_ONLINE },
-	{ 0x338b00, 1, RI_ALL_ONLINE },
-	{ 0x338b40, 1, RI_ALL_ONLINE },
-	{ 0x338b80, 1, RI_ALL_ONLINE },
-	{ 0x338bc0, 1, RI_ALL_ONLINE },
-	{ 0x338c00, 1, RI_ALL_ONLINE },
-	{ 0x338c40, 1, RI_ALL_ONLINE },
-	{ 0x338c80, 1, RI_ALL_ONLINE },
-	{ 0x338cc0, 1, RI_ALL_ONLINE },
-	{ 0x338cc4, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x338d00, 1, RI_ALL_ONLINE },
-	{ 0x338d40, 1, RI_ALL_ONLINE },
-	{ 0x338d80, 1, RI_ALL_ONLINE },
-	{ 0x338dc0, 1, RI_ALL_ONLINE },
-	{ 0x338e00, 1, RI_ALL_ONLINE },
-	{ 0x338e40, 1, RI_ALL_ONLINE },
-	{ 0x338e80, 1, RI_ALL_ONLINE },
-	{ 0x338e84, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x338ec0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x338f00, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x338f40, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x338f80, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x338fc0, 1, RI_E1HE2E3E3B0_ONLINE },
-	{ 0x338fc4, 2, RI_E2E3E3B0_ONLINE },
-	{ 0x338fd0, 6, RI_E2E3E3B0_ONLINE },
-	{ 0x338fe8, 2, RI_E3E3B0_ONLINE },
-	{ 0x339000, 1, RI_E2E3E3B0_ONLINE },
-	{ 0x339040, 3, RI_E2E3E3B0_ONLINE },
-	{ 0x33905c, 1, RI_E3E3B0_ONLINE },
-	{ 0x339064, 1, RI_E3B0_ONLINE },
-	{ 0x339080, 10, RI_E3B0_ONLINE },
-	{ 0x340000, 2, RI_ALL_ONLINE },
-};
-#define REGS_COUNT			ARRAY_SIZE(reg_addrs)
-
-static const struct dump_sign dump_sign_all = { 0x4e23fde1, 0x70017, 0x3a };
-
-static const u32 page_vals_e2[] = { 0, 128 };
-#define PAGE_MODE_VALUES_E2		ARRAY_SIZE(page_vals_e2)
-
-static const u32 page_write_regs_e2[] = { 328476 };
-#define PAGE_WRITE_REGS_E2		ARRAY_SIZE(page_write_regs_e2)
-
-static const struct reg_addr page_read_regs_e2[] = {
-	{ 0x58000, 4608, RI_E2_ONLINE } };
-#define PAGE_READ_REGS_E2		ARRAY_SIZE(page_read_regs_e2)
-
-static const u32 page_vals_e3[] = { 0, 128 };
-#define PAGE_MODE_VALUES_E3		ARRAY_SIZE(page_vals_e3)
-
-static const u32 page_write_regs_e3[] = { 328476 };
-#define PAGE_WRITE_REGS_E3		ARRAY_SIZE(page_write_regs_e3)
-
-static const struct reg_addr page_read_regs_e3[] = {
-	{ 0x58000, 4608, RI_E3E3B0_ONLINE } };
-#define PAGE_READ_REGS_E3		ARRAY_SIZE(page_read_regs_e3)
-
-#endif /* BNX2X_DUMP_H */
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_ethtool.c linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_ethtool.c
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_ethtool.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_ethtool.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2389 +0,0 @@
-/* bnx2x_ethtool.c: Broadcom Everest network driver.
- *
- * Copyright (c) 2007-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
- * the Free Software Foundation.
- *
- * Maintained by: Eilon Greenstein <eilong@broadcom.com>
- * Written by: Eliezer Tamir
- * Based on code from Michael Chan's bnx2 driver
- * UDP CSUM errata workaround by Arik Gendelman
- * Slowpath and fastpath rework by Vladislav Zolotarov
- * Statistics and Link management by Yitchak Gertner
- *
- */
-#include <linux/ethtool.h>
-#include <linux/netdevice.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/crc32.h>
-
-
-#include "bnx2x.h"
-#include "bnx2x_cmn.h"
-#include "bnx2x_dump.h"
-#include "bnx2x_init.h"
-#include "bnx2x_sp.h"
-
-/* Note: in the format strings below %s is replaced by the queue-name which is
- * either its index or 'fcoe' for the fcoe queue. Make sure the format string
- * length does not exceed ETH_GSTRING_LEN - MAX_QUEUE_NAME_LEN + 2
- */
-#define MAX_QUEUE_NAME_LEN	4
-static const struct {
-	long offset;
-	int size;
-	char string[ETH_GSTRING_LEN];
-} bnx2x_q_stats_arr[] = {
-/* 1 */	{ Q_STATS_OFFSET32(total_bytes_received_hi), 8, "[%s]: rx_bytes" },
-	{ Q_STATS_OFFSET32(total_unicast_packets_received_hi),
-						8, "[%s]: rx_ucast_packets" },
-	{ Q_STATS_OFFSET32(total_multicast_packets_received_hi),
-						8, "[%s]: rx_mcast_packets" },
-	{ Q_STATS_OFFSET32(total_broadcast_packets_received_hi),
-						8, "[%s]: rx_bcast_packets" },
-	{ Q_STATS_OFFSET32(no_buff_discard_hi),	8, "[%s]: rx_discards" },
-	{ Q_STATS_OFFSET32(rx_err_discard_pkt),
-					 4, "[%s]: rx_phy_ip_err_discards"},
-	{ Q_STATS_OFFSET32(rx_skb_alloc_failed),
-					 4, "[%s]: rx_skb_alloc_discard" },
-	{ Q_STATS_OFFSET32(hw_csum_err), 4, "[%s]: rx_csum_offload_errors" },
-
-	{ Q_STATS_OFFSET32(total_bytes_transmitted_hi),	8, "[%s]: tx_bytes" },
-/* 10 */{ Q_STATS_OFFSET32(total_unicast_packets_transmitted_hi),
-						8, "[%s]: tx_ucast_packets" },
-	{ Q_STATS_OFFSET32(total_multicast_packets_transmitted_hi),
-						8, "[%s]: tx_mcast_packets" },
-	{ Q_STATS_OFFSET32(total_broadcast_packets_transmitted_hi),
-						8, "[%s]: tx_bcast_packets" },
-	{ Q_STATS_OFFSET32(total_tpa_aggregations_hi),
-						8, "[%s]: tpa_aggregations" },
-	{ Q_STATS_OFFSET32(total_tpa_aggregated_frames_hi),
-					8, "[%s]: tpa_aggregated_frames"},
-	{ Q_STATS_OFFSET32(total_tpa_bytes_hi),	8, "[%s]: tpa_bytes"}
-};
-
-#define BNX2X_NUM_Q_STATS ARRAY_SIZE(bnx2x_q_stats_arr)
-
-static const struct {
-	long offset;
-	int size;
-	u32 flags;
-#define STATS_FLAGS_PORT		1
-#define STATS_FLAGS_FUNC		2
-#define STATS_FLAGS_BOTH		(STATS_FLAGS_FUNC | STATS_FLAGS_PORT)
-	char string[ETH_GSTRING_LEN];
-} bnx2x_stats_arr[] = {
-/* 1 */	{ STATS_OFFSET32(total_bytes_received_hi),
-				8, STATS_FLAGS_BOTH, "rx_bytes" },
-	{ STATS_OFFSET32(error_bytes_received_hi),
-				8, STATS_FLAGS_BOTH, "rx_error_bytes" },
-	{ STATS_OFFSET32(total_unicast_packets_received_hi),
-				8, STATS_FLAGS_BOTH, "rx_ucast_packets" },
-	{ STATS_OFFSET32(total_multicast_packets_received_hi),
-				8, STATS_FLAGS_BOTH, "rx_mcast_packets" },
-	{ STATS_OFFSET32(total_broadcast_packets_received_hi),
-				8, STATS_FLAGS_BOTH, "rx_bcast_packets" },
-	{ STATS_OFFSET32(rx_stat_dot3statsfcserrors_hi),
-				8, STATS_FLAGS_PORT, "rx_crc_errors" },
-	{ STATS_OFFSET32(rx_stat_dot3statsalignmenterrors_hi),
-				8, STATS_FLAGS_PORT, "rx_align_errors" },
-	{ STATS_OFFSET32(rx_stat_etherstatsundersizepkts_hi),
-				8, STATS_FLAGS_PORT, "rx_undersize_packets" },
-	{ STATS_OFFSET32(etherstatsoverrsizepkts_hi),
-				8, STATS_FLAGS_PORT, "rx_oversize_packets" },
-/* 10 */{ STATS_OFFSET32(rx_stat_etherstatsfragments_hi),
-				8, STATS_FLAGS_PORT, "rx_fragments" },
-	{ STATS_OFFSET32(rx_stat_etherstatsjabbers_hi),
-				8, STATS_FLAGS_PORT, "rx_jabbers" },
-	{ STATS_OFFSET32(no_buff_discard_hi),
-				8, STATS_FLAGS_BOTH, "rx_discards" },
-	{ STATS_OFFSET32(mac_filter_discard),
-				4, STATS_FLAGS_PORT, "rx_filtered_packets" },
-	{ STATS_OFFSET32(mf_tag_discard),
-				4, STATS_FLAGS_PORT, "rx_mf_tag_discard" },
-	{ STATS_OFFSET32(brb_drop_hi),
-				8, STATS_FLAGS_PORT, "rx_brb_discard" },
-	{ STATS_OFFSET32(brb_truncate_hi),
-				8, STATS_FLAGS_PORT, "rx_brb_truncate" },
-	{ STATS_OFFSET32(pause_frames_received_hi),
-				8, STATS_FLAGS_PORT, "rx_pause_frames" },
-	{ STATS_OFFSET32(rx_stat_maccontrolframesreceived_hi),
-				8, STATS_FLAGS_PORT, "rx_mac_ctrl_frames" },
-	{ STATS_OFFSET32(nig_timer_max),
-			4, STATS_FLAGS_PORT, "rx_constant_pause_events" },
-/* 20 */{ STATS_OFFSET32(rx_err_discard_pkt),
-				4, STATS_FLAGS_BOTH, "rx_phy_ip_err_discards"},
-	{ STATS_OFFSET32(rx_skb_alloc_failed),
-				4, STATS_FLAGS_BOTH, "rx_skb_alloc_discard" },
-	{ STATS_OFFSET32(hw_csum_err),
-				4, STATS_FLAGS_BOTH, "rx_csum_offload_errors" },
-
-	{ STATS_OFFSET32(total_bytes_transmitted_hi),
-				8, STATS_FLAGS_BOTH, "tx_bytes" },
-	{ STATS_OFFSET32(tx_stat_ifhcoutbadoctets_hi),
-				8, STATS_FLAGS_PORT, "tx_error_bytes" },
-	{ STATS_OFFSET32(total_unicast_packets_transmitted_hi),
-				8, STATS_FLAGS_BOTH, "tx_ucast_packets" },
-	{ STATS_OFFSET32(total_multicast_packets_transmitted_hi),
-				8, STATS_FLAGS_BOTH, "tx_mcast_packets" },
-	{ STATS_OFFSET32(total_broadcast_packets_transmitted_hi),
-				8, STATS_FLAGS_BOTH, "tx_bcast_packets" },
-	{ STATS_OFFSET32(tx_stat_dot3statsinternalmactransmiterrors_hi),
-				8, STATS_FLAGS_PORT, "tx_mac_errors" },
-	{ STATS_OFFSET32(rx_stat_dot3statscarriersenseerrors_hi),
-				8, STATS_FLAGS_PORT, "tx_carrier_errors" },
-/* 30 */{ STATS_OFFSET32(tx_stat_dot3statssinglecollisionframes_hi),
-				8, STATS_FLAGS_PORT, "tx_single_collisions" },
-	{ STATS_OFFSET32(tx_stat_dot3statsmultiplecollisionframes_hi),
-				8, STATS_FLAGS_PORT, "tx_multi_collisions" },
-	{ STATS_OFFSET32(tx_stat_dot3statsdeferredtransmissions_hi),
-				8, STATS_FLAGS_PORT, "tx_deferred" },
-	{ STATS_OFFSET32(tx_stat_dot3statsexcessivecollisions_hi),
-				8, STATS_FLAGS_PORT, "tx_excess_collisions" },
-	{ STATS_OFFSET32(tx_stat_dot3statslatecollisions_hi),
-				8, STATS_FLAGS_PORT, "tx_late_collisions" },
-	{ STATS_OFFSET32(tx_stat_etherstatscollisions_hi),
-				8, STATS_FLAGS_PORT, "tx_total_collisions" },
-	{ STATS_OFFSET32(tx_stat_etherstatspkts64octets_hi),
-				8, STATS_FLAGS_PORT, "tx_64_byte_packets" },
-	{ STATS_OFFSET32(tx_stat_etherstatspkts65octetsto127octets_hi),
-			8, STATS_FLAGS_PORT, "tx_65_to_127_byte_packets" },
-	{ STATS_OFFSET32(tx_stat_etherstatspkts128octetsto255octets_hi),
-			8, STATS_FLAGS_PORT, "tx_128_to_255_byte_packets" },
-	{ STATS_OFFSET32(tx_stat_etherstatspkts256octetsto511octets_hi),
-			8, STATS_FLAGS_PORT, "tx_256_to_511_byte_packets" },
-/* 40 */{ STATS_OFFSET32(tx_stat_etherstatspkts512octetsto1023octets_hi),
-			8, STATS_FLAGS_PORT, "tx_512_to_1023_byte_packets" },
-	{ STATS_OFFSET32(etherstatspkts1024octetsto1522octets_hi),
-			8, STATS_FLAGS_PORT, "tx_1024_to_1522_byte_packets" },
-	{ STATS_OFFSET32(etherstatspktsover1522octets_hi),
-			8, STATS_FLAGS_PORT, "tx_1523_to_9022_byte_packets" },
-	{ STATS_OFFSET32(pause_frames_sent_hi),
-				8, STATS_FLAGS_PORT, "tx_pause_frames" },
-	{ STATS_OFFSET32(total_tpa_aggregations_hi),
-			8, STATS_FLAGS_FUNC, "tpa_aggregations" },
-	{ STATS_OFFSET32(total_tpa_aggregated_frames_hi),
-			8, STATS_FLAGS_FUNC, "tpa_aggregated_frames"},
-	{ STATS_OFFSET32(total_tpa_bytes_hi),
-			8, STATS_FLAGS_FUNC, "tpa_bytes"}
-};
-
-#define BNX2X_NUM_STATS		ARRAY_SIZE(bnx2x_stats_arr)
-static int bnx2x_get_port_type(struct bnx2x *bp)
-{
-	int port_type;
-	u32 phy_idx = bnx2x_get_cur_phy_idx(bp);
-	switch (bp->link_params.phy[phy_idx].media_type) {
-	case ETH_PHY_SFP_FIBER:
-	case ETH_PHY_XFP_FIBER:
-	case ETH_PHY_KR:
-	case ETH_PHY_CX4:
-		port_type = PORT_FIBRE;
-		break;
-	case ETH_PHY_DA_TWINAX:
-		port_type = PORT_DA;
-		break;
-	case ETH_PHY_BASE_T:
-		port_type = PORT_TP;
-		break;
-	case ETH_PHY_NOT_PRESENT:
-		port_type = PORT_NONE;
-		break;
-	case ETH_PHY_UNSPECIFIED:
-	default:
-		port_type = PORT_OTHER;
-		break;
-	}
-	return port_type;
-}
-
-static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	int cfg_idx = bnx2x_get_link_cfg_idx(bp);
-
-	/* Dual Media boards present all available port types */
-	cmd->supported = bp->port.supported[cfg_idx] |
-		(bp->port.supported[cfg_idx ^ 1] &
-		 (SUPPORTED_TP | SUPPORTED_FIBRE));
-	cmd->advertising = bp->port.advertising[cfg_idx];
-
-	if ((bp->state == BNX2X_STATE_OPEN) &&
-	    !(bp->flags & MF_FUNC_DIS) &&
-	    (bp->link_vars.link_up)) {
-		ethtool_cmd_speed_set(cmd, bp->link_vars.line_speed);
-		cmd->duplex = bp->link_vars.duplex;
-	} else {
-		ethtool_cmd_speed_set(
-			cmd, bp->link_params.req_line_speed[cfg_idx]);
-		cmd->duplex = bp->link_params.req_duplex[cfg_idx];
-	}
-
-	if (IS_MF(bp))
-		ethtool_cmd_speed_set(cmd, bnx2x_get_mf_speed(bp));
-
-	cmd->port = bnx2x_get_port_type(bp);
-
-	cmd->phy_address = bp->mdio.prtad;
-	cmd->transceiver = XCVR_INTERNAL;
-
-	if (bp->link_params.req_line_speed[cfg_idx] == SPEED_AUTO_NEG)
-		cmd->autoneg = AUTONEG_ENABLE;
-	else
-		cmd->autoneg = AUTONEG_DISABLE;
-
-	cmd->maxtxpkt = 0;
-	cmd->maxrxpkt = 0;
-
-	DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n"
-	   DP_LEVEL "  supported 0x%x  advertising 0x%x  speed %u\n"
-	   DP_LEVEL "  duplex %d  port %d  phy_address %d  transceiver %d\n"
-	   DP_LEVEL "  autoneg %d  maxtxpkt %d  maxrxpkt %d\n",
-	   cmd->cmd, cmd->supported, cmd->advertising,
-	   ethtool_cmd_speed(cmd),
-	   cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver,
-	   cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt);
-
-	return 0;
-}
-
-static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	u32 advertising, cfg_idx, old_multi_phy_config, new_multi_phy_config;
-	u32 speed;
-
-	if (IS_MF_SD(bp))
-		return 0;
-
-	DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n"
-	   "  supported 0x%x  advertising 0x%x  speed %u\n"
-	   "  duplex %d  port %d  phy_address %d  transceiver %d\n"
-	   "  autoneg %d  maxtxpkt %d  maxrxpkt %d\n",
-	   cmd->cmd, cmd->supported, cmd->advertising,
-	   ethtool_cmd_speed(cmd),
-	   cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver,
-	   cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt);
-
-	speed = ethtool_cmd_speed(cmd);
-
-	if (IS_MF_SI(bp)) {
-		u32 part;
-		u32 line_speed = bp->link_vars.line_speed;
-
-		/* use 10G if no link detected */
-		if (!line_speed)
-			line_speed = 10000;
-
-		if (bp->common.bc_ver < REQ_BC_VER_4_SET_MF_BW) {
-			BNX2X_DEV_INFO("To set speed BC %X or higher "
-				       "is required, please upgrade BC\n",
-				       REQ_BC_VER_4_SET_MF_BW);
-			return -EINVAL;
-		}
-
-		part = (speed * 100) / line_speed;
-
-		if (line_speed < speed || !part) {
-			BNX2X_DEV_INFO("Speed setting should be in a range "
-				       "from 1%% to 100%% "
-				       "of actual line speed\n");
-			return -EINVAL;
-		}
-
-		if (bp->state != BNX2X_STATE_OPEN)
-			/* store value for following "load" */
-			bp->pending_max = part;
-		else
-			bnx2x_update_max_mf_config(bp, part);
-
-		return 0;
-	}
-
-	cfg_idx = bnx2x_get_link_cfg_idx(bp);
-	old_multi_phy_config = bp->link_params.multi_phy_config;
-	switch (cmd->port) {
-	case PORT_TP:
-		if (bp->port.supported[cfg_idx] & SUPPORTED_TP)
-			break; /* no port change */
-
-		if (!(bp->port.supported[0] & SUPPORTED_TP ||
-		      bp->port.supported[1] & SUPPORTED_TP)) {
-			DP(NETIF_MSG_LINK, "Unsupported port type\n");
-			return -EINVAL;
-		}
-		bp->link_params.multi_phy_config &=
-			~PORT_HW_CFG_PHY_SELECTION_MASK;
-		if (bp->link_params.multi_phy_config &
-		    PORT_HW_CFG_PHY_SWAPPED_ENABLED)
-			bp->link_params.multi_phy_config |=
-			PORT_HW_CFG_PHY_SELECTION_SECOND_PHY;
-		else
-			bp->link_params.multi_phy_config |=
-			PORT_HW_CFG_PHY_SELECTION_FIRST_PHY;
-		break;
-	case PORT_FIBRE:
-		if (bp->port.supported[cfg_idx] & SUPPORTED_FIBRE)
-			break; /* no port change */
-
-		if (!(bp->port.supported[0] & SUPPORTED_FIBRE ||
-		      bp->port.supported[1] & SUPPORTED_FIBRE)) {
-			DP(NETIF_MSG_LINK, "Unsupported port type\n");
-			return -EINVAL;
-		}
-		bp->link_params.multi_phy_config &=
-			~PORT_HW_CFG_PHY_SELECTION_MASK;
-		if (bp->link_params.multi_phy_config &
-		    PORT_HW_CFG_PHY_SWAPPED_ENABLED)
-			bp->link_params.multi_phy_config |=
-			PORT_HW_CFG_PHY_SELECTION_FIRST_PHY;
-		else
-			bp->link_params.multi_phy_config |=
-			PORT_HW_CFG_PHY_SELECTION_SECOND_PHY;
-		break;
-	default:
-		DP(NETIF_MSG_LINK, "Unsupported port type\n");
-		return -EINVAL;
-	}
-	/* Save new config in case command complete successuly */
-	new_multi_phy_config = bp->link_params.multi_phy_config;
-	/* Get the new cfg_idx */
-	cfg_idx = bnx2x_get_link_cfg_idx(bp);
-	/* Restore old config in case command failed */
-	bp->link_params.multi_phy_config = old_multi_phy_config;
-	DP(NETIF_MSG_LINK, "cfg_idx = %x\n", cfg_idx);
-
-	if (cmd->autoneg == AUTONEG_ENABLE) {
-		if (!(bp->port.supported[cfg_idx] & SUPPORTED_Autoneg)) {
-			DP(NETIF_MSG_LINK, "Autoneg not supported\n");
-			return -EINVAL;
-		}
-
-		/* advertise the requested speed and duplex if supported */
-		if (cmd->advertising & ~(bp->port.supported[cfg_idx])) {
-			DP(NETIF_MSG_LINK, "Advertisement parameters "
-					   "are not supported\n");
-			return -EINVAL;
-		}
-
-		bp->link_params.req_line_speed[cfg_idx] = SPEED_AUTO_NEG;
-		bp->link_params.req_duplex[cfg_idx] = cmd->duplex;
-		bp->port.advertising[cfg_idx] = (ADVERTISED_Autoneg |
-					 cmd->advertising);
-		if (cmd->advertising) {
-
-			bp->link_params.speed_cap_mask[cfg_idx] = 0;
-			if (cmd->advertising & ADVERTISED_10baseT_Half) {
-				bp->link_params.speed_cap_mask[cfg_idx] |=
-				PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF;
-			}
-			if (cmd->advertising & ADVERTISED_10baseT_Full)
-				bp->link_params.speed_cap_mask[cfg_idx] |=
-				PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL;
-
-			if (cmd->advertising & ADVERTISED_100baseT_Full)
-				bp->link_params.speed_cap_mask[cfg_idx] |=
-				PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL;
-
-			if (cmd->advertising & ADVERTISED_100baseT_Half) {
-				bp->link_params.speed_cap_mask[cfg_idx] |=
-				     PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF;
-			}
-			if (cmd->advertising & ADVERTISED_1000baseT_Half) {
-				bp->link_params.speed_cap_mask[cfg_idx] |=
-					PORT_HW_CFG_SPEED_CAPABILITY_D0_1G;
-			}
-			if (cmd->advertising & (ADVERTISED_1000baseT_Full |
-						ADVERTISED_1000baseKX_Full))
-				bp->link_params.speed_cap_mask[cfg_idx] |=
-					PORT_HW_CFG_SPEED_CAPABILITY_D0_1G;
-
-			if (cmd->advertising & (ADVERTISED_10000baseT_Full |
-						ADVERTISED_10000baseKX4_Full |
-						ADVERTISED_10000baseKR_Full))
-				bp->link_params.speed_cap_mask[cfg_idx] |=
-					PORT_HW_CFG_SPEED_CAPABILITY_D0_10G;
-		}
-	} else { /* forced speed */
-		/* advertise the requested speed and duplex if supported */
-		switch (speed) {
-		case SPEED_10:
-			if (cmd->duplex == DUPLEX_FULL) {
-				if (!(bp->port.supported[cfg_idx] &
-				      SUPPORTED_10baseT_Full)) {
-					DP(NETIF_MSG_LINK,
-					   "10M full not supported\n");
-					return -EINVAL;
-				}
-
-				advertising = (ADVERTISED_10baseT_Full |
-					       ADVERTISED_TP);
-			} else {
-				if (!(bp->port.supported[cfg_idx] &
-				      SUPPORTED_10baseT_Half)) {
-					DP(NETIF_MSG_LINK,
-					   "10M half not supported\n");
-					return -EINVAL;
-				}
-
-				advertising = (ADVERTISED_10baseT_Half |
-					       ADVERTISED_TP);
-			}
-			break;
-
-		case SPEED_100:
-			if (cmd->duplex == DUPLEX_FULL) {
-				if (!(bp->port.supported[cfg_idx] &
-						SUPPORTED_100baseT_Full)) {
-					DP(NETIF_MSG_LINK,
-					   "100M full not supported\n");
-					return -EINVAL;
-				}
-
-				advertising = (ADVERTISED_100baseT_Full |
-					       ADVERTISED_TP);
-			} else {
-				if (!(bp->port.supported[cfg_idx] &
-						SUPPORTED_100baseT_Half)) {
-					DP(NETIF_MSG_LINK,
-					   "100M half not supported\n");
-					return -EINVAL;
-				}
-
-				advertising = (ADVERTISED_100baseT_Half |
-					       ADVERTISED_TP);
-			}
-			break;
-
-		case SPEED_1000:
-			if (cmd->duplex != DUPLEX_FULL) {
-				DP(NETIF_MSG_LINK, "1G half not supported\n");
-				return -EINVAL;
-			}
-
-			if (!(bp->port.supported[cfg_idx] &
-			      SUPPORTED_1000baseT_Full)) {
-				DP(NETIF_MSG_LINK, "1G full not supported\n");
-				return -EINVAL;
-			}
-
-			advertising = (ADVERTISED_1000baseT_Full |
-				       ADVERTISED_TP);
-			break;
-
-		case SPEED_2500:
-			if (cmd->duplex != DUPLEX_FULL) {
-				DP(NETIF_MSG_LINK,
-				   "2.5G half not supported\n");
-				return -EINVAL;
-			}
-
-			if (!(bp->port.supported[cfg_idx]
-			      & SUPPORTED_2500baseX_Full)) {
-				DP(NETIF_MSG_LINK,
-				   "2.5G full not supported\n");
-				return -EINVAL;
-			}
-
-			advertising = (ADVERTISED_2500baseX_Full |
-				       ADVERTISED_TP);
-			break;
-
-		case SPEED_10000:
-			if (cmd->duplex != DUPLEX_FULL) {
-				DP(NETIF_MSG_LINK, "10G half not supported\n");
-				return -EINVAL;
-			}
-
-			if (!(bp->port.supported[cfg_idx]
-			      & SUPPORTED_10000baseT_Full)) {
-				DP(NETIF_MSG_LINK, "10G full not supported\n");
-				return -EINVAL;
-			}
-
-			advertising = (ADVERTISED_10000baseT_Full |
-				       ADVERTISED_FIBRE);
-			break;
-
-		default:
-			DP(NETIF_MSG_LINK, "Unsupported speed %u\n", speed);
-			return -EINVAL;
-		}
-
-		bp->link_params.req_line_speed[cfg_idx] = speed;
-		bp->link_params.req_duplex[cfg_idx] = cmd->duplex;
-		bp->port.advertising[cfg_idx] = advertising;
-	}
-
-	DP(NETIF_MSG_LINK, "req_line_speed %d\n"
-	   DP_LEVEL "  req_duplex %d  advertising 0x%x\n",
-	   bp->link_params.req_line_speed[cfg_idx],
-	   bp->link_params.req_duplex[cfg_idx],
-	   bp->port.advertising[cfg_idx]);
-
-	/* Set new config */
-	bp->link_params.multi_phy_config = new_multi_phy_config;
-	if (netif_running(dev)) {
-		bnx2x_stats_handle(bp, STATS_EVENT_STOP);
-		bnx2x_link_set(bp);
-	}
-
-	return 0;
-}
-
-#define IS_E1_ONLINE(info)	(((info) & RI_E1_ONLINE) == RI_E1_ONLINE)
-#define IS_E1H_ONLINE(info)	(((info) & RI_E1H_ONLINE) == RI_E1H_ONLINE)
-#define IS_E2_ONLINE(info)	(((info) & RI_E2_ONLINE) == RI_E2_ONLINE)
-#define IS_E3_ONLINE(info)	(((info) & RI_E3_ONLINE) == RI_E3_ONLINE)
-#define IS_E3B0_ONLINE(info)	(((info) & RI_E3B0_ONLINE) == RI_E3B0_ONLINE)
-
-static inline bool bnx2x_is_reg_online(struct bnx2x *bp,
-				       const struct reg_addr *reg_info)
-{
-	if (CHIP_IS_E1(bp))
-		return IS_E1_ONLINE(reg_info->info);
-	else if (CHIP_IS_E1H(bp))
-		return IS_E1H_ONLINE(reg_info->info);
-	else if (CHIP_IS_E2(bp))
-		return IS_E2_ONLINE(reg_info->info);
-	else if (CHIP_IS_E3A0(bp))
-		return IS_E3_ONLINE(reg_info->info);
-	else if (CHIP_IS_E3B0(bp))
-		return IS_E3B0_ONLINE(reg_info->info);
-	else
-		return false;
-}
-
-/******* Paged registers info selectors ********/
-static inline const u32 *__bnx2x_get_page_addr_ar(struct bnx2x *bp)
-{
-	if (CHIP_IS_E2(bp))
-		return page_vals_e2;
-	else if (CHIP_IS_E3(bp))
-		return page_vals_e3;
-	else
-		return NULL;
-}
-
-static inline u32 __bnx2x_get_page_reg_num(struct bnx2x *bp)
-{
-	if (CHIP_IS_E2(bp))
-		return PAGE_MODE_VALUES_E2;
-	else if (CHIP_IS_E3(bp))
-		return PAGE_MODE_VALUES_E3;
-	else
-		return 0;
-}
-
-static inline const u32 *__bnx2x_get_page_write_ar(struct bnx2x *bp)
-{
-	if (CHIP_IS_E2(bp))
-		return page_write_regs_e2;
-	else if (CHIP_IS_E3(bp))
-		return page_write_regs_e3;
-	else
-		return NULL;
-}
-
-static inline u32 __bnx2x_get_page_write_num(struct bnx2x *bp)
-{
-	if (CHIP_IS_E2(bp))
-		return PAGE_WRITE_REGS_E2;
-	else if (CHIP_IS_E3(bp))
-		return PAGE_WRITE_REGS_E3;
-	else
-		return 0;
-}
-
-static inline const struct reg_addr *__bnx2x_get_page_read_ar(struct bnx2x *bp)
-{
-	if (CHIP_IS_E2(bp))
-		return page_read_regs_e2;
-	else if (CHIP_IS_E3(bp))
-		return page_read_regs_e3;
-	else
-		return NULL;
-}
-
-static inline u32 __bnx2x_get_page_read_num(struct bnx2x *bp)
-{
-	if (CHIP_IS_E2(bp))
-		return PAGE_READ_REGS_E2;
-	else if (CHIP_IS_E3(bp))
-		return PAGE_READ_REGS_E3;
-	else
-		return 0;
-}
-
-static inline int __bnx2x_get_regs_len(struct bnx2x *bp)
-{
-	int num_pages = __bnx2x_get_page_reg_num(bp);
-	int page_write_num = __bnx2x_get_page_write_num(bp);
-	const struct reg_addr *page_read_addr = __bnx2x_get_page_read_ar(bp);
-	int page_read_num = __bnx2x_get_page_read_num(bp);
-	int regdump_len = 0;
-	int i, j, k;
-
-	for (i = 0; i < REGS_COUNT; i++)
-		if (bnx2x_is_reg_online(bp, &reg_addrs[i]))
-			regdump_len += reg_addrs[i].size;
-
-	for (i = 0; i < num_pages; i++)
-		for (j = 0; j < page_write_num; j++)
-			for (k = 0; k < page_read_num; k++)
-				if (bnx2x_is_reg_online(bp, &page_read_addr[k]))
-					regdump_len += page_read_addr[k].size;
-
-	return regdump_len;
-}
-
-static int bnx2x_get_regs_len(struct net_device *dev)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	int regdump_len = 0;
-
-	regdump_len = __bnx2x_get_regs_len(bp);
-	regdump_len *= 4;
-	regdump_len += sizeof(struct dump_hdr);
-
-	return regdump_len;
-}
-
-/**
- * bnx2x_read_pages_regs - read "paged" registers
- *
- * @bp		device handle
- * @p		output buffer
- *
- * Reads "paged" memories: memories that may only be read by first writing to a
- * specific address ("write address") and then reading from a specific address
- * ("read address"). There may be more than one write address per "page" and
- * more than one read address per write address.
- */
-static inline void bnx2x_read_pages_regs(struct bnx2x *bp, u32 *p)
-{
-	u32 i, j, k, n;
-	/* addresses of the paged registers */
-	const u32 *page_addr = __bnx2x_get_page_addr_ar(bp);
-	/* number of paged registers */
-	int num_pages = __bnx2x_get_page_reg_num(bp);
-	/* write addresses */
-	const u32 *write_addr = __bnx2x_get_page_write_ar(bp);
-	/* number of write addresses */
-	int write_num = __bnx2x_get_page_write_num(bp);
-	/* read addresses info */
-	const struct reg_addr *read_addr = __bnx2x_get_page_read_ar(bp);
-	/* number of read addresses */
-	int read_num = __bnx2x_get_page_read_num(bp);
-
-	for (i = 0; i < num_pages; i++) {
-		for (j = 0; j < write_num; j++) {
-			REG_WR(bp, write_addr[j], page_addr[i]);
-			for (k = 0; k < read_num; k++)
-				if (bnx2x_is_reg_online(bp, &read_addr[k]))
-					for (n = 0; n <
-					      read_addr[k].size; n++)
-						*p++ = REG_RD(bp,
-						       read_addr[k].addr + n*4);
-		}
-	}
-}
-
-static inline void __bnx2x_get_regs(struct bnx2x *bp, u32 *p)
-{
-	u32 i, j;
-
-	/* Read the regular registers */
-	for (i = 0; i < REGS_COUNT; i++)
-		if (bnx2x_is_reg_online(bp, &reg_addrs[i]))
-			for (j = 0; j < reg_addrs[i].size; j++)
-				*p++ = REG_RD(bp, reg_addrs[i].addr + j*4);
-
-	/* Read "paged" registes */
-	bnx2x_read_pages_regs(bp, p);
-}
-
-static void bnx2x_get_regs(struct net_device *dev,
-			   struct ethtool_regs *regs, void *_p)
-{
-	u32 *p = _p;
-	struct bnx2x *bp = netdev_priv(dev);
-	struct dump_hdr dump_hdr = {0};
-
-	regs->version = 0;
-	memset(p, 0, regs->len);
-
-	if (!netif_running(bp->dev))
-		return;
-
-	/* Disable parity attentions as long as following dump may
-	 * cause false alarms by reading never written registers. We
-	 * will re-enable parity attentions right after the dump.
-	 */
-	bnx2x_disable_blocks_parity(bp);
-
-	dump_hdr.hdr_size = (sizeof(struct dump_hdr) / 4) - 1;
-	dump_hdr.dump_sign = dump_sign_all;
-	dump_hdr.xstorm_waitp = REG_RD(bp, XSTORM_WAITP_ADDR);
-	dump_hdr.tstorm_waitp = REG_RD(bp, TSTORM_WAITP_ADDR);
-	dump_hdr.ustorm_waitp = REG_RD(bp, USTORM_WAITP_ADDR);
-	dump_hdr.cstorm_waitp = REG_RD(bp, CSTORM_WAITP_ADDR);
-
-	if (CHIP_IS_E1(bp))
-		dump_hdr.info = RI_E1_ONLINE;
-	else if (CHIP_IS_E1H(bp))
-		dump_hdr.info = RI_E1H_ONLINE;
-	else if (!CHIP_IS_E1x(bp))
-		dump_hdr.info = RI_E2_ONLINE |
-		(BP_PATH(bp) ? RI_PATH1_DUMP : RI_PATH0_DUMP);
-
-	memcpy(p, &dump_hdr, sizeof(struct dump_hdr));
-	p += dump_hdr.hdr_size + 1;
-
-	/* Actually read the registers */
-	__bnx2x_get_regs(bp, p);
-
-	/* Re-enable parity attentions */
-	bnx2x_clear_blocks_parity(bp);
-	bnx2x_enable_blocks_parity(bp);
-}
-
-static void bnx2x_get_drvinfo(struct net_device *dev,
-			      struct ethtool_drvinfo *info)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	u8 phy_fw_ver[PHY_FW_VER_LEN];
-
-	strcpy(info->driver, DRV_MODULE_NAME);
-	strcpy(info->version, DRV_MODULE_VERSION);
-
-	phy_fw_ver[0] = '\0';
-	if (bp->port.pmf) {
-		bnx2x_acquire_phy_lock(bp);
-		bnx2x_get_ext_phy_fw_version(&bp->link_params,
-					     (bp->state != BNX2X_STATE_CLOSED),
-					     phy_fw_ver, PHY_FW_VER_LEN);
-		bnx2x_release_phy_lock(bp);
-	}
-
-	strncpy(info->fw_version, bp->fw_ver, 32);
-	snprintf(info->fw_version + strlen(bp->fw_ver), 32 - strlen(bp->fw_ver),
-		 "bc %d.%d.%d%s%s",
-		 (bp->common.bc_ver & 0xff0000) >> 16,
-		 (bp->common.bc_ver & 0xff00) >> 8,
-		 (bp->common.bc_ver & 0xff),
-		 ((phy_fw_ver[0] != '\0') ? " phy " : ""), phy_fw_ver);
-	strcpy(info->bus_info, pci_name(bp->pdev));
-	info->n_stats = BNX2X_NUM_STATS;
-	info->testinfo_len = BNX2X_NUM_TESTS;
-	info->eedump_len = bp->common.flash_size;
-	info->regdump_len = bnx2x_get_regs_len(dev);
-}
-
-static void bnx2x_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	if (bp->flags & NO_WOL_FLAG) {
-		wol->supported = 0;
-		wol->wolopts = 0;
-	} else {
-		wol->supported = WAKE_MAGIC;
-		if (bp->wol)
-			wol->wolopts = WAKE_MAGIC;
-		else
-			wol->wolopts = 0;
-	}
-	memset(&wol->sopass, 0, sizeof(wol->sopass));
-}
-
-static int bnx2x_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	if (wol->wolopts & ~WAKE_MAGIC)
-		return -EINVAL;
-
-	if (wol->wolopts & WAKE_MAGIC) {
-		if (bp->flags & NO_WOL_FLAG)
-			return -EINVAL;
-
-		bp->wol = 1;
-	} else
-		bp->wol = 0;
-
-	return 0;
-}
-
-static u32 bnx2x_get_msglevel(struct net_device *dev)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	return bp->msg_enable;
-}
-
-static void bnx2x_set_msglevel(struct net_device *dev, u32 level)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	if (capable(CAP_NET_ADMIN)) {
-		/* dump MCP trace */
-		if (level & BNX2X_MSG_MCP)
-			bnx2x_fw_dump_lvl(bp, KERN_INFO);
-		bp->msg_enable = level;
-	}
-}
-
-static int bnx2x_nway_reset(struct net_device *dev)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	if (!bp->port.pmf)
-		return 0;
-
-	if (netif_running(dev)) {
-		bnx2x_stats_handle(bp, STATS_EVENT_STOP);
-		bnx2x_link_set(bp);
-	}
-
-	return 0;
-}
-
-static u32 bnx2x_get_link(struct net_device *dev)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	if (bp->flags & MF_FUNC_DIS || (bp->state != BNX2X_STATE_OPEN))
-		return 0;
-
-	return bp->link_vars.link_up;
-}
-
-static int bnx2x_get_eeprom_len(struct net_device *dev)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	return bp->common.flash_size;
-}
-
-static int bnx2x_acquire_nvram_lock(struct bnx2x *bp)
-{
-	int port = BP_PORT(bp);
-	int count, i;
-	u32 val = 0;
-
-	/* adjust timeout for emulation/FPGA */
-	count = BNX2X_NVRAM_TIMEOUT_COUNT;
-	if (CHIP_REV_IS_SLOW(bp))
-		count *= 100;
-
-	/* request access to nvram interface */
-	REG_WR(bp, MCP_REG_MCPR_NVM_SW_ARB,
-	       (MCPR_NVM_SW_ARB_ARB_REQ_SET1 << port));
-
-	for (i = 0; i < count*10; i++) {
-		val = REG_RD(bp, MCP_REG_MCPR_NVM_SW_ARB);
-		if (val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port))
-			break;
-
-		udelay(5);
-	}
-
-	if (!(val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port))) {
-		DP(BNX2X_MSG_NVM, "cannot get access to nvram interface\n");
-		return -EBUSY;
-	}
-
-	return 0;
-}
-
-static int bnx2x_release_nvram_lock(struct bnx2x *bp)
-{
-	int port = BP_PORT(bp);
-	int count, i;
-	u32 val = 0;
-
-	/* adjust timeout for emulation/FPGA */
-	count = BNX2X_NVRAM_TIMEOUT_COUNT;
-	if (CHIP_REV_IS_SLOW(bp))
-		count *= 100;
-
-	/* relinquish nvram interface */
-	REG_WR(bp, MCP_REG_MCPR_NVM_SW_ARB,
-	       (MCPR_NVM_SW_ARB_ARB_REQ_CLR1 << port));
-
-	for (i = 0; i < count*10; i++) {
-		val = REG_RD(bp, MCP_REG_MCPR_NVM_SW_ARB);
-		if (!(val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port)))
-			break;
-
-		udelay(5);
-	}
-
-	if (val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port)) {
-		DP(BNX2X_MSG_NVM, "cannot free access to nvram interface\n");
-		return -EBUSY;
-	}
-
-	return 0;
-}
-
-static void bnx2x_enable_nvram_access(struct bnx2x *bp)
-{
-	u32 val;
-
-	val = REG_RD(bp, MCP_REG_MCPR_NVM_ACCESS_ENABLE);
-
-	/* enable both bits, even on read */
-	REG_WR(bp, MCP_REG_MCPR_NVM_ACCESS_ENABLE,
-	       (val | MCPR_NVM_ACCESS_ENABLE_EN |
-		      MCPR_NVM_ACCESS_ENABLE_WR_EN));
-}
-
-static void bnx2x_disable_nvram_access(struct bnx2x *bp)
-{
-	u32 val;
-
-	val = REG_RD(bp, MCP_REG_MCPR_NVM_ACCESS_ENABLE);
-
-	/* disable both bits, even after read */
-	REG_WR(bp, MCP_REG_MCPR_NVM_ACCESS_ENABLE,
-	       (val & ~(MCPR_NVM_ACCESS_ENABLE_EN |
-			MCPR_NVM_ACCESS_ENABLE_WR_EN)));
-}
-
-static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, __be32 *ret_val,
-				  u32 cmd_flags)
-{
-	int count, i, rc;
-	u32 val;
-
-	/* build the command word */
-	cmd_flags |= MCPR_NVM_COMMAND_DOIT;
-
-	/* need to clear DONE bit separately */
-	REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DONE);
-
-	/* address of the NVRAM to read from */
-	REG_WR(bp, MCP_REG_MCPR_NVM_ADDR,
-	       (offset & MCPR_NVM_ADDR_NVM_ADDR_VALUE));
-
-	/* issue a read command */
-	REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, cmd_flags);
-
-	/* adjust timeout for emulation/FPGA */
-	count = BNX2X_NVRAM_TIMEOUT_COUNT;
-	if (CHIP_REV_IS_SLOW(bp))
-		count *= 100;
-
-	/* wait for completion */
-	*ret_val = 0;
-	rc = -EBUSY;
-	for (i = 0; i < count; i++) {
-		udelay(5);
-		val = REG_RD(bp, MCP_REG_MCPR_NVM_COMMAND);
-
-		if (val & MCPR_NVM_COMMAND_DONE) {
-			val = REG_RD(bp, MCP_REG_MCPR_NVM_READ);
-			/* we read nvram data in cpu order
-			 * but ethtool sees it as an array of bytes
-			 * converting to big-endian will do the work */
-			*ret_val = cpu_to_be32(val);
-			rc = 0;
-			break;
-		}
-	}
-
-	return rc;
-}
-
-static int bnx2x_nvram_read(struct bnx2x *bp, u32 offset, u8 *ret_buf,
-			    int buf_size)
-{
-	int rc;
-	u32 cmd_flags;
-	__be32 val;
-
-	if ((offset & 0x03) || (buf_size & 0x03) || (buf_size == 0)) {
-		DP(BNX2X_MSG_NVM,
-		   "Invalid parameter: offset 0x%x  buf_size 0x%x\n",
-		   offset, buf_size);
-		return -EINVAL;
-	}
-
-	if (offset + buf_size > bp->common.flash_size) {
-		DP(BNX2X_MSG_NVM, "Invalid parameter: offset (0x%x) +"
-				  " buf_size (0x%x) > flash_size (0x%x)\n",
-		   offset, buf_size, bp->common.flash_size);
-		return -EINVAL;
-	}
-
-	/* request access to nvram interface */
-	rc = bnx2x_acquire_nvram_lock(bp);
-	if (rc)
-		return rc;
-
-	/* enable access to nvram interface */
-	bnx2x_enable_nvram_access(bp);
-
-	/* read the first word(s) */
-	cmd_flags = MCPR_NVM_COMMAND_FIRST;
-	while ((buf_size > sizeof(u32)) && (rc == 0)) {
-		rc = bnx2x_nvram_read_dword(bp, offset, &val, cmd_flags);
-		memcpy(ret_buf, &val, 4);
-
-		/* advance to the next dword */
-		offset += sizeof(u32);
-		ret_buf += sizeof(u32);
-		buf_size -= sizeof(u32);
-		cmd_flags = 0;
-	}
-
-	if (rc == 0) {
-		cmd_flags |= MCPR_NVM_COMMAND_LAST;
-		rc = bnx2x_nvram_read_dword(bp, offset, &val, cmd_flags);
-		memcpy(ret_buf, &val, 4);
-	}
-
-	/* disable access to nvram interface */
-	bnx2x_disable_nvram_access(bp);
-	bnx2x_release_nvram_lock(bp);
-
-	return rc;
-}
-
-static int bnx2x_get_eeprom(struct net_device *dev,
-			    struct ethtool_eeprom *eeprom, u8 *eebuf)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	int rc;
-
-	if (!netif_running(dev))
-		return -EAGAIN;
-
-	DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n"
-	   DP_LEVEL "  magic 0x%x  offset 0x%x (%d)  len 0x%x (%d)\n",
-	   eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset,
-	   eeprom->len, eeprom->len);
-
-	/* parameters already validated in ethtool_get_eeprom */
-
-	rc = bnx2x_nvram_read(bp, eeprom->offset, eebuf, eeprom->len);
-
-	return rc;
-}
-
-static int bnx2x_nvram_write_dword(struct bnx2x *bp, u32 offset, u32 val,
-				   u32 cmd_flags)
-{
-	int count, i, rc;
-
-	/* build the command word */
-	cmd_flags |= MCPR_NVM_COMMAND_DOIT | MCPR_NVM_COMMAND_WR;
-
-	/* need to clear DONE bit separately */
-	REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DONE);
-
-	/* write the data */
-	REG_WR(bp, MCP_REG_MCPR_NVM_WRITE, val);
-
-	/* address of the NVRAM to write to */
-	REG_WR(bp, MCP_REG_MCPR_NVM_ADDR,
-	       (offset & MCPR_NVM_ADDR_NVM_ADDR_VALUE));
-
-	/* issue the write command */
-	REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, cmd_flags);
-
-	/* adjust timeout for emulation/FPGA */
-	count = BNX2X_NVRAM_TIMEOUT_COUNT;
-	if (CHIP_REV_IS_SLOW(bp))
-		count *= 100;
-
-	/* wait for completion */
-	rc = -EBUSY;
-	for (i = 0; i < count; i++) {
-		udelay(5);
-		val = REG_RD(bp, MCP_REG_MCPR_NVM_COMMAND);
-		if (val & MCPR_NVM_COMMAND_DONE) {
-			rc = 0;
-			break;
-		}
-	}
-
-	return rc;
-}
-
-#define BYTE_OFFSET(offset)		(8 * (offset & 0x03))
-
-static int bnx2x_nvram_write1(struct bnx2x *bp, u32 offset, u8 *data_buf,
-			      int buf_size)
-{
-	int rc;
-	u32 cmd_flags;
-	u32 align_offset;
-	__be32 val;
-
-	if (offset + buf_size > bp->common.flash_size) {
-		DP(BNX2X_MSG_NVM, "Invalid parameter: offset (0x%x) +"
-				  " buf_size (0x%x) > flash_size (0x%x)\n",
-		   offset, buf_size, bp->common.flash_size);
-		return -EINVAL;
-	}
-
-	/* request access to nvram interface */
-	rc = bnx2x_acquire_nvram_lock(bp);
-	if (rc)
-		return rc;
-
-	/* enable access to nvram interface */
-	bnx2x_enable_nvram_access(bp);
-
-	cmd_flags = (MCPR_NVM_COMMAND_FIRST | MCPR_NVM_COMMAND_LAST);
-	align_offset = (offset & ~0x03);
-	rc = bnx2x_nvram_read_dword(bp, align_offset, &val, cmd_flags);
-
-	if (rc == 0) {
-		val &= ~(0xff << BYTE_OFFSET(offset));
-		val |= (*data_buf << BYTE_OFFSET(offset));
-
-		/* nvram data is returned as an array of bytes
-		 * convert it back to cpu order */
-		val = be32_to_cpu(val);
-
-		rc = bnx2x_nvram_write_dword(bp, align_offset, val,
-					     cmd_flags);
-	}
-
-	/* disable access to nvram interface */
-	bnx2x_disable_nvram_access(bp);
-	bnx2x_release_nvram_lock(bp);
-
-	return rc;
-}
-
-static int bnx2x_nvram_write(struct bnx2x *bp, u32 offset, u8 *data_buf,
-			     int buf_size)
-{
-	int rc;
-	u32 cmd_flags;
-	u32 val;
-	u32 written_so_far;
-
-	if (buf_size == 1)	/* ethtool */
-		return bnx2x_nvram_write1(bp, offset, data_buf, buf_size);
-
-	if ((offset & 0x03) || (buf_size & 0x03) || (buf_size == 0)) {
-		DP(BNX2X_MSG_NVM,
-		   "Invalid parameter: offset 0x%x  buf_size 0x%x\n",
-		   offset, buf_size);
-		return -EINVAL;
-	}
-
-	if (offset + buf_size > bp->common.flash_size) {
-		DP(BNX2X_MSG_NVM, "Invalid parameter: offset (0x%x) +"
-				  " buf_size (0x%x) > flash_size (0x%x)\n",
-		   offset, buf_size, bp->common.flash_size);
-		return -EINVAL;
-	}
-
-	/* request access to nvram interface */
-	rc = bnx2x_acquire_nvram_lock(bp);
-	if (rc)
-		return rc;
-
-	/* enable access to nvram interface */
-	bnx2x_enable_nvram_access(bp);
-
-	written_so_far = 0;
-	cmd_flags = MCPR_NVM_COMMAND_FIRST;
-	while ((written_so_far < buf_size) && (rc == 0)) {
-		if (written_so_far == (buf_size - sizeof(u32)))
-			cmd_flags |= MCPR_NVM_COMMAND_LAST;
-		else if (((offset + 4) % BNX2X_NVRAM_PAGE_SIZE) == 0)
-			cmd_flags |= MCPR_NVM_COMMAND_LAST;
-		else if ((offset % BNX2X_NVRAM_PAGE_SIZE) == 0)
-			cmd_flags |= MCPR_NVM_COMMAND_FIRST;
-
-		memcpy(&val, data_buf, 4);
-
-		rc = bnx2x_nvram_write_dword(bp, offset, val, cmd_flags);
-
-		/* advance to the next dword */
-		offset += sizeof(u32);
-		data_buf += sizeof(u32);
-		written_so_far += sizeof(u32);
-		cmd_flags = 0;
-	}
-
-	/* disable access to nvram interface */
-	bnx2x_disable_nvram_access(bp);
-	bnx2x_release_nvram_lock(bp);
-
-	return rc;
-}
-
-static int bnx2x_set_eeprom(struct net_device *dev,
-			    struct ethtool_eeprom *eeprom, u8 *eebuf)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	int port = BP_PORT(bp);
-	int rc = 0;
-	u32 ext_phy_config;
-	if (!netif_running(dev))
-		return -EAGAIN;
-
-	DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n"
-	   DP_LEVEL "  magic 0x%x  offset 0x%x (%d)  len 0x%x (%d)\n",
-	   eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset,
-	   eeprom->len, eeprom->len);
-
-	/* parameters already validated in ethtool_set_eeprom */
-
-	/* PHY eeprom can be accessed only by the PMF */
-	if ((eeprom->magic >= 0x50485900) && (eeprom->magic <= 0x504859FF) &&
-	    !bp->port.pmf)
-		return -EINVAL;
-
-	ext_phy_config =
-		SHMEM_RD(bp,
-			 dev_info.port_hw_config[port].external_phy_config);
-
-	if (eeprom->magic == 0x50485950) {
-		/* 'PHYP' (0x50485950): prepare phy for FW upgrade */
-		bnx2x_stats_handle(bp, STATS_EVENT_STOP);
-
-		bnx2x_acquire_phy_lock(bp);
-		rc |= bnx2x_link_reset(&bp->link_params,
-				       &bp->link_vars, 0);
-		if (XGXS_EXT_PHY_TYPE(ext_phy_config) ==
-					PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101)
-			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
-				       MISC_REGISTERS_GPIO_HIGH, port);
-		bnx2x_release_phy_lock(bp);
-		bnx2x_link_report(bp);
-
-	} else if (eeprom->magic == 0x50485952) {
-		/* 'PHYR' (0x50485952): re-init link after FW upgrade */
-		if (bp->state == BNX2X_STATE_OPEN) {
-			bnx2x_acquire_phy_lock(bp);
-			rc |= bnx2x_link_reset(&bp->link_params,
-					       &bp->link_vars, 1);
-
-			rc |= bnx2x_phy_init(&bp->link_params,
-					     &bp->link_vars);
-			bnx2x_release_phy_lock(bp);
-			bnx2x_calc_fc_adv(bp);
-		}
-	} else if (eeprom->magic == 0x53985943) {
-		/* 'PHYC' (0x53985943): PHY FW upgrade completed */
-		if (XGXS_EXT_PHY_TYPE(ext_phy_config) ==
-				       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) {
-
-			/* DSP Remove Download Mode */
-			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
-				       MISC_REGISTERS_GPIO_LOW, port);
-
-			bnx2x_acquire_phy_lock(bp);
-
-			bnx2x_sfx7101_sp_sw_reset(bp,
-						&bp->link_params.phy[EXT_PHY1]);
-
-			/* wait 0.5 sec to allow it to run */
-			msleep(500);
-			bnx2x_ext_phy_hw_reset(bp, port);
-			msleep(500);
-			bnx2x_release_phy_lock(bp);
-		}
-	} else
-		rc = bnx2x_nvram_write(bp, eeprom->offset, eebuf, eeprom->len);
-
-	return rc;
-}
-
-static int bnx2x_get_coalesce(struct net_device *dev,
-			      struct ethtool_coalesce *coal)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	memset(coal, 0, sizeof(struct ethtool_coalesce));
-
-	coal->rx_coalesce_usecs = bp->rx_ticks;
-	coal->tx_coalesce_usecs = bp->tx_ticks;
-
-	return 0;
-}
-
-static int bnx2x_set_coalesce(struct net_device *dev,
-			      struct ethtool_coalesce *coal)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	bp->rx_ticks = (u16)coal->rx_coalesce_usecs;
-	if (bp->rx_ticks > BNX2X_MAX_COALESCE_TOUT)
-		bp->rx_ticks = BNX2X_MAX_COALESCE_TOUT;
-
-	bp->tx_ticks = (u16)coal->tx_coalesce_usecs;
-	if (bp->tx_ticks > BNX2X_MAX_COALESCE_TOUT)
-		bp->tx_ticks = BNX2X_MAX_COALESCE_TOUT;
-
-	if (netif_running(dev))
-		bnx2x_update_coalesce(bp);
-
-	return 0;
-}
-
-static void bnx2x_get_ringparam(struct net_device *dev,
-				struct ethtool_ringparam *ering)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	ering->rx_max_pending = MAX_RX_AVAIL;
-	ering->rx_mini_max_pending = 0;
-	ering->rx_jumbo_max_pending = 0;
-
-	if (bp->rx_ring_size)
-		ering->rx_pending = bp->rx_ring_size;
-	else
-		ering->rx_pending = MAX_RX_AVAIL;
-
-	ering->rx_mini_pending = 0;
-	ering->rx_jumbo_pending = 0;
-
-	ering->tx_max_pending = MAX_TX_AVAIL;
-	ering->tx_pending = bp->tx_ring_size;
-}
-
-static int bnx2x_set_ringparam(struct net_device *dev,
-			       struct ethtool_ringparam *ering)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
-		printk(KERN_ERR "Handling parity error recovery. Try again later\n");
-		return -EAGAIN;
-	}
-
-	if ((ering->rx_pending > MAX_RX_AVAIL) ||
-	    (ering->rx_pending < (bp->disable_tpa ? MIN_RX_SIZE_NONTPA :
-						    MIN_RX_SIZE_TPA)) ||
-	    (ering->tx_pending > MAX_TX_AVAIL) ||
-	    (ering->tx_pending <= MAX_SKB_FRAGS + 4))
-		return -EINVAL;
-
-	bp->rx_ring_size = ering->rx_pending;
-	bp->tx_ring_size = ering->tx_pending;
-
-	return bnx2x_reload_if_running(dev);
-}
-
-static void bnx2x_get_pauseparam(struct net_device *dev,
-				 struct ethtool_pauseparam *epause)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	int cfg_idx = bnx2x_get_link_cfg_idx(bp);
-	epause->autoneg = (bp->link_params.req_flow_ctrl[cfg_idx] ==
-			   BNX2X_FLOW_CTRL_AUTO);
-
-	epause->rx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) ==
-			    BNX2X_FLOW_CTRL_RX);
-	epause->tx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX) ==
-			    BNX2X_FLOW_CTRL_TX);
-
-	DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n"
-	   DP_LEVEL "  autoneg %d  rx_pause %d  tx_pause %d\n",
-	   epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause);
-}
-
-static int bnx2x_set_pauseparam(struct net_device *dev,
-				struct ethtool_pauseparam *epause)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	u32 cfg_idx = bnx2x_get_link_cfg_idx(bp);
-	if (IS_MF(bp))
-		return 0;
-
-	DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n"
-	   DP_LEVEL "  autoneg %d  rx_pause %d  tx_pause %d\n",
-	   epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause);
-
-	bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_AUTO;
-
-	if (epause->rx_pause)
-		bp->link_params.req_flow_ctrl[cfg_idx] |= BNX2X_FLOW_CTRL_RX;
-
-	if (epause->tx_pause)
-		bp->link_params.req_flow_ctrl[cfg_idx] |= BNX2X_FLOW_CTRL_TX;
-
-	if (bp->link_params.req_flow_ctrl[cfg_idx] == BNX2X_FLOW_CTRL_AUTO)
-		bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_NONE;
-
-	if (epause->autoneg) {
-		if (!(bp->port.supported[cfg_idx] & SUPPORTED_Autoneg)) {
-			DP(NETIF_MSG_LINK, "autoneg not supported\n");
-			return -EINVAL;
-		}
-
-		if (bp->link_params.req_line_speed[cfg_idx] == SPEED_AUTO_NEG) {
-			bp->link_params.req_flow_ctrl[cfg_idx] =
-				BNX2X_FLOW_CTRL_AUTO;
-		}
-	}
-
-	DP(NETIF_MSG_LINK,
-	   "req_flow_ctrl 0x%x\n", bp->link_params.req_flow_ctrl[cfg_idx]);
-
-	if (netif_running(dev)) {
-		bnx2x_stats_handle(bp, STATS_EVENT_STOP);
-		bnx2x_link_set(bp);
-	}
-
-	return 0;
-}
-
-static const struct {
-	char string[ETH_GSTRING_LEN];
-} bnx2x_tests_str_arr[BNX2X_NUM_TESTS] = {
-	{ "register_test (offline)" },
-	{ "memory_test (offline)" },
-	{ "loopback_test (offline)" },
-	{ "nvram_test (online)" },
-	{ "interrupt_test (online)" },
-	{ "link_test (online)" },
-	{ "idle check (online)" }
-};
-
-enum {
-	BNX2X_CHIP_E1_OFST = 0,
-	BNX2X_CHIP_E1H_OFST,
-	BNX2X_CHIP_E2_OFST,
-	BNX2X_CHIP_E3_OFST,
-	BNX2X_CHIP_E3B0_OFST,
-	BNX2X_CHIP_MAX_OFST
-};
-
-#define BNX2X_CHIP_MASK_E1	(1 << BNX2X_CHIP_E1_OFST)
-#define BNX2X_CHIP_MASK_E1H	(1 << BNX2X_CHIP_E1H_OFST)
-#define BNX2X_CHIP_MASK_E2	(1 << BNX2X_CHIP_E2_OFST)
-#define BNX2X_CHIP_MASK_E3	(1 << BNX2X_CHIP_E3_OFST)
-#define BNX2X_CHIP_MASK_E3B0	(1 << BNX2X_CHIP_E3B0_OFST)
-
-#define BNX2X_CHIP_MASK_ALL	((1 << BNX2X_CHIP_MAX_OFST) - 1)
-#define BNX2X_CHIP_MASK_E1X	(BNX2X_CHIP_MASK_E1 | BNX2X_CHIP_MASK_E1H)
-
-static int bnx2x_test_registers(struct bnx2x *bp)
-{
-	int idx, i, rc = -ENODEV;
-	u32 wr_val = 0, hw;
-	int port = BP_PORT(bp);
-	static const struct {
-		u32 hw;
-		u32 offset0;
-		u32 offset1;
-		u32 mask;
-	} reg_tbl[] = {
-/* 0 */		{ BNX2X_CHIP_MASK_ALL,
-			BRB1_REG_PAUSE_LOW_THRESHOLD_0,	4, 0x000003ff },
-		{ BNX2X_CHIP_MASK_ALL,
-			DORQ_REG_DB_ADDR0,		4, 0xffffffff },
-		{ BNX2X_CHIP_MASK_E1X,
-			HC_REG_AGG_INT_0,		4, 0x000003ff },
-		{ BNX2X_CHIP_MASK_ALL,
-			PBF_REG_MAC_IF0_ENABLE,		4, 0x00000001 },
-		{ BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2 | BNX2X_CHIP_MASK_E3,
-			PBF_REG_P0_INIT_CRD,		4, 0x000007ff },
-		{ BNX2X_CHIP_MASK_E3B0,
-			PBF_REG_INIT_CRD_Q0,		4, 0x000007ff },
-		{ BNX2X_CHIP_MASK_ALL,
-			PRS_REG_CID_PORT_0,		4, 0x00ffffff },
-		{ BNX2X_CHIP_MASK_ALL,
-			PXP2_REG_PSWRQ_CDU0_L2P,	4, 0x000fffff },
-		{ BNX2X_CHIP_MASK_ALL,
-			PXP2_REG_RQ_CDU0_EFIRST_MEM_ADDR, 8, 0x0003ffff },
-		{ BNX2X_CHIP_MASK_ALL,
-			PXP2_REG_PSWRQ_TM0_L2P,		4, 0x000fffff },
-/* 10 */	{ BNX2X_CHIP_MASK_ALL,
-			PXP2_REG_RQ_USDM0_EFIRST_MEM_ADDR, 8, 0x0003ffff },
-		{ BNX2X_CHIP_MASK_ALL,
-			PXP2_REG_PSWRQ_TSDM0_L2P,	4, 0x000fffff },
-		{ BNX2X_CHIP_MASK_ALL,
-			QM_REG_CONNNUM_0,		4, 0x000fffff },
-		{ BNX2X_CHIP_MASK_ALL,
-			TM_REG_LIN0_MAX_ACTIVE_CID,	4, 0x0003ffff },
-		{ BNX2X_CHIP_MASK_ALL,
-			SRC_REG_KEYRSS0_0,		40, 0xffffffff },
-		{ BNX2X_CHIP_MASK_ALL,
-			SRC_REG_KEYRSS0_7,		40, 0xffffffff },
-		{ BNX2X_CHIP_MASK_ALL,
-			XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 4, 0x00000001 },
-		{ BNX2X_CHIP_MASK_ALL,
-			XCM_REG_WU_DA_CNT_CMD00,	4, 0x00000003 },
-		{ BNX2X_CHIP_MASK_ALL,
-			XCM_REG_GLB_DEL_ACK_MAX_CNT_0,	4, 0x000000ff },
-		{ BNX2X_CHIP_MASK_ALL,
-			NIG_REG_LLH0_T_BIT,		4, 0x00000001 },
-/* 20 */	{ BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
-			NIG_REG_EMAC0_IN_EN,		4, 0x00000001 },
-		{ BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
-			NIG_REG_BMAC0_IN_EN,		4, 0x00000001 },
-		{ BNX2X_CHIP_MASK_ALL,
-			NIG_REG_XCM0_OUT_EN,		4, 0x00000001 },
-		{ BNX2X_CHIP_MASK_ALL,
-			NIG_REG_BRB0_OUT_EN,		4, 0x00000001 },
-		{ BNX2X_CHIP_MASK_ALL,
-			NIG_REG_LLH0_XCM_MASK,		4, 0x00000007 },
-		{ BNX2X_CHIP_MASK_ALL,
-			NIG_REG_LLH0_ACPI_PAT_6_LEN,	68, 0x000000ff },
-		{ BNX2X_CHIP_MASK_ALL,
-			NIG_REG_LLH0_ACPI_PAT_0_CRC,	68, 0xffffffff },
-		{ BNX2X_CHIP_MASK_ALL,
-			NIG_REG_LLH0_DEST_MAC_0_0,	160, 0xffffffff },
-		{ BNX2X_CHIP_MASK_ALL,
-			NIG_REG_LLH0_DEST_IP_0_1,	160, 0xffffffff },
-		{ BNX2X_CHIP_MASK_ALL,
-			NIG_REG_LLH0_IPV4_IPV6_0,	160, 0x00000001 },
-/* 30 */	{ BNX2X_CHIP_MASK_ALL,
-			NIG_REG_LLH0_DEST_UDP_0,	160, 0x0000ffff },
-		{ BNX2X_CHIP_MASK_ALL,
-			NIG_REG_LLH0_DEST_TCP_0,	160, 0x0000ffff },
-		{ BNX2X_CHIP_MASK_ALL,
-			NIG_REG_LLH0_VLAN_ID_0,	160, 0x00000fff },
-		{ BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
-			NIG_REG_XGXS_SERDES0_MODE_SEL,	4, 0x00000001 },
-		{ BNX2X_CHIP_MASK_ALL,
-			NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0, 4, 0x00000001},
-		{ BNX2X_CHIP_MASK_ALL,
-			NIG_REG_STATUS_INTERRUPT_PORT0,	4, 0x07ffffff },
-		{ BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
-			NIG_REG_XGXS0_CTRL_EXTREMOTEMDIOST, 24, 0x00000001 },
-		{ BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
-			NIG_REG_SERDES0_CTRL_PHY_ADDR,	16, 0x0000001f },
-
-		{ BNX2X_CHIP_MASK_ALL, 0xffffffff, 0, 0x00000000 }
-	};
-
-	if (!netif_running(bp->dev))
-		return rc;
-
-	if (CHIP_IS_E1(bp))
-		hw = BNX2X_CHIP_MASK_E1;
-	else if (CHIP_IS_E1H(bp))
-		hw = BNX2X_CHIP_MASK_E1H;
-	else if (CHIP_IS_E2(bp))
-		hw = BNX2X_CHIP_MASK_E2;
-	else if (CHIP_IS_E3B0(bp))
-		hw = BNX2X_CHIP_MASK_E3B0;
-	else /* e3 A0 */
-		hw = BNX2X_CHIP_MASK_E3;
-
-	/* Repeat the test twice:
-	   First by writing 0x00000000, second by writing 0xffffffff */
-	for (idx = 0; idx < 2; idx++) {
-
-		switch (idx) {
-		case 0:
-			wr_val = 0;
-			break;
-		case 1:
-			wr_val = 0xffffffff;
-			break;
-		}
-
-		for (i = 0; reg_tbl[i].offset0 != 0xffffffff; i++) {
-			u32 offset, mask, save_val, val;
-			if (!(hw & reg_tbl[i].hw))
-				continue;
-
-			offset = reg_tbl[i].offset0 + port*reg_tbl[i].offset1;
-			mask = reg_tbl[i].mask;
-
-			save_val = REG_RD(bp, offset);
-
-			REG_WR(bp, offset, wr_val & mask);
-
-			val = REG_RD(bp, offset);
-
-			/* Restore the original register's value */
-			REG_WR(bp, offset, save_val);
-
-			/* verify value is as expected */
-			if ((val & mask) != (wr_val & mask)) {
-				DP(NETIF_MSG_HW,
-				   "offset 0x%x: val 0x%x != 0x%x mask 0x%x\n",
-				   offset, val, wr_val, mask);
-				goto test_reg_exit;
-			}
-		}
-	}
-
-	rc = 0;
-
-test_reg_exit:
-	return rc;
-}
-
-static int bnx2x_test_memory(struct bnx2x *bp)
-{
-	int i, j, rc = -ENODEV;
-	u32 val, index;
-	static const struct {
-		u32 offset;
-		int size;
-	} mem_tbl[] = {
-		{ CCM_REG_XX_DESCR_TABLE,   CCM_REG_XX_DESCR_TABLE_SIZE },
-		{ CFC_REG_ACTIVITY_COUNTER, CFC_REG_ACTIVITY_COUNTER_SIZE },
-		{ CFC_REG_LINK_LIST,        CFC_REG_LINK_LIST_SIZE },
-		{ DMAE_REG_CMD_MEM,         DMAE_REG_CMD_MEM_SIZE },
-		{ TCM_REG_XX_DESCR_TABLE,   TCM_REG_XX_DESCR_TABLE_SIZE },
-		{ UCM_REG_XX_DESCR_TABLE,   UCM_REG_XX_DESCR_TABLE_SIZE },
-		{ XCM_REG_XX_DESCR_TABLE,   XCM_REG_XX_DESCR_TABLE_SIZE },
-
-		{ 0xffffffff, 0 }
-	};
-
-	static const struct {
-		char *name;
-		u32 offset;
-		u32 hw_mask[BNX2X_CHIP_MAX_OFST];
-	} prty_tbl[] = {
-		{ "CCM_PRTY_STS",  CCM_REG_CCM_PRTY_STS,
-			{0x3ffc0, 0,   0, 0} },
-		{ "CFC_PRTY_STS",  CFC_REG_CFC_PRTY_STS,
-			{0x2,     0x2, 0, 0} },
-		{ "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS,
-			{0,       0,   0, 0} },
-		{ "TCM_PRTY_STS",  TCM_REG_TCM_PRTY_STS,
-			{0x3ffc0, 0,   0, 0} },
-		{ "UCM_PRTY_STS",  UCM_REG_UCM_PRTY_STS,
-			{0x3ffc0, 0,   0, 0} },
-		{ "XCM_PRTY_STS",  XCM_REG_XCM_PRTY_STS,
-			{0x3ffc1, 0,   0, 0} },
-
-		{ NULL, 0xffffffff, {0, 0, 0, 0} }
-	};
-
-	if (!netif_running(bp->dev))
-		return rc;
-
-	if (CHIP_IS_E1(bp))
-		index = BNX2X_CHIP_E1_OFST;
-	else if (CHIP_IS_E1H(bp))
-		index = BNX2X_CHIP_E1H_OFST;
-	else if (CHIP_IS_E2(bp))
-		index = BNX2X_CHIP_E2_OFST;
-	else /* e3 */
-		index = BNX2X_CHIP_E3_OFST;
-
-	/* pre-Check the parity status */
-	for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) {
-		val = REG_RD(bp, prty_tbl[i].offset);
-		if (val & ~(prty_tbl[i].hw_mask[index])) {
-			DP(NETIF_MSG_HW,
-			   "%s is 0x%x\n", prty_tbl[i].name, val);
-			goto test_mem_exit;
-		}
-	}
-
-	/* Go through all the memories */
-	for (i = 0; mem_tbl[i].offset != 0xffffffff; i++)
-		for (j = 0; j < mem_tbl[i].size; j++)
-			REG_RD(bp, mem_tbl[i].offset + j*4);
-
-	/* Check the parity status */
-	for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) {
-		val = REG_RD(bp, prty_tbl[i].offset);
-		if (val & ~(prty_tbl[i].hw_mask[index])) {
-			DP(NETIF_MSG_HW,
-			   "%s is 0x%x\n", prty_tbl[i].name, val);
-			goto test_mem_exit;
-		}
-	}
-
-	rc = 0;
-
-test_mem_exit:
-	return rc;
-}
-
-static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up, u8 is_serdes)
-{
-	int cnt = 1400;
-
-	if (link_up) {
-		while (bnx2x_link_test(bp, is_serdes) && cnt--)
-			msleep(20);
-
-		if (cnt <= 0 && bnx2x_link_test(bp, is_serdes))
-			DP(NETIF_MSG_LINK, "Timeout waiting for link up\n");
-	}
-}
-
-static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
-{
-	unsigned int pkt_size, num_pkts, i;
-	struct sk_buff *skb;
-	unsigned char *packet;
-	struct bnx2x_fastpath *fp_rx = &bp->fp[0];
-	struct bnx2x_fastpath *fp_tx = &bp->fp[0];
-	struct bnx2x_fp_txdata *txdata = &fp_tx->txdata[0];
-	u16 tx_start_idx, tx_idx;
-	u16 rx_start_idx, rx_idx;
-	u16 pkt_prod, bd_prod, rx_comp_cons;
-	struct sw_tx_bd *tx_buf;
-	struct eth_tx_start_bd *tx_start_bd;
-	struct eth_tx_parse_bd_e1x  *pbd_e1x = NULL;
-	struct eth_tx_parse_bd_e2  *pbd_e2 = NULL;
-	dma_addr_t mapping;
-	union eth_rx_cqe *cqe;
-	u8 cqe_fp_flags, cqe_fp_type;
-	struct sw_rx_bd *rx_buf;
-	u16 len;
-	int rc = -ENODEV;
-
-	/* check the loopback mode */
-	switch (loopback_mode) {
-	case BNX2X_PHY_LOOPBACK:
-		if (bp->link_params.loopback_mode != LOOPBACK_XGXS)
-			return -EINVAL;
-		break;
-	case BNX2X_MAC_LOOPBACK:
-		bp->link_params.loopback_mode = CHIP_IS_E3(bp) ?
-						LOOPBACK_XMAC : LOOPBACK_BMAC;
-		bnx2x_phy_init(&bp->link_params, &bp->link_vars);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* 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, fp_rx->rx_buf_size);
-	if (!skb) {
-		rc = -ENOMEM;
-		goto test_loopback_exit;
-	}
-	packet = skb_put(skb, pkt_size);
-	memcpy(packet, bp->dev->dev_addr, ETH_ALEN);
-	memset(packet + ETH_ALEN, 0, ETH_ALEN);
-	memset(packet + 2*ETH_ALEN, 0x77, (ETH_HLEN - 2*ETH_ALEN));
-	for (i = ETH_HLEN; i < pkt_size; i++)
-		packet[i] = (unsigned char) (i & 0xff);
-	mapping = dma_map_single(&bp->pdev->dev, skb->data,
-				 skb_headlen(skb), DMA_TO_DEVICE);
-	if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
-		rc = -ENOMEM;
-		dev_kfree_skb(skb);
-		BNX2X_ERR("Unable to map SKB\n");
-		goto test_loopback_exit;
-	}
-
-	/* send the loopback packet */
-	num_pkts = 0;
-	tx_start_idx = le16_to_cpu(*txdata->tx_cons_sb);
-	rx_start_idx = le16_to_cpu(*fp_rx->rx_cons_sb);
-
-	pkt_prod = txdata->tx_pkt_prod++;
-	tx_buf = &txdata->tx_buf_ring[TX_BD(pkt_prod)];
-	tx_buf->first_bd = txdata->tx_bd_prod;
-	tx_buf->skb = skb;
-	tx_buf->flags = 0;
-
-	bd_prod = TX_BD(txdata->tx_bd_prod);
-	tx_start_bd = &txdata->tx_desc_ring[bd_prod].start_bd;
-	tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
-	tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
-	tx_start_bd->nbd = cpu_to_le16(2); /* start + pbd */
-	tx_start_bd->nbytes = cpu_to_le16(skb_headlen(skb));
-	tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod);
-	tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD;
-	SET_FLAG(tx_start_bd->general_data,
-		 ETH_TX_START_BD_ETH_ADDR_TYPE,
-		 UNICAST_ADDRESS);
-	SET_FLAG(tx_start_bd->general_data,
-		 ETH_TX_START_BD_HDR_NBDS,
-		 1);
-
-	/* turn on parsing and get a BD */
-	bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
-
-	pbd_e1x = &txdata->tx_desc_ring[bd_prod].parse_bd_e1x;
-	pbd_e2 = &txdata->tx_desc_ring[bd_prod].parse_bd_e2;
-
-	memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
-	memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
-
-	wmb();
-
-	txdata->tx_db.data.prod += 2;
-	barrier();
-	DOORBELL(bp, txdata->cid, txdata->tx_db.raw);
-
-	mmiowb();
-	barrier();
-
-	num_pkts++;
-	txdata->tx_bd_prod += 2; /* start + pbd */
-
-	udelay(100);
-
-	tx_idx = le16_to_cpu(*txdata->tx_cons_sb);
-	if (tx_idx != tx_start_idx + num_pkts)
-		goto test_loopback_exit;
-
-	/* Unlike HC IGU won't generate an interrupt for status block
-	 * updates that have been performed while interrupts were
-	 * disabled.
-	 */
-	if (bp->common.int_block == INT_BLOCK_IGU) {
-		/* Disable local BHes to prevent a dead-lock situation between
-		 * sch_direct_xmit() and bnx2x_run_loopback() (calling
-		 * bnx2x_tx_int()), as both are taking netif_tx_lock().
-		 */
-		local_bh_disable();
-		bnx2x_tx_int(bp, txdata);
-		local_bh_enable();
-	}
-
-	rx_idx = le16_to_cpu(*fp_rx->rx_cons_sb);
-	if (rx_idx != rx_start_idx + num_pkts)
-		goto test_loopback_exit;
-
-	rx_comp_cons = le16_to_cpu(fp_rx->rx_comp_cons);
-	cqe = &fp_rx->rx_comp_ring[RCQ_BD(rx_comp_cons)];
-	cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
-	cqe_fp_type = cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE;
-	if (!CQE_TYPE_FAST(cqe_fp_type) || (cqe_fp_flags & ETH_RX_ERROR_FALGS))
-		goto test_loopback_rx_exit;
-
-	len = le16_to_cpu(cqe->fast_path_cqe.pkt_len);
-	if (len != pkt_size)
-		goto test_loopback_rx_exit;
-
-	rx_buf = &fp_rx->rx_buf_ring[RX_BD(fp_rx->rx_bd_cons)];
-	dma_sync_single_for_cpu(&bp->pdev->dev,
-				   dma_unmap_addr(rx_buf, mapping),
-				   fp_rx->rx_buf_size, DMA_FROM_DEVICE);
-	skb = rx_buf->skb;
-	skb_reserve(skb, cqe->fast_path_cqe.placement_offset);
-	for (i = ETH_HLEN; i < pkt_size; i++)
-		if (*(skb->data + i) != (unsigned char) (i & 0xff))
-			goto test_loopback_rx_exit;
-
-	rc = 0;
-
-test_loopback_rx_exit:
-
-	fp_rx->rx_bd_cons = NEXT_RX_IDX(fp_rx->rx_bd_cons);
-	fp_rx->rx_bd_prod = NEXT_RX_IDX(fp_rx->rx_bd_prod);
-	fp_rx->rx_comp_cons = NEXT_RCQ_IDX(fp_rx->rx_comp_cons);
-	fp_rx->rx_comp_prod = NEXT_RCQ_IDX(fp_rx->rx_comp_prod);
-
-	/* Update producers */
-	bnx2x_update_rx_prod(bp, fp_rx, fp_rx->rx_bd_prod, fp_rx->rx_comp_prod,
-			     fp_rx->rx_sge_prod);
-
-test_loopback_exit:
-	bp->link_params.loopback_mode = LOOPBACK_NONE;
-
-	return rc;
-}
-
-static int bnx2x_test_loopback(struct bnx2x *bp)
-{
-	int rc = 0, res;
-
-	if (BP_NOMCP(bp))
-		return rc;
-
-	if (!netif_running(bp->dev))
-		return BNX2X_LOOPBACK_FAILED;
-
-	bnx2x_netif_stop(bp, 1);
-	bnx2x_acquire_phy_lock(bp);
-
-	res = bnx2x_run_loopback(bp, BNX2X_PHY_LOOPBACK);
-	if (res) {
-		DP(NETIF_MSG_PROBE, "  PHY loopback failed  (res %d)\n", res);
-		rc |= BNX2X_PHY_LOOPBACK_FAILED;
-	}
-
-	res = bnx2x_run_loopback(bp, BNX2X_MAC_LOOPBACK);
-	if (res) {
-		DP(NETIF_MSG_PROBE, "  MAC loopback failed  (res %d)\n", res);
-		rc |= BNX2X_MAC_LOOPBACK_FAILED;
-	}
-
-	bnx2x_release_phy_lock(bp);
-	bnx2x_netif_start(bp);
-
-	return rc;
-}
-
-#define CRC32_RESIDUAL			0xdebb20e3
-
-static int bnx2x_test_nvram(struct bnx2x *bp)
-{
-	static const struct {
-		int offset;
-		int size;
-	} nvram_tbl[] = {
-		{     0,  0x14 }, /* bootstrap */
-		{  0x14,  0xec }, /* dir */
-		{ 0x100, 0x350 }, /* manuf_info */
-		{ 0x450,  0xf0 }, /* feature_info */
-		{ 0x640,  0x64 }, /* upgrade_key_info */
-		{ 0x708,  0x70 }, /* manuf_key_info */
-		{     0,     0 }
-	};
-	__be32 buf[0x350 / 4];
-	u8 *data = (u8 *)buf;
-	int i, rc;
-	u32 magic, crc;
-
-	if (BP_NOMCP(bp))
-		return 0;
-
-	rc = bnx2x_nvram_read(bp, 0, data, 4);
-	if (rc) {
-		DP(NETIF_MSG_PROBE, "magic value read (rc %d)\n", rc);
-		goto test_nvram_exit;
-	}
-
-	magic = be32_to_cpu(buf[0]);
-	if (magic != 0x669955aa) {
-		DP(NETIF_MSG_PROBE, "magic value (0x%08x)\n", magic);
-		rc = -ENODEV;
-		goto test_nvram_exit;
-	}
-
-	for (i = 0; nvram_tbl[i].size; i++) {
-
-		rc = bnx2x_nvram_read(bp, nvram_tbl[i].offset, data,
-				      nvram_tbl[i].size);
-		if (rc) {
-			DP(NETIF_MSG_PROBE,
-			   "nvram_tbl[%d] read data (rc %d)\n", i, rc);
-			goto test_nvram_exit;
-		}
-
-		crc = ether_crc_le(nvram_tbl[i].size, data);
-		if (crc != CRC32_RESIDUAL) {
-			DP(NETIF_MSG_PROBE,
-			   "nvram_tbl[%d] crc value (0x%08x)\n", i, crc);
-			rc = -ENODEV;
-			goto test_nvram_exit;
-		}
-	}
-
-test_nvram_exit:
-	return rc;
-}
-
-/* Send an EMPTY ramrod on the first queue */
-static int bnx2x_test_intr(struct bnx2x *bp)
-{
-	struct bnx2x_queue_state_params params = {0};
-
-	if (!netif_running(bp->dev))
-		return -ENODEV;
-
-	params.q_obj = &bp->fp->q_obj;
-	params.cmd = BNX2X_Q_CMD_EMPTY;
-
-	__set_bit(RAMROD_COMP_WAIT, &params.ramrod_flags);
-
-	return bnx2x_queue_state_change(bp, &params);
-}
-
-static void bnx2x_self_test(struct net_device *dev,
-			    struct ethtool_test *etest, u64 *buf)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	u8 is_serdes;
-	if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
-		printk(KERN_ERR "Handling parity error recovery. Try again later\n");
-		etest->flags |= ETH_TEST_FL_FAILED;
-		return;
-	}
-
-	memset(buf, 0, sizeof(u64) * BNX2X_NUM_TESTS);
-
-	if (!netif_running(dev))
-		return;
-
-	/* offline tests are not supported in MF mode */
-	if (IS_MF(bp))
-		etest->flags &= ~ETH_TEST_FL_OFFLINE;
-	is_serdes = (bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) > 0;
-
-	if (etest->flags & ETH_TEST_FL_OFFLINE) {
-		int port = BP_PORT(bp);
-		u32 val;
-		u8 link_up;
-
-		/* save current value of input enable for TX port IF */
-		val = REG_RD(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4);
-		/* disable input for TX port IF */
-		REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, 0);
-
-		link_up = bp->link_vars.link_up;
-
-		bnx2x_nic_unload(bp, UNLOAD_NORMAL);
-		bnx2x_nic_load(bp, LOAD_DIAG);
-		/* wait until link state is restored */
-		bnx2x_wait_for_link(bp, 1, is_serdes);
-
-		if (bnx2x_test_registers(bp) != 0) {
-			buf[0] = 1;
-			etest->flags |= ETH_TEST_FL_FAILED;
-		}
-		if (bnx2x_test_memory(bp) != 0) {
-			buf[1] = 1;
-			etest->flags |= ETH_TEST_FL_FAILED;
-		}
-
-		buf[2] = bnx2x_test_loopback(bp);
-		if (buf[2] != 0)
-			etest->flags |= ETH_TEST_FL_FAILED;
-
-		bnx2x_nic_unload(bp, UNLOAD_NORMAL);
-
-		/* restore input for TX port IF */
-		REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, val);
-
-		bnx2x_nic_load(bp, LOAD_NORMAL);
-		/* wait until link state is restored */
-		bnx2x_wait_for_link(bp, link_up, is_serdes);
-	}
-	if (bnx2x_test_nvram(bp) != 0) {
-		buf[3] = 1;
-		etest->flags |= ETH_TEST_FL_FAILED;
-	}
-	if (bnx2x_test_intr(bp) != 0) {
-		buf[4] = 1;
-		etest->flags |= ETH_TEST_FL_FAILED;
-	}
-
-	if (bnx2x_link_test(bp, is_serdes) != 0) {
-		buf[5] = 1;
-		etest->flags |= ETH_TEST_FL_FAILED;
-	}
-
-#ifdef BNX2X_EXTRA_DEBUG
-	bnx2x_panic_dump(bp);
-#endif
-}
-
-#define IS_PORT_STAT(i) \
-	((bnx2x_stats_arr[i].flags & STATS_FLAGS_BOTH) == STATS_FLAGS_PORT)
-#define IS_FUNC_STAT(i)		(bnx2x_stats_arr[i].flags & STATS_FLAGS_FUNC)
-#define IS_MF_MODE_STAT(bp) \
-			(IS_MF(bp) && !(bp->msg_enable & BNX2X_MSG_STATS))
-
-/* ethtool statistics are displayed for all regular ethernet queues and the
- * fcoe L2 queue if not disabled
- */
-static inline int bnx2x_num_stat_queues(struct bnx2x *bp)
-{
-	return BNX2X_NUM_ETH_QUEUES(bp);
-}
-
-static int bnx2x_get_sset_count(struct net_device *dev, int stringset)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	int i, num_stats;
-
-	switch (stringset) {
-	case ETH_SS_STATS:
-		if (is_multi(bp)) {
-			num_stats = bnx2x_num_stat_queues(bp) *
-				BNX2X_NUM_Q_STATS;
-			if (!IS_MF_MODE_STAT(bp))
-				num_stats += BNX2X_NUM_STATS;
-		} else {
-			if (IS_MF_MODE_STAT(bp)) {
-				num_stats = 0;
-				for (i = 0; i < BNX2X_NUM_STATS; i++)
-					if (IS_FUNC_STAT(i))
-						num_stats++;
-			} else
-				num_stats = BNX2X_NUM_STATS;
-		}
-		return num_stats;
-
-	case ETH_SS_TEST:
-		return BNX2X_NUM_TESTS;
-
-	default:
-		return -EINVAL;
-	}
-}
-
-static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	int i, j, k;
-	char queue_name[MAX_QUEUE_NAME_LEN+1];
-
-	switch (stringset) {
-	case ETH_SS_STATS:
-		if (is_multi(bp)) {
-			k = 0;
-			for_each_eth_queue(bp, i) {
-				memset(queue_name, 0, sizeof(queue_name));
-				sprintf(queue_name, "%d", i);
-				for (j = 0; j < BNX2X_NUM_Q_STATS; j++)
-					snprintf(buf + (k + j)*ETH_GSTRING_LEN,
-						ETH_GSTRING_LEN,
-						bnx2x_q_stats_arr[j].string,
-						queue_name);
-				k += BNX2X_NUM_Q_STATS;
-			}
-			if (IS_MF_MODE_STAT(bp))
-				break;
-			for (j = 0; j < BNX2X_NUM_STATS; j++)
-				strcpy(buf + (k + j)*ETH_GSTRING_LEN,
-				       bnx2x_stats_arr[j].string);
-		} else {
-			for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
-				if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
-					continue;
-				strcpy(buf + j*ETH_GSTRING_LEN,
-				       bnx2x_stats_arr[i].string);
-				j++;
-			}
-		}
-		break;
-
-	case ETH_SS_TEST:
-		memcpy(buf, bnx2x_tests_str_arr, sizeof(bnx2x_tests_str_arr));
-		break;
-	}
-}
-
-static void bnx2x_get_ethtool_stats(struct net_device *dev,
-				    struct ethtool_stats *stats, u64 *buf)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	u32 *hw_stats, *offset;
-	int i, j, k;
-
-	if (is_multi(bp)) {
-		k = 0;
-		for_each_eth_queue(bp, i) {
-			hw_stats = (u32 *)&bp->fp[i].eth_q_stats;
-			for (j = 0; j < BNX2X_NUM_Q_STATS; j++) {
-				if (bnx2x_q_stats_arr[j].size == 0) {
-					/* skip this counter */
-					buf[k + j] = 0;
-					continue;
-				}
-				offset = (hw_stats +
-					  bnx2x_q_stats_arr[j].offset);
-				if (bnx2x_q_stats_arr[j].size == 4) {
-					/* 4-byte counter */
-					buf[k + j] = (u64) *offset;
-					continue;
-				}
-				/* 8-byte counter */
-				buf[k + j] = HILO_U64(*offset, *(offset + 1));
-			}
-			k += BNX2X_NUM_Q_STATS;
-		}
-		if (IS_MF_MODE_STAT(bp))
-			return;
-		hw_stats = (u32 *)&bp->eth_stats;
-		for (j = 0; j < BNX2X_NUM_STATS; j++) {
-			if (bnx2x_stats_arr[j].size == 0) {
-				/* skip this counter */
-				buf[k + j] = 0;
-				continue;
-			}
-			offset = (hw_stats + bnx2x_stats_arr[j].offset);
-			if (bnx2x_stats_arr[j].size == 4) {
-				/* 4-byte counter */
-				buf[k + j] = (u64) *offset;
-				continue;
-			}
-			/* 8-byte counter */
-			buf[k + j] = HILO_U64(*offset, *(offset + 1));
-		}
-	} else {
-		hw_stats = (u32 *)&bp->eth_stats;
-		for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
-			if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
-				continue;
-			if (bnx2x_stats_arr[i].size == 0) {
-				/* skip this counter */
-				buf[j] = 0;
-				j++;
-				continue;
-			}
-			offset = (hw_stats + bnx2x_stats_arr[i].offset);
-			if (bnx2x_stats_arr[i].size == 4) {
-				/* 4-byte counter */
-				buf[j] = (u64) *offset;
-				j++;
-				continue;
-			}
-			/* 8-byte counter */
-			buf[j] = HILO_U64(*offset, *(offset + 1));
-			j++;
-		}
-	}
-}
-
-static int bnx2x_set_phys_id(struct net_device *dev,
-			     enum ethtool_phys_id_state state)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	if (!netif_running(dev))
-		return -EAGAIN;
-
-	if (!bp->port.pmf)
-		return -EOPNOTSUPP;
-
-	switch (state) {
-	case ETHTOOL_ID_ACTIVE:
-		return 1;	/* cycle on/off once per second */
-
-	case ETHTOOL_ID_ON:
-		bnx2x_set_led(&bp->link_params, &bp->link_vars,
-			      LED_MODE_ON, SPEED_1000);
-		break;
-
-	case ETHTOOL_ID_OFF:
-		bnx2x_set_led(&bp->link_params, &bp->link_vars,
-			      LED_MODE_FRONT_PANEL_OFF, 0);
-
-		break;
-
-	case ETHTOOL_ID_INACTIVE:
-		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, T_ETH_INDIRECTION_TABLE_SIZE);
-	u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
-	size_t i;
-
-	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
-		return -EOPNOTSUPP;
-
-	/* Get the current configuration of the RSS indirection table */
-	bnx2x_get_rss_ind_table(&bp->rss_conf_obj, ind_table);
-
-	/*
-	 * We can't use a memcpy() as an internal storage of an
-	 * indirection table is a u8 array while indir->ring_index
-	 * points to an array of u32.
-	 *
-	 * Indirection table contains the FW Client IDs, so we need to
-	 * align the returned table to the Client ID of the leading RSS
-	 * queue.
-	 */
-	for (i = 0; i < copy_size; i++)
-		indir->ring_index[i] = ind_table[i] - bp->fp->cl_id;
-
-	indir->size = T_ETH_INDIRECTION_TABLE_SIZE;
-
-	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;
-	u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
-	u32 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp);
-
-	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
-		return -EOPNOTSUPP;
-
-	/* validate the size */
-	if (indir->size != T_ETH_INDIRECTION_TABLE_SIZE)
-		return -EINVAL;
-
-	for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
-		/* validate the indices */
-		if (indir->ring_index[i] >= num_eth_queues)
-			return -EINVAL;
-		/*
-		 * The same as in bnx2x_get_rxfh_indir: we can't use a memcpy()
-		 * as an internal storage of an indirection table is a u8 array
-		 * while indir->ring_index points to an array of u32.
-		 *
-		 * Indirection table contains the FW Client IDs, so we need to
-		 * align the received table to the Client ID of the leading RSS
-		 * queue
-		 */
-		ind_table[i] = indir->ring_index[i] + bp->fp->cl_id;
-	}
-
-	return bnx2x_config_rss_pf(bp, ind_table, false);
-}
-
-static const struct ethtool_ops bnx2x_ethtool_ops = {
-	.get_settings		= bnx2x_get_settings,
-	.set_settings		= bnx2x_set_settings,
-	.get_drvinfo		= bnx2x_get_drvinfo,
-	.get_regs_len		= bnx2x_get_regs_len,
-	.get_regs		= bnx2x_get_regs,
-	.get_wol		= bnx2x_get_wol,
-	.set_wol		= bnx2x_set_wol,
-	.get_msglevel		= bnx2x_get_msglevel,
-	.set_msglevel		= bnx2x_set_msglevel,
-	.nway_reset		= bnx2x_nway_reset,
-	.get_link		= bnx2x_get_link,
-	.get_eeprom_len		= bnx2x_get_eeprom_len,
-	.get_eeprom		= bnx2x_get_eeprom,
-	.set_eeprom		= bnx2x_set_eeprom,
-	.get_coalesce		= bnx2x_get_coalesce,
-	.set_coalesce		= bnx2x_set_coalesce,
-	.get_ringparam		= bnx2x_get_ringparam,
-	.set_ringparam		= bnx2x_set_ringparam,
-	.get_pauseparam		= bnx2x_get_pauseparam,
-	.set_pauseparam		= bnx2x_set_pauseparam,
-	.self_test		= bnx2x_self_test,
-	.get_sset_count		= bnx2x_get_sset_count,
-	.get_strings		= bnx2x_get_strings,
-	.set_phys_id		= bnx2x_set_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)
-{
-	SET_ETHTOOL_OPS(netdev, &bnx2x_ethtool_ops);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_fw_defs.h linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_fw_defs.h
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_fw_defs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_fw_defs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,410 +0,0 @@
-/* bnx2x_fw_defs.h: Broadcom Everest network driver.
- *
- * Copyright (c) 2007-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
- * the Free Software Foundation.
- */
-
-#ifndef BNX2X_FW_DEFS_H
-#define BNX2X_FW_DEFS_H
-
-#define CSTORM_ASSERT_LIST_INDEX_OFFSET	(IRO[148].base)
-#define CSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
-	(IRO[147].base + ((assertListEntry) * IRO[147].m1))
-#define CSTORM_EVENT_RING_DATA_OFFSET(pfId) \
-	(IRO[153].base + (((pfId)>>1) * IRO[153].m1) + (((pfId)&1) * \
-	IRO[153].m2))
-#define CSTORM_EVENT_RING_PROD_OFFSET(pfId) \
-	(IRO[154].base + (((pfId)>>1) * IRO[154].m1) + (((pfId)&1) * \
-	IRO[154].m2))
-#define CSTORM_FINAL_CLEANUP_COMPLETE_OFFSET(funcId) \
-	(IRO[159].base + ((funcId) * IRO[159].m1))
-#define CSTORM_FUNC_EN_OFFSET(funcId) \
-	(IRO[149].base + ((funcId) * IRO[149].m1))
-#define CSTORM_IGU_MODE_OFFSET (IRO[157].base)
-#define CSTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
-	(IRO[315].base + ((pfId) * IRO[315].m1))
-#define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
-	(IRO[316].base + ((pfId) * IRO[316].m1))
-#define CSTORM_ISCSI_EQ_CONS_OFFSET(pfId, iscsiEqId) \
-	(IRO[308].base + ((pfId) * IRO[308].m1) + ((iscsiEqId) * IRO[308].m2))
-#define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfId, iscsiEqId) \
-	(IRO[310].base + ((pfId) * IRO[310].m1) + ((iscsiEqId) * IRO[310].m2))
-#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfId, iscsiEqId) \
-	(IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * IRO[309].m2))
-#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfId, iscsiEqId) \
-	(IRO[311].base + ((pfId) * IRO[311].m1) + ((iscsiEqId) * IRO[311].m2))
-#define CSTORM_ISCSI_EQ_PROD_OFFSET(pfId, iscsiEqId) \
-	(IRO[307].base + ((pfId) * IRO[307].m1) + ((iscsiEqId) * IRO[307].m2))
-#define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfId, iscsiEqId) \
-	(IRO[313].base + ((pfId) * IRO[313].m1) + ((iscsiEqId) * IRO[313].m2))
-#define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfId, iscsiEqId) \
-	(IRO[312].base + ((pfId) * IRO[312].m1) + ((iscsiEqId) * IRO[312].m2))
-#define CSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
-	(IRO[314].base + ((pfId) * IRO[314].m1))
-#define CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
-	(IRO[306].base + ((pfId) * IRO[306].m1))
-#define CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
-	(IRO[305].base + ((pfId) * IRO[305].m1))
-#define CSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
-	(IRO[304].base + ((pfId) * IRO[304].m1))
-#define CSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
-	(IRO[151].base + ((funcId) * IRO[151].m1))
-#define CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(pfId) \
-	(IRO[142].base + ((pfId) * IRO[142].m1))
-#define CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(pfId) \
-	(IRO[143].base + ((pfId) * IRO[143].m1))
-#define CSTORM_SP_STATUS_BLOCK_OFFSET(pfId) \
-	(IRO[141].base + ((pfId) * IRO[141].m1))
-#define CSTORM_SP_STATUS_BLOCK_SIZE (IRO[141].size)
-#define CSTORM_SP_SYNC_BLOCK_OFFSET(pfId) \
-	(IRO[144].base + ((pfId) * IRO[144].m1))
-#define CSTORM_SP_SYNC_BLOCK_SIZE (IRO[144].size)
-#define CSTORM_STATUS_BLOCK_DATA_FLAGS_OFFSET(sbId, hcIndex) \
-	(IRO[136].base + ((sbId) * IRO[136].m1) + ((hcIndex) * IRO[136].m2))
-#define CSTORM_STATUS_BLOCK_DATA_OFFSET(sbId) \
-	(IRO[133].base + ((sbId) * IRO[133].m1))
-#define CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(sbId) \
-	(IRO[134].base + ((sbId) * IRO[134].m1))
-#define CSTORM_STATUS_BLOCK_DATA_TIMEOUT_OFFSET(sbId, hcIndex) \
-	(IRO[135].base + ((sbId) * IRO[135].m1) + ((hcIndex) * IRO[135].m2))
-#define CSTORM_STATUS_BLOCK_OFFSET(sbId) \
-	(IRO[132].base + ((sbId) * IRO[132].m1))
-#define CSTORM_STATUS_BLOCK_SIZE (IRO[132].size)
-#define CSTORM_SYNC_BLOCK_OFFSET(sbId) \
-	(IRO[137].base + ((sbId) * IRO[137].m1))
-#define CSTORM_SYNC_BLOCK_SIZE (IRO[137].size)
-#define CSTORM_VF_PF_CHANNEL_STATE_OFFSET(vfId) \
-	(IRO[155].base + ((vfId) * IRO[155].m1))
-#define CSTORM_VF_PF_CHANNEL_VALID_OFFSET(vfId) \
-	(IRO[156].base + ((vfId) * IRO[156].m1))
-#define CSTORM_VF_TO_PF_OFFSET(funcId) \
-	(IRO[150].base + ((funcId) * IRO[150].m1))
-#define TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET (IRO[204].base)
-#define TSTORM_APPROXIMATE_MATCH_MULTICAST_FILTERING_OFFSET(pfId) \
-	(IRO[203].base + ((pfId) * IRO[203].m1))
-#define TSTORM_ASSERT_LIST_INDEX_OFFSET	(IRO[102].base)
-#define TSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
-	(IRO[101].base + ((assertListEntry) * IRO[101].m1))
-#define TSTORM_COMMON_SAFC_WORKAROUND_ENABLE_OFFSET (IRO[107].base)
-#define TSTORM_COMMON_SAFC_WORKAROUND_TIMEOUT_10USEC_OFFSET \
-	(IRO[108].base)
-#define TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(pfId) \
-	(IRO[201].base + ((pfId) * IRO[201].m1))
-#define TSTORM_FUNC_EN_OFFSET(funcId) \
-	(IRO[103].base + ((funcId) * IRO[103].m1))
-#define TSTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
-	(IRO[271].base + ((pfId) * IRO[271].m1))
-#define TSTORM_ISCSI_L2_ISCSI_OOO_CID_TABLE_OFFSET(pfId) \
-	(IRO[272].base + ((pfId) * IRO[272].m1))
-#define TSTORM_ISCSI_L2_ISCSI_OOO_CLIENT_ID_TABLE_OFFSET(pfId) \
-	(IRO[273].base + ((pfId) * IRO[273].m1))
-#define TSTORM_ISCSI_L2_ISCSI_OOO_PROD_OFFSET(pfId) \
-	(IRO[274].base + ((pfId) * IRO[274].m1))
-#define TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
-	(IRO[270].base + ((pfId) * IRO[270].m1))
-#define TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
-	(IRO[269].base + ((pfId) * IRO[269].m1))
-#define TSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
-	(IRO[268].base + ((pfId) * IRO[268].m1))
-#define TSTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
-	(IRO[267].base + ((pfId) * IRO[267].m1))
-#define TSTORM_ISCSI_TCP_LOCAL_ADV_WND_OFFSET(pfId) \
-	(IRO[276].base + ((pfId) * IRO[276].m1))
-#define TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
-	(IRO[263].base + ((pfId) * IRO[263].m1))
-#define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
-	(IRO[264].base + ((pfId) * IRO[264].m1))
-#define TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfId) \
-	(IRO[265].base + ((pfId) * IRO[265].m1))
-#define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
-	(IRO[266].base + ((pfId) * IRO[266].m1))
-#define TSTORM_MAC_FILTER_CONFIG_OFFSET(pfId) \
-	(IRO[202].base + ((pfId) * IRO[202].m1))
-#define TSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
-	(IRO[105].base + ((funcId) * IRO[105].m1))
-#define TSTORM_TCP_MAX_CWND_OFFSET(pfId) \
-	(IRO[216].base + ((pfId) * IRO[216].m1))
-#define TSTORM_VF_TO_PF_OFFSET(funcId) \
-	(IRO[104].base + ((funcId) * IRO[104].m1))
-#define USTORM_AGG_DATA_OFFSET (IRO[206].base)
-#define USTORM_AGG_DATA_SIZE (IRO[206].size)
-#define USTORM_ASSERT_LIST_INDEX_OFFSET	(IRO[177].base)
-#define USTORM_ASSERT_LIST_OFFSET(assertListEntry) \
-	(IRO[176].base + ((assertListEntry) * IRO[176].m1))
-#define USTORM_CQE_PAGE_NEXT_OFFSET(portId, clientId) \
-	(IRO[205].base + ((portId) * IRO[205].m1) + ((clientId) * \
-	IRO[205].m2))
-#define USTORM_ETH_PAUSE_ENABLED_OFFSET(portId) \
-	(IRO[183].base + ((portId) * IRO[183].m1))
-#define USTORM_FCOE_EQ_PROD_OFFSET(pfId) \
-	(IRO[317].base + ((pfId) * IRO[317].m1))
-#define USTORM_FUNC_EN_OFFSET(funcId) \
-	(IRO[178].base + ((funcId) * IRO[178].m1))
-#define USTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
-	(IRO[281].base + ((pfId) * IRO[281].m1))
-#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
-	(IRO[282].base + ((pfId) * IRO[282].m1))
-#define USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
-	(IRO[286].base + ((pfId) * IRO[286].m1))
-#define USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfId) \
-	(IRO[283].base + ((pfId) * IRO[283].m1))
-#define USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
-	(IRO[279].base + ((pfId) * IRO[279].m1))
-#define USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
-	(IRO[278].base + ((pfId) * IRO[278].m1))
-#define USTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
-	(IRO[277].base + ((pfId) * IRO[277].m1))
-#define USTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
-	(IRO[280].base + ((pfId) * IRO[280].m1))
-#define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfId) \
-	(IRO[284].base + ((pfId) * IRO[284].m1))
-#define USTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
-	(IRO[285].base + ((pfId) * IRO[285].m1))
-#define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(pfId) \
-	(IRO[182].base + ((pfId) * IRO[182].m1))
-#define USTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
-	(IRO[180].base + ((funcId) * IRO[180].m1))
-#define USTORM_RX_PRODS_E1X_OFFSET(portId, clientId) \
-	(IRO[209].base + ((portId) * IRO[209].m1) + ((clientId) * \
-	IRO[209].m2))
-#define USTORM_RX_PRODS_E2_OFFSET(qzoneId) \
-	(IRO[210].base + ((qzoneId) * IRO[210].m1))
-#define USTORM_TPA_BTR_OFFSET (IRO[207].base)
-#define USTORM_TPA_BTR_SIZE (IRO[207].size)
-#define USTORM_VF_TO_PF_OFFSET(funcId) \
-	(IRO[179].base + ((funcId) * IRO[179].m1))
-#define XSTORM_AGG_INT_FINAL_CLEANUP_COMP_TYPE (IRO[67].base)
-#define XSTORM_AGG_INT_FINAL_CLEANUP_INDEX (IRO[66].base)
-#define XSTORM_ASSERT_LIST_INDEX_OFFSET	(IRO[51].base)
-#define XSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
-	(IRO[50].base + ((assertListEntry) * IRO[50].m1))
-#define XSTORM_CMNG_PER_PORT_VARS_OFFSET(portId) \
-	(IRO[43].base + ((portId) * IRO[43].m1))
-#define XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(pfId) \
-	(IRO[45].base + ((pfId) * IRO[45].m1))
-#define XSTORM_FUNC_EN_OFFSET(funcId) \
-	(IRO[47].base + ((funcId) * IRO[47].m1))
-#define XSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
-	(IRO[294].base + ((pfId) * IRO[294].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(pfId) \
-	(IRO[297].base + ((pfId) * IRO[297].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfId) \
-	(IRO[298].base + ((pfId) * IRO[298].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfId) \
-	(IRO[299].base + ((pfId) * IRO[299].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfId) \
-	(IRO[300].base + ((pfId) * IRO[300].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfId) \
-	(IRO[301].base + ((pfId) * IRO[301].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfId) \
-	(IRO[302].base + ((pfId) * IRO[302].m1))
-#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfId) \
-	(IRO[303].base + ((pfId) * IRO[303].m1))
-#define XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
-	(IRO[293].base + ((pfId) * IRO[293].m1))
-#define XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
-	(IRO[292].base + ((pfId) * IRO[292].m1))
-#define XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
-	(IRO[291].base + ((pfId) * IRO[291].m1))
-#define XSTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
-	(IRO[296].base + ((pfId) * IRO[296].m1))
-#define XSTORM_ISCSI_SQ_SIZE_OFFSET(pfId) \
-	(IRO[295].base + ((pfId) * IRO[295].m1))
-#define XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(pfId) \
-	(IRO[290].base + ((pfId) * IRO[290].m1))
-#define XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
-	(IRO[289].base + ((pfId) * IRO[289].m1))
-#define XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(pfId) \
-	(IRO[288].base + ((pfId) * IRO[288].m1))
-#define XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(pfId) \
-	(IRO[287].base + ((pfId) * IRO[287].m1))
-#define XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(pfId) \
-	(IRO[44].base + ((pfId) * IRO[44].m1))
-#define XSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
-	(IRO[49].base + ((funcId) * IRO[49].m1))
-#define XSTORM_SPQ_DATA_OFFSET(funcId) \
-	(IRO[32].base + ((funcId) * IRO[32].m1))
-#define XSTORM_SPQ_DATA_SIZE (IRO[32].size)
-#define XSTORM_SPQ_PAGE_BASE_OFFSET(funcId) \
-	(IRO[30].base + ((funcId) * IRO[30].m1))
-#define XSTORM_SPQ_PROD_OFFSET(funcId) \
-	(IRO[31].base + ((funcId) * IRO[31].m1))
-#define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_OFFSET(portId) \
-	(IRO[211].base + ((portId) * IRO[211].m1))
-#define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_OFFSET(portId) \
-	(IRO[212].base + ((portId) * IRO[212].m1))
-#define XSTORM_TCP_TX_SWS_TIMER_VAL_OFFSET(pfId) \
-	(IRO[214].base + (((pfId)>>1) * IRO[214].m1) + (((pfId)&1) * \
-	IRO[214].m2))
-#define XSTORM_VF_TO_PF_OFFSET(funcId) \
-	(IRO[48].base + ((funcId) * IRO[48].m1))
-#define COMMON_ASM_INVALID_ASSERT_OPCODE 0x0
-
-/**
-* This file defines HSI constants for the ETH flow
-*/
-#ifdef _EVEREST_MICROCODE
-#include "Microcode\Generated\DataTypes\eth_rx_bd.h"
-#include "Microcode\Generated\DataTypes\eth_tx_bd.h"
-#include "Microcode\Generated\DataTypes\eth_rx_cqe.h"
-#include "Microcode\Generated\DataTypes\eth_rx_sge.h"
-#include "Microcode\Generated\DataTypes\eth_rx_cqe_next_page.h"
-#endif
-
-
-/* Ethernet Ring parameters */
-#define X_ETH_LOCAL_RING_SIZE 13
-#define FIRST_BD_IN_PKT	0
-#define PARSE_BD_INDEX 1
-#define NUM_OF_ETH_BDS_IN_PAGE ((PAGE_SIZE)/(STRUCT_SIZE(eth_tx_bd)/8))
-#define U_ETH_NUM_OF_SGES_TO_FETCH 8
-#define U_ETH_MAX_SGES_FOR_PACKET 3
-
-/* Rx ring params */
-#define U_ETH_LOCAL_BD_RING_SIZE 8
-#define U_ETH_LOCAL_SGE_RING_SIZE 10
-#define U_ETH_SGL_SIZE 8
-	/* The fw will padd the buffer with this value, so the IP header \
-	will be align to 4 Byte */
-#define IP_HEADER_ALIGNMENT_PADDING 2
-
-#define U_ETH_SGES_PER_PAGE_INVERSE_MASK \
-	(0xFFFF - ((PAGE_SIZE/((STRUCT_SIZE(eth_rx_sge))/8))-1))
-
-#define TU_ETH_CQES_PER_PAGE (PAGE_SIZE/(STRUCT_SIZE(eth_rx_cqe)/8))
-#define U_ETH_BDS_PER_PAGE (PAGE_SIZE/(STRUCT_SIZE(eth_rx_bd)/8))
-#define U_ETH_SGES_PER_PAGE (PAGE_SIZE/(STRUCT_SIZE(eth_rx_sge)/8))
-
-#define U_ETH_BDS_PER_PAGE_MASK	(U_ETH_BDS_PER_PAGE-1)
-#define U_ETH_CQE_PER_PAGE_MASK	(TU_ETH_CQES_PER_PAGE-1)
-#define U_ETH_SGES_PER_PAGE_MASK (U_ETH_SGES_PER_PAGE-1)
-
-#define U_ETH_UNDEFINED_Q 0xFF
-
-#define T_ETH_INDIRECTION_TABLE_SIZE 128
-#define T_ETH_RSS_KEY 10
-#define ETH_NUM_OF_RSS_ENGINES_E2 72
-
-#define FILTER_RULES_COUNT 16
-#define MULTICAST_RULES_COUNT 16
-#define CLASSIFY_RULES_COUNT 16
-
-/*The CRC32 seed, that is used for the hash(reduction) multicast address */
-#define ETH_CRC32_HASH_SEED 0x00000000
-
-#define ETH_CRC32_HASH_BIT_SIZE	(8)
-#define ETH_CRC32_HASH_MASK EVAL((1<<ETH_CRC32_HASH_BIT_SIZE)-1)
-
-/* Maximal L2 clients supported */
-#define ETH_MAX_RX_CLIENTS_E1 18
-#define ETH_MAX_RX_CLIENTS_E1H 28
-#define ETH_MAX_RX_CLIENTS_E2 152
-
-/* Maximal statistics client Ids */
-#define MAX_STAT_COUNTER_ID_E1 36
-#define MAX_STAT_COUNTER_ID_E1H	56
-#define MAX_STAT_COUNTER_ID_E2 140
-
-#define MAX_MAC_CREDIT_E1 192 /* Per Chip */
-#define MAX_MAC_CREDIT_E1H 256 /* Per Chip */
-#define MAX_MAC_CREDIT_E2 272 /* Per Path */
-#define MAX_VLAN_CREDIT_E1 0 /* Per Chip */
-#define MAX_VLAN_CREDIT_E1H 0 /* Per Chip */
-#define MAX_VLAN_CREDIT_E2 272 /* Per Path */
-
-
-/* Maximal aggregation queues supported */
-#define ETH_MAX_AGGREGATION_QUEUES_E1 32
-#define ETH_MAX_AGGREGATION_QUEUES_E1H_E2 64
-
-
-#define ETH_NUM_OF_MCAST_BINS 256
-#define ETH_NUM_OF_MCAST_ENGINES_E2 72
-
-#define ETH_MIN_RX_CQES_WITHOUT_TPA (MAX_RAMRODS_PER_PORT + 3)
-#define ETH_MIN_RX_CQES_WITH_TPA_E1 \
-	(ETH_MAX_AGGREGATION_QUEUES_E1 + ETH_MIN_RX_CQES_WITHOUT_TPA)
-#define ETH_MIN_RX_CQES_WITH_TPA_E1H_E2 \
-	(ETH_MAX_AGGREGATION_QUEUES_E1H_E2 + ETH_MIN_RX_CQES_WITHOUT_TPA)
-
-#define DISABLE_STATISTIC_COUNTER_ID_VALUE 0
-
-
-/**
- * This file defines HSI constants common to all microcode flows
- */
-
-#define PROTOCOL_STATE_BIT_OFFSET 6
-
-#define ETH_STATE (ETH_CONNECTION_TYPE << PROTOCOL_STATE_BIT_OFFSET)
-#define TOE_STATE (TOE_CONNECTION_TYPE << PROTOCOL_STATE_BIT_OFFSET)
-#define RDMA_STATE (RDMA_CONNECTION_TYPE << PROTOCOL_STATE_BIT_OFFSET)
-
-/* microcode fixed page page size 4K (chains and ring segments) */
-#define MC_PAGE_SIZE 4096
-
-/* Number of indices per slow-path SB */
-#define HC_SP_SB_MAX_INDICES 16
-
-/* Number of indices per SB */
-#define HC_SB_MAX_INDICES_E1X 8
-#define HC_SB_MAX_INDICES_E2 8
-
-#define HC_SB_MAX_SB_E1X 32
-#define HC_SB_MAX_SB_E2	136
-
-#define HC_SP_SB_ID 0xde
-
-#define HC_SB_MAX_SM 2
-
-#define HC_SB_MAX_DYNAMIC_INDICES 4
-
-/* max number of slow path commands per port */
-#define MAX_RAMRODS_PER_PORT 8
-
-
-/**** DEFINES FOR TIMERS/CLOCKS RESOLUTIONS ****/
-
-#define TIMERS_TICK_SIZE_CHIP (1e-3)
-
-#define TSEMI_CLK1_RESUL_CHIP (1e-3)
-
-#define XSEMI_CLK1_RESUL_CHIP (1e-3)
-
-#define SDM_TIMER_TICK_RESUL_CHIP (4 * (1e-6))
-
-/**** END DEFINES FOR TIMERS/CLOCKS RESOLUTIONS ****/
-
-#define XSTORM_IP_ID_ROLL_HALF 0x8000
-#define XSTORM_IP_ID_ROLL_ALL 0
-
-#define FW_LOG_LIST_SIZE 50
-
-#define NUM_OF_SAFC_BITS 16
-#define MAX_COS_NUMBER 4
-#define MAX_TRAFFIC_TYPES 8
-#define MAX_PFC_PRIORITIES 8
-
-	/* used by array traffic_type_to_priority[] to mark traffic type \
-	that is not mapped to priority*/
-#define LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED 0xFF
-
-
-#define C_ERES_PER_PAGE \
-	(PAGE_SIZE / BITS_TO_BYTES(STRUCT_SIZE(event_ring_elem)))
-#define C_ERE_PER_PAGE_MASK (C_ERES_PER_PAGE - 1)
-
-#define STATS_QUERY_CMD_COUNT 16
-
-#define NIV_LIST_TABLE_SIZE 4096
-
-#define INVALID_VNIC_ID	0xFF
-
-
-#define UNDEF_IRO 0x80000000
-
-
-#endif /* BNX2X_FW_DEFS_H */
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_fw_file_hdr.h linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_fw_file_hdr.h
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_fw_file_hdr.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_fw_file_hdr.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-/* bnx2x_fw_file_hdr.h: FW binary file header structure.
- *
- * Copyright (c) 2007-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
- * the Free Software Foundation.
- *
- * Maintained by: Eilon Greenstein <eilong@broadcom.com>
- * Written by: Vladislav Zolotarov <vladz@broadcom.com>
- * Based on the original idea of John Wright <john.wright@hp.com>.
- */
-
-#ifndef BNX2X_INIT_FILE_HDR_H
-#define BNX2X_INIT_FILE_HDR_H
-
-struct bnx2x_fw_file_section {
-	__be32 len;
-	__be32 offset;
-};
-
-struct bnx2x_fw_file_hdr {
-	struct bnx2x_fw_file_section init_ops;
-	struct bnx2x_fw_file_section init_ops_offsets;
-	struct bnx2x_fw_file_section init_data;
-	struct bnx2x_fw_file_section tsem_int_table_data;
-	struct bnx2x_fw_file_section tsem_pram_data;
-	struct bnx2x_fw_file_section usem_int_table_data;
-	struct bnx2x_fw_file_section usem_pram_data;
-	struct bnx2x_fw_file_section csem_int_table_data;
-	struct bnx2x_fw_file_section csem_pram_data;
-	struct bnx2x_fw_file_section xsem_int_table_data;
-	struct bnx2x_fw_file_section xsem_pram_data;
-	struct bnx2x_fw_file_section iro_arr;
-	struct bnx2x_fw_file_section fw_version;
-};
-
-#endif /* BNX2X_INIT_FILE_HDR_H */
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x.h linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x.h
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,2080 +0,0 @@
-/* bnx2x.h: Broadcom Everest network driver.
- *
- * Copyright (c) 2007-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
- * the Free Software Foundation.
- *
- * Maintained by: Eilon Greenstein <eilong@broadcom.com>
- * Written by: Eliezer Tamir
- * Based on code from Michael Chan's bnx2 driver
- */
-
-#ifndef BNX2X_H
-#define BNX2X_H
-#include <linux/netdevice.h>
-#include <linux/dma-mapping.h>
-#include <linux/types.h>
-
-/* compilation time flags */
-
-/* define this to make the driver freeze on error to allow getting debug info
- * (you will need to reboot afterwards) */
-/* #define BNX2X_STOP_ON_ERROR */
-
-#define DRV_MODULE_VERSION      "1.70.00-0"
-#define DRV_MODULE_RELDATE      "2011/06/13"
-#define BNX2X_BC_VER            0x040200
-
-#if defined(CONFIG_DCB)
-#define BCM_DCBNL
-#endif
-#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
-#define BCM_CNIC 1
-#include "../cnic_if.h"
-#endif
-
-#ifdef BCM_CNIC
-#define BNX2X_MIN_MSIX_VEC_CNT 3
-#define BNX2X_MSIX_VEC_FP_START 2
-#else
-#define BNX2X_MIN_MSIX_VEC_CNT 2
-#define BNX2X_MSIX_VEC_FP_START 1
-#endif
-
-#include <linux/mdio.h>
-
-#include "bnx2x_reg.h"
-#include "bnx2x_fw_defs.h"
-#include "bnx2x_hsi.h"
-#include "bnx2x_link.h"
-#include "bnx2x_sp.h"
-#include "bnx2x_dcb.h"
-#include "bnx2x_stats.h"
-
-/* error/debug prints */
-
-#define DRV_MODULE_NAME		"bnx2x"
-
-/* for messages that are currently off */
-#define BNX2X_MSG_OFF			0
-#define BNX2X_MSG_MCP			0x010000 /* was: NETIF_MSG_HW */
-#define BNX2X_MSG_STATS			0x020000 /* was: NETIF_MSG_TIMER */
-#define BNX2X_MSG_NVM			0x040000 /* was: NETIF_MSG_HW */
-#define BNX2X_MSG_DMAE			0x080000 /* was: NETIF_MSG_HW */
-#define BNX2X_MSG_SP			0x100000 /* was: NETIF_MSG_INTR */
-#define BNX2X_MSG_FP			0x200000 /* was: NETIF_MSG_INTR */
-
-#define DP_LEVEL			KERN_NOTICE	/* was: KERN_DEBUG */
-
-/* regular debug print */
-#define DP(__mask, __fmt, __args...)				\
-do {								\
-	if (bp->msg_enable & (__mask))				\
-		printk(DP_LEVEL "[%s:%d(%s)]" __fmt,		\
-		       __func__, __LINE__,			\
-		       bp->dev ? (bp->dev->name) : "?",		\
-		       ##__args);				\
-} while (0)
-
-#define DP_CONT(__mask, __fmt, __args...)			\
-do {								\
-	if (bp->msg_enable & (__mask))				\
-		pr_cont(__fmt, ##__args);			\
-} while (0)
-
-/* errors debug print */
-#define BNX2X_DBG_ERR(__fmt, __args...)				\
-do {								\
-	if (netif_msg_probe(bp))				\
-		pr_err("[%s:%d(%s)]" __fmt,			\
-		       __func__, __LINE__,			\
-		       bp->dev ? (bp->dev->name) : "?",		\
-		       ##__args);				\
-} while (0)
-
-/* for errors (never masked) */
-#define BNX2X_ERR(__fmt, __args...)				\
-do {								\
-	pr_err("[%s:%d(%s)]" __fmt,				\
-	       __func__, __LINE__,				\
-	       bp->dev ? (bp->dev->name) : "?",			\
-	       ##__args);					\
-	} while (0)
-
-#define BNX2X_ERROR(__fmt, __args...) do { \
-	pr_err("[%s:%d]" __fmt, __func__, __LINE__, ##__args); \
-	} while (0)
-
-
-/* before we have a dev->name use dev_info() */
-#define BNX2X_DEV_INFO(__fmt, __args...)			 \
-do {								 \
-	if (netif_msg_probe(bp))				 \
-		dev_info(&bp->pdev->dev, __fmt, ##__args);	 \
-} while (0)
-
-#define BNX2X_MAC_FMT		"%pM"
-#define BNX2X_MAC_PRN_LIST(mac)	(mac)
-
-
-#ifdef BNX2X_STOP_ON_ERROR
-void bnx2x_int_disable(struct bnx2x *bp);
-#define bnx2x_panic() do { \
-		bp->panic = 1; \
-		BNX2X_ERR("driver assert\n"); \
-		bnx2x_int_disable(bp); \
-		bnx2x_panic_dump(bp); \
-	} while (0)
-#else
-#define bnx2x_panic() do { \
-		bp->panic = 1; \
-		BNX2X_ERR("driver assert\n"); \
-		bnx2x_panic_dump(bp); \
-	} while (0)
-#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)
-#define HILO_U64(hi, lo)		((((u64)(hi)) << 32) + (lo))
-
-
-#define REG_ADDR(bp, offset)		((bp->regview) + (offset))
-
-#define REG_RD(bp, offset)		readl(REG_ADDR(bp, offset))
-#define REG_RD8(bp, offset)		readb(REG_ADDR(bp, offset))
-#define REG_RD16(bp, offset)		readw(REG_ADDR(bp, offset))
-
-#define REG_WR(bp, offset, val)		writel((u32)val, REG_ADDR(bp, offset))
-#define REG_WR8(bp, offset, val)	writeb((u8)val, REG_ADDR(bp, offset))
-#define REG_WR16(bp, offset, val)	writew((u16)val, REG_ADDR(bp, offset))
-
-#define REG_RD_IND(bp, offset)		bnx2x_reg_rd_ind(bp, offset)
-#define REG_WR_IND(bp, offset, val)	bnx2x_reg_wr_ind(bp, offset, val)
-
-#define REG_RD_DMAE(bp, offset, valp, len32) \
-	do { \
-		bnx2x_read_dmae(bp, offset, len32);\
-		memcpy(valp, bnx2x_sp(bp, wb_data[0]), (len32) * 4); \
-	} while (0)
-
-#define REG_WR_DMAE(bp, offset, valp, len32) \
-	do { \
-		memcpy(bnx2x_sp(bp, wb_data[0]), valp, (len32) * 4); \
-		bnx2x_write_dmae(bp, bnx2x_sp_mapping(bp, wb_data), \
-				 offset, len32); \
-	} while (0)
-
-#define REG_WR_DMAE_LEN(bp, offset, valp, len32) \
-	REG_WR_DMAE(bp, offset, valp, len32)
-
-#define VIRT_WR_DMAE_LEN(bp, data, addr, len32, le32_swap) \
-	do { \
-		memcpy(GUNZIP_BUF(bp), data, (len32) * 4); \
-		bnx2x_write_big_buf_wb(bp, addr, len32); \
-	} while (0)
-
-#define SHMEM_ADDR(bp, field)		(bp->common.shmem_base + \
-					 offsetof(struct shmem_region, field))
-#define SHMEM_RD(bp, field)		REG_RD(bp, SHMEM_ADDR(bp, field))
-#define SHMEM_WR(bp, field, val)	REG_WR(bp, SHMEM_ADDR(bp, field), val)
-
-#define SHMEM2_ADDR(bp, field)		(bp->common.shmem2_base + \
-					 offsetof(struct shmem2_region, field))
-#define SHMEM2_RD(bp, field)		REG_RD(bp, SHMEM2_ADDR(bp, field))
-#define SHMEM2_WR(bp, field, val)	REG_WR(bp, SHMEM2_ADDR(bp, field), val)
-#define MF_CFG_ADDR(bp, field)		(bp->common.mf_cfg_base + \
-					 offsetof(struct mf_cfg, field))
-#define MF2_CFG_ADDR(bp, field)		(bp->common.mf2_cfg_base + \
-					 offsetof(struct mf2_cfg, field))
-
-#define MF_CFG_RD(bp, field)		REG_RD(bp, MF_CFG_ADDR(bp, field))
-#define MF_CFG_WR(bp, field, val)	REG_WR(bp,\
-					       MF_CFG_ADDR(bp, field), (val))
-#define MF2_CFG_RD(bp, field)		REG_RD(bp, MF2_CFG_ADDR(bp, field))
-
-#define SHMEM2_HAS(bp, field)		((bp)->common.shmem2_base &&	\
-					 (SHMEM2_RD((bp), size) >	\
-					 offsetof(struct shmem2_region, field)))
-
-#define EMAC_RD(bp, reg)		REG_RD(bp, emac_base + reg)
-#define EMAC_WR(bp, reg, val)		REG_WR(bp, emac_base + reg, val)
-
-/* SP SB indices */
-
-/* General SP events - stats query, cfc delete, etc  */
-#define HC_SP_INDEX_ETH_DEF_CONS		3
-
-/* EQ completions */
-#define HC_SP_INDEX_EQ_CONS			7
-
-/* FCoE L2 connection completions */
-#define HC_SP_INDEX_ETH_FCOE_TX_CQ_CONS		6
-#define HC_SP_INDEX_ETH_FCOE_RX_CQ_CONS		4
-/* iSCSI L2 */
-#define HC_SP_INDEX_ETH_ISCSI_CQ_CONS		5
-#define HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS	1
-
-/* Special clients parameters */
-
-/* SB indices */
-/* FCoE L2 */
-#define BNX2X_FCOE_L2_RX_INDEX \
-	(&bp->def_status_blk->sp_sb.\
-	index_values[HC_SP_INDEX_ETH_FCOE_RX_CQ_CONS])
-
-#define BNX2X_FCOE_L2_TX_INDEX \
-	(&bp->def_status_blk->sp_sb.\
-	index_values[HC_SP_INDEX_ETH_FCOE_TX_CQ_CONS])
-
-/**
- *  CIDs and CLIDs:
- *  CLIDs below is a CLID for func 0, then the CLID for other
- *  functions will be calculated by the formula:
- *
- *  FUNC_N_CLID_X = N * NUM_SPECIAL_CLIENTS + FUNC_0_CLID_X
- *
- */
-enum {
-	BNX2X_ISCSI_ETH_CL_ID_IDX,
-	BNX2X_FCOE_ETH_CL_ID_IDX,
-	BNX2X_MAX_CNIC_ETH_CL_ID_IDX,
-};
-
-#define BNX2X_CNIC_START_ETH_CID	48
-enum {
-	/* iSCSI L2 */
-	BNX2X_ISCSI_ETH_CID = BNX2X_CNIC_START_ETH_CID,
-	/* FCoE L2 */
-	BNX2X_FCOE_ETH_CID,
-};
-
-/** Additional rings budgeting */
-#ifdef BCM_CNIC
-#define CNIC_PRESENT			1
-#define FCOE_PRESENT			1
-#else
-#define CNIC_PRESENT			0
-#define FCOE_PRESENT			0
-#endif /* BCM_CNIC */
-#define NON_ETH_CONTEXT_USE	(FCOE_PRESENT)
-
-#define AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR \
-	AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR
-
-#define SM_RX_ID			0
-#define SM_TX_ID			1
-
-/* defines for multiple tx priority indices */
-#define FIRST_TX_ONLY_COS_INDEX		1
-#define FIRST_TX_COS_INDEX		0
-
-/* defines for decodeing the fastpath index and the cos index out of the
- * transmission queue index
- */
-#define MAX_TXQS_PER_COS	FP_SB_MAX_E1x
-
-#define TXQ_TO_FP(txq_index)	((txq_index) % MAX_TXQS_PER_COS)
-#define TXQ_TO_COS(txq_index)	((txq_index) / MAX_TXQS_PER_COS)
-
-/* rules for calculating the cids of tx-only connections */
-#define CID_TO_FP(cid)		((cid) % MAX_TXQS_PER_COS)
-#define CID_COS_TO_TX_ONLY_CID(cid, cos)	(cid + cos * MAX_TXQS_PER_COS)
-
-/* fp index inside class of service range */
-#define FP_COS_TO_TXQ(fp, cos)    ((fp)->index + cos * MAX_TXQS_PER_COS)
-
-/*
- * 0..15 eth cos0
- * 16..31 eth cos1 if applicable
- * 32..47 eth cos2 If applicable
- * fcoe queue follows eth queues (16, 32, 48 depending on cos)
- */
-#define MAX_ETH_TXQ_IDX(bp)	(MAX_TXQS_PER_COS * (bp)->max_cos)
-#define FCOE_TXQ_IDX(bp)	(MAX_ETH_TXQ_IDX(bp))
-
-/* fast path */
-struct sw_rx_bd {
-	struct sk_buff	*skb;
-	DEFINE_DMA_UNMAP_ADDR(mapping);
-};
-
-struct sw_tx_bd {
-	struct sk_buff	*skb;
-	u16		first_bd;
-	u8		flags;
-/* Set on the first BD descriptor when there is a split BD */
-#define BNX2X_TSO_SPLIT_BD		(1<<0)
-};
-
-struct sw_rx_page {
-	struct page	*page;
-	DEFINE_DMA_UNMAP_ADDR(mapping);
-};
-
-union db_prod {
-	struct doorbell_set_prod data;
-	u32		raw;
-};
-
-/* dropless fc FW/HW related params */
-#define BRB_SIZE(bp)		(CHIP_IS_E3(bp) ? 1024 : 512)
-#define MAX_AGG_QS(bp)		(CHIP_IS_E1(bp) ? \
-					ETH_MAX_AGGREGATION_QUEUES_E1 :\
-					ETH_MAX_AGGREGATION_QUEUES_E1H_E2)
-#define FW_DROP_LEVEL(bp)	(3 + MAX_SPQ_PENDING + MAX_AGG_QS(bp))
-#define FW_PREFETCH_CNT		16
-#define DROPLESS_FC_HEADROOM	100
-
-/* MC hsi */
-#define BCM_PAGE_SHIFT		12
-#define BCM_PAGE_SIZE		(1 << BCM_PAGE_SHIFT)
-#define BCM_PAGE_MASK		(~(BCM_PAGE_SIZE - 1))
-#define BCM_PAGE_ALIGN(addr)	(((addr) + BCM_PAGE_SIZE - 1) & BCM_PAGE_MASK)
-
-#define PAGES_PER_SGE_SHIFT	0
-#define PAGES_PER_SGE		(1 << PAGES_PER_SGE_SHIFT)
-#define SGE_PAGE_SIZE		PAGE_SIZE
-#define SGE_PAGE_SHIFT		PAGE_SHIFT
-#define SGE_PAGE_ALIGN(addr)	PAGE_ALIGN((typeof(PAGE_SIZE))(addr))
-
-/* SGE ring related macros */
-#define NUM_RX_SGE_PAGES	2
-#define RX_SGE_CNT		(BCM_PAGE_SIZE / sizeof(struct eth_rx_sge))
-#define NEXT_PAGE_SGE_DESC_CNT	2
-#define MAX_RX_SGE_CNT		(RX_SGE_CNT - NEXT_PAGE_SGE_DESC_CNT)
-/* RX_SGE_CNT is promised to be a power of 2 */
-#define RX_SGE_MASK		(RX_SGE_CNT - 1)
-#define NUM_RX_SGE		(RX_SGE_CNT * NUM_RX_SGE_PAGES)
-#define MAX_RX_SGE		(NUM_RX_SGE - 1)
-#define NEXT_SGE_IDX(x)		((((x) & RX_SGE_MASK) == \
-				  (MAX_RX_SGE_CNT - 1)) ? \
-					(x) + 1 + NEXT_PAGE_SGE_DESC_CNT : \
-					(x) + 1)
-#define RX_SGE(x)		((x) & MAX_RX_SGE)
-
-/*
- * Number of required  SGEs is the sum of two:
- * 1. Number of possible opened aggregations (next packet for
- *    these aggregations will probably consume SGE immidiatelly)
- * 2. Rest of BRB blocks divided by 2 (block will consume new SGE only
- *    after placement on BD for new TPA aggregation)
- *
- * Takes into account NEXT_PAGE_SGE_DESC_CNT "next" elements on each page
- */
-#define NUM_SGE_REQ		(MAX_AGG_QS(bp) + \
-					(BRB_SIZE(bp) - MAX_AGG_QS(bp)) / 2)
-#define NUM_SGE_PG_REQ		((NUM_SGE_REQ + MAX_RX_SGE_CNT - 1) / \
-						MAX_RX_SGE_CNT)
-#define SGE_TH_LO(bp)		(NUM_SGE_REQ + \
-				 NUM_SGE_PG_REQ * NEXT_PAGE_SGE_DESC_CNT)
-#define SGE_TH_HI(bp)		(SGE_TH_LO(bp) + DROPLESS_FC_HEADROOM)
-
-/* Manipulate a bit vector defined as an array of u64 */
-
-/* Number of bits in one sge_mask array element */
-#define BIT_VEC64_ELEM_SZ		64
-#define BIT_VEC64_ELEM_SHIFT		6
-#define BIT_VEC64_ELEM_MASK		((u64)BIT_VEC64_ELEM_SZ - 1)
-
-
-#define __BIT_VEC64_SET_BIT(el, bit) \
-	do { \
-		el = ((el) | ((u64)0x1 << (bit))); \
-	} while (0)
-
-#define __BIT_VEC64_CLEAR_BIT(el, bit) \
-	do { \
-		el = ((el) & (~((u64)0x1 << (bit)))); \
-	} while (0)
-
-
-#define BIT_VEC64_SET_BIT(vec64, idx) \
-	__BIT_VEC64_SET_BIT((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT], \
-			   (idx) & BIT_VEC64_ELEM_MASK)
-
-#define BIT_VEC64_CLEAR_BIT(vec64, idx) \
-	__BIT_VEC64_CLEAR_BIT((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT], \
-			     (idx) & BIT_VEC64_ELEM_MASK)
-
-#define BIT_VEC64_TEST_BIT(vec64, idx) \
-	(((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT] >> \
-	((idx) & BIT_VEC64_ELEM_MASK)) & 0x1)
-
-/* Creates a bitmask of all ones in less significant bits.
-   idx - index of the most significant bit in the created mask */
-#define BIT_VEC64_ONES_MASK(idx) \
-		(((u64)0x1 << (((idx) & BIT_VEC64_ELEM_MASK) + 1)) - 1)
-#define BIT_VEC64_ELEM_ONE_MASK	((u64)(~0))
-
-/*******************************************************/
-
-
-
-/* Number of u64 elements in SGE mask array */
-#define RX_SGE_MASK_LEN			((NUM_RX_SGE_PAGES * RX_SGE_CNT) / \
-					 BIT_VEC64_ELEM_SZ)
-#define RX_SGE_MASK_LEN_MASK		(RX_SGE_MASK_LEN - 1)
-#define NEXT_SGE_MASK_ELEM(el)		(((el) + 1) & RX_SGE_MASK_LEN_MASK)
-
-union host_hc_status_block {
-	/* pointer to fp status block e1x */
-	struct host_hc_status_block_e1x *e1x_sb;
-	/* pointer to fp status block e2 */
-	struct host_hc_status_block_e2  *e2_sb;
-};
-
-struct bnx2x_agg_info {
-	/*
-	 * First aggregation buffer is an skb, the following - are pages.
-	 * We will preallocate the skbs for each aggregation when
-	 * we open the interface and will replace the BD at the consumer
-	 * with this one when we receive the TPA_START CQE in order to
-	 * keep the Rx BD ring consistent.
-	 */
-	struct sw_rx_bd		first_buf;
-	u8			tpa_state;
-#define BNX2X_TPA_START			1
-#define BNX2X_TPA_STOP			2
-#define BNX2X_TPA_ERROR			3
-	u8			placement_offset;
-	u16			parsing_flags;
-	u16			vlan_tag;
-	u16			len_on_bd;
-};
-
-#define Q_STATS_OFFSET32(stat_name) \
-			(offsetof(struct bnx2x_eth_q_stats, stat_name) / 4)
-
-struct bnx2x_fp_txdata {
-
-	struct sw_tx_bd		*tx_buf_ring;
-
-	union eth_tx_bd_types	*tx_desc_ring;
-	dma_addr_t		tx_desc_mapping;
-
-	u32			cid;
-
-	union db_prod		tx_db;
-
-	u16			tx_pkt_prod;
-	u16			tx_pkt_cons;
-	u16			tx_bd_prod;
-	u16			tx_bd_cons;
-
-	unsigned long		tx_pkt;
-
-	__le16			*tx_cons_sb;
-
-	int			txq_index;
-};
-
-struct bnx2x_fastpath {
-	struct bnx2x		*bp; /* parent */
-
-#define BNX2X_NAPI_WEIGHT       128
-	struct napi_struct	napi;
-	union host_hc_status_block	status_blk;
-	/* chip independed shortcuts into sb structure */
-	__le16			*sb_index_values;
-	__le16			*sb_running_index;
-	/* chip independed shortcut into rx_prods_offset memory */
-	u32			ustorm_rx_prods_offset;
-
-	u32			rx_buf_size;
-
-	dma_addr_t		status_blk_mapping;
-
-	u8			max_cos; /* actual number of active tx coses */
-	struct bnx2x_fp_txdata	txdata[BNX2X_MULTI_TX_COS];
-
-	struct sw_rx_bd		*rx_buf_ring;	/* BDs mappings ring */
-	struct sw_rx_page	*rx_page_ring;	/* SGE pages mappings ring */
-
-	struct eth_rx_bd	*rx_desc_ring;
-	dma_addr_t		rx_desc_mapping;
-
-	union eth_rx_cqe	*rx_comp_ring;
-	dma_addr_t		rx_comp_mapping;
-
-	/* SGE ring */
-	struct eth_rx_sge	*rx_sge_ring;
-	dma_addr_t		rx_sge_mapping;
-
-	u64			sge_mask[RX_SGE_MASK_LEN];
-
-	u32			cid;
-
-	__le16			fp_hc_idx;
-
-	u8			index;		/* number in fp array */
-	u8			cl_id;		/* eth client id */
-	u8			cl_qzone_id;
-	u8			fw_sb_id;	/* status block number in FW */
-	u8			igu_sb_id;	/* status block number in HW */
-
-	u16			rx_bd_prod;
-	u16			rx_bd_cons;
-	u16			rx_comp_prod;
-	u16			rx_comp_cons;
-	u16			rx_sge_prod;
-	/* The last maximal completed SGE */
-	u16			last_max_sge;
-	__le16			*rx_cons_sb;
-	unsigned long		rx_pkt,
-				rx_calls;
-
-	/* TPA related */
-	struct bnx2x_agg_info	tpa_info[ETH_MAX_AGGREGATION_QUEUES_E1H_E2];
-	u8			disable_tpa;
-#ifdef BNX2X_STOP_ON_ERROR
-	u64			tpa_queue_used;
-#endif
-
-	struct tstorm_per_queue_stats old_tclient;
-	struct ustorm_per_queue_stats old_uclient;
-	struct xstorm_per_queue_stats old_xclient;
-	struct bnx2x_eth_q_stats eth_q_stats;
-
-	/* The size is calculated using the following:
-	     sizeof name field from netdev structure +
-	     4 ('-Xx-' string) +
-	     4 (for the digits and to make it DWORD aligned) */
-#define FP_NAME_SIZE		(sizeof(((struct net_device *)0)->name) + 8)
-	char			name[FP_NAME_SIZE];
-
-	/* MACs object */
-	struct bnx2x_vlan_mac_obj mac_obj;
-
-	/* Queue State object */
-	struct bnx2x_queue_sp_obj q_obj;
-
-};
-
-#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
-
-/* FCoE L2 `fastpath' entry is right after the eth entries */
-#define FCOE_IDX			BNX2X_NUM_ETH_QUEUES(bp)
-#define bnx2x_fcoe_fp(bp)		(&bp->fp[FCOE_IDX])
-#define bnx2x_fcoe(bp, var)		(bnx2x_fcoe_fp(bp)->var)
-#define bnx2x_fcoe_tx(bp, var)		(bnx2x_fcoe_fp(bp)-> \
-						txdata[FIRST_TX_COS_INDEX].var)
-
-
-#define IS_ETH_FP(fp)			(fp->index < \
-					 BNX2X_NUM_ETH_QUEUES(fp->bp))
-#ifdef BCM_CNIC
-#define IS_FCOE_FP(fp)			(fp->index == FCOE_IDX)
-#define IS_FCOE_IDX(idx)		((idx) == FCOE_IDX)
-#else
-#define IS_FCOE_FP(fp)		false
-#define IS_FCOE_IDX(idx)	false
-#endif
-
-
-/* MC hsi */
-#define MAX_FETCH_BD		13	/* HW max BDs per packet */
-#define RX_COPY_THRESH		92
-
-#define NUM_TX_RINGS		16
-#define TX_DESC_CNT		(BCM_PAGE_SIZE / sizeof(union eth_tx_bd_types))
-#define NEXT_PAGE_TX_DESC_CNT	1
-#define MAX_TX_DESC_CNT		(TX_DESC_CNT - NEXT_PAGE_TX_DESC_CNT)
-#define NUM_TX_BD		(TX_DESC_CNT * NUM_TX_RINGS)
-#define MAX_TX_BD		(NUM_TX_BD - 1)
-#define MAX_TX_AVAIL		(MAX_TX_DESC_CNT * NUM_TX_RINGS - 2)
-#define NEXT_TX_IDX(x)		((((x) & MAX_TX_DESC_CNT) == \
-				  (MAX_TX_DESC_CNT - 1)) ? \
-					(x) + 1 + NEXT_PAGE_TX_DESC_CNT : \
-					(x) + 1)
-#define TX_BD(x)		((x) & MAX_TX_BD)
-#define TX_BD_POFF(x)		((x) & MAX_TX_DESC_CNT)
-
-/* The RX BD ring is special, each bd is 8 bytes but the last one is 16 */
-#define NUM_RX_RINGS		8
-#define RX_DESC_CNT		(BCM_PAGE_SIZE / sizeof(struct eth_rx_bd))
-#define NEXT_PAGE_RX_DESC_CNT	2
-#define MAX_RX_DESC_CNT		(RX_DESC_CNT - NEXT_PAGE_RX_DESC_CNT)
-#define RX_DESC_MASK		(RX_DESC_CNT - 1)
-#define NUM_RX_BD		(RX_DESC_CNT * NUM_RX_RINGS)
-#define MAX_RX_BD		(NUM_RX_BD - 1)
-#define MAX_RX_AVAIL		(MAX_RX_DESC_CNT * NUM_RX_RINGS - 2)
-
-/* dropless fc calculations for BDs
- *
- * Number of BDs should as number of buffers in BRB:
- * Low threshold takes into account NEXT_PAGE_RX_DESC_CNT
- * "next" elements on each page
- */
-#define NUM_BD_REQ		BRB_SIZE(bp)
-#define NUM_BD_PG_REQ		((NUM_BD_REQ + MAX_RX_DESC_CNT - 1) / \
-					      MAX_RX_DESC_CNT)
-#define BD_TH_LO(bp)		(NUM_BD_REQ + \
-				 NUM_BD_PG_REQ * NEXT_PAGE_RX_DESC_CNT + \
-				 FW_DROP_LEVEL(bp))
-#define BD_TH_HI(bp)		(BD_TH_LO(bp) + DROPLESS_FC_HEADROOM)
-
-#define MIN_RX_AVAIL		((bp)->dropless_fc ? BD_TH_HI(bp) + 128 : 128)
-
-#define MIN_RX_SIZE_TPA_HW	(CHIP_IS_E1(bp) ? \
-					ETH_MIN_RX_CQES_WITH_TPA_E1 : \
-					ETH_MIN_RX_CQES_WITH_TPA_E1H_E2)
-#define MIN_RX_SIZE_NONTPA_HW   ETH_MIN_RX_CQES_WITHOUT_TPA
-#define MIN_RX_SIZE_TPA		(max_t(u32, MIN_RX_SIZE_TPA_HW, MIN_RX_AVAIL))
-#define MIN_RX_SIZE_NONTPA	(max_t(u32, MIN_RX_SIZE_NONTPA_HW,\
-								MIN_RX_AVAIL))
-
-#define NEXT_RX_IDX(x)		((((x) & RX_DESC_MASK) == \
-				  (MAX_RX_DESC_CNT - 1)) ? \
-					(x) + 1 + NEXT_PAGE_RX_DESC_CNT : \
-					(x) + 1)
-#define RX_BD(x)		((x) & MAX_RX_BD)
-
-/*
- * As long as CQE is X times bigger than BD entry we have to allocate X times
- * more pages for CQ ring in order to keep it balanced with BD ring
- */
-#define CQE_BD_REL	(sizeof(union eth_rx_cqe) / sizeof(struct eth_rx_bd))
-#define NUM_RCQ_RINGS		(NUM_RX_RINGS * CQE_BD_REL)
-#define RCQ_DESC_CNT		(BCM_PAGE_SIZE / sizeof(union eth_rx_cqe))
-#define NEXT_PAGE_RCQ_DESC_CNT	1
-#define MAX_RCQ_DESC_CNT	(RCQ_DESC_CNT - NEXT_PAGE_RCQ_DESC_CNT)
-#define NUM_RCQ_BD		(RCQ_DESC_CNT * NUM_RCQ_RINGS)
-#define MAX_RCQ_BD		(NUM_RCQ_BD - 1)
-#define MAX_RCQ_AVAIL		(MAX_RCQ_DESC_CNT * NUM_RCQ_RINGS - 2)
-#define NEXT_RCQ_IDX(x)		((((x) & MAX_RCQ_DESC_CNT) == \
-				  (MAX_RCQ_DESC_CNT - 1)) ? \
-					(x) + 1 + NEXT_PAGE_RCQ_DESC_CNT : \
-					(x) + 1)
-#define RCQ_BD(x)		((x) & MAX_RCQ_BD)
-
-/* dropless fc calculations for RCQs
- *
- * Number of RCQs should be as number of buffers in BRB:
- * Low threshold takes into account NEXT_PAGE_RCQ_DESC_CNT
- * "next" elements on each page
- */
-#define NUM_RCQ_REQ		BRB_SIZE(bp)
-#define NUM_RCQ_PG_REQ		((NUM_BD_REQ + MAX_RCQ_DESC_CNT - 1) / \
-					      MAX_RCQ_DESC_CNT)
-#define RCQ_TH_LO(bp)		(NUM_RCQ_REQ + \
-				 NUM_RCQ_PG_REQ * NEXT_PAGE_RCQ_DESC_CNT + \
-				 FW_DROP_LEVEL(bp))
-#define RCQ_TH_HI(bp)		(RCQ_TH_LO(bp) + DROPLESS_FC_HEADROOM)
-
-
-/* This is needed for determining of last_max */
-#define SUB_S16(a, b)		(s16)((s16)(a) - (s16)(b))
-#define SUB_S32(a, b)		(s32)((s32)(a) - (s32)(b))
-
-
-#define BNX2X_SWCID_SHIFT	17
-#define BNX2X_SWCID_MASK	((0x1 << BNX2X_SWCID_SHIFT) - 1)
-
-/* used on a CID received from the HW */
-#define SW_CID(x)			(le32_to_cpu(x) & BNX2X_SWCID_MASK)
-#define CQE_CMD(x)			(le32_to_cpu(x) >> \
-					COMMON_RAMROD_ETH_RX_CQE_CMD_ID_SHIFT)
-
-#define BD_UNMAP_ADDR(bd)		HILO_U64(le32_to_cpu((bd)->addr_hi), \
-						 le32_to_cpu((bd)->addr_lo))
-#define BD_UNMAP_LEN(bd)		(le16_to_cpu((bd)->nbytes))
-
-#define BNX2X_DB_MIN_SHIFT		3	/* 8 bytes */
-#define BNX2X_DB_SHIFT			7	/* 128 bytes*/
-#if (BNX2X_DB_SHIFT < BNX2X_DB_MIN_SHIFT)
-#error "Min DB doorbell stride is 8"
-#endif
-#define DPM_TRIGER_TYPE			0x40
-#define DOORBELL(bp, cid, val) \
-	do { \
-		writel((u32)(val), bp->doorbells + (bp->db_size * (cid)) + \
-		       DPM_TRIGER_TYPE); \
-	} while (0)
-
-
-/* TX CSUM helpers */
-#define SKB_CS_OFF(skb)		(offsetof(struct tcphdr, check) - \
-				 skb->csum_offset)
-#define SKB_CS(skb)		(*(u16 *)(skb_transport_header(skb) + \
-					  skb->csum_offset))
-
-#define pbd_tcp_flags(skb)	(ntohl(tcp_flag_word(tcp_hdr(skb)))>>16 & 0xff)
-
-#define XMIT_PLAIN			0
-#define XMIT_CSUM_V4			0x1
-#define XMIT_CSUM_V6			0x2
-#define XMIT_CSUM_TCP			0x4
-#define XMIT_GSO_V4			0x8
-#define XMIT_GSO_V6			0x10
-
-#define XMIT_CSUM			(XMIT_CSUM_V4 | XMIT_CSUM_V6)
-#define XMIT_GSO			(XMIT_GSO_V4 | XMIT_GSO_V6)
-
-
-/* stuff added to make the code fit 80Col */
-#define CQE_TYPE(cqe_fp_flags)	 ((cqe_fp_flags) & ETH_FAST_PATH_RX_CQE_TYPE)
-#define CQE_TYPE_START(cqe_type) ((cqe_type) == RX_ETH_CQE_TYPE_ETH_START_AGG)
-#define CQE_TYPE_STOP(cqe_type)  ((cqe_type) == RX_ETH_CQE_TYPE_ETH_STOP_AGG)
-#define CQE_TYPE_SLOW(cqe_type)  ((cqe_type) == RX_ETH_CQE_TYPE_ETH_RAMROD)
-#define CQE_TYPE_FAST(cqe_type)  ((cqe_type) == RX_ETH_CQE_TYPE_ETH_FASTPATH)
-
-#define ETH_RX_ERROR_FALGS		ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG
-
-#define BNX2X_IP_CSUM_ERR(cqe) \
-			(!((cqe)->fast_path_cqe.status_flags & \
-			   ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG) && \
-			 ((cqe)->fast_path_cqe.type_error_flags & \
-			  ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG))
-
-#define BNX2X_L4_CSUM_ERR(cqe) \
-			(!((cqe)->fast_path_cqe.status_flags & \
-			   ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG) && \
-			 ((cqe)->fast_path_cqe.type_error_flags & \
-			  ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG))
-
-#define BNX2X_RX_CSUM_OK(cqe) \
-			(!(BNX2X_L4_CSUM_ERR(cqe) || BNX2X_IP_CSUM_ERR(cqe)))
-
-#define BNX2X_PRS_FLAG_OVERETH_IPV4(flags) \
-				(((le16_to_cpu(flags) & \
-				   PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) >> \
-				  PARSING_FLAGS_OVER_ETHERNET_PROTOCOL_SHIFT) \
-				 == PRS_FLAG_OVERETH_IPV4)
-#define BNX2X_RX_SUM_FIX(cqe) \
-	BNX2X_PRS_FLAG_OVERETH_IPV4(cqe->fast_path_cqe.pars_flags.flags)
-
-
-#define FP_USB_FUNC_OFF	\
-			offsetof(struct cstorm_status_block_u, func)
-#define FP_CSB_FUNC_OFF	\
-			offsetof(struct cstorm_status_block_c, func)
-
-#define HC_INDEX_ETH_RX_CQ_CONS		1
-
-#define HC_INDEX_OOO_TX_CQ_CONS		4
-
-#define HC_INDEX_ETH_TX_CQ_CONS_COS0	5
-
-#define HC_INDEX_ETH_TX_CQ_CONS_COS1	6
-
-#define HC_INDEX_ETH_TX_CQ_CONS_COS2	7
-
-#define HC_INDEX_ETH_FIRST_TX_CQ_CONS	HC_INDEX_ETH_TX_CQ_CONS_COS0
-
-#define BNX2X_RX_SB_INDEX \
-	(&fp->sb_index_values[HC_INDEX_ETH_RX_CQ_CONS])
-
-#define BNX2X_TX_SB_INDEX_BASE BNX2X_TX_SB_INDEX_COS0
-
-#define BNX2X_TX_SB_INDEX_COS0 \
-	(&fp->sb_index_values[HC_INDEX_ETH_TX_CQ_CONS_COS0])
-
-/* end of fast path */
-
-/* common */
-
-struct bnx2x_common {
-
-	u32			chip_id;
-/* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
-#define CHIP_ID(bp)			(bp->common.chip_id & 0xfffffff0)
-
-#define CHIP_NUM(bp)			(bp->common.chip_id >> 16)
-#define CHIP_NUM_57710			0x164e
-#define CHIP_NUM_57711			0x164f
-#define CHIP_NUM_57711E			0x1650
-#define CHIP_NUM_57712			0x1662
-#define CHIP_NUM_57712_MF		0x1663
-#define CHIP_NUM_57713			0x1651
-#define CHIP_NUM_57713E			0x1652
-#define CHIP_NUM_57800			0x168a
-#define CHIP_NUM_57800_MF		0x16a5
-#define CHIP_NUM_57810			0x168e
-#define CHIP_NUM_57810_MF		0x16ae
-#define CHIP_NUM_57840			0x168d
-#define CHIP_NUM_57840_MF		0x16ab
-#define CHIP_IS_E1(bp)			(CHIP_NUM(bp) == CHIP_NUM_57710)
-#define CHIP_IS_57711(bp)		(CHIP_NUM(bp) == CHIP_NUM_57711)
-#define CHIP_IS_57711E(bp)		(CHIP_NUM(bp) == CHIP_NUM_57711E)
-#define CHIP_IS_57712(bp)		(CHIP_NUM(bp) == CHIP_NUM_57712)
-#define CHIP_IS_57712_MF(bp)		(CHIP_NUM(bp) == CHIP_NUM_57712_MF)
-#define CHIP_IS_57800(bp)		(CHIP_NUM(bp) == CHIP_NUM_57800)
-#define CHIP_IS_57800_MF(bp)		(CHIP_NUM(bp) == CHIP_NUM_57800_MF)
-#define CHIP_IS_57810(bp)		(CHIP_NUM(bp) == CHIP_NUM_57810)
-#define CHIP_IS_57810_MF(bp)		(CHIP_NUM(bp) == CHIP_NUM_57810_MF)
-#define CHIP_IS_57840(bp)		(CHIP_NUM(bp) == CHIP_NUM_57840)
-#define CHIP_IS_57840_MF(bp)		(CHIP_NUM(bp) == CHIP_NUM_57840_MF)
-#define CHIP_IS_E1H(bp)			(CHIP_IS_57711(bp) || \
-					 CHIP_IS_57711E(bp))
-#define CHIP_IS_E2(bp)			(CHIP_IS_57712(bp) || \
-					 CHIP_IS_57712_MF(bp))
-#define CHIP_IS_E3(bp)			(CHIP_IS_57800(bp) || \
-					 CHIP_IS_57800_MF(bp) || \
-					 CHIP_IS_57810(bp) || \
-					 CHIP_IS_57810_MF(bp) || \
-					 CHIP_IS_57840(bp) || \
-					 CHIP_IS_57840_MF(bp))
-#define CHIP_IS_E1x(bp)			(CHIP_IS_E1((bp)) || CHIP_IS_E1H((bp)))
-#define USES_WARPCORE(bp)		(CHIP_IS_E3(bp))
-#define IS_E1H_OFFSET			(!CHIP_IS_E1(bp))
-
-#define CHIP_REV_SHIFT			12
-#define CHIP_REV_MASK			(0xF << CHIP_REV_SHIFT)
-#define CHIP_REV_VAL(bp)		(bp->common.chip_id & CHIP_REV_MASK)
-#define CHIP_REV_Ax			(0x0 << CHIP_REV_SHIFT)
-#define CHIP_REV_Bx			(0x1 << CHIP_REV_SHIFT)
-/* assume maximum 5 revisions */
-#define CHIP_REV_IS_SLOW(bp)		(CHIP_REV_VAL(bp) > 0x00005000)
-/* Emul versions are A=>0xe, B=>0xc, C=>0xa, D=>8, E=>6 */
-#define CHIP_REV_IS_EMUL(bp)		((CHIP_REV_IS_SLOW(bp)) && \
-					 !(CHIP_REV_VAL(bp) & 0x00001000))
-/* FPGA versions are A=>0xf, B=>0xd, C=>0xb, D=>9, E=>7 */
-#define CHIP_REV_IS_FPGA(bp)		((CHIP_REV_IS_SLOW(bp)) && \
-					 (CHIP_REV_VAL(bp) & 0x00001000))
-
-#define CHIP_TIME(bp)			((CHIP_REV_IS_EMUL(bp)) ? 2000 : \
-					((CHIP_REV_IS_FPGA(bp)) ? 200 : 1))
-
-#define CHIP_METAL(bp)			(bp->common.chip_id & 0x00000ff0)
-#define CHIP_BOND_ID(bp)		(bp->common.chip_id & 0x0000000f)
-#define CHIP_REV_SIM(bp)		(((CHIP_REV_MASK - CHIP_REV_VAL(bp)) >>\
-					   (CHIP_REV_SHIFT + 1)) \
-						<< CHIP_REV_SHIFT)
-#define CHIP_REV(bp)			(CHIP_REV_IS_SLOW(bp) ? \
-						CHIP_REV_SIM(bp) :\
-						CHIP_REV_VAL(bp))
-#define CHIP_IS_E3B0(bp)		(CHIP_IS_E3(bp) && \
-					 (CHIP_REV(bp) == CHIP_REV_Bx))
-#define CHIP_IS_E3A0(bp)		(CHIP_IS_E3(bp) && \
-					 (CHIP_REV(bp) == CHIP_REV_Ax))
-
-	int			flash_size;
-#define BNX2X_NVRAM_1MB_SIZE			0x20000	/* 1M bit in bytes */
-#define BNX2X_NVRAM_TIMEOUT_COUNT		30000
-#define BNX2X_NVRAM_PAGE_SIZE			256
-
-	u32			shmem_base;
-	u32			shmem2_base;
-	u32			mf_cfg_base;
-	u32			mf2_cfg_base;
-
-	u32			hw_config;
-
-	u32			bc_ver;
-
-	u8			int_block;
-#define INT_BLOCK_HC			0
-#define INT_BLOCK_IGU			1
-#define INT_BLOCK_MODE_NORMAL		0
-#define INT_BLOCK_MODE_BW_COMP		2
-#define CHIP_INT_MODE_IS_NBC(bp)		\
-			(!CHIP_IS_E1x(bp) &&	\
-			!((bp)->common.int_block & INT_BLOCK_MODE_BW_COMP))
-#define CHIP_INT_MODE_IS_BC(bp) (!CHIP_INT_MODE_IS_NBC(bp))
-
-	u8			chip_port_mode;
-#define CHIP_4_PORT_MODE			0x0
-#define CHIP_2_PORT_MODE			0x1
-#define CHIP_PORT_MODE_NONE			0x2
-#define CHIP_MODE(bp)			(bp->common.chip_port_mode)
-#define CHIP_MODE_IS_4_PORT(bp) (CHIP_MODE(bp) == CHIP_4_PORT_MODE)
-};
-
-/* IGU MSIX STATISTICS on 57712: 64 for VFs; 4 for PFs; 4 for Attentions */
-#define BNX2X_IGU_STAS_MSG_VF_CNT 64
-#define BNX2X_IGU_STAS_MSG_PF_CNT 4
-
-/* end of common */
-
-/* port */
-
-struct bnx2x_port {
-	u32			pmf;
-
-	u32			link_config[LINK_CONFIG_SIZE];
-
-	u32			supported[LINK_CONFIG_SIZE];
-/* link settings - missing defines */
-#define SUPPORTED_2500baseX_Full	(1 << 15)
-
-	u32			advertising[LINK_CONFIG_SIZE];
-/* link settings - missing defines */
-#define ADVERTISED_2500baseX_Full	(1 << 15)
-
-	u32			phy_addr;
-
-	/* used to synchronize phy accesses */
-	struct mutex		phy_mutex;
-	int			need_hw_lock;
-
-	u32			port_stx;
-
-	struct nig_stats	old_nig_stats;
-};
-
-/* end of port */
-
-#define STATS_OFFSET32(stat_name) \
-			(offsetof(struct bnx2x_eth_stats, stat_name) / 4)
-
-/* slow path */
-
-/* slow path work-queue */
-extern struct workqueue_struct *bnx2x_wq;
-
-#define BNX2X_MAX_NUM_OF_VFS	64
-#define BNX2X_VF_ID_INVALID	0xFF
-
-/*
- * The total number of L2 queues, MSIX vectors and HW contexts (CIDs) is
- * control by the number of fast-path status blocks supported by the
- * device (HW/FW). Each fast-path status block (FP-SB) aka non-default
- * status block represents an independent interrupts context that can
- * serve a regular L2 networking queue. However special L2 queues such
- * as the FCoE queue do not require a FP-SB and other components like
- * the CNIC may consume FP-SB reducing the number of possible L2 queues
- *
- * If the maximum number of FP-SB available is X then:
- * a. If CNIC is supported it consumes 1 FP-SB thus the max number of
- *    regular L2 queues is Y=X-1
- * b. in MF mode the actual number of L2 queues is Y= (X-1/MF_factor)
- * c. If the FCoE L2 queue is supported the actual number of L2 queues
- *    is Y+1
- * d. The number of irqs (MSIX vectors) is either Y+1 (one extra for
- *    slow-path interrupts) or Y+2 if CNIC is supported (one additional
- *    FP interrupt context for the CNIC).
- * e. The number of HW context (CID count) is always X or X+1 if FCoE
- *    L2 queue is supported. the cid for the FCoE L2 queue is always X.
- */
-
-/* fast-path interrupt contexts E1x */
-#define FP_SB_MAX_E1x		16
-/* fast-path interrupt contexts E2 */
-#define FP_SB_MAX_E2		HC_SB_MAX_SB_E2
-
-union cdu_context {
-	struct eth_context eth;
-	char pad[1024];
-};
-
-/* CDU host DB constants */
-#define CDU_ILT_PAGE_SZ_HW	3
-#define CDU_ILT_PAGE_SZ		(8192 << CDU_ILT_PAGE_SZ_HW) /* 64K */
-#define ILT_PAGE_CIDS		(CDU_ILT_PAGE_SZ / sizeof(union cdu_context))
-
-#ifdef BCM_CNIC
-#define CNIC_ISCSI_CID_MAX	256
-#define CNIC_FCOE_CID_MAX	2048
-#define CNIC_CID_MAX		(CNIC_ISCSI_CID_MAX + CNIC_FCOE_CID_MAX)
-#define CNIC_ILT_LINES		DIV_ROUND_UP(CNIC_CID_MAX, ILT_PAGE_CIDS)
-#endif
-
-#define QM_ILT_PAGE_SZ_HW	0
-#define QM_ILT_PAGE_SZ		(4096 << QM_ILT_PAGE_SZ_HW) /* 4K */
-#define QM_CID_ROUND		1024
-
-#ifdef BCM_CNIC
-/* TM (timers) host DB constants */
-#define TM_ILT_PAGE_SZ_HW	0
-#define TM_ILT_PAGE_SZ		(4096 << TM_ILT_PAGE_SZ_HW) /* 4K */
-/* #define TM_CONN_NUM		(CNIC_STARTING_CID+CNIC_ISCSI_CXT_MAX) */
-#define TM_CONN_NUM		1024
-#define TM_ILT_SZ		(8 * TM_CONN_NUM)
-#define TM_ILT_LINES		DIV_ROUND_UP(TM_ILT_SZ, TM_ILT_PAGE_SZ)
-
-/* SRC (Searcher) host DB constants */
-#define SRC_ILT_PAGE_SZ_HW	0
-#define SRC_ILT_PAGE_SZ		(4096 << SRC_ILT_PAGE_SZ_HW) /* 4K */
-#define SRC_HASH_BITS		10
-#define SRC_CONN_NUM		(1 << SRC_HASH_BITS) /* 1024 */
-#define SRC_ILT_SZ		(sizeof(struct src_ent) * SRC_CONN_NUM)
-#define SRC_T2_SZ		SRC_ILT_SZ
-#define SRC_ILT_LINES		DIV_ROUND_UP(SRC_ILT_SZ, SRC_ILT_PAGE_SZ)
-
-#endif
-
-#define MAX_DMAE_C		8
-
-/* DMA memory not used in fastpath */
-struct bnx2x_slowpath {
-	union {
-		struct mac_configuration_cmd		e1x;
-		struct eth_classify_rules_ramrod_data	e2;
-	} mac_rdata;
-
-
-	union {
-		struct tstorm_eth_mac_filter_config	e1x;
-		struct eth_filter_rules_ramrod_data	e2;
-	} rx_mode_rdata;
-
-	union {
-		struct mac_configuration_cmd		e1;
-		struct eth_multicast_rules_ramrod_data  e2;
-	} mcast_rdata;
-
-	struct eth_rss_update_ramrod_data	rss_rdata;
-
-	/* Queue State related ramrods are always sent under rtnl_lock */
-	union {
-		struct client_init_ramrod_data  init_data;
-		struct client_update_ramrod_data update_data;
-	} q_rdata;
-
-	union {
-		struct function_start_data	func_start;
-		/* pfc configuration for DCBX ramrod */
-		struct flow_control_configuration pfc_config;
-	} func_rdata;
-
-	/* used by dmae command executer */
-	struct dmae_command		dmae[MAX_DMAE_C];
-
-	u32				stats_comp;
-	union mac_stats			mac_stats;
-	struct nig_stats		nig_stats;
-	struct host_port_stats		port_stats;
-	struct host_func_stats		func_stats;
-	struct host_func_stats		func_stats_base;
-
-	u32				wb_comp;
-	u32				wb_data[4];
-};
-
-#define bnx2x_sp(bp, var)		(&bp->slowpath->var)
-#define bnx2x_sp_mapping(bp, var) \
-		(bp->slowpath_mapping + offsetof(struct bnx2x_slowpath, var))
-
-
-/* attn group wiring */
-#define MAX_DYNAMIC_ATTN_GRPS		8
-
-struct attn_route {
-	u32 sig[5];
-};
-
-struct iro {
-	u32 base;
-	u16 m1;
-	u16 m2;
-	u16 m3;
-	u16 size;
-};
-
-struct hw_context {
-	union cdu_context *vcxt;
-	dma_addr_t cxt_mapping;
-	size_t size;
-};
-
-/* forward */
-struct bnx2x_ilt;
-
-
-enum bnx2x_recovery_state {
-	BNX2X_RECOVERY_DONE,
-	BNX2X_RECOVERY_INIT,
-	BNX2X_RECOVERY_WAIT,
-	BNX2X_RECOVERY_FAILED
-};
-
-/*
- * Event queue (EQ or event ring) MC hsi
- * NUM_EQ_PAGES and EQ_DESC_CNT_PAGE must be power of 2
- */
-#define NUM_EQ_PAGES		1
-#define EQ_DESC_CNT_PAGE	(BCM_PAGE_SIZE / sizeof(union event_ring_elem))
-#define EQ_DESC_MAX_PAGE	(EQ_DESC_CNT_PAGE - 1)
-#define NUM_EQ_DESC		(EQ_DESC_CNT_PAGE * NUM_EQ_PAGES)
-#define EQ_DESC_MASK		(NUM_EQ_DESC - 1)
-#define MAX_EQ_AVAIL		(EQ_DESC_MAX_PAGE * NUM_EQ_PAGES - 2)
-
-/* depends on EQ_DESC_CNT_PAGE being a power of 2 */
-#define NEXT_EQ_IDX(x)		((((x) & EQ_DESC_MAX_PAGE) == \
-				  (EQ_DESC_MAX_PAGE - 1)) ? (x) + 2 : (x) + 1)
-
-/* depends on the above and on NUM_EQ_PAGES being a power of 2 */
-#define EQ_DESC(x)		((x) & EQ_DESC_MASK)
-
-#define BNX2X_EQ_INDEX \
-	(&bp->def_status_blk->sp_sb.\
-	index_values[HC_SP_INDEX_EQ_CONS])
-
-/* This is a data that will be used to create a link report message.
- * We will keep the data used for the last link report in order
- * to prevent reporting the same link parameters twice.
- */
-struct bnx2x_link_report_data {
-	u16 line_speed;			/* Effective line speed */
-	unsigned long link_report_flags;/* BNX2X_LINK_REPORT_XXX flags */
-};
-
-enum {
-	BNX2X_LINK_REPORT_FD,		/* Full DUPLEX */
-	BNX2X_LINK_REPORT_LINK_DOWN,
-	BNX2X_LINK_REPORT_RX_FC_ON,
-	BNX2X_LINK_REPORT_TX_FC_ON,
-};
-
-enum {
-	BNX2X_PORT_QUERY_IDX,
-	BNX2X_PF_QUERY_IDX,
-	BNX2X_FIRST_QUEUE_QUERY_IDX,
-};
-
-struct bnx2x_fw_stats_req {
-	struct stats_query_header hdr;
-	struct stats_query_entry query[STATS_QUERY_CMD_COUNT];
-};
-
-struct bnx2x_fw_stats_data {
-	struct stats_counter	storm_counters;
-	struct per_port_stats	port;
-	struct per_pf_stats	pf;
-	struct per_queue_stats  queue_stats[1];
-};
-
-/* Public slow path states */
-enum {
-	BNX2X_SP_RTNL_SETUP_TC,
-	BNX2X_SP_RTNL_TX_TIMEOUT,
-};
-
-
-struct bnx2x {
-	/* Fields used in the tx and intr/napi performance paths
-	 * are grouped together in the beginning of the structure
-	 */
-	struct bnx2x_fastpath	*fp;
-	void __iomem		*regview;
-	void __iomem		*doorbells;
-	u16			db_size;
-
-	u8			pf_num;	/* absolute PF number */
-	u8			pfid;	/* per-path PF number */
-	int			base_fw_ndsb; /**/
-#define BP_PATH(bp)			(CHIP_IS_E1x(bp) ? 0 : (bp->pf_num & 1))
-#define BP_PORT(bp)			(bp->pfid & 1)
-#define BP_FUNC(bp)			(bp->pfid)
-#define BP_ABS_FUNC(bp)			(bp->pf_num)
-#define BP_VN(bp)			((bp)->pfid >> 1)
-#define BP_MAX_VN_NUM(bp)		(CHIP_MODE_IS_4_PORT(bp) ? 2 : 4)
-#define BP_L_ID(bp)			(BP_VN(bp) << 2)
-#define BP_FW_MB_IDX_VN(bp, vn)		(BP_PORT(bp) +\
-	  (vn) * ((CHIP_IS_E1x(bp) || (CHIP_MODE_IS_4_PORT(bp))) ? 2  : 1))
-#define BP_FW_MB_IDX(bp)		BP_FW_MB_IDX_VN(bp, BP_VN(bp))
-
-	struct net_device	*dev;
-	struct pci_dev		*pdev;
-
-	const struct iro	*iro_arr;
-#define IRO (bp->iro_arr)
-
-	enum bnx2x_recovery_state recovery_state;
-	int			is_leader;
-	struct msix_entry	*msix_table;
-
-	int			tx_ring_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
-#define ETH_MAX_PACKET_SIZE		1500
-#define ETH_MAX_JUMBO_PACKET_SIZE	9600
-
-	/* Max supported alignment is 256 (8 shift) */
-#define BNX2X_RX_ALIGN_SHIFT		((L1_CACHE_SHIFT < 8) ? \
-					 L1_CACHE_SHIFT : 8)
-	/* FW use 2 Cache lines Alignment for start packet and size  */
-#define BNX2X_FW_RX_ALIGN		(2 << BNX2X_RX_ALIGN_SHIFT)
-#define BNX2X_PXP_DRAM_ALIGN		(BNX2X_RX_ALIGN_SHIFT - 5)
-
-	struct host_sp_status_block *def_status_blk;
-#define DEF_SB_IGU_ID			16
-#define DEF_SB_ID			HC_SP_SB_ID
-	__le16			def_idx;
-	__le16			def_att_idx;
-	u32			attn_state;
-	struct attn_route	attn_group[MAX_DYNAMIC_ATTN_GRPS];
-
-	/* slow path ring */
-	struct eth_spe		*spq;
-	dma_addr_t		spq_mapping;
-	u16			spq_prod_idx;
-	struct eth_spe		*spq_prod_bd;
-	struct eth_spe		*spq_last_bd;
-	__le16			*dsb_sp_prod;
-	atomic_t		cq_spq_left; /* ETH_XXX ramrods credit */
-	/* used to synchronize spq accesses */
-	spinlock_t		spq_lock;
-
-	/* event queue */
-	union event_ring_elem	*eq_ring;
-	dma_addr_t		eq_mapping;
-	u16			eq_prod;
-	u16			eq_cons;
-	__le16			*eq_cons_sb;
-	atomic_t		eq_spq_left; /* COMMON_XXX ramrods credit */
-
-
-
-	/* Counter for marking that there is a STAT_QUERY ramrod pending */
-	u16			stats_pending;
-	/*  Counter for completed statistics ramrods */
-	u16			stats_comp;
-
-	/* End of fields used in the performance code paths */
-
-	int			panic;
-	int			msg_enable;
-
-	u32			flags;
-#define PCIX_FLAG			(1 << 0)
-#define PCI_32BIT_FLAG			(1 << 1)
-#define ONE_PORT_FLAG			(1 << 2)
-#define NO_WOL_FLAG			(1 << 3)
-#define USING_DAC_FLAG			(1 << 4)
-#define USING_MSIX_FLAG			(1 << 5)
-#define USING_MSI_FLAG			(1 << 6)
-#define DISABLE_MSI_FLAG		(1 << 7)
-#define TPA_ENABLE_FLAG			(1 << 8)
-#define NO_MCP_FLAG			(1 << 9)
-
-#define BP_NOMCP(bp)			(bp->flags & NO_MCP_FLAG)
-#define MF_FUNC_DIS			(1 << 11)
-#define OWN_CNIC_IRQ			(1 << 12)
-#define NO_ISCSI_OOO_FLAG		(1 << 13)
-#define NO_ISCSI_FLAG			(1 << 14)
-#define NO_FCOE_FLAG			(1 << 15)
-
-#define NO_ISCSI(bp)		((bp)->flags & NO_ISCSI_FLAG)
-#define NO_ISCSI_OOO(bp)	((bp)->flags & NO_ISCSI_OOO_FLAG)
-#define NO_FCOE(bp)		((bp)->flags & NO_FCOE_FLAG)
-
-	int			pm_cap;
-	int			mrrs;
-
-	struct delayed_work	sp_task;
-	struct delayed_work	sp_rtnl_task;
-
-	struct delayed_work	period_task;
-	struct timer_list	timer;
-	int			current_interval;
-
-	u16			fw_seq;
-	u16			fw_drv_pulse_wr_seq;
-	u32			func_stx;
-
-	struct link_params	link_params;
-	struct link_vars	link_vars;
-	u32			link_cnt;
-	struct bnx2x_link_report_data last_reported_link;
-
-	struct mdio_if_info	mdio;
-
-	struct bnx2x_common	common;
-	struct bnx2x_port	port;
-
-	struct cmng_struct_per_port cmng;
-	u32			vn_weight_sum;
-	u32			mf_config[E1HVN_MAX];
-	u32			mf2_config[E2_FUNC_MAX];
-	u32			path_has_ovlan; /* E3 */
-	u16			mf_ov;
-	u8			mf_mode;
-#define IS_MF(bp)		(bp->mf_mode != 0)
-#define IS_MF_SI(bp)		(bp->mf_mode == MULTI_FUNCTION_SI)
-#define IS_MF_SD(bp)		(bp->mf_mode == MULTI_FUNCTION_SD)
-
-	u8			wol;
-
-	int			rx_ring_size;
-
-	u16			tx_quick_cons_trip_int;
-	u16			tx_quick_cons_trip;
-	u16			tx_ticks_int;
-	u16			tx_ticks;
-
-	u16			rx_quick_cons_trip_int;
-	u16			rx_quick_cons_trip;
-	u16			rx_ticks_int;
-	u16			rx_ticks;
-/* Maximal coalescing timeout in us */
-#define BNX2X_MAX_COALESCE_TOUT		(0xf0*12)
-
-	u32			lin_cnt;
-
-	u16			state;
-#define BNX2X_STATE_CLOSED		0
-#define BNX2X_STATE_OPENING_WAIT4_LOAD	0x1000
-#define BNX2X_STATE_OPENING_WAIT4_PORT	0x2000
-#define BNX2X_STATE_OPEN		0x3000
-#define BNX2X_STATE_CLOSING_WAIT4_HALT	0x4000
-#define BNX2X_STATE_CLOSING_WAIT4_DELETE 0x5000
-
-#define BNX2X_STATE_DIAG		0xe000
-#define BNX2X_STATE_ERROR		0xf000
-
-	int			multi_mode;
-#define BNX2X_MAX_PRIORITY		8
-#define BNX2X_MAX_ENTRIES_PER_PRI	16
-#define BNX2X_MAX_COS			3
-#define BNX2X_MAX_TX_COS		2
-	int			num_queues;
-	int			disable_tpa;
-
-	u32			rx_mode;
-#define BNX2X_RX_MODE_NONE		0
-#define BNX2X_RX_MODE_NORMAL		1
-#define BNX2X_RX_MODE_ALLMULTI		2
-#define BNX2X_RX_MODE_PROMISC		3
-#define BNX2X_MAX_MULTICAST		64
-
-	u8			igu_dsb_id;
-	u8			igu_base_sb;
-	u8			igu_sb_cnt;
-	dma_addr_t		def_status_blk_mapping;
-
-	struct bnx2x_slowpath	*slowpath;
-	dma_addr_t		slowpath_mapping;
-
-	/* Total number of FW statistics requests */
-	u8			fw_stats_num;
-
-	/*
-	 * This is a memory buffer that will contain both statistics
-	 * ramrod request and data.
-	 */
-	void			*fw_stats;
-	dma_addr_t		fw_stats_mapping;
-
-	/*
-	 * FW statistics request shortcut (points at the
-	 * beginning of fw_stats buffer).
-	 */
-	struct bnx2x_fw_stats_req	*fw_stats_req;
-	dma_addr_t			fw_stats_req_mapping;
-	int				fw_stats_req_sz;
-
-	/*
-	 * FW statistics data shortcut (points at the begining of
-	 * fw_stats buffer + fw_stats_req_sz).
-	 */
-	struct bnx2x_fw_stats_data	*fw_stats_data;
-	dma_addr_t			fw_stats_data_mapping;
-	int				fw_stats_data_sz;
-
-	struct hw_context	context;
-
-	struct bnx2x_ilt	*ilt;
-#define BP_ILT(bp)		((bp)->ilt)
-#define ILT_MAX_LINES		256
-/*
- * Maximum supported number of RSS queues: number of IGU SBs minus one that goes
- * to CNIC.
- */
-#define BNX2X_MAX_RSS_COUNT(bp)	((bp)->igu_sb_cnt - CNIC_PRESENT)
-
-/*
- * Maximum CID count that might be required by the bnx2x:
- * Max Tss * Max_Tx_Multi_Cos + CNIC L2 Clients (FCoE and iSCSI related)
- */
-#define BNX2X_L2_CID_COUNT(bp)	(MAX_TXQS_PER_COS * BNX2X_MULTI_TX_COS +\
-					NON_ETH_CONTEXT_USE + CNIC_PRESENT)
-#define L2_ILT_LINES(bp)	(DIV_ROUND_UP(BNX2X_L2_CID_COUNT(bp),\
-					ILT_PAGE_CIDS))
-#define BNX2X_DB_SIZE(bp)	(BNX2X_L2_CID_COUNT(bp) * (1 << BNX2X_DB_SHIFT))
-
-	int			qm_cid_count;
-
-	int			dropless_fc;
-
-#ifdef BCM_CNIC
-	u32			cnic_flags;
-#define BNX2X_CNIC_FLAG_MAC_SET		1
-	void			*t2;
-	dma_addr_t		t2_mapping;
-	struct cnic_ops	__rcu	*cnic_ops;
-	void			*cnic_data;
-	u32			cnic_tag;
-	struct cnic_eth_dev	cnic_eth_dev;
-	union host_hc_status_block cnic_sb;
-	dma_addr_t		cnic_sb_mapping;
-	struct eth_spe		*cnic_kwq;
-	struct eth_spe		*cnic_kwq_prod;
-	struct eth_spe		*cnic_kwq_cons;
-	struct eth_spe		*cnic_kwq_last;
-	u16			cnic_kwq_pending;
-	u16			cnic_spq_pending;
-	u8			fip_mac[ETH_ALEN];
-	struct mutex		cnic_mutex;
-	struct bnx2x_vlan_mac_obj iscsi_l2_mac_obj;
-
-	/* Start index of the "special" (CNIC related) L2 cleints */
-	u8				cnic_base_cl_id;
-#endif
-
-	int			dmae_ready;
-	/* used to synchronize dmae accesses */
-	spinlock_t		dmae_lock;
-
-	/* used to protect the FW mail box */
-	struct mutex		fw_mb_mutex;
-
-	/* used to synchronize stats collecting */
-	int			stats_state;
-
-	/* used for synchronization of concurrent threads statistics handling */
-	spinlock_t		stats_lock;
-
-	/* used by dmae command loader */
-	struct dmae_command	stats_dmae;
-	int			executer_idx;
-
-	u16			stats_counter;
-	struct bnx2x_eth_stats	eth_stats;
-
-	struct z_stream_s	*strm;
-	void			*gunzip_buf;
-	dma_addr_t		gunzip_mapping;
-	int			gunzip_outlen;
-#define FW_BUF_SIZE			0x8000
-#define GUNZIP_BUF(bp)			(bp->gunzip_buf)
-#define GUNZIP_PHYS(bp)			(bp->gunzip_mapping)
-#define GUNZIP_OUTLEN(bp)		(bp->gunzip_outlen)
-
-	struct raw_op		*init_ops;
-	/* Init blocks offsets inside init_ops */
-	u16			*init_ops_offsets;
-	/* Data blob - has 32 bit granularity */
-	u32			*init_data;
-	u32			init_mode_flags;
-#define INIT_MODE_FLAGS(bp)	(bp->init_mode_flags)
-	/* Zipped PRAM blobs - raw data */
-	const u8		*tsem_int_table_data;
-	const u8		*tsem_pram_data;
-	const u8		*usem_int_table_data;
-	const u8		*usem_pram_data;
-	const u8		*xsem_int_table_data;
-	const u8		*xsem_pram_data;
-	const u8		*csem_int_table_data;
-	const u8		*csem_pram_data;
-#define INIT_OPS(bp)			(bp->init_ops)
-#define INIT_OPS_OFFSETS(bp)		(bp->init_ops_offsets)
-#define INIT_DATA(bp)			(bp->init_data)
-#define INIT_TSEM_INT_TABLE_DATA(bp)	(bp->tsem_int_table_data)
-#define INIT_TSEM_PRAM_DATA(bp)		(bp->tsem_pram_data)
-#define INIT_USEM_INT_TABLE_DATA(bp)	(bp->usem_int_table_data)
-#define INIT_USEM_PRAM_DATA(bp)		(bp->usem_pram_data)
-#define INIT_XSEM_INT_TABLE_DATA(bp)	(bp->xsem_int_table_data)
-#define INIT_XSEM_PRAM_DATA(bp)		(bp->xsem_pram_data)
-#define INIT_CSEM_INT_TABLE_DATA(bp)	(bp->csem_int_table_data)
-#define INIT_CSEM_PRAM_DATA(bp)		(bp->csem_pram_data)
-
-#define PHY_FW_VER_LEN			20
-	char			fw_ver[32];
-	const struct firmware	*firmware;
-
-	/* DCB support on/off */
-	u16 dcb_state;
-#define BNX2X_DCB_STATE_OFF			0
-#define BNX2X_DCB_STATE_ON			1
-
-	/* DCBX engine mode */
-	int dcbx_enabled;
-#define BNX2X_DCBX_ENABLED_OFF			0
-#define BNX2X_DCBX_ENABLED_ON_NEG_OFF		1
-#define BNX2X_DCBX_ENABLED_ON_NEG_ON		2
-#define BNX2X_DCBX_ENABLED_INVALID		(-1)
-
-	bool dcbx_mode_uset;
-
-	struct bnx2x_config_dcbx_params		dcbx_config_params;
-	struct bnx2x_dcbx_port_params		dcbx_port_params;
-	int					dcb_version;
-
-	/* CAM credit pools */
-	struct bnx2x_credit_pool_obj		macs_pool;
-
-	/* RX_MODE object */
-	struct bnx2x_rx_mode_obj		rx_mode_obj;
-
-	/* MCAST object */
-	struct bnx2x_mcast_obj			mcast_obj;
-
-	/* RSS configuration object */
-	struct bnx2x_rss_config_obj		rss_conf_obj;
-
-	/* Function State controlling object */
-	struct bnx2x_func_sp_obj		func_obj;
-
-	unsigned long				sp_state;
-
-	/* operation indication for the sp_rtnl task */
-	unsigned long				sp_rtnl_state;
-
-	/* DCBX Negotation results */
-	struct dcbx_features			dcbx_local_feat;
-	u32					dcbx_error;
-
-#ifdef BCM_DCBNL
-	struct dcbx_features			dcbx_remote_feat;
-	u32					dcbx_remote_flags;
-#endif
-	u32					pending_max;
-
-	/* multiple tx classes of service */
-	u8					max_cos;
-
-	/* priority to cos mapping */
-	u8					prio_to_cos[8];
-};
-
-/* Tx queues may be less or equal to Rx queues */
-extern int num_queues;
-#define BNX2X_NUM_QUEUES(bp)	(bp->num_queues)
-#define BNX2X_NUM_ETH_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - NON_ETH_CONTEXT_USE)
-#define BNX2X_NUM_RX_QUEUES(bp)	BNX2X_NUM_QUEUES(bp)
-
-#define is_multi(bp)		(BNX2X_NUM_QUEUES(bp) > 1)
-
-#define BNX2X_MAX_QUEUES(bp)	BNX2X_MAX_RSS_COUNT(bp)
-/* #define is_eth_multi(bp)	(BNX2X_NUM_ETH_QUEUES(bp) > 1) */
-
-#define RSS_IPV4_CAP_MASK						\
-	TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY
-
-#define RSS_IPV4_TCP_CAP_MASK						\
-	TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY
-
-#define RSS_IPV6_CAP_MASK						\
-	TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY
-
-#define RSS_IPV6_TCP_CAP_MASK						\
-	TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY
-
-/* func init flags */
-#define FUNC_FLG_RSS		0x0001
-#define FUNC_FLG_STATS		0x0002
-/* removed  FUNC_FLG_UNMATCHED	0x0004 */
-#define FUNC_FLG_TPA		0x0008
-#define FUNC_FLG_SPQ		0x0010
-#define FUNC_FLG_LEADING	0x0020	/* PF only */
-
-
-struct bnx2x_func_init_params {
-	/* dma */
-	dma_addr_t	fw_stat_map;	/* valid iff FUNC_FLG_STATS */
-	dma_addr_t	spq_map;	/* valid iff FUNC_FLG_SPQ */
-
-	u16		func_flgs;
-	u16		func_id;	/* abs fid */
-	u16		pf_id;
-	u16		spq_prod;	/* valid iff FUNC_FLG_SPQ */
-};
-
-#define for_each_eth_queue(bp, var) \
-	for ((var) = 0; (var) < BNX2X_NUM_ETH_QUEUES(bp); (var)++)
-
-#define for_each_nondefault_eth_queue(bp, var) \
-	for ((var) = 1; (var) < BNX2X_NUM_ETH_QUEUES(bp); (var)++)
-
-#define for_each_queue(bp, var) \
-	for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
-		if (skip_queue(bp, var))	\
-			continue;		\
-		else
-
-/* Skip forwarding FP */
-#define for_each_rx_queue(bp, var) \
-	for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
-		if (skip_rx_queue(bp, var))	\
-			continue;		\
-		else
-
-/* Skip OOO FP */
-#define for_each_tx_queue(bp, var) \
-	for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
-		if (skip_tx_queue(bp, var))	\
-			continue;		\
-		else
-
-#define for_each_nondefault_queue(bp, var) \
-	for ((var) = 1; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
-		if (skip_queue(bp, var))	\
-			continue;		\
-		else
-
-#define for_each_cos_in_tx_queue(fp, var) \
-	for ((var) = 0; (var) < (fp)->max_cos; (var)++)
-
-/* skip rx queue
- * if FCOE l2 support is disabled and this is the fcoe L2 queue
- */
-#define skip_rx_queue(bp, idx)	(NO_FCOE(bp) && IS_FCOE_IDX(idx))
-
-/* skip tx queue
- * if FCOE l2 support is disabled and this is the fcoe L2 queue
- */
-#define skip_tx_queue(bp, idx)	(NO_FCOE(bp) && IS_FCOE_IDX(idx))
-
-#define skip_queue(bp, idx)	(NO_FCOE(bp) && IS_FCOE_IDX(idx))
-
-
-
-
-/**
- * bnx2x_set_mac_one - configure a single MAC address
- *
- * @bp:			driver handle
- * @mac:		MAC to configure
- * @obj:		MAC object handle
- * @set:		if 'true' add a new MAC, otherwise - delete
- * @mac_type:		the type of the MAC to configure (e.g. ETH, UC list)
- * @ramrod_flags:	RAMROD_XXX flags (e.g. RAMROD_CONT, RAMROD_COMP_WAIT)
- *
- * Configures one MAC according to provided parameters or continues the
- * execution of previously scheduled commands if RAMROD_CONT is set in
- * ramrod_flags.
- *
- * Returns zero if operation has successfully completed, a positive value if the
- * operation has been successfully scheduled and a negative - if a requested
- * operations has failed.
- */
-int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,
-		      struct bnx2x_vlan_mac_obj *obj, bool set,
-		      int mac_type, unsigned long *ramrod_flags);
-/**
- * Deletes all MACs configured for the specific MAC object.
- *
- * @param bp Function driver instance
- * @param mac_obj MAC object to cleanup
- *
- * @return zero if all MACs were cleaned
- */
-
-/**
- * bnx2x_del_all_macs - delete all MACs configured for the specific MAC object
- *
- * @bp:			driver handle
- * @mac_obj:		MAC object handle
- * @mac_type:		type of the MACs to clear (BNX2X_XXX_MAC)
- * @wait_for_comp:	if 'true' block until completion
- *
- * Deletes all MACs of the specific type (e.g. ETH, UC list).
- *
- * Returns zero if operation has successfully completed, a positive value if the
- * operation has been successfully scheduled and a negative - if a requested
- * operations has failed.
- */
-int bnx2x_del_all_macs(struct bnx2x *bp,
-		       struct bnx2x_vlan_mac_obj *mac_obj,
-		       int mac_type, bool wait_for_comp);
-
-/* Init Function API  */
-void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p);
-int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port);
-int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
-int bnx2x_set_mult_gpio(struct bnx2x *bp, u8 pins, u32 mode);
-int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
-void bnx2x_read_mf_cfg(struct bnx2x *bp);
-
-
-/* dmae */
-void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32);
-void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
-		      u32 len32);
-void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx);
-u32 bnx2x_dmae_opcode_add_comp(u32 opcode, u8 comp_type);
-u32 bnx2x_dmae_opcode_clr_src_reset(u32 opcode);
-u32 bnx2x_dmae_opcode(struct bnx2x *bp, u8 src_type, u8 dst_type,
-		      bool with_comp, u8 comp_type);
-
-
-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 cmd_type);
-void bnx2x_update_coalesce(struct bnx2x *bp);
-int bnx2x_get_cur_phy_idx(struct bnx2x *bp);
-
-static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
-			   int wait)
-{
-	u32 val;
-
-	do {
-		val = REG_RD(bp, reg);
-		if (val == expected)
-			break;
-		ms -= wait;
-		msleep(wait);
-
-	} while (ms > 0);
-
-	return val;
-}
-
-#define BNX2X_ILT_ZALLOC(x, y, size) \
-	do { \
-		x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
-		if (x) \
-			memset(x, 0, size); \
-	} while (0)
-
-#define BNX2X_ILT_FREE(x, y, size) \
-	do { \
-		if (x) { \
-			dma_free_coherent(&bp->pdev->dev, size, x, y); \
-			x = NULL; \
-			y = 0; \
-		} \
-	} while (0)
-
-#define ILOG2(x)	(ilog2((x)))
-
-#define ILT_NUM_PAGE_ENTRIES	(3072)
-/* In 57710/11 we use whole table since we have 8 func
- * In 57712 we have only 4 func, but use same size per func, then only half of
- * the table in use
- */
-#define ILT_PER_FUNC		(ILT_NUM_PAGE_ENTRIES/8)
-
-#define FUNC_ILT_BASE(func)	(func * ILT_PER_FUNC)
-/*
- * the phys address is shifted right 12 bits and has an added
- * 1=valid bit added to the 53rd bit
- * then since this is a wide register(TM)
- * we split it into two 32 bit writes
- */
-#define ONCHIP_ADDR1(x)		((u32)(((u64)x >> 12) & 0xFFFFFFFF))
-#define ONCHIP_ADDR2(x)		((u32)((1 << 20) | ((u64)x >> 44)))
-
-/* load/unload mode */
-#define LOAD_NORMAL			0
-#define LOAD_OPEN			1
-#define LOAD_DIAG			2
-#define UNLOAD_NORMAL			0
-#define UNLOAD_CLOSE			1
-#define UNLOAD_RECOVERY			2
-
-
-/* DMAE command defines */
-#define DMAE_TIMEOUT			-1
-#define DMAE_PCI_ERROR			-2	/* E2 and onward */
-#define DMAE_NOT_RDY			-3
-#define DMAE_PCI_ERR_FLAG		0x80000000
-
-#define DMAE_SRC_PCI			0
-#define DMAE_SRC_GRC			1
-
-#define DMAE_DST_NONE			0
-#define DMAE_DST_PCI			1
-#define DMAE_DST_GRC			2
-
-#define DMAE_COMP_PCI			0
-#define DMAE_COMP_GRC			1
-
-/* E2 and onward - PCI error handling in the completion */
-
-#define DMAE_COMP_REGULAR		0
-#define DMAE_COM_SET_ERR		1
-
-#define DMAE_CMD_SRC_PCI		(DMAE_SRC_PCI << \
-						DMAE_COMMAND_SRC_SHIFT)
-#define DMAE_CMD_SRC_GRC		(DMAE_SRC_GRC << \
-						DMAE_COMMAND_SRC_SHIFT)
-
-#define DMAE_CMD_DST_PCI		(DMAE_DST_PCI << \
-						DMAE_COMMAND_DST_SHIFT)
-#define DMAE_CMD_DST_GRC		(DMAE_DST_GRC << \
-						DMAE_COMMAND_DST_SHIFT)
-
-#define DMAE_CMD_C_DST_PCI		(DMAE_COMP_PCI << \
-						DMAE_COMMAND_C_DST_SHIFT)
-#define DMAE_CMD_C_DST_GRC		(DMAE_COMP_GRC << \
-						DMAE_COMMAND_C_DST_SHIFT)
-
-#define DMAE_CMD_C_ENABLE		DMAE_COMMAND_C_TYPE_ENABLE
-
-#define DMAE_CMD_ENDIANITY_NO_SWAP	(0 << DMAE_COMMAND_ENDIANITY_SHIFT)
-#define DMAE_CMD_ENDIANITY_B_SWAP	(1 << DMAE_COMMAND_ENDIANITY_SHIFT)
-#define DMAE_CMD_ENDIANITY_DW_SWAP	(2 << DMAE_COMMAND_ENDIANITY_SHIFT)
-#define DMAE_CMD_ENDIANITY_B_DW_SWAP	(3 << DMAE_COMMAND_ENDIANITY_SHIFT)
-
-#define DMAE_CMD_PORT_0			0
-#define DMAE_CMD_PORT_1			DMAE_COMMAND_PORT
-
-#define DMAE_CMD_SRC_RESET		DMAE_COMMAND_SRC_RESET
-#define DMAE_CMD_DST_RESET		DMAE_COMMAND_DST_RESET
-#define DMAE_CMD_E1HVN_SHIFT		DMAE_COMMAND_E1HVN_SHIFT
-
-#define DMAE_SRC_PF			0
-#define DMAE_SRC_VF			1
-
-#define DMAE_DST_PF			0
-#define DMAE_DST_VF			1
-
-#define DMAE_C_SRC			0
-#define DMAE_C_DST			1
-
-#define DMAE_LEN32_RD_MAX		0x80
-#define DMAE_LEN32_WR_MAX(bp)		(CHIP_IS_E1(bp) ? 0x400 : 0x2000)
-
-#define DMAE_COMP_VAL			0x60d0d0ae /* E2 and on - upper bit
-							indicates eror */
-
-#define MAX_DMAE_C_PER_PORT		8
-#define INIT_DMAE_C(bp)			(BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \
-					 BP_VN(bp))
-#define PMF_DMAE_C(bp)			(BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \
-					 E1HVN_MAX)
-
-/* PCIE link and speed */
-#define PCICFG_LINK_WIDTH		0x1f00000
-#define PCICFG_LINK_WIDTH_SHIFT		20
-#define PCICFG_LINK_SPEED		0xf0000
-#define PCICFG_LINK_SPEED_SHIFT		16
-
-
-#define BNX2X_NUM_TESTS			7
-
-#define BNX2X_PHY_LOOPBACK		0
-#define BNX2X_MAC_LOOPBACK		1
-#define BNX2X_PHY_LOOPBACK_FAILED	1
-#define BNX2X_MAC_LOOPBACK_FAILED	2
-#define BNX2X_LOOPBACK_FAILED		(BNX2X_MAC_LOOPBACK_FAILED | \
-					 BNX2X_PHY_LOOPBACK_FAILED)
-
-
-#define STROM_ASSERT_ARRAY_SIZE		50
-
-
-/* must be used on a CID before placing it on a HW ring */
-#define HW_CID(bp, x)			((BP_PORT(bp) << 23) | \
-					 (BP_VN(bp) << BNX2X_SWCID_SHIFT) | \
-					 (x))
-
-#define SP_DESC_CNT		(BCM_PAGE_SIZE / sizeof(struct eth_spe))
-#define MAX_SP_DESC_CNT			(SP_DESC_CNT - 1)
-
-
-#define BNX2X_BTR			4
-#define MAX_SPQ_PENDING			8
-
-/* CMNG constants, as derived from system spec calculations */
-/* default MIN rate in case VNIC min rate is configured to zero - 100Mbps */
-#define DEF_MIN_RATE					100
-/* resolution of the rate shaping timer - 400 usec */
-#define RS_PERIODIC_TIMEOUT_USEC			400
-/* number of bytes in single QM arbitration cycle -
- * coefficient for calculating the fairness timer */
-#define QM_ARB_BYTES					160000
-/* resolution of Min algorithm 1:100 */
-#define MIN_RES						100
-/* how many bytes above threshold for the minimal credit of Min algorithm*/
-#define MIN_ABOVE_THRESH				32768
-/* Fairness algorithm integration time coefficient -
- * for calculating the actual Tfair */
-#define T_FAIR_COEF	((MIN_ABOVE_THRESH +  QM_ARB_BYTES) * 8 * MIN_RES)
-/* Memory of fairness algorithm . 2 cycles */
-#define FAIR_MEM					2
-
-
-#define ATTN_NIG_FOR_FUNC		(1L << 8)
-#define ATTN_SW_TIMER_4_FUNC		(1L << 9)
-#define GPIO_2_FUNC			(1L << 10)
-#define GPIO_3_FUNC			(1L << 11)
-#define GPIO_4_FUNC			(1L << 12)
-#define ATTN_GENERAL_ATTN_1		(1L << 13)
-#define ATTN_GENERAL_ATTN_2		(1L << 14)
-#define ATTN_GENERAL_ATTN_3		(1L << 15)
-#define ATTN_GENERAL_ATTN_4		(1L << 13)
-#define ATTN_GENERAL_ATTN_5		(1L << 14)
-#define ATTN_GENERAL_ATTN_6		(1L << 15)
-
-#define ATTN_HARD_WIRED_MASK		0xff00
-#define ATTENTION_ID			4
-
-
-/* stuff added to make the code fit 80Col */
-
-#define BNX2X_PMF_LINK_ASSERT \
-	GENERAL_ATTEN_OFFSET(LINK_SYNC_ATTENTION_BIT_FUNC_0 + BP_FUNC(bp))
-
-#define BNX2X_MC_ASSERT_BITS \
-	(GENERAL_ATTEN_OFFSET(TSTORM_FATAL_ASSERT_ATTENTION_BIT) | \
-	 GENERAL_ATTEN_OFFSET(USTORM_FATAL_ASSERT_ATTENTION_BIT) | \
-	 GENERAL_ATTEN_OFFSET(CSTORM_FATAL_ASSERT_ATTENTION_BIT) | \
-	 GENERAL_ATTEN_OFFSET(XSTORM_FATAL_ASSERT_ATTENTION_BIT))
-
-#define BNX2X_MCP_ASSERT \
-	GENERAL_ATTEN_OFFSET(MCP_FATAL_ASSERT_ATTENTION_BIT)
-
-#define BNX2X_GRC_TIMEOUT	GENERAL_ATTEN_OFFSET(LATCHED_ATTN_TIMEOUT_GRC)
-#define BNX2X_GRC_RSV		(GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCR) | \
-				 GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCT) | \
-				 GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCN) | \
-				 GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCU) | \
-				 GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCP) | \
-				 GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RSVD_GRC))
-
-#define HW_INTERRUT_ASSERT_SET_0 \
-				(AEU_INPUTS_ATTN_BITS_TSDM_HW_INTERRUPT | \
-				 AEU_INPUTS_ATTN_BITS_TCM_HW_INTERRUPT | \
-				 AEU_INPUTS_ATTN_BITS_TSEMI_HW_INTERRUPT | \
-				 AEU_INPUTS_ATTN_BITS_PBCLIENT_HW_INTERRUPT)
-#define HW_PRTY_ASSERT_SET_0	(AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR | \
-				 AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR | \
-				 AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR | \
-				 AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR |\
-				 AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR |\
-				 AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR |\
-				 AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR)
-#define HW_INTERRUT_ASSERT_SET_1 \
-				(AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT | \
-				 AEU_INPUTS_ATTN_BITS_TIMERS_HW_INTERRUPT | \
-				 AEU_INPUTS_ATTN_BITS_XSDM_HW_INTERRUPT | \
-				 AEU_INPUTS_ATTN_BITS_XCM_HW_INTERRUPT | \
-				 AEU_INPUTS_ATTN_BITS_XSEMI_HW_INTERRUPT | \
-				 AEU_INPUTS_ATTN_BITS_USDM_HW_INTERRUPT | \
-				 AEU_INPUTS_ATTN_BITS_UCM_HW_INTERRUPT | \
-				 AEU_INPUTS_ATTN_BITS_USEMI_HW_INTERRUPT | \
-				 AEU_INPUTS_ATTN_BITS_UPB_HW_INTERRUPT | \
-				 AEU_INPUTS_ATTN_BITS_CSDM_HW_INTERRUPT | \
-				 AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT)
-#define HW_PRTY_ASSERT_SET_1	(AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR |\
-				 AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR | \
-				 AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR |\
-				 AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR | \
-				 AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR |\
-				 AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR | \
-				 AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR |\
-				 AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR |\
-			     AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR |\
-				 AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR | \
-				 AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR | \
-				 AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR |\
-				 AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR | \
-				 AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR | \
-				 AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR |\
-				 AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR)
-#define HW_INTERRUT_ASSERT_SET_2 \
-				(AEU_INPUTS_ATTN_BITS_CSEMI_HW_INTERRUPT | \
-				 AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT | \
-				 AEU_INPUTS_ATTN_BITS_DMAE_HW_INTERRUPT | \
-			AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_HW_INTERRUPT |\
-				 AEU_INPUTS_ATTN_BITS_MISC_HW_INTERRUPT)
-#define HW_PRTY_ASSERT_SET_2	(AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR | \
-				 AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR | \
-			AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR |\
-				 AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR | \
-				 AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR | \
-				 AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR |\
-				 AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR | \
-				 AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR)
-
-#define HW_PRTY_ASSERT_SET_3 (AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY | \
-		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY | \
-		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY | \
-		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY)
-
-#define HW_PRTY_ASSERT_SET_4 (AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR | \
-			      AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR)
-
-#define RSS_FLAGS(bp) \
-		(TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY | \
-		 TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY | \
-		 TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY | \
-		 TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY | \
-		 (bp->multi_mode << \
-		  TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT))
-#define MULTI_MASK			0x7f
-
-
-#define DEF_USB_FUNC_OFF	offsetof(struct cstorm_def_status_block_u, func)
-#define DEF_CSB_FUNC_OFF	offsetof(struct cstorm_def_status_block_c, func)
-#define DEF_XSB_FUNC_OFF	offsetof(struct xstorm_def_status_block, func)
-#define DEF_TSB_FUNC_OFF	offsetof(struct tstorm_def_status_block, func)
-
-#define DEF_USB_IGU_INDEX_OFF \
-			offsetof(struct cstorm_def_status_block_u, igu_index)
-#define DEF_CSB_IGU_INDEX_OFF \
-			offsetof(struct cstorm_def_status_block_c, igu_index)
-#define DEF_XSB_IGU_INDEX_OFF \
-			offsetof(struct xstorm_def_status_block, igu_index)
-#define DEF_TSB_IGU_INDEX_OFF \
-			offsetof(struct tstorm_def_status_block, igu_index)
-
-#define DEF_USB_SEGMENT_OFF \
-			offsetof(struct cstorm_def_status_block_u, segment)
-#define DEF_CSB_SEGMENT_OFF \
-			offsetof(struct cstorm_def_status_block_c, segment)
-#define DEF_XSB_SEGMENT_OFF \
-			offsetof(struct xstorm_def_status_block, segment)
-#define DEF_TSB_SEGMENT_OFF \
-			offsetof(struct tstorm_def_status_block, segment)
-
-#define BNX2X_SP_DSB_INDEX \
-		(&bp->def_status_blk->sp_sb.\
-					index_values[HC_SP_INDEX_ETH_DEF_CONS])
-
-#define SET_FLAG(value, mask, flag) \
-	do {\
-		(value) &= ~(mask);\
-		(value) |= ((flag) << (mask##_SHIFT));\
-	} while (0)
-
-#define GET_FLAG(value, mask) \
-	(((value) & (mask)) >> (mask##_SHIFT))
-
-#define GET_FIELD(value, fname) \
-	(((value) & (fname##_MASK)) >> (fname##_SHIFT))
-
-#define CAM_IS_INVALID(x) \
-	(GET_FLAG(x.flags, \
-	MAC_CONFIGURATION_ENTRY_ACTION_TYPE) == \
-	(T_ETH_MAC_COMMAND_INVALIDATE))
-
-/* Number of u32 elements in MC hash array */
-#define MC_HASH_SIZE			8
-#define MC_HASH_OFFSET(bp, i)		(BAR_TSTRORM_INTMEM + \
-	TSTORM_APPROXIMATE_MATCH_MULTICAST_FILTERING_OFFSET(BP_FUNC(bp)) + i*4)
-
-
-#ifndef PXP2_REG_PXP2_INT_STS
-#define PXP2_REG_PXP2_INT_STS		PXP2_REG_PXP2_INT_STS_0
-#endif
-
-#ifndef ETH_MAX_RX_CLIENTS_E2
-#define ETH_MAX_RX_CLIENTS_E2		ETH_MAX_RX_CLIENTS_E1H
-#endif
-
-#define BNX2X_VPD_LEN			128
-#define VENDOR_ID_LEN			4
-
-/* Congestion management fairness mode */
-#define CMNG_FNS_NONE		0
-#define CMNG_FNS_MINMAX		1
-
-#define HC_SEG_ACCESS_DEF		0   /*Driver decision 0-3*/
-#define HC_SEG_ACCESS_ATTN		4
-#define HC_SEG_ACCESS_NORM		0   /*Driver decision 0-1*/
-
-static const u32 dmae_reg_go_c[] = {
-	DMAE_REG_GO_C0, DMAE_REG_GO_C1, DMAE_REG_GO_C2, DMAE_REG_GO_C3,
-	DMAE_REG_GO_C4, DMAE_REG_GO_C5, DMAE_REG_GO_C6, DMAE_REG_GO_C7,
-	DMAE_REG_GO_C8, DMAE_REG_GO_C9, DMAE_REG_GO_C10, DMAE_REG_GO_C11,
-	DMAE_REG_GO_C12, DMAE_REG_GO_C13, DMAE_REG_GO_C14, DMAE_REG_GO_C15
-};
-
-void bnx2x_set_ethtool_ops(struct net_device *netdev);
-void bnx2x_notify_link_changed(struct bnx2x *bp);
-#endif /* bnx2x.h */
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_hsi.h linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_hsi.h
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_hsi.h	2012-03-19 21:43:19.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_hsi.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,5127 +0,0 @@
-/* bnx2x_hsi.h: Broadcom Everest network driver.
- *
- * Copyright (c) 2007-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
- * the Free Software Foundation.
- */
-#ifndef BNX2X_HSI_H
-#define BNX2X_HSI_H
-
-#include "bnx2x_fw_defs.h"
-
-#define FW_ENCODE_32BIT_PATTERN         0x1e1e1e1e
-
-struct license_key {
-	u32 reserved[6];
-
-	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;
-
-	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
-#define PORT_MAX            2
-
-/****************************************************************************
- * Shared HW configuration                                                  *
- ****************************************************************************/
-#define PIN_CFG_NA                          0x00000000
-#define PIN_CFG_GPIO0_P0                    0x00000001
-#define PIN_CFG_GPIO1_P0                    0x00000002
-#define PIN_CFG_GPIO2_P0                    0x00000003
-#define PIN_CFG_GPIO3_P0                    0x00000004
-#define PIN_CFG_GPIO0_P1                    0x00000005
-#define PIN_CFG_GPIO1_P1                    0x00000006
-#define PIN_CFG_GPIO2_P1                    0x00000007
-#define PIN_CFG_GPIO3_P1                    0x00000008
-#define PIN_CFG_EPIO0                       0x00000009
-#define PIN_CFG_EPIO1                       0x0000000a
-#define PIN_CFG_EPIO2                       0x0000000b
-#define PIN_CFG_EPIO3                       0x0000000c
-#define PIN_CFG_EPIO4                       0x0000000d
-#define PIN_CFG_EPIO5                       0x0000000e
-#define PIN_CFG_EPIO6                       0x0000000f
-#define PIN_CFG_EPIO7                       0x00000010
-#define PIN_CFG_EPIO8                       0x00000011
-#define PIN_CFG_EPIO9                       0x00000012
-#define PIN_CFG_EPIO10                      0x00000013
-#define PIN_CFG_EPIO11                      0x00000014
-#define PIN_CFG_EPIO12                      0x00000015
-#define PIN_CFG_EPIO13                      0x00000016
-#define PIN_CFG_EPIO14                      0x00000017
-#define PIN_CFG_EPIO15                      0x00000018
-#define PIN_CFG_EPIO16                      0x00000019
-#define PIN_CFG_EPIO17                      0x0000001a
-#define PIN_CFG_EPIO18                      0x0000001b
-#define PIN_CFG_EPIO19                      0x0000001c
-#define PIN_CFG_EPIO20                      0x0000001d
-#define PIN_CFG_EPIO21                      0x0000001e
-#define PIN_CFG_EPIO22                      0x0000001f
-#define PIN_CFG_EPIO23                      0x00000020
-#define PIN_CFG_EPIO24                      0x00000021
-#define PIN_CFG_EPIO25                      0x00000022
-#define PIN_CFG_EPIO26                      0x00000023
-#define PIN_CFG_EPIO27                      0x00000024
-#define PIN_CFG_EPIO28                      0x00000025
-#define PIN_CFG_EPIO29                      0x00000026
-#define PIN_CFG_EPIO30                      0x00000027
-#define PIN_CFG_EPIO31                      0x00000028
-
-/* EPIO definition */
-#define EPIO_CFG_NA                         0x00000000
-#define EPIO_CFG_EPIO0                      0x00000001
-#define EPIO_CFG_EPIO1                      0x00000002
-#define EPIO_CFG_EPIO2                      0x00000003
-#define EPIO_CFG_EPIO3                      0x00000004
-#define EPIO_CFG_EPIO4                      0x00000005
-#define EPIO_CFG_EPIO5                      0x00000006
-#define EPIO_CFG_EPIO6                      0x00000007
-#define EPIO_CFG_EPIO7                      0x00000008
-#define EPIO_CFG_EPIO8                      0x00000009
-#define EPIO_CFG_EPIO9                      0x0000000a
-#define EPIO_CFG_EPIO10                     0x0000000b
-#define EPIO_CFG_EPIO11                     0x0000000c
-#define EPIO_CFG_EPIO12                     0x0000000d
-#define EPIO_CFG_EPIO13                     0x0000000e
-#define EPIO_CFG_EPIO14                     0x0000000f
-#define EPIO_CFG_EPIO15                     0x00000010
-#define EPIO_CFG_EPIO16                     0x00000011
-#define EPIO_CFG_EPIO17                     0x00000012
-#define EPIO_CFG_EPIO18                     0x00000013
-#define EPIO_CFG_EPIO19                     0x00000014
-#define EPIO_CFG_EPIO20                     0x00000015
-#define EPIO_CFG_EPIO21                     0x00000016
-#define EPIO_CFG_EPIO22                     0x00000017
-#define EPIO_CFG_EPIO23                     0x00000018
-#define EPIO_CFG_EPIO24                     0x00000019
-#define EPIO_CFG_EPIO25                     0x0000001a
-#define EPIO_CFG_EPIO26                     0x0000001b
-#define EPIO_CFG_EPIO27                     0x0000001c
-#define EPIO_CFG_EPIO28                     0x0000001d
-#define EPIO_CFG_EPIO29                     0x0000001e
-#define EPIO_CFG_EPIO30                     0x0000001f
-#define EPIO_CFG_EPIO31                     0x00000020
-
-
-struct shared_hw_cfg {			 /* NVRAM Offset */
-	/* Up to 16 bytes of NULL-terminated string */
-	u8  part_num[16];		    /* 0x104 */
-
-	u32 config;			/* 0x114 */
-	#define SHARED_HW_CFG_MDIO_VOLTAGE_MASK             0x00000001
-		#define SHARED_HW_CFG_MDIO_VOLTAGE_SHIFT             0
-		#define SHARED_HW_CFG_MDIO_VOLTAGE_1_2V              0x00000000
-		#define SHARED_HW_CFG_MDIO_VOLTAGE_2_5V              0x00000001
-	#define SHARED_HW_CFG_MCP_RST_ON_CORE_RST_EN        0x00000002
-
-	#define SHARED_HW_CFG_PORT_SWAP                     0x00000004
-
-	#define SHARED_HW_CFG_BEACON_WOL_EN                 0x00000008
-
-	#define SHARED_HW_CFG_PCIE_GEN3_DISABLED            0x00000000
-	#define SHARED_HW_CFG_PCIE_GEN3_ENABLED             0x00000010
-
-	#define SHARED_HW_CFG_MFW_SELECT_MASK               0x00000700
-		#define SHARED_HW_CFG_MFW_SELECT_SHIFT               8
-	/* Whatever MFW found in NVM
-	   (if multiple found, priority order is: NC-SI, UMP, IPMI) */
-		#define SHARED_HW_CFG_MFW_SELECT_DEFAULT             0x00000000
-		#define SHARED_HW_CFG_MFW_SELECT_NC_SI               0x00000100
-		#define SHARED_HW_CFG_MFW_SELECT_UMP                 0x00000200
-		#define SHARED_HW_CFG_MFW_SELECT_IPMI                0x00000300
-	/* Use SPIO4 as an arbiter between: 0-NC_SI, 1-IPMI
-	  (can only be used when an add-in board, not BMC, pulls-down SPIO4) */
-		#define SHARED_HW_CFG_MFW_SELECT_SPIO4_NC_SI_IPMI    0x00000400
-	/* Use SPIO4 as an arbiter between: 0-UMP, 1-IPMI
-	  (can only be used when an add-in board, not BMC, pulls-down SPIO4) */
-		#define SHARED_HW_CFG_MFW_SELECT_SPIO4_UMP_IPMI      0x00000500
-	/* Use SPIO4 as an arbiter between: 0-NC-SI, 1-UMP
-	  (can only be used when an add-in board, not BMC, pulls-down SPIO4) */
-		#define SHARED_HW_CFG_MFW_SELECT_SPIO4_NC_SI_UMP     0x00000600
-
-	#define SHARED_HW_CFG_LED_MODE_MASK                 0x000f0000
-		#define SHARED_HW_CFG_LED_MODE_SHIFT                 16
-		#define SHARED_HW_CFG_LED_MAC1                       0x00000000
-		#define SHARED_HW_CFG_LED_PHY1                       0x00010000
-		#define SHARED_HW_CFG_LED_PHY2                       0x00020000
-		#define SHARED_HW_CFG_LED_PHY3                       0x00030000
-		#define SHARED_HW_CFG_LED_MAC2                       0x00040000
-		#define SHARED_HW_CFG_LED_PHY4                       0x00050000
-		#define SHARED_HW_CFG_LED_PHY5                       0x00060000
-		#define SHARED_HW_CFG_LED_PHY6                       0x00070000
-		#define SHARED_HW_CFG_LED_MAC3                       0x00080000
-		#define SHARED_HW_CFG_LED_PHY7                       0x00090000
-		#define SHARED_HW_CFG_LED_PHY9                       0x000a0000
-		#define SHARED_HW_CFG_LED_PHY11                      0x000b0000
-		#define SHARED_HW_CFG_LED_MAC4                       0x000c0000
-		#define SHARED_HW_CFG_LED_PHY8                       0x000d0000
-		#define SHARED_HW_CFG_LED_EXTPHY1                    0x000e0000
-
-
-	#define SHARED_HW_CFG_AN_ENABLE_MASK                0x3f000000
-		#define SHARED_HW_CFG_AN_ENABLE_SHIFT                24
-		#define SHARED_HW_CFG_AN_ENABLE_CL37                 0x01000000
-		#define SHARED_HW_CFG_AN_ENABLE_CL73                 0x02000000
-		#define SHARED_HW_CFG_AN_ENABLE_BAM                  0x04000000
-		#define SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION   0x08000000
-		#define SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT  0x10000000
-		#define SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY           0x20000000
-
-	#define SHARED_HW_CFG_SRIOV_MASK                    0x40000000
-		#define SHARED_HW_CFG_SRIOV_DISABLED                 0x00000000
-		#define SHARED_HW_CFG_SRIOV_ENABLED                  0x40000000
-
-	#define SHARED_HW_CFG_ATC_MASK                      0x80000000
-		#define SHARED_HW_CFG_ATC_DISABLED                   0x00000000
-		#define SHARED_HW_CFG_ATC_ENABLED                    0x80000000
-
-	u32 config2;			    /* 0x118 */
-	/* one time auto detect grace period (in sec) */
-	#define SHARED_HW_CFG_GRACE_PERIOD_MASK             0x000000ff
-	#define SHARED_HW_CFG_GRACE_PERIOD_SHIFT                     0
-
-	#define SHARED_HW_CFG_PCIE_GEN2_ENABLED             0x00000100
-	#define SHARED_HW_CFG_PCIE_GEN2_DISABLED            0x00000000
-
-	/* The default value for the core clock is 250MHz and it is
-	   achieved by setting the clock change to 4 */
-	#define SHARED_HW_CFG_CLOCK_CHANGE_MASK             0x00000e00
-	#define SHARED_HW_CFG_CLOCK_CHANGE_SHIFT                     9
-
-	#define SHARED_HW_CFG_SMBUS_TIMING_MASK             0x00001000
-		#define SHARED_HW_CFG_SMBUS_TIMING_100KHZ            0x00000000
-		#define SHARED_HW_CFG_SMBUS_TIMING_400KHZ            0x00001000
-
-	#define SHARED_HW_CFG_HIDE_PORT1                    0x00002000
-
-	#define SHARED_HW_CFG_WOL_CAPABLE_MASK              0x00004000
-		#define SHARED_HW_CFG_WOL_CAPABLE_DISABLED           0x00000000
-		#define SHARED_HW_CFG_WOL_CAPABLE_ENABLED            0x00004000
-
-		/* Output low when PERST is asserted */
-	#define SHARED_HW_CFG_SPIO4_FOLLOW_PERST_MASK       0x00008000
-		#define SHARED_HW_CFG_SPIO4_FOLLOW_PERST_DISABLED    0x00000000
-		#define SHARED_HW_CFG_SPIO4_FOLLOW_PERST_ENABLED     0x00008000
-
-	#define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_MASK    0x00070000
-		#define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_SHIFT    16
-		#define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_HW       0x00000000
-		#define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_0DB      0x00010000
-		#define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_3_5DB    0x00020000
-		#define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_6_0DB    0x00030000
-
-	/*  The fan failure mechanism is usually related to the PHY type
-	      since the power consumption of the board is determined by the PHY.
-	      Currently, fan is required for most designs with SFX7101, BCM8727
-	      and BCM8481. If a fan is not required for a board which uses one
-	      of those PHYs, this field should be set to "Disabled". If a fan is
-	      required for a different PHY type, this option should be set to
-	      "Enabled". The fan failure indication is expected on SPIO5 */
-	#define SHARED_HW_CFG_FAN_FAILURE_MASK              0x00180000
-		#define SHARED_HW_CFG_FAN_FAILURE_SHIFT              19
-		#define SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE           0x00000000
-		#define SHARED_HW_CFG_FAN_FAILURE_DISABLED           0x00080000
-		#define SHARED_HW_CFG_FAN_FAILURE_ENABLED            0x00100000
-
-		/* ASPM Power Management support */
-	#define SHARED_HW_CFG_ASPM_SUPPORT_MASK             0x00600000
-		#define SHARED_HW_CFG_ASPM_SUPPORT_SHIFT             21
-		#define SHARED_HW_CFG_ASPM_SUPPORT_L0S_L1_ENABLED    0x00000000
-		#define SHARED_HW_CFG_ASPM_SUPPORT_L0S_DISABLED      0x00200000
-		#define SHARED_HW_CFG_ASPM_SUPPORT_L1_DISABLED       0x00400000
-		#define SHARED_HW_CFG_ASPM_SUPPORT_L0S_L1_DISABLED   0x00600000
-
-	/* The value of PM_TL_IGNORE_REQS (bit0) in PCI register
-	   tl_control_0 (register 0x2800) */
-	#define SHARED_HW_CFG_PREVENT_L1_ENTRY_MASK         0x00800000
-		#define SHARED_HW_CFG_PREVENT_L1_ENTRY_DISABLED      0x00000000
-		#define SHARED_HW_CFG_PREVENT_L1_ENTRY_ENABLED       0x00800000
-
-	#define SHARED_HW_CFG_PORT_MODE_MASK                0x01000000
-		#define SHARED_HW_CFG_PORT_MODE_2                    0x00000000
-		#define SHARED_HW_CFG_PORT_MODE_4                    0x01000000
-
-	#define SHARED_HW_CFG_PATH_SWAP_MASK                0x02000000
-		#define SHARED_HW_CFG_PATH_SWAP_DISABLED             0x00000000
-		#define SHARED_HW_CFG_PATH_SWAP_ENABLED              0x02000000
-
-	/*  Set the MDC/MDIO access for the first external phy */
-	#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK         0x1C000000
-		#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT         26
-		#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE      0x00000000
-		#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0         0x04000000
-		#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1         0x08000000
-		#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH          0x0c000000
-		#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED       0x10000000
-
-	/*  Set the MDC/MDIO access for the second external phy */
-	#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK         0xE0000000
-		#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT         29
-		#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_PHY_TYPE      0x00000000
-		#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC0         0x20000000
-		#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC1         0x40000000
-		#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_BOTH          0x60000000
-		#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SWAPPED       0x80000000
-
-
-	u32 power_dissipated;			/* 0x11c */
-	#define SHARED_HW_CFG_POWER_MGNT_SCALE_MASK         0x00ff0000
-		#define SHARED_HW_CFG_POWER_MGNT_SCALE_SHIFT         16
-		#define SHARED_HW_CFG_POWER_MGNT_UNKNOWN_SCALE       0x00000000
-		#define SHARED_HW_CFG_POWER_MGNT_DOT_1_WATT          0x00010000
-		#define SHARED_HW_CFG_POWER_MGNT_DOT_01_WATT         0x00020000
-		#define SHARED_HW_CFG_POWER_MGNT_DOT_001_WATT        0x00030000
-
-	#define SHARED_HW_CFG_POWER_DIS_CMN_MASK            0xff000000
-	#define SHARED_HW_CFG_POWER_DIS_CMN_SHIFT                    24
-
-	u32 ump_nc_si_config;			/* 0x120 */
-	#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MASK       0x00000003
-		#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_SHIFT       0
-		#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MAC         0x00000000
-		#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_PHY         0x00000001
-		#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MII         0x00000000
-		#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_RMII        0x00000002
-
-	#define SHARED_HW_CFG_UMP_NC_SI_NUM_DEVS_MASK       0x00000f00
-		#define SHARED_HW_CFG_UMP_NC_SI_NUM_DEVS_SHIFT       8
-
-	#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_MASK   0x00ff0000
-		#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_SHIFT   16
-		#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_NONE    0x00000000
-		#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_BCM5221 0x00010000
-
-	u32 board;			/* 0x124 */
-	#define SHARED_HW_CFG_E3_I2C_MUX0_MASK              0x0000003F
-	#define SHARED_HW_CFG_E3_I2C_MUX0_SHIFT                      0
-	#define SHARED_HW_CFG_E3_I2C_MUX1_MASK              0x00000FC0
-	#define SHARED_HW_CFG_E3_I2C_MUX1_SHIFT                      6
-	/* Use the PIN_CFG_XXX defines on top */
-	#define SHARED_HW_CFG_BOARD_REV_MASK                0x00ff0000
-	#define SHARED_HW_CFG_BOARD_REV_SHIFT                        16
-
-	#define SHARED_HW_CFG_BOARD_MAJOR_VER_MASK          0x0f000000
-	#define SHARED_HW_CFG_BOARD_MAJOR_VER_SHIFT                  24
-
-	#define SHARED_HW_CFG_BOARD_MINOR_VER_MASK          0xf0000000
-	#define SHARED_HW_CFG_BOARD_MINOR_VER_SHIFT                  28
-
-	u32 wc_lane_config;				    /* 0x128 */
-	#define SHARED_HW_CFG_LANE_SWAP_CFG_MASK            0x0000FFFF
-		#define SHARED_HW_CFG_LANE_SWAP_CFG_SHIFT            0
-		#define SHARED_HW_CFG_LANE_SWAP_CFG_32103210         0x00001b1b
-		#define SHARED_HW_CFG_LANE_SWAP_CFG_32100123         0x00001be4
-		#define SHARED_HW_CFG_LANE_SWAP_CFG_01233210         0x0000e41b
-		#define SHARED_HW_CFG_LANE_SWAP_CFG_01230123         0x0000e4e4
-	#define SHARED_HW_CFG_LANE_SWAP_CFG_TX_MASK         0x000000FF
-	#define SHARED_HW_CFG_LANE_SWAP_CFG_TX_SHIFT                 0
-	#define SHARED_HW_CFG_LANE_SWAP_CFG_RX_MASK         0x0000FF00
-	#define SHARED_HW_CFG_LANE_SWAP_CFG_RX_SHIFT                 8
-
-	/* TX lane Polarity swap */
-	#define SHARED_HW_CFG_TX_LANE0_POL_FLIP_ENABLED     0x00010000
-	#define SHARED_HW_CFG_TX_LANE1_POL_FLIP_ENABLED     0x00020000
-	#define SHARED_HW_CFG_TX_LANE2_POL_FLIP_ENABLED     0x00040000
-	#define SHARED_HW_CFG_TX_LANE3_POL_FLIP_ENABLED     0x00080000
-	/* TX lane Polarity swap */
-	#define SHARED_HW_CFG_RX_LANE0_POL_FLIP_ENABLED     0x00100000
-	#define SHARED_HW_CFG_RX_LANE1_POL_FLIP_ENABLED     0x00200000
-	#define SHARED_HW_CFG_RX_LANE2_POL_FLIP_ENABLED     0x00400000
-	#define SHARED_HW_CFG_RX_LANE3_POL_FLIP_ENABLED     0x00800000
-
-	/*  Selects the port layout of the board */
-	#define SHARED_HW_CFG_E3_PORT_LAYOUT_MASK           0x0F000000
-		#define SHARED_HW_CFG_E3_PORT_LAYOUT_SHIFT           24
-		#define SHARED_HW_CFG_E3_PORT_LAYOUT_2P_01           0x00000000
-		#define SHARED_HW_CFG_E3_PORT_LAYOUT_2P_10           0x01000000
-		#define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_0123         0x02000000
-		#define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_1032         0x03000000
-		#define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_2301         0x04000000
-		#define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_3210         0x05000000
-};
-
-
-/****************************************************************************
- * Port HW configuration                                                    *
- ****************************************************************************/
-struct port_hw_cfg {		    /* port 0: 0x12c  port 1: 0x2bc */
-
-	u32 pci_id;
-	#define PORT_HW_CFG_PCI_VENDOR_ID_MASK              0xffff0000
-	#define PORT_HW_CFG_PCI_DEVICE_ID_MASK              0x0000ffff
-
-	u32 pci_sub_id;
-	#define PORT_HW_CFG_PCI_SUBSYS_DEVICE_ID_MASK       0xffff0000
-	#define PORT_HW_CFG_PCI_SUBSYS_VENDOR_ID_MASK       0x0000ffff
-
-	u32 power_dissipated;
-	#define PORT_HW_CFG_POWER_DIS_D0_MASK               0x000000ff
-	#define PORT_HW_CFG_POWER_DIS_D0_SHIFT                       0
-	#define PORT_HW_CFG_POWER_DIS_D1_MASK               0x0000ff00
-	#define PORT_HW_CFG_POWER_DIS_D1_SHIFT                       8
-	#define PORT_HW_CFG_POWER_DIS_D2_MASK               0x00ff0000
-	#define PORT_HW_CFG_POWER_DIS_D2_SHIFT                       16
-	#define PORT_HW_CFG_POWER_DIS_D3_MASK               0xff000000
-	#define PORT_HW_CFG_POWER_DIS_D3_SHIFT                       24
-
-	u32 power_consumed;
-	#define PORT_HW_CFG_POWER_CONS_D0_MASK              0x000000ff
-	#define PORT_HW_CFG_POWER_CONS_D0_SHIFT                      0
-	#define PORT_HW_CFG_POWER_CONS_D1_MASK              0x0000ff00
-	#define PORT_HW_CFG_POWER_CONS_D1_SHIFT                      8
-	#define PORT_HW_CFG_POWER_CONS_D2_MASK              0x00ff0000
-	#define PORT_HW_CFG_POWER_CONS_D2_SHIFT                      16
-	#define PORT_HW_CFG_POWER_CONS_D3_MASK              0xff000000
-	#define PORT_HW_CFG_POWER_CONS_D3_SHIFT                      24
-
-	u32 mac_upper;
-	#define PORT_HW_CFG_UPPERMAC_MASK                   0x0000ffff
-	#define PORT_HW_CFG_UPPERMAC_SHIFT                           0
-	u32 mac_lower;
-
-	u32 iscsi_mac_upper;  /* Upper 16 bits are always zeroes */
-	u32 iscsi_mac_lower;
-
-	u32 rdma_mac_upper;   /* Upper 16 bits are always zeroes */
-	u32 rdma_mac_lower;
-
-	u32 serdes_config;
-	#define PORT_HW_CFG_SERDES_TX_DRV_PRE_EMPHASIS_MASK 0x0000ffff
-	#define PORT_HW_CFG_SERDES_TX_DRV_PRE_EMPHASIS_SHIFT         0
-
-	#define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK    0xffff0000
-	#define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT            16
-
-
-	/*  Default values: 2P-64, 4P-32 */
-	u32 pf_config;					    /* 0x158 */
-	#define PORT_HW_CFG_PF_NUM_VF_MASK                  0x0000007F
-	#define PORT_HW_CFG_PF_NUM_VF_SHIFT                          0
-
-	/*  Default values: 17 */
-	#define PORT_HW_CFG_PF_NUM_MSIX_VECTORS_MASK        0x00007F00
-	#define PORT_HW_CFG_PF_NUM_MSIX_VECTORS_SHIFT                8
-
-	#define PORT_HW_CFG_ENABLE_FLR_MASK                 0x00010000
-	#define PORT_HW_CFG_FLR_ENABLED                     0x00010000
-
-	u32 vf_config;					    /* 0x15C */
-	#define PORT_HW_CFG_VF_NUM_MSIX_VECTORS_MASK        0x0000007F
-	#define PORT_HW_CFG_VF_NUM_MSIX_VECTORS_SHIFT                0
-
-	#define PORT_HW_CFG_VF_PCI_DEVICE_ID_MASK           0xFFFF0000
-	#define PORT_HW_CFG_VF_PCI_DEVICE_ID_SHIFT                   16
-
-	u32 mf_pci_id;					    /* 0x160 */
-	#define PORT_HW_CFG_MF_PCI_DEVICE_ID_MASK           0x0000FFFF
-	#define PORT_HW_CFG_MF_PCI_DEVICE_ID_SHIFT                   0
-
-	/*  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
-
-	/*  The output pin TX_DIS that controls the TX laser of the SFP+
-	  module. Use the PIN_CFG_XXX defines on top */
-	u32 e3_sfp_ctrl;				    /* 0x168 */
-	#define PORT_HW_CFG_E3_TX_LASER_MASK                0x000000FF
-	#define PORT_HW_CFG_E3_TX_LASER_SHIFT                        0
-
-	/*  The output pin for SFPP_TYPE which turns on the Fault module LED */
-	#define PORT_HW_CFG_E3_FAULT_MDL_LED_MASK           0x0000FF00
-	#define PORT_HW_CFG_E3_FAULT_MDL_LED_SHIFT                   8
-
-	/*  The input pin MOD_ABS that indicates whether SFP+ module is
-	  present or not. Use the PIN_CFG_XXX defines on top */
-	#define PORT_HW_CFG_E3_MOD_ABS_MASK                 0x00FF0000
-	#define PORT_HW_CFG_E3_MOD_ABS_SHIFT                         16
-
-	/*  The output pin PWRDIS_SFP_X which disable the power of the SFP+
-	  module. Use the PIN_CFG_XXX defines on top */
-	#define PORT_HW_CFG_E3_PWR_DIS_MASK                 0xFF000000
-	#define PORT_HW_CFG_E3_PWR_DIS_SHIFT                         24
-
-	/*
-	 * The input pin which signals module transmit fault. Use the
-	 * PIN_CFG_XXX defines on top
-	 */
-	u32 e3_cmn_pin_cfg;				    /* 0x16C */
-	#define PORT_HW_CFG_E3_TX_FAULT_MASK                0x000000FF
-	#define PORT_HW_CFG_E3_TX_FAULT_SHIFT                        0
-
-	/*  The output pin which reset the PHY. Use the PIN_CFG_XXX defines on
-	 top */
-	#define PORT_HW_CFG_E3_PHY_RESET_MASK               0x0000FF00
-	#define PORT_HW_CFG_E3_PHY_RESET_SHIFT                       8
-
-	/*
-	 * The output pin which powers down the PHY. Use the PIN_CFG_XXX
-	 * defines on top
-	 */
-	#define PORT_HW_CFG_E3_PWR_DOWN_MASK                0x00FF0000
-	#define PORT_HW_CFG_E3_PWR_DOWN_SHIFT                        16
-
-	/*  The output pin values BSC_SEL which selects the I2C for this port
-	  in the I2C Mux */
-	#define PORT_HW_CFG_E3_I2C_MUX0_MASK                0x01000000
-	#define PORT_HW_CFG_E3_I2C_MUX1_MASK                0x02000000
-
-
-	/*
-	 * The input pin I_FAULT which indicate over-current has occurred.
-	 * Use the PIN_CFG_XXX defines on top
-	 */
-	u32 e3_cmn_pin_cfg1;				    /* 0x170 */
-	#define PORT_HW_CFG_E3_OVER_CURRENT_MASK            0x000000FF
-	#define PORT_HW_CFG_E3_OVER_CURRENT_SHIFT                    0
-	u32 reserved0[7];				    /* 0x174 */
-
-	u32 aeu_int_mask;				    /* 0x190 */
-
-	u32 media_type;					    /* 0x194 */
-	#define PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK            0x000000FF
-	#define PORT_HW_CFG_MEDIA_TYPE_PHY0_SHIFT                    0
-
-	#define PORT_HW_CFG_MEDIA_TYPE_PHY1_MASK            0x0000FF00
-	#define PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT                    8
-
-	#define PORT_HW_CFG_MEDIA_TYPE_PHY2_MASK            0x00FF0000
-	#define PORT_HW_CFG_MEDIA_TYPE_PHY2_SHIFT                    16
-
-	/*  4 times 16 bits for all 4 lanes. In case external PHY is present
-	      (not direct mode), those values will not take effect on the 4 XGXS
-	      lanes. For some external PHYs (such as 8706 and 8726) the values
-	      will be used to configure the external PHY  in those cases, not
-	      all 4 values are needed. */
-	u16 xgxs_config_rx[4];			/* 0x198 */
-	u16 xgxs_config_tx[4];			/* 0x1A0 */
-
-	/* For storing FCOE mac on shared memory */
-	u32 fcoe_fip_mac_upper;
-	#define PORT_HW_CFG_FCOE_UPPERMAC_MASK              0x0000ffff
-	#define PORT_HW_CFG_FCOE_UPPERMAC_SHIFT                      0
-	u32 fcoe_fip_mac_lower;
-
-	u32 fcoe_wwn_port_name_upper;
-	u32 fcoe_wwn_port_name_lower;
-
-	u32 fcoe_wwn_node_name_upper;
-	u32 fcoe_wwn_node_name_lower;
-
-	u32 Reserved1[49];				    /* 0x1C0 */
-
-	/*  Enable RJ45 magjack pair swapping on 10GBase-T PHY (0=default),
-	      84833 only */
-	u32 xgbt_phy_cfg;				    /* 0x284 */
-	#define PORT_HW_CFG_RJ45_PAIR_SWAP_MASK             0x000000FF
-	#define PORT_HW_CFG_RJ45_PAIR_SWAP_SHIFT                     0
-
-		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
-
-	/*  Enable RJ45 magjack pair swapping on 10GBase-T PHY, 84833 only */
-	#define PORT_HW_CFG_RJ45_PR_SWP_MASK                0x00400000
-	#define PORT_HW_CFG_RJ45_PR_SWP_SHIFT			     22
-	#define PORT_HW_CFG_RJ45_PR_SWP_DISABLED		     0x00000000
-	#define PORT_HW_CFG_RJ45_PR_SWP_ENABLED			     0x00400000
-
-	/*  Determine the Serdes electrical interface   */
-	#define PORT_HW_CFG_NET_SERDES_IF_MASK              0x0F000000
-	#define PORT_HW_CFG_NET_SERDES_IF_SHIFT                      24
-	#define PORT_HW_CFG_NET_SERDES_IF_SGMII                      0x00000000
-	#define PORT_HW_CFG_NET_SERDES_IF_XFI                        0x01000000
-	#define PORT_HW_CFG_NET_SERDES_IF_SFI                        0x02000000
-	#define PORT_HW_CFG_NET_SERDES_IF_KR                         0x03000000
-	#define PORT_HW_CFG_NET_SERDES_IF_DXGXS                      0x04000000
-	#define PORT_HW_CFG_NET_SERDES_IF_KR2                        0x05000000
-
-
-	u32 speed_capability_mask2;			    /* 0x28C */
-	#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_MASK       0x0000FFFF
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_SHIFT       0
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10M_FULL    0x00000001
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3__           0x00000002
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3___          0x00000004
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_100M_FULL   0x00000008
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_1G          0x00000010
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_2_DOT_5G    0x00000020
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10G         0x00000040
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_20G         0x00000080
-
-	#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_MASK       0xFFFF0000
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_SHIFT       16
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10M_FULL    0x00010000
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0__           0x00020000
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0___          0x00040000
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_100M_FULL   0x00080000
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_1G          0x00100000
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_2_DOT_5G    0x00200000
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10G         0x00400000
-		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_20G         0x00800000
-
-
-	/*  In the case where two media types (e.g. copper and fiber) are
-	      present and electrically active at the same time, PHY Selection
-	      will determine which of the two PHYs will be designated as the
-	      Active PHY and used for a connection to the network.  */
-	u32 multi_phy_config;				    /* 0x290 */
-	#define PORT_HW_CFG_PHY_SELECTION_MASK              0x00000007
-		#define PORT_HW_CFG_PHY_SELECTION_SHIFT              0
-		#define PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT   0x00000000
-		#define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY          0x00000001
-		#define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY         0x00000002
-		#define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY 0x00000003
-		#define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY 0x00000004
-
-	/*  When enabled, all second phy nvram parameters will be swapped
-	      with the first phy parameters */
-	#define PORT_HW_CFG_PHY_SWAPPED_MASK                0x00000008
-		#define PORT_HW_CFG_PHY_SWAPPED_SHIFT                3
-		#define PORT_HW_CFG_PHY_SWAPPED_DISABLED             0x00000000
-		#define PORT_HW_CFG_PHY_SWAPPED_ENABLED              0x00000008
-
-
-	/*  Address of the second external phy */
-	u32 external_phy_config2;			    /* 0x294 */
-	#define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_MASK         0x000000FF
-	#define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_SHIFT                 0
-
-	/*  The second XGXS external PHY type */
-	#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_MASK         0x0000FF00
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SHIFT         8
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_DIRECT        0x00000000
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8071       0x00000100
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8072       0x00000200
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8073       0x00000300
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8705       0x00000400
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8706       0x00000500
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8726       0x00000600
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8481       0x00000700
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SFX7101       0x00000800
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727       0x00000900
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727_NOC   0x00000a00
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84823      0x00000b00
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54640      0x00000c00
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84833      0x00000d00
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54618SE    0x00000e00
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8722       0x00000f00
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE       0x0000fd00
-		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN      0x0000ff00
-
-
-	/*  4 times 16 bits for all 4 lanes. For some external PHYs (such as
-	      8706, 8726 and 8727) not all 4 values are needed. */
-	u16 xgxs_config2_rx[4];				    /* 0x296 */
-	u16 xgxs_config2_tx[4];				    /* 0x2A0 */
-
-	u32 lane_config;
-	#define PORT_HW_CFG_LANE_SWAP_CFG_MASK              0x0000ffff
-		#define PORT_HW_CFG_LANE_SWAP_CFG_SHIFT              0
-		/* AN and forced */
-		#define PORT_HW_CFG_LANE_SWAP_CFG_01230123           0x00001b1b
-		/* forced only */
-		#define PORT_HW_CFG_LANE_SWAP_CFG_01233210           0x00001be4
-		/* forced only */
-		#define PORT_HW_CFG_LANE_SWAP_CFG_31203120           0x0000d8d8
-		/* forced only */
-		#define PORT_HW_CFG_LANE_SWAP_CFG_32103210           0x0000e4e4
-	#define PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK           0x000000ff
-	#define PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT                   0
-	#define PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK           0x0000ff00
-	#define PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT                   8
-	#define PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK       0x0000c000
-	#define PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT               14
-
-	/*  Indicate whether to swap the external phy polarity */
-	#define PORT_HW_CFG_SWAP_PHY_POLARITY_MASK          0x00010000
-		#define PORT_HW_CFG_SWAP_PHY_POLARITY_DISABLED       0x00000000
-		#define PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED        0x00010000
-
-
-	u32 external_phy_config;
-	#define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK          0x000000ff
-	#define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT                  0
-
-	#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK          0x0000ff00
-		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SHIFT          8
-		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT         0x00000000
-		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8071        0x00000100
-		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072        0x00000200
-		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073        0x00000300
-		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705        0x00000400
-		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706        0x00000500
-		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726        0x00000600
-		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481        0x00000700
-		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101        0x00000800
-		#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_BCM54640       0x00000c00
-		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833       0x00000d00
-		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE     0x00000e00
-		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722        0x00000f00
-		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT_WC      0x0000fc00
-		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE        0x0000fd00
-		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN       0x0000ff00
-
-	#define PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK        0x00ff0000
-	#define PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT                16
-
-	#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK        0xff000000
-		#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_SHIFT        24
-		#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT       0x00000000
-		#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482      0x01000000
-		#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT_SD    0x02000000
-		#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN     0xff000000
-
-	u32 speed_capability_mask;
-	#define PORT_HW_CFG_SPEED_CAPABILITY_D3_MASK        0x0000ffff
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_SHIFT        0
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_10M_FULL     0x00000001
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_10M_HALF     0x00000002
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_100M_HALF    0x00000004
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_100M_FULL    0x00000008
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_1G           0x00000010
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_2_5G         0x00000020
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_10G          0x00000040
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_20G          0x00000080
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_RESERVED     0x0000f000
-
-	#define PORT_HW_CFG_SPEED_CAPABILITY_D0_MASK        0xffff0000
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_SHIFT        16
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL     0x00010000
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF     0x00020000
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF    0x00040000
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL    0x00080000
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_1G           0x00100000
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G         0x00200000
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_10G          0x00400000
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_20G          0x00800000
-		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_RESERVED     0xf0000000
-
-	/*  A place to hold the original MAC address as a backup */
-	u32 backup_mac_upper;			/* 0x2B4 */
-	u32 backup_mac_lower;			/* 0x2B8 */
-
-};
-
-
-/****************************************************************************
- * Shared Feature configuration                                             *
- ****************************************************************************/
-struct shared_feat_cfg {		 /* NVRAM Offset */
-
-	u32 config;			/* 0x450 */
-	#define SHARED_FEATURE_BMC_ECHO_MODE_EN             0x00000001
-
-	/* Use NVRAM values instead of HW default values */
-	#define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_MASK \
-							    0x00000002
-		#define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_DISABLED \
-								     0x00000000
-		#define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_ENABLED \
-								     0x00000002
-
-	#define SHARED_FEAT_CFG_NCSI_ID_METHOD_MASK         0x00000008
-		#define SHARED_FEAT_CFG_NCSI_ID_METHOD_SPIO          0x00000000
-		#define SHARED_FEAT_CFG_NCSI_ID_METHOD_NVRAM         0x00000008
-
-	#define SHARED_FEAT_CFG_NCSI_ID_MASK                0x00000030
-	#define SHARED_FEAT_CFG_NCSI_ID_SHIFT                        4
-
-	/*  Override the OTP back to single function mode. When using GPIO,
-	      high means only SF, 0 is according to CLP configuration */
-	#define SHARED_FEAT_CFG_FORCE_SF_MODE_MASK          0x00000700
-		#define SHARED_FEAT_CFG_FORCE_SF_MODE_SHIFT          8
-		#define SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED     0x00000000
-		#define SHARED_FEAT_CFG_FORCE_SF_MODE_FORCED_SF      0x00000100
-		#define SHARED_FEAT_CFG_FORCE_SF_MODE_SPIO4          0x00000200
-		#define SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT  0x00000300
-
-	/* The interval in seconds between sending LLDP packets. Set to zero
-	   to disable the feature */
-	#define SHARED_FEAT_CFG_LLDP_XMIT_INTERVAL_MASK     0x00ff0000
-	#define SHARED_FEAT_CFG_LLDP_XMIT_INTERVAL_SHIFT             16
-
-	/* The assigned device type ID for LLDP usage */
-	#define SHARED_FEAT_CFG_LLDP_DEVICE_TYPE_ID_MASK    0xff000000
-	#define SHARED_FEAT_CFG_LLDP_DEVICE_TYPE_ID_SHIFT            24
-
-};
-
-
-/****************************************************************************
- * Port Feature configuration                                               *
- ****************************************************************************/
-struct port_feat_cfg {		    /* port 0: 0x454  port 1: 0x4c8 */
-
-	u32 config;
-	#define PORT_FEATURE_BAR1_SIZE_MASK                 0x0000000f
-		#define PORT_FEATURE_BAR1_SIZE_SHIFT                 0
-		#define PORT_FEATURE_BAR1_SIZE_DISABLED              0x00000000
-		#define PORT_FEATURE_BAR1_SIZE_64K                   0x00000001
-		#define PORT_FEATURE_BAR1_SIZE_128K                  0x00000002
-		#define PORT_FEATURE_BAR1_SIZE_256K                  0x00000003
-		#define PORT_FEATURE_BAR1_SIZE_512K                  0x00000004
-		#define PORT_FEATURE_BAR1_SIZE_1M                    0x00000005
-		#define PORT_FEATURE_BAR1_SIZE_2M                    0x00000006
-		#define PORT_FEATURE_BAR1_SIZE_4M                    0x00000007
-		#define PORT_FEATURE_BAR1_SIZE_8M                    0x00000008
-		#define PORT_FEATURE_BAR1_SIZE_16M                   0x00000009
-		#define PORT_FEATURE_BAR1_SIZE_32M                   0x0000000a
-		#define PORT_FEATURE_BAR1_SIZE_64M                   0x0000000b
-		#define PORT_FEATURE_BAR1_SIZE_128M                  0x0000000c
-		#define PORT_FEATURE_BAR1_SIZE_256M                  0x0000000d
-		#define PORT_FEATURE_BAR1_SIZE_512M                  0x0000000e
-		#define PORT_FEATURE_BAR1_SIZE_1G                    0x0000000f
-	#define PORT_FEATURE_BAR2_SIZE_MASK                 0x000000f0
-		#define PORT_FEATURE_BAR2_SIZE_SHIFT                 4
-		#define PORT_FEATURE_BAR2_SIZE_DISABLED              0x00000000
-		#define PORT_FEATURE_BAR2_SIZE_64K                   0x00000010
-		#define PORT_FEATURE_BAR2_SIZE_128K                  0x00000020
-		#define PORT_FEATURE_BAR2_SIZE_256K                  0x00000030
-		#define PORT_FEATURE_BAR2_SIZE_512K                  0x00000040
-		#define PORT_FEATURE_BAR2_SIZE_1M                    0x00000050
-		#define PORT_FEATURE_BAR2_SIZE_2M                    0x00000060
-		#define PORT_FEATURE_BAR2_SIZE_4M                    0x00000070
-		#define PORT_FEATURE_BAR2_SIZE_8M                    0x00000080
-		#define PORT_FEATURE_BAR2_SIZE_16M                   0x00000090
-		#define PORT_FEATURE_BAR2_SIZE_32M                   0x000000a0
-		#define PORT_FEATURE_BAR2_SIZE_64M                   0x000000b0
-		#define PORT_FEATURE_BAR2_SIZE_128M                  0x000000c0
-		#define PORT_FEATURE_BAR2_SIZE_256M                  0x000000d0
-		#define PORT_FEATURE_BAR2_SIZE_512M                  0x000000e0
-		#define PORT_FEATURE_BAR2_SIZE_1G                    0x000000f0
-
-	#define PORT_FEAT_CFG_DCBX_MASK                     0x00000100
-		#define PORT_FEAT_CFG_DCBX_DISABLED                  0x00000000
-		#define PORT_FEAT_CFG_DCBX_ENABLED                   0x00000100
-
-	#define PORT_FEAT_CFG_AUTOGREEN_MASK                0x00000200
-	#define PORT_FEAT_CFG_AUTOGREEN_SHIFT                        9
-	#define PORT_FEAT_CFG_AUTOGREEN_DISABLED                     0x00000000
-	#define PORT_FEAT_CFG_AUTOGREEN_ENABLED                      0x00000200
-
-	#define PORT_FEATURE_EN_SIZE_MASK                   0x0f000000
-	#define PORT_FEATURE_EN_SIZE_SHIFT                           24
-	#define PORT_FEATURE_WOL_ENABLED                             0x01000000
-	#define PORT_FEATURE_MBA_ENABLED                             0x02000000
-	#define PORT_FEATURE_MFW_ENABLED                             0x04000000
-
-	/* Advertise expansion ROM even if MBA is disabled */
-	#define PORT_FEAT_CFG_FORCE_EXP_ROM_ADV_MASK        0x08000000
-		#define PORT_FEAT_CFG_FORCE_EXP_ROM_ADV_DISABLED     0x00000000
-		#define PORT_FEAT_CFG_FORCE_EXP_ROM_ADV_ENABLED      0x08000000
-
-	/* Check the optic vendor via i2c against a list of approved modules
-	   in a separate nvram image */
-	#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK         0xe0000000
-		#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_SHIFT         29
-		#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT \
-								     0x00000000
-		#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER \
-								     0x20000000
-		#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_WARNING_MSG   0x40000000
-		#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN    0x60000000
-
-	u32 wol_config;
-	/* Default is used when driver sets to "auto" mode */
-	#define PORT_FEATURE_WOL_DEFAULT_MASK               0x00000003
-		#define PORT_FEATURE_WOL_DEFAULT_SHIFT               0
-		#define PORT_FEATURE_WOL_DEFAULT_DISABLE             0x00000000
-		#define PORT_FEATURE_WOL_DEFAULT_MAGIC               0x00000001
-		#define PORT_FEATURE_WOL_DEFAULT_ACPI                0x00000002
-		#define PORT_FEATURE_WOL_DEFAULT_MAGIC_AND_ACPI      0x00000003
-	#define PORT_FEATURE_WOL_RES_PAUSE_CAP              0x00000004
-	#define PORT_FEATURE_WOL_RES_ASYM_PAUSE_CAP         0x00000008
-	#define PORT_FEATURE_WOL_ACPI_UPON_MGMT             0x00000010
-
-	u32 mba_config;
-	#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK       0x00000007
-		#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_SHIFT       0
-		#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_PXE         0x00000000
-		#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_RPL         0x00000001
-		#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_BOOTP       0x00000002
-		#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_ISCSIB      0x00000003
-		#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_FCOE_BOOT   0x00000004
-		#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_NONE        0x00000007
-
-	#define PORT_FEATURE_MBA_BOOT_RETRY_MASK            0x00000038
-	#define PORT_FEATURE_MBA_BOOT_RETRY_SHIFT                    3
-
-	#define PORT_FEATURE_MBA_RES_PAUSE_CAP              0x00000100
-	#define PORT_FEATURE_MBA_RES_ASYM_PAUSE_CAP         0x00000200
-	#define PORT_FEATURE_MBA_SETUP_PROMPT_ENABLE        0x00000400
-	#define PORT_FEATURE_MBA_HOTKEY_MASK                0x00000800
-		#define PORT_FEATURE_MBA_HOTKEY_CTRL_S               0x00000000
-		#define PORT_FEATURE_MBA_HOTKEY_CTRL_B               0x00000800
-	#define PORT_FEATURE_MBA_EXP_ROM_SIZE_MASK          0x000ff000
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_SHIFT          12
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_DISABLED       0x00000000
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_2K             0x00001000
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_4K             0x00002000
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_8K             0x00003000
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_16K            0x00004000
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_32K            0x00005000
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_64K            0x00006000
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_128K           0x00007000
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_256K           0x00008000
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_512K           0x00009000
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_1M             0x0000a000
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_2M             0x0000b000
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_4M             0x0000c000
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_8M             0x0000d000
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_16M            0x0000e000
-		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_32M            0x0000f000
-	#define PORT_FEATURE_MBA_MSG_TIMEOUT_MASK           0x00f00000
-	#define PORT_FEATURE_MBA_MSG_TIMEOUT_SHIFT                   20
-	#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_MASK        0x03000000
-		#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_SHIFT        24
-		#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_AUTO         0x00000000
-		#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_BBS          0x01000000
-		#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT18H       0x02000000
-		#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT19H       0x03000000
-	#define PORT_FEATURE_MBA_LINK_SPEED_MASK            0x3c000000
-		#define PORT_FEATURE_MBA_LINK_SPEED_SHIFT            26
-		#define PORT_FEATURE_MBA_LINK_SPEED_AUTO             0x00000000
-		#define PORT_FEATURE_MBA_LINK_SPEED_10HD             0x04000000
-		#define PORT_FEATURE_MBA_LINK_SPEED_10FD             0x08000000
-		#define PORT_FEATURE_MBA_LINK_SPEED_100HD            0x0c000000
-		#define PORT_FEATURE_MBA_LINK_SPEED_100FD            0x10000000
-		#define PORT_FEATURE_MBA_LINK_SPEED_1GBPS            0x14000000
-		#define PORT_FEATURE_MBA_LINK_SPEED_2_5GBPS          0x18000000
-		#define PORT_FEATURE_MBA_LINK_SPEED_10GBPS_CX4       0x1c000000
-		#define PORT_FEATURE_MBA_LINK_SPEED_20GBPS           0x20000000
-	u32 bmc_config;
-	#define PORT_FEATURE_BMC_LINK_OVERRIDE_MASK         0x00000001
-		#define PORT_FEATURE_BMC_LINK_OVERRIDE_DEFAULT       0x00000000
-		#define PORT_FEATURE_BMC_LINK_OVERRIDE_EN            0x00000001
-
-	u32 mba_vlan_cfg;
-	#define PORT_FEATURE_MBA_VLAN_TAG_MASK              0x0000ffff
-	#define PORT_FEATURE_MBA_VLAN_TAG_SHIFT                      0
-	#define PORT_FEATURE_MBA_VLAN_EN                    0x00010000
-
-	u32 resource_cfg;
-	#define PORT_FEATURE_RESOURCE_CFG_VALID             0x00000001
-	#define PORT_FEATURE_RESOURCE_CFG_DIAG              0x00000002
-	#define PORT_FEATURE_RESOURCE_CFG_L2                0x00000004
-	#define PORT_FEATURE_RESOURCE_CFG_ISCSI             0x00000008
-	#define PORT_FEATURE_RESOURCE_CFG_RDMA              0x00000010
-
-	u32 smbus_config;
-	#define PORT_FEATURE_SMBUS_ADDR_MASK                0x000000fe
-	#define PORT_FEATURE_SMBUS_ADDR_SHIFT                        1
-
-	u32 vf_config;
-	#define PORT_FEAT_CFG_VF_BAR2_SIZE_MASK             0x0000000f
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_SHIFT             0
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_DISABLED          0x00000000
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_4K                0x00000001
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_8K                0x00000002
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_16K               0x00000003
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_32K               0x00000004
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_64K               0x00000005
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_128K              0x00000006
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_256K              0x00000007
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_512K              0x00000008
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_1M                0x00000009
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_2M                0x0000000a
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_4M                0x0000000b
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_8M                0x0000000c
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_16M               0x0000000d
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_32M               0x0000000e
-		#define PORT_FEAT_CFG_VF_BAR2_SIZE_64M               0x0000000f
-
-	u32 link_config;    /* Used as HW defaults for the driver */
-	#define PORT_FEATURE_CONNECTED_SWITCH_MASK          0x03000000
-		#define PORT_FEATURE_CONNECTED_SWITCH_SHIFT          24
-		/* (forced) low speed switch (< 10G) */
-		#define PORT_FEATURE_CON_SWITCH_1G_SWITCH            0x00000000
-		/* (forced) high speed switch (>= 10G) */
-		#define PORT_FEATURE_CON_SWITCH_10G_SWITCH           0x01000000
-		#define PORT_FEATURE_CON_SWITCH_AUTO_DETECT          0x02000000
-		#define PORT_FEATURE_CON_SWITCH_ONE_TIME_DETECT      0x03000000
-
-	#define PORT_FEATURE_LINK_SPEED_MASK                0x000f0000
-		#define PORT_FEATURE_LINK_SPEED_SHIFT                16
-		#define PORT_FEATURE_LINK_SPEED_AUTO                 0x00000000
-		#define PORT_FEATURE_LINK_SPEED_10M_FULL             0x00010000
-		#define PORT_FEATURE_LINK_SPEED_10M_HALF             0x00020000
-		#define PORT_FEATURE_LINK_SPEED_100M_HALF            0x00030000
-		#define PORT_FEATURE_LINK_SPEED_100M_FULL            0x00040000
-		#define PORT_FEATURE_LINK_SPEED_1G                   0x00050000
-		#define PORT_FEATURE_LINK_SPEED_2_5G                 0x00060000
-		#define PORT_FEATURE_LINK_SPEED_10G_CX4              0x00070000
-		#define PORT_FEATURE_LINK_SPEED_20G                  0x00080000
-
-	#define PORT_FEATURE_FLOW_CONTROL_MASK              0x00000700
-		#define PORT_FEATURE_FLOW_CONTROL_SHIFT              8
-		#define PORT_FEATURE_FLOW_CONTROL_AUTO               0x00000000
-		#define PORT_FEATURE_FLOW_CONTROL_TX                 0x00000100
-		#define PORT_FEATURE_FLOW_CONTROL_RX                 0x00000200
-		#define PORT_FEATURE_FLOW_CONTROL_BOTH               0x00000300
-		#define PORT_FEATURE_FLOW_CONTROL_NONE               0x00000400
-
-	/* The default for MCP link configuration,
-	   uses the same defines as link_config */
-	u32 mfw_wol_link_cfg;
-
-	/* The default for the driver of the second external phy,
-	   uses the same defines as link_config */
-	u32 link_config2;				    /* 0x47C */
-
-	/* The default for MCP of the second external phy,
-	   uses the same defines as link_config */
-	u32 mfw_wol_link_cfg2;				    /* 0x480 */
-
-	u32 Reserved2[17];				    /* 0x484 */
-
-};
-
-
-/****************************************************************************
- * Device Information                                                       *
- ****************************************************************************/
-struct shm_dev_info {				/* size */
-
-	u32    bc_rev; /* 8 bits each: major, minor, build */	       /* 4 */
-
-	struct shared_hw_cfg     shared_hw_config;	      /* 40 */
-
-	struct port_hw_cfg       port_hw_config[PORT_MAX];     /* 400*2=800 */
-
-	struct shared_feat_cfg   shared_feature_config;		   /* 4 */
-
-	struct port_feat_cfg     port_feature_config[PORT_MAX];/* 116*2=232 */
-
-};
-
-
-#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
-	#error "Missing either LITTLE_ENDIAN or BIG_ENDIAN definition."
-#endif
-
-#define FUNC_0              0
-#define FUNC_1              1
-#define FUNC_2              2
-#define FUNC_3              3
-#define FUNC_4              4
-#define FUNC_5              5
-#define FUNC_6              6
-#define FUNC_7              7
-#define E1_FUNC_MAX         2
-#define E1H_FUNC_MAX            8
-#define E2_FUNC_MAX         4   /* per path */
-
-#define VN_0                0
-#define VN_1                1
-#define VN_2                2
-#define VN_3                3
-#define E1VN_MAX            1
-#define E1HVN_MAX           4
-
-#define E2_VF_MAX           64  /* HC_REG_VF_CONFIGURATION_SIZE */
-/* This value (in milliseconds) determines the frequency of the driver
- * issuing the PULSE message code.  The firmware monitors this periodic
- * pulse to determine when to switch to an OS-absent mode. */
-#define DRV_PULSE_PERIOD_MS     250
-
-/* This value (in milliseconds) determines how long the driver should
- * wait for an acknowledgement from the firmware before timing out.  Once
- * the firmware has timed out, the driver will assume there is no firmware
- * running and there won't be any firmware-driver synchronization during a
- * driver reset. */
-#define FW_ACK_TIME_OUT_MS      5000
-
-#define FW_ACK_POLL_TIME_MS     1
-
-#define FW_ACK_NUM_OF_POLL  (FW_ACK_TIME_OUT_MS/FW_ACK_POLL_TIME_MS)
-
-/* LED Blink rate that will achieve ~15.9Hz */
-#define LED_BLINK_RATE_VAL      480
-
-/****************************************************************************
- * Driver <-> FW Mailbox                                                    *
- ****************************************************************************/
-struct drv_port_mb {
-
-	u32 link_status;
-	/* Driver should update this field on any link change event */
-
-	#define LINK_STATUS_LINK_FLAG_MASK			0x00000001
-	#define LINK_STATUS_LINK_UP				0x00000001
-	#define LINK_STATUS_SPEED_AND_DUPLEX_MASK		0x0000001E
-	#define LINK_STATUS_SPEED_AND_DUPLEX_AN_NOT_COMPLETE	(0<<1)
-	#define LINK_STATUS_SPEED_AND_DUPLEX_10THD		(1<<1)
-	#define LINK_STATUS_SPEED_AND_DUPLEX_10TFD		(2<<1)
-	#define LINK_STATUS_SPEED_AND_DUPLEX_100TXHD		(3<<1)
-	#define LINK_STATUS_SPEED_AND_DUPLEX_100T4		(4<<1)
-	#define LINK_STATUS_SPEED_AND_DUPLEX_100TXFD		(5<<1)
-	#define LINK_STATUS_SPEED_AND_DUPLEX_1000THD		(6<<1)
-	#define LINK_STATUS_SPEED_AND_DUPLEX_1000TFD		(7<<1)
-	#define LINK_STATUS_SPEED_AND_DUPLEX_1000XFD		(7<<1)
-	#define LINK_STATUS_SPEED_AND_DUPLEX_2500THD		(8<<1)
-	#define LINK_STATUS_SPEED_AND_DUPLEX_2500TFD		(9<<1)
-	#define LINK_STATUS_SPEED_AND_DUPLEX_2500XFD		(9<<1)
-	#define LINK_STATUS_SPEED_AND_DUPLEX_10GTFD		(10<<1)
-	#define LINK_STATUS_SPEED_AND_DUPLEX_10GXFD		(10<<1)
-	#define LINK_STATUS_SPEED_AND_DUPLEX_20GTFD		(11<<1)
-	#define LINK_STATUS_SPEED_AND_DUPLEX_20GXFD		(11<<1)
-
-	#define LINK_STATUS_AUTO_NEGOTIATE_FLAG_MASK		0x00000020
-	#define LINK_STATUS_AUTO_NEGOTIATE_ENABLED		0x00000020
-
-	#define LINK_STATUS_AUTO_NEGOTIATE_COMPLETE		0x00000040
-	#define LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK	0x00000080
-	#define LINK_STATUS_PARALLEL_DETECTION_USED		0x00000080
-
-	#define LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE	0x00000200
-	#define LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE	0x00000400
-	#define LINK_STATUS_LINK_PARTNER_100T4_CAPABLE		0x00000800
-	#define LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE	0x00001000
-	#define LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE	0x00002000
-	#define LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE		0x00004000
-	#define LINK_STATUS_LINK_PARTNER_10THD_CAPABLE		0x00008000
-
-	#define LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK		0x00010000
-	#define LINK_STATUS_TX_FLOW_CONTROL_ENABLED		0x00010000
-
-	#define LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK		0x00020000
-	#define LINK_STATUS_RX_FLOW_CONTROL_ENABLED		0x00020000
-
-	#define LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK	0x000C0000
-	#define LINK_STATUS_LINK_PARTNER_NOT_PAUSE_CAPABLE	(0<<18)
-	#define LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE	(1<<18)
-	#define LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE	(2<<18)
-	#define LINK_STATUS_LINK_PARTNER_BOTH_PAUSE		(3<<18)
-
-	#define LINK_STATUS_SERDES_LINK				0x00100000
-
-	#define LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE	0x00200000
-	#define LINK_STATUS_LINK_PARTNER_2500XHD_CAPABLE	0x00400000
-	#define LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE		0x00800000
-	#define LINK_STATUS_LINK_PARTNER_20GXFD_CAPABLE		0x10000000
-
-	#define LINK_STATUS_PFC_ENABLED				0x20000000
-
-	#define LINK_STATUS_PHYSICAL_LINK_FLAG			0x40000000
-
-	u32 port_stx;
-
-	u32 stat_nig_timer;
-
-	/* MCP firmware does not use this field */
-	u32 ext_phy_fw_version;
-
-};
-
-
-struct drv_func_mb {
-
-	u32 drv_mb_header;
-	#define DRV_MSG_CODE_MASK                       0xffff0000
-	#define DRV_MSG_CODE_LOAD_REQ                   0x10000000
-	#define DRV_MSG_CODE_LOAD_DONE                  0x11000000
-	#define DRV_MSG_CODE_UNLOAD_REQ_WOL_EN          0x20000000
-	#define DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS         0x20010000
-	#define DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP         0x20020000
-	#define DRV_MSG_CODE_UNLOAD_DONE                0x21000000
-	#define DRV_MSG_CODE_DCC_OK                     0x30000000
-	#define DRV_MSG_CODE_DCC_FAILURE                0x31000000
-	#define DRV_MSG_CODE_DIAG_ENTER_REQ             0x50000000
-	#define DRV_MSG_CODE_DIAG_EXIT_REQ              0x60000000
-	#define DRV_MSG_CODE_VALIDATE_KEY               0x70000000
-	#define DRV_MSG_CODE_GET_CURR_KEY               0x80000000
-	#define DRV_MSG_CODE_GET_UPGRADE_KEY            0x81000000
-	#define DRV_MSG_CODE_GET_MANUF_KEY              0x82000000
-	#define DRV_MSG_CODE_LOAD_L2B_PRAM              0x90000000
-	/*
-	 * The optic module verification command requires bootcode
-	 * v5.0.6 or later, te specific optic module verification command
-	 * requires bootcode v5.2.12 or later
-	 */
-	#define DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL     0xa0000000
-	#define REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL     0x00050006
-	#define DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL  0xa1000000
-	#define REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL  0x00050234
-	#define REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED   0x00070014
-
-	#define DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG         0xb0000000
-	#define DRV_MSG_CODE_DCBX_PMF_DRV_OK            0xb2000000
-
-	#define DRV_MSG_CODE_VF_DISABLED_DONE           0xc0000000
-
-	#define DRV_MSG_CODE_SET_MF_BW                  0xe0000000
-	#define REQ_BC_VER_4_SET_MF_BW                  0x00060202
-	#define DRV_MSG_CODE_SET_MF_BW_ACK              0xe1000000
-
-	#define DRV_MSG_CODE_LINK_STATUS_CHANGED        0x01000000
-
-	#define BIOS_MSG_CODE_LIC_CHALLENGE             0xff010000
-	#define BIOS_MSG_CODE_LIC_RESPONSE              0xff020000
-	#define BIOS_MSG_CODE_VIRT_MAC_PRIM             0xff030000
-	#define BIOS_MSG_CODE_VIRT_MAC_ISCSI            0xff040000
-
-	#define DRV_MSG_SEQ_NUMBER_MASK                 0x0000ffff
-
-	u32 drv_mb_param;
-	#define DRV_MSG_CODE_SET_MF_BW_MIN_MASK         0x00ff0000
-	#define DRV_MSG_CODE_SET_MF_BW_MAX_MASK         0xff000000
-
-	u32 fw_mb_header;
-	#define FW_MSG_CODE_MASK                        0xffff0000
-	#define FW_MSG_CODE_DRV_LOAD_COMMON             0x10100000
-	#define FW_MSG_CODE_DRV_LOAD_PORT               0x10110000
-	#define FW_MSG_CODE_DRV_LOAD_FUNCTION           0x10120000
-	/* Load common chip is supported from bc 6.0.0  */
-	#define REQ_BC_VER_4_DRV_LOAD_COMMON_CHIP       0x00060000
-	#define FW_MSG_CODE_DRV_LOAD_COMMON_CHIP        0x10130000
-
-	#define FW_MSG_CODE_DRV_LOAD_REFUSED            0x10200000
-	#define FW_MSG_CODE_DRV_LOAD_DONE               0x11100000
-	#define FW_MSG_CODE_DRV_UNLOAD_COMMON           0x20100000
-	#define FW_MSG_CODE_DRV_UNLOAD_PORT             0x20110000
-	#define FW_MSG_CODE_DRV_UNLOAD_FUNCTION         0x20120000
-	#define FW_MSG_CODE_DRV_UNLOAD_DONE             0x21100000
-	#define FW_MSG_CODE_DCC_DONE                    0x30100000
-	#define FW_MSG_CODE_LLDP_DONE                   0x40100000
-	#define FW_MSG_CODE_DIAG_ENTER_DONE             0x50100000
-	#define FW_MSG_CODE_DIAG_REFUSE                 0x50200000
-	#define FW_MSG_CODE_DIAG_EXIT_DONE              0x60100000
-	#define FW_MSG_CODE_VALIDATE_KEY_SUCCESS        0x70100000
-	#define FW_MSG_CODE_VALIDATE_KEY_FAILURE        0x70200000
-	#define FW_MSG_CODE_GET_KEY_DONE                0x80100000
-	#define FW_MSG_CODE_NO_KEY                      0x80f00000
-	#define FW_MSG_CODE_LIC_INFO_NOT_READY          0x80f80000
-	#define FW_MSG_CODE_L2B_PRAM_LOADED             0x90100000
-	#define FW_MSG_CODE_L2B_PRAM_T_LOAD_FAILURE     0x90210000
-	#define FW_MSG_CODE_L2B_PRAM_C_LOAD_FAILURE     0x90220000
-	#define FW_MSG_CODE_L2B_PRAM_X_LOAD_FAILURE     0x90230000
-	#define FW_MSG_CODE_L2B_PRAM_U_LOAD_FAILURE     0x90240000
-	#define FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS        0xa0100000
-	#define FW_MSG_CODE_VRFY_OPT_MDL_INVLD_IMG      0xa0200000
-	#define FW_MSG_CODE_VRFY_OPT_MDL_UNAPPROVED     0xa0300000
-	#define FW_MSG_CODE_VF_DISABLED_DONE            0xb0000000
-
-	#define FW_MSG_CODE_SET_MF_BW_SENT              0xe0000000
-	#define FW_MSG_CODE_SET_MF_BW_DONE              0xe1000000
-
-	#define FW_MSG_CODE_LINK_CHANGED_ACK            0x01100000
-
-	#define FW_MSG_CODE_LIC_CHALLENGE               0xff010000
-	#define FW_MSG_CODE_LIC_RESPONSE                0xff020000
-	#define FW_MSG_CODE_VIRT_MAC_PRIM               0xff030000
-	#define FW_MSG_CODE_VIRT_MAC_ISCSI              0xff040000
-
-	#define FW_MSG_SEQ_NUMBER_MASK                  0x0000ffff
-
-	u32 fw_mb_param;
-
-	u32 drv_pulse_mb;
-	#define DRV_PULSE_SEQ_MASK                      0x00007fff
-	#define DRV_PULSE_SYSTEM_TIME_MASK              0xffff0000
-	/*
-	 * The system time is in the format of
-	 * (year-2001)*12*32 + month*32 + day.
-	 */
-	#define DRV_PULSE_ALWAYS_ALIVE                  0x00008000
-	/*
-	 * Indicate to the firmware not to go into the
-	 * OS-absent when it is not getting driver pulse.
-	 * This is used for debugging as well for PXE(MBA).
-	 */
-
-	u32 mcp_pulse_mb;
-	#define MCP_PULSE_SEQ_MASK                      0x00007fff
-	#define MCP_PULSE_ALWAYS_ALIVE                  0x00008000
-	/* Indicates to the driver not to assert due to lack
-	 * of MCP response */
-	#define MCP_EVENT_MASK                          0xffff0000
-	#define MCP_EVENT_OTHER_DRIVER_RESET_REQ        0x00010000
-
-	u32 iscsi_boot_signature;
-	u32 iscsi_boot_block_offset;
-
-	u32 drv_status;
-	#define DRV_STATUS_PMF                          0x00000001
-	#define DRV_STATUS_VF_DISABLED                  0x00000002
-	#define DRV_STATUS_SET_MF_BW                    0x00000004
-	#define DRV_STATUS_LINK_EVENT                   0x00000008
-
-	#define DRV_STATUS_DCC_EVENT_MASK               0x0000ff00
-	#define DRV_STATUS_DCC_DISABLE_ENABLE_PF        0x00000100
-	#define DRV_STATUS_DCC_BANDWIDTH_ALLOCATION     0x00000200
-	#define DRV_STATUS_DCC_CHANGE_MAC_ADDRESS       0x00000400
-	#define DRV_STATUS_DCC_RESERVED1                0x00000800
-	#define DRV_STATUS_DCC_SET_PROTOCOL             0x00001000
-	#define DRV_STATUS_DCC_SET_PRIORITY             0x00002000
-
-	#define DRV_STATUS_DCBX_EVENT_MASK              0x000f0000
-	#define DRV_STATUS_DCBX_NEGOTIATION_RESULTS     0x00010000
-
-	u32 virt_mac_upper;
-	#define VIRT_MAC_SIGN_MASK                      0xffff0000
-	#define VIRT_MAC_SIGNATURE                      0x564d0000
-	u32 virt_mac_lower;
-
-};
-
-
-/****************************************************************************
- * Management firmware state                                                *
- ****************************************************************************/
-/* Allocate 440 bytes for management firmware */
-#define MGMTFW_STATE_WORD_SIZE                          110
-
-struct mgmtfw_state {
-	u32 opaque[MGMTFW_STATE_WORD_SIZE];
-};
-
-
-/****************************************************************************
- * Multi-Function configuration                                             *
- ****************************************************************************/
-struct shared_mf_cfg {
-
-	u32 clp_mb;
-	#define SHARED_MF_CLP_SET_DEFAULT               0x00000000
-	/* set by CLP */
-	#define SHARED_MF_CLP_EXIT                      0x00000001
-	/* set by MCP */
-	#define SHARED_MF_CLP_EXIT_DONE                 0x00010000
-
-};
-
-struct port_mf_cfg {
-
-	u32 dynamic_cfg;    /* device control channel */
-	#define PORT_MF_CFG_E1HOV_TAG_MASK              0x0000ffff
-	#define PORT_MF_CFG_E1HOV_TAG_SHIFT             0
-	#define PORT_MF_CFG_E1HOV_TAG_DEFAULT         PORT_MF_CFG_E1HOV_TAG_MASK
-
-	u32 reserved[3];
-
-};
-
-struct func_mf_cfg {
-
-	u32 config;
-	/* E/R/I/D */
-	/* function 0 of each port cannot be hidden */
-	#define FUNC_MF_CFG_FUNC_HIDE                   0x00000001
-
-	#define FUNC_MF_CFG_PROTOCOL_MASK               0x00000006
-	#define FUNC_MF_CFG_PROTOCOL_FCOE               0x00000000
-	#define FUNC_MF_CFG_PROTOCOL_ETHERNET           0x00000002
-	#define FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA 0x00000004
-	#define FUNC_MF_CFG_PROTOCOL_ISCSI              0x00000006
-	#define FUNC_MF_CFG_PROTOCOL_DEFAULT \
-				FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA
-
-	#define FUNC_MF_CFG_FUNC_DISABLED               0x00000008
-	#define FUNC_MF_CFG_FUNC_DELETED                0x00000010
-
-	/* PRI */
-	/* 0 - low priority, 3 - high priority */
-	#define FUNC_MF_CFG_TRANSMIT_PRIORITY_MASK      0x00000300
-	#define FUNC_MF_CFG_TRANSMIT_PRIORITY_SHIFT     8
-	#define FUNC_MF_CFG_TRANSMIT_PRIORITY_DEFAULT   0x00000000
-
-	/* MINBW, MAXBW */
-	/* value range - 0..100, increments in 100Mbps */
-	#define FUNC_MF_CFG_MIN_BW_MASK                 0x00ff0000
-	#define FUNC_MF_CFG_MIN_BW_SHIFT                16
-	#define FUNC_MF_CFG_MIN_BW_DEFAULT              0x00000000
-	#define FUNC_MF_CFG_MAX_BW_MASK                 0xff000000
-	#define FUNC_MF_CFG_MAX_BW_SHIFT                24
-	#define FUNC_MF_CFG_MAX_BW_DEFAULT              0x64000000
-
-	u32 mac_upper;	    /* MAC */
-	#define FUNC_MF_CFG_UPPERMAC_MASK               0x0000ffff
-	#define FUNC_MF_CFG_UPPERMAC_SHIFT              0
-	#define FUNC_MF_CFG_UPPERMAC_DEFAULT           FUNC_MF_CFG_UPPERMAC_MASK
-	u32 mac_lower;
-	#define FUNC_MF_CFG_LOWERMAC_DEFAULT            0xffffffff
-
-	u32 e1hov_tag;	/* VNI */
-	#define FUNC_MF_CFG_E1HOV_TAG_MASK              0x0000ffff
-	#define FUNC_MF_CFG_E1HOV_TAG_SHIFT             0
-	#define FUNC_MF_CFG_E1HOV_TAG_DEFAULT         FUNC_MF_CFG_E1HOV_TAG_MASK
-
-	u32 reserved[2];
-};
-
-/* This structure is not applicable and should not be accessed on 57711 */
-struct func_ext_cfg {
-	u32 func_cfg;
-	#define MACP_FUNC_CFG_FLAGS_MASK                0x000000FF
-	#define MACP_FUNC_CFG_FLAGS_SHIFT               0
-	#define MACP_FUNC_CFG_FLAGS_ENABLED             0x00000001
-	#define MACP_FUNC_CFG_FLAGS_ETHERNET            0x00000002
-	#define MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD       0x00000004
-	#define MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD        0x00000008
-
-	u32 iscsi_mac_addr_upper;
-	u32 iscsi_mac_addr_lower;
-
-	u32 fcoe_mac_addr_upper;
-	u32 fcoe_mac_addr_lower;
-
-	u32 fcoe_wwn_port_name_upper;
-	u32 fcoe_wwn_port_name_lower;
-
-	u32 fcoe_wwn_node_name_upper;
-	u32 fcoe_wwn_node_name_lower;
-
-	u32 preserve_data;
-	#define MF_FUNC_CFG_PRESERVE_L2_MAC             (1<<0)
-	#define MF_FUNC_CFG_PRESERVE_ISCSI_MAC          (1<<1)
-	#define MF_FUNC_CFG_PRESERVE_FCOE_MAC           (1<<2)
-	#define MF_FUNC_CFG_PRESERVE_FCOE_WWN_P         (1<<3)
-	#define MF_FUNC_CFG_PRESERVE_FCOE_WWN_N         (1<<4)
-	#define MF_FUNC_CFG_PRESERVE_TX_BW              (1<<5)
-};
-
-struct mf_cfg {
-
-	struct shared_mf_cfg    shared_mf_config;       /* 0x4 */
-	struct port_mf_cfg  port_mf_config[PORT_MAX];   /* 0x10 * 2 = 0x20 */
-	/* for all chips, there are 8 mf functions */
-	struct func_mf_cfg  func_mf_config[E1H_FUNC_MAX]; /* 0x18 * 8 = 0xc0 */
-	/*
-	 * Extended configuration per function  - this array does not exist and
-	 * should not be accessed on 57711
-	 */
-	struct func_ext_cfg func_ext_config[E1H_FUNC_MAX]; /* 0x28 * 8 = 0x140*/
-}; /* 0x224 */
-
-/****************************************************************************
- * Shared Memory Region                                                     *
- ****************************************************************************/
-struct shmem_region {		       /*   SharedMem Offset (size) */
-
-	u32         validity_map[PORT_MAX];  /* 0x0 (4*2 = 0x8) */
-	#define SHR_MEM_FORMAT_REV_MASK                     0xff000000
-	#define SHR_MEM_FORMAT_REV_ID                       ('A'<<24)
-	/* validity bits */
-	#define SHR_MEM_VALIDITY_PCI_CFG                    0x00100000
-	#define SHR_MEM_VALIDITY_MB                         0x00200000
-	#define SHR_MEM_VALIDITY_DEV_INFO                   0x00400000
-	#define SHR_MEM_VALIDITY_RESERVED                   0x00000007
-	/* One licensing bit should be set */
-	#define SHR_MEM_VALIDITY_LIC_KEY_IN_EFFECT_MASK     0x00000038
-	#define SHR_MEM_VALIDITY_LIC_MANUF_KEY_IN_EFFECT    0x00000008
-	#define SHR_MEM_VALIDITY_LIC_UPGRADE_KEY_IN_EFFECT  0x00000010
-	#define SHR_MEM_VALIDITY_LIC_NO_KEY_IN_EFFECT       0x00000020
-	/* Active MFW */
-	#define SHR_MEM_VALIDITY_ACTIVE_MFW_UNKNOWN         0x00000000
-	#define SHR_MEM_VALIDITY_ACTIVE_MFW_MASK            0x000001c0
-	#define SHR_MEM_VALIDITY_ACTIVE_MFW_IPMI            0x00000040
-	#define SHR_MEM_VALIDITY_ACTIVE_MFW_UMP             0x00000080
-	#define SHR_MEM_VALIDITY_ACTIVE_MFW_NCSI            0x000000c0
-	#define SHR_MEM_VALIDITY_ACTIVE_MFW_NONE            0x000001c0
-
-	struct shm_dev_info dev_info;	     /* 0x8     (0x438) */
-
-	struct license_key       drv_lic_key[PORT_MAX]; /* 0x440 (52*2=0x68) */
-
-	/* FW information (for internal FW use) */
-	u32         fw_info_fio_offset;		/* 0x4a8       (0x4) */
-	struct mgmtfw_state mgmtfw_state;	/* 0x4ac     (0x1b8) */
-
-	struct drv_port_mb  port_mb[PORT_MAX];	/* 0x664 (16*2=0x20) */
-
-#ifdef BMAPI
-	/* This is a variable length array */
-	/* the number of function depends on the chip type */
-	struct drv_func_mb func_mb[1];	/* 0x684 (44*2/4/8=0x58/0xb0/0x160) */
-#else
-	/* the number of function depends on the chip type */
-	struct drv_func_mb  func_mb[];	/* 0x684 (44*2/4/8=0x58/0xb0/0x160) */
-#endif /* BMAPI */
-
-}; /* 57710 = 0x6dc | 57711 = 0x7E4 | 57712 = 0x734 */
-
-/****************************************************************************
- * Shared Memory 2 Region                                                   *
- ****************************************************************************/
-/* The fw_flr_ack is actually built in the following way:                   */
-/* 8 bit:  PF ack                                                           */
-/* 64 bit: VF ack                                                           */
-/* 8 bit:  ios_dis_ack                                                      */
-/* In order to maintain endianity in the mailbox hsi, we want to keep using */
-/* u32. The fw must have the VF right after the PF since this is how it     */
-/* access arrays(it expects always the VF to reside after the PF, and that  */
-/* makes the calculation much easier for it. )                              */
-/* In order to answer both limitations, and keep the struct small, the code */
-/* will abuse the structure defined here to achieve the actual partition    */
-/* above                                                                    */
-/****************************************************************************/
-struct fw_flr_ack {
-	u32         pf_ack;
-	u32         vf_ack[1];
-	u32         iov_dis_ack;
-};
-
-struct fw_flr_mb {
-	u32         aggint;
-	u32         opgen_addr;
-	struct fw_flr_ack ack;
-};
-
-/**** SUPPORT FOR SHMEM ARRRAYS ***
- * The SHMEM HSI is aligned on 32 bit boundaries which makes it difficult to
- * define arrays with storage types smaller then unsigned dwords.
- * The macros below add generic support for SHMEM arrays with numeric elements
- * that can span 2,4,8 or 16 bits. The array underlying type is a 32 bit dword
- * array with individual bit-filed elements accessed using shifts and masks.
- *
- */
-
-/* eb is the bitwidth of a single element */
-#define SHMEM_ARRAY_MASK(eb)		((1<<(eb))-1)
-#define SHMEM_ARRAY_ENTRY(i, eb)	((i)/(32/(eb)))
-
-/* the bit-position macro allows the used to flip the order of the arrays
- * elements on a per byte or word boundary.
- *
- * example: an array with 8 entries each 4 bit wide. This array will fit into
- * a single dword. The diagrmas below show the array order of the nibbles.
- *
- * SHMEM_ARRAY_BITPOS(i, 4, 4) defines the stadard ordering:
- *
- *                |                |                |               |
- *   0    |   1   |   2    |   3   |   4    |   5   |   6   |   7   |
- *                |                |                |               |
- *
- * SHMEM_ARRAY_BITPOS(i, 4, 8) defines a flip ordering per byte:
- *
- *                |                |                |               |
- *   1   |   0    |   3    |   2   |   5    |   4   |   7   |   6   |
- *                |                |                |               |
- *
- * SHMEM_ARRAY_BITPOS(i, 4, 16) defines a flip ordering per word:
- *
- *                |                |                |               |
- *   3   |   2    |   1   |   0    |   7   |   6    |   5   |   4   |
- *                |                |                |               |
- */
-#define SHMEM_ARRAY_BITPOS(i, eb, fb)	\
-	((((32/(fb)) - 1 - ((i)/((fb)/(eb))) % (32/(fb))) * (fb)) + \
-	(((i)%((fb)/(eb))) * (eb)))
-
-#define SHMEM_ARRAY_GET(a, i, eb, fb)					\
-	((a[SHMEM_ARRAY_ENTRY(i, eb)] >> SHMEM_ARRAY_BITPOS(i, eb, fb)) &  \
-	SHMEM_ARRAY_MASK(eb))
-
-#define SHMEM_ARRAY_SET(a, i, eb, fb, val)				\
-do {									   \
-	a[SHMEM_ARRAY_ENTRY(i, eb)] &= ~(SHMEM_ARRAY_MASK(eb) <<	   \
-	SHMEM_ARRAY_BITPOS(i, eb, fb));					   \
-	a[SHMEM_ARRAY_ENTRY(i, eb)] |= (((val) & SHMEM_ARRAY_MASK(eb)) <<  \
-	SHMEM_ARRAY_BITPOS(i, eb, fb));					   \
-} while (0)
-
-
-/****START OF DCBX STRUCTURES DECLARATIONS****/
-#define DCBX_MAX_NUM_PRI_PG_ENTRIES	8
-#define DCBX_PRI_PG_BITWIDTH		4
-#define DCBX_PRI_PG_FBITS		8
-#define DCBX_PRI_PG_GET(a, i)		\
-	SHMEM_ARRAY_GET(a, i, DCBX_PRI_PG_BITWIDTH, DCBX_PRI_PG_FBITS)
-#define DCBX_PRI_PG_SET(a, i, val)	\
-	SHMEM_ARRAY_SET(a, i, DCBX_PRI_PG_BITWIDTH, DCBX_PRI_PG_FBITS, val)
-#define DCBX_MAX_NUM_PG_BW_ENTRIES	8
-#define DCBX_BW_PG_BITWIDTH		8
-#define DCBX_PG_BW_GET(a, i)		\
-	SHMEM_ARRAY_GET(a, i, DCBX_BW_PG_BITWIDTH, DCBX_BW_PG_BITWIDTH)
-#define DCBX_PG_BW_SET(a, i, val)	\
-	SHMEM_ARRAY_SET(a, i, DCBX_BW_PG_BITWIDTH, DCBX_BW_PG_BITWIDTH, val)
-#define DCBX_STRICT_PRI_PG		15
-#define DCBX_MAX_APP_PROTOCOL		16
-#define FCOE_APP_IDX			0
-#define ISCSI_APP_IDX			1
-#define PREDEFINED_APP_IDX_MAX		2
-
-
-/* Big/Little endian have the same representation. */
-struct dcbx_ets_feature {
-	/*
-	 * For Admin MIB - is this feature supported by the
-	 * driver | For Local MIB - should this feature be enabled.
-	 */
-	u32 enabled;
-	u32  pg_bw_tbl[2];
-	u32  pri_pg_tbl[1];
-};
-
-/* Driver structure in LE */
-struct dcbx_pfc_feature {
-#ifdef __BIG_ENDIAN
-	u8 pri_en_bitmap;
-	#define DCBX_PFC_PRI_0 0x01
-	#define DCBX_PFC_PRI_1 0x02
-	#define DCBX_PFC_PRI_2 0x04
-	#define DCBX_PFC_PRI_3 0x08
-	#define DCBX_PFC_PRI_4 0x10
-	#define DCBX_PFC_PRI_5 0x20
-	#define DCBX_PFC_PRI_6 0x40
-	#define DCBX_PFC_PRI_7 0x80
-	u8 pfc_caps;
-	u8 reserved;
-	u8 enabled;
-#elif defined(__LITTLE_ENDIAN)
-	u8 enabled;
-	u8 reserved;
-	u8 pfc_caps;
-	u8 pri_en_bitmap;
-	#define DCBX_PFC_PRI_0 0x01
-	#define DCBX_PFC_PRI_1 0x02
-	#define DCBX_PFC_PRI_2 0x04
-	#define DCBX_PFC_PRI_3 0x08
-	#define DCBX_PFC_PRI_4 0x10
-	#define DCBX_PFC_PRI_5 0x20
-	#define DCBX_PFC_PRI_6 0x40
-	#define DCBX_PFC_PRI_7 0x80
-#endif
-};
-
-struct dcbx_app_priority_entry {
-#ifdef __BIG_ENDIAN
-	u16  app_id;
-	u8  pri_bitmap;
-	u8  appBitfield;
-	#define DCBX_APP_ENTRY_VALID         0x01
-	#define DCBX_APP_ENTRY_SF_MASK       0x30
-	#define DCBX_APP_ENTRY_SF_SHIFT      4
-	#define DCBX_APP_SF_ETH_TYPE         0x10
-	#define DCBX_APP_SF_PORT             0x20
-#elif defined(__LITTLE_ENDIAN)
-	u8 appBitfield;
-	#define DCBX_APP_ENTRY_VALID         0x01
-	#define DCBX_APP_ENTRY_SF_MASK       0x30
-	#define DCBX_APP_ENTRY_SF_SHIFT      4
-	#define DCBX_APP_SF_ETH_TYPE         0x10
-	#define DCBX_APP_SF_PORT             0x20
-	u8  pri_bitmap;
-	u16  app_id;
-#endif
-};
-
-
-/* FW structure in BE */
-struct dcbx_app_priority_feature {
-#ifdef __BIG_ENDIAN
-	u8 reserved;
-	u8 default_pri;
-	u8 tc_supported;
-	u8 enabled;
-#elif defined(__LITTLE_ENDIAN)
-	u8 enabled;
-	u8 tc_supported;
-	u8 default_pri;
-	u8 reserved;
-#endif
-	struct dcbx_app_priority_entry  app_pri_tbl[DCBX_MAX_APP_PROTOCOL];
-};
-
-/* FW structure in BE */
-struct dcbx_features {
-	/* PG feature */
-	struct dcbx_ets_feature ets;
-	/* PFC feature */
-	struct dcbx_pfc_feature pfc;
-	/* APP feature */
-	struct dcbx_app_priority_feature app;
-};
-
-/* LLDP protocol parameters */
-/* FW structure in BE */
-struct lldp_params {
-#ifdef __BIG_ENDIAN
-	u8  msg_fast_tx_interval;
-	u8  msg_tx_hold;
-	u8  msg_tx_interval;
-	u8  admin_status;
-	#define LLDP_TX_ONLY  0x01
-	#define LLDP_RX_ONLY  0x02
-	#define LLDP_TX_RX    0x03
-	#define LLDP_DISABLED 0x04
-	u8  reserved1;
-	u8  tx_fast;
-	u8  tx_crd_max;
-	u8  tx_crd;
-#elif defined(__LITTLE_ENDIAN)
-	u8  admin_status;
-	#define LLDP_TX_ONLY  0x01
-	#define LLDP_RX_ONLY  0x02
-	#define LLDP_TX_RX    0x03
-	#define LLDP_DISABLED 0x04
-	u8  msg_tx_interval;
-	u8  msg_tx_hold;
-	u8  msg_fast_tx_interval;
-	u8  tx_crd;
-	u8  tx_crd_max;
-	u8  tx_fast;
-	u8  reserved1;
-#endif
-	#define REM_CHASSIS_ID_STAT_LEN 4
-	#define REM_PORT_ID_STAT_LEN 4
-	/* Holds remote Chassis ID TLV header, subtype and 9B of payload. */
-	u32 peer_chassis_id[REM_CHASSIS_ID_STAT_LEN];
-	/* Holds remote Port ID TLV header, subtype and 9B of payload. */
-	u32 peer_port_id[REM_PORT_ID_STAT_LEN];
-};
-
-struct lldp_dcbx_stat {
-	#define LOCAL_CHASSIS_ID_STAT_LEN 2
-	#define LOCAL_PORT_ID_STAT_LEN 2
-	/* Holds local Chassis ID 8B payload of constant subtype 4. */
-	u32 local_chassis_id[LOCAL_CHASSIS_ID_STAT_LEN];
-	/* Holds local Port ID 8B payload of constant subtype 3. */
-	u32 local_port_id[LOCAL_PORT_ID_STAT_LEN];
-	/* Number of DCBX frames transmitted. */
-	u32 num_tx_dcbx_pkts;
-	/* Number of DCBX frames received. */
-	u32 num_rx_dcbx_pkts;
-};
-
-/* ADMIN MIB - DCBX local machine default configuration. */
-struct lldp_admin_mib {
-	u32     ver_cfg_flags;
-	#define DCBX_ETS_CONFIG_TX_ENABLED       0x00000001
-	#define DCBX_PFC_CONFIG_TX_ENABLED       0x00000002
-	#define DCBX_APP_CONFIG_TX_ENABLED       0x00000004
-	#define DCBX_ETS_RECO_TX_ENABLED         0x00000008
-	#define DCBX_ETS_RECO_VALID              0x00000010
-	#define DCBX_ETS_WILLING                 0x00000020
-	#define DCBX_PFC_WILLING                 0x00000040
-	#define DCBX_APP_WILLING                 0x00000080
-	#define DCBX_VERSION_CEE                 0x00000100
-	#define DCBX_VERSION_IEEE                0x00000200
-	#define DCBX_DCBX_ENABLED                0x00000400
-	#define DCBX_CEE_VERSION_MASK            0x0000f000
-	#define DCBX_CEE_VERSION_SHIFT           12
-	#define DCBX_CEE_MAX_VERSION_MASK        0x000f0000
-	#define DCBX_CEE_MAX_VERSION_SHIFT       16
-	struct dcbx_features     features;
-};
-
-/* REMOTE MIB - remote machine DCBX configuration. */
-struct lldp_remote_mib {
-	u32 prefix_seq_num;
-	u32 flags;
-	#define DCBX_ETS_TLV_RX                  0x00000001
-	#define DCBX_PFC_TLV_RX                  0x00000002
-	#define DCBX_APP_TLV_RX                  0x00000004
-	#define DCBX_ETS_RX_ERROR                0x00000010
-	#define DCBX_PFC_RX_ERROR                0x00000020
-	#define DCBX_APP_RX_ERROR                0x00000040
-	#define DCBX_ETS_REM_WILLING             0x00000100
-	#define DCBX_PFC_REM_WILLING             0x00000200
-	#define DCBX_APP_REM_WILLING             0x00000400
-	#define DCBX_REMOTE_ETS_RECO_VALID       0x00001000
-	#define DCBX_REMOTE_MIB_VALID            0x00002000
-	struct dcbx_features features;
-	u32 suffix_seq_num;
-};
-
-/* LOCAL MIB - operational DCBX configuration - transmitted on Tx LLDPDU. */
-struct lldp_local_mib {
-	u32 prefix_seq_num;
-	/* Indicates if there is mismatch with negotiation results. */
-	u32 error;
-	#define DCBX_LOCAL_ETS_ERROR             0x00000001
-	#define DCBX_LOCAL_PFC_ERROR             0x00000002
-	#define DCBX_LOCAL_APP_ERROR             0x00000004
-	#define DCBX_LOCAL_PFC_MISMATCH          0x00000010
-	#define DCBX_LOCAL_APP_MISMATCH          0x00000020
-	#define DCBX_REMOTE_MIB_ERROR		 0x00000040
-	struct dcbx_features   features;
-	u32 suffix_seq_num;
-};
-/***END OF DCBX STRUCTURES DECLARATIONS***/
-
-struct ncsi_oem_fcoe_features {
-	u32 fcoe_features1;
-	#define FCOE_FEATURES1_IOS_PER_CONNECTION_MASK          0x0000FFFF
-	#define FCOE_FEATURES1_IOS_PER_CONNECTION_OFFSET        0
-
-	#define FCOE_FEATURES1_LOGINS_PER_PORT_MASK             0xFFFF0000
-	#define FCOE_FEATURES1_LOGINS_PER_PORT_OFFSET           16
-
-	u32 fcoe_features2;
-	#define FCOE_FEATURES2_EXCHANGES_MASK                   0x0000FFFF
-	#define FCOE_FEATURES2_EXCHANGES_OFFSET                 0
-
-	#define FCOE_FEATURES2_NPIV_WWN_PER_PORT_MASK           0xFFFF0000
-	#define FCOE_FEATURES2_NPIV_WWN_PER_PORT_OFFSET         16
-
-	u32 fcoe_features3;
-	#define FCOE_FEATURES3_TARGETS_SUPPORTED_MASK           0x0000FFFF
-	#define FCOE_FEATURES3_TARGETS_SUPPORTED_OFFSET         0
-
-	#define FCOE_FEATURES3_OUTSTANDING_COMMANDS_MASK        0xFFFF0000
-	#define FCOE_FEATURES3_OUTSTANDING_COMMANDS_OFFSET      16
-
-	u32 fcoe_features4;
-	#define FCOE_FEATURES4_FEATURE_SETTINGS_MASK            0x0000000F
-	#define FCOE_FEATURES4_FEATURE_SETTINGS_OFFSET          0
-};
-
-struct ncsi_oem_data {
-	u32 driver_version[4];
-	struct ncsi_oem_fcoe_features ncsi_oem_fcoe_features;
-};
-
-struct shmem2_region {
-
-	u32 size;					/* 0x0000 */
-
-	u32 dcc_support;				/* 0x0004 */
-	#define SHMEM_DCC_SUPPORT_NONE                      0x00000000
-	#define SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV     0x00000001
-	#define SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV  0x00000004
-	#define SHMEM_DCC_SUPPORT_CHANGE_MAC_ADDRESS_TLV    0x00000008
-	#define SHMEM_DCC_SUPPORT_SET_PROTOCOL_TLV          0x00000040
-	#define SHMEM_DCC_SUPPORT_SET_PRIORITY_TLV          0x00000080
-
-	u32 ext_phy_fw_version2[PORT_MAX];		/* 0x0008 */
-	/*
-	 * For backwards compatibility, if the mf_cfg_addr does not exist
-	 * (the size filed is smaller than 0xc) the mf_cfg resides at the
-	 * end of struct shmem_region
-	 */
-	u32 mf_cfg_addr;				/* 0x0010 */
-	#define SHMEM_MF_CFG_ADDR_NONE                  0x00000000
-
-	struct fw_flr_mb flr_mb;			/* 0x0014 */
-	u32 dcbx_lldp_params_offset;			/* 0x0028 */
-	#define SHMEM_LLDP_DCBX_PARAMS_NONE             0x00000000
-	u32 dcbx_neg_res_offset;			/* 0x002c */
-	#define SHMEM_DCBX_NEG_RES_NONE			0x00000000
-	u32 dcbx_remote_mib_offset;			/* 0x0030 */
-	#define SHMEM_DCBX_REMOTE_MIB_NONE              0x00000000
-	/*
-	 * The other shmemX_base_addr holds the other path's shmem address
-	 * required for example in case of common phy init, or for path1 to know
-	 * the address of mcp debug trace which is located in offset from shmem
-	 * of path0
-	 */
-	u32 other_shmem_base_addr;			/* 0x0034 */
-	u32 other_shmem2_base_addr;			/* 0x0038 */
-	/*
-	 * mcp_vf_disabled is set by the MCP to indicate the driver about VFs
-	 * which were disabled/flred
-	 */
-	u32 mcp_vf_disabled[E2_VF_MAX / 32];		/* 0x003c */
-
-	/*
-	 * drv_ack_vf_disabled is set by the PF driver to ack handled disabled
-	 * VFs
-	 */
-	u32 drv_ack_vf_disabled[E2_FUNC_MAX][E2_VF_MAX / 32]; /* 0x0044 */
-
-	u32 dcbx_lldp_dcbx_stat_offset;			/* 0x0064 */
-	#define SHMEM_LLDP_DCBX_STAT_NONE               0x00000000
-
-	/*
-	 * edebug_driver_if field is used to transfer messages between edebug
-	 * app to the driver through shmem2.
-	 *
-	 * message format:
-	 * bits 0-2 -  function number / instance of driver to perform request
-	 * bits 3-5 -  op code / is_ack?
-	 * bits 6-63 - data
-	 */
-	u32 edebug_driver_if[2];			/* 0x0068 */
-	#define EDEBUG_DRIVER_IF_OP_CODE_GET_PHYS_ADDR  1
-	#define EDEBUG_DRIVER_IF_OP_CODE_GET_BUS_ADDR   2
-	#define EDEBUG_DRIVER_IF_OP_CODE_DISABLE_STAT   3
-
-	u32 nvm_retain_bitmap_addr;			/* 0x0070 */
-
-	u32	reserved1;	/* 0x0074 */
-
-	u32	reserved2[E2_FUNC_MAX];
-
-	u32	reserved3[E2_FUNC_MAX];/* 0x0088 */
-	u32	reserved4[E2_FUNC_MAX];/* 0x0098 */
-
-	u32 swim_base_addr;				/* 0x0108 */
-	u32 swim_funcs;
-	u32 swim_main_cb;
-
-	u32	reserved5[2];
-
-	/* generic flags controlled by the driver */
-	u32 drv_flags;
-	#define DRV_FLAGS_DCB_CONFIGURED                0x1
-
-	/* pointer to extended dev_info shared data copied from nvm image */
-	u32 extended_dev_info_shared_addr;
-	u32 ncsi_oem_data_addr;
-
-	u32 ocsd_host_addr;
-	u32 ocbb_host_addr;
-	u32 ocsd_req_update_interval;
-};
-
-
-struct emac_stats {
-	u32     rx_stat_ifhcinoctets;
-	u32     rx_stat_ifhcinbadoctets;
-	u32     rx_stat_etherstatsfragments;
-	u32     rx_stat_ifhcinucastpkts;
-	u32     rx_stat_ifhcinmulticastpkts;
-	u32     rx_stat_ifhcinbroadcastpkts;
-	u32     rx_stat_dot3statsfcserrors;
-	u32     rx_stat_dot3statsalignmenterrors;
-	u32     rx_stat_dot3statscarriersenseerrors;
-	u32     rx_stat_xonpauseframesreceived;
-	u32     rx_stat_xoffpauseframesreceived;
-	u32     rx_stat_maccontrolframesreceived;
-	u32     rx_stat_xoffstateentered;
-	u32     rx_stat_dot3statsframestoolong;
-	u32     rx_stat_etherstatsjabbers;
-	u32     rx_stat_etherstatsundersizepkts;
-	u32     rx_stat_etherstatspkts64octets;
-	u32     rx_stat_etherstatspkts65octetsto127octets;
-	u32     rx_stat_etherstatspkts128octetsto255octets;
-	u32     rx_stat_etherstatspkts256octetsto511octets;
-	u32     rx_stat_etherstatspkts512octetsto1023octets;
-	u32     rx_stat_etherstatspkts1024octetsto1522octets;
-	u32     rx_stat_etherstatspktsover1522octets;
-
-	u32     rx_stat_falsecarriererrors;
-
-	u32     tx_stat_ifhcoutoctets;
-	u32     tx_stat_ifhcoutbadoctets;
-	u32     tx_stat_etherstatscollisions;
-	u32     tx_stat_outxonsent;
-	u32     tx_stat_outxoffsent;
-	u32     tx_stat_flowcontroldone;
-	u32     tx_stat_dot3statssinglecollisionframes;
-	u32     tx_stat_dot3statsmultiplecollisionframes;
-	u32     tx_stat_dot3statsdeferredtransmissions;
-	u32     tx_stat_dot3statsexcessivecollisions;
-	u32     tx_stat_dot3statslatecollisions;
-	u32     tx_stat_ifhcoutucastpkts;
-	u32     tx_stat_ifhcoutmulticastpkts;
-	u32     tx_stat_ifhcoutbroadcastpkts;
-	u32     tx_stat_etherstatspkts64octets;
-	u32     tx_stat_etherstatspkts65octetsto127octets;
-	u32     tx_stat_etherstatspkts128octetsto255octets;
-	u32     tx_stat_etherstatspkts256octetsto511octets;
-	u32     tx_stat_etherstatspkts512octetsto1023octets;
-	u32     tx_stat_etherstatspkts1024octetsto1522octets;
-	u32     tx_stat_etherstatspktsover1522octets;
-	u32     tx_stat_dot3statsinternalmactransmiterrors;
-};
-
-
-struct bmac1_stats {
-	u32	tx_stat_gtpkt_lo;
-	u32	tx_stat_gtpkt_hi;
-	u32	tx_stat_gtxpf_lo;
-	u32	tx_stat_gtxpf_hi;
-	u32	tx_stat_gtfcs_lo;
-	u32	tx_stat_gtfcs_hi;
-	u32	tx_stat_gtmca_lo;
-	u32	tx_stat_gtmca_hi;
-	u32	tx_stat_gtbca_lo;
-	u32	tx_stat_gtbca_hi;
-	u32	tx_stat_gtfrg_lo;
-	u32	tx_stat_gtfrg_hi;
-	u32	tx_stat_gtovr_lo;
-	u32	tx_stat_gtovr_hi;
-	u32	tx_stat_gt64_lo;
-	u32	tx_stat_gt64_hi;
-	u32	tx_stat_gt127_lo;
-	u32	tx_stat_gt127_hi;
-	u32	tx_stat_gt255_lo;
-	u32	tx_stat_gt255_hi;
-	u32	tx_stat_gt511_lo;
-	u32	tx_stat_gt511_hi;
-	u32	tx_stat_gt1023_lo;
-	u32	tx_stat_gt1023_hi;
-	u32	tx_stat_gt1518_lo;
-	u32	tx_stat_gt1518_hi;
-	u32	tx_stat_gt2047_lo;
-	u32	tx_stat_gt2047_hi;
-	u32	tx_stat_gt4095_lo;
-	u32	tx_stat_gt4095_hi;
-	u32	tx_stat_gt9216_lo;
-	u32	tx_stat_gt9216_hi;
-	u32	tx_stat_gt16383_lo;
-	u32	tx_stat_gt16383_hi;
-	u32	tx_stat_gtmax_lo;
-	u32	tx_stat_gtmax_hi;
-	u32	tx_stat_gtufl_lo;
-	u32	tx_stat_gtufl_hi;
-	u32	tx_stat_gterr_lo;
-	u32	tx_stat_gterr_hi;
-	u32	tx_stat_gtbyt_lo;
-	u32	tx_stat_gtbyt_hi;
-
-	u32	rx_stat_gr64_lo;
-	u32	rx_stat_gr64_hi;
-	u32	rx_stat_gr127_lo;
-	u32	rx_stat_gr127_hi;
-	u32	rx_stat_gr255_lo;
-	u32	rx_stat_gr255_hi;
-	u32	rx_stat_gr511_lo;
-	u32	rx_stat_gr511_hi;
-	u32	rx_stat_gr1023_lo;
-	u32	rx_stat_gr1023_hi;
-	u32	rx_stat_gr1518_lo;
-	u32	rx_stat_gr1518_hi;
-	u32	rx_stat_gr2047_lo;
-	u32	rx_stat_gr2047_hi;
-	u32	rx_stat_gr4095_lo;
-	u32	rx_stat_gr4095_hi;
-	u32	rx_stat_gr9216_lo;
-	u32	rx_stat_gr9216_hi;
-	u32	rx_stat_gr16383_lo;
-	u32	rx_stat_gr16383_hi;
-	u32	rx_stat_grmax_lo;
-	u32	rx_stat_grmax_hi;
-	u32	rx_stat_grpkt_lo;
-	u32	rx_stat_grpkt_hi;
-	u32	rx_stat_grfcs_lo;
-	u32	rx_stat_grfcs_hi;
-	u32	rx_stat_grmca_lo;
-	u32	rx_stat_grmca_hi;
-	u32	rx_stat_grbca_lo;
-	u32	rx_stat_grbca_hi;
-	u32	rx_stat_grxcf_lo;
-	u32	rx_stat_grxcf_hi;
-	u32	rx_stat_grxpf_lo;
-	u32	rx_stat_grxpf_hi;
-	u32	rx_stat_grxuo_lo;
-	u32	rx_stat_grxuo_hi;
-	u32	rx_stat_grjbr_lo;
-	u32	rx_stat_grjbr_hi;
-	u32	rx_stat_grovr_lo;
-	u32	rx_stat_grovr_hi;
-	u32	rx_stat_grflr_lo;
-	u32	rx_stat_grflr_hi;
-	u32	rx_stat_grmeg_lo;
-	u32	rx_stat_grmeg_hi;
-	u32	rx_stat_grmeb_lo;
-	u32	rx_stat_grmeb_hi;
-	u32	rx_stat_grbyt_lo;
-	u32	rx_stat_grbyt_hi;
-	u32	rx_stat_grund_lo;
-	u32	rx_stat_grund_hi;
-	u32	rx_stat_grfrg_lo;
-	u32	rx_stat_grfrg_hi;
-	u32	rx_stat_grerb_lo;
-	u32	rx_stat_grerb_hi;
-	u32	rx_stat_grfre_lo;
-	u32	rx_stat_grfre_hi;
-	u32	rx_stat_gripj_lo;
-	u32	rx_stat_gripj_hi;
-};
-
-struct bmac2_stats {
-	u32	tx_stat_gtpk_lo; /* gtpok */
-	u32	tx_stat_gtpk_hi; /* gtpok */
-	u32	tx_stat_gtxpf_lo; /* gtpf */
-	u32	tx_stat_gtxpf_hi; /* gtpf */
-	u32	tx_stat_gtpp_lo; /* NEW BMAC2 */
-	u32	tx_stat_gtpp_hi; /* NEW BMAC2 */
-	u32	tx_stat_gtfcs_lo;
-	u32	tx_stat_gtfcs_hi;
-	u32	tx_stat_gtuca_lo; /* NEW BMAC2 */
-	u32	tx_stat_gtuca_hi; /* NEW BMAC2 */
-	u32	tx_stat_gtmca_lo;
-	u32	tx_stat_gtmca_hi;
-	u32	tx_stat_gtbca_lo;
-	u32	tx_stat_gtbca_hi;
-	u32	tx_stat_gtovr_lo;
-	u32	tx_stat_gtovr_hi;
-	u32	tx_stat_gtfrg_lo;
-	u32	tx_stat_gtfrg_hi;
-	u32	tx_stat_gtpkt1_lo; /* gtpkt */
-	u32	tx_stat_gtpkt1_hi; /* gtpkt */
-	u32	tx_stat_gt64_lo;
-	u32	tx_stat_gt64_hi;
-	u32	tx_stat_gt127_lo;
-	u32	tx_stat_gt127_hi;
-	u32	tx_stat_gt255_lo;
-	u32	tx_stat_gt255_hi;
-	u32	tx_stat_gt511_lo;
-	u32	tx_stat_gt511_hi;
-	u32	tx_stat_gt1023_lo;
-	u32	tx_stat_gt1023_hi;
-	u32	tx_stat_gt1518_lo;
-	u32	tx_stat_gt1518_hi;
-	u32	tx_stat_gt2047_lo;
-	u32	tx_stat_gt2047_hi;
-	u32	tx_stat_gt4095_lo;
-	u32	tx_stat_gt4095_hi;
-	u32	tx_stat_gt9216_lo;
-	u32	tx_stat_gt9216_hi;
-	u32	tx_stat_gt16383_lo;
-	u32	tx_stat_gt16383_hi;
-	u32	tx_stat_gtmax_lo;
-	u32	tx_stat_gtmax_hi;
-	u32	tx_stat_gtufl_lo;
-	u32	tx_stat_gtufl_hi;
-	u32	tx_stat_gterr_lo;
-	u32	tx_stat_gterr_hi;
-	u32	tx_stat_gtbyt_lo;
-	u32	tx_stat_gtbyt_hi;
-
-	u32	rx_stat_gr64_lo;
-	u32	rx_stat_gr64_hi;
-	u32	rx_stat_gr127_lo;
-	u32	rx_stat_gr127_hi;
-	u32	rx_stat_gr255_lo;
-	u32	rx_stat_gr255_hi;
-	u32	rx_stat_gr511_lo;
-	u32	rx_stat_gr511_hi;
-	u32	rx_stat_gr1023_lo;
-	u32	rx_stat_gr1023_hi;
-	u32	rx_stat_gr1518_lo;
-	u32	rx_stat_gr1518_hi;
-	u32	rx_stat_gr2047_lo;
-	u32	rx_stat_gr2047_hi;
-	u32	rx_stat_gr4095_lo;
-	u32	rx_stat_gr4095_hi;
-	u32	rx_stat_gr9216_lo;
-	u32	rx_stat_gr9216_hi;
-	u32	rx_stat_gr16383_lo;
-	u32	rx_stat_gr16383_hi;
-	u32	rx_stat_grmax_lo;
-	u32	rx_stat_grmax_hi;
-	u32	rx_stat_grpkt_lo;
-	u32	rx_stat_grpkt_hi;
-	u32	rx_stat_grfcs_lo;
-	u32	rx_stat_grfcs_hi;
-	u32	rx_stat_gruca_lo;
-	u32	rx_stat_gruca_hi;
-	u32	rx_stat_grmca_lo;
-	u32	rx_stat_grmca_hi;
-	u32	rx_stat_grbca_lo;
-	u32	rx_stat_grbca_hi;
-	u32	rx_stat_grxpf_lo; /* grpf */
-	u32	rx_stat_grxpf_hi; /* grpf */
-	u32	rx_stat_grpp_lo;
-	u32	rx_stat_grpp_hi;
-	u32	rx_stat_grxuo_lo; /* gruo */
-	u32	rx_stat_grxuo_hi; /* gruo */
-	u32	rx_stat_grjbr_lo;
-	u32	rx_stat_grjbr_hi;
-	u32	rx_stat_grovr_lo;
-	u32	rx_stat_grovr_hi;
-	u32	rx_stat_grxcf_lo; /* grcf */
-	u32	rx_stat_grxcf_hi; /* grcf */
-	u32	rx_stat_grflr_lo;
-	u32	rx_stat_grflr_hi;
-	u32	rx_stat_grpok_lo;
-	u32	rx_stat_grpok_hi;
-	u32	rx_stat_grmeg_lo;
-	u32	rx_stat_grmeg_hi;
-	u32	rx_stat_grmeb_lo;
-	u32	rx_stat_grmeb_hi;
-	u32	rx_stat_grbyt_lo;
-	u32	rx_stat_grbyt_hi;
-	u32	rx_stat_grund_lo;
-	u32	rx_stat_grund_hi;
-	u32	rx_stat_grfrg_lo;
-	u32	rx_stat_grfrg_hi;
-	u32	rx_stat_grerb_lo; /* grerrbyt */
-	u32	rx_stat_grerb_hi; /* grerrbyt */
-	u32	rx_stat_grfre_lo; /* grfrerr */
-	u32	rx_stat_grfre_hi; /* grfrerr */
-	u32	rx_stat_gripj_lo;
-	u32	rx_stat_gripj_hi;
-};
-
-struct mstat_stats {
-	struct {
-		/* OTE MSTAT on E3 has a bug where this register's contents are
-		 * actually tx_gtxpok + tx_gtxpf + (possibly)tx_gtxpp
-		 */
-		u32 tx_gtxpok_lo;
-		u32 tx_gtxpok_hi;
-		u32 tx_gtxpf_lo;
-		u32 tx_gtxpf_hi;
-		u32 tx_gtxpp_lo;
-		u32 tx_gtxpp_hi;
-		u32 tx_gtfcs_lo;
-		u32 tx_gtfcs_hi;
-		u32 tx_gtuca_lo;
-		u32 tx_gtuca_hi;
-		u32 tx_gtmca_lo;
-		u32 tx_gtmca_hi;
-		u32 tx_gtgca_lo;
-		u32 tx_gtgca_hi;
-		u32 tx_gtpkt_lo;
-		u32 tx_gtpkt_hi;
-		u32 tx_gt64_lo;
-		u32 tx_gt64_hi;
-		u32 tx_gt127_lo;
-		u32 tx_gt127_hi;
-		u32 tx_gt255_lo;
-		u32 tx_gt255_hi;
-		u32 tx_gt511_lo;
-		u32 tx_gt511_hi;
-		u32 tx_gt1023_lo;
-		u32 tx_gt1023_hi;
-		u32 tx_gt1518_lo;
-		u32 tx_gt1518_hi;
-		u32 tx_gt2047_lo;
-		u32 tx_gt2047_hi;
-		u32 tx_gt4095_lo;
-		u32 tx_gt4095_hi;
-		u32 tx_gt9216_lo;
-		u32 tx_gt9216_hi;
-		u32 tx_gt16383_lo;
-		u32 tx_gt16383_hi;
-		u32 tx_gtufl_lo;
-		u32 tx_gtufl_hi;
-		u32 tx_gterr_lo;
-		u32 tx_gterr_hi;
-		u32 tx_gtbyt_lo;
-		u32 tx_gtbyt_hi;
-		u32 tx_collisions_lo;
-		u32 tx_collisions_hi;
-		u32 tx_singlecollision_lo;
-		u32 tx_singlecollision_hi;
-		u32 tx_multiplecollisions_lo;
-		u32 tx_multiplecollisions_hi;
-		u32 tx_deferred_lo;
-		u32 tx_deferred_hi;
-		u32 tx_excessivecollisions_lo;
-		u32 tx_excessivecollisions_hi;
-		u32 tx_latecollisions_lo;
-		u32 tx_latecollisions_hi;
-	} stats_tx;
-
-	struct {
-		u32 rx_gr64_lo;
-		u32 rx_gr64_hi;
-		u32 rx_gr127_lo;
-		u32 rx_gr127_hi;
-		u32 rx_gr255_lo;
-		u32 rx_gr255_hi;
-		u32 rx_gr511_lo;
-		u32 rx_gr511_hi;
-		u32 rx_gr1023_lo;
-		u32 rx_gr1023_hi;
-		u32 rx_gr1518_lo;
-		u32 rx_gr1518_hi;
-		u32 rx_gr2047_lo;
-		u32 rx_gr2047_hi;
-		u32 rx_gr4095_lo;
-		u32 rx_gr4095_hi;
-		u32 rx_gr9216_lo;
-		u32 rx_gr9216_hi;
-		u32 rx_gr16383_lo;
-		u32 rx_gr16383_hi;
-		u32 rx_grpkt_lo;
-		u32 rx_grpkt_hi;
-		u32 rx_grfcs_lo;
-		u32 rx_grfcs_hi;
-		u32 rx_gruca_lo;
-		u32 rx_gruca_hi;
-		u32 rx_grmca_lo;
-		u32 rx_grmca_hi;
-		u32 rx_grbca_lo;
-		u32 rx_grbca_hi;
-		u32 rx_grxpf_lo;
-		u32 rx_grxpf_hi;
-		u32 rx_grxpp_lo;
-		u32 rx_grxpp_hi;
-		u32 rx_grxuo_lo;
-		u32 rx_grxuo_hi;
-		u32 rx_grovr_lo;
-		u32 rx_grovr_hi;
-		u32 rx_grxcf_lo;
-		u32 rx_grxcf_hi;
-		u32 rx_grflr_lo;
-		u32 rx_grflr_hi;
-		u32 rx_grpok_lo;
-		u32 rx_grpok_hi;
-		u32 rx_grbyt_lo;
-		u32 rx_grbyt_hi;
-		u32 rx_grund_lo;
-		u32 rx_grund_hi;
-		u32 rx_grfrg_lo;
-		u32 rx_grfrg_hi;
-		u32 rx_grerb_lo;
-		u32 rx_grerb_hi;
-		u32 rx_grfre_lo;
-		u32 rx_grfre_hi;
-
-		u32 rx_alignmenterrors_lo;
-		u32 rx_alignmenterrors_hi;
-		u32 rx_falsecarrier_lo;
-		u32 rx_falsecarrier_hi;
-		u32 rx_llfcmsgcnt_lo;
-		u32 rx_llfcmsgcnt_hi;
-	} stats_rx;
-};
-
-union mac_stats {
-	struct emac_stats	emac_stats;
-	struct bmac1_stats	bmac1_stats;
-	struct bmac2_stats	bmac2_stats;
-	struct mstat_stats	mstat_stats;
-};
-
-
-struct mac_stx {
-	/* in_bad_octets */
-	u32     rx_stat_ifhcinbadoctets_hi;
-	u32     rx_stat_ifhcinbadoctets_lo;
-
-	/* out_bad_octets */
-	u32     tx_stat_ifhcoutbadoctets_hi;
-	u32     tx_stat_ifhcoutbadoctets_lo;
-
-	/* crc_receive_errors */
-	u32     rx_stat_dot3statsfcserrors_hi;
-	u32     rx_stat_dot3statsfcserrors_lo;
-	/* alignment_errors */
-	u32     rx_stat_dot3statsalignmenterrors_hi;
-	u32     rx_stat_dot3statsalignmenterrors_lo;
-	/* carrier_sense_errors */
-	u32     rx_stat_dot3statscarriersenseerrors_hi;
-	u32     rx_stat_dot3statscarriersenseerrors_lo;
-	/* false_carrier_detections */
-	u32     rx_stat_falsecarriererrors_hi;
-	u32     rx_stat_falsecarriererrors_lo;
-
-	/* runt_packets_received */
-	u32     rx_stat_etherstatsundersizepkts_hi;
-	u32     rx_stat_etherstatsundersizepkts_lo;
-	/* jabber_packets_received */
-	u32     rx_stat_dot3statsframestoolong_hi;
-	u32     rx_stat_dot3statsframestoolong_lo;
-
-	/* error_runt_packets_received */
-	u32     rx_stat_etherstatsfragments_hi;
-	u32     rx_stat_etherstatsfragments_lo;
-	/* error_jabber_packets_received */
-	u32     rx_stat_etherstatsjabbers_hi;
-	u32     rx_stat_etherstatsjabbers_lo;
-
-	/* control_frames_received */
-	u32     rx_stat_maccontrolframesreceived_hi;
-	u32     rx_stat_maccontrolframesreceived_lo;
-	u32     rx_stat_mac_xpf_hi;
-	u32     rx_stat_mac_xpf_lo;
-	u32     rx_stat_mac_xcf_hi;
-	u32     rx_stat_mac_xcf_lo;
-
-	/* xoff_state_entered */
-	u32     rx_stat_xoffstateentered_hi;
-	u32     rx_stat_xoffstateentered_lo;
-	/* pause_xon_frames_received */
-	u32     rx_stat_xonpauseframesreceived_hi;
-	u32     rx_stat_xonpauseframesreceived_lo;
-	/* pause_xoff_frames_received */
-	u32     rx_stat_xoffpauseframesreceived_hi;
-	u32     rx_stat_xoffpauseframesreceived_lo;
-	/* pause_xon_frames_transmitted */
-	u32     tx_stat_outxonsent_hi;
-	u32     tx_stat_outxonsent_lo;
-	/* pause_xoff_frames_transmitted */
-	u32     tx_stat_outxoffsent_hi;
-	u32     tx_stat_outxoffsent_lo;
-	/* flow_control_done */
-	u32     tx_stat_flowcontroldone_hi;
-	u32     tx_stat_flowcontroldone_lo;
-
-	/* ether_stats_collisions */
-	u32     tx_stat_etherstatscollisions_hi;
-	u32     tx_stat_etherstatscollisions_lo;
-	/* single_collision_transmit_frames */
-	u32     tx_stat_dot3statssinglecollisionframes_hi;
-	u32     tx_stat_dot3statssinglecollisionframes_lo;
-	/* multiple_collision_transmit_frames */
-	u32     tx_stat_dot3statsmultiplecollisionframes_hi;
-	u32     tx_stat_dot3statsmultiplecollisionframes_lo;
-	/* deferred_transmissions */
-	u32     tx_stat_dot3statsdeferredtransmissions_hi;
-	u32     tx_stat_dot3statsdeferredtransmissions_lo;
-	/* excessive_collision_frames */
-	u32     tx_stat_dot3statsexcessivecollisions_hi;
-	u32     tx_stat_dot3statsexcessivecollisions_lo;
-	/* late_collision_frames */
-	u32     tx_stat_dot3statslatecollisions_hi;
-	u32     tx_stat_dot3statslatecollisions_lo;
-
-	/* frames_transmitted_64_bytes */
-	u32     tx_stat_etherstatspkts64octets_hi;
-	u32     tx_stat_etherstatspkts64octets_lo;
-	/* frames_transmitted_65_127_bytes */
-	u32     tx_stat_etherstatspkts65octetsto127octets_hi;
-	u32     tx_stat_etherstatspkts65octetsto127octets_lo;
-	/* frames_transmitted_128_255_bytes */
-	u32     tx_stat_etherstatspkts128octetsto255octets_hi;
-	u32     tx_stat_etherstatspkts128octetsto255octets_lo;
-	/* frames_transmitted_256_511_bytes */
-	u32     tx_stat_etherstatspkts256octetsto511octets_hi;
-	u32     tx_stat_etherstatspkts256octetsto511octets_lo;
-	/* frames_transmitted_512_1023_bytes */
-	u32     tx_stat_etherstatspkts512octetsto1023octets_hi;
-	u32     tx_stat_etherstatspkts512octetsto1023octets_lo;
-	/* frames_transmitted_1024_1522_bytes */
-	u32     tx_stat_etherstatspkts1024octetsto1522octets_hi;
-	u32     tx_stat_etherstatspkts1024octetsto1522octets_lo;
-	/* frames_transmitted_1523_9022_bytes */
-	u32     tx_stat_etherstatspktsover1522octets_hi;
-	u32     tx_stat_etherstatspktsover1522octets_lo;
-	u32     tx_stat_mac_2047_hi;
-	u32     tx_stat_mac_2047_lo;
-	u32     tx_stat_mac_4095_hi;
-	u32     tx_stat_mac_4095_lo;
-	u32     tx_stat_mac_9216_hi;
-	u32     tx_stat_mac_9216_lo;
-	u32     tx_stat_mac_16383_hi;
-	u32     tx_stat_mac_16383_lo;
-
-	/* internal_mac_transmit_errors */
-	u32     tx_stat_dot3statsinternalmactransmiterrors_hi;
-	u32     tx_stat_dot3statsinternalmactransmiterrors_lo;
-
-	/* if_out_discards */
-	u32     tx_stat_mac_ufl_hi;
-	u32     tx_stat_mac_ufl_lo;
-};
-
-
-#define MAC_STX_IDX_MAX                     2
-
-struct host_port_stats {
-	u32            host_port_stats_start;
-
-	struct mac_stx mac_stx[MAC_STX_IDX_MAX];
-
-	u32            brb_drop_hi;
-	u32            brb_drop_lo;
-
-	u32            host_port_stats_end;
-};
-
-
-struct host_func_stats {
-	u32     host_func_stats_start;
-
-	u32     total_bytes_received_hi;
-	u32     total_bytes_received_lo;
-
-	u32     total_bytes_transmitted_hi;
-	u32     total_bytes_transmitted_lo;
-
-	u32     total_unicast_packets_received_hi;
-	u32     total_unicast_packets_received_lo;
-
-	u32     total_multicast_packets_received_hi;
-	u32     total_multicast_packets_received_lo;
-
-	u32     total_broadcast_packets_received_hi;
-	u32     total_broadcast_packets_received_lo;
-
-	u32     total_unicast_packets_transmitted_hi;
-	u32     total_unicast_packets_transmitted_lo;
-
-	u32     total_multicast_packets_transmitted_hi;
-	u32     total_multicast_packets_transmitted_lo;
-
-	u32     total_broadcast_packets_transmitted_hi;
-	u32     total_broadcast_packets_transmitted_lo;
-
-	u32     valid_bytes_received_hi;
-	u32     valid_bytes_received_lo;
-
-	u32     host_func_stats_end;
-};
-
-/* VIC definitions */
-#define VICSTATST_UIF_INDEX 2
-
-/*(DEBLOBBED)*/
-
-
-/*
- * attention bits
- */
-struct atten_sp_status_block {
-	__le32 attn_bits;
-	__le32 attn_bits_ack;
-	u8 status_block_id;
-	u8 reserved0;
-	__le16 attn_bits_index;
-	__le32 reserved1;
-};
-
-
-/*
- * The eth aggregative context of Cstorm
- */
-struct cstorm_eth_ag_context {
-	u32 __reserved0[10];
-};
-
-
-/*
- * dmae command structure
- */
-struct dmae_command {
-	u32 opcode;
-#define DMAE_COMMAND_SRC (0x1<<0)
-#define DMAE_COMMAND_SRC_SHIFT 0
-#define DMAE_COMMAND_DST (0x3<<1)
-#define DMAE_COMMAND_DST_SHIFT 1
-#define DMAE_COMMAND_C_DST (0x1<<3)
-#define DMAE_COMMAND_C_DST_SHIFT 3
-#define DMAE_COMMAND_C_TYPE_ENABLE (0x1<<4)
-#define DMAE_COMMAND_C_TYPE_ENABLE_SHIFT 4
-#define DMAE_COMMAND_C_TYPE_CRC_ENABLE (0x1<<5)
-#define DMAE_COMMAND_C_TYPE_CRC_ENABLE_SHIFT 5
-#define DMAE_COMMAND_C_TYPE_CRC_OFFSET (0x7<<6)
-#define DMAE_COMMAND_C_TYPE_CRC_OFFSET_SHIFT 6
-#define DMAE_COMMAND_ENDIANITY (0x3<<9)
-#define DMAE_COMMAND_ENDIANITY_SHIFT 9
-#define DMAE_COMMAND_PORT (0x1<<11)
-#define DMAE_COMMAND_PORT_SHIFT 11
-#define DMAE_COMMAND_CRC_RESET (0x1<<12)
-#define DMAE_COMMAND_CRC_RESET_SHIFT 12
-#define DMAE_COMMAND_SRC_RESET (0x1<<13)
-#define DMAE_COMMAND_SRC_RESET_SHIFT 13
-#define DMAE_COMMAND_DST_RESET (0x1<<14)
-#define DMAE_COMMAND_DST_RESET_SHIFT 14
-#define DMAE_COMMAND_E1HVN (0x3<<15)
-#define DMAE_COMMAND_E1HVN_SHIFT 15
-#define DMAE_COMMAND_DST_VN (0x3<<17)
-#define DMAE_COMMAND_DST_VN_SHIFT 17
-#define DMAE_COMMAND_C_FUNC (0x1<<19)
-#define DMAE_COMMAND_C_FUNC_SHIFT 19
-#define DMAE_COMMAND_ERR_POLICY (0x3<<20)
-#define DMAE_COMMAND_ERR_POLICY_SHIFT 20
-#define DMAE_COMMAND_RESERVED0 (0x3FF<<22)
-#define DMAE_COMMAND_RESERVED0_SHIFT 22
-	u32 src_addr_lo;
-	u32 src_addr_hi;
-	u32 dst_addr_lo;
-	u32 dst_addr_hi;
-#if defined(__BIG_ENDIAN)
-	u16 opcode_iov;
-#define DMAE_COMMAND_SRC_VFID (0x3F<<0)
-#define DMAE_COMMAND_SRC_VFID_SHIFT 0
-#define DMAE_COMMAND_SRC_VFPF (0x1<<6)
-#define DMAE_COMMAND_SRC_VFPF_SHIFT 6
-#define DMAE_COMMAND_RESERVED1 (0x1<<7)
-#define DMAE_COMMAND_RESERVED1_SHIFT 7
-#define DMAE_COMMAND_DST_VFID (0x3F<<8)
-#define DMAE_COMMAND_DST_VFID_SHIFT 8
-#define DMAE_COMMAND_DST_VFPF (0x1<<14)
-#define DMAE_COMMAND_DST_VFPF_SHIFT 14
-#define DMAE_COMMAND_RESERVED2 (0x1<<15)
-#define DMAE_COMMAND_RESERVED2_SHIFT 15
-	u16 len;
-#elif defined(__LITTLE_ENDIAN)
-	u16 len;
-	u16 opcode_iov;
-#define DMAE_COMMAND_SRC_VFID (0x3F<<0)
-#define DMAE_COMMAND_SRC_VFID_SHIFT 0
-#define DMAE_COMMAND_SRC_VFPF (0x1<<6)
-#define DMAE_COMMAND_SRC_VFPF_SHIFT 6
-#define DMAE_COMMAND_RESERVED1 (0x1<<7)
-#define DMAE_COMMAND_RESERVED1_SHIFT 7
-#define DMAE_COMMAND_DST_VFID (0x3F<<8)
-#define DMAE_COMMAND_DST_VFID_SHIFT 8
-#define DMAE_COMMAND_DST_VFPF (0x1<<14)
-#define DMAE_COMMAND_DST_VFPF_SHIFT 14
-#define DMAE_COMMAND_RESERVED2 (0x1<<15)
-#define DMAE_COMMAND_RESERVED2_SHIFT 15
-#endif
-	u32 comp_addr_lo;
-	u32 comp_addr_hi;
-	u32 comp_val;
-	u32 crc32;
-	u32 crc32_c;
-#if defined(__BIG_ENDIAN)
-	u16 crc16_c;
-	u16 crc16;
-#elif defined(__LITTLE_ENDIAN)
-	u16 crc16;
-	u16 crc16_c;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 reserved3;
-	u16 crc_t10;
-#elif defined(__LITTLE_ENDIAN)
-	u16 crc_t10;
-	u16 reserved3;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 xsum8;
-	u16 xsum16;
-#elif defined(__LITTLE_ENDIAN)
-	u16 xsum16;
-	u16 xsum8;
-#endif
-};
-
-
-/*
- * common data for all protocols
- */
-struct doorbell_hdr {
-	u8 header;
-#define DOORBELL_HDR_RX (0x1<<0)
-#define DOORBELL_HDR_RX_SHIFT 0
-#define DOORBELL_HDR_DB_TYPE (0x1<<1)
-#define DOORBELL_HDR_DB_TYPE_SHIFT 1
-#define DOORBELL_HDR_DPM_SIZE (0x3<<2)
-#define DOORBELL_HDR_DPM_SIZE_SHIFT 2
-#define DOORBELL_HDR_CONN_TYPE (0xF<<4)
-#define DOORBELL_HDR_CONN_TYPE_SHIFT 4
-};
-
-/*
- * Ethernet doorbell
- */
-struct eth_tx_doorbell {
-#if defined(__BIG_ENDIAN)
-	u16 npackets;
-	u8 params;
-#define ETH_TX_DOORBELL_NUM_BDS (0x3F<<0)
-#define ETH_TX_DOORBELL_NUM_BDS_SHIFT 0
-#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG (0x1<<6)
-#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG_SHIFT 6
-#define ETH_TX_DOORBELL_SPARE (0x1<<7)
-#define ETH_TX_DOORBELL_SPARE_SHIFT 7
-	struct doorbell_hdr hdr;
-#elif defined(__LITTLE_ENDIAN)
-	struct doorbell_hdr hdr;
-	u8 params;
-#define ETH_TX_DOORBELL_NUM_BDS (0x3F<<0)
-#define ETH_TX_DOORBELL_NUM_BDS_SHIFT 0
-#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG (0x1<<6)
-#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG_SHIFT 6
-#define ETH_TX_DOORBELL_SPARE (0x1<<7)
-#define ETH_TX_DOORBELL_SPARE_SHIFT 7
-	u16 npackets;
-#endif
-};
-
-
-/*
- * 3 lines. status block
- */
-struct hc_status_block_e1x {
-	__le16 index_values[HC_SB_MAX_INDICES_E1X];
-	__le16 running_index[HC_SB_MAX_SM];
-	__le32 rsrv[11];
-};
-
-/*
- * host status block
- */
-struct host_hc_status_block_e1x {
-	struct hc_status_block_e1x sb;
-};
-
-
-/*
- * 3 lines. status block
- */
-struct hc_status_block_e2 {
-	__le16 index_values[HC_SB_MAX_INDICES_E2];
-	__le16 running_index[HC_SB_MAX_SM];
-	__le32 reserved[11];
-};
-
-/*
- * host status block
- */
-struct host_hc_status_block_e2 {
-	struct hc_status_block_e2 sb;
-};
-
-
-/*
- * 5 lines. slow-path status block
- */
-struct hc_sp_status_block {
-	__le16 index_values[HC_SP_SB_MAX_INDICES];
-	__le16 running_index;
-	__le16 rsrv;
-	u32 rsrv1;
-};
-
-/*
- * host status block
- */
-struct host_sp_status_block {
-	struct atten_sp_status_block atten_status_block;
-	struct hc_sp_status_block sp_sb;
-};
-
-
-/*
- * IGU driver acknowledgment register
- */
-struct igu_ack_register {
-#if defined(__BIG_ENDIAN)
-	u16 sb_id_and_flags;
-#define IGU_ACK_REGISTER_STATUS_BLOCK_ID (0x1F<<0)
-#define IGU_ACK_REGISTER_STATUS_BLOCK_ID_SHIFT 0
-#define IGU_ACK_REGISTER_STORM_ID (0x7<<5)
-#define IGU_ACK_REGISTER_STORM_ID_SHIFT 5
-#define IGU_ACK_REGISTER_UPDATE_INDEX (0x1<<8)
-#define IGU_ACK_REGISTER_UPDATE_INDEX_SHIFT 8
-#define IGU_ACK_REGISTER_INTERRUPT_MODE (0x3<<9)
-#define IGU_ACK_REGISTER_INTERRUPT_MODE_SHIFT 9
-#define IGU_ACK_REGISTER_RESERVED (0x1F<<11)
-#define IGU_ACK_REGISTER_RESERVED_SHIFT 11
-	u16 status_block_index;
-#elif defined(__LITTLE_ENDIAN)
-	u16 status_block_index;
-	u16 sb_id_and_flags;
-#define IGU_ACK_REGISTER_STATUS_BLOCK_ID (0x1F<<0)
-#define IGU_ACK_REGISTER_STATUS_BLOCK_ID_SHIFT 0
-#define IGU_ACK_REGISTER_STORM_ID (0x7<<5)
-#define IGU_ACK_REGISTER_STORM_ID_SHIFT 5
-#define IGU_ACK_REGISTER_UPDATE_INDEX (0x1<<8)
-#define IGU_ACK_REGISTER_UPDATE_INDEX_SHIFT 8
-#define IGU_ACK_REGISTER_INTERRUPT_MODE (0x3<<9)
-#define IGU_ACK_REGISTER_INTERRUPT_MODE_SHIFT 9
-#define IGU_ACK_REGISTER_RESERVED (0x1F<<11)
-#define IGU_ACK_REGISTER_RESERVED_SHIFT 11
-#endif
-};
-
-
-/*
- * IGU driver acknowledgement register
- */
-struct igu_backward_compatible {
-	u32 sb_id_and_flags;
-#define IGU_BACKWARD_COMPATIBLE_SB_INDEX (0xFFFF<<0)
-#define IGU_BACKWARD_COMPATIBLE_SB_INDEX_SHIFT 0
-#define IGU_BACKWARD_COMPATIBLE_SB_SELECT (0x1F<<16)
-#define IGU_BACKWARD_COMPATIBLE_SB_SELECT_SHIFT 16
-#define IGU_BACKWARD_COMPATIBLE_SEGMENT_ACCESS (0x7<<21)
-#define IGU_BACKWARD_COMPATIBLE_SEGMENT_ACCESS_SHIFT 21
-#define IGU_BACKWARD_COMPATIBLE_BUPDATE (0x1<<24)
-#define IGU_BACKWARD_COMPATIBLE_BUPDATE_SHIFT 24
-#define IGU_BACKWARD_COMPATIBLE_ENABLE_INT (0x3<<25)
-#define IGU_BACKWARD_COMPATIBLE_ENABLE_INT_SHIFT 25
-#define IGU_BACKWARD_COMPATIBLE_RESERVED_0 (0x1F<<27)
-#define IGU_BACKWARD_COMPATIBLE_RESERVED_0_SHIFT 27
-	u32 reserved_2;
-};
-
-
-/*
- * IGU driver acknowledgement register
- */
-struct igu_regular {
-	u32 sb_id_and_flags;
-#define IGU_REGULAR_SB_INDEX (0xFFFFF<<0)
-#define IGU_REGULAR_SB_INDEX_SHIFT 0
-#define IGU_REGULAR_RESERVED0 (0x1<<20)
-#define IGU_REGULAR_RESERVED0_SHIFT 20
-#define IGU_REGULAR_SEGMENT_ACCESS (0x7<<21)
-#define IGU_REGULAR_SEGMENT_ACCESS_SHIFT 21
-#define IGU_REGULAR_BUPDATE (0x1<<24)
-#define IGU_REGULAR_BUPDATE_SHIFT 24
-#define IGU_REGULAR_ENABLE_INT (0x3<<25)
-#define IGU_REGULAR_ENABLE_INT_SHIFT 25
-#define IGU_REGULAR_RESERVED_1 (0x1<<27)
-#define IGU_REGULAR_RESERVED_1_SHIFT 27
-#define IGU_REGULAR_CLEANUP_TYPE (0x3<<28)
-#define IGU_REGULAR_CLEANUP_TYPE_SHIFT 28
-#define IGU_REGULAR_CLEANUP_SET (0x1<<30)
-#define IGU_REGULAR_CLEANUP_SET_SHIFT 30
-#define IGU_REGULAR_BCLEANUP (0x1<<31)
-#define IGU_REGULAR_BCLEANUP_SHIFT 31
-	u32 reserved_2;
-};
-
-/*
- * IGU driver acknowledgement register
- */
-union igu_consprod_reg {
-	struct igu_regular regular;
-	struct igu_backward_compatible backward_compatible;
-};
-
-
-/*
- * Igu control commands
- */
-enum igu_ctrl_cmd {
-	IGU_CTRL_CMD_TYPE_RD,
-	IGU_CTRL_CMD_TYPE_WR,
-	MAX_IGU_CTRL_CMD
-};
-
-
-/*
- * Control register for the IGU command register
- */
-struct igu_ctrl_reg {
-	u32 ctrl_data;
-#define IGU_CTRL_REG_ADDRESS (0xFFF<<0)
-#define IGU_CTRL_REG_ADDRESS_SHIFT 0
-#define IGU_CTRL_REG_FID (0x7F<<12)
-#define IGU_CTRL_REG_FID_SHIFT 12
-#define IGU_CTRL_REG_RESERVED (0x1<<19)
-#define IGU_CTRL_REG_RESERVED_SHIFT 19
-#define IGU_CTRL_REG_TYPE (0x1<<20)
-#define IGU_CTRL_REG_TYPE_SHIFT 20
-#define IGU_CTRL_REG_UNUSED (0x7FF<<21)
-#define IGU_CTRL_REG_UNUSED_SHIFT 21
-};
-
-
-/*
- * Igu interrupt command
- */
-enum igu_int_cmd {
-	IGU_INT_ENABLE,
-	IGU_INT_DISABLE,
-	IGU_INT_NOP,
-	IGU_INT_NOP2,
-	MAX_IGU_INT_CMD
-};
-
-
-/*
- * Igu segments
- */
-enum igu_seg_access {
-	IGU_SEG_ACCESS_NORM,
-	IGU_SEG_ACCESS_DEF,
-	IGU_SEG_ACCESS_ATTN,
-	MAX_IGU_SEG_ACCESS
-};
-
-
-/*
- * Parser parsing flags field
- */
-struct parsing_flags {
-	__le16 flags;
-#define PARSING_FLAGS_ETHERNET_ADDRESS_TYPE (0x1<<0)
-#define PARSING_FLAGS_ETHERNET_ADDRESS_TYPE_SHIFT 0
-#define PARSING_FLAGS_VLAN (0x1<<1)
-#define PARSING_FLAGS_VLAN_SHIFT 1
-#define PARSING_FLAGS_EXTRA_VLAN (0x1<<2)
-#define PARSING_FLAGS_EXTRA_VLAN_SHIFT 2
-#define PARSING_FLAGS_OVER_ETHERNET_PROTOCOL (0x3<<3)
-#define PARSING_FLAGS_OVER_ETHERNET_PROTOCOL_SHIFT 3
-#define PARSING_FLAGS_IP_OPTIONS (0x1<<5)
-#define PARSING_FLAGS_IP_OPTIONS_SHIFT 5
-#define PARSING_FLAGS_FRAGMENTATION_STATUS (0x1<<6)
-#define PARSING_FLAGS_FRAGMENTATION_STATUS_SHIFT 6
-#define PARSING_FLAGS_OVER_IP_PROTOCOL (0x3<<7)
-#define PARSING_FLAGS_OVER_IP_PROTOCOL_SHIFT 7
-#define PARSING_FLAGS_PURE_ACK_INDICATION (0x1<<9)
-#define PARSING_FLAGS_PURE_ACK_INDICATION_SHIFT 9
-#define PARSING_FLAGS_TCP_OPTIONS_EXIST (0x1<<10)
-#define PARSING_FLAGS_TCP_OPTIONS_EXIST_SHIFT 10
-#define PARSING_FLAGS_TIME_STAMP_EXIST_FLAG (0x1<<11)
-#define PARSING_FLAGS_TIME_STAMP_EXIST_FLAG_SHIFT 11
-#define PARSING_FLAGS_CONNECTION_MATCH (0x1<<12)
-#define PARSING_FLAGS_CONNECTION_MATCH_SHIFT 12
-#define PARSING_FLAGS_LLC_SNAP (0x1<<13)
-#define PARSING_FLAGS_LLC_SNAP_SHIFT 13
-#define PARSING_FLAGS_RESERVED0 (0x3<<14)
-#define PARSING_FLAGS_RESERVED0_SHIFT 14
-};
-
-
-/*
- * Parsing flags for TCP ACK type
- */
-enum prs_flags_ack_type {
-	PRS_FLAG_PUREACK_PIGGY,
-	PRS_FLAG_PUREACK_PURE,
-	MAX_PRS_FLAGS_ACK_TYPE
-};
-
-
-/*
- * Parsing flags for Ethernet address type
- */
-enum prs_flags_eth_addr_type {
-	PRS_FLAG_ETHTYPE_NON_UNICAST,
-	PRS_FLAG_ETHTYPE_UNICAST,
-	MAX_PRS_FLAGS_ETH_ADDR_TYPE
-};
-
-
-/*
- * Parsing flags for over-ethernet protocol
- */
-enum prs_flags_over_eth {
-	PRS_FLAG_OVERETH_UNKNOWN,
-	PRS_FLAG_OVERETH_IPV4,
-	PRS_FLAG_OVERETH_IPV6,
-	PRS_FLAG_OVERETH_LLCSNAP_UNKNOWN,
-	MAX_PRS_FLAGS_OVER_ETH
-};
-
-
-/*
- * Parsing flags for over-IP protocol
- */
-enum prs_flags_over_ip {
-	PRS_FLAG_OVERIP_UNKNOWN,
-	PRS_FLAG_OVERIP_TCP,
-	PRS_FLAG_OVERIP_UDP,
-	MAX_PRS_FLAGS_OVER_IP
-};
-
-
-/*
- * SDM operation gen command (generate aggregative interrupt)
- */
-struct sdm_op_gen {
-	__le32 command;
-#define SDM_OP_GEN_COMP_PARAM (0x1F<<0)
-#define SDM_OP_GEN_COMP_PARAM_SHIFT 0
-#define SDM_OP_GEN_COMP_TYPE (0x7<<5)
-#define SDM_OP_GEN_COMP_TYPE_SHIFT 5
-#define SDM_OP_GEN_AGG_VECT_IDX (0xFF<<8)
-#define SDM_OP_GEN_AGG_VECT_IDX_SHIFT 8
-#define SDM_OP_GEN_AGG_VECT_IDX_VALID (0x1<<16)
-#define SDM_OP_GEN_AGG_VECT_IDX_VALID_SHIFT 16
-#define SDM_OP_GEN_RESERVED (0x7FFF<<17)
-#define SDM_OP_GEN_RESERVED_SHIFT 17
-};
-
-
-/*
- * Timers connection context
- */
-struct timers_block_context {
-	u32 __reserved_0;
-	u32 __reserved_1;
-	u32 __reserved_2;
-	u32 flags;
-#define __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS (0x3<<0)
-#define __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS_SHIFT 0
-#define TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG (0x1<<2)
-#define TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG_SHIFT 2
-#define __TIMERS_BLOCK_CONTEXT_RESERVED0 (0x1FFFFFFF<<3)
-#define __TIMERS_BLOCK_CONTEXT_RESERVED0_SHIFT 3
-};
-
-
-/*
- * The eth aggregative context of Tstorm
- */
-struct tstorm_eth_ag_context {
-	u32 __reserved0[14];
-};
-
-
-/*
- * The eth aggregative context of Ustorm
- */
-struct ustorm_eth_ag_context {
-	u32 __reserved0;
-#if defined(__BIG_ENDIAN)
-	u8 cdu_usage;
-	u8 __reserved2;
-	u16 __reserved1;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __reserved1;
-	u8 __reserved2;
-	u8 cdu_usage;
-#endif
-	u32 __reserved3[6];
-};
-
-
-/*
- * The eth aggregative context of Xstorm
- */
-struct xstorm_eth_ag_context {
-	u32 reserved0;
-#if defined(__BIG_ENDIAN)
-	u8 cdu_reserved;
-	u8 reserved2;
-	u16 reserved1;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved1;
-	u8 reserved2;
-	u8 cdu_reserved;
-#endif
-	u32 reserved3[30];
-};
-
-
-/*
- * doorbell message sent to the chip
- */
-struct doorbell {
-#if defined(__BIG_ENDIAN)
-	u16 zero_fill2;
-	u8 zero_fill1;
-	struct doorbell_hdr header;
-#elif defined(__LITTLE_ENDIAN)
-	struct doorbell_hdr header;
-	u8 zero_fill1;
-	u16 zero_fill2;
-#endif
-};
-
-
-/*
- * doorbell message sent to the chip
- */
-struct doorbell_set_prod {
-#if defined(__BIG_ENDIAN)
-	u16 prod;
-	u8 zero_fill1;
-	struct doorbell_hdr header;
-#elif defined(__LITTLE_ENDIAN)
-	struct doorbell_hdr header;
-	u8 zero_fill1;
-	u16 prod;
-#endif
-};
-
-
-struct regpair {
-	__le32 lo;
-	__le32 hi;
-};
-
-
-/*
- * Classify rule opcodes in E2/E3
- */
-enum classify_rule {
-	CLASSIFY_RULE_OPCODE_MAC,
-	CLASSIFY_RULE_OPCODE_VLAN,
-	CLASSIFY_RULE_OPCODE_PAIR,
-	MAX_CLASSIFY_RULE
-};
-
-
-/*
- * Classify rule types in E2/E3
- */
-enum classify_rule_action_type {
-	CLASSIFY_RULE_REMOVE,
-	CLASSIFY_RULE_ADD,
-	MAX_CLASSIFY_RULE_ACTION_TYPE
-};
-
-
-/*
- * client init ramrod data
- */
-struct client_init_general_data {
-	u8 client_id;
-	u8 statistics_counter_id;
-	u8 statistics_en_flg;
-	u8 is_fcoe_flg;
-	u8 activate_flg;
-	u8 sp_client_id;
-	__le16 mtu;
-	u8 statistics_zero_flg;
-	u8 func_id;
-	u8 cos;
-	u8 traffic_type;
-	u32 reserved0;
-};
-
-
-/*
- * client init rx data
- */
-struct client_init_rx_data {
-	u8 tpa_en;
-#define CLIENT_INIT_RX_DATA_TPA_EN_IPV4 (0x1<<0)
-#define CLIENT_INIT_RX_DATA_TPA_EN_IPV4_SHIFT 0
-#define CLIENT_INIT_RX_DATA_TPA_EN_IPV6 (0x1<<1)
-#define CLIENT_INIT_RX_DATA_TPA_EN_IPV6_SHIFT 1
-#define CLIENT_INIT_RX_DATA_RESERVED5 (0x3F<<2)
-#define CLIENT_INIT_RX_DATA_RESERVED5_SHIFT 2
-	u8 vmqueue_mode_en_flg;
-	u8 extra_data_over_sgl_en_flg;
-	u8 cache_line_alignment_log_size;
-	u8 enable_dynamic_hc;
-	u8 max_sges_for_packet;
-	u8 client_qzone_id;
-	u8 drop_ip_cs_err_flg;
-	u8 drop_tcp_cs_err_flg;
-	u8 drop_ttl0_flg;
-	u8 drop_udp_cs_err_flg;
-	u8 inner_vlan_removal_enable_flg;
-	u8 outer_vlan_removal_enable_flg;
-	u8 status_block_id;
-	u8 rx_sb_index_number;
-	u8 reserved0;
-	u8 max_tpa_queues;
-	u8 silent_vlan_removal_flg;
-	__le16 max_bytes_on_bd;
-	__le16 sge_buff_size;
-	u8 approx_mcast_engine_id;
-	u8 rss_engine_id;
-	struct regpair bd_page_base;
-	struct regpair sge_page_base;
-	struct regpair cqe_page_base;
-	u8 is_leading_rss;
-	u8 is_approx_mcast;
-	__le16 max_agg_size;
-	__le16 state;
-#define CLIENT_INIT_RX_DATA_UCAST_DROP_ALL (0x1<<0)
-#define CLIENT_INIT_RX_DATA_UCAST_DROP_ALL_SHIFT 0
-#define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_ALL (0x1<<1)
-#define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_ALL_SHIFT 1
-#define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_UNMATCHED (0x1<<2)
-#define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_UNMATCHED_SHIFT 2
-#define CLIENT_INIT_RX_DATA_MCAST_DROP_ALL (0x1<<3)
-#define CLIENT_INIT_RX_DATA_MCAST_DROP_ALL_SHIFT 3
-#define CLIENT_INIT_RX_DATA_MCAST_ACCEPT_ALL (0x1<<4)
-#define CLIENT_INIT_RX_DATA_MCAST_ACCEPT_ALL_SHIFT 4
-#define CLIENT_INIT_RX_DATA_BCAST_ACCEPT_ALL (0x1<<5)
-#define CLIENT_INIT_RX_DATA_BCAST_ACCEPT_ALL_SHIFT 5
-#define CLIENT_INIT_RX_DATA_ACCEPT_ANY_VLAN (0x1<<6)
-#define CLIENT_INIT_RX_DATA_ACCEPT_ANY_VLAN_SHIFT 6
-#define CLIENT_INIT_RX_DATA_RESERVED2 (0x1FF<<7)
-#define CLIENT_INIT_RX_DATA_RESERVED2_SHIFT 7
-	__le16 cqe_pause_thr_low;
-	__le16 cqe_pause_thr_high;
-	__le16 bd_pause_thr_low;
-	__le16 bd_pause_thr_high;
-	__le16 sge_pause_thr_low;
-	__le16 sge_pause_thr_high;
-	__le16 rx_cos_mask;
-	__le16 silent_vlan_value;
-	__le16 silent_vlan_mask;
-	__le32 reserved6[2];
-};
-
-/*
- * client init tx data
- */
-struct client_init_tx_data {
-	u8 enforce_security_flg;
-	u8 tx_status_block_id;
-	u8 tx_sb_index_number;
-	u8 tss_leading_client_id;
-	u8 tx_switching_flg;
-	u8 anti_spoofing_flg;
-	__le16 default_vlan;
-	struct regpair tx_bd_page_base;
-	__le16 state;
-#define CLIENT_INIT_TX_DATA_UCAST_ACCEPT_ALL (0x1<<0)
-#define CLIENT_INIT_TX_DATA_UCAST_ACCEPT_ALL_SHIFT 0
-#define CLIENT_INIT_TX_DATA_MCAST_ACCEPT_ALL (0x1<<1)
-#define CLIENT_INIT_TX_DATA_MCAST_ACCEPT_ALL_SHIFT 1
-#define CLIENT_INIT_TX_DATA_BCAST_ACCEPT_ALL (0x1<<2)
-#define CLIENT_INIT_TX_DATA_BCAST_ACCEPT_ALL_SHIFT 2
-#define CLIENT_INIT_TX_DATA_ACCEPT_ANY_VLAN (0x1<<3)
-#define CLIENT_INIT_TX_DATA_ACCEPT_ANY_VLAN_SHIFT 3
-#define CLIENT_INIT_TX_DATA_RESERVED1 (0xFFF<<4)
-#define CLIENT_INIT_TX_DATA_RESERVED1_SHIFT 4
-	u8 default_vlan_flg;
-	u8 reserved2;
-	__le32 reserved3;
-};
-
-/*
- * client init ramrod data
- */
-struct client_init_ramrod_data {
-	struct client_init_general_data general;
-	struct client_init_rx_data rx;
-	struct client_init_tx_data tx;
-};
-
-
-/*
- * client update ramrod data
- */
-struct client_update_ramrod_data {
-	u8 client_id;
-	u8 func_id;
-	u8 inner_vlan_removal_enable_flg;
-	u8 inner_vlan_removal_change_flg;
-	u8 outer_vlan_removal_enable_flg;
-	u8 outer_vlan_removal_change_flg;
-	u8 anti_spoofing_enable_flg;
-	u8 anti_spoofing_change_flg;
-	u8 activate_flg;
-	u8 activate_change_flg;
-	__le16 default_vlan;
-	u8 default_vlan_enable_flg;
-	u8 default_vlan_change_flg;
-	__le16 silent_vlan_value;
-	__le16 silent_vlan_mask;
-	u8 silent_vlan_removal_flg;
-	u8 silent_vlan_change_flg;
-	__le32 echo;
-};
-
-
-/*
- * The eth storm context of Cstorm
- */
-struct cstorm_eth_st_context {
-	u32 __reserved0[4];
-};
-
-
-struct double_regpair {
-	u32 regpair0_lo;
-	u32 regpair0_hi;
-	u32 regpair1_lo;
-	u32 regpair1_hi;
-};
-
-
-/*
- * Ethernet address typesm used in ethernet tx BDs
- */
-enum eth_addr_type {
-	UNKNOWN_ADDRESS,
-	UNICAST_ADDRESS,
-	MULTICAST_ADDRESS,
-	BROADCAST_ADDRESS,
-	MAX_ETH_ADDR_TYPE
-};
-
-
-/*
- *
- */
-struct eth_classify_cmd_header {
-	u8 cmd_general_data;
-#define ETH_CLASSIFY_CMD_HEADER_RX_CMD (0x1<<0)
-#define ETH_CLASSIFY_CMD_HEADER_RX_CMD_SHIFT 0
-#define ETH_CLASSIFY_CMD_HEADER_TX_CMD (0x1<<1)
-#define ETH_CLASSIFY_CMD_HEADER_TX_CMD_SHIFT 1
-#define ETH_CLASSIFY_CMD_HEADER_OPCODE (0x3<<2)
-#define ETH_CLASSIFY_CMD_HEADER_OPCODE_SHIFT 2
-#define ETH_CLASSIFY_CMD_HEADER_IS_ADD (0x1<<4)
-#define ETH_CLASSIFY_CMD_HEADER_IS_ADD_SHIFT 4
-#define ETH_CLASSIFY_CMD_HEADER_RESERVED0 (0x7<<5)
-#define ETH_CLASSIFY_CMD_HEADER_RESERVED0_SHIFT 5
-	u8 func_id;
-	u8 client_id;
-	u8 reserved1;
-};
-
-
-/*
- * header for eth classification config ramrod
- */
-struct eth_classify_header {
-	u8 rule_cnt;
-	u8 reserved0;
-	__le16 reserved1;
-	__le32 echo;
-};
-
-
-/*
- * Command for adding/removing a MAC classification rule
- */
-struct eth_classify_mac_cmd {
-	struct eth_classify_cmd_header header;
-	__le32 reserved0;
-	__le16 mac_lsb;
-	__le16 mac_mid;
-	__le16 mac_msb;
-	__le16 reserved1;
-};
-
-
-/*
- * Command for adding/removing a MAC-VLAN pair classification rule
- */
-struct eth_classify_pair_cmd {
-	struct eth_classify_cmd_header header;
-	__le32 reserved0;
-	__le16 mac_lsb;
-	__le16 mac_mid;
-	__le16 mac_msb;
-	__le16 vlan;
-};
-
-
-/*
- * Command for adding/removing a VLAN classification rule
- */
-struct eth_classify_vlan_cmd {
-	struct eth_classify_cmd_header header;
-	__le32 reserved0;
-	__le32 reserved1;
-	__le16 reserved2;
-	__le16 vlan;
-};
-
-/*
- * union for eth classification rule
- */
-union eth_classify_rule_cmd {
-	struct eth_classify_mac_cmd mac;
-	struct eth_classify_vlan_cmd vlan;
-	struct eth_classify_pair_cmd pair;
-};
-
-/*
- * parameters for eth classification configuration ramrod
- */
-struct eth_classify_rules_ramrod_data {
-	struct eth_classify_header header;
-	union eth_classify_rule_cmd rules[CLASSIFY_RULES_COUNT];
-};
-
-
-/*
- * The data contain client ID need to the ramrod
- */
-struct eth_common_ramrod_data {
-	__le32 client_id;
-	__le32 reserved1;
-};
-
-
-/*
- * The eth storm context of Ustorm
- */
-struct ustorm_eth_st_context {
-	u32 reserved0[52];
-};
-
-/*
- * The eth storm context of Tstorm
- */
-struct tstorm_eth_st_context {
-	u32 __reserved0[28];
-};
-
-/*
- * The eth storm context of Xstorm
- */
-struct xstorm_eth_st_context {
-	u32 reserved0[60];
-};
-
-/*
- * Ethernet connection context
- */
-struct eth_context {
-	struct ustorm_eth_st_context ustorm_st_context;
-	struct tstorm_eth_st_context tstorm_st_context;
-	struct xstorm_eth_ag_context xstorm_ag_context;
-	struct tstorm_eth_ag_context tstorm_ag_context;
-	struct cstorm_eth_ag_context cstorm_ag_context;
-	struct ustorm_eth_ag_context ustorm_ag_context;
-	struct timers_block_context timers_context;
-	struct xstorm_eth_st_context xstorm_st_context;
-	struct cstorm_eth_st_context cstorm_st_context;
-};
-
-
-/*
- * union for sgl and raw data.
- */
-union eth_sgl_or_raw_data {
-	__le16 sgl[8];
-	u32 raw_data[4];
-};
-
-/*
- * eth FP end aggregation CQE parameters struct
- */
-struct eth_end_agg_rx_cqe {
-	u8 type_error_flags;
-#define ETH_END_AGG_RX_CQE_TYPE (0x3<<0)
-#define ETH_END_AGG_RX_CQE_TYPE_SHIFT 0
-#define ETH_END_AGG_RX_CQE_SGL_RAW_SEL (0x1<<2)
-#define ETH_END_AGG_RX_CQE_SGL_RAW_SEL_SHIFT 2
-#define ETH_END_AGG_RX_CQE_RESERVED0 (0x1F<<3)
-#define ETH_END_AGG_RX_CQE_RESERVED0_SHIFT 3
-	u8 reserved1;
-	u8 queue_index;
-	u8 reserved2;
-	__le32 timestamp_delta;
-	__le16 num_of_coalesced_segs;
-	__le16 pkt_len;
-	u8 pure_ack_count;
-	u8 reserved3;
-	__le16 reserved4;
-	union eth_sgl_or_raw_data sgl_or_raw_data;
-	__le32 reserved5[8];
-};
-
-
-/*
- * regular eth FP CQE parameters struct
- */
-struct eth_fast_path_rx_cqe {
-	u8 type_error_flags;
-#define ETH_FAST_PATH_RX_CQE_TYPE (0x3<<0)
-#define ETH_FAST_PATH_RX_CQE_TYPE_SHIFT 0
-#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL (0x1<<2)
-#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL_SHIFT 2
-#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG (0x1<<3)
-#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG_SHIFT 3
-#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG (0x1<<4)
-#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG_SHIFT 4
-#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG (0x1<<5)
-#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG_SHIFT 5
-#define ETH_FAST_PATH_RX_CQE_RESERVED0 (0x3<<6)
-#define ETH_FAST_PATH_RX_CQE_RESERVED0_SHIFT 6
-	u8 status_flags;
-#define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE (0x7<<0)
-#define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE_SHIFT 0
-#define ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG (0x1<<3)
-#define ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG_SHIFT 3
-#define ETH_FAST_PATH_RX_CQE_BROADCAST_FLG (0x1<<4)
-#define ETH_FAST_PATH_RX_CQE_BROADCAST_FLG_SHIFT 4
-#define ETH_FAST_PATH_RX_CQE_MAC_MATCH_FLG (0x1<<5)
-#define ETH_FAST_PATH_RX_CQE_MAC_MATCH_FLG_SHIFT 5
-#define ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG (0x1<<6)
-#define ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG_SHIFT 6
-#define ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG (0x1<<7)
-#define ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG_SHIFT 7
-	u8 queue_index;
-	u8 placement_offset;
-	__le32 rss_hash_result;
-	__le16 vlan_tag;
-	__le16 pkt_len;
-	__le16 len_on_bd;
-	struct parsing_flags pars_flags;
-	union eth_sgl_or_raw_data sgl_or_raw_data;
-	__le32 reserved1[8];
-};
-
-
-/*
- * Command for setting classification flags for a client
- */
-struct eth_filter_rules_cmd {
-	u8 cmd_general_data;
-#define ETH_FILTER_RULES_CMD_RX_CMD (0x1<<0)
-#define ETH_FILTER_RULES_CMD_RX_CMD_SHIFT 0
-#define ETH_FILTER_RULES_CMD_TX_CMD (0x1<<1)
-#define ETH_FILTER_RULES_CMD_TX_CMD_SHIFT 1
-#define ETH_FILTER_RULES_CMD_RESERVED0 (0x3F<<2)
-#define ETH_FILTER_RULES_CMD_RESERVED0_SHIFT 2
-	u8 func_id;
-	u8 client_id;
-	u8 reserved1;
-	__le16 state;
-#define ETH_FILTER_RULES_CMD_UCAST_DROP_ALL (0x1<<0)
-#define ETH_FILTER_RULES_CMD_UCAST_DROP_ALL_SHIFT 0
-#define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL (0x1<<1)
-#define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL_SHIFT 1
-#define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED (0x1<<2)
-#define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED_SHIFT 2
-#define ETH_FILTER_RULES_CMD_MCAST_DROP_ALL (0x1<<3)
-#define ETH_FILTER_RULES_CMD_MCAST_DROP_ALL_SHIFT 3
-#define ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL (0x1<<4)
-#define ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL_SHIFT 4
-#define ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL (0x1<<5)
-#define ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL_SHIFT 5
-#define ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN (0x1<<6)
-#define ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN_SHIFT 6
-#define ETH_FILTER_RULES_CMD_RESERVED2 (0x1FF<<7)
-#define ETH_FILTER_RULES_CMD_RESERVED2_SHIFT 7
-	__le16 reserved3;
-	struct regpair reserved4;
-};
-
-
-/*
- * parameters for eth classification filters ramrod
- */
-struct eth_filter_rules_ramrod_data {
-	struct eth_classify_header header;
-	struct eth_filter_rules_cmd rules[FILTER_RULES_COUNT];
-};
-
-
-/*
- * parameters for eth classification configuration ramrod
- */
-struct eth_general_rules_ramrod_data {
-	struct eth_classify_header header;
-	union eth_classify_rule_cmd rules[CLASSIFY_RULES_COUNT];
-};
-
-
-/*
- * The data for Halt ramrod
- */
-struct eth_halt_ramrod_data {
-	__le32 client_id;
-	__le32 reserved0;
-};
-
-
-/*
- * Command for setting multicast classification for a client
- */
-struct eth_multicast_rules_cmd {
-	u8 cmd_general_data;
-#define ETH_MULTICAST_RULES_CMD_RX_CMD (0x1<<0)
-#define ETH_MULTICAST_RULES_CMD_RX_CMD_SHIFT 0
-#define ETH_MULTICAST_RULES_CMD_TX_CMD (0x1<<1)
-#define ETH_MULTICAST_RULES_CMD_TX_CMD_SHIFT 1
-#define ETH_MULTICAST_RULES_CMD_IS_ADD (0x1<<2)
-#define ETH_MULTICAST_RULES_CMD_IS_ADD_SHIFT 2
-#define ETH_MULTICAST_RULES_CMD_RESERVED0 (0x1F<<3)
-#define ETH_MULTICAST_RULES_CMD_RESERVED0_SHIFT 3
-	u8 func_id;
-	u8 bin_id;
-	u8 engine_id;
-	__le32 reserved2;
-	struct regpair reserved3;
-};
-
-
-/*
- * parameters for multicast classification ramrod
- */
-struct eth_multicast_rules_ramrod_data {
-	struct eth_classify_header header;
-	struct eth_multicast_rules_cmd rules[MULTICAST_RULES_COUNT];
-};
-
-
-/*
- * Place holder for ramrods protocol specific data
- */
-struct ramrod_data {
-	__le32 data_lo;
-	__le32 data_hi;
-};
-
-/*
- * union for ramrod data for Ethernet protocol (CQE) (force size of 16 bits)
- */
-union eth_ramrod_data {
-	struct ramrod_data general;
-};
-
-
-/*
- * RSS toeplitz hash type, as reported in CQE
- */
-enum eth_rss_hash_type {
-	DEFAULT_HASH_TYPE,
-	IPV4_HASH_TYPE,
-	TCP_IPV4_HASH_TYPE,
-	IPV6_HASH_TYPE,
-	TCP_IPV6_HASH_TYPE,
-	VLAN_PRI_HASH_TYPE,
-	E1HOV_PRI_HASH_TYPE,
-	DSCP_HASH_TYPE,
-	MAX_ETH_RSS_HASH_TYPE
-};
-
-
-/*
- * Ethernet RSS mode
- */
-enum eth_rss_mode {
-	ETH_RSS_MODE_DISABLED,
-	ETH_RSS_MODE_REGULAR,
-	ETH_RSS_MODE_VLAN_PRI,
-	ETH_RSS_MODE_E1HOV_PRI,
-	ETH_RSS_MODE_IP_DSCP,
-	MAX_ETH_RSS_MODE
-};
-
-
-/*
- * parameters for RSS update ramrod (E2)
- */
-struct eth_rss_update_ramrod_data {
-	u8 rss_engine_id;
-	u8 capabilities;
-#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY (0x1<<0)
-#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY_SHIFT 0
-#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY (0x1<<1)
-#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY_SHIFT 1
-#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY (0x1<<2)
-#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY_SHIFT 2
-#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY (0x1<<3)
-#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY_SHIFT 3
-#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY (0x1<<4)
-#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY_SHIFT 4
-#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY (0x1<<5)
-#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY_SHIFT 5
-#define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY (0x1<<6)
-#define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY_SHIFT 6
-#define __ETH_RSS_UPDATE_RAMROD_DATA_RESERVED0 (0x1<<7)
-#define __ETH_RSS_UPDATE_RAMROD_DATA_RESERVED0_SHIFT 7
-	u8 rss_result_mask;
-	u8 rss_mode;
-	__le32 __reserved2;
-	u8 indirection_table[T_ETH_INDIRECTION_TABLE_SIZE];
-	__le32 rss_key[T_ETH_RSS_KEY];
-	__le32 echo;
-	__le32 reserved3;
-};
-
-
-/*
- * The eth Rx Buffer Descriptor
- */
-struct eth_rx_bd {
-	__le32 addr_lo;
-	__le32 addr_hi;
-};
-
-
-/*
- * Eth Rx Cqe structure- general structure for ramrods
- */
-struct common_ramrod_eth_rx_cqe {
-	u8 ramrod_type;
-#define COMMON_RAMROD_ETH_RX_CQE_TYPE (0x3<<0)
-#define COMMON_RAMROD_ETH_RX_CQE_TYPE_SHIFT 0
-#define COMMON_RAMROD_ETH_RX_CQE_ERROR (0x1<<2)
-#define COMMON_RAMROD_ETH_RX_CQE_ERROR_SHIFT 2
-#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0 (0x1F<<3)
-#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0_SHIFT 3
-	u8 conn_type;
-	__le16 reserved1;
-	__le32 conn_and_cmd_data;
-#define COMMON_RAMROD_ETH_RX_CQE_CID (0xFFFFFF<<0)
-#define COMMON_RAMROD_ETH_RX_CQE_CID_SHIFT 0
-#define COMMON_RAMROD_ETH_RX_CQE_CMD_ID (0xFF<<24)
-#define COMMON_RAMROD_ETH_RX_CQE_CMD_ID_SHIFT 24
-	struct ramrod_data protocol_data;
-	__le32 echo;
-	__le32 reserved2[11];
-};
-
-/*
- * Rx Last CQE in page (in ETH)
- */
-struct eth_rx_cqe_next_page {
-	__le32 addr_lo;
-	__le32 addr_hi;
-	__le32 reserved[14];
-};
-
-/*
- * union for all eth rx cqe types (fix their sizes)
- */
-union eth_rx_cqe {
-	struct eth_fast_path_rx_cqe fast_path_cqe;
-	struct common_ramrod_eth_rx_cqe ramrod_cqe;
-	struct eth_rx_cqe_next_page next_page_cqe;
-	struct eth_end_agg_rx_cqe end_agg_cqe;
-};
-
-
-/*
- * Values for RX ETH CQE type field
- */
-enum eth_rx_cqe_type {
-	RX_ETH_CQE_TYPE_ETH_FASTPATH,
-	RX_ETH_CQE_TYPE_ETH_RAMROD,
-	RX_ETH_CQE_TYPE_ETH_START_AGG,
-	RX_ETH_CQE_TYPE_ETH_STOP_AGG,
-	MAX_ETH_RX_CQE_TYPE
-};
-
-
-/*
- * Type of SGL/Raw field in ETH RX fast path CQE
- */
-enum eth_rx_fp_sel {
-	ETH_FP_CQE_REGULAR,
-	ETH_FP_CQE_RAW,
-	MAX_ETH_RX_FP_SEL
-};
-
-
-/*
- * The eth Rx SGE Descriptor
- */
-struct eth_rx_sge {
-	__le32 addr_lo;
-	__le32 addr_hi;
-};
-
-
-/*
- * common data for all protocols
- */
-struct spe_hdr {
-	__le32 conn_and_cmd_data;
-#define SPE_HDR_CID (0xFFFFFF<<0)
-#define SPE_HDR_CID_SHIFT 0
-#define SPE_HDR_CMD_ID (0xFF<<24)
-#define SPE_HDR_CMD_ID_SHIFT 24
-	__le16 type;
-#define SPE_HDR_CONN_TYPE (0xFF<<0)
-#define SPE_HDR_CONN_TYPE_SHIFT 0
-#define SPE_HDR_FUNCTION_ID (0xFF<<8)
-#define SPE_HDR_FUNCTION_ID_SHIFT 8
-	__le16 reserved1;
-};
-
-/*
- * specific data for ethernet slow path element
- */
-union eth_specific_data {
-	u8 protocol_data[8];
-	struct regpair client_update_ramrod_data;
-	struct regpair client_init_ramrod_init_data;
-	struct eth_halt_ramrod_data halt_ramrod_data;
-	struct regpair update_data_addr;
-	struct eth_common_ramrod_data common_ramrod_data;
-	struct regpair classify_cfg_addr;
-	struct regpair filter_cfg_addr;
-	struct regpair mcast_cfg_addr;
-};
-
-/*
- * Ethernet slow path element
- */
-struct eth_spe {
-	struct spe_hdr hdr;
-	union eth_specific_data data;
-};
-
-
-/*
- * Ethernet command ID for slow path elements
- */
-enum eth_spqe_cmd_id {
-	RAMROD_CMD_ID_ETH_UNUSED,
-	RAMROD_CMD_ID_ETH_CLIENT_SETUP,
-	RAMROD_CMD_ID_ETH_HALT,
-	RAMROD_CMD_ID_ETH_FORWARD_SETUP,
-	RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP,
-	RAMROD_CMD_ID_ETH_CLIENT_UPDATE,
-	RAMROD_CMD_ID_ETH_EMPTY,
-	RAMROD_CMD_ID_ETH_TERMINATE,
-	RAMROD_CMD_ID_ETH_TPA_UPDATE,
-	RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES,
-	RAMROD_CMD_ID_ETH_FILTER_RULES,
-	RAMROD_CMD_ID_ETH_MULTICAST_RULES,
-	RAMROD_CMD_ID_ETH_RSS_UPDATE,
-	RAMROD_CMD_ID_ETH_SET_MAC,
-	MAX_ETH_SPQE_CMD_ID
-};
-
-
-/*
- * eth tpa update command
- */
-enum eth_tpa_update_command {
-	TPA_UPDATE_NONE_COMMAND,
-	TPA_UPDATE_ENABLE_COMMAND,
-	TPA_UPDATE_DISABLE_COMMAND,
-	MAX_ETH_TPA_UPDATE_COMMAND
-};
-
-
-/*
- * Tx regular BD structure
- */
-struct eth_tx_bd {
-	__le32 addr_lo;
-	__le32 addr_hi;
-	__le16 total_pkt_bytes;
-	__le16 nbytes;
-	u8 reserved[4];
-};
-
-
-/*
- * structure for easy accessibility to assembler
- */
-struct eth_tx_bd_flags {
-	u8 as_bitfield;
-#define ETH_TX_BD_FLAGS_IP_CSUM (0x1<<0)
-#define ETH_TX_BD_FLAGS_IP_CSUM_SHIFT 0
-#define ETH_TX_BD_FLAGS_L4_CSUM (0x1<<1)
-#define ETH_TX_BD_FLAGS_L4_CSUM_SHIFT 1
-#define ETH_TX_BD_FLAGS_VLAN_MODE (0x3<<2)
-#define ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT 2
-#define ETH_TX_BD_FLAGS_START_BD (0x1<<4)
-#define ETH_TX_BD_FLAGS_START_BD_SHIFT 4
-#define ETH_TX_BD_FLAGS_IS_UDP (0x1<<5)
-#define ETH_TX_BD_FLAGS_IS_UDP_SHIFT 5
-#define ETH_TX_BD_FLAGS_SW_LSO (0x1<<6)
-#define ETH_TX_BD_FLAGS_SW_LSO_SHIFT 6
-#define ETH_TX_BD_FLAGS_IPV6 (0x1<<7)
-#define ETH_TX_BD_FLAGS_IPV6_SHIFT 7
-};
-
-/*
- * The eth Tx Buffer Descriptor
- */
-struct eth_tx_start_bd {
-	__le32 addr_lo;
-	__le32 addr_hi;
-	__le16 nbd;
-	__le16 nbytes;
-	__le16 vlan_or_ethertype;
-	struct eth_tx_bd_flags bd_flags;
-	u8 general_data;
-#define ETH_TX_START_BD_HDR_NBDS (0xF<<0)
-#define ETH_TX_START_BD_HDR_NBDS_SHIFT 0
-#define ETH_TX_START_BD_FORCE_VLAN_MODE (0x1<<4)
-#define ETH_TX_START_BD_FORCE_VLAN_MODE_SHIFT 4
-#define ETH_TX_START_BD_RESREVED (0x1<<5)
-#define ETH_TX_START_BD_RESREVED_SHIFT 5
-#define ETH_TX_START_BD_ETH_ADDR_TYPE (0x3<<6)
-#define ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT 6
-};
-
-/*
- * Tx parsing BD structure for ETH E1/E1h
- */
-struct eth_tx_parse_bd_e1x {
-	u8 global_data;
-#define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W (0xF<<0)
-#define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W_SHIFT 0
-#define ETH_TX_PARSE_BD_E1X_RESERVED0 (0x1<<4)
-#define ETH_TX_PARSE_BD_E1X_RESERVED0_SHIFT 4
-#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN (0x1<<5)
-#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN_SHIFT 5
-#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN (0x1<<6)
-#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT 6
-#define ETH_TX_PARSE_BD_E1X_NS_FLG (0x1<<7)
-#define ETH_TX_PARSE_BD_E1X_NS_FLG_SHIFT 7
-	u8 tcp_flags;
-#define ETH_TX_PARSE_BD_E1X_FIN_FLG (0x1<<0)
-#define ETH_TX_PARSE_BD_E1X_FIN_FLG_SHIFT 0
-#define ETH_TX_PARSE_BD_E1X_SYN_FLG (0x1<<1)
-#define ETH_TX_PARSE_BD_E1X_SYN_FLG_SHIFT 1
-#define ETH_TX_PARSE_BD_E1X_RST_FLG (0x1<<2)
-#define ETH_TX_PARSE_BD_E1X_RST_FLG_SHIFT 2
-#define ETH_TX_PARSE_BD_E1X_PSH_FLG (0x1<<3)
-#define ETH_TX_PARSE_BD_E1X_PSH_FLG_SHIFT 3
-#define ETH_TX_PARSE_BD_E1X_ACK_FLG (0x1<<4)
-#define ETH_TX_PARSE_BD_E1X_ACK_FLG_SHIFT 4
-#define ETH_TX_PARSE_BD_E1X_URG_FLG (0x1<<5)
-#define ETH_TX_PARSE_BD_E1X_URG_FLG_SHIFT 5
-#define ETH_TX_PARSE_BD_E1X_ECE_FLG (0x1<<6)
-#define ETH_TX_PARSE_BD_E1X_ECE_FLG_SHIFT 6
-#define ETH_TX_PARSE_BD_E1X_CWR_FLG (0x1<<7)
-#define ETH_TX_PARSE_BD_E1X_CWR_FLG_SHIFT 7
-	u8 ip_hlen_w;
-	s8 reserved;
-	__le16 total_hlen_w;
-	__le16 tcp_pseudo_csum;
-	__le16 lso_mss;
-	__le16 ip_id;
-	__le32 tcp_send_seq;
-};
-
-/*
- * Tx parsing BD structure for ETH E2
- */
-struct eth_tx_parse_bd_e2 {
-	__le16 dst_mac_addr_lo;
-	__le16 dst_mac_addr_mid;
-	__le16 dst_mac_addr_hi;
-	__le16 src_mac_addr_lo;
-	__le16 src_mac_addr_mid;
-	__le16 src_mac_addr_hi;
-	__le32 parsing_data;
-#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W (0x1FFF<<0)
-#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT 0
-#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW (0xF<<13)
-#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT 13
-#define ETH_TX_PARSE_BD_E2_LSO_MSS (0x3FFF<<17)
-#define ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT 17
-#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR (0x1<<31)
-#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR_SHIFT 31
-};
-
-/*
- * The last BD in the BD memory will hold a pointer to the next BD memory
- */
-struct eth_tx_next_bd {
-	__le32 addr_lo;
-	__le32 addr_hi;
-	u8 reserved[8];
-};
-
-/*
- * union for 4 Bd types
- */
-union eth_tx_bd_types {
-	struct eth_tx_start_bd start_bd;
-	struct eth_tx_bd reg_bd;
-	struct eth_tx_parse_bd_e1x parse_bd_e1x;
-	struct eth_tx_parse_bd_e2 parse_bd_e2;
-	struct eth_tx_next_bd next_bd;
-};
-
-/*
- * array of 13 bds as appears in the eth xstorm context
- */
-struct eth_tx_bds_array {
-	union eth_tx_bd_types bds[13];
-};
-
-
-/*
- * VLAN mode on TX BDs
- */
-enum eth_tx_vlan_type {
-	X_ETH_NO_VLAN,
-	X_ETH_OUTBAND_VLAN,
-	X_ETH_INBAND_VLAN,
-	X_ETH_FW_ADDED_VLAN,
-	MAX_ETH_TX_VLAN_TYPE
-};
-
-
-/*
- * Ethernet VLAN filtering mode in E1x
- */
-enum eth_vlan_filter_mode {
-	ETH_VLAN_FILTER_ANY_VLAN,
-	ETH_VLAN_FILTER_SPECIFIC_VLAN,
-	ETH_VLAN_FILTER_CLASSIFY,
-	MAX_ETH_VLAN_FILTER_MODE
-};
-
-
-/*
- * MAC filtering configuration command header
- */
-struct mac_configuration_hdr {
-	u8 length;
-	u8 offset;
-	__le16 client_id;
-	__le32 echo;
-};
-
-/*
- * MAC address in list for ramrod
- */
-struct mac_configuration_entry {
-	__le16 lsb_mac_addr;
-	__le16 middle_mac_addr;
-	__le16 msb_mac_addr;
-	__le16 vlan_id;
-	u8 pf_id;
-	u8 flags;
-#define MAC_CONFIGURATION_ENTRY_ACTION_TYPE (0x1<<0)
-#define MAC_CONFIGURATION_ENTRY_ACTION_TYPE_SHIFT 0
-#define MAC_CONFIGURATION_ENTRY_RDMA_MAC (0x1<<1)
-#define MAC_CONFIGURATION_ENTRY_RDMA_MAC_SHIFT 1
-#define MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE (0x3<<2)
-#define MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE_SHIFT 2
-#define MAC_CONFIGURATION_ENTRY_OVERRIDE_VLAN_REMOVAL (0x1<<4)
-#define MAC_CONFIGURATION_ENTRY_OVERRIDE_VLAN_REMOVAL_SHIFT 4
-#define MAC_CONFIGURATION_ENTRY_BROADCAST (0x1<<5)
-#define MAC_CONFIGURATION_ENTRY_BROADCAST_SHIFT 5
-#define MAC_CONFIGURATION_ENTRY_RESERVED1 (0x3<<6)
-#define MAC_CONFIGURATION_ENTRY_RESERVED1_SHIFT 6
-	__le16 reserved0;
-	__le32 clients_bit_vector;
-};
-
-/*
- * MAC filtering configuration command
- */
-struct mac_configuration_cmd {
-	struct mac_configuration_hdr hdr;
-	struct mac_configuration_entry config_table[64];
-};
-
-
-/*
- * Set-MAC command type (in E1x)
- */
-enum set_mac_action_type {
-	T_ETH_MAC_COMMAND_INVALIDATE,
-	T_ETH_MAC_COMMAND_SET,
-	MAX_SET_MAC_ACTION_TYPE
-};
-
-
-/*
- * tpa update ramrod data
- */
-struct tpa_update_ramrod_data {
-	u8 update_ipv4;
-	u8 update_ipv6;
-	u8 client_id;
-	u8 max_tpa_queues;
-	u8 max_sges_for_packet;
-	u8 complete_on_both_clients;
-	__le16 reserved1;
-	__le16 sge_buff_size;
-	__le16 max_agg_size;
-	__le32 sge_page_base_lo;
-	__le32 sge_page_base_hi;
-	__le16 sge_pause_thr_low;
-	__le16 sge_pause_thr_high;
-};
-
-
-/*
- * approximate-match multicast filtering for E1H per function in Tstorm
- */
-struct tstorm_eth_approximate_match_multicast_filtering {
-	u32 mcast_add_hash_bit_array[8];
-};
-
-
-/*
- * Common configuration parameters per function in Tstorm
- */
-struct tstorm_eth_function_common_config {
-	__le16 config_flags;
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY (0x1<<0)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY_SHIFT 0
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY (0x1<<1)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY_SHIFT 1
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY (0x1<<2)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY_SHIFT 2
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY (0x1<<3)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY_SHIFT 3
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE (0x7<<4)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT 4
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE (0x1<<7)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE_SHIFT 7
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0xFF<<8)
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 8
-	u8 rss_result_mask;
-	u8 reserved1;
-	__le16 vlan_id[2];
-};
-
-
-/*
- * MAC filtering configuration parameters per port in Tstorm
- */
-struct tstorm_eth_mac_filter_config {
-	__le32 ucast_drop_all;
-	__le32 ucast_accept_all;
-	__le32 mcast_drop_all;
-	__le32 mcast_accept_all;
-	__le32 bcast_accept_all;
-	__le32 vlan_filter[2];
-	__le32 unmatched_unicast;
-};
-
-
-/*
- * tx only queue init ramrod data
- */
-struct tx_queue_init_ramrod_data {
-	struct client_init_general_data general;
-	struct client_init_tx_data tx;
-};
-
-
-/*
- * Three RX producers for ETH
- */
-struct ustorm_eth_rx_producers {
-#if defined(__BIG_ENDIAN)
-	u16 bd_prod;
-	u16 cqe_prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 cqe_prod;
-	u16 bd_prod;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 reserved;
-	u16 sge_prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 sge_prod;
-	u16 reserved;
-#endif
-};
-
-
-/*
- * cfc delete event data
- */
-struct cfc_del_event_data {
-	u32 cid;
-	u32 reserved0;
-	u32 reserved1;
-};
-
-
-/*
- * per-port SAFC demo variables
- */
-struct cmng_flags_per_port {
-	u32 cmng_enables;
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_VN (0x1<<0)
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_VN_SHIFT 0
-#define CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN (0x1<<1)
-#define CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN_SHIFT 1
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS (0x1<<2)
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_SHIFT 2
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE (0x1<<3)
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE_SHIFT 3
-#define __CMNG_FLAGS_PER_PORT_RESERVED0 (0xFFFFFFF<<4)
-#define __CMNG_FLAGS_PER_PORT_RESERVED0_SHIFT 4
-	u32 __reserved1;
-};
-
-
-/*
- * per-port rate shaping variables
- */
-struct rate_shaping_vars_per_port {
-	u32 rs_periodic_timeout;
-	u32 rs_threshold;
-};
-
-/*
- * per-port fairness variables
- */
-struct fairness_vars_per_port {
-	u32 upper_bound;
-	u32 fair_threshold;
-	u32 fairness_timeout;
-	u32 reserved0;
-};
-
-/*
- * per-port SAFC variables
- */
-struct safc_struct_per_port {
-#if defined(__BIG_ENDIAN)
-	u16 __reserved1;
-	u8 __reserved0;
-	u8 safc_timeout_usec;
-#elif defined(__LITTLE_ENDIAN)
-	u8 safc_timeout_usec;
-	u8 __reserved0;
-	u16 __reserved1;
-#endif
-	u8 cos_to_traffic_types[MAX_COS_NUMBER];
-	u16 cos_to_pause_mask[NUM_OF_SAFC_BITS];
-};
-
-/*
- * Per-port congestion management variables
- */
-struct cmng_struct_per_port {
-	struct rate_shaping_vars_per_port rs_vars;
-	struct fairness_vars_per_port fair_vars;
-	struct safc_struct_per_port safc_vars;
-	struct cmng_flags_per_port flags;
-};
-
-
-/*
- * Protocol-common command ID for slow path elements
- */
-enum common_spqe_cmd_id {
-	RAMROD_CMD_ID_COMMON_UNUSED,
-	RAMROD_CMD_ID_COMMON_FUNCTION_START,
-	RAMROD_CMD_ID_COMMON_FUNCTION_STOP,
-	RAMROD_CMD_ID_COMMON_CFC_DEL,
-	RAMROD_CMD_ID_COMMON_CFC_DEL_WB,
-	RAMROD_CMD_ID_COMMON_STAT_QUERY,
-	RAMROD_CMD_ID_COMMON_STOP_TRAFFIC,
-	RAMROD_CMD_ID_COMMON_START_TRAFFIC,
-	RAMROD_CMD_ID_COMMON_RESERVED1,
-	RAMROD_CMD_ID_COMMON_RESERVED2,
-	MAX_COMMON_SPQE_CMD_ID
-};
-
-
-/*
- * Per-protocol connection types
- */
-enum connection_type {
-	ETH_CONNECTION_TYPE,
-	TOE_CONNECTION_TYPE,
-	RDMA_CONNECTION_TYPE,
-	ISCSI_CONNECTION_TYPE,
-	FCOE_CONNECTION_TYPE,
-	RESERVED_CONNECTION_TYPE_0,
-	RESERVED_CONNECTION_TYPE_1,
-	RESERVED_CONNECTION_TYPE_2,
-	NONE_CONNECTION_TYPE,
-	MAX_CONNECTION_TYPE
-};
-
-
-/*
- * Cos modes
- */
-enum cos_mode {
-	OVERRIDE_COS,
-	STATIC_COS,
-	FW_WRR,
-	MAX_COS_MODE
-};
-
-
-/*
- * Dynamic HC counters set by the driver
- */
-struct hc_dynamic_drv_counter {
-	u32 val[HC_SB_MAX_DYNAMIC_INDICES];
-};
-
-/*
- * zone A per-queue data
- */
-struct cstorm_queue_zone_data {
-	struct hc_dynamic_drv_counter hc_dyn_drv_cnt;
-	struct regpair reserved[2];
-};
-
-
-/*
- * Vf-PF channel data in cstorm ram (non-triggered zone)
- */
-struct vf_pf_channel_zone_data {
-	u32 msg_addr_lo;
-	u32 msg_addr_hi;
-};
-
-/*
- * zone for VF non-triggered data
- */
-struct non_trigger_vf_zone {
-	struct vf_pf_channel_zone_data vf_pf_channel;
-};
-
-/*
- * Vf-PF channel trigger zone in cstorm ram
- */
-struct vf_pf_channel_zone_trigger {
-	u8 addr_valid;
-};
-
-/*
- * zone that triggers the in-bound interrupt
- */
-struct trigger_vf_zone {
-#if defined(__BIG_ENDIAN)
-	u16 reserved1;
-	u8 reserved0;
-	struct vf_pf_channel_zone_trigger vf_pf_channel;
-#elif defined(__LITTLE_ENDIAN)
-	struct vf_pf_channel_zone_trigger vf_pf_channel;
-	u8 reserved0;
-	u16 reserved1;
-#endif
-	u32 reserved2;
-};
-
-/*
- * zone B per-VF data
- */
-struct cstorm_vf_zone_data {
-	struct non_trigger_vf_zone non_trigger;
-	struct trigger_vf_zone trigger;
-};
-
-
-/*
- * Dynamic host coalescing init parameters, per state machine
- */
-struct dynamic_hc_sm_config {
-	u32 threshold[3];
-	u8 shift_per_protocol[HC_SB_MAX_DYNAMIC_INDICES];
-	u8 hc_timeout0[HC_SB_MAX_DYNAMIC_INDICES];
-	u8 hc_timeout1[HC_SB_MAX_DYNAMIC_INDICES];
-	u8 hc_timeout2[HC_SB_MAX_DYNAMIC_INDICES];
-	u8 hc_timeout3[HC_SB_MAX_DYNAMIC_INDICES];
-};
-
-/*
- * Dynamic host coalescing init parameters
- */
-struct dynamic_hc_config {
-	struct dynamic_hc_sm_config sm_config[HC_SB_MAX_SM];
-};
-
-
-struct e2_integ_data {
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define E2_INTEG_DATA_TESTING_EN (0x1<<0)
-#define E2_INTEG_DATA_TESTING_EN_SHIFT 0
-#define E2_INTEG_DATA_LB_TX (0x1<<1)
-#define E2_INTEG_DATA_LB_TX_SHIFT 1
-#define E2_INTEG_DATA_COS_TX (0x1<<2)
-#define E2_INTEG_DATA_COS_TX_SHIFT 2
-#define E2_INTEG_DATA_OPPORTUNISTICQM (0x1<<3)
-#define E2_INTEG_DATA_OPPORTUNISTICQM_SHIFT 3
-#define E2_INTEG_DATA_DPMTESTRELEASEDQ (0x1<<4)
-#define E2_INTEG_DATA_DPMTESTRELEASEDQ_SHIFT 4
-#define E2_INTEG_DATA_RESERVED (0x7<<5)
-#define E2_INTEG_DATA_RESERVED_SHIFT 5
-	u8 cos;
-	u8 voq;
-	u8 pbf_queue;
-#elif defined(__LITTLE_ENDIAN)
-	u8 pbf_queue;
-	u8 voq;
-	u8 cos;
-	u8 flags;
-#define E2_INTEG_DATA_TESTING_EN (0x1<<0)
-#define E2_INTEG_DATA_TESTING_EN_SHIFT 0
-#define E2_INTEG_DATA_LB_TX (0x1<<1)
-#define E2_INTEG_DATA_LB_TX_SHIFT 1
-#define E2_INTEG_DATA_COS_TX (0x1<<2)
-#define E2_INTEG_DATA_COS_TX_SHIFT 2
-#define E2_INTEG_DATA_OPPORTUNISTICQM (0x1<<3)
-#define E2_INTEG_DATA_OPPORTUNISTICQM_SHIFT 3
-#define E2_INTEG_DATA_DPMTESTRELEASEDQ (0x1<<4)
-#define E2_INTEG_DATA_DPMTESTRELEASEDQ_SHIFT 4
-#define E2_INTEG_DATA_RESERVED (0x7<<5)
-#define E2_INTEG_DATA_RESERVED_SHIFT 5
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 reserved3;
-	u8 reserved2;
-	u8 ramEn;
-#elif defined(__LITTLE_ENDIAN)
-	u8 ramEn;
-	u8 reserved2;
-	u16 reserved3;
-#endif
-};
-
-
-/*
- * set mac event data
- */
-struct eth_event_data {
-	u32 echo;
-	u32 reserved0;
-	u32 reserved1;
-};
-
-
-/*
- * pf-vf event data
- */
-struct vf_pf_event_data {
-	u8 vf_id;
-	u8 reserved0;
-	u16 reserved1;
-	u32 msg_addr_lo;
-	u32 msg_addr_hi;
-};
-
-/*
- * VF FLR event data
- */
-struct vf_flr_event_data {
-	u8 vf_id;
-	u8 reserved0;
-	u16 reserved1;
-	u32 reserved2;
-	u32 reserved3;
-};
-
-/*
- * malicious VF event data
- */
-struct malicious_vf_event_data {
-	u8 vf_id;
-	u8 reserved0;
-	u16 reserved1;
-	u32 reserved2;
-	u32 reserved3;
-};
-
-/*
- * union for all event ring message types
- */
-union event_data {
-	struct vf_pf_event_data vf_pf_event;
-	struct eth_event_data eth_event;
-	struct cfc_del_event_data cfc_del_event;
-	struct vf_flr_event_data vf_flr_event;
-	struct malicious_vf_event_data malicious_vf_event;
-};
-
-
-/*
- * per PF event ring data
- */
-struct event_ring_data {
-	struct regpair base_addr;
-#if defined(__BIG_ENDIAN)
-	u8 index_id;
-	u8 sb_id;
-	u16 producer;
-#elif defined(__LITTLE_ENDIAN)
-	u16 producer;
-	u8 sb_id;
-	u8 index_id;
-#endif
-	u32 reserved0;
-};
-
-
-/*
- * event ring message element (each element is 128 bits)
- */
-struct event_ring_msg {
-	u8 opcode;
-	u8 error;
-	u16 reserved1;
-	union event_data data;
-};
-
-/*
- * event ring next page element (128 bits)
- */
-struct event_ring_next {
-	struct regpair addr;
-	u32 reserved[2];
-};
-
-/*
- * union for event ring element types (each element is 128 bits)
- */
-union event_ring_elem {
-	struct event_ring_msg message;
-	struct event_ring_next next_page;
-};
-
-
-/*
- * Common event ring opcodes
- */
-enum event_ring_opcode {
-	EVENT_RING_OPCODE_VF_PF_CHANNEL,
-	EVENT_RING_OPCODE_FUNCTION_START,
-	EVENT_RING_OPCODE_FUNCTION_STOP,
-	EVENT_RING_OPCODE_CFC_DEL,
-	EVENT_RING_OPCODE_CFC_DEL_WB,
-	EVENT_RING_OPCODE_STAT_QUERY,
-	EVENT_RING_OPCODE_STOP_TRAFFIC,
-	EVENT_RING_OPCODE_START_TRAFFIC,
-	EVENT_RING_OPCODE_VF_FLR,
-	EVENT_RING_OPCODE_MALICIOUS_VF,
-	EVENT_RING_OPCODE_FORWARD_SETUP,
-	EVENT_RING_OPCODE_RSS_UPDATE_RULES,
-	EVENT_RING_OPCODE_RESERVED1,
-	EVENT_RING_OPCODE_RESERVED2,
-	EVENT_RING_OPCODE_SET_MAC,
-	EVENT_RING_OPCODE_CLASSIFICATION_RULES,
-	EVENT_RING_OPCODE_FILTERS_RULES,
-	EVENT_RING_OPCODE_MULTICAST_RULES,
-	MAX_EVENT_RING_OPCODE
-};
-
-
-/*
- * Modes for fairness algorithm
- */
-enum fairness_mode {
-	FAIRNESS_COS_WRR_MODE,
-	FAIRNESS_COS_ETS_MODE,
-	MAX_FAIRNESS_MODE
-};
-
-
-/*
- * per-vnic fairness variables
- */
-struct fairness_vars_per_vn {
-	u32 cos_credit_delta[MAX_COS_NUMBER];
-	u32 vn_credit_delta;
-	u32 __reserved0;
-};
-
-
-/*
- * Priority and cos
- */
-struct priority_cos {
-	u8 priority;
-	u8 cos;
-	__le16 reserved1;
-};
-
-/*
- * The data for flow control configuration
- */
-struct flow_control_configuration {
-	struct priority_cos traffic_type_to_priority_cos[MAX_TRAFFIC_TYPES];
-	u8 dcb_enabled;
-	u8 dcb_version;
-	u8 dont_add_pri_0_en;
-	u8 reserved1;
-	__le32 reserved2;
-};
-
-
-/*
- *
- */
-struct function_start_data {
-	__le16 function_mode;
-	__le16 sd_vlan_tag;
-	u16 reserved;
-	u8 path_id;
-	u8 network_cos_mode;
-};
-
-
-/*
- * FW version stored in the Xstorm RAM
- */
-struct fw_version {
-#if defined(__BIG_ENDIAN)
-	u8 engineering;
-	u8 revision;
-	u8 minor;
-	u8 major;
-#elif defined(__LITTLE_ENDIAN)
-	u8 major;
-	u8 minor;
-	u8 revision;
-	u8 engineering;
-#endif
-	u32 flags;
-#define FW_VERSION_OPTIMIZED (0x1<<0)
-#define FW_VERSION_OPTIMIZED_SHIFT 0
-#define FW_VERSION_BIG_ENDIEN (0x1<<1)
-#define FW_VERSION_BIG_ENDIEN_SHIFT 1
-#define FW_VERSION_CHIP_VERSION (0x3<<2)
-#define FW_VERSION_CHIP_VERSION_SHIFT 2
-#define __FW_VERSION_RESERVED (0xFFFFFFF<<4)
-#define __FW_VERSION_RESERVED_SHIFT 4
-};
-
-
-/*
- * Dynamic Host-Coalescing - Driver(host) counters
- */
-struct hc_dynamic_sb_drv_counters {
-	u32 dynamic_hc_drv_counter[HC_SB_MAX_DYNAMIC_INDICES];
-};
-
-
-/*
- * 2 bytes. configuration/state parameters for a single protocol index
- */
-struct hc_index_data {
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define HC_INDEX_DATA_SM_ID (0x1<<0)
-#define HC_INDEX_DATA_SM_ID_SHIFT 0
-#define HC_INDEX_DATA_HC_ENABLED (0x1<<1)
-#define HC_INDEX_DATA_HC_ENABLED_SHIFT 1
-#define HC_INDEX_DATA_DYNAMIC_HC_ENABLED (0x1<<2)
-#define HC_INDEX_DATA_DYNAMIC_HC_ENABLED_SHIFT 2
-#define HC_INDEX_DATA_RESERVE (0x1F<<3)
-#define HC_INDEX_DATA_RESERVE_SHIFT 3
-	u8 timeout;
-#elif defined(__LITTLE_ENDIAN)
-	u8 timeout;
-	u8 flags;
-#define HC_INDEX_DATA_SM_ID (0x1<<0)
-#define HC_INDEX_DATA_SM_ID_SHIFT 0
-#define HC_INDEX_DATA_HC_ENABLED (0x1<<1)
-#define HC_INDEX_DATA_HC_ENABLED_SHIFT 1
-#define HC_INDEX_DATA_DYNAMIC_HC_ENABLED (0x1<<2)
-#define HC_INDEX_DATA_DYNAMIC_HC_ENABLED_SHIFT 2
-#define HC_INDEX_DATA_RESERVE (0x1F<<3)
-#define HC_INDEX_DATA_RESERVE_SHIFT 3
-#endif
-};
-
-
-/*
- * HC state-machine
- */
-struct hc_status_block_sm {
-#if defined(__BIG_ENDIAN)
-	u8 igu_seg_id;
-	u8 igu_sb_id;
-	u8 timer_value;
-	u8 __flags;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __flags;
-	u8 timer_value;
-	u8 igu_sb_id;
-	u8 igu_seg_id;
-#endif
-	u32 time_to_expire;
-};
-
-/*
- * hold PCI identification variables- used in various places in firmware
- */
-struct pci_entity {
-#if defined(__BIG_ENDIAN)
-	u8 vf_valid;
-	u8 vf_id;
-	u8 vnic_id;
-	u8 pf_id;
-#elif defined(__LITTLE_ENDIAN)
-	u8 pf_id;
-	u8 vnic_id;
-	u8 vf_id;
-	u8 vf_valid;
-#endif
-};
-
-/*
- * The fast-path status block meta-data, common to all chips
- */
-struct hc_sb_data {
-	struct regpair host_sb_addr;
-	struct hc_status_block_sm state_machine[HC_SB_MAX_SM];
-	struct pci_entity p_func;
-#if defined(__BIG_ENDIAN)
-	u8 rsrv0;
-	u8 state;
-	u8 dhc_qzone_id;
-	u8 same_igu_sb_1b;
-#elif defined(__LITTLE_ENDIAN)
-	u8 same_igu_sb_1b;
-	u8 dhc_qzone_id;
-	u8 state;
-	u8 rsrv0;
-#endif
-	struct regpair rsrv1[2];
-};
-
-
-/*
- * Segment types for host coaslescing
- */
-enum hc_segment {
-	HC_REGULAR_SEGMENT,
-	HC_DEFAULT_SEGMENT,
-	MAX_HC_SEGMENT
-};
-
-
-/*
- * The fast-path status block meta-data
- */
-struct hc_sp_status_block_data {
-	struct regpair host_sb_addr;
-#if defined(__BIG_ENDIAN)
-	u8 rsrv1;
-	u8 state;
-	u8 igu_seg_id;
-	u8 igu_sb_id;
-#elif defined(__LITTLE_ENDIAN)
-	u8 igu_sb_id;
-	u8 igu_seg_id;
-	u8 state;
-	u8 rsrv1;
-#endif
-	struct pci_entity p_func;
-};
-
-
-/*
- * The fast-path status block meta-data
- */
-struct hc_status_block_data_e1x {
-	struct hc_index_data index_data[HC_SB_MAX_INDICES_E1X];
-	struct hc_sb_data common;
-};
-
-
-/*
- * The fast-path status block meta-data
- */
-struct hc_status_block_data_e2 {
-	struct hc_index_data index_data[HC_SB_MAX_INDICES_E2];
-	struct hc_sb_data common;
-};
-
-
-/*
- * IGU block operartion modes (in Everest2)
- */
-enum igu_mode {
-	HC_IGU_BC_MODE,
-	HC_IGU_NBC_MODE,
-	MAX_IGU_MODE
-};
-
-
-/*
- * IP versions
- */
-enum ip_ver {
-	IP_V4,
-	IP_V6,
-	MAX_IP_VER
-};
-
-
-/*
- * Multi-function modes
- */
-enum mf_mode {
-	SINGLE_FUNCTION,
-	MULTI_FUNCTION_SD,
-	MULTI_FUNCTION_SI,
-	MULTI_FUNCTION_RESERVED,
-	MAX_MF_MODE
-};
-
-/*
- * Protocol-common statistics collected by the Tstorm (per pf)
- */
-struct tstorm_per_pf_stats {
-	struct regpair rcv_error_bytes;
-};
-
-/*
- *
- */
-struct per_pf_stats {
-	struct tstorm_per_pf_stats tstorm_pf_statistics;
-};
-
-
-/*
- * Protocol-common statistics collected by the Tstorm (per port)
- */
-struct tstorm_per_port_stats {
-	__le32 mac_discard;
-	__le32 mac_filter_discard;
-	__le32 brb_truncate_discard;
-	__le32 mf_tag_discard;
-	__le32 packet_drop;
-	__le32 reserved;
-};
-
-/*
- *
- */
-struct per_port_stats {
-	struct tstorm_per_port_stats tstorm_port_statistics;
-};
-
-
-/*
- * Protocol-common statistics collected by the Tstorm (per client)
- */
-struct tstorm_per_queue_stats {
-	struct regpair rcv_ucast_bytes;
-	__le32 rcv_ucast_pkts;
-	__le32 checksum_discard;
-	struct regpair rcv_bcast_bytes;
-	__le32 rcv_bcast_pkts;
-	__le32 pkts_too_big_discard;
-	struct regpair rcv_mcast_bytes;
-	__le32 rcv_mcast_pkts;
-	__le32 ttl0_discard;
-	__le16 no_buff_discard;
-	__le16 reserved0;
-	__le32 reserved1;
-};
-
-/*
- * Protocol-common statistics collected by the Ustorm (per client)
- */
-struct ustorm_per_queue_stats {
-	struct regpair ucast_no_buff_bytes;
-	struct regpair mcast_no_buff_bytes;
-	struct regpair bcast_no_buff_bytes;
-	__le32 ucast_no_buff_pkts;
-	__le32 mcast_no_buff_pkts;
-	__le32 bcast_no_buff_pkts;
-	__le32 coalesced_pkts;
-	struct regpair coalesced_bytes;
-	__le32 coalesced_events;
-	__le32 coalesced_aborts;
-};
-
-/*
- * Protocol-common statistics collected by the Xstorm (per client)
- */
-struct xstorm_per_queue_stats {
-	struct regpair ucast_bytes_sent;
-	struct regpair mcast_bytes_sent;
-	struct regpair bcast_bytes_sent;
-	__le32 ucast_pkts_sent;
-	__le32 mcast_pkts_sent;
-	__le32 bcast_pkts_sent;
-	__le32 error_drop_pkts;
-};
-
-/*
- *
- */
-struct per_queue_stats {
-	struct tstorm_per_queue_stats tstorm_queue_statistics;
-	struct ustorm_per_queue_stats ustorm_queue_statistics;
-	struct xstorm_per_queue_stats xstorm_queue_statistics;
-};
-
-
-/*
- * FW version stored in first line of pram
- */
-struct pram_fw_version {
-	u8 major;
-	u8 minor;
-	u8 revision;
-	u8 engineering;
-	u8 flags;
-#define PRAM_FW_VERSION_OPTIMIZED (0x1<<0)
-#define PRAM_FW_VERSION_OPTIMIZED_SHIFT 0
-#define PRAM_FW_VERSION_STORM_ID (0x3<<1)
-#define PRAM_FW_VERSION_STORM_ID_SHIFT 1
-#define PRAM_FW_VERSION_BIG_ENDIEN (0x1<<3)
-#define PRAM_FW_VERSION_BIG_ENDIEN_SHIFT 3
-#define PRAM_FW_VERSION_CHIP_VERSION (0x3<<4)
-#define PRAM_FW_VERSION_CHIP_VERSION_SHIFT 4
-#define __PRAM_FW_VERSION_RESERVED0 (0x3<<6)
-#define __PRAM_FW_VERSION_RESERVED0_SHIFT 6
-};
-
-
-/*
- * Ethernet slow path element
- */
-union protocol_common_specific_data {
-	u8 protocol_data[8];
-	struct regpair phy_address;
-	struct regpair mac_config_addr;
-};
-
-/*
- * The send queue element
- */
-struct protocol_common_spe {
-	struct spe_hdr hdr;
-	union protocol_common_specific_data data;
-};
-
-
-/*
- * a single rate shaping counter. can be used as protocol or vnic counter
- */
-struct rate_shaping_counter {
-	u32 quota;
-#if defined(__BIG_ENDIAN)
-	u16 __reserved0;
-	u16 rate;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rate;
-	u16 __reserved0;
-#endif
-};
-
-
-/*
- * per-vnic rate shaping variables
- */
-struct rate_shaping_vars_per_vn {
-	struct rate_shaping_counter vn_counter;
-};
-
-
-/*
- * The send queue element
- */
-struct slow_path_element {
-	struct spe_hdr hdr;
-	struct regpair protocol_data;
-};
-
-
-/*
- * Protocol-common statistics counter
- */
-struct stats_counter {
-	__le16 xstats_counter;
-	__le16 reserved0;
-	__le32 reserved1;
-	__le16 tstats_counter;
-	__le16 reserved2;
-	__le32 reserved3;
-	__le16 ustats_counter;
-	__le16 reserved4;
-	__le32 reserved5;
-	__le16 cstats_counter;
-	__le16 reserved6;
-	__le32 reserved7;
-};
-
-
-/*
- *
- */
-struct stats_query_entry {
-	u8 kind;
-	u8 index;
-	__le16 funcID;
-	__le32 reserved;
-	struct regpair address;
-};
-
-/*
- * statistic command
- */
-struct stats_query_cmd_group {
-	struct stats_query_entry query[STATS_QUERY_CMD_COUNT];
-};
-
-
-/*
- * statistic command header
- */
-struct stats_query_header {
-	u8 cmd_num;
-	u8 reserved0;
-	__le16 drv_stats_counter;
-	__le32 reserved1;
-	struct regpair stats_counters_addrs;
-};
-
-
-/*
- * Types of statistcis query entry
- */
-enum stats_query_type {
-	STATS_TYPE_QUEUE,
-	STATS_TYPE_PORT,
-	STATS_TYPE_PF,
-	STATS_TYPE_TOE,
-	STATS_TYPE_FCOE,
-	MAX_STATS_QUERY_TYPE
-};
-
-
-/*
- * Indicate of the function status block state
- */
-enum status_block_state {
-	SB_DISABLED,
-	SB_ENABLED,
-	SB_CLEANED,
-	MAX_STATUS_BLOCK_STATE
-};
-
-
-/*
- * Storm IDs (including attentions for IGU related enums)
- */
-enum storm_id {
-	USTORM_ID,
-	CSTORM_ID,
-	XSTORM_ID,
-	TSTORM_ID,
-	ATTENTION_ID,
-	MAX_STORM_ID
-};
-
-
-/*
- * Taffic types used in ETS and flow control algorithms
- */
-enum traffic_type {
-	LLFC_TRAFFIC_TYPE_NW,
-	LLFC_TRAFFIC_TYPE_FCOE,
-	LLFC_TRAFFIC_TYPE_ISCSI,
-	MAX_TRAFFIC_TYPE
-};
-
-
-/*
- * zone A per-queue data
- */
-struct tstorm_queue_zone_data {
-	struct regpair reserved[4];
-};
-
-
-/*
- * zone B per-VF data
- */
-struct tstorm_vf_zone_data {
-	struct regpair reserved;
-};
-
-
-/*
- * zone A per-queue data
- */
-struct ustorm_queue_zone_data {
-	struct ustorm_eth_rx_producers eth_rx_producers;
-	struct regpair reserved[3];
-};
-
-
-/*
- * zone B per-VF data
- */
-struct ustorm_vf_zone_data {
-	struct regpair reserved;
-};
-
-
-/*
- * data per VF-PF channel
- */
-struct vf_pf_channel_data {
-#if defined(__BIG_ENDIAN)
-	u16 reserved0;
-	u8 valid;
-	u8 state;
-#elif defined(__LITTLE_ENDIAN)
-	u8 state;
-	u8 valid;
-	u16 reserved0;
-#endif
-	u32 reserved1;
-};
-
-
-/*
- * State of VF-PF channel
- */
-enum vf_pf_channel_state {
-	VF_PF_CHANNEL_STATE_READY,
-	VF_PF_CHANNEL_STATE_WAITING_FOR_ACK,
-	MAX_VF_PF_CHANNEL_STATE
-};
-
-
-/*
- * zone A per-queue data
- */
-struct xstorm_queue_zone_data {
-	struct regpair reserved[4];
-};
-
-
-/*
- * zone B per-VF data
- */
-struct xstorm_vf_zone_data {
-	struct regpair reserved;
-};
-
-#endif /* BNX2X_HSI_H */
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_init.h linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_init.h
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_init.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_init.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,567 +0,0 @@
-/* bnx2x_init.h: Broadcom Everest network driver.
- *               Structures and macroes needed during the initialization.
- *
- * Copyright (c) 2007-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
- * the Free Software Foundation.
- *
- * Maintained by: Eilon Greenstein <eilong@broadcom.com>
- * Written by: Eliezer Tamir
- * Modified by: Vladislav Zolotarov <vladz@broadcom.com>
- */
-
-#ifndef BNX2X_INIT_H
-#define BNX2X_INIT_H
-
-/* Init operation types and structures */
-enum {
-	OP_RD = 0x1,	/* read a single register */
-	OP_WR,		/* write a single register */
-	OP_SW,		/* copy a string to the device */
-	OP_ZR,		/* clear memory */
-	OP_ZP,		/* unzip then copy with DMAE */
-	OP_WR_64,	/* write 64 bit pattern */
-	OP_WB,		/* copy a string using DMAE */
-	OP_WB_ZR,	/* Clear a string using DMAE or indirect-wr */
-	/* Skip the following ops if all of the init modes don't match */
-	OP_IF_MODE_OR,
-	/* Skip the following ops if any of the init modes don't match */
-	OP_IF_MODE_AND,
-	OP_MAX
-};
-
-enum {
-	STAGE_START,
-	STAGE_END,
-};
-
-/* Returns the index of start or end of a specific block stage in ops array*/
-#define BLOCK_OPS_IDX(block, stage, end) \
-	(2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end))
-
-
-/* structs for the various opcodes */
-struct raw_op {
-	u32 op:8;
-	u32 offset:24;
-	u32 raw_data;
-};
-
-struct op_read {
-	u32 op:8;
-	u32 offset:24;
-	u32 val;
-};
-
-struct op_write {
-	u32 op:8;
-	u32 offset:24;
-	u32 val;
-};
-
-struct op_arr_write {
-	u32 op:8;
-	u32 offset:24;
-#ifdef __BIG_ENDIAN
-	u16 data_len;
-	u16 data_off;
-#else /* __LITTLE_ENDIAN */
-	u16 data_off;
-	u16 data_len;
-#endif
-};
-
-struct op_zero {
-	u32 op:8;
-	u32 offset:24;
-	u32 len;
-};
-
-struct op_if_mode {
-	u32 op:8;
-	u32 cmd_offset:24;
-	u32 mode_bit_map;
-};
-
-
-union init_op {
-	struct op_read		read;
-	struct op_write		write;
-	struct op_arr_write	arr_wr;
-	struct op_zero		zero;
-	struct raw_op		raw;
-	struct op_if_mode	if_mode;
-};
-
-
-/* Init Phases */
-enum {
-	PHASE_COMMON,
-	PHASE_PORT0,
-	PHASE_PORT1,
-	PHASE_PF0,
-	PHASE_PF1,
-	PHASE_PF2,
-	PHASE_PF3,
-	PHASE_PF4,
-	PHASE_PF5,
-	PHASE_PF6,
-	PHASE_PF7,
-	NUM_OF_INIT_PHASES
-};
-
-/* Init Modes */
-enum {
-	MODE_ASIC                      = 0x00000001,
-	MODE_FPGA                      = 0x00000002,
-	MODE_EMUL                      = 0x00000004,
-	MODE_E2                        = 0x00000008,
-	MODE_E3                        = 0x00000010,
-	MODE_PORT2                     = 0x00000020,
-	MODE_PORT4                     = 0x00000040,
-	MODE_SF                        = 0x00000080,
-	MODE_MF                        = 0x00000100,
-	MODE_MF_SD                     = 0x00000200,
-	MODE_MF_SI                     = 0x00000400,
-	MODE_MF_NIV                    = 0x00000800,
-	MODE_E3_A0                     = 0x00001000,
-	MODE_E3_B0                     = 0x00002000,
-	MODE_COS3                      = 0x00004000,
-	MODE_COS6                      = 0x00008000,
-	MODE_LITTLE_ENDIAN             = 0x00010000,
-	MODE_BIG_ENDIAN                = 0x00020000,
-};
-
-/* Init Blocks */
-enum {
-	BLOCK_ATC,
-	BLOCK_BRB1,
-	BLOCK_CCM,
-	BLOCK_CDU,
-	BLOCK_CFC,
-	BLOCK_CSDM,
-	BLOCK_CSEM,
-	BLOCK_DBG,
-	BLOCK_DMAE,
-	BLOCK_DORQ,
-	BLOCK_HC,
-	BLOCK_IGU,
-	BLOCK_MISC,
-	BLOCK_NIG,
-	BLOCK_PBF,
-	BLOCK_PGLUE_B,
-	BLOCK_PRS,
-	BLOCK_PXP2,
-	BLOCK_PXP,
-	BLOCK_QM,
-	BLOCK_SRC,
-	BLOCK_TCM,
-	BLOCK_TM,
-	BLOCK_TSDM,
-	BLOCK_TSEM,
-	BLOCK_UCM,
-	BLOCK_UPB,
-	BLOCK_USDM,
-	BLOCK_USEM,
-	BLOCK_XCM,
-	BLOCK_XPB,
-	BLOCK_XSDM,
-	BLOCK_XSEM,
-	BLOCK_MISC_AEU,
-	NUM_OF_INIT_BLOCKS
-};
-
-/* QM queue numbers */
-#define BNX2X_ETH_Q		0
-#define BNX2X_TOE_Q		3
-#define BNX2X_TOE_ACK_Q		6
-#define BNX2X_ISCSI_Q		9
-#define BNX2X_ISCSI_ACK_Q	11
-#define BNX2X_FCOE_Q		10
-
-/* Vnics per mode */
-#define BNX2X_PORT2_MODE_NUM_VNICS 4
-#define BNX2X_PORT4_MODE_NUM_VNICS 2
-
-/* COS offset for port1 in E3 B0 4port mode */
-#define BNX2X_E3B0_PORT1_COS_OFFSET 3
-
-/* QM Register addresses */
-#define BNX2X_Q_VOQ_REG_ADDR(pf_q_num)\
-	(QM_REG_QVOQIDX_0 + 4 * (pf_q_num))
-#define BNX2X_VOQ_Q_REG_ADDR(cos, pf_q_num)\
-	(QM_REG_VOQQMASK_0_LSB + 4 * ((cos) * 2 + ((pf_q_num) >> 5)))
-#define BNX2X_Q_CMDQ_REG_ADDR(pf_q_num)\
-	(QM_REG_BYTECRDCMDQ_0 + 4 * ((pf_q_num) >> 4))
-
-/* extracts the QM queue number for the specified port and vnic */
-#define BNX2X_PF_Q_NUM(q_num, port, vnic)\
-	((((port) << 1) | (vnic)) * 16 + (q_num))
-
-
-/* Maps the specified queue to the specified COS */
-static inline void bnx2x_map_q_cos(struct bnx2x *bp, u32 q_num, u32 new_cos)
-{
-	/* find current COS mapping */
-	u32 curr_cos = REG_RD(bp, QM_REG_QVOQIDX_0 + q_num * 4);
-
-	/* check if queue->COS mapping has changed */
-	if (curr_cos != new_cos) {
-		u32 num_vnics = BNX2X_PORT2_MODE_NUM_VNICS;
-		u32 reg_addr, reg_bit_map, vnic;
-
-		/* update parameters for 4port mode */
-		if (INIT_MODE_FLAGS(bp) & MODE_PORT4) {
-			num_vnics = BNX2X_PORT4_MODE_NUM_VNICS;
-			if (BP_PORT(bp)) {
-				curr_cos += BNX2X_E3B0_PORT1_COS_OFFSET;
-				new_cos += BNX2X_E3B0_PORT1_COS_OFFSET;
-			}
-		}
-
-		/* change queue mapping for each VNIC */
-		for (vnic = 0; vnic < num_vnics; vnic++) {
-			u32 pf_q_num =
-				BNX2X_PF_Q_NUM(q_num, BP_PORT(bp), vnic);
-			u32 q_bit_map = 1 << (pf_q_num & 0x1f);
-
-			/* overwrite queue->VOQ mapping */
-			REG_WR(bp, BNX2X_Q_VOQ_REG_ADDR(pf_q_num), new_cos);
-
-			/* clear queue bit from current COS bit map */
-			reg_addr = BNX2X_VOQ_Q_REG_ADDR(curr_cos, pf_q_num);
-			reg_bit_map = REG_RD(bp, reg_addr);
-			REG_WR(bp, reg_addr, reg_bit_map & (~q_bit_map));
-
-			/* set queue bit in new COS bit map */
-			reg_addr = BNX2X_VOQ_Q_REG_ADDR(new_cos, pf_q_num);
-			reg_bit_map = REG_RD(bp, reg_addr);
-			REG_WR(bp, reg_addr, reg_bit_map | q_bit_map);
-
-			/* set/clear queue bit in command-queue bit map
-			(E2/E3A0 only, valid COS values are 0/1) */
-			if (!(INIT_MODE_FLAGS(bp) & MODE_E3_B0)) {
-				reg_addr = BNX2X_Q_CMDQ_REG_ADDR(pf_q_num);
-				reg_bit_map = REG_RD(bp, reg_addr);
-				q_bit_map = 1 << (2 * (pf_q_num & 0xf));
-				reg_bit_map = new_cos ?
-					      (reg_bit_map | q_bit_map) :
-					      (reg_bit_map & (~q_bit_map));
-				REG_WR(bp, reg_addr, reg_bit_map);
-			}
-		}
-	}
-}
-
-/* Configures the QM according to the specified per-traffic-type COSes */
-static inline void bnx2x_dcb_config_qm(struct bnx2x *bp, enum cos_mode mode,
-				       struct priority_cos *traffic_cos)
-{
-	bnx2x_map_q_cos(bp, BNX2X_FCOE_Q,
-			traffic_cos[LLFC_TRAFFIC_TYPE_FCOE].cos);
-	bnx2x_map_q_cos(bp, BNX2X_ISCSI_Q,
-			traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
-	bnx2x_map_q_cos(bp, BNX2X_ISCSI_ACK_Q,
-		traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
-	if (mode != STATIC_COS) {
-		/* required only in backward compatible COS mode */
-		bnx2x_map_q_cos(bp, BNX2X_ETH_Q,
-				traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
-		bnx2x_map_q_cos(bp, BNX2X_TOE_Q,
-				traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
-		bnx2x_map_q_cos(bp, BNX2X_TOE_ACK_Q,
-				traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
-	}
-}
-
-
-/* Returns the index of start or end of a specific block stage in ops array*/
-#define BLOCK_OPS_IDX(block, stage, end) \
-			(2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end))
-
-
-#define INITOP_SET		0	/* set the HW directly */
-#define INITOP_CLEAR		1	/* clear the HW directly */
-#define INITOP_INIT		2	/* set the init-value array */
-
-/****************************************************************************
-* ILT management
-****************************************************************************/
-struct ilt_line {
-	dma_addr_t page_mapping;
-	void *page;
-	u32 size;
-};
-
-struct ilt_client_info {
-	u32 page_size;
-	u16 start;
-	u16 end;
-	u16 client_num;
-	u16 flags;
-#define ILT_CLIENT_SKIP_INIT	0x1
-#define ILT_CLIENT_SKIP_MEM	0x2
-};
-
-struct bnx2x_ilt {
-	u32 start_line;
-	struct ilt_line		*lines;
-	struct ilt_client_info	clients[4];
-#define ILT_CLIENT_CDU	0
-#define ILT_CLIENT_QM	1
-#define ILT_CLIENT_SRC	2
-#define ILT_CLIENT_TM	3
-};
-
-/****************************************************************************
-* SRC configuration
-****************************************************************************/
-struct src_ent {
-	u8 opaque[56];
-	u64 next;
-};
-
-/****************************************************************************
-* Parity configuration
-****************************************************************************/
-#define BLOCK_PRTY_INFO(block, en_mask, m1, m1h, m2, m3) \
-{ \
-	block##_REG_##block##_PRTY_MASK, \
-	block##_REG_##block##_PRTY_STS_CLR, \
-	en_mask, {m1, m1h, m2, m3}, #block \
-}
-
-#define BLOCK_PRTY_INFO_0(block, en_mask, m1, m1h, m2, m3) \
-{ \
-	block##_REG_##block##_PRTY_MASK_0, \
-	block##_REG_##block##_PRTY_STS_CLR_0, \
-	en_mask, {m1, m1h, m2, m3}, #block"_0" \
-}
-
-#define BLOCK_PRTY_INFO_1(block, en_mask, m1, m1h, m2, m3) \
-{ \
-	block##_REG_##block##_PRTY_MASK_1, \
-	block##_REG_##block##_PRTY_STS_CLR_1, \
-	en_mask, {m1, m1h, m2, m3}, #block"_1" \
-}
-
-static const struct {
-	u32 mask_addr;
-	u32 sts_clr_addr;
-	u32 en_mask;		/* Mask to enable parity attentions */
-	struct {
-		u32 e1;		/* 57710 */
-		u32 e1h;	/* 57711 */
-		u32 e2;		/* 57712 */
-		u32 e3;		/* 578xx */
-	} reg_mask;		/* Register mask (all valid bits) */
-	char name[7];		/* Block's longest name is 6 characters long
-				 * (name + suffix)
-				 */
-} bnx2x_blocks_parity_data[] = {
-	/* bit 19 masked */
-	/* REG_WR(bp, PXP_REG_PXP_PRTY_MASK, 0x80000); */
-	/* bit 5,18,20-31 */
-	/* REG_WR(bp, PXP2_REG_PXP2_PRTY_MASK_0, 0xfff40020); */
-	/* bit 5 */
-	/* REG_WR(bp, PXP2_REG_PXP2_PRTY_MASK_1, 0x20);	*/
-	/* REG_WR(bp, HC_REG_HC_PRTY_MASK, 0x0); */
-	/* REG_WR(bp, MISC_REG_MISC_PRTY_MASK, 0x0); */
-
-	/* Block IGU, MISC, PXP and PXP2 parity errors as long as we don't
-	 * want to handle "system kill" flow at the moment.
-	 */
-	BLOCK_PRTY_INFO(PXP, 0x7ffffff, 0x3ffffff, 0x3ffffff, 0x7ffffff,
-			0x7ffffff),
-	BLOCK_PRTY_INFO_0(PXP2,	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
-			  0xffffffff),
-	BLOCK_PRTY_INFO_1(PXP2,	0x1ffffff, 0x7f, 0x7f, 0x7ff, 0x1ffffff),
-	BLOCK_PRTY_INFO(HC, 0x7, 0x7, 0x7, 0, 0),
-	BLOCK_PRTY_INFO(NIG, 0xffffffff, 0x3fffffff, 0xffffffff, 0, 0),
-	BLOCK_PRTY_INFO_0(NIG,	0xffffffff, 0, 0, 0xffffffff, 0xffffffff),
-	BLOCK_PRTY_INFO_1(NIG,	0xffff, 0, 0, 0xff, 0xffff),
-	BLOCK_PRTY_INFO(IGU, 0x7ff, 0, 0, 0x7ff, 0x7ff),
-	BLOCK_PRTY_INFO(MISC, 0x1, 0x1, 0x1, 0x1, 0x1),
-	BLOCK_PRTY_INFO(QM, 0, 0x1ff, 0xfff, 0xfff, 0xfff),
-	BLOCK_PRTY_INFO(ATC, 0x1f, 0, 0, 0x1f, 0x1f),
-	BLOCK_PRTY_INFO(PGLUE_B, 0x3, 0, 0, 0x3, 0x3),
-	BLOCK_PRTY_INFO(DORQ, 0, 0x3, 0x3, 0x3, 0x3),
-	{GRCBASE_UPB + PB_REG_PB_PRTY_MASK,
-		GRCBASE_UPB + PB_REG_PB_PRTY_STS_CLR, 0xf,
-		{0xf, 0xf, 0xf, 0xf}, "UPB"},
-	{GRCBASE_XPB + PB_REG_PB_PRTY_MASK,
-		GRCBASE_XPB + PB_REG_PB_PRTY_STS_CLR, 0,
-		{0xf, 0xf, 0xf, 0xf}, "XPB"},
-	BLOCK_PRTY_INFO(SRC, 0x4, 0x7, 0x7, 0x7, 0x7),
-	BLOCK_PRTY_INFO(CDU, 0, 0x1f, 0x1f, 0x1f, 0x1f),
-	BLOCK_PRTY_INFO(CFC, 0, 0xf, 0xf, 0xf, 0x3f),
-	BLOCK_PRTY_INFO(DBG, 0, 0x1, 0x1, 0x1, 0x1),
-	BLOCK_PRTY_INFO(DMAE, 0, 0xf, 0xf, 0xf, 0xf),
-	BLOCK_PRTY_INFO(BRB1, 0, 0xf, 0xf, 0xf, 0xf),
-	BLOCK_PRTY_INFO(PRS, (1<<6), 0xff, 0xff, 0xff, 0xff),
-	BLOCK_PRTY_INFO(PBF, 0, 0, 0x3ffff, 0xfffff, 0xfffffff),
-	BLOCK_PRTY_INFO(TM, 0, 0, 0x7f, 0x7f, 0x7f),
-	BLOCK_PRTY_INFO(TSDM, 0x18, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
-	BLOCK_PRTY_INFO(CSDM, 0x8, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
-	BLOCK_PRTY_INFO(USDM, 0x38, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
-	BLOCK_PRTY_INFO(XSDM, 0x8, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
-	BLOCK_PRTY_INFO(TCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff),
-	BLOCK_PRTY_INFO(CCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff),
-	BLOCK_PRTY_INFO(UCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff),
-	BLOCK_PRTY_INFO(XCM, 0, 0, 0x3fffffff, 0x3fffffff, 0x3fffffff),
-	BLOCK_PRTY_INFO_0(TSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
-			  0xffffffff),
-	BLOCK_PRTY_INFO_1(TSEM, 0, 0x3, 0x1f, 0x3f, 0x3f),
-	BLOCK_PRTY_INFO_0(USEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
-			  0xffffffff),
-	BLOCK_PRTY_INFO_1(USEM, 0, 0x3, 0x1f, 0x1f, 0x1f),
-	BLOCK_PRTY_INFO_0(CSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
-			  0xffffffff),
-	BLOCK_PRTY_INFO_1(CSEM, 0, 0x3, 0x1f, 0x1f, 0x1f),
-	BLOCK_PRTY_INFO_0(XSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
-			  0xffffffff),
-	BLOCK_PRTY_INFO_1(XSEM, 0, 0x3, 0x1f, 0x3f, 0x3f),
-};
-
-
-/* [28] MCP Latched rom_parity
- * [29] MCP Latched ump_rx_parity
- * [30] MCP Latched ump_tx_parity
- * [31] MCP Latched scpad_parity
- */
-#define MISC_AEU_ENABLE_MCP_PRTY_BITS	\
-	(AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY | \
-	 AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY | \
-	 AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY | \
-	 AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY)
-
-/* Below registers control the MCP parity attention output. When
- * MISC_AEU_ENABLE_MCP_PRTY_BITS are set - attentions are
- * enabled, when cleared - disabled.
- */
-static const u32 mcp_attn_ctl_regs[] = {
-	MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0,
-	MISC_REG_AEU_ENABLE4_NIG_0,
-	MISC_REG_AEU_ENABLE4_PXP_0,
-	MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0,
-	MISC_REG_AEU_ENABLE4_NIG_1,
-	MISC_REG_AEU_ENABLE4_PXP_1
-};
-
-static inline void bnx2x_set_mcp_parity(struct bnx2x *bp, u8 enable)
-{
-	int i;
-	u32 reg_val;
-
-	for (i = 0; i < ARRAY_SIZE(mcp_attn_ctl_regs); i++) {
-		reg_val = REG_RD(bp, mcp_attn_ctl_regs[i]);
-
-		if (enable)
-			reg_val |= MISC_AEU_ENABLE_MCP_PRTY_BITS;
-		else
-			reg_val &= ~MISC_AEU_ENABLE_MCP_PRTY_BITS;
-
-		REG_WR(bp, mcp_attn_ctl_regs[i], reg_val);
-	}
-}
-
-static inline u32 bnx2x_parity_reg_mask(struct bnx2x *bp, int idx)
-{
-	if (CHIP_IS_E1(bp))
-		return bnx2x_blocks_parity_data[idx].reg_mask.e1;
-	else if (CHIP_IS_E1H(bp))
-		return bnx2x_blocks_parity_data[idx].reg_mask.e1h;
-	else if (CHIP_IS_E2(bp))
-		return bnx2x_blocks_parity_data[idx].reg_mask.e2;
-	else /* CHIP_IS_E3 */
-		return bnx2x_blocks_parity_data[idx].reg_mask.e3;
-}
-
-static inline void bnx2x_disable_blocks_parity(struct bnx2x *bp)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(bnx2x_blocks_parity_data); i++) {
-		u32 dis_mask = bnx2x_parity_reg_mask(bp, i);
-
-		if (dis_mask) {
-			REG_WR(bp, bnx2x_blocks_parity_data[i].mask_addr,
-			       dis_mask);
-			DP(NETIF_MSG_HW, "Setting parity mask "
-						 "for %s to\t\t0x%x\n",
-				    bnx2x_blocks_parity_data[i].name, dis_mask);
-		}
-	}
-
-	/* Disable MCP parity attentions */
-	bnx2x_set_mcp_parity(bp, false);
-}
-
-/**
- * Clear the parity error status registers.
- */
-static inline void bnx2x_clear_blocks_parity(struct bnx2x *bp)
-{
-	int i;
-	u32 reg_val, mcp_aeu_bits =
-		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY |
-		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY |
-		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY |
-		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY;
-
-	/* Clear SEM_FAST parities */
-	REG_WR(bp, XSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1);
-	REG_WR(bp, TSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1);
-	REG_WR(bp, USEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1);
-	REG_WR(bp, CSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1);
-
-	for (i = 0; i < ARRAY_SIZE(bnx2x_blocks_parity_data); i++) {
-		u32 reg_mask = bnx2x_parity_reg_mask(bp, i);
-
-		if (reg_mask) {
-			reg_val = REG_RD(bp, bnx2x_blocks_parity_data[i].
-					 sts_clr_addr);
-			if (reg_val & reg_mask)
-				DP(NETIF_MSG_HW,
-					    "Parity errors in %s: 0x%x\n",
-					    bnx2x_blocks_parity_data[i].name,
-					    reg_val & reg_mask);
-		}
-	}
-
-	/* Check if there were parity attentions in MCP */
-	reg_val = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_4_MCP);
-	if (reg_val & mcp_aeu_bits)
-		DP(NETIF_MSG_HW, "Parity error in MCP: 0x%x\n",
-		   reg_val & mcp_aeu_bits);
-
-	/* Clear parity attentions in MCP:
-	 * [7]  clears Latched rom_parity
-	 * [8]  clears Latched ump_rx_parity
-	 * [9]  clears Latched ump_tx_parity
-	 * [10] clears Latched scpad_parity (both ports)
-	 */
-	REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0x780);
-}
-
-static inline void bnx2x_enable_blocks_parity(struct bnx2x *bp)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(bnx2x_blocks_parity_data); i++) {
-		u32 reg_mask = bnx2x_parity_reg_mask(bp, i);
-
-		if (reg_mask)
-			REG_WR(bp, bnx2x_blocks_parity_data[i].mask_addr,
-				bnx2x_blocks_parity_data[i].en_mask & reg_mask);
-	}
-
-	/* Enable MCP parity attentions */
-	bnx2x_set_mcp_parity(bp, true);
-}
-
-
-#endif /* BNX2X_INIT_H */
-
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_init_ops.h linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_init_ops.h
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_init_ops.h	2012-03-19 21:43:27.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_init_ops.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,825 +0,0 @@
-/* bnx2x_init_ops.h: Broadcom Everest network driver.
- *               Static functions needed during the initialization.
- *               This file is "included" in bnx2x_main.c.
- *
- * Copyright (c) 2007-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
- * the Free Software Foundation.
- *
- * Maintained by: Eilon Greenstein <eilong@broadcom.com>
- * Written by: Vladislav Zolotarov <vladz@broadcom.com>
- */
-
-#ifndef BNX2X_INIT_OPS_H
-#define BNX2X_INIT_OPS_H
-
-
-#ifndef BP_ILT
-#define BP_ILT(bp)	NULL
-#endif
-
-#ifndef BP_FUNC
-#define BP_FUNC(bp)	0
-#endif
-
-#ifndef BP_PORT
-#define BP_PORT(bp)	0
-#endif
-
-#ifndef BNX2X_ILT_FREE
-#define BNX2X_ILT_FREE(x, y, sz)
-#endif
-
-#ifndef BNX2X_ILT_ZALLOC
-#define BNX2X_ILT_ZALLOC(x, y, sz)
-#endif
-
-#ifndef ILOG2
-#define ILOG2(x)	x
-#endif
-
-static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len);
-static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);
-static void bnx2x_write_dmae_phys_len(struct bnx2x *bp,
-				      dma_addr_t phys_addr, u32 addr,
-				      u32 len);
-
-static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr,
-			      const u32 *data, u32 len)
-{
-	u32 i;
-
-	for (i = 0; i < len; i++)
-		REG_WR(bp, addr + i*4, data[i]);
-}
-
-static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr,
-			      const u32 *data, u32 len)
-{
-	u32 i;
-
-	for (i = 0; i < len; i++)
-		bnx2x_reg_wr_ind(bp, addr + i*4, data[i]);
-}
-
-static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len,
-				u8 wb)
-{
-	if (bp->dmae_ready)
-		bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
-	else if (wb)
-		/*
-		 * Wide bus registers with no dmae need to be written
-		 * using indirect write.
-		 */
-		bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);
-	else
-		bnx2x_init_str_wr(bp, addr, GUNZIP_BUF(bp), len);
-}
-
-static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill,
-			    u32 len, u8 wb)
-{
-	u32 buf_len = (((len*4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len*4));
-	u32 buf_len32 = buf_len/4;
-	u32 i;
-
-	memset(GUNZIP_BUF(bp), (u8)fill, buf_len);
-
-	for (i = 0; i < len; i += buf_len32) {
-		u32 cur_len = min(buf_len32, len - i);
-
-		bnx2x_write_big_buf(bp, addr + i*4, cur_len, wb);
-	}
-}
-
-static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len)
-{
-	if (bp->dmae_ready)
-		bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
-	else
-		bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);
-}
-
-static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr,
-			     const u32 *data, u32 len64)
-{
-	u32 buf_len32 = FW_BUF_SIZE/4;
-	u32 len = len64*2;
-	u64 data64 = 0;
-	u32 i;
-
-	/* 64 bit value is in a blob: first low DWORD, then high DWORD */
-	data64 = HILO_U64((*(data + 1)), (*data));
-
-	len64 = min((u32)(FW_BUF_SIZE/8), len64);
-	for (i = 0; i < len64; i++) {
-		u64 *pdata = ((u64 *)(GUNZIP_BUF(bp))) + i;
-
-		*pdata = data64;
-	}
-
-	for (i = 0; i < len; i += buf_len32) {
-		u32 cur_len = min(buf_len32, len - i);
-
-		bnx2x_write_big_buf_wb(bp, addr + i*4, cur_len);
-	}
-}
-
-/*********************************************************
-   There are different blobs for each PRAM section.
-   In addition, each blob write operation is divided into a few operations
-   in order to decrease the amount of phys. contiguous buffer needed.
-   Thus, when we select a blob the address may be with some offset
-   from the beginning of PRAM section.
-   The same holds for the INT_TABLE sections.
-**********************************************************/
-#define IF_IS_INT_TABLE_ADDR(base, addr) \
-			if (((base) <= (addr)) && ((base) + 0x400 >= (addr)))
-
-#define IF_IS_PRAM_ADDR(base, addr) \
-			if (((base) <= (addr)) && ((base) + 0x40000 >= (addr)))
-
-static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr,
-				const u8 *data)
-{
-	IF_IS_INT_TABLE_ADDR(TSEM_REG_INT_TABLE, addr)
-		data = INIT_TSEM_INT_TABLE_DATA(bp);
-	else
-		IF_IS_INT_TABLE_ADDR(CSEM_REG_INT_TABLE, addr)
-			data = INIT_CSEM_INT_TABLE_DATA(bp);
-	else
-		IF_IS_INT_TABLE_ADDR(USEM_REG_INT_TABLE, addr)
-			data = INIT_USEM_INT_TABLE_DATA(bp);
-	else
-		IF_IS_INT_TABLE_ADDR(XSEM_REG_INT_TABLE, addr)
-			data = INIT_XSEM_INT_TABLE_DATA(bp);
-	else
-		IF_IS_PRAM_ADDR(TSEM_REG_PRAM, addr)
-			data = INIT_TSEM_PRAM_DATA(bp);
-	else
-		IF_IS_PRAM_ADDR(CSEM_REG_PRAM, addr)
-			data = INIT_CSEM_PRAM_DATA(bp);
-	else
-		IF_IS_PRAM_ADDR(USEM_REG_PRAM, addr)
-			data = INIT_USEM_PRAM_DATA(bp);
-	else
-		IF_IS_PRAM_ADDR(XSEM_REG_PRAM, addr)
-			data = INIT_XSEM_PRAM_DATA(bp);
-
-	return data;
-}
-
-/*(DEBLOBBED)*/
-
-static void bnx2x_wr_64(struct bnx2x *bp, u32 reg, u32 val_lo,
-			u32 val_hi)
-{
-	u32 wb_write[2];
-
-	wb_write[0] = val_lo;
-	wb_write[1] = val_hi;
-	REG_WR_DMAE_LEN(bp, reg, wb_write, 2);
-}
-static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, u32 len,
-			     u32 blob_off)
-{
-	const u8 *data = NULL;
-	int rc;
-	u32 i;
-
-	data = bnx2x_sel_blob(bp, addr, data) + blob_off*4;
-
-	rc = bnx2x_gunzip(bp, data, len);
-	if (rc)
-		return;
-
-	/* gunzip_outlen is in dwords */
-	len = GUNZIP_OUTLEN(bp);
-	for (i = 0; i < len; i++)
-		((u32 *)GUNZIP_BUF(bp))[i] =
-				cpu_to_le32(((u32 *)GUNZIP_BUF(bp))[i]);
-
-	bnx2x_write_big_buf_wb(bp, addr, len);
-}
-
-/*(DEBLOBBED)*/
-
-
-/****************************************************************************
-* PXP Arbiter
-****************************************************************************/
-/*
- * This code configures the PCI read/write arbiter
- * which implements a weighted round robin
- * between the virtual queues in the chip.
- *
- * The values were derived for each PCI max payload and max request size.
- * since max payload and max request size are only known at run time,
- * this is done as a separate init stage.
- */
-
-#define NUM_WR_Q			13
-#define NUM_RD_Q			29
-#define MAX_RD_ORD			3
-#define MAX_WR_ORD			2
-
-/* configuration for one arbiter queue */
-struct arb_line {
-	int l;
-	int add;
-	int ubound;
-};
-
-/* derived configuration for each read queue for each max request size */
-static const struct arb_line read_arb_data[NUM_RD_Q][MAX_RD_ORD + 1] = {
-/* 1 */	{ {8, 64, 25}, {16, 64, 25}, {32, 64, 25}, {64, 64, 41} },
-	{ {4, 8,  4},  {4,  8,  4},  {4,  8,  4},  {4,  8,  4}  },
-	{ {4, 3,  3},  {4,  3,  3},  {4,  3,  3},  {4,  3,  3}  },
-	{ {8, 3,  6},  {16, 3,  11}, {16, 3,  11}, {16, 3,  11} },
-	{ {8, 64, 25}, {16, 64, 25}, {32, 64, 25}, {64, 64, 41} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {64, 3,  41} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {64, 3,  41} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {64, 3,  41} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {64, 3,  41} },
-/* 10 */{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 64, 6},  {16, 64, 11}, {32, 64, 21}, {32, 64, 21} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-/* 20 */{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 3,  6},  {16, 3,  11}, {32, 3,  21}, {32, 3,  21} },
-	{ {8, 64, 25}, {16, 64, 41}, {32, 64, 81}, {64, 64, 120} }
-};
-
-/* derived configuration for each write queue for each max request size */
-static const struct arb_line write_arb_data[NUM_WR_Q][MAX_WR_ORD + 1] = {
-/* 1 */	{ {4, 6,  3},  {4,  6,  3},  {4,  6,  3} },
-	{ {4, 2,  3},  {4,  2,  3},  {4,  2,  3} },
-	{ {8, 2,  6},  {16, 2,  11}, {16, 2,  11} },
-	{ {8, 2,  6},  {16, 2,  11}, {32, 2,  21} },
-	{ {8, 2,  6},  {16, 2,  11}, {32, 2,  21} },
-	{ {8, 2,  6},  {16, 2,  11}, {32, 2,  21} },
-	{ {8, 64, 25}, {16, 64, 25}, {32, 64, 25} },
-	{ {8, 2,  6},  {16, 2,  11}, {16, 2,  11} },
-	{ {8, 2,  6},  {16, 2,  11}, {16, 2,  11} },
-/* 10 */{ {8, 9,  6},  {16, 9,  11}, {32, 9,  21} },
-	{ {8, 47, 19}, {16, 47, 19}, {32, 47, 21} },
-	{ {8, 9,  6},  {16, 9,  11}, {16, 9,  11} },
-	{ {8, 64, 25}, {16, 64, 41}, {32, 64, 81} }
-};
-
-/* register addresses for read queues */
-static const struct arb_line read_arb_addr[NUM_RD_Q-1] = {
-/* 1 */	{PXP2_REG_RQ_BW_RD_L0, PXP2_REG_RQ_BW_RD_ADD0,
-		PXP2_REG_RQ_BW_RD_UBOUND0},
-	{PXP2_REG_PSWRQ_BW_L1, PXP2_REG_PSWRQ_BW_ADD1,
-		PXP2_REG_PSWRQ_BW_UB1},
-	{PXP2_REG_PSWRQ_BW_L2, PXP2_REG_PSWRQ_BW_ADD2,
-		PXP2_REG_PSWRQ_BW_UB2},
-	{PXP2_REG_PSWRQ_BW_L3, PXP2_REG_PSWRQ_BW_ADD3,
-		PXP2_REG_PSWRQ_BW_UB3},
-	{PXP2_REG_RQ_BW_RD_L4, PXP2_REG_RQ_BW_RD_ADD4,
-		PXP2_REG_RQ_BW_RD_UBOUND4},
-	{PXP2_REG_RQ_BW_RD_L5, PXP2_REG_RQ_BW_RD_ADD5,
-		PXP2_REG_RQ_BW_RD_UBOUND5},
-	{PXP2_REG_PSWRQ_BW_L6, PXP2_REG_PSWRQ_BW_ADD6,
-		PXP2_REG_PSWRQ_BW_UB6},
-	{PXP2_REG_PSWRQ_BW_L7, PXP2_REG_PSWRQ_BW_ADD7,
-		PXP2_REG_PSWRQ_BW_UB7},
-	{PXP2_REG_PSWRQ_BW_L8, PXP2_REG_PSWRQ_BW_ADD8,
-		PXP2_REG_PSWRQ_BW_UB8},
-/* 10 */{PXP2_REG_PSWRQ_BW_L9, PXP2_REG_PSWRQ_BW_ADD9,
-		PXP2_REG_PSWRQ_BW_UB9},
-	{PXP2_REG_PSWRQ_BW_L10, PXP2_REG_PSWRQ_BW_ADD10,
-		PXP2_REG_PSWRQ_BW_UB10},
-	{PXP2_REG_PSWRQ_BW_L11, PXP2_REG_PSWRQ_BW_ADD11,
-		PXP2_REG_PSWRQ_BW_UB11},
-	{PXP2_REG_RQ_BW_RD_L12, PXP2_REG_RQ_BW_RD_ADD12,
-		PXP2_REG_RQ_BW_RD_UBOUND12},
-	{PXP2_REG_RQ_BW_RD_L13, PXP2_REG_RQ_BW_RD_ADD13,
-		PXP2_REG_RQ_BW_RD_UBOUND13},
-	{PXP2_REG_RQ_BW_RD_L14, PXP2_REG_RQ_BW_RD_ADD14,
-		PXP2_REG_RQ_BW_RD_UBOUND14},
-	{PXP2_REG_RQ_BW_RD_L15, PXP2_REG_RQ_BW_RD_ADD15,
-		PXP2_REG_RQ_BW_RD_UBOUND15},
-	{PXP2_REG_RQ_BW_RD_L16, PXP2_REG_RQ_BW_RD_ADD16,
-		PXP2_REG_RQ_BW_RD_UBOUND16},
-	{PXP2_REG_RQ_BW_RD_L17, PXP2_REG_RQ_BW_RD_ADD17,
-		PXP2_REG_RQ_BW_RD_UBOUND17},
-	{PXP2_REG_RQ_BW_RD_L18, PXP2_REG_RQ_BW_RD_ADD18,
-		PXP2_REG_RQ_BW_RD_UBOUND18},
-/* 20 */{PXP2_REG_RQ_BW_RD_L19, PXP2_REG_RQ_BW_RD_ADD19,
-		PXP2_REG_RQ_BW_RD_UBOUND19},
-	{PXP2_REG_RQ_BW_RD_L20, PXP2_REG_RQ_BW_RD_ADD20,
-		PXP2_REG_RQ_BW_RD_UBOUND20},
-	{PXP2_REG_RQ_BW_RD_L22, PXP2_REG_RQ_BW_RD_ADD22,
-		PXP2_REG_RQ_BW_RD_UBOUND22},
-	{PXP2_REG_RQ_BW_RD_L23, PXP2_REG_RQ_BW_RD_ADD23,
-		PXP2_REG_RQ_BW_RD_UBOUND23},
-	{PXP2_REG_RQ_BW_RD_L24, PXP2_REG_RQ_BW_RD_ADD24,
-		PXP2_REG_RQ_BW_RD_UBOUND24},
-	{PXP2_REG_RQ_BW_RD_L25, PXP2_REG_RQ_BW_RD_ADD25,
-		PXP2_REG_RQ_BW_RD_UBOUND25},
-	{PXP2_REG_RQ_BW_RD_L26, PXP2_REG_RQ_BW_RD_ADD26,
-		PXP2_REG_RQ_BW_RD_UBOUND26},
-	{PXP2_REG_RQ_BW_RD_L27, PXP2_REG_RQ_BW_RD_ADD27,
-		PXP2_REG_RQ_BW_RD_UBOUND27},
-	{PXP2_REG_PSWRQ_BW_L28, PXP2_REG_PSWRQ_BW_ADD28,
-		PXP2_REG_PSWRQ_BW_UB28}
-};
-
-/* register addresses for write queues */
-static const struct arb_line write_arb_addr[NUM_WR_Q-1] = {
-/* 1 */	{PXP2_REG_PSWRQ_BW_L1, PXP2_REG_PSWRQ_BW_ADD1,
-		PXP2_REG_PSWRQ_BW_UB1},
-	{PXP2_REG_PSWRQ_BW_L2, PXP2_REG_PSWRQ_BW_ADD2,
-		PXP2_REG_PSWRQ_BW_UB2},
-	{PXP2_REG_PSWRQ_BW_L3, PXP2_REG_PSWRQ_BW_ADD3,
-		PXP2_REG_PSWRQ_BW_UB3},
-	{PXP2_REG_PSWRQ_BW_L6, PXP2_REG_PSWRQ_BW_ADD6,
-		PXP2_REG_PSWRQ_BW_UB6},
-	{PXP2_REG_PSWRQ_BW_L7, PXP2_REG_PSWRQ_BW_ADD7,
-		PXP2_REG_PSWRQ_BW_UB7},
-	{PXP2_REG_PSWRQ_BW_L8, PXP2_REG_PSWRQ_BW_ADD8,
-		PXP2_REG_PSWRQ_BW_UB8},
-	{PXP2_REG_PSWRQ_BW_L9, PXP2_REG_PSWRQ_BW_ADD9,
-		PXP2_REG_PSWRQ_BW_UB9},
-	{PXP2_REG_PSWRQ_BW_L10, PXP2_REG_PSWRQ_BW_ADD10,
-		PXP2_REG_PSWRQ_BW_UB10},
-	{PXP2_REG_PSWRQ_BW_L11, PXP2_REG_PSWRQ_BW_ADD11,
-		PXP2_REG_PSWRQ_BW_UB11},
-/* 10 */{PXP2_REG_PSWRQ_BW_L28, PXP2_REG_PSWRQ_BW_ADD28,
-		PXP2_REG_PSWRQ_BW_UB28},
-	{PXP2_REG_RQ_BW_WR_L29, PXP2_REG_RQ_BW_WR_ADD29,
-		PXP2_REG_RQ_BW_WR_UBOUND29},
-	{PXP2_REG_RQ_BW_WR_L30, PXP2_REG_RQ_BW_WR_ADD30,
-		PXP2_REG_RQ_BW_WR_UBOUND30}
-};
-
-static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order,
-			       int w_order)
-{
-	u32 val, i;
-
-	if (r_order > MAX_RD_ORD) {
-		DP(NETIF_MSG_HW, "read order of %d  order adjusted to %d\n",
-		   r_order, MAX_RD_ORD);
-		r_order = MAX_RD_ORD;
-	}
-	if (w_order > MAX_WR_ORD) {
-		DP(NETIF_MSG_HW, "write order of %d  order adjusted to %d\n",
-		   w_order, MAX_WR_ORD);
-		w_order = MAX_WR_ORD;
-	}
-	if (CHIP_REV_IS_FPGA(bp)) {
-		DP(NETIF_MSG_HW, "write order adjusted to 1 for FPGA\n");
-		w_order = 0;
-	}
-	DP(NETIF_MSG_HW, "read order %d  write order %d\n", r_order, w_order);
-
-	for (i = 0; i < NUM_RD_Q-1; i++) {
-		REG_WR(bp, read_arb_addr[i].l, read_arb_data[i][r_order].l);
-		REG_WR(bp, read_arb_addr[i].add,
-		       read_arb_data[i][r_order].add);
-		REG_WR(bp, read_arb_addr[i].ubound,
-		       read_arb_data[i][r_order].ubound);
-	}
-
-	for (i = 0; i < NUM_WR_Q-1; i++) {
-		if ((write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L29) ||
-		    (write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L30)) {
-
-			REG_WR(bp, write_arb_addr[i].l,
-			       write_arb_data[i][w_order].l);
-
-			REG_WR(bp, write_arb_addr[i].add,
-			       write_arb_data[i][w_order].add);
-
-			REG_WR(bp, write_arb_addr[i].ubound,
-			       write_arb_data[i][w_order].ubound);
-		} else {
-
-			val = REG_RD(bp, write_arb_addr[i].l);
-			REG_WR(bp, write_arb_addr[i].l,
-			       val | (write_arb_data[i][w_order].l << 10));
-
-			val = REG_RD(bp, write_arb_addr[i].add);
-			REG_WR(bp, write_arb_addr[i].add,
-			       val | (write_arb_data[i][w_order].add << 10));
-
-			val = REG_RD(bp, write_arb_addr[i].ubound);
-			REG_WR(bp, write_arb_addr[i].ubound,
-			       val | (write_arb_data[i][w_order].ubound << 7));
-		}
-	}
-
-	val =  write_arb_data[NUM_WR_Q-1][w_order].add;
-	val += write_arb_data[NUM_WR_Q-1][w_order].ubound << 10;
-	val += write_arb_data[NUM_WR_Q-1][w_order].l << 17;
-	REG_WR(bp, PXP2_REG_PSWRQ_BW_RD, val);
-
-	val =  read_arb_data[NUM_RD_Q-1][r_order].add;
-	val += read_arb_data[NUM_RD_Q-1][r_order].ubound << 10;
-	val += read_arb_data[NUM_RD_Q-1][r_order].l << 17;
-	REG_WR(bp, PXP2_REG_PSWRQ_BW_WR, val);
-
-	REG_WR(bp, PXP2_REG_RQ_WR_MBS0, w_order);
-	REG_WR(bp, PXP2_REG_RQ_WR_MBS1, w_order);
-	REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order);
-	REG_WR(bp, PXP2_REG_RQ_RD_MBS1, r_order);
-
-	if ((CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) && (r_order == MAX_RD_ORD))
-		REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00);
-
-	if (CHIP_IS_E3(bp))
-		REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x4 << w_order));
-	else if (CHIP_IS_E2(bp))
-		REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x8 << w_order));
-	else
-		REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));
-
-	if (!CHIP_IS_E1(bp)) {
-		/*    MPS      w_order     optimal TH      presently TH
-		 *    128         0             0               2
-		 *    256         1             1               3
-		 *    >=512       2             2               3
-		 */
-		/* DMAE is special */
-		if (!CHIP_IS_E1H(bp)) {
-			/* E2 can use optimal TH */
-			val = w_order;
-			REG_WR(bp, PXP2_REG_WR_DMAE_MPS, val);
-		} else {
-			val = ((w_order == 0) ? 2 : 3);
-			REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2);
-		}
-
-		REG_WR(bp, PXP2_REG_WR_HC_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_USDM_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_CSDM_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_TSDM_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_XSDM_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_QM_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_TM_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_SRC_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_DBG_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_CDU_MPS, val);
-	}
-
-	/* Validate number of tags suppoted by device */
-#define PCIE_REG_PCIER_TL_HDR_FC_ST		0x2980
-	val = REG_RD(bp, PCIE_REG_PCIER_TL_HDR_FC_ST);
-	val &= 0xFF;
-	if (val <= 0x20)
-		REG_WR(bp, PXP2_REG_PGL_TAGS_LIMIT, 0x20);
-}
-
-/****************************************************************************
-* ILT management
-****************************************************************************/
-/*
- * This codes hides the low level HW interaction for ILT management and
- * configuration. The API consists of a shadow ILT table which is set by the
- * driver and a set of routines to use it to configure the HW.
- *
- */
-
-/* ILT HW init operations */
-
-/* ILT memory management operations */
-#define ILT_MEMOP_ALLOC		0
-#define ILT_MEMOP_FREE		1
-
-/* the phys address is shifted right 12 bits and has an added
- * 1=valid bit added to the 53rd bit
- * then since this is a wide register(TM)
- * we split it into two 32 bit writes
- */
-#define ILT_ADDR1(x)		((u32)(((u64)x >> 12) & 0xFFFFFFFF))
-#define ILT_ADDR2(x)		((u32)((1 << 20) | ((u64)x >> 44)))
-#define ILT_RANGE(f, l)		(((l) << 10) | f)
-
-static int bnx2x_ilt_line_mem_op(struct bnx2x *bp,
-				 struct ilt_line *line, u32 size, u8 memop)
-{
-	if (memop == ILT_MEMOP_FREE) {
-		BNX2X_ILT_FREE(line->page, line->page_mapping, line->size);
-		return 0;
-	}
-	BNX2X_ILT_ZALLOC(line->page, &line->page_mapping, size);
-	if (!line->page)
-		return -1;
-	line->size = size;
-	return 0;
-}
-
-
-static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num,
-				   u8 memop)
-{
-	int i, rc;
-	struct bnx2x_ilt *ilt = BP_ILT(bp);
-	struct ilt_client_info *ilt_cli = &ilt->clients[cli_num];
-
-	if (!ilt || !ilt->lines)
-		return -1;
-
-	if (ilt_cli->flags & (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM))
-		return 0;
-
-	for (rc = 0, i = ilt_cli->start; i <= ilt_cli->end && !rc; i++) {
-		rc = bnx2x_ilt_line_mem_op(bp, &ilt->lines[i],
-					   ilt_cli->page_size, memop);
-	}
-	return rc;
-}
-
-static int bnx2x_ilt_mem_op(struct bnx2x *bp, u8 memop)
-{
-	int rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_CDU, memop);
-	if (!rc)
-		rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_QM, memop);
-	if (!rc)
-		rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop);
-	if (!rc)
-		rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_TM, memop);
-
-	return rc;
-}
-
-static void bnx2x_ilt_line_wr(struct bnx2x *bp, int abs_idx,
-			      dma_addr_t page_mapping)
-{
-	u32 reg;
-
-	if (CHIP_IS_E1(bp))
-		reg = PXP2_REG_RQ_ONCHIP_AT + abs_idx*8;
-	else
-		reg = PXP2_REG_RQ_ONCHIP_AT_B0 + abs_idx*8;
-
-	bnx2x_wr_64(bp, reg, ILT_ADDR1(page_mapping), ILT_ADDR2(page_mapping));
-}
-
-static void bnx2x_ilt_line_init_op(struct bnx2x *bp,
-				   struct bnx2x_ilt *ilt, int idx, u8 initop)
-{
-	dma_addr_t	null_mapping;
-	int abs_idx = ilt->start_line + idx;
-
-
-	switch (initop) {
-	case INITOP_INIT:
-		/* set in the init-value array */
-	case INITOP_SET:
-		bnx2x_ilt_line_wr(bp, abs_idx, ilt->lines[idx].page_mapping);
-		break;
-	case INITOP_CLEAR:
-		null_mapping = 0;
-		bnx2x_ilt_line_wr(bp, abs_idx, null_mapping);
-		break;
-	}
-}
-
-static void bnx2x_ilt_boundry_init_op(struct bnx2x *bp,
-				      struct ilt_client_info *ilt_cli,
-				      u32 ilt_start, u8 initop)
-{
-	u32 start_reg = 0;
-	u32 end_reg = 0;
-
-	/* The boundary is either SET or INIT,
-	   CLEAR => SET and for now SET ~~ INIT */
-
-	/* find the appropriate regs */
-	if (CHIP_IS_E1(bp)) {
-		switch (ilt_cli->client_num) {
-		case ILT_CLIENT_CDU:
-			start_reg = PXP2_REG_PSWRQ_CDU0_L2P;
-			break;
-		case ILT_CLIENT_QM:
-			start_reg = PXP2_REG_PSWRQ_QM0_L2P;
-			break;
-		case ILT_CLIENT_SRC:
-			start_reg = PXP2_REG_PSWRQ_SRC0_L2P;
-			break;
-		case ILT_CLIENT_TM:
-			start_reg = PXP2_REG_PSWRQ_TM0_L2P;
-			break;
-		}
-		REG_WR(bp, start_reg + BP_FUNC(bp)*4,
-		       ILT_RANGE((ilt_start + ilt_cli->start),
-				 (ilt_start + ilt_cli->end)));
-	} else {
-		switch (ilt_cli->client_num) {
-		case ILT_CLIENT_CDU:
-			start_reg = PXP2_REG_RQ_CDU_FIRST_ILT;
-			end_reg = PXP2_REG_RQ_CDU_LAST_ILT;
-			break;
-		case ILT_CLIENT_QM:
-			start_reg = PXP2_REG_RQ_QM_FIRST_ILT;
-			end_reg = PXP2_REG_RQ_QM_LAST_ILT;
-			break;
-		case ILT_CLIENT_SRC:
-			start_reg = PXP2_REG_RQ_SRC_FIRST_ILT;
-			end_reg = PXP2_REG_RQ_SRC_LAST_ILT;
-			break;
-		case ILT_CLIENT_TM:
-			start_reg = PXP2_REG_RQ_TM_FIRST_ILT;
-			end_reg = PXP2_REG_RQ_TM_LAST_ILT;
-			break;
-		}
-		REG_WR(bp, start_reg, (ilt_start + ilt_cli->start));
-		REG_WR(bp, end_reg, (ilt_start + ilt_cli->end));
-	}
-}
-
-static void bnx2x_ilt_client_init_op_ilt(struct bnx2x *bp,
-					 struct bnx2x_ilt *ilt,
-					 struct ilt_client_info *ilt_cli,
-					 u8 initop)
-{
-	int i;
-
-	if (ilt_cli->flags & ILT_CLIENT_SKIP_INIT)
-		return;
-
-	for (i = ilt_cli->start; i <= ilt_cli->end; i++)
-		bnx2x_ilt_line_init_op(bp, ilt, i, initop);
-
-	/* init/clear the ILT boundries */
-	bnx2x_ilt_boundry_init_op(bp, ilt_cli, ilt->start_line, initop);
-}
-
-static void bnx2x_ilt_client_init_op(struct bnx2x *bp,
-				     struct ilt_client_info *ilt_cli, u8 initop)
-{
-	struct bnx2x_ilt *ilt = BP_ILT(bp);
-
-	bnx2x_ilt_client_init_op_ilt(bp, ilt, ilt_cli, initop);
-}
-
-static void bnx2x_ilt_client_id_init_op(struct bnx2x *bp,
-					int cli_num, u8 initop)
-{
-	struct bnx2x_ilt *ilt = BP_ILT(bp);
-	struct ilt_client_info *ilt_cli = &ilt->clients[cli_num];
-
-	bnx2x_ilt_client_init_op(bp, ilt_cli, initop);
-}
-
-static void bnx2x_ilt_init_op(struct bnx2x *bp, u8 initop)
-{
-	bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_CDU, initop);
-	bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_QM, initop);
-	bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop);
-	bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_TM, initop);
-}
-
-static void bnx2x_ilt_init_client_psz(struct bnx2x *bp, int cli_num,
-				      u32 psz_reg, u8 initop)
-{
-	struct bnx2x_ilt *ilt = BP_ILT(bp);
-	struct ilt_client_info *ilt_cli = &ilt->clients[cli_num];
-
-	if (ilt_cli->flags & ILT_CLIENT_SKIP_INIT)
-		return;
-
-	switch (initop) {
-	case INITOP_INIT:
-		/* set in the init-value array */
-	case INITOP_SET:
-		REG_WR(bp, psz_reg, ILOG2(ilt_cli->page_size >> 12));
-		break;
-	case INITOP_CLEAR:
-		break;
-	}
-}
-
-/*
- * called during init common stage, ilt clients should be initialized
- * prioir to calling this function
- */
-static void bnx2x_ilt_init_page_size(struct bnx2x *bp, u8 initop)
-{
-	bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_CDU,
-				  PXP2_REG_RQ_CDU_P_SIZE, initop);
-	bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_QM,
-				  PXP2_REG_RQ_QM_P_SIZE, initop);
-	bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_SRC,
-				  PXP2_REG_RQ_SRC_P_SIZE, initop);
-	bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_TM,
-				  PXP2_REG_RQ_TM_P_SIZE, initop);
-}
-
-/****************************************************************************
-* QM initializations
-****************************************************************************/
-#define QM_QUEUES_PER_FUNC	16 /* E1 has 32, but only 16 are used */
-#define QM_INIT_MIN_CID_COUNT	31
-#define QM_INIT(cid_cnt)	(cid_cnt > QM_INIT_MIN_CID_COUNT)
-
-/* called during init port stage */
-static void bnx2x_qm_init_cid_count(struct bnx2x *bp, int qm_cid_count,
-				    u8 initop)
-{
-	int port = BP_PORT(bp);
-
-	if (QM_INIT(qm_cid_count)) {
-		switch (initop) {
-		case INITOP_INIT:
-			/* set in the init-value array */
-		case INITOP_SET:
-			REG_WR(bp, QM_REG_CONNNUM_0 + port*4,
-			       qm_cid_count/16 - 1);
-			break;
-		case INITOP_CLEAR:
-			break;
-		}
-	}
-}
-
-static void bnx2x_qm_set_ptr_table(struct bnx2x *bp, int qm_cid_count)
-{
-	int i;
-	u32 wb_data[2];
-
-	wb_data[0] = wb_data[1] = 0;
-
-	for (i = 0; i < 4 * QM_QUEUES_PER_FUNC; i++) {
-		REG_WR(bp, QM_REG_BASEADDR + i*4,
-		       qm_cid_count * 4 * (i % QM_QUEUES_PER_FUNC));
-		bnx2x_init_ind_wr(bp, QM_REG_PTRTBL + i*8,
-				  wb_data, 2);
-
-		if (CHIP_IS_E1H(bp)) {
-			REG_WR(bp, QM_REG_BASEADDR_EXT_A + i*4,
-			       qm_cid_count * 4 * (i % QM_QUEUES_PER_FUNC));
-			bnx2x_init_ind_wr(bp, QM_REG_PTRTBL_EXT_A + i*8,
-					  wb_data, 2);
-		}
-	}
-}
-
-/* called during init common stage */
-static void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count,
-				    u8 initop)
-{
-	if (!QM_INIT(qm_cid_count))
-		return;
-
-	switch (initop) {
-	case INITOP_INIT:
-		/* set in the init-value array */
-	case INITOP_SET:
-		bnx2x_qm_set_ptr_table(bp, qm_cid_count);
-		break;
-	case INITOP_CLEAR:
-		break;
-	}
-}
-
-/****************************************************************************
-* SRC initializations
-****************************************************************************/
-#ifdef BCM_CNIC
-/* called during init func stage */
-static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
-			      dma_addr_t t2_mapping, int src_cid_count)
-{
-	int i;
-	int port = BP_PORT(bp);
-
-	/* Initialize T2 */
-	for (i = 0; i < src_cid_count-1; i++)
-		t2[i].next = (u64)(t2_mapping +
-			     (i+1)*sizeof(struct src_ent));
-
-	/* tell the searcher where the T2 table is */
-	REG_WR(bp, SRC_REG_COUNTFREE0 + port*4, src_cid_count);
-
-	bnx2x_wr_64(bp, SRC_REG_FIRSTFREE0 + port*16,
-		    U64_LO(t2_mapping), U64_HI(t2_mapping));
-
-	bnx2x_wr_64(bp, SRC_REG_LASTFREE0 + port*16,
-		    U64_LO((u64)t2_mapping +
-			   (src_cid_count-1) * sizeof(struct src_ent)),
-		    U64_HI((u64)t2_mapping +
-			   (src_cid_count-1) * sizeof(struct src_ent)));
-}
-#endif
-#endif /* BNX2X_INIT_OPS_H */
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_link.c linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_link.c
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_link.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_link.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,12472 +0,0 @@
-/* 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
- * under the terms of the GNU General Public License version 2, available
- * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
- *
- * Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a
- * license other than the GPL, without Broadcom's express prior written
- * consent.
- *
- * Written by Yaniv Rosner
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/delay.h>
-#include <linux/ethtool.h>
-#include <linux/mutex.h>
-
-#include "bnx2x.h"
-#include "bnx2x_cmn.h"
-
-
-/********************************************************/
-#define ETH_HLEN			14
-/* 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 WC_LANE_MAX			4
-#define I2C_SWITCH_WIDTH		2
-#define I2C_BSC0			0
-#define I2C_BSC1			1
-#define I2C_WA_RETRY_CNT		3
-#define MCPR_IMC_COMMAND_READ_OP	1
-#define MCPR_IMC_COMMAND_WRITE_OP	2
-
-/***********************************************************/
-/*			Shortcut definitions		   */
-/***********************************************************/
-
-#define NIG_LATCH_BC_ENABLE_MI_INT 0
-
-#define NIG_STATUS_EMAC0_MI_INT \
-		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_MI_INT
-#define NIG_STATUS_XGXS0_LINK10G \
-		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G
-#define NIG_STATUS_XGXS0_LINK_STATUS \
-		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS
-#define NIG_STATUS_XGXS0_LINK_STATUS_SIZE \
-		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE
-#define NIG_STATUS_SERDES0_LINK_STATUS \
-		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS
-#define NIG_MASK_MI_INT \
-		NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT
-#define NIG_MASK_XGXS0_LINK10G \
-		NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G
-#define NIG_MASK_XGXS0_LINK_STATUS \
-		NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK_STATUS
-#define NIG_MASK_SERDES0_LINK_STATUS \
-		NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS
-
-#define MDIO_AN_CL73_OR_37_COMPLETE \
-		(MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | \
-		 MDIO_GP_STATUS_TOP_AN_STATUS1_CL37_AUTONEG_COMPLETE)
-
-#define XGXS_RESET_BITS \
-	(MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_RSTB_HW |   \
-	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_IDDQ |      \
-	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN |    \
-	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN_SD | \
-	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_TXD_FIFO_RSTB)
-
-#define SERDES_RESET_BITS \
-	(MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_RSTB_HW | \
-	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_IDDQ |    \
-	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN |  \
-	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN_SD)
-
-#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_PARALLEL \
-				SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION
-#define AUTONEG_SGMII_FIBER_AUTODET \
-				SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT
-#define AUTONEG_REMOTE_PHY	SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY
-
-#define GP_STATUS_PAUSE_RSOLUTION_TXSIDE \
-			MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_TXSIDE
-#define GP_STATUS_PAUSE_RSOLUTION_RXSIDE \
-			MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_RXSIDE
-#define GP_STATUS_SPEED_MASK \
-			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_MASK
-#define GP_STATUS_10M	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10M
-#define GP_STATUS_100M	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_100M
-#define GP_STATUS_1G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G
-#define GP_STATUS_2_5G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_2_5G
-#define GP_STATUS_5G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_5G
-#define GP_STATUS_6G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_6G
-#define GP_STATUS_10G_HIG \
-			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_HIG
-#define GP_STATUS_10G_CX4 \
-			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_CX4
-#define GP_STATUS_1G_KX MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX
-#define GP_STATUS_10G_KX4 \
-			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4
-#define	GP_STATUS_10G_KR MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KR
-#define	GP_STATUS_10G_XFI   MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI
-#define	GP_STATUS_20G_DXGXS MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS
-#define	GP_STATUS_10G_SFI   MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI
-#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_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
-#define LINK_1000XFD		LINK_STATUS_SPEED_AND_DUPLEX_1000XFD
-#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_20GTFD		LINK_STATUS_SPEED_AND_DUPLEX_20GTFD
-#define LINK_20GXFD		LINK_STATUS_SPEED_AND_DUPLEX_20GXFD
-
-
-
-/* */
-#define SFP_EEPROM_CON_TYPE_ADDR		0x2
-	#define SFP_EEPROM_CON_TYPE_VAL_LC	0x7
-	#define SFP_EEPROM_CON_TYPE_VAL_COPPER	0x21
-
-
-#define SFP_EEPROM_COMP_CODE_ADDR		0x3
-	#define SFP_EEPROM_COMP_CODE_SR_MASK	(1<<4)
-	#define SFP_EEPROM_COMP_CODE_LR_MASK	(1<<5)
-	#define SFP_EEPROM_COMP_CODE_LRM_MASK	(1<<6)
-
-#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_OPTIONS_ADDR			0x40
-	#define SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK 0x1
-#define SFP_EEPROM_OPTIONS_SIZE			2
-
-#define EDC_MODE_LINEAR				0x0022
-#define EDC_MODE_LIMITING				0x0044
-#define EDC_MODE_PASSIVE_DAC			0x0055
-
-
-/* BRB thresholds for E2*/
-#define PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE		170
-#define PFC_E2_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE		0
-
-#define PFC_E2_BRB_MAC_PAUSE_XON_THR_PAUSE		250
-#define PFC_E2_BRB_MAC_PAUSE_XON_THR_NON_PAUSE		0
-
-#define PFC_E2_BRB_MAC_FULL_XOFF_THR_PAUSE		10
-#define PFC_E2_BRB_MAC_FULL_XOFF_THR_NON_PAUSE		90
-
-#define PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE			50
-#define PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE		250
-
-/* BRB thresholds for E3A0 */
-#define PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE		290
-#define PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE		0
-
-#define PFC_E3A0_BRB_MAC_PAUSE_XON_THR_PAUSE		410
-#define PFC_E3A0_BRB_MAC_PAUSE_XON_THR_NON_PAUSE		0
-
-#define PFC_E3A0_BRB_MAC_FULL_XOFF_THR_PAUSE		10
-#define PFC_E3A0_BRB_MAC_FULL_XOFF_THR_NON_PAUSE		170
-
-#define PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE		50
-#define PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE		410
-
-
-/* BRB thresholds for E3B0 2 port mode*/
-#define PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_PAUSE		1025
-#define PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE	0
-
-#define PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_PAUSE		1025
-#define PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE	0
-
-#define PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_PAUSE		10
-#define PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE	1025
-
-#define PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_PAUSE		50
-#define PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_NON_PAUSE	1025
-
-/* only for E3B0*/
-#define PFC_E3B0_2P_BRB_FULL_LB_XOFF_THR			1025
-#define PFC_E3B0_2P_BRB_FULL_LB_XON_THR			1025
-
-/* Lossy +Lossless GUARANTIED == GUART */
-#define PFC_E3B0_2P_MIX_PAUSE_LB_GUART			284
-/* Lossless +Lossless*/
-#define PFC_E3B0_2P_PAUSE_LB_GUART			236
-/* Lossy +Lossy*/
-#define PFC_E3B0_2P_NON_PAUSE_LB_GUART			342
-
-/* Lossy +Lossless*/
-#define PFC_E3B0_2P_MIX_PAUSE_MAC_0_CLASS_T_GUART		284
-/* Lossless +Lossless*/
-#define PFC_E3B0_2P_PAUSE_MAC_0_CLASS_T_GUART		236
-/* Lossy +Lossy*/
-#define PFC_E3B0_2P_NON_PAUSE_MAC_0_CLASS_T_GUART		336
-#define PFC_E3B0_2P_BRB_MAC_0_CLASS_T_GUART_HYST		80
-
-#define PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART		0
-#define PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART_HYST		0
-
-/* BRB thresholds for E3B0 4 port mode */
-#define PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_PAUSE		304
-#define PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE	0
-
-#define PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_PAUSE		384
-#define PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE	0
-
-#define PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_PAUSE		10
-#define PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE	304
-
-#define PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_PAUSE		50
-#define PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_NON_PAUSE	384
-
-
-/* only for E3B0*/
-#define PFC_E3B0_4P_BRB_FULL_LB_XOFF_THR			304
-#define PFC_E3B0_4P_BRB_FULL_LB_XON_THR			384
-#define PFC_E3B0_4P_LB_GUART				120
-
-#define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART		120
-#define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST		80
-
-#define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART		80
-#define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST		120
-
-#define DCBX_INVALID_COS					(0xFF)
-
-#define ETS_BW_LIMIT_CREDIT_UPPER_BOUND		(0x5000)
-#define ETS_BW_LIMIT_CREDIT_WEIGHT		(0x5000)
-#define ETS_E3B0_NIG_MIN_W_VAL_UP_TO_10GBPS		(1360)
-#define ETS_E3B0_NIG_MIN_W_VAL_20GBPS			(2720)
-#define ETS_E3B0_PBF_MIN_W_VAL				(10000)
-
-#define MAX_PACKET_SIZE					(9700)
-#define WC_UC_TIMEOUT					100
-
-/**********************************************************/
-/*                     INTERFACE                          */
-/**********************************************************/
-
-#define CL22_WR_OVER_CL45(_bp, _phy, _bank, _addr, _val) \
-	bnx2x_cl45_write(_bp, _phy, \
-		(_phy)->def_md_devad, \
-		(_bank + (_addr & 0xf)), \
-		_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 u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits)
-{
-	u32 val = REG_RD(bp, reg);
-
-	val |= bits;
-	REG_WR(bp, reg, val);
-	return val;
-}
-
-static u32 bnx2x_bits_dis(struct bnx2x *bp, u32 reg, u32 bits)
-{
-	u32 val = REG_RD(bp, reg);
-
-	val &= ~bits;
-	REG_WR(bp, reg, val);
-	return val;
-}
-
-/******************************************************************/
-/*			EPIO/GPIO section			  */
-/******************************************************************/
-static void bnx2x_get_epio(struct bnx2x *bp, u32 epio_pin, u32 *en)
-{
-	u32 epio_mask, gp_oenable;
-	*en = 0;
-	/* Sanity check */
-	if (epio_pin > 31) {
-		DP(NETIF_MSG_LINK, "Invalid EPIO pin %d to get\n", epio_pin);
-		return;
-	}
-
-	epio_mask = 1 << epio_pin;
-	/* Set this EPIO to output */
-	gp_oenable = REG_RD(bp, MCP_REG_MCPR_GP_OENABLE);
-	REG_WR(bp, MCP_REG_MCPR_GP_OENABLE, gp_oenable & ~epio_mask);
-
-	*en = (REG_RD(bp, MCP_REG_MCPR_GP_INPUTS) & epio_mask) >> epio_pin;
-}
-static void bnx2x_set_epio(struct bnx2x *bp, u32 epio_pin, u32 en)
-{
-	u32 epio_mask, gp_output, gp_oenable;
-
-	/* Sanity check */
-	if (epio_pin > 31) {
-		DP(NETIF_MSG_LINK, "Invalid EPIO pin %d to set\n", epio_pin);
-		return;
-	}
-	DP(NETIF_MSG_LINK, "Setting EPIO pin %d to %d\n", epio_pin, en);
-	epio_mask = 1 << epio_pin;
-	/* Set this EPIO to output */
-	gp_output = REG_RD(bp, MCP_REG_MCPR_GP_OUTPUTS);
-	if (en)
-		gp_output |= epio_mask;
-	else
-		gp_output &= ~epio_mask;
-
-	REG_WR(bp, MCP_REG_MCPR_GP_OUTPUTS, gp_output);
-
-	/* Set the value for this EPIO */
-	gp_oenable = REG_RD(bp, MCP_REG_MCPR_GP_OENABLE);
-	REG_WR(bp, MCP_REG_MCPR_GP_OENABLE, gp_oenable | epio_mask);
-}
-
-static void bnx2x_set_cfg_pin(struct bnx2x *bp, u32 pin_cfg, u32 val)
-{
-	if (pin_cfg == PIN_CFG_NA)
-		return;
-	if (pin_cfg >= PIN_CFG_EPIO0) {
-		bnx2x_set_epio(bp, pin_cfg - PIN_CFG_EPIO0, val);
-	} else {
-		u8 gpio_num = (pin_cfg - PIN_CFG_GPIO0_P0) & 0x3;
-		u8 gpio_port = (pin_cfg - PIN_CFG_GPIO0_P0) >> 2;
-		bnx2x_set_gpio(bp, gpio_num, (u8)val, gpio_port);
-	}
-}
-
-static u32 bnx2x_get_cfg_pin(struct bnx2x *bp, u32 pin_cfg, u32 *val)
-{
-	if (pin_cfg == PIN_CFG_NA)
-		return -EINVAL;
-	if (pin_cfg >= PIN_CFG_EPIO0) {
-		bnx2x_get_epio(bp, pin_cfg - PIN_CFG_EPIO0, val);
-	} else {
-		u8 gpio_num = (pin_cfg - PIN_CFG_GPIO0_P0) & 0x3;
-		u8 gpio_port = (pin_cfg - PIN_CFG_GPIO0_P0) >> 2;
-		*val = bnx2x_get_gpio(bp, gpio_num, gpio_port);
-	}
-	return 0;
-
-}
-/******************************************************************/
-/*				ETS section			  */
-/******************************************************************/
-static void bnx2x_ets_e2e3a0_disabled(struct link_params *params)
-{
-	/* ETS disabled configuration*/
-	struct bnx2x *bp = params->bp;
-
-	DP(NETIF_MSG_LINK, "ETS E2E3 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.
-	 *   PRI4    |    PRI3    |    PRI2    |    PRI1    |    PRI0
-	 * cos1-100     cos0-011     dbg1-010     dbg0-001     MCP-000
-	 */
-
-	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.
-	 * COS1 | COS0 | DEBUG1 | DEBUG0 | MGMT
-	 * bit4   bit3	  bit2   bit1	  bit0
-	 * MCP and debug are strict
-	 */
-
-	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.
-	 */
-	REG_WR(bp, NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
-	/*
-	 * mapping between the CREDIT_WEIGHT registers and actual client
-	 * numbers
-	 */
-	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP, 0);
-	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, 0);
-	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1, 0);
-
-	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0, 0);
-	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1, 0);
-	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.
-	 */
-	REG_WR(bp, PBF_REG_COS0_WEIGHT, 0x2710);
-	REG_WR(bp, PBF_REG_COS1_WEIGHT, 0x2710);
-	/* Upper bound that COS0_WEIGHT can reach in the WFQ arbiter */
-	REG_WR(bp, PBF_REG_COS0_UPPER_BOUND, 0x989680);
-	REG_WR(bp, PBF_REG_COS1_UPPER_BOUND, 0x989680);
-	/* Defines the number of consecutive slots for the strict priority */
-	REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
-}
-/******************************************************************************
-* Description:
-*	Getting min_w_val will be set according to line speed .
-*.
-******************************************************************************/
-static u32 bnx2x_ets_get_min_w_val_nig(const struct link_vars *vars)
-{
-	u32 min_w_val = 0;
-	/* Calculate min_w_val.*/
-	if (vars->link_up) {
-		if (SPEED_20000 == vars->line_speed)
-			min_w_val = ETS_E3B0_NIG_MIN_W_VAL_20GBPS;
-		else
-			min_w_val = ETS_E3B0_NIG_MIN_W_VAL_UP_TO_10GBPS;
-	} else
-		min_w_val = ETS_E3B0_NIG_MIN_W_VAL_20GBPS;
-	/**
-	 *  If the link isn't up (static configuration for example ) The
-	 *  link will be according to 20GBPS.
-	*/
-	return min_w_val;
-}
-/******************************************************************************
-* Description:
-*	Getting credit upper bound form min_w_val.
-*.
-******************************************************************************/
-static u32 bnx2x_ets_get_credit_upper_bound(const u32 min_w_val)
-{
-	const u32 credit_upper_bound = (u32)MAXVAL((150 * min_w_val),
-						MAX_PACKET_SIZE);
-	return credit_upper_bound;
-}
-/******************************************************************************
-* Description:
-*	Set credit upper bound for NIG.
-*.
-******************************************************************************/
-static void bnx2x_ets_e3b0_set_credit_upper_bound_nig(
-	const struct link_params *params,
-	const u32 min_w_val)
-{
-	struct bnx2x *bp = params->bp;
-	const u8 port = params->port;
-	const u32 credit_upper_bound =
-	    bnx2x_ets_get_credit_upper_bound(min_w_val);
-
-	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_0 :
-		NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0, credit_upper_bound);
-	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_1 :
-		   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1, credit_upper_bound);
-	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_2 :
-		   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_2, credit_upper_bound);
-	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_3 :
-		   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_3, credit_upper_bound);
-	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_4 :
-		   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_4, credit_upper_bound);
-	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_5 :
-		   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_5, credit_upper_bound);
-
-	if (0 == port) {
-		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_6,
-			credit_upper_bound);
-		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_7,
-			credit_upper_bound);
-		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_8,
-			credit_upper_bound);
-	}
-}
-/******************************************************************************
-* Description:
-*	Will return the NIG ETS registers to init values.Except
-*	credit_upper_bound.
-*	That isn't used in this configuration (No WFQ is enabled) and will be
-*	configured acording to spec
-*.
-******************************************************************************/
-static void bnx2x_ets_e3b0_nig_disabled(const struct link_params *params,
-					const struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	const u8 port = params->port;
-	const u32 min_w_val = bnx2x_ets_get_min_w_val_nig(vars);
-	/**
-	 * mapping between entry  priority to client number (0,1,2 -debug and
-	 * management clients, 3 - COS0 client, 4 - COS1, ... 8 -
-	 * COS5)(HIGHEST) 4bits client num.TODO_ETS - Should be done by
-	 * reset value or init tool
-	 */
-	if (port) {
-		REG_WR(bp, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB, 0x543210);
-		REG_WR(bp, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB, 0x0);
-	} else {
-		REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB, 0x76543210);
-		REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB, 0x8);
-	}
-	/**
-	* For strict priority entries defines the number of consecutive
-	* slots for the highest priority.
-	*/
-	/* TODO_ETS - Should be done by reset value or init tool */
-	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS :
-		   NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
-	/**
-	 * mapping between the CREDIT_WEIGHT registers and actual client
-	 * numbers
-	 */
-	/* TODO_ETS - Should be done by reset value or init tool */
-	if (port) {
-		/*Port 1 has 6 COS*/
-		REG_WR(bp, NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_LSB, 0x210543);
-		REG_WR(bp, NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_MSB, 0x0);
-	} else {
-		/*Port 0 has 9 COS*/
-		REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_LSB,
-		       0x43210876);
-		REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_MSB, 0x5);
-	}
-
-	/**
-	 * 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 | DEBUG1 | DEBUG0 | MGMT
-	 * bit4   bit3	  bit2   bit1	  bit0
-	 * MCP and debug are strict
-	 */
-	if (port)
-		REG_WR(bp, NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT, 0x3f);
-	else
-		REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x1ff);
-	/* defines which entries (clients) are subjected to WFQ arbitration */
-	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ :
-		   NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0);
-
-	/**
-	* Please notice the register address are note continuous and a
-	* for here is note appropriate.In 2 port mode port0 only COS0-5
-	* can be used. DEBUG1,DEBUG1,MGMT are never used for WFQ* In 4
-	* port mode port1 only COS0-2 can be used. DEBUG1,DEBUG1,MGMT
-	* are never used for WFQ
-	*/
-	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 :
-		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, 0x0);
-	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 :
-		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1, 0x0);
-	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 :
-		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2, 0x0);
-	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_3 :
-		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3, 0x0);
-	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_4 :
-		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4, 0x0);
-	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_5 :
-		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5, 0x0);
-	if (0 == port) {
-		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_6, 0x0);
-		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_7, 0x0);
-		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_8, 0x0);
-	}
-
-	bnx2x_ets_e3b0_set_credit_upper_bound_nig(params, min_w_val);
-}
-/******************************************************************************
-* Description:
-*	Set credit upper bound for PBF.
-*.
-******************************************************************************/
-static void bnx2x_ets_e3b0_set_credit_upper_bound_pbf(
-	const struct link_params *params,
-	const u32 min_w_val)
-{
-	struct bnx2x *bp = params->bp;
-	const u32 credit_upper_bound =
-	    bnx2x_ets_get_credit_upper_bound(min_w_val);
-	const u8 port = params->port;
-	u32 base_upper_bound = 0;
-	u8 max_cos = 0;
-	u8 i = 0;
-	/**
-	* In 2 port mode port0 has COS0-5 that can be used for WFQ.In 4
-	* port mode port1 has COS0-2 that can be used for WFQ.
-	*/
-	if (0 == port) {
-		base_upper_bound = PBF_REG_COS0_UPPER_BOUND_P0;
-		max_cos = DCBX_E3B0_MAX_NUM_COS_PORT0;
-	} else {
-		base_upper_bound = PBF_REG_COS0_UPPER_BOUND_P1;
-		max_cos = DCBX_E3B0_MAX_NUM_COS_PORT1;
-	}
-
-	for (i = 0; i < max_cos; i++)
-		REG_WR(bp, base_upper_bound + (i << 2), credit_upper_bound);
-}
-
-/******************************************************************************
-* Description:
-*	Will return the PBF ETS registers to init values.Except
-*	credit_upper_bound.
-*	That isn't used in this configuration (No WFQ is enabled) and will be
-*	configured acording to spec
-*.
-******************************************************************************/
-static void bnx2x_ets_e3b0_pbf_disabled(const struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	const u8 port = params->port;
-	const u32 min_w_val_pbf = ETS_E3B0_PBF_MIN_W_VAL;
-	u8 i = 0;
-	u32 base_weight = 0;
-	u8 max_cos = 0;
-
-	/**
-	 * mapping between entry  priority to client number 0 - COS0
-	 * client, 2 - COS1, ... 5 - COS5)(HIGHEST) 4bits client num.
-	 * TODO_ETS - Should be done by reset value or init tool
-	 */
-	if (port)
-		/*  0x688 (|011|0 10|00 1|000) */
-		REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1 , 0x688);
-	else
-		/*  (10 1|100 |011|0 10|00 1|000) */
-		REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0 , 0x2C688);
-
-	/* TODO_ETS - Should be done by reset value or init tool */
-	if (port)
-		/* 0x688 (|011|0 10|00 1|000)*/
-		REG_WR(bp, PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P1, 0x688);
-	else
-	/* 0x2C688 (10 1|100 |011|0 10|00 1|000) */
-	REG_WR(bp, PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P0, 0x2C688);
-
-	REG_WR(bp, (port) ? PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P1 :
-		   PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P0 , 0x100);
-
-
-	REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1 :
-		   PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0 , 0);
-
-	REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1 :
-		   PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0 , 0);
-	/**
-	* In 2 port mode port0 has COS0-5 that can be used for WFQ.
-	* In 4 port mode port1 has COS0-2 that can be used for WFQ.
-	*/
-	if (0 == port) {
-		base_weight = PBF_REG_COS0_WEIGHT_P0;
-		max_cos = DCBX_E3B0_MAX_NUM_COS_PORT0;
-	} else {
-		base_weight = PBF_REG_COS0_WEIGHT_P1;
-		max_cos = DCBX_E3B0_MAX_NUM_COS_PORT1;
-	}
-
-	for (i = 0; i < max_cos; i++)
-		REG_WR(bp, base_weight + (0x4 * i), 0);
-
-	bnx2x_ets_e3b0_set_credit_upper_bound_pbf(params, min_w_val_pbf);
-}
-/******************************************************************************
-* Description:
-*	E3B0 disable will return basicly the values to init values.
-*.
-******************************************************************************/
-static int bnx2x_ets_e3b0_disabled(const struct link_params *params,
-				   const struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-
-	if (!CHIP_IS_E3B0(bp)) {
-		DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_disabled the chip isn't E3B0"
-				   "\n");
-		return -EINVAL;
-	}
-
-	bnx2x_ets_e3b0_nig_disabled(params, vars);
-
-	bnx2x_ets_e3b0_pbf_disabled(params);
-
-	return 0;
-}
-
-/******************************************************************************
-* Description:
-*	Disable will return basicly the values to init values.
-*.
-******************************************************************************/
-int bnx2x_ets_disabled(struct link_params *params,
-		      struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	int bnx2x_status = 0;
-
-	if ((CHIP_IS_E2(bp)) || (CHIP_IS_E3A0(bp)))
-		bnx2x_ets_e2e3a0_disabled(params);
-	else if (CHIP_IS_E3B0(bp))
-		bnx2x_status = bnx2x_ets_e3b0_disabled(params, vars);
-	else {
-		DP(NETIF_MSG_LINK, "bnx2x_ets_disabled - chip not supported\n");
-		return -EINVAL;
-	}
-
-	return bnx2x_status;
-}
-
-/******************************************************************************
-* Description
-*	Set the COS mappimg to SP and BW until this point all the COS are not
-*	set as SP or BW.
-******************************************************************************/
-static int bnx2x_ets_e3b0_cli_map(const struct link_params *params,
-				  const struct bnx2x_ets_params *ets_params,
-				  const u8 cos_sp_bitmap,
-				  const u8 cos_bw_bitmap)
-{
-	struct bnx2x *bp = params->bp;
-	const u8 port = params->port;
-	const u8 nig_cli_sp_bitmap = 0x7 | (cos_sp_bitmap << 3);
-	const u8 pbf_cli_sp_bitmap = cos_sp_bitmap;
-	const u8 nig_cli_subject2wfq_bitmap = cos_bw_bitmap << 3;
-	const u8 pbf_cli_subject2wfq_bitmap = cos_bw_bitmap;
-
-	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT :
-	       NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, nig_cli_sp_bitmap);
-
-	REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1 :
-	       PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0 , pbf_cli_sp_bitmap);
-
-	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ :
-	       NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ,
-	       nig_cli_subject2wfq_bitmap);
-
-	REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1 :
-	       PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0,
-	       pbf_cli_subject2wfq_bitmap);
-
-	return 0;
-}
-
-/******************************************************************************
-* Description:
-*	This function is needed because NIG ARB_CREDIT_WEIGHT_X are
-*	not continues and ARB_CREDIT_WEIGHT_0 + offset is suitable.
-******************************************************************************/
-static int bnx2x_ets_e3b0_set_cos_bw(struct bnx2x *bp,
-				     const u8 cos_entry,
-				     const u32 min_w_val_nig,
-				     const u32 min_w_val_pbf,
-				     const u16 total_bw,
-				     const u8 bw,
-				     const u8 port)
-{
-	u32 nig_reg_adress_crd_weight = 0;
-	u32 pbf_reg_adress_crd_weight = 0;
-	/* Calculate and set BW for this COS - use 1 instead of 0 for BW */
-	const u32 cos_bw_nig = ((bw ? bw : 1) * min_w_val_nig) / total_bw;
-	const u32 cos_bw_pbf = ((bw ? bw : 1) * min_w_val_pbf) / total_bw;
-
-	switch (cos_entry) {
-	case 0:
-	    nig_reg_adress_crd_weight =
-		 (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 :
-		     NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0;
-	     pbf_reg_adress_crd_weight = (port) ?
-		 PBF_REG_COS0_WEIGHT_P1 : PBF_REG_COS0_WEIGHT_P0;
-	     break;
-	case 1:
-	     nig_reg_adress_crd_weight = (port) ?
-		 NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 :
-		 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1;
-	     pbf_reg_adress_crd_weight = (port) ?
-		 PBF_REG_COS1_WEIGHT_P1 : PBF_REG_COS1_WEIGHT_P0;
-	     break;
-	case 2:
-	     nig_reg_adress_crd_weight = (port) ?
-		 NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 :
-		 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2;
-
-		 pbf_reg_adress_crd_weight = (port) ?
-		     PBF_REG_COS2_WEIGHT_P1 : PBF_REG_COS2_WEIGHT_P0;
-	     break;
-	case 3:
-	    if (port)
-			return -EINVAL;
-	     nig_reg_adress_crd_weight =
-		 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3;
-	     pbf_reg_adress_crd_weight =
-		 PBF_REG_COS3_WEIGHT_P0;
-	     break;
-	case 4:
-	    if (port)
-		return -EINVAL;
-	     nig_reg_adress_crd_weight =
-		 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4;
-	     pbf_reg_adress_crd_weight = PBF_REG_COS4_WEIGHT_P0;
-	     break;
-	case 5:
-	    if (port)
-		return -EINVAL;
-	     nig_reg_adress_crd_weight =
-		 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5;
-	     pbf_reg_adress_crd_weight = PBF_REG_COS5_WEIGHT_P0;
-	     break;
-	}
-
-	REG_WR(bp, nig_reg_adress_crd_weight, cos_bw_nig);
-
-	REG_WR(bp, pbf_reg_adress_crd_weight, cos_bw_pbf);
-
-	return 0;
-}
-/******************************************************************************
-* Description:
-*	Calculate the total BW.A value of 0 isn't legal.
-*.
-******************************************************************************/
-static int bnx2x_ets_e3b0_get_total_bw(
-	const struct link_params *params,
-	const struct bnx2x_ets_params *ets_params,
-	u16 *total_bw)
-{
-	struct bnx2x *bp = params->bp;
-	u8 cos_idx = 0;
-
-	*total_bw = 0 ;
-	/* Calculate total BW requested */
-	for (cos_idx = 0; cos_idx < ets_params->num_of_cos; cos_idx++) {
-		if (bnx2x_cos_state_bw == ets_params->cos[cos_idx].state) {
-			*total_bw +=
-				ets_params->cos[cos_idx].params.bw_params.bw;
-		}
-	}
-
-	/* Check total BW is valid */
-	if ((100 != *total_bw) || (0 == *total_bw)) {
-		if (0 == *total_bw) {
-			DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config toatl BW"
-					   "shouldn't be 0\n");
-			return -EINVAL;
-		}
-		DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config toatl BW should be"
-				   "100\n");
-		/**
-		*   We can handle a case whre the BW isn't 100 this can happen
-		*   if the TC are joined.
-		*/
-	}
-	return 0;
-}
-
-/******************************************************************************
-* Description:
-*	Invalidate all the sp_pri_to_cos.
-*.
-******************************************************************************/
-static void bnx2x_ets_e3b0_sp_pri_to_cos_init(u8 *sp_pri_to_cos)
-{
-	u8 pri = 0;
-	for (pri = 0; pri < DCBX_MAX_NUM_COS; pri++)
-		sp_pri_to_cos[pri] = DCBX_INVALID_COS;
-}
-/******************************************************************************
-* Description:
-*	Calculate and set the SP (ARB_PRIORITY_CLIENT) NIG and PBF registers
-*	according to sp_pri_to_cos.
-*.
-******************************************************************************/
-static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params,
-					    u8 *sp_pri_to_cos, const u8 pri,
-					    const u8 cos_entry)
-{
-	struct bnx2x *bp = params->bp;
-	const u8 port = params->port;
-	const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
-		DCBX_E3B0_MAX_NUM_COS_PORT0;
-
-	if (DCBX_INVALID_COS != sp_pri_to_cos[pri]) {
-		DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
-				   "parameter There can't be two COS's with"
-				   "the same strict pri\n");
-		return -EINVAL;
-	}
-
-	if (pri > max_num_of_cos) {
-		DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid"
-			       "parameter Illegal strict priority\n");
-	    return -EINVAL;
-	}
-
-	sp_pri_to_cos[pri] = cos_entry;
-	return 0;
-
-}
-
-/******************************************************************************
-* Description:
-*	Returns the correct value according to COS and priority in
-*	the sp_pri_cli register.
-*.
-******************************************************************************/
-static u64 bnx2x_e3b0_sp_get_pri_cli_reg(const u8 cos, const u8 cos_offset,
-					 const u8 pri_set,
-					 const u8 pri_offset,
-					 const u8 entry_size)
-{
-	u64 pri_cli_nig = 0;
-	pri_cli_nig = ((u64)(cos + cos_offset)) << (entry_size *
-						    (pri_set + pri_offset));
-
-	return pri_cli_nig;
-}
-/******************************************************************************
-* Description:
-*	Returns the correct value according to COS and priority in the
-*	sp_pri_cli register for NIG.
-*.
-******************************************************************************/
-static u64 bnx2x_e3b0_sp_get_pri_cli_reg_nig(const u8 cos, const u8 pri_set)
-{
-	/* MCP Dbg0 and dbg1 are always with higher strict pri*/
-	const u8 nig_cos_offset = 3;
-	const u8 nig_pri_offset = 3;
-
-	return bnx2x_e3b0_sp_get_pri_cli_reg(cos, nig_cos_offset, pri_set,
-		nig_pri_offset, 4);
-
-}
-/******************************************************************************
-* Description:
-*	Returns the correct value according to COS and priority in the
-*	sp_pri_cli register for PBF.
-*.
-******************************************************************************/
-static u64 bnx2x_e3b0_sp_get_pri_cli_reg_pbf(const u8 cos, const u8 pri_set)
-{
-	const u8 pbf_cos_offset = 0;
-	const u8 pbf_pri_offset = 0;
-
-	return bnx2x_e3b0_sp_get_pri_cli_reg(cos, pbf_cos_offset, pri_set,
-		pbf_pri_offset, 3);
-
-}
-
-/******************************************************************************
-* Description:
-*	Calculate and set the SP (ARB_PRIORITY_CLIENT) NIG and PBF registers
-*	according to sp_pri_to_cos.(which COS has higher priority)
-*.
-******************************************************************************/
-static int bnx2x_ets_e3b0_sp_set_pri_cli_reg(const struct link_params *params,
-					     u8 *sp_pri_to_cos)
-{
-	struct bnx2x *bp = params->bp;
-	u8 i = 0;
-	const u8 port = params->port;
-	/* MCP Dbg0 and dbg1 are always with higher strict pri*/
-	u64 pri_cli_nig = 0x210;
-	u32 pri_cli_pbf = 0x0;
-	u8 pri_set = 0;
-	u8 pri_bitmask = 0;
-	const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
-		DCBX_E3B0_MAX_NUM_COS_PORT0;
-
-	u8 cos_bit_to_set = (1 << max_num_of_cos) - 1;
-
-	/* Set all the strict priority first */
-	for (i = 0; i < max_num_of_cos; i++) {
-		if (DCBX_INVALID_COS != sp_pri_to_cos[i]) {
-			if (DCBX_MAX_NUM_COS <= sp_pri_to_cos[i]) {
-				DP(NETIF_MSG_LINK,
-					   "bnx2x_ets_e3b0_sp_set_pri_cli_reg "
-					   "invalid cos entry\n");
-				return -EINVAL;
-			}
-
-			pri_cli_nig |= bnx2x_e3b0_sp_get_pri_cli_reg_nig(
-			    sp_pri_to_cos[i], pri_set);
-
-			pri_cli_pbf |= bnx2x_e3b0_sp_get_pri_cli_reg_pbf(
-			    sp_pri_to_cos[i], pri_set);
-			pri_bitmask = 1 << sp_pri_to_cos[i];
-			/* COS is used remove it from bitmap.*/
-			if (0 == (pri_bitmask & cos_bit_to_set)) {
-				DP(NETIF_MSG_LINK,
-					"bnx2x_ets_e3b0_sp_set_pri_cli_reg "
-					"invalid There can't be two COS's with"
-					" the same strict pri\n");
-				return -EINVAL;
-			}
-			cos_bit_to_set &= ~pri_bitmask;
-			pri_set++;
-		}
-	}
-
-	/* Set all the Non strict priority i= COS*/
-	for (i = 0; i < max_num_of_cos; i++) {
-		pri_bitmask = 1 << i;
-		/* Check if COS was already used for SP */
-		if (pri_bitmask & cos_bit_to_set) {
-			/* COS wasn't used for SP */
-			pri_cli_nig |= bnx2x_e3b0_sp_get_pri_cli_reg_nig(
-			    i, pri_set);
-
-			pri_cli_pbf |= bnx2x_e3b0_sp_get_pri_cli_reg_pbf(
-			    i, pri_set);
-			/* COS is used remove it from bitmap.*/
-			cos_bit_to_set &= ~pri_bitmask;
-			pri_set++;
-		}
-	}
-
-	if (pri_set != max_num_of_cos) {
-		DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_set_pri_cli_reg not all "
-				   "entries were set\n");
-		return -EINVAL;
-	}
-
-	if (port) {
-		/* Only 6 usable clients*/
-		REG_WR(bp, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB,
-		       (u32)pri_cli_nig);
-
-		REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1 , pri_cli_pbf);
-	} else {
-		/* Only 9 usable clients*/
-		const u32 pri_cli_nig_lsb = (u32) (pri_cli_nig);
-		const u32 pri_cli_nig_msb = (u32) ((pri_cli_nig >> 32) & 0xF);
-
-		REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB,
-		       pri_cli_nig_lsb);
-		REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB,
-		       pri_cli_nig_msb);
-
-		REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0 , pri_cli_pbf);
-	}
-	return 0;
-}
-
-/******************************************************************************
-* Description:
-*	Configure the COS to ETS according to BW and SP settings.
-******************************************************************************/
-int bnx2x_ets_e3b0_config(const struct link_params *params,
-			 const struct link_vars *vars,
-			 const struct bnx2x_ets_params *ets_params)
-{
-	struct bnx2x *bp = params->bp;
-	int bnx2x_status = 0;
-	const u8 port = params->port;
-	u16 total_bw = 0;
-	const u32 min_w_val_nig = bnx2x_ets_get_min_w_val_nig(vars);
-	const u32 min_w_val_pbf = ETS_E3B0_PBF_MIN_W_VAL;
-	u8 cos_bw_bitmap = 0;
-	u8 cos_sp_bitmap = 0;
-	u8 sp_pri_to_cos[DCBX_MAX_NUM_COS] = {0};
-	const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
-		DCBX_E3B0_MAX_NUM_COS_PORT0;
-	u8 cos_entry = 0;
-
-	if (!CHIP_IS_E3B0(bp)) {
-		DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_disabled the chip isn't E3B0"
-				   "\n");
-		return -EINVAL;
-	}
-
-	if ((ets_params->num_of_cos > max_num_of_cos)) {
-		DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config the number of COS "
-				   "isn't supported\n");
-		return -EINVAL;
-	}
-
-	/* Prepare sp strict priority parameters*/
-	bnx2x_ets_e3b0_sp_pri_to_cos_init(sp_pri_to_cos);
-
-	/* Prepare BW parameters*/
-	bnx2x_status = bnx2x_ets_e3b0_get_total_bw(params, ets_params,
-						   &total_bw);
-	if (0 != bnx2x_status) {
-		DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config get_total_bw failed "
-				   "\n");
-		return -EINVAL;
-	}
-
-	/**
-	 *  Upper bound is set according to current link speed (min_w_val
-	 *  should be the same for upper bound and COS credit val).
-	 */
-	bnx2x_ets_e3b0_set_credit_upper_bound_nig(params, min_w_val_nig);
-	bnx2x_ets_e3b0_set_credit_upper_bound_pbf(params, min_w_val_pbf);
-
-
-	for (cos_entry = 0; cos_entry < ets_params->num_of_cos; cos_entry++) {
-		if (bnx2x_cos_state_bw == ets_params->cos[cos_entry].state) {
-			cos_bw_bitmap |= (1 << cos_entry);
-			/**
-			 * The function also sets the BW in HW(not the mappin
-			 * yet)
-			 */
-			bnx2x_status = bnx2x_ets_e3b0_set_cos_bw(
-				bp, cos_entry, min_w_val_nig, min_w_val_pbf,
-				total_bw,
-				ets_params->cos[cos_entry].params.bw_params.bw,
-				 port);
-		} else if (bnx2x_cos_state_strict ==
-			ets_params->cos[cos_entry].state){
-			cos_sp_bitmap |= (1 << cos_entry);
-
-			bnx2x_status = bnx2x_ets_e3b0_sp_pri_to_cos_set(
-				params,
-				sp_pri_to_cos,
-				ets_params->cos[cos_entry].params.sp_params.pri,
-				cos_entry);
-
-		} else {
-			DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_config cos state not"
-					   " valid\n");
-			return -EINVAL;
-		}
-		if (0 != bnx2x_status) {
-			DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_config set cos bw "
-					   "failed\n");
-			return bnx2x_status;
-		}
-	}
-
-	/* Set SP register (which COS has higher priority) */
-	bnx2x_status = bnx2x_ets_e3b0_sp_set_pri_cli_reg(params,
-							 sp_pri_to_cos);
-
-	if (0 != bnx2x_status) {
-		DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config set_pri_cli_reg "
-				   "failed\n");
-		return bnx2x_status;
-	}
-
-	/* Set client mapping of BW and strict */
-	bnx2x_status = bnx2x_ets_e3b0_cli_map(params, ets_params,
-					      cos_sp_bitmap,
-					      cos_bw_bitmap);
-
-	if (0 != bnx2x_status) {
-		DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config SP failed\n");
-		return bnx2x_status;
-	}
-	return 0;
-}
-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
-	 */
-	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
-	 */
-	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP, 0x111A);
-
-	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0,
-	       ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
-	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1,
-	       ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
-
-	/* ETS mode enabled*/
-	REG_WR(bp, PBF_REG_ETS_ENABLED, 1);
-
-	/* 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
-	 */
-	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x7);
-
-	/* Upper bound that COS0_WEIGHT can reach in the WFQ arbiter.*/
-	REG_WR(bp, PBF_REG_COS0_UPPER_BOUND,
-	       ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
-	REG_WR(bp, PBF_REG_COS1_UPPER_BOUND,
-	       ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
-}
-
-void bnx2x_ets_bw_limit(const struct link_params *params, const u32 cos0_bw,
-			const u32 cos1_bw)
-{
-	/* ETS disabled configuration*/
-	struct bnx2x *bp = params->bp;
-	const u32 total_bw = cos0_bw + cos1_bw;
-	u32 cos0_credit_weight = 0;
-	u32 cos1_credit_weight = 0;
-
-	DP(NETIF_MSG_LINK, "ETS enabled BW limit configuration\n");
-
-	if ((0 == total_bw) ||
-	    (0 == cos0_bw) ||
-	    (0 == cos1_bw)) {
-		DP(NETIF_MSG_LINK, "Total BW can't be zero\n");
-		return;
-	}
-
-	cos0_credit_weight = (cos0_bw * ETS_BW_LIMIT_CREDIT_WEIGHT)/
-		total_bw;
-	cos1_credit_weight = (cos1_bw * ETS_BW_LIMIT_CREDIT_WEIGHT)/
-		total_bw;
-
-	bnx2x_ets_bw_limit_common(params);
-
-	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, cos0_credit_weight);
-	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1, cos1_credit_weight);
-
-	REG_WR(bp, PBF_REG_COS0_WEIGHT, cos0_credit_weight);
-	REG_WR(bp, PBF_REG_COS1_WEIGHT, cos1_credit_weight);
-}
-
-int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
-{
-	/* ETS disabled configuration*/
-	struct bnx2x *bp = params->bp;
-	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.
-	 *  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, 0x1F);
-	/*
-	 * 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);
-	/* ETS mode disable */
-	REG_WR(bp, PBF_REG_ETS_ENABLED, 0);
-	/* Defines the number of consecutive slots for the strict priority */
-	REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0x100);
-
-	/* 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
-	 */
-	val = (0 == strict_cos) ? 0x2318 : 0x22E0;
-	REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT, val);
-
-	return 0;
-}
-/******************************************************************/
-/*			PFC section				  */
-/******************************************************************/
-
-static void bnx2x_update_pfc_xmac(struct link_params *params,
-				  struct link_vars *vars,
-				  u8 is_lb)
-{
-	struct bnx2x *bp = params->bp;
-	u32 xmac_base;
-	u32 pause_val, pfc0_val, pfc1_val;
-
-	/* XMAC base adrr */
-	xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
-
-	/* Initialize pause and pfc registers */
-	pause_val = 0x18000;
-	pfc0_val = 0xFFFF8000;
-	pfc1_val = 0x2;
-
-	/* No PFC support */
-	if (!(params->feature_config_flags &
-	      FEATURE_CONFIG_PFC_ENABLED)) {
-
-		/*
-		 * RX flow control - Process pause frame in receive direction
-		 */
-		if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
-			pause_val |= XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN;
-
-		/*
-		 * TX flow control - Send pause packet when buffer is full
-		 */
-		if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
-			pause_val |= XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN;
-	} else {/* PFC support */
-		pfc1_val |= XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN |
-			XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN |
-			XMAC_PFC_CTRL_HI_REG_RX_PFC_EN |
-			XMAC_PFC_CTRL_HI_REG_TX_PFC_EN;
-	}
-
-	/* Write pause and PFC registers */
-	REG_WR(bp, xmac_base + XMAC_REG_PAUSE_CTRL, pause_val);
-	REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL, pfc0_val);
-	REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI, pfc1_val);
-
-
-	/* Set MAC address for source TX Pause/PFC frames */
-	REG_WR(bp, xmac_base + XMAC_REG_CTRL_SA_LO,
-	       ((params->mac_addr[2] << 24) |
-		(params->mac_addr[3] << 16) |
-		(params->mac_addr[4] << 8) |
-		(params->mac_addr[5])));
-	REG_WR(bp, xmac_base + XMAC_REG_CTRL_SA_HI,
-	       ((params->mac_addr[0] << 8) |
-		(params->mac_addr[1])));
-
-	udelay(30);
-}
-
-
-static void bnx2x_emac_get_pfc_stat(struct link_params *params,
-				    u32 pfc_frames_sent[2],
-				    u32 pfc_frames_received[2])
-{
-	/* Read pfc statistic */
-	struct bnx2x *bp = params->bp;
-	u32 emac_base = params->port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-	u32 val_xon = 0;
-	u32 val_xoff = 0;
-
-	DP(NETIF_MSG_LINK, "pfc statistic read from EMAC\n");
-
-	/* PFC received frames */
-	val_xoff = REG_RD(bp, emac_base +
-				EMAC_REG_RX_PFC_STATS_XOFF_RCVD);
-	val_xoff &= EMAC_REG_RX_PFC_STATS_XOFF_RCVD_COUNT;
-	val_xon = REG_RD(bp, emac_base + EMAC_REG_RX_PFC_STATS_XON_RCVD);
-	val_xon &= EMAC_REG_RX_PFC_STATS_XON_RCVD_COUNT;
-
-	pfc_frames_received[0] = val_xon + val_xoff;
-
-	/* PFC received sent */
-	val_xoff = REG_RD(bp, emac_base +
-				EMAC_REG_RX_PFC_STATS_XOFF_SENT);
-	val_xoff &= EMAC_REG_RX_PFC_STATS_XOFF_SENT_COUNT;
-	val_xon = REG_RD(bp, emac_base + EMAC_REG_RX_PFC_STATS_XON_SENT);
-	val_xon &= EMAC_REG_RX_PFC_STATS_XON_SENT_COUNT;
-
-	pfc_frames_sent[0] = val_xon + val_xoff;
-}
-
-/* Read pfc statistic*/
-void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
-			 u32 pfc_frames_sent[2],
-			 u32 pfc_frames_received[2])
-{
-	/* Read pfc statistic */
-	struct bnx2x *bp = params->bp;
-
-	DP(NETIF_MSG_LINK, "pfc statistic\n");
-
-	if (!vars->link_up)
-		return;
-
-	if (MAC_TYPE_EMAC == vars->mac_type) {
-		DP(NETIF_MSG_LINK, "About to read PFC stats from EMAC\n");
-		bnx2x_emac_get_pfc_stat(params, pfc_frames_sent,
-					pfc_frames_received);
-	}
-}
-/******************************************************************/
-/*			MAC/PBF section				  */
-/******************************************************************/
-static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id, u8 port)
-{
-	u32 mode, emac_base;
-	/**
-	 * 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
-	 */
-
-	if (CHIP_IS_E2(bp))
-		emac_base = GRCBASE_EMAC0;
-	else
-		emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-	mode = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
-	mode &= ~(EMAC_MDIO_MODE_AUTO_POLL |
-		  EMAC_MDIO_MODE_CLOCK_CNT);
-	if (USES_WARPCORE(bp))
-		mode |= (74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
-	else
-		mode |= (49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
-
-	mode |= (EMAC_MDIO_MODE_CLAUSE_45);
-	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE, mode);
-
-	udelay(40);
-}
-
-static void bnx2x_emac_init(struct link_params *params,
-			    struct link_vars *vars)
-{
-	/* reset and unreset the emac core */
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-	u32 val;
-	u16 timeout;
-
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-	       (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));
-
-	/* init emac - use read-modify-write */
-	/* self clear reset */
-	val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
-	EMAC_WR(bp, EMAC_REG_EMAC_MODE, (val | EMAC_MODE_RESET));
-
-	timeout = 200;
-	do {
-		val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
-		DP(NETIF_MSG_LINK, "EMAC reset reg is %u\n", val);
-		if (!timeout) {
-			DP(NETIF_MSG_LINK, "EMAC timeout!\n");
-			return;
-		}
-		timeout--;
-	} while (val & EMAC_MODE_RESET);
-	bnx2x_set_mdio_clk(bp, params->chip_id, port);
-	/* Set mac address */
-	val = ((params->mac_addr[0] << 8) |
-		params->mac_addr[1]);
-	EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH, val);
-
-	val = ((params->mac_addr[2] << 24) |
-	       (params->mac_addr[3] << 16) |
-	       (params->mac_addr[4] << 8) |
-		params->mac_addr[5]);
-	EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + 4, val);
-}
-
-static void bnx2x_set_xumac_nig(struct link_params *params,
-				u16 tx_pause_en,
-				u8 enable)
-{
-	struct bnx2x *bp = params->bp;
-
-	REG_WR(bp, params->port ? NIG_REG_P1_MAC_IN_EN : NIG_REG_P0_MAC_IN_EN,
-	       enable);
-	REG_WR(bp, params->port ? NIG_REG_P1_MAC_OUT_EN : NIG_REG_P0_MAC_OUT_EN,
-	       enable);
-	REG_WR(bp, params->port ? NIG_REG_P1_MAC_PAUSE_OUT_EN :
-	       NIG_REG_P0_MAC_PAUSE_OUT_EN, tx_pause_en);
-}
-
-static void bnx2x_umac_enable(struct link_params *params,
-			    struct link_vars *vars, u8 lb)
-{
-	u32 val;
-	u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
-	struct bnx2x *bp = params->bp;
-	/* Reset UMAC */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-	       (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port));
-	usleep_range(1000, 1000);
-
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
-	       (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port));
-
-	DP(NETIF_MSG_LINK, "enabling UMAC\n");
-
-	/**
-	 * This register determines on which events the MAC will assert
-	 * error on the i/f to the NIG along w/ EOP.
-	 */
-
-	/**
-	 * BD REG_WR(bp, NIG_REG_P0_MAC_RSV_ERR_MASK +
-	 * params->port*0x14,      0xfffff.
-	 */
-	/* This register opens the gate for the UMAC despite its name */
-	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 1);
-
-	val = UMAC_COMMAND_CONFIG_REG_PROMIS_EN |
-		UMAC_COMMAND_CONFIG_REG_PAD_EN |
-		UMAC_COMMAND_CONFIG_REG_SW_RESET |
-		UMAC_COMMAND_CONFIG_REG_NO_LGTH_CHECK;
-	switch (vars->line_speed) {
-	case SPEED_10:
-		val |= (0<<2);
-		break;
-	case SPEED_100:
-		val |= (1<<2);
-		break;
-	case SPEED_1000:
-		val |= (2<<2);
-		break;
-	case SPEED_2500:
-		val |= (3<<2);
-		break;
-	default:
-		DP(NETIF_MSG_LINK, "Invalid speed for UMAC %d\n",
-			       vars->line_speed);
-		break;
-	}
-	if (!(vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
-		val |= UMAC_COMMAND_CONFIG_REG_IGNORE_TX_PAUSE;
-
-	if (!(vars->flow_ctrl & BNX2X_FLOW_CTRL_RX))
-		val |= UMAC_COMMAND_CONFIG_REG_PAUSE_IGNORE;
-
-	REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
-	udelay(50);
-
-	/* Set MAC address for source TX Pause/PFC frames (under SW reset) */
-	REG_WR(bp, umac_base + UMAC_REG_MAC_ADDR0,
-	       ((params->mac_addr[2] << 24) |
-		(params->mac_addr[3] << 16) |
-		(params->mac_addr[4] << 8) |
-		(params->mac_addr[5])));
-	REG_WR(bp, umac_base + UMAC_REG_MAC_ADDR1,
-	       ((params->mac_addr[0] << 8) |
-		(params->mac_addr[1])));
-
-	/* Enable RX and TX */
-	val &= ~UMAC_COMMAND_CONFIG_REG_PAD_EN;
-	val |= UMAC_COMMAND_CONFIG_REG_TX_ENA |
-		UMAC_COMMAND_CONFIG_REG_RX_ENA;
-	REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
-	udelay(50);
-
-	/* Remove SW Reset */
-	val &= ~UMAC_COMMAND_CONFIG_REG_SW_RESET;
-
-	/* Check loopback mode */
-	if (lb)
-		val |= UMAC_COMMAND_CONFIG_REG_LOOP_ENA;
-	REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
-
-	/*
-	 * Maximum Frame Length (RW). Defines a 14-Bit maximum frame
-	 * length used by the MAC receive logic to check frames.
-	 */
-	REG_WR(bp, umac_base + UMAC_REG_MAXFR, 0x2710);
-	bnx2x_set_xumac_nig(params,
-			    ((vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) != 0), 1);
-	vars->mac_type = MAC_TYPE_UMAC;
-
-}
-
-static u8 bnx2x_is_4_port_mode(struct bnx2x *bp)
-{
-	u32 port4mode_ovwr_val;
-	/* Check 4-port override enabled */
-	port4mode_ovwr_val = REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR);
-	if (port4mode_ovwr_val & (1<<0)) {
-		/* Return 4-port mode override value */
-		return ((port4mode_ovwr_val & (1<<1)) == (1<<1));
-	}
-	/* Return 4-port mode from input pin */
-	return (u8)REG_RD(bp, MISC_REG_PORT4MODE_EN);
-}
-
-/* Define the XMAC mode */
-static void bnx2x_xmac_init(struct bnx2x *bp, u32 max_speed)
-{
-	u32 is_port4mode = bnx2x_is_4_port_mode(bp);
-
-	/**
-	* In 4-port mode, need to set the mode only once, so if XMAC is
-	* already out of reset, it means the mode has already been set,
-	* and it must not* reset the XMAC again, since it controls both
-	* ports of the path
-	**/
-
-	if (is_port4mode && (REG_RD(bp, MISC_REG_RESET_REG_2) &
-	     MISC_REGISTERS_RESET_REG_2_XMAC)) {
-		DP(NETIF_MSG_LINK, "XMAC already out of reset"
-				   " in 4-port mode\n");
-		return;
-	}
-
-	/* Hard reset */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-	       MISC_REGISTERS_RESET_REG_2_XMAC);
-	usleep_range(1000, 1000);
-
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
-	       MISC_REGISTERS_RESET_REG_2_XMAC);
-	if (is_port4mode) {
-		DP(NETIF_MSG_LINK, "Init XMAC to 2 ports x 10G per path\n");
-
-		/*  Set the number of ports on the system side to up to 2 */
-		REG_WR(bp, MISC_REG_XMAC_CORE_PORT_MODE, 1);
-
-		/* Set the number of ports on the Warp Core to 10G */
-		REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 3);
-	} else {
-		/*  Set the number of ports on the system side to 1 */
-		REG_WR(bp, MISC_REG_XMAC_CORE_PORT_MODE, 0);
-		if (max_speed == SPEED_10000) {
-			DP(NETIF_MSG_LINK, "Init XMAC to 10G x 1"
-					   " port per path\n");
-			/* Set the number of ports on the Warp Core to 10G */
-			REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 3);
-		} else {
-			DP(NETIF_MSG_LINK, "Init XMAC to 20G x 2 ports"
-					   " per path\n");
-			/* Set the number of ports on the Warp Core to 20G */
-			REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 1);
-		}
-	}
-	/* Soft reset */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-	       MISC_REGISTERS_RESET_REG_2_XMAC_SOFT);
-	usleep_range(1000, 1000);
-
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
-	       MISC_REGISTERS_RESET_REG_2_XMAC_SOFT);
-
-}
-
-static void bnx2x_xmac_disable(struct link_params *params)
-{
-	u8 port = params->port;
-	struct bnx2x *bp = params->bp;
-	u32 pfc_ctrl, xmac_base = (port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
-
-	if (REG_RD(bp, MISC_REG_RESET_REG_2) &
-	    MISC_REGISTERS_RESET_REG_2_XMAC) {
-		/*
-		 * Send an indication to change the state in the NIG back to XON
-		 * Clearing this bit enables the next set of this bit to get
-		 * rising edge
-		 */
-		pfc_ctrl = REG_RD(bp, xmac_base + XMAC_REG_PFC_CTRL_HI);
-		REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI,
-		       (pfc_ctrl & ~(1<<1)));
-		REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI,
-		       (pfc_ctrl | (1<<1)));
-		DP(NETIF_MSG_LINK, "Disable XMAC on port %x\n", port);
-		REG_WR(bp, xmac_base + XMAC_REG_CTRL, 0);
-		usleep_range(1000, 1000);
-		bnx2x_set_xumac_nig(params, 0, 0);
-		REG_WR(bp, xmac_base + XMAC_REG_CTRL,
-		       XMAC_CTRL_REG_SOFT_RESET);
-	}
-}
-
-static int bnx2x_xmac_enable(struct link_params *params,
-			     struct link_vars *vars, u8 lb)
-{
-	u32 val, xmac_base;
-	struct bnx2x *bp = params->bp;
-	DP(NETIF_MSG_LINK, "enabling XMAC\n");
-
-	xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
-
-	bnx2x_xmac_init(bp, vars->line_speed);
-
-	/*
-	 * This register determines on which events the MAC will assert
-	 * error on the i/f to the NIG along w/ EOP.
-	 */
-
-	/*
-	 * This register tells the NIG whether to send traffic to UMAC
-	 * or XMAC
-	 */
-	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 0);
-
-	/* Set Max packet size */
-	REG_WR(bp, xmac_base + XMAC_REG_RX_MAX_SIZE, 0x2710);
-
-	/* CRC append for Tx packets */
-	REG_WR(bp, xmac_base + XMAC_REG_TX_CTRL, 0xC800);
-
-	/* update PFC */
-	bnx2x_update_pfc_xmac(params, vars, 0);
-
-	/* Enable TX and RX */
-	val = XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN;
-
-	/* Check loopback mode */
-	if (lb)
-		val |= XMAC_CTRL_REG_LINE_LOCAL_LPBK;
-	REG_WR(bp, xmac_base + XMAC_REG_CTRL, val);
-	bnx2x_set_xumac_nig(params,
-			    ((vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) != 0), 1);
-
-	vars->mac_type = MAC_TYPE_XMAC;
-
-	return 0;
-}
-static int bnx2x_emac_enable(struct link_params *params,
-			     struct link_vars *vars, u8 lb)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-	u32 val;
-
-	DP(NETIF_MSG_LINK, "enabling EMAC\n");
-
-	/* Disable BMAC */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
-
-	/* enable emac and not bmac */
-	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1);
-
-	/* 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);
-
-		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);
-		/* select XGXS */
-		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);
-	}
-
-	bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
-		      EMAC_RX_MODE_RESET);
-	bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
-		      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));
-	} else { /* ASIC */
-		/* pause enable/disable */
-		bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
-			       EMAC_RX_MODE_FLOW_EN);
-
-		bnx2x_bits_dis(bp,  emac_base + EMAC_REG_EMAC_TX_MODE,
-			       (EMAC_TX_MODE_EXT_PAUSE_EN |
-				EMAC_TX_MODE_FLOW_EN));
-		if (!(params->feature_config_flags &
-		      FEATURE_CONFIG_PFC_ENABLED)) {
-			if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
-				bnx2x_bits_en(bp, emac_base +
-					      EMAC_REG_EMAC_RX_MODE,
-					      EMAC_RX_MODE_FLOW_EN);
-
-			if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
-				bnx2x_bits_en(bp, emac_base +
-					      EMAC_REG_EMAC_TX_MODE,
-					      (EMAC_TX_MODE_EXT_PAUSE_EN |
-					       EMAC_TX_MODE_FLOW_EN));
-		} else
-			bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
-				      EMAC_TX_MODE_FLOW_EN);
-	}
-
-	/* KEEP_VLAN_TAG, promiscuous */
-	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.
-	 */
-	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");
-		/* Enable PFC again */
-		EMAC_WR(bp, EMAC_REG_RX_PFC_MODE,
-			EMAC_REG_RX_PFC_MODE_RX_EN |
-			EMAC_REG_RX_PFC_MODE_TX_EN |
-			EMAC_REG_RX_PFC_MODE_PRIORITIES);
-
-		EMAC_WR(bp, EMAC_REG_RX_PFC_PARAM,
-			((0x0101 <<
-			  EMAC_REG_RX_PFC_PARAM_OPCODE_BITSHIFT) |
-			 (0x00ff <<
-			  EMAC_REG_RX_PFC_PARAM_PRIORITY_EN_BITSHIFT)));
-		val |= EMAC_RX_MODE_KEEP_MAC_CONTROL;
-	}
-	EMAC_WR(bp, EMAC_REG_EMAC_RX_MODE, val);
-
-	/* Set Loopback */
-	val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
-	if (lb)
-		val |= 0x810;
-	else
-		val &= ~0x810;
-	EMAC_WR(bp, EMAC_REG_EMAC_MODE, val);
-
-	/* enable emac */
-	REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 1);
-
-	/* enable emac for jumbo packets */
-	EMAC_WR(bp, EMAC_REG_EMAC_RX_MTU_SIZE,
-		(EMAC_RX_MTU_SIZE_JUMBO_ENA |
-		 (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD)));
-
-	/* strip CRC */
-	REG_WR(bp, NIG_REG_NIG_INGRESS_EMAC0_NO_CRC + port*4, 0x1);
-
-	/* disable the NIG in/out to the bmac */
-	REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x0);
-	REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, 0x0);
-	REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x0);
-
-	/* enable the NIG in/out to the emac */
-	REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x1);
-	val = 0;
-	if ((params->feature_config_flags &
-	      FEATURE_CONFIG_PFC_ENABLED) ||
-	    (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
-		val = 1;
-
-	REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, val);
-	REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x1);
-
-	REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x0);
-
-	vars->mac_type = MAC_TYPE_EMAC;
-	return 0;
-}
-
-static void bnx2x_update_pfc_bmac1(struct link_params *params,
-				   struct link_vars *vars)
-{
-	u32 wb_data[2];
-	struct bnx2x *bp = params->bp;
-	u32 bmac_addr =  params->port ? NIG_REG_INGRESS_BMAC1_MEM :
-		NIG_REG_INGRESS_BMAC0_MEM;
-
-	u32 val = 0x14;
-	if ((!(params->feature_config_flags &
-	      FEATURE_CONFIG_PFC_ENABLED)) &&
-		(vars->flow_ctrl & BNX2X_FLOW_CTRL_RX))
-		/* Enable BigMAC to react on received Pause packets */
-		val |= (1<<5);
-	wb_data[0] = val;
-	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_CONTROL, wb_data, 2);
-
-	/* tx control */
-	val = 0xc0;
-	if (!(params->feature_config_flags &
-	      FEATURE_CONFIG_PFC_ENABLED) &&
-		(vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
-		val |= 0x800000;
-	wb_data[0] = val;
-	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_CONTROL, wb_data, 2);
-}
-
-static void bnx2x_update_pfc_bmac2(struct link_params *params,
-				   struct link_vars *vars,
-				   u8 is_lb)
-{
-	/*
-	 * Set rx control: Strip CRC and enable BigMAC to relay
-	 * control packets to the system as well
-	 */
-	u32 wb_data[2];
-	struct bnx2x *bp = params->bp;
-	u32 bmac_addr = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
-		NIG_REG_INGRESS_BMAC0_MEM;
-	u32 val = 0x14;
-
-	if ((!(params->feature_config_flags &
-	      FEATURE_CONFIG_PFC_ENABLED)) &&
-		(vars->flow_ctrl & BNX2X_FLOW_CTRL_RX))
-		/* Enable BigMAC to react on received Pause packets */
-		val |= (1<<5);
-	wb_data[0] = val;
-	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_CONTROL, wb_data, 2);
-	udelay(30);
-
-	/* Tx control */
-	val = 0xc0;
-	if (!(params->feature_config_flags &
-				FEATURE_CONFIG_PFC_ENABLED) &&
-	    (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
-		val |= 0x800000;
-	wb_data[0] = val;
-	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_CONTROL, wb_data, 2);
-
-	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED) {
-		DP(NETIF_MSG_LINK, "PFC is enabled\n");
-		/* Enable PFC RX & TX & STATS and set 8 COS  */
-		wb_data[0] = 0x0;
-		wb_data[0] |= (1<<0);  /* RX */
-		wb_data[0] |= (1<<1);  /* TX */
-		wb_data[0] |= (1<<2);  /* Force initial Xon */
-		wb_data[0] |= (1<<3);  /* 8 cos */
-		wb_data[0] |= (1<<5);  /* STATS */
-		wb_data[1] = 0;
-		REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_PFC_CONTROL,
-			    wb_data, 2);
-		/* Clear the force Xon */
-		wb_data[0] &= ~(1<<2);
-	} else {
-		DP(NETIF_MSG_LINK, "PFC is disabled\n");
-		/* disable PFC RX & TX & STATS and set 8 COS */
-		wb_data[0] = 0x8;
-		wb_data[1] = 0;
-	}
-
-	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.
-	 */
-	val = 0x8000;
-	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
-		val |= (1<<16); /* enable automatic re-send */
-
-	wb_data[0] = val;
-	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_PAUSE_CONTROL,
-		    wb_data, 2);
-
-	/* mac control */
-	val = 0x3; /* Enable RX and TX */
-	if (is_lb) {
-		val |= 0x4; /* Local loopback */
-		DP(NETIF_MSG_LINK, "enable bmac loopback\n");
-	}
-	/* When PFC enabled, Pass pause frames towards the NIG. */
-	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
-		val |= ((1<<6)|(1<<5));
-
-	wb_data[0] = val;
-	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2);
-}
-
-
-/* PFC BRB internal port configuration params */
-struct bnx2x_pfc_brb_threshold_val {
-	u32 pause_xoff;
-	u32 pause_xon;
-	u32 full_xoff;
-	u32 full_xon;
-};
-
-struct bnx2x_pfc_brb_e3b0_val {
-	u32 full_lb_xoff_th;
-	u32 full_lb_xon_threshold;
-	u32 lb_guarantied;
-	u32 mac_0_class_t_guarantied;
-	u32 mac_0_class_t_guarantied_hyst;
-	u32 mac_1_class_t_guarantied;
-	u32 mac_1_class_t_guarantied_hyst;
-};
-
-struct bnx2x_pfc_brb_th_val {
-	struct bnx2x_pfc_brb_threshold_val pauseable_th;
-	struct bnx2x_pfc_brb_threshold_val non_pauseable_th;
-};
-static int bnx2x_pfc_brb_get_config_params(
-				struct link_params *params,
-				struct bnx2x_pfc_brb_th_val *config_val)
-{
-	struct bnx2x *bp = params->bp;
-	DP(NETIF_MSG_LINK, "Setting PFC BRB configuration\n");
-	if (CHIP_IS_E2(bp)) {
-		config_val->pauseable_th.pause_xoff =
-		    PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
-		config_val->pauseable_th.pause_xon =
-		    PFC_E2_BRB_MAC_PAUSE_XON_THR_PAUSE;
-		config_val->pauseable_th.full_xoff =
-		    PFC_E2_BRB_MAC_FULL_XOFF_THR_PAUSE;
-		config_val->pauseable_th.full_xon =
-		    PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE;
-		/* non pause able*/
-		config_val->non_pauseable_th.pause_xoff =
-		    PFC_E2_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
-		config_val->non_pauseable_th.pause_xon =
-		    PFC_E2_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
-		config_val->non_pauseable_th.full_xoff =
-		    PFC_E2_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
-		config_val->non_pauseable_th.full_xon =
-		    PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE;
-	} else if (CHIP_IS_E3A0(bp)) {
-		config_val->pauseable_th.pause_xoff =
-		    PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
-		config_val->pauseable_th.pause_xon =
-		    PFC_E3A0_BRB_MAC_PAUSE_XON_THR_PAUSE;
-		config_val->pauseable_th.full_xoff =
-		    PFC_E3A0_BRB_MAC_FULL_XOFF_THR_PAUSE;
-		config_val->pauseable_th.full_xon =
-		    PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE;
-		/* non pause able*/
-		config_val->non_pauseable_th.pause_xoff =
-		    PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
-		config_val->non_pauseable_th.pause_xon =
-		    PFC_E3A0_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
-		config_val->non_pauseable_th.full_xoff =
-		    PFC_E3A0_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
-		config_val->non_pauseable_th.full_xon =
-		    PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE;
-	} else if (CHIP_IS_E3B0(bp)) {
-		if (params->phy[INT_PHY].flags &
-		    FLAGS_4_PORT_MODE) {
-			config_val->pauseable_th.pause_xoff =
-			    PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
-			config_val->pauseable_th.pause_xon =
-			    PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_PAUSE;
-			config_val->pauseable_th.full_xoff =
-			    PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_PAUSE;
-			config_val->pauseable_th.full_xon =
-			    PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_PAUSE;
-			/* non pause able*/
-			config_val->non_pauseable_th.pause_xoff =
-			    PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
-			config_val->non_pauseable_th.pause_xon =
-			    PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
-			config_val->non_pauseable_th.full_xoff =
-			    PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
-			config_val->non_pauseable_th.full_xon =
-			    PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_NON_PAUSE;
-	    } else {
-		config_val->pauseable_th.pause_xoff =
-		    PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
-		config_val->pauseable_th.pause_xon =
-		    PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_PAUSE;
-		config_val->pauseable_th.full_xoff =
-		    PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_PAUSE;
-		config_val->pauseable_th.full_xon =
-			PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_PAUSE;
-		/* non pause able*/
-		config_val->non_pauseable_th.pause_xoff =
-		    PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
-		config_val->non_pauseable_th.pause_xon =
-		    PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
-		config_val->non_pauseable_th.full_xoff =
-		    PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
-		config_val->non_pauseable_th.full_xon =
-		    PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_NON_PAUSE;
-	    }
-	} else
-	    return -EINVAL;
-
-	return 0;
-}
-
-
-static void bnx2x_pfc_brb_get_e3b0_config_params(struct link_params *params,
-						 struct bnx2x_pfc_brb_e3b0_val
-						 *e3b0_val,
-						 u32 cos0_pauseable,
-						 u32 cos1_pauseable)
-{
-	if (params->phy[INT_PHY].flags & FLAGS_4_PORT_MODE) {
-		e3b0_val->full_lb_xoff_th =
-		    PFC_E3B0_4P_BRB_FULL_LB_XOFF_THR;
-		e3b0_val->full_lb_xon_threshold =
-		    PFC_E3B0_4P_BRB_FULL_LB_XON_THR;
-		e3b0_val->lb_guarantied =
-		    PFC_E3B0_4P_LB_GUART;
-		e3b0_val->mac_0_class_t_guarantied =
-		    PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART;
-		e3b0_val->mac_0_class_t_guarantied_hyst =
-		    PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST;
-		e3b0_val->mac_1_class_t_guarantied =
-		    PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART;
-		e3b0_val->mac_1_class_t_guarantied_hyst =
-		    PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST;
-	} else {
-		e3b0_val->full_lb_xoff_th =
-		    PFC_E3B0_2P_BRB_FULL_LB_XOFF_THR;
-		e3b0_val->full_lb_xon_threshold =
-		    PFC_E3B0_2P_BRB_FULL_LB_XON_THR;
-		e3b0_val->mac_0_class_t_guarantied_hyst =
-		    PFC_E3B0_2P_BRB_MAC_0_CLASS_T_GUART_HYST;
-		e3b0_val->mac_1_class_t_guarantied =
-		    PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART;
-		e3b0_val->mac_1_class_t_guarantied_hyst =
-		    PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART_HYST;
-
-		if (cos0_pauseable != cos1_pauseable) {
-			/* nonpauseable= Lossy + pauseable = Lossless*/
-			e3b0_val->lb_guarantied =
-			    PFC_E3B0_2P_MIX_PAUSE_LB_GUART;
-			e3b0_val->mac_0_class_t_guarantied =
-			    PFC_E3B0_2P_MIX_PAUSE_MAC_0_CLASS_T_GUART;
-		} else if (cos0_pauseable) {
-			/* Lossless +Lossless*/
-			e3b0_val->lb_guarantied =
-			    PFC_E3B0_2P_PAUSE_LB_GUART;
-			e3b0_val->mac_0_class_t_guarantied =
-			    PFC_E3B0_2P_PAUSE_MAC_0_CLASS_T_GUART;
-		} else {
-			/* Lossy +Lossy*/
-			e3b0_val->lb_guarantied =
-			    PFC_E3B0_2P_NON_PAUSE_LB_GUART;
-			e3b0_val->mac_0_class_t_guarantied =
-			    PFC_E3B0_2P_NON_PAUSE_MAC_0_CLASS_T_GUART;
-		}
-	}
-}
-static int bnx2x_update_pfc_brb(struct link_params *params,
-				struct link_vars *vars,
-				struct bnx2x_nig_brb_pfc_port_params
-				*pfc_params)
-{
-	struct bnx2x *bp = params->bp;
-	struct bnx2x_pfc_brb_th_val config_val = { {0} };
-	struct bnx2x_pfc_brb_threshold_val *reg_th_config =
-	    &config_val.pauseable_th;
-	struct bnx2x_pfc_brb_e3b0_val e3b0_val = {0};
-	int set_pfc = params->feature_config_flags &
-		FEATURE_CONFIG_PFC_ENABLED;
-	int bnx2x_status = 0;
-	u8 port = params->port;
-
-	/* default - pause configuration */
-	reg_th_config = &config_val.pauseable_th;
-	bnx2x_status = bnx2x_pfc_brb_get_config_params(params, &config_val);
-	if (0 != bnx2x_status)
-		return bnx2x_status;
-
-	if (set_pfc && pfc_params)
-		/* First COS */
-		if (!pfc_params->cos0_pauseable)
-			reg_th_config = &config_val.non_pauseable_th;
-	/*
-	 * The number of free blocks below which the pause signal to class 0
-	 * of MAC #n is asserted. n=0,1
-	 */
-	REG_WR(bp, (port) ? BRB1_REG_PAUSE_0_XOFF_THRESHOLD_1 :
-	       BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 ,
-	       reg_th_config->pause_xoff);
-	/*
-	 * 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, (port) ? BRB1_REG_PAUSE_0_XON_THRESHOLD_1 :
-	       BRB1_REG_PAUSE_0_XON_THRESHOLD_0 , reg_th_config->pause_xon);
-	/*
-	 * The number of free blocks below which the full signal to class 0
-	 * of MAC #n is asserted. n=0,1
-	 */
-	REG_WR(bp, (port) ? BRB1_REG_FULL_0_XOFF_THRESHOLD_1 :
-	       BRB1_REG_FULL_0_XOFF_THRESHOLD_0 , reg_th_config->full_xoff);
-	/*
-	 * 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, (port) ? BRB1_REG_FULL_0_XON_THRESHOLD_1 :
-	       BRB1_REG_FULL_0_XON_THRESHOLD_0 , reg_th_config->full_xon);
-
-	if (set_pfc && pfc_params) {
-		/* Second COS */
-		if (pfc_params->cos1_pauseable)
-			reg_th_config = &config_val.pauseable_th;
-		else
-			reg_th_config = &config_val.non_pauseable_th;
-		/*
-		 * The number of free blocks below which the pause signal to
-		 * class 1 of MAC #n is asserted. n=0,1
-		**/
-		REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XOFF_THRESHOLD_1 :
-		       BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0,
-		       reg_th_config->pause_xoff);
-		/*
-		 * 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, (port) ? BRB1_REG_PAUSE_1_XON_THRESHOLD_1 :
-		       BRB1_REG_PAUSE_1_XON_THRESHOLD_0,
-		       reg_th_config->pause_xon);
-		/*
-		 * The number of free blocks below which the full signal to
-		 * class 1 of MAC #n is asserted. n=0,1
-		 */
-		REG_WR(bp, (port) ? BRB1_REG_FULL_1_XOFF_THRESHOLD_1 :
-		       BRB1_REG_FULL_1_XOFF_THRESHOLD_0,
-		       reg_th_config->full_xoff);
-		/*
-		 * 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, (port) ? BRB1_REG_FULL_1_XON_THRESHOLD_1 :
-		       BRB1_REG_FULL_1_XON_THRESHOLD_0,
-		       reg_th_config->full_xon);
-
-
-		if (CHIP_IS_E3B0(bp)) {
-			/*Should be done by init tool */
-			/*
-			* BRB_empty_for_dup = BRB1_REG_BRB_EMPTY_THRESHOLD
-			* reset value
-			* 944
-			*/
-
-			/**
-			 * The hysteresis on the guarantied buffer space for the Lb port
-			 * before signaling XON.
-			 **/
-			REG_WR(bp, BRB1_REG_LB_GUARANTIED_HYST, 80);
-
-			bnx2x_pfc_brb_get_e3b0_config_params(
-			    params,
-			    &e3b0_val,
-			    pfc_params->cos0_pauseable,
-			    pfc_params->cos1_pauseable);
-			/**
-			 * The number of free blocks below which the full signal to the
-			 * LB port is asserted.
-			*/
-			REG_WR(bp, BRB1_REG_FULL_LB_XOFF_THRESHOLD,
-				   e3b0_val.full_lb_xoff_th);
-			/**
-			 * The number of free blocks above which the full signal to the
-			 * LB port is de-asserted.
-			*/
-			REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD,
-				   e3b0_val.full_lb_xon_threshold);
-			/**
-			* The number of blocks guarantied for the MAC #n port. n=0,1
-			*/
-
-			/*The number of blocks guarantied for the LB port.*/
-			REG_WR(bp, BRB1_REG_LB_GUARANTIED,
-			       e3b0_val.lb_guarantied);
-
-			/**
-			 * The number of blocks guarantied for the MAC #n port.
-			*/
-			REG_WR(bp, BRB1_REG_MAC_GUARANTIED_0,
-				   2 * e3b0_val.mac_0_class_t_guarantied);
-			REG_WR(bp, BRB1_REG_MAC_GUARANTIED_1,
-				   2 * e3b0_val.mac_1_class_t_guarantied);
-			/**
-			 * The number of blocks guarantied for class #t in MAC0. t=0,1
-			*/
-			REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED,
-			       e3b0_val.mac_0_class_t_guarantied);
-			REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED,
-			       e3b0_val.mac_0_class_t_guarantied);
-			/**
-			 * The hysteresis on the guarantied buffer space for class in
-			 * MAC0.  t=0,1
-			*/
-			REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED_HYST,
-			       e3b0_val.mac_0_class_t_guarantied_hyst);
-			REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED_HYST,
-			       e3b0_val.mac_0_class_t_guarantied_hyst);
-
-			/**
-			 * The number of blocks guarantied for class #t in MAC1.t=0,1
-			*/
-			REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED,
-			       e3b0_val.mac_1_class_t_guarantied);
-			REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED,
-			       e3b0_val.mac_1_class_t_guarantied);
-			/**
-			 * The hysteresis on the guarantied buffer space for class #t
-			* in MAC1.  t=0,1
-			*/
-			REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED_HYST,
-			       e3b0_val.mac_1_class_t_guarantied_hyst);
-			REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED_HYST,
-			       e3b0_val.mac_1_class_t_guarantied_hyst);
-
-	    }
-
-	}
-
-	return bnx2x_status;
-}
-
-/******************************************************************************
-* Description:
-*  This function is needed because NIG ARB_CREDIT_WEIGHT_X are
-*  not continues and ARB_CREDIT_WEIGHT_0 + offset is suitable.
-******************************************************************************/
-int bnx2x_pfc_nig_rx_priority_mask(struct bnx2x *bp,
-					      u8 cos_entry,
-					      u32 priority_mask, u8 port)
-{
-	u32 nig_reg_rx_priority_mask_add = 0;
-
-	switch (cos_entry) {
-	case 0:
-	     nig_reg_rx_priority_mask_add = (port) ?
-		 NIG_REG_P1_RX_COS0_PRIORITY_MASK :
-		 NIG_REG_P0_RX_COS0_PRIORITY_MASK;
-	     break;
-	case 1:
-	    nig_reg_rx_priority_mask_add = (port) ?
-		NIG_REG_P1_RX_COS1_PRIORITY_MASK :
-		NIG_REG_P0_RX_COS1_PRIORITY_MASK;
-	    break;
-	case 2:
-	    nig_reg_rx_priority_mask_add = (port) ?
-		NIG_REG_P1_RX_COS2_PRIORITY_MASK :
-		NIG_REG_P0_RX_COS2_PRIORITY_MASK;
-	    break;
-	case 3:
-	    if (port)
-		return -EINVAL;
-	    nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS3_PRIORITY_MASK;
-	    break;
-	case 4:
-	    if (port)
-		return -EINVAL;
-	    nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS4_PRIORITY_MASK;
-	    break;
-	case 5:
-	    if (port)
-		return -EINVAL;
-	    nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS5_PRIORITY_MASK;
-	    break;
-	}
-
-	REG_WR(bp, nig_reg_rx_priority_mask_add, priority_mask);
-
-	return 0;
-}
-static void bnx2x_update_mng(struct link_params *params, u32 link_status)
-{
-	struct bnx2x *bp = params->bp;
-
-	REG_WR(bp, params->shmem_base +
-	       offsetof(struct shmem_region,
-			port_mb[params->port].link_status), link_status);
-}
-
-static void bnx2x_update_pfc_nig(struct link_params *params,
-		struct link_vars *vars,
-		struct bnx2x_nig_brb_pfc_port_params *nig_params)
-{
-	u32 xcm_mask = 0, ppp_enable = 0, pause_enable = 0, llfc_out_en = 0;
-	u32 llfc_enable = 0, xcm0_out_en = 0, p0_hwpfc_enable = 0;
-	u32 pkt_priority_to_cos = 0;
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-
-	int set_pfc = params->feature_config_flags &
-		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.
-	 */
-	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
-	 */
-	if (set_pfc) {
-		pause_enable = 0;
-		llfc_out_en = 0;
-		llfc_enable = 0;
-		if (CHIP_IS_E3(bp))
-			ppp_enable = 0;
-		else
-		ppp_enable = 1;
-		xcm_mask &= ~(port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
-				     NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
-		xcm0_out_en = 0;
-		p0_hwpfc_enable = 1;
-	} else  {
-		if (nig_params) {
-			llfc_out_en = nig_params->llfc_out_en;
-			llfc_enable = nig_params->llfc_enable;
-			pause_enable = nig_params->pause_enable;
-		} else  /*defaul non PFC mode - PAUSE */
-			pause_enable = 1;
-
-		xcm_mask |= (port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
-			NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
-		xcm0_out_en = 1;
-	}
-
-	if (CHIP_IS_E3(bp))
-		REG_WR(bp, port ? NIG_REG_BRB1_PAUSE_IN_EN :
-		       NIG_REG_BRB0_PAUSE_IN_EN, pause_enable);
-	REG_WR(bp, port ? NIG_REG_LLFC_OUT_EN_1 :
-	       NIG_REG_LLFC_OUT_EN_0, llfc_out_en);
-	REG_WR(bp, port ? NIG_REG_LLFC_ENABLE_1 :
-	       NIG_REG_LLFC_ENABLE_0, llfc_enable);
-	REG_WR(bp, port ? NIG_REG_PAUSE_ENABLE_1 :
-	       NIG_REG_PAUSE_ENABLE_0, pause_enable);
-
-	REG_WR(bp, port ? NIG_REG_PPP_ENABLE_1 :
-	       NIG_REG_PPP_ENABLE_0, ppp_enable);
-
-	REG_WR(bp, port ? NIG_REG_LLH1_XCM_MASK :
-	       NIG_REG_LLH0_XCM_MASK, xcm_mask);
-
-	REG_WR(bp,  NIG_REG_LLFC_EGRESS_SRC_ENABLE_0, 0x7);
-
-	/* output enable for RX_XCM # IF */
-	REG_WR(bp, NIG_REG_XCM0_OUT_EN, xcm0_out_en);
-
-	/* HW PFC TX enable */
-	REG_WR(bp, NIG_REG_P0_HWPFC_ENABLE, p0_hwpfc_enable);
-
-	if (nig_params) {
-		u8 i = 0;
-		pkt_priority_to_cos = nig_params->pkt_priority_to_cos;
-
-		for (i = 0; i < nig_params->num_of_rx_cos_priority_mask; i++)
-			bnx2x_pfc_nig_rx_priority_mask(bp, i,
-		nig_params->rx_cos_priority_mask[i], port);
-
-		REG_WR(bp, port ? NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_1 :
-		       NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_0,
-		       nig_params->llfc_high_priority_classes);
-
-		REG_WR(bp, port ? NIG_REG_LLFC_LOW_PRIORITY_CLASSES_1 :
-		       NIG_REG_LLFC_LOW_PRIORITY_CLASSES_0,
-		       nig_params->llfc_low_priority_classes);
-	}
-	REG_WR(bp, port ? NIG_REG_P1_PKT_PRIORITY_TO_COS :
-	       NIG_REG_P0_PKT_PRIORITY_TO_COS,
-	       pkt_priority_to_cos);
-}
-
-int bnx2x_update_pfc(struct link_params *params,
-		      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.
-	 */
-	u32 val;
-	struct bnx2x *bp = params->bp;
-	int bnx2x_status = 0;
-	u8 bmac_loopback = (params->loopback_mode == LOOPBACK_BMAC);
-
-	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
-		vars->link_status |= LINK_STATUS_PFC_ENABLED;
-	else
-		vars->link_status &= ~LINK_STATUS_PFC_ENABLED;
-
-	bnx2x_update_mng(params, vars->link_status);
-
-	/* update NIG params */
-	bnx2x_update_pfc_nig(params, vars, pfc_params);
-
-	/* update BRB params */
-	bnx2x_status = bnx2x_update_pfc_brb(params, vars, pfc_params);
-	if (0 != bnx2x_status)
-		return bnx2x_status;
-
-	if (!vars->link_up)
-		return bnx2x_status;
-
-	DP(NETIF_MSG_LINK, "About to update PFC in BMAC\n");
-	if (CHIP_IS_E3(bp))
-		bnx2x_update_pfc_xmac(params, vars, 0);
-	else {
-		val = REG_RD(bp, MISC_REG_RESET_REG_2);
-		if ((val &
-		     (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
-		    == 0) {
-			DP(NETIF_MSG_LINK, "About to update PFC in EMAC\n");
-			bnx2x_emac_enable(params, vars, 0);
-			return bnx2x_status;
-		}
-
-		if (CHIP_IS_E2(bp))
-			bnx2x_update_pfc_bmac2(params, vars, bmac_loopback);
-		else
-			bnx2x_update_pfc_bmac1(params, vars);
-
-		val = 0;
-		if ((params->feature_config_flags &
-		     FEATURE_CONFIG_PFC_ENABLED) ||
-		    (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
-			val = 1;
-		REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + params->port*4, val);
-	}
-	return bnx2x_status;
-}
-
-
-static int bnx2x_bmac1_enable(struct link_params *params,
-			      struct link_vars *vars,
-			      u8 is_lb)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
-			       NIG_REG_INGRESS_BMAC0_MEM;
-	u32 wb_data[2];
-	u32 val;
-
-	DP(NETIF_MSG_LINK, "Enabling BigMAC1\n");
-
-	/* XGXS control */
-	wb_data[0] = 0x3c;
-	wb_data[1] = 0;
-	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) |
-		       (params->mac_addr[3] << 16) |
-		       (params->mac_addr[4] << 8) |
-			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);
-
-	/* mac control */
-	val = 0x3;
-	if (is_lb) {
-		val |= 0x4;
-		DP(NETIF_MSG_LINK, "enable bmac loopback\n");
-	}
-	wb_data[0] = val;
-	wb_data[1] = 0;
-	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);
-
-	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);
-
-	/* 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);
-
-	/* 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);
-
-	return 0;
-}
-
-static int bnx2x_bmac2_enable(struct link_params *params,
-			      struct link_vars *vars,
-			      u8 is_lb)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
-			       NIG_REG_INGRESS_BMAC0_MEM;
-	u32 wb_data[2];
-
-	DP(NETIF_MSG_LINK, "Enabling BigMAC2\n");
-
-	wb_data[0] = 0;
-	wb_data[1] = 0;
-	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);
-
-	udelay(30);
-
-	/* tx MAC SA */
-	wb_data[0] = ((params->mac_addr[2] << 24) |
-		       (params->mac_addr[3] << 16) |
-		       (params->mac_addr[4] << 8) |
-			params->mac_addr[5]);
-	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);
-
-	udelay(30);
-
-	/* Configure SAFC */
-	wb_data[0] = 0x1000200;
-	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS,
-		    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);
-	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);
-	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);
-	udelay(30);
-	bnx2x_update_pfc_bmac2(params, vars, is_lb);
-
-	return 0;
-}
-
-static int bnx2x_bmac_enable(struct link_params *params,
-			     struct link_vars *vars,
-			     u8 is_lb)
-{
-	int rc = 0;
-	u8 port = params->port;
-	struct bnx2x *bp = params->bp;
-	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));
-	msleep(1);
-
-	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);
-
-	/* Enable BMAC according to BMAC type*/
-	if (CHIP_IS_E2(bp))
-		rc = bnx2x_bmac2_enable(params, vars, is_lb);
-	else
-		rc = bnx2x_bmac1_enable(params, vars, is_lb);
-	REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0x1);
-	REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
-	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
-	val = 0;
-	if ((params->feature_config_flags &
-	      FEATURE_CONFIG_PFC_ENABLED) ||
-	    (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
-		val = 1;
-	REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, val);
-	REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x0);
-	REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x0);
-	REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, 0x0);
-	REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x1);
-	REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x1);
-
-	vars->mac_type = MAC_TYPE_BMAC;
-	return rc;
-}
-
-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;
-	u32 wb_data[2];
-	u32 nig_bmac_enable = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4);
-
-	/* Only if the bmac is out of reset */
-	if (REG_RD(bp, MISC_REG_RESET_REG_2) &
-			(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port) &&
-	    nig_bmac_enable) {
-
-		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);
-			wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
-			REG_WR_DMAE(bp, bmac_addr +
-				    BIGMAC2_REGISTER_BMAC_CONTROL,
-				    wb_data, 2);
-		} else {
-			/* Clear Rx Enable bit in BMAC_CONTROL register */
-			REG_RD_DMAE(bp, bmac_addr +
-					BIGMAC_REGISTER_BMAC_CONTROL,
-					wb_data, 2);
-			wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
-			REG_WR_DMAE(bp, bmac_addr +
-					BIGMAC_REGISTER_BMAC_CONTROL,
-					wb_data, 2);
-		}
-		msleep(1);
-	}
-}
-
-static int bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
-			    u32 line_speed)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	u32 init_crd, crd;
-	u32 count = 1000;
-
-	/* disable port */
-	REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x1);
-
-	/* wait for init credit */
-	init_crd = REG_RD(bp, PBF_REG_P0_INIT_CRD + port*4);
-	crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
-	DP(NETIF_MSG_LINK, "init_crd 0x%x  crd 0x%x\n", init_crd, crd);
-
-	while ((init_crd != crd) && count) {
-		msleep(5);
-
-		crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
-		count--;
-	}
-	crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
-	if (init_crd != crd) {
-		DP(NETIF_MSG_LINK, "BUG! init_crd 0x%x != crd 0x%x\n",
-			  init_crd, crd);
-		return -EINVAL;
-	}
-
-	if (flow_ctrl & BNX2X_FLOW_CTRL_RX ||
-	    line_speed == SPEED_10 ||
-	    line_speed == SPEED_100 ||
-	    line_speed == SPEED_1000 ||
-	    line_speed == SPEED_2500) {
-		REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 1);
-		/* update threshold */
-		REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, 0);
-		/* update init credit */
-		init_crd = 778;		/* (800-18-4) */
-
-	} else {
-		u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE +
-			      ETH_OVREHEAD)/16;
-		REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
-		/* update threshold */
-		REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, thresh);
-		/* update init credit */
-		switch (line_speed) {
-		case SPEED_10000:
-			init_crd = thresh + 553 - 22;
-			break;
-		default:
-			DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
-				  line_speed);
-			return -EINVAL;
-		}
-	}
-	REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, init_crd);
-	DP(NETIF_MSG_LINK, "PBF updated to speed %d credit %d\n",
-		 line_speed, init_crd);
-
-	/* probe the credit changes */
-	REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x1);
-	msleep(5);
-	REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x0);
-
-	/* enable port */
-	REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x0);
-	return 0;
-}
-
-/**
- * bnx2x_get_emac_base - retrive emac base address
- *
- * @bp:			driver handle
- * @mdc_mdio_access:	access type
- * @port:		port id
- *
- * 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)
-{
-	u32 emac_base = 0;
-	switch (mdc_mdio_access) {
-	case SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE:
-		break;
-	case SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0:
-		if (REG_RD(bp, NIG_REG_PORT_SWAP))
-			emac_base = GRCBASE_EMAC1;
-		else
-			emac_base = GRCBASE_EMAC0;
-		break;
-	case SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1:
-		if (REG_RD(bp, NIG_REG_PORT_SWAP))
-			emac_base = GRCBASE_EMAC0;
-		else
-			emac_base = GRCBASE_EMAC1;
-		break;
-	case SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH:
-		emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-		break;
-	case SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED:
-		emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1;
-		break;
-	default:
-		break;
-	}
-	return emac_base;
-
-}
-
-/******************************************************************/
-/*			CL22 access functions			  */
-/******************************************************************/
-static int bnx2x_cl22_write(struct bnx2x *bp,
-				       struct bnx2x_phy *phy,
-				       u16 reg, u16 val)
-{
-	u32 tmp, mode;
-	u8 i;
-	int rc = 0;
-	/* Switch to CL22 */
-	mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
-	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE,
-	       mode & ~EMAC_MDIO_MODE_CLAUSE_45);
-
-	/* address */
-	tmp = ((phy->addr << 21) | (reg << 16) | val |
-	       EMAC_MDIO_COMM_COMMAND_WRITE_22 |
-	       EMAC_MDIO_COMM_START_BUSY);
-	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
-
-	for (i = 0; i < 50; i++) {
-		udelay(10);
-
-		tmp = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
-		if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
-			udelay(5);
-			break;
-		}
-	}
-	if (tmp & EMAC_MDIO_COMM_START_BUSY) {
-		DP(NETIF_MSG_LINK, "write phy register failed\n");
-		rc = -EFAULT;
-	}
-	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, mode);
-	return rc;
-}
-
-static int bnx2x_cl22_read(struct bnx2x *bp,
-				      struct bnx2x_phy *phy,
-				      u16 reg, u16 *ret_val)
-{
-	u32 val, mode;
-	u16 i;
-	int rc = 0;
-
-	/* Switch to CL22 */
-	mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
-	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE,
-	       mode & ~EMAC_MDIO_MODE_CLAUSE_45);
-
-	/* address */
-	val = ((phy->addr << 21) | (reg << 16) |
-	       EMAC_MDIO_COMM_COMMAND_READ_22 |
-	       EMAC_MDIO_COMM_START_BUSY);
-	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
-
-	for (i = 0; i < 50; i++) {
-		udelay(10);
-
-		val = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
-		if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
-			*ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
-			udelay(5);
-			break;
-		}
-	}
-	if (val & EMAC_MDIO_COMM_START_BUSY) {
-		DP(NETIF_MSG_LINK, "read phy register failed\n");
-
-		*ret_val = 0;
-		rc = -EFAULT;
-	}
-	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, mode);
-	return rc;
-}
-
-/******************************************************************/
-/*			CL45 access functions			  */
-/******************************************************************/
-static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
-			   u8 devad, u16 reg, u16 *ret_val)
-{
-	u32 val;
-	u16 i;
-	int rc = 0;
-	if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
-		bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
-			      EMAC_MDIO_STATUS_10MB);
-	/* address */
-	val = ((phy->addr << 21) | (devad << 16) | reg |
-	       EMAC_MDIO_COMM_COMMAND_ADDRESS |
-	       EMAC_MDIO_COMM_START_BUSY);
-	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
-
-	for (i = 0; i < 50; i++) {
-		udelay(10);
-
-		val = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
-		if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
-			udelay(5);
-			break;
-		}
-	}
-	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;
-	} else {
-		/* data */
-		val = ((phy->addr << 21) | (devad << 16) |
-		       EMAC_MDIO_COMM_COMMAND_READ_45 |
-		       EMAC_MDIO_COMM_START_BUSY);
-		REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
-
-		for (i = 0; i < 50; i++) {
-			udelay(10);
-
-			val = REG_RD(bp, phy->mdio_ctrl +
-				     EMAC_REG_EMAC_MDIO_COMM);
-			if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
-				*ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
-				break;
-			}
-		}
-		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;
-		}
-	}
-	/* Work around for E3 A0 */
-	if (phy->flags & FLAGS_MDC_MDIO_WA) {
-		phy->flags ^= FLAGS_DUMMY_READ;
-		if (phy->flags & FLAGS_DUMMY_READ) {
-			u16 temp_val;
-			bnx2x_cl45_read(bp, phy, devad, 0xf, &temp_val);
-		}
-	}
-
-	if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
-		bnx2x_bits_dis(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
-			       EMAC_MDIO_STATUS_10MB);
-	return rc;
-}
-
-static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
-			    u8 devad, u16 reg, u16 val)
-{
-	u32 tmp;
-	u8 i;
-	int rc = 0;
-	if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
-		bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
-			      EMAC_MDIO_STATUS_10MB);
-
-	/* address */
-
-	tmp = ((phy->addr << 21) | (devad << 16) | reg |
-	       EMAC_MDIO_COMM_COMMAND_ADDRESS |
-	       EMAC_MDIO_COMM_START_BUSY);
-	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
-
-	for (i = 0; i < 50; i++) {
-		udelay(10);
-
-		tmp = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
-		if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
-			udelay(5);
-			break;
-		}
-	}
-	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 */
-		tmp = ((phy->addr << 21) | (devad << 16) | val |
-		       EMAC_MDIO_COMM_COMMAND_WRITE_45 |
-		       EMAC_MDIO_COMM_START_BUSY);
-		REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
-
-		for (i = 0; i < 50; i++) {
-			udelay(10);
-
-			tmp = REG_RD(bp, phy->mdio_ctrl +
-				     EMAC_REG_EMAC_MDIO_COMM);
-			if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
-				udelay(5);
-				break;
-			}
-		}
-		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;
-		}
-	}
-	/* Work around for E3 A0 */
-	if (phy->flags & FLAGS_MDC_MDIO_WA) {
-		phy->flags ^= FLAGS_DUMMY_READ;
-		if (phy->flags & FLAGS_DUMMY_READ) {
-			u16 temp_val;
-			bnx2x_cl45_read(bp, phy, devad, 0xf, &temp_val);
-		}
-	}
-	if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
-		bnx2x_bits_dis(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
-			       EMAC_MDIO_STATUS_10MB);
-	return rc;
-}
-
-
-/******************************************************************/
-/*			BSC access functions from E3	          */
-/******************************************************************/
-static void bnx2x_bsc_module_sel(struct link_params *params)
-{
-	int idx;
-	u32 board_cfg, sfp_ctrl;
-	u32 i2c_pins[I2C_SWITCH_WIDTH], i2c_val[I2C_SWITCH_WIDTH];
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	/* Read I2C output PINs */
-	board_cfg = REG_RD(bp, params->shmem_base +
-			   offsetof(struct shmem_region,
-				    dev_info.shared_hw_config.board));
-	i2c_pins[I2C_BSC0] = board_cfg & SHARED_HW_CFG_E3_I2C_MUX0_MASK;
-	i2c_pins[I2C_BSC1] = (board_cfg & SHARED_HW_CFG_E3_I2C_MUX1_MASK) >>
-			SHARED_HW_CFG_E3_I2C_MUX1_SHIFT;
-
-	/* Read I2C output value */
-	sfp_ctrl = REG_RD(bp, params->shmem_base +
-			  offsetof(struct shmem_region,
-				 dev_info.port_hw_config[port].e3_cmn_pin_cfg));
-	i2c_val[I2C_BSC0] = (sfp_ctrl & PORT_HW_CFG_E3_I2C_MUX0_MASK) > 0;
-	i2c_val[I2C_BSC1] = (sfp_ctrl & PORT_HW_CFG_E3_I2C_MUX1_MASK) > 0;
-	DP(NETIF_MSG_LINK, "Setting BSC switch\n");
-	for (idx = 0; idx < I2C_SWITCH_WIDTH; idx++)
-		bnx2x_set_cfg_pin(bp, i2c_pins[idx], i2c_val[idx]);
-}
-
-static int bnx2x_bsc_read(struct link_params *params,
-			  struct bnx2x_phy *phy,
-			  u8 sl_devid,
-			  u16 sl_addr,
-			  u8 lc_addr,
-			  u8 xfer_cnt,
-			  u32 *data_array)
-{
-	u32 val, i;
-	int rc = 0;
-	struct bnx2x *bp = params->bp;
-
-	if ((sl_devid != 0xa0) && (sl_devid != 0xa2)) {
-		DP(NETIF_MSG_LINK, "invalid sl_devid 0x%x\n", sl_devid);
-		return -EINVAL;
-	}
-
-	if (xfer_cnt > 16) {
-		DP(NETIF_MSG_LINK, "invalid xfer_cnt %d. Max is 16 bytes\n",
-					xfer_cnt);
-		return -EINVAL;
-	}
-	bnx2x_bsc_module_sel(params);
-
-	xfer_cnt = 16 - lc_addr;
-
-	/* enable the engine */
-	val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
-	val |= MCPR_IMC_COMMAND_ENABLE;
-	REG_WR(bp, MCP_REG_MCPR_IMC_COMMAND, val);
-
-	/* program slave device ID */
-	val = (sl_devid << 16) | sl_addr;
-	REG_WR(bp, MCP_REG_MCPR_IMC_SLAVE_CONTROL, val);
-
-	/* start xfer with 0 byte to update the address pointer ???*/
-	val = (MCPR_IMC_COMMAND_ENABLE) |
-	      (MCPR_IMC_COMMAND_WRITE_OP <<
-		MCPR_IMC_COMMAND_OPERATION_BITSHIFT) |
-		(lc_addr << MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT) | (0);
-	REG_WR(bp, MCP_REG_MCPR_IMC_COMMAND, val);
-
-	/* poll for completion */
-	i = 0;
-	val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
-	while (((val >> MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT) & 0x3) != 1) {
-		udelay(10);
-		val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
-		if (i++ > 1000) {
-			DP(NETIF_MSG_LINK, "wr 0 byte timed out after %d try\n",
-								i);
-			rc = -EFAULT;
-			break;
-		}
-	}
-	if (rc == -EFAULT)
-		return rc;
-
-	/* start xfer with read op */
-	val = (MCPR_IMC_COMMAND_ENABLE) |
-		(MCPR_IMC_COMMAND_READ_OP <<
-		MCPR_IMC_COMMAND_OPERATION_BITSHIFT) |
-		(lc_addr << MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT) |
-		  (xfer_cnt);
-	REG_WR(bp, MCP_REG_MCPR_IMC_COMMAND, val);
-
-	/* poll for completion */
-	i = 0;
-	val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
-	while (((val >> MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT) & 0x3) != 1) {
-		udelay(10);
-		val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
-		if (i++ > 1000) {
-			DP(NETIF_MSG_LINK, "rd op timed out after %d try\n", i);
-			rc = -EFAULT;
-			break;
-		}
-	}
-	if (rc == -EFAULT)
-		return rc;
-
-	for (i = (lc_addr >> 2); i < 4; i++) {
-		data_array[i] = REG_RD(bp, (MCP_REG_MCPR_IMC_DATAREG0 + i*4));
-#ifdef __BIG_ENDIAN
-		data_array[i] = ((data_array[i] & 0x000000ff) << 24) |
-				((data_array[i] & 0x0000ff00) << 8) |
-				((data_array[i] & 0x00ff0000) >> 8) |
-				((data_array[i] & 0xff000000) >> 24);
-#endif
-	}
-	return rc;
-}
-
-static void bnx2x_cl45_read_or_write(struct bnx2x *bp, struct bnx2x_phy *phy,
-				     u8 devad, u16 reg, u16 or_val)
-{
-	u16 val;
-	bnx2x_cl45_read(bp, phy, devad, reg, &val);
-	bnx2x_cl45_write(bp, phy, devad, reg, val | or_val);
-}
-
-int bnx2x_phy_read(struct link_params *params, u8 phy_addr,
-		   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
-	 */
-	for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
-		if (params->phy[phy_index].addr == phy_addr) {
-			return bnx2x_cl45_read(params->bp,
-					       &params->phy[phy_index], devad,
-					       reg, ret_val);
-		}
-	}
-	return -EINVAL;
-}
-
-int bnx2x_phy_write(struct link_params *params, u8 phy_addr,
-		    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
-	 */
-	for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
-		if (params->phy[phy_index].addr == phy_addr) {
-			return bnx2x_cl45_write(params->bp,
-						&params->phy[phy_index], devad,
-						reg, val);
-		}
-	}
-	return -EINVAL;
-}
-static u8 bnx2x_get_warpcore_lane(struct bnx2x_phy *phy,
-				  struct link_params *params)
-{
-	u8 lane = 0;
-	struct bnx2x *bp = params->bp;
-	u32 path_swap, path_swap_ovr;
-	u8 path, port;
-
-	path = BP_PATH(bp);
-	port = params->port;
-
-	if (bnx2x_is_4_port_mode(bp)) {
-		u32 port_swap, port_swap_ovr;
-
-		/*figure out path swap value */
-		path_swap_ovr = REG_RD(bp, MISC_REG_FOUR_PORT_PATH_SWAP_OVWR);
-		if (path_swap_ovr & 0x1)
-			path_swap = (path_swap_ovr & 0x2);
-		else
-			path_swap = REG_RD(bp, MISC_REG_FOUR_PORT_PATH_SWAP);
-
-		if (path_swap)
-			path = path ^ 1;
-
-		/*figure out port swap value */
-		port_swap_ovr = REG_RD(bp, MISC_REG_FOUR_PORT_PORT_SWAP_OVWR);
-		if (port_swap_ovr & 0x1)
-			port_swap = (port_swap_ovr & 0x2);
-		else
-			port_swap = REG_RD(bp, MISC_REG_FOUR_PORT_PORT_SWAP);
-
-		if (port_swap)
-			port = port ^ 1;
-
-		lane = (port<<1) + path;
-	} else { /* two port mode - no port swap */
-
-		/*figure out path swap value */
-		path_swap_ovr =
-			REG_RD(bp, MISC_REG_TWO_PORT_PATH_SWAP_OVWR);
-		if (path_swap_ovr & 0x1) {
-			path_swap = (path_swap_ovr & 0x2);
-		} else {
-			path_swap =
-				REG_RD(bp, MISC_REG_TWO_PORT_PATH_SWAP);
-		}
-		if (path_swap)
-			path = path ^ 1;
-
-		lane = path << 1 ;
-	}
-	return lane;
-}
-
-static void bnx2x_set_aer_mmd(struct link_params *params,
-			      struct bnx2x_phy *phy)
-{
-	u32 ser_lane;
-	u16 offset, aer_val;
-	struct bnx2x *bp = params->bp;
-	ser_lane = ((params->lane_config &
-		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
-		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
-
-	offset = (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ?
-		(phy->addr + ser_lane) : 0;
-
-	if (USES_WARPCORE(bp)) {
-		aer_val = bnx2x_get_warpcore_lane(phy, params);
-		/*
-		 * In Dual-lane mode, two lanes are joined together,
-		 * so in order to configure them, the AER broadcast method is
-		 * used here.
-		 * 0x200 is the broadcast address for lanes 0,1
-		 * 0x201 is the broadcast address for lanes 2,3
-		 */
-		if (phy->flags & FLAGS_WC_DUAL_MODE)
-			aer_val = (aer_val >> 1) | 0x200;
-	} else if (CHIP_IS_E2(bp))
-		aer_val = 0x3800 + offset - 1;
-	else
-		aer_val = 0x3800 + offset;
-	DP(NETIF_MSG_LINK, "Set AER to 0x%x\n", aer_val);
-	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
-			  MDIO_AER_BLOCK_AER_REG, aer_val);
-
-}
-
-/******************************************************************/
-/*			Internal phy section			  */
-/******************************************************************/
-
-static void bnx2x_set_serdes_access(struct bnx2x *bp, u8 port)
-{
-	u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-
-	/* Set Clause 22 */
-	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 1);
-	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245f8000);
-	udelay(500);
-	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245d000f);
-	udelay(500);
-	 /* Set Clause 45 */
-	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 0);
-}
-
-static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)
-{
-	u32 val;
-
-	DP(NETIF_MSG_LINK, "bnx2x_serdes_deassert\n");
-
-	val = SERDES_RESET_BITS << (port*16);
-
-	/* reset and unreset the SerDes/XGXS */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
-	udelay(500);
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
-
-	bnx2x_set_serdes_access(bp, port);
-
-	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD + port*0x10,
-	       DEFAULT_PHY_DEV_ADDR);
-}
-
-static void bnx2x_xgxs_deassert(struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port;
-	u32 val;
-	DP(NETIF_MSG_LINK, "bnx2x_xgxs_deassert\n");
-	port = params->port;
-
-	val = XGXS_RESET_BITS << (port*16);
-
-	/* reset and unreset the SerDes/XGXS */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
-	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_DEVAD + port*0x18,
-	       params->phy[INT_PHY].def_md_devad);
-}
-
-static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
-				     struct link_params *params, u16 *ieee_fc)
-{
-	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
-	 */
-
-	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
-			*ieee_fc |=
-			MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
-		break;
-
-	case BNX2X_FLOW_CTRL_TX:
-		*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
-		break;
-
-	case BNX2X_FLOW_CTRL_RX:
-	case BNX2X_FLOW_CTRL_BOTH:
-		*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
-		break;
-
-	case BNX2X_FLOW_CTRL_NONE:
-	default:
-		*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
-		break;
-	}
-	DP(NETIF_MSG_LINK, "ieee_fc = 0x%x\n", *ieee_fc);
-}
-
-static void set_phy_vars(struct link_params *params,
-			 struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u8 actual_phy_idx, phy_index, link_cfg_idx;
-	u8 phy_config_swapped = params->multi_phy_config &
-			PORT_HW_CFG_PHY_SWAPPED_ENABLED;
-	for (phy_index = INT_PHY; phy_index < params->num_phys;
-	      phy_index++) {
-		link_cfg_idx = LINK_CONFIG_IDX(phy_index);
-		actual_phy_idx = phy_index;
-		if (phy_config_swapped) {
-			if (phy_index == EXT_PHY1)
-				actual_phy_idx = EXT_PHY2;
-			else if (phy_index == EXT_PHY2)
-				actual_phy_idx = EXT_PHY1;
-		}
-		params->phy[actual_phy_idx].req_flow_ctrl =
-			params->req_flow_ctrl[link_cfg_idx];
-
-		params->phy[actual_phy_idx].req_line_speed =
-			params->req_line_speed[link_cfg_idx];
-
-		params->phy[actual_phy_idx].speed_cap_mask =
-			params->speed_cap_mask[link_cfg_idx];
-
-		params->phy[actual_phy_idx].req_duplex =
-			params->req_duplex[link_cfg_idx];
-
-		if (params->req_line_speed[link_cfg_idx] ==
-		    SPEED_AUTO_NEG)
-			vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
-
-		DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x,"
-			   " speed_cap_mask %x\n",
-			   params->phy[actual_phy_idx].req_flow_ctrl,
-			   params->phy[actual_phy_idx].req_line_speed,
-			   params->phy[actual_phy_idx].speed_cap_mask);
-	}
-}
-
-static void bnx2x_ext_phy_set_pause(struct link_params *params,
-				    struct bnx2x_phy *phy,
-				    struct link_vars *vars)
-{
-	u16 val;
-	struct bnx2x *bp = params->bp;
-	/* read modify write pause advertizing */
-	bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &val);
-
-	val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
-
-	/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
-	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
-	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;
-	}
-	if ((vars->ieee_fc &
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
-		val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
-	}
-	DP(NETIF_MSG_LINK, "Ext phy AN advertize 0x%x\n", val);
-	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val);
-}
-
-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 */
-		vars->flow_ctrl = BNX2X_FLOW_CTRL_TX;
-		break;
-
-	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 */
-		vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
-		break;
-
-	default:
-		break;
-	}
-	if (pause_result & (1<<0))
-		vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
-	if (pause_result & (1<<1))
-		vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
-}
-
-static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
-				   struct link_params *params,
-				   struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u16 ld_pause;		/* local */
-	u16 lp_pause;		/* link partner */
-	u16 pause_result;
-	u8 ret = 0;
-	/* read twice */
-
-	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-
-	if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
-		vars->flow_ctrl = phy->req_flow_ctrl;
-	else if (phy->req_line_speed != SPEED_AUTO_NEG)
-		vars->flow_ctrl = params->req_fc_auto_adv;
-	else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
-		ret = 1;
-		if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) {
-			bnx2x_cl22_read(bp, phy,
-					0x4, &ld_pause);
-			bnx2x_cl22_read(bp, phy,
-					0x5, &lp_pause);
-		} else {
-			bnx2x_cl45_read(bp, phy,
-					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);
-		}
-		pause_result = (ld_pause &
-				MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
-		pause_result |= (lp_pause &
-				 MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
-		DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
-		   pause_result);
-		bnx2x_pause_resolve(vars, pause_result);
-	}
-	return ret;
-}
-/******************************************************************/
-/*			Warpcore section			  */
-/******************************************************************/
-/* The init_internal_warpcore should mirror the xgxs,
- * i.e. reset the lane (if needed), set aer for the
- * init configuration, and set/clear SGMII flag. Internal
- * phy init is done purely in phy_init stage.
- */
-static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
-					struct link_params *params,
-					struct link_vars *vars) {
-	u16 val16 = 0, lane, bam37 = 0;
-	struct bnx2x *bp = params->bp;
-	DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n");
-	/* Check adding advertisement for 1G KX */
-	if (((vars->line_speed == SPEED_AUTO_NEG) &&
-	     (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
-	    (vars->line_speed == SPEED_1000)) {
-		u16 sd_digital;
-		val16 |= (1<<5);
-
-		/* Enable CL37 1G Parallel Detect */
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &sd_digital);
-		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
-				 (sd_digital | 0x1));
-
-		DP(NETIF_MSG_LINK, "Advertize 1G\n");
-	}
-	if (((vars->line_speed == SPEED_AUTO_NEG) &&
-	     (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
-	    (vars->line_speed ==  SPEED_10000)) {
-		/* Check adding advertisement for 10G KR */
-		val16 |= (1<<7);
-		/* Enable 10G Parallel Detect */
-		bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
-				MDIO_WC_REG_PAR_DET_10G_CTRL, 1);
-
-		DP(NETIF_MSG_LINK, "Advertize 10G\n");
-	}
-
-	/* Set Transmit PMD settings */
-	lane = bnx2x_get_warpcore_lane(phy, params);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-		      MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
-		     ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
-		      (0x06 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
-		      (0x09 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL,
-			 0x03f0);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_CL72_USERB0_CL72_2P5_DEF_CTRL,
-			 0x03f0);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
-			 0x383f);
-
-	/* Advertised speeds */
-	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
-			 MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16);
-
-	/* Advertised and set FEC (Forward Error Correction) */
-	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
-			 MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT2,
-			 (MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_ABILITY |
-			  MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_REQ));
-
-	/* Enable CL37 BAM */
-	if (REG_RD(bp, params->shmem_base +
-		   offsetof(struct shmem_region, dev_info.
-			    port_hw_config[params->port].default_cfg)) &
-	    PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED) {
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL, &bam37);
-		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL, bam37 | 1);
-		DP(NETIF_MSG_LINK, "Enable CL37 BAM on KR\n");
-	}
-
-	/* Advertise pause */
-	bnx2x_ext_phy_set_pause(params, phy, vars);
-
-	/* Enable Autoneg */
-	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
-			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1000);
-
-	/* Over 1G - AN local device user page 1 */
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_DIGITAL3_UP1, 0x1f);
-
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_DIGITAL5_MISC7, &val16);
-
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_DIGITAL5_MISC7, val16 | 0x100);
-}
-
-static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
-				      struct link_params *params,
-				      struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val;
-
-	/* Disable Autoneg */
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7);
-
-	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
-			 MDIO_WC_REG_PAR_DET_10G_CTRL, 0);
-
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0x3f00);
-
-	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
-			 MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0);
-
-	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
-			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0);
-
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_DIGITAL3_UP1, 0x1);
-
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_DIGITAL5_MISC7, 0xa);
-
-	/* Disable CL36 PCS Tx */
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0);
-
-	/* Double Wide Single Data Rate @ pll rate */
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF);
-
-	/* Leave cl72 training enable, needed for KR */
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
-		MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150,
-		0x2);
-
-	/* Leave CL72 enabled */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
-			 &val);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
-			 val | 0x3800);
-
-	/* Set speed via PMA/PMD register */
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
-			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
-
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
-			 MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0xB);
-
-	/*Enable encoded forced speed */
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x30);
-
-	/* Turn TX scramble payload only the 64/66 scrambler */
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_TX66_CONTROL, 0x9);
-
-	/* Turn RX scramble payload only the 64/66 scrambler */
-	bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
-				 MDIO_WC_REG_RX66_CONTROL, 0xF9);
-
-	/* set and clear loopback to cause a reset to 64/66 decoder */
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x4000);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0);
-
-}
-
-static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy,
-				       struct link_params *params,
-				       u8 is_xfi)
-{
-	struct bnx2x *bp = params->bp;
-	u16 misc1_val, tap_val, tx_driver_val, lane, val;
-	/* Hold rxSeqStart */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, &val);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, (val | 0x8000));
-
-	/* Hold tx_fifo_reset */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, &val);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, (val | 0x1));
-
-	/* Disable CL73 AN */
-	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0);
-
-	/* Disable 100FX Enable and Auto-Detect */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_FX100_CTRL1, &val);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_FX100_CTRL1, (val & 0xFFFA));
-
-	/* Disable 100FX Idle detect */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_FX100_CTRL3, &val);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_FX100_CTRL3, (val | 0x0080));
-
-	/* Set Block address to Remote PHY & Clear forced_speed[5] */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_DIGITAL4_MISC3, &val);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_DIGITAL4_MISC3, (val & 0xFF7F));
-
-	/* Turn off auto-detect & fiber mode */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &val);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
-			 (val & 0xFFEE));
-
-	/* Set filter_force_link, disable_false_link and parallel_detect */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &val);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
-			 ((val | 0x0006) & 0xFFFE));
-
-	/* Set XFI / SFI */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_SERDESDIGITAL_MISC1, &misc1_val);
-
-	misc1_val &= ~(0x1f);
-
-	if (is_xfi) {
-		misc1_val |= 0x5;
-		tap_val = ((0x08 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
-			   (0x37 << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
-			   (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET));
-		tx_driver_val =
-		      ((0x00 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
-		       (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
-		       (0x03 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET));
-
-	} else {
-		misc1_val |= 0x9;
-		tap_val = ((0x12 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
-			   (0x2d << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
-			   (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET));
-		tx_driver_val =
-		      ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
-		       (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
-		       (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET));
-	}
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_SERDESDIGITAL_MISC1, misc1_val);
-
-	/* Set Transmit PMD settings */
-	lane = bnx2x_get_warpcore_lane(phy, params);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_TX_FIR_TAP,
-			 tap_val | MDIO_WC_REG_TX_FIR_TAP_ENABLE);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
-			 tx_driver_val);
-
-	/* Enable fiber mode, enable and invert sig_det */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &val);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, val | 0xd);
-
-	/* Set Block address to Remote PHY & Set forced_speed[5], 40bit mode */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_DIGITAL4_MISC3, &val);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_DIGITAL4_MISC3, val | 0x8080);
-
-	/* 10G XFI Full Duplex */
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x100);
-
-	/* Release tx_fifo_reset */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, &val);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, val & 0xFFFE);
-
-	/* Release rxSeqStart */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, &val);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, (val & 0x7FFF));
-}
-
-static void bnx2x_warpcore_set_20G_KR2(struct bnx2x *bp,
-				       struct bnx2x_phy *phy)
-{
-	DP(NETIF_MSG_LINK, "KR2 still not supported !!!\n");
-}
-
-static void bnx2x_warpcore_set_20G_DXGXS(struct bnx2x *bp,
-					 struct bnx2x_phy *phy,
-					 u16 lane)
-{
-	/* Rx0 anaRxControl1G */
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_RX0_ANARXCONTROL1G, 0x90);
-
-	/* Rx2 anaRxControl1G */
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_RX2_ANARXCONTROL1G, 0x90);
-
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_RX66_SCW0, 0xE070);
-
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_RX66_SCW1, 0xC0D0);
-
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_RX66_SCW2, 0xA0B0);
-
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_RX66_SCW3, 0x8090);
-
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_RX66_SCW0_MASK, 0xF0F0);
-
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_RX66_SCW1_MASK, 0xF0F0);
-
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_RX66_SCW2_MASK, 0xF0F0);
-
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_RX66_SCW3_MASK, 0xF0F0);
-
-	/* Serdes Digital Misc1 */
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x6008);
-
-	/* Serdes Digital4 Misc3 */
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_DIGITAL4_MISC3, 0x8088);
-
-	/* Set Transmit PMD settings */
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_TX_FIR_TAP,
-			((0x12 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
-			 (0x2d << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
-			 (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET) |
-			 MDIO_WC_REG_TX_FIR_TAP_ENABLE));
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-		      MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
-		     ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
-		      (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
-		      (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
-}
-
-static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
-					   struct link_params *params,
-					   u8 fiber_mode)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val16, digctrl_kx1, digctrl_kx2;
-	u8 lane;
-
-	lane = bnx2x_get_warpcore_lane(phy, params);
-
-	/* Clear XFI clock comp in non-10G single lane mode. */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_RX66_CONTROL, &val16);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_RX66_CONTROL, val16 & ~(3<<13));
-
-	if (phy->req_line_speed == SPEED_AUTO_NEG) {
-		/* SGMII Autoneg */
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
-		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-				 MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
-				 val16 | 0x1000);
-		DP(NETIF_MSG_LINK, "set SGMII AUTONEG\n");
-	} else {
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
-		val16 &= 0xcfbf;
-		switch (phy->req_line_speed) {
-		case SPEED_10:
-			break;
-		case SPEED_100:
-			val16 |= 0x2000;
-			break;
-		case SPEED_1000:
-			val16 |= 0x0040;
-			break;
-		default:
-			DP(NETIF_MSG_LINK, "Speed not supported: 0x%x"
-					   "\n", phy->req_line_speed);
-			return;
-		}
-
-		if (phy->req_duplex == DUPLEX_FULL)
-			val16 |= 0x0100;
-
-		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16);
-
-		DP(NETIF_MSG_LINK, "set SGMII force speed %d\n",
-			       phy->req_line_speed);
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
-		DP(NETIF_MSG_LINK, "  (readback) %x\n", val16);
-	}
-
-	/* SGMII Slave mode and disable signal detect */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &digctrl_kx1);
-	if (fiber_mode)
-		digctrl_kx1 = 1;
-	else
-		digctrl_kx1 &= 0xff4a;
-
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
-			digctrl_kx1);
-
-	/* Turn off parallel detect */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &digctrl_kx2);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
-			(digctrl_kx2 & ~(1<<2)));
-
-	/* Re-enable parallel detect */
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
-			(digctrl_kx2 | (1<<2)));
-
-	/* Enable autodet */
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
-			(digctrl_kx1 | 0x10));
-}
-
-static void bnx2x_warpcore_reset_lane(struct bnx2x *bp,
-				      struct bnx2x_phy *phy,
-				      u8 reset)
-{
-	u16 val;
-	/* Take lane out of reset after configuration is finished */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_DIGITAL5_MISC6, &val);
-	if (reset)
-		val |= 0xC000;
-	else
-		val &= 0x3FFF;
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_DIGITAL5_MISC6, val);
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_DIGITAL5_MISC6, &val);
-}
-
-
-	/* Clear SFI/XFI link settings registers */
-static void bnx2x_warpcore_clear_regs(struct bnx2x_phy *phy,
-				      struct link_params *params,
-				      u16 lane)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val16;
-
-	/* Set XFI clock comp as default. */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_RX66_CONTROL, &val16);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_RX66_CONTROL, val16 | (3<<13));
-
-	bnx2x_warpcore_reset_lane(bp, phy, 1);
-	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_FX100_CTRL1, 0x014a);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_FX100_CTRL3, 0x0800);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_DIGITAL4_MISC3, 0x8008);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, 0x0195);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x0007);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, 0x0002);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x6000);
-	lane = bnx2x_get_warpcore_lane(phy, params);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_TX_FIR_TAP, 0x0000);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane, 0x0990);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0x0140);
-	bnx2x_warpcore_reset_lane(bp, phy, 0);
-}
-
-static int bnx2x_get_mod_abs_int_cfg(struct bnx2x *bp,
-						u32 chip_id,
-						u32 shmem_base, u8 port,
-						u8 *gpio_num, u8 *gpio_port)
-{
-	u32 cfg_pin;
-	*gpio_num = 0;
-	*gpio_port = 0;
-	if (CHIP_IS_E3(bp)) {
-		cfg_pin = (REG_RD(bp, shmem_base +
-				offsetof(struct shmem_region,
-				dev_info.port_hw_config[port].e3_sfp_ctrl)) &
-				PORT_HW_CFG_E3_MOD_ABS_MASK) >>
-				PORT_HW_CFG_E3_MOD_ABS_SHIFT;
-
-		/*
-		 * Should not happen. This function called upon interrupt
-		 * triggered by GPIO ( since EPIO can only generate interrupts
-		 * to MCP).
-		 * So if this function was called and none of the GPIOs was set,
-		 * it means the shit hit the fan.
-		 */
-		if ((cfg_pin < PIN_CFG_GPIO0_P0) ||
-		    (cfg_pin > PIN_CFG_GPIO3_P1)) {
-			DP(NETIF_MSG_LINK, "ERROR: Invalid cfg pin %x for "
-					   "module detect indication\n",
-				       cfg_pin);
-			return -EINVAL;
-		}
-
-		*gpio_num = (cfg_pin - PIN_CFG_GPIO0_P0) & 0x3;
-		*gpio_port = (cfg_pin - PIN_CFG_GPIO0_P0) >> 2;
-	} else {
-		*gpio_num = MISC_REGISTERS_GPIO_3;
-		*gpio_port = port;
-	}
-	DP(NETIF_MSG_LINK, "MOD_ABS int GPIO%d_P%d\n", *gpio_num, *gpio_port);
-	return 0;
-}
-
-static int bnx2x_is_sfp_module_plugged(struct bnx2x_phy *phy,
-				       struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u8 gpio_num, gpio_port;
-	u32 gpio_val;
-	if (bnx2x_get_mod_abs_int_cfg(bp, params->chip_id,
-				      params->shmem_base, params->port,
-				      &gpio_num, &gpio_port) != 0)
-		return 0;
-	gpio_val = bnx2x_get_gpio(bp, gpio_num, gpio_port);
-
-	/* Call the handling function in case module is detected */
-	if (gpio_val == 0)
-		return 1;
-	else
-		return 0;
-}
-
-static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
-				       struct link_params *params,
-				       struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u32 serdes_net_if;
-	u8 fiber_mode;
-	u16 lane = bnx2x_get_warpcore_lane(phy, params);
-	serdes_net_if = (REG_RD(bp, params->shmem_base +
-			 offsetof(struct shmem_region, dev_info.
-				  port_hw_config[params->port].default_cfg)) &
-			 PORT_HW_CFG_NET_SERDES_IF_MASK);
-	DP(NETIF_MSG_LINK, "Begin Warpcore init, link_speed %d, "
-			   "serdes_net_if = 0x%x\n",
-		       vars->line_speed, serdes_net_if);
-	bnx2x_set_aer_mmd(params, phy);
-
-	vars->phy_flags |= PHY_XGXS_FLAG;
-	if ((serdes_net_if == PORT_HW_CFG_NET_SERDES_IF_SGMII) ||
-	    (phy->req_line_speed &&
-	     ((phy->req_line_speed == SPEED_100) ||
-	      (phy->req_line_speed == SPEED_10)))) {
-		vars->phy_flags |= PHY_SGMII_FLAG;
-		DP(NETIF_MSG_LINK, "Setting SGMII mode\n");
-		bnx2x_warpcore_clear_regs(phy, params, lane);
-		bnx2x_warpcore_set_sgmii_speed(phy, params, 0);
-	} else {
-		switch (serdes_net_if) {
-		case PORT_HW_CFG_NET_SERDES_IF_KR:
-			/* Enable KR Auto Neg */
-			if (params->loopback_mode == LOOPBACK_NONE)
-				bnx2x_warpcore_enable_AN_KR(phy, params, vars);
-			else {
-				DP(NETIF_MSG_LINK, "Setting KR 10G-Force\n");
-				bnx2x_warpcore_set_10G_KR(phy, params, vars);
-			}
-			break;
-
-		case PORT_HW_CFG_NET_SERDES_IF_XFI:
-			bnx2x_warpcore_clear_regs(phy, params, lane);
-			if (vars->line_speed == SPEED_10000) {
-				DP(NETIF_MSG_LINK, "Setting 10G XFI\n");
-				bnx2x_warpcore_set_10G_XFI(phy, params, 1);
-			} else {
-				if (SINGLE_MEDIA_DIRECT(params)) {
-					DP(NETIF_MSG_LINK, "1G Fiber\n");
-					fiber_mode = 1;
-				} else {
-					DP(NETIF_MSG_LINK, "10/100/1G SGMII\n");
-					fiber_mode = 0;
-				}
-				bnx2x_warpcore_set_sgmii_speed(phy,
-								params,
-								fiber_mode);
-			}
-
-			break;
-
-		case PORT_HW_CFG_NET_SERDES_IF_SFI:
-
-			bnx2x_warpcore_clear_regs(phy, params, lane);
-			if (vars->line_speed == SPEED_10000) {
-				DP(NETIF_MSG_LINK, "Setting 10G SFI\n");
-				bnx2x_warpcore_set_10G_XFI(phy, params, 0);
-			} else if (vars->line_speed == SPEED_1000) {
-				DP(NETIF_MSG_LINK, "Setting 1G Fiber\n");
-				bnx2x_warpcore_set_sgmii_speed(phy, params, 1);
-			}
-			/* Issue Module detection */
-			if (bnx2x_is_sfp_module_plugged(phy, params))
-				bnx2x_sfp_module_detection(phy, params);
-			break;
-
-		case PORT_HW_CFG_NET_SERDES_IF_DXGXS:
-			if (vars->line_speed != SPEED_20000) {
-				DP(NETIF_MSG_LINK, "Speed not supported yet\n");
-				return;
-			}
-			DP(NETIF_MSG_LINK, "Setting 20G DXGXS\n");
-			bnx2x_warpcore_set_20G_DXGXS(bp, phy, lane);
-			/* Issue Module detection */
-
-			bnx2x_sfp_module_detection(phy, params);
-			break;
-
-		case PORT_HW_CFG_NET_SERDES_IF_KR2:
-			if (vars->line_speed != SPEED_20000) {
-				DP(NETIF_MSG_LINK, "Speed not supported yet\n");
-				return;
-			}
-			DP(NETIF_MSG_LINK, "Setting 20G KR2\n");
-			bnx2x_warpcore_set_20G_KR2(bp, phy);
-			break;
-
-		default:
-			DP(NETIF_MSG_LINK, "Unsupported Serdes Net Interface "
-					   "0x%x\n", serdes_net_if);
-			return;
-		}
-	}
-
-	/* Take lane out of reset after configuration is finished */
-	bnx2x_warpcore_reset_lane(bp, phy, 0);
-	DP(NETIF_MSG_LINK, "Exit config init\n");
-}
-
-static void bnx2x_sfp_e3_set_transmitter(struct link_params *params,
-					 struct bnx2x_phy *phy,
-					 u8 tx_en)
-{
-	struct bnx2x *bp = params->bp;
-	u32 cfg_pin;
-	u8 port = params->port;
-
-	cfg_pin = REG_RD(bp, params->shmem_base +
-				offsetof(struct shmem_region,
-				dev_info.port_hw_config[port].e3_sfp_ctrl)) &
-				PORT_HW_CFG_TX_LASER_MASK;
-	/* Set the !tx_en since this pin is DISABLE_TX_LASER */
-	DP(NETIF_MSG_LINK, "Setting WC TX to %d\n", tx_en);
-	/* For 20G, the expected pin to be used is 3 pins after the current */
-
-	bnx2x_set_cfg_pin(bp, cfg_pin, tx_en ^ 1);
-	if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)
-		bnx2x_set_cfg_pin(bp, cfg_pin + 3, tx_en ^ 1);
-}
-
-static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
-				      struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val16;
-	bnx2x_sfp_e3_set_transmitter(params, phy, 0);
-	bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
-	bnx2x_set_aer_mmd(params, phy);
-	/* Global register */
-	bnx2x_warpcore_reset_lane(bp, phy, 1);
-
-	/* Clear loopback settings (if any) */
-	/* 10G & 20G */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 &
-			 0xBFFF);
-
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_IEEE0BLK_MIICNTL, &val16);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_IEEE0BLK_MIICNTL, val16 & 0xfffe);
-
-	/* Update those 1-copy registers */
-	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
-			  MDIO_AER_BLOCK_AER_REG, 0);
-		/* Enable 1G MDIO (1-copy) */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
-			&val16);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
-			 val16 & ~0x10);
-
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_XGXSBLK1_LANECTRL2,
-			 val16 & 0xff00);
-
-}
-
-static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
-					struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val16;
-	u32 lane;
-	DP(NETIF_MSG_LINK, "Setting Warpcore loopback type %x, speed %d\n",
-		       params->loopback_mode, phy->req_line_speed);
-
-	if (phy->req_line_speed < SPEED_10000) {
-		/* 10/100/1000 */
-
-		/* Update those 1-copy registers */
-		CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
-				  MDIO_AER_BLOCK_AER_REG, 0);
-		/* Enable 1G MDIO (1-copy) */
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
-				&val16);
-		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
-				val16 | 0x10);
-		/* Set 1G loopback based on lane (1-copy) */
-		lane = bnx2x_get_warpcore_lane(phy, params);
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
-		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_XGXSBLK1_LANECTRL2,
-				val16 | (1<<lane));
-
-		/* Switch back to 4-copy registers */
-		bnx2x_set_aer_mmd(params, phy);
-		/* Global loopback, not recommended. */
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
-		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 |
-				0x4000);
-	} else {
-		/* 10G & 20G */
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
-		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 |
-				 0x4000);
-
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_IEEE0BLK_MIICNTL, &val16);
-		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_IEEE0BLK_MIICNTL, val16 | 0x1);
-	}
-}
-
-
-void bnx2x_link_status_update(struct link_params *params,
-			      struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u8 link_10g_plus;
-	u8 port = params->port;
-	u32 sync_offset, media_types;
-	/* Update PHY configuration */
-	set_phy_vars(params, vars);
-
-	vars->link_status = REG_RD(bp, params->shmem_base +
-				   offsetof(struct shmem_region,
-					    port_mb[port].link_status));
-
-	vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
-	vars->phy_flags = PHY_XGXS_FLAG;
-	if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG)
-		vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
-
-	if (vars->link_up) {
-		DP(NETIF_MSG_LINK, "phy link up\n");
-
-		vars->phy_link_up = 1;
-		vars->duplex = DUPLEX_FULL;
-		switch (vars->link_status &
-			LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
-			case LINK_10THD:
-				vars->duplex = DUPLEX_HALF;
-				/* fall thru */
-			case LINK_10TFD:
-				vars->line_speed = SPEED_10;
-				break;
-
-			case LINK_100TXHD:
-				vars->duplex = DUPLEX_HALF;
-				/* fall thru */
-			case LINK_100T4:
-			case LINK_100TXFD:
-				vars->line_speed = SPEED_100;
-				break;
-
-			case LINK_1000THD:
-				vars->duplex = DUPLEX_HALF;
-				/* fall thru */
-			case LINK_1000TFD:
-				vars->line_speed = SPEED_1000;
-				break;
-
-			case LINK_2500THD:
-				vars->duplex = DUPLEX_HALF;
-				/* fall thru */
-			case LINK_2500TFD:
-				vars->line_speed = SPEED_2500;
-				break;
-
-			case LINK_10GTFD:
-				vars->line_speed = SPEED_10000;
-				break;
-			case LINK_20GTFD:
-				vars->line_speed = SPEED_20000;
-				break;
-			default:
-				break;
-		}
-		vars->flow_ctrl = 0;
-		if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
-			vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX;
-
-		if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
-			vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX;
-
-		if (!vars->flow_ctrl)
-			vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-
-		if (vars->line_speed &&
-		    ((vars->line_speed == SPEED_10) ||
-		     (vars->line_speed == SPEED_100))) {
-			vars->phy_flags |= PHY_SGMII_FLAG;
-		} else {
-			vars->phy_flags &= ~PHY_SGMII_FLAG;
-		}
-		if (vars->line_speed &&
-		    USES_WARPCORE(bp) &&
-		    (vars->line_speed == SPEED_1000))
-			vars->phy_flags |= PHY_SGMII_FLAG;
-		/* anything 10 and over uses the bmac */
-		link_10g_plus = (vars->line_speed >= SPEED_10000);
-
-		if (link_10g_plus) {
-			if (USES_WARPCORE(bp))
-				vars->mac_type = MAC_TYPE_XMAC;
-			else
-				vars->mac_type = MAC_TYPE_BMAC;
-		} else {
-			if (USES_WARPCORE(bp))
-				vars->mac_type = MAC_TYPE_UMAC;
-			else
-				vars->mac_type = MAC_TYPE_EMAC;
-		}
-	} else { /* link down */
-		DP(NETIF_MSG_LINK, "phy link down\n");
-
-		vars->phy_link_up = 0;
-
-		vars->line_speed = 0;
-		vars->duplex = DUPLEX_FULL;
-		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-
-		/* indicate no mac active */
-		vars->mac_type = MAC_TYPE_NONE;
-		if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG)
-			vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
-	}
-
-	/* Sync media type */
-	sync_offset = params->shmem_base +
-			offsetof(struct shmem_region,
-				 dev_info.port_hw_config[port].media_type);
-	media_types = REG_RD(bp, sync_offset);
-
-	params->phy[INT_PHY].media_type =
-		(media_types & PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) >>
-		PORT_HW_CFG_MEDIA_TYPE_PHY0_SHIFT;
-	params->phy[EXT_PHY1].media_type =
-		(media_types & PORT_HW_CFG_MEDIA_TYPE_PHY1_MASK) >>
-		PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT;
-	params->phy[EXT_PHY2].media_type =
-		(media_types & PORT_HW_CFG_MEDIA_TYPE_PHY2_MASK) >>
-		PORT_HW_CFG_MEDIA_TYPE_PHY2_SHIFT;
-	DP(NETIF_MSG_LINK, "media_types = 0x%x\n", media_types);
-
-	/* Sync AEU offset */
-	sync_offset = params->shmem_base +
-			offsetof(struct shmem_region,
-				 dev_info.port_hw_config[port].aeu_int_mask);
-
-	vars->aeu_int_mask = REG_RD(bp, sync_offset);
-
-	/* Sync PFC status */
-	if (vars->link_status & LINK_STATUS_PFC_ENABLED)
-		params->feature_config_flags |=
-					FEATURE_CONFIG_PFC_ENABLED;
-	else
-		params->feature_config_flags &=
-					~FEATURE_CONFIG_PFC_ENABLED;
-
-	DP(NETIF_MSG_LINK, "link_status 0x%x  phy_link_up %x int_mask 0x%x\n",
-		 vars->link_status, vars->phy_link_up, vars->aeu_int_mask);
-	DP(NETIF_MSG_LINK, "line_speed %x  duplex %x  flow_ctrl 0x%x\n",
-		 vars->line_speed, vars->duplex, vars->flow_ctrl);
-}
-
-
-static void bnx2x_set_master_ln(struct link_params *params,
-				struct bnx2x_phy *phy)
-{
-	struct bnx2x *bp = params->bp;
-	u16 new_master_ln, ser_lane;
-	ser_lane = ((params->lane_config &
-		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
-		    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
-
-	/* set the master_ln for AN */
-	CL22_RD_OVER_CL45(bp, phy,
-			  MDIO_REG_BANK_XGXS_BLOCK2,
-			  MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
-			  &new_master_ln);
-
-	CL22_WR_OVER_CL45(bp, phy,
-			  MDIO_REG_BANK_XGXS_BLOCK2 ,
-			  MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
-			  (new_master_ln | ser_lane));
-}
-
-static int bnx2x_reset_unicore(struct link_params *params,
-			       struct bnx2x_phy *phy,
-			       u8 set_serdes)
-{
-	struct bnx2x *bp = params->bp;
-	u16 mii_control;
-	u16 i;
-	CL22_RD_OVER_CL45(bp, phy,
-			  MDIO_REG_BANK_COMBO_IEEE0,
-			  MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control);
-
-	/* reset the unicore */
-	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);
-
-	/* wait for the reset to self clear */
-	for (i = 0; i < MDIO_ACCESS_TIMEOUT; i++) {
-		udelay(5);
-
-		/* the reset erased the previous bank value */
-		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);
-			return 0;
-		}
-	}
-
-	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;
-
-}
-
-static void bnx2x_set_swap_lanes(struct link_params *params,
-				 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
-	 */
-	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);
-	rx_lane_swap = ((params->lane_config &
-			 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);
-
-	if (rx_lane_swap != 0x1b) {
-		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 {
-		CL22_WR_OVER_CL45(bp, phy,
-				  MDIO_REG_BANK_XGXS_BLOCK2,
-				  MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
-	}
-
-	if (tx_lane_swap != 0x1b) {
-		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 {
-		CL22_WR_OVER_CL45(bp, phy,
-				  MDIO_REG_BANK_XGXS_BLOCK2,
-				  MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
-	}
-}
-
-static void bnx2x_set_parallel_detection(struct bnx2x_phy *phy,
-					 struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u16 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);
-	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");
-
-		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);
-
-		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;
-
-		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 */
-		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 bnx2x *bp = params->bp;
-	u16 reg_val;
-
-	/* CL37 Autoneg */
-	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)
-		reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_AN_EN;
-	else /* CL37 Autoneg Disabled */
-		reg_val &= ~(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, reg_val);
-
-	/* Enable/Disable Autodetection */
-
-	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;
-	if (vars->line_speed == SPEED_AUTO_NEG)
-		reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
-	else
-		reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
-
-	CL22_WR_OVER_CL45(bp, phy,
-			  MDIO_REG_BANK_SERDES_DIGITAL,
-			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, reg_val);
-
-	/* Enable TetonII and BAM autoneg */
-	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 */
-		reg_val |= (MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
-			    MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
-	} else {
-		/* TetonII and BAM Autoneg Disabled */
-		reg_val &= ~(MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
-			     MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
-	}
-	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 */
-		CL22_WR_OVER_CL45(bp, phy,
-				  MDIO_REG_BANK_CL73_USERB0,
-				  MDIO_CL73_USERB0_CL73_UCTRL,
-				  0xe);
-
-		/* Enable BAM Station Manager*/
-		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 |
-			MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN |
-			MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN);
-
-		/* Advertise CL73 link speeds */
-		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;
-		if (phy->speed_cap_mask &
-		    PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
-			reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
-
-		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;
-
-	} else /* CL73 Autoneg Disabled */
-		reg_val = 0;
-
-	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 bnx2x *bp = params->bp;
-	u16 reg_val;
-
-	/* program duplex, disable autoneg and sgmii*/
-	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;
-	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)
-	 */
-	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);
-
-	reg_val &= ~(MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK |
-		     MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
-
-	if (!((vars->line_speed == SPEED_1000) ||
-	      (vars->line_speed == SPEED_100) ||
-	      (vars->line_speed == SPEED_10))) {
-
-		reg_val |= (MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M |
-			    MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
-		if (vars->line_speed == SPEED_10000)
-			reg_val |=
-				MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4;
-	}
-
-	CL22_WR_OVER_CL45(bp, phy,
-			  MDIO_REG_BANK_SERDES_DIGITAL,
-			  MDIO_SERDES_DIGITAL_MISC1, reg_val);
-
-}
-
-static void bnx2x_set_brcm_cl37_advertisement(struct bnx2x_phy *phy,
-					      struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val = 0;
-
-	/* configure the 48 bits for BAM AN */
-
-	/* set extended capabilities */
-	if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
-		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;
-	CL22_WR_OVER_CL45(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_UP3, 0x400);
-}
-
-static void bnx2x_set_ieee_aneg_advertisement(struct bnx2x_phy *phy,
-					      struct link_params *params,
-					      u16 ieee_fc)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val;
-	/* for AN, we are always publishing full duplex */
-
-	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);
-	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,
-				  struct link_params *params,
-				  u8 enable_cl73)
-{
-	struct bnx2x *bp = params->bp;
-	u16 mii_control;
-
-	DP(NETIF_MSG_LINK, "bnx2x_restart_autoneg\n");
-	/* Enable and restart BAM/CL37 aneg */
-
-	if (enable_cl73) {
-		CL22_RD_OVER_CL45(bp, phy,
-				  MDIO_REG_BANK_CL73_IEEEB0,
-				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
-				  &mii_control);
-
-		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 {
-
-		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);
-		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 bnx2x *bp = params->bp;
-	u16 control1;
-
-	/* in SGMII mode, the unicore is always slave */
-
-	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);
-	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;
-
-		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);
-
-		switch (vars->line_speed) {
-		case SPEED_100:
-			mii_control |=
-				MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_100;
-			break;
-		case SPEED_1000:
-			mii_control |=
-				MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_1000;
-			break;
-		case SPEED_10:
-			/* there is nothing to set for 10M */
-			break;
-		default:
-			/* invalid speed for SGMII */
-			DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
-				  vars->line_speed);
-			break;
-		}
-
-		/* setting the full duplex */
-		if (phy->req_duplex == DUPLEX_FULL)
-			mii_control |=
-				MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
-		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 */
-		bnx2x_restart_autoneg(phy, params, 0);
-	}
-}
-
-
-/*
- * link management
- */
-
-static int bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
-					     struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u16 pd_10g, status2_1000x;
-	if (phy->req_line_speed != SPEED_AUTO_NEG)
-		return 0;
-	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;
-	}
-
-	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",
-			 params->port);
-		return 1;
-	}
-	return 0;
-}
-
-static void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy,
-				    struct link_params *params,
-				    struct link_vars *vars,
-				    u32 gp_status)
-{
-	struct bnx2x *bp = params->bp;
-	u16 ld_pause;   /* local driver */
-	u16 lp_pause;   /* link partner */
-	u16 pause_result;
-
-	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-
-	/* resolve from gp_status in case of AN complete and not sgmii */
-	if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
-		vars->flow_ctrl = phy->req_flow_ctrl;
-	else if (phy->req_line_speed != SPEED_AUTO_NEG)
-		vars->flow_ctrl = params->req_fc_auto_adv;
-	else if ((gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
-		 (!(vars->phy_flags & PHY_SGMII_FLAG))) {
-		if (bnx2x_direct_parallel_detect_used(phy, params)) {
-			vars->flow_ctrl = params->req_fc_auto_adv;
-			return;
-		}
-		if ((gp_status &
-		    (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
-		     MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) ==
-		    (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
-		     MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) {
-
-			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;
-			pause_result |= (lp_pause &
-					MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK)
-					>> 10;
-			DP(NETIF_MSG_LINK, "pause_result CL73 0x%x\n",
-				 pause_result);
-		} else {
-			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;
-			DP(NETIF_MSG_LINK, "pause_result CL37 0x%x\n",
-				 pause_result);
-		}
-		bnx2x_pause_resolve(vars, pause_result);
-	}
-	DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
-}
-
-static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
-					 struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u16 rx_status, ustat_val, cl37_fsm_received;
-	DP(NETIF_MSG_LINK, "bnx2x_check_fallback_to_cl37\n");
-	/* Step 1: Make sure signal is detected */
-	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);
-		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 */
-	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)) !=
-	    (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK |
-	      MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) {
-		DP(NETIF_MSG_LINK, "CL73 state-machine is not stable. "
-			     "ustat_val(0x8371) = 0x%x\n", ustat_val);
-		return;
-	}
-	/*
-	 * 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_received);
-	if ((cl37_fsm_received &
-	     (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
-	     MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) !=
-	    (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
-	      MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) {
-		DP(NETIF_MSG_LINK, "No CL37 FSM were received. "
-			     "misc_rx_status(0x8330) = 0x%x\n",
-			 cl37_fsm_received);
-		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
-	 */
-
-	/* Disable CL73 */
-	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");
-}
-
-static void bnx2x_xgxs_an_resolve(struct bnx2x_phy *phy,
-				  struct link_params *params,
-				  struct link_vars *vars,
-				  u32 gp_status)
-{
-	if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE)
-		vars->link_status |=
-			LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
-
-	if (bnx2x_direct_parallel_detect_used(phy, params))
-		vars->link_status |=
-			LINK_STATUS_PARALLEL_DETECTION_USED;
-}
-static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
-				     struct link_params *params,
-				      struct link_vars *vars,
-				      u16 is_link_up,
-				      u16 speed_mask,
-				      u16 is_duplex)
-{
-	struct bnx2x *bp = params->bp;
-	if (phy->req_line_speed == SPEED_AUTO_NEG)
-		vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
-	if (is_link_up) {
-		DP(NETIF_MSG_LINK, "phy link up\n");
-
-		vars->phy_link_up = 1;
-		vars->link_status |= LINK_STATUS_LINK_UP;
-
-		switch (speed_mask) {
-		case GP_STATUS_10M:
-			vars->line_speed = SPEED_10;
-			if (vars->duplex == DUPLEX_FULL)
-				vars->link_status |= LINK_10TFD;
-			else
-				vars->link_status |= LINK_10THD;
-			break;
-
-		case GP_STATUS_100M:
-			vars->line_speed = SPEED_100;
-			if (vars->duplex == DUPLEX_FULL)
-				vars->link_status |= LINK_100TXFD;
-			else
-				vars->link_status |= LINK_100TXHD;
-			break;
-
-		case GP_STATUS_1G:
-		case GP_STATUS_1G_KX:
-			vars->line_speed = SPEED_1000;
-			if (vars->duplex == DUPLEX_FULL)
-				vars->link_status |= LINK_1000TFD;
-			else
-				vars->link_status |= LINK_1000THD;
-			break;
-
-		case GP_STATUS_2_5G:
-			vars->line_speed = SPEED_2500;
-			if (vars->duplex == DUPLEX_FULL)
-				vars->link_status |= LINK_2500TFD;
-			else
-				vars->link_status |= LINK_2500THD;
-			break;
-
-		case GP_STATUS_5G:
-		case GP_STATUS_6G:
-			DP(NETIF_MSG_LINK,
-				 "link speed unsupported  gp_status 0x%x\n",
-				  speed_mask);
-			return -EINVAL;
-
-		case GP_STATUS_10G_KX4:
-		case GP_STATUS_10G_HIG:
-		case GP_STATUS_10G_CX4:
-		case GP_STATUS_10G_KR:
-		case GP_STATUS_10G_SFI:
-		case GP_STATUS_10G_XFI:
-			vars->line_speed = SPEED_10000;
-			vars->link_status |= LINK_10GTFD;
-			break;
-		case GP_STATUS_20G_DXGXS:
-			vars->line_speed = SPEED_20000;
-			vars->link_status |= LINK_20GTFD;
-			break;
-		default:
-			DP(NETIF_MSG_LINK,
-				  "link speed unsupported gp_status 0x%x\n",
-				  speed_mask);
-			return -EINVAL;
-		}
-	} else { /* link_down */
-		DP(NETIF_MSG_LINK, "phy link down\n");
-
-		vars->phy_link_up = 0;
-
-		vars->duplex = DUPLEX_FULL;
-		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-		vars->mac_type = MAC_TYPE_NONE;
-	}
-	DP(NETIF_MSG_LINK, " phy_link_up %x line_speed %d\n",
-		    vars->phy_link_up, vars->line_speed);
-	return 0;
-}
-
-static int bnx2x_link_settings_status(struct bnx2x_phy *phy,
-				      struct link_params *params,
-				      struct link_vars *vars)
-{
-
-	struct bnx2x *bp = params->bp;
-
-	u16 gp_status, duplex = DUPLEX_HALF, link_up = 0, speed_mask;
-	int rc = 0;
-
-	/* Read gp_status */
-	CL22_RD_OVER_CL45(bp, phy,
-			  MDIO_REG_BANK_GP_STATUS,
-			  MDIO_GP_STATUS_TOP_AN_STATUS1,
-			  &gp_status);
-	if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
-		duplex = DUPLEX_FULL;
-	if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS)
-		link_up = 1;
-	speed_mask = gp_status & GP_STATUS_SPEED_MASK;
-	DP(NETIF_MSG_LINK, "gp_status 0x%x, is_link_up %d, speed_mask 0x%x\n",
-		       gp_status, link_up, speed_mask);
-	rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, speed_mask,
-					 duplex);
-	if (rc == -EINVAL)
-		return rc;
-
-	if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
-		if (SINGLE_MEDIA_DIRECT(params)) {
-			bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);
-			if (phy->req_line_speed == SPEED_AUTO_NEG)
-				bnx2x_xgxs_an_resolve(phy, params, vars,
-						      gp_status);
-		}
-	} else { /* link_down */
-		if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
-		    SINGLE_MEDIA_DIRECT(params)) {
-			/* Check signal is detected */
-			bnx2x_check_fallback_to_cl37(phy, params);
-		}
-	}
-
-	DP(NETIF_MSG_LINK, "duplex %x  flow_ctrl 0x%x link_status 0x%x\n",
-		   vars->duplex, vars->flow_ctrl, vars->link_status);
-	return rc;
-}
-
-static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
-				     struct link_params *params,
-				     struct link_vars *vars)
-{
-
-	struct bnx2x *bp = params->bp;
-
-	u8 lane;
-	u16 gp_status1, gp_speed, link_up, duplex = DUPLEX_FULL;
-	int rc = 0;
-	lane = bnx2x_get_warpcore_lane(phy, params);
-	/* Read gp_status */
-	if (phy->req_line_speed > SPEED_10000) {
-		u16 temp_link_up;
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				1, &temp_link_up);
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				1, &link_up);
-		DP(NETIF_MSG_LINK, "PCS RX link status = 0x%x-->0x%x\n",
-			       temp_link_up, link_up);
-		link_up &= (1<<2);
-		if (link_up)
-			bnx2x_ext_phy_resolve_fc(phy, params, vars);
-	} else {
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_GP2_STATUS_GP_2_1, &gp_status1);
-		DP(NETIF_MSG_LINK, "0x81d1 = 0x%x\n", gp_status1);
-		/* Check for either KR or generic link up. */
-		gp_status1 = ((gp_status1 >> 8) & 0xf) |
-			((gp_status1 >> 12) & 0xf);
-		link_up = gp_status1 & (1 << lane);
-		if (link_up && SINGLE_MEDIA_DIRECT(params)) {
-			u16 pd, gp_status4;
-			if (phy->req_line_speed == SPEED_AUTO_NEG) {
-				/* Check Autoneg complete */
-				bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-						MDIO_WC_REG_GP2_STATUS_GP_2_4,
-						&gp_status4);
-				if (gp_status4 & ((1<<12)<<lane))
-					vars->link_status |=
-					LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
-
-				/* Check parallel detect used */
-				bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-						MDIO_WC_REG_PAR_DET_10G_STATUS,
-						&pd);
-				if (pd & (1<<15))
-					vars->link_status |=
-					LINK_STATUS_PARALLEL_DETECTION_USED;
-			}
-			bnx2x_ext_phy_resolve_fc(phy, params, vars);
-		}
-	}
-
-	if (lane < 2) {
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_GP2_STATUS_GP_2_2, &gp_speed);
-	} else {
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_GP2_STATUS_GP_2_3, &gp_speed);
-	}
-	DP(NETIF_MSG_LINK, "lane %d gp_speed 0x%x\n", lane, gp_speed);
-
-	if ((lane & 1) == 0)
-		gp_speed <<= 8;
-	gp_speed &= 0x3f00;
-
-
-	rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, gp_speed,
-					 duplex);
-
-	DP(NETIF_MSG_LINK, "duplex %x  flow_ctrl 0x%x link_status 0x%x\n",
-		   vars->duplex, vars->flow_ctrl, vars->link_status);
-	return rc;
-}
-static void bnx2x_set_gmii_tx_driver(struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	struct bnx2x_phy *phy = &params->phy[INT_PHY];
-	u16 lp_up2;
-	u16 tx_driver;
-	u16 bank;
-
-	/* read precomp */
-	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) >>
-		   MDIO_OVER_1G_LP_UP2_PREEMPHASIS_SHIFT) <<
-		  MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT);
-
-	if (lp_up2 == 0)
-		return;
-
-	for (bank = MDIO_REG_BANK_TX0; bank <= MDIO_REG_BANK_TX3;
-	      bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0)) {
-		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;
-			CL22_WR_OVER_CL45(bp, phy,
-					  bank,
-					  MDIO_TX0_TX_DRIVER, tx_driver);
-		}
-	}
-}
-
-static int bnx2x_emac_program(struct link_params *params,
-			      struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	u16 mode = 0;
-
-	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));
-	switch (vars->line_speed) {
-	case SPEED_10:
-		mode |= EMAC_MODE_PORT_MII_10M;
-		break;
-
-	case SPEED_100:
-		mode |= EMAC_MODE_PORT_MII;
-		break;
-
-	case SPEED_1000:
-		mode |= EMAC_MODE_PORT_GMII;
-		break;
-
-	case SPEED_2500:
-		mode |= (EMAC_MODE_25G_MODE | EMAC_MODE_PORT_GMII);
-		break;
-
-	default:
-		/* 10G not valid for EMAC */
-		DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
-			   vars->line_speed);
-		return -EINVAL;
-	}
-
-	if (vars->duplex == DUPLEX_HALF)
-		mode |= EMAC_MODE_HALF_DUPLEX;
-	bnx2x_bits_en(bp,
-		      GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
-		      mode);
-
-	bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed);
-	return 0;
-}
-
-static void bnx2x_set_preemphasis(struct bnx2x_phy *phy,
-				  struct link_params *params)
-{
-
-	u16 bank, i = 0;
-	struct bnx2x *bp = params->bp;
-
-	for (bank = MDIO_REG_BANK_RX0, i = 0; bank <= MDIO_REG_BANK_RX3;
-	      bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0), i++) {
-			CL22_WR_OVER_CL45(bp, phy,
-					  bank,
-					  MDIO_RX0_RX_EQ_BOOST,
-					  phy->rx_preemphasis[i]);
-	}
-
-	for (bank = MDIO_REG_BANK_TX0, i = 0; bank <= MDIO_REG_BANK_TX3;
-		      bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0), i++) {
-			CL22_WR_OVER_CL45(bp, phy,
-					  bank,
-					  MDIO_TX0_TX_DRIVER,
-					  phy->tx_preemphasis[i]);
-	}
-}
-
-static void bnx2x_xgxs_config_init(struct bnx2x_phy *phy,
-				   struct link_params *params,
-				   struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u8 enable_cl73 = (SINGLE_MEDIA_DIRECT(params) ||
-			  (params->loopback_mode == LOOPBACK_XGXS));
-	if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
-		if (SINGLE_MEDIA_DIRECT(params) &&
-		    (params->feature_config_flags &
-		     FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED))
-			bnx2x_set_preemphasis(phy, params);
-
-		/* forced speed requested? */
-		if (vars->line_speed != SPEED_AUTO_NEG ||
-		    (SINGLE_MEDIA_DIRECT(params) &&
-		     params->loopback_mode == LOOPBACK_EXT)) {
-			DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
-
-			/* disable autoneg */
-			bnx2x_set_autoneg(phy, params, vars, 0);
-
-			/* program speed and duplex */
-			bnx2x_program_serdes(phy, params, vars);
-
-		} else { /* AN_mode */
-			DP(NETIF_MSG_LINK, "not SGMII, AN\n");
-
-			/* AN enabled */
-			bnx2x_set_brcm_cl37_advertisement(phy, params);
-
-			/* program duplex & pause advertisement (for aneg) */
-			bnx2x_set_ieee_aneg_advertisement(phy, params,
-							  vars->ieee_fc);
-
-			/* enable autoneg */
-			bnx2x_set_autoneg(phy, params, vars, enable_cl73);
-
-			/* enable and restart AN */
-			bnx2x_restart_autoneg(phy, params, enable_cl73);
-		}
-
-	} else { /* SGMII mode */
-		DP(NETIF_MSG_LINK, "SGMII\n");
-
-		bnx2x_initialize_sgmii_process(phy, params, vars);
-	}
-}
-
-static int bnx2x_prepare_xgxs(struct bnx2x_phy *phy,
-			  struct link_params *params,
-			  struct link_vars *vars)
-{
-	int rc;
-	vars->phy_flags |= PHY_XGXS_FLAG;
-	if ((phy->req_line_speed &&
-	     ((phy->req_line_speed == SPEED_100) ||
-	      (phy->req_line_speed == SPEED_10))) ||
-	    (!phy->req_line_speed &&
-	     (phy->speed_cap_mask >=
-	      PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
-	     (phy->speed_cap_mask <
-	      PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
-	    (phy->type == PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT_SD))
-		vars->phy_flags |= PHY_SGMII_FLAG;
-	else
-		vars->phy_flags &= ~PHY_SGMII_FLAG;
-
-	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
-	bnx2x_set_aer_mmd(params, phy);
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
-		bnx2x_set_master_ln(params, phy);
-
-	rc = bnx2x_reset_unicore(params, phy, 0);
-	/* reset the SerDes and wait for reset bit return low */
-	if (rc != 0)
-		return rc;
-
-	bnx2x_set_aer_mmd(params, phy);
-	/* setting the masterLn_def again after the reset */
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
-		bnx2x_set_master_ln(params, phy);
-		bnx2x_set_swap_lanes(params, phy);
-	}
-
-	return rc;
-}
-
-static u16 bnx2x_wait_reset_complete(struct bnx2x *bp,
-				     struct bnx2x_phy *phy,
-				     struct link_params *params)
-{
-	u16 cnt, ctrl;
-	/* Wait for soft reset to get cleared up to 1 sec */
-	for (cnt = 0; cnt < 1000; cnt++) {
-		if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE)
-			bnx2x_cl22_read(bp, phy,
-				MDIO_PMA_REG_CTRL, &ctrl);
-		else
-			bnx2x_cl45_read(bp, phy,
-				MDIO_PMA_DEVAD,
-				MDIO_PMA_REG_CTRL, &ctrl);
-		if (!(ctrl & (1<<15)))
-			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;
-}
-
-static void bnx2x_link_int_enable(struct link_params *params)
-{
-	u8 port = params->port;
-	u32 mask;
-	struct bnx2x *bp = params->bp;
-
-	/* Setting the status to report on link up for either XGXS or SerDes */
-	if (CHIP_IS_E3(bp)) {
-		mask = NIG_MASK_XGXS0_LINK_STATUS;
-		if (!(SINGLE_MEDIA_DIRECT(params)))
-			mask |= NIG_MASK_MI_INT;
-	} else if (params->switch_cfg == SWITCH_CFG_10G) {
-		mask = (NIG_MASK_XGXS0_LINK10G |
-			NIG_MASK_XGXS0_LINK_STATUS);
-		DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n");
-		if (!(SINGLE_MEDIA_DIRECT(params)) &&
-			params->phy[INT_PHY].type !=
-				PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) {
-			mask |= NIG_MASK_MI_INT;
-			DP(NETIF_MSG_LINK, "enabled external phy int\n");
-		}
-
-	} else { /* SerDes */
-		mask = NIG_MASK_SERDES0_LINK_STATUS;
-		DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n");
-		if (!(SINGLE_MEDIA_DIRECT(params)) &&
-			params->phy[INT_PHY].type !=
-				PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN) {
-			mask |= NIG_MASK_MI_INT;
-			DP(NETIF_MSG_LINK, "enabled external phy int\n");
-		}
-	}
-	bnx2x_bits_en(bp,
-		      NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
-		      mask);
-
-	DP(NETIF_MSG_LINK, "port %x, is_xgxs %x, int_status 0x%x\n", port,
-		 (params->switch_cfg == SWITCH_CFG_10G),
-		 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
-	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),
-		 REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
-		 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),
-	   REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
-}
-
-static void bnx2x_rearm_latch_signal(struct bnx2x *bp, u8 port,
-				     u8 exp_mi_int)
-{
-	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
-	 */
-	/* Read Latched signals */
-	latch_status = REG_RD(bp,
-				    NIG_REG_LATCH_STATUS_0 + port*8);
-	DP(NETIF_MSG_LINK, "latch_status = 0x%x\n", latch_status);
-	/* Handle only those with latched-signal=up.*/
-	if (exp_mi_int)
-		bnx2x_bits_en(bp,
-			      NIG_REG_STATUS_INTERRUPT_PORT0
-			      + port*4,
-			      NIG_STATUS_EMAC0_MI_INT);
-	else
-		bnx2x_bits_dis(bp,
-			       NIG_REG_STATUS_INTERRUPT_PORT0
-			       + port*4,
-			       NIG_STATUS_EMAC0_MI_INT);
-
-	if (latch_status & 1) {
-
-		/* 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));
-	}
-	/* 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_plus)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	u32 mask;
-	/*
-	 * 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));
-	if (vars->phy_link_up) {
-		if (USES_WARPCORE(bp))
-			mask = NIG_STATUS_XGXS0_LINK_STATUS;
-		else {
-			if (is_10g_plus)
-				mask = 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
-				 */
-				u32 ser_lane =
-					((params->lane_config &
-				    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
-				    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
-				mask = ((1 << ser_lane) <<
-				       NIG_STATUS_XGXS0_LINK_STATUS_SIZE);
-			} else
-				mask = NIG_STATUS_SERDES0_LINK_STATUS;
-		}
-		DP(NETIF_MSG_LINK, "Ack link up interrupt with mask 0x%x\n",
-			       mask);
-		bnx2x_bits_en(bp,
-			      NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
-			      mask);
-	}
-}
-
-static int bnx2x_format_ver(u32 num, u8 *str, u16 *len)
-{
-	u8 *str_ptr = str;
-	u32 mask = 0xf0000000;
-	u8 shift = 8*4;
-	u8 digit;
-	u8 remove_leading_zeros = 1;
-	if (*len < 10) {
-		/* Need more than 10chars for this format */
-		*str_ptr = '\0';
-		(*len)--;
-		return -EINVAL;
-	}
-	while (shift > 0) {
-
-		shift -= 4;
-		digit = ((num & mask) >> shift);
-		if (digit == 0 && remove_leading_zeros) {
-			mask = mask >> 4;
-			continue;
-		} else if (digit < 0xa)
-			*str_ptr = digit + '0';
-		else
-			*str_ptr = digit - 0xa + 'a';
-		remove_leading_zeros = 0;
-		str_ptr++;
-		(*len)--;
-		mask = mask >> 4;
-		if (shift == 4*4) {
-			*str_ptr = '.';
-			str_ptr++;
-			(*len)--;
-			remove_leading_zeros = 1;
-		}
-	}
-	return 0;
-}
-
-
-static int bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
-{
-	str[0] = '\0';
-	(*len)--;
-	return 0;
-}
-
-int bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
-				 u8 *version, u16 len)
-{
-	struct bnx2x *bp;
-	u32 spirom_ver = 0;
-	int status = 0;
-	u8 *ver_p = version;
-	u16 remain_len = len;
-	if (version == NULL || params == NULL)
-		return -EINVAL;
-	bp = params->bp;
-
-	/* Extract first external phy*/
-	version[0] = '\0';
-	spirom_ver = REG_RD(bp, params->phy[EXT_PHY1].ver_addr);
-
-	if (params->phy[EXT_PHY1].format_fw_ver) {
-		status |= params->phy[EXT_PHY1].format_fw_ver(spirom_ver,
-							      ver_p,
-							      &remain_len);
-		ver_p += (len - remain_len);
-	}
-	if ((params->num_phys == MAX_PHYS) &&
-	    (params->phy[EXT_PHY2].ver_addr != 0)) {
-		spirom_ver = REG_RD(bp, params->phy[EXT_PHY2].ver_addr);
-		if (params->phy[EXT_PHY2].format_fw_ver) {
-			*ver_p = '/';
-			ver_p++;
-			remain_len--;
-			status |= params->phy[EXT_PHY2].format_fw_ver(
-				spirom_ver,
-				ver_p,
-				&remain_len);
-			ver_p = version + (len - remain_len);
-		}
-	}
-	*ver_p = '\0';
-	return status;
-}
-
-static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy,
-				    struct link_params *params)
-{
-	u8 port = params->port;
-	struct bnx2x *bp = params->bp;
-
-	if (phy->req_line_speed != SPEED_1000) {
-		u32 md_devad = 0;
-
-		DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n");
-
-		if (!CHIP_IS_E3(bp)) {
-			/* change the uni_phy_addr in the nig */
-			md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
-					       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);
-
-		bnx2x_cl45_write(bp, phy,
-				 5,
-				 (MDIO_REG_BANK_CL73_IEEEB0 +
-				  (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
-				 0x6041);
-		msleep(200);
-		/* set aer mmd back */
-		bnx2x_set_aer_mmd(params, phy);
-
-		if (!CHIP_IS_E3(bp)) {
-			/* and 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");
-		bnx2x_cl45_read(bp, phy, 5,
-				(MDIO_REG_BANK_COMBO_IEEE0 +
-				(MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)),
-				&mii_ctrl);
-		bnx2x_cl45_write(bp, phy, 5,
-				 (MDIO_REG_BANK_COMBO_IEEE0 +
-				 (MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)),
-				 mii_ctrl |
-				 MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK);
-	}
-}
-
-int bnx2x_set_led(struct link_params *params,
-		  struct link_vars *vars, u8 mode, u32 speed)
-{
-	u8 port = params->port;
-	u16 hw_led_mode = params->hw_led_mode;
-	int rc = 0;
-	u8 phy_idx;
-	u32 tmp;
-	u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-	struct bnx2x *bp = params->bp;
-	DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode);
-	DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n",
-		 speed, hw_led_mode);
-	/* In case */
-	for (phy_idx = EXT_PHY1; phy_idx < MAX_PHYS; phy_idx++) {
-		if (params->phy[phy_idx].set_link_led) {
-			params->phy[phy_idx].set_link_led(
-				&params->phy[phy_idx], params, mode);
-		}
-	}
-
-	switch (mode) {
-	case LED_MODE_FRONT_PANEL_OFF:
-	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);
-
-		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) ||
-			 (params->phy[EXT_PHY1].type ==
-			  PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722)) &&
-		    CHIP_IS_E2(bp) && params->num_phys == 2) {
-			/*
-			 * 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);
-				REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1);
-
-				tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
-				EMAC_WR(bp, EMAC_REG_EMAC_LED,
-					(tmp | EMAC_LED_OVERRIDE));
-				/*
-				 * return here without enabling traffic
-				 * LED blink and setting rate in ON mode.
-				 * In oper mode, enabling LED blink
-				 * and setting rate is needed.
-				 */
-				if (mode == LED_MODE_ON)
-					return rc;
-			}
-		} else if (SINGLE_MEDIA_DIRECT(params)) {
-			/*
-			 * This is a work-around for HW issue found when link
-			 * is up in CL73
-			 */
-			if ((!CHIP_IS_E3(bp)) ||
-			    (CHIP_IS_E3(bp) &&
-			     mode == LED_MODE_ON))
-				REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1);
-
-			if (CHIP_IS_E1x(bp) ||
-			    CHIP_IS_E2(bp) ||
-			    (mode == LED_MODE_ON))
-				REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
-			else
-				REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
-				       hw_led_mode);
-		} else
-			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);
-		/* Set blinking rate to ~15.9Hz */
-		REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
-		       LED_BLINK_RATE_VAL);
-		REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
-		       port*4, 1);
-		tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
-		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
-			 */
-			REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
-			       + port*4, 1);
-			REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 +
-			       port*4, 0);
-			REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 +
-			       port*4, 1);
-		}
-		break;
-
-	default:
-		rc = -EINVAL;
-		DP(NETIF_MSG_LINK, "bnx2x_set_led: Invalid led mode %d\n",
-			 mode);
-		break;
-	}
-	return rc;
-
-}
-
-/*
- * This function comes to reflect the actual link state read DIRECTLY from the
- * HW
- */
-int bnx2x_test_link(struct link_params *params, struct link_vars *vars,
-		    u8 is_serdes)
-{
-	struct bnx2x *bp = params->bp;
-	u16 gp_status = 0, phy_index = 0;
-	u8 ext_phy_link_up = 0, serdes_phy_type;
-	struct link_vars temp_vars;
-	struct bnx2x_phy *int_phy = &params->phy[INT_PHY];
-
-	if (CHIP_IS_E3(bp)) {
-		u16 link_up;
-		if (params->req_line_speed[LINK_CONFIG_IDX(INT_PHY)]
-		    > SPEED_10000) {
-			/* Check 20G link */
-			bnx2x_cl45_read(bp, int_phy, MDIO_WC_DEVAD,
-					1, &link_up);
-			bnx2x_cl45_read(bp, int_phy, MDIO_WC_DEVAD,
-					1, &link_up);
-			link_up &= (1<<2);
-		} else {
-			/* Check 10G link and below*/
-			u8 lane = bnx2x_get_warpcore_lane(int_phy, params);
-			bnx2x_cl45_read(bp, int_phy, MDIO_WC_DEVAD,
-					MDIO_WC_REG_GP2_STATUS_GP_2_1,
-					&gp_status);
-			gp_status = ((gp_status >> 8) & 0xf) |
-				((gp_status >> 12) & 0xf);
-			link_up = gp_status & (1 << lane);
-		}
-		if (!link_up)
-			return -ESRCH;
-	} else {
-		CL22_RD_OVER_CL45(bp, 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;
-	}
-	/* In XGXS loopback mode, do not check external PHY */
-	if (params->loopback_mode == LOOPBACK_XGXS)
-		return 0;
-
-	switch (params->num_phys) {
-	case 1:
-		/* No external PHY */
-		return 0;
-	case 2:
-		ext_phy_link_up = params->phy[EXT_PHY1].read_status(
-			&params->phy[EXT_PHY1],
-			params, &temp_vars);
-		break;
-	case 3: /* Dual Media */
-		for (phy_index = EXT_PHY1; phy_index < params->num_phys;
-		      phy_index++) {
-			serdes_phy_type = ((params->phy[phy_index].media_type ==
-					    ETH_PHY_SFP_FIBER) ||
-					   (params->phy[phy_index].media_type ==
-					    ETH_PHY_XFP_FIBER) ||
-					   (params->phy[phy_index].media_type ==
-					    ETH_PHY_DA_TWINAX));
-
-			if (is_serdes != serdes_phy_type)
-				continue;
-			if (params->phy[phy_index].read_status) {
-				ext_phy_link_up |=
-					params->phy[phy_index].read_status(
-						&params->phy[phy_index],
-						params, &temp_vars);
-			}
-		}
-		break;
-	}
-	if (ext_phy_link_up)
-		return 0;
-	return -ESRCH;
-}
-
-static int bnx2x_link_initialize(struct link_params *params,
-				 struct link_vars *vars)
-{
-	int 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
-	 */
-	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.
-	 */
-	if (!USES_WARPCORE(bp))
-		bnx2x_prepare_xgxs(&params->phy[INT_PHY], params, vars);
-	/* init ext phy and enable link state int */
-	non_ext_phy = (SINGLE_MEDIA_DIRECT(params) ||
-		       (params->loopback_mode == LOOPBACK_XGXS));
-
-	if (non_ext_phy ||
-	    (params->phy[EXT_PHY1].flags & FLAGS_INIT_XGXS_FIRST) ||
-	    (params->loopback_mode == LOOPBACK_EXT_PHY)) {
-		struct bnx2x_phy *phy = &params->phy[INT_PHY];
-		if (vars->line_speed == SPEED_AUTO_NEG &&
-		    (CHIP_IS_E1x(bp) ||
-		     CHIP_IS_E2(bp)))
-			bnx2x_set_parallel_detection(phy, params);
-			if (params->phy[INT_PHY].config_init)
-				params->phy[INT_PHY].config_init(phy,
-								 params,
-								 vars);
-	}
-
-	/* Init external phy*/
-	if (non_ext_phy) {
-		if (params->phy[INT_PHY].supported &
-		    SUPPORTED_FIBRE)
-			vars->link_status |= LINK_STATUS_SERDES_LINK;
-	} else {
-		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 (params->phy[phy_index].supported &
-			    SUPPORTED_FIBRE)
-				vars->link_status |= LINK_STATUS_SERDES_LINK;
-
-			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");
-				continue;
-			}
-			params->phy[phy_index].config_init(
-				&params->phy[phy_index],
-				params, vars);
-		}
-	}
-	/* Reset the interrupt indication after phy was initialized */
-	bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 +
-		       params->port*4,
-		       (NIG_STATUS_XGXS0_LINK10G |
-			NIG_STATUS_XGXS0_LINK_STATUS |
-			NIG_STATUS_SERDES0_LINK_STATUS |
-			NIG_MASK_MI_INT));
-	bnx2x_update_mng(params, vars->link_status);
-	return rc;
-}
-
-static void bnx2x_int_link_reset(struct bnx2x_phy *phy,
-				 struct link_params *params)
-{
-	/* reset the SerDes/XGXS */
-	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,
-					struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u8 gpio_port;
-	/* HW reset */
-	if (CHIP_IS_E2(bp))
-		gpio_port = BP_PATH(bp);
-	else
-		gpio_port = params->port;
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-		       MISC_REGISTERS_GPIO_OUTPUT_LOW,
-		       gpio_port);
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-		       MISC_REGISTERS_GPIO_OUTPUT_LOW,
-		       gpio_port);
-	DP(NETIF_MSG_LINK, "reset external PHY\n");
-}
-
-static int bnx2x_update_link_down(struct link_params *params,
-				  struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-
-	DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
-	bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
-	vars->phy_flags &= ~PHY_PHYSICAL_LINK_FLAG;
-	/* indicate no mac active */
-	vars->mac_type = MAC_TYPE_NONE;
-
-	/* update shared memory */
-	vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK |
-			       LINK_STATUS_LINK_UP |
-			       LINK_STATUS_PHYSICAL_LINK_FLAG |
-			       LINK_STATUS_AUTO_NEGOTIATE_COMPLETE |
-			       LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK |
-			       LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK |
-			       LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK);
-	vars->line_speed = 0;
-	bnx2x_update_mng(params, vars->link_status);
-
-	/* activate nig drain */
-	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
-
-	/* disable emac */
-	if (!CHIP_IS_E3(bp))
-		REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
-
-	msleep(10);
-	/* reset BigMac/Xmac */
-	if (CHIP_IS_E1x(bp) ||
-	    CHIP_IS_E2(bp)) {
-		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));
-	}
-	if (CHIP_IS_E3(bp))
-		bnx2x_xmac_disable(params);
-
-	return 0;
-}
-
-static int bnx2x_update_link_up(struct link_params *params,
-				struct link_vars *vars,
-				u8 link_10g)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	int rc = 0;
-
-	vars->link_status |= (LINK_STATUS_LINK_UP |
-			      LINK_STATUS_PHYSICAL_LINK_FLAG);
-	vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
-
-	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
-		vars->link_status |=
-			LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
-
-	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
-		vars->link_status |=
-			LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
-	if (USES_WARPCORE(bp)) {
-		if (link_10g) {
-			if (bnx2x_xmac_enable(params, vars, 0) ==
-			    -ESRCH) {
-				DP(NETIF_MSG_LINK, "Found errors on XMAC\n");
-				vars->link_up = 0;
-				vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
-				vars->link_status &= ~LINK_STATUS_LINK_UP;
-			}
-		} else
-			bnx2x_umac_enable(params, vars, 0);
-		bnx2x_set_led(params, vars,
-			      LED_MODE_OPER, vars->line_speed);
-	}
-	if ((CHIP_IS_E1x(bp) ||
-	     CHIP_IS_E2(bp))) {
-		if (link_10g) {
-			if (bnx2x_bmac_enable(params, vars, 0) ==
-			    -ESRCH) {
-				DP(NETIF_MSG_LINK, "Found errors on BMAC\n");
-				vars->link_up = 0;
-				vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
-				vars->link_status &= ~LINK_STATUS_LINK_UP;
-			}
-
-			bnx2x_set_led(params, vars,
-				      LED_MODE_OPER, SPEED_10000);
-		} else {
-			rc = bnx2x_emac_program(params, vars);
-			bnx2x_emac_enable(params, vars, 0);
-
-			/* AN complete? */
-			if ((vars->link_status &
-			     LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
-			    && (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
-			    SINGLE_MEDIA_DIRECT(params))
-				bnx2x_set_gmii_tx_driver(params);
-		}
-	}
-
-	/* PBF - link up */
-	if (CHIP_IS_E1x(bp))
-		rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
-				       vars->line_speed);
-
-	/* disable drain */
-	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
-
-	/* update shared memory */
-	bnx2x_update_mng(params, vars->link_status);
-	msleep(20);
-	return rc;
-}
-/*
- * The bnx2x_link_update function should be called upon link
- * interrupt.
- * Link is considered up as follows:
- * - DIRECT_SINGLE_MEDIA - Only XGXS link (internal link) needs
- *   to be up
- * - SINGLE_MEDIA - The link between the 577xx and the external
- *   phy (XGXS) need to up as well as the external link of the
- *   phy (PHY_EXT1)
- * - DUAL_MEDIA - The link between the 577xx and the first
- *   external phy needs to be up, and at least one of the 2
- *   external phy link must be up.
- */
-int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	struct link_vars phy_vars[MAX_PHYS];
-	u8 port = params->port;
-	u8 link_10g_plus, phy_index;
-	u8 ext_phy_link_up = 0, cur_link_up;
-	int rc = 0;
-	u8 is_mi_int = 0;
-	u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
-	u8 active_external_phy = INT_PHY;
-	vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
-	for (phy_index = INT_PHY; phy_index < params->num_phys;
-	      phy_index++) {
-		phy_vars[phy_index].flow_ctrl = 0;
-		phy_vars[phy_index].link_status = 0;
-		phy_vars[phy_index].line_speed = 0;
-		phy_vars[phy_index].duplex = DUPLEX_FULL;
-		phy_vars[phy_index].phy_link_up = 0;
-		phy_vars[phy_index].link_up = 0;
-		phy_vars[phy_index].fault_detected = 0;
-	}
-
-	if (USES_WARPCORE(bp))
-		bnx2x_set_aer_mmd(params, &params->phy[INT_PHY]);
-
-	DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
-		 port, (vars->phy_flags & PHY_XGXS_FLAG),
-		 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);
-	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));
-
-	DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
-	  REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
-	  REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
-
-	/* disable emac */
-	if (!CHIP_IS_E3(bp))
-		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 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];
-		if (!phy->read_status)
-			continue;
-		/* Read link status and params of this ext phy */
-		cur_link_up = phy->read_status(phy, params,
-					       &phy_vars[phy_index]);
-		if (cur_link_up) {
-			DP(NETIF_MSG_LINK, "phy in index %d link is up\n",
-				   phy_index);
-		} else {
-			DP(NETIF_MSG_LINK, "phy in index %d link is down\n",
-				   phy_index);
-			continue;
-		}
-
-		if (!ext_phy_link_up) {
-			ext_phy_link_up = 1;
-			active_external_phy = phy_index;
-		} else {
-			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,
-			 * hence its link is expected to be down
-			 * - 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);
-				ext_phy_link_up = 0;
-				break;
-			}
-		}
-	}
-	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
-	 */
-	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
-	 * to the vars. The ext_phy_line_speed is needed to check if the
-	 * speed is different between the internal phy and external phy.
-	 * This case may be result of intermediate link speed change.
-	 */
-	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
-		 */
-		if (active_external_phy == EXT_PHY1) {
-			if (params->phy[EXT_PHY2].phy_specific_func) {
-				DP(NETIF_MSG_LINK, "Disabling TX on"
-						   " EXT_PHY2\n");
-				params->phy[EXT_PHY2].phy_specific_func(
-					&params->phy[EXT_PHY2],
-					params, DISABLE_TX);
-			}
-		}
-
-		ext_phy_line_speed = phy_vars[active_external_phy].line_speed;
-		vars->duplex = phy_vars[active_external_phy].duplex;
-		if (params->phy[active_external_phy].supported &
-		    SUPPORTED_FIBRE)
-			vars->link_status |= LINK_STATUS_SERDES_LINK;
-		else
-			vars->link_status &= ~LINK_STATUS_SERDES_LINK;
-		DP(NETIF_MSG_LINK, "Active external phy selected: %x\n",
-			   active_external_phy);
-	}
-
-	for (phy_index = EXT_PHY1; phy_index < params->num_phys;
-	      phy_index++) {
-		if (params->phy[phy_index].flags &
-		    FLAGS_REARM_LATCH_SIGNAL) {
-			bnx2x_rearm_latch_signal(bp, port,
-						 phy_index ==
-						 active_external_phy);
-			break;
-		}
-	}
-	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
-	 */
-
-	if (vars->phy_link_up) {
-		if (!(SINGLE_MEDIA_DIRECT(params)) && ext_phy_link_up &&
-		    (ext_phy_line_speed != vars->line_speed)) {
-			DP(NETIF_MSG_LINK, "Internal link speed %d is"
-				   " different than the external"
-				   " link speed %d\n", vars->line_speed,
-				   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);
-			msleep(1);
-		}
-	}
-
-	/* anything 10 and over uses the bmac */
-	link_10g_plus = (vars->line_speed >= SPEED_10000);
-
-	bnx2x_link_int_ack(params, vars, link_10g_plus);
-
-	/*
-	 * 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,
-			   vars->phy_link_up,
-			   params->phy[EXT_PHY1].flags &
-			   FLAGS_INIT_XGXS_FIRST);
-		if (!(params->phy[EXT_PHY1].flags &
-		      FLAGS_INIT_XGXS_FIRST)
-		    && ext_phy_link_up && !vars->phy_link_up) {
-			vars->line_speed = ext_phy_line_speed;
-			if (vars->line_speed < SPEED_1000)
-				vars->phy_flags |= PHY_SGMII_FLAG;
-			else
-				vars->phy_flags &= ~PHY_SGMII_FLAG;
-
-			if (params->phy[INT_PHY].config_init)
-				params->phy[INT_PHY].config_init(
-					&params->phy[INT_PHY], params,
-						vars);
-		}
-	}
-	/*
-	 * Link is up only if both local phy and external phy (in case of
-	 * non-direct board) are up and no fault detected on active PHY.
-	 */
-	vars->link_up = (vars->phy_link_up &&
-			 (ext_phy_link_up ||
-			  SINGLE_MEDIA_DIRECT(params)) &&
-			 (phy_vars[active_external_phy].fault_detected == 0));
-
-	if (vars->link_up)
-		rc = bnx2x_update_link_up(params, vars, link_10g_plus);
-	else
-		rc = bnx2x_update_link_down(params, vars);
-
-	return rc;
-}
-
-
-/*****************************************************************************/
-/*			    External Phy section			     */
-/*****************************************************************************/
-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);
-	msleep(1);
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
-}
-
-static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port,
-				      u32 spirom_ver, u32 ver_addr)
-{
-	DP(NETIF_MSG_LINK, "FW version 0x%x:0x%x for port %d\n",
-		 (u16)(spirom_ver>>16), (u16)spirom_ver, port);
-
-	if (ver_addr)
-		REG_WR(bp, ver_addr, spirom_ver);
-}
-
-static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp,
-				      struct bnx2x_phy *phy,
-				      u8 port)
-{
-	u16 fw_ver1, fw_ver2;
-
-	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_ROM_VER1, &fw_ver1);
-	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_ROM_VER2, &fw_ver2);
-	bnx2x_save_spirom_version(bp, port, (u32)(fw_ver1<<16 | fw_ver2),
-				  phy->ver_addr);
-}
-
-static void bnx2x_ext_phy_10G_an_resolve(struct bnx2x *bp,
-				       struct bnx2x_phy *phy,
-				       struct link_vars *vars)
-{
-	u16 val;
-	bnx2x_cl45_read(bp, phy,
-			MDIO_AN_DEVAD,
-			MDIO_AN_REG_STATUS, &val);
-	bnx2x_cl45_read(bp, phy,
-			MDIO_AN_DEVAD,
-			MDIO_AN_REG_STATUS, &val);
-	if (val & (1<<5))
-		vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
-	if ((val & (1<<0)) == 0)
-		vars->link_status |= LINK_STATUS_PARALLEL_DETECTION_USED;
-}
-
-/******************************************************************/
-/*		common BCM8073/BCM8727 PHY SECTION		  */
-/******************************************************************/
-static void bnx2x_8073_resolve_fc(struct bnx2x_phy *phy,
-				  struct link_params *params,
-				  struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	if (phy->req_line_speed == SPEED_10 ||
-	    phy->req_line_speed == SPEED_100) {
-		vars->flow_ctrl = phy->req_flow_ctrl;
-		return;
-	}
-
-	if (bnx2x_ext_phy_resolve_fc(phy, params, vars) &&
-	    (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE)) {
-		u16 pause_result;
-		u16 ld_pause;		/* local */
-		u16 lp_pause;		/* link partner */
-		bnx2x_cl45_read(bp, phy,
-				MDIO_AN_DEVAD,
-				MDIO_AN_REG_CL37_FC_LD, &ld_pause);
-
-		bnx2x_cl45_read(bp, phy,
-				MDIO_AN_DEVAD,
-				MDIO_AN_REG_CL37_FC_LP, &lp_pause);
-		pause_result = (ld_pause &
-				MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
-		pause_result |= (lp_pause &
-				 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
-
-		bnx2x_pause_resolve(vars, pause_result);
-		DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n",
-			   pause_result);
-	}
-}
-static int bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
-					     struct bnx2x_phy *phy,
-					     u8 port)
-{
-	u32 count = 0;
-	u16 fw_ver1, fw_msgout;
-	int rc = 0;
-
-	/* Boot port from external ROM  */
-	/* EDC grst */
-	bnx2x_cl45_write(bp, phy,
-			 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);
-
-	bnx2x_cl45_write(bp, phy,
-			 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);
-
-	/* 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);
-
-	/* Delay 100ms per the PHY specifications */
-	msleep(100);
-
-	/* 8073 sometimes taking longer to download */
-	do {
-		count++;
-		if (count > 300) {
-			DP(NETIF_MSG_LINK,
-				 "bnx2x_8073_8727_external_rom_boot port %x:"
-				 "Download failed. fw version = 0x%x\n",
-				 port, fw_ver1);
-			rc = -EINVAL;
-			break;
-		}
-
-		bnx2x_cl45_read(bp, phy,
-				MDIO_PMA_DEVAD,
-				MDIO_PMA_REG_ROM_VER1, &fw_ver1);
-		bnx2x_cl45_read(bp, phy,
-				MDIO_PMA_DEVAD,
-				MDIO_PMA_REG_M8051_MSGOUT_REG, &fw_msgout);
-
-		msleep(1);
-	} while (fw_ver1 == 0 || fw_ver1 == 0x4321 ||
-			((fw_msgout & 0xff) != 0x03 && (phy->type ==
-			PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)));
-
-	/* Clear ser_boot_ctl bit */
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
-	bnx2x_save_bcm_spirom_ver(bp, phy, port);
-
-	DP(NETIF_MSG_LINK,
-		 "bnx2x_8073_8727_external_rom_boot port %x:"
-		 "Download complete. fw version = 0x%x\n",
-		 port, fw_ver1);
-
-	return rc;
-}
-
-/******************************************************************/
-/*			BCM8073 PHY SECTION			  */
-/******************************************************************/
-static int bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy)
-{
-	/* This is only required for 8073A1, version 102 only */
-	u16 val;
-
-	/* Read 8073 HW revision*/
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_8073_CHIP_REV, &val);
-
-	if (val != 1) {
-		/* No need to workaround in 8073 A1 */
-		return 0;
-	}
-
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_ROM_VER2, &val);
-
-	/* SNR should be applied only for version 0x102 */
-	if (val != 0x102)
-		return 0;
-
-	return 1;
-}
-
-static int bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
-{
-	u16 val, cnt, cnt1 ;
-
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_8073_CHIP_REV, &val);
-
-	if (val > 0) {
-		/* No need to workaround in 8073 A1 */
-		return 0;
-	}
-	/* XAUI workaround in 8073 A0: */
-
-	/*
-	 * 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).
-		   */
-		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, "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,
-					MDIO_PMA_REG_8073_XAUI_WA, &val);
-				if (val & (1<<15)) {
-					DP(NETIF_MSG_LINK,
-					  "XAUI workaround has completed\n");
-					return 0;
-				 }
-				 msleep(3);
-			}
-			break;
-		}
-		msleep(3);
-	}
-	DP(NETIF_MSG_LINK, "Warning: XAUI work-around timeout !!!\n");
-	return -EINVAL;
-}
-
-static void bnx2x_807x_force_10G(struct bnx2x *bp, struct bnx2x_phy *phy)
-{
-	/* Force KR or KX */
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x2040);
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0x000b);
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_BCM_CTRL, 0x0000);
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000);
-}
-
-static void bnx2x_8073_set_pause_cl37(struct link_params *params,
-				      struct bnx2x_phy *phy,
-				      struct link_vars *vars)
-{
-	u16 cl37_val;
-	struct bnx2x *bp = params->bp;
-	bnx2x_cl45_read(bp, phy,
-			MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &cl37_val);
-
-	cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
-	/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
-	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
-	if ((vars->ieee_fc &
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) ==
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) {
-		cl37_val |=  MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC;
-	}
-	if ((vars->ieee_fc &
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
-		cl37_val |=  MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
-	}
-	if ((vars->ieee_fc &
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
-		cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
-	}
-	DP(NETIF_MSG_LINK,
-		 "Ext phy AN advertize cl37 0x%x\n", cl37_val);
-
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, cl37_val);
-	msleep(500);
-}
-
-static int bnx2x_8073_config_init(struct bnx2x_phy *phy,
-				  struct link_params *params,
-				  struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val = 0, tmp1;
-	u8 gpio_port;
-	DP(NETIF_MSG_LINK, "Init 8073\n");
-
-	if (CHIP_IS_E2(bp))
-		gpio_port = BP_PATH(bp);
-	else
-		gpio_port = params->port;
-	/* Restore normal power mode*/
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
-
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
-
-	/* enable LASI */
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL, (1<<2));
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL,  0x0004);
-
-	bnx2x_8073_set_pause_cl37(params, phy, vars);
-
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
-
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &tmp1);
-
-	DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1): 0x%x\n", tmp1);
-
-	/* 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 */
-		DP(NETIF_MSG_LINK, "Swapping polarity for the 8073\n");
-		/* 10G Rx/Tx and 1G Tx signal polarity swap */
-		bnx2x_cl45_read(bp, phy,
-				MDIO_PMA_DEVAD,
-				MDIO_PMA_REG_8073_OPT_DIGITAL_CTRL, &val);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD,
-				 MDIO_PMA_REG_8073_OPT_DIGITAL_CTRL,
-				 (val | (3<<9)));
-	}
-
-
-	/* Enable CL37 BAM */
-	if (REG_RD(bp, params->shmem_base +
-			 offsetof(struct shmem_region, dev_info.
-				  port_hw_config[params->port].default_cfg)) &
-	    PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED) {
-
-		bnx2x_cl45_read(bp, phy,
-				MDIO_AN_DEVAD,
-				MDIO_AN_REG_8073_BAM, &val);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD,
-				 MDIO_AN_REG_8073_BAM, val | 1);
-		DP(NETIF_MSG_LINK, "Enable CL37 BAM on KR\n");
-	}
-	if (params->loopback_mode == LOOPBACK_EXT) {
-		bnx2x_807x_force_10G(bp, phy);
-		DP(NETIF_MSG_LINK, "Forced speed 10G on 807X\n");
-		return 0;
-	} else {
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_BCM_CTRL, 0x0002);
-	}
-	if (phy->req_line_speed != SPEED_AUTO_NEG) {
-		if (phy->req_line_speed == SPEED_10000) {
-			val = (1<<7);
-		} else if (phy->req_line_speed ==  SPEED_2500) {
-			val = (1<<5);
-			/*
-			 * Note that 2.5G works only when used with 1G
-			 * advertisement
-			 */
-		} else
-			val = (1<<5);
-	} else {
-		val = 0;
-		if (phy->speed_cap_mask &
-			PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
-			val |= (1<<7);
-
-		/* 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))
-			val |= (1<<5);
-		DP(NETIF_MSG_LINK, "807x autoneg val = 0x%x\n", val);
-	}
-
-	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV, val);
-	bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, &tmp1);
-
-	if (((phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) &&
-	     (phy->req_line_speed == SPEED_AUTO_NEG)) ||
-	    (phy->req_line_speed == SPEED_2500)) {
-		u16 phy_ver;
-		/* Allow 2.5G for A1 and above */
-		bnx2x_cl45_read(bp, phy,
-				MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV,
-				&phy_ver);
-		DP(NETIF_MSG_LINK, "Add 2.5G\n");
-		if (phy_ver > 0)
-			tmp1 |= 1;
-		else
-			tmp1 &= 0xfffe;
-	} else {
-		DP(NETIF_MSG_LINK, "Disable 2.5G\n");
-		tmp1 &= 0xfffe;
-	}
-
-	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, tmp1);
-	/* Add support for CL37 (passive mode) II */
-
-	bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &tmp1);
-	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD,
-			 (tmp1 | ((phy->req_duplex == DUPLEX_FULL) ?
-				  0x20 : 0x40)));
-
-	/* 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
-	 * 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,
-				 0xFB0C);
-
-	/* Enable FEC (Forware Error Correction) Request in the AN */
-	bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, &tmp1);
-	tmp1 |= (1<<15);
-	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, tmp1);
-
-	bnx2x_ext_phy_set_pause(params, phy, vars);
-
-	/* Restart autoneg */
-	msleep(500);
-	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
-	DP(NETIF_MSG_LINK, "807x Autoneg Restart: Advertise 1G=%x, 10G=%x\n",
-		   ((val & (1<<5)) > 0), ((val & (1<<7)) > 0));
-	return 0;
-}
-
-static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
-				 struct link_params *params,
-				 struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u8 link_up = 0;
-	u16 val1, val2;
-	u16 link_status = 0;
-	u16 an1000_status = 0;
-
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
-
-	DP(NETIF_MSG_LINK, "8703 LASI status 0x%x\n", val1);
-
-	/* clear the interrupt LASI status register */
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2);
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val1);
-	DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n", val2, val1);
-	/* Clear MSG-OUT */
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1);
-
-	/* Check the LASI */
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &val2);
-
-	DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2);
-
-	/* Check the link status */
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2);
-	DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2);
-
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
-	link_up = ((val1 & 4) == 4);
-	DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1);
-
-	if (link_up &&
-	     ((phy->req_line_speed != SPEED_10000))) {
-		if (bnx2x_8073_xaui_wa(bp, phy) != 0)
-			return 0;
-	}
-	bnx2x_cl45_read(bp, phy,
-			MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status);
-	bnx2x_cl45_read(bp, phy,
-			MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status);
-
-	/* Check the link status on 1.1.2 */
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
-	DP(NETIF_MSG_LINK, "KR PMA status 0x%x->0x%x,"
-		   "an_link_status=0x%x\n", val2, val1, an1000_status);
-
-	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
-		 */
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_PLL_BANDWIDTH,
-				 0x26BC);
-
-		/* Change CDR Bandwidth in EDC register */
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_CDR_BANDWIDTH,
-				 0x0333);
-	}
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
-			&link_status);
-
-	/* 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<<1)) && (!(link_status & (1<<14)))) {
-		link_up = 1;
-		vars->line_speed = SPEED_2500;
-		DP(NETIF_MSG_LINK, "port %x: External link up in 2.5G\n",
-			   params->port);
-	} else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) {
-		link_up = 1;
-		vars->line_speed = SPEED_1000;
-		DP(NETIF_MSG_LINK, "port %x: External link up in 1G\n",
-			   params->port);
-	} else {
-		link_up = 0;
-		DP(NETIF_MSG_LINK, "port %x: External link is down\n",
-			   params->port);
-	}
-
-	if (link_up) {
-		/* Swap polarity if required */
-		if (params->lane_config &
-		    PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED) {
-			/* Configure the 8073 to swap P and N of the KR lines */
-			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.
-			 */
-			if (vars->line_speed == SPEED_1000) {
-				DP(NETIF_MSG_LINK, "Swapping 1G polarity for"
-					      "the 8073\n");
-				val1 |= (1<<3);
-			} else
-				val1 &= ~(1<<3);
-
-			bnx2x_cl45_write(bp, phy,
-					 MDIO_XS_DEVAD,
-					 MDIO_XS_REG_8073_RX_CTRL_PCIE,
-					 val1);
-		}
-		bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
-		bnx2x_8073_resolve_fc(phy, params, vars);
-		vars->duplex = DUPLEX_FULL;
-	}
-	return link_up;
-}
-
-static void bnx2x_8073_link_reset(struct bnx2x_phy *phy,
-				  struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u8 gpio_port;
-	if (CHIP_IS_E2(bp))
-		gpio_port = BP_PATH(bp);
-	else
-		gpio_port = params->port;
-	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);
-}
-
-/******************************************************************/
-/*			BCM8705 PHY SECTION			  */
-/******************************************************************/
-static int bnx2x_8705_config_init(struct bnx2x_phy *phy,
-				  struct link_params *params,
-				  struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	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);
-	/* 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, params);
-
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL, 0x8288);
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, 0x7fbf);
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_CMU_PLL_BYPASS, 0x0100);
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_CNTL, 0x1);
-	/* BCM8705 doesn't have microcode, hence the 0 */
-	bnx2x_save_spirom_version(bp, params->port, params->shmem_base, 0);
-	return 0;
-}
-
-static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy,
-				 struct link_params *params,
-				 struct link_vars *vars)
-{
-	u8 link_up = 0;
-	u16 val1, rx_sd;
-	struct bnx2x *bp = params->bp;
-	DP(NETIF_MSG_LINK, "read status 8705\n");
-	bnx2x_cl45_read(bp, phy,
-		      MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1);
-	DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
-
-	bnx2x_cl45_read(bp, phy,
-		      MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1);
-	DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
-
-	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd);
-
-	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD, 0xc809, &val1);
-	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD, 0xc809, &val1);
-
-	DP(NETIF_MSG_LINK, "8705 1.c809 val=0x%x\n", val1);
-	link_up = ((rx_sd & 0x1) && (val1 & (1<<9)) && ((val1 & (1<<8)) == 0));
-	if (link_up) {
-		vars->line_speed = SPEED_10000;
-		bnx2x_ext_phy_resolve_fc(phy, params, vars);
-	}
-	return link_up;
-}
-
-/******************************************************************/
-/*			SFP+ module Section			  */
-/******************************************************************/
-static void bnx2x_set_disable_pmd_transmit(struct link_params *params,
-					   struct bnx2x_phy *phy,
-					   u8 pmd_dis)
-{
-	struct bnx2x *bp = params->bp;
-	/*
-	 * Disable transmitter only for bootcodes which can enable it afterwards
-	 * (for D3 link)
-	 */
-	if (pmd_dis) {
-		if (params->feature_config_flags &
-		     FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED)
-			DP(NETIF_MSG_LINK, "Disabling PMD transmitter\n");
-		else {
-			DP(NETIF_MSG_LINK, "NOT disabling PMD transmitter\n");
-			return;
-		}
-	} else
-		DP(NETIF_MSG_LINK, "Enabling PMD transmitter\n");
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_TX_DISABLE, pmd_dis);
-}
-
-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_e1e2_set_transmitter(struct link_params *params,
-					   struct bnx2x_phy *phy,
-					   u8 tx_en)
-{
-	u16 val;
-	u8 port = params->port;
-	struct bnx2x *bp = params->bp;
-	u32 tx_en_mode;
-
-	/* Disable/Enable transmitter ( TX laser of the SFP+ module.)*/
-	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:
-
-		bnx2x_cl45_read(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 void bnx2x_sfp_set_transmitter(struct link_params *params,
-				      struct bnx2x_phy *phy,
-				      u8 tx_en)
-{
-	struct bnx2x *bp = params->bp;
-	DP(NETIF_MSG_LINK, "Setting SFP+ transmitter to %d\n", tx_en);
-	if (CHIP_IS_E3(bp))
-		bnx2x_sfp_e3_set_transmitter(params, phy, tx_en);
-	else
-		bnx2x_sfp_e1e2_set_transmitter(params, phy, tx_en);
-}
-
-static int bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
-					     struct link_params *params,
-					     u16 addr, u8 byte_cnt, u8 *o_buf)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val = 0;
-	u16 i;
-	if (byte_cnt > 16) {
-		DP(NETIF_MSG_LINK, "Reading from eeprom is"
-			    " is limited to 0xf\n");
-		return -EINVAL;
-	}
-	/* 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));
-
-	/* Set the read command address */
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
-			 addr);
-
-	/* Activate read command */
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
-			 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);
-		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
-		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
-			break;
-		udelay(5);
-	}
-
-	if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
-		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) {
-		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;
-	}
-
-	/* 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);
-		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);
-		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
-		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
-			return 0;
-		msleep(1);
-	}
-	return -EINVAL;
-}
-
-static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
-						 struct link_params *params,
-						 u16 addr, u8 byte_cnt,
-						 u8 *o_buf)
-{
-	int rc = 0;
-	u8 i, j = 0, cnt = 0;
-	u32 data_array[4];
-	u16 addr32;
-	struct bnx2x *bp = params->bp;
-	/*DP(NETIF_MSG_LINK, "bnx2x_direct_read_sfp_module_eeprom:"
-					" addr %d, cnt %d\n",
-					addr, byte_cnt);*/
-	if (byte_cnt > 16) {
-		DP(NETIF_MSG_LINK, "Reading from eeprom is"
-			    " is limited to 16 bytes\n");
-		return -EINVAL;
-	}
-
-	/* 4 byte aligned address */
-	addr32 = addr & (~0x3);
-	do {
-		rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt,
-				    data_array);
-	} while ((rc != 0) && (++cnt < I2C_WA_RETRY_CNT));
-
-	if (rc == 0) {
-		for (i = (addr - addr32); i < byte_cnt + (addr - addr32); i++) {
-			o_buf[j] = *((u8 *)data_array + i);
-			j++;
-		}
-	}
-
-	return rc;
-}
-
-static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
-					     struct link_params *params,
-					     u16 addr, u8 byte_cnt, u8 *o_buf)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val, i;
-
-	if (byte_cnt > 16) {
-		DP(NETIF_MSG_LINK, "Reading from eeprom is"
-			    " is limited to 0xf\n");
-		return -EINVAL;
-	}
-
-	/* 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);
-
-	/* 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));
-
-	/* Set the read command address */
-	bnx2x_cl45_write(bp, phy,
-			 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);
-
-	/* 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
-	 */
-	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);
-		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
-		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
-			break;
-		udelay(5);
-	}
-
-	if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
-		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) {
-		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 -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);
-		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);
-		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
-		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
-			return 0;
-		msleep(1);
-	}
-
-	return -EINVAL;
-}
-
-int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
-				 struct link_params *params, u16 addr,
-				 u8 byte_cnt, u8 *o_buf)
-{
-	int rc = -EINVAL;
-	switch (phy->type) {
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-		rc = bnx2x_8726_read_sfp_module_eeprom(phy, params, addr,
-						       byte_cnt, o_buf);
-	break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
-		rc = bnx2x_8727_read_sfp_module_eeprom(phy, params, addr,
-						       byte_cnt, o_buf);
-	break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-		rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr,
-							   byte_cnt, o_buf);
-	break;
-	}
-	return rc;
-}
-
-static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
-			      struct link_params *params,
-			      u16 *edc_mode)
-{
-	struct bnx2x *bp = params->bp;
-	u32 sync_offset = 0, phy_idx, media_types;
-	u8 val, check_limiting_mode = 0;
-	*edc_mode = EDC_MODE_LIMITING;
-
-	phy->media_type = ETH_PHY_UNSPECIFIED;
-	/* First check for copper cable */
-	if (bnx2x_read_sfp_module_eeprom(phy,
-					 params,
-					 SFP_EEPROM_CON_TYPE_ADDR,
-					 1,
-					 &val) != 0) {
-		DP(NETIF_MSG_LINK, "Failed to read from SFP+ module EEPROM\n");
-		return -EINVAL;
-	}
-
-	switch (val) {
-	case SFP_EEPROM_CON_TYPE_VAL_COPPER:
-	{
-		u8 copper_module_type;
-		phy->media_type = ETH_PHY_DA_TWINAX;
-		/*
-		 * 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,
-					       1,
-					       &copper_module_type) != 0) {
-			DP(NETIF_MSG_LINK,
-				"Failed to read copper-cable-type"
-				" from SFP+ EEPROM\n");
-			return -EINVAL;
-		}
-
-		if (copper_module_type &
-		    SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) {
-			DP(NETIF_MSG_LINK, "Active Copper cable detected\n");
-			check_limiting_mode = 1;
-		} else if (copper_module_type &
-			SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
-				DP(NETIF_MSG_LINK, "Passive Copper"
-					    " cable detected\n");
-				*edc_mode =
-				      EDC_MODE_PASSIVE_DAC;
-		} else {
-			DP(NETIF_MSG_LINK, "Unknown copper-cable-"
-				     "type 0x%x !!!\n", copper_module_type);
-			return -EINVAL;
-		}
-		break;
-	}
-	case SFP_EEPROM_CON_TYPE_VAL_LC:
-		phy->media_type = ETH_PHY_SFP_FIBER;
-		DP(NETIF_MSG_LINK, "Optic module detected\n");
-		check_limiting_mode = 1;
-		break;
-	default:
-		DP(NETIF_MSG_LINK, "Unable to determine module type 0x%x !!!\n",
-			 val);
-		return -EINVAL;
-	}
-	sync_offset = params->shmem_base +
-		offsetof(struct shmem_region,
-			 dev_info.port_hw_config[params->port].media_type);
-	media_types = REG_RD(bp, sync_offset);
-	/* Update media type for non-PMF sync */
-	for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
-		if (&(params->phy[phy_idx]) == phy) {
-			media_types &= ~(PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK <<
-				(PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * phy_idx));
-			media_types |= ((phy->media_type &
-					PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) <<
-				(PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * phy_idx));
-			break;
-		}
-	}
-	REG_WR(bp, sync_offset, media_types);
-	if (check_limiting_mode) {
-		u8 options[SFP_EEPROM_OPTIONS_SIZE];
-		if (bnx2x_read_sfp_module_eeprom(phy,
-						 params,
-						 SFP_EEPROM_OPTIONS_ADDR,
-						 SFP_EEPROM_OPTIONS_SIZE,
-						 options) != 0) {
-			DP(NETIF_MSG_LINK, "Failed to read Option"
-				" field from module EEPROM\n");
-			return -EINVAL;
-		}
-		if ((options[0] & SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK))
-			*edc_mode = EDC_MODE_LINEAR;
-		else
-			*edc_mode = EDC_MODE_LIMITING;
-	}
-	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
- */
-static int bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
-				   struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u32 val, cmd;
-	u32 fw_resp, fw_cmd_param;
-	char vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE+1];
-	char vendor_pn[SFP_EEPROM_PART_NO_SIZE+1];
-	phy->flags &= ~FLAGS_SFP_NOT_APPROVED;
-	val = REG_RD(bp, params->shmem_base +
-			 offsetof(struct shmem_region, dev_info.
-				  port_feature_config[params->port].config));
-	if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
-	    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT) {
-		DP(NETIF_MSG_LINK, "NOT enforcing module verification\n");
-		return 0;
-	}
-
-	if (params->feature_config_flags &
-	    FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY) {
-		/* Use specific phy request */
-		cmd = DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL;
-	} else if (params->feature_config_flags &
-		   FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY) {
-		/* Use first phy request only in case of non-dual media*/
-		if (DUAL_MEDIA(params)) {
-			DP(NETIF_MSG_LINK, "FW does not support OPT MDL "
-			   "verification\n");
-			return -EINVAL;
-		}
-		cmd = DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL;
-	} else {
-		/* No support in OPT MDL detection */
-		DP(NETIF_MSG_LINK, "FW does not support OPT MDL "
-			  "verification\n");
-		return -EINVAL;
-	}
-
-	fw_cmd_param = FW_PARAM_SET(phy->addr, phy->type, phy->mdio_ctrl);
-	fw_resp = bnx2x_fw_command(bp, cmd, fw_cmd_param);
-	if (fw_resp == FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS) {
-		DP(NETIF_MSG_LINK, "Approved module\n");
-		return 0;
-	}
-
-	/* 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))
-		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))
-		vendor_pn[0] = '\0';
-	else
-		vendor_pn[SFP_EEPROM_PART_NO_SIZE] = '\0';
-
-	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;
-}
-
-static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
-						 struct link_params *params)
-
-{
-	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 )
-	 */
-
-	for (timeout = 0; timeout < 60; timeout++) {
-		if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val)
-		    == 0) {
-			DP(NETIF_MSG_LINK, "SFP+ module initialization "
-				     "took %d ms\n", timeout * 5);
-			return 0;
-		}
-		msleep(5);
-	}
-	return -EINVAL;
-}
-
-static void bnx2x_8727_power_module(struct bnx2x *bp,
-				    struct bnx2x_phy *phy,
-				    u8 is_power_up) {
-	/* Make sure GPIOs are not using for LED mode */
-	u16 val;
-	/*
-	 * 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
-	 */
-	if (phy->flags & FLAGS_NOC)
-		return;
-	if (is_power_up)
-		val = (1<<4);
-	else
-		/*
-		 * Set GPIO control to OUTPUT, and set the power bit
-		 * to according to the is_power_up
-		 */
-		val = (1<<1);
-
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8727_GPIO_CTRL,
-			 val);
-}
-
-static int bnx2x_8726_set_limiting_mode(struct bnx2x *bp,
-					struct bnx2x_phy *phy,
-					u16 edc_mode)
-{
-	u16 cur_limiting_mode;
-
-	bnx2x_cl45_read(bp, phy,
-			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");
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD,
-				 MDIO_PMA_REG_ROM_VER2,
-				 EDC_MODE_LIMITING);
-	} else { /* LRM mode ( default )*/
-
-		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)
-		 */
-		if (cur_limiting_mode != EDC_MODE_LIMITING)
-			return 0;
-
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD,
-				 MDIO_PMA_REG_LRM_MODE,
-				 0);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD,
-				 MDIO_PMA_REG_ROM_VER2,
-				 0x128);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD,
-				 MDIO_PMA_REG_MISC_CTRL0,
-				 0x4008);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD,
-				 MDIO_PMA_REG_LRM_MODE,
-				 0xaaaa);
-	}
-	return 0;
-}
-
-static int bnx2x_8727_set_limiting_mode(struct bnx2x *bp,
-					struct bnx2x_phy *phy,
-					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);
-
-	bnx2x_cl45_write(bp, phy,
-			 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);
-	/* 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));
-
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_PHY_IDENTIFIER,
-			 (phy_identifier | (1<<9)));
-
-	return 0;
-}
-
-static void bnx2x_8727_specific_func(struct bnx2x_phy *phy,
-				     struct link_params *params,
-				     u32 action)
-{
-	struct bnx2x *bp = params->bp;
-
-	switch (action) {
-	case DISABLE_TX:
-		bnx2x_sfp_set_transmitter(params, phy, 0);
-		break;
-	case ENABLE_TX:
-		if (!(phy->flags & FLAGS_SFP_NOT_APPROVED))
-			bnx2x_sfp_set_transmitter(params, phy, 1);
-		break;
-	default:
-		DP(NETIF_MSG_LINK, "Function 0x%x not supported by 8727\n",
-		   action);
-		return;
-	}
-}
-
-static void bnx2x_set_e1e2_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 void bnx2x_set_e3_module_fault_led(struct link_params *params,
-					  u8 gpio_mode)
-{
-	u32 pin_cfg;
-	u8 port = params->port;
-	struct bnx2x *bp = params->bp;
-	pin_cfg = (REG_RD(bp, params->shmem_base +
-			 offsetof(struct shmem_region,
-				  dev_info.port_hw_config[port].e3_sfp_ctrl)) &
-		PORT_HW_CFG_E3_FAULT_MDL_LED_MASK) >>
-		PORT_HW_CFG_E3_FAULT_MDL_LED_SHIFT;
-	DP(NETIF_MSG_LINK, "Setting Fault LED to %d using pin cfg %d\n",
-		       gpio_mode, pin_cfg);
-	bnx2x_set_cfg_pin(bp, pin_cfg, gpio_mode);
-}
-
-static void bnx2x_set_sfp_module_fault_led(struct link_params *params,
-					   u8 gpio_mode)
-{
-	struct bnx2x *bp = params->bp;
-	DP(NETIF_MSG_LINK, "Setting SFP+ module fault LED to %d\n", gpio_mode);
-	if (CHIP_IS_E3(bp)) {
-		/*
-		 * Low ==> if SFP+ module is supported otherwise
-		 * High ==> if SFP+ module is not on the approved vendor list
-		 */
-		bnx2x_set_e3_module_fault_led(params, gpio_mode);
-	} else
-		bnx2x_set_e1e2_module_fault_led(params, gpio_mode);
-}
-
-static void bnx2x_warpcore_power_module(struct link_params *params,
-					struct bnx2x_phy *phy,
-					u8 power)
-{
-	u32 pin_cfg;
-	struct bnx2x *bp = params->bp;
-
-	pin_cfg = (REG_RD(bp, params->shmem_base +
-			  offsetof(struct shmem_region,
-			dev_info.port_hw_config[params->port].e3_sfp_ctrl)) &
-			PORT_HW_CFG_E3_PWR_DIS_MASK) >>
-			PORT_HW_CFG_E3_PWR_DIS_SHIFT;
-
-	if (pin_cfg == PIN_CFG_NA)
-		return;
-	DP(NETIF_MSG_LINK, "Setting SFP+ module power to %d using pin cfg %d\n",
-		       power, pin_cfg);
-	/*
-	 * Low ==> corresponding SFP+ module is powered
-	 * high ==> the SFP+ module is powered down
-	 */
-	bnx2x_set_cfg_pin(bp, pin_cfg, power ^ 1);
-}
-
-static void bnx2x_warpcore_hw_reset(struct bnx2x_phy *phy,
-				    struct link_params *params)
-{
-	bnx2x_warpcore_power_module(params, phy, 0);
-}
-
-static void bnx2x_power_sfp_module(struct link_params *params,
-				   struct bnx2x_phy *phy,
-				   u8 power)
-{
-	struct bnx2x *bp = params->bp;
-	DP(NETIF_MSG_LINK, "Setting SFP+ power to %x\n", power);
-
-	switch (phy->type) {
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
-		bnx2x_8727_power_module(params->bp, phy, power);
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-		bnx2x_warpcore_power_module(params, phy, power);
-		break;
-	default:
-		break;
-	}
-}
-static void bnx2x_warpcore_set_limiting_mode(struct link_params *params,
-					     struct bnx2x_phy *phy,
-					     u16 edc_mode)
-{
-	u16 val = 0;
-	u16 mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT;
-	struct bnx2x *bp = params->bp;
-
-	u8 lane = bnx2x_get_warpcore_lane(phy, params);
-	/* This is a global register which controls all lanes */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val);
-	val &= ~(0xf << (lane << 2));
-
-	switch (edc_mode) {
-	case EDC_MODE_LINEAR:
-	case EDC_MODE_LIMITING:
-		mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT;
-		break;
-	case EDC_MODE_PASSIVE_DAC:
-		mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_DAC;
-		break;
-	default:
-		break;
-	}
-
-	val |= (mode << (lane << 2));
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, val);
-	/* A must read */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val);
-
-	/* Restart microcode to re-read the new mode */
-	bnx2x_warpcore_reset_lane(bp, phy, 1);
-	bnx2x_warpcore_reset_lane(bp, phy, 0);
-
-}
-
-static void bnx2x_set_limiting_mode(struct link_params *params,
-				    struct bnx2x_phy *phy,
-				    u16 edc_mode)
-{
-	switch (phy->type) {
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-		bnx2x_8726_set_limiting_mode(params->bp, phy, edc_mode);
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
-		bnx2x_8727_set_limiting_mode(params->bp, phy, edc_mode);
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-		bnx2x_warpcore_set_limiting_mode(params, phy, edc_mode);
-		break;
-	}
-}
-
-int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
-			       struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u16 edc_mode;
-	int rc = 0;
-
-	u32 val = REG_RD(bp, params->shmem_base +
-			     offsetof(struct shmem_region, dev_info.
-				     port_feature_config[params->port].config));
-
-	DP(NETIF_MSG_LINK, "SFP+ module plugged in/out detected on port %d\n",
-		 params->port);
-	/* Power up module */
-	bnx2x_power_sfp_module(params, phy, 1);
-	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) {
-		/* check SFP+ module compatibility */
-		DP(NETIF_MSG_LINK, "Module verification failed!!\n");
-		rc = -EINVAL;
-		/* Turn on fault module-detected led */
-		bnx2x_set_sfp_module_fault_led(params,
-					       MISC_REGISTERS_GPIO_HIGH);
-
-		/* Check if need to power down the SFP+ module */
-		if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
-		     PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN) {
-			DP(NETIF_MSG_LINK, "Shutdown SFP+ module!!\n");
-			bnx2x_power_sfp_module(params, phy, 0);
-			return rc;
-		}
-	} else {
-		/* Turn off fault module-detected led */
-		bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_LOW);
-	}
-
-	/*
-	 * Check and set limiting mode / LRM mode on 8726. On 8727 it
-	 * is done automatically
-	 */
-	bnx2x_set_limiting_mode(params, phy, edc_mode);
-
-	/*
-	 * Enable transmit for this module if the module is approved, or
-	 * if unapproved modules should also enable the Tx laser
-	 */
-	if (rc == 0 ||
-	    (val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
-	    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-		bnx2x_sfp_set_transmitter(params, phy, 1);
-	else
-		bnx2x_sfp_set_transmitter(params, phy, 0);
-
-	return rc;
-}
-
-void bnx2x_handle_module_detect_int(struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	struct bnx2x_phy *phy;
-	u32 gpio_val;
-	u8 gpio_num, gpio_port;
-	if (CHIP_IS_E3(bp))
-		phy = &params->phy[INT_PHY];
-	else
-		phy = &params->phy[EXT_PHY1];
-
-	if (bnx2x_get_mod_abs_int_cfg(bp, params->chip_id, params->shmem_base,
-				      params->port, &gpio_num, &gpio_port) ==
-	    -EINVAL) {
-		DP(NETIF_MSG_LINK, "Failed to get MOD_ABS interrupt config\n");
-		return;
-	}
-
-	/* Set valid module led off */
-	bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_HIGH);
-
-	/* Get current gpio val reflecting module plugged in / out*/
-	gpio_val = bnx2x_get_gpio(bp, gpio_num, gpio_port);
-
-	/* Call the handling function in case module is detected */
-	if (gpio_val == 0) {
-		bnx2x_power_sfp_module(params, phy, 1);
-		bnx2x_set_gpio_int(bp, gpio_num,
-				   MISC_REGISTERS_GPIO_INT_OUTPUT_CLR,
-				   gpio_port);
-		if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
-			bnx2x_sfp_module_detection(phy, params);
-		else
-			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));
-		bnx2x_set_gpio_int(bp, gpio_num,
-				   MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
-				   gpio_port);
-		/*
-		 * Module was plugged out.
-		 * Disable transmit for this module
-		 */
-		phy->media_type = ETH_PHY_NOT_PRESENT;
-		if (((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
-		     PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) ||
-		    CHIP_IS_E3(bp))
-			bnx2x_sfp_set_transmitter(params, phy, 0);
-	}
-}
-
-/******************************************************************/
-/*		Used by 8706 and 8727                             */
-/******************************************************************/
-static void bnx2x_sfp_mask_fault(struct bnx2x *bp,
-				 struct bnx2x_phy *phy,
-				 u16 alarm_status_offset,
-				 u16 alarm_ctrl_offset)
-{
-	u16 alarm_status, val;
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, alarm_status_offset,
-			&alarm_status);
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, alarm_status_offset,
-			&alarm_status);
-	/* Mask or enable the fault event. */
-	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, alarm_ctrl_offset, &val);
-	if (alarm_status & (1<<0))
-		val &= ~(1<<0);
-	else
-		val |= (1<<0);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, alarm_ctrl_offset, val);
-}
-/******************************************************************/
-/*		common BCM8706/BCM8726 PHY SECTION		  */
-/******************************************************************/
-static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
-				      struct link_params *params,
-				      struct link_vars *vars)
-{
-	u8 link_up = 0;
-	u16 val1, val2, rx_sd, pcs_status;
-	struct bnx2x *bp = params->bp;
-	DP(NETIF_MSG_LINK, "XGXS 8706/8726\n");
-	/* Clear RX Alarm*/
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &val2);
-
-	bnx2x_sfp_mask_fault(bp, phy, MDIO_PMA_LASI_TXSTAT,
-			     MDIO_PMA_LASI_TXCTRL);
-
-	/* clear LASI indication*/
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val2);
-	DP(NETIF_MSG_LINK, "8706/8726 LASI status 0x%x--> 0x%x\n", val1, val2);
-
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd);
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &pcs_status);
-	bnx2x_cl45_read(bp, phy,
-			MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2);
-	bnx2x_cl45_read(bp, phy,
-			MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2);
-
-	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_up = ((rx_sd & pcs_status & 0x1) || (val2 & (1<<1)));
-	if (link_up) {
-		if (val2 & (1<<1))
-			vars->line_speed = SPEED_1000;
-		else
-			vars->line_speed = SPEED_10000;
-		bnx2x_ext_phy_resolve_fc(phy, params, vars);
-		vars->duplex = DUPLEX_FULL;
-	}
-
-	/* Capture 10G link fault. Read twice to clear stale value. */
-	if (vars->line_speed == SPEED_10000) {
-		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
-			    MDIO_PMA_LASI_TXSTAT, &val1);
-		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
-			    MDIO_PMA_LASI_TXSTAT, &val1);
-		if (val1 & (1<<0))
-			vars->fault_detected = 1;
-	}
-
-	return link_up;
-}
-
-/******************************************************************/
-/*			BCM8706 PHY SECTION			  */
-/******************************************************************/
-static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
-				 struct link_params *params,
-				 struct link_vars *vars)
-{
-	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);
-	/* 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, params);
-
-	/* Wait until fw is loaded */
-	for (cnt = 0; cnt < 100; cnt++) {
-		bnx2x_cl45_read(bp, phy,
-				MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER1, &val);
-		if (val)
-			break;
-		msleep(10);
-	}
-	DP(NETIF_MSG_LINK, "XGXS 8706 is initialized after %d ms\n", cnt);
-	if ((params->feature_config_flags &
-	     FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
-		u8 i;
-		u16 reg;
-		for (i = 0; i < 4; i++) {
-			reg = MDIO_XS_8706_REG_BANK_RX0 +
-				i*(MDIO_XS_8706_REG_BANK_RX1 -
-				   MDIO_XS_8706_REG_BANK_RX0);
-			bnx2x_cl45_read(bp, phy, MDIO_XS_DEVAD, reg, &val);
-			/* Clear first 3 bits of the control */
-			val &= ~0x7;
-			/* Set control bits according to configuration */
-			val |= (phy->rx_preemphasis[i] & 0x7);
-			DP(NETIF_MSG_LINK, "Setting RX Equalizer to BCM8706"
-				   " reg 0x%x <-- val 0x%x\n", reg, val);
-			bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, reg, val);
-		}
-	}
-	/* Force speed */
-	if (phy->req_line_speed == SPEED_10000) {
-		DP(NETIF_MSG_LINK, "XGXS 8706 force 10Gbps\n");
-
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD,
-				 MDIO_PMA_REG_DIGITAL_CTRL, 0x400);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXCTRL,
-				 0);
-		/* Arm LASI for link and Tx fault. */
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 3);
-	} else {
-		/* 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 advertisement on CL37 */
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LP, 0x0020);
-		/* Enable CL37 AN */
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
-		/* 1G support */
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD, MDIO_AN_REG_ADV, (1<<5));
-
-		/* Enable clause 73 AN */
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
-				 0x0400);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL,
-				 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;
-}
-
-static int bnx2x_8706_read_status(struct bnx2x_phy *phy,
-				  struct link_params *params,
-				  struct link_vars *vars)
-{
-	return bnx2x_8706_8726_read_status(phy, params, vars);
-}
-
-/******************************************************************/
-/*			BCM8726 PHY SECTION			  */
-/******************************************************************/
-static void bnx2x_8726_config_loopback(struct bnx2x_phy *phy,
-				       struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	DP(NETIF_MSG_LINK, "PMA/PMD ext_phy_loopback: 8726\n");
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0001);
-}
-
-static void bnx2x_8726_external_rom_boot(struct bnx2x_phy *phy,
-					 struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	/* Need to wait 100ms after reset */
-	msleep(100);
-
-	/* Micro controller re-boot */
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x018B);
-
-	/* Set soft reset */
-	bnx2x_cl45_write(bp, phy,
-			 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);
-
-	bnx2x_cl45_write(bp, phy,
-			 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);
-
-	msleep(200);
-	bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
-}
-
-static u8 bnx2x_8726_read_status(struct bnx2x_phy *phy,
-				 struct link_params *params,
-				 struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val1;
-	u8 link_up = bnx2x_8706_8726_read_status(phy, params, vars);
-	if (link_up) {
-		bnx2x_cl45_read(bp, phy,
-				MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
-				&val1);
-		if (val1 & (1<<15)) {
-			DP(NETIF_MSG_LINK, "Tx is disabled\n");
-			link_up = 0;
-			vars->line_speed = 0;
-		}
-	}
-	return link_up;
-}
-
-
-static int bnx2x_8726_config_init(struct bnx2x_phy *phy,
-				  struct link_params *params,
-				  struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
-
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
-	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
-	 */
-	bnx2x_sfp_module_detection(phy, params);
-
-	if (phy->req_line_speed == SPEED_1000) {
-		DP(NETIF_MSG_LINK, "Setting 1G force\n");
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x40);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x5);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
-				 0x400);
-	} else if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
-		   (phy->speed_cap_mask &
-		      PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) &&
-		   ((phy->speed_cap_mask &
-		      PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) !=
-		    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
-		DP(NETIF_MSG_LINK, "Setting 1G clause37\n");
-		/* Set Flow control */
-		bnx2x_ext_phy_set_pause(params, phy, vars);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD, MDIO_AN_REG_ADV, 0x20);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_CL73, 0x040c);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, 0x0020);
-		bnx2x_cl45_write(bp, phy,
-				 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
-		 */
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x4);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
-				 0x400);
-
-	} else { /* Default 10G. Set only LASI control */
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 1);
-	}
-
-	/* Set TX PreEmphasis if needed */
-	if ((params->feature_config_flags &
-	     FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
-		DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x,"
-			 "TX_CTRL2 0x%x\n",
-			 phy->tx_preemphasis[0],
-			 phy->tx_preemphasis[1]);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD,
-				 MDIO_PMA_REG_8726_TX_CTRL1,
-				 phy->tx_preemphasis[0]);
-
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD,
-				 MDIO_PMA_REG_8726_TX_CTRL2,
-				 phy->tx_preemphasis[1]);
-	}
-
-	return 0;
-
-}
-
-static void bnx2x_8726_link_reset(struct bnx2x_phy *phy,
-				  struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	DP(NETIF_MSG_LINK, "bnx2x_8726_link_reset port %d\n", params->port);
-	/* Set serial boot control for external load */
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_GEN_CTRL, 0x0001);
-}
-
-/******************************************************************/
-/*			BCM8727 PHY SECTION			  */
-/******************************************************************/
-
-static void bnx2x_8727_set_link_led(struct bnx2x_phy *phy,
-				    struct link_params *params, u8 mode)
-{
-	struct bnx2x *bp = params->bp;
-	u16 led_mode_bitmask = 0;
-	u16 gpio_pins_bitmask = 0;
-	u16 val;
-	/* Only NOC flavor requires to set the LED specifically */
-	if (!(phy->flags & FLAGS_NOC))
-		return;
-	switch (mode) {
-	case LED_MODE_FRONT_PANEL_OFF:
-	case LED_MODE_OFF:
-		led_mode_bitmask = 0;
-		gpio_pins_bitmask = 0x03;
-		break;
-	case LED_MODE_ON:
-		led_mode_bitmask = 0;
-		gpio_pins_bitmask = 0x02;
-		break;
-	case LED_MODE_OPER:
-		led_mode_bitmask = 0x60;
-		gpio_pins_bitmask = 0x11;
-		break;
-	}
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_8727_PCS_OPT_CTRL,
-			&val);
-	val &= 0xff8f;
-	val |= led_mode_bitmask;
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8727_PCS_OPT_CTRL,
-			 val);
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_8727_GPIO_CTRL,
-			&val);
-	val &= 0xffe0;
-	val |= gpio_pins_bitmask;
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8727_GPIO_CTRL,
-			 val);
-}
-static void bnx2x_8727_hw_reset(struct bnx2x_phy *phy,
-				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()
-	 */
-	struct bnx2x *bp = params->bp;
-	swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
-	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);
-}
-
-static int bnx2x_8727_config_init(struct bnx2x_phy *phy,
-				  struct link_params *params,
-				  struct link_vars *vars)
-{
-	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, params);
-	rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
-	/* Should be 0x6 to enable XS on Tx side. */
-	lasi_ctrl_val = 0x0006;
-
-	DP(NETIF_MSG_LINK, "Initializing BCM8727\n");
-	/* enable LASI */
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
-			 rx_alarm_ctrl_val);
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXCTRL,
-			 0);
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, lasi_ctrl_val);
-
-	/*
-	 * 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'
-	 */
-	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);
-
-
-	/* Enable/Disable PHY transmitter output */
-	bnx2x_set_disable_pmd_transmit(params, phy, 0);
-
-	/* Make MOD_ABS give interrupt on change */
-	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL,
-			&val);
-	val |= (1<<12);
-	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
-	 */
-	if (!(phy->flags & FLAGS_NOC))
-		val &= 0xff8f; /* Reset bits 4-6 */
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL, val);
-
-	bnx2x_8727_power_module(bp, phy, 1);
-
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
-
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &tmp1);
-
-	/* Set option 1G speed */
-	if (phy->req_line_speed == SPEED_1000) {
-		DP(NETIF_MSG_LINK, "Setting 1G force\n");
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x40);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD);
-		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
-		 */
-		if (DUAL_MEDIA(params)) {
-			bnx2x_cl45_read(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8727_PCS_GP, &val);
-			val |= (3<<10);
-			bnx2x_cl45_write(bp, phy,
-					 MDIO_PMA_DEVAD,
-					 MDIO_PMA_REG_8727_PCS_GP, val);
-		}
-	} else if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
-		   ((phy->speed_cap_mask &
-		     PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) &&
-		   ((phy->speed_cap_mask &
-		      PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) !=
-		   PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
-
-		DP(NETIF_MSG_LINK, "Setting 1G clause37\n");
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL, 0);
-		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
-		 */
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL,
-				 0x0020);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x0100);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x2040);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2,
-				 0x0008);
-	}
-
-	/*
-	 * Set 2-wire transfer rate of SFP+ module EEPROM
-	 * to 100Khz since some DACs(direct attached cables) do
-	 * not work at 400Khz.
-	 */
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR,
-			 0xa001);
-
-	/* Set TX PreEmphasis if needed */
-	if ((params->feature_config_flags &
-	     FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
-		DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x, TX_CTRL2 0x%x\n",
-			   phy->tx_preemphasis[0],
-			   phy->tx_preemphasis[1]);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TX_CTRL1,
-				 phy->tx_preemphasis[0]);
-
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TX_CTRL2,
-				 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;
-}
-
-static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
-				      struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u16 mod_abs, rx_alarm_status;
-	u32 val = REG_RD(bp, params->shmem_base +
-			     offsetof(struct shmem_region, dev_info.
-				      port_feature_config[params->port].
-				      config));
-	bnx2x_cl45_read(bp, phy,
-			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");
-		phy->media_type = ETH_PHY_NOT_PRESENT;
-		/*
-		 * 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);
-
-		/*
-		 * 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_LASI_RXSTAT, &rx_alarm_status);
-
-	} else {
-		/* Module is present */
-		DP(NETIF_MSG_LINK, "MOD_ABS indication "
-			    "show module is present\n");
-		/*
-		 * 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);
-		bnx2x_cl45_write(bp, phy,
-				 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
-		 */
-		bnx2x_cl45_read(bp, phy,
-				MDIO_PMA_DEVAD,
-				MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
-
-
-		if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
-		    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-			bnx2x_sfp_set_transmitter(params, phy, 0);
-
-		if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
-			bnx2x_sfp_module_detection(phy, params);
-		else
-			DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
-	}
-
-	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 */
-}
-
-static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
-				 struct link_params *params,
-				 struct link_vars *vars)
-
-{
-	struct bnx2x *bp = params->bp;
-	u8 link_up = 0, oc_port = params->port;
-	u16 link_status = 0;
-	u16 rx_alarm_status, lasi_ctrl, val1;
-
-	/* If PHY is not initialized, do not check link status */
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL,
-			&lasi_ctrl);
-	if (!lasi_ctrl)
-		return 0;
-
-	/* Check the LASI on Rx */
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT,
-			&rx_alarm_status);
-	vars->line_speed = 0;
-	DP(NETIF_MSG_LINK, "8727 RX_ALARM_STATUS  0x%x\n", rx_alarm_status);
-
-	bnx2x_sfp_mask_fault(bp, phy, MDIO_PMA_LASI_TXSTAT,
-			     MDIO_PMA_LASI_TXCTRL);
-
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
-
-	DP(NETIF_MSG_LINK, "8727 LASI status 0x%x\n", val1);
-
-	/* Clear MSG-OUT */
-	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
-	 */
-	if (!(phy->flags & FLAGS_NOC) && !(rx_alarm_status & (1<<5))) {
-		/* Check over-current using 8727 GPIO0 input*/
-		bnx2x_cl45_read(bp, phy,
-				MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_GPIO_CTRL,
-				&val1);
-
-		if ((val1 & (1<<8)) == 0) {
-			if (!CHIP_IS_E1x(bp))
-				oc_port = BP_PATH(bp) + (params->port << 1);
-			DP(NETIF_MSG_LINK, "8727 Power fault has been detected"
-				       " on port %d\n", oc_port);
-			netdev_err(bp->dev, "Error:  Power fault on Port %d has"
-					    " been detected and the power to "
-					    "that SFP+ module has been removed"
-					    " to prevent failure of the card."
-					    " Please remove the SFP+ module and"
-					    " restart the system to clear this"
-					    " error.\n",
-			 oc_port);
-			/* Disable all RX_ALARMs except for mod_abs */
-			bnx2x_cl45_write(bp, phy,
-					 MDIO_PMA_DEVAD,
-					 MDIO_PMA_LASI_RXCTRL, (1<<5));
-
-			bnx2x_cl45_read(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_PHY_IDENTIFIER, &val1);
-			/* Wait for module_absent_event */
-			val1 |= (1<<8);
-			bnx2x_cl45_write(bp, phy,
-					 MDIO_PMA_DEVAD,
-					 MDIO_PMA_REG_PHY_IDENTIFIER, val1);
-			/* Clear RX alarm */
-			bnx2x_cl45_read(bp, phy,
-				MDIO_PMA_DEVAD,
-				MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
-			return 0;
-		}
-	} /* Over current check */
-
-	/* When module absent bit is set, check module */
-	if (rx_alarm_status & (1<<5)) {
-		bnx2x_8727_handle_mod_abs(phy, params);
-		/* Enable all mod_abs and link detection bits */
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
-				 ((1<<5) | (1<<2)));
-	}
-	DP(NETIF_MSG_LINK, "Enabling 8727 TX laser if SFP is approved\n");
-	bnx2x_8727_specific_func(phy, params, ENABLE_TX);
-	/* If transmitter is disabled, ignore false link up indication */
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &val1);
-	if (val1 & (1<<15)) {
-		DP(NETIF_MSG_LINK, "Tx is disabled\n");
-		return 0;
-	}
-
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_8073_SPEED_LINK_STATUS, &link_status);
-
-	/*
-	 * 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;
-		DP(NETIF_MSG_LINK, "port %x: External link up in 1G\n",
-			   params->port);
-	} else {
-		link_up = 0;
-		DP(NETIF_MSG_LINK, "port %x: External link is down\n",
-			   params->port);
-	}
-
-	/* Capture 10G link fault. */
-	if (vars->line_speed == SPEED_10000) {
-		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
-			    MDIO_PMA_LASI_TXSTAT, &val1);
-
-		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
-			    MDIO_PMA_LASI_TXSTAT, &val1);
-
-		if (val1 & (1<<0)) {
-			vars->fault_detected = 1;
-		}
-	}
-
-	if (link_up) {
-		bnx2x_ext_phy_resolve_fc(phy, params, vars);
-		vars->duplex = DUPLEX_FULL;
-		DP(NETIF_MSG_LINK, "duplex = 0x%x\n", vars->duplex);
-	}
-
-	if ((DUAL_MEDIA(params)) &&
-	    (phy->req_line_speed == SPEED_1000)) {
-		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
-		 */
-		if (link_up)
-			val1 &= ~(3<<10);
-		else
-			val1 |= (3<<10);
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD,
-				 MDIO_PMA_REG_8727_PCS_GP, val1);
-	}
-	return link_up;
-}
-
-static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
-				  struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-
-	/* Enable/Disable PHY transmitter output */
-	bnx2x_set_disable_pmd_transmit(params, phy, 1);
-
-	/* Disable Transmitter */
-	bnx2x_sfp_set_transmitter(params, phy, 0);
-	/* Clear LASI */
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0);
-
-}
-
-/******************************************************************/
-/*		BCM8481/BCM84823/BCM84833 PHY SECTION	          */
-/******************************************************************/
-static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
-					   struct link_params *params)
-{
-	u16 val, fw_ver1, fw_ver2, cnt;
-	u8 port;
-	struct bnx2x *bp = params->bp;
-
-	port = params->port;
-
-	/* 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);
-
-	for (cnt = 0; cnt < 100; cnt++) {
-		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
-		if (val & 1)
-			break;
-		udelay(5);
-	}
-	if (cnt == 100) {
-		DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(1)\n");
-		bnx2x_save_spirom_version(bp, port, 0,
-					  phy->ver_addr);
-		return;
-	}
-
-
-	/* 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);
-	for (cnt = 0; cnt < 100; cnt++) {
-		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
-		if (val & 1)
-			break;
-		udelay(5);
-	}
-	if (cnt == 100) {
-		DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(2)\n");
-		bnx2x_save_spirom_version(bp, port, 0,
-					  phy->ver_addr);
-		return;
-	}
-
-	/* lower 16 bits of the register SPI_FW_STATUS */
-	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1);
-	/* upper 16 bits of register SPI_FW_STATUS */
-	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2);
-
-	bnx2x_save_spirom_version(bp, port, (fw_ver2<<16) | fw_ver1,
-				  phy->ver_addr);
-}
-
-static void bnx2x_848xx_set_led(struct bnx2x *bp,
-				struct bnx2x_phy *phy)
-{
-	u16 val;
-
-	/* PHYC_CTL_LED_CTL */
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_8481_LINK_SIGNAL, &val);
-	val &= 0xFE00;
-	val |= 0x0092;
-
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LINK_SIGNAL, val);
-
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LED1_MASK,
-			 0x80);
-
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LED2_MASK,
-			 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,
-			 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,
-			0);
-
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_84823_CTL_LED_CTL_1, &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);
-
-	/* 'Interrupt Mask' */
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_AN_DEVAD,
-			 0xFFFB, 0xFFFD);
-}
-
-static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
-				       struct link_params *params,
-				       struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u16 autoneg_val, an_1000_val, an_10_100_val;
-	u16 tmp_req_line_speed;
-
-	tmp_req_line_speed = phy->req_line_speed;
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
-		if (phy->req_line_speed == SPEED_10000)
-			phy->req_line_speed = SPEED_AUTO_NEG;
-
-	/*
-	 * 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);
-
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0000);
-
-	bnx2x_848xx_set_led(bp, phy);
-
-	/* set 1000 speed advertisement */
-	bnx2x_cl45_read(bp, phy,
-			MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
-			&an_1000_val);
-
-	bnx2x_ext_phy_set_pause(params, phy, vars);
-	bnx2x_cl45_read(bp, phy,
-			MDIO_AN_DEVAD,
-			MDIO_AN_REG_8481_LEGACY_AN_ADV,
-			&an_10_100_val);
-	bnx2x_cl45_read(bp, phy,
-			MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_MII_CTRL,
-			&autoneg_val);
-	/* Disable forced speed */
-	autoneg_val &= ~((1<<6) | (1<<8) | (1<<9) | (1<<12) | (1<<13));
-	an_10_100_val &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8));
-
-	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-	     (phy->speed_cap_mask &
-	     PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
-	    (phy->req_line_speed == SPEED_1000)) {
-		an_1000_val |= (1<<8);
-		autoneg_val |= (1<<9 | 1<<12);
-		if (phy->req_duplex == DUPLEX_FULL)
-			an_1000_val |= (1<<9);
-		DP(NETIF_MSG_LINK, "Advertising 1G\n");
-	} else
-		an_1000_val &= ~((1<<8) | (1<<9));
-
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
-			 an_1000_val);
-
-	/* set 100 speed advertisement */
-	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-	     (phy->speed_cap_mask &
-	      (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
-	       PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)) &&
-	     (phy->supported &
-	      (SUPPORTED_100baseT_Half |
-	       SUPPORTED_100baseT_Full)))) {
-		an_10_100_val |= (1<<7);
-		/* Enable autoneg and restart autoneg for legacy speeds */
-		autoneg_val |= (1<<9 | 1<<12);
-
-		if (phy->req_duplex == DUPLEX_FULL)
-			an_10_100_val |= (1<<8);
-		DP(NETIF_MSG_LINK, "Advertising 100M\n");
-	}
-	/* set 10 speed advertisement */
-	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-	     (phy->speed_cap_mask &
-	      (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
-	       PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) &&
-	     (phy->supported &
-	      (SUPPORTED_10baseT_Half |
-	       SUPPORTED_10baseT_Full)))) {
-		an_10_100_val |= (1<<5);
-		autoneg_val |= (1<<9 | 1<<12);
-		if (phy->req_duplex == DUPLEX_FULL)
-			an_10_100_val |= (1<<6);
-		DP(NETIF_MSG_LINK, "Advertising 10M\n");
-	}
-
-	/* Only 10/100 are allowed to work in FORCE mode */
-	if ((phy->req_line_speed == SPEED_100) &&
-	    (phy->supported &
-	     (SUPPORTED_100baseT_Half |
-	      SUPPORTED_100baseT_Full))) {
-		autoneg_val |= (1<<13);
-		/* Enabled AUTO-MDIX when autoneg is disabled */
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
-				 (1<<15 | 1<<9 | 7<<0));
-		DP(NETIF_MSG_LINK, "Setting 100M force\n");
-	}
-	if ((phy->req_line_speed == SPEED_10) &&
-	    (phy->supported &
-	     (SUPPORTED_10baseT_Half |
-	      SUPPORTED_10baseT_Full))) {
-		/* Enabled AUTO-MDIX when autoneg is disabled */
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
-				 (1<<15 | 1<<9 | 7<<0));
-		DP(NETIF_MSG_LINK, "Setting 10M force\n");
-	}
-
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_AN_ADV,
-			 an_10_100_val);
-
-	if (phy->req_duplex == DUPLEX_FULL)
-		autoneg_val |= (1<<8);
-
-	/*
-	 * Always write this if this is not 84833.
-	 * For 84833, write it only when it's a forced speed.
-	 */
-	if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
-		((autoneg_val & (1<<12)) == 0))
-		bnx2x_cl45_write(bp, phy,
-			 MDIO_AN_DEVAD,
-			 MDIO_AN_REG_8481_LEGACY_MII_CTRL, autoneg_val);
-
-	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-	    (phy->speed_cap_mask &
-	     PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
-		(phy->req_line_speed == SPEED_10000)) {
-			DP(NETIF_MSG_LINK, "Advertising 10G\n");
-			/* Restart autoneg for 10G*/
-
-			bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
-				 0x3200);
-	} else
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD,
-				 MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
-				 1);
-
-	/* Save spirom version */
-	bnx2x_save_848xx_spirom_version(phy, params);
-
-	phy->req_line_speed = tmp_req_line_speed;
-
-	return 0;
-}
-
-static int bnx2x_8481_config_init(struct bnx2x_phy *phy,
-				  struct link_params *params,
-				  struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	/* Restore normal power mode*/
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
-
-	/* HW reset */
-	bnx2x_ext_phy_hw_reset(bp, params->port);
-	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);
-}
-
-
-#define PHY84833_HDSHK_WAIT 300
-static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy,
-				   struct link_params *params,
-				   struct link_vars *vars)
-{
-	u32 idx;
-	u32 pair_swap;
-	u16 val;
-	u16 data;
-	struct bnx2x *bp = params->bp;
-	/* Do pair swap */
-
-	/* Check for configuration. */
-	pair_swap = REG_RD(bp, params->shmem_base +
-			   offsetof(struct shmem_region,
-			dev_info.port_hw_config[params->port].xgbt_phy_cfg)) &
-		PORT_HW_CFG_RJ45_PAIR_SWAP_MASK;
-
-	if (pair_swap == 0)
-		return 0;
-
-	data = (u16)pair_swap;
-
-	/* Write CMD_OPEN_OVERRIDE to STATUS reg */
-	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-			MDIO_84833_TOP_CFG_SCRATCH_REG2,
-			PHY84833_CMD_OPEN_OVERRIDE);
-	for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
-		bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
-		if (val == PHY84833_CMD_OPEN_FOR_CMDS)
-			break;
-		msleep(1);
-	}
-	if (idx >= PHY84833_HDSHK_WAIT) {
-		DP(NETIF_MSG_LINK, "Pairswap: FW not ready.\n");
-		return -EINVAL;
-	}
-
-	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-			MDIO_84833_TOP_CFG_SCRATCH_REG4,
-			data);
-	/* Issue pair swap command */
-	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-			MDIO_84833_TOP_CFG_SCRATCH_REG0,
-			PHY84833_DIAG_CMD_PAIR_SWAP_CHANGE);
-	for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
-		bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
-		if ((val == PHY84833_CMD_COMPLETE_PASS) ||
-			(val == PHY84833_CMD_COMPLETE_ERROR))
-			break;
-		msleep(1);
-	}
-	if ((idx >= PHY84833_HDSHK_WAIT) ||
-		(val == PHY84833_CMD_COMPLETE_ERROR)) {
-		DP(NETIF_MSG_LINK, "Pairswap: override failed.\n");
-		return -EINVAL;
-	}
-	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-			MDIO_84833_TOP_CFG_SCRATCH_REG2,
-			PHY84833_CMD_CLEAR_COMPLETE);
-	DP(NETIF_MSG_LINK, "Pairswap OK, val=0x%x\n", data);
-	return 0;
-}
-
-
-static u8 bnx2x_84833_get_reset_gpios(struct bnx2x *bp,
-				      u32 shmem_base_path[],
-				      u32 chip_id)
-{
-	u32 reset_pin[2];
-	u32 idx;
-	u8 reset_gpios;
-	if (CHIP_IS_E3(bp)) {
-		/* Assume that these will be GPIOs, not EPIOs. */
-		for (idx = 0; idx < 2; idx++) {
-			/* Map config param to register bit. */
-			reset_pin[idx] = REG_RD(bp, shmem_base_path[idx] +
-				offsetof(struct shmem_region,
-				dev_info.port_hw_config[0].e3_cmn_pin_cfg));
-			reset_pin[idx] = (reset_pin[idx] &
-				PORT_HW_CFG_E3_PHY_RESET_MASK) >>
-				PORT_HW_CFG_E3_PHY_RESET_SHIFT;
-			reset_pin[idx] -= PIN_CFG_GPIO0_P0;
-			reset_pin[idx] = (1 << reset_pin[idx]);
-		}
-		reset_gpios = (u8)(reset_pin[0] | reset_pin[1]);
-	} else {
-		/* E2, look from diff place of shmem. */
-		for (idx = 0; idx < 2; idx++) {
-			reset_pin[idx] = REG_RD(bp, shmem_base_path[idx] +
-				offsetof(struct shmem_region,
-				dev_info.port_hw_config[0].default_cfg));
-			reset_pin[idx] &= PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK;
-			reset_pin[idx] -= PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0;
-			reset_pin[idx] >>= PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT;
-			reset_pin[idx] = (1 << reset_pin[idx]);
-		}
-		reset_gpios = (u8)(reset_pin[0] | reset_pin[1]);
-	}
-
-	return reset_gpios;
-}
-
-static int bnx2x_84833_hw_reset_phy(struct bnx2x_phy *phy,
-				struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u8 reset_gpios;
-	u32 other_shmem_base_addr = REG_RD(bp, params->shmem2_base +
-				offsetof(struct shmem2_region,
-				other_shmem_base_addr));
-
-	u32 shmem_base_path[2];
-	shmem_base_path[0] = params->shmem_base;
-	shmem_base_path[1] = other_shmem_base_addr;
-
-	reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path,
-						  params->chip_id);
-
-	bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
-	udelay(10);
-	DP(NETIF_MSG_LINK, "84833 hw reset on pin values 0x%x\n",
-		reset_gpios);
-
-	return 0;
-}
-
-static int bnx2x_84833_common_init_phy(struct bnx2x *bp,
-						u32 shmem_base_path[],
-						u32 chip_id)
-{
-	u8 reset_gpios;
-
-	reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path, chip_id);
-
-	bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
-	udelay(10);
-	bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_HIGH);
-	msleep(800);
-	DP(NETIF_MSG_LINK, "84833 reset pulse on pin values 0x%x\n",
-		reset_gpios);
-
-	return 0;
-}
-
-#define PHY84833_CONSTANT_LATENCY 1193
-static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
-				   struct link_params *params,
-				   struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port, initialize = 1;
-	u16 val;
-	u16 temp;
-	u32 actual_phy_selection, cms_enable, idx;
-	int rc = 0;
-
-	msleep(1);
-
-	if (!(CHIP_IS_E1(bp)))
-		port = BP_PATH(bp);
-	else
-		port = params->port;
-
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
-		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
-			       MISC_REGISTERS_GPIO_OUTPUT_HIGH,
-			       port);
-	} else {
-		/* MDIO reset */
-		bnx2x_cl45_write(bp, phy,
-				MDIO_PMA_DEVAD,
-				MDIO_PMA_REG_CTRL, 0x8000);
-		/* Bring PHY out of super isolate mode */
-		bnx2x_cl45_read(bp, phy,
-				MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
-		val &= ~MDIO_84833_SUPER_ISOLATE;
-		bnx2x_cl45_write(bp, phy,
-				MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
-	}
-
-	bnx2x_wait_reset_complete(bp, phy, params);
-
-	/* Wait for GPHY to come out of reset */
-	msleep(50);
-
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
-		bnx2x_84833_pair_swap_cfg(phy, params, vars);
-
-	/*
-	 * 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);
-	bnx2x_program_serdes(&params->phy[INT_PHY], params, vars);
-	vars->line_speed = temp;
-
-	/* Set dual-media configuration according to configuration */
-
-	bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-			MDIO_CTL_REG_84823_MEDIA, &val);
-	val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
-		 MDIO_CTL_REG_84823_MEDIA_LINE_MASK |
-		 MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN |
-		 MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK |
-		 MDIO_CTL_REG_84823_MEDIA_FIBER_1G);
-
-	if (CHIP_IS_E3(bp)) {
-		val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
-			 MDIO_CTL_REG_84823_MEDIA_LINE_MASK);
-	} else {
-		val |= (MDIO_CTL_REG_84823_CTRL_MAC_XFI |
-			MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L);
-	}
-
-	actual_phy_selection = bnx2x_phy_selection(params);
-
-	switch (actual_phy_selection) {
-	case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
-		/* 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;
-		break;
-	case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
-		val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER;
-		break;
-	case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
-		/* Do nothing here. The first PHY won't be initialized at all */
-		break;
-	case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
-		val |= MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN;
-		initialize = 0;
-		break;
-	}
-	if (params->phy[EXT_PHY2].req_line_speed == SPEED_1000)
-		val |= MDIO_CTL_REG_84823_MEDIA_FIBER_1G;
-
-	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-			 MDIO_CTL_REG_84823_MEDIA, val);
-	DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
-		   params->multi_phy_config, val);
-
-	/* AutogrEEEn */
-	if (params->feature_config_flags &
-		FEATURE_CONFIG_AUTOGREEEN_ENABLED) {
-		/* Ensure that f/w is ready */
-		for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
-			bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-					MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
-			if (val == PHY84833_CMD_OPEN_FOR_CMDS)
-				break;
-			usleep_range(1000, 1000);
-		}
-		if (idx >= PHY84833_HDSHK_WAIT) {
-			DP(NETIF_MSG_LINK, "AutogrEEEn: FW not ready.\n");
-			return -EINVAL;
-		}
-
-		/* Select EEE mode */
-		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_SCRATCH_REG3,
-				0x2);
-
-		/* Set Idle and Latency */
-		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_SCRATCH_REG4,
-				PHY84833_CONSTANT_LATENCY + 1);
-
-		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_DATA3_REG,
-				PHY84833_CONSTANT_LATENCY + 1);
-
-		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_DATA4_REG,
-				PHY84833_CONSTANT_LATENCY);
-
-		/* Send EEE instruction to command register */
-		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_SCRATCH_REG0,
-				PHY84833_DIAG_CMD_SET_EEE_MODE);
-
-		/* Ensure that the command has completed */
-		for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
-			bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-					MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
-			if ((val == PHY84833_CMD_COMPLETE_PASS) ||
-				(val == PHY84833_CMD_COMPLETE_ERROR))
-				break;
-			usleep_range(1000, 1000);
-		}
-		if ((idx >= PHY84833_HDSHK_WAIT) ||
-			(val == PHY84833_CMD_COMPLETE_ERROR)) {
-			DP(NETIF_MSG_LINK, "AutogrEEEn: command failed.\n");
-			return -EINVAL;
-		}
-
-		/* Reset command handler */
-		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-			    MDIO_84833_TOP_CFG_SCRATCH_REG2,
-			    PHY84833_CMD_CLEAR_COMPLETE);
-	}
-
-	if (initialize)
-		rc = bnx2x_848xx_cmn_config_init(phy, params, vars);
-	else
-		bnx2x_save_848xx_spirom_version(phy, params);
-	/* 84833 PHY has a better feature and doesn't need to support this. */
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
-		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 bnx2x *bp = params->bp;
-	u16 val, val1, val2;
-	u8 link_up = 0;
-
-
-	/* 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,
-			&val2);
-	DP(NETIF_MSG_LINK, "BCM848xx: PMD_SIGNAL 1.a811 = 0x%x\n", val2);
-
-	/* Check link 10G */
-	if (val2 & (1<<11)) {
-		vars->line_speed = SPEED_10000;
-		vars->duplex = DUPLEX_FULL;
-		link_up = 1;
-		bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
-	} else { /* Check Legacy speed link */
-		u16 legacy_status, legacy_speed;
-
-		/* Enable expansion register 0x42 (Operation mode status) */
-		bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD,
-				 MDIO_AN_REG_8481_EXPANSION_REG_ACCESS, 0xf42);
-
-		/* Get legacy speed operation status */
-		bnx2x_cl45_read(bp, phy,
-				MDIO_AN_DEVAD,
-				MDIO_AN_REG_8481_EXPANSION_REG_RD_RW,
-				&legacy_status);
-
-		DP(NETIF_MSG_LINK, "Legacy speed status"
-			     " = 0x%x\n", legacy_status);
-		link_up = ((legacy_status & (1<<11)) == (1<<11));
-		if (link_up) {
-			legacy_speed = (legacy_status & (3<<9));
-			if (legacy_speed == (0<<9))
-				vars->line_speed = SPEED_10;
-			else if (legacy_speed == (1<<9))
-				vars->line_speed = SPEED_100;
-			else if (legacy_speed == (2<<9))
-				vars->line_speed = SPEED_1000;
-			else /* Should not happen */
-				vars->line_speed = 0;
-
-			if (legacy_status & (1<<8))
-				vars->duplex = DUPLEX_FULL;
-			else
-				vars->duplex = DUPLEX_HALF;
-
-			DP(NETIF_MSG_LINK, "Link is up in %dMbps,"
-				   " is_duplex_full= %d\n", vars->line_speed,
-				   (vars->duplex == DUPLEX_FULL));
-			/* Check legacy speed AN resolution */
-			bnx2x_cl45_read(bp, phy,
-					MDIO_AN_DEVAD,
-					MDIO_AN_REG_8481_LEGACY_MII_STATUS,
-					&val);
-			if (val & (1<<5))
-				vars->link_status |=
-					LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
-			bnx2x_cl45_read(bp, phy,
-					MDIO_AN_DEVAD,
-					MDIO_AN_REG_8481_LEGACY_AN_EXPANSION,
-					&val);
-			if ((val & (1<<0)) == 0)
-				vars->link_status |=
-					LINK_STATUS_PARALLEL_DETECTION_USED;
-		}
-	}
-	if (link_up) {
-		DP(NETIF_MSG_LINK, "BCM84823: link speed is %d\n",
-			   vars->line_speed);
-		bnx2x_ext_phy_resolve_fc(phy, params, vars);
-	}
-
-	return link_up;
-}
-
-
-static int bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
-{
-	int status = 0;
-	u32 spirom_ver;
-	spirom_ver = ((raw_ver & 0xF80) >> 7) << 16 | (raw_ver & 0x7F);
-	status = bnx2x_format_ver(spirom_ver, str, len);
-	return status;
-}
-
-static void bnx2x_8481_hw_reset(struct bnx2x_phy *phy,
-				struct link_params *params)
-{
-	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
-		       MISC_REGISTERS_GPIO_OUTPUT_LOW, 0);
-	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
-		       MISC_REGISTERS_GPIO_OUTPUT_LOW, 1);
-}
-
-static void bnx2x_8481_link_reset(struct bnx2x_phy *phy,
-					struct link_params *params)
-{
-	bnx2x_cl45_write(params->bp, phy,
-			 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000);
-	bnx2x_cl45_write(params->bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1);
-}
-
-static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy,
-				   struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port;
-	u16 val16;
-
-	if (!(CHIP_IS_E1(bp)))
-		port = BP_PATH(bp);
-	else
-		port = params->port;
-
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
-		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
-			       MISC_REGISTERS_GPIO_OUTPUT_LOW,
-			       port);
-	} else {
-		bnx2x_cl45_read(bp, phy,
-				MDIO_CTL_DEVAD,
-				0x400f, &val16);
-		bnx2x_cl45_write(bp, phy,
-				MDIO_PMA_DEVAD,
-				MDIO_PMA_REG_CTRL, 0x800);
-	}
-}
-
-static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
-				     struct link_params *params, u8 mode)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val;
-	u8 port;
-
-	if (!(CHIP_IS_E1(bp)))
-		port = BP_PATH(bp);
-	else
-		port = params->port;
-
-	switch (mode) {
-	case LED_MODE_OFF:
-
-		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OFF\n", port);
-
-		if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
-		    SHARED_HW_CFG_LED_EXTPHY1) {
-
-			/* Set LED masks */
-			bnx2x_cl45_write(bp, phy,
-					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);
-
-			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED3_MASK,
-					0x0);
-
-			bnx2x_cl45_write(bp, phy,
-					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,
-					 0x0);
-		}
-		break;
-	case LED_MODE_FRONT_PANEL_OFF:
-
-		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE FRONT PANEL OFF\n",
-		   port);
-
-		if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
-		    SHARED_HW_CFG_LED_EXTPHY1) {
-
-			/* Set LED masks */
-			bnx2x_cl45_write(bp, phy,
-					 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);
-
-			bnx2x_cl45_write(bp, phy,
-					 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);
-
-		} else {
-			bnx2x_cl45_write(bp, phy,
-					 MDIO_PMA_DEVAD,
-					 MDIO_PMA_REG_8481_LED1_MASK,
-					 0x0);
-		}
-		break;
-	case LED_MODE_ON:
-
-		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE ON\n", port);
-
-		if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
-		    SHARED_HW_CFG_LED_EXTPHY1) {
-			/* Set control reg */
-			bnx2x_cl45_read(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LINK_SIGNAL,
-					&val);
-			val &= 0x8000;
-			val |= 0x2492;
-
-			bnx2x_cl45_write(bp, phy,
-					 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);
-
-			bnx2x_cl45_write(bp, phy,
-					 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);
-
-			bnx2x_cl45_write(bp, phy,
-					 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);
-		}
-		break;
-
-	case LED_MODE_OPER:
-
-		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OPER\n", port);
-
-		if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
-		    SHARED_HW_CFG_LED_EXTPHY1) {
-
-			/* Set control reg */
-			bnx2x_cl45_read(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LINK_SIGNAL,
-					&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, "Setting LINK_SIGNAL\n");
-				bnx2x_cl45_write(bp, phy,
-						 MDIO_PMA_DEVAD,
-						 MDIO_PMA_REG_8481_LINK_SIGNAL,
-						 0xa492);
-			}
-
-			/* Set LED masks */
-			bnx2x_cl45_write(bp, phy,
-					 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);
-
-			bnx2x_cl45_write(bp, phy,
-					 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);
-
-		} else {
-			bnx2x_cl45_write(bp, phy,
-					 MDIO_PMA_DEVAD,
-					 MDIO_PMA_REG_8481_LED1_MASK,
-					 0x80);
-
-			/* Tell LED3 to blink on source */
-			bnx2x_cl45_read(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LINK_SIGNAL,
-					&val);
-			val &= ~(7<<6);
-			val |= (1<<6); /* A83B[8:6]= 1 */
-			bnx2x_cl45_write(bp, phy,
-					 MDIO_PMA_DEVAD,
-					 MDIO_PMA_REG_8481_LINK_SIGNAL,
-					 val);
-		}
-		break;
-	}
-
-	/*
-	 * This is a workaround for E3+84833 until autoneg
-	 * restart is fixed in f/w
-	 */
-	if (CHIP_IS_E3(bp)) {
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_GP2_STATUS_GP_2_1, &val);
-	}
-}
-
-/******************************************************************/
-/*			54618SE PHY SECTION			  */
-/******************************************************************/
-static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
-					       struct link_params *params,
-					       struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port;
-	u16 autoneg_val, an_1000_val, an_10_100_val, fc_val, temp;
-	u32 cfg_pin;
-
-	DP(NETIF_MSG_LINK, "54618SE cfg init\n");
-	usleep_range(1000, 1000);
-
-	/* This works with E3 only, no need to check the chip
-	   before determining the port. */
-	port = params->port;
-
-	cfg_pin = (REG_RD(bp, params->shmem_base +
-			offsetof(struct shmem_region,
-			dev_info.port_hw_config[port].e3_cmn_pin_cfg)) &
-			PORT_HW_CFG_E3_PHY_RESET_MASK) >>
-			PORT_HW_CFG_E3_PHY_RESET_SHIFT;
-
-	/* Drive pin high to bring the GPHY out of reset. */
-	bnx2x_set_cfg_pin(bp, cfg_pin, 1);
-
-	/* wait for GPHY to reset */
-	msleep(50);
-
-	/* reset phy */
-	bnx2x_cl22_write(bp, phy,
-			 MDIO_PMA_REG_CTRL, 0x8000);
-	bnx2x_wait_reset_complete(bp, phy, params);
-
-	/*wait for GPHY to reset */
-	msleep(50);
-
-	/* Configure LED4: set to INTR (0x6). */
-	/* Accessing shadow register 0xe. */
-	bnx2x_cl22_write(bp, phy,
-			MDIO_REG_GPHY_SHADOW,
-			MDIO_REG_GPHY_SHADOW_LED_SEL2);
-	bnx2x_cl22_read(bp, phy,
-			MDIO_REG_GPHY_SHADOW,
-			&temp);
-	temp &= ~(0xf << 4);
-	temp |= (0x6 << 4);
-	bnx2x_cl22_write(bp, phy,
-			MDIO_REG_GPHY_SHADOW,
-			MDIO_REG_GPHY_SHADOW_WR_ENA | temp);
-	/* Configure INTR based on link status change. */
-	bnx2x_cl22_write(bp, phy,
-			MDIO_REG_INTR_MASK,
-			~MDIO_REG_INTR_MASK_LINK_STATUS);
-
-	/* Flip the signal detect polarity (set 0x1c.0x1e[8]). */
-	bnx2x_cl22_write(bp, phy,
-			MDIO_REG_GPHY_SHADOW,
-			MDIO_REG_GPHY_SHADOW_AUTO_DET_MED);
-	bnx2x_cl22_read(bp, phy,
-			MDIO_REG_GPHY_SHADOW,
-			&temp);
-	temp |= MDIO_REG_GPHY_SHADOW_INVERT_FIB_SD;
-	bnx2x_cl22_write(bp, phy,
-			MDIO_REG_GPHY_SHADOW,
-			MDIO_REG_GPHY_SHADOW_WR_ENA | temp);
-
-	/* Set up fc */
-	/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
-	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
-	fc_val = 0;
-	if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
-			MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC)
-		fc_val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
-
-	if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
-			MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH)
-		fc_val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
-
-	/* read all advertisement */
-	bnx2x_cl22_read(bp, phy,
-			0x09,
-			&an_1000_val);
-
-	bnx2x_cl22_read(bp, phy,
-			0x04,
-			&an_10_100_val);
-
-	bnx2x_cl22_read(bp, phy,
-			MDIO_PMA_REG_CTRL,
-			&autoneg_val);
-
-	/* Disable forced speed */
-	autoneg_val &= ~((1<<6) | (1<<8) | (1<<9) | (1<<12) | (1<<13));
-	an_10_100_val &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8) | (1<<10) |
-			   (1<<11));
-
-	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-			(phy->speed_cap_mask &
-			PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
-			(phy->req_line_speed == SPEED_1000)) {
-		an_1000_val |= (1<<8);
-		autoneg_val |= (1<<9 | 1<<12);
-		if (phy->req_duplex == DUPLEX_FULL)
-			an_1000_val |= (1<<9);
-		DP(NETIF_MSG_LINK, "Advertising 1G\n");
-	} else
-		an_1000_val &= ~((1<<8) | (1<<9));
-
-	bnx2x_cl22_write(bp, phy,
-			0x09,
-			an_1000_val);
-	bnx2x_cl22_read(bp, phy,
-			0x09,
-			&an_1000_val);
-
-	/* set 100 speed advertisement */
-	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-			(phy->speed_cap_mask &
-			(PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
-			PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) {
-		an_10_100_val |= (1<<7);
-		/* Enable autoneg and restart autoneg for legacy speeds */
-		autoneg_val |= (1<<9 | 1<<12);
-
-		if (phy->req_duplex == DUPLEX_FULL)
-			an_10_100_val |= (1<<8);
-		DP(NETIF_MSG_LINK, "Advertising 100M\n");
-	}
-
-	/* set 10 speed advertisement */
-	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-			(phy->speed_cap_mask &
-			(PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
-			PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) {
-		an_10_100_val |= (1<<5);
-		autoneg_val |= (1<<9 | 1<<12);
-		if (phy->req_duplex == DUPLEX_FULL)
-			an_10_100_val |= (1<<6);
-		DP(NETIF_MSG_LINK, "Advertising 10M\n");
-	}
-
-	/* Only 10/100 are allowed to work in FORCE mode */
-	if (phy->req_line_speed == SPEED_100) {
-		autoneg_val |= (1<<13);
-		/* Enabled AUTO-MDIX when autoneg is disabled */
-		bnx2x_cl22_write(bp, phy,
-				0x18,
-				(1<<15 | 1<<9 | 7<<0));
-		DP(NETIF_MSG_LINK, "Setting 100M force\n");
-	}
-	if (phy->req_line_speed == SPEED_10) {
-		/* Enabled AUTO-MDIX when autoneg is disabled */
-		bnx2x_cl22_write(bp, phy,
-				0x18,
-				(1<<15 | 1<<9 | 7<<0));
-		DP(NETIF_MSG_LINK, "Setting 10M force\n");
-	}
-
-	/* Check if we should turn on Auto-GrEEEn */
-	bnx2x_cl22_read(bp, phy, MDIO_REG_GPHY_PHYID_LSB, &temp);
-	if (temp == MDIO_REG_GPHY_ID_54618SE) {
-		if (params->feature_config_flags &
-		    FEATURE_CONFIG_AUTOGREEEN_ENABLED) {
-			temp = 6;
-			DP(NETIF_MSG_LINK, "Enabling Auto-GrEEEn\n");
-		} else {
-			temp = 0;
-			DP(NETIF_MSG_LINK, "Disabling Auto-GrEEEn\n");
-		}
-		bnx2x_cl22_write(bp, phy,
-				 MDIO_REG_GPHY_CL45_ADDR_REG, MDIO_AN_DEVAD);
-		bnx2x_cl22_write(bp, phy,
-				 MDIO_REG_GPHY_CL45_DATA_REG,
-				 MDIO_REG_GPHY_EEE_ADV);
-		bnx2x_cl22_write(bp, phy,
-				 MDIO_REG_GPHY_CL45_ADDR_REG,
-				 (0x1 << 14) | MDIO_AN_DEVAD);
-		bnx2x_cl22_write(bp, phy,
-				 MDIO_REG_GPHY_CL45_DATA_REG,
-				 temp);
-	}
-
-	bnx2x_cl22_write(bp, phy,
-			0x04,
-			an_10_100_val | fc_val);
-
-	if (phy->req_duplex == DUPLEX_FULL)
-		autoneg_val |= (1<<8);
-
-	bnx2x_cl22_write(bp, phy,
-			MDIO_PMA_REG_CTRL, autoneg_val);
-
-	return 0;
-}
-
-static void bnx2x_54618se_set_link_led(struct bnx2x_phy *phy,
-				       struct link_params *params, u8 mode)
-{
-	struct bnx2x *bp = params->bp;
-	DP(NETIF_MSG_LINK, "54618SE set link led (mode=%x)\n", mode);
-	switch (mode) {
-	case LED_MODE_FRONT_PANEL_OFF:
-	case LED_MODE_OFF:
-	case LED_MODE_OPER:
-	case LED_MODE_ON:
-	default:
-		break;
-	}
-	return;
-}
-
-static void bnx2x_54618se_link_reset(struct bnx2x_phy *phy,
-				     struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u32 cfg_pin;
-	u8 port;
-
-	/*
-	 * In case of no EPIO routed to reset the GPHY, put it
-	 * in low power mode.
-	 */
-	bnx2x_cl22_write(bp, phy, MDIO_PMA_REG_CTRL, 0x800);
-	/*
-	 * This works with E3 only, no need to check the chip
-	 * before determining the port.
-	 */
-	port = params->port;
-	cfg_pin = (REG_RD(bp, params->shmem_base +
-			offsetof(struct shmem_region,
-			dev_info.port_hw_config[port].e3_cmn_pin_cfg)) &
-			PORT_HW_CFG_E3_PHY_RESET_MASK) >>
-			PORT_HW_CFG_E3_PHY_RESET_SHIFT;
-
-	/* Drive pin low to put GPHY in reset. */
-	bnx2x_set_cfg_pin(bp, cfg_pin, 0);
-}
-
-static u8 bnx2x_54618se_read_status(struct bnx2x_phy *phy,
-				    struct link_params *params,
-				    struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val;
-	u8 link_up = 0;
-	u16 legacy_status, legacy_speed;
-
-	/* Get speed operation status */
-	bnx2x_cl22_read(bp, phy,
-			0x19,
-			&legacy_status);
-	DP(NETIF_MSG_LINK, "54618SE read_status: 0x%x\n", legacy_status);
-
-	/* Read status to clear the PHY interrupt. */
-	bnx2x_cl22_read(bp, phy,
-			MDIO_REG_INTR_STATUS,
-			&val);
-
-	link_up = ((legacy_status & (1<<2)) == (1<<2));
-
-	if (link_up) {
-		legacy_speed = (legacy_status & (7<<8));
-		if (legacy_speed == (7<<8)) {
-			vars->line_speed = SPEED_1000;
-			vars->duplex = DUPLEX_FULL;
-		} else if (legacy_speed == (6<<8)) {
-			vars->line_speed = SPEED_1000;
-			vars->duplex = DUPLEX_HALF;
-		} else if (legacy_speed == (5<<8)) {
-			vars->line_speed = SPEED_100;
-			vars->duplex = DUPLEX_FULL;
-		}
-		/* Omitting 100Base-T4 for now */
-		else if (legacy_speed == (3<<8)) {
-			vars->line_speed = SPEED_100;
-			vars->duplex = DUPLEX_HALF;
-		} else if (legacy_speed == (2<<8)) {
-			vars->line_speed = SPEED_10;
-			vars->duplex = DUPLEX_FULL;
-		} else if (legacy_speed == (1<<8)) {
-			vars->line_speed = SPEED_10;
-			vars->duplex = DUPLEX_HALF;
-		} else /* Should not happen */
-			vars->line_speed = 0;
-
-		DP(NETIF_MSG_LINK, "Link is up in %dMbps,"
-			   " is_duplex_full= %d\n", vars->line_speed,
-			   (vars->duplex == DUPLEX_FULL));
-
-		/* Check legacy speed AN resolution */
-		bnx2x_cl22_read(bp, phy,
-				0x01,
-				&val);
-		if (val & (1<<5))
-			vars->link_status |=
-				LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
-		bnx2x_cl22_read(bp, phy,
-				0x06,
-				&val);
-		if ((val & (1<<0)) == 0)
-			vars->link_status |=
-				LINK_STATUS_PARALLEL_DETECTION_USED;
-
-		DP(NETIF_MSG_LINK, "BCM54618SE: link speed is %d\n",
-			   vars->line_speed);
-
-		/* Report whether EEE is resolved. */
-		bnx2x_cl22_read(bp, phy, MDIO_REG_GPHY_PHYID_LSB, &val);
-		if (val == MDIO_REG_GPHY_ID_54618SE) {
-			if (vars->link_status &
-			    LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
-				val = 0;
-			else {
-				bnx2x_cl22_write(bp, phy,
-					MDIO_REG_GPHY_CL45_ADDR_REG,
-					MDIO_AN_DEVAD);
-				bnx2x_cl22_write(bp, phy,
-					MDIO_REG_GPHY_CL45_DATA_REG,
-					MDIO_REG_GPHY_EEE_RESOLVED);
-				bnx2x_cl22_write(bp, phy,
-					MDIO_REG_GPHY_CL45_ADDR_REG,
-					(0x1 << 14) | MDIO_AN_DEVAD);
-				bnx2x_cl22_read(bp, phy,
-					MDIO_REG_GPHY_CL45_DATA_REG,
-					&val);
-			}
-			DP(NETIF_MSG_LINK, "EEE resolution: 0x%x\n", val);
-		}
-
-		bnx2x_ext_phy_resolve_fc(phy, params, vars);
-	}
-	return link_up;
-}
-
-static void bnx2x_54618se_config_loopback(struct bnx2x_phy *phy,
-					  struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val;
-	u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
-
-	DP(NETIF_MSG_LINK, "2PMA/PMD ext_phy_loopback: 54618se\n");
-
-	/* Enable master/slave manual mmode and set to master */
-	/* mii write 9 [bits set 11 12] */
-	bnx2x_cl22_write(bp, phy, 0x09, 3<<11);
-
-	/* forced 1G and disable autoneg */
-	/* set val [mii read 0] */
-	/* set val [expr $val & [bits clear 6 12 13]] */
-	/* set val [expr $val | [bits set 6 8]] */
-	/* mii write 0 $val */
-	bnx2x_cl22_read(bp, phy, 0x00, &val);
-	val &= ~((1<<6) | (1<<12) | (1<<13));
-	val |= (1<<6) | (1<<8);
-	bnx2x_cl22_write(bp, phy, 0x00, val);
-
-	/* Set external loopback and Tx using 6dB coding */
-	/* mii write 0x18 7 */
-	/* set val [mii read 0x18] */
-	/* mii write 0x18 [expr $val | [bits set 10 15]] */
-	bnx2x_cl22_write(bp, phy, 0x18, 7);
-	bnx2x_cl22_read(bp, phy, 0x18, &val);
-	bnx2x_cl22_write(bp, phy, 0x18, val | (1<<10) | (1<<15));
-
-	/* This register opens the gate for the UMAC despite its name */
-	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 1);
-
-	/*
-	 * Maximum Frame Length (RW). Defines a 14-Bit maximum frame
-	 * length used by the MAC receive logic to check frames.
-	 */
-	REG_WR(bp, umac_base + UMAC_REG_MAXFR, 0x2710);
-}
-
-/******************************************************************/
-/*			SFX7101 PHY SECTION			  */
-/******************************************************************/
-static void bnx2x_7101_config_loopback(struct bnx2x_phy *phy,
-				       struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	/* SFX7101_XGXS_TEST1 */
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_XS_DEVAD, MDIO_XS_SFX7101_XGXS_TEST1, 0x100);
-}
-
-static int bnx2x_7101_config_init(struct bnx2x_phy *phy,
-				  struct link_params *params,
-				  struct link_vars *vars)
-{
-	u16 fw_ver1, fw_ver2, val;
-	struct bnx2x *bp = params->bp;
-	DP(NETIF_MSG_LINK, "Setting the SFX7101 LASI indication\n");
-
-	/* Restore normal power mode*/
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
-	/* HW reset */
-	bnx2x_ext_phy_hw_reset(bp, params->port);
-	bnx2x_wait_reset_complete(bp, phy, params);
-
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x1);
-	DP(NETIF_MSG_LINK, "Setting the SFX7101 LED to blink on traffic\n");
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
-
-	bnx2x_ext_phy_set_pause(params, phy, vars);
-	/* Restart autoneg */
-	bnx2x_cl45_read(bp, phy,
-			MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, &val);
-	val |= 0x200;
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, val);
-
-	/* Save spirom version */
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER1, &fw_ver1);
-
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER2, &fw_ver2);
-	bnx2x_save_spirom_version(bp, params->port,
-				  (u32)(fw_ver1<<16 | fw_ver2), phy->ver_addr);
-	return 0;
-}
-
-static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy,
-				 struct link_params *params,
-				 struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u8 link_up;
-	u16 val1, val2;
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val2);
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
-	DP(NETIF_MSG_LINK, "10G-base-T LASI status 0x%x->0x%x\n",
-		   val2, val1);
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
-	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_up) {
-		bnx2x_cl45_read(bp, phy,
-				MDIO_AN_DEVAD, MDIO_AN_REG_MASTER_STATUS,
-				&val2);
-		vars->line_speed = SPEED_10000;
-		vars->duplex = DUPLEX_FULL;
-		DP(NETIF_MSG_LINK, "SFX7101 AN status 0x%x->Master=%x\n",
-			   val2, (val2 & (1<<14)));
-		bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
-		bnx2x_ext_phy_resolve_fc(phy, params, vars);
-	}
-	return link_up;
-}
-
-static int bnx2x_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len)
-{
-	if (*len < 5)
-		return -EINVAL;
-	str[0] = (spirom_ver & 0xFF);
-	str[1] = (spirom_ver & 0xFF00) >> 8;
-	str[2] = (spirom_ver & 0xFF0000) >> 16;
-	str[3] = (spirom_ver & 0xFF000000) >> 24;
-	str[4] = '\0';
-	*len -= 5;
-	return 0;
-}
-
-void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy)
-{
-	u16 val, cnt;
-
-	bnx2x_cl45_read(bp, phy,
-			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)));
-		/* Wait for clear */
-		bnx2x_cl45_read(bp, phy,
-				MDIO_PMA_DEVAD,
-				MDIO_PMA_REG_7101_RESET, &val);
-
-		if ((val & (1<<15)) == 0)
-			break;
-	}
-}
-
-static void bnx2x_7101_hw_reset(struct bnx2x_phy *phy,
-				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);
-	/* The PHY reset is controlled by GPIO 1 */
-	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
-		       MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
-}
-
-static void bnx2x_7101_set_link_led(struct bnx2x_phy *phy,
-				    struct link_params *params, u8 mode)
-{
-	u16 val = 0;
-	struct bnx2x *bp = params->bp;
-	switch (mode) {
-	case LED_MODE_FRONT_PANEL_OFF:
-	case LED_MODE_OFF:
-		val = 2;
-		break;
-	case LED_MODE_ON:
-		val = 1;
-		break;
-	case LED_MODE_OPER:
-		val = 0;
-		break;
-	}
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_7107_LINK_LED_CNTL,
-			 val);
-}
-
-/******************************************************************/
-/*			STATIC PHY DECLARATION			  */
-/******************************************************************/
-
-static struct bnx2x_phy phy_null = {
-	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN,
-	.addr		= 0,
-	.def_md_devad	= 0,
-	.flags		= FLAGS_INIT_XGXS_FIRST,
-	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
-	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
-	.mdio_ctrl	= 0,
-	.supported	= 0,
-	.media_type	= ETH_PHY_NOT_PRESENT,
-	.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)NULL,
-	.read_status	= (read_status_t)NULL,
-	.link_reset	= (link_reset_t)NULL,
-	.config_loopback = (config_loopback_t)NULL,
-	.format_fw_ver	= (format_fw_ver_t)NULL,
-	.hw_reset	= (hw_reset_t)NULL,
-	.set_link_led	= (set_link_led_t)NULL,
-	.phy_specific_func = (phy_specific_func_t)NULL
-};
-
-static struct bnx2x_phy phy_serdes = {
-	.type		= PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT,
-	.addr		= 0xff,
-	.def_md_devad	= 0,
-	.flags		= 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_2500baseX_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_xgxs_config_init,
-	.read_status	= (read_status_t)bnx2x_link_settings_status,
-	.link_reset	= (link_reset_t)bnx2x_int_link_reset,
-	.config_loopback = (config_loopback_t)NULL,
-	.format_fw_ver	= (format_fw_ver_t)NULL,
-	.hw_reset	= (hw_reset_t)NULL,
-	.set_link_led	= (set_link_led_t)NULL,
-	.phy_specific_func = (phy_specific_func_t)NULL
-};
-
-static struct bnx2x_phy phy_xgxs = {
-	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
-	.addr		= 0xff,
-	.def_md_devad	= 0,
-	.flags		= 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_2500baseX_Full |
-			   SUPPORTED_10000baseT_Full |
-			   SUPPORTED_FIBRE |
-			   SUPPORTED_Autoneg |
-			   SUPPORTED_Pause |
-			   SUPPORTED_Asym_Pause),
-	.media_type	= ETH_PHY_CX4,
-	.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_xgxs_config_init,
-	.read_status	= (read_status_t)bnx2x_link_settings_status,
-	.link_reset	= (link_reset_t)bnx2x_int_link_reset,
-	.config_loopback = (config_loopback_t)bnx2x_set_xgxs_loopback,
-	.format_fw_ver	= (format_fw_ver_t)NULL,
-	.hw_reset	= (hw_reset_t)NULL,
-	.set_link_led	= (set_link_led_t)NULL,
-	.phy_specific_func = (phy_specific_func_t)NULL
-};
-static struct bnx2x_phy phy_warpcore = {
-	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
-	.addr		= 0xff,
-	.def_md_devad	= 0,
-	.flags		= FLAGS_HW_LOCK_REQUIRED,
-	.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_20000baseKR2_Full |
-			     SUPPORTED_20000baseMLD2_Full |
-			     SUPPORTED_FIBRE |
-			     SUPPORTED_Autoneg |
-			     SUPPORTED_Pause |
-			     SUPPORTED_Asym_Pause),
-	.media_type	= ETH_PHY_UNSPECIFIED,
-	.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_warpcore_config_init,
-	.read_status	= (read_status_t)bnx2x_warpcore_read_status,
-	.link_reset	= (link_reset_t)bnx2x_warpcore_link_reset,
-	.config_loopback = (config_loopback_t)bnx2x_set_warpcore_loopback,
-	.format_fw_ver	= (format_fw_ver_t)NULL,
-	.hw_reset	= (hw_reset_t)bnx2x_warpcore_hw_reset,
-	.set_link_led	= (set_link_led_t)NULL,
-	.phy_specific_func = (phy_specific_func_t)NULL
-};
-
-
-static struct bnx2x_phy phy_7101 = {
-	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
-	.addr		= 0xff,
-	.def_md_devad	= 0,
-	.flags		= FLAGS_FAN_FAILURE_DET_REQ,
-	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
-	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
-	.mdio_ctrl	= 0,
-	.supported	= (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_7101_config_init,
-	.read_status	= (read_status_t)bnx2x_7101_read_status,
-	.link_reset	= (link_reset_t)bnx2x_common_ext_link_reset,
-	.config_loopback = (config_loopback_t)bnx2x_7101_config_loopback,
-	.format_fw_ver	= (format_fw_ver_t)bnx2x_7101_format_ver,
-	.hw_reset	= (hw_reset_t)bnx2x_7101_hw_reset,
-	.set_link_led	= (set_link_led_t)bnx2x_7101_set_link_led,
-	.phy_specific_func = (phy_specific_func_t)NULL
-};
-static struct bnx2x_phy phy_8073 = {
-	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-	.addr		= 0xff,
-	.def_md_devad	= 0,
-	.flags		= FLAGS_HW_LOCK_REQUIRED,
-	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
-	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
-	.mdio_ctrl	= 0,
-	.supported	= (SUPPORTED_10000baseT_Full |
-			   SUPPORTED_2500baseX_Full |
-			   SUPPORTED_1000baseT_Full |
-			   SUPPORTED_FIBRE |
-			   SUPPORTED_Autoneg |
-			   SUPPORTED_Pause |
-			   SUPPORTED_Asym_Pause),
-	.media_type	= ETH_PHY_KR,
-	.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_8073_config_init,
-	.read_status	= (read_status_t)bnx2x_8073_read_status,
-	.link_reset	= (link_reset_t)bnx2x_8073_link_reset,
-	.config_loopback = (config_loopback_t)NULL,
-	.format_fw_ver	= (format_fw_ver_t)bnx2x_format_ver,
-	.hw_reset	= (hw_reset_t)NULL,
-	.set_link_led	= (set_link_led_t)NULL,
-	.phy_specific_func = (phy_specific_func_t)NULL
-};
-static struct bnx2x_phy phy_8705 = {
-	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705,
-	.addr		= 0xff,
-	.def_md_devad	= 0,
-	.flags		= FLAGS_INIT_XGXS_FIRST,
-	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
-	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
-	.mdio_ctrl	= 0,
-	.supported	= (SUPPORTED_10000baseT_Full |
-			   SUPPORTED_FIBRE |
-			   SUPPORTED_Pause |
-			   SUPPORTED_Asym_Pause),
-	.media_type	= ETH_PHY_XFP_FIBER,
-	.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_8705_config_init,
-	.read_status	= (read_status_t)bnx2x_8705_read_status,
-	.link_reset	= (link_reset_t)bnx2x_common_ext_link_reset,
-	.config_loopback = (config_loopback_t)NULL,
-	.format_fw_ver	= (format_fw_ver_t)bnx2x_null_format_ver,
-	.hw_reset	= (hw_reset_t)NULL,
-	.set_link_led	= (set_link_led_t)NULL,
-	.phy_specific_func = (phy_specific_func_t)NULL
-};
-static struct bnx2x_phy phy_8706 = {
-	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
-	.addr		= 0xff,
-	.def_md_devad	= 0,
-	.flags		= FLAGS_INIT_XGXS_FIRST,
-	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
-	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
-	.mdio_ctrl	= 0,
-	.supported	= (SUPPORTED_10000baseT_Full |
-			   SUPPORTED_1000baseT_Full |
-			   SUPPORTED_FIBRE |
-			   SUPPORTED_Pause |
-			   SUPPORTED_Asym_Pause),
-	.media_type	= ETH_PHY_SFP_FIBER,
-	.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_8706_config_init,
-	.read_status	= (read_status_t)bnx2x_8706_read_status,
-	.link_reset	= (link_reset_t)bnx2x_common_ext_link_reset,
-	.config_loopback = (config_loopback_t)NULL,
-	.format_fw_ver	= (format_fw_ver_t)bnx2x_format_ver,
-	.hw_reset	= (hw_reset_t)NULL,
-	.set_link_led	= (set_link_led_t)NULL,
-	.phy_specific_func = (phy_specific_func_t)NULL
-};
-
-static struct bnx2x_phy phy_8726 = {
-	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
-	.addr		= 0xff,
-	.def_md_devad	= 0,
-	.flags		= (FLAGS_HW_LOCK_REQUIRED |
-			   FLAGS_INIT_XGXS_FIRST),
-	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
-	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
-	.mdio_ctrl	= 0,
-	.supported	= (SUPPORTED_10000baseT_Full |
-			   SUPPORTED_1000baseT_Full |
-			   SUPPORTED_Autoneg |
-			   SUPPORTED_FIBRE |
-			   SUPPORTED_Pause |
-			   SUPPORTED_Asym_Pause),
-	.media_type	= ETH_PHY_NOT_PRESENT,
-	.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_8726_config_init,
-	.read_status	= (read_status_t)bnx2x_8726_read_status,
-	.link_reset	= (link_reset_t)bnx2x_8726_link_reset,
-	.config_loopback = (config_loopback_t)bnx2x_8726_config_loopback,
-	.format_fw_ver	= (format_fw_ver_t)bnx2x_format_ver,
-	.hw_reset	= (hw_reset_t)NULL,
-	.set_link_led	= (set_link_led_t)NULL,
-	.phy_specific_func = (phy_specific_func_t)NULL
-};
-
-static struct bnx2x_phy phy_8727 = {
-	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-	.addr		= 0xff,
-	.def_md_devad	= 0,
-	.flags		= FLAGS_FAN_FAILURE_DET_REQ,
-	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
-	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
-	.mdio_ctrl	= 0,
-	.supported	= (SUPPORTED_10000baseT_Full |
-			   SUPPORTED_1000baseT_Full |
-			   SUPPORTED_FIBRE |
-			   SUPPORTED_Pause |
-			   SUPPORTED_Asym_Pause),
-	.media_type	= ETH_PHY_NOT_PRESENT,
-	.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_8727_config_init,
-	.read_status	= (read_status_t)bnx2x_8727_read_status,
-	.link_reset	= (link_reset_t)bnx2x_8727_link_reset,
-	.config_loopback = (config_loopback_t)NULL,
-	.format_fw_ver	= (format_fw_ver_t)bnx2x_format_ver,
-	.hw_reset	= (hw_reset_t)bnx2x_8727_hw_reset,
-	.set_link_led	= (set_link_led_t)bnx2x_8727_set_link_led,
-	.phy_specific_func = (phy_specific_func_t)bnx2x_8727_specific_func
-};
-static struct bnx2x_phy phy_8481 = {
-	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
-	.addr		= 0xff,
-	.def_md_devad	= 0,
-	.flags		= FLAGS_FAN_FAILURE_DET_REQ |
-			  FLAGS_REARM_LATCH_SIGNAL,
-	.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_8481_config_init,
-	.read_status	= (read_status_t)bnx2x_848xx_read_status,
-	.link_reset	= (link_reset_t)bnx2x_8481_link_reset,
-	.config_loopback = (config_loopback_t)NULL,
-	.format_fw_ver	= (format_fw_ver_t)bnx2x_848xx_format_ver,
-	.hw_reset	= (hw_reset_t)bnx2x_8481_hw_reset,
-	.set_link_led	= (set_link_led_t)bnx2x_848xx_set_link_led,
-	.phy_specific_func = (phy_specific_func_t)NULL
-};
-
-static struct bnx2x_phy phy_84823 = {
-	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
-	.addr		= 0xff,
-	.def_md_devad	= 0,
-	.flags		= FLAGS_FAN_FAILURE_DET_REQ |
-			  FLAGS_REARM_LATCH_SIGNAL,
-	.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
-};
-
-static struct bnx2x_phy phy_84833 = {
-	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833,
-	.addr		= 0xff,
-	.def_md_devad	= 0,
-	.flags		= FLAGS_FAN_FAILURE_DET_REQ |
-			    FLAGS_REARM_LATCH_SIGNAL,
-	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
-	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
-	.mdio_ctrl	= 0,
-	.supported	= (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)bnx2x_84833_hw_reset_phy,
-	.set_link_led	= (set_link_led_t)bnx2x_848xx_set_link_led,
-	.phy_specific_func = (phy_specific_func_t)NULL
-};
-
-static struct bnx2x_phy phy_54618se = {
-	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE,
-	.addr		= 0xff,
-	.def_md_devad	= 0,
-	.flags		= FLAGS_INIT_XGXS_FIRST,
-	.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_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_54618se_config_init,
-	.read_status	= (read_status_t)bnx2x_54618se_read_status,
-	.link_reset	= (link_reset_t)bnx2x_54618se_link_reset,
-	.config_loopback = (config_loopback_t)bnx2x_54618se_config_loopback,
-	.format_fw_ver	= (format_fw_ver_t)NULL,
-	.hw_reset	= (hw_reset_t)NULL,
-	.set_link_led	= (set_link_led_t)bnx2x_54618se_set_link_led,
-	.phy_specific_func = (phy_specific_func_t)NULL
-};
-/*****************************************************************/
-/*                                                               */
-/* Populate the phy according. Main function: bnx2x_populate_phy   */
-/*                                                               */
-/*****************************************************************/
-
-static void bnx2x_populate_preemphasis(struct bnx2x *bp, u32 shmem_base,
-				     struct bnx2x_phy *phy, u8 port,
-				     u8 phy_index)
-{
-	/* 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
-		 */
-		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]));
-
-			tx = REG_RD(bp, shmem_base +
-				    offsetof(struct shmem_region,
-			  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]));
-
-			tx = REG_RD(bp, shmem_base +
-				    offsetof(struct shmem_region,
-			 dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
-		}
-
-		phy->rx_preemphasis[i << 1] = ((rx>>16) & 0xffff);
-		phy->rx_preemphasis[(i << 1) + 1] = (rx & 0xffff);
-
-		phy->tx_preemphasis[i << 1] = ((tx>>16) & 0xffff);
-		phy->tx_preemphasis[(i << 1) + 1] = (tx & 0xffff);
-	}
-}
-
-static u32 bnx2x_get_ext_phy_config(struct bnx2x *bp, u32 shmem_base,
-				    u8 phy_index, u8 port)
-{
-	u32 ext_phy_config = 0;
-	switch (phy_index) {
-	case EXT_PHY1:
-		ext_phy_config = REG_RD(bp, shmem_base +
-					      offsetof(struct shmem_region,
-			dev_info.port_hw_config[port].external_phy_config));
-		break;
-	case EXT_PHY2:
-		ext_phy_config = REG_RD(bp, shmem_base +
-					      offsetof(struct shmem_region,
-			dev_info.port_hw_config[port].external_phy_config2));
-		break;
-	default:
-		DP(NETIF_MSG_LINK, "Invalid phy_index %d\n", phy_index);
-		return -EINVAL;
-	}
-
-	return ext_phy_config;
-}
-static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
-				  struct bnx2x_phy *phy)
-{
-	u32 phy_addr;
-	u32 chip_id;
-	u32 switch_cfg = (REG_RD(bp, shmem_base +
-				       offsetof(struct shmem_region,
-			dev_info.port_feature_config[port].link_config)) &
-			  PORT_FEATURE_CONNECTED_SWITCH_MASK);
-	chip_id = REG_RD(bp, MISC_REG_CHIP_NUM) << 16;
-	DP(NETIF_MSG_LINK, ":chip_id = 0x%x\n", chip_id);
-	if (USES_WARPCORE(bp)) {
-		u32 serdes_net_if;
-		phy_addr = REG_RD(bp,
-				  MISC_REG_WC0_CTRL_PHY_ADDR);
-		*phy = phy_warpcore;
-		if (REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR) == 0x3)
-			phy->flags |= FLAGS_4_PORT_MODE;
-		else
-			phy->flags &= ~FLAGS_4_PORT_MODE;
-			/* Check Dual mode */
-		serdes_net_if = (REG_RD(bp, shmem_base +
-					offsetof(struct shmem_region, dev_info.
-					port_hw_config[port].default_cfg)) &
-				 PORT_HW_CFG_NET_SERDES_IF_MASK);
-		/*
-		 * Set the appropriate supported and flags indications per
-		 * interface type of the chip
-		 */
-		switch (serdes_net_if) {
-		case PORT_HW_CFG_NET_SERDES_IF_SGMII:
-			phy->supported &= (SUPPORTED_10baseT_Half |
-					   SUPPORTED_10baseT_Full |
-					   SUPPORTED_100baseT_Half |
-					   SUPPORTED_100baseT_Full |
-					   SUPPORTED_1000baseT_Full |
-					   SUPPORTED_FIBRE |
-					   SUPPORTED_Autoneg |
-					   SUPPORTED_Pause |
-					   SUPPORTED_Asym_Pause);
-			phy->media_type = ETH_PHY_BASE_T;
-			break;
-		case PORT_HW_CFG_NET_SERDES_IF_XFI:
-			phy->media_type = ETH_PHY_XFP_FIBER;
-			break;
-		case PORT_HW_CFG_NET_SERDES_IF_SFI:
-			phy->supported &= (SUPPORTED_1000baseT_Full |
-					   SUPPORTED_10000baseT_Full |
-					   SUPPORTED_FIBRE |
-					   SUPPORTED_Pause |
-					   SUPPORTED_Asym_Pause);
-			phy->media_type = ETH_PHY_SFP_FIBER;
-			break;
-		case PORT_HW_CFG_NET_SERDES_IF_KR:
-			phy->media_type = ETH_PHY_KR;
-			phy->supported &= (SUPPORTED_1000baseT_Full |
-					   SUPPORTED_10000baseT_Full |
-					   SUPPORTED_FIBRE |
-					   SUPPORTED_Autoneg |
-					   SUPPORTED_Pause |
-					   SUPPORTED_Asym_Pause);
-			break;
-		case PORT_HW_CFG_NET_SERDES_IF_DXGXS:
-			phy->media_type = ETH_PHY_KR;
-			phy->flags |= FLAGS_WC_DUAL_MODE;
-			phy->supported &= (SUPPORTED_20000baseMLD2_Full |
-					   SUPPORTED_FIBRE |
-					   SUPPORTED_Pause |
-					   SUPPORTED_Asym_Pause);
-			break;
-		case PORT_HW_CFG_NET_SERDES_IF_KR2:
-			phy->media_type = ETH_PHY_KR;
-			phy->flags |= FLAGS_WC_DUAL_MODE;
-			phy->supported &= (SUPPORTED_20000baseKR2_Full |
-					   SUPPORTED_FIBRE |
-					   SUPPORTED_Pause |
-					   SUPPORTED_Asym_Pause);
-			break;
-		default:
-			DP(NETIF_MSG_LINK, "Unknown WC interface type 0x%x\n",
-				       serdes_net_if);
-			break;
-		}
-
-		/*
-		 * Enable MDC/MDIO work-around for E3 A0 since free running MDC
-		 * was not set as expected. For B0, ECO will be enabled so there
-		 * won't be an issue there
-		 */
-		if (CHIP_REV(bp) == CHIP_REV_Ax)
-			phy->flags |= FLAGS_MDC_MDIO_WA;
-		else
-			phy->flags |= FLAGS_MDC_MDIO_WA_B0;
-	} else {
-		switch (switch_cfg) {
-		case SWITCH_CFG_1G:
-			phy_addr = REG_RD(bp,
-					  NIG_REG_SERDES0_CTRL_PHY_ADDR +
-					  port * 0x10);
-			*phy = phy_serdes;
-			break;
-		case SWITCH_CFG_10G:
-			phy_addr = REG_RD(bp,
-					  NIG_REG_XGXS0_CTRL_PHY_ADDR +
-					  port * 0x18);
-			*phy = phy_xgxs;
-			break;
-		default:
-			DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
-			return -EINVAL;
-		}
-	}
-	phy->addr = (u8)phy_addr;
-	phy->mdio_ctrl = bnx2x_get_emac_base(bp,
-					    SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH,
-					    port);
-	if (CHIP_IS_E2(bp))
-		phy->def_md_devad = E2_DEFAULT_PHY_DEV_ADDR;
-	else
-		phy->def_md_devad = DEFAULT_PHY_DEV_ADDR;
-
-	DP(NETIF_MSG_LINK, "Internal phy port=%d, addr=0x%x, mdio_ctl=0x%x\n",
-		   port, phy->addr, phy->mdio_ctrl);
-
-	bnx2x_populate_preemphasis(bp, shmem_base, phy, port, INT_PHY);
-	return 0;
-}
-
-static int bnx2x_populate_ext_phy(struct bnx2x *bp,
-				  u8 phy_index,
-				  u32 shmem_base,
-				  u32 shmem2_base,
-				  u8 port,
-				  struct bnx2x_phy *phy)
-{
-	u32 ext_phy_config, phy_type, config2;
-	u32 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH;
-	ext_phy_config = bnx2x_get_ext_phy_config(bp, shmem_base,
-						  phy_index, port);
-	phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
-	/* Select the phy type */
-	switch (phy_type) {
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-		mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED;
-		*phy = phy_8073;
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
-		*phy = phy_8705;
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
-		*phy = phy_8706;
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-		mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
-		*phy = phy_8726;
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
-		/* BCM8727_NOC => BCM8727 no over current */
-		mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
-		*phy = phy_8727;
-		phy->flags |= FLAGS_NOC;
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-		mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
-		*phy = phy_8727;
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
-		*phy = phy_8481;
-		break;
-	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_BCM54618SE:
-		*phy = phy_54618se;
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
-		*phy = phy_7101;
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
-		*phy = phy_null;
-		return -EINVAL;
-	default:
-		*phy = phy_null;
-		return 0;
-	}
-
-	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
-	 */
-	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;
-	} else {
-		u32 size = REG_RD(bp, shmem2_base);
-
-		if (size >
-		    offsetof(struct shmem2_region, ext_phy_fw_version2)) {
-			phy->ver_addr = shmem2_base +
-			    offsetof(struct shmem2_region,
-				     ext_phy_fw_version2[port]);
-		}
-		/* Check specific mdc mdio settings */
-		if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK)
-			mdc_mdio_access = (config2 &
-			SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK) >>
-			(SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT -
-			 SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT);
-	}
-	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.
-	 */
-	if (mdc_mdio_access != SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH)
-		phy->flags |= FLAGS_HW_LOCK_REQUIRED;
-	DP(NETIF_MSG_LINK, "phy_type 0x%x port %d found in index %d\n",
-		   phy_type, port, phy_index);
-	DP(NETIF_MSG_LINK, "             addr=0x%x, mdio_ctl=0x%x\n",
-		   phy->addr, phy->mdio_ctrl);
-	return 0;
-}
-
-static int bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base,
-			      u32 shmem2_base, u8 port, struct bnx2x_phy *phy)
-{
-	int status = 0;
-	phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN;
-	if (phy_index == INT_PHY)
-		return bnx2x_populate_int_phy(bp, shmem_base, port, phy);
-	status = bnx2x_populate_ext_phy(bp, phy_index, shmem_base, shmem2_base,
-					port, phy);
-	return status;
-}
-
-static void bnx2x_phy_def_cfg(struct link_params *params,
-			      struct bnx2x_phy *phy,
-			      u8 phy_index)
-{
-	struct bnx2x *bp = params->bp;
-	u32 link_config;
-	/* 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.
-			port_feature_config[params->port].link_config2));
-		phy->speed_cap_mask = REG_RD(bp, params->shmem_base +
-					     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.
-				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));
-	}
-	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);
-
-	phy->req_duplex = DUPLEX_FULL;
-	switch (link_config  & PORT_FEATURE_LINK_SPEED_MASK) {
-	case PORT_FEATURE_LINK_SPEED_10M_HALF:
-		phy->req_duplex = DUPLEX_HALF;
-	case PORT_FEATURE_LINK_SPEED_10M_FULL:
-		phy->req_line_speed = SPEED_10;
-		break;
-	case PORT_FEATURE_LINK_SPEED_100M_HALF:
-		phy->req_duplex = DUPLEX_HALF;
-	case PORT_FEATURE_LINK_SPEED_100M_FULL:
-		phy->req_line_speed = SPEED_100;
-		break;
-	case PORT_FEATURE_LINK_SPEED_1G:
-		phy->req_line_speed = SPEED_1000;
-		break;
-	case PORT_FEATURE_LINK_SPEED_2_5G:
-		phy->req_line_speed = SPEED_2500;
-		break;
-	case PORT_FEATURE_LINK_SPEED_10G_CX4:
-		phy->req_line_speed = SPEED_10000;
-		break;
-	default:
-		phy->req_line_speed = SPEED_AUTO_NEG;
-		break;
-	}
-
-	switch (link_config  & PORT_FEATURE_FLOW_CONTROL_MASK) {
-	case PORT_FEATURE_FLOW_CONTROL_AUTO:
-		phy->req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO;
-		break;
-	case PORT_FEATURE_FLOW_CONTROL_TX:
-		phy->req_flow_ctrl = BNX2X_FLOW_CTRL_TX;
-		break;
-	case PORT_FEATURE_FLOW_CONTROL_RX:
-		phy->req_flow_ctrl = BNX2X_FLOW_CTRL_RX;
-		break;
-	case PORT_FEATURE_FLOW_CONTROL_BOTH:
-		phy->req_flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
-		break;
-	default:
-		phy->req_flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-		break;
-	}
-}
-
-u32 bnx2x_phy_selection(struct link_params *params)
-{
-	u32 phy_config_swapped, prio_cfg;
-	u32 return_cfg = PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT;
-
-	phy_config_swapped = params->multi_phy_config &
-		PORT_HW_CFG_PHY_SWAPPED_ENABLED;
-
-	prio_cfg = params->multi_phy_config &
-			PORT_HW_CFG_PHY_SELECTION_MASK;
-
-	if (phy_config_swapped) {
-		switch (prio_cfg) {
-		case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
-		     return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY;
-		     break;
-		case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
-		     return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY;
-		     break;
-		case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
-		     return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY;
-		     break;
-		case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
-		     return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY;
-		     break;
-		}
-	} else
-		return_cfg = prio_cfg;
-
-	return return_cfg;
-}
-
-
-int bnx2x_phy_probe(struct link_params *params)
-{
-	u8 phy_index, actual_phy_idx, link_cfg_idx;
-	u32 phy_config_swapped, sync_offset, media_types;
-	struct bnx2x *bp = params->bp;
-	struct bnx2x_phy *phy;
-	params->num_phys = 0;
-	DP(NETIF_MSG_LINK, "Begin phy probe\n");
-	phy_config_swapped = params->multi_phy_config &
-		PORT_HW_CFG_PHY_SWAPPED_ENABLED;
-
-	for (phy_index = INT_PHY; phy_index < MAX_PHYS;
-	      phy_index++) {
-		link_cfg_idx = LINK_CONFIG_IDX(phy_index);
-		actual_phy_idx = phy_index;
-		if (phy_config_swapped) {
-			if (phy_index == EXT_PHY1)
-				actual_phy_idx = EXT_PHY2;
-			else if (phy_index == EXT_PHY2)
-				actual_phy_idx = EXT_PHY1;
-		}
-		DP(NETIF_MSG_LINK, "phy_config_swapped %x, phy_index %x,"
-			       " actual_phy_idx %x\n", phy_config_swapped,
-			   phy_index, actual_phy_idx);
-		phy = &params->phy[actual_phy_idx];
-		if (bnx2x_populate_phy(bp, phy_index, params->shmem_base,
-				       params->shmem2_base, params->port,
-				       phy) != 0) {
-			params->num_phys = 0;
-			DP(NETIF_MSG_LINK, "phy probe failed in phy index %d\n",
-				   phy_index);
-			for (phy_index = INT_PHY;
-			      phy_index < MAX_PHYS;
-			      phy_index++)
-				*phy = phy_null;
-			return -EINVAL;
-		}
-		if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
-			break;
-
-		sync_offset = params->shmem_base +
-			offsetof(struct shmem_region,
-			dev_info.port_hw_config[params->port].media_type);
-		media_types = REG_RD(bp, sync_offset);
-
-		/*
-		 * Update media type for non-PMF sync only for the first time
-		 * In case the media type changes afterwards, it will be updated
-		 * using the update_status function
-		 */
-		if ((media_types & (PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK <<
-				    (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT *
-				     actual_phy_idx))) == 0) {
-			media_types |= ((phy->media_type &
-					PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) <<
-				(PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT *
-				 actual_phy_idx));
-		}
-		REG_WR(bp, sync_offset, media_types);
-
-		bnx2x_phy_def_cfg(params, phy, phy_index);
-		params->num_phys++;
-	}
-
-	DP(NETIF_MSG_LINK, "End phy probe. #phys found %x\n", params->num_phys);
-	return 0;
-}
-
-void bnx2x_init_bmac_loopback(struct link_params *params,
-			      struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-		vars->link_up = 1;
-		vars->line_speed = SPEED_10000;
-		vars->duplex = DUPLEX_FULL;
-		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-		vars->mac_type = MAC_TYPE_BMAC;
-
-		vars->phy_flags = PHY_XGXS_FLAG;
-
-		bnx2x_xgxs_deassert(params);
-
-		/* set bmac loopback */
-		bnx2x_bmac_enable(params, vars, 1);
-
-		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
-}
-
-void bnx2x_init_emac_loopback(struct link_params *params,
-			      struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-		vars->link_up = 1;
-		vars->line_speed = SPEED_1000;
-		vars->duplex = DUPLEX_FULL;
-		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-		vars->mac_type = MAC_TYPE_EMAC;
-
-		vars->phy_flags = PHY_XGXS_FLAG;
-
-		bnx2x_xgxs_deassert(params);
-		/* 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);
-}
-
-void bnx2x_init_xmac_loopback(struct link_params *params,
-			      struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	vars->link_up = 1;
-	if (!params->req_line_speed[0])
-		vars->line_speed = SPEED_10000;
-	else
-		vars->line_speed = params->req_line_speed[0];
-	vars->duplex = DUPLEX_FULL;
-	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-	vars->mac_type = MAC_TYPE_XMAC;
-	vars->phy_flags = PHY_XGXS_FLAG;
-	/*
-	 * Set WC to loopback mode since link is required to provide clock
-	 * to the XMAC in 20G mode
-	 */
-	bnx2x_set_aer_mmd(params, &params->phy[0]);
-	bnx2x_warpcore_reset_lane(bp, &params->phy[0], 0);
-	params->phy[INT_PHY].config_loopback(
-			&params->phy[INT_PHY],
-			params);
-
-	bnx2x_xmac_enable(params, vars, 1);
-	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
-}
-
-void bnx2x_init_umac_loopback(struct link_params *params,
-			      struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	vars->link_up = 1;
-	vars->line_speed = SPEED_1000;
-	vars->duplex = DUPLEX_FULL;
-	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-	vars->mac_type = MAC_TYPE_UMAC;
-	vars->phy_flags = PHY_XGXS_FLAG;
-	bnx2x_umac_enable(params, vars, 1);
-
-	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
-}
-
-void bnx2x_init_xgxs_loopback(struct link_params *params,
-			      struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-		vars->link_up = 1;
-		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-		vars->duplex = DUPLEX_FULL;
-	if (params->req_line_speed[0] == SPEED_1000)
-			vars->line_speed = SPEED_1000;
-	else
-			vars->line_speed = SPEED_10000;
-
-	if (!USES_WARPCORE(bp))
-		bnx2x_xgxs_deassert(params);
-	bnx2x_link_initialize(params, vars);
-
-	if (params->req_line_speed[0] == SPEED_1000) {
-		if (USES_WARPCORE(bp))
-			bnx2x_umac_enable(params, vars, 0);
-		else {
-			bnx2x_emac_program(params, vars);
-			bnx2x_emac_enable(params, vars, 0);
-		}
-	} else {
-		if (USES_WARPCORE(bp))
-			bnx2x_xmac_enable(params, vars, 0);
-		else
-			bnx2x_bmac_enable(params, vars, 0);
-	}
-
-		if (params->loopback_mode == LOOPBACK_XGXS) {
-			/* set 10G XGXS loopback */
-			params->phy[INT_PHY].config_loopback(
-				&params->phy[INT_PHY],
-				params);
-
-		} else {
-			/* set external phy loopback */
-			u8 phy_index;
-			for (phy_index = EXT_PHY1;
-			      phy_index < params->num_phys; phy_index++) {
-				if (params->phy[phy_index].config_loopback)
-					params->phy[phy_index].config_loopback(
-						&params->phy[phy_index],
-						params);
-			}
-		}
-		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
-
-	bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed);
-}
-
-int bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	DP(NETIF_MSG_LINK, "Phy Initialization started\n");
-	DP(NETIF_MSG_LINK, "(1) req_speed %d, req_flowctrl %d\n",
-		   params->req_line_speed[0], params->req_flow_ctrl[0]);
-	DP(NETIF_MSG_LINK, "(2) req_speed %d, req_flowctrl %d\n",
-		   params->req_line_speed[1], params->req_flow_ctrl[1]);
-	vars->link_status = 0;
-	vars->phy_link_up = 0;
-	vars->link_up = 0;
-	vars->line_speed = 0;
-	vars->duplex = DUPLEX_FULL;
-	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-	vars->mac_type = MAC_TYPE_NONE;
-	vars->phy_flags = 0;
-
-	/* disable attentions */
-	bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
-		       (NIG_MASK_XGXS0_LINK_STATUS |
-			NIG_MASK_XGXS0_LINK10G |
-			NIG_MASK_SERDES0_LINK_STATUS |
-			NIG_MASK_MI_INT));
-
-	bnx2x_emac_init(params, vars);
-
-	if (params->num_phys == 0) {
-		DP(NETIF_MSG_LINK, "No phy found for initialization !!\n");
-		return -EINVAL;
-	}
-	set_phy_vars(params, vars);
-
-	DP(NETIF_MSG_LINK, "Num of phys on board: %d\n", params->num_phys);
-	switch (params->loopback_mode) {
-	case LOOPBACK_BMAC:
-		bnx2x_init_bmac_loopback(params, vars);
-		break;
-	case LOOPBACK_EMAC:
-		bnx2x_init_emac_loopback(params, vars);
-		break;
-	case LOOPBACK_XMAC:
-		bnx2x_init_xmac_loopback(params, vars);
-		break;
-	case LOOPBACK_UMAC:
-		bnx2x_init_umac_loopback(params, vars);
-		break;
-	case LOOPBACK_XGXS:
-	case LOOPBACK_EXT_PHY:
-		bnx2x_init_xgxs_loopback(params, vars);
-		break;
-	default:
-		if (!CHIP_IS_E3(bp)) {
-			if (params->switch_cfg == SWITCH_CFG_10G)
-				bnx2x_xgxs_deassert(params);
-			else
-				bnx2x_serdes_deassert(bp, params->port);
-		}
-		bnx2x_link_initialize(params, vars);
-		msleep(30);
-		bnx2x_link_int_enable(params);
-		break;
-	}
-	return 0;
-}
-
-int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
-		     u8 reset_ext_phy)
-{
-	struct bnx2x *bp = params->bp;
-	u8 phy_index, port = params->port, clear_latch_ind = 0;
-	DP(NETIF_MSG_LINK, "Resetting the link of port %d\n", port);
-	/* disable attentions */
-	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));
-
-	/* activate nig drain */
-	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
-
-	/* disable nig egress interface */
-	if (!CHIP_IS_E3(bp)) {
-		REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
-		REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
-	}
-
-	/* Stop BigMac rx */
-	if (!CHIP_IS_E3(bp))
-		bnx2x_bmac_rx_disable(bp, port);
-	else
-		bnx2x_xmac_disable(params);
-	/* disable emac */
-	if (!CHIP_IS_E3(bp))
-		REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
-
-	msleep(10);
-	/* The PHY reset is controlled by GPIO 1
-	 * Hold it as vars low
-	 */
-	 /* clear link led */
-	bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
-
-	if (reset_ext_phy) {
-		bnx2x_set_mdio_clk(bp, params->chip_id, port);
-		for (phy_index = EXT_PHY1; phy_index < params->num_phys;
-		      phy_index++) {
-			if (params->phy[phy_index].link_reset) {
-				bnx2x_set_aer_mmd(params,
-						  &params->phy[phy_index]);
-				params->phy[phy_index].link_reset(
-					&params->phy[phy_index],
-					params);
-			}
-			if (params->phy[phy_index].flags &
-			    FLAGS_REARM_LATCH_SIGNAL)
-				clear_latch_ind = 1;
-		}
-	}
-
-	if (clear_latch_ind) {
-		/* Clear latching indication */
-		bnx2x_rearm_latch_signal(bp, port, 0);
-		bnx2x_bits_dis(bp, NIG_REG_LATCH_BC_0 + port*4,
-			       1 << NIG_LATCH_BC_ENABLE_MI_INT);
-	}
-	if (params->phy[INT_PHY].link_reset)
-		params->phy[INT_PHY].link_reset(
-			&params->phy[INT_PHY], params);
-	/* reset BigMac */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
-
-	/* disable nig ingress interface */
-	if (!CHIP_IS_E3(bp)) {
-		REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0);
-		REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0);
-	}
-	vars->link_up = 0;
-	vars->phy_flags = 0;
-	return 0;
-}
-
-/****************************************************************************/
-/*				Common function				    */
-/****************************************************************************/
-static int bnx2x_8073_common_init_phy(struct bnx2x *bp,
-				      u32 shmem_base_path[],
-				      u32 shmem2_base_path[], u8 phy_index,
-				      u32 chip_id)
-{
-	struct bnx2x_phy phy[PORT_MAX];
-	struct bnx2x_phy *phy_blk[PORT_MAX];
-	u16 val;
-	s8 port = 0;
-	s8 port_of_path = 0;
-	u32 swap_val, swap_override;
-	swap_val = REG_RD(bp,  NIG_REG_PORT_SWAP);
-	swap_override = REG_RD(bp,  NIG_REG_STRAP_OVERRIDE);
-	port ^= (swap_val && swap_override);
-	bnx2x_ext_phy_hw_reset(bp, port);
-	/* PART1 - Reset both phys */
-	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
-		u32 shmem_base, shmem2_base;
-		/* In E2, same phy is using for port0 of the two paths */
-		if (CHIP_IS_E1x(bp)) {
-			shmem_base = shmem_base_path[0];
-			shmem2_base = shmem2_base_path[0];
-			port_of_path = port;
-		} else {
-			shmem_base = shmem_base_path[port];
-			shmem2_base = shmem2_base_path[port];
-			port_of_path = 0;
-		}
-
-		/* Extract the ext phy address for the port */
-		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
-				       port_of_path, &phy[port]) !=
-		    0) {
-			DP(NETIF_MSG_LINK, "populate_phy failed\n");
-			return -EINVAL;
-		}
-		/* 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));
-
-		/* 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);
-
-		/* Reset the phy */
-		bnx2x_cl45_write(bp, &phy[port],
-				 MDIO_PMA_DEVAD,
-				 MDIO_PMA_REG_CTRL,
-				 1<<15);
-	}
-
-	/* Add delay of 150ms after reset */
-	msleep(150);
-
-	if (phy[PORT_0].addr & 0x1) {
-		phy_blk[PORT_0] = &(phy[PORT_1]);
-		phy_blk[PORT_1] = &(phy[PORT_0]);
-	} else {
-		phy_blk[PORT_0] = &(phy[PORT_0]);
-		phy_blk[PORT_1] = &(phy[PORT_1]);
-	}
-
-	/* PART2 - Download firmware to both phys */
-	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
-		if (CHIP_IS_E1x(bp))
-			port_of_path = port;
-		else
-			port_of_path = 0;
-
-		DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
-			   phy_blk[port]->addr);
-		if (bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
-						      port_of_path))
-			return -EINVAL;
-
-		/* 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);
-
-		/* 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));
-	}
-
-	/*
-	 * 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 */
-	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
-		/* 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);
-
-		bnx2x_cl45_write(bp, phy_blk[port],
-				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);
-		bnx2x_cl45_write(bp, phy_blk[port],
-				 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);
-	}
-	return 0;
-}
-static int bnx2x_8726_common_init_phy(struct bnx2x *bp,
-				      u32 shmem_base_path[],
-				      u32 shmem2_base_path[], u8 phy_index,
-				      u32 chip_id)
-{
-	u32 val;
-	s8 port;
-	struct bnx2x_phy phy;
-	/* Use port1 because of the static port-swap */
-	/* Enable the module detection interrupt */
-	val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN);
-	val |= ((1<<MISC_REGISTERS_GPIO_3)|
-		(1<<(MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT)));
-	REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val);
-
-	bnx2x_ext_phy_hw_reset(bp, 0);
-	msleep(5);
-	for (port = 0; port < PORT_MAX; port++) {
-		u32 shmem_base, shmem2_base;
-
-		/* In E2, same phy is using for port0 of the two paths */
-		if (CHIP_IS_E1x(bp)) {
-			shmem_base = shmem_base_path[0];
-			shmem2_base = shmem2_base_path[0];
-		} else {
-			shmem_base = shmem_base_path[port];
-			shmem2_base = shmem2_base_path[port];
-		}
-		/* Extract the ext phy address for the port */
-		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
-				       port, &phy) !=
-		    0) {
-			DP(NETIF_MSG_LINK, "populate phy failed\n");
-			return -EINVAL;
-		}
-
-		/* Reset phy*/
-		bnx2x_cl45_write(bp, &phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x0001);
-
-
-		/* Set fault module detected LED on */
-		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
-			       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 int bnx2x_8727_common_init_phy(struct bnx2x *bp,
-				      u32 shmem_base_path[],
-				      u32 shmem2_base_path[], u8 phy_index,
-				      u32 chip_id)
-{
-	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);
-
-	reset_gpio = MISC_REGISTERS_GPIO_1;
-	port = 1;
-
-	/*
-	 * 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 */
-	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
-		u32 shmem_base, shmem2_base;
-
-		/* In E2, same phy is using for port0 of the two paths */
-		if (CHIP_IS_E1x(bp)) {
-			shmem_base = shmem_base_path[0];
-			shmem2_base = shmem2_base_path[0];
-			port_of_path = port;
-		} else {
-			shmem_base = shmem_base_path[port];
-			shmem2_base = shmem2_base_path[port];
-			port_of_path = 0;
-		}
-
-		/* Extract the ext phy address for the port */
-		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
-				       port_of_path, &phy[port]) !=
-				       0) {
-			DP(NETIF_MSG_LINK, "populate phy failed\n");
-			return -EINVAL;
-		}
-		/* 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));
-
-
-		/* Reset the phy */
-		bnx2x_cl45_write(bp, &phy[port],
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
-	}
-
-	/* Add delay of 150ms after reset */
-	msleep(150);
-	if (phy[PORT_0].addr & 0x1) {
-		phy_blk[PORT_0] = &(phy[PORT_1]);
-		phy_blk[PORT_1] = &(phy[PORT_0]);
-	} else {
-		phy_blk[PORT_0] = &(phy[PORT_0]);
-		phy_blk[PORT_1] = &(phy[PORT_1]);
-	}
-	/* PART2 - Download firmware to both phys */
-	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
-		if (CHIP_IS_E1x(bp))
-			port_of_path = port;
-		else
-			port_of_path = 0;
-		DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
-			   phy_blk[port]->addr);
-		if (bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
-						      port_of_path))
-			return -EINVAL;
-		/* Disable PHY transmitter output */
-		bnx2x_cl45_write(bp, phy_blk[port],
-				 MDIO_PMA_DEVAD,
-				 MDIO_PMA_REG_TX_DISABLE, 1);
-
-	}
-	return 0;
-}
-
-static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
-				     u32 shmem2_base_path[], u8 phy_index,
-				     u32 ext_phy_type, u32 chip_id)
-{
-	int rc = 0;
-
-	switch (ext_phy_type) {
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-		rc = bnx2x_8073_common_init_phy(bp, shmem_base_path,
-						shmem2_base_path,
-						phy_index, chip_id);
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
-		rc = bnx2x_8727_common_init_phy(bp, shmem_base_path,
-						shmem2_base_path,
-						phy_index, chip_id);
-		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
-		 */
-		rc = bnx2x_8726_common_init_phy(bp, shmem_base_path,
-						shmem2_base_path,
-						phy_index, chip_id);
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
-		/*
-		 * GPIO3's are linked, and so both need to be toggled
-		 * to obtain required 2us pulse.
-		 */
-		rc = bnx2x_84833_common_init_phy(bp, shmem_base_path, chip_id);
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
-		rc = -EINVAL;
-		break;
-	default:
-		DP(NETIF_MSG_LINK,
-			   "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;
-}
-
-int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
-			  u32 shmem2_base_path[], u32 chip_id)
-{
-	int rc = 0;
-	u32 phy_ver, val;
-	u8 phy_index = 0;
-	u32 ext_phy_type, ext_phy_config;
-	bnx2x_set_mdio_clk(bp, chip_id, PORT_0);
-	bnx2x_set_mdio_clk(bp, chip_id, PORT_1);
-	DP(NETIF_MSG_LINK, "Begin common phy init\n");
-	if (CHIP_IS_E3(bp)) {
-		/* Enable EPIO */
-		val = REG_RD(bp, MISC_REG_GEN_PURP_HWG);
-		REG_WR(bp, MISC_REG_GEN_PURP_HWG, val | 1);
-	}
-	/* Check if common init was already done */
-	phy_ver = REG_RD(bp, shmem_base_path[0] +
-			 offsetof(struct shmem_region,
-				  port_mb[PORT_0].ext_phy_fw_version));
-	if (phy_ver) {
-		DP(NETIF_MSG_LINK, "Not doing common init; phy ver is 0x%x\n",
-			       phy_ver);
-		return 0;
-	}
-
-	/* Read the ext_phy_type for arbitrary port(0) */
-	for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
-	      phy_index++) {
-		ext_phy_config = bnx2x_get_ext_phy_config(bp,
-							  shmem_base_path[0],
-							  phy_index, 0);
-		ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
-		rc |= bnx2x_ext_phy_common_init(bp, shmem_base_path,
-						shmem2_base_path,
-						phy_index, ext_phy_type,
-						chip_id);
-	}
-	return rc;
-}
-
-static void bnx2x_check_over_curr(struct link_params *params,
-				  struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u32 cfg_pin;
-	u8 port = params->port;
-	u32 pin_val;
-
-	cfg_pin = (REG_RD(bp, params->shmem_base +
-			  offsetof(struct shmem_region,
-			       dev_info.port_hw_config[port].e3_cmn_pin_cfg1)) &
-		   PORT_HW_CFG_E3_OVER_CURRENT_MASK) >>
-		PORT_HW_CFG_E3_OVER_CURRENT_SHIFT;
-
-	/* Ignore check if no external input PIN available */
-	if (bnx2x_get_cfg_pin(bp, cfg_pin, &pin_val) != 0)
-		return;
-
-	if (!pin_val) {
-		if ((vars->phy_flags & PHY_OVER_CURRENT_FLAG) == 0) {
-			netdev_err(bp->dev, "Error:  Power fault on Port %d has"
-					    " been detected and the power to "
-					    "that SFP+ module has been removed"
-					    " to prevent failure of the card."
-					    " Please remove the SFP+ module and"
-					    " restart the system to clear this"
-					    " error.\n",
-			 params->port);
-			vars->phy_flags |= PHY_OVER_CURRENT_FLAG;
-		}
-	} else
-		vars->phy_flags &= ~PHY_OVER_CURRENT_FLAG;
-}
-
-static void bnx2x_analyze_link_error(struct link_params *params,
-				     struct link_vars *vars, u32 lss_status)
-{
-	struct bnx2x *bp = params->bp;
-	/* Compare new value with previous value */
-	u8 led_mode;
-	u32 half_open_conn = (vars->phy_flags & PHY_HALF_OPEN_CONN_FLAG) > 0;
-
-	if ((lss_status ^ half_open_conn) == 0)
-		return;
-
-	/* If values differ */
-	DP(NETIF_MSG_LINK, "Link changed:%x %x->%x\n", vars->link_up,
-		       half_open_conn, lss_status);
-
-	/*
-	 * a. Update shmem->link_status accordingly
-	 * b. Update link_vars->link_up
-	 */
-	if (lss_status) {
-		DP(NETIF_MSG_LINK, "Remote Fault detected !!!\n");
-		vars->link_status &= ~LINK_STATUS_LINK_UP;
-		vars->link_up = 0;
-		vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
-		/*
-		 * Set LED mode to off since the PHY doesn't know about these
-		 * errors
-		 */
-		led_mode = LED_MODE_OFF;
-	} else {
-		DP(NETIF_MSG_LINK, "Remote Fault cleared\n");
-		vars->link_status |= LINK_STATUS_LINK_UP;
-		vars->link_up = 1;
-		vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
-		led_mode = LED_MODE_OPER;
-	}
-	/* Update the LED according to the link state */
-	bnx2x_set_led(params, vars, led_mode, SPEED_10000);
-
-	/* Update link status in the shared memory */
-	bnx2x_update_mng(params, vars->link_status);
-
-	/* C. Trigger General Attention */
-	vars->periodic_flags |= PERIODIC_FLAGS_LINK_EVENT;
-	bnx2x_notify_link_changed(bp);
-}
-
-/******************************************************************************
-* Description:
-*	This function checks for half opened connection change indication.
-*	When such change occurs, it calls the bnx2x_analyze_link_error
-*	to check if Remote Fault is set or cleared. Reception of remote fault
-*	status message in the MAC indicates that the peer's MAC has detected
-*	a fault, for example, due to break in the TX side of fiber.
-*
-******************************************************************************/
-static void bnx2x_check_half_open_conn(struct link_params *params,
-				       struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u32 lss_status = 0;
-	u32 mac_base;
-	/* In case link status is physically up @ 10G do */
-	if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0)
-		return;
-
-	if (CHIP_IS_E3(bp) &&
-	    (REG_RD(bp, MISC_REG_RESET_REG_2) &
-	      (MISC_REGISTERS_RESET_REG_2_XMAC))) {
-		/* Check E3 XMAC */
-		/*
-		 * Note that link speed cannot be queried here, since it may be
-		 * zero while link is down. In case UMAC is active, LSS will
-		 * simply not be set
-		 */
-		mac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
-
-		/* Clear stick bits (Requires rising edge) */
-		REG_WR(bp, mac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, 0);
-		REG_WR(bp, mac_base + XMAC_REG_CLEAR_RX_LSS_STATUS,
-		       XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS |
-		       XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS);
-		if (REG_RD(bp, mac_base + XMAC_REG_RX_LSS_STATUS))
-			lss_status = 1;
-
-		bnx2x_analyze_link_error(params, vars, lss_status);
-	} else if (REG_RD(bp, MISC_REG_RESET_REG_2) &
-		   (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) {
-		/* Check E1X / E2 BMAC */
-		u32 lss_status_reg;
-		u32 wb_data[2];
-		mac_base = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
-			NIG_REG_INGRESS_BMAC0_MEM;
-		/*  Read BIGMAC_REGISTER_RX_LSS_STATUS */
-		if (CHIP_IS_E2(bp))
-			lss_status_reg = BIGMAC2_REGISTER_RX_LSS_STAT;
-		else
-			lss_status_reg = BIGMAC_REGISTER_RX_LSS_STATUS;
-
-		REG_RD_DMAE(bp, mac_base + lss_status_reg, wb_data, 2);
-		lss_status = (wb_data[0] > 0);
-
-		bnx2x_analyze_link_error(params, vars, lss_status);
-	}
-}
-
-void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u16 phy_idx;
-	if (!params) {
-		DP(NETIF_MSG_LINK, "Uninitialized params !\n");
-		return;
-	}
-
-	for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
-		if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) {
-			bnx2x_set_aer_mmd(params, &params->phy[phy_idx]);
-			bnx2x_check_half_open_conn(params, vars);
-			break;
-		}
-	}
-
-	if (CHIP_IS_E3(bp))
-		bnx2x_check_over_curr(params, vars);
-}
-
-u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base)
-{
-	u8 phy_index;
-	struct bnx2x_phy phy;
-	for (phy_index = INT_PHY; phy_index < MAX_PHYS;
-	      phy_index++) {
-		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
-				       0, &phy) != 0) {
-			DP(NETIF_MSG_LINK, "populate phy failed\n");
-			return 0;
-		}
-
-		if (phy.flags & FLAGS_HW_LOCK_REQUIRED)
-			return 1;
-	}
-	return 0;
-}
-
-u8 bnx2x_fan_failure_det_req(struct bnx2x *bp,
-			     u32 shmem_base,
-			     u32 shmem2_base,
-			     u8 port)
-{
-	u8 phy_index, fan_failure_det_req = 0;
-	struct bnx2x_phy phy;
-	for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
-	      phy_index++) {
-		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
-				       port, &phy)
-		    != 0) {
-			DP(NETIF_MSG_LINK, "populate phy failed\n");
-			return 0;
-		}
-		fan_failure_det_req |= (phy.flags &
-					FLAGS_FAN_FAILURE_DET_REQ);
-	}
-	return fan_failure_det_req;
-}
-
-void bnx2x_hw_reset_phy(struct link_params *params)
-{
-	u8 phy_index;
-	struct bnx2x *bp = params->bp;
-	bnx2x_update_mng(params, 0);
-	bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
-		       (NIG_MASK_XGXS0_LINK_STATUS |
-			NIG_MASK_XGXS0_LINK10G |
-			NIG_MASK_SERDES0_LINK_STATUS |
-			NIG_MASK_MI_INT));
-
-	for (phy_index = INT_PHY; phy_index < MAX_PHYS;
-	      phy_index++) {
-		if (params->phy[phy_index].hw_reset) {
-			params->phy[phy_index].hw_reset(
-				&params->phy[phy_index],
-				params);
-			params->phy[phy_index] = phy_null;
-		}
-	}
-}
-
-void bnx2x_init_mod_abs_int(struct bnx2x *bp, struct link_vars *vars,
-			    u32 chip_id, u32 shmem_base, u32 shmem2_base,
-			    u8 port)
-{
-	u8 gpio_num = 0xff, gpio_port = 0xff, phy_index;
-	u32 val;
-	u32 offset, aeu_mask, swap_val, swap_override, sync_offset;
-	if (CHIP_IS_E3(bp)) {
-		if (bnx2x_get_mod_abs_int_cfg(bp, chip_id,
-					      shmem_base,
-					      port,
-					      &gpio_num,
-					      &gpio_port) != 0)
-			return;
-	} else {
-		struct bnx2x_phy phy;
-		for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
-		      phy_index++) {
-			if (bnx2x_populate_phy(bp, phy_index, shmem_base,
-					       shmem2_base, port, &phy)
-			    != 0) {
-				DP(NETIF_MSG_LINK, "populate phy failed\n");
-				return;
-			}
-			if (phy.type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) {
-				gpio_num = MISC_REGISTERS_GPIO_3;
-				gpio_port = port;
-				break;
-			}
-		}
-	}
-
-	if (gpio_num == 0xff)
-		return;
-
-	/* Set GPIO3 to trigger SFP+ module insertion/removal */
-	bnx2x_set_gpio(bp, gpio_num, MISC_REGISTERS_GPIO_INPUT_HI_Z, gpio_port);
-
-	swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
-	swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
-	gpio_port ^= (swap_val && swap_override);
-
-	vars->aeu_int_mask = AEU_INPUTS_ATTN_BITS_GPIO0_FUNCTION_0 <<
-		(gpio_num + (gpio_port << 2));
-
-	sync_offset = shmem_base +
-		offsetof(struct shmem_region,
-			 dev_info.port_hw_config[port].aeu_int_mask);
-	REG_WR(bp, sync_offset, vars->aeu_int_mask);
-
-	DP(NETIF_MSG_LINK, "Setting MOD_ABS (GPIO%d_P%d) AEU to 0x%x\n",
-		       gpio_num, gpio_port, vars->aeu_int_mask);
-
-	if (port == 0)
-		offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0;
-	else
-		offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0;
-
-	/* Open appropriate AEU for interrupts */
-	aeu_mask = REG_RD(bp, offset);
-	aeu_mask |= vars->aeu_int_mask;
-	REG_WR(bp, offset, aeu_mask);
-
-	/* Enable the GPIO to trigger interrupt */
-	val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN);
-	val |= 1 << (gpio_num + (gpio_port << 2));
-	REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_link.h linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_link.h
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_link.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_link.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,493 +0,0 @@
-/* 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
- * under the terms of the GNU General Public License version 2, available
- * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
- *
- * Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a
- * license other than the GPL, without Broadcom's express prior written
- * consent.
- *
- * Written by Yaniv Rosner
- *
- */
-
-#ifndef BNX2X_LINK_H
-#define BNX2X_LINK_H
-
-
-
-/***********************************************************/
-/*                         Defines                         */
-/***********************************************************/
-#define DEFAULT_PHY_DEV_ADDR	3
-#define E2_DEFAULT_PHY_DEV_ADDR	5
-
-
-
-#define BNX2X_FLOW_CTRL_AUTO		PORT_FEATURE_FLOW_CONTROL_AUTO
-#define BNX2X_FLOW_CTRL_TX		PORT_FEATURE_FLOW_CONTROL_TX
-#define BNX2X_FLOW_CTRL_RX		PORT_FEATURE_FLOW_CONTROL_RX
-#define BNX2X_FLOW_CTRL_BOTH		PORT_FEATURE_FLOW_CONTROL_BOTH
-#define BNX2X_FLOW_CTRL_NONE		PORT_FEATURE_FLOW_CONTROL_NONE
-
-#define NET_SERDES_IF_XFI		1
-#define NET_SERDES_IF_SFI		2
-#define NET_SERDES_IF_KR		3
-#define NET_SERDES_IF_DXGXS	4
-
-#define SPEED_AUTO_NEG		0
-#define SPEED_20000		20000
-
-#define SFP_EEPROM_VENDOR_NAME_ADDR		0x14
-#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_REVISION_ADDR		0x38
-#define SFP_EEPROM_REVISION_SIZE		4
-#define SFP_EEPROM_SERIAL_ADDR			0x44
-#define SFP_EEPROM_SERIAL_SIZE			16
-#define SFP_EEPROM_DATE_ADDR			0x54 /* ASCII YYMMDD */
-#define SFP_EEPROM_DATE_SIZE			6
-#define PWR_FLT_ERR_MSG_LEN			250
-
-#define XGXS_EXT_PHY_TYPE(ext_phy_config) \
-		((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK)
-#define XGXS_EXT_PHY_ADDR(ext_phy_config) \
-		(((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> \
-		 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT)
-#define SERDES_EXT_PHY_TYPE(ext_phy_config) \
-		((ext_phy_config) & PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK)
-
-/* Single Media Direct board is the plain 577xx board with CX4/RJ45 jacks */
-#define SINGLE_MEDIA_DIRECT(params)	(params->num_phys == 1)
-/* Single Media board contains single external phy */
-#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_PHY_ADDR_MASK		0x000000FF
-#define FW_PARAM_PHY_TYPE_MASK		0x0000FF00
-#define FW_PARAM_MDIO_CTRL_MASK		0xFFFF0000
-#define FW_PARAM_MDIO_CTRL_OFFSET		16
-#define FW_PARAM_PHY_ADDR(fw_param) (fw_param & \
-					   FW_PARAM_PHY_ADDR_MASK)
-#define FW_PARAM_PHY_TYPE(fw_param) (fw_param & \
-					   FW_PARAM_PHY_TYPE_MASK)
-#define FW_PARAM_MDIO_CTRL(fw_param) ((fw_param & \
-					    FW_PARAM_MDIO_CTRL_MASK) >> \
-					    FW_PARAM_MDIO_CTRL_OFFSET)
-#define FW_PARAM_SET(phy_addr, phy_type, mdio_access) \
-	(phy_addr | phy_type | mdio_access << FW_PARAM_MDIO_CTRL_OFFSET)
-
-
-#define PFC_BRB_FULL_LB_XOFF_THRESHOLD				170
-#define PFC_BRB_FULL_LB_XON_THRESHOLD				250
-
-#define MAXVAL(a, b) (((a) > (b)) ? (a) : (b))
-/***********************************************************/
-/*                         Structs                         */
-/***********************************************************/
-#define INT_PHY		0
-#define EXT_PHY1	1
-#define EXT_PHY2	2
-#define MAX_PHYS	3
-
-/* Same configuration is shared between the XGXS and the first external phy */
-#define LINK_CONFIG_SIZE (MAX_PHYS - 1)
-#define LINK_CONFIG_IDX(_phy_idx) ((_phy_idx == INT_PHY) ? \
-					 0 : (_phy_idx - 1))
-/***********************************************************/
-/*                      bnx2x_phy struct                     */
-/*  Defines the required arguments and function per phy    */
-/***********************************************************/
-struct link_vars;
-struct link_params;
-struct bnx2x_phy;
-
-typedef u8 (*config_init_t)(struct bnx2x_phy *phy, struct link_params *params,
-			    struct link_vars *vars);
-typedef u8 (*read_status_t)(struct bnx2x_phy *phy, struct link_params *params,
-			    struct link_vars *vars);
-typedef void (*link_reset_t)(struct bnx2x_phy *phy,
-			     struct link_params *params);
-typedef void (*config_loopback_t)(struct bnx2x_phy *phy,
-				  struct link_params *params);
-typedef u8 (*format_fw_ver_t)(u32 raw, u8 *str, u16 *len);
-typedef void (*hw_reset_t)(struct bnx2x_phy *phy, struct link_params *params);
-typedef void (*set_link_led_t)(struct bnx2x_phy *phy,
-			       struct link_params *params, u8 mode);
-typedef void (*phy_specific_func_t)(struct bnx2x_phy *phy,
-				    struct link_params *params, u32 action);
-
-struct bnx2x_phy {
-	u32 type;
-
-	/* Loaded during init */
-	u8 addr;
-	u8 def_md_devad;
-	u16 flags;
-	/* Require HW lock */
-#define FLAGS_HW_LOCK_REQUIRED		(1<<0)
-	/* No Over-Current detection */
-#define FLAGS_NOC			(1<<1)
-	/* Fan failure detection required */
-#define FLAGS_FAN_FAILURE_DET_REQ	(1<<2)
-	/* Initialize first the XGXS and only then the phy itself */
-#define FLAGS_INIT_XGXS_FIRST		(1<<3)
-#define FLAGS_WC_DUAL_MODE		(1<<4)
-#define FLAGS_4_PORT_MODE		(1<<5)
-#define FLAGS_REARM_LATCH_SIGNAL	(1<<6)
-#define FLAGS_SFP_NOT_APPROVED		(1<<7)
-#define FLAGS_MDC_MDIO_WA		(1<<8)
-#define FLAGS_DUMMY_READ		(1<<9)
-#define FLAGS_MDC_MDIO_WA_B0		(1<<10)
-#define FLAGS_TX_ERROR_CHECK		(1<<12)
-
-	/* preemphasis values for the rx side */
-	u16 rx_preemphasis[4];
-
-	/* preemphasis values for the tx side */
-	u16 tx_preemphasis[4];
-
-	/* EMAC address for access MDIO */
-	u32 mdio_ctrl;
-
-	u32 supported;
-
-	u32 media_type;
-#define	ETH_PHY_UNSPECIFIED 0x0
-#define	ETH_PHY_SFP_FIBER   0x1
-#define	ETH_PHY_XFP_FIBER   0x2
-#define	ETH_PHY_DA_TWINAX   0x3
-#define	ETH_PHY_BASE_T      0x4
-#define	ETH_PHY_KR          0xf0
-#define	ETH_PHY_CX4         0xf1
-#define	ETH_PHY_NOT_PRESENT 0xff
-
-	/* The address in which version is located*/
-	u32 ver_addr;
-
-	u16 req_flow_ctrl;
-
-	u16 req_line_speed;
-
-	u32 speed_cap_mask;
-
-	u16 req_duplex;
-	u16 rsrv;
-	/* Called per phy/port init, and it configures LASI, speed, autoneg,
-	 duplex, flow control negotiation, etc. */
-	config_init_t config_init;
-
-	/* Called due to interrupt. It determines the link, speed */
-	read_status_t read_status;
-
-	/* Called when driver is unloading. Should reset the phy */
-	link_reset_t link_reset;
-
-	/* Set the loopback configuration for the phy */
-	config_loopback_t config_loopback;
-
-	/* Format the given raw number into str up to len */
-	format_fw_ver_t format_fw_ver;
-
-	/* Reset the phy (both ports) */
-	hw_reset_t hw_reset;
-
-	/* Set link led mode (on/off/oper)*/
-	set_link_led_t set_link_led;
-
-	/* PHY Specific tasks */
-	phy_specific_func_t phy_specific_func;
-#define DISABLE_TX	1
-#define ENABLE_TX	2
-};
-
-/* Inputs parameters to the CLC */
-struct link_params {
-
-	u8 port;
-
-	/* Default / User Configuration */
-	u8 loopback_mode;
-#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_UMAC		6
-#define LOOPBACK_XMAC		7
-
-	/* Device parameters */
-	u8 mac_addr[6];
-
-	u16 req_duplex[LINK_CONFIG_SIZE];
-	u16 req_flow_ctrl[LINK_CONFIG_SIZE];
-
-	u16 req_line_speed[LINK_CONFIG_SIZE]; /* Also determine AutoNeg */
-
-	/* shmem parameters */
-	u32 shmem_base;
-	u32 shmem2_base;
-	u32 speed_cap_mask[LINK_CONFIG_SIZE];
-	u32 switch_cfg;
-#define SWITCH_CFG_1G		PORT_FEATURE_CON_SWITCH_1G_SWITCH
-#define SWITCH_CFG_10G		PORT_FEATURE_CON_SWITCH_10G_SWITCH
-#define SWITCH_CFG_AUTO_DETECT	PORT_FEATURE_CON_SWITCH_AUTO_DETECT
-
-	u32 lane_config;
-
-	/* 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_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY	(1<<3)
-#define FEATURE_CONFIG_AUTOGREEEN_ENABLED			(1<<9)
-#define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED		(1<<10)
-	/* Will be populated during common init */
-	struct bnx2x_phy phy[MAX_PHYS];
-
-	/* Will be populated during common init */
-	u8 num_phys;
-
-	u8 rsrv;
-	u16 hw_led_mode; /* part of the hw_config read from the shmem */
-	u32 multi_phy_config;
-
-	/* Device pointer passed to all callback functions */
-	struct bnx2x *bp;
-	u16 req_fc_auto_adv; /* Should be set to TX / BOTH when
-				req_flow_ctrl is set to AUTO */
-};
-
-/* Output parameters */
-struct link_vars {
-	u8 phy_flags;
-#define PHY_XGXS_FLAG			(1<<0)
-#define PHY_SGMII_FLAG			(1<<1)
-#define PHY_PHYSICAL_LINK_FLAG		(1<<2)
-#define PHY_HALF_OPEN_CONN_FLAG		(1<<3)
-#define PHY_OVER_CURRENT_FLAG		(1<<4)
-
-	u8 mac_type;
-#define MAC_TYPE_NONE		0
-#define MAC_TYPE_EMAC		1
-#define MAC_TYPE_BMAC		2
-#define MAC_TYPE_UMAC		3
-#define MAC_TYPE_XMAC		4
-
-	u8 phy_link_up; /* internal phy link indication */
-	u8 link_up;
-
-	u16 line_speed;
-	u16 duplex;
-
-	u16 flow_ctrl;
-	u16 ieee_fc;
-
-	/* The same definitions as the shmem parameter */
-	u32 link_status;
-	u8 fault_detected;
-	u8 rsrv1;
-	u16 periodic_flags;
-#define PERIODIC_FLAGS_LINK_EVENT	0x0001
-
-	u32 aeu_int_mask;
-};
-
-/***********************************************************/
-/*                         Functions                       */
-/***********************************************************/
-int bnx2x_phy_init(struct link_params *params, struct link_vars *vars);
-
-/* Reset the link. Should be called when driver or interface goes down
-   Before calling phy firmware upgrade, the reset_ext_phy should be set
-   to 0 */
-int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
-		     u8 reset_ext_phy);
-
-/* bnx2x_link_update should be called upon link interrupt */
-int bnx2x_link_update(struct link_params *params, struct link_vars *vars);
-
-/* use the following phy functions to read/write from external_phy
-  In order to use it to read/write internal phy registers, use
-  DEFAULT_PHY_DEV_ADDR as devad, and (_bank + (_addr & 0xf)) as
-  the register */
-int bnx2x_phy_read(struct link_params *params, u8 phy_addr,
-		   u8 devad, u16 reg, u16 *ret_val);
-
-int bnx2x_phy_write(struct link_params *params, u8 phy_addr,
-		    u8 devad, u16 reg, u16 val);
-
-/* Reads the link_status from the shmem,
-   and update the link vars accordingly */
-void bnx2x_link_status_update(struct link_params *input,
-			    struct link_vars *output);
-/* returns string representing the fw_version of the external phy */
-int bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
-				 u8 *version, u16 len);
-
-/* Set/Unset the led
-   Basically, the CLC takes care of the led for the link, but in case one needs
-   to set/unset the led unnaturally, set the "mode" to LED_MODE_OPER to
-   blink the led, and LED_MODE_OFF to set the led off.*/
-int bnx2x_set_led(struct link_params *params,
-		  struct link_vars *vars, u8 mode, u32 speed);
-#define LED_MODE_OFF			0
-#define LED_MODE_ON			1
-#define LED_MODE_OPER			2
-#define LED_MODE_FRONT_PANEL_OFF	3
-
-/* bnx2x_handle_module_detect_int should be called upon module detection
-   interrupt */
-void bnx2x_handle_module_detect_int(struct link_params *params);
-
-/* Get the actual link status. In case it returns 0, link is up,
-	otherwise link is down*/
-int bnx2x_test_link(struct link_params *params, struct link_vars *vars,
-		    u8 is_serdes);
-
-/* One-time initialization for external phy after power up */
-int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
-			  u32 shmem2_base_path[], u32 chip_id);
-
-/* Reset the external PHY using GPIO */
-void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port);
-
-/* 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 */
-int 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 */
-u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base,
-			  u32 shmem2_base);
-
-/* Check swap bit and adjust PHY order */
-u32 bnx2x_phy_selection(struct link_params *params);
-
-/* Probe the phys on board, and populate them in "params" */
-int bnx2x_phy_probe(struct link_params *params);
-
-/* Checks if fan failure detection is required on one of the phys on board */
-u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base,
-			     u32 shmem2_base, u8 port);
-
-
-
-/* DCBX structs */
-
-/* Number of maximum COS per chip */
-#define DCBX_E2E3_MAX_NUM_COS		(2)
-#define DCBX_E3B0_MAX_NUM_COS_PORT0	(6)
-#define DCBX_E3B0_MAX_NUM_COS_PORT1	(3)
-#define DCBX_E3B0_MAX_NUM_COS		( \
-			MAXVAL(DCBX_E3B0_MAX_NUM_COS_PORT0, \
-			    DCBX_E3B0_MAX_NUM_COS_PORT1))
-
-#define DCBX_MAX_NUM_COS			( \
-			MAXVAL(DCBX_E3B0_MAX_NUM_COS, \
-			    DCBX_E2E3_MAX_NUM_COS))
-
-/* PFC port configuration params */
-struct bnx2x_nig_brb_pfc_port_params {
-	/* NIG */
-	u32 pause_enable;
-	u32 llfc_out_en;
-	u32 llfc_enable;
-	u32 pkt_priority_to_cos;
-	u8 num_of_rx_cos_priority_mask;
-	u32 rx_cos_priority_mask[DCBX_MAX_NUM_COS];
-	u32 llfc_high_priority_classes;
-	u32 llfc_low_priority_classes;
-	/* BRB */
-	u32 cos0_pauseable;
-	u32 cos1_pauseable;
-};
-
-
-/* ETS port configuration params */
-struct bnx2x_ets_bw_params {
-	u8 bw;
-};
-
-struct bnx2x_ets_sp_params {
-	/**
-	 * valid values are 0 - 5. 0 is highest strict priority.
-	 * There can't be two COS's with the same pri.
-	 */
-	u8 pri;
-};
-
-enum bnx2x_cos_state {
-	bnx2x_cos_state_strict = 0,
-	bnx2x_cos_state_bw = 1,
-};
-
-struct bnx2x_ets_cos_params {
-	enum bnx2x_cos_state state ;
-	union {
-		struct bnx2x_ets_bw_params bw_params;
-		struct bnx2x_ets_sp_params sp_params;
-	} params;
-};
-
-struct bnx2x_ets_params {
-	u8 num_of_cos; /* Number of valid COS entries*/
-	struct bnx2x_ets_cos_params cos[DCBX_MAX_NUM_COS];
-};
-
-/**
- * Used to update the PFC attributes in EMAC, BMAC, NIG and BRB
- * when link is already up
- */
-int bnx2x_update_pfc(struct link_params *params,
-		      struct link_vars *vars,
-		      struct bnx2x_nig_brb_pfc_port_params *pfc_params);
-
-
-/* Used to configure the ETS to disable */
-int bnx2x_ets_disabled(struct link_params *params,
-		       struct link_vars *vars);
-
-/* 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);
-
-/* Used to configure the ETS to strict */
-int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos);
-
-
-/*  Configure the COS to ETS according to BW and SP settings.*/
-int bnx2x_ets_e3b0_config(const struct link_params *params,
-			 const struct link_vars *vars,
-			 const struct bnx2x_ets_params *ets_params);
-/* Read pfc statistic*/
-void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
-						 u32 pfc_frames_sent[2],
-						 u32 pfc_frames_received[2]);
-void bnx2x_init_mod_abs_int(struct bnx2x *bp, struct link_vars *vars,
-			    u32 chip_id, u32 shmem_base, u32 shmem2_base,
-			    u8 port);
-
-int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
-			       struct link_params *params);
-
-void bnx2x_period_func(struct link_params *params, struct link_vars *vars);
-
-#endif /* BNX2X_LINK_H */
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_main.c linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_main.c
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_main.c	2012-03-19 21:43:04.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_main.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,11562 +0,0 @@
-/* bnx2x_main.c: Broadcom Everest network driver.
- *
- * Copyright (c) 2007-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
- * the Free Software Foundation.
- *
- * Maintained by: Eilon Greenstein <eilong@broadcom.com>
- * Written by: Eliezer Tamir
- * Based on code from Michael Chan's bnx2 driver
- * UDP CSUM errata workaround by Arik Gendelman
- * Slowpath and fastpath rework by Vladislav Zolotarov
- * Statistics and Link management by Yitchak Gertner
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/device.h>  /* for dev_info() */
-#include <linux/timer.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/dma-mapping.h>
-#include <linux/bitops.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-#include <asm/byteorder.h>
-#include <linux/time.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-#include <linux/if_vlan.h>
-#include <net/ip.h>
-#include <net/ipv6.h>
-#include <net/tcp.h>
-#include <net/checksum.h>
-#include <net/ip6_checksum.h>
-#include <linux/workqueue.h>
-#include <linux/crc32.h>
-#include <linux/crc32c.h>
-#include <linux/prefetch.h>
-#include <linux/zlib.h>
-#include <linux/io.h>
-#include <linux/stringify.h>
-#include <linux/vmalloc.h>
-
-#include "bnx2x.h"
-#include "bnx2x_init.h"
-#include "bnx2x_init_ops.h"
-#include "bnx2x_cmn.h"
-#include "bnx2x_dcb.h"
-#include "bnx2x_sp.h"
-#define bnx2x_init_block(bp, start, end) \
-  return (printk(KERN_ERR "%s: Missing Free firmware\n", bp->dev->name),\
-	  -EINVAL)
-
-#include <linux/firmware.h>
-#include "bnx2x_fw_file_hdr.h"
-/* FW files */
-/*(DEBLOBBED)*/
-#define FW_FILE_NAME_E1		"/*(DEBLOBBED)*/"
-#define FW_FILE_NAME_E1H	"/*(DEBLOBBED)*/"
-#define FW_FILE_NAME_E2		"/*(DEBLOBBED)*/"
-
-/* Time in jiffies before concluding the transmitter is hung */
-#define TX_TIMEOUT		(5*HZ)
-
-static char version[] __devinitdata =
-	"Broadcom NetXtreme II 5771x/578xx 10/20-Gigabit Ethernet Driver "
-	DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
-
-MODULE_AUTHOR("Eliezer Tamir");
-MODULE_DESCRIPTION("Broadcom NetXtreme II "
-		   "BCM57710/57711/57711E/"
-		   "57712/57712_MF/57800/57800_MF/57810/57810_MF/"
-		   "57840/57840_MF Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_MODULE_VERSION);
-/*(DEBLOBBED)*/
-
-static int multi_mode = 1;
-module_param(multi_mode, int, 0);
-MODULE_PARM_DESC(multi_mode, " Multi queue mode "
-			     "(0 Disable; 1 Enable (default))");
-
-int num_queues;
-module_param(num_queues, int, 0);
-MODULE_PARM_DESC(num_queues, " Number of queues for multi_mode=1"
-				" (default is as a number of CPUs)");
-
-static int disable_tpa;
-module_param(disable_tpa, int, 0);
-MODULE_PARM_DESC(disable_tpa, " Disable the TPA (LRO) feature");
-
-#define INT_MODE_INTx			1
-#define INT_MODE_MSI			2
-static int int_mode;
-module_param(int_mode, int, 0);
-MODULE_PARM_DESC(int_mode, " Force interrupt mode other than MSI-X "
-				"(1 INT#x; 2 MSI)");
-
-static int dropless_fc;
-module_param(dropless_fc, int, 0);
-MODULE_PARM_DESC(dropless_fc, " Pause on exhausted host ring");
-
-static int poll;
-module_param(poll, int, 0);
-MODULE_PARM_DESC(poll, " Use polling (for debug)");
-
-static int mrrs = -1;
-module_param(mrrs, int, 0);
-MODULE_PARM_DESC(mrrs, " Force Max Read Req Size (0..3) (for debug)");
-
-static int debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, " Default debug msglevel");
-
-
-
-struct workqueue_struct *bnx2x_wq;
-
-enum bnx2x_board_type {
-	BCM57710 = 0,
-	BCM57711,
-	BCM57711E,
-	BCM57712,
-	BCM57712_MF,
-	BCM57800,
-	BCM57800_MF,
-	BCM57810,
-	BCM57810_MF,
-	BCM57840,
-	BCM57840_MF
-};
-
-/* indexed by board_type, above */
-static struct {
-	char *name;
-} board_info[] __devinitdata = {
-	{ "Broadcom NetXtreme II BCM57710 10 Gigabit PCIe [Everest]" },
-	{ "Broadcom NetXtreme II BCM57711 10 Gigabit PCIe" },
-	{ "Broadcom NetXtreme II BCM57711E 10 Gigabit PCIe" },
-	{ "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet" },
-	{ "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet Multi Function" },
-	{ "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet" },
-	{ "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet Multi Function" },
-	{ "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet" },
-	{ "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function" },
-	{ "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet" },
-	{ "Broadcom NetXtreme II BCM57840 10/20 Gigabit "
-						"Ethernet Multi Function"}
-};
-
-#ifndef PCI_DEVICE_ID_NX2_57710
-#define PCI_DEVICE_ID_NX2_57710		CHIP_NUM_57710
-#endif
-#ifndef PCI_DEVICE_ID_NX2_57711
-#define PCI_DEVICE_ID_NX2_57711		CHIP_NUM_57711
-#endif
-#ifndef PCI_DEVICE_ID_NX2_57711E
-#define PCI_DEVICE_ID_NX2_57711E	CHIP_NUM_57711E
-#endif
-#ifndef PCI_DEVICE_ID_NX2_57712
-#define PCI_DEVICE_ID_NX2_57712		CHIP_NUM_57712
-#endif
-#ifndef PCI_DEVICE_ID_NX2_57712_MF
-#define PCI_DEVICE_ID_NX2_57712_MF	CHIP_NUM_57712_MF
-#endif
-#ifndef PCI_DEVICE_ID_NX2_57800
-#define PCI_DEVICE_ID_NX2_57800		CHIP_NUM_57800
-#endif
-#ifndef PCI_DEVICE_ID_NX2_57800_MF
-#define PCI_DEVICE_ID_NX2_57800_MF	CHIP_NUM_57800_MF
-#endif
-#ifndef PCI_DEVICE_ID_NX2_57810
-#define PCI_DEVICE_ID_NX2_57810		CHIP_NUM_57810
-#endif
-#ifndef PCI_DEVICE_ID_NX2_57810_MF
-#define PCI_DEVICE_ID_NX2_57810_MF	CHIP_NUM_57810_MF
-#endif
-#ifndef PCI_DEVICE_ID_NX2_57840
-#define PCI_DEVICE_ID_NX2_57840		CHIP_NUM_57840
-#endif
-#ifndef PCI_DEVICE_ID_NX2_57840_MF
-#define PCI_DEVICE_ID_NX2_57840_MF	CHIP_NUM_57840_MF
-#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 },
-	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711E), BCM57711E },
-	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712), BCM57712 },
-	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712_MF), BCM57712_MF },
-	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57800), BCM57800 },
-	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57800_MF), BCM57800_MF },
-	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57810), BCM57810 },
-	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57810_MF), BCM57810_MF },
-	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840), BCM57840 },
-	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840_MF), BCM57840_MF },
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, bnx2x_pci_tbl);
-
-/****************************************************************************
-* General service functions
-****************************************************************************/
-
-static inline void __storm_memset_dma_mapping(struct bnx2x *bp,
-				       u32 addr, dma_addr_t mapping)
-{
-	REG_WR(bp,  addr, U64_LO(mapping));
-	REG_WR(bp,  addr + 4, U64_HI(mapping));
-}
-
-static inline void storm_memset_spq_addr(struct bnx2x *bp,
-					 dma_addr_t mapping, u16 abs_fid)
-{
-	u32 addr = XSEM_REG_FAST_MEMORY +
-			XSTORM_SPQ_PAGE_BASE_OFFSET(abs_fid);
-
-	__storm_memset_dma_mapping(bp, addr, mapping);
-}
-
-static inline void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid,
-					 u16 pf_id)
-{
-	REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_VF_TO_PF_OFFSET(abs_fid),
-		pf_id);
-	REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_VF_TO_PF_OFFSET(abs_fid),
-		pf_id);
-	REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_VF_TO_PF_OFFSET(abs_fid),
-		pf_id);
-	REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_VF_TO_PF_OFFSET(abs_fid),
-		pf_id);
-}
-
-static inline void storm_memset_func_en(struct bnx2x *bp, u16 abs_fid,
-					u8 enable)
-{
-	REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNC_EN_OFFSET(abs_fid),
-		enable);
-	REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_FUNC_EN_OFFSET(abs_fid),
-		enable);
-	REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_FUNC_EN_OFFSET(abs_fid),
-		enable);
-	REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNC_EN_OFFSET(abs_fid),
-		enable);
-}
-
-static inline void storm_memset_eq_data(struct bnx2x *bp,
-				struct event_ring_data *eq_data,
-				u16 pfid)
-{
-	size_t size = sizeof(struct event_ring_data);
-
-	u32 addr = BAR_CSTRORM_INTMEM + CSTORM_EVENT_RING_DATA_OFFSET(pfid);
-
-	__storm_memset_struct(bp, addr, size, (u32 *)eq_data);
-}
-
-static inline void storm_memset_eq_prod(struct bnx2x *bp, u16 eq_prod,
-					u16 pfid)
-{
-	u32 addr = BAR_CSTRORM_INTMEM + CSTORM_EVENT_RING_PROD_OFFSET(pfid);
-	REG_WR16(bp, addr, eq_prod);
-}
-
-/* used only at init
- * locking is done by mcp
- */
-static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val)
-{
-	pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS, addr);
-	pci_write_config_dword(bp->pdev, PCICFG_GRC_DATA, val);
-	pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS,
-			       PCICFG_VENDOR_ID_OFFSET);
-}
-
-static u32 bnx2x_reg_rd_ind(struct bnx2x *bp, u32 addr)
-{
-	u32 val;
-
-	pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS, addr);
-	pci_read_config_dword(bp->pdev, PCICFG_GRC_DATA, &val);
-	pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS,
-			       PCICFG_VENDOR_ID_OFFSET);
-
-	return val;
-}
-
-#define DMAE_DP_SRC_GRC		"grc src_addr [%08x]"
-#define DMAE_DP_SRC_PCI		"pci src_addr [%x:%08x]"
-#define DMAE_DP_DST_GRC		"grc dst_addr [%08x]"
-#define DMAE_DP_DST_PCI		"pci dst_addr [%x:%08x]"
-#define DMAE_DP_DST_NONE	"dst_addr [none]"
-
-static void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae,
-			  int msglvl)
-{
-	u32 src_type = dmae->opcode & DMAE_COMMAND_SRC;
-
-	switch (dmae->opcode & DMAE_COMMAND_DST) {
-	case DMAE_CMD_DST_PCI:
-		if (src_type == DMAE_CMD_SRC_PCI)
-			DP(msglvl, "DMAE: opcode 0x%08x\n"
-			   "src [%x:%08x], len [%d*4], dst [%x:%08x]\n"
-			   "comp_addr [%x:%08x], comp_val 0x%08x\n",
-			   dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo,
-			   dmae->len, dmae->dst_addr_hi, dmae->dst_addr_lo,
-			   dmae->comp_addr_hi, dmae->comp_addr_lo,
-			   dmae->comp_val);
-		else
-			DP(msglvl, "DMAE: opcode 0x%08x\n"
-			   "src [%08x], len [%d*4], dst [%x:%08x]\n"
-			   "comp_addr [%x:%08x], comp_val 0x%08x\n",
-			   dmae->opcode, dmae->src_addr_lo >> 2,
-			   dmae->len, dmae->dst_addr_hi, dmae->dst_addr_lo,
-			   dmae->comp_addr_hi, dmae->comp_addr_lo,
-			   dmae->comp_val);
-		break;
-	case DMAE_CMD_DST_GRC:
-		if (src_type == DMAE_CMD_SRC_PCI)
-			DP(msglvl, "DMAE: opcode 0x%08x\n"
-			   "src [%x:%08x], len [%d*4], dst_addr [%08x]\n"
-			   "comp_addr [%x:%08x], comp_val 0x%08x\n",
-			   dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo,
-			   dmae->len, dmae->dst_addr_lo >> 2,
-			   dmae->comp_addr_hi, dmae->comp_addr_lo,
-			   dmae->comp_val);
-		else
-			DP(msglvl, "DMAE: opcode 0x%08x\n"
-			   "src [%08x], len [%d*4], dst [%08x]\n"
-			   "comp_addr [%x:%08x], comp_val 0x%08x\n",
-			   dmae->opcode, dmae->src_addr_lo >> 2,
-			   dmae->len, dmae->dst_addr_lo >> 2,
-			   dmae->comp_addr_hi, dmae->comp_addr_lo,
-			   dmae->comp_val);
-		break;
-	default:
-		if (src_type == DMAE_CMD_SRC_PCI)
-			DP(msglvl, "DMAE: opcode 0x%08x\n"
-			   DP_LEVEL "src_addr [%x:%08x]  len [%d * 4]  "
-				    "dst_addr [none]\n"
-			   DP_LEVEL "comp_addr [%x:%08x]  comp_val 0x%08x\n",
-			   dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo,
-			   dmae->len, dmae->comp_addr_hi, dmae->comp_addr_lo,
-			   dmae->comp_val);
-		else
-			DP(msglvl, "DMAE: opcode 0x%08x\n"
-			   DP_LEVEL "src_addr [%08x]  len [%d * 4]  "
-				    "dst_addr [none]\n"
-			   DP_LEVEL "comp_addr [%x:%08x]  comp_val 0x%08x\n",
-			   dmae->opcode, dmae->src_addr_lo >> 2,
-			   dmae->len, dmae->comp_addr_hi, dmae->comp_addr_lo,
-			   dmae->comp_val);
-		break;
-	}
-
-}
-
-/* copy command into DMAE command memory and set DMAE command go */
-void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx)
-{
-	u32 cmd_offset;
-	int i;
-
-	cmd_offset = (DMAE_REG_CMD_MEM + sizeof(struct dmae_command) * idx);
-	for (i = 0; i < (sizeof(struct dmae_command)/4); i++) {
-		REG_WR(bp, cmd_offset + i*4, *(((u32 *)dmae) + i));
-
-		DP(BNX2X_MSG_OFF, "DMAE cmd[%d].%d (0x%08x) : 0x%08x\n",
-		   idx, i, cmd_offset + i*4, *(((u32 *)dmae) + i));
-	}
-	REG_WR(bp, dmae_reg_go_c[idx], 1);
-}
-
-u32 bnx2x_dmae_opcode_add_comp(u32 opcode, u8 comp_type)
-{
-	return opcode | ((comp_type << DMAE_COMMAND_C_DST_SHIFT) |
-			   DMAE_CMD_C_ENABLE);
-}
-
-u32 bnx2x_dmae_opcode_clr_src_reset(u32 opcode)
-{
-	return opcode & ~DMAE_CMD_SRC_RESET;
-}
-
-u32 bnx2x_dmae_opcode(struct bnx2x *bp, u8 src_type, u8 dst_type,
-			     bool with_comp, u8 comp_type)
-{
-	u32 opcode = 0;
-
-	opcode |= ((src_type << DMAE_COMMAND_SRC_SHIFT) |
-		   (dst_type << DMAE_COMMAND_DST_SHIFT));
-
-	opcode |= (DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET);
-
-	opcode |= (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0);
-	opcode |= ((BP_VN(bp) << DMAE_CMD_E1HVN_SHIFT) |
-		   (BP_VN(bp) << DMAE_COMMAND_DST_VN_SHIFT));
-	opcode |= (DMAE_COM_SET_ERR << DMAE_COMMAND_ERR_POLICY_SHIFT);
-
-#ifdef __BIG_ENDIAN
-	opcode |= DMAE_CMD_ENDIANITY_B_DW_SWAP;
-#else
-	opcode |= DMAE_CMD_ENDIANITY_DW_SWAP;
-#endif
-	if (with_comp)
-		opcode = bnx2x_dmae_opcode_add_comp(opcode, comp_type);
-	return opcode;
-}
-
-static void bnx2x_prep_dmae_with_comp(struct bnx2x *bp,
-				      struct dmae_command *dmae,
-				      u8 src_type, u8 dst_type)
-{
-	memset(dmae, 0, sizeof(struct dmae_command));
-
-	/* set the opcode */
-	dmae->opcode = bnx2x_dmae_opcode(bp, src_type, dst_type,
-					 true, DMAE_COMP_PCI);
-
-	/* fill in the completion parameters */
-	dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_comp));
-	dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_comp));
-	dmae->comp_val = DMAE_COMP_VAL;
-}
-
-/* issue a dmae command over the init-channel and wailt for completion */
-static int bnx2x_issue_dmae_with_comp(struct bnx2x *bp,
-				      struct dmae_command *dmae)
-{
-	u32 *wb_comp = bnx2x_sp(bp, wb_comp);
-	int cnt = CHIP_REV_IS_SLOW(bp) ? (400000) : 4000;
-	int rc = 0;
-
-	DP(BNX2X_MSG_OFF, "data before [0x%08x 0x%08x 0x%08x 0x%08x]\n",
-	   bp->slowpath->wb_data[0], bp->slowpath->wb_data[1],
-	   bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
-
-	/*
-	 * Lock the dmae channel. Disable BHs to prevent a dead-lock
-	 * as long as this code is called both from syscall context and
-	 * from ndo_set_rx_mode() flow that may be called from BH.
-	 */
-	spin_lock_bh(&bp->dmae_lock);
-
-	/* reset completion */
-	*wb_comp = 0;
-
-	/* post the command on the channel used for initializations */
-	bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));
-
-	/* wait for completion */
-	udelay(5);
-	while ((*wb_comp & ~DMAE_PCI_ERR_FLAG) != DMAE_COMP_VAL) {
-		DP(BNX2X_MSG_OFF, "wb_comp 0x%08x\n", *wb_comp);
-
-		if (!cnt) {
-			BNX2X_ERR("DMAE timeout!\n");
-			rc = DMAE_TIMEOUT;
-			goto unlock;
-		}
-		cnt--;
-		udelay(50);
-	}
-	if (*wb_comp & DMAE_PCI_ERR_FLAG) {
-		BNX2X_ERR("DMAE PCI error!\n");
-		rc = DMAE_PCI_ERROR;
-	}
-
-	DP(BNX2X_MSG_OFF, "data after [0x%08x 0x%08x 0x%08x 0x%08x]\n",
-	   bp->slowpath->wb_data[0], bp->slowpath->wb_data[1],
-	   bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
-
-unlock:
-	spin_unlock_bh(&bp->dmae_lock);
-	return rc;
-}
-
-void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
-		      u32 len32)
-{
-	struct dmae_command dmae;
-
-	if (!bp->dmae_ready) {
-		u32 *data = bnx2x_sp(bp, wb_data[0]);
-
-		DP(BNX2X_MSG_OFF, "DMAE is not ready (dst_addr %08x  len32 %d)"
-		   "  using indirect\n", dst_addr, len32);
-		bnx2x_init_ind_wr(bp, dst_addr, data, len32);
-		return;
-	}
-
-	/* set opcode and fixed command fields */
-	bnx2x_prep_dmae_with_comp(bp, &dmae, DMAE_SRC_PCI, DMAE_DST_GRC);
-
-	/* fill in addresses and len */
-	dmae.src_addr_lo = U64_LO(dma_addr);
-	dmae.src_addr_hi = U64_HI(dma_addr);
-	dmae.dst_addr_lo = dst_addr >> 2;
-	dmae.dst_addr_hi = 0;
-	dmae.len = len32;
-
-	bnx2x_dp_dmae(bp, &dmae, BNX2X_MSG_OFF);
-
-	/* issue the command and wait for completion */
-	bnx2x_issue_dmae_with_comp(bp, &dmae);
-}
-
-void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32)
-{
-	struct dmae_command dmae;
-
-	if (!bp->dmae_ready) {
-		u32 *data = bnx2x_sp(bp, wb_data[0]);
-		int i;
-
-		DP(BNX2X_MSG_OFF, "DMAE is not ready (src_addr %08x  len32 %d)"
-		   "  using indirect\n", src_addr, len32);
-		for (i = 0; i < len32; i++)
-			data[i] = bnx2x_reg_rd_ind(bp, src_addr + i*4);
-		return;
-	}
-
-	/* set opcode and fixed command fields */
-	bnx2x_prep_dmae_with_comp(bp, &dmae, DMAE_SRC_GRC, DMAE_DST_PCI);
-
-	/* fill in addresses and len */
-	dmae.src_addr_lo = src_addr >> 2;
-	dmae.src_addr_hi = 0;
-	dmae.dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_data));
-	dmae.dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_data));
-	dmae.len = len32;
-
-	bnx2x_dp_dmae(bp, &dmae, BNX2X_MSG_OFF);
-
-	/* issue the command and wait for completion */
-	bnx2x_issue_dmae_with_comp(bp, &dmae);
-}
-
-static void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr,
-				      u32 addr, u32 len)
-{
-	int dmae_wr_max = DMAE_LEN32_WR_MAX(bp);
-	int offset = 0;
-
-	while (len > dmae_wr_max) {
-		bnx2x_write_dmae(bp, phys_addr + offset,
-				 addr + offset, dmae_wr_max);
-		offset += dmae_wr_max * 4;
-		len -= dmae_wr_max;
-	}
-
-	bnx2x_write_dmae(bp, phys_addr + offset, addr + offset, len);
-}
-
-/* used only for slowpath so not inlined */
-static void bnx2x_wb_wr(struct bnx2x *bp, int reg, u32 val_hi, u32 val_lo)
-{
-	u32 wb_write[2];
-
-	wb_write[0] = val_hi;
-	wb_write[1] = val_lo;
-	REG_WR_DMAE(bp, reg, wb_write, 2);
-}
-
-#ifdef USE_WB_RD
-static u64 bnx2x_wb_rd(struct bnx2x *bp, int reg)
-{
-	u32 wb_data[2];
-
-	REG_RD_DMAE(bp, reg, wb_data, 2);
-
-	return HILO_U64(wb_data[0], wb_data[1]);
-}
-#endif
-
-static int bnx2x_mc_assert(struct bnx2x *bp)
-{
-	char last_idx;
-	int i, rc = 0;
-	u32 row0, row1, row2, row3;
-
-	/* XSTORM */
-	last_idx = REG_RD8(bp, BAR_XSTRORM_INTMEM +
-			   XSTORM_ASSERT_LIST_INDEX_OFFSET);
-	if (last_idx)
-		BNX2X_ERR("XSTORM_ASSERT_LIST_INDEX 0x%x\n", last_idx);
-
-	/* print the asserts */
-	for (i = 0; i < STROM_ASSERT_ARRAY_SIZE; i++) {
-
-		row0 = REG_RD(bp, BAR_XSTRORM_INTMEM +
-			      XSTORM_ASSERT_LIST_OFFSET(i));
-		row1 = REG_RD(bp, BAR_XSTRORM_INTMEM +
-			      XSTORM_ASSERT_LIST_OFFSET(i) + 4);
-		row2 = REG_RD(bp, BAR_XSTRORM_INTMEM +
-			      XSTORM_ASSERT_LIST_OFFSET(i) + 8);
-		row3 = REG_RD(bp, BAR_XSTRORM_INTMEM +
-			      XSTORM_ASSERT_LIST_OFFSET(i) + 12);
-
-		if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) {
-			BNX2X_ERR("XSTORM_ASSERT_INDEX 0x%x = 0x%08x"
-				  " 0x%08x 0x%08x 0x%08x\n",
-				  i, row3, row2, row1, row0);
-			rc++;
-		} else {
-			break;
-		}
-	}
-
-	/* TSTORM */
-	last_idx = REG_RD8(bp, BAR_TSTRORM_INTMEM +
-			   TSTORM_ASSERT_LIST_INDEX_OFFSET);
-	if (last_idx)
-		BNX2X_ERR("TSTORM_ASSERT_LIST_INDEX 0x%x\n", last_idx);
-
-	/* print the asserts */
-	for (i = 0; i < STROM_ASSERT_ARRAY_SIZE; i++) {
-
-		row0 = REG_RD(bp, BAR_TSTRORM_INTMEM +
-			      TSTORM_ASSERT_LIST_OFFSET(i));
-		row1 = REG_RD(bp, BAR_TSTRORM_INTMEM +
-			      TSTORM_ASSERT_LIST_OFFSET(i) + 4);
-		row2 = REG_RD(bp, BAR_TSTRORM_INTMEM +
-			      TSTORM_ASSERT_LIST_OFFSET(i) + 8);
-		row3 = REG_RD(bp, BAR_TSTRORM_INTMEM +
-			      TSTORM_ASSERT_LIST_OFFSET(i) + 12);
-
-		if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) {
-			BNX2X_ERR("TSTORM_ASSERT_INDEX 0x%x = 0x%08x"
-				  " 0x%08x 0x%08x 0x%08x\n",
-				  i, row3, row2, row1, row0);
-			rc++;
-		} else {
-			break;
-		}
-	}
-
-	/* CSTORM */
-	last_idx = REG_RD8(bp, BAR_CSTRORM_INTMEM +
-			   CSTORM_ASSERT_LIST_INDEX_OFFSET);
-	if (last_idx)
-		BNX2X_ERR("CSTORM_ASSERT_LIST_INDEX 0x%x\n", last_idx);
-
-	/* print the asserts */
-	for (i = 0; i < STROM_ASSERT_ARRAY_SIZE; i++) {
-
-		row0 = REG_RD(bp, BAR_CSTRORM_INTMEM +
-			      CSTORM_ASSERT_LIST_OFFSET(i));
-		row1 = REG_RD(bp, BAR_CSTRORM_INTMEM +
-			      CSTORM_ASSERT_LIST_OFFSET(i) + 4);
-		row2 = REG_RD(bp, BAR_CSTRORM_INTMEM +
-			      CSTORM_ASSERT_LIST_OFFSET(i) + 8);
-		row3 = REG_RD(bp, BAR_CSTRORM_INTMEM +
-			      CSTORM_ASSERT_LIST_OFFSET(i) + 12);
-
-		if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) {
-			BNX2X_ERR("CSTORM_ASSERT_INDEX 0x%x = 0x%08x"
-				  " 0x%08x 0x%08x 0x%08x\n",
-				  i, row3, row2, row1, row0);
-			rc++;
-		} else {
-			break;
-		}
-	}
-
-	/* USTORM */
-	last_idx = REG_RD8(bp, BAR_USTRORM_INTMEM +
-			   USTORM_ASSERT_LIST_INDEX_OFFSET);
-	if (last_idx)
-		BNX2X_ERR("USTORM_ASSERT_LIST_INDEX 0x%x\n", last_idx);
-
-	/* print the asserts */
-	for (i = 0; i < STROM_ASSERT_ARRAY_SIZE; i++) {
-
-		row0 = REG_RD(bp, BAR_USTRORM_INTMEM +
-			      USTORM_ASSERT_LIST_OFFSET(i));
-		row1 = REG_RD(bp, BAR_USTRORM_INTMEM +
-			      USTORM_ASSERT_LIST_OFFSET(i) + 4);
-		row2 = REG_RD(bp, BAR_USTRORM_INTMEM +
-			      USTORM_ASSERT_LIST_OFFSET(i) + 8);
-		row3 = REG_RD(bp, BAR_USTRORM_INTMEM +
-			      USTORM_ASSERT_LIST_OFFSET(i) + 12);
-
-		if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) {
-			BNX2X_ERR("USTORM_ASSERT_INDEX 0x%x = 0x%08x"
-				  " 0x%08x 0x%08x 0x%08x\n",
-				  i, row3, row2, row1, row0);
-			rc++;
-		} else {
-			break;
-		}
-	}
-
-	return rc;
-}
-
-void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl)
-{
-	u32 addr, val;
-	u32 mark, offset;
-	__be32 data[9];
-	int word;
-	u32 trace_shmem_base;
-	if (BP_NOMCP(bp)) {
-		BNX2X_ERR("NO MCP - can not dump\n");
-		return;
-	}
-	netdev_printk(lvl, bp->dev, "bc %d.%d.%d\n",
-		(bp->common.bc_ver & 0xff0000) >> 16,
-		(bp->common.bc_ver & 0xff00) >> 8,
-		(bp->common.bc_ver & 0xff));
-
-	val = REG_RD(bp, MCP_REG_MCPR_CPU_PROGRAM_COUNTER);
-	if (val == REG_RD(bp, MCP_REG_MCPR_CPU_PROGRAM_COUNTER))
-		printk("%s" "MCP PC at 0x%x\n", lvl, val);
-
-	if (BP_PATH(bp) == 0)
-		trace_shmem_base = bp->common.shmem_base;
-	else
-		trace_shmem_base = SHMEM2_RD(bp, other_shmem_base_addr);
-	addr = trace_shmem_base - 0x0800 + 4;
-	mark = REG_RD(bp, addr);
-	mark = (CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH)
-			+ ((mark + 0x3) & ~0x3) - 0x08000000;
-	printk("%s" "begin fw dump (mark 0x%x)\n", lvl, mark);
-
-	printk("%s", lvl);
-	for (offset = mark; offset <= trace_shmem_base; offset += 0x8*4) {
-		for (word = 0; word < 8; word++)
-			data[word] = htonl(REG_RD(bp, offset + 4*word));
-		data[8] = 0x0;
-		pr_cont("%s", (char *)data);
-	}
-	for (offset = addr + 4; offset <= mark; offset += 0x8*4) {
-		for (word = 0; word < 8; word++)
-			data[word] = htonl(REG_RD(bp, offset + 4*word));
-		data[8] = 0x0;
-		pr_cont("%s", (char *)data);
-	}
-	printk("%s" "end of fw dump\n", lvl);
-}
-
-static inline void bnx2x_fw_dump(struct bnx2x *bp)
-{
-	bnx2x_fw_dump_lvl(bp, KERN_ERR);
-}
-
-void bnx2x_panic_dump(struct bnx2x *bp)
-{
-	int i;
-	u16 j;
-	struct hc_sp_status_block_data sp_sb_data;
-	int func = BP_FUNC(bp);
-#ifdef BNX2X_STOP_ON_ERROR
-	u16 start = 0, end = 0;
-	u8 cos;
-#endif
-
-	bp->stats_state = STATS_STATE_DISABLED;
-	DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n");
-
-	BNX2X_ERR("begin crash dump -----------------\n");
-
-	/* Indices */
-	/* Common */
-	BNX2X_ERR("def_idx(0x%x)  def_att_idx(0x%x)  attn_state(0x%x)"
-		  "  spq_prod_idx(0x%x) next_stats_cnt(0x%x)\n",
-		  bp->def_idx, bp->def_att_idx, bp->attn_state,
-		  bp->spq_prod_idx, bp->stats_counter);
-	BNX2X_ERR("DSB: attn bits(0x%x)  ack(0x%x)  id(0x%x)  idx(0x%x)\n",
-		  bp->def_status_blk->atten_status_block.attn_bits,
-		  bp->def_status_blk->atten_status_block.attn_bits_ack,
-		  bp->def_status_blk->atten_status_block.status_block_id,
-		  bp->def_status_blk->atten_status_block.attn_bits_index);
-	BNX2X_ERR("     def (");
-	for (i = 0; i < HC_SP_SB_MAX_INDICES; i++)
-		pr_cont("0x%x%s",
-		       bp->def_status_blk->sp_sb.index_values[i],
-		       (i == HC_SP_SB_MAX_INDICES - 1) ? ")  " : " ");
-
-	for (i = 0; i < sizeof(struct hc_sp_status_block_data)/sizeof(u32); i++)
-		*((u32 *)&sp_sb_data + i) = REG_RD(bp, BAR_CSTRORM_INTMEM +
-			CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
-			i*sizeof(u32));
-
-	pr_cont("igu_sb_id(0x%x)  igu_seg_id(0x%x) "
-			 "pf_id(0x%x)  vnic_id(0x%x)  "
-			 "vf_id(0x%x)  vf_valid (0x%x) "
-			 "state(0x%x)\n",
-	       sp_sb_data.igu_sb_id,
-	       sp_sb_data.igu_seg_id,
-	       sp_sb_data.p_func.pf_id,
-	       sp_sb_data.p_func.vnic_id,
-	       sp_sb_data.p_func.vf_id,
-	       sp_sb_data.p_func.vf_valid,
-	       sp_sb_data.state);
-
-
-	for_each_eth_queue(bp, i) {
-		struct bnx2x_fastpath *fp = &bp->fp[i];
-		int loop;
-		struct hc_status_block_data_e2 sb_data_e2;
-		struct hc_status_block_data_e1x sb_data_e1x;
-		struct hc_status_block_sm  *hc_sm_p =
-			CHIP_IS_E1x(bp) ?
-			sb_data_e1x.common.state_machine :
-			sb_data_e2.common.state_machine;
-		struct hc_index_data *hc_index_p =
-			CHIP_IS_E1x(bp) ?
-			sb_data_e1x.index_data :
-			sb_data_e2.index_data;
-		u8 data_size, cos;
-		u32 *sb_data_p;
-		struct bnx2x_fp_txdata txdata;
-
-		/* Rx */
-		BNX2X_ERR("fp%d: rx_bd_prod(0x%x)  rx_bd_cons(0x%x)"
-			  "  rx_comp_prod(0x%x)"
-			  "  rx_comp_cons(0x%x)  *rx_cons_sb(0x%x)\n",
-			  i, fp->rx_bd_prod, fp->rx_bd_cons,
-			  fp->rx_comp_prod,
-			  fp->rx_comp_cons, le16_to_cpu(*fp->rx_cons_sb));
-		BNX2X_ERR("     rx_sge_prod(0x%x)  last_max_sge(0x%x)"
-			  "  fp_hc_idx(0x%x)\n",
-			  fp->rx_sge_prod, fp->last_max_sge,
-			  le16_to_cpu(fp->fp_hc_idx));
-
-		/* Tx */
-		for_each_cos_in_tx_queue(fp, cos)
-		{
-			txdata = fp->txdata[cos];
-			BNX2X_ERR("fp%d: tx_pkt_prod(0x%x)  tx_pkt_cons(0x%x)"
-				  "  tx_bd_prod(0x%x)  tx_bd_cons(0x%x)"
-				  "  *tx_cons_sb(0x%x)\n",
-				  i, txdata.tx_pkt_prod,
-				  txdata.tx_pkt_cons, txdata.tx_bd_prod,
-				  txdata.tx_bd_cons,
-				  le16_to_cpu(*txdata.tx_cons_sb));
-		}
-
-		loop = CHIP_IS_E1x(bp) ?
-			HC_SB_MAX_INDICES_E1X : HC_SB_MAX_INDICES_E2;
-
-		/* host sb data */
-
-#ifdef BCM_CNIC
-		if (IS_FCOE_FP(fp))
-			continue;
-#endif
-		BNX2X_ERR("     run indexes (");
-		for (j = 0; j < HC_SB_MAX_SM; j++)
-			pr_cont("0x%x%s",
-			       fp->sb_running_index[j],
-			       (j == HC_SB_MAX_SM - 1) ? ")" : " ");
-
-		BNX2X_ERR("     indexes (");
-		for (j = 0; j < loop; j++)
-			pr_cont("0x%x%s",
-			       fp->sb_index_values[j],
-			       (j == loop - 1) ? ")" : " ");
-		/* fw sb data */
-		data_size = CHIP_IS_E1x(bp) ?
-			sizeof(struct hc_status_block_data_e1x) :
-			sizeof(struct hc_status_block_data_e2);
-		data_size /= sizeof(u32);
-		sb_data_p = CHIP_IS_E1x(bp) ?
-			(u32 *)&sb_data_e1x :
-			(u32 *)&sb_data_e2;
-		/* copy sb data in here */
-		for (j = 0; j < data_size; j++)
-			*(sb_data_p + j) = REG_RD(bp, BAR_CSTRORM_INTMEM +
-				CSTORM_STATUS_BLOCK_DATA_OFFSET(fp->fw_sb_id) +
-				j * sizeof(u32));
-
-		if (!CHIP_IS_E1x(bp)) {
-			pr_cont("pf_id(0x%x)  vf_id(0x%x)  vf_valid(0x%x) "
-				"vnic_id(0x%x)  same_igu_sb_1b(0x%x) "
-				"state(0x%x)\n",
-				sb_data_e2.common.p_func.pf_id,
-				sb_data_e2.common.p_func.vf_id,
-				sb_data_e2.common.p_func.vf_valid,
-				sb_data_e2.common.p_func.vnic_id,
-				sb_data_e2.common.same_igu_sb_1b,
-				sb_data_e2.common.state);
-		} else {
-			pr_cont("pf_id(0x%x)  vf_id(0x%x)  vf_valid(0x%x) "
-				"vnic_id(0x%x)  same_igu_sb_1b(0x%x) "
-				"state(0x%x)\n",
-				sb_data_e1x.common.p_func.pf_id,
-				sb_data_e1x.common.p_func.vf_id,
-				sb_data_e1x.common.p_func.vf_valid,
-				sb_data_e1x.common.p_func.vnic_id,
-				sb_data_e1x.common.same_igu_sb_1b,
-				sb_data_e1x.common.state);
-		}
-
-		/* SB_SMs data */
-		for (j = 0; j < HC_SB_MAX_SM; j++) {
-			pr_cont("SM[%d] __flags (0x%x) "
-			       "igu_sb_id (0x%x)  igu_seg_id(0x%x) "
-			       "time_to_expire (0x%x) "
-			       "timer_value(0x%x)\n", j,
-			       hc_sm_p[j].__flags,
-			       hc_sm_p[j].igu_sb_id,
-			       hc_sm_p[j].igu_seg_id,
-			       hc_sm_p[j].time_to_expire,
-			       hc_sm_p[j].timer_value);
-		}
-
-		/* Indecies data */
-		for (j = 0; j < loop; j++) {
-			pr_cont("INDEX[%d] flags (0x%x) "
-					 "timeout (0x%x)\n", j,
-			       hc_index_p[j].flags,
-			       hc_index_p[j].timeout);
-		}
-	}
-
-#ifdef BNX2X_STOP_ON_ERROR
-	/* Rings */
-	/* Rx */
-	for_each_rx_queue(bp, i) {
-		struct bnx2x_fastpath *fp = &bp->fp[i];
-
-		start = RX_BD(le16_to_cpu(*fp->rx_cons_sb) - 10);
-		end = RX_BD(le16_to_cpu(*fp->rx_cons_sb) + 503);
-		for (j = start; j != end; j = RX_BD(j + 1)) {
-			u32 *rx_bd = (u32 *)&fp->rx_desc_ring[j];
-			struct sw_rx_bd *sw_bd = &fp->rx_buf_ring[j];
-
-			BNX2X_ERR("fp%d: rx_bd[%x]=[%x:%x]  sw_bd=[%p]\n",
-				  i, j, rx_bd[1], rx_bd[0], sw_bd->skb);
-		}
-
-		start = RX_SGE(fp->rx_sge_prod);
-		end = RX_SGE(fp->last_max_sge);
-		for (j = start; j != end; j = RX_SGE(j + 1)) {
-			u32 *rx_sge = (u32 *)&fp->rx_sge_ring[j];
-			struct sw_rx_page *sw_page = &fp->rx_page_ring[j];
-
-			BNX2X_ERR("fp%d: rx_sge[%x]=[%x:%x]  sw_page=[%p]\n",
-				  i, j, rx_sge[1], rx_sge[0], sw_page->page);
-		}
-
-		start = RCQ_BD(fp->rx_comp_cons - 10);
-		end = RCQ_BD(fp->rx_comp_cons + 503);
-		for (j = start; j != end; j = RCQ_BD(j + 1)) {
-			u32 *cqe = (u32 *)&fp->rx_comp_ring[j];
-
-			BNX2X_ERR("fp%d: cqe[%x]=[%x:%x:%x:%x]\n",
-				  i, j, cqe[0], cqe[1], cqe[2], cqe[3]);
-		}
-	}
-
-	/* Tx */
-	for_each_tx_queue(bp, i) {
-		struct bnx2x_fastpath *fp = &bp->fp[i];
-		for_each_cos_in_tx_queue(fp, cos) {
-			struct bnx2x_fp_txdata *txdata = &fp->txdata[cos];
-
-			start = TX_BD(le16_to_cpu(*txdata->tx_cons_sb) - 10);
-			end = TX_BD(le16_to_cpu(*txdata->tx_cons_sb) + 245);
-			for (j = start; j != end; j = TX_BD(j + 1)) {
-				struct sw_tx_bd *sw_bd =
-					&txdata->tx_buf_ring[j];
-
-				BNX2X_ERR("fp%d: txdata %d, "
-					  "packet[%x]=[%p,%x]\n",
-					  i, cos, j, sw_bd->skb,
-					  sw_bd->first_bd);
-			}
-
-			start = TX_BD(txdata->tx_bd_cons - 10);
-			end = TX_BD(txdata->tx_bd_cons + 254);
-			for (j = start; j != end; j = TX_BD(j + 1)) {
-				u32 *tx_bd = (u32 *)&txdata->tx_desc_ring[j];
-
-				BNX2X_ERR("fp%d: txdata %d, tx_bd[%x]="
-					  "[%x:%x:%x:%x]\n",
-					  i, cos, j, tx_bd[0], tx_bd[1],
-					  tx_bd[2], tx_bd[3]);
-			}
-		}
-	}
-#endif
-	bnx2x_fw_dump(bp);
-	bnx2x_mc_assert(bp);
-	BNX2X_ERR("end crash dump -----------------\n");
-}
-
-/*
- * FLR Support for E2
- *
- * bnx2x_pf_flr_clnup() is called during nic_load in the per function HW
- * initialization.
- */
-#define FLR_WAIT_USEC		10000	/* 10 miliseconds */
-#define FLR_WAIT_INTERAVAL	50	/* usec */
-#define	FLR_POLL_CNT		(FLR_WAIT_USEC/FLR_WAIT_INTERAVAL) /* 200 */
-
-struct pbf_pN_buf_regs {
-	int pN;
-	u32 init_crd;
-	u32 crd;
-	u32 crd_freed;
-};
-
-struct pbf_pN_cmd_regs {
-	int pN;
-	u32 lines_occup;
-	u32 lines_freed;
-};
-
-static void bnx2x_pbf_pN_buf_flushed(struct bnx2x *bp,
-				     struct pbf_pN_buf_regs *regs,
-				     u32 poll_count)
-{
-	u32 init_crd, crd, crd_start, crd_freed, crd_freed_start;
-	u32 cur_cnt = poll_count;
-
-	crd_freed = crd_freed_start = REG_RD(bp, regs->crd_freed);
-	crd = crd_start = REG_RD(bp, regs->crd);
-	init_crd = REG_RD(bp, regs->init_crd);
-
-	DP(BNX2X_MSG_SP, "INIT CREDIT[%d] : %x\n", regs->pN, init_crd);
-	DP(BNX2X_MSG_SP, "CREDIT[%d]      : s:%x\n", regs->pN, crd);
-	DP(BNX2X_MSG_SP, "CREDIT_FREED[%d]: s:%x\n", regs->pN, crd_freed);
-
-	while ((crd != init_crd) && ((u32)SUB_S32(crd_freed, crd_freed_start) <
-	       (init_crd - crd_start))) {
-		if (cur_cnt--) {
-			udelay(FLR_WAIT_INTERAVAL);
-			crd = REG_RD(bp, regs->crd);
-			crd_freed = REG_RD(bp, regs->crd_freed);
-		} else {
-			DP(BNX2X_MSG_SP, "PBF tx buffer[%d] timed out\n",
-			   regs->pN);
-			DP(BNX2X_MSG_SP, "CREDIT[%d]      : c:%x\n",
-			   regs->pN, crd);
-			DP(BNX2X_MSG_SP, "CREDIT_FREED[%d]: c:%x\n",
-			   regs->pN, crd_freed);
-			break;
-		}
-	}
-	DP(BNX2X_MSG_SP, "Waited %d*%d usec for PBF tx buffer[%d]\n",
-	   poll_count-cur_cnt, FLR_WAIT_INTERAVAL, regs->pN);
-}
-
-static void bnx2x_pbf_pN_cmd_flushed(struct bnx2x *bp,
-				     struct pbf_pN_cmd_regs *regs,
-				     u32 poll_count)
-{
-	u32 occup, to_free, freed, freed_start;
-	u32 cur_cnt = poll_count;
-
-	occup = to_free = REG_RD(bp, regs->lines_occup);
-	freed = freed_start = REG_RD(bp, regs->lines_freed);
-
-	DP(BNX2X_MSG_SP, "OCCUPANCY[%d]   : s:%x\n", regs->pN, occup);
-	DP(BNX2X_MSG_SP, "LINES_FREED[%d] : s:%x\n", regs->pN, freed);
-
-	while (occup && ((u32)SUB_S32(freed, freed_start) < to_free)) {
-		if (cur_cnt--) {
-			udelay(FLR_WAIT_INTERAVAL);
-			occup = REG_RD(bp, regs->lines_occup);
-			freed = REG_RD(bp, regs->lines_freed);
-		} else {
-			DP(BNX2X_MSG_SP, "PBF cmd queue[%d] timed out\n",
-			   regs->pN);
-			DP(BNX2X_MSG_SP, "OCCUPANCY[%d]   : s:%x\n",
-			   regs->pN, occup);
-			DP(BNX2X_MSG_SP, "LINES_FREED[%d] : s:%x\n",
-			   regs->pN, freed);
-			break;
-		}
-	}
-	DP(BNX2X_MSG_SP, "Waited %d*%d usec for PBF cmd queue[%d]\n",
-	   poll_count-cur_cnt, FLR_WAIT_INTERAVAL, regs->pN);
-}
-
-static inline u32 bnx2x_flr_clnup_reg_poll(struct bnx2x *bp, u32 reg,
-				     u32 expected, u32 poll_count)
-{
-	u32 cur_cnt = poll_count;
-	u32 val;
-
-	while ((val = REG_RD(bp, reg)) != expected && cur_cnt--)
-		udelay(FLR_WAIT_INTERAVAL);
-
-	return val;
-}
-
-static inline int bnx2x_flr_clnup_poll_hw_counter(struct bnx2x *bp, u32 reg,
-						  char *msg, u32 poll_cnt)
-{
-	u32 val = bnx2x_flr_clnup_reg_poll(bp, reg, 0, poll_cnt);
-	if (val != 0) {
-		BNX2X_ERR("%s usage count=%d\n", msg, val);
-		return 1;
-	}
-	return 0;
-}
-
-static u32 bnx2x_flr_clnup_poll_count(struct bnx2x *bp)
-{
-	/* adjust polling timeout */
-	if (CHIP_REV_IS_EMUL(bp))
-		return FLR_POLL_CNT * 2000;
-
-	if (CHIP_REV_IS_FPGA(bp))
-		return FLR_POLL_CNT * 120;
-
-	return FLR_POLL_CNT;
-}
-
-static void bnx2x_tx_hw_flushed(struct bnx2x *bp, u32 poll_count)
-{
-	struct pbf_pN_cmd_regs cmd_regs[] = {
-		{0, (CHIP_IS_E3B0(bp)) ?
-			PBF_REG_TQ_OCCUPANCY_Q0 :
-			PBF_REG_P0_TQ_OCCUPANCY,
-		    (CHIP_IS_E3B0(bp)) ?
-			PBF_REG_TQ_LINES_FREED_CNT_Q0 :
-			PBF_REG_P0_TQ_LINES_FREED_CNT},
-		{1, (CHIP_IS_E3B0(bp)) ?
-			PBF_REG_TQ_OCCUPANCY_Q1 :
-			PBF_REG_P1_TQ_OCCUPANCY,
-		    (CHIP_IS_E3B0(bp)) ?
-			PBF_REG_TQ_LINES_FREED_CNT_Q1 :
-			PBF_REG_P1_TQ_LINES_FREED_CNT},
-		{4, (CHIP_IS_E3B0(bp)) ?
-			PBF_REG_TQ_OCCUPANCY_LB_Q :
-			PBF_REG_P4_TQ_OCCUPANCY,
-		    (CHIP_IS_E3B0(bp)) ?
-			PBF_REG_TQ_LINES_FREED_CNT_LB_Q :
-			PBF_REG_P4_TQ_LINES_FREED_CNT}
-	};
-
-	struct pbf_pN_buf_regs buf_regs[] = {
-		{0, (CHIP_IS_E3B0(bp)) ?
-			PBF_REG_INIT_CRD_Q0 :
-			PBF_REG_P0_INIT_CRD ,
-		    (CHIP_IS_E3B0(bp)) ?
-			PBF_REG_CREDIT_Q0 :
-			PBF_REG_P0_CREDIT,
-		    (CHIP_IS_E3B0(bp)) ?
-			PBF_REG_INTERNAL_CRD_FREED_CNT_Q0 :
-			PBF_REG_P0_INTERNAL_CRD_FREED_CNT},
-		{1, (CHIP_IS_E3B0(bp)) ?
-			PBF_REG_INIT_CRD_Q1 :
-			PBF_REG_P1_INIT_CRD,
-		    (CHIP_IS_E3B0(bp)) ?
-			PBF_REG_CREDIT_Q1 :
-			PBF_REG_P1_CREDIT,
-		    (CHIP_IS_E3B0(bp)) ?
-			PBF_REG_INTERNAL_CRD_FREED_CNT_Q1 :
-			PBF_REG_P1_INTERNAL_CRD_FREED_CNT},
-		{4, (CHIP_IS_E3B0(bp)) ?
-			PBF_REG_INIT_CRD_LB_Q :
-			PBF_REG_P4_INIT_CRD,
-		    (CHIP_IS_E3B0(bp)) ?
-			PBF_REG_CREDIT_LB_Q :
-			PBF_REG_P4_CREDIT,
-		    (CHIP_IS_E3B0(bp)) ?
-			PBF_REG_INTERNAL_CRD_FREED_CNT_LB_Q :
-			PBF_REG_P4_INTERNAL_CRD_FREED_CNT},
-	};
-
-	int i;
-
-	/* Verify the command queues are flushed P0, P1, P4 */
-	for (i = 0; i < ARRAY_SIZE(cmd_regs); i++)
-		bnx2x_pbf_pN_cmd_flushed(bp, &cmd_regs[i], poll_count);
-
-
-	/* Verify the transmission buffers are flushed P0, P1, P4 */
-	for (i = 0; i < ARRAY_SIZE(buf_regs); i++)
-		bnx2x_pbf_pN_buf_flushed(bp, &buf_regs[i], poll_count);
-}
-
-#define OP_GEN_PARAM(param) \
-	(((param) << SDM_OP_GEN_COMP_PARAM_SHIFT) & SDM_OP_GEN_COMP_PARAM)
-
-#define OP_GEN_TYPE(type) \
-	(((type) << SDM_OP_GEN_COMP_TYPE_SHIFT) & SDM_OP_GEN_COMP_TYPE)
-
-#define OP_GEN_AGG_VECT(index) \
-	(((index) << SDM_OP_GEN_AGG_VECT_IDX_SHIFT) & SDM_OP_GEN_AGG_VECT_IDX)
-
-
-static inline int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func,
-					 u32 poll_cnt)
-{
-	struct sdm_op_gen op_gen = {0};
-
-	u32 comp_addr = BAR_CSTRORM_INTMEM +
-			CSTORM_FINAL_CLEANUP_COMPLETE_OFFSET(clnup_func);
-	int ret = 0;
-
-	if (REG_RD(bp, comp_addr)) {
-		BNX2X_ERR("Cleanup complete is not 0\n");
-		return 1;
-	}
-
-	op_gen.command |= OP_GEN_PARAM(XSTORM_AGG_INT_FINAL_CLEANUP_INDEX);
-	op_gen.command |= OP_GEN_TYPE(XSTORM_AGG_INT_FINAL_CLEANUP_COMP_TYPE);
-	op_gen.command |= OP_GEN_AGG_VECT(clnup_func);
-	op_gen.command |= 1 << SDM_OP_GEN_AGG_VECT_IDX_VALID_SHIFT;
-
-	DP(BNX2X_MSG_SP, "FW Final cleanup\n");
-	REG_WR(bp, XSDM_REG_OPERATION_GEN, op_gen.command);
-
-	if (bnx2x_flr_clnup_reg_poll(bp, comp_addr, 1, poll_cnt) != 1) {
-		BNX2X_ERR("FW final cleanup did not succeed\n");
-		ret = 1;
-	}
-	/* Zero completion for nxt FLR */
-	REG_WR(bp, comp_addr, 0);
-
-	return ret;
-}
-
-static inline u8 bnx2x_is_pcie_pending(struct pci_dev *dev)
-{
-	int pos;
-	u16 status;
-
-	pos = pci_pcie_cap(dev);
-	if (!pos)
-		return false;
-
-	pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status);
-	return status & PCI_EXP_DEVSTA_TRPND;
-}
-
-/* PF FLR specific routines
-*/
-static int bnx2x_poll_hw_usage_counters(struct bnx2x *bp, u32 poll_cnt)
-{
-
-	/* wait for CFC PF usage-counter to zero (includes all the VFs) */
-	if (bnx2x_flr_clnup_poll_hw_counter(bp,
-			CFC_REG_NUM_LCIDS_INSIDE_PF,
-			"CFC PF usage counter timed out",
-			poll_cnt))
-		return 1;
-
-
-	/* Wait for DQ PF usage-counter to zero (until DQ cleanup) */
-	if (bnx2x_flr_clnup_poll_hw_counter(bp,
-			DORQ_REG_PF_USAGE_CNT,
-			"DQ PF usage counter timed out",
-			poll_cnt))
-		return 1;
-
-	/* Wait for QM PF usage-counter to zero (until DQ cleanup) */
-	if (bnx2x_flr_clnup_poll_hw_counter(bp,
-			QM_REG_PF_USG_CNT_0 + 4*BP_FUNC(bp),
-			"QM PF usage counter timed out",
-			poll_cnt))
-		return 1;
-
-	/* Wait for Timer PF usage-counters to zero (until DQ cleanup) */
-	if (bnx2x_flr_clnup_poll_hw_counter(bp,
-			TM_REG_LIN0_VNIC_UC + 4*BP_PORT(bp),
-			"Timers VNIC usage counter timed out",
-			poll_cnt))
-		return 1;
-	if (bnx2x_flr_clnup_poll_hw_counter(bp,
-			TM_REG_LIN0_NUM_SCANS + 4*BP_PORT(bp),
-			"Timers NUM_SCANS usage counter timed out",
-			poll_cnt))
-		return 1;
-
-	/* Wait DMAE PF usage counter to zero */
-	if (bnx2x_flr_clnup_poll_hw_counter(bp,
-			dmae_reg_go_c[INIT_DMAE_C(bp)],
-			"DMAE dommand register timed out",
-			poll_cnt))
-		return 1;
-
-	return 0;
-}
-
-static void bnx2x_hw_enable_status(struct bnx2x *bp)
-{
-	u32 val;
-
-	val = REG_RD(bp, CFC_REG_WEAK_ENABLE_PF);
-	DP(BNX2X_MSG_SP, "CFC_REG_WEAK_ENABLE_PF is 0x%x\n", val);
-
-	val = REG_RD(bp, PBF_REG_DISABLE_PF);
-	DP(BNX2X_MSG_SP, "PBF_REG_DISABLE_PF is 0x%x\n", val);
-
-	val = REG_RD(bp, IGU_REG_PCI_PF_MSI_EN);
-	DP(BNX2X_MSG_SP, "IGU_REG_PCI_PF_MSI_EN is 0x%x\n", val);
-
-	val = REG_RD(bp, IGU_REG_PCI_PF_MSIX_EN);
-	DP(BNX2X_MSG_SP, "IGU_REG_PCI_PF_MSIX_EN is 0x%x\n", val);
-
-	val = REG_RD(bp, IGU_REG_PCI_PF_MSIX_FUNC_MASK);
-	DP(BNX2X_MSG_SP, "IGU_REG_PCI_PF_MSIX_FUNC_MASK is 0x%x\n", val);
-
-	val = REG_RD(bp, PGLUE_B_REG_SHADOW_BME_PF_7_0_CLR);
-	DP(BNX2X_MSG_SP, "PGLUE_B_REG_SHADOW_BME_PF_7_0_CLR is 0x%x\n", val);
-
-	val = REG_RD(bp, PGLUE_B_REG_FLR_REQUEST_PF_7_0_CLR);
-	DP(BNX2X_MSG_SP, "PGLUE_B_REG_FLR_REQUEST_PF_7_0_CLR is 0x%x\n", val);
-
-	val = REG_RD(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER);
-	DP(BNX2X_MSG_SP, "PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER is 0x%x\n",
-	   val);
-}
-
-static int bnx2x_pf_flr_clnup(struct bnx2x *bp)
-{
-	u32 poll_cnt = bnx2x_flr_clnup_poll_count(bp);
-
-	DP(BNX2X_MSG_SP, "Cleanup after FLR PF[%d]\n", BP_ABS_FUNC(bp));
-
-	/* Re-enable PF target read access */
-	REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
-
-	/* Poll HW usage counters */
-	if (bnx2x_poll_hw_usage_counters(bp, poll_cnt))
-		return -EBUSY;
-
-	/* Zero the igu 'trailing edge' and 'leading edge' */
-
-	/* Send the FW cleanup command */
-	if (bnx2x_send_final_clnup(bp, (u8)BP_FUNC(bp), poll_cnt))
-		return -EBUSY;
-
-	/* ATC cleanup */
-
-	/* Verify TX hw is flushed */
-	bnx2x_tx_hw_flushed(bp, poll_cnt);
-
-	/* Wait 100ms (not adjusted according to platform) */
-	msleep(100);
-
-	/* Verify no pending pci transactions */
-	if (bnx2x_is_pcie_pending(bp->pdev))
-		BNX2X_ERR("PCIE Transactions still pending\n");
-
-	/* Debug */
-	bnx2x_hw_enable_status(bp);
-
-	/*
-	 * Master enable - Due to WB DMAE writes performed before this
-	 * register is re-initialized as part of the regular function init
-	 */
-	REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1);
-
-	return 0;
-}
-
-static void bnx2x_hc_int_enable(struct bnx2x *bp)
-{
-	int port = BP_PORT(bp);
-	u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
-	u32 val = REG_RD(bp, addr);
-	int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
-	int msi = (bp->flags & USING_MSI_FLAG) ? 1 : 0;
-
-	if (msix) {
-		val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
-			 HC_CONFIG_0_REG_INT_LINE_EN_0);
-		val |= (HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 |
-			HC_CONFIG_0_REG_ATTN_BIT_EN_0);
-	} else if (msi) {
-		val &= ~HC_CONFIG_0_REG_INT_LINE_EN_0;
-		val |= (HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
-			HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 |
-			HC_CONFIG_0_REG_ATTN_BIT_EN_0);
-	} else {
-		val |= (HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
-			HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 |
-			HC_CONFIG_0_REG_INT_LINE_EN_0 |
-			HC_CONFIG_0_REG_ATTN_BIT_EN_0);
-
-		if (!CHIP_IS_E1(bp)) {
-			DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x)\n",
-			   val, port, addr);
-
-			REG_WR(bp, addr, val);
-
-			val &= ~HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0;
-		}
-	}
-
-	if (CHIP_IS_E1(bp))
-		REG_WR(bp, HC_REG_INT_MASK + port*4, 0x1FFFF);
-
-	DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x)  mode %s\n",
-	   val, port, addr, (msix ? "MSI-X" : (msi ? "MSI" : "INTx")));
-
-	REG_WR(bp, addr, val);
-	/*
-	 * Ensure that HC_CONFIG is written before leading/trailing edge config
-	 */
-	mmiowb();
-	barrier();
-
-	if (!CHIP_IS_E1(bp)) {
-		/* init leading/trailing edge */
-		if (IS_MF(bp)) {
-			val = (0xee0f | (1 << (BP_VN(bp) + 4)));
-			if (bp->port.pmf)
-				/* enable nig and gpio3 attention */
-				val |= 0x1100;
-		} else
-			val = 0xffff;
-
-		REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val);
-		REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val);
-	}
-
-	/* Make sure that interrupts are indeed enabled from here on */
-	mmiowb();
-}
-
-static void bnx2x_igu_int_enable(struct bnx2x *bp)
-{
-	u32 val;
-	int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
-	int msi = (bp->flags & USING_MSI_FLAG) ? 1 : 0;
-
-	val = REG_RD(bp, IGU_REG_PF_CONFIGURATION);
-
-	if (msix) {
-		val &= ~(IGU_PF_CONF_INT_LINE_EN |
-			 IGU_PF_CONF_SINGLE_ISR_EN);
-		val |= (IGU_PF_CONF_FUNC_EN |
-			IGU_PF_CONF_MSI_MSIX_EN |
-			IGU_PF_CONF_ATTN_BIT_EN);
-	} else if (msi) {
-		val &= ~IGU_PF_CONF_INT_LINE_EN;
-		val |= (IGU_PF_CONF_FUNC_EN |
-			IGU_PF_CONF_MSI_MSIX_EN |
-			IGU_PF_CONF_ATTN_BIT_EN |
-			IGU_PF_CONF_SINGLE_ISR_EN);
-	} else {
-		val &= ~IGU_PF_CONF_MSI_MSIX_EN;
-		val |= (IGU_PF_CONF_FUNC_EN |
-			IGU_PF_CONF_INT_LINE_EN |
-			IGU_PF_CONF_ATTN_BIT_EN |
-			IGU_PF_CONF_SINGLE_ISR_EN);
-	}
-
-	DP(NETIF_MSG_INTR, "write 0x%x to IGU  mode %s\n",
-	   val, (msix ? "MSI-X" : (msi ? "MSI" : "INTx")));
-
-	REG_WR(bp, IGU_REG_PF_CONFIGURATION, val);
-
-	barrier();
-
-	/* init leading/trailing edge */
-	if (IS_MF(bp)) {
-		val = (0xee0f | (1 << (BP_VN(bp) + 4)));
-		if (bp->port.pmf)
-			/* enable nig and gpio3 attention */
-			val |= 0x1100;
-	} else
-		val = 0xffff;
-
-	REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, val);
-	REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, val);
-
-	/* Make sure that interrupts are indeed enabled from here on */
-	mmiowb();
-}
-
-void bnx2x_int_enable(struct bnx2x *bp)
-{
-	if (bp->common.int_block == INT_BLOCK_HC)
-		bnx2x_hc_int_enable(bp);
-	else
-		bnx2x_igu_int_enable(bp);
-}
-
-static void bnx2x_hc_int_disable(struct bnx2x *bp)
-{
-	int port = BP_PORT(bp);
-	u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
-	u32 val = REG_RD(bp, addr);
-
-	/*
-	 * in E1 we must use only PCI configuration space to disable
-	 * MSI/MSIX capablility
-	 * It's forbitten to disable IGU_PF_CONF_MSI_MSIX_EN in HC block
-	 */
-	if (CHIP_IS_E1(bp)) {
-		/*  Since IGU_PF_CONF_MSI_MSIX_EN still always on
-		 *  Use mask register to prevent from HC sending interrupts
-		 *  after we exit the function
-		 */
-		REG_WR(bp, HC_REG_INT_MASK + port*4, 0);
-
-		val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
-			 HC_CONFIG_0_REG_INT_LINE_EN_0 |
-			 HC_CONFIG_0_REG_ATTN_BIT_EN_0);
-	} else
-		val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
-			 HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 |
-			 HC_CONFIG_0_REG_INT_LINE_EN_0 |
-			 HC_CONFIG_0_REG_ATTN_BIT_EN_0);
-
-	DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x)\n",
-	   val, port, addr);
-
-	/* flush all outstanding writes */
-	mmiowb();
-
-	REG_WR(bp, addr, val);
-	if (REG_RD(bp, addr) != val)
-		BNX2X_ERR("BUG! proper val not read from IGU!\n");
-}
-
-static void bnx2x_igu_int_disable(struct bnx2x *bp)
-{
-	u32 val = REG_RD(bp, IGU_REG_PF_CONFIGURATION);
-
-	val &= ~(IGU_PF_CONF_MSI_MSIX_EN |
-		 IGU_PF_CONF_INT_LINE_EN |
-		 IGU_PF_CONF_ATTN_BIT_EN);
-
-	DP(NETIF_MSG_INTR, "write %x to IGU\n", val);
-
-	/* flush all outstanding writes */
-	mmiowb();
-
-	REG_WR(bp, IGU_REG_PF_CONFIGURATION, val);
-	if (REG_RD(bp, IGU_REG_PF_CONFIGURATION) != val)
-		BNX2X_ERR("BUG! proper val not read from IGU!\n");
-}
-
-void bnx2x_int_disable(struct bnx2x *bp)
-{
-	if (bp->common.int_block == INT_BLOCK_HC)
-		bnx2x_hc_int_disable(bp);
-	else
-		bnx2x_igu_int_disable(bp);
-}
-
-void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
-{
-	int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
-	int i, offset;
-
-	if (disable_hw)
-		/* prevent the HW from sending interrupts */
-		bnx2x_int_disable(bp);
-
-	/* make sure all ISRs are done */
-	if (msix) {
-		synchronize_irq(bp->msix_table[0].vector);
-		offset = 1;
-#ifdef BCM_CNIC
-		offset++;
-#endif
-		for_each_eth_queue(bp, i)
-			synchronize_irq(bp->msix_table[offset++].vector);
-	} else
-		synchronize_irq(bp->pdev->irq);
-
-	/* make sure sp_task is not running */
-	cancel_delayed_work(&bp->sp_task);
-	cancel_delayed_work(&bp->period_task);
-	flush_workqueue(bnx2x_wq);
-}
-
-/* fast path */
-
-/*
- * General service functions
- */
-
-/* Return true if succeeded to acquire the lock */
-static bool bnx2x_trylock_hw_lock(struct bnx2x *bp, u32 resource)
-{
-	u32 lock_status;
-	u32 resource_bit = (1 << resource);
-	int func = BP_FUNC(bp);
-	u32 hw_lock_control_reg;
-
-	DP(NETIF_MSG_HW, "Trying to take a lock on resource %d\n", resource);
-
-	/* Validating that the resource is within range */
-	if (resource > HW_LOCK_MAX_RESOURCE_VALUE) {
-		DP(NETIF_MSG_HW,
-		   "resource(0x%x) > HW_LOCK_MAX_RESOURCE_VALUE(0x%x)\n",
-		   resource, HW_LOCK_MAX_RESOURCE_VALUE);
-		return false;
-	}
-
-	if (func <= 5)
-		hw_lock_control_reg = (MISC_REG_DRIVER_CONTROL_1 + func*8);
-	else
-		hw_lock_control_reg =
-				(MISC_REG_DRIVER_CONTROL_7 + (func - 6)*8);
-
-	/* Try to acquire the lock */
-	REG_WR(bp, hw_lock_control_reg + 4, resource_bit);
-	lock_status = REG_RD(bp, hw_lock_control_reg);
-	if (lock_status & resource_bit)
-		return true;
-
-	DP(NETIF_MSG_HW, "Failed to get a lock on resource %d\n", resource);
-	return false;
-}
-
-/**
- * bnx2x_get_leader_lock_resource - get the recovery leader resource id
- *
- * @bp:	driver handle
- *
- * Returns the recovery leader resource id according to the engine this function
- * belongs to. Currently only only 2 engines is supported.
- */
-static inline int bnx2x_get_leader_lock_resource(struct bnx2x *bp)
-{
-	if (BP_PATH(bp))
-		return HW_LOCK_RESOURCE_RECOVERY_LEADER_1;
-	else
-		return HW_LOCK_RESOURCE_RECOVERY_LEADER_0;
-}
-
-/**
- * bnx2x_trylock_leader_lock- try to aquire a leader lock.
- *
- * @bp: driver handle
- *
- * Tries to aquire a leader lock for cuurent engine.
- */
-static inline bool bnx2x_trylock_leader_lock(struct bnx2x *bp)
-{
-	return bnx2x_trylock_hw_lock(bp, bnx2x_get_leader_lock_resource(bp));
-}
-
-#ifdef BCM_CNIC
-static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid, u8 err);
-#endif
-
-void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe)
-{
-	struct bnx2x *bp = fp->bp;
-	int cid = SW_CID(rr_cqe->ramrod_cqe.conn_and_cmd_data);
-	int command = CQE_CMD(rr_cqe->ramrod_cqe.conn_and_cmd_data);
-	enum bnx2x_queue_cmd drv_cmd = BNX2X_Q_CMD_MAX;
-	struct bnx2x_queue_sp_obj *q_obj = &fp->q_obj;
-
-	DP(BNX2X_MSG_SP,
-	   "fp %d  cid %d  got ramrod #%d  state is %x  type is %d\n",
-	   fp->index, cid, command, bp->state,
-	   rr_cqe->ramrod_cqe.ramrod_type);
-
-	switch (command) {
-	case (RAMROD_CMD_ID_ETH_CLIENT_UPDATE):
-		DP(BNX2X_MSG_SP, "got UPDATE ramrod. CID %d\n", cid);
-		drv_cmd = BNX2X_Q_CMD_UPDATE;
-		break;
-
-	case (RAMROD_CMD_ID_ETH_CLIENT_SETUP):
-		DP(BNX2X_MSG_SP, "got MULTI[%d] setup ramrod\n", cid);
-		drv_cmd = BNX2X_Q_CMD_SETUP;
-		break;
-
-	case (RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP):
-		DP(NETIF_MSG_IFUP, "got MULTI[%d] tx-only setup ramrod\n", cid);
-		drv_cmd = BNX2X_Q_CMD_SETUP_TX_ONLY;
-		break;
-
-	case (RAMROD_CMD_ID_ETH_HALT):
-		DP(BNX2X_MSG_SP, "got MULTI[%d] halt ramrod\n", cid);
-		drv_cmd = BNX2X_Q_CMD_HALT;
-		break;
-
-	case (RAMROD_CMD_ID_ETH_TERMINATE):
-		DP(BNX2X_MSG_SP, "got MULTI[%d] teminate ramrod\n", cid);
-		drv_cmd = BNX2X_Q_CMD_TERMINATE;
-		break;
-
-	case (RAMROD_CMD_ID_ETH_EMPTY):
-		DP(BNX2X_MSG_SP, "got MULTI[%d] empty ramrod\n", cid);
-		drv_cmd = BNX2X_Q_CMD_EMPTY;
-		break;
-
-	default:
-		BNX2X_ERR("unexpected MC reply (%d) on fp[%d]\n",
-			  command, fp->index);
-		return;
-	}
-
-	if ((drv_cmd != BNX2X_Q_CMD_MAX) &&
-	    q_obj->complete_cmd(bp, q_obj, drv_cmd))
-		/* q_obj->complete_cmd() failure means that this was
-		 * an unexpected completion.
-		 *
-		 * In this case we don't want to increase the bp->spq_left
-		 * because apparently we haven't sent this command the first
-		 * place.
-		 */
-#ifdef BNX2X_STOP_ON_ERROR
-		bnx2x_panic();
-#else
-		return;
-#endif
-
-	smp_mb__before_atomic_inc();
-	atomic_inc(&bp->cq_spq_left);
-	/* push the change in bp->spq_left and towards the memory */
-	smp_mb__after_atomic_inc();
-
-	DP(BNX2X_MSG_SP, "bp->cq_spq_left %x\n", atomic_read(&bp->cq_spq_left));
-
-	return;
-}
-
-void bnx2x_update_rx_prod(struct bnx2x *bp, struct bnx2x_fastpath *fp,
-			u16 bd_prod, u16 rx_comp_prod, u16 rx_sge_prod)
-{
-	u32 start = BAR_USTRORM_INTMEM + fp->ustorm_rx_prods_offset;
-
-	bnx2x_update_rx_prod_gen(bp, fp, bd_prod, rx_comp_prod, rx_sge_prod,
-				 start);
-}
-
-irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
-{
-	struct bnx2x *bp = netdev_priv(dev_instance);
-	u16 status = bnx2x_ack_int(bp);
-	u16 mask;
-	int i;
-	u8 cos;
-
-	/* Return here if interrupt is shared and it's not for us */
-	if (unlikely(status == 0)) {
-		DP(NETIF_MSG_INTR, "not our interrupt!\n");
-		return IRQ_NONE;
-	}
-	DP(NETIF_MSG_INTR, "got an interrupt  status 0x%x\n", status);
-
-#ifdef BNX2X_STOP_ON_ERROR
-	if (unlikely(bp->panic))
-		return IRQ_HANDLED;
-#endif
-
-	for_each_eth_queue(bp, i) {
-		struct bnx2x_fastpath *fp = &bp->fp[i];
-
-		mask = 0x2 << (fp->index + CNIC_PRESENT);
-		if (status & mask) {
-			/* Handle Rx or Tx according to SB id */
-			prefetch(fp->rx_cons_sb);
-			for_each_cos_in_tx_queue(fp, cos)
-				prefetch(fp->txdata[cos].tx_cons_sb);
-			prefetch(&fp->sb_running_index[SM_RX_ID]);
-			napi_schedule(&bnx2x_fp(bp, fp->index, napi));
-			status &= ~mask;
-		}
-	}
-
-#ifdef BCM_CNIC
-	mask = 0x2;
-	if (status & (mask | 0x1)) {
-		struct cnic_ops *c_ops = NULL;
-
-		if (likely(bp->state == BNX2X_STATE_OPEN)) {
-			rcu_read_lock();
-			c_ops = rcu_dereference(bp->cnic_ops);
-			if (c_ops)
-				c_ops->cnic_handler(bp->cnic_data, NULL);
-			rcu_read_unlock();
-		}
-
-		status &= ~mask;
-	}
-#endif
-
-	if (unlikely(status & 0x1)) {
-		queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
-
-		status &= ~0x1;
-		if (!status)
-			return IRQ_HANDLED;
-	}
-
-	if (unlikely(status))
-		DP(NETIF_MSG_INTR, "got an unknown interrupt! (status 0x%x)\n",
-		   status);
-
-	return IRQ_HANDLED;
-}
-
-/* Link */
-
-/*
- * General service functions
- */
-
-int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource)
-{
-	u32 lock_status;
-	u32 resource_bit = (1 << resource);
-	int func = BP_FUNC(bp);
-	u32 hw_lock_control_reg;
-	int cnt;
-
-	/* Validating that the resource is within range */
-	if (resource > HW_LOCK_MAX_RESOURCE_VALUE) {
-		DP(NETIF_MSG_HW,
-		   "resource(0x%x) > HW_LOCK_MAX_RESOURCE_VALUE(0x%x)\n",
-		   resource, HW_LOCK_MAX_RESOURCE_VALUE);
-		return -EINVAL;
-	}
-
-	if (func <= 5) {
-		hw_lock_control_reg = (MISC_REG_DRIVER_CONTROL_1 + func*8);
-	} else {
-		hw_lock_control_reg =
-				(MISC_REG_DRIVER_CONTROL_7 + (func - 6)*8);
-	}
-
-	/* Validating that the resource is not already taken */
-	lock_status = REG_RD(bp, hw_lock_control_reg);
-	if (lock_status & resource_bit) {
-		DP(NETIF_MSG_HW, "lock_status 0x%x  resource_bit 0x%x\n",
-		   lock_status, resource_bit);
-		return -EEXIST;
-	}
-
-	/* Try for 5 second every 5ms */
-	for (cnt = 0; cnt < 1000; cnt++) {
-		/* Try to acquire the lock */
-		REG_WR(bp, hw_lock_control_reg + 4, resource_bit);
-		lock_status = REG_RD(bp, hw_lock_control_reg);
-		if (lock_status & resource_bit)
-			return 0;
-
-		msleep(5);
-	}
-	DP(NETIF_MSG_HW, "Timeout\n");
-	return -EAGAIN;
-}
-
-int bnx2x_release_leader_lock(struct bnx2x *bp)
-{
-	return bnx2x_release_hw_lock(bp, bnx2x_get_leader_lock_resource(bp));
-}
-
-int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource)
-{
-	u32 lock_status;
-	u32 resource_bit = (1 << resource);
-	int func = BP_FUNC(bp);
-	u32 hw_lock_control_reg;
-
-	DP(NETIF_MSG_HW, "Releasing a lock on resource %d\n", resource);
-
-	/* Validating that the resource is within range */
-	if (resource > HW_LOCK_MAX_RESOURCE_VALUE) {
-		DP(NETIF_MSG_HW,
-		   "resource(0x%x) > HW_LOCK_MAX_RESOURCE_VALUE(0x%x)\n",
-		   resource, HW_LOCK_MAX_RESOURCE_VALUE);
-		return -EINVAL;
-	}
-
-	if (func <= 5) {
-		hw_lock_control_reg = (MISC_REG_DRIVER_CONTROL_1 + func*8);
-	} else {
-		hw_lock_control_reg =
-				(MISC_REG_DRIVER_CONTROL_7 + (func - 6)*8);
-	}
-
-	/* Validating that the resource is currently taken */
-	lock_status = REG_RD(bp, hw_lock_control_reg);
-	if (!(lock_status & resource_bit)) {
-		DP(NETIF_MSG_HW, "lock_status 0x%x  resource_bit 0x%x\n",
-		   lock_status, resource_bit);
-		return -EFAULT;
-	}
-
-	REG_WR(bp, hw_lock_control_reg, resource_bit);
-	return 0;
-}
-
-
-int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port)
-{
-	/* The GPIO should be swapped if swap register is set and active */
-	int gpio_port = (REG_RD(bp, NIG_REG_PORT_SWAP) &&
-			 REG_RD(bp, NIG_REG_STRAP_OVERRIDE)) ^ port;
-	int gpio_shift = gpio_num +
-			(gpio_port ? MISC_REGISTERS_GPIO_PORT_SHIFT : 0);
-	u32 gpio_mask = (1 << gpio_shift);
-	u32 gpio_reg;
-	int value;
-
-	if (gpio_num > MISC_REGISTERS_GPIO_3) {
-		BNX2X_ERR("Invalid GPIO %d\n", gpio_num);
-		return -EINVAL;
-	}
-
-	/* read GPIO value */
-	gpio_reg = REG_RD(bp, MISC_REG_GPIO);
-
-	/* get the requested pin value */
-	if ((gpio_reg & gpio_mask) == gpio_mask)
-		value = 1;
-	else
-		value = 0;
-
-	DP(NETIF_MSG_LINK, "pin %d  value 0x%x\n", gpio_num, value);
-
-	return value;
-}
-
-int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port)
-{
-	/* The GPIO should be swapped if swap register is set and active */
-	int gpio_port = (REG_RD(bp, NIG_REG_PORT_SWAP) &&
-			 REG_RD(bp, NIG_REG_STRAP_OVERRIDE)) ^ port;
-	int gpio_shift = gpio_num +
-			(gpio_port ? MISC_REGISTERS_GPIO_PORT_SHIFT : 0);
-	u32 gpio_mask = (1 << gpio_shift);
-	u32 gpio_reg;
-
-	if (gpio_num > MISC_REGISTERS_GPIO_3) {
-		BNX2X_ERR("Invalid GPIO %d\n", gpio_num);
-		return -EINVAL;
-	}
-
-	bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
-	/* read GPIO and mask except the float bits */
-	gpio_reg = (REG_RD(bp, MISC_REG_GPIO) & MISC_REGISTERS_GPIO_FLOAT);
-
-	switch (mode) {
-	case MISC_REGISTERS_GPIO_OUTPUT_LOW:
-		DP(NETIF_MSG_LINK, "Set GPIO %d (shift %d) -> output low\n",
-		   gpio_num, gpio_shift);
-		/* clear FLOAT and set CLR */
-		gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS);
-		gpio_reg |=  (gpio_mask << MISC_REGISTERS_GPIO_CLR_POS);
-		break;
-
-	case MISC_REGISTERS_GPIO_OUTPUT_HIGH:
-		DP(NETIF_MSG_LINK, "Set GPIO %d (shift %d) -> output high\n",
-		   gpio_num, gpio_shift);
-		/* clear FLOAT and set SET */
-		gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS);
-		gpio_reg |=  (gpio_mask << MISC_REGISTERS_GPIO_SET_POS);
-		break;
-
-	case MISC_REGISTERS_GPIO_INPUT_HI_Z:
-		DP(NETIF_MSG_LINK, "Set GPIO %d (shift %d) -> input\n",
-		   gpio_num, gpio_shift);
-		/* set FLOAT */
-		gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS);
-		break;
-
-	default:
-		break;
-	}
-
-	REG_WR(bp, MISC_REG_GPIO, gpio_reg);
-	bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
-
-	return 0;
-}
-
-int bnx2x_set_mult_gpio(struct bnx2x *bp, u8 pins, u32 mode)
-{
-	u32 gpio_reg = 0;
-	int rc = 0;
-
-	/* Any port swapping should be handled by caller. */
-
-	bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
-	/* read GPIO and mask except the float bits */
-	gpio_reg = REG_RD(bp, MISC_REG_GPIO);
-	gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_FLOAT_POS);
-	gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_CLR_POS);
-	gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_SET_POS);
-
-	switch (mode) {
-	case MISC_REGISTERS_GPIO_OUTPUT_LOW:
-		DP(NETIF_MSG_LINK, "Set GPIO 0x%x -> output low\n", pins);
-		/* set CLR */
-		gpio_reg |= (pins << MISC_REGISTERS_GPIO_CLR_POS);
-		break;
-
-	case MISC_REGISTERS_GPIO_OUTPUT_HIGH:
-		DP(NETIF_MSG_LINK, "Set GPIO 0x%x -> output high\n", pins);
-		/* set SET */
-		gpio_reg |= (pins << MISC_REGISTERS_GPIO_SET_POS);
-		break;
-
-	case MISC_REGISTERS_GPIO_INPUT_HI_Z:
-		DP(NETIF_MSG_LINK, "Set GPIO 0x%x -> input\n", pins);
-		/* set FLOAT */
-		gpio_reg |= (pins << MISC_REGISTERS_GPIO_FLOAT_POS);
-		break;
-
-	default:
-		BNX2X_ERR("Invalid GPIO mode assignment %d\n", mode);
-		rc = -EINVAL;
-		break;
-	}
-
-	if (rc == 0)
-		REG_WR(bp, MISC_REG_GPIO, gpio_reg);
-
-	bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
-
-	return rc;
-}
-
-int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port)
-{
-	/* The GPIO should be swapped if swap register is set and active */
-	int gpio_port = (REG_RD(bp, NIG_REG_PORT_SWAP) &&
-			 REG_RD(bp, NIG_REG_STRAP_OVERRIDE)) ^ port;
-	int gpio_shift = gpio_num +
-			(gpio_port ? MISC_REGISTERS_GPIO_PORT_SHIFT : 0);
-	u32 gpio_mask = (1 << gpio_shift);
-	u32 gpio_reg;
-
-	if (gpio_num > MISC_REGISTERS_GPIO_3) {
-		BNX2X_ERR("Invalid GPIO %d\n", gpio_num);
-		return -EINVAL;
-	}
-
-	bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
-	/* read GPIO int */
-	gpio_reg = REG_RD(bp, MISC_REG_GPIO_INT);
-
-	switch (mode) {
-	case MISC_REGISTERS_GPIO_INT_OUTPUT_CLR:
-		DP(NETIF_MSG_LINK, "Clear GPIO INT %d (shift %d) -> "
-				   "output low\n", gpio_num, gpio_shift);
-		/* clear SET and set CLR */
-		gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_INT_SET_POS);
-		gpio_reg |=  (gpio_mask << MISC_REGISTERS_GPIO_INT_CLR_POS);
-		break;
-
-	case MISC_REGISTERS_GPIO_INT_OUTPUT_SET:
-		DP(NETIF_MSG_LINK, "Set GPIO INT %d (shift %d) -> "
-				   "output high\n", gpio_num, gpio_shift);
-		/* clear CLR and set SET */
-		gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_INT_CLR_POS);
-		gpio_reg |=  (gpio_mask << MISC_REGISTERS_GPIO_INT_SET_POS);
-		break;
-
-	default:
-		break;
-	}
-
-	REG_WR(bp, MISC_REG_GPIO_INT, gpio_reg);
-	bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
-
-	return 0;
-}
-
-static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode)
-{
-	u32 spio_mask = (1 << spio_num);
-	u32 spio_reg;
-
-	if ((spio_num < MISC_REGISTERS_SPIO_4) ||
-	    (spio_num > MISC_REGISTERS_SPIO_7)) {
-		BNX2X_ERR("Invalid SPIO %d\n", spio_num);
-		return -EINVAL;
-	}
-
-	bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_SPIO);
-	/* read SPIO and mask except the float bits */
-	spio_reg = (REG_RD(bp, MISC_REG_SPIO) & MISC_REGISTERS_SPIO_FLOAT);
-
-	switch (mode) {
-	case MISC_REGISTERS_SPIO_OUTPUT_LOW:
-		DP(NETIF_MSG_LINK, "Set SPIO %d -> output low\n", spio_num);
-		/* clear FLOAT and set CLR */
-		spio_reg &= ~(spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS);
-		spio_reg |=  (spio_mask << MISC_REGISTERS_SPIO_CLR_POS);
-		break;
-
-	case MISC_REGISTERS_SPIO_OUTPUT_HIGH:
-		DP(NETIF_MSG_LINK, "Set SPIO %d -> output high\n", spio_num);
-		/* clear FLOAT and set SET */
-		spio_reg &= ~(spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS);
-		spio_reg |=  (spio_mask << MISC_REGISTERS_SPIO_SET_POS);
-		break;
-
-	case MISC_REGISTERS_SPIO_INPUT_HI_Z:
-		DP(NETIF_MSG_LINK, "Set SPIO %d -> input\n", spio_num);
-		/* set FLOAT */
-		spio_reg |= (spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS);
-		break;
-
-	default:
-		break;
-	}
-
-	REG_WR(bp, MISC_REG_SPIO, spio_reg);
-	bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_SPIO);
-
-	return 0;
-}
-
-void bnx2x_calc_fc_adv(struct bnx2x *bp)
-{
-	u8 cfg_idx = bnx2x_get_link_cfg_idx(bp);
-	switch (bp->link_vars.ieee_fc &
-		MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) {
-	case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE:
-		bp->port.advertising[cfg_idx] &= ~(ADVERTISED_Asym_Pause |
-						   ADVERTISED_Pause);
-		break;
-
-	case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH:
-		bp->port.advertising[cfg_idx] |= (ADVERTISED_Asym_Pause |
-						  ADVERTISED_Pause);
-		break;
-
-	case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC:
-		bp->port.advertising[cfg_idx] |= ADVERTISED_Asym_Pause;
-		break;
-
-	default:
-		bp->port.advertising[cfg_idx] &= ~(ADVERTISED_Asym_Pause |
-						   ADVERTISED_Pause);
-		break;
-	}
-}
-
-u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
-{
-	if (!BP_NOMCP(bp)) {
-		u8 rc;
-		int cfx_idx = bnx2x_get_link_cfg_idx(bp);
-		u16 req_line_speed = bp->link_params.req_line_speed[cfx_idx];
-		/*
-		 * Initialize link parameters structure variables
-		 * It is recommended to turn off RX FC for jumbo frames
-		 * for better performance
-		 */
-		if (CHIP_IS_E1x(bp) && (bp->dev->mtu > 5000))
-			bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_TX;
-		else
-			bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
-
-		bnx2x_acquire_phy_lock(bp);
-
-		if (load_mode == LOAD_DIAG) {
-			struct link_params *lp = &bp->link_params;
-			lp->loopback_mode = LOOPBACK_XGXS;
-			/* do PHY loopback at 10G speed, if possible */
-			if (lp->req_line_speed[cfx_idx] < SPEED_10000) {
-				if (lp->speed_cap_mask[cfx_idx] &
-				    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
-					lp->req_line_speed[cfx_idx] =
-					SPEED_10000;
-				else
-					lp->req_line_speed[cfx_idx] =
-					SPEED_1000;
-			}
-		}
-
-		rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars);
-
-		bnx2x_release_phy_lock(bp);
-
-		bnx2x_calc_fc_adv(bp);
-
-		if (CHIP_REV_IS_SLOW(bp) && bp->link_vars.link_up) {
-			bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
-			bnx2x_link_report(bp);
-		} else
-			queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
-		bp->link_params.req_line_speed[cfx_idx] = req_line_speed;
-		return rc;
-	}
-	BNX2X_ERR("Bootcode is missing - can not initialize link\n");
-	return -EINVAL;
-}
-
-void bnx2x_link_set(struct bnx2x *bp)
-{
-	if (!BP_NOMCP(bp)) {
-		bnx2x_acquire_phy_lock(bp);
-		bnx2x_link_reset(&bp->link_params, &bp->link_vars, 1);
-		bnx2x_phy_init(&bp->link_params, &bp->link_vars);
-		bnx2x_release_phy_lock(bp);
-
-		bnx2x_calc_fc_adv(bp);
-	} else
-		BNX2X_ERR("Bootcode is missing - can not set link\n");
-}
-
-static void bnx2x__link_reset(struct bnx2x *bp)
-{
-	if (!BP_NOMCP(bp)) {
-		bnx2x_acquire_phy_lock(bp);
-		bnx2x_link_reset(&bp->link_params, &bp->link_vars, 1);
-		bnx2x_release_phy_lock(bp);
-	} else
-		BNX2X_ERR("Bootcode is missing - can not reset link\n");
-}
-
-u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes)
-{
-	u8 rc = 0;
-
-	if (!BP_NOMCP(bp)) {
-		bnx2x_acquire_phy_lock(bp);
-		rc = bnx2x_test_link(&bp->link_params, &bp->link_vars,
-				     is_serdes);
-		bnx2x_release_phy_lock(bp);
-	} else
-		BNX2X_ERR("Bootcode is missing - can not test link\n");
-
-	return rc;
-}
-
-static void bnx2x_init_port_minmax(struct bnx2x *bp)
-{
-	u32 r_param = bp->link_vars.line_speed / 8;
-	u32 fair_periodic_timeout_usec;
-	u32 t_fair;
-
-	memset(&(bp->cmng.rs_vars), 0,
-	       sizeof(struct rate_shaping_vars_per_port));
-	memset(&(bp->cmng.fair_vars), 0, sizeof(struct fairness_vars_per_port));
-
-	/* 100 usec in SDM ticks = 25 since each tick is 4 usec */
-	bp->cmng.rs_vars.rs_periodic_timeout = RS_PERIODIC_TIMEOUT_USEC / 4;
-
-	/* this is the threshold below which no timer arming will occur
-	   1.25 coefficient is for the threshold to be a little bigger
-	   than the real time, to compensate for timer in-accuracy */
-	bp->cmng.rs_vars.rs_threshold =
-				(RS_PERIODIC_TIMEOUT_USEC * r_param * 5) / 4;
-
-	/* resolution of fairness timer */
-	fair_periodic_timeout_usec = QM_ARB_BYTES / r_param;
-	/* for 10G it is 1000usec. for 1G it is 10000usec. */
-	t_fair = T_FAIR_COEF / bp->link_vars.line_speed;
-
-	/* this is the threshold below which we won't arm the timer anymore */
-	bp->cmng.fair_vars.fair_threshold = QM_ARB_BYTES;
-
-	/* we multiply by 1e3/8 to get bytes/msec.
-	   We don't want the credits to pass a credit
-	   of the t_fair*FAIR_MEM (algorithm resolution) */
-	bp->cmng.fair_vars.upper_bound = r_param * t_fair * FAIR_MEM;
-	/* since each tick is 4 usec */
-	bp->cmng.fair_vars.fairness_timeout = fair_periodic_timeout_usec / 4;
-}
-
-/* Calculates the sum of vn_min_rates.
-   It's needed for further normalizing of the min_rates.
-   Returns:
-     sum of vn_min_rates.
-       or
-     0 - if all the min_rates are 0.
-     In the later case fainess algorithm should be deactivated.
-     If not all min_rates are zero then those that are zeroes will be set to 1.
- */
-static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp)
-{
-	int all_zero = 1;
-	int vn;
-
-	bp->vn_weight_sum = 0;
-	for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++) {
-		u32 vn_cfg = bp->mf_config[vn];
-		u32 vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
-				   FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
-
-		/* Skip hidden vns */
-		if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE)
-			continue;
-
-		/* If min rate is zero - set it to 1 */
-		if (!vn_min_rate)
-			vn_min_rate = DEF_MIN_RATE;
-		else
-			all_zero = 0;
-
-		bp->vn_weight_sum += vn_min_rate;
-	}
-
-	/* if ETS or all min rates are zeros - disable fairness */
-	if (BNX2X_IS_ETS_ENABLED(bp)) {
-		bp->cmng.flags.cmng_enables &=
-					~CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
-		DP(NETIF_MSG_IFUP, "Fairness will be disabled due to ETS\n");
-	} else if (all_zero) {
-		bp->cmng.flags.cmng_enables &=
-					~CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
-		DP(NETIF_MSG_IFUP, "All MIN values are zeroes"
-		   "  fairness will be disabled\n");
-	} else
-		bp->cmng.flags.cmng_enables |=
-					CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
-}
-
-/* returns func by VN for current port */
-static inline int func_by_vn(struct bnx2x *bp, int vn)
-{
-	return 2 * vn + BP_PORT(bp);
-}
-
-static void bnx2x_init_vn_minmax(struct bnx2x *bp, int vn)
-{
-	struct rate_shaping_vars_per_vn m_rs_vn;
-	struct fairness_vars_per_vn m_fair_vn;
-	u32 vn_cfg = bp->mf_config[vn];
-	int func = func_by_vn(bp, vn);
-	u16 vn_min_rate, vn_max_rate;
-	int i;
-
-	/* If function is hidden - set min and max to zeroes */
-	if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE) {
-		vn_min_rate = 0;
-		vn_max_rate = 0;
-
-	} else {
-		u32 maxCfg = bnx2x_extract_max_cfg(bp, vn_cfg);
-
-		vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
-				FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
-		/* If fairness is enabled (not all min rates are zeroes) and
-		   if current min rate is zero - set it to 1.
-		   This is a requirement of the algorithm. */
-		if (bp->vn_weight_sum && (vn_min_rate == 0))
-			vn_min_rate = DEF_MIN_RATE;
-
-		if (IS_MF_SI(bp))
-			/* maxCfg in percents of linkspeed */
-			vn_max_rate = (bp->link_vars.line_speed * maxCfg) / 100;
-		else
-			/* maxCfg is absolute in 100Mb units */
-			vn_max_rate = maxCfg * 100;
-	}
-
-	DP(NETIF_MSG_IFUP,
-	   "func %d: vn_min_rate %d  vn_max_rate %d  vn_weight_sum %d\n",
-	   func, vn_min_rate, vn_max_rate, bp->vn_weight_sum);
-
-	memset(&m_rs_vn, 0, sizeof(struct rate_shaping_vars_per_vn));
-	memset(&m_fair_vn, 0, sizeof(struct fairness_vars_per_vn));
-
-	/* global vn counter - maximal Mbps for this vn */
-	m_rs_vn.vn_counter.rate = vn_max_rate;
-
-	/* quota - number of bytes transmitted in this period */
-	m_rs_vn.vn_counter.quota =
-				(vn_max_rate * RS_PERIODIC_TIMEOUT_USEC) / 8;
-
-	if (bp->vn_weight_sum) {
-		/* credit for each period of the fairness algorithm:
-		   number of bytes in T_FAIR (the vn share the port rate).
-		   vn_weight_sum should not be larger than 10000, thus
-		   T_FAIR_COEF / (8 * vn_weight_sum) will always be greater
-		   than zero */
-		m_fair_vn.vn_credit_delta =
-			max_t(u32, (vn_min_rate * (T_FAIR_COEF /
-						   (8 * bp->vn_weight_sum))),
-			      (bp->cmng.fair_vars.fair_threshold +
-							MIN_ABOVE_THRESH));
-		DP(NETIF_MSG_IFUP, "m_fair_vn.vn_credit_delta %d\n",
-		   m_fair_vn.vn_credit_delta);
-	}
-
-	/* Store it to internal memory */
-	for (i = 0; i < sizeof(struct rate_shaping_vars_per_vn)/4; i++)
-		REG_WR(bp, BAR_XSTRORM_INTMEM +
-		       XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(func) + i * 4,
-		       ((u32 *)(&m_rs_vn))[i]);
-
-	for (i = 0; i < sizeof(struct fairness_vars_per_vn)/4; i++)
-		REG_WR(bp, BAR_XSTRORM_INTMEM +
-		       XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(func) + i * 4,
-		       ((u32 *)(&m_fair_vn))[i]);
-}
-
-static int bnx2x_get_cmng_fns_mode(struct bnx2x *bp)
-{
-	if (CHIP_REV_IS_SLOW(bp))
-		return CMNG_FNS_NONE;
-	if (IS_MF(bp))
-		return CMNG_FNS_MINMAX;
-
-	return CMNG_FNS_NONE;
-}
-
-void bnx2x_read_mf_cfg(struct bnx2x *bp)
-{
-	int vn, n = (CHIP_MODE_IS_4_PORT(bp) ? 2 : 1);
-
-	if (BP_NOMCP(bp))
-		return; /* what should be the default bvalue in this case */
-
-	/* For 2 port configuration the absolute function number formula
-	 * is:
-	 *      abs_func = 2 * vn + BP_PORT + BP_PATH
-	 *
-	 *      and there are 4 functions per port
-	 *
-	 * For 4 port configuration it is
-	 *      abs_func = 4 * vn + 2 * BP_PORT + BP_PATH
-	 *
-	 *      and there are 2 functions per port
-	 */
-	for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++) {
-		int /*abs*/func = n * (2 * vn + BP_PORT(bp)) + BP_PATH(bp);
-
-		if (func >= E1H_FUNC_MAX)
-			break;
-
-		bp->mf_config[vn] =
-			MF_CFG_RD(bp, func_mf_config[func].config);
-	}
-}
-
-static void bnx2x_cmng_fns_init(struct bnx2x *bp, u8 read_cfg, u8 cmng_type)
-{
-
-	if (cmng_type == CMNG_FNS_MINMAX) {
-		int vn;
-
-		/* clear cmng_enables */
-		bp->cmng.flags.cmng_enables = 0;
-
-		/* read mf conf from shmem */
-		if (read_cfg)
-			bnx2x_read_mf_cfg(bp);
-
-		/* Init rate shaping and fairness contexts */
-		bnx2x_init_port_minmax(bp);
-
-		/* vn_weight_sum and enable fairness if not 0 */
-		bnx2x_calc_vn_weight_sum(bp);
-
-		/* calculate and set min-max rate for each vn */
-		if (bp->port.pmf)
-			for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++)
-				bnx2x_init_vn_minmax(bp, vn);
-
-		/* always enable rate shaping and fairness */
-		bp->cmng.flags.cmng_enables |=
-					CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN;
-		if (!bp->vn_weight_sum)
-			DP(NETIF_MSG_IFUP, "All MIN values are zeroes"
-				   "  fairness will be disabled\n");
-		return;
-	}
-
-	/* rate shaping and fairness are disabled */
-	DP(NETIF_MSG_IFUP,
-	   "rate shaping and fairness are disabled\n");
-}
-
-static inline void bnx2x_link_sync_notify(struct bnx2x *bp)
-{
-	int func;
-	int vn;
-
-	/* Set the attention towards other drivers on the same port */
-	for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++) {
-		if (vn == BP_VN(bp))
-			continue;
-
-		func = func_by_vn(bp, vn);
-		REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_0 +
-		       (LINK_SYNC_ATTENTION_BIT_FUNC_0 + func)*4, 1);
-	}
-}
-
-/* This function is called upon link interrupt */
-static void bnx2x_link_attn(struct bnx2x *bp)
-{
-	/* Make sure that we are synced with the current statistics */
-	bnx2x_stats_handle(bp, STATS_EVENT_STOP);
-
-	bnx2x_link_update(&bp->link_params, &bp->link_vars);
-
-	if (bp->link_vars.link_up) {
-
-		/* dropless flow control */
-		if (!CHIP_IS_E1(bp) && bp->dropless_fc) {
-			int port = BP_PORT(bp);
-			u32 pause_enabled = 0;
-
-			if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
-				pause_enabled = 1;
-
-			REG_WR(bp, BAR_USTRORM_INTMEM +
-			       USTORM_ETH_PAUSE_ENABLED_OFFSET(port),
-			       pause_enabled);
-		}
-
-		if (bp->link_vars.mac_type != MAC_TYPE_EMAC) {
-			struct host_port_stats *pstats;
-
-			pstats = bnx2x_sp(bp, port_stats);
-			/* reset old mac stats */
-			memset(&(pstats->mac_stx[0]), 0,
-			       sizeof(struct mac_stx));
-		}
-		if (bp->state == BNX2X_STATE_OPEN)
-			bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
-	}
-
-	if (bp->link_vars.link_up && bp->link_vars.line_speed) {
-		int cmng_fns = bnx2x_get_cmng_fns_mode(bp);
-
-		if (cmng_fns != CMNG_FNS_NONE) {
-			bnx2x_cmng_fns_init(bp, false, cmng_fns);
-			storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
-		} else
-			/* rate shaping and fairness are disabled */
-			DP(NETIF_MSG_IFUP,
-			   "single function mode without fairness\n");
-	}
-
-	__bnx2x_link_report(bp);
-
-	if (IS_MF(bp))
-		bnx2x_link_sync_notify(bp);
-}
-
-void bnx2x__link_status_update(struct bnx2x *bp)
-{
-	if (bp->state != BNX2X_STATE_OPEN)
-		return;
-
-	bnx2x_link_status_update(&bp->link_params, &bp->link_vars);
-
-	if (bp->link_vars.link_up)
-		bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
-	else
-		bnx2x_stats_handle(bp, STATS_EVENT_STOP);
-
-	/* indicate link status */
-	bnx2x_link_report(bp);
-}
-
-static void bnx2x_pmf_update(struct bnx2x *bp)
-{
-	int port = BP_PORT(bp);
-	u32 val;
-
-	bp->port.pmf = 1;
-	DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);
-
-	/*
-	 * We need the mb() to ensure the ordering between the writing to
-	 * bp->port.pmf here and reading it from the bnx2x_periodic_task().
-	 */
-	smp_mb();
-
-	/* queue a periodic task */
-	queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
-
-	bnx2x_dcbx_pmf_update(bp);
-
-	/* enable nig attention */
-	val = (0xff0f | (1 << (BP_VN(bp) + 4)));
-	if (bp->common.int_block == INT_BLOCK_HC) {
-		REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val);
-		REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val);
-	} else if (!CHIP_IS_E1x(bp)) {
-		REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, val);
-		REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, val);
-	}
-
-	bnx2x_stats_handle(bp, STATS_EVENT_PMF);
-}
-
-/* end of Link */
-
-/* slow path */
-
-/*
- * General service functions
- */
-
-/* send the MCP a request, block until there is a reply */
-u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param)
-{
-	int mb_idx = BP_FW_MB_IDX(bp);
-	u32 seq;
-	u32 rc = 0;
-	u32 cnt = 1;
-	u8 delay = CHIP_REV_IS_SLOW(bp) ? 100 : 10;
-
-	mutex_lock(&bp->fw_mb_mutex);
-	seq = ++bp->fw_seq;
-	SHMEM_WR(bp, func_mb[mb_idx].drv_mb_param, param);
-	SHMEM_WR(bp, func_mb[mb_idx].drv_mb_header, (command | seq));
-
-	DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB param 0x%08x\n",
-			(command | seq), param);
-
-	do {
-		/* let the FW do it's magic ... */
-		msleep(delay);
-
-		rc = SHMEM_RD(bp, func_mb[mb_idx].fw_mb_header);
-
-		/* Give the FW up to 5 second (500*10ms) */
-	} while ((seq != (rc & FW_MSG_SEQ_NUMBER_MASK)) && (cnt++ < 500));
-
-	DP(BNX2X_MSG_MCP, "[after %d ms] read (%x) seq is (%x) from FW MB\n",
-	   cnt*delay, rc, seq);
-
-	/* is this a reply to our command? */
-	if (seq == (rc & FW_MSG_SEQ_NUMBER_MASK))
-		rc &= FW_MSG_CODE_MASK;
-	else {
-		/* FW BUG! */
-		BNX2X_ERR("FW failed to respond!\n");
-		bnx2x_fw_dump(bp);
-		rc = 0;
-	}
-	mutex_unlock(&bp->fw_mb_mutex);
-
-	return rc;
-}
-
-static u8 stat_counter_valid(struct bnx2x *bp, struct bnx2x_fastpath *fp)
-{
-#ifdef BCM_CNIC
-	/* Statistics are not supported for CNIC Clients at the moment */
-	if (IS_FCOE_FP(fp))
-		return false;
-#endif
-	return true;
-}
-
-void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p)
-{
-	if (CHIP_IS_E1x(bp)) {
-		struct tstorm_eth_function_common_config tcfg = {0};
-
-		storm_memset_func_cfg(bp, &tcfg, p->func_id);
-	}
-
-	/* Enable the function in the FW */
-	storm_memset_vf_to_pf(bp, p->func_id, p->pf_id);
-	storm_memset_func_en(bp, p->func_id, 1);
-
-	/* spq */
-	if (p->func_flgs & FUNC_FLG_SPQ) {
-		storm_memset_spq_addr(bp, p->spq_map, p->func_id);
-		REG_WR(bp, XSEM_REG_FAST_MEMORY +
-		       XSTORM_SPQ_PROD_OFFSET(p->func_id), p->spq_prod);
-	}
-}
-
-/**
- * bnx2x_get_tx_only_flags - Return common flags
- *
- * @bp		device handle
- * @fp		queue handle
- * @zero_stats	TRUE if statistics zeroing is needed
- *
- * Return the flags that are common for the Tx-only and not normal connections.
- */
-static inline unsigned long bnx2x_get_common_flags(struct bnx2x *bp,
-						   struct bnx2x_fastpath *fp,
-						   bool zero_stats)
-{
-	unsigned long flags = 0;
-
-	/* PF driver will always initialize the Queue to an ACTIVE state */
-	__set_bit(BNX2X_Q_FLG_ACTIVE, &flags);
-
-	/* tx only connections collect statistics (on the same index as the
-	 *  parent connection). The statistics are zeroed when the parent
-	 *  connection is initialized.
-	 */
-	if (stat_counter_valid(bp, fp)) {
-		__set_bit(BNX2X_Q_FLG_STATS, &flags);
-		if (zero_stats)
-			__set_bit(BNX2X_Q_FLG_ZERO_STATS, &flags);
-	}
-
-	return flags;
-}
-
-static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
-					      struct bnx2x_fastpath *fp,
-					      bool leading)
-{
-	unsigned long flags = 0;
-
-	/* calculate other queue flags */
-	if (IS_MF_SD(bp))
-		__set_bit(BNX2X_Q_FLG_OV, &flags);
-
-	if (IS_FCOE_FP(fp))
-		__set_bit(BNX2X_Q_FLG_FCOE, &flags);
-
-	if (!fp->disable_tpa) {
-		__set_bit(BNX2X_Q_FLG_TPA, &flags);
-		__set_bit(BNX2X_Q_FLG_TPA_IPV6, &flags);
-	}
-
-	if (leading) {
-		__set_bit(BNX2X_Q_FLG_LEADING_RSS, &flags);
-		__set_bit(BNX2X_Q_FLG_MCAST, &flags);
-	}
-
-	/* Always set HW VLAN stripping */
-	__set_bit(BNX2X_Q_FLG_VLAN, &flags);
-
-
-	return flags | bnx2x_get_common_flags(bp, fp, true);
-}
-
-static void bnx2x_pf_q_prep_general(struct bnx2x *bp,
-	struct bnx2x_fastpath *fp, struct bnx2x_general_setup_params *gen_init,
-	u8 cos)
-{
-	gen_init->stat_id = bnx2x_stats_id(fp);
-	gen_init->spcl_id = fp->cl_id;
-
-	/* Always use mini-jumbo MTU for FCoE L2 ring */
-	if (IS_FCOE_FP(fp))
-		gen_init->mtu = BNX2X_FCOE_MINI_JUMBO_MTU;
-	else
-		gen_init->mtu = bp->dev->mtu;
-
-	gen_init->cos = cos;
-}
-
-static void bnx2x_pf_rx_q_prep(struct bnx2x *bp,
-	struct bnx2x_fastpath *fp, struct rxq_pause_params *pause,
-	struct bnx2x_rxq_setup_params *rxq_init)
-{
-	u8 max_sge = 0;
-	u16 sge_sz = 0;
-	u16 tpa_agg_size = 0;
-
-	if (!fp->disable_tpa) {
-		pause->sge_th_lo = SGE_TH_LO(bp);
-		pause->sge_th_hi = SGE_TH_HI(bp);
-
-		/* validate SGE ring has enough to cross high threshold */
-		WARN_ON(bp->dropless_fc &&
-				pause->sge_th_hi + FW_PREFETCH_CNT >
-				MAX_RX_SGE_CNT * NUM_RX_SGE_PAGES);
-
-		tpa_agg_size = min_t(u32,
-			(min_t(u32, 8, MAX_SKB_FRAGS) *
-			SGE_PAGE_SIZE * PAGES_PER_SGE), 0xffff);
-		max_sge = SGE_PAGE_ALIGN(bp->dev->mtu) >>
-			SGE_PAGE_SHIFT;
-		max_sge = ((max_sge + PAGES_PER_SGE - 1) &
-			  (~(PAGES_PER_SGE-1))) >> PAGES_PER_SGE_SHIFT;
-		sge_sz = (u16)min_t(u32, SGE_PAGE_SIZE * PAGES_PER_SGE,
-				    0xffff);
-	}
-
-	/* pause - not for e1 */
-	if (!CHIP_IS_E1(bp)) {
-		pause->bd_th_lo = BD_TH_LO(bp);
-		pause->bd_th_hi = BD_TH_HI(bp);
-
-		pause->rcq_th_lo = RCQ_TH_LO(bp);
-		pause->rcq_th_hi = RCQ_TH_HI(bp);
-		/*
-		 * validate that rings have enough entries to cross
-		 * high thresholds
-		 */
-		WARN_ON(bp->dropless_fc &&
-				pause->bd_th_hi + FW_PREFETCH_CNT >
-				bp->rx_ring_size);
-		WARN_ON(bp->dropless_fc &&
-				pause->rcq_th_hi + FW_PREFETCH_CNT >
-				NUM_RCQ_RINGS * MAX_RCQ_DESC_CNT);
-
-		pause->pri_map = 1;
-	}
-
-	/* rxq setup */
-	rxq_init->dscr_map = fp->rx_desc_mapping;
-	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;
-
-	/* This should be a maximum number of data bytes that may be
-	 * placed on the BD (not including paddings).
-	 */
-	rxq_init->buf_sz = fp->rx_buf_size - BNX2X_FW_RX_ALIGN -
-		IP_HEADER_ALIGNMENT_PADDING;
-
-	rxq_init->cl_qzone_id = fp->cl_qzone_id;
-	rxq_init->tpa_agg_sz = tpa_agg_size;
-	rxq_init->sge_buf_sz = sge_sz;
-	rxq_init->max_sges_pkt = max_sge;
-	rxq_init->rss_engine_id = BP_FUNC(bp);
-
-	/* Maximum number or simultaneous TPA aggregation for this Queue.
-	 *
-	 * For PF Clients it should be the maximum avaliable number.
-	 * VF driver(s) may want to define it to a smaller value.
-	 */
-	rxq_init->max_tpa_queues = MAX_AGG_QS(bp);
-
-	rxq_init->cache_line_log = BNX2X_RX_ALIGN_SHIFT;
-	rxq_init->fw_sb_id = fp->fw_sb_id;
-
-	if (IS_FCOE_FP(fp))
-		rxq_init->sb_cq_index = HC_SP_INDEX_ETH_FCOE_RX_CQ_CONS;
-	else
-		rxq_init->sb_cq_index = HC_INDEX_ETH_RX_CQ_CONS;
-}
-
-static void bnx2x_pf_tx_q_prep(struct bnx2x *bp,
-	struct bnx2x_fastpath *fp, struct bnx2x_txq_setup_params *txq_init,
-	u8 cos)
-{
-	txq_init->dscr_map = fp->txdata[cos].tx_desc_mapping;
-	txq_init->sb_cq_index = HC_INDEX_ETH_FIRST_TX_CQ_CONS + cos;
-	txq_init->traffic_type = LLFC_TRAFFIC_TYPE_NW;
-	txq_init->fw_sb_id = fp->fw_sb_id;
-
-	/*
-	 * set the tss leading client id for TX classfication ==
-	 * leading RSS client id
-	 */
-	txq_init->tss_leading_cl_id = bnx2x_fp(bp, 0, cl_id);
-
-	if (IS_FCOE_FP(fp)) {
-		txq_init->sb_cq_index = HC_SP_INDEX_ETH_FCOE_TX_CQ_CONS;
-		txq_init->traffic_type = LLFC_TRAFFIC_TYPE_FCOE;
-	}
-}
-
-static void bnx2x_pf_init(struct bnx2x *bp)
-{
-	struct bnx2x_func_init_params func_init = {0};
-	struct event_ring_data eq_data = { {0} };
-	u16 flags;
-
-	if (!CHIP_IS_E1x(bp)) {
-		/* reset IGU PF statistics: MSIX + ATTN */
-		/* PF */
-		REG_WR(bp, IGU_REG_STATISTIC_NUM_MESSAGE_SENT +
-			   BNX2X_IGU_STAS_MSG_VF_CNT*4 +
-			   (CHIP_MODE_IS_4_PORT(bp) ?
-				BP_FUNC(bp) : BP_VN(bp))*4, 0);
-		/* ATTN */
-		REG_WR(bp, IGU_REG_STATISTIC_NUM_MESSAGE_SENT +
-			   BNX2X_IGU_STAS_MSG_VF_CNT*4 +
-			   BNX2X_IGU_STAS_MSG_PF_CNT*4 +
-			   (CHIP_MODE_IS_4_PORT(bp) ?
-				BP_FUNC(bp) : BP_VN(bp))*4, 0);
-	}
-
-	/* function setup flags */
-	flags = (FUNC_FLG_STATS | FUNC_FLG_LEADING | FUNC_FLG_SPQ);
-
-	/* This flag is relevant for E1x only.
-	 * E2 doesn't have a TPA configuration in a function level.
-	 */
-	flags |= (bp->flags & TPA_ENABLE_FLAG) ? FUNC_FLG_TPA : 0;
-
-	func_init.func_flgs = flags;
-	func_init.pf_id = BP_FUNC(bp);
-	func_init.func_id = BP_FUNC(bp);
-	func_init.spq_map = bp->spq_mapping;
-	func_init.spq_prod = bp->spq_prod_idx;
-
-	bnx2x_func_init(bp, &func_init);
-
-	memset(&(bp->cmng), 0, sizeof(struct cmng_struct_per_port));
-
-	/*
-	 * Congestion management values depend on the link rate
-	 * There is no active link so initial link rate is set to 10 Gbps.
-	 * When the link comes up The congestion management values are
-	 * re-calculated according to the actual link rate.
-	 */
-	bp->link_vars.line_speed = SPEED_10000;
-	bnx2x_cmng_fns_init(bp, true, bnx2x_get_cmng_fns_mode(bp));
-
-	/* Only the PMF sets the HW */
-	if (bp->port.pmf)
-		storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
-
-	/* init Event Queue */
-	eq_data.base_addr.hi = U64_HI(bp->eq_mapping);
-	eq_data.base_addr.lo = U64_LO(bp->eq_mapping);
-	eq_data.producer = bp->eq_prod;
-	eq_data.index_id = HC_SP_INDEX_EQ_CONS;
-	eq_data.sb_id = DEF_SB_ID;
-	storm_memset_eq_data(bp, &eq_data, BP_FUNC(bp));
-}
-
-
-static void bnx2x_e1h_disable(struct bnx2x *bp)
-{
-	int port = BP_PORT(bp);
-
-	bnx2x_tx_disable(bp);
-
-	REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
-}
-
-static void bnx2x_e1h_enable(struct bnx2x *bp)
-{
-	int port = BP_PORT(bp);
-
-	REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1);
-
-	/* Tx queue should be only reenabled */
-	netif_tx_wake_all_queues(bp->dev);
-
-	/*
-	 * Should not call netif_carrier_on since it will be called if the link
-	 * is up when checking for link state
-	 */
-}
-
-/* called due to MCP event (on pmf):
- *	reread new bandwidth configuration
- *	configure FW
- *	notify others function about the change
- */
-static inline void bnx2x_config_mf_bw(struct bnx2x *bp)
-{
-	if (bp->link_vars.link_up) {
-		bnx2x_cmng_fns_init(bp, true, CMNG_FNS_MINMAX);
-		bnx2x_link_sync_notify(bp);
-	}
-	storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
-}
-
-static inline void bnx2x_set_mf_bw(struct bnx2x *bp)
-{
-	bnx2x_config_mf_bw(bp);
-	bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW_ACK, 0);
-}
-
-static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event)
-{
-	DP(BNX2X_MSG_MCP, "dcc_event 0x%x\n", dcc_event);
-
-	if (dcc_event & DRV_STATUS_DCC_DISABLE_ENABLE_PF) {
-
-		/*
-		 * This is the only place besides the function initialization
-		 * where the bp->flags can change so it is done without any
-		 * locks
-		 */
-		if (bp->mf_config[BP_VN(bp)] & FUNC_MF_CFG_FUNC_DISABLED) {
-			DP(NETIF_MSG_IFDOWN, "mf_cfg function disabled\n");
-			bp->flags |= MF_FUNC_DIS;
-
-			bnx2x_e1h_disable(bp);
-		} else {
-			DP(NETIF_MSG_IFUP, "mf_cfg function enabled\n");
-			bp->flags &= ~MF_FUNC_DIS;
-
-			bnx2x_e1h_enable(bp);
-		}
-		dcc_event &= ~DRV_STATUS_DCC_DISABLE_ENABLE_PF;
-	}
-	if (dcc_event & DRV_STATUS_DCC_BANDWIDTH_ALLOCATION) {
-		bnx2x_config_mf_bw(bp);
-		dcc_event &= ~DRV_STATUS_DCC_BANDWIDTH_ALLOCATION;
-	}
-
-	/* Report results to MCP */
-	if (dcc_event)
-		bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_FAILURE, 0);
-	else
-		bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_OK, 0);
-}
-
-/* must be called under the spq lock */
-static inline struct eth_spe *bnx2x_sp_get_next(struct bnx2x *bp)
-{
-	struct eth_spe *next_spe = bp->spq_prod_bd;
-
-	if (bp->spq_prod_bd == bp->spq_last_bd) {
-		bp->spq_prod_bd = bp->spq;
-		bp->spq_prod_idx = 0;
-		DP(NETIF_MSG_TIMER, "end of spq\n");
-	} else {
-		bp->spq_prod_bd++;
-		bp->spq_prod_idx++;
-	}
-	return next_spe;
-}
-
-/* must be called under the spq lock */
-static inline void bnx2x_sp_prod_update(struct bnx2x *bp)
-{
-	int func = BP_FUNC(bp);
-
-	/*
-	 * Make sure that BD data is updated before writing the producer:
-	 * BD data is written to the memory, the producer is read from the
-	 * memory, thus we need a full memory barrier to ensure the ordering.
-	 */
-	mb();
-
-	REG_WR16(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(func),
-		 bp->spq_prod_idx);
-	mmiowb();
-}
-
-/**
- * bnx2x_is_contextless_ramrod - check if the current command ends on EQ
- *
- * @cmd:	command to check
- * @cmd_type:	command type
- */
-static inline bool bnx2x_is_contextless_ramrod(int cmd, int cmd_type)
-{
-	if ((cmd_type == NONE_CONNECTION_TYPE) ||
-	    (cmd == RAMROD_CMD_ID_ETH_FORWARD_SETUP) ||
-	    (cmd == RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES) ||
-	    (cmd == RAMROD_CMD_ID_ETH_FILTER_RULES) ||
-	    (cmd == RAMROD_CMD_ID_ETH_MULTICAST_RULES) ||
-	    (cmd == RAMROD_CMD_ID_ETH_SET_MAC) ||
-	    (cmd == RAMROD_CMD_ID_ETH_RSS_UPDATE))
-		return true;
-	else
-		return false;
-
-}
-
-
-/**
- * bnx2x_sp_post - place a single command on an SP ring
- *
- * @bp:		driver handle
- * @command:	command to place (e.g. SETUP, FILTER_RULES, etc.)
- * @cid:	SW CID the command is related to
- * @data_hi:	command private data address (high 32 bits)
- * @data_lo:	command private data address (low 32 bits)
- * @cmd_type:	command type (e.g. NONE, ETH)
- *
- * SP data is handled as if it's always an address pair, thus data fields are
- * not swapped to little endian in upper functions. Instead this function swaps
- * data as if it's two u32 fields.
- */
-int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
-		  u32 data_hi, u32 data_lo, int cmd_type)
-{
-	struct eth_spe *spe;
-	u16 type;
-	bool common = bnx2x_is_contextless_ramrod(command, cmd_type);
-
-#ifdef BNX2X_STOP_ON_ERROR
-	if (unlikely(bp->panic))
-		return -EIO;
-#endif
-
-	spin_lock_bh(&bp->spq_lock);
-
-	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);
-
-	/* CID needs port number to be encoded int it */
-	spe->hdr.conn_and_cmd_data =
-			cpu_to_le32((command << SPE_HDR_CMD_ID_SHIFT) |
-				    HW_CID(bp, cid));
-
-	type = (cmd_type << SPE_HDR_CONN_TYPE_SHIFT) & SPE_HDR_CONN_TYPE;
-
-	type |= ((BP_FUNC(bp) << SPE_HDR_FUNCTION_ID_SHIFT) &
-		 SPE_HDR_FUNCTION_ID);
-
-	spe->hdr.type = cpu_to_le16(type);
-
-	spe->data.update_data_addr.hi = cpu_to_le32(data_hi);
-	spe->data.update_data_addr.lo = cpu_to_le32(data_lo);
-
-	/*
-	 * 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.
-	 */
-	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)  (cmd, common?) (%d,%d)  hw_cid %x  data (%x:%x) "
-	   "type(0x%x) left (CQ, EQ) (%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, common,
-	   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);
-	return 0;
-}
-
-/* acquire split MCP access lock register */
-static int bnx2x_acquire_alr(struct bnx2x *bp)
-{
-	u32 j, val;
-	int rc = 0;
-
-	might_sleep();
-	for (j = 0; j < 1000; j++) {
-		val = (1UL << 31);
-		REG_WR(bp, GRCBASE_MCP + 0x9c, val);
-		val = REG_RD(bp, GRCBASE_MCP + 0x9c);
-		if (val & (1L << 31))
-			break;
-
-		msleep(5);
-	}
-	if (!(val & (1L << 31))) {
-		BNX2X_ERR("Cannot acquire MCP access lock register\n");
-		rc = -EBUSY;
-	}
-
-	return rc;
-}
-
-/* release split MCP access lock register */
-static void bnx2x_release_alr(struct bnx2x *bp)
-{
-	REG_WR(bp, GRCBASE_MCP + 0x9c, 0);
-}
-
-#define BNX2X_DEF_SB_ATT_IDX	0x0001
-#define BNX2X_DEF_SB_IDX	0x0002
-
-static inline u16 bnx2x_update_dsb_idx(struct bnx2x *bp)
-{
-	struct host_sp_status_block *def_sb = bp->def_status_blk;
-	u16 rc = 0;
-
-	barrier(); /* status block is written to by the chip */
-	if (bp->def_att_idx != def_sb->atten_status_block.attn_bits_index) {
-		bp->def_att_idx = def_sb->atten_status_block.attn_bits_index;
-		rc |= BNX2X_DEF_SB_ATT_IDX;
-	}
-
-	if (bp->def_idx != def_sb->sp_sb.running_index) {
-		bp->def_idx = def_sb->sp_sb.running_index;
-		rc |= BNX2X_DEF_SB_IDX;
-	}
-
-	/* Do not reorder: indecies reading should complete before handling */
-	barrier();
-	return rc;
-}
-
-/*
- * slow path service functions
- */
-
-static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
-{
-	int port = BP_PORT(bp);
-	u32 aeu_addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
-			      MISC_REG_AEU_MASK_ATTN_FUNC_0;
-	u32 nig_int_mask_addr = port ? NIG_REG_MASK_INTERRUPT_PORT1 :
-				       NIG_REG_MASK_INTERRUPT_PORT0;
-	u32 aeu_mask;
-	u32 nig_mask = 0;
-	u32 reg_addr;
-
-	if (bp->attn_state & asserted)
-		BNX2X_ERR("IGU ERROR\n");
-
-	bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_PORT0_ATT_MASK + port);
-	aeu_mask = REG_RD(bp, aeu_addr);
-
-	DP(NETIF_MSG_HW, "aeu_mask %x  newly asserted %x\n",
-	   aeu_mask, asserted);
-	aeu_mask &= ~(asserted & 0x3ff);
-	DP(NETIF_MSG_HW, "new mask %x\n", aeu_mask);
-
-	REG_WR(bp, aeu_addr, aeu_mask);
-	bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_PORT0_ATT_MASK + port);
-
-	DP(NETIF_MSG_HW, "attn_state %x\n", bp->attn_state);
-	bp->attn_state |= asserted;
-	DP(NETIF_MSG_HW, "new state %x\n", bp->attn_state);
-
-	if (asserted & ATTN_HARD_WIRED_MASK) {
-		if (asserted & ATTN_NIG_FOR_FUNC) {
-
-			bnx2x_acquire_phy_lock(bp);
-
-			/* save nig interrupt mask */
-			nig_mask = REG_RD(bp, nig_int_mask_addr);
-
-			/* If nig_mask is not set, no need to call the update
-			 * function.
-			 */
-			if (nig_mask) {
-				REG_WR(bp, nig_int_mask_addr, 0);
-
-				bnx2x_link_attn(bp);
-			}
-
-			/* handle unicore attn? */
-		}
-		if (asserted & ATTN_SW_TIMER_4_FUNC)
-			DP(NETIF_MSG_HW, "ATTN_SW_TIMER_4_FUNC!\n");
-
-		if (asserted & GPIO_2_FUNC)
-			DP(NETIF_MSG_HW, "GPIO_2_FUNC!\n");
-
-		if (asserted & GPIO_3_FUNC)
-			DP(NETIF_MSG_HW, "GPIO_3_FUNC!\n");
-
-		if (asserted & GPIO_4_FUNC)
-			DP(NETIF_MSG_HW, "GPIO_4_FUNC!\n");
-
-		if (port == 0) {
-			if (asserted & ATTN_GENERAL_ATTN_1) {
-				DP(NETIF_MSG_HW, "ATTN_GENERAL_ATTN_1!\n");
-				REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_1, 0x0);
-			}
-			if (asserted & ATTN_GENERAL_ATTN_2) {
-				DP(NETIF_MSG_HW, "ATTN_GENERAL_ATTN_2!\n");
-				REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_2, 0x0);
-			}
-			if (asserted & ATTN_GENERAL_ATTN_3) {
-				DP(NETIF_MSG_HW, "ATTN_GENERAL_ATTN_3!\n");
-				REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_3, 0x0);
-			}
-		} else {
-			if (asserted & ATTN_GENERAL_ATTN_4) {
-				DP(NETIF_MSG_HW, "ATTN_GENERAL_ATTN_4!\n");
-				REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_4, 0x0);
-			}
-			if (asserted & ATTN_GENERAL_ATTN_5) {
-				DP(NETIF_MSG_HW, "ATTN_GENERAL_ATTN_5!\n");
-				REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_5, 0x0);
-			}
-			if (asserted & ATTN_GENERAL_ATTN_6) {
-				DP(NETIF_MSG_HW, "ATTN_GENERAL_ATTN_6!\n");
-				REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_6, 0x0);
-			}
-		}
-
-	} /* if hardwired */
-
-	if (bp->common.int_block == INT_BLOCK_HC)
-		reg_addr = (HC_REG_COMMAND_REG + port*32 +
-			    COMMAND_REG_ATTN_BITS_SET);
-	else
-		reg_addr = (BAR_IGU_INTMEM + IGU_CMD_ATTN_BIT_SET_UPPER*8);
-
-	DP(NETIF_MSG_HW, "about to mask 0x%08x at %s addr 0x%x\n", asserted,
-	   (bp->common.int_block == INT_BLOCK_HC) ? "HC" : "IGU", reg_addr);
-	REG_WR(bp, reg_addr, asserted);
-
-	/* now set back the mask */
-	if (asserted & ATTN_NIG_FOR_FUNC) {
-		REG_WR(bp, nig_int_mask_addr, nig_mask);
-		bnx2x_release_phy_lock(bp);
-	}
-}
-
-static inline void bnx2x_fan_failure(struct bnx2x *bp)
-{
-	int port = BP_PORT(bp);
-	u32 ext_phy_config;
-	/* mark the failure */
-	ext_phy_config =
-		SHMEM_RD(bp,
-			 dev_info.port_hw_config[port].external_phy_config);
-
-	ext_phy_config &= ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
-	ext_phy_config |= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE;
-	SHMEM_WR(bp, dev_info.port_hw_config[port].external_phy_config,
-		 ext_phy_config);
-
-	/* log the failure */
-	netdev_err(bp->dev, "Fan Failure on Network Controller has caused"
-	       " the driver to shutdown the card to prevent permanent"
-	       " damage.  Please contact OEM Support for assistance\n");
-}
-
-static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
-{
-	int port = BP_PORT(bp);
-	int reg_offset;
-	u32 val;
-
-	reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
-			     MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
-
-	if (attn & AEU_INPUTS_ATTN_BITS_SPIO5) {
-
-		val = REG_RD(bp, reg_offset);
-		val &= ~AEU_INPUTS_ATTN_BITS_SPIO5;
-		REG_WR(bp, reg_offset, val);
-
-		BNX2X_ERR("SPIO5 hw attention\n");
-
-		/* Fan failure attention */
-		bnx2x_hw_reset_phy(&bp->link_params);
-		bnx2x_fan_failure(bp);
-	}
-
-	if ((attn & bp->link_vars.aeu_int_mask) && bp->port.pmf) {
-		bnx2x_acquire_phy_lock(bp);
-		bnx2x_handle_module_detect_int(&bp->link_params);
-		bnx2x_release_phy_lock(bp);
-	}
-
-	if (attn & HW_INTERRUT_ASSERT_SET_0) {
-
-		val = REG_RD(bp, reg_offset);
-		val &= ~(attn & HW_INTERRUT_ASSERT_SET_0);
-		REG_WR(bp, reg_offset, val);
-
-		BNX2X_ERR("FATAL HW block attention set0 0x%x\n",
-			  (u32)(attn & HW_INTERRUT_ASSERT_SET_0));
-		bnx2x_panic();
-	}
-}
-
-static inline void bnx2x_attn_int_deasserted1(struct bnx2x *bp, u32 attn)
-{
-	u32 val;
-
-	if (attn & AEU_INPUTS_ATTN_BITS_DOORBELLQ_HW_INTERRUPT) {
-
-		val = REG_RD(bp, DORQ_REG_DORQ_INT_STS_CLR);
-		BNX2X_ERR("DB hw attention 0x%x\n", val);
-		/* DORQ discard attention */
-		if (val & 0x2)
-			BNX2X_ERR("FATAL error from DORQ\n");
-	}
-
-	if (attn & HW_INTERRUT_ASSERT_SET_1) {
-
-		int port = BP_PORT(bp);
-		int reg_offset;
-
-		reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_1 :
-				     MISC_REG_AEU_ENABLE1_FUNC_0_OUT_1);
-
-		val = REG_RD(bp, reg_offset);
-		val &= ~(attn & HW_INTERRUT_ASSERT_SET_1);
-		REG_WR(bp, reg_offset, val);
-
-		BNX2X_ERR("FATAL HW block attention set1 0x%x\n",
-			  (u32)(attn & HW_INTERRUT_ASSERT_SET_1));
-		bnx2x_panic();
-	}
-}
-
-static inline void bnx2x_attn_int_deasserted2(struct bnx2x *bp, u32 attn)
-{
-	u32 val;
-
-	if (attn & AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT) {
-
-		val = REG_RD(bp, CFC_REG_CFC_INT_STS_CLR);
-		BNX2X_ERR("CFC hw attention 0x%x\n", val);
-		/* CFC error attention */
-		if (val & 0x2)
-			BNX2X_ERR("FATAL error from CFC\n");
-	}
-
-	if (attn & AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT) {
-		val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_0);
-		BNX2X_ERR("PXP hw attention-0 0x%x\n", val);
-		/* RQ_USDMDP_FIFO_OVERFLOW */
-		if (val & 0x18000)
-			BNX2X_ERR("FATAL error from PXP\n");
-
-		if (!CHIP_IS_E1x(bp)) {
-			val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_1);
-			BNX2X_ERR("PXP hw attention-1 0x%x\n", val);
-		}
-	}
-
-	if (attn & HW_INTERRUT_ASSERT_SET_2) {
-
-		int port = BP_PORT(bp);
-		int reg_offset;
-
-		reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_2 :
-				     MISC_REG_AEU_ENABLE1_FUNC_0_OUT_2);
-
-		val = REG_RD(bp, reg_offset);
-		val &= ~(attn & HW_INTERRUT_ASSERT_SET_2);
-		REG_WR(bp, reg_offset, val);
-
-		BNX2X_ERR("FATAL HW block attention set2 0x%x\n",
-			  (u32)(attn & HW_INTERRUT_ASSERT_SET_2));
-		bnx2x_panic();
-	}
-}
-
-static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
-{
-	u32 val;
-
-	if (attn & EVEREST_GEN_ATTN_IN_USE_MASK) {
-
-		if (attn & BNX2X_PMF_LINK_ASSERT) {
-			int func = BP_FUNC(bp);
-
-			REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
-			bp->mf_config[BP_VN(bp)] = MF_CFG_RD(bp,
-					func_mf_config[BP_ABS_FUNC(bp)].config);
-			val = SHMEM_RD(bp,
-				       func_mb[BP_FW_MB_IDX(bp)].drv_status);
-			if (val & DRV_STATUS_DCC_EVENT_MASK)
-				bnx2x_dcc_event(bp,
-					    (val & DRV_STATUS_DCC_EVENT_MASK));
-
-			if (val & DRV_STATUS_SET_MF_BW)
-				bnx2x_set_mf_bw(bp);
-
-			if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF))
-				bnx2x_pmf_update(bp);
-
-			if (bp->port.pmf &&
-			    (val & DRV_STATUS_DCBX_NEGOTIATION_RESULTS) &&
-				bp->dcbx_enabled > 0)
-				/* start dcbx state machine */
-				bnx2x_dcbx_set_params(bp,
-					BNX2X_DCBX_STATE_NEG_RECEIVED);
-			if (bp->link_vars.periodic_flags &
-			    PERIODIC_FLAGS_LINK_EVENT) {
-				/*  sync with link */
-				bnx2x_acquire_phy_lock(bp);
-				bp->link_vars.periodic_flags &=
-					~PERIODIC_FLAGS_LINK_EVENT;
-				bnx2x_release_phy_lock(bp);
-				if (IS_MF(bp))
-					bnx2x_link_sync_notify(bp);
-				bnx2x_link_report(bp);
-			}
-			/* Always call it here: bnx2x_link_report() will
-			 * prevent the link indication duplication.
-			 */
-			bnx2x__link_status_update(bp);
-		} else if (attn & BNX2X_MC_ASSERT_BITS) {
-
-			BNX2X_ERR("MC assert!\n");
-			bnx2x_mc_assert(bp);
-			REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_10, 0);
-			REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_9, 0);
-			REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_8, 0);
-			REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_7, 0);
-			bnx2x_panic();
-
-		} else if (attn & BNX2X_MCP_ASSERT) {
-
-			BNX2X_ERR("MCP assert!\n");
-			REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_11, 0);
-			bnx2x_fw_dump(bp);
-
-		} else
-			BNX2X_ERR("Unknown HW assert! (attn 0x%x)\n", attn);
-	}
-
-	if (attn & EVEREST_LATCHED_ATTN_IN_USE_MASK) {
-		BNX2X_ERR("LATCHED attention 0x%08x (masked)\n", attn);
-		if (attn & BNX2X_GRC_TIMEOUT) {
-			val = CHIP_IS_E1(bp) ? 0 :
-					REG_RD(bp, MISC_REG_GRC_TIMEOUT_ATTN);
-			BNX2X_ERR("GRC time-out 0x%08x\n", val);
-		}
-		if (attn & BNX2X_GRC_RSV) {
-			val = CHIP_IS_E1(bp) ? 0 :
-					REG_RD(bp, MISC_REG_GRC_RSV_ATTN);
-			BNX2X_ERR("GRC reserved 0x%08x\n", val);
-		}
-		REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0x7ff);
-	}
-}
-
-/*
- * Bits map:
- * 0-7   - Engine0 load counter.
- * 8-15  - Engine1 load counter.
- * 16    - Engine0 RESET_IN_PROGRESS bit.
- * 17    - Engine1 RESET_IN_PROGRESS bit.
- * 18    - Engine0 ONE_IS_LOADED. Set when there is at least one active function
- *         on the engine
- * 19    - Engine1 ONE_IS_LOADED.
- * 20    - Chip reset flow bit. When set none-leader must wait for both engines
- *         leader to complete (check for both RESET_IN_PROGRESS bits and not for
- *         just the one belonging to its engine).
- *
- */
-#define BNX2X_RECOVERY_GLOB_REG		MISC_REG_GENERIC_POR_1
-
-#define BNX2X_PATH0_LOAD_CNT_MASK	0x000000ff
-#define BNX2X_PATH0_LOAD_CNT_SHIFT	0
-#define BNX2X_PATH1_LOAD_CNT_MASK	0x0000ff00
-#define BNX2X_PATH1_LOAD_CNT_SHIFT	8
-#define BNX2X_PATH0_RST_IN_PROG_BIT	0x00010000
-#define BNX2X_PATH1_RST_IN_PROG_BIT	0x00020000
-#define BNX2X_GLOBAL_RESET_BIT		0x00040000
-
-/*
- * Set the GLOBAL_RESET bit.
- *
- * Should be run under rtnl lock
- */
-void bnx2x_set_reset_global(struct bnx2x *bp)
-{
-	u32 val	= REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
-
-	REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val | BNX2X_GLOBAL_RESET_BIT);
-	barrier();
-	mmiowb();
-}
-
-/*
- * Clear the GLOBAL_RESET bit.
- *
- * Should be run under rtnl lock
- */
-static inline void bnx2x_clear_reset_global(struct bnx2x *bp)
-{
-	u32 val	= REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
-
-	REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~BNX2X_GLOBAL_RESET_BIT));
-	barrier();
-	mmiowb();
-}
-
-/*
- * Checks the GLOBAL_RESET bit.
- *
- * should be run under rtnl lock
- */
-static inline bool bnx2x_reset_is_global(struct bnx2x *bp)
-{
-	u32 val	= REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
-
-	DP(NETIF_MSG_HW, "GEN_REG_VAL=0x%08x\n", val);
-	return (val & BNX2X_GLOBAL_RESET_BIT) ? true : false;
-}
-
-/*
- * Clear RESET_IN_PROGRESS bit for the current engine.
- *
- * Should be run under rtnl lock
- */
-static inline void bnx2x_set_reset_done(struct bnx2x *bp)
-{
-	u32 val	= REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
-	u32 bit = BP_PATH(bp) ?
-		BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT;
-
-	/* Clear the bit */
-	val &= ~bit;
-	REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
-	barrier();
-	mmiowb();
-}
-
-/*
- * Set RESET_IN_PROGRESS for the current engine.
- *
- * should be run under rtnl lock
- */
-void bnx2x_set_reset_in_progress(struct bnx2x *bp)
-{
-	u32 val	= REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
-	u32 bit = BP_PATH(bp) ?
-		BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT;
-
-	/* Set the bit */
-	val |= bit;
-	REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
-	barrier();
-	mmiowb();
-}
-
-/*
- * Checks the RESET_IN_PROGRESS bit for the given engine.
- * should be run under rtnl lock
- */
-bool bnx2x_reset_is_done(struct bnx2x *bp, int engine)
-{
-	u32 val	= REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
-	u32 bit = engine ?
-		BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT;
-
-	/* return false if bit is set */
-	return (val & bit) ? false : true;
-}
-
-/*
- * Increment the load counter for the current engine.
- *
- * should be run under rtnl lock
- */
-void bnx2x_inc_load_cnt(struct bnx2x *bp)
-{
-	u32 val1, val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
-	u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
-			     BNX2X_PATH0_LOAD_CNT_MASK;
-	u32 shift = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_SHIFT :
-			     BNX2X_PATH0_LOAD_CNT_SHIFT;
-
-	DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val);
-
-	/* get the current counter value */
-	val1 = (val & mask) >> shift;
-
-	/* increment... */
-	val1++;
-
-	/* clear the old value */
-	val &= ~mask;
-
-	/* set the new one */
-	val |= ((val1 << shift) & mask);
-
-	REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
-	barrier();
-	mmiowb();
-}
-
-/**
- * bnx2x_dec_load_cnt - decrement the load counter
- *
- * @bp:		driver handle
- *
- * Should be run under rtnl lock.
- * Decrements the load counter for the current engine. Returns
- * the new counter value.
- */
-u32 bnx2x_dec_load_cnt(struct bnx2x *bp)
-{
-	u32 val1, val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
-	u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
-			     BNX2X_PATH0_LOAD_CNT_MASK;
-	u32 shift = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_SHIFT :
-			     BNX2X_PATH0_LOAD_CNT_SHIFT;
-
-	DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val);
-
-	/* get the current counter value */
-	val1 = (val & mask) >> shift;
-
-	/* decrement... */
-	val1--;
-
-	/* clear the old value */
-	val &= ~mask;
-
-	/* set the new one */
-	val |= ((val1 << shift) & mask);
-
-	REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
-	barrier();
-	mmiowb();
-
-	return val1;
-}
-
-/*
- * Read the load counter for the current engine.
- *
- * should be run under rtnl lock
- */
-static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp, int engine)
-{
-	u32 mask = (engine ? BNX2X_PATH1_LOAD_CNT_MASK :
-			     BNX2X_PATH0_LOAD_CNT_MASK);
-	u32 shift = (engine ? BNX2X_PATH1_LOAD_CNT_SHIFT :
-			     BNX2X_PATH0_LOAD_CNT_SHIFT);
-	u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
-
-	DP(NETIF_MSG_HW, "GLOB_REG=0x%08x\n", val);
-
-	val = (val & mask) >> shift;
-
-	DP(NETIF_MSG_HW, "load_cnt for engine %d = %d\n", engine, val);
-
-	return val;
-}
-
-/*
- * Reset the load counter for the current engine.
- *
- * should be run under rtnl lock
- */
-static inline void bnx2x_clear_load_cnt(struct bnx2x *bp)
-{
-	u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
-	u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
-			     BNX2X_PATH0_LOAD_CNT_MASK);
-
-	REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~mask));
-}
-
-static inline void _print_next_block(int idx, const char *blk)
-{
-	if (idx)
-		pr_cont(", ");
-	pr_cont("%s", blk);
-}
-
-static inline int bnx2x_check_blocks_with_parity0(u32 sig, int par_num,
-						  bool print)
-{
-	int i = 0;
-	u32 cur_bit = 0;
-	for (i = 0; sig; i++) {
-		cur_bit = ((u32)0x1 << i);
-		if (sig & cur_bit) {
-			switch (cur_bit) {
-			case AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "BRB");
-				break;
-			case AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "PARSER");
-				break;
-			case AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "TSDM");
-				break;
-			case AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++,
-							  "SEARCHER");
-				break;
-			case AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "TCM");
-				break;
-			case AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "TSEMI");
-				break;
-			case AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "XPB");
-				break;
-			}
-
-			/* Clear the bit */
-			sig &= ~cur_bit;
-		}
-	}
-
-	return par_num;
-}
-
-static inline int bnx2x_check_blocks_with_parity1(u32 sig, int par_num,
-						  bool *global, bool print)
-{
-	int i = 0;
-	u32 cur_bit = 0;
-	for (i = 0; sig; i++) {
-		cur_bit = ((u32)0x1 << i);
-		if (sig & cur_bit) {
-			switch (cur_bit) {
-			case AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "PBF");
-				break;
-			case AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "QM");
-				break;
-			case AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "TM");
-				break;
-			case AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "XSDM");
-				break;
-			case AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "XCM");
-				break;
-			case AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "XSEMI");
-				break;
-			case AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++,
-							  "DOORBELLQ");
-				break;
-			case AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "NIG");
-				break;
-			case AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++,
-							  "VAUX PCI CORE");
-				*global = true;
-				break;
-			case AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "DEBUG");
-				break;
-			case AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "USDM");
-				break;
-			case AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "UCM");
-				break;
-			case AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "USEMI");
-				break;
-			case AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "UPB");
-				break;
-			case AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "CSDM");
-				break;
-			case AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "CCM");
-				break;
-			}
-
-			/* Clear the bit */
-			sig &= ~cur_bit;
-		}
-	}
-
-	return par_num;
-}
-
-static inline int bnx2x_check_blocks_with_parity2(u32 sig, int par_num,
-						  bool print)
-{
-	int i = 0;
-	u32 cur_bit = 0;
-	for (i = 0; sig; i++) {
-		cur_bit = ((u32)0x1 << i);
-		if (sig & cur_bit) {
-			switch (cur_bit) {
-			case AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "CSEMI");
-				break;
-			case AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "PXP");
-				break;
-			case AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++,
-					"PXPPCICLOCKCLIENT");
-				break;
-			case AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "CFC");
-				break;
-			case AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "CDU");
-				break;
-			case AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "DMAE");
-				break;
-			case AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "IGU");
-				break;
-			case AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "MISC");
-				break;
-			}
-
-			/* Clear the bit */
-			sig &= ~cur_bit;
-		}
-	}
-
-	return par_num;
-}
-
-static inline int bnx2x_check_blocks_with_parity3(u32 sig, int par_num,
-						  bool *global, bool print)
-{
-	int i = 0;
-	u32 cur_bit = 0;
-	for (i = 0; sig; i++) {
-		cur_bit = ((u32)0x1 << i);
-		if (sig & cur_bit) {
-			switch (cur_bit) {
-			case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY:
-				if (print)
-					_print_next_block(par_num++, "MCP ROM");
-				*global = true;
-				break;
-			case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY:
-				if (print)
-					_print_next_block(par_num++,
-							  "MCP UMP RX");
-				*global = true;
-				break;
-			case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY:
-				if (print)
-					_print_next_block(par_num++,
-							  "MCP UMP TX");
-				*global = true;
-				break;
-			case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY:
-				if (print)
-					_print_next_block(par_num++,
-							  "MCP SCPAD");
-				*global = true;
-				break;
-			}
-
-			/* Clear the bit */
-			sig &= ~cur_bit;
-		}
-	}
-
-	return par_num;
-}
-
-static inline int bnx2x_check_blocks_with_parity4(u32 sig, int par_num,
-						  bool print)
-{
-	int i = 0;
-	u32 cur_bit = 0;
-	for (i = 0; sig; i++) {
-		cur_bit = ((u32)0x1 << i);
-		if (sig & cur_bit) {
-			switch (cur_bit) {
-			case AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "PGLUE_B");
-				break;
-			case AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++, "ATC");
-				break;
-			}
-
-			/* Clear the bit */
-			sig &= ~cur_bit;
-		}
-	}
-
-	return par_num;
-}
-
-static inline bool bnx2x_parity_attn(struct bnx2x *bp, bool *global, bool print,
-				     u32 *sig)
-{
-	if ((sig[0] & HW_PRTY_ASSERT_SET_0) ||
-	    (sig[1] & HW_PRTY_ASSERT_SET_1) ||
-	    (sig[2] & HW_PRTY_ASSERT_SET_2) ||
-	    (sig[3] & HW_PRTY_ASSERT_SET_3) ||
-	    (sig[4] & HW_PRTY_ASSERT_SET_4)) {
-		int par_num = 0;
-		DP(NETIF_MSG_HW, "Was parity error: HW block parity attention: "
-			"[0]:0x%08x [1]:0x%08x [2]:0x%08x [3]:0x%08x "
-			"[4]:0x%08x\n",
-			  sig[0] & HW_PRTY_ASSERT_SET_0,
-			  sig[1] & HW_PRTY_ASSERT_SET_1,
-			  sig[2] & HW_PRTY_ASSERT_SET_2,
-			  sig[3] & HW_PRTY_ASSERT_SET_3,
-			  sig[4] & HW_PRTY_ASSERT_SET_4);
-		if (print)
-			netdev_err(bp->dev,
-				   "Parity errors detected in blocks: ");
-		par_num = bnx2x_check_blocks_with_parity0(
-			sig[0] & HW_PRTY_ASSERT_SET_0, par_num, print);
-		par_num = bnx2x_check_blocks_with_parity1(
-			sig[1] & HW_PRTY_ASSERT_SET_1, par_num, global, print);
-		par_num = bnx2x_check_blocks_with_parity2(
-			sig[2] & HW_PRTY_ASSERT_SET_2, par_num, print);
-		par_num = bnx2x_check_blocks_with_parity3(
-			sig[3] & HW_PRTY_ASSERT_SET_3, par_num, global, print);
-		par_num = bnx2x_check_blocks_with_parity4(
-			sig[4] & HW_PRTY_ASSERT_SET_4, par_num, print);
-
-		if (print)
-			pr_cont("\n");
-
-		return true;
-	} else
-		return false;
-}
-
-/**
- * bnx2x_chk_parity_attn - checks for parity attentions.
- *
- * @bp:		driver handle
- * @global:	true if there was a global attention
- * @print:	show parity attention in syslog
- */
-bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print)
-{
-	struct attn_route attn = { {0} };
-	int port = BP_PORT(bp);
-
-	attn.sig[0] = REG_RD(bp,
-		MISC_REG_AEU_AFTER_INVERT_1_FUNC_0 +
-			     port*4);
-	attn.sig[1] = REG_RD(bp,
-		MISC_REG_AEU_AFTER_INVERT_2_FUNC_0 +
-			     port*4);
-	attn.sig[2] = REG_RD(bp,
-		MISC_REG_AEU_AFTER_INVERT_3_FUNC_0 +
-			     port*4);
-	attn.sig[3] = REG_RD(bp,
-		MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 +
-			     port*4);
-
-	if (!CHIP_IS_E1x(bp))
-		attn.sig[4] = REG_RD(bp,
-			MISC_REG_AEU_AFTER_INVERT_5_FUNC_0 +
-				     port*4);
-
-	return bnx2x_parity_attn(bp, global, print, attn.sig);
-}
-
-
-static inline void bnx2x_attn_int_deasserted4(struct bnx2x *bp, u32 attn)
-{
-	u32 val;
-	if (attn & AEU_INPUTS_ATTN_BITS_PGLUE_HW_INTERRUPT) {
-
-		val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS_CLR);
-		BNX2X_ERR("PGLUE hw attention 0x%x\n", val);
-		if (val & PGLUE_B_PGLUE_B_INT_STS_REG_ADDRESS_ERROR)
-			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
-				  "ADDRESS_ERROR\n");
-		if (val & PGLUE_B_PGLUE_B_INT_STS_REG_INCORRECT_RCV_BEHAVIOR)
-			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
-				  "INCORRECT_RCV_BEHAVIOR\n");
-		if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN)
-			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
-				  "WAS_ERROR_ATTN\n");
-		if (val & PGLUE_B_PGLUE_B_INT_STS_REG_VF_LENGTH_VIOLATION_ATTN)
-			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
-				  "VF_LENGTH_VIOLATION_ATTN\n");
-		if (val &
-		    PGLUE_B_PGLUE_B_INT_STS_REG_VF_GRC_SPACE_VIOLATION_ATTN)
-			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
-				  "VF_GRC_SPACE_VIOLATION_ATTN\n");
-		if (val &
-		    PGLUE_B_PGLUE_B_INT_STS_REG_VF_MSIX_BAR_VIOLATION_ATTN)
-			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
-				  "VF_MSIX_BAR_VIOLATION_ATTN\n");
-		if (val & PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_ERROR_ATTN)
-			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
-				  "TCPL_ERROR_ATTN\n");
-		if (val & PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_IN_TWO_RCBS_ATTN)
-			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
-				  "TCPL_IN_TWO_RCBS_ATTN\n");
-		if (val & PGLUE_B_PGLUE_B_INT_STS_REG_CSSNOOP_FIFO_OVERFLOW)
-			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
-				  "CSSNOOP_FIFO_OVERFLOW\n");
-	}
-	if (attn & AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT) {
-		val = REG_RD(bp, ATC_REG_ATC_INT_STS_CLR);
-		BNX2X_ERR("ATC hw attention 0x%x\n", val);
-		if (val & ATC_ATC_INT_STS_REG_ADDRESS_ERROR)
-			BNX2X_ERR("ATC_ATC_INT_STS_REG_ADDRESS_ERROR\n");
-		if (val & ATC_ATC_INT_STS_REG_ATC_TCPL_TO_NOT_PEND)
-			BNX2X_ERR("ATC_ATC_INT_STS_REG"
-				  "_ATC_TCPL_TO_NOT_PEND\n");
-		if (val & ATC_ATC_INT_STS_REG_ATC_GPA_MULTIPLE_HITS)
-			BNX2X_ERR("ATC_ATC_INT_STS_REG_"
-				  "ATC_GPA_MULTIPLE_HITS\n");
-		if (val & ATC_ATC_INT_STS_REG_ATC_RCPL_TO_EMPTY_CNT)
-			BNX2X_ERR("ATC_ATC_INT_STS_REG_"
-				  "ATC_RCPL_TO_EMPTY_CNT\n");
-		if (val & ATC_ATC_INT_STS_REG_ATC_TCPL_ERROR)
-			BNX2X_ERR("ATC_ATC_INT_STS_REG_ATC_TCPL_ERROR\n");
-		if (val & ATC_ATC_INT_STS_REG_ATC_IREQ_LESS_THAN_STU)
-			BNX2X_ERR("ATC_ATC_INT_STS_REG_"
-				  "ATC_IREQ_LESS_THAN_STU\n");
-	}
-
-	if (attn & (AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR |
-		    AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR)) {
-		BNX2X_ERR("FATAL parity attention set4 0x%x\n",
-		(u32)(attn & (AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR |
-		    AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR)));
-	}
-
-}
-
-static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
-{
-	struct attn_route attn, *group_mask;
-	int port = BP_PORT(bp);
-	int index;
-	u32 reg_addr;
-	u32 val;
-	u32 aeu_mask;
-	bool global = false;
-
-	/* need to take HW lock because MCP or other port might also
-	   try to handle this event */
-	bnx2x_acquire_alr(bp);
-
-	if (bnx2x_chk_parity_attn(bp, &global, true)) {
-#ifndef BNX2X_STOP_ON_ERROR
-		bp->recovery_state = BNX2X_RECOVERY_INIT;
-		schedule_delayed_work(&bp->sp_rtnl_task, 0);
-		/* Disable HW interrupts */
-		bnx2x_int_disable(bp);
-		/* In case of parity errors don't handle attentions so that
-		 * other function would "see" parity errors.
-		 */
-#else
-		bnx2x_panic();
-#endif
-		bnx2x_release_alr(bp);
-		return;
-	}
-
-	attn.sig[0] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_1_FUNC_0 + port*4);
-	attn.sig[1] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_2_FUNC_0 + port*4);
-	attn.sig[2] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_3_FUNC_0 + port*4);
-	attn.sig[3] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 + port*4);
-	if (!CHIP_IS_E1x(bp))
-		attn.sig[4] =
-		      REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_5_FUNC_0 + port*4);
-	else
-		attn.sig[4] = 0;
-
-	DP(NETIF_MSG_HW, "attn: %08x %08x %08x %08x %08x\n",
-	   attn.sig[0], attn.sig[1], attn.sig[2], attn.sig[3], attn.sig[4]);
-
-	for (index = 0; index < MAX_DYNAMIC_ATTN_GRPS; index++) {
-		if (deasserted & (1 << index)) {
-			group_mask = &bp->attn_group[index];
-
-			DP(NETIF_MSG_HW, "group[%d]: %08x %08x "
-					 "%08x %08x %08x\n",
-			   index,
-			   group_mask->sig[0], group_mask->sig[1],
-			   group_mask->sig[2], group_mask->sig[3],
-			   group_mask->sig[4]);
-
-			bnx2x_attn_int_deasserted4(bp,
-					attn.sig[4] & group_mask->sig[4]);
-			bnx2x_attn_int_deasserted3(bp,
-					attn.sig[3] & group_mask->sig[3]);
-			bnx2x_attn_int_deasserted1(bp,
-					attn.sig[1] & group_mask->sig[1]);
-			bnx2x_attn_int_deasserted2(bp,
-					attn.sig[2] & group_mask->sig[2]);
-			bnx2x_attn_int_deasserted0(bp,
-					attn.sig[0] & group_mask->sig[0]);
-		}
-	}
-
-	bnx2x_release_alr(bp);
-
-	if (bp->common.int_block == INT_BLOCK_HC)
-		reg_addr = (HC_REG_COMMAND_REG + port*32 +
-			    COMMAND_REG_ATTN_BITS_CLR);
-	else
-		reg_addr = (BAR_IGU_INTMEM + IGU_CMD_ATTN_BIT_CLR_UPPER*8);
-
-	val = ~deasserted;
-	DP(NETIF_MSG_HW, "about to mask 0x%08x at %s addr 0x%x\n", val,
-	   (bp->common.int_block == INT_BLOCK_HC) ? "HC" : "IGU", reg_addr);
-	REG_WR(bp, reg_addr, val);
-
-	if (~bp->attn_state & deasserted)
-		BNX2X_ERR("IGU ERROR\n");
-
-	reg_addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
-			  MISC_REG_AEU_MASK_ATTN_FUNC_0;
-
-	bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_PORT0_ATT_MASK + port);
-	aeu_mask = REG_RD(bp, reg_addr);
-
-	DP(NETIF_MSG_HW, "aeu_mask %x  newly deasserted %x\n",
-	   aeu_mask, deasserted);
-	aeu_mask |= (deasserted & 0x3ff);
-	DP(NETIF_MSG_HW, "new mask %x\n", aeu_mask);
-
-	REG_WR(bp, reg_addr, aeu_mask);
-	bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_PORT0_ATT_MASK + port);
-
-	DP(NETIF_MSG_HW, "attn_state %x\n", bp->attn_state);
-	bp->attn_state &= ~deasserted;
-	DP(NETIF_MSG_HW, "new state %x\n", bp->attn_state);
-}
-
-static void bnx2x_attn_int(struct bnx2x *bp)
-{
-	/* read local copy of bits */
-	u32 attn_bits = le32_to_cpu(bp->def_status_blk->atten_status_block.
-								attn_bits);
-	u32 attn_ack = le32_to_cpu(bp->def_status_blk->atten_status_block.
-								attn_bits_ack);
-	u32 attn_state = bp->attn_state;
-
-	/* look for changed bits */
-	u32 asserted   =  attn_bits & ~attn_ack & ~attn_state;
-	u32 deasserted = ~attn_bits &  attn_ack &  attn_state;
-
-	DP(NETIF_MSG_HW,
-	   "attn_bits %x  attn_ack %x  asserted %x  deasserted %x\n",
-	   attn_bits, attn_ack, asserted, deasserted);
-
-	if (~(attn_bits ^ attn_ack) & (attn_bits ^ attn_state))
-		BNX2X_ERR("BAD attention state\n");
-
-	/* handle bits that were raised */
-	if (asserted)
-		bnx2x_attn_int_asserted(bp, asserted);
-
-	if (deasserted)
-		bnx2x_attn_int_deasserted(bp, deasserted);
-}
-
-void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment,
-		      u16 index, u8 op, u8 update)
-{
-	u32 igu_addr = BAR_IGU_INTMEM + (IGU_CMD_INT_ACK_BASE + igu_sb_id)*8;
-
-	bnx2x_igu_ack_sb_gen(bp, igu_sb_id, segment, index, op, update,
-			     igu_addr);
-}
-
-static inline void bnx2x_update_eq_prod(struct bnx2x *bp, u16 prod)
-{
-	/* No memory barriers */
-	storm_memset_eq_prod(bp, prod, BP_FUNC(bp));
-	mmiowb(); /* keep prod updates ordered */
-}
-
-#ifdef BCM_CNIC
-static int  bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid,
-				      union event_ring_elem *elem)
-{
-	u8 err = elem->message.error;
-
-	if (!bp->cnic_eth_dev.starting_cid  ||
-	    (cid < bp->cnic_eth_dev.starting_cid &&
-	    cid != bp->cnic_eth_dev.iscsi_l2_cid))
-		return 1;
-
-	DP(BNX2X_MSG_SP, "got delete ramrod for CNIC CID %d\n", cid);
-
-	if (unlikely(err)) {
-
-		BNX2X_ERR("got delete ramrod for CNIC CID %d with error!\n",
-			  cid);
-		bnx2x_panic_dump(bp);
-	}
-	bnx2x_cnic_cfc_comp(bp, cid, err);
-	return 0;
-}
-#endif
-
-static inline void bnx2x_handle_mcast_eqe(struct bnx2x *bp)
-{
-	struct bnx2x_mcast_ramrod_params rparam;
-	int rc;
-
-	memset(&rparam, 0, sizeof(rparam));
-
-	rparam.mcast_obj = &bp->mcast_obj;
-
-	netif_addr_lock_bh(bp->dev);
-
-	/* Clear pending state for the last command */
-	bp->mcast_obj.raw.clear_pending(&bp->mcast_obj.raw);
-
-	/* If there are pending mcast commands - send them */
-	if (bp->mcast_obj.check_pending(&bp->mcast_obj)) {
-		rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_CONT);
-		if (rc < 0)
-			BNX2X_ERR("Failed to send pending mcast commands: %d\n",
-				  rc);
-	}
-
-	netif_addr_unlock_bh(bp->dev);
-}
-
-static inline void bnx2x_handle_classification_eqe(struct bnx2x *bp,
-						   union event_ring_elem *elem)
-{
-	unsigned long ramrod_flags = 0;
-	int rc = 0;
-	u32 cid = elem->message.data.eth_event.echo & BNX2X_SWCID_MASK;
-	struct bnx2x_vlan_mac_obj *vlan_mac_obj;
-
-	/* Always push next commands out, don't wait here */
-	__set_bit(RAMROD_CONT, &ramrod_flags);
-
-	switch (elem->message.data.eth_event.echo >> BNX2X_SWCID_SHIFT) {
-	case BNX2X_FILTER_MAC_PENDING:
-#ifdef BCM_CNIC
-		if (cid == BNX2X_ISCSI_ETH_CID)
-			vlan_mac_obj = &bp->iscsi_l2_mac_obj;
-		else
-#endif
-			vlan_mac_obj = &bp->fp[cid].mac_obj;
-
-		break;
-		vlan_mac_obj = &bp->fp[cid].mac_obj;
-
-	case BNX2X_FILTER_MCAST_PENDING:
-		/* This is only relevant for 57710 where multicast MACs are
-		 * configured as unicast MACs using the same ramrod.
-		 */
-		bnx2x_handle_mcast_eqe(bp);
-		return;
-	default:
-		BNX2X_ERR("Unsupported classification command: %d\n",
-			  elem->message.data.eth_event.echo);
-		return;
-	}
-
-	rc = vlan_mac_obj->complete(bp, vlan_mac_obj, elem, &ramrod_flags);
-
-	if (rc < 0)
-		BNX2X_ERR("Failed to schedule new commands: %d\n", rc);
-	else if (rc > 0)
-		DP(BNX2X_MSG_SP, "Scheduled next pending commands...\n");
-
-}
-
-#ifdef BCM_CNIC
-static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start);
-#endif
-
-static inline void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp)
-{
-	netif_addr_lock_bh(bp->dev);
-
-	clear_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state);
-
-	/* Send rx_mode command again if was requested */
-	if (test_and_clear_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state))
-		bnx2x_set_storm_rx_mode(bp);
-#ifdef BCM_CNIC
-	else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED,
-				    &bp->sp_state))
-		bnx2x_set_iscsi_eth_rx_mode(bp, true);
-	else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED,
-				    &bp->sp_state))
-		bnx2x_set_iscsi_eth_rx_mode(bp, false);
-#endif
-
-	netif_addr_unlock_bh(bp->dev);
-}
-
-static inline struct bnx2x_queue_sp_obj *bnx2x_cid_to_q_obj(
-	struct bnx2x *bp, u32 cid)
-{
-	DP(BNX2X_MSG_SP, "retrieving fp from cid %d", cid);
-#ifdef BCM_CNIC
-	if (cid == BNX2X_FCOE_ETH_CID)
-		return &bnx2x_fcoe(bp, q_obj);
-	else
-#endif
-		return &bnx2x_fp(bp, CID_TO_FP(cid), q_obj);
-}
-
-static void bnx2x_eq_int(struct bnx2x *bp)
-{
-	u16 hw_cons, sw_cons, sw_prod;
-	union event_ring_elem *elem;
-	u32 cid;
-	u8 opcode;
-	int spqe_cnt = 0;
-	struct bnx2x_queue_sp_obj *q_obj;
-	struct bnx2x_func_sp_obj *f_obj = &bp->func_obj;
-	struct bnx2x_raw_obj *rss_raw = &bp->rss_conf_obj.raw;
-
-	hw_cons = le16_to_cpu(*bp->eq_cons_sb);
-
-	/* The hw_cos range is 1-255, 257 - the sw_cons range is 0-254, 256.
-	 * when we get the the next-page we nned to adjust so the loop
-	 * condition below will be met. The next element is the size of a
-	 * regular element and hence incrementing by 1
-	 */
-	if ((hw_cons & EQ_DESC_MAX_PAGE) == EQ_DESC_MAX_PAGE)
-		hw_cons++;
-
-	/* 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->eq_spq_left %x\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)) {
-
-
-		elem = &bp->eq_ring[EQ_DESC(sw_cons)];
-
-		cid = SW_CID(elem->message.data.cfc_del_event.cid);
-		opcode = elem->message.opcode;
-
-
-		/* handle eq element */
-		switch (opcode) {
-		case EVENT_RING_OPCODE_STAT_QUERY:
-			DP(NETIF_MSG_TIMER, "got statistics comp event %d\n",
-			   bp->stats_comp++);
-			/* nothing to do with stats comp */
-			goto next_spqe;
-
-		case EVENT_RING_OPCODE_CFC_DEL:
-			/* handle according to cid range */
-			/*
-			 * we may want to verify here that the bp state is
-			 * HALTING
-			 */
-			DP(BNX2X_MSG_SP,
-			   "got delete ramrod for MULTI[%d]\n", cid);
-#ifdef BCM_CNIC
-			if (!bnx2x_cnic_handle_cfc_del(bp, cid, elem))
-				goto next_spqe;
-#endif
-			q_obj = bnx2x_cid_to_q_obj(bp, cid);
-
-			if (q_obj->complete_cmd(bp, q_obj, BNX2X_Q_CMD_CFC_DEL))
-				break;
-
-
-
-			goto next_spqe;
-
-		case EVENT_RING_OPCODE_STOP_TRAFFIC:
-			DP(BNX2X_MSG_SP, "got STOP TRAFFIC\n");
-			if (f_obj->complete_cmd(bp, f_obj,
-						BNX2X_F_CMD_TX_STOP))
-				break;
-			bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_PAUSED);
-			goto next_spqe;
-
-		case EVENT_RING_OPCODE_START_TRAFFIC:
-			DP(BNX2X_MSG_SP, "got START TRAFFIC\n");
-			if (f_obj->complete_cmd(bp, f_obj,
-						BNX2X_F_CMD_TX_START))
-				break;
-			bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_RELEASED);
-			goto next_spqe;
-		case EVENT_RING_OPCODE_FUNCTION_START:
-			DP(BNX2X_MSG_SP, "got FUNC_START ramrod\n");
-			if (f_obj->complete_cmd(bp, f_obj, BNX2X_F_CMD_START))
-				break;
-
-			goto next_spqe;
-
-		case EVENT_RING_OPCODE_FUNCTION_STOP:
-			DP(BNX2X_MSG_SP, "got FUNC_STOP ramrod\n");
-			if (f_obj->complete_cmd(bp, f_obj, BNX2X_F_CMD_STOP))
-				break;
-
-			goto next_spqe;
-		}
-
-		switch (opcode | bp->state) {
-		case (EVENT_RING_OPCODE_RSS_UPDATE_RULES |
-		      BNX2X_STATE_OPEN):
-		case (EVENT_RING_OPCODE_RSS_UPDATE_RULES |
-		      BNX2X_STATE_OPENING_WAIT4_PORT):
-			cid = elem->message.data.eth_event.echo &
-				BNX2X_SWCID_MASK;
-			DP(BNX2X_MSG_SP, "got RSS_UPDATE ramrod. CID %d\n",
-			   cid);
-			rss_raw->clear_pending(rss_raw);
-			break;
-
-		case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_OPEN):
-		case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_DIAG):
-		case (EVENT_RING_OPCODE_SET_MAC |
-		      BNX2X_STATE_CLOSING_WAIT4_HALT):
-		case (EVENT_RING_OPCODE_CLASSIFICATION_RULES |
-		      BNX2X_STATE_OPEN):
-		case (EVENT_RING_OPCODE_CLASSIFICATION_RULES |
-		      BNX2X_STATE_DIAG):
-		case (EVENT_RING_OPCODE_CLASSIFICATION_RULES |
-		      BNX2X_STATE_CLOSING_WAIT4_HALT):
-			DP(BNX2X_MSG_SP, "got (un)set mac ramrod\n");
-			bnx2x_handle_classification_eqe(bp, elem);
-			break;
-
-		case (EVENT_RING_OPCODE_MULTICAST_RULES |
-		      BNX2X_STATE_OPEN):
-		case (EVENT_RING_OPCODE_MULTICAST_RULES |
-		      BNX2X_STATE_DIAG):
-		case (EVENT_RING_OPCODE_MULTICAST_RULES |
-		      BNX2X_STATE_CLOSING_WAIT4_HALT):
-			DP(BNX2X_MSG_SP, "got mcast ramrod\n");
-			bnx2x_handle_mcast_eqe(bp);
-			break;
-
-		case (EVENT_RING_OPCODE_FILTERS_RULES |
-		      BNX2X_STATE_OPEN):
-		case (EVENT_RING_OPCODE_FILTERS_RULES |
-		      BNX2X_STATE_DIAG):
-		case (EVENT_RING_OPCODE_FILTERS_RULES |
-		      BNX2X_STATE_CLOSING_WAIT4_HALT):
-			DP(BNX2X_MSG_SP, "got rx_mode ramrod\n");
-			bnx2x_handle_rx_mode_eqe(bp);
-			break;
-		default:
-			/* unknown event log error and continue */
-			BNX2X_ERR("Unknown EQ event %d, bp->state 0x%x\n",
-				  elem->message.opcode, bp->state);
-		}
-next_spqe:
-		spqe_cnt++;
-	} /* for */
-
-	smp_mb__before_atomic_inc();
-	atomic_add(spqe_cnt, &bp->eq_spq_left);
-
-	bp->eq_cons = sw_cons;
-	bp->eq_prod = sw_prod;
-	/* Make sure that above mem writes were issued towards the memory */
-	smp_wmb();
-
-	/* update producer */
-	bnx2x_update_eq_prod(bp, bp->eq_prod);
-}
-
-static void bnx2x_sp_task(struct work_struct *work)
-{
-	struct bnx2x *bp = container_of(work, struct bnx2x, sp_task.work);
-	u16 status;
-
-	status = bnx2x_update_dsb_idx(bp);
-/*	if (status == 0)				     */
-/*		BNX2X_ERR("spurious slowpath interrupt!\n"); */
-
-	DP(NETIF_MSG_INTR, "got a slowpath interrupt (status 0x%x)\n", status);
-
-	/* HW attentions */
-	if (status & BNX2X_DEF_SB_ATT_IDX) {
-		bnx2x_attn_int(bp);
-		status &= ~BNX2X_DEF_SB_ATT_IDX;
-	}
-
-	/* SP events: STAT_QUERY and others */
-	if (status & BNX2X_DEF_SB_IDX) {
-#ifdef BCM_CNIC
-		struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
-
-		if ((!NO_FCOE(bp)) &&
-			(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
-			/*
-			 * Prevent local bottom-halves from running as
-			 * we are going to change the local NAPI list.
-			 */
-			local_bh_disable();
-			napi_schedule(&bnx2x_fcoe(bp, napi));
-			local_bh_enable();
-		}
-#endif
-		/* Handle EQ completions */
-		bnx2x_eq_int(bp);
-
-		bnx2x_ack_sb(bp, bp->igu_dsb_id, USTORM_ID,
-			le16_to_cpu(bp->def_idx), IGU_INT_NOP, 1);
-
-		status &= ~BNX2X_DEF_SB_IDX;
-	}
-
-	if (unlikely(status))
-		DP(NETIF_MSG_INTR, "got an unknown interrupt! (status 0x%x)\n",
-		   status);
-
-	bnx2x_ack_sb(bp, bp->igu_dsb_id, ATTENTION_ID,
-	     le16_to_cpu(bp->def_att_idx), IGU_INT_ENABLE, 1);
-}
-
-irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
-{
-	struct net_device *dev = dev_instance;
-	struct bnx2x *bp = netdev_priv(dev);
-
-	bnx2x_ack_sb(bp, bp->igu_dsb_id, USTORM_ID, 0,
-		     IGU_INT_DISABLE, 0);
-
-#ifdef BNX2X_STOP_ON_ERROR
-	if (unlikely(bp->panic))
-		return IRQ_HANDLED;
-#endif
-
-#ifdef BCM_CNIC
-	{
-		struct cnic_ops *c_ops;
-
-		rcu_read_lock();
-		c_ops = rcu_dereference(bp->cnic_ops);
-		if (c_ops)
-			c_ops->cnic_handler(bp->cnic_data, NULL);
-		rcu_read_unlock();
-	}
-#endif
-	queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
-
-	return IRQ_HANDLED;
-}
-
-/* end of slow path */
-
-
-void bnx2x_drv_pulse(struct bnx2x *bp)
-{
-	SHMEM_WR(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb,
-		 bp->fw_drv_pulse_wr_seq);
-}
-
-
-static void bnx2x_timer(unsigned long data)
-{
-	u8 cos;
-	struct bnx2x *bp = (struct bnx2x *) data;
-
-	if (!netif_running(bp->dev))
-		return;
-
-	if (poll) {
-		struct bnx2x_fastpath *fp = &bp->fp[0];
-
-		for_each_cos_in_tx_queue(fp, cos)
-			bnx2x_tx_int(bp, &fp->txdata[cos]);
-		bnx2x_rx_int(fp, 1000);
-	}
-
-	if (!BP_NOMCP(bp)) {
-		int mb_idx = BP_FW_MB_IDX(bp);
-		u32 drv_pulse;
-		u32 mcp_pulse;
-
-		++bp->fw_drv_pulse_wr_seq;
-		bp->fw_drv_pulse_wr_seq &= DRV_PULSE_SEQ_MASK;
-		/* TBD - add SYSTEM_TIME */
-		drv_pulse = bp->fw_drv_pulse_wr_seq;
-		bnx2x_drv_pulse(bp);
-
-		mcp_pulse = (SHMEM_RD(bp, func_mb[mb_idx].mcp_pulse_mb) &
-			     MCP_PULSE_SEQ_MASK);
-		/* The delta between driver pulse and mcp response
-		 * should be 1 (before mcp response) or 0 (after mcp response)
-		 */
-		if ((drv_pulse != mcp_pulse) &&
-		    (drv_pulse != ((mcp_pulse + 1) & MCP_PULSE_SEQ_MASK))) {
-			/* someone lost a heartbeat... */
-			BNX2X_ERR("drv_pulse (0x%x) != mcp_pulse (0x%x)\n",
-				  drv_pulse, mcp_pulse);
-		}
-	}
-
-	if (bp->state == BNX2X_STATE_OPEN)
-		bnx2x_stats_handle(bp, STATS_EVENT_UPDATE);
-
-	mod_timer(&bp->timer, jiffies + bp->current_interval);
-}
-
-/* end of Statistics */
-
-/* nic init */
-
-/*
- * nic init service functions
- */
-
-static inline void bnx2x_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
-{
-	u32 i;
-	if (!(len%4) && !(addr%4))
-		for (i = 0; i < len; i += 4)
-			REG_WR(bp, addr + i, fill);
-	else
-		for (i = 0; i < len; i++)
-			REG_WR8(bp, addr + i, fill);
-
-}
-
-/* helper: writes FP SP data to FW - data_size in dwords */
-static inline void bnx2x_wr_fp_sb_data(struct bnx2x *bp,
-				       int fw_sb_id,
-				       u32 *sb_data_p,
-				       u32 data_size)
-{
-	int index;
-	for (index = 0; index < data_size; index++)
-		REG_WR(bp, BAR_CSTRORM_INTMEM +
-			CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id) +
-			sizeof(u32)*index,
-			*(sb_data_p + index));
-}
-
-static inline void bnx2x_zero_fp_sb(struct bnx2x *bp, int fw_sb_id)
-{
-	u32 *sb_data_p;
-	u32 data_size = 0;
-	struct hc_status_block_data_e2 sb_data_e2;
-	struct hc_status_block_data_e1x sb_data_e1x;
-
-	/* disable the function first */
-	if (!CHIP_IS_E1x(bp)) {
-		memset(&sb_data_e2, 0, sizeof(struct hc_status_block_data_e2));
-		sb_data_e2.common.state = SB_DISABLED;
-		sb_data_e2.common.p_func.vf_valid = false;
-		sb_data_p = (u32 *)&sb_data_e2;
-		data_size = sizeof(struct hc_status_block_data_e2)/sizeof(u32);
-	} else {
-		memset(&sb_data_e1x, 0,
-		       sizeof(struct hc_status_block_data_e1x));
-		sb_data_e1x.common.state = SB_DISABLED;
-		sb_data_e1x.common.p_func.vf_valid = false;
-		sb_data_p = (u32 *)&sb_data_e1x;
-		data_size = sizeof(struct hc_status_block_data_e1x)/sizeof(u32);
-	}
-	bnx2x_wr_fp_sb_data(bp, fw_sb_id, sb_data_p, data_size);
-
-	bnx2x_fill(bp, BAR_CSTRORM_INTMEM +
-			CSTORM_STATUS_BLOCK_OFFSET(fw_sb_id), 0,
-			CSTORM_STATUS_BLOCK_SIZE);
-	bnx2x_fill(bp, BAR_CSTRORM_INTMEM +
-			CSTORM_SYNC_BLOCK_OFFSET(fw_sb_id), 0,
-			CSTORM_SYNC_BLOCK_SIZE);
-}
-
-/* helper:  writes SP SB data to FW */
-static inline void bnx2x_wr_sp_sb_data(struct bnx2x *bp,
-		struct hc_sp_status_block_data *sp_sb_data)
-{
-	int func = BP_FUNC(bp);
-	int i;
-	for (i = 0; i < sizeof(struct hc_sp_status_block_data)/sizeof(u32); i++)
-		REG_WR(bp, BAR_CSTRORM_INTMEM +
-			CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
-			i*sizeof(u32),
-			*((u32 *)sp_sb_data + i));
-}
-
-static inline void bnx2x_zero_sp_sb(struct bnx2x *bp)
-{
-	int func = BP_FUNC(bp);
-	struct hc_sp_status_block_data sp_sb_data;
-	memset(&sp_sb_data, 0, sizeof(struct hc_sp_status_block_data));
-
-	sp_sb_data.state = SB_DISABLED;
-	sp_sb_data.p_func.vf_valid = false;
-
-	bnx2x_wr_sp_sb_data(bp, &sp_sb_data);
-
-	bnx2x_fill(bp, BAR_CSTRORM_INTMEM +
-			CSTORM_SP_STATUS_BLOCK_OFFSET(func), 0,
-			CSTORM_SP_STATUS_BLOCK_SIZE);
-	bnx2x_fill(bp, BAR_CSTRORM_INTMEM +
-			CSTORM_SP_SYNC_BLOCK_OFFSET(func), 0,
-			CSTORM_SP_SYNC_BLOCK_SIZE);
-
-}
-
-
-static inline
-void bnx2x_setup_ndsb_state_machine(struct hc_status_block_sm *hc_sm,
-					   int igu_sb_id, int igu_seg_id)
-{
-	hc_sm->igu_sb_id = igu_sb_id;
-	hc_sm->igu_seg_id = igu_seg_id;
-	hc_sm->timer_value = 0xFF;
-	hc_sm->time_to_expire = 0xFFFFFFFF;
-}
-
-
-/* allocates state machine ids. */
-static inline
-void bnx2x_map_sb_state_machines(struct hc_index_data *index_data)
-{
-	/* zero out state machine indices */
-	/* rx indices */
-	index_data[HC_INDEX_ETH_RX_CQ_CONS].flags &= ~HC_INDEX_DATA_SM_ID;
-
-	/* tx indices */
-	index_data[HC_INDEX_OOO_TX_CQ_CONS].flags &= ~HC_INDEX_DATA_SM_ID;
-	index_data[HC_INDEX_ETH_TX_CQ_CONS_COS0].flags &= ~HC_INDEX_DATA_SM_ID;
-	index_data[HC_INDEX_ETH_TX_CQ_CONS_COS1].flags &= ~HC_INDEX_DATA_SM_ID;
-	index_data[HC_INDEX_ETH_TX_CQ_CONS_COS2].flags &= ~HC_INDEX_DATA_SM_ID;
-
-	/* map indices */
-	/* rx indices */
-	index_data[HC_INDEX_ETH_RX_CQ_CONS].flags |=
-		SM_RX_ID << HC_INDEX_DATA_SM_ID_SHIFT;
-
-	/* tx indices */
-	index_data[HC_INDEX_OOO_TX_CQ_CONS].flags |=
-		SM_TX_ID << HC_INDEX_DATA_SM_ID_SHIFT;
-	index_data[HC_INDEX_ETH_TX_CQ_CONS_COS0].flags |=
-		SM_TX_ID << HC_INDEX_DATA_SM_ID_SHIFT;
-	index_data[HC_INDEX_ETH_TX_CQ_CONS_COS1].flags |=
-		SM_TX_ID << HC_INDEX_DATA_SM_ID_SHIFT;
-	index_data[HC_INDEX_ETH_TX_CQ_CONS_COS2].flags |=
-		SM_TX_ID << HC_INDEX_DATA_SM_ID_SHIFT;
-}
-
-static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid,
-			  u8 vf_valid, int fw_sb_id, int igu_sb_id)
-{
-	int igu_seg_id;
-
-	struct hc_status_block_data_e2 sb_data_e2;
-	struct hc_status_block_data_e1x sb_data_e1x;
-	struct hc_status_block_sm  *hc_sm_p;
-	int data_size;
-	u32 *sb_data_p;
-
-	if (CHIP_INT_MODE_IS_BC(bp))
-		igu_seg_id = HC_SEG_ACCESS_NORM;
-	else
-		igu_seg_id = IGU_SEG_ACCESS_NORM;
-
-	bnx2x_zero_fp_sb(bp, fw_sb_id);
-
-	if (!CHIP_IS_E1x(bp)) {
-		memset(&sb_data_e2, 0, sizeof(struct hc_status_block_data_e2));
-		sb_data_e2.common.state = SB_ENABLED;
-		sb_data_e2.common.p_func.pf_id = BP_FUNC(bp);
-		sb_data_e2.common.p_func.vf_id = vfid;
-		sb_data_e2.common.p_func.vf_valid = vf_valid;
-		sb_data_e2.common.p_func.vnic_id = BP_VN(bp);
-		sb_data_e2.common.same_igu_sb_1b = true;
-		sb_data_e2.common.host_sb_addr.hi = U64_HI(mapping);
-		sb_data_e2.common.host_sb_addr.lo = U64_LO(mapping);
-		hc_sm_p = sb_data_e2.common.state_machine;
-		sb_data_p = (u32 *)&sb_data_e2;
-		data_size = sizeof(struct hc_status_block_data_e2)/sizeof(u32);
-		bnx2x_map_sb_state_machines(sb_data_e2.index_data);
-	} else {
-		memset(&sb_data_e1x, 0,
-		       sizeof(struct hc_status_block_data_e1x));
-		sb_data_e1x.common.state = SB_ENABLED;
-		sb_data_e1x.common.p_func.pf_id = BP_FUNC(bp);
-		sb_data_e1x.common.p_func.vf_id = 0xff;
-		sb_data_e1x.common.p_func.vf_valid = false;
-		sb_data_e1x.common.p_func.vnic_id = BP_VN(bp);
-		sb_data_e1x.common.same_igu_sb_1b = true;
-		sb_data_e1x.common.host_sb_addr.hi = U64_HI(mapping);
-		sb_data_e1x.common.host_sb_addr.lo = U64_LO(mapping);
-		hc_sm_p = sb_data_e1x.common.state_machine;
-		sb_data_p = (u32 *)&sb_data_e1x;
-		data_size = sizeof(struct hc_status_block_data_e1x)/sizeof(u32);
-		bnx2x_map_sb_state_machines(sb_data_e1x.index_data);
-	}
-
-	bnx2x_setup_ndsb_state_machine(&hc_sm_p[SM_RX_ID],
-				       igu_sb_id, igu_seg_id);
-	bnx2x_setup_ndsb_state_machine(&hc_sm_p[SM_TX_ID],
-				       igu_sb_id, igu_seg_id);
-
-	DP(NETIF_MSG_HW, "Init FW SB %d\n", fw_sb_id);
-
-	/* write indecies to HW */
-	bnx2x_wr_fp_sb_data(bp, fw_sb_id, sb_data_p, data_size);
-}
-
-static void bnx2x_update_coalesce_sb(struct bnx2x *bp, u8 fw_sb_id,
-				     u16 tx_usec, u16 rx_usec)
-{
-	bnx2x_update_coalesce_sb_index(bp, fw_sb_id, HC_INDEX_ETH_RX_CQ_CONS,
-				    false, rx_usec);
-	bnx2x_update_coalesce_sb_index(bp, fw_sb_id,
-				       HC_INDEX_ETH_TX_CQ_CONS_COS0, false,
-				       tx_usec);
-	bnx2x_update_coalesce_sb_index(bp, fw_sb_id,
-				       HC_INDEX_ETH_TX_CQ_CONS_COS1, false,
-				       tx_usec);
-	bnx2x_update_coalesce_sb_index(bp, fw_sb_id,
-				       HC_INDEX_ETH_TX_CQ_CONS_COS2, false,
-				       tx_usec);
-}
-
-static void bnx2x_init_def_sb(struct bnx2x *bp)
-{
-	struct host_sp_status_block *def_sb = bp->def_status_blk;
-	dma_addr_t mapping = bp->def_status_blk_mapping;
-	int igu_sp_sb_index;
-	int igu_seg_id;
-	int port = BP_PORT(bp);
-	int func = BP_FUNC(bp);
-	int reg_offset, reg_offset_en5;
-	u64 section;
-	int index;
-	struct hc_sp_status_block_data sp_sb_data;
-	memset(&sp_sb_data, 0, sizeof(struct hc_sp_status_block_data));
-
-	if (CHIP_INT_MODE_IS_BC(bp)) {
-		igu_sp_sb_index = DEF_SB_IGU_ID;
-		igu_seg_id = HC_SEG_ACCESS_DEF;
-	} else {
-		igu_sp_sb_index = bp->igu_dsb_id;
-		igu_seg_id = IGU_SEG_ACCESS_DEF;
-	}
-
-	/* ATTN */
-	section = ((u64)mapping) + offsetof(struct host_sp_status_block,
-					    atten_status_block);
-	def_sb->atten_status_block.status_block_id = igu_sp_sb_index;
-
-	bp->attn_state = 0;
-
-	reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
-			     MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
-	reg_offset_en5 = (port ? MISC_REG_AEU_ENABLE5_FUNC_1_OUT_0 :
-				 MISC_REG_AEU_ENABLE5_FUNC_0_OUT_0);
-	for (index = 0; index < MAX_DYNAMIC_ATTN_GRPS; index++) {
-		int sindex;
-		/* take care of sig[0]..sig[4] */
-		for (sindex = 0; sindex < 4; sindex++)
-			bp->attn_group[index].sig[sindex] =
-			   REG_RD(bp, reg_offset + sindex*0x4 + 0x10*index);
-
-		if (!CHIP_IS_E1x(bp))
-			/*
-			 * enable5 is separate from the rest of the registers,
-			 * and therefore the address skip is 4
-			 * and not 16 between the different groups
-			 */
-			bp->attn_group[index].sig[4] = REG_RD(bp,
-					reg_offset_en5 + 0x4*index);
-		else
-			bp->attn_group[index].sig[4] = 0;
-	}
-
-	if (bp->common.int_block == INT_BLOCK_HC) {
-		reg_offset = (port ? HC_REG_ATTN_MSG1_ADDR_L :
-				     HC_REG_ATTN_MSG0_ADDR_L);
-
-		REG_WR(bp, reg_offset, U64_LO(section));
-		REG_WR(bp, reg_offset + 4, U64_HI(section));
-	} else if (!CHIP_IS_E1x(bp)) {
-		REG_WR(bp, IGU_REG_ATTN_MSG_ADDR_L, U64_LO(section));
-		REG_WR(bp, IGU_REG_ATTN_MSG_ADDR_H, U64_HI(section));
-	}
-
-	section = ((u64)mapping) + offsetof(struct host_sp_status_block,
-					    sp_sb);
-
-	bnx2x_zero_sp_sb(bp);
-
-	sp_sb_data.state		= SB_ENABLED;
-	sp_sb_data.host_sb_addr.lo	= U64_LO(section);
-	sp_sb_data.host_sb_addr.hi	= U64_HI(section);
-	sp_sb_data.igu_sb_id		= igu_sp_sb_index;
-	sp_sb_data.igu_seg_id		= igu_seg_id;
-	sp_sb_data.p_func.pf_id		= func;
-	sp_sb_data.p_func.vnic_id	= BP_VN(bp);
-	sp_sb_data.p_func.vf_id		= 0xff;
-
-	bnx2x_wr_sp_sb_data(bp, &sp_sb_data);
-
-	bnx2x_ack_sb(bp, bp->igu_dsb_id, USTORM_ID, 0, IGU_INT_ENABLE, 0);
-}
-
-void bnx2x_update_coalesce(struct bnx2x *bp)
-{
-	int i;
-
-	for_each_eth_queue(bp, i)
-		bnx2x_update_coalesce_sb(bp, bp->fp[i].fw_sb_id,
-					 bp->tx_ticks, bp->rx_ticks);
-}
-
-static void bnx2x_init_sp_ring(struct bnx2x *bp)
-{
-	spin_lock_init(&bp->spq_lock);
-	atomic_set(&bp->cq_spq_left, MAX_SPQ_PENDING);
-
-	bp->spq_prod_idx = 0;
-	bp->dsb_sp_prod = BNX2X_SP_DSB_INDEX;
-	bp->spq_prod_bd = bp->spq;
-	bp->spq_last_bd = bp->spq_prod_bd + MAX_SP_DESC_CNT;
-}
-
-static void bnx2x_init_eq_ring(struct bnx2x *bp)
-{
-	int i;
-	for (i = 1; i <= NUM_EQ_PAGES; i++) {
-		union event_ring_elem *elem =
-			&bp->eq_ring[EQ_DESC_CNT_PAGE * i - 1];
-
-		elem->next_page.addr.hi =
-			cpu_to_le32(U64_HI(bp->eq_mapping +
-				   BCM_PAGE_SIZE * (i % NUM_EQ_PAGES)));
-		elem->next_page.addr.lo =
-			cpu_to_le32(U64_LO(bp->eq_mapping +
-				   BCM_PAGE_SIZE*(i % NUM_EQ_PAGES)));
-	}
-	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);
-}
-
-
-/* called with netif_addr_lock_bh() */
-void bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
-			 unsigned long rx_mode_flags,
-			 unsigned long rx_accept_flags,
-			 unsigned long tx_accept_flags,
-			 unsigned long ramrod_flags)
-{
-	struct bnx2x_rx_mode_ramrod_params ramrod_param;
-	int rc;
-
-	memset(&ramrod_param, 0, sizeof(ramrod_param));
-
-	/* Prepare ramrod parameters */
-	ramrod_param.cid = 0;
-	ramrod_param.cl_id = cl_id;
-	ramrod_param.rx_mode_obj = &bp->rx_mode_obj;
-	ramrod_param.func_id = BP_FUNC(bp);
-
-	ramrod_param.pstate = &bp->sp_state;
-	ramrod_param.state = BNX2X_FILTER_RX_MODE_PENDING;
-
-	ramrod_param.rdata = bnx2x_sp(bp, rx_mode_rdata);
-	ramrod_param.rdata_mapping = bnx2x_sp_mapping(bp, rx_mode_rdata);
-
-	set_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state);
-
-	ramrod_param.ramrod_flags = ramrod_flags;
-	ramrod_param.rx_mode_flags = rx_mode_flags;
-
-	ramrod_param.rx_accept_flags = rx_accept_flags;
-	ramrod_param.tx_accept_flags = tx_accept_flags;
-
-	rc = bnx2x_config_rx_mode(bp, &ramrod_param);
-	if (rc < 0) {
-		BNX2X_ERR("Set rx_mode %d failed\n", bp->rx_mode);
-		return;
-	}
-}
-
-/* called with netif_addr_lock_bh() */
-void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
-{
-	unsigned long rx_mode_flags = 0, ramrod_flags = 0;
-	unsigned long rx_accept_flags = 0, tx_accept_flags = 0;
-
-#ifdef BCM_CNIC
-	if (!NO_FCOE(bp))
-
-		/* Configure rx_mode of FCoE Queue */
-		__set_bit(BNX2X_RX_MODE_FCOE_ETH, &rx_mode_flags);
-#endif
-
-	switch (bp->rx_mode) {
-	case BNX2X_RX_MODE_NONE:
-		/*
-		 * 'drop all' supersedes any accept flags that may have been
-		 * passed to the function.
-		 */
-		break;
-	case BNX2X_RX_MODE_NORMAL:
-		__set_bit(BNX2X_ACCEPT_UNICAST, &rx_accept_flags);
-		__set_bit(BNX2X_ACCEPT_MULTICAST, &rx_accept_flags);
-		__set_bit(BNX2X_ACCEPT_BROADCAST, &rx_accept_flags);
-
-		/* internal switching mode */
-		__set_bit(BNX2X_ACCEPT_UNICAST, &tx_accept_flags);
-		__set_bit(BNX2X_ACCEPT_MULTICAST, &tx_accept_flags);
-		__set_bit(BNX2X_ACCEPT_BROADCAST, &tx_accept_flags);
-
-		break;
-	case BNX2X_RX_MODE_ALLMULTI:
-		__set_bit(BNX2X_ACCEPT_UNICAST, &rx_accept_flags);
-		__set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &rx_accept_flags);
-		__set_bit(BNX2X_ACCEPT_BROADCAST, &rx_accept_flags);
-
-		/* internal switching mode */
-		__set_bit(BNX2X_ACCEPT_UNICAST, &tx_accept_flags);
-		__set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &tx_accept_flags);
-		__set_bit(BNX2X_ACCEPT_BROADCAST, &tx_accept_flags);
-
-		break;
-	case BNX2X_RX_MODE_PROMISC:
-		/* According to deffinition of SI mode, iface in promisc mode
-		 * should receive matched and unmatched (in resolution of port)
-		 * unicast packets.
-		 */
-		__set_bit(BNX2X_ACCEPT_UNMATCHED, &rx_accept_flags);
-		__set_bit(BNX2X_ACCEPT_UNICAST, &rx_accept_flags);
-		__set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &rx_accept_flags);
-		__set_bit(BNX2X_ACCEPT_BROADCAST, &rx_accept_flags);
-
-		/* internal switching mode */
-		__set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &tx_accept_flags);
-		__set_bit(BNX2X_ACCEPT_BROADCAST, &tx_accept_flags);
-
-		if (IS_MF_SI(bp))
-			__set_bit(BNX2X_ACCEPT_ALL_UNICAST, &tx_accept_flags);
-		else
-			__set_bit(BNX2X_ACCEPT_UNICAST, &tx_accept_flags);
-
-		break;
-	default:
-		BNX2X_ERR("Unknown rx_mode: %d\n", bp->rx_mode);
-		return;
-	}
-
-	if (bp->rx_mode != BNX2X_RX_MODE_NONE) {
-		__set_bit(BNX2X_ACCEPT_ANY_VLAN, &rx_accept_flags);
-		__set_bit(BNX2X_ACCEPT_ANY_VLAN, &tx_accept_flags);
-	}
-
-	__set_bit(RAMROD_RX, &ramrod_flags);
-	__set_bit(RAMROD_TX, &ramrod_flags);
-
-	bnx2x_set_q_rx_mode(bp, bp->fp->cl_id, rx_mode_flags, rx_accept_flags,
-			    tx_accept_flags, ramrod_flags);
-}
-
-static void bnx2x_init_internal_common(struct bnx2x *bp)
-{
-	int i;
-
-	if (IS_MF_SI(bp))
-		/*
-		 * In switch independent mode, the TSTORM needs to accept
-		 * packets that failed classification, since approximate match
-		 * mac addresses aren't written to NIG LLH
-		 */
-		REG_WR8(bp, BAR_TSTRORM_INTMEM +
-			    TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET, 2);
-	else if (!CHIP_IS_E1(bp)) /* 57710 doesn't support MF */
-		REG_WR8(bp, BAR_TSTRORM_INTMEM +
-			    TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET, 0);
-
-	/* Zero this manually as its initialization is
-	   currently missing in the initTool */
-	for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++)
-		REG_WR(bp, BAR_USTRORM_INTMEM +
-		       USTORM_AGG_DATA_OFFSET + i * 4, 0);
-	if (!CHIP_IS_E1x(bp)) {
-		REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_IGU_MODE_OFFSET,
-			CHIP_INT_MODE_IS_BC(bp) ?
-			HC_IGU_BC_MODE : HC_IGU_NBC_MODE);
-	}
-}
-
-static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
-{
-	switch (load_code) {
-	case FW_MSG_CODE_DRV_LOAD_COMMON:
-	case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
-		bnx2x_init_internal_common(bp);
-		/* no break */
-
-	case FW_MSG_CODE_DRV_LOAD_PORT:
-		/* nothing to do */
-		/* no break */
-
-	case FW_MSG_CODE_DRV_LOAD_FUNCTION:
-		/* internal memory per function is
-		   initialized inside bnx2x_pf_init */
-		break;
-
-	default:
-		BNX2X_ERR("Unknown load_code (0x%x) from MCP\n", load_code);
-		break;
-	}
-}
-
-static inline u8 bnx2x_fp_igu_sb_id(struct bnx2x_fastpath *fp)
-{
-	return fp->bp->igu_base_sb + fp->index + CNIC_PRESENT;
-}
-
-static inline u8 bnx2x_fp_fw_sb_id(struct bnx2x_fastpath *fp)
-{
-	return fp->bp->base_fw_ndsb + fp->index + CNIC_PRESENT;
-}
-
-static inline u8 bnx2x_fp_cl_id(struct bnx2x_fastpath *fp)
-{
-	if (CHIP_IS_E1x(fp->bp))
-		return BP_L_ID(fp->bp) + fp->index;
-	else	/* We want Client ID to be the same as IGU SB ID for 57712 */
-		return bnx2x_fp_igu_sb_id(fp);
-}
-
-static void bnx2x_init_eth_fp(struct bnx2x *bp, int fp_idx)
-{
-	struct bnx2x_fastpath *fp = &bp->fp[fp_idx];
-	u8 cos;
-	unsigned long q_type = 0;
-	u32 cids[BNX2X_MULTI_TX_COS] = { 0 };
-
-	fp->cid = fp_idx;
-	fp->cl_id = bnx2x_fp_cl_id(fp);
-	fp->fw_sb_id = bnx2x_fp_fw_sb_id(fp);
-	fp->igu_sb_id = bnx2x_fp_igu_sb_id(fp);
-	/* qZone id equals to FW (per path) client id */
-	fp->cl_qzone_id  = bnx2x_fp_qzone_id(fp);
-
-	/* init shortcut */
-	fp->ustorm_rx_prods_offset = bnx2x_rx_ustorm_prods_offset(fp);
-	/* Setup SB indicies */
-	fp->rx_cons_sb = BNX2X_RX_SB_INDEX;
-
-	/* Configure Queue State object */
-	__set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type);
-	__set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type);
-
-	BUG_ON(fp->max_cos > BNX2X_MULTI_TX_COS);
-
-	/* init tx data */
-	for_each_cos_in_tx_queue(fp, cos) {
-		bnx2x_init_txdata(bp, &fp->txdata[cos],
-				  CID_COS_TO_TX_ONLY_CID(fp->cid, cos),
-				  FP_COS_TO_TXQ(fp, cos),
-				  BNX2X_TX_SB_INDEX_BASE + cos);
-		cids[cos] = fp->txdata[cos].cid;
-	}
-
-	bnx2x_init_queue_obj(bp, &fp->q_obj, fp->cl_id, cids, fp->max_cos,
-			     BP_FUNC(bp), bnx2x_sp(bp, q_rdata),
-			     bnx2x_sp_mapping(bp, q_rdata), q_type);
-
-	/**
-	 * Configure classification DBs: Always enable Tx switching
-	 */
-	bnx2x_init_vlan_mac_fp_objs(fp, BNX2X_OBJ_TYPE_RX_TX);
-
-	DP(NETIF_MSG_IFUP, "queue[%d]:  bnx2x_init_sb(%p,%p)  "
-				   "cl_id %d  fw_sb %d  igu_sb %d\n",
-		   fp_idx, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id,
-		   fp->igu_sb_id);
-	bnx2x_init_sb(bp, fp->status_blk_mapping, BNX2X_VF_ID_INVALID, false,
-		      fp->fw_sb_id, fp->igu_sb_id);
-
-	bnx2x_update_fpsb_idx(fp);
-}
-
-void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
-{
-	int i;
-
-	for_each_eth_queue(bp, i)
-		bnx2x_init_eth_fp(bp, i);
-#ifdef BCM_CNIC
-	if (!NO_FCOE(bp))
-		bnx2x_init_fcoe_fp(bp);
-
-	bnx2x_init_sb(bp, bp->cnic_sb_mapping,
-		      BNX2X_VF_ID_INVALID, false,
-		      bnx2x_cnic_fw_sb_id(bp), bnx2x_cnic_igu_sb_id(bp));
-
-#endif
-
-	/* Initialize MOD_ABS interrupts */
-	bnx2x_init_mod_abs_int(bp, &bp->link_vars, bp->common.chip_id,
-			       bp->common.shmem_base, bp->common.shmem2_base,
-			       BP_PORT(bp));
-	/* ensure status block indices were read */
-	rmb();
-
-	bnx2x_init_def_sb(bp);
-	bnx2x_update_dsb_idx(bp);
-	bnx2x_init_rx_rings(bp);
-	bnx2x_init_tx_rings(bp);
-	bnx2x_init_sp_ring(bp);
-	bnx2x_init_eq_ring(bp);
-	bnx2x_init_internal(bp, load_code);
-	bnx2x_pf_init(bp);
-	bnx2x_stats_init(bp);
-
-	/* flush all before enabling interrupts */
-	mb();
-	mmiowb();
-
-	bnx2x_int_enable(bp);
-
-	/* Check for SPIO5 */
-	bnx2x_attn_int_deasserted0(bp,
-		REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_1_FUNC_0 + BP_PORT(bp)*4) &
-				   AEU_INPUTS_ATTN_BITS_SPIO5);
-}
-
-/* end of nic init */
-
-/*
- * gzip service functions
- */
-
-static int bnx2x_gunzip_init(struct bnx2x *bp)
-{
-	bp->gunzip_buf = dma_alloc_coherent(&bp->pdev->dev, FW_BUF_SIZE,
-					    &bp->gunzip_mapping, GFP_KERNEL);
-	if (bp->gunzip_buf  == NULL)
-		goto gunzip_nomem1;
-
-	bp->strm = kmalloc(sizeof(*bp->strm), GFP_KERNEL);
-	if (bp->strm  == NULL)
-		goto gunzip_nomem2;
-
-	bp->strm->workspace = vmalloc(zlib_inflate_workspacesize());
-	if (bp->strm->workspace == NULL)
-		goto gunzip_nomem3;
-
-	return 0;
-
-gunzip_nomem3:
-	kfree(bp->strm);
-	bp->strm = NULL;
-
-gunzip_nomem2:
-	dma_free_coherent(&bp->pdev->dev, FW_BUF_SIZE, bp->gunzip_buf,
-			  bp->gunzip_mapping);
-	bp->gunzip_buf = NULL;
-
-gunzip_nomem1:
-	netdev_err(bp->dev, "Cannot allocate firmware buffer for"
-	       " un-compression\n");
-	return -ENOMEM;
-}
-
-static void bnx2x_gunzip_end(struct bnx2x *bp)
-{
-	if (bp->strm) {
-		vfree(bp->strm->workspace);
-		kfree(bp->strm);
-		bp->strm = NULL;
-	}
-
-	if (bp->gunzip_buf) {
-		dma_free_coherent(&bp->pdev->dev, FW_BUF_SIZE, bp->gunzip_buf,
-				  bp->gunzip_mapping);
-		bp->gunzip_buf = NULL;
-	}
-}
-
-static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len)
-{
-	int n, rc;
-
-	/* check gzip header */
-	if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED)) {
-		BNX2X_ERR("Bad gzip header\n");
-		return -EINVAL;
-	}
-
-	n = 10;
-
-#define FNAME				0x8
-
-	if (zbuf[3] & FNAME)
-		while ((zbuf[n++] != 0) && (n < len));
-
-	bp->strm->next_in = (typeof(bp->strm->next_in))zbuf + n;
-	bp->strm->avail_in = len - n;
-	bp->strm->next_out = bp->gunzip_buf;
-	bp->strm->avail_out = FW_BUF_SIZE;
-
-	rc = zlib_inflateInit2(bp->strm, -MAX_WBITS);
-	if (rc != Z_OK)
-		return rc;
-
-	rc = zlib_inflate(bp->strm, Z_FINISH);
-	if ((rc != Z_OK) && (rc != Z_STREAM_END))
-		netdev_err(bp->dev, "Firmware decompression error: %s\n",
-			   bp->strm->msg);
-
-	bp->gunzip_outlen = (FW_BUF_SIZE - bp->strm->avail_out);
-	if (bp->gunzip_outlen & 0x3)
-		netdev_err(bp->dev, "Firmware decompression error:"
-				    " gunzip_outlen (%d) not aligned\n",
-				bp->gunzip_outlen);
-	bp->gunzip_outlen >>= 2;
-
-	zlib_inflateEnd(bp->strm);
-
-	if (rc == Z_STREAM_END)
-		return 0;
-
-	return rc;
-}
-
-/* nic load/unload */
-
-/*
- * General service functions
- */
-
-/* send a NIG loopback debug packet */
-static void bnx2x_lb_pckt(struct bnx2x *bp)
-{
-	u32 wb_write[3];
-
-	/* Ethernet source and destination addresses */
-	wb_write[0] = 0x55555555;
-	wb_write[1] = 0x55555555;
-	wb_write[2] = 0x20;		/* SOP */
-	REG_WR_DMAE(bp, NIG_REG_DEBUG_PACKET_LB, wb_write, 3);
-
-	/* NON-IP protocol */
-	wb_write[0] = 0x09000000;
-	wb_write[1] = 0x55555555;
-	wb_write[2] = 0x10;		/* EOP, eop_bvalid = 0 */
-	REG_WR_DMAE(bp, NIG_REG_DEBUG_PACKET_LB, wb_write, 3);
-}
-
-/* some of the internal memories
- * are not directly readable from the driver
- * to test them we send debug packets
- */
-static int bnx2x_int_mem_test(struct bnx2x *bp)
-{
-	int factor;
-	int count, i;
-	u32 val = 0;
-
-	if (CHIP_REV_IS_FPGA(bp))
-		factor = 120;
-	else if (CHIP_REV_IS_EMUL(bp))
-		factor = 200;
-	else
-		factor = 1;
-
-	/* Disable inputs of parser neighbor blocks */
-	REG_WR(bp, TSDM_REG_ENABLE_IN1, 0x0);
-	REG_WR(bp, TCM_REG_PRS_IFEN, 0x0);
-	REG_WR(bp, CFC_REG_DEBUG0, 0x1);
-	REG_WR(bp, NIG_REG_PRS_REQ_IN_EN, 0x0);
-
-	/*  Write 0 to parser credits for CFC search request */
-	REG_WR(bp, PRS_REG_CFC_SEARCH_INITIAL_CREDIT, 0x0);
-
-	/* send Ethernet packet */
-	bnx2x_lb_pckt(bp);
-
-	/* TODO do i reset NIG statistic? */
-	/* Wait until NIG register shows 1 packet of size 0x10 */
-	count = 1000 * factor;
-	while (count) {
-
-		bnx2x_read_dmae(bp, NIG_REG_STAT2_BRB_OCTET, 2);
-		val = *bnx2x_sp(bp, wb_data[0]);
-		if (val == 0x10)
-			break;
-
-		msleep(10);
-		count--;
-	}
-	if (val != 0x10) {
-		BNX2X_ERR("NIG timeout  val = 0x%x\n", val);
-		return -1;
-	}
-
-	/* Wait until PRS register shows 1 packet */
-	count = 1000 * factor;
-	while (count) {
-		val = REG_RD(bp, PRS_REG_NUM_OF_PACKETS);
-		if (val == 1)
-			break;
-
-		msleep(10);
-		count--;
-	}
-	if (val != 0x1) {
-		BNX2X_ERR("PRS timeout val = 0x%x\n", val);
-		return -2;
-	}
-
-	/* Reset and init BRB, PRS */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, 0x03);
-	msleep(50);
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03);
-	msleep(50);
-	bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON);
-	bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON);
-
-	DP(NETIF_MSG_HW, "part2\n");
-
-	/* Disable inputs of parser neighbor blocks */
-	REG_WR(bp, TSDM_REG_ENABLE_IN1, 0x0);
-	REG_WR(bp, TCM_REG_PRS_IFEN, 0x0);
-	REG_WR(bp, CFC_REG_DEBUG0, 0x1);
-	REG_WR(bp, NIG_REG_PRS_REQ_IN_EN, 0x0);
-
-	/* Write 0 to parser credits for CFC search request */
-	REG_WR(bp, PRS_REG_CFC_SEARCH_INITIAL_CREDIT, 0x0);
-
-	/* send 10 Ethernet packets */
-	for (i = 0; i < 10; i++)
-		bnx2x_lb_pckt(bp);
-
-	/* Wait until NIG register shows 10 + 1
-	   packets of size 11*0x10 = 0xb0 */
-	count = 1000 * factor;
-	while (count) {
-
-		bnx2x_read_dmae(bp, NIG_REG_STAT2_BRB_OCTET, 2);
-		val = *bnx2x_sp(bp, wb_data[0]);
-		if (val == 0xb0)
-			break;
-
-		msleep(10);
-		count--;
-	}
-	if (val != 0xb0) {
-		BNX2X_ERR("NIG timeout  val = 0x%x\n", val);
-		return -3;
-	}
-
-	/* Wait until PRS register shows 2 packets */
-	val = REG_RD(bp, PRS_REG_NUM_OF_PACKETS);
-	if (val != 2)
-		BNX2X_ERR("PRS timeout  val = 0x%x\n", val);
-
-	/* Write 1 to parser credits for CFC search request */
-	REG_WR(bp, PRS_REG_CFC_SEARCH_INITIAL_CREDIT, 0x1);
-
-	/* Wait until PRS register shows 3 packets */
-	msleep(10 * factor);
-	/* Wait until NIG register shows 1 packet of size 0x10 */
-	val = REG_RD(bp, PRS_REG_NUM_OF_PACKETS);
-	if (val != 3)
-		BNX2X_ERR("PRS timeout  val = 0x%x\n", val);
-
-	/* clear NIG EOP FIFO */
-	for (i = 0; i < 11; i++)
-		REG_RD(bp, NIG_REG_INGRESS_EOP_LB_FIFO);
-	val = REG_RD(bp, NIG_REG_INGRESS_EOP_LB_EMPTY);
-	if (val != 1) {
-		BNX2X_ERR("clear of NIG failed\n");
-		return -4;
-	}
-
-	/* Reset and init BRB, PRS, NIG */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, 0x03);
-	msleep(50);
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03);
-	msleep(50);
-	bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON);
-	bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON);
-#ifndef BCM_CNIC
-	/* set NIC mode */
-	REG_WR(bp, PRS_REG_NIC_MODE, 1);
-#endif
-
-	/* Enable inputs of parser neighbor blocks */
-	REG_WR(bp, TSDM_REG_ENABLE_IN1, 0x7fffffff);
-	REG_WR(bp, TCM_REG_PRS_IFEN, 0x1);
-	REG_WR(bp, CFC_REG_DEBUG0, 0x0);
-	REG_WR(bp, NIG_REG_PRS_REQ_IN_EN, 0x1);
-
-	DP(NETIF_MSG_HW, "done\n");
-
-	return 0; /* OK */
-}
-
-static void bnx2x_enable_blocks_attention(struct bnx2x *bp)
-{
-	REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
-	if (!CHIP_IS_E1x(bp))
-		REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0x40);
-	else
-		REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0);
-	REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0);
-	REG_WR(bp, CFC_REG_CFC_INT_MASK, 0);
-	/*
-	 * mask read length error interrupts in brb for parser
-	 * (parsing unit and 'checksum and crc' unit)
-	 * these errors are legal (PU reads fixed length and CAC can cause
-	 * read length error on truncated packets)
-	 */
-	REG_WR(bp, BRB1_REG_BRB1_INT_MASK, 0xFC00);
-	REG_WR(bp, QM_REG_QM_INT_MASK, 0);
-	REG_WR(bp, TM_REG_TM_INT_MASK, 0);
-	REG_WR(bp, XSDM_REG_XSDM_INT_MASK_0, 0);
-	REG_WR(bp, XSDM_REG_XSDM_INT_MASK_1, 0);
-	REG_WR(bp, XCM_REG_XCM_INT_MASK, 0);
-/*	REG_WR(bp, XSEM_REG_XSEM_INT_MASK_0, 0); */
-/*	REG_WR(bp, XSEM_REG_XSEM_INT_MASK_1, 0); */
-	REG_WR(bp, USDM_REG_USDM_INT_MASK_0, 0);
-	REG_WR(bp, USDM_REG_USDM_INT_MASK_1, 0);
-	REG_WR(bp, UCM_REG_UCM_INT_MASK, 0);
-/*	REG_WR(bp, USEM_REG_USEM_INT_MASK_0, 0); */
-/*	REG_WR(bp, USEM_REG_USEM_INT_MASK_1, 0); */
-	REG_WR(bp, GRCBASE_UPB + PB_REG_PB_INT_MASK, 0);
-	REG_WR(bp, CSDM_REG_CSDM_INT_MASK_0, 0);
-	REG_WR(bp, CSDM_REG_CSDM_INT_MASK_1, 0);
-	REG_WR(bp, CCM_REG_CCM_INT_MASK, 0);
-/*	REG_WR(bp, CSEM_REG_CSEM_INT_MASK_0, 0); */
-/*	REG_WR(bp, CSEM_REG_CSEM_INT_MASK_1, 0); */
-
-	if (CHIP_REV_IS_FPGA(bp))
-		REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x580000);
-	else if (!CHIP_IS_E1x(bp))
-		REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0,
-			   (PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF
-				| PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT
-				| PXP2_PXP2_INT_MASK_0_REG_PGL_PCIE_ATTN
-				| PXP2_PXP2_INT_MASK_0_REG_PGL_READ_BLOCKED
-				| PXP2_PXP2_INT_MASK_0_REG_PGL_WRITE_BLOCKED));
-	else
-		REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x480000);
-	REG_WR(bp, TSDM_REG_TSDM_INT_MASK_0, 0);
-	REG_WR(bp, TSDM_REG_TSDM_INT_MASK_1, 0);
-	REG_WR(bp, TCM_REG_TCM_INT_MASK, 0);
-/*	REG_WR(bp, TSEM_REG_TSEM_INT_MASK_0, 0); */
-
-	if (!CHIP_IS_E1x(bp))
-		/* enable VFC attentions: bits 11 and 12, bits 31:13 reserved */
-		REG_WR(bp, TSEM_REG_TSEM_INT_MASK_1, 0x07ff);
-
-	REG_WR(bp, CDU_REG_CDU_INT_MASK, 0);
-	REG_WR(bp, DMAE_REG_DMAE_INT_MASK, 0);
-/*	REG_WR(bp, MISC_REG_MISC_INT_MASK, 0); */
-	REG_WR(bp, PBF_REG_PBF_INT_MASK, 0x18);		/* bit 3,4 masked */
-}
-
-static void bnx2x_reset_common(struct bnx2x *bp)
-{
-	u32 val = 0x1400;
-
-	/* reset_common */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
-	       0xd3ffff7f);
-
-	if (CHIP_IS_E3(bp)) {
-		val |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
-		val |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
-	}
-
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, val);
-}
-
-static void bnx2x_setup_dmae(struct bnx2x *bp)
-{
-	bp->dmae_ready = 0;
-	spin_lock_init(&bp->dmae_lock);
-}
-
-static void bnx2x_init_pxp(struct bnx2x *bp)
-{
-	u16 devctl;
-	int r_order, w_order;
-
-	pci_read_config_word(bp->pdev,
-			     pci_pcie_cap(bp->pdev) + PCI_EXP_DEVCTL, &devctl);
-	DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl);
-	w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
-	if (bp->mrrs == -1)
-		r_order = ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12);
-	else {
-		DP(NETIF_MSG_HW, "force read order to %d\n", bp->mrrs);
-		r_order = bp->mrrs;
-	}
-
-	bnx2x_init_pxp_arb(bp, r_order, w_order);
-}
-
-static void bnx2x_setup_fan_failure_detection(struct bnx2x *bp)
-{
-	int is_required;
-	u32 val;
-	int port;
-
-	if (BP_NOMCP(bp))
-		return;
-
-	is_required = 0;
-	val = SHMEM_RD(bp, dev_info.shared_hw_config.config2) &
-	      SHARED_HW_CFG_FAN_FAILURE_MASK;
-
-	if (val == SHARED_HW_CFG_FAN_FAILURE_ENABLED)
-		is_required = 1;
-
-	/*
-	 * The fan failure mechanism is usually related to the PHY type since
-	 * the power consumption of the board is affected by the PHY. Currently,
-	 * fan is required for most designs with SFX7101, BCM8727 and BCM8481.
-	 */
-	else if (val == SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE)
-		for (port = PORT_0; port < PORT_MAX; port++) {
-			is_required |=
-				bnx2x_fan_failure_det_req(
-					bp,
-					bp->common.shmem_base,
-					bp->common.shmem2_base,
-					port);
-		}
-
-	DP(NETIF_MSG_HW, "fan detection setting: %d\n", is_required);
-
-	if (is_required == 0)
-		return;
-
-	/* Fan failure is indicated by SPIO 5 */
-	bnx2x_set_spio(bp, MISC_REGISTERS_SPIO_5,
-		       MISC_REGISTERS_SPIO_INPUT_HI_Z);
-
-	/* set to active low mode */
-	val = REG_RD(bp, MISC_REG_SPIO_INT);
-	val |= ((1 << MISC_REGISTERS_SPIO_5) <<
-					MISC_REGISTERS_SPIO_INT_OLD_SET_POS);
-	REG_WR(bp, MISC_REG_SPIO_INT, val);
-
-	/* enable interrupt to signal the IGU */
-	val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
-	val |= (1 << MISC_REGISTERS_SPIO_5);
-	REG_WR(bp, MISC_REG_SPIO_EVENT_EN, val);
-}
-
-static void bnx2x_pretend_func(struct bnx2x *bp, u8 pretend_func_num)
-{
-	u32 offset = 0;
-
-	if (CHIP_IS_E1(bp))
-		return;
-	if (CHIP_IS_E1H(bp) && (pretend_func_num >= E1H_FUNC_MAX))
-		return;
-
-	switch (BP_ABS_FUNC(bp)) {
-	case 0:
-		offset = PXP2_REG_PGL_PRETEND_FUNC_F0;
-		break;
-	case 1:
-		offset = PXP2_REG_PGL_PRETEND_FUNC_F1;
-		break;
-	case 2:
-		offset = PXP2_REG_PGL_PRETEND_FUNC_F2;
-		break;
-	case 3:
-		offset = PXP2_REG_PGL_PRETEND_FUNC_F3;
-		break;
-	case 4:
-		offset = PXP2_REG_PGL_PRETEND_FUNC_F4;
-		break;
-	case 5:
-		offset = PXP2_REG_PGL_PRETEND_FUNC_F5;
-		break;
-	case 6:
-		offset = PXP2_REG_PGL_PRETEND_FUNC_F6;
-		break;
-	case 7:
-		offset = PXP2_REG_PGL_PRETEND_FUNC_F7;
-		break;
-	default:
-		return;
-	}
-
-	REG_WR(bp, offset, pretend_func_num);
-	REG_RD(bp, offset);
-	DP(NETIF_MSG_HW, "Pretending to func %d\n", pretend_func_num);
-}
-
-void bnx2x_pf_disable(struct bnx2x *bp)
-{
-	u32 val = REG_RD(bp, IGU_REG_PF_CONFIGURATION);
-	val &= ~IGU_PF_CONF_FUNC_EN;
-
-	REG_WR(bp, IGU_REG_PF_CONFIGURATION, val);
-	REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 0);
-	REG_WR(bp, CFC_REG_WEAK_ENABLE_PF, 0);
-}
-
-static inline void bnx2x__common_init_phy(struct bnx2x *bp)
-{
-	u32 shmem_base[2], shmem2_base[2];
-	shmem_base[0] =  bp->common.shmem_base;
-	shmem2_base[0] = bp->common.shmem2_base;
-	if (!CHIP_IS_E1x(bp)) {
-		shmem_base[1] =
-			SHMEM2_RD(bp, other_shmem_base_addr);
-		shmem2_base[1] =
-			SHMEM2_RD(bp, other_shmem2_base_addr);
-	}
-	bnx2x_acquire_phy_lock(bp);
-	bnx2x_common_init_phy(bp, shmem_base, shmem2_base,
-			      bp->common.chip_id);
-	bnx2x_release_phy_lock(bp);
-}
-
-/**
- * bnx2x_init_hw_common - initialize the HW at the COMMON phase.
- *
- * @bp:		driver handle
- */
-static int bnx2x_init_hw_common(struct bnx2x *bp)
-{
-	u32 val;
-
-	DP(BNX2X_MSG_MCP, "starting common init  func %d\n", BP_ABS_FUNC(bp));
-
-	/*
-	 * take the UNDI lock to protect undi_unload flow from accessing
-	 * registers while we're resetting the chip
-	 */
-	bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
-
-	bnx2x_reset_common(bp);
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff);
-
-	val = 0xfffc;
-	if (CHIP_IS_E3(bp)) {
-		val |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
-		val |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
-	}
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, val);
-
-	bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
-
-	bnx2x_init_block(bp, BLOCK_MISC, PHASE_COMMON);
-
-	if (!CHIP_IS_E1x(bp)) {
-		u8 abs_func_id;
-
-		/**
-		 * 4-port mode or 2-port mode we need to turn of master-enable
-		 * for everyone, after that, turn it back on for self.
-		 * so, we disregard multi-function or not, and always disable
-		 * for all functions on the given path, this means 0,2,4,6 for
-		 * path 0 and 1,3,5,7 for path 1
-		 */
-		for (abs_func_id = BP_PATH(bp);
-		     abs_func_id < E2_FUNC_MAX*2; abs_func_id += 2) {
-			if (abs_func_id == BP_ABS_FUNC(bp)) {
-				REG_WR(bp,
-				    PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER,
-				    1);
-				continue;
-			}
-
-			bnx2x_pretend_func(bp, abs_func_id);
-			/* clear pf enable */
-			bnx2x_pf_disable(bp);
-			bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
-		}
-	}
-
-	bnx2x_init_block(bp, BLOCK_PXP, PHASE_COMMON);
-	if (CHIP_IS_E1(bp)) {
-		/* enable HW interrupt from PXP on USDM overflow
-		   bit 16 on INT_MASK_0 */
-		REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
-	}
-
-	bnx2x_init_block(bp, BLOCK_PXP2, PHASE_COMMON);
-	bnx2x_init_pxp(bp);
-
-#ifdef __BIG_ENDIAN
-	REG_WR(bp, PXP2_REG_RQ_QM_ENDIAN_M, 1);
-	REG_WR(bp, PXP2_REG_RQ_TM_ENDIAN_M, 1);
-	REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, 1);
-	REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, 1);
-	REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, 1);
-	/* make sure this value is 0 */
-	REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 0);
-
-/*	REG_WR(bp, PXP2_REG_RD_PBF_SWAP_MODE, 1); */
-	REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, 1);
-	REG_WR(bp, PXP2_REG_RD_TM_SWAP_MODE, 1);
-	REG_WR(bp, PXP2_REG_RD_SRC_SWAP_MODE, 1);
-	REG_WR(bp, PXP2_REG_RD_CDURD_SWAP_MODE, 1);
-#endif
-
-	bnx2x_ilt_init_page_size(bp, INITOP_SET);
-
-	if (CHIP_REV_IS_FPGA(bp) && CHIP_IS_E1H(bp))
-		REG_WR(bp, PXP2_REG_PGL_TAGS_LIMIT, 0x1);
-
-	/* let the HW do it's magic ... */
-	msleep(100);
-	/* finish PXP init */
-	val = REG_RD(bp, PXP2_REG_RQ_CFG_DONE);
-	if (val != 1) {
-		BNX2X_ERR("PXP2 CFG failed\n");
-		return -EBUSY;
-	}
-	val = REG_RD(bp, PXP2_REG_RD_INIT_DONE);
-	if (val != 1) {
-		BNX2X_ERR("PXP2 RD_INIT failed\n");
-		return -EBUSY;
-	}
-
-	/* Timers bug workaround E2 only. We need to set the entire ILT to
-	 * have entries with value "0" and valid bit on.
-	 * This needs to be done by the first PF that is loaded in a path
-	 * (i.e. common phase)
-	 */
-	if (!CHIP_IS_E1x(bp)) {
-/* In E2 there is a bug in the timers block that can cause function 6 / 7
- * (i.e. vnic3) to start even if it is marked as "scan-off".
- * This occurs when a different function (func2,3) is being marked
- * as "scan-off". Real-life scenario for example: if a driver is being
- * load-unloaded while func6,7 are down. This will cause the timer to access
- * the ilt, translate to a logical address and send a request to read/write.
- * Since the ilt for the function that is down is not valid, this will cause
- * a translation error which is unrecoverable.
- * The Workaround is intended to make sure that when this happens nothing fatal
- * will occur. The workaround:
- *	1.  First PF driver which loads on a path will:
- *		a.  After taking the chip out of reset, by using pretend,
- *		    it will write "0" to the following registers of
- *		    the other vnics.
- *		    REG_WR(pdev, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 0);
- *		    REG_WR(pdev, CFC_REG_WEAK_ENABLE_PF,0);
- *		    REG_WR(pdev, CFC_REG_STRONG_ENABLE_PF,0);
- *		    And for itself it will write '1' to
- *		    PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER to enable
- *		    dmae-operations (writing to pram for example.)
- *		    note: can be done for only function 6,7 but cleaner this
- *			  way.
- *		b.  Write zero+valid to the entire ILT.
- *		c.  Init the first_timers_ilt_entry, last_timers_ilt_entry of
- *		    VNIC3 (of that port). The range allocated will be the
- *		    entire ILT. This is needed to prevent  ILT range error.
- *	2.  Any PF driver load flow:
- *		a.  ILT update with the physical addresses of the allocated
- *		    logical pages.
- *		b.  Wait 20msec. - note that this timeout is needed to make
- *		    sure there are no requests in one of the PXP internal
- *		    queues with "old" ILT addresses.
- *		c.  PF enable in the PGLC.
- *		d.  Clear the was_error of the PF in the PGLC. (could have
- *		    occured while driver was down)
- *		e.  PF enable in the CFC (WEAK + STRONG)
- *		f.  Timers scan enable
- *	3.  PF driver unload flow:
- *		a.  Clear the Timers scan_en.
- *		b.  Polling for scan_on=0 for that PF.
- *		c.  Clear the PF enable bit in the PXP.
- *		d.  Clear the PF enable in the CFC (WEAK + STRONG)
- *		e.  Write zero+valid to all ILT entries (The valid bit must
- *		    stay set)
- *		f.  If this is VNIC 3 of a port then also init
- *		    first_timers_ilt_entry to zero and last_timers_ilt_entry
- *		    to the last enrty in the ILT.
- *
- *	Notes:
- *	Currently the PF error in the PGLC is non recoverable.
- *	In the future the there will be a recovery routine for this error.
- *	Currently attention is masked.
- *	Having an MCP lock on the load/unload process does not guarantee that
- *	there is no Timer disable during Func6/7 enable. This is because the
- *	Timers scan is currently being cleared by the MCP on FLR.
- *	Step 2.d can be done only for PF6/7 and the driver can also check if
- *	there is error before clearing it. But the flow above is simpler and
- *	more general.
- *	All ILT entries are written by zero+valid and not just PF6/7
- *	ILT entries since in the future the ILT entries allocation for
- *	PF-s might be dynamic.
- */
-		struct ilt_client_info ilt_cli;
-		struct bnx2x_ilt ilt;
-		memset(&ilt_cli, 0, sizeof(struct ilt_client_info));
-		memset(&ilt, 0, sizeof(struct bnx2x_ilt));
-
-		/* initialize dummy TM client */
-		ilt_cli.start = 0;
-		ilt_cli.end = ILT_NUM_PAGE_ENTRIES - 1;
-		ilt_cli.client_num = ILT_CLIENT_TM;
-
-		/* 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)
-		 *
-		 * both steps performed by call to bnx2x_ilt_client_init_op()
-		 * with dummy TM client
-		 *
-		 * we must use pretend since PXP2_REG_RQ_##blk##_FIRST_ILT
-		 * and his brother are split registers
-		 */
-		bnx2x_pretend_func(bp, (BP_PATH(bp) + 6));
-		bnx2x_ilt_client_init_op_ilt(bp, &ilt, &ilt_cli, INITOP_CLEAR);
-		bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
-
-		REG_WR(bp, PXP2_REG_RQ_DRAM_ALIGN, BNX2X_PXP_DRAM_ALIGN);
-		REG_WR(bp, PXP2_REG_RQ_DRAM_ALIGN_RD, BNX2X_PXP_DRAM_ALIGN);
-		REG_WR(bp, PXP2_REG_RQ_DRAM_ALIGN_SEL, 1);
-	}
-
-
-	REG_WR(bp, PXP2_REG_RQ_DISABLE_INPUTS, 0);
-	REG_WR(bp, PXP2_REG_RD_DISABLE_INPUTS, 0);
-
-	if (!CHIP_IS_E1x(bp)) {
-		int factor = CHIP_REV_IS_EMUL(bp) ? 1000 :
-				(CHIP_REV_IS_FPGA(bp) ? 400 : 0);
-		bnx2x_init_block(bp, BLOCK_PGLUE_B, PHASE_COMMON);
-
-		bnx2x_init_block(bp, BLOCK_ATC, PHASE_COMMON);
-
-		/* let the HW do it's magic ... */
-		do {
-			msleep(200);
-			val = REG_RD(bp, ATC_REG_ATC_INIT_DONE);
-		} while (factor-- && (val != 1));
-
-		if (val != 1) {
-			BNX2X_ERR("ATC_INIT failed\n");
-			return -EBUSY;
-		}
-	}
-
-	bnx2x_init_block(bp, BLOCK_DMAE, PHASE_COMMON);
-
-	/* clean the DMAE memory */
-	bp->dmae_ready = 1;
-	bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8, 1);
-
-	bnx2x_init_block(bp, BLOCK_TCM, PHASE_COMMON);
-
-	bnx2x_init_block(bp, BLOCK_UCM, PHASE_COMMON);
-
-	bnx2x_init_block(bp, BLOCK_CCM, PHASE_COMMON);
-
-	bnx2x_init_block(bp, BLOCK_XCM, PHASE_COMMON);
-
-	bnx2x_read_dmae(bp, XSEM_REG_PASSIVE_BUFFER, 3);
-	bnx2x_read_dmae(bp, CSEM_REG_PASSIVE_BUFFER, 3);
-	bnx2x_read_dmae(bp, TSEM_REG_PASSIVE_BUFFER, 3);
-	bnx2x_read_dmae(bp, USEM_REG_PASSIVE_BUFFER, 3);
-
-	bnx2x_init_block(bp, BLOCK_QM, PHASE_COMMON);
-
-
-	/* QM queues pointers table */
-	bnx2x_qm_init_ptr_table(bp, bp->qm_cid_count, INITOP_SET);
-
-	/* soft reset pulse */
-	REG_WR(bp, QM_REG_SOFT_RESET, 1);
-	REG_WR(bp, QM_REG_SOFT_RESET, 0);
-
-#ifdef BCM_CNIC
-	bnx2x_init_block(bp, BLOCK_TM, PHASE_COMMON);
-#endif
-
-	bnx2x_init_block(bp, BLOCK_DORQ, PHASE_COMMON);
-	REG_WR(bp, DORQ_REG_DPM_CID_OFST, BNX2X_DB_SHIFT);
-	if (!CHIP_REV_IS_SLOW(bp))
-		/* enable hw interrupt from doorbell Q */
-		REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0);
-
-	bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON);
-
-	bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON);
-	REG_WR(bp, PRS_REG_A_PRSU_20, 0xf);
-
-	if (!CHIP_IS_E1(bp))
-		REG_WR(bp, PRS_REG_E1HOV_MODE, bp->path_has_ovlan);
-
-	if (!CHIP_IS_E1x(bp) && !CHIP_IS_E3B0(bp))
-		/* Bit-map indicating which L2 hdrs may appear
-		 * after the basic Ethernet header
-		 */
-		REG_WR(bp, PRS_REG_HDRS_AFTER_BASIC,
-		       bp->path_has_ovlan ? 7 : 6);
-
-	bnx2x_init_block(bp, BLOCK_TSDM, PHASE_COMMON);
-	bnx2x_init_block(bp, BLOCK_CSDM, PHASE_COMMON);
-	bnx2x_init_block(bp, BLOCK_USDM, PHASE_COMMON);
-	bnx2x_init_block(bp, BLOCK_XSDM, PHASE_COMMON);
-
-	if (!CHIP_IS_E1x(bp)) {
-		/* reset VFC memories */
-		REG_WR(bp, TSEM_REG_FAST_MEMORY + VFC_REG_MEMORIES_RST,
-			   VFC_MEMORIES_RST_REG_CAM_RST |
-			   VFC_MEMORIES_RST_REG_RAM_RST);
-		REG_WR(bp, XSEM_REG_FAST_MEMORY + VFC_REG_MEMORIES_RST,
-			   VFC_MEMORIES_RST_REG_CAM_RST |
-			   VFC_MEMORIES_RST_REG_RAM_RST);
-
-		msleep(20);
-	}
-
-	bnx2x_init_block(bp, BLOCK_TSEM, PHASE_COMMON);
-	bnx2x_init_block(bp, BLOCK_USEM, PHASE_COMMON);
-	bnx2x_init_block(bp, BLOCK_CSEM, PHASE_COMMON);
-	bnx2x_init_block(bp, BLOCK_XSEM, PHASE_COMMON);
-
-	/* sync semi rtc */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
-	       0x80000000);
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
-	       0x80000000);
-
-	bnx2x_init_block(bp, BLOCK_UPB, PHASE_COMMON);
-	bnx2x_init_block(bp, BLOCK_XPB, PHASE_COMMON);
-	bnx2x_init_block(bp, BLOCK_PBF, PHASE_COMMON);
-
-	if (!CHIP_IS_E1x(bp))
-		REG_WR(bp, PBF_REG_HDRS_AFTER_BASIC,
-		       bp->path_has_ovlan ? 7 : 6);
-
-	REG_WR(bp, SRC_REG_SOFT_RST, 1);
-
-	bnx2x_init_block(bp, BLOCK_SRC, PHASE_COMMON);
-
-#ifdef BCM_CNIC
-	REG_WR(bp, SRC_REG_KEYSEARCH_0, 0x63285672);
-	REG_WR(bp, SRC_REG_KEYSEARCH_1, 0x24b8f2cc);
-	REG_WR(bp, SRC_REG_KEYSEARCH_2, 0x223aef9b);
-	REG_WR(bp, SRC_REG_KEYSEARCH_3, 0x26001e3a);
-	REG_WR(bp, SRC_REG_KEYSEARCH_4, 0x7ae91116);
-	REG_WR(bp, SRC_REG_KEYSEARCH_5, 0x5ce5230b);
-	REG_WR(bp, SRC_REG_KEYSEARCH_6, 0x298d8adf);
-	REG_WR(bp, SRC_REG_KEYSEARCH_7, 0x6eb0ff09);
-	REG_WR(bp, SRC_REG_KEYSEARCH_8, 0x1830f82f);
-	REG_WR(bp, SRC_REG_KEYSEARCH_9, 0x01e46be7);
-#endif
-	REG_WR(bp, SRC_REG_SOFT_RST, 0);
-
-	if (sizeof(union cdu_context) != 1024)
-		/* we currently assume that a context is 1024 bytes */
-		dev_alert(&bp->pdev->dev, "please adjust the size "
-					  "of cdu_context(%ld)\n",
-			 (long)sizeof(union cdu_context));
-
-	bnx2x_init_block(bp, BLOCK_CDU, PHASE_COMMON);
-	val = (4 << 24) + (0 << 12) + 1024;
-	REG_WR(bp, CDU_REG_CDU_GLOBAL_PARAMS, val);
-
-	bnx2x_init_block(bp, BLOCK_CFC, PHASE_COMMON);
-	REG_WR(bp, CFC_REG_INIT_REG, 0x7FF);
-	/* enable context validation interrupt from CFC */
-	REG_WR(bp, CFC_REG_CFC_INT_MASK, 0);
-
-	/* set the thresholds to prevent CFC/CDU race */
-	REG_WR(bp, CFC_REG_DEBUG0, 0x20020000);
-
-	bnx2x_init_block(bp, BLOCK_HC, PHASE_COMMON);
-
-	if (!CHIP_IS_E1x(bp) && BP_NOMCP(bp))
-		REG_WR(bp, IGU_REG_RESET_MEMORIES, 0x36);
-
-	bnx2x_init_block(bp, BLOCK_IGU, PHASE_COMMON);
-	bnx2x_init_block(bp, BLOCK_MISC_AEU, PHASE_COMMON);
-
-	/* Reset PCIE errors for debug */
-	REG_WR(bp, 0x2814, 0xffffffff);
-	REG_WR(bp, 0x3820, 0xffffffff);
-
-	if (!CHIP_IS_E1x(bp)) {
-		REG_WR(bp, PCICFG_OFFSET + PXPCS_TL_CONTROL_5,
-			   (PXPCS_TL_CONTROL_5_ERR_UNSPPORT1 |
-				PXPCS_TL_CONTROL_5_ERR_UNSPPORT));
-		REG_WR(bp, PCICFG_OFFSET + PXPCS_TL_FUNC345_STAT,
-			   (PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT4 |
-				PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT3 |
-				PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT2));
-		REG_WR(bp, PCICFG_OFFSET + PXPCS_TL_FUNC678_STAT,
-			   (PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT7 |
-				PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT6 |
-				PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT5));
-	}
-
-	bnx2x_init_block(bp, BLOCK_NIG, PHASE_COMMON);
-	if (!CHIP_IS_E1(bp)) {
-		/* in E3 this done in per-port section */
-		if (!CHIP_IS_E3(bp))
-			REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_MF(bp));
-	}
-	if (CHIP_IS_E1H(bp))
-		/* not applicable for E2 (and above ...) */
-		REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_MF_SD(bp));
-
-	if (CHIP_REV_IS_SLOW(bp))
-		msleep(200);
-
-	/* finish CFC init */
-	val = reg_poll(bp, CFC_REG_LL_INIT_DONE, 1, 100, 10);
-	if (val != 1) {
-		BNX2X_ERR("CFC LL_INIT failed\n");
-		return -EBUSY;
-	}
-	val = reg_poll(bp, CFC_REG_AC_INIT_DONE, 1, 100, 10);
-	if (val != 1) {
-		BNX2X_ERR("CFC AC_INIT failed\n");
-		return -EBUSY;
-	}
-	val = reg_poll(bp, CFC_REG_CAM_INIT_DONE, 1, 100, 10);
-	if (val != 1) {
-		BNX2X_ERR("CFC CAM_INIT failed\n");
-		return -EBUSY;
-	}
-	REG_WR(bp, CFC_REG_DEBUG0, 0);
-
-	if (CHIP_IS_E1(bp)) {
-		/* read NIG statistic
-		   to see if this is our first up since powerup */
-		bnx2x_read_dmae(bp, NIG_REG_STAT2_BRB_OCTET, 2);
-		val = *bnx2x_sp(bp, wb_data[0]);
-
-		/* do internal memory self test */
-		if ((val == 0) && bnx2x_int_mem_test(bp)) {
-			BNX2X_ERR("internal mem self test failed\n");
-			return -EBUSY;
-		}
-	}
-
-	bnx2x_setup_fan_failure_detection(bp);
-
-	/* clear PXP2 attentions */
-	REG_RD(bp, PXP2_REG_PXP2_INT_STS_CLR_0);
-
-	bnx2x_enable_blocks_attention(bp);
-	bnx2x_enable_blocks_parity(bp);
-
-	if (!BP_NOMCP(bp)) {
-		if (CHIP_IS_E1x(bp))
-			bnx2x__common_init_phy(bp);
-	} else
-		BNX2X_ERR("Bootcode is missing - can not initialize link\n");
-
-	return 0;
-}
-
-/**
- * bnx2x_init_hw_common_chip - init HW at the COMMON_CHIP phase.
- *
- * @bp:		driver handle
- */
-static int bnx2x_init_hw_common_chip(struct bnx2x *bp)
-{
-	int rc = bnx2x_init_hw_common(bp);
-
-	if (rc)
-		return rc;
-
-	/* In E2 2-PORT mode, same ext phy is used for the two paths */
-	if (!BP_NOMCP(bp))
-		bnx2x__common_init_phy(bp);
-
-	return 0;
-}
-
-static int bnx2x_init_hw_port(struct bnx2x *bp)
-{
-	int port = BP_PORT(bp);
-	int init_phase = port ? PHASE_PORT1 : PHASE_PORT0;
-	u32 low, high;
-	u32 val;
-
-	bnx2x__link_reset(bp);
-
-	DP(BNX2X_MSG_MCP, "starting port init  port %d\n", port);
-
-	REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0);
-
-	bnx2x_init_block(bp, BLOCK_MISC, init_phase);
-	bnx2x_init_block(bp, BLOCK_PXP, init_phase);
-	bnx2x_init_block(bp, BLOCK_PXP2, init_phase);
-
-	/* Timers bug workaround: disables the pf_master bit in pglue at
-	 * common phase, we need to enable it here before any dmae access are
-	 * attempted. Therefore we manually added the enable-master to the
-	 * port phase (it also happens in the function phase)
-	 */
-	if (!CHIP_IS_E1x(bp))
-		REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1);
-
-	bnx2x_init_block(bp, BLOCK_ATC, init_phase);
-	bnx2x_init_block(bp, BLOCK_DMAE, init_phase);
-	bnx2x_init_block(bp, BLOCK_PGLUE_B, init_phase);
-	bnx2x_init_block(bp, BLOCK_QM, init_phase);
-
-	bnx2x_init_block(bp, BLOCK_TCM, init_phase);
-	bnx2x_init_block(bp, BLOCK_UCM, init_phase);
-	bnx2x_init_block(bp, BLOCK_CCM, init_phase);
-	bnx2x_init_block(bp, BLOCK_XCM, init_phase);
-
-	/* QM cid (connection) count */
-	bnx2x_qm_init_cid_count(bp, bp->qm_cid_count, INITOP_SET);
-
-#ifdef BCM_CNIC
-	bnx2x_init_block(bp, BLOCK_TM, init_phase);
-	REG_WR(bp, TM_REG_LIN0_SCAN_TIME + port*4, 20);
-	REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + port*4, 31);
-#endif
-
-	bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
-
-	if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) {
-		bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
-
-		if (IS_MF(bp))
-			low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
-		else if (bp->dev->mtu > 4096) {
-			if (bp->flags & ONE_PORT_FLAG)
-				low = 160;
-			else {
-				val = bp->dev->mtu;
-				/* (24*1024 + val*4)/256 */
-				low = 96 + (val/64) +
-						((val % 64) ? 1 : 0);
-			}
-		} else
-			low = ((bp->flags & ONE_PORT_FLAG) ? 80 : 160);
-		high = low + 56;	/* 14*1024/256 */
-		REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_0 + port*4, low);
-		REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_0 + port*4, high);
-	}
-
-	if (CHIP_MODE_IS_4_PORT(bp))
-		REG_WR(bp, (BP_PORT(bp) ?
-			    BRB1_REG_MAC_GUARANTIED_1 :
-			    BRB1_REG_MAC_GUARANTIED_0), 40);
-
-
-	bnx2x_init_block(bp, BLOCK_PRS, init_phase);
-	if (CHIP_IS_E3B0(bp))
-		/* Ovlan exists only if we are in multi-function +
-		 * switch-dependent mode, in switch-independent there
-		 * is no ovlan headers
-		 */
-		REG_WR(bp, BP_PORT(bp) ?
-		       PRS_REG_HDRS_AFTER_BASIC_PORT_1 :
-		       PRS_REG_HDRS_AFTER_BASIC_PORT_0,
-		       (bp->path_has_ovlan ? 7 : 6));
-
-	bnx2x_init_block(bp, BLOCK_TSDM, init_phase);
-	bnx2x_init_block(bp, BLOCK_CSDM, init_phase);
-	bnx2x_init_block(bp, BLOCK_USDM, init_phase);
-	bnx2x_init_block(bp, BLOCK_XSDM, init_phase);
-
-	bnx2x_init_block(bp, BLOCK_TSEM, init_phase);
-	bnx2x_init_block(bp, BLOCK_USEM, init_phase);
-	bnx2x_init_block(bp, BLOCK_CSEM, init_phase);
-	bnx2x_init_block(bp, BLOCK_XSEM, init_phase);
-
-	bnx2x_init_block(bp, BLOCK_UPB, init_phase);
-	bnx2x_init_block(bp, BLOCK_XPB, init_phase);
-
-	bnx2x_init_block(bp, BLOCK_PBF, init_phase);
-
-	if (CHIP_IS_E1x(bp)) {
-		/* configure PBF to work without PAUSE mtu 9000 */
-		REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
-
-		/* update threshold */
-		REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, (9040/16));
-		/* update init credit */
-		REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, (9040/16) + 553 - 22);
-
-		/* probe changes */
-		REG_WR(bp, PBF_REG_INIT_P0 + port*4, 1);
-		udelay(50);
-		REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0);
-	}
-
-#ifdef BCM_CNIC
-	bnx2x_init_block(bp, BLOCK_SRC, init_phase);
-#endif
-	bnx2x_init_block(bp, BLOCK_CDU, init_phase);
-	bnx2x_init_block(bp, BLOCK_CFC, init_phase);
-
-	if (CHIP_IS_E1(bp)) {
-		REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
-		REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
-	}
-	bnx2x_init_block(bp, BLOCK_HC, init_phase);
-
-	bnx2x_init_block(bp, BLOCK_IGU, init_phase);
-
-	bnx2x_init_block(bp, BLOCK_MISC_AEU, init_phase);
-	/* init aeu_mask_attn_func_0/1:
-	 *  - SF mode: bits 3-7 are masked. only bits 0-2 are in use
-	 *  - MF mode: bit 3 is masked. bits 0-2 are in use as in SF
-	 *             bits 4-7 are used for "per vn group attention" */
-	val = IS_MF(bp) ? 0xF7 : 0x7;
-	/* Enable DCBX attention for all but E1 */
-	val |= CHIP_IS_E1(bp) ? 0 : 0x10;
-	REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4, val);
-
-	bnx2x_init_block(bp, BLOCK_NIG, init_phase);
-
-	if (!CHIP_IS_E1x(bp)) {
-		/* Bit-map indicating which L2 hdrs may appear after the
-		 * basic Ethernet header
-		 */
-		REG_WR(bp, BP_PORT(bp) ?
-			   NIG_REG_P1_HDRS_AFTER_BASIC :
-			   NIG_REG_P0_HDRS_AFTER_BASIC,
-			   IS_MF_SD(bp) ? 7 : 6);
-
-		if (CHIP_IS_E3(bp))
-			REG_WR(bp, BP_PORT(bp) ?
-				   NIG_REG_LLH1_MF_MODE :
-				   NIG_REG_LLH_MF_MODE, IS_MF(bp));
-	}
-	if (!CHIP_IS_E3(bp))
-		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
-
-	if (!CHIP_IS_E1(bp)) {
-		/* 0x2 disable mf_ov, 0x1 enable */
-		REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK_MF + port*4,
-		       (IS_MF_SD(bp) ? 0x1 : 0x2));
-
-		if (!CHIP_IS_E1x(bp)) {
-			val = 0;
-			switch (bp->mf_mode) {
-			case MULTI_FUNCTION_SD:
-				val = 1;
-				break;
-			case MULTI_FUNCTION_SI:
-				val = 2;
-				break;
-			}
-
-			REG_WR(bp, (BP_PORT(bp) ? NIG_REG_LLH1_CLS_TYPE :
-						  NIG_REG_LLH0_CLS_TYPE), val);
-		}
-		{
-			REG_WR(bp, NIG_REG_LLFC_ENABLE_0 + port*4, 0);
-			REG_WR(bp, NIG_REG_LLFC_OUT_EN_0 + port*4, 0);
-			REG_WR(bp, NIG_REG_PAUSE_ENABLE_0 + port*4, 1);
-		}
-	}
-
-
-	/* If SPIO5 is set to generate interrupts, enable it for this port */
-	val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
-	if (val & (1 << MISC_REGISTERS_SPIO_5)) {
-		u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
-				       MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
-		val = REG_RD(bp, reg_addr);
-		val |= AEU_INPUTS_ATTN_BITS_SPIO5;
-		REG_WR(bp, reg_addr, val);
-	}
-
-	return 0;
-}
-
-static void bnx2x_ilt_wr(struct bnx2x *bp, u32 index, dma_addr_t addr)
-{
-	int reg;
-
-	if (CHIP_IS_E1(bp))
-		reg = PXP2_REG_RQ_ONCHIP_AT + index*8;
-	else
-		reg = PXP2_REG_RQ_ONCHIP_AT_B0 + index*8;
-
-	bnx2x_wb_wr(bp, reg, ONCHIP_ADDR1(addr), ONCHIP_ADDR2(addr));
-}
-
-static inline void bnx2x_igu_clear_sb(struct bnx2x *bp, u8 idu_sb_id)
-{
-	bnx2x_igu_clear_sb_gen(bp, BP_FUNC(bp), idu_sb_id, true /*PF*/);
-}
-
-static inline void bnx2x_clear_func_ilt(struct bnx2x *bp, u32 func)
-{
-	u32 i, base = FUNC_ILT_BASE(func);
-	for (i = base; i < base + ILT_PER_FUNC; i++)
-		bnx2x_ilt_wr(bp, i, 0);
-}
-
-static int bnx2x_init_hw_func(struct bnx2x *bp)
-{
-	int port = BP_PORT(bp);
-	int func = BP_FUNC(bp);
-	int init_phase = PHASE_PF0 + func;
-	struct bnx2x_ilt *ilt = BP_ILT(bp);
-	u16 cdu_ilt_start;
-	u32 addr, val;
-	u32 main_mem_base, main_mem_size, main_mem_prty_clr;
-	int i, main_mem_width;
-
-	DP(BNX2X_MSG_MCP, "starting func init  func %d\n", func);
-
-	/* FLR cleanup - hmmm */
-	if (!CHIP_IS_E1x(bp))
-		bnx2x_pf_flr_clnup(bp);
-
-	/* set MSI reconfigure capability */
-	if (bp->common.int_block == INT_BLOCK_HC) {
-		addr = (port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0);
-		val = REG_RD(bp, addr);
-		val |= HC_CONFIG_0_REG_MSI_ATTN_EN_0;
-		REG_WR(bp, addr, val);
-	}
-
-	bnx2x_init_block(bp, BLOCK_PXP, init_phase);
-	bnx2x_init_block(bp, BLOCK_PXP2, init_phase);
-
-	ilt = BP_ILT(bp);
-	cdu_ilt_start = ilt->clients[ILT_CLIENT_CDU].start;
-
-	for (i = 0; i < L2_ILT_LINES(bp); i++) {
-		ilt->lines[cdu_ilt_start + i].page =
-			bp->context.vcxt + (ILT_PAGE_CIDS * i);
-		ilt->lines[cdu_ilt_start + i].page_mapping =
-			bp->context.cxt_mapping + (CDU_ILT_PAGE_SZ * i);
-		/* cdu ilt pages are allocated manually so there's no need to
-		set the size */
-	}
-	bnx2x_ilt_init_op(bp, INITOP_SET);
-
-#ifdef BCM_CNIC
-	bnx2x_src_init_t2(bp, bp->t2, bp->t2_mapping, SRC_CONN_NUM);
-
-	/* T1 hash bits value determines the T1 number of entries */
-	REG_WR(bp, SRC_REG_NUMBER_HASH_BITS0 + port*4, SRC_HASH_BITS);
-#endif
-
-#ifndef BCM_CNIC
-	/* set NIC mode */
-	REG_WR(bp, PRS_REG_NIC_MODE, 1);
-#endif  /* BCM_CNIC */
-
-	if (!CHIP_IS_E1x(bp)) {
-		u32 pf_conf = IGU_PF_CONF_FUNC_EN;
-
-		/* Turn on a single ISR mode in IGU if driver is going to use
-		 * INT#x or MSI
-		 */
-		if (!(bp->flags & USING_MSIX_FLAG))
-			pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN;
-		/*
-		 * Timers workaround bug: function init part.
-		 * Need to wait 20msec after initializing ILT,
-		 * needed to make sure there are no requests in
-		 * one of the PXP internal queues with "old" ILT addresses
-		 */
-		msleep(20);
-		/*
-		 * Master enable - Due to WB DMAE writes performed before this
-		 * register is re-initialized as part of the regular function
-		 * init
-		 */
-		REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1);
-		/* Enable the function in IGU */
-		REG_WR(bp, IGU_REG_PF_CONFIGURATION, pf_conf);
-	}
-
-	bp->dmae_ready = 1;
-
-	bnx2x_init_block(bp, BLOCK_PGLUE_B, init_phase);
-
-	if (!CHIP_IS_E1x(bp))
-		REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, func);
-
-	bnx2x_init_block(bp, BLOCK_ATC, init_phase);
-	bnx2x_init_block(bp, BLOCK_DMAE, init_phase);
-	bnx2x_init_block(bp, BLOCK_NIG, init_phase);
-	bnx2x_init_block(bp, BLOCK_SRC, init_phase);
-	bnx2x_init_block(bp, BLOCK_MISC, init_phase);
-	bnx2x_init_block(bp, BLOCK_TCM, init_phase);
-	bnx2x_init_block(bp, BLOCK_UCM, init_phase);
-	bnx2x_init_block(bp, BLOCK_CCM, init_phase);
-	bnx2x_init_block(bp, BLOCK_XCM, init_phase);
-	bnx2x_init_block(bp, BLOCK_TSEM, init_phase);
-	bnx2x_init_block(bp, BLOCK_USEM, init_phase);
-	bnx2x_init_block(bp, BLOCK_CSEM, init_phase);
-	bnx2x_init_block(bp, BLOCK_XSEM, init_phase);
-
-	if (!CHIP_IS_E1x(bp))
-		REG_WR(bp, QM_REG_PF_EN, 1);
-
-	if (!CHIP_IS_E1x(bp)) {
-		REG_WR(bp, TSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func);
-		REG_WR(bp, USEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func);
-		REG_WR(bp, CSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func);
-		REG_WR(bp, XSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func);
-	}
-	bnx2x_init_block(bp, BLOCK_QM, init_phase);
-
-	bnx2x_init_block(bp, BLOCK_TM, init_phase);
-	bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
-	bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
-	bnx2x_init_block(bp, BLOCK_PRS, init_phase);
-	bnx2x_init_block(bp, BLOCK_TSDM, init_phase);
-	bnx2x_init_block(bp, BLOCK_CSDM, init_phase);
-	bnx2x_init_block(bp, BLOCK_USDM, init_phase);
-	bnx2x_init_block(bp, BLOCK_XSDM, init_phase);
-	bnx2x_init_block(bp, BLOCK_UPB, init_phase);
-	bnx2x_init_block(bp, BLOCK_XPB, init_phase);
-	bnx2x_init_block(bp, BLOCK_PBF, init_phase);
-	if (!CHIP_IS_E1x(bp))
-		REG_WR(bp, PBF_REG_DISABLE_PF, 0);
-
-	bnx2x_init_block(bp, BLOCK_CDU, init_phase);
-
-	bnx2x_init_block(bp, BLOCK_CFC, init_phase);
-
-	if (!CHIP_IS_E1x(bp))
-		REG_WR(bp, CFC_REG_WEAK_ENABLE_PF, 1);
-
-	if (IS_MF(bp)) {
-		REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1);
-		REG_WR(bp, NIG_REG_LLH0_FUNC_VLAN_ID + port*8, bp->mf_ov);
-	}
-
-	bnx2x_init_block(bp, BLOCK_MISC_AEU, init_phase);
-
-	/* HC init per function */
-	if (bp->common.int_block == INT_BLOCK_HC) {
-		if (CHIP_IS_E1H(bp)) {
-			REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
-
-			REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
-			REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
-		}
-		bnx2x_init_block(bp, BLOCK_HC, init_phase);
-
-	} else {
-		int num_segs, sb_idx, prod_offset;
-
-		REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
-
-		if (!CHIP_IS_E1x(bp)) {
-			REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, 0);
-			REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, 0);
-		}
-
-		bnx2x_init_block(bp, BLOCK_IGU, init_phase);
-
-		if (!CHIP_IS_E1x(bp)) {
-			int dsb_idx = 0;
-			/**
-			 * Producer memory:
-			 * E2 mode: address 0-135 match to the mapping memory;
-			 * 136 - PF0 default prod; 137 - PF1 default prod;
-			 * 138 - PF2 default prod; 139 - PF3 default prod;
-			 * 140 - PF0 attn prod;    141 - PF1 attn prod;
-			 * 142 - PF2 attn prod;    143 - PF3 attn prod;
-			 * 144-147 reserved.
-			 *
-			 * E1.5 mode - In backward compatible mode;
-			 * for non default SB; each even line in the memory
-			 * holds the U producer and each odd line hold
-			 * the C producer. The first 128 producers are for
-			 * NDSB (PF0 - 0-31; PF1 - 32-63 and so on). The last 20
-			 * producers are for the DSB for each PF.
-			 * Each PF has five segments: (the order inside each
-			 * segment is PF0; PF1; PF2; PF3) - 128-131 U prods;
-			 * 132-135 C prods; 136-139 X prods; 140-143 T prods;
-			 * 144-147 attn prods;
-			 */
-			/* non-default-status-blocks */
-			num_segs = CHIP_INT_MODE_IS_BC(bp) ?
-				IGU_BC_NDSB_NUM_SEGS : IGU_NORM_NDSB_NUM_SEGS;
-			for (sb_idx = 0; sb_idx < bp->igu_sb_cnt; sb_idx++) {
-				prod_offset = (bp->igu_base_sb + sb_idx) *
-					num_segs;
-
-				for (i = 0; i < num_segs; i++) {
-					addr = IGU_REG_PROD_CONS_MEMORY +
-							(prod_offset + i) * 4;
-					REG_WR(bp, addr, 0);
-				}
-				/* send consumer update with value 0 */
-				bnx2x_ack_sb(bp, bp->igu_base_sb + sb_idx,
-					     USTORM_ID, 0, IGU_INT_NOP, 1);
-				bnx2x_igu_clear_sb(bp,
-						   bp->igu_base_sb + sb_idx);
-			}
-
-			/* default-status-blocks */
-			num_segs = CHIP_INT_MODE_IS_BC(bp) ?
-				IGU_BC_DSB_NUM_SEGS : IGU_NORM_DSB_NUM_SEGS;
-
-			if (CHIP_MODE_IS_4_PORT(bp))
-				dsb_idx = BP_FUNC(bp);
-			else
-				dsb_idx = BP_VN(bp);
-
-			prod_offset = (CHIP_INT_MODE_IS_BC(bp) ?
-				       IGU_BC_BASE_DSB_PROD + dsb_idx :
-				       IGU_NORM_BASE_DSB_PROD + dsb_idx);
-
-			/*
-			 * igu prods come in chunks of E1HVN_MAX (4) -
-			 * does not matters what is the current chip mode
-			 */
-			for (i = 0; i < (num_segs * E1HVN_MAX);
-			     i += E1HVN_MAX) {
-				addr = IGU_REG_PROD_CONS_MEMORY +
-							(prod_offset + i)*4;
-				REG_WR(bp, addr, 0);
-			}
-			/* send consumer update with 0 */
-			if (CHIP_INT_MODE_IS_BC(bp)) {
-				bnx2x_ack_sb(bp, bp->igu_dsb_id,
-					     USTORM_ID, 0, IGU_INT_NOP, 1);
-				bnx2x_ack_sb(bp, bp->igu_dsb_id,
-					     CSTORM_ID, 0, IGU_INT_NOP, 1);
-				bnx2x_ack_sb(bp, bp->igu_dsb_id,
-					     XSTORM_ID, 0, IGU_INT_NOP, 1);
-				bnx2x_ack_sb(bp, bp->igu_dsb_id,
-					     TSTORM_ID, 0, IGU_INT_NOP, 1);
-				bnx2x_ack_sb(bp, bp->igu_dsb_id,
-					     ATTENTION_ID, 0, IGU_INT_NOP, 1);
-			} else {
-				bnx2x_ack_sb(bp, bp->igu_dsb_id,
-					     USTORM_ID, 0, IGU_INT_NOP, 1);
-				bnx2x_ack_sb(bp, bp->igu_dsb_id,
-					     ATTENTION_ID, 0, IGU_INT_NOP, 1);
-			}
-			bnx2x_igu_clear_sb(bp, bp->igu_dsb_id);
-
-			/* !!! these should become driver const once
-			   rf-tool supports split-68 const */
-			REG_WR(bp, IGU_REG_SB_INT_BEFORE_MASK_LSB, 0);
-			REG_WR(bp, IGU_REG_SB_INT_BEFORE_MASK_MSB, 0);
-			REG_WR(bp, IGU_REG_SB_MASK_LSB, 0);
-			REG_WR(bp, IGU_REG_SB_MASK_MSB, 0);
-			REG_WR(bp, IGU_REG_PBA_STATUS_LSB, 0);
-			REG_WR(bp, IGU_REG_PBA_STATUS_MSB, 0);
-		}
-	}
-
-	/* Reset PCIE errors for debug */
-	REG_WR(bp, 0x2114, 0xffffffff);
-	REG_WR(bp, 0x2120, 0xffffffff);
-
-	if (CHIP_IS_E1x(bp)) {
-		main_mem_size = HC_REG_MAIN_MEMORY_SIZE / 2; /*dwords*/
-		main_mem_base = HC_REG_MAIN_MEMORY +
-				BP_PORT(bp) * (main_mem_size * 4);
-		main_mem_prty_clr = HC_REG_HC_PRTY_STS_CLR;
-		main_mem_width = 8;
-
-		val = REG_RD(bp, main_mem_prty_clr);
-		if (val)
-			DP(BNX2X_MSG_MCP, "Hmmm... Parity errors in HC "
-					  "block during "
-					  "function init (0x%x)!\n", val);
-
-		/* Clear "false" parity errors in MSI-X table */
-		for (i = main_mem_base;
-		     i < main_mem_base + main_mem_size * 4;
-		     i += main_mem_width) {
-			bnx2x_read_dmae(bp, i, main_mem_width / 4);
-			bnx2x_write_dmae(bp, bnx2x_sp_mapping(bp, wb_data),
-					 i, main_mem_width / 4);
-		}
-		/* Clear HC parity attention */
-		REG_RD(bp, main_mem_prty_clr);
-	}
-
-#ifdef BNX2X_STOP_ON_ERROR
-	/* Enable STORMs SP logging */
-	REG_WR8(bp, BAR_USTRORM_INTMEM +
-	       USTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1);
-	REG_WR8(bp, BAR_TSTRORM_INTMEM +
-	       TSTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1);
-	REG_WR8(bp, BAR_CSTRORM_INTMEM +
-	       CSTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1);
-	REG_WR8(bp, BAR_XSTRORM_INTMEM +
-	       XSTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1);
-#endif
-
-	bnx2x_phy_probe(&bp->link_params);
-
-	return 0;
-}
-
-
-void bnx2x_free_mem(struct bnx2x *bp)
-{
-	/* fastpath */
-	bnx2x_free_fp_mem(bp);
-	/* end of fastpath */
-
-	BNX2X_PCI_FREE(bp->def_status_blk, bp->def_status_blk_mapping,
-		       sizeof(struct host_sp_status_block));
-
-	BNX2X_PCI_FREE(bp->fw_stats, bp->fw_stats_mapping,
-		       bp->fw_stats_data_sz + bp->fw_stats_req_sz);
-
-	BNX2X_PCI_FREE(bp->slowpath, bp->slowpath_mapping,
-		       sizeof(struct bnx2x_slowpath));
-
-	BNX2X_PCI_FREE(bp->context.vcxt, bp->context.cxt_mapping,
-		       bp->context.size);
-
-	bnx2x_ilt_mem_op(bp, ILT_MEMOP_FREE);
-
-	BNX2X_FREE(bp->ilt->lines);
-
-#ifdef BCM_CNIC
-	if (!CHIP_IS_E1x(bp))
-		BNX2X_PCI_FREE(bp->cnic_sb.e2_sb, bp->cnic_sb_mapping,
-			       sizeof(struct host_hc_status_block_e2));
-	else
-		BNX2X_PCI_FREE(bp->cnic_sb.e1x_sb, bp->cnic_sb_mapping,
-			       sizeof(struct host_hc_status_block_e1x));
-
-	BNX2X_PCI_FREE(bp->t2, bp->t2_mapping, SRC_T2_SZ);
-#endif
-
-	BNX2X_PCI_FREE(bp->spq, bp->spq_mapping, BCM_PAGE_SIZE);
-
-	BNX2X_PCI_FREE(bp->eq_ring, bp->eq_mapping,
-		       BCM_PAGE_SIZE * NUM_EQ_PAGES);
-}
-
-static inline int bnx2x_alloc_fw_stats_mem(struct bnx2x *bp)
-{
-	int num_groups;
-
-	/* number of eth_queues */
-	u8 num_queue_stats = BNX2X_NUM_ETH_QUEUES(bp);
-
-	/* Total number of FW statistics requests =
-	 * 1 for port stats + 1 for PF stats + num_eth_queues */
-	bp->fw_stats_num = 2 + num_queue_stats;
-
-
-	/* Request is built from stats_query_header and an array of
-	 * stats_query_cmd_group each of which contains
-	 * STATS_QUERY_CMD_COUNT rules. The real number or requests is
-	 * configured in the stats_query_header.
-	 */
-	num_groups = (2 + num_queue_stats) / STATS_QUERY_CMD_COUNT +
-		(((2 + num_queue_stats) % STATS_QUERY_CMD_COUNT) ? 1 : 0);
-
-	bp->fw_stats_req_sz = sizeof(struct stats_query_header) +
-			num_groups * sizeof(struct stats_query_cmd_group);
-
-	/* Data for statistics requests + stats_conter
-	 *
-	 * stats_counter holds per-STORM counters that are incremented
-	 * when STORM has finished with the current request.
-	 */
-	bp->fw_stats_data_sz = sizeof(struct per_port_stats) +
-		sizeof(struct per_pf_stats) +
-		sizeof(struct per_queue_stats) * num_queue_stats +
-		sizeof(struct stats_counter);
-
-	BNX2X_PCI_ALLOC(bp->fw_stats, &bp->fw_stats_mapping,
-			bp->fw_stats_data_sz + bp->fw_stats_req_sz);
-
-	/* Set shortcuts */
-	bp->fw_stats_req = (struct bnx2x_fw_stats_req *)bp->fw_stats;
-	bp->fw_stats_req_mapping = bp->fw_stats_mapping;
-
-	bp->fw_stats_data = (struct bnx2x_fw_stats_data *)
-		((u8 *)bp->fw_stats + bp->fw_stats_req_sz);
-
-	bp->fw_stats_data_mapping = bp->fw_stats_mapping +
-				   bp->fw_stats_req_sz;
-	return 0;
-
-alloc_mem_err:
-	BNX2X_PCI_FREE(bp->fw_stats, bp->fw_stats_mapping,
-		       bp->fw_stats_data_sz + bp->fw_stats_req_sz);
-	return -ENOMEM;
-}
-
-
-int bnx2x_alloc_mem(struct bnx2x *bp)
-{
-#ifdef BCM_CNIC
-	if (!CHIP_IS_E1x(bp))
-		/* size = the status block + ramrod buffers */
-		BNX2X_PCI_ALLOC(bp->cnic_sb.e2_sb, &bp->cnic_sb_mapping,
-				sizeof(struct host_hc_status_block_e2));
-	else
-		BNX2X_PCI_ALLOC(bp->cnic_sb.e1x_sb, &bp->cnic_sb_mapping,
-				sizeof(struct host_hc_status_block_e1x));
-
-	/* allocate searcher T2 table */
-	BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ);
-#endif
-
-
-	BNX2X_PCI_ALLOC(bp->def_status_blk, &bp->def_status_blk_mapping,
-			sizeof(struct host_sp_status_block));
-
-	BNX2X_PCI_ALLOC(bp->slowpath, &bp->slowpath_mapping,
-			sizeof(struct bnx2x_slowpath));
-
-	/* Allocated memory for FW statistics  */
-	if (bnx2x_alloc_fw_stats_mem(bp))
-		goto alloc_mem_err;
-
-	bp->context.size = sizeof(union cdu_context) * BNX2X_L2_CID_COUNT(bp);
-
-	BNX2X_PCI_ALLOC(bp->context.vcxt, &bp->context.cxt_mapping,
-			bp->context.size);
-
-	BNX2X_ALLOC(bp->ilt->lines, sizeof(struct ilt_line) * ILT_MAX_LINES);
-
-	if (bnx2x_ilt_mem_op(bp, ILT_MEMOP_ALLOC))
-		goto alloc_mem_err;
-
-	/* Slow path ring */
-	BNX2X_PCI_ALLOC(bp->spq, &bp->spq_mapping, BCM_PAGE_SIZE);
-
-	/* EQ */
-	BNX2X_PCI_ALLOC(bp->eq_ring, &bp->eq_mapping,
-			BCM_PAGE_SIZE * NUM_EQ_PAGES);
-
-
-	/* fastpath */
-	/* need to be done at the end, since it's self adjusting to amount
-	 * of memory available for RSS queues
-	 */
-	if (bnx2x_alloc_fp_mem(bp))
-		goto alloc_mem_err;
-	return 0;
-
-alloc_mem_err:
-	bnx2x_free_mem(bp);
-	return -ENOMEM;
-}
-
-/*
- * Init service functions
- */
-
-int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,
-		      struct bnx2x_vlan_mac_obj *obj, bool set,
-		      int mac_type, unsigned long *ramrod_flags)
-{
-	int rc;
-	struct bnx2x_vlan_mac_ramrod_params ramrod_param;
-
-	memset(&ramrod_param, 0, sizeof(ramrod_param));
-
-	/* Fill general parameters */
-	ramrod_param.vlan_mac_obj = obj;
-	ramrod_param.ramrod_flags = *ramrod_flags;
-
-	/* Fill a user request section if needed */
-	if (!test_bit(RAMROD_CONT, ramrod_flags)) {
-		memcpy(ramrod_param.user_req.u.mac.mac, mac, ETH_ALEN);
-
-		__set_bit(mac_type, &ramrod_param.user_req.vlan_mac_flags);
-
-		/* Set the command: ADD or DEL */
-		if (set)
-			ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
-		else
-			ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_DEL;
-	}
-
-	rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
-	if (rc < 0)
-		BNX2X_ERR("%s MAC failed\n", (set ? "Set" : "Del"));
-	return rc;
-}
-
-int bnx2x_del_all_macs(struct bnx2x *bp,
-		       struct bnx2x_vlan_mac_obj *mac_obj,
-		       int mac_type, bool wait_for_comp)
-{
-	int rc;
-	unsigned long ramrod_flags = 0, vlan_mac_flags = 0;
-
-	/* Wait for completion of requested */
-	if (wait_for_comp)
-		__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
-
-	/* Set the mac type of addresses we want to clear */
-	__set_bit(mac_type, &vlan_mac_flags);
-
-	rc = mac_obj->delete_all(bp, mac_obj, &vlan_mac_flags, &ramrod_flags);
-	if (rc < 0)
-		BNX2X_ERR("Failed to delete MACs: %d\n", rc);
-
-	return rc;
-}
-
-int bnx2x_set_eth_mac(struct bnx2x *bp, bool set)
-{
-	unsigned long ramrod_flags = 0;
-
-	DP(NETIF_MSG_IFUP, "Adding Eth MAC\n");
-
-	__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
-	/* Eth MAC is set on RSS leading client (fp[0]) */
-	return bnx2x_set_mac_one(bp, bp->dev->dev_addr, &bp->fp->mac_obj, set,
-				 BNX2X_ETH_MAC, &ramrod_flags);
-}
-
-int bnx2x_setup_leading(struct bnx2x *bp)
-{
-	return bnx2x_setup_queue(bp, &bp->fp[0], 1);
-}
-
-/**
- * bnx2x_set_int_mode - configure interrupt mode
- *
- * @bp:		driver handle
- *
- * In case of MSI-X it will also try to enable MSI-X.
- */
-static void __devinit bnx2x_set_int_mode(struct bnx2x *bp)
-{
-	switch (int_mode) {
-	case INT_MODE_MSI:
-		bnx2x_enable_msi(bp);
-		/* falling through... */
-	case INT_MODE_INTx:
-		bp->num_queues = 1 + NON_ETH_CONTEXT_USE;
-		DP(NETIF_MSG_IFUP, "set number of queues to 1\n");
-		break;
-	default:
-		/* Set number of queues according to bp->multi_mode value */
-		bnx2x_set_num_queues(bp);
-
-		DP(NETIF_MSG_IFUP, "set number of queues to %d\n",
-		   bp->num_queues);
-
-		/* if we can't use MSI-X we only need one fp,
-		 * so try to enable MSI-X with the requested number of fp's
-		 * and fallback to MSI or legacy INTx with one fp
-		 */
-		if (bnx2x_enable_msix(bp)) {
-			/* failed to enable MSI-X */
-			if (bp->multi_mode)
-				DP(NETIF_MSG_IFUP,
-					  "Multi requested but failed to "
-					  "enable MSI-X (%d), "
-					  "set number of queues to %d\n",
-				   bp->num_queues,
-				   1 + NON_ETH_CONTEXT_USE);
-			bp->num_queues = 1 + NON_ETH_CONTEXT_USE;
-
-			/* Try to enable MSI */
-			if (!(bp->flags & DISABLE_MSI_FLAG))
-				bnx2x_enable_msi(bp);
-		}
-		break;
-	}
-}
-
-/* must be called prioir to any HW initializations */
-static inline u16 bnx2x_cid_ilt_lines(struct bnx2x *bp)
-{
-	return L2_ILT_LINES(bp);
-}
-
-void bnx2x_ilt_set_info(struct bnx2x *bp)
-{
-	struct ilt_client_info *ilt_client;
-	struct bnx2x_ilt *ilt = BP_ILT(bp);
-	u16 line = 0;
-
-	ilt->start_line = FUNC_ILT_BASE(BP_FUNC(bp));
-	DP(BNX2X_MSG_SP, "ilt starts at line %d\n", ilt->start_line);
-
-	/* CDU */
-	ilt_client = &ilt->clients[ILT_CLIENT_CDU];
-	ilt_client->client_num = ILT_CLIENT_CDU;
-	ilt_client->page_size = CDU_ILT_PAGE_SZ;
-	ilt_client->flags = ILT_CLIENT_SKIP_MEM;
-	ilt_client->start = line;
-	line += bnx2x_cid_ilt_lines(bp);
-#ifdef BCM_CNIC
-	line += CNIC_ILT_LINES;
-#endif
-	ilt_client->end = line - 1;
-
-	DP(BNX2X_MSG_SP, "ilt client[CDU]: start %d, end %d, psz 0x%x, "
-					 "flags 0x%x, hw psz %d\n",
-	   ilt_client->start,
-	   ilt_client->end,
-	   ilt_client->page_size,
-	   ilt_client->flags,
-	   ilog2(ilt_client->page_size >> 12));
-
-	/* QM */
-	if (QM_INIT(bp->qm_cid_count)) {
-		ilt_client = &ilt->clients[ILT_CLIENT_QM];
-		ilt_client->client_num = ILT_CLIENT_QM;
-		ilt_client->page_size = QM_ILT_PAGE_SZ;
-		ilt_client->flags = 0;
-		ilt_client->start = line;
-
-		/* 4 bytes for each cid */
-		line += DIV_ROUND_UP(bp->qm_cid_count * QM_QUEUES_PER_FUNC * 4,
-							 QM_ILT_PAGE_SZ);
-
-		ilt_client->end = line - 1;
-
-		DP(BNX2X_MSG_SP, "ilt client[QM]: start %d, end %d, psz 0x%x, "
-						 "flags 0x%x, hw psz %d\n",
-		   ilt_client->start,
-		   ilt_client->end,
-		   ilt_client->page_size,
-		   ilt_client->flags,
-		   ilog2(ilt_client->page_size >> 12));
-
-	}
-	/* SRC */
-	ilt_client = &ilt->clients[ILT_CLIENT_SRC];
-#ifdef BCM_CNIC
-	ilt_client->client_num = ILT_CLIENT_SRC;
-	ilt_client->page_size = SRC_ILT_PAGE_SZ;
-	ilt_client->flags = 0;
-	ilt_client->start = line;
-	line += SRC_ILT_LINES;
-	ilt_client->end = line - 1;
-
-	DP(BNX2X_MSG_SP, "ilt client[SRC]: start %d, end %d, psz 0x%x, "
-					 "flags 0x%x, hw psz %d\n",
-	   ilt_client->start,
-	   ilt_client->end,
-	   ilt_client->page_size,
-	   ilt_client->flags,
-	   ilog2(ilt_client->page_size >> 12));
-
-#else
-	ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM);
-#endif
-
-	/* TM */
-	ilt_client = &ilt->clients[ILT_CLIENT_TM];
-#ifdef BCM_CNIC
-	ilt_client->client_num = ILT_CLIENT_TM;
-	ilt_client->page_size = TM_ILT_PAGE_SZ;
-	ilt_client->flags = 0;
-	ilt_client->start = line;
-	line += TM_ILT_LINES;
-	ilt_client->end = line - 1;
-
-	DP(BNX2X_MSG_SP, "ilt client[TM]: start %d, end %d, psz 0x%x, "
-					 "flags 0x%x, hw psz %d\n",
-	   ilt_client->start,
-	   ilt_client->end,
-	   ilt_client->page_size,
-	   ilt_client->flags,
-	   ilog2(ilt_client->page_size >> 12));
-
-#else
-	ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM);
-#endif
-	BUG_ON(line > ILT_MAX_LINES);
-}
-
-/**
- * bnx2x_pf_q_prep_init - prepare INIT transition parameters
- *
- * @bp:			driver handle
- * @fp:			pointer to fastpath
- * @init_params:	pointer to parameters structure
- *
- * parameters configured:
- *      - HC configuration
- *      - Queue's CDU context
- */
-static inline void bnx2x_pf_q_prep_init(struct bnx2x *bp,
-	struct bnx2x_fastpath *fp, struct bnx2x_queue_init_params *init_params)
-{
-
-	u8 cos;
-	/* FCoE Queue uses Default SB, thus has no HC capabilities */
-	if (!IS_FCOE_FP(fp)) {
-		__set_bit(BNX2X_Q_FLG_HC, &init_params->rx.flags);
-		__set_bit(BNX2X_Q_FLG_HC, &init_params->tx.flags);
-
-		/* If HC is supporterd, enable host coalescing in the transition
-		 * to INIT state.
-		 */
-		__set_bit(BNX2X_Q_FLG_HC_EN, &init_params->rx.flags);
-		__set_bit(BNX2X_Q_FLG_HC_EN, &init_params->tx.flags);
-
-		/* HC rate */
-		init_params->rx.hc_rate = bp->rx_ticks ?
-			(1000000 / bp->rx_ticks) : 0;
-		init_params->tx.hc_rate = bp->tx_ticks ?
-			(1000000 / bp->tx_ticks) : 0;
-
-		/* FW SB ID */
-		init_params->rx.fw_sb_id = init_params->tx.fw_sb_id =
-			fp->fw_sb_id;
-
-		/*
-		 * CQ index among the SB indices: FCoE clients uses the default
-		 * SB, therefore it's different.
-		 */
-		init_params->rx.sb_cq_index = HC_INDEX_ETH_RX_CQ_CONS;
-		init_params->tx.sb_cq_index = HC_INDEX_ETH_FIRST_TX_CQ_CONS;
-	}
-
-	/* set maximum number of COSs supported by this queue */
-	init_params->max_cos = fp->max_cos;
-
-	DP(BNX2X_MSG_SP, "fp: %d setting queue params max cos to: %d",
-	    fp->index, init_params->max_cos);
-
-	/* set the context pointers queue object */
-	for (cos = FIRST_TX_COS_INDEX; cos < init_params->max_cos; cos++)
-		init_params->cxts[cos] =
-			&bp->context.vcxt[fp->txdata[cos].cid].eth;
-}
-
-int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp,
-			struct bnx2x_queue_state_params *q_params,
-			struct bnx2x_queue_setup_tx_only_params *tx_only_params,
-			int tx_index, bool leading)
-{
-	memset(tx_only_params, 0, sizeof(*tx_only_params));
-
-	/* Set the command */
-	q_params->cmd = BNX2X_Q_CMD_SETUP_TX_ONLY;
-
-	/* Set tx-only QUEUE flags: don't zero statistics */
-	tx_only_params->flags = bnx2x_get_common_flags(bp, fp, false);
-
-	/* choose the index of the cid to send the slow path on */
-	tx_only_params->cid_index = tx_index;
-
-	/* Set general TX_ONLY_SETUP parameters */
-	bnx2x_pf_q_prep_general(bp, fp, &tx_only_params->gen_params, tx_index);
-
-	/* Set Tx TX_ONLY_SETUP parameters */
-	bnx2x_pf_tx_q_prep(bp, fp, &tx_only_params->txq_params, tx_index);
-
-	DP(BNX2X_MSG_SP, "preparing to send tx-only ramrod for connection:"
-			 "cos %d, primary cid %d, cid %d, "
-			 "client id %d, sp-client id %d, flags %lx",
-	   tx_index, q_params->q_obj->cids[FIRST_TX_COS_INDEX],
-	   q_params->q_obj->cids[tx_index], q_params->q_obj->cl_id,
-	   tx_only_params->gen_params.spcl_id, tx_only_params->flags);
-
-	/* send the ramrod */
-	return bnx2x_queue_state_change(bp, q_params);
-}
-
-
-/**
- * bnx2x_setup_queue - setup queue
- *
- * @bp:		driver handle
- * @fp:		pointer to fastpath
- * @leading:	is leading
- *
- * This function performs 2 steps in a Queue state machine
- *      actually: 1) RESET->INIT 2) INIT->SETUP
- */
-
-int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
-		       bool leading)
-{
-	struct bnx2x_queue_state_params q_params = {0};
-	struct bnx2x_queue_setup_params *setup_params =
-						&q_params.params.setup;
-	struct bnx2x_queue_setup_tx_only_params *tx_only_params =
-						&q_params.params.tx_only;
-	int rc;
-	u8 tx_index;
-
-	DP(BNX2X_MSG_SP, "setting up queue %d", fp->index);
-
-	/* reset IGU state skip FCoE L2 queue */
-	if (!IS_FCOE_FP(fp))
-		bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, 0,
-			     IGU_INT_ENABLE, 0);
-
-	q_params.q_obj = &fp->q_obj;
-	/* We want to wait for completion in this context */
-	__set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
-
-	/* Prepare the INIT parameters */
-	bnx2x_pf_q_prep_init(bp, fp, &q_params.params.init);
-
-	/* Set the command */
-	q_params.cmd = BNX2X_Q_CMD_INIT;
-
-	/* Change the state to INIT */
-	rc = bnx2x_queue_state_change(bp, &q_params);
-	if (rc) {
-		BNX2X_ERR("Queue(%d) INIT failed\n", fp->index);
-		return rc;
-	}
-
-	DP(BNX2X_MSG_SP, "init complete");
-
-
-	/* Now move the Queue to the SETUP state... */
-	memset(setup_params, 0, sizeof(*setup_params));
-
-	/* Set QUEUE flags */
-	setup_params->flags = bnx2x_get_q_flags(bp, fp, leading);
-
-	/* Set general SETUP parameters */
-	bnx2x_pf_q_prep_general(bp, fp, &setup_params->gen_params,
-				FIRST_TX_COS_INDEX);
-
-	bnx2x_pf_rx_q_prep(bp, fp, &setup_params->pause_params,
-			    &setup_params->rxq_params);
-
-	bnx2x_pf_tx_q_prep(bp, fp, &setup_params->txq_params,
-			   FIRST_TX_COS_INDEX);
-
-	/* Set the command */
-	q_params.cmd = BNX2X_Q_CMD_SETUP;
-
-	/* Change the state to SETUP */
-	rc = bnx2x_queue_state_change(bp, &q_params);
-	if (rc) {
-		BNX2X_ERR("Queue(%d) SETUP failed\n", fp->index);
-		return rc;
-	}
-
-	/* loop through the relevant tx-only indices */
-	for (tx_index = FIRST_TX_ONLY_COS_INDEX;
-	      tx_index < fp->max_cos;
-	      tx_index++) {
-
-		/* prepare and send tx-only ramrod*/
-		rc = bnx2x_setup_tx_only(bp, fp, &q_params,
-					  tx_only_params, tx_index, leading);
-		if (rc) {
-			BNX2X_ERR("Queue(%d.%d) TX_ONLY_SETUP failed\n",
-				  fp->index, tx_index);
-			return rc;
-		}
-	}
-
-	return rc;
-}
-
-static int bnx2x_stop_queue(struct bnx2x *bp, int index)
-{
-	struct bnx2x_fastpath *fp = &bp->fp[index];
-	struct bnx2x_fp_txdata *txdata;
-	struct bnx2x_queue_state_params q_params = {0};
-	int rc, tx_index;
-
-	DP(BNX2X_MSG_SP, "stopping queue %d cid %d", index, fp->cid);
-
-	q_params.q_obj = &fp->q_obj;
-	/* We want to wait for completion in this context */
-	__set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
-
-
-	/* close tx-only connections */
-	for (tx_index = FIRST_TX_ONLY_COS_INDEX;
-	     tx_index < fp->max_cos;
-	     tx_index++){
-
-		/* ascertain this is a normal queue*/
-		txdata = &fp->txdata[tx_index];
-
-		DP(BNX2X_MSG_SP, "stopping tx-only queue %d",
-							txdata->txq_index);
-
-		/* send halt terminate on tx-only connection */
-		q_params.cmd = BNX2X_Q_CMD_TERMINATE;
-		memset(&q_params.params.terminate, 0,
-		       sizeof(q_params.params.terminate));
-		q_params.params.terminate.cid_index = tx_index;
-
-		rc = bnx2x_queue_state_change(bp, &q_params);
-		if (rc)
-			return rc;
-
-		/* send halt terminate on tx-only connection */
-		q_params.cmd = BNX2X_Q_CMD_CFC_DEL;
-		memset(&q_params.params.cfc_del, 0,
-		       sizeof(q_params.params.cfc_del));
-		q_params.params.cfc_del.cid_index = tx_index;
-		rc = bnx2x_queue_state_change(bp, &q_params);
-		if (rc)
-			return rc;
-	}
-	/* Stop the primary connection: */
-	/* ...halt the connection */
-	q_params.cmd = BNX2X_Q_CMD_HALT;
-	rc = bnx2x_queue_state_change(bp, &q_params);
-	if (rc)
-		return rc;
-
-	/* ...terminate the connection */
-	q_params.cmd = BNX2X_Q_CMD_TERMINATE;
-	memset(&q_params.params.terminate, 0,
-	       sizeof(q_params.params.terminate));
-	q_params.params.terminate.cid_index = FIRST_TX_COS_INDEX;
-	rc = bnx2x_queue_state_change(bp, &q_params);
-	if (rc)
-		return rc;
-	/* ...delete cfc entry */
-	q_params.cmd = BNX2X_Q_CMD_CFC_DEL;
-	memset(&q_params.params.cfc_del, 0,
-	       sizeof(q_params.params.cfc_del));
-	q_params.params.cfc_del.cid_index = FIRST_TX_COS_INDEX;
-	return bnx2x_queue_state_change(bp, &q_params);
-}
-
-
-static void bnx2x_reset_func(struct bnx2x *bp)
-{
-	int port = BP_PORT(bp);
-	int func = BP_FUNC(bp);
-	int i;
-
-	/* Disable the function in the FW */
-	REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNC_EN_OFFSET(func), 0);
-	REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_FUNC_EN_OFFSET(func), 0);
-	REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_FUNC_EN_OFFSET(func), 0);
-	REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNC_EN_OFFSET(func), 0);
-
-	/* FP SBs */
-	for_each_eth_queue(bp, i) {
-		struct bnx2x_fastpath *fp = &bp->fp[i];
-		REG_WR8(bp, BAR_CSTRORM_INTMEM +
-			   CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(fp->fw_sb_id),
-			   SB_DISABLED);
-	}
-
-#ifdef BCM_CNIC
-	/* CNIC SB */
-	REG_WR8(bp, BAR_CSTRORM_INTMEM +
-		CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(bnx2x_cnic_fw_sb_id(bp)),
-		SB_DISABLED);
-#endif
-	/* SP SB */
-	REG_WR8(bp, BAR_CSTRORM_INTMEM +
-		   CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(func),
-		   SB_DISABLED);
-
-	for (i = 0; i < XSTORM_SPQ_DATA_SIZE / 4; i++)
-		REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_DATA_OFFSET(func),
-		       0);
-
-	/* Configure IGU */
-	if (bp->common.int_block == INT_BLOCK_HC) {
-		REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
-		REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
-	} else {
-		REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, 0);
-		REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, 0);
-	}
-
-#ifdef BCM_CNIC
-	/* Disable Timer scan */
-	REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
-	/*
-	 * Wait for at least 10ms and up to 2 second for the timers scan to
-	 * complete
-	 */
-	for (i = 0; i < 200; i++) {
-		msleep(10);
-		if (!REG_RD(bp, TM_REG_LIN0_SCAN_ON + port*4))
-			break;
-	}
-#endif
-	/* Clear ILT */
-	bnx2x_clear_func_ilt(bp, func);
-
-	/* Timers workaround bug for E2: if this is vnic-3,
-	 * we need to set the entire ilt range for this timers.
-	 */
-	if (!CHIP_IS_E1x(bp) && BP_VN(bp) == 3) {
-		struct ilt_client_info ilt_cli;
-		/* use dummy TM client */
-		memset(&ilt_cli, 0, sizeof(struct ilt_client_info));
-		ilt_cli.start = 0;
-		ilt_cli.end = ILT_NUM_PAGE_ENTRIES - 1;
-		ilt_cli.client_num = ILT_CLIENT_TM;
-
-		bnx2x_ilt_boundry_init_op(bp, &ilt_cli, 0, INITOP_CLEAR);
-	}
-
-	/* this assumes that reset_port() called before reset_func()*/
-	if (!CHIP_IS_E1x(bp))
-		bnx2x_pf_disable(bp);
-
-	bp->dmae_ready = 0;
-}
-
-static void bnx2x_reset_port(struct bnx2x *bp)
-{
-	int port = BP_PORT(bp);
-	u32 val;
-
-	/* Reset physical Link */
-	bnx2x__link_reset(bp);
-
-	REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0);
-
-	/* Do not rcv packets to BRB */
-	REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK + port*4, 0x0);
-	/* Do not direct rcv packets that are not for MCP to the BRB */
-	REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_NOT_MCP :
-			   NIG_REG_LLH0_BRB1_NOT_MCP), 0x0);
-
-	/* Configure AEU */
-	REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4, 0);
-
-	msleep(100);
-	/* Check for BRB port occupancy */
-	val = REG_RD(bp, BRB1_REG_PORT_NUM_OCC_BLOCKS_0 + port*4);
-	if (val)
-		DP(NETIF_MSG_IFDOWN,
-		   "BRB1 is not empty  %d blocks are occupied\n", val);
-
-	/* TODO: Close Doorbell port? */
-}
-
-static inline int bnx2x_reset_hw(struct bnx2x *bp, u32 load_code)
-{
-	struct bnx2x_func_state_params func_params = {0};
-
-	/* Prepare parameters for function state transitions */
-	__set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
-
-	func_params.f_obj = &bp->func_obj;
-	func_params.cmd = BNX2X_F_CMD_HW_RESET;
-
-	func_params.params.hw_init.load_phase = load_code;
-
-	return bnx2x_func_state_change(bp, &func_params);
-}
-
-static inline int bnx2x_func_stop(struct bnx2x *bp)
-{
-	struct bnx2x_func_state_params func_params = {0};
-	int rc;
-
-	/* Prepare parameters for function state transitions */
-	__set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
-	func_params.f_obj = &bp->func_obj;
-	func_params.cmd = BNX2X_F_CMD_STOP;
-
-	/*
-	 * Try to stop the function the 'good way'. If fails (in case
-	 * of a parity error during bnx2x_chip_cleanup()) and we are
-	 * not in a debug mode, perform a state transaction in order to
-	 * enable further HW_RESET transaction.
-	 */
-	rc = bnx2x_func_state_change(bp, &func_params);
-	if (rc) {
-#ifdef BNX2X_STOP_ON_ERROR
-		return rc;
-#else
-		BNX2X_ERR("FUNC_STOP ramrod failed. Running a dry "
-			  "transaction\n");
-		__set_bit(RAMROD_DRV_CLR_ONLY, &func_params.ramrod_flags);
-		return bnx2x_func_state_change(bp, &func_params);
-#endif
-	}
-
-	return 0;
-}
-
-/**
- * bnx2x_send_unload_req - request unload mode from the MCP.
- *
- * @bp:			driver handle
- * @unload_mode:	requested function's unload mode
- *
- * Return unload mode returned by the MCP: COMMON, PORT or FUNC.
- */
-u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode)
-{
-	u32 reset_code = 0;
-	int port = BP_PORT(bp);
-
-	/* Select the UNLOAD request mode */
-	if (unload_mode == UNLOAD_NORMAL)
-		reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
-
-	else if (bp->flags & NO_WOL_FLAG)
-		reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP;
-
-	else if (bp->wol) {
-		u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-		u8 *mac_addr = bp->dev->dev_addr;
-		u32 val;
-		u16 pmc;
-
-		/* The mac address is written to entries 1-4 to
-		 * preserve entry 0 which is used by the PMF
-		 */
-		u8 entry = (BP_VN(bp) + 1)*8;
-
-		val = (mac_addr[0] << 8) | mac_addr[1];
-		EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry, val);
-
-		val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
-		      (mac_addr[4] << 8) | mac_addr[5];
-		EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry + 4, val);
-
-		/* Enable the PME and clear the status */
-		pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmc);
-		pmc |= PCI_PM_CTRL_PME_ENABLE | PCI_PM_CTRL_PME_STATUS;
-		pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, pmc);
-
-		reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN;
-
-	} else
-		reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
-
-	/* Send the request to the MCP */
-	if (!BP_NOMCP(bp))
-		reset_code = bnx2x_fw_command(bp, reset_code, 0);
-	else {
-		int path = BP_PATH(bp);
-
-		DP(NETIF_MSG_IFDOWN, "NO MCP - load counts[%d]      "
-				     "%d, %d, %d\n",
-		   path, load_count[path][0], load_count[path][1],
-		   load_count[path][2]);
-		load_count[path][0]--;
-		load_count[path][1 + port]--;
-		DP(NETIF_MSG_IFDOWN, "NO MCP - new load counts[%d]  "
-				     "%d, %d, %d\n",
-		   path, load_count[path][0], load_count[path][1],
-		   load_count[path][2]);
-		if (load_count[path][0] == 0)
-			reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON;
-		else if (load_count[path][1 + port] == 0)
-			reset_code = FW_MSG_CODE_DRV_UNLOAD_PORT;
-		else
-			reset_code = FW_MSG_CODE_DRV_UNLOAD_FUNCTION;
-	}
-
-	return reset_code;
-}
-
-/**
- * bnx2x_send_unload_done - send UNLOAD_DONE command to the MCP.
- *
- * @bp:		driver handle
- */
-void bnx2x_send_unload_done(struct bnx2x *bp)
-{
-	/* Report UNLOAD_DONE to MCP */
-	if (!BP_NOMCP(bp))
-		bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
-}
-
-static inline int bnx2x_func_wait_started(struct bnx2x *bp)
-{
-	int tout = 50;
-	int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
-
-	if (!bp->port.pmf)
-		return 0;
-
-	/*
-	 * (assumption: No Attention from MCP at this stage)
-	 * PMF probably in the middle of TXdisable/enable transaction
-	 * 1. Sync IRS for default SB
-	 * 2. Sync SP queue - this guarantes us that attention handling started
-	 * 3. Wait, that TXdisable/enable transaction completes
-	 *
-	 * 1+2 guranty that if DCBx attention was scheduled it already changed
-	 * pending bit of transaction from STARTED-->TX_STOPPED, if we alredy
-	 * received complettion for the transaction the state is TX_STOPPED.
-	 * State will return to STARTED after completion of TX_STOPPED-->STARTED
-	 * transaction.
-	 */
-
-	/* make sure default SB ISR is done */
-	if (msix)
-		synchronize_irq(bp->msix_table[0].vector);
-	else
-		synchronize_irq(bp->pdev->irq);
-
-	flush_workqueue(bnx2x_wq);
-
-	while (bnx2x_func_get_state(bp, &bp->func_obj) !=
-				BNX2X_F_STATE_STARTED && tout--)
-		msleep(20);
-
-	if (bnx2x_func_get_state(bp, &bp->func_obj) !=
-						BNX2X_F_STATE_STARTED) {
-#ifdef BNX2X_STOP_ON_ERROR
-		return -EBUSY;
-#else
-		/*
-		 * Failed to complete the transaction in a "good way"
-		 * Force both transactions with CLR bit
-		 */
-		struct bnx2x_func_state_params func_params = {0};
-
-		DP(BNX2X_MSG_SP, "Hmmm... unexpected function state! "
-			  "Forcing STARTED-->TX_ST0PPED-->STARTED\n");
-
-		func_params.f_obj = &bp->func_obj;
-		__set_bit(RAMROD_DRV_CLR_ONLY,
-					&func_params.ramrod_flags);
-
-		/* STARTED-->TX_ST0PPED */
-		func_params.cmd = BNX2X_F_CMD_TX_STOP;
-		bnx2x_func_state_change(bp, &func_params);
-
-		/* TX_ST0PPED-->STARTED */
-		func_params.cmd = BNX2X_F_CMD_TX_START;
-		return bnx2x_func_state_change(bp, &func_params);
-#endif
-	}
-
-	return 0;
-}
-
-void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
-{
-	int port = BP_PORT(bp);
-	int i, rc = 0;
-	u8 cos;
-	struct bnx2x_mcast_ramrod_params rparam = {0};
-	u32 reset_code;
-
-	/* Wait until tx fastpath tasks complete */
-	for_each_tx_queue(bp, i) {
-		struct bnx2x_fastpath *fp = &bp->fp[i];
-
-		for_each_cos_in_tx_queue(fp, cos)
-			rc = bnx2x_clean_tx_queue(bp, &fp->txdata[cos]);
-#ifdef BNX2X_STOP_ON_ERROR
-		if (rc)
-			return;
-#endif
-	}
-
-	/* Give HW time to discard old tx messages */
-	usleep_range(1000, 1000);
-
-	/* Clean all ETH MACs */
-	rc = bnx2x_del_all_macs(bp, &bp->fp[0].mac_obj, BNX2X_ETH_MAC, false);
-	if (rc < 0)
-		BNX2X_ERR("Failed to delete all ETH macs: %d\n", rc);
-
-	/* Clean up UC list  */
-	rc = bnx2x_del_all_macs(bp, &bp->fp[0].mac_obj, BNX2X_UC_LIST_MAC,
-				true);
-	if (rc < 0)
-		BNX2X_ERR("Failed to schedule DEL commands for UC MACs list: "
-			  "%d\n", rc);
-
-	/* Disable LLH */
-	if (!CHIP_IS_E1(bp))
-		REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
-
-	/* Set "drop all" (stop Rx).
-	 * We need to take a netif_addr_lock() here in order to prevent
-	 * a race between the completion code and this code.
-	 */
-	netif_addr_lock_bh(bp->dev);
-	/* Schedule the rx_mode command */
-	if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state))
-		set_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state);
-	else
-		bnx2x_set_storm_rx_mode(bp);
-
-	/* Cleanup multicast configuration */
-	rparam.mcast_obj = &bp->mcast_obj;
-	rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
-	if (rc < 0)
-		BNX2X_ERR("Failed to send DEL multicast command: %d\n", rc);
-
-	netif_addr_unlock_bh(bp->dev);
-
-
-
-	/*
-	 * Send the UNLOAD_REQUEST to the MCP. This will return if
-	 * this function should perform FUNC, PORT or COMMON HW
-	 * reset.
-	 */
-	reset_code = bnx2x_send_unload_req(bp, unload_mode);
-
-	/*
-	 * (assumption: No Attention from MCP at this stage)
-	 * PMF probably in the middle of TXdisable/enable transaction
-	 */
-	rc = bnx2x_func_wait_started(bp);
-	if (rc) {
-		BNX2X_ERR("bnx2x_func_wait_started failed\n");
-#ifdef BNX2X_STOP_ON_ERROR
-		return;
-#endif
-	}
-
-	/* Close multi and leading connections
-	 * Completions for ramrods are collected in a synchronous way
-	 */
-	for_each_queue(bp, i)
-		if (bnx2x_stop_queue(bp, i))
-#ifdef BNX2X_STOP_ON_ERROR
-			return;
-#else
-			goto unload_error;
-#endif
-	/* If SP settings didn't get completed so far - something
-	 * very wrong has happen.
-	 */
-	if (!bnx2x_wait_sp_comp(bp, ~0x0UL))
-		BNX2X_ERR("Hmmm... Common slow path ramrods got stuck!\n");
-
-#ifndef BNX2X_STOP_ON_ERROR
-unload_error:
-#endif
-	rc = bnx2x_func_stop(bp);
-	if (rc) {
-		BNX2X_ERR("Function stop failed!\n");
-#ifdef BNX2X_STOP_ON_ERROR
-		return;
-#endif
-	}
-
-	/* Disable HW interrupts, NAPI */
-	bnx2x_netif_stop(bp, 1);
-
-	/* Release IRQs */
-	bnx2x_free_irq(bp);
-
-	/* Reset the chip */
-	rc = bnx2x_reset_hw(bp, reset_code);
-	if (rc)
-		BNX2X_ERR("HW_RESET failed\n");
-
-
-	/* Report UNLOAD_DONE to MCP */
-	bnx2x_send_unload_done(bp);
-}
-
-void bnx2x_disable_close_the_gate(struct bnx2x *bp)
-{
-	u32 val;
-
-	DP(NETIF_MSG_HW, "Disabling \"close the gates\"\n");
-
-	if (CHIP_IS_E1(bp)) {
-		int port = BP_PORT(bp);
-		u32 addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
-			MISC_REG_AEU_MASK_ATTN_FUNC_0;
-
-		val = REG_RD(bp, addr);
-		val &= ~(0x300);
-		REG_WR(bp, addr, val);
-	} else {
-		val = REG_RD(bp, MISC_REG_AEU_GENERAL_MASK);
-		val &= ~(MISC_AEU_GENERAL_MASK_REG_AEU_PXP_CLOSE_MASK |
-			 MISC_AEU_GENERAL_MASK_REG_AEU_NIG_CLOSE_MASK);
-		REG_WR(bp, MISC_REG_AEU_GENERAL_MASK, val);
-	}
-}
-
-/* Close gates #2, #3 and #4: */
-static void bnx2x_set_234_gates(struct bnx2x *bp, bool close)
-{
-	u32 val;
-
-	/* Gates #2 and #4a are closed/opened for "not E1" only */
-	if (!CHIP_IS_E1(bp)) {
-		/* #4 */
-		REG_WR(bp, PXP_REG_HST_DISCARD_DOORBELLS, !!close);
-		/* #2 */
-		REG_WR(bp, PXP_REG_HST_DISCARD_INTERNAL_WRITES, !!close);
-	}
-
-	/* #3 */
-	if (CHIP_IS_E1x(bp)) {
-		/* Prevent interrupts from HC on both ports */
-		val = REG_RD(bp, HC_REG_CONFIG_1);
-		REG_WR(bp, HC_REG_CONFIG_1,
-		       (!close) ? (val | HC_CONFIG_1_REG_BLOCK_DISABLE_1) :
-		       (val & ~(u32)HC_CONFIG_1_REG_BLOCK_DISABLE_1));
-
-		val = REG_RD(bp, HC_REG_CONFIG_0);
-		REG_WR(bp, HC_REG_CONFIG_0,
-		       (!close) ? (val | HC_CONFIG_0_REG_BLOCK_DISABLE_0) :
-		       (val & ~(u32)HC_CONFIG_0_REG_BLOCK_DISABLE_0));
-	} else {
-		/* Prevent incomming interrupts in IGU */
-		val = REG_RD(bp, IGU_REG_BLOCK_CONFIGURATION);
-
-		REG_WR(bp, IGU_REG_BLOCK_CONFIGURATION,
-		       (!close) ?
-		       (val | IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE) :
-		       (val & ~(u32)IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE));
-	}
-
-	DP(NETIF_MSG_HW, "%s gates #2, #3 and #4\n",
-		close ? "closing" : "opening");
-	mmiowb();
-}
-
-#define SHARED_MF_CLP_MAGIC  0x80000000 /* `magic' bit */
-
-static void bnx2x_clp_reset_prep(struct bnx2x *bp, u32 *magic_val)
-{
-	/* Do some magic... */
-	u32 val = MF_CFG_RD(bp, shared_mf_config.clp_mb);
-	*magic_val = val & SHARED_MF_CLP_MAGIC;
-	MF_CFG_WR(bp, shared_mf_config.clp_mb, val | SHARED_MF_CLP_MAGIC);
-}
-
-/**
- * bnx2x_clp_reset_done - restore the value of the `magic' bit.
- *
- * @bp:		driver handle
- * @magic_val:	old value of the `magic' bit.
- */
-static void bnx2x_clp_reset_done(struct bnx2x *bp, u32 magic_val)
-{
-	/* Restore the `magic' bit value... */
-	u32 val = MF_CFG_RD(bp, shared_mf_config.clp_mb);
-	MF_CFG_WR(bp, shared_mf_config.clp_mb,
-		(val & (~SHARED_MF_CLP_MAGIC)) | magic_val);
-}
-
-/**
- * bnx2x_reset_mcp_prep - prepare for MCP reset.
- *
- * @bp:		driver handle
- * @magic_val:	old value of 'magic' bit.
- *
- * Takes care of CLP configurations.
- */
-static void bnx2x_reset_mcp_prep(struct bnx2x *bp, u32 *magic_val)
-{
-	u32 shmem;
-	u32 validity_offset;
-
-	DP(NETIF_MSG_HW, "Starting\n");
-
-	/* Set `magic' bit in order to save MF config */
-	if (!CHIP_IS_E1(bp))
-		bnx2x_clp_reset_prep(bp, magic_val);
-
-	/* Get shmem offset */
-	shmem = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR);
-	validity_offset = offsetof(struct shmem_region, validity_map[0]);
-
-	/* Clear validity map flags */
-	if (shmem > 0)
-		REG_WR(bp, shmem + validity_offset, 0);
-}
-
-#define MCP_TIMEOUT      5000   /* 5 seconds (in ms) */
-#define MCP_ONE_TIMEOUT  100    /* 100 ms */
-
-/**
- * bnx2x_mcp_wait_one - wait for MCP_ONE_TIMEOUT
- *
- * @bp:	driver handle
- */
-static inline void bnx2x_mcp_wait_one(struct bnx2x *bp)
-{
-	/* special handling for emulation and FPGA,
-	   wait 10 times longer */
-	if (CHIP_REV_IS_SLOW(bp))
-		msleep(MCP_ONE_TIMEOUT*10);
-	else
-		msleep(MCP_ONE_TIMEOUT);
-}
-
-/*
- * initializes bp->common.shmem_base and waits for validity signature to appear
- */
-static int bnx2x_init_shmem(struct bnx2x *bp)
-{
-	int cnt = 0;
-	u32 val = 0;
-
-	do {
-		bp->common.shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR);
-		if (bp->common.shmem_base) {
-			val = SHMEM_RD(bp, validity_map[BP_PORT(bp)]);
-			if (val & SHR_MEM_VALIDITY_MB)
-				return 0;
-		}
-
-		bnx2x_mcp_wait_one(bp);
-
-	} while (cnt++ < (MCP_TIMEOUT / MCP_ONE_TIMEOUT));
-
-	BNX2X_ERR("BAD MCP validity signature\n");
-
-	return -ENODEV;
-}
-
-static int bnx2x_reset_mcp_comp(struct bnx2x *bp, u32 magic_val)
-{
-	int rc = bnx2x_init_shmem(bp);
-
-	/* Restore the `magic' bit value */
-	if (!CHIP_IS_E1(bp))
-		bnx2x_clp_reset_done(bp, magic_val);
-
-	return rc;
-}
-
-static void bnx2x_pxp_prep(struct bnx2x *bp)
-{
-	if (!CHIP_IS_E1(bp)) {
-		REG_WR(bp, PXP2_REG_RD_START_INIT, 0);
-		REG_WR(bp, PXP2_REG_RQ_RBC_DONE, 0);
-		mmiowb();
-	}
-}
-
-/*
- * Reset the whole chip except for:
- *      - PCIE core
- *      - PCI Glue, PSWHST, PXP/PXP2 RF (all controlled by
- *              one reset bit)
- *      - IGU
- *      - MISC (including AEU)
- *      - GRC
- *      - RBCN, RBCP
- */
-static void bnx2x_process_kill_chip_reset(struct bnx2x *bp, bool global)
-{
-	u32 not_reset_mask1, reset_mask1, not_reset_mask2, reset_mask2;
-	u32 global_bits2, stay_reset2;
-
-	/*
-	 * Bits that have to be set in reset_mask2 if we want to reset 'global'
-	 * (per chip) blocks.
-	 */
-	global_bits2 =
-		MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CPU |
-		MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CORE;
-
-	/* Don't reset the following blocks */
-	not_reset_mask1 =
-		MISC_REGISTERS_RESET_REG_1_RST_HC |
-		MISC_REGISTERS_RESET_REG_1_RST_PXPV |
-		MISC_REGISTERS_RESET_REG_1_RST_PXP;
-
-	not_reset_mask2 =
-		MISC_REGISTERS_RESET_REG_2_RST_PCI_MDIO |
-		MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE |
-		MISC_REGISTERS_RESET_REG_2_RST_EMAC1_HARD_CORE |
-		MISC_REGISTERS_RESET_REG_2_RST_MISC_CORE |
-		MISC_REGISTERS_RESET_REG_2_RST_RBCN |
-		MISC_REGISTERS_RESET_REG_2_RST_GRC  |
-		MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_REG_HARD_CORE |
-		MISC_REGISTERS_RESET_REG_2_RST_MCP_N_HARD_CORE_RST_B |
-		MISC_REGISTERS_RESET_REG_2_RST_ATC |
-		MISC_REGISTERS_RESET_REG_2_PGLC;
-
-	/*
-	 * Keep the following blocks in reset:
-	 *  - all xxMACs are handled by the bnx2x_link code.
-	 */
-	stay_reset2 =
-		MISC_REGISTERS_RESET_REG_2_RST_BMAC0 |
-		MISC_REGISTERS_RESET_REG_2_RST_BMAC1 |
-		MISC_REGISTERS_RESET_REG_2_RST_EMAC0 |
-		MISC_REGISTERS_RESET_REG_2_RST_EMAC1 |
-		MISC_REGISTERS_RESET_REG_2_UMAC0 |
-		MISC_REGISTERS_RESET_REG_2_UMAC1 |
-		MISC_REGISTERS_RESET_REG_2_XMAC |
-		MISC_REGISTERS_RESET_REG_2_XMAC_SOFT;
-
-	/* Full reset masks according to the chip */
-	reset_mask1 = 0xffffffff;
-
-	if (CHIP_IS_E1(bp))
-		reset_mask2 = 0xffff;
-	else if (CHIP_IS_E1H(bp))
-		reset_mask2 = 0x1ffff;
-	else if (CHIP_IS_E2(bp))
-		reset_mask2 = 0xfffff;
-	else /* CHIP_IS_E3 */
-		reset_mask2 = 0x3ffffff;
-
-	/* Don't reset global blocks unless we need to */
-	if (!global)
-		reset_mask2 &= ~global_bits2;
-
-	/*
-	 * In case of attention in the QM, we need to reset PXP
-	 * (MISC_REGISTERS_RESET_REG_2_RST_PXP_RQ_RD_WR) before QM
-	 * because otherwise QM reset would release 'close the gates' shortly
-	 * before resetting the PXP, then the PSWRQ would send a write
-	 * request to PGLUE. Then when PXP is reset, PGLUE would try to
-	 * read the payload data from PSWWR, but PSWWR would not
-	 * respond. The write queue in PGLUE would stuck, dmae commands
-	 * would not return. Therefore it's important to reset the second
-	 * reset register (containing the
-	 * MISC_REGISTERS_RESET_REG_2_RST_PXP_RQ_RD_WR bit) before the
-	 * first one (containing the MISC_REGISTERS_RESET_REG_1_RST_QM
-	 * bit).
-	 */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-	       reset_mask2 & (~not_reset_mask2));
-
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
-	       reset_mask1 & (~not_reset_mask1));
-
-	barrier();
-	mmiowb();
-
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
-	       reset_mask2 & (~stay_reset2));
-
-	barrier();
-	mmiowb();
-
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, reset_mask1);
-	mmiowb();
-}
-
-/**
- * bnx2x_er_poll_igu_vq - poll for pending writes bit.
- * It should get cleared in no more than 1s.
- *
- * @bp:	driver handle
- *
- * It should get cleared in no more than 1s. Returns 0 if
- * pending writes bit gets cleared.
- */
-static int bnx2x_er_poll_igu_vq(struct bnx2x *bp)
-{
-	u32 cnt = 1000;
-	u32 pend_bits = 0;
-
-	do {
-		pend_bits  = REG_RD(bp, IGU_REG_PENDING_BITS_STATUS);
-
-		if (pend_bits == 0)
-			break;
-
-		usleep_range(1000, 1000);
-	} while (cnt-- > 0);
-
-	if (cnt <= 0) {
-		BNX2X_ERR("Still pending IGU requests pend_bits=%x!\n",
-			  pend_bits);
-		return -EBUSY;
-	}
-
-	return 0;
-}
-
-static int bnx2x_process_kill(struct bnx2x *bp, bool global)
-{
-	int cnt = 1000;
-	u32 val = 0;
-	u32 sr_cnt, blk_cnt, port_is_idle_0, port_is_idle_1, pgl_exp_rom2;
-
-
-	/* Empty the Tetris buffer, wait for 1s */
-	do {
-		sr_cnt  = REG_RD(bp, PXP2_REG_RD_SR_CNT);
-		blk_cnt = REG_RD(bp, PXP2_REG_RD_BLK_CNT);
-		port_is_idle_0 = REG_RD(bp, PXP2_REG_RD_PORT_IS_IDLE_0);
-		port_is_idle_1 = REG_RD(bp, PXP2_REG_RD_PORT_IS_IDLE_1);
-		pgl_exp_rom2 = REG_RD(bp, PXP2_REG_PGL_EXP_ROM2);
-		if ((sr_cnt == 0x7e) && (blk_cnt == 0xa0) &&
-		    ((port_is_idle_0 & 0x1) == 0x1) &&
-		    ((port_is_idle_1 & 0x1) == 0x1) &&
-		    (pgl_exp_rom2 == 0xffffffff))
-			break;
-		usleep_range(1000, 1000);
-	} while (cnt-- > 0);
-
-	if (cnt <= 0) {
-		DP(NETIF_MSG_HW, "Tetris buffer didn't get empty or there"
-			  " are still"
-			  " outstanding read requests after 1s!\n");
-		DP(NETIF_MSG_HW, "sr_cnt=0x%08x, blk_cnt=0x%08x,"
-			  " port_is_idle_0=0x%08x,"
-			  " port_is_idle_1=0x%08x, pgl_exp_rom2=0x%08x\n",
-			  sr_cnt, blk_cnt, port_is_idle_0, port_is_idle_1,
-			  pgl_exp_rom2);
-		return -EAGAIN;
-	}
-
-	barrier();
-
-	/* Close gates #2, #3 and #4 */
-	bnx2x_set_234_gates(bp, true);
-
-	/* Poll for IGU VQs for 57712 and newer chips */
-	if (!CHIP_IS_E1x(bp) && bnx2x_er_poll_igu_vq(bp))
-		return -EAGAIN;
-
-
-	/* TBD: Indicate that "process kill" is in progress to MCP */
-
-	/* Clear "unprepared" bit */
-	REG_WR(bp, MISC_REG_UNPREPARED, 0);
-	barrier();
-
-	/* Make sure all is written to the chip before the reset */
-	mmiowb();
-
-	/* Wait for 1ms to empty GLUE and PCI-E core queues,
-	 * PSWHST, GRC and PSWRD Tetris buffer.
-	 */
-	usleep_range(1000, 1000);
-
-	/* Prepare to chip reset: */
-	/* MCP */
-	if (global)
-		bnx2x_reset_mcp_prep(bp, &val);
-
-	/* PXP */
-	bnx2x_pxp_prep(bp);
-	barrier();
-
-	/* reset the chip */
-	bnx2x_process_kill_chip_reset(bp, global);
-	barrier();
-
-	/* Recover after reset: */
-	/* MCP */
-	if (global && bnx2x_reset_mcp_comp(bp, val))
-		return -EAGAIN;
-
-	/* TBD: Add resetting the NO_MCP mode DB here */
-
-	/* PXP */
-	bnx2x_pxp_prep(bp);
-
-	/* Open the gates #2, #3 and #4 */
-	bnx2x_set_234_gates(bp, false);
-
-	/* TBD: IGU/AEU preparation bring back the AEU/IGU to a
-	 * reset state, re-enable attentions. */
-
-	return 0;
-}
-
-int bnx2x_leader_reset(struct bnx2x *bp)
-{
-	int rc = 0;
-	bool global = bnx2x_reset_is_global(bp);
-
-	/* Try to recover after the failure */
-	if (bnx2x_process_kill(bp, global)) {
-		netdev_err(bp->dev, "Something bad had happen on engine %d! "
-				    "Aii!\n", BP_PATH(bp));
-		rc = -EAGAIN;
-		goto exit_leader_reset;
-	}
-
-	/*
-	 * Clear RESET_IN_PROGRES and RESET_GLOBAL bits and update the driver
-	 * state.
-	 */
-	bnx2x_set_reset_done(bp);
-	if (global)
-		bnx2x_clear_reset_global(bp);
-
-exit_leader_reset:
-	bp->is_leader = 0;
-	bnx2x_release_leader_lock(bp);
-	smp_mb();
-	return rc;
-}
-
-static inline void bnx2x_recovery_failed(struct bnx2x *bp)
-{
-	netdev_err(bp->dev, "Recovery has failed. Power cycle is needed.\n");
-
-	/* Disconnect this device */
-	netif_device_detach(bp->dev);
-
-	/*
-	 * Block ifup for all function on this engine until "process kill"
-	 * or power cycle.
-	 */
-	bnx2x_set_reset_in_progress(bp);
-
-	/* Shut down the power */
-	bnx2x_set_power_state(bp, PCI_D3hot);
-
-	bp->recovery_state = BNX2X_RECOVERY_FAILED;
-
-	smp_mb();
-}
-
-/*
- * Assumption: runs under rtnl lock. This together with the fact
- * that it's called only from bnx2x_sp_rtnl() ensure that it
- * will never be called when netif_running(bp->dev) is false.
- */
-static void bnx2x_parity_recover(struct bnx2x *bp)
-{
-	bool global = false;
-
-	DP(NETIF_MSG_HW, "Handling parity\n");
-	while (1) {
-		switch (bp->recovery_state) {
-		case BNX2X_RECOVERY_INIT:
-			DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_INIT\n");
-			bnx2x_chk_parity_attn(bp, &global, false);
-
-			/* Try to get a LEADER_LOCK HW lock */
-			if (bnx2x_trylock_leader_lock(bp)) {
-				bnx2x_set_reset_in_progress(bp);
-				/*
-				 * Check if there is a global attention and if
-				 * there was a global attention, set the global
-				 * reset bit.
-				 */
-
-				if (global)
-					bnx2x_set_reset_global(bp);
-
-				bp->is_leader = 1;
-			}
-
-			/* Stop the driver */
-			/* If interface has been removed - break */
-			if (bnx2x_nic_unload(bp, UNLOAD_RECOVERY))
-				return;
-
-			bp->recovery_state = BNX2X_RECOVERY_WAIT;
-
-			/*
-			 * Reset MCP command sequence number and MCP mail box
-			 * sequence as we are going to reset the MCP.
-			 */
-			if (global) {
-				bp->fw_seq = 0;
-				bp->fw_drv_pulse_wr_seq = 0;
-			}
-
-			/* Ensure "is_leader", MCP command sequence and
-			 * "recovery_state" update values are seen on other
-			 * CPUs.
-			 */
-			smp_mb();
-			break;
-
-		case BNX2X_RECOVERY_WAIT:
-			DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_WAIT\n");
-			if (bp->is_leader) {
-				int other_engine = BP_PATH(bp) ? 0 : 1;
-				u32 other_load_counter =
-					bnx2x_get_load_cnt(bp, other_engine);
-				u32 load_counter =
-					bnx2x_get_load_cnt(bp, BP_PATH(bp));
-				global = bnx2x_reset_is_global(bp);
-
-				/*
-				 * In case of a parity in a global block, let
-				 * the first leader that performs a
-				 * leader_reset() reset the global blocks in
-				 * order to clear global attentions. Otherwise
-				 * the the gates will remain closed for that
-				 * engine.
-				 */
-				if (load_counter ||
-				    (global && other_load_counter)) {
-					/* Wait until all other functions get
-					 * down.
-					 */
-					schedule_delayed_work(&bp->sp_rtnl_task,
-								HZ/10);
-					return;
-				} else {
-					/* If all other functions got down -
-					 * try to bring the chip back to
-					 * normal. In any case it's an exit
-					 * point for a leader.
-					 */
-					if (bnx2x_leader_reset(bp)) {
-						bnx2x_recovery_failed(bp);
-						return;
-					}
-
-					/* If we are here, means that the
-					 * leader has succeeded and doesn't
-					 * want to be a leader any more. Try
-					 * to continue as a none-leader.
-					 */
-					break;
-				}
-			} else { /* non-leader */
-				if (!bnx2x_reset_is_done(bp, BP_PATH(bp))) {
-					/* Try to get a LEADER_LOCK HW lock as
-					 * long as a former leader may have
-					 * been unloaded by the user or
-					 * released a leadership by another
-					 * reason.
-					 */
-					if (bnx2x_trylock_leader_lock(bp)) {
-						/* I'm a leader now! Restart a
-						 * switch case.
-						 */
-						bp->is_leader = 1;
-						break;
-					}
-
-					schedule_delayed_work(&bp->sp_rtnl_task,
-								HZ/10);
-					return;
-
-				} else {
-					/*
-					 * If there was a global attention, wait
-					 * for it to be cleared.
-					 */
-					if (bnx2x_reset_is_global(bp)) {
-						schedule_delayed_work(
-							&bp->sp_rtnl_task,
-							HZ/10);
-						return;
-					}
-
-					if (bnx2x_nic_load(bp, LOAD_NORMAL))
-						bnx2x_recovery_failed(bp);
-					else {
-						bp->recovery_state =
-							BNX2X_RECOVERY_DONE;
-						smp_mb();
-					}
-
-					return;
-				}
-			}
-		default:
-			return;
-		}
-	}
-}
-
-/* bnx2x_nic_unload() flushes the bnx2x_wq, thus reset task is
- * scheduled on a general queue in order to prevent a dead lock.
- */
-static void bnx2x_sp_rtnl_task(struct work_struct *work)
-{
-	struct bnx2x *bp = container_of(work, struct bnx2x, sp_rtnl_task.work);
-
-	rtnl_lock();
-
-	if (!netif_running(bp->dev))
-		goto sp_rtnl_exit;
-
-	/* if stop on error is defined no recovery flows should be executed */
-#ifdef BNX2X_STOP_ON_ERROR
-	BNX2X_ERR("recovery flow called but STOP_ON_ERROR defined "
-		  "so reset not done to allow debug dump,\n"
-		  "you will need to reboot when done\n");
-	goto sp_rtnl_not_reset;
-#endif
-
-	if (unlikely(bp->recovery_state != BNX2X_RECOVERY_DONE)) {
-		/*
-		 * Clear all pending SP commands as we are going to reset the
-		 * function anyway.
-		 */
-		bp->sp_rtnl_state = 0;
-		smp_mb();
-
-		bnx2x_parity_recover(bp);
-
-		goto sp_rtnl_exit;
-	}
-
-	if (test_and_clear_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state)) {
-		/*
-		 * Clear all pending SP commands as we are going to reset the
-		 * function anyway.
-		 */
-		bp->sp_rtnl_state = 0;
-		smp_mb();
-
-		bnx2x_nic_unload(bp, UNLOAD_NORMAL);
-		bnx2x_nic_load(bp, LOAD_NORMAL);
-
-		goto sp_rtnl_exit;
-	}
-#ifdef BNX2X_STOP_ON_ERROR
-sp_rtnl_not_reset:
-#endif
-	if (test_and_clear_bit(BNX2X_SP_RTNL_SETUP_TC, &bp->sp_rtnl_state))
-		bnx2x_setup_tc(bp->dev, bp->dcbx_port_params.ets.num_of_cos);
-
-sp_rtnl_exit:
-	rtnl_unlock();
-}
-
-/* end of nic load/unload */
-
-static void bnx2x_period_task(struct work_struct *work)
-{
-	struct bnx2x *bp = container_of(work, struct bnx2x, period_task.work);
-
-	if (!netif_running(bp->dev))
-		goto period_task_exit;
-
-	if (CHIP_REV_IS_SLOW(bp)) {
-		BNX2X_ERR("period task called on emulation, ignoring\n");
-		goto period_task_exit;
-	}
-
-	bnx2x_acquire_phy_lock(bp);
-	/*
-	 * The barrier is needed to ensure the ordering between the writing to
-	 * the bp->port.pmf in the bnx2x_nic_load() or bnx2x_pmf_update() and
-	 * the reading here.
-	 */
-	smp_mb();
-	if (bp->port.pmf) {
-		bnx2x_period_func(&bp->link_params, &bp->link_vars);
-
-		/* Re-queue task in 1 sec */
-		queue_delayed_work(bnx2x_wq, &bp->period_task, 1*HZ);
-	}
-
-	bnx2x_release_phy_lock(bp);
-period_task_exit:
-	return;
-}
-
-/*
- * Init service functions
- */
-
-static u32 bnx2x_get_pretend_reg(struct bnx2x *bp)
-{
-	u32 base = PXP2_REG_PGL_PRETEND_FUNC_F0;
-	u32 stride = PXP2_REG_PGL_PRETEND_FUNC_F1 - base;
-	return base + (BP_ABS_FUNC(bp)) * stride;
-}
-
-static void bnx2x_undi_int_disable_e1h(struct bnx2x *bp)
-{
-	u32 reg = bnx2x_get_pretend_reg(bp);
-
-	/* Flush all outstanding writes */
-	mmiowb();
-
-	/* Pretend to be function 0 */
-	REG_WR(bp, reg, 0);
-	REG_RD(bp, reg);	/* Flush the GRC transaction (in the chip) */
-
-	/* From now we are in the "like-E1" mode */
-	bnx2x_int_disable(bp);
-
-	/* Flush all outstanding writes */
-	mmiowb();
-
-	/* Restore the original function */
-	REG_WR(bp, reg, BP_ABS_FUNC(bp));
-	REG_RD(bp, reg);
-}
-
-static inline void bnx2x_undi_int_disable(struct bnx2x *bp)
-{
-	if (CHIP_IS_E1(bp))
-		bnx2x_int_disable(bp);
-	else
-		bnx2x_undi_int_disable_e1h(bp);
-}
-
-static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
-{
-	u32 val;
-
-	/* Check if there is any driver already loaded */
-	val = REG_RD(bp, MISC_REG_UNPREPARED);
-	if (val == 0x1) {
-
-		bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
-		/*
-		 * Check if it is the UNDI driver
-		 * UNDI driver initializes CID offset for normal bell to 0x7
-		 */
-		val = REG_RD(bp, DORQ_REG_NORM_CID_OFST);
-		if (val == 0x7) {
-			u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
-			/* save our pf_num */
-			int orig_pf_num = bp->pf_num;
-			int port;
-			u32 swap_en, swap_val, value;
-
-			/* clear the UNDI indication */
-			REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0);
-
-			BNX2X_DEV_INFO("UNDI is active! reset device\n");
-
-			/* try unload UNDI on port 0 */
-			bp->pf_num = 0;
-			bp->fw_seq =
-			      (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
-				DRV_MSG_SEQ_NUMBER_MASK);
-			reset_code = bnx2x_fw_command(bp, reset_code, 0);
-
-			/* if UNDI is loaded on the other port */
-			if (reset_code != FW_MSG_CODE_DRV_UNLOAD_COMMON) {
-
-				/* send "DONE" for previous unload */
-				bnx2x_fw_command(bp,
-						 DRV_MSG_CODE_UNLOAD_DONE, 0);
-
-				/* unload UNDI on port 1 */
-				bp->pf_num = 1;
-				bp->fw_seq =
-			      (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
-					DRV_MSG_SEQ_NUMBER_MASK);
-				reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
-
-				bnx2x_fw_command(bp, reset_code, 0);
-			}
-
-			bnx2x_undi_int_disable(bp);
-			port = BP_PORT(bp);
-
-			/* close input traffic and wait for it */
-			/* Do not rcv packets to BRB */
-			REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_DRV_MASK :
-					   NIG_REG_LLH0_BRB1_DRV_MASK), 0x0);
-			/* Do not direct rcv packets that are not for MCP to
-			 * the BRB */
-			REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_NOT_MCP :
-					   NIG_REG_LLH0_BRB1_NOT_MCP), 0x0);
-			/* clear AEU */
-			REG_WR(bp, (port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
-					   MISC_REG_AEU_MASK_ATTN_FUNC_0), 0);
-			msleep(10);
-
-			/* save NIG port swap info */
-			swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
-			swap_en = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
-			/* reset device */
-			REG_WR(bp,
-			       GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
-			       0xd3ffffff);
-
-			value = 0x1400;
-			if (CHIP_IS_E3(bp)) {
-				value |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
-				value |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
-			}
-
-			REG_WR(bp,
-			       GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-			       value);
-
-			/* take the NIG out of reset and restore swap values */
-			REG_WR(bp,
-			       GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
-			       MISC_REGISTERS_RESET_REG_1_RST_NIG);
-			REG_WR(bp, NIG_REG_PORT_SWAP, swap_val);
-			REG_WR(bp, NIG_REG_STRAP_OVERRIDE, swap_en);
-
-			/* send unload done to the MCP */
-			bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
-
-			/* restore our func and fw_seq */
-			bp->pf_num = orig_pf_num;
-			bp->fw_seq =
-			      (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
-				DRV_MSG_SEQ_NUMBER_MASK);
-		}
-
-		/* now it's safe to release the lock */
-		bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
-	}
-}
-
-static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
-{
-	u32 val, val2, val3, val4, id;
-	u16 pmc;
-
-	/* Get the chip revision id and number. */
-	/* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
-	val = REG_RD(bp, MISC_REG_CHIP_NUM);
-	id = ((val & 0xffff) << 16);
-	val = REG_RD(bp, MISC_REG_CHIP_REV);
-	id |= ((val & 0xf) << 12);
-	val = REG_RD(bp, MISC_REG_CHIP_METAL);
-	id |= ((val & 0xff) << 4);
-	val = REG_RD(bp, MISC_REG_BOND_ID);
-	id |= (val & 0xf);
-	bp->common.chip_id = id;
-
-	/* Set doorbell size */
-	bp->db_size = (1 << BNX2X_DB_SHIFT);
-
-	if (!CHIP_IS_E1x(bp)) {
-		val = REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR);
-		if ((val & 1) == 0)
-			val = REG_RD(bp, MISC_REG_PORT4MODE_EN);
-		else
-			val = (val >> 1) & 1;
-		BNX2X_DEV_INFO("chip is in %s\n", val ? "4_PORT_MODE" :
-						       "2_PORT_MODE");
-		bp->common.chip_port_mode = val ? CHIP_4_PORT_MODE :
-						 CHIP_2_PORT_MODE;
-
-		if (CHIP_MODE_IS_4_PORT(bp))
-			bp->pfid = (bp->pf_num >> 1);	/* 0..3 */
-		else
-			bp->pfid = (bp->pf_num & 0x6);	/* 0, 2, 4, 6 */
-	} else {
-		bp->common.chip_port_mode = CHIP_PORT_MODE_NONE; /* N/A */
-		bp->pfid = bp->pf_num;			/* 0..7 */
-	}
-
-	bp->link_params.chip_id = bp->common.chip_id;
-	BNX2X_DEV_INFO("chip ID is 0x%x\n", id);
-
-	val = (REG_RD(bp, 0x2874) & 0x55);
-	if ((bp->common.chip_id & 0x1) ||
-	    (CHIP_IS_E1(bp) && val) || (CHIP_IS_E1H(bp) && (val == 0x55))) {
-		bp->flags |= ONE_PORT_FLAG;
-		BNX2X_DEV_INFO("single port device\n");
-	}
-
-	val = REG_RD(bp, MCP_REG_MCPR_NVM_CFG4);
-	bp->common.flash_size = (BNX2X_NVRAM_1MB_SIZE <<
-				 (val & MCPR_NVM_CFG4_FLASH_SIZE));
-	BNX2X_DEV_INFO("flash_size 0x%x (%d)\n",
-		       bp->common.flash_size, bp->common.flash_size);
-
-	bnx2x_init_shmem(bp);
-
-
-
-	bp->common.shmem2_base = REG_RD(bp, (BP_PATH(bp) ?
-					MISC_REG_GENERIC_CR_1 :
-					MISC_REG_GENERIC_CR_0));
-
-	bp->link_params.shmem_base = bp->common.shmem_base;
-	bp->link_params.shmem2_base = bp->common.shmem2_base;
-	BNX2X_DEV_INFO("shmem offset 0x%x  shmem2 offset 0x%x\n",
-		       bp->common.shmem_base, bp->common.shmem2_base);
-
-	if (!bp->common.shmem_base) {
-		BNX2X_DEV_INFO("MCP not active\n");
-		bp->flags |= NO_MCP_FLAG;
-		return;
-	}
-
-	bp->common.hw_config = SHMEM_RD(bp, dev_info.shared_hw_config.config);
-	BNX2X_DEV_INFO("hw_config 0x%08x\n", bp->common.hw_config);
-
-	bp->link_params.hw_led_mode = ((bp->common.hw_config &
-					SHARED_HW_CFG_LED_MODE_MASK) >>
-				       SHARED_HW_CFG_LED_MODE_SHIFT);
-
-	bp->link_params.feature_config_flags = 0;
-	val = SHMEM_RD(bp, dev_info.shared_feature_config.config);
-	if (val & SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_ENABLED)
-		bp->link_params.feature_config_flags |=
-				FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED;
-	else
-		bp->link_params.feature_config_flags &=
-				~FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED;
-
-	val = SHMEM_RD(bp, dev_info.bc_rev) >> 8;
-	bp->common.bc_ver = val;
-	BNX2X_DEV_INFO("bc_ver %X\n", val);
-	if (val < BNX2X_BC_VER) {
-		/* for now only warn
-		 * later we might need to enforce this */
-		BNX2X_ERR("This driver needs bc_ver %X but found %X, "
-			  "please upgrade BC\n", BNX2X_BC_VER, val);
-	}
-	bp->link_params.feature_config_flags |=
-				(val >= REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL) ?
-				FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY : 0;
-
-	bp->link_params.feature_config_flags |=
-		(val >= REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL) ?
-		FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY : 0;
-
-	bp->link_params.feature_config_flags |=
-		(val >= REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED) ?
-		FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED : 0;
-
-	pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc);
-	bp->flags |= (pmc & PCI_PM_CAP_PME_D3cold) ? 0 : NO_WOL_FLAG;
-
-	BNX2X_DEV_INFO("%sWoL capable\n",
-		       (bp->flags & NO_WOL_FLAG) ? "not " : "");
-
-	val = SHMEM_RD(bp, dev_info.shared_hw_config.part_num);
-	val2 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[4]);
-	val3 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[8]);
-	val4 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[12]);
-
-	dev_info(&bp->pdev->dev, "part number %X-%X-%X-%X\n",
-		 val, val2, val3, val4);
-}
-
-#define IGU_FID(val)	GET_FIELD((val), IGU_REG_MAPPING_MEMORY_FID)
-#define IGU_VEC(val)	GET_FIELD((val), IGU_REG_MAPPING_MEMORY_VECTOR)
-
-static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
-{
-	int pfid = BP_FUNC(bp);
-	int igu_sb_id;
-	u32 val;
-	u8 fid, igu_sb_cnt = 0;
-
-	bp->igu_base_sb = 0xff;
-	if (CHIP_INT_MODE_IS_BC(bp)) {
-		int vn = BP_VN(bp);
-		igu_sb_cnt = bp->igu_sb_cnt;
-		bp->igu_base_sb = (CHIP_MODE_IS_4_PORT(bp) ? pfid : vn) *
-			FP_SB_MAX_E1x;
-
-		bp->igu_dsb_id =  E1HVN_MAX * FP_SB_MAX_E1x +
-			(CHIP_MODE_IS_4_PORT(bp) ? pfid : vn);
-
-		return;
-	}
-
-	/* IGU in normal mode - read CAM */
-	for (igu_sb_id = 0; igu_sb_id < IGU_REG_MAPPING_MEMORY_SIZE;
-	     igu_sb_id++) {
-		val = REG_RD(bp, IGU_REG_MAPPING_MEMORY + igu_sb_id * 4);
-		if (!(val & IGU_REG_MAPPING_MEMORY_VALID))
-			continue;
-		fid = IGU_FID(val);
-		if ((fid & IGU_FID_ENCODE_IS_PF)) {
-			if ((fid & IGU_FID_PF_NUM_MASK) != pfid)
-				continue;
-			if (IGU_VEC(val) == 0)
-				/* default status block */
-				bp->igu_dsb_id = igu_sb_id;
-			else {
-				if (bp->igu_base_sb == 0xff)
-					bp->igu_base_sb = igu_sb_id;
-				igu_sb_cnt++;
-			}
-		}
-	}
-
-#ifdef CONFIG_PCI_MSI
-	/*
-	 * It's expected that number of CAM entries for this functions is equal
-	 * to the number evaluated based on the MSI-X table size. We want a
-	 * harsh warning if these values are different!
-	 */
-	WARN_ON(bp->igu_sb_cnt != igu_sb_cnt);
-#endif
-
-	if (igu_sb_cnt == 0)
-		BNX2X_ERR("CAM configuration error\n");
-}
-
-static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
-						    u32 switch_cfg)
-{
-	int cfg_size = 0, idx, port = BP_PORT(bp);
-
-	/* Aggregation of supported attributes of all external phys */
-	bp->port.supported[0] = 0;
-	bp->port.supported[1] = 0;
-	switch (bp->link_params.num_phys) {
-	case 1:
-		bp->port.supported[0] = bp->link_params.phy[INT_PHY].supported;
-		cfg_size = 1;
-		break;
-	case 2:
-		bp->port.supported[0] = bp->link_params.phy[EXT_PHY1].supported;
-		cfg_size = 1;
-		break;
-	case 3:
-		if (bp->link_params.multi_phy_config &
-		    PORT_HW_CFG_PHY_SWAPPED_ENABLED) {
-			bp->port.supported[1] =
-				bp->link_params.phy[EXT_PHY1].supported;
-			bp->port.supported[0] =
-				bp->link_params.phy[EXT_PHY2].supported;
-		} else {
-			bp->port.supported[0] =
-				bp->link_params.phy[EXT_PHY1].supported;
-			bp->port.supported[1] =
-				bp->link_params.phy[EXT_PHY2].supported;
-		}
-		cfg_size = 2;
-		break;
-	}
-
-	if (!(bp->port.supported[0] || bp->port.supported[1])) {
-		BNX2X_ERR("NVRAM config error. BAD phy config."
-			  "PHY1 config 0x%x, PHY2 config 0x%x\n",
-			   SHMEM_RD(bp,
-			   dev_info.port_hw_config[port].external_phy_config),
-			   SHMEM_RD(bp,
-			   dev_info.port_hw_config[port].external_phy_config2));
-			return;
-	}
-
-	if (CHIP_IS_E3(bp))
-		bp->port.phy_addr = REG_RD(bp, MISC_REG_WC0_CTRL_PHY_ADDR);
-	else {
-		switch (switch_cfg) {
-		case SWITCH_CFG_1G:
-			bp->port.phy_addr = REG_RD(
-				bp, NIG_REG_SERDES0_CTRL_PHY_ADDR + port*0x10);
-			break;
-		case SWITCH_CFG_10G:
-			bp->port.phy_addr = REG_RD(
-				bp, NIG_REG_XGXS0_CTRL_PHY_ADDR + port*0x18);
-			break;
-		default:
-			BNX2X_ERR("BAD switch_cfg link_config 0x%x\n",
-				  bp->port.link_config[0]);
-			return;
-		}
-	}
-	BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
-	/* mask what we support according to speed_cap_mask per configuration */
-	for (idx = 0; idx < cfg_size; idx++) {
-		if (!(bp->link_params.speed_cap_mask[idx] &
-				PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF))
-			bp->port.supported[idx] &= ~SUPPORTED_10baseT_Half;
-
-		if (!(bp->link_params.speed_cap_mask[idx] &
-				PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL))
-			bp->port.supported[idx] &= ~SUPPORTED_10baseT_Full;
-
-		if (!(bp->link_params.speed_cap_mask[idx] &
-				PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF))
-			bp->port.supported[idx] &= ~SUPPORTED_100baseT_Half;
-
-		if (!(bp->link_params.speed_cap_mask[idx] &
-				PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL))
-			bp->port.supported[idx] &= ~SUPPORTED_100baseT_Full;
-
-		if (!(bp->link_params.speed_cap_mask[idx] &
-					PORT_HW_CFG_SPEED_CAPABILITY_D0_1G))
-			bp->port.supported[idx] &= ~(SUPPORTED_1000baseT_Half |
-						     SUPPORTED_1000baseT_Full);
-
-		if (!(bp->link_params.speed_cap_mask[idx] &
-					PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
-			bp->port.supported[idx] &= ~SUPPORTED_2500baseX_Full;
-
-		if (!(bp->link_params.speed_cap_mask[idx] &
-					PORT_HW_CFG_SPEED_CAPABILITY_D0_10G))
-			bp->port.supported[idx] &= ~SUPPORTED_10000baseT_Full;
-
-	}
-
-	BNX2X_DEV_INFO("supported 0x%x 0x%x\n", bp->port.supported[0],
-		       bp->port.supported[1]);
-}
-
-static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
-{
-	u32 link_config, idx, cfg_size = 0;
-	bp->port.advertising[0] = 0;
-	bp->port.advertising[1] = 0;
-	switch (bp->link_params.num_phys) {
-	case 1:
-	case 2:
-		cfg_size = 1;
-		break;
-	case 3:
-		cfg_size = 2;
-		break;
-	}
-	for (idx = 0; idx < cfg_size; idx++) {
-		bp->link_params.req_duplex[idx] = DUPLEX_FULL;
-		link_config = bp->port.link_config[idx];
-		switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) {
-		case PORT_FEATURE_LINK_SPEED_AUTO:
-			if (bp->port.supported[idx] & SUPPORTED_Autoneg) {
-				bp->link_params.req_line_speed[idx] =
-					SPEED_AUTO_NEG;
-				bp->port.advertising[idx] |=
-					bp->port.supported[idx];
-			} else {
-				/* force 10G, no AN */
-				bp->link_params.req_line_speed[idx] =
-					SPEED_10000;
-				bp->port.advertising[idx] |=
-					(ADVERTISED_10000baseT_Full |
-					 ADVERTISED_FIBRE);
-				continue;
-			}
-			break;
-
-		case PORT_FEATURE_LINK_SPEED_10M_FULL:
-			if (bp->port.supported[idx] & SUPPORTED_10baseT_Full) {
-				bp->link_params.req_line_speed[idx] =
-					SPEED_10;
-				bp->port.advertising[idx] |=
-					(ADVERTISED_10baseT_Full |
-					 ADVERTISED_TP);
-			} else {
-				BNX2X_ERR("NVRAM config error. "
-					    "Invalid link_config 0x%x"
-					    "  speed_cap_mask 0x%x\n",
-					    link_config,
-				    bp->link_params.speed_cap_mask[idx]);
-				return;
-			}
-			break;
-
-		case PORT_FEATURE_LINK_SPEED_10M_HALF:
-			if (bp->port.supported[idx] & SUPPORTED_10baseT_Half) {
-				bp->link_params.req_line_speed[idx] =
-					SPEED_10;
-				bp->link_params.req_duplex[idx] =
-					DUPLEX_HALF;
-				bp->port.advertising[idx] |=
-					(ADVERTISED_10baseT_Half |
-					 ADVERTISED_TP);
-			} else {
-				BNX2X_ERR("NVRAM config error. "
-					    "Invalid link_config 0x%x"
-					    "  speed_cap_mask 0x%x\n",
-					    link_config,
-					  bp->link_params.speed_cap_mask[idx]);
-				return;
-			}
-			break;
-
-		case PORT_FEATURE_LINK_SPEED_100M_FULL:
-			if (bp->port.supported[idx] &
-			    SUPPORTED_100baseT_Full) {
-				bp->link_params.req_line_speed[idx] =
-					SPEED_100;
-				bp->port.advertising[idx] |=
-					(ADVERTISED_100baseT_Full |
-					 ADVERTISED_TP);
-			} else {
-				BNX2X_ERR("NVRAM config error. "
-					    "Invalid link_config 0x%x"
-					    "  speed_cap_mask 0x%x\n",
-					    link_config,
-					  bp->link_params.speed_cap_mask[idx]);
-				return;
-			}
-			break;
-
-		case PORT_FEATURE_LINK_SPEED_100M_HALF:
-			if (bp->port.supported[idx] &
-			    SUPPORTED_100baseT_Half) {
-				bp->link_params.req_line_speed[idx] =
-								SPEED_100;
-				bp->link_params.req_duplex[idx] =
-								DUPLEX_HALF;
-				bp->port.advertising[idx] |=
-					(ADVERTISED_100baseT_Half |
-					 ADVERTISED_TP);
-			} else {
-				BNX2X_ERR("NVRAM config error. "
-				    "Invalid link_config 0x%x"
-				    "  speed_cap_mask 0x%x\n",
-				    link_config,
-				    bp->link_params.speed_cap_mask[idx]);
-				return;
-			}
-			break;
-
-		case PORT_FEATURE_LINK_SPEED_1G:
-			if (bp->port.supported[idx] &
-			    SUPPORTED_1000baseT_Full) {
-				bp->link_params.req_line_speed[idx] =
-					SPEED_1000;
-				bp->port.advertising[idx] |=
-					(ADVERTISED_1000baseT_Full |
-					 ADVERTISED_TP);
-			} else {
-				BNX2X_ERR("NVRAM config error. "
-				    "Invalid link_config 0x%x"
-				    "  speed_cap_mask 0x%x\n",
-				    link_config,
-				    bp->link_params.speed_cap_mask[idx]);
-				return;
-			}
-			break;
-
-		case PORT_FEATURE_LINK_SPEED_2_5G:
-			if (bp->port.supported[idx] &
-			    SUPPORTED_2500baseX_Full) {
-				bp->link_params.req_line_speed[idx] =
-					SPEED_2500;
-				bp->port.advertising[idx] |=
-					(ADVERTISED_2500baseX_Full |
-						ADVERTISED_TP);
-			} else {
-				BNX2X_ERR("NVRAM config error. "
-				    "Invalid link_config 0x%x"
-				    "  speed_cap_mask 0x%x\n",
-				    link_config,
-				    bp->link_params.speed_cap_mask[idx]);
-				return;
-			}
-			break;
-
-		case PORT_FEATURE_LINK_SPEED_10G_CX4:
-			if (bp->port.supported[idx] &
-			    SUPPORTED_10000baseT_Full) {
-				bp->link_params.req_line_speed[idx] =
-					SPEED_10000;
-				bp->port.advertising[idx] |=
-					(ADVERTISED_10000baseT_Full |
-						ADVERTISED_FIBRE);
-			} else {
-				BNX2X_ERR("NVRAM config error. "
-				    "Invalid link_config 0x%x"
-				    "  speed_cap_mask 0x%x\n",
-				    link_config,
-				    bp->link_params.speed_cap_mask[idx]);
-				return;
-			}
-			break;
-		case PORT_FEATURE_LINK_SPEED_20G:
-			bp->link_params.req_line_speed[idx] = SPEED_20000;
-
-			break;
-		default:
-			BNX2X_ERR("NVRAM config error. "
-				  "BAD link speed link_config 0x%x\n",
-				  link_config);
-				bp->link_params.req_line_speed[idx] =
-							SPEED_AUTO_NEG;
-				bp->port.advertising[idx] =
-						bp->port.supported[idx];
-			break;
-		}
-
-		bp->link_params.req_flow_ctrl[idx] = (link_config &
-					 PORT_FEATURE_FLOW_CONTROL_MASK);
-		if ((bp->link_params.req_flow_ctrl[idx] ==
-		     BNX2X_FLOW_CTRL_AUTO) &&
-		    !(bp->port.supported[idx] & SUPPORTED_Autoneg)) {
-			bp->link_params.req_flow_ctrl[idx] =
-				BNX2X_FLOW_CTRL_NONE;
-		}
-
-		BNX2X_DEV_INFO("req_line_speed %d  req_duplex %d req_flow_ctrl"
-			       " 0x%x advertising 0x%x\n",
-			       bp->link_params.req_line_speed[idx],
-			       bp->link_params.req_duplex[idx],
-			       bp->link_params.req_flow_ctrl[idx],
-			       bp->port.advertising[idx]);
-	}
-}
-
-static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi)
-{
-	mac_hi = cpu_to_be16(mac_hi);
-	mac_lo = cpu_to_be32(mac_lo);
-	memcpy(mac_buf, &mac_hi, sizeof(mac_hi));
-	memcpy(mac_buf + sizeof(mac_hi), &mac_lo, sizeof(mac_lo));
-}
-
-static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
-{
-	int port = BP_PORT(bp);
-	u32 config;
-	u32 ext_phy_type, ext_phy_config;
-
-	bp->link_params.bp = bp;
-	bp->link_params.port = port;
-
-	bp->link_params.lane_config =
-		SHMEM_RD(bp, dev_info.port_hw_config[port].lane_config);
-
-	bp->link_params.speed_cap_mask[0] =
-		SHMEM_RD(bp,
-			 dev_info.port_hw_config[port].speed_capability_mask);
-	bp->link_params.speed_cap_mask[1] =
-		SHMEM_RD(bp,
-			 dev_info.port_hw_config[port].speed_capability_mask2);
-	bp->port.link_config[0] =
-		SHMEM_RD(bp, dev_info.port_feature_config[port].link_config);
-
-	bp->port.link_config[1] =
-		SHMEM_RD(bp, dev_info.port_feature_config[port].link_config2);
-
-	bp->link_params.multi_phy_config =
-		SHMEM_RD(bp, dev_info.port_hw_config[port].multi_phy_config);
-	/* If the device is capable of WoL, set the default state according
-	 * to the HW
-	 */
-	config = SHMEM_RD(bp, dev_info.port_feature_config[port].config);
-	bp->wol = (!(bp->flags & NO_WOL_FLAG) &&
-		   (config & PORT_FEATURE_WOL_ENABLED));
-
-	BNX2X_DEV_INFO("lane_config 0x%08x  "
-		       "speed_cap_mask0 0x%08x  link_config0 0x%08x\n",
-		       bp->link_params.lane_config,
-		       bp->link_params.speed_cap_mask[0],
-		       bp->port.link_config[0]);
-
-	bp->link_params.switch_cfg = (bp->port.link_config[0] &
-				      PORT_FEATURE_CONNECTED_SWITCH_MASK);
-	bnx2x_phy_probe(&bp->link_params);
-	bnx2x_link_settings_supported(bp, bp->link_params.switch_cfg);
-
-	bnx2x_link_settings_requested(bp);
-
-	/*
-	 * If connected directly, work with the internal PHY, otherwise, work
-	 * with the external PHY
-	 */
-	ext_phy_config =
-		SHMEM_RD(bp,
-			 dev_info.port_hw_config[port].external_phy_config);
-	ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
-	if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
-		bp->mdio.prtad = bp->port.phy_addr;
-
-	else if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
-		 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN))
-		bp->mdio.prtad =
-			XGXS_EXT_PHY_ADDR(ext_phy_config);
-
-	/*
-	 * Check if hw lock is required to access MDC/MDIO bus to the PHY(s)
-	 * In MF mode, it is set to cover self test cases
-	 */
-	if (IS_MF(bp))
-		bp->port.need_hw_lock = 1;
-	else
-		bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
-							bp->common.shmem_base,
-							bp->common.shmem2_base);
-}
-
-#ifdef BCM_CNIC
-static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp)
-{
-	int port = BP_PORT(bp);
-	int func = BP_ABS_FUNC(bp);
-
-	u32 max_iscsi_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
-				drv_lic_key[port].max_iscsi_conn);
-	u32 max_fcoe_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
-				drv_lic_key[port].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;
-
-	/* Read the WWN: */
-	if (!IS_MF(bp)) {
-		/* Port info */
-		bp->cnic_eth_dev.fcoe_wwn_port_name_hi =
-			SHMEM_RD(bp,
-				dev_info.port_hw_config[port].
-				 fcoe_wwn_port_name_upper);
-		bp->cnic_eth_dev.fcoe_wwn_port_name_lo =
-			SHMEM_RD(bp,
-				dev_info.port_hw_config[port].
-				 fcoe_wwn_port_name_lower);
-
-		/* Node info */
-		bp->cnic_eth_dev.fcoe_wwn_node_name_hi =
-			SHMEM_RD(bp,
-				dev_info.port_hw_config[port].
-				 fcoe_wwn_node_name_upper);
-		bp->cnic_eth_dev.fcoe_wwn_node_name_lo =
-			SHMEM_RD(bp,
-				dev_info.port_hw_config[port].
-				 fcoe_wwn_node_name_lower);
-	} else if (!IS_MF_SD(bp)) {
-		u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg);
-
-		/*
-		 * Read the WWN info only if the FCoE feature is enabled for
-		 * this function.
-		 */
-		if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD) {
-			/* Port info */
-			bp->cnic_eth_dev.fcoe_wwn_port_name_hi =
-				MF_CFG_RD(bp, func_ext_config[func].
-						fcoe_wwn_port_name_upper);
-			bp->cnic_eth_dev.fcoe_wwn_port_name_lo =
-				MF_CFG_RD(bp, func_ext_config[func].
-						fcoe_wwn_port_name_lower);
-
-			/* Node info */
-			bp->cnic_eth_dev.fcoe_wwn_node_name_hi =
-				MF_CFG_RD(bp, func_ext_config[func].
-						fcoe_wwn_node_name_upper);
-			bp->cnic_eth_dev.fcoe_wwn_node_name_lo =
-				MF_CFG_RD(bp, func_ext_config[func].
-						fcoe_wwn_node_name_lower);
-		}
-	}
-
-	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 maximum 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
-
-	/* Zero primary MAC configuration */
-	memset(bp->dev->dev_addr, 0, ETH_ALEN);
-
-	if (BP_NOMCP(bp)) {
-		BNX2X_ERROR("warning: random MAC workaround active\n");
-		random_ether_addr(bp->dev->dev_addr);
-	} else if (IS_MF(bp)) {
-		val2 = MF_CFG_RD(bp, func_mf_config[func].mac_upper);
-		val = MF_CFG_RD(bp, func_mf_config[func].mac_lower);
-		if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) &&
-		    (val != FUNC_MF_CFG_LOWERMAC_DEFAULT))
-			bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
-
-#ifdef BCM_CNIC
-		/* 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) {
-				val2 = MF_CFG_RD(bp, func_ext_config[func].
-						     iscsi_mac_addr_upper);
-				val = MF_CFG_RD(bp, func_ext_config[func].
-						    iscsi_mac_addr_lower);
-				bnx2x_set_mac_buf(iscsi_mac, val, val2);
-				BNX2X_DEV_INFO("Read iSCSI MAC: "
-					       BNX2X_MAC_FMT"\n",
-					       BNX2X_MAC_PRN_LIST(iscsi_mac));
-			} 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_set_mac_buf(fip_mac, val, val2);
-				BNX2X_DEV_INFO("Read FCoE L2 MAC to "
-					       BNX2X_MAC_FMT"\n",
-					       BNX2X_MAC_PRN_LIST(fip_mac));
-
-			} else
-				bp->flags |= NO_FCOE_FLAG;
-		}
-#endif
-	} else {
-		/* in SF read MACs from port configuration */
-		val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
-		val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
-		bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
-
-#ifdef BCM_CNIC
-		val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].
-				    iscsi_mac_upper);
-		val = SHMEM_RD(bp, dev_info.port_hw_config[port].
-				   iscsi_mac_lower);
-		bnx2x_set_mac_buf(iscsi_mac, val, val2);
-
-		val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].
-				    fcoe_fip_mac_upper);
-		val = SHMEM_RD(bp, dev_info.port_hw_config[port].
-				   fcoe_fip_mac_lower);
-		bnx2x_set_mac_buf(fip_mac, val, val2);
-#endif
-	}
-
-	memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN);
-	memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
-
-#ifdef BCM_CNIC
-	/* Set the FCoE MAC in MF_SD mode */
-	if (!CHIP_IS_E1x(bp) && IS_MF_SD(bp))
-		memcpy(fip_mac, bp->dev->dev_addr, ETH_ALEN);
-
-	/* Disable iSCSI if MAC configuration is
-	 * invalid.
-	 */
-	if (!is_valid_ether_addr(iscsi_mac)) {
-		bp->flags |= NO_ISCSI_FLAG;
-		memset(iscsi_mac, 0, ETH_ALEN);
-	}
-
-	/* 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);
-	}
-#endif
-
-	if (!is_valid_ether_addr(bp->dev->dev_addr))
-		dev_err(&bp->pdev->dev,
-			"bad Ethernet MAC address configuration: "
-			BNX2X_MAC_FMT", change it manually before bringing up "
-			"the appropriate network interface\n",
-			BNX2X_MAC_PRN_LIST(bp->dev->dev_addr));
-}
-
-static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
-{
-	int /*abs*/func = BP_ABS_FUNC(bp);
-	int vn;
-	u32 val = 0;
-	int rc = 0;
-
-	bnx2x_get_common_hwinfo(bp);
-
-	/*
-	 * initialize IGU parameters
-	 */
-	if (CHIP_IS_E1x(bp)) {
-		bp->common.int_block = INT_BLOCK_HC;
-
-		bp->igu_dsb_id = DEF_SB_IGU_ID;
-		bp->igu_base_sb = 0;
-	} else {
-		bp->common.int_block = INT_BLOCK_IGU;
-
-		/* do not allow device reset during IGU info preocessing */
-		bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
-
-		val = REG_RD(bp, IGU_REG_BLOCK_CONFIGURATION);
-
-		if (val & IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN) {
-			int tout = 5000;
-
-			BNX2X_DEV_INFO("FORCING Normal Mode\n");
-
-			val &= ~(IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN);
-			REG_WR(bp, IGU_REG_BLOCK_CONFIGURATION, val);
-			REG_WR(bp, IGU_REG_RESET_MEMORIES, 0x7f);
-
-			while (tout && REG_RD(bp, IGU_REG_RESET_MEMORIES)) {
-				tout--;
-				usleep_range(1000, 1000);
-			}
-
-			if (REG_RD(bp, IGU_REG_RESET_MEMORIES)) {
-				dev_err(&bp->pdev->dev,
-					"FORCING Normal Mode failed!!!\n");
-				return -EPERM;
-			}
-		}
-
-		if (val & IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN) {
-			BNX2X_DEV_INFO("IGU Backward Compatible Mode\n");
-			bp->common.int_block |= INT_BLOCK_MODE_BW_COMP;
-		} else
-			BNX2X_DEV_INFO("IGU Normal Mode\n");
-
-		bnx2x_get_igu_cam_info(bp);
-
-		bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
-	}
-
-	/*
-	 * set base FW non-default (fast path) status block id, this value is
-	 * used to initialize the fw_sb_id saved on the fp/queue structure to
-	 * determine the id used by the FW.
-	 */
-	if (CHIP_IS_E1x(bp))
-		bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E1x + BP_L_ID(bp);
-	else /*
-	      * 57712 - we currently use one FW SB per IGU SB (Rx and Tx of
-	      * the same queue are indicated on the same IGU SB). So we prefer
-	      * FW and IGU SBs to be the same value.
-	      */
-		bp->base_fw_ndsb = bp->igu_base_sb;
-
-	BNX2X_DEV_INFO("igu_dsb_id %d  igu_base_sb %d  igu_sb_cnt %d\n"
-		       "base_fw_ndsb %d\n", bp->igu_dsb_id, bp->igu_base_sb,
-		       bp->igu_sb_cnt, bp->base_fw_ndsb);
-
-	/*
-	 * Initialize MF configuration
-	 */
-
-	bp->mf_ov = 0;
-	bp->mf_mode = 0;
-	vn = BP_VN(bp);
-
-	if (!CHIP_IS_E1(bp) && !BP_NOMCP(bp)) {
-		BNX2X_DEV_INFO("shmem2base 0x%x, size %d, mfcfg offset %d\n",
-			       bp->common.shmem2_base, SHMEM2_RD(bp, size),
-			      (u32)offsetof(struct shmem2_region, mf_cfg_addr));
-
-		if (SHMEM2_HAS(bp, mf_cfg_addr))
-			bp->common.mf_cfg_base = SHMEM2_RD(bp, mf_cfg_addr);
-		else
-			bp->common.mf_cfg_base = bp->common.shmem_base +
-				offsetof(struct shmem_region, func_mb) +
-				E1H_FUNC_MAX * sizeof(struct drv_func_mb);
-		/*
-		 * get 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
-		 * 3. SF_MODE configures specific MF mode
-		 */
-		if (bp->common.mf_cfg_base != SHMEM_MF_CFG_ADDR_NONE) {
-			/* get mf configuration */
-			val = SHMEM_RD(bp,
-				       dev_info.shared_feature_config.config);
-			val &= SHARED_FEAT_CFG_FORCE_SF_MODE_MASK;
-
-			switch (val) {
-			case SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT:
-				val = MF_CFG_RD(bp, func_mf_config[func].
-						mac_upper);
-				/* check for legal mac (upper bytes)*/
-				if (val != 0xffff) {
-					bp->mf_mode = MULTI_FUNCTION_SI;
-					bp->mf_config[vn] = MF_CFG_RD(bp,
-						   func_mf_config[func].config);
-				} else
-					BNX2X_DEV_INFO("illegal MAC address "
-						       "for SI\n");
-				break;
-			case SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED:
-				/* get OV configuration */
-				val = MF_CFG_RD(bp,
-					func_mf_config[FUNC_0].e1hov_tag);
-				val &= FUNC_MF_CFG_E1HOV_TAG_MASK;
-
-				if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
-					bp->mf_mode = MULTI_FUNCTION_SD;
-					bp->mf_config[vn] = MF_CFG_RD(bp,
-						func_mf_config[func].config);
-				} else
-					BNX2X_DEV_INFO("illegal OV for SD\n");
-				break;
-			default:
-				/* Unknown configuration: reset mf_config */
-				bp->mf_config[vn] = 0;
-				BNX2X_DEV_INFO("unkown MF mode 0x%x\n", val);
-			}
-		}
-
-		BNX2X_DEV_INFO("%s function mode\n",
-			       IS_MF(bp) ? "multi" : "single");
-
-		switch (bp->mf_mode) {
-		case MULTI_FUNCTION_SD:
-			val = MF_CFG_RD(bp, func_mf_config[func].e1hov_tag) &
-			      FUNC_MF_CFG_E1HOV_TAG_MASK;
-			if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
-				bp->mf_ov = val;
-				bp->path_has_ovlan = true;
-
-				BNX2X_DEV_INFO("MF OV for func %d is %d "
-					       "(0x%04x)\n", func, bp->mf_ov,
-					       bp->mf_ov);
-			} else {
-				dev_err(&bp->pdev->dev,
-					"No valid MF OV for func %d, "
-					"aborting\n", func);
-				return -EPERM;
-			}
-			break;
-		case MULTI_FUNCTION_SI:
-			BNX2X_DEV_INFO("func %d is in MF "
-				       "switch-independent mode\n", func);
-			break;
-		default:
-			if (vn) {
-				dev_err(&bp->pdev->dev,
-					"VN %d is in a single function mode, "
-					"aborting\n", vn);
-				return -EPERM;
-			}
-			break;
-		}
-
-		/* check if other port on the path needs ovlan:
-		 * Since MF configuration is shared between ports
-		 * Possible mixed modes are only
-		 * {SF, SI} {SF, SD} {SD, SF} {SI, SF}
-		 */
-		if (CHIP_MODE_IS_4_PORT(bp) &&
-		    !bp->path_has_ovlan &&
-		    !IS_MF(bp) &&
-		    bp->common.mf_cfg_base != SHMEM_MF_CFG_ADDR_NONE) {
-			u8 other_port = !BP_PORT(bp);
-			u8 other_func = BP_PATH(bp) + 2*other_port;
-			val = MF_CFG_RD(bp,
-					func_mf_config[other_func].e1hov_tag);
-			if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT)
-				bp->path_has_ovlan = true;
-		}
-	}
-
-	/* adjust igu_sb_cnt to MF for E1x */
-	if (CHIP_IS_E1x(bp) && IS_MF(bp))
-		bp->igu_sb_cnt /= E1HVN_MAX;
-
-	/* port info */
-	bnx2x_get_port_hwinfo(bp);
-
-	/* Get MAC addresses */
-	bnx2x_get_mac_hwinfo(bp);
-
-#ifdef BCM_CNIC
-	bnx2x_get_cnic_info(bp);
-#endif
-
-	/* Get current FW pulse sequence */
-	if (!BP_NOMCP(bp)) {
-		int mb_idx = BP_FW_MB_IDX(bp);
-
-		bp->fw_drv_pulse_wr_seq =
-				(SHMEM_RD(bp, func_mb[mb_idx].drv_pulse_mb) &
-				 DRV_PULSE_SEQ_MASK);
-		BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
-	}
-
-	return rc;
-}
-
-static void __devinit bnx2x_read_fwinfo(struct bnx2x *bp)
-{
-	int cnt, i, block_end, rodi;
-	char vpd_data[BNX2X_VPD_LEN+1];
-	char str_id_reg[VENDOR_ID_LEN+1];
-	char str_id_cap[VENDOR_ID_LEN+1];
-	u8 len;
-
-	cnt = pci_read_vpd(bp->pdev, 0, BNX2X_VPD_LEN, vpd_data);
-	memset(bp->fw_ver, 0, sizeof(bp->fw_ver));
-
-	if (cnt < BNX2X_VPD_LEN)
-		goto out_not_found;
-
-	i = pci_vpd_find_tag(vpd_data, 0, BNX2X_VPD_LEN,
-			     PCI_VPD_LRDT_RO_DATA);
-	if (i < 0)
-		goto out_not_found;
-
-
-	block_end = i + PCI_VPD_LRDT_TAG_SIZE +
-		    pci_vpd_lrdt_size(&vpd_data[i]);
-
-	i += PCI_VPD_LRDT_TAG_SIZE;
-
-	if (block_end > BNX2X_VPD_LEN)
-		goto out_not_found;
-
-	rodi = pci_vpd_find_info_keyword(vpd_data, i, block_end,
-				   PCI_VPD_RO_KEYWORD_MFR_ID);
-	if (rodi < 0)
-		goto out_not_found;
-
-	len = pci_vpd_info_field_size(&vpd_data[rodi]);
-
-	if (len != VENDOR_ID_LEN)
-		goto out_not_found;
-
-	rodi += PCI_VPD_INFO_FLD_HDR_SIZE;
-
-	/* vendor specific info */
-	snprintf(str_id_reg, VENDOR_ID_LEN + 1, "%04x", PCI_VENDOR_ID_DELL);
-	snprintf(str_id_cap, VENDOR_ID_LEN + 1, "%04X", PCI_VENDOR_ID_DELL);
-	if (!strncmp(str_id_reg, &vpd_data[rodi], VENDOR_ID_LEN) ||
-	    !strncmp(str_id_cap, &vpd_data[rodi], VENDOR_ID_LEN)) {
-
-		rodi = pci_vpd_find_info_keyword(vpd_data, i, block_end,
-						PCI_VPD_RO_KEYWORD_VENDOR0);
-		if (rodi >= 0) {
-			len = pci_vpd_info_field_size(&vpd_data[rodi]);
-
-			rodi += PCI_VPD_INFO_FLD_HDR_SIZE;
-
-			if (len < 32 && (len + rodi) <= BNX2X_VPD_LEN) {
-				memcpy(bp->fw_ver, &vpd_data[rodi], len);
-				bp->fw_ver[len] = ' ';
-			}
-		}
-		return;
-	}
-out_not_found:
-	return;
-}
-
-static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp)
-{
-	u32 flags = 0;
-
-	if (CHIP_REV_IS_FPGA(bp))
-		SET_FLAGS(flags, MODE_FPGA);
-	else if (CHIP_REV_IS_EMUL(bp))
-		SET_FLAGS(flags, MODE_EMUL);
-	else
-		SET_FLAGS(flags, MODE_ASIC);
-
-	if (CHIP_MODE_IS_4_PORT(bp))
-		SET_FLAGS(flags, MODE_PORT4);
-	else
-		SET_FLAGS(flags, MODE_PORT2);
-
-	if (CHIP_IS_E2(bp))
-		SET_FLAGS(flags, MODE_E2);
-	else if (CHIP_IS_E3(bp)) {
-		SET_FLAGS(flags, MODE_E3);
-		if (CHIP_REV(bp) == CHIP_REV_Ax)
-			SET_FLAGS(flags, MODE_E3_A0);
-		else /*if (CHIP_REV(bp) == CHIP_REV_Bx)*/
-			SET_FLAGS(flags, MODE_E3_B0 | MODE_COS3);
-	}
-
-	if (IS_MF(bp)) {
-		SET_FLAGS(flags, MODE_MF);
-		switch (bp->mf_mode) {
-		case MULTI_FUNCTION_SD:
-			SET_FLAGS(flags, MODE_MF_SD);
-			break;
-		case MULTI_FUNCTION_SI:
-			SET_FLAGS(flags, MODE_MF_SI);
-			break;
-		}
-	} else
-		SET_FLAGS(flags, MODE_SF);
-
-#if defined(__LITTLE_ENDIAN)
-	SET_FLAGS(flags, MODE_LITTLE_ENDIAN);
-#else /*(__BIG_ENDIAN)*/
-	SET_FLAGS(flags, MODE_BIG_ENDIAN);
-#endif
-	INIT_MODE_FLAGS(bp) = flags;
-}
-
-static int __devinit bnx2x_init_bp(struct bnx2x *bp)
-{
-	int func;
-	int timer_interval;
-	int rc;
-
-	mutex_init(&bp->port.phy_mutex);
-	mutex_init(&bp->fw_mb_mutex);
-	spin_lock_init(&bp->stats_lock);
-#ifdef BCM_CNIC
-	mutex_init(&bp->cnic_mutex);
-#endif
-
-	INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
-	INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task);
-	INIT_DELAYED_WORK(&bp->period_task, bnx2x_period_task);
-	rc = bnx2x_get_hwinfo(bp);
-	if (rc)
-		return rc;
-
-	bnx2x_set_modes_bitmap(bp);
-
-	rc = bnx2x_alloc_mem_bp(bp);
-	if (rc)
-		return rc;
-
-	bnx2x_read_fwinfo(bp);
-
-	func = BP_FUNC(bp);
-
-	/* need to reset chip if undi was active */
-	if (!BP_NOMCP(bp))
-		bnx2x_undi_unload(bp);
-
-	/* init fw_seq after undi_unload! */
-	if (!BP_NOMCP(bp)) {
-		bp->fw_seq =
-			(SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
-			 DRV_MSG_SEQ_NUMBER_MASK);
-		BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
-	}
-
-	if (CHIP_REV_IS_FPGA(bp))
-		dev_err(&bp->pdev->dev, "FPGA detected\n");
-
-	if (BP_NOMCP(bp) && (func == 0))
-		dev_err(&bp->pdev->dev, "MCP disabled, "
-					"must load devices in order!\n");
-
-	bp->multi_mode = multi_mode;
-
-	/* Set TPA flags */
-	if (disable_tpa) {
-		bp->flags &= ~TPA_ENABLE_FLAG;
-		bp->dev->features &= ~NETIF_F_LRO;
-	} else {
-		bp->flags |= TPA_ENABLE_FLAG;
-		bp->dev->features |= NETIF_F_LRO;
-	}
-	bp->disable_tpa = disable_tpa;
-
-	if (CHIP_IS_E1(bp))
-		bp->dropless_fc = 0;
-	else
-		bp->dropless_fc = dropless_fc;
-
-	bp->mrrs = mrrs;
-
-	bp->tx_ring_size = MAX_TX_AVAIL;
-
-	/* make sure that the numbers are in the right granularity */
-	bp->tx_ticks = (50 / BNX2X_BTR) * BNX2X_BTR;
-	bp->rx_ticks = (25 / BNX2X_BTR) * BNX2X_BTR;
-
-	timer_interval = (CHIP_REV_IS_SLOW(bp) ? 5*HZ : HZ);
-	bp->current_interval = (poll ? poll : timer_interval);
-
-	init_timer(&bp->timer);
-	bp->timer.expires = jiffies + bp->current_interval;
-	bp->timer.data = (unsigned long) bp;
-	bp->timer.function = bnx2x_timer;
-
-	bnx2x_dcbx_set_state(bp, true, BNX2X_DCBX_ENABLED_ON_NEG_ON);
-	bnx2x_dcbx_init_params(bp);
-
-#ifdef BCM_CNIC
-	if (CHIP_IS_E1x(bp))
-		bp->cnic_base_cl_id = FP_SB_MAX_E1x;
-	else
-		bp->cnic_base_cl_id = FP_SB_MAX_E2;
-#endif
-
-	/* multiple tx priority */
-	if (CHIP_IS_E1x(bp))
-		bp->max_cos = BNX2X_MULTI_TX_COS_E1X;
-	if (CHIP_IS_E2(bp) || CHIP_IS_E3A0(bp))
-		bp->max_cos = BNX2X_MULTI_TX_COS_E2_E3A0;
-	if (CHIP_IS_E3B0(bp))
-		bp->max_cos = BNX2X_MULTI_TX_COS_E3B0;
-
-	return rc;
-}
-
-
-/****************************************************************************
-* General service functions
-****************************************************************************/
-
-/*
- * net_device service functions
- */
-
-/* called with rtnl_lock */
-static int bnx2x_open(struct net_device *dev)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	bool global = false;
-	int other_engine = BP_PATH(bp) ? 0 : 1;
-	u32 other_load_counter, load_counter;
-
-	netif_carrier_off(dev);
-
-	bnx2x_set_power_state(bp, PCI_D0);
-
-	other_load_counter = bnx2x_get_load_cnt(bp, other_engine);
-	load_counter = bnx2x_get_load_cnt(bp, BP_PATH(bp));
-
-	/*
-	 * If parity had happen during the unload, then attentions
-	 * and/or RECOVERY_IN_PROGRES may still be set. In this case we
-	 * want the first function loaded on the current engine to
-	 * complete the recovery.
-	 */
-	if (!bnx2x_reset_is_done(bp, BP_PATH(bp)) ||
-	    bnx2x_chk_parity_attn(bp, &global, true))
-		do {
-			/*
-			 * If there are attentions and they are in a global
-			 * blocks, set the GLOBAL_RESET bit regardless whether
-			 * it will be this function that will complete the
-			 * recovery or not.
-			 */
-			if (global)
-				bnx2x_set_reset_global(bp);
-
-			/*
-			 * Only the first function on the current engine should
-			 * try to recover in open. In case of attentions in
-			 * global blocks only the first in the chip should try
-			 * to recover.
-			 */
-			if ((!load_counter &&
-			     (!global || !other_load_counter)) &&
-			    bnx2x_trylock_leader_lock(bp) &&
-			    !bnx2x_leader_reset(bp)) {
-				netdev_info(bp->dev, "Recovered in open\n");
-				break;
-			}
-
-			/* recovery has failed... */
-			bnx2x_set_power_state(bp, PCI_D3hot);
-			bp->recovery_state = BNX2X_RECOVERY_FAILED;
-
-			netdev_err(bp->dev, "Recovery flow hasn't been properly"
-			" completed yet. Try again later. If u still see this"
-			" message after a few retries then power cycle is"
-			" required.\n");
-
-			return -EAGAIN;
-		} while (0);
-
-	bp->recovery_state = BNX2X_RECOVERY_DONE;
-	return bnx2x_nic_load(bp, LOAD_OPEN);
-}
-
-/* called with rtnl_lock */
-static int bnx2x_close(struct net_device *dev)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	/* Unload the driver, release IRQs */
-	bnx2x_nic_unload(bp, UNLOAD_CLOSE);
-
-	/* Power off */
-	bnx2x_set_power_state(bp, PCI_D3hot);
-
-	return 0;
-}
-
-static inline int bnx2x_init_mcast_macs_list(struct bnx2x *bp,
-					 struct bnx2x_mcast_ramrod_params *p)
-{
-	int mc_count = netdev_mc_count(bp->dev);
-	struct bnx2x_mcast_list_elem *mc_mac =
-		kzalloc(sizeof(*mc_mac) * mc_count, GFP_ATOMIC);
-	struct netdev_hw_addr *ha;
-
-	if (!mc_mac)
-		return -ENOMEM;
-
-	INIT_LIST_HEAD(&p->mcast_list);
-
-	netdev_for_each_mc_addr(ha, bp->dev) {
-		mc_mac->mac = bnx2x_mc_addr(ha);
-		list_add_tail(&mc_mac->link, &p->mcast_list);
-		mc_mac++;
-	}
-
-	p->mcast_list_len = mc_count;
-
-	return 0;
-}
-
-static inline void bnx2x_free_mcast_macs_list(
-	struct bnx2x_mcast_ramrod_params *p)
-{
-	struct bnx2x_mcast_list_elem *mc_mac =
-		list_first_entry(&p->mcast_list, struct bnx2x_mcast_list_elem,
-				 link);
-
-	WARN_ON(!mc_mac);
-	kfree(mc_mac);
-}
-
-/**
- * bnx2x_set_uc_list - configure a new unicast MACs list.
- *
- * @bp: driver handle
- *
- * We will use zero (0) as a MAC type for these MACs.
- */
-static inline int bnx2x_set_uc_list(struct bnx2x *bp)
-{
-	int rc;
-	struct net_device *dev = bp->dev;
-	struct netdev_hw_addr *ha;
-	struct bnx2x_vlan_mac_obj *mac_obj = &bp->fp->mac_obj;
-	unsigned long ramrod_flags = 0;
-
-	/* First schedule a cleanup up of old configuration */
-	rc = bnx2x_del_all_macs(bp, mac_obj, BNX2X_UC_LIST_MAC, false);
-	if (rc < 0) {
-		BNX2X_ERR("Failed to schedule DELETE operations: %d\n", rc);
-		return rc;
-	}
-
-	netdev_for_each_uc_addr(ha, dev) {
-		rc = bnx2x_set_mac_one(bp, bnx2x_uc_addr(ha), mac_obj, true,
-				       BNX2X_UC_LIST_MAC, &ramrod_flags);
-		if (rc < 0) {
-			BNX2X_ERR("Failed to schedule ADD operations: %d\n",
-				  rc);
-			return rc;
-		}
-	}
-
-	/* Execute the pending commands */
-	__set_bit(RAMROD_CONT, &ramrod_flags);
-	return bnx2x_set_mac_one(bp, NULL, mac_obj, false /* don't care */,
-				 BNX2X_UC_LIST_MAC, &ramrod_flags);
-}
-
-static inline int bnx2x_set_mc_list(struct bnx2x *bp)
-{
-	struct net_device *dev = bp->dev;
-	struct bnx2x_mcast_ramrod_params rparam = {0};
-	int rc = 0;
-
-	rparam.mcast_obj = &bp->mcast_obj;
-
-	/* first, clear all configured multicast MACs */
-	rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
-	if (rc < 0) {
-		BNX2X_ERR("Failed to clear multicast "
-			  "configuration: %d\n", rc);
-		return rc;
-	}
-
-	/* then, configure a new MACs list */
-	if (netdev_mc_count(dev)) {
-		rc = bnx2x_init_mcast_macs_list(bp, &rparam);
-		if (rc) {
-			BNX2X_ERR("Failed to create multicast MACs "
-				  "list: %d\n", rc);
-			return rc;
-		}
-
-		/* Now add the new MACs */
-		rc = bnx2x_config_mcast(bp, &rparam,
-					BNX2X_MCAST_CMD_ADD);
-		if (rc < 0)
-			BNX2X_ERR("Failed to set a new multicast "
-				  "configuration: %d\n", rc);
-
-		bnx2x_free_mcast_macs_list(&rparam);
-	}
-
-	return rc;
-}
-
-
-/* If bp->state is OPEN, should be called with netif_addr_lock_bh() */
-void bnx2x_set_rx_mode(struct net_device *dev)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	u32 rx_mode = BNX2X_RX_MODE_NORMAL;
-
-	if (bp->state != BNX2X_STATE_OPEN) {
-		DP(NETIF_MSG_IFUP, "state is %x, returning\n", bp->state);
-		return;
-	}
-
-	DP(NETIF_MSG_IFUP, "dev->flags = %x\n", bp->dev->flags);
-
-	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)))
-		rx_mode = BNX2X_RX_MODE_ALLMULTI;
-	else {
-		/* some multicasts */
-		if (bnx2x_set_mc_list(bp) < 0)
-			rx_mode = BNX2X_RX_MODE_ALLMULTI;
-
-		if (bnx2x_set_uc_list(bp) < 0)
-			rx_mode = BNX2X_RX_MODE_PROMISC;
-	}
-
-	bp->rx_mode = rx_mode;
-
-	/* Schedule the rx_mode command */
-	if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state)) {
-		set_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state);
-		return;
-	}
-
-	bnx2x_set_storm_rx_mode(bp);
-}
-
-/* called with rtnl_lock */
-static int bnx2x_mdio_read(struct net_device *netdev, int prtad,
-			   int devad, u16 addr)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	u16 value;
-	int rc;
-
-	DP(NETIF_MSG_LINK, "mdio_read: prtad 0x%x, devad 0x%x, addr 0x%x\n",
-	   prtad, devad, addr);
-
-	/* The HW expects different devad if CL22 is used */
-	devad = (devad == MDIO_DEVAD_NONE) ? DEFAULT_PHY_DEV_ADDR : devad;
-
-	bnx2x_acquire_phy_lock(bp);
-	rc = bnx2x_phy_read(&bp->link_params, prtad, devad, addr, &value);
-	bnx2x_release_phy_lock(bp);
-	DP(NETIF_MSG_LINK, "mdio_read_val 0x%x rc = 0x%x\n", value, rc);
-
-	if (!rc)
-		rc = value;
-	return rc;
-}
-
-/* called with rtnl_lock */
-static int bnx2x_mdio_write(struct net_device *netdev, int prtad, int devad,
-			    u16 addr, u16 value)
-{
-	struct bnx2x *bp = netdev_priv(netdev);
-	int rc;
-
-	DP(NETIF_MSG_LINK, "mdio_write: prtad 0x%x, devad 0x%x, addr 0x%x,"
-			   " value 0x%x\n", prtad, devad, addr, value);
-
-	/* The HW expects different devad if CL22 is used */
-	devad = (devad == MDIO_DEVAD_NONE) ? DEFAULT_PHY_DEV_ADDR : devad;
-
-	bnx2x_acquire_phy_lock(bp);
-	rc = bnx2x_phy_write(&bp->link_params, prtad, devad, addr, value);
-	bnx2x_release_phy_lock(bp);
-	return rc;
-}
-
-/* called with rtnl_lock */
-static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	struct mii_ioctl_data *mdio = if_mii(ifr);
-
-	DP(NETIF_MSG_LINK, "ioctl: phy id 0x%x, reg 0x%x, val_in 0x%x\n",
-	   mdio->phy_id, mdio->reg_num, mdio->val_in);
-
-	if (!netif_running(dev))
-		return -EAGAIN;
-
-	return mdio_mii_ioctl(&bp->mdio, mdio, cmd);
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void poll_bnx2x(struct net_device *dev)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	disable_irq(bp->pdev->irq);
-	bnx2x_interrupt(bp->pdev->irq, dev);
-	enable_irq(bp->pdev->irq);
-}
-#endif
-
-static const struct net_device_ops bnx2x_netdev_ops = {
-	.ndo_open		= bnx2x_open,
-	.ndo_stop		= bnx2x_close,
-	.ndo_start_xmit		= bnx2x_start_xmit,
-	.ndo_select_queue	= bnx2x_select_queue,
-	.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,
-	.ndo_change_mtu		= bnx2x_change_mtu,
-	.ndo_fix_features	= bnx2x_fix_features,
-	.ndo_set_features	= bnx2x_set_features,
-	.ndo_tx_timeout		= bnx2x_tx_timeout,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= poll_bnx2x,
-#endif
-	.ndo_setup_tc		= bnx2x_setup_tc,
-
-#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
-	.ndo_fcoe_get_wwn	= bnx2x_fcoe_get_wwn,
-#endif
-};
-
-static inline int bnx2x_set_coherency_mask(struct bnx2x *bp)
-{
-	struct device *dev = &bp->pdev->dev;
-
-	if (dma_set_mask(dev, DMA_BIT_MASK(64)) == 0) {
-		bp->flags |= USING_DAC_FLAG;
-		if (dma_set_coherent_mask(dev, DMA_BIT_MASK(64)) != 0) {
-			dev_err(dev, "dma_set_coherent_mask failed, "
-				     "aborting\n");
-			return -EIO;
-		}
-	} else if (dma_set_mask(dev, DMA_BIT_MASK(32)) != 0) {
-		dev_err(dev, "System does not support DMA, aborting\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
-				    struct net_device *dev,
-				    unsigned long board_type)
-{
-	struct bnx2x *bp;
-	int rc;
-
-	SET_NETDEV_DEV(dev, &pdev->dev);
-	bp = netdev_priv(dev);
-
-	bp->dev = dev;
-	bp->pdev = pdev;
-	bp->flags = 0;
-	bp->pf_num = PCI_FUNC(pdev->devfn);
-
-	rc = pci_enable_device(pdev);
-	if (rc) {
-		dev_err(&bp->pdev->dev,
-			"Cannot enable PCI device, aborting\n");
-		goto err_out;
-	}
-
-	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
-		dev_err(&bp->pdev->dev,
-			"Cannot find PCI device base address, aborting\n");
-		rc = -ENODEV;
-		goto err_out_disable;
-	}
-
-	if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
-		dev_err(&bp->pdev->dev, "Cannot find second PCI device"
-		       " base address, aborting\n");
-		rc = -ENODEV;
-		goto err_out_disable;
-	}
-
-	if (atomic_read(&pdev->enable_cnt) == 1) {
-		rc = pci_request_regions(pdev, DRV_MODULE_NAME);
-		if (rc) {
-			dev_err(&bp->pdev->dev,
-				"Cannot obtain PCI resources, aborting\n");
-			goto err_out_disable;
-		}
-
-		pci_set_master(pdev);
-		pci_save_state(pdev);
-	}
-
-	bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
-	if (bp->pm_cap == 0) {
-		dev_err(&bp->pdev->dev,
-			"Cannot find power management capability, aborting\n");
-		rc = -EIO;
-		goto err_out_release;
-	}
-
-	if (!pci_is_pcie(pdev)) {
-		dev_err(&bp->pdev->dev,	"Not PCI Express, aborting\n");
-		rc = -EIO;
-		goto err_out_release;
-	}
-
-	rc = bnx2x_set_coherency_mask(bp);
-	if (rc)
-		goto err_out_release;
-
-	dev->mem_start = pci_resource_start(pdev, 0);
-	dev->base_addr = dev->mem_start;
-	dev->mem_end = pci_resource_end(pdev, 0);
-
-	dev->irq = pdev->irq;
-
-	bp->regview = pci_ioremap_bar(pdev, 0);
-	if (!bp->regview) {
-		dev_err(&bp->pdev->dev,
-			"Cannot map register space, aborting\n");
-		rc = -ENOMEM;
-		goto err_out_release;
-	}
-
-	bnx2x_set_power_state(bp, PCI_D0);
-
-	/* clean indirect addresses */
-	pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS,
-			       PCICFG_VENDOR_ID_OFFSET);
-	/*
-	 * Clean the following indirect addresses for all functions since it
-	 * is not used by the driver.
-	 */
-	REG_WR(bp, PXP2_REG_PGL_ADDR_88_F0, 0);
-	REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F0, 0);
-	REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0, 0);
-	REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0, 0);
-
-	if (CHIP_IS_E1x(bp)) {
-		REG_WR(bp, PXP2_REG_PGL_ADDR_88_F1, 0);
-		REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F1, 0);
-		REG_WR(bp, PXP2_REG_PGL_ADDR_90_F1, 0);
-		REG_WR(bp, PXP2_REG_PGL_ADDR_94_F1, 0);
-	}
-
-	/*
-	 * Enable internal target-read (in case we are probed after PF FLR).
-	 * Must be done prior to any BAR read access. Only for 57712 and up
-	 */
-	if (board_type != BCM57710 &&
-	    board_type != BCM57711 &&
-	    board_type != BCM57711E)
-		REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
-
-	/* Reset the load counter */
-	bnx2x_clear_load_cnt(bp);
-
-	dev->watchdog_timeo = TX_TIMEOUT;
-
-	dev->netdev_ops = &bnx2x_netdev_ops;
-	bnx2x_set_ethtool_ops(dev);
-
-	dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 |
-		NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_HW_VLAN_TX;
-
-	dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_HIGHDMA;
-
-	dev->features |= dev->hw_features | NETIF_F_HW_VLAN_RX;
-	if (bp->flags & USING_DAC_FLAG)
-		dev->features |= NETIF_F_HIGHDMA;
-
-	/* Add Loopback capability to the device */
-	dev->hw_features |= NETIF_F_LOOPBACK;
-
-#ifdef BCM_DCBNL
-	dev->dcbnl_ops = &bnx2x_dcbnl_ops;
-#endif
-
-	/* get_port_hwinfo() will set prtad and mmds properly */
-	bp->mdio.prtad = MDIO_PRTAD_NONE;
-	bp->mdio.mmds = 0;
-	bp->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
-	bp->mdio.dev = dev;
-	bp->mdio.mdio_read = bnx2x_mdio_read;
-	bp->mdio.mdio_write = bnx2x_mdio_write;
-
-	return 0;
-
-err_out_release:
-	if (atomic_read(&pdev->enable_cnt) == 1)
-		pci_release_regions(pdev);
-
-err_out_disable:
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-
-err_out:
-	return rc;
-}
-
-static void __devinit bnx2x_get_pcie_width_speed(struct bnx2x *bp,
-						 int *width, int *speed)
-{
-	u32 val = REG_RD(bp, PCICFG_OFFSET + PCICFG_LINK_CONTROL);
-
-	*width = (val & PCICFG_LINK_WIDTH) >> PCICFG_LINK_WIDTH_SHIFT;
-
-	/* return value of 1=2.5GHz 2=5GHz */
-	*speed = (val & PCICFG_LINK_SPEED) >> PCICFG_LINK_SPEED_SHIFT;
-}
-
-/*(DEBLOBBED)*/
-
-static inline void be32_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
-{
-	const __be32 *source = (const __be32 *)_source;
-	u32 *target = (u32 *)_target;
-	u32 i;
-
-	for (i = 0; i < n/4; i++)
-		target[i] = be32_to_cpu(source[i]);
-}
-
-/*
-   Ops array is stored in the following format:
-   {op(8bit), offset(24bit, big endian), data(32bit, big endian)}
- */
-static inline void bnx2x_prep_ops(const u8 *_source, u8 *_target, u32 n)
-{
-	const __be32 *source = (const __be32 *)_source;
-	struct raw_op *target = (struct raw_op *)_target;
-	u32 i, j, tmp;
-
-	for (i = 0, j = 0; i < n/8; i++, j += 2) {
-		tmp = be32_to_cpu(source[j]);
-		target[i].op = (tmp >> 24) & 0xff;
-		target[i].offset = tmp & 0xffffff;
-		target[i].raw_data = be32_to_cpu(source[j + 1]);
-	}
-}
-
-/**
- * IRO array is stored in the following format:
- * {base(24bit), m1(16bit), m2(16bit), m3(16bit), size(16bit) }
- */
-static inline void bnx2x_prep_iro(const u8 *_source, u8 *_target, u32 n)
-{
-	const __be32 *source = (const __be32 *)_source;
-	struct iro *target = (struct iro *)_target;
-	u32 i, j, tmp;
-
-	for (i = 0, j = 0; i < n/sizeof(struct iro); i++) {
-		target[i].base = be32_to_cpu(source[j]);
-		j++;
-		tmp = be32_to_cpu(source[j]);
-		target[i].m1 = (tmp >> 16) & 0xffff;
-		target[i].m2 = tmp & 0xffff;
-		j++;
-		tmp = be32_to_cpu(source[j]);
-		target[i].m3 = (tmp >> 16) & 0xffff;
-		target[i].size = tmp & 0xffff;
-		j++;
-	}
-}
-
-static inline void be16_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
-{
-	const __be16 *source = (const __be16 *)_source;
-	u16 *target = (u16 *)_target;
-	u32 i;
-
-	for (i = 0; i < n/2; i++)
-		target[i] = be16_to_cpu(source[i]);
-}
-
-#define BNX2X_ALLOC_AND_SET(arr, lbl, func)				\
-do {									\
-	u32 len = be32_to_cpu(fw_hdr->arr.len);				\
-	bp->arr = kmalloc(len, GFP_KERNEL);				\
-	if (!bp->arr) {							\
-		pr_err("Failed to allocate %d bytes for "#arr"\n", len); \
-		goto lbl;						\
-	}								\
-	func(bp->firmware->data + be32_to_cpu(fw_hdr->arr.offset),	\
-	     (u8 *)bp->arr, len);					\
-} while (0)
-
-int bnx2x_init_firmware(struct bnx2x *bp)
-{
-	const char *fw_file_name;
-	struct bnx2x_fw_file_hdr *fw_hdr;
-	int rc;
-
-	if (CHIP_IS_E1(bp))
-		fw_file_name = FW_FILE_NAME_E1;
-	else if (CHIP_IS_E1H(bp))
-		fw_file_name = FW_FILE_NAME_E1H;
-	else if (!CHIP_IS_E1x(bp))
-		fw_file_name = FW_FILE_NAME_E2;
-	else {
-		BNX2X_ERR("Unsupported chip revision\n");
-		return -EINVAL;
-	}
-
-	BNX2X_DEV_INFO("Loading %s\n", fw_file_name);
-
-	rc = reject_firmware(&bp->firmware, fw_file_name, &bp->pdev->dev);
-	if (rc) {
-		BNX2X_ERR("Can't load firmware file %s\n", fw_file_name);
-		goto reject_firmware_exit;
-	}
-
-	/*(DEBLOBBED)*/
-	if (rc) {
-		BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name);
-		goto reject_firmware_exit;
-	}
-
-	fw_hdr = (struct bnx2x_fw_file_hdr *)bp->firmware->data;
-
-	/* Initialize the pointers to the init arrays */
-	/* Blob */
-	BNX2X_ALLOC_AND_SET(init_data, reject_firmware_exit, be32_to_cpu_n);
-
-	/* Opcodes */
-	BNX2X_ALLOC_AND_SET(init_ops, init_ops_alloc_err, bnx2x_prep_ops);
-
-	/* Offsets */
-	BNX2X_ALLOC_AND_SET(init_ops_offsets, init_offsets_alloc_err,
-			    be16_to_cpu_n);
-
-	/* STORMs firmware */
-	INIT_TSEM_INT_TABLE_DATA(bp) = bp->firmware->data +
-			be32_to_cpu(fw_hdr->tsem_int_table_data.offset);
-	INIT_TSEM_PRAM_DATA(bp)      = bp->firmware->data +
-			be32_to_cpu(fw_hdr->tsem_pram_data.offset);
-	INIT_USEM_INT_TABLE_DATA(bp) = bp->firmware->data +
-			be32_to_cpu(fw_hdr->usem_int_table_data.offset);
-	INIT_USEM_PRAM_DATA(bp)      = bp->firmware->data +
-			be32_to_cpu(fw_hdr->usem_pram_data.offset);
-	INIT_XSEM_INT_TABLE_DATA(bp) = bp->firmware->data +
-			be32_to_cpu(fw_hdr->xsem_int_table_data.offset);
-	INIT_XSEM_PRAM_DATA(bp)      = bp->firmware->data +
-			be32_to_cpu(fw_hdr->xsem_pram_data.offset);
-	INIT_CSEM_INT_TABLE_DATA(bp) = bp->firmware->data +
-			be32_to_cpu(fw_hdr->csem_int_table_data.offset);
-	INIT_CSEM_PRAM_DATA(bp)      = bp->firmware->data +
-			be32_to_cpu(fw_hdr->csem_pram_data.offset);
-	/* IRO */
-	BNX2X_ALLOC_AND_SET(iro_arr, iro_alloc_err, bnx2x_prep_iro);
-
-	return 0;
-
-iro_alloc_err:
-	kfree(bp->init_ops_offsets);
-init_offsets_alloc_err:
-	kfree(bp->init_ops);
-init_ops_alloc_err:
-	kfree(bp->init_data);
-reject_firmware_exit:
-	release_firmware(bp->firmware);
-
-	return rc;
-}
-
-static void bnx2x_release_firmware(struct bnx2x *bp)
-{
-	kfree(bp->init_ops_offsets);
-	kfree(bp->init_ops);
-	kfree(bp->init_data);
-	release_firmware(bp->firmware);
-}
-
-
-static struct bnx2x_func_sp_drv_ops bnx2x_func_sp_drv = {
-	.init_hw_cmn_chip = bnx2x_init_hw_common_chip,
-	.init_hw_cmn      = bnx2x_init_hw_common,
-	.init_hw_port     = bnx2x_init_hw_port,
-	.init_hw_func     = bnx2x_init_hw_func,
-
-	.reset_hw_cmn     = bnx2x_reset_common,
-	.reset_hw_port    = bnx2x_reset_port,
-	.reset_hw_func    = bnx2x_reset_func,
-
-	.gunzip_init      = bnx2x_gunzip_init,
-	.gunzip_end       = bnx2x_gunzip_end,
-
-	.init_fw          = bnx2x_init_firmware,
-	.release_fw       = bnx2x_release_firmware,
-};
-
-void bnx2x__init_func_obj(struct bnx2x *bp)
-{
-	/* Prepare DMAE related driver resources */
-	bnx2x_setup_dmae(bp);
-
-	bnx2x_init_func_obj(bp, &bp->func_obj,
-			    bnx2x_sp(bp, func_rdata),
-			    bnx2x_sp_mapping(bp, func_rdata),
-			    &bnx2x_func_sp_drv);
-}
-
-/* must be called after sriov-enable */
-static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp)
-{
-	int cid_count = BNX2X_L2_CID_COUNT(bp);
-
-#ifdef BCM_CNIC
-	cid_count += CNIC_CID_MAX;
-#endif
-	return roundup(cid_count, QM_CID_ROUND);
-}
-
-/**
- * bnx2x_get_num_none_def_sbs - return the number of none default SBs
- *
- * @dev:	pci device
- *
- */
-static inline int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev)
-{
-	int pos;
-	u16 control;
-
-	pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
-
-	/*
-	 * If MSI-X is not supported - return number of SBs needed to support
-	 * one fast path queue: one FP queue + SB for CNIC
-	 */
-	if (!pos)
-		return 1 + CNIC_PRESENT;
-
-	/*
-	 * The value in the PCI configuration space is the index of the last
-	 * entry, namely one less than the actual size of the table, which is
-	 * exactly what we want to return from this function: number of all SBs
-	 * without the default SB.
-	 */
-	pci_read_config_word(pdev, pos  + PCI_MSI_FLAGS, &control);
-	return control & PCI_MSIX_FLAGS_QSIZE;
-}
-
-static int __devinit bnx2x_init_one(struct pci_dev *pdev,
-				    const struct pci_device_id *ent)
-{
-	struct net_device *dev = NULL;
-	struct bnx2x *bp;
-	int pcie_width, pcie_speed;
-	int rc, max_non_def_sbs;
-	int rx_count, tx_count, rss_count;
-	/*
-	 * An estimated maximum supported CoS number according to the chip
-	 * version.
-	 * We will try to roughly estimate the maximum number of CoSes this chip
-	 * may support in order to minimize the memory allocated for Tx
-	 * netdev_queue's. This number will be accurately calculated during the
-	 * initialization of bp->max_cos based on the chip versions AND chip
-	 * revision in the bnx2x_init_bp().
-	 */
-	u8 max_cos_est = 0;
-
-	switch (ent->driver_data) {
-	case BCM57710:
-	case BCM57711:
-	case BCM57711E:
-		max_cos_est = BNX2X_MULTI_TX_COS_E1X;
-		break;
-
-	case BCM57712:
-	case BCM57712_MF:
-		max_cos_est = BNX2X_MULTI_TX_COS_E2_E3A0;
-		break;
-
-	case BCM57800:
-	case BCM57800_MF:
-	case BCM57810:
-	case BCM57810_MF:
-	case BCM57840:
-	case BCM57840_MF:
-		max_cos_est = BNX2X_MULTI_TX_COS_E3B0;
-		break;
-
-	default:
-		pr_err("Unknown board_type (%ld), aborting\n",
-			   ent->driver_data);
-		return -ENODEV;
-	}
-
-	max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev);
-
-	/* !!! FIXME !!!
-	 * Do not allow the maximum SB count to grow above 16
-	 * since Special CIDs starts from 16*BNX2X_MULTI_TX_COS=48.
-	 * We will use the FP_SB_MAX_E1x macro for this matter.
-	 */
-	max_non_def_sbs = min_t(int, FP_SB_MAX_E1x, max_non_def_sbs);
-
-	WARN_ON(!max_non_def_sbs);
-
-	/* Maximum number of RSS queues: one IGU SB goes to CNIC */
-	rss_count = max_non_def_sbs - CNIC_PRESENT;
-
-	/* Maximum number of netdev Rx queues: RSS + FCoE L2 */
-	rx_count = rss_count + FCOE_PRESENT;
-
-	/*
-	 * Maximum number of netdev Tx queues:
-	 *      Maximum TSS queues * Maximum supported number of CoS  + FCoE L2
-	 */
-	tx_count = MAX_TXQS_PER_COS * max_cos_est + FCOE_PRESENT;
-
-	/* dev zeroed in init_etherdev */
-	dev = alloc_etherdev_mqs(sizeof(*bp), tx_count, rx_count);
-	if (!dev) {
-		dev_err(&pdev->dev, "Cannot allocate net device\n");
-		return -ENOMEM;
-	}
-
-	bp = netdev_priv(dev);
-
-	DP(NETIF_MSG_DRV, "Allocated netdev with %d tx and %d rx queues\n",
-			  tx_count, rx_count);
-
-	bp->igu_sb_cnt = max_non_def_sbs;
-	bp->msg_enable = debug;
-	pci_set_drvdata(pdev, dev);
-
-	rc = bnx2x_init_dev(pdev, dev, ent->driver_data);
-	if (rc < 0) {
-		free_netdev(dev);
-		return rc;
-	}
-
-	DP(NETIF_MSG_DRV, "max_non_def_sbs %d", max_non_def_sbs);
-
-	rc = bnx2x_init_bp(bp);
-	if (rc)
-		goto init_one_exit;
-
-	/*
-	 * Map doorbels here as we need the real value of bp->max_cos which
-	 * is initialized in bnx2x_init_bp().
-	 */
-	bp->doorbells = ioremap_nocache(pci_resource_start(pdev, 2),
-					min_t(u64, BNX2X_DB_SIZE(bp),
-					      pci_resource_len(pdev, 2)));
-	if (!bp->doorbells) {
-		dev_err(&bp->pdev->dev,
-			"Cannot map doorbell space, aborting\n");
-		rc = -ENOMEM;
-		goto init_one_exit;
-	}
-
-	/* calc qm_cid_count */
-	bp->qm_cid_count = bnx2x_set_qm_cid_count(bp);
-
-#ifdef BCM_CNIC
-	/* disable FCOE L2 queue for E1x and E3*/
-	if (CHIP_IS_E1x(bp) || CHIP_IS_E3(bp))
-		bp->flags |= NO_FCOE_FLAG;
-
-#endif
-
-	/* Configure interrupt mode: try to enable MSI-X/MSI if
-	 * needed, set bp->num_queues appropriately.
-	 */
-	bnx2x_set_int_mode(bp);
-
-	/* Add all NAPI objects */
-	bnx2x_add_all_napi(bp);
-
-	rc = register_netdev(dev);
-	if (rc) {
-		dev_err(&pdev->dev, "Cannot register net device\n");
-		goto init_one_exit;
-	}
-
-#ifdef BCM_CNIC
-	if (!NO_FCOE(bp)) {
-		/* Add storage MAC address */
-		rtnl_lock();
-		dev_addr_add(bp->dev, bp->fip_mac, NETDEV_HW_ADDR_T_SAN);
-		rtnl_unlock();
-	}
-#endif
-
-	bnx2x_get_pcie_width_speed(bp, &pcie_width, &pcie_speed);
-
-	netdev_info(dev, "%s (%c%d) PCI-E x%d %s found at mem %lx,"
-	       " IRQ %d, ", board_info[ent->driver_data].name,
-	       (CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4),
-	       pcie_width,
-	       ((!CHIP_IS_E2(bp) && pcie_speed == 2) ||
-		 (CHIP_IS_E2(bp) && pcie_speed == 1)) ?
-						"5GHz (Gen2)" : "2.5GHz",
-	       dev->base_addr, bp->pdev->irq);
-	pr_cont("node addr %pM\n", dev->dev_addr);
-
-	return 0;
-
-init_one_exit:
-	if (bp->regview)
-		iounmap(bp->regview);
-
-	if (bp->doorbells)
-		iounmap(bp->doorbells);
-
-	free_netdev(dev);
-
-	if (atomic_read(&pdev->enable_cnt) == 1)
-		pci_release_regions(pdev);
-
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-
-	return rc;
-}
-
-static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct bnx2x *bp;
-
-	if (!dev) {
-		dev_err(&pdev->dev, "BAD net device from bnx2x_init_one\n");
-		return;
-	}
-	bp = netdev_priv(dev);
-
-#ifdef BCM_CNIC
-	/* Delete storage MAC address */
-	if (!NO_FCOE(bp)) {
-		rtnl_lock();
-		dev_addr_del(bp->dev, bp->fip_mac, NETDEV_HW_ADDR_T_SAN);
-		rtnl_unlock();
-	}
-#endif
-
-#ifdef BCM_DCBNL
-	/* Delete app tlvs from dcbnl */
-	bnx2x_dcbnl_update_applist(bp, true);
-#endif
-
-	unregister_netdev(dev);
-
-	/* Delete all NAPI objects */
-	bnx2x_del_all_napi(bp);
-
-	/* Power on: we can't let PCI layer write to us while we are in D3 */
-	bnx2x_set_power_state(bp, PCI_D0);
-
-	/* Disable MSI/MSI-X */
-	bnx2x_disable_msi(bp);
-
-	/* Power off */
-	bnx2x_set_power_state(bp, PCI_D3hot);
-
-	/* Make sure RESET task is not scheduled before continuing */
-	cancel_delayed_work_sync(&bp->sp_rtnl_task);
-
-	if (bp->regview)
-		iounmap(bp->regview);
-
-	if (bp->doorbells)
-		iounmap(bp->doorbells);
-
-	bnx2x_free_mem_bp(bp);
-
-	free_netdev(dev);
-
-	if (atomic_read(&pdev->enable_cnt) == 1)
-		pci_release_regions(pdev);
-
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-}
-
-static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
-{
-	int i;
-
-	bp->state = BNX2X_STATE_ERROR;
-
-	bp->rx_mode = BNX2X_RX_MODE_NONE;
-
-#ifdef BCM_CNIC
-	bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
-#endif
-	/* Stop Tx */
-	bnx2x_tx_disable(bp);
-
-	bnx2x_netif_stop(bp, 0);
-
-	del_timer_sync(&bp->timer);
-
-	bnx2x_stats_handle(bp, STATS_EVENT_STOP);
-
-	/* Release IRQs */
-	bnx2x_free_irq(bp);
-
-	/* Free SKBs, SGEs, TPA pool and driver internals */
-	bnx2x_free_skbs(bp);
-
-	for_each_rx_queue(bp, i)
-		bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
-
-	bnx2x_free_mem(bp);
-
-	bp->state = BNX2X_STATE_CLOSED;
-
-	netif_carrier_off(bp->dev);
-
-	return 0;
-}
-
-static void bnx2x_eeh_recover(struct bnx2x *bp)
-{
-	u32 val;
-
-	mutex_init(&bp->port.phy_mutex);
-
-	bp->common.shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR);
-	bp->link_params.shmem_base = bp->common.shmem_base;
-	BNX2X_DEV_INFO("shmem offset is 0x%x\n", bp->common.shmem_base);
-
-	if (!bp->common.shmem_base ||
-	    (bp->common.shmem_base < 0xA0000) ||
-	    (bp->common.shmem_base >= 0xC0000)) {
-		BNX2X_DEV_INFO("MCP not active\n");
-		bp->flags |= NO_MCP_FLAG;
-		return;
-	}
-
-	val = SHMEM_RD(bp, validity_map[BP_PORT(bp)]);
-	if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
-		!= (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
-		BNX2X_ERR("BAD MCP validity signature\n");
-
-	if (!BP_NOMCP(bp)) {
-		bp->fw_seq =
-		    (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
-		    DRV_MSG_SEQ_NUMBER_MASK);
-		BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
-	}
-}
-
-/**
- * bnx2x_io_error_detected - called when PCI error is detected
- * @pdev: Pointer to PCI device
- * @state: The current pci connection state
- *
- * This function is called after a PCI bus error affecting
- * this device has been detected.
- */
-static pci_ers_result_t bnx2x_io_error_detected(struct pci_dev *pdev,
-						pci_channel_state_t state)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct bnx2x *bp = netdev_priv(dev);
-
-	rtnl_lock();
-
-	netif_device_detach(dev);
-
-	if (state == pci_channel_io_perm_failure) {
-		rtnl_unlock();
-		return PCI_ERS_RESULT_DISCONNECT;
-	}
-
-	if (netif_running(dev))
-		bnx2x_eeh_nic_unload(bp);
-
-	pci_disable_device(pdev);
-
-	rtnl_unlock();
-
-	/* Request a slot reset */
-	return PCI_ERS_RESULT_NEED_RESET;
-}
-
-/**
- * bnx2x_io_slot_reset - called after the PCI bus has been reset
- * @pdev: Pointer to PCI device
- *
- * Restart the card from scratch, as if from a cold-boot.
- */
-static pci_ers_result_t bnx2x_io_slot_reset(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct bnx2x *bp = netdev_priv(dev);
-
-	rtnl_lock();
-
-	if (pci_enable_device(pdev)) {
-		dev_err(&pdev->dev,
-			"Cannot re-enable PCI device after reset\n");
-		rtnl_unlock();
-		return PCI_ERS_RESULT_DISCONNECT;
-	}
-
-	pci_set_master(pdev);
-	pci_restore_state(pdev);
-
-	if (netif_running(dev))
-		bnx2x_set_power_state(bp, PCI_D0);
-
-	rtnl_unlock();
-
-	return PCI_ERS_RESULT_RECOVERED;
-}
-
-/**
- * bnx2x_io_resume - called when traffic can start flowing again
- * @pdev: Pointer to PCI device
- *
- * This callback is called when the error recovery driver tells us that
- * its OK to resume normal operation.
- */
-static void bnx2x_io_resume(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct bnx2x *bp = netdev_priv(dev);
-
-	if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
-		netdev_err(bp->dev, "Handling parity error recovery. "
-				    "Try again later\n");
-		return;
-	}
-
-	rtnl_lock();
-
-	bnx2x_eeh_recover(bp);
-
-	if (netif_running(dev))
-		bnx2x_nic_load(bp, LOAD_NORMAL);
-
-	netif_device_attach(dev);
-
-	rtnl_unlock();
-}
-
-static struct pci_error_handlers bnx2x_err_handler = {
-	.error_detected = bnx2x_io_error_detected,
-	.slot_reset     = bnx2x_io_slot_reset,
-	.resume         = bnx2x_io_resume,
-};
-
-static struct pci_driver bnx2x_pci_driver = {
-	.name        = DRV_MODULE_NAME,
-	.id_table    = bnx2x_pci_tbl,
-	.probe       = bnx2x_init_one,
-	.remove      = __devexit_p(bnx2x_remove_one),
-	.suspend     = bnx2x_suspend,
-	.resume      = bnx2x_resume,
-	.err_handler = &bnx2x_err_handler,
-};
-
-static int __init bnx2x_init(void)
-{
-	int ret;
-
-	pr_info("%s", version);
-
-	bnx2x_wq = create_singlethread_workqueue("bnx2x");
-	if (bnx2x_wq == NULL) {
-		pr_err("Cannot create workqueue\n");
-		return -ENOMEM;
-	}
-
-	ret = pci_register_driver(&bnx2x_pci_driver);
-	if (ret) {
-		pr_err("Cannot register driver\n");
-		destroy_workqueue(bnx2x_wq);
-	}
-	return ret;
-}
-
-static void __exit bnx2x_cleanup(void)
-{
-	pci_unregister_driver(&bnx2x_pci_driver);
-
-	destroy_workqueue(bnx2x_wq);
-}
-
-void bnx2x_notify_link_changed(struct bnx2x *bp)
-{
-	REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + BP_FUNC(bp)*sizeof(u32), 1);
-}
-
-module_init(bnx2x_init);
-module_exit(bnx2x_cleanup);
-
-#ifdef BCM_CNIC
-/**
- * bnx2x_set_iscsi_eth_mac_addr - set iSCSI MAC(s).
- *
- * @bp:		driver handle
- * @set:	set or clear the CAM entry
- *
- * This function will wait until the ramdord completion returns.
- * Return 0 if success, -ENODEV if ramrod doesn't return.
- */
-static inline int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp)
-{
-	unsigned long ramrod_flags = 0;
-
-	__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
-	return bnx2x_set_mac_one(bp, bp->cnic_eth_dev.iscsi_mac,
-				 &bp->iscsi_l2_mac_obj, true,
-				 BNX2X_ISCSI_ETH_MAC, &ramrod_flags);
-}
-
-/* count denotes the number of new completions we have seen */
-static void bnx2x_cnic_sp_post(struct bnx2x *bp, int count)
-{
-	struct eth_spe *spe;
-
-#ifdef BNX2X_STOP_ON_ERROR
-	if (unlikely(bp->panic))
-		return;
-#endif
-
-	spin_lock_bh(&bp->spq_lock);
-	BUG_ON(bp->cnic_spq_pending < count);
-	bp->cnic_spq_pending -= count;
-
-
-	for (; bp->cnic_kwq_pending; bp->cnic_kwq_pending--) {
-		u16 type =  (le16_to_cpu(bp->cnic_kwq_cons->hdr.type)
-				& SPE_HDR_CONN_TYPE) >>
-				SPE_HDR_CONN_TYPE_SHIFT;
-		u8 cmd = (le32_to_cpu(bp->cnic_kwq_cons->hdr.conn_and_cmd_data)
-				>> SPE_HDR_CMD_ID_SHIFT) & 0xff;
-
-		/* Set validation for iSCSI L2 client before sending SETUP
-		 *  ramrod
-		 */
-		if (type == ETH_CONNECTION_TYPE) {
-			if (cmd == RAMROD_CMD_ID_ETH_CLIENT_SETUP)
-				bnx2x_set_ctx_validation(bp, &bp->context.
-					vcxt[BNX2X_ISCSI_ETH_CID].eth,
-					BNX2X_ISCSI_ETH_CID);
-		}
-
-		/*
-		 * There may be not more than 8 L2, not more than 8 L5 SPEs
-		 * and in the air. We also check that number of outstanding
-		 * COMMON ramrods is not more than the EQ and SPQ can
-		 * accommodate.
-		 */
-		if (type == ETH_CONNECTION_TYPE) {
-			if (!atomic_read(&bp->cq_spq_left))
-				break;
-			else
-				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 >=
-			    bp->cnic_eth_dev.max_kwqe_pending)
-				break;
-			else
-				bp->cnic_spq_pending++;
-		} else {
-			BNX2X_ERR("Unknown SPE type: %d\n", type);
-			bnx2x_panic();
-			break;
-		}
-
-		spe = bnx2x_sp_get_next(bp);
-		*spe = *bp->cnic_kwq_cons;
-
-		DP(NETIF_MSG_TIMER, "pending on SPQ %d, on KWQ %d count %d\n",
-		   bp->cnic_spq_pending, bp->cnic_kwq_pending, count);
-
-		if (bp->cnic_kwq_cons == bp->cnic_kwq_last)
-			bp->cnic_kwq_cons = bp->cnic_kwq;
-		else
-			bp->cnic_kwq_cons++;
-	}
-	bnx2x_sp_prod_update(bp);
-	spin_unlock_bh(&bp->spq_lock);
-}
-
-static int bnx2x_cnic_sp_queue(struct net_device *dev,
-			       struct kwqe_16 *kwqes[], u32 count)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	int i;
-
-#ifdef BNX2X_STOP_ON_ERROR
-	if (unlikely(bp->panic))
-		return -EIO;
-#endif
-
-	spin_lock_bh(&bp->spq_lock);
-
-	for (i = 0; i < count; i++) {
-		struct eth_spe *spe = (struct eth_spe *)kwqes[i];
-
-		if (bp->cnic_kwq_pending == MAX_SP_DESC_CNT)
-			break;
-
-		*bp->cnic_kwq_prod = *spe;
-
-		bp->cnic_kwq_pending++;
-
-		DP(NETIF_MSG_TIMER, "L5 SPQE %x %x %x:%x pos %d\n",
-		   spe->hdr.conn_and_cmd_data, spe->hdr.type,
-		   spe->data.update_data_addr.hi,
-		   spe->data.update_data_addr.lo,
-		   bp->cnic_kwq_pending);
-
-		if (bp->cnic_kwq_prod == bp->cnic_kwq_last)
-			bp->cnic_kwq_prod = bp->cnic_kwq;
-		else
-			bp->cnic_kwq_prod++;
-	}
-
-	spin_unlock_bh(&bp->spq_lock);
-
-	if (bp->cnic_spq_pending < bp->cnic_eth_dev.max_kwqe_pending)
-		bnx2x_cnic_sp_post(bp, 0);
-
-	return i;
-}
-
-static int bnx2x_cnic_ctl_send(struct bnx2x *bp, struct cnic_ctl_info *ctl)
-{
-	struct cnic_ops *c_ops;
-	int rc = 0;
-
-	mutex_lock(&bp->cnic_mutex);
-	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);
-
-	return rc;
-}
-
-static int bnx2x_cnic_ctl_send_bh(struct bnx2x *bp, struct cnic_ctl_info *ctl)
-{
-	struct cnic_ops *c_ops;
-	int rc = 0;
-
-	rcu_read_lock();
-	c_ops = rcu_dereference(bp->cnic_ops);
-	if (c_ops)
-		rc = c_ops->cnic_ctl(bp->cnic_data, ctl);
-	rcu_read_unlock();
-
-	return rc;
-}
-
-/*
- * for commands that have no data
- */
-int bnx2x_cnic_notify(struct bnx2x *bp, int cmd)
-{
-	struct cnic_ctl_info ctl = {0};
-
-	ctl.cmd = cmd;
-
-	return bnx2x_cnic_ctl_send(bp, &ctl);
-}
-
-static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid, u8 err)
-{
-	struct cnic_ctl_info ctl = {0};
-
-	/* first we tell CNIC and only then we count this as a completion */
-	ctl.cmd = CNIC_CTL_COMPLETION_CMD;
-	ctl.data.comp.cid = cid;
-	ctl.data.comp.error = err;
-
-	bnx2x_cnic_ctl_send_bh(bp, &ctl);
-	bnx2x_cnic_sp_post(bp, 0);
-}
-
-
-/* Called with netif_addr_lock_bh() taken.
- * Sets an rx_mode config for an iSCSI ETH client.
- * Doesn't block.
- * Completion should be checked outside.
- */
-static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start)
-{
-	unsigned long accept_flags = 0, ramrod_flags = 0;
-	u8 cl_id = bnx2x_cnic_eth_cl_id(bp, BNX2X_ISCSI_ETH_CL_ID_IDX);
-	int sched_state = BNX2X_FILTER_ISCSI_ETH_STOP_SCHED;
-
-	if (start) {
-		/* Start accepting on iSCSI L2 ring. Accept all multicasts
-		 * because it's the only way for UIO Queue to accept
-		 * multicasts (in non-promiscuous mode only one Queue per
-		 * function will receive multicast packets (leading in our
-		 * case).
-		 */
-		__set_bit(BNX2X_ACCEPT_UNICAST, &accept_flags);
-		__set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &accept_flags);
-		__set_bit(BNX2X_ACCEPT_BROADCAST, &accept_flags);
-		__set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
-
-		/* Clear STOP_PENDING bit if START is requested */
-		clear_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED, &bp->sp_state);
-
-		sched_state = BNX2X_FILTER_ISCSI_ETH_START_SCHED;
-	} else
-		/* Clear START_PENDING bit if STOP is requested */
-		clear_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED, &bp->sp_state);
-
-	if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state))
-		set_bit(sched_state, &bp->sp_state);
-	else {
-		__set_bit(RAMROD_RX, &ramrod_flags);
-		bnx2x_set_q_rx_mode(bp, cl_id, 0, accept_flags, 0,
-				    ramrod_flags);
-	}
-}
-
-
-static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	int rc = 0;
-
-	switch (ctl->cmd) {
-	case DRV_CTL_CTXTBL_WR_CMD: {
-		u32 index = ctl->data.io.offset;
-		dma_addr_t addr = ctl->data.io.dma_addr;
-
-		bnx2x_ilt_wr(bp, index, addr);
-		break;
-	}
-
-	case DRV_CTL_RET_L5_SPQ_CREDIT_CMD: {
-		int count = ctl->data.credit.credit_count;
-
-		bnx2x_cnic_sp_post(bp, count);
-		break;
-	}
-
-	/* rtnl_lock is held.  */
-	case DRV_CTL_START_L2_CMD: {
-		struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
-		unsigned long sp_bits = 0;
-
-		/* Configure the iSCSI classification object */
-		bnx2x_init_mac_obj(bp, &bp->iscsi_l2_mac_obj,
-				   cp->iscsi_l2_client_id,
-				   cp->iscsi_l2_cid, BP_FUNC(bp),
-				   bnx2x_sp(bp, mac_rdata),
-				   bnx2x_sp_mapping(bp, mac_rdata),
-				   BNX2X_FILTER_MAC_PENDING,
-				   &bp->sp_state, BNX2X_OBJ_TYPE_RX,
-				   &bp->macs_pool);
-
-		/* Set iSCSI MAC address */
-		rc = bnx2x_set_iscsi_eth_mac_addr(bp);
-		if (rc)
-			break;
-
-		mmiowb();
-		barrier();
-
-		/* Start accepting on iSCSI L2 ring */
-
-		netif_addr_lock_bh(dev);
-		bnx2x_set_iscsi_eth_rx_mode(bp, true);
-		netif_addr_unlock_bh(dev);
-
-		/* bits to wait on */
-		__set_bit(BNX2X_FILTER_RX_MODE_PENDING, &sp_bits);
-		__set_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED, &sp_bits);
-
-		if (!bnx2x_wait_sp_comp(bp, sp_bits))
-			BNX2X_ERR("rx_mode completion timed out!\n");
-
-		break;
-	}
-
-	/* rtnl_lock is held.  */
-	case DRV_CTL_STOP_L2_CMD: {
-		unsigned long sp_bits = 0;
-
-		/* Stop accepting on iSCSI L2 ring */
-		netif_addr_lock_bh(dev);
-		bnx2x_set_iscsi_eth_rx_mode(bp, false);
-		netif_addr_unlock_bh(dev);
-
-		/* bits to wait on */
-		__set_bit(BNX2X_FILTER_RX_MODE_PENDING, &sp_bits);
-		__set_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED, &sp_bits);
-
-		if (!bnx2x_wait_sp_comp(bp, sp_bits))
-			BNX2X_ERR("rx_mode completion timed out!\n");
-
-		mmiowb();
-		barrier();
-
-		/* Unset iSCSI L2 MAC */
-		rc = bnx2x_del_all_macs(bp, &bp->iscsi_l2_mac_obj,
-					BNX2X_ISCSI_ETH_MAC, true);
-		break;
-	}
-	case DRV_CTL_RET_L2_SPQ_CREDIT_CMD: {
-		int count = ctl->data.credit.credit_count;
-
-		smp_mb__before_atomic_inc();
-		atomic_add(count, &bp->cq_spq_left);
-		smp_mb__after_atomic_inc();
-		break;
-	}
-
-	default:
-		BNX2X_ERR("unknown command %x\n", ctl->cmd);
-		rc = -EINVAL;
-	}
-
-	return rc;
-}
-
-void bnx2x_setup_cnic_irq_info(struct bnx2x *bp)
-{
-	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
-
-	if (bp->flags & USING_MSIX_FLAG) {
-		cp->drv_state |= CNIC_DRV_STATE_USING_MSIX;
-		cp->irq_arr[0].irq_flags |= CNIC_IRQ_FL_MSIX;
-		cp->irq_arr[0].vector = bp->msix_table[1].vector;
-	} else {
-		cp->drv_state &= ~CNIC_DRV_STATE_USING_MSIX;
-		cp->irq_arr[0].irq_flags &= ~CNIC_IRQ_FL_MSIX;
-	}
-	if (!CHIP_IS_E1x(bp))
-		cp->irq_arr[0].status_blk = (void *)bp->cnic_sb.e2_sb;
-	else
-		cp->irq_arr[0].status_blk = (void *)bp->cnic_sb.e1x_sb;
-
-	cp->irq_arr[0].status_blk_num =  bnx2x_cnic_fw_sb_id(bp);
-	cp->irq_arr[0].status_blk_num2 = bnx2x_cnic_igu_sb_id(bp);
-	cp->irq_arr[1].status_blk = bp->def_status_blk;
-	cp->irq_arr[1].status_blk_num = DEF_SB_ID;
-	cp->irq_arr[1].status_blk_num2 = DEF_SB_IGU_ID;
-
-	cp->num_irq = 2;
-}
-
-static int bnx2x_register_cnic(struct net_device *dev, struct cnic_ops *ops,
-			       void *data)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
-
-	if (ops == NULL)
-		return -EINVAL;
-
-	bp->cnic_kwq = kzalloc(PAGE_SIZE, GFP_KERNEL);
-	if (!bp->cnic_kwq)
-		return -ENOMEM;
-
-	bp->cnic_kwq_cons = bp->cnic_kwq;
-	bp->cnic_kwq_prod = bp->cnic_kwq;
-	bp->cnic_kwq_last = bp->cnic_kwq + MAX_SP_DESC_CNT;
-
-	bp->cnic_spq_pending = 0;
-	bp->cnic_kwq_pending = 0;
-
-	bp->cnic_data = data;
-
-	cp->num_irq = 0;
-	cp->drv_state |= CNIC_DRV_STATE_REGD;
-	cp->iro_arr = bp->iro_arr;
-
-	bnx2x_setup_cnic_irq_info(bp);
-
-	rcu_assign_pointer(bp->cnic_ops, ops);
-
-	return 0;
-}
-
-static int bnx2x_unregister_cnic(struct net_device *dev)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
-
-	mutex_lock(&bp->cnic_mutex);
-	cp->drv_state = 0;
-	rcu_assign_pointer(bp->cnic_ops, NULL);
-	mutex_unlock(&bp->cnic_mutex);
-	synchronize_rcu();
-	kfree(bp->cnic_kwq);
-	bp->cnic_kwq = NULL;
-
-	return 0;
-}
-
-struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
-{
-	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;
-	cp->io_base = bp->regview;
-	cp->io_base2 = bp->doorbells;
-	cp->max_kwqe_pending = 8;
-	cp->ctx_blk_size = CDU_ILT_PAGE_SZ;
-	cp->ctx_tbl_offset = FUNC_ILT_BASE(BP_FUNC(bp)) +
-			     bnx2x_cid_ilt_lines(bp);
-	cp->ctx_tbl_len = CNIC_ILT_LINES;
-	cp->starting_cid = bnx2x_cid_ilt_lines(bp) * ILT_PAGE_CIDS;
-	cp->drv_submit_kwqes_16 = bnx2x_cnic_sp_queue;
-	cp->drv_ctl = bnx2x_drv_ctl;
-	cp->drv_register_cnic = bnx2x_register_cnic;
-	cp->drv_unregister_cnic = bnx2x_unregister_cnic;
-	cp->fcoe_init_cid = BNX2X_FCOE_ETH_CID;
-	cp->iscsi_l2_client_id =
-		bnx2x_cnic_eth_cl_id(bp, BNX2X_ISCSI_ETH_CL_ID_IDX);
-	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,
-	   cp->ctx_tbl_offset,
-	   cp->ctx_tbl_len,
-	   cp->starting_cid);
-	return cp;
-}
-EXPORT_SYMBOL(bnx2x_cnic_probe);
-
-#endif /* BCM_CNIC */
-
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_reg.h linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_reg.h
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_reg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_reg.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7177 +0,0 @@
-/* bnx2x_reg.h: Broadcom Everest network driver.
- *
- * Copyright (c) 2007-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
- * the Free Software Foundation.
- *
- * The registers description starts with the register Access type followed
- * by size in bits. For example [RW 32]. The access types are:
- * R  - Read only
- * RC - Clear on read
- * RW - Read/Write
- * ST - Statistics register (clear on read)
- * W  - Write only
- * WB - Wide bus register - the size is over 32 bits and it should be
- *      read/write in consecutive 32 bits accesses
- * WR - Write Clear (write 1 to clear the bit)
- *
- */
-#ifndef BNX2X_REG_H
-#define BNX2X_REG_H
-
-#define ATC_ATC_INT_STS_REG_ADDRESS_ERROR			 (0x1<<0)
-#define ATC_ATC_INT_STS_REG_ATC_GPA_MULTIPLE_HITS		 (0x1<<2)
-#define ATC_ATC_INT_STS_REG_ATC_IREQ_LESS_THAN_STU		 (0x1<<5)
-#define ATC_ATC_INT_STS_REG_ATC_RCPL_TO_EMPTY_CNT		 (0x1<<3)
-#define ATC_ATC_INT_STS_REG_ATC_TCPL_ERROR			 (0x1<<4)
-#define ATC_ATC_INT_STS_REG_ATC_TCPL_TO_NOT_PEND		 (0x1<<1)
-/* [RW 1] Initiate the ATC array - reset all the valid bits */
-#define ATC_REG_ATC_INIT_ARRAY					 0x1100b8
-/* [R 1] ATC initalization done */
-#define ATC_REG_ATC_INIT_DONE					 0x1100bc
-/* [RC 6] Interrupt register #0 read clear */
-#define ATC_REG_ATC_INT_STS_CLR					 0x1101c0
-/* [RW 5] Parity mask register #0 read/write */
-#define ATC_REG_ATC_PRTY_MASK					 0x1101d8
-/* [RC 5] Parity register #0 read clear */
-#define ATC_REG_ATC_PRTY_STS_CLR				 0x1101d0
-/* [RW 19] Interrupt mask register #0 read/write */
-#define BRB1_REG_BRB1_INT_MASK					 0x60128
-/* [R 19] Interrupt register #0 read */
-#define BRB1_REG_BRB1_INT_STS					 0x6011c
-/* [RW 4] Parity mask register #0 read/write */
-#define BRB1_REG_BRB1_PRTY_MASK 				 0x60138
-/* [R 4] Parity register #0 read */
-#define BRB1_REG_BRB1_PRTY_STS					 0x6012c
-/* [RC 4] Parity register #0 read clear */
-#define BRB1_REG_BRB1_PRTY_STS_CLR				 0x60130
-/* [RW 10] At address BRB1_IND_FREE_LIST_PRS_CRDT initialize free head. At
- * address BRB1_IND_FREE_LIST_PRS_CRDT+1 initialize free tail. At address
- * BRB1_IND_FREE_LIST_PRS_CRDT+2 initialize parser initial credit. Warning -
- * following reset the first rbc access to this reg must be write; there can
- * be no more rbc writes after the first one; there can be any number of rbc
- * read following the first write; rbc access not following these rules will
- * result in hang condition. */
-#define BRB1_REG_FREE_LIST_PRS_CRDT				 0x60200
-/* [RW 10] The number of free blocks below which the full signal to class 0
- * is asserted */
-#define BRB1_REG_FULL_0_XOFF_THRESHOLD_0			 0x601d0
-#define BRB1_REG_FULL_0_XOFF_THRESHOLD_1			 0x60230
-/* [RW 11] The number of free blocks above which the full signal to class 0
- * is de-asserted */
-#define BRB1_REG_FULL_0_XON_THRESHOLD_0				 0x601d4
-#define BRB1_REG_FULL_0_XON_THRESHOLD_1				 0x60234
-/* [RW 11] The number of free blocks below which the full signal to class 1
- * is asserted */
-#define BRB1_REG_FULL_1_XOFF_THRESHOLD_0			 0x601d8
-#define BRB1_REG_FULL_1_XOFF_THRESHOLD_1			 0x60238
-/* [RW 11] The number of free blocks above which the full signal to class 1
- * is de-asserted */
-#define BRB1_REG_FULL_1_XON_THRESHOLD_0				 0x601dc
-#define BRB1_REG_FULL_1_XON_THRESHOLD_1				 0x6023c
-/* [RW 11] The number of free blocks below which the full signal to the LB
- * port is asserted */
-#define BRB1_REG_FULL_LB_XOFF_THRESHOLD				 0x601e0
-/* [RW 10] The number of free blocks above which the full signal to the LB
- * port is de-asserted */
-#define BRB1_REG_FULL_LB_XON_THRESHOLD				 0x601e4
-/* [RW 10] The number of free blocks above which the High_llfc signal to
-   interface #n is de-asserted. */
-#define BRB1_REG_HIGH_LLFC_HIGH_THRESHOLD_0			 0x6014c
-/* [RW 10] The number of free blocks below which the High_llfc signal to
-   interface #n is asserted. */
-#define BRB1_REG_HIGH_LLFC_LOW_THRESHOLD_0			 0x6013c
-/* [RW 11] The number of blocks guarantied for the LB port */
-#define BRB1_REG_LB_GUARANTIED					 0x601ec
-/* [RW 11] The hysteresis on the guarantied buffer space for the Lb port
- * before signaling XON. */
-#define BRB1_REG_LB_GUARANTIED_HYST				 0x60264
-/* [RW 24] LL RAM data. */
-#define BRB1_REG_LL_RAM						 0x61000
-/* [RW 10] The number of free blocks above which the Low_llfc signal to
-   interface #n is de-asserted. */
-#define BRB1_REG_LOW_LLFC_HIGH_THRESHOLD_0			 0x6016c
-/* [RW 10] The number of free blocks below which the Low_llfc signal to
-   interface #n is asserted. */
-#define BRB1_REG_LOW_LLFC_LOW_THRESHOLD_0			 0x6015c
-/* [RW 11] The number of blocks guarantied for class 0 in MAC 0. The
- * register is applicable only when per_class_guaranty_mode is set. */
-#define BRB1_REG_MAC_0_CLASS_0_GUARANTIED			 0x60244
-/* [RW 11] The hysteresis on the guarantied buffer space for class 0 in MAC
- * 1 before signaling XON. The register is applicable only when
- * per_class_guaranty_mode is set. */
-#define BRB1_REG_MAC_0_CLASS_0_GUARANTIED_HYST			 0x60254
-/* [RW 11] The number of blocks guarantied for class 1 in MAC 0. The
- * register is applicable only when per_class_guaranty_mode is set. */
-#define BRB1_REG_MAC_0_CLASS_1_GUARANTIED			 0x60248
-/* [RW 11] The hysteresis on the guarantied buffer space for class 1in MAC 0
- * before signaling XON. The register is applicable only when
- * per_class_guaranty_mode is set. */
-#define BRB1_REG_MAC_0_CLASS_1_GUARANTIED_HYST			 0x60258
-/* [RW 11] The number of blocks guarantied for class 0in MAC1.The register
- * is applicable only when per_class_guaranty_mode is set. */
-#define BRB1_REG_MAC_1_CLASS_0_GUARANTIED			 0x6024c
-/* [RW 11] The hysteresis on the guarantied buffer space for class 0 in MAC
- * 1 before signaling XON. The register is applicable only when
- * per_class_guaranty_mode is set. */
-#define BRB1_REG_MAC_1_CLASS_0_GUARANTIED_HYST			 0x6025c
-/* [RW 11] The number of blocks guarantied for class 1 in MAC 1. The
- * register is applicable only when per_class_guaranty_mode is set. */
-#define BRB1_REG_MAC_1_CLASS_1_GUARANTIED			 0x60250
-/* [RW 11] The hysteresis on the guarantied buffer space for class 1 in MAC
- * 1 before signaling XON. The register is applicable only when
- * per_class_guaranty_mode is set. */
-#define BRB1_REG_MAC_1_CLASS_1_GUARANTIED_HYST			 0x60260
-/* [RW 11] The number of blocks guarantied for the MAC port. The register is
- * applicable only when per_class_guaranty_mode is reset. */
-#define BRB1_REG_MAC_GUARANTIED_0				 0x601e8
-#define BRB1_REG_MAC_GUARANTIED_1				 0x60240
-/* [R 24] The number of full blocks. */
-#define BRB1_REG_NUM_OF_FULL_BLOCKS				 0x60090
-/* [ST 32] The number of cycles that the write_full signal towards MAC #0
-   was asserted. */
-#define BRB1_REG_NUM_OF_FULL_CYCLES_0				 0x600c8
-#define BRB1_REG_NUM_OF_FULL_CYCLES_1				 0x600cc
-#define BRB1_REG_NUM_OF_FULL_CYCLES_4				 0x600d8
-/* [ST 32] The number of cycles that the pause signal towards MAC #0 was
-   asserted. */
-#define BRB1_REG_NUM_OF_PAUSE_CYCLES_0				 0x600b8
-#define BRB1_REG_NUM_OF_PAUSE_CYCLES_1				 0x600bc
-/* [RW 10] The number of free blocks below which the pause signal to class 0
- * is asserted */
-#define BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0			 0x601c0
-#define BRB1_REG_PAUSE_0_XOFF_THRESHOLD_1			 0x60220
-/* [RW 11] The number of free blocks above which the pause signal to class 0
- * is de-asserted */
-#define BRB1_REG_PAUSE_0_XON_THRESHOLD_0			 0x601c4
-#define BRB1_REG_PAUSE_0_XON_THRESHOLD_1			 0x60224
-/* [RW 11] The number of free blocks below which the pause signal to class 1
- * is asserted */
-#define BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0			 0x601c8
-#define BRB1_REG_PAUSE_1_XOFF_THRESHOLD_1			 0x60228
-/* [RW 11] The number of free blocks above which the pause signal to class 1
- * is de-asserted */
-#define BRB1_REG_PAUSE_1_XON_THRESHOLD_0			 0x601cc
-#define BRB1_REG_PAUSE_1_XON_THRESHOLD_1			 0x6022c
-/* [RW 10] Write client 0: De-assert pause threshold. Not Functional */
-#define BRB1_REG_PAUSE_HIGH_THRESHOLD_0 			 0x60078
-#define BRB1_REG_PAUSE_HIGH_THRESHOLD_1 			 0x6007c
-/* [RW 10] Write client 0: Assert pause threshold. */
-#define BRB1_REG_PAUSE_LOW_THRESHOLD_0				 0x60068
-#define BRB1_REG_PAUSE_LOW_THRESHOLD_1				 0x6006c
-/* [R 24] The number of full blocks occupied by port. */
-#define BRB1_REG_PORT_NUM_OCC_BLOCKS_0				 0x60094
-/* [RW 1] Reset the design by software. */
-#define BRB1_REG_SOFT_RESET					 0x600dc
-/* [R 5] Used to read the value of the XX protection CAM occupancy counter. */
-#define CCM_REG_CAM_OCCUP					 0xd0188
-/* [RW 1] CM - CFC Interface enable. If 0 - the valid input is disregarded;
-   acknowledge output is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define CCM_REG_CCM_CFC_IFEN					 0xd003c
-/* [RW 1] CM - QM Interface enable. If 0 - the acknowledge input is
-   disregarded; valid is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define CCM_REG_CCM_CQM_IFEN					 0xd000c
-/* [RW 1] If set the Q index; received from the QM is inserted to event ID.
-   Otherwise 0 is inserted. */
-#define CCM_REG_CCM_CQM_USE_Q					 0xd00c0
-/* [RW 11] Interrupt mask register #0 read/write */
-#define CCM_REG_CCM_INT_MASK					 0xd01e4
-/* [R 11] Interrupt register #0 read */
-#define CCM_REG_CCM_INT_STS					 0xd01d8
-/* [RW 27] Parity mask register #0 read/write */
-#define CCM_REG_CCM_PRTY_MASK					 0xd01f4
-/* [R 27] Parity register #0 read */
-#define CCM_REG_CCM_PRTY_STS					 0xd01e8
-/* [RC 27] Parity register #0 read clear */
-#define CCM_REG_CCM_PRTY_STS_CLR				 0xd01ec
-/* [RW 3] The size of AG context region 0 in REG-pairs. Designates the MS
-   REG-pair number (e.g. if region 0 is 6 REG-pairs; the value should be 5).
-   Is used to determine the number of the AG context REG-pairs written back;
-   when the input message Reg1WbFlg isn't set. */
-#define CCM_REG_CCM_REG0_SZ					 0xd00c4
-/* [RW 1] CM - STORM 0 Interface enable. If 0 - the acknowledge input is
-   disregarded; valid is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define CCM_REG_CCM_STORM0_IFEN 				 0xd0004
-/* [RW 1] CM - STORM 1 Interface enable. If 0 - the acknowledge input is
-   disregarded; valid is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define CCM_REG_CCM_STORM1_IFEN 				 0xd0008
-/* [RW 1] CDU AG read Interface enable. If 0 - the request input is
-   disregarded; valid output is deasserted; all other signals are treated as
-   usual; if 1 - normal activity. */
-#define CCM_REG_CDU_AG_RD_IFEN					 0xd0030
-/* [RW 1] CDU AG write Interface enable. If 0 - the request and valid input
-   are disregarded; all other signals are treated as usual; if 1 - normal
-   activity. */
-#define CCM_REG_CDU_AG_WR_IFEN					 0xd002c
-/* [RW 1] CDU STORM read Interface enable. If 0 - the request input is
-   disregarded; valid output is deasserted; all other signals are treated as
-   usual; if 1 - normal activity. */
-#define CCM_REG_CDU_SM_RD_IFEN					 0xd0038
-/* [RW 1] CDU STORM write Interface enable. If 0 - the request and valid
-   input is disregarded; all other signals are treated as usual; if 1 -
-   normal activity. */
-#define CCM_REG_CDU_SM_WR_IFEN					 0xd0034
-/* [RW 4] CFC output initial credit. Max credit available - 15.Write writes
-   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] Auxiliary counter flag Q number 1. */
-#define CCM_REG_CNT_AUX1_Q					 0xd00c8
-/* [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
-/* [RW 28] The CM header value for QM request (secondary). */
-#define CCM_REG_CQM_CCM_HDR_S					 0xd0090
-/* [RW 1] QM - CM Interface enable. If 0 - the valid input is disregarded;
-   acknowledge output is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define CCM_REG_CQM_CCM_IFEN					 0xd0014
-/* [RW 6] QM output initial credit. Max credit available - 32. Write writes
-   the initial credit value; read returns the current value of the credit
-   counter. Must be initialized to 32 at start-up. */
-#define CCM_REG_CQM_INIT_CRD					 0xd020c
-/* [RW 3] The weight of the QM (primary) input in the WRR mechanism. 0
-   stands for weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define CCM_REG_CQM_P_WEIGHT					 0xd00b8
-/* [RW 3] The weight of the QM (secondary) input in the WRR mechanism. 0
-   stands for weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define CCM_REG_CQM_S_WEIGHT					 0xd00bc
-/* [RW 1] Input SDM Interface enable. If 0 - the valid input is disregarded;
-   acknowledge output is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define CCM_REG_CSDM_IFEN					 0xd0018
-/* [RC 1] Set when the message length mismatch (relative to last indication)
-   at the SDM interface is detected. */
-#define CCM_REG_CSDM_LENGTH_MIS 				 0xd0170
-/* [RW 3] The weight of the SDM input in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define CCM_REG_CSDM_WEIGHT					 0xd00b4
-/* [RW 28] The CM header for QM formatting in case of an error in the QM
-   inputs. */
-#define CCM_REG_ERR_CCM_HDR					 0xd0094
-/* [RW 8] The Event ID in case the input message ErrorFlg is set. */
-#define CCM_REG_ERR_EVNT_ID					 0xd0098
-/* [RW 8] FIC0 output initial credit. Max credit available - 255. Write
-   writes the initial credit value; read returns the current value of the
-   credit counter. Must be initialized to 64 at start-up. */
-#define CCM_REG_FIC0_INIT_CRD					 0xd0210
-/* [RW 8] FIC1 output initial credit. Max credit available - 255.Write
-   writes the initial credit value; read returns the current value of the
-   credit counter. Must be initialized to 64 at start-up. */
-#define CCM_REG_FIC1_INIT_CRD					 0xd0214
-/* [RW 1] Arbitration between Input Arbiter groups: 0 - fair Round-Robin; 1
-   - strict priority defined by ~ccm_registers_gr_ag_pr.gr_ag_pr;
-   ~ccm_registers_gr_ld0_pr.gr_ld0_pr and
-   ~ccm_registers_gr_ld1_pr.gr_ld1_pr. Groups are according to channels and
-   outputs to STORM: aggregation; load FIC0; load FIC1 and store. */
-#define CCM_REG_GR_ARB_TYPE					 0xd015c
-/* [RW 2] Load (FIC0) channel group priority. The lowest priority is 0; the
-   highest priority is 3. It is supposed; that the Store channel priority is
-   the compliment to 4 of the rest priorities - Aggregation channel; Load
-   (FIC0) channel and Load (FIC1). */
-#define CCM_REG_GR_LD0_PR					 0xd0164
-/* [RW 2] Load (FIC1) channel group priority. The lowest priority is 0; the
-   highest priority is 3. It is supposed; that the Store channel priority is
-   the compliment to 4 of the rest priorities - Aggregation channel; Load
-   (FIC0) channel and Load (FIC1). */
-#define CCM_REG_GR_LD1_PR					 0xd0168
-/* [RW 2] General flags index. */
-#define CCM_REG_INV_DONE_Q					 0xd0108
-/* [RW 4] The number of double REG-pairs(128 bits); loaded from the STORM
-   context and sent to STORM; for a specific connection type. The double
-   REG-pairs are used in order to align to STORM context row size of 128
-   bits. The offset of these data in the STORM context is always 0. Index
-   _(0..15) stands for the connection type (one of 16). */
-#define CCM_REG_N_SM_CTX_LD_0					 0xd004c
-#define CCM_REG_N_SM_CTX_LD_1					 0xd0050
-#define CCM_REG_N_SM_CTX_LD_2					 0xd0054
-#define CCM_REG_N_SM_CTX_LD_3					 0xd0058
-#define CCM_REG_N_SM_CTX_LD_4					 0xd005c
-/* [RW 1] Input pbf Interface enable. If 0 - the valid input is disregarded;
-   acknowledge output is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define CCM_REG_PBF_IFEN					 0xd0028
-/* [RC 1] Set when the message length mismatch (relative to last indication)
-   at the pbf interface is detected. */
-#define CCM_REG_PBF_LENGTH_MIS					 0xd0180
-/* [RW 3] The weight of the input pbf in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define CCM_REG_PBF_WEIGHT					 0xd00ac
-#define CCM_REG_PHYS_QNUM1_0					 0xd0134
-#define CCM_REG_PHYS_QNUM1_1					 0xd0138
-#define CCM_REG_PHYS_QNUM2_0					 0xd013c
-#define CCM_REG_PHYS_QNUM2_1					 0xd0140
-#define CCM_REG_PHYS_QNUM3_0					 0xd0144
-#define CCM_REG_PHYS_QNUM3_1					 0xd0148
-#define CCM_REG_QOS_PHYS_QNUM0_0				 0xd0114
-#define CCM_REG_QOS_PHYS_QNUM0_1				 0xd0118
-#define CCM_REG_QOS_PHYS_QNUM1_0				 0xd011c
-#define CCM_REG_QOS_PHYS_QNUM1_1				 0xd0120
-#define CCM_REG_QOS_PHYS_QNUM2_0				 0xd0124
-#define CCM_REG_QOS_PHYS_QNUM2_1				 0xd0128
-#define CCM_REG_QOS_PHYS_QNUM3_0				 0xd012c
-#define CCM_REG_QOS_PHYS_QNUM3_1				 0xd0130
-/* [RW 1] STORM - CM Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define CCM_REG_STORM_CCM_IFEN					 0xd0010
-/* [RC 1] Set when the message length mismatch (relative to last indication)
-   at the STORM interface is detected. */
-#define CCM_REG_STORM_LENGTH_MIS				 0xd016c
-/* [RW 3] The weight of the STORM input in the WRR (Weighted Round robin)
-   mechanism. 0 stands for weight 8 (the most prioritised); 1 stands for
-   weight 1(least prioritised); 2 stands for weight 2 (more prioritised);
-   tc. */
-#define CCM_REG_STORM_WEIGHT					 0xd009c
-/* [RW 1] Input tsem Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define CCM_REG_TSEM_IFEN					 0xd001c
-/* [RC 1] Set when the message length mismatch (relative to last indication)
-   at the tsem interface is detected. */
-#define CCM_REG_TSEM_LENGTH_MIS 				 0xd0174
-/* [RW 3] The weight of the input tsem in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define CCM_REG_TSEM_WEIGHT					 0xd00a0
-/* [RW 1] Input usem Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define CCM_REG_USEM_IFEN					 0xd0024
-/* [RC 1] Set when message length mismatch (relative to last indication) at
-   the usem interface is detected. */
-#define CCM_REG_USEM_LENGTH_MIS 				 0xd017c
-/* [RW 3] The weight of the input usem in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define CCM_REG_USEM_WEIGHT					 0xd00a8
-/* [RW 1] Input xsem Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define CCM_REG_XSEM_IFEN					 0xd0020
-/* [RC 1] Set when the message length mismatch (relative to last indication)
-   at the xsem interface is detected. */
-#define CCM_REG_XSEM_LENGTH_MIS 				 0xd0178
-/* [RW 3] The weight of the input xsem in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define CCM_REG_XSEM_WEIGHT					 0xd00a4
-/* [RW 19] Indirect access to the descriptor table of the XX protection
-   mechanism. The fields are: [5:0] - message length; [12:6] - message
-   pointer; 18:13] - next pointer. */
-#define CCM_REG_XX_DESCR_TABLE					 0xd0300
-#define CCM_REG_XX_DESCR_TABLE_SIZE				 24
-/* [R 7] Used to read the value of XX protection Free counter. */
-#define CCM_REG_XX_FREE 					 0xd0184
-/* [RW 6] Initial value for the credit counter; responsible for fulfilling
-   of the Input Stage XX protection buffer by the XX protection pending
-   messages. Max credit available - 127. Write writes the initial credit
-   value; read returns the current value of the credit counter. Must be
-   initialized to maximum XX protected message size - 2 at start-up. */
-#define CCM_REG_XX_INIT_CRD					 0xd0220
-/* [RW 7] The maximum number of pending messages; which may be stored in XX
-   protection. At read the ~ccm_registers_xx_free.xx_free counter is read.
-   At write comprises the start value of the ~ccm_registers_xx_free.xx_free
-   counter. */
-#define CCM_REG_XX_MSG_NUM					 0xd0224
-/* [RW 8] The Event ID; sent to the STORM in case of XX overflow. */
-#define CCM_REG_XX_OVFL_EVNT_ID 				 0xd0044
-/* [RW 18] Indirect access to the XX table of the XX protection mechanism.
-   The fields are: [5:0] - tail pointer; 11:6] - Link List size; 17:12] -
-   header pointer. */
-#define CCM_REG_XX_TABLE					 0xd0280
-#define CDU_REG_CDU_CHK_MASK0					 0x101000
-#define CDU_REG_CDU_CHK_MASK1					 0x101004
-#define CDU_REG_CDU_CONTROL0					 0x101008
-#define CDU_REG_CDU_DEBUG					 0x101010
-#define CDU_REG_CDU_GLOBAL_PARAMS				 0x101020
-/* [RW 7] Interrupt mask register #0 read/write */
-#define CDU_REG_CDU_INT_MASK					 0x10103c
-/* [R 7] Interrupt register #0 read */
-#define CDU_REG_CDU_INT_STS					 0x101030
-/* [RW 5] Parity mask register #0 read/write */
-#define CDU_REG_CDU_PRTY_MASK					 0x10104c
-/* [R 5] Parity register #0 read */
-#define CDU_REG_CDU_PRTY_STS					 0x101040
-/* [RC 5] Parity register #0 read clear */
-#define CDU_REG_CDU_PRTY_STS_CLR				 0x101044
-/* [RC 32] logging of error data in case of a CDU load error:
-   {expected_cid[15:0]; xpected_type[2:0]; xpected_region[2:0]; ctive_error;
-   ype_error; ctual_active; ctual_compressed_context}; */
-#define CDU_REG_ERROR_DATA					 0x101014
-/* [WB 216] L1TT ram access. each entry has the following format :
-   {mrege_regions[7:0]; ffset12[5:0]...offset0[5:0];
-   ength12[5:0]...length0[5:0]; d12[3:0]...id0[3:0]} */
-#define CDU_REG_L1TT						 0x101800
-/* [WB 24] MATT ram access. each entry has the following
-   format:{RegionLength[11:0]; egionOffset[11:0]} */
-#define CDU_REG_MATT						 0x101100
-/* [RW 1] when this bit is set the CDU operates in e1hmf mode */
-#define CDU_REG_MF_MODE 					 0x101050
-/* [R 1] indication the initializing the activity counter by the hardware
-   was done. */
-#define CFC_REG_AC_INIT_DONE					 0x104078
-/* [RW 13] activity counter ram access */
-#define CFC_REG_ACTIVITY_COUNTER				 0x104400
-#define CFC_REG_ACTIVITY_COUNTER_SIZE				 256
-/* [R 1] indication the initializing the cams by the hardware was done. */
-#define CFC_REG_CAM_INIT_DONE					 0x10407c
-/* [RW 2] Interrupt mask register #0 read/write */
-#define CFC_REG_CFC_INT_MASK					 0x104108
-/* [R 2] Interrupt register #0 read */
-#define CFC_REG_CFC_INT_STS					 0x1040fc
-/* [RC 2] Interrupt register #0 read clear */
-#define CFC_REG_CFC_INT_STS_CLR 				 0x104100
-/* [RW 4] Parity mask register #0 read/write */
-#define CFC_REG_CFC_PRTY_MASK					 0x104118
-/* [R 4] Parity register #0 read */
-#define CFC_REG_CFC_PRTY_STS					 0x10410c
-/* [RC 4] Parity register #0 read clear */
-#define CFC_REG_CFC_PRTY_STS_CLR				 0x104110
-/* [RW 21] CID cam access (21:1 - Data; alid - 0) */
-#define CFC_REG_CID_CAM 					 0x104800
-#define CFC_REG_CONTROL0					 0x104028
-#define CFC_REG_DEBUG0						 0x104050
-/* [RW 14] indicates per error (in #cfc_registers_cfc_error_vector.cfc_error
-   vector) whether the cfc should be disabled upon it */
-#define CFC_REG_DISABLE_ON_ERROR				 0x104044
-/* [RC 14] CFC error vector. when the CFC detects an internal error it will
-   set one of these bits. the bit description can be found in CFC
-   specifications */
-#define CFC_REG_ERROR_VECTOR					 0x10403c
-/* [WB 93] LCID info ram access */
-#define CFC_REG_INFO_RAM					 0x105000
-#define CFC_REG_INFO_RAM_SIZE					 1024
-#define CFC_REG_INIT_REG					 0x10404c
-#define CFC_REG_INTERFACES					 0x104058
-/* [RW 24] {weight_load_client7[2:0] to weight_load_client0[2:0]}. this
-   field allows changing the priorities of the weighted-round-robin arbiter
-   which selects which CFC load client should be served next */
-#define CFC_REG_LCREQ_WEIGHTS					 0x104084
-/* [RW 16] Link List ram access; data = {prev_lcid; ext_lcid} */
-#define CFC_REG_LINK_LIST					 0x104c00
-#define CFC_REG_LINK_LIST_SIZE					 256
-/* [R 1] indication the initializing the link list by the hardware was done. */
-#define CFC_REG_LL_INIT_DONE					 0x104074
-/* [R 9] Number of allocated LCIDs which are at empty state */
-#define CFC_REG_NUM_LCIDS_ALLOC 				 0x104020
-/* [R 9] Number of Arriving LCIDs in Link List Block */
-#define CFC_REG_NUM_LCIDS_ARRIVING				 0x104004
-#define CFC_REG_NUM_LCIDS_INSIDE_PF				 0x104120
-/* [R 9] Number of Leaving LCIDs in Link List Block */
-#define CFC_REG_NUM_LCIDS_LEAVING				 0x104018
-#define CFC_REG_WEAK_ENABLE_PF					 0x104124
-/* [RW 8] The event id for aggregated interrupt 0 */
-#define CSDM_REG_AGG_INT_EVENT_0				 0xc2038
-#define CSDM_REG_AGG_INT_EVENT_10				 0xc2060
-#define CSDM_REG_AGG_INT_EVENT_11				 0xc2064
-#define CSDM_REG_AGG_INT_EVENT_12				 0xc2068
-#define CSDM_REG_AGG_INT_EVENT_13				 0xc206c
-#define CSDM_REG_AGG_INT_EVENT_14				 0xc2070
-#define CSDM_REG_AGG_INT_EVENT_15				 0xc2074
-#define CSDM_REG_AGG_INT_EVENT_16				 0xc2078
-#define CSDM_REG_AGG_INT_EVENT_2				 0xc2040
-#define CSDM_REG_AGG_INT_EVENT_3				 0xc2044
-#define CSDM_REG_AGG_INT_EVENT_4				 0xc2048
-#define CSDM_REG_AGG_INT_EVENT_5				 0xc204c
-#define CSDM_REG_AGG_INT_EVENT_6				 0xc2050
-#define CSDM_REG_AGG_INT_EVENT_7				 0xc2054
-#define CSDM_REG_AGG_INT_EVENT_8				 0xc2058
-#define CSDM_REG_AGG_INT_EVENT_9				 0xc205c
-/* [RW 1] For each aggregated interrupt index whether the mode is normal (0)
-   or auto-mask-mode (1) */
-#define CSDM_REG_AGG_INT_MODE_10				 0xc21e0
-#define CSDM_REG_AGG_INT_MODE_11				 0xc21e4
-#define CSDM_REG_AGG_INT_MODE_12				 0xc21e8
-#define CSDM_REG_AGG_INT_MODE_13				 0xc21ec
-#define CSDM_REG_AGG_INT_MODE_14				 0xc21f0
-#define CSDM_REG_AGG_INT_MODE_15				 0xc21f4
-#define CSDM_REG_AGG_INT_MODE_16				 0xc21f8
-#define CSDM_REG_AGG_INT_MODE_6 				 0xc21d0
-#define CSDM_REG_AGG_INT_MODE_7 				 0xc21d4
-#define CSDM_REG_AGG_INT_MODE_8 				 0xc21d8
-#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 completion counter #0 */
-#define CSDM_REG_CMP_COUNTER_MAX0				 0xc201c
-/* [RW 16] The maximum value of the completion counter #1 */
-#define CSDM_REG_CMP_COUNTER_MAX1				 0xc2020
-/* [RW 16] The maximum value of the completion counter #2 */
-#define CSDM_REG_CMP_COUNTER_MAX2				 0xc2024
-/* [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. */
-#define CSDM_REG_CMP_COUNTER_START_ADDR 			 0xc200c
-/* [RW 32] Interrupt mask register #0 read/write */
-#define CSDM_REG_CSDM_INT_MASK_0				 0xc229c
-#define CSDM_REG_CSDM_INT_MASK_1				 0xc22ac
-/* [R 32] Interrupt register #0 read */
-#define CSDM_REG_CSDM_INT_STS_0 				 0xc2290
-#define CSDM_REG_CSDM_INT_STS_1 				 0xc22a0
-/* [RW 11] Parity mask register #0 read/write */
-#define CSDM_REG_CSDM_PRTY_MASK 				 0xc22bc
-/* [R 11] Parity register #0 read */
-#define CSDM_REG_CSDM_PRTY_STS					 0xc22b0
-/* [RC 11] Parity register #0 read clear */
-#define CSDM_REG_CSDM_PRTY_STS_CLR				 0xc22b4
-#define CSDM_REG_ENABLE_IN1					 0xc2238
-#define CSDM_REG_ENABLE_IN2					 0xc223c
-#define CSDM_REG_ENABLE_OUT1					 0xc2240
-#define CSDM_REG_ENABLE_OUT2					 0xc2244
-/* [RW 4] The initial number of messages that can be sent to the pxp control
-   interface without receiving any ACK. */
-#define CSDM_REG_INIT_CREDIT_PXP_CTRL				 0xc24bc
-/* [ST 32] The number of ACK after placement messages received */
-#define CSDM_REG_NUM_OF_ACK_AFTER_PLACE 			 0xc227c
-/* [ST 32] The number of packet end messages received from the parser */
-#define CSDM_REG_NUM_OF_PKT_END_MSG				 0xc2274
-/* [ST 32] The number of requests received from the pxp async if */
-#define CSDM_REG_NUM_OF_PXP_ASYNC_REQ				 0xc2278
-/* [ST 32] The number of commands received in queue 0 */
-#define CSDM_REG_NUM_OF_Q0_CMD					 0xc2248
-/* [ST 32] The number of commands received in queue 10 */
-#define CSDM_REG_NUM_OF_Q10_CMD 				 0xc226c
-/* [ST 32] The number of commands received in queue 11 */
-#define CSDM_REG_NUM_OF_Q11_CMD 				 0xc2270
-/* [ST 32] The number of commands received in queue 1 */
-#define CSDM_REG_NUM_OF_Q1_CMD					 0xc224c
-/* [ST 32] The number of commands received in queue 3 */
-#define CSDM_REG_NUM_OF_Q3_CMD					 0xc2250
-/* [ST 32] The number of commands received in queue 4 */
-#define CSDM_REG_NUM_OF_Q4_CMD					 0xc2254
-/* [ST 32] The number of commands received in queue 5 */
-#define CSDM_REG_NUM_OF_Q5_CMD					 0xc2258
-/* [ST 32] The number of commands received in queue 6 */
-#define CSDM_REG_NUM_OF_Q6_CMD					 0xc225c
-/* [ST 32] The number of commands received in queue 7 */
-#define CSDM_REG_NUM_OF_Q7_CMD					 0xc2260
-/* [ST 32] The number of commands received in queue 8 */
-#define CSDM_REG_NUM_OF_Q8_CMD					 0xc2264
-/* [ST 32] The number of commands received in queue 9 */
-#define CSDM_REG_NUM_OF_Q9_CMD					 0xc2268
-/* [RW 13] The start address in the internal RAM for queue counters */
-#define CSDM_REG_Q_COUNTER_START_ADDR				 0xc2010
-/* [R 1] pxp_ctrl rd_data fifo empty in sdm_dma_rsp block */
-#define CSDM_REG_RSP_PXP_CTRL_RDATA_EMPTY			 0xc2548
-/* [R 1] parser fifo empty in sdm_sync block */
-#define CSDM_REG_SYNC_PARSER_EMPTY				 0xc2550
-/* [R 1] parser serial fifo empty in sdm_sync block */
-#define CSDM_REG_SYNC_SYNC_EMPTY				 0xc2558
-/* [RW 32] Tick for timer counter. Applicable only when
-   ~csdm_registers_timer_tick_enable.timer_tick_enable =1 */
-#define CSDM_REG_TIMER_TICK					 0xc2000
-/* [RW 5] The number of time_slots in the arbitration cycle */
-#define CSEM_REG_ARB_CYCLE_SIZE 				 0x200034
-/* [RW 3] The source that is associated with arbitration element 0. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2 */
-#define CSEM_REG_ARB_ELEMENT0					 0x200020
-/* [RW 3] The source that is associated with arbitration element 1. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2.
-   Could not be equal to register ~csem_registers_arb_element0.arb_element0 */
-#define CSEM_REG_ARB_ELEMENT1					 0x200024
-/* [RW 3] The source that is associated with arbitration element 2. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2.
-   Could not be equal to register ~csem_registers_arb_element0.arb_element0
-   and ~csem_registers_arb_element1.arb_element1 */
-#define CSEM_REG_ARB_ELEMENT2					 0x200028
-/* [RW 3] The source that is associated with arbitration element 3. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2.Could
-   not be equal to register ~csem_registers_arb_element0.arb_element0 and
-   ~csem_registers_arb_element1.arb_element1 and
-   ~csem_registers_arb_element2.arb_element2 */
-#define CSEM_REG_ARB_ELEMENT3					 0x20002c
-/* [RW 3] The source that is associated with arbitration element 4. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2.
-   Could not be equal to register ~csem_registers_arb_element0.arb_element0
-   and ~csem_registers_arb_element1.arb_element1 and
-   ~csem_registers_arb_element2.arb_element2 and
-   ~csem_registers_arb_element3.arb_element3 */
-#define CSEM_REG_ARB_ELEMENT4					 0x200030
-/* [RW 32] Interrupt mask register #0 read/write */
-#define CSEM_REG_CSEM_INT_MASK_0				 0x200110
-#define CSEM_REG_CSEM_INT_MASK_1				 0x200120
-/* [R 32] Interrupt register #0 read */
-#define CSEM_REG_CSEM_INT_STS_0 				 0x200104
-#define CSEM_REG_CSEM_INT_STS_1 				 0x200114
-/* [RW 32] Parity mask register #0 read/write */
-#define CSEM_REG_CSEM_PRTY_MASK_0				 0x200130
-#define CSEM_REG_CSEM_PRTY_MASK_1				 0x200140
-/* [R 32] Parity register #0 read */
-#define CSEM_REG_CSEM_PRTY_STS_0				 0x200124
-#define CSEM_REG_CSEM_PRTY_STS_1				 0x200134
-/* [RC 32] Parity register #0 read clear */
-#define CSEM_REG_CSEM_PRTY_STS_CLR_0				 0x200128
-#define CSEM_REG_CSEM_PRTY_STS_CLR_1				 0x200138
-#define CSEM_REG_ENABLE_IN					 0x2000a4
-#define CSEM_REG_ENABLE_OUT					 0x2000a8
-/* [RW 32] This address space contains all registers and memories that are
-   placed in SEM_FAST block. The SEM_FAST registers are described in
-   appendix B. In order to access the sem_fast registers the base address
-   ~fast_memory.fast_memory should be added to eachsem_fast register offset. */
-#define CSEM_REG_FAST_MEMORY					 0x220000
-/* [RW 1] Disables input messages from FIC0 May be updated during run_time
-   by the microcode */
-#define CSEM_REG_FIC0_DISABLE					 0x200224
-/* [RW 1] Disables input messages from FIC1 May be updated during run_time
-   by the microcode */
-#define CSEM_REG_FIC1_DISABLE					 0x200234
-/* [RW 15] Interrupt table Read and write access to it is not possible in
-   the middle of the work */
-#define CSEM_REG_INT_TABLE					 0x200400
-/* [ST 24] Statistics register. The number of messages that entered through
-   FIC0 */
-#define CSEM_REG_MSG_NUM_FIC0					 0x200000
-/* [ST 24] Statistics register. The number of messages that entered through
-   FIC1 */
-#define CSEM_REG_MSG_NUM_FIC1					 0x200004
-/* [ST 24] Statistics register. The number of messages that were sent to
-   FOC0 */
-#define CSEM_REG_MSG_NUM_FOC0					 0x200008
-/* [ST 24] Statistics register. The number of messages that were sent to
-   FOC1 */
-#define CSEM_REG_MSG_NUM_FOC1					 0x20000c
-/* [ST 24] Statistics register. The number of messages that were sent to
-   FOC2 */
-#define CSEM_REG_MSG_NUM_FOC2					 0x200010
-/* [ST 24] Statistics register. The number of messages that were sent to
-   FOC3 */
-#define CSEM_REG_MSG_NUM_FOC3					 0x200014
-/* [RW 1] Disables input messages from the passive buffer May be updated
-   during run_time by the microcode */
-#define CSEM_REG_PAS_DISABLE					 0x20024c
-/* [WB 128] Debug only. Passive buffer memory */
-#define CSEM_REG_PASSIVE_BUFFER 				 0x202000
-/* [WB 46] pram memory. B45 is parity; b[44:0] - data. */
-#define CSEM_REG_PRAM						 0x240000
-/* [R 16] Valid sleeping threads indication have bit per thread */
-#define CSEM_REG_SLEEP_THREADS_VALID				 0x20026c
-/* [R 1] EXT_STORE FIFO is empty in sem_slow_ls_ext */
-#define CSEM_REG_SLOW_EXT_STORE_EMPTY				 0x2002a0
-/* [RW 16] List of free threads . There is a bit per thread. */
-#define CSEM_REG_THREADS_LIST					 0x2002e4
-/* [RW 3] The arbitration scheme of time_slot 0 */
-#define CSEM_REG_TS_0_AS					 0x200038
-/* [RW 3] The arbitration scheme of time_slot 10 */
-#define CSEM_REG_TS_10_AS					 0x200060
-/* [RW 3] The arbitration scheme of time_slot 11 */
-#define CSEM_REG_TS_11_AS					 0x200064
-/* [RW 3] The arbitration scheme of time_slot 12 */
-#define CSEM_REG_TS_12_AS					 0x200068
-/* [RW 3] The arbitration scheme of time_slot 13 */
-#define CSEM_REG_TS_13_AS					 0x20006c
-/* [RW 3] The arbitration scheme of time_slot 14 */
-#define CSEM_REG_TS_14_AS					 0x200070
-/* [RW 3] The arbitration scheme of time_slot 15 */
-#define CSEM_REG_TS_15_AS					 0x200074
-/* [RW 3] The arbitration scheme of time_slot 16 */
-#define CSEM_REG_TS_16_AS					 0x200078
-/* [RW 3] The arbitration scheme of time_slot 17 */
-#define CSEM_REG_TS_17_AS					 0x20007c
-/* [RW 3] The arbitration scheme of time_slot 18 */
-#define CSEM_REG_TS_18_AS					 0x200080
-/* [RW 3] The arbitration scheme of time_slot 1 */
-#define CSEM_REG_TS_1_AS					 0x20003c
-/* [RW 3] The arbitration scheme of time_slot 2 */
-#define CSEM_REG_TS_2_AS					 0x200040
-/* [RW 3] The arbitration scheme of time_slot 3 */
-#define CSEM_REG_TS_3_AS					 0x200044
-/* [RW 3] The arbitration scheme of time_slot 4 */
-#define CSEM_REG_TS_4_AS					 0x200048
-/* [RW 3] The arbitration scheme of time_slot 5 */
-#define CSEM_REG_TS_5_AS					 0x20004c
-/* [RW 3] The arbitration scheme of time_slot 6 */
-#define CSEM_REG_TS_6_AS					 0x200050
-/* [RW 3] The arbitration scheme of time_slot 7 */
-#define CSEM_REG_TS_7_AS					 0x200054
-/* [RW 3] The arbitration scheme of time_slot 8 */
-#define CSEM_REG_TS_8_AS					 0x200058
-/* [RW 3] The arbitration scheme of time_slot 9 */
-#define CSEM_REG_TS_9_AS					 0x20005c
-/* [W 7] VF or PF ID for reset error bit. Values 0-63 reset error bit for 64
- * VF; values 64-67 reset error for 4 PF; values 68-127 are not valid. */
-#define CSEM_REG_VFPF_ERR_NUM					 0x200380
-/* [RW 1] Parity mask register #0 read/write */
-#define DBG_REG_DBG_PRTY_MASK					 0xc0a8
-/* [R 1] Parity register #0 read */
-#define DBG_REG_DBG_PRTY_STS					 0xc09c
-/* [RC 1] Parity register #0 read clear */
-#define DBG_REG_DBG_PRTY_STS_CLR				 0xc0a0
-/* [RW 1] When set the DMAE will process the commands as in E1.5. 1.The
- * function that is used is always SRC-PCI; 2.VF_Valid = 0; 3.VFID=0;
- * 4.Completion function=0; 5.Error handling=0 */
-#define DMAE_REG_BACKWARD_COMP_EN				 0x10207c
-/* [RW 32] Commands memory. The address to command X; row Y is to calculated
-   as 14*X+Y. */
-#define DMAE_REG_CMD_MEM					 0x102400
-#define DMAE_REG_CMD_MEM_SIZE					 224
-/* [RW 1] If 0 - the CRC-16c initial value is all zeroes; if 1 - the CRC-16c
-   initial value is all ones. */
-#define DMAE_REG_CRC16C_INIT					 0x10201c
-/* [RW 1] If 0 - the CRC-16 T10 initial value is all zeroes; if 1 - the
-   CRC-16 T10 initial value is all ones. */
-#define DMAE_REG_CRC16T10_INIT					 0x102020
-/* [RW 2] Interrupt mask register #0 read/write */
-#define DMAE_REG_DMAE_INT_MASK					 0x102054
-/* [RW 4] Parity mask register #0 read/write */
-#define DMAE_REG_DMAE_PRTY_MASK 				 0x102064
-/* [R 4] Parity register #0 read */
-#define DMAE_REG_DMAE_PRTY_STS					 0x102058
-/* [RC 4] Parity register #0 read clear */
-#define DMAE_REG_DMAE_PRTY_STS_CLR				 0x10205c
-/* [RW 1] Command 0 go. */
-#define DMAE_REG_GO_C0						 0x102080
-/* [RW 1] Command 1 go. */
-#define DMAE_REG_GO_C1						 0x102084
-/* [RW 1] Command 10 go. */
-#define DMAE_REG_GO_C10 					 0x102088
-/* [RW 1] Command 11 go. */
-#define DMAE_REG_GO_C11 					 0x10208c
-/* [RW 1] Command 12 go. */
-#define DMAE_REG_GO_C12 					 0x102090
-/* [RW 1] Command 13 go. */
-#define DMAE_REG_GO_C13 					 0x102094
-/* [RW 1] Command 14 go. */
-#define DMAE_REG_GO_C14 					 0x102098
-/* [RW 1] Command 15 go. */
-#define DMAE_REG_GO_C15 					 0x10209c
-/* [RW 1] Command 2 go. */
-#define DMAE_REG_GO_C2						 0x1020a0
-/* [RW 1] Command 3 go. */
-#define DMAE_REG_GO_C3						 0x1020a4
-/* [RW 1] Command 4 go. */
-#define DMAE_REG_GO_C4						 0x1020a8
-/* [RW 1] Command 5 go. */
-#define DMAE_REG_GO_C5						 0x1020ac
-/* [RW 1] Command 6 go. */
-#define DMAE_REG_GO_C6						 0x1020b0
-/* [RW 1] Command 7 go. */
-#define DMAE_REG_GO_C7						 0x1020b4
-/* [RW 1] Command 8 go. */
-#define DMAE_REG_GO_C8						 0x1020b8
-/* [RW 1] Command 9 go. */
-#define DMAE_REG_GO_C9						 0x1020bc
-/* [RW 1] DMAE GRC Interface (Target; aster) enable. If 0 - the acknowledge
-   input is disregarded; valid is deasserted; all other signals are treated
-   as usual; if 1 - normal activity. */
-#define DMAE_REG_GRC_IFEN					 0x102008
-/* [RW 1] DMAE PCI Interface (Request; ead; rite) enable. If 0 - the
-   acknowledge input is disregarded; valid is deasserted; full is asserted;
-   all other signals are treated as usual; if 1 - normal activity. */
-#define DMAE_REG_PCI_IFEN					 0x102004
-/* [RW 4] DMAE- PCI Request Interface initial credit. Write writes the
-   initial value to the credit counter; related to the address. Read returns
-   the current value of the counter. */
-#define DMAE_REG_PXP_REQ_INIT_CRD				 0x1020c0
-/* [RW 8] Aggregation command. */
-#define DORQ_REG_AGG_CMD0					 0x170060
-/* [RW 8] Aggregation command. */
-#define DORQ_REG_AGG_CMD1					 0x170064
-/* [RW 8] Aggregation command. */
-#define DORQ_REG_AGG_CMD2					 0x170068
-/* [RW 8] Aggregation command. */
-#define DORQ_REG_AGG_CMD3					 0x17006c
-/* [RW 28] UCM Header. */
-#define DORQ_REG_CMHEAD_RX					 0x170050
-/* [RW 32] Doorbell address for RBC doorbells (function 0). */
-#define DORQ_REG_DB_ADDR0					 0x17008c
-/* [RW 5] Interrupt mask register #0 read/write */
-#define DORQ_REG_DORQ_INT_MASK					 0x170180
-/* [R 5] Interrupt register #0 read */
-#define DORQ_REG_DORQ_INT_STS					 0x170174
-/* [RC 5] Interrupt register #0 read clear */
-#define DORQ_REG_DORQ_INT_STS_CLR				 0x170178
-/* [RW 2] Parity mask register #0 read/write */
-#define DORQ_REG_DORQ_PRTY_MASK 				 0x170190
-/* [R 2] Parity register #0 read */
-#define DORQ_REG_DORQ_PRTY_STS					 0x170184
-/* [RC 2] Parity register #0 read clear */
-#define DORQ_REG_DORQ_PRTY_STS_CLR				 0x170188
-/* [RW 8] The address to write the DPM CID to STORM. */
-#define DORQ_REG_DPM_CID_ADDR					 0x170044
-/* [RW 5] The DPM mode CID extraction offset. */
-#define DORQ_REG_DPM_CID_OFST					 0x170030
-/* [RW 12] The threshold of the DQ FIFO to send the almost full interrupt. */
-#define DORQ_REG_DQ_FIFO_AFULL_TH				 0x17007c
-/* [RW 12] The threshold of the DQ FIFO to send the full interrupt. */
-#define DORQ_REG_DQ_FIFO_FULL_TH				 0x170078
-/* [R 13] Current value of the DQ FIFO fill level according to following
-   pointer. The range is 0 - 256 FIFO rows; where each row stands for the
-   doorbell. */
-#define DORQ_REG_DQ_FILL_LVLF					 0x1700a4
-/* [R 1] DQ FIFO full status. Is set; when FIFO filling level is more or
-   equal to full threshold; reset on full clear. */
-#define DORQ_REG_DQ_FULL_ST					 0x1700c0
-/* [RW 28] The value sent to CM header in the case of CFC load error. */
-#define DORQ_REG_ERR_CMHEAD					 0x170058
-#define DORQ_REG_IF_EN						 0x170004
-#define DORQ_REG_MODE_ACT					 0x170008
-/* [RW 5] The normal mode CID extraction offset. */
-#define DORQ_REG_NORM_CID_OFST					 0x17002c
-/* [RW 28] TCM Header when only TCP context is loaded. */
-#define DORQ_REG_NORM_CMHEAD_TX 				 0x17004c
-/* [RW 3] The number of simultaneous outstanding requests to Context Fetch
-   Interface. */
-#define DORQ_REG_OUTST_REQ					 0x17003c
-#define DORQ_REG_PF_USAGE_CNT					 0x1701d0
-#define DORQ_REG_REGN						 0x170038
-/* [R 4] Current value of response A counter credit. Initial credit is
-   configured through write to ~dorq_registers_rsp_init_crd.rsp_init_crd
-   register. */
-#define DORQ_REG_RSPA_CRD_CNT					 0x1700ac
-/* [R 4] Current value of response B counter credit. Initial credit is
-   configured through write to ~dorq_registers_rsp_init_crd.rsp_init_crd
-   register. */
-#define DORQ_REG_RSPB_CRD_CNT					 0x1700b0
-/* [RW 4] The initial credit at the Doorbell Response Interface. The write
-   writes the same initial credit to the rspa_crd_cnt and rspb_crd_cnt. The
-   read reads this written value. */
-#define DORQ_REG_RSP_INIT_CRD					 0x170048
-/* [RW 4] Initial activity counter value on the load request; when the
-   shortcut is done. */
-#define DORQ_REG_SHRT_ACT_CNT					 0x170070
-/* [RW 28] TCM Header when both ULP and TCP context is loaded. */
-#define DORQ_REG_SHRT_CMHEAD					 0x170054
-#define HC_CONFIG_0_REG_ATTN_BIT_EN_0				 (0x1<<4)
-#define HC_CONFIG_0_REG_BLOCK_DISABLE_0				 (0x1<<0)
-#define HC_CONFIG_0_REG_INT_LINE_EN_0				 (0x1<<3)
-#define HC_CONFIG_0_REG_MSI_ATTN_EN_0				 (0x1<<7)
-#define HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0			 (0x1<<2)
-#define HC_CONFIG_0_REG_SINGLE_ISR_EN_0				 (0x1<<1)
-#define HC_CONFIG_1_REG_BLOCK_DISABLE_1				 (0x1<<0)
-#define HC_REG_AGG_INT_0					 0x108050
-#define HC_REG_AGG_INT_1					 0x108054
-#define HC_REG_ATTN_BIT 					 0x108120
-#define HC_REG_ATTN_IDX 					 0x108100
-#define HC_REG_ATTN_MSG0_ADDR_L 				 0x108018
-#define HC_REG_ATTN_MSG1_ADDR_L 				 0x108020
-#define HC_REG_ATTN_NUM_P0					 0x108038
-#define HC_REG_ATTN_NUM_P1					 0x10803c
-#define HC_REG_COMMAND_REG					 0x108180
-#define HC_REG_CONFIG_0 					 0x108000
-#define HC_REG_CONFIG_1 					 0x108004
-#define HC_REG_FUNC_NUM_P0					 0x1080ac
-#define HC_REG_FUNC_NUM_P1					 0x1080b0
-/* [RW 3] Parity mask register #0 read/write */
-#define HC_REG_HC_PRTY_MASK					 0x1080a0
-/* [R 3] Parity register #0 read */
-#define HC_REG_HC_PRTY_STS					 0x108094
-/* [RC 3] Parity register #0 read clear */
-#define HC_REG_HC_PRTY_STS_CLR					 0x108098
-#define HC_REG_INT_MASK						 0x108108
-#define HC_REG_LEADING_EDGE_0					 0x108040
-#define HC_REG_LEADING_EDGE_1					 0x108048
-#define HC_REG_MAIN_MEMORY					 0x108800
-#define HC_REG_MAIN_MEMORY_SIZE					 152
-#define HC_REG_P0_PROD_CONS					 0x108200
-#define HC_REG_P1_PROD_CONS					 0x108400
-#define HC_REG_PBA_COMMAND					 0x108140
-#define HC_REG_PCI_CONFIG_0					 0x108010
-#define HC_REG_PCI_CONFIG_1					 0x108014
-#define HC_REG_STATISTIC_COUNTERS				 0x109000
-#define HC_REG_TRAILING_EDGE_0					 0x108044
-#define HC_REG_TRAILING_EDGE_1					 0x10804c
-#define HC_REG_UC_RAM_ADDR_0					 0x108028
-#define HC_REG_UC_RAM_ADDR_1					 0x108030
-#define HC_REG_USTORM_ADDR_FOR_COALESCE 			 0x108068
-#define HC_REG_VQID_0						 0x108008
-#define HC_REG_VQID_1						 0x10800c
-#define IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN		 (0x1<<1)
-#define IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE		 (0x1<<0)
-#define IGU_REG_ATTENTION_ACK_BITS				 0x130108
-/* [R 4] Debug: attn_fsm */
-#define IGU_REG_ATTN_FSM					 0x130054
-#define IGU_REG_ATTN_MSG_ADDR_H				 0x13011c
-#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 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
-#define IGU_REG_COMMAND_REG_CTRL				 0x13012c
-/* [WB_R 32] Cleanup bit status per SB. 1 = cleanup is set. 0 = cleanup bit
- * is clear. The bits in this registers are set and clear via the producer
- * command. Data valid only in addresses 0-4. all the rest are zero. */
-#define IGU_REG_CSTORM_TYPE_0_SB_CLEANUP			 0x130200
-/* [R 5] Debug: ctrl_fsm */
-#define IGU_REG_CTRL_FSM					 0x130064
-/* [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 */
-#define IGU_REG_IGU_PRTY_MASK					 0x1300a8
-/* [R 11] Parity register #0 read */
-#define IGU_REG_IGU_PRTY_STS					 0x13009c
-/* [RC 11] Parity register #0 read clear */
-#define IGU_REG_IGU_PRTY_STS_CLR				 0x1300a0
-/* [R 4] Debug: int_handle_fsm */
-#define IGU_REG_INT_HANDLE_FSM					 0x130050
-#define IGU_REG_LEADING_EDGE_LATCH				 0x130134
-/* [RW 14] mapping CAM; relevant for E2 operating mode only. [0] - valid.
- * [6:1] - vector number; [13:7] - FID (if VF - [13] = 0; [12:7] = VF
- * number; if PF - [13] = 1; [12:10] = 0; [9:7] = PF number); */
-#define IGU_REG_MAPPING_MEMORY					 0x131000
-#define IGU_REG_MAPPING_MEMORY_SIZE				 136
-#define IGU_REG_PBA_STATUS_LSB					 0x130138
-#define IGU_REG_PBA_STATUS_MSB					 0x13013c
-#define IGU_REG_PCI_PF_MSI_EN					 0x130140
-#define IGU_REG_PCI_PF_MSIX_EN					 0x130144
-#define IGU_REG_PCI_PF_MSIX_FUNC_MASK				 0x130148
-/* [WB_R 32] Each bit represent the pending bits status for that SB. 0 = no
- * pending; 1 = pending. Pendings means interrupt was asserted; and write
- * done was not received. Data valid only in addresses 0-4. all the rest are
- * zero. */
-#define IGU_REG_PENDING_BITS_STATUS				 0x130300
-#define IGU_REG_PF_CONFIGURATION				 0x130154
-/* [RW 20] producers only. E2 mode: address 0-135 match to the mapping
- * memory; 136 - PF0 default prod; 137 PF1 default prod; 138 - PF2 default
- * prod; 139 PF3 default prod; 140 - PF0 - ATTN prod; 141 - PF1 - ATTN prod;
- * 142 - PF2 - ATTN prod; 143 - PF3 - ATTN prod; 144-147 reserved. E1.5 mode
- * - In backward compatible mode; for non default SB; each even line in the
- * memory holds the U producer and each odd line hold the C producer. The
- * first 128 producer are for NDSB (PF0 - 0-31; PF1 - 32-63 and so on). The
- * last 20 producers are for the DSB for each PF. each PF has five segments
- * (the order inside each segment is PF0; PF1; PF2; PF3) - 128-131 U prods;
- * 132-135 C prods; 136-139 X prods; 140-143 T prods; 144-147 ATTN prods; */
-#define IGU_REG_PROD_CONS_MEMORY				 0x132000
-/* [R 3] Debug: pxp_arb_fsm */
-#define IGU_REG_PXP_ARB_FSM					 0x130068
-/* [RW 6] Write one for each bit will reset the appropriate memory. When the
- * memory reset finished the appropriate bit will be clear. Bit 0 - mapping
- * memory; Bit 1 - SB memory; Bit 2 - SB interrupt and mask register; Bit 3
- * - MSIX memory; Bit 4 - PBA memory; Bit 5 - statistics; */
-#define IGU_REG_RESET_MEMORIES					 0x130158
-/* [R 4] Debug: sb_ctrl_fsm */
-#define IGU_REG_SB_CTRL_FSM					 0x13004c
-#define IGU_REG_SB_INT_BEFORE_MASK_LSB				 0x13015c
-#define IGU_REG_SB_INT_BEFORE_MASK_MSB				 0x130160
-#define IGU_REG_SB_MASK_LSB					 0x130164
-#define IGU_REG_SB_MASK_MSB					 0x130168
-/* [RW 16] Number of command that were dropped without causing an interrupt
- * due to: read access for WO BAR address; or write access for RO BAR
- * address or any access for reserved address or PCI function error is set
- * and address is not MSIX; PBA or cleanup */
-#define IGU_REG_SILENT_DROP					 0x13016c
-/* [RW 10] Number of MSI/MSIX/ATTN messages sent for the function: 0-63 -
- * number of MSIX messages per VF; 64-67 - number of MSI/MSIX messages per
- * PF; 68-71 number of ATTN messages per PF */
-#define IGU_REG_STATISTIC_NUM_MESSAGE_SENT			 0x130800
-/* [RW 32] Number of cycles the timer mask masking the IGU interrupt when a
- * timer mask command arrives. Value must be bigger than 100. */
-#define IGU_REG_TIMER_MASKING_VALUE				 0x13003c
-#define IGU_REG_TRAILING_EDGE_LATCH				 0x130104
-#define IGU_REG_VF_CONFIGURATION				 0x130170
-/* [WB_R 32] Each bit represent write done pending bits status for that SB
- * (MSI/MSIX message was sent and write done was not received yet). 0 =
- * clear; 1 = set. Data valid only in addresses 0-4. all the rest are zero. */
-#define IGU_REG_WRITE_DONE_PENDING				 0x130480
-#define MCP_A_REG_MCPR_SCRATCH					 0x3a0000
-#define MCP_REG_MCPR_CPU_PROGRAM_COUNTER			 0x8501c
-#define MCP_REG_MCPR_GP_INPUTS					 0x800c0
-#define MCP_REG_MCPR_GP_OENABLE					 0x800c8
-#define MCP_REG_MCPR_GP_OUTPUTS					 0x800c4
-#define MCP_REG_MCPR_IMC_COMMAND				 0x85900
-#define MCP_REG_MCPR_IMC_DATAREG0				 0x85920
-#define MCP_REG_MCPR_IMC_SLAVE_CONTROL				 0x85904
-#define MCP_REG_MCPR_CPU_PROGRAM_COUNTER			 0x8501c
-#define MCP_REG_MCPR_NVM_ACCESS_ENABLE				 0x86424
-#define MCP_REG_MCPR_NVM_ADDR					 0x8640c
-#define MCP_REG_MCPR_NVM_CFG4					 0x8642c
-#define MCP_REG_MCPR_NVM_COMMAND				 0x86400
-#define MCP_REG_MCPR_NVM_READ					 0x86410
-#define MCP_REG_MCPR_NVM_SW_ARB 				 0x86420
-#define MCP_REG_MCPR_NVM_WRITE					 0x86408
-#define MCP_REG_MCPR_SCRATCH					 0xa0000
-#define MISC_AEU_GENERAL_MASK_REG_AEU_NIG_CLOSE_MASK		 (0x1<<1)
-#define MISC_AEU_GENERAL_MASK_REG_AEU_PXP_CLOSE_MASK		 (0x1<<0)
-/* [R 32] read first 32 bit after inversion of function 0. mapped as
-   follows: [0] NIG attention for function0; [1] NIG attention for
-   function1; [2] GPIO1 mcp; [3] GPIO2 mcp; [4] GPIO3 mcp; [5] GPIO4 mcp;
-   [6] GPIO1 function 1; [7] GPIO2 function 1; [8] GPIO3 function 1; [9]
-   GPIO4 function 1; [10] PCIE glue/PXP VPD event function0; [11] PCIE
-   glue/PXP VPD event function1; [12] PCIE glue/PXP Expansion ROM event0;
-   [13] PCIE glue/PXP Expansion ROM event1; [14] SPIO4; [15] SPIO5; [16]
-   MSI/X indication for mcp; [17] MSI/X indication for function 1; [18] BRB
-   Parity error; [19] BRB Hw interrupt; [20] PRS Parity error; [21] PRS Hw
-   interrupt; [22] SRC Parity error; [23] SRC Hw interrupt; [24] TSDM Parity
-   error; [25] TSDM Hw interrupt; [26] TCM Parity error; [27] TCM Hw
-   interrupt; [28] TSEMI Parity error; [29] TSEMI Hw interrupt; [30] PBF
-   Parity error; [31] PBF Hw interrupt; */
-#define MISC_REG_AEU_AFTER_INVERT_1_FUNC_0			 0xa42c
-#define MISC_REG_AEU_AFTER_INVERT_1_FUNC_1			 0xa430
-/* [R 32] read first 32 bit after inversion of mcp. mapped as follows: [0]
-   NIG attention for function0; [1] NIG attention for function1; [2] GPIO1
-   mcp; [3] GPIO2 mcp; [4] GPIO3 mcp; [5] GPIO4 mcp; [6] GPIO1 function 1;
-   [7] GPIO2 function 1; [8] GPIO3 function 1; [9] GPIO4 function 1; [10]
-   PCIE glue/PXP VPD event function0; [11] PCIE glue/PXP VPD event
-   function1; [12] PCIE glue/PXP Expansion ROM event0; [13] PCIE glue/PXP
-   Expansion ROM event1; [14] SPIO4; [15] SPIO5; [16] MSI/X indication for
-   mcp; [17] MSI/X indication for function 1; [18] BRB Parity error; [19]
-   BRB Hw interrupt; [20] PRS Parity error; [21] PRS Hw interrupt; [22] SRC
-   Parity error; [23] SRC Hw interrupt; [24] TSDM Parity error; [25] TSDM Hw
-   interrupt; [26] TCM Parity error; [27] TCM Hw interrupt; [28] TSEMI
-   Parity error; [29] TSEMI Hw interrupt; [30] PBF Parity error; [31] PBF Hw
-   interrupt; */
-#define MISC_REG_AEU_AFTER_INVERT_1_MCP 			 0xa434
-/* [R 32] read second 32 bit after inversion of function 0. mapped as
-   follows: [0] PBClient Parity error; [1] PBClient Hw interrupt; [2] QM
-   Parity error; [3] QM Hw interrupt; [4] Timers Parity error; [5] Timers Hw
-   interrupt; [6] XSDM Parity error; [7] XSDM Hw interrupt; [8] XCM Parity
-   error; [9] XCM Hw interrupt; [10] XSEMI Parity error; [11] XSEMI Hw
-   interrupt; [12] DoorbellQ Parity error; [13] DoorbellQ Hw interrupt; [14]
-   NIG Parity error; [15] NIG Hw interrupt; [16] Vaux PCI core Parity error;
-   [17] Vaux PCI core Hw interrupt; [18] Debug Parity error; [19] Debug Hw
-   interrupt; [20] USDM Parity error; [21] USDM Hw interrupt; [22] UCM
-   Parity error; [23] UCM Hw interrupt; [24] USEMI Parity error; [25] USEMI
-   Hw interrupt; [26] UPB Parity error; [27] UPB Hw interrupt; [28] CSDM
-   Parity error; [29] CSDM Hw interrupt; [30] CCM Parity error; [31] CCM Hw
-   interrupt; */
-#define MISC_REG_AEU_AFTER_INVERT_2_FUNC_0			 0xa438
-#define MISC_REG_AEU_AFTER_INVERT_2_FUNC_1			 0xa43c
-/* [R 32] read second 32 bit after inversion of mcp. mapped as follows: [0]
-   PBClient Parity error; [1] PBClient Hw interrupt; [2] QM Parity error;
-   [3] QM Hw interrupt; [4] Timers Parity error; [5] Timers Hw interrupt;
-   [6] XSDM Parity error; [7] XSDM Hw interrupt; [8] XCM Parity error; [9]
-   XCM Hw interrupt; [10] XSEMI Parity error; [11] XSEMI Hw interrupt; [12]
-   DoorbellQ Parity error; [13] DoorbellQ Hw interrupt; [14] NIG Parity
-   error; [15] NIG Hw interrupt; [16] Vaux PCI core Parity error; [17] Vaux
-   PCI core Hw interrupt; [18] Debug Parity error; [19] Debug Hw interrupt;
-   [20] USDM Parity error; [21] USDM Hw interrupt; [22] UCM Parity error;
-   [23] UCM Hw interrupt; [24] USEMI Parity error; [25] USEMI Hw interrupt;
-   [26] UPB Parity error; [27] UPB Hw interrupt; [28] CSDM Parity error;
-   [29] CSDM Hw interrupt; [30] CCM Parity error; [31] CCM Hw interrupt; */
-#define MISC_REG_AEU_AFTER_INVERT_2_MCP 			 0xa440
-/* [R 32] read third 32 bit after inversion of function 0. mapped as
-   follows: [0] CSEMI Parity error; [1] CSEMI Hw interrupt; [2] PXP Parity
-   error; [3] PXP Hw interrupt; [4] PXPpciClockClient Parity error; [5]
-   PXPpciClockClient Hw interrupt; [6] CFC Parity error; [7] CFC Hw
-   interrupt; [8] CDU Parity error; [9] CDU Hw interrupt; [10] DMAE Parity
-   error; [11] DMAE Hw interrupt; [12] IGU (HC) Parity error; [13] IGU (HC)
-   Hw interrupt; [14] MISC Parity error; [15] MISC Hw interrupt; [16]
-   pxp_misc_mps_attn; [17] Flash event; [18] SMB event; [19] MCP attn0; [20]
-   MCP attn1; [21] SW timers attn_1 func0; [22] SW timers attn_2 func0; [23]
-   SW timers attn_3 func0; [24] SW timers attn_4 func0; [25] PERST; [26] SW
-   timers attn_1 func1; [27] SW timers attn_2 func1; [28] SW timers attn_3
-   func1; [29] SW timers attn_4 func1; [30] General attn0; [31] General
-   attn1; */
-#define MISC_REG_AEU_AFTER_INVERT_3_FUNC_0			 0xa444
-#define MISC_REG_AEU_AFTER_INVERT_3_FUNC_1			 0xa448
-/* [R 32] read third 32 bit after inversion of mcp. mapped as follows: [0]
-   CSEMI Parity error; [1] CSEMI Hw interrupt; [2] PXP Parity error; [3] PXP
-   Hw interrupt; [4] PXPpciClockClient Parity error; [5] PXPpciClockClient
-   Hw interrupt; [6] CFC Parity error; [7] CFC Hw interrupt; [8] CDU Parity
-   error; [9] CDU Hw interrupt; [10] DMAE Parity error; [11] DMAE Hw
-   interrupt; [12] IGU (HC) Parity error; [13] IGU (HC) Hw interrupt; [14]
-   MISC Parity error; [15] MISC Hw interrupt; [16] pxp_misc_mps_attn; [17]
-   Flash event; [18] SMB event; [19] MCP attn0; [20] MCP attn1; [21] SW
-   timers attn_1 func0; [22] SW timers attn_2 func0; [23] SW timers attn_3
-   func0; [24] SW timers attn_4 func0; [25] PERST; [26] SW timers attn_1
-   func1; [27] SW timers attn_2 func1; [28] SW timers attn_3 func1; [29] SW
-   timers attn_4 func1; [30] General attn0; [31] General attn1; */
-#define MISC_REG_AEU_AFTER_INVERT_3_MCP 			 0xa44c
-/* [R 32] read fourth 32 bit after inversion of function 0. mapped as
-   follows: [0] General attn2; [1] General attn3; [2] General attn4; [3]
-   General attn5; [4] General attn6; [5] General attn7; [6] General attn8;
-   [7] General attn9; [8] General attn10; [9] General attn11; [10] General
-   attn12; [11] General attn13; [12] General attn14; [13] General attn15;
-   [14] General attn16; [15] General attn17; [16] General attn18; [17]
-   General attn19; [18] General attn20; [19] General attn21; [20] Main power
-   interrupt; [21] RBCR Latched attn; [22] RBCT Latched attn; [23] RBCN
-   Latched attn; [24] RBCU Latched attn; [25] RBCP Latched attn; [26] GRC
-   Latched timeout attention; [27] GRC Latched reserved access attention;
-   [28] MCP Latched rom_parity; [29] MCP Latched ump_rx_parity; [30] MCP
-   Latched ump_tx_parity; [31] MCP Latched scpad_parity; */
-#define MISC_REG_AEU_AFTER_INVERT_4_FUNC_0			 0xa450
-#define MISC_REG_AEU_AFTER_INVERT_4_FUNC_1			 0xa454
-/* [R 32] read fourth 32 bit after inversion of mcp. mapped as follows: [0]
-   General attn2; [1] General attn3; [2] General attn4; [3] General attn5;
-   [4] General attn6; [5] General attn7; [6] General attn8; [7] General
-   attn9; [8] General attn10; [9] General attn11; [10] General attn12; [11]
-   General attn13; [12] General attn14; [13] General attn15; [14] General
-   attn16; [15] General attn17; [16] General attn18; [17] General attn19;
-   [18] General attn20; [19] General attn21; [20] Main power interrupt; [21]
-   RBCR Latched attn; [22] RBCT Latched attn; [23] RBCN Latched attn; [24]
-   RBCU Latched attn; [25] RBCP Latched attn; [26] GRC Latched timeout
-   attention; [27] GRC Latched reserved access attention; [28] MCP Latched
-   rom_parity; [29] MCP Latched ump_rx_parity; [30] MCP Latched
-   ump_tx_parity; [31] MCP Latched scpad_parity; */
-#define MISC_REG_AEU_AFTER_INVERT_4_MCP 			 0xa458
-/* [R 32] Read fifth 32 bit after inversion of function 0. Mapped as
- * follows: [0] PGLUE config_space; [1] PGLUE misc_flr; [2] PGLUE B RBC
- * attention [3] PGLUE B RBC parity; [4] ATC attention; [5] ATC parity; [6]
- * CNIG attention (reserved); [7] CNIG parity (reserved); [31-8] Reserved; */
-#define MISC_REG_AEU_AFTER_INVERT_5_FUNC_0			 0xa700
-/* [W 14] write to this register results with the clear of the latched
-   signals; one in d0 clears RBCR latch; one in d1 clears RBCT latch; one in
-   d2 clears RBCN latch; one in d3 clears RBCU latch; one in d4 clears RBCP
-   latch; one in d5 clears GRC Latched timeout attention; one in d6 clears
-   GRC Latched reserved access attention; one in d7 clears Latched
-   rom_parity; one in d8 clears Latched ump_rx_parity; one in d9 clears
-   Latched ump_tx_parity; one in d10 clears Latched scpad_parity (both
-   ports); one in d11 clears pxpv_misc_mps_attn; one in d12 clears
-   pxp_misc_exp_rom_attn0; one in d13 clears pxp_misc_exp_rom_attn1; read
-   from this register return zero */
-#define MISC_REG_AEU_CLR_LATCH_SIGNAL				 0xa45c
-/* [RW 32] first 32b for enabling the output for function 0 output0. mapped
-   as follows: [0] NIG attention for function0; [1] NIG attention for
-   function1; [2] GPIO1 function 0; [3] GPIO2 function 0; [4] GPIO3 function
-   0; [5] GPIO4 function 0; [6] GPIO1 function 1; [7] GPIO2 function 1; [8]
-   GPIO3 function 1; [9] GPIO4 function 1; [10] PCIE glue/PXP VPD event
-   function0; [11] PCIE glue/PXP VPD event function1; [12] PCIE glue/PXP
-   Expansion ROM event0; [13] PCIE glue/PXP Expansion ROM event1; [14]
-   SPIO4; [15] SPIO5; [16] MSI/X indication for function 0; [17] MSI/X
-   indication for function 1; [18] BRB Parity error; [19] BRB Hw interrupt;
-   [20] PRS Parity error; [21] PRS Hw interrupt; [22] SRC Parity error; [23]
-   SRC Hw interrupt; [24] TSDM Parity error; [25] TSDM Hw interrupt; [26]
-   TCM Parity error; [27] TCM Hw interrupt; [28] TSEMI Parity error; [29]
-   TSEMI Hw interrupt; [30] PBF Parity error; [31] PBF Hw interrupt; */
-#define MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0			 0xa06c
-#define MISC_REG_AEU_ENABLE1_FUNC_0_OUT_1			 0xa07c
-#define MISC_REG_AEU_ENABLE1_FUNC_0_OUT_2			 0xa08c
-#define MISC_REG_AEU_ENABLE1_FUNC_0_OUT_3			 0xa09c
-#define MISC_REG_AEU_ENABLE1_FUNC_0_OUT_5			 0xa0bc
-#define MISC_REG_AEU_ENABLE1_FUNC_0_OUT_6			 0xa0cc
-#define MISC_REG_AEU_ENABLE1_FUNC_0_OUT_7			 0xa0dc
-/* [RW 32] first 32b for enabling the output for function 1 output0. mapped
-   as follows: [0] NIG attention for function0; [1] NIG attention for
-   function1; [2] GPIO1 function 1; [3] GPIO2 function 1; [4] GPIO3 function
-   1; [5] GPIO4 function 1; [6] GPIO1 function 1; [7] GPIO2 function 1; [8]
-   GPIO3 function 1; [9] GPIO4 function 1; [10] PCIE glue/PXP VPD event
-   function0; [11] PCIE glue/PXP VPD event function1; [12] PCIE glue/PXP
-   Expansion ROM event0; [13] PCIE glue/PXP Expansion ROM event1; [14]
-   SPIO4; [15] SPIO5; [16] MSI/X indication for function 1; [17] MSI/X
-   indication for function 1; [18] BRB Parity error; [19] BRB Hw interrupt;
-   [20] PRS Parity error; [21] PRS Hw interrupt; [22] SRC Parity error; [23]
-   SRC Hw interrupt; [24] TSDM Parity error; [25] TSDM Hw interrupt; [26]
-   TCM Parity error; [27] TCM Hw interrupt; [28] TSEMI Parity error; [29]
-   TSEMI Hw interrupt; [30] PBF Parity error; [31] PBF Hw interrupt; */
-#define MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0			 0xa10c
-#define MISC_REG_AEU_ENABLE1_FUNC_1_OUT_1			 0xa11c
-#define MISC_REG_AEU_ENABLE1_FUNC_1_OUT_2			 0xa12c
-#define MISC_REG_AEU_ENABLE1_FUNC_1_OUT_3			 0xa13c
-#define MISC_REG_AEU_ENABLE1_FUNC_1_OUT_5			 0xa15c
-#define MISC_REG_AEU_ENABLE1_FUNC_1_OUT_6			 0xa16c
-#define MISC_REG_AEU_ENABLE1_FUNC_1_OUT_7			 0xa17c
-/* [RW 32] first 32b for enabling the output for close the gate nig. mapped
-   as follows: [0] NIG attention for function0; [1] NIG attention for
-   function1; [2] GPIO1 function 0; [3] GPIO2 function 0; [4] GPIO3 function
-   0; [5] GPIO4 function 0; [6] GPIO1 function 1; [7] GPIO2 function 1; [8]
-   GPIO3 function 1; [9] GPIO4 function 1; [10] PCIE glue/PXP VPD event
-   function0; [11] PCIE glue/PXP VPD event function1; [12] PCIE glue/PXP
-   Expansion ROM event0; [13] PCIE glue/PXP Expansion ROM event1; [14]
-   SPIO4; [15] SPIO5; [16] MSI/X indication for function 0; [17] MSI/X
-   indication for function 1; [18] BRB Parity error; [19] BRB Hw interrupt;
-   [20] PRS Parity error; [21] PRS Hw interrupt; [22] SRC Parity error; [23]
-   SRC Hw interrupt; [24] TSDM Parity error; [25] TSDM Hw interrupt; [26]
-   TCM Parity error; [27] TCM Hw interrupt; [28] TSEMI Parity error; [29]
-   TSEMI Hw interrupt; [30] PBF Parity error; [31] PBF Hw interrupt; */
-#define MISC_REG_AEU_ENABLE1_NIG_0				 0xa0ec
-#define MISC_REG_AEU_ENABLE1_NIG_1				 0xa18c
-/* [RW 32] first 32b for enabling the output for close the gate pxp. mapped
-   as follows: [0] NIG attention for function0; [1] NIG attention for
-   function1; [2] GPIO1 function 0; [3] GPIO2 function 0; [4] GPIO3 function
-   0; [5] GPIO4 function 0; [6] GPIO1 function 1; [7] GPIO2 function 1; [8]
-   GPIO3 function 1; [9] GPIO4 function 1; [10] PCIE glue/PXP VPD event
-   function0; [11] PCIE glue/PXP VPD event function1; [12] PCIE glue/PXP
-   Expansion ROM event0; [13] PCIE glue/PXP Expansion ROM event1; [14]
-   SPIO4; [15] SPIO5; [16] MSI/X indication for function 0; [17] MSI/X
-   indication for function 1; [18] BRB Parity error; [19] BRB Hw interrupt;
-   [20] PRS Parity error; [21] PRS Hw interrupt; [22] SRC Parity error; [23]
-   SRC Hw interrupt; [24] TSDM Parity error; [25] TSDM Hw interrupt; [26]
-   TCM Parity error; [27] TCM Hw interrupt; [28] TSEMI Parity error; [29]
-   TSEMI Hw interrupt; [30] PBF Parity error; [31] PBF Hw interrupt; */
-#define MISC_REG_AEU_ENABLE1_PXP_0				 0xa0fc
-#define MISC_REG_AEU_ENABLE1_PXP_1				 0xa19c
-/* [RW 32] second 32b for enabling the output for function 0 output0. mapped
-   as follows: [0] PBClient Parity error; [1] PBClient Hw interrupt; [2] QM
-   Parity error; [3] QM Hw interrupt; [4] Timers Parity error; [5] Timers Hw
-   interrupt; [6] XSDM Parity error; [7] XSDM Hw interrupt; [8] XCM Parity
-   error; [9] XCM Hw interrupt; [10] XSEMI Parity error; [11] XSEMI Hw
-   interrupt; [12] DoorbellQ Parity error; [13] DoorbellQ Hw interrupt; [14]
-   NIG Parity error; [15] NIG Hw interrupt; [16] Vaux PCI core Parity error;
-   [17] Vaux PCI core Hw interrupt; [18] Debug Parity error; [19] Debug Hw
-   interrupt; [20] USDM Parity error; [21] USDM Hw interrupt; [22] UCM
-   Parity error; [23] UCM Hw interrupt; [24] USEMI Parity error; [25] USEMI
-   Hw interrupt; [26] UPB Parity error; [27] UPB Hw interrupt; [28] CSDM
-   Parity error; [29] CSDM Hw interrupt; [30] CCM Parity error; [31] CCM Hw
-   interrupt; */
-#define MISC_REG_AEU_ENABLE2_FUNC_0_OUT_0			 0xa070
-#define MISC_REG_AEU_ENABLE2_FUNC_0_OUT_1			 0xa080
-/* [RW 32] second 32b for enabling the output for function 1 output0. mapped
-   as follows: [0] PBClient Parity error; [1] PBClient Hw interrupt; [2] QM
-   Parity error; [3] QM Hw interrupt; [4] Timers Parity error; [5] Timers Hw
-   interrupt; [6] XSDM Parity error; [7] XSDM Hw interrupt; [8] XCM Parity
-   error; [9] XCM Hw interrupt; [10] XSEMI Parity error; [11] XSEMI Hw
-   interrupt; [12] DoorbellQ Parity error; [13] DoorbellQ Hw interrupt; [14]
-   NIG Parity error; [15] NIG Hw interrupt; [16] Vaux PCI core Parity error;
-   [17] Vaux PCI core Hw interrupt; [18] Debug Parity error; [19] Debug Hw
-   interrupt; [20] USDM Parity error; [21] USDM Hw interrupt; [22] UCM
-   Parity error; [23] UCM Hw interrupt; [24] USEMI Parity error; [25] USEMI
-   Hw interrupt; [26] UPB Parity error; [27] UPB Hw interrupt; [28] CSDM
-   Parity error; [29] CSDM Hw interrupt; [30] CCM Parity error; [31] CCM Hw
-   interrupt; */
-#define MISC_REG_AEU_ENABLE2_FUNC_1_OUT_0			 0xa110
-#define MISC_REG_AEU_ENABLE2_FUNC_1_OUT_1			 0xa120
-/* [RW 32] second 32b for enabling the output for close the gate nig. mapped
-   as follows: [0] PBClient Parity error; [1] PBClient Hw interrupt; [2] QM
-   Parity error; [3] QM Hw interrupt; [4] Timers Parity error; [5] Timers Hw
-   interrupt; [6] XSDM Parity error; [7] XSDM Hw interrupt; [8] XCM Parity
-   error; [9] XCM Hw interrupt; [10] XSEMI Parity error; [11] XSEMI Hw
-   interrupt; [12] DoorbellQ Parity error; [13] DoorbellQ Hw interrupt; [14]
-   NIG Parity error; [15] NIG Hw interrupt; [16] Vaux PCI core Parity error;
-   [17] Vaux PCI core Hw interrupt; [18] Debug Parity error; [19] Debug Hw
-   interrupt; [20] USDM Parity error; [21] USDM Hw interrupt; [22] UCM
-   Parity error; [23] UCM Hw interrupt; [24] USEMI Parity error; [25] USEMI
-   Hw interrupt; [26] UPB Parity error; [27] UPB Hw interrupt; [28] CSDM
-   Parity error; [29] CSDM Hw interrupt; [30] CCM Parity error; [31] CCM Hw
-   interrupt; */
-#define MISC_REG_AEU_ENABLE2_NIG_0				 0xa0f0
-#define MISC_REG_AEU_ENABLE2_NIG_1				 0xa190
-/* [RW 32] second 32b for enabling the output for close the gate pxp. mapped
-   as follows: [0] PBClient Parity error; [1] PBClient Hw interrupt; [2] QM
-   Parity error; [3] QM Hw interrupt; [4] Timers Parity error; [5] Timers Hw
-   interrupt; [6] XSDM Parity error; [7] XSDM Hw interrupt; [8] XCM Parity
-   error; [9] XCM Hw interrupt; [10] XSEMI Parity error; [11] XSEMI Hw
-   interrupt; [12] DoorbellQ Parity error; [13] DoorbellQ Hw interrupt; [14]
-   NIG Parity error; [15] NIG Hw interrupt; [16] Vaux PCI core Parity error;
-   [17] Vaux PCI core Hw interrupt; [18] Debug Parity error; [19] Debug Hw
-   interrupt; [20] USDM Parity error; [21] USDM Hw interrupt; [22] UCM
-   Parity error; [23] UCM Hw interrupt; [24] USEMI Parity error; [25] USEMI
-   Hw interrupt; [26] UPB Parity error; [27] UPB Hw interrupt; [28] CSDM
-   Parity error; [29] CSDM Hw interrupt; [30] CCM Parity error; [31] CCM Hw
-   interrupt; */
-#define MISC_REG_AEU_ENABLE2_PXP_0				 0xa100
-#define MISC_REG_AEU_ENABLE2_PXP_1				 0xa1a0
-/* [RW 32] third 32b for enabling the output for function 0 output0. mapped
-   as follows: [0] CSEMI Parity error; [1] CSEMI Hw interrupt; [2] PXP
-   Parity error; [3] PXP Hw interrupt; [4] PXPpciClockClient Parity error;
-   [5] PXPpciClockClient Hw interrupt; [6] CFC Parity error; [7] CFC Hw
-   interrupt; [8] CDU Parity error; [9] CDU Hw interrupt; [10] DMAE Parity
-   error; [11] DMAE Hw interrupt; [12] IGU (HC) Parity error; [13] IGU (HC)
-   Hw interrupt; [14] MISC Parity error; [15] MISC Hw interrupt; [16]
-   pxp_misc_mps_attn; [17] Flash event; [18] SMB event; [19] MCP attn0; [20]
-   MCP attn1; [21] SW timers attn_1 func0; [22] SW timers attn_2 func0; [23]
-   SW timers attn_3 func0; [24] SW timers attn_4 func0; [25] PERST; [26] SW
-   timers attn_1 func1; [27] SW timers attn_2 func1; [28] SW timers attn_3
-   func1; [29] SW timers attn_4 func1; [30] General attn0; [31] General
-   attn1; */
-#define MISC_REG_AEU_ENABLE3_FUNC_0_OUT_0			 0xa074
-#define MISC_REG_AEU_ENABLE3_FUNC_0_OUT_1			 0xa084
-/* [RW 32] third 32b for enabling the output for function 1 output0. mapped
-   as follows: [0] CSEMI Parity error; [1] CSEMI Hw interrupt; [2] PXP
-   Parity error; [3] PXP Hw interrupt; [4] PXPpciClockClient Parity error;
-   [5] PXPpciClockClient Hw interrupt; [6] CFC Parity error; [7] CFC Hw
-   interrupt; [8] CDU Parity error; [9] CDU Hw interrupt; [10] DMAE Parity
-   error; [11] DMAE Hw interrupt; [12] IGU (HC) Parity error; [13] IGU (HC)
-   Hw interrupt; [14] MISC Parity error; [15] MISC Hw interrupt; [16]
-   pxp_misc_mps_attn; [17] Flash event; [18] SMB event; [19] MCP attn0; [20]
-   MCP attn1; [21] SW timers attn_1 func0; [22] SW timers attn_2 func0; [23]
-   SW timers attn_3 func0; [24] SW timers attn_4 func0; [25] PERST; [26] SW
-   timers attn_1 func1; [27] SW timers attn_2 func1; [28] SW timers attn_3
-   func1; [29] SW timers attn_4 func1; [30] General attn0; [31] General
-   attn1; */
-#define MISC_REG_AEU_ENABLE3_FUNC_1_OUT_0			 0xa114
-#define MISC_REG_AEU_ENABLE3_FUNC_1_OUT_1			 0xa124
-/* [RW 32] third 32b for enabling the output for close the gate nig. mapped
-   as follows: [0] CSEMI Parity error; [1] CSEMI Hw interrupt; [2] PXP
-   Parity error; [3] PXP Hw interrupt; [4] PXPpciClockClient Parity error;
-   [5] PXPpciClockClient Hw interrupt; [6] CFC Parity error; [7] CFC Hw
-   interrupt; [8] CDU Parity error; [9] CDU Hw interrupt; [10] DMAE Parity
-   error; [11] DMAE Hw interrupt; [12] IGU (HC) Parity error; [13] IGU (HC)
-   Hw interrupt; [14] MISC Parity error; [15] MISC Hw interrupt; [16]
-   pxp_misc_mps_attn; [17] Flash event; [18] SMB event; [19] MCP attn0; [20]
-   MCP attn1; [21] SW timers attn_1 func0; [22] SW timers attn_2 func0; [23]
-   SW timers attn_3 func0; [24] SW timers attn_4 func0; [25] PERST; [26] SW
-   timers attn_1 func1; [27] SW timers attn_2 func1; [28] SW timers attn_3
-   func1; [29] SW timers attn_4 func1; [30] General attn0; [31] General
-   attn1; */
-#define MISC_REG_AEU_ENABLE3_NIG_0				 0xa0f4
-#define MISC_REG_AEU_ENABLE3_NIG_1				 0xa194
-/* [RW 32] third 32b for enabling the output for close the gate pxp. mapped
-   as follows: [0] CSEMI Parity error; [1] CSEMI Hw interrupt; [2] PXP
-   Parity error; [3] PXP Hw interrupt; [4] PXPpciClockClient Parity error;
-   [5] PXPpciClockClient Hw interrupt; [6] CFC Parity error; [7] CFC Hw
-   interrupt; [8] CDU Parity error; [9] CDU Hw interrupt; [10] DMAE Parity
-   error; [11] DMAE Hw interrupt; [12] IGU (HC) Parity error; [13] IGU (HC)
-   Hw interrupt; [14] MISC Parity error; [15] MISC Hw interrupt; [16]
-   pxp_misc_mps_attn; [17] Flash event; [18] SMB event; [19] MCP attn0; [20]
-   MCP attn1; [21] SW timers attn_1 func0; [22] SW timers attn_2 func0; [23]
-   SW timers attn_3 func0; [24] SW timers attn_4 func0; [25] PERST; [26] SW
-   timers attn_1 func1; [27] SW timers attn_2 func1; [28] SW timers attn_3
-   func1; [29] SW timers attn_4 func1; [30] General attn0; [31] General
-   attn1; */
-#define MISC_REG_AEU_ENABLE3_PXP_0				 0xa104
-#define MISC_REG_AEU_ENABLE3_PXP_1				 0xa1a4
-/* [RW 32] fourth 32b for enabling the output for function 0 output0.mapped
-   as follows: [0] General attn2; [1] General attn3; [2] General attn4; [3]
-   General attn5; [4] General attn6; [5] General attn7; [6] General attn8;
-   [7] General attn9; [8] General attn10; [9] General attn11; [10] General
-   attn12; [11] General attn13; [12] General attn14; [13] General attn15;
-   [14] General attn16; [15] General attn17; [16] General attn18; [17]
-   General attn19; [18] General attn20; [19] General attn21; [20] Main power
-   interrupt; [21] RBCR Latched attn; [22] RBCT Latched attn; [23] RBCN
-   Latched attn; [24] RBCU Latched attn; [25] RBCP Latched attn; [26] GRC
-   Latched timeout attention; [27] GRC Latched reserved access attention;
-   [28] MCP Latched rom_parity; [29] MCP Latched ump_rx_parity; [30] MCP
-   Latched ump_tx_parity; [31] MCP Latched scpad_parity; */
-#define MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0			 0xa078
-#define MISC_REG_AEU_ENABLE4_FUNC_0_OUT_2			 0xa098
-#define MISC_REG_AEU_ENABLE4_FUNC_0_OUT_4			 0xa0b8
-#define MISC_REG_AEU_ENABLE4_FUNC_0_OUT_5			 0xa0c8
-#define MISC_REG_AEU_ENABLE4_FUNC_0_OUT_6			 0xa0d8
-#define MISC_REG_AEU_ENABLE4_FUNC_0_OUT_7			 0xa0e8
-/* [RW 32] fourth 32b for enabling the output for function 1 output0.mapped
-   as follows: [0] General attn2; [1] General attn3; [2] General attn4; [3]
-   General attn5; [4] General attn6; [5] General attn7; [6] General attn8;
-   [7] General attn9; [8] General attn10; [9] General attn11; [10] General
-   attn12; [11] General attn13; [12] General attn14; [13] General attn15;
-   [14] General attn16; [15] General attn17; [16] General attn18; [17]
-   General attn19; [18] General attn20; [19] General attn21; [20] Main power
-   interrupt; [21] RBCR Latched attn; [22] RBCT Latched attn; [23] RBCN
-   Latched attn; [24] RBCU Latched attn; [25] RBCP Latched attn; [26] GRC
-   Latched timeout attention; [27] GRC Latched reserved access attention;
-   [28] MCP Latched rom_parity; [29] MCP Latched ump_rx_parity; [30] MCP
-   Latched ump_tx_parity; [31] MCP Latched scpad_parity; */
-#define MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0			 0xa118
-#define MISC_REG_AEU_ENABLE4_FUNC_1_OUT_2			 0xa138
-#define MISC_REG_AEU_ENABLE4_FUNC_1_OUT_4			 0xa158
-#define MISC_REG_AEU_ENABLE4_FUNC_1_OUT_5			 0xa168
-#define MISC_REG_AEU_ENABLE4_FUNC_1_OUT_6			 0xa178
-#define MISC_REG_AEU_ENABLE4_FUNC_1_OUT_7			 0xa188
-/* [RW 32] fourth 32b for enabling the output for close the gate nig.mapped
-   as follows: [0] General attn2; [1] General attn3; [2] General attn4; [3]
-   General attn5; [4] General attn6; [5] General attn7; [6] General attn8;
-   [7] General attn9; [8] General attn10; [9] General attn11; [10] General
-   attn12; [11] General attn13; [12] General attn14; [13] General attn15;
-   [14] General attn16; [15] General attn17; [16] General attn18; [17]
-   General attn19; [18] General attn20; [19] General attn21; [20] Main power
-   interrupt; [21] RBCR Latched attn; [22] RBCT Latched attn; [23] RBCN
-   Latched attn; [24] RBCU Latched attn; [25] RBCP Latched attn; [26] GRC
-   Latched timeout attention; [27] GRC Latched reserved access attention;
-   [28] MCP Latched rom_parity; [29] MCP Latched ump_rx_parity; [30] MCP
-   Latched ump_tx_parity; [31] MCP Latched scpad_parity; */
-#define MISC_REG_AEU_ENABLE4_NIG_0				 0xa0f8
-#define MISC_REG_AEU_ENABLE4_NIG_1				 0xa198
-/* [RW 32] fourth 32b for enabling the output for close the gate pxp.mapped
-   as follows: [0] General attn2; [1] General attn3; [2] General attn4; [3]
-   General attn5; [4] General attn6; [5] General attn7; [6] General attn8;
-   [7] General attn9; [8] General attn10; [9] General attn11; [10] General
-   attn12; [11] General attn13; [12] General attn14; [13] General attn15;
-   [14] General attn16; [15] General attn17; [16] General attn18; [17]
-   General attn19; [18] General attn20; [19] General attn21; [20] Main power
-   interrupt; [21] RBCR Latched attn; [22] RBCT Latched attn; [23] RBCN
-   Latched attn; [24] RBCU Latched attn; [25] RBCP Latched attn; [26] GRC
-   Latched timeout attention; [27] GRC Latched reserved access attention;
-   [28] MCP Latched rom_parity; [29] MCP Latched ump_rx_parity; [30] MCP
-   Latched ump_tx_parity; [31] MCP Latched scpad_parity; */
-#define MISC_REG_AEU_ENABLE4_PXP_0				 0xa108
-#define MISC_REG_AEU_ENABLE4_PXP_1				 0xa1a8
-/* [RW 32] fifth 32b for enabling the output for function 0 output0. Mapped
- * as follows: [0] PGLUE config_space; [1] PGLUE misc_flr; [2] PGLUE B RBC
- * attention [3] PGLUE B RBC parity; [4] ATC attention; [5] ATC parity; [6]
- * mstat0 attention; [7] mstat0 parity; [8] mstat1 attention; [9] mstat1
- * parity; [31-10] Reserved; */
-#define MISC_REG_AEU_ENABLE5_FUNC_0_OUT_0			 0xa688
-/* [RW 32] Fifth 32b for enabling the output for function 1 output0. Mapped
- * as follows: [0] PGLUE config_space; [1] PGLUE misc_flr; [2] PGLUE B RBC
- * attention [3] PGLUE B RBC parity; [4] ATC attention; [5] ATC parity; [6]
- * mstat0 attention; [7] mstat0 parity; [8] mstat1 attention; [9] mstat1
- * parity; [31-10] Reserved; */
-#define MISC_REG_AEU_ENABLE5_FUNC_1_OUT_0			 0xa6b0
-/* [RW 1] set/clr general attention 0; this will set/clr bit 94 in the aeu
-   128 bit vector */
-#define MISC_REG_AEU_GENERAL_ATTN_0				 0xa000
-#define MISC_REG_AEU_GENERAL_ATTN_1				 0xa004
-#define MISC_REG_AEU_GENERAL_ATTN_10				 0xa028
-#define MISC_REG_AEU_GENERAL_ATTN_11				 0xa02c
-#define MISC_REG_AEU_GENERAL_ATTN_12				 0xa030
-#define MISC_REG_AEU_GENERAL_ATTN_2				 0xa008
-#define MISC_REG_AEU_GENERAL_ATTN_3				 0xa00c
-#define MISC_REG_AEU_GENERAL_ATTN_4				 0xa010
-#define MISC_REG_AEU_GENERAL_ATTN_5				 0xa014
-#define MISC_REG_AEU_GENERAL_ATTN_6				 0xa018
-#define MISC_REG_AEU_GENERAL_ATTN_7				 0xa01c
-#define MISC_REG_AEU_GENERAL_ATTN_8				 0xa020
-#define MISC_REG_AEU_GENERAL_ATTN_9				 0xa024
-#define MISC_REG_AEU_GENERAL_MASK				 0xa61c
-/* [RW 32] first 32b for inverting the input for function 0; for each bit:
-   0= do not invert; 1= invert; mapped as follows: [0] NIG attention for
-   function0; [1] NIG attention for function1; [2] GPIO1 mcp; [3] GPIO2 mcp;
-   [4] GPIO3 mcp; [5] GPIO4 mcp; [6] GPIO1 function 1; [7] GPIO2 function 1;
-   [8] GPIO3 function 1; [9] GPIO4 function 1; [10] PCIE glue/PXP VPD event
-   function0; [11] PCIE glue/PXP VPD event function1; [12] PCIE glue/PXP
-   Expansion ROM event0; [13] PCIE glue/PXP Expansion ROM event1; [14]
-   SPIO4; [15] SPIO5; [16] MSI/X indication for mcp; [17] MSI/X indication
-   for function 1; [18] BRB Parity error; [19] BRB Hw interrupt; [20] PRS
-   Parity error; [21] PRS Hw interrupt; [22] SRC Parity error; [23] SRC Hw
-   interrupt; [24] TSDM Parity error; [25] TSDM Hw interrupt; [26] TCM
-   Parity error; [27] TCM Hw interrupt; [28] TSEMI Parity error; [29] TSEMI
-   Hw interrupt; [30] PBF Parity error; [31] PBF Hw interrupt; */
-#define MISC_REG_AEU_INVERTER_1_FUNC_0				 0xa22c
-#define MISC_REG_AEU_INVERTER_1_FUNC_1				 0xa23c
-/* [RW 32] second 32b for inverting the input for function 0; for each bit:
-   0= do not invert; 1= invert. mapped as follows: [0] PBClient Parity
-   error; [1] PBClient Hw interrupt; [2] QM Parity error; [3] QM Hw
-   interrupt; [4] Timers Parity error; [5] Timers Hw interrupt; [6] XSDM
-   Parity error; [7] XSDM Hw interrupt; [8] XCM Parity error; [9] XCM Hw
-   interrupt; [10] XSEMI Parity error; [11] XSEMI Hw interrupt; [12]
-   DoorbellQ Parity error; [13] DoorbellQ Hw interrupt; [14] NIG Parity
-   error; [15] NIG Hw interrupt; [16] Vaux PCI core Parity error; [17] Vaux
-   PCI core Hw interrupt; [18] Debug Parity error; [19] Debug Hw interrupt;
-   [20] USDM Parity error; [21] USDM Hw interrupt; [22] UCM Parity error;
-   [23] UCM Hw interrupt; [24] USEMI Parity error; [25] USEMI Hw interrupt;
-   [26] UPB Parity error; [27] UPB Hw interrupt; [28] CSDM Parity error;
-   [29] CSDM Hw interrupt; [30] CCM Parity error; [31] CCM Hw interrupt; */
-#define MISC_REG_AEU_INVERTER_2_FUNC_0				 0xa230
-#define MISC_REG_AEU_INVERTER_2_FUNC_1				 0xa240
-/* [RW 10] [7:0] = mask 8 attention output signals toward IGU function0;
-   [9:8] = raserved. Zero = mask; one = unmask */
-#define MISC_REG_AEU_MASK_ATTN_FUNC_0				 0xa060
-#define MISC_REG_AEU_MASK_ATTN_FUNC_1				 0xa064
-/* [RW 1] If set a system kill occurred */
-#define MISC_REG_AEU_SYS_KILL_OCCURRED				 0xa610
-/* [RW 32] Represent the status of the input vector to the AEU when a system
-   kill occurred. The register is reset in por reset. Mapped as follows: [0]
-   NIG attention for function0; [1] NIG attention for function1; [2] GPIO1
-   mcp; [3] GPIO2 mcp; [4] GPIO3 mcp; [5] GPIO4 mcp; [6] GPIO1 function 1;
-   [7] GPIO2 function 1; [8] GPIO3 function 1; [9] GPIO4 function 1; [10]
-   PCIE glue/PXP VPD event function0; [11] PCIE glue/PXP VPD event
-   function1; [12] PCIE glue/PXP Expansion ROM event0; [13] PCIE glue/PXP
-   Expansion ROM event1; [14] SPIO4; [15] SPIO5; [16] MSI/X indication for
-   mcp; [17] MSI/X indication for function 1; [18] BRB Parity error; [19]
-   BRB Hw interrupt; [20] PRS Parity error; [21] PRS Hw interrupt; [22] SRC
-   Parity error; [23] SRC Hw interrupt; [24] TSDM Parity error; [25] TSDM Hw
-   interrupt; [26] TCM Parity error; [27] TCM Hw interrupt; [28] TSEMI
-   Parity error; [29] TSEMI Hw interrupt; [30] PBF Parity error; [31] PBF Hw
-   interrupt; */
-#define MISC_REG_AEU_SYS_KILL_STATUS_0				 0xa600
-#define MISC_REG_AEU_SYS_KILL_STATUS_1				 0xa604
-#define MISC_REG_AEU_SYS_KILL_STATUS_2				 0xa608
-#define MISC_REG_AEU_SYS_KILL_STATUS_3				 0xa60c
-/* [R 4] This field indicates the type of the device. '0' - 2 Ports; '1' - 1
-   Port. */
-#define MISC_REG_BOND_ID					 0xa400
-/* [R 8] These bits indicate the metal revision of the chip. This value
-   starts at 0x00 for each all-layer tape-out and increments by one for each
-   tape-out. */
-#define MISC_REG_CHIP_METAL					 0xa404
-/* [R 16] These bits indicate the part number for the chip. */
-#define MISC_REG_CHIP_NUM					 0xa408
-/* [R 4] These bits indicate the base revision of the chip. This value
-   starts at 0x0 for the A0 tape-out and increments by one for each
-   all-layer tape-out. */
-#define MISC_REG_CHIP_REV					 0xa40c
-/* [RW 32] The following driver registers(1...16) represent 16 drivers and
-   32 clients. Each client can be controlled by one driver only. One in each
-   bit represent that this driver control the appropriate client (Ex: bit 5
-   is set means this driver control client number 5). addr1 = set; addr0 =
-   clear; read from both addresses will give the same result = status. write
-   to address 1 will set a request to control all the clients that their
-   appropriate bit (in the write command) is set. if the client is free (the
-   appropriate bit in all the other drivers is clear) one will be written to
-   that driver register; if the client isn't free the bit will remain zero.
-   if the appropriate bit is set (the driver request to gain control on a
-   client it already controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW
-   interrupt will be asserted). write to address 0 will set a request to
-   free all the clients that their appropriate bit (in the write command) is
-   set. if the appropriate bit is clear (the driver request to free a client
-   it doesn't controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW interrupt will
-   be asserted). */
-#define MISC_REG_DRIVER_CONTROL_1				 0xa510
-#define MISC_REG_DRIVER_CONTROL_7				 0xa3c8
-/* [RW 1] e1hmf for WOL. If clr WOL signal o the PXP will be send on bit 0
-   only. */
-#define MISC_REG_E1HMF_MODE					 0xa5f8
-/* [R 1] Status of four port mode path swap input pin. */
-#define MISC_REG_FOUR_PORT_PATH_SWAP				 0xa75c
-/* [RW 2] 4 port path swap overwrite.[0] - Overwrite control; if it is 0 -
-   the path_swap output is equal to 4 port mode path swap input pin; if it
-   is 1 - the path_swap output is equal to bit[1] of this register; [1] -
-   Overwrite value. If bit[0] of this register is 1 this is the value that
-   receives the path_swap output. Reset on Hard reset. */
-#define MISC_REG_FOUR_PORT_PATH_SWAP_OVWR			 0xa738
-/* [R 1] Status of 4 port mode port swap input pin. */
-#define MISC_REG_FOUR_PORT_PORT_SWAP				 0xa754
-/* [RW 2] 4 port port swap overwrite.[0] - Overwrite control; if it is 0 -
-   the port_swap output is equal to 4 port mode port swap input pin; if it
-   is 1 - the port_swap output is equal to bit[1] of this register; [1] -
-   Overwrite value. If bit[0] of this register is 1 this is the value that
-   receives the port_swap output. Reset on Hard reset. */
-#define MISC_REG_FOUR_PORT_PORT_SWAP_OVWR			 0xa734
-/* [RW 32] Debug only: spare RW register reset by core reset */
-#define MISC_REG_GENERIC_CR_0					 0xa460
-#define MISC_REG_GENERIC_CR_1					 0xa464
-/* [RW 32] Debug only: spare RW register reset by por reset */
-#define MISC_REG_GENERIC_POR_1					 0xa474
-/* [RW 32] Bit[0]: EPIO MODE SEL: Setting this bit to 1 will allow SW/FW to
-   use all of the 32 Extended GPIO pins. Without setting this bit; an EPIO
-   can not be configured as an output. Each output has its output enable in
-   the MCP register space; but this bit needs to be set to make use of that.
-   Bit[3:1] spare. Bit[4]: WCVTMON_PWRDN: Powerdown for Warpcore VTMON. When
-   set to 1 - Powerdown. Bit[5]: WCVTMON_RESETB: Reset for Warpcore VTMON.
-   When set to 0 - vTMON is in reset. Bit[6]: setting this bit will change
-   the i/o to an output and will drive the TimeSync output. Bit[31:7]:
-   spare. Global register. Reset by hard reset. */
-#define MISC_REG_GEN_PURP_HWG					 0xa9a0
-/* [RW 32] GPIO. [31-28] FLOAT port 0; [27-24] FLOAT port 0; When any of
-   these bits is written as a '1'; the corresponding SPIO bit will turn off
-   it's drivers and become an input. This is the reset state of all GPIO
-   pins. The read value of these bits will be a '1' if that last command
-   (#SET; #CLR; or #FLOAT) for this bit was a #FLOAT. (reset value 0xff).
-   [23-20] CLR port 1; 19-16] CLR port 0; When any of these bits is written
-   as a '1'; the corresponding GPIO bit will drive low. The read value of
-   these bits will be a '1' if that last command (#SET; #CLR; or #FLOAT) for
-   this bit was a #CLR. (reset value 0). [15-12] SET port 1; 11-8] port 0;
-   SET When any of these bits is written as a '1'; the corresponding GPIO
-   bit will drive high (if it has that capability). The read value of these
-   bits will be a '1' if that last command (#SET; #CLR; or #FLOAT) for this
-   bit was a #SET. (reset value 0). [7-4] VALUE port 1; [3-0] VALUE port 0;
-   RO; These bits indicate the read value of each of the eight GPIO pins.
-   This is the result value of the pin; not the drive value. Writing these
-   bits will have not effect. */
-#define MISC_REG_GPIO						 0xa490
-/* [RW 8] These bits enable the GPIO_INTs to signals event to the
-   IGU/MCP.according to the following map: [0] p0_gpio_0; [1] p0_gpio_1; [2]
-   p0_gpio_2; [3] p0_gpio_3; [4] p1_gpio_0; [5] p1_gpio_1; [6] p1_gpio_2;
-   [7] p1_gpio_3; */
-#define MISC_REG_GPIO_EVENT_EN					 0xa2bc
-/* [RW 32] GPIO INT. [31-28] OLD_CLR port1; [27-24] OLD_CLR port0; Writing a
-   '1' to these bit clears the corresponding bit in the #OLD_VALUE register.
-   This will acknowledge an interrupt on the falling edge of corresponding
-   GPIO input (reset value 0). [23-16] OLD_SET [23-16] port1; OLD_SET port0;
-   Writing a '1' to these bit sets the corresponding bit in the #OLD_VALUE
-   register. This will acknowledge an interrupt on the rising edge of
-   corresponding SPIO input (reset value 0). [15-12] OLD_VALUE [11-8] port1;
-   OLD_VALUE port0; RO; These bits indicate the old value of the GPIO input
-   value. When the ~INT_STATE bit is set; this bit indicates the OLD value
-   of the pin such that if ~INT_STATE is set and this bit is '0'; then the
-   interrupt is due to a low to high edge. If ~INT_STATE is set and this bit
-   is '1'; then the interrupt is due to a high to low edge (reset value 0).
-   [7-4] INT_STATE port1; [3-0] INT_STATE RO port0; These bits indicate the
-   current GPIO interrupt state for each GPIO pin. This bit is cleared when
-   the appropriate #OLD_SET or #OLD_CLR command bit is written. This bit is
-   set when the GPIO input does not match the current value in #OLD_VALUE
-   (reset value 0). */
-#define MISC_REG_GPIO_INT					 0xa494
-/* [R 28] this field hold the last information that caused reserved
-   attention. bits [19:0] - address; [22:20] function; [23] reserved;
-   [27:24] the master that caused the attention - according to the following
-   encodeing:1 = pxp; 2 = mcp; 3 = usdm; 4 = tsdm; 5 = xsdm; 6 = csdm; 7 =
-   dbu; 8 = dmae */
-#define MISC_REG_GRC_RSV_ATTN					 0xa3c0
-/* [R 28] this field hold the last information that caused timeout
-   attention. bits [19:0] - address; [22:20] function; [23] reserved;
-   [27:24] the master that caused the attention - according to the following
-   encodeing:1 = pxp; 2 = mcp; 3 = usdm; 4 = tsdm; 5 = xsdm; 6 = csdm; 7 =
-   dbu; 8 = dmae */
-#define MISC_REG_GRC_TIMEOUT_ATTN				 0xa3c4
-/* [RW 1] Setting this bit enables a timer in the GRC block to timeout any
-   access that does not finish within
-   ~misc_registers_grc_timout_val.grc_timeout_val cycles. When this bit is
-   cleared; this timeout is disabled. If this timeout occurs; the GRC shall
-   assert it attention output. */
-#define MISC_REG_GRC_TIMEOUT_EN 				 0xa280
-/* [RW 28] 28 LSB of LCPLL first register; reset val = 521. inside order of
-   the bits is: [2:0] OAC reset value 001) CML output buffer bias control;
-   111 for +40%; 011 for +20%; 001 for 0%; 000 for -20%. [5:3] Icp_ctrl
-   (reset value 001) Charge pump current control; 111 for 720u; 011 for
-   600u; 001 for 480u and 000 for 360u. [7:6] Bias_ctrl (reset value 00)
-   Global bias control; When bit 7 is high bias current will be 10 0gh; When
-   bit 6 is high bias will be 100w; Valid values are 00; 10; 01. [10:8]
-   Pll_observe (reset value 010) Bits to control observability. bit 10 is
-   for test bias; bit 9 is for test CK; bit 8 is test Vc. [12:11] Vth_ctrl
-   (reset value 00) Comparator threshold control. 00 for 0.6V; 01 for 0.54V
-   and 10 for 0.66V. [13] pllSeqStart (reset value 0) Enables VCO tuning
-   sequencer: 1= sequencer disabled; 0= sequencer enabled (inverted
-   internally). [14] reserved (reset value 0) Reset for VCO sequencer is
-   connected to RESET input directly. [15] capRetry_en (reset value 0)
-   enable retry on cap search failure (inverted). [16] freqMonitor_e (reset
-   value 0) bit to continuously monitor vco freq (inverted). [17]
-   freqDetRestart_en (reset value 0) bit to enable restart when not freq
-   locked (inverted). [18] freqDetRetry_en (reset value 0) bit to enable
-   retry on freq det failure(inverted). [19] pllForceFdone_en (reset value
-   0) bit to enable pllForceFdone & pllForceFpass into pllSeq. [20]
-   pllForceFdone (reset value 0) bit to force freqDone. [21] pllForceFpass
-   (reset value 0) bit to force freqPass. [22] pllForceDone_en (reset value
-   0) bit to enable pllForceCapDone. [23] pllForceCapDone (reset value 0)
-   bit to force capDone. [24] pllForceCapPass_en (reset value 0) bit to
-   enable pllForceCapPass. [25] pllForceCapPass (reset value 0) bit to force
-   capPass. [26] capRestart (reset value 0) bit to force cap sequencer to
-   restart. [27] capSelectM_en (reset value 0) bit to enable cap select
-   register bits. */
-#define MISC_REG_LCPLL_CTRL_1					 0xa2a4
-#define MISC_REG_LCPLL_CTRL_REG_2				 0xa2a8
-/* [RW 4] Interrupt mask register #0 read/write */
-#define MISC_REG_MISC_INT_MASK					 0xa388
-/* [RW 1] Parity mask register #0 read/write */
-#define MISC_REG_MISC_PRTY_MASK 				 0xa398
-/* [R 1] Parity register #0 read */
-#define MISC_REG_MISC_PRTY_STS					 0xa38c
-/* [RC 1] Parity register #0 read clear */
-#define MISC_REG_MISC_PRTY_STS_CLR				 0xa390
-#define MISC_REG_NIG_WOL_P0					 0xa270
-#define MISC_REG_NIG_WOL_P1					 0xa274
-/* [R 1] If set indicate that the pcie_rst_b was asserted without perst
-   assertion */
-#define MISC_REG_PCIE_HOT_RESET 				 0xa618
-/* [RW 32] 32 LSB of storm PLL first register; reset val = 0x 071d2911.
-   inside order of the bits is: [0] P1 divider[0] (reset value 1); [1] P1
-   divider[1] (reset value 0); [2] P1 divider[2] (reset value 0); [3] P1
-   divider[3] (reset value 0); [4] P2 divider[0] (reset value 1); [5] P2
-   divider[1] (reset value 0); [6] P2 divider[2] (reset value 0); [7] P2
-   divider[3] (reset value 0); [8] ph_det_dis (reset value 1); [9]
-   freq_det_dis (reset value 0); [10] Icpx[0] (reset value 0); [11] Icpx[1]
-   (reset value 1); [12] Icpx[2] (reset value 0); [13] Icpx[3] (reset value
-   1); [14] Icpx[4] (reset value 0); [15] Icpx[5] (reset value 0); [16]
-   Rx[0] (reset value 1); [17] Rx[1] (reset value 0); [18] vc_en (reset
-   value 1); [19] vco_rng[0] (reset value 1); [20] vco_rng[1] (reset value
-   1); [21] Kvco_xf[0] (reset value 0); [22] Kvco_xf[1] (reset value 0);
-   [23] Kvco_xf[2] (reset value 0); [24] Kvco_xs[0] (reset value 1); [25]
-   Kvco_xs[1] (reset value 1); [26] Kvco_xs[2] (reset value 1); [27]
-   testd_en (reset value 0); [28] testd_sel[0] (reset value 0); [29]
-   testd_sel[1] (reset value 0); [30] testd_sel[2] (reset value 0); [31]
-   testa_en (reset value 0); */
-#define MISC_REG_PLL_STORM_CTRL_1				 0xa294
-#define MISC_REG_PLL_STORM_CTRL_2				 0xa298
-#define MISC_REG_PLL_STORM_CTRL_3				 0xa29c
-#define MISC_REG_PLL_STORM_CTRL_4				 0xa2a0
-/* [R 1] Status of 4 port mode enable input pin. */
-#define MISC_REG_PORT4MODE_EN					 0xa750
-/* [RW 2] 4 port mode enable overwrite.[0] - Overwrite control; if it is 0 -
- * the port4mode_en output is equal to 4 port mode input pin; if it is 1 -
- * the port4mode_en output is equal to bit[1] of this register; [1] -
- * Overwrite value. If bit[0] of this register is 1 this is the value that
- * receives the port4mode_en output . */
-#define MISC_REG_PORT4MODE_EN_OVWR				 0xa720
-/* [RW 32] reset reg#2; rite/read one = the specific block is out of reset;
-   write/read zero = the specific block is in reset; addr 0-wr- the write
-   value will be written to the register; addr 1-set - one will be written
-   to all the bits that have the value of one in the data written (bits that
-   have the value of zero will not be change) ; addr 2-clear - zero will be
-   written to all the bits that have the value of one in the data written
-   (bits that have the value of zero will not be change); addr 3-ignore;
-   read ignore from all addr except addr 00; inside order of the bits is:
-   [0] rst_bmac0; [1] rst_bmac1; [2] rst_emac0; [3] rst_emac1; [4] rst_grc;
-   [5] rst_mcp_n_reset_reg_hard_core; [6] rst_ mcp_n_hard_core_rst_b; [7]
-   rst_ mcp_n_reset_cmn_cpu; [8] rst_ mcp_n_reset_cmn_core; [9] rst_rbcn;
-   [10] rst_dbg; [11] rst_misc_core; [12] rst_dbue (UART); [13]
-   Pci_resetmdio_n; [14] rst_emac0_hard_core; [15] rst_emac1_hard_core; 16]
-   rst_pxp_rq_rd_wr; 31:17] reserved */
-#define MISC_REG_RESET_REG_2					 0xa590
-/* [RW 20] 20 bit GRC address where the scratch-pad of the MCP that is
-   shared with the driver resides */
-#define MISC_REG_SHARED_MEM_ADDR				 0xa2b4
-/* [RW 32] SPIO. [31-24] FLOAT When any of these bits is written as a '1';
-   the corresponding SPIO bit will turn off it's drivers and become an
-   input. This is the reset state of all SPIO pins. The read value of these
-   bits will be a '1' if that last command (#SET; #CL; or #FLOAT) for this
-   bit was a #FLOAT. (reset value 0xff). [23-16] CLR When any of these bits
-   is written as a '1'; the corresponding SPIO bit will drive low. The read
-   value of these bits will be a '1' if that last command (#SET; #CLR; or
-#FLOAT) for this bit was a #CLR. (reset value 0). [15-8] SET When any of
-   these bits is written as a '1'; the corresponding SPIO bit will drive
-   high (if it has that capability). The read value of these bits will be a
-   '1' if that last command (#SET; #CLR; or #FLOAT) for this bit was a #SET.
-   (reset value 0). [7-0] VALUE RO; These bits indicate the read value of
-   each of the eight SPIO pins. This is the result value of the pin; not the
-   drive value. Writing these bits will have not effect. Each 8 bits field
-   is divided as follows: [0] VAUX Enable; when pulsed low; enables supply
-   from VAUX. (This is an output pin only; the FLOAT field is not applicable
-   for this pin); [1] VAUX Disable; when pulsed low; disables supply form
-   VAUX. (This is an output pin only; FLOAT field is not applicable for this
-   pin); [2] SEL_VAUX_B - Control to power switching logic. Drive low to
-   select VAUX supply. (This is an output pin only; it is not controlled by
-   the SET and CLR fields; it is controlled by the Main Power SM; the FLOAT
-   field is not applicable for this pin; only the VALUE fields is relevant -
-   it reflects the output value); [3] port swap [4] spio_4; [5] spio_5; [6]
-   Bit 0 of UMP device ID select; read by UMP firmware; [7] Bit 1 of UMP
-   device ID select; read by UMP firmware. */
-#define MISC_REG_SPIO						 0xa4fc
-/* [RW 8] These bits enable the SPIO_INTs to signals event to the IGU/MC.
-   according to the following map: [3:0] reserved; [4] spio_4 [5] spio_5;
-   [7:0] reserved */
-#define MISC_REG_SPIO_EVENT_EN					 0xa2b8
-/* [RW 32] SPIO INT. [31-24] OLD_CLR Writing a '1' to these bit clears the
-   corresponding bit in the #OLD_VALUE register. This will acknowledge an
-   interrupt on the falling edge of corresponding SPIO input (reset value
-   0). [23-16] OLD_SET Writing a '1' to these bit sets the corresponding bit
-   in the #OLD_VALUE register. This will acknowledge an interrupt on the
-   rising edge of corresponding SPIO input (reset value 0). [15-8] OLD_VALUE
-   RO; These bits indicate the old value of the SPIO input value. When the
-   ~INT_STATE bit is set; this bit indicates the OLD value of the pin such
-   that if ~INT_STATE is set and this bit is '0'; then the interrupt is due
-   to a low to high edge. If ~INT_STATE is set and this bit is '1'; then the
-   interrupt is due to a high to low edge (reset value 0). [7-0] INT_STATE
-   RO; These bits indicate the current SPIO interrupt state for each SPIO
-   pin. This bit is cleared when the appropriate #OLD_SET or #OLD_CLR
-   command bit is written. This bit is set when the SPIO input does not
-   match the current value in #OLD_VALUE (reset value 0). */
-#define MISC_REG_SPIO_INT					 0xa500
-/* [RW 32] reload value for counter 4 if reload; the value will be reload if
-   the counter reached zero and the reload bit
-   (~misc_registers_sw_timer_cfg_4.sw_timer_cfg_4[1] ) is set */
-#define MISC_REG_SW_TIMER_RELOAD_VAL_4				 0xa2fc
-/* [RW 32] the value of the counter for sw timers1-8. there are 8 addresses
-   in this register. address 0 - timer 1; address 1 - timer 2, ...  address 7 -
-   timer 8 */
-#define MISC_REG_SW_TIMER_VAL					 0xa5c0
-/* [R 1] Status of two port mode path swap input pin. */
-#define MISC_REG_TWO_PORT_PATH_SWAP				 0xa758
-/* [RW 2] 2 port swap overwrite.[0] - Overwrite control; if it is 0 - the
-   path_swap output is equal to 2 port mode path swap input pin; if it is 1
-   - the path_swap output is equal to bit[1] of this register; [1] -
-   Overwrite value. If bit[0] of this register is 1 this is the value that
-   receives the path_swap output. Reset on Hard reset. */
-#define MISC_REG_TWO_PORT_PATH_SWAP_OVWR			 0xa72c
-/* [RW 1] Set by the MCP to remember if one or more of the drivers is/are
-   loaded; 0-prepare; -unprepare */
-#define MISC_REG_UNPREPARED					 0xa424
-#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_BRCST	 (0x1<<0)
-#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_MLCST	 (0x1<<1)
-#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN	 (0x1<<4)
-#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST	 (0x1<<2)
-#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN	 (0x1<<3)
-/* [RW 5] MDIO PHY Address. The WC uses this address to determine whether or
- * not it is the recipient of the message on the MDIO interface. The value
- * is compared to the value on ctrl_md_devad. Drives output
- * misc_xgxs0_phy_addr. Global register. */
-#define MISC_REG_WC0_CTRL_PHY_ADDR				 0xa9cc
-/* [RW 2] XMAC Core port mode. Indicates the number of ports on the system
-   side. This should be less than or equal to phy_port_mode; if some of the
-   ports are not used. This enables reduction of frequency on the core side.
-   This is a strap input for the XMAC_MP core. 00 - Single Port Mode; 01 -
-   Dual Port Mode; 10 - Tri Port Mode; 11 - Quad Port Mode. This is a strap
-   input for the XMAC_MP core; and should be changed only while reset is
-   held low. Reset on Hard reset. */
-#define MISC_REG_XMAC_CORE_PORT_MODE				 0xa964
-/* [RW 2] XMAC PHY port mode. Indicates the number of ports on the Warp
-   Core. This is a strap input for the XMAC_MP core. 00 - Single Port Mode;
-   01 - Dual Port Mode; 1x - Quad Port Mode; This is a strap input for the
-   XMAC_MP core; and should be changed only while reset is held low. Reset
-   on Hard reset. */
-#define MISC_REG_XMAC_PHY_PORT_MODE				 0xa960
-/* [RW 32] 1 [47] Packet Size = 64 Write to this register write bits 31:0.
- * Reads from this register will clear bits 31:0. */
-#define MSTAT_REG_RX_STAT_GR64_LO				 0x200
-/* [RW 32] 1 [00] Tx Good Packet Count Write to this register write bits
- * 31:0. Reads from this register will clear bits 31:0. */
-#define MSTAT_REG_TX_STAT_GTXPOK_LO				 0
-#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_BRCST	 (0x1<<0)
-#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_MLCST	 (0x1<<1)
-#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN	 (0x1<<4)
-#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST	 (0x1<<2)
-#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN	 (0x1<<3)
-#define NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN			 (0x1<<0)
-#define NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN			 (0x1<<0)
-#define NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT	 (0x1<<0)
-#define NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS	 (0x1<<9)
-#define NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G 	 (0x1<<15)
-#define NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK_STATUS	 (0xf<<18)
-/* [RW 1] Input enable for RX_BMAC0 IF */
-#define NIG_REG_BMAC0_IN_EN					 0x100ac
-/* [RW 1] output enable for TX_BMAC0 IF */
-#define NIG_REG_BMAC0_OUT_EN					 0x100e0
-/* [RW 1] output enable for TX BMAC pause port 0 IF */
-#define NIG_REG_BMAC0_PAUSE_OUT_EN				 0x10110
-/* [RW 1] output enable for RX_BMAC0_REGS IF */
-#define NIG_REG_BMAC0_REGS_OUT_EN				 0x100e8
-/* [RW 1] output enable for RX BRB1 port0 IF */
-#define NIG_REG_BRB0_OUT_EN					 0x100f8
-/* [RW 1] Input enable for TX BRB1 pause port 0 IF */
-#define NIG_REG_BRB0_PAUSE_IN_EN				 0x100c4
-/* [RW 1] output enable for RX BRB1 port1 IF */
-#define NIG_REG_BRB1_OUT_EN					 0x100fc
-/* [RW 1] Input enable for TX BRB1 pause port 1 IF */
-#define NIG_REG_BRB1_PAUSE_IN_EN				 0x100c8
-/* [RW 1] output enable for RX BRB1 LP IF */
-#define NIG_REG_BRB_LB_OUT_EN					 0x10100
-/* [WB_W 82] Debug packet to LP from RBC; Data spelling:[63:0] data; 64]
-   error; [67:65]eop_bvalid; [68]eop; [69]sop; [70]port_id; 71]flush;
-   72:73]-vnic_num; 81:74]-sideband_info */
-#define NIG_REG_DEBUG_PACKET_LB 				 0x10800
-/* [RW 1] Input enable for TX Debug packet */
-#define NIG_REG_EGRESS_DEBUG_IN_EN				 0x100dc
-/* [RW 1] If 1 - egress drain mode for port0 is active. In this mode all
-   packets from PBFare not forwarded to the MAC and just deleted from FIFO.
-   First packet may be deleted from the middle. And last packet will be
-   always deleted till the end. */
-#define NIG_REG_EGRESS_DRAIN0_MODE				 0x10060
-/* [RW 1] Output enable to EMAC0 */
-#define NIG_REG_EGRESS_EMAC0_OUT_EN				 0x10120
-/* [RW 1] MAC configuration for packets of port0. If 1 - all packet outputs
-   to emac for port0; other way to bmac for port0 */
-#define NIG_REG_EGRESS_EMAC0_PORT				 0x10058
-/* [RW 1] Input enable for TX PBF user packet port0 IF */
-#define NIG_REG_EGRESS_PBF0_IN_EN				 0x100cc
-/* [RW 1] Input enable for TX PBF user packet port1 IF */
-#define NIG_REG_EGRESS_PBF1_IN_EN				 0x100d0
-/* [RW 1] Input enable for TX UMP management packet port0 IF */
-#define NIG_REG_EGRESS_UMP0_IN_EN				 0x100d4
-/* [RW 1] Input enable for RX_EMAC0 IF */
-#define NIG_REG_EMAC0_IN_EN					 0x100a4
-/* [RW 1] output enable for TX EMAC pause port 0 IF */
-#define NIG_REG_EMAC0_PAUSE_OUT_EN				 0x10118
-/* [R 1] status from emac0. This bit is set when MDINT from either the
-   EXT_MDINT pin or from the Copper PHY is driven low. This condition must
-   be cleared in the attached PHY device that is driving the MINT pin. */
-#define NIG_REG_EMAC0_STATUS_MISC_MI_INT			 0x10494
-/* [WB 48] This address space contains BMAC0 registers. The BMAC registers
-   are described in appendix A. In order to access the BMAC0 registers; the
-   base address; NIG_REGISTERS_INGRESS_BMAC0_MEM; Offset: 0x10c00; should be
-   added to each BMAC register offset */
-#define NIG_REG_INGRESS_BMAC0_MEM				 0x10c00
-/* [WB 48] This address space contains BMAC1 registers. The BMAC registers
-   are described in appendix A. In order to access the BMAC0 registers; the
-   base address; NIG_REGISTERS_INGRESS_BMAC1_MEM; Offset: 0x11000; should be
-   added to each BMAC register offset */
-#define NIG_REG_INGRESS_BMAC1_MEM				 0x11000
-/* [R 1] FIFO empty in EOP descriptor FIFO of LP in NIG_RX_EOP */
-#define NIG_REG_INGRESS_EOP_LB_EMPTY				 0x104e0
-/* [RW 17] Debug only. RX_EOP_DSCR_lb_FIFO in NIG_RX_EOP. Data
-   packet_length[13:0]; mac_error[14]; trunc_error[15]; parity[16] */
-#define NIG_REG_INGRESS_EOP_LB_FIFO				 0x104e4
-/* [RW 27] 0 - must be active for Everest A0; 1- for Everest B0 when latch
-   logic for interrupts must be used. Enable per bit of interrupt of
-   ~latch_status.latch_status */
-#define NIG_REG_LATCH_BC_0					 0x16210
-/* [RW 27] Latch for each interrupt from Unicore.b[0]
-   status_emac0_misc_mi_int; b[1] status_emac0_misc_mi_complete;
-   b[2]status_emac0_misc_cfg_change; b[3]status_emac0_misc_link_status;
-   b[4]status_emac0_misc_link_change; b[5]status_emac0_misc_attn;
-   b[6]status_serdes0_mac_crs; b[7]status_serdes0_autoneg_complete;
-   b[8]status_serdes0_fiber_rxact; b[9]status_serdes0_link_status;
-   b[10]status_serdes0_mr_page_rx; b[11]status_serdes0_cl73_an_complete;
-   b[12]status_serdes0_cl73_mr_page_rx; b[13]status_serdes0_rx_sigdet;
-   b[14]status_xgxs0_remotemdioreq; b[15]status_xgxs0_link10g;
-   b[16]status_xgxs0_autoneg_complete; b[17]status_xgxs0_fiber_rxact;
-   b[21:18]status_xgxs0_link_status; b[22]status_xgxs0_mr_page_rx;
-   b[23]status_xgxs0_cl73_an_complete; b[24]status_xgxs0_cl73_mr_page_rx;
-   b[25]status_xgxs0_rx_sigdet; b[26]status_xgxs0_mac_crs */
-#define NIG_REG_LATCH_STATUS_0					 0x18000
-/* [RW 1] led 10g for port 0 */
-#define NIG_REG_LED_10G_P0					 0x10320
-/* [RW 1] led 10g for port 1 */
-#define NIG_REG_LED_10G_P1					 0x10324
-/* [RW 1] Port0: This bit is set to enable the use of the
-   ~nig_registers_led_control_blink_rate_p0.led_control_blink_rate_p0 field
-   defined below. If this bit is cleared; then the blink rate will be about
-   8Hz. */
-#define NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0			 0x10318
-/* [RW 12] Port0: Specifies the period of each blink cycle (on + off) for
-   Traffic LED in milliseconds. Must be a non-zero value. This 12-bit field
-   is reset to 0x080; giving a default blink period of approximately 8Hz. */
-#define NIG_REG_LED_CONTROL_BLINK_RATE_P0			 0x10310
-/* [RW 1] Port0: If set along with the
- ~nig_registers_led_control_override_traffic_p0.led_control_override_traffic_p0
-   bit and ~nig_registers_led_control_traffic_p0.led_control_traffic_p0 LED
-   bit; the Traffic LED will blink with the blink rate specified in
-   ~nig_registers_led_control_blink_rate_p0.led_control_blink_rate_p0 and
-   ~nig_registers_led_control_blink_rate_ena_p0.led_control_blink_rate_ena_p0
-   fields. */
-#define NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0			 0x10308
-/* [RW 1] Port0: If set overrides hardware control of the Traffic LED. The
-   Traffic LED will then be controlled via bit ~nig_registers_
-   led_control_traffic_p0.led_control_traffic_p0 and bit
-   ~nig_registers_led_control_blink_traffic_p0.led_control_blink_traffic_p0 */
-#define NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 		 0x102f8
-/* [RW 1] Port0: If set along with the led_control_override_trafic_p0 bit;
-   turns on the Traffic LED. If the led_control_blink_traffic_p0 bit is also
-   set; the LED will blink with blink rate specified in
-   ~nig_registers_led_control_blink_rate_p0.led_control_blink_rate_p0 and
-   ~nig_regsters_led_control_blink_rate_ena_p0.led_control_blink_rate_ena_p0
-   fields. */
-#define NIG_REG_LED_CONTROL_TRAFFIC_P0				 0x10300
-/* [RW 4] led mode for port0: 0 MAC; 1-3 PHY1; 4 MAC2; 5-7 PHY4; 8-MAC3;
-   9-11PHY7; 12 MAC4; 13-15 PHY10; */
-#define NIG_REG_LED_MODE_P0					 0x102f0
-/* [RW 3] for port0 enable for llfc ppp and pause. b0 - brb1 enable; b1-
-   tsdm enable; b2- usdm enable */
-#define NIG_REG_LLFC_EGRESS_SRC_ENABLE_0			 0x16070
-#define NIG_REG_LLFC_EGRESS_SRC_ENABLE_1			 0x16074
-/* [RW 1] SAFC enable for port0. This register may get 1 only when
-   ~ppp_enable.ppp_enable = 0 and pause_enable.pause_enable =0 for the same
-   port */
-#define NIG_REG_LLFC_ENABLE_0					 0x16208
-#define NIG_REG_LLFC_ENABLE_1					 0x1620c
-/* [RW 16] classes are high-priority for port0 */
-#define NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_0			 0x16058
-#define NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_1			 0x1605c
-/* [RW 16] classes are low-priority for port0 */
-#define NIG_REG_LLFC_LOW_PRIORITY_CLASSES_0			 0x16060
-#define NIG_REG_LLFC_LOW_PRIORITY_CLASSES_1			 0x16064
-/* [RW 1] Output enable of message to LLFC BMAC IF for port0 */
-#define NIG_REG_LLFC_OUT_EN_0					 0x160c8
-#define NIG_REG_LLFC_OUT_EN_1					 0x160cc
-#define NIG_REG_LLH0_ACPI_PAT_0_CRC				 0x1015c
-#define NIG_REG_LLH0_ACPI_PAT_6_LEN				 0x10154
-#define NIG_REG_LLH0_BRB1_DRV_MASK				 0x10244
-#define NIG_REG_LLH0_BRB1_DRV_MASK_MF				 0x16048
-/* [RW 1] send to BRB1 if no match on any of RMP rules. */
-#define NIG_REG_LLH0_BRB1_NOT_MCP				 0x1025c
-/* [RW 2] Determine the classification participants. 0: no classification.1:
-   classification upon VLAN id. 2: classification upon MAC address. 3:
-   classification upon both VLAN id & MAC addr. */
-#define NIG_REG_LLH0_CLS_TYPE					 0x16080
-/* [RW 32] cm header for llh0 */
-#define NIG_REG_LLH0_CM_HEADER					 0x1007c
-#define NIG_REG_LLH0_DEST_IP_0_1				 0x101dc
-#define NIG_REG_LLH0_DEST_MAC_0_0				 0x101c0
-/* [RW 16] destination TCP address 1. The LLH will look for this address in
-   all incoming packets. */
-#define NIG_REG_LLH0_DEST_TCP_0 				 0x10220
-/* [RW 16] destination UDP address 1 The LLH will look for this address in
-   all incoming packets. */
-#define NIG_REG_LLH0_DEST_UDP_0 				 0x10214
-#define NIG_REG_LLH0_ERROR_MASK 				 0x1008c
-/* [RW 8] event id for llh0 */
-#define NIG_REG_LLH0_EVENT_ID					 0x10084
-#define NIG_REG_LLH0_FUNC_EN					 0x160fc
-#define NIG_REG_LLH0_FUNC_MEM					 0x16180
-#define NIG_REG_LLH0_FUNC_MEM_ENABLE				 0x16140
-#define NIG_REG_LLH0_FUNC_VLAN_ID				 0x16100
-/* [RW 1] Determine the IP version to look for in
-   ~nig_registers_llh0_dest_ip_0.llh0_dest_ip_0. 0 - IPv6; 1-IPv4 */
-#define NIG_REG_LLH0_IPV4_IPV6_0				 0x10208
-/* [RW 1] t bit for llh0 */
-#define NIG_REG_LLH0_T_BIT					 0x10074
-/* [RW 12] VLAN ID 1. In case of VLAN packet the LLH will look for this ID. */
-#define NIG_REG_LLH0_VLAN_ID_0					 0x1022c
-/* [RW 8] init credit counter for port0 in LLH */
-#define NIG_REG_LLH0_XCM_INIT_CREDIT				 0x10554
-#define NIG_REG_LLH0_XCM_MASK					 0x10130
-#define NIG_REG_LLH1_BRB1_DRV_MASK				 0x10248
-/* [RW 1] send to BRB1 if no match on any of RMP rules. */
-#define NIG_REG_LLH1_BRB1_NOT_MCP				 0x102dc
-/* [RW 2] Determine the classification participants. 0: no classification.1:
-   classification upon VLAN id. 2: classification upon MAC address. 3:
-   classification upon both VLAN id & MAC addr. */
-#define NIG_REG_LLH1_CLS_TYPE					 0x16084
-/* [RW 32] cm header for llh1 */
-#define NIG_REG_LLH1_CM_HEADER					 0x10080
-#define NIG_REG_LLH1_ERROR_MASK 				 0x10090
-/* [RW 8] event id for llh1 */
-#define NIG_REG_LLH1_EVENT_ID					 0x10088
-#define NIG_REG_LLH1_FUNC_MEM					 0x161c0
-#define NIG_REG_LLH1_FUNC_MEM_ENABLE				 0x16160
-#define NIG_REG_LLH1_FUNC_MEM_SIZE				 16
-/* [RW 1] When this bit is set; the LLH will classify the packet before
- * sending it to the BRB or calculating WoL on it. This bit controls port 1
- * only. The legacy llh_multi_function_mode bit controls port 0. */
-#define NIG_REG_LLH1_MF_MODE					 0x18614
-/* [RW 8] init credit counter for port1 in LLH */
-#define NIG_REG_LLH1_XCM_INIT_CREDIT				 0x10564
-#define NIG_REG_LLH1_XCM_MASK					 0x10134
-/* [RW 1] When this bit is set; the LLH will expect all packets to be with
-   e1hov */
-#define NIG_REG_LLH_E1HOV_MODE					 0x160d8
-/* [RW 1] When this bit is set; the LLH will classify the packet before
-   sending it to the BRB or calculating WoL on it. */
-#define NIG_REG_LLH_MF_MODE					 0x16024
-#define NIG_REG_MASK_INTERRUPT_PORT0				 0x10330
-#define NIG_REG_MASK_INTERRUPT_PORT1				 0x10334
-/* [RW 1] Output signal from NIG to EMAC0. When set enables the EMAC0 block. */
-#define NIG_REG_NIG_EMAC0_EN					 0x1003c
-/* [RW 1] Output signal from NIG to EMAC1. When set enables the EMAC1 block. */
-#define NIG_REG_NIG_EMAC1_EN					 0x10040
-/* [RW 1] Output signal from NIG to TX_EMAC0. When set indicates to the
-   EMAC0 to strip the CRC from the ingress packets. */
-#define NIG_REG_NIG_INGRESS_EMAC0_NO_CRC			 0x10044
-/* [R 32] Interrupt register #0 read */
-#define NIG_REG_NIG_INT_STS_0					 0x103b0
-#define NIG_REG_NIG_INT_STS_1					 0x103c0
-/* [R 32] Legacy E1 and E1H location for parity error mask register. */
-#define NIG_REG_NIG_PRTY_MASK					 0x103dc
-/* [RW 32] Parity mask register #0 read/write */
-#define NIG_REG_NIG_PRTY_MASK_0					 0x183c8
-#define NIG_REG_NIG_PRTY_MASK_1					 0x183d8
-/* [R 32] Legacy E1 and E1H location for parity error status register. */
-#define NIG_REG_NIG_PRTY_STS					 0x103d0
-/* [R 32] Parity register #0 read */
-#define NIG_REG_NIG_PRTY_STS_0					 0x183bc
-#define NIG_REG_NIG_PRTY_STS_1					 0x183cc
-/* [R 32] Legacy E1 and E1H location for parity error status clear register. */
-#define NIG_REG_NIG_PRTY_STS_CLR				 0x103d4
-/* [RC 32] Parity register #0 read clear */
-#define NIG_REG_NIG_PRTY_STS_CLR_0				 0x183c0
-#define NIG_REG_NIG_PRTY_STS_CLR_1				 0x183d0
-#define MCPR_IMC_COMMAND_ENABLE					 (1L<<31)
-#define MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT			 16
-#define MCPR_IMC_COMMAND_OPERATION_BITSHIFT			 28
-#define MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT		 8
-/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
- * Ethernet header. */
-#define NIG_REG_P0_HDRS_AFTER_BASIC				 0x18038
-/* [RW 1] HW PFC enable bit. Set this bit to enable the PFC functionality in
- * the NIG. Other flow control modes such as PAUSE and SAFC/LLFC should be
- * disabled when this bit is set. */
-#define NIG_REG_P0_HWPFC_ENABLE				 0x18078
-#define NIG_REG_P0_LLH_FUNC_MEM2				 0x18480
-#define NIG_REG_P0_LLH_FUNC_MEM2_ENABLE			 0x18440
-/* [RW 1] Input enable for RX MAC interface. */
-#define NIG_REG_P0_MAC_IN_EN					 0x185ac
-/* [RW 1] Output enable for TX MAC interface */
-#define NIG_REG_P0_MAC_OUT_EN					 0x185b0
-/* [RW 1] Output enable for TX PAUSE signal to the MAC. */
-#define NIG_REG_P0_MAC_PAUSE_OUT_EN				 0x185b4
-/* [RW 32] Eight 4-bit configurations for specifying which COS (0-15 for
- * future expansion) each priorty is to be mapped to. Bits 3:0 specify the
- * COS for priority 0. Bits 31:28 specify the COS for priority 7. The 3-bit
- * priority field is extracted from the outer-most VLAN in receive packet.
- * Only COS 0 and COS 1 are supported in E2. */
-#define NIG_REG_P0_PKT_PRIORITY_TO_COS				 0x18054
-/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 0. A
- * priority is mapped to COS 0 when the corresponding mask bit is 1. More
- * than one bit may be set; allowing multiple priorities to be mapped to one
- * COS. */
-#define NIG_REG_P0_RX_COS0_PRIORITY_MASK			 0x18058
-/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 1. A
- * priority is mapped to COS 1 when the corresponding mask bit is 1. More
- * than one bit may be set; allowing multiple priorities to be mapped to one
- * COS. */
-#define NIG_REG_P0_RX_COS1_PRIORITY_MASK			 0x1805c
-/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 2. A
- * priority is mapped to COS 2 when the corresponding mask bit is 1. More
- * than one bit may be set; allowing multiple priorities to be mapped to one
- * COS. */
-#define NIG_REG_P0_RX_COS2_PRIORITY_MASK			 0x186b0
-/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 3. A
- * priority is mapped to COS 3 when the corresponding mask bit is 1. More
- * than one bit may be set; allowing multiple priorities to be mapped to one
- * COS. */
-#define NIG_REG_P0_RX_COS3_PRIORITY_MASK			 0x186b4
-/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 4. A
- * priority is mapped to COS 4 when the corresponding mask bit is 1. More
- * than one bit may be set; allowing multiple priorities to be mapped to one
- * COS. */
-#define NIG_REG_P0_RX_COS4_PRIORITY_MASK			 0x186b8
-/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 5. A
- * priority is mapped to COS 5 when the corresponding mask bit is 1. More
- * than one bit may be set; allowing multiple priorities to be mapped to one
- * COS. */
-#define NIG_REG_P0_RX_COS5_PRIORITY_MASK			 0x186bc
-/* [R 1] RX FIFO for receiving data from MAC is empty. */
-/* [RW 15] Specify which of the credit registers the client is to be mapped
- * to. Bits[2:0] are for client 0; bits [14:12] are for client 4. For
- * clients that are not subject to WFQ credit blocking - their
- * specifications here are not used. */
-#define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP			 0x180f0
-/* [RW 32] Specify which of the credit registers the client is to be mapped
- * to. This register specifies bits 31:0 of the 36-bit value. Bits[3:0] are
- * for client 0; bits [35:32] are for client 8. For clients that are not
- * subject to WFQ credit blocking - their specifications here are not used.
- * This is a new register (with 2_) added in E3 B0 to accommodate the 9
- * input clients to ETS arbiter. The reset default is set for management and
- * debug to use credit registers 6, 7, and 8, respectively, and COSes 0-5 to
- * use credit registers 0-5 respectively (0x543210876). Note that credit
- * registers can not be shared between clients. */
-#define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_LSB		 0x18688
-/* [RW 4] Specify which of the credit registers the client is to be mapped
- * to. This register specifies bits 35:32 of the 36-bit value. Bits[3:0] are
- * for client 0; bits [35:32] are for client 8. For clients that are not
- * subject to WFQ credit blocking - their specifications here are not used.
- * This is a new register (with 2_) added in E3 B0 to accommodate the 9
- * input clients to ETS arbiter. The reset default is set for management and
- * debug to use credit registers 6, 7, and 8, respectively, and COSes 0-5 to
- * use credit registers 0-5 respectively (0x543210876). Note that credit
- * registers can not be shared between clients. */
-#define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_MSB		 0x1868c
-/* [RW 5] Specify whether the client competes directly in the strict
- * priority arbiter. The bits are mapped according to client ID (client IDs
- * are defined in tx_arb_priority_client). Default value is set to enable
- * strict priorities for clients 0-2 -- management and debug traffic. */
-#define NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT			 0x180e8
-/* [RW 5] Specify whether the client is subject to WFQ credit blocking. The
- * bits are mapped according to client ID (client IDs are defined in
- * tx_arb_priority_client). Default value is 0 for not using WFQ credit
- * blocking. */
-#define NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ		 0x180ec
-/* [RW 32] Specify the upper bound that credit register 0 is allowed to
- * reach. */
-#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0			 0x1810c
-#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1			 0x18110
-#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_2			 0x18114
-#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_3			 0x18118
-#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_4			 0x1811c
-#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_5			 0x186a0
-#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_6			 0x186a4
-#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_7			 0x186a8
-#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_8			 0x186ac
-/* [RW 32] Specify the weight (in bytes) to be added to credit register 0
- * when it is time to increment. */
-#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0			 0x180f8
-#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1			 0x180fc
-#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2			 0x18100
-#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3			 0x18104
-#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4			 0x18108
-#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5			 0x18690
-#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_6			 0x18694
-#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_7			 0x18698
-#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_8			 0x1869c
-/* [RW 12] Specify the number of strict priority arbitration slots between
- * two round-robin arbitration slots to avoid starvation. A value of 0 means
- * no strict priority cycles - the strict priority with anti-starvation
- * arbiter becomes a round-robin arbiter. */
-#define NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS			 0x180f4
-/* [RW 15] Specify the client number to be assigned to each priority of the
- * strict priority arbiter. Priority 0 is the highest priority. Bits [2:0]
- * are for priority 0 client; bits [14:12] are for priority 4 client. The
- * clients are assigned the following IDs: 0-management; 1-debug traffic
- * from this port; 2-debug traffic from other port; 3-COS0 traffic; 4-COS1
- * traffic. The reset value[14:0] is set to 0x4688 (15'b100_011_010_001_000)
- * for management at priority 0; debug traffic at priorities 1 and 2; COS0
- * traffic at priority 3; and COS1 traffic at priority 4. */
-#define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT			 0x180e4
-/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
- * Ethernet header. */
-#define NIG_REG_P1_HDRS_AFTER_BASIC				 0x1818c
-#define NIG_REG_P1_LLH_FUNC_MEM2				 0x184c0
-#define NIG_REG_P1_LLH_FUNC_MEM2_ENABLE			 0x18460
-/* [RW 32] Specify the client number to be assigned to each priority of the
- * strict priority arbiter. This register specifies bits 31:0 of the 36-bit
- * value. Priority 0 is the highest priority. Bits [3:0] are for priority 0
- * client; bits [35-32] are for priority 8 client. The clients are assigned
- * the following IDs: 0-management; 1-debug traffic from this port; 2-debug
- * traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2 traffic;
- * 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. The reset value[35:0] is
- * set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
- * accommodate the 9 input clients to ETS arbiter. */
-#define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB			 0x18680
-/* [RW 4] Specify the client number to be assigned to each priority of the
- * strict priority arbiter. This register specifies bits 35:32 of the 36-bit
- * value. Priority 0 is the highest priority. Bits [3:0] are for priority 0
- * client; bits [35-32] are for priority 8 client. The clients are assigned
- * the following IDs: 0-management; 1-debug traffic from this port; 2-debug
- * traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2 traffic;
- * 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. The reset value[35:0] is
- * set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
- * accommodate the 9 input clients to ETS arbiter. */
-#define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB			 0x18684
-#define NIG_REG_P1_MAC_IN_EN					 0x185c0
-/* [RW 1] Output enable for TX MAC interface */
-#define NIG_REG_P1_MAC_OUT_EN					 0x185c4
-/* [RW 1] Output enable for TX PAUSE signal to the MAC. */
-#define NIG_REG_P1_MAC_PAUSE_OUT_EN				 0x185c8
-/* [RW 32] Eight 4-bit configurations for specifying which COS (0-15 for
- * future expansion) each priorty is to be mapped to. Bits 3:0 specify the
- * COS for priority 0. Bits 31:28 specify the COS for priority 7. The 3-bit
- * priority field is extracted from the outer-most VLAN in receive packet.
- * Only COS 0 and COS 1 are supported in E2. */
-#define NIG_REG_P1_PKT_PRIORITY_TO_COS				 0x181a8
-/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 0. A
- * priority is mapped to COS 0 when the corresponding mask bit is 1. More
- * than one bit may be set; allowing multiple priorities to be mapped to one
- * COS. */
-#define NIG_REG_P1_RX_COS0_PRIORITY_MASK			 0x181ac
-/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 1. A
- * priority is mapped to COS 1 when the corresponding mask bit is 1. More
- * than one bit may be set; allowing multiple priorities to be mapped to one
- * COS. */
-#define NIG_REG_P1_RX_COS1_PRIORITY_MASK			 0x181b0
-/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 2. A
- * priority is mapped to COS 2 when the corresponding mask bit is 1. More
- * than one bit may be set; allowing multiple priorities to be mapped to one
- * COS. */
-#define NIG_REG_P1_RX_COS2_PRIORITY_MASK			 0x186f8
-/* [R 1] RX FIFO for receiving data from MAC is empty. */
-#define NIG_REG_P1_RX_MACFIFO_EMPTY				 0x1858c
-/* [R 1] TLLH FIFO is empty. */
-#define NIG_REG_P1_TLLH_FIFO_EMPTY				 0x18338
-/* [RW 32] Specify which of the credit registers the client is to be mapped
- * to. This register specifies bits 31:0 of the 36-bit value. Bits[3:0] are
- * for client 0; bits [35:32] are for client 8. For clients that are not
- * subject to WFQ credit blocking - their specifications here are not used.
- * This is a new register (with 2_) added in E3 B0 to accommodate the 9
- * input clients to ETS arbiter. The reset default is set for management and
- * debug to use credit registers 6, 7, and 8, respectively, and COSes 0-5 to
- * use credit registers 0-5 respectively (0x543210876). Note that credit
- * registers can not be shared between clients. Note also that there are
- * only COS0-2 in port 1- there is a total of 6 clients in port 1. Only
- * credit registers 0-5 are valid. This register should be configured
- * appropriately before enabling WFQ. */
-#define NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_LSB		 0x186e8
-/* [RW 4] Specify which of the credit registers the client is to be mapped
- * to. This register specifies bits 35:32 of the 36-bit value. Bits[3:0] are
- * for client 0; bits [35:32] are for client 8. For clients that are not
- * subject to WFQ credit blocking - their specifications here are not used.
- * This is a new register (with 2_) added in E3 B0 to accommodate the 9
- * input clients to ETS arbiter. The reset default is set for management and
- * debug to use credit registers 6, 7, and 8, respectively, and COSes 0-5 to
- * use credit registers 0-5 respectively (0x543210876). Note that credit
- * registers can not be shared between clients. Note also that there are
- * only COS0-2 in port 1- there is a total of 6 clients in port 1. Only
- * credit registers 0-5 are valid. This register should be configured
- * appropriately before enabling WFQ. */
-#define NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_MSB		 0x186ec
-/* [RW 9] Specify whether the client competes directly in the strict
- * priority arbiter. The bits are mapped according to client ID (client IDs
- * are defined in tx_arb_priority_client2): 0-management; 1-debug traffic
- * from this port; 2-debug traffic from other port; 3-COS0 traffic; 4-COS1
- * traffic; 5-COS2 traffic; 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic.
- * Default value is set to enable strict priorities for all clients. */
-#define NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT			 0x18234
-/* [RW 9] Specify whether the client is subject to WFQ credit blocking. The
- * bits are mapped according to client ID (client IDs are defined in
- * tx_arb_priority_client2): 0-management; 1-debug traffic from this port;
- * 2-debug traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2
- * traffic; 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. Default value is
- * 0 for not using WFQ credit blocking. */
-#define NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ			 0x18238
-#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_0			 0x18258
-#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_1			 0x1825c
-#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_2			 0x18260
-#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_3			 0x18264
-#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_4			 0x18268
-#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_5			 0x186f4
-/* [RW 32] Specify the weight (in bytes) to be added to credit register 0
- * when it is time to increment. */
-#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0			 0x18244
-#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1			 0x18248
-#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2			 0x1824c
-#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_3			 0x18250
-#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_4			 0x18254
-#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_5			 0x186f0
-/* [RW 12] Specify the number of strict priority arbitration slots between
-   two round-robin arbitration slots to avoid starvation. A value of 0 means
-   no strict priority cycles - the strict priority with anti-starvation
-   arbiter becomes a round-robin arbiter. */
-#define NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS			 0x18240
-/* [RW 32] Specify the client number to be assigned to each priority of the
-   strict priority arbiter. This register specifies bits 31:0 of the 36-bit
-   value. Priority 0 is the highest priority. Bits [3:0] are for priority 0
-   client; bits [35-32] are for priority 8 client. The clients are assigned
-   the following IDs: 0-management; 1-debug traffic from this port; 2-debug
-   traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2 traffic;
-   6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. The reset value[35:0] is
-   set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
-   accommodate the 9 input clients to ETS arbiter. Note that this register
-   is the same as the one for port 0, except that port 1 only has COS 0-2
-   traffic. There is no traffic for COS 3-5 of port 1. */
-#define NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB			 0x186e0
-/* [RW 4] Specify the client number to be assigned to each priority of the
-   strict priority arbiter. This register specifies bits 35:32 of the 36-bit
-   value. Priority 0 is the highest priority. Bits [3:0] are for priority 0
-   client; bits [35-32] are for priority 8 client. The clients are assigned
-   the following IDs: 0-management; 1-debug traffic from this port; 2-debug
-   traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2 traffic;
-   6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. The reset value[35:0] is
-   set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
-   accommodate the 9 input clients to ETS arbiter. Note that this register
-   is the same as the one for port 0, except that port 1 only has COS 0-2
-   traffic. There is no traffic for COS 3-5 of port 1. */
-#define NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB			 0x186e4
-/* [R 1] TX FIFO for transmitting data to MAC is empty. */
-#define NIG_REG_P1_TX_MACFIFO_EMPTY				 0x18594
-/* [R 1] FIFO empty status of the MCP TX FIFO used for storing MCP packets
-   forwarded to the host. */
-#define NIG_REG_P1_TX_MNG_HOST_FIFO_EMPTY			 0x182b8
-/* [RW 32] Specify the upper bound that credit register 0 is allowed to
- * reach. */
-/* [RW 1] Pause enable for port0. This register may get 1 only when
-   ~safc_enable.safc_enable = 0 and ppp_enable.ppp_enable =0 for the same
-   port */
-#define NIG_REG_PAUSE_ENABLE_0					 0x160c0
-#define NIG_REG_PAUSE_ENABLE_1					 0x160c4
-/* [RW 1] Input enable for RX PBF LP IF */
-#define NIG_REG_PBF_LB_IN_EN					 0x100b4
-/* [RW 1] Value of this register will be transmitted to port swap when
-   ~nig_registers_strap_override.strap_override =1 */
-#define NIG_REG_PORT_SWAP					 0x10394
-/* [RW 1] PPP enable for port0. This register may get 1 only when
- * ~safc_enable.safc_enable = 0 and pause_enable.pause_enable =0 for the
- * same port */
-#define NIG_REG_PPP_ENABLE_0					 0x160b0
-#define NIG_REG_PPP_ENABLE_1					 0x160b4
-/* [RW 1] output enable for RX parser descriptor IF */
-#define NIG_REG_PRS_EOP_OUT_EN					 0x10104
-/* [RW 1] Input enable for RX parser request IF */
-#define NIG_REG_PRS_REQ_IN_EN					 0x100b8
-/* [RW 5] control to serdes - CL45 DEVAD */
-#define NIG_REG_SERDES0_CTRL_MD_DEVAD				 0x10370
-/* [RW 1] control to serdes; 0 - clause 45; 1 - clause 22 */
-#define NIG_REG_SERDES0_CTRL_MD_ST				 0x1036c
-/* [RW 5] control to serdes - CL22 PHY_ADD and CL45 PRTAD */
-#define NIG_REG_SERDES0_CTRL_PHY_ADDR				 0x10374
-/* [R 1] status from serdes0 that inputs to interrupt logic of link status */
-#define NIG_REG_SERDES0_STATUS_LINK_STATUS			 0x10578
-/* [R 32] Rx statistics : In user packets discarded due to BRB backpressure
-   for port0 */
-#define NIG_REG_STAT0_BRB_DISCARD				 0x105f0
-/* [R 32] Rx statistics : In user packets truncated due to BRB backpressure
-   for port0 */
-#define NIG_REG_STAT0_BRB_TRUNCATE				 0x105f8
-/* [WB_R 36] Tx statistics : Number of packets from emac0 or bmac0 that
-   between 1024 and 1522 bytes for port0 */
-#define NIG_REG_STAT0_EGRESS_MAC_PKT0				 0x10750
-/* [WB_R 36] Tx statistics : Number of packets from emac0 or bmac0 that
-   between 1523 bytes and above for port0 */
-#define NIG_REG_STAT0_EGRESS_MAC_PKT1				 0x10760
-/* [R 32] Rx statistics : In user packets discarded due to BRB backpressure
-   for port1 */
-#define NIG_REG_STAT1_BRB_DISCARD				 0x10628
-/* [WB_R 36] Tx statistics : Number of packets from emac1 or bmac1 that
-   between 1024 and 1522 bytes for port1 */
-#define NIG_REG_STAT1_EGRESS_MAC_PKT0				 0x107a0
-/* [WB_R 36] Tx statistics : Number of packets from emac1 or bmac1 that
-   between 1523 bytes and above for port1 */
-#define NIG_REG_STAT1_EGRESS_MAC_PKT1				 0x107b0
-/* [WB_R 64] Rx statistics : User octets received for LP */
-#define NIG_REG_STAT2_BRB_OCTET 				 0x107e0
-#define NIG_REG_STATUS_INTERRUPT_PORT0				 0x10328
-#define NIG_REG_STATUS_INTERRUPT_PORT1				 0x1032c
-/* [RW 1] port swap mux selection. If this register equal to 0 then port
-   swap is equal to SPIO pin that inputs from ifmux_serdes_swap. If 1 then
-   ort swap is equal to ~nig_registers_port_swap.port_swap */
-#define NIG_REG_STRAP_OVERRIDE					 0x10398
-/* [RW 1] output enable for RX_XCM0 IF */
-#define NIG_REG_XCM0_OUT_EN					 0x100f0
-/* [RW 1] output enable for RX_XCM1 IF */
-#define NIG_REG_XCM1_OUT_EN					 0x100f4
-/* [RW 1] control to xgxs - remote PHY in-band MDIO */
-#define NIG_REG_XGXS0_CTRL_EXTREMOTEMDIOST			 0x10348
-/* [RW 5] control to xgxs - CL45 DEVAD */
-#define NIG_REG_XGXS0_CTRL_MD_DEVAD				 0x1033c
-/* [RW 1] control to xgxs; 0 - clause 45; 1 - clause 22 */
-#define NIG_REG_XGXS0_CTRL_MD_ST				 0x10338
-/* [RW 5] control to xgxs - CL22 PHY_ADD and CL45 PRTAD */
-#define NIG_REG_XGXS0_CTRL_PHY_ADDR				 0x10340
-/* [R 1] status from xgxs0 that inputs to interrupt logic of link10g. */
-#define NIG_REG_XGXS0_STATUS_LINK10G				 0x10680
-/* [R 4] status from xgxs0 that inputs to interrupt logic of link status */
-#define NIG_REG_XGXS0_STATUS_LINK_STATUS			 0x10684
-/* [RW 2] selection for XGXS lane of port 0 in NIG_MUX block */
-#define NIG_REG_XGXS_LANE_SEL_P0				 0x102e8
-/* [RW 1] selection for port0 for NIG_MUX block : 0 = SerDes; 1 = XGXS */
-#define NIG_REG_XGXS_SERDES0_MODE_SEL				 0x102e0
-#define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_MI_INT  (0x1<<0)
-#define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS (0x1<<9)
-#define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G	 (0x1<<15)
-#define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS  (0xf<<18)
-#define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE 18
-/* [RW 31] The upper bound of the weight of COS0 in the ETS command arbiter. */
-#define PBF_REG_COS0_UPPER_BOUND				 0x15c05c
-/* [RW 31] The upper bound of the weight of COS0 in the ETS command arbiter
- * of port 0. */
-#define PBF_REG_COS0_UPPER_BOUND_P0				 0x15c2cc
-/* [RW 31] The upper bound of the weight of COS0 in the ETS command arbiter
- * of port 1. */
-#define PBF_REG_COS0_UPPER_BOUND_P1				 0x15c2e4
-/* [RW 31] The weight of COS0 in the ETS command arbiter. */
-#define PBF_REG_COS0_WEIGHT					 0x15c054
-/* [RW 31] The weight of COS0 in port 0 ETS command arbiter. */
-#define PBF_REG_COS0_WEIGHT_P0					 0x15c2a8
-/* [RW 31] The weight of COS0 in port 1 ETS command arbiter. */
-#define PBF_REG_COS0_WEIGHT_P1					 0x15c2c0
-/* [RW 31] The upper bound of the weight of COS1 in the ETS command arbiter. */
-#define PBF_REG_COS1_UPPER_BOUND				 0x15c060
-/* [RW 31] The weight of COS1 in the ETS command arbiter. */
-#define PBF_REG_COS1_WEIGHT					 0x15c058
-/* [RW 31] The weight of COS1 in port 0 ETS command arbiter. */
-#define PBF_REG_COS1_WEIGHT_P0					 0x15c2ac
-/* [RW 31] The weight of COS1 in port 1 ETS command arbiter. */
-#define PBF_REG_COS1_WEIGHT_P1					 0x15c2c4
-/* [RW 31] The weight of COS2 in port 0 ETS command arbiter. */
-#define PBF_REG_COS2_WEIGHT_P0					 0x15c2b0
-/* [RW 31] The weight of COS2 in port 1 ETS command arbiter. */
-#define PBF_REG_COS2_WEIGHT_P1					 0x15c2c8
-/* [RW 31] The weight of COS3 in port 0 ETS command arbiter. */
-#define PBF_REG_COS3_WEIGHT_P0					 0x15c2b4
-/* [RW 31] The weight of COS4 in port 0 ETS command arbiter. */
-#define PBF_REG_COS4_WEIGHT_P0					 0x15c2b8
-/* [RW 31] The weight of COS5 in port 0 ETS command arbiter. */
-#define PBF_REG_COS5_WEIGHT_P0					 0x15c2bc
-/* [R 11] Current credit for the LB queue in the tx port buffers in 16 byte
- * lines. */
-#define PBF_REG_CREDIT_LB_Q					 0x140338
-/* [R 11] Current credit for queue 0 in the tx port buffers in 16 byte
- * lines. */
-#define PBF_REG_CREDIT_Q0					 0x14033c
-/* [R 11] Current credit for queue 1 in the tx port buffers in 16 byte
- * lines. */
-#define PBF_REG_CREDIT_Q1					 0x140340
-/* [RW 1] Disable processing further tasks from port 0 (after ending the
-   current task in process). */
-#define PBF_REG_DISABLE_NEW_TASK_PROC_P0			 0x14005c
-/* [RW 1] Disable processing further tasks from port 1 (after ending the
-   current task in process). */
-#define PBF_REG_DISABLE_NEW_TASK_PROC_P1			 0x140060
-/* [RW 1] Disable processing further tasks from port 4 (after ending the
-   current task in process). */
-#define PBF_REG_DISABLE_NEW_TASK_PROC_P4			 0x14006c
-#define PBF_REG_DISABLE_PF					 0x1402e8
-/* [RW 18] For port 0: For each client that is subject to WFQ (the
- * corresponding bit is 1); indicates to which of the credit registers this
- * client is mapped. For clients which are not credit blocked; their mapping
- * is dont care. */
-#define PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P0			 0x15c288
-/* [RW 9] For port 1: For each client that is subject to WFQ (the
- * corresponding bit is 1); indicates to which of the credit registers this
- * client is mapped. For clients which are not credit blocked; their mapping
- * is dont care. */
-#define PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P1			 0x15c28c
-/* [RW 6] For port 0: Bit per client to indicate if the client competes in
- * the strict priority arbiter directly (corresponding bit = 1); or first
- * goes to the RR arbiter (corresponding bit = 0); and then competes in the
- * lowest priority in the strict-priority arbiter. */
-#define PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0			 0x15c278
-/* [RW 3] For port 1: Bit per client to indicate if the client competes in
- * the strict priority arbiter directly (corresponding bit = 1); or first
- * goes to the RR arbiter (corresponding bit = 0); and then competes in the
- * lowest priority in the strict-priority arbiter. */
-#define PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1			 0x15c27c
-/* [RW 6] For port 0: Bit per client to indicate if the client is subject to
- * WFQ credit blocking (corresponding bit = 1). */
-#define PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0		 0x15c280
-/* [RW 3] For port 0: Bit per client to indicate if the client is subject to
- * WFQ credit blocking (corresponding bit = 1). */
-#define PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1		 0x15c284
-/* [RW 16] For port 0: The number of strict priority arbitration slots
- * between 2 RR arbitration slots. A value of 0 means no strict priority
- * cycles; i.e. the strict-priority w/ anti-starvation arbiter is a RR
- * arbiter. */
-#define PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P0			 0x15c2a0
-/* [RW 16] For port 1: The number of strict priority arbitration slots
- * between 2 RR arbitration slots. A value of 0 means no strict priority
- * cycles; i.e. the strict-priority w/ anti-starvation arbiter is a RR
- * arbiter. */
-#define PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P1			 0x15c2a4
-/* [RW 18] For port 0: Indicates which client is connected to each priority
- * in the strict-priority arbiter. Priority 0 is the highest priority, and
- * priority 5 is the lowest; to which the RR output is connected to (this is
- * not configurable). */
-#define PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0			 0x15c270
-/* [RW 9] For port 1: Indicates which client is connected to each priority
- * in the strict-priority arbiter. Priority 0 is the highest priority, and
- * priority 5 is the lowest; to which the RR output is connected to (this is
- * not configurable). */
-#define PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1			 0x15c274
-/* [RW 1] Indicates that ETS is performed between the COSes in the command
- * arbiter. If reset strict priority w/ anti-starvation will be performed
- * w/o WFQ. */
-#define PBF_REG_ETS_ENABLED					 0x15c050
-/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
- * Ethernet header. */
-#define PBF_REG_HDRS_AFTER_BASIC				 0x15c0a8
-/* [RW 6] Bit-map indicating which L2 hdrs may appear after L2 tag 0 */
-#define PBF_REG_HDRS_AFTER_TAG_0				 0x15c0b8
-/* [R 1] Removed for E3 B0 - Indicates which COS is conncted to the highest
- * priority in the command arbiter. */
-#define PBF_REG_HIGH_PRIORITY_COS_NUM				 0x15c04c
-#define PBF_REG_IF_ENABLE_REG					 0x140044
-/* [RW 1] Init bit. When set the initial credits are copied to the credit
-   registers (except the port credits). Should be set and then reset after
-   the configuration of the block has ended. */
-#define PBF_REG_INIT						 0x140000
-/* [RW 11] Initial credit for the LB queue in the tx port buffers in 16 byte
- * lines. */
-#define PBF_REG_INIT_CRD_LB_Q					 0x15c248
-/* [RW 11] Initial credit for queue 0 in the tx port buffers in 16 byte
- * lines. */
-#define PBF_REG_INIT_CRD_Q0					 0x15c230
-/* [RW 11] Initial credit for queue 1 in the tx port buffers in 16 byte
- * lines. */
-#define PBF_REG_INIT_CRD_Q1					 0x15c234
-/* [RW 1] Init bit for port 0. When set the initial credit of port 0 is
-   copied to the credit register. Should be set and then reset after the
-   configuration of the port has ended. */
-#define PBF_REG_INIT_P0 					 0x140004
-/* [RW 1] Init bit for port 1. When set the initial credit of port 1 is
-   copied to the credit register. Should be set and then reset after the
-   configuration of the port has ended. */
-#define PBF_REG_INIT_P1 					 0x140008
-/* [RW 1] Init bit for port 4. When set the initial credit of port 4 is
-   copied to the credit register. Should be set and then reset after the
-   configuration of the port has ended. */
-#define PBF_REG_INIT_P4 					 0x14000c
-/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
- * the LB queue. Reset upon init. */
-#define PBF_REG_INTERNAL_CRD_FREED_CNT_LB_Q			 0x140354
-/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
- * queue 0. Reset upon init. */
-#define PBF_REG_INTERNAL_CRD_FREED_CNT_Q0			 0x140358
-/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
- * queue 1. Reset upon init. */
-#define PBF_REG_INTERNAL_CRD_FREED_CNT_Q1			 0x14035c
-/* [RW 1] Enable for mac interface 0. */
-#define PBF_REG_MAC_IF0_ENABLE					 0x140030
-/* [RW 1] Enable for mac interface 1. */
-#define PBF_REG_MAC_IF1_ENABLE					 0x140034
-/* [RW 1] Enable for the loopback interface. */
-#define PBF_REG_MAC_LB_ENABLE					 0x140040
-/* [RW 6] Bit-map indicating which headers must appear in the packet */
-#define PBF_REG_MUST_HAVE_HDRS					 0x15c0c4
-/* [RW 16] The number of strict priority arbitration slots between 2 RR
- * arbitration slots. A value of 0 means no strict priority cycles; i.e. the
- * strict-priority w/ anti-starvation arbiter is a RR arbiter. */
-#define PBF_REG_NUM_STRICT_ARB_SLOTS				 0x15c064
-/* [RW 10] Port 0 threshold used by arbiter in 16 byte lines used when pause
-   not suppoterd. */
-#define PBF_REG_P0_ARB_THRSH					 0x1400e4
-/* [R 11] Current credit for port 0 in the tx port buffers in 16 byte lines. */
-#define PBF_REG_P0_CREDIT					 0x140200
-/* [RW 11] Initial credit for port 0 in the tx port buffers in 16 byte
-   lines. */
-#define PBF_REG_P0_INIT_CRD					 0x1400d0
-/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
- * port 0. Reset upon init. */
-#define PBF_REG_P0_INTERNAL_CRD_FREED_CNT			 0x140308
-/* [R 1] Removed for E3 B0 - Indication that pause is enabled for port 0. */
-#define PBF_REG_P0_PAUSE_ENABLE					 0x140014
-/* [R 8] Removed for E3 B0 - Number of tasks in port 0 task queue. */
-#define PBF_REG_P0_TASK_CNT					 0x140204
-/* [R 32] Removed for E3 B0 - Cyclic counter for number of 8 byte lines
- * freed from the task queue of port 0. Reset upon init. */
-#define PBF_REG_P0_TQ_LINES_FREED_CNT				 0x1402f0
-/* [R 12] Number of 8 bytes lines occupied in the task queue of port 0. */
-#define PBF_REG_P0_TQ_OCCUPANCY					 0x1402fc
-/* [R 11] Removed for E3 B0 - Current credit for port 1 in the tx port
- * buffers in 16 byte lines. */
-#define PBF_REG_P1_CREDIT					 0x140208
-/* [R 11] Removed for E3 B0 - Initial credit for port 0 in the tx port
- * buffers in 16 byte lines. */
-#define PBF_REG_P1_INIT_CRD					 0x1400d4
-/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
- * port 1. Reset upon init. */
-#define PBF_REG_P1_INTERNAL_CRD_FREED_CNT			 0x14030c
-/* [R 8] Removed for E3 B0 - Number of tasks in port 1 task queue. */
-#define PBF_REG_P1_TASK_CNT					 0x14020c
-/* [R 32] Removed for E3 B0 - Cyclic counter for number of 8 byte lines
- * freed from the task queue of port 1. Reset upon init. */
-#define PBF_REG_P1_TQ_LINES_FREED_CNT				 0x1402f4
-/* [R 12] Number of 8 bytes lines occupied in the task queue of port 1. */
-#define PBF_REG_P1_TQ_OCCUPANCY					 0x140300
-/* [R 11] Current credit for port 4 in the tx port buffers in 16 byte lines. */
-#define PBF_REG_P4_CREDIT					 0x140210
-/* [RW 11] Initial credit for port 4 in the tx port buffers in 16 byte
-   lines. */
-#define PBF_REG_P4_INIT_CRD					 0x1400e0
-/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
- * port 4. Reset upon init. */
-#define PBF_REG_P4_INTERNAL_CRD_FREED_CNT			 0x140310
-/* [R 8] Removed for E3 B0 - Number of tasks in port 4 task queue. */
-#define PBF_REG_P4_TASK_CNT					 0x140214
-/* [R 32] Removed for E3 B0 - Cyclic counter for number of 8 byte lines
- * freed from the task queue of port 4. Reset upon init. */
-#define PBF_REG_P4_TQ_LINES_FREED_CNT				 0x1402f8
-/* [R 12] Number of 8 bytes lines occupied in the task queue of port 4. */
-#define PBF_REG_P4_TQ_OCCUPANCY					 0x140304
-/* [RW 5] Interrupt mask register #0 read/write */
-#define PBF_REG_PBF_INT_MASK					 0x1401d4
-/* [R 5] Interrupt register #0 read */
-#define PBF_REG_PBF_INT_STS					 0x1401c8
-/* [RW 20] Parity mask register #0 read/write */
-#define PBF_REG_PBF_PRTY_MASK					 0x1401e4
-/* [RC 20] Parity register #0 read clear */
-#define PBF_REG_PBF_PRTY_STS_CLR				 0x1401dc
-/* [RW 16] The Ethernet type value for L2 tag 0 */
-#define PBF_REG_TAG_ETHERTYPE_0					 0x15c090
-/* [RW 4] The length of the info field for L2 tag 0. The length is between
- * 2B and 14B; in 2B granularity */
-#define PBF_REG_TAG_LEN_0					 0x15c09c
-/* [R 32] Cyclic counter for number of 8 byte lines freed from the LB task
- * queue. Reset upon init. */
-#define PBF_REG_TQ_LINES_FREED_CNT_LB_Q				 0x14038c
-/* [R 32] Cyclic counter for number of 8 byte lines freed from the task
- * queue 0. Reset upon init. */
-#define PBF_REG_TQ_LINES_FREED_CNT_Q0				 0x140390
-/* [R 32] Cyclic counter for number of 8 byte lines freed from task queue 1.
- * Reset upon init. */
-#define PBF_REG_TQ_LINES_FREED_CNT_Q1				 0x140394
-/* [R 13] Number of 8 bytes lines occupied in the task queue of the LB
- * queue. */
-#define PBF_REG_TQ_OCCUPANCY_LB_Q				 0x1403a8
-/* [R 13] Number of 8 bytes lines occupied in the task queue of queue 0. */
-#define PBF_REG_TQ_OCCUPANCY_Q0					 0x1403ac
-/* [R 13] Number of 8 bytes lines occupied in the task queue of queue 1. */
-#define PBF_REG_TQ_OCCUPANCY_Q1					 0x1403b0
-#define PB_REG_CONTROL						 0
-/* [RW 2] Interrupt mask register #0 read/write */
-#define PB_REG_PB_INT_MASK					 0x28
-/* [R 2] Interrupt register #0 read */
-#define PB_REG_PB_INT_STS					 0x1c
-/* [RW 4] Parity mask register #0 read/write */
-#define PB_REG_PB_PRTY_MASK					 0x38
-/* [R 4] Parity register #0 read */
-#define PB_REG_PB_PRTY_STS					 0x2c
-/* [RC 4] Parity register #0 read clear */
-#define PB_REG_PB_PRTY_STS_CLR					 0x30
-#define PGLUE_B_PGLUE_B_INT_STS_REG_ADDRESS_ERROR		 (0x1<<0)
-#define PGLUE_B_PGLUE_B_INT_STS_REG_CSSNOOP_FIFO_OVERFLOW	 (0x1<<8)
-#define PGLUE_B_PGLUE_B_INT_STS_REG_INCORRECT_RCV_BEHAVIOR	 (0x1<<1)
-#define PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_ERROR_ATTN		 (0x1<<6)
-#define PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_IN_TWO_RCBS_ATTN	 (0x1<<7)
-#define PGLUE_B_PGLUE_B_INT_STS_REG_VF_GRC_SPACE_VIOLATION_ATTN  (0x1<<4)
-#define PGLUE_B_PGLUE_B_INT_STS_REG_VF_LENGTH_VIOLATION_ATTN	 (0x1<<3)
-#define PGLUE_B_PGLUE_B_INT_STS_REG_VF_MSIX_BAR_VIOLATION_ATTN	 (0x1<<5)
-#define PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN		 (0x1<<2)
-/* [R 8] Config space A attention dirty bits. Each bit indicates that the
- * corresponding PF generates config space A attention. Set by PXP. Reset by
- * MCP writing 1 to icfg_space_a_request_clr. Note: register contains bits
- * from both paths. */
-#define PGLUE_B_REG_CFG_SPACE_A_REQUEST			 0x9010
-/* [R 8] Config space B attention dirty bits. Each bit indicates that the
- * corresponding PF generates config space B attention. Set by PXP. Reset by
- * MCP writing 1 to icfg_space_b_request_clr. Note: register contains bits
- * from both paths. */
-#define PGLUE_B_REG_CFG_SPACE_B_REQUEST			 0x9014
-/* [RW 1] Type A PF enable inbound interrupt table for CSDM. 0 - disable; 1
- * - enable. */
-#define PGLUE_B_REG_CSDM_INB_INT_A_PF_ENABLE			 0x9194
-/* [RW 18] Type B VF inbound interrupt table for CSDM: bits[17:9]-mask;
- * its[8:0]-address. Bits [1:0] must be zero (DW resolution address). */
-#define PGLUE_B_REG_CSDM_INB_INT_B_VF				 0x916c
-/* [RW 1] Type B VF enable inbound interrupt table for CSDM. 0 - disable; 1
- * - enable. */
-#define PGLUE_B_REG_CSDM_INB_INT_B_VF_ENABLE			 0x919c
-/* [RW 16] Start offset of CSDM zone A (queue zone) in the internal RAM */
-#define PGLUE_B_REG_CSDM_START_OFFSET_A			 0x9100
-/* [RW 16] Start offset of CSDM zone B (legacy zone) in the internal RAM */
-#define PGLUE_B_REG_CSDM_START_OFFSET_B			 0x9108
-/* [RW 5] VF Shift of CSDM zone B (legacy zone) in the internal RAM */
-#define PGLUE_B_REG_CSDM_VF_SHIFT_B				 0x9110
-/* [RW 1] 0 - Zone A size is 136x32B; 1 - Zone A size is 152x32B. */
-#define PGLUE_B_REG_CSDM_ZONE_A_SIZE_PF			 0x91ac
-/* [R 8] FLR request attention dirty bits for PFs 0 to 7. Each bit indicates
- * that the FLR register of the corresponding PF was set. Set by PXP. Reset
- * by MCP writing 1 to flr_request_pf_7_0_clr. Note: register contains bits
- * from both paths. */
-#define PGLUE_B_REG_FLR_REQUEST_PF_7_0				 0x9028
-/* [W 8] FLR request attention dirty bits clear for PFs 0 to 7. MCP writes 1
- * to a bit in this register in order to clear the corresponding bit in
- * flr_request_pf_7_0 register. Note: register contains bits from both
- * paths. */
-#define PGLUE_B_REG_FLR_REQUEST_PF_7_0_CLR			 0x9418
-/* [R 32] FLR request attention dirty bits for VFs 96 to 127. Each bit
- * indicates that the FLR register of the corresponding VF was set. Set by
- * PXP. Reset by MCP writing 1 to flr_request_vf_127_96_clr. */
-#define PGLUE_B_REG_FLR_REQUEST_VF_127_96			 0x9024
-/* [R 32] FLR request attention dirty bits for VFs 0 to 31. Each bit
- * indicates that the FLR register of the corresponding VF was set. Set by
- * PXP. Reset by MCP writing 1 to flr_request_vf_31_0_clr. */
-#define PGLUE_B_REG_FLR_REQUEST_VF_31_0			 0x9018
-/* [R 32] FLR request attention dirty bits for VFs 32 to 63. Each bit
- * indicates that the FLR register of the corresponding VF was set. Set by
- * PXP. Reset by MCP writing 1 to flr_request_vf_63_32_clr. */
-#define PGLUE_B_REG_FLR_REQUEST_VF_63_32			 0x901c
-/* [R 32] FLR request attention dirty bits for VFs 64 to 95. Each bit
- * indicates that the FLR register of the corresponding VF was set. Set by
- * PXP. Reset by MCP writing 1 to flr_request_vf_95_64_clr. */
-#define PGLUE_B_REG_FLR_REQUEST_VF_95_64			 0x9020
-/* [R 8] Each bit indicates an incorrect behavior in user RX interface. Bit
- * 0 - Target memory read arrived with a correctable error. Bit 1 - Target
- * memory read arrived with an uncorrectable error. Bit 2 - Configuration RW
- * arrived with a correctable error. Bit 3 - Configuration RW arrived with
- * an uncorrectable error. Bit 4 - Completion with Configuration Request
- * Retry Status. Bit 5 - Expansion ROM access received with a write request.
- * Bit 6 - Completion with pcie_rx_err of 0000; CMPL_STATUS of non-zero; and
- * pcie_rx_last not asserted. Bit 7 - Completion with pcie_rx_err of 1010;
- * and pcie_rx_last not asserted. */
-#define PGLUE_B_REG_INCORRECT_RCV_DETAILS			 0x9068
-#define PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER		 0x942c
-#define PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ		 0x9430
-#define PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_WRITE		 0x9434
-#define PGLUE_B_REG_INTERNAL_VFID_ENABLE			 0x9438
-/* [R 9] Interrupt register #0 read */
-#define PGLUE_B_REG_PGLUE_B_INT_STS				 0x9298
-/* [RC 9] Interrupt register #0 read clear */
-#define PGLUE_B_REG_PGLUE_B_INT_STS_CLR			 0x929c
-/* [RW 2] Parity mask register #0 read/write */
-#define PGLUE_B_REG_PGLUE_B_PRTY_MASK				 0x92b4
-/* [R 2] Parity register #0 read */
-#define PGLUE_B_REG_PGLUE_B_PRTY_STS				 0x92a8
-/* [RC 2] Parity register #0 read clear */
-#define PGLUE_B_REG_PGLUE_B_PRTY_STS_CLR			 0x92ac
-/* [R 13] Details of first request received with error. [2:0] - PFID. [3] -
- * VF_VALID. [9:4] - VFID. [11:10] - Error Code - 0 - Indicates Completion
- * Timeout of a User Tx non-posted request. 1 - unsupported request. 2 -
- * completer abort. 3 - Illegal value for this field. [12] valid - indicates
- * if there was a completion error since the last time this register was
- * cleared. */
-#define PGLUE_B_REG_RX_ERR_DETAILS				 0x9080
-/* [R 18] Details of first ATS Translation Completion request received with
- * error. [2:0] - PFID. [3] - VF_VALID. [9:4] - VFID. [11:10] - Error Code -
- * 0 - Indicates Completion Timeout of a User Tx non-posted request. 1 -
- * unsupported request. 2 - completer abort. 3 - Illegal value for this
- * field. [16:12] - ATC OTB EntryID. [17] valid - indicates if there was a
- * completion error since the last time this register was cleared. */
-#define PGLUE_B_REG_RX_TCPL_ERR_DETAILS			 0x9084
-/* [W 8] Debug only - Shadow BME bits clear for PFs 0 to 7. MCP writes 1 to
- * a bit in this register in order to clear the corresponding bit in
- * shadow_bme_pf_7_0 register. MCP should never use this unless a
- * work-around is needed. Note: register contains bits from both paths. */
-#define PGLUE_B_REG_SHADOW_BME_PF_7_0_CLR			 0x9458
-/* [R 8] SR IOV disabled attention dirty bits. Each bit indicates that the
- * VF enable register of the corresponding PF is written to 0 and was
- * previously 1. Set by PXP. Reset by MCP writing 1 to
- * sr_iov_disabled_request_clr. Note: register contains bits from both
- * paths. */
-#define PGLUE_B_REG_SR_IOV_DISABLED_REQUEST			 0x9030
-/* [R 32] Indicates the status of tags 32-63. 0 - tags is used - read
- * completion did not return yet. 1 - tag is unused. Same functionality as
- * pxp2_registers_pgl_exp_rom_data2 for tags 0-31. */
-#define PGLUE_B_REG_TAGS_63_32					 0x9244
-/* [RW 1] Type A PF enable inbound interrupt table for TSDM. 0 - disable; 1
- * - enable. */
-#define PGLUE_B_REG_TSDM_INB_INT_A_PF_ENABLE			 0x9170
-/* [RW 16] Start offset of TSDM zone A (queue zone) in the internal RAM */
-#define PGLUE_B_REG_TSDM_START_OFFSET_A			 0x90c4
-/* [RW 16] Start offset of TSDM zone B (legacy zone) in the internal RAM */
-#define PGLUE_B_REG_TSDM_START_OFFSET_B			 0x90cc
-/* [RW 5] VF Shift of TSDM zone B (legacy zone) in the internal RAM */
-#define PGLUE_B_REG_TSDM_VF_SHIFT_B				 0x90d4
-/* [RW 1] 0 - Zone A size is 136x32B; 1 - Zone A size is 152x32B. */
-#define PGLUE_B_REG_TSDM_ZONE_A_SIZE_PF			 0x91a0
-/* [R 32] Address [31:0] of first read request not submitted due to error */
-#define PGLUE_B_REG_TX_ERR_RD_ADD_31_0				 0x9098
-/* [R 32] Address [63:32] of first read request not submitted due to error */
-#define PGLUE_B_REG_TX_ERR_RD_ADD_63_32			 0x909c
-/* [R 31] Details of first read request not submitted due to error. [4:0]
- * VQID. [5] TREQ. 1 - Indicates the request is a Translation Request.
- * [20:8] - Length in bytes. [23:21] - PFID. [24] - VF_VALID. [30:25] -
- * VFID. */
-#define PGLUE_B_REG_TX_ERR_RD_DETAILS				 0x90a0
-/* [R 26] Details of first read request not submitted due to error. [15:0]
- * Request ID. [19:16] client ID. [20] - last SR. [24:21] - Error type -
- * [21] - Indicates was_error was set; [22] - Indicates BME was cleared;
- * [23] - Indicates FID_enable was cleared; [24] - Indicates VF with parent
- * PF FLR_request or IOV_disable_request dirty bit is set. [25] valid -
- * indicates if there was a request not submitted due to error since the
- * last time this register was cleared. */
-#define PGLUE_B_REG_TX_ERR_RD_DETAILS2				 0x90a4
-/* [R 32] Address [31:0] of first write request not submitted due to error */
-#define PGLUE_B_REG_TX_ERR_WR_ADD_31_0				 0x9088
-/* [R 32] Address [63:32] of first write request not submitted due to error */
-#define PGLUE_B_REG_TX_ERR_WR_ADD_63_32			 0x908c
-/* [R 31] Details of first write request not submitted due to error. [4:0]
- * VQID. [20:8] - Length in bytes. [23:21] - PFID. [24] - VF_VALID. [30:25]
- * - VFID. */
-#define PGLUE_B_REG_TX_ERR_WR_DETAILS				 0x9090
-/* [R 26] Details of first write request not submitted due to error. [15:0]
- * Request ID. [19:16] client ID. [20] - last SR. [24:21] - Error type -
- * [21] - Indicates was_error was set; [22] - Indicates BME was cleared;
- * [23] - Indicates FID_enable was cleared; [24] - Indicates VF with parent
- * PF FLR_request or IOV_disable_request dirty bit is set. [25] valid -
- * indicates if there was a request not submitted due to error since the
- * last time this register was cleared. */
-#define PGLUE_B_REG_TX_ERR_WR_DETAILS2				 0x9094
-/* [RW 10] Type A PF/VF inbound interrupt table for USDM: bits[9:5]-mask;
- * its[4:0]-address relative to start_offset_a. Bits [1:0] can have any
- * value (Byte resolution address). */
-#define PGLUE_B_REG_USDM_INB_INT_A_0				 0x9128
-#define PGLUE_B_REG_USDM_INB_INT_A_1				 0x912c
-#define PGLUE_B_REG_USDM_INB_INT_A_2				 0x9130
-#define PGLUE_B_REG_USDM_INB_INT_A_3				 0x9134
-#define PGLUE_B_REG_USDM_INB_INT_A_4				 0x9138
-#define PGLUE_B_REG_USDM_INB_INT_A_5				 0x913c
-#define PGLUE_B_REG_USDM_INB_INT_A_6				 0x9140
-/* [RW 1] Type A PF enable inbound interrupt table for USDM. 0 - disable; 1
- * - enable. */
-#define PGLUE_B_REG_USDM_INB_INT_A_PF_ENABLE			 0x917c
-/* [RW 1] Type A VF enable inbound interrupt table for USDM. 0 - disable; 1
- * - enable. */
-#define PGLUE_B_REG_USDM_INB_INT_A_VF_ENABLE			 0x9180
-/* [RW 1] Type B VF enable inbound interrupt table for USDM. 0 - disable; 1
- * - enable. */
-#define PGLUE_B_REG_USDM_INB_INT_B_VF_ENABLE			 0x9184
-/* [RW 16] Start offset of USDM zone A (queue zone) in the internal RAM */
-#define PGLUE_B_REG_USDM_START_OFFSET_A			 0x90d8
-/* [RW 16] Start offset of USDM zone B (legacy zone) in the internal RAM */
-#define PGLUE_B_REG_USDM_START_OFFSET_B			 0x90e0
-/* [RW 5] VF Shift of USDM zone B (legacy zone) in the internal RAM */
-#define PGLUE_B_REG_USDM_VF_SHIFT_B				 0x90e8
-/* [RW 1] 0 - Zone A size is 136x32B; 1 - Zone A size is 152x32B. */
-#define PGLUE_B_REG_USDM_ZONE_A_SIZE_PF			 0x91a4
-/* [R 26] Details of first target VF request accessing VF GRC space that
- * failed permission check. [14:0] Address. [15] w_nr: 0 - Read; 1 - Write.
- * [21:16] VFID. [24:22] - PFID. [25] valid - indicates if there was a
- * request accessing VF GRC space that failed permission check since the
- * last time this register was cleared. Permission checks are: function
- * permission; R/W permission; address range permission. */
-#define PGLUE_B_REG_VF_GRC_SPACE_VIOLATION_DETAILS		 0x9234
-/* [R 31] Details of first target VF request with length violation (too many
- * DWs) accessing BAR0. [12:0] Address in DWs (bits [14:2] of byte address).
- * [14:13] BAR. [20:15] VFID. [23:21] - PFID. [29:24] - Length in DWs. [30]
- * valid - indicates if there was a request with length violation since the
- * last time this register was cleared. Length violations: length of more
- * than 2DWs; length of 2DWs and address not QW aligned; window is GRC and
- * length is more than 1 DW. */
-#define PGLUE_B_REG_VF_LENGTH_VIOLATION_DETAILS		 0x9230
-/* [R 8] Was_error indication dirty bits for PFs 0 to 7. Each bit indicates
- * that there was a completion with uncorrectable error for the
- * corresponding PF. Set by PXP. Reset by MCP writing 1 to
- * was_error_pf_7_0_clr. */
-#define PGLUE_B_REG_WAS_ERROR_PF_7_0				 0x907c
-/* [W 8] Was_error indication dirty bits clear for PFs 0 to 7. MCP writes 1
- * to a bit in this register in order to clear the corresponding bit in
- * flr_request_pf_7_0 register. */
-#define PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR			 0x9470
-/* [R 32] Was_error indication dirty bits for VFs 96 to 127. Each bit
- * indicates that there was a completion with uncorrectable error for the
- * corresponding VF. Set by PXP. Reset by MCP writing 1 to
- * was_error_vf_127_96_clr. */
-#define PGLUE_B_REG_WAS_ERROR_VF_127_96			 0x9078
-/* [W 32] Was_error indication dirty bits clear for VFs 96 to 127. MCP
- * writes 1 to a bit in this register in order to clear the corresponding
- * bit in was_error_vf_127_96 register. */
-#define PGLUE_B_REG_WAS_ERROR_VF_127_96_CLR			 0x9474
-/* [R 32] Was_error indication dirty bits for VFs 0 to 31. Each bit
- * indicates that there was a completion with uncorrectable error for the
- * corresponding VF. Set by PXP. Reset by MCP writing 1 to
- * was_error_vf_31_0_clr. */
-#define PGLUE_B_REG_WAS_ERROR_VF_31_0				 0x906c
-/* [W 32] Was_error indication dirty bits clear for VFs 0 to 31. MCP writes
- * 1 to a bit in this register in order to clear the corresponding bit in
- * was_error_vf_31_0 register. */
-#define PGLUE_B_REG_WAS_ERROR_VF_31_0_CLR			 0x9478
-/* [R 32] Was_error indication dirty bits for VFs 32 to 63. Each bit
- * indicates that there was a completion with uncorrectable error for the
- * corresponding VF. Set by PXP. Reset by MCP writing 1 to
- * was_error_vf_63_32_clr. */
-#define PGLUE_B_REG_WAS_ERROR_VF_63_32				 0x9070
-/* [W 32] Was_error indication dirty bits clear for VFs 32 to 63. MCP writes
- * 1 to a bit in this register in order to clear the corresponding bit in
- * was_error_vf_63_32 register. */
-#define PGLUE_B_REG_WAS_ERROR_VF_63_32_CLR			 0x947c
-/* [R 32] Was_error indication dirty bits for VFs 64 to 95. Each bit
- * indicates that there was a completion with uncorrectable error for the
- * corresponding VF. Set by PXP. Reset by MCP writing 1 to
- * was_error_vf_95_64_clr. */
-#define PGLUE_B_REG_WAS_ERROR_VF_95_64				 0x9074
-/* [W 32] Was_error indication dirty bits clear for VFs 64 to 95. MCP writes
- * 1 to a bit in this register in order to clear the corresponding bit in
- * was_error_vf_95_64 register. */
-#define PGLUE_B_REG_WAS_ERROR_VF_95_64_CLR			 0x9480
-/* [RW 1] Type A PF enable inbound interrupt table for XSDM. 0 - disable; 1
- * - enable. */
-#define PGLUE_B_REG_XSDM_INB_INT_A_PF_ENABLE			 0x9188
-/* [RW 16] Start offset of XSDM zone A (queue zone) in the internal RAM */
-#define PGLUE_B_REG_XSDM_START_OFFSET_A			 0x90ec
-/* [RW 16] Start offset of XSDM zone B (legacy zone) in the internal RAM */
-#define PGLUE_B_REG_XSDM_START_OFFSET_B			 0x90f4
-/* [RW 5] VF Shift of XSDM zone B (legacy zone) in the internal RAM */
-#define PGLUE_B_REG_XSDM_VF_SHIFT_B				 0x90fc
-/* [RW 1] 0 - Zone A size is 136x32B; 1 - Zone A size is 152x32B. */
-#define PGLUE_B_REG_XSDM_ZONE_A_SIZE_PF			 0x91a8
-#define PRS_REG_A_PRSU_20					 0x40134
-/* [R 8] debug only: CFC load request current credit. Transaction based. */
-#define PRS_REG_CFC_LD_CURRENT_CREDIT				 0x40164
-/* [R 8] debug only: CFC search request current credit. Transaction based. */
-#define PRS_REG_CFC_SEARCH_CURRENT_CREDIT			 0x40168
-/* [RW 6] The initial credit for the search message to the CFC interface.
-   Credit is transaction based. */
-#define PRS_REG_CFC_SEARCH_INITIAL_CREDIT			 0x4011c
-/* [RW 24] CID for port 0 if no match */
-#define PRS_REG_CID_PORT_0					 0x400fc
-/* [RW 32] The CM header for flush message where 'load existed' bit in CFC
-   load response is reset and packet type is 0. Used in packet start message
-   to TCM. */
-#define PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_0			 0x400dc
-#define PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_1			 0x400e0
-#define PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_2			 0x400e4
-#define PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_3			 0x400e8
-#define PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_4			 0x400ec
-#define PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_5			 0x400f0
-/* [RW 32] The CM header for flush message where 'load existed' bit in CFC
-   load response is set and packet type is 0. Used in packet start message
-   to TCM. */
-#define PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_0			 0x400bc
-#define PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_1			 0x400c0
-#define PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_2			 0x400c4
-#define PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_3			 0x400c8
-#define PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_4			 0x400cc
-#define PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_5			 0x400d0
-/* [RW 32] The CM header for a match and packet type 1 for loopback port.
-   Used in packet start message to TCM. */
-#define PRS_REG_CM_HDR_LOOPBACK_TYPE_1				 0x4009c
-#define PRS_REG_CM_HDR_LOOPBACK_TYPE_2				 0x400a0
-#define PRS_REG_CM_HDR_LOOPBACK_TYPE_3				 0x400a4
-#define PRS_REG_CM_HDR_LOOPBACK_TYPE_4				 0x400a8
-/* [RW 32] The CM header for a match and packet type 0. Used in packet start
-   message to TCM. */
-#define PRS_REG_CM_HDR_TYPE_0					 0x40078
-#define PRS_REG_CM_HDR_TYPE_1					 0x4007c
-#define PRS_REG_CM_HDR_TYPE_2					 0x40080
-#define PRS_REG_CM_HDR_TYPE_3					 0x40084
-#define PRS_REG_CM_HDR_TYPE_4					 0x40088
-/* [RW 32] The CM header in case there was not a match on the connection */
-#define PRS_REG_CM_NO_MATCH_HDR 				 0x400b8
-/* [RW 1] Indicates if in e1hov mode. 0=non-e1hov mode; 1=e1hov mode. */
-#define PRS_REG_E1HOV_MODE					 0x401c8
-/* [RW 8] The 8-bit event ID for a match and packet type 1. Used in packet
-   start message to TCM. */
-#define PRS_REG_EVENT_ID_1					 0x40054
-#define PRS_REG_EVENT_ID_2					 0x40058
-#define PRS_REG_EVENT_ID_3					 0x4005c
-/* [RW 16] The Ethernet type value for FCoE */
-#define PRS_REG_FCOE_TYPE					 0x401d0
-/* [RW 8] Context region for flush packet with packet type 0. Used in CFC
-   load request message. */
-#define PRS_REG_FLUSH_REGIONS_TYPE_0				 0x40004
-#define PRS_REG_FLUSH_REGIONS_TYPE_1				 0x40008
-#define PRS_REG_FLUSH_REGIONS_TYPE_2				 0x4000c
-#define PRS_REG_FLUSH_REGIONS_TYPE_3				 0x40010
-#define PRS_REG_FLUSH_REGIONS_TYPE_4				 0x40014
-#define PRS_REG_FLUSH_REGIONS_TYPE_5				 0x40018
-#define PRS_REG_FLUSH_REGIONS_TYPE_6				 0x4001c
-#define PRS_REG_FLUSH_REGIONS_TYPE_7				 0x40020
-/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
- * Ethernet header. */
-#define PRS_REG_HDRS_AFTER_BASIC				 0x40238
-/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
- * Ethernet header for port 0 packets. */
-#define PRS_REG_HDRS_AFTER_BASIC_PORT_0				 0x40270
-#define PRS_REG_HDRS_AFTER_BASIC_PORT_1				 0x40290
-/* [R 6] Bit-map indicating which L2 hdrs may appear after L2 tag 0 */
-#define PRS_REG_HDRS_AFTER_TAG_0				 0x40248
-/* [RW 6] Bit-map indicating which L2 hdrs may appear after L2 tag 0 for
- * port 0 packets */
-#define PRS_REG_HDRS_AFTER_TAG_0_PORT_0				 0x40280
-#define PRS_REG_HDRS_AFTER_TAG_0_PORT_1				 0x402a0
-/* [RW 4] The increment value to send in the CFC load request message */
-#define PRS_REG_INC_VALUE					 0x40048
-/* [RW 6] Bit-map indicating which headers must appear in the packet */
-#define PRS_REG_MUST_HAVE_HDRS					 0x40254
-/* [RW 6] Bit-map indicating which headers must appear in the packet for
- * port 0 packets */
-#define PRS_REG_MUST_HAVE_HDRS_PORT_0				 0x4028c
-#define PRS_REG_MUST_HAVE_HDRS_PORT_1				 0x402ac
-#define PRS_REG_NIC_MODE					 0x40138
-/* [RW 8] The 8-bit event ID for cases where there is no match on the
-   connection. Used in packet start message to TCM. */
-#define PRS_REG_NO_MATCH_EVENT_ID				 0x40070
-/* [ST 24] The number of input CFC flush packets */
-#define PRS_REG_NUM_OF_CFC_FLUSH_MESSAGES			 0x40128
-/* [ST 32] The number of cycles the Parser halted its operation since it
-   could not allocate the next serial number */
-#define PRS_REG_NUM_OF_DEAD_CYCLES				 0x40130
-/* [ST 24] The number of input packets */
-#define PRS_REG_NUM_OF_PACKETS					 0x40124
-/* [ST 24] The number of input transparent flush packets */
-#define PRS_REG_NUM_OF_TRANSPARENT_FLUSH_MESSAGES		 0x4012c
-/* [RW 8] Context region for received Ethernet packet with a match and
-   packet type 0. Used in CFC load request message */
-#define PRS_REG_PACKET_REGIONS_TYPE_0				 0x40028
-#define PRS_REG_PACKET_REGIONS_TYPE_1				 0x4002c
-#define PRS_REG_PACKET_REGIONS_TYPE_2				 0x40030
-#define PRS_REG_PACKET_REGIONS_TYPE_3				 0x40034
-#define PRS_REG_PACKET_REGIONS_TYPE_4				 0x40038
-#define PRS_REG_PACKET_REGIONS_TYPE_5				 0x4003c
-#define PRS_REG_PACKET_REGIONS_TYPE_6				 0x40040
-#define PRS_REG_PACKET_REGIONS_TYPE_7				 0x40044
-/* [R 2] debug only: Number of pending requests for CAC on port 0. */
-#define PRS_REG_PENDING_BRB_CAC0_RQ				 0x40174
-/* [R 2] debug only: Number of pending requests for header parsing. */
-#define PRS_REG_PENDING_BRB_PRS_RQ				 0x40170
-/* [R 1] Interrupt register #0 read */
-#define PRS_REG_PRS_INT_STS					 0x40188
-/* [RW 8] Parity mask register #0 read/write */
-#define PRS_REG_PRS_PRTY_MASK					 0x401a4
-/* [R 8] Parity register #0 read */
-#define PRS_REG_PRS_PRTY_STS					 0x40198
-/* [RC 8] Parity register #0 read clear */
-#define PRS_REG_PRS_PRTY_STS_CLR				 0x4019c
-/* [RW 8] Context region for pure acknowledge packets. Used in CFC load
-   request message */
-#define PRS_REG_PURE_REGIONS					 0x40024
-/* [R 32] debug only: Serial number status lsb 32 bits. '1' indicates this
-   serail number was released by SDM but cannot be used because a previous
-   serial number was not released. */
-#define PRS_REG_SERIAL_NUM_STATUS_LSB				 0x40154
-/* [R 32] debug only: Serial number status msb 32 bits. '1' indicates this
-   serail number was released by SDM but cannot be used because a previous
-   serial number was not released. */
-#define PRS_REG_SERIAL_NUM_STATUS_MSB				 0x40158
-/* [R 4] debug only: SRC current credit. Transaction based. */
-#define PRS_REG_SRC_CURRENT_CREDIT				 0x4016c
-/* [RW 16] The Ethernet type value for L2 tag 0 */
-#define PRS_REG_TAG_ETHERTYPE_0					 0x401d4
-/* [RW 4] The length of the info field for L2 tag 0. The length is between
- * 2B and 14B; in 2B granularity */
-#define PRS_REG_TAG_LEN_0					 0x4022c
-/* [R 8] debug only: TCM current credit. Cycle based. */
-#define PRS_REG_TCM_CURRENT_CREDIT				 0x40160
-/* [R 8] debug only: TSDM current credit. Transaction based. */
-#define PRS_REG_TSDM_CURRENT_CREDIT				 0x4015c
-#define PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT			 (0x1<<19)
-#define PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF			 (0x1<<20)
-#define PXP2_PXP2_INT_MASK_0_REG_PGL_PCIE_ATTN			 (0x1<<22)
-#define PXP2_PXP2_INT_MASK_0_REG_PGL_READ_BLOCKED		 (0x1<<23)
-#define PXP2_PXP2_INT_MASK_0_REG_PGL_WRITE_BLOCKED		 (0x1<<24)
-#define PXP2_PXP2_INT_STS_0_REG_WR_PGLUE_EOP_ERROR		 (0x1<<7)
-#define PXP2_PXP2_INT_STS_CLR_0_REG_WR_PGLUE_EOP_ERROR		 (0x1<<7)
-/* [R 6] Debug only: Number of used entries in the data FIFO */
-#define PXP2_REG_HST_DATA_FIFO_STATUS				 0x12047c
-/* [R 7] Debug only: Number of used entries in the header FIFO */
-#define PXP2_REG_HST_HEADER_FIFO_STATUS				 0x120478
-#define PXP2_REG_PGL_ADDR_88_F0					 0x120534
-/* [R 32] GRC address for configuration access to PCIE config address 0x88.
- * any write to this PCIE address will cause a GRC write access to the
- * address that's in t this register */
-#define PXP2_REG_PGL_ADDR_88_F1					 0x120544
-#define PXP2_REG_PGL_ADDR_8C_F0					 0x120538
-/* [R 32] GRC address for configuration access to PCIE config address 0x8c.
- * any write to this PCIE address will cause a GRC write access to the
- * address that's in t this register */
-#define PXP2_REG_PGL_ADDR_8C_F1					 0x120548
-#define PXP2_REG_PGL_ADDR_90_F0					 0x12053c
-/* [R 32] GRC address for configuration access to PCIE config address 0x90.
- * any write to this PCIE address will cause a GRC write access to the
- * address that's in t this register */
-#define PXP2_REG_PGL_ADDR_90_F1					 0x12054c
-#define PXP2_REG_PGL_ADDR_94_F0					 0x120540
-/* [R 32] GRC address for configuration access to PCIE config address 0x94.
- * any write to this PCIE address will cause a GRC write access to the
- * address that's in t this register */
-#define PXP2_REG_PGL_ADDR_94_F1					 0x120550
-#define PXP2_REG_PGL_CONTROL0					 0x120490
-#define PXP2_REG_PGL_CONTROL1					 0x120514
-#define PXP2_REG_PGL_DEBUG					 0x120520
-/* [RW 32] third dword data of expansion rom request. this register is
-   special. reading from it provides a vector outstanding read requests. if
-   a bit is zero it means that a read request on the corresponding tag did
-   not finish yet (not all completions have arrived for it) */
-#define PXP2_REG_PGL_EXP_ROM2					 0x120808
-/* [RW 32] Inbound interrupt table for CSDM: bits[31:16]-mask;
-   its[15:0]-address */
-#define PXP2_REG_PGL_INT_CSDM_0 				 0x1204f4
-#define PXP2_REG_PGL_INT_CSDM_1 				 0x1204f8
-#define PXP2_REG_PGL_INT_CSDM_2 				 0x1204fc
-#define PXP2_REG_PGL_INT_CSDM_3 				 0x120500
-#define PXP2_REG_PGL_INT_CSDM_4 				 0x120504
-#define PXP2_REG_PGL_INT_CSDM_5 				 0x120508
-#define PXP2_REG_PGL_INT_CSDM_6 				 0x12050c
-#define PXP2_REG_PGL_INT_CSDM_7 				 0x120510
-/* [RW 32] Inbound interrupt table for TSDM: bits[31:16]-mask;
-   its[15:0]-address */
-#define PXP2_REG_PGL_INT_TSDM_0 				 0x120494
-#define PXP2_REG_PGL_INT_TSDM_1 				 0x120498
-#define PXP2_REG_PGL_INT_TSDM_2 				 0x12049c
-#define PXP2_REG_PGL_INT_TSDM_3 				 0x1204a0
-#define PXP2_REG_PGL_INT_TSDM_4 				 0x1204a4
-#define PXP2_REG_PGL_INT_TSDM_5 				 0x1204a8
-#define PXP2_REG_PGL_INT_TSDM_6 				 0x1204ac
-#define PXP2_REG_PGL_INT_TSDM_7 				 0x1204b0
-/* [RW 32] Inbound interrupt table for USDM: bits[31:16]-mask;
-   its[15:0]-address */
-#define PXP2_REG_PGL_INT_USDM_0 				 0x1204b4
-#define PXP2_REG_PGL_INT_USDM_1 				 0x1204b8
-#define PXP2_REG_PGL_INT_USDM_2 				 0x1204bc
-#define PXP2_REG_PGL_INT_USDM_3 				 0x1204c0
-#define PXP2_REG_PGL_INT_USDM_4 				 0x1204c4
-#define PXP2_REG_PGL_INT_USDM_5 				 0x1204c8
-#define PXP2_REG_PGL_INT_USDM_6 				 0x1204cc
-#define PXP2_REG_PGL_INT_USDM_7 				 0x1204d0
-/* [RW 32] Inbound interrupt table for XSDM: bits[31:16]-mask;
-   its[15:0]-address */
-#define PXP2_REG_PGL_INT_XSDM_0 				 0x1204d4
-#define PXP2_REG_PGL_INT_XSDM_1 				 0x1204d8
-#define PXP2_REG_PGL_INT_XSDM_2 				 0x1204dc
-#define PXP2_REG_PGL_INT_XSDM_3 				 0x1204e0
-#define PXP2_REG_PGL_INT_XSDM_4 				 0x1204e4
-#define PXP2_REG_PGL_INT_XSDM_5 				 0x1204e8
-#define PXP2_REG_PGL_INT_XSDM_6 				 0x1204ec
-#define PXP2_REG_PGL_INT_XSDM_7 				 0x1204f0
-/* [RW 3] this field allows one function to pretend being another function
-   when accessing any BAR mapped resource within the device. the value of
-   the field is the number of the function that will be accessed
-   effectively. after software write to this bit it must read it in order to
-   know that the new value is updated */
-#define PXP2_REG_PGL_PRETEND_FUNC_F0				 0x120674
-#define PXP2_REG_PGL_PRETEND_FUNC_F1				 0x120678
-#define PXP2_REG_PGL_PRETEND_FUNC_F2				 0x12067c
-#define PXP2_REG_PGL_PRETEND_FUNC_F3				 0x120680
-#define PXP2_REG_PGL_PRETEND_FUNC_F4				 0x120684
-#define PXP2_REG_PGL_PRETEND_FUNC_F5				 0x120688
-#define PXP2_REG_PGL_PRETEND_FUNC_F6				 0x12068c
-#define PXP2_REG_PGL_PRETEND_FUNC_F7				 0x120690
-/* [R 1] this bit indicates that a read request was blocked because of
-   bus_master_en was deasserted */
-#define PXP2_REG_PGL_READ_BLOCKED				 0x120568
-#define PXP2_REG_PGL_TAGS_LIMIT 				 0x1205a8
-/* [R 18] debug only */
-#define PXP2_REG_PGL_TXW_CDTS					 0x12052c
-/* [R 1] this bit indicates that a write request was blocked because of
-   bus_master_en was deasserted */
-#define PXP2_REG_PGL_WRITE_BLOCKED				 0x120564
-#define PXP2_REG_PSWRQ_BW_ADD1					 0x1201c0
-#define PXP2_REG_PSWRQ_BW_ADD10 				 0x1201e4
-#define PXP2_REG_PSWRQ_BW_ADD11 				 0x1201e8
-#define PXP2_REG_PSWRQ_BW_ADD2					 0x1201c4
-#define PXP2_REG_PSWRQ_BW_ADD28 				 0x120228
-#define PXP2_REG_PSWRQ_BW_ADD3					 0x1201c8
-#define PXP2_REG_PSWRQ_BW_ADD6					 0x1201d4
-#define PXP2_REG_PSWRQ_BW_ADD7					 0x1201d8
-#define PXP2_REG_PSWRQ_BW_ADD8					 0x1201dc
-#define PXP2_REG_PSWRQ_BW_ADD9					 0x1201e0
-#define PXP2_REG_PSWRQ_BW_CREDIT				 0x12032c
-#define PXP2_REG_PSWRQ_BW_L1					 0x1202b0
-#define PXP2_REG_PSWRQ_BW_L10					 0x1202d4
-#define PXP2_REG_PSWRQ_BW_L11					 0x1202d8
-#define PXP2_REG_PSWRQ_BW_L2					 0x1202b4
-#define PXP2_REG_PSWRQ_BW_L28					 0x120318
-#define PXP2_REG_PSWRQ_BW_L3					 0x1202b8
-#define PXP2_REG_PSWRQ_BW_L6					 0x1202c4
-#define PXP2_REG_PSWRQ_BW_L7					 0x1202c8
-#define PXP2_REG_PSWRQ_BW_L8					 0x1202cc
-#define PXP2_REG_PSWRQ_BW_L9					 0x1202d0
-#define PXP2_REG_PSWRQ_BW_RD					 0x120324
-#define PXP2_REG_PSWRQ_BW_UB1					 0x120238
-#define PXP2_REG_PSWRQ_BW_UB10					 0x12025c
-#define PXP2_REG_PSWRQ_BW_UB11					 0x120260
-#define PXP2_REG_PSWRQ_BW_UB2					 0x12023c
-#define PXP2_REG_PSWRQ_BW_UB28					 0x1202a0
-#define PXP2_REG_PSWRQ_BW_UB3					 0x120240
-#define PXP2_REG_PSWRQ_BW_UB6					 0x12024c
-#define PXP2_REG_PSWRQ_BW_UB7					 0x120250
-#define PXP2_REG_PSWRQ_BW_UB8					 0x120254
-#define PXP2_REG_PSWRQ_BW_UB9					 0x120258
-#define PXP2_REG_PSWRQ_BW_WR					 0x120328
-#define PXP2_REG_PSWRQ_CDU0_L2P 				 0x120000
-#define PXP2_REG_PSWRQ_QM0_L2P					 0x120038
-#define PXP2_REG_PSWRQ_SRC0_L2P 				 0x120054
-#define PXP2_REG_PSWRQ_TM0_L2P					 0x12001c
-#define PXP2_REG_PSWRQ_TSDM0_L2P				 0x1200e0
-/* [RW 32] Interrupt mask register #0 read/write */
-#define PXP2_REG_PXP2_INT_MASK_0				 0x120578
-/* [R 32] Interrupt register #0 read */
-#define PXP2_REG_PXP2_INT_STS_0 				 0x12056c
-#define PXP2_REG_PXP2_INT_STS_1 				 0x120608
-/* [RC 32] Interrupt register #0 read clear */
-#define PXP2_REG_PXP2_INT_STS_CLR_0				 0x120570
-/* [RW 32] Parity mask register #0 read/write */
-#define PXP2_REG_PXP2_PRTY_MASK_0				 0x120588
-#define PXP2_REG_PXP2_PRTY_MASK_1				 0x120598
-/* [R 32] Parity register #0 read */
-#define PXP2_REG_PXP2_PRTY_STS_0				 0x12057c
-#define PXP2_REG_PXP2_PRTY_STS_1				 0x12058c
-/* [RC 32] Parity register #0 read clear */
-#define PXP2_REG_PXP2_PRTY_STS_CLR_0				 0x120580
-#define PXP2_REG_PXP2_PRTY_STS_CLR_1				 0x120590
-/* [R 1] Debug only: The 'almost full' indication from each fifo (gives
-   indication about backpressure) */
-#define PXP2_REG_RD_ALMOST_FULL_0				 0x120424
-/* [R 8] Debug only: The blocks counter - number of unused block ids */
-#define PXP2_REG_RD_BLK_CNT					 0x120418
-/* [RW 8] Debug only: Total number of available blocks in Tetris Buffer.
-   Must be bigger than 6. Normally should not be changed. */
-#define PXP2_REG_RD_BLK_NUM_CFG 				 0x12040c
-/* [RW 2] CDU byte swapping mode configuration for master read requests */
-#define PXP2_REG_RD_CDURD_SWAP_MODE				 0x120404
-/* [RW 1] When '1'; inputs to the PSWRD block are ignored */
-#define PXP2_REG_RD_DISABLE_INPUTS				 0x120374
-/* [R 1] PSWRD internal memories initialization is done */
-#define PXP2_REG_RD_INIT_DONE					 0x120370
-/* [RW 8] The maximum number of blocks in Tetris Buffer that can be
-   allocated for vq10 */
-#define PXP2_REG_RD_MAX_BLKS_VQ10				 0x1203a0
-/* [RW 8] The maximum number of blocks in Tetris Buffer that can be
-   allocated for vq11 */
-#define PXP2_REG_RD_MAX_BLKS_VQ11				 0x1203a4
-/* [RW 8] The maximum number of blocks in Tetris Buffer that can be
-   allocated for vq17 */
-#define PXP2_REG_RD_MAX_BLKS_VQ17				 0x1203bc
-/* [RW 8] The maximum number of blocks in Tetris Buffer that can be
-   allocated for vq18 */
-#define PXP2_REG_RD_MAX_BLKS_VQ18				 0x1203c0
-/* [RW 8] The maximum number of blocks in Tetris Buffer that can be
-   allocated for vq19 */
-#define PXP2_REG_RD_MAX_BLKS_VQ19				 0x1203c4
-/* [RW 8] The maximum number of blocks in Tetris Buffer that can be
-   allocated for vq22 */
-#define PXP2_REG_RD_MAX_BLKS_VQ22				 0x1203d0
-/* [RW 8] The maximum number of blocks in Tetris Buffer that can be
-   allocated for vq25 */
-#define PXP2_REG_RD_MAX_BLKS_VQ25				 0x1203dc
-/* [RW 8] The maximum number of blocks in Tetris Buffer that can be
-   allocated for vq6 */
-#define PXP2_REG_RD_MAX_BLKS_VQ6				 0x120390
-/* [RW 8] The maximum number of blocks in Tetris Buffer that can be
-   allocated for vq9 */
-#define PXP2_REG_RD_MAX_BLKS_VQ9				 0x12039c
-/* [RW 2] PBF byte swapping mode configuration for master read requests */
-#define PXP2_REG_RD_PBF_SWAP_MODE				 0x1203f4
-/* [R 1] Debug only: Indication if delivery ports are idle */
-#define PXP2_REG_RD_PORT_IS_IDLE_0				 0x12041c
-#define PXP2_REG_RD_PORT_IS_IDLE_1				 0x120420
-/* [RW 2] QM byte swapping mode configuration for master read requests */
-#define PXP2_REG_RD_QM_SWAP_MODE				 0x1203f8
-/* [R 7] Debug only: The SR counter - number of unused sub request ids */
-#define PXP2_REG_RD_SR_CNT					 0x120414
-/* [RW 2] SRC byte swapping mode configuration for master read requests */
-#define PXP2_REG_RD_SRC_SWAP_MODE				 0x120400
-/* [RW 7] Debug only: Total number of available PCI read sub-requests. Must
-   be bigger than 1. Normally should not be changed. */
-#define PXP2_REG_RD_SR_NUM_CFG					 0x120408
-/* [RW 1] Signals the PSWRD block to start initializing internal memories */
-#define PXP2_REG_RD_START_INIT					 0x12036c
-/* [RW 2] TM byte swapping mode configuration for master read requests */
-#define PXP2_REG_RD_TM_SWAP_MODE				 0x1203fc
-/* [RW 10] Bandwidth addition to VQ0 write requests */
-#define PXP2_REG_RQ_BW_RD_ADD0					 0x1201bc
-/* [RW 10] Bandwidth addition to VQ12 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD12 				 0x1201ec
-/* [RW 10] Bandwidth addition to VQ13 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD13 				 0x1201f0
-/* [RW 10] Bandwidth addition to VQ14 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD14 				 0x1201f4
-/* [RW 10] Bandwidth addition to VQ15 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD15 				 0x1201f8
-/* [RW 10] Bandwidth addition to VQ16 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD16 				 0x1201fc
-/* [RW 10] Bandwidth addition to VQ17 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD17 				 0x120200
-/* [RW 10] Bandwidth addition to VQ18 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD18 				 0x120204
-/* [RW 10] Bandwidth addition to VQ19 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD19 				 0x120208
-/* [RW 10] Bandwidth addition to VQ20 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD20 				 0x12020c
-/* [RW 10] Bandwidth addition to VQ22 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD22 				 0x120210
-/* [RW 10] Bandwidth addition to VQ23 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD23 				 0x120214
-/* [RW 10] Bandwidth addition to VQ24 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD24 				 0x120218
-/* [RW 10] Bandwidth addition to VQ25 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD25 				 0x12021c
-/* [RW 10] Bandwidth addition to VQ26 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD26 				 0x120220
-/* [RW 10] Bandwidth addition to VQ27 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD27 				 0x120224
-/* [RW 10] Bandwidth addition to VQ4 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD4					 0x1201cc
-/* [RW 10] Bandwidth addition to VQ5 read requests */
-#define PXP2_REG_RQ_BW_RD_ADD5					 0x1201d0
-/* [RW 10] Bandwidth Typical L for VQ0 Read requests */
-#define PXP2_REG_RQ_BW_RD_L0					 0x1202ac
-/* [RW 10] Bandwidth Typical L for VQ12 Read requests */
-#define PXP2_REG_RQ_BW_RD_L12					 0x1202dc
-/* [RW 10] Bandwidth Typical L for VQ13 Read requests */
-#define PXP2_REG_RQ_BW_RD_L13					 0x1202e0
-/* [RW 10] Bandwidth Typical L for VQ14 Read requests */
-#define PXP2_REG_RQ_BW_RD_L14					 0x1202e4
-/* [RW 10] Bandwidth Typical L for VQ15 Read requests */
-#define PXP2_REG_RQ_BW_RD_L15					 0x1202e8
-/* [RW 10] Bandwidth Typical L for VQ16 Read requests */
-#define PXP2_REG_RQ_BW_RD_L16					 0x1202ec
-/* [RW 10] Bandwidth Typical L for VQ17 Read requests */
-#define PXP2_REG_RQ_BW_RD_L17					 0x1202f0
-/* [RW 10] Bandwidth Typical L for VQ18 Read requests */
-#define PXP2_REG_RQ_BW_RD_L18					 0x1202f4
-/* [RW 10] Bandwidth Typical L for VQ19 Read requests */
-#define PXP2_REG_RQ_BW_RD_L19					 0x1202f8
-/* [RW 10] Bandwidth Typical L for VQ20 Read requests */
-#define PXP2_REG_RQ_BW_RD_L20					 0x1202fc
-/* [RW 10] Bandwidth Typical L for VQ22 Read requests */
-#define PXP2_REG_RQ_BW_RD_L22					 0x120300
-/* [RW 10] Bandwidth Typical L for VQ23 Read requests */
-#define PXP2_REG_RQ_BW_RD_L23					 0x120304
-/* [RW 10] Bandwidth Typical L for VQ24 Read requests */
-#define PXP2_REG_RQ_BW_RD_L24					 0x120308
-/* [RW 10] Bandwidth Typical L for VQ25 Read requests */
-#define PXP2_REG_RQ_BW_RD_L25					 0x12030c
-/* [RW 10] Bandwidth Typical L for VQ26 Read requests */
-#define PXP2_REG_RQ_BW_RD_L26					 0x120310
-/* [RW 10] Bandwidth Typical L for VQ27 Read requests */
-#define PXP2_REG_RQ_BW_RD_L27					 0x120314
-/* [RW 10] Bandwidth Typical L for VQ4 Read requests */
-#define PXP2_REG_RQ_BW_RD_L4					 0x1202bc
-/* [RW 10] Bandwidth Typical L for VQ5 Read- currently not used */
-#define PXP2_REG_RQ_BW_RD_L5					 0x1202c0
-/* [RW 7] Bandwidth upper bound for VQ0 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND0				 0x120234
-/* [RW 7] Bandwidth upper bound for VQ12 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND12				 0x120264
-/* [RW 7] Bandwidth upper bound for VQ13 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND13				 0x120268
-/* [RW 7] Bandwidth upper bound for VQ14 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND14				 0x12026c
-/* [RW 7] Bandwidth upper bound for VQ15 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND15				 0x120270
-/* [RW 7] Bandwidth upper bound for VQ16 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND16				 0x120274
-/* [RW 7] Bandwidth upper bound for VQ17 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND17				 0x120278
-/* [RW 7] Bandwidth upper bound for VQ18 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND18				 0x12027c
-/* [RW 7] Bandwidth upper bound for VQ19 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND19				 0x120280
-/* [RW 7] Bandwidth upper bound for VQ20 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND20				 0x120284
-/* [RW 7] Bandwidth upper bound for VQ22 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND22				 0x120288
-/* [RW 7] Bandwidth upper bound for VQ23 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND23				 0x12028c
-/* [RW 7] Bandwidth upper bound for VQ24 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND24				 0x120290
-/* [RW 7] Bandwidth upper bound for VQ25 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND25				 0x120294
-/* [RW 7] Bandwidth upper bound for VQ26 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND26				 0x120298
-/* [RW 7] Bandwidth upper bound for VQ27 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND27				 0x12029c
-/* [RW 7] Bandwidth upper bound for VQ4 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND4				 0x120244
-/* [RW 7] Bandwidth upper bound for VQ5 read requests */
-#define PXP2_REG_RQ_BW_RD_UBOUND5				 0x120248
-/* [RW 10] Bandwidth addition to VQ29 write requests */
-#define PXP2_REG_RQ_BW_WR_ADD29 				 0x12022c
-/* [RW 10] Bandwidth addition to VQ30 write requests */
-#define PXP2_REG_RQ_BW_WR_ADD30 				 0x120230
-/* [RW 10] Bandwidth Typical L for VQ29 Write requests */
-#define PXP2_REG_RQ_BW_WR_L29					 0x12031c
-/* [RW 10] Bandwidth Typical L for VQ30 Write requests */
-#define PXP2_REG_RQ_BW_WR_L30					 0x120320
-/* [RW 7] Bandwidth upper bound for VQ29 */
-#define PXP2_REG_RQ_BW_WR_UBOUND29				 0x1202a4
-/* [RW 7] Bandwidth upper bound for VQ30 */
-#define PXP2_REG_RQ_BW_WR_UBOUND30				 0x1202a8
-/* [RW 18] external first_mem_addr field in L2P table for CDU module port 0 */
-#define PXP2_REG_RQ_CDU0_EFIRST_MEM_ADDR			 0x120008
-/* [RW 2] Endian mode for cdu */
-#define PXP2_REG_RQ_CDU_ENDIAN_M				 0x1201a0
-#define PXP2_REG_RQ_CDU_FIRST_ILT				 0x12061c
-#define PXP2_REG_RQ_CDU_LAST_ILT				 0x120620
-/* [RW 3] page size in L2P table for CDU module; -4k; -8k; -16k; -32k; -64k;
-   -128k */
-#define PXP2_REG_RQ_CDU_P_SIZE					 0x120018
-/* [R 1] 1' indicates that the requester has finished its internal
-   configuration */
-#define PXP2_REG_RQ_CFG_DONE					 0x1201b4
-/* [RW 2] Endian mode for debug */
-#define PXP2_REG_RQ_DBG_ENDIAN_M				 0x1201a4
-/* [RW 1] When '1'; requests will enter input buffers but wont get out
-   towards the glue */
-#define PXP2_REG_RQ_DISABLE_INPUTS				 0x120330
-/* [RW 4] Determines alignment of write SRs when a request is split into
- * several SRs. 0 - 8B aligned. 1 - 64B aligned. 2 - 128B aligned. 3 - 256B
- * aligned. 4 - 512B aligned. */
-#define PXP2_REG_RQ_DRAM_ALIGN					 0x1205b0
-/* [RW 4] Determines alignment of read SRs when a request is split into
- * several SRs. 0 - 8B aligned. 1 - 64B aligned. 2 - 128B aligned. 3 - 256B
- * aligned. 4 - 512B aligned. */
-#define PXP2_REG_RQ_DRAM_ALIGN_RD				 0x12092c
-/* [RW 1] when set the new alignment method (E2) will be applied; when reset
- * the original alignment method (E1 E1H) will be applied */
-#define PXP2_REG_RQ_DRAM_ALIGN_SEL				 0x120930
-/* [RW 1] If 1 ILT failiue will not result in ELT access; An interrupt will
-   be asserted */
-#define PXP2_REG_RQ_ELT_DISABLE 				 0x12066c
-/* [RW 2] Endian mode for hc */
-#define PXP2_REG_RQ_HC_ENDIAN_M 				 0x1201a8
-/* [RW 1] when '0' ILT logic will work as in A0; otherwise B0; for back
-   compatibility needs; Note that different registers are used per mode */
-#define PXP2_REG_RQ_ILT_MODE					 0x1205b4
-/* [WB 53] Onchip address table */
-#define PXP2_REG_RQ_ONCHIP_AT					 0x122000
-/* [WB 53] Onchip address table - B0 */
-#define PXP2_REG_RQ_ONCHIP_AT_B0				 0x128000
-/* [RW 13] Pending read limiter threshold; in Dwords */
-#define PXP2_REG_RQ_PDR_LIMIT					 0x12033c
-/* [RW 2] Endian mode for qm */
-#define PXP2_REG_RQ_QM_ENDIAN_M 				 0x120194
-#define PXP2_REG_RQ_QM_FIRST_ILT				 0x120634
-#define PXP2_REG_RQ_QM_LAST_ILT 				 0x120638
-/* [RW 3] page size in L2P table for QM module; -4k; -8k; -16k; -32k; -64k;
-   -128k */
-#define PXP2_REG_RQ_QM_P_SIZE					 0x120050
-/* [RW 1] 1' indicates that the RBC has finished configuring the PSWRQ */
-#define PXP2_REG_RQ_RBC_DONE					 0x1201b0
-/* [RW 3] Max burst size filed for read requests port 0; 000 - 128B;
-   001:256B; 010: 512B; 11:1K:100:2K; 01:4K */
-#define PXP2_REG_RQ_RD_MBS0					 0x120160
-/* [RW 3] Max burst size filed for read requests port 1; 000 - 128B;
-   001:256B; 010: 512B; 11:1K:100:2K; 01:4K */
-#define PXP2_REG_RQ_RD_MBS1					 0x120168
-/* [RW 2] Endian mode for src */
-#define PXP2_REG_RQ_SRC_ENDIAN_M				 0x12019c
-#define PXP2_REG_RQ_SRC_FIRST_ILT				 0x12063c
-#define PXP2_REG_RQ_SRC_LAST_ILT				 0x120640
-/* [RW 3] page size in L2P table for SRC module; -4k; -8k; -16k; -32k; -64k;
-   -128k */
-#define PXP2_REG_RQ_SRC_P_SIZE					 0x12006c
-/* [RW 2] Endian mode for tm */
-#define PXP2_REG_RQ_TM_ENDIAN_M 				 0x120198
-#define PXP2_REG_RQ_TM_FIRST_ILT				 0x120644
-#define PXP2_REG_RQ_TM_LAST_ILT 				 0x120648
-/* [RW 3] page size in L2P table for TM module; -4k; -8k; -16k; -32k; -64k;
-   -128k */
-#define PXP2_REG_RQ_TM_P_SIZE					 0x120034
-/* [R 5] Number of entries in the ufifo; his fifo has l2p completions */
-#define PXP2_REG_RQ_UFIFO_NUM_OF_ENTRY				 0x12080c
-/* [RW 18] external first_mem_addr field in L2P table for USDM module port 0 */
-#define PXP2_REG_RQ_USDM0_EFIRST_MEM_ADDR			 0x120094
-/* [R 8] Number of entries occupied by vq 0 in pswrq memory */
-#define PXP2_REG_RQ_VQ0_ENTRY_CNT				 0x120810
-/* [R 8] Number of entries occupied by vq 10 in pswrq memory */
-#define PXP2_REG_RQ_VQ10_ENTRY_CNT				 0x120818
-/* [R 8] Number of entries occupied by vq 11 in pswrq memory */
-#define PXP2_REG_RQ_VQ11_ENTRY_CNT				 0x120820
-/* [R 8] Number of entries occupied by vq 12 in pswrq memory */
-#define PXP2_REG_RQ_VQ12_ENTRY_CNT				 0x120828
-/* [R 8] Number of entries occupied by vq 13 in pswrq memory */
-#define PXP2_REG_RQ_VQ13_ENTRY_CNT				 0x120830
-/* [R 8] Number of entries occupied by vq 14 in pswrq memory */
-#define PXP2_REG_RQ_VQ14_ENTRY_CNT				 0x120838
-/* [R 8] Number of entries occupied by vq 15 in pswrq memory */
-#define PXP2_REG_RQ_VQ15_ENTRY_CNT				 0x120840
-/* [R 8] Number of entries occupied by vq 16 in pswrq memory */
-#define PXP2_REG_RQ_VQ16_ENTRY_CNT				 0x120848
-/* [R 8] Number of entries occupied by vq 17 in pswrq memory */
-#define PXP2_REG_RQ_VQ17_ENTRY_CNT				 0x120850
-/* [R 8] Number of entries occupied by vq 18 in pswrq memory */
-#define PXP2_REG_RQ_VQ18_ENTRY_CNT				 0x120858
-/* [R 8] Number of entries occupied by vq 19 in pswrq memory */
-#define PXP2_REG_RQ_VQ19_ENTRY_CNT				 0x120860
-/* [R 8] Number of entries occupied by vq 1 in pswrq memory */
-#define PXP2_REG_RQ_VQ1_ENTRY_CNT				 0x120868
-/* [R 8] Number of entries occupied by vq 20 in pswrq memory */
-#define PXP2_REG_RQ_VQ20_ENTRY_CNT				 0x120870
-/* [R 8] Number of entries occupied by vq 21 in pswrq memory */
-#define PXP2_REG_RQ_VQ21_ENTRY_CNT				 0x120878
-/* [R 8] Number of entries occupied by vq 22 in pswrq memory */
-#define PXP2_REG_RQ_VQ22_ENTRY_CNT				 0x120880
-/* [R 8] Number of entries occupied by vq 23 in pswrq memory */
-#define PXP2_REG_RQ_VQ23_ENTRY_CNT				 0x120888
-/* [R 8] Number of entries occupied by vq 24 in pswrq memory */
-#define PXP2_REG_RQ_VQ24_ENTRY_CNT				 0x120890
-/* [R 8] Number of entries occupied by vq 25 in pswrq memory */
-#define PXP2_REG_RQ_VQ25_ENTRY_CNT				 0x120898
-/* [R 8] Number of entries occupied by vq 26 in pswrq memory */
-#define PXP2_REG_RQ_VQ26_ENTRY_CNT				 0x1208a0
-/* [R 8] Number of entries occupied by vq 27 in pswrq memory */
-#define PXP2_REG_RQ_VQ27_ENTRY_CNT				 0x1208a8
-/* [R 8] Number of entries occupied by vq 28 in pswrq memory */
-#define PXP2_REG_RQ_VQ28_ENTRY_CNT				 0x1208b0
-/* [R 8] Number of entries occupied by vq 29 in pswrq memory */
-#define PXP2_REG_RQ_VQ29_ENTRY_CNT				 0x1208b8
-/* [R 8] Number of entries occupied by vq 2 in pswrq memory */
-#define PXP2_REG_RQ_VQ2_ENTRY_CNT				 0x1208c0
-/* [R 8] Number of entries occupied by vq 30 in pswrq memory */
-#define PXP2_REG_RQ_VQ30_ENTRY_CNT				 0x1208c8
-/* [R 8] Number of entries occupied by vq 31 in pswrq memory */
-#define PXP2_REG_RQ_VQ31_ENTRY_CNT				 0x1208d0
-/* [R 8] Number of entries occupied by vq 3 in pswrq memory */
-#define PXP2_REG_RQ_VQ3_ENTRY_CNT				 0x1208d8
-/* [R 8] Number of entries occupied by vq 4 in pswrq memory */
-#define PXP2_REG_RQ_VQ4_ENTRY_CNT				 0x1208e0
-/* [R 8] Number of entries occupied by vq 5 in pswrq memory */
-#define PXP2_REG_RQ_VQ5_ENTRY_CNT				 0x1208e8
-/* [R 8] Number of entries occupied by vq 6 in pswrq memory */
-#define PXP2_REG_RQ_VQ6_ENTRY_CNT				 0x1208f0
-/* [R 8] Number of entries occupied by vq 7 in pswrq memory */
-#define PXP2_REG_RQ_VQ7_ENTRY_CNT				 0x1208f8
-/* [R 8] Number of entries occupied by vq 8 in pswrq memory */
-#define PXP2_REG_RQ_VQ8_ENTRY_CNT				 0x120900
-/* [R 8] Number of entries occupied by vq 9 in pswrq memory */
-#define PXP2_REG_RQ_VQ9_ENTRY_CNT				 0x120908
-/* [RW 3] Max burst size filed for write requests port 0; 000 - 128B;
-   001:256B; 010: 512B; */
-#define PXP2_REG_RQ_WR_MBS0					 0x12015c
-/* [RW 3] Max burst size filed for write requests port 1; 000 - 128B;
-   001:256B; 010: 512B; */
-#define PXP2_REG_RQ_WR_MBS1					 0x120164
-/* [RW 2] 0 - 128B;  - 256B;  - 512B;  - 1024B; when the payload in the
-   buffer reaches this number has_payload will be asserted */
-#define PXP2_REG_WR_CDU_MPS					 0x1205f0
-/* [RW 2] 0 - 128B;  - 256B;  - 512B;  - 1024B; when the payload in the
-   buffer reaches this number has_payload will be asserted */
-#define PXP2_REG_WR_CSDM_MPS					 0x1205d0
-/* [RW 2] 0 - 128B;  - 256B;  - 512B;  - 1024B; when the payload in the
-   buffer reaches this number has_payload will be asserted */
-#define PXP2_REG_WR_DBG_MPS					 0x1205e8
-/* [RW 2] 0 - 128B;  - 256B;  - 512B;  - 1024B; when the payload in the
-   buffer reaches this number has_payload will be asserted */
-#define PXP2_REG_WR_DMAE_MPS					 0x1205ec
-/* [RW 10] if Number of entries in dmae fifo will be higher than this
-   threshold then has_payload indication will be asserted; the default value
-   should be equal to &gt;  write MBS size! */
-#define PXP2_REG_WR_DMAE_TH					 0x120368
-/* [RW 2] 0 - 128B;  - 256B;  - 512B;  - 1024B; when the payload in the
-   buffer reaches this number has_payload will be asserted */
-#define PXP2_REG_WR_HC_MPS					 0x1205c8
-/* [RW 2] 0 - 128B;  - 256B;  - 512B;  - 1024B; when the payload in the
-   buffer reaches this number has_payload will be asserted */
-#define PXP2_REG_WR_QM_MPS					 0x1205dc
-/* [RW 1] 0 - working in A0 mode;  - working in B0 mode */
-#define PXP2_REG_WR_REV_MODE					 0x120670
-/* [RW 2] 0 - 128B;  - 256B;  - 512B;  - 1024B; when the payload in the
-   buffer reaches this number has_payload will be asserted */
-#define PXP2_REG_WR_SRC_MPS					 0x1205e4
-/* [RW 2] 0 - 128B;  - 256B;  - 512B;  - 1024B; when the payload in the
-   buffer reaches this number has_payload will be asserted */
-#define PXP2_REG_WR_TM_MPS					 0x1205e0
-/* [RW 2] 0 - 128B;  - 256B;  - 512B;  - 1024B; when the payload in the
-   buffer reaches this number has_payload will be asserted */
-#define PXP2_REG_WR_TSDM_MPS					 0x1205d4
-/* [RW 10] if Number of entries in usdmdp fifo will be higher than this
-   threshold then has_payload indication will be asserted; the default value
-   should be equal to &gt;  write MBS size! */
-#define PXP2_REG_WR_USDMDP_TH					 0x120348
-/* [RW 2] 0 - 128B;  - 256B;  - 512B;  - 1024B; when the payload in the
-   buffer reaches this number has_payload will be asserted */
-#define PXP2_REG_WR_USDM_MPS					 0x1205cc
-/* [RW 2] 0 - 128B;  - 256B;  - 512B;  - 1024B; when the payload in the
-   buffer reaches this number has_payload will be asserted */
-#define PXP2_REG_WR_XSDM_MPS					 0x1205d8
-/* [R 1] debug only: Indication if PSWHST arbiter is idle */
-#define PXP_REG_HST_ARB_IS_IDLE 				 0x103004
-/* [R 8] debug only: A bit mask for all PSWHST arbiter clients. '1' means
-   this client is waiting for the arbiter. */
-#define PXP_REG_HST_CLIENTS_WAITING_TO_ARB			 0x103008
-/* [RW 1] When 1; doorbells are discarded and not passed to doorbell queue
-   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 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.
-   Should be used for close the gates. */
-#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 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 */
-#define PXP_REG_HST_INBOUND_INT 				 0x103800
-/* [RW 32] Interrupt mask register #0 read/write */
-#define PXP_REG_PXP_INT_MASK_0					 0x103074
-#define PXP_REG_PXP_INT_MASK_1					 0x103084
-/* [R 32] Interrupt register #0 read */
-#define PXP_REG_PXP_INT_STS_0					 0x103068
-#define PXP_REG_PXP_INT_STS_1					 0x103078
-/* [RC 32] Interrupt register #0 read clear */
-#define PXP_REG_PXP_INT_STS_CLR_0				 0x10306c
-#define PXP_REG_PXP_INT_STS_CLR_1				 0x10307c
-/* [RW 27] Parity mask register #0 read/write */
-#define PXP_REG_PXP_PRTY_MASK					 0x103094
-/* [R 26] Parity register #0 read */
-#define PXP_REG_PXP_PRTY_STS					 0x103088
-/* [RC 27] Parity register #0 read clear */
-#define PXP_REG_PXP_PRTY_STS_CLR				 0x10308c
-/* [RW 4] The activity counter initial increment value sent in the load
-   request */
-#define QM_REG_ACTCTRINITVAL_0					 0x168040
-#define QM_REG_ACTCTRINITVAL_1					 0x168044
-#define QM_REG_ACTCTRINITVAL_2					 0x168048
-#define QM_REG_ACTCTRINITVAL_3					 0x16804c
-/* [RW 32] The base logical address (in bytes) of each physical queue. The
-   index I represents the physical queue number. The 12 lsbs are ignore and
-   considered zero so practically there are only 20 bits in this register;
-   queues 63-0 */
-#define QM_REG_BASEADDR 					 0x168900
-/* [RW 32] The base logical address (in bytes) of each physical queue. The
-   index I represents the physical queue number. The 12 lsbs are ignore and
-   considered zero so practically there are only 20 bits in this register;
-   queues 127-64 */
-#define QM_REG_BASEADDR_EXT_A					 0x16e100
-/* [RW 16] The byte credit cost for each task. This value is for both ports */
-#define QM_REG_BYTECRDCOST					 0x168234
-/* [RW 16] The initial byte credit value for both ports. */
-#define QM_REG_BYTECRDINITVAL					 0x168238
-/* [RW 32] A bit per physical queue. If the bit is cleared then the physical
-   queue uses port 0 else it uses port 1; queues 31-0 */
-#define QM_REG_BYTECRDPORT_LSB					 0x168228
-/* [RW 32] A bit per physical queue. If the bit is cleared then the physical
-   queue uses port 0 else it uses port 1; queues 95-64 */
-#define QM_REG_BYTECRDPORT_LSB_EXT_A				 0x16e520
-/* [RW 32] A bit per physical queue. If the bit is cleared then the physical
-   queue uses port 0 else it uses port 1; queues 63-32 */
-#define QM_REG_BYTECRDPORT_MSB					 0x168224
-/* [RW 32] A bit per physical queue. If the bit is cleared then the physical
-   queue uses port 0 else it uses port 1; queues 127-96 */
-#define QM_REG_BYTECRDPORT_MSB_EXT_A				 0x16e51c
-/* [RW 16] The byte credit value that if above the QM is considered almost
-   full */
-#define QM_REG_BYTECREDITAFULLTHR				 0x168094
-/* [RW 4] The initial credit for interface */
-#define QM_REG_CMINITCRD_0					 0x1680cc
-#define QM_REG_BYTECRDCMDQ_0					 0x16e6e8
-#define QM_REG_CMINITCRD_1					 0x1680d0
-#define QM_REG_CMINITCRD_2					 0x1680d4
-#define QM_REG_CMINITCRD_3					 0x1680d8
-#define QM_REG_CMINITCRD_4					 0x1680dc
-#define QM_REG_CMINITCRD_5					 0x1680e0
-#define QM_REG_CMINITCRD_6					 0x1680e4
-#define QM_REG_CMINITCRD_7					 0x1680e8
-/* [RW 8] A mask bit per CM interface. If this bit is 0 then this interface
-   is masked */
-#define QM_REG_CMINTEN						 0x1680ec
-/* [RW 12] A bit vector which indicates which one of the queues are tied to
-   interface 0 */
-#define QM_REG_CMINTVOQMASK_0					 0x1681f4
-#define QM_REG_CMINTVOQMASK_1					 0x1681f8
-#define QM_REG_CMINTVOQMASK_2					 0x1681fc
-#define QM_REG_CMINTVOQMASK_3					 0x168200
-#define QM_REG_CMINTVOQMASK_4					 0x168204
-#define QM_REG_CMINTVOQMASK_5					 0x168208
-#define QM_REG_CMINTVOQMASK_6					 0x16820c
-#define QM_REG_CMINTVOQMASK_7					 0x168210
-/* [RW 20] The number of connections divided by 16 which dictates the size
-   of each queue which belongs to even function number. */
-#define QM_REG_CONNNUM_0					 0x168020
-/* [R 6] Keep the fill level of the fifo from write client 4 */
-#define QM_REG_CQM_WRC_FIFOLVL					 0x168018
-/* [RW 8] The context regions sent in the CFC load request */
-#define QM_REG_CTXREG_0 					 0x168030
-#define QM_REG_CTXREG_1 					 0x168034
-#define QM_REG_CTXREG_2 					 0x168038
-#define QM_REG_CTXREG_3 					 0x16803c
-/* [RW 12] The VOQ mask used to select the VOQs which needs to be full for
-   bypass enable */
-#define QM_REG_ENBYPVOQMASK					 0x16823c
-/* [RW 32] A bit mask per each physical queue. If a bit is set then the
-   physical queue uses the byte credit; queues 31-0 */
-#define QM_REG_ENBYTECRD_LSB					 0x168220
-/* [RW 32] A bit mask per each physical queue. If a bit is set then the
-   physical queue uses the byte credit; queues 95-64 */
-#define QM_REG_ENBYTECRD_LSB_EXT_A				 0x16e518
-/* [RW 32] A bit mask per each physical queue. If a bit is set then the
-   physical queue uses the byte credit; queues 63-32 */
-#define QM_REG_ENBYTECRD_MSB					 0x16821c
-/* [RW 32] A bit mask per each physical queue. If a bit is set then the
-   physical queue uses the byte credit; queues 127-96 */
-#define QM_REG_ENBYTECRD_MSB_EXT_A				 0x16e514
-/* [RW 4] If cleared then the secondary interface will not be served by the
-   RR arbiter */
-#define QM_REG_ENSEC						 0x1680f0
-/* [RW 32] NA */
-#define QM_REG_FUNCNUMSEL_LSB					 0x168230
-/* [RW 32] NA */
-#define QM_REG_FUNCNUMSEL_MSB					 0x16822c
-/* [RW 32] A mask register to mask the Almost empty signals which will not
-   be use for the almost empty indication to the HW block; queues 31:0 */
-#define QM_REG_HWAEMPTYMASK_LSB 				 0x168218
-/* [RW 32] A mask register to mask the Almost empty signals which will not
-   be use for the almost empty indication to the HW block; queues 95-64 */
-#define QM_REG_HWAEMPTYMASK_LSB_EXT_A				 0x16e510
-/* [RW 32] A mask register to mask the Almost empty signals which will not
-   be use for the almost empty indication to the HW block; queues 63:32 */
-#define QM_REG_HWAEMPTYMASK_MSB 				 0x168214
-/* [RW 32] A mask register to mask the Almost empty signals which will not
-   be use for the almost empty indication to the HW block; queues 127-96 */
-#define QM_REG_HWAEMPTYMASK_MSB_EXT_A				 0x16e50c
-/* [RW 4] The number of outstanding request to CFC */
-#define QM_REG_OUTLDREQ 					 0x168804
-/* [RC 1] A flag to indicate that overflow error occurred in one of the
-   queues. */
-#define QM_REG_OVFERROR 					 0x16805c
-/* [RC 7] the Q where the overflow occurs */
-#define QM_REG_OVFQNUM						 0x168058
-/* [R 16] Pause state for physical queues 15-0 */
-#define QM_REG_PAUSESTATE0					 0x168410
-/* [R 16] Pause state for physical queues 31-16 */
-#define QM_REG_PAUSESTATE1					 0x168414
-/* [R 16] Pause state for physical queues 47-32 */
-#define QM_REG_PAUSESTATE2					 0x16e684
-/* [R 16] Pause state for physical queues 63-48 */
-#define QM_REG_PAUSESTATE3					 0x16e688
-/* [R 16] Pause state for physical queues 79-64 */
-#define QM_REG_PAUSESTATE4					 0x16e68c
-/* [R 16] Pause state for physical queues 95-80 */
-#define QM_REG_PAUSESTATE5					 0x16e690
-/* [R 16] Pause state for physical queues 111-96 */
-#define QM_REG_PAUSESTATE6					 0x16e694
-/* [R 16] Pause state for physical queues 127-112 */
-#define QM_REG_PAUSESTATE7					 0x16e698
-/* [RW 2] The PCI attributes field used in the PCI request. */
-#define QM_REG_PCIREQAT 					 0x168054
-#define QM_REG_PF_EN						 0x16e70c
-/* [R 24] The number of tasks stored in the QM for the PF. only even
- * functions are valid in E2 (odd I registers will be hard wired to 0) */
-#define QM_REG_PF_USG_CNT_0					 0x16e040
-/* [R 16] NOT USED */
-#define QM_REG_PORT0BYTECRD					 0x168300
-/* [R 16] The byte credit of port 1 */
-#define QM_REG_PORT1BYTECRD					 0x168304
-/* [RW 3] pci function number of queues 15-0 */
-#define QM_REG_PQ2PCIFUNC_0					 0x16e6bc
-#define QM_REG_PQ2PCIFUNC_1					 0x16e6c0
-#define QM_REG_PQ2PCIFUNC_2					 0x16e6c4
-#define QM_REG_PQ2PCIFUNC_3					 0x16e6c8
-#define QM_REG_PQ2PCIFUNC_4					 0x16e6cc
-#define QM_REG_PQ2PCIFUNC_5					 0x16e6d0
-#define QM_REG_PQ2PCIFUNC_6					 0x16e6d4
-#define QM_REG_PQ2PCIFUNC_7					 0x16e6d8
-/* [WB 54] Pointer Table Memory for queues 63-0; The mapping is as follow:
-   ptrtbl[53:30] read pointer; ptrtbl[29:6] write pointer; ptrtbl[5:4] read
-   bank0; ptrtbl[3:2] read bank 1; ptrtbl[1:0] write bank; */
-#define QM_REG_PTRTBL						 0x168a00
-/* [WB 54] Pointer Table Memory for queues 127-64; The mapping is as follow:
-   ptrtbl[53:30] read pointer; ptrtbl[29:6] write pointer; ptrtbl[5:4] read
-   bank0; ptrtbl[3:2] read bank 1; ptrtbl[1:0] write bank; */
-#define QM_REG_PTRTBL_EXT_A					 0x16e200
-/* [RW 2] Interrupt mask register #0 read/write */
-#define QM_REG_QM_INT_MASK					 0x168444
-/* [R 2] Interrupt register #0 read */
-#define QM_REG_QM_INT_STS					 0x168438
-/* [RW 12] Parity mask register #0 read/write */
-#define QM_REG_QM_PRTY_MASK					 0x168454
-/* [R 12] Parity register #0 read */
-#define QM_REG_QM_PRTY_STS					 0x168448
-/* [RC 12] Parity register #0 read clear */
-#define QM_REG_QM_PRTY_STS_CLR					 0x16844c
-/* [R 32] Current queues in pipeline: Queues from 32 to 63 */
-#define QM_REG_QSTATUS_HIGH					 0x16802c
-/* [R 32] Current queues in pipeline: Queues from 96 to 127 */
-#define QM_REG_QSTATUS_HIGH_EXT_A				 0x16e408
-/* [R 32] Current queues in pipeline: Queues from 0 to 31 */
-#define QM_REG_QSTATUS_LOW					 0x168028
-/* [R 32] Current queues in pipeline: Queues from 64 to 95 */
-#define QM_REG_QSTATUS_LOW_EXT_A				 0x16e404
-/* [R 24] The number of tasks queued for each queue; queues 63-0 */
-#define QM_REG_QTASKCTR_0					 0x168308
-/* [R 24] The number of tasks queued for each queue; queues 127-64 */
-#define QM_REG_QTASKCTR_EXT_A_0 				 0x16e584
-/* [RW 4] Queue tied to VOQ */
-#define QM_REG_QVOQIDX_0					 0x1680f4
-#define QM_REG_QVOQIDX_10					 0x16811c
-#define QM_REG_QVOQIDX_100					 0x16e49c
-#define QM_REG_QVOQIDX_101					 0x16e4a0
-#define QM_REG_QVOQIDX_102					 0x16e4a4
-#define QM_REG_QVOQIDX_103					 0x16e4a8
-#define QM_REG_QVOQIDX_104					 0x16e4ac
-#define QM_REG_QVOQIDX_105					 0x16e4b0
-#define QM_REG_QVOQIDX_106					 0x16e4b4
-#define QM_REG_QVOQIDX_107					 0x16e4b8
-#define QM_REG_QVOQIDX_108					 0x16e4bc
-#define QM_REG_QVOQIDX_109					 0x16e4c0
-#define QM_REG_QVOQIDX_11					 0x168120
-#define QM_REG_QVOQIDX_110					 0x16e4c4
-#define QM_REG_QVOQIDX_111					 0x16e4c8
-#define QM_REG_QVOQIDX_112					 0x16e4cc
-#define QM_REG_QVOQIDX_113					 0x16e4d0
-#define QM_REG_QVOQIDX_114					 0x16e4d4
-#define QM_REG_QVOQIDX_115					 0x16e4d8
-#define QM_REG_QVOQIDX_116					 0x16e4dc
-#define QM_REG_QVOQIDX_117					 0x16e4e0
-#define QM_REG_QVOQIDX_118					 0x16e4e4
-#define QM_REG_QVOQIDX_119					 0x16e4e8
-#define QM_REG_QVOQIDX_12					 0x168124
-#define QM_REG_QVOQIDX_120					 0x16e4ec
-#define QM_REG_QVOQIDX_121					 0x16e4f0
-#define QM_REG_QVOQIDX_122					 0x16e4f4
-#define QM_REG_QVOQIDX_123					 0x16e4f8
-#define QM_REG_QVOQIDX_124					 0x16e4fc
-#define QM_REG_QVOQIDX_125					 0x16e500
-#define QM_REG_QVOQIDX_126					 0x16e504
-#define QM_REG_QVOQIDX_127					 0x16e508
-#define QM_REG_QVOQIDX_13					 0x168128
-#define QM_REG_QVOQIDX_14					 0x16812c
-#define QM_REG_QVOQIDX_15					 0x168130
-#define QM_REG_QVOQIDX_16					 0x168134
-#define QM_REG_QVOQIDX_17					 0x168138
-#define QM_REG_QVOQIDX_21					 0x168148
-#define QM_REG_QVOQIDX_22					 0x16814c
-#define QM_REG_QVOQIDX_23					 0x168150
-#define QM_REG_QVOQIDX_24					 0x168154
-#define QM_REG_QVOQIDX_25					 0x168158
-#define QM_REG_QVOQIDX_26					 0x16815c
-#define QM_REG_QVOQIDX_27					 0x168160
-#define QM_REG_QVOQIDX_28					 0x168164
-#define QM_REG_QVOQIDX_29					 0x168168
-#define QM_REG_QVOQIDX_30					 0x16816c
-#define QM_REG_QVOQIDX_31					 0x168170
-#define QM_REG_QVOQIDX_32					 0x168174
-#define QM_REG_QVOQIDX_33					 0x168178
-#define QM_REG_QVOQIDX_34					 0x16817c
-#define QM_REG_QVOQIDX_35					 0x168180
-#define QM_REG_QVOQIDX_36					 0x168184
-#define QM_REG_QVOQIDX_37					 0x168188
-#define QM_REG_QVOQIDX_38					 0x16818c
-#define QM_REG_QVOQIDX_39					 0x168190
-#define QM_REG_QVOQIDX_40					 0x168194
-#define QM_REG_QVOQIDX_41					 0x168198
-#define QM_REG_QVOQIDX_42					 0x16819c
-#define QM_REG_QVOQIDX_43					 0x1681a0
-#define QM_REG_QVOQIDX_44					 0x1681a4
-#define QM_REG_QVOQIDX_45					 0x1681a8
-#define QM_REG_QVOQIDX_46					 0x1681ac
-#define QM_REG_QVOQIDX_47					 0x1681b0
-#define QM_REG_QVOQIDX_48					 0x1681b4
-#define QM_REG_QVOQIDX_49					 0x1681b8
-#define QM_REG_QVOQIDX_5					 0x168108
-#define QM_REG_QVOQIDX_50					 0x1681bc
-#define QM_REG_QVOQIDX_51					 0x1681c0
-#define QM_REG_QVOQIDX_52					 0x1681c4
-#define QM_REG_QVOQIDX_53					 0x1681c8
-#define QM_REG_QVOQIDX_54					 0x1681cc
-#define QM_REG_QVOQIDX_55					 0x1681d0
-#define QM_REG_QVOQIDX_56					 0x1681d4
-#define QM_REG_QVOQIDX_57					 0x1681d8
-#define QM_REG_QVOQIDX_58					 0x1681dc
-#define QM_REG_QVOQIDX_59					 0x1681e0
-#define QM_REG_QVOQIDX_6					 0x16810c
-#define QM_REG_QVOQIDX_60					 0x1681e4
-#define QM_REG_QVOQIDX_61					 0x1681e8
-#define QM_REG_QVOQIDX_62					 0x1681ec
-#define QM_REG_QVOQIDX_63					 0x1681f0
-#define QM_REG_QVOQIDX_64					 0x16e40c
-#define QM_REG_QVOQIDX_65					 0x16e410
-#define QM_REG_QVOQIDX_69					 0x16e420
-#define QM_REG_QVOQIDX_7					 0x168110
-#define QM_REG_QVOQIDX_70					 0x16e424
-#define QM_REG_QVOQIDX_71					 0x16e428
-#define QM_REG_QVOQIDX_72					 0x16e42c
-#define QM_REG_QVOQIDX_73					 0x16e430
-#define QM_REG_QVOQIDX_74					 0x16e434
-#define QM_REG_QVOQIDX_75					 0x16e438
-#define QM_REG_QVOQIDX_76					 0x16e43c
-#define QM_REG_QVOQIDX_77					 0x16e440
-#define QM_REG_QVOQIDX_78					 0x16e444
-#define QM_REG_QVOQIDX_79					 0x16e448
-#define QM_REG_QVOQIDX_8					 0x168114
-#define QM_REG_QVOQIDX_80					 0x16e44c
-#define QM_REG_QVOQIDX_81					 0x16e450
-#define QM_REG_QVOQIDX_85					 0x16e460
-#define QM_REG_QVOQIDX_86					 0x16e464
-#define QM_REG_QVOQIDX_87					 0x16e468
-#define QM_REG_QVOQIDX_88					 0x16e46c
-#define QM_REG_QVOQIDX_89					 0x16e470
-#define QM_REG_QVOQIDX_9					 0x168118
-#define QM_REG_QVOQIDX_90					 0x16e474
-#define QM_REG_QVOQIDX_91					 0x16e478
-#define QM_REG_QVOQIDX_92					 0x16e47c
-#define QM_REG_QVOQIDX_93					 0x16e480
-#define QM_REG_QVOQIDX_94					 0x16e484
-#define QM_REG_QVOQIDX_95					 0x16e488
-#define QM_REG_QVOQIDX_96					 0x16e48c
-#define QM_REG_QVOQIDX_97					 0x16e490
-#define QM_REG_QVOQIDX_98					 0x16e494
-#define QM_REG_QVOQIDX_99					 0x16e498
-/* [RW 1] Initialization bit command */
-#define QM_REG_SOFT_RESET					 0x168428
-/* [RW 8] The credit cost per every task in the QM. A value per each VOQ */
-#define QM_REG_TASKCRDCOST_0					 0x16809c
-#define QM_REG_TASKCRDCOST_1					 0x1680a0
-#define QM_REG_TASKCRDCOST_2					 0x1680a4
-#define QM_REG_TASKCRDCOST_4					 0x1680ac
-#define QM_REG_TASKCRDCOST_5					 0x1680b0
-/* [R 6] Keep the fill level of the fifo from write client 3 */
-#define QM_REG_TQM_WRC_FIFOLVL					 0x168010
-/* [R 6] Keep the fill level of the fifo from write client 2 */
-#define QM_REG_UQM_WRC_FIFOLVL					 0x168008
-/* [RC 32] Credit update error register */
-#define QM_REG_VOQCRDERRREG					 0x168408
-/* [R 16] The credit value for each VOQ */
-#define QM_REG_VOQCREDIT_0					 0x1682d0
-#define QM_REG_VOQCREDIT_1					 0x1682d4
-#define QM_REG_VOQCREDIT_4					 0x1682e0
-/* [RW 16] The credit value that if above the QM is considered almost full */
-#define QM_REG_VOQCREDITAFULLTHR				 0x168090
-/* [RW 16] The init and maximum credit for each VoQ */
-#define QM_REG_VOQINITCREDIT_0					 0x168060
-#define QM_REG_VOQINITCREDIT_1					 0x168064
-#define QM_REG_VOQINITCREDIT_2					 0x168068
-#define QM_REG_VOQINITCREDIT_4					 0x168070
-#define QM_REG_VOQINITCREDIT_5					 0x168074
-/* [RW 1] The port of which VOQ belongs */
-#define QM_REG_VOQPORT_0					 0x1682a0
-#define QM_REG_VOQPORT_1					 0x1682a4
-#define QM_REG_VOQPORT_2					 0x1682a8
-/* [RW 32] The physical queue number associated with each VOQ; queues 31-0 */
-#define QM_REG_VOQQMASK_0_LSB					 0x168240
-/* [RW 32] The physical queue number associated with each VOQ; queues 95-64 */
-#define QM_REG_VOQQMASK_0_LSB_EXT_A				 0x16e524
-/* [RW 32] The physical queue number associated with each VOQ; queues 63-32 */
-#define QM_REG_VOQQMASK_0_MSB					 0x168244
-/* [RW 32] The physical queue number associated with each VOQ; queues 127-96 */
-#define QM_REG_VOQQMASK_0_MSB_EXT_A				 0x16e528
-/* [RW 32] The physical queue number associated with each VOQ; queues 31-0 */
-#define QM_REG_VOQQMASK_10_LSB					 0x168290
-/* [RW 32] The physical queue number associated with each VOQ; queues 95-64 */
-#define QM_REG_VOQQMASK_10_LSB_EXT_A				 0x16e574
-/* [RW 32] The physical queue number associated with each VOQ; queues 63-32 */
-#define QM_REG_VOQQMASK_10_MSB					 0x168294
-/* [RW 32] The physical queue number associated with each VOQ; queues 127-96 */
-#define QM_REG_VOQQMASK_10_MSB_EXT_A				 0x16e578
-/* [RW 32] The physical queue number associated with each VOQ; queues 31-0 */
-#define QM_REG_VOQQMASK_11_LSB					 0x168298
-/* [RW 32] The physical queue number associated with each VOQ; queues 95-64 */
-#define QM_REG_VOQQMASK_11_LSB_EXT_A				 0x16e57c
-/* [RW 32] The physical queue number associated with each VOQ; queues 63-32 */
-#define QM_REG_VOQQMASK_11_MSB					 0x16829c
-/* [RW 32] The physical queue number associated with each VOQ; queues 127-96 */
-#define QM_REG_VOQQMASK_11_MSB_EXT_A				 0x16e580
-/* [RW 32] The physical queue number associated with each VOQ; queues 31-0 */
-#define QM_REG_VOQQMASK_1_LSB					 0x168248
-/* [RW 32] The physical queue number associated with each VOQ; queues 95-64 */
-#define QM_REG_VOQQMASK_1_LSB_EXT_A				 0x16e52c
-/* [RW 32] The physical queue number associated with each VOQ; queues 63-32 */
-#define QM_REG_VOQQMASK_1_MSB					 0x16824c
-/* [RW 32] The physical queue number associated with each VOQ; queues 127-96 */
-#define QM_REG_VOQQMASK_1_MSB_EXT_A				 0x16e530
-/* [RW 32] The physical queue number associated with each VOQ; queues 31-0 */
-#define QM_REG_VOQQMASK_2_LSB					 0x168250
-/* [RW 32] The physical queue number associated with each VOQ; queues 95-64 */
-#define QM_REG_VOQQMASK_2_LSB_EXT_A				 0x16e534
-/* [RW 32] The physical queue number associated with each VOQ; queues 63-32 */
-#define QM_REG_VOQQMASK_2_MSB					 0x168254
-/* [RW 32] The physical queue number associated with each VOQ; queues 127-96 */
-#define QM_REG_VOQQMASK_2_MSB_EXT_A				 0x16e538
-/* [RW 32] The physical queue number associated with each VOQ; queues 31-0 */
-#define QM_REG_VOQQMASK_3_LSB					 0x168258
-/* [RW 32] The physical queue number associated with each VOQ; queues 95-64 */
-#define QM_REG_VOQQMASK_3_LSB_EXT_A				 0x16e53c
-/* [RW 32] The physical queue number associated with each VOQ; queues 127-96 */
-#define QM_REG_VOQQMASK_3_MSB_EXT_A				 0x16e540
-/* [RW 32] The physical queue number associated with each VOQ; queues 31-0 */
-#define QM_REG_VOQQMASK_4_LSB					 0x168260
-/* [RW 32] The physical queue number associated with each VOQ; queues 95-64 */
-#define QM_REG_VOQQMASK_4_LSB_EXT_A				 0x16e544
-/* [RW 32] The physical queue number associated with each VOQ; queues 63-32 */
-#define QM_REG_VOQQMASK_4_MSB					 0x168264
-/* [RW 32] The physical queue number associated with each VOQ; queues 127-96 */
-#define QM_REG_VOQQMASK_4_MSB_EXT_A				 0x16e548
-/* [RW 32] The physical queue number associated with each VOQ; queues 31-0 */
-#define QM_REG_VOQQMASK_5_LSB					 0x168268
-/* [RW 32] The physical queue number associated with each VOQ; queues 95-64 */
-#define QM_REG_VOQQMASK_5_LSB_EXT_A				 0x16e54c
-/* [RW 32] The physical queue number associated with each VOQ; queues 63-32 */
-#define QM_REG_VOQQMASK_5_MSB					 0x16826c
-/* [RW 32] The physical queue number associated with each VOQ; queues 127-96 */
-#define QM_REG_VOQQMASK_5_MSB_EXT_A				 0x16e550
-/* [RW 32] The physical queue number associated with each VOQ; queues 31-0 */
-#define QM_REG_VOQQMASK_6_LSB					 0x168270
-/* [RW 32] The physical queue number associated with each VOQ; queues 95-64 */
-#define QM_REG_VOQQMASK_6_LSB_EXT_A				 0x16e554
-/* [RW 32] The physical queue number associated with each VOQ; queues 63-32 */
-#define QM_REG_VOQQMASK_6_MSB					 0x168274
-/* [RW 32] The physical queue number associated with each VOQ; queues 127-96 */
-#define QM_REG_VOQQMASK_6_MSB_EXT_A				 0x16e558
-/* [RW 32] The physical queue number associated with each VOQ; queues 31-0 */
-#define QM_REG_VOQQMASK_7_LSB					 0x168278
-/* [RW 32] The physical queue number associated with each VOQ; queues 95-64 */
-#define QM_REG_VOQQMASK_7_LSB_EXT_A				 0x16e55c
-/* [RW 32] The physical queue number associated with each VOQ; queues 63-32 */
-#define QM_REG_VOQQMASK_7_MSB					 0x16827c
-/* [RW 32] The physical queue number associated with each VOQ; queues 127-96 */
-#define QM_REG_VOQQMASK_7_MSB_EXT_A				 0x16e560
-/* [RW 32] The physical queue number associated with each VOQ; queues 31-0 */
-#define QM_REG_VOQQMASK_8_LSB					 0x168280
-/* [RW 32] The physical queue number associated with each VOQ; queues 95-64 */
-#define QM_REG_VOQQMASK_8_LSB_EXT_A				 0x16e564
-/* [RW 32] The physical queue number associated with each VOQ; queues 63-32 */
-#define QM_REG_VOQQMASK_8_MSB					 0x168284
-/* [RW 32] The physical queue number associated with each VOQ; queues 127-96 */
-#define QM_REG_VOQQMASK_8_MSB_EXT_A				 0x16e568
-/* [RW 32] The physical queue number associated with each VOQ; queues 31-0 */
-#define QM_REG_VOQQMASK_9_LSB					 0x168288
-/* [RW 32] The physical queue number associated with each VOQ; queues 95-64 */
-#define QM_REG_VOQQMASK_9_LSB_EXT_A				 0x16e56c
-/* [RW 32] The physical queue number associated with each VOQ; queues 127-96 */
-#define QM_REG_VOQQMASK_9_MSB_EXT_A				 0x16e570
-/* [RW 32] Wrr weights */
-#define QM_REG_WRRWEIGHTS_0					 0x16880c
-#define QM_REG_WRRWEIGHTS_1					 0x168810
-#define QM_REG_WRRWEIGHTS_10					 0x168814
-#define QM_REG_WRRWEIGHTS_11					 0x168818
-#define QM_REG_WRRWEIGHTS_12					 0x16881c
-#define QM_REG_WRRWEIGHTS_13					 0x168820
-#define QM_REG_WRRWEIGHTS_14					 0x168824
-#define QM_REG_WRRWEIGHTS_15					 0x168828
-#define QM_REG_WRRWEIGHTS_16					 0x16e000
-#define QM_REG_WRRWEIGHTS_17					 0x16e004
-#define QM_REG_WRRWEIGHTS_18					 0x16e008
-#define QM_REG_WRRWEIGHTS_19					 0x16e00c
-#define QM_REG_WRRWEIGHTS_2					 0x16882c
-#define QM_REG_WRRWEIGHTS_20					 0x16e010
-#define QM_REG_WRRWEIGHTS_21					 0x16e014
-#define QM_REG_WRRWEIGHTS_22					 0x16e018
-#define QM_REG_WRRWEIGHTS_23					 0x16e01c
-#define QM_REG_WRRWEIGHTS_24					 0x16e020
-#define QM_REG_WRRWEIGHTS_25					 0x16e024
-#define QM_REG_WRRWEIGHTS_26					 0x16e028
-#define QM_REG_WRRWEIGHTS_27					 0x16e02c
-#define QM_REG_WRRWEIGHTS_28					 0x16e030
-#define QM_REG_WRRWEIGHTS_29					 0x16e034
-#define QM_REG_WRRWEIGHTS_3					 0x168830
-#define QM_REG_WRRWEIGHTS_30					 0x16e038
-#define QM_REG_WRRWEIGHTS_31					 0x16e03c
-#define QM_REG_WRRWEIGHTS_4					 0x168834
-#define QM_REG_WRRWEIGHTS_5					 0x168838
-#define QM_REG_WRRWEIGHTS_6					 0x16883c
-#define QM_REG_WRRWEIGHTS_7					 0x168840
-#define QM_REG_WRRWEIGHTS_8					 0x168844
-#define QM_REG_WRRWEIGHTS_9					 0x168848
-/* [R 6] Keep the fill level of the fifo from write client 1 */
-#define QM_REG_XQM_WRC_FIFOLVL					 0x168000
-/* [W 1] reset to parity interrupt */
-#define SEM_FAST_REG_PARITY_RST					 0x18840
-#define SRC_REG_COUNTFREE0					 0x40500
-/* [RW 1] If clr the searcher is compatible to E1 A0 - support only two
-   ports. If set the searcher support 8 functions. */
-#define SRC_REG_E1HMF_ENABLE					 0x404cc
-#define SRC_REG_FIRSTFREE0					 0x40510
-#define SRC_REG_KEYRSS0_0					 0x40408
-#define SRC_REG_KEYRSS0_7					 0x40424
-#define SRC_REG_KEYRSS1_9					 0x40454
-#define SRC_REG_KEYSEARCH_0					 0x40458
-#define SRC_REG_KEYSEARCH_1					 0x4045c
-#define SRC_REG_KEYSEARCH_2					 0x40460
-#define SRC_REG_KEYSEARCH_3					 0x40464
-#define SRC_REG_KEYSEARCH_4					 0x40468
-#define SRC_REG_KEYSEARCH_5					 0x4046c
-#define SRC_REG_KEYSEARCH_6					 0x40470
-#define SRC_REG_KEYSEARCH_7					 0x40474
-#define SRC_REG_KEYSEARCH_8					 0x40478
-#define SRC_REG_KEYSEARCH_9					 0x4047c
-#define SRC_REG_LASTFREE0					 0x40530
-#define SRC_REG_NUMBER_HASH_BITS0				 0x40400
-/* [RW 1] Reset internal state machines. */
-#define SRC_REG_SOFT_RST					 0x4049c
-/* [R 3] Interrupt register #0 read */
-#define SRC_REG_SRC_INT_STS					 0x404ac
-/* [RW 3] Parity mask register #0 read/write */
-#define SRC_REG_SRC_PRTY_MASK					 0x404c8
-/* [R 3] Parity register #0 read */
-#define SRC_REG_SRC_PRTY_STS					 0x404bc
-/* [RC 3] Parity register #0 read clear */
-#define SRC_REG_SRC_PRTY_STS_CLR				 0x404c0
-/* [R 4] Used to read the value of the XX protection CAM occupancy counter. */
-#define TCM_REG_CAM_OCCUP					 0x5017c
-/* [RW 1] CDU AG read Interface enable. If 0 - the request input is
-   disregarded; valid output is deasserted; all other signals are treated as
-   usual; if 1 - normal activity. */
-#define TCM_REG_CDU_AG_RD_IFEN					 0x50034
-/* [RW 1] CDU AG write Interface enable. If 0 - the request and valid input
-   are disregarded; all other signals are treated as usual; if 1 - normal
-   activity. */
-#define TCM_REG_CDU_AG_WR_IFEN					 0x50030
-/* [RW 1] CDU STORM read Interface enable. If 0 - the request input is
-   disregarded; valid output is deasserted; all other signals are treated as
-   usual; if 1 - normal activity. */
-#define TCM_REG_CDU_SM_RD_IFEN					 0x5003c
-/* [RW 1] CDU STORM write Interface enable. If 0 - the request and valid
-   input is disregarded; all other signals are treated as usual; if 1 -
-   normal activity. */
-#define TCM_REG_CDU_SM_WR_IFEN					 0x50038
-/* [RW 4] CFC output initial credit. Max credit available - 15.Write writes
-   the initial credit value; read returns the current value of the credit
-   counter. Must be initialized to 1 at start-up. */
-#define TCM_REG_CFC_INIT_CRD					 0x50204
-/* [RW 3] The weight of the CP input in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define TCM_REG_CP_WEIGHT					 0x500c0
-/* [RW 1] Input csem Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define TCM_REG_CSEM_IFEN					 0x5002c
-/* [RC 1] Message length mismatch (relative to last indication) at the In#9
-   interface. */
-#define TCM_REG_CSEM_LENGTH_MIS 				 0x50174
-/* [RW 3] The weight of the input csem in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define TCM_REG_CSEM_WEIGHT					 0x500bc
-/* [RW 8] The Event ID in case of ErrorFlg is set in the input message. */
-#define TCM_REG_ERR_EVNT_ID					 0x500a0
-/* [RW 28] The CM erroneous header for QM and Timers formatting. */
-#define TCM_REG_ERR_TCM_HDR					 0x5009c
-/* [RW 8] The Event ID for Timers expiration. */
-#define TCM_REG_EXPR_EVNT_ID					 0x500a4
-/* [RW 8] FIC0 output initial credit. Max credit available - 255.Write
-   writes the initial credit value; read returns the current value of the
-   credit counter. Must be initialized to 64 at start-up. */
-#define TCM_REG_FIC0_INIT_CRD					 0x5020c
-/* [RW 8] FIC1 output initial credit. Max credit available - 255.Write
-   writes the initial credit value; read returns the current value of the
-   credit counter. Must be initialized to 64 at start-up. */
-#define TCM_REG_FIC1_INIT_CRD					 0x50210
-/* [RW 1] Arbitration between Input Arbiter groups: 0 - fair Round-Robin; 1
-   - strict priority defined by ~tcm_registers_gr_ag_pr.gr_ag_pr;
-   ~tcm_registers_gr_ld0_pr.gr_ld0_pr and
-   ~tcm_registers_gr_ld1_pr.gr_ld1_pr. */
-#define TCM_REG_GR_ARB_TYPE					 0x50114
-/* [RW 2] Load (FIC0) channel group priority. The lowest priority is 0; the
-   highest priority is 3. It is supposed that the Store channel is the
-   compliment of the other 3 groups. */
-#define TCM_REG_GR_LD0_PR					 0x5011c
-/* [RW 2] Load (FIC1) channel group priority. The lowest priority is 0; the
-   highest priority is 3. It is supposed that the Store channel is the
-   compliment of the other 3 groups. */
-#define TCM_REG_GR_LD1_PR					 0x50120
-/* [RW 4] The number of double REG-pairs; loaded from the STORM context and
-   sent to STORM; for a specific connection type. The double REG-pairs are
-   used to align to STORM context row size of 128 bits. The offset of these
-   data in the STORM context is always 0. Index _i stands for the connection
-   type (one of 16). */
-#define TCM_REG_N_SM_CTX_LD_0					 0x50050
-#define TCM_REG_N_SM_CTX_LD_1					 0x50054
-#define TCM_REG_N_SM_CTX_LD_2					 0x50058
-#define TCM_REG_N_SM_CTX_LD_3					 0x5005c
-#define TCM_REG_N_SM_CTX_LD_4					 0x50060
-#define TCM_REG_N_SM_CTX_LD_5					 0x50064
-/* [RW 1] Input pbf Interface enable. If 0 - the valid input is disregarded;
-   acknowledge output is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define TCM_REG_PBF_IFEN					 0x50024
-/* [RC 1] Message length mismatch (relative to last indication) at the In#7
-   interface. */
-#define TCM_REG_PBF_LENGTH_MIS					 0x5016c
-/* [RW 3] The weight of the input pbf in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define TCM_REG_PBF_WEIGHT					 0x500b4
-#define TCM_REG_PHYS_QNUM0_0					 0x500e0
-#define TCM_REG_PHYS_QNUM0_1					 0x500e4
-#define TCM_REG_PHYS_QNUM1_0					 0x500e8
-#define TCM_REG_PHYS_QNUM1_1					 0x500ec
-#define TCM_REG_PHYS_QNUM2_0					 0x500f0
-#define TCM_REG_PHYS_QNUM2_1					 0x500f4
-#define TCM_REG_PHYS_QNUM3_0					 0x500f8
-#define TCM_REG_PHYS_QNUM3_1					 0x500fc
-/* [RW 1] Input prs Interface enable. If 0 - the valid input is disregarded;
-   acknowledge output is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define TCM_REG_PRS_IFEN					 0x50020
-/* [RC 1] Message length mismatch (relative to last indication) at the In#6
-   interface. */
-#define TCM_REG_PRS_LENGTH_MIS					 0x50168
-/* [RW 3] The weight of the input prs in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define TCM_REG_PRS_WEIGHT					 0x500b0
-/* [RW 8] The Event ID for Timers formatting in case of stop done. */
-#define TCM_REG_STOP_EVNT_ID					 0x500a8
-/* [RC 1] Message length mismatch (relative to last indication) at the STORM
-   interface. */
-#define TCM_REG_STORM_LENGTH_MIS				 0x50160
-/* [RW 1] STORM - CM Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define TCM_REG_STORM_TCM_IFEN					 0x50010
-/* [RW 3] The weight of the STORM input in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define TCM_REG_STORM_WEIGHT					 0x500ac
-/* [RW 1] CM - CFC Interface enable. If 0 - the valid input is disregarded;
-   acknowledge output is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define TCM_REG_TCM_CFC_IFEN					 0x50040
-/* [RW 11] Interrupt mask register #0 read/write */
-#define TCM_REG_TCM_INT_MASK					 0x501dc
-/* [R 11] Interrupt register #0 read */
-#define TCM_REG_TCM_INT_STS					 0x501d0
-/* [RW 27] Parity mask register #0 read/write */
-#define TCM_REG_TCM_PRTY_MASK					 0x501ec
-/* [R 27] Parity register #0 read */
-#define TCM_REG_TCM_PRTY_STS					 0x501e0
-/* [RC 27] Parity register #0 read clear */
-#define TCM_REG_TCM_PRTY_STS_CLR				 0x501e4
-/* [RW 3] The size of AG context region 0 in REG-pairs. Designates the MS
-   REG-pair number (e.g. if region 0 is 6 REG-pairs; the value should be 5).
-   Is used to determine the number of the AG context REG-pairs written back;
-   when the input message Reg1WbFlg isn't set. */
-#define TCM_REG_TCM_REG0_SZ					 0x500d8
-/* [RW 1] CM - STORM 0 Interface enable. If 0 - the acknowledge input is
-   disregarded; valid is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define TCM_REG_TCM_STORM0_IFEN 				 0x50004
-/* [RW 1] CM - STORM 1 Interface enable. If 0 - the acknowledge input is
-   disregarded; valid is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define TCM_REG_TCM_STORM1_IFEN 				 0x50008
-/* [RW 1] CM - QM Interface enable. If 0 - the acknowledge input is
-   disregarded; valid is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define TCM_REG_TCM_TQM_IFEN					 0x5000c
-/* [RW 1] If set the Q index; received from the QM is inserted to event ID. */
-#define TCM_REG_TCM_TQM_USE_Q					 0x500d4
-/* [RW 28] The CM header for Timers expiration command. */
-#define TCM_REG_TM_TCM_HDR					 0x50098
-/* [RW 1] Timers - CM Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define TCM_REG_TM_TCM_IFEN					 0x5001c
-/* [RW 3] The weight of the Timers input in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define TCM_REG_TM_WEIGHT					 0x500d0
-/* [RW 6] QM output initial credit. Max credit available - 32.Write writes
-   the initial credit value; read returns the current value of the credit
-   counter. Must be initialized to 32 at start-up. */
-#define TCM_REG_TQM_INIT_CRD					 0x5021c
-/* [RW 3] The weight of the QM (primary) input in the WRR mechanism. 0
-   stands for weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define TCM_REG_TQM_P_WEIGHT					 0x500c8
-/* [RW 3] The weight of the QM (secondary) input in the WRR mechanism. 0
-   stands for weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define TCM_REG_TQM_S_WEIGHT					 0x500cc
-/* [RW 28] The CM header value for QM request (primary). */
-#define TCM_REG_TQM_TCM_HDR_P					 0x50090
-/* [RW 28] The CM header value for QM request (secondary). */
-#define TCM_REG_TQM_TCM_HDR_S					 0x50094
-/* [RW 1] QM - CM Interface enable. If 0 - the valid input is disregarded;
-   acknowledge output is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define TCM_REG_TQM_TCM_IFEN					 0x50014
-/* [RW 1] Input SDM Interface enable. If 0 - the valid input is disregarded;
-   acknowledge output is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define TCM_REG_TSDM_IFEN					 0x50018
-/* [RC 1] Message length mismatch (relative to last indication) at the SDM
-   interface. */
-#define TCM_REG_TSDM_LENGTH_MIS 				 0x50164
-/* [RW 3] The weight of the SDM input in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define TCM_REG_TSDM_WEIGHT					 0x500c4
-/* [RW 1] Input usem Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define TCM_REG_USEM_IFEN					 0x50028
-/* [RC 1] Message length mismatch (relative to last indication) at the In#8
-   interface. */
-#define TCM_REG_USEM_LENGTH_MIS 				 0x50170
-/* [RW 3] The weight of the input usem in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define TCM_REG_USEM_WEIGHT					 0x500b8
-/* [RW 21] Indirect access to the descriptor table of the XX protection
-   mechanism. The fields are: [5:0] - length of the message; 15:6] - message
-   pointer; 20:16] - next pointer. */
-#define TCM_REG_XX_DESCR_TABLE					 0x50280
-#define TCM_REG_XX_DESCR_TABLE_SIZE				 29
-/* [R 6] Use to read the value of XX protection Free counter. */
-#define TCM_REG_XX_FREE 					 0x50178
-/* [RW 6] Initial value for the credit counter; responsible for fulfilling
-   of the Input Stage XX protection buffer by the XX protection pending
-   messages. Max credit available - 127.Write writes the initial credit
-   value; read returns the current value of the credit counter. Must be
-   initialized to 19 at start-up. */
-#define TCM_REG_XX_INIT_CRD					 0x50220
-/* [RW 6] Maximum link list size (messages locked) per connection in the XX
-   protection. */
-#define TCM_REG_XX_MAX_LL_SZ					 0x50044
-/* [RW 6] The maximum number of pending messages; which may be stored in XX
-   protection. ~tcm_registers_xx_free.xx_free is read on read. */
-#define TCM_REG_XX_MSG_NUM					 0x50224
-/* [RW 8] The Event ID; sent to the STORM in case of XX overflow. */
-#define TCM_REG_XX_OVFL_EVNT_ID 				 0x50048
-/* [RW 16] Indirect access to the XX table of the XX protection mechanism.
-   The fields are:[4:0] - tail pointer; [10:5] - Link List size; 15:11] -
-   header pointer. */
-#define TCM_REG_XX_TABLE					 0x50240
-/* [RW 4] Load value for cfc ac credit cnt. */
-#define TM_REG_CFC_AC_CRDCNT_VAL				 0x164208
-/* [RW 4] Load value for cfc cld credit cnt. */
-#define TM_REG_CFC_CLD_CRDCNT_VAL				 0x164210
-/* [RW 8] Client0 context region. */
-#define TM_REG_CL0_CONT_REGION					 0x164030
-/* [RW 8] Client1 context region. */
-#define TM_REG_CL1_CONT_REGION					 0x164034
-/* [RW 8] Client2 context region. */
-#define TM_REG_CL2_CONT_REGION					 0x164038
-/* [RW 2] Client in High priority client number. */
-#define TM_REG_CLIN_PRIOR0_CLIENT				 0x164024
-/* [RW 4] Load value for clout0 cred cnt. */
-#define TM_REG_CLOUT_CRDCNT0_VAL				 0x164220
-/* [RW 4] Load value for clout1 cred cnt. */
-#define TM_REG_CLOUT_CRDCNT1_VAL				 0x164228
-/* [RW 4] Load value for clout2 cred cnt. */
-#define TM_REG_CLOUT_CRDCNT2_VAL				 0x164230
-/* [RW 1] Enable client0 input. */
-#define TM_REG_EN_CL0_INPUT					 0x164008
-/* [RW 1] Enable client1 input. */
-#define TM_REG_EN_CL1_INPUT					 0x16400c
-/* [RW 1] Enable client2 input. */
-#define TM_REG_EN_CL2_INPUT					 0x164010
-#define TM_REG_EN_LINEAR0_TIMER 				 0x164014
-/* [RW 1] Enable real time counter. */
-#define TM_REG_EN_REAL_TIME_CNT 				 0x1640d8
-/* [RW 1] Enable for Timers state machines. */
-#define TM_REG_EN_TIMERS					 0x164000
-/* [RW 4] Load value for expiration credit cnt. CFC max number of
-   outstanding load requests for timers (expiration) context loading. */
-#define TM_REG_EXP_CRDCNT_VAL					 0x164238
-/* [RW 32] Linear0 logic address. */
-#define TM_REG_LIN0_LOGIC_ADDR					 0x164240
-/* [RW 18] Linear0 Max active cid (in banks of 32 entries). */
-#define TM_REG_LIN0_MAX_ACTIVE_CID				 0x164048
-/* [ST 16] Linear0 Number of scans counter. */
-#define TM_REG_LIN0_NUM_SCANS					 0x1640a0
-/* [WB 64] Linear0 phy address. */
-#define TM_REG_LIN0_PHY_ADDR					 0x164270
-/* [RW 1] Linear0 physical address valid. */
-#define TM_REG_LIN0_PHY_ADDR_VALID				 0x164248
-#define TM_REG_LIN0_SCAN_ON					 0x1640d0
-/* [RW 24] Linear0 array scan timeout. */
-#define TM_REG_LIN0_SCAN_TIME					 0x16403c
-#define TM_REG_LIN0_VNIC_UC					 0x164128
-/* [RW 32] Linear1 logic address. */
-#define TM_REG_LIN1_LOGIC_ADDR					 0x164250
-/* [WB 64] Linear1 phy address. */
-#define TM_REG_LIN1_PHY_ADDR					 0x164280
-/* [RW 1] Linear1 physical address valid. */
-#define TM_REG_LIN1_PHY_ADDR_VALID				 0x164258
-/* [RW 6] Linear timer set_clear fifo threshold. */
-#define TM_REG_LIN_SETCLR_FIFO_ALFULL_THR			 0x164070
-/* [RW 2] Load value for pci arbiter credit cnt. */
-#define TM_REG_PCIARB_CRDCNT_VAL				 0x164260
-/* [RW 20] The amount of hardware cycles for each timer tick. */
-#define TM_REG_TIMER_TICK_SIZE					 0x16401c
-/* [RW 8] Timers Context region. */
-#define TM_REG_TM_CONTEXT_REGION				 0x164044
-/* [RW 1] Interrupt mask register #0 read/write */
-#define TM_REG_TM_INT_MASK					 0x1640fc
-/* [R 1] Interrupt register #0 read */
-#define TM_REG_TM_INT_STS					 0x1640f0
-/* [RW 7] Parity mask register #0 read/write */
-#define TM_REG_TM_PRTY_MASK					 0x16410c
-/* [RC 7] Parity register #0 read clear */
-#define TM_REG_TM_PRTY_STS_CLR					 0x164104
-/* [RW 8] The event id for aggregated interrupt 0 */
-#define TSDM_REG_AGG_INT_EVENT_0				 0x42038
-#define TSDM_REG_AGG_INT_EVENT_1				 0x4203c
-#define TSDM_REG_AGG_INT_EVENT_2				 0x42040
-#define TSDM_REG_AGG_INT_EVENT_3				 0x42044
-#define TSDM_REG_AGG_INT_EVENT_4				 0x42048
-/* [RW 1] The T bit for aggregated interrupt 0 */
-#define TSDM_REG_AGG_INT_T_0					 0x420b8
-#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 completion counter #0 */
-#define TSDM_REG_CMP_COUNTER_MAX0				 0x4201c
-/* [RW 16] The maximum value of the completion counter #1 */
-#define TSDM_REG_CMP_COUNTER_MAX1				 0x42020
-/* [RW 16] The maximum value of the completion counter #2 */
-#define TSDM_REG_CMP_COUNTER_MAX2				 0x42024
-/* [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. */
-#define TSDM_REG_CMP_COUNTER_START_ADDR 			 0x4200c
-#define TSDM_REG_ENABLE_IN1					 0x42238
-#define TSDM_REG_ENABLE_IN2					 0x4223c
-#define TSDM_REG_ENABLE_OUT1					 0x42240
-#define TSDM_REG_ENABLE_OUT2					 0x42244
-/* [RW 4] The initial number of messages that can be sent to the pxp control
-   interface without receiving any ACK. */
-#define TSDM_REG_INIT_CREDIT_PXP_CTRL				 0x424bc
-/* [ST 32] The number of ACK after placement messages received */
-#define TSDM_REG_NUM_OF_ACK_AFTER_PLACE 			 0x4227c
-/* [ST 32] The number of packet end messages received from the parser */
-#define TSDM_REG_NUM_OF_PKT_END_MSG				 0x42274
-/* [ST 32] The number of requests received from the pxp async if */
-#define TSDM_REG_NUM_OF_PXP_ASYNC_REQ				 0x42278
-/* [ST 32] The number of commands received in queue 0 */
-#define TSDM_REG_NUM_OF_Q0_CMD					 0x42248
-/* [ST 32] The number of commands received in queue 10 */
-#define TSDM_REG_NUM_OF_Q10_CMD 				 0x4226c
-/* [ST 32] The number of commands received in queue 11 */
-#define TSDM_REG_NUM_OF_Q11_CMD 				 0x42270
-/* [ST 32] The number of commands received in queue 1 */
-#define TSDM_REG_NUM_OF_Q1_CMD					 0x4224c
-/* [ST 32] The number of commands received in queue 3 */
-#define TSDM_REG_NUM_OF_Q3_CMD					 0x42250
-/* [ST 32] The number of commands received in queue 4 */
-#define TSDM_REG_NUM_OF_Q4_CMD					 0x42254
-/* [ST 32] The number of commands received in queue 5 */
-#define TSDM_REG_NUM_OF_Q5_CMD					 0x42258
-/* [ST 32] The number of commands received in queue 6 */
-#define TSDM_REG_NUM_OF_Q6_CMD					 0x4225c
-/* [ST 32] The number of commands received in queue 7 */
-#define TSDM_REG_NUM_OF_Q7_CMD					 0x42260
-/* [ST 32] The number of commands received in queue 8 */
-#define TSDM_REG_NUM_OF_Q8_CMD					 0x42264
-/* [ST 32] The number of commands received in queue 9 */
-#define TSDM_REG_NUM_OF_Q9_CMD					 0x42268
-/* [RW 13] The start address in the internal RAM for the packet end message */
-#define TSDM_REG_PCK_END_MSG_START_ADDR 			 0x42014
-/* [RW 13] The start address in the internal RAM for queue counters */
-#define TSDM_REG_Q_COUNTER_START_ADDR				 0x42010
-/* [R 1] pxp_ctrl rd_data fifo empty in sdm_dma_rsp block */
-#define TSDM_REG_RSP_PXP_CTRL_RDATA_EMPTY			 0x42548
-/* [R 1] parser fifo empty in sdm_sync block */
-#define TSDM_REG_SYNC_PARSER_EMPTY				 0x42550
-/* [R 1] parser serial fifo empty in sdm_sync block */
-#define TSDM_REG_SYNC_SYNC_EMPTY				 0x42558
-/* [RW 32] Tick for timer counter. Applicable only when
-   ~tsdm_registers_timer_tick_enable.timer_tick_enable =1 */
-#define TSDM_REG_TIMER_TICK					 0x42000
-/* [RW 32] Interrupt mask register #0 read/write */
-#define TSDM_REG_TSDM_INT_MASK_0				 0x4229c
-#define TSDM_REG_TSDM_INT_MASK_1				 0x422ac
-/* [R 32] Interrupt register #0 read */
-#define TSDM_REG_TSDM_INT_STS_0 				 0x42290
-#define TSDM_REG_TSDM_INT_STS_1 				 0x422a0
-/* [RW 11] Parity mask register #0 read/write */
-#define TSDM_REG_TSDM_PRTY_MASK 				 0x422bc
-/* [R 11] Parity register #0 read */
-#define TSDM_REG_TSDM_PRTY_STS					 0x422b0
-/* [RC 11] Parity register #0 read clear */
-#define TSDM_REG_TSDM_PRTY_STS_CLR				 0x422b4
-/* [RW 5] The number of time_slots in the arbitration cycle */
-#define TSEM_REG_ARB_CYCLE_SIZE 				 0x180034
-/* [RW 3] The source that is associated with arbitration element 0. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2 */
-#define TSEM_REG_ARB_ELEMENT0					 0x180020
-/* [RW 3] The source that is associated with arbitration element 1. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2.
-   Could not be equal to register ~tsem_registers_arb_element0.arb_element0 */
-#define TSEM_REG_ARB_ELEMENT1					 0x180024
-/* [RW 3] The source that is associated with arbitration element 2. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2.
-   Could not be equal to register ~tsem_registers_arb_element0.arb_element0
-   and ~tsem_registers_arb_element1.arb_element1 */
-#define TSEM_REG_ARB_ELEMENT2					 0x180028
-/* [RW 3] The source that is associated with arbitration element 3. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2.Could
-   not be equal to register ~tsem_registers_arb_element0.arb_element0 and
-   ~tsem_registers_arb_element1.arb_element1 and
-   ~tsem_registers_arb_element2.arb_element2 */
-#define TSEM_REG_ARB_ELEMENT3					 0x18002c
-/* [RW 3] The source that is associated with arbitration element 4. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2.
-   Could not be equal to register ~tsem_registers_arb_element0.arb_element0
-   and ~tsem_registers_arb_element1.arb_element1 and
-   ~tsem_registers_arb_element2.arb_element2 and
-   ~tsem_registers_arb_element3.arb_element3 */
-#define TSEM_REG_ARB_ELEMENT4					 0x180030
-#define TSEM_REG_ENABLE_IN					 0x1800a4
-#define TSEM_REG_ENABLE_OUT					 0x1800a8
-/* [RW 32] This address space contains all registers and memories that are
-   placed in SEM_FAST block. The SEM_FAST registers are described in
-   appendix B. In order to access the sem_fast registers the base address
-   ~fast_memory.fast_memory should be added to eachsem_fast register offset. */
-#define TSEM_REG_FAST_MEMORY					 0x1a0000
-/* [RW 1] Disables input messages from FIC0 May be updated during run_time
-   by the microcode */
-#define TSEM_REG_FIC0_DISABLE					 0x180224
-/* [RW 1] Disables input messages from FIC1 May be updated during run_time
-   by the microcode */
-#define TSEM_REG_FIC1_DISABLE					 0x180234
-/* [RW 15] Interrupt table Read and write access to it is not possible in
-   the middle of the work */
-#define TSEM_REG_INT_TABLE					 0x180400
-/* [ST 24] Statistics register. The number of messages that entered through
-   FIC0 */
-#define TSEM_REG_MSG_NUM_FIC0					 0x180000
-/* [ST 24] Statistics register. The number of messages that entered through
-   FIC1 */
-#define TSEM_REG_MSG_NUM_FIC1					 0x180004
-/* [ST 24] Statistics register. The number of messages that were sent to
-   FOC0 */
-#define TSEM_REG_MSG_NUM_FOC0					 0x180008
-/* [ST 24] Statistics register. The number of messages that were sent to
-   FOC1 */
-#define TSEM_REG_MSG_NUM_FOC1					 0x18000c
-/* [ST 24] Statistics register. The number of messages that were sent to
-   FOC2 */
-#define TSEM_REG_MSG_NUM_FOC2					 0x180010
-/* [ST 24] Statistics register. The number of messages that were sent to
-   FOC3 */
-#define TSEM_REG_MSG_NUM_FOC3					 0x180014
-/* [RW 1] Disables input messages from the passive buffer May be updated
-   during run_time by the microcode */
-#define TSEM_REG_PAS_DISABLE					 0x18024c
-/* [WB 128] Debug only. Passive buffer memory */
-#define TSEM_REG_PASSIVE_BUFFER 				 0x181000
-/* [WB 46] pram memory. B45 is parity; b[44:0] - data. */
-#define TSEM_REG_PRAM						 0x1c0000
-/* [R 8] Valid sleeping threads indication have bit per thread */
-#define TSEM_REG_SLEEP_THREADS_VALID				 0x18026c
-/* [R 1] EXT_STORE FIFO is empty in sem_slow_ls_ext */
-#define TSEM_REG_SLOW_EXT_STORE_EMPTY				 0x1802a0
-/* [RW 8] List of free threads . There is a bit per thread. */
-#define TSEM_REG_THREADS_LIST					 0x1802e4
-/* [RC 32] Parity register #0 read clear */
-#define TSEM_REG_TSEM_PRTY_STS_CLR_0				 0x180118
-#define TSEM_REG_TSEM_PRTY_STS_CLR_1				 0x180128
-/* [RW 3] The arbitration scheme of time_slot 0 */
-#define TSEM_REG_TS_0_AS					 0x180038
-/* [RW 3] The arbitration scheme of time_slot 10 */
-#define TSEM_REG_TS_10_AS					 0x180060
-/* [RW 3] The arbitration scheme of time_slot 11 */
-#define TSEM_REG_TS_11_AS					 0x180064
-/* [RW 3] The arbitration scheme of time_slot 12 */
-#define TSEM_REG_TS_12_AS					 0x180068
-/* [RW 3] The arbitration scheme of time_slot 13 */
-#define TSEM_REG_TS_13_AS					 0x18006c
-/* [RW 3] The arbitration scheme of time_slot 14 */
-#define TSEM_REG_TS_14_AS					 0x180070
-/* [RW 3] The arbitration scheme of time_slot 15 */
-#define TSEM_REG_TS_15_AS					 0x180074
-/* [RW 3] The arbitration scheme of time_slot 16 */
-#define TSEM_REG_TS_16_AS					 0x180078
-/* [RW 3] The arbitration scheme of time_slot 17 */
-#define TSEM_REG_TS_17_AS					 0x18007c
-/* [RW 3] The arbitration scheme of time_slot 18 */
-#define TSEM_REG_TS_18_AS					 0x180080
-/* [RW 3] The arbitration scheme of time_slot 1 */
-#define TSEM_REG_TS_1_AS					 0x18003c
-/* [RW 3] The arbitration scheme of time_slot 2 */
-#define TSEM_REG_TS_2_AS					 0x180040
-/* [RW 3] The arbitration scheme of time_slot 3 */
-#define TSEM_REG_TS_3_AS					 0x180044
-/* [RW 3] The arbitration scheme of time_slot 4 */
-#define TSEM_REG_TS_4_AS					 0x180048
-/* [RW 3] The arbitration scheme of time_slot 5 */
-#define TSEM_REG_TS_5_AS					 0x18004c
-/* [RW 3] The arbitration scheme of time_slot 6 */
-#define TSEM_REG_TS_6_AS					 0x180050
-/* [RW 3] The arbitration scheme of time_slot 7 */
-#define TSEM_REG_TS_7_AS					 0x180054
-/* [RW 3] The arbitration scheme of time_slot 8 */
-#define TSEM_REG_TS_8_AS					 0x180058
-/* [RW 3] The arbitration scheme of time_slot 9 */
-#define TSEM_REG_TS_9_AS					 0x18005c
-/* [RW 32] Interrupt mask register #0 read/write */
-#define TSEM_REG_TSEM_INT_MASK_0				 0x180100
-#define TSEM_REG_TSEM_INT_MASK_1				 0x180110
-/* [R 32] Interrupt register #0 read */
-#define TSEM_REG_TSEM_INT_STS_0 				 0x1800f4
-#define TSEM_REG_TSEM_INT_STS_1 				 0x180104
-/* [RW 32] Parity mask register #0 read/write */
-#define TSEM_REG_TSEM_PRTY_MASK_0				 0x180120
-#define TSEM_REG_TSEM_PRTY_MASK_1				 0x180130
-/* [R 32] Parity register #0 read */
-#define TSEM_REG_TSEM_PRTY_STS_0				 0x180114
-#define TSEM_REG_TSEM_PRTY_STS_1				 0x180124
-/* [W 7] VF or PF ID for reset error bit. Values 0-63 reset error bit for 64
- * VF; values 64-67 reset error for 4 PF; values 68-127 are not valid. */
-#define TSEM_REG_VFPF_ERR_NUM					 0x180380
-/* [RW 32] Indirect access to AG context with 32-bits granularity. The bits
- * [10:8] of the address should be the offset within the accessed LCID
- * context; the bits [7:0] are the accessed LCID.Example: to write to REG10
- * LCID100. The RBC address should be 12'ha64. */
-#define UCM_REG_AG_CTX						 0xe2000
-/* [R 5] Used to read the XX protection CAM occupancy counter. */
-#define UCM_REG_CAM_OCCUP					 0xe0170
-/* [RW 1] CDU AG read Interface enable. If 0 - the request input is
-   disregarded; valid output is deasserted; all other signals are treated as
-   usual; if 1 - normal activity. */
-#define UCM_REG_CDU_AG_RD_IFEN					 0xe0038
-/* [RW 1] CDU AG write Interface enable. If 0 - the request and valid input
-   are disregarded; all other signals are treated as usual; if 1 - normal
-   activity. */
-#define UCM_REG_CDU_AG_WR_IFEN					 0xe0034
-/* [RW 1] CDU STORM read Interface enable. If 0 - the request input is
-   disregarded; valid output is deasserted; all other signals are treated as
-   usual; if 1 - normal activity. */
-#define UCM_REG_CDU_SM_RD_IFEN					 0xe0040
-/* [RW 1] CDU STORM write Interface enable. If 0 - the request and valid
-   input is disregarded; all other signals are treated as usual; if 1 -
-   normal activity. */
-#define UCM_REG_CDU_SM_WR_IFEN					 0xe003c
-/* [RW 4] CFC output initial credit. Max credit available - 15.Write writes
-   the initial credit value; read returns the current value of the credit
-   counter. Must be initialized to 1 at start-up. */
-#define UCM_REG_CFC_INIT_CRD					 0xe0204
-/* [RW 3] The weight of the CP input in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define UCM_REG_CP_WEIGHT					 0xe00c4
-/* [RW 1] Input csem Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define UCM_REG_CSEM_IFEN					 0xe0028
-/* [RC 1] Set when the message length mismatch (relative to last indication)
-   at the csem interface is detected. */
-#define UCM_REG_CSEM_LENGTH_MIS 				 0xe0160
-/* [RW 3] The weight of the input csem in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define UCM_REG_CSEM_WEIGHT					 0xe00b8
-/* [RW 1] Input dorq Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define UCM_REG_DORQ_IFEN					 0xe0030
-/* [RC 1] Set when the message length mismatch (relative to last indication)
-   at the dorq interface is detected. */
-#define UCM_REG_DORQ_LENGTH_MIS 				 0xe0168
-/* [RW 3] The weight of the input dorq in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define UCM_REG_DORQ_WEIGHT					 0xe00c0
-/* [RW 8] The Event ID in case ErrorFlg input message bit is set. */
-#define UCM_REG_ERR_EVNT_ID					 0xe00a4
-/* [RW 28] The CM erroneous header for QM and Timers formatting. */
-#define UCM_REG_ERR_UCM_HDR					 0xe00a0
-/* [RW 8] The Event ID for Timers expiration. */
-#define UCM_REG_EXPR_EVNT_ID					 0xe00a8
-/* [RW 8] FIC0 output initial credit. Max credit available - 255.Write
-   writes the initial credit value; read returns the current value of the
-   credit counter. Must be initialized to 64 at start-up. */
-#define UCM_REG_FIC0_INIT_CRD					 0xe020c
-/* [RW 8] FIC1 output initial credit. Max credit available - 255.Write
-   writes the initial credit value; read returns the current value of the
-   credit counter. Must be initialized to 64 at start-up. */
-#define UCM_REG_FIC1_INIT_CRD					 0xe0210
-/* [RW 1] Arbitration between Input Arbiter groups: 0 - fair Round-Robin; 1
-   - strict priority defined by ~ucm_registers_gr_ag_pr.gr_ag_pr;
-   ~ucm_registers_gr_ld0_pr.gr_ld0_pr and
-   ~ucm_registers_gr_ld1_pr.gr_ld1_pr. */
-#define UCM_REG_GR_ARB_TYPE					 0xe0144
-/* [RW 2] Load (FIC0) channel group priority. The lowest priority is 0; the
-   highest priority is 3. It is supposed that the Store channel group is
-   compliment to the others. */
-#define UCM_REG_GR_LD0_PR					 0xe014c
-/* [RW 2] Load (FIC1) channel group priority. The lowest priority is 0; the
-   highest priority is 3. It is supposed that the Store channel group is
-   compliment to the others. */
-#define UCM_REG_GR_LD1_PR					 0xe0150
-/* [RW 2] The queue index for invalidate counter flag decision. */
-#define UCM_REG_INV_CFLG_Q					 0xe00e4
-/* [RW 5] The number of double REG-pairs; loaded from the STORM context and
-   sent to STORM; for a specific connection type. the double REG-pairs are
-   used in order to align to STORM context row size of 128 bits. The offset
-   of these data in the STORM context is always 0. Index _i stands for the
-   connection type (one of 16). */
-#define UCM_REG_N_SM_CTX_LD_0					 0xe0054
-#define UCM_REG_N_SM_CTX_LD_1					 0xe0058
-#define UCM_REG_N_SM_CTX_LD_2					 0xe005c
-#define UCM_REG_N_SM_CTX_LD_3					 0xe0060
-#define UCM_REG_N_SM_CTX_LD_4					 0xe0064
-#define UCM_REG_N_SM_CTX_LD_5					 0xe0068
-#define UCM_REG_PHYS_QNUM0_0					 0xe0110
-#define UCM_REG_PHYS_QNUM0_1					 0xe0114
-#define UCM_REG_PHYS_QNUM1_0					 0xe0118
-#define UCM_REG_PHYS_QNUM1_1					 0xe011c
-#define UCM_REG_PHYS_QNUM2_0					 0xe0120
-#define UCM_REG_PHYS_QNUM2_1					 0xe0124
-#define UCM_REG_PHYS_QNUM3_0					 0xe0128
-#define UCM_REG_PHYS_QNUM3_1					 0xe012c
-/* [RW 8] The Event ID for Timers formatting in case of stop done. */
-#define UCM_REG_STOP_EVNT_ID					 0xe00ac
-/* [RC 1] Set when the message length mismatch (relative to last indication)
-   at the STORM interface is detected. */
-#define UCM_REG_STORM_LENGTH_MIS				 0xe0154
-/* [RW 1] STORM - CM Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define UCM_REG_STORM_UCM_IFEN					 0xe0010
-/* [RW 3] The weight of the STORM input in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define UCM_REG_STORM_WEIGHT					 0xe00b0
-/* [RW 4] Timers output initial credit. Max credit available - 15.Write
-   writes the initial credit value; read returns the current value of the
-   credit counter. Must be initialized to 4 at start-up. */
-#define UCM_REG_TM_INIT_CRD					 0xe021c
-/* [RW 28] The CM header for Timers expiration command. */
-#define UCM_REG_TM_UCM_HDR					 0xe009c
-/* [RW 1] Timers - CM Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define UCM_REG_TM_UCM_IFEN					 0xe001c
-/* [RW 3] The weight of the Timers input in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define UCM_REG_TM_WEIGHT					 0xe00d4
-/* [RW 1] Input tsem Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define UCM_REG_TSEM_IFEN					 0xe0024
-/* [RC 1] Set when the message length mismatch (relative to last indication)
-   at the tsem interface is detected. */
-#define UCM_REG_TSEM_LENGTH_MIS 				 0xe015c
-/* [RW 3] The weight of the input tsem in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define UCM_REG_TSEM_WEIGHT					 0xe00b4
-/* [RW 1] CM - CFC Interface enable. If 0 - the valid input is disregarded;
-   acknowledge output is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define UCM_REG_UCM_CFC_IFEN					 0xe0044
-/* [RW 11] Interrupt mask register #0 read/write */
-#define UCM_REG_UCM_INT_MASK					 0xe01d4
-/* [R 11] Interrupt register #0 read */
-#define UCM_REG_UCM_INT_STS					 0xe01c8
-/* [RW 27] Parity mask register #0 read/write */
-#define UCM_REG_UCM_PRTY_MASK					 0xe01e4
-/* [R 27] Parity register #0 read */
-#define UCM_REG_UCM_PRTY_STS					 0xe01d8
-/* [RC 27] Parity register #0 read clear */
-#define UCM_REG_UCM_PRTY_STS_CLR				 0xe01dc
-/* [RW 2] The size of AG context region 0 in REG-pairs. Designates the MS
-   REG-pair number (e.g. if region 0 is 6 REG-pairs; the value should be 5).
-   Is used to determine the number of the AG context REG-pairs written back;
-   when the Reg1WbFlg isn't set. */
-#define UCM_REG_UCM_REG0_SZ					 0xe00dc
-/* [RW 1] CM - STORM 0 Interface enable. If 0 - the acknowledge input is
-   disregarded; valid is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define UCM_REG_UCM_STORM0_IFEN 				 0xe0004
-/* [RW 1] CM - STORM 1 Interface enable. If 0 - the acknowledge input is
-   disregarded; valid is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define UCM_REG_UCM_STORM1_IFEN 				 0xe0008
-/* [RW 1] CM - Timers Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define UCM_REG_UCM_TM_IFEN					 0xe0020
-/* [RW 1] CM - QM Interface enable. If 0 - the acknowledge input is
-   disregarded; valid is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define UCM_REG_UCM_UQM_IFEN					 0xe000c
-/* [RW 1] If set the Q index; received from the QM is inserted to event ID. */
-#define UCM_REG_UCM_UQM_USE_Q					 0xe00d8
-/* [RW 6] QM output initial credit. Max credit available - 32.Write writes
-   the initial credit value; read returns the current value of the credit
-   counter. Must be initialized to 32 at start-up. */
-#define UCM_REG_UQM_INIT_CRD					 0xe0220
-/* [RW 3] The weight of the QM (primary) input in the WRR mechanism. 0
-   stands for weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define UCM_REG_UQM_P_WEIGHT					 0xe00cc
-/* [RW 3] The weight of the QM (secondary) input in the WRR mechanism. 0
-   stands for weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define UCM_REG_UQM_S_WEIGHT					 0xe00d0
-/* [RW 28] The CM header value for QM request (primary). */
-#define UCM_REG_UQM_UCM_HDR_P					 0xe0094
-/* [RW 28] The CM header value for QM request (secondary). */
-#define UCM_REG_UQM_UCM_HDR_S					 0xe0098
-/* [RW 1] QM - CM Interface enable. If 0 - the valid input is disregarded;
-   acknowledge output is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define UCM_REG_UQM_UCM_IFEN					 0xe0014
-/* [RW 1] Input SDM Interface enable. If 0 - the valid input is disregarded;
-   acknowledge output is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define UCM_REG_USDM_IFEN					 0xe0018
-/* [RC 1] Set when the message length mismatch (relative to last indication)
-   at the SDM interface is detected. */
-#define UCM_REG_USDM_LENGTH_MIS 				 0xe0158
-/* [RW 3] The weight of the SDM input in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define UCM_REG_USDM_WEIGHT					 0xe00c8
-/* [RW 1] Input xsem Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define UCM_REG_XSEM_IFEN					 0xe002c
-/* [RC 1] Set when the message length mismatch (relative to last indication)
-   at the xsem interface isdetected. */
-#define UCM_REG_XSEM_LENGTH_MIS 				 0xe0164
-/* [RW 3] The weight of the input xsem in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define UCM_REG_XSEM_WEIGHT					 0xe00bc
-/* [RW 20] Indirect access to the descriptor table of the XX protection
-   mechanism. The fields are:[5:0] - message length; 14:6] - message
-   pointer; 19:15] - next pointer. */
-#define UCM_REG_XX_DESCR_TABLE					 0xe0280
-#define UCM_REG_XX_DESCR_TABLE_SIZE				 27
-/* [R 6] Use to read the XX protection Free counter. */
-#define UCM_REG_XX_FREE 					 0xe016c
-/* [RW 6] Initial value for the credit counter; responsible for fulfilling
-   of the Input Stage XX protection buffer by the XX protection pending
-   messages. Write writes the initial credit value; read returns the current
-   value of the credit counter. Must be initialized to 12 at start-up. */
-#define UCM_REG_XX_INIT_CRD					 0xe0224
-/* [RW 6] The maximum number of pending messages; which may be stored in XX
-   protection. ~ucm_registers_xx_free.xx_free read on read. */
-#define UCM_REG_XX_MSG_NUM					 0xe0228
-/* [RW 8] The Event ID; sent to the STORM in case of XX overflow. */
-#define UCM_REG_XX_OVFL_EVNT_ID 				 0xe004c
-/* [RW 16] Indirect access to the XX table of the XX protection mechanism.
-   The fields are: [4:0] - tail pointer; 10:5] - Link List size; 15:11] -
-   header pointer. */
-#define UCM_REG_XX_TABLE					 0xe0300
-#define UMAC_COMMAND_CONFIG_REG_IGNORE_TX_PAUSE			 (0x1<<28)
-#define UMAC_COMMAND_CONFIG_REG_LOOP_ENA			 (0x1<<15)
-#define UMAC_COMMAND_CONFIG_REG_NO_LGTH_CHECK			 (0x1<<24)
-#define UMAC_COMMAND_CONFIG_REG_PAD_EN				 (0x1<<5)
-#define UMAC_COMMAND_CONFIG_REG_PAUSE_IGNORE			 (0x1<<8)
-#define UMAC_COMMAND_CONFIG_REG_PROMIS_EN			 (0x1<<4)
-#define UMAC_COMMAND_CONFIG_REG_RX_ENA				 (0x1<<1)
-#define UMAC_COMMAND_CONFIG_REG_SW_RESET			 (0x1<<13)
-#define UMAC_COMMAND_CONFIG_REG_TX_ENA				 (0x1<<0)
-#define UMAC_REG_COMMAND_CONFIG					 0x8
-/* [RW 32] Register Bit 0 refers to Bit 16 of the MAC address; Bit 1 refers
- * to bit 17 of the MAC address etc. */
-#define UMAC_REG_MAC_ADDR0					 0xc
-/* [RW 16] Register Bit 0 refers to Bit 0 of the MAC address; Register Bit 1
- * refers to Bit 1 of the MAC address etc. Bits 16 to 31 are reserved. */
-#define UMAC_REG_MAC_ADDR1					 0x10
-/* [RW 14] Defines a 14-Bit maximum frame length used by the MAC receive
- * logic to check frames. */
-#define UMAC_REG_MAXFR						 0x14
-/* [RW 8] The event id for aggregated interrupt 0 */
-#define USDM_REG_AGG_INT_EVENT_0				 0xc4038
-#define USDM_REG_AGG_INT_EVENT_1				 0xc403c
-#define USDM_REG_AGG_INT_EVENT_2				 0xc4040
-#define USDM_REG_AGG_INT_EVENT_4				 0xc4048
-#define USDM_REG_AGG_INT_EVENT_5				 0xc404c
-#define USDM_REG_AGG_INT_EVENT_6				 0xc4050
-/* [RW 1] For each aggregated interrupt index whether the mode is normal (0)
-   or auto-mask-mode (1) */
-#define USDM_REG_AGG_INT_MODE_0 				 0xc41b8
-#define USDM_REG_AGG_INT_MODE_1 				 0xc41bc
-#define USDM_REG_AGG_INT_MODE_4 				 0xc41c8
-#define USDM_REG_AGG_INT_MODE_5 				 0xc41cc
-#define USDM_REG_AGG_INT_MODE_6 				 0xc41d0
-/* [RW 1] The T bit for aggregated interrupt 5 */
-#define USDM_REG_AGG_INT_T_5					 0xc40cc
-#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 completion counter #0 */
-#define USDM_REG_CMP_COUNTER_MAX0				 0xc401c
-/* [RW 16] The maximum value of the completion counter #1 */
-#define USDM_REG_CMP_COUNTER_MAX1				 0xc4020
-/* [RW 16] The maximum value of the completion counter #2 */
-#define USDM_REG_CMP_COUNTER_MAX2				 0xc4024
-/* [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. */
-#define USDM_REG_CMP_COUNTER_START_ADDR 			 0xc400c
-#define USDM_REG_ENABLE_IN1					 0xc4238
-#define USDM_REG_ENABLE_IN2					 0xc423c
-#define USDM_REG_ENABLE_OUT1					 0xc4240
-#define USDM_REG_ENABLE_OUT2					 0xc4244
-/* [RW 4] The initial number of messages that can be sent to the pxp control
-   interface without receiving any ACK. */
-#define USDM_REG_INIT_CREDIT_PXP_CTRL				 0xc44c0
-/* [ST 32] The number of ACK after placement messages received */
-#define USDM_REG_NUM_OF_ACK_AFTER_PLACE 			 0xc4280
-/* [ST 32] The number of packet end messages received from the parser */
-#define USDM_REG_NUM_OF_PKT_END_MSG				 0xc4278
-/* [ST 32] The number of requests received from the pxp async if */
-#define USDM_REG_NUM_OF_PXP_ASYNC_REQ				 0xc427c
-/* [ST 32] The number of commands received in queue 0 */
-#define USDM_REG_NUM_OF_Q0_CMD					 0xc4248
-/* [ST 32] The number of commands received in queue 10 */
-#define USDM_REG_NUM_OF_Q10_CMD 				 0xc4270
-/* [ST 32] The number of commands received in queue 11 */
-#define USDM_REG_NUM_OF_Q11_CMD 				 0xc4274
-/* [ST 32] The number of commands received in queue 1 */
-#define USDM_REG_NUM_OF_Q1_CMD					 0xc424c
-/* [ST 32] The number of commands received in queue 2 */
-#define USDM_REG_NUM_OF_Q2_CMD					 0xc4250
-/* [ST 32] The number of commands received in queue 3 */
-#define USDM_REG_NUM_OF_Q3_CMD					 0xc4254
-/* [ST 32] The number of commands received in queue 4 */
-#define USDM_REG_NUM_OF_Q4_CMD					 0xc4258
-/* [ST 32] The number of commands received in queue 5 */
-#define USDM_REG_NUM_OF_Q5_CMD					 0xc425c
-/* [ST 32] The number of commands received in queue 6 */
-#define USDM_REG_NUM_OF_Q6_CMD					 0xc4260
-/* [ST 32] The number of commands received in queue 7 */
-#define USDM_REG_NUM_OF_Q7_CMD					 0xc4264
-/* [ST 32] The number of commands received in queue 8 */
-#define USDM_REG_NUM_OF_Q8_CMD					 0xc4268
-/* [ST 32] The number of commands received in queue 9 */
-#define USDM_REG_NUM_OF_Q9_CMD					 0xc426c
-/* [RW 13] The start address in the internal RAM for the packet end message */
-#define USDM_REG_PCK_END_MSG_START_ADDR 			 0xc4014
-/* [RW 13] The start address in the internal RAM for queue counters */
-#define USDM_REG_Q_COUNTER_START_ADDR				 0xc4010
-/* [R 1] pxp_ctrl rd_data fifo empty in sdm_dma_rsp block */
-#define USDM_REG_RSP_PXP_CTRL_RDATA_EMPTY			 0xc4550
-/* [R 1] parser fifo empty in sdm_sync block */
-#define USDM_REG_SYNC_PARSER_EMPTY				 0xc4558
-/* [R 1] parser serial fifo empty in sdm_sync block */
-#define USDM_REG_SYNC_SYNC_EMPTY				 0xc4560
-/* [RW 32] Tick for timer counter. Applicable only when
-   ~usdm_registers_timer_tick_enable.timer_tick_enable =1 */
-#define USDM_REG_TIMER_TICK					 0xc4000
-/* [RW 32] Interrupt mask register #0 read/write */
-#define USDM_REG_USDM_INT_MASK_0				 0xc42a0
-#define USDM_REG_USDM_INT_MASK_1				 0xc42b0
-/* [R 32] Interrupt register #0 read */
-#define USDM_REG_USDM_INT_STS_0 				 0xc4294
-#define USDM_REG_USDM_INT_STS_1 				 0xc42a4
-/* [RW 11] Parity mask register #0 read/write */
-#define USDM_REG_USDM_PRTY_MASK 				 0xc42c0
-/* [R 11] Parity register #0 read */
-#define USDM_REG_USDM_PRTY_STS					 0xc42b4
-/* [RC 11] Parity register #0 read clear */
-#define USDM_REG_USDM_PRTY_STS_CLR				 0xc42b8
-/* [RW 5] The number of time_slots in the arbitration cycle */
-#define USEM_REG_ARB_CYCLE_SIZE 				 0x300034
-/* [RW 3] The source that is associated with arbitration element 0. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2 */
-#define USEM_REG_ARB_ELEMENT0					 0x300020
-/* [RW 3] The source that is associated with arbitration element 1. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2.
-   Could not be equal to register ~usem_registers_arb_element0.arb_element0 */
-#define USEM_REG_ARB_ELEMENT1					 0x300024
-/* [RW 3] The source that is associated with arbitration element 2. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2.
-   Could not be equal to register ~usem_registers_arb_element0.arb_element0
-   and ~usem_registers_arb_element1.arb_element1 */
-#define USEM_REG_ARB_ELEMENT2					 0x300028
-/* [RW 3] The source that is associated with arbitration element 3. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2.Could
-   not be equal to register ~usem_registers_arb_element0.arb_element0 and
-   ~usem_registers_arb_element1.arb_element1 and
-   ~usem_registers_arb_element2.arb_element2 */
-#define USEM_REG_ARB_ELEMENT3					 0x30002c
-/* [RW 3] The source that is associated with arbitration element 4. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2.
-   Could not be equal to register ~usem_registers_arb_element0.arb_element0
-   and ~usem_registers_arb_element1.arb_element1 and
-   ~usem_registers_arb_element2.arb_element2 and
-   ~usem_registers_arb_element3.arb_element3 */
-#define USEM_REG_ARB_ELEMENT4					 0x300030
-#define USEM_REG_ENABLE_IN					 0x3000a4
-#define USEM_REG_ENABLE_OUT					 0x3000a8
-/* [RW 32] This address space contains all registers and memories that are
-   placed in SEM_FAST block. The SEM_FAST registers are described in
-   appendix B. In order to access the sem_fast registers the base address
-   ~fast_memory.fast_memory should be added to eachsem_fast register offset. */
-#define USEM_REG_FAST_MEMORY					 0x320000
-/* [RW 1] Disables input messages from FIC0 May be updated during run_time
-   by the microcode */
-#define USEM_REG_FIC0_DISABLE					 0x300224
-/* [RW 1] Disables input messages from FIC1 May be updated during run_time
-   by the microcode */
-#define USEM_REG_FIC1_DISABLE					 0x300234
-/* [RW 15] Interrupt table Read and write access to it is not possible in
-   the middle of the work */
-#define USEM_REG_INT_TABLE					 0x300400
-/* [ST 24] Statistics register. The number of messages that entered through
-   FIC0 */
-#define USEM_REG_MSG_NUM_FIC0					 0x300000
-/* [ST 24] Statistics register. The number of messages that entered through
-   FIC1 */
-#define USEM_REG_MSG_NUM_FIC1					 0x300004
-/* [ST 24] Statistics register. The number of messages that were sent to
-   FOC0 */
-#define USEM_REG_MSG_NUM_FOC0					 0x300008
-/* [ST 24] Statistics register. The number of messages that were sent to
-   FOC1 */
-#define USEM_REG_MSG_NUM_FOC1					 0x30000c
-/* [ST 24] Statistics register. The number of messages that were sent to
-   FOC2 */
-#define USEM_REG_MSG_NUM_FOC2					 0x300010
-/* [ST 24] Statistics register. The number of messages that were sent to
-   FOC3 */
-#define USEM_REG_MSG_NUM_FOC3					 0x300014
-/* [RW 1] Disables input messages from the passive buffer May be updated
-   during run_time by the microcode */
-#define USEM_REG_PAS_DISABLE					 0x30024c
-/* [WB 128] Debug only. Passive buffer memory */
-#define USEM_REG_PASSIVE_BUFFER 				 0x302000
-/* [WB 46] pram memory. B45 is parity; b[44:0] - data. */
-#define USEM_REG_PRAM						 0x340000
-/* [R 16] Valid sleeping threads indication have bit per thread */
-#define USEM_REG_SLEEP_THREADS_VALID				 0x30026c
-/* [R 1] EXT_STORE FIFO is empty in sem_slow_ls_ext */
-#define USEM_REG_SLOW_EXT_STORE_EMPTY				 0x3002a0
-/* [RW 16] List of free threads . There is a bit per thread. */
-#define USEM_REG_THREADS_LIST					 0x3002e4
-/* [RW 3] The arbitration scheme of time_slot 0 */
-#define USEM_REG_TS_0_AS					 0x300038
-/* [RW 3] The arbitration scheme of time_slot 10 */
-#define USEM_REG_TS_10_AS					 0x300060
-/* [RW 3] The arbitration scheme of time_slot 11 */
-#define USEM_REG_TS_11_AS					 0x300064
-/* [RW 3] The arbitration scheme of time_slot 12 */
-#define USEM_REG_TS_12_AS					 0x300068
-/* [RW 3] The arbitration scheme of time_slot 13 */
-#define USEM_REG_TS_13_AS					 0x30006c
-/* [RW 3] The arbitration scheme of time_slot 14 */
-#define USEM_REG_TS_14_AS					 0x300070
-/* [RW 3] The arbitration scheme of time_slot 15 */
-#define USEM_REG_TS_15_AS					 0x300074
-/* [RW 3] The arbitration scheme of time_slot 16 */
-#define USEM_REG_TS_16_AS					 0x300078
-/* [RW 3] The arbitration scheme of time_slot 17 */
-#define USEM_REG_TS_17_AS					 0x30007c
-/* [RW 3] The arbitration scheme of time_slot 18 */
-#define USEM_REG_TS_18_AS					 0x300080
-/* [RW 3] The arbitration scheme of time_slot 1 */
-#define USEM_REG_TS_1_AS					 0x30003c
-/* [RW 3] The arbitration scheme of time_slot 2 */
-#define USEM_REG_TS_2_AS					 0x300040
-/* [RW 3] The arbitration scheme of time_slot 3 */
-#define USEM_REG_TS_3_AS					 0x300044
-/* [RW 3] The arbitration scheme of time_slot 4 */
-#define USEM_REG_TS_4_AS					 0x300048
-/* [RW 3] The arbitration scheme of time_slot 5 */
-#define USEM_REG_TS_5_AS					 0x30004c
-/* [RW 3] The arbitration scheme of time_slot 6 */
-#define USEM_REG_TS_6_AS					 0x300050
-/* [RW 3] The arbitration scheme of time_slot 7 */
-#define USEM_REG_TS_7_AS					 0x300054
-/* [RW 3] The arbitration scheme of time_slot 8 */
-#define USEM_REG_TS_8_AS					 0x300058
-/* [RW 3] The arbitration scheme of time_slot 9 */
-#define USEM_REG_TS_9_AS					 0x30005c
-/* [RW 32] Interrupt mask register #0 read/write */
-#define USEM_REG_USEM_INT_MASK_0				 0x300110
-#define USEM_REG_USEM_INT_MASK_1				 0x300120
-/* [R 32] Interrupt register #0 read */
-#define USEM_REG_USEM_INT_STS_0 				 0x300104
-#define USEM_REG_USEM_INT_STS_1 				 0x300114
-/* [RW 32] Parity mask register #0 read/write */
-#define USEM_REG_USEM_PRTY_MASK_0				 0x300130
-#define USEM_REG_USEM_PRTY_MASK_1				 0x300140
-/* [R 32] Parity register #0 read */
-#define USEM_REG_USEM_PRTY_STS_0				 0x300124
-#define USEM_REG_USEM_PRTY_STS_1				 0x300134
-/* [RC 32] Parity register #0 read clear */
-#define USEM_REG_USEM_PRTY_STS_CLR_0				 0x300128
-#define USEM_REG_USEM_PRTY_STS_CLR_1				 0x300138
-/* [W 7] VF or PF ID for reset error bit. Values 0-63 reset error bit for 64
- * VF; values 64-67 reset error for 4 PF; values 68-127 are not valid. */
-#define USEM_REG_VFPF_ERR_NUM					 0x300380
-#define VFC_MEMORIES_RST_REG_CAM_RST				 (0x1<<0)
-#define VFC_MEMORIES_RST_REG_RAM_RST				 (0x1<<1)
-#define VFC_REG_MEMORIES_RST					 0x1943c
-/* [RW 32] Indirect access to AG context with 32-bits granularity. The bits
- * [12:8] of the address should be the offset within the accessed LCID
- * context; the bits [7:0] are the accessed LCID.Example: to write to REG10
- * LCID100. The RBC address should be 13'ha64. */
-#define XCM_REG_AG_CTX						 0x28000
-/* [RW 2] The queue index for registration on Aux1 counter flag. */
-#define XCM_REG_AUX1_Q						 0x20134
-/* [RW 2] Per each decision rule the queue index to register to. */
-#define XCM_REG_AUX_CNT_FLG_Q_19				 0x201b0
-/* [R 5] Used to read the XX protection CAM occupancy counter. */
-#define XCM_REG_CAM_OCCUP					 0x20244
-/* [RW 1] CDU AG read Interface enable. If 0 - the request input is
-   disregarded; valid output is deasserted; all other signals are treated as
-   usual; if 1 - normal activity. */
-#define XCM_REG_CDU_AG_RD_IFEN					 0x20044
-/* [RW 1] CDU AG write Interface enable. If 0 - the request and valid input
-   are disregarded; all other signals are treated as usual; if 1 - normal
-   activity. */
-#define XCM_REG_CDU_AG_WR_IFEN					 0x20040
-/* [RW 1] CDU STORM read Interface enable. If 0 - the request input is
-   disregarded; valid output is deasserted; all other signals are treated as
-   usual; if 1 - normal activity. */
-#define XCM_REG_CDU_SM_RD_IFEN					 0x2004c
-/* [RW 1] CDU STORM write Interface enable. If 0 - the request and valid
-   input is disregarded; all other signals are treated as usual; if 1 -
-   normal activity. */
-#define XCM_REG_CDU_SM_WR_IFEN					 0x20048
-/* [RW 4] CFC output initial credit. Max credit available - 15.Write writes
-   the initial credit value; read returns the current value of the credit
-   counter. Must be initialized to 1 at start-up. */
-#define XCM_REG_CFC_INIT_CRD					 0x20404
-/* [RW 3] The weight of the CP input in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define XCM_REG_CP_WEIGHT					 0x200dc
-/* [RW 1] Input csem Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define XCM_REG_CSEM_IFEN					 0x20028
-/* [RC 1] Set at message length mismatch (relative to last indication) at
-   the csem interface. */
-#define XCM_REG_CSEM_LENGTH_MIS 				 0x20228
-/* [RW 3] The weight of the input csem in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define XCM_REG_CSEM_WEIGHT					 0x200c4
-/* [RW 1] Input dorq Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define XCM_REG_DORQ_IFEN					 0x20030
-/* [RC 1] Set at message length mismatch (relative to last indication) at
-   the dorq interface. */
-#define XCM_REG_DORQ_LENGTH_MIS 				 0x20230
-/* [RW 3] The weight of the input dorq in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define XCM_REG_DORQ_WEIGHT					 0x200cc
-/* [RW 8] The Event ID in case the ErrorFlg input message bit is set. */
-#define XCM_REG_ERR_EVNT_ID					 0x200b0
-/* [RW 28] The CM erroneous header for QM and Timers formatting. */
-#define XCM_REG_ERR_XCM_HDR					 0x200ac
-/* [RW 8] The Event ID for Timers expiration. */
-#define XCM_REG_EXPR_EVNT_ID					 0x200b4
-/* [RW 8] FIC0 output initial credit. Max credit available - 255.Write
-   writes the initial credit value; read returns the current value of the
-   credit counter. Must be initialized to 64 at start-up. */
-#define XCM_REG_FIC0_INIT_CRD					 0x2040c
-/* [RW 8] FIC1 output initial credit. Max credit available - 255.Write
-   writes the initial credit value; read returns the current value of the
-   credit counter. Must be initialized to 64 at start-up. */
-#define XCM_REG_FIC1_INIT_CRD					 0x20410
-#define XCM_REG_GLB_DEL_ACK_MAX_CNT_0				 0x20118
-#define XCM_REG_GLB_DEL_ACK_MAX_CNT_1				 0x2011c
-#define XCM_REG_GLB_DEL_ACK_TMR_VAL_0				 0x20108
-#define XCM_REG_GLB_DEL_ACK_TMR_VAL_1				 0x2010c
-/* [RW 1] Arbitratiojn between Input Arbiter groups: 0 - fair Round-Robin; 1
-   - strict priority defined by ~xcm_registers_gr_ag_pr.gr_ag_pr;
-   ~xcm_registers_gr_ld0_pr.gr_ld0_pr and
-   ~xcm_registers_gr_ld1_pr.gr_ld1_pr. */
-#define XCM_REG_GR_ARB_TYPE					 0x2020c
-/* [RW 2] Load (FIC0) channel group priority. The lowest priority is 0; the
-   highest priority is 3. It is supposed that the Channel group is the
-   compliment of the other 3 groups. */
-#define XCM_REG_GR_LD0_PR					 0x20214
-/* [RW 2] Load (FIC1) channel group priority. The lowest priority is 0; the
-   highest priority is 3. It is supposed that the Channel group is the
-   compliment of the other 3 groups. */
-#define XCM_REG_GR_LD1_PR					 0x20218
-/* [RW 1] Input nig0 Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define XCM_REG_NIG0_IFEN					 0x20038
-/* [RC 1] Set at message length mismatch (relative to last indication) at
-   the nig0 interface. */
-#define XCM_REG_NIG0_LENGTH_MIS 				 0x20238
-/* [RW 3] The weight of the input nig0 in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define XCM_REG_NIG0_WEIGHT					 0x200d4
-/* [RW 1] Input nig1 Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define XCM_REG_NIG1_IFEN					 0x2003c
-/* [RC 1] Set at message length mismatch (relative to last indication) at
-   the nig1 interface. */
-#define XCM_REG_NIG1_LENGTH_MIS 				 0x2023c
-/* [RW 5] The number of double REG-pairs; loaded from the STORM context and
-   sent to STORM; for a specific connection type. The double REG-pairs are
-   used in order to align to STORM context row size of 128 bits. The offset
-   of these data in the STORM context is always 0. Index _i stands for the
-   connection type (one of 16). */
-#define XCM_REG_N_SM_CTX_LD_0					 0x20060
-#define XCM_REG_N_SM_CTX_LD_1					 0x20064
-#define XCM_REG_N_SM_CTX_LD_2					 0x20068
-#define XCM_REG_N_SM_CTX_LD_3					 0x2006c
-#define XCM_REG_N_SM_CTX_LD_4					 0x20070
-#define XCM_REG_N_SM_CTX_LD_5					 0x20074
-/* [RW 1] Input pbf Interface enable. If 0 - the valid input is disregarded;
-   acknowledge output is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define XCM_REG_PBF_IFEN					 0x20034
-/* [RC 1] Set at message length mismatch (relative to last indication) at
-   the pbf interface. */
-#define XCM_REG_PBF_LENGTH_MIS					 0x20234
-/* [RW 3] The weight of the input pbf in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define XCM_REG_PBF_WEIGHT					 0x200d0
-#define XCM_REG_PHYS_QNUM3_0					 0x20100
-#define XCM_REG_PHYS_QNUM3_1					 0x20104
-/* [RW 8] The Event ID for Timers formatting in case of stop done. */
-#define XCM_REG_STOP_EVNT_ID					 0x200b8
-/* [RC 1] Set at message length mismatch (relative to last indication) at
-   the STORM interface. */
-#define XCM_REG_STORM_LENGTH_MIS				 0x2021c
-/* [RW 3] The weight of the STORM input in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define XCM_REG_STORM_WEIGHT					 0x200bc
-/* [RW 1] STORM - CM Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define XCM_REG_STORM_XCM_IFEN					 0x20010
-/* [RW 4] Timers output initial credit. Max credit available - 15.Write
-   writes the initial credit value; read returns the current value of the
-   credit counter. Must be initialized to 4 at start-up. */
-#define XCM_REG_TM_INIT_CRD					 0x2041c
-/* [RW 3] The weight of the Timers input in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define XCM_REG_TM_WEIGHT					 0x200ec
-/* [RW 28] The CM header for Timers expiration command. */
-#define XCM_REG_TM_XCM_HDR					 0x200a8
-/* [RW 1] Timers - CM Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define XCM_REG_TM_XCM_IFEN					 0x2001c
-/* [RW 1] Input tsem Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define XCM_REG_TSEM_IFEN					 0x20024
-/* [RC 1] Set at message length mismatch (relative to last indication) at
-   the tsem interface. */
-#define XCM_REG_TSEM_LENGTH_MIS 				 0x20224
-/* [RW 3] The weight of the input tsem in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define XCM_REG_TSEM_WEIGHT					 0x200c0
-/* [RW 2] The queue index for registration on UNA greater NXT decision rule. */
-#define XCM_REG_UNA_GT_NXT_Q					 0x20120
-/* [RW 1] Input usem Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define XCM_REG_USEM_IFEN					 0x2002c
-/* [RC 1] Message length mismatch (relative to last indication) at the usem
-   interface. */
-#define XCM_REG_USEM_LENGTH_MIS 				 0x2022c
-/* [RW 3] The weight of the input usem in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define XCM_REG_USEM_WEIGHT					 0x200c8
-#define XCM_REG_WU_DA_CNT_CMD00 				 0x201d4
-#define XCM_REG_WU_DA_CNT_CMD01 				 0x201d8
-#define XCM_REG_WU_DA_CNT_CMD10 				 0x201dc
-#define XCM_REG_WU_DA_CNT_CMD11 				 0x201e0
-#define XCM_REG_WU_DA_CNT_UPD_VAL00				 0x201e4
-#define XCM_REG_WU_DA_CNT_UPD_VAL01				 0x201e8
-#define XCM_REG_WU_DA_CNT_UPD_VAL10				 0x201ec
-#define XCM_REG_WU_DA_CNT_UPD_VAL11				 0x201f0
-#define XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00			 0x201c4
-#define XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01			 0x201c8
-#define XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD10			 0x201cc
-#define XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD11			 0x201d0
-/* [RW 1] CM - CFC Interface enable. If 0 - the valid input is disregarded;
-   acknowledge output is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define XCM_REG_XCM_CFC_IFEN					 0x20050
-/* [RW 14] Interrupt mask register #0 read/write */
-#define XCM_REG_XCM_INT_MASK					 0x202b4
-/* [R 14] Interrupt register #0 read */
-#define XCM_REG_XCM_INT_STS					 0x202a8
-/* [RW 30] Parity mask register #0 read/write */
-#define XCM_REG_XCM_PRTY_MASK					 0x202c4
-/* [R 30] Parity register #0 read */
-#define XCM_REG_XCM_PRTY_STS					 0x202b8
-/* [RC 30] Parity register #0 read clear */
-#define XCM_REG_XCM_PRTY_STS_CLR				 0x202bc
-
-/* [RW 4] The size of AG context region 0 in REG-pairs. Designates the MS
-   REG-pair number (e.g. if region 0 is 6 REG-pairs; the value should be 5).
-   Is used to determine the number of the AG context REG-pairs written back;
-   when the Reg1WbFlg isn't set. */
-#define XCM_REG_XCM_REG0_SZ					 0x200f4
-/* [RW 1] CM - STORM 0 Interface enable. If 0 - the acknowledge input is
-   disregarded; valid is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define XCM_REG_XCM_STORM0_IFEN 				 0x20004
-/* [RW 1] CM - STORM 1 Interface enable. If 0 - the acknowledge input is
-   disregarded; valid is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define XCM_REG_XCM_STORM1_IFEN 				 0x20008
-/* [RW 1] CM - Timers Interface enable. If 0 - the valid input is
-   disregarded; acknowledge output is deasserted; all other signals are
-   treated as usual; if 1 - normal activity. */
-#define XCM_REG_XCM_TM_IFEN					 0x20020
-/* [RW 1] CM - QM Interface enable. If 0 - the acknowledge input is
-   disregarded; valid is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define XCM_REG_XCM_XQM_IFEN					 0x2000c
-/* [RW 1] If set the Q index; received from the QM is inserted to event ID. */
-#define XCM_REG_XCM_XQM_USE_Q					 0x200f0
-/* [RW 4] The value by which CFC updates the activity counter at QM bypass. */
-#define XCM_REG_XQM_BYP_ACT_UPD 				 0x200fc
-/* [RW 6] QM output initial credit. Max credit available - 32.Write writes
-   the initial credit value; read returns the current value of the credit
-   counter. Must be initialized to 32 at start-up. */
-#define XCM_REG_XQM_INIT_CRD					 0x20420
-/* [RW 3] The weight of the QM (primary) input in the WRR mechanism. 0
-   stands for weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define XCM_REG_XQM_P_WEIGHT					 0x200e4
-/* [RW 3] The weight of the QM (secondary) input in the WRR mechanism. 0
-   stands for weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define XCM_REG_XQM_S_WEIGHT					 0x200e8
-/* [RW 28] The CM header value for QM request (primary). */
-#define XCM_REG_XQM_XCM_HDR_P					 0x200a0
-/* [RW 28] The CM header value for QM request (secondary). */
-#define XCM_REG_XQM_XCM_HDR_S					 0x200a4
-/* [RW 1] QM - CM Interface enable. If 0 - the valid input is disregarded;
-   acknowledge output is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define XCM_REG_XQM_XCM_IFEN					 0x20014
-/* [RW 1] Input SDM Interface enable. If 0 - the valid input is disregarded;
-   acknowledge output is deasserted; all other signals are treated as usual;
-   if 1 - normal activity. */
-#define XCM_REG_XSDM_IFEN					 0x20018
-/* [RC 1] Set at message length mismatch (relative to last indication) at
-   the SDM interface. */
-#define XCM_REG_XSDM_LENGTH_MIS 				 0x20220
-/* [RW 3] The weight of the SDM input in the WRR mechanism. 0 stands for
-   weight 8 (the most prioritised); 1 stands for weight 1(least
-   prioritised); 2 stands for weight 2; tc. */
-#define XCM_REG_XSDM_WEIGHT					 0x200e0
-/* [RW 17] Indirect access to the descriptor table of the XX protection
-   mechanism. The fields are: [5:0] - message length; 11:6] - message
-   pointer; 16:12] - next pointer. */
-#define XCM_REG_XX_DESCR_TABLE					 0x20480
-#define XCM_REG_XX_DESCR_TABLE_SIZE				 32
-/* [R 6] Used to read the XX protection Free counter. */
-#define XCM_REG_XX_FREE 					 0x20240
-/* [RW 6] Initial value for the credit counter; responsible for fulfilling
-   of the Input Stage XX protection buffer by the XX protection pending
-   messages. Max credit available - 3.Write writes the initial credit value;
-   read returns the current value of the credit counter. Must be initialized
-   to 2 at start-up. */
-#define XCM_REG_XX_INIT_CRD					 0x20424
-/* [RW 6] The maximum number of pending messages; which may be stored in XX
-   protection. ~xcm_registers_xx_free.xx_free read on read. */
-#define XCM_REG_XX_MSG_NUM					 0x20428
-/* [RW 8] The Event ID; sent to the STORM in case of XX overflow. */
-#define XCM_REG_XX_OVFL_EVNT_ID 				 0x20058
-#define XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS	 (0x1<<0)
-#define XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS	 (0x1<<1)
-#define XMAC_CTRL_REG_LINE_LOCAL_LPBK				 (0x1<<2)
-#define XMAC_CTRL_REG_RX_EN					 (0x1<<1)
-#define XMAC_CTRL_REG_SOFT_RESET				 (0x1<<6)
-#define XMAC_CTRL_REG_TX_EN					 (0x1<<0)
-#define XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN				 (0x1<<18)
-#define XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN				 (0x1<<17)
-#define XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN			 (0x1<<0)
-#define XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN			 (0x1<<3)
-#define XMAC_PFC_CTRL_HI_REG_RX_PFC_EN				 (0x1<<4)
-#define XMAC_PFC_CTRL_HI_REG_TX_PFC_EN				 (0x1<<5)
-#define XMAC_REG_CLEAR_RX_LSS_STATUS				 0x60
-#define XMAC_REG_CTRL						 0
-/* [RW 16] Upper 48 bits of ctrl_sa register. Used as the SA in PAUSE/PFC
- * packets transmitted by the MAC */
-#define XMAC_REG_CTRL_SA_HI					 0x2c
-/* [RW 32] Lower 48 bits of ctrl_sa register. Used as the SA in PAUSE/PFC
- * packets transmitted by the MAC */
-#define XMAC_REG_CTRL_SA_LO					 0x28
-#define XMAC_REG_PAUSE_CTRL					 0x68
-#define XMAC_REG_PFC_CTRL					 0x70
-#define XMAC_REG_PFC_CTRL_HI					 0x74
-#define XMAC_REG_RX_LSS_STATUS					 0x58
-/* [RW 14] Maximum packet size in receive direction; exclusive of preamble &
- * CRC in strip mode */
-#define XMAC_REG_RX_MAX_SIZE					 0x40
-#define XMAC_REG_TX_CTRL					 0x20
-/* [RW 16] Indirect access to the XX table of the XX protection mechanism.
-   The fields are:[4:0] - tail pointer; 9:5] - Link List size; 14:10] -
-   header pointer. */
-#define XCM_REG_XX_TABLE					 0x20500
-/* [RW 8] The event id for aggregated interrupt 0 */
-#define XSDM_REG_AGG_INT_EVENT_0				 0x166038
-#define XSDM_REG_AGG_INT_EVENT_1				 0x16603c
-#define XSDM_REG_AGG_INT_EVENT_10				 0x166060
-#define XSDM_REG_AGG_INT_EVENT_11				 0x166064
-#define XSDM_REG_AGG_INT_EVENT_12				 0x166068
-#define XSDM_REG_AGG_INT_EVENT_13				 0x16606c
-#define XSDM_REG_AGG_INT_EVENT_14				 0x166070
-#define XSDM_REG_AGG_INT_EVENT_2				 0x166040
-#define XSDM_REG_AGG_INT_EVENT_3				 0x166044
-#define XSDM_REG_AGG_INT_EVENT_4				 0x166048
-#define XSDM_REG_AGG_INT_EVENT_5				 0x16604c
-#define XSDM_REG_AGG_INT_EVENT_6				 0x166050
-#define XSDM_REG_AGG_INT_EVENT_7				 0x166054
-#define XSDM_REG_AGG_INT_EVENT_8				 0x166058
-#define XSDM_REG_AGG_INT_EVENT_9				 0x16605c
-/* [RW 1] For each aggregated interrupt index whether the mode is normal (0)
-   or auto-mask-mode (1) */
-#define XSDM_REG_AGG_INT_MODE_0 				 0x1661b8
-#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 completion counter #0 */
-#define XSDM_REG_CMP_COUNTER_MAX0				 0x16601c
-/* [RW 16] The maximum value of the completion counter #1 */
-#define XSDM_REG_CMP_COUNTER_MAX1				 0x166020
-/* [RW 16] The maximum value of the completion counter #2 */
-#define XSDM_REG_CMP_COUNTER_MAX2				 0x166024
-/* [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. */
-#define XSDM_REG_CMP_COUNTER_START_ADDR 			 0x16600c
-#define XSDM_REG_ENABLE_IN1					 0x166238
-#define XSDM_REG_ENABLE_IN2					 0x16623c
-#define XSDM_REG_ENABLE_OUT1					 0x166240
-#define XSDM_REG_ENABLE_OUT2					 0x166244
-/* [RW 4] The initial number of messages that can be sent to the pxp control
-   interface without receiving any ACK. */
-#define XSDM_REG_INIT_CREDIT_PXP_CTRL				 0x1664bc
-/* [ST 32] The number of ACK after placement messages received */
-#define XSDM_REG_NUM_OF_ACK_AFTER_PLACE 			 0x16627c
-/* [ST 32] The number of packet end messages received from the parser */
-#define XSDM_REG_NUM_OF_PKT_END_MSG				 0x166274
-/* [ST 32] The number of requests received from the pxp async if */
-#define XSDM_REG_NUM_OF_PXP_ASYNC_REQ				 0x166278
-/* [ST 32] The number of commands received in queue 0 */
-#define XSDM_REG_NUM_OF_Q0_CMD					 0x166248
-/* [ST 32] The number of commands received in queue 10 */
-#define XSDM_REG_NUM_OF_Q10_CMD 				 0x16626c
-/* [ST 32] The number of commands received in queue 11 */
-#define XSDM_REG_NUM_OF_Q11_CMD 				 0x166270
-/* [ST 32] The number of commands received in queue 1 */
-#define XSDM_REG_NUM_OF_Q1_CMD					 0x16624c
-/* [ST 32] The number of commands received in queue 3 */
-#define XSDM_REG_NUM_OF_Q3_CMD					 0x166250
-/* [ST 32] The number of commands received in queue 4 */
-#define XSDM_REG_NUM_OF_Q4_CMD					 0x166254
-/* [ST 32] The number of commands received in queue 5 */
-#define XSDM_REG_NUM_OF_Q5_CMD					 0x166258
-/* [ST 32] The number of commands received in queue 6 */
-#define XSDM_REG_NUM_OF_Q6_CMD					 0x16625c
-/* [ST 32] The number of commands received in queue 7 */
-#define XSDM_REG_NUM_OF_Q7_CMD					 0x166260
-/* [ST 32] The number of commands received in queue 8 */
-#define XSDM_REG_NUM_OF_Q8_CMD					 0x166264
-/* [ST 32] The number of commands received in queue 9 */
-#define XSDM_REG_NUM_OF_Q9_CMD					 0x166268
-/* [RW 13] The start address in the internal RAM for queue counters */
-#define XSDM_REG_Q_COUNTER_START_ADDR				 0x166010
-/* [W 17] Generate an operation after completion; bit-16 is
- * AggVectIdx_valid; bits 15:8 are AggVectIdx; bits 7:5 are the TRIG and
- * bits 4:0 are the T124Param[4:0] */
-#define XSDM_REG_OPERATION_GEN					 0x1664c4
-/* [R 1] pxp_ctrl rd_data fifo empty in sdm_dma_rsp block */
-#define XSDM_REG_RSP_PXP_CTRL_RDATA_EMPTY			 0x166548
-/* [R 1] parser fifo empty in sdm_sync block */
-#define XSDM_REG_SYNC_PARSER_EMPTY				 0x166550
-/* [R 1] parser serial fifo empty in sdm_sync block */
-#define XSDM_REG_SYNC_SYNC_EMPTY				 0x166558
-/* [RW 32] Tick for timer counter. Applicable only when
-   ~xsdm_registers_timer_tick_enable.timer_tick_enable =1 */
-#define XSDM_REG_TIMER_TICK					 0x166000
-/* [RW 32] Interrupt mask register #0 read/write */
-#define XSDM_REG_XSDM_INT_MASK_0				 0x16629c
-#define XSDM_REG_XSDM_INT_MASK_1				 0x1662ac
-/* [R 32] Interrupt register #0 read */
-#define XSDM_REG_XSDM_INT_STS_0 				 0x166290
-#define XSDM_REG_XSDM_INT_STS_1 				 0x1662a0
-/* [RW 11] Parity mask register #0 read/write */
-#define XSDM_REG_XSDM_PRTY_MASK 				 0x1662bc
-/* [R 11] Parity register #0 read */
-#define XSDM_REG_XSDM_PRTY_STS					 0x1662b0
-/* [RC 11] Parity register #0 read clear */
-#define XSDM_REG_XSDM_PRTY_STS_CLR				 0x1662b4
-/* [RW 5] The number of time_slots in the arbitration cycle */
-#define XSEM_REG_ARB_CYCLE_SIZE 				 0x280034
-/* [RW 3] The source that is associated with arbitration element 0. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2 */
-#define XSEM_REG_ARB_ELEMENT0					 0x280020
-/* [RW 3] The source that is associated with arbitration element 1. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2.
-   Could not be equal to register ~xsem_registers_arb_element0.arb_element0 */
-#define XSEM_REG_ARB_ELEMENT1					 0x280024
-/* [RW 3] The source that is associated with arbitration element 2. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2.
-   Could not be equal to register ~xsem_registers_arb_element0.arb_element0
-   and ~xsem_registers_arb_element1.arb_element1 */
-#define XSEM_REG_ARB_ELEMENT2					 0x280028
-/* [RW 3] The source that is associated with arbitration element 3. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2.Could
-   not be equal to register ~xsem_registers_arb_element0.arb_element0 and
-   ~xsem_registers_arb_element1.arb_element1 and
-   ~xsem_registers_arb_element2.arb_element2 */
-#define XSEM_REG_ARB_ELEMENT3					 0x28002c
-/* [RW 3] The source that is associated with arbitration element 4. Source
-   decoding is: 0- foc0; 1-fic1; 2-sleeping thread with priority 0; 3-
-   sleeping thread with priority 1; 4- sleeping thread with priority 2.
-   Could not be equal to register ~xsem_registers_arb_element0.arb_element0
-   and ~xsem_registers_arb_element1.arb_element1 and
-   ~xsem_registers_arb_element2.arb_element2 and
-   ~xsem_registers_arb_element3.arb_element3 */
-#define XSEM_REG_ARB_ELEMENT4					 0x280030
-#define XSEM_REG_ENABLE_IN					 0x2800a4
-#define XSEM_REG_ENABLE_OUT					 0x2800a8
-/* [RW 32] This address space contains all registers and memories that are
-   placed in SEM_FAST block. The SEM_FAST registers are described in
-   appendix B. In order to access the sem_fast registers the base address
-   ~fast_memory.fast_memory should be added to eachsem_fast register offset. */
-#define XSEM_REG_FAST_MEMORY					 0x2a0000
-/* [RW 1] Disables input messages from FIC0 May be updated during run_time
-   by the microcode */
-#define XSEM_REG_FIC0_DISABLE					 0x280224
-/* [RW 1] Disables input messages from FIC1 May be updated during run_time
-   by the microcode */
-#define XSEM_REG_FIC1_DISABLE					 0x280234
-/* [RW 15] Interrupt table Read and write access to it is not possible in
-   the middle of the work */
-#define XSEM_REG_INT_TABLE					 0x280400
-/* [ST 24] Statistics register. The number of messages that entered through
-   FIC0 */
-#define XSEM_REG_MSG_NUM_FIC0					 0x280000
-/* [ST 24] Statistics register. The number of messages that entered through
-   FIC1 */
-#define XSEM_REG_MSG_NUM_FIC1					 0x280004
-/* [ST 24] Statistics register. The number of messages that were sent to
-   FOC0 */
-#define XSEM_REG_MSG_NUM_FOC0					 0x280008
-/* [ST 24] Statistics register. The number of messages that were sent to
-   FOC1 */
-#define XSEM_REG_MSG_NUM_FOC1					 0x28000c
-/* [ST 24] Statistics register. The number of messages that were sent to
-   FOC2 */
-#define XSEM_REG_MSG_NUM_FOC2					 0x280010
-/* [ST 24] Statistics register. The number of messages that were sent to
-   FOC3 */
-#define XSEM_REG_MSG_NUM_FOC3					 0x280014
-/* [RW 1] Disables input messages from the passive buffer May be updated
-   during run_time by the microcode */
-#define XSEM_REG_PAS_DISABLE					 0x28024c
-/* [WB 128] Debug only. Passive buffer memory */
-#define XSEM_REG_PASSIVE_BUFFER 				 0x282000
-/* [WB 46] pram memory. B45 is parity; b[44:0] - data. */
-#define XSEM_REG_PRAM						 0x2c0000
-/* [R 16] Valid sleeping threads indication have bit per thread */
-#define XSEM_REG_SLEEP_THREADS_VALID				 0x28026c
-/* [R 1] EXT_STORE FIFO is empty in sem_slow_ls_ext */
-#define XSEM_REG_SLOW_EXT_STORE_EMPTY				 0x2802a0
-/* [RW 16] List of free threads . There is a bit per thread. */
-#define XSEM_REG_THREADS_LIST					 0x2802e4
-/* [RW 3] The arbitration scheme of time_slot 0 */
-#define XSEM_REG_TS_0_AS					 0x280038
-/* [RW 3] The arbitration scheme of time_slot 10 */
-#define XSEM_REG_TS_10_AS					 0x280060
-/* [RW 3] The arbitration scheme of time_slot 11 */
-#define XSEM_REG_TS_11_AS					 0x280064
-/* [RW 3] The arbitration scheme of time_slot 12 */
-#define XSEM_REG_TS_12_AS					 0x280068
-/* [RW 3] The arbitration scheme of time_slot 13 */
-#define XSEM_REG_TS_13_AS					 0x28006c
-/* [RW 3] The arbitration scheme of time_slot 14 */
-#define XSEM_REG_TS_14_AS					 0x280070
-/* [RW 3] The arbitration scheme of time_slot 15 */
-#define XSEM_REG_TS_15_AS					 0x280074
-/* [RW 3] The arbitration scheme of time_slot 16 */
-#define XSEM_REG_TS_16_AS					 0x280078
-/* [RW 3] The arbitration scheme of time_slot 17 */
-#define XSEM_REG_TS_17_AS					 0x28007c
-/* [RW 3] The arbitration scheme of time_slot 18 */
-#define XSEM_REG_TS_18_AS					 0x280080
-/* [RW 3] The arbitration scheme of time_slot 1 */
-#define XSEM_REG_TS_1_AS					 0x28003c
-/* [RW 3] The arbitration scheme of time_slot 2 */
-#define XSEM_REG_TS_2_AS					 0x280040
-/* [RW 3] The arbitration scheme of time_slot 3 */
-#define XSEM_REG_TS_3_AS					 0x280044
-/* [RW 3] The arbitration scheme of time_slot 4 */
-#define XSEM_REG_TS_4_AS					 0x280048
-/* [RW 3] The arbitration scheme of time_slot 5 */
-#define XSEM_REG_TS_5_AS					 0x28004c
-/* [RW 3] The arbitration scheme of time_slot 6 */
-#define XSEM_REG_TS_6_AS					 0x280050
-/* [RW 3] The arbitration scheme of time_slot 7 */
-#define XSEM_REG_TS_7_AS					 0x280054
-/* [RW 3] The arbitration scheme of time_slot 8 */
-#define XSEM_REG_TS_8_AS					 0x280058
-/* [RW 3] The arbitration scheme of time_slot 9 */
-#define XSEM_REG_TS_9_AS					 0x28005c
-/* [W 7] VF or PF ID for reset error bit. Values 0-63 reset error bit for 64
- * VF; values 64-67 reset error for 4 PF; values 68-127 are not valid. */
-#define XSEM_REG_VFPF_ERR_NUM					 0x280380
-/* [RW 32] Interrupt mask register #0 read/write */
-#define XSEM_REG_XSEM_INT_MASK_0				 0x280110
-#define XSEM_REG_XSEM_INT_MASK_1				 0x280120
-/* [R 32] Interrupt register #0 read */
-#define XSEM_REG_XSEM_INT_STS_0 				 0x280104
-#define XSEM_REG_XSEM_INT_STS_1 				 0x280114
-/* [RW 32] Parity mask register #0 read/write */
-#define XSEM_REG_XSEM_PRTY_MASK_0				 0x280130
-#define XSEM_REG_XSEM_PRTY_MASK_1				 0x280140
-/* [R 32] Parity register #0 read */
-#define XSEM_REG_XSEM_PRTY_STS_0				 0x280124
-#define XSEM_REG_XSEM_PRTY_STS_1				 0x280134
-/* [RC 32] Parity register #0 read clear */
-#define XSEM_REG_XSEM_PRTY_STS_CLR_0				 0x280128
-#define XSEM_REG_XSEM_PRTY_STS_CLR_1				 0x280138
-#define MCPR_NVM_ACCESS_ENABLE_EN				 (1L<<0)
-#define MCPR_NVM_ACCESS_ENABLE_WR_EN				 (1L<<1)
-#define MCPR_NVM_ADDR_NVM_ADDR_VALUE				 (0xffffffL<<0)
-#define MCPR_NVM_CFG4_FLASH_SIZE				 (0x7L<<0)
-#define MCPR_NVM_COMMAND_DOIT					 (1L<<4)
-#define MCPR_NVM_COMMAND_DONE					 (1L<<3)
-#define MCPR_NVM_COMMAND_FIRST					 (1L<<7)
-#define MCPR_NVM_COMMAND_LAST					 (1L<<8)
-#define MCPR_NVM_COMMAND_WR					 (1L<<5)
-#define MCPR_NVM_SW_ARB_ARB_ARB1				 (1L<<9)
-#define MCPR_NVM_SW_ARB_ARB_REQ_CLR1				 (1L<<5)
-#define MCPR_NVM_SW_ARB_ARB_REQ_SET1				 (1L<<1)
-#define BIGMAC_REGISTER_BMAC_CONTROL				 (0x00<<3)
-#define BIGMAC_REGISTER_BMAC_XGXS_CONTROL			 (0x01<<3)
-#define BIGMAC_REGISTER_CNT_MAX_SIZE				 (0x05<<3)
-#define BIGMAC_REGISTER_RX_CONTROL				 (0x21<<3)
-#define BIGMAC_REGISTER_RX_LLFC_MSG_FLDS			 (0x46<<3)
-#define BIGMAC_REGISTER_RX_LSS_STATUS				 (0x43<<3)
-#define BIGMAC_REGISTER_RX_MAX_SIZE				 (0x23<<3)
-#define BIGMAC_REGISTER_RX_STAT_GR64				 (0x26<<3)
-#define BIGMAC_REGISTER_RX_STAT_GRIPJ				 (0x42<<3)
-#define BIGMAC_REGISTER_TX_CONTROL				 (0x07<<3)
-#define BIGMAC_REGISTER_TX_MAX_SIZE				 (0x09<<3)
-#define BIGMAC_REGISTER_TX_PAUSE_THRESHOLD			 (0x0A<<3)
-#define BIGMAC_REGISTER_TX_SOURCE_ADDR				 (0x08<<3)
-#define BIGMAC_REGISTER_TX_STAT_GTBYT				 (0x20<<3)
-#define BIGMAC_REGISTER_TX_STAT_GTPKT				 (0x0C<<3)
-#define BIGMAC2_REGISTER_BMAC_CONTROL				 (0x00<<3)
-#define BIGMAC2_REGISTER_BMAC_XGXS_CONTROL			 (0x01<<3)
-#define BIGMAC2_REGISTER_CNT_MAX_SIZE				 (0x05<<3)
-#define BIGMAC2_REGISTER_PFC_CONTROL				 (0x06<<3)
-#define BIGMAC2_REGISTER_RX_CONTROL				 (0x3A<<3)
-#define BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS			 (0x62<<3)
-#define BIGMAC2_REGISTER_RX_LSS_STAT				 (0x3E<<3)
-#define BIGMAC2_REGISTER_RX_MAX_SIZE				 (0x3C<<3)
-#define BIGMAC2_REGISTER_RX_STAT_GR64				 (0x40<<3)
-#define BIGMAC2_REGISTER_RX_STAT_GRIPJ				 (0x5f<<3)
-#define BIGMAC2_REGISTER_RX_STAT_GRPP				 (0x51<<3)
-#define BIGMAC2_REGISTER_TX_CONTROL				 (0x1C<<3)
-#define BIGMAC2_REGISTER_TX_MAX_SIZE				 (0x1E<<3)
-#define BIGMAC2_REGISTER_TX_PAUSE_CONTROL			 (0x20<<3)
-#define BIGMAC2_REGISTER_TX_SOURCE_ADDR			 (0x1D<<3)
-#define BIGMAC2_REGISTER_TX_STAT_GTBYT				 (0x39<<3)
-#define BIGMAC2_REGISTER_TX_STAT_GTPOK				 (0x22<<3)
-#define BIGMAC2_REGISTER_TX_STAT_GTPP				 (0x24<<3)
-#define EMAC_LED_1000MB_OVERRIDE				 (1L<<1)
-#define EMAC_LED_100MB_OVERRIDE 				 (1L<<2)
-#define EMAC_LED_10MB_OVERRIDE					 (1L<<3)
-#define EMAC_LED_2500MB_OVERRIDE				 (1L<<12)
-#define EMAC_LED_OVERRIDE					 (1L<<0)
-#define EMAC_LED_TRAFFIC					 (1L<<6)
-#define EMAC_MDIO_COMM_COMMAND_ADDRESS				 (0L<<26)
-#define EMAC_MDIO_COMM_COMMAND_READ_22				 (2L<<26)
-#define EMAC_MDIO_COMM_COMMAND_READ_45				 (3L<<26)
-#define EMAC_MDIO_COMM_COMMAND_WRITE_22				 (1L<<26)
-#define EMAC_MDIO_COMM_COMMAND_WRITE_45 			 (1L<<26)
-#define EMAC_MDIO_COMM_DATA					 (0xffffL<<0)
-#define EMAC_MDIO_COMM_START_BUSY				 (1L<<29)
-#define EMAC_MDIO_MODE_AUTO_POLL				 (1L<<4)
-#define EMAC_MDIO_MODE_CLAUSE_45				 (1L<<31)
-#define EMAC_MDIO_MODE_CLOCK_CNT				 (0x3ffL<<16)
-#define EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT			 16
-#define EMAC_MDIO_STATUS_10MB					 (1L<<1)
-#define EMAC_MODE_25G_MODE					 (1L<<5)
-#define EMAC_MODE_HALF_DUPLEX					 (1L<<1)
-#define EMAC_MODE_PORT_GMII					 (2L<<2)
-#define EMAC_MODE_PORT_MII					 (1L<<2)
-#define EMAC_MODE_PORT_MII_10M					 (3L<<2)
-#define EMAC_MODE_RESET 					 (1L<<0)
-#define EMAC_REG_EMAC_LED					 0xc
-#define EMAC_REG_EMAC_MAC_MATCH 				 0x10
-#define EMAC_REG_EMAC_MDIO_COMM 				 0xac
-#define EMAC_REG_EMAC_MDIO_MODE 				 0xb4
-#define EMAC_REG_EMAC_MDIO_STATUS				 0xb0
-#define EMAC_REG_EMAC_MODE					 0x0
-#define EMAC_REG_EMAC_RX_MODE					 0xc8
-#define EMAC_REG_EMAC_RX_MTU_SIZE				 0x9c
-#define EMAC_REG_EMAC_RX_STAT_AC				 0x180
-#define EMAC_REG_EMAC_RX_STAT_AC_28				 0x1f4
-#define EMAC_REG_EMAC_RX_STAT_AC_COUNT				 23
-#define EMAC_REG_EMAC_TX_MODE					 0xbc
-#define EMAC_REG_EMAC_TX_STAT_AC				 0x280
-#define EMAC_REG_EMAC_TX_STAT_AC_COUNT				 22
-#define EMAC_REG_RX_PFC_MODE					 0x320
-#define EMAC_REG_RX_PFC_MODE_PRIORITIES				 (1L<<2)
-#define EMAC_REG_RX_PFC_MODE_RX_EN				 (1L<<1)
-#define EMAC_REG_RX_PFC_MODE_TX_EN				 (1L<<0)
-#define EMAC_REG_RX_PFC_PARAM					 0x324
-#define EMAC_REG_RX_PFC_PARAM_OPCODE_BITSHIFT			 0
-#define EMAC_REG_RX_PFC_PARAM_PRIORITY_EN_BITSHIFT		 16
-#define EMAC_REG_RX_PFC_STATS_XOFF_RCVD				 0x328
-#define EMAC_REG_RX_PFC_STATS_XOFF_RCVD_COUNT			 (0xffff<<0)
-#define EMAC_REG_RX_PFC_STATS_XOFF_SENT				 0x330
-#define EMAC_REG_RX_PFC_STATS_XOFF_SENT_COUNT			 (0xffff<<0)
-#define EMAC_REG_RX_PFC_STATS_XON_RCVD				 0x32c
-#define EMAC_REG_RX_PFC_STATS_XON_RCVD_COUNT			 (0xffff<<0)
-#define EMAC_REG_RX_PFC_STATS_XON_SENT				 0x334
-#define EMAC_REG_RX_PFC_STATS_XON_SENT_COUNT			 (0xffff<<0)
-#define EMAC_RX_MODE_FLOW_EN					 (1L<<2)
-#define EMAC_RX_MODE_KEEP_MAC_CONTROL				 (1L<<3)
-#define EMAC_RX_MODE_KEEP_VLAN_TAG				 (1L<<10)
-#define EMAC_RX_MODE_PROMISCUOUS				 (1L<<8)
-#define EMAC_RX_MODE_RESET					 (1L<<0)
-#define EMAC_RX_MTU_SIZE_JUMBO_ENA				 (1L<<31)
-#define EMAC_TX_MODE_EXT_PAUSE_EN				 (1L<<3)
-#define EMAC_TX_MODE_FLOW_EN					 (1L<<4)
-#define EMAC_TX_MODE_RESET					 (1L<<0)
-#define MISC_REGISTERS_GPIO_0					 0
-#define MISC_REGISTERS_GPIO_1					 1
-#define MISC_REGISTERS_GPIO_2					 2
-#define MISC_REGISTERS_GPIO_3					 3
-#define MISC_REGISTERS_GPIO_CLR_POS				 16
-#define MISC_REGISTERS_GPIO_FLOAT				 (0xffL<<24)
-#define MISC_REGISTERS_GPIO_FLOAT_POS				 24
-#define MISC_REGISTERS_GPIO_HIGH				 1
-#define MISC_REGISTERS_GPIO_INPUT_HI_Z				 2
-#define MISC_REGISTERS_GPIO_INT_CLR_POS 			 24
-#define MISC_REGISTERS_GPIO_INT_OUTPUT_CLR			 0
-#define MISC_REGISTERS_GPIO_INT_OUTPUT_SET			 1
-#define MISC_REGISTERS_GPIO_INT_SET_POS 			 16
-#define MISC_REGISTERS_GPIO_LOW 				 0
-#define MISC_REGISTERS_GPIO_OUTPUT_HIGH 			 1
-#define MISC_REGISTERS_GPIO_OUTPUT_LOW				 0
-#define MISC_REGISTERS_GPIO_PORT_SHIFT				 4
-#define MISC_REGISTERS_GPIO_SET_POS				 8
-#define MISC_REGISTERS_RESET_REG_1_CLEAR			 0x588
-#define MISC_REGISTERS_RESET_REG_1_RST_HC			 (0x1<<29)
-#define MISC_REGISTERS_RESET_REG_1_RST_NIG			 (0x1<<7)
-#define MISC_REGISTERS_RESET_REG_1_RST_PXP			 (0x1<<26)
-#define MISC_REGISTERS_RESET_REG_1_RST_PXPV			 (0x1<<27)
-#define MISC_REGISTERS_RESET_REG_1_SET				 0x584
-#define MISC_REGISTERS_RESET_REG_2_CLEAR			 0x598
-#define MISC_REGISTERS_RESET_REG_2_MSTAT0			 (0x1<<24)
-#define MISC_REGISTERS_RESET_REG_2_MSTAT1			 (0x1<<25)
-#define MISC_REGISTERS_RESET_REG_2_PGLC				 (0x1<<19)
-#define MISC_REGISTERS_RESET_REG_2_RST_ATC			 (0x1<<17)
-#define MISC_REGISTERS_RESET_REG_2_RST_BMAC0			 (0x1<<0)
-#define MISC_REGISTERS_RESET_REG_2_RST_BMAC1			 (0x1<<1)
-#define MISC_REGISTERS_RESET_REG_2_RST_EMAC0			 (0x1<<2)
-#define MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE		 (0x1<<14)
-#define MISC_REGISTERS_RESET_REG_2_RST_EMAC1			 (0x1<<3)
-#define MISC_REGISTERS_RESET_REG_2_RST_EMAC1_HARD_CORE		 (0x1<<15)
-#define MISC_REGISTERS_RESET_REG_2_RST_GRC			 (0x1<<4)
-#define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_HARD_CORE_RST_B	 (0x1<<6)
-#define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CORE	 (0x1<<8)
-#define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CPU	 (0x1<<7)
-#define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_REG_HARD_CORE (0x1<<5)
-#define MISC_REGISTERS_RESET_REG_2_RST_MDIO			 (0x1<<13)
-#define MISC_REGISTERS_RESET_REG_2_RST_MISC_CORE		 (0x1<<11)
-#define MISC_REGISTERS_RESET_REG_2_RST_PCI_MDIO			 (0x1<<13)
-#define MISC_REGISTERS_RESET_REG_2_RST_RBCN			 (0x1<<9)
-#define MISC_REGISTERS_RESET_REG_2_SET				 0x594
-#define MISC_REGISTERS_RESET_REG_2_UMAC0			 (0x1<<20)
-#define MISC_REGISTERS_RESET_REG_2_UMAC1			 (0x1<<21)
-#define MISC_REGISTERS_RESET_REG_2_XMAC				 (0x1<<22)
-#define MISC_REGISTERS_RESET_REG_2_XMAC_SOFT			 (0x1<<23)
-#define MISC_REGISTERS_RESET_REG_3_CLEAR			 0x5a8
-#define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_IDDQ	 (0x1<<1)
-#define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN	 (0x1<<2)
-#define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN_SD (0x1<<3)
-#define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_RSTB_HW  (0x1<<0)
-#define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_IDDQ	 (0x1<<5)
-#define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN	 (0x1<<6)
-#define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN_SD  (0x1<<7)
-#define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_RSTB_HW	 (0x1<<4)
-#define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_TXD_FIFO_RSTB (0x1<<8)
-#define MISC_REGISTERS_RESET_REG_3_SET				 0x5a4
-#define MISC_REGISTERS_SPIO_4					 4
-#define MISC_REGISTERS_SPIO_5					 5
-#define MISC_REGISTERS_SPIO_7					 7
-#define MISC_REGISTERS_SPIO_CLR_POS				 16
-#define MISC_REGISTERS_SPIO_FLOAT				 (0xffL<<24)
-#define MISC_REGISTERS_SPIO_FLOAT_POS				 24
-#define MISC_REGISTERS_SPIO_INPUT_HI_Z				 2
-#define MISC_REGISTERS_SPIO_INT_OLD_SET_POS			 16
-#define MISC_REGISTERS_SPIO_OUTPUT_HIGH 			 1
-#define MISC_REGISTERS_SPIO_OUTPUT_LOW				 0
-#define MISC_REGISTERS_SPIO_SET_POS				 8
-#define HW_LOCK_DRV_FLAGS					 10
-#define HW_LOCK_MAX_RESOURCE_VALUE				 31
-#define HW_LOCK_RESOURCE_GPIO					 1
-#define HW_LOCK_RESOURCE_MDIO					 0
-#define HW_LOCK_RESOURCE_PORT0_ATT_MASK				 3
-#define HW_LOCK_RESOURCE_RECOVERY_LEADER_0			 8
-#define HW_LOCK_RESOURCE_RECOVERY_LEADER_1			 9
-#define HW_LOCK_RESOURCE_SPIO					 2
-#define HW_LOCK_RESOURCE_RESET					 5
-#define AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT			 (0x1<<4)
-#define AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR			 (0x1<<5)
-#define AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR			 (0x1<<18)
-#define AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT			 (0x1<<31)
-#define AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR			 (0x1<<30)
-#define AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT			 (0x1<<9)
-#define AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR			 (0x1<<8)
-#define AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT			 (0x1<<7)
-#define AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR			 (0x1<<6)
-#define AEU_INPUTS_ATTN_BITS_CSDM_HW_INTERRUPT			 (0x1<<29)
-#define AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR			 (0x1<<28)
-#define AEU_INPUTS_ATTN_BITS_CSEMI_HW_INTERRUPT			 (0x1<<1)
-#define AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR			 (0x1<<0)
-#define AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR			 (0x1<<18)
-#define AEU_INPUTS_ATTN_BITS_DMAE_HW_INTERRUPT			 (0x1<<11)
-#define AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR			 (0x1<<10)
-#define AEU_INPUTS_ATTN_BITS_DOORBELLQ_HW_INTERRUPT		 (0x1<<13)
-#define AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR		 (0x1<<12)
-#define AEU_INPUTS_ATTN_BITS_GPIO0_FUNCTION_0			 (0x1<<2)
-#define AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR			 (0x1<<12)
-#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY		 (0x1<<28)
-#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY		 (0x1<<31)
-#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY		 (0x1<<29)
-#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY		 (0x1<<30)
-#define AEU_INPUTS_ATTN_BITS_MISC_HW_INTERRUPT			 (0x1<<15)
-#define AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR			 (0x1<<14)
-#define AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR			 (0x1<<14)
-#define AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR		 (0x1<<20)
-#define AEU_INPUTS_ATTN_BITS_PBCLIENT_HW_INTERRUPT		 (0x1<<31)
-#define AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR		 (0x1<<30)
-#define AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR			 (0x1<<0)
-#define AEU_INPUTS_ATTN_BITS_PGLUE_HW_INTERRUPT			 (0x1<<2)
-#define AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR			 (0x1<<3)
-#define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_HW_INTERRUPT	 (0x1<<5)
-#define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR	 (0x1<<4)
-#define AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT			 (0x1<<3)
-#define AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR			 (0x1<<2)
-#define AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT			 (0x1<<3)
-#define AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR			 (0x1<<2)
-#define AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR		 (0x1<<22)
-#define AEU_INPUTS_ATTN_BITS_SPIO5				 (0x1<<15)
-#define AEU_INPUTS_ATTN_BITS_TCM_HW_INTERRUPT			 (0x1<<27)
-#define AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR			 (0x1<<26)
-#define AEU_INPUTS_ATTN_BITS_TIMERS_HW_INTERRUPT		 (0x1<<5)
-#define AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR		 (0x1<<4)
-#define AEU_INPUTS_ATTN_BITS_TSDM_HW_INTERRUPT			 (0x1<<25)
-#define AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR			 (0x1<<24)
-#define AEU_INPUTS_ATTN_BITS_TSEMI_HW_INTERRUPT			 (0x1<<29)
-#define AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR			 (0x1<<28)
-#define AEU_INPUTS_ATTN_BITS_UCM_HW_INTERRUPT			 (0x1<<23)
-#define AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR			 (0x1<<22)
-#define AEU_INPUTS_ATTN_BITS_UPB_HW_INTERRUPT			 (0x1<<27)
-#define AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR			 (0x1<<26)
-#define AEU_INPUTS_ATTN_BITS_USDM_HW_INTERRUPT			 (0x1<<21)
-#define AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR			 (0x1<<20)
-#define AEU_INPUTS_ATTN_BITS_USEMI_HW_INTERRUPT			 (0x1<<25)
-#define AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR			 (0x1<<24)
-#define AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR		 (0x1<<16)
-#define AEU_INPUTS_ATTN_BITS_XCM_HW_INTERRUPT			 (0x1<<9)
-#define AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR			 (0x1<<8)
-#define AEU_INPUTS_ATTN_BITS_XSDM_HW_INTERRUPT			 (0x1<<7)
-#define AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR			 (0x1<<6)
-#define AEU_INPUTS_ATTN_BITS_XSEMI_HW_INTERRUPT			 (0x1<<11)
-#define AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR			 (0x1<<10)
-
-#define AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0			(0x1<<5)
-#define AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1			(0x1<<9)
-
-#define RESERVED_GENERAL_ATTENTION_BIT_0	0
-
-#define EVEREST_GEN_ATTN_IN_USE_MASK		0x7ffe0
-#define EVEREST_LATCHED_ATTN_IN_USE_MASK	0xffe00000
-
-#define RESERVED_GENERAL_ATTENTION_BIT_6	6
-#define RESERVED_GENERAL_ATTENTION_BIT_7	7
-#define RESERVED_GENERAL_ATTENTION_BIT_8	8
-#define RESERVED_GENERAL_ATTENTION_BIT_9	9
-#define RESERVED_GENERAL_ATTENTION_BIT_10	10
-#define RESERVED_GENERAL_ATTENTION_BIT_11	11
-#define RESERVED_GENERAL_ATTENTION_BIT_12	12
-#define RESERVED_GENERAL_ATTENTION_BIT_13	13
-#define RESERVED_GENERAL_ATTENTION_BIT_14	14
-#define RESERVED_GENERAL_ATTENTION_BIT_15	15
-#define RESERVED_GENERAL_ATTENTION_BIT_16	16
-#define RESERVED_GENERAL_ATTENTION_BIT_17	17
-#define RESERVED_GENERAL_ATTENTION_BIT_18	18
-#define RESERVED_GENERAL_ATTENTION_BIT_19	19
-#define RESERVED_GENERAL_ATTENTION_BIT_20	20
-#define RESERVED_GENERAL_ATTENTION_BIT_21	21
-
-/* storm asserts attention bits */
-#define TSTORM_FATAL_ASSERT_ATTENTION_BIT     RESERVED_GENERAL_ATTENTION_BIT_7
-#define USTORM_FATAL_ASSERT_ATTENTION_BIT     RESERVED_GENERAL_ATTENTION_BIT_8
-#define CSTORM_FATAL_ASSERT_ATTENTION_BIT     RESERVED_GENERAL_ATTENTION_BIT_9
-#define XSTORM_FATAL_ASSERT_ATTENTION_BIT     RESERVED_GENERAL_ATTENTION_BIT_10
-
-/* mcp error attention bit */
-#define MCP_FATAL_ASSERT_ATTENTION_BIT	      RESERVED_GENERAL_ATTENTION_BIT_11
-
-/*E1H NIG status sync attention mapped to group 4-7*/
-#define LINK_SYNC_ATTENTION_BIT_FUNC_0	    RESERVED_GENERAL_ATTENTION_BIT_12
-#define LINK_SYNC_ATTENTION_BIT_FUNC_1	    RESERVED_GENERAL_ATTENTION_BIT_13
-#define LINK_SYNC_ATTENTION_BIT_FUNC_2	    RESERVED_GENERAL_ATTENTION_BIT_14
-#define LINK_SYNC_ATTENTION_BIT_FUNC_3	    RESERVED_GENERAL_ATTENTION_BIT_15
-#define LINK_SYNC_ATTENTION_BIT_FUNC_4	    RESERVED_GENERAL_ATTENTION_BIT_16
-#define LINK_SYNC_ATTENTION_BIT_FUNC_5	    RESERVED_GENERAL_ATTENTION_BIT_17
-#define LINK_SYNC_ATTENTION_BIT_FUNC_6	    RESERVED_GENERAL_ATTENTION_BIT_18
-#define LINK_SYNC_ATTENTION_BIT_FUNC_7	    RESERVED_GENERAL_ATTENTION_BIT_19
-
-
-#define LATCHED_ATTN_RBCR			23
-#define LATCHED_ATTN_RBCT			24
-#define LATCHED_ATTN_RBCN			25
-#define LATCHED_ATTN_RBCU			26
-#define LATCHED_ATTN_RBCP			27
-#define LATCHED_ATTN_TIMEOUT_GRC		28
-#define LATCHED_ATTN_RSVD_GRC			29
-#define LATCHED_ATTN_ROM_PARITY_MCP		30
-#define LATCHED_ATTN_UM_RX_PARITY_MCP		31
-#define LATCHED_ATTN_UM_TX_PARITY_MCP		32
-#define LATCHED_ATTN_SCPAD_PARITY_MCP		33
-
-#define GENERAL_ATTEN_WORD(atten_name)	       ((94 + atten_name) / 32)
-#define GENERAL_ATTEN_OFFSET(atten_name)\
-	(1UL << ((94 + atten_name) % 32))
-/*
- * This file defines GRC base address for every block.
- * This file is included by chipsim, asm microcode and cpp microcode.
- * These values are used in Design.xml on regBase attribute
- * Use the base with the generated offsets of specific registers.
- */
-
-#define GRCBASE_PXPCS		0x000000
-#define GRCBASE_PCICONFIG	0x002000
-#define GRCBASE_PCIREG		0x002400
-#define GRCBASE_EMAC0		0x008000
-#define GRCBASE_EMAC1		0x008400
-#define GRCBASE_DBU		0x008800
-#define GRCBASE_MISC		0x00A000
-#define GRCBASE_DBG		0x00C000
-#define GRCBASE_NIG		0x010000
-#define GRCBASE_XCM		0x020000
-#define GRCBASE_PRS		0x040000
-#define GRCBASE_SRCH		0x040400
-#define GRCBASE_TSDM		0x042000
-#define GRCBASE_TCM		0x050000
-#define GRCBASE_BRB1		0x060000
-#define GRCBASE_MCP		0x080000
-#define GRCBASE_UPB		0x0C1000
-#define GRCBASE_CSDM		0x0C2000
-#define GRCBASE_USDM		0x0C4000
-#define GRCBASE_CCM		0x0D0000
-#define GRCBASE_UCM		0x0E0000
-#define GRCBASE_CDU		0x101000
-#define GRCBASE_DMAE		0x102000
-#define GRCBASE_PXP		0x103000
-#define GRCBASE_CFC		0x104000
-#define GRCBASE_HC		0x108000
-#define GRCBASE_PXP2		0x120000
-#define GRCBASE_PBF		0x140000
-#define GRCBASE_UMAC0		0x160000
-#define GRCBASE_UMAC1		0x160400
-#define GRCBASE_XPB		0x161000
-#define GRCBASE_MSTAT0	    0x162000
-#define GRCBASE_MSTAT1	    0x162800
-#define GRCBASE_XMAC0		0x163000
-#define GRCBASE_XMAC1		0x163800
-#define GRCBASE_TIMERS		0x164000
-#define GRCBASE_XSDM		0x166000
-#define GRCBASE_QM		0x168000
-#define GRCBASE_DQ		0x170000
-#define GRCBASE_TSEM		0x180000
-#define GRCBASE_CSEM		0x200000
-#define GRCBASE_XSEM		0x280000
-#define GRCBASE_USEM		0x300000
-#define GRCBASE_MISC_AEU	GRCBASE_MISC
-
-
-/* offset of configuration space in the pci core register */
-#define PCICFG_OFFSET					0x2000
-#define PCICFG_VENDOR_ID_OFFSET 			0x00
-#define PCICFG_DEVICE_ID_OFFSET 			0x02
-#define PCICFG_COMMAND_OFFSET				0x04
-#define PCICFG_COMMAND_IO_SPACE 		(1<<0)
-#define PCICFG_COMMAND_MEM_SPACE		(1<<1)
-#define PCICFG_COMMAND_BUS_MASTER		(1<<2)
-#define PCICFG_COMMAND_SPECIAL_CYCLES		(1<<3)
-#define PCICFG_COMMAND_MWI_CYCLES		(1<<4)
-#define PCICFG_COMMAND_VGA_SNOOP		(1<<5)
-#define PCICFG_COMMAND_PERR_ENA 		(1<<6)
-#define PCICFG_COMMAND_STEPPING 		(1<<7)
-#define PCICFG_COMMAND_SERR_ENA 		(1<<8)
-#define PCICFG_COMMAND_FAST_B2B 		(1<<9)
-#define PCICFG_COMMAND_INT_DISABLE		(1<<10)
-#define PCICFG_COMMAND_RESERVED 		(0x1f<<11)
-#define PCICFG_STATUS_OFFSET				0x06
-#define PCICFG_REVESION_ID_OFFSET			0x08
-#define PCICFG_CACHE_LINE_SIZE				0x0c
-#define PCICFG_LATENCY_TIMER				0x0d
-#define PCICFG_BAR_1_LOW				0x10
-#define PCICFG_BAR_1_HIGH				0x14
-#define PCICFG_BAR_2_LOW				0x18
-#define PCICFG_BAR_2_HIGH				0x1c
-#define PCICFG_SUBSYSTEM_VENDOR_ID_OFFSET		0x2c
-#define PCICFG_SUBSYSTEM_ID_OFFSET			0x2e
-#define PCICFG_INT_LINE 				0x3c
-#define PCICFG_INT_PIN					0x3d
-#define PCICFG_PM_CAPABILITY				0x48
-#define PCICFG_PM_CAPABILITY_VERSION		(0x3<<16)
-#define PCICFG_PM_CAPABILITY_CLOCK		(1<<19)
-#define PCICFG_PM_CAPABILITY_RESERVED		(1<<20)
-#define PCICFG_PM_CAPABILITY_DSI		(1<<21)
-#define PCICFG_PM_CAPABILITY_AUX_CURRENT	(0x7<<22)
-#define PCICFG_PM_CAPABILITY_D1_SUPPORT 	(1<<25)
-#define PCICFG_PM_CAPABILITY_D2_SUPPORT 	(1<<26)
-#define PCICFG_PM_CAPABILITY_PME_IN_D0		(1<<27)
-#define PCICFG_PM_CAPABILITY_PME_IN_D1		(1<<28)
-#define PCICFG_PM_CAPABILITY_PME_IN_D2		(1<<29)
-#define PCICFG_PM_CAPABILITY_PME_IN_D3_HOT	(1<<30)
-#define PCICFG_PM_CAPABILITY_PME_IN_D3_COLD	(1<<31)
-#define PCICFG_PM_CSR_OFFSET				0x4c
-#define PCICFG_PM_CSR_STATE			(0x3<<0)
-#define PCICFG_PM_CSR_PME_ENABLE		(1<<8)
-#define PCICFG_PM_CSR_PME_STATUS		(1<<15)
-#define PCICFG_MSI_CAP_ID_OFFSET			0x58
-#define PCICFG_MSI_CONTROL_ENABLE		(0x1<<16)
-#define PCICFG_MSI_CONTROL_MCAP 		(0x7<<17)
-#define PCICFG_MSI_CONTROL_MENA 		(0x7<<20)
-#define PCICFG_MSI_CONTROL_64_BIT_ADDR_CAP	(0x1<<23)
-#define PCICFG_MSI_CONTROL_MSI_PVMASK_CAPABLE	(0x1<<24)
-#define PCICFG_GRC_ADDRESS				0x78
-#define PCICFG_GRC_DATA 				0x80
-#define PCICFG_MSIX_CAP_ID_OFFSET			0xa0
-#define PCICFG_MSIX_CONTROL_TABLE_SIZE		(0x7ff<<16)
-#define PCICFG_MSIX_CONTROL_RESERVED		(0x7<<27)
-#define PCICFG_MSIX_CONTROL_FUNC_MASK		(0x1<<30)
-#define PCICFG_MSIX_CONTROL_MSIX_ENABLE 	(0x1<<31)
-
-#define PCICFG_DEVICE_CONTROL				0xb4
-#define PCICFG_DEVICE_STATUS				0xb6
-#define PCICFG_DEVICE_STATUS_CORR_ERR_DET	(1<<0)
-#define PCICFG_DEVICE_STATUS_NON_FATAL_ERR_DET	(1<<1)
-#define PCICFG_DEVICE_STATUS_FATAL_ERR_DET	(1<<2)
-#define PCICFG_DEVICE_STATUS_UNSUP_REQ_DET	(1<<3)
-#define PCICFG_DEVICE_STATUS_AUX_PWR_DET	(1<<4)
-#define PCICFG_DEVICE_STATUS_NO_PEND		(1<<5)
-#define PCICFG_LINK_CONTROL				0xbc
-
-
-#define BAR_USTRORM_INTMEM				0x400000
-#define BAR_CSTRORM_INTMEM				0x410000
-#define BAR_XSTRORM_INTMEM				0x420000
-#define BAR_TSTRORM_INTMEM				0x430000
-
-/* for accessing the IGU in case of status block ACK */
-#define BAR_IGU_INTMEM					0x440000
-
-#define BAR_DOORBELL_OFFSET				0x800000
-
-#define BAR_ME_REGISTER 				0x450000
-
-/* config_2 offset */
-#define GRC_CONFIG_2_SIZE_REG				0x408
-#define PCI_CONFIG_2_BAR1_SIZE			(0xfL<<0)
-#define PCI_CONFIG_2_BAR1_SIZE_DISABLED 	(0L<<0)
-#define PCI_CONFIG_2_BAR1_SIZE_64K		(1L<<0)
-#define PCI_CONFIG_2_BAR1_SIZE_128K		(2L<<0)
-#define PCI_CONFIG_2_BAR1_SIZE_256K		(3L<<0)
-#define PCI_CONFIG_2_BAR1_SIZE_512K		(4L<<0)
-#define PCI_CONFIG_2_BAR1_SIZE_1M		(5L<<0)
-#define PCI_CONFIG_2_BAR1_SIZE_2M		(6L<<0)
-#define PCI_CONFIG_2_BAR1_SIZE_4M		(7L<<0)
-#define PCI_CONFIG_2_BAR1_SIZE_8M		(8L<<0)
-#define PCI_CONFIG_2_BAR1_SIZE_16M		(9L<<0)
-#define PCI_CONFIG_2_BAR1_SIZE_32M		(10L<<0)
-#define PCI_CONFIG_2_BAR1_SIZE_64M		(11L<<0)
-#define PCI_CONFIG_2_BAR1_SIZE_128M		(12L<<0)
-#define PCI_CONFIG_2_BAR1_SIZE_256M		(13L<<0)
-#define PCI_CONFIG_2_BAR1_SIZE_512M		(14L<<0)
-#define PCI_CONFIG_2_BAR1_SIZE_1G		(15L<<0)
-#define PCI_CONFIG_2_BAR1_64ENA 		(1L<<4)
-#define PCI_CONFIG_2_EXP_ROM_RETRY		(1L<<5)
-#define PCI_CONFIG_2_CFG_CYCLE_RETRY		(1L<<6)
-#define PCI_CONFIG_2_FIRST_CFG_DONE		(1L<<7)
-#define PCI_CONFIG_2_EXP_ROM_SIZE		(0xffL<<8)
-#define PCI_CONFIG_2_EXP_ROM_SIZE_DISABLED	(0L<<8)
-#define PCI_CONFIG_2_EXP_ROM_SIZE_2K		(1L<<8)
-#define PCI_CONFIG_2_EXP_ROM_SIZE_4K		(2L<<8)
-#define PCI_CONFIG_2_EXP_ROM_SIZE_8K		(3L<<8)
-#define PCI_CONFIG_2_EXP_ROM_SIZE_16K		(4L<<8)
-#define PCI_CONFIG_2_EXP_ROM_SIZE_32K		(5L<<8)
-#define PCI_CONFIG_2_EXP_ROM_SIZE_64K		(6L<<8)
-#define PCI_CONFIG_2_EXP_ROM_SIZE_128K		(7L<<8)
-#define PCI_CONFIG_2_EXP_ROM_SIZE_256K		(8L<<8)
-#define PCI_CONFIG_2_EXP_ROM_SIZE_512K		(9L<<8)
-#define PCI_CONFIG_2_EXP_ROM_SIZE_1M		(10L<<8)
-#define PCI_CONFIG_2_EXP_ROM_SIZE_2M		(11L<<8)
-#define PCI_CONFIG_2_EXP_ROM_SIZE_4M		(12L<<8)
-#define PCI_CONFIG_2_EXP_ROM_SIZE_8M		(13L<<8)
-#define PCI_CONFIG_2_EXP_ROM_SIZE_16M		(14L<<8)
-#define PCI_CONFIG_2_EXP_ROM_SIZE_32M		(15L<<8)
-#define PCI_CONFIG_2_BAR_PREFETCH		(1L<<16)
-#define PCI_CONFIG_2_RESERVED0			(0x7fffL<<17)
-
-/* config_3 offset */
-#define GRC_CONFIG_3_SIZE_REG				0x40c
-#define PCI_CONFIG_3_STICKY_BYTE		(0xffL<<0)
-#define PCI_CONFIG_3_FORCE_PME			(1L<<24)
-#define PCI_CONFIG_3_PME_STATUS 		(1L<<25)
-#define PCI_CONFIG_3_PME_ENABLE 		(1L<<26)
-#define PCI_CONFIG_3_PM_STATE			(0x3L<<27)
-#define PCI_CONFIG_3_VAUX_PRESET		(1L<<30)
-#define PCI_CONFIG_3_PCI_POWER			(1L<<31)
-
-#define GRC_BAR2_CONFIG 				0x4e0
-#define PCI_CONFIG_2_BAR2_SIZE			(0xfL<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_DISABLED 	(0L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_64K		(1L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_128K		(2L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_256K		(3L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_512K		(4L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_1M		(5L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_2M		(6L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_4M		(7L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_8M		(8L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_16M		(9L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_32M		(10L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_64M		(11L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_128M		(12L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_256M		(13L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_512M		(14L<<0)
-#define PCI_CONFIG_2_BAR2_SIZE_1G		(15L<<0)
-#define PCI_CONFIG_2_BAR2_64ENA 		(1L<<4)
-
-#define PCI_PM_DATA_A					0x410
-#define PCI_PM_DATA_B					0x414
-#define PCI_ID_VAL1					0x434
-#define PCI_ID_VAL2					0x438
-
-#define PXPCS_TL_CONTROL_5		    0x814
-#define PXPCS_TL_CONTROL_5_UNKNOWNTYPE_ERR_ATTN    (1 << 29) /*WC*/
-#define PXPCS_TL_CONTROL_5_BOUNDARY4K_ERR_ATTN	   (1 << 28)   /*WC*/
-#define PXPCS_TL_CONTROL_5_MRRS_ERR_ATTN   (1 << 27)   /*WC*/
-#define PXPCS_TL_CONTROL_5_MPS_ERR_ATTN    (1 << 26)   /*WC*/
-#define PXPCS_TL_CONTROL_5_TTX_BRIDGE_FORWARD_ERR  (1 << 25)   /*WC*/
-#define PXPCS_TL_CONTROL_5_TTX_TXINTF_OVERFLOW	   (1 << 24)   /*WC*/
-#define PXPCS_TL_CONTROL_5_PHY_ERR_ATTN    (1 << 23)   /*RO*/
-#define PXPCS_TL_CONTROL_5_DL_ERR_ATTN	   (1 << 22)   /*RO*/
-#define PXPCS_TL_CONTROL_5_TTX_ERR_NP_TAG_IN_USE   (1 << 21)   /*WC*/
-#define PXPCS_TL_CONTROL_5_TRX_ERR_UNEXP_RTAG  (1 << 20)   /*WC*/
-#define PXPCS_TL_CONTROL_5_PRI_SIG_TARGET_ABORT1   (1 << 19)   /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_UNSPPORT1   (1 << 18)   /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_ECRC1   (1 << 17)   /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_MALF_TLP1   (1 << 16)   /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_RX_OFLOW1   (1 << 15)   /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_UNEXP_CPL1  (1 << 14)   /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_MASTER_ABRT1    (1 << 13)   /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_CPL_TIMEOUT1    (1 << 12)   /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_FC_PRTL1    (1 << 11)   /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_PSND_TLP1   (1 << 10)   /*WC*/
-#define PXPCS_TL_CONTROL_5_PRI_SIG_TARGET_ABORT    (1 << 9)    /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_UNSPPORT    (1 << 8)    /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_ECRC    (1 << 7)    /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_MALF_TLP    (1 << 6)    /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_RX_OFLOW    (1 << 5)    /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_UNEXP_CPL   (1 << 4)    /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_MASTER_ABRT     (1 << 3)    /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_CPL_TIMEOUT     (1 << 2)    /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_FC_PRTL	   (1 << 1)    /*WC*/
-#define PXPCS_TL_CONTROL_5_ERR_PSND_TLP    (1 << 0)    /*WC*/
-
-
-#define PXPCS_TL_FUNC345_STAT	   0x854
-#define PXPCS_TL_FUNC345_STAT_PRI_SIG_TARGET_ABORT4    (1 << 29)   /* WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT4\
-	(1 << 28) /* Unsupported Request Error Status in function4, if \
-	set, generate pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_ECRC4\
-	(1 << 27) /* ECRC Error TLP Status Status in function 4, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_MALF_TLP4\
-	(1 << 26) /* Malformed TLP Status Status in function 4, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_RX_OFLOW4\
-	(1 << 25) /* Receiver Overflow Status Status in function 4, if \
-	set, generate pcie_err_attn output when this error is seen.. WC \
-	*/
-#define PXPCS_TL_FUNC345_STAT_ERR_UNEXP_CPL4\
-	(1 << 24) /* Unexpected Completion Status Status in function 4, \
-	if set, generate pcie_err_attn output when this error is seen. WC \
-	*/
-#define PXPCS_TL_FUNC345_STAT_ERR_MASTER_ABRT4\
-	(1 << 23) /* Receive UR Statusin function 4. If set, generate \
-	pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_CPL_TIMEOUT4\
-	(1 << 22) /* Completer Timeout Status Status in function 4, if \
-	set, generate pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_FC_PRTL4\
-	(1 << 21) /* Flow Control Protocol Error Status Status in \
-	function 4, if set, generate pcie_err_attn output when this error \
-	is seen. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_PSND_TLP4\
-	(1 << 20) /* Poisoned Error Status Status in function 4, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-#define PXPCS_TL_FUNC345_STAT_PRI_SIG_TARGET_ABORT3    (1 << 19)   /* WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT3\
-	(1 << 18) /* Unsupported Request Error Status in function3, if \
-	set, generate pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_ECRC3\
-	(1 << 17) /* ECRC Error TLP Status Status in function 3, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_MALF_TLP3\
-	(1 << 16) /* Malformed TLP Status Status in function 3, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_RX_OFLOW3\
-	(1 << 15) /* Receiver Overflow Status Status in function 3, if \
-	set, generate pcie_err_attn output when this error is seen.. WC \
-	*/
-#define PXPCS_TL_FUNC345_STAT_ERR_UNEXP_CPL3\
-	(1 << 14) /* Unexpected Completion Status Status in function 3, \
-	if set, generate pcie_err_attn output when this error is seen. WC \
-	*/
-#define PXPCS_TL_FUNC345_STAT_ERR_MASTER_ABRT3\
-	(1 << 13) /* Receive UR Statusin function 3. If set, generate \
-	pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_CPL_TIMEOUT3\
-	(1 << 12) /* Completer Timeout Status Status in function 3, if \
-	set, generate pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_FC_PRTL3\
-	(1 << 11) /* Flow Control Protocol Error Status Status in \
-	function 3, if set, generate pcie_err_attn output when this error \
-	is seen. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_PSND_TLP3\
-	(1 << 10) /* Poisoned Error Status Status in function 3, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-#define PXPCS_TL_FUNC345_STAT_PRI_SIG_TARGET_ABORT2    (1 << 9)    /* WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT2\
-	(1 << 8) /* Unsupported Request Error Status for Function 2, if \
-	set, generate pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_ECRC2\
-	(1 << 7) /* ECRC Error TLP Status Status for Function 2, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_MALF_TLP2\
-	(1 << 6) /* Malformed TLP Status Status for Function 2, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_RX_OFLOW2\
-	(1 << 5) /* Receiver Overflow Status Status for Function 2, if \
-	set, generate pcie_err_attn output when this error is seen.. WC \
-	*/
-#define PXPCS_TL_FUNC345_STAT_ERR_UNEXP_CPL2\
-	(1 << 4) /* Unexpected Completion Status Status for Function 2, \
-	if set, generate pcie_err_attn output when this error is seen. WC \
-	*/
-#define PXPCS_TL_FUNC345_STAT_ERR_MASTER_ABRT2\
-	(1 << 3) /* Receive UR Statusfor Function 2. If set, generate \
-	pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_CPL_TIMEOUT2\
-	(1 << 2) /* Completer Timeout Status Status for Function 2, if \
-	set, generate pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_FC_PRTL2\
-	(1 << 1) /* Flow Control Protocol Error Status Status for \
-	Function 2, if set, generate pcie_err_attn output when this error \
-	is seen. WC */
-#define PXPCS_TL_FUNC345_STAT_ERR_PSND_TLP2\
-	(1 << 0) /* Poisoned Error Status Status for Function 2, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-
-
-#define PXPCS_TL_FUNC678_STAT  0x85C
-#define PXPCS_TL_FUNC678_STAT_PRI_SIG_TARGET_ABORT7    (1 << 29)   /*	 WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT7\
-	(1 << 28) /* Unsupported Request Error Status in function7, if \
-	set, generate pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_ECRC7\
-	(1 << 27) /* ECRC Error TLP Status Status in function 7, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_MALF_TLP7\
-	(1 << 26) /* Malformed TLP Status Status in function 7, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_RX_OFLOW7\
-	(1 << 25) /* Receiver Overflow Status Status in function 7, if \
-	set, generate pcie_err_attn output when this error is seen.. WC \
-	*/
-#define PXPCS_TL_FUNC678_STAT_ERR_UNEXP_CPL7\
-	(1 << 24) /* Unexpected Completion Status Status in function 7, \
-	if set, generate pcie_err_attn output when this error is seen. WC \
-	*/
-#define PXPCS_TL_FUNC678_STAT_ERR_MASTER_ABRT7\
-	(1 << 23) /* Receive UR Statusin function 7. If set, generate \
-	pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_CPL_TIMEOUT7\
-	(1 << 22) /* Completer Timeout Status Status in function 7, if \
-	set, generate pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_FC_PRTL7\
-	(1 << 21) /* Flow Control Protocol Error Status Status in \
-	function 7, if set, generate pcie_err_attn output when this error \
-	is seen. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_PSND_TLP7\
-	(1 << 20) /* Poisoned Error Status Status in function 7, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-#define PXPCS_TL_FUNC678_STAT_PRI_SIG_TARGET_ABORT6    (1 << 19)    /*	  WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT6\
-	(1 << 18) /* Unsupported Request Error Status in function6, if \
-	set, generate pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_ECRC6\
-	(1 << 17) /* ECRC Error TLP Status Status in function 6, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_MALF_TLP6\
-	(1 << 16) /* Malformed TLP Status Status in function 6, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_RX_OFLOW6\
-	(1 << 15) /* Receiver Overflow Status Status in function 6, if \
-	set, generate pcie_err_attn output when this error is seen.. WC \
-	*/
-#define PXPCS_TL_FUNC678_STAT_ERR_UNEXP_CPL6\
-	(1 << 14) /* Unexpected Completion Status Status in function 6, \
-	if set, generate pcie_err_attn output when this error is seen. WC \
-	*/
-#define PXPCS_TL_FUNC678_STAT_ERR_MASTER_ABRT6\
-	(1 << 13) /* Receive UR Statusin function 6. If set, generate \
-	pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_CPL_TIMEOUT6\
-	(1 << 12) /* Completer Timeout Status Status in function 6, if \
-	set, generate pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_FC_PRTL6\
-	(1 << 11) /* Flow Control Protocol Error Status Status in \
-	function 6, if set, generate pcie_err_attn output when this error \
-	is seen. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_PSND_TLP6\
-	(1 << 10) /* Poisoned Error Status Status in function 6, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-#define PXPCS_TL_FUNC678_STAT_PRI_SIG_TARGET_ABORT5    (1 << 9) /*    WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT5\
-	(1 << 8) /* Unsupported Request Error Status for Function 5, if \
-	set, generate pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_ECRC5\
-	(1 << 7) /* ECRC Error TLP Status Status for Function 5, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_MALF_TLP5\
-	(1 << 6) /* Malformed TLP Status Status for Function 5, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_RX_OFLOW5\
-	(1 << 5) /* Receiver Overflow Status Status for Function 5, if \
-	set, generate pcie_err_attn output when this error is seen.. WC \
-	*/
-#define PXPCS_TL_FUNC678_STAT_ERR_UNEXP_CPL5\
-	(1 << 4) /* Unexpected Completion Status Status for Function 5, \
-	if set, generate pcie_err_attn output when this error is seen. WC \
-	*/
-#define PXPCS_TL_FUNC678_STAT_ERR_MASTER_ABRT5\
-	(1 << 3) /* Receive UR Statusfor Function 5. If set, generate \
-	pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_CPL_TIMEOUT5\
-	(1 << 2) /* Completer Timeout Status Status for Function 5, if \
-	set, generate pcie_err_attn output when this error is seen. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_FC_PRTL5\
-	(1 << 1) /* Flow Control Protocol Error Status Status for \
-	Function 5, if set, generate pcie_err_attn output when this error \
-	is seen. WC */
-#define PXPCS_TL_FUNC678_STAT_ERR_PSND_TLP5\
-	(1 << 0) /* Poisoned Error Status Status for Function 5, if set, \
-	generate pcie_err_attn output when this error is seen.. WC */
-
-
-#define BAR_USTRORM_INTMEM				0x400000
-#define BAR_CSTRORM_INTMEM				0x410000
-#define BAR_XSTRORM_INTMEM				0x420000
-#define BAR_TSTRORM_INTMEM				0x430000
-
-/* for accessing the IGU in case of status block ACK */
-#define BAR_IGU_INTMEM					0x440000
-
-#define BAR_DOORBELL_OFFSET				0x800000
-
-#define BAR_ME_REGISTER				0x450000
-#define ME_REG_PF_NUM_SHIFT		0
-#define ME_REG_PF_NUM\
-	(7L<<ME_REG_PF_NUM_SHIFT) /* Relative PF Num */
-#define ME_REG_VF_VALID		(1<<8)
-#define ME_REG_VF_NUM_SHIFT		9
-#define ME_REG_VF_NUM_MASK		(0x3f<<ME_REG_VF_NUM_SHIFT)
-#define ME_REG_VF_ERR			(0x1<<3)
-#define ME_REG_ABS_PF_NUM_SHIFT	16
-#define ME_REG_ABS_PF_NUM\
-	(7L<<ME_REG_ABS_PF_NUM_SHIFT) /* Absolute PF Num */
-
-
-#define MDIO_REG_BANK_CL73_IEEEB0	0x0
-#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL	0x0
-#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN	0x0200
-#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN		0x1000
-#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_MAIN_RST	0x8000
-
-#define MDIO_REG_BANK_CL73_IEEEB1	0x10
-#define MDIO_CL73_IEEEB1_AN_ADV1		0x00
-#define MDIO_CL73_IEEEB1_AN_ADV1_PAUSE			0x0400
-#define MDIO_CL73_IEEEB1_AN_ADV1_ASYMMETRIC		0x0800
-#define MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH		0x0C00
-#define MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK		0x0C00
-#define MDIO_CL73_IEEEB1_AN_ADV2		0x01
-#define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M		0x0000
-#define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX		0x0020
-#define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4		0x0040
-#define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KR		0x0080
-#define MDIO_CL73_IEEEB1_AN_LP_ADV1		0x03
-#define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE		0x0400
-#define MDIO_CL73_IEEEB1_AN_LP_ADV1_ASYMMETRIC		0x0800
-#define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_BOTH		0x0C00
-#define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK		0x0C00
-
-#define MDIO_REG_BANK_RX0				0x80b0
-#define MDIO_RX0_RX_STATUS				0x10
-#define MDIO_RX0_RX_STATUS_SIGDET			0x8000
-#define MDIO_RX0_RX_STATUS_RX_SEQ_DONE			0x1000
-#define MDIO_RX0_RX_EQ_BOOST				0x1c
-#define MDIO_RX0_RX_EQ_BOOST_EQUALIZER_CTRL_MASK	0x7
-#define MDIO_RX0_RX_EQ_BOOST_OFFSET_CTRL		0x10
-
-#define MDIO_REG_BANK_RX1				0x80c0
-#define MDIO_RX1_RX_EQ_BOOST				0x1c
-#define MDIO_RX1_RX_EQ_BOOST_EQUALIZER_CTRL_MASK	0x7
-#define MDIO_RX1_RX_EQ_BOOST_OFFSET_CTRL		0x10
-
-#define MDIO_REG_BANK_RX2				0x80d0
-#define MDIO_RX2_RX_EQ_BOOST				0x1c
-#define MDIO_RX2_RX_EQ_BOOST_EQUALIZER_CTRL_MASK	0x7
-#define MDIO_RX2_RX_EQ_BOOST_OFFSET_CTRL		0x10
-
-#define MDIO_REG_BANK_RX3				0x80e0
-#define MDIO_RX3_RX_EQ_BOOST				0x1c
-#define MDIO_RX3_RX_EQ_BOOST_EQUALIZER_CTRL_MASK	0x7
-#define MDIO_RX3_RX_EQ_BOOST_OFFSET_CTRL		0x10
-
-#define MDIO_REG_BANK_RX_ALL				0x80f0
-#define MDIO_RX_ALL_RX_EQ_BOOST 			0x1c
-#define MDIO_RX_ALL_RX_EQ_BOOST_EQUALIZER_CTRL_MASK	0x7
-#define MDIO_RX_ALL_RX_EQ_BOOST_OFFSET_CTRL	0x10
-
-#define MDIO_REG_BANK_TX0				0x8060
-#define MDIO_TX0_TX_DRIVER				0x17
-#define MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK		0xf000
-#define MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT		12
-#define MDIO_TX0_TX_DRIVER_IDRIVER_MASK 		0x0f00
-#define MDIO_TX0_TX_DRIVER_IDRIVER_SHIFT		8
-#define MDIO_TX0_TX_DRIVER_IPREDRIVER_MASK		0x00f0
-#define MDIO_TX0_TX_DRIVER_IPREDRIVER_SHIFT		4
-#define MDIO_TX0_TX_DRIVER_IFULLSPD_MASK		0x000e
-#define MDIO_TX0_TX_DRIVER_IFULLSPD_SHIFT		1
-#define MDIO_TX0_TX_DRIVER_ICBUF1T			1
-
-#define MDIO_REG_BANK_TX1				0x8070
-#define MDIO_TX1_TX_DRIVER				0x17
-#define MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK		0xf000
-#define MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT		12
-#define MDIO_TX0_TX_DRIVER_IDRIVER_MASK 		0x0f00
-#define MDIO_TX0_TX_DRIVER_IDRIVER_SHIFT		8
-#define MDIO_TX0_TX_DRIVER_IPREDRIVER_MASK		0x00f0
-#define MDIO_TX0_TX_DRIVER_IPREDRIVER_SHIFT		4
-#define MDIO_TX0_TX_DRIVER_IFULLSPD_MASK		0x000e
-#define MDIO_TX0_TX_DRIVER_IFULLSPD_SHIFT		1
-#define MDIO_TX0_TX_DRIVER_ICBUF1T			1
-
-#define MDIO_REG_BANK_TX2				0x8080
-#define MDIO_TX2_TX_DRIVER				0x17
-#define MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK		0xf000
-#define MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT		12
-#define MDIO_TX0_TX_DRIVER_IDRIVER_MASK 		0x0f00
-#define MDIO_TX0_TX_DRIVER_IDRIVER_SHIFT		8
-#define MDIO_TX0_TX_DRIVER_IPREDRIVER_MASK		0x00f0
-#define MDIO_TX0_TX_DRIVER_IPREDRIVER_SHIFT		4
-#define MDIO_TX0_TX_DRIVER_IFULLSPD_MASK		0x000e
-#define MDIO_TX0_TX_DRIVER_IFULLSPD_SHIFT		1
-#define MDIO_TX0_TX_DRIVER_ICBUF1T			1
-
-#define MDIO_REG_BANK_TX3				0x8090
-#define MDIO_TX3_TX_DRIVER				0x17
-#define MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK		0xf000
-#define MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT		12
-#define MDIO_TX0_TX_DRIVER_IDRIVER_MASK 		0x0f00
-#define MDIO_TX0_TX_DRIVER_IDRIVER_SHIFT		8
-#define MDIO_TX0_TX_DRIVER_IPREDRIVER_MASK		0x00f0
-#define MDIO_TX0_TX_DRIVER_IPREDRIVER_SHIFT		4
-#define MDIO_TX0_TX_DRIVER_IFULLSPD_MASK		0x000e
-#define MDIO_TX0_TX_DRIVER_IFULLSPD_SHIFT		1
-#define MDIO_TX0_TX_DRIVER_ICBUF1T			1
-
-#define MDIO_REG_BANK_XGXS_BLOCK0			0x8000
-#define MDIO_BLOCK0_XGXS_CONTROL			0x10
-
-#define MDIO_REG_BANK_XGXS_BLOCK1			0x8010
-#define MDIO_BLOCK1_LANE_CTRL0				0x15
-#define MDIO_BLOCK1_LANE_CTRL1				0x16
-#define MDIO_BLOCK1_LANE_CTRL2				0x17
-#define MDIO_BLOCK1_LANE_PRBS				0x19
-
-#define MDIO_REG_BANK_XGXS_BLOCK2			0x8100
-#define MDIO_XGXS_BLOCK2_RX_LN_SWAP			0x10
-#define MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE		0x8000
-#define MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE	0x4000
-#define MDIO_XGXS_BLOCK2_TX_LN_SWAP		0x11
-#define MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE		0x8000
-#define MDIO_XGXS_BLOCK2_UNICORE_MODE_10G	0x14
-#define MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS	0x0001
-#define MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS	0x0010
-#define MDIO_XGXS_BLOCK2_TEST_MODE_LANE 	0x15
-
-#define MDIO_REG_BANK_GP_STATUS 			0x8120
-#define MDIO_GP_STATUS_TOP_AN_STATUS1				0x1B
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE	0x0001
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_CL37_AUTONEG_COMPLETE	0x0002
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS		0x0004
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS		0x0008
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE	0x0010
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_LP_NP_BAM_ABLE	0x0020
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_TXSIDE	0x0040
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_RXSIDE	0x0080
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_MASK 	0x3f00
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10M		0x0000
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_100M 	0x0100
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G		0x0200
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_2_5G 	0x0300
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_5G		0x0400
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_6G		0x0500
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_HIG	0x0600
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_CX4	0x0700
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12G_HIG	0x0800
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12_5G	0x0900
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_13G		0x0A00
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_15G		0x0B00
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_16G		0x0C00
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX	0x0D00
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4	0x0E00
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KR	0x0F00
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI	0x1B00
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS	0x1E00
-#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI	0x1F00
-
-
-#define MDIO_REG_BANK_10G_PARALLEL_DETECT		0x8130
-#define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS		0x10
-#define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS_PD_LINK		0x8000
-#define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL		0x11
-#define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN	0x1
-#define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK		0x13
-#define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT		(0xb71<<1)
-
-#define MDIO_REG_BANK_SERDES_DIGITAL			0x8300
-#define MDIO_SERDES_DIGITAL_A_1000X_CONTROL1			0x10
-#define MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE 		0x0001
-#define MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_TBI_IF			0x0002
-#define MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN		0x0004
-#define MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT	0x0008
-#define MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET			0x0010
-#define MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_MSTR_MODE			0x0020
-#define MDIO_SERDES_DIGITAL_A_1000X_CONTROL2			0x11
-#define MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN			0x0001
-#define MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_AN_FST_TMR 		0x0040
-#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1			0x14
-#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SGMII			0x0001
-#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_LINK			0x0002
-#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_DUPLEX			0x0004
-#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_MASK			0x0018
-#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_SHIFT 		3
-#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_2_5G			0x0018
-#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_1G			0x0010
-#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_100M			0x0008
-#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_10M			0x0000
-#define MDIO_SERDES_DIGITAL_A_1000X_STATUS2			0x15
-#define MDIO_SERDES_DIGITAL_A_1000X_STATUS2_AN_DISABLED 		0x0002
-#define MDIO_SERDES_DIGITAL_MISC1				0x18
-#define MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_MASK			0xE000
-#define MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_25M			0x0000
-#define MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_100M			0x2000
-#define MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_125M			0x4000
-#define MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M			0x6000
-#define MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_187_5M			0x8000
-#define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL			0x0010
-#define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK			0x000f
-#define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_2_5G			0x0000
-#define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_5G			0x0001
-#define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_6G			0x0002
-#define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_HIG			0x0003
-#define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4			0x0004
-#define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_12G			0x0005
-#define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_12_5G			0x0006
-#define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G			0x0007
-#define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_15G			0x0008
-#define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_16G			0x0009
-
-#define MDIO_REG_BANK_OVER_1G				0x8320
-#define MDIO_OVER_1G_DIGCTL_3_4 				0x14
-#define MDIO_OVER_1G_DIGCTL_3_4_MP_ID_MASK				0xffe0
-#define MDIO_OVER_1G_DIGCTL_3_4_MP_ID_SHIFT				5
-#define MDIO_OVER_1G_UP1					0x19
-#define MDIO_OVER_1G_UP1_2_5G						0x0001
-#define MDIO_OVER_1G_UP1_5G						0x0002
-#define MDIO_OVER_1G_UP1_6G						0x0004
-#define MDIO_OVER_1G_UP1_10G						0x0010
-#define MDIO_OVER_1G_UP1_10GH						0x0008
-#define MDIO_OVER_1G_UP1_12G						0x0020
-#define MDIO_OVER_1G_UP1_12_5G						0x0040
-#define MDIO_OVER_1G_UP1_13G						0x0080
-#define MDIO_OVER_1G_UP1_15G						0x0100
-#define MDIO_OVER_1G_UP1_16G						0x0200
-#define MDIO_OVER_1G_UP2					0x1A
-#define MDIO_OVER_1G_UP2_IPREDRIVER_MASK				0x0007
-#define MDIO_OVER_1G_UP2_IDRIVER_MASK					0x0038
-#define MDIO_OVER_1G_UP2_PREEMPHASIS_MASK				0x03C0
-#define MDIO_OVER_1G_UP3					0x1B
-#define MDIO_OVER_1G_UP3_HIGIG2 					0x0001
-#define MDIO_OVER_1G_LP_UP1					0x1C
-#define MDIO_OVER_1G_LP_UP2					0x1D
-#define MDIO_OVER_1G_LP_UP2_MR_ADV_OVER_1G_MASK 			0x03ff
-#define MDIO_OVER_1G_LP_UP2_PREEMPHASIS_MASK				0x0780
-#define MDIO_OVER_1G_LP_UP2_PREEMPHASIS_SHIFT				7
-#define MDIO_OVER_1G_LP_UP3						0x1E
-
-#define MDIO_REG_BANK_REMOTE_PHY			0x8330
-#define MDIO_REMOTE_PHY_MISC_RX_STATUS				0x10
-#define MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG	0x0010
-#define MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG	0x0600
-
-#define MDIO_REG_BANK_BAM_NEXT_PAGE			0x8350
-#define MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL			0x10
-#define MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE			0x0001
-#define MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN			0x0002
-
-#define MDIO_REG_BANK_CL73_USERB0		0x8370
-#define MDIO_CL73_USERB0_CL73_UCTRL				0x10
-#define MDIO_CL73_USERB0_CL73_UCTRL_USTAT1_MUXSEL			0x0002
-#define MDIO_CL73_USERB0_CL73_USTAT1				0x11
-#define MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK			0x0100
-#define MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37		0x0400
-#define MDIO_CL73_USERB0_CL73_BAM_CTRL1 			0x12
-#define MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN				0x8000
-#define MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN		0x4000
-#define MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN		0x2000
-#define MDIO_CL73_USERB0_CL73_BAM_CTRL3 			0x14
-#define MDIO_CL73_USERB0_CL73_BAM_CTRL3_USE_CL73_HCD_MR 		0x0001
-
-#define MDIO_REG_BANK_AER_BLOCK 		0xFFD0
-#define MDIO_AER_BLOCK_AER_REG					0x1E
-
-#define MDIO_REG_BANK_COMBO_IEEE0		0xFFE0
-#define MDIO_COMBO_IEEE0_MII_CONTROL				0x10
-#define MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK			0x2040
-#define MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_10			0x0000
-#define MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_100			0x2000
-#define MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_1000			0x0040
-#define MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX 			0x0100
-#define MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN				0x0200
-#define MDIO_COMBO_IEEO_MII_CONTROL_AN_EN				0x1000
-#define MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK				0x4000
-#define MDIO_COMBO_IEEO_MII_CONTROL_RESET				0x8000
-#define MDIO_COMBO_IEEE0_MII_STATUS				0x11
-#define MDIO_COMBO_IEEE0_MII_STATUS_LINK_PASS				0x0004
-#define MDIO_COMBO_IEEE0_MII_STATUS_AUTONEG_COMPLETE			0x0020
-#define MDIO_COMBO_IEEE0_AUTO_NEG_ADV				0x14
-#define MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX			0x0020
-#define MDIO_COMBO_IEEE0_AUTO_NEG_ADV_HALF_DUPLEX			0x0040
-#define MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK			0x0180
-#define MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE			0x0000
-#define MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC			0x0080
-#define MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC			0x0100
-#define MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH			0x0180
-#define MDIO_COMBO_IEEE0_AUTO_NEG_ADV_NEXT_PAGE 			0x8000
-#define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1 	0x15
-#define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_NEXT_PAGE	0x8000
-#define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_ACK		0x4000
-#define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_PAUSE_MASK	0x0180
-#define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_PAUSE_NONE	0x0000
-#define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_PAUSE_BOTH	0x0180
-#define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_HALF_DUP_CAP	0x0040
-#define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_FULL_DUP_CAP	0x0020
-/*WhenthelinkpartnerisinSGMIImode(bit0=1),then
-bit15=link,bit12=duplex,bits11:10=speed,bit14=acknowledge.
-Theotherbitsarereservedandshouldbezero*/
-#define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_SGMII_MODE	0x0001
-
-
-#define MDIO_PMA_DEVAD			0x1
-/*ieee*/
-#define MDIO_PMA_REG_CTRL		0x0
-#define MDIO_PMA_REG_STATUS		0x1
-#define MDIO_PMA_REG_10G_CTRL2		0x7
-#define MDIO_PMA_REG_TX_DISABLE		0x0009
-#define MDIO_PMA_REG_RX_SD		0xa
-/*bcm*/
-#define MDIO_PMA_REG_BCM_CTRL		0x0096
-#define MDIO_PMA_REG_FEC_CTRL		0x00ab
-#define MDIO_PMA_REG_PHY_IDENTIFIER	0xc800
-#define MDIO_PMA_REG_DIGITAL_CTRL	0xc808
-#define MDIO_PMA_REG_DIGITAL_STATUS	0xc809
-#define MDIO_PMA_REG_TX_POWER_DOWN	0xca02
-#define MDIO_PMA_REG_CMU_PLL_BYPASS	0xca09
-#define MDIO_PMA_REG_MISC_CTRL		0xca0a
-#define MDIO_PMA_REG_GEN_CTRL		0xca10
-#define MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP	0x0188
-#define MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET		0x018a
-#define MDIO_PMA_REG_M8051_MSGIN_REG	0xca12
-#define MDIO_PMA_REG_M8051_MSGOUT_REG	0xca13
-#define MDIO_PMA_REG_ROM_VER1		0xca19
-#define MDIO_PMA_REG_ROM_VER2		0xca1a
-#define MDIO_PMA_REG_EDC_FFE_MAIN	0xca1b
-#define MDIO_PMA_REG_PLL_BANDWIDTH	0xca1d
-#define MDIO_PMA_REG_PLL_CTRL		0xca1e
-#define MDIO_PMA_REG_MISC_CTRL0 	0xca23
-#define MDIO_PMA_REG_LRM_MODE		0xca3f
-#define MDIO_PMA_REG_CDR_BANDWIDTH	0xca46
-#define MDIO_PMA_REG_MISC_CTRL1 	0xca85
-
-#define MDIO_PMA_REG_SFP_TWO_WIRE_CTRL		0x8000
-#define MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK	0x000c
-#define MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE		0x0000
-#define MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE	0x0004
-#define MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IN_PROGRESS	0x0008
-#define MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_FAILED 	0x000c
-#define MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT	0x8002
-#define MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR	0x8003
-#define MDIO_PMA_REG_8726_TWO_WIRE_DATA_BUF	0xc820
-#define MDIO_PMA_REG_8726_TWO_WIRE_DATA_MASK 0xff
-#define MDIO_PMA_REG_8726_TX_CTRL1		0xca01
-#define MDIO_PMA_REG_8726_TX_CTRL2		0xca05
-
-#define MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR	0x8005
-#define MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF	0x8007
-#define MDIO_PMA_REG_8727_TWO_WIRE_DATA_MASK 0xff
-#define MDIO_PMA_REG_8727_TX_CTRL1		0xca02
-#define MDIO_PMA_REG_8727_TX_CTRL2		0xca05
-#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
-
-#define MDIO_PMA_REG_8073_CHIP_REV			0xc801
-#define MDIO_PMA_REG_8073_SPEED_LINK_STATUS		0xc820
-#define MDIO_PMA_REG_8073_XAUI_WA			0xc841
-#define MDIO_PMA_REG_8073_OPT_DIGITAL_CTRL		0xcd08
-
-#define MDIO_PMA_REG_7101_RESET 	0xc000
-#define MDIO_PMA_REG_7107_LED_CNTL	0xc007
-#define MDIO_PMA_REG_7107_LINK_LED_CNTL 0xc009
-#define MDIO_PMA_REG_7101_VER1		0xc026
-#define MDIO_PMA_REG_7101_VER2		0xc027
-
-#define MDIO_PMA_REG_8481_PMD_SIGNAL			0xa811
-#define MDIO_PMA_REG_8481_LED1_MASK			0xa82c
-#define MDIO_PMA_REG_8481_LED2_MASK			0xa82f
-#define MDIO_PMA_REG_8481_LED3_MASK			0xa832
-#define MDIO_PMA_REG_8481_LED3_BLINK			0xa834
-#define MDIO_PMA_REG_8481_LED5_MASK			0xa838
-#define MDIO_PMA_REG_8481_SIGNAL_MASK			0xa835
-#define MDIO_PMA_REG_8481_LINK_SIGNAL			0xa83b
-#define MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_MASK	0x800
-#define MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_SHIFT 11
-
-
-#define MDIO_WIS_DEVAD			0x2
-/*bcm*/
-#define MDIO_WIS_REG_LASI_CNTL		0x9002
-#define MDIO_WIS_REG_LASI_STATUS	0x9005
-
-#define MDIO_PCS_DEVAD			0x3
-#define MDIO_PCS_REG_STATUS		0x0020
-#define MDIO_PCS_REG_LASI_STATUS	0x9005
-#define MDIO_PCS_REG_7101_DSP_ACCESS	0xD000
-#define MDIO_PCS_REG_7101_SPI_MUX	0xD008
-#define MDIO_PCS_REG_7101_SPI_CTRL_ADDR 0xE12A
-#define MDIO_PCS_REG_7101_SPI_RESET_BIT (5)
-#define MDIO_PCS_REG_7101_SPI_FIFO_ADDR 0xE02A
-#define MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD (6)
-#define MDIO_PCS_REG_7101_SPI_FIFO_ADDR_BULK_ERASE_CMD	 (0xC7)
-#define MDIO_PCS_REG_7101_SPI_FIFO_ADDR_PAGE_PROGRAM_CMD (2)
-#define MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR 0xE028
-
-
-#define MDIO_XS_DEVAD			0x4
-#define MDIO_XS_PLL_SEQUENCER		0x8000
-#define MDIO_XS_SFX7101_XGXS_TEST1	0xc00a
-
-#define MDIO_XS_8706_REG_BANK_RX0	0x80bc
-#define MDIO_XS_8706_REG_BANK_RX1	0x80cc
-#define MDIO_XS_8706_REG_BANK_RX2	0x80dc
-#define MDIO_XS_8706_REG_BANK_RX3	0x80ec
-#define MDIO_XS_8706_REG_BANK_RXA	0x80fc
-
-#define MDIO_XS_REG_8073_RX_CTRL_PCIE	0x80FA
-
-#define MDIO_AN_DEVAD			0x7
-/*ieee*/
-#define MDIO_AN_REG_CTRL		0x0000
-#define MDIO_AN_REG_STATUS		0x0001
-#define MDIO_AN_REG_STATUS_AN_COMPLETE		0x0020
-#define MDIO_AN_REG_ADV_PAUSE		0x0010
-#define MDIO_AN_REG_ADV_PAUSE_PAUSE		0x0400
-#define MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC	0x0800
-#define MDIO_AN_REG_ADV_PAUSE_BOTH		0x0C00
-#define MDIO_AN_REG_ADV_PAUSE_MASK		0x0C00
-#define MDIO_AN_REG_ADV 		0x0011
-#define MDIO_AN_REG_ADV2		0x0012
-#define MDIO_AN_REG_LP_AUTO_NEG 	0x0013
-#define MDIO_AN_REG_MASTER_STATUS	0x0021
-/*bcm*/
-#define MDIO_AN_REG_LINK_STATUS 	0x8304
-#define MDIO_AN_REG_CL37_CL73		0x8370
-#define MDIO_AN_REG_CL37_AN		0xffe0
-#define MDIO_AN_REG_CL37_FC_LD		0xffe4
-#define MDIO_AN_REG_CL37_FC_LP		0xffe5
-
-#define MDIO_AN_REG_8073_2_5G		0x8329
-#define MDIO_AN_REG_8073_BAM		0x8350
-
-#define MDIO_AN_REG_8481_10GBASE_T_AN_CTRL	0x0020
-#define MDIO_AN_REG_8481_LEGACY_MII_CTRL	0xffe0
-#define MDIO_AN_REG_8481_LEGACY_MII_STATUS	0xffe1
-#define MDIO_AN_REG_8481_LEGACY_AN_ADV		0xffe4
-#define MDIO_AN_REG_8481_LEGACY_AN_EXPANSION	0xffe6
-#define MDIO_AN_REG_8481_1000T_CTRL		0xffe9
-#define MDIO_AN_REG_8481_EXPANSION_REG_RD_RW	0xfff5
-#define MDIO_AN_REG_8481_EXPANSION_REG_ACCESS	0xfff7
-#define MDIO_AN_REG_8481_AUX_CTRL		0xfff8
-#define MDIO_AN_REG_8481_LEGACY_SHADOW		0xfffc
-
-/* BCM84823 only */
-#define MDIO_CTL_DEVAD			0x1e
-#define MDIO_CTL_REG_84823_MEDIA		0x401a
-#define MDIO_CTL_REG_84823_MEDIA_MAC_MASK		0x0018
-	/* These pins configure the BCM84823 interface to MAC after reset. */
-#define MDIO_CTL_REG_84823_CTRL_MAC_XFI			0x0008
-#define MDIO_CTL_REG_84823_MEDIA_MAC_XAUI_M		0x0010
-	/* These pins configure the BCM84823 interface to Line after reset. */
-#define MDIO_CTL_REG_84823_MEDIA_LINE_MASK		0x0060
-#define MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L		0x0020
-#define MDIO_CTL_REG_84823_MEDIA_LINE_XFI		0x0040
-	/* When this pin is active high during reset, 10GBASE-T core is power
-	 * down, When it is active low the 10GBASE-T is power up
-	 */
-#define MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN	0x0080
-#define MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK		0x0100
-#define MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER	0x0000
-#define MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER		0x0100
-#define MDIO_CTL_REG_84823_MEDIA_FIBER_1G			0x1000
-#define MDIO_CTL_REG_84823_USER_CTRL_REG		0x4005
-#define MDIO_CTL_REG_84823_USER_CTRL_CMS		0x0080
-
-#define MDIO_PMA_REG_84823_CTL_LED_CTL_1		0xa8e3
-#define MDIO_PMA_REG_84823_LED3_STRETCH_EN		0x0080
-
-/* BCM84833 only */
-#define MDIO_84833_TOP_CFG_XGPHY_STRAP1			0x401a
-#define MDIO_84833_SUPER_ISOLATE		0x8000
-/* These are mailbox register set used by 84833. */
-#define MDIO_84833_TOP_CFG_SCRATCH_REG0			0x4005
-#define MDIO_84833_TOP_CFG_SCRATCH_REG1			0x4006
-#define MDIO_84833_TOP_CFG_SCRATCH_REG2			0x4007
-#define MDIO_84833_TOP_CFG_SCRATCH_REG3			0x4008
-#define MDIO_84833_TOP_CFG_SCRATCH_REG4			0x4009
-#define MDIO_84833_TOP_CFG_DATA3_REG			0x4011
-#define MDIO_84833_TOP_CFG_DATA4_REG			0x4012
-
-/* Mailbox command set used by 84833. */
-#define PHY84833_DIAG_CMD_PAIR_SWAP_CHANGE		0x2
-/* Mailbox status set used by 84833. */
-#define PHY84833_CMD_RECEIVED				0x0001
-#define PHY84833_CMD_IN_PROGRESS			0x0002
-#define PHY84833_CMD_COMPLETE_PASS			0x0004
-#define PHY84833_CMD_COMPLETE_ERROR			0x0008
-#define PHY84833_CMD_OPEN_FOR_CMDS			0x0010
-#define PHY84833_CMD_SYSTEM_BOOT			0x0020
-#define PHY84833_CMD_NOT_OPEN_FOR_CMDS			0x0040
-#define PHY84833_CMD_CLEAR_COMPLETE			0x0080
-#define PHY84833_CMD_OPEN_OVERRIDE			0xa5a5
-
-
-/* 84833 F/W Feature Commands */
-#define PHY84833_DIAG_CMD_GET_EEE_MODE			0x27
-#define PHY84833_DIAG_CMD_SET_EEE_MODE			0x28
-
-/* Warpcore clause 45 addressing */
-#define MDIO_WC_DEVAD					0x3
-#define MDIO_WC_REG_IEEE0BLK_MIICNTL			0x0
-#define MDIO_WC_REG_IEEE0BLK_AUTONEGNP			0x7
-#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT0	0x10
-#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1	0x11
-#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT2	0x12
-#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_ABILITY	0x4000
-#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_REQ		0x8000
-#define MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150  0x96
-#define MDIO_WC_REG_XGXSBLK0_XGXSCONTROL		0x8000
-#define MDIO_WC_REG_XGXSBLK0_MISCCONTROL1		0x800e
-#define MDIO_WC_REG_XGXSBLK1_DESKEW			0x8010
-#define MDIO_WC_REG_XGXSBLK1_LANECTRL0			0x8015
-#define MDIO_WC_REG_XGXSBLK1_LANECTRL1			0x8016
-#define MDIO_WC_REG_XGXSBLK1_LANECTRL2			0x8017
-#define MDIO_WC_REG_TX0_ANA_CTRL0			0x8061
-#define MDIO_WC_REG_TX1_ANA_CTRL0			0x8071
-#define MDIO_WC_REG_TX2_ANA_CTRL0			0x8081
-#define MDIO_WC_REG_TX3_ANA_CTRL0			0x8091
-#define MDIO_WC_REG_TX0_TX_DRIVER			0x8067
-#define MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET		0x04
-#define MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_MASK			0x00f0
-#define MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET		0x08
-#define MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_MASK				0x0f00
-#define MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET		0x0c
-#define MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_MASK			0x7000
-#define MDIO_WC_REG_TX1_TX_DRIVER			0x8077
-#define MDIO_WC_REG_TX2_TX_DRIVER			0x8087
-#define MDIO_WC_REG_TX3_TX_DRIVER			0x8097
-#define MDIO_WC_REG_RX0_ANARXCONTROL1G			0x80b9
-#define MDIO_WC_REG_RX2_ANARXCONTROL1G			0x80d9
-#define MDIO_WC_REG_RX0_PCI_CTRL			0x80ba
-#define MDIO_WC_REG_RX1_PCI_CTRL			0x80ca
-#define MDIO_WC_REG_RX2_PCI_CTRL			0x80da
-#define MDIO_WC_REG_RX3_PCI_CTRL			0x80ea
-#define MDIO_WC_REG_XGXSBLK2_UNICORE_MODE_10G		0x8104
-#define MDIO_WC_REG_XGXS_STATUS3			0x8129
-#define MDIO_WC_REG_PAR_DET_10G_STATUS			0x8130
-#define MDIO_WC_REG_PAR_DET_10G_CTRL			0x8131
-#define MDIO_WC_REG_XGXS_X2_CONTROL2			0x8141
-#define MDIO_WC_REG_XGXS_RX_LN_SWAP1			0x816B
-#define MDIO_WC_REG_XGXS_TX_LN_SWAP1			0x8169
-#define MDIO_WC_REG_GP2_STATUS_GP_2_0			0x81d0
-#define MDIO_WC_REG_GP2_STATUS_GP_2_1			0x81d1
-#define MDIO_WC_REG_GP2_STATUS_GP_2_2			0x81d2
-#define MDIO_WC_REG_GP2_STATUS_GP_2_3			0x81d3
-#define MDIO_WC_REG_GP2_STATUS_GP_2_4			0x81d4
-#define MDIO_WC_REG_UC_INFO_B0_DEAD_TRAP		0x81EE
-#define MDIO_WC_REG_UC_INFO_B1_VERSION			0x81F0
-#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE		0x81F2
-#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE0_OFFSET	0x0
-#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT	    0x0
-#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_OPT_LR	    0x1
-#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_DAC	    0x2
-#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_XLAUI	    0x3
-#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_LONG_CH_6G	    0x4
-#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE1_OFFSET	0x4
-#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE2_OFFSET	0x8
-#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE3_OFFSET	0xc
-#define MDIO_WC_REG_UC_INFO_B1_CRC			0x81FE
-#define MDIO_WC_REG_DSC_SMC				0x8213
-#define MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0		0x821e
-#define MDIO_WC_REG_TX_FIR_TAP				0x82e2
-#define MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET		0x00
-#define MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_MASK			0x000f
-#define MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET		0x04
-#define MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_MASK		0x03f0
-#define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET		0x0a
-#define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_MASK		0x7c00
-#define MDIO_WC_REG_TX_FIR_TAP_ENABLE		0x8000
-#define MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL	0x82e3
-#define MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL	0x82e6
-#define MDIO_WC_REG_CL72_USERB0_CL72_BR_DEF_CTRL	0x82e7
-#define MDIO_WC_REG_CL72_USERB0_CL72_2P5_DEF_CTRL	0x82e8
-#define MDIO_WC_REG_CL72_USERB0_CL72_MISC4_CONTROL	0x82ec
-#define MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1		0x8300
-#define MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2		0x8301
-#define MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3		0x8302
-#define MDIO_WC_REG_SERDESDIGITAL_STATUS1000X1		0x8304
-#define MDIO_WC_REG_SERDESDIGITAL_MISC1			0x8308
-#define MDIO_WC_REG_SERDESDIGITAL_MISC2			0x8309
-#define MDIO_WC_REG_DIGITAL3_UP1			0x8329
-#define MDIO_WC_REG_DIGITAL4_MISC3			0x833c
-#define MDIO_WC_REG_DIGITAL5_MISC6			0x8345
-#define MDIO_WC_REG_DIGITAL5_MISC7			0x8349
-#define MDIO_WC_REG_DIGITAL5_ACTUAL_SPEED		0x834e
-#define MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL		0x8350
-#define MDIO_WC_REG_CL49_USERB0_CTRL			0x8368
-#define MDIO_WC_REG_TX66_CONTROL			0x83b0
-#define MDIO_WC_REG_RX66_CONTROL			0x83c0
-#define MDIO_WC_REG_RX66_SCW0				0x83c2
-#define MDIO_WC_REG_RX66_SCW1				0x83c3
-#define MDIO_WC_REG_RX66_SCW2				0x83c4
-#define MDIO_WC_REG_RX66_SCW3				0x83c5
-#define MDIO_WC_REG_RX66_SCW0_MASK			0x83c6
-#define MDIO_WC_REG_RX66_SCW1_MASK			0x83c7
-#define MDIO_WC_REG_RX66_SCW2_MASK			0x83c8
-#define MDIO_WC_REG_RX66_SCW3_MASK			0x83c9
-#define MDIO_WC_REG_FX100_CTRL1				0x8400
-#define MDIO_WC_REG_FX100_CTRL3				0x8402
-
-#define MDIO_WC_REG_MICROBLK_CMD			0xffc2
-#define MDIO_WC_REG_MICROBLK_DL_STATUS			0xffc5
-#define MDIO_WC_REG_MICROBLK_CMD3			0xffcc
-
-#define MDIO_WC_REG_AERBLK_AER				0xffde
-#define MDIO_WC_REG_COMBO_IEEE0_MIICTRL			0xffe0
-#define MDIO_WC_REG_COMBO_IEEE0_MIIISTAT		0xffe1
-
-#define MDIO_WC0_XGXS_BLK2_LANE_RESET			0x810A
-#define MDIO_WC0_XGXS_BLK2_LANE_RESET_RX_BITSHIFT	0
-#define MDIO_WC0_XGXS_BLK2_LANE_RESET_TX_BITSHIFT	4
-
-#define MDIO_WC0_XGXS_BLK6_XGXS_X2_CONTROL2		0x8141
-
-#define DIGITAL5_ACTUAL_SPEED_TX_MASK			0x003f
-
-/* 54618se */
-#define MDIO_REG_GPHY_PHYID_LSB				0x3
-#define MDIO_REG_GPHY_ID_54618SE		0x5cd5
-#define MDIO_REG_GPHY_CL45_ADDR_REG			0xd
-#define MDIO_REG_GPHY_CL45_DATA_REG			0xe
-#define MDIO_REG_GPHY_EEE_ADV			0x3c
-#define MDIO_REG_GPHY_EEE_1G		(0x1 << 2)
-#define MDIO_REG_GPHY_EEE_100		(0x1 << 1)
-#define MDIO_REG_GPHY_EEE_RESOLVED		0x803e
-#define MDIO_REG_INTR_STATUS				0x1a
-#define MDIO_REG_INTR_MASK				0x1b
-#define MDIO_REG_INTR_MASK_LINK_STATUS			(0x1 << 1)
-#define MDIO_REG_GPHY_SHADOW				0x1c
-#define MDIO_REG_GPHY_SHADOW_LED_SEL2			(0x0e << 10)
-#define MDIO_REG_GPHY_SHADOW_WR_ENA			(0x1 << 15)
-#define MDIO_REG_GPHY_SHADOW_AUTO_DET_MED		(0x1e << 10)
-#define MDIO_REG_GPHY_SHADOW_INVERT_FIB_SD		(0x1 << 8)
-
-#define IGU_FUNC_BASE			0x0400
-
-#define IGU_ADDR_MSIX			0x0000
-#define IGU_ADDR_INT_ACK		0x0200
-#define IGU_ADDR_PROD_UPD		0x0201
-#define IGU_ADDR_ATTN_BITS_UPD	0x0202
-#define IGU_ADDR_ATTN_BITS_SET	0x0203
-#define IGU_ADDR_ATTN_BITS_CLR	0x0204
-#define IGU_ADDR_COALESCE_NOW	0x0205
-#define IGU_ADDR_SIMD_MASK		0x0206
-#define IGU_ADDR_SIMD_NOMASK	0x0207
-#define IGU_ADDR_MSI_CTL		0x0210
-#define IGU_ADDR_MSI_ADDR_LO	0x0211
-#define IGU_ADDR_MSI_ADDR_HI	0x0212
-#define IGU_ADDR_MSI_DATA		0x0213
-
-#define IGU_USE_REGISTER_ustorm_type_0_sb_cleanup  0
-#define IGU_USE_REGISTER_ustorm_type_1_sb_cleanup  1
-#define IGU_USE_REGISTER_cstorm_type_0_sb_cleanup  2
-#define IGU_USE_REGISTER_cstorm_type_1_sb_cleanup  3
-
-#define COMMAND_REG_INT_ACK	    0x0
-#define COMMAND_REG_PROD_UPD	    0x4
-#define COMMAND_REG_ATTN_BITS_UPD   0x8
-#define COMMAND_REG_ATTN_BITS_SET   0xc
-#define COMMAND_REG_ATTN_BITS_CLR   0x10
-#define COMMAND_REG_COALESCE_NOW    0x14
-#define COMMAND_REG_SIMD_MASK	    0x18
-#define COMMAND_REG_SIMD_NOMASK     0x1c
-
-
-#define IGU_MEM_BASE						0x0000
-
-#define IGU_MEM_MSIX_BASE					0x0000
-#define IGU_MEM_MSIX_UPPER					0x007f
-#define IGU_MEM_MSIX_RESERVED_UPPER			0x01ff
-
-#define IGU_MEM_PBA_MSIX_BASE				0x0200
-#define IGU_MEM_PBA_MSIX_UPPER				0x0200
-
-#define IGU_CMD_BACKWARD_COMP_PROD_UPD		0x0201
-#define IGU_MEM_PBA_MSIX_RESERVED_UPPER 	0x03ff
-
-#define IGU_CMD_INT_ACK_BASE				0x0400
-#define IGU_CMD_INT_ACK_UPPER\
-	(IGU_CMD_INT_ACK_BASE + MAX_SB_PER_PORT * NUM_OF_PORTS_PER_PATH - 1)
-#define IGU_CMD_INT_ACK_RESERVED_UPPER		0x04ff
-
-#define IGU_CMD_E2_PROD_UPD_BASE			0x0500
-#define IGU_CMD_E2_PROD_UPD_UPPER\
-	(IGU_CMD_E2_PROD_UPD_BASE + MAX_SB_PER_PORT * NUM_OF_PORTS_PER_PATH - 1)
-#define IGU_CMD_E2_PROD_UPD_RESERVED_UPPER	0x059f
-
-#define IGU_CMD_ATTN_BIT_UPD_UPPER			0x05a0
-#define IGU_CMD_ATTN_BIT_SET_UPPER			0x05a1
-#define IGU_CMD_ATTN_BIT_CLR_UPPER			0x05a2
-
-#define IGU_REG_SISR_MDPC_WMASK_UPPER		0x05a3
-#define IGU_REG_SISR_MDPC_WMASK_LSB_UPPER	0x05a4
-#define IGU_REG_SISR_MDPC_WMASK_MSB_UPPER	0x05a5
-#define IGU_REG_SISR_MDPC_WOMASK_UPPER		0x05a6
-
-#define IGU_REG_RESERVED_UPPER				0x05ff
-/* Fields of IGU PF CONFIGRATION REGISTER */
-#define IGU_PF_CONF_FUNC_EN	  (0x1<<0)  /* function enable	      */
-#define IGU_PF_CONF_MSI_MSIX_EN   (0x1<<1)  /* MSI/MSIX enable	      */
-#define IGU_PF_CONF_INT_LINE_EN   (0x1<<2)  /* INT enable	      */
-#define IGU_PF_CONF_ATTN_BIT_EN   (0x1<<3)  /* attention enable       */
-#define IGU_PF_CONF_SINGLE_ISR_EN (0x1<<4)  /* single ISR mode enable */
-#define IGU_PF_CONF_SIMD_MODE	  (0x1<<5)  /* simd all ones mode     */
-
-/* Fields of IGU VF CONFIGRATION REGISTER */
-#define IGU_VF_CONF_FUNC_EN	   (0x1<<0)  /* function enable        */
-#define IGU_VF_CONF_MSI_MSIX_EN    (0x1<<1)  /* MSI/MSIX enable        */
-#define IGU_VF_CONF_PARENT_MASK    (0x3<<2)  /* Parent PF	       */
-#define IGU_VF_CONF_PARENT_SHIFT   2	     /* Parent PF	       */
-#define IGU_VF_CONF_SINGLE_ISR_EN  (0x1<<4)  /* single ISR mode enable */
-
-
-#define IGU_BC_DSB_NUM_SEGS    5
-#define IGU_BC_NDSB_NUM_SEGS   2
-#define IGU_NORM_DSB_NUM_SEGS  2
-#define IGU_NORM_NDSB_NUM_SEGS 1
-#define IGU_BC_BASE_DSB_PROD   128
-#define IGU_NORM_BASE_DSB_PROD 136
-
-	/* FID (if VF - [6] = 0; [5:0] = VF number; if PF - [6] = 1; \
-	[5:2] = 0; [1:0] = PF number) */
-#define IGU_FID_ENCODE_IS_PF	    (0x1<<6)
-#define IGU_FID_ENCODE_IS_PF_SHIFT  6
-#define IGU_FID_VF_NUM_MASK	    (0x3f)
-#define IGU_FID_PF_NUM_MASK	    (0x7)
-
-#define IGU_REG_MAPPING_MEMORY_VALID		(1<<0)
-#define IGU_REG_MAPPING_MEMORY_VECTOR_MASK	(0x3F<<1)
-#define IGU_REG_MAPPING_MEMORY_VECTOR_SHIFT	1
-#define IGU_REG_MAPPING_MEMORY_FID_MASK	(0x7F<<7)
-#define IGU_REG_MAPPING_MEMORY_FID_SHIFT	7
-
-
-#define CDU_REGION_NUMBER_XCM_AG 2
-#define CDU_REGION_NUMBER_UCM_AG 4
-
-
-/**
- * String-to-compress [31:8] = CID (all 24 bits)
- * String-to-compress [7:4] = Region
- * String-to-compress [3:0] = Type
- */
-#define CDU_VALID_DATA(_cid, _region, _type)\
-	(((_cid) << 8) | (((_region)&0xf)<<4) | (((_type)&0xf)))
-#define CDU_CRC8(_cid, _region, _type)\
-	(calc_crc8(CDU_VALID_DATA(_cid, _region, _type), 0xff))
-#define CDU_RSRVD_VALUE_TYPE_A(_cid, _region, _type)\
-	(0x80 | ((CDU_CRC8(_cid, _region, _type)) & 0x7f))
-#define CDU_RSRVD_VALUE_TYPE_B(_crc, _type)\
-	(0x80 | ((_type)&0xf << 3) | ((CDU_CRC8(_cid, _region, _type)) & 0x7))
-#define CDU_RSRVD_INVALIDATE_CONTEXT_VALUE(_val) ((_val) & ~0x80)
-
-/******************************************************************************
- * Description:
- *	   Calculates crc 8 on a word value: polynomial 0-1-2-8
- *	   Code was translated from Verilog.
- * Return:
- *****************************************************************************/
-static inline u8 calc_crc8(u32 data, u8 crc)
-{
-	u8 D[32];
-	u8 NewCRC[8];
-	u8 C[8];
-	u8 crc_res;
-	u8 i;
-
-	/* split the data into 31 bits */
-	for (i = 0; i < 32; i++) {
-		D[i] = (u8)(data & 1);
-		data = data >> 1;
-	}
-
-	/* split the crc into 8 bits */
-	for (i = 0; i < 8; i++) {
-		C[i] = crc & 1;
-		crc = crc >> 1;
-	}
-
-	NewCRC[0] = D[31] ^ D[30] ^ D[28] ^ D[23] ^ D[21] ^ D[19] ^ D[18] ^
-		    D[16] ^ D[14] ^ D[12] ^ D[8] ^ D[7] ^ D[6] ^ D[0] ^ C[4] ^
-		    C[6] ^ C[7];
-	NewCRC[1] = D[30] ^ D[29] ^ D[28] ^ D[24] ^ D[23] ^ D[22] ^ D[21] ^
-		    D[20] ^ D[18] ^ D[17] ^ D[16] ^ D[15] ^ D[14] ^ D[13] ^
-		    D[12] ^ D[9] ^ D[6] ^ D[1] ^ D[0] ^ C[0] ^ C[4] ^ C[5] ^
-		    C[6];
-	NewCRC[2] = D[29] ^ D[28] ^ D[25] ^ D[24] ^ D[22] ^ D[17] ^ D[15] ^
-		    D[13] ^ D[12] ^ D[10] ^ D[8] ^ D[6] ^ D[2] ^ D[1] ^ D[0] ^
-		    C[0] ^ C[1] ^ C[4] ^ C[5];
-	NewCRC[3] = D[30] ^ D[29] ^ D[26] ^ D[25] ^ D[23] ^ D[18] ^ D[16] ^
-		    D[14] ^ D[13] ^ D[11] ^ D[9] ^ D[7] ^ D[3] ^ D[2] ^ D[1] ^
-		    C[1] ^ C[2] ^ C[5] ^ C[6];
-	NewCRC[4] = D[31] ^ D[30] ^ D[27] ^ D[26] ^ D[24] ^ D[19] ^ D[17] ^
-		    D[15] ^ D[14] ^ D[12] ^ D[10] ^ D[8] ^ D[4] ^ D[3] ^ D[2] ^
-		    C[0] ^ C[2] ^ C[3] ^ C[6] ^ C[7];
-	NewCRC[5] = D[31] ^ D[28] ^ D[27] ^ D[25] ^ D[20] ^ D[18] ^ D[16] ^
-		    D[15] ^ D[13] ^ D[11] ^ D[9] ^ D[5] ^ D[4] ^ D[3] ^ C[1] ^
-		    C[3] ^ C[4] ^ C[7];
-	NewCRC[6] = D[29] ^ D[28] ^ D[26] ^ D[21] ^ D[19] ^ D[17] ^ D[16] ^
-		    D[14] ^ D[12] ^ D[10] ^ D[6] ^ D[5] ^ D[4] ^ C[2] ^ C[4] ^
-		    C[5];
-	NewCRC[7] = D[30] ^ D[29] ^ D[27] ^ D[22] ^ D[20] ^ D[18] ^ D[17] ^
-		    D[15] ^ D[13] ^ D[11] ^ D[7] ^ D[6] ^ D[5] ^ C[3] ^ C[5] ^
-		    C[6];
-
-	crc_res = 0;
-	for (i = 0; i < 8; i++)
-		crc_res |= (NewCRC[i] << i);
-
-	return crc_res;
-}
-
-
-#endif /* BNX2X_REG_H */
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_sp.c linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_sp.c
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_sp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_sp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,5692 +0,0 @@
-/* bnx2x_sp.c: Broadcom Everest network driver.
- *
- * Copyright 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
- * under the terms of the GNU General Public License version 2, available
- * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
- *
- * Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a
- * license other than the GPL, without Broadcom's express prior written
- * consent.
- *
- * Maintained by: Eilon Greenstein <eilong@broadcom.com>
- * Written by: Vladislav Zolotarov
- *
- */
-#include <linux/module.h>
-#include <linux/crc32.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/crc32c.h>
-#include "bnx2x.h"
-#include "bnx2x_cmn.h"
-#include "bnx2x_sp.h"
-
-#define BNX2X_MAX_EMUL_MULTI		16
-
-/**** Exe Queue interfaces ****/
-
-/**
- * bnx2x_exe_queue_init - init the Exe Queue object
- *
- * @o:		poiter to the object
- * @exe_len:	length
- * @owner:	poiter to the owner
- * @validate:	validate function pointer
- * @optimize:	optimize function pointer
- * @exec:	execute function pointer
- * @get:	get function pointer
- */
-static inline void bnx2x_exe_queue_init(struct bnx2x *bp,
-					struct bnx2x_exe_queue_obj *o,
-					int exe_len,
-					union bnx2x_qable_obj *owner,
-					exe_q_validate validate,
-					exe_q_optimize optimize,
-					exe_q_execute exec,
-					exe_q_get get)
-{
-	memset(o, 0, sizeof(*o));
-
-	INIT_LIST_HEAD(&o->exe_queue);
-	INIT_LIST_HEAD(&o->pending_comp);
-
-	spin_lock_init(&o->lock);
-
-	o->exe_chunk_len = exe_len;
-	o->owner         = owner;
-
-	/* Owner specific callbacks */
-	o->validate      = validate;
-	o->optimize      = optimize;
-	o->execute       = exec;
-	o->get           = get;
-
-	DP(BNX2X_MSG_SP, "Setup the execution queue with the chunk "
-			 "length of %d\n", exe_len);
-}
-
-static inline void bnx2x_exe_queue_free_elem(struct bnx2x *bp,
-					     struct bnx2x_exeq_elem *elem)
-{
-	DP(BNX2X_MSG_SP, "Deleting an exe_queue element\n");
-	kfree(elem);
-}
-
-static inline int bnx2x_exe_queue_length(struct bnx2x_exe_queue_obj *o)
-{
-	struct bnx2x_exeq_elem *elem;
-	int cnt = 0;
-
-	spin_lock_bh(&o->lock);
-
-	list_for_each_entry(elem, &o->exe_queue, link)
-		cnt++;
-
-	spin_unlock_bh(&o->lock);
-
-	return cnt;
-}
-
-/**
- * bnx2x_exe_queue_add - add a new element to the execution queue
- *
- * @bp:		driver handle
- * @o:		queue
- * @cmd:	new command to add
- * @restore:	true - do not optimize the command
- *
- * If the element is optimized or is illegal, frees it.
- */
-static inline int bnx2x_exe_queue_add(struct bnx2x *bp,
-				      struct bnx2x_exe_queue_obj *o,
-				      struct bnx2x_exeq_elem *elem,
-				      bool restore)
-{
-	int rc;
-
-	spin_lock_bh(&o->lock);
-
-	if (!restore) {
-		/* Try to cancel this element queue */
-		rc = o->optimize(bp, o->owner, elem);
-		if (rc)
-			goto free_and_exit;
-
-		/* Check if this request is ok */
-		rc = o->validate(bp, o->owner, elem);
-		if (rc) {
-			BNX2X_ERR("Preamble failed: %d\n", rc);
-			goto free_and_exit;
-		}
-	}
-
-	/* If so, add it to the execution queue */
-	list_add_tail(&elem->link, &o->exe_queue);
-
-	spin_unlock_bh(&o->lock);
-
-	return 0;
-
-free_and_exit:
-	bnx2x_exe_queue_free_elem(bp, elem);
-
-	spin_unlock_bh(&o->lock);
-
-	return rc;
-
-}
-
-static inline void __bnx2x_exe_queue_reset_pending(
-	struct bnx2x *bp,
-	struct bnx2x_exe_queue_obj *o)
-{
-	struct bnx2x_exeq_elem *elem;
-
-	while (!list_empty(&o->pending_comp)) {
-		elem = list_first_entry(&o->pending_comp,
-					struct bnx2x_exeq_elem, link);
-
-		list_del(&elem->link);
-		bnx2x_exe_queue_free_elem(bp, elem);
-	}
-}
-
-static inline void bnx2x_exe_queue_reset_pending(struct bnx2x *bp,
-						 struct bnx2x_exe_queue_obj *o)
-{
-
-	spin_lock_bh(&o->lock);
-
-	__bnx2x_exe_queue_reset_pending(bp, o);
-
-	spin_unlock_bh(&o->lock);
-
-}
-
-/**
- * bnx2x_exe_queue_step - execute one execution chunk atomically
- *
- * @bp:			driver handle
- * @o:			queue
- * @ramrod_flags:	flags
- *
- * (Atomicy is ensured using the exe_queue->lock).
- */
-static inline int bnx2x_exe_queue_step(struct bnx2x *bp,
-				       struct bnx2x_exe_queue_obj *o,
-				       unsigned long *ramrod_flags)
-{
-	struct bnx2x_exeq_elem *elem, spacer;
-	int cur_len = 0, rc;
-
-	memset(&spacer, 0, sizeof(spacer));
-
-	spin_lock_bh(&o->lock);
-
-	/*
-	 * Next step should not be performed until the current is finished,
-	 * unless a DRV_CLEAR_ONLY bit is set. In this case we just want to
-	 * properly clear object internals without sending any command to the FW
-	 * which also implies there won't be any completion to clear the
-	 * 'pending' list.
-	 */
-	if (!list_empty(&o->pending_comp)) {
-		if (test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags)) {
-			DP(BNX2X_MSG_SP, "RAMROD_DRV_CLR_ONLY requested: "
-					 "resetting pending_comp\n");
-			__bnx2x_exe_queue_reset_pending(bp, o);
-		} else {
-			spin_unlock_bh(&o->lock);
-			return 1;
-		}
-	}
-
-	/*
-	 * Run through the pending commands list and create a next
-	 * execution chunk.
-	 */
-	while (!list_empty(&o->exe_queue)) {
-		elem = list_first_entry(&o->exe_queue, struct bnx2x_exeq_elem,
-					link);
-		WARN_ON(!elem->cmd_len);
-
-		if (cur_len + elem->cmd_len <= o->exe_chunk_len) {
-			cur_len += elem->cmd_len;
-			/*
-			 * Prevent from both lists being empty when moving an
-			 * element. This will allow the call of
-			 * bnx2x_exe_queue_empty() without locking.
-			 */
-			list_add_tail(&spacer.link, &o->pending_comp);
-			mb();
-			list_del(&elem->link);
-			list_add_tail(&elem->link, &o->pending_comp);
-			list_del(&spacer.link);
-		} else
-			break;
-	}
-
-	/* Sanity check */
-	if (!cur_len) {
-		spin_unlock_bh(&o->lock);
-		return 0;
-	}
-
-	rc = o->execute(bp, o->owner, &o->pending_comp, ramrod_flags);
-	if (rc < 0)
-		/*
-		 *  In case of an error return the commands back to the queue
-		 *  and reset the pending_comp.
-		 */
-		list_splice_init(&o->pending_comp, &o->exe_queue);
-	else if (!rc)
-		/*
-		 * If zero is returned, means there are no outstanding pending
-		 * completions and we may dismiss the pending list.
-		 */
-		__bnx2x_exe_queue_reset_pending(bp, o);
-
-	spin_unlock_bh(&o->lock);
-	return rc;
-}
-
-static inline bool bnx2x_exe_queue_empty(struct bnx2x_exe_queue_obj *o)
-{
-	bool empty = list_empty(&o->exe_queue);
-
-	/* Don't reorder!!! */
-	mb();
-
-	return empty && list_empty(&o->pending_comp);
-}
-
-static inline struct bnx2x_exeq_elem *bnx2x_exe_queue_alloc_elem(
-	struct bnx2x *bp)
-{
-	DP(BNX2X_MSG_SP, "Allocating a new exe_queue element\n");
-	return kzalloc(sizeof(struct bnx2x_exeq_elem), GFP_ATOMIC);
-}
-
-/************************ raw_obj functions ***********************************/
-static bool bnx2x_raw_check_pending(struct bnx2x_raw_obj *o)
-{
-	return !!test_bit(o->state, o->pstate);
-}
-
-static void bnx2x_raw_clear_pending(struct bnx2x_raw_obj *o)
-{
-	smp_mb__before_clear_bit();
-	clear_bit(o->state, o->pstate);
-	smp_mb__after_clear_bit();
-}
-
-static void bnx2x_raw_set_pending(struct bnx2x_raw_obj *o)
-{
-	smp_mb__before_clear_bit();
-	set_bit(o->state, o->pstate);
-	smp_mb__after_clear_bit();
-}
-
-/**
- * bnx2x_state_wait - wait until the given bit(state) is cleared
- *
- * @bp:		device handle
- * @state:	state which is to be cleared
- * @state_p:	state buffer
- *
- */
-static inline int bnx2x_state_wait(struct bnx2x *bp, int state,
-				   unsigned long *pstate)
-{
-	/* can take a while if any port is running */
-	int cnt = 5000;
-
-
-	if (CHIP_REV_IS_EMUL(bp))
-		cnt *= 20;
-
-	DP(BNX2X_MSG_SP, "waiting for state to become %d\n", state);
-
-	might_sleep();
-	while (cnt--) {
-		if (!test_bit(state, pstate)) {
-#ifdef BNX2X_STOP_ON_ERROR
-			DP(BNX2X_MSG_SP, "exit  (cnt %d)\n", 5000 - cnt);
-#endif
-			return 0;
-		}
-
-		usleep_range(1000, 1000);
-
-		if (bp->panic)
-			return -EIO;
-	}
-
-	/* timeout! */
-	BNX2X_ERR("timeout waiting for state %d\n", state);
-#ifdef BNX2X_STOP_ON_ERROR
-	bnx2x_panic();
-#endif
-
-	return -EBUSY;
-}
-
-static int bnx2x_raw_wait(struct bnx2x *bp, struct bnx2x_raw_obj *raw)
-{
-	return bnx2x_state_wait(bp, raw->state, raw->pstate);
-}
-
-/***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/
-/* credit handling callbacks */
-static bool bnx2x_get_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int *offset)
-{
-	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
-
-	WARN_ON(!mp);
-
-	return mp->get_entry(mp, offset);
-}
-
-static bool bnx2x_get_credit_mac(struct bnx2x_vlan_mac_obj *o)
-{
-	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
-
-	WARN_ON(!mp);
-
-	return mp->get(mp, 1);
-}
-
-static bool bnx2x_get_cam_offset_vlan(struct bnx2x_vlan_mac_obj *o, int *offset)
-{
-	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
-
-	WARN_ON(!vp);
-
-	return vp->get_entry(vp, offset);
-}
-
-static bool bnx2x_get_credit_vlan(struct bnx2x_vlan_mac_obj *o)
-{
-	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
-
-	WARN_ON(!vp);
-
-	return vp->get(vp, 1);
-}
-
-static bool bnx2x_get_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
-{
-	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
-	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
-
-	if (!mp->get(mp, 1))
-		return false;
-
-	if (!vp->get(vp, 1)) {
-		mp->put(mp, 1);
-		return false;
-	}
-
-	return true;
-}
-
-static bool bnx2x_put_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int offset)
-{
-	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
-
-	return mp->put_entry(mp, offset);
-}
-
-static bool bnx2x_put_credit_mac(struct bnx2x_vlan_mac_obj *o)
-{
-	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
-
-	return mp->put(mp, 1);
-}
-
-static bool bnx2x_put_cam_offset_vlan(struct bnx2x_vlan_mac_obj *o, int offset)
-{
-	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
-
-	return vp->put_entry(vp, offset);
-}
-
-static bool bnx2x_put_credit_vlan(struct bnx2x_vlan_mac_obj *o)
-{
-	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
-
-	return vp->put(vp, 1);
-}
-
-static bool bnx2x_put_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
-{
-	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
-	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
-
-	if (!mp->put(mp, 1))
-		return false;
-
-	if (!vp->put(vp, 1)) {
-		mp->get(mp, 1);
-		return false;
-	}
-
-	return true;
-}
-
-/* check_add() callbacks */
-static int bnx2x_check_mac_add(struct bnx2x_vlan_mac_obj *o,
-			       union bnx2x_classification_ramrod_data *data)
-{
-	struct bnx2x_vlan_mac_registry_elem *pos;
-
-	if (!is_valid_ether_addr(data->mac.mac))
-		return -EINVAL;
-
-	/* Check if a requested MAC already exists */
-	list_for_each_entry(pos, &o->head, link)
-		if (!memcmp(data->mac.mac, pos->u.mac.mac, ETH_ALEN))
-			return -EEXIST;
-
-	return 0;
-}
-
-static int bnx2x_check_vlan_add(struct bnx2x_vlan_mac_obj *o,
-				union bnx2x_classification_ramrod_data *data)
-{
-	struct bnx2x_vlan_mac_registry_elem *pos;
-
-	list_for_each_entry(pos, &o->head, link)
-		if (data->vlan.vlan == pos->u.vlan.vlan)
-			return -EEXIST;
-
-	return 0;
-}
-
-static int bnx2x_check_vlan_mac_add(struct bnx2x_vlan_mac_obj *o,
-				   union bnx2x_classification_ramrod_data *data)
-{
-	struct bnx2x_vlan_mac_registry_elem *pos;
-
-	list_for_each_entry(pos, &o->head, link)
-		if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
-		    (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
-			     ETH_ALEN)))
-			return -EEXIST;
-
-	return 0;
-}
-
-
-/* check_del() callbacks */
-static struct bnx2x_vlan_mac_registry_elem *
-	bnx2x_check_mac_del(struct bnx2x_vlan_mac_obj *o,
-			    union bnx2x_classification_ramrod_data *data)
-{
-	struct bnx2x_vlan_mac_registry_elem *pos;
-
-	list_for_each_entry(pos, &o->head, link)
-		if (!memcmp(data->mac.mac, pos->u.mac.mac, ETH_ALEN))
-			return pos;
-
-	return NULL;
-}
-
-static struct bnx2x_vlan_mac_registry_elem *
-	bnx2x_check_vlan_del(struct bnx2x_vlan_mac_obj *o,
-			     union bnx2x_classification_ramrod_data *data)
-{
-	struct bnx2x_vlan_mac_registry_elem *pos;
-
-	list_for_each_entry(pos, &o->head, link)
-		if (data->vlan.vlan == pos->u.vlan.vlan)
-			return pos;
-
-	return NULL;
-}
-
-static struct bnx2x_vlan_mac_registry_elem *
-	bnx2x_check_vlan_mac_del(struct bnx2x_vlan_mac_obj *o,
-				 union bnx2x_classification_ramrod_data *data)
-{
-	struct bnx2x_vlan_mac_registry_elem *pos;
-
-	list_for_each_entry(pos, &o->head, link)
-		if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
-		    (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
-			     ETH_ALEN)))
-			return pos;
-
-	return NULL;
-}
-
-/* check_move() callback */
-static bool bnx2x_check_move(struct bnx2x_vlan_mac_obj *src_o,
-			     struct bnx2x_vlan_mac_obj *dst_o,
-			     union bnx2x_classification_ramrod_data *data)
-{
-	struct bnx2x_vlan_mac_registry_elem *pos;
-	int rc;
-
-	/* Check if we can delete the requested configuration from the first
-	 * object.
-	 */
-	pos = src_o->check_del(src_o, data);
-
-	/*  check if configuration can be added */
-	rc = dst_o->check_add(dst_o, data);
-
-	/* If this classification can not be added (is already set)
-	 * or can't be deleted - return an error.
-	 */
-	if (rc || !pos)
-		return false;
-
-	return true;
-}
-
-static bool bnx2x_check_move_always_err(
-	struct bnx2x_vlan_mac_obj *src_o,
-	struct bnx2x_vlan_mac_obj *dst_o,
-	union bnx2x_classification_ramrod_data *data)
-{
-	return false;
-}
-
-
-static inline u8 bnx2x_vlan_mac_get_rx_tx_flag(struct bnx2x_vlan_mac_obj *o)
-{
-	struct bnx2x_raw_obj *raw = &o->raw;
-	u8 rx_tx_flag = 0;
-
-	if ((raw->obj_type == BNX2X_OBJ_TYPE_TX) ||
-	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
-		rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_TX_CMD;
-
-	if ((raw->obj_type == BNX2X_OBJ_TYPE_RX) ||
-	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
-		rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_RX_CMD;
-
-	return rx_tx_flag;
-}
-
-/* LLH CAM line allocations */
-enum {
-	LLH_CAM_ISCSI_ETH_LINE = 0,
-	LLH_CAM_ETH_LINE,
-	LLH_CAM_MAX_PF_LINE = NIG_REG_LLH1_FUNC_MEM_SIZE / 2
-};
-
-static inline void bnx2x_set_mac_in_nig(struct bnx2x *bp,
-				 bool add, unsigned char *dev_addr, int index)
-{
-	u32 wb_data[2];
-	u32 reg_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM :
-			 NIG_REG_LLH0_FUNC_MEM;
-
-	if (!IS_MF_SI(bp) || index > LLH_CAM_MAX_PF_LINE)
-		return;
-
-	DP(BNX2X_MSG_SP, "Going to %s LLH configuration at entry %d\n",
-			 (add ? "ADD" : "DELETE"), index);
-
-	if (add) {
-		/* LLH_FUNC_MEM is a u64 WB register */
-		reg_offset += 8*index;
-
-		wb_data[0] = ((dev_addr[2] << 24) | (dev_addr[3] << 16) |
-			      (dev_addr[4] <<  8) |  dev_addr[5]);
-		wb_data[1] = ((dev_addr[0] <<  8) |  dev_addr[1]);
-
-		REG_WR_DMAE(bp, reg_offset, wb_data, 2);
-	}
-
-	REG_WR(bp, (BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM_ENABLE :
-				  NIG_REG_LLH0_FUNC_MEM_ENABLE) + 4*index, add);
-}
-
-/**
- * bnx2x_vlan_mac_set_cmd_hdr_e2 - set a header in a single classify ramrod
- *
- * @bp:		device handle
- * @o:		queue for which we want to configure this rule
- * @add:	if true the command is an ADD command, DEL otherwise
- * @opcode:	CLASSIFY_RULE_OPCODE_XXX
- * @hdr:	pointer to a header to setup
- *
- */
-static inline void bnx2x_vlan_mac_set_cmd_hdr_e2(struct bnx2x *bp,
-	struct bnx2x_vlan_mac_obj *o, bool add, int opcode,
-	struct eth_classify_cmd_header *hdr)
-{
-	struct bnx2x_raw_obj *raw = &o->raw;
-
-	hdr->client_id = raw->cl_id;
-	hdr->func_id = raw->func_id;
-
-	/* Rx or/and Tx (internal switching) configuration ? */
-	hdr->cmd_general_data |=
-		bnx2x_vlan_mac_get_rx_tx_flag(o);
-
-	if (add)
-		hdr->cmd_general_data |= ETH_CLASSIFY_CMD_HEADER_IS_ADD;
-
-	hdr->cmd_general_data |=
-		(opcode << ETH_CLASSIFY_CMD_HEADER_OPCODE_SHIFT);
-}
-
-/**
- * bnx2x_vlan_mac_set_rdata_hdr_e2 - set the classify ramrod data header
- *
- * @cid:	connection id
- * @type:	BNX2X_FILTER_XXX_PENDING
- * @hdr:	poiter to header to setup
- * @rule_cnt:
- *
- * currently we always configure one rule and echo field to contain a CID and an
- * opcode type.
- */
-static inline void bnx2x_vlan_mac_set_rdata_hdr_e2(u32 cid, int type,
-				struct eth_classify_header *hdr, int rule_cnt)
-{
-	hdr->echo = (cid & BNX2X_SWCID_MASK) | (type << BNX2X_SWCID_SHIFT);
-	hdr->rule_cnt = (u8)rule_cnt;
-}
-
-
-/* hw_config() callbacks */
-static void bnx2x_set_one_mac_e2(struct bnx2x *bp,
-				 struct bnx2x_vlan_mac_obj *o,
-				 struct bnx2x_exeq_elem *elem, int rule_idx,
-				 int cam_offset)
-{
-	struct bnx2x_raw_obj *raw = &o->raw;
-	struct eth_classify_rules_ramrod_data *data =
-		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
-	int rule_cnt = rule_idx + 1, cmd = elem->cmd_data.vlan_mac.cmd;
-	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
-	bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
-	unsigned long *vlan_mac_flags = &elem->cmd_data.vlan_mac.vlan_mac_flags;
-	u8 *mac = elem->cmd_data.vlan_mac.u.mac.mac;
-
-	/*
-	 * Set LLH CAM entry: 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 8 per function MAC
-	 * entries in the LLH register. There is also
-	 * NIG_REG_P[01]_LLH_FUNC_MEM2 registers that complete the
-	 * total number of CAM entries to 16.
-	 *
-	 * Currently we won't configure NIG for MACs other than a primary ETH
-	 * MAC and iSCSI L2 MAC.
-	 *
-	 * If this MAC is moving from one Queue to another, no need to change
-	 * NIG configuration.
-	 */
-	if (cmd != BNX2X_VLAN_MAC_MOVE) {
-		if (test_bit(BNX2X_ISCSI_ETH_MAC, vlan_mac_flags))
-			bnx2x_set_mac_in_nig(bp, add, mac,
-					     LLH_CAM_ISCSI_ETH_LINE);
-		else if (test_bit(BNX2X_ETH_MAC, vlan_mac_flags))
-			bnx2x_set_mac_in_nig(bp, add, mac, LLH_CAM_ETH_LINE);
-	}
-
-	/* Reset the ramrod data buffer for the first rule */
-	if (rule_idx == 0)
-		memset(data, 0, sizeof(*data));
-
-	/* Setup a command header */
-	bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_MAC,
-				      &rule_entry->mac.header);
-
-	DP(BNX2X_MSG_SP, "About to %s MAC "BNX2X_MAC_FMT" for "
-			 "Queue %d\n", (add ? "add" : "delete"),
-			 BNX2X_MAC_PRN_LIST(mac), raw->cl_id);
-
-	/* Set a MAC itself */
-	bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
-			      &rule_entry->mac.mac_mid,
-			      &rule_entry->mac.mac_lsb, mac);
-
-	/* MOVE: Add a rule that will add this MAC to the target Queue */
-	if (cmd == BNX2X_VLAN_MAC_MOVE) {
-		rule_entry++;
-		rule_cnt++;
-
-		/* Setup ramrod data */
-		bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
-					elem->cmd_data.vlan_mac.target_obj,
-					      true, CLASSIFY_RULE_OPCODE_MAC,
-					      &rule_entry->mac.header);
-
-		/* Set a MAC itself */
-		bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
-				      &rule_entry->mac.mac_mid,
-				      &rule_entry->mac.mac_lsb, mac);
-	}
-
-	/* Set the ramrod data header */
-	/* TODO: take this to the higher level in order to prevent multiple
-		 writing */
-	bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
-					rule_cnt);
-}
-
-/**
- * bnx2x_vlan_mac_set_rdata_hdr_e1x - set a header in a single classify ramrod
- *
- * @bp:		device handle
- * @o:		queue
- * @type:
- * @cam_offset:	offset in cam memory
- * @hdr:	pointer to a header to setup
- *
- * E1/E1H
- */
-static inline void bnx2x_vlan_mac_set_rdata_hdr_e1x(struct bnx2x *bp,
-	struct bnx2x_vlan_mac_obj *o, int type, int cam_offset,
-	struct mac_configuration_hdr *hdr)
-{
-	struct bnx2x_raw_obj *r = &o->raw;
-
-	hdr->length = 1;
-	hdr->offset = (u8)cam_offset;
-	hdr->client_id = 0xff;
-	hdr->echo = ((r->cid & BNX2X_SWCID_MASK) | (type << BNX2X_SWCID_SHIFT));
-}
-
-static inline void bnx2x_vlan_mac_set_cfg_entry_e1x(struct bnx2x *bp,
-	struct bnx2x_vlan_mac_obj *o, bool add, int opcode, u8 *mac,
-	u16 vlan_id, struct mac_configuration_entry *cfg_entry)
-{
-	struct bnx2x_raw_obj *r = &o->raw;
-	u32 cl_bit_vec = (1 << r->cl_id);
-
-	cfg_entry->clients_bit_vector = cpu_to_le32(cl_bit_vec);
-	cfg_entry->pf_id = r->func_id;
-	cfg_entry->vlan_id = cpu_to_le16(vlan_id);
-
-	if (add) {
-		SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
-			 T_ETH_MAC_COMMAND_SET);
-		SET_FLAG(cfg_entry->flags,
-			 MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE, opcode);
-
-		/* Set a MAC in a ramrod data */
-		bnx2x_set_fw_mac_addr(&cfg_entry->msb_mac_addr,
-				      &cfg_entry->middle_mac_addr,
-				      &cfg_entry->lsb_mac_addr, mac);
-	} else
-		SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
-			 T_ETH_MAC_COMMAND_INVALIDATE);
-}
-
-static inline void bnx2x_vlan_mac_set_rdata_e1x(struct bnx2x *bp,
-	struct bnx2x_vlan_mac_obj *o, int type, int cam_offset, bool add,
-	u8 *mac, u16 vlan_id, int opcode, struct mac_configuration_cmd *config)
-{
-	struct mac_configuration_entry *cfg_entry = &config->config_table[0];
-	struct bnx2x_raw_obj *raw = &o->raw;
-
-	bnx2x_vlan_mac_set_rdata_hdr_e1x(bp, o, type, cam_offset,
-					 &config->hdr);
-	bnx2x_vlan_mac_set_cfg_entry_e1x(bp, o, add, opcode, mac, vlan_id,
-					 cfg_entry);
-
-	DP(BNX2X_MSG_SP, "%s MAC "BNX2X_MAC_FMT" CLID %d CAM offset %d\n",
-			 (add ? "setting" : "clearing"),
-			 BNX2X_MAC_PRN_LIST(mac), raw->cl_id, cam_offset);
-}
-
-/**
- * bnx2x_set_one_mac_e1x - fill a single MAC rule ramrod data
- *
- * @bp:		device handle
- * @o:		bnx2x_vlan_mac_obj
- * @elem:	bnx2x_exeq_elem
- * @rule_idx:	rule_idx
- * @cam_offset: cam_offset
- */
-static void bnx2x_set_one_mac_e1x(struct bnx2x *bp,
-				  struct bnx2x_vlan_mac_obj *o,
-				  struct bnx2x_exeq_elem *elem, int rule_idx,
-				  int cam_offset)
-{
-	struct bnx2x_raw_obj *raw = &o->raw;
-	struct mac_configuration_cmd *config =
-		(struct mac_configuration_cmd *)(raw->rdata);
-	/*
-	 * 57710 and 57711 do not support MOVE command,
-	 * so it's either ADD or DEL
-	 */
-	bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
-		true : false;
-
-	/* Reset the ramrod data buffer */
-	memset(config, 0, sizeof(*config));
-
-	bnx2x_vlan_mac_set_rdata_e1x(bp, o, BNX2X_FILTER_MAC_PENDING,
-				     cam_offset, add,
-				     elem->cmd_data.vlan_mac.u.mac.mac, 0,
-				     ETH_VLAN_FILTER_ANY_VLAN, config);
-}
-
-static void bnx2x_set_one_vlan_e2(struct bnx2x *bp,
-				  struct bnx2x_vlan_mac_obj *o,
-				  struct bnx2x_exeq_elem *elem, int rule_idx,
-				  int cam_offset)
-{
-	struct bnx2x_raw_obj *raw = &o->raw;
-	struct eth_classify_rules_ramrod_data *data =
-		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
-	int rule_cnt = rule_idx + 1;
-	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
-	int cmd = elem->cmd_data.vlan_mac.cmd;
-	bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
-	u16 vlan = elem->cmd_data.vlan_mac.u.vlan.vlan;
-
-	/* Reset the ramrod data buffer for the first rule */
-	if (rule_idx == 0)
-		memset(data, 0, sizeof(*data));
-
-	/* Set a rule header */
-	bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_VLAN,
-				      &rule_entry->vlan.header);
-
-	DP(BNX2X_MSG_SP, "About to %s VLAN %d\n", (add ? "add" : "delete"),
-			 vlan);
-
-	/* Set a VLAN itself */
-	rule_entry->vlan.vlan = cpu_to_le16(vlan);
-
-	/* MOVE: Add a rule that will add this MAC to the target Queue */
-	if (cmd == BNX2X_VLAN_MAC_MOVE) {
-		rule_entry++;
-		rule_cnt++;
-
-		/* Setup ramrod data */
-		bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
-					elem->cmd_data.vlan_mac.target_obj,
-					      true, CLASSIFY_RULE_OPCODE_VLAN,
-					      &rule_entry->vlan.header);
-
-		/* Set a VLAN itself */
-		rule_entry->vlan.vlan = cpu_to_le16(vlan);
-	}
-
-	/* Set the ramrod data header */
-	/* TODO: take this to the higher level in order to prevent multiple
-		 writing */
-	bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
-					rule_cnt);
-}
-
-static void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp,
-				      struct bnx2x_vlan_mac_obj *o,
-				      struct bnx2x_exeq_elem *elem,
-				      int rule_idx, int cam_offset)
-{
-	struct bnx2x_raw_obj *raw = &o->raw;
-	struct eth_classify_rules_ramrod_data *data =
-		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
-	int rule_cnt = rule_idx + 1;
-	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
-	int cmd = elem->cmd_data.vlan_mac.cmd;
-	bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
-	u16 vlan = elem->cmd_data.vlan_mac.u.vlan_mac.vlan;
-	u8 *mac = elem->cmd_data.vlan_mac.u.vlan_mac.mac;
-
-
-	/* Reset the ramrod data buffer for the first rule */
-	if (rule_idx == 0)
-		memset(data, 0, sizeof(*data));
-
-	/* Set a rule header */
-	bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_PAIR,
-				      &rule_entry->pair.header);
-
-	/* Set VLAN and MAC themselvs */
-	rule_entry->pair.vlan = cpu_to_le16(vlan);
-	bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
-			      &rule_entry->pair.mac_mid,
-			      &rule_entry->pair.mac_lsb, mac);
-
-	/* MOVE: Add a rule that will add this MAC to the target Queue */
-	if (cmd == BNX2X_VLAN_MAC_MOVE) {
-		rule_entry++;
-		rule_cnt++;
-
-		/* Setup ramrod data */
-		bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
-					elem->cmd_data.vlan_mac.target_obj,
-					      true, CLASSIFY_RULE_OPCODE_PAIR,
-					      &rule_entry->pair.header);
-
-		/* Set a VLAN itself */
-		rule_entry->pair.vlan = cpu_to_le16(vlan);
-		bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
-				      &rule_entry->pair.mac_mid,
-				      &rule_entry->pair.mac_lsb, mac);
-	}
-
-	/* Set the ramrod data header */
-	/* TODO: take this to the higher level in order to prevent multiple
-		 writing */
-	bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
-					rule_cnt);
-}
-
-/**
- * bnx2x_set_one_vlan_mac_e1h -
- *
- * @bp:		device handle
- * @o:		bnx2x_vlan_mac_obj
- * @elem:	bnx2x_exeq_elem
- * @rule_idx:	rule_idx
- * @cam_offset:	cam_offset
- */
-static void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp,
-				       struct bnx2x_vlan_mac_obj *o,
-				       struct bnx2x_exeq_elem *elem,
-				       int rule_idx, int cam_offset)
-{
-	struct bnx2x_raw_obj *raw = &o->raw;
-	struct mac_configuration_cmd *config =
-		(struct mac_configuration_cmd *)(raw->rdata);
-	/*
-	 * 57710 and 57711 do not support MOVE command,
-	 * so it's either ADD or DEL
-	 */
-	bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
-		true : false;
-
-	/* Reset the ramrod data buffer */
-	memset(config, 0, sizeof(*config));
-
-	bnx2x_vlan_mac_set_rdata_e1x(bp, o, BNX2X_FILTER_VLAN_MAC_PENDING,
-				     cam_offset, add,
-				     elem->cmd_data.vlan_mac.u.vlan_mac.mac,
-				     elem->cmd_data.vlan_mac.u.vlan_mac.vlan,
-				     ETH_VLAN_FILTER_CLASSIFY, config);
-}
-
-#define list_next_entry(pos, member) \
-	list_entry((pos)->member.next, typeof(*(pos)), member)
-
-/**
- * bnx2x_vlan_mac_restore - reconfigure next MAC/VLAN/VLAN-MAC element
- *
- * @bp:		device handle
- * @p:		command parameters
- * @ppos:	pointer to the cooky
- *
- * reconfigure next MAC/VLAN/VLAN-MAC element from the
- * previously configured elements list.
- *
- * from command parameters only RAMROD_COMP_WAIT bit in ramrod_flags is	taken
- * into an account
- *
- * pointer to the cooky  - that should be given back in the next call to make
- * function handle the next element. If *ppos is set to NULL it will restart the
- * iterator. If returned *ppos == NULL this means that the last element has been
- * handled.
- *
- */
-static int bnx2x_vlan_mac_restore(struct bnx2x *bp,
-			   struct bnx2x_vlan_mac_ramrod_params *p,
-			   struct bnx2x_vlan_mac_registry_elem **ppos)
-{
-	struct bnx2x_vlan_mac_registry_elem *pos;
-	struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
-
-	/* If list is empty - there is nothing to do here */
-	if (list_empty(&o->head)) {
-		*ppos = NULL;
-		return 0;
-	}
-
-	/* make a step... */
-	if (*ppos == NULL)
-		*ppos = list_first_entry(&o->head,
-					 struct bnx2x_vlan_mac_registry_elem,
-					 link);
-	else
-		*ppos = list_next_entry(*ppos, link);
-
-	pos = *ppos;
-
-	/* If it's the last step - return NULL */
-	if (list_is_last(&pos->link, &o->head))
-		*ppos = NULL;
-
-	/* Prepare a 'user_req' */
-	memcpy(&p->user_req.u, &pos->u, sizeof(pos->u));
-
-	/* Set the command */
-	p->user_req.cmd = BNX2X_VLAN_MAC_ADD;
-
-	/* Set vlan_mac_flags */
-	p->user_req.vlan_mac_flags = pos->vlan_mac_flags;
-
-	/* Set a restore bit */
-	__set_bit(RAMROD_RESTORE, &p->ramrod_flags);
-
-	return bnx2x_config_vlan_mac(bp, p);
-}
-
-/*
- * bnx2x_exeq_get_mac/bnx2x_exeq_get_vlan/bnx2x_exeq_get_vlan_mac return a
- * pointer to an element with a specific criteria and NULL if such an element
- * hasn't been found.
- */
-static struct bnx2x_exeq_elem *bnx2x_exeq_get_mac(
-	struct bnx2x_exe_queue_obj *o,
-	struct bnx2x_exeq_elem *elem)
-{
-	struct bnx2x_exeq_elem *pos;
-	struct bnx2x_mac_ramrod_data *data = &elem->cmd_data.vlan_mac.u.mac;
-
-	/* Check pending for execution commands */
-	list_for_each_entry(pos, &o->exe_queue, link)
-		if (!memcmp(&pos->cmd_data.vlan_mac.u.mac, data,
-			      sizeof(*data)) &&
-		    (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
-			return pos;
-
-	return NULL;
-}
-
-static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan(
-	struct bnx2x_exe_queue_obj *o,
-	struct bnx2x_exeq_elem *elem)
-{
-	struct bnx2x_exeq_elem *pos;
-	struct bnx2x_vlan_ramrod_data *data = &elem->cmd_data.vlan_mac.u.vlan;
-
-	/* Check pending for execution commands */
-	list_for_each_entry(pos, &o->exe_queue, link)
-		if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan, data,
-			      sizeof(*data)) &&
-		    (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
-			return pos;
-
-	return NULL;
-}
-
-static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan_mac(
-	struct bnx2x_exe_queue_obj *o,
-	struct bnx2x_exeq_elem *elem)
-{
-	struct bnx2x_exeq_elem *pos;
-	struct bnx2x_vlan_mac_ramrod_data *data =
-		&elem->cmd_data.vlan_mac.u.vlan_mac;
-
-	/* Check pending for execution commands */
-	list_for_each_entry(pos, &o->exe_queue, link)
-		if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan_mac, data,
-			      sizeof(*data)) &&
-		    (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
-			return pos;
-
-	return NULL;
-}
-
-/**
- * bnx2x_validate_vlan_mac_add - check if an ADD command can be executed
- *
- * @bp:		device handle
- * @qo:		bnx2x_qable_obj
- * @elem:	bnx2x_exeq_elem
- *
- * Checks that the requested configuration can be added. If yes and if
- * requested, consume CAM credit.
- *
- * The 'validate' is run after the 'optimize'.
- *
- */
-static inline int bnx2x_validate_vlan_mac_add(struct bnx2x *bp,
-					      union bnx2x_qable_obj *qo,
-					      struct bnx2x_exeq_elem *elem)
-{
-	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
-	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
-	int rc;
-
-	/* Check the registry */
-	rc = o->check_add(o, &elem->cmd_data.vlan_mac.u);
-	if (rc) {
-		DP(BNX2X_MSG_SP, "ADD command is not allowed considering "
-				 "current registry state\n");
-		return rc;
-	}
-
-	/*
-	 * Check if there is a pending ADD command for this
-	 * MAC/VLAN/VLAN-MAC. Return an error if there is.
-	 */
-	if (exeq->get(exeq, elem)) {
-		DP(BNX2X_MSG_SP, "There is a pending ADD command already\n");
-		return -EEXIST;
-	}
-
-	/*
-	 * TODO: Check the pending MOVE from other objects where this
-	 * object is a destination object.
-	 */
-
-	/* Consume the credit if not requested not to */
-	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
-		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
-	    o->get_credit(o)))
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- * bnx2x_validate_vlan_mac_del - check if the DEL command can be executed
- *
- * @bp:		device handle
- * @qo:		quable object to check
- * @elem:	element that needs to be deleted
- *
- * Checks that the requested configuration can be deleted. If yes and if
- * requested, returns a CAM credit.
- *
- * The 'validate' is run after the 'optimize'.
- */
-static inline int bnx2x_validate_vlan_mac_del(struct bnx2x *bp,
-					      union bnx2x_qable_obj *qo,
-					      struct bnx2x_exeq_elem *elem)
-{
-	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
-	struct bnx2x_vlan_mac_registry_elem *pos;
-	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
-	struct bnx2x_exeq_elem query_elem;
-
-	/* If this classification can not be deleted (doesn't exist)
-	 * - return a BNX2X_EXIST.
-	 */
-	pos = o->check_del(o, &elem->cmd_data.vlan_mac.u);
-	if (!pos) {
-		DP(BNX2X_MSG_SP, "DEL command is not allowed considering "
-				 "current registry state\n");
-		return -EEXIST;
-	}
-
-	/*
-	 * Check if there are pending DEL or MOVE commands for this
-	 * MAC/VLAN/VLAN-MAC. Return an error if so.
-	 */
-	memcpy(&query_elem, elem, sizeof(query_elem));
-
-	/* Check for MOVE commands */
-	query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_MOVE;
-	if (exeq->get(exeq, &query_elem)) {
-		BNX2X_ERR("There is a pending MOVE command already\n");
-		return -EINVAL;
-	}
-
-	/* Check for DEL commands */
-	if (exeq->get(exeq, elem)) {
-		DP(BNX2X_MSG_SP, "There is a pending DEL command already\n");
-		return -EEXIST;
-	}
-
-	/* Return the credit to the credit pool if not requested not to */
-	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
-		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
-	    o->put_credit(o))) {
-		BNX2X_ERR("Failed to return a credit\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/**
- * bnx2x_validate_vlan_mac_move - check if the MOVE command can be executed
- *
- * @bp:		device handle
- * @qo:		quable object to check (source)
- * @elem:	element that needs to be moved
- *
- * Checks that the requested configuration can be moved. If yes and if
- * requested, returns a CAM credit.
- *
- * The 'validate' is run after the 'optimize'.
- */
-static inline int bnx2x_validate_vlan_mac_move(struct bnx2x *bp,
-					       union bnx2x_qable_obj *qo,
-					       struct bnx2x_exeq_elem *elem)
-{
-	struct bnx2x_vlan_mac_obj *src_o = &qo->vlan_mac;
-	struct bnx2x_vlan_mac_obj *dest_o = elem->cmd_data.vlan_mac.target_obj;
-	struct bnx2x_exeq_elem query_elem;
-	struct bnx2x_exe_queue_obj *src_exeq = &src_o->exe_queue;
-	struct bnx2x_exe_queue_obj *dest_exeq = &dest_o->exe_queue;
-
-	/*
-	 * Check if we can perform this operation based on the current registry
-	 * state.
-	 */
-	if (!src_o->check_move(src_o, dest_o, &elem->cmd_data.vlan_mac.u)) {
-		DP(BNX2X_MSG_SP, "MOVE command is not allowed considering "
-				 "current registry state\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * Check if there is an already pending DEL or MOVE command for the
-	 * source object or ADD command for a destination object. Return an
-	 * error if so.
-	 */
-	memcpy(&query_elem, elem, sizeof(query_elem));
-
-	/* Check DEL on source */
-	query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_DEL;
-	if (src_exeq->get(src_exeq, &query_elem)) {
-		BNX2X_ERR("There is a pending DEL command on the source "
-			  "queue already\n");
-		return -EINVAL;
-	}
-
-	/* Check MOVE on source */
-	if (src_exeq->get(src_exeq, elem)) {
-		DP(BNX2X_MSG_SP, "There is a pending MOVE command already\n");
-		return -EEXIST;
-	}
-
-	/* Check ADD on destination */
-	query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_ADD;
-	if (dest_exeq->get(dest_exeq, &query_elem)) {
-		BNX2X_ERR("There is a pending ADD command on the "
-			  "destination queue already\n");
-		return -EINVAL;
-	}
-
-	/* Consume the credit if not requested not to */
-	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
-		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
-	    dest_o->get_credit(dest_o)))
-		return -EINVAL;
-
-	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
-		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
-	    src_o->put_credit(src_o))) {
-		/* return the credit taken from dest... */
-		dest_o->put_credit(dest_o);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int bnx2x_validate_vlan_mac(struct bnx2x *bp,
-				   union bnx2x_qable_obj *qo,
-				   struct bnx2x_exeq_elem *elem)
-{
-	switch (elem->cmd_data.vlan_mac.cmd) {
-	case BNX2X_VLAN_MAC_ADD:
-		return bnx2x_validate_vlan_mac_add(bp, qo, elem);
-	case BNX2X_VLAN_MAC_DEL:
-		return bnx2x_validate_vlan_mac_del(bp, qo, elem);
-	case BNX2X_VLAN_MAC_MOVE:
-		return bnx2x_validate_vlan_mac_move(bp, qo, elem);
-	default:
-		return -EINVAL;
-	}
-}
-
-/**
- * bnx2x_wait_vlan_mac - passivly wait for 5 seconds until all work completes.
- *
- * @bp:		device handle
- * @o:		bnx2x_vlan_mac_obj
- *
- */
-static int bnx2x_wait_vlan_mac(struct bnx2x *bp,
-			       struct bnx2x_vlan_mac_obj *o)
-{
-	int cnt = 5000, rc;
-	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
-	struct bnx2x_raw_obj *raw = &o->raw;
-
-	while (cnt--) {
-		/* Wait for the current command to complete */
-		rc = raw->wait_comp(bp, raw);
-		if (rc)
-			return rc;
-
-		/* Wait until there are no pending commands */
-		if (!bnx2x_exe_queue_empty(exeq))
-			usleep_range(1000, 1000);
-		else
-			return 0;
-	}
-
-	return -EBUSY;
-}
-
-/**
- * bnx2x_complete_vlan_mac - complete one VLAN-MAC ramrod
- *
- * @bp:		device handle
- * @o:		bnx2x_vlan_mac_obj
- * @cqe:
- * @cont:	if true schedule next execution chunk
- *
- */
-static int bnx2x_complete_vlan_mac(struct bnx2x *bp,
-				   struct bnx2x_vlan_mac_obj *o,
-				   union event_ring_elem *cqe,
-				   unsigned long *ramrod_flags)
-{
-	struct bnx2x_raw_obj *r = &o->raw;
-	int rc;
-
-	/* Reset pending list */
-	bnx2x_exe_queue_reset_pending(bp, &o->exe_queue);
-
-	/* Clear pending */
-	r->clear_pending(r);
-
-	/* If ramrod failed this is most likely a SW bug */
-	if (cqe->message.error)
-		return -EINVAL;
-
-	/* Run the next bulk of pending commands if requeted */
-	if (test_bit(RAMROD_CONT, ramrod_flags)) {
-		rc = bnx2x_exe_queue_step(bp, &o->exe_queue, ramrod_flags);
-		if (rc < 0)
-			return rc;
-	}
-
-	/* If there is more work to do return PENDING */
-	if (!bnx2x_exe_queue_empty(&o->exe_queue))
-		return 1;
-
-	return 0;
-}
-
-/**
- * bnx2x_optimize_vlan_mac - optimize ADD and DEL commands.
- *
- * @bp:		device handle
- * @o:		bnx2x_qable_obj
- * @elem:	bnx2x_exeq_elem
- */
-static int bnx2x_optimize_vlan_mac(struct bnx2x *bp,
-				   union bnx2x_qable_obj *qo,
-				   struct bnx2x_exeq_elem *elem)
-{
-	struct bnx2x_exeq_elem query, *pos;
-	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
-	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
-
-	memcpy(&query, elem, sizeof(query));
-
-	switch (elem->cmd_data.vlan_mac.cmd) {
-	case BNX2X_VLAN_MAC_ADD:
-		query.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_DEL;
-		break;
-	case BNX2X_VLAN_MAC_DEL:
-		query.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_ADD;
-		break;
-	default:
-		/* Don't handle anything other than ADD or DEL */
-		return 0;
-	}
-
-	/* If we found the appropriate element - delete it */
-	pos = exeq->get(exeq, &query);
-	if (pos) {
-
-		/* Return the credit of the optimized command */
-		if (!test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
-			      &pos->cmd_data.vlan_mac.vlan_mac_flags)) {
-			if ((query.cmd_data.vlan_mac.cmd ==
-			     BNX2X_VLAN_MAC_ADD) && !o->put_credit(o)) {
-				BNX2X_ERR("Failed to return the credit for the "
-					  "optimized ADD command\n");
-				return -EINVAL;
-			} else if (!o->get_credit(o)) { /* VLAN_MAC_DEL */
-				BNX2X_ERR("Failed to recover the credit from "
-					  "the optimized DEL command\n");
-				return -EINVAL;
-			}
-		}
-
-		DP(BNX2X_MSG_SP, "Optimizing %s command\n",
-			   (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
-			   "ADD" : "DEL");
-
-		list_del(&pos->link);
-		bnx2x_exe_queue_free_elem(bp, pos);
-		return 1;
-	}
-
-	return 0;
-}
-
-/**
- * bnx2x_vlan_mac_get_registry_elem - prepare a registry element
- *
- * @bp:	  device handle
- * @o:
- * @elem:
- * @restore:
- * @re:
- *
- * prepare a registry element according to the current command request.
- */
-static inline int bnx2x_vlan_mac_get_registry_elem(
-	struct bnx2x *bp,
-	struct bnx2x_vlan_mac_obj *o,
-	struct bnx2x_exeq_elem *elem,
-	bool restore,
-	struct bnx2x_vlan_mac_registry_elem **re)
-{
-	int cmd = elem->cmd_data.vlan_mac.cmd;
-	struct bnx2x_vlan_mac_registry_elem *reg_elem;
-
-	/* Allocate a new registry element if needed. */
-	if (!restore &&
-	    ((cmd == BNX2X_VLAN_MAC_ADD) || (cmd == BNX2X_VLAN_MAC_MOVE))) {
-		reg_elem = kzalloc(sizeof(*reg_elem), GFP_ATOMIC);
-		if (!reg_elem)
-			return -ENOMEM;
-
-		/* Get a new CAM offset */
-		if (!o->get_cam_offset(o, &reg_elem->cam_offset)) {
-			/*
-			 * This shell never happen, because we have checked the
-			 * CAM availiability in the 'validate'.
-			 */
-			WARN_ON(1);
-			kfree(reg_elem);
-			return -EINVAL;
-		}
-
-		DP(BNX2X_MSG_SP, "Got cam offset %d\n", reg_elem->cam_offset);
-
-		/* Set a VLAN-MAC data */
-		memcpy(&reg_elem->u, &elem->cmd_data.vlan_mac.u,
-			  sizeof(reg_elem->u));
-
-		/* Copy the flags (needed for DEL and RESTORE flows) */
-		reg_elem->vlan_mac_flags =
-			elem->cmd_data.vlan_mac.vlan_mac_flags;
-	} else /* DEL, RESTORE */
-		reg_elem = o->check_del(o, &elem->cmd_data.vlan_mac.u);
-
-	*re = reg_elem;
-	return 0;
-}
-
-/**
- * bnx2x_execute_vlan_mac - execute vlan mac command
- *
- * @bp:			device handle
- * @qo:
- * @exe_chunk:
- * @ramrod_flags:
- *
- * go and send a ramrod!
- */
-static int bnx2x_execute_vlan_mac(struct bnx2x *bp,
-				  union bnx2x_qable_obj *qo,
-				  struct list_head *exe_chunk,
-				  unsigned long *ramrod_flags)
-{
-	struct bnx2x_exeq_elem *elem;
-	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac, *cam_obj;
-	struct bnx2x_raw_obj *r = &o->raw;
-	int rc, idx = 0;
-	bool restore = test_bit(RAMROD_RESTORE, ramrod_flags);
-	bool drv_only = test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags);
-	struct bnx2x_vlan_mac_registry_elem *reg_elem;
-	int cmd;
-
-	/*
-	 * If DRIVER_ONLY execution is requested, cleanup a registry
-	 * and exit. Otherwise send a ramrod to FW.
-	 */
-	if (!drv_only) {
-		WARN_ON(r->check_pending(r));
-
-		/* Set pending */
-		r->set_pending(r);
-
-		/* Fill tha ramrod data */
-		list_for_each_entry(elem, exe_chunk, link) {
-			cmd = elem->cmd_data.vlan_mac.cmd;
-			/*
-			 * We will add to the target object in MOVE command, so
-			 * change the object for a CAM search.
-			 */
-			if (cmd == BNX2X_VLAN_MAC_MOVE)
-				cam_obj = elem->cmd_data.vlan_mac.target_obj;
-			else
-				cam_obj = o;
-
-			rc = bnx2x_vlan_mac_get_registry_elem(bp, cam_obj,
-							      elem, restore,
-							      &reg_elem);
-			if (rc)
-				goto error_exit;
-
-			WARN_ON(!reg_elem);
-
-			/* Push a new entry into the registry */
-			if (!restore &&
-			    ((cmd == BNX2X_VLAN_MAC_ADD) ||
-			    (cmd == BNX2X_VLAN_MAC_MOVE)))
-				list_add(&reg_elem->link, &cam_obj->head);
-
-			/* Configure a single command in a ramrod data buffer */
-			o->set_one_rule(bp, o, elem, idx,
-					reg_elem->cam_offset);
-
-			/* MOVE command consumes 2 entries in the ramrod data */
-			if (cmd == BNX2X_VLAN_MAC_MOVE)
-				idx += 2;
-			else
-				idx++;
-		}
-
-		/*
-		 *  No need for an explicit memory barrier here as long we would
-		 *  need to ensure the ordering of writing to the SPQ element
-		 *  and updating of the SPQ producer which involves a memory
-		 *  read and we will have to put a full memory barrier there
-		 *  (inside bnx2x_sp_post()).
-		 */
-
-		rc = bnx2x_sp_post(bp, o->ramrod_cmd, r->cid,
-				   U64_HI(r->rdata_mapping),
-				   U64_LO(r->rdata_mapping),
-				   ETH_CONNECTION_TYPE);
-		if (rc)
-			goto error_exit;
-	}
-
-	/* Now, when we are done with the ramrod - clean up the registry */
-	list_for_each_entry(elem, exe_chunk, link) {
-		cmd = elem->cmd_data.vlan_mac.cmd;
-		if ((cmd == BNX2X_VLAN_MAC_DEL) ||
-		    (cmd == BNX2X_VLAN_MAC_MOVE)) {
-			reg_elem = o->check_del(o, &elem->cmd_data.vlan_mac.u);
-
-			WARN_ON(!reg_elem);
-
-			o->put_cam_offset(o, reg_elem->cam_offset);
-			list_del(&reg_elem->link);
-			kfree(reg_elem);
-		}
-	}
-
-	if (!drv_only)
-		return 1;
-	else
-		return 0;
-
-error_exit:
-	r->clear_pending(r);
-
-	/* Cleanup a registry in case of a failure */
-	list_for_each_entry(elem, exe_chunk, link) {
-		cmd = elem->cmd_data.vlan_mac.cmd;
-
-		if (cmd == BNX2X_VLAN_MAC_MOVE)
-			cam_obj = elem->cmd_data.vlan_mac.target_obj;
-		else
-			cam_obj = o;
-
-		/* Delete all newly added above entries */
-		if (!restore &&
-		    ((cmd == BNX2X_VLAN_MAC_ADD) ||
-		    (cmd == BNX2X_VLAN_MAC_MOVE))) {
-			reg_elem = o->check_del(cam_obj,
-						&elem->cmd_data.vlan_mac.u);
-			if (reg_elem) {
-				list_del(&reg_elem->link);
-				kfree(reg_elem);
-			}
-		}
-	}
-
-	return rc;
-}
-
-static inline int bnx2x_vlan_mac_push_new_cmd(
-	struct bnx2x *bp,
-	struct bnx2x_vlan_mac_ramrod_params *p)
-{
-	struct bnx2x_exeq_elem *elem;
-	struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
-	bool restore = test_bit(RAMROD_RESTORE, &p->ramrod_flags);
-
-	/* Allocate the execution queue element */
-	elem = bnx2x_exe_queue_alloc_elem(bp);
-	if (!elem)
-		return -ENOMEM;
-
-	/* Set the command 'length' */
-	switch (p->user_req.cmd) {
-	case BNX2X_VLAN_MAC_MOVE:
-		elem->cmd_len = 2;
-		break;
-	default:
-		elem->cmd_len = 1;
-	}
-
-	/* Fill the object specific info */
-	memcpy(&elem->cmd_data.vlan_mac, &p->user_req, sizeof(p->user_req));
-
-	/* Try to add a new command to the pending list */
-	return bnx2x_exe_queue_add(bp, &o->exe_queue, elem, restore);
-}
-
-/**
- * bnx2x_config_vlan_mac - configure VLAN/MAC/VLAN_MAC filtering rules.
- *
- * @bp:	  device handle
- * @p:
- *
- */
-int bnx2x_config_vlan_mac(
-	struct bnx2x *bp,
-	struct bnx2x_vlan_mac_ramrod_params *p)
-{
-	int rc = 0;
-	struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
-	unsigned long *ramrod_flags = &p->ramrod_flags;
-	bool cont = test_bit(RAMROD_CONT, ramrod_flags);
-	struct bnx2x_raw_obj *raw = &o->raw;
-
-	/*
-	 * Add new elements to the execution list for commands that require it.
-	 */
-	if (!cont) {
-		rc = bnx2x_vlan_mac_push_new_cmd(bp, p);
-		if (rc)
-			return rc;
-	}
-
-	/*
-	 * If nothing will be executed further in this iteration we want to
-	 * return PENDING if there are pending commands
-	 */
-	if (!bnx2x_exe_queue_empty(&o->exe_queue))
-		rc = 1;
-
-	if (test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags))  {
-		DP(BNX2X_MSG_SP, "RAMROD_DRV_CLR_ONLY requested: "
-				 "clearing a pending bit.\n");
-		raw->clear_pending(raw);
-	}
-
-	/* Execute commands if required */
-	if (cont || test_bit(RAMROD_EXEC, ramrod_flags) ||
-	    test_bit(RAMROD_COMP_WAIT, ramrod_flags)) {
-		rc = bnx2x_exe_queue_step(bp, &o->exe_queue, ramrod_flags);
-		if (rc < 0)
-			return rc;
-	}
-
-	/*
-	 * RAMROD_COMP_WAIT is a superset of RAMROD_EXEC. If it was set
-	 * then user want to wait until the last command is done.
-	 */
-	if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
-		/*
-		 * Wait maximum for the current exe_queue length iterations plus
-		 * one (for the current pending command).
-		 */
-		int max_iterations = bnx2x_exe_queue_length(&o->exe_queue) + 1;
-
-		while (!bnx2x_exe_queue_empty(&o->exe_queue) &&
-		       max_iterations--) {
-
-			/* Wait for the current command to complete */
-			rc = raw->wait_comp(bp, raw);
-			if (rc)
-				return rc;
-
-			/* Make a next step */
-			rc = bnx2x_exe_queue_step(bp, &o->exe_queue,
-						  ramrod_flags);
-			if (rc < 0)
-				return rc;
-		}
-
-		return 0;
-	}
-
-	return rc;
-}
-
-
-
-/**
- * bnx2x_vlan_mac_del_all - delete elements with given vlan_mac_flags spec
- *
- * @bp:			device handle
- * @o:
- * @vlan_mac_flags:
- * @ramrod_flags:	execution flags to be used for this deletion
- *
- * if the last operation has completed successfully and there are no
- * moreelements left, positive value if the last operation has completed
- * successfully and there are more previously configured elements, negative
- * value is current operation has failed.
- */
-static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
-				  struct bnx2x_vlan_mac_obj *o,
-				  unsigned long *vlan_mac_flags,
-				  unsigned long *ramrod_flags)
-{
-	struct bnx2x_vlan_mac_registry_elem *pos = NULL;
-	int rc = 0;
-	struct bnx2x_vlan_mac_ramrod_params p;
-	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
-	struct bnx2x_exeq_elem *exeq_pos, *exeq_pos_n;
-
-	/* Clear pending commands first */
-
-	spin_lock_bh(&exeq->lock);
-
-	list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) {
-		if (exeq_pos->cmd_data.vlan_mac.vlan_mac_flags ==
-		    *vlan_mac_flags)
-			list_del(&exeq_pos->link);
-	}
-
-	spin_unlock_bh(&exeq->lock);
-
-	/* Prepare a command request */
-	memset(&p, 0, sizeof(p));
-	p.vlan_mac_obj = o;
-	p.ramrod_flags = *ramrod_flags;
-	p.user_req.cmd = BNX2X_VLAN_MAC_DEL;
-
-	/*
-	 * Add all but the last VLAN-MAC to the execution queue without actually
-	 * execution anything.
-	 */
-	__clear_bit(RAMROD_COMP_WAIT, &p.ramrod_flags);
-	__clear_bit(RAMROD_EXEC, &p.ramrod_flags);
-	__clear_bit(RAMROD_CONT, &p.ramrod_flags);
-
-	list_for_each_entry(pos, &o->head, link) {
-		if (pos->vlan_mac_flags == *vlan_mac_flags) {
-			p.user_req.vlan_mac_flags = pos->vlan_mac_flags;
-			memcpy(&p.user_req.u, &pos->u, sizeof(pos->u));
-			rc = bnx2x_config_vlan_mac(bp, &p);
-			if (rc < 0) {
-				BNX2X_ERR("Failed to add a new DEL command\n");
-				return rc;
-			}
-		}
-	}
-
-	p.ramrod_flags = *ramrod_flags;
-	__set_bit(RAMROD_CONT, &p.ramrod_flags);
-
-	return bnx2x_config_vlan_mac(bp, &p);
-}
-
-static inline void bnx2x_init_raw_obj(struct bnx2x_raw_obj *raw, u8 cl_id,
-	u32 cid, u8 func_id, void *rdata, dma_addr_t rdata_mapping, int state,
-	unsigned long *pstate, bnx2x_obj_type type)
-{
-	raw->func_id = func_id;
-	raw->cid = cid;
-	raw->cl_id = cl_id;
-	raw->rdata = rdata;
-	raw->rdata_mapping = rdata_mapping;
-	raw->state = state;
-	raw->pstate = pstate;
-	raw->obj_type = type;
-	raw->check_pending = bnx2x_raw_check_pending;
-	raw->clear_pending = bnx2x_raw_clear_pending;
-	raw->set_pending = bnx2x_raw_set_pending;
-	raw->wait_comp = bnx2x_raw_wait;
-}
-
-static inline void bnx2x_init_vlan_mac_common(struct bnx2x_vlan_mac_obj *o,
-	u8 cl_id, u32 cid, u8 func_id, void *rdata, dma_addr_t rdata_mapping,
-	int state, unsigned long *pstate, bnx2x_obj_type type,
-	struct bnx2x_credit_pool_obj *macs_pool,
-	struct bnx2x_credit_pool_obj *vlans_pool)
-{
-	INIT_LIST_HEAD(&o->head);
-
-	o->macs_pool = macs_pool;
-	o->vlans_pool = vlans_pool;
-
-	o->delete_all = bnx2x_vlan_mac_del_all;
-	o->restore = bnx2x_vlan_mac_restore;
-	o->complete = bnx2x_complete_vlan_mac;
-	o->wait = bnx2x_wait_vlan_mac;
-
-	bnx2x_init_raw_obj(&o->raw, cl_id, cid, func_id, rdata, rdata_mapping,
-			   state, pstate, type);
-}
-
-
-void bnx2x_init_mac_obj(struct bnx2x *bp,
-			struct bnx2x_vlan_mac_obj *mac_obj,
-			u8 cl_id, u32 cid, u8 func_id, void *rdata,
-			dma_addr_t rdata_mapping, int state,
-			unsigned long *pstate, bnx2x_obj_type type,
-			struct bnx2x_credit_pool_obj *macs_pool)
-{
-	union bnx2x_qable_obj *qable_obj = (union bnx2x_qable_obj *)mac_obj;
-
-	bnx2x_init_vlan_mac_common(mac_obj, cl_id, cid, func_id, rdata,
-				   rdata_mapping, state, pstate, type,
-				   macs_pool, NULL);
-
-	/* CAM credit pool handling */
-	mac_obj->get_credit = bnx2x_get_credit_mac;
-	mac_obj->put_credit = bnx2x_put_credit_mac;
-	mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac;
-	mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac;
-
-	if (CHIP_IS_E1x(bp)) {
-		mac_obj->set_one_rule      = bnx2x_set_one_mac_e1x;
-		mac_obj->check_del         = bnx2x_check_mac_del;
-		mac_obj->check_add         = bnx2x_check_mac_add;
-		mac_obj->check_move        = bnx2x_check_move_always_err;
-		mac_obj->ramrod_cmd        = RAMROD_CMD_ID_ETH_SET_MAC;
-
-		/* Exe Queue */
-		bnx2x_exe_queue_init(bp,
-				     &mac_obj->exe_queue, 1, qable_obj,
-				     bnx2x_validate_vlan_mac,
-				     bnx2x_optimize_vlan_mac,
-				     bnx2x_execute_vlan_mac,
-				     bnx2x_exeq_get_mac);
-	} else {
-		mac_obj->set_one_rule      = bnx2x_set_one_mac_e2;
-		mac_obj->check_del         = bnx2x_check_mac_del;
-		mac_obj->check_add         = bnx2x_check_mac_add;
-		mac_obj->check_move        = bnx2x_check_move;
-		mac_obj->ramrod_cmd        =
-			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
-
-		/* Exe Queue */
-		bnx2x_exe_queue_init(bp,
-				     &mac_obj->exe_queue, CLASSIFY_RULES_COUNT,
-				     qable_obj, bnx2x_validate_vlan_mac,
-				     bnx2x_optimize_vlan_mac,
-				     bnx2x_execute_vlan_mac,
-				     bnx2x_exeq_get_mac);
-	}
-}
-
-void bnx2x_init_vlan_obj(struct bnx2x *bp,
-			 struct bnx2x_vlan_mac_obj *vlan_obj,
-			 u8 cl_id, u32 cid, u8 func_id, void *rdata,
-			 dma_addr_t rdata_mapping, int state,
-			 unsigned long *pstate, bnx2x_obj_type type,
-			 struct bnx2x_credit_pool_obj *vlans_pool)
-{
-	union bnx2x_qable_obj *qable_obj = (union bnx2x_qable_obj *)vlan_obj;
-
-	bnx2x_init_vlan_mac_common(vlan_obj, cl_id, cid, func_id, rdata,
-				   rdata_mapping, state, pstate, type, NULL,
-				   vlans_pool);
-
-	vlan_obj->get_credit = bnx2x_get_credit_vlan;
-	vlan_obj->put_credit = bnx2x_put_credit_vlan;
-	vlan_obj->get_cam_offset = bnx2x_get_cam_offset_vlan;
-	vlan_obj->put_cam_offset = bnx2x_put_cam_offset_vlan;
-
-	if (CHIP_IS_E1x(bp)) {
-		BNX2X_ERR("Do not support chips others than E2 and newer\n");
-		BUG();
-	} else {
-		vlan_obj->set_one_rule      = bnx2x_set_one_vlan_e2;
-		vlan_obj->check_del         = bnx2x_check_vlan_del;
-		vlan_obj->check_add         = bnx2x_check_vlan_add;
-		vlan_obj->check_move        = bnx2x_check_move;
-		vlan_obj->ramrod_cmd        =
-			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
-
-		/* Exe Queue */
-		bnx2x_exe_queue_init(bp,
-				     &vlan_obj->exe_queue, CLASSIFY_RULES_COUNT,
-				     qable_obj, bnx2x_validate_vlan_mac,
-				     bnx2x_optimize_vlan_mac,
-				     bnx2x_execute_vlan_mac,
-				     bnx2x_exeq_get_vlan);
-	}
-}
-
-void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
-			     struct bnx2x_vlan_mac_obj *vlan_mac_obj,
-			     u8 cl_id, u32 cid, u8 func_id, void *rdata,
-			     dma_addr_t rdata_mapping, int state,
-			     unsigned long *pstate, bnx2x_obj_type type,
-			     struct bnx2x_credit_pool_obj *macs_pool,
-			     struct bnx2x_credit_pool_obj *vlans_pool)
-{
-	union bnx2x_qable_obj *qable_obj =
-		(union bnx2x_qable_obj *)vlan_mac_obj;
-
-	bnx2x_init_vlan_mac_common(vlan_mac_obj, cl_id, cid, func_id, rdata,
-				   rdata_mapping, state, pstate, type,
-				   macs_pool, vlans_pool);
-
-	/* CAM pool handling */
-	vlan_mac_obj->get_credit = bnx2x_get_credit_vlan_mac;
-	vlan_mac_obj->put_credit = bnx2x_put_credit_vlan_mac;
-	/*
-	 * CAM offset is relevant for 57710 and 57711 chips only which have a
-	 * single CAM for both MACs and VLAN-MAC pairs. So the offset
-	 * will be taken from MACs' pool object only.
-	 */
-	vlan_mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac;
-	vlan_mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac;
-
-	if (CHIP_IS_E1(bp)) {
-		BNX2X_ERR("Do not support chips others than E2\n");
-		BUG();
-	} else if (CHIP_IS_E1H(bp)) {
-		vlan_mac_obj->set_one_rule      = bnx2x_set_one_vlan_mac_e1h;
-		vlan_mac_obj->check_del         = bnx2x_check_vlan_mac_del;
-		vlan_mac_obj->check_add         = bnx2x_check_vlan_mac_add;
-		vlan_mac_obj->check_move        = bnx2x_check_move_always_err;
-		vlan_mac_obj->ramrod_cmd        = RAMROD_CMD_ID_ETH_SET_MAC;
-
-		/* Exe Queue */
-		bnx2x_exe_queue_init(bp,
-				     &vlan_mac_obj->exe_queue, 1, qable_obj,
-				     bnx2x_validate_vlan_mac,
-				     bnx2x_optimize_vlan_mac,
-				     bnx2x_execute_vlan_mac,
-				     bnx2x_exeq_get_vlan_mac);
-	} else {
-		vlan_mac_obj->set_one_rule      = bnx2x_set_one_vlan_mac_e2;
-		vlan_mac_obj->check_del         = bnx2x_check_vlan_mac_del;
-		vlan_mac_obj->check_add         = bnx2x_check_vlan_mac_add;
-		vlan_mac_obj->check_move        = bnx2x_check_move;
-		vlan_mac_obj->ramrod_cmd        =
-			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
-
-		/* Exe Queue */
-		bnx2x_exe_queue_init(bp,
-				     &vlan_mac_obj->exe_queue,
-				     CLASSIFY_RULES_COUNT,
-				     qable_obj, bnx2x_validate_vlan_mac,
-				     bnx2x_optimize_vlan_mac,
-				     bnx2x_execute_vlan_mac,
-				     bnx2x_exeq_get_vlan_mac);
-	}
-
-}
-
-/* RX_MODE verbs: DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
-static inline void __storm_memset_mac_filters(struct bnx2x *bp,
-			struct tstorm_eth_mac_filter_config *mac_filters,
-			u16 pf_id)
-{
-	size_t size = sizeof(struct tstorm_eth_mac_filter_config);
-
-	u32 addr = BAR_TSTRORM_INTMEM +
-			TSTORM_MAC_FILTER_CONFIG_OFFSET(pf_id);
-
-	__storm_memset_struct(bp, addr, size, (u32 *)mac_filters);
-}
-
-static int bnx2x_set_rx_mode_e1x(struct bnx2x *bp,
-				 struct bnx2x_rx_mode_ramrod_params *p)
-{
-	/* update the bp MAC filter structure  */
-	u32 mask = (1 << p->cl_id);
-
-	struct tstorm_eth_mac_filter_config *mac_filters =
-		(struct tstorm_eth_mac_filter_config *)p->rdata;
-
-	/* initial seeting is drop-all */
-	u8 drop_all_ucast = 1, drop_all_mcast = 1;
-	u8 accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0;
-	u8 unmatched_unicast = 0;
-
-    /* In e1x there we only take into account rx acceot flag since tx switching
-     * isn't enabled. */
-	if (test_bit(BNX2X_ACCEPT_UNICAST, &p->rx_accept_flags))
-		/* accept matched ucast */
-		drop_all_ucast = 0;
-
-	if (test_bit(BNX2X_ACCEPT_MULTICAST, &p->rx_accept_flags))
-		/* accept matched mcast */
-		drop_all_mcast = 0;
-
-	if (test_bit(BNX2X_ACCEPT_ALL_UNICAST, &p->rx_accept_flags)) {
-		/* accept all mcast */
-		drop_all_ucast = 0;
-		accp_all_ucast = 1;
-	}
-	if (test_bit(BNX2X_ACCEPT_ALL_MULTICAST, &p->rx_accept_flags)) {
-		/* accept all mcast */
-		drop_all_mcast = 0;
-		accp_all_mcast = 1;
-	}
-	if (test_bit(BNX2X_ACCEPT_BROADCAST, &p->rx_accept_flags))
-		/* accept (all) bcast */
-		accp_all_bcast = 1;
-	if (test_bit(BNX2X_ACCEPT_UNMATCHED, &p->rx_accept_flags))
-		/* accept unmatched unicasts */
-		unmatched_unicast = 1;
-
-	mac_filters->ucast_drop_all = drop_all_ucast ?
-		mac_filters->ucast_drop_all | mask :
-		mac_filters->ucast_drop_all & ~mask;
-
-	mac_filters->mcast_drop_all = drop_all_mcast ?
-		mac_filters->mcast_drop_all | mask :
-		mac_filters->mcast_drop_all & ~mask;
-
-	mac_filters->ucast_accept_all = accp_all_ucast ?
-		mac_filters->ucast_accept_all | mask :
-		mac_filters->ucast_accept_all & ~mask;
-
-	mac_filters->mcast_accept_all = accp_all_mcast ?
-		mac_filters->mcast_accept_all | mask :
-		mac_filters->mcast_accept_all & ~mask;
-
-	mac_filters->bcast_accept_all = accp_all_bcast ?
-		mac_filters->bcast_accept_all | mask :
-		mac_filters->bcast_accept_all & ~mask;
-
-	mac_filters->unmatched_unicast = unmatched_unicast ?
-		mac_filters->unmatched_unicast | mask :
-		mac_filters->unmatched_unicast & ~mask;
-
-	DP(BNX2X_MSG_SP, "drop_ucast 0x%x\ndrop_mcast 0x%x\n accp_ucast 0x%x\n"
-			 "accp_mcast 0x%x\naccp_bcast 0x%x\n",
-			 mac_filters->ucast_drop_all,
-			 mac_filters->mcast_drop_all,
-			 mac_filters->ucast_accept_all,
-			 mac_filters->mcast_accept_all,
-			 mac_filters->bcast_accept_all);
-
-	/* write the MAC filter structure*/
-	__storm_memset_mac_filters(bp, mac_filters, p->func_id);
-
-	/* The operation is completed */
-	clear_bit(p->state, p->pstate);
-	smp_mb__after_clear_bit();
-
-	return 0;
-}
-
-/* Setup ramrod data */
-static inline void bnx2x_rx_mode_set_rdata_hdr_e2(u32 cid,
-				struct eth_classify_header *hdr,
-				u8 rule_cnt)
-{
-	hdr->echo = cid;
-	hdr->rule_cnt = rule_cnt;
-}
-
-static inline void bnx2x_rx_mode_set_cmd_state_e2(struct bnx2x *bp,
-				unsigned long accept_flags,
-				struct eth_filter_rules_cmd *cmd,
-				bool clear_accept_all)
-{
-	u16 state;
-
-	/* start with 'drop-all' */
-	state = ETH_FILTER_RULES_CMD_UCAST_DROP_ALL |
-		ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
-
-	if (accept_flags) {
-		if (test_bit(BNX2X_ACCEPT_UNICAST, &accept_flags))
-			state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
-
-		if (test_bit(BNX2X_ACCEPT_MULTICAST, &accept_flags))
-			state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
-
-		if (test_bit(BNX2X_ACCEPT_ALL_UNICAST, &accept_flags)) {
-			state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
-			state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL;
-		}
-
-		if (test_bit(BNX2X_ACCEPT_ALL_MULTICAST, &accept_flags)) {
-			state |= ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL;
-			state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
-		}
-		if (test_bit(BNX2X_ACCEPT_BROADCAST, &accept_flags))
-			state |= ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL;
-
-		if (test_bit(BNX2X_ACCEPT_UNMATCHED, &accept_flags)) {
-			state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
-			state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED;
-		}
-		if (test_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags))
-			state |= ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN;
-	}
-
-	/* Clear ACCEPT_ALL_XXX flags for FCoE L2 Queue */
-	if (clear_accept_all) {
-		state &= ~ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL;
-		state &= ~ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL;
-		state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL;
-		state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED;
-	}
-
-	cmd->state = cpu_to_le16(state);
-
-}
-
-static int bnx2x_set_rx_mode_e2(struct bnx2x *bp,
-				struct bnx2x_rx_mode_ramrod_params *p)
-{
-	struct eth_filter_rules_ramrod_data *data = p->rdata;
-	int rc;
-	u8 rule_idx = 0;
-
-	/* Reset the ramrod data buffer */
-	memset(data, 0, sizeof(*data));
-
-	/* Setup ramrod data */
-
-	/* Tx (internal switching) */
-	if (test_bit(RAMROD_TX, &p->ramrod_flags)) {
-		data->rules[rule_idx].client_id = p->cl_id;
-		data->rules[rule_idx].func_id = p->func_id;
-
-		data->rules[rule_idx].cmd_general_data =
-			ETH_FILTER_RULES_CMD_TX_CMD;
-
-		bnx2x_rx_mode_set_cmd_state_e2(bp, p->tx_accept_flags,
-			&(data->rules[rule_idx++]), false);
-	}
-
-	/* Rx */
-	if (test_bit(RAMROD_RX, &p->ramrod_flags)) {
-		data->rules[rule_idx].client_id = p->cl_id;
-		data->rules[rule_idx].func_id = p->func_id;
-
-		data->rules[rule_idx].cmd_general_data =
-			ETH_FILTER_RULES_CMD_RX_CMD;
-
-		bnx2x_rx_mode_set_cmd_state_e2(bp, p->rx_accept_flags,
-			&(data->rules[rule_idx++]), false);
-	}
-
-
-	/*
-	 * If FCoE Queue configuration has been requested configure the Rx and
-	 * internal switching modes for this queue in separate rules.
-	 *
-	 * FCoE queue shell never be set to ACCEPT_ALL packets of any sort:
-	 * MCAST_ALL, UCAST_ALL, BCAST_ALL and UNMATCHED.
-	 */
-	if (test_bit(BNX2X_RX_MODE_FCOE_ETH, &p->rx_mode_flags)) {
-		/*  Tx (internal switching) */
-		if (test_bit(RAMROD_TX, &p->ramrod_flags)) {
-			data->rules[rule_idx].client_id = bnx2x_fcoe(bp, cl_id);
-			data->rules[rule_idx].func_id = p->func_id;
-
-			data->rules[rule_idx].cmd_general_data =
-						ETH_FILTER_RULES_CMD_TX_CMD;
-
-			bnx2x_rx_mode_set_cmd_state_e2(bp, p->tx_accept_flags,
-						     &(data->rules[rule_idx++]),
-						       true);
-		}
-
-		/* Rx */
-		if (test_bit(RAMROD_RX, &p->ramrod_flags)) {
-			data->rules[rule_idx].client_id = bnx2x_fcoe(bp, cl_id);
-			data->rules[rule_idx].func_id = p->func_id;
-
-			data->rules[rule_idx].cmd_general_data =
-						ETH_FILTER_RULES_CMD_RX_CMD;
-
-			bnx2x_rx_mode_set_cmd_state_e2(bp, p->rx_accept_flags,
-						     &(data->rules[rule_idx++]),
-						       true);
-		}
-	}
-
-	/*
-	 * Set the ramrod header (most importantly - number of rules to
-	 * configure).
-	 */
-	bnx2x_rx_mode_set_rdata_hdr_e2(p->cid, &data->header, rule_idx);
-
-	DP(BNX2X_MSG_SP, "About to configure %d rules, rx_accept_flags 0x%lx, "
-			 "tx_accept_flags 0x%lx\n",
-			 data->header.rule_cnt, p->rx_accept_flags,
-			 p->tx_accept_flags);
-
-	/*
-	 *  No need for an explicit memory barrier here as long we would
-	 *  need to ensure the ordering of writing to the SPQ element
-	 *  and updating of the SPQ producer which involves a memory
-	 *  read and we will have to put a full memory barrier there
-	 *  (inside bnx2x_sp_post()).
-	 */
-
-	/* Send a ramrod */
-	rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_FILTER_RULES, p->cid,
-			   U64_HI(p->rdata_mapping),
-			   U64_LO(p->rdata_mapping),
-			   ETH_CONNECTION_TYPE);
-	if (rc)
-		return rc;
-
-	/* Ramrod completion is pending */
-	return 1;
-}
-
-static int bnx2x_wait_rx_mode_comp_e2(struct bnx2x *bp,
-				      struct bnx2x_rx_mode_ramrod_params *p)
-{
-	return bnx2x_state_wait(bp, p->state, p->pstate);
-}
-
-static int bnx2x_empty_rx_mode_wait(struct bnx2x *bp,
-				    struct bnx2x_rx_mode_ramrod_params *p)
-{
-	/* Do nothing */
-	return 0;
-}
-
-int bnx2x_config_rx_mode(struct bnx2x *bp,
-			 struct bnx2x_rx_mode_ramrod_params *p)
-{
-	int rc;
-
-	/* Configure the new classification in the chip */
-	rc = p->rx_mode_obj->config_rx_mode(bp, p);
-	if (rc < 0)
-		return rc;
-
-	/* Wait for a ramrod completion if was requested */
-	if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
-		rc = p->rx_mode_obj->wait_comp(bp, p);
-		if (rc)
-			return rc;
-	}
-
-	return rc;
-}
-
-void bnx2x_init_rx_mode_obj(struct bnx2x *bp,
-			    struct bnx2x_rx_mode_obj *o)
-{
-	if (CHIP_IS_E1x(bp)) {
-		o->wait_comp      = bnx2x_empty_rx_mode_wait;
-		o->config_rx_mode = bnx2x_set_rx_mode_e1x;
-	} else {
-		o->wait_comp      = bnx2x_wait_rx_mode_comp_e2;
-		o->config_rx_mode = bnx2x_set_rx_mode_e2;
-	}
-}
-
-/********************* Multicast verbs: SET, CLEAR ****************************/
-static inline u8 bnx2x_mcast_bin_from_mac(u8 *mac)
-{
-	return (crc32c_le(0, mac, ETH_ALEN) >> 24) & 0xff;
-}
-
-struct bnx2x_mcast_mac_elem {
-	struct list_head link;
-	u8 mac[ETH_ALEN];
-	u8 pad[2]; /* For a natural alignment of the following buffer */
-};
-
-struct bnx2x_pending_mcast_cmd {
-	struct list_head link;
-	int type; /* BNX2X_MCAST_CMD_X */
-	union {
-		struct list_head macs_head;
-		u32 macs_num; /* Needed for DEL command */
-		int next_bin; /* Needed for RESTORE flow with aprox match */
-	} data;
-
-	bool done; /* set to true, when the command has been handled,
-		    * practically used in 57712 handling only, where one pending
-		    * command may be handled in a few operations. As long as for
-		    * other chips every operation handling is completed in a
-		    * single ramrod, there is no need to utilize this field.
-		    */
-};
-
-static int bnx2x_mcast_wait(struct bnx2x *bp,
-			    struct bnx2x_mcast_obj *o)
-{
-	if (bnx2x_state_wait(bp, o->sched_state, o->raw.pstate) ||
-			o->raw.wait_comp(bp, &o->raw))
-		return -EBUSY;
-
-	return 0;
-}
-
-static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp,
-				   struct bnx2x_mcast_obj *o,
-				   struct bnx2x_mcast_ramrod_params *p,
-				   int cmd)
-{
-	int total_sz;
-	struct bnx2x_pending_mcast_cmd *new_cmd;
-	struct bnx2x_mcast_mac_elem *cur_mac = NULL;
-	struct bnx2x_mcast_list_elem *pos;
-	int macs_list_len = ((cmd == BNX2X_MCAST_CMD_ADD) ?
-			     p->mcast_list_len : 0);
-
-	/* If the command is empty ("handle pending commands only"), break */
-	if (!p->mcast_list_len)
-		return 0;
-
-	total_sz = sizeof(*new_cmd) +
-		macs_list_len * sizeof(struct bnx2x_mcast_mac_elem);
-
-	/* Add mcast is called under spin_lock, thus calling with GFP_ATOMIC */
-	new_cmd = kzalloc(total_sz, GFP_ATOMIC);
-
-	if (!new_cmd)
-		return -ENOMEM;
-
-	DP(BNX2X_MSG_SP, "About to enqueue a new %d command. "
-			 "macs_list_len=%d\n", cmd, macs_list_len);
-
-	INIT_LIST_HEAD(&new_cmd->data.macs_head);
-
-	new_cmd->type = cmd;
-	new_cmd->done = false;
-
-	switch (cmd) {
-	case BNX2X_MCAST_CMD_ADD:
-		cur_mac = (struct bnx2x_mcast_mac_elem *)
-			  ((u8 *)new_cmd + sizeof(*new_cmd));
-
-		/* Push the MACs of the current command into the pendig command
-		 * MACs list: FIFO
-		 */
-		list_for_each_entry(pos, &p->mcast_list, link) {
-			memcpy(cur_mac->mac, pos->mac, ETH_ALEN);
-			list_add_tail(&cur_mac->link, &new_cmd->data.macs_head);
-			cur_mac++;
-		}
-
-		break;
-
-	case BNX2X_MCAST_CMD_DEL:
-		new_cmd->data.macs_num = p->mcast_list_len;
-		break;
-
-	case BNX2X_MCAST_CMD_RESTORE:
-		new_cmd->data.next_bin = 0;
-		break;
-
-	default:
-		BNX2X_ERR("Unknown command: %d\n", cmd);
-		return -EINVAL;
-	}
-
-	/* Push the new pending command to the tail of the pending list: FIFO */
-	list_add_tail(&new_cmd->link, &o->pending_cmds_head);
-
-	o->set_sched(o);
-
-	return 1;
-}
-
-/**
- * bnx2x_mcast_get_next_bin - get the next set bin (index)
- *
- * @o:
- * @last:	index to start looking from (including)
- *
- * returns the next found (set) bin or a negative value if none is found.
- */
-static inline int bnx2x_mcast_get_next_bin(struct bnx2x_mcast_obj *o, int last)
-{
-	int i, j, inner_start = last % BIT_VEC64_ELEM_SZ;
-
-	for (i = last / BIT_VEC64_ELEM_SZ; i < BNX2X_MCAST_VEC_SZ; i++) {
-		if (o->registry.aprox_match.vec[i])
-			for (j = inner_start; j < BIT_VEC64_ELEM_SZ; j++) {
-				int cur_bit = j + BIT_VEC64_ELEM_SZ * i;
-				if (BIT_VEC64_TEST_BIT(o->registry.aprox_match.
-						       vec, cur_bit)) {
-					return cur_bit;
-				}
-			}
-		inner_start = 0;
-	}
-
-	/* None found */
-	return -1;
-}
-
-/**
- * bnx2x_mcast_clear_first_bin - find the first set bin and clear it
- *
- * @o:
- *
- * returns the index of the found bin or -1 if none is found
- */
-static inline int bnx2x_mcast_clear_first_bin(struct bnx2x_mcast_obj *o)
-{
-	int cur_bit = bnx2x_mcast_get_next_bin(o, 0);
-
-	if (cur_bit >= 0)
-		BIT_VEC64_CLEAR_BIT(o->registry.aprox_match.vec, cur_bit);
-
-	return cur_bit;
-}
-
-static inline u8 bnx2x_mcast_get_rx_tx_flag(struct bnx2x_mcast_obj *o)
-{
-	struct bnx2x_raw_obj *raw = &o->raw;
-	u8 rx_tx_flag = 0;
-
-	if ((raw->obj_type == BNX2X_OBJ_TYPE_TX) ||
-	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
-		rx_tx_flag |= ETH_MULTICAST_RULES_CMD_TX_CMD;
-
-	if ((raw->obj_type == BNX2X_OBJ_TYPE_RX) ||
-	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
-		rx_tx_flag |= ETH_MULTICAST_RULES_CMD_RX_CMD;
-
-	return rx_tx_flag;
-}
-
-static void bnx2x_mcast_set_one_rule_e2(struct bnx2x *bp,
-					struct bnx2x_mcast_obj *o, int idx,
-					union bnx2x_mcast_config_data *cfg_data,
-					int cmd)
-{
-	struct bnx2x_raw_obj *r = &o->raw;
-	struct eth_multicast_rules_ramrod_data *data =
-		(struct eth_multicast_rules_ramrod_data *)(r->rdata);
-	u8 func_id = r->func_id;
-	u8 rx_tx_add_flag = bnx2x_mcast_get_rx_tx_flag(o);
-	int bin;
-
-	if ((cmd == BNX2X_MCAST_CMD_ADD) || (cmd == BNX2X_MCAST_CMD_RESTORE))
-		rx_tx_add_flag |= ETH_MULTICAST_RULES_CMD_IS_ADD;
-
-	data->rules[idx].cmd_general_data |= rx_tx_add_flag;
-
-	/* Get a bin and update a bins' vector */
-	switch (cmd) {
-	case BNX2X_MCAST_CMD_ADD:
-		bin = bnx2x_mcast_bin_from_mac(cfg_data->mac);
-		BIT_VEC64_SET_BIT(o->registry.aprox_match.vec, bin);
-		break;
-
-	case BNX2X_MCAST_CMD_DEL:
-		/* If there were no more bins to clear
-		 * (bnx2x_mcast_clear_first_bin() returns -1) then we would
-		 * clear any (0xff) bin.
-		 * See bnx2x_mcast_validate_e2() for explanation when it may
-		 * happen.
-		 */
-		bin = bnx2x_mcast_clear_first_bin(o);
-		break;
-
-	case BNX2X_MCAST_CMD_RESTORE:
-		bin = cfg_data->bin;
-		break;
-
-	default:
-		BNX2X_ERR("Unknown command: %d\n", cmd);
-		return;
-	}
-
-	DP(BNX2X_MSG_SP, "%s bin %d\n",
-			 ((rx_tx_add_flag & ETH_MULTICAST_RULES_CMD_IS_ADD) ?
-			 "Setting"  : "Clearing"), bin);
-
-	data->rules[idx].bin_id    = (u8)bin;
-	data->rules[idx].func_id   = func_id;
-	data->rules[idx].engine_id = o->engine_id;
-}
-
-/**
- * bnx2x_mcast_handle_restore_cmd_e2 - restore configuration from the registry
- *
- * @bp:		device handle
- * @o:
- * @start_bin:	index in the registry to start from (including)
- * @rdata_idx:	index in the ramrod data to start from
- *
- * returns last handled bin index or -1 if all bins have been handled
- */
-static inline int bnx2x_mcast_handle_restore_cmd_e2(
-	struct bnx2x *bp, struct bnx2x_mcast_obj *o , int start_bin,
-	int *rdata_idx)
-{
-	int cur_bin, cnt = *rdata_idx;
-	union bnx2x_mcast_config_data cfg_data = {0};
-
-	/* go through the registry and configure the bins from it */
-	for (cur_bin = bnx2x_mcast_get_next_bin(o, start_bin); cur_bin >= 0;
-	    cur_bin = bnx2x_mcast_get_next_bin(o, cur_bin + 1)) {
-
-		cfg_data.bin = (u8)cur_bin;
-		o->set_one_rule(bp, o, cnt, &cfg_data,
-				BNX2X_MCAST_CMD_RESTORE);
-
-		cnt++;
-
-		DP(BNX2X_MSG_SP, "About to configure a bin %d\n", cur_bin);
-
-		/* Break if we reached the maximum number
-		 * of rules.
-		 */
-		if (cnt >= o->max_cmd_len)
-			break;
-	}
-
-	*rdata_idx = cnt;
-
-	return cur_bin;
-}
-
-static inline void bnx2x_mcast_hdl_pending_add_e2(struct bnx2x *bp,
-	struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
-	int *line_idx)
-{
-	struct bnx2x_mcast_mac_elem *pmac_pos, *pmac_pos_n;
-	int cnt = *line_idx;
-	union bnx2x_mcast_config_data cfg_data = {0};
-
-	list_for_each_entry_safe(pmac_pos, pmac_pos_n, &cmd_pos->data.macs_head,
-				 link) {
-
-		cfg_data.mac = &pmac_pos->mac[0];
-		o->set_one_rule(bp, o, cnt, &cfg_data, cmd_pos->type);
-
-		cnt++;
-
-		DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
-				 " mcast MAC\n",
-				 BNX2X_MAC_PRN_LIST(pmac_pos->mac));
-
-		list_del(&pmac_pos->link);
-
-		/* Break if we reached the maximum number
-		 * of rules.
-		 */
-		if (cnt >= o->max_cmd_len)
-			break;
-	}
-
-	*line_idx = cnt;
-
-	/* if no more MACs to configure - we are done */
-	if (list_empty(&cmd_pos->data.macs_head))
-		cmd_pos->done = true;
-}
-
-static inline void bnx2x_mcast_hdl_pending_del_e2(struct bnx2x *bp,
-	struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
-	int *line_idx)
-{
-	int cnt = *line_idx;
-
-	while (cmd_pos->data.macs_num) {
-		o->set_one_rule(bp, o, cnt, NULL, cmd_pos->type);
-
-		cnt++;
-
-		cmd_pos->data.macs_num--;
-
-		  DP(BNX2X_MSG_SP, "Deleting MAC. %d left,cnt is %d\n",
-				   cmd_pos->data.macs_num, cnt);
-
-		/* Break if we reached the maximum
-		 * number of rules.
-		 */
-		if (cnt >= o->max_cmd_len)
-			break;
-	}
-
-	*line_idx = cnt;
-
-	/* If we cleared all bins - we are done */
-	if (!cmd_pos->data.macs_num)
-		cmd_pos->done = true;
-}
-
-static inline void bnx2x_mcast_hdl_pending_restore_e2(struct bnx2x *bp,
-	struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
-	int *line_idx)
-{
-	cmd_pos->data.next_bin = o->hdl_restore(bp, o, cmd_pos->data.next_bin,
-						line_idx);
-
-	if (cmd_pos->data.next_bin < 0)
-		/* If o->set_restore returned -1 we are done */
-		cmd_pos->done = true;
-	else
-		/* Start from the next bin next time */
-		cmd_pos->data.next_bin++;
-}
-
-static inline int bnx2x_mcast_handle_pending_cmds_e2(struct bnx2x *bp,
-				struct bnx2x_mcast_ramrod_params *p)
-{
-	struct bnx2x_pending_mcast_cmd *cmd_pos, *cmd_pos_n;
-	int cnt = 0;
-	struct bnx2x_mcast_obj *o = p->mcast_obj;
-
-	list_for_each_entry_safe(cmd_pos, cmd_pos_n, &o->pending_cmds_head,
-				 link) {
-		switch (cmd_pos->type) {
-		case BNX2X_MCAST_CMD_ADD:
-			bnx2x_mcast_hdl_pending_add_e2(bp, o, cmd_pos, &cnt);
-			break;
-
-		case BNX2X_MCAST_CMD_DEL:
-			bnx2x_mcast_hdl_pending_del_e2(bp, o, cmd_pos, &cnt);
-			break;
-
-		case BNX2X_MCAST_CMD_RESTORE:
-			bnx2x_mcast_hdl_pending_restore_e2(bp, o, cmd_pos,
-							   &cnt);
-			break;
-
-		default:
-			BNX2X_ERR("Unknown command: %d\n", cmd_pos->type);
-			return -EINVAL;
-		}
-
-		/* If the command has been completed - remove it from the list
-		 * and free the memory
-		 */
-		if (cmd_pos->done) {
-			list_del(&cmd_pos->link);
-			kfree(cmd_pos);
-		}
-
-		/* Break if we reached the maximum number of rules */
-		if (cnt >= o->max_cmd_len)
-			break;
-	}
-
-	return cnt;
-}
-
-static inline void bnx2x_mcast_hdl_add(struct bnx2x *bp,
-	struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
-	int *line_idx)
-{
-	struct bnx2x_mcast_list_elem *mlist_pos;
-	union bnx2x_mcast_config_data cfg_data = {0};
-	int cnt = *line_idx;
-
-	list_for_each_entry(mlist_pos, &p->mcast_list, link) {
-		cfg_data.mac = mlist_pos->mac;
-		o->set_one_rule(bp, o, cnt, &cfg_data, BNX2X_MCAST_CMD_ADD);
-
-		cnt++;
-
-		DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
-				 " mcast MAC\n",
-				 BNX2X_MAC_PRN_LIST(mlist_pos->mac));
-	}
-
-	*line_idx = cnt;
-}
-
-static inline void bnx2x_mcast_hdl_del(struct bnx2x *bp,
-	struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
-	int *line_idx)
-{
-	int cnt = *line_idx, i;
-
-	for (i = 0; i < p->mcast_list_len; i++) {
-		o->set_one_rule(bp, o, cnt, NULL, BNX2X_MCAST_CMD_DEL);
-
-		cnt++;
-
-		DP(BNX2X_MSG_SP, "Deleting MAC. %d left\n",
-				 p->mcast_list_len - i - 1);
-	}
-
-	*line_idx = cnt;
-}
-
-/**
- * bnx2x_mcast_handle_current_cmd -
- *
- * @bp:		device handle
- * @p:
- * @cmd:
- * @start_cnt:	first line in the ramrod data that may be used
- *
- * This function is called iff there is enough place for the current command in
- * the ramrod data.
- * Returns number of lines filled in the ramrod data in total.
- */
-static inline int bnx2x_mcast_handle_current_cmd(struct bnx2x *bp,
-			struct bnx2x_mcast_ramrod_params *p, int cmd,
-			int start_cnt)
-{
-	struct bnx2x_mcast_obj *o = p->mcast_obj;
-	int cnt = start_cnt;
-
-	DP(BNX2X_MSG_SP, "p->mcast_list_len=%d\n", p->mcast_list_len);
-
-	switch (cmd) {
-	case BNX2X_MCAST_CMD_ADD:
-		bnx2x_mcast_hdl_add(bp, o, p, &cnt);
-		break;
-
-	case BNX2X_MCAST_CMD_DEL:
-		bnx2x_mcast_hdl_del(bp, o, p, &cnt);
-		break;
-
-	case BNX2X_MCAST_CMD_RESTORE:
-		o->hdl_restore(bp, o, 0, &cnt);
-		break;
-
-	default:
-		BNX2X_ERR("Unknown command: %d\n", cmd);
-		return -EINVAL;
-	}
-
-	/* The current command has been handled */
-	p->mcast_list_len = 0;
-
-	return cnt;
-}
-
-static int bnx2x_mcast_validate_e2(struct bnx2x *bp,
-				   struct bnx2x_mcast_ramrod_params *p,
-				   int cmd)
-{
-	struct bnx2x_mcast_obj *o = p->mcast_obj;
-	int reg_sz = o->get_registry_size(o);
-
-	switch (cmd) {
-	/* DEL command deletes all currently configured MACs */
-	case BNX2X_MCAST_CMD_DEL:
-		o->set_registry_size(o, 0);
-		/* Don't break */
-
-	/* RESTORE command will restore the entire multicast configuration */
-	case BNX2X_MCAST_CMD_RESTORE:
-		/* Here we set the approximate amount of work to do, which in
-		 * fact may be only less as some MACs in postponed ADD
-		 * command(s) scheduled before this command may fall into
-		 * the same bin and the actual number of bins set in the
-		 * registry would be less than we estimated here. See
-		 * bnx2x_mcast_set_one_rule_e2() for further details.
-		 */
-		p->mcast_list_len = reg_sz;
-		break;
-
-	case BNX2X_MCAST_CMD_ADD:
-	case BNX2X_MCAST_CMD_CONT:
-		/* Here we assume that all new MACs will fall into new bins.
-		 * However we will correct the real registry size after we
-		 * handle all pending commands.
-		 */
-		o->set_registry_size(o, reg_sz + p->mcast_list_len);
-		break;
-
-	default:
-		BNX2X_ERR("Unknown command: %d\n", cmd);
-		return -EINVAL;
-
-	}
-
-	/* Increase the total number of MACs pending to be configured */
-	o->total_pending_num += p->mcast_list_len;
-
-	return 0;
-}
-
-static void bnx2x_mcast_revert_e2(struct bnx2x *bp,
-				      struct bnx2x_mcast_ramrod_params *p,
-				      int old_num_bins)
-{
-	struct bnx2x_mcast_obj *o = p->mcast_obj;
-
-	o->set_registry_size(o, old_num_bins);
-	o->total_pending_num -= p->mcast_list_len;
-}
-
-/**
- * bnx2x_mcast_set_rdata_hdr_e2 - sets a header values
- *
- * @bp:		device handle
- * @p:
- * @len:	number of rules to handle
- */
-static inline void bnx2x_mcast_set_rdata_hdr_e2(struct bnx2x *bp,
-					struct bnx2x_mcast_ramrod_params *p,
-					u8 len)
-{
-	struct bnx2x_raw_obj *r = &p->mcast_obj->raw;
-	struct eth_multicast_rules_ramrod_data *data =
-		(struct eth_multicast_rules_ramrod_data *)(r->rdata);
-
-	data->header.echo = ((r->cid & BNX2X_SWCID_MASK) |
-			  (BNX2X_FILTER_MCAST_PENDING << BNX2X_SWCID_SHIFT));
-	data->header.rule_cnt = len;
-}
-
-/**
- * bnx2x_mcast_refresh_registry_e2 - recalculate the actual number of set bins
- *
- * @bp:		device handle
- * @o:
- *
- * Recalculate the actual number of set bins in the registry using Brian
- * Kernighan's algorithm: it's execution complexity is as a number of set bins.
- *
- * returns 0 for the compliance with bnx2x_mcast_refresh_registry_e1().
- */
-static inline int bnx2x_mcast_refresh_registry_e2(struct bnx2x *bp,
-						  struct bnx2x_mcast_obj *o)
-{
-	int i, cnt = 0;
-	u64 elem;
-
-	for (i = 0; i < BNX2X_MCAST_VEC_SZ; i++) {
-		elem = o->registry.aprox_match.vec[i];
-		for (; elem; cnt++)
-			elem &= elem - 1;
-	}
-
-	o->set_registry_size(o, cnt);
-
-	return 0;
-}
-
-static int bnx2x_mcast_setup_e2(struct bnx2x *bp,
-				struct bnx2x_mcast_ramrod_params *p,
-				int cmd)
-{
-	struct bnx2x_raw_obj *raw = &p->mcast_obj->raw;
-	struct bnx2x_mcast_obj *o = p->mcast_obj;
-	struct eth_multicast_rules_ramrod_data *data =
-		(struct eth_multicast_rules_ramrod_data *)(raw->rdata);
-	int cnt = 0, rc;
-
-	/* Reset the ramrod data buffer */
-	memset(data, 0, sizeof(*data));
-
-	cnt = bnx2x_mcast_handle_pending_cmds_e2(bp, p);
-
-	/* If there are no more pending commands - clear SCHEDULED state */
-	if (list_empty(&o->pending_cmds_head))
-		o->clear_sched(o);
-
-	/* The below may be true iff there was enough room in ramrod
-	 * data for all pending commands and for the current
-	 * command. Otherwise the current command would have been added
-	 * to the pending commands and p->mcast_list_len would have been
-	 * zeroed.
-	 */
-	if (p->mcast_list_len > 0)
-		cnt = bnx2x_mcast_handle_current_cmd(bp, p, cmd, cnt);
-
-	/* We've pulled out some MACs - update the total number of
-	 * outstanding.
-	 */
-	o->total_pending_num -= cnt;
-
-	/* send a ramrod */
-	WARN_ON(o->total_pending_num < 0);
-	WARN_ON(cnt > o->max_cmd_len);
-
-	bnx2x_mcast_set_rdata_hdr_e2(bp, p, (u8)cnt);
-
-	/* Update a registry size if there are no more pending operations.
-	 *
-	 * We don't want to change the value of the registry size if there are
-	 * pending operations because we want it to always be equal to the
-	 * exact or the approximate number (see bnx2x_mcast_validate_e2()) of
-	 * set bins after the last requested operation in order to properly
-	 * evaluate the size of the next DEL/RESTORE operation.
-	 *
-	 * Note that we update the registry itself during command(s) handling
-	 * - see bnx2x_mcast_set_one_rule_e2(). That's because for 57712 we
-	 * aggregate multiple commands (ADD/DEL/RESTORE) into one ramrod but
-	 * with a limited amount of update commands (per MAC/bin) and we don't
-	 * know in this scope what the actual state of bins configuration is
-	 * going to be after this ramrod.
-	 */
-	if (!o->total_pending_num)
-		bnx2x_mcast_refresh_registry_e2(bp, o);
-
-	/*
-	 * If CLEAR_ONLY was requested - don't send a ramrod and clear
-	 * RAMROD_PENDING status immediately.
-	 */
-	if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
-		raw->clear_pending(raw);
-		return 0;
-	} else {
-		/*
-		 *  No need for an explicit memory barrier here as long we would
-		 *  need to ensure the ordering of writing to the SPQ element
-		 *  and updating of the SPQ producer which involves a memory
-		 *  read and we will have to put a full memory barrier there
-		 *  (inside bnx2x_sp_post()).
-		 */
-
-		/* Send a ramrod */
-		rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_MULTICAST_RULES,
-				   raw->cid, U64_HI(raw->rdata_mapping),
-				   U64_LO(raw->rdata_mapping),
-				   ETH_CONNECTION_TYPE);
-		if (rc)
-			return rc;
-
-		/* Ramrod completion is pending */
-		return 1;
-	}
-}
-
-static int bnx2x_mcast_validate_e1h(struct bnx2x *bp,
-				    struct bnx2x_mcast_ramrod_params *p,
-				    int cmd)
-{
-	/* Mark, that there is a work to do */
-	if ((cmd == BNX2X_MCAST_CMD_DEL) || (cmd == BNX2X_MCAST_CMD_RESTORE))
-		p->mcast_list_len = 1;
-
-	return 0;
-}
-
-static void bnx2x_mcast_revert_e1h(struct bnx2x *bp,
-				       struct bnx2x_mcast_ramrod_params *p,
-				       int old_num_bins)
-{
-	/* Do nothing */
-}
-
-#define BNX2X_57711_SET_MC_FILTER(filter, bit) \
-do { \
-	(filter)[(bit) >> 5] |= (1 << ((bit) & 0x1f)); \
-} while (0)
-
-static inline void bnx2x_mcast_hdl_add_e1h(struct bnx2x *bp,
-					   struct bnx2x_mcast_obj *o,
-					   struct bnx2x_mcast_ramrod_params *p,
-					   u32 *mc_filter)
-{
-	struct bnx2x_mcast_list_elem *mlist_pos;
-	int bit;
-
-	list_for_each_entry(mlist_pos, &p->mcast_list, link) {
-		bit = bnx2x_mcast_bin_from_mac(mlist_pos->mac);
-		BNX2X_57711_SET_MC_FILTER(mc_filter, bit);
-
-		DP(BNX2X_MSG_SP, "About to configure "
-				 BNX2X_MAC_FMT" mcast MAC, bin %d\n",
-				 BNX2X_MAC_PRN_LIST(mlist_pos->mac), bit);
-
-		/* bookkeeping... */
-		BIT_VEC64_SET_BIT(o->registry.aprox_match.vec,
-				  bit);
-	}
-}
-
-static inline void bnx2x_mcast_hdl_restore_e1h(struct bnx2x *bp,
-	struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
-	u32 *mc_filter)
-{
-	int bit;
-
-	for (bit = bnx2x_mcast_get_next_bin(o, 0);
-	     bit >= 0;
-	     bit = bnx2x_mcast_get_next_bin(o, bit + 1)) {
-		BNX2X_57711_SET_MC_FILTER(mc_filter, bit);
-		DP(BNX2X_MSG_SP, "About to set bin %d\n", bit);
-	}
-}
-
-/* On 57711 we write the multicast MACs' aproximate match
- * table by directly into the TSTORM's internal RAM. So we don't
- * really need to handle any tricks to make it work.
- */
-static int bnx2x_mcast_setup_e1h(struct bnx2x *bp,
-				 struct bnx2x_mcast_ramrod_params *p,
-				 int cmd)
-{
-	int i;
-	struct bnx2x_mcast_obj *o = p->mcast_obj;
-	struct bnx2x_raw_obj *r = &o->raw;
-
-	/* If CLEAR_ONLY has been requested - clear the registry
-	 * and clear a pending bit.
-	 */
-	if (!test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
-		u32 mc_filter[MC_HASH_SIZE] = {0};
-
-		/* Set the multicast filter bits before writing it into
-		 * the internal memory.
-		 */
-		switch (cmd) {
-		case BNX2X_MCAST_CMD_ADD:
-			bnx2x_mcast_hdl_add_e1h(bp, o, p, mc_filter);
-			break;
-
-		case BNX2X_MCAST_CMD_DEL:
-			DP(BNX2X_MSG_SP, "Invalidating multicast "
-					 "MACs configuration\n");
-
-			/* clear the registry */
-			memset(o->registry.aprox_match.vec, 0,
-			       sizeof(o->registry.aprox_match.vec));
-			break;
-
-		case BNX2X_MCAST_CMD_RESTORE:
-			bnx2x_mcast_hdl_restore_e1h(bp, o, p, mc_filter);
-			break;
-
-		default:
-			BNX2X_ERR("Unknown command: %d\n", cmd);
-			return -EINVAL;
-		}
-
-		/* Set the mcast filter in the internal memory */
-		for (i = 0; i < MC_HASH_SIZE; i++)
-			REG_WR(bp, MC_HASH_OFFSET(bp, i), mc_filter[i]);
-	} else
-		/* clear the registry */
-		memset(o->registry.aprox_match.vec, 0,
-		       sizeof(o->registry.aprox_match.vec));
-
-	/* We are done */
-	r->clear_pending(r);
-
-	return 0;
-}
-
-static int bnx2x_mcast_validate_e1(struct bnx2x *bp,
-				   struct bnx2x_mcast_ramrod_params *p,
-				   int cmd)
-{
-	struct bnx2x_mcast_obj *o = p->mcast_obj;
-	int reg_sz = o->get_registry_size(o);
-
-	switch (cmd) {
-	/* DEL command deletes all currently configured MACs */
-	case BNX2X_MCAST_CMD_DEL:
-		o->set_registry_size(o, 0);
-		/* Don't break */
-
-	/* RESTORE command will restore the entire multicast configuration */
-	case BNX2X_MCAST_CMD_RESTORE:
-		p->mcast_list_len = reg_sz;
-		  DP(BNX2X_MSG_SP, "Command %d, p->mcast_list_len=%d\n",
-				   cmd, p->mcast_list_len);
-		break;
-
-	case BNX2X_MCAST_CMD_ADD:
-	case BNX2X_MCAST_CMD_CONT:
-		/* Multicast MACs on 57710 are configured as unicast MACs and
-		 * there is only a limited number of CAM entries for that
-		 * matter.
-		 */
-		if (p->mcast_list_len > o->max_cmd_len) {
-			BNX2X_ERR("Can't configure more than %d multicast MACs"
-				   "on 57710\n", o->max_cmd_len);
-			return -EINVAL;
-		}
-		/* Every configured MAC should be cleared if DEL command is
-		 * called. Only the last ADD command is relevant as long as
-		 * every ADD commands overrides the previous configuration.
-		 */
-		DP(BNX2X_MSG_SP, "p->mcast_list_len=%d\n", p->mcast_list_len);
-		if (p->mcast_list_len > 0)
-			o->set_registry_size(o, p->mcast_list_len);
-
-		break;
-
-	default:
-		BNX2X_ERR("Unknown command: %d\n", cmd);
-		return -EINVAL;
-
-	}
-
-	/* We want to ensure that commands are executed one by one for 57710.
-	 * Therefore each none-empty command will consume o->max_cmd_len.
-	 */
-	if (p->mcast_list_len)
-		o->total_pending_num += o->max_cmd_len;
-
-	return 0;
-}
-
-static void bnx2x_mcast_revert_e1(struct bnx2x *bp,
-				      struct bnx2x_mcast_ramrod_params *p,
-				      int old_num_macs)
-{
-	struct bnx2x_mcast_obj *o = p->mcast_obj;
-
-	o->set_registry_size(o, old_num_macs);
-
-	/* If current command hasn't been handled yet and we are
-	 * here means that it's meant to be dropped and we have to
-	 * update the number of outstandling MACs accordingly.
-	 */
-	if (p->mcast_list_len)
-		o->total_pending_num -= o->max_cmd_len;
-}
-
-static void bnx2x_mcast_set_one_rule_e1(struct bnx2x *bp,
-					struct bnx2x_mcast_obj *o, int idx,
-					union bnx2x_mcast_config_data *cfg_data,
-					int cmd)
-{
-	struct bnx2x_raw_obj *r = &o->raw;
-	struct mac_configuration_cmd *data =
-		(struct mac_configuration_cmd *)(r->rdata);
-
-	/* copy mac */
-	if ((cmd == BNX2X_MCAST_CMD_ADD) || (cmd == BNX2X_MCAST_CMD_RESTORE)) {
-		bnx2x_set_fw_mac_addr(&data->config_table[idx].msb_mac_addr,
-				      &data->config_table[idx].middle_mac_addr,
-				      &data->config_table[idx].lsb_mac_addr,
-				      cfg_data->mac);
-
-		data->config_table[idx].vlan_id = 0;
-		data->config_table[idx].pf_id = r->func_id;
-		data->config_table[idx].clients_bit_vector =
-			cpu_to_le32(1 << r->cl_id);
-
-		SET_FLAG(data->config_table[idx].flags,
-			 MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
-			 T_ETH_MAC_COMMAND_SET);
-	}
-}
-
-/**
- * bnx2x_mcast_set_rdata_hdr_e1  - set header values in mac_configuration_cmd
- *
- * @bp:		device handle
- * @p:
- * @len:	number of rules to handle
- */
-static inline void bnx2x_mcast_set_rdata_hdr_e1(struct bnx2x *bp,
-					struct bnx2x_mcast_ramrod_params *p,
-					u8 len)
-{
-	struct bnx2x_raw_obj *r = &p->mcast_obj->raw;
-	struct mac_configuration_cmd *data =
-		(struct mac_configuration_cmd *)(r->rdata);
-
-	u8 offset = (CHIP_REV_IS_SLOW(bp) ?
-		     BNX2X_MAX_EMUL_MULTI*(1 + r->func_id) :
-		     BNX2X_MAX_MULTICAST*(1 + r->func_id));
-
-	data->hdr.offset = offset;
-	data->hdr.client_id = 0xff;
-	data->hdr.echo = ((r->cid & BNX2X_SWCID_MASK) |
-			  (BNX2X_FILTER_MCAST_PENDING << BNX2X_SWCID_SHIFT));
-	data->hdr.length = len;
-}
-
-/**
- * bnx2x_mcast_handle_restore_cmd_e1 - restore command for 57710
- *
- * @bp:		device handle
- * @o:
- * @start_idx:	index in the registry to start from
- * @rdata_idx:	index in the ramrod data to start from
- *
- * restore command for 57710 is like all other commands - always a stand alone
- * command - start_idx and rdata_idx will always be 0. This function will always
- * succeed.
- * returns -1 to comply with 57712 variant.
- */
-static inline int bnx2x_mcast_handle_restore_cmd_e1(
-	struct bnx2x *bp, struct bnx2x_mcast_obj *o , int start_idx,
-	int *rdata_idx)
-{
-	struct bnx2x_mcast_mac_elem *elem;
-	int i = 0;
-	union bnx2x_mcast_config_data cfg_data = {0};
-
-	/* go through the registry and configure the MACs from it. */
-	list_for_each_entry(elem, &o->registry.exact_match.macs, link) {
-		cfg_data.mac = &elem->mac[0];
-		o->set_one_rule(bp, o, i, &cfg_data, BNX2X_MCAST_CMD_RESTORE);
-
-		i++;
-
-		  DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
-				   " mcast MAC\n",
-				   BNX2X_MAC_PRN_LIST(cfg_data.mac));
-	}
-
-	*rdata_idx = i;
-
-	return -1;
-}
-
-
-static inline int bnx2x_mcast_handle_pending_cmds_e1(
-	struct bnx2x *bp, struct bnx2x_mcast_ramrod_params *p)
-{
-	struct bnx2x_pending_mcast_cmd *cmd_pos;
-	struct bnx2x_mcast_mac_elem *pmac_pos;
-	struct bnx2x_mcast_obj *o = p->mcast_obj;
-	union bnx2x_mcast_config_data cfg_data = {0};
-	int cnt = 0;
-
-
-	/* If nothing to be done - return */
-	if (list_empty(&o->pending_cmds_head))
-		return 0;
-
-	/* Handle the first command */
-	cmd_pos = list_first_entry(&o->pending_cmds_head,
-				   struct bnx2x_pending_mcast_cmd, link);
-
-	switch (cmd_pos->type) {
-	case BNX2X_MCAST_CMD_ADD:
-		list_for_each_entry(pmac_pos, &cmd_pos->data.macs_head, link) {
-			cfg_data.mac = &pmac_pos->mac[0];
-			o->set_one_rule(bp, o, cnt, &cfg_data, cmd_pos->type);
-
-			cnt++;
-
-			DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
-					 " mcast MAC\n",
-					 BNX2X_MAC_PRN_LIST(pmac_pos->mac));
-		}
-		break;
-
-	case BNX2X_MCAST_CMD_DEL:
-		cnt = cmd_pos->data.macs_num;
-		DP(BNX2X_MSG_SP, "About to delete %d multicast MACs\n", cnt);
-		break;
-
-	case BNX2X_MCAST_CMD_RESTORE:
-		o->hdl_restore(bp, o, 0, &cnt);
-		break;
-
-	default:
-		BNX2X_ERR("Unknown command: %d\n", cmd_pos->type);
-		return -EINVAL;
-	}
-
-	list_del(&cmd_pos->link);
-	kfree(cmd_pos);
-
-	return cnt;
-}
-
-/**
- * bnx2x_get_fw_mac_addr - revert the bnx2x_set_fw_mac_addr().
- *
- * @fw_hi:
- * @fw_mid:
- * @fw_lo:
- * @mac:
- */
-static inline void bnx2x_get_fw_mac_addr(__le16 *fw_hi, __le16 *fw_mid,
-					 __le16 *fw_lo, u8 *mac)
-{
-	mac[1] = ((u8 *)fw_hi)[0];
-	mac[0] = ((u8 *)fw_hi)[1];
-	mac[3] = ((u8 *)fw_mid)[0];
-	mac[2] = ((u8 *)fw_mid)[1];
-	mac[5] = ((u8 *)fw_lo)[0];
-	mac[4] = ((u8 *)fw_lo)[1];
-}
-
-/**
- * bnx2x_mcast_refresh_registry_e1 -
- *
- * @bp:		device handle
- * @cnt:
- *
- * Check the ramrod data first entry flag to see if it's a DELETE or ADD command
- * and update the registry correspondingly: if ADD - allocate a memory and add
- * the entries to the registry (list), if DELETE - clear the registry and free
- * the memory.
- */
-static inline int bnx2x_mcast_refresh_registry_e1(struct bnx2x *bp,
-						  struct bnx2x_mcast_obj *o)
-{
-	struct bnx2x_raw_obj *raw = &o->raw;
-	struct bnx2x_mcast_mac_elem *elem;
-	struct mac_configuration_cmd *data =
-			(struct mac_configuration_cmd *)(raw->rdata);
-
-	/* If first entry contains a SET bit - the command was ADD,
-	 * otherwise - DEL_ALL
-	 */
-	if (GET_FLAG(data->config_table[0].flags,
-			MAC_CONFIGURATION_ENTRY_ACTION_TYPE)) {
-		int i, len = data->hdr.length;
-
-		/* Break if it was a RESTORE command */
-		if (!list_empty(&o->registry.exact_match.macs))
-			return 0;
-
-		elem = kzalloc(sizeof(*elem)*len, GFP_ATOMIC);
-		if (!elem) {
-			BNX2X_ERR("Failed to allocate registry memory\n");
-			return -ENOMEM;
-		}
-
-		for (i = 0; i < len; i++, elem++) {
-			bnx2x_get_fw_mac_addr(
-				&data->config_table[i].msb_mac_addr,
-				&data->config_table[i].middle_mac_addr,
-				&data->config_table[i].lsb_mac_addr,
-				elem->mac);
-			DP(BNX2X_MSG_SP, "Adding registry entry for ["
-					 BNX2X_MAC_FMT"]\n",
-				   BNX2X_MAC_PRN_LIST(elem->mac));
-			list_add_tail(&elem->link,
-				      &o->registry.exact_match.macs);
-		}
-	} else {
-		elem = list_first_entry(&o->registry.exact_match.macs,
-					struct bnx2x_mcast_mac_elem, link);
-		DP(BNX2X_MSG_SP, "Deleting a registry\n");
-		kfree(elem);
-		INIT_LIST_HEAD(&o->registry.exact_match.macs);
-	}
-
-	return 0;
-}
-
-static int bnx2x_mcast_setup_e1(struct bnx2x *bp,
-				struct bnx2x_mcast_ramrod_params *p,
-				int cmd)
-{
-	struct bnx2x_mcast_obj *o = p->mcast_obj;
-	struct bnx2x_raw_obj *raw = &o->raw;
-	struct mac_configuration_cmd *data =
-		(struct mac_configuration_cmd *)(raw->rdata);
-	int cnt = 0, i, rc;
-
-	/* Reset the ramrod data buffer */
-	memset(data, 0, sizeof(*data));
-
-	/* First set all entries as invalid */
-	for (i = 0; i < o->max_cmd_len ; i++)
-		SET_FLAG(data->config_table[i].flags,
-			 MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
-			 T_ETH_MAC_COMMAND_INVALIDATE);
-
-	/* Handle pending commands first */
-	cnt = bnx2x_mcast_handle_pending_cmds_e1(bp, p);
-
-	/* If there are no more pending commands - clear SCHEDULED state */
-	if (list_empty(&o->pending_cmds_head))
-		o->clear_sched(o);
-
-	/* The below may be true iff there were no pending commands */
-	if (!cnt)
-		cnt = bnx2x_mcast_handle_current_cmd(bp, p, cmd, 0);
-
-	/* For 57710 every command has o->max_cmd_len length to ensure that
-	 * commands are done one at a time.
-	 */
-	o->total_pending_num -= o->max_cmd_len;
-
-	/* send a ramrod */
-
-	WARN_ON(cnt > o->max_cmd_len);
-
-	/* Set ramrod header (in particular, a number of entries to update) */
-	bnx2x_mcast_set_rdata_hdr_e1(bp, p, (u8)cnt);
-
-	/* update a registry: we need the registry contents to be always up
-	 * to date in order to be able to execute a RESTORE opcode. Here
-	 * we use the fact that for 57710 we sent one command at a time
-	 * hence we may take the registry update out of the command handling
-	 * and do it in a simpler way here.
-	 */
-	rc = bnx2x_mcast_refresh_registry_e1(bp, o);
-	if (rc)
-		return rc;
-
-	/*
-	 * If CLEAR_ONLY was requested - don't send a ramrod and clear
-	 * RAMROD_PENDING status immediately.
-	 */
-	if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
-		raw->clear_pending(raw);
-		return 0;
-	} else {
-		/*
-		 *  No need for an explicit memory barrier here as long we would
-		 *  need to ensure the ordering of writing to the SPQ element
-		 *  and updating of the SPQ producer which involves a memory
-		 *  read and we will have to put a full memory barrier there
-		 *  (inside bnx2x_sp_post()).
-		 */
-
-		/* Send a ramrod */
-		rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, raw->cid,
-				   U64_HI(raw->rdata_mapping),
-				   U64_LO(raw->rdata_mapping),
-				   ETH_CONNECTION_TYPE);
-		if (rc)
-			return rc;
-
-		/* Ramrod completion is pending */
-		return 1;
-	}
-
-}
-
-static int bnx2x_mcast_get_registry_size_exact(struct bnx2x_mcast_obj *o)
-{
-	return o->registry.exact_match.num_macs_set;
-}
-
-static int bnx2x_mcast_get_registry_size_aprox(struct bnx2x_mcast_obj *o)
-{
-	return o->registry.aprox_match.num_bins_set;
-}
-
-static void bnx2x_mcast_set_registry_size_exact(struct bnx2x_mcast_obj *o,
-						int n)
-{
-	o->registry.exact_match.num_macs_set = n;
-}
-
-static void bnx2x_mcast_set_registry_size_aprox(struct bnx2x_mcast_obj *o,
-						int n)
-{
-	o->registry.aprox_match.num_bins_set = n;
-}
-
-int bnx2x_config_mcast(struct bnx2x *bp,
-		       struct bnx2x_mcast_ramrod_params *p,
-		       int cmd)
-{
-	struct bnx2x_mcast_obj *o = p->mcast_obj;
-	struct bnx2x_raw_obj *r = &o->raw;
-	int rc = 0, old_reg_size;
-
-	/* This is needed to recover number of currently configured mcast macs
-	 * in case of failure.
-	 */
-	old_reg_size = o->get_registry_size(o);
-
-	/* Do some calculations and checks */
-	rc = o->validate(bp, p, cmd);
-	if (rc)
-		return rc;
-
-	/* Return if there is no work to do */
-	if ((!p->mcast_list_len) && (!o->check_sched(o)))
-		return 0;
-
-	DP(BNX2X_MSG_SP, "o->total_pending_num=%d p->mcast_list_len=%d "
-			 "o->max_cmd_len=%d\n", o->total_pending_num,
-			 p->mcast_list_len, o->max_cmd_len);
-
-	/* Enqueue the current command to the pending list if we can't complete
-	 * it in the current iteration
-	 */
-	if (r->check_pending(r) ||
-	    ((o->max_cmd_len > 0) && (o->total_pending_num > o->max_cmd_len))) {
-		rc = o->enqueue_cmd(bp, p->mcast_obj, p, cmd);
-		if (rc < 0)
-			goto error_exit1;
-
-		/* As long as the current command is in a command list we
-		 * don't need to handle it separately.
-		 */
-		p->mcast_list_len = 0;
-	}
-
-	if (!r->check_pending(r)) {
-
-		/* Set 'pending' state */
-		r->set_pending(r);
-
-		/* Configure the new classification in the chip */
-		rc = o->config_mcast(bp, p, cmd);
-		if (rc < 0)
-			goto error_exit2;
-
-		/* Wait for a ramrod completion if was requested */
-		if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags))
-			rc = o->wait_comp(bp, o);
-	}
-
-	return rc;
-
-error_exit2:
-	r->clear_pending(r);
-
-error_exit1:
-	o->revert(bp, p, old_reg_size);
-
-	return rc;
-}
-
-static void bnx2x_mcast_clear_sched(struct bnx2x_mcast_obj *o)
-{
-	smp_mb__before_clear_bit();
-	clear_bit(o->sched_state, o->raw.pstate);
-	smp_mb__after_clear_bit();
-}
-
-static void bnx2x_mcast_set_sched(struct bnx2x_mcast_obj *o)
-{
-	smp_mb__before_clear_bit();
-	set_bit(o->sched_state, o->raw.pstate);
-	smp_mb__after_clear_bit();
-}
-
-static bool bnx2x_mcast_check_sched(struct bnx2x_mcast_obj *o)
-{
-	return !!test_bit(o->sched_state, o->raw.pstate);
-}
-
-static bool bnx2x_mcast_check_pending(struct bnx2x_mcast_obj *o)
-{
-	return o->raw.check_pending(&o->raw) || o->check_sched(o);
-}
-
-void bnx2x_init_mcast_obj(struct bnx2x *bp,
-			  struct bnx2x_mcast_obj *mcast_obj,
-			  u8 mcast_cl_id, u32 mcast_cid, u8 func_id,
-			  u8 engine_id, void *rdata, dma_addr_t rdata_mapping,
-			  int state, unsigned long *pstate, bnx2x_obj_type type)
-{
-	memset(mcast_obj, 0, sizeof(*mcast_obj));
-
-	bnx2x_init_raw_obj(&mcast_obj->raw, mcast_cl_id, mcast_cid, func_id,
-			   rdata, rdata_mapping, state, pstate, type);
-
-	mcast_obj->engine_id = engine_id;
-
-	INIT_LIST_HEAD(&mcast_obj->pending_cmds_head);
-
-	mcast_obj->sched_state = BNX2X_FILTER_MCAST_SCHED;
-	mcast_obj->check_sched = bnx2x_mcast_check_sched;
-	mcast_obj->set_sched = bnx2x_mcast_set_sched;
-	mcast_obj->clear_sched = bnx2x_mcast_clear_sched;
-
-	if (CHIP_IS_E1(bp)) {
-		mcast_obj->config_mcast      = bnx2x_mcast_setup_e1;
-		mcast_obj->enqueue_cmd       = bnx2x_mcast_enqueue_cmd;
-		mcast_obj->hdl_restore       =
-			bnx2x_mcast_handle_restore_cmd_e1;
-		mcast_obj->check_pending     = bnx2x_mcast_check_pending;
-
-		if (CHIP_REV_IS_SLOW(bp))
-			mcast_obj->max_cmd_len = BNX2X_MAX_EMUL_MULTI;
-		else
-			mcast_obj->max_cmd_len = BNX2X_MAX_MULTICAST;
-
-		mcast_obj->wait_comp         = bnx2x_mcast_wait;
-		mcast_obj->set_one_rule      = bnx2x_mcast_set_one_rule_e1;
-		mcast_obj->validate          = bnx2x_mcast_validate_e1;
-		mcast_obj->revert            = bnx2x_mcast_revert_e1;
-		mcast_obj->get_registry_size =
-			bnx2x_mcast_get_registry_size_exact;
-		mcast_obj->set_registry_size =
-			bnx2x_mcast_set_registry_size_exact;
-
-		/* 57710 is the only chip that uses the exact match for mcast
-		 * at the moment.
-		 */
-		INIT_LIST_HEAD(&mcast_obj->registry.exact_match.macs);
-
-	} else if (CHIP_IS_E1H(bp)) {
-		mcast_obj->config_mcast  = bnx2x_mcast_setup_e1h;
-		mcast_obj->enqueue_cmd   = NULL;
-		mcast_obj->hdl_restore   = NULL;
-		mcast_obj->check_pending = bnx2x_mcast_check_pending;
-
-		/* 57711 doesn't send a ramrod, so it has unlimited credit
-		 * for one command.
-		 */
-		mcast_obj->max_cmd_len       = -1;
-		mcast_obj->wait_comp         = bnx2x_mcast_wait;
-		mcast_obj->set_one_rule      = NULL;
-		mcast_obj->validate          = bnx2x_mcast_validate_e1h;
-		mcast_obj->revert            = bnx2x_mcast_revert_e1h;
-		mcast_obj->get_registry_size =
-			bnx2x_mcast_get_registry_size_aprox;
-		mcast_obj->set_registry_size =
-			bnx2x_mcast_set_registry_size_aprox;
-	} else {
-		mcast_obj->config_mcast      = bnx2x_mcast_setup_e2;
-		mcast_obj->enqueue_cmd       = bnx2x_mcast_enqueue_cmd;
-		mcast_obj->hdl_restore       =
-			bnx2x_mcast_handle_restore_cmd_e2;
-		mcast_obj->check_pending     = bnx2x_mcast_check_pending;
-		/* TODO: There should be a proper HSI define for this number!!!
-		 */
-		mcast_obj->max_cmd_len       = 16;
-		mcast_obj->wait_comp         = bnx2x_mcast_wait;
-		mcast_obj->set_one_rule      = bnx2x_mcast_set_one_rule_e2;
-		mcast_obj->validate          = bnx2x_mcast_validate_e2;
-		mcast_obj->revert            = bnx2x_mcast_revert_e2;
-		mcast_obj->get_registry_size =
-			bnx2x_mcast_get_registry_size_aprox;
-		mcast_obj->set_registry_size =
-			bnx2x_mcast_set_registry_size_aprox;
-	}
-}
-
-/*************************** Credit handling **********************************/
-
-/**
- * atomic_add_ifless - add if the result is less than a given value.
- *
- * @v:	pointer of type atomic_t
- * @a:	the amount to add to v...
- * @u:	...if (v + a) is less than u.
- *
- * returns true if (v + a) was less than u, and false otherwise.
- *
- */
-static inline bool __atomic_add_ifless(atomic_t *v, int a, int u)
-{
-	int c, old;
-
-	c = atomic_read(v);
-	for (;;) {
-		if (unlikely(c + a >= u))
-			return false;
-
-		old = atomic_cmpxchg((v), c, c + a);
-		if (likely(old == c))
-			break;
-		c = old;
-	}
-
-	return true;
-}
-
-/**
- * atomic_dec_ifmoe - dec if the result is more or equal than a given value.
- *
- * @v:	pointer of type atomic_t
- * @a:	the amount to dec from v...
- * @u:	...if (v - a) is more or equal than u.
- *
- * returns true if (v - a) was more or equal than u, and false
- * otherwise.
- */
-static inline bool __atomic_dec_ifmoe(atomic_t *v, int a, int u)
-{
-	int c, old;
-
-	c = atomic_read(v);
-	for (;;) {
-		if (unlikely(c - a < u))
-			return false;
-
-		old = atomic_cmpxchg((v), c, c - a);
-		if (likely(old == c))
-			break;
-		c = old;
-	}
-
-	return true;
-}
-
-static bool bnx2x_credit_pool_get(struct bnx2x_credit_pool_obj *o, int cnt)
-{
-	bool rc;
-
-	smp_mb();
-	rc = __atomic_dec_ifmoe(&o->credit, cnt, 0);
-	smp_mb();
-
-	return rc;
-}
-
-static bool bnx2x_credit_pool_put(struct bnx2x_credit_pool_obj *o, int cnt)
-{
-	bool rc;
-
-	smp_mb();
-
-	/* Don't let to refill if credit + cnt > pool_sz */
-	rc = __atomic_add_ifless(&o->credit, cnt, o->pool_sz + 1);
-
-	smp_mb();
-
-	return rc;
-}
-
-static int bnx2x_credit_pool_check(struct bnx2x_credit_pool_obj *o)
-{
-	int cur_credit;
-
-	smp_mb();
-	cur_credit = atomic_read(&o->credit);
-
-	return cur_credit;
-}
-
-static bool bnx2x_credit_pool_always_true(struct bnx2x_credit_pool_obj *o,
-					  int cnt)
-{
-	return true;
-}
-
-
-static bool bnx2x_credit_pool_get_entry(
-	struct bnx2x_credit_pool_obj *o,
-	int *offset)
-{
-	int idx, vec, i;
-
-	*offset = -1;
-
-	/* Find "internal cam-offset" then add to base for this object... */
-	for (vec = 0; vec < BNX2X_POOL_VEC_SIZE; vec++) {
-
-		/* Skip the current vector if there are no free entries in it */
-		if (!o->pool_mirror[vec])
-			continue;
-
-		/* If we've got here we are going to find a free entry */
-		for (idx = vec * BNX2X_POOL_VEC_SIZE, i = 0;
-		      i < BIT_VEC64_ELEM_SZ; idx++, i++)
-
-			if (BIT_VEC64_TEST_BIT(o->pool_mirror, idx)) {
-				/* Got one!! */
-				BIT_VEC64_CLEAR_BIT(o->pool_mirror, idx);
-				*offset = o->base_pool_offset + idx;
-				return true;
-			}
-	}
-
-	return false;
-}
-
-static bool bnx2x_credit_pool_put_entry(
-	struct bnx2x_credit_pool_obj *o,
-	int offset)
-{
-	if (offset < o->base_pool_offset)
-		return false;
-
-	offset -= o->base_pool_offset;
-
-	if (offset >= o->pool_sz)
-		return false;
-
-	/* Return the entry to the pool */
-	BIT_VEC64_SET_BIT(o->pool_mirror, offset);
-
-	return true;
-}
-
-static bool bnx2x_credit_pool_put_entry_always_true(
-	struct bnx2x_credit_pool_obj *o,
-	int offset)
-{
-	return true;
-}
-
-static bool bnx2x_credit_pool_get_entry_always_true(
-	struct bnx2x_credit_pool_obj *o,
-	int *offset)
-{
-	*offset = -1;
-	return true;
-}
-/**
- * bnx2x_init_credit_pool - initialize credit pool internals.
- *
- * @p:
- * @base:	Base entry in the CAM to use.
- * @credit:	pool size.
- *
- * If base is negative no CAM entries handling will be performed.
- * If credit is negative pool operations will always succeed (unlimited pool).
- *
- */
-static inline void bnx2x_init_credit_pool(struct bnx2x_credit_pool_obj *p,
-					  int base, int credit)
-{
-	/* Zero the object first */
-	memset(p, 0, sizeof(*p));
-
-	/* Set the table to all 1s */
-	memset(&p->pool_mirror, 0xff, sizeof(p->pool_mirror));
-
-	/* Init a pool as full */
-	atomic_set(&p->credit, credit);
-
-	/* The total poll size */
-	p->pool_sz = credit;
-
-	p->base_pool_offset = base;
-
-	/* Commit the change */
-	smp_mb();
-
-	p->check = bnx2x_credit_pool_check;
-
-	/* if pool credit is negative - disable the checks */
-	if (credit >= 0) {
-		p->put      = bnx2x_credit_pool_put;
-		p->get      = bnx2x_credit_pool_get;
-		p->put_entry = bnx2x_credit_pool_put_entry;
-		p->get_entry = bnx2x_credit_pool_get_entry;
-	} else {
-		p->put      = bnx2x_credit_pool_always_true;
-		p->get      = bnx2x_credit_pool_always_true;
-		p->put_entry = bnx2x_credit_pool_put_entry_always_true;
-		p->get_entry = bnx2x_credit_pool_get_entry_always_true;
-	}
-
-	/* If base is negative - disable entries handling */
-	if (base < 0) {
-		p->put_entry = bnx2x_credit_pool_put_entry_always_true;
-		p->get_entry = bnx2x_credit_pool_get_entry_always_true;
-	}
-}
-
-void bnx2x_init_mac_credit_pool(struct bnx2x *bp,
-				struct bnx2x_credit_pool_obj *p, u8 func_id,
-				u8 func_num)
-{
-/* TODO: this will be defined in consts as well... */
-#define BNX2X_CAM_SIZE_EMUL 5
-
-	int cam_sz;
-
-	if (CHIP_IS_E1(bp)) {
-		/* In E1, Multicast is saved in cam... */
-		if (!CHIP_REV_IS_SLOW(bp))
-			cam_sz = (MAX_MAC_CREDIT_E1 / 2) - BNX2X_MAX_MULTICAST;
-		else
-			cam_sz = BNX2X_CAM_SIZE_EMUL - BNX2X_MAX_EMUL_MULTI;
-
-		bnx2x_init_credit_pool(p, func_id * cam_sz, cam_sz);
-
-	} else if (CHIP_IS_E1H(bp)) {
-		/* CAM credit is equaly divided between all active functions
-		 * on the PORT!.
-		 */
-		if ((func_num > 0)) {
-			if (!CHIP_REV_IS_SLOW(bp))
-				cam_sz = (MAX_MAC_CREDIT_E1H / (2*func_num));
-			else
-				cam_sz = BNX2X_CAM_SIZE_EMUL;
-			bnx2x_init_credit_pool(p, func_id * cam_sz, cam_sz);
-		} else {
-			/* this should never happen! Block MAC operations. */
-			bnx2x_init_credit_pool(p, 0, 0);
-		}
-
-	} else {
-
-		/*
-		 * CAM credit is equaly divided between all active functions
-		 * on the PATH.
-		 */
-		if ((func_num > 0)) {
-			if (!CHIP_REV_IS_SLOW(bp))
-				cam_sz = (MAX_MAC_CREDIT_E2 / func_num);
-			else
-				cam_sz = BNX2X_CAM_SIZE_EMUL;
-
-			/*
-			 * No need for CAM entries handling for 57712 and
-			 * newer.
-			 */
-			bnx2x_init_credit_pool(p, -1, cam_sz);
-		} else {
-			/* this should never happen! Block MAC operations. */
-			bnx2x_init_credit_pool(p, 0, 0);
-		}
-
-	}
-}
-
-void bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
-				 struct bnx2x_credit_pool_obj *p,
-				 u8 func_id,
-				 u8 func_num)
-{
-	if (CHIP_IS_E1x(bp)) {
-		/*
-		 * There is no VLAN credit in HW on 57710 and 57711 only
-		 * MAC / MAC-VLAN can be set
-		 */
-		bnx2x_init_credit_pool(p, 0, -1);
-	} else {
-		/*
-		 * CAM credit is equaly divided between all active functions
-		 * on the PATH.
-		 */
-		if (func_num > 0) {
-			int credit = MAX_VLAN_CREDIT_E2 / func_num;
-			bnx2x_init_credit_pool(p, func_id * credit, credit);
-		} else
-			/* this should never happen! Block VLAN operations. */
-			bnx2x_init_credit_pool(p, 0, 0);
-	}
-}
-
-/****************** RSS Configuration ******************/
-/**
- * bnx2x_debug_print_ind_table - prints the indirection table configuration.
- *
- * @bp:		driver hanlde
- * @p:		pointer to rss configuration
- *
- * Prints it when NETIF_MSG_IFUP debug level is configured.
- */
-static inline void bnx2x_debug_print_ind_table(struct bnx2x *bp,
-					struct bnx2x_config_rss_params *p)
-{
-	int i;
-
-	DP(BNX2X_MSG_SP, "Setting indirection table to:\n");
-	DP(BNX2X_MSG_SP, "0x0000: ");
-	for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
-		DP_CONT(BNX2X_MSG_SP, "0x%02x ", p->ind_table[i]);
-
-		/* Print 4 bytes in a line */
-		if ((i + 1 < T_ETH_INDIRECTION_TABLE_SIZE) &&
-		    (((i + 1) & 0x3) == 0)) {
-			DP_CONT(BNX2X_MSG_SP, "\n");
-			DP(BNX2X_MSG_SP, "0x%04x: ", i + 1);
-		}
-	}
-
-	DP_CONT(BNX2X_MSG_SP, "\n");
-}
-
-/**
- * bnx2x_setup_rss - configure RSS
- *
- * @bp:		device handle
- * @p:		rss configuration
- *
- * sends on UPDATE ramrod for that matter.
- */
-static int bnx2x_setup_rss(struct bnx2x *bp,
-			   struct bnx2x_config_rss_params *p)
-{
-	struct bnx2x_rss_config_obj *o = p->rss_obj;
-	struct bnx2x_raw_obj *r = &o->raw;
-	struct eth_rss_update_ramrod_data *data =
-		(struct eth_rss_update_ramrod_data *)(r->rdata);
-	u8 rss_mode = 0;
-	int rc;
-
-	memset(data, 0, sizeof(*data));
-
-	DP(BNX2X_MSG_SP, "Configuring RSS\n");
-
-	/* Set an echo field */
-	data->echo = (r->cid & BNX2X_SWCID_MASK) |
-		     (r->state << BNX2X_SWCID_SHIFT);
-
-	/* RSS mode */
-	if (test_bit(BNX2X_RSS_MODE_DISABLED, &p->rss_flags))
-		rss_mode = ETH_RSS_MODE_DISABLED;
-	else if (test_bit(BNX2X_RSS_MODE_REGULAR, &p->rss_flags))
-		rss_mode = ETH_RSS_MODE_REGULAR;
-	else if (test_bit(BNX2X_RSS_MODE_VLAN_PRI, &p->rss_flags))
-		rss_mode = ETH_RSS_MODE_VLAN_PRI;
-	else if (test_bit(BNX2X_RSS_MODE_E1HOV_PRI, &p->rss_flags))
-		rss_mode = ETH_RSS_MODE_E1HOV_PRI;
-	else if (test_bit(BNX2X_RSS_MODE_IP_DSCP, &p->rss_flags))
-		rss_mode = ETH_RSS_MODE_IP_DSCP;
-
-	data->rss_mode = rss_mode;
-
-	DP(BNX2X_MSG_SP, "rss_mode=%d\n", rss_mode);
-
-	/* RSS capabilities */
-	if (test_bit(BNX2X_RSS_IPV4, &p->rss_flags))
-		data->capabilities |=
-			ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY;
-
-	if (test_bit(BNX2X_RSS_IPV4_TCP, &p->rss_flags))
-		data->capabilities |=
-			ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY;
-
-	if (test_bit(BNX2X_RSS_IPV6, &p->rss_flags))
-		data->capabilities |=
-			ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY;
-
-	if (test_bit(BNX2X_RSS_IPV6_TCP, &p->rss_flags))
-		data->capabilities |=
-			ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY;
-
-	/* Hashing mask */
-	data->rss_result_mask = p->rss_result_mask;
-
-	/* RSS engine ID */
-	data->rss_engine_id = o->engine_id;
-
-	DP(BNX2X_MSG_SP, "rss_engine_id=%d\n", data->rss_engine_id);
-
-	/* Indirection table */
-	memcpy(data->indirection_table, p->ind_table,
-		  T_ETH_INDIRECTION_TABLE_SIZE);
-
-	/* Remember the last configuration */
-	memcpy(o->ind_table, p->ind_table, T_ETH_INDIRECTION_TABLE_SIZE);
-
-	/* Print the indirection table */
-	if (netif_msg_ifup(bp))
-		bnx2x_debug_print_ind_table(bp, p);
-
-	/* RSS keys */
-	if (test_bit(BNX2X_RSS_SET_SRCH, &p->rss_flags)) {
-		memcpy(&data->rss_key[0], &p->rss_key[0],
-		       sizeof(data->rss_key));
-		data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY;
-	}
-
-	/*
-	 *  No need for an explicit memory barrier here as long we would
-	 *  need to ensure the ordering of writing to the SPQ element
-	 *  and updating of the SPQ producer which involves a memory
-	 *  read and we will have to put a full memory barrier there
-	 *  (inside bnx2x_sp_post()).
-	 */
-
-	/* Send a ramrod */
-	rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_RSS_UPDATE, r->cid,
-			   U64_HI(r->rdata_mapping),
-			   U64_LO(r->rdata_mapping),
-			   ETH_CONNECTION_TYPE);
-
-	if (rc < 0)
-		return rc;
-
-	return 1;
-}
-
-void bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj,
-			     u8 *ind_table)
-{
-	memcpy(ind_table, rss_obj->ind_table, sizeof(rss_obj->ind_table));
-}
-
-int bnx2x_config_rss(struct bnx2x *bp,
-		     struct bnx2x_config_rss_params *p)
-{
-	int rc;
-	struct bnx2x_rss_config_obj *o = p->rss_obj;
-	struct bnx2x_raw_obj *r = &o->raw;
-
-	/* Do nothing if only driver cleanup was requested */
-	if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags))
-		return 0;
-
-	r->set_pending(r);
-
-	rc = o->config_rss(bp, p);
-	if (rc < 0) {
-		r->clear_pending(r);
-		return rc;
-	}
-
-	if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags))
-		rc = r->wait_comp(bp, r);
-
-	return rc;
-}
-
-
-void bnx2x_init_rss_config_obj(struct bnx2x *bp,
-			       struct bnx2x_rss_config_obj *rss_obj,
-			       u8 cl_id, u32 cid, u8 func_id, u8 engine_id,
-			       void *rdata, dma_addr_t rdata_mapping,
-			       int state, unsigned long *pstate,
-			       bnx2x_obj_type type)
-{
-	bnx2x_init_raw_obj(&rss_obj->raw, cl_id, cid, func_id, rdata,
-			   rdata_mapping, state, pstate, type);
-
-	rss_obj->engine_id  = engine_id;
-	rss_obj->config_rss = bnx2x_setup_rss;
-}
-
-/********************** Queue state object ***********************************/
-
-/**
- * bnx2x_queue_state_change - perform Queue state change transition
- *
- * @bp:		device handle
- * @params:	parameters to perform the transition
- *
- * returns 0 in case of successfully completed transition, negative error
- * code in case of failure, positive (EBUSY) value if there is a completion
- * to that is still pending (possible only if RAMROD_COMP_WAIT is
- * not set in params->ramrod_flags for asynchronous commands).
- *
- */
-int bnx2x_queue_state_change(struct bnx2x *bp,
-			     struct bnx2x_queue_state_params *params)
-{
-	struct bnx2x_queue_sp_obj *o = params->q_obj;
-	int rc, pending_bit;
-	unsigned long *pending = &o->pending;
-
-	/* Check that the requested transition is legal */
-	if (o->check_transition(bp, o, params))
-		return -EINVAL;
-
-	/* Set "pending" bit */
-	pending_bit = o->set_pending(o, params);
-
-	/* Don't send a command if only driver cleanup was requested */
-	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags))
-		o->complete_cmd(bp, o, pending_bit);
-	else {
-		/* Send a ramrod */
-		rc = o->send_cmd(bp, params);
-		if (rc) {
-			o->next_state = BNX2X_Q_STATE_MAX;
-			clear_bit(pending_bit, pending);
-			smp_mb__after_clear_bit();
-			return rc;
-		}
-
-		if (test_bit(RAMROD_COMP_WAIT, &params->ramrod_flags)) {
-			rc = o->wait_comp(bp, o, pending_bit);
-			if (rc)
-				return rc;
-
-			return 0;
-		}
-	}
-
-	return !!test_bit(pending_bit, pending);
-}
-
-
-static int bnx2x_queue_set_pending(struct bnx2x_queue_sp_obj *obj,
-				   struct bnx2x_queue_state_params *params)
-{
-	enum bnx2x_queue_cmd cmd = params->cmd, bit;
-
-	/* ACTIVATE and DEACTIVATE commands are implemented on top of
-	 * UPDATE command.
-	 */
-	if ((cmd == BNX2X_Q_CMD_ACTIVATE) ||
-	    (cmd == BNX2X_Q_CMD_DEACTIVATE))
-		bit = BNX2X_Q_CMD_UPDATE;
-	else
-		bit = cmd;
-
-	set_bit(bit, &obj->pending);
-	return bit;
-}
-
-static int bnx2x_queue_wait_comp(struct bnx2x *bp,
-				 struct bnx2x_queue_sp_obj *o,
-				 enum bnx2x_queue_cmd cmd)
-{
-	return bnx2x_state_wait(bp, cmd, &o->pending);
-}
-
-/**
- * bnx2x_queue_comp_cmd - complete the state change command.
- *
- * @bp:		device handle
- * @o:
- * @cmd:
- *
- * Checks that the arrived completion is expected.
- */
-static int bnx2x_queue_comp_cmd(struct bnx2x *bp,
-				struct bnx2x_queue_sp_obj *o,
-				enum bnx2x_queue_cmd cmd)
-{
-	unsigned long cur_pending = o->pending;
-
-	if (!test_and_clear_bit(cmd, &cur_pending)) {
-		BNX2X_ERR("Bad MC reply %d for queue %d in state %d "
-			  "pending 0x%lx, next_state %d\n", cmd,
-			  o->cids[BNX2X_PRIMARY_CID_INDEX],
-			  o->state, cur_pending, o->next_state);
-		return -EINVAL;
-	}
-
-	if (o->next_tx_only >= o->max_cos)
-		/* >= becuase tx only must always be smaller than cos since the
-		 * primary connection suports COS 0
-		 */
-		BNX2X_ERR("illegal value for next tx_only: %d. max cos was %d",
-			   o->next_tx_only, o->max_cos);
-
-	DP(BNX2X_MSG_SP, "Completing command %d for queue %d, "
-			 "setting state to %d\n", cmd,
-			 o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_state);
-
-	if (o->next_tx_only)  /* print num tx-only if any exist */
-		DP(BNX2X_MSG_SP, "primary cid %d: num tx-only cons %d",
-			   o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_tx_only);
-
-	o->state = o->next_state;
-	o->num_tx_only = o->next_tx_only;
-	o->next_state = BNX2X_Q_STATE_MAX;
-
-	/* It's important that o->state and o->next_state are
-	 * updated before o->pending.
-	 */
-	wmb();
-
-	clear_bit(cmd, &o->pending);
-	smp_mb__after_clear_bit();
-
-	return 0;
-}
-
-static void bnx2x_q_fill_setup_data_e2(struct bnx2x *bp,
-				struct bnx2x_queue_state_params *cmd_params,
-				struct client_init_ramrod_data *data)
-{
-	struct bnx2x_queue_setup_params *params = &cmd_params->params.setup;
-
-	/* Rx data */
-
-	/* IPv6 TPA supported for E2 and above only */
-	data->rx.tpa_en |= test_bit(BNX2X_Q_FLG_TPA_IPV6, &params->flags) *
-				CLIENT_INIT_RX_DATA_TPA_EN_IPV6;
-}
-
-static void bnx2x_q_fill_init_general_data(struct bnx2x *bp,
-				struct bnx2x_queue_sp_obj *o,
-				struct bnx2x_general_setup_params *params,
-				struct client_init_general_data *gen_data,
-				unsigned long *flags)
-{
-	gen_data->client_id = o->cl_id;
-
-	if (test_bit(BNX2X_Q_FLG_STATS, flags)) {
-		gen_data->statistics_counter_id =
-					params->stat_id;
-		gen_data->statistics_en_flg = 1;
-		gen_data->statistics_zero_flg =
-			test_bit(BNX2X_Q_FLG_ZERO_STATS, flags);
-	} else
-		gen_data->statistics_counter_id =
-					DISABLE_STATISTIC_COUNTER_ID_VALUE;
-
-	gen_data->is_fcoe_flg = test_bit(BNX2X_Q_FLG_FCOE, flags);
-	gen_data->activate_flg = test_bit(BNX2X_Q_FLG_ACTIVE, flags);
-	gen_data->sp_client_id = params->spcl_id;
-	gen_data->mtu = cpu_to_le16(params->mtu);
-	gen_data->func_id = o->func_id;
-
-
-	gen_data->cos = params->cos;
-
-	gen_data->traffic_type =
-		test_bit(BNX2X_Q_FLG_FCOE, flags) ?
-		LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW;
-
-	DP(BNX2X_MSG_SP, "flags: active %d, cos %d, stats en %d",
-	   gen_data->activate_flg, gen_data->cos, gen_data->statistics_en_flg);
-}
-
-static void bnx2x_q_fill_init_tx_data(struct bnx2x_queue_sp_obj *o,
-				struct bnx2x_txq_setup_params *params,
-				struct client_init_tx_data *tx_data,
-				unsigned long *flags)
-{
-	tx_data->enforce_security_flg =
-		test_bit(BNX2X_Q_FLG_TX_SEC, flags);
-	tx_data->default_vlan =
-		cpu_to_le16(params->default_vlan);
-	tx_data->default_vlan_flg =
-		test_bit(BNX2X_Q_FLG_DEF_VLAN, flags);
-	tx_data->tx_switching_flg =
-		test_bit(BNX2X_Q_FLG_TX_SWITCH, flags);
-	tx_data->anti_spoofing_flg =
-		test_bit(BNX2X_Q_FLG_ANTI_SPOOF, flags);
-	tx_data->tx_status_block_id = params->fw_sb_id;
-	tx_data->tx_sb_index_number = params->sb_cq_index;
-	tx_data->tss_leading_client_id = params->tss_leading_cl_id;
-
-	tx_data->tx_bd_page_base.lo =
-		cpu_to_le32(U64_LO(params->dscr_map));
-	tx_data->tx_bd_page_base.hi =
-		cpu_to_le32(U64_HI(params->dscr_map));
-
-	/* Don't configure any Tx switching mode during queue SETUP */
-	tx_data->state = 0;
-}
-
-static void bnx2x_q_fill_init_pause_data(struct bnx2x_queue_sp_obj *o,
-				struct rxq_pause_params *params,
-				struct client_init_rx_data *rx_data)
-{
-	/* flow control data */
-	rx_data->cqe_pause_thr_low = cpu_to_le16(params->rcq_th_lo);
-	rx_data->cqe_pause_thr_high = cpu_to_le16(params->rcq_th_hi);
-	rx_data->bd_pause_thr_low = cpu_to_le16(params->bd_th_lo);
-	rx_data->bd_pause_thr_high = cpu_to_le16(params->bd_th_hi);
-	rx_data->sge_pause_thr_low = cpu_to_le16(params->sge_th_lo);
-	rx_data->sge_pause_thr_high = cpu_to_le16(params->sge_th_hi);
-	rx_data->rx_cos_mask = cpu_to_le16(params->pri_map);
-}
-
-static void bnx2x_q_fill_init_rx_data(struct bnx2x_queue_sp_obj *o,
-				struct bnx2x_rxq_setup_params *params,
-				struct client_init_rx_data *rx_data,
-				unsigned long *flags)
-{
-		/* Rx data */
-	rx_data->tpa_en = test_bit(BNX2X_Q_FLG_TPA, flags) *
-				CLIENT_INIT_RX_DATA_TPA_EN_IPV4;
-	rx_data->vmqueue_mode_en_flg = 0;
-
-	rx_data->cache_line_alignment_log_size =
-		params->cache_line_log;
-	rx_data->enable_dynamic_hc =
-		test_bit(BNX2X_Q_FLG_DHC, flags);
-	rx_data->max_sges_for_packet = params->max_sges_pkt;
-	rx_data->client_qzone_id = params->cl_qzone_id;
-	rx_data->max_agg_size = cpu_to_le16(params->tpa_agg_sz);
-
-	/* Always start in DROP_ALL mode */
-	rx_data->state = cpu_to_le16(CLIENT_INIT_RX_DATA_UCAST_DROP_ALL |
-				     CLIENT_INIT_RX_DATA_MCAST_DROP_ALL);
-
-	/* We don't set drop flags */
-	rx_data->drop_ip_cs_err_flg = 0;
-	rx_data->drop_tcp_cs_err_flg = 0;
-	rx_data->drop_ttl0_flg = 0;
-	rx_data->drop_udp_cs_err_flg = 0;
-	rx_data->inner_vlan_removal_enable_flg =
-		test_bit(BNX2X_Q_FLG_VLAN, flags);
-	rx_data->outer_vlan_removal_enable_flg =
-		test_bit(BNX2X_Q_FLG_OV, flags);
-	rx_data->status_block_id = params->fw_sb_id;
-	rx_data->rx_sb_index_number = params->sb_cq_index;
-	rx_data->max_tpa_queues = params->max_tpa_queues;
-	rx_data->max_bytes_on_bd = cpu_to_le16(params->buf_sz);
-	rx_data->sge_buff_size = cpu_to_le16(params->sge_buf_sz);
-	rx_data->bd_page_base.lo =
-		cpu_to_le32(U64_LO(params->dscr_map));
-	rx_data->bd_page_base.hi =
-		cpu_to_le32(U64_HI(params->dscr_map));
-	rx_data->sge_page_base.lo =
-		cpu_to_le32(U64_LO(params->sge_map));
-	rx_data->sge_page_base.hi =
-		cpu_to_le32(U64_HI(params->sge_map));
-	rx_data->cqe_page_base.lo =
-		cpu_to_le32(U64_LO(params->rcq_map));
-	rx_data->cqe_page_base.hi =
-		cpu_to_le32(U64_HI(params->rcq_map));
-	rx_data->is_leading_rss = test_bit(BNX2X_Q_FLG_LEADING_RSS, flags);
-
-	if (test_bit(BNX2X_Q_FLG_MCAST, flags)) {
-		rx_data->approx_mcast_engine_id = o->func_id;
-		rx_data->is_approx_mcast = 1;
-	}
-
-	rx_data->rss_engine_id = params->rss_engine_id;
-
-	/* silent vlan removal */
-	rx_data->silent_vlan_removal_flg =
-		test_bit(BNX2X_Q_FLG_SILENT_VLAN_REM, flags);
-	rx_data->silent_vlan_value =
-		cpu_to_le16(params->silent_removal_value);
-	rx_data->silent_vlan_mask =
-		cpu_to_le16(params->silent_removal_mask);
-
-}
-
-/* initialize the general, tx and rx parts of a queue object */
-static void bnx2x_q_fill_setup_data_cmn(struct bnx2x *bp,
-				struct bnx2x_queue_state_params *cmd_params,
-				struct client_init_ramrod_data *data)
-{
-	bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj,
-				       &cmd_params->params.setup.gen_params,
-				       &data->general,
-				       &cmd_params->params.setup.flags);
-
-	bnx2x_q_fill_init_tx_data(cmd_params->q_obj,
-				  &cmd_params->params.setup.txq_params,
-				  &data->tx,
-				  &cmd_params->params.setup.flags);
-
-	bnx2x_q_fill_init_rx_data(cmd_params->q_obj,
-				  &cmd_params->params.setup.rxq_params,
-				  &data->rx,
-				  &cmd_params->params.setup.flags);
-
-	bnx2x_q_fill_init_pause_data(cmd_params->q_obj,
-				     &cmd_params->params.setup.pause_params,
-				     &data->rx);
-}
-
-/* initialize the general and tx parts of a tx-only queue object */
-static void bnx2x_q_fill_setup_tx_only(struct bnx2x *bp,
-				struct bnx2x_queue_state_params *cmd_params,
-				struct tx_queue_init_ramrod_data *data)
-{
-	bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj,
-				       &cmd_params->params.tx_only.gen_params,
-				       &data->general,
-				       &cmd_params->params.tx_only.flags);
-
-	bnx2x_q_fill_init_tx_data(cmd_params->q_obj,
-				  &cmd_params->params.tx_only.txq_params,
-				  &data->tx,
-				  &cmd_params->params.tx_only.flags);
-
-	DP(BNX2X_MSG_SP, "cid %d, tx bd page lo %x hi %x",cmd_params->q_obj->cids[0],
-	   data->tx.tx_bd_page_base.lo, data->tx.tx_bd_page_base.hi);
-}
-
-/**
- * bnx2x_q_init - init HW/FW queue
- *
- * @bp:		device handle
- * @params:
- *
- * HW/FW initial Queue configuration:
- *      - HC: Rx and Tx
- *      - CDU context validation
- *
- */
-static inline int bnx2x_q_init(struct bnx2x *bp,
-			       struct bnx2x_queue_state_params *params)
-{
-	struct bnx2x_queue_sp_obj *o = params->q_obj;
-	struct bnx2x_queue_init_params *init = &params->params.init;
-	u16 hc_usec;
-	u8 cos;
-
-	/* Tx HC configuration */
-	if (test_bit(BNX2X_Q_TYPE_HAS_TX, &o->type) &&
-	    test_bit(BNX2X_Q_FLG_HC, &init->tx.flags)) {
-		hc_usec = init->tx.hc_rate ? 1000000 / init->tx.hc_rate : 0;
-
-		bnx2x_update_coalesce_sb_index(bp, init->tx.fw_sb_id,
-			init->tx.sb_cq_index,
-			!test_bit(BNX2X_Q_FLG_HC_EN, &init->tx.flags),
-			hc_usec);
-	}
-
-	/* Rx HC configuration */
-	if (test_bit(BNX2X_Q_TYPE_HAS_RX, &o->type) &&
-	    test_bit(BNX2X_Q_FLG_HC, &init->rx.flags)) {
-		hc_usec = init->rx.hc_rate ? 1000000 / init->rx.hc_rate : 0;
-
-		bnx2x_update_coalesce_sb_index(bp, init->rx.fw_sb_id,
-			init->rx.sb_cq_index,
-			!test_bit(BNX2X_Q_FLG_HC_EN, &init->rx.flags),
-			hc_usec);
-	}
-
-	/* Set CDU context validation values */
-	for (cos = 0; cos < o->max_cos; cos++) {
-		DP(BNX2X_MSG_SP, "setting context validation. cid %d, cos %d",
-				 o->cids[cos], cos);
-		DP(BNX2X_MSG_SP, "context pointer %p", init->cxts[cos]);
-		bnx2x_set_ctx_validation(bp, init->cxts[cos], o->cids[cos]);
-	}
-
-	/* As no ramrod is sent, complete the command immediately  */
-	o->complete_cmd(bp, o, BNX2X_Q_CMD_INIT);
-
-	mmiowb();
-	smp_mb();
-
-	return 0;
-}
-
-static inline int bnx2x_q_send_setup_e1x(struct bnx2x *bp,
-					struct bnx2x_queue_state_params *params)
-{
-	struct bnx2x_queue_sp_obj *o = params->q_obj;
-	struct client_init_ramrod_data *rdata =
-		(struct client_init_ramrod_data *)o->rdata;
-	dma_addr_t data_mapping = o->rdata_mapping;
-	int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
-
-	/* Clear the ramrod data */
-	memset(rdata, 0, sizeof(*rdata));
-
-	/* Fill the ramrod data */
-	bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
-
-	/*
-	 *  No need for an explicit memory barrier here as long we would
-	 *  need to ensure the ordering of writing to the SPQ element
-	 *  and updating of the SPQ producer which involves a memory
-	 *  read and we will have to put a full memory barrier there
-	 *  (inside bnx2x_sp_post()).
-	 */
-
-	return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
-			     U64_HI(data_mapping),
-			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
-}
-
-static inline int bnx2x_q_send_setup_e2(struct bnx2x *bp,
-					struct bnx2x_queue_state_params *params)
-{
-	struct bnx2x_queue_sp_obj *o = params->q_obj;
-	struct client_init_ramrod_data *rdata =
-		(struct client_init_ramrod_data *)o->rdata;
-	dma_addr_t data_mapping = o->rdata_mapping;
-	int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
-
-	/* Clear the ramrod data */
-	memset(rdata, 0, sizeof(*rdata));
-
-	/* Fill the ramrod data */
-	bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
-	bnx2x_q_fill_setup_data_e2(bp, params, rdata);
-
-	/*
-	 *  No need for an explicit memory barrier here as long we would
-	 *  need to ensure the ordering of writing to the SPQ element
-	 *  and updating of the SPQ producer which involves a memory
-	 *  read and we will have to put a full memory barrier there
-	 *  (inside bnx2x_sp_post()).
-	 */
-
-	return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
-			     U64_HI(data_mapping),
-			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
-}
-
-static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp,
-				  struct bnx2x_queue_state_params *params)
-{
-	struct bnx2x_queue_sp_obj *o = params->q_obj;
-	struct tx_queue_init_ramrod_data *rdata =
-		(struct tx_queue_init_ramrod_data *)o->rdata;
-	dma_addr_t data_mapping = o->rdata_mapping;
-	int ramrod = RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP;
-	struct bnx2x_queue_setup_tx_only_params *tx_only_params =
-		&params->params.tx_only;
-	u8 cid_index = tx_only_params->cid_index;
-
-
-	if (cid_index >= o->max_cos) {
-		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
-			  o->cl_id, cid_index);
-		return -EINVAL;
-	}
-
-	DP(BNX2X_MSG_SP, "parameters received: cos: %d sp-id: %d",
-			 tx_only_params->gen_params.cos,
-			 tx_only_params->gen_params.spcl_id);
-
-	/* Clear the ramrod data */
-	memset(rdata, 0, sizeof(*rdata));
-
-	/* Fill the ramrod data */
-	bnx2x_q_fill_setup_tx_only(bp, params, rdata);
-
-	DP(BNX2X_MSG_SP, "sending tx-only ramrod: cid %d, client-id %d,"
-			 "sp-client id %d, cos %d",
-			 o->cids[cid_index],
-			 rdata->general.client_id,
-			 rdata->general.sp_client_id, rdata->general.cos);
-
-	/*
-	 *  No need for an explicit memory barrier here as long we would
-	 *  need to ensure the ordering of writing to the SPQ element
-	 *  and updating of the SPQ producer which involves a memory
-	 *  read and we will have to put a full memory barrier there
-	 *  (inside bnx2x_sp_post()).
-	 */
-
-	return bnx2x_sp_post(bp, ramrod, o->cids[cid_index],
-			     U64_HI(data_mapping),
-			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
-}
-
-static void bnx2x_q_fill_update_data(struct bnx2x *bp,
-				     struct bnx2x_queue_sp_obj *obj,
-				     struct bnx2x_queue_update_params *params,
-				     struct client_update_ramrod_data *data)
-{
-	/* Client ID of the client to update */
-	data->client_id = obj->cl_id;
-
-	/* Function ID of the client to update */
-	data->func_id = obj->func_id;
-
-	/* Default VLAN value */
-	data->default_vlan = cpu_to_le16(params->def_vlan);
-
-	/* Inner VLAN stripping */
-	data->inner_vlan_removal_enable_flg =
-		test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM, &params->update_flags);
-	data->inner_vlan_removal_change_flg =
-		test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM_CHNG,
-			 &params->update_flags);
-
-	/* Outer VLAN sripping */
-	data->outer_vlan_removal_enable_flg =
-		test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM, &params->update_flags);
-	data->outer_vlan_removal_change_flg =
-		test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM_CHNG,
-			 &params->update_flags);
-
-	/* Drop packets that have source MAC that doesn't belong to this
-	 * Queue.
-	 */
-	data->anti_spoofing_enable_flg =
-		test_bit(BNX2X_Q_UPDATE_ANTI_SPOOF, &params->update_flags);
-	data->anti_spoofing_change_flg =
-		test_bit(BNX2X_Q_UPDATE_ANTI_SPOOF_CHNG, &params->update_flags);
-
-	/* Activate/Deactivate */
-	data->activate_flg =
-		test_bit(BNX2X_Q_UPDATE_ACTIVATE, &params->update_flags);
-	data->activate_change_flg =
-		test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &params->update_flags);
-
-	/* Enable default VLAN */
-	data->default_vlan_enable_flg =
-		test_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN, &params->update_flags);
-	data->default_vlan_change_flg =
-		test_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
-			 &params->update_flags);
-
-	/* silent vlan removal */
-	data->silent_vlan_change_flg =
-		test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
-			 &params->update_flags);
-	data->silent_vlan_removal_flg =
-		test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM, &params->update_flags);
-	data->silent_vlan_value = cpu_to_le16(params->silent_removal_value);
-	data->silent_vlan_mask = cpu_to_le16(params->silent_removal_mask);
-}
-
-static inline int bnx2x_q_send_update(struct bnx2x *bp,
-				      struct bnx2x_queue_state_params *params)
-{
-	struct bnx2x_queue_sp_obj *o = params->q_obj;
-	struct client_update_ramrod_data *rdata =
-		(struct client_update_ramrod_data *)o->rdata;
-	dma_addr_t data_mapping = o->rdata_mapping;
-	struct bnx2x_queue_update_params *update_params =
-		&params->params.update;
-	u8 cid_index = update_params->cid_index;
-
-	if (cid_index >= o->max_cos) {
-		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
-			  o->cl_id, cid_index);
-		return -EINVAL;
-	}
-
-
-	/* Clear the ramrod data */
-	memset(rdata, 0, sizeof(*rdata));
-
-	/* Fill the ramrod data */
-	bnx2x_q_fill_update_data(bp, o, update_params, rdata);
-
-	/*
-	 *  No need for an explicit memory barrier here as long we would
-	 *  need to ensure the ordering of writing to the SPQ element
-	 *  and updating of the SPQ producer which involves a memory
-	 *  read and we will have to put a full memory barrier there
-	 *  (inside bnx2x_sp_post()).
-	 */
-
-	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE,
-			     o->cids[cid_index], U64_HI(data_mapping),
-			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
-}
-
-/**
- * bnx2x_q_send_deactivate - send DEACTIVATE command
- *
- * @bp:		device handle
- * @params:
- *
- * implemented using the UPDATE command.
- */
-static inline int bnx2x_q_send_deactivate(struct bnx2x *bp,
-					struct bnx2x_queue_state_params *params)
-{
-	struct bnx2x_queue_update_params *update = &params->params.update;
-
-	memset(update, 0, sizeof(*update));
-
-	__set_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags);
-
-	return bnx2x_q_send_update(bp, params);
-}
-
-/**
- * bnx2x_q_send_activate - send ACTIVATE command
- *
- * @bp:		device handle
- * @params:
- *
- * implemented using the UPDATE command.
- */
-static inline int bnx2x_q_send_activate(struct bnx2x *bp,
-					struct bnx2x_queue_state_params *params)
-{
-	struct bnx2x_queue_update_params *update = &params->params.update;
-
-	memset(update, 0, sizeof(*update));
-
-	__set_bit(BNX2X_Q_UPDATE_ACTIVATE, &update->update_flags);
-	__set_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags);
-
-	return bnx2x_q_send_update(bp, params);
-}
-
-static inline int bnx2x_q_send_update_tpa(struct bnx2x *bp,
-					struct bnx2x_queue_state_params *params)
-{
-	/* TODO: Not implemented yet. */
-	return -1;
-}
-
-static inline int bnx2x_q_send_halt(struct bnx2x *bp,
-				    struct bnx2x_queue_state_params *params)
-{
-	struct bnx2x_queue_sp_obj *o = params->q_obj;
-
-	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT,
-			     o->cids[BNX2X_PRIMARY_CID_INDEX], 0, o->cl_id,
-			     ETH_CONNECTION_TYPE);
-}
-
-static inline int bnx2x_q_send_cfc_del(struct bnx2x *bp,
-				       struct bnx2x_queue_state_params *params)
-{
-	struct bnx2x_queue_sp_obj *o = params->q_obj;
-	u8 cid_idx = params->params.cfc_del.cid_index;
-
-	if (cid_idx >= o->max_cos) {
-		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
-			  o->cl_id, cid_idx);
-		return -EINVAL;
-	}
-
-	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL,
-			     o->cids[cid_idx], 0, 0, NONE_CONNECTION_TYPE);
-}
-
-static inline int bnx2x_q_send_terminate(struct bnx2x *bp,
-					struct bnx2x_queue_state_params *params)
-{
-	struct bnx2x_queue_sp_obj *o = params->q_obj;
-	u8 cid_index = params->params.terminate.cid_index;
-
-	if (cid_index >= o->max_cos) {
-		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
-			  o->cl_id, cid_index);
-		return -EINVAL;
-	}
-
-	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE,
-			     o->cids[cid_index], 0, 0, ETH_CONNECTION_TYPE);
-}
-
-static inline int bnx2x_q_send_empty(struct bnx2x *bp,
-				     struct bnx2x_queue_state_params *params)
-{
-	struct bnx2x_queue_sp_obj *o = params->q_obj;
-
-	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_EMPTY,
-			     o->cids[BNX2X_PRIMARY_CID_INDEX], 0, 0,
-			     ETH_CONNECTION_TYPE);
-}
-
-static inline int bnx2x_queue_send_cmd_cmn(struct bnx2x *bp,
-					struct bnx2x_queue_state_params *params)
-{
-	switch (params->cmd) {
-	case BNX2X_Q_CMD_INIT:
-		return bnx2x_q_init(bp, params);
-	case BNX2X_Q_CMD_SETUP_TX_ONLY:
-		return bnx2x_q_send_setup_tx_only(bp, params);
-	case BNX2X_Q_CMD_DEACTIVATE:
-		return bnx2x_q_send_deactivate(bp, params);
-	case BNX2X_Q_CMD_ACTIVATE:
-		return bnx2x_q_send_activate(bp, params);
-	case BNX2X_Q_CMD_UPDATE:
-		return bnx2x_q_send_update(bp, params);
-	case BNX2X_Q_CMD_UPDATE_TPA:
-		return bnx2x_q_send_update_tpa(bp, params);
-	case BNX2X_Q_CMD_HALT:
-		return bnx2x_q_send_halt(bp, params);
-	case BNX2X_Q_CMD_CFC_DEL:
-		return bnx2x_q_send_cfc_del(bp, params);
-	case BNX2X_Q_CMD_TERMINATE:
-		return bnx2x_q_send_terminate(bp, params);
-	case BNX2X_Q_CMD_EMPTY:
-		return bnx2x_q_send_empty(bp, params);
-	default:
-		BNX2X_ERR("Unknown command: %d\n", params->cmd);
-		return -EINVAL;
-	}
-}
-
-static int bnx2x_queue_send_cmd_e1x(struct bnx2x *bp,
-				    struct bnx2x_queue_state_params *params)
-{
-	switch (params->cmd) {
-	case BNX2X_Q_CMD_SETUP:
-		return bnx2x_q_send_setup_e1x(bp, params);
-	case BNX2X_Q_CMD_INIT:
-	case BNX2X_Q_CMD_SETUP_TX_ONLY:
-	case BNX2X_Q_CMD_DEACTIVATE:
-	case BNX2X_Q_CMD_ACTIVATE:
-	case BNX2X_Q_CMD_UPDATE:
-	case BNX2X_Q_CMD_UPDATE_TPA:
-	case BNX2X_Q_CMD_HALT:
-	case BNX2X_Q_CMD_CFC_DEL:
-	case BNX2X_Q_CMD_TERMINATE:
-	case BNX2X_Q_CMD_EMPTY:
-		return bnx2x_queue_send_cmd_cmn(bp, params);
-	default:
-		BNX2X_ERR("Unknown command: %d\n", params->cmd);
-		return -EINVAL;
-	}
-}
-
-static int bnx2x_queue_send_cmd_e2(struct bnx2x *bp,
-				   struct bnx2x_queue_state_params *params)
-{
-	switch (params->cmd) {
-	case BNX2X_Q_CMD_SETUP:
-		return bnx2x_q_send_setup_e2(bp, params);
-	case BNX2X_Q_CMD_INIT:
-	case BNX2X_Q_CMD_SETUP_TX_ONLY:
-	case BNX2X_Q_CMD_DEACTIVATE:
-	case BNX2X_Q_CMD_ACTIVATE:
-	case BNX2X_Q_CMD_UPDATE:
-	case BNX2X_Q_CMD_UPDATE_TPA:
-	case BNX2X_Q_CMD_HALT:
-	case BNX2X_Q_CMD_CFC_DEL:
-	case BNX2X_Q_CMD_TERMINATE:
-	case BNX2X_Q_CMD_EMPTY:
-		return bnx2x_queue_send_cmd_cmn(bp, params);
-	default:
-		BNX2X_ERR("Unknown command: %d\n", params->cmd);
-		return -EINVAL;
-	}
-}
-
-/**
- * bnx2x_queue_chk_transition - check state machine of a regular Queue
- *
- * @bp:		device handle
- * @o:
- * @params:
- *
- * (not Forwarding)
- * It both checks if the requested command is legal in a current
- * state and, if it's legal, sets a `next_state' in the object
- * that will be used in the completion flow to set the `state'
- * of the object.
- *
- * returns 0 if a requested command is a legal transition,
- *         -EINVAL otherwise.
- */
-static int bnx2x_queue_chk_transition(struct bnx2x *bp,
-				      struct bnx2x_queue_sp_obj *o,
-				      struct bnx2x_queue_state_params *params)
-{
-	enum bnx2x_q_state state = o->state, next_state = BNX2X_Q_STATE_MAX;
-	enum bnx2x_queue_cmd cmd = params->cmd;
-	struct bnx2x_queue_update_params *update_params =
-		 &params->params.update;
-	u8 next_tx_only = o->num_tx_only;
-
-	/*
-	 * Forget all pending for completion commands if a driver only state
-	 * transition has been requested.
-	 */
-	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
-		o->pending = 0;
-		o->next_state = BNX2X_Q_STATE_MAX;
-	}
-
-	/*
-	 * Don't allow a next state transition if we are in the middle of
-	 * the previous one.
-	 */
-	if (o->pending)
-		return -EBUSY;
-
-	switch (state) {
-	case BNX2X_Q_STATE_RESET:
-		if (cmd == BNX2X_Q_CMD_INIT)
-			next_state = BNX2X_Q_STATE_INITIALIZED;
-
-		break;
-	case BNX2X_Q_STATE_INITIALIZED:
-		if (cmd == BNX2X_Q_CMD_SETUP) {
-			if (test_bit(BNX2X_Q_FLG_ACTIVE,
-				     &params->params.setup.flags))
-				next_state = BNX2X_Q_STATE_ACTIVE;
-			else
-				next_state = BNX2X_Q_STATE_INACTIVE;
-		}
-
-		break;
-	case BNX2X_Q_STATE_ACTIVE:
-		if (cmd == BNX2X_Q_CMD_DEACTIVATE)
-			next_state = BNX2X_Q_STATE_INACTIVE;
-
-		else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
-			 (cmd == BNX2X_Q_CMD_UPDATE_TPA))
-			next_state = BNX2X_Q_STATE_ACTIVE;
-
-		else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) {
-			next_state = BNX2X_Q_STATE_MULTI_COS;
-			next_tx_only = 1;
-		}
-
-		else if (cmd == BNX2X_Q_CMD_HALT)
-			next_state = BNX2X_Q_STATE_STOPPED;
-
-		else if (cmd == BNX2X_Q_CMD_UPDATE) {
-			/* If "active" state change is requested, update the
-			 *  state accordingly.
-			 */
-			if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
-				     &update_params->update_flags) &&
-			    !test_bit(BNX2X_Q_UPDATE_ACTIVATE,
-				      &update_params->update_flags))
-				next_state = BNX2X_Q_STATE_INACTIVE;
-			else
-				next_state = BNX2X_Q_STATE_ACTIVE;
-		}
-
-		break;
-	case BNX2X_Q_STATE_MULTI_COS:
-		if (cmd == BNX2X_Q_CMD_TERMINATE)
-			next_state = BNX2X_Q_STATE_MCOS_TERMINATED;
-
-		else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) {
-			next_state = BNX2X_Q_STATE_MULTI_COS;
-			next_tx_only = o->num_tx_only + 1;
-		}
-
-		else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
-			 (cmd == BNX2X_Q_CMD_UPDATE_TPA))
-			next_state = BNX2X_Q_STATE_MULTI_COS;
-
-		else if (cmd == BNX2X_Q_CMD_UPDATE) {
-			/* If "active" state change is requested, update the
-			 *  state accordingly.
-			 */
-			if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
-				     &update_params->update_flags) &&
-			    !test_bit(BNX2X_Q_UPDATE_ACTIVATE,
-				      &update_params->update_flags))
-				next_state = BNX2X_Q_STATE_INACTIVE;
-			else
-				next_state = BNX2X_Q_STATE_MULTI_COS;
-		}
-
-		break;
-	case BNX2X_Q_STATE_MCOS_TERMINATED:
-		if (cmd == BNX2X_Q_CMD_CFC_DEL) {
-			next_tx_only = o->num_tx_only - 1;
-			if (next_tx_only == 0)
-				next_state = BNX2X_Q_STATE_ACTIVE;
-			else
-				next_state = BNX2X_Q_STATE_MULTI_COS;
-		}
-
-		break;
-	case BNX2X_Q_STATE_INACTIVE:
-		if (cmd == BNX2X_Q_CMD_ACTIVATE)
-			next_state = BNX2X_Q_STATE_ACTIVE;
-
-		else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
-			 (cmd == BNX2X_Q_CMD_UPDATE_TPA))
-			next_state = BNX2X_Q_STATE_INACTIVE;
-
-		else if (cmd == BNX2X_Q_CMD_HALT)
-			next_state = BNX2X_Q_STATE_STOPPED;
-
-		else if (cmd == BNX2X_Q_CMD_UPDATE) {
-			/* If "active" state change is requested, update the
-			 * state accordingly.
-			 */
-			if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
-				     &update_params->update_flags) &&
-			    test_bit(BNX2X_Q_UPDATE_ACTIVATE,
-				     &update_params->update_flags)){
-				if (o->num_tx_only == 0)
-					next_state = BNX2X_Q_STATE_ACTIVE;
-				else /* tx only queues exist for this queue */
-					next_state = BNX2X_Q_STATE_MULTI_COS;
-			} else
-				next_state = BNX2X_Q_STATE_INACTIVE;
-		}
-
-		break;
-	case BNX2X_Q_STATE_STOPPED:
-		if (cmd == BNX2X_Q_CMD_TERMINATE)
-			next_state = BNX2X_Q_STATE_TERMINATED;
-
-		break;
-	case BNX2X_Q_STATE_TERMINATED:
-		if (cmd == BNX2X_Q_CMD_CFC_DEL)
-			next_state = BNX2X_Q_STATE_RESET;
-
-		break;
-	default:
-		BNX2X_ERR("Illegal state: %d\n", state);
-	}
-
-	/* Transition is assured */
-	if (next_state != BNX2X_Q_STATE_MAX) {
-		DP(BNX2X_MSG_SP, "Good state transition: %d(%d)->%d\n",
-				 state, cmd, next_state);
-		o->next_state = next_state;
-		o->next_tx_only = next_tx_only;
-		return 0;
-	}
-
-	DP(BNX2X_MSG_SP, "Bad state transition request: %d %d\n", state, cmd);
-
-	return -EINVAL;
-}
-
-void bnx2x_init_queue_obj(struct bnx2x *bp,
-			  struct bnx2x_queue_sp_obj *obj,
-			  u8 cl_id, u32 *cids, u8 cid_cnt, u8 func_id,
-			  void *rdata,
-			  dma_addr_t rdata_mapping, unsigned long type)
-{
-	memset(obj, 0, sizeof(*obj));
-
-	/* We support only BNX2X_MULTI_TX_COS Tx CoS at the moment */
-	BUG_ON(BNX2X_MULTI_TX_COS < cid_cnt);
-
-	memcpy(obj->cids, cids, sizeof(obj->cids[0]) * cid_cnt);
-	obj->max_cos = cid_cnt;
-	obj->cl_id = cl_id;
-	obj->func_id = func_id;
-	obj->rdata = rdata;
-	obj->rdata_mapping = rdata_mapping;
-	obj->type = type;
-	obj->next_state = BNX2X_Q_STATE_MAX;
-
-	if (CHIP_IS_E1x(bp))
-		obj->send_cmd = bnx2x_queue_send_cmd_e1x;
-	else
-		obj->send_cmd = bnx2x_queue_send_cmd_e2;
-
-	obj->check_transition = bnx2x_queue_chk_transition;
-
-	obj->complete_cmd = bnx2x_queue_comp_cmd;
-	obj->wait_comp = bnx2x_queue_wait_comp;
-	obj->set_pending = bnx2x_queue_set_pending;
-}
-
-void bnx2x_queue_set_cos_cid(struct bnx2x *bp,
-			     struct bnx2x_queue_sp_obj *obj,
-			     u32 cid, u8 index)
-{
-	obj->cids[index] = cid;
-}
-
-/********************** Function state object *********************************/
-enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp,
-					   struct bnx2x_func_sp_obj *o)
-{
-	/* in the middle of transaction - return INVALID state */
-	if (o->pending)
-		return BNX2X_F_STATE_MAX;
-
-	/*
-	 * unsure the order of reading of o->pending and o->state
-	 * o->pending should be read first
-	 */
-	rmb();
-
-	return o->state;
-}
-
-static int bnx2x_func_wait_comp(struct bnx2x *bp,
-				struct bnx2x_func_sp_obj *o,
-				enum bnx2x_func_cmd cmd)
-{
-	return bnx2x_state_wait(bp, cmd, &o->pending);
-}
-
-/**
- * bnx2x_func_state_change_comp - complete the state machine transition
- *
- * @bp:		device handle
- * @o:
- * @cmd:
- *
- * Called on state change transition. Completes the state
- * machine transition only - no HW interaction.
- */
-static inline int bnx2x_func_state_change_comp(struct bnx2x *bp,
-					       struct bnx2x_func_sp_obj *o,
-					       enum bnx2x_func_cmd cmd)
-{
-	unsigned long cur_pending = o->pending;
-
-	if (!test_and_clear_bit(cmd, &cur_pending)) {
-		BNX2X_ERR("Bad MC reply %d for func %d in state %d "
-			  "pending 0x%lx, next_state %d\n", cmd, BP_FUNC(bp),
-			  o->state, cur_pending, o->next_state);
-		return -EINVAL;
-	}
-
-	DP(BNX2X_MSG_SP, "Completing command %d for func %d, setting state to "
-			 "%d\n", cmd, BP_FUNC(bp), o->next_state);
-
-	o->state = o->next_state;
-	o->next_state = BNX2X_F_STATE_MAX;
-
-	/* It's important that o->state and o->next_state are
-	 * updated before o->pending.
-	 */
-	wmb();
-
-	clear_bit(cmd, &o->pending);
-	smp_mb__after_clear_bit();
-
-	return 0;
-}
-
-/**
- * bnx2x_func_comp_cmd - complete the state change command
- *
- * @bp:		device handle
- * @o:
- * @cmd:
- *
- * Checks that the arrived completion is expected.
- */
-static int bnx2x_func_comp_cmd(struct bnx2x *bp,
-			       struct bnx2x_func_sp_obj *o,
-			       enum bnx2x_func_cmd cmd)
-{
-	/* Complete the state machine part first, check if it's a
-	 * legal completion.
-	 */
-	int rc = bnx2x_func_state_change_comp(bp, o, cmd);
-	return rc;
-}
-
-/**
- * bnx2x_func_chk_transition - perform function state machine transition
- *
- * @bp:		device handle
- * @o:
- * @params:
- *
- * It both checks if the requested command is legal in a current
- * state and, if it's legal, sets a `next_state' in the object
- * that will be used in the completion flow to set the `state'
- * of the object.
- *
- * returns 0 if a requested command is a legal transition,
- *         -EINVAL otherwise.
- */
-static int bnx2x_func_chk_transition(struct bnx2x *bp,
-				     struct bnx2x_func_sp_obj *o,
-				     struct bnx2x_func_state_params *params)
-{
-	enum bnx2x_func_state state = o->state, next_state = BNX2X_F_STATE_MAX;
-	enum bnx2x_func_cmd cmd = params->cmd;
-
-	/*
-	 * Forget all pending for completion commands if a driver only state
-	 * transition has been requested.
-	 */
-	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
-		o->pending = 0;
-		o->next_state = BNX2X_F_STATE_MAX;
-	}
-
-	/*
-	 * Don't allow a next state transition if we are in the middle of
-	 * the previous one.
-	 */
-	if (o->pending)
-		return -EBUSY;
-
-	switch (state) {
-	case BNX2X_F_STATE_RESET:
-		if (cmd == BNX2X_F_CMD_HW_INIT)
-			next_state = BNX2X_F_STATE_INITIALIZED;
-
-		break;
-	case BNX2X_F_STATE_INITIALIZED:
-		if (cmd == BNX2X_F_CMD_START)
-			next_state = BNX2X_F_STATE_STARTED;
-
-		else if (cmd == BNX2X_F_CMD_HW_RESET)
-			next_state = BNX2X_F_STATE_RESET;
-
-		break;
-	case BNX2X_F_STATE_STARTED:
-		if (cmd == BNX2X_F_CMD_STOP)
-			next_state = BNX2X_F_STATE_INITIALIZED;
-		else if (cmd == BNX2X_F_CMD_TX_STOP)
-			next_state = BNX2X_F_STATE_TX_STOPPED;
-
-		break;
-	case BNX2X_F_STATE_TX_STOPPED:
-		if (cmd == BNX2X_F_CMD_TX_START)
-			next_state = BNX2X_F_STATE_STARTED;
-
-		break;
-	default:
-		BNX2X_ERR("Unknown state: %d\n", state);
-	}
-
-	/* Transition is assured */
-	if (next_state != BNX2X_F_STATE_MAX) {
-		DP(BNX2X_MSG_SP, "Good function state transition: %d(%d)->%d\n",
-				 state, cmd, next_state);
-		o->next_state = next_state;
-		return 0;
-	}
-
-	DP(BNX2X_MSG_SP, "Bad function state transition request: %d %d\n",
-			 state, cmd);
-
-	return -EINVAL;
-}
-
-/**
- * bnx2x_func_init_func - performs HW init at function stage
- *
- * @bp:		device handle
- * @drv:
- *
- * Init HW when the current phase is
- * FW_MSG_CODE_DRV_LOAD_FUNCTION: initialize only FUNCTION-only
- * HW blocks.
- */
-static inline int bnx2x_func_init_func(struct bnx2x *bp,
-				       const struct bnx2x_func_sp_drv_ops *drv)
-{
-	return drv->init_hw_func(bp);
-}
-
-/**
- * bnx2x_func_init_port - performs HW init at port stage
- *
- * @bp:		device handle
- * @drv:
- *
- * Init HW when the current phase is
- * FW_MSG_CODE_DRV_LOAD_PORT: initialize PORT-only and
- * FUNCTION-only HW blocks.
- *
- */
-static inline int bnx2x_func_init_port(struct bnx2x *bp,
-				       const struct bnx2x_func_sp_drv_ops *drv)
-{
-	int rc = drv->init_hw_port(bp);
-	if (rc)
-		return rc;
-
-	return bnx2x_func_init_func(bp, drv);
-}
-
-/**
- * bnx2x_func_init_cmn_chip - performs HW init at chip-common stage
- *
- * @bp:		device handle
- * @drv:
- *
- * Init HW when the current phase is
- * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON_CHIP,
- * PORT-only and FUNCTION-only HW blocks.
- */
-static inline int bnx2x_func_init_cmn_chip(struct bnx2x *bp,
-					const struct bnx2x_func_sp_drv_ops *drv)
-{
-	int rc = drv->init_hw_cmn_chip(bp);
-	if (rc)
-		return rc;
-
-	return bnx2x_func_init_port(bp, drv);
-}
-
-/**
- * bnx2x_func_init_cmn - performs HW init at common stage
- *
- * @bp:		device handle
- * @drv:
- *
- * Init HW when the current phase is
- * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON,
- * PORT-only and FUNCTION-only HW blocks.
- */
-static inline int bnx2x_func_init_cmn(struct bnx2x *bp,
-				      const struct bnx2x_func_sp_drv_ops *drv)
-{
-	int rc = drv->init_hw_cmn(bp);
-	if (rc)
-		return rc;
-
-	return bnx2x_func_init_port(bp, drv);
-}
-
-static int bnx2x_func_hw_init(struct bnx2x *bp,
-			      struct bnx2x_func_state_params *params)
-{
-	u32 load_code = params->params.hw_init.load_phase;
-	struct bnx2x_func_sp_obj *o = params->f_obj;
-	const struct bnx2x_func_sp_drv_ops *drv = o->drv;
-	int rc = 0;
-
-	DP(BNX2X_MSG_SP, "function %d  load_code %x\n",
-			 BP_ABS_FUNC(bp), load_code);
-
-	/* Prepare buffers for unzipping the FW */
-	rc = drv->gunzip_init(bp);
-	if (rc)
-		return rc;
-
-	/* Prepare FW */
-	rc = drv->init_fw(bp);
-	if (rc) {
-		BNX2X_ERR("Error loading firmware\n");
-		goto fw_init_err;
-	}
-
-	/* Handle the beginning of COMMON_XXX pases separatelly... */
-	switch (load_code) {
-	case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
-		rc = bnx2x_func_init_cmn_chip(bp, drv);
-		if (rc)
-			goto init_hw_err;
-
-		break;
-	case FW_MSG_CODE_DRV_LOAD_COMMON:
-		rc = bnx2x_func_init_cmn(bp, drv);
-		if (rc)
-			goto init_hw_err;
-
-		break;
-	case FW_MSG_CODE_DRV_LOAD_PORT:
-		rc = bnx2x_func_init_port(bp, drv);
-		if (rc)
-			goto init_hw_err;
-
-		break;
-	case FW_MSG_CODE_DRV_LOAD_FUNCTION:
-		rc = bnx2x_func_init_func(bp, drv);
-		if (rc)
-			goto init_hw_err;
-
-		break;
-	default:
-		BNX2X_ERR("Unknown load_code (0x%x) from MCP\n", load_code);
-		rc = -EINVAL;
-	}
-
-init_hw_err:
-	drv->release_fw(bp);
-
-fw_init_err:
-	drv->gunzip_end(bp);
-
-	/* In case of success, complete the comand immediatelly: no ramrods
-	 * have been sent.
-	 */
-	if (!rc)
-		o->complete_cmd(bp, o, BNX2X_F_CMD_HW_INIT);
-
-	return rc;
-}
-
-/**
- * bnx2x_func_reset_func - reset HW at function stage
- *
- * @bp:		device handle
- * @drv:
- *
- * Reset HW at FW_MSG_CODE_DRV_UNLOAD_FUNCTION stage: reset only
- * FUNCTION-only HW blocks.
- */
-static inline void bnx2x_func_reset_func(struct bnx2x *bp,
-					const struct bnx2x_func_sp_drv_ops *drv)
-{
-	drv->reset_hw_func(bp);
-}
-
-/**
- * bnx2x_func_reset_port - reser HW at port stage
- *
- * @bp:		device handle
- * @drv:
- *
- * Reset HW at FW_MSG_CODE_DRV_UNLOAD_PORT stage: reset
- * FUNCTION-only and PORT-only HW blocks.
- *
- *                 !!!IMPORTANT!!!
- *
- * It's important to call reset_port before reset_func() as the last thing
- * reset_func does is pf_disable() thus disabling PGLUE_B, which
- * makes impossible any DMAE transactions.
- */
-static inline void bnx2x_func_reset_port(struct bnx2x *bp,
-					const struct bnx2x_func_sp_drv_ops *drv)
-{
-	drv->reset_hw_port(bp);
-	bnx2x_func_reset_func(bp, drv);
-}
-
-/**
- * bnx2x_func_reset_cmn - reser HW at common stage
- *
- * @bp:		device handle
- * @drv:
- *
- * Reset HW at FW_MSG_CODE_DRV_UNLOAD_COMMON and
- * FW_MSG_CODE_DRV_UNLOAD_COMMON_CHIP stages: reset COMMON,
- * COMMON_CHIP, FUNCTION-only and PORT-only HW blocks.
- */
-static inline void bnx2x_func_reset_cmn(struct bnx2x *bp,
-					const struct bnx2x_func_sp_drv_ops *drv)
-{
-	bnx2x_func_reset_port(bp, drv);
-	drv->reset_hw_cmn(bp);
-}
-
-
-static inline int bnx2x_func_hw_reset(struct bnx2x *bp,
-				      struct bnx2x_func_state_params *params)
-{
-	u32 reset_phase = params->params.hw_reset.reset_phase;
-	struct bnx2x_func_sp_obj *o = params->f_obj;
-	const struct bnx2x_func_sp_drv_ops *drv = o->drv;
-
-	DP(BNX2X_MSG_SP, "function %d  reset_phase %x\n", BP_ABS_FUNC(bp),
-			 reset_phase);
-
-	switch (reset_phase) {
-	case FW_MSG_CODE_DRV_UNLOAD_COMMON:
-		bnx2x_func_reset_cmn(bp, drv);
-		break;
-	case FW_MSG_CODE_DRV_UNLOAD_PORT:
-		bnx2x_func_reset_port(bp, drv);
-		break;
-	case FW_MSG_CODE_DRV_UNLOAD_FUNCTION:
-		bnx2x_func_reset_func(bp, drv);
-		break;
-	default:
-		BNX2X_ERR("Unknown reset_phase (0x%x) from MCP\n",
-			   reset_phase);
-		break;
-	}
-
-	/* Complete the comand immediatelly: no ramrods have been sent. */
-	o->complete_cmd(bp, o, BNX2X_F_CMD_HW_RESET);
-
-	return 0;
-}
-
-static inline int bnx2x_func_send_start(struct bnx2x *bp,
-					struct bnx2x_func_state_params *params)
-{
-	struct bnx2x_func_sp_obj *o = params->f_obj;
-	struct function_start_data *rdata =
-		(struct function_start_data *)o->rdata;
-	dma_addr_t data_mapping = o->rdata_mapping;
-	struct bnx2x_func_start_params *start_params = &params->params.start;
-
-	memset(rdata, 0, sizeof(*rdata));
-
-	/* Fill the ramrod data with provided parameters */
-	rdata->function_mode = cpu_to_le16(start_params->mf_mode);
-	rdata->sd_vlan_tag   = start_params->sd_vlan_tag;
-	rdata->path_id       = BP_PATH(bp);
-	rdata->network_cos_mode = start_params->network_cos_mode;
-
-	/*
-	 *  No need for an explicit memory barrier here as long we would
-	 *  need to ensure the ordering of writing to the SPQ element
-	 *  and updating of the SPQ producer which involves a memory
-	 *  read and we will have to put a full memory barrier there
-	 *  (inside bnx2x_sp_post()).
-	 */
-
-	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0,
-			     U64_HI(data_mapping),
-			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
-}
-
-static inline int bnx2x_func_send_stop(struct bnx2x *bp,
-				       struct bnx2x_func_state_params *params)
-{
-	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0, 0,
-			     NONE_CONNECTION_TYPE);
-}
-
-static inline int bnx2x_func_send_tx_stop(struct bnx2x *bp,
-				       struct bnx2x_func_state_params *params)
-{
-	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC, 0, 0, 0,
-			     NONE_CONNECTION_TYPE);
-}
-static inline int bnx2x_func_send_tx_start(struct bnx2x *bp,
-				       struct bnx2x_func_state_params *params)
-{
-	struct bnx2x_func_sp_obj *o = params->f_obj;
-	struct flow_control_configuration *rdata =
-		(struct flow_control_configuration *)o->rdata;
-	dma_addr_t data_mapping = o->rdata_mapping;
-	struct bnx2x_func_tx_start_params *tx_start_params =
-		&params->params.tx_start;
-	int i;
-
-	memset(rdata, 0, sizeof(*rdata));
-
-	rdata->dcb_enabled = tx_start_params->dcb_enabled;
-	rdata->dcb_version = tx_start_params->dcb_version;
-	rdata->dont_add_pri_0_en = tx_start_params->dont_add_pri_0_en;
-
-	for (i = 0; i < ARRAY_SIZE(rdata->traffic_type_to_priority_cos); i++)
-		rdata->traffic_type_to_priority_cos[i] =
-			tx_start_params->traffic_type_to_priority_cos[i];
-
-	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC, 0,
-			     U64_HI(data_mapping),
-			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
-}
-
-static int bnx2x_func_send_cmd(struct bnx2x *bp,
-			       struct bnx2x_func_state_params *params)
-{
-	switch (params->cmd) {
-	case BNX2X_F_CMD_HW_INIT:
-		return bnx2x_func_hw_init(bp, params);
-	case BNX2X_F_CMD_START:
-		return bnx2x_func_send_start(bp, params);
-	case BNX2X_F_CMD_STOP:
-		return bnx2x_func_send_stop(bp, params);
-	case BNX2X_F_CMD_HW_RESET:
-		return bnx2x_func_hw_reset(bp, params);
-	case BNX2X_F_CMD_TX_STOP:
-		return bnx2x_func_send_tx_stop(bp, params);
-	case BNX2X_F_CMD_TX_START:
-		return bnx2x_func_send_tx_start(bp, params);
-	default:
-		BNX2X_ERR("Unknown command: %d\n", params->cmd);
-		return -EINVAL;
-	}
-}
-
-void bnx2x_init_func_obj(struct bnx2x *bp,
-			 struct bnx2x_func_sp_obj *obj,
-			 void *rdata, dma_addr_t rdata_mapping,
-			 struct bnx2x_func_sp_drv_ops *drv_iface)
-{
-	memset(obj, 0, sizeof(*obj));
-
-	mutex_init(&obj->one_pending_mutex);
-
-	obj->rdata = rdata;
-	obj->rdata_mapping = rdata_mapping;
-
-	obj->send_cmd = bnx2x_func_send_cmd;
-	obj->check_transition = bnx2x_func_chk_transition;
-	obj->complete_cmd = bnx2x_func_comp_cmd;
-	obj->wait_comp = bnx2x_func_wait_comp;
-
-	obj->drv = drv_iface;
-}
-
-/**
- * bnx2x_func_state_change - perform Function state change transition
- *
- * @bp:		device handle
- * @params:	parameters to perform the transaction
- *
- * returns 0 in case of successfully completed transition,
- *         negative error code in case of failure, positive
- *         (EBUSY) value if there is a completion to that is
- *         still pending (possible only if RAMROD_COMP_WAIT is
- *         not set in params->ramrod_flags for asynchronous
- *         commands).
- */
-int bnx2x_func_state_change(struct bnx2x *bp,
-			    struct bnx2x_func_state_params *params)
-{
-	struct bnx2x_func_sp_obj *o = params->f_obj;
-	int rc;
-	enum bnx2x_func_cmd cmd = params->cmd;
-	unsigned long *pending = &o->pending;
-
-	mutex_lock(&o->one_pending_mutex);
-
-	/* Check that the requested transition is legal */
-	if (o->check_transition(bp, o, params)) {
-		mutex_unlock(&o->one_pending_mutex);
-		return -EINVAL;
-	}
-
-	/* Set "pending" bit */
-	set_bit(cmd, pending);
-
-	/* Don't send a command if only driver cleanup was requested */
-	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
-		bnx2x_func_state_change_comp(bp, o, cmd);
-		mutex_unlock(&o->one_pending_mutex);
-	} else {
-		/* Send a ramrod */
-		rc = o->send_cmd(bp, params);
-
-		mutex_unlock(&o->one_pending_mutex);
-
-		if (rc) {
-			o->next_state = BNX2X_F_STATE_MAX;
-			clear_bit(cmd, pending);
-			smp_mb__after_clear_bit();
-			return rc;
-		}
-
-		if (test_bit(RAMROD_COMP_WAIT, &params->ramrod_flags)) {
-			rc = o->wait_comp(bp, o, cmd);
-			if (rc)
-				return rc;
-
-			return 0;
-		}
-	}
-
-	return !!test_bit(cmd, pending);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_sp.h linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_sp.h
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_sp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_sp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1297 +0,0 @@
-/* bnx2x_sp.h: Broadcom Everest network driver.
- *
- * Copyright 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
- * under the terms of the GNU General Public License version 2, available
- * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
- *
- * Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a
- * license other than the GPL, without Broadcom's express prior written
- * consent.
- *
- * Maintained by: Eilon Greenstein <eilong@broadcom.com>
- * Written by: Vladislav Zolotarov
- *
- */
-#ifndef BNX2X_SP_VERBS
-#define BNX2X_SP_VERBS
-
-struct bnx2x;
-struct eth_context;
-
-/* Bits representing general command's configuration */
-enum {
-	RAMROD_TX,
-	RAMROD_RX,
-	/* Wait until all pending commands complete */
-	RAMROD_COMP_WAIT,
-	/* Don't send a ramrod, only update a registry */
-	RAMROD_DRV_CLR_ONLY,
-	/* Configure HW according to the current object state */
-	RAMROD_RESTORE,
-	 /* Execute the next command now */
-	RAMROD_EXEC,
-	/*
-	 * Don't add a new command and continue execution of posponed
-	 * commands. If not set a new command will be added to the
-	 * pending commands list.
-	 */
-	RAMROD_CONT,
-};
-
-typedef enum {
-	BNX2X_OBJ_TYPE_RX,
-	BNX2X_OBJ_TYPE_TX,
-	BNX2X_OBJ_TYPE_RX_TX,
-} bnx2x_obj_type;
-
-/* Filtering states */
-enum {
-	BNX2X_FILTER_MAC_PENDING,
-	BNX2X_FILTER_VLAN_PENDING,
-	BNX2X_FILTER_VLAN_MAC_PENDING,
-	BNX2X_FILTER_RX_MODE_PENDING,
-	BNX2X_FILTER_RX_MODE_SCHED,
-	BNX2X_FILTER_ISCSI_ETH_START_SCHED,
-	BNX2X_FILTER_ISCSI_ETH_STOP_SCHED,
-	BNX2X_FILTER_FCOE_ETH_START_SCHED,
-	BNX2X_FILTER_FCOE_ETH_STOP_SCHED,
-	BNX2X_FILTER_MCAST_PENDING,
-	BNX2X_FILTER_MCAST_SCHED,
-	BNX2X_FILTER_RSS_CONF_PENDING,
-};
-
-struct bnx2x_raw_obj {
-	u8		func_id;
-
-	/* Queue params */
-	u8		cl_id;
-	u32		cid;
-
-	/* Ramrod data buffer params */
-	void		*rdata;
-	dma_addr_t	rdata_mapping;
-
-	/* Ramrod state params */
-	int		state;   /* "ramrod is pending" state bit */
-	unsigned long	*pstate; /* pointer to state buffer */
-
-	bnx2x_obj_type	obj_type;
-
-	int (*wait_comp)(struct bnx2x *bp,
-			 struct bnx2x_raw_obj *o);
-
-	bool (*check_pending)(struct bnx2x_raw_obj *o);
-	void (*clear_pending)(struct bnx2x_raw_obj *o);
-	void (*set_pending)(struct bnx2x_raw_obj *o);
-};
-
-/************************* VLAN-MAC commands related parameters ***************/
-struct bnx2x_mac_ramrod_data {
-	u8 mac[ETH_ALEN];
-};
-
-struct bnx2x_vlan_ramrod_data {
-	u16 vlan;
-};
-
-struct bnx2x_vlan_mac_ramrod_data {
-	u8 mac[ETH_ALEN];
-	u16 vlan;
-};
-
-union bnx2x_classification_ramrod_data {
-	struct bnx2x_mac_ramrod_data mac;
-	struct bnx2x_vlan_ramrod_data vlan;
-	struct bnx2x_vlan_mac_ramrod_data vlan_mac;
-};
-
-/* VLAN_MAC commands */
-enum bnx2x_vlan_mac_cmd {
-	BNX2X_VLAN_MAC_ADD,
-	BNX2X_VLAN_MAC_DEL,
-	BNX2X_VLAN_MAC_MOVE,
-};
-
-struct bnx2x_vlan_mac_data {
-	/* Requested command: BNX2X_VLAN_MAC_XX */
-	enum bnx2x_vlan_mac_cmd cmd;
-	/*
-	 * used to contain the data related vlan_mac_flags bits from
-	 * ramrod parameters.
-	 */
-	unsigned long vlan_mac_flags;
-
-	/* Needed for MOVE command */
-	struct bnx2x_vlan_mac_obj *target_obj;
-
-	union bnx2x_classification_ramrod_data u;
-};
-
-/*************************** Exe Queue obj ************************************/
-union bnx2x_exe_queue_cmd_data {
-	struct bnx2x_vlan_mac_data vlan_mac;
-
-	struct {
-		/* TODO */
-	} mcast;
-};
-
-struct bnx2x_exeq_elem {
-	struct list_head		link;
-
-	/* Length of this element in the exe_chunk. */
-	int				cmd_len;
-
-	union bnx2x_exe_queue_cmd_data	cmd_data;
-};
-
-union bnx2x_qable_obj;
-
-union bnx2x_exeq_comp_elem {
-	union event_ring_elem *elem;
-};
-
-struct bnx2x_exe_queue_obj;
-
-typedef int (*exe_q_validate)(struct bnx2x *bp,
-			      union bnx2x_qable_obj *o,
-			      struct bnx2x_exeq_elem *elem);
-
-/**
- * @return positive is entry was optimized, 0 - if not, negative
- *         in case of an error.
- */
-typedef int (*exe_q_optimize)(struct bnx2x *bp,
-			      union bnx2x_qable_obj *o,
-			      struct bnx2x_exeq_elem *elem);
-typedef int (*exe_q_execute)(struct bnx2x *bp,
-			     union bnx2x_qable_obj *o,
-			     struct list_head *exe_chunk,
-			     unsigned long *ramrod_flags);
-typedef struct bnx2x_exeq_elem *
-			(*exe_q_get)(struct bnx2x_exe_queue_obj *o,
-				     struct bnx2x_exeq_elem *elem);
-
-struct bnx2x_exe_queue_obj {
-	/*
-	 * Commands pending for an execution.
-	 */
-	struct list_head	exe_queue;
-
-	/*
-	 * Commands pending for an completion.
-	 */
-	struct list_head	pending_comp;
-
-	spinlock_t		lock;
-
-	/* Maximum length of commands' list for one execution */
-	int			exe_chunk_len;
-
-	union bnx2x_qable_obj	*owner;
-
-	/****** Virtual functions ******/
-	/**
-	 * Called before commands execution for commands that are really
-	 * going to be executed (after 'optimize').
-	 *
-	 * Must run under exe_queue->lock
-	 */
-	exe_q_validate		validate;
-
-
-	/**
-	 * This will try to cancel the current pending commands list
-	 * considering the new command.
-	 *
-	 * Must run under exe_queue->lock
-	 */
-	exe_q_optimize		optimize;
-
-	/**
-	 * Run the next commands chunk (owner specific).
-	 */
-	exe_q_execute		execute;
-
-	/**
-	 * Return the exe_queue element containing the specific command
-	 * if any. Otherwise return NULL.
-	 */
-	exe_q_get		get;
-};
-/***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/
-/*
- * Element in the VLAN_MAC registry list having all currenty configured
- * rules.
- */
-struct bnx2x_vlan_mac_registry_elem {
-	struct list_head	link;
-
-	/*
-	 * Used to store the cam offset used for the mac/vlan/vlan-mac.
-	 * Relevant for 57710 and 57711 only. VLANs and MACs share the
-	 * same CAM for these chips.
-	 */
-	int			cam_offset;
-
-	/* Needed for DEL and RESTORE flows */
-	unsigned long		vlan_mac_flags;
-
-	union bnx2x_classification_ramrod_data u;
-};
-
-/* Bits representing VLAN_MAC commands specific flags */
-enum {
-	BNX2X_UC_LIST_MAC,
-	BNX2X_ETH_MAC,
-	BNX2X_ISCSI_ETH_MAC,
-	BNX2X_NETQ_ETH_MAC,
-	BNX2X_DONT_CONSUME_CAM_CREDIT,
-	BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
-};
-
-struct bnx2x_vlan_mac_ramrod_params {
-	/* Object to run the command from */
-	struct bnx2x_vlan_mac_obj *vlan_mac_obj;
-
-	/* General command flags: COMP_WAIT, etc. */
-	unsigned long ramrod_flags;
-
-	/* Command specific configuration request */
-	struct bnx2x_vlan_mac_data user_req;
-};
-
-struct bnx2x_vlan_mac_obj {
-	struct bnx2x_raw_obj raw;
-
-	/* Bookkeeping list: will prevent the addition of already existing
-	 * entries.
-	 */
-	struct list_head		head;
-
-	/* TODO: Add it's initialization in the init functions */
-	struct bnx2x_exe_queue_obj	exe_queue;
-
-	/* MACs credit pool */
-	struct bnx2x_credit_pool_obj	*macs_pool;
-
-	/* VLANs credit pool */
-	struct bnx2x_credit_pool_obj	*vlans_pool;
-
-	/* RAMROD command to be used */
-	int				ramrod_cmd;
-
-	/**
-	 * Checks if ADD-ramrod with the given params may be performed.
-	 *
-	 * @return zero if the element may be added
-	 */
-
-	int (*check_add)(struct bnx2x_vlan_mac_obj *o,
-			 union bnx2x_classification_ramrod_data *data);
-
-	/**
-	 * Checks if DEL-ramrod with the given params may be performed.
-	 *
-	 * @return true if the element may be deleted
-	 */
-	struct bnx2x_vlan_mac_registry_elem *
-		(*check_del)(struct bnx2x_vlan_mac_obj *o,
-			     union bnx2x_classification_ramrod_data *data);
-
-	/**
-	 * Checks if DEL-ramrod with the given params may be performed.
-	 *
-	 * @return true if the element may be deleted
-	 */
-	bool (*check_move)(struct bnx2x_vlan_mac_obj *src_o,
-			   struct bnx2x_vlan_mac_obj *dst_o,
-			   union bnx2x_classification_ramrod_data *data);
-
-	/**
-	 *  Update the relevant credit object(s) (consume/return
-	 *  correspondingly).
-	 */
-	bool (*get_credit)(struct bnx2x_vlan_mac_obj *o);
-	bool (*put_credit)(struct bnx2x_vlan_mac_obj *o);
-	bool (*get_cam_offset)(struct bnx2x_vlan_mac_obj *o, int *offset);
-	bool (*put_cam_offset)(struct bnx2x_vlan_mac_obj *o, int offset);
-
-	/**
-	 * Configures one rule in the ramrod data buffer.
-	 */
-	void (*set_one_rule)(struct bnx2x *bp,
-			     struct bnx2x_vlan_mac_obj *o,
-			     struct bnx2x_exeq_elem *elem, int rule_idx,
-			     int cam_offset);
-
-	/**
-	*  Delete all configured elements having the given
-	*  vlan_mac_flags specification. Assumes no pending for
-	*  execution commands. Will schedule all all currently
-	*  configured MACs/VLANs/VLAN-MACs matching the vlan_mac_flags
-	*  specification for deletion and will use the given
-	*  ramrod_flags for the last DEL operation.
-	 *
-	 * @param bp
-	 * @param o
-	 * @param ramrod_flags RAMROD_XX flags
-	 *
-	 * @return 0 if the last operation has completed successfully
-	 *         and there are no more elements left, positive value
-	 *         if there are pending for completion commands,
-	 *         negative value in case of failure.
-	 */
-	int (*delete_all)(struct bnx2x *bp,
-			  struct bnx2x_vlan_mac_obj *o,
-			  unsigned long *vlan_mac_flags,
-			  unsigned long *ramrod_flags);
-
-	/**
-	 * Reconfigures the next MAC/VLAN/VLAN-MAC element from the previously
-	 * configured elements list.
-	 *
-	 * @param bp
-	 * @param p Command parameters (RAMROD_COMP_WAIT bit in
-	 *          ramrod_flags is only taken into an account)
-	 * @param ppos a pointer to the cooky that should be given back in the
-	 *        next call to make function handle the next element. If
-	 *        *ppos is set to NULL it will restart the iterator.
-	 *        If returned *ppos == NULL this means that the last
-	 *        element has been handled.
-	 *
-	 * @return int
-	 */
-	int (*restore)(struct bnx2x *bp,
-		       struct bnx2x_vlan_mac_ramrod_params *p,
-		       struct bnx2x_vlan_mac_registry_elem **ppos);
-
-	/**
-	 * Should be called on a completion arival.
-	 *
-	 * @param bp
-	 * @param o
-	 * @param cqe Completion element we are handling
-	 * @param ramrod_flags if RAMROD_CONT is set the next bulk of
-	 *		       pending commands will be executed.
-	 *		       RAMROD_DRV_CLR_ONLY and RAMROD_RESTORE
-	 *		       may also be set if needed.
-	 *
-	 * @return 0 if there are neither pending nor waiting for
-	 *         completion commands. Positive value if there are
-	 *         pending for execution or for completion commands.
-	 *         Negative value in case of an error (including an
-	 *         error in the cqe).
-	 */
-	int (*complete)(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o,
-			union event_ring_elem *cqe,
-			unsigned long *ramrod_flags);
-
-	/**
-	 * Wait for completion of all commands. Don't schedule new ones,
-	 * just wait. It assumes that the completion code will schedule
-	 * for new commands.
-	 */
-	int (*wait)(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o);
-};
-
-/** RX_MODE verbs:DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
-
-/* RX_MODE ramrod spesial flags: set in rx_mode_flags field in
- * a bnx2x_rx_mode_ramrod_params.
- */
-enum {
-	BNX2X_RX_MODE_FCOE_ETH,
-	BNX2X_RX_MODE_ISCSI_ETH,
-};
-
-enum {
-	BNX2X_ACCEPT_UNICAST,
-	BNX2X_ACCEPT_MULTICAST,
-	BNX2X_ACCEPT_ALL_UNICAST,
-	BNX2X_ACCEPT_ALL_MULTICAST,
-	BNX2X_ACCEPT_BROADCAST,
-	BNX2X_ACCEPT_UNMATCHED,
-	BNX2X_ACCEPT_ANY_VLAN
-};
-
-struct bnx2x_rx_mode_ramrod_params {
-	struct bnx2x_rx_mode_obj *rx_mode_obj;
-	unsigned long *pstate;
-	int state;
-	u8 cl_id;
-	u32 cid;
-	u8 func_id;
-	unsigned long ramrod_flags;
-	unsigned long rx_mode_flags;
-
-	/*
-	 * rdata is either a pointer to eth_filter_rules_ramrod_data(e2) or to
-	 * a tstorm_eth_mac_filter_config (e1x).
-	 */
-	void *rdata;
-	dma_addr_t rdata_mapping;
-
-	/* Rx mode settings */
-	unsigned long rx_accept_flags;
-
-	/* internal switching settings */
-	unsigned long tx_accept_flags;
-};
-
-struct bnx2x_rx_mode_obj {
-	int (*config_rx_mode)(struct bnx2x *bp,
-			      struct bnx2x_rx_mode_ramrod_params *p);
-
-	int (*wait_comp)(struct bnx2x *bp,
-			 struct bnx2x_rx_mode_ramrod_params *p);
-};
-
-/********************** Set multicast group ***********************************/
-
-struct bnx2x_mcast_list_elem {
-	struct list_head link;
-	u8 *mac;
-};
-
-union bnx2x_mcast_config_data {
-	u8 *mac;
-	u8 bin; /* used in a RESTORE flow */
-};
-
-struct bnx2x_mcast_ramrod_params {
-	struct bnx2x_mcast_obj *mcast_obj;
-
-	/* Relevant options are RAMROD_COMP_WAIT and RAMROD_DRV_CLR_ONLY */
-	unsigned long ramrod_flags;
-
-	struct list_head mcast_list; /* list of struct bnx2x_mcast_list_elem */
-	/** TODO:
-	 *      - rename it to macs_num.
-	 *      - Add a new command type for handling pending commands
-	 *        (remove "zero semantics").
-	 *
-	 *  Length of mcast_list. If zero and ADD_CONT command - post
-	 *  pending commands.
-	 */
-	int mcast_list_len;
-};
-
-enum {
-	BNX2X_MCAST_CMD_ADD,
-	BNX2X_MCAST_CMD_CONT,
-	BNX2X_MCAST_CMD_DEL,
-	BNX2X_MCAST_CMD_RESTORE,
-};
-
-struct bnx2x_mcast_obj {
-	struct bnx2x_raw_obj raw;
-
-	union {
-		struct {
-		#define BNX2X_MCAST_BINS_NUM	256
-		#define BNX2X_MCAST_VEC_SZ	(BNX2X_MCAST_BINS_NUM / 64)
-			u64 vec[BNX2X_MCAST_VEC_SZ];
-
-			/** Number of BINs to clear. Should be updated
-			 *  immediately when a command arrives in order to
-			 *  properly create DEL commands.
-			 */
-			int num_bins_set;
-		} aprox_match;
-
-		struct {
-			struct list_head macs;
-			int num_macs_set;
-		} exact_match;
-	} registry;
-
-	/* Pending commands */
-	struct list_head pending_cmds_head;
-
-	/* A state that is set in raw.pstate, when there are pending commands */
-	int sched_state;
-
-	/* Maximal number of mcast MACs configured in one command */
-	int max_cmd_len;
-
-	/* Total number of currently pending MACs to configure: both
-	 * in the pending commands list and in the current command.
-	 */
-	int total_pending_num;
-
-	u8 engine_id;
-
-	/**
-	 * @param cmd command to execute (BNX2X_MCAST_CMD_X, see above)
-	 */
-	int (*config_mcast)(struct bnx2x *bp,
-				struct bnx2x_mcast_ramrod_params *p, int cmd);
-
-	/**
-	 * Fills the ramrod data during the RESTORE flow.
-	 *
-	 * @param bp
-	 * @param o
-	 * @param start_idx Registry index to start from
-	 * @param rdata_idx Index in the ramrod data to start from
-	 *
-	 * @return -1 if we handled the whole registry or index of the last
-	 *         handled registry element.
-	 */
-	int (*hdl_restore)(struct bnx2x *bp, struct bnx2x_mcast_obj *o,
-			   int start_bin, int *rdata_idx);
-
-	int (*enqueue_cmd)(struct bnx2x *bp, struct bnx2x_mcast_obj *o,
-			   struct bnx2x_mcast_ramrod_params *p, int cmd);
-
-	void (*set_one_rule)(struct bnx2x *bp,
-			     struct bnx2x_mcast_obj *o, int idx,
-			     union bnx2x_mcast_config_data *cfg_data, int cmd);
-
-	/** Checks if there are more mcast MACs to be set or a previous
-	 *  command is still pending.
-	 */
-	bool (*check_pending)(struct bnx2x_mcast_obj *o);
-
-	/**
-	 * Set/Clear/Check SCHEDULED state of the object
-	 */
-	void (*set_sched)(struct bnx2x_mcast_obj *o);
-	void (*clear_sched)(struct bnx2x_mcast_obj *o);
-	bool (*check_sched)(struct bnx2x_mcast_obj *o);
-
-	/* Wait until all pending commands complete */
-	int (*wait_comp)(struct bnx2x *bp, struct bnx2x_mcast_obj *o);
-
-	/**
-	 * Handle the internal object counters needed for proper
-	 * commands handling. Checks that the provided parameters are
-	 * feasible.
-	 */
-	int (*validate)(struct bnx2x *bp,
-			struct bnx2x_mcast_ramrod_params *p, int cmd);
-
-	/**
-	 * Restore the values of internal counters in case of a failure.
-	 */
-	void (*revert)(struct bnx2x *bp,
-		       struct bnx2x_mcast_ramrod_params *p,
-		       int old_num_bins);
-
-	int (*get_registry_size)(struct bnx2x_mcast_obj *o);
-	void (*set_registry_size)(struct bnx2x_mcast_obj *o, int n);
-};
-
-/*************************** Credit handling **********************************/
-struct bnx2x_credit_pool_obj {
-
-	/* Current amount of credit in the pool */
-	atomic_t	credit;
-
-	/* Maximum allowed credit. put() will check against it. */
-	int		pool_sz;
-
-	/*
-	 *  Allocate a pool table statically.
-	 *
-	 *  Currently the mamimum allowed size is MAX_MAC_CREDIT_E2(272)
-	 *
-	 *  The set bit in the table will mean that the entry is available.
-	 */
-#define BNX2X_POOL_VEC_SIZE	(MAX_MAC_CREDIT_E2 / 64)
-	u64		pool_mirror[BNX2X_POOL_VEC_SIZE];
-
-	/* Base pool offset (initialized differently */
-	int		base_pool_offset;
-
-	/**
-	 * Get the next free pool entry.
-	 *
-	 * @return true if there was a free entry in the pool
-	 */
-	bool (*get_entry)(struct bnx2x_credit_pool_obj *o, int *entry);
-
-	/**
-	 * Return the entry back to the pool.
-	 *
-	 * @return true if entry is legal and has been successfully
-	 *         returned to the pool.
-	 */
-	bool (*put_entry)(struct bnx2x_credit_pool_obj *o, int entry);
-
-	/**
-	 * Get the requested amount of credit from the pool.
-	 *
-	 * @param cnt Amount of requested credit
-	 * @return true if the operation is successful
-	 */
-	bool (*get)(struct bnx2x_credit_pool_obj *o, int cnt);
-
-	/**
-	 * Returns the credit to the pool.
-	 *
-	 * @param cnt Amount of credit to return
-	 * @return true if the operation is successful
-	 */
-	bool (*put)(struct bnx2x_credit_pool_obj *o, int cnt);
-
-	/**
-	 * Reads the current amount of credit.
-	 */
-	int (*check)(struct bnx2x_credit_pool_obj *o);
-};
-
-/*************************** RSS configuration ********************************/
-enum {
-	/* RSS_MODE bits are mutually exclusive */
-	BNX2X_RSS_MODE_DISABLED,
-	BNX2X_RSS_MODE_REGULAR,
-	BNX2X_RSS_MODE_VLAN_PRI,
-	BNX2X_RSS_MODE_E1HOV_PRI,
-	BNX2X_RSS_MODE_IP_DSCP,
-
-	BNX2X_RSS_SET_SRCH, /* Setup searcher, E1x specific flag */
-
-	BNX2X_RSS_IPV4,
-	BNX2X_RSS_IPV4_TCP,
-	BNX2X_RSS_IPV6,
-	BNX2X_RSS_IPV6_TCP,
-};
-
-struct bnx2x_config_rss_params {
-	struct bnx2x_rss_config_obj *rss_obj;
-
-	/* may have RAMROD_COMP_WAIT set only */
-	unsigned long	ramrod_flags;
-
-	/* BNX2X_RSS_X bits */
-	unsigned long	rss_flags;
-
-	/* Number hash bits to take into an account */
-	u8		rss_result_mask;
-
-	/* Indirection table */
-	u8		ind_table[T_ETH_INDIRECTION_TABLE_SIZE];
-
-	/* RSS hash values */
-	u32		rss_key[10];
-
-	/* valid only iff BNX2X_RSS_UPDATE_TOE is set */
-	u16		toe_rss_bitmap;
-};
-
-struct bnx2x_rss_config_obj {
-	struct bnx2x_raw_obj	raw;
-
-	/* RSS engine to use */
-	u8			engine_id;
-
-	/* Last configured indirection table */
-	u8			ind_table[T_ETH_INDIRECTION_TABLE_SIZE];
-
-	int (*config_rss)(struct bnx2x *bp,
-			  struct bnx2x_config_rss_params *p);
-};
-
-/*********************** Queue state update ***********************************/
-
-/* UPDATE command options */
-enum {
-	BNX2X_Q_UPDATE_IN_VLAN_REM,
-	BNX2X_Q_UPDATE_IN_VLAN_REM_CHNG,
-	BNX2X_Q_UPDATE_OUT_VLAN_REM,
-	BNX2X_Q_UPDATE_OUT_VLAN_REM_CHNG,
-	BNX2X_Q_UPDATE_ANTI_SPOOF,
-	BNX2X_Q_UPDATE_ANTI_SPOOF_CHNG,
-	BNX2X_Q_UPDATE_ACTIVATE,
-	BNX2X_Q_UPDATE_ACTIVATE_CHNG,
-	BNX2X_Q_UPDATE_DEF_VLAN_EN,
-	BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
-	BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
-	BNX2X_Q_UPDATE_SILENT_VLAN_REM
-};
-
-/* Allowed Queue states */
-enum bnx2x_q_state {
-	BNX2X_Q_STATE_RESET,
-	BNX2X_Q_STATE_INITIALIZED,
-	BNX2X_Q_STATE_ACTIVE,
-	BNX2X_Q_STATE_MULTI_COS,
-	BNX2X_Q_STATE_MCOS_TERMINATED,
-	BNX2X_Q_STATE_INACTIVE,
-	BNX2X_Q_STATE_STOPPED,
-	BNX2X_Q_STATE_TERMINATED,
-	BNX2X_Q_STATE_FLRED,
-	BNX2X_Q_STATE_MAX,
-};
-
-/* Allowed commands */
-enum bnx2x_queue_cmd {
-	BNX2X_Q_CMD_INIT,
-	BNX2X_Q_CMD_SETUP,
-	BNX2X_Q_CMD_SETUP_TX_ONLY,
-	BNX2X_Q_CMD_DEACTIVATE,
-	BNX2X_Q_CMD_ACTIVATE,
-	BNX2X_Q_CMD_UPDATE,
-	BNX2X_Q_CMD_UPDATE_TPA,
-	BNX2X_Q_CMD_HALT,
-	BNX2X_Q_CMD_CFC_DEL,
-	BNX2X_Q_CMD_TERMINATE,
-	BNX2X_Q_CMD_EMPTY,
-	BNX2X_Q_CMD_MAX,
-};
-
-/* queue SETUP + INIT flags */
-enum {
-	BNX2X_Q_FLG_TPA,
-	BNX2X_Q_FLG_TPA_IPV6,
-	BNX2X_Q_FLG_STATS,
-	BNX2X_Q_FLG_ZERO_STATS,
-	BNX2X_Q_FLG_ACTIVE,
-	BNX2X_Q_FLG_OV,
-	BNX2X_Q_FLG_VLAN,
-	BNX2X_Q_FLG_COS,
-	BNX2X_Q_FLG_HC,
-	BNX2X_Q_FLG_HC_EN,
-	BNX2X_Q_FLG_DHC,
-	BNX2X_Q_FLG_FCOE,
-	BNX2X_Q_FLG_LEADING_RSS,
-	BNX2X_Q_FLG_MCAST,
-	BNX2X_Q_FLG_DEF_VLAN,
-	BNX2X_Q_FLG_TX_SWITCH,
-	BNX2X_Q_FLG_TX_SEC,
-	BNX2X_Q_FLG_ANTI_SPOOF,
-	BNX2X_Q_FLG_SILENT_VLAN_REM
-};
-
-/* Queue type options: queue type may be a compination of below. */
-enum bnx2x_q_type {
-	/** TODO: Consider moving both these flags into the init()
-	 *        ramrod params.
-	 */
-	BNX2X_Q_TYPE_HAS_RX,
-	BNX2X_Q_TYPE_HAS_TX,
-};
-
-#define BNX2X_PRIMARY_CID_INDEX			0
-#define BNX2X_MULTI_TX_COS_E1X			1
-#define BNX2X_MULTI_TX_COS_E2_E3A0		2
-#define BNX2X_MULTI_TX_COS_E3B0			3
-#define BNX2X_MULTI_TX_COS			BNX2X_MULTI_TX_COS_E3B0
-
-
-struct bnx2x_queue_init_params {
-	struct {
-		unsigned long	flags;
-		u16		hc_rate;
-		u8		fw_sb_id;
-		u8		sb_cq_index;
-	} tx;
-
-	struct {
-		unsigned long	flags;
-		u16		hc_rate;
-		u8		fw_sb_id;
-		u8		sb_cq_index;
-	} rx;
-
-	/* CID context in the host memory */
-	struct eth_context *cxts[BNX2X_MULTI_TX_COS];
-
-	/* maximum number of cos supported by hardware */
-	u8 max_cos;
-};
-
-struct bnx2x_queue_terminate_params {
-	/* index within the tx_only cids of this queue object */
-	u8 cid_index;
-};
-
-struct bnx2x_queue_cfc_del_params {
-	/* index within the tx_only cids of this queue object */
-	u8 cid_index;
-};
-
-struct bnx2x_queue_update_params {
-	unsigned long	update_flags; /* BNX2X_Q_UPDATE_XX bits */
-	u16		def_vlan;
-	u16		silent_removal_value;
-	u16		silent_removal_mask;
-/* index within the tx_only cids of this queue object */
-	u8		cid_index;
-};
-
-struct rxq_pause_params {
-	u16		bd_th_lo;
-	u16		bd_th_hi;
-	u16		rcq_th_lo;
-	u16		rcq_th_hi;
-	u16		sge_th_lo; /* valid iff BNX2X_Q_FLG_TPA */
-	u16		sge_th_hi; /* valid iff BNX2X_Q_FLG_TPA */
-	u16		pri_map;
-};
-
-/* general */
-struct bnx2x_general_setup_params {
-	/* valid iff BNX2X_Q_FLG_STATS */
-	u8		stat_id;
-
-	u8		spcl_id;
-	u16		mtu;
-	u8		cos;
-};
-
-struct bnx2x_rxq_setup_params {
-	/* dma */
-	dma_addr_t	dscr_map;
-	dma_addr_t	sge_map;
-	dma_addr_t	rcq_map;
-	dma_addr_t	rcq_np_map;
-
-	u16		drop_flags;
-	u16		buf_sz;
-	u8		fw_sb_id;
-	u8		cl_qzone_id;
-
-	/* valid iff BNX2X_Q_FLG_TPA */
-	u16		tpa_agg_sz;
-	u16		sge_buf_sz;
-	u8		max_sges_pkt;
-	u8		max_tpa_queues;
-	u8		rss_engine_id;
-
-	u8		cache_line_log;
-
-	u8		sb_cq_index;
-
-	/* valid iff BXN2X_Q_FLG_SILENT_VLAN_REM */
-	u16 silent_removal_value;
-	u16 silent_removal_mask;
-};
-
-struct bnx2x_txq_setup_params {
-	/* dma */
-	dma_addr_t	dscr_map;
-
-	u8		fw_sb_id;
-	u8		sb_cq_index;
-	u8		cos;		/* valid iff BNX2X_Q_FLG_COS */
-	u16		traffic_type;
-	/* equals to the leading rss client id, used for TX classification*/
-	u8		tss_leading_cl_id;
-
-	/* valid iff BNX2X_Q_FLG_DEF_VLAN */
-	u16		default_vlan;
-};
-
-struct bnx2x_queue_setup_params {
-	struct bnx2x_general_setup_params gen_params;
-	struct bnx2x_txq_setup_params txq_params;
-	struct bnx2x_rxq_setup_params rxq_params;
-	struct rxq_pause_params pause_params;
-	unsigned long flags;
-};
-
-struct bnx2x_queue_setup_tx_only_params {
-	struct bnx2x_general_setup_params	gen_params;
-	struct bnx2x_txq_setup_params		txq_params;
-	unsigned long				flags;
-	/* index within the tx_only cids of this queue object */
-	u8					cid_index;
-};
-
-struct bnx2x_queue_state_params {
-	struct bnx2x_queue_sp_obj *q_obj;
-
-	/* Current command */
-	enum bnx2x_queue_cmd cmd;
-
-	/* may have RAMROD_COMP_WAIT set only */
-	unsigned long ramrod_flags;
-
-	/* Params according to the current command */
-	union {
-		struct bnx2x_queue_update_params	update;
-		struct bnx2x_queue_setup_params		setup;
-		struct bnx2x_queue_init_params		init;
-		struct bnx2x_queue_setup_tx_only_params	tx_only;
-		struct bnx2x_queue_terminate_params	terminate;
-		struct bnx2x_queue_cfc_del_params	cfc_del;
-	} params;
-};
-
-struct bnx2x_queue_sp_obj {
-	u32		cids[BNX2X_MULTI_TX_COS];
-	u8		cl_id;
-	u8		func_id;
-
-	/*
-	 * number of traffic classes supported by queue.
-	 * The primary connection of the queue suppotrs the first traffic
-	 * class. Any further traffic class is suppoted by a tx-only
-	 * connection.
-	 *
-	 * Therefore max_cos is also a number of valid entries in the cids
-	 * array.
-	 */
-	u8 max_cos;
-	u8 num_tx_only, next_tx_only;
-
-	enum bnx2x_q_state state, next_state;
-
-	/* bits from enum bnx2x_q_type */
-	unsigned long	type;
-
-	/* BNX2X_Q_CMD_XX bits. This object implements "one
-	 * pending" paradigm but for debug and tracing purposes it's
-	 * more convinient to have different bits for different
-	 * commands.
-	 */
-	unsigned long	pending;
-
-	/* Buffer to use as a ramrod data and its mapping */
-	void		*rdata;
-	dma_addr_t	rdata_mapping;
-
-	/**
-	 * Performs one state change according to the given parameters.
-	 *
-	 * @return 0 in case of success and negative value otherwise.
-	 */
-	int (*send_cmd)(struct bnx2x *bp,
-			struct bnx2x_queue_state_params *params);
-
-	/**
-	 * Sets the pending bit according to the requested transition.
-	 */
-	int (*set_pending)(struct bnx2x_queue_sp_obj *o,
-			   struct bnx2x_queue_state_params *params);
-
-	/**
-	 * Checks that the requested state transition is legal.
-	 */
-	int (*check_transition)(struct bnx2x *bp,
-				struct bnx2x_queue_sp_obj *o,
-				struct bnx2x_queue_state_params *params);
-
-	/**
-	 * Completes the pending command.
-	 */
-	int (*complete_cmd)(struct bnx2x *bp,
-			    struct bnx2x_queue_sp_obj *o,
-			    enum bnx2x_queue_cmd);
-
-	int (*wait_comp)(struct bnx2x *bp,
-			 struct bnx2x_queue_sp_obj *o,
-			 enum bnx2x_queue_cmd cmd);
-};
-
-/********************** Function state update *********************************/
-/* Allowed Function states */
-enum bnx2x_func_state {
-	BNX2X_F_STATE_RESET,
-	BNX2X_F_STATE_INITIALIZED,
-	BNX2X_F_STATE_STARTED,
-	BNX2X_F_STATE_TX_STOPPED,
-	BNX2X_F_STATE_MAX,
-};
-
-/* Allowed Function commands */
-enum bnx2x_func_cmd {
-	BNX2X_F_CMD_HW_INIT,
-	BNX2X_F_CMD_START,
-	BNX2X_F_CMD_STOP,
-	BNX2X_F_CMD_HW_RESET,
-	BNX2X_F_CMD_TX_STOP,
-	BNX2X_F_CMD_TX_START,
-	BNX2X_F_CMD_MAX,
-};
-
-struct bnx2x_func_hw_init_params {
-	/* A load phase returned by MCP.
-	 *
-	 * May be:
-	 *		FW_MSG_CODE_DRV_LOAD_COMMON_CHIP
-	 *		FW_MSG_CODE_DRV_LOAD_COMMON
-	 *		FW_MSG_CODE_DRV_LOAD_PORT
-	 *		FW_MSG_CODE_DRV_LOAD_FUNCTION
-	 */
-	u32 load_phase;
-};
-
-struct bnx2x_func_hw_reset_params {
-	/* A load phase returned by MCP.
-	 *
-	 * May be:
-	 *		FW_MSG_CODE_DRV_LOAD_COMMON_CHIP
-	 *		FW_MSG_CODE_DRV_LOAD_COMMON
-	 *		FW_MSG_CODE_DRV_LOAD_PORT
-	 *		FW_MSG_CODE_DRV_LOAD_FUNCTION
-	 */
-	u32 reset_phase;
-};
-
-struct bnx2x_func_start_params {
-	/* Multi Function mode:
-	 *	- Single Function
-	 *	- Switch Dependent
-	 *	- Switch Independent
-	 */
-	u16 mf_mode;
-
-	/* Switch Dependent mode outer VLAN tag */
-	u16 sd_vlan_tag;
-
-	/* Function cos mode */
-	u8 network_cos_mode;
-};
-
-struct bnx2x_func_tx_start_params {
-	struct priority_cos traffic_type_to_priority_cos[MAX_TRAFFIC_TYPES];
-	u8 dcb_enabled;
-	u8 dcb_version;
-	u8 dont_add_pri_0_en;
-};
-
-struct bnx2x_func_state_params {
-	struct bnx2x_func_sp_obj *f_obj;
-
-	/* Current command */
-	enum bnx2x_func_cmd cmd;
-
-	/* may have RAMROD_COMP_WAIT set only */
-	unsigned long	ramrod_flags;
-
-	/* Params according to the current command */
-	union {
-		struct bnx2x_func_hw_init_params hw_init;
-		struct bnx2x_func_hw_reset_params hw_reset;
-		struct bnx2x_func_start_params start;
-		struct bnx2x_func_tx_start_params tx_start;
-	} params;
-};
-
-struct bnx2x_func_sp_drv_ops {
-	/* Init tool + runtime initialization:
-	 *      - Common Chip
-	 *      - Common (per Path)
-	 *      - Port
-	 *      - Function phases
-	 */
-	int (*init_hw_cmn_chip)(struct bnx2x *bp);
-	int (*init_hw_cmn)(struct bnx2x *bp);
-	int (*init_hw_port)(struct bnx2x *bp);
-	int (*init_hw_func)(struct bnx2x *bp);
-
-	/* Reset Function HW: Common, Port, Function phases. */
-	void (*reset_hw_cmn)(struct bnx2x *bp);
-	void (*reset_hw_port)(struct bnx2x *bp);
-	void (*reset_hw_func)(struct bnx2x *bp);
-
-	/* Init/Free GUNZIP resources */
-	int (*gunzip_init)(struct bnx2x *bp);
-	void (*gunzip_end)(struct bnx2x *bp);
-
-	/* Prepare/Release FW resources */
-	int (*init_fw)(struct bnx2x *bp);
-	void (*release_fw)(struct bnx2x *bp);
-};
-
-struct bnx2x_func_sp_obj {
-	enum bnx2x_func_state	state, next_state;
-
-	/* BNX2X_FUNC_CMD_XX bits. This object implements "one
-	 * pending" paradigm but for debug and tracing purposes it's
-	 * more convinient to have different bits for different
-	 * commands.
-	 */
-	unsigned long		pending;
-
-	/* Buffer to use as a ramrod data and its mapping */
-	void			*rdata;
-	dma_addr_t		rdata_mapping;
-
-	/* this mutex validates that when pending flag is taken, the next
-	 * ramrod to be sent will be the one set the pending bit
-	 */
-	struct mutex		one_pending_mutex;
-
-	/* Driver interface */
-	struct bnx2x_func_sp_drv_ops	*drv;
-
-	/**
-	 * Performs one state change according to the given parameters.
-	 *
-	 * @return 0 in case of success and negative value otherwise.
-	 */
-	int (*send_cmd)(struct bnx2x *bp,
-			struct bnx2x_func_state_params *params);
-
-	/**
-	 * Checks that the requested state transition is legal.
-	 */
-	int (*check_transition)(struct bnx2x *bp,
-				struct bnx2x_func_sp_obj *o,
-				struct bnx2x_func_state_params *params);
-
-	/**
-	 * Completes the pending command.
-	 */
-	int (*complete_cmd)(struct bnx2x *bp,
-			    struct bnx2x_func_sp_obj *o,
-			    enum bnx2x_func_cmd cmd);
-
-	int (*wait_comp)(struct bnx2x *bp, struct bnx2x_func_sp_obj *o,
-			 enum bnx2x_func_cmd cmd);
-};
-
-/********************** Interfaces ********************************************/
-/* Queueable objects set */
-union bnx2x_qable_obj {
-	struct bnx2x_vlan_mac_obj vlan_mac;
-};
-/************** Function state update *********/
-void bnx2x_init_func_obj(struct bnx2x *bp,
-			 struct bnx2x_func_sp_obj *obj,
-			 void *rdata, dma_addr_t rdata_mapping,
-			 struct bnx2x_func_sp_drv_ops *drv_iface);
-
-int bnx2x_func_state_change(struct bnx2x *bp,
-			    struct bnx2x_func_state_params *params);
-
-enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp,
-					   struct bnx2x_func_sp_obj *o);
-/******************* Queue State **************/
-void bnx2x_init_queue_obj(struct bnx2x *bp,
-			  struct bnx2x_queue_sp_obj *obj, u8 cl_id, u32 *cids,
-			  u8 cid_cnt, u8 func_id, void *rdata,
-			  dma_addr_t rdata_mapping, unsigned long type);
-
-int bnx2x_queue_state_change(struct bnx2x *bp,
-			     struct bnx2x_queue_state_params *params);
-
-/********************* VLAN-MAC ****************/
-void bnx2x_init_mac_obj(struct bnx2x *bp,
-			struct bnx2x_vlan_mac_obj *mac_obj,
-			u8 cl_id, u32 cid, u8 func_id, void *rdata,
-			dma_addr_t rdata_mapping, int state,
-			unsigned long *pstate, bnx2x_obj_type type,
-			struct bnx2x_credit_pool_obj *macs_pool);
-
-void bnx2x_init_vlan_obj(struct bnx2x *bp,
-			 struct bnx2x_vlan_mac_obj *vlan_obj,
-			 u8 cl_id, u32 cid, u8 func_id, void *rdata,
-			 dma_addr_t rdata_mapping, int state,
-			 unsigned long *pstate, bnx2x_obj_type type,
-			 struct bnx2x_credit_pool_obj *vlans_pool);
-
-void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
-			     struct bnx2x_vlan_mac_obj *vlan_mac_obj,
-			     u8 cl_id, u32 cid, u8 func_id, void *rdata,
-			     dma_addr_t rdata_mapping, int state,
-			     unsigned long *pstate, bnx2x_obj_type type,
-			     struct bnx2x_credit_pool_obj *macs_pool,
-			     struct bnx2x_credit_pool_obj *vlans_pool);
-
-int bnx2x_config_vlan_mac(struct bnx2x *bp,
-			  struct bnx2x_vlan_mac_ramrod_params *p);
-
-int bnx2x_vlan_mac_move(struct bnx2x *bp,
-			struct bnx2x_vlan_mac_ramrod_params *p,
-			struct bnx2x_vlan_mac_obj *dest_o);
-
-/********************* RX MODE ****************/
-
-void bnx2x_init_rx_mode_obj(struct bnx2x *bp,
-			    struct bnx2x_rx_mode_obj *o);
-
-/**
- * Send and RX_MODE ramrod according to the provided parameters.
- *
- * @param bp
- * @param p Command parameters
- *
- * @return 0 - if operation was successfull and there is no pending completions,
- *         positive number - if there are pending completions,
- *         negative - if there were errors
- */
-int bnx2x_config_rx_mode(struct bnx2x *bp,
-			 struct bnx2x_rx_mode_ramrod_params *p);
-
-/****************** MULTICASTS ****************/
-
-void bnx2x_init_mcast_obj(struct bnx2x *bp,
-			  struct bnx2x_mcast_obj *mcast_obj,
-			  u8 mcast_cl_id, u32 mcast_cid, u8 func_id,
-			  u8 engine_id, void *rdata, dma_addr_t rdata_mapping,
-			  int state, unsigned long *pstate,
-			  bnx2x_obj_type type);
-
-/**
- * Configure multicast MACs list. May configure a new list
- * provided in p->mcast_list (BNX2X_MCAST_CMD_ADD), clean up
- * (BNX2X_MCAST_CMD_DEL) or restore (BNX2X_MCAST_CMD_RESTORE) a current
- * configuration, continue to execute the pending commands
- * (BNX2X_MCAST_CMD_CONT).
- *
- * If previous command is still pending or if number of MACs to
- * configure is more that maximum number of MACs in one command,
- * the current command will be enqueued to the tail of the
- * pending commands list.
- *
- * @param bp
- * @param p
- * @param command to execute: BNX2X_MCAST_CMD_X
- *
- * @return 0 is operation was sucessfull and there are no pending completions,
- *         negative if there were errors, positive if there are pending
- *         completions.
- */
-int bnx2x_config_mcast(struct bnx2x *bp,
-		       struct bnx2x_mcast_ramrod_params *p, int cmd);
-
-/****************** CREDIT POOL ****************/
-void bnx2x_init_mac_credit_pool(struct bnx2x *bp,
-				struct bnx2x_credit_pool_obj *p, u8 func_id,
-				u8 func_num);
-void bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
-				 struct bnx2x_credit_pool_obj *p, u8 func_id,
-				 u8 func_num);
-
-
-/****************** RSS CONFIGURATION ****************/
-void bnx2x_init_rss_config_obj(struct bnx2x *bp,
-			       struct bnx2x_rss_config_obj *rss_obj,
-			       u8 cl_id, u32 cid, u8 func_id, u8 engine_id,
-			       void *rdata, dma_addr_t rdata_mapping,
-			       int state, unsigned long *pstate,
-			       bnx2x_obj_type type);
-
-/**
- * Updates RSS configuration according to provided parameters.
- *
- * @param bp
- * @param p
- *
- * @return 0 in case of success
- */
-int bnx2x_config_rss(struct bnx2x *bp,
-		     struct bnx2x_config_rss_params *p);
-
-/**
- * Return the current ind_table configuration.
- *
- * @param bp
- * @param ind_table buffer to fill with the current indirection
- *                  table content. Should be at least
- *                  T_ETH_INDIRECTION_TABLE_SIZE bytes long.
- */
-void bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj,
-			     u8 *ind_table);
-
-#endif /* BNX2X_SP_VERBS */
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_stats.c linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_stats.c
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_stats.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_stats.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1599 +0,0 @@
-/* bnx2x_stats.c: Broadcom Everest network driver.
- *
- * Copyright (c) 2007-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
- * the Free Software Foundation.
- *
- * Maintained by: Eilon Greenstein <eilong@broadcom.com>
- * Written by: Eliezer Tamir
- * Based on code from Michael Chan's bnx2 driver
- * UDP CSUM errata workaround by Arik Gendelman
- * Slowpath and fastpath rework by Vladislav Zolotarov
- * Statistics and Link management by Yitchak Gertner
- *
- */
-#include "bnx2x_stats.h"
-#include "bnx2x_cmn.h"
-
-
-/* Statistics */
-
-/*
- * General service functions
- */
-
-static inline long bnx2x_hilo(u32 *hiref)
-{
-	u32 lo = *(hiref + 1);
-#if (BITS_PER_LONG == 64)
-	u32 hi = *hiref;
-
-	return HILO_U64(hi, lo);
-#else
-	return lo;
-#endif
-}
-
-/*
- * Init service functions
- */
-
-/* Post the next statistics ramrod. Protect it with the spin in
- * order to ensure the strict order between statistics ramrods
- * (each ramrod has a sequence number passed in a
- * bp->fw_stats_req->hdr.drv_stats_counter and ramrods must be
- * sent in order).
- */
-static void bnx2x_storm_stats_post(struct bnx2x *bp)
-{
-	if (!bp->stats_pending) {
-		int rc;
-
-		spin_lock_bh(&bp->stats_lock);
-
-		if (bp->stats_pending) {
-			spin_unlock_bh(&bp->stats_lock);
-			return;
-		}
-
-		bp->fw_stats_req->hdr.drv_stats_counter =
-			cpu_to_le16(bp->stats_counter++);
-
-		DP(NETIF_MSG_TIMER, "Sending statistics ramrod %d\n",
-			bp->fw_stats_req->hdr.drv_stats_counter);
-
-
-
-		/* send FW stats ramrod */
-		rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STAT_QUERY, 0,
-				   U64_HI(bp->fw_stats_req_mapping),
-				   U64_LO(bp->fw_stats_req_mapping),
-				   NONE_CONNECTION_TYPE);
-		if (rc == 0)
-			bp->stats_pending = 1;
-
-		spin_unlock_bh(&bp->stats_lock);
-	}
-}
-
-static void bnx2x_hw_stats_post(struct bnx2x *bp)
-{
-	struct dmae_command *dmae = &bp->stats_dmae;
-	u32 *stats_comp = bnx2x_sp(bp, stats_comp);
-
-	*stats_comp = DMAE_COMP_VAL;
-	if (CHIP_REV_IS_SLOW(bp))
-		return;
-
-	/* loader */
-	if (bp->executer_idx) {
-		int loader_idx = PMF_DMAE_C(bp);
-		u32 opcode =  bnx2x_dmae_opcode(bp, DMAE_SRC_PCI, DMAE_DST_GRC,
-						 true, DMAE_COMP_GRC);
-		opcode = bnx2x_dmae_opcode_clr_src_reset(opcode);
-
-		memset(dmae, 0, sizeof(struct dmae_command));
-		dmae->opcode = opcode;
-		dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, dmae[0]));
-		dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, dmae[0]));
-		dmae->dst_addr_lo = (DMAE_REG_CMD_MEM +
-				     sizeof(struct dmae_command) *
-				     (loader_idx + 1)) >> 2;
-		dmae->dst_addr_hi = 0;
-		dmae->len = sizeof(struct dmae_command) >> 2;
-		if (CHIP_IS_E1(bp))
-			dmae->len--;
-		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx + 1] >> 2;
-		dmae->comp_addr_hi = 0;
-		dmae->comp_val = 1;
-
-		*stats_comp = 0;
-		bnx2x_post_dmae(bp, dmae, loader_idx);
-
-	} else if (bp->func_stx) {
-		*stats_comp = 0;
-		bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));
-	}
-}
-
-static int bnx2x_stats_comp(struct bnx2x *bp)
-{
-	u32 *stats_comp = bnx2x_sp(bp, stats_comp);
-	int cnt = 10;
-
-	might_sleep();
-	while (*stats_comp != DMAE_COMP_VAL) {
-		if (!cnt) {
-			BNX2X_ERR("timeout waiting for stats finished\n");
-			break;
-		}
-		cnt--;
-		usleep_range(1000, 1000);
-	}
-	return 1;
-}
-
-/*
- * Statistics service functions
- */
-
-static void bnx2x_stats_pmf_update(struct bnx2x *bp)
-{
-	struct dmae_command *dmae;
-	u32 opcode;
-	int loader_idx = PMF_DMAE_C(bp);
-	u32 *stats_comp = bnx2x_sp(bp, stats_comp);
-
-	/* sanity */
-	if (!IS_MF(bp) || !bp->port.pmf || !bp->port.port_stx) {
-		BNX2X_ERR("BUG!\n");
-		return;
-	}
-
-	bp->executer_idx = 0;
-
-	opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI, false, 0);
-
-	dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-	dmae->opcode = bnx2x_dmae_opcode_add_comp(opcode, DMAE_COMP_GRC);
-	dmae->src_addr_lo = bp->port.port_stx >> 2;
-	dmae->src_addr_hi = 0;
-	dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats));
-	dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats));
-	dmae->len = DMAE_LEN32_RD_MAX;
-	dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
-	dmae->comp_addr_hi = 0;
-	dmae->comp_val = 1;
-
-	dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-	dmae->opcode = bnx2x_dmae_opcode_add_comp(opcode, DMAE_COMP_PCI);
-	dmae->src_addr_lo = (bp->port.port_stx >> 2) + DMAE_LEN32_RD_MAX;
-	dmae->src_addr_hi = 0;
-	dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats) +
-				   DMAE_LEN32_RD_MAX * 4);
-	dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats) +
-				   DMAE_LEN32_RD_MAX * 4);
-	dmae->len = (sizeof(struct host_port_stats) >> 2) - DMAE_LEN32_RD_MAX;
-	dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp));
-	dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp));
-	dmae->comp_val = DMAE_COMP_VAL;
-
-	*stats_comp = 0;
-	bnx2x_hw_stats_post(bp);
-	bnx2x_stats_comp(bp);
-}
-
-static void bnx2x_port_stats_init(struct bnx2x *bp)
-{
-	struct dmae_command *dmae;
-	int port = BP_PORT(bp);
-	u32 opcode;
-	int loader_idx = PMF_DMAE_C(bp);
-	u32 mac_addr;
-	u32 *stats_comp = bnx2x_sp(bp, stats_comp);
-
-	/* sanity */
-	if (!bp->link_vars.link_up || !bp->port.pmf) {
-		BNX2X_ERR("BUG!\n");
-		return;
-	}
-
-	bp->executer_idx = 0;
-
-	/* MCP */
-	opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_PCI, DMAE_DST_GRC,
-				    true, DMAE_COMP_GRC);
-
-	if (bp->port.port_stx) {
-
-		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-		dmae->opcode = opcode;
-		dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats));
-		dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats));
-		dmae->dst_addr_lo = bp->port.port_stx >> 2;
-		dmae->dst_addr_hi = 0;
-		dmae->len = sizeof(struct host_port_stats) >> 2;
-		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
-		dmae->comp_addr_hi = 0;
-		dmae->comp_val = 1;
-	}
-
-	if (bp->func_stx) {
-
-		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-		dmae->opcode = opcode;
-		dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats));
-		dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats));
-		dmae->dst_addr_lo = bp->func_stx >> 2;
-		dmae->dst_addr_hi = 0;
-		dmae->len = sizeof(struct host_func_stats) >> 2;
-		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
-		dmae->comp_addr_hi = 0;
-		dmae->comp_val = 1;
-	}
-
-	/* MAC */
-	opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
-				   true, DMAE_COMP_GRC);
-
-	/* EMAC is special */
-	if (bp->link_vars.mac_type == MAC_TYPE_EMAC) {
-		mac_addr = (port ? GRCBASE_EMAC1 : GRCBASE_EMAC0);
-
-		/* EMAC_REG_EMAC_RX_STAT_AC (EMAC_REG_EMAC_RX_STAT_AC_COUNT)*/
-		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-		dmae->opcode = opcode;
-		dmae->src_addr_lo = (mac_addr +
-				     EMAC_REG_EMAC_RX_STAT_AC) >> 2;
-		dmae->src_addr_hi = 0;
-		dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats));
-		dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats));
-		dmae->len = EMAC_REG_EMAC_RX_STAT_AC_COUNT;
-		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
-		dmae->comp_addr_hi = 0;
-		dmae->comp_val = 1;
-
-		/* EMAC_REG_EMAC_RX_STAT_AC_28 */
-		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-		dmae->opcode = opcode;
-		dmae->src_addr_lo = (mac_addr +
-				     EMAC_REG_EMAC_RX_STAT_AC_28) >> 2;
-		dmae->src_addr_hi = 0;
-		dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats) +
-		     offsetof(struct emac_stats, rx_stat_falsecarriererrors));
-		dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats) +
-		     offsetof(struct emac_stats, rx_stat_falsecarriererrors));
-		dmae->len = 1;
-		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
-		dmae->comp_addr_hi = 0;
-		dmae->comp_val = 1;
-
-		/* EMAC_REG_EMAC_TX_STAT_AC (EMAC_REG_EMAC_TX_STAT_AC_COUNT)*/
-		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-		dmae->opcode = opcode;
-		dmae->src_addr_lo = (mac_addr +
-				     EMAC_REG_EMAC_TX_STAT_AC) >> 2;
-		dmae->src_addr_hi = 0;
-		dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats) +
-			offsetof(struct emac_stats, tx_stat_ifhcoutoctets));
-		dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats) +
-			offsetof(struct emac_stats, tx_stat_ifhcoutoctets));
-		dmae->len = EMAC_REG_EMAC_TX_STAT_AC_COUNT;
-		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
-		dmae->comp_addr_hi = 0;
-		dmae->comp_val = 1;
-	} else {
-		u32 tx_src_addr_lo, rx_src_addr_lo;
-		u16 rx_len, tx_len;
-
-		/* configure the params according to MAC type */
-		switch (bp->link_vars.mac_type) {
-		case MAC_TYPE_BMAC:
-			mac_addr = (port ? NIG_REG_INGRESS_BMAC1_MEM :
-					   NIG_REG_INGRESS_BMAC0_MEM);
-
-			/* BIGMAC_REGISTER_TX_STAT_GTPKT ..
-			   BIGMAC_REGISTER_TX_STAT_GTBYT */
-			if (CHIP_IS_E1x(bp)) {
-				tx_src_addr_lo = (mac_addr +
-					BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
-				tx_len = (8 + BIGMAC_REGISTER_TX_STAT_GTBYT -
-					  BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
-				rx_src_addr_lo = (mac_addr +
-					BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
-				rx_len = (8 + BIGMAC_REGISTER_RX_STAT_GRIPJ -
-					  BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
-			} else {
-				tx_src_addr_lo = (mac_addr +
-					BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
-				tx_len = (8 + BIGMAC2_REGISTER_TX_STAT_GTBYT -
-					  BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
-				rx_src_addr_lo = (mac_addr +
-					BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
-				rx_len = (8 + BIGMAC2_REGISTER_RX_STAT_GRIPJ -
-					  BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
-			}
-			break;
-
-		case MAC_TYPE_UMAC: /* handled by MSTAT */
-		case MAC_TYPE_XMAC: /* handled by MSTAT */
-		default:
-			mac_addr = port ? GRCBASE_MSTAT1 : GRCBASE_MSTAT0;
-			tx_src_addr_lo = (mac_addr +
-					  MSTAT_REG_TX_STAT_GTXPOK_LO) >> 2;
-			rx_src_addr_lo = (mac_addr +
-					  MSTAT_REG_RX_STAT_GR64_LO) >> 2;
-			tx_len = sizeof(bp->slowpath->
-					mac_stats.mstat_stats.stats_tx) >> 2;
-			rx_len = sizeof(bp->slowpath->
-					mac_stats.mstat_stats.stats_rx) >> 2;
-			break;
-		}
-
-		/* TX stats */
-		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-		dmae->opcode = opcode;
-		dmae->src_addr_lo = tx_src_addr_lo;
-		dmae->src_addr_hi = 0;
-		dmae->len = tx_len;
-		dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats));
-		dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats));
-		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
-		dmae->comp_addr_hi = 0;
-		dmae->comp_val = 1;
-
-		/* RX stats */
-		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-		dmae->opcode = opcode;
-		dmae->src_addr_hi = 0;
-		dmae->src_addr_lo = rx_src_addr_lo;
-		dmae->dst_addr_lo =
-			U64_LO(bnx2x_sp_mapping(bp, mac_stats) + (tx_len << 2));
-		dmae->dst_addr_hi =
-			U64_HI(bnx2x_sp_mapping(bp, mac_stats) + (tx_len << 2));
-		dmae->len = rx_len;
-		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
-		dmae->comp_addr_hi = 0;
-		dmae->comp_val = 1;
-	}
-
-	/* NIG */
-	if (!CHIP_IS_E3(bp)) {
-		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-		dmae->opcode = opcode;
-		dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT0 :
-					    NIG_REG_STAT0_EGRESS_MAC_PKT0) >> 2;
-		dmae->src_addr_hi = 0;
-		dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) +
-				offsetof(struct nig_stats, egress_mac_pkt0_lo));
-		dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) +
-				offsetof(struct nig_stats, egress_mac_pkt0_lo));
-		dmae->len = (2*sizeof(u32)) >> 2;
-		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
-		dmae->comp_addr_hi = 0;
-		dmae->comp_val = 1;
-
-		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-		dmae->opcode = opcode;
-		dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT1 :
-					    NIG_REG_STAT0_EGRESS_MAC_PKT1) >> 2;
-		dmae->src_addr_hi = 0;
-		dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) +
-				offsetof(struct nig_stats, egress_mac_pkt1_lo));
-		dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) +
-				offsetof(struct nig_stats, egress_mac_pkt1_lo));
-		dmae->len = (2*sizeof(u32)) >> 2;
-		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
-		dmae->comp_addr_hi = 0;
-		dmae->comp_val = 1;
-	}
-
-	dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-	dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
-						 true, DMAE_COMP_PCI);
-	dmae->src_addr_lo = (port ? NIG_REG_STAT1_BRB_DISCARD :
-				    NIG_REG_STAT0_BRB_DISCARD) >> 2;
-	dmae->src_addr_hi = 0;
-	dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats));
-	dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats));
-	dmae->len = (sizeof(struct nig_stats) - 4*sizeof(u32)) >> 2;
-
-	dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp));
-	dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp));
-	dmae->comp_val = DMAE_COMP_VAL;
-
-	*stats_comp = 0;
-}
-
-static void bnx2x_func_stats_init(struct bnx2x *bp)
-{
-	struct dmae_command *dmae = &bp->stats_dmae;
-	u32 *stats_comp = bnx2x_sp(bp, stats_comp);
-
-	/* sanity */
-	if (!bp->func_stx) {
-		BNX2X_ERR("BUG!\n");
-		return;
-	}
-
-	bp->executer_idx = 0;
-	memset(dmae, 0, sizeof(struct dmae_command));
-
-	dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_PCI, DMAE_DST_GRC,
-					 true, DMAE_COMP_PCI);
-	dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats));
-	dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats));
-	dmae->dst_addr_lo = bp->func_stx >> 2;
-	dmae->dst_addr_hi = 0;
-	dmae->len = sizeof(struct host_func_stats) >> 2;
-	dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp));
-	dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp));
-	dmae->comp_val = DMAE_COMP_VAL;
-
-	*stats_comp = 0;
-}
-
-static void bnx2x_stats_start(struct bnx2x *bp)
-{
-	if (bp->port.pmf)
-		bnx2x_port_stats_init(bp);
-
-	else if (bp->func_stx)
-		bnx2x_func_stats_init(bp);
-
-	bnx2x_hw_stats_post(bp);
-	bnx2x_storm_stats_post(bp);
-}
-
-static void bnx2x_stats_pmf_start(struct bnx2x *bp)
-{
-	bnx2x_stats_comp(bp);
-	bnx2x_stats_pmf_update(bp);
-	bnx2x_stats_start(bp);
-}
-
-static void bnx2x_stats_restart(struct bnx2x *bp)
-{
-	bnx2x_stats_comp(bp);
-	bnx2x_stats_start(bp);
-}
-
-static void bnx2x_bmac_stats_update(struct bnx2x *bp)
-{
-	struct host_port_stats *pstats = bnx2x_sp(bp, port_stats);
-	struct bnx2x_eth_stats *estats = &bp->eth_stats;
-	struct {
-		u32 lo;
-		u32 hi;
-	} diff;
-
-	if (CHIP_IS_E1x(bp)) {
-		struct bmac1_stats *new = bnx2x_sp(bp, mac_stats.bmac1_stats);
-
-		/* the macros below will use "bmac1_stats" type */
-		UPDATE_STAT64(rx_stat_grerb, rx_stat_ifhcinbadoctets);
-		UPDATE_STAT64(rx_stat_grfcs, rx_stat_dot3statsfcserrors);
-		UPDATE_STAT64(rx_stat_grund, rx_stat_etherstatsundersizepkts);
-		UPDATE_STAT64(rx_stat_grovr, rx_stat_dot3statsframestoolong);
-		UPDATE_STAT64(rx_stat_grfrg, rx_stat_etherstatsfragments);
-		UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
-		UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
-		UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
-		UPDATE_STAT64(rx_stat_grxpf, rx_stat_mac_xpf);
-
-		UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
-		UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone);
-		UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets);
-		UPDATE_STAT64(tx_stat_gt127,
-				tx_stat_etherstatspkts65octetsto127octets);
-		UPDATE_STAT64(tx_stat_gt255,
-				tx_stat_etherstatspkts128octetsto255octets);
-		UPDATE_STAT64(tx_stat_gt511,
-				tx_stat_etherstatspkts256octetsto511octets);
-		UPDATE_STAT64(tx_stat_gt1023,
-				tx_stat_etherstatspkts512octetsto1023octets);
-		UPDATE_STAT64(tx_stat_gt1518,
-				tx_stat_etherstatspkts1024octetsto1522octets);
-		UPDATE_STAT64(tx_stat_gt2047, tx_stat_mac_2047);
-		UPDATE_STAT64(tx_stat_gt4095, tx_stat_mac_4095);
-		UPDATE_STAT64(tx_stat_gt9216, tx_stat_mac_9216);
-		UPDATE_STAT64(tx_stat_gt16383, tx_stat_mac_16383);
-		UPDATE_STAT64(tx_stat_gterr,
-				tx_stat_dot3statsinternalmactransmiterrors);
-		UPDATE_STAT64(tx_stat_gtufl, tx_stat_mac_ufl);
-
-	} else {
-		struct bmac2_stats *new = bnx2x_sp(bp, mac_stats.bmac2_stats);
-
-		/* the macros below will use "bmac2_stats" type */
-		UPDATE_STAT64(rx_stat_grerb, rx_stat_ifhcinbadoctets);
-		UPDATE_STAT64(rx_stat_grfcs, rx_stat_dot3statsfcserrors);
-		UPDATE_STAT64(rx_stat_grund, rx_stat_etherstatsundersizepkts);
-		UPDATE_STAT64(rx_stat_grovr, rx_stat_dot3statsframestoolong);
-		UPDATE_STAT64(rx_stat_grfrg, rx_stat_etherstatsfragments);
-		UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
-		UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
-		UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
-		UPDATE_STAT64(rx_stat_grxpf, rx_stat_mac_xpf);
-		UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
-		UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone);
-		UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets);
-		UPDATE_STAT64(tx_stat_gt127,
-				tx_stat_etherstatspkts65octetsto127octets);
-		UPDATE_STAT64(tx_stat_gt255,
-				tx_stat_etherstatspkts128octetsto255octets);
-		UPDATE_STAT64(tx_stat_gt511,
-				tx_stat_etherstatspkts256octetsto511octets);
-		UPDATE_STAT64(tx_stat_gt1023,
-				tx_stat_etherstatspkts512octetsto1023octets);
-		UPDATE_STAT64(tx_stat_gt1518,
-				tx_stat_etherstatspkts1024octetsto1522octets);
-		UPDATE_STAT64(tx_stat_gt2047, tx_stat_mac_2047);
-		UPDATE_STAT64(tx_stat_gt4095, tx_stat_mac_4095);
-		UPDATE_STAT64(tx_stat_gt9216, tx_stat_mac_9216);
-		UPDATE_STAT64(tx_stat_gt16383, tx_stat_mac_16383);
-		UPDATE_STAT64(tx_stat_gterr,
-				tx_stat_dot3statsinternalmactransmiterrors);
-		UPDATE_STAT64(tx_stat_gtufl, tx_stat_mac_ufl);
-	}
-
-	estats->pause_frames_received_hi =
-				pstats->mac_stx[1].rx_stat_mac_xpf_hi;
-	estats->pause_frames_received_lo =
-				pstats->mac_stx[1].rx_stat_mac_xpf_lo;
-
-	estats->pause_frames_sent_hi =
-				pstats->mac_stx[1].tx_stat_outxoffsent_hi;
-	estats->pause_frames_sent_lo =
-				pstats->mac_stx[1].tx_stat_outxoffsent_lo;
-}
-
-static void bnx2x_mstat_stats_update(struct bnx2x *bp)
-{
-	struct host_port_stats *pstats = bnx2x_sp(bp, port_stats);
-	struct bnx2x_eth_stats *estats = &bp->eth_stats;
-
-	struct mstat_stats *new = bnx2x_sp(bp, mac_stats.mstat_stats);
-
-	ADD_STAT64(stats_rx.rx_grerb, rx_stat_ifhcinbadoctets);
-	ADD_STAT64(stats_rx.rx_grfcs, rx_stat_dot3statsfcserrors);
-	ADD_STAT64(stats_rx.rx_grund, rx_stat_etherstatsundersizepkts);
-	ADD_STAT64(stats_rx.rx_grovr, rx_stat_dot3statsframestoolong);
-	ADD_STAT64(stats_rx.rx_grfrg, rx_stat_etherstatsfragments);
-	ADD_STAT64(stats_rx.rx_grxcf, rx_stat_maccontrolframesreceived);
-	ADD_STAT64(stats_rx.rx_grxpf, rx_stat_xoffstateentered);
-	ADD_STAT64(stats_rx.rx_grxpf, rx_stat_mac_xpf);
-	ADD_STAT64(stats_tx.tx_gtxpf, tx_stat_outxoffsent);
-	ADD_STAT64(stats_tx.tx_gtxpf, tx_stat_flowcontroldone);
-
-
-	ADD_STAT64(stats_tx.tx_gt64, tx_stat_etherstatspkts64octets);
-	ADD_STAT64(stats_tx.tx_gt127,
-			tx_stat_etherstatspkts65octetsto127octets);
-	ADD_STAT64(stats_tx.tx_gt255,
-			tx_stat_etherstatspkts128octetsto255octets);
-	ADD_STAT64(stats_tx.tx_gt511,
-			tx_stat_etherstatspkts256octetsto511octets);
-	ADD_STAT64(stats_tx.tx_gt1023,
-			tx_stat_etherstatspkts512octetsto1023octets);
-	ADD_STAT64(stats_tx.tx_gt1518,
-			tx_stat_etherstatspkts1024octetsto1522octets);
-	ADD_STAT64(stats_tx.tx_gt2047, tx_stat_mac_2047);
-
-	ADD_STAT64(stats_tx.tx_gt4095, tx_stat_mac_4095);
-	ADD_STAT64(stats_tx.tx_gt9216, tx_stat_mac_9216);
-	ADD_STAT64(stats_tx.tx_gt16383, tx_stat_mac_16383);
-
-	ADD_STAT64(stats_tx.tx_gterr,
-			tx_stat_dot3statsinternalmactransmiterrors);
-	ADD_STAT64(stats_tx.tx_gtufl, tx_stat_mac_ufl);
-
-	ADD_64(estats->etherstatspkts1024octetsto1522octets_hi,
-	       new->stats_tx.tx_gt1518_hi,
-	       estats->etherstatspkts1024octetsto1522octets_lo,
-	       new->stats_tx.tx_gt1518_lo);
-
-	ADD_64(estats->etherstatspktsover1522octets_hi,
-	       new->stats_tx.tx_gt2047_hi,
-	       estats->etherstatspktsover1522octets_lo,
-	       new->stats_tx.tx_gt2047_lo);
-
-	ADD_64(estats->etherstatspktsover1522octets_hi,
-	       new->stats_tx.tx_gt4095_hi,
-	       estats->etherstatspktsover1522octets_lo,
-	       new->stats_tx.tx_gt4095_lo);
-
-	ADD_64(estats->etherstatspktsover1522octets_hi,
-	       new->stats_tx.tx_gt9216_hi,
-	       estats->etherstatspktsover1522octets_lo,
-	       new->stats_tx.tx_gt9216_lo);
-
-
-	ADD_64(estats->etherstatspktsover1522octets_hi,
-	       new->stats_tx.tx_gt16383_hi,
-	       estats->etherstatspktsover1522octets_lo,
-	       new->stats_tx.tx_gt16383_lo);
-
-	estats->pause_frames_received_hi =
-				pstats->mac_stx[1].rx_stat_mac_xpf_hi;
-	estats->pause_frames_received_lo =
-				pstats->mac_stx[1].rx_stat_mac_xpf_lo;
-
-	estats->pause_frames_sent_hi =
-				pstats->mac_stx[1].tx_stat_outxoffsent_hi;
-	estats->pause_frames_sent_lo =
-				pstats->mac_stx[1].tx_stat_outxoffsent_lo;
-}
-
-static void bnx2x_emac_stats_update(struct bnx2x *bp)
-{
-	struct emac_stats *new = bnx2x_sp(bp, mac_stats.emac_stats);
-	struct host_port_stats *pstats = bnx2x_sp(bp, port_stats);
-	struct bnx2x_eth_stats *estats = &bp->eth_stats;
-
-	UPDATE_EXTEND_STAT(rx_stat_ifhcinbadoctets);
-	UPDATE_EXTEND_STAT(tx_stat_ifhcoutbadoctets);
-	UPDATE_EXTEND_STAT(rx_stat_dot3statsfcserrors);
-	UPDATE_EXTEND_STAT(rx_stat_dot3statsalignmenterrors);
-	UPDATE_EXTEND_STAT(rx_stat_dot3statscarriersenseerrors);
-	UPDATE_EXTEND_STAT(rx_stat_falsecarriererrors);
-	UPDATE_EXTEND_STAT(rx_stat_etherstatsundersizepkts);
-	UPDATE_EXTEND_STAT(rx_stat_dot3statsframestoolong);
-	UPDATE_EXTEND_STAT(rx_stat_etherstatsfragments);
-	UPDATE_EXTEND_STAT(rx_stat_etherstatsjabbers);
-	UPDATE_EXTEND_STAT(rx_stat_maccontrolframesreceived);
-	UPDATE_EXTEND_STAT(rx_stat_xoffstateentered);
-	UPDATE_EXTEND_STAT(rx_stat_xonpauseframesreceived);
-	UPDATE_EXTEND_STAT(rx_stat_xoffpauseframesreceived);
-	UPDATE_EXTEND_STAT(tx_stat_outxonsent);
-	UPDATE_EXTEND_STAT(tx_stat_outxoffsent);
-	UPDATE_EXTEND_STAT(tx_stat_flowcontroldone);
-	UPDATE_EXTEND_STAT(tx_stat_etherstatscollisions);
-	UPDATE_EXTEND_STAT(tx_stat_dot3statssinglecollisionframes);
-	UPDATE_EXTEND_STAT(tx_stat_dot3statsmultiplecollisionframes);
-	UPDATE_EXTEND_STAT(tx_stat_dot3statsdeferredtransmissions);
-	UPDATE_EXTEND_STAT(tx_stat_dot3statsexcessivecollisions);
-	UPDATE_EXTEND_STAT(tx_stat_dot3statslatecollisions);
-	UPDATE_EXTEND_STAT(tx_stat_etherstatspkts64octets);
-	UPDATE_EXTEND_STAT(tx_stat_etherstatspkts65octetsto127octets);
-	UPDATE_EXTEND_STAT(tx_stat_etherstatspkts128octetsto255octets);
-	UPDATE_EXTEND_STAT(tx_stat_etherstatspkts256octetsto511octets);
-	UPDATE_EXTEND_STAT(tx_stat_etherstatspkts512octetsto1023octets);
-	UPDATE_EXTEND_STAT(tx_stat_etherstatspkts1024octetsto1522octets);
-	UPDATE_EXTEND_STAT(tx_stat_etherstatspktsover1522octets);
-	UPDATE_EXTEND_STAT(tx_stat_dot3statsinternalmactransmiterrors);
-
-	estats->pause_frames_received_hi =
-			pstats->mac_stx[1].rx_stat_xonpauseframesreceived_hi;
-	estats->pause_frames_received_lo =
-			pstats->mac_stx[1].rx_stat_xonpauseframesreceived_lo;
-	ADD_64(estats->pause_frames_received_hi,
-	       pstats->mac_stx[1].rx_stat_xoffpauseframesreceived_hi,
-	       estats->pause_frames_received_lo,
-	       pstats->mac_stx[1].rx_stat_xoffpauseframesreceived_lo);
-
-	estats->pause_frames_sent_hi =
-			pstats->mac_stx[1].tx_stat_outxonsent_hi;
-	estats->pause_frames_sent_lo =
-			pstats->mac_stx[1].tx_stat_outxonsent_lo;
-	ADD_64(estats->pause_frames_sent_hi,
-	       pstats->mac_stx[1].tx_stat_outxoffsent_hi,
-	       estats->pause_frames_sent_lo,
-	       pstats->mac_stx[1].tx_stat_outxoffsent_lo);
-}
-
-static int bnx2x_hw_stats_update(struct bnx2x *bp)
-{
-	struct nig_stats *new = bnx2x_sp(bp, nig_stats);
-	struct nig_stats *old = &(bp->port.old_nig_stats);
-	struct host_port_stats *pstats = bnx2x_sp(bp, port_stats);
-	struct bnx2x_eth_stats *estats = &bp->eth_stats;
-	struct {
-		u32 lo;
-		u32 hi;
-	} diff;
-
-	switch (bp->link_vars.mac_type) {
-	case MAC_TYPE_BMAC:
-		bnx2x_bmac_stats_update(bp);
-		break;
-
-	case MAC_TYPE_EMAC:
-		bnx2x_emac_stats_update(bp);
-		break;
-
-	case MAC_TYPE_UMAC:
-	case MAC_TYPE_XMAC:
-		bnx2x_mstat_stats_update(bp);
-		break;
-
-	case MAC_TYPE_NONE: /* unreached */
-		DP(BNX2X_MSG_STATS,
-		   "stats updated by DMAE but no MAC active\n");
-		return -1;
-
-	default: /* unreached */
-		BNX2X_ERR("Unknown MAC type\n");
-	}
-
-	ADD_EXTEND_64(pstats->brb_drop_hi, pstats->brb_drop_lo,
-		      new->brb_discard - old->brb_discard);
-	ADD_EXTEND_64(estats->brb_truncate_hi, estats->brb_truncate_lo,
-		      new->brb_truncate - old->brb_truncate);
-
-	if (!CHIP_IS_E3(bp)) {
-		UPDATE_STAT64_NIG(egress_mac_pkt0,
-					etherstatspkts1024octetsto1522octets);
-		UPDATE_STAT64_NIG(egress_mac_pkt1,
-					etherstatspktsover1522octets);
-	}
-
-	memcpy(old, new, sizeof(struct nig_stats));
-
-	memcpy(&(estats->rx_stat_ifhcinbadoctets_hi), &(pstats->mac_stx[1]),
-	       sizeof(struct mac_stx));
-	estats->brb_drop_hi = pstats->brb_drop_hi;
-	estats->brb_drop_lo = pstats->brb_drop_lo;
-
-	pstats->host_port_stats_start = ++pstats->host_port_stats_end;
-
-	if (!BP_NOMCP(bp)) {
-		u32 nig_timer_max =
-			SHMEM_RD(bp, port_mb[BP_PORT(bp)].stat_nig_timer);
-		if (nig_timer_max != estats->nig_timer_max) {
-			estats->nig_timer_max = nig_timer_max;
-			BNX2X_ERR("NIG timer max (%u)\n",
-				  estats->nig_timer_max);
-		}
-	}
-
-	return 0;
-}
-
-static int bnx2x_storm_stats_update(struct bnx2x *bp)
-{
-	struct tstorm_per_port_stats *tport =
-				&bp->fw_stats_data->port.tstorm_port_statistics;
-	struct tstorm_per_pf_stats *tfunc =
-				&bp->fw_stats_data->pf.tstorm_pf_statistics;
-	struct host_func_stats *fstats = bnx2x_sp(bp, func_stats);
-	struct bnx2x_eth_stats *estats = &bp->eth_stats;
-	struct stats_counter *counters = &bp->fw_stats_data->storm_counters;
-	int i;
-	u16 cur_stats_counter;
-
-	/* Make sure we use the value of the counter
-	 * used for sending the last stats ramrod.
-	 */
-	spin_lock_bh(&bp->stats_lock);
-	cur_stats_counter = bp->stats_counter - 1;
-	spin_unlock_bh(&bp->stats_lock);
-
-	/* are storm stats valid? */
-	if (le16_to_cpu(counters->xstats_counter) != cur_stats_counter) {
-		DP(BNX2X_MSG_STATS, "stats not updated by xstorm"
-		   "  xstorm counter (0x%x) != stats_counter (0x%x)\n",
-		   le16_to_cpu(counters->xstats_counter), bp->stats_counter);
-		return -EAGAIN;
-	}
-
-	if (le16_to_cpu(counters->ustats_counter) != cur_stats_counter) {
-		DP(BNX2X_MSG_STATS, "stats not updated by ustorm"
-		   "  ustorm counter (0x%x) != stats_counter (0x%x)\n",
-		   le16_to_cpu(counters->ustats_counter), bp->stats_counter);
-		return -EAGAIN;
-	}
-
-	if (le16_to_cpu(counters->cstats_counter) != cur_stats_counter) {
-		DP(BNX2X_MSG_STATS, "stats not updated by cstorm"
-		   "  cstorm counter (0x%x) != stats_counter (0x%x)\n",
-		   le16_to_cpu(counters->cstats_counter), bp->stats_counter);
-		return -EAGAIN;
-	}
-
-	if (le16_to_cpu(counters->tstats_counter) != cur_stats_counter) {
-		DP(BNX2X_MSG_STATS, "stats not updated by tstorm"
-		   "  tstorm counter (0x%x) != stats_counter (0x%x)\n",
-		   le16_to_cpu(counters->tstats_counter), bp->stats_counter);
-		return -EAGAIN;
-	}
-
-	memcpy(&(fstats->total_bytes_received_hi),
-	       &(bnx2x_sp(bp, func_stats_base)->total_bytes_received_hi),
-	       sizeof(struct host_func_stats) - 2*sizeof(u32));
-	estats->error_bytes_received_hi = 0;
-	estats->error_bytes_received_lo = 0;
-	estats->etherstatsoverrsizepkts_hi = 0;
-	estats->etherstatsoverrsizepkts_lo = 0;
-	estats->no_buff_discard_hi = 0;
-	estats->no_buff_discard_lo = 0;
-	estats->total_tpa_aggregations_hi = 0;
-	estats->total_tpa_aggregations_lo = 0;
-	estats->total_tpa_aggregated_frames_hi = 0;
-	estats->total_tpa_aggregated_frames_lo = 0;
-	estats->total_tpa_bytes_hi = 0;
-	estats->total_tpa_bytes_lo = 0;
-
-	for_each_eth_queue(bp, i) {
-		struct bnx2x_fastpath *fp = &bp->fp[i];
-		struct tstorm_per_queue_stats *tclient =
-			&bp->fw_stats_data->queue_stats[i].
-			tstorm_queue_statistics;
-		struct tstorm_per_queue_stats *old_tclient = &fp->old_tclient;
-		struct ustorm_per_queue_stats *uclient =
-			&bp->fw_stats_data->queue_stats[i].
-			ustorm_queue_statistics;
-		struct ustorm_per_queue_stats *old_uclient = &fp->old_uclient;
-		struct xstorm_per_queue_stats *xclient =
-			&bp->fw_stats_data->queue_stats[i].
-			xstorm_queue_statistics;
-		struct xstorm_per_queue_stats *old_xclient = &fp->old_xclient;
-		struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
-		u32 diff;
-
-		DP(BNX2X_MSG_STATS, "queue[%d]: ucast_sent 0x%x, "
-				    "bcast_sent 0x%x mcast_sent 0x%x\n",
-		   i, xclient->ucast_pkts_sent,
-		   xclient->bcast_pkts_sent, xclient->mcast_pkts_sent);
-
-		DP(BNX2X_MSG_STATS, "---------------\n");
-
-		qstats->total_broadcast_bytes_received_hi =
-			le32_to_cpu(tclient->rcv_bcast_bytes.hi);
-		qstats->total_broadcast_bytes_received_lo =
-			le32_to_cpu(tclient->rcv_bcast_bytes.lo);
-
-		qstats->total_multicast_bytes_received_hi =
-			le32_to_cpu(tclient->rcv_mcast_bytes.hi);
-		qstats->total_multicast_bytes_received_lo =
-			le32_to_cpu(tclient->rcv_mcast_bytes.lo);
-
-		qstats->total_unicast_bytes_received_hi =
-			le32_to_cpu(tclient->rcv_ucast_bytes.hi);
-		qstats->total_unicast_bytes_received_lo =
-			le32_to_cpu(tclient->rcv_ucast_bytes.lo);
-
-		/*
-		 * sum to total_bytes_received all
-		 * unicast/multicast/broadcast
-		 */
-		qstats->total_bytes_received_hi =
-			qstats->total_broadcast_bytes_received_hi;
-		qstats->total_bytes_received_lo =
-			qstats->total_broadcast_bytes_received_lo;
-
-		ADD_64(qstats->total_bytes_received_hi,
-		       qstats->total_multicast_bytes_received_hi,
-		       qstats->total_bytes_received_lo,
-		       qstats->total_multicast_bytes_received_lo);
-
-		ADD_64(qstats->total_bytes_received_hi,
-		       qstats->total_unicast_bytes_received_hi,
-		       qstats->total_bytes_received_lo,
-		       qstats->total_unicast_bytes_received_lo);
-
-		qstats->valid_bytes_received_hi =
-					qstats->total_bytes_received_hi;
-		qstats->valid_bytes_received_lo =
-					qstats->total_bytes_received_lo;
-
-
-		UPDATE_EXTEND_TSTAT(rcv_ucast_pkts,
-					total_unicast_packets_received);
-		UPDATE_EXTEND_TSTAT(rcv_mcast_pkts,
-					total_multicast_packets_received);
-		UPDATE_EXTEND_TSTAT(rcv_bcast_pkts,
-					total_broadcast_packets_received);
-		UPDATE_EXTEND_TSTAT(pkts_too_big_discard,
-					etherstatsoverrsizepkts);
-		UPDATE_EXTEND_TSTAT(no_buff_discard, no_buff_discard);
-
-		SUB_EXTEND_USTAT(ucast_no_buff_pkts,
-					total_unicast_packets_received);
-		SUB_EXTEND_USTAT(mcast_no_buff_pkts,
-					total_multicast_packets_received);
-		SUB_EXTEND_USTAT(bcast_no_buff_pkts,
-					total_broadcast_packets_received);
-		UPDATE_EXTEND_USTAT(ucast_no_buff_pkts, no_buff_discard);
-		UPDATE_EXTEND_USTAT(mcast_no_buff_pkts, no_buff_discard);
-		UPDATE_EXTEND_USTAT(bcast_no_buff_pkts, no_buff_discard);
-
-		qstats->total_broadcast_bytes_transmitted_hi =
-			le32_to_cpu(xclient->bcast_bytes_sent.hi);
-		qstats->total_broadcast_bytes_transmitted_lo =
-			le32_to_cpu(xclient->bcast_bytes_sent.lo);
-
-		qstats->total_multicast_bytes_transmitted_hi =
-			le32_to_cpu(xclient->mcast_bytes_sent.hi);
-		qstats->total_multicast_bytes_transmitted_lo =
-			le32_to_cpu(xclient->mcast_bytes_sent.lo);
-
-		qstats->total_unicast_bytes_transmitted_hi =
-			le32_to_cpu(xclient->ucast_bytes_sent.hi);
-		qstats->total_unicast_bytes_transmitted_lo =
-			le32_to_cpu(xclient->ucast_bytes_sent.lo);
-		/*
-		 * sum to total_bytes_transmitted all
-		 * unicast/multicast/broadcast
-		 */
-		qstats->total_bytes_transmitted_hi =
-				qstats->total_unicast_bytes_transmitted_hi;
-		qstats->total_bytes_transmitted_lo =
-				qstats->total_unicast_bytes_transmitted_lo;
-
-		ADD_64(qstats->total_bytes_transmitted_hi,
-		       qstats->total_broadcast_bytes_transmitted_hi,
-		       qstats->total_bytes_transmitted_lo,
-		       qstats->total_broadcast_bytes_transmitted_lo);
-
-		ADD_64(qstats->total_bytes_transmitted_hi,
-		       qstats->total_multicast_bytes_transmitted_hi,
-		       qstats->total_bytes_transmitted_lo,
-		       qstats->total_multicast_bytes_transmitted_lo);
-
-		UPDATE_EXTEND_XSTAT(ucast_pkts_sent,
-					total_unicast_packets_transmitted);
-		UPDATE_EXTEND_XSTAT(mcast_pkts_sent,
-					total_multicast_packets_transmitted);
-		UPDATE_EXTEND_XSTAT(bcast_pkts_sent,
-					total_broadcast_packets_transmitted);
-
-		UPDATE_EXTEND_TSTAT(checksum_discard,
-				    total_packets_received_checksum_discarded);
-		UPDATE_EXTEND_TSTAT(ttl0_discard,
-				    total_packets_received_ttl0_discarded);
-
-		UPDATE_EXTEND_XSTAT(error_drop_pkts,
-				    total_transmitted_dropped_packets_error);
-
-		/* TPA aggregations completed */
-		UPDATE_EXTEND_USTAT(coalesced_events, total_tpa_aggregations);
-		/* Number of network frames aggregated by TPA */
-		UPDATE_EXTEND_USTAT(coalesced_pkts,
-				    total_tpa_aggregated_frames);
-		/* Total number of bytes in completed TPA aggregations */
-		qstats->total_tpa_bytes_lo =
-			le32_to_cpu(uclient->coalesced_bytes.lo);
-		qstats->total_tpa_bytes_hi =
-			le32_to_cpu(uclient->coalesced_bytes.hi);
-
-		/* TPA stats per-function */
-		ADD_64(estats->total_tpa_aggregations_hi,
-		       qstats->total_tpa_aggregations_hi,
-		       estats->total_tpa_aggregations_lo,
-		       qstats->total_tpa_aggregations_lo);
-		ADD_64(estats->total_tpa_aggregated_frames_hi,
-		       qstats->total_tpa_aggregated_frames_hi,
-		       estats->total_tpa_aggregated_frames_lo,
-		       qstats->total_tpa_aggregated_frames_lo);
-		ADD_64(estats->total_tpa_bytes_hi,
-		       qstats->total_tpa_bytes_hi,
-		       estats->total_tpa_bytes_lo,
-		       qstats->total_tpa_bytes_lo);
-
-		ADD_64(fstats->total_bytes_received_hi,
-		       qstats->total_bytes_received_hi,
-		       fstats->total_bytes_received_lo,
-		       qstats->total_bytes_received_lo);
-		ADD_64(fstats->total_bytes_transmitted_hi,
-		       qstats->total_bytes_transmitted_hi,
-		       fstats->total_bytes_transmitted_lo,
-		       qstats->total_bytes_transmitted_lo);
-		ADD_64(fstats->total_unicast_packets_received_hi,
-		       qstats->total_unicast_packets_received_hi,
-		       fstats->total_unicast_packets_received_lo,
-		       qstats->total_unicast_packets_received_lo);
-		ADD_64(fstats->total_multicast_packets_received_hi,
-		       qstats->total_multicast_packets_received_hi,
-		       fstats->total_multicast_packets_received_lo,
-		       qstats->total_multicast_packets_received_lo);
-		ADD_64(fstats->total_broadcast_packets_received_hi,
-		       qstats->total_broadcast_packets_received_hi,
-		       fstats->total_broadcast_packets_received_lo,
-		       qstats->total_broadcast_packets_received_lo);
-		ADD_64(fstats->total_unicast_packets_transmitted_hi,
-		       qstats->total_unicast_packets_transmitted_hi,
-		       fstats->total_unicast_packets_transmitted_lo,
-		       qstats->total_unicast_packets_transmitted_lo);
-		ADD_64(fstats->total_multicast_packets_transmitted_hi,
-		       qstats->total_multicast_packets_transmitted_hi,
-		       fstats->total_multicast_packets_transmitted_lo,
-		       qstats->total_multicast_packets_transmitted_lo);
-		ADD_64(fstats->total_broadcast_packets_transmitted_hi,
-		       qstats->total_broadcast_packets_transmitted_hi,
-		       fstats->total_broadcast_packets_transmitted_lo,
-		       qstats->total_broadcast_packets_transmitted_lo);
-		ADD_64(fstats->valid_bytes_received_hi,
-		       qstats->valid_bytes_received_hi,
-		       fstats->valid_bytes_received_lo,
-		       qstats->valid_bytes_received_lo);
-
-		ADD_64(estats->etherstatsoverrsizepkts_hi,
-		       qstats->etherstatsoverrsizepkts_hi,
-		       estats->etherstatsoverrsizepkts_lo,
-		       qstats->etherstatsoverrsizepkts_lo);
-		ADD_64(estats->no_buff_discard_hi, qstats->no_buff_discard_hi,
-		       estats->no_buff_discard_lo, qstats->no_buff_discard_lo);
-	}
-
-	ADD_64(fstats->total_bytes_received_hi,
-	       estats->rx_stat_ifhcinbadoctets_hi,
-	       fstats->total_bytes_received_lo,
-	       estats->rx_stat_ifhcinbadoctets_lo);
-
-	ADD_64(fstats->total_bytes_received_hi,
-	       tfunc->rcv_error_bytes.hi,
-	       fstats->total_bytes_received_lo,
-	       tfunc->rcv_error_bytes.lo);
-
-	memcpy(estats, &(fstats->total_bytes_received_hi),
-	       sizeof(struct host_func_stats) - 2*sizeof(u32));
-
-	ADD_64(estats->error_bytes_received_hi,
-	       tfunc->rcv_error_bytes.hi,
-	       estats->error_bytes_received_lo,
-	       tfunc->rcv_error_bytes.lo);
-
-	ADD_64(estats->etherstatsoverrsizepkts_hi,
-	       estats->rx_stat_dot3statsframestoolong_hi,
-	       estats->etherstatsoverrsizepkts_lo,
-	       estats->rx_stat_dot3statsframestoolong_lo);
-	ADD_64(estats->error_bytes_received_hi,
-	       estats->rx_stat_ifhcinbadoctets_hi,
-	       estats->error_bytes_received_lo,
-	       estats->rx_stat_ifhcinbadoctets_lo);
-
-	if (bp->port.pmf) {
-		estats->mac_filter_discard =
-				le32_to_cpu(tport->mac_filter_discard);
-		estats->mf_tag_discard =
-				le32_to_cpu(tport->mf_tag_discard);
-		estats->brb_truncate_discard =
-				le32_to_cpu(tport->brb_truncate_discard);
-		estats->mac_discard = le32_to_cpu(tport->mac_discard);
-	}
-
-	fstats->host_func_stats_start = ++fstats->host_func_stats_end;
-
-	bp->stats_pending = 0;
-
-	return 0;
-}
-
-static void bnx2x_net_stats_update(struct bnx2x *bp)
-{
-	struct bnx2x_eth_stats *estats = &bp->eth_stats;
-	struct net_device_stats *nstats = &bp->dev->stats;
-	unsigned long tmp;
-	int i;
-
-	nstats->rx_packets =
-		bnx2x_hilo(&estats->total_unicast_packets_received_hi) +
-		bnx2x_hilo(&estats->total_multicast_packets_received_hi) +
-		bnx2x_hilo(&estats->total_broadcast_packets_received_hi);
-
-	nstats->tx_packets =
-		bnx2x_hilo(&estats->total_unicast_packets_transmitted_hi) +
-		bnx2x_hilo(&estats->total_multicast_packets_transmitted_hi) +
-		bnx2x_hilo(&estats->total_broadcast_packets_transmitted_hi);
-
-	nstats->rx_bytes = bnx2x_hilo(&estats->total_bytes_received_hi);
-
-	nstats->tx_bytes = bnx2x_hilo(&estats->total_bytes_transmitted_hi);
-
-	tmp = estats->mac_discard;
-	for_each_rx_queue(bp, i)
-		tmp += le32_to_cpu(bp->fp[i].old_tclient.checksum_discard);
-	nstats->rx_dropped = tmp;
-
-	nstats->tx_dropped = 0;
-
-	nstats->multicast =
-		bnx2x_hilo(&estats->total_multicast_packets_received_hi);
-
-	nstats->collisions =
-		bnx2x_hilo(&estats->tx_stat_etherstatscollisions_hi);
-
-	nstats->rx_length_errors =
-		bnx2x_hilo(&estats->rx_stat_etherstatsundersizepkts_hi) +
-		bnx2x_hilo(&estats->etherstatsoverrsizepkts_hi);
-	nstats->rx_over_errors = bnx2x_hilo(&estats->brb_drop_hi) +
-				 bnx2x_hilo(&estats->brb_truncate_hi);
-	nstats->rx_crc_errors =
-		bnx2x_hilo(&estats->rx_stat_dot3statsfcserrors_hi);
-	nstats->rx_frame_errors =
-		bnx2x_hilo(&estats->rx_stat_dot3statsalignmenterrors_hi);
-	nstats->rx_fifo_errors = bnx2x_hilo(&estats->no_buff_discard_hi);
-	nstats->rx_missed_errors = 0;
-
-	nstats->rx_errors = nstats->rx_length_errors +
-			    nstats->rx_over_errors +
-			    nstats->rx_crc_errors +
-			    nstats->rx_frame_errors +
-			    nstats->rx_fifo_errors +
-			    nstats->rx_missed_errors;
-
-	nstats->tx_aborted_errors =
-		bnx2x_hilo(&estats->tx_stat_dot3statslatecollisions_hi) +
-		bnx2x_hilo(&estats->tx_stat_dot3statsexcessivecollisions_hi);
-	nstats->tx_carrier_errors =
-		bnx2x_hilo(&estats->rx_stat_dot3statscarriersenseerrors_hi);
-	nstats->tx_fifo_errors = 0;
-	nstats->tx_heartbeat_errors = 0;
-	nstats->tx_window_errors = 0;
-
-	nstats->tx_errors = nstats->tx_aborted_errors +
-			    nstats->tx_carrier_errors +
-	    bnx2x_hilo(&estats->tx_stat_dot3statsinternalmactransmiterrors_hi);
-}
-
-static void bnx2x_drv_stats_update(struct bnx2x *bp)
-{
-	struct bnx2x_eth_stats *estats = &bp->eth_stats;
-	int i;
-
-	estats->driver_xoff = 0;
-	estats->rx_err_discard_pkt = 0;
-	estats->rx_skb_alloc_failed = 0;
-	estats->hw_csum_err = 0;
-	for_each_queue(bp, i) {
-		struct bnx2x_eth_q_stats *qstats = &bp->fp[i].eth_q_stats;
-
-		estats->driver_xoff += qstats->driver_xoff;
-		estats->rx_err_discard_pkt += qstats->rx_err_discard_pkt;
-		estats->rx_skb_alloc_failed += qstats->rx_skb_alloc_failed;
-		estats->hw_csum_err += qstats->hw_csum_err;
-	}
-}
-
-static bool bnx2x_edebug_stats_stopped(struct bnx2x *bp)
-{
-	u32 val;
-
-	if (SHMEM2_HAS(bp, edebug_driver_if[1])) {
-		val = SHMEM2_RD(bp, edebug_driver_if[1]);
-
-		if (val == EDEBUG_DRIVER_IF_OP_CODE_DISABLE_STAT)
-			return true;
-	}
-
-	return false;
-}
-
-static void bnx2x_stats_update(struct bnx2x *bp)
-{
-	u32 *stats_comp = bnx2x_sp(bp, stats_comp);
-
-	if (bnx2x_edebug_stats_stopped(bp))
-		return;
-
-	if (*stats_comp != DMAE_COMP_VAL)
-		return;
-
-	if (bp->port.pmf)
-		bnx2x_hw_stats_update(bp);
-
-	if (bnx2x_storm_stats_update(bp) && (bp->stats_pending++ == 3)) {
-		BNX2X_ERR("storm stats were not updated for 3 times\n");
-		bnx2x_panic();
-		return;
-	}
-
-	bnx2x_net_stats_update(bp);
-	bnx2x_drv_stats_update(bp);
-
-	if (netif_msg_timer(bp)) {
-		struct bnx2x_eth_stats *estats = &bp->eth_stats;
-		int i, cos;
-
-		netdev_dbg(bp->dev, "brb drops %u  brb truncate %u\n",
-		       estats->brb_drop_lo, estats->brb_truncate_lo);
-
-		for_each_eth_queue(bp, i) {
-			struct bnx2x_fastpath *fp = &bp->fp[i];
-			struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
-
-			printk(KERN_DEBUG "%s: rx usage(%4u)  *rx_cons_sb(%u)"
-					  "  rx pkt(%lu)  rx calls(%lu %lu)\n",
-			       fp->name, (le16_to_cpu(*fp->rx_cons_sb) -
-			       fp->rx_comp_cons),
-			       le16_to_cpu(*fp->rx_cons_sb),
-			       bnx2x_hilo(&qstats->
-					  total_unicast_packets_received_hi),
-			       fp->rx_calls, fp->rx_pkt);
-		}
-
-		for_each_eth_queue(bp, i) {
-			struct bnx2x_fastpath *fp = &bp->fp[i];
-			struct bnx2x_fp_txdata *txdata;
-			struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
-			struct netdev_queue *txq;
-
-			printk(KERN_DEBUG "%s: tx pkt(%lu) (Xoff events %u)",
-				fp->name, bnx2x_hilo(
-				&qstats->total_unicast_packets_transmitted_hi),
-				qstats->driver_xoff);
-
-			for_each_cos_in_tx_queue(fp, cos) {
-				txdata = &fp->txdata[cos];
-				txq = netdev_get_tx_queue(bp->dev,
-						FP_COS_TO_TXQ(fp, cos));
-
-				printk(KERN_DEBUG "%d: tx avail(%4u)"
-				       "  *tx_cons_sb(%u)"
-				       "  tx calls (%lu)"
-				       "  %s\n",
-				       cos,
-				       bnx2x_tx_avail(bp, txdata),
-				       le16_to_cpu(*txdata->tx_cons_sb),
-				       txdata->tx_pkt,
-				       (netif_tx_queue_stopped(txq) ?
-					"Xoff" : "Xon")
-				       );
-			}
-		}
-	}
-
-	bnx2x_hw_stats_post(bp);
-	bnx2x_storm_stats_post(bp);
-}
-
-static void bnx2x_port_stats_stop(struct bnx2x *bp)
-{
-	struct dmae_command *dmae;
-	u32 opcode;
-	int loader_idx = PMF_DMAE_C(bp);
-	u32 *stats_comp = bnx2x_sp(bp, stats_comp);
-
-	bp->executer_idx = 0;
-
-	opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_PCI, DMAE_DST_GRC, false, 0);
-
-	if (bp->port.port_stx) {
-
-		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-		if (bp->func_stx)
-			dmae->opcode = bnx2x_dmae_opcode_add_comp(
-						opcode, DMAE_COMP_GRC);
-		else
-			dmae->opcode = bnx2x_dmae_opcode_add_comp(
-						opcode, DMAE_COMP_PCI);
-
-		dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats));
-		dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats));
-		dmae->dst_addr_lo = bp->port.port_stx >> 2;
-		dmae->dst_addr_hi = 0;
-		dmae->len = sizeof(struct host_port_stats) >> 2;
-		if (bp->func_stx) {
-			dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
-			dmae->comp_addr_hi = 0;
-			dmae->comp_val = 1;
-		} else {
-			dmae->comp_addr_lo =
-				U64_LO(bnx2x_sp_mapping(bp, stats_comp));
-			dmae->comp_addr_hi =
-				U64_HI(bnx2x_sp_mapping(bp, stats_comp));
-			dmae->comp_val = DMAE_COMP_VAL;
-
-			*stats_comp = 0;
-		}
-	}
-
-	if (bp->func_stx) {
-
-		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-		dmae->opcode =
-			bnx2x_dmae_opcode_add_comp(opcode, DMAE_COMP_PCI);
-		dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats));
-		dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats));
-		dmae->dst_addr_lo = bp->func_stx >> 2;
-		dmae->dst_addr_hi = 0;
-		dmae->len = sizeof(struct host_func_stats) >> 2;
-		dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp));
-		dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp));
-		dmae->comp_val = DMAE_COMP_VAL;
-
-		*stats_comp = 0;
-	}
-}
-
-static void bnx2x_stats_stop(struct bnx2x *bp)
-{
-	int update = 0;
-
-	bnx2x_stats_comp(bp);
-
-	if (bp->port.pmf)
-		update = (bnx2x_hw_stats_update(bp) == 0);
-
-	update |= (bnx2x_storm_stats_update(bp) == 0);
-
-	if (update) {
-		bnx2x_net_stats_update(bp);
-
-		if (bp->port.pmf)
-			bnx2x_port_stats_stop(bp);
-
-		bnx2x_hw_stats_post(bp);
-		bnx2x_stats_comp(bp);
-	}
-}
-
-static void bnx2x_stats_do_nothing(struct bnx2x *bp)
-{
-}
-
-static const struct {
-	void (*action)(struct bnx2x *bp);
-	enum bnx2x_stats_state next_state;
-} bnx2x_stats_stm[STATS_STATE_MAX][STATS_EVENT_MAX] = {
-/* state	event	*/
-{
-/* DISABLED	PMF	*/ {bnx2x_stats_pmf_update, STATS_STATE_DISABLED},
-/*		LINK_UP	*/ {bnx2x_stats_start,      STATS_STATE_ENABLED},
-/*		UPDATE	*/ {bnx2x_stats_do_nothing, STATS_STATE_DISABLED},
-/*		STOP	*/ {bnx2x_stats_do_nothing, STATS_STATE_DISABLED}
-},
-{
-/* ENABLED	PMF	*/ {bnx2x_stats_pmf_start,  STATS_STATE_ENABLED},
-/*		LINK_UP	*/ {bnx2x_stats_restart,    STATS_STATE_ENABLED},
-/*		UPDATE	*/ {bnx2x_stats_update,     STATS_STATE_ENABLED},
-/*		STOP	*/ {bnx2x_stats_stop,       STATS_STATE_DISABLED}
-}
-};
-
-void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event)
-{
-	enum bnx2x_stats_state state;
-	if (unlikely(bp->panic))
-		return;
-	bnx2x_stats_stm[bp->stats_state][event].action(bp);
-	spin_lock_bh(&bp->stats_lock);
-	state = bp->stats_state;
-	bp->stats_state = bnx2x_stats_stm[state][event].next_state;
-	spin_unlock_bh(&bp->stats_lock);
-
-	if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp))
-		DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n",
-		   state, event, bp->stats_state);
-}
-
-static void bnx2x_port_stats_base_init(struct bnx2x *bp)
-{
-	struct dmae_command *dmae;
-	u32 *stats_comp = bnx2x_sp(bp, stats_comp);
-
-	/* sanity */
-	if (!bp->port.pmf || !bp->port.port_stx) {
-		BNX2X_ERR("BUG!\n");
-		return;
-	}
-
-	bp->executer_idx = 0;
-
-	dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-	dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_PCI, DMAE_DST_GRC,
-					 true, DMAE_COMP_PCI);
-	dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats));
-	dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats));
-	dmae->dst_addr_lo = bp->port.port_stx >> 2;
-	dmae->dst_addr_hi = 0;
-	dmae->len = sizeof(struct host_port_stats) >> 2;
-	dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp));
-	dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp));
-	dmae->comp_val = DMAE_COMP_VAL;
-
-	*stats_comp = 0;
-	bnx2x_hw_stats_post(bp);
-	bnx2x_stats_comp(bp);
-}
-
-static void bnx2x_func_stats_base_init(struct bnx2x *bp)
-{
-	int vn, vn_max = IS_MF(bp) ? BP_MAX_VN_NUM(bp) : E1VN_MAX;
-	u32 func_stx;
-
-	/* sanity */
-	if (!bp->port.pmf || !bp->func_stx) {
-		BNX2X_ERR("BUG!\n");
-		return;
-	}
-
-	/* save our func_stx */
-	func_stx = bp->func_stx;
-
-	for (vn = VN_0; vn < vn_max; vn++) {
-		int mb_idx = BP_FW_MB_IDX_VN(bp, vn);
-
-		bp->func_stx = SHMEM_RD(bp, func_mb[mb_idx].fw_mb_param);
-		bnx2x_func_stats_init(bp);
-		bnx2x_hw_stats_post(bp);
-		bnx2x_stats_comp(bp);
-	}
-
-	/* restore our func_stx */
-	bp->func_stx = func_stx;
-}
-
-static void bnx2x_func_stats_base_update(struct bnx2x *bp)
-{
-	struct dmae_command *dmae = &bp->stats_dmae;
-	u32 *stats_comp = bnx2x_sp(bp, stats_comp);
-
-	/* sanity */
-	if (!bp->func_stx) {
-		BNX2X_ERR("BUG!\n");
-		return;
-	}
-
-	bp->executer_idx = 0;
-	memset(dmae, 0, sizeof(struct dmae_command));
-
-	dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
-					 true, DMAE_COMP_PCI);
-	dmae->src_addr_lo = bp->func_stx >> 2;
-	dmae->src_addr_hi = 0;
-	dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats_base));
-	dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats_base));
-	dmae->len = sizeof(struct host_func_stats) >> 2;
-	dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp));
-	dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp));
-	dmae->comp_val = DMAE_COMP_VAL;
-
-	*stats_comp = 0;
-	bnx2x_hw_stats_post(bp);
-	bnx2x_stats_comp(bp);
-}
-
-/**
- * This function will prepare the statistics ramrod data the way
- * we will only have to increment the statistics counter and
- * send the ramrod each time we have to.
- *
- * @param bp
- */
-static inline void bnx2x_prep_fw_stats_req(struct bnx2x *bp)
-{
-	int i;
-	struct stats_query_header *stats_hdr = &bp->fw_stats_req->hdr;
-
-	dma_addr_t cur_data_offset;
-	struct stats_query_entry *cur_query_entry;
-
-	stats_hdr->cmd_num = bp->fw_stats_num;
-	stats_hdr->drv_stats_counter = 0;
-
-	/* storm_counters struct contains the counters of completed
-	 * statistics requests per storm which are incremented by FW
-	 * each time it completes hadning a statistics ramrod. We will
-	 * check these counters in the timer handler and discard a
-	 * (statistics) ramrod completion.
-	 */
-	cur_data_offset = bp->fw_stats_data_mapping +
-		offsetof(struct bnx2x_fw_stats_data, storm_counters);
-
-	stats_hdr->stats_counters_addrs.hi =
-		cpu_to_le32(U64_HI(cur_data_offset));
-	stats_hdr->stats_counters_addrs.lo =
-		cpu_to_le32(U64_LO(cur_data_offset));
-
-	/* prepare to the first stats ramrod (will be completed with
-	 * the counters equal to zero) - init counters to somethig different.
-	 */
-	memset(&bp->fw_stats_data->storm_counters, 0xff,
-	       sizeof(struct stats_counter));
-
-	/**** Port FW statistics data ****/
-	cur_data_offset = bp->fw_stats_data_mapping +
-		offsetof(struct bnx2x_fw_stats_data, port);
-
-	cur_query_entry = &bp->fw_stats_req->query[BNX2X_PORT_QUERY_IDX];
-
-	cur_query_entry->kind = STATS_TYPE_PORT;
-	/* For port query index is a DONT CARE */
-	cur_query_entry->index = BP_PORT(bp);
-	/* For port query funcID is a DONT CARE */
-	cur_query_entry->funcID = cpu_to_le16(BP_FUNC(bp));
-	cur_query_entry->address.hi = cpu_to_le32(U64_HI(cur_data_offset));
-	cur_query_entry->address.lo = cpu_to_le32(U64_LO(cur_data_offset));
-
-	/**** PF FW statistics data ****/
-	cur_data_offset = bp->fw_stats_data_mapping +
-		offsetof(struct bnx2x_fw_stats_data, pf);
-
-	cur_query_entry = &bp->fw_stats_req->query[BNX2X_PF_QUERY_IDX];
-
-	cur_query_entry->kind = STATS_TYPE_PF;
-	/* For PF query index is a DONT CARE */
-	cur_query_entry->index = BP_PORT(bp);
-	cur_query_entry->funcID = cpu_to_le16(BP_FUNC(bp));
-	cur_query_entry->address.hi = cpu_to_le32(U64_HI(cur_data_offset));
-	cur_query_entry->address.lo = cpu_to_le32(U64_LO(cur_data_offset));
-
-	/**** Clients' queries ****/
-	cur_data_offset = bp->fw_stats_data_mapping +
-		offsetof(struct bnx2x_fw_stats_data, queue_stats);
-
-	for_each_eth_queue(bp, i) {
-		cur_query_entry =
-			&bp->fw_stats_req->
-					query[BNX2X_FIRST_QUEUE_QUERY_IDX + i];
-
-		cur_query_entry->kind = STATS_TYPE_QUEUE;
-		cur_query_entry->index = bnx2x_stats_id(&bp->fp[i]);
-		cur_query_entry->funcID = cpu_to_le16(BP_FUNC(bp));
-		cur_query_entry->address.hi =
-			cpu_to_le32(U64_HI(cur_data_offset));
-		cur_query_entry->address.lo =
-			cpu_to_le32(U64_LO(cur_data_offset));
-
-		cur_data_offset += sizeof(struct per_queue_stats);
-	}
-}
-
-void bnx2x_stats_init(struct bnx2x *bp)
-{
-	int /*abs*/port = BP_PORT(bp);
-	int mb_idx = BP_FW_MB_IDX(bp);
-	int i;
-
-	bp->stats_pending = 0;
-	bp->executer_idx = 0;
-	bp->stats_counter = 0;
-
-	/* port and func stats for management */
-	if (!BP_NOMCP(bp)) {
-		bp->port.port_stx = SHMEM_RD(bp, port_mb[port].port_stx);
-		bp->func_stx = SHMEM_RD(bp, func_mb[mb_idx].fw_mb_param);
-
-	} else {
-		bp->port.port_stx = 0;
-		bp->func_stx = 0;
-	}
-	DP(BNX2X_MSG_STATS, "port_stx 0x%x  func_stx 0x%x\n",
-	   bp->port.port_stx, bp->func_stx);
-
-	port = BP_PORT(bp);
-	/* port stats */
-	memset(&(bp->port.old_nig_stats), 0, sizeof(struct nig_stats));
-	bp->port.old_nig_stats.brb_discard =
-			REG_RD(bp, NIG_REG_STAT0_BRB_DISCARD + port*0x38);
-	bp->port.old_nig_stats.brb_truncate =
-			REG_RD(bp, NIG_REG_STAT0_BRB_TRUNCATE + port*0x38);
-	if (!CHIP_IS_E3(bp)) {
-		REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT0 + port*0x50,
-			    &(bp->port.old_nig_stats.egress_mac_pkt0_lo), 2);
-		REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT1 + port*0x50,
-			    &(bp->port.old_nig_stats.egress_mac_pkt1_lo), 2);
-	}
-
-	/* function stats */
-	for_each_queue(bp, i) {
-		struct bnx2x_fastpath *fp = &bp->fp[i];
-
-		memset(&fp->old_tclient, 0, sizeof(fp->old_tclient));
-		memset(&fp->old_uclient, 0, sizeof(fp->old_uclient));
-		memset(&fp->old_xclient, 0, sizeof(fp->old_xclient));
-		memset(&fp->eth_q_stats, 0, sizeof(fp->eth_q_stats));
-	}
-
-	/* Prepare statistics ramrod data */
-	bnx2x_prep_fw_stats_req(bp);
-
-	memset(&bp->dev->stats, 0, sizeof(bp->dev->stats));
-	memset(&bp->eth_stats, 0, sizeof(bp->eth_stats));
-
-	bp->stats_state = STATS_STATE_DISABLED;
-
-	if (bp->port.pmf) {
-		if (bp->port.port_stx)
-			bnx2x_port_stats_base_init(bp);
-
-		if (bp->func_stx)
-			bnx2x_func_stats_base_init(bp);
-
-	} else if (bp->func_stx)
-		bnx2x_func_stats_base_update(bp);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_stats.h linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_stats.h
--- linux-libre-3.1-gnu/drivers/net/bnx2x/bnx2x_stats.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/bnx2x_stats.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,381 +0,0 @@
-/* bnx2x_stats.h: Broadcom Everest network driver.
- *
- * Copyright (c) 2007-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
- * the Free Software Foundation.
- *
- * Maintained by: Eilon Greenstein <eilong@broadcom.com>
- * Written by: Eliezer Tamir
- * Based on code from Michael Chan's bnx2 driver
- * UDP CSUM errata workaround by Arik Gendelman
- * Slowpath and fastpath rework by Vladislav Zolotarov
- * Statistics and Link management by Yitchak Gertner
- *
- */
-#ifndef BNX2X_STATS_H
-#define BNX2X_STATS_H
-
-#include <linux/types.h>
-
-struct nig_stats {
-	u32 brb_discard;
-	u32 brb_packet;
-	u32 brb_truncate;
-	u32 flow_ctrl_discard;
-	u32 flow_ctrl_octets;
-	u32 flow_ctrl_packet;
-	u32 mng_discard;
-	u32 mng_octet_inp;
-	u32 mng_octet_out;
-	u32 mng_packet_inp;
-	u32 mng_packet_out;
-	u32 pbf_octets;
-	u32 pbf_packet;
-	u32 safc_inp;
-	u32 egress_mac_pkt0_lo;
-	u32 egress_mac_pkt0_hi;
-	u32 egress_mac_pkt1_lo;
-	u32 egress_mac_pkt1_hi;
-};
-
-
-enum bnx2x_stats_event {
-	STATS_EVENT_PMF = 0,
-	STATS_EVENT_LINK_UP,
-	STATS_EVENT_UPDATE,
-	STATS_EVENT_STOP,
-	STATS_EVENT_MAX
-};
-
-enum bnx2x_stats_state {
-	STATS_STATE_DISABLED = 0,
-	STATS_STATE_ENABLED,
-	STATS_STATE_MAX
-};
-
-struct bnx2x_eth_stats {
-	u32 total_bytes_received_hi;
-	u32 total_bytes_received_lo;
-	u32 total_bytes_transmitted_hi;
-	u32 total_bytes_transmitted_lo;
-	u32 total_unicast_packets_received_hi;
-	u32 total_unicast_packets_received_lo;
-	u32 total_multicast_packets_received_hi;
-	u32 total_multicast_packets_received_lo;
-	u32 total_broadcast_packets_received_hi;
-	u32 total_broadcast_packets_received_lo;
-	u32 total_unicast_packets_transmitted_hi;
-	u32 total_unicast_packets_transmitted_lo;
-	u32 total_multicast_packets_transmitted_hi;
-	u32 total_multicast_packets_transmitted_lo;
-	u32 total_broadcast_packets_transmitted_hi;
-	u32 total_broadcast_packets_transmitted_lo;
-	u32 valid_bytes_received_hi;
-	u32 valid_bytes_received_lo;
-
-	u32 error_bytes_received_hi;
-	u32 error_bytes_received_lo;
-	u32 etherstatsoverrsizepkts_hi;
-	u32 etherstatsoverrsizepkts_lo;
-	u32 no_buff_discard_hi;
-	u32 no_buff_discard_lo;
-
-	u32 rx_stat_ifhcinbadoctets_hi;
-	u32 rx_stat_ifhcinbadoctets_lo;
-	u32 tx_stat_ifhcoutbadoctets_hi;
-	u32 tx_stat_ifhcoutbadoctets_lo;
-	u32 rx_stat_dot3statsfcserrors_hi;
-	u32 rx_stat_dot3statsfcserrors_lo;
-	u32 rx_stat_dot3statsalignmenterrors_hi;
-	u32 rx_stat_dot3statsalignmenterrors_lo;
-	u32 rx_stat_dot3statscarriersenseerrors_hi;
-	u32 rx_stat_dot3statscarriersenseerrors_lo;
-	u32 rx_stat_falsecarriererrors_hi;
-	u32 rx_stat_falsecarriererrors_lo;
-	u32 rx_stat_etherstatsundersizepkts_hi;
-	u32 rx_stat_etherstatsundersizepkts_lo;
-	u32 rx_stat_dot3statsframestoolong_hi;
-	u32 rx_stat_dot3statsframestoolong_lo;
-	u32 rx_stat_etherstatsfragments_hi;
-	u32 rx_stat_etherstatsfragments_lo;
-	u32 rx_stat_etherstatsjabbers_hi;
-	u32 rx_stat_etherstatsjabbers_lo;
-	u32 rx_stat_maccontrolframesreceived_hi;
-	u32 rx_stat_maccontrolframesreceived_lo;
-	u32 rx_stat_bmac_xpf_hi;
-	u32 rx_stat_bmac_xpf_lo;
-	u32 rx_stat_bmac_xcf_hi;
-	u32 rx_stat_bmac_xcf_lo;
-	u32 rx_stat_xoffstateentered_hi;
-	u32 rx_stat_xoffstateentered_lo;
-	u32 rx_stat_xonpauseframesreceived_hi;
-	u32 rx_stat_xonpauseframesreceived_lo;
-	u32 rx_stat_xoffpauseframesreceived_hi;
-	u32 rx_stat_xoffpauseframesreceived_lo;
-	u32 tx_stat_outxonsent_hi;
-	u32 tx_stat_outxonsent_lo;
-	u32 tx_stat_outxoffsent_hi;
-	u32 tx_stat_outxoffsent_lo;
-	u32 tx_stat_flowcontroldone_hi;
-	u32 tx_stat_flowcontroldone_lo;
-	u32 tx_stat_etherstatscollisions_hi;
-	u32 tx_stat_etherstatscollisions_lo;
-	u32 tx_stat_dot3statssinglecollisionframes_hi;
-	u32 tx_stat_dot3statssinglecollisionframes_lo;
-	u32 tx_stat_dot3statsmultiplecollisionframes_hi;
-	u32 tx_stat_dot3statsmultiplecollisionframes_lo;
-	u32 tx_stat_dot3statsdeferredtransmissions_hi;
-	u32 tx_stat_dot3statsdeferredtransmissions_lo;
-	u32 tx_stat_dot3statsexcessivecollisions_hi;
-	u32 tx_stat_dot3statsexcessivecollisions_lo;
-	u32 tx_stat_dot3statslatecollisions_hi;
-	u32 tx_stat_dot3statslatecollisions_lo;
-	u32 tx_stat_etherstatspkts64octets_hi;
-	u32 tx_stat_etherstatspkts64octets_lo;
-	u32 tx_stat_etherstatspkts65octetsto127octets_hi;
-	u32 tx_stat_etherstatspkts65octetsto127octets_lo;
-	u32 tx_stat_etherstatspkts128octetsto255octets_hi;
-	u32 tx_stat_etherstatspkts128octetsto255octets_lo;
-	u32 tx_stat_etherstatspkts256octetsto511octets_hi;
-	u32 tx_stat_etherstatspkts256octetsto511octets_lo;
-	u32 tx_stat_etherstatspkts512octetsto1023octets_hi;
-	u32 tx_stat_etherstatspkts512octetsto1023octets_lo;
-	u32 tx_stat_etherstatspkts1024octetsto1522octets_hi;
-	u32 tx_stat_etherstatspkts1024octetsto1522octets_lo;
-	u32 tx_stat_etherstatspktsover1522octets_hi;
-	u32 tx_stat_etherstatspktsover1522octets_lo;
-	u32 tx_stat_bmac_2047_hi;
-	u32 tx_stat_bmac_2047_lo;
-	u32 tx_stat_bmac_4095_hi;
-	u32 tx_stat_bmac_4095_lo;
-	u32 tx_stat_bmac_9216_hi;
-	u32 tx_stat_bmac_9216_lo;
-	u32 tx_stat_bmac_16383_hi;
-	u32 tx_stat_bmac_16383_lo;
-	u32 tx_stat_dot3statsinternalmactransmiterrors_hi;
-	u32 tx_stat_dot3statsinternalmactransmiterrors_lo;
-	u32 tx_stat_bmac_ufl_hi;
-	u32 tx_stat_bmac_ufl_lo;
-
-	u32 pause_frames_received_hi;
-	u32 pause_frames_received_lo;
-	u32 pause_frames_sent_hi;
-	u32 pause_frames_sent_lo;
-
-	u32 etherstatspkts1024octetsto1522octets_hi;
-	u32 etherstatspkts1024octetsto1522octets_lo;
-	u32 etherstatspktsover1522octets_hi;
-	u32 etherstatspktsover1522octets_lo;
-
-	u32 brb_drop_hi;
-	u32 brb_drop_lo;
-	u32 brb_truncate_hi;
-	u32 brb_truncate_lo;
-
-	u32 mac_filter_discard;
-	u32 mf_tag_discard;
-	u32 brb_truncate_discard;
-	u32 mac_discard;
-
-	u32 driver_xoff;
-	u32 rx_err_discard_pkt;
-	u32 rx_skb_alloc_failed;
-	u32 hw_csum_err;
-
-	u32 nig_timer_max;
-
-	/* TPA */
-	u32 total_tpa_aggregations_hi;
-	u32 total_tpa_aggregations_lo;
-	u32 total_tpa_aggregated_frames_hi;
-	u32 total_tpa_aggregated_frames_lo;
-	u32 total_tpa_bytes_hi;
-	u32 total_tpa_bytes_lo;
-};
-
-
-struct bnx2x_eth_q_stats {
-	u32 total_unicast_bytes_received_hi;
-	u32 total_unicast_bytes_received_lo;
-	u32 total_broadcast_bytes_received_hi;
-	u32 total_broadcast_bytes_received_lo;
-	u32 total_multicast_bytes_received_hi;
-	u32 total_multicast_bytes_received_lo;
-	u32 total_bytes_received_hi;
-	u32 total_bytes_received_lo;
-	u32 total_unicast_bytes_transmitted_hi;
-	u32 total_unicast_bytes_transmitted_lo;
-	u32 total_broadcast_bytes_transmitted_hi;
-	u32 total_broadcast_bytes_transmitted_lo;
-	u32 total_multicast_bytes_transmitted_hi;
-	u32 total_multicast_bytes_transmitted_lo;
-	u32 total_bytes_transmitted_hi;
-	u32 total_bytes_transmitted_lo;
-	u32 total_unicast_packets_received_hi;
-	u32 total_unicast_packets_received_lo;
-	u32 total_multicast_packets_received_hi;
-	u32 total_multicast_packets_received_lo;
-	u32 total_broadcast_packets_received_hi;
-	u32 total_broadcast_packets_received_lo;
-	u32 total_unicast_packets_transmitted_hi;
-	u32 total_unicast_packets_transmitted_lo;
-	u32 total_multicast_packets_transmitted_hi;
-	u32 total_multicast_packets_transmitted_lo;
-	u32 total_broadcast_packets_transmitted_hi;
-	u32 total_broadcast_packets_transmitted_lo;
-	u32 valid_bytes_received_hi;
-	u32 valid_bytes_received_lo;
-
-	u32 etherstatsoverrsizepkts_hi;
-	u32 etherstatsoverrsizepkts_lo;
-	u32 no_buff_discard_hi;
-	u32 no_buff_discard_lo;
-
-	u32 driver_xoff;
-	u32 rx_err_discard_pkt;
-	u32 rx_skb_alloc_failed;
-	u32 hw_csum_err;
-
-	u32 total_packets_received_checksum_discarded_hi;
-	u32 total_packets_received_checksum_discarded_lo;
-	u32 total_packets_received_ttl0_discarded_hi;
-	u32 total_packets_received_ttl0_discarded_lo;
-	u32 total_transmitted_dropped_packets_error_hi;
-	u32 total_transmitted_dropped_packets_error_lo;
-
-	/* TPA */
-	u32 total_tpa_aggregations_hi;
-	u32 total_tpa_aggregations_lo;
-	u32 total_tpa_aggregated_frames_hi;
-	u32 total_tpa_aggregated_frames_lo;
-	u32 total_tpa_bytes_hi;
-	u32 total_tpa_bytes_lo;
-};
-
-/****************************************************************************
-* Macros
-****************************************************************************/
-
-/* sum[hi:lo] += add[hi:lo] */
-#define ADD_64(s_hi, a_hi, s_lo, a_lo) \
-	do { \
-		s_lo += a_lo; \
-		s_hi += a_hi + ((s_lo < a_lo) ? 1 : 0); \
-	} while (0)
-
-/* difference = minuend - subtrahend */
-#define DIFF_64(d_hi, m_hi, s_hi, d_lo, m_lo, s_lo) \
-	do { \
-		if (m_lo < s_lo) { \
-			/* underflow */ \
-			d_hi = m_hi - s_hi; \
-			if (d_hi > 0) { \
-				/* we can 'loan' 1 */ \
-				d_hi--; \
-				d_lo = m_lo + (UINT_MAX - s_lo) + 1; \
-			} else { \
-				/* m_hi <= s_hi */ \
-				d_hi = 0; \
-				d_lo = 0; \
-			} \
-		} else { \
-			/* m_lo >= s_lo */ \
-			if (m_hi < s_hi) { \
-				d_hi = 0; \
-				d_lo = 0; \
-			} else { \
-				/* m_hi >= s_hi */ \
-				d_hi = m_hi - s_hi; \
-				d_lo = m_lo - s_lo; \
-			} \
-		} \
-	} while (0)
-
-#define UPDATE_STAT64(s, t) \
-	do { \
-		DIFF_64(diff.hi, new->s##_hi, pstats->mac_stx[0].t##_hi, \
-			diff.lo, new->s##_lo, pstats->mac_stx[0].t##_lo); \
-		pstats->mac_stx[0].t##_hi = new->s##_hi; \
-		pstats->mac_stx[0].t##_lo = new->s##_lo; \
-		ADD_64(pstats->mac_stx[1].t##_hi, diff.hi, \
-		       pstats->mac_stx[1].t##_lo, diff.lo); \
-	} while (0)
-
-#define UPDATE_STAT64_NIG(s, t) \
-	do { \
-		DIFF_64(diff.hi, new->s##_hi, old->s##_hi, \
-			diff.lo, new->s##_lo, old->s##_lo); \
-		ADD_64(estats->t##_hi, diff.hi, \
-		       estats->t##_lo, diff.lo); \
-	} while (0)
-
-/* sum[hi:lo] += add */
-#define ADD_EXTEND_64(s_hi, s_lo, a) \
-	do { \
-		s_lo += a; \
-		s_hi += (s_lo < a) ? 1 : 0; \
-	} while (0)
-
-#define ADD_STAT64(diff, t) \
-	do { \
-		ADD_64(pstats->mac_stx[1].t##_hi, new->diff##_hi, \
-		       pstats->mac_stx[1].t##_lo, new->diff##_lo); \
-	} while (0)
-
-#define UPDATE_EXTEND_STAT(s) \
-	do { \
-		ADD_EXTEND_64(pstats->mac_stx[1].s##_hi, \
-			      pstats->mac_stx[1].s##_lo, \
-			      new->s); \
-	} while (0)
-
-#define UPDATE_EXTEND_TSTAT(s, t) \
-	do { \
-		diff = le32_to_cpu(tclient->s) - le32_to_cpu(old_tclient->s); \
-		old_tclient->s = tclient->s; \
-		ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
-	} while (0)
-
-#define UPDATE_EXTEND_USTAT(s, t) \
-	do { \
-		diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \
-		old_uclient->s = uclient->s; \
-		ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
-	} while (0)
-
-#define UPDATE_EXTEND_XSTAT(s, t) \
-	do { \
-		diff = le32_to_cpu(xclient->s) - le32_to_cpu(old_xclient->s); \
-		old_xclient->s = xclient->s; \
-		ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
-	} while (0)
-
-/* minuend -= subtrahend */
-#define SUB_64(m_hi, s_hi, m_lo, s_lo) \
-	do { \
-		DIFF_64(m_hi, m_hi, s_hi, m_lo, m_lo, s_lo); \
-	} while (0)
-
-/* minuend[hi:lo] -= subtrahend */
-#define SUB_EXTEND_64(m_hi, m_lo, s) \
-	do { \
-		SUB_64(m_hi, 0, m_lo, s); \
-	} while (0)
-
-#define SUB_EXTEND_USTAT(s, t) \
-	do { \
-		diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \
-		SUB_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
-	} while (0)
-
-
-/* forward */
-struct bnx2x;
-
-void bnx2x_stats_init(struct bnx2x *bp);
-
-void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
-
-#endif /* BNX2X_STATS_H */
diff -druN linux-libre-3.1-gnu/drivers/net/bnx2x/Makefile linux-libre-3.2-gnu/drivers/net/bnx2x/Makefile
--- linux-libre-3.1-gnu/drivers/net/bnx2x/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bnx2x/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#
-# Makefile for Broadcom 10-Gigabit ethernet driver
-#
-
-obj-$(CONFIG_BNX2X) += bnx2x.o
-
-bnx2x-objs := bnx2x_main.o bnx2x_link.o bnx2x_cmn.o bnx2x_ethtool.o bnx2x_stats.o bnx2x_dcb.o bnx2x_sp.o
diff -druN linux-libre-3.1-gnu/drivers/net/bonding/bond_3ad.c linux-libre-3.2-gnu/drivers/net/bonding/bond_3ad.c
--- linux-libre-3.1-gnu/drivers/net/bonding/bond_3ad.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bonding/bond_3ad.c	2012-01-04 18:55:44.000000000 -0500
@@ -1135,13 +1135,6 @@
 			__record_pdu(lacpdu, port);
 			port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT));
 			port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
-			// verify that if the aggregator is enabled, the port is enabled too.
-			//(because if the link goes down for a short time, the 802.3ad will not
-			// catch it, and the port will continue to be disabled)
-			if (port->aggregator
-			    && port->aggregator->is_active
-			    && !__port_is_enabled(port))
-				__enable_port(port);
 			break;
 		default:    //to silence the compiler
 			break;
@@ -2117,9 +2110,6 @@
 
 	read_lock(&bond->lock);
 
-	if (bond->kill_timers)
-		goto out;
-
 	//check if there are any slaves
 	if (bond->slave_cnt == 0)
 		goto re_arm;
@@ -2168,9 +2158,8 @@
 	}
 
 re_arm:
-	if (!bond->kill_timers)
-		queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks);
-out:
+	queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks);
+
 	read_unlock(&bond->lock);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/net/bonding/bond_alb.c linux-libre-3.2-gnu/drivers/net/bonding/bond_alb.c
--- linux-libre-3.1-gnu/drivers/net/bonding/bond_alb.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bonding/bond_alb.c	2012-01-04 18:55:44.000000000 -0500
@@ -1343,10 +1343,6 @@
 
 	read_lock(&bond->lock);
 
-	if (bond->kill_timers) {
-		goto out;
-	}
-
 	if (bond->slave_cnt == 0) {
 		bond_info->tx_rebalance_counter = 0;
 		bond_info->lp_counter = 0;
@@ -1401,10 +1397,13 @@
 
 			/*
 			 * dev_set_promiscuity requires rtnl and
-			 * nothing else.
+			 * nothing else.  Avoid race with bond_close.
 			 */
 			read_unlock(&bond->lock);
-			rtnl_lock();
+			if (!rtnl_trylock()) {
+				read_lock(&bond->lock);
+				goto re_arm;
+			}
 
 			bond_info->rlb_promisc_timeout_counter = 0;
 
@@ -1440,9 +1439,8 @@
 	}
 
 re_arm:
-	if (!bond->kill_timers)
-		queue_delayed_work(bond->wq, &bond->alb_work, alb_delta_in_ticks);
-out:
+	queue_delayed_work(bond->wq, &bond->alb_work, alb_delta_in_ticks);
+
 	read_unlock(&bond->lock);
 }
 
diff -druN linux-libre-3.1-gnu/drivers/net/bonding/bonding.h linux-libre-3.2-gnu/drivers/net/bonding/bonding.h
--- linux-libre-3.1-gnu/drivers/net/bonding/bonding.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bonding/bonding.h	2012-01-04 18:55:44.000000000 -0500
@@ -222,7 +222,6 @@
 			       struct slave *);
 	rwlock_t lock;
 	rwlock_t curr_slave_lock;
-	s8       kill_timers;
 	u8	 send_peer_notif;
 	s8	 setup_by_slave;
 	s8       igmp_retrans;
@@ -234,7 +233,6 @@
 	struct   netdev_hw_addr_list mc_list;
 	int      (*xmit_hash_policy)(struct sk_buff *, int);
 	__be32   master_ip;
-	u16      flags;
 	u16      rr_tx_counter;
 	struct   ad_bond_info ad_info;
 	struct   alb_bond_info alb_info;
@@ -380,11 +378,13 @@
 	return slave->inactive;
 }
 
+struct bond_net;
+
 struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
 int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
 int bond_create(struct net *net, const char *name);
-int bond_create_sysfs(void);
-void bond_destroy_sysfs(void);
+int bond_create_sysfs(struct bond_net *net);
+void bond_destroy_sysfs(struct bond_net *net);
 void bond_prepare_sysfs_group(struct bonding *bond);
 int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave);
 void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
@@ -410,6 +410,7 @@
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *	proc_dir;
 #endif
+	struct class_attribute	class_attr_bonding_masters;
 };
 
 #ifdef CONFIG_PROC_FS
diff -druN linux-libre-3.1-gnu/drivers/net/bonding/bond_main.c linux-libre-3.2-gnu/drivers/net/bonding/bond_main.c
--- linux-libre-3.1-gnu/drivers/net/bonding/bond_main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bonding/bond_main.c	2012-01-04 18:55:44.000000000 -0500
@@ -395,7 +395,6 @@
 			struct net_device *slave_dev)
 {
 	skb->dev = slave_dev;
-	skb->priority = 1;
 
 	skb->queue_mapping = bond_queue_mapping(skb);
 
@@ -551,32 +550,28 @@
 /*
  * Get link speed and duplex from the slave's base driver
  * using ethtool. If for some reason the call fails or the
- * values are invalid, fake speed and duplex to 100/Full
+ * values are invalid, set speed and duplex to -1,
  * and return error.
  */
 static int bond_update_speed_duplex(struct slave *slave)
 {
 	struct net_device *slave_dev = slave->dev;
-	struct ethtool_cmd etool = { .cmd = ETHTOOL_GSET };
+	struct ethtool_cmd ecmd;
 	u32 slave_speed;
 	int res;
 
-	/* Fake speed and duplex */
-	slave->speed = SPEED_100;
-	slave->duplex = DUPLEX_FULL;
-
-	if (!slave_dev->ethtool_ops || !slave_dev->ethtool_ops->get_settings)
-		return -1;
+	slave->speed = SPEED_UNKNOWN;
+	slave->duplex = DUPLEX_UNKNOWN;
 
-	res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool);
+	res = __ethtool_get_settings(slave_dev, &ecmd);
 	if (res < 0)
 		return -1;
 
-	slave_speed = ethtool_cmd_speed(&etool);
+	slave_speed = ethtool_cmd_speed(&ecmd);
 	if (slave_speed == 0 || slave_speed == ((__u32) -1))
 		return -1;
 
-	switch (etool.duplex) {
+	switch (ecmd.duplex) {
 	case DUPLEX_FULL:
 	case DUPLEX_HALF:
 		break;
@@ -585,7 +580,7 @@
 	}
 
 	slave->speed = slave_speed;
-	slave->duplex = etool.duplex;
+	slave->duplex = ecmd.duplex;
 
 	return 0;
 }
@@ -777,9 +772,6 @@
 
 	read_lock(&bond->lock);
 
-	if (bond->kill_timers)
-		goto out;
-
 	/* rejoin all groups on bond device */
 	__bond_resend_igmp_join_requests(bond->dev);
 
@@ -793,9 +785,9 @@
 			__bond_resend_igmp_join_requests(vlan_dev);
 	}
 
-	if ((--bond->igmp_retrans > 0) && !bond->kill_timers)
+	if (--bond->igmp_retrans > 0)
 		queue_delayed_work(bond->wq, &bond->mcast_work, HZ/5);
-out:
+
 	read_unlock(&bond->lock);
 }
 
@@ -1758,16 +1750,7 @@
 		new_slave->link  = BOND_LINK_DOWN;
 	}
 
-	if (bond_update_speed_duplex(new_slave) &&
-	    (new_slave->link != BOND_LINK_DOWN)) {
-		pr_warning("%s: Warning: failed to get speed and duplex from %s, assumed to be 100Mb/sec and Full.\n",
-			   bond_dev->name, new_slave->dev->name);
-
-		if (bond->params.mode == BOND_MODE_8023AD) {
-			pr_warning("%s: Warning: Operation of 802.3ad mode requires ETHTOOL support in base driver for proper aggregator selection.\n",
-				   bond_dev->name);
-		}
-	}
+	bond_update_speed_duplex(new_slave);
 
 	if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
 		/* if there is a primary slave, remember it */
@@ -2521,10 +2504,11 @@
 	struct bonding *bond = container_of(work, struct bonding,
 					    mii_work.work);
 	bool should_notify_peers = false;
+	unsigned long delay;
 
 	read_lock(&bond->lock);
-	if (bond->kill_timers)
-		goto out;
+
+	delay = msecs_to_jiffies(bond->params.miimon);
 
 	if (bond->slave_cnt == 0)
 		goto re_arm;
@@ -2533,7 +2517,15 @@
 
 	if (bond_miimon_inspect(bond)) {
 		read_unlock(&bond->lock);
-		rtnl_lock();
+
+		/* Race avoidance with bond_close cancel of workqueue */
+		if (!rtnl_trylock()) {
+			read_lock(&bond->lock);
+			delay = 1;
+			should_notify_peers = false;
+			goto re_arm;
+		}
+
 		read_lock(&bond->lock);
 
 		bond_miimon_commit(bond);
@@ -2544,43 +2536,23 @@
 	}
 
 re_arm:
-	if (bond->params.miimon && !bond->kill_timers)
-		queue_delayed_work(bond->wq, &bond->mii_work,
-				   msecs_to_jiffies(bond->params.miimon));
-out:
+	if (bond->params.miimon)
+		queue_delayed_work(bond->wq, &bond->mii_work, delay);
+
 	read_unlock(&bond->lock);
 
 	if (should_notify_peers) {
-		rtnl_lock();
+		if (!rtnl_trylock()) {
+			read_lock(&bond->lock);
+			bond->send_peer_notif++;
+			read_unlock(&bond->lock);
+			return;
+		}
 		netdev_bonding_change(bond->dev, NETDEV_NOTIFY_PEERS);
 		rtnl_unlock();
 	}
 }
 
-static __be32 bond_glean_dev_ip(struct net_device *dev)
-{
-	struct in_device *idev;
-	struct in_ifaddr *ifa;
-	__be32 addr = 0;
-
-	if (!dev)
-		return 0;
-
-	rcu_read_lock();
-	idev = __in_dev_get_rcu(dev);
-	if (!idev)
-		goto out;
-
-	ifa = idev->ifa_list;
-	if (!ifa)
-		goto out;
-
-	addr = ifa->ifa_local;
-out:
-	rcu_read_unlock();
-	return addr;
-}
-
 static int bond_has_this_ip(struct bonding *bond, __be32 ip)
 {
 	struct vlan_entry *vlan;
@@ -2793,9 +2765,6 @@
 
 	delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
 
-	if (bond->kill_timers)
-		goto out;
-
 	if (bond->slave_cnt == 0)
 		goto re_arm;
 
@@ -2892,9 +2861,9 @@
 	}
 
 re_arm:
-	if (bond->params.arp_interval && !bond->kill_timers)
+	if (bond->params.arp_interval)
 		queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
-out:
+
 	read_unlock(&bond->lock);
 }
 
@@ -3135,9 +3104,6 @@
 
 	read_lock(&bond->lock);
 
-	if (bond->kill_timers)
-		goto out;
-
 	delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
 
 	if (bond->slave_cnt == 0)
@@ -3147,7 +3113,15 @@
 
 	if (bond_ab_arp_inspect(bond, delta_in_ticks)) {
 		read_unlock(&bond->lock);
-		rtnl_lock();
+
+		/* Race avoidance with bond_close flush of workqueue */
+		if (!rtnl_trylock()) {
+			read_lock(&bond->lock);
+			delta_in_ticks = 1;
+			should_notify_peers = false;
+			goto re_arm;
+		}
+
 		read_lock(&bond->lock);
 
 		bond_ab_arp_commit(bond, delta_in_ticks);
@@ -3160,13 +3134,18 @@
 	bond_ab_arp_probe(bond);
 
 re_arm:
-	if (bond->params.arp_interval && !bond->kill_timers)
+	if (bond->params.arp_interval)
 		queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
-out:
+
 	read_unlock(&bond->lock);
 
 	if (should_notify_peers) {
-		rtnl_lock();
+		if (!rtnl_trylock()) {
+			read_lock(&bond->lock);
+			bond->send_peer_notif++;
+			read_unlock(&bond->lock);
+			return;
+		}
 		netdev_bonding_change(bond->dev, NETDEV_NOTIFY_PEERS);
 		rtnl_unlock();
 	}
@@ -3207,6 +3186,7 @@
 {
 	struct net_device *bond_dev = slave_dev->master;
 	struct bonding *bond = netdev_priv(bond_dev);
+	struct slave *slave = NULL;
 
 	switch (event) {
 	case NETDEV_UNREGISTER:
@@ -3217,20 +3197,16 @@
 				bond_release(bond_dev, slave_dev);
 		}
 		break;
+	case NETDEV_UP:
 	case NETDEV_CHANGE:
-		if (bond->params.mode == BOND_MODE_8023AD || bond_is_lb(bond)) {
-			struct slave *slave;
-
-			slave = bond_get_slave_by_dev(bond, slave_dev);
-			if (slave) {
-				u32 old_speed = slave->speed;
-				u8  old_duplex = slave->duplex;
-
-				bond_update_speed_duplex(slave);
+		slave = bond_get_slave_by_dev(bond, slave_dev);
+		if (slave) {
+			u32 old_speed = slave->speed;
+			u8  old_duplex = slave->duplex;
 
-				if (bond_is_lb(bond))
-					break;
+			bond_update_speed_duplex(slave);
 
+			if (bond->params.mode == BOND_MODE_8023AD) {
 				if (old_speed != slave->speed)
 					bond_3ad_adapter_speed_changed(slave);
 				if (old_duplex != slave->duplex)
@@ -3322,6 +3298,10 @@
 	struct bonding *bond;
 	struct vlan_entry *vlan;
 
+	/* we only care about primary address */
+	if(ifa->ifa_flags & IFA_F_SECONDARY)
+		return NOTIFY_DONE;
+
 	list_for_each_entry(bond, &bn->dev_list, bond_list) {
 		if (bond->dev == event_dev) {
 			switch (event) {
@@ -3329,7 +3309,7 @@
 				bond->master_ip = ifa->ifa_local;
 				return NOTIFY_OK;
 			case NETDEV_DOWN:
-				bond->master_ip = bond_glean_dev_ip(bond->dev);
+				bond->master_ip = 0;
 				return NOTIFY_OK;
 			default:
 				return NOTIFY_DONE;
@@ -3345,8 +3325,7 @@
 					vlan->vlan_ip = ifa->ifa_local;
 					return NOTIFY_OK;
 				case NETDEV_DOWN:
-					vlan->vlan_ip =
-						bond_glean_dev_ip(vlan_dev);
+					vlan->vlan_ip = 0;
 					return NOTIFY_OK;
 				default:
 					return NOTIFY_DONE;
@@ -3428,8 +3407,6 @@
 	struct slave *slave;
 	int i;
 
-	bond->kill_timers = 0;
-
 	/* reset slave->backup and slave->inactive */
 	read_lock(&bond->lock);
 	if (bond->slave_cnt > 0) {
@@ -3498,33 +3475,30 @@
 
 	bond->send_peer_notif = 0;
 
-	/* signal timers not to re-arm */
-	bond->kill_timers = 1;
-
 	write_unlock_bh(&bond->lock);
 
 	if (bond->params.miimon) {  /* link check interval, in milliseconds. */
-		cancel_delayed_work(&bond->mii_work);
+		cancel_delayed_work_sync(&bond->mii_work);
 	}
 
 	if (bond->params.arp_interval) {  /* arp interval, in milliseconds. */
-		cancel_delayed_work(&bond->arp_work);
+		cancel_delayed_work_sync(&bond->arp_work);
 	}
 
 	switch (bond->params.mode) {
 	case BOND_MODE_8023AD:
-		cancel_delayed_work(&bond->ad_work);
+		cancel_delayed_work_sync(&bond->ad_work);
 		break;
 	case BOND_MODE_TLB:
 	case BOND_MODE_ALB:
-		cancel_delayed_work(&bond->alb_work);
+		cancel_delayed_work_sync(&bond->alb_work);
 		break;
 	default:
 		break;
 	}
 
 	if (delayed_work_pending(&bond->mcast_work))
-		cancel_delayed_work(&bond->mcast_work);
+		cancel_delayed_work_sync(&bond->mcast_work);
 
 	if (bond_is_lb(bond)) {
 		/* Must be called only after all
@@ -3710,44 +3684,27 @@
 	return false;
 }
 
-static void bond_set_multicast_list(struct net_device *bond_dev)
+static void bond_change_rx_flags(struct net_device *bond_dev, int change)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
-	struct netdev_hw_addr *ha;
-	bool found;
-
-	/*
-	 * Do promisc before checking multicast_mode
-	 */
-	if ((bond_dev->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC))
-		/*
-		 * FIXME: Need to handle the error when one of the multi-slaves
-		 * encounters error.
-		 */
-		bond_set_promiscuity(bond, 1);
-
-
-	if (!(bond_dev->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC))
-		bond_set_promiscuity(bond, -1);
-
-
-	/* set allmulti flag to slaves */
-	if ((bond_dev->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI))
-		/*
-		 * FIXME: Need to handle the error when one of the multi-slaves
-		 * encounters error.
-		 */
-		bond_set_allmulti(bond, 1);
 
+	if (change & IFF_PROMISC)
+		bond_set_promiscuity(bond,
+				     bond_dev->flags & IFF_PROMISC ? 1 : -1);
 
-	if (!(bond_dev->flags & IFF_ALLMULTI) && (bond->flags & IFF_ALLMULTI))
-		bond_set_allmulti(bond, -1);
+	if (change & IFF_ALLMULTI)
+		bond_set_allmulti(bond,
+				  bond_dev->flags & IFF_ALLMULTI ? 1 : -1);
+}
 
+static void bond_set_multicast_list(struct net_device *bond_dev)
+{
+	struct bonding *bond = netdev_priv(bond_dev);
+	struct netdev_hw_addr *ha;
+	bool found;
 
 	read_lock(&bond->lock);
 
-	bond->flags = bond_dev->flags;
-
 	/* looking for addresses to add to slaves' mc list */
 	netdev_for_each_mc_addr(ha, bond_dev) {
 		found = bond_addr_in_mc_list(ha->addr, &bond->mc_list,
@@ -4306,7 +4263,8 @@
 	.ndo_select_queue	= bond_select_queue,
 	.ndo_get_stats64	= bond_get_stats,
 	.ndo_do_ioctl		= bond_do_ioctl,
-	.ndo_set_multicast_list	= bond_set_multicast_list,
+	.ndo_change_rx_flags	= bond_change_rx_flags,
+	.ndo_set_rx_mode	= bond_set_multicast_list,
 	.ndo_change_mtu		= bond_change_mtu,
 	.ndo_set_mac_address	= bond_set_mac_address,
 	.ndo_neigh_setup	= bond_neigh_setup,
@@ -4387,26 +4345,22 @@
 
 static void bond_work_cancel_all(struct bonding *bond)
 {
-	write_lock_bh(&bond->lock);
-	bond->kill_timers = 1;
-	write_unlock_bh(&bond->lock);
-
 	if (bond->params.miimon && delayed_work_pending(&bond->mii_work))
-		cancel_delayed_work(&bond->mii_work);
+		cancel_delayed_work_sync(&bond->mii_work);
 
 	if (bond->params.arp_interval && delayed_work_pending(&bond->arp_work))
-		cancel_delayed_work(&bond->arp_work);
+		cancel_delayed_work_sync(&bond->arp_work);
 
 	if (bond->params.mode == BOND_MODE_ALB &&
 	    delayed_work_pending(&bond->alb_work))
-		cancel_delayed_work(&bond->alb_work);
+		cancel_delayed_work_sync(&bond->alb_work);
 
 	if (bond->params.mode == BOND_MODE_8023AD &&
 	    delayed_work_pending(&bond->ad_work))
-		cancel_delayed_work(&bond->ad_work);
+		cancel_delayed_work_sync(&bond->ad_work);
 
 	if (delayed_work_pending(&bond->mcast_work))
-		cancel_delayed_work(&bond->mcast_work);
+		cancel_delayed_work_sync(&bond->mcast_work);
 }
 
 /*
@@ -4852,11 +4806,20 @@
 	return 0;
 }
 
+static int bond_get_tx_queues(struct net *net, struct nlattr *tb[],
+			      unsigned int *num_queues,
+			      unsigned int *real_num_queues)
+{
+	*num_queues = tx_queues;
+	return 0;
+}
+
 static struct rtnl_link_ops bond_link_ops __read_mostly = {
 	.kind		= "bond",
 	.priv_size	= sizeof(struct bonding),
 	.setup		= bond_setup,
 	.validate	= bond_validate,
+	.get_tx_queues	= bond_get_tx_queues,
 };
 
 /* Create a new bond based on the specified name and bonding parameters.
@@ -4901,6 +4864,7 @@
 	INIT_LIST_HEAD(&bn->dev_list);
 
 	bond_create_proc_dir(bn);
+	bond_create_sysfs(bn);
 	
 	return 0;
 }
@@ -4909,6 +4873,7 @@
 {
 	struct bond_net *bn = net_generic(net, bond_net_id);
 
+	bond_destroy_sysfs(bn);
 	bond_destroy_proc_dir(bn);
 }
 
@@ -4946,10 +4911,6 @@
 			goto err;
 	}
 
-	res = bond_create_sysfs();
-	if (res)
-		goto err;
-
 	register_netdevice_notifier(&bond_netdev_notifier);
 	register_inetaddr_notifier(&bond_inetaddr_notifier);
 out:
@@ -4967,7 +4928,6 @@
 	unregister_netdevice_notifier(&bond_netdev_notifier);
 	unregister_inetaddr_notifier(&bond_inetaddr_notifier);
 
-	bond_destroy_sysfs();
 	bond_destroy_debugfs();
 
 	rtnl_link_unregister(&bond_link_ops);
diff -druN linux-libre-3.1-gnu/drivers/net/bonding/bond_procfs.c linux-libre-3.2-gnu/drivers/net/bonding/bond_procfs.c
--- linux-libre-3.1-gnu/drivers/net/bonding/bond_procfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bonding/bond_procfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -1,4 +1,5 @@
 #include <linux/proc_fs.h>
+#include <linux/export.h>
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 #include "bonding.h"
@@ -157,8 +158,16 @@
 	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");
+	if (slave->speed == SPEED_UNKNOWN)
+		seq_printf(seq, "Speed: %s\n", "Unknown");
+	else
+		seq_printf(seq, "Speed: %d Mbps\n", slave->speed);
+
+	if (slave->duplex == DUPLEX_UNKNOWN)
+		seq_printf(seq, "Duplex: %s\n", "Unknown");
+	else
+		seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half");
+
 	seq_printf(seq, "Link Failure Count: %u\n",
 		   slave->link_failure_count);
 
diff -druN linux-libre-3.1-gnu/drivers/net/bonding/bond_sysfs.c linux-libre-3.2-gnu/drivers/net/bonding/bond_sysfs.c
--- linux-libre-3.1-gnu/drivers/net/bonding/bond_sysfs.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bonding/bond_sysfs.c	2012-01-04 18:55:44.000000000 -0500
@@ -55,8 +55,8 @@
 				  struct class_attribute *attr,
 				  char *buf)
 {
-	struct net *net = current->nsproxy->net_ns;
-	struct bond_net *bn = net_generic(net, bond_net_id);
+	struct bond_net *bn =
+		container_of(attr, struct bond_net, class_attr_bonding_masters);
 	int res = 0;
 	struct bonding *bond;
 
@@ -79,9 +79,8 @@
 	return res;
 }
 
-static struct net_device *bond_get_by_name(struct net *net, const char *ifname)
+static struct net_device *bond_get_by_name(struct bond_net *bn, const char *ifname)
 {
-	struct bond_net *bn = net_generic(net, bond_net_id);
 	struct bonding *bond;
 
 	list_for_each_entry(bond, &bn->dev_list, bond_list) {
@@ -103,7 +102,8 @@
 				   struct class_attribute *attr,
 				   const char *buffer, size_t count)
 {
-	struct net *net = current->nsproxy->net_ns;
+	struct bond_net *bn =
+		container_of(attr, struct bond_net, class_attr_bonding_masters);
 	char command[IFNAMSIZ + 1] = {0, };
 	char *ifname;
 	int rv, res = count;
@@ -116,7 +116,7 @@
 
 	if (command[0] == '+') {
 		pr_info("%s is being created...\n", ifname);
-		rv = bond_create(net, ifname);
+		rv = bond_create(bn->net, ifname);
 		if (rv) {
 			if (rv == -EEXIST)
 				pr_info("%s already exists.\n", ifname);
@@ -128,7 +128,7 @@
 		struct net_device *bond_dev;
 
 		rtnl_lock();
-		bond_dev = bond_get_by_name(net, ifname);
+		bond_dev = bond_get_by_name(bn, ifname);
 		if (bond_dev) {
 			pr_info("%s is being deleted...\n", ifname);
 			unregister_netdevice(bond_dev);
@@ -150,9 +150,24 @@
 	return -EPERM;
 }
 
+static const void *bonding_namespace(struct class *cls,
+				     const struct class_attribute *attr)
+{
+	const struct bond_net *bn =
+		container_of(attr, struct bond_net, class_attr_bonding_masters);
+	return bn->net;
+}
+
 /* class attribute for bond_masters file.  This ends up in /sys/class/net */
-static CLASS_ATTR(bonding_masters,  S_IWUSR | S_IRUGO,
-		  bonding_show_bonds, bonding_store_bonds);
+static const struct class_attribute class_attr_bonding_masters = {
+	.attr = {
+		.name = "bonding_masters",
+		.mode = S_IWUSR | S_IRUGO,
+	},
+	.show = bonding_show_bonds,
+	.store = bonding_store_bonds,
+	.namespace = bonding_namespace,
+};
 
 int bond_create_slave_symlinks(struct net_device *master,
 			       struct net_device *slave)
@@ -304,6 +319,13 @@
 		goto out;
 	}
 
+	if (bond->slave_cnt > 0) {
+		pr_err("unable to update mode of %s because it has slaves.\n",
+			bond->dev->name);
+		ret = -EPERM;
+		goto out;
+	}
+
 	new_value = bond_parse_parm(buf, bond_mode_tbl);
 	if (new_value < 0)  {
 		pr_err("%s: Ignoring invalid mode value %.*s.\n",
@@ -1655,11 +1677,14 @@
  * Initialize sysfs.  This sets up the bonding_masters file in
  * /sys/class/net.
  */
-int bond_create_sysfs(void)
+int bond_create_sysfs(struct bond_net *bn)
 {
 	int ret;
 
-	ret = netdev_class_create_file(&class_attr_bonding_masters);
+	bn->class_attr_bonding_masters = class_attr_bonding_masters;
+	sysfs_attr_init(&bn->class_attr_bonding_masters.attr);
+
+	ret = netdev_class_create_file(&bn->class_attr_bonding_masters);
 	/*
 	 * Permit multiple loads of the module by ignoring failures to
 	 * create the bonding_masters sysfs file.  Bonding devices
@@ -1673,7 +1698,7 @@
 	 */
 	if (ret == -EEXIST) {
 		/* Is someone being kinky and naming a device bonding_master? */
-		if (__dev_get_by_name(&init_net,
+		if (__dev_get_by_name(bn->net,
 				      class_attr_bonding_masters.attr.name))
 			pr_err("network device named %s already exists in sysfs",
 			       class_attr_bonding_masters.attr.name);
@@ -1687,9 +1712,9 @@
 /*
  * Remove /sys/class/net/bonding_masters.
  */
-void bond_destroy_sysfs(void)
+void bond_destroy_sysfs(struct bond_net *bn)
 {
-	netdev_class_remove_file(&class_attr_bonding_masters);
+	netdev_class_remove_file(&bn->class_attr_bonding_masters);
 }
 
 /*
diff -druN linux-libre-3.1-gnu/drivers/net/bsd_comp.c linux-libre-3.2-gnu/drivers/net/bsd_comp.c
--- linux-libre-3.1-gnu/drivers/net/bsd_comp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/bsd_comp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1170 +0,0 @@
-/*
- * Update: The Berkeley copyright was changed, and the change
- * is retroactive to all "true" BSD software (ie everything
- * from UCB as opposed to other peoples code that just carried
- * the same license). The new copyright doesn't clash with the
- * GPL, so the module-only restriction has been removed..
- */
-
-/* Because this code is derived from the 4.3BSD compress source:
- *
- * Copyright (c) 1985, 1986 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * James A. Woods, derived from original work by Spencer Thomas
- * and Joseph Orost.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 version is for use with contiguous buffers on Linux-derived systems.
- *
- *  ==FILEVERSION 20000226==
- *
- *  NOTE TO MAINTAINERS:
- *     If you modify this file at all, please set the number above to the
- *     date of the modification as YYMMDD (year month day).
- *     bsd_comp.c is shipped with a PPP distribution as well as with
- *     the kernel; if everyone increases the FILEVERSION number above,
- *     then scripts can do the right thing when deciding whether to
- *     install a new bsd_comp.c file. Don't change the format of that
- *     line otherwise, so the installation script can recognize it.
- *
- * From: bsd_comp.c,v 1.3 1994/12/08 01:59:58 paulus Exp
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/string.h>
-
-#include <linux/ppp_defs.h>
-
-#undef   PACKETPTR
-#define  PACKETPTR 1
-#include <linux/ppp-comp.h>
-#undef   PACKETPTR
-
-#include <asm/byteorder.h>
-
-/*
- * PPP "BSD compress" compression
- *  The differences between this compression and the classic BSD LZW
- *  source are obvious from the requirement that the classic code worked
- *  with files while this handles arbitrarily long streams that
- *  are broken into packets.  They are:
- *
- *	When the code size expands, a block of junk is not emitted by
- *	    the compressor and not expected by the decompressor.
- *
- *	New codes are not necessarily assigned every time an old
- *	    code is output by the compressor.  This is because a packet
- *	    end forces a code to be emitted, but does not imply that a
- *	    new sequence has been seen.
- *
- *	The compression ratio is checked at the first end of a packet
- *	    after the appropriate gap.	Besides simplifying and speeding
- *	    things up, this makes it more likely that the transmitter
- *	    and receiver will agree when the dictionary is cleared when
- *	    compression is not going well.
- */
-
-/*
- * Macros to extract protocol version and number of bits
- * from the third byte of the BSD Compress CCP configuration option.
- */
-
-#define BSD_VERSION(x)	((x) >> 5)
-#define BSD_NBITS(x)	((x) & 0x1F)
-
-#define BSD_CURRENT_VERSION	1
-
-/*
- * A dictionary for doing BSD compress.
- */
-
-struct bsd_dict {
-    union {				/* hash value */
-	unsigned long	fcode;
-	struct {
-#if defined(__LITTLE_ENDIAN)		/* Little endian order */
-	    unsigned short	prefix;	/* preceding code */
-	    unsigned char	suffix; /* last character of new code */
-	    unsigned char	pad;
-#elif defined(__BIG_ENDIAN)		/* Big endian order */
-	    unsigned char	pad;
-	    unsigned char	suffix; /* last character of new code */
-	    unsigned short	prefix; /* preceding code */
-#else
-#error Endianness not defined...
-#endif
-	} hs;
-    } f;
-    unsigned short codem1;		/* output of hash table -1 */
-    unsigned short cptr;		/* map code to hash table entry */
-};
-
-struct bsd_db {
-    int	    totlen;			/* length of this structure */
-    unsigned int   hsize;		/* size of the hash table */
-    unsigned char  hshift;		/* used in hash function */
-    unsigned char  n_bits;		/* current bits/code */
-    unsigned char  maxbits;		/* maximum bits/code */
-    unsigned char  debug;		/* non-zero if debug desired */
-    unsigned char  unit;		/* ppp unit number */
-    unsigned short seqno;		/* sequence # of next packet */
-    unsigned int   mru;			/* size of receive (decompress) bufr */
-    unsigned int   maxmaxcode;		/* largest valid code */
-    unsigned int   max_ent;		/* largest code in use */
-    unsigned int   in_count;		/* uncompressed bytes, aged */
-    unsigned int   bytes_out;		/* compressed bytes, aged */
-    unsigned int   ratio;		/* recent compression ratio */
-    unsigned int   checkpoint;		/* when to next check the ratio */
-    unsigned int   clear_count;		/* times dictionary cleared */
-    unsigned int   incomp_count;	/* incompressible packets */
-    unsigned int   incomp_bytes;	/* incompressible bytes */
-    unsigned int   uncomp_count;	/* uncompressed packets */
-    unsigned int   uncomp_bytes;	/* uncompressed bytes */
-    unsigned int   comp_count;		/* compressed packets */
-    unsigned int   comp_bytes;		/* compressed bytes */
-    unsigned short  *lens;		/* array of lengths of codes */
-    struct bsd_dict *dict;		/* dictionary */
-};
-
-#define BSD_OVHD	2		/* BSD compress overhead/packet */
-#define MIN_BSD_BITS	9
-#define BSD_INIT_BITS	MIN_BSD_BITS
-#define MAX_BSD_BITS	15
-
-static void	bsd_free (void *state);
-static void	*bsd_alloc(unsigned char *options, int opt_len, int decomp);
-static void	*bsd_comp_alloc (unsigned char *options, int opt_len);
-static void	*bsd_decomp_alloc (unsigned char *options, int opt_len);
-
-static int	bsd_init        (void *db, unsigned char *options,
-			         int opt_len, int unit, int debug, int decomp);
-static int	bsd_comp_init   (void *state, unsigned char *options,
-			         int opt_len, int unit, int opthdr, int debug);
-static int	bsd_decomp_init (void *state, unsigned char *options,
-				 int opt_len, int unit, int opthdr, int mru,
-				 int debug);
-
-static void	bsd_reset (void *state);
-static void	bsd_comp_stats (void *state, struct compstat *stats);
-
-static int	bsd_compress (void *state, unsigned char *rptr,
-			      unsigned char *obuf, int isize, int osize);
-static void	bsd_incomp (void *state, unsigned char *ibuf, int icnt);
-
-static int	bsd_decompress (void *state, unsigned char *ibuf, int isize,
-				unsigned char *obuf, int osize);
-
-/* These are in ppp_generic.c */
-extern int  ppp_register_compressor   (struct compressor *cp);
-extern void ppp_unregister_compressor (struct compressor *cp);
-
-/*
- * the next two codes should not be changed lightly, as they must not
- * lie within the contiguous general code space.
- */
-#define CLEAR	256			/* table clear output code */
-#define FIRST	257			/* first free entry */
-#define LAST	255
-
-#define MAXCODE(b)	((1 << (b)) - 1)
-#define BADCODEM1	MAXCODE(MAX_BSD_BITS)
-
-#define BSD_HASH(prefix,suffix,hshift) ((((unsigned long)(suffix))<<(hshift)) \
-					 ^ (unsigned long)(prefix))
-#define BSD_KEY(prefix,suffix)		((((unsigned long)(suffix)) << 16) \
-					 + (unsigned long)(prefix))
-
-#define CHECK_GAP	10000		/* Ratio check interval */
-
-#define RATIO_SCALE_LOG	8
-#define RATIO_SCALE	(1<<RATIO_SCALE_LOG)
-#define RATIO_MAX	(0x7fffffff>>RATIO_SCALE_LOG)
-
-/*
- * clear the dictionary
- */
-
-static void
-bsd_clear(struct bsd_db *db)
-{
-    db->clear_count++;
-    db->max_ent      = FIRST-1;
-    db->n_bits       = BSD_INIT_BITS;
-    db->bytes_out    = 0;
-    db->in_count     = 0;
-    db->ratio	     = 0;
-    db->checkpoint   = CHECK_GAP;
-}
-
-/*
- * If the dictionary is full, then see if it is time to reset it.
- *
- * Compute the compression ratio using fixed-point arithmetic
- * with 8 fractional bits.
- *
- * Since we have an infinite stream instead of a single file,
- * watch only the local compression ratio.
- *
- * Since both peers must reset the dictionary at the same time even in
- * the absence of CLEAR codes (while packets are incompressible), they
- * must compute the same ratio.
- */
-
-static int bsd_check (struct bsd_db *db)	/* 1=output CLEAR */
-  {
-    unsigned int new_ratio;
-
-    if (db->in_count >= db->checkpoint)
-      {
-	/* age the ratio by limiting the size of the counts */
-	if (db->in_count >= RATIO_MAX || db->bytes_out >= RATIO_MAX)
-	  {
-	    db->in_count  -= (db->in_count  >> 2);
-	    db->bytes_out -= (db->bytes_out >> 2);
-	  }
-
-	db->checkpoint = db->in_count + CHECK_GAP;
-
-	if (db->max_ent >= db->maxmaxcode)
-	  {
-	    /* Reset the dictionary only if the ratio is worse,
-	     * or if it looks as if it has been poisoned
-	     * by incompressible data.
-	     *
-	     * This does not overflow, because
-	     *	db->in_count <= RATIO_MAX.
-	     */
-
-	    new_ratio = db->in_count << RATIO_SCALE_LOG;
-	    if (db->bytes_out != 0)
-	      {
-		new_ratio /= db->bytes_out;
-	      }
-
-	    if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE)
-	      {
-		bsd_clear (db);
-		return 1;
-	      }
-	    db->ratio = new_ratio;
-	  }
-      }
-    return 0;
-  }
-
-/*
- * Return statistics.
- */
-
-static void bsd_comp_stats (void *state, struct compstat *stats)
-  {
-    struct bsd_db *db = (struct bsd_db *) state;
-
-    stats->unc_bytes    = db->uncomp_bytes;
-    stats->unc_packets  = db->uncomp_count;
-    stats->comp_bytes   = db->comp_bytes;
-    stats->comp_packets = db->comp_count;
-    stats->inc_bytes    = db->incomp_bytes;
-    stats->inc_packets  = db->incomp_count;
-    stats->in_count     = db->in_count;
-    stats->bytes_out    = db->bytes_out;
-  }
-
-/*
- * Reset state, as on a CCP ResetReq.
- */
-
-static void bsd_reset (void *state)
-  {
-    struct bsd_db *db = (struct bsd_db *) state;
-
-    bsd_clear(db);
-
-    db->seqno       = 0;
-    db->clear_count = 0;
-  }
-
-/*
- * Release the compression structure
- */
-
-static void bsd_free (void *state)
-{
-	struct bsd_db *db = state;
-
-	if (!db)
-		return;
-
-/*
- * Release the dictionary
- */
-	vfree(db->dict);
-	db->dict = NULL;
-/*
- * Release the string buffer
- */
-	vfree(db->lens);
-	db->lens = NULL;
-/*
- * Finally release the structure itself.
- */
-	kfree(db);
-}
-
-/*
- * Allocate space for a (de) compressor.
- */
-
-static void *bsd_alloc (unsigned char *options, int opt_len, int decomp)
-  {
-    int bits;
-    unsigned int hsize, hshift, maxmaxcode;
-    struct bsd_db *db;
-
-    if (opt_len != 3 || options[0] != CI_BSD_COMPRESS || options[1] != 3
-	|| BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
-      {
-	return NULL;
-      }
-
-    bits = BSD_NBITS(options[2]);
-
-    switch (bits)
-      {
-    case 9:			/* needs 82152 for both directions */
-    case 10:			/* needs 84144 */
-    case 11:			/* needs 88240 */
-    case 12:			/* needs 96432 */
-	hsize = 5003;
-	hshift = 4;
-	break;
-    case 13:			/* needs 176784 */
-	hsize = 9001;
-	hshift = 5;
-	break;
-    case 14:			/* needs 353744 */
-	hsize = 18013;
-	hshift = 6;
-	break;
-    case 15:			/* needs 691440 */
-	hsize = 35023;
-	hshift = 7;
-	break;
-    case 16:			/* needs 1366160--far too much, */
-	/* hsize = 69001; */	/* and 69001 is too big for cptr */
-	/* hshift = 8; */	/* in struct bsd_db */
-	/* break; */
-    default:
-	return NULL;
-      }
-/*
- * Allocate the main control structure for this instance.
- */
-    maxmaxcode = MAXCODE(bits);
-    db         = kzalloc(sizeof (struct bsd_db),
-					    GFP_KERNEL);
-    if (!db)
-      {
-	return NULL;
-      }
-
-/*
- * Allocate space for the dictionary. This may be more than one page in
- * length.
- */
-    db->dict = vmalloc(hsize * sizeof(struct bsd_dict));
-    if (!db->dict)
-      {
-	bsd_free (db);
-	return NULL;
-      }
-
-/*
- * If this is the compression buffer then there is no length data.
- */
-    if (!decomp)
-      {
-	db->lens = NULL;
-      }
-/*
- * For decompression, the length information is needed as well.
- */
-    else
-      {
-        db->lens = vmalloc((maxmaxcode + 1) * sizeof(db->lens[0]));
-	if (!db->lens)
-	  {
-	    bsd_free (db);
-	    return NULL;
-	  }
-      }
-/*
- * Initialize the data information for the compression code
- */
-    db->totlen     = sizeof (struct bsd_db)   +
-      		    (sizeof (struct bsd_dict) * hsize);
-
-    db->hsize      = hsize;
-    db->hshift     = hshift;
-    db->maxmaxcode = maxmaxcode;
-    db->maxbits    = bits;
-
-    return (void *) db;
-  }
-
-static void *bsd_comp_alloc (unsigned char *options, int opt_len)
-  {
-    return bsd_alloc (options, opt_len, 0);
-  }
-
-static void *bsd_decomp_alloc (unsigned char *options, int opt_len)
-  {
-    return bsd_alloc (options, opt_len, 1);
-  }
-
-/*
- * Initialize the database.
- */
-
-static int bsd_init (void *state, unsigned char *options,
-		     int opt_len, int unit, int debug, int decomp)
-  {
-    struct bsd_db *db = state;
-    int indx;
-
-    if ((opt_len != 3) || (options[0] != CI_BSD_COMPRESS) || (options[1] != 3)
-	|| (BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
-	|| (BSD_NBITS(options[2]) != db->maxbits)
-	|| (decomp && db->lens == NULL))
-      {
-	return 0;
-      }
-
-    if (decomp)
-      {
-	indx = LAST;
-	do
-	  {
-	    db->lens[indx] = 1;
-	  }
-	while (indx-- > 0);
-      }
-
-    indx = db->hsize;
-    while (indx-- != 0)
-      {
-	db->dict[indx].codem1 = BADCODEM1;
-	db->dict[indx].cptr   = 0;
-      }
-
-    db->unit = unit;
-    db->mru  = 0;
-#ifndef DEBUG
-    if (debug)
-#endif
-      db->debug = 1;
-
-    bsd_reset(db);
-
-    return 1;
-  }
-
-static int bsd_comp_init (void *state, unsigned char *options,
-			  int opt_len, int unit, int opthdr, int debug)
-  {
-    return bsd_init (state, options, opt_len, unit, debug, 0);
-  }
-
-static int bsd_decomp_init (void *state, unsigned char *options,
-			    int opt_len, int unit, int opthdr, int mru,
-			    int debug)
-  {
-    return bsd_init (state, options, opt_len, unit, debug, 1);
-  }
-
-/*
- * Obtain pointers to the various structures in the compression tables
- */
-
-#define dict_ptrx(p,idx) &(p->dict[idx])
-#define lens_ptrx(p,idx) &(p->lens[idx])
-
-#ifdef DEBUG
-static unsigned short *lens_ptr(struct bsd_db *db, int idx)
-  {
-    if ((unsigned int) idx > (unsigned int) db->maxmaxcode)
-      {
-	printk ("<9>ppp: lens_ptr(%d) > max\n", idx);
-	idx = 0;
-      }
-    return lens_ptrx (db, idx);
-  }
-
-static struct bsd_dict *dict_ptr(struct bsd_db *db, int idx)
-  {
-    if ((unsigned int) idx >= (unsigned int) db->hsize)
-      {
-	printk ("<9>ppp: dict_ptr(%d) > max\n", idx);
-	idx = 0;
-      }
-    return dict_ptrx (db, idx);
-  }
-
-#else
-#define lens_ptr(db,idx) lens_ptrx(db,idx)
-#define dict_ptr(db,idx) dict_ptrx(db,idx)
-#endif
-
-/*
- * compress a packet
- *
- *	The result of this function is the size of the compressed
- *	packet. A zero is returned if the packet was not compressed
- *	for some reason, such as the size being larger than uncompressed.
- *
- *	One change from the BSD compress command is that when the
- *	code size expands, we do not output a bunch of padding.
- */
-
-static int bsd_compress (void *state, unsigned char *rptr, unsigned char *obuf,
-			 int isize, int osize)
-  {
-    struct bsd_db *db;
-    int hshift;
-    unsigned int max_ent;
-    unsigned int n_bits;
-    unsigned int bitno;
-    unsigned long accm;
-    int ent;
-    unsigned long fcode;
-    struct bsd_dict *dictp;
-    unsigned char c;
-    int hval;
-    int disp;
-    int ilen;
-    int mxcode;
-    unsigned char *wptr;
-    int olen;
-
-#define PUTBYTE(v)			\
-  {					\
-    ++olen;				\
-    if (wptr)				\
-      {					\
-	*wptr++ = (unsigned char) (v);	\
-	if (olen >= osize)		\
-	  {				\
-	    wptr = NULL;		\
-	  }				\
-      }					\
-  }
-
-#define OUTPUT(ent)			\
-  {					\
-    bitno -= n_bits;			\
-    accm |= ((ent) << bitno);		\
-    do					\
-      {					\
-	PUTBYTE(accm >> 24);		\
-	accm <<= 8;			\
-	bitno += 8;			\
-      }					\
-    while (bitno <= 24);		\
-  }
-
-  /*
-   * If the protocol is not in the range we're interested in,
-   * just return without compressing the packet.  If it is,
-   * the protocol becomes the first byte to compress.
-   */
-
-    ent = PPP_PROTOCOL(rptr);
-    if (ent < 0x21 || ent > 0xf9)
-      {
-	return 0;
-      }
-
-    db      = (struct bsd_db *) state;
-    hshift  = db->hshift;
-    max_ent = db->max_ent;
-    n_bits  = db->n_bits;
-    bitno   = 32;
-    accm    = 0;
-    mxcode  = MAXCODE (n_bits);
-
-    /* Initialize the output pointers */
-    wptr  = obuf;
-    olen  = PPP_HDRLEN + BSD_OVHD;
-
-    if (osize > isize)
-      {
-	osize = isize;
-      }
-
-    /* This is the PPP header information */
-    if (wptr)
-      {
-	*wptr++ = PPP_ADDRESS(rptr);
-	*wptr++ = PPP_CONTROL(rptr);
-	*wptr++ = 0;
-	*wptr++ = PPP_COMP;
-	*wptr++ = db->seqno >> 8;
-	*wptr++ = db->seqno;
-      }
-
-    /* Skip the input header */
-    rptr  += PPP_HDRLEN;
-    isize -= PPP_HDRLEN;
-    ilen   = ++isize;	/* Low byte of protocol is counted as input */
-
-    while (--ilen > 0)
-      {
-	c     = *rptr++;
-	fcode = BSD_KEY  (ent, c);
-	hval  = BSD_HASH (ent, c, hshift);
-	dictp = dict_ptr (db, hval);
-
-	/* Validate and then check the entry. */
-	if (dictp->codem1 >= max_ent)
-	  {
-	    goto nomatch;
-	  }
-
-	if (dictp->f.fcode == fcode)
-	  {
-	    ent = dictp->codem1 + 1;
-	    continue;	/* found (prefix,suffix) */
-	  }
-
-	/* continue probing until a match or invalid entry */
-	disp = (hval == 0) ? 1 : hval;
-
-	do
-	  {
-	    hval += disp;
-	    if (hval >= db->hsize)
-	      {
-		hval -= db->hsize;
-	      }
-	    dictp = dict_ptr (db, hval);
-	    if (dictp->codem1 >= max_ent)
-	      {
-		goto nomatch;
-	      }
-	  }
-	while (dictp->f.fcode != fcode);
-
-	ent = dictp->codem1 + 1;	/* finally found (prefix,suffix) */
-	continue;
-
-nomatch:
-	OUTPUT(ent);		/* output the prefix */
-
-	/* code -> hashtable */
-	if (max_ent < db->maxmaxcode)
-	  {
-	    struct bsd_dict *dictp2;
-	    struct bsd_dict *dictp3;
-	    int    indx;
-
-	    /* expand code size if needed */
-	    if (max_ent >= mxcode)
-	      {
-		db->n_bits = ++n_bits;
-		mxcode     = MAXCODE (n_bits);
-	      }
-
-	    /* Invalidate old hash table entry using
-	     * this code, and then take it over.
-	     */
-
-	    dictp2 = dict_ptr (db, max_ent + 1);
-	    indx   = dictp2->cptr;
-	    dictp3 = dict_ptr (db, indx);
-
-	    if (dictp3->codem1 == max_ent)
-	      {
-		dictp3->codem1 = BADCODEM1;
-	      }
-
-	    dictp2->cptr   = hval;
-	    dictp->codem1  = max_ent;
-	    dictp->f.fcode = fcode;
-	    db->max_ent    = ++max_ent;
-
-	    if (db->lens)
-	      {
-		unsigned short *len1 = lens_ptr (db, max_ent);
-		unsigned short *len2 = lens_ptr (db, ent);
-		*len1 = *len2 + 1;
-	      }
-	  }
-	ent = c;
-      }
-
-    OUTPUT(ent);		/* output the last code */
-
-    db->bytes_out    += olen - PPP_HDRLEN - BSD_OVHD;
-    db->uncomp_bytes += isize;
-    db->in_count     += isize;
-    ++db->uncomp_count;
-    ++db->seqno;
-
-    if (bitno < 32)
-      {
-	++db->bytes_out; /* must be set before calling bsd_check */
-      }
-
-    /*
-     * Generate the clear command if needed
-     */
-
-    if (bsd_check(db))
-      {
-	OUTPUT (CLEAR);
-      }
-
-    /*
-     * Pad dribble bits of last code with ones.
-     * Do not emit a completely useless byte of ones.
-     */
-
-    if (bitno != 32)
-      {
-	PUTBYTE((accm | (0xff << (bitno-8))) >> 24);
-      }
-
-    /*
-     * Increase code size if we would have without the packet
-     * boundary because the decompressor will do so.
-     */
-
-    if (max_ent >= mxcode && max_ent < db->maxmaxcode)
-      {
-	db->n_bits++;
-      }
-
-    /* If output length is too large then this is an incomplete frame. */
-    if (wptr == NULL)
-      {
-	++db->incomp_count;
-	db->incomp_bytes += isize;
-	olen              = 0;
-      }
-    else /* Count the number of compressed frames */
-      {
-	++db->comp_count;
-	db->comp_bytes += olen;
-      }
-
-    /* Return the resulting output length */
-    return olen;
-#undef OUTPUT
-#undef PUTBYTE
-  }
-
-/*
- * Update the "BSD Compress" dictionary on the receiver for
- * incompressible data by pretending to compress the incoming data.
- */
-
-static void bsd_incomp (void *state, unsigned char *ibuf, int icnt)
-  {
-    (void) bsd_compress (state, ibuf, (char *) 0, icnt, 0);
-  }
-
-/*
- * Decompress "BSD Compress".
- *
- * Because of patent problems, we return DECOMP_ERROR for errors
- * found by inspecting the input data and for system problems, but
- * DECOMP_FATALERROR for any errors which could possibly be said to
- * be being detected "after" decompression.  For DECOMP_ERROR,
- * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
- * infringing a patent of Motorola's if we do, so we take CCP down
- * instead.
- *
- * Given that the frame has the correct sequence number and a good FCS,
- * errors such as invalid codes in the input most likely indicate a
- * bug, so we return DECOMP_FATALERROR for them in order to turn off
- * compression, even though they are detected by inspecting the input.
- */
-
-static int bsd_decompress (void *state, unsigned char *ibuf, int isize,
-			   unsigned char *obuf, int osize)
-  {
-    struct bsd_db *db;
-    unsigned int max_ent;
-    unsigned long accm;
-    unsigned int bitno;		/* 1st valid bit in accm */
-    unsigned int n_bits;
-    unsigned int tgtbitno;	/* bitno when we have a code */
-    struct bsd_dict *dictp;
-    int explen;
-    int seq;
-    unsigned int incode;
-    unsigned int oldcode;
-    unsigned int finchar;
-    unsigned char *p;
-    unsigned char *wptr;
-    int adrs;
-    int ctrl;
-    int ilen;
-    int codelen;
-    int extra;
-
-    db       = (struct bsd_db *) state;
-    max_ent  = db->max_ent;
-    accm     = 0;
-    bitno    = 32;		/* 1st valid bit in accm */
-    n_bits   = db->n_bits;
-    tgtbitno = 32 - n_bits;	/* bitno when we have a code */
-
-    /*
-     * Save the address/control from the PPP header
-     * and then get the sequence number.
-     */
-
-    adrs  = PPP_ADDRESS (ibuf);
-    ctrl  = PPP_CONTROL (ibuf);
-
-    seq   = (ibuf[4] << 8) + ibuf[5];
-
-    ibuf += (PPP_HDRLEN + 2);
-    ilen  = isize - (PPP_HDRLEN + 2);
-
-    /*
-     * Check the sequence number and give up if it differs from
-     * the value we're expecting.
-     */
-
-    if (seq != db->seqno)
-      {
-	if (db->debug)
-	  {
-	    printk("bsd_decomp%d: bad sequence # %d, expected %d\n",
-		   db->unit, seq, db->seqno - 1);
-	  }
-	return DECOMP_ERROR;
-      }
-
-    ++db->seqno;
-    db->bytes_out += ilen;
-
-    /*
-     * Fill in the ppp header, but not the last byte of the protocol
-     * (that comes from the decompressed data).
-     */
-
-    wptr    = obuf;
-    *wptr++ = adrs;
-    *wptr++ = ctrl;
-    *wptr++ = 0;
-
-    oldcode = CLEAR;
-    explen  = 3;
-
-    /*
-     * Keep the checkpoint correctly so that incompressible packets
-     * clear the dictionary at the proper times.
-     */
-
-    for (;;)
-      {
-	if (ilen-- <= 0)
-	  {
-	    db->in_count += (explen - 3); /* don't count the header */
-	    break;
-	  }
-
-	/*
-	 * Accumulate bytes until we have a complete code.
-	 * Then get the next code, relying on the 32-bit,
-	 * unsigned accm to mask the result.
-	 */
-
-	bitno -= 8;
-	accm  |= *ibuf++ << bitno;
-	if (tgtbitno < bitno)
-	  {
-	    continue;
-	  }
-
-	incode = accm >> tgtbitno;
-	accm <<= n_bits;
-	bitno += n_bits;
-
-	/*
-	 * The dictionary must only be cleared at the end of a packet.
-	 */
-
-	if (incode == CLEAR)
-	  {
-	    if (ilen > 0)
-	      {
-		if (db->debug)
-		  {
-		    printk("bsd_decomp%d: bad CLEAR\n", db->unit);
-		  }
-		return DECOMP_FATALERROR;	/* probably a bug */
-	      }
-
-	    bsd_clear(db);
-	    break;
-	  }
-
-	if ((incode > max_ent + 2) || (incode > db->maxmaxcode)
-	    || (incode > max_ent && oldcode == CLEAR))
-	  {
-	    if (db->debug)
-	      {
-		printk("bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
-		       db->unit, incode, oldcode);
-		printk("max_ent=0x%x explen=%d seqno=%d\n",
-		       max_ent, explen, db->seqno);
-	      }
-	    return DECOMP_FATALERROR;	/* probably a bug */
-	  }
-
-	/* Special case for KwKwK string. */
-	if (incode > max_ent)
-	  {
-	    finchar = oldcode;
-	    extra   = 1;
-	  }
-	else
-	  {
-	    finchar = incode;
-	    extra   = 0;
-	  }
-
-	codelen = *(lens_ptr (db, finchar));
-	explen += codelen + extra;
-	if (explen > osize)
-	  {
-	    if (db->debug)
-	      {
-		printk("bsd_decomp%d: ran out of mru\n", db->unit);
-#ifdef DEBUG
-		printk("  len=%d, finchar=0x%x, codelen=%d, explen=%d\n",
-		       ilen, finchar, codelen, explen);
-#endif
-	      }
-	    return DECOMP_FATALERROR;
-	  }
-
-	/*
-	 * Decode this code and install it in the decompressed buffer.
-	 */
-
-	wptr += codelen;
-	p     = wptr;
-	while (finchar > LAST)
-	  {
-	    struct bsd_dict *dictp2 = dict_ptr (db, finchar);
-
-	    dictp = dict_ptr (db, dictp2->cptr);
-#ifdef DEBUG
-	    if (--codelen <= 0 || dictp->codem1 != finchar-1)
-	      {
-		if (codelen <= 0)
-		  {
-		    printk("bsd_decomp%d: fell off end of chain ", db->unit);
-		    printk("0x%x at 0x%x by 0x%x, max_ent=0x%x\n",
-			   incode, finchar, dictp2->cptr, max_ent);
-		  }
-		else
-		  {
-		    if (dictp->codem1 != finchar-1)
-		      {
-			printk("bsd_decomp%d: bad code chain 0x%x "
-			       "finchar=0x%x ",
-			       db->unit, incode, finchar);
-
-			printk("oldcode=0x%x cptr=0x%x codem1=0x%x\n",
-			       oldcode, dictp2->cptr, dictp->codem1);
-		      }
-		  }
-		return DECOMP_FATALERROR;
-	      }
-#endif
-	    *--p    = dictp->f.hs.suffix;
-	    finchar = dictp->f.hs.prefix;
-	  }
-	*--p = finchar;
-
-#ifdef DEBUG
-	if (--codelen != 0)
-	  {
-	    printk("bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n",
-		   db->unit, codelen, incode, max_ent);
-	  }
-#endif
-
-	if (extra)		/* the KwKwK case again */
-	  {
-	    *wptr++ = finchar;
-	  }
-
-	/*
-	 * If not first code in a packet, and
-	 * if not out of code space, then allocate a new code.
-	 *
-	 * Keep the hash table correct so it can be used
-	 * with uncompressed packets.
-	 */
-
-	if (oldcode != CLEAR && max_ent < db->maxmaxcode)
-	  {
-	    struct bsd_dict *dictp2, *dictp3;
-	    unsigned short  *lens1,  *lens2;
-	    unsigned long fcode;
-	    int hval, disp, indx;
-
-	    fcode = BSD_KEY(oldcode,finchar);
-	    hval  = BSD_HASH(oldcode,finchar,db->hshift);
-	    dictp = dict_ptr (db, hval);
-
-	    /* look for a free hash table entry */
-	    if (dictp->codem1 < max_ent)
-	      {
-		disp = (hval == 0) ? 1 : hval;
-		do
-		  {
-		    hval += disp;
-		    if (hval >= db->hsize)
-		      {
-			hval -= db->hsize;
-		      }
-		    dictp = dict_ptr (db, hval);
-		  }
-		while (dictp->codem1 < max_ent);
-	      }
-
-	    /*
-	     * Invalidate previous hash table entry
-	     * assigned this code, and then take it over
-	     */
-
-	    dictp2 = dict_ptr (db, max_ent + 1);
-	    indx   = dictp2->cptr;
-	    dictp3 = dict_ptr (db, indx);
-
-	    if (dictp3->codem1 == max_ent)
-	      {
-		dictp3->codem1 = BADCODEM1;
-	      }
-
-	    dictp2->cptr   = hval;
-	    dictp->codem1  = max_ent;
-	    dictp->f.fcode = fcode;
-	    db->max_ent    = ++max_ent;
-
-	    /* Update the length of this string. */
-	    lens1  = lens_ptr (db, max_ent);
-	    lens2  = lens_ptr (db, oldcode);
-	    *lens1 = *lens2 + 1;
-
-	    /* Expand code size if needed. */
-	    if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
-	      {
-		db->n_bits = ++n_bits;
-		tgtbitno   = 32-n_bits;
-	      }
-	  }
-	oldcode = incode;
-      }
-
-    ++db->comp_count;
-    ++db->uncomp_count;
-    db->comp_bytes   += isize - BSD_OVHD - PPP_HDRLEN;
-    db->uncomp_bytes += explen;
-
-    if (bsd_check(db))
-      {
-	if (db->debug)
-	  {
-	    printk("bsd_decomp%d: peer should have cleared dictionary on %d\n",
-		   db->unit, db->seqno - 1);
-	  }
-      }
-    return explen;
-  }
-
-/*************************************************************
- * Table of addresses for the BSD compression module
- *************************************************************/
-
-static struct compressor ppp_bsd_compress = {
-	.compress_proto =	CI_BSD_COMPRESS,
-	.comp_alloc =		bsd_comp_alloc,
-	.comp_free =		bsd_free,
-	.comp_init =		bsd_comp_init,
-	.comp_reset =		bsd_reset,
-	.compress =		bsd_compress,
-	.comp_stat =		bsd_comp_stats,
-	.decomp_alloc =		bsd_decomp_alloc,
-	.decomp_free =		bsd_free,
-	.decomp_init =		bsd_decomp_init,
-	.decomp_reset =		bsd_reset,
-	.decompress =		bsd_decompress,
-	.incomp =		bsd_incomp,
-	.decomp_stat =		bsd_comp_stats,
-	.owner =		THIS_MODULE
-};
-
-/*************************************************************
- * Module support routines
- *************************************************************/
-
-static int __init bsdcomp_init(void)
-{
-	int answer = ppp_register_compressor(&ppp_bsd_compress);
-	if (answer == 0)
-		printk(KERN_INFO "PPP BSD Compression module registered\n");
-	return answer;
-}
-
-static void __exit bsdcomp_cleanup(void)
-{
-	ppp_unregister_compressor(&ppp_bsd_compress);
-}
-
-module_init(bsdcomp_init);
-module_exit(bsdcomp_cleanup);
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_ALIAS("ppp-compress-" __stringify(CI_BSD_COMPRESS));
diff -druN linux-libre-3.1-gnu/drivers/net/caif/caif_hsi.c linux-libre-3.2-gnu/drivers/net/caif/caif_hsi.c
--- linux-libre-3.1-gnu/drivers/net/caif/caif_hsi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/caif/caif_hsi.c	2012-01-04 18:55:44.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/sched.h>
 #include <linux/if_arp.h>
 #include <linux/timer.h>
+#include <linux/rtnetlink.h>
 #include <net/caif/caif_layer.h>
 #include <net/caif/caif_hsi.h>
 
@@ -29,6 +30,10 @@
 #define PAD_POW2(x, pow) ((((x)&((pow)-1)) == 0) ? 0 :\
 				(((pow)-((x)&((pow)-1)))))
 
+static int inactivity_timeout = 1000;
+module_param(inactivity_timeout, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(inactivity_timeout, "Inactivity timeout on HSI, ms.");
+
 /*
  * HSI padding options.
  * Warning: must be a base of 2 (& operation used) and can not be zero !
@@ -98,7 +103,8 @@
 	}
 	cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
 	if (!test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
-		mod_timer(&cfhsi->timer, jiffies + CFHSI_INACTIVITY_TOUT);
+		mod_timer(&cfhsi->timer,
+			jiffies + cfhsi->inactivity_timeout);
 	spin_unlock_bh(&cfhsi->lock);
 }
 
@@ -145,7 +151,7 @@
 		}
 
 		ret = 5 * HZ;
-		wait_event_interruptible_timeout(cfhsi->flush_fifo_wait,
+		ret = wait_event_interruptible_timeout(cfhsi->flush_fifo_wait,
 			 !test_bit(CFHSI_FLUSH_FIFO, &cfhsi->bits), ret);
 
 		if (ret < 0) {
@@ -178,6 +184,9 @@
 	if (!skb)
 		return 0;
 
+	/* Clear offset. */
+	desc->offset = 0;
+
 	/* Check if we can embed a CAIF frame. */
 	if (skb->len < CFHSI_MAX_EMB_FRM_SZ) {
 		struct caif_payload_info *info;
@@ -206,9 +215,7 @@
 			consume_skb(skb);
 			skb = NULL;
 		}
-	} else
-		/* Clear offset. */
-		desc->offset = 0;
+	}
 
 	/* Create payload CAIF frames. */
 	pfrm = desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ;
@@ -271,16 +278,13 @@
 	return CFHSI_DESC_SZ + pld_len;
 }
 
-static void cfhsi_tx_done_work(struct work_struct *work)
+static void cfhsi_tx_done(struct cfhsi *cfhsi)
 {
-	struct cfhsi *cfhsi = NULL;
 	struct cfhsi_desc *desc = NULL;
 	int len = 0;
 	int res;
 
-	cfhsi = container_of(work, struct cfhsi, tx_done_work);
-	dev_dbg(&cfhsi->ndev->dev, "%s.\n",
-		__func__);
+	dev_dbg(&cfhsi->ndev->dev, "%s.\n", __func__);
 
 	if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
 		return;
@@ -303,14 +307,22 @@
 		spin_unlock_bh(&cfhsi->lock);
 
 		/* Create HSI frame. */
-		len = cfhsi_tx_frm(desc, cfhsi);
-		if (!len) {
-			cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
-			/* Start inactivity timer. */
-			mod_timer(&cfhsi->timer,
-					jiffies + CFHSI_INACTIVITY_TOUT);
-			break;
-		}
+		do {
+			len = cfhsi_tx_frm(desc, cfhsi);
+			if (!len) {
+				spin_lock_bh(&cfhsi->lock);
+				if (unlikely(skb_peek(&cfhsi->qhead))) {
+					spin_unlock_bh(&cfhsi->lock);
+					continue;
+				}
+				cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
+				/* Start inactivity timer. */
+				mod_timer(&cfhsi->timer,
+					jiffies + cfhsi->inactivity_timeout);
+				spin_unlock_bh(&cfhsi->lock);
+				goto done;
+			}
+		} while (!len);
 
 		/* Set up new transfer. */
 		res = cfhsi->dev->cfhsi_tx(cfhsi->tx_buf, len, cfhsi->dev);
@@ -319,6 +331,9 @@
 				__func__, res);
 		}
 	} while (res < 0);
+
+done:
+	return;
 }
 
 static void cfhsi_tx_done_cb(struct cfhsi_drv *drv)
@@ -331,8 +346,7 @@
 
 	if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
 		return;
-
-	queue_work(cfhsi->wq, &cfhsi->tx_done_work);
+	cfhsi_tx_done(cfhsi);
 }
 
 static int cfhsi_rx_desc(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
@@ -346,14 +360,14 @@
 			(desc->offset > CFHSI_MAX_EMB_FRM_SZ)) {
 		dev_err(&cfhsi->ndev->dev, "%s: Invalid descriptor.\n",
 			__func__);
-		return 0;
+		return -EPROTO;
 	}
 
 	/* Check for embedded CAIF frame. */
 	if (desc->offset) {
 		struct sk_buff *skb;
 		u8 *dst = NULL;
-		int len = 0, retries = 0;
+		int len = 0;
 		pfrm = ((u8 *)desc) + desc->offset;
 
 		/* Remove offset padding. */
@@ -364,26 +378,19 @@
 		len |= ((*(pfrm+1)) << 8) & 0xFF00;
 		len += 2;	/* Add FCS fields. */
 
+		/* Sanity check length of CAIF frame. */
+		if (unlikely(len > CFHSI_MAX_CAIF_FRAME_SZ)) {
+			dev_err(&cfhsi->ndev->dev, "%s: Invalid length.\n",
+				__func__);
+			return -EPROTO;
+		}
 
 		/* Allocate SKB (OK even in IRQ context). */
-		skb = alloc_skb(len + 1, GFP_KERNEL);
-		while (!skb) {
-			retries++;
-			schedule_timeout(1);
-			skb = alloc_skb(len + 1, GFP_KERNEL);
-			if (skb) {
-				printk(KERN_WARNING "%s: slept for %u "
-						"before getting memory\n",
-						__func__, retries);
-				break;
-			}
-			if (retries > HZ) {
-				printk(KERN_ERR "%s: slept for 1HZ and "
-						"did not get memory\n",
-						__func__);
-				cfhsi->ndev->stats.rx_dropped++;
-				goto drop_frame;
-			}
+		skb = alloc_skb(len + 1, GFP_ATOMIC);
+		if (!skb) {
+			dev_err(&cfhsi->ndev->dev, "%s: Out of memory !\n",
+				__func__);
+			return -ENOMEM;
 		}
 		caif_assert(skb != NULL);
 
@@ -409,7 +416,6 @@
 		cfhsi->ndev->stats.rx_bytes += len;
 	}
 
-drop_frame:
 	/* Calculate transfer length. */
 	plen = desc->cffrm_len;
 	while (nfrms < CFHSI_MAX_PKTS && *plen) {
@@ -422,13 +428,12 @@
 	if (desc->header & CFHSI_PIGGY_DESC)
 		xfer_sz += CFHSI_DESC_SZ;
 
-	if (xfer_sz % 4) {
+	if ((xfer_sz % 4) || (xfer_sz > (CFHSI_BUF_SZ_RX - CFHSI_DESC_SZ))) {
 		dev_err(&cfhsi->ndev->dev,
 				"%s: Invalid payload len: %d, ignored.\n",
 			__func__, xfer_sz);
-		xfer_sz = 0;
+		return -EPROTO;
 	}
-
 	return xfer_sz;
 }
 
@@ -444,23 +449,27 @@
 			(desc->offset > CFHSI_MAX_EMB_FRM_SZ))) {
 		dev_err(&cfhsi->ndev->dev, "%s: Invalid descriptor.\n",
 			__func__);
-		return -EINVAL;
+		return -EPROTO;
 	}
 
 	/* Set frame pointer to start of payload. */
 	pfrm = desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ;
 	plen = desc->cffrm_len;
+
+	/* Skip already processed frames. */
+	while (nfrms < cfhsi->rx_state.nfrms) {
+		pfrm += *plen;
+		rx_sz += *plen;
+		plen++;
+		nfrms++;
+	}
+
+	/* Parse payload. */
 	while (nfrms < CFHSI_MAX_PKTS && *plen) {
 		struct sk_buff *skb;
 		u8 *dst = NULL;
 		u8 *pcffrm = NULL;
-		int len = 0, retries = 0;
-
-		if (WARN_ON(desc->cffrm_len[nfrms] > CFHSI_MAX_PAYLOAD_SZ)) {
-			dev_err(&cfhsi->ndev->dev, "%s: Invalid payload.\n",
-				__func__);
-			return -EINVAL;
-		}
+		int len = 0;
 
 		/* CAIF frame starts after head padding. */
 		pcffrm = pfrm + *pfrm + 1;
@@ -470,25 +479,20 @@
 		len |= ((*(pcffrm + 1)) << 8) & 0xFF00;
 		len += 2;	/* Add FCS fields. */
 
+		/* Sanity check length of CAIF frames. */
+		if (unlikely(len > CFHSI_MAX_CAIF_FRAME_SZ)) {
+			dev_err(&cfhsi->ndev->dev, "%s: Invalid length.\n",
+				__func__);
+			return -EPROTO;
+		}
+
 		/* Allocate SKB (OK even in IRQ context). */
-		skb = alloc_skb(len + 1, GFP_KERNEL);
-		while (!skb) {
-			retries++;
-			schedule_timeout(1);
-			skb = alloc_skb(len + 1, GFP_KERNEL);
-			if (skb) {
-				printk(KERN_WARNING "%s: slept for %u "
-						"before getting memory\n",
-						__func__, retries);
-				break;
-			}
-			if (retries > HZ) {
-				printk(KERN_ERR "%s: slept for 1HZ "
-						"and did not get memory\n",
-						__func__);
-				cfhsi->ndev->stats.rx_dropped++;
-				goto drop_frame;
-			}
+		skb = alloc_skb(len + 1, GFP_ATOMIC);
+		if (!skb) {
+			dev_err(&cfhsi->ndev->dev, "%s: Out of memory !\n",
+				__func__);
+			cfhsi->rx_state.nfrms = nfrms;
+			return -ENOMEM;
 		}
 		caif_assert(skb != NULL);
 
@@ -512,7 +516,6 @@
 		cfhsi->ndev->stats.rx_packets++;
 		cfhsi->ndev->stats.rx_bytes += len;
 
-drop_frame:
 		pfrm += *plen;
 		rx_sz += *plen;
 		plen++;
@@ -522,40 +525,56 @@
 	return rx_sz;
 }
 
-static void cfhsi_rx_done_work(struct work_struct *work)
+static void cfhsi_rx_done(struct cfhsi *cfhsi)
 {
 	int res;
 	int desc_pld_len = 0;
-	struct cfhsi *cfhsi = NULL;
 	struct cfhsi_desc *desc = NULL;
 
-	cfhsi = container_of(work, struct cfhsi, rx_done_work);
 	desc = (struct cfhsi_desc *)cfhsi->rx_buf;
 
-	dev_dbg(&cfhsi->ndev->dev, "%s: Kick timer if pending.\n",
-		__func__);
+	dev_dbg(&cfhsi->ndev->dev, "%s\n", __func__);
 
 	if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
 		return;
 
 	/* Update inactivity timer if pending. */
-	mod_timer_pending(&cfhsi->timer, jiffies + CFHSI_INACTIVITY_TOUT);
+	spin_lock_bh(&cfhsi->lock);
+	mod_timer_pending(&cfhsi->timer,
+			jiffies + cfhsi->inactivity_timeout);
+	spin_unlock_bh(&cfhsi->lock);
 
-	if (cfhsi->rx_state == CFHSI_RX_STATE_DESC) {
+	if (cfhsi->rx_state.state == CFHSI_RX_STATE_DESC) {
 		desc_pld_len = cfhsi_rx_desc(desc, cfhsi);
+		if (desc_pld_len == -ENOMEM)
+			goto restart;
+		if (desc_pld_len == -EPROTO)
+			goto out_of_sync;
 	} else {
 		int pld_len;
 
-		pld_len = cfhsi_rx_pld(desc, cfhsi);
+		if (!cfhsi->rx_state.piggy_desc) {
+			pld_len = cfhsi_rx_pld(desc, cfhsi);
+			if (pld_len == -ENOMEM)
+				goto restart;
+			if (pld_len == -EPROTO)
+				goto out_of_sync;
+			cfhsi->rx_state.pld_len = pld_len;
+		} else {
+			pld_len = cfhsi->rx_state.pld_len;
+		}
 
 		if ((pld_len > 0) && (desc->header & CFHSI_PIGGY_DESC)) {
 			struct cfhsi_desc *piggy_desc;
 			piggy_desc = (struct cfhsi_desc *)
 				(desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ +
 						pld_len);
+			cfhsi->rx_state.piggy_desc = true;
 
 			/* Extract piggy-backed descriptor. */
 			desc_pld_len = cfhsi_rx_desc(piggy_desc, cfhsi);
+			if (desc_pld_len == -ENOMEM)
+				goto restart;
 
 			/*
 			 * Copy needed information from the piggy-backed
@@ -563,19 +582,22 @@
 			 */
 			memcpy((u8 *)desc, (u8 *)piggy_desc,
 					CFHSI_DESC_SHORT_SZ);
+
+			if (desc_pld_len == -EPROTO)
+				goto out_of_sync;
 		}
 	}
 
+	memset(&cfhsi->rx_state, 0, sizeof(cfhsi->rx_state));
 	if (desc_pld_len) {
-		cfhsi->rx_state = CFHSI_RX_STATE_PAYLOAD;
+		cfhsi->rx_state.state = CFHSI_RX_STATE_PAYLOAD;
 		cfhsi->rx_ptr = cfhsi->rx_buf + CFHSI_DESC_SZ;
 		cfhsi->rx_len = desc_pld_len;
 	} else {
-		cfhsi->rx_state = CFHSI_RX_STATE_DESC;
+		cfhsi->rx_state.state = CFHSI_RX_STATE_DESC;
 		cfhsi->rx_ptr = cfhsi->rx_buf;
 		cfhsi->rx_len = CFHSI_DESC_SZ;
 	}
-	clear_bit(CFHSI_PENDING_RX, &cfhsi->bits);
 
 	if (test_bit(CFHSI_AWAKE, &cfhsi->bits)) {
 		/* Set up new transfer. */
@@ -590,6 +612,33 @@
 			cfhsi->ndev->stats.rx_dropped++;
 		}
 	}
+	return;
+
+restart:
+	if (++cfhsi->rx_state.retries > CFHSI_MAX_RX_RETRIES) {
+		dev_err(&cfhsi->ndev->dev, "%s: No memory available "
+			"in %d iterations.\n",
+			__func__, CFHSI_MAX_RX_RETRIES);
+		BUG();
+	}
+	mod_timer(&cfhsi->rx_slowpath_timer, jiffies + 1);
+	return;
+
+out_of_sync:
+	dev_err(&cfhsi->ndev->dev, "%s: Out of sync.\n", __func__);
+	print_hex_dump_bytes("--> ", DUMP_PREFIX_NONE,
+			cfhsi->rx_buf, CFHSI_DESC_SZ);
+	schedule_work(&cfhsi->out_of_sync_work);
+}
+
+static void cfhsi_rx_slowpath(unsigned long arg)
+{
+	struct cfhsi *cfhsi = (struct cfhsi *)arg;
+
+	dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+		__func__);
+
+	cfhsi_rx_done(cfhsi);
 }
 
 static void cfhsi_rx_done_cb(struct cfhsi_drv *drv)
@@ -603,12 +652,10 @@
 	if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
 		return;
 
-	set_bit(CFHSI_PENDING_RX, &cfhsi->bits);
-
 	if (test_and_clear_bit(CFHSI_FLUSH_FIFO, &cfhsi->bits))
 		wake_up_interruptible(&cfhsi->flush_fifo_wait);
 	else
-		queue_work(cfhsi->wq, &cfhsi->rx_done_work);
+		cfhsi_rx_done(cfhsi);
 }
 
 static void cfhsi_wake_up(struct work_struct *work)
@@ -627,6 +674,7 @@
 		/* It happenes when wakeup is requested by
 		 * both ends at the same time. */
 		clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
+		clear_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits);
 		return;
 	}
 
@@ -637,25 +685,53 @@
 		__func__);
 
 	/* Wait for acknowledge. */
-	ret = CFHSI_WAKEUP_TOUT;
-	wait_event_interruptible_timeout(cfhsi->wake_up_wait,
-					test_bit(CFHSI_WAKE_UP_ACK,
+	ret = CFHSI_WAKE_TOUT;
+	ret = wait_event_interruptible_timeout(cfhsi->wake_up_wait,
+					test_and_clear_bit(CFHSI_WAKE_UP_ACK,
 							&cfhsi->bits), ret);
 	if (unlikely(ret < 0)) {
 		/* Interrupted by signal. */
-		dev_info(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n",
+		dev_err(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n",
 			__func__, ret);
+
 		clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
 		cfhsi->dev->cfhsi_wake_down(cfhsi->dev);
 		return;
 	} else if (!ret) {
+		bool ca_wake = false;
+		size_t fifo_occupancy = 0;
+
 		/* Wakeup timeout */
 		dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n",
 			__func__);
+
+		/* Check FIFO to check if modem has sent something. */
+		WARN_ON(cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
+					&fifo_occupancy));
+
+		dev_err(&cfhsi->ndev->dev, "%s: Bytes in FIFO: %u.\n",
+				__func__, (unsigned) fifo_occupancy);
+
+		/* Check if we misssed the interrupt. */
+		WARN_ON(cfhsi->dev->cfhsi_get_peer_wake(cfhsi->dev,
+							&ca_wake));
+
+		if (ca_wake) {
+			dev_err(&cfhsi->ndev->dev, "%s: CA Wake missed !.\n",
+				__func__);
+
+			/* Clear the CFHSI_WAKE_UP_ACK bit to prevent race. */
+			clear_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits);
+
+			/* Continue execution. */
+			goto wake_ack;
+		}
+
 		clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
 		cfhsi->dev->cfhsi_wake_down(cfhsi->dev);
 		return;
 	}
+wake_ack:
 	dev_dbg(&cfhsi->ndev->dev, "%s: Woken.\n",
 		__func__);
 
@@ -664,16 +740,11 @@
 	clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
 
 	/* Resume read operation. */
-	if (!test_bit(CFHSI_PENDING_RX, &cfhsi->bits)) {
-		dev_dbg(&cfhsi->ndev->dev, "%s: Start RX.\n",
-			__func__);
-		res = cfhsi->dev->cfhsi_rx(cfhsi->rx_ptr,
-				cfhsi->rx_len, cfhsi->dev);
-		if (WARN_ON(res < 0)) {
-			dev_err(&cfhsi->ndev->dev, "%s: RX error %d.\n",
-				__func__, res);
-		}
-	}
+	dev_dbg(&cfhsi->ndev->dev, "%s: Start RX.\n", __func__);
+	res = cfhsi->dev->cfhsi_rx(cfhsi->rx_ptr, cfhsi->rx_len, cfhsi->dev);
+
+	if (WARN_ON(res < 0))
+		dev_err(&cfhsi->ndev->dev, "%s: RX err %d.\n", __func__, res);
 
 	/* Clear power up acknowledment. */
 	clear_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits);
@@ -686,7 +757,7 @@
 			__func__);
 		/* Start inactivity timer. */
 		mod_timer(&cfhsi->timer,
-				jiffies + CFHSI_INACTIVITY_TOUT);
+				jiffies + cfhsi->inactivity_timeout);
 		spin_unlock_bh(&cfhsi->lock);
 		return;
 	}
@@ -712,79 +783,81 @@
 				"%s: Failed to create HSI frame: %d.\n",
 				__func__, len);
 	}
-
 }
 
 static void cfhsi_wake_down(struct work_struct *work)
 {
 	long ret;
 	struct cfhsi *cfhsi = NULL;
-	size_t fifo_occupancy;
+	size_t fifo_occupancy = 0;
+	int retry = CFHSI_WAKE_TOUT;
 
 	cfhsi = container_of(work, struct cfhsi, wake_down_work);
-	dev_dbg(&cfhsi->ndev->dev, "%s.\n",
-		__func__);
+	dev_dbg(&cfhsi->ndev->dev, "%s.\n", __func__);
 
 	if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
 		return;
 
-	/* Check if there is something in FIFO. */
-	if (WARN_ON(cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
-							&fifo_occupancy)))
-		fifo_occupancy = 0;
-
-	if (fifo_occupancy) {
-		dev_dbg(&cfhsi->ndev->dev,
-				"%s: %u words in RX FIFO, restart timer.\n",
-				__func__, (unsigned) fifo_occupancy);
-		spin_lock_bh(&cfhsi->lock);
-		mod_timer(&cfhsi->timer,
-				jiffies + CFHSI_INACTIVITY_TOUT);
-		spin_unlock_bh(&cfhsi->lock);
-		return;
-	}
-
-	/* Cancel pending RX requests */
-	cfhsi->dev->cfhsi_rx_cancel(cfhsi->dev);
-
 	/* Deactivate wake line. */
 	cfhsi->dev->cfhsi_wake_down(cfhsi->dev);
 
 	/* Wait for acknowledge. */
-	ret = CFHSI_WAKEUP_TOUT;
+	ret = CFHSI_WAKE_TOUT;
 	ret = wait_event_interruptible_timeout(cfhsi->wake_down_wait,
-					test_bit(CFHSI_WAKE_DOWN_ACK,
-							&cfhsi->bits),
-					ret);
+					test_and_clear_bit(CFHSI_WAKE_DOWN_ACK,
+							&cfhsi->bits), ret);
 	if (ret < 0) {
 		/* Interrupted by signal. */
-		dev_info(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n",
+		dev_err(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n",
 			__func__, ret);
 		return;
 	} else if (!ret) {
+		bool ca_wake = true;
+
 		/* Timeout */
-		dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n",
-			__func__);
+		dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n", __func__);
+
+		/* Check if we misssed the interrupt. */
+		WARN_ON(cfhsi->dev->cfhsi_get_peer_wake(cfhsi->dev,
+							&ca_wake));
+		if (!ca_wake)
+			dev_err(&cfhsi->ndev->dev, "%s: CA Wake missed !.\n",
+				__func__);
 	}
 
-	/* Clear power down acknowledment. */
-	clear_bit(CFHSI_WAKE_DOWN_ACK, &cfhsi->bits);
+	/* Check FIFO occupancy. */
+	while (retry) {
+		WARN_ON(cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
+							&fifo_occupancy));
+
+		if (!fifo_occupancy)
+			break;
+
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(1);
+		retry--;
+	}
+
+	if (!retry)
+		dev_err(&cfhsi->ndev->dev, "%s: FIFO Timeout.\n", __func__);
+
+	/* Clear AWAKE condition. */
 	clear_bit(CFHSI_AWAKE, &cfhsi->bits);
 
-	/* Check if there is something in FIFO. */
-	if (WARN_ON(cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
-							&fifo_occupancy)))
-		fifo_occupancy = 0;
+	/* Cancel pending RX requests. */
+	cfhsi->dev->cfhsi_rx_cancel(cfhsi->dev);
 
-	if (fifo_occupancy) {
-		dev_dbg(&cfhsi->ndev->dev,
-				"%s: %u words in RX FIFO, wakeup forced.\n",
-				__func__, (unsigned) fifo_occupancy);
-		if (!test_and_set_bit(CFHSI_WAKE_UP, &cfhsi->bits))
-			queue_work(cfhsi->wq, &cfhsi->wake_up_work);
-	} else
-		dev_dbg(&cfhsi->ndev->dev, "%s: Done.\n",
-			__func__);
+}
+
+static void cfhsi_out_of_sync(struct work_struct *work)
+{
+	struct cfhsi *cfhsi = NULL;
+
+	cfhsi = container_of(work, struct cfhsi, out_of_sync_work);
+
+	rtnl_lock();
+	dev_close(cfhsi->ndev);
+	rtnl_unlock();
 }
 
 static void cfhsi_wake_up_cb(struct cfhsi_drv *drv)
@@ -854,17 +927,15 @@
 		start_xfer = 1;
 	}
 
-	spin_unlock_bh(&cfhsi->lock);
-
-	if (!start_xfer)
+	if (!start_xfer) {
+		spin_unlock_bh(&cfhsi->lock);
 		return 0;
+	}
 
 	/* Delete inactivity timer if started. */
-#ifdef CONFIG_SMP
 	timer_active = del_timer_sync(&cfhsi->timer);
-#else
-	timer_active = del_timer(&cfhsi->timer);
-#endif /* CONFIG_SMP */
+
+	spin_unlock_bh(&cfhsi->lock);
 
 	if (timer_active) {
 		struct cfhsi_desc *desc = (struct cfhsi_desc *)cfhsi->tx_buf;
@@ -937,11 +1008,8 @@
 	int res;
 
 	ndev = alloc_netdev(sizeof(struct cfhsi), "cfhsi%d", cfhsi_setup);
-	if (!ndev) {
-		dev_err(&pdev->dev, "%s: alloc_netdev failed.\n",
-			__func__);
+	if (!ndev)
 		return -ENODEV;
-	}
 
 	cfhsi = netdev_priv(ndev);
 	cfhsi->ndev = ndev;
@@ -949,7 +1017,7 @@
 
 	/* Initialize state vaiables. */
 	cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
-	cfhsi->rx_state = CFHSI_RX_STATE_DESC;
+	cfhsi->rx_state.state = CFHSI_RX_STATE_DESC;
 
 	/* Set flow info */
 	cfhsi->flow_off_sent = 0;
@@ -969,8 +1037,6 @@
 	 */
 	cfhsi->tx_buf = kzalloc(CFHSI_BUF_SZ_TX, GFP_KERNEL);
 	if (!cfhsi->tx_buf) {
-		dev_err(&ndev->dev, "%s: Failed to allocate TX buffer.\n",
-			__func__);
 		res = -ENODEV;
 		goto err_alloc_tx;
 	}
@@ -981,13 +1047,23 @@
 	 */
 	cfhsi->rx_buf = kzalloc(CFHSI_BUF_SZ_RX, GFP_KERNEL);
 	if (!cfhsi->rx_buf) {
-		dev_err(&ndev->dev, "%s: Failed to allocate RX buffer.\n",
-			__func__);
 		res = -ENODEV;
 		goto err_alloc_rx;
 	}
 
-	/* Initialize receive variables. */
+	/* Pre-calculate inactivity timeout. */
+	if (inactivity_timeout != -1) {
+		cfhsi->inactivity_timeout =
+				inactivity_timeout * HZ / 1000;
+		if (!cfhsi->inactivity_timeout)
+			cfhsi->inactivity_timeout = 1;
+		else if (cfhsi->inactivity_timeout > NEXT_TIMER_MAX_DELTA)
+			cfhsi->inactivity_timeout = NEXT_TIMER_MAX_DELTA;
+	} else {
+		cfhsi->inactivity_timeout = NEXT_TIMER_MAX_DELTA;
+	}
+
+	/* Initialize recieve vaiables. */
 	cfhsi->rx_ptr = cfhsi->rx_buf;
 	cfhsi->rx_len = CFHSI_DESC_SZ;
 
@@ -997,19 +1073,19 @@
 	/* Set up the driver. */
 	cfhsi->drv.tx_done_cb = cfhsi_tx_done_cb;
 	cfhsi->drv.rx_done_cb = cfhsi_rx_done_cb;
+	cfhsi->drv.wake_up_cb = cfhsi_wake_up_cb;
+	cfhsi->drv.wake_down_cb = cfhsi_wake_down_cb;
 
 	/* Initialize the work queues. */
 	INIT_WORK(&cfhsi->wake_up_work, cfhsi_wake_up);
 	INIT_WORK(&cfhsi->wake_down_work, cfhsi_wake_down);
-	INIT_WORK(&cfhsi->rx_done_work, cfhsi_rx_done_work);
-	INIT_WORK(&cfhsi->tx_done_work, cfhsi_tx_done_work);
+	INIT_WORK(&cfhsi->out_of_sync_work, cfhsi_out_of_sync);
 
 	/* Clear all bit fields. */
 	clear_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits);
 	clear_bit(CFHSI_WAKE_DOWN_ACK, &cfhsi->bits);
 	clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
 	clear_bit(CFHSI_AWAKE, &cfhsi->bits);
-	clear_bit(CFHSI_PENDING_RX, &cfhsi->bits);
 
 	/* Create work thread. */
 	cfhsi->wq = create_singlethread_workqueue(pdev->name);
@@ -1029,6 +1105,10 @@
 	init_timer(&cfhsi->timer);
 	cfhsi->timer.data = (unsigned long)cfhsi;
 	cfhsi->timer.function = cfhsi_inactivity_tout;
+	/* Setup the slowpath RX timer. */
+	init_timer(&cfhsi->rx_slowpath_timer);
+	cfhsi->rx_slowpath_timer.data = (unsigned long)cfhsi;
+	cfhsi->rx_slowpath_timer.function = cfhsi_rx_slowpath;
 
 	/* Add CAIF HSI device to list. */
 	spin_lock(&cfhsi_list_lock);
@@ -1052,9 +1132,6 @@
 		goto err_net_reg;
 	}
 
-	cfhsi->drv.wake_up_cb = cfhsi_wake_up_cb;
-	cfhsi->drv.wake_down_cb = cfhsi_wake_down_cb;
-
 	/* Register network device. */
 	res = register_netdev(ndev);
 	if (res) {
@@ -1081,7 +1158,7 @@
 	return res;
 }
 
-static void cfhsi_shutdown(struct cfhsi *cfhsi, bool remove_platform_dev)
+static void cfhsi_shutdown(struct cfhsi *cfhsi)
 {
 	u8 *tx_buf, *rx_buf;
 
@@ -1091,28 +1168,17 @@
 	/* going to shutdown driver */
 	set_bit(CFHSI_SHUTDOWN, &cfhsi->bits);
 
-	if (remove_platform_dev) {
-		/* Flush workqueue */
-		flush_workqueue(cfhsi->wq);
-
-		/* Notify device. */
-		platform_device_unregister(cfhsi->pdev);
-	}
-
 	/* Flush workqueue */
 	flush_workqueue(cfhsi->wq);
 
-	/* Delete timer if pending */
-#ifdef CONFIG_SMP
+	/* Delete timers if pending */
 	del_timer_sync(&cfhsi->timer);
-#else
-	del_timer(&cfhsi->timer);
-#endif /* CONFIG_SMP */
+	del_timer_sync(&cfhsi->rx_slowpath_timer);
 
 	/* Cancel pending RX request (if any) */
 	cfhsi->dev->cfhsi_rx_cancel(cfhsi->dev);
 
-	/* Flush again and destroy workqueue */
+	/* Destroy workqueue */
 	destroy_workqueue(cfhsi->wq);
 
 	/* Store bufferes: will be freed later. */
@@ -1151,7 +1217,7 @@
 			spin_unlock(&cfhsi_list_lock);
 
 			/* Shutdown driver. */
-			cfhsi_shutdown(cfhsi, false);
+			cfhsi_shutdown(cfhsi);
 
 			return 0;
 		}
@@ -1184,7 +1250,7 @@
 		spin_unlock(&cfhsi_list_lock);
 
 		/* Shutdown driver. */
-		cfhsi_shutdown(cfhsi, true);
+		cfhsi_shutdown(cfhsi);
 
 		spin_lock(&cfhsi_list_lock);
 	}
diff -druN linux-libre-3.1-gnu/drivers/net/caif/caif_spi.c linux-libre-3.2-gnu/drivers/net/caif/caif_spi.c
--- linux-libre-3.1-gnu/drivers/net/caif/caif_spi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/caif/caif_spi.c	2012-01-04 18:55:44.000000000 -0500
@@ -664,8 +664,6 @@
 	/* Allocate DMA buffers. */
 	cfspi->xfer.va_tx = dma_alloc(&cfspi->xfer.pa_tx);
 	if (!cfspi->xfer.va_tx) {
-		printk(KERN_WARNING
-		       "CFSPI: failed to allocate dma TX buffer.\n");
 		res = -ENODEV;
 		goto err_dma_alloc_tx;
 	}
@@ -673,8 +671,6 @@
 	cfspi->xfer.va_rx = dma_alloc(&cfspi->xfer.pa_rx);
 
 	if (!cfspi->xfer.va_rx) {
-		printk(KERN_WARNING
-		       "CFSPI: failed to allocate dma TX buffer.\n");
 		res = -ENODEV;
 		goto err_dma_alloc_rx;
 	}
diff -druN linux-libre-3.1-gnu/drivers/net/can/at91_can.c linux-libre-3.2-gnu/drivers/net/can/at91_can.c
--- linux-libre-3.1-gnu/drivers/net/can/at91_can.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/can/at91_can.c	2012-01-04 18:55:44.000000000 -0500
@@ -8,8 +8,6 @@
  * Public License ("GPL") version 2 as distributed in the 'COPYING'
  * file from the main directory of the linux kernel source.
  *
- * Send feedback to <socketcan-users@lists.berlios.de>
- *
  *
  * Your platform definition file should specify something like:
  *
diff -druN linux-libre-3.1-gnu/drivers/net/can/dev.c linux-libre-3.2-gnu/drivers/net/can/dev.c
--- linux-libre-3.1-gnu/drivers/net/can/dev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/can/dev.c	2012-01-04 18:55:44.000000000 -0500
@@ -150,7 +150,19 @@
 	bt->prop_seg = tseg1 / 2;
 	bt->phase_seg1 = tseg1 - bt->prop_seg;
 	bt->phase_seg2 = tseg2;
-	bt->sjw = 1;
+
+	/* check for sjw user settings */
+	if (!bt->sjw || !btc->sjw_max)
+		bt->sjw = 1;
+	else {
+		/* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
+		if (bt->sjw > btc->sjw_max)
+			bt->sjw = btc->sjw_max;
+		/* bt->sjw must not be higher than tseg2 */
+		if (tseg2 < bt->sjw)
+			bt->sjw = tseg2;
+	}
+
 	bt->brp = best_brp;
 	/* real bit-rate */
 	bt->bitrate = priv->clock.freq / (bt->brp * (tseg1 + tseg2 + 1));
diff -druN linux-libre-3.1-gnu/drivers/net/can/flexcan.c linux-libre-3.2-gnu/drivers/net/can/flexcan.c
--- linux-libre-3.1-gnu/drivers/net/can/flexcan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/can/flexcan.c	2012-01-04 18:55:44.000000000 -0500
@@ -33,10 +33,9 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 
-#include <mach/clock.h>
-
 #define DRV_NAME			"flexcan"
 
 /* 8 for RX fifo and 2 error handling */
@@ -192,6 +191,31 @@
 };
 
 /*
+ * Abstract off the read/write for arm versus ppc.
+ */
+#if defined(__BIG_ENDIAN)
+static inline u32 flexcan_read(void __iomem *addr)
+{
+	return in_be32(addr);
+}
+
+static inline void flexcan_write(u32 val, void __iomem *addr)
+{
+	out_be32(addr, val);
+}
+#else
+static inline u32 flexcan_read(void __iomem *addr)
+{
+	return readl(addr);
+}
+
+static inline void flexcan_write(u32 val, void __iomem *addr)
+{
+	writel(val, addr);
+}
+#endif
+
+/*
  * Swtich transceiver on or off
  */
 static void flexcan_transceiver_switch(const struct flexcan_priv *priv, int on)
@@ -212,9 +236,9 @@
 	struct flexcan_regs __iomem *regs = priv->base;
 	u32 reg;
 
-	reg = readl(&regs->mcr);
+	reg = flexcan_read(&regs->mcr);
 	reg &= ~FLEXCAN_MCR_MDIS;
-	writel(reg, &regs->mcr);
+	flexcan_write(reg, &regs->mcr);
 
 	udelay(10);
 }
@@ -224,9 +248,9 @@
 	struct flexcan_regs __iomem *regs = priv->base;
 	u32 reg;
 
-	reg = readl(&regs->mcr);
+	reg = flexcan_read(&regs->mcr);
 	reg |= FLEXCAN_MCR_MDIS;
-	writel(reg, &regs->mcr);
+	flexcan_write(reg, &regs->mcr);
 }
 
 static int flexcan_get_berr_counter(const struct net_device *dev,
@@ -234,7 +258,7 @@
 {
 	const struct flexcan_priv *priv = netdev_priv(dev);
 	struct flexcan_regs __iomem *regs = priv->base;
-	u32 reg = readl(&regs->ecr);
+	u32 reg = flexcan_read(&regs->ecr);
 
 	bec->txerr = (reg >> 0) & 0xff;
 	bec->rxerr = (reg >> 8) & 0xff;
@@ -268,15 +292,15 @@
 
 	if (cf->can_dlc > 0) {
 		u32 data = be32_to_cpup((__be32 *)&cf->data[0]);
-		writel(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[0]);
+		flexcan_write(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[0]);
 	}
 	if (cf->can_dlc > 3) {
 		u32 data = be32_to_cpup((__be32 *)&cf->data[4]);
-		writel(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[1]);
+		flexcan_write(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[1]);
 	}
 
-	writel(can_id, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
-	writel(ctrl, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
+	flexcan_write(can_id, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
+	flexcan_write(ctrl, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
 
 	kfree_skb(skb);
 
@@ -464,8 +488,8 @@
 	struct flexcan_mb __iomem *mb = &regs->cantxfg[0];
 	u32 reg_ctrl, reg_id;
 
-	reg_ctrl = readl(&mb->can_ctrl);
-	reg_id = readl(&mb->can_id);
+	reg_ctrl = flexcan_read(&mb->can_ctrl);
+	reg_id = flexcan_read(&mb->can_id);
 	if (reg_ctrl & FLEXCAN_MB_CNT_IDE)
 		cf->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG;
 	else
@@ -475,12 +499,12 @@
 		cf->can_id |= CAN_RTR_FLAG;
 	cf->can_dlc = get_can_dlc((reg_ctrl >> 16) & 0xf);
 
-	*(__be32 *)(cf->data + 0) = cpu_to_be32(readl(&mb->data[0]));
-	*(__be32 *)(cf->data + 4) = cpu_to_be32(readl(&mb->data[1]));
+	*(__be32 *)(cf->data + 0) = cpu_to_be32(flexcan_read(&mb->data[0]));
+	*(__be32 *)(cf->data + 4) = cpu_to_be32(flexcan_read(&mb->data[1]));
 
 	/* mark as read */
-	writel(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->iflag1);
-	readl(&regs->timer);
+	flexcan_write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->iflag1);
+	flexcan_read(&regs->timer);
 }
 
 static int flexcan_read_frame(struct net_device *dev)
@@ -516,17 +540,17 @@
 	 * The error bits are cleared on read,
 	 * use saved value from irq handler.
 	 */
-	reg_esr = readl(&regs->esr) | priv->reg_esr;
+	reg_esr = flexcan_read(&regs->esr) | priv->reg_esr;
 
 	/* handle state changes */
 	work_done += flexcan_poll_state(dev, reg_esr);
 
 	/* handle RX-FIFO */
-	reg_iflag1 = readl(&regs->iflag1);
+	reg_iflag1 = flexcan_read(&regs->iflag1);
 	while (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE &&
 	       work_done < quota) {
 		work_done += flexcan_read_frame(dev);
-		reg_iflag1 = readl(&regs->iflag1);
+		reg_iflag1 = flexcan_read(&regs->iflag1);
 	}
 
 	/* report bus errors */
@@ -536,8 +560,8 @@
 	if (work_done < quota) {
 		napi_complete(napi);
 		/* enable IRQs */
-		writel(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
-		writel(priv->reg_ctrl_default, &regs->ctrl);
+		flexcan_write(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
+		flexcan_write(priv->reg_ctrl_default, &regs->ctrl);
 	}
 
 	return work_done;
@@ -551,9 +575,9 @@
 	struct flexcan_regs __iomem *regs = priv->base;
 	u32 reg_iflag1, reg_esr;
 
-	reg_iflag1 = readl(&regs->iflag1);
-	reg_esr = readl(&regs->esr);
-	writel(FLEXCAN_ESR_ERR_INT, &regs->esr);	/* ACK err IRQ */
+	reg_iflag1 = flexcan_read(&regs->iflag1);
+	reg_esr = flexcan_read(&regs->esr);
+	flexcan_write(FLEXCAN_ESR_ERR_INT, &regs->esr);	/* ACK err IRQ */
 
 	/*
 	 * schedule NAPI in case of:
@@ -569,16 +593,16 @@
 		 * save them for later use.
 		 */
 		priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS;
-		writel(FLEXCAN_IFLAG_DEFAULT & ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE,
-		       &regs->imask1);
-		writel(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
+		flexcan_write(FLEXCAN_IFLAG_DEFAULT &
+			~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->imask1);
+		flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
 		       &regs->ctrl);
 		napi_schedule(&priv->napi);
 	}
 
 	/* FIFO overflow */
 	if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW) {
-		writel(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, &regs->iflag1);
+		flexcan_write(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, &regs->iflag1);
 		dev->stats.rx_over_errors++;
 		dev->stats.rx_errors++;
 	}
@@ -587,7 +611,7 @@
 	if (reg_iflag1 & (1 << FLEXCAN_TX_BUF_ID)) {
 		/* tx_bytes is incremented in flexcan_start_xmit */
 		stats->tx_packets++;
-		writel((1 << FLEXCAN_TX_BUF_ID), &regs->iflag1);
+		flexcan_write((1 << FLEXCAN_TX_BUF_ID), &regs->iflag1);
 		netif_wake_queue(dev);
 	}
 
@@ -601,7 +625,7 @@
 	struct flexcan_regs __iomem *regs = priv->base;
 	u32 reg;
 
-	reg = readl(&regs->ctrl);
+	reg = flexcan_read(&regs->ctrl);
 	reg &= ~(FLEXCAN_CTRL_PRESDIV(0xff) |
 		 FLEXCAN_CTRL_RJW(0x3) |
 		 FLEXCAN_CTRL_PSEG1(0x7) |
@@ -625,11 +649,11 @@
 		reg |= FLEXCAN_CTRL_SMP;
 
 	dev_info(dev->dev.parent, "writing ctrl=0x%08x\n", reg);
-	writel(reg, &regs->ctrl);
+	flexcan_write(reg, &regs->ctrl);
 
 	/* print chip status */
 	dev_dbg(dev->dev.parent, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__,
-		readl(&regs->mcr), readl(&regs->ctrl));
+		flexcan_read(&regs->mcr), flexcan_read(&regs->ctrl));
 }
 
 /*
@@ -650,10 +674,10 @@
 	flexcan_chip_enable(priv);
 
 	/* soft reset */
-	writel(FLEXCAN_MCR_SOFTRST, &regs->mcr);
+	flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
 	udelay(10);
 
-	reg_mcr = readl(&regs->mcr);
+	reg_mcr = flexcan_read(&regs->mcr);
 	if (reg_mcr & FLEXCAN_MCR_SOFTRST) {
 		dev_err(dev->dev.parent,
 			"Failed to softreset can module (mcr=0x%08x)\n",
@@ -675,12 +699,12 @@
 	 * choose format C
 	 *
 	 */
-	reg_mcr = readl(&regs->mcr);
+	reg_mcr = flexcan_read(&regs->mcr);
 	reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
 		FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN |
 		FLEXCAN_MCR_IDAM_C;
 	dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr);
-	writel(reg_mcr, &regs->mcr);
+	flexcan_write(reg_mcr, &regs->mcr);
 
 	/*
 	 * CTRL
@@ -698,7 +722,7 @@
 	 * (FLEXCAN_CTRL_ERR_MSK), too. Otherwise we don't get any
 	 * warning or bus passive interrupts.
 	 */
-	reg_ctrl = readl(&regs->ctrl);
+	reg_ctrl = flexcan_read(&regs->ctrl);
 	reg_ctrl &= ~FLEXCAN_CTRL_TSYN;
 	reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF |
 		FLEXCAN_CTRL_ERR_STATE | FLEXCAN_CTRL_ERR_MSK;
@@ -706,38 +730,39 @@
 	/* save for later use */
 	priv->reg_ctrl_default = reg_ctrl;
 	dev_dbg(dev->dev.parent, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
-	writel(reg_ctrl, &regs->ctrl);
+	flexcan_write(reg_ctrl, &regs->ctrl);
 
 	for (i = 0; i < ARRAY_SIZE(regs->cantxfg); i++) {
-		writel(0, &regs->cantxfg[i].can_ctrl);
-		writel(0, &regs->cantxfg[i].can_id);
-		writel(0, &regs->cantxfg[i].data[0]);
-		writel(0, &regs->cantxfg[i].data[1]);
+		flexcan_write(0, &regs->cantxfg[i].can_ctrl);
+		flexcan_write(0, &regs->cantxfg[i].can_id);
+		flexcan_write(0, &regs->cantxfg[i].data[0]);
+		flexcan_write(0, &regs->cantxfg[i].data[1]);
 
 		/* put MB into rx queue */
-		writel(FLEXCAN_MB_CNT_CODE(0x4), &regs->cantxfg[i].can_ctrl);
+		flexcan_write(FLEXCAN_MB_CNT_CODE(0x4),
+			&regs->cantxfg[i].can_ctrl);
 	}
 
 	/* acceptance mask/acceptance code (accept everything) */
-	writel(0x0, &regs->rxgmask);
-	writel(0x0, &regs->rx14mask);
-	writel(0x0, &regs->rx15mask);
+	flexcan_write(0x0, &regs->rxgmask);
+	flexcan_write(0x0, &regs->rx14mask);
+	flexcan_write(0x0, &regs->rx15mask);
 
 	flexcan_transceiver_switch(priv, 1);
 
 	/* synchronize with the can bus */
-	reg_mcr = readl(&regs->mcr);
+	reg_mcr = flexcan_read(&regs->mcr);
 	reg_mcr &= ~FLEXCAN_MCR_HALT;
-	writel(reg_mcr, &regs->mcr);
+	flexcan_write(reg_mcr, &regs->mcr);
 
 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
 	/* enable FIFO interrupts */
-	writel(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
+	flexcan_write(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
 
 	/* print chip status */
 	dev_dbg(dev->dev.parent, "%s: reading mcr=0x%08x ctrl=0x%08x\n",
-		__func__, readl(&regs->mcr), readl(&regs->ctrl));
+		__func__, flexcan_read(&regs->mcr), flexcan_read(&regs->ctrl));
 
 	return 0;
 
@@ -759,12 +784,12 @@
 	u32 reg;
 
 	/* Disable all interrupts */
-	writel(0, &regs->imask1);
+	flexcan_write(0, &regs->imask1);
 
 	/* Disable + halt module */
-	reg = readl(&regs->mcr);
+	reg = flexcan_read(&regs->mcr);
 	reg |= FLEXCAN_MCR_MDIS | FLEXCAN_MCR_HALT;
-	writel(reg, &regs->mcr);
+	flexcan_write(reg, &regs->mcr);
 
 	flexcan_transceiver_switch(priv, 0);
 	priv->can.state = CAN_STATE_STOPPED;
@@ -856,24 +881,24 @@
 
 	/* select "bus clock", chip must be disabled */
 	flexcan_chip_disable(priv);
-	reg = readl(&regs->ctrl);
+	reg = flexcan_read(&regs->ctrl);
 	reg |= FLEXCAN_CTRL_CLK_SRC;
-	writel(reg, &regs->ctrl);
+	flexcan_write(reg, &regs->ctrl);
 
 	flexcan_chip_enable(priv);
 
 	/* set freeze, halt and activate FIFO, restrict register access */
-	reg = readl(&regs->mcr);
+	reg = flexcan_read(&regs->mcr);
 	reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT |
 		FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV;
-	writel(reg, &regs->mcr);
+	flexcan_write(reg, &regs->mcr);
 
 	/*
 	 * Currently we only support newer versions of this core
 	 * featuring a RX FIFO. Older cores found on some Coldfire
 	 * derivates are not yet supported.
 	 */
-	reg = readl(&regs->mcr);
+	reg = flexcan_read(&regs->mcr);
 	if (!(reg & FLEXCAN_MCR_FEN)) {
 		dev_err(dev->dev.parent,
 			"Could not enable RX FIFO, unsupported core\n");
@@ -901,16 +926,29 @@
 	struct net_device *dev;
 	struct flexcan_priv *priv;
 	struct resource *mem;
-	struct clk *clk;
+	struct clk *clk = NULL;
 	void __iomem *base;
 	resource_size_t mem_size;
 	int err, irq;
+	u32 clock_freq = 0;
 
-	clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(clk)) {
-		dev_err(&pdev->dev, "no clock defined\n");
-		err = PTR_ERR(clk);
-		goto failed_clock;
+	if (pdev->dev.of_node) {
+		const u32 *clock_freq_p;
+
+		clock_freq_p = of_get_property(pdev->dev.of_node,
+						"clock-frequency", NULL);
+		if (clock_freq_p)
+			clock_freq = *clock_freq_p;
+	}
+
+	if (!clock_freq) {
+		clk = clk_get(&pdev->dev, NULL);
+		if (IS_ERR(clk)) {
+			dev_err(&pdev->dev, "no clock defined\n");
+			err = PTR_ERR(clk);
+			goto failed_clock;
+		}
+		clock_freq = clk_get_rate(clk);
 	}
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -943,7 +981,7 @@
 	dev->flags |= IFF_ECHO; /* we support local echo in hardware */
 
 	priv = netdev_priv(dev);
-	priv->can.clock.freq = clk_get_rate(clk);
+	priv->can.clock.freq = clock_freq;
 	priv->can.bittiming_const = &flexcan_bittiming_const;
 	priv->can.do_set_mode = flexcan_set_mode;
 	priv->can.do_get_berr_counter = flexcan_get_berr_counter;
@@ -978,7 +1016,8 @@
  failed_map:
 	release_mem_region(mem->start, mem_size);
  failed_get:
-	clk_put(clk);
+	if (clk)
+		clk_put(clk);
  failed_clock:
 	return err;
 }
@@ -996,15 +1035,27 @@
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	release_mem_region(mem->start, resource_size(mem));
 
-	clk_put(priv->clk);
+	if (priv->clk)
+		clk_put(priv->clk);
 
 	free_candev(dev);
 
 	return 0;
 }
 
+static struct of_device_id flexcan_of_match[] = {
+	{
+		.compatible = "fsl,p1010-flexcan",
+	},
+	{},
+};
+
 static struct platform_driver flexcan_driver = {
-	.driver.name = DRV_NAME,
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = flexcan_of_match,
+	},
 	.probe = flexcan_probe,
 	.remove = __devexit_p(flexcan_remove),
 };
diff -druN linux-libre-3.1-gnu/drivers/net/can/mscan/mscan.c linux-libre-3.2-gnu/drivers/net/can/mscan/mscan.c
--- linux-libre-3.1-gnu/drivers/net/can/mscan/mscan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/can/mscan/mscan.c	2012-01-04 18:55:44.000000000 -0500
@@ -62,7 +62,7 @@
 static int mscan_set_mode(struct net_device *dev, u8 mode)
 {
 	struct mscan_priv *priv = netdev_priv(dev);
-	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+	struct mscan_regs __iomem *regs = priv->reg_base;
 	int ret = 0;
 	int i;
 	u8 canctl1;
@@ -138,7 +138,7 @@
 static int mscan_start(struct net_device *dev)
 {
 	struct mscan_priv *priv = netdev_priv(dev);
-	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+	struct mscan_regs __iomem *regs = priv->reg_base;
 	u8 canrflg;
 	int err;
 
@@ -178,7 +178,7 @@
 	struct mscan_priv *priv = netdev_priv(dev);
 
 	if (priv->type == MSCAN_TYPE_MPC5121) {
-		struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+		struct mscan_regs __iomem *regs = priv->reg_base;
 
 		priv->can.state = CAN_STATE_ERROR_ACTIVE;
 		WARN(!(in_8(&regs->canmisc) & MSCAN_BOHOLD),
@@ -199,7 +199,7 @@
 {
 	struct can_frame *frame = (struct can_frame *)skb->data;
 	struct mscan_priv *priv = netdev_priv(dev);
-	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+	struct mscan_regs __iomem *regs = priv->reg_base;
 	int i, rtr, buf_id;
 	u32 can_id;
 
@@ -307,7 +307,7 @@
 static void mscan_get_rx_frame(struct net_device *dev, struct can_frame *frame)
 {
 	struct mscan_priv *priv = netdev_priv(dev);
-	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+	struct mscan_regs __iomem *regs = priv->reg_base;
 	u32 can_id;
 	int i;
 
@@ -348,7 +348,7 @@
 				u8 canrflg)
 {
 	struct mscan_priv *priv = netdev_priv(dev);
-	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+	struct mscan_regs __iomem *regs = priv->reg_base;
 	struct net_device_stats *stats = &dev->stats;
 	enum can_state old_state;
 
@@ -411,7 +411,7 @@
 {
 	struct mscan_priv *priv = container_of(napi, struct mscan_priv, napi);
 	struct net_device *dev = napi->dev;
-	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+	struct mscan_regs __iomem *regs = priv->reg_base;
 	struct net_device_stats *stats = &dev->stats;
 	int npackets = 0;
 	int ret = 1;
@@ -458,7 +458,7 @@
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct mscan_priv *priv = netdev_priv(dev);
-	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+	struct mscan_regs __iomem *regs = priv->reg_base;
 	struct net_device_stats *stats = &dev->stats;
 	u8 cantier, cantflg, canrflg;
 	irqreturn_t ret = IRQ_NONE;
@@ -542,7 +542,7 @@
 static int mscan_do_set_bittiming(struct net_device *dev)
 {
 	struct mscan_priv *priv = netdev_priv(dev);
-	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+	struct mscan_regs __iomem *regs = priv->reg_base;
 	struct can_bittiming *bt = &priv->can.bittiming;
 	u8 btr0, btr1;
 
@@ -564,7 +564,7 @@
 {
 	int ret;
 	struct mscan_priv *priv = netdev_priv(dev);
-	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+	struct mscan_regs __iomem *regs = priv->reg_base;
 
 	/* common open */
 	ret = open_candev(dev);
@@ -603,7 +603,7 @@
 static int mscan_close(struct net_device *dev)
 {
 	struct mscan_priv *priv = netdev_priv(dev);
-	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+	struct mscan_regs __iomem *regs = priv->reg_base;
 
 	netif_stop_queue(dev);
 	napi_disable(&priv->napi);
@@ -627,7 +627,7 @@
 int register_mscandev(struct net_device *dev, int mscan_clksrc)
 {
 	struct mscan_priv *priv = netdev_priv(dev);
-	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+	struct mscan_regs __iomem *regs = priv->reg_base;
 	u8 ctl1;
 
 	ctl1 = in_8(&regs->canctl1);
@@ -664,7 +664,7 @@
 void unregister_mscandev(struct net_device *dev)
 {
 	struct mscan_priv *priv = netdev_priv(dev);
-	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+	struct mscan_regs __iomem *regs = priv->reg_base;
 	mscan_set_mode(dev, MSCAN_INIT_MODE);
 	clrbits8(&regs->canctl1, MSCAN_CANE);
 	unregister_candev(dev);
diff -druN linux-libre-3.1-gnu/drivers/net/can/sja1000/ems_pcmcia.c linux-libre-3.2-gnu/drivers/net/can/sja1000/ems_pcmcia.c
--- linux-libre-3.1-gnu/drivers/net/can/sja1000/ems_pcmcia.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/can/sja1000/ems_pcmcia.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2008 Sebastian Haas (initial chardev implementation)
+ * Copyright (C) 2010 Markus Plessing <plessing@ems-wuensche.com>
+ * Rework for mainline by Oliver Hartkopp <socketcan@hartkopp.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include "sja1000.h"
+
+#define DRV_NAME "ems_pcmcia"
+
+MODULE_AUTHOR("Markus Plessing <plessing@ems-wuensche.com>");
+MODULE_DESCRIPTION("Socket-CAN driver for EMS CPC-CARD cards");
+MODULE_SUPPORTED_DEVICE("EMS CPC-CARD CAN card");
+MODULE_LICENSE("GPL v2");
+
+#define EMS_PCMCIA_MAX_CHAN 2
+
+struct ems_pcmcia_card {
+	int channels;
+	struct pcmcia_device *pcmcia_dev;
+	struct net_device *net_dev[EMS_PCMCIA_MAX_CHAN];
+	void __iomem *base_addr;
+};
+
+#define EMS_PCMCIA_CAN_CLOCK (16000000 / 2)
+
+/*
+ * The board configuration is probably following:
+ * RX1 is connected to ground.
+ * TX1 is not connected.
+ * CLKO is not connected.
+ * Setting the OCR register to 0xDA is a good idea.
+ * This means  normal output mode , push-pull and the correct polarity.
+ */
+#define EMS_PCMCIA_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
+
+/*
+ * In the CDR register, you should set CBP to 1.
+ * You will probably also want to set the clock divider value to 7
+ * (meaning direct oscillator output) because the second SJA1000 chip
+ * is driven by the first one CLKOUT output.
+ */
+#define EMS_PCMCIA_CDR (CDR_CBP | CDR_CLKOUT_MASK)
+#define EMS_PCMCIA_MEM_SIZE 4096 /* Size of the remapped io-memory */
+#define EMS_PCMCIA_CAN_BASE_OFFSET 0x100 /* Offset where controllers starts */
+#define EMS_PCMCIA_CAN_CTRL_SIZE 0x80 /* Memory size for each controller */
+
+#define EMS_CMD_RESET 0x00 /* Perform a reset of the card */
+#define EMS_CMD_MAP   0x03 /* Map CAN controllers into card' memory */
+#define EMS_CMD_UMAP  0x02 /* Unmap CAN controllers from card' memory */
+
+static struct pcmcia_device_id ems_pcmcia_tbl[] = {
+	PCMCIA_DEVICE_PROD_ID123("EMS_T_W", "CPC-Card", "V2.0", 0xeab1ea23,
+				 0xa338573f, 0xe4575800),
+	PCMCIA_DEVICE_NULL,
+};
+
+MODULE_DEVICE_TABLE(pcmcia, ems_pcmcia_tbl);
+
+static u8 ems_pcmcia_read_reg(const struct sja1000_priv *priv, int port)
+{
+	return readb(priv->reg_base + port);
+}
+
+static void ems_pcmcia_write_reg(const struct sja1000_priv *priv, int port,
+				 u8 val)
+{
+	writeb(val, priv->reg_base + port);
+}
+
+static irqreturn_t ems_pcmcia_interrupt(int irq, void *dev_id)
+{
+	struct ems_pcmcia_card *card = dev_id;
+	struct net_device *dev;
+	irqreturn_t retval = IRQ_NONE;
+	int i, again;
+
+	/* Card not present */
+	if (readw(card->base_addr) != 0xAA55)
+		return IRQ_HANDLED;
+
+	do {
+		again = 0;
+
+		/* Check interrupt for each channel */
+		for (i = 0; i < card->channels; i++) {
+			dev = card->net_dev[i];
+			if (!dev)
+				continue;
+
+			if (sja1000_interrupt(irq, dev) == IRQ_HANDLED)
+				again = 1;
+		}
+		/* At least one channel handled the interrupt */
+		if (again)
+			retval = IRQ_HANDLED;
+
+	} while (again);
+
+	return retval;
+}
+
+/*
+ * Check if a CAN controller is present at the specified location
+ * by trying to set 'em into the PeliCAN mode
+ */
+static inline int ems_pcmcia_check_chan(struct sja1000_priv *priv)
+{
+	/* Make sure SJA1000 is in reset mode */
+	ems_pcmcia_write_reg(priv, REG_MOD, 1);
+	ems_pcmcia_write_reg(priv, REG_CDR, CDR_PELICAN);
+
+	/* read reset-values */
+	if (ems_pcmcia_read_reg(priv, REG_CDR) == CDR_PELICAN)
+		return 1;
+
+	return 0;
+}
+
+static void ems_pcmcia_del_card(struct pcmcia_device *pdev)
+{
+	struct ems_pcmcia_card *card = pdev->priv;
+	struct net_device *dev;
+	int i;
+
+	free_irq(pdev->irq, card);
+
+	for (i = 0; i < card->channels; i++) {
+		dev = card->net_dev[i];
+		if (!dev)
+			continue;
+
+		printk(KERN_INFO "%s: removing %s on channel #%d\n",
+		       DRV_NAME, dev->name, i);
+		unregister_sja1000dev(dev);
+		free_sja1000dev(dev);
+	}
+
+	writeb(EMS_CMD_UMAP, card->base_addr);
+	iounmap(card->base_addr);
+	kfree(card);
+
+	pdev->priv = NULL;
+}
+
+/*
+ * Probe PCI device for EMS CAN signature and register each available
+ * CAN channel to SJA1000 Socket-CAN subsystem.
+ */
+static int __devinit ems_pcmcia_add_card(struct pcmcia_device *pdev,
+					 unsigned long base)
+{
+	struct sja1000_priv *priv;
+	struct net_device *dev;
+	struct ems_pcmcia_card *card;
+	int err, i;
+
+	/* Allocating card structures to hold addresses, ... */
+	card = kzalloc(sizeof(struct ems_pcmcia_card), GFP_KERNEL);
+	if (!card)
+		return -ENOMEM;
+
+	pdev->priv = card;
+	card->channels = 0;
+
+	card->base_addr = ioremap(base, EMS_PCMCIA_MEM_SIZE);
+	if (!card->base_addr) {
+		err = -ENOMEM;
+		goto failure_cleanup;
+	}
+
+	/* Check for unique EMS CAN signature */
+	if (readw(card->base_addr) != 0xAA55) {
+		err = -ENODEV;
+		goto failure_cleanup;
+	}
+
+	/* Request board reset */
+	writeb(EMS_CMD_RESET, card->base_addr);
+
+	/* Make sure CAN controllers are mapped into card's memory space */
+	writeb(EMS_CMD_MAP, card->base_addr);
+
+	/* Detect available channels */
+	for (i = 0; i < EMS_PCMCIA_MAX_CHAN; i++) {
+		dev = alloc_sja1000dev(0);
+		if (!dev) {
+			err = -ENOMEM;
+			goto failure_cleanup;
+		}
+
+		card->net_dev[i] = dev;
+		priv = netdev_priv(dev);
+		priv->priv = card;
+		SET_NETDEV_DEV(dev, &pdev->dev);
+
+		priv->irq_flags = IRQF_SHARED;
+		dev->irq = pdev->irq;
+		priv->reg_base = card->base_addr + EMS_PCMCIA_CAN_BASE_OFFSET +
+			(i * EMS_PCMCIA_CAN_CTRL_SIZE);
+
+		/* Check if channel is present */
+		if (ems_pcmcia_check_chan(priv)) {
+			priv->read_reg  = ems_pcmcia_read_reg;
+			priv->write_reg = ems_pcmcia_write_reg;
+			priv->can.clock.freq = EMS_PCMCIA_CAN_CLOCK;
+			priv->ocr = EMS_PCMCIA_OCR;
+			priv->cdr = EMS_PCMCIA_CDR;
+			priv->flags |= SJA1000_CUSTOM_IRQ_HANDLER;
+
+			/* Register SJA1000 device */
+			err = register_sja1000dev(dev);
+			if (err) {
+				free_sja1000dev(dev);
+				goto failure_cleanup;
+			}
+
+			card->channels++;
+
+			printk(KERN_INFO "%s: registered %s on channel "
+			       "#%d at 0x%p, irq %d\n", DRV_NAME, dev->name,
+			       i, priv->reg_base, dev->irq);
+		} else
+			free_sja1000dev(dev);
+	}
+
+	err = request_irq(dev->irq, &ems_pcmcia_interrupt, IRQF_SHARED,
+			  DRV_NAME, card);
+	if (!err)
+		return 0;
+
+failure_cleanup:
+	ems_pcmcia_del_card(pdev);
+	return err;
+}
+
+/*
+ * Setup PCMCIA socket and probe for EMS CPC-CARD
+ */
+static int __devinit ems_pcmcia_probe(struct pcmcia_device *dev)
+{
+	int csval;
+
+	/* General socket configuration */
+	dev->config_flags |= CONF_ENABLE_IRQ;
+	dev->config_index = 1;
+	dev->config_regs = PRESENT_OPTION;
+
+	/* The io structure describes IO port mapping */
+	dev->resource[0]->end = 16;
+	dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	dev->resource[1]->end = 16;
+	dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
+	dev->io_lines = 5;
+
+	/* Allocate a memory window */
+	dev->resource[2]->flags =
+		(WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE);
+	dev->resource[2]->start = dev->resource[2]->end = 0;
+
+	csval = pcmcia_request_window(dev, dev->resource[2], 0);
+	if (csval) {
+		dev_err(&dev->dev, "pcmcia_request_window failed (err=%d)\n",
+			csval);
+		return 0;
+	}
+
+	csval = pcmcia_map_mem_page(dev, dev->resource[2], dev->config_base);
+	if (csval) {
+		dev_err(&dev->dev, "pcmcia_map_mem_page failed (err=%d)\n",
+			csval);
+		return 0;
+	}
+
+	csval = pcmcia_enable_device(dev);
+	if (csval) {
+		dev_err(&dev->dev, "pcmcia_enable_device failed (err=%d)\n",
+			csval);
+		return 0;
+	}
+
+	ems_pcmcia_add_card(dev, dev->resource[2]->start);
+	return 0;
+}
+
+/*
+ * Release claimed resources
+ */
+static void ems_pcmcia_remove(struct pcmcia_device *dev)
+{
+	ems_pcmcia_del_card(dev);
+	pcmcia_disable_device(dev);
+}
+
+static struct pcmcia_driver ems_pcmcia_driver = {
+	.name = DRV_NAME,
+	.probe = ems_pcmcia_probe,
+	.remove = ems_pcmcia_remove,
+	.id_table = ems_pcmcia_tbl,
+};
+
+static int __init ems_pcmcia_init(void)
+{
+	return pcmcia_register_driver(&ems_pcmcia_driver);
+}
+module_init(ems_pcmcia_init);
+
+static void __exit ems_pcmcia_exit(void)
+{
+	pcmcia_unregister_driver(&ems_pcmcia_driver);
+}
+module_exit(ems_pcmcia_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/can/sja1000/Kconfig linux-libre-3.2-gnu/drivers/net/can/sja1000/Kconfig
--- linux-libre-3.1-gnu/drivers/net/can/sja1000/Kconfig	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/can/sja1000/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -29,6 +29,13 @@
 	  OpenFirmware bindings, e.g. if you have a PowerPC based system
 	  you may want to enable this option.
 
+config CAN_EMS_PCMCIA
+	tristate "EMS CPC-CARD Card"
+	depends on PCMCIA
+	---help---
+	  This driver is for the one or two channel CPC-CARD cards from
+	  EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
+
 config CAN_EMS_PCI
 	tristate "EMS CPC-PCI, CPC-PCIe and CPC-104P Card"
 	depends on PCI
@@ -37,6 +44,13 @@
 	  CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche
 	  (http://www.ems-wuensche.de).
 
+config CAN_PEAK_PCI
+	tristate "PEAK PCAN PCI/PCIe Cards"
+	depends on PCI
+	---help---
+	  This driver is for the PCAN PCI/PCIe cards (1, 2, 3 or 4 channels)
+	  from PEAK Systems (http://www.peak-system.com).
+
 config CAN_KVASER_PCI
 	tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
 	depends on PCI
diff -druN linux-libre-3.1-gnu/drivers/net/can/sja1000/Makefile linux-libre-3.2-gnu/drivers/net/can/sja1000/Makefile
--- linux-libre-3.1-gnu/drivers/net/can/sja1000/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/can/sja1000/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -6,8 +6,10 @@
 obj-$(CONFIG_CAN_SJA1000_ISA) += sja1000_isa.o
 obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o
 obj-$(CONFIG_CAN_SJA1000_OF_PLATFORM) += sja1000_of_platform.o
+obj-$(CONFIG_CAN_EMS_PCMCIA) += ems_pcmcia.o
 obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o
 obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o
+obj-$(CONFIG_CAN_PEAK_PCI) += peak_pci.o
 obj-$(CONFIG_CAN_PLX_PCI) += plx_pci.o
 obj-$(CONFIG_CAN_TSCAN1) += tscan1.o
 
diff -druN linux-libre-3.1-gnu/drivers/net/can/sja1000/peak_pci.c linux-libre-3.2-gnu/drivers/net/can/sja1000/peak_pci.c
--- linux-libre-3.1-gnu/drivers/net/can/sja1000/peak_pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/can/sja1000/peak_pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2007, 2011 Wolfgang Grandegger <wg@grandegger.com>
+ *
+ * Derived from the PCAN project file driver/src/pcan_pci.c:
+ *
+ * Copyright (C) 2001-2006  PEAK System-Technik GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+
+#include "sja1000.h"
+
+MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
+MODULE_DESCRIPTION("Socket-CAN driver for PEAK PCAN PCI/PCIe cards");
+MODULE_SUPPORTED_DEVICE("PEAK PCAN PCI/PCIe CAN card");
+MODULE_LICENSE("GPL v2");
+
+#define DRV_NAME  "peak_pci"
+
+struct peak_pci_chan {
+	void __iomem *cfg_base;	     /* Common for all channels */
+	struct net_device *next_dev; /* Chain of network devices */
+	u16 icr_mask;		     /* Interrupt mask for fast ack */
+};
+
+#define PEAK_PCI_CAN_CLOCK	(16000000 / 2)
+
+#define PEAK_PCI_CDR		(CDR_CBP | CDR_CLKOUT_MASK)
+#define PEAK_PCI_OCR		OCR_TX0_PUSHPULL
+
+/*
+ * Important PITA registers
+ */
+#define PITA_ICR		0x00	/* Interrupt control register */
+#define PITA_GPIOICR		0x18	/* GPIO interface control register */
+#define PITA_MISC		0x1C	/* Miscellaneous register */
+
+#define PEAK_PCI_CFG_SIZE	0x1000	/* Size of the config PCI bar */
+#define PEAK_PCI_CHAN_SIZE	0x0400	/* Size used by the channel */
+
+#define PEAK_PCI_VENDOR_ID	0x001C	/* The PCI device and vendor IDs */
+#define PEAK_PCI_DEVICE_ID	0x0001	/* for PCI/PCIe slot cards */
+
+static const u16 peak_pci_icr_masks[] = {0x02, 0x01, 0x40, 0x80};
+
+static DEFINE_PCI_DEVICE_TABLE(peak_pci_tbl) = {
+	{PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, peak_pci_tbl);
+
+static u8 peak_pci_read_reg(const struct sja1000_priv *priv, int port)
+{
+	return readb(priv->reg_base + (port << 2));
+}
+
+static void peak_pci_write_reg(const struct sja1000_priv *priv,
+			       int port, u8 val)
+{
+	writeb(val, priv->reg_base + (port << 2));
+}
+
+static void peak_pci_post_irq(const struct sja1000_priv *priv)
+{
+	struct peak_pci_chan *chan = priv->priv;
+	u16 icr;
+
+	/* Select and clear in PITA stored interrupt */
+	icr = readw(chan->cfg_base + PITA_ICR);
+	if (icr & chan->icr_mask)
+		writew(chan->icr_mask, chan->cfg_base + PITA_ICR);
+}
+
+static int __devinit peak_pci_probe(struct pci_dev *pdev,
+				    const struct pci_device_id *ent)
+{
+	struct sja1000_priv *priv;
+	struct peak_pci_chan *chan;
+	struct net_device *dev, *dev0 = NULL;
+	void __iomem *cfg_base, *reg_base;
+	u16 sub_sys_id, icr;
+	int i, err, channels;
+
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+
+	err = pci_request_regions(pdev, DRV_NAME);
+	if (err)
+		goto failure_disable_pci;
+
+	err = pci_read_config_word(pdev, 0x2e, &sub_sys_id);
+	if (err)
+		goto failure_release_regions;
+
+	dev_dbg(&pdev->dev, "probing device %04x:%04x:%04x\n",
+		pdev->vendor, pdev->device, sub_sys_id);
+
+	err = pci_write_config_word(pdev, 0x44, 0);
+	if (err)
+		goto failure_release_regions;
+
+	if (sub_sys_id >= 12)
+		channels = 4;
+	else if (sub_sys_id >= 10)
+		channels = 3;
+	else if (sub_sys_id >= 4)
+		channels = 2;
+	else
+		channels = 1;
+
+	cfg_base = pci_iomap(pdev, 0, PEAK_PCI_CFG_SIZE);
+	if (!cfg_base) {
+		dev_err(&pdev->dev, "failed to map PCI resource #0\n");
+		goto failure_release_regions;
+	}
+
+	reg_base = pci_iomap(pdev, 1, PEAK_PCI_CHAN_SIZE * channels);
+	if (!reg_base) {
+		dev_err(&pdev->dev, "failed to map PCI resource #1\n");
+		goto failure_unmap_cfg_base;
+	}
+
+	/* Set GPIO control register */
+	writew(0x0005, cfg_base + PITA_GPIOICR + 2);
+	/* Enable all channels of this card */
+	writeb(0x00, cfg_base + PITA_GPIOICR);
+	/* Toggle reset */
+	writeb(0x05, cfg_base + PITA_MISC + 3);
+	mdelay(5);
+	/* Leave parport mux mode */
+	writeb(0x04, cfg_base + PITA_MISC + 3);
+
+	icr = readw(cfg_base + PITA_ICR + 2);
+
+	for (i = 0; i < channels; i++) {
+		dev = alloc_sja1000dev(sizeof(struct peak_pci_chan));
+		if (!dev) {
+			err = -ENOMEM;
+			goto failure_remove_channels;
+		}
+
+		priv = netdev_priv(dev);
+		chan = priv->priv;
+
+		chan->cfg_base = cfg_base;
+		priv->reg_base = reg_base + i * PEAK_PCI_CHAN_SIZE;
+
+		priv->read_reg = peak_pci_read_reg;
+		priv->write_reg = peak_pci_write_reg;
+		priv->post_irq = peak_pci_post_irq;
+
+		priv->can.clock.freq = PEAK_PCI_CAN_CLOCK;
+		priv->ocr = PEAK_PCI_OCR;
+		priv->cdr = PEAK_PCI_CDR;
+		/* Neither a slave nor a single device distributes the clock */
+		if (channels == 1 || i > 0)
+			priv->cdr |= CDR_CLK_OFF;
+
+		/* Setup interrupt handling */
+		priv->irq_flags = IRQF_SHARED;
+		dev->irq = pdev->irq;
+
+		chan->icr_mask = peak_pci_icr_masks[i];
+		icr |= chan->icr_mask;
+
+		SET_NETDEV_DEV(dev, &pdev->dev);
+
+		err = register_sja1000dev(dev);
+		if (err) {
+			dev_err(&pdev->dev, "failed to register device\n");
+			free_sja1000dev(dev);
+			goto failure_remove_channels;
+		}
+
+		/* Create chain of SJA1000 devices */
+		if (i == 0)
+			dev0 = dev;
+		else
+			chan->next_dev = dev;
+
+		dev_info(&pdev->dev,
+			 "%s at reg_base=0x%p cfg_base=0x%p irq=%d\n",
+			 dev->name, priv->reg_base, chan->cfg_base, dev->irq);
+	}
+
+	pci_set_drvdata(pdev, dev0);
+
+	/* Enable interrupts */
+	writew(icr, cfg_base + PITA_ICR + 2);
+
+	return 0;
+
+failure_remove_channels:
+	/* Disable interrupts */
+	writew(0x0, cfg_base + PITA_ICR + 2);
+
+	for (dev = dev0; dev; dev = chan->next_dev) {
+		unregister_sja1000dev(dev);
+		free_sja1000dev(dev);
+		priv = netdev_priv(dev);
+		chan = priv->priv;
+		dev = chan->next_dev;
+	}
+
+	pci_iounmap(pdev, reg_base);
+
+failure_unmap_cfg_base:
+	pci_iounmap(pdev, cfg_base);
+
+failure_release_regions:
+	pci_release_regions(pdev);
+
+failure_disable_pci:
+	pci_disable_device(pdev);
+
+	return err;
+}
+
+static void __devexit peak_pci_remove(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev); /* First device */
+	struct sja1000_priv *priv = netdev_priv(dev);
+	struct peak_pci_chan *chan = priv->priv;
+	void __iomem *cfg_base = chan->cfg_base;
+	void __iomem *reg_base = priv->reg_base;
+
+	/* Disable interrupts */
+	writew(0x0, cfg_base + PITA_ICR + 2);
+
+	/* Loop over all registered devices */
+	while (1) {
+		dev_info(&pdev->dev, "removing device %s\n", dev->name);
+		unregister_sja1000dev(dev);
+		free_sja1000dev(dev);
+		dev = chan->next_dev;
+		if (!dev)
+			break;
+		priv = netdev_priv(dev);
+		chan = priv->priv;
+	}
+
+	pci_iounmap(pdev, reg_base);
+	pci_iounmap(pdev, cfg_base);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+
+	pci_set_drvdata(pdev, NULL);
+}
+
+static struct pci_driver peak_pci_driver = {
+	.name = DRV_NAME,
+	.id_table = peak_pci_tbl,
+	.probe = peak_pci_probe,
+	.remove = __devexit_p(peak_pci_remove),
+};
+
+static int __init peak_pci_init(void)
+{
+	return pci_register_driver(&peak_pci_driver);
+}
+module_init(peak_pci_init);
+
+static void __exit peak_pci_exit(void)
+{
+	pci_unregister_driver(&peak_pci_driver);
+}
+module_exit(peak_pci_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/can/sja1000/sja1000.c linux-libre-3.2-gnu/drivers/net/can/sja1000/sja1000.c
--- linux-libre-3.1-gnu/drivers/net/can/sja1000/sja1000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/can/sja1000/sja1000.c	2012-01-04 18:55:44.000000000 -0500
@@ -40,8 +40,6 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  * DAMAGE.
  *
- * Send feedback to <socketcan-users@lists.berlios.de>
- *
  */
 
 #include <linux/module.h>
diff -druN linux-libre-3.1-gnu/drivers/net/can/sja1000/sja1000.h linux-libre-3.2-gnu/drivers/net/can/sja1000/sja1000.h
--- linux-libre-3.1-gnu/drivers/net/can/sja1000/sja1000.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/can/sja1000/sja1000.h	2012-01-04 18:55:44.000000000 -0500
@@ -40,8 +40,6 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  * DAMAGE.
  *
- * Send feedback to <socketcan-users@lists.berlios.de>
- *
  */
 
 #ifndef SJA1000_DEV_H
diff -druN linux-libre-3.1-gnu/drivers/net/can/sja1000/sja1000_of_platform.c linux-libre-3.2-gnu/drivers/net/can/sja1000/sja1000_of_platform.c
--- linux-libre-3.1-gnu/drivers/net/can/sja1000/sja1000_of_platform.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/can/sja1000/sja1000_of_platform.c	2012-01-04 18:55:44.000000000 -0500
@@ -29,7 +29,7 @@
  *           nxp,external-clock-frequency = <16000000>;
  *   };
  *
- * See "Documentation/powerpc/dts-bindings/can/sja1000.txt" for further
+ * See "Documentation/devicetree/bindings/net/can/sja1000.txt" for further
  * information.
  */
 
diff -druN linux-libre-3.1-gnu/drivers/net/can/slcan.c linux-libre-3.2-gnu/drivers/net/can/slcan.c
--- linux-libre-3.1-gnu/drivers/net/can/slcan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/can/slcan.c	2012-01-04 18:55:44.000000000 -0500
@@ -35,8 +35,6 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  * DAMAGE.
  *
- * Send feedback to <socketcan-users@lists.berlios.de>
- *
  */
 
 #include <linux/module.h>
diff -druN linux-libre-3.1-gnu/drivers/net/can/vcan.c linux-libre-3.2-gnu/drivers/net/can/vcan.c
--- linux-libre-3.1-gnu/drivers/net/can/vcan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/can/vcan.c	2012-01-04 18:55:44.000000000 -0500
@@ -37,8 +37,6 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  * DAMAGE.
  *
- * Send feedback to <socketcan-users@lists.berlios.de>
- *
  */
 
 #include <linux/module.h>
diff -druN linux-libre-3.1-gnu/drivers/net/cassini.c linux-libre-3.2-gnu/drivers/net/cassini.c
--- linux-libre-3.1-gnu/drivers/net/cassini.c	2012-03-19 21:43:43.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cassini.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,5304 +0,0 @@
-/* cassini.c: Sun Microsystems Cassini(+) ethernet driver.
- *
- * Copyright (C) 2004 Sun Microsystems Inc.
- * Copyright (C) 2003 Adrian Sun (asun@darksunrising.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 uses the sungem driver (c) David Miller
- * (davem@redhat.com) as its basis.
- *
- * The cassini chip has a number of features that distinguish it from
- * the gem chip:
- *  4 transmit descriptor rings that are used for either QoS (VLAN) or
- *      load balancing (non-VLAN mode)
- *  batching of multiple packets
- *  multiple CPU dispatching
- *  page-based RX descriptor engine with separate completion rings
- *  Gigabit support (GMII and PCS interface)
- *  MIF link up/down detection works
- *
- * RX is handled by page sized buffers that are attached as fragments to
- * the skb. here's what's done:
- *  -- driver allocates pages at a time and keeps reference counts
- *     on them.
- *  -- the upper protocol layers assume that the header is in the skb
- *     itself. as a result, cassini will copy a small amount (64 bytes)
- *     to make them happy.
- *  -- driver appends the rest of the data pages as frags to skbuffs
- *     and increments the reference count
- *  -- on page reclamation, the driver swaps the page with a spare page.
- *     if that page is still in use, it frees its reference to that page,
- *     and allocates a new page for use. otherwise, it just recycles the
- *     the page.
- *
- * NOTE: cassini can parse the header. however, it's not worth it
- *       as long as the network stack requires a header copy.
- *
- * 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 targeted to particular transmit rings.
- * alternatively, the queues can be configured via use of the all-purpose
- * ioctl.
- *
- * RX DATA: the rx completion ring has all the info, but the rx desc
- * ring has all of the data. RX can conceivably come in under multiple
- * interrupts, but the INT# assignment needs to be set up properly by
- * the BIOS and conveyed to the driver. PCI BIOSes don't know how to do
- * that. also, the two descriptor rings are designed to distinguish between
- * encrypted and non-encrypted packets, but we use them for buffering
- * instead.
- *
- * by default, the selective clear mask is set up to process rx packets.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/compiler.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/vmalloc.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/list.h>
-#include <linux/dma-mapping.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/ethtool.h>
-#include <linux/crc32.h>
-#include <linux/random.h>
-#include <linux/mii.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/mutex.h>
-#include <linux/firmware.h>
-
-#include <net/checksum.h>
-
-#include <linux/atomic.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-
-#define cas_page_map(x)      kmap_atomic((x), KM_SKB_DATA_SOFTIRQ)
-#define cas_page_unmap(x)    kunmap_atomic((x), KM_SKB_DATA_SOFTIRQ)
-#define CAS_NCPUS            num_online_cpus()
-
-#define cas_skb_release(x)  netif_rx(x)
-
-/* select which firmware to use */
-#define USE_HP_WORKAROUND
-#define HP_WORKAROUND_DEFAULT /* select which firmware to use as default */
-#define CAS_HP_ALT_FIRMWARE   cas_prog_null /* alternate firmware */
-
-#include "cassini.h"
-
-#define USE_TX_COMPWB      /* use completion writeback registers */
-#define USE_CSMA_CD_PROTO  /* standard CSMA/CD */
-#define USE_RX_BLANK       /* hw interrupt mitigation */
-#undef USE_ENTROPY_DEV     /* don't test for entropy device */
-
-/* NOTE: these aren't useable unless PCI interrupts can be assigned.
- * also, we need to make cp->lock finer-grained.
- */
-#undef  USE_PCI_INTB
-#undef  USE_PCI_INTC
-#undef  USE_PCI_INTD
-#undef  USE_QOS
-
-#undef  USE_VPD_DEBUG       /* debug vpd information if defined */
-
-/* rx processing options */
-#define USE_PAGE_ORDER      /* specify to allocate large rx pages */
-#define RX_DONT_BATCH  0    /* if 1, don't batch flows */
-#define RX_COPY_ALWAYS 0    /* if 0, use frags */
-#define RX_COPY_MIN    64   /* copy a little to make upper layers happy */
-#undef  RX_COUNT_BUFFERS    /* define to calculate RX buffer stats */
-
-#define DRV_MODULE_NAME		"cassini"
-#define DRV_MODULE_VERSION	"1.6"
-#define DRV_MODULE_RELDATE	"21 May 2008"
-
-#define CAS_DEF_MSG_ENABLE	  \
-	(NETIF_MSG_DRV		| \
-	 NETIF_MSG_PROBE	| \
-	 NETIF_MSG_LINK		| \
-	 NETIF_MSG_TIMER	| \
-	 NETIF_MSG_IFDOWN	| \
-	 NETIF_MSG_IFUP		| \
-	 NETIF_MSG_RX_ERR	| \
-	 NETIF_MSG_TX_ERR)
-
-/* length of time before we decide the hardware is borked,
- * and dev->tx_timeout() should be called to fix the problem
- */
-#define CAS_TX_TIMEOUT			(HZ)
-#define CAS_LINK_TIMEOUT                (22*HZ/10)
-#define CAS_LINK_FAST_TIMEOUT           (1)
-
-/* timeout values for state changing. these specify the number
- * of 10us delays to be used before giving up.
- */
-#define STOP_TRIES_PHY 1000
-#define STOP_TRIES     5000
-
-/* specify a minimum frame size to deal with some fifo issues
- * max mtu == 2 * page size - ethernet header - 64 - swivel =
- *            2 * page_size - 0x50
- */
-#define CAS_MIN_FRAME			97
-#define CAS_1000MB_MIN_FRAME            255
-#define CAS_MIN_MTU                     60
-#define CAS_MAX_MTU                     min(((cp->page_size << 1) - 0x50), 9000)
-
-#if 1
-/*
- * Eliminate these and use separate atomic counters for each, to
- * avoid a race condition.
- */
-#else
-#define CAS_RESET_MTU                   1
-#define CAS_RESET_ALL                   2
-#define CAS_RESET_SPARE                 3
-#endif
-
-static char version[] __devinitdata =
-	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
-
-static int cassini_debug = -1;	/* -1 == use CAS_DEF_MSG_ENABLE as value */
-static int link_mode;
-
-MODULE_AUTHOR("Adrian Sun (asun@darksunrising.com)");
-MODULE_DESCRIPTION("Sun Cassini(+) ethernet driver");
-MODULE_LICENSE("GPL");
-/*(DEBLOBBED)*/
-module_param(cassini_debug, int, 0);
-MODULE_PARM_DESC(cassini_debug, "Cassini bitmapped debugging message enable value");
-module_param(link_mode, int, 0);
-MODULE_PARM_DESC(link_mode, "default link mode");
-
-/*
- * Work around for a PCS bug in which the link goes down due to the chip
- * being confused and never showing a link status of "up."
- */
-#define DEFAULT_LINKDOWN_TIMEOUT 5
-/*
- * Value in seconds, for user input.
- */
-static int linkdown_timeout = DEFAULT_LINKDOWN_TIMEOUT;
-module_param(linkdown_timeout, int, 0);
-MODULE_PARM_DESC(linkdown_timeout,
-"min reset interval in sec. for PCS linkdown issue; disabled if not positive");
-
-/*
- * value in 'ticks' (units used by jiffies). Set when we init the
- * module because 'HZ' in actually a function call on some flavors of
- * Linux.  This will default to DEFAULT_LINKDOWN_TIMEOUT * HZ.
- */
-static int link_transition_timeout;
-
-
-
-static u16 link_modes[] __devinitdata = {
-	BMCR_ANENABLE,			 /* 0 : autoneg */
-	0,				 /* 1 : 10bt half duplex */
-	BMCR_SPEED100,			 /* 2 : 100bt half duplex */
-	BMCR_FULLDPLX,			 /* 3 : 10bt full duplex */
-	BMCR_SPEED100|BMCR_FULLDPLX,	 /* 4 : 100bt full duplex */
-	CAS_BMCR_SPEED1000|BMCR_FULLDPLX /* 5 : 1000bt full duplex */
-};
-
-static DEFINE_PCI_DEVICE_TABLE(cas_pci_tbl) = {
-	{ PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_CASSINI,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-	{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SATURN,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-	{ 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, cas_pci_tbl);
-
-static void cas_set_link_modes(struct cas *cp);
-
-static inline void cas_lock_tx(struct cas *cp)
-{
-	int i;
-
-	for (i = 0; i < N_TX_RINGS; i++)
-		spin_lock(&cp->tx_lock[i]);
-}
-
-static inline void cas_lock_all(struct cas *cp)
-{
-	spin_lock_irq(&cp->lock);
-	cas_lock_tx(cp);
-}
-
-/* WTZ: QA was finding deadlock problems with the previous
- * versions after long test runs with multiple cards per machine.
- * See if replacing cas_lock_all with safer versions helps. The
- * symptoms QA is reporting match those we'd expect if interrupts
- * aren't being properly restored, and we fixed a previous deadlock
- * with similar symptoms by using save/restore versions in other
- * places.
- */
-#define cas_lock_all_save(cp, flags) \
-do { \
-	struct cas *xxxcp = (cp); \
-	spin_lock_irqsave(&xxxcp->lock, flags); \
-	cas_lock_tx(xxxcp); \
-} while (0)
-
-static inline void cas_unlock_tx(struct cas *cp)
-{
-	int i;
-
-	for (i = N_TX_RINGS; i > 0; i--)
-		spin_unlock(&cp->tx_lock[i - 1]);
-}
-
-static inline void cas_unlock_all(struct cas *cp)
-{
-	cas_unlock_tx(cp);
-	spin_unlock_irq(&cp->lock);
-}
-
-#define cas_unlock_all_restore(cp, flags) \
-do { \
-	struct cas *xxxcp = (cp); \
-	cas_unlock_tx(xxxcp); \
-	spin_unlock_irqrestore(&xxxcp->lock, flags); \
-} while (0)
-
-static void cas_disable_irq(struct cas *cp, const int ring)
-{
-	/* Make sure we won't get any more interrupts */
-	if (ring == 0) {
-		writel(0xFFFFFFFF, cp->regs + REG_INTR_MASK);
-		return;
-	}
-
-	/* disable completion interrupts and selectively mask */
-	if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
-		switch (ring) {
-#if defined (USE_PCI_INTB) || defined(USE_PCI_INTC) || defined(USE_PCI_INTD)
-#ifdef USE_PCI_INTB
-		case 1:
-#endif
-#ifdef USE_PCI_INTC
-		case 2:
-#endif
-#ifdef USE_PCI_INTD
-		case 3:
-#endif
-			writel(INTRN_MASK_CLEAR_ALL | INTRN_MASK_RX_EN,
-			       cp->regs + REG_PLUS_INTRN_MASK(ring));
-			break;
-#endif
-		default:
-			writel(INTRN_MASK_CLEAR_ALL, cp->regs +
-			       REG_PLUS_INTRN_MASK(ring));
-			break;
-		}
-	}
-}
-
-static inline void cas_mask_intr(struct cas *cp)
-{
-	int i;
-
-	for (i = 0; i < N_RX_COMP_RINGS; i++)
-		cas_disable_irq(cp, i);
-}
-
-static void cas_enable_irq(struct cas *cp, const int ring)
-{
-	if (ring == 0) { /* all but TX_DONE */
-		writel(INTR_TX_DONE, cp->regs + REG_INTR_MASK);
-		return;
-	}
-
-	if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
-		switch (ring) {
-#if defined (USE_PCI_INTB) || defined(USE_PCI_INTC) || defined(USE_PCI_INTD)
-#ifdef USE_PCI_INTB
-		case 1:
-#endif
-#ifdef USE_PCI_INTC
-		case 2:
-#endif
-#ifdef USE_PCI_INTD
-		case 3:
-#endif
-			writel(INTRN_MASK_RX_EN, cp->regs +
-			       REG_PLUS_INTRN_MASK(ring));
-			break;
-#endif
-		default:
-			break;
-		}
-	}
-}
-
-static inline void cas_unmask_intr(struct cas *cp)
-{
-	int i;
-
-	for (i = 0; i < N_RX_COMP_RINGS; i++)
-		cas_enable_irq(cp, i);
-}
-
-static inline void cas_entropy_gather(struct cas *cp)
-{
-#ifdef USE_ENTROPY_DEV
-	if ((cp->cas_flags & CAS_FLAG_ENTROPY_DEV) == 0)
-		return;
-
-	batch_entropy_store(readl(cp->regs + REG_ENTROPY_IV),
-			    readl(cp->regs + REG_ENTROPY_IV),
-			    sizeof(uint64_t)*8);
-#endif
-}
-
-static inline void cas_entropy_reset(struct cas *cp)
-{
-#ifdef USE_ENTROPY_DEV
-	if ((cp->cas_flags & CAS_FLAG_ENTROPY_DEV) == 0)
-		return;
-
-	writel(BIM_LOCAL_DEV_PAD | BIM_LOCAL_DEV_PROM | BIM_LOCAL_DEV_EXT,
-	       cp->regs + REG_BIM_LOCAL_DEV_EN);
-	writeb(ENTROPY_RESET_STC_MODE, cp->regs + REG_ENTROPY_RESET);
-	writeb(0x55, cp->regs + REG_ENTROPY_RAND_REG);
-
-	/* if we read back 0x0, we don't have an entropy device */
-	if (readb(cp->regs + REG_ENTROPY_RAND_REG) == 0)
-		cp->cas_flags &= ~CAS_FLAG_ENTROPY_DEV;
-#endif
-}
-
-/* access to the phy. the following assumes that we've initialized the MIF to
- * be in frame rather than bit-bang mode
- */
-static u16 cas_phy_read(struct cas *cp, int reg)
-{
-	u32 cmd;
-	int limit = STOP_TRIES_PHY;
-
-	cmd = MIF_FRAME_ST | MIF_FRAME_OP_READ;
-	cmd |= CAS_BASE(MIF_FRAME_PHY_ADDR, cp->phy_addr);
-	cmd |= CAS_BASE(MIF_FRAME_REG_ADDR, reg);
-	cmd |= MIF_FRAME_TURN_AROUND_MSB;
-	writel(cmd, cp->regs + REG_MIF_FRAME);
-
-	/* poll for completion */
-	while (limit-- > 0) {
-		udelay(10);
-		cmd = readl(cp->regs + REG_MIF_FRAME);
-		if (cmd & MIF_FRAME_TURN_AROUND_LSB)
-			return cmd & MIF_FRAME_DATA_MASK;
-	}
-	return 0xFFFF; /* -1 */
-}
-
-static int cas_phy_write(struct cas *cp, int reg, u16 val)
-{
-	int limit = STOP_TRIES_PHY;
-	u32 cmd;
-
-	cmd = MIF_FRAME_ST | MIF_FRAME_OP_WRITE;
-	cmd |= CAS_BASE(MIF_FRAME_PHY_ADDR, cp->phy_addr);
-	cmd |= CAS_BASE(MIF_FRAME_REG_ADDR, reg);
-	cmd |= MIF_FRAME_TURN_AROUND_MSB;
-	cmd |= val & MIF_FRAME_DATA_MASK;
-	writel(cmd, cp->regs + REG_MIF_FRAME);
-
-	/* poll for completion */
-	while (limit-- > 0) {
-		udelay(10);
-		cmd = readl(cp->regs + REG_MIF_FRAME);
-		if (cmd & MIF_FRAME_TURN_AROUND_LSB)
-			return 0;
-	}
-	return -1;
-}
-
-static void cas_phy_powerup(struct cas *cp)
-{
-	u16 ctl = cas_phy_read(cp, MII_BMCR);
-
-	if ((ctl & BMCR_PDOWN) == 0)
-		return;
-	ctl &= ~BMCR_PDOWN;
-	cas_phy_write(cp, MII_BMCR, ctl);
-}
-
-static void cas_phy_powerdown(struct cas *cp)
-{
-	u16 ctl = cas_phy_read(cp, MII_BMCR);
-
-	if (ctl & BMCR_PDOWN)
-		return;
-	ctl |= BMCR_PDOWN;
-	cas_phy_write(cp, MII_BMCR, ctl);
-}
-
-/* cp->lock held. note: the last put_page will free the buffer */
-static int cas_page_free(struct cas *cp, cas_page_t *page)
-{
-	pci_unmap_page(cp->pdev, page->dma_addr, cp->page_size,
-		       PCI_DMA_FROMDEVICE);
-	__free_pages(page->buffer, cp->page_order);
-	kfree(page);
-	return 0;
-}
-
-#ifdef RX_COUNT_BUFFERS
-#define RX_USED_ADD(x, y)       ((x)->used += (y))
-#define RX_USED_SET(x, y)       ((x)->used  = (y))
-#else
-#define RX_USED_ADD(x, y)
-#define RX_USED_SET(x, y)
-#endif
-
-/* local page allocation routines for the receive buffers. jumbo pages
- * require at least 8K contiguous and 8K aligned buffers.
- */
-static cas_page_t *cas_page_alloc(struct cas *cp, const gfp_t flags)
-{
-	cas_page_t *page;
-
-	page = kmalloc(sizeof(cas_page_t), flags);
-	if (!page)
-		return NULL;
-
-	INIT_LIST_HEAD(&page->list);
-	RX_USED_SET(page, 0);
-	page->buffer = alloc_pages(flags, cp->page_order);
-	if (!page->buffer)
-		goto page_err;
-	page->dma_addr = pci_map_page(cp->pdev, page->buffer, 0,
-				      cp->page_size, PCI_DMA_FROMDEVICE);
-	return page;
-
-page_err:
-	kfree(page);
-	return NULL;
-}
-
-/* initialize spare pool of rx buffers, but allocate during the open */
-static void cas_spare_init(struct cas *cp)
-{
-  	spin_lock(&cp->rx_inuse_lock);
-	INIT_LIST_HEAD(&cp->rx_inuse_list);
-	spin_unlock(&cp->rx_inuse_lock);
-
-	spin_lock(&cp->rx_spare_lock);
-	INIT_LIST_HEAD(&cp->rx_spare_list);
-	cp->rx_spares_needed = RX_SPARE_COUNT;
-	spin_unlock(&cp->rx_spare_lock);
-}
-
-/* used on close. free all the spare buffers. */
-static void cas_spare_free(struct cas *cp)
-{
-	struct list_head list, *elem, *tmp;
-
-	/* free spare buffers */
-	INIT_LIST_HEAD(&list);
-	spin_lock(&cp->rx_spare_lock);
-	list_splice_init(&cp->rx_spare_list, &list);
-	spin_unlock(&cp->rx_spare_lock);
-	list_for_each_safe(elem, tmp, &list) {
-		cas_page_free(cp, list_entry(elem, cas_page_t, list));
-	}
-
-	INIT_LIST_HEAD(&list);
-#if 1
-	/*
-	 * Looks like Adrian had protected this with a different
-	 * lock than used everywhere else to manipulate this list.
-	 */
-	spin_lock(&cp->rx_inuse_lock);
-	list_splice_init(&cp->rx_inuse_list, &list);
-	spin_unlock(&cp->rx_inuse_lock);
-#else
-	spin_lock(&cp->rx_spare_lock);
-	list_splice_init(&cp->rx_inuse_list, &list);
-	spin_unlock(&cp->rx_spare_lock);
-#endif
-	list_for_each_safe(elem, tmp, &list) {
-		cas_page_free(cp, list_entry(elem, cas_page_t, list));
-	}
-}
-
-/* replenish spares if needed */
-static void cas_spare_recover(struct cas *cp, const gfp_t flags)
-{
-	struct list_head list, *elem, *tmp;
-	int needed, i;
-
-	/* check inuse list. if we don't need any more free buffers,
-	 * just free it
-	 */
-
-	/* make a local copy of the list */
-	INIT_LIST_HEAD(&list);
-	spin_lock(&cp->rx_inuse_lock);
-	list_splice_init(&cp->rx_inuse_list, &list);
-	spin_unlock(&cp->rx_inuse_lock);
-
-	list_for_each_safe(elem, tmp, &list) {
-		cas_page_t *page = list_entry(elem, cas_page_t, list);
-
-		/*
-		 * With the lockless pagecache, cassini buffering scheme gets
-		 * slightly less accurate: we might find that a page has an
-		 * elevated reference count here, due to a speculative ref,
-		 * and skip it as in-use. Ideally we would be able to reclaim
-		 * it. However this would be such a rare case, it doesn't
-		 * matter too much as we should pick it up the next time round.
-		 *
-		 * Importantly, if we find that the page has a refcount of 1
-		 * here (our refcount), then we know it is definitely not inuse
-		 * so we can reuse it.
-		 */
-		if (page_count(page->buffer) > 1)
-			continue;
-
-		list_del(elem);
-		spin_lock(&cp->rx_spare_lock);
-		if (cp->rx_spares_needed > 0) {
-			list_add(elem, &cp->rx_spare_list);
-			cp->rx_spares_needed--;
-			spin_unlock(&cp->rx_spare_lock);
-		} else {
-			spin_unlock(&cp->rx_spare_lock);
-			cas_page_free(cp, page);
-		}
-	}
-
-	/* put any inuse buffers back on the list */
-	if (!list_empty(&list)) {
-		spin_lock(&cp->rx_inuse_lock);
-		list_splice(&list, &cp->rx_inuse_list);
-		spin_unlock(&cp->rx_inuse_lock);
-	}
-
-	spin_lock(&cp->rx_spare_lock);
-	needed = cp->rx_spares_needed;
-	spin_unlock(&cp->rx_spare_lock);
-	if (!needed)
-		return;
-
-	/* we still need spares, so try to allocate some */
-	INIT_LIST_HEAD(&list);
-	i = 0;
-	while (i < needed) {
-		cas_page_t *spare = cas_page_alloc(cp, flags);
-		if (!spare)
-			break;
-		list_add(&spare->list, &list);
-		i++;
-	}
-
-	spin_lock(&cp->rx_spare_lock);
-	list_splice(&list, &cp->rx_spare_list);
-	cp->rx_spares_needed -= i;
-	spin_unlock(&cp->rx_spare_lock);
-}
-
-/* pull a page from the list. */
-static cas_page_t *cas_page_dequeue(struct cas *cp)
-{
-	struct list_head *entry;
-	int recover;
-
-	spin_lock(&cp->rx_spare_lock);
-	if (list_empty(&cp->rx_spare_list)) {
-		/* try to do a quick recovery */
-		spin_unlock(&cp->rx_spare_lock);
-		cas_spare_recover(cp, GFP_ATOMIC);
-		spin_lock(&cp->rx_spare_lock);
-		if (list_empty(&cp->rx_spare_list)) {
-			netif_err(cp, rx_err, cp->dev,
-				  "no spare buffers available\n");
-			spin_unlock(&cp->rx_spare_lock);
-			return NULL;
-		}
-	}
-
-	entry = cp->rx_spare_list.next;
-	list_del(entry);
-	recover = ++cp->rx_spares_needed;
-	spin_unlock(&cp->rx_spare_lock);
-
-	/* trigger the timer to do the recovery */
-	if ((recover & (RX_SPARE_RECOVER_VAL - 1)) == 0) {
-#if 1
-		atomic_inc(&cp->reset_task_pending);
-		atomic_inc(&cp->reset_task_pending_spare);
-		schedule_work(&cp->reset_task);
-#else
-		atomic_set(&cp->reset_task_pending, CAS_RESET_SPARE);
-		schedule_work(&cp->reset_task);
-#endif
-	}
-	return list_entry(entry, cas_page_t, list);
-}
-
-
-static void cas_mif_poll(struct cas *cp, const int enable)
-{
-	u32 cfg;
-
-	cfg  = readl(cp->regs + REG_MIF_CFG);
-	cfg &= (MIF_CFG_MDIO_0 | MIF_CFG_MDIO_1);
-
-	if (cp->phy_type & CAS_PHY_MII_MDIO1)
-		cfg |= MIF_CFG_PHY_SELECT;
-
-	/* poll and interrupt on link status change. */
-	if (enable) {
-		cfg |= MIF_CFG_POLL_EN;
-		cfg |= CAS_BASE(MIF_CFG_POLL_REG, MII_BMSR);
-		cfg |= CAS_BASE(MIF_CFG_POLL_PHY, cp->phy_addr);
-	}
-	writel((enable) ? ~(BMSR_LSTATUS | BMSR_ANEGCOMPLETE) : 0xFFFF,
-	       cp->regs + REG_MIF_MASK);
-	writel(cfg, cp->regs + REG_MIF_CFG);
-}
-
-/* Must be invoked under cp->lock */
-static void cas_begin_auto_negotiation(struct cas *cp, struct ethtool_cmd *ep)
-{
-	u16 ctl;
-#if 1
-	int lcntl;
-	int changed = 0;
-	int oldstate = cp->lstate;
-	int link_was_not_down = !(oldstate == link_down);
-#endif
-	/* Setup link parameters */
-	if (!ep)
-		goto start_aneg;
-	lcntl = cp->link_cntl;
-	if (ep->autoneg == AUTONEG_ENABLE)
-		cp->link_cntl = BMCR_ANENABLE;
-	else {
-		u32 speed = ethtool_cmd_speed(ep);
-		cp->link_cntl = 0;
-		if (speed == SPEED_100)
-			cp->link_cntl |= BMCR_SPEED100;
-		else if (speed == SPEED_1000)
-			cp->link_cntl |= CAS_BMCR_SPEED1000;
-		if (ep->duplex == DUPLEX_FULL)
-			cp->link_cntl |= BMCR_FULLDPLX;
-	}
-#if 1
-	changed = (lcntl != cp->link_cntl);
-#endif
-start_aneg:
-	if (cp->lstate == link_up) {
-		netdev_info(cp->dev, "PCS link down\n");
-	} else {
-		if (changed) {
-			netdev_info(cp->dev, "link configuration changed\n");
-		}
-	}
-	cp->lstate = link_down;
-	cp->link_transition = LINK_TRANSITION_LINK_DOWN;
-	if (!cp->hw_running)
-		return;
-#if 1
-	/*
-	 * WTZ: If the old state was link_up, we turn off the carrier
-	 * to replicate everything we do elsewhere on a link-down
-	 * event when we were already in a link-up state..
-	 */
-	if (oldstate == link_up)
-		netif_carrier_off(cp->dev);
-	if (changed  && link_was_not_down) {
-		/*
-		 * WTZ: This branch will simply schedule a full reset after
-		 * we explicitly changed link modes in an ioctl. See if this
-		 * fixes the link-problems we were having for forced mode.
-		 */
-		atomic_inc(&cp->reset_task_pending);
-		atomic_inc(&cp->reset_task_pending_all);
-		schedule_work(&cp->reset_task);
-		cp->timer_ticks = 0;
-		mod_timer(&cp->link_timer, jiffies + CAS_LINK_TIMEOUT);
-		return;
-	}
-#endif
-	if (cp->phy_type & CAS_PHY_SERDES) {
-		u32 val = readl(cp->regs + REG_PCS_MII_CTRL);
-
-		if (cp->link_cntl & BMCR_ANENABLE) {
-			val |= (PCS_MII_RESTART_AUTONEG | PCS_MII_AUTONEG_EN);
-			cp->lstate = link_aneg;
-		} else {
-			if (cp->link_cntl & BMCR_FULLDPLX)
-				val |= PCS_MII_CTRL_DUPLEX;
-			val &= ~PCS_MII_AUTONEG_EN;
-			cp->lstate = link_force_ok;
-		}
-		cp->link_transition = LINK_TRANSITION_LINK_CONFIG;
-		writel(val, cp->regs + REG_PCS_MII_CTRL);
-
-	} else {
-		cas_mif_poll(cp, 0);
-		ctl = cas_phy_read(cp, MII_BMCR);
-		ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 |
-			 CAS_BMCR_SPEED1000 | BMCR_ANENABLE);
-		ctl |= cp->link_cntl;
-		if (ctl & BMCR_ANENABLE) {
-			ctl |= BMCR_ANRESTART;
-			cp->lstate = link_aneg;
-		} else {
-			cp->lstate = link_force_ok;
-		}
-		cp->link_transition = LINK_TRANSITION_LINK_CONFIG;
-		cas_phy_write(cp, MII_BMCR, ctl);
-		cas_mif_poll(cp, 1);
-	}
-
-	cp->timer_ticks = 0;
-	mod_timer(&cp->link_timer, jiffies + CAS_LINK_TIMEOUT);
-}
-
-/* Must be invoked under cp->lock. */
-static int cas_reset_mii_phy(struct cas *cp)
-{
-	int limit = STOP_TRIES_PHY;
-	u16 val;
-
-	cas_phy_write(cp, MII_BMCR, BMCR_RESET);
-	udelay(100);
-	while (--limit) {
-		val = cas_phy_read(cp, MII_BMCR);
-		if ((val & BMCR_RESET) == 0)
-			break;
-		udelay(10);
-	}
-	return limit <= 0;
-}
-
-static int cas_saturn_firmware_init(struct cas *cp)
-{
-	const struct firmware *fw;
-	const char fw_name[] = "/*(DEBLOBBED)*/";
-	int err;
-
-	if (PHY_NS_DP83065 != cp->phy_id)
-		return 0;
-
-	err = reject_firmware(&fw, fw_name, &cp->pdev->dev);
-	if (err) {
-		pr_err("Failed to load firmware \"%s\"\n",
-		       fw_name);
-		return err;
-	}
-	if (fw->size < 2) {
-		pr_err("bogus length %zu in \"%s\"\n",
-		       fw->size, fw_name);
-		err = -EINVAL;
-		goto out;
-	}
-	cp->fw_load_addr= fw->data[1] << 8 | fw->data[0];
-	cp->fw_size = fw->size - 2;
-	cp->fw_data = vmalloc(cp->fw_size);
-	if (!cp->fw_data) {
-		err = -ENOMEM;
-		pr_err("\"%s\" Failed %d\n", fw_name, err);
-		goto out;
-	}
-	memcpy(cp->fw_data, &fw->data[2], cp->fw_size);
-out:
-	release_firmware(fw);
-	return err;
-}
-
-static void cas_saturn_firmware_load(struct cas *cp)
-{
-	int i;
-
-	cas_phy_powerdown(cp);
-
-	/* expanded memory access mode */
-	cas_phy_write(cp, DP83065_MII_MEM, 0x0);
-
-	/* pointer configuration for new firmware */
-	cas_phy_write(cp, DP83065_MII_REGE, 0x8ff9);
-	cas_phy_write(cp, DP83065_MII_REGD, 0xbd);
-	cas_phy_write(cp, DP83065_MII_REGE, 0x8ffa);
-	cas_phy_write(cp, DP83065_MII_REGD, 0x82);
-	cas_phy_write(cp, DP83065_MII_REGE, 0x8ffb);
-	cas_phy_write(cp, DP83065_MII_REGD, 0x0);
-	cas_phy_write(cp, DP83065_MII_REGE, 0x8ffc);
-	cas_phy_write(cp, DP83065_MII_REGD, 0x39);
-
-	/* download new firmware */
-	cas_phy_write(cp, DP83065_MII_MEM, 0x1);
-	cas_phy_write(cp, DP83065_MII_REGE, cp->fw_load_addr);
-	for (i = 0; i < cp->fw_size; i++)
-		cas_phy_write(cp, DP83065_MII_REGD, cp->fw_data[i]);
-
-	/* enable firmware */
-	cas_phy_write(cp, DP83065_MII_REGE, 0x8ff8);
-	cas_phy_write(cp, DP83065_MII_REGD, 0x1);
-}
-
-
-/* phy initialization */
-static void cas_phy_init(struct cas *cp)
-{
-	u16 val;
-
-	/* if we're in MII/GMII mode, set up phy */
-	if (CAS_PHY_MII(cp->phy_type)) {
-		writel(PCS_DATAPATH_MODE_MII,
-		       cp->regs + REG_PCS_DATAPATH_MODE);
-
-		cas_mif_poll(cp, 0);
-		cas_reset_mii_phy(cp); /* take out of isolate mode */
-
-		if (PHY_LUCENT_B0 == cp->phy_id) {
-			/* workaround link up/down issue with lucent */
-			cas_phy_write(cp, LUCENT_MII_REG, 0x8000);
-			cas_phy_write(cp, MII_BMCR, 0x00f1);
-			cas_phy_write(cp, LUCENT_MII_REG, 0x0);
-
-		} else if (PHY_BROADCOM_B0 == (cp->phy_id & 0xFFFFFFFC)) {
-			/* workarounds for broadcom phy */
-			cas_phy_write(cp, BROADCOM_MII_REG8, 0x0C20);
-			cas_phy_write(cp, BROADCOM_MII_REG7, 0x0012);
-			cas_phy_write(cp, BROADCOM_MII_REG5, 0x1804);
-			cas_phy_write(cp, BROADCOM_MII_REG7, 0x0013);
-			cas_phy_write(cp, BROADCOM_MII_REG5, 0x1204);
-			cas_phy_write(cp, BROADCOM_MII_REG7, 0x8006);
-			cas_phy_write(cp, BROADCOM_MII_REG5, 0x0132);
-			cas_phy_write(cp, BROADCOM_MII_REG7, 0x8006);
-			cas_phy_write(cp, BROADCOM_MII_REG5, 0x0232);
-			cas_phy_write(cp, BROADCOM_MII_REG7, 0x201F);
-			cas_phy_write(cp, BROADCOM_MII_REG5, 0x0A20);
-
-		} else if (PHY_BROADCOM_5411 == cp->phy_id) {
-			val = cas_phy_read(cp, BROADCOM_MII_REG4);
-			val = cas_phy_read(cp, BROADCOM_MII_REG4);
-			if (val & 0x0080) {
-				/* link workaround */
-				cas_phy_write(cp, BROADCOM_MII_REG4,
-					      val & ~0x0080);
-			}
-
-		} else if (cp->cas_flags & CAS_FLAG_SATURN) {
-			writel((cp->phy_type & CAS_PHY_MII_MDIO0) ?
-			       SATURN_PCFG_FSI : 0x0,
-			       cp->regs + REG_SATURN_PCFG);
-
-			/* load firmware to address 10Mbps auto-negotiation
-			 * issue. NOTE: this will need to be changed if the
-			 * default firmware gets fixed.
-			 */
-			if (PHY_NS_DP83065 == cp->phy_id) {
-				cas_saturn_firmware_load(cp);
-			}
-			cas_phy_powerup(cp);
-		}
-
-		/* advertise capabilities */
-		val = cas_phy_read(cp, MII_BMCR);
-		val &= ~BMCR_ANENABLE;
-		cas_phy_write(cp, MII_BMCR, val);
-		udelay(10);
-
-		cas_phy_write(cp, MII_ADVERTISE,
-			      cas_phy_read(cp, MII_ADVERTISE) |
-			      (ADVERTISE_10HALF | ADVERTISE_10FULL |
-			       ADVERTISE_100HALF | ADVERTISE_100FULL |
-			       CAS_ADVERTISE_PAUSE |
-			       CAS_ADVERTISE_ASYM_PAUSE));
-
-		if (cp->cas_flags & CAS_FLAG_1000MB_CAP) {
-			/* make sure that we don't advertise half
-			 * duplex to avoid a chip issue
-			 */
-			val  = cas_phy_read(cp, CAS_MII_1000_CTRL);
-			val &= ~CAS_ADVERTISE_1000HALF;
-			val |= CAS_ADVERTISE_1000FULL;
-			cas_phy_write(cp, CAS_MII_1000_CTRL, val);
-		}
-
-	} else {
-		/* reset pcs for serdes */
-		u32 val;
-		int limit;
-
-		writel(PCS_DATAPATH_MODE_SERDES,
-		       cp->regs + REG_PCS_DATAPATH_MODE);
-
-		/* enable serdes pins on saturn */
-		if (cp->cas_flags & CAS_FLAG_SATURN)
-			writel(0, cp->regs + REG_SATURN_PCFG);
-
-		/* Reset PCS unit. */
-		val = readl(cp->regs + REG_PCS_MII_CTRL);
-		val |= PCS_MII_RESET;
-		writel(val, cp->regs + REG_PCS_MII_CTRL);
-
-		limit = STOP_TRIES;
-		while (--limit > 0) {
-			udelay(10);
-			if ((readl(cp->regs + REG_PCS_MII_CTRL) &
-			     PCS_MII_RESET) == 0)
-				break;
-		}
-		if (limit <= 0)
-			netdev_warn(cp->dev, "PCS reset bit would not clear [%08x]\n",
-				    readl(cp->regs + REG_PCS_STATE_MACHINE));
-
-		/* Make sure PCS is disabled while changing advertisement
-		 * configuration.
-		 */
-		writel(0x0, cp->regs + REG_PCS_CFG);
-
-		/* Advertise all capabilities except half-duplex. */
-		val  = readl(cp->regs + REG_PCS_MII_ADVERT);
-		val &= ~PCS_MII_ADVERT_HD;
-		val |= (PCS_MII_ADVERT_FD | PCS_MII_ADVERT_SYM_PAUSE |
-			PCS_MII_ADVERT_ASYM_PAUSE);
-		writel(val, cp->regs + REG_PCS_MII_ADVERT);
-
-		/* enable PCS */
-		writel(PCS_CFG_EN, cp->regs + REG_PCS_CFG);
-
-		/* pcs workaround: enable sync detect */
-		writel(PCS_SERDES_CTRL_SYNCD_EN,
-		       cp->regs + REG_PCS_SERDES_CTRL);
-	}
-}
-
-
-static int cas_pcs_link_check(struct cas *cp)
-{
-	u32 stat, state_machine;
-	int retval = 0;
-
-	/* The link status bit latches on zero, so you must
-	 * read it twice in such a case to see a transition
-	 * to the link being up.
-	 */
-	stat = readl(cp->regs + REG_PCS_MII_STATUS);
-	if ((stat & PCS_MII_STATUS_LINK_STATUS) == 0)
-		stat = readl(cp->regs + REG_PCS_MII_STATUS);
-
-	/* The remote-fault indication is only valid
-	 * when autoneg has completed.
-	 */
-	if ((stat & (PCS_MII_STATUS_AUTONEG_COMP |
-		     PCS_MII_STATUS_REMOTE_FAULT)) ==
-	    (PCS_MII_STATUS_AUTONEG_COMP | PCS_MII_STATUS_REMOTE_FAULT))
-		netif_info(cp, link, cp->dev, "PCS RemoteFault\n");
-
-	/* work around link detection issue by querying the PCS state
-	 * machine directly.
-	 */
-	state_machine = readl(cp->regs + REG_PCS_STATE_MACHINE);
-	if ((state_machine & PCS_SM_LINK_STATE_MASK) != SM_LINK_STATE_UP) {
-		stat &= ~PCS_MII_STATUS_LINK_STATUS;
-	} else if (state_machine & PCS_SM_WORD_SYNC_STATE_MASK) {
-		stat |= PCS_MII_STATUS_LINK_STATUS;
-	}
-
-	if (stat & PCS_MII_STATUS_LINK_STATUS) {
-		if (cp->lstate != link_up) {
-			if (cp->opened) {
-				cp->lstate = link_up;
-				cp->link_transition = LINK_TRANSITION_LINK_UP;
-
-				cas_set_link_modes(cp);
-				netif_carrier_on(cp->dev);
-			}
-		}
-	} else if (cp->lstate == link_up) {
-		cp->lstate = link_down;
-		if (link_transition_timeout != 0 &&
-		    cp->link_transition != LINK_TRANSITION_REQUESTED_RESET &&
-		    !cp->link_transition_jiffies_valid) {
-			/*
-			 * force a reset, as a workaround for the
-			 * link-failure problem. May want to move this to a
-			 * point a bit earlier in the sequence. If we had
-			 * generated a reset a short time ago, we'll wait for
-			 * the link timer to check the status until a
-			 * timer expires (link_transistion_jiffies_valid is
-			 * true when the timer is running.)  Instead of using
-			 * a system timer, we just do a check whenever the
-			 * link timer is running - this clears the flag after
-			 * a suitable delay.
-			 */
-			retval = 1;
-			cp->link_transition = LINK_TRANSITION_REQUESTED_RESET;
-			cp->link_transition_jiffies = jiffies;
-			cp->link_transition_jiffies_valid = 1;
-		} else {
-			cp->link_transition = LINK_TRANSITION_ON_FAILURE;
-		}
-		netif_carrier_off(cp->dev);
-		if (cp->opened)
-			netif_info(cp, link, cp->dev, "PCS link down\n");
-
-		/* Cassini only: if you force a mode, there can be
-		 * sync problems on link down. to fix that, the following
-		 * things need to be checked:
-		 * 1) read serialink state register
-		 * 2) read pcs status register to verify link down.
-		 * 3) if link down and serial link == 0x03, then you need
-		 *    to global reset the chip.
-		 */
-		if ((cp->cas_flags & CAS_FLAG_REG_PLUS) == 0) {
-			/* should check to see if we're in a forced mode */
-			stat = readl(cp->regs + REG_PCS_SERDES_STATE);
-			if (stat == 0x03)
-				return 1;
-		}
-	} else if (cp->lstate == link_down) {
-		if (link_transition_timeout != 0 &&
-		    cp->link_transition != LINK_TRANSITION_REQUESTED_RESET &&
-		    !cp->link_transition_jiffies_valid) {
-			/* force a reset, as a workaround for the
-			 * link-failure problem.  May want to move
-			 * this to a point a bit earlier in the
-			 * sequence.
-			 */
-			retval = 1;
-			cp->link_transition = LINK_TRANSITION_REQUESTED_RESET;
-			cp->link_transition_jiffies = jiffies;
-			cp->link_transition_jiffies_valid = 1;
-		} else {
-			cp->link_transition = LINK_TRANSITION_STILL_FAILED;
-		}
-	}
-
-	return retval;
-}
-
-static int cas_pcs_interrupt(struct net_device *dev,
-			     struct cas *cp, u32 status)
-{
-	u32 stat = readl(cp->regs + REG_PCS_INTR_STATUS);
-
-	if ((stat & PCS_INTR_STATUS_LINK_CHANGE) == 0)
-		return 0;
-	return cas_pcs_link_check(cp);
-}
-
-static int cas_txmac_interrupt(struct net_device *dev,
-			       struct cas *cp, u32 status)
-{
-	u32 txmac_stat = readl(cp->regs + REG_MAC_TX_STATUS);
-
-	if (!txmac_stat)
-		return 0;
-
-	netif_printk(cp, intr, KERN_DEBUG, cp->dev,
-		     "txmac interrupt, txmac_stat: 0x%x\n", txmac_stat);
-
-	/* Defer timer expiration is quite normal,
-	 * don't even log the event.
-	 */
-	if ((txmac_stat & MAC_TX_DEFER_TIMER) &&
-	    !(txmac_stat & ~MAC_TX_DEFER_TIMER))
-		return 0;
-
-	spin_lock(&cp->stat_lock[0]);
-	if (txmac_stat & MAC_TX_UNDERRUN) {
-		netdev_err(dev, "TX MAC xmit underrun\n");
-		cp->net_stats[0].tx_fifo_errors++;
-	}
-
-	if (txmac_stat & MAC_TX_MAX_PACKET_ERR) {
-		netdev_err(dev, "TX MAC max packet size error\n");
-		cp->net_stats[0].tx_errors++;
-	}
-
-	/* The rest are all cases of one of the 16-bit TX
-	 * counters expiring.
-	 */
-	if (txmac_stat & MAC_TX_COLL_NORMAL)
-		cp->net_stats[0].collisions += 0x10000;
-
-	if (txmac_stat & MAC_TX_COLL_EXCESS) {
-		cp->net_stats[0].tx_aborted_errors += 0x10000;
-		cp->net_stats[0].collisions += 0x10000;
-	}
-
-	if (txmac_stat & MAC_TX_COLL_LATE) {
-		cp->net_stats[0].tx_aborted_errors += 0x10000;
-		cp->net_stats[0].collisions += 0x10000;
-	}
-	spin_unlock(&cp->stat_lock[0]);
-
-	/* We do not keep track of MAC_TX_COLL_FIRST and
-	 * MAC_TX_PEAK_ATTEMPTS events.
-	 */
-	return 0;
-}
-
-static void cas_load_firmware(struct cas *cp, cas_hp_inst_t *firmware)
-{
-	cas_hp_inst_t *inst;
-	u32 val;
-	int i;
-
-	i = 0;
-	while ((inst = firmware) && inst->note) {
-		writel(i, cp->regs + REG_HP_INSTR_RAM_ADDR);
-
-		val = CAS_BASE(HP_INSTR_RAM_HI_VAL, inst->val);
-		val |= CAS_BASE(HP_INSTR_RAM_HI_MASK, inst->mask);
-		writel(val, cp->regs + REG_HP_INSTR_RAM_DATA_HI);
-
-		val = CAS_BASE(HP_INSTR_RAM_MID_OUTARG, inst->outarg >> 10);
-		val |= CAS_BASE(HP_INSTR_RAM_MID_OUTOP, inst->outop);
-		val |= CAS_BASE(HP_INSTR_RAM_MID_FNEXT, inst->fnext);
-		val |= CAS_BASE(HP_INSTR_RAM_MID_FOFF, inst->foff);
-		val |= CAS_BASE(HP_INSTR_RAM_MID_SNEXT, inst->snext);
-		val |= CAS_BASE(HP_INSTR_RAM_MID_SOFF, inst->soff);
-		val |= CAS_BASE(HP_INSTR_RAM_MID_OP, inst->op);
-		writel(val, cp->regs + REG_HP_INSTR_RAM_DATA_MID);
-
-		val = CAS_BASE(HP_INSTR_RAM_LOW_OUTMASK, inst->outmask);
-		val |= CAS_BASE(HP_INSTR_RAM_LOW_OUTSHIFT, inst->outshift);
-		val |= CAS_BASE(HP_INSTR_RAM_LOW_OUTEN, inst->outenab);
-		val |= CAS_BASE(HP_INSTR_RAM_LOW_OUTARG, inst->outarg);
-		writel(val, cp->regs + REG_HP_INSTR_RAM_DATA_LOW);
-		++firmware;
-		++i;
-	}
-}
-
-static void cas_init_rx_dma(struct cas *cp)
-{
-	u64 desc_dma = cp->block_dvma;
-	u32 val;
-	int i, size;
-
-	/* rx free descriptors */
-	val = CAS_BASE(RX_CFG_SWIVEL, RX_SWIVEL_OFF_VAL);
-	val |= CAS_BASE(RX_CFG_DESC_RING, RX_DESC_RINGN_INDEX(0));
-	val |= CAS_BASE(RX_CFG_COMP_RING, RX_COMP_RINGN_INDEX(0));
-	if ((N_RX_DESC_RINGS > 1) &&
-	    (cp->cas_flags & CAS_FLAG_REG_PLUS))  /* do desc 2 */
-		val |= CAS_BASE(RX_CFG_DESC_RING1, RX_DESC_RINGN_INDEX(1));
-	writel(val, cp->regs + REG_RX_CFG);
-
-	val = (unsigned long) cp->init_rxds[0] -
-		(unsigned long) cp->init_block;
-	writel((desc_dma + val) >> 32, cp->regs + REG_RX_DB_HI);
-	writel((desc_dma + val) & 0xffffffff, cp->regs + REG_RX_DB_LOW);
-	writel(RX_DESC_RINGN_SIZE(0) - 4, cp->regs + REG_RX_KICK);
-
-	if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
-		/* rx desc 2 is for IPSEC packets. however,
-		 * we don't it that for that purpose.
-		 */
-		val = (unsigned long) cp->init_rxds[1] -
-			(unsigned long) cp->init_block;
-		writel((desc_dma + val) >> 32, cp->regs + REG_PLUS_RX_DB1_HI);
-		writel((desc_dma + val) & 0xffffffff, cp->regs +
-		       REG_PLUS_RX_DB1_LOW);
-		writel(RX_DESC_RINGN_SIZE(1) - 4, cp->regs +
-		       REG_PLUS_RX_KICK1);
-	}
-
-	/* rx completion registers */
-	val = (unsigned long) cp->init_rxcs[0] -
-		(unsigned long) cp->init_block;
-	writel((desc_dma + val) >> 32, cp->regs + REG_RX_CB_HI);
-	writel((desc_dma + val) & 0xffffffff, cp->regs + REG_RX_CB_LOW);
-
-	if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
-		/* rx comp 2-4 */
-		for (i = 1; i < MAX_RX_COMP_RINGS; i++) {
-			val = (unsigned long) cp->init_rxcs[i] -
-				(unsigned long) cp->init_block;
-			writel((desc_dma + val) >> 32, cp->regs +
-			       REG_PLUS_RX_CBN_HI(i));
-			writel((desc_dma + val) & 0xffffffff, cp->regs +
-			       REG_PLUS_RX_CBN_LOW(i));
-		}
-	}
-
-	/* read selective clear regs to prevent spurious interrupts
-	 * on reset because complete == kick.
-	 * selective clear set up to prevent interrupts on resets
-	 */
-	readl(cp->regs + REG_INTR_STATUS_ALIAS);
-	writel(INTR_RX_DONE | INTR_RX_BUF_UNAVAIL, cp->regs + REG_ALIAS_CLEAR);
-	if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
-		for (i = 1; i < N_RX_COMP_RINGS; i++)
-			readl(cp->regs + REG_PLUS_INTRN_STATUS_ALIAS(i));
-
-		/* 2 is different from 3 and 4 */
-		if (N_RX_COMP_RINGS > 1)
-			writel(INTR_RX_DONE_ALT | INTR_RX_BUF_UNAVAIL_1,
-			       cp->regs + REG_PLUS_ALIASN_CLEAR(1));
-
-		for (i = 2; i < N_RX_COMP_RINGS; i++)
-			writel(INTR_RX_DONE_ALT,
-			       cp->regs + REG_PLUS_ALIASN_CLEAR(i));
-	}
-
-	/* set up pause thresholds */
-	val  = CAS_BASE(RX_PAUSE_THRESH_OFF,
-			cp->rx_pause_off / RX_PAUSE_THRESH_QUANTUM);
-	val |= CAS_BASE(RX_PAUSE_THRESH_ON,
-			cp->rx_pause_on / RX_PAUSE_THRESH_QUANTUM);
-	writel(val, cp->regs + REG_RX_PAUSE_THRESH);
-
-	/* zero out dma reassembly buffers */
-	for (i = 0; i < 64; i++) {
-		writel(i, cp->regs + REG_RX_TABLE_ADDR);
-		writel(0x0, cp->regs + REG_RX_TABLE_DATA_LOW);
-		writel(0x0, cp->regs + REG_RX_TABLE_DATA_MID);
-		writel(0x0, cp->regs + REG_RX_TABLE_DATA_HI);
-	}
-
-	/* make sure address register is 0 for normal operation */
-	writel(0x0, cp->regs + REG_RX_CTRL_FIFO_ADDR);
-	writel(0x0, cp->regs + REG_RX_IPP_FIFO_ADDR);
-
-	/* interrupt mitigation */
-#ifdef USE_RX_BLANK
-	val = CAS_BASE(RX_BLANK_INTR_TIME, RX_BLANK_INTR_TIME_VAL);
-	val |= CAS_BASE(RX_BLANK_INTR_PKT, RX_BLANK_INTR_PKT_VAL);
-	writel(val, cp->regs + REG_RX_BLANK);
-#else
-	writel(0x0, cp->regs + REG_RX_BLANK);
-#endif
-
-	/* interrupt generation as a function of low water marks for
-	 * free desc and completion entries. these are used to trigger
-	 * housekeeping for rx descs. we don't use the free interrupt
-	 * as it's not very useful
-	 */
-	/* val = CAS_BASE(RX_AE_THRESH_FREE, RX_AE_FREEN_VAL(0)); */
-	val = CAS_BASE(RX_AE_THRESH_COMP, RX_AE_COMP_VAL);
-	writel(val, cp->regs + REG_RX_AE_THRESH);
-	if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
-		val = CAS_BASE(RX_AE1_THRESH_FREE, RX_AE_FREEN_VAL(1));
-		writel(val, cp->regs + REG_PLUS_RX_AE1_THRESH);
-	}
-
-	/* Random early detect registers. useful for congestion avoidance.
-	 * this should be tunable.
-	 */
-	writel(0x0, cp->regs + REG_RX_RED);
-
-	/* receive page sizes. default == 2K (0x800) */
-	val = 0;
-	if (cp->page_size == 0x1000)
-		val = 0x1;
-	else if (cp->page_size == 0x2000)
-		val = 0x2;
-	else if (cp->page_size == 0x4000)
-		val = 0x3;
-
-	/* round mtu + offset. constrain to page size. */
-	size = cp->dev->mtu + 64;
-	if (size > cp->page_size)
-		size = cp->page_size;
-
-	if (size <= 0x400)
-		i = 0x0;
-	else if (size <= 0x800)
-		i = 0x1;
-	else if (size <= 0x1000)
-		i = 0x2;
-	else
-		i = 0x3;
-
-	cp->mtu_stride = 1 << (i + 10);
-	val  = CAS_BASE(RX_PAGE_SIZE, val);
-	val |= CAS_BASE(RX_PAGE_SIZE_MTU_STRIDE, i);
-	val |= CAS_BASE(RX_PAGE_SIZE_MTU_COUNT, cp->page_size >> (i + 10));
-	val |= CAS_BASE(RX_PAGE_SIZE_MTU_OFF, 0x1);
-	writel(val, cp->regs + REG_RX_PAGE_SIZE);
-
-	/* enable the header parser if desired */
-	if (CAS_HP_FIRMWARE == cas_prog_null)
-		return;
-
-	val = CAS_BASE(HP_CFG_NUM_CPU, CAS_NCPUS > 63 ? 0 : CAS_NCPUS);
-	val |= HP_CFG_PARSE_EN | HP_CFG_SYN_INC_MASK;
-	val |= CAS_BASE(HP_CFG_TCP_THRESH, HP_TCP_THRESH_VAL);
-	writel(val, cp->regs + REG_HP_CFG);
-}
-
-static inline void cas_rxc_init(struct cas_rx_comp *rxc)
-{
-	memset(rxc, 0, sizeof(*rxc));
-	rxc->word4 = cpu_to_le64(RX_COMP4_ZERO);
-}
-
-/* NOTE: we use the ENC RX DESC ring for spares. the rx_page[0,1]
- * flipping is protected by the fact that the chip will not
- * hand back the same page index while it's being processed.
- */
-static inline cas_page_t *cas_page_spare(struct cas *cp, const int index)
-{
-	cas_page_t *page = cp->rx_pages[1][index];
-	cas_page_t *new;
-
-	if (page_count(page->buffer) == 1)
-		return page;
-
-	new = cas_page_dequeue(cp);
-	if (new) {
-		spin_lock(&cp->rx_inuse_lock);
-		list_add(&page->list, &cp->rx_inuse_list);
-		spin_unlock(&cp->rx_inuse_lock);
-	}
-	return new;
-}
-
-/* this needs to be changed if we actually use the ENC RX DESC ring */
-static cas_page_t *cas_page_swap(struct cas *cp, const int ring,
-				 const int index)
-{
-	cas_page_t **page0 = cp->rx_pages[0];
-	cas_page_t **page1 = cp->rx_pages[1];
-
-	/* swap if buffer is in use */
-	if (page_count(page0[index]->buffer) > 1) {
-		cas_page_t *new = cas_page_spare(cp, index);
-		if (new) {
-			page1[index] = page0[index];
-			page0[index] = new;
-		}
-	}
-	RX_USED_SET(page0[index], 0);
-	return page0[index];
-}
-
-static void cas_clean_rxds(struct cas *cp)
-{
-	/* only clean ring 0 as ring 1 is used for spare buffers */
-        struct cas_rx_desc *rxd = cp->init_rxds[0];
-	int i, size;
-
-	/* release all rx flows */
-	for (i = 0; i < N_RX_FLOWS; i++) {
-		struct sk_buff *skb;
-		while ((skb = __skb_dequeue(&cp->rx_flows[i]))) {
-			cas_skb_release(skb);
-		}
-	}
-
-	/* initialize descriptors */
-	size = RX_DESC_RINGN_SIZE(0);
-	for (i = 0; i < size; i++) {
-		cas_page_t *page = cas_page_swap(cp, 0, i);
-		rxd[i].buffer = cpu_to_le64(page->dma_addr);
-		rxd[i].index  = cpu_to_le64(CAS_BASE(RX_INDEX_NUM, i) |
-					    CAS_BASE(RX_INDEX_RING, 0));
-	}
-
-	cp->rx_old[0]  = RX_DESC_RINGN_SIZE(0) - 4;
-	cp->rx_last[0] = 0;
-	cp->cas_flags &= ~CAS_FLAG_RXD_POST(0);
-}
-
-static void cas_clean_rxcs(struct cas *cp)
-{
-	int i, j;
-
-	/* take ownership of rx comp descriptors */
-	memset(cp->rx_cur, 0, sizeof(*cp->rx_cur)*N_RX_COMP_RINGS);
-	memset(cp->rx_new, 0, sizeof(*cp->rx_new)*N_RX_COMP_RINGS);
-	for (i = 0; i < N_RX_COMP_RINGS; i++) {
-		struct cas_rx_comp *rxc = cp->init_rxcs[i];
-		for (j = 0; j < RX_COMP_RINGN_SIZE(i); j++) {
-			cas_rxc_init(rxc + j);
-		}
-	}
-}
-
-#if 0
-/* When we get a RX fifo overflow, the RX unit is probably hung
- * so we do the following.
- *
- * If any part of the reset goes wrong, we return 1 and that causes the
- * whole chip to be reset.
- */
-static int cas_rxmac_reset(struct cas *cp)
-{
-	struct net_device *dev = cp->dev;
-	int limit;
-	u32 val;
-
-	/* First, reset MAC RX. */
-	writel(cp->mac_rx_cfg & ~MAC_RX_CFG_EN, cp->regs + REG_MAC_RX_CFG);
-	for (limit = 0; limit < STOP_TRIES; limit++) {
-		if (!(readl(cp->regs + REG_MAC_RX_CFG) & MAC_RX_CFG_EN))
-			break;
-		udelay(10);
-	}
-	if (limit == STOP_TRIES) {
-		netdev_err(dev, "RX MAC will not disable, resetting whole chip\n");
-		return 1;
-	}
-
-	/* Second, disable RX DMA. */
-	writel(0, cp->regs + REG_RX_CFG);
-	for (limit = 0; limit < STOP_TRIES; limit++) {
-		if (!(readl(cp->regs + REG_RX_CFG) & RX_CFG_DMA_EN))
-			break;
-		udelay(10);
-	}
-	if (limit == STOP_TRIES) {
-		netdev_err(dev, "RX DMA will not disable, resetting whole chip\n");
-		return 1;
-	}
-
-	mdelay(5);
-
-	/* Execute RX reset command. */
-	writel(SW_RESET_RX, cp->regs + REG_SW_RESET);
-	for (limit = 0; limit < STOP_TRIES; limit++) {
-		if (!(readl(cp->regs + REG_SW_RESET) & SW_RESET_RX))
-			break;
-		udelay(10);
-	}
-	if (limit == STOP_TRIES) {
-		netdev_err(dev, "RX reset command will not execute, resetting whole chip\n");
-		return 1;
-	}
-
-	/* reset driver rx state */
-	cas_clean_rxds(cp);
-	cas_clean_rxcs(cp);
-
-	/* Now, reprogram the rest of RX unit. */
-	cas_init_rx_dma(cp);
-
-	/* re-enable */
-	val = readl(cp->regs + REG_RX_CFG);
-	writel(val | RX_CFG_DMA_EN, cp->regs + REG_RX_CFG);
-	writel(MAC_RX_FRAME_RECV, cp->regs + REG_MAC_RX_MASK);
-	val = readl(cp->regs + REG_MAC_RX_CFG);
-	writel(val | MAC_RX_CFG_EN, cp->regs + REG_MAC_RX_CFG);
-	return 0;
-}
-#endif
-
-static int cas_rxmac_interrupt(struct net_device *dev, struct cas *cp,
-			       u32 status)
-{
-	u32 stat = readl(cp->regs + REG_MAC_RX_STATUS);
-
-	if (!stat)
-		return 0;
-
-	netif_dbg(cp, intr, cp->dev, "rxmac interrupt, stat: 0x%x\n", stat);
-
-	/* these are all rollovers */
-	spin_lock(&cp->stat_lock[0]);
-	if (stat & MAC_RX_ALIGN_ERR)
-		cp->net_stats[0].rx_frame_errors += 0x10000;
-
-	if (stat & MAC_RX_CRC_ERR)
-		cp->net_stats[0].rx_crc_errors += 0x10000;
-
-	if (stat & MAC_RX_LEN_ERR)
-		cp->net_stats[0].rx_length_errors += 0x10000;
-
-	if (stat & MAC_RX_OVERFLOW) {
-		cp->net_stats[0].rx_over_errors++;
-		cp->net_stats[0].rx_fifo_errors++;
-	}
-
-	/* We do not track MAC_RX_FRAME_COUNT and MAC_RX_VIOL_ERR
-	 * events.
-	 */
-	spin_unlock(&cp->stat_lock[0]);
-	return 0;
-}
-
-static int cas_mac_interrupt(struct net_device *dev, struct cas *cp,
-			     u32 status)
-{
-	u32 stat = readl(cp->regs + REG_MAC_CTRL_STATUS);
-
-	if (!stat)
-		return 0;
-
-	netif_printk(cp, intr, KERN_DEBUG, cp->dev,
-		     "mac interrupt, stat: 0x%x\n", stat);
-
-	/* This interrupt is just for pause frame and pause
-	 * tracking.  It is useful for diagnostics and debug
-	 * but probably by default we will mask these events.
-	 */
-	if (stat & MAC_CTRL_PAUSE_STATE)
-		cp->pause_entered++;
-
-	if (stat & MAC_CTRL_PAUSE_RECEIVED)
-		cp->pause_last_time_recvd = (stat >> 16);
-
-	return 0;
-}
-
-
-/* Must be invoked under cp->lock. */
-static inline int cas_mdio_link_not_up(struct cas *cp)
-{
-	u16 val;
-
-	switch (cp->lstate) {
-	case link_force_ret:
-		netif_info(cp, link, cp->dev, "Autoneg failed again, keeping forced mode\n");
-		cas_phy_write(cp, MII_BMCR, cp->link_fcntl);
-		cp->timer_ticks = 5;
-		cp->lstate = link_force_ok;
-		cp->link_transition = LINK_TRANSITION_LINK_CONFIG;
-		break;
-
-	case link_aneg:
-		val = cas_phy_read(cp, MII_BMCR);
-
-		/* Try forced modes. we try things in the following order:
-		 * 1000 full -> 100 full/half -> 10 half
-		 */
-		val &= ~(BMCR_ANRESTART | BMCR_ANENABLE);
-		val |= BMCR_FULLDPLX;
-		val |= (cp->cas_flags & CAS_FLAG_1000MB_CAP) ?
-			CAS_BMCR_SPEED1000 : BMCR_SPEED100;
-		cas_phy_write(cp, MII_BMCR, val);
-		cp->timer_ticks = 5;
-		cp->lstate = link_force_try;
-		cp->link_transition = LINK_TRANSITION_LINK_CONFIG;
-		break;
-
-	case link_force_try:
-		/* Downgrade from 1000 to 100 to 10 Mbps if necessary. */
-		val = cas_phy_read(cp, MII_BMCR);
-		cp->timer_ticks = 5;
-		if (val & CAS_BMCR_SPEED1000) { /* gigabit */
-			val &= ~CAS_BMCR_SPEED1000;
-			val |= (BMCR_SPEED100 | BMCR_FULLDPLX);
-			cas_phy_write(cp, MII_BMCR, val);
-			break;
-		}
-
-		if (val & BMCR_SPEED100) {
-			if (val & BMCR_FULLDPLX) /* fd failed */
-				val &= ~BMCR_FULLDPLX;
-			else { /* 100Mbps failed */
-				val &= ~BMCR_SPEED100;
-			}
-			cas_phy_write(cp, MII_BMCR, val);
-			break;
-		}
-	default:
-		break;
-	}
-	return 0;
-}
-
-
-/* must be invoked with cp->lock held */
-static int cas_mii_link_check(struct cas *cp, const u16 bmsr)
-{
-	int restart;
-
-	if (bmsr & BMSR_LSTATUS) {
-		/* Ok, here we got a link. If we had it due to a forced
-		 * fallback, and we were configured for autoneg, we
-		 * retry a short autoneg pass. If you know your hub is
-		 * broken, use ethtool ;)
-		 */
-		if ((cp->lstate == link_force_try) &&
-		    (cp->link_cntl & BMCR_ANENABLE)) {
-			cp->lstate = link_force_ret;
-			cp->link_transition = LINK_TRANSITION_LINK_CONFIG;
-			cas_mif_poll(cp, 0);
-			cp->link_fcntl = cas_phy_read(cp, MII_BMCR);
-			cp->timer_ticks = 5;
-			if (cp->opened)
-				netif_info(cp, link, cp->dev,
-					   "Got link after fallback, retrying autoneg once...\n");
-			cas_phy_write(cp, MII_BMCR,
-				      cp->link_fcntl | BMCR_ANENABLE |
-				      BMCR_ANRESTART);
-			cas_mif_poll(cp, 1);
-
-		} else if (cp->lstate != link_up) {
-			cp->lstate = link_up;
-			cp->link_transition = LINK_TRANSITION_LINK_UP;
-
-			if (cp->opened) {
-				cas_set_link_modes(cp);
-				netif_carrier_on(cp->dev);
-			}
-		}
-		return 0;
-	}
-
-	/* link not up. if the link was previously up, we restart the
-	 * whole process
-	 */
-	restart = 0;
-	if (cp->lstate == link_up) {
-		cp->lstate = link_down;
-		cp->link_transition = LINK_TRANSITION_LINK_DOWN;
-
-		netif_carrier_off(cp->dev);
-		if (cp->opened)
-			netif_info(cp, link, cp->dev, "Link down\n");
-		restart = 1;
-
-	} else if (++cp->timer_ticks > 10)
-		cas_mdio_link_not_up(cp);
-
-	return restart;
-}
-
-static int cas_mif_interrupt(struct net_device *dev, struct cas *cp,
-			     u32 status)
-{
-	u32 stat = readl(cp->regs + REG_MIF_STATUS);
-	u16 bmsr;
-
-	/* check for a link change */
-	if (CAS_VAL(MIF_STATUS_POLL_STATUS, stat) == 0)
-		return 0;
-
-	bmsr = CAS_VAL(MIF_STATUS_POLL_DATA, stat);
-	return cas_mii_link_check(cp, bmsr);
-}
-
-static int cas_pci_interrupt(struct net_device *dev, struct cas *cp,
-			     u32 status)
-{
-	u32 stat = readl(cp->regs + REG_PCI_ERR_STATUS);
-
-	if (!stat)
-		return 0;
-
-	netdev_err(dev, "PCI error [%04x:%04x]",
-		   stat, readl(cp->regs + REG_BIM_DIAG));
-
-	/* cassini+ has this reserved */
-	if ((stat & PCI_ERR_BADACK) &&
-	    ((cp->cas_flags & CAS_FLAG_REG_PLUS) == 0))
-		pr_cont(" <No ACK64# during ABS64 cycle>");
-
-	if (stat & PCI_ERR_DTRTO)
-		pr_cont(" <Delayed transaction timeout>");
-	if (stat & PCI_ERR_OTHER)
-		pr_cont(" <other>");
-	if (stat & PCI_ERR_BIM_DMA_WRITE)
-		pr_cont(" <BIM DMA 0 write req>");
-	if (stat & PCI_ERR_BIM_DMA_READ)
-		pr_cont(" <BIM DMA 0 read req>");
-	pr_cont("\n");
-
-	if (stat & PCI_ERR_OTHER) {
-		u16 cfg;
-
-		/* Interrogate PCI config space for the
-		 * true cause.
-		 */
-		pci_read_config_word(cp->pdev, PCI_STATUS, &cfg);
-		netdev_err(dev, "Read PCI cfg space status [%04x]\n", cfg);
-		if (cfg & PCI_STATUS_PARITY)
-			netdev_err(dev, "PCI parity error detected\n");
-		if (cfg & PCI_STATUS_SIG_TARGET_ABORT)
-			netdev_err(dev, "PCI target abort\n");
-		if (cfg & PCI_STATUS_REC_TARGET_ABORT)
-			netdev_err(dev, "PCI master acks target abort\n");
-		if (cfg & PCI_STATUS_REC_MASTER_ABORT)
-			netdev_err(dev, "PCI master abort\n");
-		if (cfg & PCI_STATUS_SIG_SYSTEM_ERROR)
-			netdev_err(dev, "PCI system error SERR#\n");
-		if (cfg & PCI_STATUS_DETECTED_PARITY)
-			netdev_err(dev, "PCI parity error\n");
-
-		/* Write the error bits back to clear them. */
-		cfg &= (PCI_STATUS_PARITY |
-			PCI_STATUS_SIG_TARGET_ABORT |
-			PCI_STATUS_REC_TARGET_ABORT |
-			PCI_STATUS_REC_MASTER_ABORT |
-			PCI_STATUS_SIG_SYSTEM_ERROR |
-			PCI_STATUS_DETECTED_PARITY);
-		pci_write_config_word(cp->pdev, PCI_STATUS, cfg);
-	}
-
-	/* For all PCI errors, we should reset the chip. */
-	return 1;
-}
-
-/* All non-normal interrupt conditions get serviced here.
- * Returns non-zero if we should just exit the interrupt
- * handler right now (ie. if we reset the card which invalidates
- * all of the other original irq status bits).
- */
-static int cas_abnormal_irq(struct net_device *dev, struct cas *cp,
-			    u32 status)
-{
-	if (status & INTR_RX_TAG_ERROR) {
-		/* corrupt RX tag framing */
-		netif_printk(cp, rx_err, KERN_DEBUG, cp->dev,
-			     "corrupt rx tag framing\n");
-		spin_lock(&cp->stat_lock[0]);
-		cp->net_stats[0].rx_errors++;
-		spin_unlock(&cp->stat_lock[0]);
-		goto do_reset;
-	}
-
-	if (status & INTR_RX_LEN_MISMATCH) {
-		/* length mismatch. */
-		netif_printk(cp, rx_err, KERN_DEBUG, cp->dev,
-			     "length mismatch for rx frame\n");
-		spin_lock(&cp->stat_lock[0]);
-		cp->net_stats[0].rx_errors++;
-		spin_unlock(&cp->stat_lock[0]);
-		goto do_reset;
-	}
-
-	if (status & INTR_PCS_STATUS) {
-		if (cas_pcs_interrupt(dev, cp, status))
-			goto do_reset;
-	}
-
-	if (status & INTR_TX_MAC_STATUS) {
-		if (cas_txmac_interrupt(dev, cp, status))
-			goto do_reset;
-	}
-
-	if (status & INTR_RX_MAC_STATUS) {
-		if (cas_rxmac_interrupt(dev, cp, status))
-			goto do_reset;
-	}
-
-	if (status & INTR_MAC_CTRL_STATUS) {
-		if (cas_mac_interrupt(dev, cp, status))
-			goto do_reset;
-	}
-
-	if (status & INTR_MIF_STATUS) {
-		if (cas_mif_interrupt(dev, cp, status))
-			goto do_reset;
-	}
-
-	if (status & INTR_PCI_ERROR_STATUS) {
-		if (cas_pci_interrupt(dev, cp, status))
-			goto do_reset;
-	}
-	return 0;
-
-do_reset:
-#if 1
-	atomic_inc(&cp->reset_task_pending);
-	atomic_inc(&cp->reset_task_pending_all);
-	netdev_err(dev, "reset called in cas_abnormal_irq [0x%x]\n", status);
-	schedule_work(&cp->reset_task);
-#else
-	atomic_set(&cp->reset_task_pending, CAS_RESET_ALL);
-	netdev_err(dev, "reset called in cas_abnormal_irq\n");
-	schedule_work(&cp->reset_task);
-#endif
-	return 1;
-}
-
-/* NOTE: CAS_TABORT returns 1 or 2 so that it can be used when
- *       determining whether to do a netif_stop/wakeup
- */
-#define CAS_TABORT(x)      (((x)->cas_flags & CAS_FLAG_TARGET_ABORT) ? 2 : 1)
-#define CAS_ROUND_PAGE(x)  (((x) + PAGE_SIZE - 1) & PAGE_MASK)
-static inline int cas_calc_tabort(struct cas *cp, const unsigned long addr,
-				  const int len)
-{
-	unsigned long off = addr + len;
-
-	if (CAS_TABORT(cp) == 1)
-		return 0;
-	if ((CAS_ROUND_PAGE(off) - off) > TX_TARGET_ABORT_LEN)
-		return 0;
-	return TX_TARGET_ABORT_LEN;
-}
-
-static inline void cas_tx_ringN(struct cas *cp, int ring, int limit)
-{
-	struct cas_tx_desc *txds;
-	struct sk_buff **skbs;
-	struct net_device *dev = cp->dev;
-	int entry, count;
-
-	spin_lock(&cp->tx_lock[ring]);
-	txds = cp->init_txds[ring];
-	skbs = cp->tx_skbs[ring];
-	entry = cp->tx_old[ring];
-
-	count = TX_BUFF_COUNT(ring, entry, limit);
-	while (entry != limit) {
-		struct sk_buff *skb = skbs[entry];
-		dma_addr_t daddr;
-		u32 dlen;
-		int frag;
-
-		if (!skb) {
-			/* this should never occur */
-			entry = TX_DESC_NEXT(ring, entry);
-			continue;
-		}
-
-		/* however, we might get only a partial skb release. */
-		count -= skb_shinfo(skb)->nr_frags +
-			+ cp->tx_tiny_use[ring][entry].nbufs + 1;
-		if (count < 0)
-			break;
-
-		netif_printk(cp, tx_done, KERN_DEBUG, cp->dev,
-			     "tx[%d] done, slot %d\n", ring, entry);
-
-		skbs[entry] = NULL;
-		cp->tx_tiny_use[ring][entry].nbufs = 0;
-
-		for (frag = 0; frag <= skb_shinfo(skb)->nr_frags; frag++) {
-			struct cas_tx_desc *txd = txds + entry;
-
-			daddr = le64_to_cpu(txd->buffer);
-			dlen = CAS_VAL(TX_DESC_BUFLEN,
-				       le64_to_cpu(txd->control));
-			pci_unmap_page(cp->pdev, daddr, dlen,
-				       PCI_DMA_TODEVICE);
-			entry = TX_DESC_NEXT(ring, entry);
-
-			/* tiny buffer may follow */
-			if (cp->tx_tiny_use[ring][entry].used) {
-				cp->tx_tiny_use[ring][entry].used = 0;
-				entry = TX_DESC_NEXT(ring, entry);
-			}
-		}
-
-		spin_lock(&cp->stat_lock[ring]);
-		cp->net_stats[ring].tx_packets++;
-		cp->net_stats[ring].tx_bytes += skb->len;
-		spin_unlock(&cp->stat_lock[ring]);
-		dev_kfree_skb_irq(skb);
-	}
-	cp->tx_old[ring] = entry;
-
-	/* this is wrong for multiple tx rings. the net device needs
-	 * multiple queues for this to do the right thing.  we wait
-	 * for 2*packets to be available when using tiny buffers
-	 */
-	if (netif_queue_stopped(dev) &&
-	    (TX_BUFFS_AVAIL(cp, ring) > CAS_TABORT(cp)*(MAX_SKB_FRAGS + 1)))
-		netif_wake_queue(dev);
-	spin_unlock(&cp->tx_lock[ring]);
-}
-
-static void cas_tx(struct net_device *dev, struct cas *cp,
-		   u32 status)
-{
-        int limit, ring;
-#ifdef USE_TX_COMPWB
-	u64 compwb = le64_to_cpu(cp->init_block->tx_compwb);
-#endif
-	netif_printk(cp, intr, KERN_DEBUG, cp->dev,
-		     "tx interrupt, status: 0x%x, %llx\n",
-		     status, (unsigned long long)compwb);
-	/* process all the rings */
-	for (ring = 0; ring < N_TX_RINGS; ring++) {
-#ifdef USE_TX_COMPWB
-		/* use the completion writeback registers */
-		limit = (CAS_VAL(TX_COMPWB_MSB, compwb) << 8) |
-			CAS_VAL(TX_COMPWB_LSB, compwb);
-		compwb = TX_COMPWB_NEXT(compwb);
-#else
-		limit = readl(cp->regs + REG_TX_COMPN(ring));
-#endif
-		if (cp->tx_old[ring] != limit)
-			cas_tx_ringN(cp, ring, limit);
-	}
-}
-
-
-static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
-			      int entry, const u64 *words,
-			      struct sk_buff **skbref)
-{
-	int dlen, hlen, len, i, alloclen;
-	int off, swivel = RX_SWIVEL_OFF_VAL;
-	struct cas_page *page;
-	struct sk_buff *skb;
-	void *addr, *crcaddr;
-	__sum16 csum;
-	char *p;
-
-	hlen = CAS_VAL(RX_COMP2_HDR_SIZE, words[1]);
-	dlen = CAS_VAL(RX_COMP1_DATA_SIZE, words[0]);
-	len  = hlen + dlen;
-
-	if (RX_COPY_ALWAYS || (words[2] & RX_COMP3_SMALL_PKT))
-		alloclen = len;
-	else
-		alloclen = max(hlen, RX_COPY_MIN);
-
-	skb = dev_alloc_skb(alloclen + swivel + cp->crc_size);
-	if (skb == NULL)
-		return -1;
-
-	*skbref = skb;
-	skb_reserve(skb, swivel);
-
-	p = skb->data;
-	addr = crcaddr = NULL;
-	if (hlen) { /* always copy header pages */
-		i = CAS_VAL(RX_COMP2_HDR_INDEX, words[1]);
-		page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)];
-		off = CAS_VAL(RX_COMP2_HDR_OFF, words[1]) * 0x100 +
-			swivel;
-
-		i = hlen;
-		if (!dlen) /* attach FCS */
-			i += cp->crc_size;
-		pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr + off, i,
-				    PCI_DMA_FROMDEVICE);
-		addr = cas_page_map(page->buffer);
-		memcpy(p, addr + off, i);
-		pci_dma_sync_single_for_device(cp->pdev, page->dma_addr + off, i,
-				    PCI_DMA_FROMDEVICE);
-		cas_page_unmap(addr);
-		RX_USED_ADD(page, 0x100);
-		p += hlen;
-		swivel = 0;
-	}
-
-
-	if (alloclen < (hlen + dlen)) {
-		skb_frag_t *frag = skb_shinfo(skb)->frags;
-
-		/* normal or jumbo packets. we use frags */
-		i = CAS_VAL(RX_COMP1_DATA_INDEX, words[0]);
-		page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)];
-		off = CAS_VAL(RX_COMP1_DATA_OFF, words[0]) + swivel;
-
-		hlen = min(cp->page_size - off, dlen);
-		if (hlen < 0) {
-			netif_printk(cp, rx_err, KERN_DEBUG, cp->dev,
-				     "rx page overflow: %d\n", hlen);
-			dev_kfree_skb_irq(skb);
-			return -1;
-		}
-		i = hlen;
-		if (i == dlen)  /* attach FCS */
-			i += cp->crc_size;
-		pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr + off, i,
-				    PCI_DMA_FROMDEVICE);
-
-		/* make sure we always copy a header */
-		swivel = 0;
-		if (p == (char *) skb->data) { /* not split */
-			addr = cas_page_map(page->buffer);
-			memcpy(p, addr + off, RX_COPY_MIN);
-			pci_dma_sync_single_for_device(cp->pdev, page->dma_addr + off, i,
-					PCI_DMA_FROMDEVICE);
-			cas_page_unmap(addr);
-			off += RX_COPY_MIN;
-			swivel = RX_COPY_MIN;
-			RX_USED_ADD(page, cp->mtu_stride);
-		} else {
-			RX_USED_ADD(page, hlen);
-		}
-		skb_put(skb, alloclen);
-
-		skb_shinfo(skb)->nr_frags++;
-		skb->data_len += hlen - swivel;
-		skb->truesize += hlen - swivel;
-		skb->len      += hlen - swivel;
-
-		get_page(page->buffer);
-		frag->page = page->buffer;
-		frag->page_offset = off;
-		frag->size = hlen - swivel;
-
-		/* any more data? */
-		if ((words[0] & RX_COMP1_SPLIT_PKT) && ((dlen -= hlen) > 0)) {
-			hlen = dlen;
-			off = 0;
-
-			i = CAS_VAL(RX_COMP2_NEXT_INDEX, words[1]);
-			page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)];
-			pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr,
-					    hlen + cp->crc_size,
-					    PCI_DMA_FROMDEVICE);
-			pci_dma_sync_single_for_device(cp->pdev, page->dma_addr,
-					    hlen + cp->crc_size,
-					    PCI_DMA_FROMDEVICE);
-
-			skb_shinfo(skb)->nr_frags++;
-			skb->data_len += hlen;
-			skb->len      += hlen;
-			frag++;
-
-			get_page(page->buffer);
-			frag->page = page->buffer;
-			frag->page_offset = 0;
-			frag->size = hlen;
-			RX_USED_ADD(page, hlen + cp->crc_size);
-		}
-
-		if (cp->crc_size) {
-			addr = cas_page_map(page->buffer);
-			crcaddr  = addr + off + hlen;
-		}
-
-	} else {
-		/* copying packet */
-		if (!dlen)
-			goto end_copy_pkt;
-
-		i = CAS_VAL(RX_COMP1_DATA_INDEX, words[0]);
-		page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)];
-		off = CAS_VAL(RX_COMP1_DATA_OFF, words[0]) + swivel;
-		hlen = min(cp->page_size - off, dlen);
-		if (hlen < 0) {
-			netif_printk(cp, rx_err, KERN_DEBUG, cp->dev,
-				     "rx page overflow: %d\n", hlen);
-			dev_kfree_skb_irq(skb);
-			return -1;
-		}
-		i = hlen;
-		if (i == dlen) /* attach FCS */
-			i += cp->crc_size;
-		pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr + off, i,
-				    PCI_DMA_FROMDEVICE);
-		addr = cas_page_map(page->buffer);
-		memcpy(p, addr + off, i);
-		pci_dma_sync_single_for_device(cp->pdev, page->dma_addr + off, i,
-				    PCI_DMA_FROMDEVICE);
-		cas_page_unmap(addr);
-		if (p == (char *) skb->data) /* not split */
-			RX_USED_ADD(page, cp->mtu_stride);
-		else
-			RX_USED_ADD(page, i);
-
-		/* any more data? */
-		if ((words[0] & RX_COMP1_SPLIT_PKT) && ((dlen -= hlen) > 0)) {
-			p += hlen;
-			i = CAS_VAL(RX_COMP2_NEXT_INDEX, words[1]);
-			page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)];
-			pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr,
-					    dlen + cp->crc_size,
-					    PCI_DMA_FROMDEVICE);
-			addr = cas_page_map(page->buffer);
-			memcpy(p, addr, dlen + cp->crc_size);
-			pci_dma_sync_single_for_device(cp->pdev, page->dma_addr,
-					    dlen + cp->crc_size,
-					    PCI_DMA_FROMDEVICE);
-			cas_page_unmap(addr);
-			RX_USED_ADD(page, dlen + cp->crc_size);
-		}
-end_copy_pkt:
-		if (cp->crc_size) {
-			addr    = NULL;
-			crcaddr = skb->data + alloclen;
-		}
-		skb_put(skb, alloclen);
-	}
-
-	csum = (__force __sum16)htons(CAS_VAL(RX_COMP4_TCP_CSUM, words[3]));
-	if (cp->crc_size) {
-		/* checksum includes FCS. strip it out. */
-		csum = csum_fold(csum_partial(crcaddr, cp->crc_size,
-					      csum_unfold(csum)));
-		if (addr)
-			cas_page_unmap(addr);
-	}
-	skb->protocol = eth_type_trans(skb, cp->dev);
-	if (skb->protocol == htons(ETH_P_IP)) {
-		skb->csum = csum_unfold(~csum);
-		skb->ip_summed = CHECKSUM_COMPLETE;
-	} else
-		skb_checksum_none_assert(skb);
-	return len;
-}
-
-
-/* we can handle up to 64 rx flows at a time. we do the same thing
- * as nonreassm except that we batch up the buffers.
- * NOTE: we currently just treat each flow as a bunch of packets that
- *       we pass up. a better way would be to coalesce the packets
- *       into a jumbo packet. to do that, we need to do the following:
- *       1) the first packet will have a clean split between header and
- *          data. save both.
- *       2) each time the next flow packet comes in, extend the
- *          data length and merge the checksums.
- *       3) on flow release, fix up the header.
- *       4) make sure the higher layer doesn't care.
- * because packets get coalesced, we shouldn't run into fragment count
- * issues.
- */
-static inline void cas_rx_flow_pkt(struct cas *cp, const u64 *words,
-				   struct sk_buff *skb)
-{
-	int flowid = CAS_VAL(RX_COMP3_FLOWID, words[2]) & (N_RX_FLOWS - 1);
-	struct sk_buff_head *flow = &cp->rx_flows[flowid];
-
-	/* this is protected at a higher layer, so no need to
-	 * do any additional locking here. stick the buffer
-	 * at the end.
-	 */
-	__skb_queue_tail(flow, skb);
-	if (words[0] & RX_COMP1_RELEASE_FLOW) {
-		while ((skb = __skb_dequeue(flow))) {
-			cas_skb_release(skb);
-		}
-	}
-}
-
-/* put rx descriptor back on ring. if a buffer is in use by a higher
- * layer, this will need to put in a replacement.
- */
-static void cas_post_page(struct cas *cp, const int ring, const int index)
-{
-	cas_page_t *new;
-	int entry;
-
-	entry = cp->rx_old[ring];
-
-	new = cas_page_swap(cp, ring, index);
-	cp->init_rxds[ring][entry].buffer = cpu_to_le64(new->dma_addr);
-	cp->init_rxds[ring][entry].index  =
-		cpu_to_le64(CAS_BASE(RX_INDEX_NUM, index) |
-			    CAS_BASE(RX_INDEX_RING, ring));
-
-	entry = RX_DESC_ENTRY(ring, entry + 1);
-	cp->rx_old[ring] = entry;
-
-	if (entry % 4)
-		return;
-
-	if (ring == 0)
-		writel(entry, cp->regs + REG_RX_KICK);
-	else if ((N_RX_DESC_RINGS > 1) &&
-		 (cp->cas_flags & CAS_FLAG_REG_PLUS))
-		writel(entry, cp->regs + REG_PLUS_RX_KICK1);
-}
-
-
-/* only when things are bad */
-static int cas_post_rxds_ringN(struct cas *cp, int ring, int num)
-{
-	unsigned int entry, last, count, released;
-	int cluster;
-	cas_page_t **page = cp->rx_pages[ring];
-
-	entry = cp->rx_old[ring];
-
-	netif_printk(cp, intr, KERN_DEBUG, cp->dev,
-		     "rxd[%d] interrupt, done: %d\n", ring, entry);
-
-	cluster = -1;
-	count = entry & 0x3;
-	last = RX_DESC_ENTRY(ring, num ? entry + num - 4: entry - 4);
-	released = 0;
-	while (entry != last) {
-		/* make a new buffer if it's still in use */
-		if (page_count(page[entry]->buffer) > 1) {
-			cas_page_t *new = cas_page_dequeue(cp);
-			if (!new) {
-				/* let the timer know that we need to
-				 * do this again
-				 */
-				cp->cas_flags |= CAS_FLAG_RXD_POST(ring);
-				if (!timer_pending(&cp->link_timer))
-					mod_timer(&cp->link_timer, jiffies +
-						  CAS_LINK_FAST_TIMEOUT);
-				cp->rx_old[ring]  = entry;
-				cp->rx_last[ring] = num ? num - released : 0;
-				return -ENOMEM;
-			}
-			spin_lock(&cp->rx_inuse_lock);
-			list_add(&page[entry]->list, &cp->rx_inuse_list);
-			spin_unlock(&cp->rx_inuse_lock);
-			cp->init_rxds[ring][entry].buffer =
-				cpu_to_le64(new->dma_addr);
-			page[entry] = new;
-
-		}
-
-		if (++count == 4) {
-			cluster = entry;
-			count = 0;
-		}
-		released++;
-		entry = RX_DESC_ENTRY(ring, entry + 1);
-	}
-	cp->rx_old[ring] = entry;
-
-	if (cluster < 0)
-		return 0;
-
-	if (ring == 0)
-		writel(cluster, cp->regs + REG_RX_KICK);
-	else if ((N_RX_DESC_RINGS > 1) &&
-		 (cp->cas_flags & CAS_FLAG_REG_PLUS))
-		writel(cluster, cp->regs + REG_PLUS_RX_KICK1);
-	return 0;
-}
-
-
-/* process a completion ring. packets are set up in three basic ways:
- * small packets: should be copied header + data in single buffer.
- * large packets: header and data in a single buffer.
- * split packets: header in a separate buffer from data.
- *                data may be in multiple pages. data may be > 256
- *                bytes but in a single page.
- *
- * NOTE: RX page posting is done in this routine as well. while there's
- *       the capability of using multiple RX completion rings, it isn't
- *       really worthwhile due to the fact that the page posting will
- *       force serialization on the single descriptor ring.
- */
-static int cas_rx_ringN(struct cas *cp, int ring, int budget)
-{
-	struct cas_rx_comp *rxcs = cp->init_rxcs[ring];
-	int entry, drops;
-	int npackets = 0;
-
-	netif_printk(cp, intr, KERN_DEBUG, cp->dev,
-		     "rx[%d] interrupt, done: %d/%d\n",
-		     ring,
-		     readl(cp->regs + REG_RX_COMP_HEAD), cp->rx_new[ring]);
-
-	entry = cp->rx_new[ring];
-	drops = 0;
-	while (1) {
-		struct cas_rx_comp *rxc = rxcs + entry;
-		struct sk_buff *uninitialized_var(skb);
-		int type, len;
-		u64 words[4];
-		int i, dring;
-
-		words[0] = le64_to_cpu(rxc->word1);
-		words[1] = le64_to_cpu(rxc->word2);
-		words[2] = le64_to_cpu(rxc->word3);
-		words[3] = le64_to_cpu(rxc->word4);
-
-		/* don't touch if still owned by hw */
-		type = CAS_VAL(RX_COMP1_TYPE, words[0]);
-		if (type == 0)
-			break;
-
-		/* hw hasn't cleared the zero bit yet */
-		if (words[3] & RX_COMP4_ZERO) {
-			break;
-		}
-
-		/* get info on the packet */
-		if (words[3] & (RX_COMP4_LEN_MISMATCH | RX_COMP4_BAD)) {
-			spin_lock(&cp->stat_lock[ring]);
-			cp->net_stats[ring].rx_errors++;
-			if (words[3] & RX_COMP4_LEN_MISMATCH)
-				cp->net_stats[ring].rx_length_errors++;
-			if (words[3] & RX_COMP4_BAD)
-				cp->net_stats[ring].rx_crc_errors++;
-			spin_unlock(&cp->stat_lock[ring]);
-
-			/* We'll just return it to Cassini. */
-		drop_it:
-			spin_lock(&cp->stat_lock[ring]);
-			++cp->net_stats[ring].rx_dropped;
-			spin_unlock(&cp->stat_lock[ring]);
-			goto next;
-		}
-
-		len = cas_rx_process_pkt(cp, rxc, entry, words, &skb);
-		if (len < 0) {
-			++drops;
-			goto drop_it;
-		}
-
-		/* see if it's a flow re-assembly or not. the driver
-		 * itself handles release back up.
-		 */
-		if (RX_DONT_BATCH || (type == 0x2)) {
-			/* non-reassm: these always get released */
-			cas_skb_release(skb);
-		} else {
-			cas_rx_flow_pkt(cp, words, skb);
-		}
-
-		spin_lock(&cp->stat_lock[ring]);
-		cp->net_stats[ring].rx_packets++;
-		cp->net_stats[ring].rx_bytes += len;
-		spin_unlock(&cp->stat_lock[ring]);
-
-	next:
-		npackets++;
-
-		/* should it be released? */
-		if (words[0] & RX_COMP1_RELEASE_HDR) {
-			i = CAS_VAL(RX_COMP2_HDR_INDEX, words[1]);
-			dring = CAS_VAL(RX_INDEX_RING, i);
-			i = CAS_VAL(RX_INDEX_NUM, i);
-			cas_post_page(cp, dring, i);
-		}
-
-		if (words[0] & RX_COMP1_RELEASE_DATA) {
-			i = CAS_VAL(RX_COMP1_DATA_INDEX, words[0]);
-			dring = CAS_VAL(RX_INDEX_RING, i);
-			i = CAS_VAL(RX_INDEX_NUM, i);
-			cas_post_page(cp, dring, i);
-		}
-
-		if (words[0] & RX_COMP1_RELEASE_NEXT) {
-			i = CAS_VAL(RX_COMP2_NEXT_INDEX, words[1]);
-			dring = CAS_VAL(RX_INDEX_RING, i);
-			i = CAS_VAL(RX_INDEX_NUM, i);
-			cas_post_page(cp, dring, i);
-		}
-
-		/* skip to the next entry */
-		entry = RX_COMP_ENTRY(ring, entry + 1 +
-				      CAS_VAL(RX_COMP1_SKIP, words[0]));
-#ifdef USE_NAPI
-		if (budget && (npackets >= budget))
-			break;
-#endif
-	}
-	cp->rx_new[ring] = entry;
-
-	if (drops)
-		netdev_info(cp->dev, "Memory squeeze, deferring packet\n");
-	return npackets;
-}
-
-
-/* put completion entries back on the ring */
-static void cas_post_rxcs_ringN(struct net_device *dev,
-				struct cas *cp, int ring)
-{
-	struct cas_rx_comp *rxc = cp->init_rxcs[ring];
-	int last, entry;
-
-	last = cp->rx_cur[ring];
-	entry = cp->rx_new[ring];
-	netif_printk(cp, intr, KERN_DEBUG, dev,
-		     "rxc[%d] interrupt, done: %d/%d\n",
-		     ring, readl(cp->regs + REG_RX_COMP_HEAD), entry);
-
-	/* zero and re-mark descriptors */
-	while (last != entry) {
-		cas_rxc_init(rxc + last);
-		last = RX_COMP_ENTRY(ring, last + 1);
-	}
-	cp->rx_cur[ring] = last;
-
-	if (ring == 0)
-		writel(last, cp->regs + REG_RX_COMP_TAIL);
-	else if (cp->cas_flags & CAS_FLAG_REG_PLUS)
-		writel(last, cp->regs + REG_PLUS_RX_COMPN_TAIL(ring));
-}
-
-
-
-/* cassini can use all four PCI interrupts for the completion ring.
- * rings 3 and 4 are identical
- */
-#if defined(USE_PCI_INTC) || defined(USE_PCI_INTD)
-static inline void cas_handle_irqN(struct net_device *dev,
-				   struct cas *cp, const u32 status,
-				   const int ring)
-{
-	if (status & (INTR_RX_COMP_FULL_ALT | INTR_RX_COMP_AF_ALT))
-		cas_post_rxcs_ringN(dev, cp, ring);
-}
-
-static irqreturn_t cas_interruptN(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct cas *cp = netdev_priv(dev);
-	unsigned long flags;
-	int ring = (irq == cp->pci_irq_INTC) ? 2 : 3;
-	u32 status = readl(cp->regs + REG_PLUS_INTRN_STATUS(ring));
-
-	/* check for shared irq */
-	if (status == 0)
-		return IRQ_NONE;
-
-	spin_lock_irqsave(&cp->lock, flags);
-	if (status & INTR_RX_DONE_ALT) { /* handle rx separately */
-#ifdef USE_NAPI
-		cas_mask_intr(cp);
-		napi_schedule(&cp->napi);
-#else
-		cas_rx_ringN(cp, ring, 0);
-#endif
-		status &= ~INTR_RX_DONE_ALT;
-	}
-
-	if (status)
-		cas_handle_irqN(dev, cp, status, ring);
-	spin_unlock_irqrestore(&cp->lock, flags);
-	return IRQ_HANDLED;
-}
-#endif
-
-#ifdef USE_PCI_INTB
-/* everything but rx packets */
-static inline void cas_handle_irq1(struct cas *cp, const u32 status)
-{
-	if (status & INTR_RX_BUF_UNAVAIL_1) {
-		/* Frame arrived, no free RX buffers available.
-		 * NOTE: we can get this on a link transition. */
-		cas_post_rxds_ringN(cp, 1, 0);
-		spin_lock(&cp->stat_lock[1]);
-		cp->net_stats[1].rx_dropped++;
-		spin_unlock(&cp->stat_lock[1]);
-	}
-
-	if (status & INTR_RX_BUF_AE_1)
-		cas_post_rxds_ringN(cp, 1, RX_DESC_RINGN_SIZE(1) -
-				    RX_AE_FREEN_VAL(1));
-
-	if (status & (INTR_RX_COMP_AF | INTR_RX_COMP_FULL))
-		cas_post_rxcs_ringN(cp, 1);
-}
-
-/* ring 2 handles a few more events than 3 and 4 */
-static irqreturn_t cas_interrupt1(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct cas *cp = netdev_priv(dev);
-	unsigned long flags;
-	u32 status = readl(cp->regs + REG_PLUS_INTRN_STATUS(1));
-
-	/* check for shared interrupt */
-	if (status == 0)
-		return IRQ_NONE;
-
-	spin_lock_irqsave(&cp->lock, flags);
-	if (status & INTR_RX_DONE_ALT) { /* handle rx separately */
-#ifdef USE_NAPI
-		cas_mask_intr(cp);
-		napi_schedule(&cp->napi);
-#else
-		cas_rx_ringN(cp, 1, 0);
-#endif
-		status &= ~INTR_RX_DONE_ALT;
-	}
-	if (status)
-		cas_handle_irq1(cp, status);
-	spin_unlock_irqrestore(&cp->lock, flags);
-	return IRQ_HANDLED;
-}
-#endif
-
-static inline void cas_handle_irq(struct net_device *dev,
-				  struct cas *cp, const u32 status)
-{
-	/* housekeeping interrupts */
-	if (status & INTR_ERROR_MASK)
-		cas_abnormal_irq(dev, cp, status);
-
-	if (status & INTR_RX_BUF_UNAVAIL) {
-		/* Frame arrived, no free RX buffers available.
-		 * NOTE: we can get this on a link transition.
-		 */
-		cas_post_rxds_ringN(cp, 0, 0);
-		spin_lock(&cp->stat_lock[0]);
-		cp->net_stats[0].rx_dropped++;
-		spin_unlock(&cp->stat_lock[0]);
-	} else if (status & INTR_RX_BUF_AE) {
-		cas_post_rxds_ringN(cp, 0, RX_DESC_RINGN_SIZE(0) -
-				    RX_AE_FREEN_VAL(0));
-	}
-
-	if (status & (INTR_RX_COMP_AF | INTR_RX_COMP_FULL))
-		cas_post_rxcs_ringN(dev, cp, 0);
-}
-
-static irqreturn_t cas_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct cas *cp = netdev_priv(dev);
-	unsigned long flags;
-	u32 status = readl(cp->regs + REG_INTR_STATUS);
-
-	if (status == 0)
-		return IRQ_NONE;
-
-	spin_lock_irqsave(&cp->lock, flags);
-	if (status & (INTR_TX_ALL | INTR_TX_INTME)) {
-		cas_tx(dev, cp, status);
-		status &= ~(INTR_TX_ALL | INTR_TX_INTME);
-	}
-
-	if (status & INTR_RX_DONE) {
-#ifdef USE_NAPI
-		cas_mask_intr(cp);
-		napi_schedule(&cp->napi);
-#else
-		cas_rx_ringN(cp, 0, 0);
-#endif
-		status &= ~INTR_RX_DONE;
-	}
-
-	if (status)
-		cas_handle_irq(dev, cp, status);
-	spin_unlock_irqrestore(&cp->lock, flags);
-	return IRQ_HANDLED;
-}
-
-
-#ifdef USE_NAPI
-static int cas_poll(struct napi_struct *napi, int budget)
-{
-	struct cas *cp = container_of(napi, struct cas, napi);
-	struct net_device *dev = cp->dev;
-	int i, enable_intr, credits;
-	u32 status = readl(cp->regs + REG_INTR_STATUS);
-	unsigned long flags;
-
-	spin_lock_irqsave(&cp->lock, flags);
-	cas_tx(dev, cp, status);
-	spin_unlock_irqrestore(&cp->lock, flags);
-
-	/* NAPI rx packets. we spread the credits across all of the
-	 * rxc rings
-	 *
-	 * to make sure we're fair with the work we loop through each
-	 * ring N_RX_COMP_RING times with a request of
-	 * budget / N_RX_COMP_RINGS
-	 */
-	enable_intr = 1;
-	credits = 0;
-	for (i = 0; i < N_RX_COMP_RINGS; i++) {
-		int j;
-		for (j = 0; j < N_RX_COMP_RINGS; j++) {
-			credits += cas_rx_ringN(cp, j, budget / N_RX_COMP_RINGS);
-			if (credits >= budget) {
-				enable_intr = 0;
-				goto rx_comp;
-			}
-		}
-	}
-
-rx_comp:
-	/* final rx completion */
-	spin_lock_irqsave(&cp->lock, flags);
-	if (status)
-		cas_handle_irq(dev, cp, status);
-
-#ifdef USE_PCI_INTB
-	if (N_RX_COMP_RINGS > 1) {
-		status = readl(cp->regs + REG_PLUS_INTRN_STATUS(1));
-		if (status)
-			cas_handle_irq1(dev, cp, status);
-	}
-#endif
-
-#ifdef USE_PCI_INTC
-	if (N_RX_COMP_RINGS > 2) {
-		status = readl(cp->regs + REG_PLUS_INTRN_STATUS(2));
-		if (status)
-			cas_handle_irqN(dev, cp, status, 2);
-	}
-#endif
-
-#ifdef USE_PCI_INTD
-	if (N_RX_COMP_RINGS > 3) {
-		status = readl(cp->regs + REG_PLUS_INTRN_STATUS(3));
-		if (status)
-			cas_handle_irqN(dev, cp, status, 3);
-	}
-#endif
-	spin_unlock_irqrestore(&cp->lock, flags);
-	if (enable_intr) {
-		napi_complete(napi);
-		cas_unmask_intr(cp);
-	}
-	return credits;
-}
-#endif
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void cas_netpoll(struct net_device *dev)
-{
-	struct cas *cp = netdev_priv(dev);
-
-	cas_disable_irq(cp, 0);
-	cas_interrupt(cp->pdev->irq, dev);
-	cas_enable_irq(cp, 0);
-
-#ifdef USE_PCI_INTB
-	if (N_RX_COMP_RINGS > 1) {
-		/* cas_interrupt1(); */
-	}
-#endif
-#ifdef USE_PCI_INTC
-	if (N_RX_COMP_RINGS > 2) {
-		/* cas_interruptN(); */
-	}
-#endif
-#ifdef USE_PCI_INTD
-	if (N_RX_COMP_RINGS > 3) {
-		/* cas_interruptN(); */
-	}
-#endif
-}
-#endif
-
-static void cas_tx_timeout(struct net_device *dev)
-{
-	struct cas *cp = netdev_priv(dev);
-
-	netdev_err(dev, "transmit timed out, resetting\n");
-	if (!cp->hw_running) {
-		netdev_err(dev, "hrm.. hw not running!\n");
-		return;
-	}
-
-	netdev_err(dev, "MIF_STATE[%08x]\n",
-		   readl(cp->regs + REG_MIF_STATE_MACHINE));
-
-	netdev_err(dev, "MAC_STATE[%08x]\n",
-		   readl(cp->regs + REG_MAC_STATE_MACHINE));
-
-	netdev_err(dev, "TX_STATE[%08x:%08x:%08x] FIFO[%08x:%08x:%08x] SM1[%08x] SM2[%08x]\n",
-		   readl(cp->regs + REG_TX_CFG),
-		   readl(cp->regs + REG_MAC_TX_STATUS),
-		   readl(cp->regs + REG_MAC_TX_CFG),
-		   readl(cp->regs + REG_TX_FIFO_PKT_CNT),
-		   readl(cp->regs + REG_TX_FIFO_WRITE_PTR),
-		   readl(cp->regs + REG_TX_FIFO_READ_PTR),
-		   readl(cp->regs + REG_TX_SM_1),
-		   readl(cp->regs + REG_TX_SM_2));
-
-	netdev_err(dev, "RX_STATE[%08x:%08x:%08x]\n",
-		   readl(cp->regs + REG_RX_CFG),
-		   readl(cp->regs + REG_MAC_RX_STATUS),
-		   readl(cp->regs + REG_MAC_RX_CFG));
-
-	netdev_err(dev, "HP_STATE[%08x:%08x:%08x:%08x]\n",
-		   readl(cp->regs + REG_HP_STATE_MACHINE),
-		   readl(cp->regs + REG_HP_STATUS0),
-		   readl(cp->regs + REG_HP_STATUS1),
-		   readl(cp->regs + REG_HP_STATUS2));
-
-#if 1
-	atomic_inc(&cp->reset_task_pending);
-	atomic_inc(&cp->reset_task_pending_all);
-	schedule_work(&cp->reset_task);
-#else
-	atomic_set(&cp->reset_task_pending, CAS_RESET_ALL);
-	schedule_work(&cp->reset_task);
-#endif
-}
-
-static inline int cas_intme(int ring, int entry)
-{
-	/* Algorithm: IRQ every 1/2 of descriptors. */
-	if (!(entry & ((TX_DESC_RINGN_SIZE(ring) >> 1) - 1)))
-		return 1;
-	return 0;
-}
-
-
-static void cas_write_txd(struct cas *cp, int ring, int entry,
-			  dma_addr_t mapping, int len, u64 ctrl, int last)
-{
-	struct cas_tx_desc *txd = cp->init_txds[ring] + entry;
-
-	ctrl |= CAS_BASE(TX_DESC_BUFLEN, len);
-	if (cas_intme(ring, entry))
-		ctrl |= TX_DESC_INTME;
-	if (last)
-		ctrl |= TX_DESC_EOF;
-	txd->control = cpu_to_le64(ctrl);
-	txd->buffer = cpu_to_le64(mapping);
-}
-
-static inline void *tx_tiny_buf(struct cas *cp, const int ring,
-				const int entry)
-{
-	return cp->tx_tiny_bufs[ring] + TX_TINY_BUF_LEN*entry;
-}
-
-static inline dma_addr_t tx_tiny_map(struct cas *cp, const int ring,
-				     const int entry, const int tentry)
-{
-	cp->tx_tiny_use[ring][tentry].nbufs++;
-	cp->tx_tiny_use[ring][entry].used = 1;
-	return cp->tx_tiny_dvma[ring] + TX_TINY_BUF_LEN*entry;
-}
-
-static inline int cas_xmit_tx_ringN(struct cas *cp, int ring,
-				    struct sk_buff *skb)
-{
-	struct net_device *dev = cp->dev;
-	int entry, nr_frags, frag, tabort, tentry;
-	dma_addr_t mapping;
-	unsigned long flags;
-	u64 ctrl;
-	u32 len;
-
-	spin_lock_irqsave(&cp->tx_lock[ring], flags);
-
-	/* This is a hard error, log it. */
-	if (TX_BUFFS_AVAIL(cp, ring) <=
-	    CAS_TABORT(cp)*(skb_shinfo(skb)->nr_frags + 1)) {
-		netif_stop_queue(dev);
-		spin_unlock_irqrestore(&cp->tx_lock[ring], flags);
-		netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
-		return 1;
-	}
-
-	ctrl = 0;
-	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		const u64 csum_start_off = skb_checksum_start_offset(skb);
-		const u64 csum_stuff_off = csum_start_off + skb->csum_offset;
-
-		ctrl =  TX_DESC_CSUM_EN |
-			CAS_BASE(TX_DESC_CSUM_START, csum_start_off) |
-			CAS_BASE(TX_DESC_CSUM_STUFF, csum_stuff_off);
-	}
-
-	entry = cp->tx_new[ring];
-	cp->tx_skbs[ring][entry] = skb;
-
-	nr_frags = skb_shinfo(skb)->nr_frags;
-	len = skb_headlen(skb);
-	mapping = pci_map_page(cp->pdev, virt_to_page(skb->data),
-			       offset_in_page(skb->data), len,
-			       PCI_DMA_TODEVICE);
-
-	tentry = entry;
-	tabort = cas_calc_tabort(cp, (unsigned long) skb->data, len);
-	if (unlikely(tabort)) {
-		/* NOTE: len is always >  tabort */
-		cas_write_txd(cp, ring, entry, mapping, len - tabort,
-			      ctrl | TX_DESC_SOF, 0);
-		entry = TX_DESC_NEXT(ring, entry);
-
-		skb_copy_from_linear_data_offset(skb, len - tabort,
-			      tx_tiny_buf(cp, ring, entry), tabort);
-		mapping = tx_tiny_map(cp, ring, entry, tentry);
-		cas_write_txd(cp, ring, entry, mapping, tabort, ctrl,
-			      (nr_frags == 0));
-	} else {
-		cas_write_txd(cp, ring, entry, mapping, len, ctrl |
-			      TX_DESC_SOF, (nr_frags == 0));
-	}
-	entry = TX_DESC_NEXT(ring, entry);
-
-	for (frag = 0; frag < nr_frags; frag++) {
-		skb_frag_t *fragp = &skb_shinfo(skb)->frags[frag];
-
-		len = fragp->size;
-		mapping = pci_map_page(cp->pdev, fragp->page,
-				       fragp->page_offset, len,
-				       PCI_DMA_TODEVICE);
-
-		tabort = cas_calc_tabort(cp, fragp->page_offset, len);
-		if (unlikely(tabort)) {
-			void *addr;
-
-			/* NOTE: len is always > tabort */
-			cas_write_txd(cp, ring, entry, mapping, len - tabort,
-				      ctrl, 0);
-			entry = TX_DESC_NEXT(ring, entry);
-
-			addr = cas_page_map(fragp->page);
-			memcpy(tx_tiny_buf(cp, ring, entry),
-			       addr + fragp->page_offset + len - tabort,
-			       tabort);
-			cas_page_unmap(addr);
-			mapping = tx_tiny_map(cp, ring, entry, tentry);
-			len     = tabort;
-		}
-
-		cas_write_txd(cp, ring, entry, mapping, len, ctrl,
-			      (frag + 1 == nr_frags));
-		entry = TX_DESC_NEXT(ring, entry);
-	}
-
-	cp->tx_new[ring] = entry;
-	if (TX_BUFFS_AVAIL(cp, ring) <= CAS_TABORT(cp)*(MAX_SKB_FRAGS + 1))
-		netif_stop_queue(dev);
-
-	netif_printk(cp, tx_queued, KERN_DEBUG, dev,
-		     "tx[%d] queued, slot %d, skblen %d, avail %d\n",
-		     ring, entry, skb->len, TX_BUFFS_AVAIL(cp, ring));
-	writel(entry, cp->regs + REG_TX_KICKN(ring));
-	spin_unlock_irqrestore(&cp->tx_lock[ring], flags);
-	return 0;
-}
-
-static netdev_tx_t cas_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct cas *cp = netdev_priv(dev);
-
-	/* this is only used as a load-balancing hint, so it doesn't
-	 * need to be SMP safe
-	 */
-	static int ring;
-
-	if (skb_padto(skb, cp->min_frame_size))
-		return NETDEV_TX_OK;
-
-	/* XXX: we need some higher-level QoS hooks to steer packets to
-	 *      individual queues.
-	 */
-	if (cas_xmit_tx_ringN(cp, ring++ & N_TX_RINGS_MASK, skb))
-		return NETDEV_TX_BUSY;
-	return NETDEV_TX_OK;
-}
-
-static void cas_init_tx_dma(struct cas *cp)
-{
-	u64 desc_dma = cp->block_dvma;
-	unsigned long off;
-	u32 val;
-	int i;
-
-	/* set up tx completion writeback registers. must be 8-byte aligned */
-#ifdef USE_TX_COMPWB
-	off = offsetof(struct cas_init_block, tx_compwb);
-	writel((desc_dma + off) >> 32, cp->regs + REG_TX_COMPWB_DB_HI);
-	writel((desc_dma + off) & 0xffffffff, cp->regs + REG_TX_COMPWB_DB_LOW);
-#endif
-
-	/* enable completion writebacks, enable paced mode,
-	 * disable read pipe, and disable pre-interrupt compwbs
-	 */
-	val =   TX_CFG_COMPWB_Q1 | TX_CFG_COMPWB_Q2 |
-		TX_CFG_COMPWB_Q3 | TX_CFG_COMPWB_Q4 |
-		TX_CFG_DMA_RDPIPE_DIS | TX_CFG_PACED_MODE |
-		TX_CFG_INTR_COMPWB_DIS;
-
-	/* write out tx ring info and tx desc bases */
-	for (i = 0; i < MAX_TX_RINGS; i++) {
-		off = (unsigned long) cp->init_txds[i] -
-			(unsigned long) cp->init_block;
-
-		val |= CAS_TX_RINGN_BASE(i);
-		writel((desc_dma + off) >> 32, cp->regs + REG_TX_DBN_HI(i));
-		writel((desc_dma + off) & 0xffffffff, cp->regs +
-		       REG_TX_DBN_LOW(i));
-		/* don't zero out the kick register here as the system
-		 * will wedge
-		 */
-	}
-	writel(val, cp->regs + REG_TX_CFG);
-
-	/* program max burst sizes. these numbers should be different
-	 * if doing QoS.
-	 */
-#ifdef USE_QOS
-	writel(0x800, cp->regs + REG_TX_MAXBURST_0);
-	writel(0x1600, cp->regs + REG_TX_MAXBURST_1);
-	writel(0x2400, cp->regs + REG_TX_MAXBURST_2);
-	writel(0x4800, cp->regs + REG_TX_MAXBURST_3);
-#else
-	writel(0x800, cp->regs + REG_TX_MAXBURST_0);
-	writel(0x800, cp->regs + REG_TX_MAXBURST_1);
-	writel(0x800, cp->regs + REG_TX_MAXBURST_2);
-	writel(0x800, cp->regs + REG_TX_MAXBURST_3);
-#endif
-}
-
-/* Must be invoked under cp->lock. */
-static inline void cas_init_dma(struct cas *cp)
-{
-	cas_init_tx_dma(cp);
-	cas_init_rx_dma(cp);
-}
-
-static void cas_process_mc_list(struct cas *cp)
-{
-	u16 hash_table[16];
-	u32 crc;
-	struct netdev_hw_addr *ha;
-	int i = 1;
-
-	memset(hash_table, 0, sizeof(hash_table));
-	netdev_for_each_mc_addr(ha, cp->dev) {
-		if (i <= CAS_MC_EXACT_MATCH_SIZE) {
-			/* use the alternate mac address registers for the
-			 * first 15 multicast addresses
-			 */
-			writel((ha->addr[4] << 8) | ha->addr[5],
-			       cp->regs + REG_MAC_ADDRN(i*3 + 0));
-			writel((ha->addr[2] << 8) | ha->addr[3],
-			       cp->regs + REG_MAC_ADDRN(i*3 + 1));
-			writel((ha->addr[0] << 8) | ha->addr[1],
-			       cp->regs + REG_MAC_ADDRN(i*3 + 2));
-			i++;
-		}
-		else {
-			/* use hw hash table for the next series of
-			 * multicast addresses
-			 */
-			crc = ether_crc_le(ETH_ALEN, ha->addr);
-			crc >>= 24;
-			hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
-		}
-	}
-	for (i = 0; i < 16; i++)
-		writel(hash_table[i], cp->regs + REG_MAC_HASH_TABLEN(i));
-}
-
-/* Must be invoked under cp->lock. */
-static u32 cas_setup_multicast(struct cas *cp)
-{
-	u32 rxcfg = 0;
-	int i;
-
-	if (cp->dev->flags & IFF_PROMISC) {
-		rxcfg |= MAC_RX_CFG_PROMISC_EN;
-
-	} else if (cp->dev->flags & IFF_ALLMULTI) {
-	    	for (i=0; i < 16; i++)
-			writel(0xFFFF, cp->regs + REG_MAC_HASH_TABLEN(i));
-		rxcfg |= MAC_RX_CFG_HASH_FILTER_EN;
-
-	} else {
-		cas_process_mc_list(cp);
-		rxcfg |= MAC_RX_CFG_HASH_FILTER_EN;
-	}
-
-	return rxcfg;
-}
-
-/* must be invoked under cp->stat_lock[N_TX_RINGS] */
-static void cas_clear_mac_err(struct cas *cp)
-{
-	writel(0, cp->regs + REG_MAC_COLL_NORMAL);
-	writel(0, cp->regs + REG_MAC_COLL_FIRST);
-	writel(0, cp->regs + REG_MAC_COLL_EXCESS);
-	writel(0, cp->regs + REG_MAC_COLL_LATE);
-	writel(0, cp->regs + REG_MAC_TIMER_DEFER);
-	writel(0, cp->regs + REG_MAC_ATTEMPTS_PEAK);
-	writel(0, cp->regs + REG_MAC_RECV_FRAME);
-	writel(0, cp->regs + REG_MAC_LEN_ERR);
-	writel(0, cp->regs + REG_MAC_ALIGN_ERR);
-	writel(0, cp->regs + REG_MAC_FCS_ERR);
-	writel(0, cp->regs + REG_MAC_RX_CODE_ERR);
-}
-
-
-static void cas_mac_reset(struct cas *cp)
-{
-	int i;
-
-	/* do both TX and RX reset */
-	writel(0x1, cp->regs + REG_MAC_TX_RESET);
-	writel(0x1, cp->regs + REG_MAC_RX_RESET);
-
-	/* wait for TX */
-	i = STOP_TRIES;
-	while (i-- > 0) {
-		if (readl(cp->regs + REG_MAC_TX_RESET) == 0)
-			break;
-		udelay(10);
-	}
-
-	/* wait for RX */
-	i = STOP_TRIES;
-	while (i-- > 0) {
-		if (readl(cp->regs + REG_MAC_RX_RESET) == 0)
-			break;
-		udelay(10);
-	}
-
-	if (readl(cp->regs + REG_MAC_TX_RESET) |
-	    readl(cp->regs + REG_MAC_RX_RESET))
-		netdev_err(cp->dev, "mac tx[%d]/rx[%d] reset failed [%08x]\n",
-			   readl(cp->regs + REG_MAC_TX_RESET),
-			   readl(cp->regs + REG_MAC_RX_RESET),
-			   readl(cp->regs + REG_MAC_STATE_MACHINE));
-}
-
-
-/* Must be invoked under cp->lock. */
-static void cas_init_mac(struct cas *cp)
-{
-	unsigned char *e = &cp->dev->dev_addr[0];
-	int i;
-	cas_mac_reset(cp);
-
-	/* setup core arbitration weight register */
-	writel(CAWR_RR_DIS, cp->regs + REG_CAWR);
-
-	/* XXX Use pci_dma_burst_advice() */
-#if !defined(CONFIG_SPARC64) && !defined(CONFIG_ALPHA)
-	/* set the infinite burst register for chips that don't have
-	 * pci issues.
-	 */
-	if ((cp->cas_flags & CAS_FLAG_TARGET_ABORT) == 0)
-		writel(INF_BURST_EN, cp->regs + REG_INF_BURST);
-#endif
-
-	writel(0x1BF0, cp->regs + REG_MAC_SEND_PAUSE);
-
-	writel(0x00, cp->regs + REG_MAC_IPG0);
-	writel(0x08, cp->regs + REG_MAC_IPG1);
-	writel(0x04, cp->regs + REG_MAC_IPG2);
-
-	/* change later for 802.3z */
-	writel(0x40, cp->regs + REG_MAC_SLOT_TIME);
-
-	/* min frame + FCS */
-	writel(ETH_ZLEN + 4, cp->regs + REG_MAC_FRAMESIZE_MIN);
-
-	/* Ethernet payload + header + FCS + optional VLAN tag. NOTE: we
-	 * specify the maximum frame size to prevent RX tag errors on
-	 * oversized frames.
-	 */
-	writel(CAS_BASE(MAC_FRAMESIZE_MAX_BURST, 0x2000) |
-	       CAS_BASE(MAC_FRAMESIZE_MAX_FRAME,
-			(CAS_MAX_MTU + ETH_HLEN + 4 + 4)),
-	       cp->regs + REG_MAC_FRAMESIZE_MAX);
-
-	/* NOTE: crc_size is used as a surrogate for half-duplex.
-	 * workaround saturn half-duplex issue by increasing preamble
-	 * size to 65 bytes.
-	 */
-	if ((cp->cas_flags & CAS_FLAG_SATURN) && cp->crc_size)
-		writel(0x41, cp->regs + REG_MAC_PA_SIZE);
-	else
-		writel(0x07, cp->regs + REG_MAC_PA_SIZE);
-	writel(0x04, cp->regs + REG_MAC_JAM_SIZE);
-	writel(0x10, cp->regs + REG_MAC_ATTEMPT_LIMIT);
-	writel(0x8808, cp->regs + REG_MAC_CTRL_TYPE);
-
-	writel((e[5] | (e[4] << 8)) & 0x3ff, cp->regs + REG_MAC_RANDOM_SEED);
-
-	writel(0, cp->regs + REG_MAC_ADDR_FILTER0);
-	writel(0, cp->regs + REG_MAC_ADDR_FILTER1);
-	writel(0, cp->regs + REG_MAC_ADDR_FILTER2);
-	writel(0, cp->regs + REG_MAC_ADDR_FILTER2_1_MASK);
-	writel(0, cp->regs + REG_MAC_ADDR_FILTER0_MASK);
-
-	/* setup mac address in perfect filter array */
-	for (i = 0; i < 45; i++)
-		writel(0x0, cp->regs + REG_MAC_ADDRN(i));
-
-	writel((e[4] << 8) | e[5], cp->regs + REG_MAC_ADDRN(0));
-	writel((e[2] << 8) | e[3], cp->regs + REG_MAC_ADDRN(1));
-	writel((e[0] << 8) | e[1], cp->regs + REG_MAC_ADDRN(2));
-
-	writel(0x0001, cp->regs + REG_MAC_ADDRN(42));
-	writel(0xc200, cp->regs + REG_MAC_ADDRN(43));
-	writel(0x0180, cp->regs + REG_MAC_ADDRN(44));
-
-	cp->mac_rx_cfg = cas_setup_multicast(cp);
-
-	spin_lock(&cp->stat_lock[N_TX_RINGS]);
-	cas_clear_mac_err(cp);
-	spin_unlock(&cp->stat_lock[N_TX_RINGS]);
-
-	/* Setup MAC interrupts.  We want to get all of the interesting
-	 * counter expiration events, but we do not want to hear about
-	 * normal rx/tx as the DMA engine tells us that.
-	 */
-	writel(MAC_TX_FRAME_XMIT, cp->regs + REG_MAC_TX_MASK);
-	writel(MAC_RX_FRAME_RECV, cp->regs + REG_MAC_RX_MASK);
-
-	/* Don't enable even the PAUSE interrupts for now, we
-	 * make no use of those events other than to record them.
-	 */
-	writel(0xffffffff, cp->regs + REG_MAC_CTRL_MASK);
-}
-
-/* Must be invoked under cp->lock. */
-static void cas_init_pause_thresholds(struct cas *cp)
-{
-	/* Calculate pause thresholds.  Setting the OFF threshold to the
-	 * full RX fifo size effectively disables PAUSE generation
-	 */
-	if (cp->rx_fifo_size <= (2 * 1024)) {
-		cp->rx_pause_off = cp->rx_pause_on = cp->rx_fifo_size;
-	} else {
-		int max_frame = (cp->dev->mtu + ETH_HLEN + 4 + 4 + 64) & ~63;
-		if (max_frame * 3 > cp->rx_fifo_size) {
-			cp->rx_pause_off = 7104;
-			cp->rx_pause_on  = 960;
-		} else {
-			int off = (cp->rx_fifo_size - (max_frame * 2));
-			int on = off - max_frame;
-			cp->rx_pause_off = off;
-			cp->rx_pause_on = on;
-		}
-	}
-}
-
-static int cas_vpd_match(const void __iomem *p, const char *str)
-{
-	int len = strlen(str) + 1;
-	int i;
-
-	for (i = 0; i < len; i++) {
-		if (readb(p + i) != str[i])
-			return 0;
-	}
-	return 1;
-}
-
-
-/* get the mac address by reading the vpd information in the rom.
- * also get the phy type and determine if there's an entropy generator.
- * NOTE: this is a bit convoluted for the following reasons:
- *  1) vpd info has order-dependent mac addresses for multinic cards
- *  2) the only way to determine the nic order is to use the slot
- *     number.
- *  3) fiber cards don't have bridges, so their slot numbers don't
- *     mean anything.
- *  4) we don't actually know we have a fiber card until after
- *     the mac addresses are parsed.
- */
-static int cas_get_vpd_info(struct cas *cp, unsigned char *dev_addr,
-			    const int offset)
-{
-	void __iomem *p = cp->regs + REG_EXPANSION_ROM_RUN_START;
-	void __iomem *base, *kstart;
-	int i, len;
-	int found = 0;
-#define VPD_FOUND_MAC        0x01
-#define VPD_FOUND_PHY        0x02
-
-	int phy_type = CAS_PHY_MII_MDIO0; /* default phy type */
-	int mac_off  = 0;
-
-#if defined(CONFIG_SPARC)
-	const unsigned char *addr;
-#endif
-
-	/* give us access to the PROM */
-	writel(BIM_LOCAL_DEV_PROM | BIM_LOCAL_DEV_PAD,
-	       cp->regs + REG_BIM_LOCAL_DEV_EN);
-
-	/* check for an expansion rom */
-	if (readb(p) != 0x55 || readb(p + 1) != 0xaa)
-		goto use_random_mac_addr;
-
-	/* search for beginning of vpd */
-	base = NULL;
-	for (i = 2; i < EXPANSION_ROM_SIZE; i++) {
-		/* check for PCIR */
-		if ((readb(p + i + 0) == 0x50) &&
-		    (readb(p + i + 1) == 0x43) &&
-		    (readb(p + i + 2) == 0x49) &&
-		    (readb(p + i + 3) == 0x52)) {
-			base = p + (readb(p + i + 8) |
-				    (readb(p + i + 9) << 8));
-			break;
-		}
-	}
-
-	if (!base || (readb(base) != 0x82))
-		goto use_random_mac_addr;
-
-	i = (readb(base + 1) | (readb(base + 2) << 8)) + 3;
-	while (i < EXPANSION_ROM_SIZE) {
-		if (readb(base + i) != 0x90) /* no vpd found */
-			goto use_random_mac_addr;
-
-		/* found a vpd field */
-		len = readb(base + i + 1) | (readb(base + i + 2) << 8);
-
-		/* extract keywords */
-		kstart = base + i + 3;
-		p = kstart;
-		while ((p - kstart) < len) {
-			int klen = readb(p + 2);
-			int j;
-			char type;
-
-			p += 3;
-
-			/* look for the following things:
-			 * -- correct length == 29
-			 * 3 (type) + 2 (size) +
-			 * 18 (strlen("local-mac-address") + 1) +
-			 * 6 (mac addr)
-			 * -- VPD Instance 'I'
-			 * -- VPD Type Bytes 'B'
-			 * -- VPD data length == 6
-			 * -- property string == local-mac-address
-			 *
-			 * -- correct length == 24
-			 * 3 (type) + 2 (size) +
-			 * 12 (strlen("entropy-dev") + 1) +
-			 * 7 (strlen("vms110") + 1)
-			 * -- VPD Instance 'I'
-			 * -- VPD Type String 'B'
-			 * -- VPD data length == 7
-			 * -- property string == entropy-dev
-			 *
-			 * -- correct length == 18
-			 * 3 (type) + 2 (size) +
-			 * 9 (strlen("phy-type") + 1) +
-			 * 4 (strlen("pcs") + 1)
-			 * -- VPD Instance 'I'
-			 * -- VPD Type String 'S'
-			 * -- VPD data length == 4
-			 * -- property string == phy-type
-			 *
-			 * -- correct length == 23
-			 * 3 (type) + 2 (size) +
-			 * 14 (strlen("phy-interface") + 1) +
-			 * 4 (strlen("pcs") + 1)
-			 * -- VPD Instance 'I'
-			 * -- VPD Type String 'S'
-			 * -- VPD data length == 4
-			 * -- property string == phy-interface
-			 */
-			if (readb(p) != 'I')
-				goto next;
-
-			/* finally, check string and length */
-			type = readb(p + 3);
-			if (type == 'B') {
-				if ((klen == 29) && readb(p + 4) == 6 &&
-				    cas_vpd_match(p + 5,
-						  "local-mac-address")) {
-					if (mac_off++ > offset)
-						goto next;
-
-					/* set mac address */
-					for (j = 0; j < 6; j++)
-						dev_addr[j] =
-							readb(p + 23 + j);
-					goto found_mac;
-				}
-			}
-
-			if (type != 'S')
-				goto next;
-
-#ifdef USE_ENTROPY_DEV
-			if ((klen == 24) &&
-			    cas_vpd_match(p + 5, "entropy-dev") &&
-			    cas_vpd_match(p + 17, "vms110")) {
-				cp->cas_flags |= CAS_FLAG_ENTROPY_DEV;
-				goto next;
-			}
-#endif
-
-			if (found & VPD_FOUND_PHY)
-				goto next;
-
-			if ((klen == 18) && readb(p + 4) == 4 &&
-			    cas_vpd_match(p + 5, "phy-type")) {
-				if (cas_vpd_match(p + 14, "pcs")) {
-					phy_type = CAS_PHY_SERDES;
-					goto found_phy;
-				}
-			}
-
-			if ((klen == 23) && readb(p + 4) == 4 &&
-			    cas_vpd_match(p + 5, "phy-interface")) {
-				if (cas_vpd_match(p + 19, "pcs")) {
-					phy_type = CAS_PHY_SERDES;
-					goto found_phy;
-				}
-			}
-found_mac:
-			found |= VPD_FOUND_MAC;
-			goto next;
-
-found_phy:
-			found |= VPD_FOUND_PHY;
-
-next:
-			p += klen;
-		}
-		i += len + 3;
-	}
-
-use_random_mac_addr:
-	if (found & VPD_FOUND_MAC)
-		goto done;
-
-#if defined(CONFIG_SPARC)
-	addr = of_get_property(cp->of_node, "local-mac-address", NULL);
-	if (addr != NULL) {
-		memcpy(dev_addr, addr, 6);
-		goto done;
-	}
-#endif
-
-	/* Sun MAC prefix then 3 random bytes. */
-	pr_info("MAC address not found in ROM VPD\n");
-	dev_addr[0] = 0x08;
-	dev_addr[1] = 0x00;
-	dev_addr[2] = 0x20;
-	get_random_bytes(dev_addr + 3, 3);
-
-done:
-	writel(0, cp->regs + REG_BIM_LOCAL_DEV_EN);
-	return phy_type;
-}
-
-/* check pci invariants */
-static void cas_check_pci_invariants(struct cas *cp)
-{
-	struct pci_dev *pdev = cp->pdev;
-
-	cp->cas_flags = 0;
-	if ((pdev->vendor == PCI_VENDOR_ID_SUN) &&
-	    (pdev->device == PCI_DEVICE_ID_SUN_CASSINI)) {
-		if (pdev->revision >= CAS_ID_REVPLUS)
-			cp->cas_flags |= CAS_FLAG_REG_PLUS;
-		if (pdev->revision < CAS_ID_REVPLUS02u)
-			cp->cas_flags |= CAS_FLAG_TARGET_ABORT;
-
-		/* Original Cassini supports HW CSUM, but it's not
-		 * enabled by default as it can trigger TX hangs.
-		 */
-		if (pdev->revision < CAS_ID_REV2)
-			cp->cas_flags |= CAS_FLAG_NO_HW_CSUM;
-	} else {
-		/* Only sun has original cassini chips.  */
-		cp->cas_flags |= CAS_FLAG_REG_PLUS;
-
-		/* We use a flag because the same phy might be externally
-		 * connected.
-		 */
-		if ((pdev->vendor == PCI_VENDOR_ID_NS) &&
-		    (pdev->device == PCI_DEVICE_ID_NS_SATURN))
-			cp->cas_flags |= CAS_FLAG_SATURN;
-	}
-}
-
-
-static int cas_check_invariants(struct cas *cp)
-{
-	struct pci_dev *pdev = cp->pdev;
-	u32 cfg;
-	int i;
-
-	/* get page size for rx buffers. */
-	cp->page_order = 0;
-#ifdef USE_PAGE_ORDER
-	if (PAGE_SHIFT < CAS_JUMBO_PAGE_SHIFT) {
-		/* see if we can allocate larger pages */
-		struct page *page = alloc_pages(GFP_ATOMIC,
-						CAS_JUMBO_PAGE_SHIFT -
-						PAGE_SHIFT);
-		if (page) {
-			__free_pages(page, CAS_JUMBO_PAGE_SHIFT - PAGE_SHIFT);
-			cp->page_order = CAS_JUMBO_PAGE_SHIFT - PAGE_SHIFT;
-		} else {
-			printk("MTU limited to %d bytes\n", CAS_MAX_MTU);
-		}
-	}
-#endif
-	cp->page_size = (PAGE_SIZE << cp->page_order);
-
-	/* Fetch the FIFO configurations. */
-	cp->tx_fifo_size = readl(cp->regs + REG_TX_FIFO_SIZE) * 64;
-	cp->rx_fifo_size = RX_FIFO_SIZE;
-
-	/* finish phy determination. MDIO1 takes precedence over MDIO0 if
-	 * they're both connected.
-	 */
-	cp->phy_type = cas_get_vpd_info(cp, cp->dev->dev_addr,
-					PCI_SLOT(pdev->devfn));
-	if (cp->phy_type & CAS_PHY_SERDES) {
-		cp->cas_flags |= CAS_FLAG_1000MB_CAP;
-		return 0; /* no more checking needed */
-	}
-
-	/* MII */
-	cfg = readl(cp->regs + REG_MIF_CFG);
-	if (cfg & MIF_CFG_MDIO_1) {
-		cp->phy_type = CAS_PHY_MII_MDIO1;
-	} else if (cfg & MIF_CFG_MDIO_0) {
-		cp->phy_type = CAS_PHY_MII_MDIO0;
-	}
-
-	cas_mif_poll(cp, 0);
-	writel(PCS_DATAPATH_MODE_MII, cp->regs + REG_PCS_DATAPATH_MODE);
-
-	for (i = 0; i < 32; i++) {
-		u32 phy_id;
-		int j;
-
-		for (j = 0; j < 3; j++) {
-			cp->phy_addr = i;
-			phy_id = cas_phy_read(cp, MII_PHYSID1) << 16;
-			phy_id |= cas_phy_read(cp, MII_PHYSID2);
-			if (phy_id && (phy_id != 0xFFFFFFFF)) {
-				cp->phy_id = phy_id;
-				goto done;
-			}
-		}
-	}
-	pr_err("MII phy did not respond [%08x]\n",
-	       readl(cp->regs + REG_MIF_STATE_MACHINE));
-	return -1;
-
-done:
-	/* see if we can do gigabit */
-	cfg = cas_phy_read(cp, MII_BMSR);
-	if ((cfg & CAS_BMSR_1000_EXTEND) &&
-	    cas_phy_read(cp, CAS_MII_1000_EXTEND))
-		cp->cas_flags |= CAS_FLAG_1000MB_CAP;
-	return 0;
-}
-
-/* Must be invoked under cp->lock. */
-static inline void cas_start_dma(struct cas *cp)
-{
-	int i;
-	u32 val;
-	int txfailed = 0;
-
-	/* enable dma */
-	val = readl(cp->regs + REG_TX_CFG) | TX_CFG_DMA_EN;
-	writel(val, cp->regs + REG_TX_CFG);
-	val = readl(cp->regs + REG_RX_CFG) | RX_CFG_DMA_EN;
-	writel(val, cp->regs + REG_RX_CFG);
-
-	/* enable the mac */
-	val = readl(cp->regs + REG_MAC_TX_CFG) | MAC_TX_CFG_EN;
-	writel(val, cp->regs + REG_MAC_TX_CFG);
-	val = readl(cp->regs + REG_MAC_RX_CFG) | MAC_RX_CFG_EN;
-	writel(val, cp->regs + REG_MAC_RX_CFG);
-
-	i = STOP_TRIES;
-	while (i-- > 0) {
-		val = readl(cp->regs + REG_MAC_TX_CFG);
-		if ((val & MAC_TX_CFG_EN))
-			break;
-		udelay(10);
-	}
-	if (i < 0) txfailed = 1;
-	i = STOP_TRIES;
-	while (i-- > 0) {
-		val = readl(cp->regs + REG_MAC_RX_CFG);
-		if ((val & MAC_RX_CFG_EN)) {
-			if (txfailed) {
-				netdev_err(cp->dev,
-					   "enabling mac failed [tx:%08x:%08x]\n",
-					   readl(cp->regs + REG_MIF_STATE_MACHINE),
-					   readl(cp->regs + REG_MAC_STATE_MACHINE));
-			}
-			goto enable_rx_done;
-		}
-		udelay(10);
-	}
-	netdev_err(cp->dev, "enabling mac failed [%s:%08x:%08x]\n",
-		   (txfailed ? "tx,rx" : "rx"),
-		   readl(cp->regs + REG_MIF_STATE_MACHINE),
-		   readl(cp->regs + REG_MAC_STATE_MACHINE));
-
-enable_rx_done:
-	cas_unmask_intr(cp); /* enable interrupts */
-	writel(RX_DESC_RINGN_SIZE(0) - 4, cp->regs + REG_RX_KICK);
-	writel(0, cp->regs + REG_RX_COMP_TAIL);
-
-	if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
-		if (N_RX_DESC_RINGS > 1)
-			writel(RX_DESC_RINGN_SIZE(1) - 4,
-			       cp->regs + REG_PLUS_RX_KICK1);
-
-		for (i = 1; i < N_RX_COMP_RINGS; i++)
-			writel(0, cp->regs + REG_PLUS_RX_COMPN_TAIL(i));
-	}
-}
-
-/* Must be invoked under cp->lock. */
-static void cas_read_pcs_link_mode(struct cas *cp, int *fd, int *spd,
-				   int *pause)
-{
-	u32 val = readl(cp->regs + REG_PCS_MII_LPA);
-	*fd     = (val & PCS_MII_LPA_FD) ? 1 : 0;
-	*pause  = (val & PCS_MII_LPA_SYM_PAUSE) ? 0x01 : 0x00;
-	if (val & PCS_MII_LPA_ASYM_PAUSE)
-		*pause |= 0x10;
-	*spd = 1000;
-}
-
-/* Must be invoked under cp->lock. */
-static void cas_read_mii_link_mode(struct cas *cp, int *fd, int *spd,
-				   int *pause)
-{
-	u32 val;
-
-	*fd = 0;
-	*spd = 10;
-	*pause = 0;
-
-	/* use GMII registers */
-	val = cas_phy_read(cp, MII_LPA);
-	if (val & CAS_LPA_PAUSE)
-		*pause = 0x01;
-
-	if (val & CAS_LPA_ASYM_PAUSE)
-		*pause |= 0x10;
-
-	if (val & LPA_DUPLEX)
-		*fd = 1;
-	if (val & LPA_100)
-		*spd = 100;
-
-	if (cp->cas_flags & CAS_FLAG_1000MB_CAP) {
-		val = cas_phy_read(cp, CAS_MII_1000_STATUS);
-		if (val & (CAS_LPA_1000FULL | CAS_LPA_1000HALF))
-			*spd = 1000;
-		if (val & CAS_LPA_1000FULL)
-			*fd = 1;
-	}
-}
-
-/* A link-up condition has occurred, initialize and enable the
- * rest of the chip.
- *
- * Must be invoked under cp->lock.
- */
-static void cas_set_link_modes(struct cas *cp)
-{
-	u32 val;
-	int full_duplex, speed, pause;
-
-	full_duplex = 0;
-	speed = 10;
-	pause = 0;
-
-	if (CAS_PHY_MII(cp->phy_type)) {
-		cas_mif_poll(cp, 0);
-		val = cas_phy_read(cp, MII_BMCR);
-		if (val & BMCR_ANENABLE) {
-			cas_read_mii_link_mode(cp, &full_duplex, &speed,
-					       &pause);
-		} else {
-			if (val & BMCR_FULLDPLX)
-				full_duplex = 1;
-
-			if (val & BMCR_SPEED100)
-				speed = 100;
-			else if (val & CAS_BMCR_SPEED1000)
-				speed = (cp->cas_flags & CAS_FLAG_1000MB_CAP) ?
-					1000 : 100;
-		}
-		cas_mif_poll(cp, 1);
-
-	} else {
-		val = readl(cp->regs + REG_PCS_MII_CTRL);
-		cas_read_pcs_link_mode(cp, &full_duplex, &speed, &pause);
-		if ((val & PCS_MII_AUTONEG_EN) == 0) {
-			if (val & PCS_MII_CTRL_DUPLEX)
-				full_duplex = 1;
-		}
-	}
-
-	netif_info(cp, link, cp->dev, "Link up at %d Mbps, %s-duplex\n",
-		   speed, full_duplex ? "full" : "half");
-
-	val = MAC_XIF_TX_MII_OUTPUT_EN | MAC_XIF_LINK_LED;
-	if (CAS_PHY_MII(cp->phy_type)) {
-		val |= MAC_XIF_MII_BUFFER_OUTPUT_EN;
-		if (!full_duplex)
-			val |= MAC_XIF_DISABLE_ECHO;
-	}
-	if (full_duplex)
-		val |= MAC_XIF_FDPLX_LED;
-	if (speed == 1000)
-		val |= MAC_XIF_GMII_MODE;
-	writel(val, cp->regs + REG_MAC_XIF_CFG);
-
-	/* deal with carrier and collision detect. */
-	val = MAC_TX_CFG_IPG_EN;
-	if (full_duplex) {
-		val |= MAC_TX_CFG_IGNORE_CARRIER;
-		val |= MAC_TX_CFG_IGNORE_COLL;
-	} else {
-#ifndef USE_CSMA_CD_PROTO
-		val |= MAC_TX_CFG_NEVER_GIVE_UP_EN;
-		val |= MAC_TX_CFG_NEVER_GIVE_UP_LIM;
-#endif
-	}
-	/* val now set up for REG_MAC_TX_CFG */
-
-	/* If gigabit and half-duplex, enable carrier extension
-	 * mode.  increase slot time to 512 bytes as well.
-	 * else, disable it and make sure slot time is 64 bytes.
-	 * also activate checksum bug workaround
-	 */
-	if ((speed == 1000) && !full_duplex) {
-		writel(val | MAC_TX_CFG_CARRIER_EXTEND,
-		       cp->regs + REG_MAC_TX_CFG);
-
-		val = readl(cp->regs + REG_MAC_RX_CFG);
-		val &= ~MAC_RX_CFG_STRIP_FCS; /* checksum workaround */
-		writel(val | MAC_RX_CFG_CARRIER_EXTEND,
-		       cp->regs + REG_MAC_RX_CFG);
-
-		writel(0x200, cp->regs + REG_MAC_SLOT_TIME);
-
-		cp->crc_size = 4;
-		/* minimum size gigabit frame at half duplex */
-		cp->min_frame_size = CAS_1000MB_MIN_FRAME;
-
-	} else {
-		writel(val, cp->regs + REG_MAC_TX_CFG);
-
-		/* checksum bug workaround. don't strip FCS when in
-		 * half-duplex mode
-		 */
-		val = readl(cp->regs + REG_MAC_RX_CFG);
-		if (full_duplex) {
-			val |= MAC_RX_CFG_STRIP_FCS;
-			cp->crc_size = 0;
-			cp->min_frame_size = CAS_MIN_MTU;
-		} else {
-			val &= ~MAC_RX_CFG_STRIP_FCS;
-			cp->crc_size = 4;
-			cp->min_frame_size = CAS_MIN_FRAME;
-		}
-		writel(val & ~MAC_RX_CFG_CARRIER_EXTEND,
-		       cp->regs + REG_MAC_RX_CFG);
-		writel(0x40, cp->regs + REG_MAC_SLOT_TIME);
-	}
-
-	if (netif_msg_link(cp)) {
-		if (pause & 0x01) {
-			netdev_info(cp->dev, "Pause is enabled (rxfifo: %d off: %d on: %d)\n",
-				    cp->rx_fifo_size,
-				    cp->rx_pause_off,
-				    cp->rx_pause_on);
-		} else if (pause & 0x10) {
-			netdev_info(cp->dev, "TX pause enabled\n");
-		} else {
-			netdev_info(cp->dev, "Pause is disabled\n");
-		}
-	}
-
-	val = readl(cp->regs + REG_MAC_CTRL_CFG);
-	val &= ~(MAC_CTRL_CFG_SEND_PAUSE_EN | MAC_CTRL_CFG_RECV_PAUSE_EN);
-	if (pause) { /* symmetric or asymmetric pause */
-		val |= MAC_CTRL_CFG_SEND_PAUSE_EN;
-		if (pause & 0x01) { /* symmetric pause */
-			val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
-		}
-	}
-	writel(val, cp->regs + REG_MAC_CTRL_CFG);
-	cas_start_dma(cp);
-}
-
-/* Must be invoked under cp->lock. */
-static void cas_init_hw(struct cas *cp, int restart_link)
-{
-	if (restart_link)
-		cas_phy_init(cp);
-
-	cas_init_pause_thresholds(cp);
-	cas_init_mac(cp);
-	cas_init_dma(cp);
-
-	if (restart_link) {
-		/* Default aneg parameters */
-		cp->timer_ticks = 0;
-		cas_begin_auto_negotiation(cp, NULL);
-	} else if (cp->lstate == link_up) {
-		cas_set_link_modes(cp);
-		netif_carrier_on(cp->dev);
-	}
-}
-
-/* Must be invoked under cp->lock. on earlier cassini boards,
- * SOFT_0 is tied to PCI reset. we use this to force a pci reset,
- * let it settle out, and then restore pci state.
- */
-static void cas_hard_reset(struct cas *cp)
-{
-	writel(BIM_LOCAL_DEV_SOFT_0, cp->regs + REG_BIM_LOCAL_DEV_EN);
-	udelay(20);
-	pci_restore_state(cp->pdev);
-}
-
-
-static void cas_global_reset(struct cas *cp, int blkflag)
-{
-	int limit;
-
-	/* issue a global reset. don't use RSTOUT. */
-	if (blkflag && !CAS_PHY_MII(cp->phy_type)) {
-		/* For PCS, when the blkflag is set, we should set the
-		 * SW_REST_BLOCK_PCS_SLINK bit to prevent the results of
-		 * the last autonegotiation from being cleared.  We'll
-		 * need some special handling if the chip is set into a
-		 * loopback mode.
-		 */
-		writel((SW_RESET_TX | SW_RESET_RX | SW_RESET_BLOCK_PCS_SLINK),
-		       cp->regs + REG_SW_RESET);
-	} else {
-		writel(SW_RESET_TX | SW_RESET_RX, cp->regs + REG_SW_RESET);
-	}
-
-	/* need to wait at least 3ms before polling register */
-	mdelay(3);
-
-	limit = STOP_TRIES;
-	while (limit-- > 0) {
-		u32 val = readl(cp->regs + REG_SW_RESET);
-		if ((val & (SW_RESET_TX | SW_RESET_RX)) == 0)
-			goto done;
-		udelay(10);
-	}
-	netdev_err(cp->dev, "sw reset failed\n");
-
-done:
-	/* enable various BIM interrupts */
-	writel(BIM_CFG_DPAR_INTR_ENABLE | BIM_CFG_RMA_INTR_ENABLE |
-	       BIM_CFG_RTA_INTR_ENABLE, cp->regs + REG_BIM_CFG);
-
-	/* clear out pci error status mask for handled errors.
-	 * we don't deal with DMA counter overflows as they happen
-	 * all the time.
-	 */
-	writel(0xFFFFFFFFU & ~(PCI_ERR_BADACK | PCI_ERR_DTRTO |
-			       PCI_ERR_OTHER | PCI_ERR_BIM_DMA_WRITE |
-			       PCI_ERR_BIM_DMA_READ), cp->regs +
-	       REG_PCI_ERR_STATUS_MASK);
-
-	/* set up for MII by default to address mac rx reset timeout
-	 * issue
-	 */
-	writel(PCS_DATAPATH_MODE_MII, cp->regs + REG_PCS_DATAPATH_MODE);
-}
-
-static void cas_reset(struct cas *cp, int blkflag)
-{
-	u32 val;
-
-	cas_mask_intr(cp);
-	cas_global_reset(cp, blkflag);
-	cas_mac_reset(cp);
-	cas_entropy_reset(cp);
-
-	/* disable dma engines. */
-	val = readl(cp->regs + REG_TX_CFG);
-	val &= ~TX_CFG_DMA_EN;
-	writel(val, cp->regs + REG_TX_CFG);
-
-	val = readl(cp->regs + REG_RX_CFG);
-	val &= ~RX_CFG_DMA_EN;
-	writel(val, cp->regs + REG_RX_CFG);
-
-	/* program header parser */
-	if ((cp->cas_flags & CAS_FLAG_TARGET_ABORT) ||
-	    (CAS_HP_ALT_FIRMWARE == cas_prog_null)) {
-		cas_load_firmware(cp, CAS_HP_FIRMWARE);
-	} else {
-		cas_load_firmware(cp, CAS_HP_ALT_FIRMWARE);
-	}
-
-	/* clear out error registers */
-	spin_lock(&cp->stat_lock[N_TX_RINGS]);
-	cas_clear_mac_err(cp);
-	spin_unlock(&cp->stat_lock[N_TX_RINGS]);
-}
-
-/* Shut down the chip, must be called with pm_mutex held.  */
-static void cas_shutdown(struct cas *cp)
-{
-	unsigned long flags;
-
-	/* Make us not-running to avoid timers respawning */
-	cp->hw_running = 0;
-
-	del_timer_sync(&cp->link_timer);
-
-	/* Stop the reset task */
-#if 0
-	while (atomic_read(&cp->reset_task_pending_mtu) ||
-	       atomic_read(&cp->reset_task_pending_spare) ||
-	       atomic_read(&cp->reset_task_pending_all))
-		schedule();
-
-#else
-	while (atomic_read(&cp->reset_task_pending))
-		schedule();
-#endif
-	/* Actually stop the chip */
-	cas_lock_all_save(cp, flags);
-	cas_reset(cp, 0);
-	if (cp->cas_flags & CAS_FLAG_SATURN)
-		cas_phy_powerdown(cp);
-	cas_unlock_all_restore(cp, flags);
-}
-
-static int cas_change_mtu(struct net_device *dev, int new_mtu)
-{
-	struct cas *cp = netdev_priv(dev);
-
-	if (new_mtu < CAS_MIN_MTU || new_mtu > CAS_MAX_MTU)
-		return -EINVAL;
-
-	dev->mtu = new_mtu;
-	if (!netif_running(dev) || !netif_device_present(dev))
-		return 0;
-
-	/* let the reset task handle it */
-#if 1
-	atomic_inc(&cp->reset_task_pending);
-	if ((cp->phy_type & CAS_PHY_SERDES)) {
-		atomic_inc(&cp->reset_task_pending_all);
-	} else {
-		atomic_inc(&cp->reset_task_pending_mtu);
-	}
-	schedule_work(&cp->reset_task);
-#else
-	atomic_set(&cp->reset_task_pending, (cp->phy_type & CAS_PHY_SERDES) ?
-		   CAS_RESET_ALL : CAS_RESET_MTU);
-	pr_err("reset called in cas_change_mtu\n");
-	schedule_work(&cp->reset_task);
-#endif
-
-	flush_work_sync(&cp->reset_task);
-	return 0;
-}
-
-static void cas_clean_txd(struct cas *cp, int ring)
-{
-	struct cas_tx_desc *txd = cp->init_txds[ring];
-	struct sk_buff *skb, **skbs = cp->tx_skbs[ring];
-	u64 daddr, dlen;
-	int i, size;
-
-	size = TX_DESC_RINGN_SIZE(ring);
-	for (i = 0; i < size; i++) {
-		int frag;
-
-		if (skbs[i] == NULL)
-			continue;
-
-		skb = skbs[i];
-		skbs[i] = NULL;
-
-		for (frag = 0; frag <= skb_shinfo(skb)->nr_frags;  frag++) {
-			int ent = i & (size - 1);
-
-			/* first buffer is never a tiny buffer and so
-			 * needs to be unmapped.
-			 */
-			daddr = le64_to_cpu(txd[ent].buffer);
-			dlen  =  CAS_VAL(TX_DESC_BUFLEN,
-					 le64_to_cpu(txd[ent].control));
-			pci_unmap_page(cp->pdev, daddr, dlen,
-				       PCI_DMA_TODEVICE);
-
-			if (frag != skb_shinfo(skb)->nr_frags) {
-				i++;
-
-				/* next buffer might by a tiny buffer.
-				 * skip past it.
-				 */
-				ent = i & (size - 1);
-				if (cp->tx_tiny_use[ring][ent].used)
-					i++;
-			}
-		}
-		dev_kfree_skb_any(skb);
-	}
-
-	/* zero out tiny buf usage */
-	memset(cp->tx_tiny_use[ring], 0, size*sizeof(*cp->tx_tiny_use[ring]));
-}
-
-/* freed on close */
-static inline void cas_free_rx_desc(struct cas *cp, int ring)
-{
-	cas_page_t **page = cp->rx_pages[ring];
-	int i, size;
-
-	size = RX_DESC_RINGN_SIZE(ring);
-	for (i = 0; i < size; i++) {
-		if (page[i]) {
-			cas_page_free(cp, page[i]);
-			page[i] = NULL;
-		}
-	}
-}
-
-static void cas_free_rxds(struct cas *cp)
-{
-	int i;
-
-	for (i = 0; i < N_RX_DESC_RINGS; i++)
-		cas_free_rx_desc(cp, i);
-}
-
-/* Must be invoked under cp->lock. */
-static void cas_clean_rings(struct cas *cp)
-{
-	int i;
-
-	/* need to clean all tx rings */
-	memset(cp->tx_old, 0, sizeof(*cp->tx_old)*N_TX_RINGS);
-	memset(cp->tx_new, 0, sizeof(*cp->tx_new)*N_TX_RINGS);
-	for (i = 0; i < N_TX_RINGS; i++)
-		cas_clean_txd(cp, i);
-
-	/* zero out init block */
-	memset(cp->init_block, 0, sizeof(struct cas_init_block));
-	cas_clean_rxds(cp);
-	cas_clean_rxcs(cp);
-}
-
-/* allocated on open */
-static inline int cas_alloc_rx_desc(struct cas *cp, int ring)
-{
-	cas_page_t **page = cp->rx_pages[ring];
-	int size, i = 0;
-
-	size = RX_DESC_RINGN_SIZE(ring);
-	for (i = 0; i < size; i++) {
-		if ((page[i] = cas_page_alloc(cp, GFP_KERNEL)) == NULL)
-			return -1;
-	}
-	return 0;
-}
-
-static int cas_alloc_rxds(struct cas *cp)
-{
-	int i;
-
-	for (i = 0; i < N_RX_DESC_RINGS; i++) {
-		if (cas_alloc_rx_desc(cp, i) < 0) {
-			cas_free_rxds(cp);
-			return -1;
-		}
-	}
-	return 0;
-}
-
-static void cas_reset_task(struct work_struct *work)
-{
-	struct cas *cp = container_of(work, struct cas, reset_task);
-#if 0
-	int pending = atomic_read(&cp->reset_task_pending);
-#else
-	int pending_all = atomic_read(&cp->reset_task_pending_all);
-	int pending_spare = atomic_read(&cp->reset_task_pending_spare);
-	int pending_mtu = atomic_read(&cp->reset_task_pending_mtu);
-
-	if (pending_all == 0 && pending_spare == 0 && pending_mtu == 0) {
-		/* We can have more tasks scheduled than actually
-		 * needed.
-		 */
-		atomic_dec(&cp->reset_task_pending);
-		return;
-	}
-#endif
-	/* The link went down, we reset the ring, but keep
-	 * DMA stopped. Use this function for reset
-	 * on error as well.
-	 */
-	if (cp->hw_running) {
-		unsigned long flags;
-
-		/* Make sure we don't get interrupts or tx packets */
-		netif_device_detach(cp->dev);
-		cas_lock_all_save(cp, flags);
-
-		if (cp->opened) {
-			/* We call cas_spare_recover when we call cas_open.
-			 * but we do not initialize the lists cas_spare_recover
-			 * uses until cas_open is called.
-			 */
-			cas_spare_recover(cp, GFP_ATOMIC);
-		}
-#if 1
-		/* test => only pending_spare set */
-		if (!pending_all && !pending_mtu)
-			goto done;
-#else
-		if (pending == CAS_RESET_SPARE)
-			goto done;
-#endif
-		/* when pending == CAS_RESET_ALL, the following
-		 * call to cas_init_hw will restart auto negotiation.
-		 * Setting the second argument of cas_reset to
-		 * !(pending == CAS_RESET_ALL) will set this argument
-		 * to 1 (avoiding reinitializing the PHY for the normal
-		 * PCS case) when auto negotiation is not restarted.
-		 */
-#if 1
-		cas_reset(cp, !(pending_all > 0));
-		if (cp->opened)
-			cas_clean_rings(cp);
-		cas_init_hw(cp, (pending_all > 0));
-#else
-		cas_reset(cp, !(pending == CAS_RESET_ALL));
-		if (cp->opened)
-			cas_clean_rings(cp);
-		cas_init_hw(cp, pending == CAS_RESET_ALL);
-#endif
-
-done:
-		cas_unlock_all_restore(cp, flags);
-		netif_device_attach(cp->dev);
-	}
-#if 1
-	atomic_sub(pending_all, &cp->reset_task_pending_all);
-	atomic_sub(pending_spare, &cp->reset_task_pending_spare);
-	atomic_sub(pending_mtu, &cp->reset_task_pending_mtu);
-	atomic_dec(&cp->reset_task_pending);
-#else
-	atomic_set(&cp->reset_task_pending, 0);
-#endif
-}
-
-static void cas_link_timer(unsigned long data)
-{
-	struct cas *cp = (struct cas *) data;
-	int mask, pending = 0, reset = 0;
-	unsigned long flags;
-
-	if (link_transition_timeout != 0 &&
-	    cp->link_transition_jiffies_valid &&
-	    ((jiffies - cp->link_transition_jiffies) >
-	      (link_transition_timeout))) {
-		/* One-second counter so link-down workaround doesn't
-		 * cause resets to occur so fast as to fool the switch
-		 * into thinking the link is down.
-		 */
-		cp->link_transition_jiffies_valid = 0;
-	}
-
-	if (!cp->hw_running)
-		return;
-
-	spin_lock_irqsave(&cp->lock, flags);
-	cas_lock_tx(cp);
-	cas_entropy_gather(cp);
-
-	/* If the link task is still pending, we just
-	 * reschedule the link timer
-	 */
-#if 1
-	if (atomic_read(&cp->reset_task_pending_all) ||
-	    atomic_read(&cp->reset_task_pending_spare) ||
-	    atomic_read(&cp->reset_task_pending_mtu))
-		goto done;
-#else
-	if (atomic_read(&cp->reset_task_pending))
-		goto done;
-#endif
-
-	/* check for rx cleaning */
-	if ((mask = (cp->cas_flags & CAS_FLAG_RXD_POST_MASK))) {
-		int i, rmask;
-
-		for (i = 0; i < MAX_RX_DESC_RINGS; i++) {
-			rmask = CAS_FLAG_RXD_POST(i);
-			if ((mask & rmask) == 0)
-				continue;
-
-			/* post_rxds will do a mod_timer */
-			if (cas_post_rxds_ringN(cp, i, cp->rx_last[i]) < 0) {
-				pending = 1;
-				continue;
-			}
-			cp->cas_flags &= ~rmask;
-		}
-	}
-
-	if (CAS_PHY_MII(cp->phy_type)) {
-		u16 bmsr;
-		cas_mif_poll(cp, 0);
-		bmsr = cas_phy_read(cp, MII_BMSR);
-		/* WTZ: Solaris driver reads this twice, but that
-		 * may be due to the PCS case and the use of a
-		 * common implementation. Read it twice here to be
-		 * safe.
-		 */
-		bmsr = cas_phy_read(cp, MII_BMSR);
-		cas_mif_poll(cp, 1);
-		readl(cp->regs + REG_MIF_STATUS); /* avoid dups */
-		reset = cas_mii_link_check(cp, bmsr);
-	} else {
-		reset = cas_pcs_link_check(cp);
-	}
-
-	if (reset)
-		goto done;
-
-	/* check for tx state machine confusion */
-	if ((readl(cp->regs + REG_MAC_TX_STATUS) & MAC_TX_FRAME_XMIT) == 0) {
-		u32 val = readl(cp->regs + REG_MAC_STATE_MACHINE);
-		u32 wptr, rptr;
-		int tlm  = CAS_VAL(MAC_SM_TLM, val);
-
-		if (((tlm == 0x5) || (tlm == 0x3)) &&
-		    (CAS_VAL(MAC_SM_ENCAP_SM, val) == 0)) {
-			netif_printk(cp, tx_err, KERN_DEBUG, cp->dev,
-				     "tx err: MAC_STATE[%08x]\n", val);
-			reset = 1;
-			goto done;
-		}
-
-		val  = readl(cp->regs + REG_TX_FIFO_PKT_CNT);
-		wptr = readl(cp->regs + REG_TX_FIFO_WRITE_PTR);
-		rptr = readl(cp->regs + REG_TX_FIFO_READ_PTR);
-		if ((val == 0) && (wptr != rptr)) {
-			netif_printk(cp, tx_err, KERN_DEBUG, cp->dev,
-				     "tx err: TX_FIFO[%08x:%08x:%08x]\n",
-				     val, wptr, rptr);
-			reset = 1;
-		}
-
-		if (reset)
-			cas_hard_reset(cp);
-	}
-
-done:
-	if (reset) {
-#if 1
-		atomic_inc(&cp->reset_task_pending);
-		atomic_inc(&cp->reset_task_pending_all);
-		schedule_work(&cp->reset_task);
-#else
-		atomic_set(&cp->reset_task_pending, CAS_RESET_ALL);
-		pr_err("reset called in cas_link_timer\n");
-		schedule_work(&cp->reset_task);
-#endif
-	}
-
-	if (!pending)
-		mod_timer(&cp->link_timer, jiffies + CAS_LINK_TIMEOUT);
-	cas_unlock_tx(cp);
-	spin_unlock_irqrestore(&cp->lock, flags);
-}
-
-/* tiny buffers are used to avoid target abort issues with
- * older cassini's
- */
-static void cas_tx_tiny_free(struct cas *cp)
-{
-	struct pci_dev *pdev = cp->pdev;
-	int i;
-
-	for (i = 0; i < N_TX_RINGS; i++) {
-		if (!cp->tx_tiny_bufs[i])
-			continue;
-
-		pci_free_consistent(pdev, TX_TINY_BUF_BLOCK,
-				    cp->tx_tiny_bufs[i],
-				    cp->tx_tiny_dvma[i]);
-		cp->tx_tiny_bufs[i] = NULL;
-	}
-}
-
-static int cas_tx_tiny_alloc(struct cas *cp)
-{
-	struct pci_dev *pdev = cp->pdev;
-	int i;
-
-	for (i = 0; i < N_TX_RINGS; i++) {
-		cp->tx_tiny_bufs[i] =
-			pci_alloc_consistent(pdev, TX_TINY_BUF_BLOCK,
-					     &cp->tx_tiny_dvma[i]);
-		if (!cp->tx_tiny_bufs[i]) {
-			cas_tx_tiny_free(cp);
-			return -1;
-		}
-	}
-	return 0;
-}
-
-
-static int cas_open(struct net_device *dev)
-{
-	struct cas *cp = netdev_priv(dev);
-	int hw_was_up, err;
-	unsigned long flags;
-
-	mutex_lock(&cp->pm_mutex);
-
-	hw_was_up = cp->hw_running;
-
-	/* The power-management mutex protects the hw_running
-	 * etc. state so it is safe to do this bit without cp->lock
-	 */
-	if (!cp->hw_running) {
-		/* Reset the chip */
-		cas_lock_all_save(cp, flags);
-		/* We set the second arg to cas_reset to zero
-		 * because cas_init_hw below will have its second
-		 * argument set to non-zero, which will force
-		 * autonegotiation to start.
-		 */
-		cas_reset(cp, 0);
-		cp->hw_running = 1;
-		cas_unlock_all_restore(cp, flags);
-	}
-
-	err = -ENOMEM;
-	if (cas_tx_tiny_alloc(cp) < 0)
-		goto err_unlock;
-
-	/* alloc rx descriptors */
-	if (cas_alloc_rxds(cp) < 0)
-		goto err_tx_tiny;
-
-	/* allocate spares */
-	cas_spare_init(cp);
-	cas_spare_recover(cp, GFP_KERNEL);
-
-	/* We can now request the interrupt as we know it's masked
-	 * on the controller. cassini+ has up to 4 interrupts
-	 * that can be used, but you need to do explicit pci interrupt
-	 * mapping to expose them
-	 */
-	if (request_irq(cp->pdev->irq, cas_interrupt,
-			IRQF_SHARED, dev->name, (void *) dev)) {
-		netdev_err(cp->dev, "failed to request irq !\n");
-		err = -EAGAIN;
-		goto err_spare;
-	}
-
-#ifdef USE_NAPI
-	napi_enable(&cp->napi);
-#endif
-	/* init hw */
-	cas_lock_all_save(cp, flags);
-	cas_clean_rings(cp);
-	cas_init_hw(cp, !hw_was_up);
-	cp->opened = 1;
-	cas_unlock_all_restore(cp, flags);
-
-	netif_start_queue(dev);
-	mutex_unlock(&cp->pm_mutex);
-	return 0;
-
-err_spare:
-	cas_spare_free(cp);
-	cas_free_rxds(cp);
-err_tx_tiny:
-	cas_tx_tiny_free(cp);
-err_unlock:
-	mutex_unlock(&cp->pm_mutex);
-	return err;
-}
-
-static int cas_close(struct net_device *dev)
-{
-	unsigned long flags;
-	struct cas *cp = netdev_priv(dev);
-
-#ifdef USE_NAPI
-	napi_disable(&cp->napi);
-#endif
-	/* Make sure we don't get distracted by suspend/resume */
-	mutex_lock(&cp->pm_mutex);
-
-	netif_stop_queue(dev);
-
-	/* Stop traffic, mark us closed */
-	cas_lock_all_save(cp, flags);
-	cp->opened = 0;
-	cas_reset(cp, 0);
-	cas_phy_init(cp);
-	cas_begin_auto_negotiation(cp, NULL);
-	cas_clean_rings(cp);
-	cas_unlock_all_restore(cp, flags);
-
-	free_irq(cp->pdev->irq, (void *) dev);
-	cas_spare_free(cp);
-	cas_free_rxds(cp);
-	cas_tx_tiny_free(cp);
-	mutex_unlock(&cp->pm_mutex);
-	return 0;
-}
-
-static struct {
-	const char name[ETH_GSTRING_LEN];
-} ethtool_cassini_statnames[] = {
-	{"collisions"},
-	{"rx_bytes"},
-	{"rx_crc_errors"},
-	{"rx_dropped"},
-	{"rx_errors"},
-	{"rx_fifo_errors"},
-	{"rx_frame_errors"},
-	{"rx_length_errors"},
-	{"rx_over_errors"},
-	{"rx_packets"},
-	{"tx_aborted_errors"},
-	{"tx_bytes"},
-	{"tx_dropped"},
-	{"tx_errors"},
-	{"tx_fifo_errors"},
-	{"tx_packets"}
-};
-#define CAS_NUM_STAT_KEYS ARRAY_SIZE(ethtool_cassini_statnames)
-
-static struct {
-	const int offsets;	/* neg. values for 2nd arg to cas_read_phy */
-} ethtool_register_table[] = {
-	{-MII_BMSR},
-	{-MII_BMCR},
-	{REG_CAWR},
-	{REG_INF_BURST},
-	{REG_BIM_CFG},
-	{REG_RX_CFG},
-	{REG_HP_CFG},
-	{REG_MAC_TX_CFG},
-	{REG_MAC_RX_CFG},
-	{REG_MAC_CTRL_CFG},
-	{REG_MAC_XIF_CFG},
-	{REG_MIF_CFG},
-	{REG_PCS_CFG},
-	{REG_SATURN_PCFG},
-	{REG_PCS_MII_STATUS},
-	{REG_PCS_STATE_MACHINE},
-	{REG_MAC_COLL_EXCESS},
-	{REG_MAC_COLL_LATE}
-};
-#define CAS_REG_LEN 	ARRAY_SIZE(ethtool_register_table)
-#define CAS_MAX_REGS 	(sizeof (u32)*CAS_REG_LEN)
-
-static void cas_read_regs(struct cas *cp, u8 *ptr, int len)
-{
-	u8 *p;
-	int i;
-	unsigned long flags;
-
-	spin_lock_irqsave(&cp->lock, flags);
-	for (i = 0, p = ptr; i < len ; i ++, p += sizeof(u32)) {
-		u16 hval;
-		u32 val;
-		if (ethtool_register_table[i].offsets < 0) {
-			hval = cas_phy_read(cp,
-				    -ethtool_register_table[i].offsets);
-			val = hval;
-		} else {
-			val= readl(cp->regs+ethtool_register_table[i].offsets);
-		}
-		memcpy(p, (u8 *)&val, sizeof(u32));
-	}
-	spin_unlock_irqrestore(&cp->lock, flags);
-}
-
-static struct net_device_stats *cas_get_stats(struct net_device *dev)
-{
-	struct cas *cp = netdev_priv(dev);
-	struct net_device_stats *stats = cp->net_stats;
-	unsigned long flags;
-	int i;
-	unsigned long tmp;
-
-	/* we collate all of the stats into net_stats[N_TX_RING] */
-	if (!cp->hw_running)
-		return stats + N_TX_RINGS;
-
-	/* collect outstanding stats */
-	/* WTZ: the Cassini spec gives these as 16 bit counters but
-	 * stored in 32-bit words.  Added a mask of 0xffff to be safe,
-	 * in case the chip somehow puts any garbage in the other bits.
-	 * Also, counter usage didn't seem to mach what Adrian did
-	 * in the parts of the code that set these quantities. Made
-	 * that consistent.
-	 */
-	spin_lock_irqsave(&cp->stat_lock[N_TX_RINGS], flags);
-	stats[N_TX_RINGS].rx_crc_errors +=
-	  readl(cp->regs + REG_MAC_FCS_ERR) & 0xffff;
-	stats[N_TX_RINGS].rx_frame_errors +=
-		readl(cp->regs + REG_MAC_ALIGN_ERR) &0xffff;
-	stats[N_TX_RINGS].rx_length_errors +=
-		readl(cp->regs + REG_MAC_LEN_ERR) & 0xffff;
-#if 1
-	tmp = (readl(cp->regs + REG_MAC_COLL_EXCESS) & 0xffff) +
-		(readl(cp->regs + REG_MAC_COLL_LATE) & 0xffff);
-	stats[N_TX_RINGS].tx_aborted_errors += tmp;
-	stats[N_TX_RINGS].collisions +=
-	  tmp + (readl(cp->regs + REG_MAC_COLL_NORMAL) & 0xffff);
-#else
-	stats[N_TX_RINGS].tx_aborted_errors +=
-		readl(cp->regs + REG_MAC_COLL_EXCESS);
-	stats[N_TX_RINGS].collisions += readl(cp->regs + REG_MAC_COLL_EXCESS) +
-		readl(cp->regs + REG_MAC_COLL_LATE);
-#endif
-	cas_clear_mac_err(cp);
-
-	/* saved bits that are unique to ring 0 */
-	spin_lock(&cp->stat_lock[0]);
-	stats[N_TX_RINGS].collisions        += stats[0].collisions;
-	stats[N_TX_RINGS].rx_over_errors    += stats[0].rx_over_errors;
-	stats[N_TX_RINGS].rx_frame_errors   += stats[0].rx_frame_errors;
-	stats[N_TX_RINGS].rx_fifo_errors    += stats[0].rx_fifo_errors;
-	stats[N_TX_RINGS].tx_aborted_errors += stats[0].tx_aborted_errors;
-	stats[N_TX_RINGS].tx_fifo_errors    += stats[0].tx_fifo_errors;
-	spin_unlock(&cp->stat_lock[0]);
-
-	for (i = 0; i < N_TX_RINGS; i++) {
-		spin_lock(&cp->stat_lock[i]);
-		stats[N_TX_RINGS].rx_length_errors +=
-			stats[i].rx_length_errors;
-		stats[N_TX_RINGS].rx_crc_errors += stats[i].rx_crc_errors;
-		stats[N_TX_RINGS].rx_packets    += stats[i].rx_packets;
-		stats[N_TX_RINGS].tx_packets    += stats[i].tx_packets;
-		stats[N_TX_RINGS].rx_bytes      += stats[i].rx_bytes;
-		stats[N_TX_RINGS].tx_bytes      += stats[i].tx_bytes;
-		stats[N_TX_RINGS].rx_errors     += stats[i].rx_errors;
-		stats[N_TX_RINGS].tx_errors     += stats[i].tx_errors;
-		stats[N_TX_RINGS].rx_dropped    += stats[i].rx_dropped;
-		stats[N_TX_RINGS].tx_dropped    += stats[i].tx_dropped;
-		memset(stats + i, 0, sizeof(struct net_device_stats));
-		spin_unlock(&cp->stat_lock[i]);
-	}
-	spin_unlock_irqrestore(&cp->stat_lock[N_TX_RINGS], flags);
-	return stats + N_TX_RINGS;
-}
-
-
-static void cas_set_multicast(struct net_device *dev)
-{
-	struct cas *cp = netdev_priv(dev);
-	u32 rxcfg, rxcfg_new;
-	unsigned long flags;
-	int limit = STOP_TRIES;
-
-	if (!cp->hw_running)
-		return;
-
-	spin_lock_irqsave(&cp->lock, flags);
-	rxcfg = readl(cp->regs + REG_MAC_RX_CFG);
-
-	/* disable RX MAC and wait for completion */
-	writel(rxcfg & ~MAC_RX_CFG_EN, cp->regs + REG_MAC_RX_CFG);
-	while (readl(cp->regs + REG_MAC_RX_CFG) & MAC_RX_CFG_EN) {
-		if (!limit--)
-			break;
-		udelay(10);
-	}
-
-	/* disable hash filter and wait for completion */
-	limit = STOP_TRIES;
-	rxcfg &= ~(MAC_RX_CFG_PROMISC_EN | MAC_RX_CFG_HASH_FILTER_EN);
-	writel(rxcfg & ~MAC_RX_CFG_EN, cp->regs + REG_MAC_RX_CFG);
-	while (readl(cp->regs + REG_MAC_RX_CFG) & MAC_RX_CFG_HASH_FILTER_EN) {
-		if (!limit--)
-			break;
-		udelay(10);
-	}
-
-	/* program hash filters */
-	cp->mac_rx_cfg = rxcfg_new = cas_setup_multicast(cp);
-	rxcfg |= rxcfg_new;
-	writel(rxcfg, cp->regs + REG_MAC_RX_CFG);
-	spin_unlock_irqrestore(&cp->lock, flags);
-}
-
-static void cas_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct cas *cp = netdev_priv(dev);
-	strncpy(info->driver, DRV_MODULE_NAME, ETHTOOL_BUSINFO_LEN);
-	strncpy(info->version, DRV_MODULE_VERSION, ETHTOOL_BUSINFO_LEN);
-	info->fw_version[0] = '\0';
-	strncpy(info->bus_info, pci_name(cp->pdev), ETHTOOL_BUSINFO_LEN);
-	info->regdump_len = cp->casreg_len < CAS_MAX_REGS ?
-		cp->casreg_len : CAS_MAX_REGS;
-	info->n_stats = CAS_NUM_STAT_KEYS;
-}
-
-static int cas_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct cas *cp = netdev_priv(dev);
-	u16 bmcr;
-	int full_duplex, speed, pause;
-	unsigned long flags;
-	enum link_state linkstate = link_up;
-
-	cmd->advertising = 0;
-	cmd->supported = SUPPORTED_Autoneg;
-	if (cp->cas_flags & CAS_FLAG_1000MB_CAP) {
-		cmd->supported |= SUPPORTED_1000baseT_Full;
-		cmd->advertising |= ADVERTISED_1000baseT_Full;
-	}
-
-	/* Record PHY settings if HW is on. */
-	spin_lock_irqsave(&cp->lock, flags);
-	bmcr = 0;
-	linkstate = cp->lstate;
-	if (CAS_PHY_MII(cp->phy_type)) {
-		cmd->port = PORT_MII;
-		cmd->transceiver = (cp->cas_flags & CAS_FLAG_SATURN) ?
-			XCVR_INTERNAL : XCVR_EXTERNAL;
-		cmd->phy_address = cp->phy_addr;
-		cmd->advertising |= ADVERTISED_TP | ADVERTISED_MII |
-			ADVERTISED_10baseT_Half |
-			ADVERTISED_10baseT_Full |
-			ADVERTISED_100baseT_Half |
-			ADVERTISED_100baseT_Full;
-
-		cmd->supported |=
-			(SUPPORTED_10baseT_Half |
-			 SUPPORTED_10baseT_Full |
-			 SUPPORTED_100baseT_Half |
-			 SUPPORTED_100baseT_Full |
-			 SUPPORTED_TP | SUPPORTED_MII);
-
-		if (cp->hw_running) {
-			cas_mif_poll(cp, 0);
-			bmcr = cas_phy_read(cp, MII_BMCR);
-			cas_read_mii_link_mode(cp, &full_duplex,
-					       &speed, &pause);
-			cas_mif_poll(cp, 1);
-		}
-
-	} else {
-		cmd->port = PORT_FIBRE;
-		cmd->transceiver = XCVR_INTERNAL;
-		cmd->phy_address = 0;
-		cmd->supported   |= SUPPORTED_FIBRE;
-		cmd->advertising |= ADVERTISED_FIBRE;
-
-		if (cp->hw_running) {
-			/* pcs uses the same bits as mii */
-			bmcr = readl(cp->regs + REG_PCS_MII_CTRL);
-			cas_read_pcs_link_mode(cp, &full_duplex,
-					       &speed, &pause);
-		}
-	}
-	spin_unlock_irqrestore(&cp->lock, flags);
-
-	if (bmcr & BMCR_ANENABLE) {
-		cmd->advertising |= ADVERTISED_Autoneg;
-		cmd->autoneg = AUTONEG_ENABLE;
-		ethtool_cmd_speed_set(cmd, ((speed == 10) ?
-					    SPEED_10 :
-					    ((speed == 1000) ?
-					     SPEED_1000 : SPEED_100)));
-		cmd->duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
-	} else {
-		cmd->autoneg = AUTONEG_DISABLE;
-		ethtool_cmd_speed_set(cmd, ((bmcr & CAS_BMCR_SPEED1000) ?
-					    SPEED_1000 :
-					    ((bmcr & BMCR_SPEED100) ?
-					     SPEED_100 : SPEED_10)));
-		cmd->duplex =
-			(bmcr & BMCR_FULLDPLX) ?
-			DUPLEX_FULL : DUPLEX_HALF;
-	}
-	if (linkstate != link_up) {
-		/* Force these to "unknown" if the link is not up and
-		 * autonogotiation in enabled. We can set the link
-		 * speed to 0, but not cmd->duplex,
-		 * because its legal values are 0 and 1.  Ethtool will
-		 * print the value reported in parentheses after the
-		 * word "Unknown" for unrecognized values.
-		 *
-		 * If in forced mode, we report the speed and duplex
-		 * settings that we configured.
-		 */
-		if (cp->link_cntl & BMCR_ANENABLE) {
-			ethtool_cmd_speed_set(cmd, 0);
-			cmd->duplex = 0xff;
-		} else {
-			ethtool_cmd_speed_set(cmd, SPEED_10);
-			if (cp->link_cntl & BMCR_SPEED100) {
-				ethtool_cmd_speed_set(cmd, SPEED_100);
-			} else if (cp->link_cntl & CAS_BMCR_SPEED1000) {
-				ethtool_cmd_speed_set(cmd, SPEED_1000);
-			}
-			cmd->duplex = (cp->link_cntl & BMCR_FULLDPLX)?
-				DUPLEX_FULL : DUPLEX_HALF;
-		}
-	}
-	return 0;
-}
-
-static int cas_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct cas *cp = netdev_priv(dev);
-	unsigned long flags;
-	u32 speed = ethtool_cmd_speed(cmd);
-
-	/* Verify the settings we care about. */
-	if (cmd->autoneg != AUTONEG_ENABLE &&
-	    cmd->autoneg != AUTONEG_DISABLE)
-		return -EINVAL;
-
-	if (cmd->autoneg == AUTONEG_DISABLE &&
-	    ((speed != SPEED_1000 &&
-	      speed != SPEED_100 &&
-	      speed != SPEED_10) ||
-	     (cmd->duplex != DUPLEX_HALF &&
-	      cmd->duplex != DUPLEX_FULL)))
-		return -EINVAL;
-
-	/* Apply settings and restart link process. */
-	spin_lock_irqsave(&cp->lock, flags);
-	cas_begin_auto_negotiation(cp, cmd);
-	spin_unlock_irqrestore(&cp->lock, flags);
-	return 0;
-}
-
-static int cas_nway_reset(struct net_device *dev)
-{
-	struct cas *cp = netdev_priv(dev);
-	unsigned long flags;
-
-	if ((cp->link_cntl & BMCR_ANENABLE) == 0)
-		return -EINVAL;
-
-	/* Restart link process. */
-	spin_lock_irqsave(&cp->lock, flags);
-	cas_begin_auto_negotiation(cp, NULL);
-	spin_unlock_irqrestore(&cp->lock, flags);
-
-	return 0;
-}
-
-static u32 cas_get_link(struct net_device *dev)
-{
-	struct cas *cp = netdev_priv(dev);
-	return cp->lstate == link_up;
-}
-
-static u32 cas_get_msglevel(struct net_device *dev)
-{
-	struct cas *cp = netdev_priv(dev);
-	return cp->msg_enable;
-}
-
-static void cas_set_msglevel(struct net_device *dev, u32 value)
-{
-	struct cas *cp = netdev_priv(dev);
-	cp->msg_enable = value;
-}
-
-static int cas_get_regs_len(struct net_device *dev)
-{
-	struct cas *cp = netdev_priv(dev);
-	return cp->casreg_len < CAS_MAX_REGS ? cp->casreg_len: CAS_MAX_REGS;
-}
-
-static void cas_get_regs(struct net_device *dev, struct ethtool_regs *regs,
-			     void *p)
-{
-	struct cas *cp = netdev_priv(dev);
-	regs->version = 0;
-	/* cas_read_regs handles locks (cp->lock).  */
-	cas_read_regs(cp, p, regs->len / sizeof(u32));
-}
-
-static int cas_get_sset_count(struct net_device *dev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		return CAS_NUM_STAT_KEYS;
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void cas_get_strings(struct net_device *dev, u32 stringset, u8 *data)
-{
-	 memcpy(data, &ethtool_cassini_statnames,
-					 CAS_NUM_STAT_KEYS * ETH_GSTRING_LEN);
-}
-
-static void cas_get_ethtool_stats(struct net_device *dev,
-				      struct ethtool_stats *estats, u64 *data)
-{
-	struct cas *cp = netdev_priv(dev);
-	struct net_device_stats *stats = cas_get_stats(cp->dev);
-	int i = 0;
-	data[i++] = stats->collisions;
-	data[i++] = stats->rx_bytes;
-	data[i++] = stats->rx_crc_errors;
-	data[i++] = stats->rx_dropped;
-	data[i++] = stats->rx_errors;
-	data[i++] = stats->rx_fifo_errors;
-	data[i++] = stats->rx_frame_errors;
-	data[i++] = stats->rx_length_errors;
-	data[i++] = stats->rx_over_errors;
-	data[i++] = stats->rx_packets;
-	data[i++] = stats->tx_aborted_errors;
-	data[i++] = stats->tx_bytes;
-	data[i++] = stats->tx_dropped;
-	data[i++] = stats->tx_errors;
-	data[i++] = stats->tx_fifo_errors;
-	data[i++] = stats->tx_packets;
-	BUG_ON(i != CAS_NUM_STAT_KEYS);
-}
-
-static const struct ethtool_ops cas_ethtool_ops = {
-	.get_drvinfo		= cas_get_drvinfo,
-	.get_settings		= cas_get_settings,
-	.set_settings		= cas_set_settings,
-	.nway_reset		= cas_nway_reset,
-	.get_link		= cas_get_link,
-	.get_msglevel		= cas_get_msglevel,
-	.set_msglevel		= cas_set_msglevel,
-	.get_regs_len		= cas_get_regs_len,
-	.get_regs		= cas_get_regs,
-	.get_sset_count		= cas_get_sset_count,
-	.get_strings		= cas_get_strings,
-	.get_ethtool_stats	= cas_get_ethtool_stats,
-};
-
-static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	struct cas *cp = netdev_priv(dev);
-	struct mii_ioctl_data *data = if_mii(ifr);
-	unsigned long flags;
-	int rc = -EOPNOTSUPP;
-
-	/* Hold the PM mutex while doing ioctl's or we may collide
-	 * with open/close and power management and oops.
-	 */
-	mutex_lock(&cp->pm_mutex);
-	switch (cmd) {
-	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-		data->phy_id = cp->phy_addr;
-		/* Fallthrough... */
-
-	case SIOCGMIIREG:		/* Read MII PHY register. */
-		spin_lock_irqsave(&cp->lock, flags);
-		cas_mif_poll(cp, 0);
-		data->val_out = cas_phy_read(cp, data->reg_num & 0x1f);
-		cas_mif_poll(cp, 1);
-		spin_unlock_irqrestore(&cp->lock, flags);
-		rc = 0;
-		break;
-
-	case SIOCSMIIREG:		/* Write MII PHY register. */
-		spin_lock_irqsave(&cp->lock, flags);
-		cas_mif_poll(cp, 0);
-		rc = cas_phy_write(cp, data->reg_num & 0x1f, data->val_in);
-		cas_mif_poll(cp, 1);
-		spin_unlock_irqrestore(&cp->lock, flags);
-		break;
-	default:
-		break;
-	}
-
-	mutex_unlock(&cp->pm_mutex);
-	return rc;
-}
-
-/* When this chip sits underneath an Intel 31154 bridge, it is the
- * only subordinate device and we can tweak the bridge settings to
- * reflect that fact.
- */
-static void __devinit cas_program_bridge(struct pci_dev *cas_pdev)
-{
-	struct pci_dev *pdev = cas_pdev->bus->self;
-	u32 val;
-
-	if (!pdev)
-		return;
-
-	if (pdev->vendor != 0x8086 || pdev->device != 0x537c)
-		return;
-
-	/* Clear bit 10 (Bus Parking Control) in the Secondary
-	 * Arbiter Control/Status Register which lives at offset
-	 * 0x41.  Using a 32-bit word read/modify/write at 0x40
-	 * is much simpler so that's how we do this.
-	 */
-	pci_read_config_dword(pdev, 0x40, &val);
-	val &= ~0x00040000;
-	pci_write_config_dword(pdev, 0x40, val);
-
-	/* Max out the Multi-Transaction Timer settings since
-	 * Cassini is the only device present.
-	 *
-	 * The register is 16-bit and lives at 0x50.  When the
-	 * settings are enabled, it extends the GRANT# signal
-	 * for a requestor after a transaction is complete.  This
-	 * allows the next request to run without first needing
-	 * to negotiate the GRANT# signal back.
-	 *
-	 * Bits 12:10 define the grant duration:
-	 *
-	 *	1	--	16 clocks
-	 *	2	--	32 clocks
-	 *	3	--	64 clocks
-	 *	4	--	128 clocks
-	 *	5	--	256 clocks
-	 *
-	 * All other values are illegal.
-	 *
-	 * Bits 09:00 define which REQ/GNT signal pairs get the
-	 * GRANT# signal treatment.  We set them all.
-	 */
-	pci_write_config_word(pdev, 0x50, (5 << 10) | 0x3ff);
-
-	/* The Read Prefecth Policy register is 16-bit and sits at
-	 * offset 0x52.  It enables a "smart" pre-fetch policy.  We
-	 * enable it and max out all of the settings since only one
-	 * device is sitting underneath and thus bandwidth sharing is
-	 * not an issue.
-	 *
-	 * The register has several 3 bit fields, which indicates a
-	 * multiplier applied to the base amount of prefetching the
-	 * chip would do.  These fields are at:
-	 *
-	 *	15:13	---	ReRead Primary Bus
-	 *	12:10	---	FirstRead Primary Bus
-	 *	09:07	---	ReRead Secondary Bus
-	 *	06:04	---	FirstRead Secondary Bus
-	 *
-	 * Bits 03:00 control which REQ/GNT pairs the prefetch settings
-	 * get enabled on.  Bit 3 is a grouped enabler which controls
-	 * all of the REQ/GNT pairs from [8:3].  Bits 2 to 0 control
-	 * the individual REQ/GNT pairs [2:0].
-	 */
-	pci_write_config_word(pdev, 0x52,
-			      (0x7 << 13) |
-			      (0x7 << 10) |
-			      (0x7 <<  7) |
-			      (0x7 <<  4) |
-			      (0xf <<  0));
-
-	/* Force cacheline size to 0x8 */
-	pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
-
-	/* Force latency timer to maximum setting so Cassini can
-	 * sit on the bus as long as it likes.
-	 */
-	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xff);
-}
-
-static const struct net_device_ops cas_netdev_ops = {
-	.ndo_open		= cas_open,
-	.ndo_stop		= cas_close,
-	.ndo_start_xmit		= cas_start_xmit,
-	.ndo_get_stats 		= cas_get_stats,
-	.ndo_set_multicast_list = cas_set_multicast,
-	.ndo_do_ioctl		= cas_ioctl,
-	.ndo_tx_timeout		= cas_tx_timeout,
-	.ndo_change_mtu		= cas_change_mtu,
-	.ndo_set_mac_address	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= cas_netpoll,
-#endif
-};
-
-static int __devinit cas_init_one(struct pci_dev *pdev,
-				  const struct pci_device_id *ent)
-{
-	static int cas_version_printed = 0;
-	unsigned long casreg_len;
-	struct net_device *dev;
-	struct cas *cp;
-	int i, err, pci_using_dac;
-	u16 pci_cmd;
-	u8 orig_cacheline_size = 0, cas_cacheline_size = 0;
-
-	if (cas_version_printed++ == 0)
-		pr_info("%s", version);
-
-	err = pci_enable_device(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n");
-		return err;
-	}
-
-	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
-		dev_err(&pdev->dev, "Cannot find proper PCI device "
-		       "base address, aborting\n");
-		err = -ENODEV;
-		goto err_out_disable_pdev;
-	}
-
-	dev = alloc_etherdev(sizeof(*cp));
-	if (!dev) {
-		dev_err(&pdev->dev, "Etherdev alloc failed, aborting\n");
-		err = -ENOMEM;
-		goto err_out_disable_pdev;
-	}
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-	err = pci_request_regions(pdev, dev->name);
-	if (err) {
-		dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting\n");
-		goto err_out_free_netdev;
-	}
-	pci_set_master(pdev);
-
-	/* we must always turn on parity response or else parity
-	 * doesn't get generated properly. disable SERR/PERR as well.
-	 * in addition, we want to turn MWI on.
-	 */
-	pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
-	pci_cmd &= ~PCI_COMMAND_SERR;
-	pci_cmd |= PCI_COMMAND_PARITY;
-	pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
-	if (pci_try_set_mwi(pdev))
-		pr_warning("Could not enable MWI for %s\n", pci_name(pdev));
-
-	cas_program_bridge(pdev);
-
-	/*
-	 * On some architectures, the default cache line size set
-	 * by pci_try_set_mwi reduces perforamnce.  We have to increase
-	 * it for this case.  To start, we'll print some configuration
-	 * data.
-	 */
-#if 1
-	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE,
-			     &orig_cacheline_size);
-	if (orig_cacheline_size < CAS_PREF_CACHELINE_SIZE) {
-		cas_cacheline_size =
-			(CAS_PREF_CACHELINE_SIZE < SMP_CACHE_BYTES) ?
-			CAS_PREF_CACHELINE_SIZE : SMP_CACHE_BYTES;
-		if (pci_write_config_byte(pdev,
-					  PCI_CACHE_LINE_SIZE,
-					  cas_cacheline_size)) {
-			dev_err(&pdev->dev, "Could not set PCI cache "
-			       "line size\n");
-			goto err_write_cacheline;
-		}
-	}
-#endif
-
-
-	/* Configure DMA attributes. */
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-		pci_using_dac = 1;
-		err = pci_set_consistent_dma_mask(pdev,
-						  DMA_BIT_MASK(64));
-		if (err < 0) {
-			dev_err(&pdev->dev, "Unable to obtain 64-bit DMA "
-			       "for consistent allocations\n");
-			goto err_out_free_res;
-		}
-
-	} else {
-		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-		if (err) {
-			dev_err(&pdev->dev, "No usable DMA configuration, "
-			       "aborting\n");
-			goto err_out_free_res;
-		}
-		pci_using_dac = 0;
-	}
-
-	casreg_len = pci_resource_len(pdev, 0);
-
-	cp = netdev_priv(dev);
-	cp->pdev = pdev;
-#if 1
-	/* A value of 0 indicates we never explicitly set it */
-	cp->orig_cacheline_size = cas_cacheline_size ? orig_cacheline_size: 0;
-#endif
-	cp->dev = dev;
-	cp->msg_enable = (cassini_debug < 0) ? CAS_DEF_MSG_ENABLE :
-	  cassini_debug;
-
-#if defined(CONFIG_SPARC)
-	cp->of_node = pci_device_to_OF_node(pdev);
-#endif
-
-	cp->link_transition = LINK_TRANSITION_UNKNOWN;
-	cp->link_transition_jiffies_valid = 0;
-
-	spin_lock_init(&cp->lock);
-	spin_lock_init(&cp->rx_inuse_lock);
-	spin_lock_init(&cp->rx_spare_lock);
-	for (i = 0; i < N_TX_RINGS; i++) {
-		spin_lock_init(&cp->stat_lock[i]);
-		spin_lock_init(&cp->tx_lock[i]);
-	}
-	spin_lock_init(&cp->stat_lock[N_TX_RINGS]);
-	mutex_init(&cp->pm_mutex);
-
-	init_timer(&cp->link_timer);
-	cp->link_timer.function = cas_link_timer;
-	cp->link_timer.data = (unsigned long) cp;
-
-#if 1
-	/* Just in case the implementation of atomic operations
-	 * change so that an explicit initialization is necessary.
-	 */
-	atomic_set(&cp->reset_task_pending, 0);
-	atomic_set(&cp->reset_task_pending_all, 0);
-	atomic_set(&cp->reset_task_pending_spare, 0);
-	atomic_set(&cp->reset_task_pending_mtu, 0);
-#endif
-	INIT_WORK(&cp->reset_task, cas_reset_task);
-
-	/* Default link parameters */
-	if (link_mode >= 0 && link_mode < 6)
-		cp->link_cntl = link_modes[link_mode];
-	else
-		cp->link_cntl = BMCR_ANENABLE;
-	cp->lstate = link_down;
-	cp->link_transition = LINK_TRANSITION_LINK_DOWN;
-	netif_carrier_off(cp->dev);
-	cp->timer_ticks = 0;
-
-	/* give us access to cassini registers */
-	cp->regs = pci_iomap(pdev, 0, casreg_len);
-	if (!cp->regs) {
-		dev_err(&pdev->dev, "Cannot map device registers, aborting\n");
-		goto err_out_free_res;
-	}
-	cp->casreg_len = casreg_len;
-
-	pci_save_state(pdev);
-	cas_check_pci_invariants(cp);
-	cas_hard_reset(cp);
-	cas_reset(cp, 0);
-	if (cas_check_invariants(cp))
-		goto err_out_iounmap;
-	if (cp->cas_flags & CAS_FLAG_SATURN)
-		if (cas_saturn_firmware_init(cp))
-			goto err_out_iounmap;
-
-	cp->init_block = (struct cas_init_block *)
-		pci_alloc_consistent(pdev, sizeof(struct cas_init_block),
-				     &cp->block_dvma);
-	if (!cp->init_block) {
-		dev_err(&pdev->dev, "Cannot allocate init block, aborting\n");
-		goto err_out_iounmap;
-	}
-
-	for (i = 0; i < N_TX_RINGS; i++)
-		cp->init_txds[i] = cp->init_block->txds[i];
-
-	for (i = 0; i < N_RX_DESC_RINGS; i++)
-		cp->init_rxds[i] = cp->init_block->rxds[i];
-
-	for (i = 0; i < N_RX_COMP_RINGS; i++)
-		cp->init_rxcs[i] = cp->init_block->rxcs[i];
-
-	for (i = 0; i < N_RX_FLOWS; i++)
-		skb_queue_head_init(&cp->rx_flows[i]);
-
-	dev->netdev_ops = &cas_netdev_ops;
-	dev->ethtool_ops = &cas_ethtool_ops;
-	dev->watchdog_timeo = CAS_TX_TIMEOUT;
-
-#ifdef USE_NAPI
-	netif_napi_add(dev, &cp->napi, cas_poll, 64);
-#endif
-	dev->irq = pdev->irq;
-	dev->dma = 0;
-
-	/* Cassini features. */
-	if ((cp->cas_flags & CAS_FLAG_NO_HW_CSUM) == 0)
-		dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
-
-	if (pci_using_dac)
-		dev->features |= NETIF_F_HIGHDMA;
-
-	if (register_netdev(dev)) {
-		dev_err(&pdev->dev, "Cannot register net device, aborting\n");
-		goto err_out_free_consistent;
-	}
-
-	i = readl(cp->regs + REG_BIM_CFG);
-	netdev_info(dev, "Sun Cassini%s (%sbit/%sMHz PCI/%s) Ethernet[%d] %pM\n",
-		    (cp->cas_flags & CAS_FLAG_REG_PLUS) ? "+" : "",
-		    (i & BIM_CFG_32BIT) ? "32" : "64",
-		    (i & BIM_CFG_66MHZ) ? "66" : "33",
-		    (cp->phy_type == CAS_PHY_SERDES) ? "Fi" : "Cu", pdev->irq,
-		    dev->dev_addr);
-
-	pci_set_drvdata(pdev, dev);
-	cp->hw_running = 1;
-	cas_entropy_reset(cp);
-	cas_phy_init(cp);
-	cas_begin_auto_negotiation(cp, NULL);
-	return 0;
-
-err_out_free_consistent:
-	pci_free_consistent(pdev, sizeof(struct cas_init_block),
-			    cp->init_block, cp->block_dvma);
-
-err_out_iounmap:
-	mutex_lock(&cp->pm_mutex);
-	if (cp->hw_running)
-		cas_shutdown(cp);
-	mutex_unlock(&cp->pm_mutex);
-
-	pci_iounmap(pdev, cp->regs);
-
-
-err_out_free_res:
-	pci_release_regions(pdev);
-
-err_write_cacheline:
-	/* 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);
-
-err_out_free_netdev:
-	free_netdev(dev);
-
-err_out_disable_pdev:
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-	return -ENODEV;
-}
-
-static void __devexit cas_remove_one(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct cas *cp;
-	if (!dev)
-		return;
-
-	cp = netdev_priv(dev);
-	unregister_netdev(dev);
-
-	if (cp->fw_data)
-		vfree(cp->fw_data);
-
-	mutex_lock(&cp->pm_mutex);
-	cancel_work_sync(&cp->reset_task);
-	if (cp->hw_running)
-		cas_shutdown(cp);
-	mutex_unlock(&cp->pm_mutex);
-
-#if 1
-	if (cp->orig_cacheline_size) {
-		/* Restore the cache line size if we had modified
-		 * it.
-		 */
-		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE,
-				      cp->orig_cacheline_size);
-	}
-#endif
-	pci_free_consistent(pdev, sizeof(struct cas_init_block),
-			    cp->init_block, cp->block_dvma);
-	pci_iounmap(pdev, cp->regs);
-	free_netdev(dev);
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-}
-
-#ifdef CONFIG_PM
-static int cas_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct cas *cp = netdev_priv(dev);
-	unsigned long flags;
-
-	mutex_lock(&cp->pm_mutex);
-
-	/* If the driver is opened, we stop the DMA */
-	if (cp->opened) {
-		netif_device_detach(dev);
-
-		cas_lock_all_save(cp, flags);
-
-		/* We can set the second arg of cas_reset to 0
-		 * because on resume, we'll call cas_init_hw with
-		 * its second arg set so that autonegotiation is
-		 * restarted.
-		 */
-		cas_reset(cp, 0);
-		cas_clean_rings(cp);
-		cas_unlock_all_restore(cp, flags);
-	}
-
-	if (cp->hw_running)
-		cas_shutdown(cp);
-	mutex_unlock(&cp->pm_mutex);
-
-	return 0;
-}
-
-static int cas_resume(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct cas *cp = netdev_priv(dev);
-
-	netdev_info(dev, "resuming\n");
-
-	mutex_lock(&cp->pm_mutex);
-	cas_hard_reset(cp);
-	if (cp->opened) {
-		unsigned long flags;
-		cas_lock_all_save(cp, flags);
-		cas_reset(cp, 0);
-		cp->hw_running = 1;
-		cas_clean_rings(cp);
-		cas_init_hw(cp, 1);
-		cas_unlock_all_restore(cp, flags);
-
-		netif_device_attach(dev);
-	}
-	mutex_unlock(&cp->pm_mutex);
-	return 0;
-}
-#endif /* CONFIG_PM */
-
-static struct pci_driver cas_driver = {
-	.name		= DRV_MODULE_NAME,
-	.id_table	= cas_pci_tbl,
-	.probe		= cas_init_one,
-	.remove		= __devexit_p(cas_remove_one),
-#ifdef CONFIG_PM
-	.suspend	= cas_suspend,
-	.resume		= cas_resume
-#endif
-};
-
-static int __init cas_init(void)
-{
-	if (linkdown_timeout > 0)
-		link_transition_timeout = linkdown_timeout * HZ;
-	else
-		link_transition_timeout = 0;
-
-	return pci_register_driver(&cas_driver);
-}
-
-static void __exit cas_cleanup(void)
-{
-	pci_unregister_driver(&cas_driver);
-}
-
-module_init(cas_init);
-module_exit(cas_cleanup);
diff -druN linux-libre-3.1-gnu/drivers/net/cassini.h linux-libre-3.2-gnu/drivers/net/cassini.h
--- linux-libre-3.1-gnu/drivers/net/cassini.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cassini.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,2914 +0,0 @@
-/* $Id: cassini.h,v 1.16 2004/08/17 21:15:16 zaumen Exp $
- * cassini.h: Definitions for Sun Microsystems Cassini(+) ethernet driver.
- *
- * Copyright (C) 2004 Sun Microsystems Inc.
- * Copyright (c) 2003 Adrian Sun (asun@darksunrising.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.
- *
- * vendor id: 0x108E (Sun Microsystems, Inc.)
- * device id: 0xabba (Cassini)
- * revision ids: 0x01 = Cassini
- *               0x02 = Cassini rev 2
- *               0x10 = Cassini+
- *               0x11 = Cassini+ 0.2u
- *
- * vendor id: 0x100b (National Semiconductor)
- * device id: 0x0035 (DP83065/Saturn)
- * revision ids: 0x30 = Saturn B2
- *
- * rings are all offset from 0.
- *
- * there are two clock domains:
- * PCI:  33/66MHz clock
- * chip: 125MHz clock
- */
-
-#ifndef _CASSINI_H
-#define _CASSINI_H
-
-/* cassini register map: 2M memory mapped in 32-bit memory space accessible as
- * 32-bit words. there is no i/o port access. REG_ addresses are
- * shared between cassini and cassini+. REG_PLUS_ addresses only
- * appear in cassini+. REG_MINUS_ addresses only appear in cassini.
- */
-#define CAS_ID_REV2          0x02
-#define CAS_ID_REVPLUS       0x10
-#define CAS_ID_REVPLUS02u    0x11
-#define CAS_ID_REVSATURNB2   0x30
-
-/** global resources **/
-
-/* this register sets the weights for the weighted round robin arbiter. e.g.,
- * if rx weight == 1 and tx weight == 0, rx == 2x tx transfer credit
- * for its next turn to access the pci bus.
- * map: 0x0 = x1, 0x1 = x2, 0x2 = x4, 0x3 = x8
- * DEFAULT: 0x0, SIZE: 5 bits
- */
-#define  REG_CAWR	               0x0004  /* core arbitration weight */
-#define    CAWR_RX_DMA_WEIGHT_SHIFT    0
-#define    CAWR_RX_DMA_WEIGHT_MASK     0x03    /* [0:1] */
-#define    CAWR_TX_DMA_WEIGHT_SHIFT    2
-#define    CAWR_TX_DMA_WEIGHT_MASK     0x0C    /* [3:2] */
-#define    CAWR_RR_DIS                 0x10    /* [4] */
-
-/* if enabled, BIM can send bursts across PCI bus > cacheline size. burst
- * sizes determined by length of packet or descriptor transfer and the
- * max length allowed by the target.
- * DEFAULT: 0x0, SIZE: 1 bit
- */
-#define  REG_INF_BURST                 0x0008  /* infinite burst enable reg */
-#define    INF_BURST_EN                0x1     /* enable */
-
-/* top level interrupts [0-9] are auto-cleared to 0 when the status
- * register is read. second level interrupts [13 - 18] are cleared at
- * the source. tx completion register 3 is replicated in [19 - 31]
- * DEFAULT: 0x00000000, SIZE: 29 bits
- */
-#define  REG_INTR_STATUS               0x000C  /* interrupt status register */
-#define    INTR_TX_INTME               0x00000001  /* frame w/ INT ME desc bit set
-						      xferred from host queue to
-						      TX FIFO */
-#define    INTR_TX_ALL                 0x00000002  /* all xmit frames xferred into
-						      TX FIFO. i.e.,
-						      TX Kick == TX complete. if
-						      PACED_MODE set, then TX FIFO
-						      also empty */
-#define    INTR_TX_DONE                0x00000004  /* any frame xferred into tx
-						      FIFO */
-#define    INTR_TX_TAG_ERROR           0x00000008  /* TX FIFO tag framing
-						      corrupted. FATAL ERROR */
-#define    INTR_RX_DONE                0x00000010  /* at least 1 frame xferred
-						      from RX FIFO to host mem.
-						      RX completion reg updated.
-						      may be delayed by recv
-						      intr blanking. */
-#define    INTR_RX_BUF_UNAVAIL         0x00000020  /* no more receive buffers.
-						      RX Kick == RX complete */
-#define    INTR_RX_TAG_ERROR           0x00000040  /* RX FIFO tag framing
-						      corrupted. FATAL ERROR */
-#define    INTR_RX_COMP_FULL           0x00000080  /* no more room in completion
-						      ring to post descriptors.
-						      RX complete head incr to
-						      almost reach RX complete
-						      tail */
-#define    INTR_RX_BUF_AE              0x00000100  /* less than the
-						      programmable threshold #
-						      of free descr avail for
-						      hw use */
-#define    INTR_RX_COMP_AF             0x00000200  /* less than the
-						      programmable threshold #
-						      of descr spaces for hw
-						      use in completion descr
-						      ring */
-#define    INTR_RX_LEN_MISMATCH        0x00000400  /* len field from MAC !=
-						      len of non-reassembly pkt
-						      from fifo during DMA or
-						      header parser provides TCP
-						      header and payload size >
-						      MAC packet size.
-						      FATAL ERROR */
-#define    INTR_SUMMARY                0x00001000  /* summary interrupt bit. this
-						      bit will be set if an interrupt
-						      generated on the pci bus. useful
-						      when driver is polling for
-						      interrupts */
-#define    INTR_PCS_STATUS             0x00002000  /* PCS interrupt status register */
-#define    INTR_TX_MAC_STATUS          0x00004000  /* TX MAC status register has at
-						      least 1 unmasked interrupt set */
-#define    INTR_RX_MAC_STATUS          0x00008000  /* RX MAC status register has at
-						      least 1 unmasked interrupt set */
-#define    INTR_MAC_CTRL_STATUS        0x00010000  /* MAC control status register has
-						      at least 1 unmasked interrupt
-						      set */
-#define    INTR_MIF_STATUS             0x00020000  /* MIF status register has at least
-						      1 unmasked interrupt set */
-#define    INTR_PCI_ERROR_STATUS       0x00040000  /* PCI error status register in the
-						      BIF has at least 1 unmasked
-						      interrupt set */
-#define    INTR_TX_COMP_3_MASK         0xFFF80000  /* mask for TX completion
-						      3 reg data */
-#define    INTR_TX_COMP_3_SHIFT        19
-#define    INTR_ERROR_MASK (INTR_MIF_STATUS | INTR_PCI_ERROR_STATUS | \
-                            INTR_PCS_STATUS | INTR_RX_LEN_MISMATCH | \
-                            INTR_TX_MAC_STATUS | INTR_RX_MAC_STATUS | \
-                            INTR_TX_TAG_ERROR | INTR_RX_TAG_ERROR | \
-                            INTR_MAC_CTRL_STATUS)
-
-/* determines which status events will cause an interrupt. layout same
- * as REG_INTR_STATUS.
- * DEFAULT: 0xFFFFFFFF, SIZE: 16 bits
- */
-#define  REG_INTR_MASK                 0x0010  /* Interrupt mask */
-
-/* top level interrupt bits that are cleared during read of REG_INTR_STATUS_ALIAS.
- * useful when driver is polling for interrupts. layout same as REG_INTR_MASK.
- * DEFAULT: 0x00000000, SIZE: 12 bits
- */
-#define  REG_ALIAS_CLEAR               0x0014  /* alias clear mask
-						  (used w/ status alias) */
-/* same as REG_INTR_STATUS except that only bits cleared are those selected by
- * REG_ALIAS_CLEAR
- * DEFAULT: 0x00000000, SIZE: 29 bits
- */
-#define  REG_INTR_STATUS_ALIAS         0x001C  /* interrupt status alias
-						  (selective clear) */
-
-/* DEFAULT: 0x0, SIZE: 3 bits */
-#define  REG_PCI_ERR_STATUS            0x1000  /* PCI error status */
-#define    PCI_ERR_BADACK              0x01    /* reserved in Cassini+.
-						  set if no ACK64# during ABS64 cycle
-						  in Cassini. */
-#define    PCI_ERR_DTRTO               0x02    /* delayed xaction timeout. set if
-						  no read retry after 2^15 clocks */
-#define    PCI_ERR_OTHER               0x04    /* other PCI errors */
-#define    PCI_ERR_BIM_DMA_WRITE       0x08    /* BIM received 0 count DMA write req.
-						  unused in Cassini. */
-#define    PCI_ERR_BIM_DMA_READ        0x10    /* BIM received 0 count DMA read req.
-						  unused in Cassini. */
-#define    PCI_ERR_BIM_DMA_TIMEOUT     0x20    /* BIM received 255 retries during
-						  DMA. unused in cassini. */
-
-/* mask for PCI status events that will set PCI_ERR_STATUS. if cleared, event
- * causes an interrupt to be generated.
- * DEFAULT: 0x7, SIZE: 3 bits
- */
-#define  REG_PCI_ERR_STATUS_MASK       0x1004  /* PCI Error status mask */
-
-/* used to configure PCI related parameters that are not in PCI config space.
- * DEFAULT: 0bxx000, SIZE: 5 bits
- */
-#define  REG_BIM_CFG                0x1008  /* BIM Configuration */
-#define    BIM_CFG_RESERVED0        0x001   /* reserved */
-#define    BIM_CFG_RESERVED1        0x002   /* reserved */
-#define    BIM_CFG_64BIT_DISABLE    0x004   /* disable 64-bit mode */
-#define    BIM_CFG_66MHZ            0x008   /* (ro) 1 = 66MHz, 0 = < 66MHz */
-#define    BIM_CFG_32BIT            0x010   /* (ro) 1 = 32-bit slot, 0 = 64-bit */
-#define    BIM_CFG_DPAR_INTR_ENABLE 0x020   /* detected parity err enable */
-#define    BIM_CFG_RMA_INTR_ENABLE  0x040   /* master abort intr enable */
-#define    BIM_CFG_RTA_INTR_ENABLE  0x080   /* target abort intr enable */
-#define    BIM_CFG_RESERVED2        0x100   /* reserved */
-#define    BIM_CFG_BIM_DISABLE      0x200   /* stop BIM DMA. use before global
-					       reset. reserved in Cassini. */
-#define    BIM_CFG_BIM_STATUS       0x400   /* (ro) 1 = BIM DMA suspended.
-						  reserved in Cassini. */
-#define    BIM_CFG_PERROR_BLOCK     0x800  /* block PERR# to pci bus. def: 0.
-						 reserved in Cassini. */
-
-/* DEFAULT: 0x00000000, SIZE: 32 bits */
-#define  REG_BIM_DIAG                  0x100C  /* BIM Diagnostic */
-#define    BIM_DIAG_MSTR_SM_MASK       0x3FFFFF00 /* PCI master controller state
-						     machine bits [21:0] */
-#define    BIM_DIAG_BRST_SM_MASK       0x7F    /* PCI burst controller state
-						  machine bits [6:0] */
-
-/* writing to SW_RESET_TX and SW_RESET_RX will issue a global
- * reset. poll until TX and RX read back as 0's for completion.
- */
-#define  REG_SW_RESET                  0x1010  /* Software reset */
-#define    SW_RESET_TX                 0x00000001  /* reset TX DMA engine. poll until
-						      cleared to 0.  */
-#define    SW_RESET_RX                 0x00000002  /* reset RX DMA engine. poll until
-						      cleared to 0. */
-#define    SW_RESET_RSTOUT             0x00000004  /* force RSTOUT# pin active (low).
-						      resets PHY and anything else
-						      connected to RSTOUT#. RSTOUT#
-						      is also activated by local PCI
-						      reset when hot-swap is being
-						      done. */
-#define    SW_RESET_BLOCK_PCS_SLINK    0x00000008  /* if a global reset is done with
-						      this bit set, PCS and SLINK
-						      modules won't be reset.
-						      i.e., link won't drop. */
-#define    SW_RESET_BREQ_SM_MASK       0x00007F00  /* breq state machine [6:0] */
-#define    SW_RESET_PCIARB_SM_MASK     0x00070000  /* pci arbitration state bits:
-						      0b000: ARB_IDLE1
-						      0b001: ARB_IDLE2
-						      0b010: ARB_WB_ACK
-						      0b011: ARB_WB_WAT
-						      0b100: ARB_RB_ACK
-						      0b101: ARB_RB_WAT
-						      0b110: ARB_RB_END
-						      0b111: ARB_WB_END */
-#define    SW_RESET_RDPCI_SM_MASK      0x00300000  /* read pci state bits:
-						      0b00: RD_PCI_WAT
-						      0b01: RD_PCI_RDY
-						      0b11: RD_PCI_ACK */
-#define    SW_RESET_RDARB_SM_MASK      0x00C00000  /* read arbitration state bits:
-						      0b00: AD_IDL_RX
-						      0b01: AD_ACK_RX
-						      0b10: AD_ACK_TX
-						      0b11: AD_IDL_TX */
-#define    SW_RESET_WRPCI_SM_MASK      0x06000000  /* write pci state bits
-						      0b00: WR_PCI_WAT
-						      0b01: WR_PCI_RDY
-						      0b11: WR_PCI_ACK */
-#define    SW_RESET_WRARB_SM_MASK      0x38000000  /* write arbitration state bits:
-						      0b000: ARB_IDLE1
-						      0b001: ARB_IDLE2
-						      0b010: ARB_TX_ACK
-						      0b011: ARB_TX_WAT
-						      0b100: ARB_RX_ACK
-						      0b110: ARB_RX_WAT */
-
-/* Cassini only. 64-bit register used to check PCI datapath. when read,
- * value written has both lower and upper 32-bit halves rotated to the right
- * one bit position. e.g., FFFFFFFF FFFFFFFF -> 7FFFFFFF 7FFFFFFF
- */
-#define  REG_MINUS_BIM_DATAPATH_TEST   0x1018  /* Cassini: BIM datapath test
-						  Cassini+: reserved */
-
-/* output enables are provided for each device's chip select and for the rest
- * of the outputs from cassini to its local bus devices. two sw programmable
- * bits are connected to general purpus control/status bits.
- * DEFAULT: 0x7
- */
-#define  REG_BIM_LOCAL_DEV_EN          0x1020  /* BIM local device
-						  output EN. default: 0x7 */
-#define    BIM_LOCAL_DEV_PAD           0x01    /* address bus, RW signal, and
-						  OE signal output enable on the
-						  local bus interface. these
-						  are shared between both local
-						  bus devices. tristate when 0. */
-#define    BIM_LOCAL_DEV_PROM          0x02    /* PROM chip select */
-#define    BIM_LOCAL_DEV_EXT           0x04    /* secondary local bus device chip
-						  select output enable */
-#define    BIM_LOCAL_DEV_SOFT_0        0x08    /* sw programmable ctrl bit 0 */
-#define    BIM_LOCAL_DEV_SOFT_1        0x10    /* sw programmable ctrl bit 1 */
-#define    BIM_LOCAL_DEV_HW_RESET      0x20    /* internal hw reset. Cassini+ only. */
-
-/* access 24 entry BIM read and write buffers. put address in REG_BIM_BUFFER_ADDR
- * and read/write from/to it REG_BIM_BUFFER_DATA_LOW and _DATA_HI.
- * _DATA_HI should be the last access of the sequence.
- * DEFAULT: undefined
- */
-#define  REG_BIM_BUFFER_ADDR           0x1024  /* BIM buffer address. for
-						  purposes. */
-#define    BIM_BUFFER_ADDR_MASK        0x3F    /* index (0 - 23) of buffer  */
-#define    BIM_BUFFER_WR_SELECT        0x40    /* write buffer access = 1
-						  read buffer access = 0 */
-/* DEFAULT: undefined */
-#define  REG_BIM_BUFFER_DATA_LOW       0x1028  /* BIM buffer data low */
-#define  REG_BIM_BUFFER_DATA_HI        0x102C  /* BIM buffer data high */
-
-/* set BIM_RAM_BIST_START to start built-in self test for BIM read buffer.
- * bit auto-clears when done with status read from _SUMMARY and _PASS bits.
- */
-#define  REG_BIM_RAM_BIST              0x102C  /* BIM RAM (read buffer) BIST
-						  control/status */
-#define    BIM_RAM_BIST_RD_START       0x01    /* start BIST for BIM read buffer */
-#define    BIM_RAM_BIST_WR_START       0x02    /* start BIST for BIM write buffer.
-						  Cassini only. reserved in
-						  Cassini+. */
-#define    BIM_RAM_BIST_RD_PASS        0x04    /* summary BIST pass status for read
-						  buffer. */
-#define    BIM_RAM_BIST_WR_PASS        0x08    /* summary BIST pass status for write
-						  buffer. Cassini only. reserved
-						  in Cassini+. */
-#define    BIM_RAM_BIST_RD_LOW_PASS    0x10    /* read low bank passes BIST */
-#define    BIM_RAM_BIST_RD_HI_PASS     0x20    /* read high bank passes BIST */
-#define    BIM_RAM_BIST_WR_LOW_PASS    0x40    /* write low bank passes BIST.
-						  Cassini only. reserved in
-						  Cassini+. */
-#define    BIM_RAM_BIST_WR_HI_PASS     0x80    /* write high bank passes BIST.
-						  Cassini only. reserved in
-						  Cassini+. */
-
-/* ASUN: i'm not sure what this does as it's not in the spec.
- * DEFAULT: 0xFC
- */
-#define  REG_BIM_DIAG_MUX              0x1030  /* BIM diagnostic probe mux
-						  select register */
-
-/* enable probe monitoring mode and select data appearing on the P_A* bus. bit
- * values for _SEL_HI_MASK and _SEL_LOW_MASK:
- * 0x0: internal probe[7:0] (pci arb state, wtc empty w, wtc full w, wtc empty w,
- *                           wtc empty r, post pci)
- * 0x1: internal probe[15:8] (pci wbuf comp, pci wpkt comp, pci rbuf comp,
- *                            pci rpkt comp, txdma wr req, txdma wr ack,
- *			      txdma wr rdy, txdma wr xfr done)
- * 0x2: internal probe[23:16] (txdma rd req, txdma rd ack, txdma rd rdy, rxdma rd,
- *                             rd arb state, rd pci state)
- * 0x3: internal probe[31:24] (rxdma req, rxdma ack, rxdma rdy, wrarb state,
- *                             wrpci state)
- * 0x4: pci io probe[7:0]     0x5: pci io probe[15:8]
- * 0x6: pci io probe[23:16]   0x7: pci io probe[31:24]
- * 0x8: pci io probe[39:32]   0x9: pci io probe[47:40]
- * 0xa: pci io probe[55:48]   0xb: pci io probe[63:56]
- * the following are not available in Cassini:
- * 0xc: rx probe[7:0]         0xd: tx probe[7:0]
- * 0xe: hp probe[7:0] 	      0xf: mac probe[7:0]
- */
-#define  REG_PLUS_PROBE_MUX_SELECT     0x1034 /* Cassini+: PROBE MUX SELECT */
-#define    PROBE_MUX_EN                0x80000000 /* allow probe signals to be
-						     driven on local bus P_A[15:0]
-						     for debugging */
-#define    PROBE_MUX_SUB_MUX_MASK      0x0000FF00 /* select sub module probe signals:
-						     0x03 = mac[1:0]
-						     0x0C = rx[1:0]
-						     0x30 = tx[1:0]
-						     0xC0 = hp[1:0] */
-#define    PROBE_MUX_SEL_HI_MASK       0x000000F0 /* select which module to appear
-						     on P_A[15:8]. see above for
-						     values. */
-#define    PROBE_MUX_SEL_LOW_MASK      0x0000000F /* select which module to appear
-						     on P_A[7:0]. see above for
-						     values. */
-
-/* values mean the same thing as REG_INTR_MASK excep that it's for INTB.
- DEFAULT: 0x1F */
-#define  REG_PLUS_INTR_MASK_1          0x1038 /* Cassini+: interrupt mask
-						 register 2 for INTB */
-#define  REG_PLUS_INTRN_MASK(x)       (REG_PLUS_INTR_MASK_1 + ((x) - 1)*16)
-/* bits correspond to both _MASK and _STATUS registers. _ALT corresponds to
- * all of the alternate (2-4) INTR registers while _1 corresponds to only
- * _MASK_1 and _STATUS_1 registers.
- * DEFAULT: 0x7 for MASK registers, 0x0 for ALIAS_CLEAR registers
- */
-#define    INTR_RX_DONE_ALT              0x01
-#define    INTR_RX_COMP_FULL_ALT         0x02
-#define    INTR_RX_COMP_AF_ALT           0x04
-#define    INTR_RX_BUF_UNAVAIL_1         0x08
-#define    INTR_RX_BUF_AE_1              0x10 /* almost empty */
-#define    INTRN_MASK_RX_EN              0x80
-#define    INTRN_MASK_CLEAR_ALL          (INTR_RX_DONE_ALT | \
-                                          INTR_RX_COMP_FULL_ALT | \
-                                          INTR_RX_COMP_AF_ALT | \
-                                          INTR_RX_BUF_UNAVAIL_1 | \
-                                          INTR_RX_BUF_AE_1)
-#define  REG_PLUS_INTR_STATUS_1        0x103C /* Cassini+: interrupt status
-						 register 2 for INTB. default: 0x1F */
-#define  REG_PLUS_INTRN_STATUS(x)       (REG_PLUS_INTR_STATUS_1 + ((x) - 1)*16)
-#define    INTR_STATUS_ALT_INTX_EN     0x80   /* generate INTX when one of the
-						 flags are set. enables desc ring. */
-
-#define  REG_PLUS_ALIAS_CLEAR_1        0x1040 /* Cassini+: alias clear mask
-						 register 2 for INTB */
-#define  REG_PLUS_ALIASN_CLEAR(x)      (REG_PLUS_ALIAS_CLEAR_1 + ((x) - 1)*16)
-
-#define  REG_PLUS_INTR_STATUS_ALIAS_1  0x1044 /* Cassini+: interrupt status
-						 register alias 2 for INTB */
-#define  REG_PLUS_INTRN_STATUS_ALIAS(x) (REG_PLUS_INTR_STATUS_ALIAS_1 + ((x) - 1)*16)
-
-#define REG_SATURN_PCFG               0x106c /* pin configuration register for
-						integrated macphy */
-
-#define   SATURN_PCFG_TLA             0x00000001 /* 1 = phy actled */
-#define   SATURN_PCFG_FLA             0x00000002 /* 1 = phy link10led */
-#define   SATURN_PCFG_CLA             0x00000004 /* 1 = phy link100led */
-#define   SATURN_PCFG_LLA             0x00000008 /* 1 = phy link1000led */
-#define   SATURN_PCFG_RLA             0x00000010 /* 1 = phy duplexled */
-#define   SATURN_PCFG_PDS             0x00000020 /* phy debug mode.
-						    0 = normal */
-#define   SATURN_PCFG_MTP             0x00000080 /* test point select */
-#define   SATURN_PCFG_GMO             0x00000100 /* GMII observe. 1 =
-						    GMII on SERDES pins for
-						    monitoring. */
-#define   SATURN_PCFG_FSI             0x00000200 /* 1 = freeze serdes/gmii. all
-						    pins configed as outputs.
-						    for power saving when using
-						    internal phy. */
-#define   SATURN_PCFG_LAD             0x00000800 /* 0 = mac core led ctrl
-						    polarity from strapping
-						    value.
-						    1 = mac core led ctrl
-						    polarity active low. */
-
-
-/** transmit dma registers **/
-#define MAX_TX_RINGS_SHIFT            2
-#define MAX_TX_RINGS                  (1 << MAX_TX_RINGS_SHIFT)
-#define MAX_TX_RINGS_MASK             (MAX_TX_RINGS - 1)
-
-/* TX configuration.
- * descr ring sizes size = 32 * (1 << n), n < 9. e.g., 0x8 = 8k. default: 0x8
- * DEFAULT: 0x3F000001
- */
-#define  REG_TX_CFG                    0x2004  /* TX config */
-#define    TX_CFG_DMA_EN               0x00000001  /* enable TX DMA. if cleared, DMA
-						      will stop after xfer of current
-						      buffer has been completed. */
-#define    TX_CFG_FIFO_PIO_SEL         0x00000002  /* TX DMA FIFO can be
-						      accessed w/ FIFO addr
-						      and data registers.
-						      TX DMA should be
-						      disabled. */
-#define    TX_CFG_DESC_RING0_MASK      0x0000003C  /* # desc entries in
-						      ring 1. */
-#define    TX_CFG_DESC_RING0_SHIFT     2
-#define    TX_CFG_DESC_RINGN_MASK(a)   (TX_CFG_DESC_RING0_MASK << (a)*4)
-#define    TX_CFG_DESC_RINGN_SHIFT(a)  (TX_CFG_DESC_RING0_SHIFT + (a)*4)
-#define    TX_CFG_PACED_MODE           0x00100000  /* TX_ALL only set after
-						      TX FIFO becomes empty.
-						      if 0, TX_ALL set
-						      if descr queue empty. */
-#define    TX_CFG_DMA_RDPIPE_DIS       0x01000000  /* always set to 1 */
-#define    TX_CFG_COMPWB_Q1            0x02000000  /* completion writeback happens at
-						      the end of every packet kicked
-						      through Q1. */
-#define    TX_CFG_COMPWB_Q2            0x04000000  /* completion writeback happens at
-						      the end of every packet kicked
-						      through Q2. */
-#define    TX_CFG_COMPWB_Q3            0x08000000  /* completion writeback happens at
-						      the end of every packet kicked
-						      through Q3 */
-#define    TX_CFG_COMPWB_Q4            0x10000000  /* completion writeback happens at
-						      the end of every packet kicked
-						      through Q4 */
-#define    TX_CFG_INTR_COMPWB_DIS      0x20000000  /* disable pre-interrupt completion
-						      writeback */
-#define    TX_CFG_CTX_SEL_MASK         0xC0000000  /* selects tx test port
-						      connection
-						      0b00: tx mac req,
-						            tx mac retry req,
-							    tx ack and tx tag.
-						      0b01: txdma rd req,
-						            txdma rd ack,
-							    txdma rd rdy,
-							    txdma rd type0
-						      0b11: txdma wr req,
-						            txdma wr ack,
-							    txdma wr rdy,
-							    txdma wr xfr done. */
-#define    TX_CFG_CTX_SEL_SHIFT        30
-
-/* 11-bit counters that point to next location in FIFO to be loaded/retrieved.
- * used for diagnostics only.
- */
-#define  REG_TX_FIFO_WRITE_PTR         0x2014  /* TX FIFO write pointer */
-#define  REG_TX_FIFO_SHADOW_WRITE_PTR  0x2018  /* TX FIFO shadow write
-						  pointer. temp hold reg.
-					          diagnostics only. */
-#define  REG_TX_FIFO_READ_PTR          0x201C  /* TX FIFO read pointer */
-#define  REG_TX_FIFO_SHADOW_READ_PTR   0x2020  /* TX FIFO shadow read
-						  pointer */
-
-/* (ro) 11-bit up/down counter w/ # of frames currently in TX FIFO */
-#define  REG_TX_FIFO_PKT_CNT           0x2024  /* TX FIFO packet counter */
-
-/* current state of all state machines in TX */
-#define  REG_TX_SM_1                   0x2028  /* TX state machine reg #1 */
-#define    TX_SM_1_CHAIN_MASK          0x000003FF   /* chaining state machine */
-#define    TX_SM_1_CSUM_MASK           0x00000C00   /* checksum state machine */
-#define    TX_SM_1_FIFO_LOAD_MASK      0x0003F000   /* FIFO load state machine.
-						       = 0x01 when TX disabled. */
-#define    TX_SM_1_FIFO_UNLOAD_MASK    0x003C0000   /* FIFO unload state machine */
-#define    TX_SM_1_CACHE_MASK          0x03C00000   /* desc. prefetch cache controller
-						       state machine */
-#define    TX_SM_1_CBQ_ARB_MASK        0xF8000000   /* CBQ arbiter state machine */
-
-#define  REG_TX_SM_2                   0x202C  /* TX state machine reg #2 */
-#define    TX_SM_2_COMP_WB_MASK        0x07    /* completion writeback sm */
-#define	   TX_SM_2_SUB_LOAD_MASK       0x38    /* sub load state machine */
-#define	   TX_SM_2_KICK_MASK           0xC0    /* kick state machine */
-
-/* 64-bit pointer to the transmit data buffer. only the 50 LSB are incremented
- * while the upper 23 bits are taken from the TX descriptor
- */
-#define  REG_TX_DATA_PTR_LOW           0x2030  /* TX data pointer low */
-#define  REG_TX_DATA_PTR_HI            0x2034  /* TX data pointer high */
-
-/* 13 bit registers written by driver w/ descriptor value that follows
- * last valid xmit descriptor. kick # and complete # values are used by
- * the xmit dma engine to control tx descr fetching. if > 1 valid
- * tx descr is available within the cache line being read, cassini will
- * internally cache up to 4 of them. 0 on reset. _KICK = rw, _COMP = ro.
- */
-#define  REG_TX_KICK0                  0x2038  /* TX kick reg #1 */
-#define  REG_TX_KICKN(x)               (REG_TX_KICK0 + (x)*4)
-#define  REG_TX_COMP0                  0x2048  /* TX completion reg #1 */
-#define  REG_TX_COMPN(x)               (REG_TX_COMP0 + (x)*4)
-
-/* values of TX_COMPLETE_1-4 are written. each completion register
- * is 2bytes in size and contiguous. 8B allocation w/ 8B alignment.
- * NOTE: completion reg values are only written back prior to TX_INTME and
- * TX_ALL interrupts. at all other times, the most up-to-date index values
- * should be obtained from the REG_TX_COMPLETE_# registers.
- * here's the layout:
- * offset from base addr      completion # byte
- *           0                TX_COMPLETE_1_MSB
- *	     1                TX_COMPLETE_1_LSB
- *           2                TX_COMPLETE_2_MSB
- *	     3                TX_COMPLETE_2_LSB
- *           4                TX_COMPLETE_3_MSB
- *	     5                TX_COMPLETE_3_LSB
- *           6                TX_COMPLETE_4_MSB
- *	     7                TX_COMPLETE_4_LSB
- */
-#define  TX_COMPWB_SIZE             8
-#define  REG_TX_COMPWB_DB_LOW       0x2058  /* TX completion write back
-					       base low */
-#define  REG_TX_COMPWB_DB_HI        0x205C  /* TX completion write back
-					       base high */
-#define    TX_COMPWB_MSB_MASK       0x00000000000000FFULL
-#define    TX_COMPWB_MSB_SHIFT      0
-#define    TX_COMPWB_LSB_MASK       0x000000000000FF00ULL
-#define    TX_COMPWB_LSB_SHIFT      8
-#define    TX_COMPWB_NEXT(x)        ((x) >> 16)
-
-/* 53 MSB used as base address. 11 LSB assumed to be 0. TX desc pointer must
- * be 2KB-aligned. */
-#define  REG_TX_DB0_LOW         0x2060  /* TX descriptor base low #1 */
-#define  REG_TX_DB0_HI          0x2064  /* TX descriptor base hi #1 */
-#define  REG_TX_DBN_LOW(x)      (REG_TX_DB0_LOW + (x)*8)
-#define  REG_TX_DBN_HI(x)       (REG_TX_DB0_HI + (x)*8)
-
-/* 16-bit registers hold weights for the weighted round-robin of the
- * four CBQ TX descr rings. weights correspond to # bytes xferred from
- * host to TXFIFO in a round of WRR arbitration. can be set
- * dynamically with new weights set upon completion of the current
- * packet transfer from host memory to TXFIFO. a dummy write to any of
- * these registers causes a queue1 pre-emption with all historical bw
- * deficit data reset to 0 (useful when congestion requires a
- * pre-emption/re-allocation of network bandwidth
- */
-#define  REG_TX_MAXBURST_0             0x2080  /* TX MaxBurst #1 */
-#define  REG_TX_MAXBURST_1             0x2084  /* TX MaxBurst #2 */
-#define  REG_TX_MAXBURST_2             0x2088  /* TX MaxBurst #3 */
-#define  REG_TX_MAXBURST_3             0x208C  /* TX MaxBurst #4 */
-
-/* diagnostics access to any TX FIFO location. every access is 65
- * bits.  _DATA_LOW = 32 LSB, _DATA_HI_T1/T0 = 32 MSB. _TAG = tag bit.
- * writing _DATA_HI_T0 sets tag bit low, writing _DATA_HI_T1 sets tag
- * bit high.  TX_FIFO_PIO_SEL must be set for TX FIFO PIO access. if
- * TX FIFO data integrity is desired, TX DMA should be
- * disabled. _DATA_HI_Tx should be the last access of the sequence.
- */
-#define  REG_TX_FIFO_ADDR              0x2104  /* TX FIFO address */
-#define  REG_TX_FIFO_TAG               0x2108  /* TX FIFO tag */
-#define  REG_TX_FIFO_DATA_LOW          0x210C  /* TX FIFO data low */
-#define  REG_TX_FIFO_DATA_HI_T1        0x2110  /* TX FIFO data high t1 */
-#define  REG_TX_FIFO_DATA_HI_T0        0x2114  /* TX FIFO data high t0 */
-#define  REG_TX_FIFO_SIZE              0x2118  /* (ro) TX FIFO size = 0x090 = 9KB */
-
-/* 9-bit register controls BIST of TX FIFO. bit set indicates that the BIST
- * passed for the specified memory
- */
-#define  REG_TX_RAMBIST                0x211C /* TX RAMBIST control/status */
-#define    TX_RAMBIST_STATE            0x01C0 /* progress state of RAMBIST
-						 controller state machine */
-#define    TX_RAMBIST_RAM33A_PASS      0x0020 /* RAM33A passed */
-#define    TX_RAMBIST_RAM32A_PASS      0x0010 /* RAM32A passed */
-#define    TX_RAMBIST_RAM33B_PASS      0x0008 /* RAM33B passed */
-#define    TX_RAMBIST_RAM32B_PASS      0x0004 /* RAM32B passed */
-#define    TX_RAMBIST_SUMMARY          0x0002 /* all RAM passed */
-#define    TX_RAMBIST_START            0x0001 /* write 1 to start BIST. self
-						 clears on completion. */
-
-/** receive dma registers **/
-#define MAX_RX_DESC_RINGS              2
-#define MAX_RX_COMP_RINGS              4
-
-/* receive DMA channel configuration. default: 0x80910
- * free ring size       = (1 << n)*32  -> [32 - 8k]
- * completion ring size = (1 << n)*128 -> [128 - 32k], n < 9
- * DEFAULT: 0x80910
- */
-#define  REG_RX_CFG                     0x4000  /* RX config */
-#define    RX_CFG_DMA_EN                0x00000001 /* enable RX DMA. 0 stops
-							 channel as soon as current
-							 frame xfer has completed.
-							 driver should disable MAC
-							 for 200ms before disabling
-							 RX */
-#define    RX_CFG_DESC_RING_MASK        0x0000001E /* # desc entries in RX
-							 free desc ring.
-							 def: 0x8 = 8k */
-#define    RX_CFG_DESC_RING_SHIFT       1
-#define    RX_CFG_COMP_RING_MASK        0x000001E0 /* # desc entries in RX complete
-							 ring. def: 0x8 = 32k */
-#define    RX_CFG_COMP_RING_SHIFT       5
-#define    RX_CFG_BATCH_DIS             0x00000200 /* disable receive desc
-						      batching. def: 0x0 =
-						      enabled */
-#define    RX_CFG_SWIVEL_MASK           0x00001C00 /* byte offset of the 1st
-						      data byte of the packet
-						      w/in 8 byte boundares.
-						      this swivels the data
-						      DMA'ed to header
-						      buffers, jumbo buffers
-						      when header split is not
-						      requested and MTU sized
-						      buffers. def: 0x2 */
-#define    RX_CFG_SWIVEL_SHIFT          10
-
-/* cassini+ only */
-#define    RX_CFG_DESC_RING1_MASK       0x000F0000 /* # of desc entries in
-							 RX free desc ring 2.
-							 def: 0x8 = 8k */
-#define    RX_CFG_DESC_RING1_SHIFT      16
-
-
-/* the page size register allows cassini chips to do the following with
- * received data:
- * [--------------------------------------------------------------] page
- * [off][buf1][pad][off][buf2][pad][off][buf3][pad][off][buf4][pad]
- * |--------------| = PAGE_SIZE_BUFFER_STRIDE
- * page = PAGE_SIZE
- * offset = PAGE_SIZE_MTU_OFF
- * for the above example, MTU_BUFFER_COUNT = 4.
- * NOTE: as is apparent, you need to ensure that the following holds:
- * MTU_BUFFER_COUNT <= PAGE_SIZE/PAGE_SIZE_BUFFER_STRIDE
- * DEFAULT: 0x48002002 (8k pages)
- */
-#define  REG_RX_PAGE_SIZE               0x4004  /* RX page size */
-#define    RX_PAGE_SIZE_MASK            0x00000003 /* size of pages pointed to
-						      by receive descriptors.
-						      if jumbo buffers are
-						      supported the page size
-						      should not be < 8k.
-						      0b00 = 2k, 0b01 = 4k
-						      0b10 = 8k, 0b11 = 16k
-						      DEFAULT: 8k */
-#define    RX_PAGE_SIZE_SHIFT           0
-#define    RX_PAGE_SIZE_MTU_COUNT_MASK  0x00007800 /* # of MTU buffers the hw
-						      packs into a page.
-						      DEFAULT: 4 */
-#define    RX_PAGE_SIZE_MTU_COUNT_SHIFT 11
-#define    RX_PAGE_SIZE_MTU_STRIDE_MASK 0x18000000 /* # of bytes that separate
-							 each MTU buffer +
-							 offset from each
-							 other.
-							 0b00 = 1k, 0b01 = 2k
-							 0b10 = 4k, 0b11 = 8k
-							 DEFAULT: 0x1 */
-#define    RX_PAGE_SIZE_MTU_STRIDE_SHIFT 27
-#define    RX_PAGE_SIZE_MTU_OFF_MASK    0xC0000000 /* offset in each page that
-						      hw writes the MTU buffer
-						      into.
-						      0b00 = 0,
-						      0b01 = 64 bytes
-						      0b10 = 96, 0b11 = 128
-						      DEFAULT: 0x1 */
-#define    RX_PAGE_SIZE_MTU_OFF_SHIFT   30
-
-/* 11-bit counter points to next location in RX FIFO to be loaded/read.
- * shadow write pointers enable retries in case of early receive aborts.
- * DEFAULT: 0x0. generated on 64-bit boundaries.
- */
-#define  REG_RX_FIFO_WRITE_PTR             0x4008  /* RX FIFO write pointer */
-#define  REG_RX_FIFO_READ_PTR              0x400C  /* RX FIFO read pointer */
-#define  REG_RX_IPP_FIFO_SHADOW_WRITE_PTR  0x4010  /* RX IPP FIFO shadow write
-						      pointer */
-#define  REG_RX_IPP_FIFO_SHADOW_READ_PTR   0x4014  /* RX IPP FIFO shadow read
-						      pointer */
-#define  REG_RX_IPP_FIFO_READ_PTR          0x400C  /* RX IPP FIFO read
-						      pointer. (8-bit counter) */
-
-/* current state of RX DMA state engines + other info
- * DEFAULT: 0x0
- */
-#define  REG_RX_DEBUG                      0x401C  /* RX debug */
-#define    RX_DEBUG_LOAD_STATE_MASK        0x0000000F /* load state machine w/ MAC:
-							 0x0 = idle,   0x1 = load_bop
-							 0x2 = load 1, 0x3 = load 2
-							 0x4 = load 3, 0x5 = load 4
-							 0x6 = last detect
-							 0x7 = wait req
-							 0x8 = wait req statuss 1st
-							 0x9 = load st
-							 0xa = bubble mac
-							 0xb = error */
-#define    RX_DEBUG_LM_STATE_MASK          0x00000070 /* load state machine w/ HP and
-							 RX FIFO:
-							 0x0 = idle,   0x1 = hp xfr
-							 0x2 = wait hp ready
-							 0x3 = wait flow code
-							 0x4 = fifo xfer
-							 0x5 = make status
-							 0x6 = csum ready
-							 0x7 = error */
-#define    RX_DEBUG_FC_STATE_MASK          0x000000180 /* flow control state machine
-							 w/ MAC:
-							 0x0 = idle
-							 0x1 = wait xoff ack
-							 0x2 = wait xon
-							 0x3 = wait xon ack */
-#define    RX_DEBUG_DATA_STATE_MASK        0x000001E00 /* unload data state machine
-							 states:
-							 0x0 = idle data
-							 0x1 = header begin
-							 0x2 = xfer header
-							 0x3 = xfer header ld
-							 0x4 = mtu begin
-							 0x5 = xfer mtu
-							 0x6 = xfer mtu ld
-							 0x7 = jumbo begin
-							 0x8 = xfer jumbo
-							 0x9 = xfer jumbo ld
-							 0xa = reas begin
-							 0xb = xfer reas
-							 0xc = flush tag
-							 0xd = xfer reas ld
-							 0xe = error
-							 0xf = bubble idle */
-#define    RX_DEBUG_DESC_STATE_MASK        0x0001E000 /* unload desc state machine
-							 states:
-							 0x0 = idle desc
-							 0x1 = wait ack
-							 0x9 = wait ack 2
-							 0x2 = fetch desc 1
-							 0xa = fetch desc 2
-							 0x3 = load ptrs
-							 0x4 = wait dma
-							 0x5 = wait ack batch
-							 0x6 = post batch
-							 0x7 = xfr done */
-#define    RX_DEBUG_INTR_READ_PTR_MASK     0x30000000 /* interrupt read ptr of the
-							 interrupt queue */
-#define    RX_DEBUG_INTR_WRITE_PTR_MASK    0xC0000000 /* interrupt write pointer
-							 of the interrupt queue */
-
-/* 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
- * into FIFO vacancy using RX_FIFO_SIZE. setting ON will trigger XON frames
- * when FIFO reaches 0. OFF threshold should not be > size of RX FIFO. max
- * value is is 0x6F.
- * DEFAULT: 0x00078
- */
-#define  REG_RX_PAUSE_THRESH               0x4020  /* RX pause thresholds */
-#define    RX_PAUSE_THRESH_QUANTUM         64
-#define    RX_PAUSE_THRESH_OFF_MASK        0x000001FF /* XOFF PAUSE emitted when
-							 RX FIFO occupancy >
-							 value*64B */
-#define    RX_PAUSE_THRESH_OFF_SHIFT       0
-#define    RX_PAUSE_THRESH_ON_MASK         0x001FF000 /* XON PAUSE emitted after
-							 emitting XOFF PAUSE when RX
-							 FIFO occupancy falls below
-							 this value*64B. must be
-							 < XOFF threshold. if =
-							 RX_FIFO_SIZE< XON frames are
-							 never emitted. */
-#define    RX_PAUSE_THRESH_ON_SHIFT        12
-
-/* 13-bit register used to control RX desc fetching and intr generation. if 4+
- * valid RX descriptors are available, Cassini will read 4 at a time.
- * writing N means that all desc up to *but* excluding N are available. N must
- * be a multiple of 4 (N % 4 = 0). first desc should be cache-line aligned.
- * DEFAULT: 0 on reset
- */
-#define  REG_RX_KICK                    0x4024  /* RX kick reg */
-
-/* 8KB aligned 64-bit pointer to the base of the RX free/completion rings.
- * lower 13 bits of the low register are hard-wired to 0.
- */
-#define  REG_RX_DB_LOW                     0x4028  /* RX descriptor ring
-							 base low */
-#define  REG_RX_DB_HI                      0x402C  /* RX descriptor ring
-							 base hi */
-#define  REG_RX_CB_LOW                     0x4030  /* RX completion ring
-							 base low */
-#define  REG_RX_CB_HI                      0x4034  /* RX completion ring
-							 base hi */
-/* 13-bit register indicate desc used by cassini for receive frames. used
- * for diagnostic purposes.
- * DEFAULT: 0 on reset
- */
-#define  REG_RX_COMP                       0x4038  /* (ro) RX completion */
-
-/* HEAD and TAIL are used to control RX desc posting and interrupt
- * generation.  hw moves the head register to pass ownership to sw. sw
- * moves the tail register to pass ownership back to hw. to give all
- * entries to hw, set TAIL = HEAD.  if HEAD and TAIL indicate that no
- * more entries are available, DMA will pause and an interrupt will be
- * generated to indicate no more entries are available.  sw can use
- * this interrupt to reduce the # of times it must update the
- * completion tail register.
- * DEFAULT: 0 on reset
- */
-#define  REG_RX_COMP_HEAD                  0x403C  /* RX completion head */
-#define  REG_RX_COMP_TAIL                  0x4040  /* RX completion tail */
-
-/* values used for receive interrupt blanking. loaded each time the ISR is read
- * DEFAULT: 0x00000000
- */
-#define  REG_RX_BLANK                      0x4044  /* RX blanking register
-							 for ISR read */
-#define    RX_BLANK_INTR_PKT_MASK          0x000001FF /* RX_DONE intr asserted if
-							 this many sets of completion
-							 writebacks (up to 2 packets)
-							 occur since the last time
-							 the ISR was read. 0 = no
-							 packet blanking */
-#define    RX_BLANK_INTR_PKT_SHIFT         0
-#define    RX_BLANK_INTR_TIME_MASK         0x3FFFF000 /* RX_DONE interrupt asserted
-							 if that many clocks were
-							 counted since last time the
-							 ISR was read.
-							 each count is 512 core
-							 clocks (125MHz). 0 = no
-							 time blanking */
-#define    RX_BLANK_INTR_TIME_SHIFT        12
-
-/* values used for interrupt generation based on threshold values of how
- * many free desc and completion entries are available for hw use.
- * DEFAULT: 0x00000000
- */
-#define  REG_RX_AE_THRESH                  0x4048  /* RX almost empty
-							 thresholds */
-#define    RX_AE_THRESH_FREE_MASK          0x00001FFF /* RX_BUF_AE will be
-							 generated if # desc
-							 avail for hw use <=
-							 # */
-#define    RX_AE_THRESH_FREE_SHIFT         0
-#define    RX_AE_THRESH_COMP_MASK          0x0FFFE000 /* RX_COMP_AE will be
-							 generated if # of
-							 completion entries
-							 avail for hw use <=
-							 # */
-#define    RX_AE_THRESH_COMP_SHIFT         13
-
-/* probabilities for random early drop (RED) thresholds on a FIFO threshold
- * basis. probability should increase when the FIFO level increases. control
- * packets are never dropped and not counted in stats. probability programmed
- * on a 12.5% granularity. e.g., 0x1 = 1/8 packets dropped.
- * DEFAULT: 0x00000000
- */
-#define  REG_RX_RED                      0x404C  /* RX random early detect enable */
-#define    RX_RED_4K_6K_FIFO_MASK        0x000000FF /*  4KB < FIFO thresh < 6KB */
-#define    RX_RED_6K_8K_FIFO_MASK        0x0000FF00 /*  6KB < FIFO thresh < 8KB */
-#define    RX_RED_8K_10K_FIFO_MASK       0x00FF0000 /*  8KB < FIFO thresh < 10KB */
-#define    RX_RED_10K_12K_FIFO_MASK      0xFF000000 /* 10KB < FIFO thresh < 12KB */
-
-/* FIFO fullness levels for RX FIFO, RX control FIFO, and RX IPP FIFO.
- * RX control FIFO = # of packets in RX FIFO.
- * DEFAULT: 0x0
- */
-#define  REG_RX_FIFO_FULLNESS              0x4050  /* (ro) RX FIFO fullness */
-#define    RX_FIFO_FULLNESS_RX_FIFO_MASK   0x3FF80000 /* level w/ 8B granularity */
-#define    RX_FIFO_FULLNESS_IPP_FIFO_MASK  0x0007FF00 /* level w/ 8B granularity */
-#define    RX_FIFO_FULLNESS_RX_PKT_MASK    0x000000FF /* # packets in RX FIFO */
-#define  REG_RX_IPP_PACKET_COUNT           0x4054  /* RX IPP packet counter */
-#define  REG_RX_WORK_DMA_PTR_LOW           0x4058  /* RX working DMA ptr low */
-#define  REG_RX_WORK_DMA_PTR_HI            0x405C  /* RX working DMA ptr
-						      high */
-
-/* BIST testing ro RX FIFO, RX control FIFO, and RX IPP FIFO. only RX BIST
- * START/COMPLETE is writeable. START will clear when the BIST has completed
- * checking all 17 RAMS.
- * DEFAULT: 0bxxxx xxxxx xxxx xxxx xxxx x000 0000 0000 00x0
- */
-#define  REG_RX_BIST                       0x4060  /* (ro) RX BIST */
-#define    RX_BIST_32A_PASS                0x80000000 /* RX FIFO 32A passed */
-#define    RX_BIST_33A_PASS                0x40000000 /* RX FIFO 33A passed */
-#define    RX_BIST_32B_PASS                0x20000000 /* RX FIFO 32B passed */
-#define    RX_BIST_33B_PASS                0x10000000 /* RX FIFO 33B passed */
-#define    RX_BIST_32C_PASS                0x08000000 /* RX FIFO 32C passed */
-#define    RX_BIST_33C_PASS                0x04000000 /* RX FIFO 33C passed */
-#define    RX_BIST_IPP_32A_PASS            0x02000000 /* RX IPP FIFO 33B passed */
-#define    RX_BIST_IPP_33A_PASS            0x01000000 /* RX IPP FIFO 33A passed */
-#define    RX_BIST_IPP_32B_PASS            0x00800000 /* RX IPP FIFO 32B passed */
-#define    RX_BIST_IPP_33B_PASS            0x00400000 /* RX IPP FIFO 33B passed */
-#define    RX_BIST_IPP_32C_PASS            0x00200000 /* RX IPP FIFO 32C passed */
-#define    RX_BIST_IPP_33C_PASS            0x00100000 /* RX IPP FIFO 33C passed */
-#define    RX_BIST_CTRL_32_PASS            0x00800000 /* RX CTRL FIFO 32 passed */
-#define    RX_BIST_CTRL_33_PASS            0x00400000 /* RX CTRL FIFO 33 passed */
-#define    RX_BIST_REAS_26A_PASS           0x00200000 /* RX Reas 26A passed */
-#define    RX_BIST_REAS_26B_PASS           0x00100000 /* RX Reas 26B passed */
-#define    RX_BIST_REAS_27_PASS            0x00080000 /* RX Reas 27 passed */
-#define    RX_BIST_STATE_MASK              0x00078000 /* BIST state machine */
-#define    RX_BIST_SUMMARY                 0x00000002 /* when BIST complete,
-							 summary pass bit
-							 contains AND of BIST
-							 results of all 16
-							 RAMS */
-#define    RX_BIST_START                   0x00000001 /* write 1 to start
-							 BIST. self clears
-							 on completion. */
-
-/* next location in RX CTRL FIFO that will be loaded w/ data from RX IPP/read
- * from to retrieve packet control info.
- * DEFAULT: 0
- */
-#define  REG_RX_CTRL_FIFO_WRITE_PTR        0x4064  /* (ro) RX control FIFO
-						      write ptr */
-#define  REG_RX_CTRL_FIFO_READ_PTR         0x4068  /* (ro) RX control FIFO read
-						      ptr */
-
-/* receive interrupt blanking. loaded each time interrupt alias register is
- * read.
- * DEFAULT: 0x0
- */
-#define  REG_RX_BLANK_ALIAS_READ           0x406C  /* RX blanking register for
-						      alias read */
-#define    RX_BAR_INTR_PACKET_MASK         0x000001FF /* assert RX_DONE if #
-							 completion writebacks
-							 > # since last ISR
-							 read. 0 = no
-							 blanking. up to 2
-							 packets per
-							 completion wb. */
-#define    RX_BAR_INTR_TIME_MASK           0x3FFFF000 /* assert RX_DONE if #
-							 clocks > # since last
-							 ISR read. each count
-							 is 512 core clocks
-							 (125MHz). 0 = no
-							 blanking. */
-
-/* diagnostic access to RX FIFO. 32 LSB accessed via DATA_LOW. 32 MSB accessed
- * via DATA_HI_T0 or DATA_HI_T1. TAG reads the tag bit. writing HI_T0
- * will unset the tag bit while writing HI_T1 will set the tag bit. to reset
- * to normal operation after diagnostics, write to address location 0x0.
- * RX_DMA_EN bit must be set to 0x0 for RX FIFO PIO access. DATA_HI should
- * be the last write access of a write sequence.
- * DEFAULT: undefined
- */
-#define  REG_RX_FIFO_ADDR                  0x4080  /* RX FIFO address */
-#define  REG_RX_FIFO_TAG                   0x4084  /* RX FIFO tag */
-#define  REG_RX_FIFO_DATA_LOW              0x4088  /* RX FIFO data low */
-#define  REG_RX_FIFO_DATA_HI_T0            0x408C  /* RX FIFO data high T0 */
-#define  REG_RX_FIFO_DATA_HI_T1            0x4090  /* RX FIFO data high T1 */
-
-/* diagnostic assess to RX CTRL FIFO. 8-bit FIFO_ADDR holds address of
- * 81 bit control entry and 6 bit flow id. LOW and MID are both 32-bit
- * accesses. HI is 7-bits with 6-bit flow id and 1 bit control
- * word. RX_DMA_EN must be 0 for RX CTRL FIFO PIO access. DATA_HI
- * should be last write access of the write sequence.
- * DEFAULT: undefined
- */
-#define  REG_RX_CTRL_FIFO_ADDR             0x4094  /* RX Control FIFO and
-						      Batching FIFO addr */
-#define  REG_RX_CTRL_FIFO_DATA_LOW         0x4098  /* RX Control FIFO data
-						      low */
-#define  REG_RX_CTRL_FIFO_DATA_MID         0x409C  /* RX Control FIFO data
-						      mid */
-#define  REG_RX_CTRL_FIFO_DATA_HI          0x4100  /* RX Control FIFO data
-						      hi and flow id */
-#define    RX_CTRL_FIFO_DATA_HI_CTRL       0x0001  /* upper bit of ctrl word */
-#define    RX_CTRL_FIFO_DATA_HI_FLOW_MASK  0x007E  /* flow id */
-
-/* diagnostic access to RX IPP FIFO. same semantics as RX_FIFO.
- * DEFAULT: undefined
- */
-#define  REG_RX_IPP_FIFO_ADDR              0x4104  /* RX IPP FIFO address */
-#define  REG_RX_IPP_FIFO_TAG               0x4108  /* RX IPP FIFO tag */
-#define  REG_RX_IPP_FIFO_DATA_LOW          0x410C  /* RX IPP FIFO data low */
-#define  REG_RX_IPP_FIFO_DATA_HI_T0        0x4110  /* RX IPP FIFO data high
-						      T0 */
-#define  REG_RX_IPP_FIFO_DATA_HI_T1        0x4114  /* RX IPP FIFO data high
-						      T1 */
-
-/* 64-bit pointer to receive data buffer in host memory used for headers and
- * small packets. MSB in high register. loaded by DMA state machine and
- * increments as DMA writes receive data. only 50 LSB are incremented. top
- * 13 bits taken from RX descriptor.
- * DEFAULT: undefined
- */
-#define  REG_RX_HEADER_PAGE_PTR_LOW        0x4118  /* (ro) RX header page ptr
-						      low */
-#define  REG_RX_HEADER_PAGE_PTR_HI         0x411C  /* (ro) RX header page ptr
-						      high */
-#define  REG_RX_MTU_PAGE_PTR_LOW           0x4120  /* (ro) RX MTU page pointer
-						      low */
-#define  REG_RX_MTU_PAGE_PTR_HI            0x4124  /* (ro) RX MTU page pointer
-						      high */
-
-/* PIO diagnostic access to RX reassembly DMA Table RAM. 6-bit register holds
- * one of 64 79-bit locations in the RX Reassembly DMA table and the addr of
- * one of the 64 byte locations in the Batching table. LOW holds 32 LSB.
- * MID holds the next 32 LSB. HIGH holds the 15 MSB. RX_DMA_EN must be set
- * to 0 for PIO access. DATA_HIGH should be last write of write sequence.
- * layout:
- * reassmbl ptr [78:15] | reassmbl index [14:1] | reassmbl entry valid [0]
- * DEFAULT: undefined
- */
-#define  REG_RX_TABLE_ADDR             0x4128  /* RX reassembly DMA table
-						  address */
-#define    RX_TABLE_ADDR_MASK          0x0000003F /* address mask */
-
-#define  REG_RX_TABLE_DATA_LOW         0x412C  /* RX reassembly DMA table
-						  data low */
-#define  REG_RX_TABLE_DATA_MID         0x4130  /* RX reassembly DMA table
-						  data mid */
-#define  REG_RX_TABLE_DATA_HI          0x4134  /* RX reassembly DMA table
-						  data high */
-
-/* cassini+ only */
-/* 8KB aligned 64-bit pointer to base of RX rings. lower 13 bits hardwired to
- * 0. same semantics as primary desc/complete rings.
- */
-#define  REG_PLUS_RX_DB1_LOW            0x4200  /* RX descriptor ring
-						   2 base low */
-#define  REG_PLUS_RX_DB1_HI             0x4204  /* RX descriptor ring
-						   2 base high */
-#define  REG_PLUS_RX_CB1_LOW            0x4208  /* RX completion ring
-						   2 base low. 4 total */
-#define  REG_PLUS_RX_CB1_HI             0x420C  /* RX completion ring
-						   2 base high. 4 total */
-#define  REG_PLUS_RX_CBN_LOW(x)        (REG_PLUS_RX_CB1_LOW + 8*((x) - 1))
-#define  REG_PLUS_RX_CBN_HI(x)         (REG_PLUS_RX_CB1_HI + 8*((x) - 1))
-#define  REG_PLUS_RX_KICK1             0x4220  /* RX Kick 2 register */
-#define  REG_PLUS_RX_COMP1             0x4224  /* (ro) RX completion 2
-						  reg */
-#define  REG_PLUS_RX_COMP1_HEAD        0x4228  /* (ro) RX completion 2
-						  head reg. 4 total. */
-#define  REG_PLUS_RX_COMP1_TAIL        0x422C  /* RX completion 2
-						  tail reg. 4 total. */
-#define  REG_PLUS_RX_COMPN_HEAD(x)    (REG_PLUS_RX_COMP1_HEAD + 8*((x) - 1))
-#define  REG_PLUS_RX_COMPN_TAIL(x)    (REG_PLUS_RX_COMP1_TAIL + 8*((x) - 1))
-#define  REG_PLUS_RX_AE1_THRESH        0x4240  /* RX almost empty 2
-						  thresholds */
-#define    RX_AE1_THRESH_FREE_MASK     RX_AE_THRESH_FREE_MASK
-#define    RX_AE1_THRESH_FREE_SHIFT    RX_AE_THRESH_FREE_SHIFT
-
-/** header parser registers **/
-
-/* RX parser configuration register.
- * DEFAULT: 0x1651004
- */
-#define  REG_HP_CFG                       0x4140  /* header parser
-						     configuration reg */
-#define    HP_CFG_PARSE_EN                0x00000001 /* enab header parsing */
-#define    HP_CFG_NUM_CPU_MASK            0x000000FC /* # processors
-						      0 = 64. 0x3f = 63 */
-#define    HP_CFG_NUM_CPU_SHIFT           2
-#define    HP_CFG_SYN_INC_MASK            0x00000100 /* SYN bit won't increment
-							TCP seq # by one when
-							stored in FDBM */
-#define    HP_CFG_TCP_THRESH_MASK         0x000FFE00 /* # bytes of TCP data
-							needed to be considered
-							for reassembly */
-#define    HP_CFG_TCP_THRESH_SHIFT        9
-
-/* access to RX Instruction RAM. 5-bit register/counter holds addr
- * of 39 bit entry to be read/written. 32 LSB in _DATA_LOW. 7 MSB in _DATA_HI.
- * RX_DMA_EN must be 0 for RX instr PIO access. DATA_HI should be last access
- * of sequence.
- * DEFAULT: undefined
- */
-#define  REG_HP_INSTR_RAM_ADDR             0x4144  /* HP instruction RAM
-						      address */
-#define    HP_INSTR_RAM_ADDR_MASK          0x01F   /* 5-bit mask */
-#define  REG_HP_INSTR_RAM_DATA_LOW         0x4148  /* HP instruction RAM
-						      data low */
-#define    HP_INSTR_RAM_LOW_OUTMASK_MASK   0x0000FFFF
-#define    HP_INSTR_RAM_LOW_OUTMASK_SHIFT  0
-#define    HP_INSTR_RAM_LOW_OUTSHIFT_MASK  0x000F0000
-#define    HP_INSTR_RAM_LOW_OUTSHIFT_SHIFT 16
-#define    HP_INSTR_RAM_LOW_OUTEN_MASK     0x00300000
-#define    HP_INSTR_RAM_LOW_OUTEN_SHIFT    20
-#define    HP_INSTR_RAM_LOW_OUTARG_MASK    0xFFC00000
-#define    HP_INSTR_RAM_LOW_OUTARG_SHIFT   22
-#define  REG_HP_INSTR_RAM_DATA_MID         0x414C  /* HP instruction RAM
-						      data mid */
-#define    HP_INSTR_RAM_MID_OUTARG_MASK    0x00000003
-#define    HP_INSTR_RAM_MID_OUTARG_SHIFT   0
-#define    HP_INSTR_RAM_MID_OUTOP_MASK     0x0000003C
-#define    HP_INSTR_RAM_MID_OUTOP_SHIFT    2
-#define    HP_INSTR_RAM_MID_FNEXT_MASK     0x000007C0
-#define    HP_INSTR_RAM_MID_FNEXT_SHIFT    6
-#define    HP_INSTR_RAM_MID_FOFF_MASK      0x0003F800
-#define    HP_INSTR_RAM_MID_FOFF_SHIFT     11
-#define    HP_INSTR_RAM_MID_SNEXT_MASK     0x007C0000
-#define    HP_INSTR_RAM_MID_SNEXT_SHIFT    18
-#define    HP_INSTR_RAM_MID_SOFF_MASK      0x3F800000
-#define    HP_INSTR_RAM_MID_SOFF_SHIFT     23
-#define    HP_INSTR_RAM_MID_OP_MASK        0xC0000000
-#define    HP_INSTR_RAM_MID_OP_SHIFT       30
-#define  REG_HP_INSTR_RAM_DATA_HI          0x4150  /* HP instruction RAM
-						      data high */
-#define    HP_INSTR_RAM_HI_VAL_MASK        0x0000FFFF
-#define    HP_INSTR_RAM_HI_VAL_SHIFT       0
-#define    HP_INSTR_RAM_HI_MASK_MASK       0xFFFF0000
-#define    HP_INSTR_RAM_HI_MASK_SHIFT      16
-
-/* PIO access into RX Header parser data RAM and flow database.
- * 11-bit register. Data fills the LSB portion of bus if less than 32 bits.
- * DATA_RAM: write RAM_FDB_DATA with index to access DATA_RAM.
- * RAM bytes = 4*(x - 1) + [3:0]. e.g., 0 -> [3:0], 31 -> [123:120]
- * FLOWDB: write DATA_RAM_FDB register and then read/write FDB1-12 to access
- * flow database.
- * RX_DMA_EN must be 0 for RX parser RAM PIO access. RX Parser RAM data reg
- * should be the last write access of the write sequence.
- * DEFAULT: undefined
- */
-#define  REG_HP_DATA_RAM_FDB_ADDR          0x4154  /* HP data and FDB
-						      RAM address */
-#define    HP_DATA_RAM_FDB_DATA_MASK       0x001F  /* select 1 of 86 byte
-						      locations in header
-						      parser data ram to
-						      read/write */
-#define    HP_DATA_RAM_FDB_FDB_MASK        0x3F00  /* 1 of 64 353-bit locations
-						      in the flow database */
-#define  REG_HP_DATA_RAM_DATA              0x4158  /* HP data RAM data */
-
-/* HP flow database registers: 1 - 12, 0x415C - 0x4188, 4 8-bit bytes
- * FLOW_DB(1) = IP_SA[127:96], FLOW_DB(2) = IP_SA[95:64]
- * FLOW_DB(3) = IP_SA[63:32],  FLOW_DB(4) = IP_SA[31:0]
- * FLOW_DB(5) = IP_DA[127:96], FLOW_DB(6) = IP_DA[95:64]
- * FLOW_DB(7) = IP_DA[63:32],  FLOW_DB(8) = IP_DA[31:0]
- * FLOW_DB(9) = {TCP_SP[15:0],TCP_DP[15:0]}
- * FLOW_DB(10) = bit 0 has value for flow valid
- * FLOW_DB(11) = TCP_SEQ[63:32], FLOW_DB(12) = TCP_SEQ[31:0]
- */
-#define  REG_HP_FLOW_DB0                   0x415C  /* HP flow database 1 reg */
-#define  REG_HP_FLOW_DBN(x)                (REG_HP_FLOW_DB0 + (x)*4)
-
-/* diagnostics for RX Header Parser block.
- * ASUN: the header parser state machine register is used for diagnostics
- * purposes. however, the spec doesn't have any details on it.
- */
-#define  REG_HP_STATE_MACHINE              0x418C  /* (ro) HP state machine */
-#define  REG_HP_STATUS0                    0x4190  /* (ro) HP status 1 */
-#define    HP_STATUS0_SAP_MASK             0xFFFF0000 /* SAP */
-#define    HP_STATUS0_L3_OFF_MASK          0x0000FE00 /* L3 offset */
-#define    HP_STATUS0_LB_CPUNUM_MASK       0x000001F8 /* load balancing CPU
-							 number */
-#define    HP_STATUS0_HRP_OPCODE_MASK      0x00000007 /* HRP opcode */
-
-#define  REG_HP_STATUS1                    0x4194  /* (ro) HP status 2 */
-#define    HP_STATUS1_ACCUR2_MASK          0xE0000000 /* accu R2[6:4] */
-#define    HP_STATUS1_FLOWID_MASK          0x1F800000 /* flow id */
-#define    HP_STATUS1_TCP_OFF_MASK         0x007F0000 /* tcp payload offset */
-#define    HP_STATUS1_TCP_SIZE_MASK        0x0000FFFF /* tcp payload size */
-
-#define  REG_HP_STATUS2                    0x4198  /* (ro) HP status 3 */
-#define    HP_STATUS2_ACCUR2_MASK          0xF0000000 /* accu R2[3:0] */
-#define    HP_STATUS2_CSUM_OFF_MASK        0x07F00000 /* checksum start
-							 start offset */
-#define    HP_STATUS2_ACCUR1_MASK          0x000FE000 /* accu R1 */
-#define    HP_STATUS2_FORCE_DROP           0x00001000 /* force drop */
-#define    HP_STATUS2_BWO_REASSM           0x00000800 /* batching w/o
-							 reassembly */
-#define    HP_STATUS2_JH_SPLIT_EN          0x00000400 /* jumbo header split
-							 enable */
-#define    HP_STATUS2_FORCE_TCP_NOCHECK    0x00000200 /* force tcp no payload
-							 check */
-#define    HP_STATUS2_DATA_MASK_ZERO       0x00000100 /* mask of data length
-							 equal to zero */
-#define    HP_STATUS2_FORCE_TCP_CHECK      0x00000080 /* force tcp payload
-							 chk */
-#define    HP_STATUS2_MASK_TCP_THRESH      0x00000040 /* mask of payload
-							 threshold */
-#define    HP_STATUS2_NO_ASSIST            0x00000020 /* no assist */
-#define    HP_STATUS2_CTRL_PACKET_FLAG     0x00000010 /* control packet flag */
-#define    HP_STATUS2_TCP_FLAG_CHECK       0x00000008 /* tcp flag check */
-#define    HP_STATUS2_SYN_FLAG             0x00000004 /* syn flag */
-#define    HP_STATUS2_TCP_CHECK            0x00000002 /* tcp payload chk */
-#define    HP_STATUS2_TCP_NOCHECK          0x00000001 /* tcp no payload chk */
-
-/* BIST for header parser(HP) and flow database memories (FDBM). set _START
- * to start BIST. controller clears _START on completion. _START can also
- * be cleared to force termination of BIST. a bit set indicates that that
- * memory passed its BIST.
- */
-#define  REG_HP_RAM_BIST                   0x419C  /* HP RAM BIST reg */
-#define    HP_RAM_BIST_HP_DATA_PASS        0x80000000 /* HP data ram */
-#define    HP_RAM_BIST_HP_INSTR0_PASS      0x40000000 /* HP instr ram 0 */
-#define    HP_RAM_BIST_HP_INSTR1_PASS      0x20000000 /* HP instr ram 1 */
-#define    HP_RAM_BIST_HP_INSTR2_PASS      0x10000000 /* HP instr ram 2 */
-#define    HP_RAM_BIST_FDBM_AGE0_PASS      0x08000000 /* FDBM aging RAM0 */
-#define    HP_RAM_BIST_FDBM_AGE1_PASS      0x04000000 /* FDBM aging RAM1 */
-#define    HP_RAM_BIST_FDBM_FLOWID00_PASS  0x02000000 /* FDBM flowid RAM0
-							 bank 0 */
-#define    HP_RAM_BIST_FDBM_FLOWID10_PASS  0x01000000 /* FDBM flowid RAM1
-							 bank 0 */
-#define    HP_RAM_BIST_FDBM_FLOWID20_PASS  0x00800000 /* FDBM flowid RAM2
-							 bank 0 */
-#define    HP_RAM_BIST_FDBM_FLOWID30_PASS  0x00400000 /* FDBM flowid RAM3
-							 bank 0 */
-#define    HP_RAM_BIST_FDBM_FLOWID01_PASS  0x00200000 /* FDBM flowid RAM0
-							 bank 1 */
-#define    HP_RAM_BIST_FDBM_FLOWID11_PASS  0x00100000 /* FDBM flowid RAM1
-							 bank 2 */
-#define    HP_RAM_BIST_FDBM_FLOWID21_PASS  0x00080000 /* FDBM flowid RAM2
-							 bank 1 */
-#define    HP_RAM_BIST_FDBM_FLOWID31_PASS  0x00040000 /* FDBM flowid RAM3
-							 bank 1 */
-#define    HP_RAM_BIST_FDBM_TCPSEQ_PASS    0x00020000 /* FDBM tcp sequence
-							 RAM */
-#define    HP_RAM_BIST_SUMMARY             0x00000002 /* all BIST tests */
-#define    HP_RAM_BIST_START               0x00000001 /* start/stop BIST */
-
-
-/** MAC registers.  **/
-/* reset bits are set using a PIO write and self-cleared after the command
- * execution has completed.
- */
-#define  REG_MAC_TX_RESET                  0x6000  /* TX MAC software reset
-						      command (default: 0x0) */
-#define  REG_MAC_RX_RESET                  0x6004  /* RX MAC software reset
-						      command (default: 0x0) */
-/* execute a pause flow control frame transmission
- DEFAULT: 0x0XXXX */
-#define  REG_MAC_SEND_PAUSE                0x6008  /* send pause command reg */
-#define    MAC_SEND_PAUSE_TIME_MASK        0x0000FFFF /* value of pause time
-							 to be sent on network
-							 in units of slot
-							 times */
-#define    MAC_SEND_PAUSE_SEND             0x00010000 /* send pause flow ctrl
-							 frame on network */
-
-/* bit set indicates that event occurred. auto-cleared when status register
- * is read and have corresponding mask bits in mask register. events will
- * trigger an interrupt if the corresponding mask bit is 0.
- * status register default: 0x00000000
- * mask register default = 0xFFFFFFFF on reset
- */
-#define  REG_MAC_TX_STATUS                 0x6010  /* TX MAC status reg */
-#define    MAC_TX_FRAME_XMIT               0x0001  /* successful frame
-						      transmision */
-#define    MAC_TX_UNDERRUN                 0x0002  /* terminated frame
-						      transmission due to
-						      data starvation in the
-						      xmit data path */
-#define    MAC_TX_MAX_PACKET_ERR           0x0004  /* frame exceeds max allowed
-						      length passed to TX MAC
-						      by the DMA engine */
-#define    MAC_TX_COLL_NORMAL              0x0008  /* rollover of the normal
-						      collision counter */
-#define    MAC_TX_COLL_EXCESS              0x0010  /* rollover of the excessive
-						      collision counter */
-#define    MAC_TX_COLL_LATE                0x0020  /* rollover of the late
-						      collision counter */
-#define    MAC_TX_COLL_FIRST               0x0040  /* rollover of the first
-						      collision counter */
-#define    MAC_TX_DEFER_TIMER              0x0080  /* rollover of the defer
-						      timer */
-#define    MAC_TX_PEAK_ATTEMPTS            0x0100  /* rollover of the peak
-						      attempts counter */
-
-#define  REG_MAC_RX_STATUS                 0x6014  /* RX MAC status reg */
-#define    MAC_RX_FRAME_RECV               0x0001  /* successful receipt of
-						      a frame */
-#define    MAC_RX_OVERFLOW                 0x0002  /* dropped frame due to
-						      RX FIFO overflow */
-#define    MAC_RX_FRAME_COUNT              0x0004  /* rollover of receive frame
-						      counter */
-#define    MAC_RX_ALIGN_ERR                0x0008  /* rollover of alignment
-						      error counter */
-#define    MAC_RX_CRC_ERR                  0x0010  /* rollover of crc error
-						      counter */
-#define    MAC_RX_LEN_ERR                  0x0020  /* rollover of length
-						      error counter */
-#define    MAC_RX_VIOL_ERR                 0x0040  /* rollover of code
-						      violation error */
-
-/* DEFAULT: 0xXXXX0000 on reset */
-#define  REG_MAC_CTRL_STATUS               0x6018  /* MAC control status reg */
-#define    MAC_CTRL_PAUSE_RECEIVED         0x00000001  /* successful
-							  reception of a
-							  pause control
-							  frame */
-#define    MAC_CTRL_PAUSE_STATE            0x00000002  /* MAC has made a
-							  transition from
-							  "not paused" to
-							  "paused" */
-#define    MAC_CTRL_NOPAUSE_STATE          0x00000004  /* MAC has made a
-							  transition from
-							  "paused" to "not
-							  paused" */
-#define    MAC_CTRL_PAUSE_TIME_MASK        0xFFFF0000  /* value of pause time
-							  operand that was
-							  received in the last
-							  pause flow control
-							  frame */
-
-/* layout identical to TX MAC[8:0] */
-#define  REG_MAC_TX_MASK                   0x6020  /* TX MAC mask reg */
-/* layout identical to RX MAC[6:0] */
-#define  REG_MAC_RX_MASK                   0x6024  /* RX MAC mask reg */
-/* layout identical to CTRL MAC[2:0] */
-#define  REG_MAC_CTRL_MASK                 0x6028  /* MAC control mask reg */
-
-/* to ensure proper operation, CFG_EN must be cleared to 0 and a delay
- * imposed before writes to other bits in the TX_MAC_CFG register or any of
- * the MAC parameters is performed. delay dependent upon time required to
- * transmit a maximum size frame (= MAC_FRAMESIZE_MAX*8/Mbps). e.g.,
- * the delay for a 1518-byte frame on a 100Mbps network is 125us.
- * alternatively, just poll TX_CFG_EN until it reads back as 0.
- * NOTE: on half-duplex 1Gbps, TX_CFG_CARRIER_EXTEND and
- * RX_CFG_CARRIER_EXTEND should be set and the SLOT_TIME register should
- * be 0x200 (slot time of 512 bytes)
- */
-#define  REG_MAC_TX_CFG                 0x6030  /* TX MAC config reg */
-#define    MAC_TX_CFG_EN                0x0001  /* enable TX MAC. 0 will
-						      force TXMAC state
-						      machine to remain in
-						      idle state or to
-						      transition to idle state
-						      on completion of an
-						      ongoing packet. */
-#define    MAC_TX_CFG_IGNORE_CARRIER    0x0002  /* disable CSMA/CD deferral
-						   process. set to 1 when
-						   full duplex and 0 when
-						   half duplex */
-#define    MAC_TX_CFG_IGNORE_COLL       0x0004  /* disable CSMA/CD backoff
-						   algorithm. set to 1 when
-						   full duplex and 0 when
-						   half duplex */
-#define    MAC_TX_CFG_IPG_EN            0x0008  /* enable extension of the
-						   Rx-to-TX IPG. after
-						   receiving a frame, TX
-						   MAC will reset its
-						   deferral process to
-						   carrier sense for the
-						   amount of time = IPG0 +
-						   IPG1 and commit to
-						   transmission for time
-						   specified in IPG2. when
-						   0 or when xmitting frames
-						   back-to-pack (Tx-to-Tx
-						   IPG), TX MAC ignores
-						   IPG0 and will only use
-						   IPG1 for deferral time.
-						   IPG2 still used. */
-#define    MAC_TX_CFG_NEVER_GIVE_UP_EN  0x0010  /* TX MAC will not easily
-						   give up on frame
-						   xmission. if backoff
-						   algorithm reaches the
-						   ATTEMPT_LIMIT, it will
-						   clear attempts counter
-						   and continue trying to
-						   send the frame as
-						   specified by
-						   GIVE_UP_LIM. when 0,
-						   TX MAC will execute
-						   standard CSMA/CD prot. */
-#define    MAC_TX_CFG_NEVER_GIVE_UP_LIM 0x0020  /* when set, TX MAC will
-						   continue to try to xmit
-						   until successful. when
-						   0, TX MAC will continue
-						   to try xmitting until
-						   successful or backoff
-						   algorithm reaches
-						   ATTEMPT_LIMIT*16 */
-#define    MAC_TX_CFG_NO_BACKOFF        0x0040  /* modify CSMA/CD to disable
-						   backoff algorithm. TX
-						   MAC will not back off
-						   after a xmission attempt
-						   that resulted in a
-						   collision. */
-#define    MAC_TX_CFG_SLOW_DOWN         0x0080  /* modify CSMA/CD so that
-						   deferral process is reset
-						   in response to carrier
-						   sense during the entire
-						   duration of IPG. TX MAC
-						   will only commit to frame
-						   xmission after frame
-						   xmission has actually
-						   begun. */
-#define    MAC_TX_CFG_NO_FCS            0x0100  /* TX MAC will not generate
-						   CRC for all xmitted
-						   packets. when clear, CRC
-						   generation is dependent
-						   upon NO_CRC bit in the
-						   xmit control word from
-						   TX DMA */
-#define    MAC_TX_CFG_CARRIER_EXTEND    0x0200  /* enables xmit part of the
-						   carrier extension
-						   feature. this allows for
-						   longer collision domains
-						   by extending the carrier
-						   and collision window
-						   from the end of FCS until
-						   the end of the slot time
-						   if necessary. Required
-						   for half-duplex at 1Gbps,
-						   clear otherwise. */
-
-/* when CRC is not stripped, reassembly packets will not contain the CRC.
- * these will be stripped by HRP because it reassembles layer 4 data, and the
- * CRC is layer 2. however, non-reassembly packets will still contain the CRC
- * when passed to the host. to ensure proper operation, need to wait 3.2ms
- * after clearing RX_CFG_EN before writing to any other RX MAC registers
- * or other MAC parameters. alternatively, poll RX_CFG_EN until it clears
- * to 0. similary, HASH_FILTER_EN and ADDR_FILTER_EN have the same
- * restrictions as CFG_EN.
- */
-#define  REG_MAC_RX_CFG                 0x6034  /* RX MAC config reg */
-#define    MAC_RX_CFG_EN                0x0001  /* enable RX MAC */
-#define    MAC_RX_CFG_STRIP_PAD         0x0002  /* always program to 0.
-						   feature not supported */
-#define    MAC_RX_CFG_STRIP_FCS         0x0004  /* RX MAC will strip the
-						   last 4 bytes of a
-						   received frame. */
-#define    MAC_RX_CFG_PROMISC_EN        0x0008  /* promiscuous mode */
-#define    MAC_RX_CFG_PROMISC_GROUP_EN  0x0010  /* accept all valid
-						   multicast frames (group
-						   bit in DA field set) */
-#define    MAC_RX_CFG_HASH_FILTER_EN    0x0020  /* use hash table to filter
-						   multicast addresses */
-#define    MAC_RX_CFG_ADDR_FILTER_EN    0x0040  /* cause RX MAC to use
-						   address filtering regs
-						   to filter both unicast
-						   and multicast
-						   addresses */
-#define    MAC_RX_CFG_DISABLE_DISCARD   0x0080  /* pass errored frames to
-						   RX DMA by setting BAD
-						   bit but not Abort bit
-						   in the status. CRC,
-						   framing, and length errs
-						   will not increment
-						   error counters. frames
-						   which don't match dest
-						   addr will be passed up
-						   w/ BAD bit set. */
-#define    MAC_RX_CFG_CARRIER_EXTEND    0x0100  /* enable reception of
-						   packet bursts generated
-						   by carrier extension
-						   with packet bursting
-						   senders. only applies
-						   to half-duplex 1Gbps */
-
-/* DEFAULT: 0x0 */
-#define  REG_MAC_CTRL_CFG               0x6038  /* MAC control config reg */
-#define    MAC_CTRL_CFG_SEND_PAUSE_EN   0x0001  /* respond to requests for
-						   sending pause flow ctrl
-						   frames */
-#define    MAC_CTRL_CFG_RECV_PAUSE_EN   0x0002  /* respond to received
-						   pause flow ctrl frames */
-#define    MAC_CTRL_CFG_PASS_CTRL       0x0004  /* pass valid MAC ctrl
-						   packets to RX DMA */
-
-/* to ensure proper operation, a global initialization sequence should be
- * performed when a loopback config is entered or exited. if programmed after
- * a hw or global sw reset, RX/TX MAC software reset and initialization
- * should be done to ensure stable clocking.
- * DEFAULT: 0x0
- */
-#define  REG_MAC_XIF_CFG                0x603C  /* XIF config reg */
-#define    MAC_XIF_TX_MII_OUTPUT_EN        0x0001  /* enable output drivers
-						      on MII xmit bus */
-#define    MAC_XIF_MII_INT_LOOPBACK        0x0002  /* loopback GMII xmit data
-						      path to GMII recv data
-						      path. phy mode register
-						      clock selection must be
-						      set to GMII mode and
-						      GMII_MODE should be set
-						      to 1. in loopback mode,
-						      REFCLK will drive the
-						      entire mac core. 0 for
-						      normal operation. */
-#define    MAC_XIF_DISABLE_ECHO            0x0004  /* disables receive data
-						      path during packet
-						      xmission. clear to 0
-						      in any full duplex mode,
-						      in any loopback mode,
-						      or in half-duplex SERDES
-						      or SLINK modes. set when
-						      in half-duplex when
-						      using external phy. */
-#define    MAC_XIF_GMII_MODE               0x0008  /* MAC operates with GMII
-						      clocks and datapath */
-#define    MAC_XIF_MII_BUFFER_OUTPUT_EN    0x0010  /* MII_BUF_EN pin. enable
-						      external tristate buffer
-						      on the MII receive
-						      bus. */
-#define    MAC_XIF_LINK_LED                0x0020  /* LINKLED# active (low) */
-#define    MAC_XIF_FDPLX_LED               0x0040  /* FDPLXLED# active (low) */
-
-#define  REG_MAC_IPG0                      0x6040  /* inter-packet gap0 reg.
-						      recommended: 0x00 */
-#define  REG_MAC_IPG1                      0x6044  /* inter-packet gap1 reg
-						      recommended: 0x08 */
-#define  REG_MAC_IPG2                      0x6048  /* inter-packet gap2 reg
-						      recommended: 0x04 */
-#define  REG_MAC_SLOT_TIME                 0x604C  /* slot time reg
-						      recommended: 0x40 */
-#define  REG_MAC_FRAMESIZE_MIN             0x6050  /* min frame size reg
-						      recommended: 0x40 */
-
-/* FRAMESIZE_MAX holds both the max frame size as well as the max burst size.
- * recommended value:  0x2000.05EE
- */
-#define  REG_MAC_FRAMESIZE_MAX             0x6054  /* max frame size reg */
-#define    MAC_FRAMESIZE_MAX_BURST_MASK    0x3FFF0000 /* max burst size */
-#define    MAC_FRAMESIZE_MAX_BURST_SHIFT   16
-#define    MAC_FRAMESIZE_MAX_FRAME_MASK    0x00007FFF /* max frame size */
-#define    MAC_FRAMESIZE_MAX_FRAME_SHIFT   0
-#define  REG_MAC_PA_SIZE                   0x6058  /* PA size reg. number of
-						      preamble bytes that the
-						      TX MAC will xmit at the
-						      beginning of each frame
-						      value should be 2 or
-						      greater. recommended
-						      value: 0x07 */
-#define  REG_MAC_JAM_SIZE                  0x605C  /* jam size reg. duration
-						      of jam in units of media
-						      byte time. recommended
-						      value: 0x04 */
-#define  REG_MAC_ATTEMPT_LIMIT             0x6060  /* attempt limit reg. #
-						      of attempts TX MAC will
-						      make to xmit a frame
-						      before it resets its
-						      attempts counter. after
-						      the limit has been
-						      reached, TX MAC may or
-						      may not drop the frame
-						      dependent upon value
-						      in TX_MAC_CFG.
-						      recommended
-						      value: 0x10 */
-#define  REG_MAC_CTRL_TYPE                 0x6064  /* MAC control type reg.
-						      type field of a MAC
-						      ctrl frame. recommended
-						      value: 0x8808 */
-
-/* mac address registers: 0 - 44, 0x6080 - 0x6130, 4 8-bit bytes.
- * register           contains                   comparison
- *    0        16 MSB of primary MAC addr        [47:32] of DA field
- *    1        16 middle bits ""                 [31:16] of DA field
- *    2        16 LSB ""                         [15:0] of DA field
- *    3*x      16MSB of alt MAC addr 1-15        [47:32] of DA field
- *    4*x      16 middle bits ""                 [31:16]
- *    5*x      16 LSB ""                         [15:0]
- *    42       16 MSB of MAC CTRL addr           [47:32] of DA.
- *    43       16 middle bits ""                 [31:16]
- *    44       16 LSB ""                         [15:0]
- *    MAC CTRL addr must be the reserved multicast addr for MAC CTRL frames.
- *    if there is a match, MAC will set the bit for alternative address
- *    filter pass [15]
-
- *    here is the map of registers given MAC address notation: a:b:c:d:e:f
- *                     ab             cd             ef
- *    primary addr     reg 2          reg 1          reg 0
- *    alt addr 1       reg 5          reg 4          reg 3
- *    alt addr x       reg 5*x        reg 4*x        reg 3*x
- *    ctrl addr        reg 44         reg 43         reg 42
- */
-#define  REG_MAC_ADDR0                     0x6080  /* MAC address 0 reg */
-#define  REG_MAC_ADDRN(x)                  (REG_MAC_ADDR0 + (x)*4)
-#define  REG_MAC_ADDR_FILTER0              0x614C  /* address filter 0 reg
-						      [47:32] */
-#define  REG_MAC_ADDR_FILTER1              0x6150  /* address filter 1 reg
-						      [31:16] */
-#define  REG_MAC_ADDR_FILTER2              0x6154  /* address filter 2 reg
-						      [15:0] */
-#define  REG_MAC_ADDR_FILTER2_1_MASK       0x6158  /* address filter 2 and 1
-						      mask reg. 8-bit reg
-						      contains nibble mask for
-						      reg 2 and 1. */
-#define  REG_MAC_ADDR_FILTER0_MASK         0x615C  /* address filter 0 mask
-						      reg */
-
-/* hash table registers: 0 - 15, 0x6160 - 0x619C, 4 8-bit bytes
- * 16-bit registers contain bits of the hash table.
- * reg x  -> [16*(15 - x) + 15 : 16*(15 - x)].
- * e.g., 15 -> [15:0], 0 -> [255:240]
- */
-#define  REG_MAC_HASH_TABLE0               0x6160  /* hash table 0 reg */
-#define  REG_MAC_HASH_TABLEN(x)            (REG_MAC_HASH_TABLE0 + (x)*4)
-
-/* statistics registers. these registers generate an interrupt on
- * overflow. recommended initialization: 0x0000. most are 16-bits except
- * for PEAK_ATTEMPTS register which is 8 bits.
- */
-#define  REG_MAC_COLL_NORMAL               0x61A0 /* normal collision
-						     counter. */
-#define  REG_MAC_COLL_FIRST                0x61A4 /* first attempt
-						     successful collision
-						     counter */
-#define  REG_MAC_COLL_EXCESS               0x61A8 /* excessive collision
-						     counter */
-#define  REG_MAC_COLL_LATE                 0x61AC /* late collision counter */
-#define  REG_MAC_TIMER_DEFER               0x61B0 /* defer timer. time base
-						     is the media byte
-						     clock/256 */
-#define  REG_MAC_ATTEMPTS_PEAK             0x61B4 /* peak attempts reg */
-#define  REG_MAC_RECV_FRAME                0x61B8 /* receive frame counter */
-#define  REG_MAC_LEN_ERR                   0x61BC /* length error counter */
-#define  REG_MAC_ALIGN_ERR                 0x61C0 /* alignment error counter */
-#define  REG_MAC_FCS_ERR                   0x61C4 /* FCS error counter */
-#define  REG_MAC_RX_CODE_ERR               0x61C8 /* RX code violation
-						     error counter */
-
-/* misc registers */
-#define  REG_MAC_RANDOM_SEED               0x61CC /* random number seed reg.
-						   10-bit register used as a
-						   seed  for the random number
-						   generator for the CSMA/CD
-						   backoff algorithm. only
-						   programmed after power-on
-						   reset and should be a
-						   random value which has a
-						   high likelihood of being
-						   unique for each MAC
-						   attached to a network
-						   segment (e.g., 10 LSB of
-						   MAC address) */
-
-/* ASUN: there's a PAUSE_TIMER (ro) described, but it's not in the address
- *       map
- */
-
-/* 27-bit register has the current state for key state machines in the MAC */
-#define  REG_MAC_STATE_MACHINE             0x61D0 /* (ro) state machine reg */
-#define    MAC_SM_RLM_MASK                 0x07800000
-#define    MAC_SM_RLM_SHIFT                23
-#define    MAC_SM_RX_FC_MASK               0x00700000
-#define    MAC_SM_RX_FC_SHIFT              20
-#define    MAC_SM_TLM_MASK                 0x000F0000
-#define    MAC_SM_TLM_SHIFT                16
-#define    MAC_SM_ENCAP_SM_MASK            0x0000F000
-#define    MAC_SM_ENCAP_SM_SHIFT           12
-#define    MAC_SM_TX_REQ_MASK              0x00000C00
-#define    MAC_SM_TX_REQ_SHIFT             10
-#define    MAC_SM_TX_FC_MASK               0x000003C0
-#define    MAC_SM_TX_FC_SHIFT              6
-#define    MAC_SM_FIFO_WRITE_SEL_MASK      0x00000038
-#define    MAC_SM_FIFO_WRITE_SEL_SHIFT     3
-#define    MAC_SM_TX_FIFO_EMPTY_MASK       0x00000007
-#define    MAC_SM_TX_FIFO_EMPTY_SHIFT      0
-
-/** MIF registers. the MIF can be programmed in either bit-bang or
- *  frame mode.
- **/
-#define  REG_MIF_BIT_BANG_CLOCK            0x6200 /* MIF bit-bang clock.
-						   1 -> 0 will generate a
-						   rising edge. 0 -> 1 will
-						   generate a falling edge. */
-#define  REG_MIF_BIT_BANG_DATA             0x6204 /* MIF bit-bang data. 1-bit
-						     register generates data */
-#define  REG_MIF_BIT_BANG_OUTPUT_EN        0x6208 /* MIF bit-bang output
-						     enable. enable when
-						     xmitting data from MIF to
-						     transceiver. */
-
-/* 32-bit register serves as an instruction register when the MIF is
- * programmed in frame mode. load this register w/ a valid instruction
- * (as per IEEE 802.3u MII spec). poll this register to check for instruction
- * execution completion. during a read operation, this register will also
- * contain the 16-bit data returned by the tranceiver. unless specified
- * otherwise, fields are considered "don't care" when polling for
- * completion.
- */
-#define  REG_MIF_FRAME                     0x620C /* MIF frame/output reg */
-#define    MIF_FRAME_START_MASK            0xC0000000 /* start of frame.
-							 load w/ 01 when
-							 issuing an instr */
-#define    MIF_FRAME_ST                    0x40000000 /* STart of frame */
-#define    MIF_FRAME_OPCODE_MASK           0x30000000 /* opcode. 01 for a
-							 write. 10 for a
-							 read */
-#define    MIF_FRAME_OP_READ               0x20000000 /* read OPcode */
-#define    MIF_FRAME_OP_WRITE              0x10000000 /* write OPcode */
-#define    MIF_FRAME_PHY_ADDR_MASK         0x0F800000 /* phy address. when
-							 issuing an instr,
-							 this field should be
-							 loaded w/ the XCVR
-							 addr */
-#define    MIF_FRAME_PHY_ADDR_SHIFT        23
-#define    MIF_FRAME_REG_ADDR_MASK         0x007C0000 /* register address.
-							 when issuing an instr,
-							 addr of register
-							 to be read/written */
-#define    MIF_FRAME_REG_ADDR_SHIFT        18
-#define    MIF_FRAME_TURN_AROUND_MSB       0x00020000 /* turn around, MSB.
-							 when issuing an instr,
-							 set this bit to 1 */
-#define    MIF_FRAME_TURN_AROUND_LSB       0x00010000 /* turn around, LSB.
-							 when issuing an instr,
-							 set this bit to 0.
-							 when polling for
-							 completion, 1 means
-							 that instr execution
-							 has been completed */
-#define    MIF_FRAME_DATA_MASK             0x0000FFFF /* instruction payload
-							 load with 16-bit data
-							 to be written in
-							 transceiver reg for a
-							 write. doesn't matter
-							 in a read. when
-							 polling for
-							 completion, field is
-							 "don't care" for write
-							 and 16-bit data
-							 returned by the
-							 transceiver for a
-							 read (if valid bit
-							 is set) */
-#define  REG_MIF_CFG                    0x6210 /* MIF config reg */
-#define    MIF_CFG_PHY_SELECT           0x0001 /* 1 -> select MDIO_1
-						  0 -> select MDIO_0 */
-#define    MIF_CFG_POLL_EN              0x0002 /* enable polling
-						  mechanism. if set,
-						  BB_MODE should be 0 */
-#define    MIF_CFG_BB_MODE              0x0004 /* 1 -> bit-bang mode
-						  0 -> frame mode */
-#define    MIF_CFG_POLL_REG_MASK        0x00F8 /* register address to be
-						  used by polling mode.
-						  only meaningful if POLL_EN
-						  is set to 1 */
-#define    MIF_CFG_POLL_REG_SHIFT       3
-#define    MIF_CFG_MDIO_0               0x0100 /* (ro) dual purpose.
-						  when MDIO_0 is idle,
-						  1 -> tranceiver is
-						  connected to MDIO_0.
-						  when MIF is communicating
-						  w/ MDIO_0 in bit-bang
-						  mode, this bit indicates
-						  the incoming bit stream
-						  during a read op */
-#define    MIF_CFG_MDIO_1               0x0200 /* (ro) dual purpose.
-						  when MDIO_1 is idle,
-						  1 -> transceiver is
-						  connected to MDIO_1.
-						  when MIF is communicating
-						  w/ MDIO_1 in bit-bang
-						  mode, this bit indicates
-						  the incoming bit stream
-						  during a read op */
-#define    MIF_CFG_POLL_PHY_MASK        0x7C00 /* tranceiver address to
-						  be polled */
-#define    MIF_CFG_POLL_PHY_SHIFT       10
-
-/* 16-bit register used to determine which bits in the POLL_STATUS portion of
- * the MIF_STATUS register will cause an interrupt. if a mask bit is 0,
- * corresponding bit of the POLL_STATUS will generate a MIF interrupt when
- * set. DEFAULT: 0xFFFF
- */
-#define  REG_MIF_MASK                      0x6214 /* MIF mask reg */
-
-/* 32-bit register used when in poll mode. auto-cleared after being read */
-#define  REG_MIF_STATUS                    0x6218 /* MIF status reg */
-#define    MIF_STATUS_POLL_DATA_MASK       0xFFFF0000 /* poll data contains
-							 the "latest image"
-							 update of the XCVR
-							 reg being read */
-#define    MIF_STATUS_POLL_DATA_SHIFT      16
-#define    MIF_STATUS_POLL_STATUS_MASK     0x0000FFFF /* poll status indicates
-							 which bits in the
-							 POLL_DATA field have
-							 changed since the
-							 MIF_STATUS reg was
-							 last read */
-#define    MIF_STATUS_POLL_STATUS_SHIFT    0
-
-/* 7-bit register has current state for all state machines in the MIF */
-#define  REG_MIF_STATE_MACHINE             0x621C /* MIF state machine reg */
-#define    MIF_SM_CONTROL_MASK             0x07   /* control state machine
-						     state */
-#define    MIF_SM_EXECUTION_MASK           0x60   /* execution state machine
-						     state */
-
-/** PCS/Serialink. the following registers are equivalent to the standard
- *  MII management registers except that they're directly mapped in
- *  Cassini's register space.
- **/
-
-/* the auto-negotiation enable bit should be programmed the same at
- * the link partner as in the local device to enable auto-negotiation to
- * complete. when that bit is reprogrammed, auto-neg/manual config is
- * restarted automatically.
- * DEFAULT: 0x1040
- */
-#define  REG_PCS_MII_CTRL                  0x9000 /* PCS MII control reg */
-#define    PCS_MII_CTRL_1000_SEL           0x0040 /* reads 1. ignored on
-						     writes */
-#define    PCS_MII_CTRL_COLLISION_TEST     0x0080 /* COL signal at the PCS
-						     to MAC interface is
-						     activated regardless
-						     of activity */
-#define    PCS_MII_CTRL_DUPLEX             0x0100 /* forced 0x0. PCS
-						     behaviour same for
-						     half and full dplx */
-#define    PCS_MII_RESTART_AUTONEG         0x0200 /* self clearing.
-						     restart auto-
-						     negotiation */
-#define    PCS_MII_ISOLATE                 0x0400 /* read as 0. ignored
-						     on writes */
-#define    PCS_MII_POWER_DOWN              0x0800 /* read as 0. ignored
-						     on writes */
-#define    PCS_MII_AUTONEG_EN              0x1000 /* default 1. PCS goes
-						     through automatic
-						     link config before it
-						     can be used. when 0,
-						     link can be used
-						     w/out any link config
-						     phase */
-#define    PCS_MII_10_100_SEL              0x2000 /* read as 0. ignored on
-						     writes */
-#define    PCS_MII_RESET                   0x8000 /* reset PCS. self-clears
-						     when done */
-
-/* DEFAULT: 0x0108 */
-#define  REG_PCS_MII_STATUS                0x9004 /* PCS MII status reg */
-#define    PCS_MII_STATUS_EXTEND_CAP       0x0001 /* reads 0 */
-#define    PCS_MII_STATUS_JABBER_DETECT    0x0002 /* reads 0 */
-#define    PCS_MII_STATUS_LINK_STATUS      0x0004 /* 1 -> link up.
-						     0 -> link down. 0 is
-						     latched so that 0 is
-						     kept until read. read
-						     2x to determine if the
-						     link has gone up again */
-#define    PCS_MII_STATUS_AUTONEG_ABLE     0x0008 /* reads 1 (able to perform
-						     auto-neg) */
-#define    PCS_MII_STATUS_REMOTE_FAULT     0x0010 /* 1 -> remote fault detected
-						     from received link code
-						     word. only valid after
-						     auto-neg completed */
-#define    PCS_MII_STATUS_AUTONEG_COMP     0x0020 /* 1 -> auto-negotiation
-						          completed
-						     0 -> auto-negotiation not
-						     completed */
-#define    PCS_MII_STATUS_EXTEND_STATUS    0x0100 /* reads as 1. used as an
-						     indication that this is
-						     a 1000 Base-X PHY. writes
-						     to it are ignored */
-
-/* used during auto-negotiation.
- * DEFAULT: 0x00E0
- */
-#define  REG_PCS_MII_ADVERT                0x9008 /* PCS MII advertisement
-						     reg */
-#define    PCS_MII_ADVERT_FD               0x0020  /* advertise full duplex
-						      1000 Base-X */
-#define    PCS_MII_ADVERT_HD               0x0040  /* advertise half-duplex
-						      1000 Base-X */
-#define    PCS_MII_ADVERT_SYM_PAUSE        0x0080  /* advertise PAUSE
-						      symmetric capability */
-#define    PCS_MII_ADVERT_ASYM_PAUSE       0x0100  /* advertises PAUSE
-						      asymmetric capability */
-#define    PCS_MII_ADVERT_RF_MASK          0x3000 /* remote fault. write bit13
-						     to optionally indicate to
-						     link partner that chip is
-						     going off-line. bit12 will
-						     get set when signal
-						     detect == FAIL and will
-						     remain set until
-						     successful negotiation */
-#define    PCS_MII_ADVERT_ACK              0x4000 /* (ro) */
-#define    PCS_MII_ADVERT_NEXT_PAGE        0x8000 /* (ro) forced 0x0 */
-
-/* contents updated as a result of autonegotiation. layout and definitions
- * identical to PCS_MII_ADVERT
- */
-#define  REG_PCS_MII_LPA                   0x900C /* PCS MII link partner
-						     ability reg */
-#define    PCS_MII_LPA_FD             PCS_MII_ADVERT_FD
-#define    PCS_MII_LPA_HD             PCS_MII_ADVERT_HD
-#define    PCS_MII_LPA_SYM_PAUSE      PCS_MII_ADVERT_SYM_PAUSE
-#define    PCS_MII_LPA_ASYM_PAUSE     PCS_MII_ADVERT_ASYM_PAUSE
-#define    PCS_MII_LPA_RF_MASK        PCS_MII_ADVERT_RF_MASK
-#define    PCS_MII_LPA_ACK            PCS_MII_ADVERT_ACK
-#define    PCS_MII_LPA_NEXT_PAGE      PCS_MII_ADVERT_NEXT_PAGE
-
-/* DEFAULT: 0x0 */
-#define  REG_PCS_CFG                       0x9010 /* PCS config reg */
-#define    PCS_CFG_EN                      0x01   /* enable PCS. must be
-						     0 when modifying
-						     PCS_MII_ADVERT */
-#define    PCS_CFG_SD_OVERRIDE             0x02   /* sets signal detect to
-						     OK. bit is
-						     non-resettable */
-#define    PCS_CFG_SD_ACTIVE_LOW           0x04   /* changes interpretation
-						     of optical signal to make
-						     signal detect okay when
-						     signal is low */
-#define    PCS_CFG_JITTER_STUDY_MASK       0x18   /* used to make jitter
-						     measurements. a single
-						     code group is xmitted
-						     regularly.
-						     0x0 = normal operation
-						     0x1 = high freq test
-						           pattern, D21.5
-						     0x2 = low freq test
-						           pattern, K28.7
-						     0x3 = reserved */
-#define    PCS_CFG_10MS_TIMER_OVERRIDE     0x20   /* shortens 10-20ms auto-
-						     negotiation timer to
-						     a few cycles for test
-						     purposes */
-
-/* used for diagnostic purposes. bits 20-22 autoclear on read */
-#define  REG_PCS_STATE_MACHINE             0x9014 /* (ro) PCS state machine
-						     and diagnostic reg */
-#define    PCS_SM_TX_STATE_MASK            0x0000000F /* 0 and 1 indicate
-							 xmission of idle.
-							 otherwise, xmission of
-							 a packet */
-#define    PCS_SM_RX_STATE_MASK            0x000000F0 /* 0 indicates reception
-							 of idle. otherwise,
-							 reception of packet */
-#define    PCS_SM_WORD_SYNC_STATE_MASK     0x00000700 /* 0 indicates loss of
-							 sync */
-#define    PCS_SM_SEQ_DETECT_STATE_MASK    0x00001800 /* cycling through 0-3
-							 indicates reception of
-							 Config codes. cycling
-							 through 0-1 indicates
-							 reception of idles */
-#define    PCS_SM_LINK_STATE_MASK          0x0001E000
-#define        SM_LINK_STATE_UP            0x00016000 /* link state is up */
-
-#define    PCS_SM_LOSS_LINK_C              0x00100000 /* loss of link due to
-							 recept of Config
-							 codes */
-#define    PCS_SM_LOSS_LINK_SYNC           0x00200000 /* loss of link due to
-							 loss of sync */
-#define    PCS_SM_LOSS_SIGNAL_DETECT       0x00400000 /* signal detect goes
-							 from OK to FAIL. bit29
-							 will also be set if
-							 this is set */
-#define    PCS_SM_NO_LINK_BREAKLINK        0x01000000 /* link not up due to
-							receipt of breaklink
-							C codes from partner.
-							C codes w/ 0 content
-							received triggering
-							start/restart of
-							autonegotiation.
-							should be sent for
-							no longer than 20ms */
-#define    PCS_SM_NO_LINK_SERDES           0x02000000 /* serdes being
-							initialized. see serdes
-							state reg */
-#define    PCS_SM_NO_LINK_C                0x04000000 /* C codes not stable or
-							 not received */
-#define    PCS_SM_NO_LINK_SYNC             0x08000000 /* word sync not
-							 achieved */
-#define    PCS_SM_NO_LINK_WAIT_C           0x10000000 /* waiting for C codes
-							 w/ ack bit set */
-#define    PCS_SM_NO_LINK_NO_IDLE          0x20000000 /* link partner continues
-							 to send C codes
-							 instead of idle
-							 symbols or pkt data */
-
-/* this register indicates interrupt changes in specific PCS MII status bits.
- * PCS_INT may be masked at the ISR level. only a single bit is implemented
- * for link status change.
- */
-#define  REG_PCS_INTR_STATUS               0x9018 /* PCS interrupt status */
-#define    PCS_INTR_STATUS_LINK_CHANGE     0x04   /* link status has changed
-						     since last read */
-
-/* control which network interface is used. no more than one bit should
- * be set.
- * DEFAULT: none
- */
-#define  REG_PCS_DATAPATH_MODE             0x9050 /* datapath mode reg */
-#define    PCS_DATAPATH_MODE_MII           0x00 /* PCS is not used and
-						   MII/GMII is selected.
-						   selection between MII and
-						   GMII is controlled by
-						   XIF_CFG */
-#define    PCS_DATAPATH_MODE_SERDES        0x02 /* PCS is used via the
-						   10-bit interface */
-
-/* input to serdes chip or serialink block */
-#define  REG_PCS_SERDES_CTRL              0x9054 /* serdes control reg */
-#define    PCS_SERDES_CTRL_LOOPBACK       0x01   /* enable loopback on
-						    serdes interface */
-#define    PCS_SERDES_CTRL_SYNCD_EN       0x02   /* enable sync carrier
-						    detection. should be
-						    0x0 for normal
-						    operation */
-#define    PCS_SERDES_CTRL_LOCKREF       0x04   /* frequency-lock RBC[0:1]
-						   to REFCLK when set.
-						   when clear, receiver
-						   clock locks to incoming
-						   serial data */
-
-/* multiplex test outputs into the PROM address (PA_3 through PA_0) pins.
- * should be 0x0 for normal operations.
- * 0b000          normal operation, PROM address[3:0] selected
- * 0b001          rxdma req, rxdma ack, rxdma ready, rxdma read
- * 0b010          rxmac req, rx ack, rx tag, rx clk shared
- * 0b011          txmac req, tx ack, tx tag, tx retry req
- * 0b100          tx tp3, tx tp2, tx tp1, tx tp0
- * 0b101          R period RX, R period TX, R period HP, R period BIM
- * DEFAULT: 0x0
- */
-#define  REG_PCS_SHARED_OUTPUT_SEL         0x9058 /* shared output select */
-#define    PCS_SOS_PROM_ADDR_MASK          0x0007
-
-/* used for diagnostics. this register indicates progress of the SERDES
- * boot up.
- * 0b00       undergoing reset
- * 0b01       waiting 500us while lockrefn is asserted
- * 0b10       waiting for comma detect
- * 0b11       receive data is synchronized
- * DEFAULT: 0x0
- */
-#define  REG_PCS_SERDES_STATE              0x905C /* (ro) serdes state */
-#define    PCS_SERDES_STATE_MASK           0x03
-
-/* used for diagnostics. indicates number of packets transmitted or received.
- * counters rollover w/out generating an interrupt.
- * DEFAULT: 0x0
- */
-#define  REG_PCS_PACKET_COUNT              0x9060 /* (ro) PCS packet counter */
-#define    PCS_PACKET_COUNT_TX             0x000007FF /* pkts xmitted by PCS */
-#define    PCS_PACKET_COUNT_RX             0x07FF0000 /* pkts recvd by PCS
-							 whether they
-							 encountered an error
-							 or not */
-
-/** LocalBus Devices. the following provides run-time access to the
- *  Cassini's PROM
- ***/
-#define  REG_EXPANSION_ROM_RUN_START       0x100000 /* expansion rom run time
-						       access */
-#define  REG_EXPANSION_ROM_RUN_END         0x17FFFF
-
-#define  REG_SECOND_LOCALBUS_START         0x180000 /* secondary local bus
-						       device */
-#define  REG_SECOND_LOCALBUS_END           0x1FFFFF
-
-/* entropy device */
-#define  REG_ENTROPY_START                 REG_SECOND_LOCALBUS_START
-#define  REG_ENTROPY_DATA                  (REG_ENTROPY_START + 0x00)
-#define  REG_ENTROPY_STATUS                (REG_ENTROPY_START + 0x04)
-#define      ENTROPY_STATUS_DRDY           0x01
-#define      ENTROPY_STATUS_BUSY           0x02
-#define      ENTROPY_STATUS_CIPHER         0x04
-#define      ENTROPY_STATUS_BYPASS_MASK    0x18
-#define  REG_ENTROPY_MODE                  (REG_ENTROPY_START + 0x05)
-#define      ENTROPY_MODE_KEY_MASK         0x07
-#define      ENTROPY_MODE_ENCRYPT          0x40
-#define  REG_ENTROPY_RAND_REG              (REG_ENTROPY_START + 0x06)
-#define  REG_ENTROPY_RESET                 (REG_ENTROPY_START + 0x07)
-#define      ENTROPY_RESET_DES_IO          0x01
-#define      ENTROPY_RESET_STC_MODE        0x02
-#define      ENTROPY_RESET_KEY_CACHE       0x04
-#define      ENTROPY_RESET_IV              0x08
-#define  REG_ENTROPY_IV                    (REG_ENTROPY_START + 0x08)
-#define  REG_ENTROPY_KEY0                  (REG_ENTROPY_START + 0x10)
-#define  REG_ENTROPY_KEYN(x)               (REG_ENTROPY_KEY0 + 4*(x))
-
-/* phys of interest w/ their special mii registers */
-#define PHY_LUCENT_B0     0x00437421
-#define   LUCENT_MII_REG      0x1F
-
-#define PHY_NS_DP83065    0x20005c78
-#define   DP83065_MII_MEM     0x16
-#define   DP83065_MII_REGD    0x1D
-#define   DP83065_MII_REGE    0x1E
-
-#define PHY_BROADCOM_5411 0x00206071
-#define PHY_BROADCOM_B0   0x00206050
-#define   BROADCOM_MII_REG4   0x14
-#define   BROADCOM_MII_REG5   0x15
-#define   BROADCOM_MII_REG7   0x17
-#define   BROADCOM_MII_REG8   0x18
-
-#define   CAS_MII_ANNPTR          0x07
-#define   CAS_MII_ANNPRR          0x08
-#define   CAS_MII_1000_CTRL       0x09
-#define   CAS_MII_1000_STATUS     0x0A
-#define   CAS_MII_1000_EXTEND     0x0F
-
-#define   CAS_BMSR_1000_EXTEND    0x0100 /* supports 1000Base-T extended status */
-/*
- * if autoneg is disabled, here's the table:
- * BMCR_SPEED100 = 100Mbps
- * BMCR_SPEED1000 = 1000Mbps
- * ~(BMCR_SPEED100 | BMCR_SPEED1000) = 10Mbps
- */
-#define   CAS_BMCR_SPEED1000      0x0040  /* Select 1000Mbps */
-
-#define   CAS_ADVERTISE_1000HALF   0x0100
-#define   CAS_ADVERTISE_1000FULL   0x0200
-#define   CAS_ADVERTISE_PAUSE      0x0400
-#define   CAS_ADVERTISE_ASYM_PAUSE 0x0800
-
-/* regular lpa register */
-#define   CAS_LPA_PAUSE	           CAS_ADVERTISE_PAUSE
-#define   CAS_LPA_ASYM_PAUSE       CAS_ADVERTISE_ASYM_PAUSE
-
-/* 1000_STATUS register */
-#define   CAS_LPA_1000HALF        0x0400
-#define   CAS_LPA_1000FULL        0x0800
-
-#define   CAS_EXTEND_1000XFULL    0x8000
-#define   CAS_EXTEND_1000XHALF    0x4000
-#define   CAS_EXTEND_1000TFULL    0x2000
-#define   CAS_EXTEND_1000THALF    0x1000
-
-/* cassini header parser firmware */
-typedef struct cas_hp_inst {
-	const char *note;
-
-	u16 mask, val;
-
-	u8 op;
-	u8 soff, snext;	/* if match succeeds, new offset and match */
-	u8 foff, fnext;	/* if match fails, new offset and match */
-	/* output info */
-	u8 outop;    /* output opcode */
-
-	u16 outarg;  /* output argument */
-	u8 outenab;  /* output enable: 0 = not, 1 = if match
-			 2 = if !match, 3 = always */
-	u8 outshift; /* barrel shift right, 4 bits */
-	u16 outmask;
-} cas_hp_inst_t;
-
-/* comparison */
-#define OP_EQ     0 /* packet == value */
-#define OP_LT     1 /* packet < value */
-#define OP_GT     2 /* packet > value */
-#define OP_NP     3 /* new packet */
-
-/* output opcodes */
-#define	CL_REG	0
-#define	LD_FID	1
-#define	LD_SEQ	2
-#define	LD_CTL	3
-#define	LD_SAP	4
-#define	LD_R1	5
-#define	LD_L3	6
-#define	LD_SUM	7
-#define	LD_HDR	8
-#define	IM_FID	9
-#define	IM_SEQ	10
-#define	IM_SAP	11
-#define	IM_R1	12
-#define	IM_CTL	13
-#define	LD_LEN	14
-#define	ST_FLG	15
-
-/* match setp #s for IP4TCP4 */
-#define S1_PCKT         0
-#define S1_VLAN         1
-#define S1_CFI          2
-#define S1_8023         3
-#define S1_LLC          4
-#define S1_LLCc         5
-#define S1_IPV4         6
-#define S1_IPV4c        7
-#define S1_IPV4F        8
-#define S1_TCP44        9
-#define S1_IPV6         10
-#define S1_IPV6L        11
-#define S1_IPV6c        12
-#define S1_TCP64        13
-#define S1_TCPSQ        14
-#define S1_TCPFG        15
-#define	S1_TCPHL	16
-#define	S1_TCPHc	17
-#define	S1_CLNP		18
-#define	S1_CLNP2	19
-#define	S1_DROP		20
-#define	S2_HTTP		21
-#define	S1_ESP4		22
-#define	S1_AH4		23
-#define	S1_ESP6		24
-#define	S1_AH6		25
-
-#define CAS_PROG_IP46TCP4_PREAMBLE \
-{ "packet arrival?", 0xffff, 0x0000, OP_NP,  6, S1_VLAN,  0, S1_PCKT,  \
-  CL_REG, 0x3ff, 1, 0x0, 0x0000}, \
-{ "VLAN?", 0xffff, 0x8100, OP_EQ,  1, S1_CFI,   0, S1_8023,  \
-  IM_CTL, 0x00a,  3, 0x0, 0xffff}, \
-{ "CFI?", 0x1000, 0x1000, OP_EQ,  0, S1_DROP,  1, S1_8023, \
-  CL_REG, 0x000,  0, 0x0, 0x0000}, \
-{ "8023?", 0xffff, 0x0600, OP_LT,  1, S1_LLC,   0, S1_IPV4, \
-  CL_REG, 0x000,  0, 0x0, 0x0000}, \
-{ "LLC?", 0xffff, 0xaaaa, OP_EQ,  1, S1_LLCc,  0, S1_CLNP, \
-  CL_REG, 0x000,  0, 0x0, 0x0000}, \
-{ "LLCc?", 0xff00, 0x0300, OP_EQ,  2, S1_IPV4,  0, S1_CLNP, \
-  CL_REG, 0x000,  0, 0x0, 0x0000}, \
-{ "IPV4?", 0xffff, 0x0800, OP_EQ,  1, S1_IPV4c, 0, S1_IPV6, \
-  LD_SAP, 0x100,  3, 0x0, 0xffff}, \
-{ "IPV4 cont?", 0xff00, 0x4500, OP_EQ,  3, S1_IPV4F, 0, S1_CLNP, \
-  LD_SUM, 0x00a,  1, 0x0, 0x0000}, \
-{ "IPV4 frag?", 0x3fff, 0x0000, OP_EQ,  1, S1_TCP44, 0, S1_CLNP, \
-  LD_LEN, 0x03e,  1, 0x0, 0xffff}, \
-{ "TCP44?", 0x00ff, 0x0006, OP_EQ,  7, S1_TCPSQ, 0, S1_CLNP, \
-  LD_FID, 0x182,  1, 0x0, 0xffff}, /* FID IP4&TCP src+dst */ \
-{ "IPV6?", 0xffff, 0x86dd, OP_EQ,  1, S1_IPV6L, 0, S1_CLNP,  \
-  LD_SUM, 0x015,  1, 0x0, 0x0000}, \
-{ "IPV6 len", 0xf000, 0x6000, OP_EQ,  0, S1_IPV6c, 0, S1_CLNP, \
-  IM_R1,  0x128,  1, 0x0, 0xffff}, \
-{ "IPV6 cont?", 0x0000, 0x0000, OP_EQ,  3, S1_TCP64, 0, S1_CLNP, \
-  LD_FID, 0x484,  1, 0x0, 0xffff}, /* FID IP6&TCP src+dst */ \
-{ "TCP64?", 0xff00, 0x0600, OP_EQ, 18, S1_TCPSQ, 0, S1_CLNP, \
-  LD_LEN, 0x03f,  1, 0x0, 0xffff}
-
-#ifdef USE_HP_IP46TCP4
-static cas_hp_inst_t cas_prog_ip46tcp4tab[] = {
-	CAS_PROG_IP46TCP4_PREAMBLE,
-	{ "TCP seq", /* DADDR should point to dest port */
-	  0x0000, 0x0000, OP_EQ, 0, S1_TCPFG, 4, S1_TCPFG, LD_SEQ,
-	  0x081,  3, 0x0, 0xffff}, /* Load TCP seq # */
-	{ "TCP control flags", 0x0000, 0x0000, OP_EQ,  0, S1_TCPHL, 0,
-	  S1_TCPHL, ST_FLG, 0x045,  3, 0x0, 0x002f}, /* Load TCP flags */
-	{ "TCP length", 0x0000, 0x0000, OP_EQ,  0, S1_TCPHc, 0,
-	  S1_TCPHc, LD_R1,  0x205,  3, 0xB, 0xf000},
-	{ "TCP length cont", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0,
-	  S1_PCKT,  LD_HDR, 0x0ff,  3, 0x0, 0xffff},
-	{ "Cleanup", 0x0000, 0x0000, OP_EQ,  0, S1_CLNP2,  0, S1_CLNP2,
-	  IM_CTL, 0x001,  3, 0x0, 0x0001},
-	{ "Cleanup 2", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
-	  IM_CTL, 0x000,  0, 0x0, 0x0000},
-	{ "Drop packet", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
-	  IM_CTL, 0x080,  3, 0x0, 0xffff},
-	{ NULL },
-};
-#ifdef HP_IP46TCP4_DEFAULT
-#define CAS_HP_FIRMWARE               cas_prog_ip46tcp4tab
-#endif
-#endif
-
-/*
- * Alternate table load which excludes HTTP server traffic from reassembly.
- * It is substantially similar to the basic table, with one extra state
- * and a few extra compares. */
-#ifdef USE_HP_IP46TCP4NOHTTP
-static cas_hp_inst_t cas_prog_ip46tcp4nohttptab[] = {
-	CAS_PROG_IP46TCP4_PREAMBLE,
-	{ "TCP seq", /* DADDR should point to dest port */
-	  0xFFFF, 0x0080, OP_EQ,  0, S2_HTTP,  0, S1_TCPFG, LD_SEQ,
-	  0x081,  3, 0x0, 0xffff} , /* Load TCP seq # */
-	{ "TCP control flags", 0xFFFF, 0x8080, OP_EQ,  0, S2_HTTP,  0,
-	  S1_TCPHL, ST_FLG, 0x145,  2, 0x0, 0x002f, }, /* Load TCP flags */
-	{ "TCP length", 0x0000, 0x0000, OP_EQ,  0, S1_TCPHc, 0, S1_TCPHc,
-	  LD_R1,  0x205,  3, 0xB, 0xf000},
-	{ "TCP length cont", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
-	  LD_HDR, 0x0ff,  3, 0x0, 0xffff},
-	{ "Cleanup", 0x0000, 0x0000, OP_EQ,  0, S1_CLNP2,  0, S1_CLNP2,
-	  IM_CTL, 0x001,  3, 0x0, 0x0001},
-	{ "Cleanup 2", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
-	  CL_REG, 0x002,  3, 0x0, 0x0000},
-	{ "Drop packet", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
-	  IM_CTL, 0x080,  3, 0x0, 0xffff},
-	{ "No HTTP", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
-	  IM_CTL, 0x044,  3, 0x0, 0xffff},
-	{ NULL },
-};
-#ifdef HP_IP46TCP4NOHTTP_DEFAULT
-#define CAS_HP_FIRMWARE               cas_prog_ip46tcp4nohttptab
-#endif
-#endif
-
-/* match step #s for IP4FRAG */
-#define	S3_IPV6c	11
-#define	S3_TCP64	12
-#define	S3_TCPSQ	13
-#define	S3_TCPFG	14
-#define	S3_TCPHL	15
-#define	S3_TCPHc	16
-#define	S3_FRAG		17
-#define	S3_FOFF		18
-#define	S3_CLNP		19
-
-#ifdef USE_HP_IP4FRAG
-static cas_hp_inst_t cas_prog_ip4fragtab[] = {
-	{ "packet arrival?", 0xffff, 0x0000, OP_NP,  6, S1_VLAN,  0, S1_PCKT,
-	  CL_REG, 0x3ff, 1, 0x0, 0x0000},
-	{ "VLAN?", 0xffff, 0x8100, OP_EQ,  1, S1_CFI,   0, S1_8023,
-	  IM_CTL, 0x00a,  3, 0x0, 0xffff},
-	{ "CFI?", 0x1000, 0x1000, OP_EQ,  0, S3_CLNP,  1, S1_8023,
-	  CL_REG, 0x000,  0, 0x0, 0x0000},
-	{ "8023?", 0xffff, 0x0600, OP_LT,  1, S1_LLC,   0, S1_IPV4,
-	  CL_REG, 0x000,  0, 0x0, 0x0000},
-	{ "LLC?", 0xffff, 0xaaaa, OP_EQ,  1, S1_LLCc,  0, S3_CLNP,
-	  CL_REG, 0x000,  0, 0x0, 0x0000},
-	{ "LLCc?",0xff00, 0x0300, OP_EQ,  2, S1_IPV4,  0, S3_CLNP,
-	  CL_REG, 0x000,  0, 0x0, 0x0000},
-	{ "IPV4?", 0xffff, 0x0800, OP_EQ,  1, S1_IPV4c, 0, S1_IPV6,
-	  LD_SAP, 0x100,  3, 0x0, 0xffff},
-	{ "IPV4 cont?", 0xff00, 0x4500, OP_EQ,  3, S1_IPV4F, 0, S3_CLNP,
-	  LD_SUM, 0x00a,  1, 0x0, 0x0000},
-	{ "IPV4 frag?", 0x3fff, 0x0000, OP_EQ,  1, S1_TCP44, 0, S3_FRAG,
-	  LD_LEN, 0x03e,  3, 0x0, 0xffff},
-	{ "TCP44?", 0x00ff, 0x0006, OP_EQ,  7, S3_TCPSQ, 0, S3_CLNP,
-	  LD_FID, 0x182,  3, 0x0, 0xffff}, /* FID IP4&TCP src+dst */
-	{ "IPV6?", 0xffff, 0x86dd, OP_EQ,  1, S3_IPV6c, 0, S3_CLNP,
-	  LD_SUM, 0x015,  1, 0x0, 0x0000},
-	{ "IPV6 cont?", 0xf000, 0x6000, OP_EQ,  3, S3_TCP64, 0, S3_CLNP,
-	  LD_FID, 0x484,  1, 0x0, 0xffff}, /* FID IP6&TCP src+dst */
-	{ "TCP64?", 0xff00, 0x0600, OP_EQ, 18, S3_TCPSQ, 0, S3_CLNP,
-	  LD_LEN, 0x03f,  1, 0x0, 0xffff},
-	{ "TCP seq",	/* DADDR should point to dest port */
-	  0x0000, 0x0000, OP_EQ,  0, S3_TCPFG, 4, S3_TCPFG, LD_SEQ,
-	  0x081,  3, 0x0, 0xffff}, /* Load TCP seq # */
-	{ "TCP control flags", 0x0000, 0x0000, OP_EQ,  0, S3_TCPHL, 0,
-	  S3_TCPHL, ST_FLG, 0x045,  3, 0x0, 0x002f}, /* Load TCP flags */
-	{ "TCP length", 0x0000, 0x0000, OP_EQ,  0, S3_TCPHc, 0, S3_TCPHc,
-	  LD_R1,  0x205,  3, 0xB, 0xf000},
-	{ "TCP length cont", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
-	  LD_HDR, 0x0ff,  3, 0x0, 0xffff},
-	{ "IP4 Fragment", 0x0000, 0x0000, OP_EQ,  0, S3_FOFF,  0, S3_FOFF,
-	  LD_FID, 0x103,  3, 0x0, 0xffff}, /* FID IP4 src+dst */
-	{ "IP4 frag offset", 0x0000, 0x0000, OP_EQ,  0, S3_FOFF,  0, S3_FOFF,
-	  LD_SEQ, 0x040,  1, 0xD, 0xfff8},
-	{ "Cleanup", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
-	  IM_CTL, 0x001,  3, 0x0, 0x0001},
-	{ NULL },
-};
-#ifdef HP_IP4FRAG_DEFAULT
-#define CAS_HP_FIRMWARE               cas_prog_ip4fragtab
-#endif
-#endif
-
-/*
- * Alternate table which does batching without reassembly
- */
-#ifdef USE_HP_IP46TCP4BATCH
-static cas_hp_inst_t cas_prog_ip46tcp4batchtab[] = {
-	CAS_PROG_IP46TCP4_PREAMBLE,
-	{ "TCP seq",	/* DADDR should point to dest port */
-	  0x0000, 0x0000, OP_EQ,  0, S1_TCPFG, 0, S1_TCPFG, LD_SEQ,
-	  0x081,  3, 0x0, 0xffff}, /* Load TCP seq # */
-	{ "TCP control flags", 0x0000, 0x0000, OP_EQ,  0, S1_TCPHL, 0,
-	  S1_TCPHL, ST_FLG, 0x000,  3, 0x0, 0x0000}, /* Load TCP flags */
-	{ "TCP length", 0x0000, 0x0000, OP_EQ,  0, S1_TCPHc, 0,
-	  S1_TCPHc, LD_R1,  0x205,  3, 0xB, 0xf000},
-	{ "TCP length cont", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0,
-	  S1_PCKT,  IM_CTL, 0x040,  3, 0x0, 0xffff}, /* set batch bit */
-	{ "Cleanup", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
-	  IM_CTL, 0x001,  3, 0x0, 0x0001},
-	{ "Drop packet", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0,
-	  S1_PCKT,  IM_CTL, 0x080,  3, 0x0, 0xffff},
-	{ NULL },
-};
-#ifdef HP_IP46TCP4BATCH_DEFAULT
-#define CAS_HP_FIRMWARE               cas_prog_ip46tcp4batchtab
-#endif
-#endif
-
-/* Workaround for Cassini rev2 descriptor corruption problem.
- * Does batching without reassembly, and sets the SAP to a known
- * data pattern for all packets.
- */
-#ifdef USE_HP_WORKAROUND
-static cas_hp_inst_t  cas_prog_workaroundtab[] = {
-	{ "packet arrival?", 0xffff, 0x0000, OP_NP,  6, S1_VLAN,  0,
-	  S1_PCKT,  CL_REG, 0x3ff,  1, 0x0, 0x0000} ,
-	{ "VLAN?", 0xffff, 0x8100, OP_EQ,  1, S1_CFI, 0, S1_8023,
-	  IM_CTL, 0x04a,  3, 0x0, 0xffff},
-	{ "CFI?", 0x1000, 0x1000, OP_EQ,  0, S1_CLNP,  1, S1_8023,
-	  CL_REG, 0x000,  0, 0x0, 0x0000},
-	{ "8023?", 0xffff, 0x0600, OP_LT,  1, S1_LLC,   0, S1_IPV4,
-	  CL_REG, 0x000,  0, 0x0, 0x0000},
-	{ "LLC?", 0xffff, 0xaaaa, OP_EQ,  1, S1_LLCc,  0, S1_CLNP,
-	  CL_REG, 0x000,  0, 0x0, 0x0000},
-	{ "LLCc?", 0xff00, 0x0300, OP_EQ,  2, S1_IPV4,  0, S1_CLNP,
-	  CL_REG, 0x000,  0, 0x0, 0x0000},
-	{ "IPV4?", 0xffff, 0x0800, OP_EQ,  1, S1_IPV4c, 0, S1_IPV6,
-	  IM_SAP, 0x6AE,  3, 0x0, 0xffff},
-	{ "IPV4 cont?", 0xff00, 0x4500, OP_EQ,  3, S1_IPV4F, 0, S1_CLNP,
-	  LD_SUM, 0x00a,  1, 0x0, 0x0000},
-	{ "IPV4 frag?", 0x3fff, 0x0000, OP_EQ,  1, S1_TCP44, 0, S1_CLNP,
-	  LD_LEN, 0x03e,  1, 0x0, 0xffff},
-	{ "TCP44?", 0x00ff, 0x0006, OP_EQ,  7, S1_TCPSQ, 0, S1_CLNP,
-	  LD_FID, 0x182,  3, 0x0, 0xffff}, /* FID IP4&TCP src+dst */
-	{ "IPV6?", 0xffff, 0x86dd, OP_EQ,  1, S1_IPV6L, 0, S1_CLNP,
-	  LD_SUM, 0x015,  1, 0x0, 0x0000},
-	{ "IPV6 len", 0xf000, 0x6000, OP_EQ,  0, S1_IPV6c, 0, S1_CLNP,
-	  IM_R1,  0x128,  1, 0x0, 0xffff},
-	{ "IPV6 cont?", 0x0000, 0x0000, OP_EQ,  3, S1_TCP64, 0, S1_CLNP,
-	  LD_FID, 0x484,  1, 0x0, 0xffff}, /* FID IP6&TCP src+dst */
-	{ "TCP64?", 0xff00, 0x0600, OP_EQ, 18, S1_TCPSQ, 0, S1_CLNP,
-	  LD_LEN, 0x03f,  1, 0x0, 0xffff},
-	{ "TCP seq",      /* DADDR should point to dest port */
-	  0x0000, 0x0000, OP_EQ,  0, S1_TCPFG, 4, S1_TCPFG, LD_SEQ,
-	  0x081,  3, 0x0, 0xffff}, /* Load TCP seq # */
-	{ "TCP control flags", 0x0000, 0x0000, OP_EQ,  0, S1_TCPHL, 0,
-	  S1_TCPHL, ST_FLG, 0x045,  3, 0x0, 0x002f}, /* Load TCP flags */
-	{ "TCP length", 0x0000, 0x0000, OP_EQ,  0, S1_TCPHc, 0, S1_TCPHc,
-	  LD_R1,  0x205,  3, 0xB, 0xf000},
-	{ "TCP length cont", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0,
-	  S1_PCKT,  LD_HDR, 0x0ff,  3, 0x0, 0xffff},
-	{ "Cleanup", 0x0000, 0x0000, OP_EQ,  0, S1_CLNP2, 0, S1_CLNP2,
-	  IM_SAP, 0x6AE,  3, 0x0, 0xffff} ,
-	{ "Cleanup 2", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
-	  IM_CTL, 0x001,  3, 0x0, 0x0001},
-	{ NULL },
-};
-#ifdef HP_WORKAROUND_DEFAULT
-#define CAS_HP_FIRMWARE               cas_prog_workaroundtab
-#endif
-#endif
-
-#ifdef USE_HP_ENCRYPT
-static cas_hp_inst_t  cas_prog_encryptiontab[] = {
-	{ "packet arrival?", 0xffff, 0x0000, OP_NP,  6, S1_VLAN,  0,
-	  S1_PCKT,  CL_REG, 0x3ff,  1, 0x0, 0x0000},
-	{ "VLAN?", 0xffff, 0x8100, OP_EQ,  1, S1_CFI,   0, S1_8023,
-	  IM_CTL, 0x00a,  3, 0x0, 0xffff},
-#if 0
-//"CFI?", /* 02 FIND CFI and If FIND go to S1_DROP */
-//0x1000, 0x1000, OP_EQ,  0, S1_DROP,  1, S1_8023,  CL_REG, 0x000,  0, 0x0, 0x00
-	00,
-#endif
-	{ "CFI?", /* FIND CFI and If FIND go to CleanUP1 (ignore and send to host) */
-	  0x1000, 0x1000, OP_EQ,  0, S1_CLNP,  1, S1_8023,
-	  CL_REG, 0x000,  0, 0x0, 0x0000},
-	{ "8023?", 0xffff, 0x0600, OP_LT,  1, S1_LLC,   0, S1_IPV4,
-	  CL_REG, 0x000,  0, 0x0, 0x0000},
-	{ "LLC?", 0xffff, 0xaaaa, OP_EQ,  1, S1_LLCc,  0, S1_CLNP,
-	  CL_REG, 0x000,  0, 0x0, 0x0000},
-	{ "LLCc?", 0xff00, 0x0300, OP_EQ,  2, S1_IPV4,  0, S1_CLNP,
-	  CL_REG, 0x000,  0, 0x0, 0x0000},
-	{ "IPV4?", 0xffff, 0x0800, OP_EQ,  1, S1_IPV4c, 0, S1_IPV6,
-	  LD_SAP, 0x100,  3, 0x0, 0xffff},
-	{ "IPV4 cont?", 0xff00, 0x4500, OP_EQ,  3, S1_IPV4F, 0, S1_CLNP,
-	  LD_SUM, 0x00a,  1, 0x0, 0x0000},
-	{ "IPV4 frag?", 0x3fff, 0x0000, OP_EQ,  1, S1_TCP44, 0, S1_CLNP,
-	  LD_LEN, 0x03e,  1, 0x0, 0xffff},
-	{ "TCP44?", 0x00ff, 0x0006, OP_EQ,  7, S1_TCPSQ, 0, S1_ESP4,
-	  LD_FID, 0x182,  1, 0x0, 0xffff}, /* FID IP4&TCP src+dst */
-	{ "IPV6?", 0xffff, 0x86dd, OP_EQ,  1, S1_IPV6L, 0, S1_CLNP,
-	  LD_SUM, 0x015,  1, 0x0, 0x0000},
-	{ "IPV6 len", 0xf000, 0x6000, OP_EQ,  0, S1_IPV6c, 0, S1_CLNP,
-	  IM_R1,  0x128,  1, 0x0, 0xffff},
-	{ "IPV6 cont?", 0x0000, 0x0000, OP_EQ,  3, S1_TCP64, 0, S1_CLNP,
-	  LD_FID, 0x484,  1, 0x0, 0xffff}, /*  FID IP6&TCP src+dst */
-	{ "TCP64?",
-#if 0
-//@@@0xff00, 0x0600, OP_EQ, 18, S1_TCPSQ, 0, S1_ESP6,  LD_LEN, 0x03f,  1, 0x0, 0xffff,
-#endif
-	  0xff00, 0x0600, OP_EQ, 12, S1_TCPSQ, 0, S1_ESP6,  LD_LEN,
-	  0x03f,  1, 0x0, 0xffff},
-	{ "TCP seq", /* 14:DADDR should point to dest port */
-	  0xFFFF, 0x0080, OP_EQ,  0, S2_HTTP,  0, S1_TCPFG, LD_SEQ,
-	  0x081,  3, 0x0, 0xffff}, /* Load TCP seq # */
-	{ "TCP control flags", 0xFFFF, 0x8080, OP_EQ,  0, S2_HTTP,  0,
-	  S1_TCPHL, ST_FLG, 0x145,  2, 0x0, 0x002f}, /* Load TCP flags */
-	{ "TCP length", 0x0000, 0x0000, OP_EQ,  0, S1_TCPHc, 0, S1_TCPHc,
-	  LD_R1,  0x205,  3, 0xB, 0xf000} ,
-	{ "TCP length cont", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0,
-	  S1_PCKT,  LD_HDR, 0x0ff,  3, 0x0, 0xffff},
-	{ "Cleanup", 0x0000, 0x0000, OP_EQ,  0, S1_CLNP2,  0, S1_CLNP2,
-	  IM_CTL, 0x001,  3, 0x0, 0x0001},
-	{ "Cleanup 2", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
-	  CL_REG, 0x002,  3, 0x0, 0x0000},
-	{ "Drop packet", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
-	  IM_CTL, 0x080,  3, 0x0, 0xffff},
-	{ "No HTTP", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
-	  IM_CTL, 0x044,  3, 0x0, 0xffff},
-	{ "IPV4 ESP encrypted?",  /* S1_ESP4 */
-	  0x00ff, 0x0032, OP_EQ,  0, S1_CLNP2, 0, S1_AH4, IM_CTL,
-	  0x021, 1,  0x0, 0xffff},
-	{ "IPV4 AH encrypted?",   /* S1_AH4 */
-	  0x00ff, 0x0033, OP_EQ,  0, S1_CLNP2, 0, S1_CLNP, IM_CTL,
-	  0x021, 1,  0x0, 0xffff},
-	{ "IPV6 ESP encrypted?",  /* S1_ESP6 */
-#if 0
-//@@@0x00ff, 0x0032, OP_EQ,  0, S1_CLNP2, 0, S1_AH6, IM_CTL, 0x021, 1,  0x0, 0xffff,
-#endif
-	  0xff00, 0x3200, OP_EQ,  0, S1_CLNP2, 0, S1_AH6, IM_CTL,
-	  0x021, 1,  0x0, 0xffff},
-	{ "IPV6 AH encrypted?",   /* S1_AH6 */
-#if 0
-//@@@0x00ff, 0x0033, OP_EQ,  0, S1_CLNP2, 0, S1_CLNP, IM_CTL, 0x021, 1,  0x0, 0xffff,
-#endif
-	  0xff00, 0x3300, OP_EQ,  0, S1_CLNP2, 0, S1_CLNP, IM_CTL,
-	  0x021, 1,  0x0, 0xffff},
-	{ NULL },
-};
-#ifdef HP_ENCRYPT_DEFAULT
-#define CAS_HP_FIRMWARE               cas_prog_encryptiontab
-#endif
-#endif
-
-static cas_hp_inst_t cas_prog_null[] = { {NULL} };
-#ifdef HP_NULL_DEFAULT
-#define CAS_HP_FIRMWARE               cas_prog_null
-#endif
-
-/* phy types */
-#define   CAS_PHY_UNKNOWN       0x00
-#define   CAS_PHY_SERDES        0x01
-#define   CAS_PHY_MII_MDIO0     0x02
-#define   CAS_PHY_MII_MDIO1     0x04
-#define   CAS_PHY_MII(x)        ((x) & (CAS_PHY_MII_MDIO0 | CAS_PHY_MII_MDIO1))
-
-/* _RING_INDEX is the index for the ring sizes to be used.  _RING_SIZE
- * is the actual size. the default index for the various rings is
- * 8. NOTE: there a bunch of alignment constraints for the rings. to
- * deal with that, i just allocate rings to create the desired
- * alignment. here are the constraints:
- *   RX DESC and COMP rings must be 8KB aligned
- *   TX DESC must be 2KB aligned.
- * if you change the numbers, be cognizant of how the alignment will change
- * in INIT_BLOCK as well.
- */
-
-#define DESC_RING_I_TO_S(x)  (32*(1 << (x)))
-#define COMP_RING_I_TO_S(x)  (128*(1 << (x)))
-#define TX_DESC_RING_INDEX 4  /* 512 = 8k */
-#define RX_DESC_RING_INDEX 4  /* 512 = 8k */
-#define RX_COMP_RING_INDEX 4  /* 2048 = 64k: should be 4x rx ring size */
-
-#if (TX_DESC_RING_INDEX > 8) || (TX_DESC_RING_INDEX < 0)
-#error TX_DESC_RING_INDEX must be between 0 and 8
-#endif
-
-#if (RX_DESC_RING_INDEX > 8) || (RX_DESC_RING_INDEX < 0)
-#error RX_DESC_RING_INDEX must be between 0 and 8
-#endif
-
-#if (RX_COMP_RING_INDEX > 8) || (RX_COMP_RING_INDEX < 0)
-#error RX_COMP_RING_INDEX must be between 0 and 8
-#endif
-
-#define N_TX_RINGS                    MAX_TX_RINGS      /* for QoS */
-#define N_TX_RINGS_MASK               MAX_TX_RINGS_MASK
-#define N_RX_DESC_RINGS               MAX_RX_DESC_RINGS /* 1 for ipsec */
-#define N_RX_COMP_RINGS               0x1 /* for mult. PCI interrupts */
-
-/* number of flows that can go through re-assembly */
-#define N_RX_FLOWS                    64
-
-#define TX_DESC_RING_SIZE  DESC_RING_I_TO_S(TX_DESC_RING_INDEX)
-#define RX_DESC_RING_SIZE  DESC_RING_I_TO_S(RX_DESC_RING_INDEX)
-#define RX_COMP_RING_SIZE  COMP_RING_I_TO_S(RX_COMP_RING_INDEX)
-#define TX_DESC_RINGN_INDEX(x) TX_DESC_RING_INDEX
-#define RX_DESC_RINGN_INDEX(x) RX_DESC_RING_INDEX
-#define RX_COMP_RINGN_INDEX(x) RX_COMP_RING_INDEX
-#define TX_DESC_RINGN_SIZE(x)  TX_DESC_RING_SIZE
-#define RX_DESC_RINGN_SIZE(x)  RX_DESC_RING_SIZE
-#define RX_COMP_RINGN_SIZE(x)  RX_COMP_RING_SIZE
-
-/* convert values */
-#define CAS_BASE(x, y)                (((y) << (x ## _SHIFT)) & (x ## _MASK))
-#define CAS_VAL(x, y)                 (((y) & (x ## _MASK)) >> (x ## _SHIFT))
-#define CAS_TX_RINGN_BASE(y)          ((TX_DESC_RINGN_INDEX(y) << \
-                                        TX_CFG_DESC_RINGN_SHIFT(y)) & \
-                                        TX_CFG_DESC_RINGN_MASK(y))
-
-/* min is 2k, but we can't do jumbo frames unless it's at least 8k */
-#define CAS_MIN_PAGE_SHIFT            11 /* 2048 */
-#define CAS_JUMBO_PAGE_SHIFT          13 /* 8192 */
-#define CAS_MAX_PAGE_SHIFT            14 /* 16384 */
-
-#define TX_DESC_BUFLEN_MASK         0x0000000000003FFFULL /* buffer length in
-							     bytes. 0 - 9256 */
-#define TX_DESC_BUFLEN_SHIFT        0
-#define TX_DESC_CSUM_START_MASK     0x00000000001F8000ULL /* checksum start. #
-							     of bytes to be
-							     skipped before
-							     csum calc begins.
-							     value must be
-							     even */
-#define TX_DESC_CSUM_START_SHIFT    15
-#define TX_DESC_CSUM_STUFF_MASK     0x000000001FE00000ULL /* checksum stuff.
-							     byte offset w/in
-							     the pkt for the
-							     1st csum byte.
-							     must be > 8 */
-#define TX_DESC_CSUM_STUFF_SHIFT    21
-#define TX_DESC_CSUM_EN             0x0000000020000000ULL /* enable checksum */
-#define TX_DESC_EOF                 0x0000000040000000ULL /* end of frame */
-#define TX_DESC_SOF                 0x0000000080000000ULL /* start of frame */
-#define TX_DESC_INTME               0x0000000100000000ULL /* interrupt me */
-#define TX_DESC_NO_CRC              0x0000000200000000ULL /* debugging only.
-							     CRC will not be
-							     inserted into
-							     outgoing frame. */
-struct cas_tx_desc {
-	__le64     control;
-	__le64     buffer;
-};
-
-/* descriptor ring for free buffers contains page-sized buffers. the index
- * value is not used by the hw in any way. it's just stored and returned in
- * the completion ring.
- */
-struct cas_rx_desc {
-	__le64     index;
-	__le64     buffer;
-};
-
-/* received packets are put on the completion ring. */
-/* word 1 */
-#define RX_COMP1_DATA_SIZE_MASK           0x0000000007FFE000ULL
-#define RX_COMP1_DATA_SIZE_SHIFT          13
-#define RX_COMP1_DATA_OFF_MASK            0x000001FFF8000000ULL
-#define RX_COMP1_DATA_OFF_SHIFT           27
-#define RX_COMP1_DATA_INDEX_MASK          0x007FFE0000000000ULL
-#define RX_COMP1_DATA_INDEX_SHIFT         41
-#define RX_COMP1_SKIP_MASK                0x0180000000000000ULL
-#define RX_COMP1_SKIP_SHIFT               55
-#define RX_COMP1_RELEASE_NEXT             0x0200000000000000ULL
-#define RX_COMP1_SPLIT_PKT                0x0400000000000000ULL
-#define RX_COMP1_RELEASE_FLOW             0x0800000000000000ULL
-#define RX_COMP1_RELEASE_DATA             0x1000000000000000ULL
-#define RX_COMP1_RELEASE_HDR              0x2000000000000000ULL
-#define RX_COMP1_TYPE_MASK                0xC000000000000000ULL
-#define RX_COMP1_TYPE_SHIFT               62
-
-/* word 2 */
-#define RX_COMP2_NEXT_INDEX_MASK          0x00000007FFE00000ULL
-#define RX_COMP2_NEXT_INDEX_SHIFT         21
-#define RX_COMP2_HDR_SIZE_MASK            0x00000FF800000000ULL
-#define RX_COMP2_HDR_SIZE_SHIFT           35
-#define RX_COMP2_HDR_OFF_MASK             0x0003F00000000000ULL
-#define RX_COMP2_HDR_OFF_SHIFT            44
-#define RX_COMP2_HDR_INDEX_MASK           0xFFFC000000000000ULL
-#define RX_COMP2_HDR_INDEX_SHIFT          50
-
-/* word 3 */
-#define RX_COMP3_SMALL_PKT                0x0000000000000001ULL
-#define RX_COMP3_JUMBO_PKT                0x0000000000000002ULL
-#define RX_COMP3_JUMBO_HDR_SPLIT_EN       0x0000000000000004ULL
-#define RX_COMP3_CSUM_START_MASK          0x000000000007F000ULL
-#define RX_COMP3_CSUM_START_SHIFT         12
-#define RX_COMP3_FLOWID_MASK              0x0000000001F80000ULL
-#define RX_COMP3_FLOWID_SHIFT             19
-#define RX_COMP3_OPCODE_MASK              0x000000000E000000ULL
-#define RX_COMP3_OPCODE_SHIFT             25
-#define RX_COMP3_FORCE_FLAG               0x0000000010000000ULL
-#define RX_COMP3_NO_ASSIST                0x0000000020000000ULL
-#define RX_COMP3_LOAD_BAL_MASK            0x000001F800000000ULL
-#define RX_COMP3_LOAD_BAL_SHIFT           35
-#define RX_PLUS_COMP3_ENC_PKT             0x0000020000000000ULL /* cas+ */
-#define RX_COMP3_L3_HEAD_OFF_MASK         0x0000FE0000000000ULL /* cas */
-#define RX_COMP3_L3_HEAD_OFF_SHIFT        41
-#define RX_PLUS_COMP_L3_HEAD_OFF_MASK     0x0000FC0000000000ULL /* cas+ */
-#define RX_PLUS_COMP_L3_HEAD_OFF_SHIFT    42
-#define RX_COMP3_SAP_MASK                 0xFFFF000000000000ULL
-#define RX_COMP3_SAP_SHIFT                48
-
-/* word 4 */
-#define RX_COMP4_TCP_CSUM_MASK            0x000000000000FFFFULL
-#define RX_COMP4_TCP_CSUM_SHIFT           0
-#define RX_COMP4_PKT_LEN_MASK             0x000000003FFF0000ULL
-#define RX_COMP4_PKT_LEN_SHIFT            16
-#define RX_COMP4_PERFECT_MATCH_MASK       0x00000003C0000000ULL
-#define RX_COMP4_PERFECT_MATCH_SHIFT      30
-#define RX_COMP4_ZERO                     0x0000080000000000ULL
-#define RX_COMP4_HASH_VAL_MASK            0x0FFFF00000000000ULL
-#define RX_COMP4_HASH_VAL_SHIFT           44
-#define RX_COMP4_HASH_PASS                0x1000000000000000ULL
-#define RX_COMP4_BAD                      0x4000000000000000ULL
-#define RX_COMP4_LEN_MISMATCH             0x8000000000000000ULL
-
-/* we encode the following: ring/index/release. only 14 bits
- * are usable.
- * NOTE: the encoding is dependent upon RX_DESC_RING_SIZE and
- *       MAX_RX_DESC_RINGS. */
-#define RX_INDEX_NUM_MASK                 0x0000000000000FFFULL
-#define RX_INDEX_NUM_SHIFT                0
-#define RX_INDEX_RING_MASK                0x0000000000001000ULL
-#define RX_INDEX_RING_SHIFT               12
-#define RX_INDEX_RELEASE                  0x0000000000002000ULL
-
-struct cas_rx_comp {
-	__le64     word1;
-	__le64     word2;
-	__le64     word3;
-	__le64     word4;
-};
-
-enum link_state {
-	link_down = 0,	/* No link, will retry */
-	link_aneg,	/* Autoneg in progress */
-	link_force_try,	/* Try Forced link speed */
-	link_force_ret,	/* Forced mode worked, retrying autoneg */
-	link_force_ok,	/* Stay in forced mode */
-	link_up		/* Link is up */
-};
-
-typedef struct cas_page {
-	struct list_head list;
-	struct page *buffer;
-	dma_addr_t dma_addr;
-	int used;
-} cas_page_t;
-
-
-/* some alignment constraints:
- * TX DESC, RX DESC, and RX COMP must each be 8K aligned.
- * TX COMPWB must be 8-byte aligned.
- * to accomplish this, here's what we do:
- *
- * INIT_BLOCK_RX_COMP  = 64k (already aligned)
- * INIT_BLOCK_RX_DESC  = 8k
- * INIT_BLOCK_TX       = 8k
- * INIT_BLOCK_RX1_DESC = 8k
- * TX COMPWB
- */
-#define INIT_BLOCK_TX           (TX_DESC_RING_SIZE)
-#define INIT_BLOCK_RX_DESC      (RX_DESC_RING_SIZE)
-#define INIT_BLOCK_RX_COMP      (RX_COMP_RING_SIZE)
-
-struct cas_init_block {
-	struct cas_rx_comp rxcs[N_RX_COMP_RINGS][INIT_BLOCK_RX_COMP];
-	struct cas_rx_desc rxds[N_RX_DESC_RINGS][INIT_BLOCK_RX_DESC];
-	struct cas_tx_desc txds[N_TX_RINGS][INIT_BLOCK_TX];
-	__le64 tx_compwb;
-};
-
-/* tiny buffers to deal with target abort issue. we allocate a bit
- * over so that we don't have target abort issues with these buffers
- * as well.
- */
-#define TX_TINY_BUF_LEN    0x100
-#define TX_TINY_BUF_BLOCK  ((INIT_BLOCK_TX + 1)*TX_TINY_BUF_LEN)
-
-struct cas_tiny_count {
-	int nbufs;
-	int used;
-};
-
-struct cas {
-	spinlock_t lock; /* for most bits */
-	spinlock_t tx_lock[N_TX_RINGS]; /* tx bits */
-	spinlock_t stat_lock[N_TX_RINGS + 1]; /* for stat gathering */
-	spinlock_t rx_inuse_lock; /* rx inuse list */
-	spinlock_t rx_spare_lock; /* rx spare list */
-
-	void __iomem *regs;
-	int tx_new[N_TX_RINGS], tx_old[N_TX_RINGS];
-	int rx_old[N_RX_DESC_RINGS];
-	int rx_cur[N_RX_COMP_RINGS], rx_new[N_RX_COMP_RINGS];
-	int rx_last[N_RX_DESC_RINGS];
-
-	struct napi_struct napi;
-
-	/* Set when chip is actually in operational state
-	 * (ie. not power managed) */
-	int hw_running;
-	int opened;
-	struct mutex pm_mutex; /* open/close/suspend/resume */
-
-	struct cas_init_block *init_block;
-	struct cas_tx_desc *init_txds[MAX_TX_RINGS];
-	struct cas_rx_desc *init_rxds[MAX_RX_DESC_RINGS];
-	struct cas_rx_comp *init_rxcs[MAX_RX_COMP_RINGS];
-
-	/* we use sk_buffs for tx and pages for rx. the rx skbuffs
-	 * are there for flow re-assembly. */
-	struct sk_buff      *tx_skbs[N_TX_RINGS][TX_DESC_RING_SIZE];
-	struct sk_buff_head  rx_flows[N_RX_FLOWS];
-	cas_page_t          *rx_pages[N_RX_DESC_RINGS][RX_DESC_RING_SIZE];
-	struct list_head     rx_spare_list, rx_inuse_list;
-	int                  rx_spares_needed;
-
-	/* for small packets when copying would be quicker than
-	   mapping */
-	struct cas_tiny_count tx_tiny_use[N_TX_RINGS][TX_DESC_RING_SIZE];
-	u8 *tx_tiny_bufs[N_TX_RINGS];
-
-	u32			msg_enable;
-
-	/* N_TX_RINGS must be >= N_RX_DESC_RINGS */
-	struct net_device_stats net_stats[N_TX_RINGS + 1];
-
-	u32			pci_cfg[64 >> 2];
-	u8                      pci_revision;
-
-	int                     phy_type;
-	int			phy_addr;
-	u32                     phy_id;
-#define CAS_FLAG_1000MB_CAP     0x00000001
-#define CAS_FLAG_REG_PLUS       0x00000002
-#define CAS_FLAG_TARGET_ABORT   0x00000004
-#define CAS_FLAG_SATURN         0x00000008
-#define CAS_FLAG_RXD_POST_MASK  0x000000F0
-#define CAS_FLAG_RXD_POST_SHIFT 4
-#define CAS_FLAG_RXD_POST(x)    ((1 << (CAS_FLAG_RXD_POST_SHIFT + (x))) & \
-                                 CAS_FLAG_RXD_POST_MASK)
-#define CAS_FLAG_ENTROPY_DEV    0x00000100
-#define CAS_FLAG_NO_HW_CSUM     0x00000200
-	u32                     cas_flags;
-	int                     packet_min; /* minimum packet size */
-	int			tx_fifo_size;
-	int			rx_fifo_size;
-	int			rx_pause_off;
-	int			rx_pause_on;
-	int                     crc_size;      /* 4 if half-duplex */
-
-	int                     pci_irq_INTC;
-	int                     min_frame_size; /* for tx fifo workaround */
-
-	/* page size allocation */
-	int                     page_size;
-	int                     page_order;
-	int                     mtu_stride;
-
-	u32			mac_rx_cfg;
-
-	/* Autoneg & PHY control */
-	int			link_cntl;
-	int			link_fcntl;
-	enum link_state		lstate;
-	struct timer_list	link_timer;
-	int			timer_ticks;
-	struct work_struct	reset_task;
-#if 0
-	atomic_t		reset_task_pending;
-#else
-	atomic_t		reset_task_pending;
-	atomic_t		reset_task_pending_mtu;
-	atomic_t		reset_task_pending_spare;
-	atomic_t		reset_task_pending_all;
-#endif
-
-	/* Link-down problem workaround */
-#define LINK_TRANSITION_UNKNOWN 	0
-#define LINK_TRANSITION_ON_FAILURE 	1
-#define LINK_TRANSITION_STILL_FAILED 	2
-#define LINK_TRANSITION_LINK_UP 	3
-#define LINK_TRANSITION_LINK_CONFIG	4
-#define LINK_TRANSITION_LINK_DOWN	5
-#define LINK_TRANSITION_REQUESTED_RESET	6
-	int			link_transition;
-	int 			link_transition_jiffies_valid;
-	unsigned long		link_transition_jiffies;
-
-	/* Tuning */
-	u8 orig_cacheline_size;	/* value when loaded */
-#define CAS_PREF_CACHELINE_SIZE	 0x20	/* Minimum desired */
-
-	/* Diagnostic counters and state. */
-	int 			casreg_len; /* reg-space size for dumping */
-	u64			pause_entered;
-	u16			pause_last_time_recvd;
-
-	dma_addr_t block_dvma, tx_tiny_dvma[N_TX_RINGS];
-	struct pci_dev *pdev;
-	struct net_device *dev;
-#if defined(CONFIG_OF)
-	struct device_node	*of_node;
-#endif
-
-	/* Firmware Info */
-	u16			fw_load_addr;
-	u32			fw_size;
-	u8			*fw_data;
-};
-
-#define TX_DESC_NEXT(r, x)  (((x) + 1) & (TX_DESC_RINGN_SIZE(r) - 1))
-#define RX_DESC_ENTRY(r, x) ((x) & (RX_DESC_RINGN_SIZE(r) - 1))
-#define RX_COMP_ENTRY(r, x) ((x) & (RX_COMP_RINGN_SIZE(r) - 1))
-
-#define TX_BUFF_COUNT(r, x, y)    ((x) <= (y) ? ((y) - (x)) : \
-        (TX_DESC_RINGN_SIZE(r) - (x) + (y)))
-
-#define TX_BUFFS_AVAIL(cp, i)	((cp)->tx_old[(i)] <= (cp)->tx_new[(i)] ? \
-        (cp)->tx_old[(i)] + (TX_DESC_RINGN_SIZE(i) - 1) - (cp)->tx_new[(i)] : \
-        (cp)->tx_old[(i)] - (cp)->tx_new[(i)] - 1)
-
-#define CAS_ALIGN(addr, align) \
-     (((unsigned long) (addr) + ((align) - 1UL)) & ~((align) - 1))
-
-#define RX_FIFO_SIZE                  16384
-#define EXPANSION_ROM_SIZE            65536
-
-#define CAS_MC_EXACT_MATCH_SIZE       15
-#define CAS_MC_HASH_SIZE              256
-#define CAS_MC_HASH_MAX              (CAS_MC_EXACT_MATCH_SIZE + \
-                                      CAS_MC_HASH_SIZE)
-
-#define TX_TARGET_ABORT_LEN           0x20
-#define RX_SWIVEL_OFF_VAL             0x2
-#define RX_AE_FREEN_VAL(x)            (RX_DESC_RINGN_SIZE(x) >> 1)
-#define RX_AE_COMP_VAL                (RX_COMP_RING_SIZE >> 1)
-#define RX_BLANK_INTR_PKT_VAL         0x05
-#define RX_BLANK_INTR_TIME_VAL        0x0F
-#define HP_TCP_THRESH_VAL             1530 /* reduce to enable reassembly */
-
-#define RX_SPARE_COUNT                (RX_DESC_RING_SIZE >> 1)
-#define RX_SPARE_RECOVER_VAL          (RX_SPARE_COUNT >> 2)
-
-#endif /* _CASSINI_H */
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/common.h linux-libre-3.2-gnu/drivers/net/chelsio/common.h
--- linux-libre-3.1-gnu/drivers/net/chelsio/common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/common.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,353 +0,0 @@
-/*****************************************************************************
- *                                                                           *
- * File: common.h                                                            *
- * $Revision: 1.21 $                                                         *
- * $Date: 2005/06/22 00:43:25 $                                              *
- * Description:                                                              *
- *  part of the Chelsio 10Gb Ethernet 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.                                *
- *                                                                           *
- * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
- *                                                                           *
- * http://www.chelsio.com                                                    *
- *                                                                           *
- * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
- * All rights reserved.                                                      *
- *                                                                           *
- * Maintainers: maintainers@chelsio.com                                      *
- *                                                                           *
- * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
- *          Tina Yang               <tainay@chelsio.com>                     *
- *          Felix Marti             <felix@chelsio.com>                      *
- *          Scott Bardone           <sbardone@chelsio.com>                   *
- *          Kurt Ottaway            <kottaway@chelsio.com>                   *
- *          Frank DiMambro          <frank@chelsio.com>                      *
- *                                                                           *
- * History:                                                                  *
- *                                                                           *
- ****************************************************************************/
-
-#define pr_fmt(fmt) "cxgb: " fmt
-
-#ifndef _CXGB_COMMON_H_
-#define _CXGB_COMMON_H_
-
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/ethtool.h>
-#include <linux/if_vlan.h>
-#include <linux/mdio.h>
-#include <linux/crc32.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-#include <linux/pci_ids.h>
-
-#define DRV_DESCRIPTION "Chelsio 10Gb Ethernet Driver"
-#define DRV_NAME "cxgb"
-#define DRV_VERSION "2.2"
-
-#define CH_DEVICE(devid, ssid, idx) \
-	{ PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, ssid, 0, 0, idx }
-
-#define SUPPORTED_PAUSE       (1 << 13)
-#define SUPPORTED_LOOPBACK    (1 << 15)
-
-#define ADVERTISED_PAUSE      (1 << 13)
-#define ADVERTISED_ASYM_PAUSE (1 << 14)
-
-typedef struct adapter adapter_t;
-
-struct t1_rx_mode {
-       struct net_device *dev;
-};
-
-#define t1_rx_mode_promisc(rm)	(rm->dev->flags & IFF_PROMISC)
-#define t1_rx_mode_allmulti(rm)	(rm->dev->flags & IFF_ALLMULTI)
-#define t1_rx_mode_mc_cnt(rm)	(netdev_mc_count(rm->dev))
-#define t1_get_netdev(rm)	(rm->dev)
-
-#define	MAX_NPORTS 4
-#define PORT_MASK ((1 << MAX_NPORTS) - 1)
-#define NMTUS      8
-#define TCB_SIZE   128
-
-#define SPEED_INVALID 0xffff
-#define DUPLEX_INVALID 0xff
-
-enum {
-	CHBT_BOARD_N110,
-	CHBT_BOARD_N210,
-	CHBT_BOARD_7500,
-	CHBT_BOARD_8000,
-	CHBT_BOARD_CHT101,
-	CHBT_BOARD_CHT110,
-	CHBT_BOARD_CHT210,
-	CHBT_BOARD_CHT204,
-	CHBT_BOARD_CHT204V,
-	CHBT_BOARD_CHT204E,
-	CHBT_BOARD_CHN204,
-	CHBT_BOARD_COUGAR,
-	CHBT_BOARD_6800,
-	CHBT_BOARD_SIMUL,
-};
-
-enum {
-	CHBT_TERM_FPGA,
-	CHBT_TERM_T1,
-	CHBT_TERM_T2,
-	CHBT_TERM_T3
-};
-
-enum {
-	CHBT_MAC_CHELSIO_A,
-	CHBT_MAC_IXF1010,
-	CHBT_MAC_PM3393,
-	CHBT_MAC_VSC7321,
-	CHBT_MAC_DUMMY
-};
-
-enum {
-	CHBT_PHY_88E1041,
-	CHBT_PHY_88E1111,
-	CHBT_PHY_88X2010,
-	CHBT_PHY_XPAK,
-	CHBT_PHY_MY3126,
-	CHBT_PHY_8244,
-	CHBT_PHY_DUMMY
-};
-
-enum {
-	PAUSE_RX      = 1 << 0,
-	PAUSE_TX      = 1 << 1,
-	PAUSE_AUTONEG = 1 << 2
-};
-
-/* Revisions of T1 chip */
-enum {
-	TERM_T1A   = 0,
-	TERM_T1B   = 1,
-	TERM_T2    = 3
-};
-
-struct sge_params {
-	unsigned int cmdQ_size[2];
-	unsigned int freelQ_size[2];
-	unsigned int large_buf_capacity;
-	unsigned int rx_coalesce_usecs;
-	unsigned int last_rx_coalesce_raw;
-	unsigned int default_rx_coalesce_usecs;
-	unsigned int sample_interval_usecs;
-	unsigned int coalesce_enable;
-	unsigned int polling;
-};
-
-struct chelsio_pci_params {
-	unsigned short speed;
-	unsigned char  width;
-	unsigned char  is_pcix;
-};
-
-struct tp_params {
-	unsigned int pm_size;
-	unsigned int cm_size;
-	unsigned int pm_rx_base;
-	unsigned int pm_tx_base;
-	unsigned int pm_rx_pg_size;
-	unsigned int pm_tx_pg_size;
-	unsigned int pm_rx_num_pgs;
-	unsigned int pm_tx_num_pgs;
-	unsigned int rx_coalescing_size;
-	unsigned int use_5tuple_mode;
-};
-
-struct mc5_params {
-	unsigned int mode;       /* selects MC5 width */
-	unsigned int nservers;   /* size of server region */
-	unsigned int nroutes;    /* size of routing region */
-};
-
-/* Default MC5 region sizes */
-#define DEFAULT_SERVER_REGION_LEN 256
-#define DEFAULT_RT_REGION_LEN 1024
-
-struct adapter_params {
-	struct sge_params sge;
-	struct mc5_params mc5;
-	struct tp_params  tp;
-	struct chelsio_pci_params pci;
-
-	const struct board_info *brd_info;
-
-	unsigned short mtus[NMTUS];
-	unsigned int   nports;          /* # of ethernet ports */
-	unsigned int   stats_update_period;
-	unsigned short chip_revision;
-	unsigned char  chip_version;
-	unsigned char  is_asic;
-	unsigned char  has_msi;
-};
-
-struct link_config {
-	unsigned int   supported;        /* link capabilities */
-	unsigned int   advertising;      /* advertised capabilities */
-	unsigned short requested_speed;  /* speed user has requested */
-	unsigned short speed;            /* actual link speed */
-	unsigned char  requested_duplex; /* duplex user has requested */
-	unsigned char  duplex;           /* actual link duplex */
-	unsigned char  requested_fc;     /* flow control user has requested */
-	unsigned char  fc;               /* actual link flow control */
-	unsigned char  autoneg;          /* autonegotiating? */
-};
-
-struct cmac;
-struct cphy;
-
-struct port_info {
-	struct net_device *dev;
-	struct cmac *mac;
-	struct cphy *phy;
-	struct link_config link_config;
-	struct net_device_stats netstats;
-};
-
-struct sge;
-struct peespi;
-
-struct adapter {
-	u8 __iomem *regs;
-	struct pci_dev *pdev;
-	unsigned long registered_device_map;
-	unsigned long open_device_map;
-	unsigned long flags;
-
-	const char *name;
-	int msg_enable;
-	u32 mmio_len;
-
-	struct work_struct ext_intr_handler_task;
-	struct adapter_params params;
-
-	/* Terminator modules. */
-	struct sge    *sge;
-	struct peespi *espi;
-	struct petp   *tp;
-
-	struct napi_struct napi;
-	struct port_info port[MAX_NPORTS];
-	struct delayed_work stats_update_task;
-	struct timer_list stats_update_timer;
-
-	spinlock_t tpi_lock;
-	spinlock_t work_lock;
-	spinlock_t mac_lock;
-
-	/* guards async operations */
-	spinlock_t async_lock ____cacheline_aligned;
-	u32 slow_intr_mask;
-	int t1powersave;
-};
-
-enum {                                           /* adapter flags */
-	FULL_INIT_DONE        = 1 << 0,
-};
-
-struct mdio_ops;
-struct gmac;
-struct gphy;
-
-struct board_info {
-	unsigned char           board;
-	unsigned char           port_number;
-	unsigned long           caps;
-	unsigned char           chip_term;
-	unsigned char           chip_mac;
-	unsigned char           chip_phy;
-	unsigned int            clock_core;
-	unsigned int            clock_mc3;
-	unsigned int            clock_mc4;
-	unsigned int            espi_nports;
-	unsigned int            clock_elmer0;
-	unsigned char           mdio_mdien;
-	unsigned char           mdio_mdiinv;
-	unsigned char           mdio_mdc;
-	unsigned char           mdio_phybaseaddr;
-	const struct gmac      *gmac;
-	const struct gphy      *gphy;
-	const struct mdio_ops  *mdio_ops;
-	const char             *desc;
-};
-
-static inline int t1_is_asic(const adapter_t *adapter)
-{
-	return adapter->params.is_asic;
-}
-
-extern const struct pci_device_id t1_pci_tbl[];
-
-static inline int adapter_matches_type(const adapter_t *adapter,
-				       int version, int revision)
-{
-	return adapter->params.chip_version == version &&
-	       adapter->params.chip_revision == revision;
-}
-
-#define t1_is_T1B(adap) adapter_matches_type(adap, CHBT_TERM_T1, TERM_T1B)
-#define is_T2(adap)     adapter_matches_type(adap, CHBT_TERM_T2, TERM_T2)
-
-/* Returns true if an adapter supports VLAN acceleration and TSO */
-static inline int vlan_tso_capable(const adapter_t *adapter)
-{
-	return !t1_is_T1B(adapter);
-}
-
-#define for_each_port(adapter, iter) \
-	for (iter = 0; iter < (adapter)->params.nports; ++iter)
-
-#define board_info(adapter) ((adapter)->params.brd_info)
-#define is_10G(adapter) (board_info(adapter)->caps & SUPPORTED_10000baseT_Full)
-
-static inline unsigned int core_ticks_per_usec(const adapter_t *adap)
-{
-	return board_info(adap)->clock_core / 1000000;
-}
-
-extern int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp);
-extern int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value);
-extern int t1_tpi_write(adapter_t *adapter, u32 addr, u32 value);
-extern int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *value);
-
-extern void t1_interrupts_enable(adapter_t *adapter);
-extern void t1_interrupts_disable(adapter_t *adapter);
-extern void t1_interrupts_clear(adapter_t *adapter);
-extern int t1_elmer0_ext_intr_handler(adapter_t *adapter);
-extern void t1_elmer0_ext_intr(adapter_t *adapter);
-extern int t1_slow_intr_handler(adapter_t *adapter);
-
-extern int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc);
-extern const struct board_info *t1_get_board_info(unsigned int board_id);
-extern const struct board_info *t1_get_board_info_from_ids(unsigned int devid,
-						    unsigned short ssid);
-extern int t1_seeprom_read(adapter_t *adapter, u32 addr, __le32 *data);
-extern int t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
-		     struct adapter_params *p);
-extern int t1_init_hw_modules(adapter_t *adapter);
-extern int t1_init_sw_modules(adapter_t *adapter, const struct board_info *bi);
-extern void t1_free_sw_modules(adapter_t *adapter);
-extern void t1_fatal_err(adapter_t *adapter);
-extern void t1_link_changed(adapter_t *adapter, int port_id);
-extern void t1_link_negotiated(adapter_t *adapter, int port_id, int link_stat,
-			    int speed, int duplex, int pause);
-#endif /* _CXGB_COMMON_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/cphy.h linux-libre-3.2-gnu/drivers/net/chelsio/cphy.h
--- linux-libre-3.1-gnu/drivers/net/chelsio/cphy.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/cphy.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,175 +0,0 @@
-/*****************************************************************************
- *                                                                           *
- * File: cphy.h                                                              *
- * $Revision: 1.7 $                                                          *
- * $Date: 2005/06/21 18:29:47 $                                              *
- * Description:                                                              *
- *  part of the Chelsio 10Gb Ethernet 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.                                *
- *                                                                           *
- * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
- *                                                                           *
- * http://www.chelsio.com                                                    *
- *                                                                           *
- * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
- * All rights reserved.                                                      *
- *                                                                           *
- * Maintainers: maintainers@chelsio.com                                      *
- *                                                                           *
- * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
- *          Tina Yang               <tainay@chelsio.com>                     *
- *          Felix Marti             <felix@chelsio.com>                      *
- *          Scott Bardone           <sbardone@chelsio.com>                   *
- *          Kurt Ottaway            <kottaway@chelsio.com>                   *
- *          Frank DiMambro          <frank@chelsio.com>                      *
- *                                                                           *
- * History:                                                                  *
- *                                                                           *
- ****************************************************************************/
-
-#ifndef _CXGB_CPHY_H_
-#define _CXGB_CPHY_H_
-
-#include "common.h"
-
-struct mdio_ops {
-	void (*init)(adapter_t *adapter, const struct board_info *bi);
-	int  (*read)(struct net_device *dev, int phy_addr, int mmd_addr,
-		     u16 reg_addr);
-	int  (*write)(struct net_device *dev, int phy_addr, int mmd_addr,
-		      u16 reg_addr, u16 val);
-	unsigned mode_support;
-};
-
-/* PHY interrupt types */
-enum {
-	cphy_cause_link_change = 0x1,
-	cphy_cause_error = 0x2,
-	cphy_cause_fifo_error = 0x3
-};
-
-enum {
-	PHY_LINK_UP = 0x1,
-	PHY_AUTONEG_RDY = 0x2,
-	PHY_AUTONEG_EN = 0x4
-};
-
-struct cphy;
-
-/* PHY operations */
-struct cphy_ops {
-	void (*destroy)(struct cphy *);
-	int (*reset)(struct cphy *, int wait);
-
-	int (*interrupt_enable)(struct cphy *);
-	int (*interrupt_disable)(struct cphy *);
-	int (*interrupt_clear)(struct cphy *);
-	int (*interrupt_handler)(struct cphy *);
-
-	int (*autoneg_enable)(struct cphy *);
-	int (*autoneg_disable)(struct cphy *);
-	int (*autoneg_restart)(struct cphy *);
-
-	int (*advertise)(struct cphy *phy, unsigned int advertise_map);
-	int (*set_loopback)(struct cphy *, int on);
-	int (*set_speed_duplex)(struct cphy *phy, int speed, int duplex);
-	int (*get_link_status)(struct cphy *phy, int *link_ok, int *speed,
-			       int *duplex, int *fc);
-
-	u32 mmds;
-};
-
-/* A PHY instance */
-struct cphy {
-	int state;	/* Link status state machine */
-	adapter_t *adapter;                  /* associated adapter */
-
-	struct delayed_work phy_update;
-
-	u16 bmsr;
-	int count;
-	int act_count;
-	int act_on;
-
-	u32 elmer_gpo;
-
-	const struct cphy_ops *ops;            /* PHY operations */
-	struct mdio_if_info mdio;
-	struct cphy_instance *instance;
-};
-
-/* Convenience MDIO read/write wrappers */
-static inline int cphy_mdio_read(struct cphy *cphy, int mmd, int reg,
-				 unsigned int *valp)
-{
-	int rc = cphy->mdio.mdio_read(cphy->mdio.dev, cphy->mdio.prtad, mmd,
-				      reg);
-	*valp = (rc >= 0) ? rc : -1;
-	return (rc >= 0) ? 0 : rc;
-}
-
-static inline int cphy_mdio_write(struct cphy *cphy, int mmd, int reg,
-				  unsigned int val)
-{
-	return cphy->mdio.mdio_write(cphy->mdio.dev, cphy->mdio.prtad, mmd,
-				     reg, val);
-}
-
-static inline int simple_mdio_read(struct cphy *cphy, int reg,
-				   unsigned int *valp)
-{
-	return cphy_mdio_read(cphy, MDIO_DEVAD_NONE, reg, valp);
-}
-
-static inline int simple_mdio_write(struct cphy *cphy, int reg,
-				    unsigned int val)
-{
-	return cphy_mdio_write(cphy, MDIO_DEVAD_NONE, reg, val);
-}
-
-/* Convenience initializer */
-static inline void cphy_init(struct cphy *phy, struct net_device *dev,
-			     int phy_addr, struct cphy_ops *phy_ops,
-			     const struct mdio_ops *mdio_ops)
-{
-	struct adapter *adapter = netdev_priv(dev);
-	phy->adapter = adapter;
-	phy->ops     = phy_ops;
-	if (mdio_ops) {
-		phy->mdio.prtad = phy_addr;
-		phy->mdio.mmds = phy_ops->mmds;
-		phy->mdio.mode_support = mdio_ops->mode_support;
-		phy->mdio.mdio_read = mdio_ops->read;
-		phy->mdio.mdio_write = mdio_ops->write;
-	}
-	phy->mdio.dev = dev;
-}
-
-/* Operations of the PHY-instance factory */
-struct gphy {
-	/* Construct a PHY instance with the given PHY address */
-	struct cphy *(*create)(struct net_device *dev, int phy_addr,
-			       const struct mdio_ops *mdio_ops);
-
-	/*
-	 * Reset the PHY chip.  This resets the whole PHY chip, not individual
-	 * ports.
-	 */
-	int (*reset)(adapter_t *adapter);
-};
-
-extern const struct gphy t1_my3126_ops;
-extern const struct gphy t1_mv88e1xxx_ops;
-extern const struct gphy t1_vsc8244_ops;
-extern const struct gphy t1_mv88x201x_ops;
-
-#endif /* _CXGB_CPHY_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/cpl5_cmd.h linux-libre-3.2-gnu/drivers/net/chelsio/cpl5_cmd.h
--- linux-libre-3.1-gnu/drivers/net/chelsio/cpl5_cmd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/cpl5_cmd.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,639 +0,0 @@
-/*****************************************************************************
- *                                                                           *
- * File: cpl5_cmd.h                                                          *
- * $Revision: 1.6 $                                                          *
- * $Date: 2005/06/21 18:29:47 $                                              *
- * Description:                                                              *
- *  part of the Chelsio 10Gb Ethernet 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.                                *
- *                                                                           *
- * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
- *                                                                           *
- * http://www.chelsio.com                                                    *
- *                                                                           *
- * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
- * All rights reserved.                                                      *
- *                                                                           *
- * Maintainers: maintainers@chelsio.com                                      *
- *                                                                           *
- * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
- *          Tina Yang               <tainay@chelsio.com>                     *
- *          Felix Marti             <felix@chelsio.com>                      *
- *          Scott Bardone           <sbardone@chelsio.com>                   *
- *          Kurt Ottaway            <kottaway@chelsio.com>                   *
- *          Frank DiMambro          <frank@chelsio.com>                      *
- *                                                                           *
- * History:                                                                  *
- *                                                                           *
- ****************************************************************************/
-
-#ifndef _CXGB_CPL5_CMD_H_
-#define _CXGB_CPL5_CMD_H_
-
-#include <asm/byteorder.h>
-
-#if !defined(__LITTLE_ENDIAN_BITFIELD) && !defined(__BIG_ENDIAN_BITFIELD)
-#error "Adjust your <asm/byteorder.h> defines"
-#endif
-
-enum CPL_opcode {
-	CPL_PASS_OPEN_REQ     = 0x1,
-	CPL_PASS_OPEN_RPL     = 0x2,
-	CPL_PASS_ESTABLISH    = 0x3,
-	CPL_PASS_ACCEPT_REQ   = 0xE,
-	CPL_PASS_ACCEPT_RPL   = 0x4,
-	CPL_ACT_OPEN_REQ      = 0x5,
-	CPL_ACT_OPEN_RPL      = 0x6,
-	CPL_CLOSE_CON_REQ     = 0x7,
-	CPL_CLOSE_CON_RPL     = 0x8,
-	CPL_CLOSE_LISTSRV_REQ = 0x9,
-	CPL_CLOSE_LISTSRV_RPL = 0xA,
-	CPL_ABORT_REQ         = 0xB,
-	CPL_ABORT_RPL         = 0xC,
-	CPL_PEER_CLOSE        = 0xD,
-	CPL_ACT_ESTABLISH     = 0x17,
-
-	CPL_GET_TCB           = 0x24,
-	CPL_GET_TCB_RPL       = 0x25,
-	CPL_SET_TCB           = 0x26,
-	CPL_SET_TCB_FIELD     = 0x27,
-	CPL_SET_TCB_RPL       = 0x28,
-	CPL_PCMD              = 0x29,
-
-	CPL_PCMD_READ         = 0x31,
-	CPL_PCMD_READ_RPL     = 0x32,
-
-
-	CPL_RX_DATA           = 0xA0,
-	CPL_RX_DATA_DDP       = 0xA1,
-	CPL_RX_DATA_ACK       = 0xA3,
-	CPL_RX_PKT            = 0xAD,
-	CPL_RX_ISCSI_HDR      = 0xAF,
-	CPL_TX_DATA_ACK       = 0xB0,
-	CPL_TX_DATA           = 0xB1,
-	CPL_TX_PKT            = 0xB2,
-	CPL_TX_PKT_LSO        = 0xB6,
-
-	CPL_RTE_DELETE_REQ    = 0xC0,
-	CPL_RTE_DELETE_RPL    = 0xC1,
-	CPL_RTE_WRITE_REQ     = 0xC2,
-	CPL_RTE_WRITE_RPL     = 0xD3,
-	CPL_RTE_READ_REQ      = 0xC3,
-	CPL_RTE_READ_RPL      = 0xC4,
-	CPL_L2T_WRITE_REQ     = 0xC5,
-	CPL_L2T_WRITE_RPL     = 0xD4,
-	CPL_L2T_READ_REQ      = 0xC6,
-	CPL_L2T_READ_RPL      = 0xC7,
-	CPL_SMT_WRITE_REQ     = 0xC8,
-	CPL_SMT_WRITE_RPL     = 0xD5,
-	CPL_SMT_READ_REQ      = 0xC9,
-	CPL_SMT_READ_RPL      = 0xCA,
-	CPL_ARP_MISS_REQ      = 0xCD,
-	CPL_ARP_MISS_RPL      = 0xCE,
-	CPL_MIGRATE_C2T_REQ   = 0xDC,
-	CPL_MIGRATE_C2T_RPL   = 0xDD,
-	CPL_ERROR             = 0xD7,
-
-	/* internal: driver -> TOM */
-	CPL_MSS_CHANGE        = 0xE1
-};
-
-#define NUM_CPL_CMDS 256
-
-enum CPL_error {
-	CPL_ERR_NONE               = 0,
-	CPL_ERR_TCAM_PARITY        = 1,
-	CPL_ERR_TCAM_FULL          = 3,
-	CPL_ERR_CONN_RESET         = 20,
-	CPL_ERR_CONN_EXIST         = 22,
-	CPL_ERR_ARP_MISS           = 23,
-	CPL_ERR_BAD_SYN            = 24,
-	CPL_ERR_CONN_TIMEDOUT      = 30,
-	CPL_ERR_XMIT_TIMEDOUT      = 31,
-	CPL_ERR_PERSIST_TIMEDOUT   = 32,
-	CPL_ERR_FINWAIT2_TIMEDOUT  = 33,
-	CPL_ERR_KEEPALIVE_TIMEDOUT = 34,
-	CPL_ERR_ABORT_FAILED       = 42,
-	CPL_ERR_GENERAL            = 99
-};
-
-enum {
-	CPL_CONN_POLICY_AUTO = 0,
-	CPL_CONN_POLICY_ASK  = 1,
-	CPL_CONN_POLICY_DENY = 3
-};
-
-enum {
-	ULP_MODE_NONE   = 0,
-	ULP_MODE_TCPDDP = 1,
-	ULP_MODE_ISCSI  = 2,
-	ULP_MODE_IWARP  = 3,
-	ULP_MODE_SSL    = 4
-};
-
-enum {
-	CPL_PASS_OPEN_ACCEPT,
-	CPL_PASS_OPEN_REJECT
-};
-
-enum {
-	CPL_ABORT_SEND_RST = 0,
-	CPL_ABORT_NO_RST,
-	CPL_ABORT_POST_CLOSE_REQ = 2
-};
-
-enum {                // TX_PKT_LSO ethernet types
-	CPL_ETH_II,
-	CPL_ETH_II_VLAN,
-	CPL_ETH_802_3,
-	CPL_ETH_802_3_VLAN
-};
-
-union opcode_tid {
-	u32 opcode_tid;
-	u8 opcode;
-};
-
-#define S_OPCODE 24
-#define V_OPCODE(x) ((x) << S_OPCODE)
-#define G_OPCODE(x) (((x) >> S_OPCODE) & 0xFF)
-#define G_TID(x)    ((x) & 0xFFFFFF)
-
-/* tid is assumed to be 24-bits */
-#define MK_OPCODE_TID(opcode, tid) (V_OPCODE(opcode) | (tid))
-
-#define OPCODE_TID(cmd) ((cmd)->ot.opcode_tid)
-
-/* extract the TID from a CPL command */
-#define GET_TID(cmd) (G_TID(ntohl(OPCODE_TID(cmd))))
-
-struct tcp_options {
-	u16 mss;
-	u8 wsf;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8 rsvd:4;
-	u8 ecn:1;
-	u8 sack:1;
-	u8 tstamp:1;
-#else
-	u8 tstamp:1;
-	u8 sack:1;
-	u8 ecn:1;
-	u8 rsvd:4;
-#endif
-};
-
-struct cpl_pass_open_req {
-	union opcode_tid ot;
-	u16 local_port;
-	u16 peer_port;
-	u32 local_ip;
-	u32 peer_ip;
-	u32 opt0h;
-	u32 opt0l;
-	u32 peer_netmask;
-	u32 opt1;
-};
-
-struct cpl_pass_open_rpl {
-	union opcode_tid ot;
-	u16 local_port;
-	u16 peer_port;
-	u32 local_ip;
-	u32 peer_ip;
-	u8 resvd[7];
-	u8 status;
-};
-
-struct cpl_pass_establish {
-	union opcode_tid ot;
-	u16 local_port;
-	u16 peer_port;
-	u32 local_ip;
-	u32 peer_ip;
-	u32 tos_tid;
-	u8  l2t_idx;
-	u8  rsvd[3];
-	u32 snd_isn;
-	u32 rcv_isn;
-};
-
-struct cpl_pass_accept_req {
-	union opcode_tid ot;
-	u16 local_port;
-	u16 peer_port;
-	u32 local_ip;
-	u32 peer_ip;
-	u32 tos_tid;
-	struct tcp_options tcp_options;
-	u8  dst_mac[6];
-	u16 vlan_tag;
-	u8  src_mac[6];
-	u8  rsvd[2];
-	u32 rcv_isn;
-	u32 unknown_tcp_options;
-};
-
-struct cpl_pass_accept_rpl {
-	union opcode_tid ot;
-	u32 rsvd0;
-	u32 rsvd1;
-	u32 peer_ip;
-	u32 opt0h;
-	union {
-		u32 opt0l;
-		struct {
-		    u8 rsvd[3];
-		    u8 status;
-		};
-	};
-};
-
-struct cpl_act_open_req {
-	union opcode_tid ot;
-	u16 local_port;
-	u16 peer_port;
-	u32 local_ip;
-	u32 peer_ip;
-	u32 opt0h;
-	u32 opt0l;
-	u32 iff_vlantag;
-	u32 rsvd;
-};
-
-struct cpl_act_open_rpl {
-	union opcode_tid ot;
-	u16 local_port;
-	u16 peer_port;
-	u32 local_ip;
-	u32 peer_ip;
-	u32 new_tid;
-	u8  rsvd[3];
-	u8  status;
-};
-
-struct cpl_act_establish {
-	union opcode_tid ot;
-	u16 local_port;
-	u16 peer_port;
-	u32 local_ip;
-	u32 peer_ip;
-	u32 tos_tid;
-	u32 rsvd;
-	u32 snd_isn;
-	u32 rcv_isn;
-};
-
-struct cpl_get_tcb {
-	union opcode_tid ot;
-	u32 rsvd;
-};
-
-struct cpl_get_tcb_rpl {
-	union opcode_tid ot;
-	u16 len;
-	u8 rsvd;
-	u8 status;
-};
-
-struct cpl_set_tcb {
-	union opcode_tid ot;
-	u16 len;
-	u16 rsvd;
-};
-
-struct cpl_set_tcb_field {
-	union opcode_tid ot;
-	u8 rsvd[3];
-	u8 offset;
-	u32 mask;
-	u32 val;
-};
-
-struct cpl_set_tcb_rpl {
-	union opcode_tid ot;
-	u8 rsvd[3];
-	u8 status;
-};
-
-struct cpl_pcmd {
-	union opcode_tid ot;
-	u16 dlen_in;
-	u16 dlen_out;
-	u32 pcmd_parm[2];
-};
-
-struct cpl_pcmd_read {
-	union opcode_tid ot;
-	u32 rsvd1;
-	u16 rsvd2;
-	u32 addr;
-	u16 len;
-};
-
-struct cpl_pcmd_read_rpl {
-	union opcode_tid ot;
-	u16 len;
-};
-
-struct cpl_close_con_req {
-	union opcode_tid ot;
-	u32 rsvd;
-};
-
-struct cpl_close_con_rpl {
-	union opcode_tid ot;
-	u8 rsvd[3];
-	u8 status;
-	u32 snd_nxt;
-	u32 rcv_nxt;
-};
-
-struct cpl_close_listserv_req {
-	union opcode_tid ot;
-	u32 rsvd;
-};
-
-struct cpl_close_listserv_rpl {
-	union opcode_tid ot;
-	u8 rsvd[3];
-	u8 status;
-};
-
-struct cpl_abort_req {
-	union opcode_tid ot;
-	u32 rsvd0;
-	u8  rsvd1;
-	u8  cmd;
-	u8  rsvd2[6];
-};
-
-struct cpl_abort_rpl {
-	union opcode_tid ot;
-	u32 rsvd0;
-	u8  rsvd1;
-	u8  status;
-	u8  rsvd2[6];
-};
-
-struct cpl_peer_close {
-	union opcode_tid ot;
-	u32 rsvd;
-};
-
-struct cpl_tx_data {
-	union opcode_tid ot;
-	u32 len;
-	u32 rsvd0;
-	u16 urg;
-	u16 flags;
-};
-
-struct cpl_tx_data_ack {
-	union opcode_tid ot;
-	u32 ack_seq;
-};
-
-struct cpl_rx_data {
-	union opcode_tid ot;
-	u32 len;
-	u32 seq;
-	u16 urg;
-	u8  rsvd;
-	u8  status;
-};
-
-struct cpl_rx_data_ack {
-	union opcode_tid ot;
-	u32 credit;
-};
-
-struct cpl_rx_data_ddp {
-	union opcode_tid ot;
-	u32 len;
-	u32 seq;
-	u32 nxt_seq;
-	u32 ulp_crc;
-	u16 ddp_status;
-	u8  rsvd;
-	u8  status;
-};
-
-/*
- * We want this header's alignment to be no more stringent than 2-byte aligned.
- * All fields are u8 or u16 except for the length.  However that field is not
- * used so we break it into 2 16-bit parts to easily meet our alignment needs.
- */
-struct cpl_tx_pkt {
-	u8 opcode;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8 iff:4;
-	u8 ip_csum_dis:1;
-	u8 l4_csum_dis:1;
-	u8 vlan_valid:1;
-	u8 rsvd:1;
-#else
-	u8 rsvd:1;
-	u8 vlan_valid:1;
-	u8 l4_csum_dis:1;
-	u8 ip_csum_dis:1;
-	u8 iff:4;
-#endif
-	u16 vlan;
-	u16 len_hi;
-	u16 len_lo;
-};
-
-struct cpl_tx_pkt_lso {
-	u8 opcode;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8 iff:4;
-	u8 ip_csum_dis:1;
-	u8 l4_csum_dis:1;
-	u8 vlan_valid:1;
-	u8 :1;
-#else
-	u8 :1;
-	u8 vlan_valid:1;
-	u8 l4_csum_dis:1;
-	u8 ip_csum_dis:1;
-	u8 iff:4;
-#endif
-	u16 vlan;
-	__be32 len;
-
-	u8 rsvd[5];
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8 tcp_hdr_words:4;
-	u8 ip_hdr_words:4;
-#else
-	u8 ip_hdr_words:4;
-	u8 tcp_hdr_words:4;
-#endif
-	__be16 eth_type_mss;
-};
-
-struct cpl_rx_pkt {
-	u8 opcode;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8 iff:4;
-	u8 csum_valid:1;
-	u8 bad_pkt:1;
-	u8 vlan_valid:1;
-	u8 rsvd:1;
-#else
-	u8 rsvd:1;
-	u8 vlan_valid:1;
-	u8 bad_pkt:1;
-	u8 csum_valid:1;
-	u8 iff:4;
-#endif
-	u16 csum;
-	u16 vlan;
-	u16 len;
-};
-
-struct cpl_l2t_write_req {
-	union opcode_tid ot;
-	u32 params;
-	u8 rsvd1[2];
-	u8 dst_mac[6];
-};
-
-struct cpl_l2t_write_rpl {
-	union opcode_tid ot;
-	u8 status;
-	u8 rsvd[3];
-};
-
-struct cpl_l2t_read_req {
-	union opcode_tid ot;
-	u8 rsvd[3];
-	u8 l2t_idx;
-};
-
-struct cpl_l2t_read_rpl {
-	union opcode_tid ot;
-	u32 params;
-	u8 rsvd1[2];
-	u8 dst_mac[6];
-};
-
-struct cpl_smt_write_req {
-	union opcode_tid ot;
-	u8 rsvd0;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8 rsvd1:1;
-	u8 mtu_idx:3;
-	u8 iff:4;
-#else
-	u8 iff:4;
-	u8 mtu_idx:3;
-	u8 rsvd1:1;
-#endif
-	u16 rsvd2;
-	u16 rsvd3;
-	u8  src_mac1[6];
-	u16 rsvd4;
-	u8  src_mac0[6];
-};
-
-struct cpl_smt_write_rpl {
-	union opcode_tid ot;
-	u8 status;
-	u8 rsvd[3];
-};
-
-struct cpl_smt_read_req {
-	union opcode_tid ot;
-	u8 rsvd0;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8 rsvd1:4;
-	u8 iff:4;
-#else
-	u8 iff:4;
-	u8 rsvd1:4;
-#endif
-	u16 rsvd2;
-};
-
-struct cpl_smt_read_rpl {
-	union opcode_tid ot;
-	u8 status;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8 rsvd1:1;
-	u8 mtu_idx:3;
-	u8 rsvd0:4;
-#else
-	u8 rsvd0:4;
-	u8 mtu_idx:3;
-	u8 rsvd1:1;
-#endif
-	u16 rsvd2;
-	u16 rsvd3;
-	u8  src_mac1[6];
-	u16 rsvd4;
-	u8  src_mac0[6];
-};
-
-struct cpl_rte_delete_req {
-	union opcode_tid ot;
-	u32 params;
-};
-
-struct cpl_rte_delete_rpl {
-	union opcode_tid ot;
-	u8 status;
-	u8 rsvd[3];
-};
-
-struct cpl_rte_write_req {
-	union opcode_tid ot;
-	u32 params;
-	u32 netmask;
-	u32 faddr;
-};
-
-struct cpl_rte_write_rpl {
-	union opcode_tid ot;
-	u8 status;
-	u8 rsvd[3];
-};
-
-struct cpl_rte_read_req {
-	union opcode_tid ot;
-	u32 params;
-};
-
-struct cpl_rte_read_rpl {
-	union opcode_tid ot;
-	u8 status;
-	u8 rsvd0[2];
-	u8 l2t_idx;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8 rsvd1:7;
-	u8 select:1;
-#else
-	u8 select:1;
-	u8 rsvd1:7;
-#endif
-	u8 rsvd2[3];
-	u32 addr;
-};
-
-struct cpl_mss_change {
-	union opcode_tid ot;
-	u32 mss;
-};
-
-#endif /* _CXGB_CPL5_CMD_H_ */
-
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/cxgb2.c linux-libre-3.2-gnu/drivers/net/chelsio/cxgb2.c
--- linux-libre-3.1-gnu/drivers/net/chelsio/cxgb2.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/cxgb2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1379 +0,0 @@
-/*****************************************************************************
- *                                                                           *
- * File: cxgb2.c                                                             *
- * $Revision: 1.25 $                                                         *
- * $Date: 2005/06/22 00:43:25 $                                              *
- * Description:                                                              *
- *  Chelsio 10Gb Ethernet 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.                                *
- *                                                                           *
- * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
- *                                                                           *
- * http://www.chelsio.com                                                    *
- *                                                                           *
- * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
- * All rights reserved.                                                      *
- *                                                                           *
- * Maintainers: maintainers@chelsio.com                                      *
- *                                                                           *
- * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
- *          Tina Yang               <tainay@chelsio.com>                     *
- *          Felix Marti             <felix@chelsio.com>                      *
- *          Scott Bardone           <sbardone@chelsio.com>                   *
- *          Kurt Ottaway            <kottaway@chelsio.com>                   *
- *          Frank DiMambro          <frank@chelsio.com>                      *
- *                                                                           *
- * History:                                                                  *
- *                                                                           *
- ****************************************************************************/
-
-#include "common.h"
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_vlan.h>
-#include <linux/mii.h>
-#include <linux/sockios.h>
-#include <linux/dma-mapping.h>
-#include <asm/uaccess.h>
-
-#include "cpl5_cmd.h"
-#include "regs.h"
-#include "gmac.h"
-#include "cphy.h"
-#include "sge.h"
-#include "tp.h"
-#include "espi.h"
-#include "elmer0.h"
-
-#include <linux/workqueue.h>
-
-static inline void schedule_mac_stats_update(struct adapter *ap, int secs)
-{
-	schedule_delayed_work(&ap->stats_update_task, secs * HZ);
-}
-
-static inline void cancel_mac_stats_update(struct adapter *ap)
-{
-	cancel_delayed_work(&ap->stats_update_task);
-}
-
-#define MAX_CMDQ_ENTRIES	16384
-#define MAX_CMDQ1_ENTRIES	1024
-#define MAX_RX_BUFFERS		16384
-#define MAX_RX_JUMBO_BUFFERS	16384
-#define MAX_TX_BUFFERS_HIGH	16384U
-#define MAX_TX_BUFFERS_LOW	1536U
-#define MAX_TX_BUFFERS		1460U
-#define MIN_FL_ENTRIES		32
-
-#define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \
-			 NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\
-			 NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
-
-/*
- * The EEPROM is actually bigger but only the first few bytes are used so we
- * only report those.
- */
-#define EEPROM_SIZE 32
-
-MODULE_DESCRIPTION(DRV_DESCRIPTION);
-MODULE_AUTHOR("Chelsio Communications");
-MODULE_LICENSE("GPL");
-
-static int dflt_msg_enable = DFLT_MSG_ENABLE;
-
-module_param(dflt_msg_enable, int, 0);
-MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T1 default message enable bitmap");
-
-#define HCLOCK 0x0
-#define LCLOCK 0x1
-
-/* T1 cards powersave mode */
-static int t1_clock(struct adapter *adapter, int mode);
-static int t1powersave = 1;	/* HW default is powersave mode. */
-
-module_param(t1powersave, int, 0);
-MODULE_PARM_DESC(t1powersave, "Enable/Disable T1 powersaving mode");
-
-static int disable_msi = 0;
-module_param(disable_msi, int, 0);
-MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
-
-static const char pci_speed[][4] = {
-	"33", "66", "100", "133"
-};
-
-/*
- * Setup MAC to receive the types of packets we want.
- */
-static void t1_set_rxmode(struct net_device *dev)
-{
-	struct adapter *adapter = dev->ml_priv;
-	struct cmac *mac = adapter->port[dev->if_port].mac;
-	struct t1_rx_mode rm;
-
-	rm.dev = dev;
-	mac->ops->set_rx_mode(mac, &rm);
-}
-
-static void link_report(struct port_info *p)
-{
-	if (!netif_carrier_ok(p->dev))
-		printk(KERN_INFO "%s: link down\n", p->dev->name);
-	else {
-		const char *s = "10Mbps";
-
-		switch (p->link_config.speed) {
-			case SPEED_10000: s = "10Gbps"; break;
-			case SPEED_1000:  s = "1000Mbps"; break;
-			case SPEED_100:   s = "100Mbps"; break;
-		}
-
-		printk(KERN_INFO "%s: link up, %s, %s-duplex\n",
-		       p->dev->name, s,
-		       p->link_config.duplex == DUPLEX_FULL ? "full" : "half");
-	}
-}
-
-void t1_link_negotiated(struct adapter *adapter, int port_id, int link_stat,
-			int speed, int duplex, int pause)
-{
-	struct port_info *p = &adapter->port[port_id];
-
-	if (link_stat != netif_carrier_ok(p->dev)) {
-		if (link_stat)
-			netif_carrier_on(p->dev);
-		else
-			netif_carrier_off(p->dev);
-		link_report(p);
-
-		/* multi-ports: inform toe */
-		if ((speed > 0) && (adapter->params.nports > 1)) {
-			unsigned int sched_speed = 10;
-			switch (speed) {
-			case SPEED_1000:
-				sched_speed = 1000;
-				break;
-			case SPEED_100:
-				sched_speed = 100;
-				break;
-			case SPEED_10:
-				sched_speed = 10;
-				break;
-			}
-			t1_sched_update_parms(adapter->sge, port_id, 0, sched_speed);
-		}
-	}
-}
-
-static void link_start(struct port_info *p)
-{
-	struct cmac *mac = p->mac;
-
-	mac->ops->reset(mac);
-	if (mac->ops->macaddress_set)
-		mac->ops->macaddress_set(mac, p->dev->dev_addr);
-	t1_set_rxmode(p->dev);
-	t1_link_start(p->phy, mac, &p->link_config);
-	mac->ops->enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
-}
-
-static void enable_hw_csum(struct adapter *adapter)
-{
-	if (adapter->port[0].dev->hw_features & NETIF_F_TSO)
-		t1_tp_set_ip_checksum_offload(adapter->tp, 1);	/* for TSO only */
-	t1_tp_set_tcp_checksum_offload(adapter->tp, 1);
-}
-
-/*
- * Things to do upon first use of a card.
- * This must run with the rtnl lock held.
- */
-static int cxgb_up(struct adapter *adapter)
-{
-	int err = 0;
-
-	if (!(adapter->flags & FULL_INIT_DONE)) {
-		err = t1_init_hw_modules(adapter);
-		if (err)
-			goto out_err;
-
-		enable_hw_csum(adapter);
-		adapter->flags |= FULL_INIT_DONE;
-	}
-
-	t1_interrupts_clear(adapter);
-
-	adapter->params.has_msi = !disable_msi && !pci_enable_msi(adapter->pdev);
-	err = request_irq(adapter->pdev->irq, t1_interrupt,
-			  adapter->params.has_msi ? 0 : IRQF_SHARED,
-			  adapter->name, adapter);
-	if (err) {
-		if (adapter->params.has_msi)
-			pci_disable_msi(adapter->pdev);
-
-		goto out_err;
-	}
-
-	t1_sge_start(adapter->sge);
-	t1_interrupts_enable(adapter);
-out_err:
-	return err;
-}
-
-/*
- * Release resources when all the ports have been stopped.
- */
-static void cxgb_down(struct adapter *adapter)
-{
-	t1_sge_stop(adapter->sge);
-	t1_interrupts_disable(adapter);
-	free_irq(adapter->pdev->irq, adapter);
-	if (adapter->params.has_msi)
-		pci_disable_msi(adapter->pdev);
-}
-
-static int cxgb_open(struct net_device *dev)
-{
-	int err;
-	struct adapter *adapter = dev->ml_priv;
-	int other_ports = adapter->open_device_map & PORT_MASK;
-
-	napi_enable(&adapter->napi);
-	if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0) {
-		napi_disable(&adapter->napi);
-		return err;
-	}
-
-	__set_bit(dev->if_port, &adapter->open_device_map);
-	link_start(&adapter->port[dev->if_port]);
-	netif_start_queue(dev);
-	if (!other_ports && adapter->params.stats_update_period)
-		schedule_mac_stats_update(adapter,
-					  adapter->params.stats_update_period);
-
-	t1_vlan_mode(adapter, dev->features);
-	return 0;
-}
-
-static int cxgb_close(struct net_device *dev)
-{
-	struct adapter *adapter = dev->ml_priv;
-	struct port_info *p = &adapter->port[dev->if_port];
-	struct cmac *mac = p->mac;
-
-	netif_stop_queue(dev);
-	napi_disable(&adapter->napi);
-	mac->ops->disable(mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
-	netif_carrier_off(dev);
-
-	clear_bit(dev->if_port, &adapter->open_device_map);
-	if (adapter->params.stats_update_period &&
-	    !(adapter->open_device_map & PORT_MASK)) {
-		/* Stop statistics accumulation. */
-		smp_mb__after_clear_bit();
-		spin_lock(&adapter->work_lock);   /* sync with update task */
-		spin_unlock(&adapter->work_lock);
-		cancel_mac_stats_update(adapter);
-	}
-
-	if (!adapter->open_device_map)
-		cxgb_down(adapter);
-	return 0;
-}
-
-static struct net_device_stats *t1_get_stats(struct net_device *dev)
-{
-	struct adapter *adapter = dev->ml_priv;
-	struct port_info *p = &adapter->port[dev->if_port];
-	struct net_device_stats *ns = &p->netstats;
-	const struct cmac_statistics *pstats;
-
-	/* Do a full update of the MAC stats */
-	pstats = p->mac->ops->statistics_update(p->mac,
-						MAC_STATS_UPDATE_FULL);
-
-	ns->tx_packets = pstats->TxUnicastFramesOK +
-		pstats->TxMulticastFramesOK + pstats->TxBroadcastFramesOK;
-
-	ns->rx_packets = pstats->RxUnicastFramesOK +
-		pstats->RxMulticastFramesOK + pstats->RxBroadcastFramesOK;
-
-	ns->tx_bytes = pstats->TxOctetsOK;
-	ns->rx_bytes = pstats->RxOctetsOK;
-
-	ns->tx_errors = pstats->TxLateCollisions + pstats->TxLengthErrors +
-		pstats->TxUnderrun + pstats->TxFramesAbortedDueToXSCollisions;
-	ns->rx_errors = pstats->RxDataErrors + pstats->RxJabberErrors +
-		pstats->RxFCSErrors + pstats->RxAlignErrors +
-		pstats->RxSequenceErrors + pstats->RxFrameTooLongErrors +
-		pstats->RxSymbolErrors + pstats->RxRuntErrors;
-
-	ns->multicast  = pstats->RxMulticastFramesOK;
-	ns->collisions = pstats->TxTotalCollisions;
-
-	/* detailed rx_errors */
-	ns->rx_length_errors = pstats->RxFrameTooLongErrors +
-		pstats->RxJabberErrors;
-	ns->rx_over_errors   = 0;
-	ns->rx_crc_errors    = pstats->RxFCSErrors;
-	ns->rx_frame_errors  = pstats->RxAlignErrors;
-	ns->rx_fifo_errors   = 0;
-	ns->rx_missed_errors = 0;
-
-	/* detailed tx_errors */
-	ns->tx_aborted_errors   = pstats->TxFramesAbortedDueToXSCollisions;
-	ns->tx_carrier_errors   = 0;
-	ns->tx_fifo_errors      = pstats->TxUnderrun;
-	ns->tx_heartbeat_errors = 0;
-	ns->tx_window_errors    = pstats->TxLateCollisions;
-	return ns;
-}
-
-static u32 get_msglevel(struct net_device *dev)
-{
-	struct adapter *adapter = dev->ml_priv;
-
-	return adapter->msg_enable;
-}
-
-static void set_msglevel(struct net_device *dev, u32 val)
-{
-	struct adapter *adapter = dev->ml_priv;
-
-	adapter->msg_enable = val;
-}
-
-static char stats_strings[][ETH_GSTRING_LEN] = {
-	"TxOctetsOK",
-	"TxOctetsBad",
-	"TxUnicastFramesOK",
-	"TxMulticastFramesOK",
-	"TxBroadcastFramesOK",
-	"TxPauseFrames",
-	"TxFramesWithDeferredXmissions",
-	"TxLateCollisions",
-	"TxTotalCollisions",
-	"TxFramesAbortedDueToXSCollisions",
-	"TxUnderrun",
-	"TxLengthErrors",
-	"TxInternalMACXmitError",
-	"TxFramesWithExcessiveDeferral",
-	"TxFCSErrors",
-	"TxJumboFramesOk",
-	"TxJumboOctetsOk",
-	
-	"RxOctetsOK",
-	"RxOctetsBad",
-	"RxUnicastFramesOK",
-	"RxMulticastFramesOK",
-	"RxBroadcastFramesOK",
-	"RxPauseFrames",
-	"RxFCSErrors",
-	"RxAlignErrors",
-	"RxSymbolErrors",
-	"RxDataErrors",
-	"RxSequenceErrors",
-	"RxRuntErrors",
-	"RxJabberErrors",
-	"RxInternalMACRcvError",
-	"RxInRangeLengthErrors",
-	"RxOutOfRangeLengthField",
-	"RxFrameTooLongErrors",
-	"RxJumboFramesOk",
-	"RxJumboOctetsOk",
-
-	/* Port stats */
-	"RxCsumGood",
-	"TxCsumOffload",
-	"TxTso",
-	"RxVlan",
-	"TxVlan",
-	"TxNeedHeadroom", 
-	
-	/* Interrupt stats */
-	"rx drops",
-	"pure_rsps",
-	"unhandled irqs",
-	"respQ_empty",
-	"respQ_overflow",
-	"freelistQ_empty",
-	"pkt_too_big",
-	"pkt_mismatch",
-	"cmdQ_full0",
-	"cmdQ_full1",
-
-	"espi_DIP2ParityErr",
-	"espi_DIP4Err",
-	"espi_RxDrops",
-	"espi_TxDrops",
-	"espi_RxOvfl",
-	"espi_ParityErr"
-};
-
-#define T2_REGMAP_SIZE (3 * 1024)
-
-static int get_regs_len(struct net_device *dev)
-{
-	return T2_REGMAP_SIZE;
-}
-
-static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct adapter *adapter = dev->ml_priv;
-
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-	strcpy(info->fw_version, "N/A");
-	strcpy(info->bus_info, pci_name(adapter->pdev));
-}
-
-static int get_sset_count(struct net_device *dev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		return ARRAY_SIZE(stats_strings);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void get_strings(struct net_device *dev, u32 stringset, u8 *data)
-{
-	if (stringset == ETH_SS_STATS)
-		memcpy(data, stats_strings, sizeof(stats_strings));
-}
-
-static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
-		      u64 *data)
-{
-	struct adapter *adapter = dev->ml_priv;
-	struct cmac *mac = adapter->port[dev->if_port].mac;
-	const struct cmac_statistics *s;
-	const struct sge_intr_counts *t;
-	struct sge_port_stats ss;
-
-	s = mac->ops->statistics_update(mac, MAC_STATS_UPDATE_FULL);
-	t = t1_sge_get_intr_counts(adapter->sge);
-	t1_sge_get_port_stats(adapter->sge, dev->if_port, &ss);
-
-	*data++ = s->TxOctetsOK;
-	*data++ = s->TxOctetsBad;
-	*data++ = s->TxUnicastFramesOK;
-	*data++ = s->TxMulticastFramesOK;
-	*data++ = s->TxBroadcastFramesOK;
-	*data++ = s->TxPauseFrames;
-	*data++ = s->TxFramesWithDeferredXmissions;
-	*data++ = s->TxLateCollisions;
-	*data++ = s->TxTotalCollisions;
-	*data++ = s->TxFramesAbortedDueToXSCollisions;
-	*data++ = s->TxUnderrun;
-	*data++ = s->TxLengthErrors;
-	*data++ = s->TxInternalMACXmitError;
-	*data++ = s->TxFramesWithExcessiveDeferral;
-	*data++ = s->TxFCSErrors;
-	*data++ = s->TxJumboFramesOK;
-	*data++ = s->TxJumboOctetsOK;
-
-	*data++ = s->RxOctetsOK;
-	*data++ = s->RxOctetsBad;
-	*data++ = s->RxUnicastFramesOK;
-	*data++ = s->RxMulticastFramesOK;
-	*data++ = s->RxBroadcastFramesOK;
-	*data++ = s->RxPauseFrames;
-	*data++ = s->RxFCSErrors;
-	*data++ = s->RxAlignErrors;
-	*data++ = s->RxSymbolErrors;
-	*data++ = s->RxDataErrors;
-	*data++ = s->RxSequenceErrors;
-	*data++ = s->RxRuntErrors;
-	*data++ = s->RxJabberErrors;
-	*data++ = s->RxInternalMACRcvError;
-	*data++ = s->RxInRangeLengthErrors;
-	*data++ = s->RxOutOfRangeLengthField;
-	*data++ = s->RxFrameTooLongErrors;
-	*data++ = s->RxJumboFramesOK;
-	*data++ = s->RxJumboOctetsOK;
-
-	*data++ = ss.rx_cso_good;
-	*data++ = ss.tx_cso;
-	*data++ = ss.tx_tso;
-	*data++ = ss.vlan_xtract;
-	*data++ = ss.vlan_insert;
-	*data++ = ss.tx_need_hdrroom;
-	
-	*data++ = t->rx_drops;
-	*data++ = t->pure_rsps;
-	*data++ = t->unhandled_irqs;
-	*data++ = t->respQ_empty;
-	*data++ = t->respQ_overflow;
-	*data++ = t->freelistQ_empty;
-	*data++ = t->pkt_too_big;
-	*data++ = t->pkt_mismatch;
-	*data++ = t->cmdQ_full[0];
-	*data++ = t->cmdQ_full[1];
-
-	if (adapter->espi) {
-		const struct espi_intr_counts *e;
-
-		e = t1_espi_get_intr_counts(adapter->espi);
-		*data++ = e->DIP2_parity_err;
-		*data++ = e->DIP4_err;
-		*data++ = e->rx_drops;
-		*data++ = e->tx_drops;
-		*data++ = e->rx_ovflw;
-		*data++ = e->parity_err;
-	}
-}
-
-static inline void reg_block_dump(struct adapter *ap, void *buf,
-				  unsigned int start, unsigned int end)
-{
-	u32 *p = buf + start;
-
-	for ( ; start <= end; start += sizeof(u32))
-		*p++ = readl(ap->regs + start);
-}
-
-static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
-		     void *buf)
-{
-	struct adapter *ap = dev->ml_priv;
-
-	/*
-	 * Version scheme: bits 0..9: chip version, bits 10..15: chip revision
-	 */
-	regs->version = 2;
-
-	memset(buf, 0, T2_REGMAP_SIZE);
-	reg_block_dump(ap, buf, 0, A_SG_RESPACCUTIMER);
-	reg_block_dump(ap, buf, A_MC3_CFG, A_MC4_INT_CAUSE);
-	reg_block_dump(ap, buf, A_TPI_ADDR, A_TPI_PAR);
-	reg_block_dump(ap, buf, A_TP_IN_CONFIG, A_TP_TX_DROP_COUNT);
-	reg_block_dump(ap, buf, A_RAT_ROUTE_CONTROL, A_RAT_INTR_CAUSE);
-	reg_block_dump(ap, buf, A_CSPI_RX_AE_WM, A_CSPI_INTR_ENABLE);
-	reg_block_dump(ap, buf, A_ESPI_SCH_TOKEN0, A_ESPI_GOSTAT);
-	reg_block_dump(ap, buf, A_ULP_ULIMIT, A_ULP_PIO_CTRL);
-	reg_block_dump(ap, buf, A_PL_ENABLE, A_PL_CAUSE);
-	reg_block_dump(ap, buf, A_MC5_CONFIG, A_MC5_MASK_WRITE_CMD);
-}
-
-static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct adapter *adapter = dev->ml_priv;
-	struct port_info *p = &adapter->port[dev->if_port];
-
-	cmd->supported = p->link_config.supported;
-	cmd->advertising = p->link_config.advertising;
-
-	if (netif_carrier_ok(dev)) {
-		ethtool_cmd_speed_set(cmd, p->link_config.speed);
-		cmd->duplex = p->link_config.duplex;
-	} else {
-		ethtool_cmd_speed_set(cmd, -1);
-		cmd->duplex = -1;
-	}
-
-	cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
-	cmd->phy_address = p->phy->mdio.prtad;
-	cmd->transceiver = XCVR_EXTERNAL;
-	cmd->autoneg = p->link_config.autoneg;
-	cmd->maxtxpkt = 0;
-	cmd->maxrxpkt = 0;
-	return 0;
-}
-
-static int speed_duplex_to_caps(int speed, int duplex)
-{
-	int cap = 0;
-
-	switch (speed) {
-	case SPEED_10:
-		if (duplex == DUPLEX_FULL)
-			cap = SUPPORTED_10baseT_Full;
-		else
-			cap = SUPPORTED_10baseT_Half;
-		break;
-	case SPEED_100:
-		if (duplex == DUPLEX_FULL)
-			cap = SUPPORTED_100baseT_Full;
-		else
-			cap = SUPPORTED_100baseT_Half;
-		break;
-	case SPEED_1000:
-		if (duplex == DUPLEX_FULL)
-			cap = SUPPORTED_1000baseT_Full;
-		else
-			cap = SUPPORTED_1000baseT_Half;
-		break;
-	case SPEED_10000:
-		if (duplex == DUPLEX_FULL)
-			cap = SUPPORTED_10000baseT_Full;
-	}
-	return cap;
-}
-
-#define ADVERTISED_MASK (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
-		      ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
-		      ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | \
-		      ADVERTISED_10000baseT_Full)
-
-static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct adapter *adapter = dev->ml_priv;
-	struct port_info *p = &adapter->port[dev->if_port];
-	struct link_config *lc = &p->link_config;
-
-	if (!(lc->supported & SUPPORTED_Autoneg))
-		return -EOPNOTSUPP;             /* can't change speed/duplex */
-
-	if (cmd->autoneg == AUTONEG_DISABLE) {
-		u32 speed = ethtool_cmd_speed(cmd);
-		int cap = speed_duplex_to_caps(speed, cmd->duplex);
-
-		if (!(lc->supported & cap) || (speed == SPEED_1000))
-			return -EINVAL;
-		lc->requested_speed = speed;
-		lc->requested_duplex = cmd->duplex;
-		lc->advertising = 0;
-	} else {
-		cmd->advertising &= ADVERTISED_MASK;
-		if (cmd->advertising & (cmd->advertising - 1))
-			cmd->advertising = lc->supported;
-		cmd->advertising &= lc->supported;
-		if (!cmd->advertising)
-			return -EINVAL;
-		lc->requested_speed = SPEED_INVALID;
-		lc->requested_duplex = DUPLEX_INVALID;
-		lc->advertising = cmd->advertising | ADVERTISED_Autoneg;
-	}
-	lc->autoneg = cmd->autoneg;
-	if (netif_running(dev))
-		t1_link_start(p->phy, p->mac, lc);
-	return 0;
-}
-
-static void get_pauseparam(struct net_device *dev,
-			   struct ethtool_pauseparam *epause)
-{
-	struct adapter *adapter = dev->ml_priv;
-	struct port_info *p = &adapter->port[dev->if_port];
-
-	epause->autoneg = (p->link_config.requested_fc & PAUSE_AUTONEG) != 0;
-	epause->rx_pause = (p->link_config.fc & PAUSE_RX) != 0;
-	epause->tx_pause = (p->link_config.fc & PAUSE_TX) != 0;
-}
-
-static int set_pauseparam(struct net_device *dev,
-			  struct ethtool_pauseparam *epause)
-{
-	struct adapter *adapter = dev->ml_priv;
-	struct port_info *p = &adapter->port[dev->if_port];
-	struct link_config *lc = &p->link_config;
-
-	if (epause->autoneg == AUTONEG_DISABLE)
-		lc->requested_fc = 0;
-	else if (lc->supported & SUPPORTED_Autoneg)
-		lc->requested_fc = PAUSE_AUTONEG;
-	else
-		return -EINVAL;
-
-	if (epause->rx_pause)
-		lc->requested_fc |= PAUSE_RX;
-	if (epause->tx_pause)
-		lc->requested_fc |= PAUSE_TX;
-	if (lc->autoneg == AUTONEG_ENABLE) {
-		if (netif_running(dev))
-			t1_link_start(p->phy, p->mac, lc);
-	} else {
-		lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
-		if (netif_running(dev))
-			p->mac->ops->set_speed_duplex_fc(p->mac, -1, -1,
-							 lc->fc);
-	}
-	return 0;
-}
-
-static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
-{
-	struct adapter *adapter = dev->ml_priv;
-	int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
-
-	e->rx_max_pending = MAX_RX_BUFFERS;
-	e->rx_mini_max_pending = 0;
-	e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS;
-	e->tx_max_pending = MAX_CMDQ_ENTRIES;
-
-	e->rx_pending = adapter->params.sge.freelQ_size[!jumbo_fl];
-	e->rx_mini_pending = 0;
-	e->rx_jumbo_pending = adapter->params.sge.freelQ_size[jumbo_fl];
-	e->tx_pending = adapter->params.sge.cmdQ_size[0];
-}
-
-static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
-{
-	struct adapter *adapter = dev->ml_priv;
-	int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
-
-	if (e->rx_pending > MAX_RX_BUFFERS || e->rx_mini_pending ||
-	    e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS ||
-	    e->tx_pending > MAX_CMDQ_ENTRIES ||
-	    e->rx_pending < MIN_FL_ENTRIES ||
-	    e->rx_jumbo_pending < MIN_FL_ENTRIES ||
-	    e->tx_pending < (adapter->params.nports + 1) * (MAX_SKB_FRAGS + 1))
-		return -EINVAL;
-
-	if (adapter->flags & FULL_INIT_DONE)
-		return -EBUSY;
-
-	adapter->params.sge.freelQ_size[!jumbo_fl] = e->rx_pending;
-	adapter->params.sge.freelQ_size[jumbo_fl] = e->rx_jumbo_pending;
-	adapter->params.sge.cmdQ_size[0] = e->tx_pending;
-	adapter->params.sge.cmdQ_size[1] = e->tx_pending > MAX_CMDQ1_ENTRIES ?
-		MAX_CMDQ1_ENTRIES : e->tx_pending;
-	return 0;
-}
-
-static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
-{
-	struct adapter *adapter = dev->ml_priv;
-
-	adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs;
-	adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce;
-	adapter->params.sge.sample_interval_usecs = c->rate_sample_interval;
-	t1_sge_set_coalesce_params(adapter->sge, &adapter->params.sge);
-	return 0;
-}
-
-static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
-{
-	struct adapter *adapter = dev->ml_priv;
-
-	c->rx_coalesce_usecs = adapter->params.sge.rx_coalesce_usecs;
-	c->rate_sample_interval = adapter->params.sge.sample_interval_usecs;
-	c->use_adaptive_rx_coalesce = adapter->params.sge.coalesce_enable;
-	return 0;
-}
-
-static int get_eeprom_len(struct net_device *dev)
-{
-	struct adapter *adapter = dev->ml_priv;
-
-	return t1_is_asic(adapter) ? EEPROM_SIZE : 0;
-}
-
-#define EEPROM_MAGIC(ap) \
-	(PCI_VENDOR_ID_CHELSIO | ((ap)->params.chip_version << 16))
-
-static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
-		      u8 *data)
-{
-	int i;
-	u8 buf[EEPROM_SIZE] __attribute__((aligned(4)));
-	struct adapter *adapter = dev->ml_priv;
-
-	e->magic = EEPROM_MAGIC(adapter);
-	for (i = e->offset & ~3; i < e->offset + e->len; i += sizeof(u32))
-		t1_seeprom_read(adapter, i, (__le32 *)&buf[i]);
-	memcpy(data, buf + e->offset, e->len);
-	return 0;
-}
-
-static const struct ethtool_ops t1_ethtool_ops = {
-	.get_settings      = get_settings,
-	.set_settings      = set_settings,
-	.get_drvinfo       = get_drvinfo,
-	.get_msglevel      = get_msglevel,
-	.set_msglevel      = set_msglevel,
-	.get_ringparam     = get_sge_param,
-	.set_ringparam     = set_sge_param,
-	.get_coalesce      = get_coalesce,
-	.set_coalesce      = set_coalesce,
-	.get_eeprom_len    = get_eeprom_len,
-	.get_eeprom        = get_eeprom,
-	.get_pauseparam    = get_pauseparam,
-	.set_pauseparam    = set_pauseparam,
-	.get_link          = ethtool_op_get_link,
-	.get_strings       = get_strings,
-	.get_sset_count	   = get_sset_count,
-	.get_ethtool_stats = get_stats,
-	.get_regs_len      = get_regs_len,
-	.get_regs          = get_regs,
-};
-
-static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
-{
-	struct adapter *adapter = dev->ml_priv;
-	struct mdio_if_info *mdio = &adapter->port[dev->if_port].phy->mdio;
-
-	return mdio_mii_ioctl(mdio, if_mii(req), cmd);
-}
-
-static int t1_change_mtu(struct net_device *dev, int new_mtu)
-{
-	int ret;
-	struct adapter *adapter = dev->ml_priv;
-	struct cmac *mac = adapter->port[dev->if_port].mac;
-
-	if (!mac->ops->set_mtu)
-		return -EOPNOTSUPP;
-	if (new_mtu < 68)
-		return -EINVAL;
-	if ((ret = mac->ops->set_mtu(mac, new_mtu)))
-		return ret;
-	dev->mtu = new_mtu;
-	return 0;
-}
-
-static int t1_set_mac_addr(struct net_device *dev, void *p)
-{
-	struct adapter *adapter = dev->ml_priv;
-	struct cmac *mac = adapter->port[dev->if_port].mac;
-	struct sockaddr *addr = p;
-
-	if (!mac->ops->macaddress_set)
-		return -EOPNOTSUPP;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-	mac->ops->macaddress_set(mac, dev->dev_addr);
-	return 0;
-}
-
-static u32 t1_fix_features(struct net_device *dev, u32 features)
-{
-	/*
-	 * Since there is no support for separate rx/tx vlan accel
-	 * enable/disable make sure tx flag is always in same state as rx.
-	 */
-	if (features & NETIF_F_HW_VLAN_RX)
-		features |= NETIF_F_HW_VLAN_TX;
-	else
-		features &= ~NETIF_F_HW_VLAN_TX;
-
-	return features;
-}
-
-static int t1_set_features(struct net_device *dev, u32 features)
-{
-	u32 changed = dev->features ^ features;
-	struct adapter *adapter = dev->ml_priv;
-
-	if (changed & NETIF_F_HW_VLAN_RX)
-		t1_vlan_mode(adapter, features);
-
-	return 0;
-}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void t1_netpoll(struct net_device *dev)
-{
-	unsigned long flags;
-	struct adapter *adapter = dev->ml_priv;
-
-	local_irq_save(flags);
-	t1_interrupt(adapter->pdev->irq, adapter);
-	local_irq_restore(flags);
-}
-#endif
-
-/*
- * Periodic accumulation of MAC statistics.  This is used only if the MAC
- * does not have any other way to prevent stats counter overflow.
- */
-static void mac_stats_task(struct work_struct *work)
-{
-	int i;
-	struct adapter *adapter =
-		container_of(work, struct adapter, stats_update_task.work);
-
-	for_each_port(adapter, i) {
-		struct port_info *p = &adapter->port[i];
-
-		if (netif_running(p->dev))
-			p->mac->ops->statistics_update(p->mac,
-						       MAC_STATS_UPDATE_FAST);
-	}
-
-	/* Schedule the next statistics update if any port is active. */
-	spin_lock(&adapter->work_lock);
-	if (adapter->open_device_map & PORT_MASK)
-		schedule_mac_stats_update(adapter,
-					  adapter->params.stats_update_period);
-	spin_unlock(&adapter->work_lock);
-}
-
-/*
- * Processes elmer0 external interrupts in process context.
- */
-static void ext_intr_task(struct work_struct *work)
-{
-	struct adapter *adapter =
-		container_of(work, struct adapter, ext_intr_handler_task);
-
-	t1_elmer0_ext_intr_handler(adapter);
-
-	/* Now reenable external interrupts */
-	spin_lock_irq(&adapter->async_lock);
-	adapter->slow_intr_mask |= F_PL_INTR_EXT;
-	writel(F_PL_INTR_EXT, adapter->regs + A_PL_CAUSE);
-	writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
-		   adapter->regs + A_PL_ENABLE);
-	spin_unlock_irq(&adapter->async_lock);
-}
-
-/*
- * Interrupt-context handler for elmer0 external interrupts.
- */
-void t1_elmer0_ext_intr(struct adapter *adapter)
-{
-	/*
-	 * Schedule a task to handle external interrupts as we require
-	 * a process context.  We disable EXT interrupts in the interim
-	 * and let the task reenable them when it's done.
-	 */
-	adapter->slow_intr_mask &= ~F_PL_INTR_EXT;
-	writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
-		   adapter->regs + A_PL_ENABLE);
-	schedule_work(&adapter->ext_intr_handler_task);
-}
-
-void t1_fatal_err(struct adapter *adapter)
-{
-	if (adapter->flags & FULL_INIT_DONE) {
-		t1_sge_stop(adapter->sge);
-		t1_interrupts_disable(adapter);
-	}
-	pr_alert("%s: encountered fatal error, operation suspended\n",
-		 adapter->name);
-}
-
-static const struct net_device_ops cxgb_netdev_ops = {
-	.ndo_open		= cxgb_open,
-	.ndo_stop		= cxgb_close,
-	.ndo_start_xmit		= t1_start_xmit,
-	.ndo_get_stats		= t1_get_stats,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_multicast_list	= t1_set_rxmode,
-	.ndo_do_ioctl		= t1_ioctl,
-	.ndo_change_mtu		= t1_change_mtu,
-	.ndo_set_mac_address	= t1_set_mac_addr,
-	.ndo_fix_features	= t1_fix_features,
-	.ndo_set_features	= t1_set_features,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= t1_netpoll,
-#endif
-};
-
-static int __devinit init_one(struct pci_dev *pdev,
-			      const struct pci_device_id *ent)
-{
-	static int version_printed;
-
-	int i, err, pci_using_dac = 0;
-	unsigned long mmio_start, mmio_len;
-	const struct board_info *bi;
-	struct adapter *adapter = NULL;
-	struct port_info *pi;
-
-	if (!version_printed) {
-		printk(KERN_INFO "%s - version %s\n", DRV_DESCRIPTION,
-		       DRV_VERSION);
-		++version_printed;
-	}
-
-	err = pci_enable_device(pdev);
-	if (err)
-		return err;
-
-	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
-		pr_err("%s: cannot find PCI device memory base address\n",
-		       pci_name(pdev));
-		err = -ENODEV;
-		goto out_disable_pdev;
-	}
-
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-		pci_using_dac = 1;
-
-		if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
-			pr_err("%s: unable to obtain 64-bit DMA for "
-			       "consistent allocations\n", pci_name(pdev));
-			err = -ENODEV;
-			goto out_disable_pdev;
-		}
-
-	} else if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) {
-		pr_err("%s: no usable DMA configuration\n", pci_name(pdev));
-		goto out_disable_pdev;
-	}
-
-	err = pci_request_regions(pdev, DRV_NAME);
-	if (err) {
-		pr_err("%s: cannot obtain PCI resources\n", pci_name(pdev));
-		goto out_disable_pdev;
-	}
-
-	pci_set_master(pdev);
-
-	mmio_start = pci_resource_start(pdev, 0);
-	mmio_len = pci_resource_len(pdev, 0);
-	bi = t1_get_board_info(ent->driver_data);
-
-	for (i = 0; i < bi->port_number; ++i) {
-		struct net_device *netdev;
-
-		netdev = alloc_etherdev(adapter ? 0 : sizeof(*adapter));
-		if (!netdev) {
-			err = -ENOMEM;
-			goto out_free_dev;
-		}
-
-		SET_NETDEV_DEV(netdev, &pdev->dev);
-
-		if (!adapter) {
-			adapter = netdev_priv(netdev);
-			adapter->pdev = pdev;
-			adapter->port[0].dev = netdev;  /* so we don't leak it */
-
-			adapter->regs = ioremap(mmio_start, mmio_len);
-			if (!adapter->regs) {
-				pr_err("%s: cannot map device registers\n",
-				       pci_name(pdev));
-				err = -ENOMEM;
-				goto out_free_dev;
-			}
-
-			if (t1_get_board_rev(adapter, bi, &adapter->params)) {
-				err = -ENODEV;	  /* Can't handle this chip rev */
-				goto out_free_dev;
-			}
-
-			adapter->name = pci_name(pdev);
-			adapter->msg_enable = dflt_msg_enable;
-			adapter->mmio_len = mmio_len;
-
-			spin_lock_init(&adapter->tpi_lock);
-			spin_lock_init(&adapter->work_lock);
-			spin_lock_init(&adapter->async_lock);
-			spin_lock_init(&adapter->mac_lock);
-
-			INIT_WORK(&adapter->ext_intr_handler_task,
-				  ext_intr_task);
-			INIT_DELAYED_WORK(&adapter->stats_update_task,
-					  mac_stats_task);
-
-			pci_set_drvdata(pdev, netdev);
-		}
-
-		pi = &adapter->port[i];
-		pi->dev = netdev;
-		netif_carrier_off(netdev);
-		netdev->irq = pdev->irq;
-		netdev->if_port = i;
-		netdev->mem_start = mmio_start;
-		netdev->mem_end = mmio_start + mmio_len - 1;
-		netdev->ml_priv = adapter;
-		netdev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM |
-			NETIF_F_RXCSUM;
-		netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM |
-			NETIF_F_RXCSUM | NETIF_F_LLTX;
-
-		if (pci_using_dac)
-			netdev->features |= NETIF_F_HIGHDMA;
-		if (vlan_tso_capable(adapter)) {
-			netdev->features |=
-				NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-			netdev->hw_features |= NETIF_F_HW_VLAN_RX;
-
-			/* T204: disable TSO */
-			if (!(is_T2(adapter)) || bi->port_number != 4) {
-				netdev->hw_features |= NETIF_F_TSO;
-				netdev->features |= NETIF_F_TSO;
-			}
-		}
-
-		netdev->netdev_ops = &cxgb_netdev_ops;
-		netdev->hard_header_len += (netdev->hw_features & NETIF_F_TSO) ?
-			sizeof(struct cpl_tx_pkt_lso) : sizeof(struct cpl_tx_pkt);
-
-		netif_napi_add(netdev, &adapter->napi, t1_poll, 64);
-
-		SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
-	}
-
-	if (t1_init_sw_modules(adapter, bi) < 0) {
-		err = -ENODEV;
-		goto out_free_dev;
-	}
-
-	/*
-	 * The card is now ready to go.  If any errors occur during device
-	 * registration we do not fail the whole card but rather proceed only
-	 * with the ports we manage to register successfully.  However we must
-	 * register at least one net device.
-	 */
-	for (i = 0; i < bi->port_number; ++i) {
-		err = register_netdev(adapter->port[i].dev);
-		if (err)
-			pr_warning("%s: cannot register net device %s, skipping\n",
-				   pci_name(pdev), adapter->port[i].dev->name);
-		else {
-			/*
-			 * Change the name we use for messages to the name of
-			 * the first successfully registered interface.
-			 */
-			if (!adapter->registered_device_map)
-				adapter->name = adapter->port[i].dev->name;
-
-			__set_bit(i, &adapter->registered_device_map);
-		}
-	}
-	if (!adapter->registered_device_map) {
-		pr_err("%s: could not register any net devices\n",
-		       pci_name(pdev));
-		goto out_release_adapter_res;
-	}
-
-	printk(KERN_INFO "%s: %s (rev %d), %s %dMHz/%d-bit\n", adapter->name,
-	       bi->desc, adapter->params.chip_revision,
-	       adapter->params.pci.is_pcix ? "PCIX" : "PCI",
-	       adapter->params.pci.speed, adapter->params.pci.width);
-
-	/*
-	 * Set the T1B ASIC and memory clocks.
-	 */
-	if (t1powersave)
-		adapter->t1powersave = LCLOCK;	/* HW default is powersave mode. */
-	else
-		adapter->t1powersave = HCLOCK;
-	if (t1_is_T1B(adapter))
-		t1_clock(adapter, t1powersave);
-
-	return 0;
-
-out_release_adapter_res:
-	t1_free_sw_modules(adapter);
-out_free_dev:
-	if (adapter) {
-		if (adapter->regs)
-			iounmap(adapter->regs);
-		for (i = bi->port_number - 1; i >= 0; --i)
-			if (adapter->port[i].dev)
-				free_netdev(adapter->port[i].dev);
-	}
-	pci_release_regions(pdev);
-out_disable_pdev:
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-	return err;
-}
-
-static void bit_bang(struct adapter *adapter, int bitdata, int nbits)
-{
-	int data;
-	int i;
-	u32 val;
-
-	enum {
-		S_CLOCK = 1 << 3,
-		S_DATA = 1 << 4
-	};
-
-	for (i = (nbits - 1); i > -1; i--) {
-
-		udelay(50);
-
-		data = ((bitdata >> i) & 0x1);
-		__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-
-		if (data)
-			val |= S_DATA;
-		else
-			val &= ~S_DATA;
-
-		udelay(50);
-
-		/* Set SCLOCK low */
-		val &= ~S_CLOCK;
-		__t1_tpi_write(adapter, A_ELMER0_GPO, val);
-
-		udelay(50);
-
-		/* Write SCLOCK high */
-		val |= S_CLOCK;
-		__t1_tpi_write(adapter, A_ELMER0_GPO, val);
-
-	}
-}
-
-static int t1_clock(struct adapter *adapter, int mode)
-{
-	u32 val;
-	int M_CORE_VAL;
-	int M_MEM_VAL;
-
-	enum {
-		M_CORE_BITS	= 9,
-		T_CORE_VAL	= 0,
-		T_CORE_BITS	= 2,
-		N_CORE_VAL	= 0,
-		N_CORE_BITS	= 2,
-		M_MEM_BITS	= 9,
-		T_MEM_VAL	= 0,
-		T_MEM_BITS	= 2,
-		N_MEM_VAL	= 0,
-		N_MEM_BITS	= 2,
-		NP_LOAD		= 1 << 17,
-		S_LOAD_MEM	= 1 << 5,
-		S_LOAD_CORE	= 1 << 6,
-		S_CLOCK		= 1 << 3
-	};
-
-	if (!t1_is_T1B(adapter))
-		return -ENODEV;	/* Can't re-clock this chip. */
-
-	if (mode & 2)
-		return 0;	/* show current mode. */
-
-	if ((adapter->t1powersave & 1) == (mode & 1))
-		return -EALREADY;	/* ASIC already running in mode. */
-
-	if ((mode & 1) == HCLOCK) {
-		M_CORE_VAL = 0x14;
-		M_MEM_VAL = 0x18;
-		adapter->t1powersave = HCLOCK;	/* overclock */
-	} else {
-		M_CORE_VAL = 0xe;
-		M_MEM_VAL = 0x10;
-		adapter->t1powersave = LCLOCK;	/* underclock */
-	}
-
-	/* Don't interrupt this serial stream! */
-	spin_lock(&adapter->tpi_lock);
-
-	/* Initialize for ASIC core */
-	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-	val |= NP_LOAD;
-	udelay(50);
-	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
-	udelay(50);
-	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-	val &= ~S_LOAD_CORE;
-	val &= ~S_CLOCK;
-	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
-	udelay(50);
-
-	/* Serial program the ASIC clock synthesizer */
-	bit_bang(adapter, T_CORE_VAL, T_CORE_BITS);
-	bit_bang(adapter, N_CORE_VAL, N_CORE_BITS);
-	bit_bang(adapter, M_CORE_VAL, M_CORE_BITS);
-	udelay(50);
-
-	/* Finish ASIC core */
-	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-	val |= S_LOAD_CORE;
-	udelay(50);
-	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
-	udelay(50);
-	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-	val &= ~S_LOAD_CORE;
-	udelay(50);
-	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
-	udelay(50);
-
-	/* Initialize for memory */
-	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-	val |= NP_LOAD;
-	udelay(50);
-	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
-	udelay(50);
-	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-	val &= ~S_LOAD_MEM;
-	val &= ~S_CLOCK;
-	udelay(50);
-	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
-	udelay(50);
-
-	/* Serial program the memory clock synthesizer */
-	bit_bang(adapter, T_MEM_VAL, T_MEM_BITS);
-	bit_bang(adapter, N_MEM_VAL, N_MEM_BITS);
-	bit_bang(adapter, M_MEM_VAL, M_MEM_BITS);
-	udelay(50);
-
-	/* Finish memory */
-	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-	val |= S_LOAD_MEM;
-	udelay(50);
-	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
-	udelay(50);
-	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-	val &= ~S_LOAD_MEM;
-	udelay(50);
-	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
-
-	spin_unlock(&adapter->tpi_lock);
-
-	return 0;
-}
-
-static inline void t1_sw_reset(struct pci_dev *pdev)
-{
-	pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 3);
-	pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 0);
-}
-
-static void __devexit remove_one(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct adapter *adapter = dev->ml_priv;
-	int i;
-
-	for_each_port(adapter, i) {
-		if (test_bit(i, &adapter->registered_device_map))
-			unregister_netdev(adapter->port[i].dev);
-	}
-
-	t1_free_sw_modules(adapter);
-	iounmap(adapter->regs);
-
-	while (--i >= 0) {
-		if (adapter->port[i].dev)
-			free_netdev(adapter->port[i].dev);
-	}
-
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-	t1_sw_reset(pdev);
-}
-
-static struct pci_driver driver = {
-	.name     = DRV_NAME,
-	.id_table = t1_pci_tbl,
-	.probe    = init_one,
-	.remove   = __devexit_p(remove_one),
-};
-
-static int __init t1_init_module(void)
-{
-	return pci_register_driver(&driver);
-}
-
-static void __exit t1_cleanup_module(void)
-{
-	pci_unregister_driver(&driver);
-}
-
-module_init(t1_init_module);
-module_exit(t1_cleanup_module);
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/elmer0.h linux-libre-3.2-gnu/drivers/net/chelsio/elmer0.h
--- linux-libre-3.1-gnu/drivers/net/chelsio/elmer0.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/elmer0.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,158 +0,0 @@
-/*****************************************************************************
- *                                                                           *
- * File: elmer0.h                                                            *
- * $Revision: 1.6 $                                                          *
- * $Date: 2005/06/21 22:49:43 $                                              *
- * Description:                                                              *
- *  part of the Chelsio 10Gb Ethernet 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.                                *
- *                                                                           *
- * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
- *                                                                           *
- * http://www.chelsio.com                                                    *
- *                                                                           *
- * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
- * All rights reserved.                                                      *
- *                                                                           *
- * Maintainers: maintainers@chelsio.com                                      *
- *                                                                           *
- * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
- *          Tina Yang               <tainay@chelsio.com>                     *
- *          Felix Marti             <felix@chelsio.com>                      *
- *          Scott Bardone           <sbardone@chelsio.com>                   *
- *          Kurt Ottaway            <kottaway@chelsio.com>                   *
- *          Frank DiMambro          <frank@chelsio.com>                      *
- *                                                                           *
- * History:                                                                  *
- *                                                                           *
- ****************************************************************************/
-
-#ifndef _CXGB_ELMER0_H_
-#define _CXGB_ELMER0_H_
-
-/* ELMER0 flavors */
-enum {
-	ELMER0_XC2S300E_6FT256_C,
-	ELMER0_XC2S100E_6TQ144_C
-};
-
-/* ELMER0 registers */
-#define A_ELMER0_VERSION	0x100000
-#define A_ELMER0_PHY_CFG	0x100004
-#define A_ELMER0_INT_ENABLE	0x100008
-#define A_ELMER0_INT_CAUSE	0x10000c
-#define A_ELMER0_GPI_CFG	0x100010
-#define A_ELMER0_GPI_STAT	0x100014
-#define A_ELMER0_GPO		0x100018
-#define A_ELMER0_PORT0_MI1_CFG	0x400000
-
-#define S_MI1_MDI_ENABLE    0
-#define V_MI1_MDI_ENABLE(x) ((x) << S_MI1_MDI_ENABLE)
-#define F_MI1_MDI_ENABLE    V_MI1_MDI_ENABLE(1U)
-
-#define S_MI1_MDI_INVERT    1
-#define V_MI1_MDI_INVERT(x) ((x) << S_MI1_MDI_INVERT)
-#define F_MI1_MDI_INVERT    V_MI1_MDI_INVERT(1U)
-
-#define S_MI1_PREAMBLE_ENABLE    2
-#define V_MI1_PREAMBLE_ENABLE(x) ((x) << S_MI1_PREAMBLE_ENABLE)
-#define F_MI1_PREAMBLE_ENABLE    V_MI1_PREAMBLE_ENABLE(1U)
-
-#define S_MI1_SOF    3
-#define M_MI1_SOF    0x3
-#define V_MI1_SOF(x) ((x) << S_MI1_SOF)
-#define G_MI1_SOF(x) (((x) >> S_MI1_SOF) & M_MI1_SOF)
-
-#define S_MI1_CLK_DIV    5
-#define M_MI1_CLK_DIV    0xff
-#define V_MI1_CLK_DIV(x) ((x) << S_MI1_CLK_DIV)
-#define G_MI1_CLK_DIV(x) (((x) >> S_MI1_CLK_DIV) & M_MI1_CLK_DIV)
-
-#define A_ELMER0_PORT0_MI1_ADDR 0x400004
-
-#define S_MI1_REG_ADDR    0
-#define M_MI1_REG_ADDR    0x1f
-#define V_MI1_REG_ADDR(x) ((x) << S_MI1_REG_ADDR)
-#define G_MI1_REG_ADDR(x) (((x) >> S_MI1_REG_ADDR) & M_MI1_REG_ADDR)
-
-#define S_MI1_PHY_ADDR    5
-#define M_MI1_PHY_ADDR    0x1f
-#define V_MI1_PHY_ADDR(x) ((x) << S_MI1_PHY_ADDR)
-#define G_MI1_PHY_ADDR(x) (((x) >> S_MI1_PHY_ADDR) & M_MI1_PHY_ADDR)
-
-#define A_ELMER0_PORT0_MI1_DATA 0x400008
-
-#define S_MI1_DATA    0
-#define M_MI1_DATA    0xffff
-#define V_MI1_DATA(x) ((x) << S_MI1_DATA)
-#define G_MI1_DATA(x) (((x) >> S_MI1_DATA) & M_MI1_DATA)
-
-#define A_ELMER0_PORT0_MI1_OP 0x40000c
-
-#define S_MI1_OP    0
-#define M_MI1_OP    0x3
-#define V_MI1_OP(x) ((x) << S_MI1_OP)
-#define G_MI1_OP(x) (((x) >> S_MI1_OP) & M_MI1_OP)
-
-#define S_MI1_ADDR_AUTOINC    2
-#define V_MI1_ADDR_AUTOINC(x) ((x) << S_MI1_ADDR_AUTOINC)
-#define F_MI1_ADDR_AUTOINC    V_MI1_ADDR_AUTOINC(1U)
-
-#define S_MI1_OP_BUSY    31
-#define V_MI1_OP_BUSY(x) ((x) << S_MI1_OP_BUSY)
-#define F_MI1_OP_BUSY    V_MI1_OP_BUSY(1U)
-
-#define A_ELMER0_PORT1_MI1_CFG	0x500000
-#define A_ELMER0_PORT1_MI1_ADDR	0x500004
-#define A_ELMER0_PORT1_MI1_DATA	0x500008
-#define A_ELMER0_PORT1_MI1_OP	0x50000c
-#define A_ELMER0_PORT2_MI1_CFG	0x600000
-#define A_ELMER0_PORT2_MI1_ADDR	0x600004
-#define A_ELMER0_PORT2_MI1_DATA	0x600008
-#define A_ELMER0_PORT2_MI1_OP	0x60000c
-#define A_ELMER0_PORT3_MI1_CFG	0x700000
-#define A_ELMER0_PORT3_MI1_ADDR	0x700004
-#define A_ELMER0_PORT3_MI1_DATA	0x700008
-#define A_ELMER0_PORT3_MI1_OP	0x70000c
-
-/* Simple bit definition for GPI and GP0 registers. */
-#define     ELMER0_GP_BIT0              0x0001
-#define     ELMER0_GP_BIT1              0x0002
-#define     ELMER0_GP_BIT2              0x0004
-#define     ELMER0_GP_BIT3              0x0008
-#define     ELMER0_GP_BIT4              0x0010
-#define     ELMER0_GP_BIT5              0x0020
-#define     ELMER0_GP_BIT6              0x0040
-#define     ELMER0_GP_BIT7              0x0080
-#define     ELMER0_GP_BIT8              0x0100
-#define     ELMER0_GP_BIT9              0x0200
-#define     ELMER0_GP_BIT10             0x0400
-#define     ELMER0_GP_BIT11             0x0800
-#define     ELMER0_GP_BIT12             0x1000
-#define     ELMER0_GP_BIT13             0x2000
-#define     ELMER0_GP_BIT14             0x4000
-#define     ELMER0_GP_BIT15             0x8000
-#define     ELMER0_GP_BIT16             0x10000
-#define     ELMER0_GP_BIT17             0x20000
-#define     ELMER0_GP_BIT18             0x40000
-#define     ELMER0_GP_BIT19             0x80000
-
-#define MI1_OP_DIRECT_WRITE 1
-#define MI1_OP_DIRECT_READ  2
-
-#define MI1_OP_INDIRECT_ADDRESS  0
-#define MI1_OP_INDIRECT_WRITE    1
-#define MI1_OP_INDIRECT_READ_INC 2
-#define MI1_OP_INDIRECT_READ     3
-
-#endif /* _CXGB_ELMER0_H_ */
-
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/espi.c linux-libre-3.2-gnu/drivers/net/chelsio/espi.c
--- linux-libre-3.1-gnu/drivers/net/chelsio/espi.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/espi.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,373 +0,0 @@
-/*****************************************************************************
- *                                                                           *
- * File: espi.c                                                              *
- * $Revision: 1.14 $                                                         *
- * $Date: 2005/05/14 00:59:32 $                                              *
- * Description:                                                              *
- *  Ethernet SPI functionality.                                              *
- *  part of the Chelsio 10Gb Ethernet 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.                                *
- *                                                                           *
- * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
- *                                                                           *
- * http://www.chelsio.com                                                    *
- *                                                                           *
- * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
- * All rights reserved.                                                      *
- *                                                                           *
- * Maintainers: maintainers@chelsio.com                                      *
- *                                                                           *
- * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
- *          Tina Yang               <tainay@chelsio.com>                     *
- *          Felix Marti             <felix@chelsio.com>                      *
- *          Scott Bardone           <sbardone@chelsio.com>                   *
- *          Kurt Ottaway            <kottaway@chelsio.com>                   *
- *          Frank DiMambro          <frank@chelsio.com>                      *
- *                                                                           *
- * History:                                                                  *
- *                                                                           *
- ****************************************************************************/
-
-#include "common.h"
-#include "regs.h"
-#include "espi.h"
-
-struct peespi {
-	adapter_t *adapter;
-	struct espi_intr_counts intr_cnt;
-	u32 misc_ctrl;
-	spinlock_t lock;
-};
-
-#define ESPI_INTR_MASK (F_DIP4ERR | F_RXDROP | F_TXDROP | F_RXOVERFLOW | \
-			F_RAMPARITYERR | F_DIP2PARITYERR)
-#define MON_MASK  (V_MONITORED_PORT_NUM(3) | F_MONITORED_DIRECTION \
-		   | F_MONITORED_INTERFACE)
-
-#define TRICN_CNFG 14
-#define TRICN_CMD_READ  0x11
-#define TRICN_CMD_WRITE 0x21
-#define TRICN_CMD_ATTEMPTS 10
-
-static int tricn_write(adapter_t *adapter, int bundle_addr, int module_addr,
-		       int ch_addr, int reg_offset, u32 wr_data)
-{
-	int busy, attempts = TRICN_CMD_ATTEMPTS;
-
-	writel(V_WRITE_DATA(wr_data) |
-	       V_REGISTER_OFFSET(reg_offset) |
-	       V_CHANNEL_ADDR(ch_addr) | V_MODULE_ADDR(module_addr) |
-	       V_BUNDLE_ADDR(bundle_addr) |
-	       V_SPI4_COMMAND(TRICN_CMD_WRITE),
-	       adapter->regs + A_ESPI_CMD_ADDR);
-	writel(0, adapter->regs + A_ESPI_GOSTAT);
-
-	do {
-		busy = readl(adapter->regs + A_ESPI_GOSTAT) & F_ESPI_CMD_BUSY;
-	} while (busy && --attempts);
-
-	if (busy)
-		pr_err("%s: TRICN write timed out\n", adapter->name);
-
-	return busy;
-}
-
-static int tricn_init(adapter_t *adapter)
-{
-	int i, sme = 1;
-
-	if (!(readl(adapter->regs + A_ESPI_RX_RESET)  & F_RX_CLK_STATUS)) {
-		pr_err("%s: ESPI clock not ready\n", adapter->name);
-		return -1;
-	}
-
-	writel(F_ESPI_RX_CORE_RST, adapter->regs + A_ESPI_RX_RESET);
-
-	if (sme) {
-		tricn_write(adapter, 0, 0, 0, TRICN_CNFG, 0x81);
-		tricn_write(adapter, 0, 1, 0, TRICN_CNFG, 0x81);
-		tricn_write(adapter, 0, 2, 0, TRICN_CNFG, 0x81);
-	}
-	for (i = 1; i <= 8; i++)
-		tricn_write(adapter, 0, 0, i, TRICN_CNFG, 0xf1);
-	for (i = 1; i <= 2; i++)
-		tricn_write(adapter, 0, 1, i, TRICN_CNFG, 0xf1);
-	for (i = 1; i <= 3; i++)
-		tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1);
-	tricn_write(adapter, 0, 2, 4, TRICN_CNFG, 0xf1);
-	tricn_write(adapter, 0, 2, 5, TRICN_CNFG, 0xe1);
-	tricn_write(adapter, 0, 2, 6, TRICN_CNFG, 0xf1);
-	tricn_write(adapter, 0, 2, 7, TRICN_CNFG, 0x80);
-	tricn_write(adapter, 0, 2, 8, TRICN_CNFG, 0xf1);
-
-	writel(F_ESPI_RX_CORE_RST | F_ESPI_RX_LNK_RST,
-	       adapter->regs + A_ESPI_RX_RESET);
-
-	return 0;
-}
-
-void t1_espi_intr_enable(struct peespi *espi)
-{
-	u32 enable, pl_intr = readl(espi->adapter->regs + A_PL_ENABLE);
-
-	/*
-	 * Cannot enable ESPI interrupts on T1B because HW asserts the
-	 * interrupt incorrectly, namely the driver gets ESPI interrupts
-	 * but no data is actually dropped (can verify this reading the ESPI
-	 * drop registers).  Also, once the ESPI interrupt is asserted it
-	 * cannot be cleared (HW bug).
-	 */
-	enable = t1_is_T1B(espi->adapter) ? 0 : ESPI_INTR_MASK;
-	writel(enable, espi->adapter->regs + A_ESPI_INTR_ENABLE);
-	writel(pl_intr | F_PL_INTR_ESPI, espi->adapter->regs + A_PL_ENABLE);
-}
-
-void t1_espi_intr_clear(struct peespi *espi)
-{
-	readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT);
-	writel(0xffffffff, espi->adapter->regs + A_ESPI_INTR_STATUS);
-	writel(F_PL_INTR_ESPI, espi->adapter->regs + A_PL_CAUSE);
-}
-
-void t1_espi_intr_disable(struct peespi *espi)
-{
-	u32 pl_intr = readl(espi->adapter->regs + A_PL_ENABLE);
-
-	writel(0, espi->adapter->regs + A_ESPI_INTR_ENABLE);
-	writel(pl_intr & ~F_PL_INTR_ESPI, espi->adapter->regs + A_PL_ENABLE);
-}
-
-int t1_espi_intr_handler(struct peespi *espi)
-{
-	u32 status = readl(espi->adapter->regs + A_ESPI_INTR_STATUS);
-
-	if (status & F_DIP4ERR)
-		espi->intr_cnt.DIP4_err++;
-	if (status & F_RXDROP)
-		espi->intr_cnt.rx_drops++;
-	if (status & F_TXDROP)
-		espi->intr_cnt.tx_drops++;
-	if (status & F_RXOVERFLOW)
-		espi->intr_cnt.rx_ovflw++;
-	if (status & F_RAMPARITYERR)
-		espi->intr_cnt.parity_err++;
-	if (status & F_DIP2PARITYERR) {
-		espi->intr_cnt.DIP2_parity_err++;
-
-		/*
-		 * Must read the error count to clear the interrupt
-		 * that it causes.
-		 */
-		readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT);
-	}
-
-	/*
-	 * For T1B we need to write 1 to clear ESPI interrupts.  For T2+ we
-	 * write the status as is.
-	 */
-	if (status && t1_is_T1B(espi->adapter))
-		status = 1;
-	writel(status, espi->adapter->regs + A_ESPI_INTR_STATUS);
-	return 0;
-}
-
-const struct espi_intr_counts *t1_espi_get_intr_counts(struct peespi *espi)
-{
-	return &espi->intr_cnt;
-}
-
-static void espi_setup_for_pm3393(adapter_t *adapter)
-{
-	u32 wmark = t1_is_T1B(adapter) ? 0x4000 : 0x3200;
-
-	writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN0);
-	writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN1);
-	writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN2);
-	writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN3);
-	writel(0x100, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
-	writel(wmark, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
-	writel(3, adapter->regs + A_ESPI_CALENDAR_LENGTH);
-	writel(0x08000008, adapter->regs + A_ESPI_TRAIN);
-	writel(V_RX_NPORTS(1) | V_TX_NPORTS(1), adapter->regs + A_PORT_CONFIG);
-}
-
-static void espi_setup_for_vsc7321(adapter_t *adapter)
-{
-	writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN0);
-	writel(0x1f401f4, adapter->regs + A_ESPI_SCH_TOKEN1);
-	writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN2);
-	writel(0xa00, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
-	writel(0x1ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
-	writel(1, adapter->regs + A_ESPI_CALENDAR_LENGTH);
-	writel(V_RX_NPORTS(4) | V_TX_NPORTS(4), adapter->regs + A_PORT_CONFIG);
-
-	writel(0x08000008, adapter->regs + A_ESPI_TRAIN);
-}
-
-/*
- * Note that T1B requires at least 2 ports for IXF1010 due to a HW bug.
- */
-static void espi_setup_for_ixf1010(adapter_t *adapter, int nports)
-{
-	writel(1, adapter->regs + A_ESPI_CALENDAR_LENGTH);
-	if (nports == 4) {
-		if (is_T2(adapter)) {
-			writel(0xf00, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
-			writel(0x3c0, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
-		} else {
-			writel(0x7ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
-			writel(0x1ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
-		}
-	} else {
-		writel(0x1fff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK);
-		writel(0x7ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK);
-	}
-	writel(V_RX_NPORTS(nports) | V_TX_NPORTS(nports), adapter->regs + A_PORT_CONFIG);
-
-}
-
-int t1_espi_init(struct peespi *espi, int mac_type, int nports)
-{
-	u32 status_enable_extra = 0;
-	adapter_t *adapter = espi->adapter;
-
-	/* Disable ESPI training.  MACs that can handle it enable it below. */
-	writel(0, adapter->regs + A_ESPI_TRAIN);
-
-	if (is_T2(adapter)) {
-		writel(V_OUT_OF_SYNC_COUNT(4) |
-		       V_DIP2_PARITY_ERR_THRES(3) |
-		       V_DIP4_THRES(1), adapter->regs + A_ESPI_MISC_CONTROL);
-		writel(nports == 4 ? 0x200040 : 0x1000080,
-		       adapter->regs + A_ESPI_MAXBURST1_MAXBURST2);
-	} else
-		writel(0x800100, adapter->regs + A_ESPI_MAXBURST1_MAXBURST2);
-
-	if (mac_type == CHBT_MAC_PM3393)
-		espi_setup_for_pm3393(adapter);
-	else if (mac_type == CHBT_MAC_VSC7321)
-		espi_setup_for_vsc7321(adapter);
-	else if (mac_type == CHBT_MAC_IXF1010) {
-		status_enable_extra = F_INTEL1010MODE;
-		espi_setup_for_ixf1010(adapter, nports);
-	} else
-		return -1;
-
-	writel(status_enable_extra | F_RXSTATUSENABLE,
-	       adapter->regs + A_ESPI_FIFO_STATUS_ENABLE);
-
-	if (is_T2(adapter)) {
-		tricn_init(adapter);
-		/*
-		 * Always position the control at the 1st port egress IN
-		 * (sop,eop) counter to reduce PIOs for T/N210 workaround.
-		 */
-		espi->misc_ctrl = readl(adapter->regs + A_ESPI_MISC_CONTROL);
-		espi->misc_ctrl &= ~MON_MASK;
-		espi->misc_ctrl |= F_MONITORED_DIRECTION;
-		if (adapter->params.nports == 1)
-			espi->misc_ctrl |= F_MONITORED_INTERFACE;
-		writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
-		spin_lock_init(&espi->lock);
-	}
-
-	return 0;
-}
-
-void t1_espi_destroy(struct peespi *espi)
-{
-	kfree(espi);
-}
-
-struct peespi *t1_espi_create(adapter_t *adapter)
-{
-	struct peespi *espi = kzalloc(sizeof(*espi), GFP_KERNEL);
-
-	if (espi)
-		espi->adapter = adapter;
-	return espi;
-}
-
-#if 0
-void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val)
-{
-	struct peespi *espi = adapter->espi;
-
-	if (!is_T2(adapter))
-		return;
-	spin_lock(&espi->lock);
-	espi->misc_ctrl = (val & ~MON_MASK) |
-			  (espi->misc_ctrl & MON_MASK);
-	writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
-	spin_unlock(&espi->lock);
-}
-#endif  /*  0  */
-
-u32 t1_espi_get_mon(adapter_t *adapter, u32 addr, u8 wait)
-{
-	struct peespi *espi = adapter->espi;
-	u32 sel;
-
-	if (!is_T2(adapter))
-		return 0;
-
-	sel = V_MONITORED_PORT_NUM((addr & 0x3c) >> 2);
-	if (!wait) {
-		if (!spin_trylock(&espi->lock))
-			return 0;
-	} else
-		spin_lock(&espi->lock);
-
-	if ((sel != (espi->misc_ctrl & MON_MASK))) {
-		writel(((espi->misc_ctrl & ~MON_MASK) | sel),
-		       adapter->regs + A_ESPI_MISC_CONTROL);
-		sel = readl(adapter->regs + A_ESPI_SCH_TOKEN3);
-		writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
-	} else
-		sel = readl(adapter->regs + A_ESPI_SCH_TOKEN3);
-	spin_unlock(&espi->lock);
-	return sel;
-}
-
-/*
- * This function is for T204 only.
- * compare with t1_espi_get_mon(), it reads espiInTxSop[0 ~ 3] in
- * one shot, since there is no per port counter on the out side.
- */
-int t1_espi_get_mon_t204(adapter_t *adapter, u32 *valp, u8 wait)
-{
-	struct peespi *espi = adapter->espi;
-	u8 i, nport = (u8)adapter->params.nports;
-
-	if (!wait) {
-		if (!spin_trylock(&espi->lock))
-			return -1;
-	} else
-		spin_lock(&espi->lock);
-
-	if ((espi->misc_ctrl & MON_MASK) != F_MONITORED_DIRECTION) {
-		espi->misc_ctrl = (espi->misc_ctrl & ~MON_MASK) |
-					F_MONITORED_DIRECTION;
-		writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
-	}
-	for (i = 0 ; i < nport; i++, valp++) {
-		if (i) {
-			writel(espi->misc_ctrl | V_MONITORED_PORT_NUM(i),
-			       adapter->regs + A_ESPI_MISC_CONTROL);
-		}
-		*valp = readl(adapter->regs + A_ESPI_SCH_TOKEN3);
-	}
-
-	writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL);
-	spin_unlock(&espi->lock);
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/espi.h linux-libre-3.2-gnu/drivers/net/chelsio/espi.h
--- linux-libre-3.1-gnu/drivers/net/chelsio/espi.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/espi.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/*****************************************************************************
- *                                                                           *
- * File: espi.h                                                              *
- * $Revision: 1.7 $                                                          *
- * $Date: 2005/06/21 18:29:47 $                                              *
- * Description:                                                              *
- *  part of the Chelsio 10Gb Ethernet 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.                                *
- *                                                                           *
- * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
- *                                                                           *
- * http://www.chelsio.com                                                    *
- *                                                                           *
- * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
- * All rights reserved.                                                      *
- *                                                                           *
- * Maintainers: maintainers@chelsio.com                                      *
- *                                                                           *
- * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
- *          Tina Yang               <tainay@chelsio.com>                     *
- *          Felix Marti             <felix@chelsio.com>                      *
- *          Scott Bardone           <sbardone@chelsio.com>                   *
- *          Kurt Ottaway            <kottaway@chelsio.com>                   *
- *          Frank DiMambro          <frank@chelsio.com>                      *
- *                                                                           *
- * History:                                                                  *
- *                                                                           *
- ****************************************************************************/
-
-#ifndef _CXGB_ESPI_H_
-#define _CXGB_ESPI_H_
-
-#include "common.h"
-
-struct espi_intr_counts {
-	unsigned int DIP4_err;
-	unsigned int rx_drops;
-	unsigned int tx_drops;
-	unsigned int rx_ovflw;
-	unsigned int parity_err;
-	unsigned int DIP2_parity_err;
-};
-
-struct peespi;
-
-struct peespi *t1_espi_create(adapter_t *adapter);
-void t1_espi_destroy(struct peespi *espi);
-int t1_espi_init(struct peespi *espi, int mac_type, int nports);
-
-void t1_espi_intr_enable(struct peespi *);
-void t1_espi_intr_clear(struct peespi *);
-void t1_espi_intr_disable(struct peespi *);
-int t1_espi_intr_handler(struct peespi *);
-const struct espi_intr_counts *t1_espi_get_intr_counts(struct peespi *espi);
-
-u32 t1_espi_get_mon(adapter_t *adapter, u32 addr, u8 wait);
-int t1_espi_get_mon_t204(adapter_t *, u32 *, u8);
-
-#endif /* _CXGB_ESPI_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/fpga_defs.h linux-libre-3.2-gnu/drivers/net/chelsio/fpga_defs.h
--- linux-libre-3.1-gnu/drivers/net/chelsio/fpga_defs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/fpga_defs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,232 +0,0 @@
-/* $Date: 2005/03/07 23:59:05 $ $RCSfile: fpga_defs.h,v $ $Revision: 1.4 $ */
-
-/*
- * FPGA specific definitions
- */
-
-#ifndef __CHELSIO_FPGA_DEFS_H__
-#define __CHELSIO_FPGA_DEFS_H__
-
-#define FPGA_PCIX_ADDR_VERSION               0xA08
-#define FPGA_PCIX_ADDR_STAT                  0xA0C
-
-/* FPGA master interrupt Cause/Enable bits */
-#define FPGA_PCIX_INTERRUPT_SGE_ERROR        0x1
-#define FPGA_PCIX_INTERRUPT_SGE_DATA         0x2
-#define FPGA_PCIX_INTERRUPT_TP               0x4
-#define FPGA_PCIX_INTERRUPT_MC3              0x8
-#define FPGA_PCIX_INTERRUPT_GMAC             0x10
-#define FPGA_PCIX_INTERRUPT_PCIX             0x20
-
-/* TP interrupt register addresses */
-#define FPGA_TP_ADDR_INTERRUPT_ENABLE        0xA10
-#define FPGA_TP_ADDR_INTERRUPT_CAUSE         0xA14
-#define FPGA_TP_ADDR_VERSION                 0xA18
-
-/* TP interrupt Cause/Enable bits */
-#define FPGA_TP_INTERRUPT_MC4                0x1
-#define FPGA_TP_INTERRUPT_MC5                0x2
-
-/*
- * PM interrupt register addresses
- */
-#define FPGA_MC3_REG_INTRENABLE              0xA20
-#define FPGA_MC3_REG_INTRCAUSE               0xA24
-#define FPGA_MC3_REG_VERSION                 0xA28
-
-/*
- * GMAC interrupt register addresses
- */
-#define FPGA_GMAC_ADDR_INTERRUPT_ENABLE      0xA30
-#define FPGA_GMAC_ADDR_INTERRUPT_CAUSE       0xA34
-#define FPGA_GMAC_ADDR_VERSION               0xA38
-
-/* GMAC Cause/Enable bits */
-#define FPGA_GMAC_INTERRUPT_PORT0            0x1
-#define FPGA_GMAC_INTERRUPT_PORT1            0x2
-#define FPGA_GMAC_INTERRUPT_PORT2            0x4
-#define FPGA_GMAC_INTERRUPT_PORT3            0x8
-
-/* MI0 registers */
-#define A_MI0_CLK 0xb00
-
-#define S_MI0_CLK_DIV    0
-#define M_MI0_CLK_DIV    0xff
-#define V_MI0_CLK_DIV(x) ((x) << S_MI0_CLK_DIV)
-#define G_MI0_CLK_DIV(x) (((x) >> S_MI0_CLK_DIV) & M_MI0_CLK_DIV)
-
-#define S_MI0_CLK_CNT    8
-#define M_MI0_CLK_CNT    0xff
-#define V_MI0_CLK_CNT(x) ((x) << S_MI0_CLK_CNT)
-#define G_MI0_CLK_CNT(x) (((x) >> S_MI0_CLK_CNT) & M_MI0_CLK_CNT)
-
-#define A_MI0_CSR 0xb04
-
-#define S_MI0_CSR_POLL    0
-#define V_MI0_CSR_POLL(x) ((x) << S_MI0_CSR_POLL)
-#define F_MI0_CSR_POLL    V_MI0_CSR_POLL(1U)
-
-#define S_MI0_PREAMBLE    1
-#define V_MI0_PREAMBLE(x) ((x) << S_MI0_PREAMBLE)
-#define F_MI0_PREAMBLE    V_MI0_PREAMBLE(1U)
-
-#define S_MI0_INTR_ENABLE    2
-#define V_MI0_INTR_ENABLE(x) ((x) << S_MI0_INTR_ENABLE)
-#define F_MI0_INTR_ENABLE    V_MI0_INTR_ENABLE(1U)
-
-#define S_MI0_BUSY    3
-#define V_MI0_BUSY(x) ((x) << S_MI0_BUSY)
-#define F_MI0_BUSY    V_MI0_BUSY(1U)
-
-#define S_MI0_MDIO    4
-#define V_MI0_MDIO(x) ((x) << S_MI0_MDIO)
-#define F_MI0_MDIO    V_MI0_MDIO(1U)
-
-#define A_MI0_ADDR 0xb08
-
-#define S_MI0_PHY_REG_ADDR    0
-#define M_MI0_PHY_REG_ADDR    0x1f
-#define V_MI0_PHY_REG_ADDR(x) ((x) << S_MI0_PHY_REG_ADDR)
-#define G_MI0_PHY_REG_ADDR(x) (((x) >> S_MI0_PHY_REG_ADDR) & M_MI0_PHY_REG_ADDR)
-
-#define S_MI0_PHY_ADDR    5
-#define M_MI0_PHY_ADDR    0x1f
-#define V_MI0_PHY_ADDR(x) ((x) << S_MI0_PHY_ADDR)
-#define G_MI0_PHY_ADDR(x) (((x) >> S_MI0_PHY_ADDR) & M_MI0_PHY_ADDR)
-
-#define A_MI0_DATA_EXT 0xb0c
-#define A_MI0_DATA_INT 0xb10
-
-/* GMAC registers */
-#define A_GMAC_MACID_LO	0x28
-#define A_GMAC_MACID_HI	0x2c
-#define A_GMAC_CSR	0x30
-
-#define S_INTERFACE    0
-#define M_INTERFACE    0x3
-#define V_INTERFACE(x) ((x) << S_INTERFACE)
-#define G_INTERFACE(x) (((x) >> S_INTERFACE) & M_INTERFACE)
-
-#define S_MAC_TX_ENABLE    2
-#define V_MAC_TX_ENABLE(x) ((x) << S_MAC_TX_ENABLE)
-#define F_MAC_TX_ENABLE    V_MAC_TX_ENABLE(1U)
-
-#define S_MAC_RX_ENABLE    3
-#define V_MAC_RX_ENABLE(x) ((x) << S_MAC_RX_ENABLE)
-#define F_MAC_RX_ENABLE    V_MAC_RX_ENABLE(1U)
-
-#define S_MAC_LB_ENABLE    4
-#define V_MAC_LB_ENABLE(x) ((x) << S_MAC_LB_ENABLE)
-#define F_MAC_LB_ENABLE    V_MAC_LB_ENABLE(1U)
-
-#define S_MAC_SPEED    5
-#define M_MAC_SPEED    0x3
-#define V_MAC_SPEED(x) ((x) << S_MAC_SPEED)
-#define G_MAC_SPEED(x) (((x) >> S_MAC_SPEED) & M_MAC_SPEED)
-
-#define S_MAC_HD_FC_ENABLE    7
-#define V_MAC_HD_FC_ENABLE(x) ((x) << S_MAC_HD_FC_ENABLE)
-#define F_MAC_HD_FC_ENABLE    V_MAC_HD_FC_ENABLE(1U)
-
-#define S_MAC_HALF_DUPLEX    8
-#define V_MAC_HALF_DUPLEX(x) ((x) << S_MAC_HALF_DUPLEX)
-#define F_MAC_HALF_DUPLEX    V_MAC_HALF_DUPLEX(1U)
-
-#define S_MAC_PROMISC    9
-#define V_MAC_PROMISC(x) ((x) << S_MAC_PROMISC)
-#define F_MAC_PROMISC    V_MAC_PROMISC(1U)
-
-#define S_MAC_MC_ENABLE    10
-#define V_MAC_MC_ENABLE(x) ((x) << S_MAC_MC_ENABLE)
-#define F_MAC_MC_ENABLE    V_MAC_MC_ENABLE(1U)
-
-#define S_MAC_RESET    11
-#define V_MAC_RESET(x) ((x) << S_MAC_RESET)
-#define F_MAC_RESET    V_MAC_RESET(1U)
-
-#define S_MAC_RX_PAUSE_ENABLE    12
-#define V_MAC_RX_PAUSE_ENABLE(x) ((x) << S_MAC_RX_PAUSE_ENABLE)
-#define F_MAC_RX_PAUSE_ENABLE    V_MAC_RX_PAUSE_ENABLE(1U)
-
-#define S_MAC_TX_PAUSE_ENABLE    13
-#define V_MAC_TX_PAUSE_ENABLE(x) ((x) << S_MAC_TX_PAUSE_ENABLE)
-#define F_MAC_TX_PAUSE_ENABLE    V_MAC_TX_PAUSE_ENABLE(1U)
-
-#define S_MAC_LWM_ENABLE    14
-#define V_MAC_LWM_ENABLE(x) ((x) << S_MAC_LWM_ENABLE)
-#define F_MAC_LWM_ENABLE    V_MAC_LWM_ENABLE(1U)
-
-#define S_MAC_MAGIC_PKT_ENABLE    15
-#define V_MAC_MAGIC_PKT_ENABLE(x) ((x) << S_MAC_MAGIC_PKT_ENABLE)
-#define F_MAC_MAGIC_PKT_ENABLE    V_MAC_MAGIC_PKT_ENABLE(1U)
-
-#define S_MAC_ISL_ENABLE    16
-#define V_MAC_ISL_ENABLE(x) ((x) << S_MAC_ISL_ENABLE)
-#define F_MAC_ISL_ENABLE    V_MAC_ISL_ENABLE(1U)
-
-#define S_MAC_JUMBO_ENABLE    17
-#define V_MAC_JUMBO_ENABLE(x) ((x) << S_MAC_JUMBO_ENABLE)
-#define F_MAC_JUMBO_ENABLE    V_MAC_JUMBO_ENABLE(1U)
-
-#define S_MAC_RX_PAD_ENABLE    18
-#define V_MAC_RX_PAD_ENABLE(x) ((x) << S_MAC_RX_PAD_ENABLE)
-#define F_MAC_RX_PAD_ENABLE    V_MAC_RX_PAD_ENABLE(1U)
-
-#define S_MAC_RX_CRC_ENABLE    19
-#define V_MAC_RX_CRC_ENABLE(x) ((x) << S_MAC_RX_CRC_ENABLE)
-#define F_MAC_RX_CRC_ENABLE    V_MAC_RX_CRC_ENABLE(1U)
-
-#define A_GMAC_IFS 0x34
-
-#define S_MAC_IFS2    0
-#define M_MAC_IFS2    0x3f
-#define V_MAC_IFS2(x) ((x) << S_MAC_IFS2)
-#define G_MAC_IFS2(x) (((x) >> S_MAC_IFS2) & M_MAC_IFS2)
-
-#define S_MAC_IFS1    8
-#define M_MAC_IFS1    0x7f
-#define V_MAC_IFS1(x) ((x) << S_MAC_IFS1)
-#define G_MAC_IFS1(x) (((x) >> S_MAC_IFS1) & M_MAC_IFS1)
-
-#define A_GMAC_JUMBO_FRAME_LEN 0x38
-#define A_GMAC_LNK_DLY 0x3c
-#define A_GMAC_PAUSETIME 0x40
-#define A_GMAC_MCAST_LO 0x44
-#define A_GMAC_MCAST_HI 0x48
-#define A_GMAC_MCAST_MASK_LO 0x4c
-#define A_GMAC_MCAST_MASK_HI 0x50
-#define A_GMAC_RMT_CNT 0x54
-#define A_GMAC_RMT_DATA 0x58
-#define A_GMAC_BACKOFF_SEED 0x5c
-#define A_GMAC_TXF_THRES 0x60
-
-#define S_TXF_READ_THRESHOLD    0
-#define M_TXF_READ_THRESHOLD    0xff
-#define V_TXF_READ_THRESHOLD(x) ((x) << S_TXF_READ_THRESHOLD)
-#define G_TXF_READ_THRESHOLD(x) (((x) >> S_TXF_READ_THRESHOLD) & M_TXF_READ_THRESHOLD)
-
-#define S_TXF_WRITE_THRESHOLD    16
-#define M_TXF_WRITE_THRESHOLD    0xff
-#define V_TXF_WRITE_THRESHOLD(x) ((x) << S_TXF_WRITE_THRESHOLD)
-#define G_TXF_WRITE_THRESHOLD(x) (((x) >> S_TXF_WRITE_THRESHOLD) & M_TXF_WRITE_THRESHOLD)
-
-#define MAC_REG_BASE 0x600
-#define MAC_REG_ADDR(idx, reg) (MAC_REG_BASE + (idx) * 128 + (reg))
-
-#define MAC_REG_IDLO(idx)              MAC_REG_ADDR(idx, A_GMAC_MACID_LO)
-#define MAC_REG_IDHI(idx)              MAC_REG_ADDR(idx, A_GMAC_MACID_HI)
-#define MAC_REG_CSR(idx)               MAC_REG_ADDR(idx, A_GMAC_CSR)
-#define MAC_REG_IFS(idx)               MAC_REG_ADDR(idx, A_GMAC_IFS)
-#define MAC_REG_LARGEFRAMELENGTH(idx) MAC_REG_ADDR(idx, A_GMAC_JUMBO_FRAME_LEN)
-#define MAC_REG_LINKDLY(idx)           MAC_REG_ADDR(idx, A_GMAC_LNK_DLY)
-#define MAC_REG_PAUSETIME(idx)         MAC_REG_ADDR(idx, A_GMAC_PAUSETIME)
-#define MAC_REG_CASTLO(idx)            MAC_REG_ADDR(idx, A_GMAC_MCAST_LO)
-#define MAC_REG_MCASTHI(idx)           MAC_REG_ADDR(idx, A_GMAC_MCAST_HI)
-#define MAC_REG_CASTMASKLO(idx)        MAC_REG_ADDR(idx, A_GMAC_MCAST_MASK_LO)
-#define MAC_REG_MCASTMASKHI(idx)       MAC_REG_ADDR(idx, A_GMAC_MCAST_MASK_HI)
-#define MAC_REG_RMCNT(idx)             MAC_REG_ADDR(idx, A_GMAC_RMT_CNT)
-#define MAC_REG_RMDATA(idx)            MAC_REG_ADDR(idx, A_GMAC_RMT_DATA)
-#define MAC_REG_GMRANDBACKOFFSEED(idx) MAC_REG_ADDR(idx, A_GMAC_BACKOFF_SEED)
-#define MAC_REG_TXFTHRESHOLDS(idx)     MAC_REG_ADDR(idx, A_GMAC_TXF_THRES)
-
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/gmac.h linux-libre-3.2-gnu/drivers/net/chelsio/gmac.h
--- linux-libre-3.1-gnu/drivers/net/chelsio/gmac.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/gmac.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,142 +0,0 @@
-/*****************************************************************************
- *                                                                           *
- * File: gmac.h                                                              *
- * $Revision: 1.6 $                                                          *
- * $Date: 2005/06/21 18:29:47 $                                              *
- * Description:                                                              *
- *  Generic MAC functionality.                                               *
- *  part of the Chelsio 10Gb Ethernet 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.                                *
- *                                                                           *
- * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
- *                                                                           *
- * http://www.chelsio.com                                                    *
- *                                                                           *
- * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
- * All rights reserved.                                                      *
- *                                                                           *
- * Maintainers: maintainers@chelsio.com                                      *
- *                                                                           *
- * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
- *          Tina Yang               <tainay@chelsio.com>                     *
- *          Felix Marti             <felix@chelsio.com>                      *
- *          Scott Bardone           <sbardone@chelsio.com>                   *
- *          Kurt Ottaway            <kottaway@chelsio.com>                   *
- *          Frank DiMambro          <frank@chelsio.com>                      *
- *                                                                           *
- * History:                                                                  *
- *                                                                           *
- ****************************************************************************/
-
-#ifndef _CXGB_GMAC_H_
-#define _CXGB_GMAC_H_
-
-#include "common.h"
-
-enum {
-	MAC_STATS_UPDATE_FAST,
-	MAC_STATS_UPDATE_FULL
-};
-
-enum {
-	MAC_DIRECTION_RX = 1,
-	MAC_DIRECTION_TX = 2
-};
-
-struct cmac_statistics {
-	/* Transmit */
-	u64 TxOctetsOK;
-	u64 TxOctetsBad;
-	u64 TxUnicastFramesOK;
-	u64 TxMulticastFramesOK;
-	u64 TxBroadcastFramesOK;
-	u64 TxPauseFrames;
-	u64 TxFramesWithDeferredXmissions;
-	u64 TxLateCollisions;
-	u64 TxTotalCollisions;
-	u64 TxFramesAbortedDueToXSCollisions;
-	u64 TxUnderrun;
-	u64 TxLengthErrors;
-	u64 TxInternalMACXmitError;
-	u64 TxFramesWithExcessiveDeferral;
-	u64 TxFCSErrors;
-	u64 TxJumboFramesOK;
-	u64 TxJumboOctetsOK;
-
-	/* Receive */
-	u64 RxOctetsOK;
-	u64 RxOctetsBad;
-	u64 RxUnicastFramesOK;
-	u64 RxMulticastFramesOK;
-	u64 RxBroadcastFramesOK;
-	u64 RxPauseFrames;
-	u64 RxFCSErrors;
-	u64 RxAlignErrors;
-	u64 RxSymbolErrors;
-	u64 RxDataErrors;
-	u64 RxSequenceErrors;
-	u64 RxRuntErrors;
-	u64 RxJabberErrors;
-	u64 RxInternalMACRcvError;
-	u64 RxInRangeLengthErrors;
-	u64 RxOutOfRangeLengthField;
-	u64 RxFrameTooLongErrors;
-	u64 RxJumboFramesOK;
-	u64 RxJumboOctetsOK;
-};
-
-struct cmac_ops {
-	void (*destroy)(struct cmac *);
-	int (*reset)(struct cmac *);
-	int (*interrupt_enable)(struct cmac *);
-	int (*interrupt_disable)(struct cmac *);
-	int (*interrupt_clear)(struct cmac *);
-	int (*interrupt_handler)(struct cmac *);
-
-	int (*enable)(struct cmac *, int);
-	int (*disable)(struct cmac *, int);
-
-	int (*loopback_enable)(struct cmac *);
-	int (*loopback_disable)(struct cmac *);
-
-	int (*set_mtu)(struct cmac *, int mtu);
-	int (*set_rx_mode)(struct cmac *, struct t1_rx_mode *rm);
-
-	int (*set_speed_duplex_fc)(struct cmac *, int speed, int duplex, int fc);
-	int (*get_speed_duplex_fc)(struct cmac *, int *speed, int *duplex,
-				   int *fc);
-
-	const struct cmac_statistics *(*statistics_update)(struct cmac *, int);
-
-	int (*macaddress_get)(struct cmac *, u8 mac_addr[6]);
-	int (*macaddress_set)(struct cmac *, u8 mac_addr[6]);
-};
-
-typedef struct _cmac_instance cmac_instance;
-
-struct cmac {
-	struct cmac_statistics stats;
-	adapter_t *adapter;
-	const struct cmac_ops *ops;
-	cmac_instance *instance;
-};
-
-struct gmac {
-	unsigned int stats_update_period;
-	struct cmac *(*create)(adapter_t *adapter, int index);
-	int (*reset)(adapter_t *);
-};
-
-extern const struct gmac t1_pm3393_ops;
-extern const struct gmac t1_vsc7326_ops;
-
-#endif /* _CXGB_GMAC_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/Makefile linux-libre-3.2-gnu/drivers/net/chelsio/Makefile
--- linux-libre-3.1-gnu/drivers/net/chelsio/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-#
-# Chelsio T1 driver
-#
-
-obj-$(CONFIG_CHELSIO_T1) += cxgb.o
-
-cxgb-$(CONFIG_CHELSIO_T1_1G) += mv88e1xxx.o vsc7326.o
-cxgb-objs := cxgb2.o espi.o tp.o pm3393.o sge.o subr.o \
-	     mv88x201x.o my3126.o $(cxgb-y)
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/mv88e1xxx.c linux-libre-3.2-gnu/drivers/net/chelsio/mv88e1xxx.c
--- linux-libre-3.1-gnu/drivers/net/chelsio/mv88e1xxx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/mv88e1xxx.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,397 +0,0 @@
-/* $Date: 2005/10/24 23:18:13 $ $RCSfile: mv88e1xxx.c,v $ $Revision: 1.49 $ */
-#include "common.h"
-#include "mv88e1xxx.h"
-#include "cphy.h"
-#include "elmer0.h"
-
-/* MV88E1XXX MDI crossover register values */
-#define CROSSOVER_MDI   0
-#define CROSSOVER_MDIX  1
-#define CROSSOVER_AUTO  3
-
-#define INTR_ENABLE_MASK 0x6CA0
-
-/*
- * Set the bits given by 'bitval' in PHY register 'reg'.
- */
-static void mdio_set_bit(struct cphy *cphy, int reg, u32 bitval)
-{
-	u32 val;
-
-	(void) simple_mdio_read(cphy, reg, &val);
-	(void) simple_mdio_write(cphy, reg, val | bitval);
-}
-
-/*
- * Clear the bits given by 'bitval' in PHY register 'reg'.
- */
-static void mdio_clear_bit(struct cphy *cphy, int reg, u32 bitval)
-{
-	u32 val;
-
-	(void) simple_mdio_read(cphy, reg, &val);
-	(void) simple_mdio_write(cphy, reg, val & ~bitval);
-}
-
-/*
- * NAME:   phy_reset
- *
- * DESC:   Reset the given PHY's port. NOTE: This is not a global
- *         chip reset.
- *
- * PARAMS: cphy     - Pointer to PHY instance data.
- *
- * RETURN:  0 - Successful reset.
- *         -1 - Timeout.
- */
-static int mv88e1xxx_reset(struct cphy *cphy, int wait)
-{
-	u32 ctl;
-	int time_out = 1000;
-
-	mdio_set_bit(cphy, MII_BMCR, BMCR_RESET);
-
-	do {
-		(void) simple_mdio_read(cphy, MII_BMCR, &ctl);
-		ctl &= BMCR_RESET;
-		if (ctl)
-			udelay(1);
-	} while (ctl && --time_out);
-
-	return ctl ? -1 : 0;
-}
-
-static int mv88e1xxx_interrupt_enable(struct cphy *cphy)
-{
-	/* Enable PHY interrupts. */
-	(void) simple_mdio_write(cphy, MV88E1XXX_INTERRUPT_ENABLE_REGISTER,
-		   INTR_ENABLE_MASK);
-
-	/* Enable Marvell interrupts through Elmer0. */
-	if (t1_is_asic(cphy->adapter)) {
-		u32 elmer;
-
-		t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
-		elmer |= ELMER0_GP_BIT1;
-		if (is_T2(cphy->adapter))
-		    elmer |= ELMER0_GP_BIT2 | ELMER0_GP_BIT3 | ELMER0_GP_BIT4;
-		t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
-	}
-	return 0;
-}
-
-static int mv88e1xxx_interrupt_disable(struct cphy *cphy)
-{
-	/* Disable all phy interrupts. */
-	(void) simple_mdio_write(cphy, MV88E1XXX_INTERRUPT_ENABLE_REGISTER, 0);
-
-	/* Disable Marvell interrupts through Elmer0. */
-	if (t1_is_asic(cphy->adapter)) {
-		u32 elmer;
-
-		t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
-		elmer &= ~ELMER0_GP_BIT1;
-		if (is_T2(cphy->adapter))
-		    elmer &= ~(ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4);
-		t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
-	}
-	return 0;
-}
-
-static int mv88e1xxx_interrupt_clear(struct cphy *cphy)
-{
-	u32 elmer;
-
-	/* Clear PHY interrupts by reading the register. */
-	(void) simple_mdio_read(cphy,
-			MV88E1XXX_INTERRUPT_STATUS_REGISTER, &elmer);
-
-	/* Clear Marvell interrupts through Elmer0. */
-	if (t1_is_asic(cphy->adapter)) {
-		t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer);
-		elmer |= ELMER0_GP_BIT1;
-		if (is_T2(cphy->adapter))
-		    elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4;
-		t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer);
-	}
-	return 0;
-}
-
-/*
- * Set the PHY speed and duplex.  This also disables auto-negotiation, except
- * for 1Gb/s, where auto-negotiation is mandatory.
- */
-static int mv88e1xxx_set_speed_duplex(struct cphy *phy, int speed, int duplex)
-{
-	u32 ctl;
-
-	(void) simple_mdio_read(phy, MII_BMCR, &ctl);
-	if (speed >= 0) {
-		ctl &= ~(BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
-		if (speed == SPEED_100)
-			ctl |= BMCR_SPEED100;
-		else if (speed == SPEED_1000)
-			ctl |= BMCR_SPEED1000;
-	}
-	if (duplex >= 0) {
-		ctl &= ~(BMCR_FULLDPLX | BMCR_ANENABLE);
-		if (duplex == DUPLEX_FULL)
-			ctl |= BMCR_FULLDPLX;
-	}
-	if (ctl & BMCR_SPEED1000)  /* auto-negotiation required for 1Gb/s */
-		ctl |= BMCR_ANENABLE;
-	(void) simple_mdio_write(phy, MII_BMCR, ctl);
-	return 0;
-}
-
-static int mv88e1xxx_crossover_set(struct cphy *cphy, int crossover)
-{
-	u32 data32;
-
-	(void) simple_mdio_read(cphy,
-			MV88E1XXX_SPECIFIC_CNTRL_REGISTER, &data32);
-	data32 &= ~V_PSCR_MDI_XOVER_MODE(M_PSCR_MDI_XOVER_MODE);
-	data32 |= V_PSCR_MDI_XOVER_MODE(crossover);
-	(void) simple_mdio_write(cphy,
-			MV88E1XXX_SPECIFIC_CNTRL_REGISTER, data32);
-	return 0;
-}
-
-static int mv88e1xxx_autoneg_enable(struct cphy *cphy)
-{
-	u32 ctl;
-
-	(void) mv88e1xxx_crossover_set(cphy, CROSSOVER_AUTO);
-
-	(void) simple_mdio_read(cphy, MII_BMCR, &ctl);
-	/* restart autoneg for change to take effect */
-	ctl |= BMCR_ANENABLE | BMCR_ANRESTART;
-	(void) simple_mdio_write(cphy, MII_BMCR, ctl);
-	return 0;
-}
-
-static int mv88e1xxx_autoneg_disable(struct cphy *cphy)
-{
-	u32 ctl;
-
-	/*
-	 * Crossover *must* be set to manual in order to disable auto-neg.
-	 * The Alaska FAQs document highlights this point.
-	 */
-	(void) mv88e1xxx_crossover_set(cphy, CROSSOVER_MDI);
-
-	/*
-	 * Must include autoneg reset when disabling auto-neg. This
-	 * is described in the Alaska FAQ document.
-	 */
-	(void) simple_mdio_read(cphy, MII_BMCR, &ctl);
-	ctl &= ~BMCR_ANENABLE;
-	(void) simple_mdio_write(cphy, MII_BMCR, ctl | BMCR_ANRESTART);
-	return 0;
-}
-
-static int mv88e1xxx_autoneg_restart(struct cphy *cphy)
-{
-	mdio_set_bit(cphy, MII_BMCR, BMCR_ANRESTART);
-	return 0;
-}
-
-static int mv88e1xxx_advertise(struct cphy *phy, unsigned int advertise_map)
-{
-	u32 val = 0;
-
-	if (advertise_map &
-	    (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full)) {
-		(void) simple_mdio_read(phy, MII_GBCR, &val);
-		val &= ~(GBCR_ADV_1000HALF | GBCR_ADV_1000FULL);
-		if (advertise_map & ADVERTISED_1000baseT_Half)
-			val |= GBCR_ADV_1000HALF;
-		if (advertise_map & ADVERTISED_1000baseT_Full)
-			val |= GBCR_ADV_1000FULL;
-	}
-	(void) simple_mdio_write(phy, MII_GBCR, val);
-
-	val = 1;
-	if (advertise_map & ADVERTISED_10baseT_Half)
-		val |= ADVERTISE_10HALF;
-	if (advertise_map & ADVERTISED_10baseT_Full)
-		val |= ADVERTISE_10FULL;
-	if (advertise_map & ADVERTISED_100baseT_Half)
-		val |= ADVERTISE_100HALF;
-	if (advertise_map & ADVERTISED_100baseT_Full)
-		val |= ADVERTISE_100FULL;
-	if (advertise_map & ADVERTISED_PAUSE)
-		val |= ADVERTISE_PAUSE;
-	if (advertise_map & ADVERTISED_ASYM_PAUSE)
-		val |= ADVERTISE_PAUSE_ASYM;
-	(void) simple_mdio_write(phy, MII_ADVERTISE, val);
-	return 0;
-}
-
-static int mv88e1xxx_set_loopback(struct cphy *cphy, int on)
-{
-	if (on)
-		mdio_set_bit(cphy, MII_BMCR, BMCR_LOOPBACK);
-	else
-		mdio_clear_bit(cphy, MII_BMCR, BMCR_LOOPBACK);
-	return 0;
-}
-
-static int mv88e1xxx_get_link_status(struct cphy *cphy, int *link_ok,
-				     int *speed, int *duplex, int *fc)
-{
-	u32 status;
-	int sp = -1, dplx = -1, pause = 0;
-
-	(void) simple_mdio_read(cphy,
-			MV88E1XXX_SPECIFIC_STATUS_REGISTER, &status);
-	if ((status & V_PSSR_STATUS_RESOLVED) != 0) {
-		if (status & V_PSSR_RX_PAUSE)
-			pause |= PAUSE_RX;
-		if (status & V_PSSR_TX_PAUSE)
-			pause |= PAUSE_TX;
-		dplx = (status & V_PSSR_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF;
-		sp = G_PSSR_SPEED(status);
-		if (sp == 0)
-			sp = SPEED_10;
-		else if (sp == 1)
-			sp = SPEED_100;
-		else
-			sp = SPEED_1000;
-	}
-	if (link_ok)
-		*link_ok = (status & V_PSSR_LINK) != 0;
-	if (speed)
-		*speed = sp;
-	if (duplex)
-		*duplex = dplx;
-	if (fc)
-		*fc = pause;
-	return 0;
-}
-
-static int mv88e1xxx_downshift_set(struct cphy *cphy, int downshift_enable)
-{
-	u32 val;
-
-	(void) simple_mdio_read(cphy,
-		MV88E1XXX_EXT_PHY_SPECIFIC_CNTRL_REGISTER, &val);
-
-	/*
-	 * Set the downshift counter to 2 so we try to establish Gb link
-	 * twice before downshifting.
-	 */
-	val &= ~(V_DOWNSHIFT_ENABLE | V_DOWNSHIFT_CNT(M_DOWNSHIFT_CNT));
-
-	if (downshift_enable)
-		val |= V_DOWNSHIFT_ENABLE | V_DOWNSHIFT_CNT(2);
-	(void) simple_mdio_write(cphy,
-			MV88E1XXX_EXT_PHY_SPECIFIC_CNTRL_REGISTER, val);
-	return 0;
-}
-
-static int mv88e1xxx_interrupt_handler(struct cphy *cphy)
-{
-	int cphy_cause = 0;
-	u32 status;
-
-	/*
-	 * Loop until cause reads zero. Need to handle bouncing interrupts.
-	 */
-	while (1) {
-		u32 cause;
-
-		(void) simple_mdio_read(cphy,
-				MV88E1XXX_INTERRUPT_STATUS_REGISTER,
-				&cause);
-		cause &= INTR_ENABLE_MASK;
-		if (!cause)
-			break;
-
-		if (cause & MV88E1XXX_INTR_LINK_CHNG) {
-			(void) simple_mdio_read(cphy,
-				MV88E1XXX_SPECIFIC_STATUS_REGISTER, &status);
-
-			if (status & MV88E1XXX_INTR_LINK_CHNG)
-				cphy->state |= PHY_LINK_UP;
-			else {
-				cphy->state &= ~PHY_LINK_UP;
-				if (cphy->state & PHY_AUTONEG_EN)
-					cphy->state &= ~PHY_AUTONEG_RDY;
-				cphy_cause |= cphy_cause_link_change;
-			}
-		}
-
-		if (cause & MV88E1XXX_INTR_AUTONEG_DONE)
-			cphy->state |= PHY_AUTONEG_RDY;
-
-		if ((cphy->state & (PHY_LINK_UP | PHY_AUTONEG_RDY)) ==
-			(PHY_LINK_UP | PHY_AUTONEG_RDY))
-				cphy_cause |= cphy_cause_link_change;
-	}
-	return cphy_cause;
-}
-
-static void mv88e1xxx_destroy(struct cphy *cphy)
-{
-	kfree(cphy);
-}
-
-static struct cphy_ops mv88e1xxx_ops = {
-	.destroy              = mv88e1xxx_destroy,
-	.reset                = mv88e1xxx_reset,
-	.interrupt_enable     = mv88e1xxx_interrupt_enable,
-	.interrupt_disable    = mv88e1xxx_interrupt_disable,
-	.interrupt_clear      = mv88e1xxx_interrupt_clear,
-	.interrupt_handler    = mv88e1xxx_interrupt_handler,
-	.autoneg_enable       = mv88e1xxx_autoneg_enable,
-	.autoneg_disable      = mv88e1xxx_autoneg_disable,
-	.autoneg_restart      = mv88e1xxx_autoneg_restart,
-	.advertise            = mv88e1xxx_advertise,
-	.set_loopback         = mv88e1xxx_set_loopback,
-	.set_speed_duplex     = mv88e1xxx_set_speed_duplex,
-	.get_link_status      = mv88e1xxx_get_link_status,
-};
-
-static struct cphy *mv88e1xxx_phy_create(struct net_device *dev, int phy_addr,
-					 const struct mdio_ops *mdio_ops)
-{
-	struct adapter *adapter = netdev_priv(dev);
-	struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL);
-
-	if (!cphy)
-		return NULL;
-
-	cphy_init(cphy, dev, phy_addr, &mv88e1xxx_ops, mdio_ops);
-
-	/* Configure particular PHY's to run in a different mode. */
-	if ((board_info(adapter)->caps & SUPPORTED_TP) &&
-	    board_info(adapter)->chip_phy == CHBT_PHY_88E1111) {
-		/*
-		 * Configure the PHY transmitter as class A to reduce EMI.
-		 */
-		(void) simple_mdio_write(cphy,
-				MV88E1XXX_EXTENDED_ADDR_REGISTER, 0xB);
-		(void) simple_mdio_write(cphy,
-				MV88E1XXX_EXTENDED_REGISTER, 0x8004);
-	}
-	(void) mv88e1xxx_downshift_set(cphy, 1);   /* Enable downshift */
-
-	/* LED */
-	if (is_T2(adapter)) {
-		(void) simple_mdio_write(cphy,
-				MV88E1XXX_LED_CONTROL_REGISTER, 0x1);
-	}
-
-	return cphy;
-}
-
-static int mv88e1xxx_phy_reset(adapter_t* adapter)
-{
-	return 0;
-}
-
-const struct gphy t1_mv88e1xxx_ops = {
-	.create = mv88e1xxx_phy_create,
-	.reset =  mv88e1xxx_phy_reset
-};
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/mv88e1xxx.h linux-libre-3.2-gnu/drivers/net/chelsio/mv88e1xxx.h
--- linux-libre-3.1-gnu/drivers/net/chelsio/mv88e1xxx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/mv88e1xxx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,127 +0,0 @@
-/* $Date: 2005/03/07 23:59:05 $ $RCSfile: mv88e1xxx.h,v $ $Revision: 1.13 $ */
-#ifndef CHELSIO_MV8E1XXX_H
-#define CHELSIO_MV8E1XXX_H
-
-#ifndef BMCR_SPEED1000
-# define BMCR_SPEED1000 0x40
-#endif
-
-#ifndef ADVERTISE_PAUSE
-# define ADVERTISE_PAUSE 0x400
-#endif
-#ifndef ADVERTISE_PAUSE_ASYM
-# define ADVERTISE_PAUSE_ASYM 0x800
-#endif
-
-/* Gigabit MII registers */
-#define MII_GBCR 9       /* 1000Base-T control register */
-#define MII_GBSR 10      /* 1000Base-T status register */
-
-/* 1000Base-T control register fields */
-#define GBCR_ADV_1000HALF         0x100
-#define GBCR_ADV_1000FULL         0x200
-#define GBCR_PREFER_MASTER        0x400
-#define GBCR_MANUAL_AS_MASTER     0x800
-#define GBCR_MANUAL_CONFIG_ENABLE 0x1000
-
-/* 1000Base-T status register fields */
-#define GBSR_LP_1000HALF  0x400
-#define GBSR_LP_1000FULL  0x800
-#define GBSR_REMOTE_OK    0x1000
-#define GBSR_LOCAL_OK     0x2000
-#define GBSR_LOCAL_MASTER 0x4000
-#define GBSR_MASTER_FAULT 0x8000
-
-/* Marvell PHY interrupt status bits. */
-#define MV88E1XXX_INTR_JABBER          0x0001
-#define MV88E1XXX_INTR_POLARITY_CHNG   0x0002
-#define MV88E1XXX_INTR_ENG_DETECT_CHNG 0x0010
-#define MV88E1XXX_INTR_DOWNSHIFT       0x0020
-#define MV88E1XXX_INTR_MDI_XOVER_CHNG  0x0040
-#define MV88E1XXX_INTR_FIFO_OVER_UNDER 0x0080
-#define MV88E1XXX_INTR_FALSE_CARRIER   0x0100
-#define MV88E1XXX_INTR_SYMBOL_ERROR    0x0200
-#define MV88E1XXX_INTR_LINK_CHNG       0x0400
-#define MV88E1XXX_INTR_AUTONEG_DONE    0x0800
-#define MV88E1XXX_INTR_PAGE_RECV       0x1000
-#define MV88E1XXX_INTR_DUPLEX_CHNG     0x2000
-#define MV88E1XXX_INTR_SPEED_CHNG      0x4000
-#define MV88E1XXX_INTR_AUTONEG_ERR     0x8000
-
-/* Marvell PHY specific registers. */
-#define MV88E1XXX_SPECIFIC_CNTRL_REGISTER               16
-#define MV88E1XXX_SPECIFIC_STATUS_REGISTER              17
-#define MV88E1XXX_INTERRUPT_ENABLE_REGISTER             18
-#define MV88E1XXX_INTERRUPT_STATUS_REGISTER             19
-#define MV88E1XXX_EXT_PHY_SPECIFIC_CNTRL_REGISTER       20
-#define MV88E1XXX_RECV_ERR_CNTR_REGISTER                21
-#define MV88E1XXX_RES_REGISTER                          22
-#define MV88E1XXX_GLOBAL_STATUS_REGISTER                23
-#define MV88E1XXX_LED_CONTROL_REGISTER                  24
-#define MV88E1XXX_MANUAL_LED_OVERRIDE_REGISTER          25
-#define MV88E1XXX_EXT_PHY_SPECIFIC_CNTRL_2_REGISTER     26
-#define MV88E1XXX_EXT_PHY_SPECIFIC_STATUS_REGISTER      27
-#define MV88E1XXX_VIRTUAL_CABLE_TESTER_REGISTER         28
-#define MV88E1XXX_EXTENDED_ADDR_REGISTER                29
-#define MV88E1XXX_EXTENDED_REGISTER                     30
-
-/* PHY specific control register fields */
-#define S_PSCR_MDI_XOVER_MODE    5
-#define M_PSCR_MDI_XOVER_MODE    0x3
-#define V_PSCR_MDI_XOVER_MODE(x) ((x) << S_PSCR_MDI_XOVER_MODE)
-#define G_PSCR_MDI_XOVER_MODE(x) (((x) >> S_PSCR_MDI_XOVER_MODE) & M_PSCR_MDI_XOVER_MODE)
-
-/* Extended PHY specific control register fields */
-#define S_DOWNSHIFT_ENABLE 8
-#define V_DOWNSHIFT_ENABLE (1 << S_DOWNSHIFT_ENABLE)
-
-#define S_DOWNSHIFT_CNT    9
-#define M_DOWNSHIFT_CNT    0x7
-#define V_DOWNSHIFT_CNT(x) ((x) << S_DOWNSHIFT_CNT)
-#define G_DOWNSHIFT_CNT(x) (((x) >> S_DOWNSHIFT_CNT) & M_DOWNSHIFT_CNT)
-
-/* PHY specific status register fields */
-#define S_PSSR_JABBER 0
-#define V_PSSR_JABBER (1 << S_PSSR_JABBER)
-
-#define S_PSSR_POLARITY 1
-#define V_PSSR_POLARITY (1 << S_PSSR_POLARITY)
-
-#define S_PSSR_RX_PAUSE 2
-#define V_PSSR_RX_PAUSE (1 << S_PSSR_RX_PAUSE)
-
-#define S_PSSR_TX_PAUSE 3
-#define V_PSSR_TX_PAUSE (1 << S_PSSR_TX_PAUSE)
-
-#define S_PSSR_ENERGY_DETECT 4
-#define V_PSSR_ENERGY_DETECT (1 << S_PSSR_ENERGY_DETECT)
-
-#define S_PSSR_DOWNSHIFT_STATUS 5
-#define V_PSSR_DOWNSHIFT_STATUS (1 << S_PSSR_DOWNSHIFT_STATUS)
-
-#define S_PSSR_MDI 6
-#define V_PSSR_MDI (1 << S_PSSR_MDI)
-
-#define S_PSSR_CABLE_LEN    7
-#define M_PSSR_CABLE_LEN    0x7
-#define V_PSSR_CABLE_LEN(x) ((x) << S_PSSR_CABLE_LEN)
-#define G_PSSR_CABLE_LEN(x) (((x) >> S_PSSR_CABLE_LEN) & M_PSSR_CABLE_LEN)
-
-#define S_PSSR_LINK 10
-#define V_PSSR_LINK (1 << S_PSSR_LINK)
-
-#define S_PSSR_STATUS_RESOLVED 11
-#define V_PSSR_STATUS_RESOLVED (1 << S_PSSR_STATUS_RESOLVED)
-
-#define S_PSSR_PAGE_RECEIVED 12
-#define V_PSSR_PAGE_RECEIVED (1 << S_PSSR_PAGE_RECEIVED)
-
-#define S_PSSR_DUPLEX 13
-#define V_PSSR_DUPLEX (1 << S_PSSR_DUPLEX)
-
-#define S_PSSR_SPEED    14
-#define M_PSSR_SPEED    0x3
-#define V_PSSR_SPEED(x) ((x) << S_PSSR_SPEED)
-#define G_PSSR_SPEED(x) (((x) >> S_PSSR_SPEED) & M_PSSR_SPEED)
-
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/mv88x201x.c linux-libre-3.2-gnu/drivers/net/chelsio/mv88x201x.c
--- linux-libre-3.1-gnu/drivers/net/chelsio/mv88x201x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/mv88x201x.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,260 +0,0 @@
-/*****************************************************************************
- *                                                                           *
- * File: mv88x201x.c                                                         *
- * $Revision: 1.12 $                                                         *
- * $Date: 2005/04/15 19:27:14 $                                              *
- * Description:                                                              *
- *  Marvell PHY (mv88x201x) functionality.                                   *
- *  part of the Chelsio 10Gb Ethernet 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.                                *
- *                                                                           *
- * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
- *                                                                           *
- * http://www.chelsio.com                                                    *
- *                                                                           *
- * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
- * All rights reserved.                                                      *
- *                                                                           *
- * Maintainers: maintainers@chelsio.com                                      *
- *                                                                           *
- * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
- *          Tina Yang               <tainay@chelsio.com>                     *
- *          Felix Marti             <felix@chelsio.com>                      *
- *          Scott Bardone           <sbardone@chelsio.com>                   *
- *          Kurt Ottaway            <kottaway@chelsio.com>                   *
- *          Frank DiMambro          <frank@chelsio.com>                      *
- *                                                                           *
- * History:                                                                  *
- *                                                                           *
- ****************************************************************************/
-
-#include "cphy.h"
-#include "elmer0.h"
-
-/*
- * The 88x2010 Rev C. requires some link status registers * to be read
- * twice in order to get the right values. Future * revisions will fix
- * this problem and then this macro * can disappear.
- */
-#define MV88x2010_LINK_STATUS_BUGS    1
-
-static int led_init(struct cphy *cphy)
-{
-	/* Setup the LED registers so we can turn on/off.
-	 * Writing these bits maps control to another
-	 * register. mmd(0x1) addr(0x7)
-	 */
-	cphy_mdio_write(cphy, MDIO_MMD_PCS, 0x8304, 0xdddd);
-	return 0;
-}
-
-static int led_link(struct cphy *cphy, u32 do_enable)
-{
-	u32 led = 0;
-#define LINK_ENABLE_BIT 0x1
-
-	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, &led);
-
-	if (do_enable & LINK_ENABLE_BIT) {
-		led |= LINK_ENABLE_BIT;
-		cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, led);
-	} else {
-		led &= ~LINK_ENABLE_BIT;
-		cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, led);
-	}
-	return 0;
-}
-
-/* Port Reset */
-static int mv88x201x_reset(struct cphy *cphy, int wait)
-{
-	/* This can be done through registers.  It is not required since
-	 * a full chip reset is used.
-	 */
-	return 0;
-}
-
-static int mv88x201x_interrupt_enable(struct cphy *cphy)
-{
-	/* Enable PHY LASI interrupts. */
-	cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL,
-			MDIO_PMA_LASI_LSALARM);
-
-	/* Enable Marvell interrupts through Elmer0. */
-	if (t1_is_asic(cphy->adapter)) {
-		u32 elmer;
-
-		t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
-		elmer |= ELMER0_GP_BIT6;
-		t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
-	}
-	return 0;
-}
-
-static int mv88x201x_interrupt_disable(struct cphy *cphy)
-{
-	/* Disable PHY LASI interrupts. */
-	cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0x0);
-
-	/* Disable Marvell interrupts through Elmer0. */
-	if (t1_is_asic(cphy->adapter)) {
-		u32 elmer;
-
-		t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
-		elmer &= ~ELMER0_GP_BIT6;
-		t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
-	}
-	return 0;
-}
-
-static int mv88x201x_interrupt_clear(struct cphy *cphy)
-{
-	u32 elmer;
-	u32 val;
-
-#ifdef MV88x2010_LINK_STATUS_BUGS
-	/* Required to read twice before clear takes affect. */
-	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_RXSTAT, &val);
-	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_TXSTAT, &val);
-	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val);
-
-	/* Read this register after the others above it else
-	 * the register doesn't clear correctly.
-	 */
-	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
-#endif
-
-	/* Clear link status. */
-	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
-	/* Clear PHY LASI interrupts. */
-	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val);
-
-#ifdef MV88x2010_LINK_STATUS_BUGS
-	/* Do it again. */
-	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_RXSTAT, &val);
-	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_TXSTAT, &val);
-#endif
-
-	/* Clear Marvell interrupts through Elmer0. */
-	if (t1_is_asic(cphy->adapter)) {
-		t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer);
-		elmer |= ELMER0_GP_BIT6;
-		t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer);
-	}
-	return 0;
-}
-
-static int mv88x201x_interrupt_handler(struct cphy *cphy)
-{
-	/* Clear interrupts */
-	mv88x201x_interrupt_clear(cphy);
-
-	/* We have only enabled link change interrupts and so
-	 * cphy_cause must be a link change interrupt.
-	 */
-	return cphy_cause_link_change;
-}
-
-static int mv88x201x_set_loopback(struct cphy *cphy, int on)
-{
-	return 0;
-}
-
-static int mv88x201x_get_link_status(struct cphy *cphy, int *link_ok,
-				     int *speed, int *duplex, int *fc)
-{
-	u32 val = 0;
-
-	if (link_ok) {
-		/* Read link status. */
-		cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
-		val &= MDIO_STAT1_LSTATUS;
-		*link_ok = (val == MDIO_STAT1_LSTATUS);
-		/* Turn on/off Link LED */
-		led_link(cphy, *link_ok);
-	}
-	if (speed)
-		*speed = SPEED_10000;
-	if (duplex)
-		*duplex = DUPLEX_FULL;
-	if (fc)
-		*fc = PAUSE_RX | PAUSE_TX;
-	return 0;
-}
-
-static void mv88x201x_destroy(struct cphy *cphy)
-{
-	kfree(cphy);
-}
-
-static struct cphy_ops mv88x201x_ops = {
-	.destroy           = mv88x201x_destroy,
-	.reset             = mv88x201x_reset,
-	.interrupt_enable  = mv88x201x_interrupt_enable,
-	.interrupt_disable = mv88x201x_interrupt_disable,
-	.interrupt_clear   = mv88x201x_interrupt_clear,
-	.interrupt_handler = mv88x201x_interrupt_handler,
-	.get_link_status   = mv88x201x_get_link_status,
-	.set_loopback      = mv88x201x_set_loopback,
-	.mmds              = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |
-			      MDIO_DEVS_PHYXS | MDIO_DEVS_WIS),
-};
-
-static struct cphy *mv88x201x_phy_create(struct net_device *dev, int phy_addr,
-					 const struct mdio_ops *mdio_ops)
-{
-	u32 val;
-	struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL);
-
-	if (!cphy)
-		return NULL;
-
-	cphy_init(cphy, dev, phy_addr, &mv88x201x_ops, mdio_ops);
-
-	/* Commands the PHY to enable XFP's clock. */
-	cphy_mdio_read(cphy, MDIO_MMD_PCS, 0x8300, &val);
-	cphy_mdio_write(cphy, MDIO_MMD_PCS, 0x8300, val | 1);
-
-	/* Clear link status. Required because of a bug in the PHY.  */
-	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT2, &val);
-	cphy_mdio_read(cphy, MDIO_MMD_PCS, MDIO_STAT2, &val);
-
-	/* Allows for Link,Ack LED turn on/off */
-	led_init(cphy);
-	return cphy;
-}
-
-/* Chip Reset */
-static int mv88x201x_phy_reset(adapter_t *adapter)
-{
-	u32 val;
-
-	t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-	val &= ~4;
-	t1_tpi_write(adapter, A_ELMER0_GPO, val);
-	msleep(100);
-
-	t1_tpi_write(adapter, A_ELMER0_GPO, val | 4);
-	msleep(1000);
-
-	/* Now lets enable the Laser. Delay 100us */
-	t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-	val |= 0x8000;
-	t1_tpi_write(adapter, A_ELMER0_GPO, val);
-	udelay(100);
-	return 0;
-}
-
-const struct gphy t1_mv88x201x_ops = {
-	.create = mv88x201x_phy_create,
-	.reset = mv88x201x_phy_reset
-};
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/my3126.c linux-libre-3.2-gnu/drivers/net/chelsio/my3126.c
--- linux-libre-3.1-gnu/drivers/net/chelsio/my3126.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/my3126.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,209 +0,0 @@
-/* $Date: 2005/11/12 02:13:49 $ $RCSfile: my3126.c,v $ $Revision: 1.15 $ */
-#include "cphy.h"
-#include "elmer0.h"
-#include "suni1x10gexp_regs.h"
-
-/* Port Reset */
-static int my3126_reset(struct cphy *cphy, int wait)
-{
-	/*
-	 * This can be done through registers.  It is not required since
-	 * a full chip reset is used.
-	 */
-	return 0;
-}
-
-static int my3126_interrupt_enable(struct cphy *cphy)
-{
-	schedule_delayed_work(&cphy->phy_update, HZ/30);
-	t1_tpi_read(cphy->adapter, A_ELMER0_GPO, &cphy->elmer_gpo);
-	return 0;
-}
-
-static int my3126_interrupt_disable(struct cphy *cphy)
-{
-	cancel_delayed_work_sync(&cphy->phy_update);
-	return 0;
-}
-
-static int my3126_interrupt_clear(struct cphy *cphy)
-{
-	return 0;
-}
-
-#define OFFSET(REG_ADDR)    (REG_ADDR << 2)
-
-static int my3126_interrupt_handler(struct cphy *cphy)
-{
-	u32 val;
-	u16 val16;
-	u16 status;
-	u32 act_count;
-	adapter_t *adapter;
-	adapter = cphy->adapter;
-
-	if (cphy->count == 50) {
-		cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
-		val16 = (u16) val;
-		status = cphy->bmsr ^ val16;
-
-		if (status & MDIO_STAT1_LSTATUS)
-			t1_link_changed(adapter, 0);
-		cphy->bmsr = val16;
-
-		/* We have only enabled link change interrupts so it
-		   must be that
-		 */
-		cphy->count = 0;
-	}
-
-	t1_tpi_write(adapter, OFFSET(SUNI1x10GEXP_REG_MSTAT_CONTROL),
-		SUNI1x10GEXP_BITMSK_MSTAT_SNAP);
-	t1_tpi_read(adapter,
-		OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW), &act_count);
-	t1_tpi_read(adapter,
-		OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW), &val);
-	act_count += val;
-
-	/* Populate elmer_gpo with the register value */
-	t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-	cphy->elmer_gpo = val;
-
-	if ( (val & (1 << 8)) || (val & (1 << 19)) ||
-	     (cphy->act_count == act_count) || cphy->act_on ) {
-		if (is_T2(adapter))
-			val |= (1 << 9);
-		else if (t1_is_T1B(adapter))
-			val |= (1 << 20);
-		cphy->act_on = 0;
-	} else {
-		if (is_T2(adapter))
-			val &= ~(1 << 9);
-		else if (t1_is_T1B(adapter))
-			val &= ~(1 << 20);
-		cphy->act_on = 1;
-	}
-
-	t1_tpi_write(adapter, A_ELMER0_GPO, val);
-
-	cphy->elmer_gpo = val;
-	cphy->act_count = act_count;
-	cphy->count++;
-
-	return cphy_cause_link_change;
-}
-
-static void my3216_poll(struct work_struct *work)
-{
-	struct cphy *cphy = container_of(work, struct cphy, phy_update.work);
-
-	my3126_interrupt_handler(cphy);
-}
-
-static int my3126_set_loopback(struct cphy *cphy, int on)
-{
-	return 0;
-}
-
-/* To check the activity LED */
-static int my3126_get_link_status(struct cphy *cphy,
-			int *link_ok, int *speed, int *duplex, int *fc)
-{
-	u32 val;
-	u16 val16;
-	adapter_t *adapter;
-
-	adapter = cphy->adapter;
-	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
-	val16 = (u16) val;
-
-	/* Populate elmer_gpo with the register value */
-	t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-	cphy->elmer_gpo = val;
-
-	*link_ok = (val16 & MDIO_STAT1_LSTATUS);
-
-	if (*link_ok) {
-		/* Turn on the LED. */
-		if (is_T2(adapter))
-			 val &= ~(1 << 8);
-		else if (t1_is_T1B(adapter))
-			 val &= ~(1 << 19);
-	} else {
-		/* Turn off the LED. */
-		if (is_T2(adapter))
-			 val |= (1 << 8);
-		else if (t1_is_T1B(adapter))
-			 val |= (1 << 19);
-	}
-
-	t1_tpi_write(adapter, A_ELMER0_GPO, val);
-	cphy->elmer_gpo = val;
-	*speed = SPEED_10000;
-	*duplex = DUPLEX_FULL;
-
-	/* need to add flow control */
-	if (fc)
-		*fc = PAUSE_RX | PAUSE_TX;
-
-	return 0;
-}
-
-static void my3126_destroy(struct cphy *cphy)
-{
-	kfree(cphy);
-}
-
-static struct cphy_ops my3126_ops = {
-	.destroy		= my3126_destroy,
-	.reset			= my3126_reset,
-	.interrupt_enable	= my3126_interrupt_enable,
-	.interrupt_disable	= my3126_interrupt_disable,
-	.interrupt_clear	= my3126_interrupt_clear,
-	.interrupt_handler	= my3126_interrupt_handler,
-	.get_link_status	= my3126_get_link_status,
-	.set_loopback		= my3126_set_loopback,
-	.mmds			= (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |
-				   MDIO_DEVS_PHYXS),
-};
-
-static struct cphy *my3126_phy_create(struct net_device *dev,
-			int phy_addr, const struct mdio_ops *mdio_ops)
-{
-	struct cphy *cphy = kzalloc(sizeof (*cphy), GFP_KERNEL);
-
-	if (!cphy)
-		return NULL;
-
-	cphy_init(cphy, dev, phy_addr, &my3126_ops, mdio_ops);
-	INIT_DELAYED_WORK(&cphy->phy_update, my3216_poll);
-	cphy->bmsr = 0;
-
-	return cphy;
-}
-
-/* Chip Reset */
-static int my3126_phy_reset(adapter_t * adapter)
-{
-	u32 val;
-
-	t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-	val &= ~4;
-	t1_tpi_write(adapter, A_ELMER0_GPO, val);
-	msleep(100);
-
-	t1_tpi_write(adapter, A_ELMER0_GPO, val | 4);
-	msleep(1000);
-
-	/* Now lets enable the Laser. Delay 100us */
-	t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-	val |= 0x8000;
-	t1_tpi_write(adapter, A_ELMER0_GPO, val);
-	udelay(100);
-	return 0;
-}
-
-const struct gphy t1_my3126_ops = {
-	.create = my3126_phy_create,
-	.reset = my3126_phy_reset
-};
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/pm3393.c linux-libre-3.2-gnu/drivers/net/chelsio/pm3393.c
--- linux-libre-3.1-gnu/drivers/net/chelsio/pm3393.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/pm3393.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,796 +0,0 @@
-/*****************************************************************************
- *                                                                           *
- * File: pm3393.c                                                            *
- * $Revision: 1.16 $                                                         *
- * $Date: 2005/05/14 00:59:32 $                                              *
- * Description:                                                              *
- *  PMC/SIERRA (pm3393) MAC-PHY functionality.                               *
- *  part of the Chelsio 10Gb Ethernet 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.                                *
- *                                                                           *
- * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
- *                                                                           *
- * http://www.chelsio.com                                                    *
- *                                                                           *
- * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
- * All rights reserved.                                                      *
- *                                                                           *
- * Maintainers: maintainers@chelsio.com                                      *
- *                                                                           *
- * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
- *          Tina Yang               <tainay@chelsio.com>                     *
- *          Felix Marti             <felix@chelsio.com>                      *
- *          Scott Bardone           <sbardone@chelsio.com>                   *
- *          Kurt Ottaway            <kottaway@chelsio.com>                   *
- *          Frank DiMambro          <frank@chelsio.com>                      *
- *                                                                           *
- * History:                                                                  *
- *                                                                           *
- ****************************************************************************/
-
-#include "common.h"
-#include "regs.h"
-#include "gmac.h"
-#include "elmer0.h"
-#include "suni1x10gexp_regs.h"
-
-#include <linux/crc32.h>
-#include <linux/slab.h>
-
-#define OFFSET(REG_ADDR)    ((REG_ADDR) << 2)
-
-/* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */
-#define MAX_FRAME_SIZE  9600
-
-#define IPG 12
-#define TXXG_CONF1_VAL ((IPG << SUNI1x10GEXP_BITOFF_TXXG_IPGT) | \
-	SUNI1x10GEXP_BITMSK_TXXG_32BIT_ALIGN | SUNI1x10GEXP_BITMSK_TXXG_CRCEN | \
-	SUNI1x10GEXP_BITMSK_TXXG_PADEN)
-#define RXXG_CONF1_VAL (SUNI1x10GEXP_BITMSK_RXXG_PUREP | 0x14 | \
-	SUNI1x10GEXP_BITMSK_RXXG_FLCHK | SUNI1x10GEXP_BITMSK_RXXG_CRC_STRIP)
-
-/* Update statistics every 15 minutes */
-#define STATS_TICK_SECS (15 * 60)
-
-enum {                     /* RMON registers */
-	RxOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW,
-	RxUnicastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_4_LOW,
-	RxMulticastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_5_LOW,
-	RxBroadcastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_6_LOW,
-	RxPAUSEMACCtrlFramesReceived = SUNI1x10GEXP_REG_MSTAT_COUNTER_8_LOW,
-	RxFrameCheckSequenceErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_10_LOW,
-	RxFramesLostDueToInternalMACErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_11_LOW,
-	RxSymbolErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_12_LOW,
-	RxInRangeLengthErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_13_LOW,
-	RxFramesTooLongErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_15_LOW,
-	RxJabbers = SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW,
-	RxFragments = SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW,
-	RxUndersizedFrames =  SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW,
-	RxJumboFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_25_LOW,
-	RxJumboOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_26_LOW,
-
-	TxOctetsTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW,
-	TxFramesLostDueToInternalMACTransmissionError = SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW,
-	TxTransmitSystemError = SUNI1x10GEXP_REG_MSTAT_COUNTER_36_LOW,
-	TxUnicastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW,
-	TxMulticastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW,
-	TxBroadcastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW,
-	TxPAUSEMACCtrlFramesTransmitted = SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW,
-	TxJumboFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_51_LOW,
-	TxJumboOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_52_LOW
-};
-
-struct _cmac_instance {
-	u8 enabled;
-	u8 fc;
-	u8 mac_addr[6];
-};
-
-static int pmread(struct cmac *cmac, u32 reg, u32 * data32)
-{
-	t1_tpi_read(cmac->adapter, OFFSET(reg), data32);
-	return 0;
-}
-
-static int pmwrite(struct cmac *cmac, u32 reg, u32 data32)
-{
-	t1_tpi_write(cmac->adapter, OFFSET(reg), data32);
-	return 0;
-}
-
-/* Port reset. */
-static int pm3393_reset(struct cmac *cmac)
-{
-	return 0;
-}
-
-/*
- * Enable interrupts for the PM3393
- *
- *	1. Enable PM3393 BLOCK interrupts.
- *	2. Enable PM3393 Master Interrupt bit(INTE)
- *	3. Enable ELMER's PM3393 bit.
- *	4. Enable Terminator external interrupt.
- */
-static int pm3393_interrupt_enable(struct cmac *cmac)
-{
-	u32 pl_intr;
-
-	/* PM3393 - Enabling all hardware block interrupts.
-	 */
-	pmwrite(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE, 0xffff);
-	pmwrite(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE, 0xffff);
-	pmwrite(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE, 0xffff);
-	pmwrite(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE, 0xffff);
-
-	/* Don't interrupt on statistics overflow, we are polling */
-	pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3, 0);
-
-	pmwrite(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE, 0xffff);
-	pmwrite(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK, 0xffff);
-	pmwrite(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE, 0xffff);
-	pmwrite(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE, 0xffff);
-	pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_3, 0xffff);
-	pmwrite(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK, 0xffff);
-	pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_3, 0xffff);
-	pmwrite(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK, 0xffff);
-	pmwrite(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE, 0xffff);
-
-	/* PM3393 - Global interrupt enable
-	 */
-	/* TBD XXX Disable for now until we figure out why error interrupts keep asserting. */
-	pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE,
-		0 /*SUNI1x10GEXP_BITMSK_TOP_INTE */ );
-
-	/* TERMINATOR - PL_INTERUPTS_EXT */
-	pl_intr = readl(cmac->adapter->regs + A_PL_ENABLE);
-	pl_intr |= F_PL_INTR_EXT;
-	writel(pl_intr, cmac->adapter->regs + A_PL_ENABLE);
-	return 0;
-}
-
-static int pm3393_interrupt_disable(struct cmac *cmac)
-{
-	u32 elmer;
-
-	/* PM3393 - Enabling HW interrupt blocks. */
-	pmwrite(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_3, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_3, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK, 0);
-	pmwrite(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE, 0);
-
-	/* PM3393 - Global interrupt enable */
-	pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE, 0);
-
-	/* ELMER - External chip interrupts. */
-	t1_tpi_read(cmac->adapter, A_ELMER0_INT_ENABLE, &elmer);
-	elmer &= ~ELMER0_GP_BIT1;
-	t1_tpi_write(cmac->adapter, A_ELMER0_INT_ENABLE, elmer);
-
-	/* TERMINATOR - PL_INTERUPTS_EXT */
-	/* DO NOT DISABLE TERMINATOR's EXTERNAL INTERRUPTS. ANOTHER CHIP
-	 * COULD WANT THEM ENABLED. We disable PM3393 at the ELMER level.
-	 */
-
-	return 0;
-}
-
-static int pm3393_interrupt_clear(struct cmac *cmac)
-{
-	u32 elmer;
-	u32 pl_intr;
-	u32 val32;
-
-	/* PM3393 - Clearing HW interrupt blocks. Note, this assumes
-	 *          bit WCIMODE=0 for a clear-on-read.
-	 */
-	pmread(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_STATUS, &val32);
-	pmread(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_STATUS, &val32);
-	pmread(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_STATUS, &val32);
-	pmread(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_STATUS, &val32);
-	pmread(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT, &val32);
-	pmread(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_STATUS, &val32);
-	pmread(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_INTERRUPT, &val32);
-	pmread(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_STATUS, &val32);
-	pmread(cmac, SUNI1x10GEXP_REG_RXXG_INTERRUPT, &val32);
-	pmread(cmac, SUNI1x10GEXP_REG_TXXG_INTERRUPT, &val32);
-	pmread(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT, &val32);
-	pmread(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_INDICATION,
-	       &val32);
-	pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_STATUS, &val32);
-	pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_CHANGE, &val32);
-
-	/* PM3393 - Global interrupt status
-	 */
-	pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS, &val32);
-
-	/* ELMER - External chip interrupts.
-	 */
-	t1_tpi_read(cmac->adapter, A_ELMER0_INT_CAUSE, &elmer);
-	elmer |= ELMER0_GP_BIT1;
-	t1_tpi_write(cmac->adapter, A_ELMER0_INT_CAUSE, elmer);
-
-	/* TERMINATOR - PL_INTERUPTS_EXT
-	 */
-	pl_intr = readl(cmac->adapter->regs + A_PL_CAUSE);
-	pl_intr |= F_PL_INTR_EXT;
-	writel(pl_intr, cmac->adapter->regs + A_PL_CAUSE);
-
-	return 0;
-}
-
-/* Interrupt handler */
-static int pm3393_interrupt_handler(struct cmac *cmac)
-{
-	u32 master_intr_status;
-
-	/* Read the master interrupt status register. */
-	pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS,
-	       &master_intr_status);
-	if (netif_msg_intr(cmac->adapter))
-		dev_dbg(&cmac->adapter->pdev->dev, "PM3393 intr cause 0x%x\n",
-			master_intr_status);
-
-	/* TBD XXX Lets just clear everything for now */
-	pm3393_interrupt_clear(cmac);
-
-	return 0;
-}
-
-static int pm3393_enable(struct cmac *cmac, int which)
-{
-	if (which & MAC_DIRECTION_RX)
-		pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1,
-			(RXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_RXXG_RXEN));
-
-	if (which & MAC_DIRECTION_TX) {
-		u32 val = TXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_TXXG_TXEN0;
-
-		if (cmac->instance->fc & PAUSE_RX)
-			val |= SUNI1x10GEXP_BITMSK_TXXG_FCRX;
-		if (cmac->instance->fc & PAUSE_TX)
-			val |= SUNI1x10GEXP_BITMSK_TXXG_FCTX;
-		pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, val);
-	}
-
-	cmac->instance->enabled |= which;
-	return 0;
-}
-
-static int pm3393_enable_port(struct cmac *cmac, int which)
-{
-	/* Clear port statistics */
-	pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
-		SUNI1x10GEXP_BITMSK_MSTAT_CLEAR);
-	udelay(2);
-	memset(&cmac->stats, 0, sizeof(struct cmac_statistics));
-
-	pm3393_enable(cmac, which);
-
-	/*
-	 * 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.
-	 */
-	t1_link_changed(cmac->adapter, 0);
-	return 0;
-}
-
-static int pm3393_disable(struct cmac *cmac, int which)
-{
-	if (which & MAC_DIRECTION_RX)
-		pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1, RXXG_CONF1_VAL);
-	if (which & MAC_DIRECTION_TX)
-		pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, TXXG_CONF1_VAL);
-
-	/*
-	 * The disable is graceful. Give the PM3393 time.  Can't wait very
-	 * long here, we may be holding locks.
-	 */
-	udelay(20);
-
-	cmac->instance->enabled &= ~which;
-	return 0;
-}
-
-static int pm3393_loopback_enable(struct cmac *cmac)
-{
-	return 0;
-}
-
-static int pm3393_loopback_disable(struct cmac *cmac)
-{
-	return 0;
-}
-
-static int pm3393_set_mtu(struct cmac *cmac, int mtu)
-{
-	int enabled = cmac->instance->enabled;
-
-	/* MAX_FRAME_SIZE includes header + FCS, mtu doesn't */
-	mtu += 14 + 4;
-	if (mtu > MAX_FRAME_SIZE)
-		return -EINVAL;
-
-	/* Disable Rx/Tx MAC before configuring it. */
-	if (enabled)
-		pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
-
-	pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MAX_FRAME_LENGTH, mtu);
-	pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_MAX_FRAME_SIZE, mtu);
-
-	if (enabled)
-		pm3393_enable(cmac, enabled);
-	return 0;
-}
-
-static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm)
-{
-	int enabled = cmac->instance->enabled & MAC_DIRECTION_RX;
-	u32 rx_mode;
-
-	/* Disable MAC RX before reconfiguring it */
-	if (enabled)
-		pm3393_disable(cmac, MAC_DIRECTION_RX);
-
-	pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, &rx_mode);
-	rx_mode &= ~(SUNI1x10GEXP_BITMSK_RXXG_PMODE |
-		     SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN);
-	pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2,
-		(u16)rx_mode);
-
-	if (t1_rx_mode_promisc(rm)) {
-		/* Promiscuous mode. */
-		rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_PMODE;
-	}
-	if (t1_rx_mode_allmulti(rm)) {
-		/* Accept all multicast. */
-		pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, 0xffff);
-		pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, 0xffff);
-		pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, 0xffff);
-		pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, 0xffff);
-		rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
-	} else if (t1_rx_mode_mc_cnt(rm)) {
-		/* Accept one or more multicast(s). */
-		struct netdev_hw_addr *ha;
-		int bit;
-		u16 mc_filter[4] = { 0, };
-
-		netdev_for_each_mc_addr(ha, t1_get_netdev(rm)) {
-			/* bit[23:28] */
-			bit = (ether_crc(ETH_ALEN, ha->addr) >> 23) & 0x3f;
-			mc_filter[bit >> 4] |= 1 << (bit & 0xf);
-		}
-		pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, mc_filter[0]);
-		pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, mc_filter[1]);
-		pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, mc_filter[2]);
-		pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, mc_filter[3]);
-		rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
-	}
-
-	pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, (u16)rx_mode);
-
-	if (enabled)
-		pm3393_enable(cmac, MAC_DIRECTION_RX);
-
-	return 0;
-}
-
-static int pm3393_get_speed_duplex_fc(struct cmac *cmac, int *speed,
-				      int *duplex, int *fc)
-{
-	if (speed)
-		*speed = SPEED_10000;
-	if (duplex)
-		*duplex = DUPLEX_FULL;
-	if (fc)
-		*fc = cmac->instance->fc;
-	return 0;
-}
-
-static int pm3393_set_speed_duplex_fc(struct cmac *cmac, int speed, int duplex,
-				      int fc)
-{
-	if (speed >= 0 && speed != SPEED_10000)
-		return -1;
-	if (duplex >= 0 && duplex != DUPLEX_FULL)
-		return -1;
-	if (fc & ~(PAUSE_TX | PAUSE_RX))
-		return -1;
-
-	if (fc != cmac->instance->fc) {
-		cmac->instance->fc = (u8) fc;
-		if (cmac->instance->enabled & MAC_DIRECTION_TX)
-			pm3393_enable(cmac, MAC_DIRECTION_TX);
-	}
-	return 0;
-}
-
-#define RMON_UPDATE(mac, name, stat_name) \
-{ \
-	t1_tpi_read((mac)->adapter, OFFSET(name), &val0);     \
-	t1_tpi_read((mac)->adapter, OFFSET((name)+1), &val1); \
-	t1_tpi_read((mac)->adapter, OFFSET((name)+2), &val2); \
-	(mac)->stats.stat_name = (u64)(val0 & 0xffff) | \
-				 ((u64)(val1 & 0xffff) << 16) | \
-				 ((u64)(val2 & 0xff) << 32) | \
-				 ((mac)->stats.stat_name & \
-					0xffffff0000000000ULL); \
-	if (ro & \
-	    (1ULL << ((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2))) \
-		(mac)->stats.stat_name += 1ULL << 40; \
-}
-
-static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac,
-							      int flag)
-{
-	u64	ro;
-	u32	val0, val1, val2, val3;
-
-	/* Snap the counters */
-	pmwrite(mac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
-		SUNI1x10GEXP_BITMSK_MSTAT_SNAP);
-
-	/* Counter rollover, clear on read */
-	pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_0, &val0);
-	pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_1, &val1);
-	pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_2, &val2);
-	pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_3, &val3);
-	ro = ((u64)val0 & 0xffff) | (((u64)val1 & 0xffff) << 16) |
-		(((u64)val2 & 0xffff) << 32) | (((u64)val3 & 0xffff) << 48);
-
-	/* Rx stats */
-	RMON_UPDATE(mac, RxOctetsReceivedOK, RxOctetsOK);
-	RMON_UPDATE(mac, RxUnicastFramesReceivedOK, RxUnicastFramesOK);
-	RMON_UPDATE(mac, RxMulticastFramesReceivedOK, RxMulticastFramesOK);
-	RMON_UPDATE(mac, RxBroadcastFramesReceivedOK, RxBroadcastFramesOK);
-	RMON_UPDATE(mac, RxPAUSEMACCtrlFramesReceived, RxPauseFrames);
-	RMON_UPDATE(mac, RxFrameCheckSequenceErrors, RxFCSErrors);
-	RMON_UPDATE(mac, RxFramesLostDueToInternalMACErrors,
-				RxInternalMACRcvError);
-	RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors);
-	RMON_UPDATE(mac, RxInRangeLengthErrors, RxInRangeLengthErrors);
-	RMON_UPDATE(mac, RxFramesTooLongErrors , RxFrameTooLongErrors);
-	RMON_UPDATE(mac, RxJabbers, RxJabberErrors);
-	RMON_UPDATE(mac, RxFragments, RxRuntErrors);
-	RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors);
-	RMON_UPDATE(mac, RxJumboFramesReceivedOK, RxJumboFramesOK);
-	RMON_UPDATE(mac, RxJumboOctetsReceivedOK, RxJumboOctetsOK);
-
-	/* Tx stats */
-	RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK);
-	RMON_UPDATE(mac, TxFramesLostDueToInternalMACTransmissionError,
-				TxInternalMACXmitError);
-	RMON_UPDATE(mac, TxTransmitSystemError, TxFCSErrors);
-	RMON_UPDATE(mac, TxUnicastFramesTransmittedOK, TxUnicastFramesOK);
-	RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK);
-	RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK);
-	RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames);
-	RMON_UPDATE(mac, TxJumboFramesReceivedOK, TxJumboFramesOK);
-	RMON_UPDATE(mac, TxJumboOctetsReceivedOK, TxJumboOctetsOK);
-
-	return &mac->stats;
-}
-
-static int pm3393_macaddress_get(struct cmac *cmac, u8 mac_addr[6])
-{
-	memcpy(mac_addr, cmac->instance->mac_addr, 6);
-	return 0;
-}
-
-static int pm3393_macaddress_set(struct cmac *cmac, u8 ma[6])
-{
-	u32 val, lo, mid, hi, enabled = cmac->instance->enabled;
-
-	/*
-	 * MAC addr: 00:07:43:00:13:09
-	 *
-	 * ma[5] = 0x09
-	 * ma[4] = 0x13
-	 * ma[3] = 0x00
-	 * ma[2] = 0x43
-	 * ma[1] = 0x07
-	 * ma[0] = 0x00
-	 *
-	 * The PM3393 requires byte swapping and reverse order entry
-	 * when programming MAC addresses:
-	 *
-	 * low_bits[15:0]    = ma[1]:ma[0]
-	 * mid_bits[31:16]   = ma[3]:ma[2]
-	 * high_bits[47:32]  = ma[5]:ma[4]
-	 */
-
-	/* Store local copy */
-	memcpy(cmac->instance->mac_addr, ma, 6);
-
-	lo  = ((u32) ma[1] << 8) | (u32) ma[0];
-	mid = ((u32) ma[3] << 8) | (u32) ma[2];
-	hi  = ((u32) ma[5] << 8) | (u32) ma[4];
-
-	/* Disable Rx/Tx MAC before configuring it. */
-	if (enabled)
-		pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
-
-	/* Set RXXG Station Address */
-	pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_15_0, lo);
-	pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_31_16, mid);
-	pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_47_32, hi);
-
-	/* Set TXXG Station Address */
-	pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_15_0, lo);
-	pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_31_16, mid);
-	pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_47_32, hi);
-
-	/* Setup Exact Match Filter 1 with our MAC address
-	 *
-	 * Must disable exact match filter before configuring it.
-	 */
-	pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, &val);
-	val &= 0xff0f;
-	pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
-
-	pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_LOW, lo);
-	pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_MID, mid);
-	pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_HIGH, hi);
-
-	val |= 0x0090;
-	pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
-
-	if (enabled)
-		pm3393_enable(cmac, enabled);
-	return 0;
-}
-
-static void pm3393_destroy(struct cmac *cmac)
-{
-	kfree(cmac);
-}
-
-static struct cmac_ops pm3393_ops = {
-	.destroy                 = pm3393_destroy,
-	.reset                   = pm3393_reset,
-	.interrupt_enable        = pm3393_interrupt_enable,
-	.interrupt_disable       = pm3393_interrupt_disable,
-	.interrupt_clear         = pm3393_interrupt_clear,
-	.interrupt_handler       = pm3393_interrupt_handler,
-	.enable                  = pm3393_enable_port,
-	.disable                 = pm3393_disable,
-	.loopback_enable         = pm3393_loopback_enable,
-	.loopback_disable        = pm3393_loopback_disable,
-	.set_mtu                 = pm3393_set_mtu,
-	.set_rx_mode             = pm3393_set_rx_mode,
-	.get_speed_duplex_fc     = pm3393_get_speed_duplex_fc,
-	.set_speed_duplex_fc     = pm3393_set_speed_duplex_fc,
-	.statistics_update       = pm3393_update_statistics,
-	.macaddress_get          = pm3393_macaddress_get,
-	.macaddress_set          = pm3393_macaddress_set
-};
-
-static struct cmac *pm3393_mac_create(adapter_t *adapter, int index)
-{
-	struct cmac *cmac;
-
-	cmac = kzalloc(sizeof(*cmac) + sizeof(cmac_instance), GFP_KERNEL);
-	if (!cmac)
-		return NULL;
-
-	cmac->ops = &pm3393_ops;
-	cmac->instance = (cmac_instance *) (cmac + 1);
-	cmac->adapter = adapter;
-	cmac->instance->fc = PAUSE_TX | PAUSE_RX;
-
-	t1_tpi_write(adapter, OFFSET(0x0001), 0x00008000);
-	t1_tpi_write(adapter, OFFSET(0x0001), 0x00000000);
-	t1_tpi_write(adapter, OFFSET(0x2308), 0x00009800);
-	t1_tpi_write(adapter, OFFSET(0x2305), 0x00001001);   /* PL4IO Enable */
-	t1_tpi_write(adapter, OFFSET(0x2320), 0x00008800);
-	t1_tpi_write(adapter, OFFSET(0x2321), 0x00008800);
-	t1_tpi_write(adapter, OFFSET(0x2322), 0x00008800);
-	t1_tpi_write(adapter, OFFSET(0x2323), 0x00008800);
-	t1_tpi_write(adapter, OFFSET(0x2324), 0x00008800);
-	t1_tpi_write(adapter, OFFSET(0x2325), 0x00008800);
-	t1_tpi_write(adapter, OFFSET(0x2326), 0x00008800);
-	t1_tpi_write(adapter, OFFSET(0x2327), 0x00008800);
-	t1_tpi_write(adapter, OFFSET(0x2328), 0x00008800);
-	t1_tpi_write(adapter, OFFSET(0x2329), 0x00008800);
-	t1_tpi_write(adapter, OFFSET(0x232a), 0x00008800);
-	t1_tpi_write(adapter, OFFSET(0x232b), 0x00008800);
-	t1_tpi_write(adapter, OFFSET(0x232c), 0x00008800);
-	t1_tpi_write(adapter, OFFSET(0x232d), 0x00008800);
-	t1_tpi_write(adapter, OFFSET(0x232e), 0x00008800);
-	t1_tpi_write(adapter, OFFSET(0x232f), 0x00008800);
-	t1_tpi_write(adapter, OFFSET(0x230d), 0x00009c00);
-	t1_tpi_write(adapter, OFFSET(0x2304), 0x00000202);	/* PL4IO Calendar Repetitions */
-
-	t1_tpi_write(adapter, OFFSET(0x3200), 0x00008080);	/* EFLX Enable */
-	t1_tpi_write(adapter, OFFSET(0x3210), 0x00000000);	/* EFLX Channel Deprovision */
-	t1_tpi_write(adapter, OFFSET(0x3203), 0x00000000);	/* EFLX Low Limit */
-	t1_tpi_write(adapter, OFFSET(0x3204), 0x00000040);	/* EFLX High Limit */
-	t1_tpi_write(adapter, OFFSET(0x3205), 0x000002cc);	/* EFLX Almost Full */
-	t1_tpi_write(adapter, OFFSET(0x3206), 0x00000199);	/* EFLX Almost Empty */
-	t1_tpi_write(adapter, OFFSET(0x3207), 0x00000240);	/* EFLX Cut Through Threshold */
-	t1_tpi_write(adapter, OFFSET(0x3202), 0x00000000);	/* EFLX Indirect Register Update */
-	t1_tpi_write(adapter, OFFSET(0x3210), 0x00000001);	/* EFLX Channel Provision */
-	t1_tpi_write(adapter, OFFSET(0x3208), 0x0000ffff);	/* EFLX Undocumented */
-	t1_tpi_write(adapter, OFFSET(0x320a), 0x0000ffff);	/* EFLX Undocumented */
-	t1_tpi_write(adapter, OFFSET(0x320c), 0x0000ffff);	/* EFLX enable overflow interrupt The other bit are undocumented */
-	t1_tpi_write(adapter, OFFSET(0x320e), 0x0000ffff);	/* EFLX Undocumented */
-
-	t1_tpi_write(adapter, OFFSET(0x2200), 0x0000c000);	/* IFLX Configuration - enable */
-	t1_tpi_write(adapter, OFFSET(0x2201), 0x00000000);	/* IFLX Channel Deprovision */
-	t1_tpi_write(adapter, OFFSET(0x220e), 0x00000000);	/* IFLX Low Limit */
-	t1_tpi_write(adapter, OFFSET(0x220f), 0x00000100);	/* IFLX High Limit */
-	t1_tpi_write(adapter, OFFSET(0x2210), 0x00000c00);	/* IFLX Almost Full Limit */
-	t1_tpi_write(adapter, OFFSET(0x2211), 0x00000599);	/* IFLX Almost Empty Limit */
-	t1_tpi_write(adapter, OFFSET(0x220d), 0x00000000);	/* IFLX Indirect Register Update */
-	t1_tpi_write(adapter, OFFSET(0x2201), 0x00000001);	/* IFLX Channel Provision */
-	t1_tpi_write(adapter, OFFSET(0x2203), 0x0000ffff);	/* IFLX Undocumented */
-	t1_tpi_write(adapter, OFFSET(0x2205), 0x0000ffff);	/* IFLX Undocumented */
-	t1_tpi_write(adapter, OFFSET(0x2209), 0x0000ffff);	/* IFLX Enable overflow interrupt.  The other bit are undocumented */
-
-	t1_tpi_write(adapter, OFFSET(0x2241), 0xfffffffe);	/* PL4MOS Undocumented */
-	t1_tpi_write(adapter, OFFSET(0x2242), 0x0000ffff);	/* PL4MOS Undocumented */
-	t1_tpi_write(adapter, OFFSET(0x2243), 0x00000008);	/* PL4MOS Starving Burst Size */
-	t1_tpi_write(adapter, OFFSET(0x2244), 0x00000008);	/* PL4MOS Hungry Burst Size */
-	t1_tpi_write(adapter, OFFSET(0x2245), 0x00000008);	/* PL4MOS Transfer Size */
-	t1_tpi_write(adapter, OFFSET(0x2240), 0x00000005);	/* PL4MOS Disable */
-
-	t1_tpi_write(adapter, OFFSET(0x2280), 0x00002103);	/* PL4ODP Training Repeat and SOP rule */
-	t1_tpi_write(adapter, OFFSET(0x2284), 0x00000000);	/* PL4ODP MAX_T setting */
-
-	t1_tpi_write(adapter, OFFSET(0x3280), 0x00000087);	/* PL4IDU Enable data forward, port state machine. Set ALLOW_NON_ZERO_OLB */
-	t1_tpi_write(adapter, OFFSET(0x3282), 0x0000001f);	/* PL4IDU Enable Dip4 check error interrupts */
-
-	t1_tpi_write(adapter, OFFSET(0x3040), 0x0c32);	/* # TXXG Config */
-	/* For T1 use timer based Mac flow control. */
-	t1_tpi_write(adapter, OFFSET(0x304d), 0x8000);
-	t1_tpi_write(adapter, OFFSET(0x2040), 0x059c);	/* # RXXG Config */
-	t1_tpi_write(adapter, OFFSET(0x2049), 0x0001);	/* # RXXG Cut Through */
-	t1_tpi_write(adapter, OFFSET(0x2070), 0x0000);	/* # Disable promiscuous mode */
-
-	/* Setup Exact Match Filter 0 to allow broadcast packets.
-	 */
-	t1_tpi_write(adapter, OFFSET(0x206e), 0x0000);	/* # Disable Match Enable bit */
-	t1_tpi_write(adapter, OFFSET(0x204a), 0xffff);	/* # low addr */
-	t1_tpi_write(adapter, OFFSET(0x204b), 0xffff);	/* # mid addr */
-	t1_tpi_write(adapter, OFFSET(0x204c), 0xffff);	/* # high addr */
-	t1_tpi_write(adapter, OFFSET(0x206e), 0x0009);	/* # Enable Match Enable bit */
-
-	t1_tpi_write(adapter, OFFSET(0x0003), 0x0000);	/* # NO SOP/ PAD_EN setup */
-	t1_tpi_write(adapter, OFFSET(0x0100), 0x0ff0);	/* # RXEQB disabled */
-	t1_tpi_write(adapter, OFFSET(0x0101), 0x0f0f);	/* # No Preemphasis */
-
-	return cmac;
-}
-
-static int pm3393_mac_reset(adapter_t * adapter)
-{
-	u32 val;
-	u32 x;
-	u32 is_pl4_reset_finished;
-	u32 is_pl4_outof_lock;
-	u32 is_xaui_mabc_pll_locked;
-	u32 successful_reset;
-	int i;
-
-	/* The following steps are required to properly reset
-	 * the PM3393. This information is provided in the
-	 * PM3393 datasheet (Issue 2: November 2002)
-	 * section 13.1 -- Device Reset.
-	 *
-	 * The PM3393 has three types of components that are
-	 * individually reset:
-	 *
-	 * DRESETB      - Digital circuitry
-	 * PL4_ARESETB  - PL4 analog circuitry
-	 * XAUI_ARESETB - XAUI bus analog circuitry
-	 *
-	 * Steps to reset PM3393 using RSTB pin:
-	 *
-	 * 1. Assert RSTB pin low ( write 0 )
-	 * 2. Wait at least 1ms to initiate a complete initialization of device.
-	 * 3. Wait until all external clocks and REFSEL are stable.
-	 * 4. Wait minimum of 1ms. (after external clocks and REFEL are stable)
-	 * 5. De-assert RSTB ( write 1 )
-	 * 6. Wait until internal timers to expires after ~14ms.
-	 *    - Allows analog clock synthesizer(PL4CSU) to stabilize to
-	 *      selected reference frequency before allowing the digital
-	 *      portion of the device to operate.
-	 * 7. Wait at least 200us for XAUI interface to stabilize.
-	 * 8. Verify the PM3393 came out of reset successfully.
-	 *    Set successful reset flag if everything worked else try again
-	 *    a few more times.
-	 */
-
-	successful_reset = 0;
-	for (i = 0; i < 3 && !successful_reset; i++) {
-		/* 1 */
-		t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-		val &= ~1;
-		t1_tpi_write(adapter, A_ELMER0_GPO, val);
-
-		/* 2 */
-		msleep(1);
-
-		/* 3 */
-		msleep(1);
-
-		/* 4 */
-		msleep(2 /*1 extra ms for safety */ );
-
-		/* 5 */
-		val |= 1;
-		t1_tpi_write(adapter, A_ELMER0_GPO, val);
-
-		/* 6 */
-		msleep(15 /*1 extra ms for safety */ );
-
-		/* 7 */
-		msleep(1);
-
-		/* 8 */
-
-		/* Has PL4 analog block come out of reset correctly? */
-		t1_tpi_read(adapter, OFFSET(SUNI1x10GEXP_REG_DEVICE_STATUS), &val);
-		is_pl4_reset_finished = (val & SUNI1x10GEXP_BITMSK_TOP_EXPIRED);
-
-		/* TBD XXX SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL gets locked later in the init sequence
-		 *         figure out why? */
-
-		/* Have all PL4 block clocks locked? */
-		x = (SUNI1x10GEXP_BITMSK_TOP_PL4_ID_DOOL
-		     /*| SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL */  |
-		     SUNI1x10GEXP_BITMSK_TOP_PL4_ID_ROOL |
-		     SUNI1x10GEXP_BITMSK_TOP_PL4_IS_ROOL |
-		     SUNI1x10GEXP_BITMSK_TOP_PL4_OUT_ROOL);
-		is_pl4_outof_lock = (val & x);
-
-		/* ??? If this fails, might be able to software reset the XAUI part
-		 *     and try to recover... thus saving us from doing another HW reset */
-		/* Has the XAUI MABC PLL circuitry stablized? */
-		is_xaui_mabc_pll_locked =
-		    (val & SUNI1x10GEXP_BITMSK_TOP_SXRA_EXPIRED);
-
-		successful_reset = (is_pl4_reset_finished && !is_pl4_outof_lock
-				    && is_xaui_mabc_pll_locked);
-
-		if (netif_msg_hw(adapter))
-			dev_dbg(&adapter->pdev->dev,
-				"PM3393 HW reset %d: pl4_reset 0x%x, val 0x%x, "
-				"is_pl4_outof_lock 0x%x, xaui_locked 0x%x\n",
-				i, is_pl4_reset_finished, val,
-				is_pl4_outof_lock, is_xaui_mabc_pll_locked);
-	}
-	return successful_reset ? 0 : 1;
-}
-
-const struct gmac t1_pm3393_ops = {
-	.stats_update_period = STATS_TICK_SECS,
-	.create              = pm3393_mac_create,
-	.reset               = pm3393_mac_reset,
-};
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/regs.h linux-libre-3.2-gnu/drivers/net/chelsio/regs.h
--- linux-libre-3.1-gnu/drivers/net/chelsio/regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/regs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,2168 +0,0 @@
-/*****************************************************************************
- *                                                                           *
- * File: regs.h                                                              *
- * $Revision: 1.8 $                                                          *
- * $Date: 2005/06/21 18:29:48 $                                              *
- * Description:                                                              *
- *  part of the Chelsio 10Gb Ethernet 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.                                *
- *                                                                           *
- * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
- *                                                                           *
- * http://www.chelsio.com                                                    *
- *                                                                           *
- * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
- * All rights reserved.                                                      *
- *                                                                           *
- * Maintainers: maintainers@chelsio.com                                      *
- *                                                                           *
- * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
- *          Tina Yang               <tainay@chelsio.com>                     *
- *          Felix Marti             <felix@chelsio.com>                      *
- *          Scott Bardone           <sbardone@chelsio.com>                   *
- *          Kurt Ottaway            <kottaway@chelsio.com>                   *
- *          Frank DiMambro          <frank@chelsio.com>                      *
- *                                                                           *
- * History:                                                                  *
- *                                                                           *
- ****************************************************************************/
-
-#ifndef _CXGB_REGS_H_
-#define _CXGB_REGS_H_
-
-/* SGE registers */
-#define A_SG_CONTROL 0x0
-
-#define S_CMDQ0_ENABLE    0
-#define V_CMDQ0_ENABLE(x) ((x) << S_CMDQ0_ENABLE)
-#define F_CMDQ0_ENABLE    V_CMDQ0_ENABLE(1U)
-
-#define S_CMDQ1_ENABLE    1
-#define V_CMDQ1_ENABLE(x) ((x) << S_CMDQ1_ENABLE)
-#define F_CMDQ1_ENABLE    V_CMDQ1_ENABLE(1U)
-
-#define S_FL0_ENABLE    2
-#define V_FL0_ENABLE(x) ((x) << S_FL0_ENABLE)
-#define F_FL0_ENABLE    V_FL0_ENABLE(1U)
-
-#define S_FL1_ENABLE    3
-#define V_FL1_ENABLE(x) ((x) << S_FL1_ENABLE)
-#define F_FL1_ENABLE    V_FL1_ENABLE(1U)
-
-#define S_CPL_ENABLE    4
-#define V_CPL_ENABLE(x) ((x) << S_CPL_ENABLE)
-#define F_CPL_ENABLE    V_CPL_ENABLE(1U)
-
-#define S_RESPONSE_QUEUE_ENABLE    5
-#define V_RESPONSE_QUEUE_ENABLE(x) ((x) << S_RESPONSE_QUEUE_ENABLE)
-#define F_RESPONSE_QUEUE_ENABLE    V_RESPONSE_QUEUE_ENABLE(1U)
-
-#define S_CMDQ_PRIORITY    6
-#define M_CMDQ_PRIORITY    0x3
-#define V_CMDQ_PRIORITY(x) ((x) << S_CMDQ_PRIORITY)
-#define G_CMDQ_PRIORITY(x) (((x) >> S_CMDQ_PRIORITY) & M_CMDQ_PRIORITY)
-
-#define S_DISABLE_CMDQ0_GTS    8
-#define V_DISABLE_CMDQ0_GTS(x) ((x) << S_DISABLE_CMDQ0_GTS)
-#define F_DISABLE_CMDQ0_GTS    V_DISABLE_CMDQ0_GTS(1U)
-
-#define S_DISABLE_CMDQ1_GTS    9
-#define V_DISABLE_CMDQ1_GTS(x) ((x) << S_DISABLE_CMDQ1_GTS)
-#define F_DISABLE_CMDQ1_GTS    V_DISABLE_CMDQ1_GTS(1U)
-
-#define S_DISABLE_FL0_GTS    10
-#define V_DISABLE_FL0_GTS(x) ((x) << S_DISABLE_FL0_GTS)
-#define F_DISABLE_FL0_GTS    V_DISABLE_FL0_GTS(1U)
-
-#define S_DISABLE_FL1_GTS    11
-#define V_DISABLE_FL1_GTS(x) ((x) << S_DISABLE_FL1_GTS)
-#define F_DISABLE_FL1_GTS    V_DISABLE_FL1_GTS(1U)
-
-#define S_ENABLE_BIG_ENDIAN    12
-#define V_ENABLE_BIG_ENDIAN(x) ((x) << S_ENABLE_BIG_ENDIAN)
-#define F_ENABLE_BIG_ENDIAN    V_ENABLE_BIG_ENDIAN(1U)
-
-#define S_FL_SELECTION_CRITERIA    13
-#define V_FL_SELECTION_CRITERIA(x) ((x) << S_FL_SELECTION_CRITERIA)
-#define F_FL_SELECTION_CRITERIA    V_FL_SELECTION_CRITERIA(1U)
-
-#define S_ISCSI_COALESCE    14
-#define V_ISCSI_COALESCE(x) ((x) << S_ISCSI_COALESCE)
-#define F_ISCSI_COALESCE    V_ISCSI_COALESCE(1U)
-
-#define S_RX_PKT_OFFSET    15
-#define M_RX_PKT_OFFSET    0x7
-#define V_RX_PKT_OFFSET(x) ((x) << S_RX_PKT_OFFSET)
-#define G_RX_PKT_OFFSET(x) (((x) >> S_RX_PKT_OFFSET) & M_RX_PKT_OFFSET)
-
-#define S_VLAN_XTRACT    18
-#define V_VLAN_XTRACT(x) ((x) << S_VLAN_XTRACT)
-#define F_VLAN_XTRACT    V_VLAN_XTRACT(1U)
-
-#define A_SG_DOORBELL 0x4
-#define A_SG_CMD0BASELWR 0x8
-#define A_SG_CMD0BASEUPR 0xc
-#define A_SG_CMD1BASELWR 0x10
-#define A_SG_CMD1BASEUPR 0x14
-#define A_SG_FL0BASELWR 0x18
-#define A_SG_FL0BASEUPR 0x1c
-#define A_SG_FL1BASELWR 0x20
-#define A_SG_FL1BASEUPR 0x24
-#define A_SG_CMD0SIZE 0x28
-
-#define S_CMDQ0_SIZE    0
-#define M_CMDQ0_SIZE    0x1ffff
-#define V_CMDQ0_SIZE(x) ((x) << S_CMDQ0_SIZE)
-#define G_CMDQ0_SIZE(x) (((x) >> S_CMDQ0_SIZE) & M_CMDQ0_SIZE)
-
-#define A_SG_FL0SIZE 0x2c
-
-#define S_FL0_SIZE    0
-#define M_FL0_SIZE    0x1ffff
-#define V_FL0_SIZE(x) ((x) << S_FL0_SIZE)
-#define G_FL0_SIZE(x) (((x) >> S_FL0_SIZE) & M_FL0_SIZE)
-
-#define A_SG_RSPSIZE 0x30
-
-#define S_RESPQ_SIZE    0
-#define M_RESPQ_SIZE    0x1ffff
-#define V_RESPQ_SIZE(x) ((x) << S_RESPQ_SIZE)
-#define G_RESPQ_SIZE(x) (((x) >> S_RESPQ_SIZE) & M_RESPQ_SIZE)
-
-#define A_SG_RSPBASELWR 0x34
-#define A_SG_RSPBASEUPR 0x38
-#define A_SG_FLTHRESHOLD 0x3c
-
-#define S_FL_THRESHOLD    0
-#define M_FL_THRESHOLD    0xffff
-#define V_FL_THRESHOLD(x) ((x) << S_FL_THRESHOLD)
-#define G_FL_THRESHOLD(x) (((x) >> S_FL_THRESHOLD) & M_FL_THRESHOLD)
-
-#define A_SG_RSPQUEUECREDIT 0x40
-
-#define S_RESPQ_CREDIT    0
-#define M_RESPQ_CREDIT    0x1ffff
-#define V_RESPQ_CREDIT(x) ((x) << S_RESPQ_CREDIT)
-#define G_RESPQ_CREDIT(x) (((x) >> S_RESPQ_CREDIT) & M_RESPQ_CREDIT)
-
-#define A_SG_SLEEPING 0x48
-
-#define S_SLEEPING    0
-#define M_SLEEPING    0xffff
-#define V_SLEEPING(x) ((x) << S_SLEEPING)
-#define G_SLEEPING(x) (((x) >> S_SLEEPING) & M_SLEEPING)
-
-#define A_SG_INTRTIMER 0x4c
-
-#define S_INTERRUPT_TIMER_COUNT    0
-#define M_INTERRUPT_TIMER_COUNT    0xffffff
-#define V_INTERRUPT_TIMER_COUNT(x) ((x) << S_INTERRUPT_TIMER_COUNT)
-#define G_INTERRUPT_TIMER_COUNT(x) (((x) >> S_INTERRUPT_TIMER_COUNT) & M_INTERRUPT_TIMER_COUNT)
-
-#define A_SG_CMD0PTR 0x50
-
-#define S_CMDQ0_POINTER    0
-#define M_CMDQ0_POINTER    0xffff
-#define V_CMDQ0_POINTER(x) ((x) << S_CMDQ0_POINTER)
-#define G_CMDQ0_POINTER(x) (((x) >> S_CMDQ0_POINTER) & M_CMDQ0_POINTER)
-
-#define S_CURRENT_GENERATION_BIT    16
-#define V_CURRENT_GENERATION_BIT(x) ((x) << S_CURRENT_GENERATION_BIT)
-#define F_CURRENT_GENERATION_BIT    V_CURRENT_GENERATION_BIT(1U)
-
-#define A_SG_CMD1PTR 0x54
-
-#define S_CMDQ1_POINTER    0
-#define M_CMDQ1_POINTER    0xffff
-#define V_CMDQ1_POINTER(x) ((x) << S_CMDQ1_POINTER)
-#define G_CMDQ1_POINTER(x) (((x) >> S_CMDQ1_POINTER) & M_CMDQ1_POINTER)
-
-#define A_SG_FL0PTR 0x58
-
-#define S_FL0_POINTER    0
-#define M_FL0_POINTER    0xffff
-#define V_FL0_POINTER(x) ((x) << S_FL0_POINTER)
-#define G_FL0_POINTER(x) (((x) >> S_FL0_POINTER) & M_FL0_POINTER)
-
-#define A_SG_FL1PTR 0x5c
-
-#define S_FL1_POINTER    0
-#define M_FL1_POINTER    0xffff
-#define V_FL1_POINTER(x) ((x) << S_FL1_POINTER)
-#define G_FL1_POINTER(x) (((x) >> S_FL1_POINTER) & M_FL1_POINTER)
-
-#define A_SG_VERSION 0x6c
-
-#define S_DAY    0
-#define M_DAY    0x1f
-#define V_DAY(x) ((x) << S_DAY)
-#define G_DAY(x) (((x) >> S_DAY) & M_DAY)
-
-#define S_MONTH    5
-#define M_MONTH    0xf
-#define V_MONTH(x) ((x) << S_MONTH)
-#define G_MONTH(x) (((x) >> S_MONTH) & M_MONTH)
-
-#define A_SG_CMD1SIZE 0xb0
-
-#define S_CMDQ1_SIZE    0
-#define M_CMDQ1_SIZE    0x1ffff
-#define V_CMDQ1_SIZE(x) ((x) << S_CMDQ1_SIZE)
-#define G_CMDQ1_SIZE(x) (((x) >> S_CMDQ1_SIZE) & M_CMDQ1_SIZE)
-
-#define A_SG_FL1SIZE 0xb4
-
-#define S_FL1_SIZE    0
-#define M_FL1_SIZE    0x1ffff
-#define V_FL1_SIZE(x) ((x) << S_FL1_SIZE)
-#define G_FL1_SIZE(x) (((x) >> S_FL1_SIZE) & M_FL1_SIZE)
-
-#define A_SG_INT_ENABLE 0xb8
-
-#define S_RESPQ_EXHAUSTED    0
-#define V_RESPQ_EXHAUSTED(x) ((x) << S_RESPQ_EXHAUSTED)
-#define F_RESPQ_EXHAUSTED    V_RESPQ_EXHAUSTED(1U)
-
-#define S_RESPQ_OVERFLOW    1
-#define V_RESPQ_OVERFLOW(x) ((x) << S_RESPQ_OVERFLOW)
-#define F_RESPQ_OVERFLOW    V_RESPQ_OVERFLOW(1U)
-
-#define S_FL_EXHAUSTED    2
-#define V_FL_EXHAUSTED(x) ((x) << S_FL_EXHAUSTED)
-#define F_FL_EXHAUSTED    V_FL_EXHAUSTED(1U)
-
-#define S_PACKET_TOO_BIG    3
-#define V_PACKET_TOO_BIG(x) ((x) << S_PACKET_TOO_BIG)
-#define F_PACKET_TOO_BIG    V_PACKET_TOO_BIG(1U)
-
-#define S_PACKET_MISMATCH    4
-#define V_PACKET_MISMATCH(x) ((x) << S_PACKET_MISMATCH)
-#define F_PACKET_MISMATCH    V_PACKET_MISMATCH(1U)
-
-#define A_SG_INT_CAUSE 0xbc
-#define A_SG_RESPACCUTIMER 0xc0
-
-/* MC3 registers */
-#define A_MC3_CFG 0x100
-
-#define S_CLK_ENABLE    0
-#define V_CLK_ENABLE(x) ((x) << S_CLK_ENABLE)
-#define F_CLK_ENABLE    V_CLK_ENABLE(1U)
-
-#define S_READY    1
-#define V_READY(x) ((x) << S_READY)
-#define F_READY    V_READY(1U)
-
-#define S_READ_TO_WRITE_DELAY    2
-#define M_READ_TO_WRITE_DELAY    0x7
-#define V_READ_TO_WRITE_DELAY(x) ((x) << S_READ_TO_WRITE_DELAY)
-#define G_READ_TO_WRITE_DELAY(x) (((x) >> S_READ_TO_WRITE_DELAY) & M_READ_TO_WRITE_DELAY)
-
-#define S_WRITE_TO_READ_DELAY    5
-#define M_WRITE_TO_READ_DELAY    0x7
-#define V_WRITE_TO_READ_DELAY(x) ((x) << S_WRITE_TO_READ_DELAY)
-#define G_WRITE_TO_READ_DELAY(x) (((x) >> S_WRITE_TO_READ_DELAY) & M_WRITE_TO_READ_DELAY)
-
-#define S_MC3_BANK_CYCLE    8
-#define M_MC3_BANK_CYCLE    0xf
-#define V_MC3_BANK_CYCLE(x) ((x) << S_MC3_BANK_CYCLE)
-#define G_MC3_BANK_CYCLE(x) (((x) >> S_MC3_BANK_CYCLE) & M_MC3_BANK_CYCLE)
-
-#define S_REFRESH_CYCLE    12
-#define M_REFRESH_CYCLE    0xf
-#define V_REFRESH_CYCLE(x) ((x) << S_REFRESH_CYCLE)
-#define G_REFRESH_CYCLE(x) (((x) >> S_REFRESH_CYCLE) & M_REFRESH_CYCLE)
-
-#define S_PRECHARGE_CYCLE    16
-#define M_PRECHARGE_CYCLE    0x3
-#define V_PRECHARGE_CYCLE(x) ((x) << S_PRECHARGE_CYCLE)
-#define G_PRECHARGE_CYCLE(x) (((x) >> S_PRECHARGE_CYCLE) & M_PRECHARGE_CYCLE)
-
-#define S_ACTIVE_TO_READ_WRITE_DELAY    18
-#define V_ACTIVE_TO_READ_WRITE_DELAY(x) ((x) << S_ACTIVE_TO_READ_WRITE_DELAY)
-#define F_ACTIVE_TO_READ_WRITE_DELAY    V_ACTIVE_TO_READ_WRITE_DELAY(1U)
-
-#define S_ACTIVE_TO_PRECHARGE_DELAY    19
-#define M_ACTIVE_TO_PRECHARGE_DELAY    0x7
-#define V_ACTIVE_TO_PRECHARGE_DELAY(x) ((x) << S_ACTIVE_TO_PRECHARGE_DELAY)
-#define G_ACTIVE_TO_PRECHARGE_DELAY(x) (((x) >> S_ACTIVE_TO_PRECHARGE_DELAY) & M_ACTIVE_TO_PRECHARGE_DELAY)
-
-#define S_WRITE_RECOVERY_DELAY    22
-#define M_WRITE_RECOVERY_DELAY    0x3
-#define V_WRITE_RECOVERY_DELAY(x) ((x) << S_WRITE_RECOVERY_DELAY)
-#define G_WRITE_RECOVERY_DELAY(x) (((x) >> S_WRITE_RECOVERY_DELAY) & M_WRITE_RECOVERY_DELAY)
-
-#define S_DENSITY    24
-#define M_DENSITY    0x3
-#define V_DENSITY(x) ((x) << S_DENSITY)
-#define G_DENSITY(x) (((x) >> S_DENSITY) & M_DENSITY)
-
-#define S_ORGANIZATION    26
-#define V_ORGANIZATION(x) ((x) << S_ORGANIZATION)
-#define F_ORGANIZATION    V_ORGANIZATION(1U)
-
-#define S_BANKS    27
-#define V_BANKS(x) ((x) << S_BANKS)
-#define F_BANKS    V_BANKS(1U)
-
-#define S_UNREGISTERED    28
-#define V_UNREGISTERED(x) ((x) << S_UNREGISTERED)
-#define F_UNREGISTERED    V_UNREGISTERED(1U)
-
-#define S_MC3_WIDTH    29
-#define M_MC3_WIDTH    0x3
-#define V_MC3_WIDTH(x) ((x) << S_MC3_WIDTH)
-#define G_MC3_WIDTH(x) (((x) >> S_MC3_WIDTH) & M_MC3_WIDTH)
-
-#define S_MC3_SLOW    31
-#define V_MC3_SLOW(x) ((x) << S_MC3_SLOW)
-#define F_MC3_SLOW    V_MC3_SLOW(1U)
-
-#define A_MC3_MODE 0x104
-
-#define S_MC3_MODE    0
-#define M_MC3_MODE    0x3fff
-#define V_MC3_MODE(x) ((x) << S_MC3_MODE)
-#define G_MC3_MODE(x) (((x) >> S_MC3_MODE) & M_MC3_MODE)
-
-#define S_BUSY    31
-#define V_BUSY(x) ((x) << S_BUSY)
-#define F_BUSY    V_BUSY(1U)
-
-#define A_MC3_EXT_MODE 0x108
-
-#define S_MC3_EXTENDED_MODE    0
-#define M_MC3_EXTENDED_MODE    0x3fff
-#define V_MC3_EXTENDED_MODE(x) ((x) << S_MC3_EXTENDED_MODE)
-#define G_MC3_EXTENDED_MODE(x) (((x) >> S_MC3_EXTENDED_MODE) & M_MC3_EXTENDED_MODE)
-
-#define A_MC3_PRECHARG 0x10c
-#define A_MC3_REFRESH 0x110
-
-#define S_REFRESH_ENABLE    0
-#define V_REFRESH_ENABLE(x) ((x) << S_REFRESH_ENABLE)
-#define F_REFRESH_ENABLE    V_REFRESH_ENABLE(1U)
-
-#define S_REFRESH_DIVISOR    1
-#define M_REFRESH_DIVISOR    0x3fff
-#define V_REFRESH_DIVISOR(x) ((x) << S_REFRESH_DIVISOR)
-#define G_REFRESH_DIVISOR(x) (((x) >> S_REFRESH_DIVISOR) & M_REFRESH_DIVISOR)
-
-#define A_MC3_STROBE 0x114
-
-#define S_MASTER_DLL_RESET    0
-#define V_MASTER_DLL_RESET(x) ((x) << S_MASTER_DLL_RESET)
-#define F_MASTER_DLL_RESET    V_MASTER_DLL_RESET(1U)
-
-#define S_MASTER_DLL_TAP_COUNT    1
-#define M_MASTER_DLL_TAP_COUNT    0xff
-#define V_MASTER_DLL_TAP_COUNT(x) ((x) << S_MASTER_DLL_TAP_COUNT)
-#define G_MASTER_DLL_TAP_COUNT(x) (((x) >> S_MASTER_DLL_TAP_COUNT) & M_MASTER_DLL_TAP_COUNT)
-
-#define S_MASTER_DLL_LOCKED    9
-#define V_MASTER_DLL_LOCKED(x) ((x) << S_MASTER_DLL_LOCKED)
-#define F_MASTER_DLL_LOCKED    V_MASTER_DLL_LOCKED(1U)
-
-#define S_MASTER_DLL_MAX_TAP_COUNT    10
-#define V_MASTER_DLL_MAX_TAP_COUNT(x) ((x) << S_MASTER_DLL_MAX_TAP_COUNT)
-#define F_MASTER_DLL_MAX_TAP_COUNT    V_MASTER_DLL_MAX_TAP_COUNT(1U)
-
-#define S_MASTER_DLL_TAP_COUNT_OFFSET    11
-#define M_MASTER_DLL_TAP_COUNT_OFFSET    0x3f
-#define V_MASTER_DLL_TAP_COUNT_OFFSET(x) ((x) << S_MASTER_DLL_TAP_COUNT_OFFSET)
-#define G_MASTER_DLL_TAP_COUNT_OFFSET(x) (((x) >> S_MASTER_DLL_TAP_COUNT_OFFSET) & M_MASTER_DLL_TAP_COUNT_OFFSET)
-
-#define S_SLAVE_DLL_RESET    11
-#define V_SLAVE_DLL_RESET(x) ((x) << S_SLAVE_DLL_RESET)
-#define F_SLAVE_DLL_RESET    V_SLAVE_DLL_RESET(1U)
-
-#define S_SLAVE_DLL_DELTA    12
-#define M_SLAVE_DLL_DELTA    0xf
-#define V_SLAVE_DLL_DELTA(x) ((x) << S_SLAVE_DLL_DELTA)
-#define G_SLAVE_DLL_DELTA(x) (((x) >> S_SLAVE_DLL_DELTA) & M_SLAVE_DLL_DELTA)
-
-#define S_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT    17
-#define M_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT    0x3f
-#define V_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT(x) ((x) << S_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT)
-#define G_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT(x) (((x) >> S_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT) & M_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT)
-
-#define S_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT_ENABLE    23
-#define V_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT_ENABLE(x) ((x) << S_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT_ENABLE)
-#define F_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT_ENABLE    V_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT_ENABLE(1U)
-
-#define S_SLAVE_DELAY_LINE_TAP_COUNT    24
-#define M_SLAVE_DELAY_LINE_TAP_COUNT    0x3f
-#define V_SLAVE_DELAY_LINE_TAP_COUNT(x) ((x) << S_SLAVE_DELAY_LINE_TAP_COUNT)
-#define G_SLAVE_DELAY_LINE_TAP_COUNT(x) (((x) >> S_SLAVE_DELAY_LINE_TAP_COUNT) & M_SLAVE_DELAY_LINE_TAP_COUNT)
-
-#define A_MC3_ECC_CNTL 0x118
-
-#define S_ECC_GENERATION_ENABLE    0
-#define V_ECC_GENERATION_ENABLE(x) ((x) << S_ECC_GENERATION_ENABLE)
-#define F_ECC_GENERATION_ENABLE    V_ECC_GENERATION_ENABLE(1U)
-
-#define S_ECC_CHECK_ENABLE    1
-#define V_ECC_CHECK_ENABLE(x) ((x) << S_ECC_CHECK_ENABLE)
-#define F_ECC_CHECK_ENABLE    V_ECC_CHECK_ENABLE(1U)
-
-#define S_CORRECTABLE_ERROR_COUNT    2
-#define M_CORRECTABLE_ERROR_COUNT    0xff
-#define V_CORRECTABLE_ERROR_COUNT(x) ((x) << S_CORRECTABLE_ERROR_COUNT)
-#define G_CORRECTABLE_ERROR_COUNT(x) (((x) >> S_CORRECTABLE_ERROR_COUNT) & M_CORRECTABLE_ERROR_COUNT)
-
-#define S_UNCORRECTABLE_ERROR_COUNT    10
-#define M_UNCORRECTABLE_ERROR_COUNT    0xff
-#define V_UNCORRECTABLE_ERROR_COUNT(x) ((x) << S_UNCORRECTABLE_ERROR_COUNT)
-#define G_UNCORRECTABLE_ERROR_COUNT(x) (((x) >> S_UNCORRECTABLE_ERROR_COUNT) & M_UNCORRECTABLE_ERROR_COUNT)
-
-#define A_MC3_CE_ADDR 0x11c
-
-#define S_MC3_CE_ADDR    4
-#define M_MC3_CE_ADDR    0xfffffff
-#define V_MC3_CE_ADDR(x) ((x) << S_MC3_CE_ADDR)
-#define G_MC3_CE_ADDR(x) (((x) >> S_MC3_CE_ADDR) & M_MC3_CE_ADDR)
-
-#define A_MC3_CE_DATA0 0x120
-#define A_MC3_CE_DATA1 0x124
-#define A_MC3_CE_DATA2 0x128
-#define A_MC3_CE_DATA3 0x12c
-#define A_MC3_CE_DATA4 0x130
-#define A_MC3_UE_ADDR 0x134
-
-#define S_MC3_UE_ADDR    4
-#define M_MC3_UE_ADDR    0xfffffff
-#define V_MC3_UE_ADDR(x) ((x) << S_MC3_UE_ADDR)
-#define G_MC3_UE_ADDR(x) (((x) >> S_MC3_UE_ADDR) & M_MC3_UE_ADDR)
-
-#define A_MC3_UE_DATA0 0x138
-#define A_MC3_UE_DATA1 0x13c
-#define A_MC3_UE_DATA2 0x140
-#define A_MC3_UE_DATA3 0x144
-#define A_MC3_UE_DATA4 0x148
-#define A_MC3_BD_ADDR 0x14c
-#define A_MC3_BD_DATA0 0x150
-#define A_MC3_BD_DATA1 0x154
-#define A_MC3_BD_DATA2 0x158
-#define A_MC3_BD_DATA3 0x15c
-#define A_MC3_BD_DATA4 0x160
-#define A_MC3_BD_OP 0x164
-
-#define S_BACK_DOOR_OPERATION    0
-#define V_BACK_DOOR_OPERATION(x) ((x) << S_BACK_DOOR_OPERATION)
-#define F_BACK_DOOR_OPERATION    V_BACK_DOOR_OPERATION(1U)
-
-#define A_MC3_BIST_ADDR_BEG 0x168
-#define A_MC3_BIST_ADDR_END 0x16c
-#define A_MC3_BIST_DATA 0x170
-#define A_MC3_BIST_OP 0x174
-
-#define S_OP    0
-#define V_OP(x) ((x) << S_OP)
-#define F_OP    V_OP(1U)
-
-#define S_DATA_PATTERN    1
-#define M_DATA_PATTERN    0x3
-#define V_DATA_PATTERN(x) ((x) << S_DATA_PATTERN)
-#define G_DATA_PATTERN(x) (((x) >> S_DATA_PATTERN) & M_DATA_PATTERN)
-
-#define S_CONTINUOUS    3
-#define V_CONTINUOUS(x) ((x) << S_CONTINUOUS)
-#define F_CONTINUOUS    V_CONTINUOUS(1U)
-
-#define A_MC3_INT_ENABLE 0x178
-
-#define S_MC3_CORR_ERR    0
-#define V_MC3_CORR_ERR(x) ((x) << S_MC3_CORR_ERR)
-#define F_MC3_CORR_ERR    V_MC3_CORR_ERR(1U)
-
-#define S_MC3_UNCORR_ERR    1
-#define V_MC3_UNCORR_ERR(x) ((x) << S_MC3_UNCORR_ERR)
-#define F_MC3_UNCORR_ERR    V_MC3_UNCORR_ERR(1U)
-
-#define S_MC3_PARITY_ERR    2
-#define M_MC3_PARITY_ERR    0xff
-#define V_MC3_PARITY_ERR(x) ((x) << S_MC3_PARITY_ERR)
-#define G_MC3_PARITY_ERR(x) (((x) >> S_MC3_PARITY_ERR) & M_MC3_PARITY_ERR)
-
-#define S_MC3_ADDR_ERR    10
-#define V_MC3_ADDR_ERR(x) ((x) << S_MC3_ADDR_ERR)
-#define F_MC3_ADDR_ERR    V_MC3_ADDR_ERR(1U)
-
-#define A_MC3_INT_CAUSE 0x17c
-
-/* MC4 registers */
-#define A_MC4_CFG 0x180
-
-#define S_POWER_UP    0
-#define V_POWER_UP(x) ((x) << S_POWER_UP)
-#define F_POWER_UP    V_POWER_UP(1U)
-
-#define S_MC4_BANK_CYCLE    8
-#define M_MC4_BANK_CYCLE    0x7
-#define V_MC4_BANK_CYCLE(x) ((x) << S_MC4_BANK_CYCLE)
-#define G_MC4_BANK_CYCLE(x) (((x) >> S_MC4_BANK_CYCLE) & M_MC4_BANK_CYCLE)
-
-#define S_MC4_NARROW    24
-#define V_MC4_NARROW(x) ((x) << S_MC4_NARROW)
-#define F_MC4_NARROW    V_MC4_NARROW(1U)
-
-#define S_MC4_SLOW    25
-#define V_MC4_SLOW(x) ((x) << S_MC4_SLOW)
-#define F_MC4_SLOW    V_MC4_SLOW(1U)
-
-#define S_MC4A_WIDTH    24
-#define M_MC4A_WIDTH    0x3
-#define V_MC4A_WIDTH(x) ((x) << S_MC4A_WIDTH)
-#define G_MC4A_WIDTH(x) (((x) >> S_MC4A_WIDTH) & M_MC4A_WIDTH)
-
-#define S_MC4A_SLOW    26
-#define V_MC4A_SLOW(x) ((x) << S_MC4A_SLOW)
-#define F_MC4A_SLOW    V_MC4A_SLOW(1U)
-
-#define A_MC4_MODE 0x184
-
-#define S_MC4_MODE    0
-#define M_MC4_MODE    0x7fff
-#define V_MC4_MODE(x) ((x) << S_MC4_MODE)
-#define G_MC4_MODE(x) (((x) >> S_MC4_MODE) & M_MC4_MODE)
-
-#define A_MC4_EXT_MODE 0x188
-
-#define S_MC4_EXTENDED_MODE    0
-#define M_MC4_EXTENDED_MODE    0x7fff
-#define V_MC4_EXTENDED_MODE(x) ((x) << S_MC4_EXTENDED_MODE)
-#define G_MC4_EXTENDED_MODE(x) (((x) >> S_MC4_EXTENDED_MODE) & M_MC4_EXTENDED_MODE)
-
-#define A_MC4_REFRESH 0x190
-#define A_MC4_STROBE 0x194
-#define A_MC4_ECC_CNTL 0x198
-#define A_MC4_CE_ADDR 0x19c
-
-#define S_MC4_CE_ADDR    4
-#define M_MC4_CE_ADDR    0xffffff
-#define V_MC4_CE_ADDR(x) ((x) << S_MC4_CE_ADDR)
-#define G_MC4_CE_ADDR(x) (((x) >> S_MC4_CE_ADDR) & M_MC4_CE_ADDR)
-
-#define A_MC4_CE_DATA0 0x1a0
-#define A_MC4_CE_DATA1 0x1a4
-#define A_MC4_CE_DATA2 0x1a8
-#define A_MC4_CE_DATA3 0x1ac
-#define A_MC4_CE_DATA4 0x1b0
-#define A_MC4_UE_ADDR 0x1b4
-
-#define S_MC4_UE_ADDR    4
-#define M_MC4_UE_ADDR    0xffffff
-#define V_MC4_UE_ADDR(x) ((x) << S_MC4_UE_ADDR)
-#define G_MC4_UE_ADDR(x) (((x) >> S_MC4_UE_ADDR) & M_MC4_UE_ADDR)
-
-#define A_MC4_UE_DATA0 0x1b8
-#define A_MC4_UE_DATA1 0x1bc
-#define A_MC4_UE_DATA2 0x1c0
-#define A_MC4_UE_DATA3 0x1c4
-#define A_MC4_UE_DATA4 0x1c8
-#define A_MC4_BD_ADDR 0x1cc
-
-#define S_MC4_BACK_DOOR_ADDR    0
-#define M_MC4_BACK_DOOR_ADDR    0xfffffff
-#define V_MC4_BACK_DOOR_ADDR(x) ((x) << S_MC4_BACK_DOOR_ADDR)
-#define G_MC4_BACK_DOOR_ADDR(x) (((x) >> S_MC4_BACK_DOOR_ADDR) & M_MC4_BACK_DOOR_ADDR)
-
-#define A_MC4_BD_DATA0 0x1d0
-#define A_MC4_BD_DATA1 0x1d4
-#define A_MC4_BD_DATA2 0x1d8
-#define A_MC4_BD_DATA3 0x1dc
-#define A_MC4_BD_DATA4 0x1e0
-#define A_MC4_BD_OP 0x1e4
-
-#define S_OPERATION    0
-#define V_OPERATION(x) ((x) << S_OPERATION)
-#define F_OPERATION    V_OPERATION(1U)
-
-#define A_MC4_BIST_ADDR_BEG 0x1e8
-#define A_MC4_BIST_ADDR_END 0x1ec
-#define A_MC4_BIST_DATA 0x1f0
-#define A_MC4_BIST_OP 0x1f4
-#define A_MC4_INT_ENABLE 0x1f8
-
-#define S_MC4_CORR_ERR    0
-#define V_MC4_CORR_ERR(x) ((x) << S_MC4_CORR_ERR)
-#define F_MC4_CORR_ERR    V_MC4_CORR_ERR(1U)
-
-#define S_MC4_UNCORR_ERR    1
-#define V_MC4_UNCORR_ERR(x) ((x) << S_MC4_UNCORR_ERR)
-#define F_MC4_UNCORR_ERR    V_MC4_UNCORR_ERR(1U)
-
-#define S_MC4_ADDR_ERR    2
-#define V_MC4_ADDR_ERR(x) ((x) << S_MC4_ADDR_ERR)
-#define F_MC4_ADDR_ERR    V_MC4_ADDR_ERR(1U)
-
-#define A_MC4_INT_CAUSE 0x1fc
-
-/* TPI registers */
-#define A_TPI_ADDR 0x280
-
-#define S_TPI_ADDRESS    0
-#define M_TPI_ADDRESS    0xffffff
-#define V_TPI_ADDRESS(x) ((x) << S_TPI_ADDRESS)
-#define G_TPI_ADDRESS(x) (((x) >> S_TPI_ADDRESS) & M_TPI_ADDRESS)
-
-#define A_TPI_WR_DATA 0x284
-#define A_TPI_RD_DATA 0x288
-#define A_TPI_CSR 0x28c
-
-#define S_TPIWR    0
-#define V_TPIWR(x) ((x) << S_TPIWR)
-#define F_TPIWR    V_TPIWR(1U)
-
-#define S_TPIRDY    1
-#define V_TPIRDY(x) ((x) << S_TPIRDY)
-#define F_TPIRDY    V_TPIRDY(1U)
-
-#define S_INT_DIR    31
-#define V_INT_DIR(x) ((x) << S_INT_DIR)
-#define F_INT_DIR    V_INT_DIR(1U)
-
-#define A_TPI_PAR 0x29c
-
-#define S_TPIPAR    0
-#define M_TPIPAR    0x7f
-#define V_TPIPAR(x) ((x) << S_TPIPAR)
-#define G_TPIPAR(x) (((x) >> S_TPIPAR) & M_TPIPAR)
-
-
-/* TP registers */
-#define A_TP_IN_CONFIG 0x300
-
-#define S_TP_IN_CSPI_TUNNEL    0
-#define V_TP_IN_CSPI_TUNNEL(x) ((x) << S_TP_IN_CSPI_TUNNEL)
-#define F_TP_IN_CSPI_TUNNEL    V_TP_IN_CSPI_TUNNEL(1U)
-
-#define S_TP_IN_CSPI_ETHERNET    1
-#define V_TP_IN_CSPI_ETHERNET(x) ((x) << S_TP_IN_CSPI_ETHERNET)
-#define F_TP_IN_CSPI_ETHERNET    V_TP_IN_CSPI_ETHERNET(1U)
-
-#define S_TP_IN_CSPI_CPL    3
-#define V_TP_IN_CSPI_CPL(x) ((x) << S_TP_IN_CSPI_CPL)
-#define F_TP_IN_CSPI_CPL    V_TP_IN_CSPI_CPL(1U)
-
-#define S_TP_IN_CSPI_POS    4
-#define V_TP_IN_CSPI_POS(x) ((x) << S_TP_IN_CSPI_POS)
-#define F_TP_IN_CSPI_POS    V_TP_IN_CSPI_POS(1U)
-
-#define S_TP_IN_CSPI_CHECK_IP_CSUM    5
-#define V_TP_IN_CSPI_CHECK_IP_CSUM(x) ((x) << S_TP_IN_CSPI_CHECK_IP_CSUM)
-#define F_TP_IN_CSPI_CHECK_IP_CSUM    V_TP_IN_CSPI_CHECK_IP_CSUM(1U)
-
-#define S_TP_IN_CSPI_CHECK_TCP_CSUM    6
-#define V_TP_IN_CSPI_CHECK_TCP_CSUM(x) ((x) << S_TP_IN_CSPI_CHECK_TCP_CSUM)
-#define F_TP_IN_CSPI_CHECK_TCP_CSUM    V_TP_IN_CSPI_CHECK_TCP_CSUM(1U)
-
-#define S_TP_IN_ESPI_TUNNEL    7
-#define V_TP_IN_ESPI_TUNNEL(x) ((x) << S_TP_IN_ESPI_TUNNEL)
-#define F_TP_IN_ESPI_TUNNEL    V_TP_IN_ESPI_TUNNEL(1U)
-
-#define S_TP_IN_ESPI_ETHERNET    8
-#define V_TP_IN_ESPI_ETHERNET(x) ((x) << S_TP_IN_ESPI_ETHERNET)
-#define F_TP_IN_ESPI_ETHERNET    V_TP_IN_ESPI_ETHERNET(1U)
-
-#define S_TP_IN_ESPI_CPL    10
-#define V_TP_IN_ESPI_CPL(x) ((x) << S_TP_IN_ESPI_CPL)
-#define F_TP_IN_ESPI_CPL    V_TP_IN_ESPI_CPL(1U)
-
-#define S_TP_IN_ESPI_POS    11
-#define V_TP_IN_ESPI_POS(x) ((x) << S_TP_IN_ESPI_POS)
-#define F_TP_IN_ESPI_POS    V_TP_IN_ESPI_POS(1U)
-
-#define S_TP_IN_ESPI_CHECK_IP_CSUM    12
-#define V_TP_IN_ESPI_CHECK_IP_CSUM(x) ((x) << S_TP_IN_ESPI_CHECK_IP_CSUM)
-#define F_TP_IN_ESPI_CHECK_IP_CSUM    V_TP_IN_ESPI_CHECK_IP_CSUM(1U)
-
-#define S_TP_IN_ESPI_CHECK_TCP_CSUM    13
-#define V_TP_IN_ESPI_CHECK_TCP_CSUM(x) ((x) << S_TP_IN_ESPI_CHECK_TCP_CSUM)
-#define F_TP_IN_ESPI_CHECK_TCP_CSUM    V_TP_IN_ESPI_CHECK_TCP_CSUM(1U)
-
-#define S_OFFLOAD_DISABLE    14
-#define V_OFFLOAD_DISABLE(x) ((x) << S_OFFLOAD_DISABLE)
-#define F_OFFLOAD_DISABLE    V_OFFLOAD_DISABLE(1U)
-
-#define A_TP_OUT_CONFIG 0x304
-
-#define S_TP_OUT_C_ETH    0
-#define V_TP_OUT_C_ETH(x) ((x) << S_TP_OUT_C_ETH)
-#define F_TP_OUT_C_ETH    V_TP_OUT_C_ETH(1U)
-
-#define S_TP_OUT_CSPI_CPL    2
-#define V_TP_OUT_CSPI_CPL(x) ((x) << S_TP_OUT_CSPI_CPL)
-#define F_TP_OUT_CSPI_CPL    V_TP_OUT_CSPI_CPL(1U)
-
-#define S_TP_OUT_CSPI_POS    3
-#define V_TP_OUT_CSPI_POS(x) ((x) << S_TP_OUT_CSPI_POS)
-#define F_TP_OUT_CSPI_POS    V_TP_OUT_CSPI_POS(1U)
-
-#define S_TP_OUT_CSPI_GENERATE_IP_CSUM    4
-#define V_TP_OUT_CSPI_GENERATE_IP_CSUM(x) ((x) << S_TP_OUT_CSPI_GENERATE_IP_CSUM)
-#define F_TP_OUT_CSPI_GENERATE_IP_CSUM    V_TP_OUT_CSPI_GENERATE_IP_CSUM(1U)
-
-#define S_TP_OUT_CSPI_GENERATE_TCP_CSUM    5
-#define V_TP_OUT_CSPI_GENERATE_TCP_CSUM(x) ((x) << S_TP_OUT_CSPI_GENERATE_TCP_CSUM)
-#define F_TP_OUT_CSPI_GENERATE_TCP_CSUM    V_TP_OUT_CSPI_GENERATE_TCP_CSUM(1U)
-
-#define S_TP_OUT_ESPI_ETHERNET    6
-#define V_TP_OUT_ESPI_ETHERNET(x) ((x) << S_TP_OUT_ESPI_ETHERNET)
-#define F_TP_OUT_ESPI_ETHERNET    V_TP_OUT_ESPI_ETHERNET(1U)
-
-#define S_TP_OUT_ESPI_TAG_ETHERNET    7
-#define V_TP_OUT_ESPI_TAG_ETHERNET(x) ((x) << S_TP_OUT_ESPI_TAG_ETHERNET)
-#define F_TP_OUT_ESPI_TAG_ETHERNET    V_TP_OUT_ESPI_TAG_ETHERNET(1U)
-
-#define S_TP_OUT_ESPI_CPL    8
-#define V_TP_OUT_ESPI_CPL(x) ((x) << S_TP_OUT_ESPI_CPL)
-#define F_TP_OUT_ESPI_CPL    V_TP_OUT_ESPI_CPL(1U)
-
-#define S_TP_OUT_ESPI_POS    9
-#define V_TP_OUT_ESPI_POS(x) ((x) << S_TP_OUT_ESPI_POS)
-#define F_TP_OUT_ESPI_POS    V_TP_OUT_ESPI_POS(1U)
-
-#define S_TP_OUT_ESPI_GENERATE_IP_CSUM    10
-#define V_TP_OUT_ESPI_GENERATE_IP_CSUM(x) ((x) << S_TP_OUT_ESPI_GENERATE_IP_CSUM)
-#define F_TP_OUT_ESPI_GENERATE_IP_CSUM    V_TP_OUT_ESPI_GENERATE_IP_CSUM(1U)
-
-#define S_TP_OUT_ESPI_GENERATE_TCP_CSUM    11
-#define V_TP_OUT_ESPI_GENERATE_TCP_CSUM(x) ((x) << S_TP_OUT_ESPI_GENERATE_TCP_CSUM)
-#define F_TP_OUT_ESPI_GENERATE_TCP_CSUM    V_TP_OUT_ESPI_GENERATE_TCP_CSUM(1U)
-
-#define A_TP_GLOBAL_CONFIG 0x308
-
-#define S_IP_TTL    0
-#define M_IP_TTL    0xff
-#define V_IP_TTL(x) ((x) << S_IP_TTL)
-#define G_IP_TTL(x) (((x) >> S_IP_TTL) & M_IP_TTL)
-
-#define S_TCAM_SERVER_REGION_USAGE    8
-#define M_TCAM_SERVER_REGION_USAGE    0x3
-#define V_TCAM_SERVER_REGION_USAGE(x) ((x) << S_TCAM_SERVER_REGION_USAGE)
-#define G_TCAM_SERVER_REGION_USAGE(x) (((x) >> S_TCAM_SERVER_REGION_USAGE) & M_TCAM_SERVER_REGION_USAGE)
-
-#define S_QOS_MAPPING    10
-#define V_QOS_MAPPING(x) ((x) << S_QOS_MAPPING)
-#define F_QOS_MAPPING    V_QOS_MAPPING(1U)
-
-#define S_TCP_CSUM    11
-#define V_TCP_CSUM(x) ((x) << S_TCP_CSUM)
-#define F_TCP_CSUM    V_TCP_CSUM(1U)
-
-#define S_UDP_CSUM    12
-#define V_UDP_CSUM(x) ((x) << S_UDP_CSUM)
-#define F_UDP_CSUM    V_UDP_CSUM(1U)
-
-#define S_IP_CSUM    13
-#define V_IP_CSUM(x) ((x) << S_IP_CSUM)
-#define F_IP_CSUM    V_IP_CSUM(1U)
-
-#define S_IP_ID_SPLIT    14
-#define V_IP_ID_SPLIT(x) ((x) << S_IP_ID_SPLIT)
-#define F_IP_ID_SPLIT    V_IP_ID_SPLIT(1U)
-
-#define S_PATH_MTU    15
-#define V_PATH_MTU(x) ((x) << S_PATH_MTU)
-#define F_PATH_MTU    V_PATH_MTU(1U)
-
-#define S_5TUPLE_LOOKUP    17
-#define M_5TUPLE_LOOKUP    0x3
-#define V_5TUPLE_LOOKUP(x) ((x) << S_5TUPLE_LOOKUP)
-#define G_5TUPLE_LOOKUP(x) (((x) >> S_5TUPLE_LOOKUP) & M_5TUPLE_LOOKUP)
-
-#define S_IP_FRAGMENT_DROP    19
-#define V_IP_FRAGMENT_DROP(x) ((x) << S_IP_FRAGMENT_DROP)
-#define F_IP_FRAGMENT_DROP    V_IP_FRAGMENT_DROP(1U)
-
-#define S_PING_DROP    20
-#define V_PING_DROP(x) ((x) << S_PING_DROP)
-#define F_PING_DROP    V_PING_DROP(1U)
-
-#define S_PROTECT_MODE    21
-#define V_PROTECT_MODE(x) ((x) << S_PROTECT_MODE)
-#define F_PROTECT_MODE    V_PROTECT_MODE(1U)
-
-#define S_SYN_COOKIE_ALGORITHM    22
-#define V_SYN_COOKIE_ALGORITHM(x) ((x) << S_SYN_COOKIE_ALGORITHM)
-#define F_SYN_COOKIE_ALGORITHM    V_SYN_COOKIE_ALGORITHM(1U)
-
-#define S_ATTACK_FILTER    23
-#define V_ATTACK_FILTER(x) ((x) << S_ATTACK_FILTER)
-#define F_ATTACK_FILTER    V_ATTACK_FILTER(1U)
-
-#define S_INTERFACE_TYPE    24
-#define V_INTERFACE_TYPE(x) ((x) << S_INTERFACE_TYPE)
-#define F_INTERFACE_TYPE    V_INTERFACE_TYPE(1U)
-
-#define S_DISABLE_RX_FLOW_CONTROL    25
-#define V_DISABLE_RX_FLOW_CONTROL(x) ((x) << S_DISABLE_RX_FLOW_CONTROL)
-#define F_DISABLE_RX_FLOW_CONTROL    V_DISABLE_RX_FLOW_CONTROL(1U)
-
-#define S_SYN_COOKIE_PARAMETER    26
-#define M_SYN_COOKIE_PARAMETER    0x3f
-#define V_SYN_COOKIE_PARAMETER(x) ((x) << S_SYN_COOKIE_PARAMETER)
-#define G_SYN_COOKIE_PARAMETER(x) (((x) >> S_SYN_COOKIE_PARAMETER) & M_SYN_COOKIE_PARAMETER)
-
-#define A_TP_GLOBAL_RX_CREDITS 0x30c
-#define A_TP_CM_SIZE 0x310
-#define A_TP_CM_MM_BASE 0x314
-
-#define S_CM_MEMMGR_BASE    0
-#define M_CM_MEMMGR_BASE    0xfffffff
-#define V_CM_MEMMGR_BASE(x) ((x) << S_CM_MEMMGR_BASE)
-#define G_CM_MEMMGR_BASE(x) (((x) >> S_CM_MEMMGR_BASE) & M_CM_MEMMGR_BASE)
-
-#define A_TP_CM_TIMER_BASE 0x318
-
-#define S_CM_TIMER_BASE    0
-#define M_CM_TIMER_BASE    0xfffffff
-#define V_CM_TIMER_BASE(x) ((x) << S_CM_TIMER_BASE)
-#define G_CM_TIMER_BASE(x) (((x) >> S_CM_TIMER_BASE) & M_CM_TIMER_BASE)
-
-#define A_TP_PM_SIZE 0x31c
-#define A_TP_PM_TX_BASE 0x320
-#define A_TP_PM_DEFRAG_BASE 0x324
-#define A_TP_PM_RX_BASE 0x328
-#define A_TP_PM_RX_PG_SIZE 0x32c
-#define A_TP_PM_RX_MAX_PGS 0x330
-#define A_TP_PM_TX_PG_SIZE 0x334
-#define A_TP_PM_TX_MAX_PGS 0x338
-#define A_TP_TCP_OPTIONS 0x340
-
-#define S_TIMESTAMP    0
-#define M_TIMESTAMP    0x3
-#define V_TIMESTAMP(x) ((x) << S_TIMESTAMP)
-#define G_TIMESTAMP(x) (((x) >> S_TIMESTAMP) & M_TIMESTAMP)
-
-#define S_WINDOW_SCALE    2
-#define M_WINDOW_SCALE    0x3
-#define V_WINDOW_SCALE(x) ((x) << S_WINDOW_SCALE)
-#define G_WINDOW_SCALE(x) (((x) >> S_WINDOW_SCALE) & M_WINDOW_SCALE)
-
-#define S_SACK    4
-#define M_SACK    0x3
-#define V_SACK(x) ((x) << S_SACK)
-#define G_SACK(x) (((x) >> S_SACK) & M_SACK)
-
-#define S_ECN    6
-#define M_ECN    0x3
-#define V_ECN(x) ((x) << S_ECN)
-#define G_ECN(x) (((x) >> S_ECN) & M_ECN)
-
-#define S_SACK_ALGORITHM    8
-#define M_SACK_ALGORITHM    0x3
-#define V_SACK_ALGORITHM(x) ((x) << S_SACK_ALGORITHM)
-#define G_SACK_ALGORITHM(x) (((x) >> S_SACK_ALGORITHM) & M_SACK_ALGORITHM)
-
-#define S_MSS    10
-#define V_MSS(x) ((x) << S_MSS)
-#define F_MSS    V_MSS(1U)
-
-#define S_DEFAULT_PEER_MSS    16
-#define M_DEFAULT_PEER_MSS    0xffff
-#define V_DEFAULT_PEER_MSS(x) ((x) << S_DEFAULT_PEER_MSS)
-#define G_DEFAULT_PEER_MSS(x) (((x) >> S_DEFAULT_PEER_MSS) & M_DEFAULT_PEER_MSS)
-
-#define A_TP_DACK_CONFIG 0x344
-
-#define S_DACK_MODE    0
-#define V_DACK_MODE(x) ((x) << S_DACK_MODE)
-#define F_DACK_MODE    V_DACK_MODE(1U)
-
-#define S_DACK_AUTO_MGMT    1
-#define V_DACK_AUTO_MGMT(x) ((x) << S_DACK_AUTO_MGMT)
-#define F_DACK_AUTO_MGMT    V_DACK_AUTO_MGMT(1U)
-
-#define S_DACK_AUTO_CAREFUL    2
-#define V_DACK_AUTO_CAREFUL(x) ((x) << S_DACK_AUTO_CAREFUL)
-#define F_DACK_AUTO_CAREFUL    V_DACK_AUTO_CAREFUL(1U)
-
-#define S_DACK_MSS_SELECTOR    3
-#define M_DACK_MSS_SELECTOR    0x3
-#define V_DACK_MSS_SELECTOR(x) ((x) << S_DACK_MSS_SELECTOR)
-#define G_DACK_MSS_SELECTOR(x) (((x) >> S_DACK_MSS_SELECTOR) & M_DACK_MSS_SELECTOR)
-
-#define S_DACK_BYTE_THRESHOLD    5
-#define M_DACK_BYTE_THRESHOLD    0xfffff
-#define V_DACK_BYTE_THRESHOLD(x) ((x) << S_DACK_BYTE_THRESHOLD)
-#define G_DACK_BYTE_THRESHOLD(x) (((x) >> S_DACK_BYTE_THRESHOLD) & M_DACK_BYTE_THRESHOLD)
-
-#define A_TP_PC_CONFIG 0x348
-
-#define S_TP_ACCESS_LATENCY    0
-#define M_TP_ACCESS_LATENCY    0xf
-#define V_TP_ACCESS_LATENCY(x) ((x) << S_TP_ACCESS_LATENCY)
-#define G_TP_ACCESS_LATENCY(x) (((x) >> S_TP_ACCESS_LATENCY) & M_TP_ACCESS_LATENCY)
-
-#define S_HELD_FIN_DISABLE    4
-#define V_HELD_FIN_DISABLE(x) ((x) << S_HELD_FIN_DISABLE)
-#define F_HELD_FIN_DISABLE    V_HELD_FIN_DISABLE(1U)
-
-#define S_DDP_FC_ENABLE    5
-#define V_DDP_FC_ENABLE(x) ((x) << S_DDP_FC_ENABLE)
-#define F_DDP_FC_ENABLE    V_DDP_FC_ENABLE(1U)
-
-#define S_RDMA_ERR_ENABLE    6
-#define V_RDMA_ERR_ENABLE(x) ((x) << S_RDMA_ERR_ENABLE)
-#define F_RDMA_ERR_ENABLE    V_RDMA_ERR_ENABLE(1U)
-
-#define S_FAST_PDU_DELIVERY    7
-#define V_FAST_PDU_DELIVERY(x) ((x) << S_FAST_PDU_DELIVERY)
-#define F_FAST_PDU_DELIVERY    V_FAST_PDU_DELIVERY(1U)
-
-#define S_CLEAR_FIN    8
-#define V_CLEAR_FIN(x) ((x) << S_CLEAR_FIN)
-#define F_CLEAR_FIN    V_CLEAR_FIN(1U)
-
-#define S_DIS_TX_FILL_WIN_PUSH    12
-#define V_DIS_TX_FILL_WIN_PUSH(x) ((x) << S_DIS_TX_FILL_WIN_PUSH)
-#define F_DIS_TX_FILL_WIN_PUSH    V_DIS_TX_FILL_WIN_PUSH(1U)
-
-#define S_TP_PC_REV    30
-#define M_TP_PC_REV    0x3
-#define V_TP_PC_REV(x) ((x) << S_TP_PC_REV)
-#define G_TP_PC_REV(x) (((x) >> S_TP_PC_REV) & M_TP_PC_REV)
-
-#define A_TP_BACKOFF0 0x350
-
-#define S_ELEMENT0    0
-#define M_ELEMENT0    0xff
-#define V_ELEMENT0(x) ((x) << S_ELEMENT0)
-#define G_ELEMENT0(x) (((x) >> S_ELEMENT0) & M_ELEMENT0)
-
-#define S_ELEMENT1    8
-#define M_ELEMENT1    0xff
-#define V_ELEMENT1(x) ((x) << S_ELEMENT1)
-#define G_ELEMENT1(x) (((x) >> S_ELEMENT1) & M_ELEMENT1)
-
-#define S_ELEMENT2    16
-#define M_ELEMENT2    0xff
-#define V_ELEMENT2(x) ((x) << S_ELEMENT2)
-#define G_ELEMENT2(x) (((x) >> S_ELEMENT2) & M_ELEMENT2)
-
-#define S_ELEMENT3    24
-#define M_ELEMENT3    0xff
-#define V_ELEMENT3(x) ((x) << S_ELEMENT3)
-#define G_ELEMENT3(x) (((x) >> S_ELEMENT3) & M_ELEMENT3)
-
-#define A_TP_BACKOFF1 0x354
-#define A_TP_BACKOFF2 0x358
-#define A_TP_BACKOFF3 0x35c
-#define A_TP_PARA_REG0 0x360
-
-#define S_VAR_MULT    0
-#define M_VAR_MULT    0xf
-#define V_VAR_MULT(x) ((x) << S_VAR_MULT)
-#define G_VAR_MULT(x) (((x) >> S_VAR_MULT) & M_VAR_MULT)
-
-#define S_VAR_GAIN    4
-#define M_VAR_GAIN    0xf
-#define V_VAR_GAIN(x) ((x) << S_VAR_GAIN)
-#define G_VAR_GAIN(x) (((x) >> S_VAR_GAIN) & M_VAR_GAIN)
-
-#define S_SRTT_GAIN    8
-#define M_SRTT_GAIN    0xf
-#define V_SRTT_GAIN(x) ((x) << S_SRTT_GAIN)
-#define G_SRTT_GAIN(x) (((x) >> S_SRTT_GAIN) & M_SRTT_GAIN)
-
-#define S_RTTVAR_INIT    12
-#define M_RTTVAR_INIT    0xf
-#define V_RTTVAR_INIT(x) ((x) << S_RTTVAR_INIT)
-#define G_RTTVAR_INIT(x) (((x) >> S_RTTVAR_INIT) & M_RTTVAR_INIT)
-
-#define S_DUP_THRESH    20
-#define M_DUP_THRESH    0xf
-#define V_DUP_THRESH(x) ((x) << S_DUP_THRESH)
-#define G_DUP_THRESH(x) (((x) >> S_DUP_THRESH) & M_DUP_THRESH)
-
-#define S_INIT_CONG_WIN    24
-#define M_INIT_CONG_WIN    0x7
-#define V_INIT_CONG_WIN(x) ((x) << S_INIT_CONG_WIN)
-#define G_INIT_CONG_WIN(x) (((x) >> S_INIT_CONG_WIN) & M_INIT_CONG_WIN)
-
-#define A_TP_PARA_REG1 0x364
-
-#define S_INITIAL_SLOW_START_THRESHOLD    0
-#define M_INITIAL_SLOW_START_THRESHOLD    0xffff
-#define V_INITIAL_SLOW_START_THRESHOLD(x) ((x) << S_INITIAL_SLOW_START_THRESHOLD)
-#define G_INITIAL_SLOW_START_THRESHOLD(x) (((x) >> S_INITIAL_SLOW_START_THRESHOLD) & M_INITIAL_SLOW_START_THRESHOLD)
-
-#define S_RECEIVE_BUFFER_SIZE    16
-#define M_RECEIVE_BUFFER_SIZE    0xffff
-#define V_RECEIVE_BUFFER_SIZE(x) ((x) << S_RECEIVE_BUFFER_SIZE)
-#define G_RECEIVE_BUFFER_SIZE(x) (((x) >> S_RECEIVE_BUFFER_SIZE) & M_RECEIVE_BUFFER_SIZE)
-
-#define A_TP_PARA_REG2 0x368
-
-#define S_RX_COALESCE_SIZE    0
-#define M_RX_COALESCE_SIZE    0xffff
-#define V_RX_COALESCE_SIZE(x) ((x) << S_RX_COALESCE_SIZE)
-#define G_RX_COALESCE_SIZE(x) (((x) >> S_RX_COALESCE_SIZE) & M_RX_COALESCE_SIZE)
-
-#define S_MAX_RX_SIZE    16
-#define M_MAX_RX_SIZE    0xffff
-#define V_MAX_RX_SIZE(x) ((x) << S_MAX_RX_SIZE)
-#define G_MAX_RX_SIZE(x) (((x) >> S_MAX_RX_SIZE) & M_MAX_RX_SIZE)
-
-#define A_TP_PARA_REG3 0x36c
-
-#define S_RX_COALESCING_PSH_DELIVER    0
-#define V_RX_COALESCING_PSH_DELIVER(x) ((x) << S_RX_COALESCING_PSH_DELIVER)
-#define F_RX_COALESCING_PSH_DELIVER    V_RX_COALESCING_PSH_DELIVER(1U)
-
-#define S_RX_COALESCING_ENABLE    1
-#define V_RX_COALESCING_ENABLE(x) ((x) << S_RX_COALESCING_ENABLE)
-#define F_RX_COALESCING_ENABLE    V_RX_COALESCING_ENABLE(1U)
-
-#define S_TAHOE_ENABLE    2
-#define V_TAHOE_ENABLE(x) ((x) << S_TAHOE_ENABLE)
-#define F_TAHOE_ENABLE    V_TAHOE_ENABLE(1U)
-
-#define S_MAX_REORDER_FRAGMENTS    12
-#define M_MAX_REORDER_FRAGMENTS    0x7
-#define V_MAX_REORDER_FRAGMENTS(x) ((x) << S_MAX_REORDER_FRAGMENTS)
-#define G_MAX_REORDER_FRAGMENTS(x) (((x) >> S_MAX_REORDER_FRAGMENTS) & M_MAX_REORDER_FRAGMENTS)
-
-#define A_TP_TIMER_RESOLUTION 0x390
-
-#define S_DELAYED_ACK_TIMER_RESOLUTION    0
-#define M_DELAYED_ACK_TIMER_RESOLUTION    0x3f
-#define V_DELAYED_ACK_TIMER_RESOLUTION(x) ((x) << S_DELAYED_ACK_TIMER_RESOLUTION)
-#define G_DELAYED_ACK_TIMER_RESOLUTION(x) (((x) >> S_DELAYED_ACK_TIMER_RESOLUTION) & M_DELAYED_ACK_TIMER_RESOLUTION)
-
-#define S_GENERIC_TIMER_RESOLUTION    16
-#define M_GENERIC_TIMER_RESOLUTION    0x3f
-#define V_GENERIC_TIMER_RESOLUTION(x) ((x) << S_GENERIC_TIMER_RESOLUTION)
-#define G_GENERIC_TIMER_RESOLUTION(x) (((x) >> S_GENERIC_TIMER_RESOLUTION) & M_GENERIC_TIMER_RESOLUTION)
-
-#define A_TP_2MSL 0x394
-
-#define S_2MSL    0
-#define M_2MSL    0x3fffffff
-#define V_2MSL(x) ((x) << S_2MSL)
-#define G_2MSL(x) (((x) >> S_2MSL) & M_2MSL)
-
-#define A_TP_RXT_MIN 0x398
-
-#define S_RETRANSMIT_TIMER_MIN    0
-#define M_RETRANSMIT_TIMER_MIN    0xffff
-#define V_RETRANSMIT_TIMER_MIN(x) ((x) << S_RETRANSMIT_TIMER_MIN)
-#define G_RETRANSMIT_TIMER_MIN(x) (((x) >> S_RETRANSMIT_TIMER_MIN) & M_RETRANSMIT_TIMER_MIN)
-
-#define A_TP_RXT_MAX 0x39c
-
-#define S_RETRANSMIT_TIMER_MAX    0
-#define M_RETRANSMIT_TIMER_MAX    0x3fffffff
-#define V_RETRANSMIT_TIMER_MAX(x) ((x) << S_RETRANSMIT_TIMER_MAX)
-#define G_RETRANSMIT_TIMER_MAX(x) (((x) >> S_RETRANSMIT_TIMER_MAX) & M_RETRANSMIT_TIMER_MAX)
-
-#define A_TP_PERS_MIN 0x3a0
-
-#define S_PERSIST_TIMER_MIN    0
-#define M_PERSIST_TIMER_MIN    0xffff
-#define V_PERSIST_TIMER_MIN(x) ((x) << S_PERSIST_TIMER_MIN)
-#define G_PERSIST_TIMER_MIN(x) (((x) >> S_PERSIST_TIMER_MIN) & M_PERSIST_TIMER_MIN)
-
-#define A_TP_PERS_MAX 0x3a4
-
-#define S_PERSIST_TIMER_MAX    0
-#define M_PERSIST_TIMER_MAX    0x3fffffff
-#define V_PERSIST_TIMER_MAX(x) ((x) << S_PERSIST_TIMER_MAX)
-#define G_PERSIST_TIMER_MAX(x) (((x) >> S_PERSIST_TIMER_MAX) & M_PERSIST_TIMER_MAX)
-
-#define A_TP_KEEP_IDLE 0x3ac
-
-#define S_KEEP_ALIVE_IDLE_TIME    0
-#define M_KEEP_ALIVE_IDLE_TIME    0x3fffffff
-#define V_KEEP_ALIVE_IDLE_TIME(x) ((x) << S_KEEP_ALIVE_IDLE_TIME)
-#define G_KEEP_ALIVE_IDLE_TIME(x) (((x) >> S_KEEP_ALIVE_IDLE_TIME) & M_KEEP_ALIVE_IDLE_TIME)
-
-#define A_TP_KEEP_INTVL 0x3b0
-
-#define S_KEEP_ALIVE_INTERVAL_TIME    0
-#define M_KEEP_ALIVE_INTERVAL_TIME    0x3fffffff
-#define V_KEEP_ALIVE_INTERVAL_TIME(x) ((x) << S_KEEP_ALIVE_INTERVAL_TIME)
-#define G_KEEP_ALIVE_INTERVAL_TIME(x) (((x) >> S_KEEP_ALIVE_INTERVAL_TIME) & M_KEEP_ALIVE_INTERVAL_TIME)
-
-#define A_TP_INIT_SRTT 0x3b4
-
-#define S_INITIAL_SRTT    0
-#define M_INITIAL_SRTT    0xffff
-#define V_INITIAL_SRTT(x) ((x) << S_INITIAL_SRTT)
-#define G_INITIAL_SRTT(x) (((x) >> S_INITIAL_SRTT) & M_INITIAL_SRTT)
-
-#define A_TP_DACK_TIME 0x3b8
-
-#define S_DELAYED_ACK_TIME    0
-#define M_DELAYED_ACK_TIME    0x7ff
-#define V_DELAYED_ACK_TIME(x) ((x) << S_DELAYED_ACK_TIME)
-#define G_DELAYED_ACK_TIME(x) (((x) >> S_DELAYED_ACK_TIME) & M_DELAYED_ACK_TIME)
-
-#define A_TP_FINWAIT2_TIME 0x3bc
-
-#define S_FINWAIT2_TIME    0
-#define M_FINWAIT2_TIME    0x3fffffff
-#define V_FINWAIT2_TIME(x) ((x) << S_FINWAIT2_TIME)
-#define G_FINWAIT2_TIME(x) (((x) >> S_FINWAIT2_TIME) & M_FINWAIT2_TIME)
-
-#define A_TP_FAST_FINWAIT2_TIME 0x3c0
-
-#define S_FAST_FINWAIT2_TIME    0
-#define M_FAST_FINWAIT2_TIME    0x3fffffff
-#define V_FAST_FINWAIT2_TIME(x) ((x) << S_FAST_FINWAIT2_TIME)
-#define G_FAST_FINWAIT2_TIME(x) (((x) >> S_FAST_FINWAIT2_TIME) & M_FAST_FINWAIT2_TIME)
-
-#define A_TP_SHIFT_CNT 0x3c4
-
-#define S_KEEPALIVE_MAX    0
-#define M_KEEPALIVE_MAX    0xff
-#define V_KEEPALIVE_MAX(x) ((x) << S_KEEPALIVE_MAX)
-#define G_KEEPALIVE_MAX(x) (((x) >> S_KEEPALIVE_MAX) & M_KEEPALIVE_MAX)
-
-#define S_WINDOWPROBE_MAX    8
-#define M_WINDOWPROBE_MAX    0xff
-#define V_WINDOWPROBE_MAX(x) ((x) << S_WINDOWPROBE_MAX)
-#define G_WINDOWPROBE_MAX(x) (((x) >> S_WINDOWPROBE_MAX) & M_WINDOWPROBE_MAX)
-
-#define S_RETRANSMISSION_MAX    16
-#define M_RETRANSMISSION_MAX    0xff
-#define V_RETRANSMISSION_MAX(x) ((x) << S_RETRANSMISSION_MAX)
-#define G_RETRANSMISSION_MAX(x) (((x) >> S_RETRANSMISSION_MAX) & M_RETRANSMISSION_MAX)
-
-#define S_SYN_MAX    24
-#define M_SYN_MAX    0xff
-#define V_SYN_MAX(x) ((x) << S_SYN_MAX)
-#define G_SYN_MAX(x) (((x) >> S_SYN_MAX) & M_SYN_MAX)
-
-#define A_TP_QOS_REG0 0x3e0
-
-#define S_L3_VALUE    0
-#define M_L3_VALUE    0x3f
-#define V_L3_VALUE(x) ((x) << S_L3_VALUE)
-#define G_L3_VALUE(x) (((x) >> S_L3_VALUE) & M_L3_VALUE)
-
-#define A_TP_QOS_REG1 0x3e4
-#define A_TP_QOS_REG2 0x3e8
-#define A_TP_QOS_REG3 0x3ec
-#define A_TP_QOS_REG4 0x3f0
-#define A_TP_QOS_REG5 0x3f4
-#define A_TP_QOS_REG6 0x3f8
-#define A_TP_QOS_REG7 0x3fc
-#define A_TP_MTU_REG0 0x404
-#define A_TP_MTU_REG1 0x408
-#define A_TP_MTU_REG2 0x40c
-#define A_TP_MTU_REG3 0x410
-#define A_TP_MTU_REG4 0x414
-#define A_TP_MTU_REG5 0x418
-#define A_TP_MTU_REG6 0x41c
-#define A_TP_MTU_REG7 0x420
-#define A_TP_RESET 0x44c
-
-#define S_TP_RESET    0
-#define V_TP_RESET(x) ((x) << S_TP_RESET)
-#define F_TP_RESET    V_TP_RESET(1U)
-
-#define S_CM_MEMMGR_INIT    1
-#define V_CM_MEMMGR_INIT(x) ((x) << S_CM_MEMMGR_INIT)
-#define F_CM_MEMMGR_INIT    V_CM_MEMMGR_INIT(1U)
-
-#define A_TP_MIB_INDEX 0x450
-#define A_TP_MIB_DATA 0x454
-#define A_TP_SYNC_TIME_HI 0x458
-#define A_TP_SYNC_TIME_LO 0x45c
-#define A_TP_CM_MM_RX_FLST_BASE 0x460
-
-#define S_CM_MEMMGR_RX_FREE_LIST_BASE    0
-#define M_CM_MEMMGR_RX_FREE_LIST_BASE    0xfffffff
-#define V_CM_MEMMGR_RX_FREE_LIST_BASE(x) ((x) << S_CM_MEMMGR_RX_FREE_LIST_BASE)
-#define G_CM_MEMMGR_RX_FREE_LIST_BASE(x) (((x) >> S_CM_MEMMGR_RX_FREE_LIST_BASE) & M_CM_MEMMGR_RX_FREE_LIST_BASE)
-
-#define A_TP_CM_MM_TX_FLST_BASE 0x464
-
-#define S_CM_MEMMGR_TX_FREE_LIST_BASE    0
-#define M_CM_MEMMGR_TX_FREE_LIST_BASE    0xfffffff
-#define V_CM_MEMMGR_TX_FREE_LIST_BASE(x) ((x) << S_CM_MEMMGR_TX_FREE_LIST_BASE)
-#define G_CM_MEMMGR_TX_FREE_LIST_BASE(x) (((x) >> S_CM_MEMMGR_TX_FREE_LIST_BASE) & M_CM_MEMMGR_TX_FREE_LIST_BASE)
-
-#define A_TP_CM_MM_P_FLST_BASE 0x468
-
-#define S_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE    0
-#define M_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE    0xfffffff
-#define V_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE(x) ((x) << S_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE)
-#define G_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE(x) (((x) >> S_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE) & M_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE)
-
-#define A_TP_CM_MM_MAX_P 0x46c
-
-#define S_CM_MEMMGR_MAX_PSTRUCT    0
-#define M_CM_MEMMGR_MAX_PSTRUCT    0xfffffff
-#define V_CM_MEMMGR_MAX_PSTRUCT(x) ((x) << S_CM_MEMMGR_MAX_PSTRUCT)
-#define G_CM_MEMMGR_MAX_PSTRUCT(x) (((x) >> S_CM_MEMMGR_MAX_PSTRUCT) & M_CM_MEMMGR_MAX_PSTRUCT)
-
-#define A_TP_INT_ENABLE 0x470
-
-#define S_TX_FREE_LIST_EMPTY    0
-#define V_TX_FREE_LIST_EMPTY(x) ((x) << S_TX_FREE_LIST_EMPTY)
-#define F_TX_FREE_LIST_EMPTY    V_TX_FREE_LIST_EMPTY(1U)
-
-#define S_RX_FREE_LIST_EMPTY    1
-#define V_RX_FREE_LIST_EMPTY(x) ((x) << S_RX_FREE_LIST_EMPTY)
-#define F_RX_FREE_LIST_EMPTY    V_RX_FREE_LIST_EMPTY(1U)
-
-#define A_TP_INT_CAUSE 0x474
-#define A_TP_TIMER_SEPARATOR 0x4a4
-
-#define S_DISABLE_PAST_TIMER_INSERTION    0
-#define V_DISABLE_PAST_TIMER_INSERTION(x) ((x) << S_DISABLE_PAST_TIMER_INSERTION)
-#define F_DISABLE_PAST_TIMER_INSERTION    V_DISABLE_PAST_TIMER_INSERTION(1U)
-
-#define S_MODULATION_TIMER_SEPARATOR    1
-#define M_MODULATION_TIMER_SEPARATOR    0x7fff
-#define V_MODULATION_TIMER_SEPARATOR(x) ((x) << S_MODULATION_TIMER_SEPARATOR)
-#define G_MODULATION_TIMER_SEPARATOR(x) (((x) >> S_MODULATION_TIMER_SEPARATOR) & M_MODULATION_TIMER_SEPARATOR)
-
-#define S_GLOBAL_TIMER_SEPARATOR    16
-#define M_GLOBAL_TIMER_SEPARATOR    0xffff
-#define V_GLOBAL_TIMER_SEPARATOR(x) ((x) << S_GLOBAL_TIMER_SEPARATOR)
-#define G_GLOBAL_TIMER_SEPARATOR(x) (((x) >> S_GLOBAL_TIMER_SEPARATOR) & M_GLOBAL_TIMER_SEPARATOR)
-
-#define A_TP_CM_FC_MODE 0x4b0
-#define A_TP_PC_CONGESTION_CNTL 0x4b4
-#define A_TP_TX_DROP_CONFIG 0x4b8
-
-#define S_ENABLE_TX_DROP    31
-#define V_ENABLE_TX_DROP(x) ((x) << S_ENABLE_TX_DROP)
-#define F_ENABLE_TX_DROP    V_ENABLE_TX_DROP(1U)
-
-#define S_ENABLE_TX_ERROR    30
-#define V_ENABLE_TX_ERROR(x) ((x) << S_ENABLE_TX_ERROR)
-#define F_ENABLE_TX_ERROR    V_ENABLE_TX_ERROR(1U)
-
-#define S_DROP_TICKS_CNT    4
-#define M_DROP_TICKS_CNT    0x3ffffff
-#define V_DROP_TICKS_CNT(x) ((x) << S_DROP_TICKS_CNT)
-#define G_DROP_TICKS_CNT(x) (((x) >> S_DROP_TICKS_CNT) & M_DROP_TICKS_CNT)
-
-#define S_NUM_PKTS_DROPPED    0
-#define M_NUM_PKTS_DROPPED    0xf
-#define V_NUM_PKTS_DROPPED(x) ((x) << S_NUM_PKTS_DROPPED)
-#define G_NUM_PKTS_DROPPED(x) (((x) >> S_NUM_PKTS_DROPPED) & M_NUM_PKTS_DROPPED)
-
-#define A_TP_TX_DROP_COUNT 0x4bc
-
-/* RAT registers */
-#define A_RAT_ROUTE_CONTROL 0x580
-
-#define S_USE_ROUTE_TABLE    0
-#define V_USE_ROUTE_TABLE(x) ((x) << S_USE_ROUTE_TABLE)
-#define F_USE_ROUTE_TABLE    V_USE_ROUTE_TABLE(1U)
-
-#define S_ENABLE_CSPI    1
-#define V_ENABLE_CSPI(x) ((x) << S_ENABLE_CSPI)
-#define F_ENABLE_CSPI    V_ENABLE_CSPI(1U)
-
-#define S_ENABLE_PCIX    2
-#define V_ENABLE_PCIX(x) ((x) << S_ENABLE_PCIX)
-#define F_ENABLE_PCIX    V_ENABLE_PCIX(1U)
-
-#define A_RAT_ROUTE_TABLE_INDEX 0x584
-
-#define S_ROUTE_TABLE_INDEX    0
-#define M_ROUTE_TABLE_INDEX    0xf
-#define V_ROUTE_TABLE_INDEX(x) ((x) << S_ROUTE_TABLE_INDEX)
-#define G_ROUTE_TABLE_INDEX(x) (((x) >> S_ROUTE_TABLE_INDEX) & M_ROUTE_TABLE_INDEX)
-
-#define A_RAT_ROUTE_TABLE_DATA 0x588
-#define A_RAT_NO_ROUTE 0x58c
-
-#define S_CPL_OPCODE    0
-#define M_CPL_OPCODE    0xff
-#define V_CPL_OPCODE(x) ((x) << S_CPL_OPCODE)
-#define G_CPL_OPCODE(x) (((x) >> S_CPL_OPCODE) & M_CPL_OPCODE)
-
-#define A_RAT_INTR_ENABLE 0x590
-
-#define S_ZEROROUTEERROR    0
-#define V_ZEROROUTEERROR(x) ((x) << S_ZEROROUTEERROR)
-#define F_ZEROROUTEERROR    V_ZEROROUTEERROR(1U)
-
-#define S_CSPIFRAMINGERROR    1
-#define V_CSPIFRAMINGERROR(x) ((x) << S_CSPIFRAMINGERROR)
-#define F_CSPIFRAMINGERROR    V_CSPIFRAMINGERROR(1U)
-
-#define S_SGEFRAMINGERROR    2
-#define V_SGEFRAMINGERROR(x) ((x) << S_SGEFRAMINGERROR)
-#define F_SGEFRAMINGERROR    V_SGEFRAMINGERROR(1U)
-
-#define S_TPFRAMINGERROR    3
-#define V_TPFRAMINGERROR(x) ((x) << S_TPFRAMINGERROR)
-#define F_TPFRAMINGERROR    V_TPFRAMINGERROR(1U)
-
-#define A_RAT_INTR_CAUSE 0x594
-
-/* CSPI registers */
-#define A_CSPI_RX_AE_WM 0x810
-#define A_CSPI_RX_AF_WM 0x814
-#define A_CSPI_CALENDAR_LEN 0x818
-
-#define S_CALENDARLENGTH    0
-#define M_CALENDARLENGTH    0xffff
-#define V_CALENDARLENGTH(x) ((x) << S_CALENDARLENGTH)
-#define G_CALENDARLENGTH(x) (((x) >> S_CALENDARLENGTH) & M_CALENDARLENGTH)
-
-#define A_CSPI_FIFO_STATUS_ENABLE 0x820
-
-#define S_FIFOSTATUSENABLE    0
-#define V_FIFOSTATUSENABLE(x) ((x) << S_FIFOSTATUSENABLE)
-#define F_FIFOSTATUSENABLE    V_FIFOSTATUSENABLE(1U)
-
-#define A_CSPI_MAXBURST1_MAXBURST2 0x828
-
-#define S_MAXBURST1    0
-#define M_MAXBURST1    0xffff
-#define V_MAXBURST1(x) ((x) << S_MAXBURST1)
-#define G_MAXBURST1(x) (((x) >> S_MAXBURST1) & M_MAXBURST1)
-
-#define S_MAXBURST2    16
-#define M_MAXBURST2    0xffff
-#define V_MAXBURST2(x) ((x) << S_MAXBURST2)
-#define G_MAXBURST2(x) (((x) >> S_MAXBURST2) & M_MAXBURST2)
-
-#define A_CSPI_TRAIN 0x82c
-
-#define S_CSPI_TRAIN_ALPHA    0
-#define M_CSPI_TRAIN_ALPHA    0xffff
-#define V_CSPI_TRAIN_ALPHA(x) ((x) << S_CSPI_TRAIN_ALPHA)
-#define G_CSPI_TRAIN_ALPHA(x) (((x) >> S_CSPI_TRAIN_ALPHA) & M_CSPI_TRAIN_ALPHA)
-
-#define S_CSPI_TRAIN_DATA_MAXT    16
-#define M_CSPI_TRAIN_DATA_MAXT    0xffff
-#define V_CSPI_TRAIN_DATA_MAXT(x) ((x) << S_CSPI_TRAIN_DATA_MAXT)
-#define G_CSPI_TRAIN_DATA_MAXT(x) (((x) >> S_CSPI_TRAIN_DATA_MAXT) & M_CSPI_TRAIN_DATA_MAXT)
-
-#define A_CSPI_INTR_STATUS 0x848
-
-#define S_DIP4ERR    0
-#define V_DIP4ERR(x) ((x) << S_DIP4ERR)
-#define F_DIP4ERR    V_DIP4ERR(1U)
-
-#define S_RXDROP    1
-#define V_RXDROP(x) ((x) << S_RXDROP)
-#define F_RXDROP    V_RXDROP(1U)
-
-#define S_TXDROP    2
-#define V_TXDROP(x) ((x) << S_TXDROP)
-#define F_TXDROP    V_TXDROP(1U)
-
-#define S_RXOVERFLOW    3
-#define V_RXOVERFLOW(x) ((x) << S_RXOVERFLOW)
-#define F_RXOVERFLOW    V_RXOVERFLOW(1U)
-
-#define S_RAMPARITYERR    4
-#define V_RAMPARITYERR(x) ((x) << S_RAMPARITYERR)
-#define F_RAMPARITYERR    V_RAMPARITYERR(1U)
-
-#define A_CSPI_INTR_ENABLE 0x84c
-
-/* ESPI registers */
-#define A_ESPI_SCH_TOKEN0 0x880
-
-#define S_SCHTOKEN0    0
-#define M_SCHTOKEN0    0xffff
-#define V_SCHTOKEN0(x) ((x) << S_SCHTOKEN0)
-#define G_SCHTOKEN0(x) (((x) >> S_SCHTOKEN0) & M_SCHTOKEN0)
-
-#define A_ESPI_SCH_TOKEN1 0x884
-
-#define S_SCHTOKEN1    0
-#define M_SCHTOKEN1    0xffff
-#define V_SCHTOKEN1(x) ((x) << S_SCHTOKEN1)
-#define G_SCHTOKEN1(x) (((x) >> S_SCHTOKEN1) & M_SCHTOKEN1)
-
-#define A_ESPI_SCH_TOKEN2 0x888
-
-#define S_SCHTOKEN2    0
-#define M_SCHTOKEN2    0xffff
-#define V_SCHTOKEN2(x) ((x) << S_SCHTOKEN2)
-#define G_SCHTOKEN2(x) (((x) >> S_SCHTOKEN2) & M_SCHTOKEN2)
-
-#define A_ESPI_SCH_TOKEN3 0x88c
-
-#define S_SCHTOKEN3    0
-#define M_SCHTOKEN3    0xffff
-#define V_SCHTOKEN3(x) ((x) << S_SCHTOKEN3)
-#define G_SCHTOKEN3(x) (((x) >> S_SCHTOKEN3) & M_SCHTOKEN3)
-
-#define A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK 0x890
-
-#define S_ALMOSTEMPTY    0
-#define M_ALMOSTEMPTY    0xffff
-#define V_ALMOSTEMPTY(x) ((x) << S_ALMOSTEMPTY)
-#define G_ALMOSTEMPTY(x) (((x) >> S_ALMOSTEMPTY) & M_ALMOSTEMPTY)
-
-#define A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK 0x894
-
-#define S_ALMOSTFULL    0
-#define M_ALMOSTFULL    0xffff
-#define V_ALMOSTFULL(x) ((x) << S_ALMOSTFULL)
-#define G_ALMOSTFULL(x) (((x) >> S_ALMOSTFULL) & M_ALMOSTFULL)
-
-#define A_ESPI_CALENDAR_LENGTH 0x898
-#define A_PORT_CONFIG 0x89c
-
-#define S_RX_NPORTS    0
-#define M_RX_NPORTS    0xff
-#define V_RX_NPORTS(x) ((x) << S_RX_NPORTS)
-#define G_RX_NPORTS(x) (((x) >> S_RX_NPORTS) & M_RX_NPORTS)
-
-#define S_TX_NPORTS    8
-#define M_TX_NPORTS    0xff
-#define V_TX_NPORTS(x) ((x) << S_TX_NPORTS)
-#define G_TX_NPORTS(x) (((x) >> S_TX_NPORTS) & M_TX_NPORTS)
-
-#define A_ESPI_FIFO_STATUS_ENABLE 0x8a0
-
-#define S_RXSTATUSENABLE    0
-#define V_RXSTATUSENABLE(x) ((x) << S_RXSTATUSENABLE)
-#define F_RXSTATUSENABLE    V_RXSTATUSENABLE(1U)
-
-#define S_TXDROPENABLE    1
-#define V_TXDROPENABLE(x) ((x) << S_TXDROPENABLE)
-#define F_TXDROPENABLE    V_TXDROPENABLE(1U)
-
-#define S_RXENDIANMODE    2
-#define V_RXENDIANMODE(x) ((x) << S_RXENDIANMODE)
-#define F_RXENDIANMODE    V_RXENDIANMODE(1U)
-
-#define S_TXENDIANMODE    3
-#define V_TXENDIANMODE(x) ((x) << S_TXENDIANMODE)
-#define F_TXENDIANMODE    V_TXENDIANMODE(1U)
-
-#define S_INTEL1010MODE    4
-#define V_INTEL1010MODE(x) ((x) << S_INTEL1010MODE)
-#define F_INTEL1010MODE    V_INTEL1010MODE(1U)
-
-#define A_ESPI_MAXBURST1_MAXBURST2 0x8a8
-#define A_ESPI_TRAIN 0x8ac
-
-#define S_MAXTRAINALPHA    0
-#define M_MAXTRAINALPHA    0xffff
-#define V_MAXTRAINALPHA(x) ((x) << S_MAXTRAINALPHA)
-#define G_MAXTRAINALPHA(x) (((x) >> S_MAXTRAINALPHA) & M_MAXTRAINALPHA)
-
-#define S_MAXTRAINDATA    16
-#define M_MAXTRAINDATA    0xffff
-#define V_MAXTRAINDATA(x) ((x) << S_MAXTRAINDATA)
-#define G_MAXTRAINDATA(x) (((x) >> S_MAXTRAINDATA) & M_MAXTRAINDATA)
-
-#define A_RAM_STATUS 0x8b0
-
-#define S_RXFIFOPARITYERROR    0
-#define M_RXFIFOPARITYERROR    0x3ff
-#define V_RXFIFOPARITYERROR(x) ((x) << S_RXFIFOPARITYERROR)
-#define G_RXFIFOPARITYERROR(x) (((x) >> S_RXFIFOPARITYERROR) & M_RXFIFOPARITYERROR)
-
-#define S_TXFIFOPARITYERROR    10
-#define M_TXFIFOPARITYERROR    0x3ff
-#define V_TXFIFOPARITYERROR(x) ((x) << S_TXFIFOPARITYERROR)
-#define G_TXFIFOPARITYERROR(x) (((x) >> S_TXFIFOPARITYERROR) & M_TXFIFOPARITYERROR)
-
-#define S_RXFIFOOVERFLOW    20
-#define M_RXFIFOOVERFLOW    0x3ff
-#define V_RXFIFOOVERFLOW(x) ((x) << S_RXFIFOOVERFLOW)
-#define G_RXFIFOOVERFLOW(x) (((x) >> S_RXFIFOOVERFLOW) & M_RXFIFOOVERFLOW)
-
-#define A_TX_DROP_COUNT0 0x8b4
-
-#define S_TXPORT0DROPCNT    0
-#define M_TXPORT0DROPCNT    0xffff
-#define V_TXPORT0DROPCNT(x) ((x) << S_TXPORT0DROPCNT)
-#define G_TXPORT0DROPCNT(x) (((x) >> S_TXPORT0DROPCNT) & M_TXPORT0DROPCNT)
-
-#define S_TXPORT1DROPCNT    16
-#define M_TXPORT1DROPCNT    0xffff
-#define V_TXPORT1DROPCNT(x) ((x) << S_TXPORT1DROPCNT)
-#define G_TXPORT1DROPCNT(x) (((x) >> S_TXPORT1DROPCNT) & M_TXPORT1DROPCNT)
-
-#define A_TX_DROP_COUNT1 0x8b8
-
-#define S_TXPORT2DROPCNT    0
-#define M_TXPORT2DROPCNT    0xffff
-#define V_TXPORT2DROPCNT(x) ((x) << S_TXPORT2DROPCNT)
-#define G_TXPORT2DROPCNT(x) (((x) >> S_TXPORT2DROPCNT) & M_TXPORT2DROPCNT)
-
-#define S_TXPORT3DROPCNT    16
-#define M_TXPORT3DROPCNT    0xffff
-#define V_TXPORT3DROPCNT(x) ((x) << S_TXPORT3DROPCNT)
-#define G_TXPORT3DROPCNT(x) (((x) >> S_TXPORT3DROPCNT) & M_TXPORT3DROPCNT)
-
-#define A_RX_DROP_COUNT0 0x8bc
-
-#define S_RXPORT0DROPCNT    0
-#define M_RXPORT0DROPCNT    0xffff
-#define V_RXPORT0DROPCNT(x) ((x) << S_RXPORT0DROPCNT)
-#define G_RXPORT0DROPCNT(x) (((x) >> S_RXPORT0DROPCNT) & M_RXPORT0DROPCNT)
-
-#define S_RXPORT1DROPCNT    16
-#define M_RXPORT1DROPCNT    0xffff
-#define V_RXPORT1DROPCNT(x) ((x) << S_RXPORT1DROPCNT)
-#define G_RXPORT1DROPCNT(x) (((x) >> S_RXPORT1DROPCNT) & M_RXPORT1DROPCNT)
-
-#define A_RX_DROP_COUNT1 0x8c0
-
-#define S_RXPORT2DROPCNT    0
-#define M_RXPORT2DROPCNT    0xffff
-#define V_RXPORT2DROPCNT(x) ((x) << S_RXPORT2DROPCNT)
-#define G_RXPORT2DROPCNT(x) (((x) >> S_RXPORT2DROPCNT) & M_RXPORT2DROPCNT)
-
-#define S_RXPORT3DROPCNT    16
-#define M_RXPORT3DROPCNT    0xffff
-#define V_RXPORT3DROPCNT(x) ((x) << S_RXPORT3DROPCNT)
-#define G_RXPORT3DROPCNT(x) (((x) >> S_RXPORT3DROPCNT) & M_RXPORT3DROPCNT)
-
-#define A_DIP4_ERROR_COUNT 0x8c4
-
-#define S_DIP4ERRORCNT    0
-#define M_DIP4ERRORCNT    0xfff
-#define V_DIP4ERRORCNT(x) ((x) << S_DIP4ERRORCNT)
-#define G_DIP4ERRORCNT(x) (((x) >> S_DIP4ERRORCNT) & M_DIP4ERRORCNT)
-
-#define S_DIP4ERRORCNTSHADOW    12
-#define M_DIP4ERRORCNTSHADOW    0xfff
-#define V_DIP4ERRORCNTSHADOW(x) ((x) << S_DIP4ERRORCNTSHADOW)
-#define G_DIP4ERRORCNTSHADOW(x) (((x) >> S_DIP4ERRORCNTSHADOW) & M_DIP4ERRORCNTSHADOW)
-
-#define S_TRICN_RX_TRAIN_ERR    24
-#define V_TRICN_RX_TRAIN_ERR(x) ((x) << S_TRICN_RX_TRAIN_ERR)
-#define F_TRICN_RX_TRAIN_ERR    V_TRICN_RX_TRAIN_ERR(1U)
-
-#define S_TRICN_RX_TRAINING    25
-#define V_TRICN_RX_TRAINING(x) ((x) << S_TRICN_RX_TRAINING)
-#define F_TRICN_RX_TRAINING    V_TRICN_RX_TRAINING(1U)
-
-#define S_TRICN_RX_TRAIN_OK    26
-#define V_TRICN_RX_TRAIN_OK(x) ((x) << S_TRICN_RX_TRAIN_OK)
-#define F_TRICN_RX_TRAIN_OK    V_TRICN_RX_TRAIN_OK(1U)
-
-#define A_ESPI_INTR_STATUS 0x8c8
-
-#define S_DIP2PARITYERR    5
-#define V_DIP2PARITYERR(x) ((x) << S_DIP2PARITYERR)
-#define F_DIP2PARITYERR    V_DIP2PARITYERR(1U)
-
-#define A_ESPI_INTR_ENABLE 0x8cc
-#define A_RX_DROP_THRESHOLD 0x8d0
-#define A_ESPI_RX_RESET 0x8ec
-
-#define S_ESPI_RX_LNK_RST    0
-#define V_ESPI_RX_LNK_RST(x) ((x) << S_ESPI_RX_LNK_RST)
-#define F_ESPI_RX_LNK_RST    V_ESPI_RX_LNK_RST(1U)
-
-#define S_ESPI_RX_CORE_RST    1
-#define V_ESPI_RX_CORE_RST(x) ((x) << S_ESPI_RX_CORE_RST)
-#define F_ESPI_RX_CORE_RST    V_ESPI_RX_CORE_RST(1U)
-
-#define S_RX_CLK_STATUS    2
-#define V_RX_CLK_STATUS(x) ((x) << S_RX_CLK_STATUS)
-#define F_RX_CLK_STATUS    V_RX_CLK_STATUS(1U)
-
-#define A_ESPI_MISC_CONTROL 0x8f0
-
-#define S_OUT_OF_SYNC_COUNT    0
-#define M_OUT_OF_SYNC_COUNT    0xf
-#define V_OUT_OF_SYNC_COUNT(x) ((x) << S_OUT_OF_SYNC_COUNT)
-#define G_OUT_OF_SYNC_COUNT(x) (((x) >> S_OUT_OF_SYNC_COUNT) & M_OUT_OF_SYNC_COUNT)
-
-#define S_DIP2_COUNT_MODE_ENABLE    4
-#define V_DIP2_COUNT_MODE_ENABLE(x) ((x) << S_DIP2_COUNT_MODE_ENABLE)
-#define F_DIP2_COUNT_MODE_ENABLE    V_DIP2_COUNT_MODE_ENABLE(1U)
-
-#define S_DIP2_PARITY_ERR_THRES    5
-#define M_DIP2_PARITY_ERR_THRES    0xf
-#define V_DIP2_PARITY_ERR_THRES(x) ((x) << S_DIP2_PARITY_ERR_THRES)
-#define G_DIP2_PARITY_ERR_THRES(x) (((x) >> S_DIP2_PARITY_ERR_THRES) & M_DIP2_PARITY_ERR_THRES)
-
-#define S_DIP4_THRES    9
-#define M_DIP4_THRES    0xfff
-#define V_DIP4_THRES(x) ((x) << S_DIP4_THRES)
-#define G_DIP4_THRES(x) (((x) >> S_DIP4_THRES) & M_DIP4_THRES)
-
-#define S_DIP4_THRES_ENABLE    21
-#define V_DIP4_THRES_ENABLE(x) ((x) << S_DIP4_THRES_ENABLE)
-#define F_DIP4_THRES_ENABLE    V_DIP4_THRES_ENABLE(1U)
-
-#define S_FORCE_DISABLE_STATUS    22
-#define V_FORCE_DISABLE_STATUS(x) ((x) << S_FORCE_DISABLE_STATUS)
-#define F_FORCE_DISABLE_STATUS    V_FORCE_DISABLE_STATUS(1U)
-
-#define S_DYNAMIC_DESKEW    23
-#define V_DYNAMIC_DESKEW(x) ((x) << S_DYNAMIC_DESKEW)
-#define F_DYNAMIC_DESKEW    V_DYNAMIC_DESKEW(1U)
-
-#define S_MONITORED_PORT_NUM    25
-#define M_MONITORED_PORT_NUM    0x3
-#define V_MONITORED_PORT_NUM(x) ((x) << S_MONITORED_PORT_NUM)
-#define G_MONITORED_PORT_NUM(x) (((x) >> S_MONITORED_PORT_NUM) & M_MONITORED_PORT_NUM)
-
-#define S_MONITORED_DIRECTION    27
-#define V_MONITORED_DIRECTION(x) ((x) << S_MONITORED_DIRECTION)
-#define F_MONITORED_DIRECTION    V_MONITORED_DIRECTION(1U)
-
-#define S_MONITORED_INTERFACE    28
-#define V_MONITORED_INTERFACE(x) ((x) << S_MONITORED_INTERFACE)
-#define F_MONITORED_INTERFACE    V_MONITORED_INTERFACE(1U)
-
-#define A_ESPI_DIP2_ERR_COUNT 0x8f4
-
-#define S_DIP2_ERR_CNT    0
-#define M_DIP2_ERR_CNT    0xf
-#define V_DIP2_ERR_CNT(x) ((x) << S_DIP2_ERR_CNT)
-#define G_DIP2_ERR_CNT(x) (((x) >> S_DIP2_ERR_CNT) & M_DIP2_ERR_CNT)
-
-#define A_ESPI_CMD_ADDR 0x8f8
-
-#define S_WRITE_DATA    0
-#define M_WRITE_DATA    0xff
-#define V_WRITE_DATA(x) ((x) << S_WRITE_DATA)
-#define G_WRITE_DATA(x) (((x) >> S_WRITE_DATA) & M_WRITE_DATA)
-
-#define S_REGISTER_OFFSET    8
-#define M_REGISTER_OFFSET    0xf
-#define V_REGISTER_OFFSET(x) ((x) << S_REGISTER_OFFSET)
-#define G_REGISTER_OFFSET(x) (((x) >> S_REGISTER_OFFSET) & M_REGISTER_OFFSET)
-
-#define S_CHANNEL_ADDR    12
-#define M_CHANNEL_ADDR    0xf
-#define V_CHANNEL_ADDR(x) ((x) << S_CHANNEL_ADDR)
-#define G_CHANNEL_ADDR(x) (((x) >> S_CHANNEL_ADDR) & M_CHANNEL_ADDR)
-
-#define S_MODULE_ADDR    16
-#define M_MODULE_ADDR    0x3
-#define V_MODULE_ADDR(x) ((x) << S_MODULE_ADDR)
-#define G_MODULE_ADDR(x) (((x) >> S_MODULE_ADDR) & M_MODULE_ADDR)
-
-#define S_BUNDLE_ADDR    20
-#define M_BUNDLE_ADDR    0x3
-#define V_BUNDLE_ADDR(x) ((x) << S_BUNDLE_ADDR)
-#define G_BUNDLE_ADDR(x) (((x) >> S_BUNDLE_ADDR) & M_BUNDLE_ADDR)
-
-#define S_SPI4_COMMAND    24
-#define M_SPI4_COMMAND    0xff
-#define V_SPI4_COMMAND(x) ((x) << S_SPI4_COMMAND)
-#define G_SPI4_COMMAND(x) (((x) >> S_SPI4_COMMAND) & M_SPI4_COMMAND)
-
-#define A_ESPI_GOSTAT 0x8fc
-
-#define S_READ_DATA    0
-#define M_READ_DATA    0xff
-#define V_READ_DATA(x) ((x) << S_READ_DATA)
-#define G_READ_DATA(x) (((x) >> S_READ_DATA) & M_READ_DATA)
-
-#define S_ESPI_CMD_BUSY    8
-#define V_ESPI_CMD_BUSY(x) ((x) << S_ESPI_CMD_BUSY)
-#define F_ESPI_CMD_BUSY    V_ESPI_CMD_BUSY(1U)
-
-#define S_ERROR_ACK    9
-#define V_ERROR_ACK(x) ((x) << S_ERROR_ACK)
-#define F_ERROR_ACK    V_ERROR_ACK(1U)
-
-#define S_UNMAPPED_ERR    10
-#define V_UNMAPPED_ERR(x) ((x) << S_UNMAPPED_ERR)
-#define F_UNMAPPED_ERR    V_UNMAPPED_ERR(1U)
-
-#define S_TRANSACTION_TIMER    16
-#define M_TRANSACTION_TIMER    0xff
-#define V_TRANSACTION_TIMER(x) ((x) << S_TRANSACTION_TIMER)
-#define G_TRANSACTION_TIMER(x) (((x) >> S_TRANSACTION_TIMER) & M_TRANSACTION_TIMER)
-
-
-/* ULP registers */
-#define A_ULP_ULIMIT 0x980
-#define A_ULP_TAGMASK 0x984
-#define A_ULP_HREG_INDEX 0x988
-#define A_ULP_HREG_DATA 0x98c
-#define A_ULP_INT_ENABLE 0x990
-#define A_ULP_INT_CAUSE 0x994
-
-#define S_HREG_PAR_ERR    0
-#define V_HREG_PAR_ERR(x) ((x) << S_HREG_PAR_ERR)
-#define F_HREG_PAR_ERR    V_HREG_PAR_ERR(1U)
-
-#define S_EGRS_DATA_PAR_ERR    1
-#define V_EGRS_DATA_PAR_ERR(x) ((x) << S_EGRS_DATA_PAR_ERR)
-#define F_EGRS_DATA_PAR_ERR    V_EGRS_DATA_PAR_ERR(1U)
-
-#define S_INGRS_DATA_PAR_ERR    2
-#define V_INGRS_DATA_PAR_ERR(x) ((x) << S_INGRS_DATA_PAR_ERR)
-#define F_INGRS_DATA_PAR_ERR    V_INGRS_DATA_PAR_ERR(1U)
-
-#define S_PM_INTR    3
-#define V_PM_INTR(x) ((x) << S_PM_INTR)
-#define F_PM_INTR    V_PM_INTR(1U)
-
-#define S_PM_E2C_SYNC_ERR    4
-#define V_PM_E2C_SYNC_ERR(x) ((x) << S_PM_E2C_SYNC_ERR)
-#define F_PM_E2C_SYNC_ERR    V_PM_E2C_SYNC_ERR(1U)
-
-#define S_PM_C2E_SYNC_ERR    5
-#define V_PM_C2E_SYNC_ERR(x) ((x) << S_PM_C2E_SYNC_ERR)
-#define F_PM_C2E_SYNC_ERR    V_PM_C2E_SYNC_ERR(1U)
-
-#define S_PM_E2C_EMPTY_ERR    6
-#define V_PM_E2C_EMPTY_ERR(x) ((x) << S_PM_E2C_EMPTY_ERR)
-#define F_PM_E2C_EMPTY_ERR    V_PM_E2C_EMPTY_ERR(1U)
-
-#define S_PM_C2E_EMPTY_ERR    7
-#define V_PM_C2E_EMPTY_ERR(x) ((x) << S_PM_C2E_EMPTY_ERR)
-#define F_PM_C2E_EMPTY_ERR    V_PM_C2E_EMPTY_ERR(1U)
-
-#define S_PM_PAR_ERR    8
-#define M_PM_PAR_ERR    0xffff
-#define V_PM_PAR_ERR(x) ((x) << S_PM_PAR_ERR)
-#define G_PM_PAR_ERR(x) (((x) >> S_PM_PAR_ERR) & M_PM_PAR_ERR)
-
-#define S_PM_E2C_WRT_FULL    24
-#define V_PM_E2C_WRT_FULL(x) ((x) << S_PM_E2C_WRT_FULL)
-#define F_PM_E2C_WRT_FULL    V_PM_E2C_WRT_FULL(1U)
-
-#define S_PM_C2E_WRT_FULL    25
-#define V_PM_C2E_WRT_FULL(x) ((x) << S_PM_C2E_WRT_FULL)
-#define F_PM_C2E_WRT_FULL    V_PM_C2E_WRT_FULL(1U)
-
-#define A_ULP_PIO_CTRL 0x998
-
-/* PL registers */
-#define A_PL_ENABLE 0xa00
-
-#define S_PL_INTR_SGE_ERR    0
-#define V_PL_INTR_SGE_ERR(x) ((x) << S_PL_INTR_SGE_ERR)
-#define F_PL_INTR_SGE_ERR    V_PL_INTR_SGE_ERR(1U)
-
-#define S_PL_INTR_SGE_DATA    1
-#define V_PL_INTR_SGE_DATA(x) ((x) << S_PL_INTR_SGE_DATA)
-#define F_PL_INTR_SGE_DATA    V_PL_INTR_SGE_DATA(1U)
-
-#define S_PL_INTR_MC3    2
-#define V_PL_INTR_MC3(x) ((x) << S_PL_INTR_MC3)
-#define F_PL_INTR_MC3    V_PL_INTR_MC3(1U)
-
-#define S_PL_INTR_MC4    3
-#define V_PL_INTR_MC4(x) ((x) << S_PL_INTR_MC4)
-#define F_PL_INTR_MC4    V_PL_INTR_MC4(1U)
-
-#define S_PL_INTR_MC5    4
-#define V_PL_INTR_MC5(x) ((x) << S_PL_INTR_MC5)
-#define F_PL_INTR_MC5    V_PL_INTR_MC5(1U)
-
-#define S_PL_INTR_RAT    5
-#define V_PL_INTR_RAT(x) ((x) << S_PL_INTR_RAT)
-#define F_PL_INTR_RAT    V_PL_INTR_RAT(1U)
-
-#define S_PL_INTR_TP    6
-#define V_PL_INTR_TP(x) ((x) << S_PL_INTR_TP)
-#define F_PL_INTR_TP    V_PL_INTR_TP(1U)
-
-#define S_PL_INTR_ULP    7
-#define V_PL_INTR_ULP(x) ((x) << S_PL_INTR_ULP)
-#define F_PL_INTR_ULP    V_PL_INTR_ULP(1U)
-
-#define S_PL_INTR_ESPI    8
-#define V_PL_INTR_ESPI(x) ((x) << S_PL_INTR_ESPI)
-#define F_PL_INTR_ESPI    V_PL_INTR_ESPI(1U)
-
-#define S_PL_INTR_CSPI    9
-#define V_PL_INTR_CSPI(x) ((x) << S_PL_INTR_CSPI)
-#define F_PL_INTR_CSPI    V_PL_INTR_CSPI(1U)
-
-#define S_PL_INTR_PCIX    10
-#define V_PL_INTR_PCIX(x) ((x) << S_PL_INTR_PCIX)
-#define F_PL_INTR_PCIX    V_PL_INTR_PCIX(1U)
-
-#define S_PL_INTR_EXT    11
-#define V_PL_INTR_EXT(x) ((x) << S_PL_INTR_EXT)
-#define F_PL_INTR_EXT    V_PL_INTR_EXT(1U)
-
-#define A_PL_CAUSE 0xa04
-
-/* MC5 registers */
-#define A_MC5_CONFIG 0xc04
-
-#define S_MODE    0
-#define V_MODE(x) ((x) << S_MODE)
-#define F_MODE    V_MODE(1U)
-
-#define S_TCAM_RESET    1
-#define V_TCAM_RESET(x) ((x) << S_TCAM_RESET)
-#define F_TCAM_RESET    V_TCAM_RESET(1U)
-
-#define S_TCAM_READY    2
-#define V_TCAM_READY(x) ((x) << S_TCAM_READY)
-#define F_TCAM_READY    V_TCAM_READY(1U)
-
-#define S_DBGI_ENABLE    4
-#define V_DBGI_ENABLE(x) ((x) << S_DBGI_ENABLE)
-#define F_DBGI_ENABLE    V_DBGI_ENABLE(1U)
-
-#define S_M_BUS_ENABLE    5
-#define V_M_BUS_ENABLE(x) ((x) << S_M_BUS_ENABLE)
-#define F_M_BUS_ENABLE    V_M_BUS_ENABLE(1U)
-
-#define S_PARITY_ENABLE    6
-#define V_PARITY_ENABLE(x) ((x) << S_PARITY_ENABLE)
-#define F_PARITY_ENABLE    V_PARITY_ENABLE(1U)
-
-#define S_SYN_ISSUE_MODE    7
-#define M_SYN_ISSUE_MODE    0x3
-#define V_SYN_ISSUE_MODE(x) ((x) << S_SYN_ISSUE_MODE)
-#define G_SYN_ISSUE_MODE(x) (((x) >> S_SYN_ISSUE_MODE) & M_SYN_ISSUE_MODE)
-
-#define S_BUILD    16
-#define V_BUILD(x) ((x) << S_BUILD)
-#define F_BUILD    V_BUILD(1U)
-
-#define S_COMPRESSION_ENABLE    17
-#define V_COMPRESSION_ENABLE(x) ((x) << S_COMPRESSION_ENABLE)
-#define F_COMPRESSION_ENABLE    V_COMPRESSION_ENABLE(1U)
-
-#define S_NUM_LIP    18
-#define M_NUM_LIP    0x3f
-#define V_NUM_LIP(x) ((x) << S_NUM_LIP)
-#define G_NUM_LIP(x) (((x) >> S_NUM_LIP) & M_NUM_LIP)
-
-#define S_TCAM_PART_CNT    24
-#define M_TCAM_PART_CNT    0x3
-#define V_TCAM_PART_CNT(x) ((x) << S_TCAM_PART_CNT)
-#define G_TCAM_PART_CNT(x) (((x) >> S_TCAM_PART_CNT) & M_TCAM_PART_CNT)
-
-#define S_TCAM_PART_TYPE    26
-#define M_TCAM_PART_TYPE    0x3
-#define V_TCAM_PART_TYPE(x) ((x) << S_TCAM_PART_TYPE)
-#define G_TCAM_PART_TYPE(x) (((x) >> S_TCAM_PART_TYPE) & M_TCAM_PART_TYPE)
-
-#define S_TCAM_PART_SIZE    28
-#define M_TCAM_PART_SIZE    0x3
-#define V_TCAM_PART_SIZE(x) ((x) << S_TCAM_PART_SIZE)
-#define G_TCAM_PART_SIZE(x) (((x) >> S_TCAM_PART_SIZE) & M_TCAM_PART_SIZE)
-
-#define S_TCAM_PART_TYPE_HI    30
-#define V_TCAM_PART_TYPE_HI(x) ((x) << S_TCAM_PART_TYPE_HI)
-#define F_TCAM_PART_TYPE_HI    V_TCAM_PART_TYPE_HI(1U)
-
-#define A_MC5_SIZE 0xc08
-
-#define S_SIZE    0
-#define M_SIZE    0x3fffff
-#define V_SIZE(x) ((x) << S_SIZE)
-#define G_SIZE(x) (((x) >> S_SIZE) & M_SIZE)
-
-#define A_MC5_ROUTING_TABLE_INDEX 0xc0c
-
-#define S_START_OF_ROUTING_TABLE    0
-#define M_START_OF_ROUTING_TABLE    0x3fffff
-#define V_START_OF_ROUTING_TABLE(x) ((x) << S_START_OF_ROUTING_TABLE)
-#define G_START_OF_ROUTING_TABLE(x) (((x) >> S_START_OF_ROUTING_TABLE) & M_START_OF_ROUTING_TABLE)
-
-#define A_MC5_SERVER_INDEX 0xc14
-
-#define S_START_OF_SERVER_INDEX    0
-#define M_START_OF_SERVER_INDEX    0x3fffff
-#define V_START_OF_SERVER_INDEX(x) ((x) << S_START_OF_SERVER_INDEX)
-#define G_START_OF_SERVER_INDEX(x) (((x) >> S_START_OF_SERVER_INDEX) & M_START_OF_SERVER_INDEX)
-
-#define A_MC5_LIP_RAM_ADDR 0xc18
-
-#define S_LOCAL_IP_RAM_ADDR    0
-#define M_LOCAL_IP_RAM_ADDR    0x3f
-#define V_LOCAL_IP_RAM_ADDR(x) ((x) << S_LOCAL_IP_RAM_ADDR)
-#define G_LOCAL_IP_RAM_ADDR(x) (((x) >> S_LOCAL_IP_RAM_ADDR) & M_LOCAL_IP_RAM_ADDR)
-
-#define S_RAM_WRITE_ENABLE    8
-#define V_RAM_WRITE_ENABLE(x) ((x) << S_RAM_WRITE_ENABLE)
-#define F_RAM_WRITE_ENABLE    V_RAM_WRITE_ENABLE(1U)
-
-#define A_MC5_LIP_RAM_DATA 0xc1c
-#define A_MC5_RSP_LATENCY 0xc20
-
-#define S_SEARCH_RESPONSE_LATENCY    0
-#define M_SEARCH_RESPONSE_LATENCY    0x1f
-#define V_SEARCH_RESPONSE_LATENCY(x) ((x) << S_SEARCH_RESPONSE_LATENCY)
-#define G_SEARCH_RESPONSE_LATENCY(x) (((x) >> S_SEARCH_RESPONSE_LATENCY) & M_SEARCH_RESPONSE_LATENCY)
-
-#define S_LEARN_RESPONSE_LATENCY    8
-#define M_LEARN_RESPONSE_LATENCY    0x1f
-#define V_LEARN_RESPONSE_LATENCY(x) ((x) << S_LEARN_RESPONSE_LATENCY)
-#define G_LEARN_RESPONSE_LATENCY(x) (((x) >> S_LEARN_RESPONSE_LATENCY) & M_LEARN_RESPONSE_LATENCY)
-
-#define A_MC5_PARITY_LATENCY 0xc24
-
-#define S_SRCHLAT    0
-#define M_SRCHLAT    0x1f
-#define V_SRCHLAT(x) ((x) << S_SRCHLAT)
-#define G_SRCHLAT(x) (((x) >> S_SRCHLAT) & M_SRCHLAT)
-
-#define S_PARLAT    8
-#define M_PARLAT    0x1f
-#define V_PARLAT(x) ((x) << S_PARLAT)
-#define G_PARLAT(x) (((x) >> S_PARLAT) & M_PARLAT)
-
-#define A_MC5_WR_LRN_VERIFY 0xc28
-
-#define S_POVEREN    0
-#define V_POVEREN(x) ((x) << S_POVEREN)
-#define F_POVEREN    V_POVEREN(1U)
-
-#define S_LRNVEREN    1
-#define V_LRNVEREN(x) ((x) << S_LRNVEREN)
-#define F_LRNVEREN    V_LRNVEREN(1U)
-
-#define S_VWVEREN    2
-#define V_VWVEREN(x) ((x) << S_VWVEREN)
-#define F_VWVEREN    V_VWVEREN(1U)
-
-#define A_MC5_PART_ID_INDEX 0xc2c
-
-#define S_IDINDEX    0
-#define M_IDINDEX    0xf
-#define V_IDINDEX(x) ((x) << S_IDINDEX)
-#define G_IDINDEX(x) (((x) >> S_IDINDEX) & M_IDINDEX)
-
-#define A_MC5_RESET_MAX 0xc30
-
-#define S_RSTMAX    0
-#define M_RSTMAX    0x1ff
-#define V_RSTMAX(x) ((x) << S_RSTMAX)
-#define G_RSTMAX(x) (((x) >> S_RSTMAX) & M_RSTMAX)
-
-#define A_MC5_INT_ENABLE 0xc40
-
-#define S_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR    0
-#define V_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR(x) ((x) << S_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR)
-#define F_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR    V_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR(1U)
-
-#define S_MC5_INT_HIT_IN_ACTIVE_REGION_ERR    1
-#define V_MC5_INT_HIT_IN_ACTIVE_REGION_ERR(x) ((x) << S_MC5_INT_HIT_IN_ACTIVE_REGION_ERR)
-#define F_MC5_INT_HIT_IN_ACTIVE_REGION_ERR    V_MC5_INT_HIT_IN_ACTIVE_REGION_ERR(1U)
-
-#define S_MC5_INT_HIT_IN_RT_REGION_ERR    2
-#define V_MC5_INT_HIT_IN_RT_REGION_ERR(x) ((x) << S_MC5_INT_HIT_IN_RT_REGION_ERR)
-#define F_MC5_INT_HIT_IN_RT_REGION_ERR    V_MC5_INT_HIT_IN_RT_REGION_ERR(1U)
-
-#define S_MC5_INT_MISS_ERR    3
-#define V_MC5_INT_MISS_ERR(x) ((x) << S_MC5_INT_MISS_ERR)
-#define F_MC5_INT_MISS_ERR    V_MC5_INT_MISS_ERR(1U)
-
-#define S_MC5_INT_LIP0_ERR    4
-#define V_MC5_INT_LIP0_ERR(x) ((x) << S_MC5_INT_LIP0_ERR)
-#define F_MC5_INT_LIP0_ERR    V_MC5_INT_LIP0_ERR(1U)
-
-#define S_MC5_INT_LIP_MISS_ERR    5
-#define V_MC5_INT_LIP_MISS_ERR(x) ((x) << S_MC5_INT_LIP_MISS_ERR)
-#define F_MC5_INT_LIP_MISS_ERR    V_MC5_INT_LIP_MISS_ERR(1U)
-
-#define S_MC5_INT_PARITY_ERR    6
-#define V_MC5_INT_PARITY_ERR(x) ((x) << S_MC5_INT_PARITY_ERR)
-#define F_MC5_INT_PARITY_ERR    V_MC5_INT_PARITY_ERR(1U)
-
-#define S_MC5_INT_ACTIVE_REGION_FULL    7
-#define V_MC5_INT_ACTIVE_REGION_FULL(x) ((x) << S_MC5_INT_ACTIVE_REGION_FULL)
-#define F_MC5_INT_ACTIVE_REGION_FULL    V_MC5_INT_ACTIVE_REGION_FULL(1U)
-
-#define S_MC5_INT_NFA_SRCH_ERR    8
-#define V_MC5_INT_NFA_SRCH_ERR(x) ((x) << S_MC5_INT_NFA_SRCH_ERR)
-#define F_MC5_INT_NFA_SRCH_ERR    V_MC5_INT_NFA_SRCH_ERR(1U)
-
-#define S_MC5_INT_SYN_COOKIE    9
-#define V_MC5_INT_SYN_COOKIE(x) ((x) << S_MC5_INT_SYN_COOKIE)
-#define F_MC5_INT_SYN_COOKIE    V_MC5_INT_SYN_COOKIE(1U)
-
-#define S_MC5_INT_SYN_COOKIE_BAD    10
-#define V_MC5_INT_SYN_COOKIE_BAD(x) ((x) << S_MC5_INT_SYN_COOKIE_BAD)
-#define F_MC5_INT_SYN_COOKIE_BAD    V_MC5_INT_SYN_COOKIE_BAD(1U)
-
-#define S_MC5_INT_SYN_COOKIE_OFF    11
-#define V_MC5_INT_SYN_COOKIE_OFF(x) ((x) << S_MC5_INT_SYN_COOKIE_OFF)
-#define F_MC5_INT_SYN_COOKIE_OFF    V_MC5_INT_SYN_COOKIE_OFF(1U)
-
-#define S_MC5_INT_UNKNOWN_CMD    15
-#define V_MC5_INT_UNKNOWN_CMD(x) ((x) << S_MC5_INT_UNKNOWN_CMD)
-#define F_MC5_INT_UNKNOWN_CMD    V_MC5_INT_UNKNOWN_CMD(1U)
-
-#define S_MC5_INT_REQUESTQ_PARITY_ERR    16
-#define V_MC5_INT_REQUESTQ_PARITY_ERR(x) ((x) << S_MC5_INT_REQUESTQ_PARITY_ERR)
-#define F_MC5_INT_REQUESTQ_PARITY_ERR    V_MC5_INT_REQUESTQ_PARITY_ERR(1U)
-
-#define S_MC5_INT_DISPATCHQ_PARITY_ERR    17
-#define V_MC5_INT_DISPATCHQ_PARITY_ERR(x) ((x) << S_MC5_INT_DISPATCHQ_PARITY_ERR)
-#define F_MC5_INT_DISPATCHQ_PARITY_ERR    V_MC5_INT_DISPATCHQ_PARITY_ERR(1U)
-
-#define S_MC5_INT_DEL_ACT_EMPTY    18
-#define V_MC5_INT_DEL_ACT_EMPTY(x) ((x) << S_MC5_INT_DEL_ACT_EMPTY)
-#define F_MC5_INT_DEL_ACT_EMPTY    V_MC5_INT_DEL_ACT_EMPTY(1U)
-
-#define A_MC5_INT_CAUSE 0xc44
-#define A_MC5_INT_TID 0xc48
-#define A_MC5_INT_PTID 0xc4c
-#define A_MC5_DBGI_CONFIG 0xc74
-#define A_MC5_DBGI_REQ_CMD 0xc78
-
-#define S_CMDMODE    0
-#define M_CMDMODE    0x7
-#define V_CMDMODE(x) ((x) << S_CMDMODE)
-#define G_CMDMODE(x) (((x) >> S_CMDMODE) & M_CMDMODE)
-
-#define S_SADRSEL    4
-#define V_SADRSEL(x) ((x) << S_SADRSEL)
-#define F_SADRSEL    V_SADRSEL(1U)
-
-#define S_WRITE_BURST_SIZE    22
-#define M_WRITE_BURST_SIZE    0x3ff
-#define V_WRITE_BURST_SIZE(x) ((x) << S_WRITE_BURST_SIZE)
-#define G_WRITE_BURST_SIZE(x) (((x) >> S_WRITE_BURST_SIZE) & M_WRITE_BURST_SIZE)
-
-#define A_MC5_DBGI_REQ_ADDR0 0xc7c
-#define A_MC5_DBGI_REQ_ADDR1 0xc80
-#define A_MC5_DBGI_REQ_ADDR2 0xc84
-#define A_MC5_DBGI_REQ_DATA0 0xc88
-#define A_MC5_DBGI_REQ_DATA1 0xc8c
-#define A_MC5_DBGI_REQ_DATA2 0xc90
-#define A_MC5_DBGI_REQ_DATA3 0xc94
-#define A_MC5_DBGI_REQ_DATA4 0xc98
-#define A_MC5_DBGI_REQ_MASK0 0xc9c
-#define A_MC5_DBGI_REQ_MASK1 0xca0
-#define A_MC5_DBGI_REQ_MASK2 0xca4
-#define A_MC5_DBGI_REQ_MASK3 0xca8
-#define A_MC5_DBGI_REQ_MASK4 0xcac
-#define A_MC5_DBGI_RSP_STATUS 0xcb0
-
-#define S_DBGI_RSP_VALID    0
-#define V_DBGI_RSP_VALID(x) ((x) << S_DBGI_RSP_VALID)
-#define F_DBGI_RSP_VALID    V_DBGI_RSP_VALID(1U)
-
-#define S_DBGI_RSP_HIT    1
-#define V_DBGI_RSP_HIT(x) ((x) << S_DBGI_RSP_HIT)
-#define F_DBGI_RSP_HIT    V_DBGI_RSP_HIT(1U)
-
-#define S_DBGI_RSP_ERR    2
-#define V_DBGI_RSP_ERR(x) ((x) << S_DBGI_RSP_ERR)
-#define F_DBGI_RSP_ERR    V_DBGI_RSP_ERR(1U)
-
-#define S_DBGI_RSP_ERR_REASON    8
-#define M_DBGI_RSP_ERR_REASON    0x7
-#define V_DBGI_RSP_ERR_REASON(x) ((x) << S_DBGI_RSP_ERR_REASON)
-#define G_DBGI_RSP_ERR_REASON(x) (((x) >> S_DBGI_RSP_ERR_REASON) & M_DBGI_RSP_ERR_REASON)
-
-#define A_MC5_DBGI_RSP_DATA0 0xcb4
-#define A_MC5_DBGI_RSP_DATA1 0xcb8
-#define A_MC5_DBGI_RSP_DATA2 0xcbc
-#define A_MC5_DBGI_RSP_DATA3 0xcc0
-#define A_MC5_DBGI_RSP_DATA4 0xcc4
-#define A_MC5_DBGI_RSP_LAST_CMD 0xcc8
-#define A_MC5_POPEN_DATA_WR_CMD 0xccc
-#define A_MC5_POPEN_MASK_WR_CMD 0xcd0
-#define A_MC5_AOPEN_SRCH_CMD 0xcd4
-#define A_MC5_AOPEN_LRN_CMD 0xcd8
-#define A_MC5_SYN_SRCH_CMD 0xcdc
-#define A_MC5_SYN_LRN_CMD 0xce0
-#define A_MC5_ACK_SRCH_CMD 0xce4
-#define A_MC5_ACK_LRN_CMD 0xce8
-#define A_MC5_ILOOKUP_CMD 0xcec
-#define A_MC5_ELOOKUP_CMD 0xcf0
-#define A_MC5_DATA_WRITE_CMD 0xcf4
-#define A_MC5_DATA_READ_CMD 0xcf8
-#define A_MC5_MASK_WRITE_CMD 0xcfc
-
-/* PCICFG registers */
-#define A_PCICFG_PM_CSR 0x44
-#define A_PCICFG_VPD_ADDR 0x4a
-
-#define S_VPD_ADDR    0
-#define M_VPD_ADDR    0x7fff
-#define V_VPD_ADDR(x) ((x) << S_VPD_ADDR)
-#define G_VPD_ADDR(x) (((x) >> S_VPD_ADDR) & M_VPD_ADDR)
-
-#define S_VPD_OP_FLAG    15
-#define V_VPD_OP_FLAG(x) ((x) << S_VPD_OP_FLAG)
-#define F_VPD_OP_FLAG    V_VPD_OP_FLAG(1U)
-
-#define A_PCICFG_VPD_DATA 0x4c
-#define A_PCICFG_PCIX_CMD 0x60
-#define A_PCICFG_INTR_ENABLE 0xf4
-
-#define S_MASTER_PARITY_ERR    0
-#define V_MASTER_PARITY_ERR(x) ((x) << S_MASTER_PARITY_ERR)
-#define F_MASTER_PARITY_ERR    V_MASTER_PARITY_ERR(1U)
-
-#define S_SIG_TARGET_ABORT    1
-#define V_SIG_TARGET_ABORT(x) ((x) << S_SIG_TARGET_ABORT)
-#define F_SIG_TARGET_ABORT    V_SIG_TARGET_ABORT(1U)
-
-#define S_RCV_TARGET_ABORT    2
-#define V_RCV_TARGET_ABORT(x) ((x) << S_RCV_TARGET_ABORT)
-#define F_RCV_TARGET_ABORT    V_RCV_TARGET_ABORT(1U)
-
-#define S_RCV_MASTER_ABORT    3
-#define V_RCV_MASTER_ABORT(x) ((x) << S_RCV_MASTER_ABORT)
-#define F_RCV_MASTER_ABORT    V_RCV_MASTER_ABORT(1U)
-
-#define S_SIG_SYS_ERR    4
-#define V_SIG_SYS_ERR(x) ((x) << S_SIG_SYS_ERR)
-#define F_SIG_SYS_ERR    V_SIG_SYS_ERR(1U)
-
-#define S_DET_PARITY_ERR    5
-#define V_DET_PARITY_ERR(x) ((x) << S_DET_PARITY_ERR)
-#define F_DET_PARITY_ERR    V_DET_PARITY_ERR(1U)
-
-#define S_PIO_PARITY_ERR    6
-#define V_PIO_PARITY_ERR(x) ((x) << S_PIO_PARITY_ERR)
-#define F_PIO_PARITY_ERR    V_PIO_PARITY_ERR(1U)
-
-#define S_WF_PARITY_ERR    7
-#define V_WF_PARITY_ERR(x) ((x) << S_WF_PARITY_ERR)
-#define F_WF_PARITY_ERR    V_WF_PARITY_ERR(1U)
-
-#define S_RF_PARITY_ERR    8
-#define M_RF_PARITY_ERR    0x3
-#define V_RF_PARITY_ERR(x) ((x) << S_RF_PARITY_ERR)
-#define G_RF_PARITY_ERR(x) (((x) >> S_RF_PARITY_ERR) & M_RF_PARITY_ERR)
-
-#define S_CF_PARITY_ERR    10
-#define M_CF_PARITY_ERR    0x3
-#define V_CF_PARITY_ERR(x) ((x) << S_CF_PARITY_ERR)
-#define G_CF_PARITY_ERR(x) (((x) >> S_CF_PARITY_ERR) & M_CF_PARITY_ERR)
-
-#define A_PCICFG_INTR_CAUSE 0xf8
-#define A_PCICFG_MODE 0xfc
-
-#define S_PCI_MODE_64BIT    0
-#define V_PCI_MODE_64BIT(x) ((x) << S_PCI_MODE_64BIT)
-#define F_PCI_MODE_64BIT    V_PCI_MODE_64BIT(1U)
-
-#define S_PCI_MODE_66MHZ    1
-#define V_PCI_MODE_66MHZ(x) ((x) << S_PCI_MODE_66MHZ)
-#define F_PCI_MODE_66MHZ    V_PCI_MODE_66MHZ(1U)
-
-#define S_PCI_MODE_PCIX_INITPAT    2
-#define M_PCI_MODE_PCIX_INITPAT    0x7
-#define V_PCI_MODE_PCIX_INITPAT(x) ((x) << S_PCI_MODE_PCIX_INITPAT)
-#define G_PCI_MODE_PCIX_INITPAT(x) (((x) >> S_PCI_MODE_PCIX_INITPAT) & M_PCI_MODE_PCIX_INITPAT)
-
-#define S_PCI_MODE_PCIX    5
-#define V_PCI_MODE_PCIX(x) ((x) << S_PCI_MODE_PCIX)
-#define F_PCI_MODE_PCIX    V_PCI_MODE_PCIX(1U)
-
-#define S_PCI_MODE_CLK    6
-#define M_PCI_MODE_CLK    0x3
-#define V_PCI_MODE_CLK(x) ((x) << S_PCI_MODE_CLK)
-#define G_PCI_MODE_CLK(x) (((x) >> S_PCI_MODE_CLK) & M_PCI_MODE_CLK)
-
-#endif /* _CXGB_REGS_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/sge.c linux-libre-3.2-gnu/drivers/net/chelsio/sge.c
--- linux-libre-3.1-gnu/drivers/net/chelsio/sge.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/sge.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2140 +0,0 @@
-/*****************************************************************************
- *                                                                           *
- * File: sge.c                                                               *
- * $Revision: 1.26 $                                                         *
- * $Date: 2005/06/21 18:29:48 $                                              *
- * Description:                                                              *
- *  DMA engine.                                                              *
- *  part of the Chelsio 10Gb Ethernet 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.                                *
- *                                                                           *
- * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
- *                                                                           *
- * http://www.chelsio.com                                                    *
- *                                                                           *
- * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
- * All rights reserved.                                                      *
- *                                                                           *
- * Maintainers: maintainers@chelsio.com                                      *
- *                                                                           *
- * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
- *          Tina Yang               <tainay@chelsio.com>                     *
- *          Felix Marti             <felix@chelsio.com>                      *
- *          Scott Bardone           <sbardone@chelsio.com>                   *
- *          Kurt Ottaway            <kottaway@chelsio.com>                   *
- *          Frank DiMambro          <frank@chelsio.com>                      *
- *                                                                           *
- * History:                                                                  *
- *                                                                           *
- ****************************************************************************/
-
-#include "common.h"
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/ktime.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_vlan.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/tcp.h>
-#include <linux/ip.h>
-#include <linux/in.h>
-#include <linux/if_arp.h>
-#include <linux/slab.h>
-#include <linux/prefetch.h>
-
-#include "cpl5_cmd.h"
-#include "sge.h"
-#include "regs.h"
-#include "espi.h"
-
-/* This belongs in if_ether.h */
-#define ETH_P_CPL5 0xf
-
-#define SGE_CMDQ_N		2
-#define SGE_FREELQ_N		2
-#define SGE_CMDQ0_E_N		1024
-#define SGE_CMDQ1_E_N		128
-#define SGE_FREEL_SIZE		4096
-#define SGE_JUMBO_FREEL_SIZE	512
-#define SGE_FREEL_REFILL_THRESH	16
-#define SGE_RESPQ_E_N		1024
-#define SGE_INTRTIMER_NRES	1000
-#define SGE_RX_SM_BUF_SIZE	1536
-#define SGE_TX_DESC_MAX_PLEN	16384
-
-#define SGE_RESPQ_REPLENISH_THRES (SGE_RESPQ_E_N / 4)
-
-/*
- * Period of the TX buffer reclaim timer.  This timer does not need to run
- * frequently as TX buffers are usually reclaimed by new TX packets.
- */
-#define TX_RECLAIM_PERIOD (HZ / 4)
-
-#define M_CMD_LEN       0x7fffffff
-#define V_CMD_LEN(v)    (v)
-#define G_CMD_LEN(v)    ((v) & M_CMD_LEN)
-#define V_CMD_GEN1(v)   ((v) << 31)
-#define V_CMD_GEN2(v)   (v)
-#define F_CMD_DATAVALID (1 << 1)
-#define F_CMD_SOP       (1 << 2)
-#define V_CMD_EOP(v)    ((v) << 3)
-
-/*
- * Command queue, receive buffer list, and response queue descriptors.
- */
-#if defined(__BIG_ENDIAN_BITFIELD)
-struct cmdQ_e {
-	u32 addr_lo;
-	u32 len_gen;
-	u32 flags;
-	u32 addr_hi;
-};
-
-struct freelQ_e {
-	u32 addr_lo;
-	u32 len_gen;
-	u32 gen2;
-	u32 addr_hi;
-};
-
-struct respQ_e {
-	u32 Qsleeping		: 4;
-	u32 Cmdq1CreditReturn	: 5;
-	u32 Cmdq1DmaComplete	: 5;
-	u32 Cmdq0CreditReturn	: 5;
-	u32 Cmdq0DmaComplete	: 5;
-	u32 FreelistQid		: 2;
-	u32 CreditValid		: 1;
-	u32 DataValid		: 1;
-	u32 Offload		: 1;
-	u32 Eop			: 1;
-	u32 Sop			: 1;
-	u32 GenerationBit	: 1;
-	u32 BufferLength;
-};
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-struct cmdQ_e {
-	u32 len_gen;
-	u32 addr_lo;
-	u32 addr_hi;
-	u32 flags;
-};
-
-struct freelQ_e {
-	u32 len_gen;
-	u32 addr_lo;
-	u32 addr_hi;
-	u32 gen2;
-};
-
-struct respQ_e {
-	u32 BufferLength;
-	u32 GenerationBit	: 1;
-	u32 Sop			: 1;
-	u32 Eop			: 1;
-	u32 Offload		: 1;
-	u32 DataValid		: 1;
-	u32 CreditValid		: 1;
-	u32 FreelistQid		: 2;
-	u32 Cmdq0DmaComplete	: 5;
-	u32 Cmdq0CreditReturn	: 5;
-	u32 Cmdq1DmaComplete	: 5;
-	u32 Cmdq1CreditReturn	: 5;
-	u32 Qsleeping		: 4;
-} ;
-#endif
-
-/*
- * SW Context Command and Freelist Queue Descriptors
- */
-struct cmdQ_ce {
-	struct sk_buff *skb;
-	DEFINE_DMA_UNMAP_ADDR(dma_addr);
-	DEFINE_DMA_UNMAP_LEN(dma_len);
-};
-
-struct freelQ_ce {
-	struct sk_buff *skb;
-	DEFINE_DMA_UNMAP_ADDR(dma_addr);
-	DEFINE_DMA_UNMAP_LEN(dma_len);
-};
-
-/*
- * SW command, freelist and response rings
- */
-struct cmdQ {
-	unsigned long   status;         /* HW DMA fetch status */
-	unsigned int    in_use;         /* # of in-use command descriptors */
-	unsigned int	size;	        /* # of descriptors */
-	unsigned int    processed;      /* total # of descs HW has processed */
-	unsigned int    cleaned;        /* total # of descs SW has reclaimed */
-	unsigned int    stop_thres;     /* SW TX queue suspend threshold */
-	u16		pidx;           /* producer index (SW) */
-	u16		cidx;           /* consumer index (HW) */
-	u8		genbit;         /* current generation (=valid) bit */
-	u8              sop;            /* is next entry start of packet? */
-	struct cmdQ_e  *entries;        /* HW command descriptor Q */
-	struct cmdQ_ce *centries;       /* SW command context descriptor Q */
-	dma_addr_t	dma_addr;       /* DMA addr HW command descriptor Q */
-	spinlock_t	lock;           /* Lock to protect cmdQ enqueuing */
-};
-
-struct freelQ {
-	unsigned int	credits;        /* # of available RX buffers */
-	unsigned int	size;	        /* free list capacity */
-	u16		pidx;           /* producer index (SW) */
-	u16		cidx;           /* consumer index (HW) */
-	u16		rx_buffer_size; /* Buffer size on this free list */
-	u16             dma_offset;     /* DMA offset to align IP headers */
-	u16             recycleq_idx;   /* skb recycle q to use */
-	u8		genbit;	        /* current generation (=valid) bit */
-	struct freelQ_e	*entries;       /* HW freelist descriptor Q */
-	struct freelQ_ce *centries;     /* SW freelist context descriptor Q */
-	dma_addr_t	dma_addr;       /* DMA addr HW freelist descriptor Q */
-};
-
-struct respQ {
-	unsigned int	credits;        /* credits to be returned to SGE */
-	unsigned int	size;	        /* # of response Q descriptors */
-	u16		cidx;	        /* consumer index (SW) */
-	u8		genbit;	        /* current generation(=valid) bit */
-	struct respQ_e *entries;        /* HW response descriptor Q */
-	dma_addr_t	dma_addr;       /* DMA addr HW response descriptor Q */
-};
-
-/* Bit flags for cmdQ.status */
-enum {
-	CMDQ_STAT_RUNNING = 1,          /* fetch engine is running */
-	CMDQ_STAT_LAST_PKT_DB = 2       /* last packet rung the doorbell */
-};
-
-/* T204 TX SW scheduler */
-
-/* Per T204 TX port */
-struct sched_port {
-	unsigned int	avail;		/* available bits - quota */
-	unsigned int	drain_bits_per_1024ns; /* drain rate */
-	unsigned int	speed;		/* drain rate, mbps */
-	unsigned int	mtu;		/* mtu size */
-	struct sk_buff_head skbq;	/* pending skbs */
-};
-
-/* Per T204 device */
-struct sched {
-	ktime_t         last_updated;   /* last time quotas were computed */
-	unsigned int	max_avail;	/* max bits to be sent to any port */
-	unsigned int	port;		/* port index (round robin ports) */
-	unsigned int	num;		/* num skbs in per port queues */
-	struct sched_port p[MAX_NPORTS];
-	struct tasklet_struct sched_tsk;/* tasklet used to run scheduler */
-};
-static void restart_sched(unsigned long);
-
-
-/*
- * Main SGE data structure
- *
- * Interrupts are handled by a single CPU and it is likely that on a MP system
- * the application is migrated to another CPU. In that scenario, we try to
- * separate the RX(in irq context) and TX state in order to decrease memory
- * contention.
- */
-struct sge {
-	struct adapter *adapter;	/* adapter backpointer */
-	struct net_device *netdev;      /* netdevice backpointer */
-	struct freelQ	freelQ[SGE_FREELQ_N]; /* buffer free lists */
-	struct respQ	respQ;		/* response Q */
-	unsigned long   stopped_tx_queues; /* bitmap of suspended Tx queues */
-	unsigned int	rx_pkt_pad;     /* RX padding for L2 packets */
-	unsigned int	jumbo_fl;       /* jumbo freelist Q index */
-	unsigned int	intrtimer_nres;	/* no-resource interrupt timer */
-	unsigned int    fixed_intrtimer;/* non-adaptive interrupt timer */
-	struct timer_list tx_reclaim_timer; /* reclaims TX buffers */
-	struct timer_list espibug_timer;
-	unsigned long	espibug_timeout;
-	struct sk_buff	*espibug_skb[MAX_NPORTS];
-	u32		sge_control;	/* shadow value of sge control reg */
-	struct sge_intr_counts stats;
-	struct sge_port_stats __percpu *port_stats[MAX_NPORTS];
-	struct sched	*tx_sched;
-	struct cmdQ cmdQ[SGE_CMDQ_N] ____cacheline_aligned_in_smp;
-};
-
-static const u8 ch_mac_addr[ETH_ALEN] = {
-	0x0, 0x7, 0x43, 0x0, 0x0, 0x0
-};
-
-/*
- * stop tasklet and free all pending skb's
- */
-static void tx_sched_stop(struct sge *sge)
-{
-	struct sched *s = sge->tx_sched;
-	int i;
-
-	tasklet_kill(&s->sched_tsk);
-
-	for (i = 0; i < MAX_NPORTS; i++)
-		__skb_queue_purge(&s->p[s->port].skbq);
-}
-
-/*
- * t1_sched_update_parms() is called when the MTU or link speed changes. It
- * re-computes scheduler parameters to scope with the change.
- */
-unsigned int t1_sched_update_parms(struct sge *sge, unsigned int port,
-				   unsigned int mtu, unsigned int speed)
-{
-	struct sched *s = sge->tx_sched;
-	struct sched_port *p = &s->p[port];
-	unsigned int max_avail_segs;
-
-	pr_debug("t1_sched_update_params mtu=%d speed=%d\n", mtu, speed);
-	if (speed)
-		p->speed = speed;
-	if (mtu)
-		p->mtu = mtu;
-
-	if (speed || mtu) {
-		unsigned long long drain = 1024ULL * p->speed * (p->mtu - 40);
-		do_div(drain, (p->mtu + 50) * 1000);
-		p->drain_bits_per_1024ns = (unsigned int) drain;
-
-		if (p->speed < 1000)
-			p->drain_bits_per_1024ns =
-				90 * p->drain_bits_per_1024ns / 100;
-	}
-
-	if (board_info(sge->adapter)->board == CHBT_BOARD_CHT204) {
-		p->drain_bits_per_1024ns -= 16;
-		s->max_avail = max(4096U, p->mtu + 16 + 14 + 4);
-		max_avail_segs = max(1U, 4096 / (p->mtu - 40));
-	} else {
-		s->max_avail = 16384;
-		max_avail_segs = max(1U, 9000 / (p->mtu - 40));
-	}
-
-	pr_debug("t1_sched_update_parms: mtu %u speed %u max_avail %u "
-		 "max_avail_segs %u drain_bits_per_1024ns %u\n", p->mtu,
-		 p->speed, s->max_avail, max_avail_segs,
-		 p->drain_bits_per_1024ns);
-
-	return max_avail_segs * (p->mtu - 40);
-}
-
-#if 0
-
-/*
- * t1_sched_max_avail_bytes() tells the scheduler the maximum amount of
- * data that can be pushed per port.
- */
-void t1_sched_set_max_avail_bytes(struct sge *sge, unsigned int val)
-{
-	struct sched *s = sge->tx_sched;
-	unsigned int i;
-
-	s->max_avail = val;
-	for (i = 0; i < MAX_NPORTS; i++)
-		t1_sched_update_parms(sge, i, 0, 0);
-}
-
-/*
- * t1_sched_set_drain_bits_per_us() tells the scheduler at which rate a port
- * is draining.
- */
-void t1_sched_set_drain_bits_per_us(struct sge *sge, unsigned int port,
-					 unsigned int val)
-{
-	struct sched *s = sge->tx_sched;
-	struct sched_port *p = &s->p[port];
-	p->drain_bits_per_1024ns = val * 1024 / 1000;
-	t1_sched_update_parms(sge, port, 0, 0);
-}
-
-#endif  /*  0  */
-
-
-/*
- * get_clock() implements a ns clock (see ktime_get)
- */
-static inline ktime_t get_clock(void)
-{
-	struct timespec ts;
-
-	ktime_get_ts(&ts);
-	return timespec_to_ktime(ts);
-}
-
-/*
- * tx_sched_init() allocates resources and does basic initialization.
- */
-static int tx_sched_init(struct sge *sge)
-{
-	struct sched *s;
-	int i;
-
-	s = kzalloc(sizeof (struct sched), GFP_KERNEL);
-	if (!s)
-		return -ENOMEM;
-
-	pr_debug("tx_sched_init\n");
-	tasklet_init(&s->sched_tsk, restart_sched, (unsigned long) sge);
-	sge->tx_sched = s;
-
-	for (i = 0; i < MAX_NPORTS; i++) {
-		skb_queue_head_init(&s->p[i].skbq);
-		t1_sched_update_parms(sge, i, 1500, 1000);
-	}
-
-	return 0;
-}
-
-/*
- * sched_update_avail() computes the delta since the last time it was called
- * and updates the per port quota (number of bits that can be sent to the any
- * port).
- */
-static inline int sched_update_avail(struct sge *sge)
-{
-	struct sched *s = sge->tx_sched;
-	ktime_t now = get_clock();
-	unsigned int i;
-	long long delta_time_ns;
-
-	delta_time_ns = ktime_to_ns(ktime_sub(now, s->last_updated));
-
-	pr_debug("sched_update_avail delta=%lld\n", delta_time_ns);
-	if (delta_time_ns < 15000)
-		return 0;
-
-	for (i = 0; i < MAX_NPORTS; i++) {
-		struct sched_port *p = &s->p[i];
-		unsigned int delta_avail;
-
-		delta_avail = (p->drain_bits_per_1024ns * delta_time_ns) >> 13;
-		p->avail = min(p->avail + delta_avail, s->max_avail);
-	}
-
-	s->last_updated = now;
-
-	return 1;
-}
-
-/*
- * sched_skb() is called from two different places. In the tx path, any
- * packet generating load on an output port will call sched_skb()
- * (skb != NULL). In addition, sched_skb() is called from the irq/soft irq
- * context (skb == NULL).
- * The scheduler only returns a skb (which will then be sent) if the
- * length of the skb is <= the current quota of the output port.
- */
-static struct sk_buff *sched_skb(struct sge *sge, struct sk_buff *skb,
-				unsigned int credits)
-{
-	struct sched *s = sge->tx_sched;
-	struct sk_buff_head *skbq;
-	unsigned int i, len, update = 1;
-
-	pr_debug("sched_skb %p\n", skb);
-	if (!skb) {
-		if (!s->num)
-			return NULL;
-	} else {
-		skbq = &s->p[skb->dev->if_port].skbq;
-		__skb_queue_tail(skbq, skb);
-		s->num++;
-		skb = NULL;
-	}
-
-	if (credits < MAX_SKB_FRAGS + 1)
-		goto out;
-
-again:
-	for (i = 0; i < MAX_NPORTS; i++) {
-		s->port = (s->port + 1) & (MAX_NPORTS - 1);
-		skbq = &s->p[s->port].skbq;
-
-		skb = skb_peek(skbq);
-
-		if (!skb)
-			continue;
-
-		len = skb->len;
-		if (len <= s->p[s->port].avail) {
-			s->p[s->port].avail -= len;
-			s->num--;
-			__skb_unlink(skb, skbq);
-			goto out;
-		}
-		skb = NULL;
-	}
-
-	if (update-- && sched_update_avail(sge))
-		goto again;
-
-out:
-	/* If there are more pending skbs, we use the hardware to schedule us
-	 * again.
-	 */
-	if (s->num && !skb) {
-		struct cmdQ *q = &sge->cmdQ[0];
-		clear_bit(CMDQ_STAT_LAST_PKT_DB, &q->status);
-		if (test_and_set_bit(CMDQ_STAT_RUNNING, &q->status) == 0) {
-			set_bit(CMDQ_STAT_LAST_PKT_DB, &q->status);
-			writel(F_CMDQ0_ENABLE, sge->adapter->regs + A_SG_DOORBELL);
-		}
-	}
-	pr_debug("sched_skb ret %p\n", skb);
-
-	return skb;
-}
-
-/*
- * PIO to indicate that memory mapped Q contains valid descriptor(s).
- */
-static inline void doorbell_pio(struct adapter *adapter, u32 val)
-{
-	wmb();
-	writel(val, adapter->regs + A_SG_DOORBELL);
-}
-
-/*
- * Frees all RX buffers on the freelist Q. The caller must make sure that
- * the SGE is turned off before calling this function.
- */
-static void free_freelQ_buffers(struct pci_dev *pdev, struct freelQ *q)
-{
-	unsigned int cidx = q->cidx;
-
-	while (q->credits--) {
-		struct freelQ_ce *ce = &q->centries[cidx];
-
-		pci_unmap_single(pdev, dma_unmap_addr(ce, dma_addr),
-				 dma_unmap_len(ce, dma_len),
-				 PCI_DMA_FROMDEVICE);
-		dev_kfree_skb(ce->skb);
-		ce->skb = NULL;
-		if (++cidx == q->size)
-			cidx = 0;
-	}
-}
-
-/*
- * Free RX free list and response queue resources.
- */
-static void free_rx_resources(struct sge *sge)
-{
-	struct pci_dev *pdev = sge->adapter->pdev;
-	unsigned int size, i;
-
-	if (sge->respQ.entries) {
-		size = sizeof(struct respQ_e) * sge->respQ.size;
-		pci_free_consistent(pdev, size, sge->respQ.entries,
-				    sge->respQ.dma_addr);
-	}
-
-	for (i = 0; i < SGE_FREELQ_N; i++) {
-		struct freelQ *q = &sge->freelQ[i];
-
-		if (q->centries) {
-			free_freelQ_buffers(pdev, q);
-			kfree(q->centries);
-		}
-		if (q->entries) {
-			size = sizeof(struct freelQ_e) * q->size;
-			pci_free_consistent(pdev, size, q->entries,
-					    q->dma_addr);
-		}
-	}
-}
-
-/*
- * Allocates basic RX resources, consisting of memory mapped freelist Qs and a
- * response queue.
- */
-static int alloc_rx_resources(struct sge *sge, struct sge_params *p)
-{
-	struct pci_dev *pdev = sge->adapter->pdev;
-	unsigned int size, i;
-
-	for (i = 0; i < SGE_FREELQ_N; i++) {
-		struct freelQ *q = &sge->freelQ[i];
-
-		q->genbit = 1;
-		q->size = p->freelQ_size[i];
-		q->dma_offset = sge->rx_pkt_pad ? 0 : NET_IP_ALIGN;
-		size = sizeof(struct freelQ_e) * q->size;
-		q->entries = pci_alloc_consistent(pdev, size, &q->dma_addr);
-		if (!q->entries)
-			goto err_no_mem;
-
-		size = sizeof(struct freelQ_ce) * q->size;
-		q->centries = kzalloc(size, GFP_KERNEL);
-		if (!q->centries)
-			goto err_no_mem;
-	}
-
-	/*
-	 * Calculate the buffer sizes for the two free lists.  FL0 accommodates
-	 * regular sized Ethernet frames, FL1 is sized not to exceed 16K,
-	 * including all the sk_buff overhead.
-	 *
-	 * Note: For T2 FL0 and FL1 are reversed.
-	 */
-	sge->freelQ[!sge->jumbo_fl].rx_buffer_size = SGE_RX_SM_BUF_SIZE +
-		sizeof(struct cpl_rx_data) +
-		sge->freelQ[!sge->jumbo_fl].dma_offset;
-
-		size = (16 * 1024) -
-		    SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
-
-	sge->freelQ[sge->jumbo_fl].rx_buffer_size = size;
-
-	/*
-	 * Setup which skb recycle Q should be used when recycling buffers from
-	 * each free list.
-	 */
-	sge->freelQ[!sge->jumbo_fl].recycleq_idx = 0;
-	sge->freelQ[sge->jumbo_fl].recycleq_idx = 1;
-
-	sge->respQ.genbit = 1;
-	sge->respQ.size = SGE_RESPQ_E_N;
-	sge->respQ.credits = 0;
-	size = sizeof(struct respQ_e) * sge->respQ.size;
-	sge->respQ.entries =
-		pci_alloc_consistent(pdev, size, &sge->respQ.dma_addr);
-	if (!sge->respQ.entries)
-		goto err_no_mem;
-	return 0;
-
-err_no_mem:
-	free_rx_resources(sge);
-	return -ENOMEM;
-}
-
-/*
- * Reclaims n TX descriptors and frees the buffers associated with them.
- */
-static void free_cmdQ_buffers(struct sge *sge, struct cmdQ *q, unsigned int n)
-{
-	struct cmdQ_ce *ce;
-	struct pci_dev *pdev = sge->adapter->pdev;
-	unsigned int cidx = q->cidx;
-
-	q->in_use -= n;
-	ce = &q->centries[cidx];
-	while (n--) {
-		if (likely(dma_unmap_len(ce, dma_len))) {
-			pci_unmap_single(pdev, dma_unmap_addr(ce, dma_addr),
-					 dma_unmap_len(ce, dma_len),
-					 PCI_DMA_TODEVICE);
-			if (q->sop)
-				q->sop = 0;
-		}
-		if (ce->skb) {
-			dev_kfree_skb_any(ce->skb);
-			q->sop = 1;
-		}
-		ce++;
-		if (++cidx == q->size) {
-			cidx = 0;
-			ce = q->centries;
-		}
-	}
-	q->cidx = cidx;
-}
-
-/*
- * Free TX resources.
- *
- * Assumes that SGE is stopped and all interrupts are disabled.
- */
-static void free_tx_resources(struct sge *sge)
-{
-	struct pci_dev *pdev = sge->adapter->pdev;
-	unsigned int size, i;
-
-	for (i = 0; i < SGE_CMDQ_N; i++) {
-		struct cmdQ *q = &sge->cmdQ[i];
-
-		if (q->centries) {
-			if (q->in_use)
-				free_cmdQ_buffers(sge, q, q->in_use);
-			kfree(q->centries);
-		}
-		if (q->entries) {
-			size = sizeof(struct cmdQ_e) * q->size;
-			pci_free_consistent(pdev, size, q->entries,
-					    q->dma_addr);
-		}
-	}
-}
-
-/*
- * Allocates basic TX resources, consisting of memory mapped command Qs.
- */
-static int alloc_tx_resources(struct sge *sge, struct sge_params *p)
-{
-	struct pci_dev *pdev = sge->adapter->pdev;
-	unsigned int size, i;
-
-	for (i = 0; i < SGE_CMDQ_N; i++) {
-		struct cmdQ *q = &sge->cmdQ[i];
-
-		q->genbit = 1;
-		q->sop = 1;
-		q->size = p->cmdQ_size[i];
-		q->in_use = 0;
-		q->status = 0;
-		q->processed = q->cleaned = 0;
-		q->stop_thres = 0;
-		spin_lock_init(&q->lock);
-		size = sizeof(struct cmdQ_e) * q->size;
-		q->entries = pci_alloc_consistent(pdev, size, &q->dma_addr);
-		if (!q->entries)
-			goto err_no_mem;
-
-		size = sizeof(struct cmdQ_ce) * q->size;
-		q->centries = kzalloc(size, GFP_KERNEL);
-		if (!q->centries)
-			goto err_no_mem;
-	}
-
-	/*
-	 * CommandQ 0 handles Ethernet and TOE packets, while queue 1 is TOE
-	 * only.  For queue 0 set the stop threshold so we can handle one more
-	 * packet from each port, plus reserve an additional 24 entries for
-	 * Ethernet packets only.  Queue 1 never suspends nor do we reserve
-	 * space for Ethernet packets.
-	 */
-	sge->cmdQ[0].stop_thres = sge->adapter->params.nports *
-		(MAX_SKB_FRAGS + 1);
-	return 0;
-
-err_no_mem:
-	free_tx_resources(sge);
-	return -ENOMEM;
-}
-
-static inline void setup_ring_params(struct adapter *adapter, u64 addr,
-				     u32 size, int base_reg_lo,
-				     int base_reg_hi, int size_reg)
-{
-	writel((u32)addr, adapter->regs + base_reg_lo);
-	writel(addr >> 32, adapter->regs + base_reg_hi);
-	writel(size, adapter->regs + size_reg);
-}
-
-/*
- * Enable/disable VLAN acceleration.
- */
-void t1_vlan_mode(struct adapter *adapter, u32 features)
-{
-	struct sge *sge = adapter->sge;
-
-	if (features & NETIF_F_HW_VLAN_RX)
-		sge->sge_control |= F_VLAN_XTRACT;
-	else
-		sge->sge_control &= ~F_VLAN_XTRACT;
-	if (adapter->open_device_map) {
-		writel(sge->sge_control, adapter->regs + A_SG_CONTROL);
-		readl(adapter->regs + A_SG_CONTROL);   /* flush */
-	}
-}
-
-/*
- * Programs the various SGE registers. However, the engine is not yet enabled,
- * but sge->sge_control is setup and ready to go.
- */
-static void configure_sge(struct sge *sge, struct sge_params *p)
-{
-	struct adapter *ap = sge->adapter;
-
-	writel(0, ap->regs + A_SG_CONTROL);
-	setup_ring_params(ap, sge->cmdQ[0].dma_addr, sge->cmdQ[0].size,
-			  A_SG_CMD0BASELWR, A_SG_CMD0BASEUPR, A_SG_CMD0SIZE);
-	setup_ring_params(ap, sge->cmdQ[1].dma_addr, sge->cmdQ[1].size,
-			  A_SG_CMD1BASELWR, A_SG_CMD1BASEUPR, A_SG_CMD1SIZE);
-	setup_ring_params(ap, sge->freelQ[0].dma_addr,
-			  sge->freelQ[0].size, A_SG_FL0BASELWR,
-			  A_SG_FL0BASEUPR, A_SG_FL0SIZE);
-	setup_ring_params(ap, sge->freelQ[1].dma_addr,
-			  sge->freelQ[1].size, A_SG_FL1BASELWR,
-			  A_SG_FL1BASEUPR, A_SG_FL1SIZE);
-
-	/* The threshold comparison uses <. */
-	writel(SGE_RX_SM_BUF_SIZE + 1, ap->regs + A_SG_FLTHRESHOLD);
-
-	setup_ring_params(ap, sge->respQ.dma_addr, sge->respQ.size,
-			  A_SG_RSPBASELWR, A_SG_RSPBASEUPR, A_SG_RSPSIZE);
-	writel((u32)sge->respQ.size - 1, ap->regs + A_SG_RSPQUEUECREDIT);
-
-	sge->sge_control = F_CMDQ0_ENABLE | F_CMDQ1_ENABLE | F_FL0_ENABLE |
-		F_FL1_ENABLE | F_CPL_ENABLE | F_RESPONSE_QUEUE_ENABLE |
-		V_CMDQ_PRIORITY(2) | F_DISABLE_CMDQ1_GTS | F_ISCSI_COALESCE |
-		V_RX_PKT_OFFSET(sge->rx_pkt_pad);
-
-#if defined(__BIG_ENDIAN_BITFIELD)
-	sge->sge_control |= F_ENABLE_BIG_ENDIAN;
-#endif
-
-	/* Initialize no-resource timer */
-	sge->intrtimer_nres = SGE_INTRTIMER_NRES * core_ticks_per_usec(ap);
-
-	t1_sge_set_coalesce_params(sge, p);
-}
-
-/*
- * Return the payload capacity of the jumbo free-list buffers.
- */
-static inline unsigned int jumbo_payload_capacity(const struct sge *sge)
-{
-	return sge->freelQ[sge->jumbo_fl].rx_buffer_size -
-		sge->freelQ[sge->jumbo_fl].dma_offset -
-		sizeof(struct cpl_rx_data);
-}
-
-/*
- * Frees all SGE related resources and the sge structure itself
- */
-void t1_sge_destroy(struct sge *sge)
-{
-	int i;
-
-	for_each_port(sge->adapter, i)
-		free_percpu(sge->port_stats[i]);
-
-	kfree(sge->tx_sched);
-	free_tx_resources(sge);
-	free_rx_resources(sge);
-	kfree(sge);
-}
-
-/*
- * Allocates new RX buffers on the freelist Q (and tracks them on the freelist
- * context Q) until the Q is full or alloc_skb fails.
- *
- * It is possible that the generation bits already match, indicating that the
- * buffer is already valid and nothing needs to be done. This happens when we
- * copied a received buffer into a new sk_buff during the interrupt processing.
- *
- * If the SGE doesn't automatically align packets properly (!sge->rx_pkt_pad),
- * we specify a RX_OFFSET in order to make sure that the IP header is 4B
- * aligned.
- */
-static void refill_free_list(struct sge *sge, struct freelQ *q)
-{
-	struct pci_dev *pdev = sge->adapter->pdev;
-	struct freelQ_ce *ce = &q->centries[q->pidx];
-	struct freelQ_e *e = &q->entries[q->pidx];
-	unsigned int dma_len = q->rx_buffer_size - q->dma_offset;
-
-	while (q->credits < q->size) {
-		struct sk_buff *skb;
-		dma_addr_t mapping;
-
-		skb = alloc_skb(q->rx_buffer_size, GFP_ATOMIC);
-		if (!skb)
-			break;
-
-		skb_reserve(skb, q->dma_offset);
-		mapping = pci_map_single(pdev, skb->data, dma_len,
-					 PCI_DMA_FROMDEVICE);
-		skb_reserve(skb, sge->rx_pkt_pad);
-
-		ce->skb = skb;
-		dma_unmap_addr_set(ce, dma_addr, mapping);
-		dma_unmap_len_set(ce, dma_len, dma_len);
-		e->addr_lo = (u32)mapping;
-		e->addr_hi = (u64)mapping >> 32;
-		e->len_gen = V_CMD_LEN(dma_len) | V_CMD_GEN1(q->genbit);
-		wmb();
-		e->gen2 = V_CMD_GEN2(q->genbit);
-
-		e++;
-		ce++;
-		if (++q->pidx == q->size) {
-			q->pidx = 0;
-			q->genbit ^= 1;
-			ce = q->centries;
-			e = q->entries;
-		}
-		q->credits++;
-	}
-}
-
-/*
- * Calls refill_free_list for both free lists. If we cannot fill at least 1/4
- * of both rings, we go into 'few interrupt mode' in order to give the system
- * time to free up resources.
- */
-static void freelQs_empty(struct sge *sge)
-{
-	struct adapter *adapter = sge->adapter;
-	u32 irq_reg = readl(adapter->regs + A_SG_INT_ENABLE);
-	u32 irqholdoff_reg;
-
-	refill_free_list(sge, &sge->freelQ[0]);
-	refill_free_list(sge, &sge->freelQ[1]);
-
-	if (sge->freelQ[0].credits > (sge->freelQ[0].size >> 2) &&
-	    sge->freelQ[1].credits > (sge->freelQ[1].size >> 2)) {
-		irq_reg |= F_FL_EXHAUSTED;
-		irqholdoff_reg = sge->fixed_intrtimer;
-	} else {
-		/* Clear the F_FL_EXHAUSTED interrupts for now */
-		irq_reg &= ~F_FL_EXHAUSTED;
-		irqholdoff_reg = sge->intrtimer_nres;
-	}
-	writel(irqholdoff_reg, adapter->regs + A_SG_INTRTIMER);
-	writel(irq_reg, adapter->regs + A_SG_INT_ENABLE);
-
-	/* We reenable the Qs to force a freelist GTS interrupt later */
-	doorbell_pio(adapter, F_FL0_ENABLE | F_FL1_ENABLE);
-}
-
-#define SGE_PL_INTR_MASK (F_PL_INTR_SGE_ERR | F_PL_INTR_SGE_DATA)
-#define SGE_INT_FATAL (F_RESPQ_OVERFLOW | F_PACKET_TOO_BIG | F_PACKET_MISMATCH)
-#define SGE_INT_ENABLE (F_RESPQ_EXHAUSTED | F_RESPQ_OVERFLOW | \
-			F_FL_EXHAUSTED | F_PACKET_TOO_BIG | F_PACKET_MISMATCH)
-
-/*
- * Disable SGE Interrupts
- */
-void t1_sge_intr_disable(struct sge *sge)
-{
-	u32 val = readl(sge->adapter->regs + A_PL_ENABLE);
-
-	writel(val & ~SGE_PL_INTR_MASK, sge->adapter->regs + A_PL_ENABLE);
-	writel(0, sge->adapter->regs + A_SG_INT_ENABLE);
-}
-
-/*
- * Enable SGE interrupts.
- */
-void t1_sge_intr_enable(struct sge *sge)
-{
-	u32 en = SGE_INT_ENABLE;
-	u32 val = readl(sge->adapter->regs + A_PL_ENABLE);
-
-	if (sge->adapter->port[0].dev->hw_features & NETIF_F_TSO)
-		en &= ~F_PACKET_TOO_BIG;
-	writel(en, sge->adapter->regs + A_SG_INT_ENABLE);
-	writel(val | SGE_PL_INTR_MASK, sge->adapter->regs + A_PL_ENABLE);
-}
-
-/*
- * Clear SGE interrupts.
- */
-void t1_sge_intr_clear(struct sge *sge)
-{
-	writel(SGE_PL_INTR_MASK, sge->adapter->regs + A_PL_CAUSE);
-	writel(0xffffffff, sge->adapter->regs + A_SG_INT_CAUSE);
-}
-
-/*
- * SGE 'Error' interrupt handler
- */
-int t1_sge_intr_error_handler(struct sge *sge)
-{
-	struct adapter *adapter = sge->adapter;
-	u32 cause = readl(adapter->regs + A_SG_INT_CAUSE);
-
-	if (adapter->port[0].dev->hw_features & NETIF_F_TSO)
-		cause &= ~F_PACKET_TOO_BIG;
-	if (cause & F_RESPQ_EXHAUSTED)
-		sge->stats.respQ_empty++;
-	if (cause & F_RESPQ_OVERFLOW) {
-		sge->stats.respQ_overflow++;
-		pr_alert("%s: SGE response queue overflow\n",
-			 adapter->name);
-	}
-	if (cause & F_FL_EXHAUSTED) {
-		sge->stats.freelistQ_empty++;
-		freelQs_empty(sge);
-	}
-	if (cause & F_PACKET_TOO_BIG) {
-		sge->stats.pkt_too_big++;
-		pr_alert("%s: SGE max packet size exceeded\n",
-			 adapter->name);
-	}
-	if (cause & F_PACKET_MISMATCH) {
-		sge->stats.pkt_mismatch++;
-		pr_alert("%s: SGE packet mismatch\n", adapter->name);
-	}
-	if (cause & SGE_INT_FATAL)
-		t1_fatal_err(adapter);
-
-	writel(cause, adapter->regs + A_SG_INT_CAUSE);
-	return 0;
-}
-
-const struct sge_intr_counts *t1_sge_get_intr_counts(const struct sge *sge)
-{
-	return &sge->stats;
-}
-
-void t1_sge_get_port_stats(const struct sge *sge, int port,
-			   struct sge_port_stats *ss)
-{
-	int cpu;
-
-	memset(ss, 0, sizeof(*ss));
-	for_each_possible_cpu(cpu) {
-		struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[port], cpu);
-
-		ss->rx_cso_good += st->rx_cso_good;
-		ss->tx_cso += st->tx_cso;
-		ss->tx_tso += st->tx_tso;
-		ss->tx_need_hdrroom += st->tx_need_hdrroom;
-		ss->vlan_xtract += st->vlan_xtract;
-		ss->vlan_insert += st->vlan_insert;
-	}
-}
-
-/**
- *	recycle_fl_buf - recycle a free list buffer
- *	@fl: the free list
- *	@idx: index of buffer to recycle
- *
- *	Recycles the specified buffer on the given free list by adding it at
- *	the next available slot on the list.
- */
-static void recycle_fl_buf(struct freelQ *fl, int idx)
-{
-	struct freelQ_e *from = &fl->entries[idx];
-	struct freelQ_e *to = &fl->entries[fl->pidx];
-
-	fl->centries[fl->pidx] = fl->centries[idx];
-	to->addr_lo = from->addr_lo;
-	to->addr_hi = from->addr_hi;
-	to->len_gen = G_CMD_LEN(from->len_gen) | V_CMD_GEN1(fl->genbit);
-	wmb();
-	to->gen2 = V_CMD_GEN2(fl->genbit);
-	fl->credits++;
-
-	if (++fl->pidx == fl->size) {
-		fl->pidx = 0;
-		fl->genbit ^= 1;
-	}
-}
-
-static int copybreak __read_mostly = 256;
-module_param(copybreak, int, 0);
-MODULE_PARM_DESC(copybreak, "Receive copy threshold");
-
-/**
- *	get_packet - return the next ingress packet buffer
- *	@pdev: the PCI device that received the packet
- *	@fl: the SGE free list holding the packet
- *	@len: the actual packet length, excluding any SGE padding
- *
- *	Get the next packet from a free list and complete setup of the
- *	sk_buff.  If the packet is small we make a copy and recycle the
- *	original buffer, otherwise we use the original buffer itself.  If a
- *	positive drop threshold is supplied packets are dropped and their
- *	buffers recycled if (a) the number of remaining buffers is under the
- *	threshold and the packet is too big to copy, or (b) the packet should
- *	be copied but there is no memory for the copy.
- */
-static inline struct sk_buff *get_packet(struct pci_dev *pdev,
-					 struct freelQ *fl, unsigned int len)
-{
-	struct sk_buff *skb;
-	const struct freelQ_ce *ce = &fl->centries[fl->cidx];
-
-	if (len < copybreak) {
-		skb = alloc_skb(len + 2, GFP_ATOMIC);
-		if (!skb)
-			goto use_orig_buf;
-
-		skb_reserve(skb, 2);	/* align IP header */
-		skb_put(skb, len);
-		pci_dma_sync_single_for_cpu(pdev,
-					    dma_unmap_addr(ce, dma_addr),
-					    dma_unmap_len(ce, dma_len),
-					    PCI_DMA_FROMDEVICE);
-		skb_copy_from_linear_data(ce->skb, skb->data, len);
-		pci_dma_sync_single_for_device(pdev,
-					       dma_unmap_addr(ce, dma_addr),
-					       dma_unmap_len(ce, dma_len),
-					       PCI_DMA_FROMDEVICE);
-		recycle_fl_buf(fl, fl->cidx);
-		return skb;
-	}
-
-use_orig_buf:
-	if (fl->credits < 2) {
-		recycle_fl_buf(fl, fl->cidx);
-		return NULL;
-	}
-
-	pci_unmap_single(pdev, dma_unmap_addr(ce, dma_addr),
-			 dma_unmap_len(ce, dma_len), PCI_DMA_FROMDEVICE);
-	skb = ce->skb;
-	prefetch(skb->data);
-
-	skb_put(skb, len);
-	return skb;
-}
-
-/**
- *	unexpected_offload - handle an unexpected offload packet
- *	@adapter: the adapter
- *	@fl: the free list that received the packet
- *
- *	Called when we receive an unexpected offload packet (e.g., the TOE
- *	function is disabled or the card is a NIC).  Prints a message and
- *	recycles the buffer.
- */
-static void unexpected_offload(struct adapter *adapter, struct freelQ *fl)
-{
-	struct freelQ_ce *ce = &fl->centries[fl->cidx];
-	struct sk_buff *skb = ce->skb;
-
-	pci_dma_sync_single_for_cpu(adapter->pdev, dma_unmap_addr(ce, dma_addr),
-			    dma_unmap_len(ce, dma_len), PCI_DMA_FROMDEVICE);
-	pr_err("%s: unexpected offload packet, cmd %u\n",
-	       adapter->name, *skb->data);
-	recycle_fl_buf(fl, fl->cidx);
-}
-
-/*
- * T1/T2 SGE limits the maximum DMA size per TX descriptor to
- * SGE_TX_DESC_MAX_PLEN (16KB). If the PAGE_SIZE is larger than 16KB, the
- * stack might send more than SGE_TX_DESC_MAX_PLEN in a contiguous manner.
- * Note that the *_large_page_tx_descs stuff will be optimized out when
- * PAGE_SIZE <= SGE_TX_DESC_MAX_PLEN.
- *
- * compute_large_page_descs() computes how many additional descriptors are
- * required to break down the stack's request.
- */
-static inline unsigned int compute_large_page_tx_descs(struct sk_buff *skb)
-{
-	unsigned int count = 0;
-
-	if (PAGE_SIZE > SGE_TX_DESC_MAX_PLEN) {
-		unsigned int nfrags = skb_shinfo(skb)->nr_frags;
-		unsigned int i, len = skb_headlen(skb);
-		while (len > SGE_TX_DESC_MAX_PLEN) {
-			count++;
-			len -= SGE_TX_DESC_MAX_PLEN;
-		}
-		for (i = 0; nfrags--; i++) {
-			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-			len = frag->size;
-			while (len > SGE_TX_DESC_MAX_PLEN) {
-				count++;
-				len -= SGE_TX_DESC_MAX_PLEN;
-			}
-		}
-	}
-	return count;
-}
-
-/*
- * Write a cmdQ entry.
- *
- * Since this function writes the 'flags' field, it must not be used to
- * write the first cmdQ entry.
- */
-static inline void write_tx_desc(struct cmdQ_e *e, dma_addr_t mapping,
-				 unsigned int len, unsigned int gen,
-				 unsigned int eop)
-{
-	BUG_ON(len > SGE_TX_DESC_MAX_PLEN);
-
-	e->addr_lo = (u32)mapping;
-	e->addr_hi = (u64)mapping >> 32;
-	e->len_gen = V_CMD_LEN(len) | V_CMD_GEN1(gen);
-	e->flags = F_CMD_DATAVALID | V_CMD_EOP(eop) | V_CMD_GEN2(gen);
-}
-
-/*
- * See comment for previous function.
- *
- * write_tx_descs_large_page() writes additional SGE tx descriptors if
- * *desc_len exceeds HW's capability.
- */
-static inline unsigned int write_large_page_tx_descs(unsigned int pidx,
-						     struct cmdQ_e **e,
-						     struct cmdQ_ce **ce,
-						     unsigned int *gen,
-						     dma_addr_t *desc_mapping,
-						     unsigned int *desc_len,
-						     unsigned int nfrags,
-						     struct cmdQ *q)
-{
-	if (PAGE_SIZE > SGE_TX_DESC_MAX_PLEN) {
-		struct cmdQ_e *e1 = *e;
-		struct cmdQ_ce *ce1 = *ce;
-
-		while (*desc_len > SGE_TX_DESC_MAX_PLEN) {
-			*desc_len -= SGE_TX_DESC_MAX_PLEN;
-			write_tx_desc(e1, *desc_mapping, SGE_TX_DESC_MAX_PLEN,
-				      *gen, nfrags == 0 && *desc_len == 0);
-			ce1->skb = NULL;
-			dma_unmap_len_set(ce1, dma_len, 0);
-			*desc_mapping += SGE_TX_DESC_MAX_PLEN;
-			if (*desc_len) {
-				ce1++;
-				e1++;
-				if (++pidx == q->size) {
-					pidx = 0;
-					*gen ^= 1;
-					ce1 = q->centries;
-					e1 = q->entries;
-				}
-			}
-		}
-		*e = e1;
-		*ce = ce1;
-	}
-	return pidx;
-}
-
-/*
- * Write the command descriptors to transmit the given skb starting at
- * descriptor pidx with the given generation.
- */
-static inline void write_tx_descs(struct adapter *adapter, struct sk_buff *skb,
-				  unsigned int pidx, unsigned int gen,
-				  struct cmdQ *q)
-{
-	dma_addr_t mapping, desc_mapping;
-	struct cmdQ_e *e, *e1;
-	struct cmdQ_ce *ce;
-	unsigned int i, flags, first_desc_len, desc_len,
-	    nfrags = skb_shinfo(skb)->nr_frags;
-
-	e = e1 = &q->entries[pidx];
-	ce = &q->centries[pidx];
-
-	mapping = pci_map_single(adapter->pdev, skb->data,
-				 skb_headlen(skb), PCI_DMA_TODEVICE);
-
-	desc_mapping = mapping;
-	desc_len = skb_headlen(skb);
-
-	flags = F_CMD_DATAVALID | F_CMD_SOP |
-	    V_CMD_EOP(nfrags == 0 && desc_len <= SGE_TX_DESC_MAX_PLEN) |
-	    V_CMD_GEN2(gen);
-	first_desc_len = (desc_len <= SGE_TX_DESC_MAX_PLEN) ?
-	    desc_len : SGE_TX_DESC_MAX_PLEN;
-	e->addr_lo = (u32)desc_mapping;
-	e->addr_hi = (u64)desc_mapping >> 32;
-	e->len_gen = V_CMD_LEN(first_desc_len) | V_CMD_GEN1(gen);
-	ce->skb = NULL;
-	dma_unmap_len_set(ce, dma_len, 0);
-
-	if (PAGE_SIZE > SGE_TX_DESC_MAX_PLEN &&
-	    desc_len > SGE_TX_DESC_MAX_PLEN) {
-		desc_mapping += first_desc_len;
-		desc_len -= first_desc_len;
-		e1++;
-		ce++;
-		if (++pidx == q->size) {
-			pidx = 0;
-			gen ^= 1;
-			e1 = q->entries;
-			ce = q->centries;
-		}
-		pidx = write_large_page_tx_descs(pidx, &e1, &ce, &gen,
-						 &desc_mapping, &desc_len,
-						 nfrags, q);
-
-		if (likely(desc_len))
-			write_tx_desc(e1, desc_mapping, desc_len, gen,
-				      nfrags == 0);
-	}
-
-	ce->skb = NULL;
-	dma_unmap_addr_set(ce, dma_addr, mapping);
-	dma_unmap_len_set(ce, dma_len, skb_headlen(skb));
-
-	for (i = 0; nfrags--; i++) {
-		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-		e1++;
-		ce++;
-		if (++pidx == q->size) {
-			pidx = 0;
-			gen ^= 1;
-			e1 = q->entries;
-			ce = q->centries;
-		}
-
-		mapping = pci_map_page(adapter->pdev, frag->page,
-				       frag->page_offset, frag->size,
-				       PCI_DMA_TODEVICE);
-		desc_mapping = mapping;
-		desc_len = frag->size;
-
-		pidx = write_large_page_tx_descs(pidx, &e1, &ce, &gen,
-						 &desc_mapping, &desc_len,
-						 nfrags, q);
-		if (likely(desc_len))
-			write_tx_desc(e1, desc_mapping, desc_len, gen,
-				      nfrags == 0);
-		ce->skb = NULL;
-		dma_unmap_addr_set(ce, dma_addr, mapping);
-		dma_unmap_len_set(ce, dma_len, frag->size);
-	}
-	ce->skb = skb;
-	wmb();
-	e->flags = flags;
-}
-
-/*
- * Clean up completed Tx buffers.
- */
-static inline void reclaim_completed_tx(struct sge *sge, struct cmdQ *q)
-{
-	unsigned int reclaim = q->processed - q->cleaned;
-
-	if (reclaim) {
-		pr_debug("reclaim_completed_tx processed:%d cleaned:%d\n",
-			 q->processed, q->cleaned);
-		free_cmdQ_buffers(sge, q, reclaim);
-		q->cleaned += reclaim;
-	}
-}
-
-/*
- * Called from tasklet. Checks the scheduler for any
- * pending skbs that can be sent.
- */
-static void restart_sched(unsigned long arg)
-{
-	struct sge *sge = (struct sge *) arg;
-	struct adapter *adapter = sge->adapter;
-	struct cmdQ *q = &sge->cmdQ[0];
-	struct sk_buff *skb;
-	unsigned int credits, queued_skb = 0;
-
-	spin_lock(&q->lock);
-	reclaim_completed_tx(sge, q);
-
-	credits = q->size - q->in_use;
-	pr_debug("restart_sched credits=%d\n", credits);
-	while ((skb = sched_skb(sge, NULL, credits)) != NULL) {
-		unsigned int genbit, pidx, count;
-	        count = 1 + skb_shinfo(skb)->nr_frags;
-		count += compute_large_page_tx_descs(skb);
-		q->in_use += count;
-		genbit = q->genbit;
-		pidx = q->pidx;
-		q->pidx += count;
-		if (q->pidx >= q->size) {
-			q->pidx -= q->size;
-			q->genbit ^= 1;
-		}
-		write_tx_descs(adapter, skb, pidx, genbit, q);
-	        credits = q->size - q->in_use;
-		queued_skb = 1;
-	}
-
-	if (queued_skb) {
-		clear_bit(CMDQ_STAT_LAST_PKT_DB, &q->status);
-		if (test_and_set_bit(CMDQ_STAT_RUNNING, &q->status) == 0) {
-			set_bit(CMDQ_STAT_LAST_PKT_DB, &q->status);
-			writel(F_CMDQ0_ENABLE, adapter->regs + A_SG_DOORBELL);
-		}
-	}
-	spin_unlock(&q->lock);
-}
-
-/**
- *	sge_rx - process an ingress ethernet packet
- *	@sge: the sge structure
- *	@fl: the free list that contains the packet buffer
- *	@len: the packet length
- *
- *	Process an ingress ethernet pakcet and deliver it to the stack.
- */
-static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len)
-{
-	struct sk_buff *skb;
-	const struct cpl_rx_pkt *p;
-	struct adapter *adapter = sge->adapter;
-	struct sge_port_stats *st;
-	struct net_device *dev;
-
-	skb = get_packet(adapter->pdev, fl, len - sge->rx_pkt_pad);
-	if (unlikely(!skb)) {
-		sge->stats.rx_drops++;
-		return;
-	}
-
-	p = (const struct cpl_rx_pkt *) skb->data;
-	if (p->iff >= adapter->params.nports) {
-		kfree_skb(skb);
-		return;
-	}
-	__skb_pull(skb, sizeof(*p));
-
-	st = this_cpu_ptr(sge->port_stats[p->iff]);
-	dev = adapter->port[p->iff].dev;
-
-	skb->protocol = eth_type_trans(skb, dev);
-	if ((dev->features & NETIF_F_RXCSUM) && p->csum == 0xffff &&
-	    skb->protocol == htons(ETH_P_IP) &&
-	    (skb->data[9] == IPPROTO_TCP || skb->data[9] == IPPROTO_UDP)) {
-		++st->rx_cso_good;
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	} else
-		skb_checksum_none_assert(skb);
-
-	if (p->vlan_valid) {
-		st->vlan_xtract++;
-		__vlan_hwaccel_put_tag(skb, ntohs(p->vlan));
-	}
-	netif_receive_skb(skb);
-}
-
-/*
- * Returns true if a command queue has enough available descriptors that
- * we can resume Tx operation after temporarily disabling its packet queue.
- */
-static inline int enough_free_Tx_descs(const struct cmdQ *q)
-{
-	unsigned int r = q->processed - q->cleaned;
-
-	return q->in_use - r < (q->size >> 1);
-}
-
-/*
- * Called when sufficient space has become available in the SGE command queues
- * after the Tx packet schedulers have been suspended to restart the Tx path.
- */
-static void restart_tx_queues(struct sge *sge)
-{
-	struct adapter *adap = sge->adapter;
-	int i;
-
-	if (!enough_free_Tx_descs(&sge->cmdQ[0]))
-		return;
-
-	for_each_port(adap, i) {
-		struct net_device *nd = adap->port[i].dev;
-
-		if (test_and_clear_bit(nd->if_port, &sge->stopped_tx_queues) &&
-		    netif_running(nd)) {
-			sge->stats.cmdQ_restarted[2]++;
-			netif_wake_queue(nd);
-		}
-	}
-}
-
-/*
- * update_tx_info is called from the interrupt handler/NAPI to return cmdQ0
- * information.
- */
-static unsigned int update_tx_info(struct adapter *adapter,
-					  unsigned int flags,
-					  unsigned int pr0)
-{
-	struct sge *sge = adapter->sge;
-	struct cmdQ *cmdq = &sge->cmdQ[0];
-
-	cmdq->processed += pr0;
-	if (flags & (F_FL0_ENABLE | F_FL1_ENABLE)) {
-		freelQs_empty(sge);
-		flags &= ~(F_FL0_ENABLE | F_FL1_ENABLE);
-	}
-	if (flags & F_CMDQ0_ENABLE) {
-		clear_bit(CMDQ_STAT_RUNNING, &cmdq->status);
-
-		if (cmdq->cleaned + cmdq->in_use != cmdq->processed &&
-		    !test_and_set_bit(CMDQ_STAT_LAST_PKT_DB, &cmdq->status)) {
-			set_bit(CMDQ_STAT_RUNNING, &cmdq->status);
-			writel(F_CMDQ0_ENABLE, adapter->regs + A_SG_DOORBELL);
-		}
-		if (sge->tx_sched)
-			tasklet_hi_schedule(&sge->tx_sched->sched_tsk);
-
-		flags &= ~F_CMDQ0_ENABLE;
-	}
-
-	if (unlikely(sge->stopped_tx_queues != 0))
-		restart_tx_queues(sge);
-
-	return flags;
-}
-
-/*
- * Process SGE responses, up to the supplied budget.  Returns the number of
- * responses processed.  A negative budget is effectively unlimited.
- */
-static int process_responses(struct adapter *adapter, int budget)
-{
-	struct sge *sge = adapter->sge;
-	struct respQ *q = &sge->respQ;
-	struct respQ_e *e = &q->entries[q->cidx];
-	int done = 0;
-	unsigned int flags = 0;
-	unsigned int cmdq_processed[SGE_CMDQ_N] = {0, 0};
-
-	while (done < budget && e->GenerationBit == q->genbit) {
-		flags |= e->Qsleeping;
-
-		cmdq_processed[0] += e->Cmdq0CreditReturn;
-		cmdq_processed[1] += e->Cmdq1CreditReturn;
-
-		/* We batch updates to the TX side to avoid cacheline
-		 * ping-pong of TX state information on MP where the sender
-		 * might run on a different CPU than this function...
-		 */
-		if (unlikely((flags & F_CMDQ0_ENABLE) || cmdq_processed[0] > 64)) {
-			flags = update_tx_info(adapter, flags, cmdq_processed[0]);
-			cmdq_processed[0] = 0;
-		}
-
-		if (unlikely(cmdq_processed[1] > 16)) {
-			sge->cmdQ[1].processed += cmdq_processed[1];
-			cmdq_processed[1] = 0;
-		}
-
-		if (likely(e->DataValid)) {
-			struct freelQ *fl = &sge->freelQ[e->FreelistQid];
-
-			BUG_ON(!e->Sop || !e->Eop);
-			if (unlikely(e->Offload))
-				unexpected_offload(adapter, fl);
-			else
-				sge_rx(sge, fl, e->BufferLength);
-
-			++done;
-
-			/*
-			 * Note: this depends on each packet consuming a
-			 * single free-list buffer; cf. the BUG above.
-			 */
-			if (++fl->cidx == fl->size)
-				fl->cidx = 0;
-			prefetch(fl->centries[fl->cidx].skb);
-
-			if (unlikely(--fl->credits <
-				     fl->size - SGE_FREEL_REFILL_THRESH))
-				refill_free_list(sge, fl);
-		} else
-			sge->stats.pure_rsps++;
-
-		e++;
-		if (unlikely(++q->cidx == q->size)) {
-			q->cidx = 0;
-			q->genbit ^= 1;
-			e = q->entries;
-		}
-		prefetch(e);
-
-		if (++q->credits > SGE_RESPQ_REPLENISH_THRES) {
-			writel(q->credits, adapter->regs + A_SG_RSPQUEUECREDIT);
-			q->credits = 0;
-		}
-	}
-
-	flags = update_tx_info(adapter, flags, cmdq_processed[0]);
-	sge->cmdQ[1].processed += cmdq_processed[1];
-
-	return done;
-}
-
-static inline int responses_pending(const struct adapter *adapter)
-{
-	const struct respQ *Q = &adapter->sge->respQ;
-	const struct respQ_e *e = &Q->entries[Q->cidx];
-
-	return e->GenerationBit == Q->genbit;
-}
-
-/*
- * A simpler version of process_responses() that handles only pure (i.e.,
- * non data-carrying) responses.  Such respones are too light-weight to justify
- * calling a softirq when using NAPI, so we handle them specially in hard
- * interrupt context.  The function is called with a pointer to a response,
- * which the caller must ensure is a valid pure response.  Returns 1 if it
- * encounters a valid data-carrying response, 0 otherwise.
- */
-static int process_pure_responses(struct adapter *adapter)
-{
-	struct sge *sge = adapter->sge;
-	struct respQ *q = &sge->respQ;
-	struct respQ_e *e = &q->entries[q->cidx];
-	const struct freelQ *fl = &sge->freelQ[e->FreelistQid];
-	unsigned int flags = 0;
-	unsigned int cmdq_processed[SGE_CMDQ_N] = {0, 0};
-
-	prefetch(fl->centries[fl->cidx].skb);
-	if (e->DataValid)
-		return 1;
-
-	do {
-		flags |= e->Qsleeping;
-
-		cmdq_processed[0] += e->Cmdq0CreditReturn;
-		cmdq_processed[1] += e->Cmdq1CreditReturn;
-
-		e++;
-		if (unlikely(++q->cidx == q->size)) {
-			q->cidx = 0;
-			q->genbit ^= 1;
-			e = q->entries;
-		}
-		prefetch(e);
-
-		if (++q->credits > SGE_RESPQ_REPLENISH_THRES) {
-			writel(q->credits, adapter->regs + A_SG_RSPQUEUECREDIT);
-			q->credits = 0;
-		}
-		sge->stats.pure_rsps++;
-	} while (e->GenerationBit == q->genbit && !e->DataValid);
-
-	flags = update_tx_info(adapter, flags, cmdq_processed[0]);
-	sge->cmdQ[1].processed += cmdq_processed[1];
-
-	return e->GenerationBit == q->genbit;
-}
-
-/*
- * Handler for new data events when using NAPI.  This does not need any locking
- * or protection from interrupts as data interrupts are off at this point and
- * other adapter interrupts do not interfere.
- */
-int t1_poll(struct napi_struct *napi, int budget)
-{
-	struct adapter *adapter = container_of(napi, struct adapter, napi);
-	int work_done = process_responses(adapter, budget);
-
-	if (likely(work_done < budget)) {
-		napi_complete(napi);
-		writel(adapter->sge->respQ.cidx,
-		       adapter->regs + A_SG_SLEEPING);
-	}
-	return work_done;
-}
-
-irqreturn_t t1_interrupt(int irq, void *data)
-{
-	struct adapter *adapter = data;
-	struct sge *sge = adapter->sge;
-	int handled;
-
-	if (likely(responses_pending(adapter))) {
-		writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
-
-		if (napi_schedule_prep(&adapter->napi)) {
-			if (process_pure_responses(adapter))
-				__napi_schedule(&adapter->napi);
-			else {
-				/* no data, no NAPI needed */
-				writel(sge->respQ.cidx, adapter->regs + A_SG_SLEEPING);
-				/* undo schedule_prep */
-				napi_enable(&adapter->napi);
-			}
-		}
-		return IRQ_HANDLED;
-	}
-
-	spin_lock(&adapter->async_lock);
-	handled = t1_slow_intr_handler(adapter);
-	spin_unlock(&adapter->async_lock);
-
-	if (!handled)
-		sge->stats.unhandled_irqs++;
-
-	return IRQ_RETVAL(handled != 0);
-}
-
-/*
- * Enqueues the sk_buff onto the cmdQ[qid] and has hardware fetch it.
- *
- * 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 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).
- *
- * This runs with softirqs disabled.
- */
-static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
-		     unsigned int qid, struct net_device *dev)
-{
-	struct sge *sge = adapter->sge;
-	struct cmdQ *q = &sge->cmdQ[qid];
-	unsigned int credits, pidx, genbit, count, use_sched_skb = 0;
-
-	if (!spin_trylock(&q->lock))
-		return NETDEV_TX_LOCKED;
-
-	reclaim_completed_tx(sge, q);
-
-	pidx = q->pidx;
-	credits = q->size - q->in_use;
-	count = 1 + skb_shinfo(skb)->nr_frags;
-	count += compute_large_page_tx_descs(skb);
-
-	/* Ethernet packet */
-	if (unlikely(credits < count)) {
-		if (!netif_queue_stopped(dev)) {
-			netif_stop_queue(dev);
-			set_bit(dev->if_port, &sge->stopped_tx_queues);
-			sge->stats.cmdQ_full[2]++;
-			pr_err("%s: Tx ring full while queue awake!\n",
-			       adapter->name);
-		}
-		spin_unlock(&q->lock);
-		return NETDEV_TX_BUSY;
-	}
-
-	if (unlikely(credits - count < q->stop_thres)) {
-		netif_stop_queue(dev);
-		set_bit(dev->if_port, &sge->stopped_tx_queues);
-		sge->stats.cmdQ_full[2]++;
-	}
-
-	/* T204 cmdQ0 skbs that are destined for a certain port have to go
-	 * through the scheduler.
-	 */
-	if (sge->tx_sched && !qid && skb->dev) {
-use_sched:
-		use_sched_skb = 1;
-		/* Note that the scheduler might return a different skb than
-		 * the one passed in.
-		 */
-		skb = sched_skb(sge, skb, credits);
-		if (!skb) {
-			spin_unlock(&q->lock);
-			return NETDEV_TX_OK;
-		}
-		pidx = q->pidx;
-		count = 1 + skb_shinfo(skb)->nr_frags;
-		count += compute_large_page_tx_descs(skb);
-	}
-
-	q->in_use += count;
-	genbit = q->genbit;
-	pidx = q->pidx;
-	q->pidx += count;
-	if (q->pidx >= q->size) {
-		q->pidx -= q->size;
-		q->genbit ^= 1;
-	}
-	spin_unlock(&q->lock);
-
-	write_tx_descs(adapter, skb, pidx, genbit, q);
-
-	/*
-	 * We always ring the doorbell for cmdQ1.  For cmdQ0, we only ring
-	 * the doorbell if the Q is asleep. There is a natural race, where
-	 * the hardware is going to sleep just after we checked, however,
-	 * then the interrupt handler will detect the outstanding TX packet
-	 * and ring the doorbell for us.
-	 */
-	if (qid)
-		doorbell_pio(adapter, F_CMDQ1_ENABLE);
-	else {
-		clear_bit(CMDQ_STAT_LAST_PKT_DB, &q->status);
-		if (test_and_set_bit(CMDQ_STAT_RUNNING, &q->status) == 0) {
-			set_bit(CMDQ_STAT_LAST_PKT_DB, &q->status);
-			writel(F_CMDQ0_ENABLE, adapter->regs + A_SG_DOORBELL);
-		}
-	}
-
-	if (use_sched_skb) {
-		if (spin_trylock(&q->lock)) {
-			credits = q->size - q->in_use;
-			skb = NULL;
-			goto use_sched;
-		}
-	}
-	return NETDEV_TX_OK;
-}
-
-#define MK_ETH_TYPE_MSS(type, mss) (((mss) & 0x3FFF) | ((type) << 14))
-
-/*
- *	eth_hdr_len - return the length of an Ethernet header
- *	@data: pointer to the start of the Ethernet header
- *
- *	Returns the length of an Ethernet header, including optional VLAN tag.
- */
-static inline int eth_hdr_len(const void *data)
-{
-	const struct ethhdr *e = data;
-
-	return e->h_proto == htons(ETH_P_8021Q) ? VLAN_ETH_HLEN : ETH_HLEN;
-}
-
-/*
- * Adds the CPL header to the sk_buff and passes it to t1_sge_tx.
- */
-netdev_tx_t t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct adapter *adapter = dev->ml_priv;
-	struct sge *sge = adapter->sge;
-	struct sge_port_stats *st = this_cpu_ptr(sge->port_stats[dev->if_port]);
-	struct cpl_tx_pkt *cpl;
-	struct sk_buff *orig_skb = skb;
-	int ret;
-
-	if (skb->protocol == htons(ETH_P_CPL5))
-		goto send;
-
-	/*
-	 * We are using a non-standard hard_header_len.
-	 * Allocate more header room in the rare cases it is not big enough.
-	 */
-	if (unlikely(skb_headroom(skb) < dev->hard_header_len - ETH_HLEN)) {
-		skb = skb_realloc_headroom(skb, sizeof(struct cpl_tx_pkt_lso));
-		++st->tx_need_hdrroom;
-		dev_kfree_skb_any(orig_skb);
-		if (!skb)
-			return NETDEV_TX_OK;
-	}
-
-	if (skb_shinfo(skb)->gso_size) {
-		int eth_type;
-		struct cpl_tx_pkt_lso *hdr;
-
-		++st->tx_tso;
-
-		eth_type = skb_network_offset(skb) == ETH_HLEN ?
-			CPL_ETH_II : CPL_ETH_II_VLAN;
-
-		hdr = (struct cpl_tx_pkt_lso *)skb_push(skb, sizeof(*hdr));
-		hdr->opcode = CPL_TX_PKT_LSO;
-		hdr->ip_csum_dis = hdr->l4_csum_dis = 0;
-		hdr->ip_hdr_words = ip_hdr(skb)->ihl;
-		hdr->tcp_hdr_words = tcp_hdr(skb)->doff;
-		hdr->eth_type_mss = htons(MK_ETH_TYPE_MSS(eth_type,
-							  skb_shinfo(skb)->gso_size));
-		hdr->len = htonl(skb->len - sizeof(*hdr));
-		cpl = (struct cpl_tx_pkt *)hdr;
-	} else {
-		/*
-		 * Packets shorter than ETH_HLEN can break the MAC, drop them
-		 * early.  Also, we may get oversized packets because some
-		 * parts of the kernel don't handle our unusual hard_header_len
-		 * right, drop those too.
-		 */
-		if (unlikely(skb->len < ETH_HLEN ||
-			     skb->len > dev->mtu + eth_hdr_len(skb->data))) {
-			pr_debug("%s: packet size %d hdr %d mtu%d\n", dev->name,
-				 skb->len, eth_hdr_len(skb->data), dev->mtu);
-			dev_kfree_skb_any(skb);
-			return NETDEV_TX_OK;
-		}
-
-		if (skb->ip_summed == CHECKSUM_PARTIAL &&
-		    ip_hdr(skb)->protocol == IPPROTO_UDP) {
-			if (unlikely(skb_checksum_help(skb))) {
-				pr_debug("%s: unable to do udp checksum\n", dev->name);
-				dev_kfree_skb_any(skb);
-				return NETDEV_TX_OK;
-			}
-		}
-
-		/* Hmmm, assuming to catch the gratious arp... and we'll use
-		 * it to flush out stuck espi packets...
-		 */
-		if ((unlikely(!adapter->sge->espibug_skb[dev->if_port]))) {
-			if (skb->protocol == htons(ETH_P_ARP) &&
-			    arp_hdr(skb)->ar_op == htons(ARPOP_REQUEST)) {
-				adapter->sge->espibug_skb[dev->if_port] = skb;
-				/* We want to re-use this skb later. We
-				 * simply bump the reference count and it
-				 * will not be freed...
-				 */
-				skb = skb_get(skb);
-			}
-		}
-
-		cpl = (struct cpl_tx_pkt *)__skb_push(skb, sizeof(*cpl));
-		cpl->opcode = CPL_TX_PKT;
-		cpl->ip_csum_dis = 1;    /* SW calculates IP csum */
-		cpl->l4_csum_dis = skb->ip_summed == CHECKSUM_PARTIAL ? 0 : 1;
-		/* the length field isn't used so don't bother setting it */
-
-		st->tx_cso += (skb->ip_summed == CHECKSUM_PARTIAL);
-	}
-	cpl->iff = dev->if_port;
-
-	if (vlan_tx_tag_present(skb)) {
-		cpl->vlan_valid = 1;
-		cpl->vlan = htons(vlan_tx_tag_get(skb));
-		st->vlan_insert++;
-	} else
-		cpl->vlan_valid = 0;
-
-send:
-	ret = t1_sge_tx(skb, adapter, 0, dev);
-
-	/* If transmit busy, and we reallocated skb's due to headroom limit,
-	 * then silently discard to avoid leak.
-	 */
-	if (unlikely(ret != NETDEV_TX_OK && skb != orig_skb)) {
-		dev_kfree_skb_any(skb);
-		ret = NETDEV_TX_OK;
-	}
-	return ret;
-}
-
-/*
- * Callback for the Tx buffer reclaim timer.  Runs with softirqs disabled.
- */
-static void sge_tx_reclaim_cb(unsigned long data)
-{
-	int i;
-	struct sge *sge = (struct sge *)data;
-
-	for (i = 0; i < SGE_CMDQ_N; ++i) {
-		struct cmdQ *q = &sge->cmdQ[i];
-
-		if (!spin_trylock(&q->lock))
-			continue;
-
-		reclaim_completed_tx(sge, q);
-		if (i == 0 && q->in_use) {    /* flush pending credits */
-			writel(F_CMDQ0_ENABLE, sge->adapter->regs + A_SG_DOORBELL);
-		}
-		spin_unlock(&q->lock);
-	}
-	mod_timer(&sge->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD);
-}
-
-/*
- * Propagate changes of the SGE coalescing parameters to the HW.
- */
-int t1_sge_set_coalesce_params(struct sge *sge, struct sge_params *p)
-{
-	sge->fixed_intrtimer = p->rx_coalesce_usecs *
-		core_ticks_per_usec(sge->adapter);
-	writel(sge->fixed_intrtimer, sge->adapter->regs + A_SG_INTRTIMER);
-	return 0;
-}
-
-/*
- * Allocates both RX and TX resources and configures the SGE. However,
- * the hardware is not enabled yet.
- */
-int t1_sge_configure(struct sge *sge, struct sge_params *p)
-{
-	if (alloc_rx_resources(sge, p))
-		return -ENOMEM;
-	if (alloc_tx_resources(sge, p)) {
-		free_rx_resources(sge);
-		return -ENOMEM;
-	}
-	configure_sge(sge, p);
-
-	/*
-	 * Now that we have sized the free lists calculate the payload
-	 * capacity of the large buffers.  Other parts of the driver use
-	 * this to set the max offload coalescing size so that RX packets
-	 * do not overflow our large buffers.
-	 */
-	p->large_buf_capacity = jumbo_payload_capacity(sge);
-	return 0;
-}
-
-/*
- * Disables the DMA engine.
- */
-void t1_sge_stop(struct sge *sge)
-{
-	int i;
-	writel(0, sge->adapter->regs + A_SG_CONTROL);
-	readl(sge->adapter->regs + A_SG_CONTROL); /* flush */
-
-	if (is_T2(sge->adapter))
-		del_timer_sync(&sge->espibug_timer);
-
-	del_timer_sync(&sge->tx_reclaim_timer);
-	if (sge->tx_sched)
-		tx_sched_stop(sge);
-
-	for (i = 0; i < MAX_NPORTS; i++)
-		kfree_skb(sge->espibug_skb[i]);
-}
-
-/*
- * Enables the DMA engine.
- */
-void t1_sge_start(struct sge *sge)
-{
-	refill_free_list(sge, &sge->freelQ[0]);
-	refill_free_list(sge, &sge->freelQ[1]);
-
-	writel(sge->sge_control, sge->adapter->regs + A_SG_CONTROL);
-	doorbell_pio(sge->adapter, F_FL0_ENABLE | F_FL1_ENABLE);
-	readl(sge->adapter->regs + A_SG_CONTROL); /* flush */
-
-	mod_timer(&sge->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD);
-
-	if (is_T2(sge->adapter))
-		mod_timer(&sge->espibug_timer, jiffies + sge->espibug_timeout);
-}
-
-/*
- * Callback for the T2 ESPI 'stuck packet feature' workaorund
- */
-static void espibug_workaround_t204(unsigned long data)
-{
-	struct adapter *adapter = (struct adapter *)data;
-	struct sge *sge = adapter->sge;
-	unsigned int nports = adapter->params.nports;
-	u32 seop[MAX_NPORTS];
-
-	if (adapter->open_device_map & PORT_MASK) {
-		int i;
-
-		if (t1_espi_get_mon_t204(adapter, &(seop[0]), 0) < 0)
-			return;
-
-		for (i = 0; i < nports; i++) {
-			struct sk_buff *skb = sge->espibug_skb[i];
-
-			if (!netif_running(adapter->port[i].dev) ||
-			    netif_queue_stopped(adapter->port[i].dev) ||
-			    !seop[i] || ((seop[i] & 0xfff) != 0) || !skb)
-				continue;
-
-			if (!skb->cb[0]) {
-				skb_copy_to_linear_data_offset(skb,
-						    sizeof(struct cpl_tx_pkt),
-							       ch_mac_addr,
-							       ETH_ALEN);
-				skb_copy_to_linear_data_offset(skb,
-							       skb->len - 10,
-							       ch_mac_addr,
-							       ETH_ALEN);
-				skb->cb[0] = 0xff;
-			}
-
-			/* bump the reference count to avoid freeing of
-			 * the skb once the DMA has completed.
-			 */
-			skb = skb_get(skb);
-			t1_sge_tx(skb, adapter, 0, adapter->port[i].dev);
-		}
-	}
-	mod_timer(&sge->espibug_timer, jiffies + sge->espibug_timeout);
-}
-
-static void espibug_workaround(unsigned long data)
-{
-	struct adapter *adapter = (struct adapter *)data;
-	struct sge *sge = adapter->sge;
-
-	if (netif_running(adapter->port[0].dev)) {
-	        struct sk_buff *skb = sge->espibug_skb[0];
-	        u32 seop = t1_espi_get_mon(adapter, 0x930, 0);
-
-	        if ((seop & 0xfff0fff) == 0xfff && skb) {
-	                if (!skb->cb[0]) {
-	                        skb_copy_to_linear_data_offset(skb,
-						     sizeof(struct cpl_tx_pkt),
-							       ch_mac_addr,
-							       ETH_ALEN);
-	                        skb_copy_to_linear_data_offset(skb,
-							       skb->len - 10,
-							       ch_mac_addr,
-							       ETH_ALEN);
-	                        skb->cb[0] = 0xff;
-	                }
-
-	                /* bump the reference count to avoid freeing of the
-	                 * skb once the DMA has completed.
-	                 */
-	                skb = skb_get(skb);
-	                t1_sge_tx(skb, adapter, 0, adapter->port[0].dev);
-	        }
-	}
-	mod_timer(&sge->espibug_timer, jiffies + sge->espibug_timeout);
-}
-
-/*
- * Creates a t1_sge structure and returns suggested resource parameters.
- */
-struct sge * __devinit t1_sge_create(struct adapter *adapter,
-				     struct sge_params *p)
-{
-	struct sge *sge = kzalloc(sizeof(*sge), GFP_KERNEL);
-	int i;
-
-	if (!sge)
-		return NULL;
-
-	sge->adapter = adapter;
-	sge->netdev = adapter->port[0].dev;
-	sge->rx_pkt_pad = t1_is_T1B(adapter) ? 0 : 2;
-	sge->jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
-
-	for_each_port(adapter, i) {
-		sge->port_stats[i] = alloc_percpu(struct sge_port_stats);
-		if (!sge->port_stats[i])
-			goto nomem_port;
-	}
-
-	init_timer(&sge->tx_reclaim_timer);
-	sge->tx_reclaim_timer.data = (unsigned long)sge;
-	sge->tx_reclaim_timer.function = sge_tx_reclaim_cb;
-
-	if (is_T2(sge->adapter)) {
-		init_timer(&sge->espibug_timer);
-
-		if (adapter->params.nports > 1) {
-			tx_sched_init(sge);
-			sge->espibug_timer.function = espibug_workaround_t204;
-		} else
-			sge->espibug_timer.function = espibug_workaround;
-		sge->espibug_timer.data = (unsigned long)sge->adapter;
-
-		sge->espibug_timeout = 1;
-		/* for T204, every 10ms */
-		if (adapter->params.nports > 1)
-			sge->espibug_timeout = HZ/100;
-	}
-
-
-	p->cmdQ_size[0] = SGE_CMDQ0_E_N;
-	p->cmdQ_size[1] = SGE_CMDQ1_E_N;
-	p->freelQ_size[!sge->jumbo_fl] = SGE_FREEL_SIZE;
-	p->freelQ_size[sge->jumbo_fl] = SGE_JUMBO_FREEL_SIZE;
-	if (sge->tx_sched) {
-		if (board_info(sge->adapter)->board == CHBT_BOARD_CHT204)
-			p->rx_coalesce_usecs = 15;
-		else
-			p->rx_coalesce_usecs = 50;
-	} else
-		p->rx_coalesce_usecs = 50;
-
-	p->coalesce_enable = 0;
-	p->sample_interval_usecs = 0;
-
-	return sge;
-nomem_port:
-	while (i >= 0) {
-		free_percpu(sge->port_stats[i]);
-		--i;
-	}
-	kfree(sge);
-	return NULL;
-
-}
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/sge.h linux-libre-3.2-gnu/drivers/net/chelsio/sge.h
--- linux-libre-3.1-gnu/drivers/net/chelsio/sge.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/sge.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,94 +0,0 @@
-/*****************************************************************************
- *                                                                           *
- * File: sge.h                                                               *
- * $Revision: 1.11 $                                                          *
- * $Date: 2005/06/21 22:10:55 $                                              *
- * Description:                                                              *
- *  part of the Chelsio 10Gb Ethernet 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.                                *
- *                                                                           *
- * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
- *                                                                           *
- * http://www.chelsio.com                                                    *
- *                                                                           *
- * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
- * All rights reserved.                                                      *
- *                                                                           *
- * Maintainers: maintainers@chelsio.com                                      *
- *                                                                           *
- * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
- *          Tina Yang               <tainay@chelsio.com>                     *
- *          Felix Marti             <felix@chelsio.com>                      *
- *          Scott Bardone           <sbardone@chelsio.com>                   *
- *          Kurt Ottaway            <kottaway@chelsio.com>                   *
- *          Frank DiMambro          <frank@chelsio.com>                      *
- *                                                                           *
- * History:                                                                  *
- *                                                                           *
- ****************************************************************************/
-
-#ifndef _CXGB_SGE_H_
-#define _CXGB_SGE_H_
-
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <asm/byteorder.h>
-
-struct sge_intr_counts {
-	unsigned int rx_drops;        /* # of packets dropped due to no mem */
-	unsigned int pure_rsps;        /* # of non-payload responses */
-	unsigned int unhandled_irqs;   /* # of unhandled interrupts */
-	unsigned int respQ_empty;      /* # times respQ empty */
-	unsigned int respQ_overflow;   /* # respQ overflow (fatal) */
-	unsigned int freelistQ_empty;  /* # times freelist empty */
-	unsigned int pkt_too_big;      /* packet too large (fatal) */
-	unsigned int pkt_mismatch;
-	unsigned int cmdQ_full[3];     /* not HW IRQ, host cmdQ[] full */
-	unsigned int cmdQ_restarted[3];/* # of times cmdQ X was restarted */
-};
-
-struct sge_port_stats {
-	u64 rx_cso_good;     /* # of successful RX csum offloads */
-	u64 tx_cso;          /* # of TX checksum offloads */
-	u64 tx_tso;          /* # of TSO requests */
-	u64 vlan_xtract;     /* # of VLAN tag extractions */
-	u64 vlan_insert;     /* # of VLAN tag insertions */
-	u64 tx_need_hdrroom; /* # of TX skbs in need of more header room */
-};
-
-struct sk_buff;
-struct net_device;
-struct adapter;
-struct sge_params;
-struct sge;
-
-struct sge *t1_sge_create(struct adapter *, struct sge_params *);
-int t1_sge_configure(struct sge *, struct sge_params *);
-int t1_sge_set_coalesce_params(struct sge *, struct sge_params *);
-void t1_sge_destroy(struct sge *);
-irqreturn_t t1_interrupt(int irq, void *cookie);
-int t1_poll(struct napi_struct *, int);
-
-netdev_tx_t t1_start_xmit(struct sk_buff *skb, struct net_device *dev);
-void t1_vlan_mode(struct adapter *adapter, u32 features);
-void t1_sge_start(struct sge *);
-void t1_sge_stop(struct sge *);
-int t1_sge_intr_error_handler(struct sge *);
-void t1_sge_intr_enable(struct sge *);
-void t1_sge_intr_disable(struct sge *);
-void t1_sge_intr_clear(struct sge *);
-const struct sge_intr_counts *t1_sge_get_intr_counts(const struct sge *sge);
-void t1_sge_get_port_stats(const struct sge *sge, int port, struct sge_port_stats *);
-unsigned int t1_sched_update_parms(struct sge *, unsigned int, unsigned int,
-			   unsigned int);
-
-#endif /* _CXGB_SGE_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/subr.c linux-libre-3.2-gnu/drivers/net/chelsio/subr.c
--- linux-libre-3.1-gnu/drivers/net/chelsio/subr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/subr.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1130 +0,0 @@
-/*****************************************************************************
- *                                                                           *
- * File: subr.c                                                              *
- * $Revision: 1.27 $                                                         *
- * $Date: 2005/06/22 01:08:36 $                                              *
- * Description:                                                              *
- *  Various subroutines (intr,pio,etc.) used by Chelsio 10G Ethernet driver. *
- *  part of the Chelsio 10Gb Ethernet 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.                                *
- *                                                                           *
- * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
- *                                                                           *
- * http://www.chelsio.com                                                    *
- *                                                                           *
- * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
- * All rights reserved.                                                      *
- *                                                                           *
- * Maintainers: maintainers@chelsio.com                                      *
- *                                                                           *
- * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
- *          Tina Yang               <tainay@chelsio.com>                     *
- *          Felix Marti             <felix@chelsio.com>                      *
- *          Scott Bardone           <sbardone@chelsio.com>                   *
- *          Kurt Ottaway            <kottaway@chelsio.com>                   *
- *          Frank DiMambro          <frank@chelsio.com>                      *
- *                                                                           *
- * History:                                                                  *
- *                                                                           *
- ****************************************************************************/
-
-#include "common.h"
-#include "elmer0.h"
-#include "regs.h"
-#include "gmac.h"
-#include "cphy.h"
-#include "sge.h"
-#include "tp.h"
-#include "espi.h"
-
-/**
- *	t1_wait_op_done - wait until an operation is completed
- *	@adapter: the adapter performing the operation
- *	@reg: the register to check for completion
- *	@mask: a single-bit field within @reg that indicates completion
- *	@polarity: the value of the field when the operation is completed
- *	@attempts: number of check iterations
- *      @delay: delay in usecs between iterations
- *
- *	Wait until an operation is completed by checking a bit in a register
- *	up to @attempts times.  Returns %0 if the operation completes and %1
- *	otherwise.
- */
-static int t1_wait_op_done(adapter_t *adapter, int reg, u32 mask, int polarity,
-			   int attempts, int delay)
-{
-	while (1) {
-		u32 val = readl(adapter->regs + reg) & mask;
-
-		if (!!val == polarity)
-			return 0;
-		if (--attempts == 0)
-			return 1;
-		if (delay)
-			udelay(delay);
-	}
-}
-
-#define TPI_ATTEMPTS 50
-
-/*
- * Write a register over the TPI interface (unlocked and locked versions).
- */
-int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
-{
-	int tpi_busy;
-
-	writel(addr, adapter->regs + A_TPI_ADDR);
-	writel(value, adapter->regs + A_TPI_WR_DATA);
-	writel(F_TPIWR, adapter->regs + A_TPI_CSR);
-
-	tpi_busy = t1_wait_op_done(adapter, A_TPI_CSR, F_TPIRDY, 1,
-				   TPI_ATTEMPTS, 3);
-	if (tpi_busy)
-		pr_alert("%s: TPI write to 0x%x failed\n",
-			 adapter->name, addr);
-	return tpi_busy;
-}
-
-int t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
-{
-	int ret;
-
-	spin_lock(&adapter->tpi_lock);
-	ret = __t1_tpi_write(adapter, addr, value);
-	spin_unlock(&adapter->tpi_lock);
-	return ret;
-}
-
-/*
- * Read a register over the TPI interface (unlocked and locked versions).
- */
-int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
-{
-	int tpi_busy;
-
-	writel(addr, adapter->regs + A_TPI_ADDR);
-	writel(0, adapter->regs + A_TPI_CSR);
-
-	tpi_busy = t1_wait_op_done(adapter, A_TPI_CSR, F_TPIRDY, 1,
-				   TPI_ATTEMPTS, 3);
-	if (tpi_busy)
-		pr_alert("%s: TPI read from 0x%x failed\n",
-			 adapter->name, addr);
-	else
-		*valp = readl(adapter->regs + A_TPI_RD_DATA);
-	return tpi_busy;
-}
-
-int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
-{
-	int ret;
-
-	spin_lock(&adapter->tpi_lock);
-	ret = __t1_tpi_read(adapter, addr, valp);
-	spin_unlock(&adapter->tpi_lock);
-	return ret;
-}
-
-/*
- * Set a TPI parameter.
- */
-static void t1_tpi_par(adapter_t *adapter, u32 value)
-{
-	writel(V_TPIPAR(value), adapter->regs + A_TPI_PAR);
-}
-
-/*
- * Called when a port's link settings change to propagate the new values to the
- * associated PHY and MAC.  After performing the common tasks it invokes an
- * OS-specific handler.
- */
-void t1_link_changed(adapter_t *adapter, int port_id)
-{
-	int link_ok, speed, duplex, fc;
-	struct cphy *phy = adapter->port[port_id].phy;
-	struct link_config *lc = &adapter->port[port_id].link_config;
-
-	phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
-
-	lc->speed = speed < 0 ? SPEED_INVALID : speed;
-	lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
-	if (!(lc->requested_fc & PAUSE_AUTONEG))
-		fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
-
-	if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) {
-		/* Set MAC speed, duplex, and flow control to match PHY. */
-		struct cmac *mac = adapter->port[port_id].mac;
-
-		mac->ops->set_speed_duplex_fc(mac, speed, duplex, fc);
-		lc->fc = (unsigned char)fc;
-	}
-	t1_link_negotiated(adapter, port_id, link_ok, speed, duplex, fc);
-}
-
-static int t1_pci_intr_handler(adapter_t *adapter)
-{
-	u32 pcix_cause;
-
-	pci_read_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, &pcix_cause);
-
-	if (pcix_cause) {
-		pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE,
-				       pcix_cause);
-		t1_fatal_err(adapter);    /* PCI errors are fatal */
-	}
-	return 0;
-}
-
-#ifdef CONFIG_CHELSIO_T1_1G
-#include "fpga_defs.h"
-
-/*
- * PHY interrupt handler for FPGA boards.
- */
-static int fpga_phy_intr_handler(adapter_t *adapter)
-{
-	int p;
-	u32 cause = readl(adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE);
-
-	for_each_port(adapter, p)
-		if (cause & (1 << p)) {
-			struct cphy *phy = adapter->port[p].phy;
-			int phy_cause = phy->ops->interrupt_handler(phy);
-
-			if (phy_cause & cphy_cause_link_change)
-				t1_link_changed(adapter, p);
-		}
-	writel(cause, adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE);
-	return 0;
-}
-
-/*
- * Slow path interrupt handler for FPGAs.
- */
-static int fpga_slow_intr(adapter_t *adapter)
-{
-	u32 cause = readl(adapter->regs + A_PL_CAUSE);
-
-	cause &= ~F_PL_INTR_SGE_DATA;
-	if (cause & F_PL_INTR_SGE_ERR)
-		t1_sge_intr_error_handler(adapter->sge);
-
-	if (cause & FPGA_PCIX_INTERRUPT_GMAC)
-		fpga_phy_intr_handler(adapter);
-
-	if (cause & FPGA_PCIX_INTERRUPT_TP) {
-		/*
-		 * FPGA doesn't support MC4 interrupts and it requires
-		 * this odd layer of indirection for MC5.
-		 */
-		u32 tp_cause = readl(adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE);
-
-		/* Clear TP interrupt */
-		writel(tp_cause, adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE);
-	}
-	if (cause & FPGA_PCIX_INTERRUPT_PCIX)
-		t1_pci_intr_handler(adapter);
-
-	/* Clear the interrupts just processed. */
-	if (cause)
-		writel(cause, adapter->regs + A_PL_CAUSE);
-
-	return cause != 0;
-}
-#endif
-
-/*
- * Wait until Elmer's MI1 interface is ready for new operations.
- */
-static int mi1_wait_until_ready(adapter_t *adapter, int mi1_reg)
-{
-	int attempts = 100, busy;
-
-	do {
-		u32 val;
-
-		__t1_tpi_read(adapter, mi1_reg, &val);
-		busy = val & F_MI1_OP_BUSY;
-		if (busy)
-			udelay(10);
-	} while (busy && --attempts);
-	if (busy)
-		pr_alert("%s: MDIO operation timed out\n", adapter->name);
-	return busy;
-}
-
-/*
- * MI1 MDIO initialization.
- */
-static void mi1_mdio_init(adapter_t *adapter, const struct board_info *bi)
-{
-	u32 clkdiv = bi->clock_elmer0 / (2 * bi->mdio_mdc) - 1;
-	u32 val = F_MI1_PREAMBLE_ENABLE | V_MI1_MDI_INVERT(bi->mdio_mdiinv) |
-		V_MI1_MDI_ENABLE(bi->mdio_mdien) | V_MI1_CLK_DIV(clkdiv);
-
-	if (!(bi->caps & SUPPORTED_10000baseT_Full))
-		val |= V_MI1_SOF(1);
-	t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_CFG, val);
-}
-
-#if defined(CONFIG_CHELSIO_T1_1G)
-/*
- * Elmer MI1 MDIO read/write operations.
- */
-static int mi1_mdio_read(struct net_device *dev, int phy_addr, int mmd_addr,
-			 u16 reg_addr)
-{
-	struct adapter *adapter = dev->ml_priv;
-	u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr);
-	unsigned int val;
-
-	spin_lock(&adapter->tpi_lock);
-	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
-	__t1_tpi_write(adapter,
-			A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_READ);
-	mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
-	__t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, &val);
-	spin_unlock(&adapter->tpi_lock);
-	return val;
-}
-
-static int mi1_mdio_write(struct net_device *dev, int phy_addr, int mmd_addr,
-			  u16 reg_addr, u16 val)
-{
-	struct adapter *adapter = dev->ml_priv;
-	u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr);
-
-	spin_lock(&adapter->tpi_lock);
-	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
-	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val);
-	__t1_tpi_write(adapter,
-			A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_WRITE);
-	mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
-	spin_unlock(&adapter->tpi_lock);
-	return 0;
-}
-
-static const struct mdio_ops mi1_mdio_ops = {
-	.init = mi1_mdio_init,
-	.read = mi1_mdio_read,
-	.write = mi1_mdio_write,
-	.mode_support = MDIO_SUPPORTS_C22
-};
-
-#endif
-
-static int mi1_mdio_ext_read(struct net_device *dev, int phy_addr, int mmd_addr,
-			     u16 reg_addr)
-{
-	struct adapter *adapter = dev->ml_priv;
-	u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
-	unsigned int val;
-
-	spin_lock(&adapter->tpi_lock);
-
-	/* Write the address we want. */
-	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
-	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, reg_addr);
-	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
-		       MI1_OP_INDIRECT_ADDRESS);
-	mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
-
-	/* Write the operation we want. */
-	__t1_tpi_write(adapter,
-			A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_READ);
-	mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
-
-	/* Read the data. */
-	__t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, &val);
-	spin_unlock(&adapter->tpi_lock);
-	return val;
-}
-
-static int mi1_mdio_ext_write(struct net_device *dev, int phy_addr,
-			      int mmd_addr, u16 reg_addr, u16 val)
-{
-	struct adapter *adapter = dev->ml_priv;
-	u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
-
-	spin_lock(&adapter->tpi_lock);
-
-	/* Write the address we want. */
-	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
-	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, reg_addr);
-	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
-		       MI1_OP_INDIRECT_ADDRESS);
-	mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
-
-	/* Write the data. */
-	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val);
-	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_WRITE);
-	mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
-	spin_unlock(&adapter->tpi_lock);
-	return 0;
-}
-
-static const struct mdio_ops mi1_mdio_ext_ops = {
-	.init = mi1_mdio_init,
-	.read = mi1_mdio_ext_read,
-	.write = mi1_mdio_ext_write,
-	.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22
-};
-
-enum {
-	CH_BRD_T110_1CU,
-	CH_BRD_N110_1F,
-	CH_BRD_N210_1F,
-	CH_BRD_T210_1F,
-	CH_BRD_T210_1CU,
-	CH_BRD_N204_4CU,
-};
-
-static const struct board_info t1_board[] = {
-	{
-		.board		= CHBT_BOARD_CHT110,
-		.port_number	= 1,
-		.caps		= SUPPORTED_10000baseT_Full,
-		.chip_term	= CHBT_TERM_T1,
-		.chip_mac	= CHBT_MAC_PM3393,
-		.chip_phy	= CHBT_PHY_MY3126,
-		.clock_core	= 125000000,
-		.clock_mc3	= 150000000,
-		.clock_mc4	= 125000000,
-		.espi_nports	= 1,
-		.clock_elmer0	= 44,
-		.mdio_mdien	= 1,
-		.mdio_mdiinv	= 1,
-		.mdio_mdc	= 1,
-		.mdio_phybaseaddr = 1,
-		.gmac		= &t1_pm3393_ops,
-		.gphy		= &t1_my3126_ops,
-		.mdio_ops	= &mi1_mdio_ext_ops,
-		.desc		= "Chelsio T110 1x10GBase-CX4 TOE",
-	},
-
-	{
-		.board		= CHBT_BOARD_N110,
-		.port_number	= 1,
-		.caps		= SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE,
-		.chip_term	= CHBT_TERM_T1,
-		.chip_mac	= CHBT_MAC_PM3393,
-		.chip_phy	= CHBT_PHY_88X2010,
-		.clock_core	= 125000000,
-		.espi_nports	= 1,
-		.clock_elmer0	= 44,
-		.mdio_mdien	= 0,
-		.mdio_mdiinv	= 0,
-		.mdio_mdc	= 1,
-		.mdio_phybaseaddr = 0,
-		.gmac		= &t1_pm3393_ops,
-		.gphy		= &t1_mv88x201x_ops,
-		.mdio_ops	= &mi1_mdio_ext_ops,
-		.desc		= "Chelsio N110 1x10GBaseX NIC",
-	},
-
-	{
-		.board		= CHBT_BOARD_N210,
-		.port_number	= 1,
-		.caps		= SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE,
-		.chip_term	= CHBT_TERM_T2,
-		.chip_mac	= CHBT_MAC_PM3393,
-		.chip_phy	= CHBT_PHY_88X2010,
-		.clock_core	= 125000000,
-		.espi_nports	= 1,
-		.clock_elmer0	= 44,
-		.mdio_mdien	= 0,
-		.mdio_mdiinv	= 0,
-		.mdio_mdc	= 1,
-		.mdio_phybaseaddr = 0,
-		.gmac		= &t1_pm3393_ops,
-		.gphy		= &t1_mv88x201x_ops,
-		.mdio_ops	= &mi1_mdio_ext_ops,
-		.desc		= "Chelsio N210 1x10GBaseX NIC",
-	},
-
-	{
-		.board		= CHBT_BOARD_CHT210,
-		.port_number	= 1,
-		.caps		= SUPPORTED_10000baseT_Full,
-		.chip_term	= CHBT_TERM_T2,
-		.chip_mac	= CHBT_MAC_PM3393,
-		.chip_phy	= CHBT_PHY_88X2010,
-		.clock_core	= 125000000,
-		.clock_mc3	= 133000000,
-		.clock_mc4	= 125000000,
-		.espi_nports	= 1,
-		.clock_elmer0	= 44,
-		.mdio_mdien	= 0,
-		.mdio_mdiinv	= 0,
-		.mdio_mdc	= 1,
-		.mdio_phybaseaddr = 0,
-		.gmac		= &t1_pm3393_ops,
-		.gphy		= &t1_mv88x201x_ops,
-		.mdio_ops	= &mi1_mdio_ext_ops,
-		.desc		= "Chelsio T210 1x10GBaseX TOE",
-	},
-
-	{
-		.board		= CHBT_BOARD_CHT210,
-		.port_number	= 1,
-		.caps		= SUPPORTED_10000baseT_Full,
-		.chip_term	= CHBT_TERM_T2,
-		.chip_mac	= CHBT_MAC_PM3393,
-		.chip_phy	= CHBT_PHY_MY3126,
-		.clock_core	= 125000000,
-		.clock_mc3	= 133000000,
-		.clock_mc4	= 125000000,
-		.espi_nports	= 1,
-		.clock_elmer0	= 44,
-		.mdio_mdien	= 1,
-		.mdio_mdiinv	= 1,
-		.mdio_mdc	= 1,
-		.mdio_phybaseaddr = 1,
-		.gmac		= &t1_pm3393_ops,
-		.gphy		= &t1_my3126_ops,
-		.mdio_ops	= &mi1_mdio_ext_ops,
-		.desc		= "Chelsio T210 1x10GBase-CX4 TOE",
-	},
-
-#ifdef CONFIG_CHELSIO_T1_1G
-	{
-		.board		= CHBT_BOARD_CHN204,
-		.port_number	= 4,
-		.caps		= SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full
-				| SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full
-				| SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
-				  SUPPORTED_PAUSE | SUPPORTED_TP,
-		.chip_term	= CHBT_TERM_T2,
-		.chip_mac	= CHBT_MAC_VSC7321,
-		.chip_phy	= CHBT_PHY_88E1111,
-		.clock_core	= 100000000,
-		.espi_nports	= 4,
-		.clock_elmer0	= 44,
-		.mdio_mdien	= 0,
-		.mdio_mdiinv	= 0,
-		.mdio_mdc	= 0,
-		.mdio_phybaseaddr = 4,
-		.gmac		= &t1_vsc7326_ops,
-		.gphy		= &t1_mv88e1xxx_ops,
-		.mdio_ops	= &mi1_mdio_ops,
-		.desc		= "Chelsio N204 4x100/1000BaseT NIC",
-	},
-#endif
-
-};
-
-DEFINE_PCI_DEVICE_TABLE(t1_pci_tbl) = {
-	CH_DEVICE(8, 0, CH_BRD_T110_1CU),
-	CH_DEVICE(8, 1, CH_BRD_T110_1CU),
-	CH_DEVICE(7, 0, CH_BRD_N110_1F),
-	CH_DEVICE(10, 1, CH_BRD_N210_1F),
-	CH_DEVICE(11, 1, CH_BRD_T210_1F),
-	CH_DEVICE(14, 1, CH_BRD_T210_1CU),
-	CH_DEVICE(16, 1, CH_BRD_N204_4CU),
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, t1_pci_tbl);
-
-/*
- * Return the board_info structure with a given index.  Out-of-range indices
- * return NULL.
- */
-const struct board_info *t1_get_board_info(unsigned int board_id)
-{
-	return board_id < ARRAY_SIZE(t1_board) ? &t1_board[board_id] : NULL;
-}
-
-struct chelsio_vpd_t {
-	u32 format_version;
-	u8 serial_number[16];
-	u8 mac_base_address[6];
-	u8 pad[2];           /* make multiple-of-4 size requirement explicit */
-};
-
-#define EEPROMSIZE        (8 * 1024)
-#define EEPROM_MAX_POLL   4
-
-/*
- * Read SEEPROM. A zero is written to the flag register when the address is
- * written to the Control register. The hardware device will set the flag to a
- * one when 4B have been transferred to the Data register.
- */
-int t1_seeprom_read(adapter_t *adapter, u32 addr, __le32 *data)
-{
-	int i = EEPROM_MAX_POLL;
-	u16 val;
-	u32 v;
-
-	if (addr >= EEPROMSIZE || (addr & 3))
-		return -EINVAL;
-
-	pci_write_config_word(adapter->pdev, A_PCICFG_VPD_ADDR, (u16)addr);
-	do {
-		udelay(50);
-		pci_read_config_word(adapter->pdev, A_PCICFG_VPD_ADDR, &val);
-	} while (!(val & F_VPD_OP_FLAG) && --i);
-
-	if (!(val & F_VPD_OP_FLAG)) {
-		pr_err("%s: reading EEPROM address 0x%x failed\n",
-		       adapter->name, addr);
-		return -EIO;
-	}
-	pci_read_config_dword(adapter->pdev, A_PCICFG_VPD_DATA, &v);
-	*data = cpu_to_le32(v);
-	return 0;
-}
-
-static int t1_eeprom_vpd_get(adapter_t *adapter, struct chelsio_vpd_t *vpd)
-{
-	int addr, ret = 0;
-
-	for (addr = 0; !ret && addr < sizeof(*vpd); addr += sizeof(u32))
-		ret = t1_seeprom_read(adapter, addr,
-				      (__le32 *)((u8 *)vpd + addr));
-
-	return ret;
-}
-
-/*
- * Read a port's MAC address from the VPD ROM.
- */
-static int vpd_macaddress_get(adapter_t *adapter, int index, u8 mac_addr[])
-{
-	struct chelsio_vpd_t vpd;
-
-	if (t1_eeprom_vpd_get(adapter, &vpd))
-		return 1;
-	memcpy(mac_addr, vpd.mac_base_address, 5);
-	mac_addr[5] = vpd.mac_base_address[5] + index;
-	return 0;
-}
-
-/*
- * Set up the MAC/PHY according to the requested link settings.
- *
- * If the PHY can auto-negotiate first decide what to advertise, then
- * enable/disable auto-negotiation as desired and reset.
- *
- * If the PHY does not auto-negotiate we just reset it.
- *
- * If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
- * otherwise do it later based on the outcome of auto-negotiation.
- */
-int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc)
-{
-	unsigned int fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
-
-	if (lc->supported & SUPPORTED_Autoneg) {
-		lc->advertising &= ~(ADVERTISED_ASYM_PAUSE | ADVERTISED_PAUSE);
-		if (fc) {
-			if (fc == ((PAUSE_RX | PAUSE_TX) &
-				   (mac->adapter->params.nports < 2)))
-				lc->advertising |= ADVERTISED_PAUSE;
-			else {
-				lc->advertising |= ADVERTISED_ASYM_PAUSE;
-				if (fc == PAUSE_RX)
-					lc->advertising |= ADVERTISED_PAUSE;
-			}
-		}
-		phy->ops->advertise(phy, lc->advertising);
-
-		if (lc->autoneg == AUTONEG_DISABLE) {
-			lc->speed = lc->requested_speed;
-			lc->duplex = lc->requested_duplex;
-			lc->fc = (unsigned char)fc;
-			mac->ops->set_speed_duplex_fc(mac, lc->speed,
-						      lc->duplex, fc);
-			/* Also disables autoneg */
-			phy->state = PHY_AUTONEG_RDY;
-			phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex);
-			phy->ops->reset(phy, 0);
-		} else {
-			phy->state = PHY_AUTONEG_EN;
-			phy->ops->autoneg_enable(phy); /* also resets PHY */
-		}
-	} else {
-		phy->state = PHY_AUTONEG_RDY;
-		mac->ops->set_speed_duplex_fc(mac, -1, -1, fc);
-		lc->fc = (unsigned char)fc;
-		phy->ops->reset(phy, 0);
-	}
-	return 0;
-}
-
-/*
- * External interrupt handler for boards using elmer0.
- */
-int t1_elmer0_ext_intr_handler(adapter_t *adapter)
-{
-	struct cphy *phy;
-	int phy_cause;
-	u32 cause;
-
-	t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause);
-
-	switch (board_info(adapter)->board) {
-#ifdef CONFIG_CHELSIO_T1_1G
-	case CHBT_BOARD_CHT204:
-	case CHBT_BOARD_CHT204E:
-	case CHBT_BOARD_CHN204:
-	case CHBT_BOARD_CHT204V: {
-		int i, port_bit;
-		for_each_port(adapter, i) {
-			port_bit = i + 1;
-			if (!(cause & (1 << port_bit)))
-				continue;
-
-			phy = adapter->port[i].phy;
-			phy_cause = phy->ops->interrupt_handler(phy);
-			if (phy_cause & cphy_cause_link_change)
-				t1_link_changed(adapter, i);
-		}
-		break;
-	}
-	case CHBT_BOARD_CHT101:
-		if (cause & ELMER0_GP_BIT1) { /* Marvell 88E1111 interrupt */
-			phy = adapter->port[0].phy;
-			phy_cause = phy->ops->interrupt_handler(phy);
-			if (phy_cause & cphy_cause_link_change)
-				t1_link_changed(adapter, 0);
-		}
-		break;
-	case CHBT_BOARD_7500: {
-		int p;
-		/*
-		 * Elmer0's interrupt cause isn't useful here because there is
-		 * only one bit that can be set for all 4 ports.  This means
-		 * we are forced to check every PHY's interrupt status
-		 * register to see who initiated the interrupt.
-		 */
-		for_each_port(adapter, p) {
-			phy = adapter->port[p].phy;
-			phy_cause = phy->ops->interrupt_handler(phy);
-			if (phy_cause & cphy_cause_link_change)
-			    t1_link_changed(adapter, p);
-		}
-		break;
-	}
-#endif
-	case CHBT_BOARD_CHT210:
-	case CHBT_BOARD_N210:
-	case CHBT_BOARD_N110:
-		if (cause & ELMER0_GP_BIT6) { /* Marvell 88x2010 interrupt */
-			phy = adapter->port[0].phy;
-			phy_cause = phy->ops->interrupt_handler(phy);
-			if (phy_cause & cphy_cause_link_change)
-				t1_link_changed(adapter, 0);
-		}
-		break;
-	case CHBT_BOARD_8000:
-	case CHBT_BOARD_CHT110:
-		if (netif_msg_intr(adapter))
-			dev_dbg(&adapter->pdev->dev,
-				"External interrupt cause 0x%x\n", cause);
-		if (cause & ELMER0_GP_BIT1) {        /* PMC3393 INTB */
-			struct cmac *mac = adapter->port[0].mac;
-
-			mac->ops->interrupt_handler(mac);
-		}
-		if (cause & ELMER0_GP_BIT5) {        /* XPAK MOD_DETECT */
-			u32 mod_detect;
-
-			t1_tpi_read(adapter,
-					A_ELMER0_GPI_STAT, &mod_detect);
-			if (netif_msg_link(adapter))
-				dev_info(&adapter->pdev->dev, "XPAK %s\n",
-					 mod_detect ? "removed" : "inserted");
-		}
-		break;
-	}
-	t1_tpi_write(adapter, A_ELMER0_INT_CAUSE, cause);
-	return 0;
-}
-
-/* Enables all interrupts. */
-void t1_interrupts_enable(adapter_t *adapter)
-{
-	unsigned int i;
-
-	adapter->slow_intr_mask = F_PL_INTR_SGE_ERR | F_PL_INTR_TP;
-
-	t1_sge_intr_enable(adapter->sge);
-	t1_tp_intr_enable(adapter->tp);
-	if (adapter->espi) {
-		adapter->slow_intr_mask |= F_PL_INTR_ESPI;
-		t1_espi_intr_enable(adapter->espi);
-	}
-
-	/* Enable MAC/PHY interrupts for each port. */
-	for_each_port(adapter, i) {
-		adapter->port[i].mac->ops->interrupt_enable(adapter->port[i].mac);
-		adapter->port[i].phy->ops->interrupt_enable(adapter->port[i].phy);
-	}
-
-	/* Enable PCIX & external chip interrupts on ASIC boards. */
-	if (t1_is_asic(adapter)) {
-		u32 pl_intr = readl(adapter->regs + A_PL_ENABLE);
-
-		/* PCI-X interrupts */
-		pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE,
-				       0xffffffff);
-
-		adapter->slow_intr_mask |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
-		pl_intr |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
-		writel(pl_intr, adapter->regs + A_PL_ENABLE);
-	}
-}
-
-/* Disables all interrupts. */
-void t1_interrupts_disable(adapter_t* adapter)
-{
-	unsigned int i;
-
-	t1_sge_intr_disable(adapter->sge);
-	t1_tp_intr_disable(adapter->tp);
-	if (adapter->espi)
-		t1_espi_intr_disable(adapter->espi);
-
-	/* Disable MAC/PHY interrupts for each port. */
-	for_each_port(adapter, i) {
-		adapter->port[i].mac->ops->interrupt_disable(adapter->port[i].mac);
-		adapter->port[i].phy->ops->interrupt_disable(adapter->port[i].phy);
-	}
-
-	/* Disable PCIX & external chip interrupts. */
-	if (t1_is_asic(adapter))
-		writel(0, adapter->regs + A_PL_ENABLE);
-
-	/* PCI-X interrupts */
-	pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE, 0);
-
-	adapter->slow_intr_mask = 0;
-}
-
-/* Clears all interrupts */
-void t1_interrupts_clear(adapter_t* adapter)
-{
-	unsigned int i;
-
-	t1_sge_intr_clear(adapter->sge);
-	t1_tp_intr_clear(adapter->tp);
-	if (adapter->espi)
-		t1_espi_intr_clear(adapter->espi);
-
-	/* Clear MAC/PHY interrupts for each port. */
-	for_each_port(adapter, i) {
-		adapter->port[i].mac->ops->interrupt_clear(adapter->port[i].mac);
-		adapter->port[i].phy->ops->interrupt_clear(adapter->port[i].phy);
-	}
-
-	/* Enable interrupts for external devices. */
-	if (t1_is_asic(adapter)) {
-		u32 pl_intr = readl(adapter->regs + A_PL_CAUSE);
-
-		writel(pl_intr | F_PL_INTR_EXT | F_PL_INTR_PCIX,
-		       adapter->regs + A_PL_CAUSE);
-	}
-
-	/* PCI-X interrupts */
-	pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, 0xffffffff);
-}
-
-/*
- * Slow path interrupt handler for ASICs.
- */
-static int asic_slow_intr(adapter_t *adapter)
-{
-	u32 cause = readl(adapter->regs + A_PL_CAUSE);
-
-	cause &= adapter->slow_intr_mask;
-	if (!cause)
-		return 0;
-	if (cause & F_PL_INTR_SGE_ERR)
-		t1_sge_intr_error_handler(adapter->sge);
-	if (cause & F_PL_INTR_TP)
-		t1_tp_intr_handler(adapter->tp);
-	if (cause & F_PL_INTR_ESPI)
-		t1_espi_intr_handler(adapter->espi);
-	if (cause & F_PL_INTR_PCIX)
-		t1_pci_intr_handler(adapter);
-	if (cause & F_PL_INTR_EXT)
-		t1_elmer0_ext_intr(adapter);
-
-	/* Clear the interrupts just processed. */
-	writel(cause, adapter->regs + A_PL_CAUSE);
-	readl(adapter->regs + A_PL_CAUSE); /* flush writes */
-	return 1;
-}
-
-int t1_slow_intr_handler(adapter_t *adapter)
-{
-#ifdef CONFIG_CHELSIO_T1_1G
-	if (!t1_is_asic(adapter))
-		return fpga_slow_intr(adapter);
-#endif
-	return asic_slow_intr(adapter);
-}
-
-/* Power sequencing is a work-around for Intel's XPAKs. */
-static void power_sequence_xpak(adapter_t* adapter)
-{
-	u32 mod_detect;
-	u32 gpo;
-
-	/* Check for XPAK */
-	t1_tpi_read(adapter, A_ELMER0_GPI_STAT, &mod_detect);
-	if (!(ELMER0_GP_BIT5 & mod_detect)) {
-		/* XPAK is present */
-		t1_tpi_read(adapter, A_ELMER0_GPO, &gpo);
-		gpo |= ELMER0_GP_BIT18;
-		t1_tpi_write(adapter, A_ELMER0_GPO, gpo);
-	}
-}
-
-int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
-			       struct adapter_params *p)
-{
-	p->chip_version = bi->chip_term;
-	p->is_asic = (p->chip_version != CHBT_TERM_FPGA);
-	if (p->chip_version == CHBT_TERM_T1 ||
-	    p->chip_version == CHBT_TERM_T2 ||
-	    p->chip_version == CHBT_TERM_FPGA) {
-		u32 val = readl(adapter->regs + A_TP_PC_CONFIG);
-
-		val = G_TP_PC_REV(val);
-		if (val == 2)
-			p->chip_revision = TERM_T1B;
-		else if (val == 3)
-			p->chip_revision = TERM_T2;
-		else
-			return -1;
-	} else
-		return -1;
-	return 0;
-}
-
-/*
- * Enable board components other than the Chelsio chip, such as external MAC
- * and PHY.
- */
-static int board_init(adapter_t *adapter, const struct board_info *bi)
-{
-	switch (bi->board) {
-	case CHBT_BOARD_8000:
-	case CHBT_BOARD_N110:
-	case CHBT_BOARD_N210:
-	case CHBT_BOARD_CHT210:
-		t1_tpi_par(adapter, 0xf);
-		t1_tpi_write(adapter, A_ELMER0_GPO, 0x800);
-		break;
-	case CHBT_BOARD_CHT110:
-		t1_tpi_par(adapter, 0xf);
-		t1_tpi_write(adapter, A_ELMER0_GPO, 0x1800);
-
-		/* TBD XXX Might not need.  This fixes a problem
-		 *         described in the Intel SR XPAK errata.
-		 */
-		power_sequence_xpak(adapter);
-		break;
-#ifdef CONFIG_CHELSIO_T1_1G
-	case CHBT_BOARD_CHT204E:
-		/* add config space write here */
-	case CHBT_BOARD_CHT204:
-	case CHBT_BOARD_CHT204V:
-	case CHBT_BOARD_CHN204:
-		t1_tpi_par(adapter, 0xf);
-		t1_tpi_write(adapter, A_ELMER0_GPO, 0x804);
-		break;
-	case CHBT_BOARD_CHT101:
-	case CHBT_BOARD_7500:
-		t1_tpi_par(adapter, 0xf);
-		t1_tpi_write(adapter, A_ELMER0_GPO, 0x1804);
-		break;
-#endif
-	}
-	return 0;
-}
-
-/*
- * Initialize and configure the Terminator HW modules.  Note that external
- * MAC and PHYs are initialized separately.
- */
-int t1_init_hw_modules(adapter_t *adapter)
-{
-	int err = -EIO;
-	const struct board_info *bi = board_info(adapter);
-
-	if (!bi->clock_mc4) {
-		u32 val = readl(adapter->regs + A_MC4_CFG);
-
-		writel(val | F_READY | F_MC4_SLOW, adapter->regs + A_MC4_CFG);
-		writel(F_M_BUS_ENABLE | F_TCAM_RESET,
-		       adapter->regs + A_MC5_CONFIG);
-	}
-
-	if (adapter->espi && t1_espi_init(adapter->espi, bi->chip_mac,
-					  bi->espi_nports))
-		goto out_err;
-
-	if (t1_tp_reset(adapter->tp, &adapter->params.tp, bi->clock_core))
-		goto out_err;
-
-	err = t1_sge_configure(adapter->sge, &adapter->params.sge);
-	if (err)
-		goto out_err;
-
-	err = 0;
-out_err:
-	return err;
-}
-
-/*
- * Determine a card's PCI mode.
- */
-static void __devinit get_pci_mode(adapter_t *adapter, struct chelsio_pci_params *p)
-{
-	static const unsigned short speed_map[] = { 33, 66, 100, 133 };
-	u32 pci_mode;
-
-	pci_read_config_dword(adapter->pdev, A_PCICFG_MODE, &pci_mode);
-	p->speed = speed_map[G_PCI_MODE_CLK(pci_mode)];
-	p->width = (pci_mode & F_PCI_MODE_64BIT) ? 64 : 32;
-	p->is_pcix = (pci_mode & F_PCI_MODE_PCIX) != 0;
-}
-
-/*
- * Release the structures holding the SW per-Terminator-HW-module state.
- */
-void t1_free_sw_modules(adapter_t *adapter)
-{
-	unsigned int i;
-
-	for_each_port(adapter, i) {
-		struct cmac *mac = adapter->port[i].mac;
-		struct cphy *phy = adapter->port[i].phy;
-
-		if (mac)
-			mac->ops->destroy(mac);
-		if (phy)
-			phy->ops->destroy(phy);
-	}
-
-	if (adapter->sge)
-		t1_sge_destroy(adapter->sge);
-	if (adapter->tp)
-		t1_tp_destroy(adapter->tp);
-	if (adapter->espi)
-		t1_espi_destroy(adapter->espi);
-}
-
-static void __devinit init_link_config(struct link_config *lc,
-				       const struct board_info *bi)
-{
-	lc->supported = bi->caps;
-	lc->requested_speed = lc->speed = SPEED_INVALID;
-	lc->requested_duplex = lc->duplex = DUPLEX_INVALID;
-	lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX;
-	if (lc->supported & SUPPORTED_Autoneg) {
-		lc->advertising = lc->supported;
-		lc->autoneg = AUTONEG_ENABLE;
-		lc->requested_fc |= PAUSE_AUTONEG;
-	} else {
-		lc->advertising = 0;
-		lc->autoneg = AUTONEG_DISABLE;
-	}
-}
-
-/*
- * Allocate and initialize the data structures that hold the SW state of
- * the Terminator HW modules.
- */
-int __devinit t1_init_sw_modules(adapter_t *adapter,
-				 const struct board_info *bi)
-{
-	unsigned int i;
-
-	adapter->params.brd_info = bi;
-	adapter->params.nports = bi->port_number;
-	adapter->params.stats_update_period = bi->gmac->stats_update_period;
-
-	adapter->sge = t1_sge_create(adapter, &adapter->params.sge);
-	if (!adapter->sge) {
-		pr_err("%s: SGE initialization failed\n",
-		       adapter->name);
-		goto error;
-	}
-
-	if (bi->espi_nports && !(adapter->espi = t1_espi_create(adapter))) {
-		pr_err("%s: ESPI initialization failed\n",
-		       adapter->name);
-		goto error;
-	}
-
-	adapter->tp = t1_tp_create(adapter, &adapter->params.tp);
-	if (!adapter->tp) {
-		pr_err("%s: TP initialization failed\n",
-		       adapter->name);
-		goto error;
-	}
-
-	board_init(adapter, bi);
-	bi->mdio_ops->init(adapter, bi);
-	if (bi->gphy->reset)
-		bi->gphy->reset(adapter);
-	if (bi->gmac->reset)
-		bi->gmac->reset(adapter);
-
-	for_each_port(adapter, i) {
-		u8 hw_addr[6];
-		struct cmac *mac;
-		int phy_addr = bi->mdio_phybaseaddr + i;
-
-		adapter->port[i].phy = bi->gphy->create(adapter->port[i].dev,
-							phy_addr, bi->mdio_ops);
-		if (!adapter->port[i].phy) {
-			pr_err("%s: PHY %d initialization failed\n",
-			       adapter->name, i);
-			goto error;
-		}
-
-		adapter->port[i].mac = mac = bi->gmac->create(adapter, i);
-		if (!mac) {
-			pr_err("%s: MAC %d initialization failed\n",
-			       adapter->name, i);
-			goto error;
-		}
-
-		/*
-		 * Get the port's MAC addresses either from the EEPROM if one
-		 * exists or the one hardcoded in the MAC.
-		 */
-		if (!t1_is_asic(adapter) || bi->chip_mac == CHBT_MAC_DUMMY)
-			mac->ops->macaddress_get(mac, hw_addr);
-		else if (vpd_macaddress_get(adapter, i, hw_addr)) {
-			pr_err("%s: could not read MAC address from VPD ROM\n",
-			       adapter->port[i].dev->name);
-			goto error;
-		}
-		memcpy(adapter->port[i].dev->dev_addr, hw_addr, ETH_ALEN);
-		init_link_config(&adapter->port[i].link_config, bi);
-	}
-
-	get_pci_mode(adapter, &adapter->params.pci);
-	t1_interrupts_clear(adapter);
-	return 0;
-
-error:
-	t1_free_sw_modules(adapter);
-	return -1;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/suni1x10gexp_regs.h linux-libre-3.2-gnu/drivers/net/chelsio/suni1x10gexp_regs.h
--- linux-libre-3.1-gnu/drivers/net/chelsio/suni1x10gexp_regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/suni1x10gexp_regs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1643 +0,0 @@
-/*****************************************************************************
- *                                                                           *
- * File: suni1x10gexp_regs.h                                                 *
- * $Revision: 1.9 $                                                          *
- * $Date: 2005/06/22 00:17:04 $                                              *
- * Description:                                                              *
- *  PMC/SIERRA (pm3393) MAC-PHY functionality.                               *
- *  part of the Chelsio 10Gb Ethernet 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.                                *
- *                                                                           *
- * You 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
- *                                                                           *
- * http://www.chelsio.com                                                    *
- *                                                                           *
- * Maintainers: maintainers@chelsio.com                                      *
- *                                                                           *
- * Authors: PMC/SIERRA                                                       *
- *                                                                           *
- * History:                                                                  *
- *                                                                           *
- ****************************************************************************/
-
-#ifndef _CXGB_SUNI1x10GEXP_REGS_H_
-#define _CXGB_SUNI1x10GEXP_REGS_H_
-
-/*
-** Space allocated for each Exact Match Filter
-**     There are 8 filter configurations
-*/
-#define SUNI1x10GEXP_REG_SIZEOF_MAC_FILTER 0x0003
-
-#define mSUNI1x10GEXP_MAC_FILTER_OFFSET(filterId)       ( (filterId) * SUNI1x10GEXP_REG_SIZEOF_MAC_FILTER )
-
-/*
-** Space allocated for VLAN-Id Filter
-**      There are 8 filter configurations
-*/
-#define SUNI1x10GEXP_REG_SIZEOF_MAC_VID_FILTER 0x0001
-
-#define mSUNI1x10GEXP_MAC_VID_FILTER_OFFSET(filterId)   ( (filterId) * SUNI1x10GEXP_REG_SIZEOF_MAC_VID_FILTER )
-
-/*
-** Space allocated for each MSTAT Counter
-*/
-#define SUNI1x10GEXP_REG_SIZEOF_MSTAT_COUNT 0x0004
-
-#define mSUNI1x10GEXP_MSTAT_COUNT_OFFSET(countId)       ( (countId) * SUNI1x10GEXP_REG_SIZEOF_MSTAT_COUNT )
-
-
-/******************************************************************************/
-/** S/UNI-1x10GE-XP REGISTER ADDRESS MAP                                     **/
-/******************************************************************************/
-/* Refer to the Register Bit Masks bellow for the naming of each register and */
-/* to the S/UNI-1x10GE-XP Data Sheet for the signification of each bit        */
-/******************************************************************************/
-
-
-#define SUNI1x10GEXP_REG_IDENTIFICATION                                  0x0000
-#define SUNI1x10GEXP_REG_PRODUCT_REVISION                                0x0001
-#define SUNI1x10GEXP_REG_CONFIG_AND_RESET_CONTROL                        0x0002
-#define SUNI1x10GEXP_REG_LOOPBACK_MISC_CTRL                              0x0003
-#define SUNI1x10GEXP_REG_DEVICE_STATUS                                   0x0004
-#define SUNI1x10GEXP_REG_GLOBAL_PERFORMANCE_MONITOR_UPDATE               0x0005
-
-#define SUNI1x10GEXP_REG_MDIO_COMMAND                                    0x0006
-#define SUNI1x10GEXP_REG_MDIO_INTERRUPT_ENABLE                           0x0007
-#define SUNI1x10GEXP_REG_MDIO_INTERRUPT_STATUS                           0x0008
-#define SUNI1x10GEXP_REG_MMD_PHY_ADDRESS                                 0x0009
-#define SUNI1x10GEXP_REG_MMD_CONTROL_ADDRESS_DATA                        0x000A
-#define SUNI1x10GEXP_REG_MDIO_READ_STATUS_DATA                           0x000B
-
-#define SUNI1x10GEXP_REG_OAM_INTF_CTRL                                   0x000C
-#define SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS                         0x000D
-#define SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE                         0x000E
-#define SUNI1x10GEXP_REG_FREE                                            0x000F
-
-#define SUNI1x10GEXP_REG_XTEF_MISC_CTRL                                  0x0010
-#define SUNI1x10GEXP_REG_XRF_MISC_CTRL                                   0x0011
-
-#define SUNI1x10GEXP_REG_SERDES_3125_CONFIG_1                            0x0100
-#define SUNI1x10GEXP_REG_SERDES_3125_CONFIG_2                            0x0101
-#define SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE                    0x0102
-#define SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_VISIBLE                   0x0103
-#define SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_STATUS                    0x0104
-#define SUNI1x10GEXP_REG_SERDES_3125_TEST_CONFIG                         0x0107
-
-#define SUNI1x10GEXP_REG_RXXG_CONFIG_1                                   0x2040
-#define SUNI1x10GEXP_REG_RXXG_CONFIG_2                                   0x2041
-#define SUNI1x10GEXP_REG_RXXG_CONFIG_3                                   0x2042
-#define SUNI1x10GEXP_REG_RXXG_INTERRUPT                                  0x2043
-#define SUNI1x10GEXP_REG_RXXG_MAX_FRAME_LENGTH                           0x2045
-#define SUNI1x10GEXP_REG_RXXG_SA_15_0                                    0x2046
-#define SUNI1x10GEXP_REG_RXXG_SA_31_16                                   0x2047
-#define SUNI1x10GEXP_REG_RXXG_SA_47_32                                   0x2048
-#define SUNI1x10GEXP_REG_RXXG_RECEIVE_FIFO_THRESHOLD                     0x2049
-#define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_LOW(filterId) (0x204A + mSUNI1x10GEXP_MAC_FILTER_OFFSET(filterId))
-#define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_MID(filterId) (0x204B + mSUNI1x10GEXP_MAC_FILTER_OFFSET(filterId))
-#define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_HIGH(filterId)(0x204C + mSUNI1x10GEXP_MAC_FILTER_OFFSET(filterId))
-#define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID(filterId)      (0x2062 + mSUNI1x10GEXP_MAC_VID_FILTER_OFFSET(filterId))
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_0_LOW                     0x204A
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_0_MID                     0x204B
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_0_HIGH                    0x204C
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_LOW                     0x204D
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_MID                     0x204E
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_HIGH                    0x204F
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_2_LOW                     0x2050
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_2_MID                     0x2051
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_2_HIGH                    0x2052
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_3_LOW                     0x2053
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_3_MID                     0x2054
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_3_HIGH                    0x2055
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_4_LOW                     0x2056
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_4_MID                     0x2057
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_4_HIGH                    0x2058
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_5_LOW                     0x2059
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_5_MID                     0x205A
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_5_HIGH                    0x205B
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_6_LOW                     0x205C
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_6_MID                     0x205D
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_6_HIGH                    0x205E
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_7_LOW                     0x205F
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_7_MID                     0x2060
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_7_HIGH                    0x2061
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_0                          0x2062
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_1                          0x2063
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_2                          0x2064
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_3                          0x2065
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_4                          0x2066
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_5                          0x2067
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_6                          0x2068
-#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_7                          0x2069
-#define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW                         0x206A
-#define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW                      0x206B
-#define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH                     0x206C
-#define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH                        0x206D
-#define SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0                   0x206E
-#define SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_1                   0x206F
-#define SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2                   0x2070
-
-#define SUNI1x10GEXP_REG_XRF_PATTERN_GEN_CTRL                            0x2081
-#define SUNI1x10GEXP_REG_XRF_8BTB_ERR_COUNT_LANE_0                       0x2084
-#define SUNI1x10GEXP_REG_XRF_8BTB_ERR_COUNT_LANE_1                       0x2085
-#define SUNI1x10GEXP_REG_XRF_8BTB_ERR_COUNT_LANE_2                       0x2086
-#define SUNI1x10GEXP_REG_XRF_8BTB_ERR_COUNT_LANE_3                       0x2087
-#define SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE                            0x2088
-#define SUNI1x10GEXP_REG_XRF_INTERRUPT_STATUS                            0x2089
-#define SUNI1x10GEXP_REG_XRF_ERR_STATUS                                  0x208A
-#define SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE                       0x208B
-#define SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_STATUS                       0x208C
-#define SUNI1x10GEXP_REG_XRF_CODE_ERR_THRES                              0x2092
-
-#define SUNI1x10GEXP_REG_RXOAM_CONFIG                                    0x20C0
-#define SUNI1x10GEXP_REG_RXOAM_FILTER_1_CONFIG                           0x20C1
-#define SUNI1x10GEXP_REG_RXOAM_FILTER_2_CONFIG                           0x20C2
-#define SUNI1x10GEXP_REG_RXOAM_CONFIG_2                                  0x20C3
-#define SUNI1x10GEXP_REG_RXOAM_HEC_CONFIG                                0x20C4
-#define SUNI1x10GEXP_REG_RXOAM_HEC_ERR_THRES                             0x20C5
-#define SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE                          0x20C7
-#define SUNI1x10GEXP_REG_RXOAM_INTERRUPT_STATUS                          0x20C8
-#define SUNI1x10GEXP_REG_RXOAM_STATUS                                    0x20C9
-#define SUNI1x10GEXP_REG_RXOAM_HEC_ERR_COUNT                             0x20CA
-#define SUNI1x10GEXP_REG_RXOAM_FIFO_OVERFLOW_COUNT                       0x20CB
-#define SUNI1x10GEXP_REG_RXOAM_FILTER_MISMATCH_COUNT_LSB                 0x20CC
-#define SUNI1x10GEXP_REG_RXOAM_FILTER_MISMATCH_COUNT_MSB                 0x20CD
-#define SUNI1x10GEXP_REG_RXOAM_FILTER_1_MISMATCH_COUNT_LSB               0x20CE
-#define SUNI1x10GEXP_REG_RXOAM_FILTER_1_MISMATCH_COUNT_MSB               0x20CF
-#define SUNI1x10GEXP_REG_RXOAM_FILTER_2_MISMATCH_COUNT_LSB               0x20D0
-#define SUNI1x10GEXP_REG_RXOAM_FILTER_2_MISMATCH_COUNT_MSB               0x20D1
-#define SUNI1x10GEXP_REG_RXOAM_OAM_EXTRACT_COUNT_LSB                     0x20D2
-#define SUNI1x10GEXP_REG_RXOAM_OAM_EXTRACT_COUNT_MSB                     0x20D3
-#define SUNI1x10GEXP_REG_RXOAM_MINI_PACKET_COUNT_LSB                     0x20D4
-#define SUNI1x10GEXP_REG_RXOAM_MINI_PACKET_COUNT_MSB                     0x20D5
-#define SUNI1x10GEXP_REG_RXOAM_FILTER_MISMATCH_THRES_LSB                 0x20D6
-#define SUNI1x10GEXP_REG_RXOAM_FILTER_MISMATCH_THRES_MSB                 0x20D7
-
-#define SUNI1x10GEXP_REG_MSTAT_CONTROL                                   0x2100
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_0                        0x2101
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_1                        0x2102
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_2                        0x2103
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_3                        0x2104
-#define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0                          0x2105
-#define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1                          0x2106
-#define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2                          0x2107
-#define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3                          0x2108
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_WRITE_ADDRESS                     0x2109
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_WRITE_DATA_LOW                    0x210A
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_WRITE_DATA_MIDDLE                 0x210B
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_WRITE_DATA_HIGH                   0x210C
-#define mSUNI1x10GEXP_REG_MSTAT_COUNTER_LOW(countId)   (0x2110 + mSUNI1x10GEXP_MSTAT_COUNT_OFFSET(countId))
-#define mSUNI1x10GEXP_REG_MSTAT_COUNTER_MID(countId)   (0x2111 + mSUNI1x10GEXP_MSTAT_COUNT_OFFSET(countId))
-#define mSUNI1x10GEXP_REG_MSTAT_COUNTER_HIGH(countId)  (0x2112 + mSUNI1x10GEXP_MSTAT_COUNT_OFFSET(countId))
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW                             0x2110
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_0_MID                             0x2111
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_0_HIGH                            0x2112
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_0_RESVD                           0x2113
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW                             0x2114
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_1_MID                             0x2115
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_1_HIGH                            0x2116
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_1_RESVD                           0x2117
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_2_LOW                             0x2118
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_2_MID                             0x2119
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_2_HIGH                            0x211A
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_2_RESVD                           0x211B
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_3_LOW                             0x211C
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_3_MID                             0x211D
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_3_HIGH                            0x211E
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_3_RESVD                           0x211F
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_4_LOW                             0x2120
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_4_MID                             0x2121
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_4_HIGH                            0x2122
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_4_RESVD                           0x2123
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_5_LOW                             0x2124
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_5_MID                             0x2125
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_5_HIGH                            0x2126
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_5_RESVD                           0x2127
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_6_LOW                             0x2128
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_6_MID                             0x2129
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_6_HIGH                            0x212A
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_6_RESVD                           0x212B
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_7_LOW                             0x212C
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_7_MID                             0x212D
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_7_HIGH                            0x212E
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_7_RESVD                           0x212F
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_8_LOW                             0x2130
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_8_MID                             0x2131
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_8_HIGH                            0x2132
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_8_RESVD                           0x2133
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_9_LOW                             0x2134
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_9_MID                             0x2135
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_9_HIGH                            0x2136
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_9_RESVD                           0x2137
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_10_LOW                            0x2138
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_10_MID                            0x2139
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_10_HIGH                           0x213A
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_10_RESVD                          0x213B
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_11_LOW                            0x213C
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_11_MID                            0x213D
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_11_HIGH                           0x213E
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_11_RESVD                          0x213F
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_12_LOW                            0x2140
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_12_MID                            0x2141
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_12_HIGH                           0x2142
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_12_RESVD                          0x2143
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_13_LOW                            0x2144
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_13_MID                            0x2145
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_13_HIGH                           0x2146
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_13_RESVD                          0x2147
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_14_LOW                            0x2148
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_14_MID                            0x2149
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_14_HIGH                           0x214A
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_14_RESVD                          0x214B
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_15_LOW                            0x214C
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_15_MID                            0x214D
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_15_HIGH                           0x214E
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_15_RESVD                          0x214F
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW                            0x2150
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_16_MID                            0x2151
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_16_HIGH                           0x2152
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_16_RESVD                          0x2153
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW                            0x2154
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_17_MID                            0x2155
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_17_HIGH                           0x2156
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_17_RESVD                          0x2157
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW                            0x2158
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_18_MID                            0x2159
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_18_HIGH                           0x215A
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_18_RESVD                          0x215B
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_19_LOW                            0x215C
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_19_MID                            0x215D
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_19_HIGH                           0x215E
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_19_RESVD                          0x215F
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_20_LOW                            0x2160
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_20_MID                            0x2161
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_20_HIGH                           0x2162
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_20_RESVD                          0x2163
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_21_LOW                            0x2164
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_21_MID                            0x2165
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_21_HIGH                           0x2166
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_21_RESVD                          0x2167
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_22_LOW                            0x2168
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_22_MID                            0x2169
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_22_HIGH                           0x216A
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_22_RESVD                          0x216B
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_23_LOW                            0x216C
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_23_MID                            0x216D
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_23_HIGH                           0x216E
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_23_RESVD                          0x216F
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_24_LOW                            0x2170
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_24_MID                            0x2171
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_24_HIGH                           0x2172
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_24_RESVD                          0x2173
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_25_LOW                            0x2174
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_25_MID                            0x2175
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_25_HIGH                           0x2176
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_25_RESVD                          0x2177
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_26_LOW                            0x2178
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_26_MID                            0x2179
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_26_HIGH                           0x217a
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_26_RESVD                          0x217b
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_27_LOW                            0x217c
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_27_MID                            0x217d
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_27_HIGH                           0x217e
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_27_RESVD                          0x217f
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_28_LOW                            0x2180
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_28_MID                            0x2181
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_28_HIGH                           0x2182
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_28_RESVD                          0x2183
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_29_LOW                            0x2184
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_29_MID                            0x2185
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_29_HIGH                           0x2186
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_29_RESVD                          0x2187
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_30_LOW                            0x2188
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_30_MID                            0x2189
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_30_HIGH                           0x218A
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_30_RESVD                          0x218B
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_31_LOW                            0x218C
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_31_MID                            0x218D
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_31_HIGH                           0x218E
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_31_RESVD                          0x218F
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_32_LOW                            0x2190
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_32_MID                            0x2191
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_32_HIGH                           0x2192
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_32_RESVD                          0x2193
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW                            0x2194
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_33_MID                            0x2195
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_33_HIGH                           0x2196
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_33_RESVD                          0x2197
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_34_LOW                            0x2198
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_34_MID                            0x2199
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_34_HIGH                           0x219A
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_34_RESVD                          0x219B
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW                            0x219C
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_35_MID                            0x219D
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_35_HIGH                           0x219E
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_35_RESVD                          0x219F
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_36_LOW                            0x21A0
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_36_MID                            0x21A1
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_36_HIGH                           0x21A2
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_36_RESVD                          0x21A3
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_37_LOW                            0x21A4
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_37_MID                            0x21A5
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_37_HIGH                           0x21A6
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_37_RESVD                          0x21A7
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW                            0x21A8
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_38_MID                            0x21A9
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_38_HIGH                           0x21AA
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_38_RESVD                          0x21AB
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_39_LOW                            0x21AC
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_39_MID                            0x21AD
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_39_HIGH                           0x21AE
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_39_RESVD                          0x21AF
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW                            0x21B0
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_40_MID                            0x21B1
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_40_HIGH                           0x21B2
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_40_RESVD                          0x21B3
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_41_LOW                            0x21B4
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_41_MID                            0x21B5
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_41_HIGH                           0x21B6
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_41_RESVD                          0x21B7
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW                            0x21B8
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_42_MID                            0x21B9
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_42_HIGH                           0x21BA
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_42_RESVD                          0x21BB
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW                            0x21BC
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_43_MID                            0x21BD
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_43_HIGH                           0x21BE
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_43_RESVD                          0x21BF
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_44_LOW                            0x21C0
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_44_MID                            0x21C1
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_44_HIGH                           0x21C2
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_44_RESVD                          0x21C3
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_45_LOW                            0x21C4
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_45_MID                            0x21C5
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_45_HIGH                           0x21C6
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_45_RESVD                          0x21C7
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_46_LOW                            0x21C8
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_46_MID                            0x21C9
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_46_HIGH                           0x21CA
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_46_RESVD                          0x21CB
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_47_LOW                            0x21CC
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_47_MID                            0x21CD
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_47_HIGH                           0x21CE
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_47_RESVD                          0x21CF
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_48_LOW                            0x21D0
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_48_MID                            0x21D1
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_48_HIGH                           0x21D2
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_48_RESVD                          0x21D3
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_49_LOW                            0x21D4
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_49_MID                            0x21D5
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_49_HIGH                           0x21D6
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_49_RESVD                          0x21D7
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_50_LOW                            0x21D8
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_50_MID                            0x21D9
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_50_HIGH                           0x21DA
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_50_RESVD                          0x21DB
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_51_LOW                            0x21DC
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_51_MID                            0x21DD
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_51_HIGH                           0x21DE
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_51_RESVD                          0x21DF
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_52_LOW                            0x21E0
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_52_MID                            0x21E1
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_52_HIGH                           0x21E2
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_52_RESVD                          0x21E3
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_53_LOW                            0x21E4
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_53_MID                            0x21E5
-#define SUNI1x10GEXP_REG_MSTAT_COUNTER_53_HIGH                           0x21E6
-#define SUNI1x10GEXP_CNTR_MAC_ETHERNET_NUM                               51
-
-#define SUNI1x10GEXP_REG_IFLX_GLOBAL_CONFIG                              0x2200
-#define SUNI1x10GEXP_REG_IFLX_CHANNEL_PROVISION                          0x2201
-#define SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE                       0x2209
-#define SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_INTERRUPT                    0x220A
-#define SUNI1x10GEXP_REG_IFLX_INDIR_CHANNEL_ADDRESS                      0x220D
-#define SUNI1x10GEXP_REG_IFLX_INDIR_LOGICAL_FIFO_LOW_LIMIT_PROVISION     0x220E
-#define SUNI1x10GEXP_REG_IFLX_INDIR_LOGICAL_FIFO_HIGH_LIMIT              0x220F
-#define SUNI1x10GEXP_REG_IFLX_INDIR_FULL_ALMOST_FULL_STATUS_LIMIT        0x2210
-#define SUNI1x10GEXP_REG_IFLX_INDIR_EMPTY_ALMOST_EMPTY_STATUS_LIMIT      0x2211
-
-#define SUNI1x10GEXP_REG_PL4MOS_CONFIG                                   0x2240
-#define SUNI1x10GEXP_REG_PL4MOS_MASK                                     0x2241
-#define SUNI1x10GEXP_REG_PL4MOS_FAIRNESS_MASKING                         0x2242
-#define SUNI1x10GEXP_REG_PL4MOS_MAXBURST1                                0x2243
-#define SUNI1x10GEXP_REG_PL4MOS_MAXBURST2                                0x2244
-#define SUNI1x10GEXP_REG_PL4MOS_TRANSFER_SIZE                            0x2245
-
-#define SUNI1x10GEXP_REG_PL4ODP_CONFIG                                   0x2280
-#define SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK                           0x2282
-#define SUNI1x10GEXP_REG_PL4ODP_INTERRUPT                                0x2283
-#define SUNI1x10GEXP_REG_PL4ODP_CONFIG_MAX_T                             0x2284
-
-#define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_STATUS                        0x2300
-#define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_CHANGE                        0x2301
-#define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK                          0x2302
-#define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_LIMITS                        0x2303
-#define SUNI1x10GEXP_REG_PL4IO_CALENDAR_REPETITIONS                      0x2304
-#define SUNI1x10GEXP_REG_PL4IO_CONFIG                                    0x2305
-
-#define SUNI1x10GEXP_REG_TXXG_CONFIG_1                                   0x3040
-#define SUNI1x10GEXP_REG_TXXG_CONFIG_2                                   0x3041
-#define SUNI1x10GEXP_REG_TXXG_CONFIG_3                                   0x3042
-#define SUNI1x10GEXP_REG_TXXG_INTERRUPT                                  0x3043
-#define SUNI1x10GEXP_REG_TXXG_STATUS                                     0x3044
-#define SUNI1x10GEXP_REG_TXXG_MAX_FRAME_SIZE                             0x3045
-#define SUNI1x10GEXP_REG_TXXG_MIN_FRAME_SIZE                             0x3046
-#define SUNI1x10GEXP_REG_TXXG_SA_15_0                                    0x3047
-#define SUNI1x10GEXP_REG_TXXG_SA_31_16                                   0x3048
-#define SUNI1x10GEXP_REG_TXXG_SA_47_32                                   0x3049
-#define SUNI1x10GEXP_REG_TXXG_PAUSE_TIMER                                0x304D
-#define SUNI1x10GEXP_REG_TXXG_PAUSE_TIMER_INTERVAL                       0x304E
-#define SUNI1x10GEXP_REG_TXXG_FILTER_ERROR_COUNTER                       0x3051
-#define SUNI1x10GEXP_REG_TXXG_PAUSE_QUANTUM_CONFIG                       0x3052
-
-#define SUNI1x10GEXP_REG_XTEF_CTRL                                       0x3080
-#define SUNI1x10GEXP_REG_XTEF_INTERRUPT_STATUS                           0x3084
-#define SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE                           0x3085
-#define SUNI1x10GEXP_REG_XTEF_VISIBILITY                                 0x3086
-
-#define SUNI1x10GEXP_REG_TXOAM_OAM_CONFIG                                0x30C0
-#define SUNI1x10GEXP_REG_TXOAM_MINI_RATE_CONFIG                          0x30C1
-#define SUNI1x10GEXP_REG_TXOAM_MINI_GAP_FIFO_CONFIG                      0x30C2
-#define SUNI1x10GEXP_REG_TXOAM_P1P2_STATIC_VALUES                        0x30C3
-#define SUNI1x10GEXP_REG_TXOAM_P3P4_STATIC_VALUES                        0x30C4
-#define SUNI1x10GEXP_REG_TXOAM_P5P6_STATIC_VALUES                        0x30C5
-#define SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE                          0x30C6
-#define SUNI1x10GEXP_REG_TXOAM_INTERRUPT_STATUS                          0x30C7
-#define SUNI1x10GEXP_REG_TXOAM_INSERT_COUNT_LSB                          0x30C8
-#define SUNI1x10GEXP_REG_TXOAM_INSERT_COUNT_MSB                          0x30C9
-#define SUNI1x10GEXP_REG_TXOAM_OAM_MINI_COUNT_LSB                        0x30CA
-#define SUNI1x10GEXP_REG_TXOAM_OAM_MINI_COUNT_MSB                        0x30CB
-#define SUNI1x10GEXP_REG_TXOAM_P1P2_MINI_MASK                            0x30CC
-#define SUNI1x10GEXP_REG_TXOAM_P3P4_MINI_MASK                            0x30CD
-#define SUNI1x10GEXP_REG_TXOAM_P5P6_MINI_MASK                            0x30CE
-#define SUNI1x10GEXP_REG_TXOAM_COSET                                     0x30CF
-#define SUNI1x10GEXP_REG_TXOAM_EMPTY_FIFO_INS_OP_CNT_LSB                 0x30D0
-#define SUNI1x10GEXP_REG_TXOAM_EMPTY_FIFO_INS_OP_CNT_MSB                 0x30D1
-#define SUNI1x10GEXP_REG_TXOAM_STATIC_VALUE_MINI_COUNT_LSB               0x30D2
-#define SUNI1x10GEXP_REG_TXOAM_STATIC_VALUE_MINI_COUNT_MSB               0x30D3
-
-
-#define SUNI1x10GEXP_REG_EFLX_GLOBAL_CONFIG                              0x3200
-#define SUNI1x10GEXP_REG_EFLX_ERCU_GLOBAL_STATUS                         0x3201
-#define SUNI1x10GEXP_REG_EFLX_INDIR_CHANNEL_ADDRESS                      0x3202
-#define SUNI1x10GEXP_REG_EFLX_INDIR_FIFO_LOW_LIMIT                       0x3203
-#define SUNI1x10GEXP_REG_EFLX_INDIR_FIFO_HIGH_LIMIT                      0x3204
-#define SUNI1x10GEXP_REG_EFLX_INDIR_FULL_ALMOST_FULL_STATUS_AND_LIMIT    0x3205
-#define SUNI1x10GEXP_REG_EFLX_INDIR_EMPTY_ALMOST_EMPTY_STATUS_AND_LIMIT  0x3206
-#define SUNI1x10GEXP_REG_EFLX_INDIR_FIFO_CUT_THROUGH_THRESHOLD           0x3207
-#define SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE                 0x320C
-#define SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_INDICATION             0x320D
-#define SUNI1x10GEXP_REG_EFLX_CHANNEL_PROVISION                          0x3210
-
-#define SUNI1x10GEXP_REG_PL4IDU_CONFIG                                   0x3280
-#define SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK                           0x3282
-#define SUNI1x10GEXP_REG_PL4IDU_INTERRUPT                                0x3283
-
-
-/*----------------------------------------*/
-#define SUNI1x10GEXP_REG_MAX_OFFSET                                      0x3480
-
-/******************************************************************************/
-/*                 -- End register offset definitions --                      */
-/******************************************************************************/
-
-/******************************************************************************/
-/** SUNI-1x10GE-XP REGISTER BIT MASKS                                        **/
-/******************************************************************************/
-
-#define SUNI1x10GEXP_BITMSK_BITS_1   0x00001
-#define SUNI1x10GEXP_BITMSK_BITS_2   0x00003
-#define SUNI1x10GEXP_BITMSK_BITS_3   0x00007
-#define SUNI1x10GEXP_BITMSK_BITS_4   0x0000f
-#define SUNI1x10GEXP_BITMSK_BITS_5   0x0001f
-#define SUNI1x10GEXP_BITMSK_BITS_6   0x0003f
-#define SUNI1x10GEXP_BITMSK_BITS_7   0x0007f
-#define SUNI1x10GEXP_BITMSK_BITS_8   0x000ff
-#define SUNI1x10GEXP_BITMSK_BITS_9   0x001ff
-#define SUNI1x10GEXP_BITMSK_BITS_10  0x003ff
-#define SUNI1x10GEXP_BITMSK_BITS_11  0x007ff
-#define SUNI1x10GEXP_BITMSK_BITS_12  0x00fff
-#define SUNI1x10GEXP_BITMSK_BITS_13  0x01fff
-#define SUNI1x10GEXP_BITMSK_BITS_14  0x03fff
-#define SUNI1x10GEXP_BITMSK_BITS_15  0x07fff
-#define SUNI1x10GEXP_BITMSK_BITS_16  0x0ffff
-
-#define mSUNI1x10GEXP_CLR_MSBITS_1(v)  ((v) & SUNI1x10GEXP_BITMSK_BITS_15)
-#define mSUNI1x10GEXP_CLR_MSBITS_2(v)  ((v) & SUNI1x10GEXP_BITMSK_BITS_14)
-#define mSUNI1x10GEXP_CLR_MSBITS_3(v)  ((v) & SUNI1x10GEXP_BITMSK_BITS_13)
-#define mSUNI1x10GEXP_CLR_MSBITS_4(v)  ((v) & SUNI1x10GEXP_BITMSK_BITS_12)
-#define mSUNI1x10GEXP_CLR_MSBITS_5(v)  ((v) & SUNI1x10GEXP_BITMSK_BITS_11)
-#define mSUNI1x10GEXP_CLR_MSBITS_6(v)  ((v) & SUNI1x10GEXP_BITMSK_BITS_10)
-#define mSUNI1x10GEXP_CLR_MSBITS_7(v)  ((v) & SUNI1x10GEXP_BITMSK_BITS_9)
-#define mSUNI1x10GEXP_CLR_MSBITS_8(v)  ((v) & SUNI1x10GEXP_BITMSK_BITS_8)
-#define mSUNI1x10GEXP_CLR_MSBITS_9(v)  ((v) & SUNI1x10GEXP_BITMSK_BITS_7)
-#define mSUNI1x10GEXP_CLR_MSBITS_10(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_6)
-#define mSUNI1x10GEXP_CLR_MSBITS_11(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_5)
-#define mSUNI1x10GEXP_CLR_MSBITS_12(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_4)
-#define mSUNI1x10GEXP_CLR_MSBITS_13(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_3)
-#define mSUNI1x10GEXP_CLR_MSBITS_14(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_2)
-#define mSUNI1x10GEXP_CLR_MSBITS_15(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_1)
-
-#define mSUNI1x10GEXP_GET_BIT(val, bitMsk) (((val)&(bitMsk)) ? 1:0)
-
-
-
-/*----------------------------------------------------------------------------
- * Register 0x0001: S/UNI-1x10GE-XP Product Revision
- *    Bit 3-0  REVISION
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_REVISION  0x000F
-
-/*----------------------------------------------------------------------------
- * Register 0x0002: S/UNI-1x10GE-XP Configuration and Reset Control
- *    Bit 2  XAUI_ARESETB
- *    Bit 1  PL4_ARESETB
- *    Bit 0  DRESETB
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_XAUI_ARESET  0x0004
-#define SUNI1x10GEXP_BITMSK_PL4_ARESET   0x0002
-#define SUNI1x10GEXP_BITMSK_DRESETB      0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x0003: S/UNI-1x10GE-XP Loop Back and Miscellaneous Control
- *    Bit 11  PL4IO_OUTCLKSEL
- *    Bit 9   SYSPCSLB
- *    Bit 8   LINEPCSLB
- *    Bit 7   MSTAT_BYPASS
- *    Bit 6   RXXG_BYPASS
- *    Bit 5   TXXG_BYPASS
- *    Bit 4   SOP_PAD_EN
- *    Bit 1   LOS_INV
- *    Bit 0   OVERRIDE_LOS
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4IO_OUTCLKSEL  0x0800
-#define SUNI1x10GEXP_BITMSK_SYSPCSLB         0x0200
-#define SUNI1x10GEXP_BITMSK_LINEPCSLB        0x0100
-#define SUNI1x10GEXP_BITMSK_MSTAT_BYPASS     0x0080
-#define SUNI1x10GEXP_BITMSK_RXXG_BYPASS      0x0040
-#define SUNI1x10GEXP_BITMSK_TXXG_BYPASS      0x0020
-#define SUNI1x10GEXP_BITMSK_SOP_PAD_EN       0x0010
-#define SUNI1x10GEXP_BITMSK_LOS_INV          0x0002
-#define SUNI1x10GEXP_BITMSK_OVERRIDE_LOS     0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x0004: S/UNI-1x10GE-XP Device Status
- *    Bit 9 TOP_SXRA_EXPIRED
- *    Bit 8 TOP_MDIO_BUSY
- *    Bit 7 TOP_DTRB
- *    Bit 6 TOP_EXPIRED
- *    Bit 5 TOP_PAUSED
- *    Bit 4 TOP_PL4_ID_DOOL
- *    Bit 3 TOP_PL4_IS_DOOL
- *    Bit 2 TOP_PL4_ID_ROOL
- *    Bit 1 TOP_PL4_IS_ROOL
- *    Bit 0 TOP_PL4_OUT_ROOL
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TOP_SXRA_EXPIRED  0x0200
-#define SUNI1x10GEXP_BITMSK_TOP_MDIO_BUSY     0x0100
-#define SUNI1x10GEXP_BITMSK_TOP_DTRB          0x0080
-#define SUNI1x10GEXP_BITMSK_TOP_EXPIRED       0x0040
-#define SUNI1x10GEXP_BITMSK_TOP_PAUSED        0x0020
-#define SUNI1x10GEXP_BITMSK_TOP_PL4_ID_DOOL   0x0010
-#define SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL   0x0008
-#define SUNI1x10GEXP_BITMSK_TOP_PL4_ID_ROOL   0x0004
-#define SUNI1x10GEXP_BITMSK_TOP_PL4_IS_ROOL   0x0002
-#define SUNI1x10GEXP_BITMSK_TOP_PL4_OUT_ROOL  0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x0005: Global Performance Update and Clock Monitors
- *    Bit 15 TIP
- *    Bit 8  XAUI_REF_CLKA
- *    Bit 7  RXLANE3CLKA
- *    Bit 6  RXLANE2CLKA
- *    Bit 5  RXLANE1CLKA
- *    Bit 4  RXLANE0CLKA
- *    Bit 3  CSUCLKA
- *    Bit 2  TDCLKA
- *    Bit 1  RSCLKA
- *    Bit 0  RDCLKA
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TIP            0x8000
-#define SUNI1x10GEXP_BITMSK_XAUI_REF_CLKA  0x0100
-#define SUNI1x10GEXP_BITMSK_RXLANE3CLKA    0x0080
-#define SUNI1x10GEXP_BITMSK_RXLANE2CLKA    0x0040
-#define SUNI1x10GEXP_BITMSK_RXLANE1CLKA    0x0020
-#define SUNI1x10GEXP_BITMSK_RXLANE0CLKA    0x0010
-#define SUNI1x10GEXP_BITMSK_CSUCLKA        0x0008
-#define SUNI1x10GEXP_BITMSK_TDCLKA         0x0004
-#define SUNI1x10GEXP_BITMSK_RSCLKA         0x0002
-#define SUNI1x10GEXP_BITMSK_RDCLKA         0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x0006: MDIO Command
- *    Bit 4 MDIO_RDINC
- *    Bit 3 MDIO_RSTAT
- *    Bit 2 MDIO_LCTLD
- *    Bit 1 MDIO_LCTLA
- *    Bit 0 MDIO_SPRE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_MDIO_RDINC  0x0010
-#define SUNI1x10GEXP_BITMSK_MDIO_RSTAT  0x0008
-#define SUNI1x10GEXP_BITMSK_MDIO_LCTLD  0x0004
-#define SUNI1x10GEXP_BITMSK_MDIO_LCTLA  0x0002
-#define SUNI1x10GEXP_BITMSK_MDIO_SPRE   0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x0007: MDIO Interrupt Enable
- *    Bit 0 MDIO_BUSY_EN
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_MDIO_BUSY_EN  0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x0008: MDIO Interrupt Status
- *    Bit 0 MDIO_BUSYI
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_MDIO_BUSYI  0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x0009: MMD PHY Address
- *    Bit 12-8 MDIO_DEVADR
- *    Bit 4-0 MDIO_PRTADR
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_MDIO_DEVADR  0x1F00
-#define SUNI1x10GEXP_BITOFF_MDIO_DEVADR  8
-#define SUNI1x10GEXP_BITMSK_MDIO_PRTADR  0x001F
-#define SUNI1x10GEXP_BITOFF_MDIO_PRTADR  0
-
-/*----------------------------------------------------------------------------
- * Register 0x000C: OAM Interface Control
- *    Bit 6 MDO_OD_ENB
- *    Bit 5 MDI_INV
- *    Bit 4 MDI_SEL
- *    Bit 3 RXOAMEN
- *    Bit 2 RXOAMCLKEN
- *    Bit 1 TXOAMEN
- *    Bit 0 TXOAMCLKEN
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_MDO_OD_ENB  0x0040
-#define SUNI1x10GEXP_BITMSK_MDI_INV     0x0020
-#define SUNI1x10GEXP_BITMSK_MDI_SEL     0x0010
-#define SUNI1x10GEXP_BITMSK_RXOAMEN     0x0008
-#define SUNI1x10GEXP_BITMSK_RXOAMCLKEN  0x0004
-#define SUNI1x10GEXP_BITMSK_TXOAMEN     0x0002
-#define SUNI1x10GEXP_BITMSK_TXOAMCLKEN  0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x000D: S/UNI-1x10GE-XP Master Interrupt Status
- *    Bit 15 TOP_PL4IO_INT
- *    Bit 14 TOP_IRAM_INT
- *    Bit 13 TOP_ERAM_INT
- *    Bit 12 TOP_XAUI_INT
- *    Bit 11 TOP_MSTAT_INT
- *    Bit 10 TOP_RXXG_INT
- *    Bit 9 TOP_TXXG_INT
- *    Bit 8 TOP_XRF_INT
- *    Bit 7 TOP_XTEF_INT
- *    Bit 6 TOP_MDIO_BUSY_INT
- *    Bit 5 TOP_RXOAM_INT
- *    Bit 4 TOP_TXOAM_INT
- *    Bit 3 TOP_IFLX_INT
- *    Bit 2 TOP_EFLX_INT
- *    Bit 1 TOP_PL4ODP_INT
- *    Bit 0 TOP_PL4IDU_INT
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TOP_PL4IO_INT      0x8000
-#define SUNI1x10GEXP_BITMSK_TOP_IRAM_INT       0x4000
-#define SUNI1x10GEXP_BITMSK_TOP_ERAM_INT       0x2000
-#define SUNI1x10GEXP_BITMSK_TOP_XAUI_INT       0x1000
-#define SUNI1x10GEXP_BITMSK_TOP_MSTAT_INT      0x0800
-#define SUNI1x10GEXP_BITMSK_TOP_RXXG_INT       0x0400
-#define SUNI1x10GEXP_BITMSK_TOP_TXXG_INT       0x0200
-#define SUNI1x10GEXP_BITMSK_TOP_XRF_INT        0x0100
-#define SUNI1x10GEXP_BITMSK_TOP_XTEF_INT       0x0080
-#define SUNI1x10GEXP_BITMSK_TOP_MDIO_BUSY_INT  0x0040
-#define SUNI1x10GEXP_BITMSK_TOP_RXOAM_INT      0x0020
-#define SUNI1x10GEXP_BITMSK_TOP_TXOAM_INT      0x0010
-#define SUNI1x10GEXP_BITMSK_TOP_IFLX_INT       0x0008
-#define SUNI1x10GEXP_BITMSK_TOP_EFLX_INT       0x0004
-#define SUNI1x10GEXP_BITMSK_TOP_PL4ODP_INT     0x0002
-#define SUNI1x10GEXP_BITMSK_TOP_PL4IDU_INT     0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x000E:PM3393 Global interrupt enable
- *    Bit 15 TOP_INTE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TOP_INTE  0x8000
-
-/*----------------------------------------------------------------------------
- * Register 0x0010: XTEF Miscellaneous Control
- *    Bit 7 RF_VAL
- *    Bit 6 RF_OVERRIDE
- *    Bit 5 LF_VAL
- *    Bit 4 LF_OVERRIDE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RF_VAL             0x0080
-#define SUNI1x10GEXP_BITMSK_RF_OVERRIDE        0x0040
-#define SUNI1x10GEXP_BITMSK_LF_VAL             0x0020
-#define SUNI1x10GEXP_BITMSK_LF_OVERRIDE        0x0010
-#define SUNI1x10GEXP_BITMSK_LFRF_OVERRIDE_VAL  0x00F0
-
-/*----------------------------------------------------------------------------
- * Register 0x0011: XRF Miscellaneous Control
- *    Bit 6-4 EN_IDLE_REP
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_EN_IDLE_REP  0x0070
-
-/*----------------------------------------------------------------------------
- * Register 0x0100: SERDES 3125 Configuration Register 1
- *    Bit 10 RXEQB_3
- *    Bit 8  RXEQB_2
- *    Bit 6  RXEQB_1
- *    Bit 4  RXEQB_0
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RXEQB    0x0FF0
-#define SUNI1x10GEXP_BITOFF_RXEQB_3  10
-#define SUNI1x10GEXP_BITOFF_RXEQB_2  8
-#define SUNI1x10GEXP_BITOFF_RXEQB_1  6
-#define SUNI1x10GEXP_BITOFF_RXEQB_0  4
-
-/*----------------------------------------------------------------------------
- * Register 0x0101: SERDES 3125 Configuration Register 2
- *    Bit 12 YSEL
- *    Bit  7 PRE_EMPH_3
- *    Bit  6 PRE_EMPH_2
- *    Bit  5 PRE_EMPH_1
- *    Bit  4 PRE_EMPH_0
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_YSEL        0x1000
-#define SUNI1x10GEXP_BITMSK_PRE_EMPH    0x00F0
-#define SUNI1x10GEXP_BITMSK_PRE_EMPH_3  0x0080
-#define SUNI1x10GEXP_BITMSK_PRE_EMPH_2  0x0040
-#define SUNI1x10GEXP_BITMSK_PRE_EMPH_1  0x0020
-#define SUNI1x10GEXP_BITMSK_PRE_EMPH_0  0x0010
-
-/*----------------------------------------------------------------------------
- * Register 0x0102: SERDES 3125 Interrupt Enable Register
- *    Bit 3 LASIE
- *    Bit 2 SPLL_RAE
- *    Bit 1 MPLL_RAE
- *    Bit 0 PLL_LOCKE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_LASIE      0x0008
-#define SUNI1x10GEXP_BITMSK_SPLL_RAE   0x0004
-#define SUNI1x10GEXP_BITMSK_MPLL_RAE   0x0002
-#define SUNI1x10GEXP_BITMSK_PLL_LOCKE  0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x0103: SERDES 3125 Interrupt Visibility Register
- *    Bit 3 LASIV
- *    Bit 2 SPLL_RAV
- *    Bit 1 MPLL_RAV
- *    Bit 0 PLL_LOCKV
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_LASIV      0x0008
-#define SUNI1x10GEXP_BITMSK_SPLL_RAV   0x0004
-#define SUNI1x10GEXP_BITMSK_MPLL_RAV   0x0002
-#define SUNI1x10GEXP_BITMSK_PLL_LOCKV  0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x0104: SERDES 3125 Interrupt Status Register
- *    Bit 3 LASII
- *    Bit 2 SPLL_RAI
- *    Bit 1 MPLL_RAI
- *    Bit 0 PLL_LOCKI
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_LASII      0x0008
-#define SUNI1x10GEXP_BITMSK_SPLL_RAI   0x0004
-#define SUNI1x10GEXP_BITMSK_MPLL_RAI   0x0002
-#define SUNI1x10GEXP_BITMSK_PLL_LOCKI  0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x0107: SERDES 3125 Test Configuration
- *    Bit 12 DUALTX
- *    Bit 10 HC_1
- *    Bit  9 HC_0
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_DUALTX  0x1000
-#define SUNI1x10GEXP_BITMSK_HC      0x0600
-#define SUNI1x10GEXP_BITOFF_HC_0    9
-
-/*----------------------------------------------------------------------------
- * Register 0x2040: RXXG Configuration 1
- *    Bit 15  RXXG_RXEN
- *    Bit 14  RXXG_ROCF
- *    Bit 13  RXXG_PAD_STRIP
- *    Bit 10  RXXG_PUREP
- *    Bit 9   RXXG_LONGP
- *    Bit 8   RXXG_PARF
- *    Bit 7   RXXG_FLCHK
- *    Bit 5   RXXG_PASS_CTRL
- *    Bit 3   RXXG_CRC_STRIP
- *    Bit 2-0 RXXG_MIFG
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RXXG_RXEN       0x8000
-#define SUNI1x10GEXP_BITMSK_RXXG_ROCF       0x4000
-#define SUNI1x10GEXP_BITMSK_RXXG_PAD_STRIP  0x2000
-#define SUNI1x10GEXP_BITMSK_RXXG_PUREP      0x0400
-#define SUNI1x10GEXP_BITMSK_RXXG_LONGP      0x0200
-#define SUNI1x10GEXP_BITMSK_RXXG_PARF       0x0100
-#define SUNI1x10GEXP_BITMSK_RXXG_FLCHK      0x0080
-#define SUNI1x10GEXP_BITMSK_RXXG_PASS_CTRL  0x0020
-#define SUNI1x10GEXP_BITMSK_RXXG_CRC_STRIP  0x0008
-
-/*----------------------------------------------------------------------------
- * Register 0x02041: RXXG Configuration 2
- *    Bit 7-0 RXXG_HDRSIZE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RXXG_HDRSIZE  0x00FF
-
-/*----------------------------------------------------------------------------
- * Register 0x2042: RXXG Configuration 3
- *    Bit 15 RXXG_MIN_LERRE
- *    Bit 14 RXXG_MAX_LERRE
- *    Bit 12 RXXG_LINE_ERRE
- *    Bit 10 RXXG_RX_OVRE
- *    Bit 9  RXXG_ADR_FILTERE
- *    Bit 8  RXXG_ERR_FILTERE
- *    Bit 5  RXXG_PRMB_ERRE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RXXG_MIN_LERRE     0x8000
-#define SUNI1x10GEXP_BITMSK_RXXG_MAX_LERRE     0x4000
-#define SUNI1x10GEXP_BITMSK_RXXG_LINE_ERRE     0x1000
-#define SUNI1x10GEXP_BITMSK_RXXG_RX_OVRE       0x0400
-#define SUNI1x10GEXP_BITMSK_RXXG_ADR_FILTERE   0x0200
-#define SUNI1x10GEXP_BITMSK_RXXG_ERR_FILTERRE  0x0100
-#define SUNI1x10GEXP_BITMSK_RXXG_PRMB_ERRE     0x0020
-
-/*----------------------------------------------------------------------------
- * Register 0x2043: RXXG Interrupt
- *    Bit 15 RXXG_MIN_LERRI
- *    Bit 14 RXXG_MAX_LERRI
- *    Bit 12 RXXG_LINE_ERRI
- *    Bit 10 RXXG_RX_OVRI
- *    Bit 9  RXXG_ADR_FILTERI
- *    Bit 8  RXXG_ERR_FILTERI
- *    Bit 5  RXXG_PRMB_ERRE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RXXG_MIN_LERRI    0x8000
-#define SUNI1x10GEXP_BITMSK_RXXG_MAX_LERRI    0x4000
-#define SUNI1x10GEXP_BITMSK_RXXG_LINE_ERRI    0x1000
-#define SUNI1x10GEXP_BITMSK_RXXG_RX_OVRI      0x0400
-#define SUNI1x10GEXP_BITMSK_RXXG_ADR_FILTERI  0x0200
-#define SUNI1x10GEXP_BITMSK_RXXG_ERR_FILTERI  0x0100
-#define SUNI1x10GEXP_BITMSK_RXXG_PRMB_ERRE    0x0020
-
-/*----------------------------------------------------------------------------
- * Register 0x2049: RXXG Receive FIFO Threshold
- *    Bit 2-0 RXXG_CUT_THRU
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RXXG_CUT_THRU  0x0007
-#define SUNI1x10GEXP_BITOFF_RXXG_CUT_THRU  0
-
-/*----------------------------------------------------------------------------
- * Register 0x2062H - 0x2069: RXXG Exact Match VID
- *    Bit 11-0 RXXG_VID_MATCH
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RXXG_VID_MATCH  0x0FFF
-#define SUNI1x10GEXP_BITOFF_RXXG_VID_MATCH  0
-
-/*----------------------------------------------------------------------------
- * Register 0x206EH - 0x206F: RXXG Address Filter Control
- *    Bit 3 RXXG_FORWARD_ENABLE
- *    Bit 2 RXXG_VLAN_ENABLE
- *    Bit 1 RXXG_SRC_ADDR
- *    Bit 0 RXXG_MATCH_ENABLE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RXXG_FORWARD_ENABLE  0x0008
-#define SUNI1x10GEXP_BITMSK_RXXG_VLAN_ENABLE     0x0004
-#define SUNI1x10GEXP_BITMSK_RXXG_SRC_ADDR        0x0002
-#define SUNI1x10GEXP_BITMSK_RXXG_MATCH_ENABLE    0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x2070: RXXG Address Filter Control 2
- *    Bit 1 RXXG_PMODE
- *    Bit 0 RXXG_MHASH_EN
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RXXG_PMODE     0x0002
-#define SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN  0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x2081: XRF Control Register 2
- *    Bit 6   EN_PKT_GEN
- *    Bit 4-2 PATT
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_EN_PKT_GEN  0x0040
-#define SUNI1x10GEXP_BITMSK_PATT        0x001C
-#define SUNI1x10GEXP_BITOFF_PATT        2
-
-/*----------------------------------------------------------------------------
- * Register 0x2088: XRF Interrupt Enable
- *    Bit 12-9 LANE_HICERE
- *    Bit 8-5  HS_SD_LANEE
- *    Bit 4    ALIGN_STATUS_ERRE
- *    Bit 3-0  LANE_SYNC_STAT_ERRE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_LANE_HICERE          0x1E00
-#define SUNI1x10GEXP_BITOFF_LANE_HICERE          9
-#define SUNI1x10GEXP_BITMSK_HS_SD_LANEE          0x01E0
-#define SUNI1x10GEXP_BITOFF_HS_SD_LANEE          5
-#define SUNI1x10GEXP_BITMSK_ALIGN_STATUS_ERRE    0x0010
-#define SUNI1x10GEXP_BITMSK_LANE_SYNC_STAT_ERRE  0x000F
-#define SUNI1x10GEXP_BITOFF_LANE_SYNC_STAT_ERRE  0
-
-/*----------------------------------------------------------------------------
- * Register 0x2089: XRF Interrupt Status
- *    Bit 12-9 LANE_HICERI
- *    Bit 8-5  HS_SD_LANEI
- *    Bit 4    ALIGN_STATUS_ERRI
- *    Bit 3-0  LANE_SYNC_STAT_ERRI
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_LANE_HICERI          0x1E00
-#define SUNI1x10GEXP_BITOFF_LANE_HICERI          9
-#define SUNI1x10GEXP_BITMSK_HS_SD_LANEI          0x01E0
-#define SUNI1x10GEXP_BITOFF_HS_SD_LANEI          5
-#define SUNI1x10GEXP_BITMSK_ALIGN_STATUS_ERRI    0x0010
-#define SUNI1x10GEXP_BITMSK_LANE_SYNC_STAT_ERRI  0x000F
-#define SUNI1x10GEXP_BITOFF_LANE_SYNC_STAT_ERRI  0
-
-/*----------------------------------------------------------------------------
- * Register 0x208A: XRF Error Status
- *    Bit 8-5  HS_SD_LANE
- *    Bit 4    ALIGN_STATUS_ERR
- *    Bit 3-0  LANE_SYNC_STAT_ERR
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_HS_SD_LANE3          0x0100
-#define SUNI1x10GEXP_BITMSK_HS_SD_LANE2          0x0080
-#define SUNI1x10GEXP_BITMSK_HS_SD_LANE1          0x0040
-#define SUNI1x10GEXP_BITMSK_HS_SD_LANE0          0x0020
-#define SUNI1x10GEXP_BITMSK_ALIGN_STATUS_ERR     0x0010
-#define SUNI1x10GEXP_BITMSK_LANE3_SYNC_STAT_ERR  0x0008
-#define SUNI1x10GEXP_BITMSK_LANE2_SYNC_STAT_ERR  0x0004
-#define SUNI1x10GEXP_BITMSK_LANE1_SYNC_STAT_ERR  0x0002
-#define SUNI1x10GEXP_BITMSK_LANE0_SYNC_STAT_ERR  0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x208B: XRF Diagnostic Interrupt Enable
- *    Bit 7-4 LANE_OVERRUNE
- *    Bit 3-0 LANE_UNDERRUNE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_LANE_OVERRUNE   0x00F0
-#define SUNI1x10GEXP_BITOFF_LANE_OVERRUNE   4
-#define SUNI1x10GEXP_BITMSK_LANE_UNDERRUNE  0x000F
-#define SUNI1x10GEXP_BITOFF_LANE_UNDERRUNE  0
-
-/*----------------------------------------------------------------------------
- * Register 0x208C: XRF Diagnostic Interrupt Status
- *    Bit 7-4 LANE_OVERRUNI
- *    Bit 3-0 LANE_UNDERRUNI
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_LANE_OVERRUNI   0x00F0
-#define SUNI1x10GEXP_BITOFF_LANE_OVERRUNI   4
-#define SUNI1x10GEXP_BITMSK_LANE_UNDERRUNI  0x000F
-#define SUNI1x10GEXP_BITOFF_LANE_UNDERRUNI  0
-
-/*----------------------------------------------------------------------------
- * Register 0x20C0: RXOAM Configuration
- *    Bit 15    RXOAM_BUSY
- *    Bit 14-12 RXOAM_F2_SEL
- *    Bit 10-8  RXOAM_F1_SEL
- *    Bit 7-6   RXOAM_FILTER_CTRL
- *    Bit 5-0   RXOAM_PX_EN
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RXOAM_BUSY         0x8000
-#define SUNI1x10GEXP_BITMSK_RXOAM_F2_SEL       0x7000
-#define SUNI1x10GEXP_BITOFF_RXOAM_F2_SEL       12
-#define SUNI1x10GEXP_BITMSK_RXOAM_F1_SEL       0x0700
-#define SUNI1x10GEXP_BITOFF_RXOAM_F1_SEL       8
-#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_CTRL  0x00C0
-#define SUNI1x10GEXP_BITOFF_RXOAM_FILTER_CTRL  6
-#define SUNI1x10GEXP_BITMSK_RXOAM_PX_EN        0x003F
-#define SUNI1x10GEXP_BITOFF_RXOAM_PX_EN        0
-
-/*----------------------------------------------------------------------------
- * Register 0x20C1,0x20C2: RXOAM Filter Configuration
- *    Bit 15-8 RXOAM_FX_MASK
- *    Bit 7-0  RXOAM_FX_VAL
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RXOAM_FX_MASK  0xFF00
-#define SUNI1x10GEXP_BITOFF_RXOAM_FX_MASK  8
-#define SUNI1x10GEXP_BITMSK_RXOAM_FX_VAL   0x00FF
-#define SUNI1x10GEXP_BITOFF_RXOAM_FX_VAl   0
-
-/*----------------------------------------------------------------------------
- * Register 0x20C3: RXOAM Configuration Register 2
- *    Bit 13    RXOAM_REC_BYTE_VAL
- *    Bit 11-10 RXOAM_BYPASS_MODE
- *    Bit 5-0   RXOAM_PX_CLEAR
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RXOAM_REC_BYTE_VAL  0x2000
-#define SUNI1x10GEXP_BITMSK_RXOAM_BYPASS_MODE   0x0C00
-#define SUNI1x10GEXP_BITOFF_RXOAM_BYPASS_MODE   10
-#define SUNI1x10GEXP_BITMSK_RXOAM_PX_CLEAR      0x003F
-#define SUNI1x10GEXP_BITOFF_RXOAM_PX_CLEAR      0
-
-/*----------------------------------------------------------------------------
- * Register 0x20C4: RXOAM HEC Configuration
- *    Bit 15-8 RXOAM_COSET
- *    Bit 2    RXOAM_HEC_ERR_PKT
- *    Bit 0    RXOAM_HEC_EN
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RXOAM_COSET        0xFF00
-#define SUNI1x10GEXP_BITOFF_RXOAM_COSET        8
-#define SUNI1x10GEXP_BITMSK_RXOAM_HEC_ERR_PKT  0x0004
-#define SUNI1x10GEXP_BITMSK_RXOAM_HEC_EN       0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x20C7: RXOAM Interrupt Enable
- *    Bit 10 RXOAM_FILTER_THRSHE
- *    Bit 9  RXOAM_OAM_ERRE
- *    Bit 8  RXOAM_HECE_THRSHE
- *    Bit 7  RXOAM_SOPE
- *    Bit 6  RXOAM_RFE
- *    Bit 5  RXOAM_LFE
- *    Bit 4  RXOAM_DV_ERRE
- *    Bit 3  RXOAM_DATA_INVALIDE
- *    Bit 2  RXOAM_FILTER_DROPE
- *    Bit 1  RXOAM_HECE
- *    Bit 0  RXOAM_OFLE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_THRSHE  0x0400
-#define SUNI1x10GEXP_BITMSK_RXOAM_OAM_ERRE       0x0200
-#define SUNI1x10GEXP_BITMSK_RXOAM_HECE_THRSHE    0x0100
-#define SUNI1x10GEXP_BITMSK_RXOAM_SOPE           0x0080
-#define SUNI1x10GEXP_BITMSK_RXOAM_RFE            0x0040
-#define SUNI1x10GEXP_BITMSK_RXOAM_LFE            0x0020
-#define SUNI1x10GEXP_BITMSK_RXOAM_DV_ERRE        0x0010
-#define SUNI1x10GEXP_BITMSK_RXOAM_DATA_INVALIDE  0x0008
-#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_DROPE   0x0004
-#define SUNI1x10GEXP_BITMSK_RXOAM_HECE           0x0002
-#define SUNI1x10GEXP_BITMSK_RXOAM_OFLE           0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x20C8: RXOAM Interrupt Status
- *    Bit 10 RXOAM_FILTER_THRSHI
- *    Bit 9  RXOAM_OAM_ERRI
- *    Bit 8  RXOAM_HECE_THRSHI
- *    Bit 7  RXOAM_SOPI
- *    Bit 6  RXOAM_RFI
- *    Bit 5  RXOAM_LFI
- *    Bit 4  RXOAM_DV_ERRI
- *    Bit 3  RXOAM_DATA_INVALIDI
- *    Bit 2  RXOAM_FILTER_DROPI
- *    Bit 1  RXOAM_HECI
- *    Bit 0  RXOAM_OFLI
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_THRSHI  0x0400
-#define SUNI1x10GEXP_BITMSK_RXOAM_OAM_ERRI       0x0200
-#define SUNI1x10GEXP_BITMSK_RXOAM_HECE_THRSHI    0x0100
-#define SUNI1x10GEXP_BITMSK_RXOAM_SOPI           0x0080
-#define SUNI1x10GEXP_BITMSK_RXOAM_RFI            0x0040
-#define SUNI1x10GEXP_BITMSK_RXOAM_LFI            0x0020
-#define SUNI1x10GEXP_BITMSK_RXOAM_DV_ERRI        0x0010
-#define SUNI1x10GEXP_BITMSK_RXOAM_DATA_INVALIDI  0x0008
-#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_DROPI   0x0004
-#define SUNI1x10GEXP_BITMSK_RXOAM_HECI           0x0002
-#define SUNI1x10GEXP_BITMSK_RXOAM_OFLI           0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x20C9: RXOAM Status
- *    Bit 10 RXOAM_FILTER_THRSHV
- *    Bit 8  RXOAM_HECE_THRSHV
- *    Bit 6  RXOAM_RFV
- *    Bit 5  RXOAM_LFV
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_THRSHV  0x0400
-#define SUNI1x10GEXP_BITMSK_RXOAM_HECE_THRSHV    0x0100
-#define SUNI1x10GEXP_BITMSK_RXOAM_RFV            0x0040
-#define SUNI1x10GEXP_BITMSK_RXOAM_LFV            0x0020
-
-/*----------------------------------------------------------------------------
- * Register 0x2100: MSTAT Control
- *    Bit 2 MSTAT_WRITE
- *    Bit 1 MSTAT_CLEAR
- *    Bit 0 MSTAT_SNAP
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_MSTAT_WRITE  0x0004
-#define SUNI1x10GEXP_BITMSK_MSTAT_CLEAR  0x0002
-#define SUNI1x10GEXP_BITMSK_MSTAT_SNAP   0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x2109: MSTAT Counter Write Address
- *    Bit 5-0 MSTAT_WRITE_ADDRESS
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_MSTAT_WRITE_ADDRESS 0x003F
-#define SUNI1x10GEXP_BITOFF_MSTAT_WRITE_ADDRESS 0
-
-/*----------------------------------------------------------------------------
- * Register 0x2200: IFLX Global Configuration Register
- *    Bit 15   IFLX_IRCU_ENABLE
- *    Bit 14   IFLX_IDSWT_ENABLE
- *    Bit 13-0 IFLX_IFD_CNT
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_IFLX_IRCU_ENABLE   0x8000
-#define SUNI1x10GEXP_BITMSK_IFLX_IDSWT_ENABLE  0x4000
-#define SUNI1x10GEXP_BITMSK_IFLX_IFD_CNT       0x3FFF
-#define SUNI1x10GEXP_BITOFF_IFLX_IFD_CNT       0
-
-/*----------------------------------------------------------------------------
- * Register 0x2209: IFLX FIFO Overflow Enable
- *    Bit 0 IFLX_OVFE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_IFLX_OVFE 0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x220A: IFLX FIFO Overflow Interrupt
- *    Bit 0 IFLX_OVFI
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_IFLX_OVFI 0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x220D: IFLX Indirect Channel Address
- *    Bit 15 IFLX_BUSY
- *    Bit 14 IFLX_RWB
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_IFLX_BUSY  0x8000
-#define SUNI1x10GEXP_BITMSK_IFLX_RWB   0x4000
-
-/*----------------------------------------------------------------------------
- * Register 0x220E: IFLX Indirect Logical FIFO Low Limit & Provision
- *    Bit 9-0 IFLX_LOLIM
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_IFLX_LOLIM  0x03FF
-#define SUNI1x10GEXP_BITOFF_IFLX_LOLIM  0
-
-/*----------------------------------------------------------------------------
- * Register 0x220F: IFLX Indirect Logical FIFO High Limit
- *    Bit 9-0 IFLX_HILIM
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_IFLX_HILIM  0x03FF
-#define SUNI1x10GEXP_BITOFF_IFLX_HILIM  0
-
-/*----------------------------------------------------------------------------
- * Register 0x2210: IFLX Indirect Full/Almost Full Status & Limit
- *    Bit 15   IFLX_FULL
- *    Bit 14   IFLX_AFULL
- *    Bit 13-0 IFLX_AFTH
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_IFLX_FULL   0x8000
-#define SUNI1x10GEXP_BITMSK_IFLX_AFULL  0x4000
-#define SUNI1x10GEXP_BITMSK_IFLX_AFTH   0x3FFF
-#define SUNI1x10GEXP_BITOFF_IFLX_AFTH   0
-
-/*----------------------------------------------------------------------------
- * Register 0x2211: IFLX Indirect Empty/Almost Empty Status & Limit
- *    Bit 15   IFLX_EMPTY
- *    Bit 14   IFLX_AEMPTY
- *    Bit 13-0 IFLX_AETH
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_IFLX_EMPTY   0x8000
-#define SUNI1x10GEXP_BITMSK_IFLX_AEMPTY  0x4000
-#define SUNI1x10GEXP_BITMSK_IFLX_AETH    0x3FFF
-#define SUNI1x10GEXP_BITOFF_IFLX_AETH    0
-
-/*----------------------------------------------------------------------------
- * Register 0x2240: PL4MOS Configuration Register
- *    Bit 3 PL4MOS_RE_INIT
- *    Bit 2 PL4MOS_EN
- *    Bit 1 PL4MOS_NO_STATUS
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4MOS_RE_INIT          0x0008
-#define SUNI1x10GEXP_BITMSK_PL4MOS_EN               0x0004
-#define SUNI1x10GEXP_BITMSK_PL4MOS_NO_STATUS        0x0002
-
-/*----------------------------------------------------------------------------
- * Register 0x2243: PL4MOS MaxBurst1 Register
- *    Bit 11-0 PL4MOS_MAX_BURST1
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4MOS_MAX_BURST1  0x0FFF
-#define SUNI1x10GEXP_BITOFF_PL4MOS_MAX_BURST1  0
-
-/*----------------------------------------------------------------------------
- * Register 0x2244: PL4MOS MaxBurst2 Register
- *    Bit 11-0 PL4MOS_MAX_BURST2
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4MOS_MAX_BURST2  0x0FFF
-#define SUNI1x10GEXP_BITOFF_PL4MOS_MAX_BURST2  0
-
-/*----------------------------------------------------------------------------
- * Register 0x2245: PL4MOS Transfer Size Register
- *    Bit 7-0 PL4MOS_MAX_TRANSFER
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4MOS_MAX_TRANSFER  0x00FF
-#define SUNI1x10GEXP_BITOFF_PL4MOS_MAX_TRANSFER  0
-
-/*----------------------------------------------------------------------------
- * Register 0x2280: PL4ODP Configuration
- *    Bit 15-12 PL4ODP_REPEAT_T
- *    Bit 8     PL4ODP_SOP_RULE
- *    Bit 1     PL4ODP_EN_PORTS
- *    Bit 0     PL4ODP_EN_DFWD
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4ODP_REPEAT_T   0xF000
-#define SUNI1x10GEXP_BITOFF_PL4ODP_REPEAT_T   12
-#define SUNI1x10GEXP_BITMSK_PL4ODP_SOP_RULE   0x0100
-#define SUNI1x10GEXP_BITMSK_PL4ODP_EN_PORTS   0x0002
-#define SUNI1x10GEXP_BITMSK_PL4ODP_EN_DFWD    0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x2282: PL4ODP Interrupt Mask
- *    Bit 0 PL4ODP_OUT_DISE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4ODP_OUT_DISE     0x0001
-
-
-
-#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_EOPEOBE  0x0080
-#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_ERREOPE  0x0040
-#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_MEOPE    0x0008
-#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_MSOPE    0x0004
-#define SUNI1x10GEXP_BITMSK_PL4ODP_ES_OVRE      0x0002
-
-
-/*----------------------------------------------------------------------------
- * Register 0x2283: PL4ODP Interrupt
- *    Bit 0 PL4ODP_OUT_DISI
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4ODP_OUT_DISI     0x0001
-
-
-
-#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_EOPEOBI  0x0080
-#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_ERREOPI  0x0040
-#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_MEOPI    0x0008
-#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_MSOPI    0x0004
-#define SUNI1x10GEXP_BITMSK_PL4ODP_ES_OVRI      0x0002
-
-/*----------------------------------------------------------------------------
- * Register 0x2300:  PL4IO Lock Detect Status
- *    Bit 15 PL4IO_OUT_ROOLV
- *    Bit 12 PL4IO_IS_ROOLV
- *    Bit 11 PL4IO_DIP2_ERRV
- *    Bit 8  PL4IO_ID_ROOLV
- *    Bit 4  PL4IO_IS_DOOLV
- *    Bit 0  PL4IO_ID_DOOLV
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4IO_OUT_ROOLV  0x8000
-#define SUNI1x10GEXP_BITMSK_PL4IO_IS_ROOLV   0x1000
-#define SUNI1x10GEXP_BITMSK_PL4IO_DIP2_ERRV  0x0800
-#define SUNI1x10GEXP_BITMSK_PL4IO_ID_ROOLV   0x0100
-#define SUNI1x10GEXP_BITMSK_PL4IO_IS_DOOLV   0x0010
-#define SUNI1x10GEXP_BITMSK_PL4IO_ID_DOOLV   0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x2301:  PL4IO Lock Detect Change
- *    Bit 15 PL4IO_OUT_ROOLI
- *    Bit 12 PL4IO_IS_ROOLI
- *    Bit 11 PL4IO_DIP2_ERRI
- *    Bit 8  PL4IO_ID_ROOLI
- *    Bit 4  PL4IO_IS_DOOLI
- *    Bit 0  PL4IO_ID_DOOLI
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4IO_OUT_ROOLI  0x8000
-#define SUNI1x10GEXP_BITMSK_PL4IO_IS_ROOLI   0x1000
-#define SUNI1x10GEXP_BITMSK_PL4IO_DIP2_ERRI  0x0800
-#define SUNI1x10GEXP_BITMSK_PL4IO_ID_ROOLI   0x0100
-#define SUNI1x10GEXP_BITMSK_PL4IO_IS_DOOLI   0x0010
-#define SUNI1x10GEXP_BITMSK_PL4IO_ID_DOOLI   0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x2302:  PL4IO Lock Detect Mask
- *    Bit 15 PL4IO_OUT_ROOLE
- *    Bit 12 PL4IO_IS_ROOLE
- *    Bit 11 PL4IO_DIP2_ERRE
- *    Bit 8  PL4IO_ID_ROOLE
- *    Bit 4  PL4IO_IS_DOOLE
- *    Bit 0  PL4IO_ID_DOOLE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4IO_OUT_ROOLE  0x8000
-#define SUNI1x10GEXP_BITMSK_PL4IO_IS_ROOLE   0x1000
-#define SUNI1x10GEXP_BITMSK_PL4IO_DIP2_ERRE  0x0800
-#define SUNI1x10GEXP_BITMSK_PL4IO_ID_ROOLE   0x0100
-#define SUNI1x10GEXP_BITMSK_PL4IO_IS_DOOLE   0x0010
-#define SUNI1x10GEXP_BITMSK_PL4IO_ID_DOOLE   0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x2303:  PL4IO Lock Detect Limits
- *    Bit 15-8 PL4IO_REF_LIMIT
- *    Bit 7-0  PL4IO_TRAN_LIMIT
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4IO_REF_LIMIT   0xFF00
-#define SUNI1x10GEXP_BITOFF_PL4IO_REF_LIMIT   8
-#define SUNI1x10GEXP_BITMSK_PL4IO_TRAN_LIMIT  0x00FF
-#define SUNI1x10GEXP_BITOFF_PL4IO_TRAN_LIMIT  0
-
-/*----------------------------------------------------------------------------
- * Register 0x2304:  PL4IO Calendar Repetitions
- *    Bit 15-8 PL4IO_IN_MUL
- *    Bit 7-0  PL4IO_OUT_MUL
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4IO_IN_MUL   0xFF00
-#define SUNI1x10GEXP_BITOFF_PL4IO_IN_MUL   8
-#define SUNI1x10GEXP_BITMSK_PL4IO_OUT_MUL  0x00FF
-#define SUNI1x10GEXP_BITOFF_PL4IO_OUT_MUL  0
-
-/*----------------------------------------------------------------------------
- * Register 0x2305:  PL4IO Configuration
- *    Bit 15  PL4IO_DIP2_ERR_CHK
- *    Bit 11  PL4IO_ODAT_DIS
- *    Bit 10  PL4IO_TRAIN_DIS
- *    Bit 9   PL4IO_OSTAT_DIS
- *    Bit 8   PL4IO_ISTAT_DIS
- *    Bit 7   PL4IO_NO_ISTAT
- *    Bit 6   PL4IO_STAT_OUTSEL
- *    Bit 5   PL4IO_INSEL
- *    Bit 4   PL4IO_DLSEL
- *    Bit 1-0 PL4IO_OUTSEL
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4IO_DIP2_ERR_CHK  0x8000
-#define SUNI1x10GEXP_BITMSK_PL4IO_ODAT_DIS      0x0800
-#define SUNI1x10GEXP_BITMSK_PL4IO_TRAIN_DIS     0x0400
-#define SUNI1x10GEXP_BITMSK_PL4IO_OSTAT_DIS     0x0200
-#define SUNI1x10GEXP_BITMSK_PL4IO_ISTAT_DIS     0x0100
-#define SUNI1x10GEXP_BITMSK_PL4IO_NO_ISTAT      0x0080
-#define SUNI1x10GEXP_BITMSK_PL4IO_STAT_OUTSEL   0x0040
-#define SUNI1x10GEXP_BITMSK_PL4IO_INSEL         0x0020
-#define SUNI1x10GEXP_BITMSK_PL4IO_DLSEL         0x0010
-#define SUNI1x10GEXP_BITMSK_PL4IO_OUTSEL        0x0003
-#define SUNI1x10GEXP_BITOFF_PL4IO_OUTSEL        0
-
-/*----------------------------------------------------------------------------
- * Register 0x3040: TXXG Configuration Register 1
- *    Bit 15   TXXG_TXEN0
- *    Bit 13   TXXG_HOSTPAUSE
- *    Bit 12-7 TXXG_IPGT
- *    Bit 5    TXXG_32BIT_ALIGN
- *    Bit 4    TXXG_CRCEN
- *    Bit 3    TXXG_FCTX
- *    Bit 2    TXXG_FCRX
- *    Bit 1    TXXG_PADEN
- *    Bit 0    TXXG_SPRE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TXXG_TXEN0        0x8000
-#define SUNI1x10GEXP_BITMSK_TXXG_HOSTPAUSE    0x2000
-#define SUNI1x10GEXP_BITMSK_TXXG_IPGT         0x1F80
-#define SUNI1x10GEXP_BITOFF_TXXG_IPGT         7
-#define SUNI1x10GEXP_BITMSK_TXXG_32BIT_ALIGN  0x0020
-#define SUNI1x10GEXP_BITMSK_TXXG_CRCEN        0x0010
-#define SUNI1x10GEXP_BITMSK_TXXG_FCTX         0x0008
-#define SUNI1x10GEXP_BITMSK_TXXG_FCRX         0x0004
-#define SUNI1x10GEXP_BITMSK_TXXG_PADEN        0x0002
-#define SUNI1x10GEXP_BITMSK_TXXG_SPRE         0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x3041: TXXG Configuration Register 2
- *    Bit 7-0   TXXG_HDRSIZE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TXXG_HDRSIZE  0x00FF
-
-/*----------------------------------------------------------------------------
- * Register 0x3042: TXXG Configuration Register 3
- *    Bit 15 TXXG_FIFO_ERRE
- *    Bit 14 TXXG_FIFO_UDRE
- *    Bit 13 TXXG_MAX_LERRE
- *    Bit 12 TXXG_MIN_LERRE
- *    Bit 11 TXXG_XFERE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TXXG_FIFO_ERRE  0x8000
-#define SUNI1x10GEXP_BITMSK_TXXG_FIFO_UDRE  0x4000
-#define SUNI1x10GEXP_BITMSK_TXXG_MAX_LERRE  0x2000
-#define SUNI1x10GEXP_BITMSK_TXXG_MIN_LERRE  0x1000
-#define SUNI1x10GEXP_BITMSK_TXXG_XFERE      0x0800
-
-/*----------------------------------------------------------------------------
- * Register 0x3043: TXXG Interrupt
- *    Bit 15 TXXG_FIFO_ERRI
- *    Bit 14 TXXG_FIFO_UDRI
- *    Bit 13 TXXG_MAX_LERRI
- *    Bit 12 TXXG_MIN_LERRI
- *    Bit 11 TXXG_XFERI
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TXXG_FIFO_ERRI  0x8000
-#define SUNI1x10GEXP_BITMSK_TXXG_FIFO_UDRI  0x4000
-#define SUNI1x10GEXP_BITMSK_TXXG_MAX_LERRI  0x2000
-#define SUNI1x10GEXP_BITMSK_TXXG_MIN_LERRI  0x1000
-#define SUNI1x10GEXP_BITMSK_TXXG_XFERI      0x0800
-
-/*----------------------------------------------------------------------------
- * Register 0x3044: TXXG Status Register
- *    Bit 1 TXXG_TXACTIVE
- *    Bit 0 TXXG_PAUSED
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TXXG_TXACTIVE  0x0002
-#define SUNI1x10GEXP_BITMSK_TXXG_PAUSED    0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x3046: TXXG TX_MINFR -  Transmit Min Frame Size Register
- *    Bit 7-0 TXXG_TX_MINFR
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TXXG_TX_MINFR  0x00FF
-#define SUNI1x10GEXP_BITOFF_TXXG_TX_MINFR  0
-
-/*----------------------------------------------------------------------------
- * Register 0x3052: TXXG Pause Quantum Value Configuration Register
- *    Bit 7-0 TXXG_FC_PAUSE_QNTM
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TXXG_FC_PAUSE_QNTM  0x00FF
-#define SUNI1x10GEXP_BITOFF_TXXG_FC_PAUSE_QNTM  0
-
-/*----------------------------------------------------------------------------
- * Register 0x3080: XTEF Control
- *    Bit 3-0 XTEF_FORCE_PARITY_ERR
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_XTEF_FORCE_PARITY_ERR  0x000F
-#define SUNI1x10GEXP_BITOFF_XTEF_FORCE_PARITY_ERR  0
-
-/*----------------------------------------------------------------------------
- * Register 0x3084: XTEF Interrupt Event Register
- *    Bit 0 XTEF_LOST_SYNCI
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_XTEF_LOST_SYNCI  0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x3085: XTEF Interrupt Enable Register
- *    Bit 0 XTEF_LOST_SYNCE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_XTEF_LOST_SYNCE  0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x3086: XTEF Visibility Register
- *    Bit 0 XTEF_LOST_SYNCV
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_XTEF_LOST_SYNCV  0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x30C0: TXOAM OAM Configuration
- *    Bit 15   TXOAM_HEC_EN
- *    Bit 14   TXOAM_EMPTYCODE_EN
- *    Bit 13   TXOAM_FORCE_IDLE
- *    Bit 12   TXOAM_IGNORE_IDLE
- *    Bit 11-6 TXOAM_PX_OVERWRITE
- *    Bit 5-0  TXOAM_PX_SEL
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TXOAM_HEC_EN        0x8000
-#define SUNI1x10GEXP_BITMSK_TXOAM_EMPTYCODE_EN  0x4000
-#define SUNI1x10GEXP_BITMSK_TXOAM_FORCE_IDLE    0x2000
-#define SUNI1x10GEXP_BITMSK_TXOAM_IGNORE_IDLE   0x1000
-#define SUNI1x10GEXP_BITMSK_TXOAM_PX_OVERWRITE  0x0FC0
-#define SUNI1x10GEXP_BITOFF_TXOAM_PX_OVERWRITE  6
-#define SUNI1x10GEXP_BITMSK_TXOAM_PX_SEL        0x003F
-#define SUNI1x10GEXP_BITOFF_TXOAM_PX_SEL        0
-
-/*----------------------------------------------------------------------------
- * Register 0x30C1: TXOAM Mini-Packet Rate Configuration
- *    Bit 15   TXOAM_MINIDIS
- *    Bit 14   TXOAM_BUSY
- *    Bit 13   TXOAM_TRANS_EN
- *    Bit 10-0 TXOAM_MINIRATE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TXOAM_MINIDIS   0x8000
-#define SUNI1x10GEXP_BITMSK_TXOAM_BUSY      0x4000
-#define SUNI1x10GEXP_BITMSK_TXOAM_TRANS_EN  0x2000
-#define SUNI1x10GEXP_BITMSK_TXOAM_MINIRATE  0x07FF
-
-/*----------------------------------------------------------------------------
- * Register 0x30C2: TXOAM Mini-Packet Gap and FIFO Configuration
- *    Bit 13-10 TXOAM_FTHRESH
- *    Bit 9-6   TXOAM_MINIPOST
- *    Bit 5-0   TXOAM_MINIPRE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TXOAM_FTHRESH   0x3C00
-#define SUNI1x10GEXP_BITOFF_TXOAM_FTHRESH   10
-#define SUNI1x10GEXP_BITMSK_TXOAM_MINIPOST  0x03C0
-#define SUNI1x10GEXP_BITOFF_TXOAM_MINIPOST  6
-#define SUNI1x10GEXP_BITMSK_TXOAM_MINIPRE   0x003F
-
-/*----------------------------------------------------------------------------
- * Register 0x30C6: TXOAM Interrupt Enable
- *    Bit 2 TXOAM_SOP_ERRE
- *    Bit 1 TXOAM_OFLE
- *    Bit 0 TXOAM_ERRE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TXOAM_SOP_ERRE    0x0004
-#define SUNI1x10GEXP_BITMSK_TXOAM_OFLE        0x0002
-#define SUNI1x10GEXP_BITMSK_TXOAM_ERRE        0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x30C7: TXOAM Interrupt Status
- *    Bit 2 TXOAM_SOP_ERRI
- *    Bit 1 TXOAM_OFLI
- *    Bit 0 TXOAM_ERRI
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TXOAM_SOP_ERRI    0x0004
-#define SUNI1x10GEXP_BITMSK_TXOAM_OFLI        0x0002
-#define SUNI1x10GEXP_BITMSK_TXOAM_ERRI        0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x30CF: TXOAM Coset
- *    Bit 7-0 TXOAM_COSET
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_TXOAM_COSET  0x00FF
-
-/*----------------------------------------------------------------------------
- * Register 0x3200: EFLX Global Configuration
- *    Bit 15 EFLX_ERCU_EN
- *    Bit 7  EFLX_EN_EDSWT
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_EFLX_ERCU_EN   0x8000
-#define SUNI1x10GEXP_BITMSK_EFLX_EN_EDSWT  0x0080
-
-/*----------------------------------------------------------------------------
- * Register 0x3201: EFLX ERCU Global Status
- *    Bit 13 EFLX_OVF_ERR
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_EFLX_OVF_ERR  0x2000
-
-/*----------------------------------------------------------------------------
- * Register 0x3202: EFLX Indirect Channel Address
- *    Bit 15 EFLX_BUSY
- *    Bit 14 EFLX_RDWRB
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_EFLX_BUSY   0x8000
-#define SUNI1x10GEXP_BITMSK_EFLX_RDWRB  0x4000
-
-/*----------------------------------------------------------------------------
- * Register 0x3203: EFLX Indirect Logical FIFO Low Limit
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_EFLX_LOLIM                    0x03FF
-#define SUNI1x10GEXP_BITOFF_EFLX_LOLIM                    0
-
-/*----------------------------------------------------------------------------
- * Register 0x3204: EFLX Indirect Logical FIFO High Limit
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_EFLX_HILIM                    0x03FF
-#define SUNI1x10GEXP_BITOFF_EFLX_HILIM                    0
-
-/*----------------------------------------------------------------------------
- * Register 0x3205: EFLX Indirect Full/Almost-Full Status and Limit
- *    Bit 15   EFLX_FULL
- *    Bit 14   EFLX_AFULL
- *    Bit 13-0 EFLX_AFTH
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_EFLX_FULL   0x8000
-#define SUNI1x10GEXP_BITMSK_EFLX_AFULL  0x4000
-#define SUNI1x10GEXP_BITMSK_EFLX_AFTH   0x3FFF
-#define SUNI1x10GEXP_BITOFF_EFLX_AFTH   0
-
-/*----------------------------------------------------------------------------
- * Register 0x3206: EFLX Indirect Empty/Almost-Empty Status and Limit
- *    Bit 15   EFLX_EMPTY
- *    Bit 14   EFLX_AEMPTY
- *    Bit 13-0 EFLX_AETH
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_EFLX_EMPTY   0x8000
-#define SUNI1x10GEXP_BITMSK_EFLX_AEMPTY  0x4000
-#define SUNI1x10GEXP_BITMSK_EFLX_AETH    0x3FFF
-#define SUNI1x10GEXP_BITOFF_EFLX_AETH    0
-
-/*----------------------------------------------------------------------------
- * Register 0x3207: EFLX Indirect FIFO Cut-Through Threshold
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_EFLX_CUT_THRU                 0x3FFF
-#define SUNI1x10GEXP_BITOFF_EFLX_CUT_THRU                 0
-
-/*----------------------------------------------------------------------------
- * Register 0x320C: EFLX FIFO Overflow Error Enable
- *    Bit 0 EFLX_OVFE
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_EFLX_OVFE  0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x320D: EFLX FIFO Overflow Error Indication
- *    Bit 0 EFLX_OVFI
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_EFLX_OVFI  0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x3210: EFLX Channel Provision
- *    Bit 0 EFLX_PROV
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_EFLX_PROV  0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x3280: PL4IDU Configuration
- *    Bit 2 PL4IDU_SYNCH_ON_TRAIN
- *    Bit 1 PL4IDU_EN_PORTS
- *    Bit 0 PL4IDU_EN_DFWD
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4IDU_SYNCH_ON_TRAIN  0x0004
-#define SUNI1x10GEXP_BITMSK_PL4IDU_EN_PORTS        0x0002
-#define SUNI1x10GEXP_BITMSK_PL4IDU_EN_DFWD         0x0001
-
-/*----------------------------------------------------------------------------
- * Register 0x3282: PL4IDU Interrupt Mask
- *    Bit 1 PL4IDU_DIP4E
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4IDU_DIP4E       0x0002
-
-/*----------------------------------------------------------------------------
- * Register 0x3283: PL4IDU Interrupt
- *    Bit 1 PL4IDU_DIP4I
- *----------------------------------------------------------------------------*/
-#define SUNI1x10GEXP_BITMSK_PL4IDU_DIP4I       0x0002
-
-#endif /* _CXGB_SUNI1x10GEXP_REGS_H_ */
-
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/tp.c linux-libre-3.2-gnu/drivers/net/chelsio/tp.c
--- linux-libre-3.1-gnu/drivers/net/chelsio/tp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/tp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,171 +0,0 @@
-/* $Date: 2006/02/07 04:21:54 $ $RCSfile: tp.c,v $ $Revision: 1.73 $ */
-#include "common.h"
-#include "regs.h"
-#include "tp.h"
-#ifdef CONFIG_CHELSIO_T1_1G
-#include "fpga_defs.h"
-#endif
-
-struct petp {
-	adapter_t *adapter;
-};
-
-/* Pause deadlock avoidance parameters */
-#define DROP_MSEC 16
-#define DROP_PKTS_CNT  1
-
-static void tp_init(adapter_t * ap, const struct tp_params *p,
-		    unsigned int tp_clk)
-{
-	u32 val;
-
-	if (!t1_is_asic(ap))
-		return;
-
-	val = F_TP_IN_CSPI_CPL | F_TP_IN_CSPI_CHECK_IP_CSUM |
-		F_TP_IN_CSPI_CHECK_TCP_CSUM | F_TP_IN_ESPI_ETHERNET;
-	if (!p->pm_size)
-		val |= F_OFFLOAD_DISABLE;
-	else
-		val |= F_TP_IN_ESPI_CHECK_IP_CSUM | F_TP_IN_ESPI_CHECK_TCP_CSUM;
-	writel(val, ap->regs + A_TP_IN_CONFIG);
-	writel(F_TP_OUT_CSPI_CPL |
-	       F_TP_OUT_ESPI_ETHERNET |
-	       F_TP_OUT_ESPI_GENERATE_IP_CSUM |
-	       F_TP_OUT_ESPI_GENERATE_TCP_CSUM, ap->regs + A_TP_OUT_CONFIG);
-	writel(V_IP_TTL(64) |
-	       F_PATH_MTU /* IP DF bit */  |
-	       V_5TUPLE_LOOKUP(p->use_5tuple_mode) |
-	       V_SYN_COOKIE_PARAMETER(29), ap->regs + A_TP_GLOBAL_CONFIG);
-	/*
-	 * Enable pause frame deadlock prevention.
-	 */
-	if (is_T2(ap) && ap->params.nports > 1) {
-		u32 drop_ticks = DROP_MSEC * (tp_clk / 1000);
-
-		writel(F_ENABLE_TX_DROP | F_ENABLE_TX_ERROR |
-		       V_DROP_TICKS_CNT(drop_ticks) |
-		       V_NUM_PKTS_DROPPED(DROP_PKTS_CNT),
-		       ap->regs + A_TP_TX_DROP_CONFIG);
-	}
-}
-
-void t1_tp_destroy(struct petp *tp)
-{
-	kfree(tp);
-}
-
-struct petp *__devinit t1_tp_create(adapter_t * adapter, struct tp_params *p)
-{
-	struct petp *tp = kzalloc(sizeof(*tp), GFP_KERNEL);
-
-	if (!tp)
-		return NULL;
-
-	tp->adapter = adapter;
-
-	return tp;
-}
-
-void t1_tp_intr_enable(struct petp *tp)
-{
-	u32 tp_intr = readl(tp->adapter->regs + A_PL_ENABLE);
-
-#ifdef CONFIG_CHELSIO_T1_1G
-	if (!t1_is_asic(tp->adapter)) {
-		/* FPGA */
-		writel(0xffffffff,
-		       tp->adapter->regs + FPGA_TP_ADDR_INTERRUPT_ENABLE);
-		writel(tp_intr | FPGA_PCIX_INTERRUPT_TP,
-		       tp->adapter->regs + A_PL_ENABLE);
-	} else
-#endif
-	{
-		/* We don't use any TP interrupts */
-		writel(0, tp->adapter->regs + A_TP_INT_ENABLE);
-		writel(tp_intr | F_PL_INTR_TP,
-		       tp->adapter->regs + A_PL_ENABLE);
-	}
-}
-
-void t1_tp_intr_disable(struct petp *tp)
-{
-	u32 tp_intr = readl(tp->adapter->regs + A_PL_ENABLE);
-
-#ifdef CONFIG_CHELSIO_T1_1G
-	if (!t1_is_asic(tp->adapter)) {
-		/* FPGA */
-		writel(0, tp->adapter->regs + FPGA_TP_ADDR_INTERRUPT_ENABLE);
-		writel(tp_intr & ~FPGA_PCIX_INTERRUPT_TP,
-		       tp->adapter->regs + A_PL_ENABLE);
-	} else
-#endif
-	{
-		writel(0, tp->adapter->regs + A_TP_INT_ENABLE);
-		writel(tp_intr & ~F_PL_INTR_TP,
-		       tp->adapter->regs + A_PL_ENABLE);
-	}
-}
-
-void t1_tp_intr_clear(struct petp *tp)
-{
-#ifdef CONFIG_CHELSIO_T1_1G
-	if (!t1_is_asic(tp->adapter)) {
-		writel(0xffffffff,
-		       tp->adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE);
-		writel(FPGA_PCIX_INTERRUPT_TP, tp->adapter->regs + A_PL_CAUSE);
-		return;
-	}
-#endif
-	writel(0xffffffff, tp->adapter->regs + A_TP_INT_CAUSE);
-	writel(F_PL_INTR_TP, tp->adapter->regs + A_PL_CAUSE);
-}
-
-int t1_tp_intr_handler(struct petp *tp)
-{
-	u32 cause;
-
-#ifdef CONFIG_CHELSIO_T1_1G
-	/* FPGA doesn't support TP interrupts. */
-	if (!t1_is_asic(tp->adapter))
-		return 1;
-#endif
-
-	cause = readl(tp->adapter->regs + A_TP_INT_CAUSE);
-	writel(cause, tp->adapter->regs + A_TP_INT_CAUSE);
-	return 0;
-}
-
-static void set_csum_offload(struct petp *tp, u32 csum_bit, int enable)
-{
-	u32 val = readl(tp->adapter->regs + A_TP_GLOBAL_CONFIG);
-
-	if (enable)
-		val |= csum_bit;
-	else
-		val &= ~csum_bit;
-	writel(val, tp->adapter->regs + A_TP_GLOBAL_CONFIG);
-}
-
-void t1_tp_set_ip_checksum_offload(struct petp *tp, int enable)
-{
-	set_csum_offload(tp, F_IP_CSUM, enable);
-}
-
-void t1_tp_set_tcp_checksum_offload(struct petp *tp, int enable)
-{
-	set_csum_offload(tp, F_TCP_CSUM, enable);
-}
-
-/*
- * Initialize TP state.  tp_params contains initial settings for some TP
- * parameters, particularly the one-time PM and CM settings.
- */
-int t1_tp_reset(struct petp *tp, struct tp_params *p, unsigned int tp_clk)
-{
-	adapter_t *adapter = tp->adapter;
-
-	tp_init(adapter, p, tp_clk);
-	writel(F_TP_RESET, adapter->regs +  A_TP_RESET);
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/tp.h linux-libre-3.2-gnu/drivers/net/chelsio/tp.h
--- linux-libre-3.1-gnu/drivers/net/chelsio/tp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/tp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,72 +0,0 @@
-/* $Date: 2005/03/07 23:59:05 $ $RCSfile: tp.h,v $ $Revision: 1.20 $ */
-#ifndef CHELSIO_TP_H
-#define CHELSIO_TP_H
-
-#include "common.h"
-
-#define TP_MAX_RX_COALESCING_SIZE 16224U
-
-struct tp_mib_statistics {
-
-	/* IP */
-	u32 ipInReceive_hi;
-	u32 ipInReceive_lo;
-	u32 ipInHdrErrors_hi;
-	u32 ipInHdrErrors_lo;
-	u32 ipInAddrErrors_hi;
-	u32 ipInAddrErrors_lo;
-	u32 ipInUnknownProtos_hi;
-	u32 ipInUnknownProtos_lo;
-	u32 ipInDiscards_hi;
-	u32 ipInDiscards_lo;
-	u32 ipInDelivers_hi;
-	u32 ipInDelivers_lo;
-	u32 ipOutRequests_hi;
-	u32 ipOutRequests_lo;
-	u32 ipOutDiscards_hi;
-	u32 ipOutDiscards_lo;
-	u32 ipOutNoRoutes_hi;
-	u32 ipOutNoRoutes_lo;
-	u32 ipReasmTimeout;
-	u32 ipReasmReqds;
-	u32 ipReasmOKs;
-	u32 ipReasmFails;
-
-	u32 reserved[8];
-
-	/* TCP */
-	u32 tcpActiveOpens;
-	u32 tcpPassiveOpens;
-	u32 tcpAttemptFails;
-	u32 tcpEstabResets;
-	u32 tcpOutRsts;
-	u32 tcpCurrEstab;
-	u32 tcpInSegs_hi;
-	u32 tcpInSegs_lo;
-	u32 tcpOutSegs_hi;
-	u32 tcpOutSegs_lo;
-	u32 tcpRetransSeg_hi;
-	u32 tcpRetransSeg_lo;
-	u32 tcpInErrs_hi;
-	u32 tcpInErrs_lo;
-	u32 tcpRtoMin;
-	u32 tcpRtoMax;
-};
-
-struct petp;
-struct tp_params;
-
-struct petp *t1_tp_create(adapter_t *adapter, struct tp_params *p);
-void t1_tp_destroy(struct petp *tp);
-
-void t1_tp_intr_disable(struct petp *tp);
-void t1_tp_intr_enable(struct petp *tp);
-void t1_tp_intr_clear(struct petp *tp);
-int t1_tp_intr_handler(struct petp *tp);
-
-void t1_tp_get_mib_statistics(adapter_t *adap, struct tp_mib_statistics *tps);
-void t1_tp_set_tcp_checksum_offload(struct petp *tp, int enable);
-void t1_tp_set_ip_checksum_offload(struct petp *tp, int enable);
-int t1_tp_set_coalescing_size(struct petp *tp, unsigned int size);
-int t1_tp_reset(struct petp *tp, struct tp_params *p, unsigned int tp_clk);
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/vsc7326.c linux-libre-3.2-gnu/drivers/net/chelsio/vsc7326.c
--- linux-libre-3.1-gnu/drivers/net/chelsio/vsc7326.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/vsc7326.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,730 +0,0 @@
-/* $Date: 2006/04/28 19:20:06 $ $RCSfile: vsc7326.c,v $ $Revision: 1.19 $ */
-
-/* Driver for Vitesse VSC7326 (Schaumburg) MAC */
-
-#include "gmac.h"
-#include "elmer0.h"
-#include "vsc7326_reg.h"
-
-/* Update fast changing statistics every 15 seconds */
-#define STATS_TICK_SECS 15
-/* 30 minutes for full statistics update */
-#define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS)
-
-#define MAX_MTU 9600
-
-/* The egress WM value 0x01a01fff should be used only when the
- * interface is down (MAC port disabled). This is a workaround
- * for disabling the T2/MAC flow-control. When the interface is
- * enabled, the WM value should be set to 0x014a03F0.
- */
-#define WM_DISABLE	0x01a01fff
-#define WM_ENABLE	0x014a03F0
-
-struct init_table {
-	u32 addr;
-	u32 data;
-};
-
-struct _cmac_instance {
-	u32 index;
-	u32 ticks;
-};
-
-#define INITBLOCK_SLEEP	0xffffffff
-
-static void vsc_read(adapter_t *adapter, u32 addr, u32 *val)
-{
-	u32 status, vlo, vhi;
-	int i;
-
-	spin_lock_bh(&adapter->mac_lock);
-	t1_tpi_read(adapter, (addr << 2) + 4, &vlo);
-	i = 0;
-	do {
-		t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo);
-		t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi);
-		status = (vhi << 16) | vlo;
-		i++;
-	} while (((status & 1) == 0) && (i < 50));
-	if (i == 50)
-		pr_err("Invalid tpi read from MAC, breaking loop.\n");
-
-	t1_tpi_read(adapter, (REG_LOCAL_DATA << 2) + 4, &vlo);
-	t1_tpi_read(adapter, REG_LOCAL_DATA << 2, &vhi);
-
-	*val = (vhi << 16) | vlo;
-
-	/* pr_err("rd: block: 0x%x  sublock: 0x%x  reg: 0x%x  data: 0x%x\n",
-		((addr&0xe000)>>13), ((addr&0x1e00)>>9),
-		((addr&0x01fe)>>1), *val); */
-	spin_unlock_bh(&adapter->mac_lock);
-}
-
-static void vsc_write(adapter_t *adapter, u32 addr, u32 data)
-{
-	spin_lock_bh(&adapter->mac_lock);
-	t1_tpi_write(adapter, (addr << 2) + 4, data & 0xFFFF);
-	t1_tpi_write(adapter, addr << 2, (data >> 16) & 0xFFFF);
-	/* pr_err("wr: block: 0x%x  sublock: 0x%x  reg: 0x%x  data: 0x%x\n",
-		((addr&0xe000)>>13), ((addr&0x1e00)>>9),
-		((addr&0x01fe)>>1), data); */
-	spin_unlock_bh(&adapter->mac_lock);
-}
-
-/* Hard reset the MAC.  This wipes out *all* configuration. */
-static void vsc7326_full_reset(adapter_t* adapter)
-{
-	u32 val;
-	u32 result = 0xffff;
-
-	t1_tpi_read(adapter, A_ELMER0_GPO, &val);
-	val &= ~1;
-	t1_tpi_write(adapter, A_ELMER0_GPO, val);
-	udelay(2);
-	val |= 0x1;	/* Enable mac MAC itself */
-	val |= 0x800;	/* Turn off the red LED */
-	t1_tpi_write(adapter, A_ELMER0_GPO, val);
-	mdelay(1);
-	vsc_write(adapter, REG_SW_RESET, 0x80000001);
-	do {
-		mdelay(1);
-		vsc_read(adapter, REG_SW_RESET, &result);
-	} while (result != 0x0);
-}
-
-static struct init_table vsc7326_reset[] = {
-	{      REG_IFACE_MODE, 0x00000000 },
-	{         REG_CRC_CFG, 0x00000020 },
-	{   REG_PLL_CLK_SPEED, 0x00050c00 },
-	{   REG_PLL_CLK_SPEED, 0x00050c00 },
-	{            REG_MSCH, 0x00002f14 },
-	{       REG_SPI4_MISC, 0x00040409 },
-	{     REG_SPI4_DESKEW, 0x00080000 },
-	{ REG_SPI4_ING_SETUP2, 0x08080004 },
-	{ REG_SPI4_ING_SETUP0, 0x04111004 },
-	{ REG_SPI4_EGR_SETUP0, 0x80001a04 },
-	{ REG_SPI4_ING_SETUP1, 0x02010000 },
-	{      REG_AGE_INC(0), 0x00000000 },
-	{      REG_AGE_INC(1), 0x00000000 },
-	{     REG_ING_CONTROL, 0x0a200011 },
-	{     REG_EGR_CONTROL, 0xa0010091 },
-};
-
-static struct init_table vsc7326_portinit[4][22] = {
-	{	/* Port 0 */
-			/* FIFO setup */
-		{           REG_DBG(0), 0x000004f0 },
-		{           REG_HDX(0), 0x00073101 },
-		{        REG_TEST(0,0), 0x00000022 },
-		{        REG_TEST(1,0), 0x00000022 },
-		{  REG_TOP_BOTTOM(0,0), 0x003f0000 },
-		{  REG_TOP_BOTTOM(1,0), 0x00120000 },
-		{ REG_HIGH_LOW_WM(0,0), 0x07460757 },
-		{ REG_HIGH_LOW_WM(1,0), WM_DISABLE },
-		{   REG_CT_THRHLD(0,0), 0x00000000 },
-		{   REG_CT_THRHLD(1,0), 0x00000000 },
-		{         REG_BUCKE(0), 0x0002ffff },
-		{         REG_BUCKI(0), 0x0002ffff },
-		{        REG_TEST(0,0), 0x00000020 },
-		{        REG_TEST(1,0), 0x00000020 },
-			/* Port config */
-		{       REG_MAX_LEN(0), 0x00002710 },
-		{     REG_PORT_FAIL(0), 0x00000002 },
-		{    REG_NORMALIZER(0), 0x00000a64 },
-		{        REG_DENORM(0), 0x00000010 },
-		{     REG_STICK_BIT(0), 0x03baa370 },
-		{     REG_DEV_SETUP(0), 0x00000083 },
-		{     REG_DEV_SETUP(0), 0x00000082 },
-		{      REG_MODE_CFG(0), 0x0200259f },
-	},
-	{	/* Port 1 */
-			/* FIFO setup */
-		{           REG_DBG(1), 0x000004f0 },
-		{           REG_HDX(1), 0x00073101 },
-		{        REG_TEST(0,1), 0x00000022 },
-		{        REG_TEST(1,1), 0x00000022 },
-		{  REG_TOP_BOTTOM(0,1), 0x007e003f },
-		{  REG_TOP_BOTTOM(1,1), 0x00240012 },
-		{ REG_HIGH_LOW_WM(0,1), 0x07460757 },
-		{ REG_HIGH_LOW_WM(1,1), WM_DISABLE },
-		{   REG_CT_THRHLD(0,1), 0x00000000 },
-		{   REG_CT_THRHLD(1,1), 0x00000000 },
-		{         REG_BUCKE(1), 0x0002ffff },
-		{         REG_BUCKI(1), 0x0002ffff },
-		{        REG_TEST(0,1), 0x00000020 },
-		{        REG_TEST(1,1), 0x00000020 },
-			/* Port config */
-		{       REG_MAX_LEN(1), 0x00002710 },
-		{     REG_PORT_FAIL(1), 0x00000002 },
-		{    REG_NORMALIZER(1), 0x00000a64 },
-		{        REG_DENORM(1), 0x00000010 },
-		{     REG_STICK_BIT(1), 0x03baa370 },
-		{     REG_DEV_SETUP(1), 0x00000083 },
-		{     REG_DEV_SETUP(1), 0x00000082 },
-		{      REG_MODE_CFG(1), 0x0200259f },
-	},
-	{	/* Port 2 */
-			/* FIFO setup */
-		{           REG_DBG(2), 0x000004f0 },
-		{           REG_HDX(2), 0x00073101 },
-		{        REG_TEST(0,2), 0x00000022 },
-		{        REG_TEST(1,2), 0x00000022 },
-		{  REG_TOP_BOTTOM(0,2), 0x00bd007e },
-		{  REG_TOP_BOTTOM(1,2), 0x00360024 },
-		{ REG_HIGH_LOW_WM(0,2), 0x07460757 },
-		{ REG_HIGH_LOW_WM(1,2), WM_DISABLE },
-		{   REG_CT_THRHLD(0,2), 0x00000000 },
-		{   REG_CT_THRHLD(1,2), 0x00000000 },
-		{         REG_BUCKE(2), 0x0002ffff },
-		{         REG_BUCKI(2), 0x0002ffff },
-		{        REG_TEST(0,2), 0x00000020 },
-		{        REG_TEST(1,2), 0x00000020 },
-			/* Port config */
-		{       REG_MAX_LEN(2), 0x00002710 },
-		{     REG_PORT_FAIL(2), 0x00000002 },
-		{    REG_NORMALIZER(2), 0x00000a64 },
-		{        REG_DENORM(2), 0x00000010 },
-		{     REG_STICK_BIT(2), 0x03baa370 },
-		{     REG_DEV_SETUP(2), 0x00000083 },
-		{     REG_DEV_SETUP(2), 0x00000082 },
-		{      REG_MODE_CFG(2), 0x0200259f },
-	},
-	{	/* Port 3 */
-			/* FIFO setup */
-		{           REG_DBG(3), 0x000004f0 },
-		{           REG_HDX(3), 0x00073101 },
-		{        REG_TEST(0,3), 0x00000022 },
-		{        REG_TEST(1,3), 0x00000022 },
-		{  REG_TOP_BOTTOM(0,3), 0x00fc00bd },
-		{  REG_TOP_BOTTOM(1,3), 0x00480036 },
-		{ REG_HIGH_LOW_WM(0,3), 0x07460757 },
-		{ REG_HIGH_LOW_WM(1,3), WM_DISABLE },
-		{   REG_CT_THRHLD(0,3), 0x00000000 },
-		{   REG_CT_THRHLD(1,3), 0x00000000 },
-		{         REG_BUCKE(3), 0x0002ffff },
-		{         REG_BUCKI(3), 0x0002ffff },
-		{        REG_TEST(0,3), 0x00000020 },
-		{        REG_TEST(1,3), 0x00000020 },
-			/* Port config */
-		{       REG_MAX_LEN(3), 0x00002710 },
-		{     REG_PORT_FAIL(3), 0x00000002 },
-		{    REG_NORMALIZER(3), 0x00000a64 },
-		{        REG_DENORM(3), 0x00000010 },
-		{     REG_STICK_BIT(3), 0x03baa370 },
-		{     REG_DEV_SETUP(3), 0x00000083 },
-		{     REG_DEV_SETUP(3), 0x00000082 },
-		{      REG_MODE_CFG(3), 0x0200259f },
-	},
-};
-
-static void run_table(adapter_t *adapter, struct init_table *ib, int len)
-{
-	int i;
-
-	for (i = 0; i < len; i++) {
-		if (ib[i].addr == INITBLOCK_SLEEP) {
-			udelay( ib[i].data );
-			pr_err("sleep %d us\n",ib[i].data);
-		} else
-			vsc_write( adapter, ib[i].addr, ib[i].data );
-	}
-}
-
-static int bist_rd(adapter_t *adapter, int moduleid, int address)
-{
-	int data = 0;
-	u32 result = 0;
-
-	if ((address != 0x0) &&
-	    (address != 0x1) &&
-	    (address != 0x2) &&
-	    (address != 0xd) &&
-	    (address != 0xe))
-			pr_err("No bist address: 0x%x\n", address);
-
-	data = ((0x00 << 24) | ((address & 0xff) << 16) | (0x00 << 8) |
-		((moduleid & 0xff) << 0));
-	vsc_write(adapter, REG_RAM_BIST_CMD, data);
-
-	udelay(10);
-
-	vsc_read(adapter, REG_RAM_BIST_RESULT, &result);
-	if ((result & (1 << 9)) != 0x0)
-		pr_err("Still in bist read: 0x%x\n", result);
-	else if ((result & (1 << 8)) != 0x0)
-		pr_err("bist read error: 0x%x\n", result);
-
-	return result & 0xff;
-}
-
-static int bist_wr(adapter_t *adapter, int moduleid, int address, int value)
-{
-	int data = 0;
-	u32 result = 0;
-
-	if ((address != 0x0) &&
-	    (address != 0x1) &&
-	    (address != 0x2) &&
-	    (address != 0xd) &&
-	    (address != 0xe))
-			pr_err("No bist address: 0x%x\n", address);
-
-	if (value > 255)
-		pr_err("Suspicious write out of range value: 0x%x\n", value);
-
-	data = ((0x01 << 24) | ((address & 0xff) << 16) | (value << 8) |
-		((moduleid & 0xff) << 0));
-	vsc_write(adapter, REG_RAM_BIST_CMD, data);
-
-	udelay(5);
-
-	vsc_read(adapter, REG_RAM_BIST_CMD, &result);
-	if ((result & (1 << 27)) != 0x0)
-		pr_err("Still in bist write: 0x%x\n", result);
-	else if ((result & (1 << 26)) != 0x0)
-		pr_err("bist write error: 0x%x\n", result);
-
-	return 0;
-}
-
-static int run_bist(adapter_t *adapter, int moduleid)
-{
-	/*run bist*/
-	(void) bist_wr(adapter,moduleid, 0x00, 0x02);
-	(void) bist_wr(adapter,moduleid, 0x01, 0x01);
-
-	return 0;
-}
-
-static int check_bist(adapter_t *adapter, int moduleid)
-{
-	int result=0;
-	int column=0;
-	/*check bist*/
-	result = bist_rd(adapter,moduleid, 0x02);
-	column = ((bist_rd(adapter,moduleid, 0x0e)<<8) +
-			(bist_rd(adapter,moduleid, 0x0d)));
-	if ((result & 3) != 0x3)
-		pr_err("Result: 0x%x  BIST error in ram %d, column: 0x%04x\n",
-			result, moduleid, column);
-	return 0;
-}
-
-static int enable_mem(adapter_t *adapter, int moduleid)
-{
-	/*enable mem*/
-	(void) bist_wr(adapter,moduleid, 0x00, 0x00);
-	return 0;
-}
-
-static int run_bist_all(adapter_t *adapter)
-{
-	int port = 0;
-	u32 val = 0;
-
-	vsc_write(adapter, REG_MEM_BIST, 0x5);
-	vsc_read(adapter, REG_MEM_BIST, &val);
-
-	for (port = 0; port < 12; port++)
-		vsc_write(adapter, REG_DEV_SETUP(port), 0x0);
-
-	udelay(300);
-	vsc_write(adapter, REG_SPI4_MISC, 0x00040409);
-	udelay(300);
-
-	(void) run_bist(adapter,13);
-	(void) run_bist(adapter,14);
-	(void) run_bist(adapter,20);
-	(void) run_bist(adapter,21);
-	mdelay(200);
-	(void) check_bist(adapter,13);
-	(void) check_bist(adapter,14);
-	(void) check_bist(adapter,20);
-	(void) check_bist(adapter,21);
-	udelay(100);
-	(void) enable_mem(adapter,13);
-	(void) enable_mem(adapter,14);
-	(void) enable_mem(adapter,20);
-	(void) enable_mem(adapter,21);
-	udelay(300);
-	vsc_write(adapter, REG_SPI4_MISC, 0x60040400);
-	udelay(300);
-	for (port = 0; port < 12; port++)
-		vsc_write(adapter, REG_DEV_SETUP(port), 0x1);
-
-	udelay(300);
-	vsc_write(adapter, REG_MEM_BIST, 0x0);
-	mdelay(10);
-	return 0;
-}
-
-static int mac_intr_handler(struct cmac *mac)
-{
-	return 0;
-}
-
-static int mac_intr_enable(struct cmac *mac)
-{
-	return 0;
-}
-
-static int mac_intr_disable(struct cmac *mac)
-{
-	return 0;
-}
-
-static int mac_intr_clear(struct cmac *mac)
-{
-	return 0;
-}
-
-/* Expect MAC address to be in network byte order. */
-static int mac_set_address(struct cmac* mac, u8 addr[6])
-{
-	u32 val;
-	int port = mac->instance->index;
-
-	vsc_write(mac->adapter, REG_MAC_LOW_ADDR(port),
-		  (addr[3] << 16) | (addr[4] << 8) | addr[5]);
-	vsc_write(mac->adapter, REG_MAC_HIGH_ADDR(port),
-		  (addr[0] << 16) | (addr[1] << 8) | addr[2]);
-
-	vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &val);
-	val &= ~0xf0000000;
-	vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, val | (port << 28));
-
-	vsc_write(mac->adapter, REG_ING_FFILT_MASK0,
-		  0xffff0000 | (addr[4] << 8) | addr[5]);
-	vsc_write(mac->adapter, REG_ING_FFILT_MASK1,
-		  0xffff0000 | (addr[2] << 8) | addr[3]);
-	vsc_write(mac->adapter, REG_ING_FFILT_MASK2,
-		  0xffff0000 | (addr[0] << 8) | addr[1]);
-	return 0;
-}
-
-static int mac_get_address(struct cmac *mac, u8 addr[6])
-{
-	u32 addr_lo, addr_hi;
-	int port = mac->instance->index;
-
-	vsc_read(mac->adapter, REG_MAC_LOW_ADDR(port), &addr_lo);
-	vsc_read(mac->adapter, REG_MAC_HIGH_ADDR(port), &addr_hi);
-
-	addr[0] = (u8) (addr_hi >> 16);
-	addr[1] = (u8) (addr_hi >> 8);
-	addr[2] = (u8) addr_hi;
-	addr[3] = (u8) (addr_lo >> 16);
-	addr[4] = (u8) (addr_lo >> 8);
-	addr[5] = (u8) addr_lo;
-	return 0;
-}
-
-/* This is intended to reset a port, not the whole MAC */
-static int mac_reset(struct cmac *mac)
-{
-	int index = mac->instance->index;
-
-	run_table(mac->adapter, vsc7326_portinit[index],
-		  ARRAY_SIZE(vsc7326_portinit[index]));
-
-	return 0;
-}
-
-static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm)
-{
-	u32 v;
-	int port = mac->instance->index;
-
-	vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &v);
-	v |= 1 << 12;
-
-	if (t1_rx_mode_promisc(rm))
-		v &= ~(1 << (port + 16));
-	else
-		v |= 1 << (port + 16);
-
-	vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, v);
-	return 0;
-}
-
-static int mac_set_mtu(struct cmac *mac, int mtu)
-{
-	int port = mac->instance->index;
-
-	if (mtu > MAX_MTU)
-		return -EINVAL;
-
-	/* max_len includes header and FCS */
-	vsc_write(mac->adapter, REG_MAX_LEN(port), mtu + 14 + 4);
-	return 0;
-}
-
-static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex,
-				   int fc)
-{
-	u32 v;
-	int enable, port = mac->instance->index;
-
-	if (speed >= 0 && speed != SPEED_10 && speed != SPEED_100 &&
-	    speed != SPEED_1000)
-		return -1;
-	if (duplex > 0 && duplex != DUPLEX_FULL)
-		return -1;
-
-	if (speed >= 0) {
-		vsc_read(mac->adapter, REG_MODE_CFG(port), &v);
-		enable = v & 3;             /* save tx/rx enables */
-		v &= ~0xf;
-		v |= 4;                     /* full duplex */
-		if (speed == SPEED_1000)
-			v |= 8;             /* GigE */
-		enable |= v;
-		vsc_write(mac->adapter, REG_MODE_CFG(port), v);
-
-		if (speed == SPEED_1000)
-			v = 0x82;
-		else if (speed == SPEED_100)
-			v = 0x84;
-		else	/* SPEED_10 */
-			v = 0x86;
-		vsc_write(mac->adapter, REG_DEV_SETUP(port), v | 1); /* reset */
-		vsc_write(mac->adapter, REG_DEV_SETUP(port), v);
-		vsc_read(mac->adapter, REG_DBG(port), &v);
-		v &= ~0xff00;
-		if (speed == SPEED_1000)
-			v |= 0x400;
-		else if (speed == SPEED_100)
-			v |= 0x2000;
-		else	/* SPEED_10 */
-			v |= 0xff00;
-		vsc_write(mac->adapter, REG_DBG(port), v);
-
-		vsc_write(mac->adapter, REG_TX_IFG(port),
-			  speed == SPEED_1000 ? 5 : 0x11);
-		if (duplex == DUPLEX_HALF)
-			enable = 0x0;	/* 100 or 10 */
-		else if (speed == SPEED_1000)
-			enable = 0xc;
-		else	/* SPEED_100 or 10 */
-			enable = 0x4;
-		enable |= 0x9 << 10;	/* IFG1 */
-		enable |= 0x6 << 6;	/* IFG2 */
-		enable |= 0x1 << 4;	/* VLAN */
-		enable |= 0x3;		/* RX/TX EN */
-		vsc_write(mac->adapter, REG_MODE_CFG(port), enable);
-
-	}
-
-	vsc_read(mac->adapter, REG_PAUSE_CFG(port), &v);
-	v &= 0xfff0ffff;
-	v |= 0x20000;      /* xon/xoff */
-	if (fc & PAUSE_RX)
-		v |= 0x40000;
-	if (fc & PAUSE_TX)
-		v |= 0x80000;
-	if (fc == (PAUSE_RX | PAUSE_TX))
-		v |= 0x10000;
-	vsc_write(mac->adapter, REG_PAUSE_CFG(port), v);
-	return 0;
-}
-
-static int mac_enable(struct cmac *mac, int which)
-{
-	u32 val;
-	int port = mac->instance->index;
-
-	/* Write the correct WM value when the port is enabled. */
-	vsc_write(mac->adapter, REG_HIGH_LOW_WM(1,port), WM_ENABLE);
-
-	vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
-	if (which & MAC_DIRECTION_RX)
-		val |= 0x2;
-	if (which & MAC_DIRECTION_TX)
-		val |= 1;
-	vsc_write(mac->adapter, REG_MODE_CFG(port), val);
-	return 0;
-}
-
-static int mac_disable(struct cmac *mac, int which)
-{
-	u32 val;
-	int i, port = mac->instance->index;
-
-	/* Reset the port, this also writes the correct WM value */
-	mac_reset(mac);
-
-	vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
-	if (which & MAC_DIRECTION_RX)
-		val &= ~0x2;
-	if (which & MAC_DIRECTION_TX)
-		val &= ~0x1;
-	vsc_write(mac->adapter, REG_MODE_CFG(port), val);
-	vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
-
-	/* Clear stats */
-	for (i = 0; i <= 0x3a; ++i)
-		vsc_write(mac->adapter, CRA(4, port, i), 0);
-
-	/* Clear software counters */
-	memset(&mac->stats, 0, sizeof(struct cmac_statistics));
-
-	return 0;
-}
-
-static void rmon_update(struct cmac *mac, unsigned int addr, u64 *stat)
-{
-	u32 v, lo;
-
-	vsc_read(mac->adapter, addr, &v);
-	lo = *stat;
-	*stat = *stat - lo + v;
-
-	if (v == 0)
-		return;
-
-	if (v < lo)
-		*stat += (1ULL << 32);
-}
-
-static void port_stats_update(struct cmac *mac)
-{
-	struct {
-		unsigned int reg;
-		unsigned int offset;
-	} hw_stats[] = {
-
-#define HW_STAT(reg, stat_name) \
-	{ reg, (&((struct cmac_statistics *)NULL)->stat_name) - (u64 *)NULL }
-
-		/* Rx stats */
-		HW_STAT(RxUnicast, RxUnicastFramesOK),
-		HW_STAT(RxMulticast, RxMulticastFramesOK),
-		HW_STAT(RxBroadcast, RxBroadcastFramesOK),
-		HW_STAT(Crc, RxFCSErrors),
-		HW_STAT(RxAlignment, RxAlignErrors),
-		HW_STAT(RxOversize, RxFrameTooLongErrors),
-		HW_STAT(RxPause, RxPauseFrames),
-		HW_STAT(RxJabbers, RxJabberErrors),
-		HW_STAT(RxFragments, RxRuntErrors),
-		HW_STAT(RxUndersize, RxRuntErrors),
-		HW_STAT(RxSymbolCarrier, RxSymbolErrors),
-		HW_STAT(RxSize1519ToMax, RxJumboFramesOK),
-
-		/* Tx stats (skip collision stats as we are full-duplex only) */
-		HW_STAT(TxUnicast, TxUnicastFramesOK),
-		HW_STAT(TxMulticast, TxMulticastFramesOK),
-		HW_STAT(TxBroadcast, TxBroadcastFramesOK),
-		HW_STAT(TxPause, TxPauseFrames),
-		HW_STAT(TxUnderrun, TxUnderrun),
-		HW_STAT(TxSize1519ToMax, TxJumboFramesOK),
-	}, *p = hw_stats;
-	unsigned int port = mac->instance->index;
-	u64 *stats = (u64 *)&mac->stats;
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(hw_stats); i++)
-		rmon_update(mac, CRA(0x4, port, p->reg), stats + p->offset);
-
-	rmon_update(mac, REG_TX_OK_BYTES(port), &mac->stats.TxOctetsOK);
-	rmon_update(mac, REG_RX_OK_BYTES(port), &mac->stats.RxOctetsOK);
-	rmon_update(mac, REG_RX_BAD_BYTES(port), &mac->stats.RxOctetsBad);
-}
-
-/*
- * This function is called periodically to accumulate the current values of the
- * RMON counters into the port statistics.  Since the counters are only 32 bits
- * some of them can overflow in less than a minute at GigE speeds, so this
- * function should be called every 30 seconds or so.
- *
- * To cut down on reading costs we update only the octet counters at each tick
- * and do a full update at major ticks, which can be every 30 minutes or more.
- */
-static const struct cmac_statistics *mac_update_statistics(struct cmac *mac,
-							   int flag)
-{
-	if (flag == MAC_STATS_UPDATE_FULL ||
-	    mac->instance->ticks >= MAJOR_UPDATE_TICKS) {
-		port_stats_update(mac);
-		mac->instance->ticks = 0;
-	} else {
-		int port = mac->instance->index;
-
-		rmon_update(mac, REG_RX_OK_BYTES(port),
-			    &mac->stats.RxOctetsOK);
-		rmon_update(mac, REG_RX_BAD_BYTES(port),
-			    &mac->stats.RxOctetsBad);
-		rmon_update(mac, REG_TX_OK_BYTES(port),
-			    &mac->stats.TxOctetsOK);
-		mac->instance->ticks++;
-	}
-	return &mac->stats;
-}
-
-static void mac_destroy(struct cmac *mac)
-{
-	kfree(mac);
-}
-
-static struct cmac_ops vsc7326_ops = {
-	.destroy                  = mac_destroy,
-	.reset                    = mac_reset,
-	.interrupt_handler        = mac_intr_handler,
-	.interrupt_enable         = mac_intr_enable,
-	.interrupt_disable        = mac_intr_disable,
-	.interrupt_clear          = mac_intr_clear,
-	.enable                   = mac_enable,
-	.disable                  = mac_disable,
-	.set_mtu                  = mac_set_mtu,
-	.set_rx_mode              = mac_set_rx_mode,
-	.set_speed_duplex_fc      = mac_set_speed_duplex_fc,
-	.statistics_update        = mac_update_statistics,
-	.macaddress_get           = mac_get_address,
-	.macaddress_set           = mac_set_address,
-};
-
-static struct cmac *vsc7326_mac_create(adapter_t *adapter, int index)
-{
-	struct cmac *mac;
-	u32 val;
-	int i;
-
-	mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL);
-	if (!mac)
-		return NULL;
-
-	mac->ops = &vsc7326_ops;
-	mac->instance = (cmac_instance *)(mac + 1);
-	mac->adapter  = adapter;
-
-	mac->instance->index = index;
-	mac->instance->ticks = 0;
-
-	i = 0;
-	do {
-		u32 vhi, vlo;
-
-		vhi = vlo = 0;
-		t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo);
-		udelay(1);
-		t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi);
-		udelay(5);
-		val = (vhi << 16) | vlo;
-	} while ((++i < 10000) && (val == 0xffffffff));
-
-	return mac;
-}
-
-static int vsc7326_mac_reset(adapter_t *adapter)
-{
-	vsc7326_full_reset(adapter);
-	(void) run_bist_all(adapter);
-	run_table(adapter, vsc7326_reset, ARRAY_SIZE(vsc7326_reset));
-	return 0;
-}
-
-const struct gmac t1_vsc7326_ops = {
-	.stats_update_period = STATS_TICK_SECS,
-	.create              = vsc7326_mac_create,
-	.reset               = vsc7326_mac_reset,
-};
diff -druN linux-libre-3.1-gnu/drivers/net/chelsio/vsc7326_reg.h linux-libre-3.2-gnu/drivers/net/chelsio/vsc7326_reg.h
--- linux-libre-3.1-gnu/drivers/net/chelsio/vsc7326_reg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/chelsio/vsc7326_reg.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,297 +0,0 @@
-/* $Date: 2006/04/28 19:20:17 $ $RCSfile: vsc7326_reg.h,v $ $Revision: 1.5 $ */
-#ifndef _VSC7321_REG_H_
-#define _VSC7321_REG_H_
-
-/* Register definitions for Vitesse VSC7321 (Meigs II) MAC
- *
- * Straight off the data sheet, VMDS-10038 Rev 2.0 and
- * PD0011-01-14-Meigs-II 2002-12-12
- */
-
-/* Just 'cause it's in here doesn't mean it's used. */
-
-#define CRA(blk,sub,adr) ((((blk) & 0x7) << 13) | (((sub) & 0xf) << 9) | (((adr) & 0xff) << 1))
-
-/* System and CPU comm's registers */
-#define REG_CHIP_ID		CRA(0x7,0xf,0x00)	/* Chip ID */
-#define REG_BLADE_ID		CRA(0x7,0xf,0x01)	/* Blade ID */
-#define REG_SW_RESET		CRA(0x7,0xf,0x02)	/* Global Soft Reset */
-#define REG_MEM_BIST		CRA(0x7,0xf,0x04)	/* mem */
-#define REG_IFACE_MODE		CRA(0x7,0xf,0x07)	/* Interface mode */
-#define REG_MSCH		CRA(0x7,0x2,0x06)	/* CRC error count */
-#define REG_CRC_CNT		CRA(0x7,0x2,0x0a)	/* CRC error count */
-#define REG_CRC_CFG		CRA(0x7,0x2,0x0b)	/* CRC config */
-#define REG_SI_TRANSFER_SEL	CRA(0x7,0xf,0x18)	/* SI Transfer Select */
-#define REG_PLL_CLK_SPEED	CRA(0x7,0xf,0x19)	/* Clock Speed Selection */
-#define REG_SYS_CLK_SELECT	CRA(0x7,0xf,0x1c)	/* System Clock Select */
-#define REG_GPIO_CTRL		CRA(0x7,0xf,0x1d)	/* GPIO Control */
-#define REG_GPIO_OUT		CRA(0x7,0xf,0x1e)	/* GPIO Out */
-#define REG_GPIO_IN		CRA(0x7,0xf,0x1f)	/* GPIO In */
-#define REG_CPU_TRANSFER_SEL	CRA(0x7,0xf,0x20)	/* CPU Transfer Select */
-#define REG_LOCAL_DATA		CRA(0x7,0xf,0xfe)	/* Local CPU Data Register */
-#define REG_LOCAL_STATUS	CRA(0x7,0xf,0xff)	/* Local CPU Status Register */
-
-/* Aggregator registers */
-#define REG_AGGR_SETUP		CRA(0x7,0x1,0x00)	/* Aggregator Setup */
-#define REG_PMAP_TABLE		CRA(0x7,0x1,0x01)	/* Port map table */
-#define REG_MPLS_BIT0		CRA(0x7,0x1,0x08)	/* MPLS bit0 position */
-#define REG_MPLS_BIT1		CRA(0x7,0x1,0x09)	/* MPLS bit1 position */
-#define REG_MPLS_BIT2		CRA(0x7,0x1,0x0a)	/* MPLS bit2 position */
-#define REG_MPLS_BIT3		CRA(0x7,0x1,0x0b)	/* MPLS bit3 position */
-#define REG_MPLS_BITMASK	CRA(0x7,0x1,0x0c)	/* MPLS bit mask */
-#define REG_PRE_BIT0POS		CRA(0x7,0x1,0x10)	/* Preamble bit0 position */
-#define REG_PRE_BIT1POS		CRA(0x7,0x1,0x11)	/* Preamble bit1 position */
-#define REG_PRE_BIT2POS		CRA(0x7,0x1,0x12)	/* Preamble bit2 position */
-#define REG_PRE_BIT3POS		CRA(0x7,0x1,0x13)	/* Preamble bit3 position */
-#define REG_PRE_ERR_CNT		CRA(0x7,0x1,0x14)	/* Preamble parity error count */
-
-/* BIST registers */
-/*#define REG_RAM_BIST_CMD	CRA(0x7,0x2,0x00)*/	/* RAM BIST Command Register */
-/*#define REG_RAM_BIST_RESULT	CRA(0x7,0x2,0x01)*/	/* RAM BIST Read Status/Result */
-#define REG_RAM_BIST_CMD	CRA(0x7,0x1,0x00)	/* RAM BIST Command Register */
-#define REG_RAM_BIST_RESULT	CRA(0x7,0x1,0x01)	/* RAM BIST Read Status/Result */
-#define   BIST_PORT_SELECT	0x00			/* BIST port select */
-#define   BIST_COMMAND		0x01			/* BIST enable/disable */
-#define   BIST_STATUS		0x02			/* BIST operation status */
-#define   BIST_ERR_CNT_LSB	0x03			/* BIST error count lo 8b */
-#define   BIST_ERR_CNT_MSB	0x04			/* BIST error count hi 8b */
-#define   BIST_ERR_SEL_LSB	0x05			/* BIST error select lo 8b */
-#define   BIST_ERR_SEL_MSB	0x06			/* BIST error select hi 8b */
-#define   BIST_ERROR_STATE	0x07			/* BIST engine internal state */
-#define   BIST_ERR_ADR0		0x08			/* BIST error address lo 8b */
-#define   BIST_ERR_ADR1		0x09			/* BIST error address lomid 8b */
-#define   BIST_ERR_ADR2		0x0a			/* BIST error address himid 8b */
-#define   BIST_ERR_ADR3		0x0b			/* BIST error address hi 8b */
-
-/* FIFO registers
- *   ie = 0 for ingress, 1 for egress
- *   fn = FIFO number, 0-9
- */
-#define REG_TEST(ie,fn)		CRA(0x2,ie&1,0x00+fn)	/* Mode & Test Register */
-#define REG_TOP_BOTTOM(ie,fn)	CRA(0x2,ie&1,0x10+fn)	/* FIFO Buffer Top & Bottom */
-#define REG_TAIL(ie,fn)		CRA(0x2,ie&1,0x20+fn)	/* FIFO Write Pointer */
-#define REG_HEAD(ie,fn)		CRA(0x2,ie&1,0x30+fn)	/* FIFO Read Pointer */
-#define REG_HIGH_LOW_WM(ie,fn)	CRA(0x2,ie&1,0x40+fn)	/* Flow Control Water Marks */
-#define REG_CT_THRHLD(ie,fn)	CRA(0x2,ie&1,0x50+fn)	/* Cut Through Threshold */
-#define REG_FIFO_DROP_CNT(ie,fn) CRA(0x2,ie&1,0x60+fn)	/* Drop & CRC Error Counter */
-#define REG_DEBUG_BUF_CNT(ie,fn) CRA(0x2,ie&1,0x70+fn)	/* Input Side Debug Counter */
-#define REG_BUCKI(fn) CRA(0x2,2,0x20+fn)	/* Input Side Debug Counter */
-#define REG_BUCKE(fn) CRA(0x2,3,0x20+fn)	/* Input Side Debug Counter */
-
-/* Traffic shaper buckets
- *   ie = 0 for ingress, 1 for egress
- *   bn = bucket number 0-10 (yes, 11 buckets)
- */
-/* OK, this one's kinda ugly.  Some hardware designers are perverse. */
-#define REG_TRAFFIC_SHAPER_BUCKET(ie,bn) CRA(0x2,ie&1,0x0a + (bn>7) | ((bn&7)<<4))
-#define REG_TRAFFIC_SHAPER_CONTROL(ie)	CRA(0x2,ie&1,0x3b)
-
-#define REG_SRAM_ADR(ie)	CRA(0x2,ie&1,0x0e)	/* FIFO SRAM address */
-#define REG_SRAM_WR_STRB(ie)	CRA(0x2,ie&1,0x1e)	/* FIFO SRAM write strobe */
-#define REG_SRAM_RD_STRB(ie)	CRA(0x2,ie&1,0x2e)	/* FIFO SRAM read strobe */
-#define REG_SRAM_DATA_0(ie)	CRA(0x2,ie&1,0x3e)	/* FIFO SRAM data lo 8b */
-#define REG_SRAM_DATA_1(ie)	CRA(0x2,ie&1,0x4e)	/* FIFO SRAM data lomid 8b */
-#define REG_SRAM_DATA_2(ie)	CRA(0x2,ie&1,0x5e)	/* FIFO SRAM data himid 8b */
-#define REG_SRAM_DATA_3(ie)	CRA(0x2,ie&1,0x6e)	/* FIFO SRAM data hi 8b */
-#define REG_SRAM_DATA_BLK_TYPE(ie) CRA(0x2,ie&1,0x7e)	/* FIFO SRAM tag */
-/* REG_ING_CONTROL equals REG_CONTROL with ie = 0, likewise REG_EGR_CONTROL is ie = 1 */
-#define REG_CONTROL(ie)		CRA(0x2,ie&1,0x0f)	/* FIFO control */
-#define REG_ING_CONTROL		CRA(0x2,0x0,0x0f)	/* Ingress control (alias) */
-#define REG_EGR_CONTROL		CRA(0x2,0x1,0x0f)	/* Egress control (alias) */
-#define REG_AGE_TIMER(ie)	CRA(0x2,ie&1,0x1f)	/* Aging timer */
-#define REG_AGE_INC(ie)		CRA(0x2,ie&1,0x2f)	/* Aging increment */
-#define DEBUG_OUT(ie)		CRA(0x2,ie&1,0x3f)	/* Output debug counter control */
-#define DEBUG_CNT(ie)		CRA(0x2,ie&1,0x4f)	/* Output debug counter */
-
-/* SPI4 interface */
-#define REG_SPI4_MISC		CRA(0x5,0x0,0x00)	/* Misc Register */
-#define REG_SPI4_STATUS		CRA(0x5,0x0,0x01)	/* CML Status */
-#define REG_SPI4_ING_SETUP0	CRA(0x5,0x0,0x02)	/* Ingress Status Channel Setup */
-#define REG_SPI4_ING_SETUP1	CRA(0x5,0x0,0x03)	/* Ingress Data Training Setup */
-#define REG_SPI4_ING_SETUP2	CRA(0x5,0x0,0x04)	/* Ingress Data Burst Size Setup */
-#define REG_SPI4_EGR_SETUP0	CRA(0x5,0x0,0x05)	/* Egress Status Channel Setup */
-#define REG_SPI4_DBG_CNT(n)	CRA(0x5,0x0,0x10+n)	/* Debug counters 0-9 */
-#define REG_SPI4_DBG_SETUP	CRA(0x5,0x0,0x1A)	/* Debug counters setup */
-#define REG_SPI4_TEST		CRA(0x5,0x0,0x20)	/* Test Setup Register */
-#define REG_TPGEN_UP0		CRA(0x5,0x0,0x21)	/* Test Pattern generator user pattern 0 */
-#define REG_TPGEN_UP1		CRA(0x5,0x0,0x22)	/* Test Pattern generator user pattern 1 */
-#define REG_TPCHK_UP0		CRA(0x5,0x0,0x23)	/* Test Pattern checker user pattern 0 */
-#define REG_TPCHK_UP1		CRA(0x5,0x0,0x24)	/* Test Pattern checker user pattern 1 */
-#define REG_TPSAM_P0		CRA(0x5,0x0,0x25)	/* Sampled pattern 0 */
-#define REG_TPSAM_P1		CRA(0x5,0x0,0x26)	/* Sampled pattern 1 */
-#define REG_TPERR_CNT		CRA(0x5,0x0,0x27)	/* Pattern checker error counter */
-#define REG_SPI4_STICKY		CRA(0x5,0x0,0x30)	/* Sticky bits register */
-#define REG_SPI4_DBG_INH	CRA(0x5,0x0,0x31)	/* Core egress & ingress inhibit */
-#define REG_SPI4_DBG_STATUS	CRA(0x5,0x0,0x32)	/* Sampled ingress status */
-#define REG_SPI4_DBG_GRANT	CRA(0x5,0x0,0x33)	/* Ingress cranted credit value */
-
-#define REG_SPI4_DESKEW 	CRA(0x5,0x0,0x43)	/* Ingress cranted credit value */
-
-/* 10GbE MAC Block Registers */
-/* Note that those registers that are exactly the same for 10GbE as for
- * tri-speed are only defined with the version that needs a port number.
- * Pass 0xa in those cases.
- *
- * Also note that despite the presence of a MAC address register, this part
- * does no ingress MAC address filtering.  That register is used only for
- * pause frame detection and generation.
- */
-/* 10GbE specific, and different from tri-speed */
-#define REG_MISC_10G		CRA(0x1,0xa,0x00)	/* Misc 10GbE setup */
-#define REG_PAUSE_10G		CRA(0x1,0xa,0x01)	/* Pause register */
-#define REG_NORMALIZER_10G	CRA(0x1,0xa,0x05)	/* 10G normalizer */
-#define REG_STICKY_RX		CRA(0x1,0xa,0x06)	/* RX debug register */
-#define REG_DENORM_10G		CRA(0x1,0xa,0x07)	/* Denormalizer  */
-#define REG_STICKY_TX		CRA(0x1,0xa,0x08)	/* TX sticky bits */
-#define REG_MAX_RXHIGH		CRA(0x1,0xa,0x0a)	/* XGMII lane 0-3 debug */
-#define REG_MAX_RXLOW		CRA(0x1,0xa,0x0b)	/* XGMII lane 4-7 debug */
-#define REG_MAC_TX_STICKY	CRA(0x1,0xa,0x0c)	/* MAC Tx state sticky debug */
-#define REG_MAC_TX_RUNNING	CRA(0x1,0xa,0x0d)	/* MAC Tx state running debug */
-#define REG_TX_ABORT_AGE	CRA(0x1,0xa,0x14)	/* Aged Tx frames discarded */
-#define REG_TX_ABORT_SHORT	CRA(0x1,0xa,0x15)	/* Short Tx frames discarded */
-#define REG_TX_ABORT_TAXI	CRA(0x1,0xa,0x16)	/* Taxi error frames discarded */
-#define REG_TX_ABORT_UNDERRUN	CRA(0x1,0xa,0x17)	/* Tx Underrun abort counter */
-#define REG_TX_DENORM_DISCARD	CRA(0x1,0xa,0x18)	/* Tx denormalizer discards */
-#define REG_XAUI_STAT_A		CRA(0x1,0xa,0x20)	/* XAUI status A */
-#define REG_XAUI_STAT_B		CRA(0x1,0xa,0x21)	/* XAUI status B */
-#define REG_XAUI_STAT_C		CRA(0x1,0xa,0x22)	/* XAUI status C */
-#define REG_XAUI_CONF_A		CRA(0x1,0xa,0x23)	/* XAUI configuration A */
-#define REG_XAUI_CONF_B		CRA(0x1,0xa,0x24)	/* XAUI configuration B */
-#define REG_XAUI_CODE_GRP_CNT	CRA(0x1,0xa,0x25)	/* XAUI code group error count */
-#define REG_XAUI_CONF_TEST_A	CRA(0x1,0xa,0x26)	/* XAUI test register A */
-#define REG_PDERRCNT		CRA(0x1,0xa,0x27)	/* XAUI test register B */
-
-/* pn = port number 0-9 for tri-speed, 10 for 10GbE */
-/* Both tri-speed and 10GbE */
-#define REG_MAX_LEN(pn)		CRA(0x1,pn,0x02)	/* Max length */
-#define REG_MAC_HIGH_ADDR(pn)	CRA(0x1,pn,0x03)	/* Upper 24 bits of MAC addr */
-#define REG_MAC_LOW_ADDR(pn)	CRA(0x1,pn,0x04)	/* Lower 24 bits of MAC addr */
-
-/* tri-speed only
- * pn = port number, 0-9
- */
-#define REG_MODE_CFG(pn)	CRA(0x1,pn,0x00)	/* Mode configuration */
-#define REG_PAUSE_CFG(pn)	CRA(0x1,pn,0x01)	/* Pause configuration */
-#define REG_NORMALIZER(pn)	CRA(0x1,pn,0x05)	/* Normalizer */
-#define REG_TBI_STATUS(pn)	CRA(0x1,pn,0x06)	/* TBI status */
-#define REG_PCS_STATUS_DBG(pn)	CRA(0x1,pn,0x07)	/* PCS status debug */
-#define REG_PCS_CTRL(pn)	CRA(0x1,pn,0x08)	/* PCS control */
-#define REG_TBI_CONFIG(pn)	CRA(0x1,pn,0x09)	/* TBI configuration */
-#define REG_STICK_BIT(pn)	CRA(0x1,pn,0x0a)	/* Sticky bits */
-#define REG_DEV_SETUP(pn)	CRA(0x1,pn,0x0b)	/* MAC clock/reset setup */
-#define REG_DROP_CNT(pn)	CRA(0x1,pn,0x0c)	/* Drop counter */
-#define REG_PORT_POS(pn)	CRA(0x1,pn,0x0d)	/* Preamble port position */
-#define REG_PORT_FAIL(pn)	CRA(0x1,pn,0x0e)	/* Preamble port position */
-#define REG_SERDES_CONF(pn)	CRA(0x1,pn,0x0f)	/* SerDes configuration */
-#define REG_SERDES_TEST(pn)	CRA(0x1,pn,0x10)	/* SerDes test */
-#define REG_SERDES_STAT(pn)	CRA(0x1,pn,0x11)	/* SerDes status */
-#define REG_SERDES_COM_CNT(pn)	CRA(0x1,pn,0x12)	/* SerDes comma counter */
-#define REG_DENORM(pn)		CRA(0x1,pn,0x15)	/* Frame denormalization */
-#define REG_DBG(pn)		CRA(0x1,pn,0x16)	/* Device 1G debug */
-#define REG_TX_IFG(pn)		CRA(0x1,pn,0x18)	/* Tx IFG config */
-#define REG_HDX(pn)		CRA(0x1,pn,0x19)	/* Half-duplex config */
-
-/* Statistics */
-/* CRA(0x4,pn,reg) */
-/* reg below */
-/* pn = port number, 0-a, a = 10GbE */
-
-enum {
-	RxInBytes		= 0x00,	// # Rx in octets
-	RxSymbolCarrier		= 0x01,	// Frames w/ symbol errors
-	RxPause			= 0x02,	// # pause frames received
-	RxUnsupOpcode		= 0x03,	// # control frames with unsupported opcode
-	RxOkBytes		= 0x04,	// # octets in good frames
-	RxBadBytes		= 0x05,	// # octets in bad frames
-	RxUnicast		= 0x06,	// # good unicast frames
-	RxMulticast		= 0x07,	// # good multicast frames
-	RxBroadcast		= 0x08,	// # good broadcast frames
-	Crc			= 0x09,	// # frames w/ bad CRC only
-	RxAlignment		= 0x0a,	// # frames w/ alignment err
-	RxUndersize		= 0x0b,	// # frames undersize
-	RxFragments		= 0x0c,	// # frames undersize w/ crc err
-	RxInRangeLengthError	= 0x0d,	// # frames with length error
-	RxOutOfRangeError	= 0x0e,	// # frames with illegal length field
-	RxOversize		= 0x0f,	// # frames oversize
-	RxJabbers		= 0x10,	// # frames oversize w/ crc err
-	RxSize64		= 0x11,	// # frames 64 octets long
-	RxSize65To127		= 0x12,	// # frames 65-127 octets
-	RxSize128To255		= 0x13,	// # frames 128-255
-	RxSize256To511		= 0x14,	// # frames 256-511
-	RxSize512To1023		= 0x15,	// # frames 512-1023
-	RxSize1024To1518	= 0x16,	// # frames 1024-1518
-	RxSize1519ToMax		= 0x17,	// # frames 1519-max
-
-	TxOutBytes		= 0x18,	// # octets tx
-	TxPause			= 0x19,	// # pause frames sent
-	TxOkBytes		= 0x1a, // # octets tx OK
-	TxUnicast		= 0x1b,	// # frames unicast
-	TxMulticast		= 0x1c,	// # frames multicast
-	TxBroadcast		= 0x1d,	// # frames broadcast
-	TxMultipleColl		= 0x1e,	// # frames tx after multiple collisions
-	TxLateColl		= 0x1f,	// # late collisions detected
-	TxXcoll			= 0x20,	// # frames lost, excessive collisions
-	TxDefer			= 0x21,	// # frames deferred on first tx attempt
-	TxXdefer		= 0x22,	// # frames excessively deferred
-	TxCsense		= 0x23,	// carrier sense errors at frame end
-	TxSize64		= 0x24,	// # frames 64 octets long
-	TxSize65To127		= 0x25,	// # frames 65-127 octets
-	TxSize128To255		= 0x26,	// # frames 128-255
-	TxSize256To511		= 0x27,	// # frames 256-511
-	TxSize512To1023		= 0x28,	// # frames 512-1023
-	TxSize1024To1518	= 0x29,	// # frames 1024-1518
-	TxSize1519ToMax		= 0x2a,	// # frames 1519-max
-	TxSingleColl		= 0x2b,	// # frames tx after single collision
-	TxBackoff2		= 0x2c,	// # frames tx ok after 2 backoffs/collisions
-	TxBackoff3		= 0x2d,	//   after 3 backoffs/collisions
-	TxBackoff4		= 0x2e,	//   after 4
-	TxBackoff5		= 0x2f,	//   after 5
-	TxBackoff6		= 0x30,	//   after 6
-	TxBackoff7		= 0x31,	//   after 7
-	TxBackoff8		= 0x32,	//   after 8
-	TxBackoff9		= 0x33,	//   after 9
-	TxBackoff10		= 0x34,	//   after 10
-	TxBackoff11		= 0x35,	//   after 11
-	TxBackoff12		= 0x36,	//   after 12
-	TxBackoff13		= 0x37,	//   after 13
-	TxBackoff14		= 0x38,	//   after 14
-	TxBackoff15		= 0x39,	//   after 15
-	TxUnderrun		= 0x3a,	// # frames dropped from underrun
-	// Hole. See REG_RX_XGMII_PROT_ERR below.
-	RxIpgShrink		= 0x3c,	// # of IPG shrinks detected
-	// Duplicate. See REG_STAT_STICKY10G below.
-	StatSticky1G		= 0x3e,	// tri-speed sticky bits
-	StatInit		= 0x3f	// Clear all statistics
-};
-
-#define REG_RX_XGMII_PROT_ERR	CRA(0x4,0xa,0x3b)		/* # protocol errors detected on XGMII interface */
-#define REG_STAT_STICKY10G	CRA(0x4,0xa,StatSticky1G)	/* 10GbE sticky bits */
-
-#define REG_RX_OK_BYTES(pn)	CRA(0x4,pn,RxOkBytes)
-#define REG_RX_BAD_BYTES(pn)	CRA(0x4,pn,RxBadBytes)
-#define REG_TX_OK_BYTES(pn)	CRA(0x4,pn,TxOkBytes)
-
-/* MII-Management Block registers */
-/* These are for MII-M interface 0, which is the bidirectional LVTTL one.  If
- * we hooked up to the one with separate directions, the middle 0x0 needs to
- * change to 0x1.  And the current errata states that MII-M 1 doesn't work.
- */
-
-#define REG_MIIM_STATUS		CRA(0x3,0x0,0x00)	/* MII-M Status */
-#define REG_MIIM_CMD		CRA(0x3,0x0,0x01)	/* MII-M Command */
-#define REG_MIIM_DATA		CRA(0x3,0x0,0x02)	/* MII-M Data */
-#define REG_MIIM_PRESCALE	CRA(0x3,0x0,0x03)	/* MII-M MDC Prescale */
-
-#define REG_ING_FFILT_UM_EN	CRA(0x2, 0, 0xd)
-#define REG_ING_FFILT_BE_EN	CRA(0x2, 0, 0x1d)
-#define REG_ING_FFILT_VAL0	CRA(0x2, 0, 0x2d)
-#define REG_ING_FFILT_VAL1	CRA(0x2, 0, 0x3d)
-#define REG_ING_FFILT_MASK0	CRA(0x2, 0, 0x4d)
-#define REG_ING_FFILT_MASK1	CRA(0x2, 0, 0x5d)
-#define REG_ING_FFILT_MASK2	CRA(0x2, 0, 0x6d)
-#define REG_ING_FFILT_ETYPE	CRA(0x2, 0, 0x7d)
-
-
-/* Whew. */
-
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/cnic.c linux-libre-3.2-gnu/drivers/net/cnic.c
--- linux-libre-3.1-gnu/drivers/net/cnic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cnic.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,5487 +0,0 @@
-/* cnic.c: Broadcom CNIC core network driver.
- *
- * Copyright (c) 2006-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
- * the Free Software Foundation.
- *
- * Original skeleton written by: John(Zongxi) Chen (zongxi@broadcom.com)
- * Modified and maintained by: Michael Chan <mchan@broadcom.com>
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/uio_driver.h>
-#include <linux/in.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/ethtool.h>
-#include <linux/if_vlan.h>
-#include <linux/prefetch.h>
-#include <linux/random.h>
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-#define BCM_VLAN 1
-#endif
-#include <net/ip.h>
-#include <net/tcp.h>
-#include <net/route.h>
-#include <net/ipv6.h>
-#include <net/ip6_route.h>
-#include <net/ip6_checksum.h>
-#include <scsi/iscsi_if.h>
-
-#include "cnic_if.h"
-#include "bnx2.h"
-#include "bnx2x/bnx2x_reg.h"
-#include "bnx2x/bnx2x_fw_defs.h"
-#include "bnx2x/bnx2x_hsi.h"
-#include "../scsi/bnx2i/57xx_iscsi_constants.h"
-#include "../scsi/bnx2i/57xx_iscsi_hsi.h"
-#include "cnic.h"
-#include "cnic_defs.h"
-
-#define DRV_MODULE_NAME		"cnic"
-
-static char version[] __devinitdata =
-	"Broadcom NetXtreme II CNIC Driver " DRV_MODULE_NAME " v" CNIC_MODULE_VERSION " (" CNIC_MODULE_RELDATE ")\n";
-
-MODULE_AUTHOR("Michael Chan <mchan@broadcom.com> and John(Zongxi) "
-	      "Chen (zongxi@broadcom.com");
-MODULE_DESCRIPTION("Broadcom NetXtreme II CNIC Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(CNIC_MODULE_VERSION);
-
-/* cnic_dev_list modifications are protected by both rtnl and cnic_dev_lock */
-static LIST_HEAD(cnic_dev_list);
-static LIST_HEAD(cnic_udev_list);
-static DEFINE_RWLOCK(cnic_dev_lock);
-static DEFINE_MUTEX(cnic_lock);
-
-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 *);
-static int cnic_ctl(void *, struct cnic_ctl_info *);
-
-static struct cnic_ops cnic_bnx2_ops = {
-	.cnic_owner	= THIS_MODULE,
-	.cnic_handler	= cnic_service_bnx2,
-	.cnic_ctl	= cnic_ctl,
-};
-
-static struct cnic_ops cnic_bnx2x_ops = {
-	.cnic_owner	= THIS_MODULE,
-	.cnic_handler	= cnic_service_bnx2x,
-	.cnic_ctl	= cnic_ctl,
-};
-
-static struct workqueue_struct *cnic_wq;
-
-static void cnic_shutdown_rings(struct cnic_dev *);
-static void cnic_init_rings(struct cnic_dev *);
-static int cnic_cm_set_pg(struct cnic_sock *);
-
-static int cnic_uio_open(struct uio_info *uinfo, struct inode *inode)
-{
-	struct cnic_uio_dev *udev = uinfo->priv;
-	struct cnic_dev *dev;
-
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	if (udev->uio_dev != -1)
-		return -EBUSY;
-
-	rtnl_lock();
-	dev = udev->dev;
-
-	if (!dev || !test_bit(CNIC_F_CNIC_UP, &dev->flags)) {
-		rtnl_unlock();
-		return -ENODEV;
-	}
-
-	udev->uio_dev = iminor(inode);
-
-	cnic_shutdown_rings(dev);
-	cnic_init_rings(dev);
-	rtnl_unlock();
-
-	return 0;
-}
-
-static int cnic_uio_close(struct uio_info *uinfo, struct inode *inode)
-{
-	struct cnic_uio_dev *udev = uinfo->priv;
-
-	udev->uio_dev = -1;
-	return 0;
-}
-
-static inline void cnic_hold(struct cnic_dev *dev)
-{
-	atomic_inc(&dev->ref_count);
-}
-
-static inline void cnic_put(struct cnic_dev *dev)
-{
-	atomic_dec(&dev->ref_count);
-}
-
-static inline void csk_hold(struct cnic_sock *csk)
-{
-	atomic_inc(&csk->ref_count);
-}
-
-static inline void csk_put(struct cnic_sock *csk)
-{
-	atomic_dec(&csk->ref_count);
-}
-
-static struct cnic_dev *cnic_from_netdev(struct net_device *netdev)
-{
-	struct cnic_dev *cdev;
-
-	read_lock(&cnic_dev_lock);
-	list_for_each_entry(cdev, &cnic_dev_list, list) {
-		if (netdev == cdev->netdev) {
-			cnic_hold(cdev);
-			read_unlock(&cnic_dev_lock);
-			return cdev;
-		}
-	}
-	read_unlock(&cnic_dev_lock);
-	return NULL;
-}
-
-static inline void ulp_get(struct cnic_ulp_ops *ulp_ops)
-{
-	atomic_inc(&ulp_ops->ref_count);
-}
-
-static inline void ulp_put(struct cnic_ulp_ops *ulp_ops)
-{
-	atomic_dec(&ulp_ops->ref_count);
-}
-
-static void cnic_ctx_wr(struct cnic_dev *dev, u32 cid_addr, u32 off, u32 val)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	struct drv_ctl_info info;
-	struct drv_ctl_io *io = &info.data.io;
-
-	info.cmd = DRV_CTL_CTX_WR_CMD;
-	io->cid_addr = cid_addr;
-	io->offset = off;
-	io->data = val;
-	ethdev->drv_ctl(dev->netdev, &info);
-}
-
-static void cnic_ctx_tbl_wr(struct cnic_dev *dev, u32 off, dma_addr_t addr)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	struct drv_ctl_info info;
-	struct drv_ctl_io *io = &info.data.io;
-
-	info.cmd = DRV_CTL_CTXTBL_WR_CMD;
-	io->offset = off;
-	io->dma_addr = addr;
-	ethdev->drv_ctl(dev->netdev, &info);
-}
-
-static void cnic_ring_ctl(struct cnic_dev *dev, u32 cid, u32 cl_id, int start)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	struct drv_ctl_info info;
-	struct drv_ctl_l2_ring *ring = &info.data.ring;
-
-	if (start)
-		info.cmd = DRV_CTL_START_L2_CMD;
-	else
-		info.cmd = DRV_CTL_STOP_L2_CMD;
-
-	ring->cid = cid;
-	ring->client_id = cl_id;
-	ethdev->drv_ctl(dev->netdev, &info);
-}
-
-static void cnic_reg_wr_ind(struct cnic_dev *dev, u32 off, u32 val)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	struct drv_ctl_info info;
-	struct drv_ctl_io *io = &info.data.io;
-
-	info.cmd = DRV_CTL_IO_WR_CMD;
-	io->offset = off;
-	io->data = val;
-	ethdev->drv_ctl(dev->netdev, &info);
-}
-
-static u32 cnic_reg_rd_ind(struct cnic_dev *dev, u32 off)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	struct drv_ctl_info info;
-	struct drv_ctl_io *io = &info.data.io;
-
-	info.cmd = DRV_CTL_IO_RD_CMD;
-	io->offset = off;
-	ethdev->drv_ctl(dev->netdev, &info);
-	return io->data;
-}
-
-static int cnic_in_use(struct cnic_sock *csk)
-{
-	return test_bit(SK_F_INUSE, &csk->flags);
-}
-
-static void cnic_spq_completion(struct cnic_dev *dev, int cmd, u32 count)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	struct drv_ctl_info info;
-
-	info.cmd = cmd;
-	info.data.credit.credit_count = count;
-	ethdev->drv_ctl(dev->netdev, &info);
-}
-
-static int cnic_get_l5_cid(struct cnic_local *cp, u32 cid, u32 *l5_cid)
-{
-	u32 i;
-
-	for (i = 0; i < cp->max_cid_space; i++) {
-		if (cp->ctx_tbl[i].cid == cid) {
-			*l5_cid = i;
-			return 0;
-		}
-	}
-	return -EINVAL;
-}
-
-static int cnic_send_nlmsg(struct cnic_local *cp, u32 type,
-			   struct cnic_sock *csk)
-{
-	struct iscsi_path path_req;
-	char *buf = NULL;
-	u16 len = 0;
-	u32 msg_type = ISCSI_KEVENT_IF_DOWN;
-	struct cnic_ulp_ops *ulp_ops;
-	struct cnic_uio_dev *udev = cp->udev;
-	int rc = 0, retry = 0;
-
-	if (!udev || udev->uio_dev == -1)
-		return -ENODEV;
-
-	if (csk) {
-		len = sizeof(path_req);
-		buf = (char *) &path_req;
-		memset(&path_req, 0, len);
-
-		msg_type = ISCSI_KEVENT_PATH_REQ;
-		path_req.handle = (u64) csk->l5_cid;
-		if (test_bit(SK_F_IPV6, &csk->flags)) {
-			memcpy(&path_req.dst.v6_addr, &csk->dst_ip[0],
-			       sizeof(struct in6_addr));
-			path_req.ip_addr_len = 16;
-		} else {
-			memcpy(&path_req.dst.v4_addr, &csk->dst_ip[0],
-			       sizeof(struct in_addr));
-			path_req.ip_addr_len = 4;
-		}
-		path_req.vlan_id = csk->vlan_id;
-		path_req.pmtu = csk->mtu;
-	}
-
-	while (retry < 3) {
-		rc = 0;
-		rcu_read_lock();
-		ulp_ops = rcu_dereference(cnic_ulp_tbl[CNIC_ULP_ISCSI]);
-		if (ulp_ops)
-			rc = ulp_ops->iscsi_nl_send_msg(
-				cp->ulp_handle[CNIC_ULP_ISCSI],
-				msg_type, buf, len);
-		rcu_read_unlock();
-		if (rc == 0 || msg_type != ISCSI_KEVENT_PATH_REQ)
-			break;
-
-		msleep(100);
-		retry++;
-	}
-	return rc;
-}
-
-static void cnic_cm_upcall(struct cnic_local *, struct cnic_sock *, u8);
-
-static int cnic_iscsi_nl_msg_recv(struct cnic_dev *dev, u32 msg_type,
-				  char *buf, u16 len)
-{
-	int rc = -EINVAL;
-
-	switch (msg_type) {
-	case ISCSI_UEVENT_PATH_UPDATE: {
-		struct cnic_local *cp;
-		u32 l5_cid;
-		struct cnic_sock *csk;
-		struct iscsi_path *path_resp;
-
-		if (len < sizeof(*path_resp))
-			break;
-
-		path_resp = (struct iscsi_path *) buf;
-		cp = dev->cnic_priv;
-		l5_cid = (u32) path_resp->handle;
-		if (l5_cid >= MAX_CM_SK_TBL_SZ)
-			break;
-
-		rcu_read_lock();
-		if (!rcu_dereference(cp->ulp_ops[CNIC_ULP_L4])) {
-			rc = -ENODEV;
-			rcu_read_unlock();
-			break;
-		}
-		csk = &cp->csk_tbl[l5_cid];
-		csk_hold(csk);
-		if (cnic_in_use(csk) &&
-		    test_bit(SK_F_CONNECT_START, &csk->flags)) {
-
-			memcpy(csk->ha, path_resp->mac_addr, 6);
-			if (test_bit(SK_F_IPV6, &csk->flags))
-				memcpy(&csk->src_ip[0], &path_resp->src.v6_addr,
-				       sizeof(struct in6_addr));
-			else
-				memcpy(&csk->src_ip[0], &path_resp->src.v4_addr,
-				       sizeof(struct in_addr));
-
-			if (is_valid_ether_addr(csk->ha)) {
-				cnic_cm_set_pg(csk);
-			} else if (!test_bit(SK_F_OFFLD_SCHED, &csk->flags) &&
-				!test_bit(SK_F_OFFLD_COMPLETE, &csk->flags)) {
-
-				cnic_cm_upcall(cp, csk,
-					L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE);
-				clear_bit(SK_F_CONNECT_START, &csk->flags);
-			}
-		}
-		csk_put(csk);
-		rcu_read_unlock();
-		rc = 0;
-	}
-	}
-
-	return rc;
-}
-
-static int cnic_offld_prep(struct cnic_sock *csk)
-{
-	if (test_and_set_bit(SK_F_OFFLD_SCHED, &csk->flags))
-		return 0;
-
-	if (!test_bit(SK_F_CONNECT_START, &csk->flags)) {
-		clear_bit(SK_F_OFFLD_SCHED, &csk->flags);
-		return 0;
-	}
-
-	return 1;
-}
-
-static int cnic_close_prep(struct cnic_sock *csk)
-{
-	clear_bit(SK_F_CONNECT_START, &csk->flags);
-	smp_mb__after_clear_bit();
-
-	if (test_and_clear_bit(SK_F_OFFLD_COMPLETE, &csk->flags)) {
-		while (test_and_set_bit(SK_F_OFFLD_SCHED, &csk->flags))
-			msleep(1);
-
-		return 1;
-	}
-	return 0;
-}
-
-static int cnic_abort_prep(struct cnic_sock *csk)
-{
-	clear_bit(SK_F_CONNECT_START, &csk->flags);
-	smp_mb__after_clear_bit();
-
-	while (test_and_set_bit(SK_F_OFFLD_SCHED, &csk->flags))
-		msleep(1);
-
-	if (test_and_clear_bit(SK_F_OFFLD_COMPLETE, &csk->flags)) {
-		csk->state = L4_KCQE_OPCODE_VALUE_RESET_COMP;
-		return 1;
-	}
-
-	return 0;
-}
-
-int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops)
-{
-	struct cnic_dev *dev;
-
-	if (ulp_type < 0 || ulp_type >= MAX_CNIC_ULP_TYPE) {
-		pr_err("%s: Bad type %d\n", __func__, ulp_type);
-		return -EINVAL;
-	}
-	mutex_lock(&cnic_lock);
-	if (cnic_ulp_tbl_prot(ulp_type)) {
-		pr_err("%s: Type %d has already been registered\n",
-		       __func__, ulp_type);
-		mutex_unlock(&cnic_lock);
-		return -EBUSY;
-	}
-
-	read_lock(&cnic_dev_lock);
-	list_for_each_entry(dev, &cnic_dev_list, list) {
-		struct cnic_local *cp = dev->cnic_priv;
-
-		clear_bit(ULP_F_INIT, &cp->ulp_flags[ulp_type]);
-	}
-	read_unlock(&cnic_dev_lock);
-
-	atomic_set(&ulp_ops->ref_count, 0);
-	rcu_assign_pointer(cnic_ulp_tbl[ulp_type], ulp_ops);
-	mutex_unlock(&cnic_lock);
-
-	/* Prevent race conditions with netdev_event */
-	rtnl_lock();
-	list_for_each_entry(dev, &cnic_dev_list, list) {
-		struct cnic_local *cp = dev->cnic_priv;
-
-		if (!test_and_set_bit(ULP_F_INIT, &cp->ulp_flags[ulp_type]))
-			ulp_ops->cnic_init(dev);
-	}
-	rtnl_unlock();
-
-	return 0;
-}
-
-int cnic_unregister_driver(int ulp_type)
-{
-	struct cnic_dev *dev;
-	struct cnic_ulp_ops *ulp_ops;
-	int i = 0;
-
-	if (ulp_type < 0 || ulp_type >= MAX_CNIC_ULP_TYPE) {
-		pr_err("%s: Bad type %d\n", __func__, ulp_type);
-		return -EINVAL;
-	}
-	mutex_lock(&cnic_lock);
-	ulp_ops = cnic_ulp_tbl_prot(ulp_type);
-	if (!ulp_ops) {
-		pr_err("%s: Type %d has not been registered\n",
-		       __func__, ulp_type);
-		goto out_unlock;
-	}
-	read_lock(&cnic_dev_lock);
-	list_for_each_entry(dev, &cnic_dev_list, list) {
-		struct cnic_local *cp = dev->cnic_priv;
-
-		if (rcu_dereference(cp->ulp_ops[ulp_type])) {
-			pr_err("%s: Type %d still has devices registered\n",
-			       __func__, ulp_type);
-			read_unlock(&cnic_dev_lock);
-			goto out_unlock;
-		}
-	}
-	read_unlock(&cnic_dev_lock);
-
-	rcu_assign_pointer(cnic_ulp_tbl[ulp_type], NULL);
-
-	mutex_unlock(&cnic_lock);
-	synchronize_rcu();
-	while ((atomic_read(&ulp_ops->ref_count) != 0) && (i < 20)) {
-		msleep(100);
-		i++;
-	}
-
-	if (atomic_read(&ulp_ops->ref_count) != 0)
-		netdev_warn(dev->netdev, "Failed waiting for ref count to go to zero\n");
-	return 0;
-
-out_unlock:
-	mutex_unlock(&cnic_lock);
-	return -EINVAL;
-}
-
-static int cnic_start_hw(struct cnic_dev *);
-static void cnic_stop_hw(struct cnic_dev *);
-
-static int cnic_register_device(struct cnic_dev *dev, int ulp_type,
-				void *ulp_ctx)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_ulp_ops *ulp_ops;
-
-	if (ulp_type < 0 || ulp_type >= MAX_CNIC_ULP_TYPE) {
-		pr_err("%s: Bad type %d\n", __func__, ulp_type);
-		return -EINVAL;
-	}
-	mutex_lock(&cnic_lock);
-	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);
-		return -EAGAIN;
-	}
-	if (rcu_dereference(cp->ulp_ops[ulp_type])) {
-		pr_err("%s: Type %d has already been registered to this device\n",
-		       __func__, ulp_type);
-		mutex_unlock(&cnic_lock);
-		return -EBUSY;
-	}
-
-	clear_bit(ULP_F_START, &cp->ulp_flags[ulp_type]);
-	cp->ulp_handle[ulp_type] = ulp_ctx;
-	ulp_ops = cnic_ulp_tbl_prot(ulp_type);
-	rcu_assign_pointer(cp->ulp_ops[ulp_type], ulp_ops);
-	cnic_hold(dev);
-
-	if (test_bit(CNIC_F_CNIC_UP, &dev->flags))
-		if (!test_and_set_bit(ULP_F_START, &cp->ulp_flags[ulp_type]))
-			ulp_ops->cnic_start(cp->ulp_handle[ulp_type]);
-
-	mutex_unlock(&cnic_lock);
-
-	return 0;
-
-}
-EXPORT_SYMBOL(cnic_register_driver);
-
-static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	int i = 0;
-
-	if (ulp_type < 0 || ulp_type >= MAX_CNIC_ULP_TYPE) {
-		pr_err("%s: Bad type %d\n", __func__, ulp_type);
-		return -EINVAL;
-	}
-	mutex_lock(&cnic_lock);
-	if (rcu_dereference(cp->ulp_ops[ulp_type])) {
-		rcu_assign_pointer(cp->ulp_ops[ulp_type], NULL);
-		cnic_put(dev);
-	} else {
-		pr_err("%s: device not registered to this ulp type %d\n",
-		       __func__, ulp_type);
-		mutex_unlock(&cnic_lock);
-		return -EINVAL;
-	}
-	mutex_unlock(&cnic_lock);
-
-	if (ulp_type == CNIC_ULP_ISCSI)
-		cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
-
-	synchronize_rcu();
-
-	while (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type]) &&
-	       i < 20) {
-		msleep(100);
-		i++;
-	}
-	if (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type]))
-		netdev_warn(dev->netdev, "Failed waiting for ULP up call to complete\n");
-
-	return 0;
-}
-EXPORT_SYMBOL(cnic_unregister_driver);
-
-static int cnic_init_id_tbl(struct cnic_id_tbl *id_tbl, u32 size, u32 start_id,
-			    u32 next)
-{
-	id_tbl->start = start_id;
-	id_tbl->max = size;
-	id_tbl->next = next;
-	spin_lock_init(&id_tbl->lock);
-	id_tbl->table = kzalloc(DIV_ROUND_UP(size, 32) * 4, GFP_KERNEL);
-	if (!id_tbl->table)
-		return -ENOMEM;
-
-	return 0;
-}
-
-static void cnic_free_id_tbl(struct cnic_id_tbl *id_tbl)
-{
-	kfree(id_tbl->table);
-	id_tbl->table = NULL;
-}
-
-static int cnic_alloc_id(struct cnic_id_tbl *id_tbl, u32 id)
-{
-	int ret = -1;
-
-	id -= id_tbl->start;
-	if (id >= id_tbl->max)
-		return ret;
-
-	spin_lock(&id_tbl->lock);
-	if (!test_bit(id, id_tbl->table)) {
-		set_bit(id, id_tbl->table);
-		ret = 0;
-	}
-	spin_unlock(&id_tbl->lock);
-	return ret;
-}
-
-/* Returns -1 if not successful */
-static u32 cnic_alloc_new_id(struct cnic_id_tbl *id_tbl)
-{
-	u32 id;
-
-	spin_lock(&id_tbl->lock);
-	id = find_next_zero_bit(id_tbl->table, id_tbl->max, id_tbl->next);
-	if (id >= id_tbl->max) {
-		id = -1;
-		if (id_tbl->next != 0) {
-			id = find_first_zero_bit(id_tbl->table, id_tbl->next);
-			if (id >= id_tbl->next)
-				id = -1;
-		}
-	}
-
-	if (id < id_tbl->max) {
-		set_bit(id, id_tbl->table);
-		id_tbl->next = (id + 1) & (id_tbl->max - 1);
-		id += id_tbl->start;
-	}
-
-	spin_unlock(&id_tbl->lock);
-
-	return id;
-}
-
-static void cnic_free_id(struct cnic_id_tbl *id_tbl, u32 id)
-{
-	if (id == -1)
-		return;
-
-	id -= id_tbl->start;
-	if (id >= id_tbl->max)
-		return;
-
-	clear_bit(id, id_tbl->table);
-}
-
-static void cnic_free_dma(struct cnic_dev *dev, struct cnic_dma *dma)
-{
-	int i;
-
-	if (!dma->pg_arr)
-		return;
-
-	for (i = 0; i < dma->num_pages; i++) {
-		if (dma->pg_arr[i]) {
-			dma_free_coherent(&dev->pcidev->dev, BCM_PAGE_SIZE,
-					  dma->pg_arr[i], dma->pg_map_arr[i]);
-			dma->pg_arr[i] = NULL;
-		}
-	}
-	if (dma->pgtbl) {
-		dma_free_coherent(&dev->pcidev->dev, dma->pgtbl_size,
-				  dma->pgtbl, dma->pgtbl_map);
-		dma->pgtbl = NULL;
-	}
-	kfree(dma->pg_arr);
-	dma->pg_arr = NULL;
-	dma->num_pages = 0;
-}
-
-static void cnic_setup_page_tbl(struct cnic_dev *dev, struct cnic_dma *dma)
-{
-	int i;
-	__le32 *page_table = (__le32 *) dma->pgtbl;
-
-	for (i = 0; i < dma->num_pages; i++) {
-		/* Each entry needs to be in big endian format. */
-		*page_table = cpu_to_le32((u64) dma->pg_map_arr[i] >> 32);
-		page_table++;
-		*page_table = cpu_to_le32(dma->pg_map_arr[i] & 0xffffffff);
-		page_table++;
-	}
-}
-
-static void cnic_setup_page_tbl_le(struct cnic_dev *dev, struct cnic_dma *dma)
-{
-	int i;
-	__le32 *page_table = (__le32 *) dma->pgtbl;
-
-	for (i = 0; i < dma->num_pages; i++) {
-		/* Each entry needs to be in little endian format. */
-		*page_table = cpu_to_le32(dma->pg_map_arr[i] & 0xffffffff);
-		page_table++;
-		*page_table = cpu_to_le32((u64) dma->pg_map_arr[i] >> 32);
-		page_table++;
-	}
-}
-
-static int cnic_alloc_dma(struct cnic_dev *dev, struct cnic_dma *dma,
-			  int pages, int use_pg_tbl)
-{
-	int i, size;
-	struct cnic_local *cp = dev->cnic_priv;
-
-	size = pages * (sizeof(void *) + sizeof(dma_addr_t));
-	dma->pg_arr = kzalloc(size, GFP_ATOMIC);
-	if (dma->pg_arr == NULL)
-		return -ENOMEM;
-
-	dma->pg_map_arr = (dma_addr_t *) (dma->pg_arr + pages);
-	dma->num_pages = pages;
-
-	for (i = 0; i < pages; i++) {
-		dma->pg_arr[i] = dma_alloc_coherent(&dev->pcidev->dev,
-						    BCM_PAGE_SIZE,
-						    &dma->pg_map_arr[i],
-						    GFP_ATOMIC);
-		if (dma->pg_arr[i] == NULL)
-			goto error;
-	}
-	if (!use_pg_tbl)
-		return 0;
-
-	dma->pgtbl_size = ((pages * 8) + BCM_PAGE_SIZE - 1) &
-			  ~(BCM_PAGE_SIZE - 1);
-	dma->pgtbl = dma_alloc_coherent(&dev->pcidev->dev, dma->pgtbl_size,
-					&dma->pgtbl_map, GFP_ATOMIC);
-	if (dma->pgtbl == NULL)
-		goto error;
-
-	cp->setup_pgtbl(dev, dma);
-
-	return 0;
-
-error:
-	cnic_free_dma(dev, dma);
-	return -ENOMEM;
-}
-
-static void cnic_free_context(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	int i;
-
-	for (i = 0; i < cp->ctx_blks; i++) {
-		if (cp->ctx_arr[i].ctx) {
-			dma_free_coherent(&dev->pcidev->dev, cp->ctx_blk_size,
-					  cp->ctx_arr[i].ctx,
-					  cp->ctx_arr[i].mapping);
-			cp->ctx_arr[i].ctx = NULL;
-		}
-	}
-}
-
-static void __cnic_free_uio(struct cnic_uio_dev *udev)
-{
-	uio_unregister_device(&udev->cnic_uinfo);
-
-	if (udev->l2_buf) {
-		dma_free_coherent(&udev->pdev->dev, udev->l2_buf_size,
-				  udev->l2_buf, udev->l2_buf_map);
-		udev->l2_buf = NULL;
-	}
-
-	if (udev->l2_ring) {
-		dma_free_coherent(&udev->pdev->dev, udev->l2_ring_size,
-				  udev->l2_ring, udev->l2_ring_map);
-		udev->l2_ring = NULL;
-	}
-
-	pci_dev_put(udev->pdev);
-	kfree(udev);
-}
-
-static void cnic_free_uio(struct cnic_uio_dev *udev)
-{
-	if (!udev)
-		return;
-
-	write_lock(&cnic_dev_lock);
-	list_del_init(&udev->list);
-	write_unlock(&cnic_dev_lock);
-	__cnic_free_uio(udev);
-}
-
-static void cnic_free_resc(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_uio_dev *udev = cp->udev;
-
-	if (udev) {
-		udev->dev = NULL;
-		cp->udev = NULL;
-	}
-
-	cnic_free_context(dev);
-	kfree(cp->ctx_arr);
-	cp->ctx_arr = NULL;
-	cp->ctx_blks = 0;
-
-	cnic_free_dma(dev, &cp->gbl_buf_info);
-	cnic_free_dma(dev, &cp->kwq_info);
-	cnic_free_dma(dev, &cp->kwq_16_data_info);
-	cnic_free_dma(dev, &cp->kcq2.dma);
-	cnic_free_dma(dev, &cp->kcq1.dma);
-	kfree(cp->iscsi_tbl);
-	cp->iscsi_tbl = NULL;
-	kfree(cp->ctx_tbl);
-	cp->ctx_tbl = NULL;
-
-	cnic_free_id_tbl(&cp->fcoe_cid_tbl);
-	cnic_free_id_tbl(&cp->cid_tbl);
-}
-
-static int cnic_alloc_context(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-
-	if (CHIP_NUM(cp) == CHIP_NUM_5709) {
-		int i, k, arr_size;
-
-		cp->ctx_blk_size = BCM_PAGE_SIZE;
-		cp->cids_per_blk = BCM_PAGE_SIZE / 128;
-		arr_size = BNX2_MAX_CID / cp->cids_per_blk *
-			   sizeof(struct cnic_ctx);
-		cp->ctx_arr = kzalloc(arr_size, GFP_KERNEL);
-		if (cp->ctx_arr == NULL)
-			return -ENOMEM;
-
-		k = 0;
-		for (i = 0; i < 2; i++) {
-			u32 j, reg, off, lo, hi;
-
-			if (i == 0)
-				off = BNX2_PG_CTX_MAP;
-			else
-				off = BNX2_ISCSI_CTX_MAP;
-
-			reg = cnic_reg_rd_ind(dev, off);
-			lo = reg >> 16;
-			hi = reg & 0xffff;
-			for (j = lo; j < hi; j += cp->cids_per_blk, k++)
-				cp->ctx_arr[k].cid = j;
-		}
-
-		cp->ctx_blks = k;
-		if (cp->ctx_blks >= (BNX2_MAX_CID / cp->cids_per_blk)) {
-			cp->ctx_blks = 0;
-			return -ENOMEM;
-		}
-
-		for (i = 0; i < cp->ctx_blks; i++) {
-			cp->ctx_arr[i].ctx =
-				dma_alloc_coherent(&dev->pcidev->dev,
-						   BCM_PAGE_SIZE,
-						   &cp->ctx_arr[i].mapping,
-						   GFP_KERNEL);
-			if (cp->ctx_arr[i].ctx == NULL)
-				return -ENOMEM;
-		}
-	}
-	return 0;
-}
-
-static u16 cnic_bnx2_next_idx(u16 idx)
-{
-	return idx + 1;
-}
-
-static u16 cnic_bnx2_hw_idx(u16 idx)
-{
-	return idx;
-}
-
-static u16 cnic_bnx2x_next_idx(u16 idx)
-{
-	idx++;
-	if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT)
-		idx++;
-
-	return idx;
-}
-
-static u16 cnic_bnx2x_hw_idx(u16 idx)
-{
-	if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT)
-		idx++;
-	return idx;
-}
-
-static int cnic_alloc_kcq(struct cnic_dev *dev, struct kcq_info *info,
-			  bool use_pg_tbl)
-{
-	int err, i, use_page_tbl = 0;
-	struct kcqe **kcq;
-
-	if (use_pg_tbl)
-		use_page_tbl = 1;
-
-	err = cnic_alloc_dma(dev, &info->dma, KCQ_PAGE_CNT, use_page_tbl);
-	if (err)
-		return err;
-
-	kcq = (struct kcqe **) info->dma.pg_arr;
-	info->kcq = kcq;
-
-	info->next_idx = cnic_bnx2_next_idx;
-	info->hw_idx = cnic_bnx2_hw_idx;
-	if (use_pg_tbl)
-		return 0;
-
-	info->next_idx = cnic_bnx2x_next_idx;
-	info->hw_idx = cnic_bnx2x_hw_idx;
-
-	for (i = 0; i < KCQ_PAGE_CNT; i++) {
-		struct bnx2x_bd_chain_next *next =
-			(struct bnx2x_bd_chain_next *) &kcq[i][MAX_KCQE_CNT];
-		int j = i + 1;
-
-		if (j >= KCQ_PAGE_CNT)
-			j = 0;
-		next->addr_hi = (u64) info->dma.pg_map_arr[j] >> 32;
-		next->addr_lo = info->dma.pg_map_arr[j] & 0xffffffff;
-	}
-	return 0;
-}
-
-static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_uio_dev *udev;
-
-	read_lock(&cnic_dev_lock);
-	list_for_each_entry(udev, &cnic_udev_list, list) {
-		if (udev->pdev == dev->pcidev) {
-			udev->dev = dev;
-			cp->udev = udev;
-			read_unlock(&cnic_dev_lock);
-			return 0;
-		}
-	}
-	read_unlock(&cnic_dev_lock);
-
-	udev = kzalloc(sizeof(struct cnic_uio_dev), GFP_ATOMIC);
-	if (!udev)
-		return -ENOMEM;
-
-	udev->uio_dev = -1;
-
-	udev->dev = dev;
-	udev->pdev = dev->pcidev;
-	udev->l2_ring_size = pages * BCM_PAGE_SIZE;
-	udev->l2_ring = dma_alloc_coherent(&udev->pdev->dev, udev->l2_ring_size,
-					   &udev->l2_ring_map,
-					   GFP_KERNEL | __GFP_COMP);
-	if (!udev->l2_ring)
-		goto err_udev;
-
-	udev->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size;
-	udev->l2_buf_size = PAGE_ALIGN(udev->l2_buf_size);
-	udev->l2_buf = dma_alloc_coherent(&udev->pdev->dev, udev->l2_buf_size,
-					  &udev->l2_buf_map,
-					  GFP_KERNEL | __GFP_COMP);
-	if (!udev->l2_buf)
-		goto err_dma;
-
-	write_lock(&cnic_dev_lock);
-	list_add(&udev->list, &cnic_udev_list);
-	write_unlock(&cnic_dev_lock);
-
-	pci_dev_get(udev->pdev);
-
-	cp->udev = udev;
-
-	return 0;
- err_dma:
-	dma_free_coherent(&udev->pdev->dev, udev->l2_ring_size,
-			  udev->l2_ring, udev->l2_ring_map);
- err_udev:
-	kfree(udev);
-	return -ENOMEM;
-}
-
-static int cnic_init_uio(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_uio_dev *udev = cp->udev;
-	struct uio_info *uinfo;
-	int ret = 0;
-
-	if (!udev)
-		return -ENOMEM;
-
-	uinfo = &udev->cnic_uinfo;
-
-	uinfo->mem[0].addr = dev->netdev->base_addr;
-	uinfo->mem[0].internal_addr = dev->regview;
-	uinfo->mem[0].size = dev->netdev->mem_end - dev->netdev->mem_start;
-	uinfo->mem[0].memtype = UIO_MEM_PHYS;
-
-	if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) {
-		uinfo->mem[1].addr = (unsigned long) cp->status_blk.gen &
-					PAGE_MASK;
-		if (cp->ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX)
-			uinfo->mem[1].size = BNX2_SBLK_MSIX_ALIGN_SIZE * 9;
-		else
-			uinfo->mem[1].size = BNX2_SBLK_MSIX_ALIGN_SIZE;
-
-		uinfo->name = "bnx2_cnic";
-	} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
-		uinfo->mem[1].addr = (unsigned long) cp->bnx2x_def_status_blk &
-			PAGE_MASK;
-		uinfo->mem[1].size = sizeof(*cp->bnx2x_def_status_blk);
-
-		uinfo->name = "bnx2x_cnic";
-	}
-
-	uinfo->mem[1].memtype = UIO_MEM_LOGICAL;
-
-	uinfo->mem[2].addr = (unsigned long) udev->l2_ring;
-	uinfo->mem[2].size = udev->l2_ring_size;
-	uinfo->mem[2].memtype = UIO_MEM_LOGICAL;
-
-	uinfo->mem[3].addr = (unsigned long) udev->l2_buf;
-	uinfo->mem[3].size = udev->l2_buf_size;
-	uinfo->mem[3].memtype = UIO_MEM_LOGICAL;
-
-	uinfo->version = CNIC_MODULE_VERSION;
-	uinfo->irq = UIO_IRQ_CUSTOM;
-
-	uinfo->open = cnic_uio_open;
-	uinfo->release = cnic_uio_close;
-
-	if (udev->uio_dev == -1) {
-		if (!uinfo->priv) {
-			uinfo->priv = udev;
-
-			ret = uio_register_device(&udev->pdev->dev, uinfo);
-		}
-	} else {
-		cnic_init_rings(dev);
-	}
-
-	return ret;
-}
-
-static int cnic_alloc_bnx2_resc(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	int ret;
-
-	ret = cnic_alloc_dma(dev, &cp->kwq_info, KWQ_PAGE_CNT, 1);
-	if (ret)
-		goto error;
-	cp->kwq = (struct kwqe **) cp->kwq_info.pg_arr;
-
-	ret = cnic_alloc_kcq(dev, &cp->kcq1, true);
-	if (ret)
-		goto error;
-
-	ret = cnic_alloc_context(dev);
-	if (ret)
-		goto error;
-
-	ret = cnic_alloc_uio_rings(dev, 2);
-	if (ret)
-		goto error;
-
-	ret = cnic_init_uio(dev);
-	if (ret)
-		goto error;
-
-	return 0;
-
-error:
-	cnic_free_resc(dev);
-	return ret;
-}
-
-static int cnic_alloc_bnx2x_context(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	int ctx_blk_size = cp->ethdev->ctx_blk_size;
-	int total_mem, blks, i;
-
-	total_mem = BNX2X_CONTEXT_MEM_SIZE * cp->max_cid_space;
-	blks = total_mem / ctx_blk_size;
-	if (total_mem % ctx_blk_size)
-		blks++;
-
-	if (blks > cp->ethdev->ctx_tbl_len)
-		return -ENOMEM;
-
-	cp->ctx_arr = kcalloc(blks, sizeof(struct cnic_ctx), GFP_KERNEL);
-	if (cp->ctx_arr == NULL)
-		return -ENOMEM;
-
-	cp->ctx_blks = blks;
-	cp->ctx_blk_size = ctx_blk_size;
-	if (!BNX2X_CHIP_IS_57710(cp->chip_id))
-		cp->ctx_align = 0;
-	else
-		cp->ctx_align = ctx_blk_size;
-
-	cp->cids_per_blk = ctx_blk_size / BNX2X_CONTEXT_MEM_SIZE;
-
-	for (i = 0; i < blks; i++) {
-		cp->ctx_arr[i].ctx =
-			dma_alloc_coherent(&dev->pcidev->dev, cp->ctx_blk_size,
-					   &cp->ctx_arr[i].mapping,
-					   GFP_KERNEL);
-		if (cp->ctx_arr[i].ctx == NULL)
-			return -ENOMEM;
-
-		if (cp->ctx_align && cp->ctx_blk_size == ctx_blk_size) {
-			if (cp->ctx_arr[i].mapping & (cp->ctx_align - 1)) {
-				cnic_free_context(dev);
-				cp->ctx_blk_size += cp->ctx_align;
-				i = -1;
-				continue;
-			}
-		}
-	}
-	return 0;
-}
-
-static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	u32 start_cid = ethdev->starting_cid;
-	int i, j, n, ret, pages;
-	struct cnic_dma *kwq_16_dma = &cp->kwq_16_data_info;
-
-	cp->iro_arr = ethdev->iro_arr;
-
-	cp->max_cid_space = MAX_ISCSI_TBL_SZ;
-	cp->iscsi_start_cid = start_cid;
-	cp->fcoe_start_cid = start_cid + MAX_ISCSI_TBL_SZ;
-
-	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
-		cp->max_cid_space += BNX2X_FCOE_NUM_CONNECTIONS;
-		cp->fcoe_init_cid = ethdev->fcoe_init_cid;
-		if (!cp->fcoe_init_cid)
-			cp->fcoe_init_cid = 0x10;
-	}
-
-	cp->iscsi_tbl = kzalloc(sizeof(struct cnic_iscsi) * MAX_ISCSI_TBL_SZ,
-				GFP_KERNEL);
-	if (!cp->iscsi_tbl)
-		goto error;
-
-	cp->ctx_tbl = kzalloc(sizeof(struct cnic_context) *
-				cp->max_cid_space, GFP_KERNEL);
-	if (!cp->ctx_tbl)
-		goto error;
-
-	for (i = 0; i < MAX_ISCSI_TBL_SZ; i++) {
-		cp->ctx_tbl[i].proto.iscsi = &cp->iscsi_tbl[i];
-		cp->ctx_tbl[i].ulp_proto_id = CNIC_ULP_ISCSI;
-	}
-
-	for (i = MAX_ISCSI_TBL_SZ; i < cp->max_cid_space; i++)
-		cp->ctx_tbl[i].ulp_proto_id = CNIC_ULP_FCOE;
-
-	pages = PAGE_ALIGN(cp->max_cid_space * CNIC_KWQ16_DATA_SIZE) /
-		PAGE_SIZE;
-
-	ret = cnic_alloc_dma(dev, kwq_16_dma, pages, 0);
-	if (ret)
-		return -ENOMEM;
-
-	n = PAGE_SIZE / CNIC_KWQ16_DATA_SIZE;
-	for (i = 0, j = 0; i < cp->max_cid_space; i++) {
-		long off = CNIC_KWQ16_DATA_SIZE * (i % n);
-
-		cp->ctx_tbl[i].kwqe_data = kwq_16_dma->pg_arr[j] + off;
-		cp->ctx_tbl[i].kwqe_data_mapping = kwq_16_dma->pg_map_arr[j] +
-						   off;
-
-		if ((i % n) == (n - 1))
-			j++;
-	}
-
-	ret = cnic_alloc_kcq(dev, &cp->kcq1, false);
-	if (ret)
-		goto error;
-
-	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
-		ret = cnic_alloc_kcq(dev, &cp->kcq2, true);
-		if (ret)
-			goto error;
-	}
-
-	pages = PAGE_ALIGN(BNX2X_ISCSI_GLB_BUF_SIZE) / PAGE_SIZE;
-	ret = cnic_alloc_dma(dev, &cp->gbl_buf_info, pages, 0);
-	if (ret)
-		goto error;
-
-	ret = cnic_alloc_bnx2x_context(dev);
-	if (ret)
-		goto error;
-
-	cp->bnx2x_def_status_blk = cp->ethdev->irq_arr[1].status_blk;
-
-	cp->l2_rx_ring_size = 15;
-
-	ret = cnic_alloc_uio_rings(dev, 4);
-	if (ret)
-		goto error;
-
-	ret = cnic_init_uio(dev);
-	if (ret)
-		goto error;
-
-	return 0;
-
-error:
-	cnic_free_resc(dev);
-	return -ENOMEM;
-}
-
-static inline u32 cnic_kwq_avail(struct cnic_local *cp)
-{
-	return cp->max_kwq_idx -
-		((cp->kwq_prod_idx - cp->kwq_con_idx) & cp->max_kwq_idx);
-}
-
-static int cnic_submit_bnx2_kwqes(struct cnic_dev *dev, struct kwqe *wqes[],
-				  u32 num_wqes)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct kwqe *prod_qe;
-	u16 prod, sw_prod, i;
-
-	if (!test_bit(CNIC_F_CNIC_UP, &dev->flags))
-		return -EAGAIN;		/* bnx2 is down */
-
-	spin_lock_bh(&cp->cnic_ulp_lock);
-	if (num_wqes > cnic_kwq_avail(cp) &&
-	    !test_bit(CNIC_LCL_FL_KWQ_INIT, &cp->cnic_local_flags)) {
-		spin_unlock_bh(&cp->cnic_ulp_lock);
-		return -EAGAIN;
-	}
-
-	clear_bit(CNIC_LCL_FL_KWQ_INIT, &cp->cnic_local_flags);
-
-	prod = cp->kwq_prod_idx;
-	sw_prod = prod & MAX_KWQ_IDX;
-	for (i = 0; i < num_wqes; i++) {
-		prod_qe = &cp->kwq[KWQ_PG(sw_prod)][KWQ_IDX(sw_prod)];
-		memcpy(prod_qe, wqes[i], sizeof(struct kwqe));
-		prod++;
-		sw_prod = prod & MAX_KWQ_IDX;
-	}
-	cp->kwq_prod_idx = prod;
-
-	CNIC_WR16(dev, cp->kwq_io_addr, cp->kwq_prod_idx);
-
-	spin_unlock_bh(&cp->cnic_ulp_lock);
-	return 0;
-}
-
-static void *cnic_get_kwqe_16_data(struct cnic_local *cp, u32 l5_cid,
-				   union l5cm_specific_data *l5_data)
-{
-	struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
-	dma_addr_t map;
-
-	map = ctx->kwqe_data_mapping;
-	l5_data->phy_address.lo = (u64) map & 0xffffffff;
-	l5_data->phy_address.hi = (u64) map >> 32;
-	return ctx->kwqe_data;
-}
-
-static int cnic_submit_kwqe_16(struct cnic_dev *dev, u32 cmd, u32 cid,
-				u32 type, union l5cm_specific_data *l5_data)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct l5cm_spe kwqe;
-	struct kwqe_16 *kwq[1];
-	u16 type_16;
-	int ret;
-
-	kwqe.hdr.conn_and_cmd_data =
-		cpu_to_le32(((cmd << SPE_HDR_CMD_ID_SHIFT) |
-			     BNX2X_HW_CID(cp, cid)));
-
-	type_16 = (type << SPE_HDR_CONN_TYPE_SHIFT) & SPE_HDR_CONN_TYPE;
-	type_16 |= (cp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) &
-		   SPE_HDR_FUNCTION_ID;
-
-	kwqe.hdr.type = cpu_to_le16(type_16);
-	kwqe.hdr.reserved1 = 0;
-	kwqe.data.phy_address.lo = cpu_to_le32(l5_data->phy_address.lo);
-	kwqe.data.phy_address.hi = cpu_to_le32(l5_data->phy_address.hi);
-
-	kwq[0] = (struct kwqe_16 *) &kwqe;
-
-	spin_lock_bh(&cp->cnic_ulp_lock);
-	ret = cp->ethdev->drv_submit_kwqes_16(dev->netdev, kwq, 1);
-	spin_unlock_bh(&cp->cnic_ulp_lock);
-
-	if (ret == 1)
-		return 0;
-
-	return -EBUSY;
-}
-
-static void cnic_reply_bnx2x_kcqes(struct cnic_dev *dev, int ulp_type,
-				   struct kcqe *cqes[], u32 num_cqes)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_ulp_ops *ulp_ops;
-
-	rcu_read_lock();
-	ulp_ops = rcu_dereference(cp->ulp_ops[ulp_type]);
-	if (likely(ulp_ops)) {
-		ulp_ops->indicate_kcqes(cp->ulp_handle[ulp_type],
-					  cqes, num_cqes);
-	}
-	rcu_read_unlock();
-}
-
-static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct iscsi_kwqe_init1 *req1 = (struct iscsi_kwqe_init1 *) kwqe;
-	int hq_bds, pages;
-	u32 pfid = cp->pfid;
-
-	cp->num_iscsi_tasks = req1->num_tasks_per_conn;
-	cp->num_ccells = req1->num_ccells_per_conn;
-	cp->task_array_size = BNX2X_ISCSI_TASK_CONTEXT_SIZE *
-			      cp->num_iscsi_tasks;
-	cp->r2tq_size = cp->num_iscsi_tasks * BNX2X_ISCSI_MAX_PENDING_R2TS *
-			BNX2X_ISCSI_R2TQE_SIZE;
-	cp->hq_size = cp->num_ccells * BNX2X_ISCSI_HQ_BD_SIZE;
-	pages = PAGE_ALIGN(cp->hq_size) / PAGE_SIZE;
-	hq_bds = pages * (PAGE_SIZE / BNX2X_ISCSI_HQ_BD_SIZE);
-	cp->num_cqs = req1->num_cqs;
-
-	if (!dev->max_iscsi_conn)
-		return 0;
-
-	/* init Tstorm RAM */
-	CNIC_WR16(dev, BAR_TSTRORM_INTMEM + TSTORM_ISCSI_RQ_SIZE_OFFSET(pfid),
-		  req1->rq_num_wqes);
-	CNIC_WR16(dev, BAR_TSTRORM_INTMEM + TSTORM_ISCSI_PAGE_SIZE_OFFSET(pfid),
-		  PAGE_SIZE);
-	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT);
-	CNIC_WR16(dev, BAR_TSTRORM_INTMEM +
-		  TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid),
-		  req1->num_tasks_per_conn);
-
-	/* init Ustorm RAM */
-	CNIC_WR16(dev, BAR_USTRORM_INTMEM +
-		  USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfid),
-		  req1->rq_buffer_size);
-	CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_PAGE_SIZE_OFFSET(pfid),
-		  PAGE_SIZE);
-	CNIC_WR8(dev, BAR_USTRORM_INTMEM +
-		 USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT);
-	CNIC_WR16(dev, BAR_USTRORM_INTMEM +
-		  USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid),
-		  req1->num_tasks_per_conn);
-	CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_RQ_SIZE_OFFSET(pfid),
-		  req1->rq_num_wqes);
-	CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_CQ_SIZE_OFFSET(pfid),
-		  req1->cq_num_wqes);
-	CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_R2TQ_SIZE_OFFSET(pfid),
-		  cp->num_iscsi_tasks * BNX2X_ISCSI_MAX_PENDING_R2TS);
-
-	/* init Xstorm RAM */
-	CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfid),
-		  PAGE_SIZE);
-	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT);
-	CNIC_WR16(dev, BAR_XSTRORM_INTMEM +
-		  XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid),
-		  req1->num_tasks_per_conn);
-	CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_HQ_SIZE_OFFSET(pfid),
-		  hq_bds);
-	CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_SQ_SIZE_OFFSET(pfid),
-		  req1->num_tasks_per_conn);
-	CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_R2TQ_SIZE_OFFSET(pfid),
-		  cp->num_iscsi_tasks * BNX2X_ISCSI_MAX_PENDING_R2TS);
-
-	/* init Cstorm RAM */
-	CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_PAGE_SIZE_OFFSET(pfid),
-		  PAGE_SIZE);
-	CNIC_WR8(dev, BAR_CSTRORM_INTMEM +
-		 CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT);
-	CNIC_WR16(dev, BAR_CSTRORM_INTMEM +
-		  CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid),
-		  req1->num_tasks_per_conn);
-	CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_CQ_SIZE_OFFSET(pfid),
-		  req1->cq_num_wqes);
-	CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_HQ_SIZE_OFFSET(pfid),
-		  hq_bds);
-
-	return 0;
-}
-
-static int cnic_bnx2x_iscsi_init2(struct cnic_dev *dev, struct kwqe *kwqe)
-{
-	struct iscsi_kwqe_init2 *req2 = (struct iscsi_kwqe_init2 *) kwqe;
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 pfid = cp->pfid;
-	struct iscsi_kcqe kcqe;
-	struct kcqe *cqes[1];
-
-	memset(&kcqe, 0, sizeof(kcqe));
-	if (!dev->max_iscsi_conn) {
-		kcqe.completion_status =
-			ISCSI_KCQE_COMPLETION_STATUS_ISCSI_NOT_SUPPORTED;
-		goto done;
-	}
-
-	CNIC_WR(dev, BAR_TSTRORM_INTMEM +
-		TSTORM_ISCSI_ERROR_BITMAP_OFFSET(pfid), req2->error_bit_map[0]);
-	CNIC_WR(dev, BAR_TSTRORM_INTMEM +
-		TSTORM_ISCSI_ERROR_BITMAP_OFFSET(pfid) + 4,
-		req2->error_bit_map[1]);
-
-	CNIC_WR16(dev, BAR_USTRORM_INTMEM +
-		  USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfid), req2->max_cq_sqn);
-	CNIC_WR(dev, BAR_USTRORM_INTMEM +
-		USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfid), req2->error_bit_map[0]);
-	CNIC_WR(dev, BAR_USTRORM_INTMEM +
-		USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfid) + 4,
-		req2->error_bit_map[1]);
-
-	CNIC_WR16(dev, BAR_CSTRORM_INTMEM +
-		  CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfid), req2->max_cq_sqn);
-
-	kcqe.completion_status = ISCSI_KCQE_COMPLETION_STATUS_SUCCESS;
-
-done:
-	kcqe.op_code = ISCSI_KCQE_OPCODE_INIT;
-	cqes[0] = (struct kcqe *) &kcqe;
-	cnic_reply_bnx2x_kcqes(dev, CNIC_ULP_ISCSI, cqes, 1);
-
-	return 0;
-}
-
-static void cnic_free_bnx2x_conn_resc(struct cnic_dev *dev, u32 l5_cid)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
-
-	if (ctx->ulp_proto_id == CNIC_ULP_ISCSI) {
-		struct cnic_iscsi *iscsi = ctx->proto.iscsi;
-
-		cnic_free_dma(dev, &iscsi->hq_info);
-		cnic_free_dma(dev, &iscsi->r2tq_info);
-		cnic_free_dma(dev, &iscsi->task_array_info);
-		cnic_free_id(&cp->cid_tbl, ctx->cid);
-	} else {
-		cnic_free_id(&cp->fcoe_cid_tbl, ctx->cid);
-	}
-
-	ctx->cid = 0;
-}
-
-static int cnic_alloc_bnx2x_conn_resc(struct cnic_dev *dev, u32 l5_cid)
-{
-	u32 cid;
-	int ret, pages;
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
-	struct cnic_iscsi *iscsi = ctx->proto.iscsi;
-
-	if (ctx->ulp_proto_id == CNIC_ULP_FCOE) {
-		cid = cnic_alloc_new_id(&cp->fcoe_cid_tbl);
-		if (cid == -1) {
-			ret = -ENOMEM;
-			goto error;
-		}
-		ctx->cid = cid;
-		return 0;
-	}
-
-	cid = cnic_alloc_new_id(&cp->cid_tbl);
-	if (cid == -1) {
-		ret = -ENOMEM;
-		goto error;
-	}
-
-	ctx->cid = cid;
-	pages = PAGE_ALIGN(cp->task_array_size) / PAGE_SIZE;
-
-	ret = cnic_alloc_dma(dev, &iscsi->task_array_info, pages, 1);
-	if (ret)
-		goto error;
-
-	pages = PAGE_ALIGN(cp->r2tq_size) / PAGE_SIZE;
-	ret = cnic_alloc_dma(dev, &iscsi->r2tq_info, pages, 1);
-	if (ret)
-		goto error;
-
-	pages = PAGE_ALIGN(cp->hq_size) / PAGE_SIZE;
-	ret = cnic_alloc_dma(dev, &iscsi->hq_info, pages, 1);
-	if (ret)
-		goto error;
-
-	return 0;
-
-error:
-	cnic_free_bnx2x_conn_resc(dev, l5_cid);
-	return ret;
-}
-
-static void *cnic_get_bnx2x_ctx(struct cnic_dev *dev, u32 cid, int init,
-				struct regpair *ctx_addr)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	int blk = (cid - ethdev->starting_cid) / cp->cids_per_blk;
-	int off = (cid - ethdev->starting_cid) % cp->cids_per_blk;
-	unsigned long align_off = 0;
-	dma_addr_t ctx_map;
-	void *ctx;
-
-	if (cp->ctx_align) {
-		unsigned long mask = cp->ctx_align - 1;
-
-		if (cp->ctx_arr[blk].mapping & mask)
-			align_off = cp->ctx_align -
-				    (cp->ctx_arr[blk].mapping & mask);
-	}
-	ctx_map = cp->ctx_arr[blk].mapping + align_off +
-		(off * BNX2X_CONTEXT_MEM_SIZE);
-	ctx = cp->ctx_arr[blk].ctx + align_off +
-	      (off * BNX2X_CONTEXT_MEM_SIZE);
-	if (init)
-		memset(ctx, 0, BNX2X_CONTEXT_MEM_SIZE);
-
-	ctx_addr->lo = ctx_map & 0xffffffff;
-	ctx_addr->hi = (u64) ctx_map >> 32;
-	return ctx;
-}
-
-static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],
-				u32 num)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct iscsi_kwqe_conn_offload1 *req1 =
-			(struct iscsi_kwqe_conn_offload1 *) wqes[0];
-	struct iscsi_kwqe_conn_offload2 *req2 =
-			(struct iscsi_kwqe_conn_offload2 *) wqes[1];
-	struct iscsi_kwqe_conn_offload3 *req3;
-	struct cnic_context *ctx = &cp->ctx_tbl[req1->iscsi_conn_id];
-	struct cnic_iscsi *iscsi = ctx->proto.iscsi;
-	u32 cid = ctx->cid;
-	u32 hw_cid = BNX2X_HW_CID(cp, cid);
-	struct iscsi_context *ictx;
-	struct regpair context_addr;
-	int i, j, n = 2, n_max;
-	u8 port = CNIC_PORT(cp);
-
-	ctx->ctx_flags = 0;
-	if (!req2->num_additional_wqes)
-		return -EINVAL;
-
-	n_max = req2->num_additional_wqes + 2;
-
-	ictx = cnic_get_bnx2x_ctx(dev, cid, 1, &context_addr);
-	if (ictx == NULL)
-		return -ENOMEM;
-
-	req3 = (struct iscsi_kwqe_conn_offload3 *) wqes[n++];
-
-	ictx->xstorm_ag_context.hq_prod = 1;
-
-	ictx->xstorm_st_context.iscsi.first_burst_length =
-		ISCSI_DEF_FIRST_BURST_LEN;
-	ictx->xstorm_st_context.iscsi.max_send_pdu_length =
-		ISCSI_DEF_MAX_RECV_SEG_LEN;
-	ictx->xstorm_st_context.iscsi.sq_pbl_base.lo =
-		req1->sq_page_table_addr_lo;
-	ictx->xstorm_st_context.iscsi.sq_pbl_base.hi =
-		req1->sq_page_table_addr_hi;
-	ictx->xstorm_st_context.iscsi.sq_curr_pbe.lo = req2->sq_first_pte.hi;
-	ictx->xstorm_st_context.iscsi.sq_curr_pbe.hi = req2->sq_first_pte.lo;
-	ictx->xstorm_st_context.iscsi.hq_pbl_base.lo =
-		iscsi->hq_info.pgtbl_map & 0xffffffff;
-	ictx->xstorm_st_context.iscsi.hq_pbl_base.hi =
-		(u64) iscsi->hq_info.pgtbl_map >> 32;
-	ictx->xstorm_st_context.iscsi.hq_curr_pbe_base.lo =
-		iscsi->hq_info.pgtbl[0];
-	ictx->xstorm_st_context.iscsi.hq_curr_pbe_base.hi =
-		iscsi->hq_info.pgtbl[1];
-	ictx->xstorm_st_context.iscsi.r2tq_pbl_base.lo =
-		iscsi->r2tq_info.pgtbl_map & 0xffffffff;
-	ictx->xstorm_st_context.iscsi.r2tq_pbl_base.hi =
-		(u64) iscsi->r2tq_info.pgtbl_map >> 32;
-	ictx->xstorm_st_context.iscsi.r2tq_curr_pbe_base.lo =
-		iscsi->r2tq_info.pgtbl[0];
-	ictx->xstorm_st_context.iscsi.r2tq_curr_pbe_base.hi =
-		iscsi->r2tq_info.pgtbl[1];
-	ictx->xstorm_st_context.iscsi.task_pbl_base.lo =
-		iscsi->task_array_info.pgtbl_map & 0xffffffff;
-	ictx->xstorm_st_context.iscsi.task_pbl_base.hi =
-		(u64) iscsi->task_array_info.pgtbl_map >> 32;
-	ictx->xstorm_st_context.iscsi.task_pbl_cache_idx =
-		BNX2X_ISCSI_PBL_NOT_CACHED;
-	ictx->xstorm_st_context.iscsi.flags.flags |=
-		XSTORM_ISCSI_CONTEXT_FLAGS_B_IMMEDIATE_DATA;
-	ictx->xstorm_st_context.iscsi.flags.flags |=
-		XSTORM_ISCSI_CONTEXT_FLAGS_B_INITIAL_R2T;
-	ictx->xstorm_st_context.common.ethernet.reserved_vlan_type =
-		ETH_P_8021Q;
-	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) &&
-		cp->port_mode == CHIP_2_PORT_MODE) {
-
-		port = 0;
-	}
-	ictx->xstorm_st_context.common.flags =
-		1 << XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED_SHIFT;
-	ictx->xstorm_st_context.common.flags =
-		port << XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT_SHIFT;
-
-	ictx->tstorm_st_context.iscsi.hdr_bytes_2_fetch = ISCSI_HEADER_SIZE;
-	/* TSTORM requires the base address of RQ DB & not PTE */
-	ictx->tstorm_st_context.iscsi.rq_db_phy_addr.lo =
-		req2->rq_page_table_addr_lo & PAGE_MASK;
-	ictx->tstorm_st_context.iscsi.rq_db_phy_addr.hi =
-		req2->rq_page_table_addr_hi;
-	ictx->tstorm_st_context.iscsi.iscsi_conn_id = req1->iscsi_conn_id;
-	ictx->tstorm_st_context.tcp.cwnd = 0x5A8;
-	ictx->tstorm_st_context.tcp.flags2 |=
-		TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN;
-	ictx->tstorm_st_context.tcp.ooo_support_mode =
-		TCP_TSTORM_OOO_DROP_AND_PROC_ACK;
-
-	ictx->timers_context.flags |= TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG;
-
-	ictx->ustorm_st_context.ring.rq.pbl_base.lo =
-		req2->rq_page_table_addr_lo;
-	ictx->ustorm_st_context.ring.rq.pbl_base.hi =
-		req2->rq_page_table_addr_hi;
-	ictx->ustorm_st_context.ring.rq.curr_pbe.lo = req3->qp_first_pte[0].hi;
-	ictx->ustorm_st_context.ring.rq.curr_pbe.hi = req3->qp_first_pte[0].lo;
-	ictx->ustorm_st_context.ring.r2tq.pbl_base.lo =
-		iscsi->r2tq_info.pgtbl_map & 0xffffffff;
-	ictx->ustorm_st_context.ring.r2tq.pbl_base.hi =
-		(u64) iscsi->r2tq_info.pgtbl_map >> 32;
-	ictx->ustorm_st_context.ring.r2tq.curr_pbe.lo =
-		iscsi->r2tq_info.pgtbl[0];
-	ictx->ustorm_st_context.ring.r2tq.curr_pbe.hi =
-		iscsi->r2tq_info.pgtbl[1];
-	ictx->ustorm_st_context.ring.cq_pbl_base.lo =
-		req1->cq_page_table_addr_lo;
-	ictx->ustorm_st_context.ring.cq_pbl_base.hi =
-		req1->cq_page_table_addr_hi;
-	ictx->ustorm_st_context.ring.cq[0].cq_sn = ISCSI_INITIAL_SN;
-	ictx->ustorm_st_context.ring.cq[0].curr_pbe.lo = req2->cq_first_pte.hi;
-	ictx->ustorm_st_context.ring.cq[0].curr_pbe.hi = req2->cq_first_pte.lo;
-	ictx->ustorm_st_context.task_pbe_cache_index =
-		BNX2X_ISCSI_PBL_NOT_CACHED;
-	ictx->ustorm_st_context.task_pdu_cache_index =
-		BNX2X_ISCSI_PDU_HEADER_NOT_CACHED;
-
-	for (i = 1, j = 1; i < cp->num_cqs; i++, j++) {
-		if (j == 3) {
-			if (n >= n_max)
-				break;
-			req3 = (struct iscsi_kwqe_conn_offload3 *) wqes[n++];
-			j = 0;
-		}
-		ictx->ustorm_st_context.ring.cq[i].cq_sn = ISCSI_INITIAL_SN;
-		ictx->ustorm_st_context.ring.cq[i].curr_pbe.lo =
-			req3->qp_first_pte[j].hi;
-		ictx->ustorm_st_context.ring.cq[i].curr_pbe.hi =
-			req3->qp_first_pte[j].lo;
-	}
-
-	ictx->ustorm_st_context.task_pbl_base.lo =
-		iscsi->task_array_info.pgtbl_map & 0xffffffff;
-	ictx->ustorm_st_context.task_pbl_base.hi =
-		(u64) iscsi->task_array_info.pgtbl_map >> 32;
-	ictx->ustorm_st_context.tce_phy_addr.lo =
-		iscsi->task_array_info.pgtbl[0];
-	ictx->ustorm_st_context.tce_phy_addr.hi =
-		iscsi->task_array_info.pgtbl[1];
-	ictx->ustorm_st_context.iscsi_conn_id = req1->iscsi_conn_id;
-	ictx->ustorm_st_context.num_cqs = cp->num_cqs;
-	ictx->ustorm_st_context.negotiated_rx |= ISCSI_DEF_MAX_RECV_SEG_LEN;
-	ictx->ustorm_st_context.negotiated_rx_and_flags |=
-		ISCSI_DEF_MAX_BURST_LEN;
-	ictx->ustorm_st_context.negotiated_rx |=
-		ISCSI_DEFAULT_MAX_OUTSTANDING_R2T <<
-		USTORM_ISCSI_ST_CONTEXT_MAX_OUTSTANDING_R2TS_SHIFT;
-
-	ictx->cstorm_st_context.hq_pbl_base.lo =
-		iscsi->hq_info.pgtbl_map & 0xffffffff;
-	ictx->cstorm_st_context.hq_pbl_base.hi =
-		(u64) iscsi->hq_info.pgtbl_map >> 32;
-	ictx->cstorm_st_context.hq_curr_pbe.lo = iscsi->hq_info.pgtbl[0];
-	ictx->cstorm_st_context.hq_curr_pbe.hi = iscsi->hq_info.pgtbl[1];
-	ictx->cstorm_st_context.task_pbl_base.lo =
-		iscsi->task_array_info.pgtbl_map & 0xffffffff;
-	ictx->cstorm_st_context.task_pbl_base.hi =
-		(u64) iscsi->task_array_info.pgtbl_map >> 32;
-	/* CSTORM and USTORM initialization is different, CSTORM requires
-	 * CQ DB base & not PTE addr */
-	ictx->cstorm_st_context.cq_db_base.lo =
-		req1->cq_page_table_addr_lo & PAGE_MASK;
-	ictx->cstorm_st_context.cq_db_base.hi = req1->cq_page_table_addr_hi;
-	ictx->cstorm_st_context.iscsi_conn_id = req1->iscsi_conn_id;
-	ictx->cstorm_st_context.cq_proc_en_bit_map = (1 << cp->num_cqs) - 1;
-	for (i = 0; i < cp->num_cqs; i++) {
-		ictx->cstorm_st_context.cq_c_prod_sqn_arr.sqn[i] =
-			ISCSI_INITIAL_SN;
-		ictx->cstorm_st_context.cq_c_sqn_2_notify_arr.sqn[i] =
-			ISCSI_INITIAL_SN;
-	}
-
-	ictx->xstorm_ag_context.cdu_reserved =
-		CDU_RSRVD_VALUE_TYPE_A(hw_cid, CDU_REGION_NUMBER_XCM_AG,
-				       ISCSI_CONNECTION_TYPE);
-	ictx->ustorm_ag_context.cdu_usage =
-		CDU_RSRVD_VALUE_TYPE_A(hw_cid, CDU_REGION_NUMBER_UCM_AG,
-				       ISCSI_CONNECTION_TYPE);
-	return 0;
-
-}
-
-static int cnic_bnx2x_iscsi_ofld1(struct cnic_dev *dev, struct kwqe *wqes[],
-				   u32 num, int *work)
-{
-	struct iscsi_kwqe_conn_offload1 *req1;
-	struct iscsi_kwqe_conn_offload2 *req2;
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_context *ctx;
-	struct iscsi_kcqe kcqe;
-	struct kcqe *cqes[1];
-	u32 l5_cid;
-	int ret = 0;
-
-	if (num < 2) {
-		*work = num;
-		return -EINVAL;
-	}
-
-	req1 = (struct iscsi_kwqe_conn_offload1 *) wqes[0];
-	req2 = (struct iscsi_kwqe_conn_offload2 *) wqes[1];
-	if ((num - 2) < req2->num_additional_wqes) {
-		*work = num;
-		return -EINVAL;
-	}
-	*work = 2 + req2->num_additional_wqes;
-
-	l5_cid = req1->iscsi_conn_id;
-	if (l5_cid >= MAX_ISCSI_TBL_SZ)
-		return -EINVAL;
-
-	memset(&kcqe, 0, sizeof(kcqe));
-	kcqe.op_code = ISCSI_KCQE_OPCODE_OFFLOAD_CONN;
-	kcqe.iscsi_conn_id = l5_cid;
-	kcqe.completion_status = ISCSI_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE;
-
-	ctx = &cp->ctx_tbl[l5_cid];
-	if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags)) {
-		kcqe.completion_status =
-			ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY;
-		goto done;
-	}
-
-	if (atomic_inc_return(&cp->iscsi_conn) > dev->max_iscsi_conn) {
-		atomic_dec(&cp->iscsi_conn);
-		goto done;
-	}
-	ret = cnic_alloc_bnx2x_conn_resc(dev, l5_cid);
-	if (ret) {
-		atomic_dec(&cp->iscsi_conn);
-		ret = 0;
-		goto done;
-	}
-	ret = cnic_setup_bnx2x_ctx(dev, wqes, num);
-	if (ret < 0) {
-		cnic_free_bnx2x_conn_resc(dev, l5_cid);
-		atomic_dec(&cp->iscsi_conn);
-		goto done;
-	}
-
-	kcqe.completion_status = ISCSI_KCQE_COMPLETION_STATUS_SUCCESS;
-	kcqe.iscsi_conn_context_id = BNX2X_HW_CID(cp, cp->ctx_tbl[l5_cid].cid);
-
-done:
-	cqes[0] = (struct kcqe *) &kcqe;
-	cnic_reply_bnx2x_kcqes(dev, CNIC_ULP_ISCSI, cqes, 1);
-	return ret;
-}
-
-
-static int cnic_bnx2x_iscsi_update(struct cnic_dev *dev, struct kwqe *kwqe)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct iscsi_kwqe_conn_update *req =
-		(struct iscsi_kwqe_conn_update *) kwqe;
-	void *data;
-	union l5cm_specific_data l5_data;
-	u32 l5_cid, cid = BNX2X_SW_CID(req->context_id);
-	int ret;
-
-	if (cnic_get_l5_cid(cp, cid, &l5_cid) != 0)
-		return -EINVAL;
-
-	data = cnic_get_kwqe_16_data(cp, l5_cid, &l5_data);
-	if (!data)
-		return -ENOMEM;
-
-	memcpy(data, kwqe, sizeof(struct kwqe));
-
-	ret = cnic_submit_kwqe_16(dev, ISCSI_RAMROD_CMD_ID_UPDATE_CONN,
-			req->context_id, ISCSI_CONNECTION_TYPE, &l5_data);
-	return ret;
-}
-
-static int cnic_bnx2x_destroy_ramrod(struct cnic_dev *dev, u32 l5_cid)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
-	union l5cm_specific_data l5_data;
-	int ret;
-	u32 hw_cid;
-
-	init_waitqueue_head(&ctx->waitq);
-	ctx->wait_cond = 0;
-	memset(&l5_data, 0, sizeof(l5_data));
-	hw_cid = BNX2X_HW_CID(cp, ctx->cid);
-
-	ret = cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_COMMON_CFC_DEL,
-				  hw_cid, NONE_CONNECTION_TYPE, &l5_data);
-
-	if (ret == 0) {
-		wait_event(ctx->waitq, ctx->wait_cond);
-		if (unlikely(test_bit(CTX_FL_CID_ERROR, &ctx->ctx_flags)))
-			return -EBUSY;
-	}
-
-	return ret;
-}
-
-static int cnic_bnx2x_iscsi_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct iscsi_kwqe_conn_destroy *req =
-		(struct iscsi_kwqe_conn_destroy *) kwqe;
-	u32 l5_cid = req->reserved0;
-	struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
-	int ret = 0;
-	struct iscsi_kcqe kcqe;
-	struct kcqe *cqes[1];
-
-	if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
-		goto skip_cfc_delete;
-
-	if (!time_after(jiffies, ctx->timestamp + (2 * HZ))) {
-		unsigned long delta = ctx->timestamp + (2 * HZ) - jiffies;
-
-		if (delta > (2 * HZ))
-			delta = 0;
-
-		set_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags);
-		queue_delayed_work(cnic_wq, &cp->delete_task, delta);
-		goto destroy_reply;
-	}
-
-	ret = cnic_bnx2x_destroy_ramrod(dev, l5_cid);
-
-skip_cfc_delete:
-	cnic_free_bnx2x_conn_resc(dev, l5_cid);
-
-	if (!ret) {
-		atomic_dec(&cp->iscsi_conn);
-		clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
-	}
-
-destroy_reply:
-	memset(&kcqe, 0, sizeof(kcqe));
-	kcqe.op_code = ISCSI_KCQE_OPCODE_DESTROY_CONN;
-	kcqe.iscsi_conn_id = l5_cid;
-	kcqe.completion_status = ISCSI_KCQE_COMPLETION_STATUS_SUCCESS;
-	kcqe.iscsi_conn_context_id = req->context_id;
-
-	cqes[0] = (struct kcqe *) &kcqe;
-	cnic_reply_bnx2x_kcqes(dev, CNIC_ULP_ISCSI, cqes, 1);
-
-	return ret;
-}
-
-static void cnic_init_storm_conn_bufs(struct cnic_dev *dev,
-				      struct l4_kwq_connect_req1 *kwqe1,
-				      struct l4_kwq_connect_req3 *kwqe3,
-				      struct l5cm_active_conn_buffer *conn_buf)
-{
-	struct l5cm_conn_addr_params *conn_addr = &conn_buf->conn_addr_buf;
-	struct l5cm_xstorm_conn_buffer *xstorm_buf =
-		&conn_buf->xstorm_conn_buffer;
-	struct l5cm_tstorm_conn_buffer *tstorm_buf =
-		&conn_buf->tstorm_conn_buffer;
-	struct regpair context_addr;
-	u32 cid = BNX2X_SW_CID(kwqe1->cid);
-	struct in6_addr src_ip, dst_ip;
-	int i;
-	u32 *addrp;
-
-	addrp = (u32 *) &conn_addr->local_ip_addr;
-	for (i = 0; i < 4; i++, addrp++)
-		src_ip.in6_u.u6_addr32[i] = cpu_to_be32(*addrp);
-
-	addrp = (u32 *) &conn_addr->remote_ip_addr;
-	for (i = 0; i < 4; i++, addrp++)
-		dst_ip.in6_u.u6_addr32[i] = cpu_to_be32(*addrp);
-
-	cnic_get_bnx2x_ctx(dev, cid, 0, &context_addr);
-
-	xstorm_buf->context_addr.hi = context_addr.hi;
-	xstorm_buf->context_addr.lo = context_addr.lo;
-	xstorm_buf->mss = 0xffff;
-	xstorm_buf->rcv_buf = kwqe3->rcv_buf;
-	if (kwqe1->tcp_flags & L4_KWQ_CONNECT_REQ1_NAGLE_ENABLE)
-		xstorm_buf->params |= L5CM_XSTORM_CONN_BUFFER_NAGLE_ENABLE;
-	xstorm_buf->pseudo_header_checksum =
-		swab16(~csum_ipv6_magic(&src_ip, &dst_ip, 0, IPPROTO_TCP, 0));
-
-	if (!(kwqe1->tcp_flags & L4_KWQ_CONNECT_REQ1_NO_DELAY_ACK))
-		tstorm_buf->params |=
-			L5CM_TSTORM_CONN_BUFFER_DELAYED_ACK_ENABLE;
-	if (kwqe3->ka_timeout) {
-		tstorm_buf->ka_enable = 1;
-		tstorm_buf->ka_timeout = kwqe3->ka_timeout;
-		tstorm_buf->ka_interval = kwqe3->ka_interval;
-		tstorm_buf->ka_max_probe_count = kwqe3->ka_max_probe_count;
-	}
-	tstorm_buf->max_rt_time = 0xffffffff;
-}
-
-static void cnic_init_bnx2x_mac(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 pfid = cp->pfid;
-	u8 *mac = dev->mac_addr;
-
-	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(pfid), mac[0]);
-	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfid), mac[1]);
-	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfid), mac[2]);
-	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfid), mac[3]);
-	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfid), mac[4]);
-	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfid), mac[5]);
-
-	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfid), mac[5]);
-	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
-		 mac[4]);
-	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfid), mac[3]);
-	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
-		 mac[2]);
-	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid), mac[1]);
-	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
-		 mac[0]);
-}
-
-static void cnic_bnx2x_set_tcp_timestamp(struct cnic_dev *dev, int tcp_ts)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	u8 xstorm_flags = XSTORM_L5CM_TCP_FLAGS_WND_SCL_EN;
-	u16 tstorm_flags = 0;
-
-	if (tcp_ts) {
-		xstorm_flags |= XSTORM_L5CM_TCP_FLAGS_TS_ENABLED;
-		tstorm_flags |= TSTORM_L5CM_TCP_FLAGS_TS_ENABLED;
-	}
-
-	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->pfid), xstorm_flags);
-
-	CNIC_WR16(dev, BAR_TSTRORM_INTMEM +
-		  TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->pfid), tstorm_flags);
-}
-
-static int cnic_bnx2x_connect(struct cnic_dev *dev, struct kwqe *wqes[],
-			      u32 num, int *work)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct l4_kwq_connect_req1 *kwqe1 =
-		(struct l4_kwq_connect_req1 *) wqes[0];
-	struct l4_kwq_connect_req3 *kwqe3;
-	struct l5cm_active_conn_buffer *conn_buf;
-	struct l5cm_conn_addr_params *conn_addr;
-	union l5cm_specific_data l5_data;
-	u32 l5_cid = kwqe1->pg_cid;
-	struct cnic_sock *csk = &cp->csk_tbl[l5_cid];
-	struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
-	int ret;
-
-	if (num < 2) {
-		*work = num;
-		return -EINVAL;
-	}
-
-	if (kwqe1->conn_flags & L4_KWQ_CONNECT_REQ1_IP_V6)
-		*work = 3;
-	else
-		*work = 2;
-
-	if (num < *work) {
-		*work = num;
-		return -EINVAL;
-	}
-
-	if (sizeof(*conn_buf) > CNIC_KWQ16_DATA_SIZE) {
-		netdev_err(dev->netdev, "conn_buf size too big\n");
-		return -ENOMEM;
-	}
-	conn_buf = cnic_get_kwqe_16_data(cp, l5_cid, &l5_data);
-	if (!conn_buf)
-		return -ENOMEM;
-
-	memset(conn_buf, 0, sizeof(*conn_buf));
-
-	conn_addr = &conn_buf->conn_addr_buf;
-	conn_addr->remote_addr_0 = csk->ha[0];
-	conn_addr->remote_addr_1 = csk->ha[1];
-	conn_addr->remote_addr_2 = csk->ha[2];
-	conn_addr->remote_addr_3 = csk->ha[3];
-	conn_addr->remote_addr_4 = csk->ha[4];
-	conn_addr->remote_addr_5 = csk->ha[5];
-
-	if (kwqe1->conn_flags & L4_KWQ_CONNECT_REQ1_IP_V6) {
-		struct l4_kwq_connect_req2 *kwqe2 =
-			(struct l4_kwq_connect_req2 *) wqes[1];
-
-		conn_addr->local_ip_addr.ip_addr_hi_hi = kwqe2->src_ip_v6_4;
-		conn_addr->local_ip_addr.ip_addr_hi_lo = kwqe2->src_ip_v6_3;
-		conn_addr->local_ip_addr.ip_addr_lo_hi = kwqe2->src_ip_v6_2;
-
-		conn_addr->remote_ip_addr.ip_addr_hi_hi = kwqe2->dst_ip_v6_4;
-		conn_addr->remote_ip_addr.ip_addr_hi_lo = kwqe2->dst_ip_v6_3;
-		conn_addr->remote_ip_addr.ip_addr_lo_hi = kwqe2->dst_ip_v6_2;
-		conn_addr->params |= L5CM_CONN_ADDR_PARAMS_IP_VERSION;
-	}
-	kwqe3 = (struct l4_kwq_connect_req3 *) wqes[*work - 1];
-
-	conn_addr->local_ip_addr.ip_addr_lo_lo = kwqe1->src_ip;
-	conn_addr->remote_ip_addr.ip_addr_lo_lo = kwqe1->dst_ip;
-	conn_addr->local_tcp_port = kwqe1->src_port;
-	conn_addr->remote_tcp_port = kwqe1->dst_port;
-
-	conn_addr->pmtu = kwqe3->pmtu;
-	cnic_init_storm_conn_bufs(dev, kwqe1, kwqe3, conn_buf);
-
-	CNIC_WR16(dev, BAR_XSTRORM_INTMEM +
-		  XSTORM_ISCSI_LOCAL_VLAN_OFFSET(cp->pfid), csk->vlan_id);
-
-	cnic_bnx2x_set_tcp_timestamp(dev,
-		kwqe1->tcp_flags & L4_KWQ_CONNECT_REQ1_TIME_STAMP);
-
-	ret = cnic_submit_kwqe_16(dev, L5CM_RAMROD_CMD_ID_TCP_CONNECT,
-			kwqe1->cid, ISCSI_CONNECTION_TYPE, &l5_data);
-	if (!ret)
-		set_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
-
-	return ret;
-}
-
-static int cnic_bnx2x_close(struct cnic_dev *dev, struct kwqe *kwqe)
-{
-	struct l4_kwq_close_req *req = (struct l4_kwq_close_req *) kwqe;
-	union l5cm_specific_data l5_data;
-	int ret;
-
-	memset(&l5_data, 0, sizeof(l5_data));
-	ret = cnic_submit_kwqe_16(dev, L5CM_RAMROD_CMD_ID_CLOSE,
-			req->cid, ISCSI_CONNECTION_TYPE, &l5_data);
-	return ret;
-}
-
-static int cnic_bnx2x_reset(struct cnic_dev *dev, struct kwqe *kwqe)
-{
-	struct l4_kwq_reset_req *req = (struct l4_kwq_reset_req *) kwqe;
-	union l5cm_specific_data l5_data;
-	int ret;
-
-	memset(&l5_data, 0, sizeof(l5_data));
-	ret = cnic_submit_kwqe_16(dev, L5CM_RAMROD_CMD_ID_ABORT,
-			req->cid, ISCSI_CONNECTION_TYPE, &l5_data);
-	return ret;
-}
-static int cnic_bnx2x_offload_pg(struct cnic_dev *dev, struct kwqe *kwqe)
-{
-	struct l4_kwq_offload_pg *req = (struct l4_kwq_offload_pg *) kwqe;
-	struct l4_kcq kcqe;
-	struct kcqe *cqes[1];
-
-	memset(&kcqe, 0, sizeof(kcqe));
-	kcqe.pg_host_opaque = req->host_opaque;
-	kcqe.pg_cid = req->host_opaque;
-	kcqe.op_code = L4_KCQE_OPCODE_VALUE_OFFLOAD_PG;
-	cqes[0] = (struct kcqe *) &kcqe;
-	cnic_reply_bnx2x_kcqes(dev, CNIC_ULP_L4, cqes, 1);
-	return 0;
-}
-
-static int cnic_bnx2x_update_pg(struct cnic_dev *dev, struct kwqe *kwqe)
-{
-	struct l4_kwq_update_pg *req = (struct l4_kwq_update_pg *) kwqe;
-	struct l4_kcq kcqe;
-	struct kcqe *cqes[1];
-
-	memset(&kcqe, 0, sizeof(kcqe));
-	kcqe.pg_host_opaque = req->pg_host_opaque;
-	kcqe.pg_cid = req->pg_cid;
-	kcqe.op_code = L4_KCQE_OPCODE_VALUE_UPDATE_PG;
-	cqes[0] = (struct kcqe *) &kcqe;
-	cnic_reply_bnx2x_kcqes(dev, CNIC_ULP_L4, cqes, 1);
-	return 0;
-}
-
-static int cnic_bnx2x_fcoe_stat(struct cnic_dev *dev, struct kwqe *kwqe)
-{
-	struct fcoe_kwqe_stat *req;
-	struct fcoe_stat_ramrod_params *fcoe_stat;
-	union l5cm_specific_data l5_data;
-	struct cnic_local *cp = dev->cnic_priv;
-	int ret;
-	u32 cid;
-
-	req = (struct fcoe_kwqe_stat *) kwqe;
-	cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid);
-
-	fcoe_stat = cnic_get_kwqe_16_data(cp, BNX2X_FCOE_L5_CID_BASE, &l5_data);
-	if (!fcoe_stat)
-		return -ENOMEM;
-
-	memset(fcoe_stat, 0, sizeof(*fcoe_stat));
-	memcpy(&fcoe_stat->stat_kwqe, req, sizeof(*req));
-
-	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_STAT_FUNC, cid,
-				  FCOE_CONNECTION_TYPE, &l5_data);
-	return ret;
-}
-
-static int cnic_bnx2x_fcoe_init1(struct cnic_dev *dev, struct kwqe *wqes[],
-				 u32 num, int *work)
-{
-	int ret;
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 cid;
-	struct fcoe_init_ramrod_params *fcoe_init;
-	struct fcoe_kwqe_init1 *req1;
-	struct fcoe_kwqe_init2 *req2;
-	struct fcoe_kwqe_init3 *req3;
-	union l5cm_specific_data l5_data;
-
-	if (num < 3) {
-		*work = num;
-		return -EINVAL;
-	}
-	req1 = (struct fcoe_kwqe_init1 *) wqes[0];
-	req2 = (struct fcoe_kwqe_init2 *) wqes[1];
-	req3 = (struct fcoe_kwqe_init3 *) wqes[2];
-	if (req2->hdr.op_code != FCOE_KWQE_OPCODE_INIT2) {
-		*work = 1;
-		return -EINVAL;
-	}
-	if (req3->hdr.op_code != FCOE_KWQE_OPCODE_INIT3) {
-		*work = 2;
-		return -EINVAL;
-	}
-
-	if (sizeof(*fcoe_init) > CNIC_KWQ16_DATA_SIZE) {
-		netdev_err(dev->netdev, "fcoe_init size too big\n");
-		return -ENOMEM;
-	}
-	fcoe_init = cnic_get_kwqe_16_data(cp, BNX2X_FCOE_L5_CID_BASE, &l5_data);
-	if (!fcoe_init)
-		return -ENOMEM;
-
-	memset(fcoe_init, 0, sizeof(*fcoe_init));
-	memcpy(&fcoe_init->init_kwqe1, req1, sizeof(*req1));
-	memcpy(&fcoe_init->init_kwqe2, req2, sizeof(*req2));
-	memcpy(&fcoe_init->init_kwqe3, req3, sizeof(*req3));
-	fcoe_init->eq_pbl_base.lo = cp->kcq2.dma.pgtbl_map & 0xffffffff;
-	fcoe_init->eq_pbl_base.hi = (u64) cp->kcq2.dma.pgtbl_map >> 32;
-	fcoe_init->eq_pbl_size = cp->kcq2.dma.num_pages;
-
-	fcoe_init->sb_num = cp->status_blk_num;
-	fcoe_init->eq_prod = MAX_KCQ_IDX;
-	fcoe_init->sb_id = HC_INDEX_FCOE_EQ_CONS;
-	cp->kcq2.sw_prod_idx = 0;
-
-	cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid);
-	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_INIT_FUNC, cid,
-				  FCOE_CONNECTION_TYPE, &l5_data);
-	*work = 3;
-	return ret;
-}
-
-static int cnic_bnx2x_fcoe_ofld1(struct cnic_dev *dev, struct kwqe *wqes[],
-				 u32 num, int *work)
-{
-	int ret = 0;
-	u32 cid = -1, l5_cid;
-	struct cnic_local *cp = dev->cnic_priv;
-	struct fcoe_kwqe_conn_offload1 *req1;
-	struct fcoe_kwqe_conn_offload2 *req2;
-	struct fcoe_kwqe_conn_offload3 *req3;
-	struct fcoe_kwqe_conn_offload4 *req4;
-	struct fcoe_conn_offload_ramrod_params *fcoe_offload;
-	struct cnic_context *ctx;
-	struct fcoe_context *fctx;
-	struct regpair ctx_addr;
-	union l5cm_specific_data l5_data;
-	struct fcoe_kcqe kcqe;
-	struct kcqe *cqes[1];
-
-	if (num < 4) {
-		*work = num;
-		return -EINVAL;
-	}
-	req1 = (struct fcoe_kwqe_conn_offload1 *) wqes[0];
-	req2 = (struct fcoe_kwqe_conn_offload2 *) wqes[1];
-	req3 = (struct fcoe_kwqe_conn_offload3 *) wqes[2];
-	req4 = (struct fcoe_kwqe_conn_offload4 *) wqes[3];
-
-	*work = 4;
-
-	l5_cid = req1->fcoe_conn_id;
-	if (l5_cid >= BNX2X_FCOE_NUM_CONNECTIONS)
-		goto err_reply;
-
-	l5_cid += BNX2X_FCOE_L5_CID_BASE;
-
-	ctx = &cp->ctx_tbl[l5_cid];
-	if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
-		goto err_reply;
-
-	ret = cnic_alloc_bnx2x_conn_resc(dev, l5_cid);
-	if (ret) {
-		ret = 0;
-		goto err_reply;
-	}
-	cid = ctx->cid;
-
-	fctx = cnic_get_bnx2x_ctx(dev, cid, 1, &ctx_addr);
-	if (fctx) {
-		u32 hw_cid = BNX2X_HW_CID(cp, cid);
-		u32 val;
-
-		val = CDU_RSRVD_VALUE_TYPE_A(hw_cid, CDU_REGION_NUMBER_XCM_AG,
-					     FCOE_CONNECTION_TYPE);
-		fctx->xstorm_ag_context.cdu_reserved = val;
-		val = CDU_RSRVD_VALUE_TYPE_A(hw_cid, CDU_REGION_NUMBER_UCM_AG,
-					     FCOE_CONNECTION_TYPE);
-		fctx->ustorm_ag_context.cdu_usage = val;
-	}
-	if (sizeof(*fcoe_offload) > CNIC_KWQ16_DATA_SIZE) {
-		netdev_err(dev->netdev, "fcoe_offload size too big\n");
-		goto err_reply;
-	}
-	fcoe_offload = cnic_get_kwqe_16_data(cp, l5_cid, &l5_data);
-	if (!fcoe_offload)
-		goto err_reply;
-
-	memset(fcoe_offload, 0, sizeof(*fcoe_offload));
-	memcpy(&fcoe_offload->offload_kwqe1, req1, sizeof(*req1));
-	memcpy(&fcoe_offload->offload_kwqe2, req2, sizeof(*req2));
-	memcpy(&fcoe_offload->offload_kwqe3, req3, sizeof(*req3));
-	memcpy(&fcoe_offload->offload_kwqe4, req4, sizeof(*req4));
-
-	cid = BNX2X_HW_CID(cp, cid);
-	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_OFFLOAD_CONN, cid,
-				  FCOE_CONNECTION_TYPE, &l5_data);
-	if (!ret)
-		set_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
-
-	return ret;
-
-err_reply:
-	if (cid != -1)
-		cnic_free_bnx2x_conn_resc(dev, l5_cid);
-
-	memset(&kcqe, 0, sizeof(kcqe));
-	kcqe.op_code = FCOE_KCQE_OPCODE_OFFLOAD_CONN;
-	kcqe.fcoe_conn_id = req1->fcoe_conn_id;
-	kcqe.completion_status = FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE;
-
-	cqes[0] = (struct kcqe *) &kcqe;
-	cnic_reply_bnx2x_kcqes(dev, CNIC_ULP_FCOE, cqes, 1);
-	return ret;
-}
-
-static int cnic_bnx2x_fcoe_enable(struct cnic_dev *dev, struct kwqe *kwqe)
-{
-	struct fcoe_kwqe_conn_enable_disable *req;
-	struct fcoe_conn_enable_disable_ramrod_params *fcoe_enable;
-	union l5cm_specific_data l5_data;
-	int ret;
-	u32 cid, l5_cid;
-	struct cnic_local *cp = dev->cnic_priv;
-
-	req = (struct fcoe_kwqe_conn_enable_disable *) kwqe;
-	cid = req->context_id;
-	l5_cid = req->conn_id + BNX2X_FCOE_L5_CID_BASE;
-
-	if (sizeof(*fcoe_enable) > CNIC_KWQ16_DATA_SIZE) {
-		netdev_err(dev->netdev, "fcoe_enable size too big\n");
-		return -ENOMEM;
-	}
-	fcoe_enable = cnic_get_kwqe_16_data(cp, l5_cid, &l5_data);
-	if (!fcoe_enable)
-		return -ENOMEM;
-
-	memset(fcoe_enable, 0, sizeof(*fcoe_enable));
-	memcpy(&fcoe_enable->enable_disable_kwqe, req, sizeof(*req));
-	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_ENABLE_CONN, cid,
-				  FCOE_CONNECTION_TYPE, &l5_data);
-	return ret;
-}
-
-static int cnic_bnx2x_fcoe_disable(struct cnic_dev *dev, struct kwqe *kwqe)
-{
-	struct fcoe_kwqe_conn_enable_disable *req;
-	struct fcoe_conn_enable_disable_ramrod_params *fcoe_disable;
-	union l5cm_specific_data l5_data;
-	int ret;
-	u32 cid, l5_cid;
-	struct cnic_local *cp = dev->cnic_priv;
-
-	req = (struct fcoe_kwqe_conn_enable_disable *) kwqe;
-	cid = req->context_id;
-	l5_cid = req->conn_id;
-	if (l5_cid >= BNX2X_FCOE_NUM_CONNECTIONS)
-		return -EINVAL;
-
-	l5_cid += BNX2X_FCOE_L5_CID_BASE;
-
-	if (sizeof(*fcoe_disable) > CNIC_KWQ16_DATA_SIZE) {
-		netdev_err(dev->netdev, "fcoe_disable size too big\n");
-		return -ENOMEM;
-	}
-	fcoe_disable = cnic_get_kwqe_16_data(cp, l5_cid, &l5_data);
-	if (!fcoe_disable)
-		return -ENOMEM;
-
-	memset(fcoe_disable, 0, sizeof(*fcoe_disable));
-	memcpy(&fcoe_disable->enable_disable_kwqe, req, sizeof(*req));
-	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_DISABLE_CONN, cid,
-				  FCOE_CONNECTION_TYPE, &l5_data);
-	return ret;
-}
-
-static int cnic_bnx2x_fcoe_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
-{
-	struct fcoe_kwqe_conn_destroy *req;
-	union l5cm_specific_data l5_data;
-	int ret;
-	u32 cid, l5_cid;
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_context *ctx;
-	struct fcoe_kcqe kcqe;
-	struct kcqe *cqes[1];
-
-	req = (struct fcoe_kwqe_conn_destroy *) kwqe;
-	cid = req->context_id;
-	l5_cid = req->conn_id;
-	if (l5_cid >= BNX2X_FCOE_NUM_CONNECTIONS)
-		return -EINVAL;
-
-	l5_cid += BNX2X_FCOE_L5_CID_BASE;
-
-	ctx = &cp->ctx_tbl[l5_cid];
-
-	init_waitqueue_head(&ctx->waitq);
-	ctx->wait_cond = 0;
-
-	memset(&l5_data, 0, sizeof(l5_data));
-	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_TERMINATE_CONN, cid,
-				  FCOE_CONNECTION_TYPE, &l5_data);
-	if (ret == 0) {
-		wait_event(ctx->waitq, ctx->wait_cond);
-		set_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags);
-		queue_delayed_work(cnic_wq, &cp->delete_task,
-				   msecs_to_jiffies(2000));
-	}
-
-	memset(&kcqe, 0, sizeof(kcqe));
-	kcqe.op_code = FCOE_KCQE_OPCODE_DESTROY_CONN;
-	kcqe.fcoe_conn_id = req->conn_id;
-	kcqe.fcoe_conn_context_id = cid;
-
-	cqes[0] = (struct kcqe *) &kcqe;
-	cnic_reply_bnx2x_kcqes(dev, CNIC_ULP_FCOE, cqes, 1);
-	return ret;
-}
-
-static void cnic_bnx2x_delete_wait(struct cnic_dev *dev, u32 start_cid)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 i;
-
-	for (i = start_cid; i < cp->max_cid_space; i++) {
-		struct cnic_context *ctx = &cp->ctx_tbl[i];
-		int j;
-
-		while (test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
-			msleep(10);
-
-		for (j = 0; j < 5; j++) {
-			if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
-				break;
-			msleep(20);
-		}
-
-		if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
-			netdev_warn(dev->netdev, "CID %x not deleted\n",
-				   ctx->cid);
-	}
-}
-
-static int cnic_bnx2x_fcoe_fw_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
-{
-	struct fcoe_kwqe_destroy *req;
-	union l5cm_specific_data l5_data;
-	struct cnic_local *cp = dev->cnic_priv;
-	int ret;
-	u32 cid;
-
-	cnic_bnx2x_delete_wait(dev, MAX_ISCSI_TBL_SZ);
-
-	req = (struct fcoe_kwqe_destroy *) kwqe;
-	cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid);
-
-	memset(&l5_data, 0, sizeof(l5_data));
-	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_DESTROY_FUNC, cid,
-				  FCOE_CONNECTION_TYPE, &l5_data);
-	return ret;
-}
-
-static int cnic_submit_bnx2x_iscsi_kwqes(struct cnic_dev *dev,
-					 struct kwqe *wqes[], u32 num_wqes)
-{
-	int i, work, ret;
-	u32 opcode;
-	struct kwqe *kwqe;
-
-	if (!test_bit(CNIC_F_CNIC_UP, &dev->flags))
-		return -EAGAIN;		/* bnx2 is down */
-
-	for (i = 0; i < num_wqes; ) {
-		kwqe = wqes[i];
-		opcode = KWQE_OPCODE(kwqe->kwqe_op_flag);
-		work = 1;
-
-		switch (opcode) {
-		case ISCSI_KWQE_OPCODE_INIT1:
-			ret = cnic_bnx2x_iscsi_init1(dev, kwqe);
-			break;
-		case ISCSI_KWQE_OPCODE_INIT2:
-			ret = cnic_bnx2x_iscsi_init2(dev, kwqe);
-			break;
-		case ISCSI_KWQE_OPCODE_OFFLOAD_CONN1:
-			ret = cnic_bnx2x_iscsi_ofld1(dev, &wqes[i],
-						     num_wqes - i, &work);
-			break;
-		case ISCSI_KWQE_OPCODE_UPDATE_CONN:
-			ret = cnic_bnx2x_iscsi_update(dev, kwqe);
-			break;
-		case ISCSI_KWQE_OPCODE_DESTROY_CONN:
-			ret = cnic_bnx2x_iscsi_destroy(dev, kwqe);
-			break;
-		case L4_KWQE_OPCODE_VALUE_CONNECT1:
-			ret = cnic_bnx2x_connect(dev, &wqes[i], num_wqes - i,
-						 &work);
-			break;
-		case L4_KWQE_OPCODE_VALUE_CLOSE:
-			ret = cnic_bnx2x_close(dev, kwqe);
-			break;
-		case L4_KWQE_OPCODE_VALUE_RESET:
-			ret = cnic_bnx2x_reset(dev, kwqe);
-			break;
-		case L4_KWQE_OPCODE_VALUE_OFFLOAD_PG:
-			ret = cnic_bnx2x_offload_pg(dev, kwqe);
-			break;
-		case L4_KWQE_OPCODE_VALUE_UPDATE_PG:
-			ret = cnic_bnx2x_update_pg(dev, kwqe);
-			break;
-		case L4_KWQE_OPCODE_VALUE_UPLOAD_PG:
-			ret = 0;
-			break;
-		default:
-			ret = 0;
-			netdev_err(dev->netdev, "Unknown type of KWQE(0x%x)\n",
-				   opcode);
-			break;
-		}
-		if (ret < 0)
-			netdev_err(dev->netdev, "KWQE(0x%x) failed\n",
-				   opcode);
-		i += work;
-	}
-	return 0;
-}
-
-static int cnic_submit_bnx2x_fcoe_kwqes(struct cnic_dev *dev,
-					struct kwqe *wqes[], u32 num_wqes)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	int i, work, ret;
-	u32 opcode;
-	struct kwqe *kwqe;
-
-	if (!test_bit(CNIC_F_CNIC_UP, &dev->flags))
-		return -EAGAIN;		/* bnx2 is down */
-
-	if (!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id))
-		return -EINVAL;
-
-	for (i = 0; i < num_wqes; ) {
-		kwqe = wqes[i];
-		opcode = KWQE_OPCODE(kwqe->kwqe_op_flag);
-		work = 1;
-
-		switch (opcode) {
-		case FCOE_KWQE_OPCODE_INIT1:
-			ret = cnic_bnx2x_fcoe_init1(dev, &wqes[i],
-						    num_wqes - i, &work);
-			break;
-		case FCOE_KWQE_OPCODE_OFFLOAD_CONN1:
-			ret = cnic_bnx2x_fcoe_ofld1(dev, &wqes[i],
-						    num_wqes - i, &work);
-			break;
-		case FCOE_KWQE_OPCODE_ENABLE_CONN:
-			ret = cnic_bnx2x_fcoe_enable(dev, kwqe);
-			break;
-		case FCOE_KWQE_OPCODE_DISABLE_CONN:
-			ret = cnic_bnx2x_fcoe_disable(dev, kwqe);
-			break;
-		case FCOE_KWQE_OPCODE_DESTROY_CONN:
-			ret = cnic_bnx2x_fcoe_destroy(dev, kwqe);
-			break;
-		case FCOE_KWQE_OPCODE_DESTROY:
-			ret = cnic_bnx2x_fcoe_fw_destroy(dev, kwqe);
-			break;
-		case FCOE_KWQE_OPCODE_STAT:
-			ret = cnic_bnx2x_fcoe_stat(dev, kwqe);
-			break;
-		default:
-			ret = 0;
-			netdev_err(dev->netdev, "Unknown type of KWQE(0x%x)\n",
-				   opcode);
-			break;
-		}
-		if (ret < 0)
-			netdev_err(dev->netdev, "KWQE(0x%x) failed\n",
-				   opcode);
-		i += work;
-	}
-	return 0;
-}
-
-static int cnic_submit_bnx2x_kwqes(struct cnic_dev *dev, struct kwqe *wqes[],
-				   u32 num_wqes)
-{
-	int ret = -EINVAL;
-	u32 layer_code;
-
-	if (!test_bit(CNIC_F_CNIC_UP, &dev->flags))
-		return -EAGAIN;		/* bnx2x is down */
-
-	if (!num_wqes)
-		return 0;
-
-	layer_code = wqes[0]->kwqe_op_flag & KWQE_LAYER_MASK;
-	switch (layer_code) {
-	case KWQE_FLAGS_LAYER_MASK_L5_ISCSI:
-	case KWQE_FLAGS_LAYER_MASK_L4:
-	case KWQE_FLAGS_LAYER_MASK_L2:
-		ret = cnic_submit_bnx2x_iscsi_kwqes(dev, wqes, num_wqes);
-		break;
-
-	case KWQE_FLAGS_LAYER_MASK_L5_FCOE:
-		ret = cnic_submit_bnx2x_fcoe_kwqes(dev, wqes, num_wqes);
-		break;
-	}
-	return ret;
-}
-
-static inline u32 cnic_get_kcqe_layer_mask(u32 opflag)
-{
-	if (unlikely(KCQE_OPCODE(opflag) == FCOE_RAMROD_CMD_ID_TERMINATE_CONN))
-		return KCQE_FLAGS_LAYER_MASK_L4;
-
-	return opflag & KCQE_FLAGS_LAYER_MASK;
-}
-
-static void service_kcqes(struct cnic_dev *dev, int num_cqes)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	int i, j, comp = 0;
-
-	i = 0;
-	j = 1;
-	while (num_cqes) {
-		struct cnic_ulp_ops *ulp_ops;
-		int ulp_type;
-		u32 kcqe_op_flag = cp->completed_kcq[i]->kcqe_op_flag;
-		u32 kcqe_layer = cnic_get_kcqe_layer_mask(kcqe_op_flag);
-
-		if (unlikely(kcqe_op_flag & KCQE_RAMROD_COMPLETION))
-			comp++;
-
-		while (j < num_cqes) {
-			u32 next_op = cp->completed_kcq[i + j]->kcqe_op_flag;
-
-			if (cnic_get_kcqe_layer_mask(next_op) != kcqe_layer)
-				break;
-
-			if (unlikely(next_op & KCQE_RAMROD_COMPLETION))
-				comp++;
-			j++;
-		}
-
-		if (kcqe_layer == KCQE_FLAGS_LAYER_MASK_L5_RDMA)
-			ulp_type = CNIC_ULP_RDMA;
-		else if (kcqe_layer == KCQE_FLAGS_LAYER_MASK_L5_ISCSI)
-			ulp_type = CNIC_ULP_ISCSI;
-		else if (kcqe_layer == KCQE_FLAGS_LAYER_MASK_L5_FCOE)
-			ulp_type = CNIC_ULP_FCOE;
-		else if (kcqe_layer == KCQE_FLAGS_LAYER_MASK_L4)
-			ulp_type = CNIC_ULP_L4;
-		else if (kcqe_layer == KCQE_FLAGS_LAYER_MASK_L2)
-			goto end;
-		else {
-			netdev_err(dev->netdev, "Unknown type of KCQE(0x%x)\n",
-				   kcqe_op_flag);
-			goto end;
-		}
-
-		rcu_read_lock();
-		ulp_ops = rcu_dereference(cp->ulp_ops[ulp_type]);
-		if (likely(ulp_ops)) {
-			ulp_ops->indicate_kcqes(cp->ulp_handle[ulp_type],
-						  cp->completed_kcq + i, j);
-		}
-		rcu_read_unlock();
-end:
-		num_cqes -= j;
-		i += j;
-		j = 1;
-	}
-	if (unlikely(comp))
-		cnic_spq_completion(dev, DRV_CTL_RET_L5_SPQ_CREDIT_CMD, comp);
-}
-
-static int cnic_get_kcqes(struct cnic_dev *dev, struct kcq_info *info)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	u16 i, ri, hw_prod, last;
-	struct kcqe *kcqe;
-	int kcqe_cnt = 0, last_cnt = 0;
-
-	i = ri = last = info->sw_prod_idx;
-	ri &= MAX_KCQ_IDX;
-	hw_prod = *info->hw_prod_idx_ptr;
-	hw_prod = info->hw_idx(hw_prod);
-
-	while ((i != hw_prod) && (kcqe_cnt < MAX_COMPLETED_KCQE)) {
-		kcqe = &info->kcq[KCQ_PG(ri)][KCQ_IDX(ri)];
-		cp->completed_kcq[kcqe_cnt++] = kcqe;
-		i = info->next_idx(i);
-		ri = i & MAX_KCQ_IDX;
-		if (likely(!(kcqe->kcqe_op_flag & KCQE_FLAGS_NEXT))) {
-			last_cnt = kcqe_cnt;
-			last = i;
-		}
-	}
-
-	info->sw_prod_idx = last;
-	return last_cnt;
-}
-
-static int cnic_l2_completion(struct cnic_local *cp)
-{
-	u16 hw_cons, sw_cons;
-	struct cnic_uio_dev *udev = cp->udev;
-	union eth_rx_cqe *cqe, *cqe_ring = (union eth_rx_cqe *)
-					(udev->l2_ring + (2 * BCM_PAGE_SIZE));
-	u32 cmd;
-	int comp = 0;
-
-	if (!test_bit(CNIC_F_BNX2X_CLASS, &cp->dev->flags))
-		return 0;
-
-	hw_cons = *cp->rx_cons_ptr;
-	if ((hw_cons & BNX2X_MAX_RCQ_DESC_CNT) == BNX2X_MAX_RCQ_DESC_CNT)
-		hw_cons++;
-
-	sw_cons = cp->rx_cons;
-	while (sw_cons != hw_cons) {
-		u8 cqe_fp_flags;
-
-		cqe = &cqe_ring[sw_cons & BNX2X_MAX_RCQ_DESC_CNT];
-		cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
-		if (cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE) {
-			cmd = le32_to_cpu(cqe->ramrod_cqe.conn_and_cmd_data);
-			cmd >>= COMMON_RAMROD_ETH_RX_CQE_CMD_ID_SHIFT;
-			if (cmd == RAMROD_CMD_ID_ETH_CLIENT_SETUP ||
-			    cmd == RAMROD_CMD_ID_ETH_HALT)
-				comp++;
-		}
-		sw_cons = BNX2X_NEXT_RCQE(sw_cons);
-	}
-	return comp;
-}
-
-static void cnic_chk_pkt_rings(struct cnic_local *cp)
-{
-	u16 rx_cons, tx_cons;
-	int comp = 0;
-
-	if (!test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags))
-		return;
-
-	rx_cons = *cp->rx_cons_ptr;
-	tx_cons = *cp->tx_cons_ptr;
-	if (cp->tx_cons != tx_cons || cp->rx_cons != rx_cons) {
-		if (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags))
-			comp = cnic_l2_completion(cp);
-
-		cp->tx_cons = tx_cons;
-		cp->rx_cons = rx_cons;
-
-		if (cp->udev)
-			uio_event_notify(&cp->udev->cnic_uinfo);
-	}
-	if (comp)
-		clear_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags);
-}
-
-static u32 cnic_service_bnx2_queues(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 status_idx = (u16) *cp->kcq1.status_idx_ptr;
-	int kcqe_cnt;
-
-	/* status block index must be read before reading other fields */
-	rmb();
-	cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
-
-	while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) {
-
-		service_kcqes(dev, kcqe_cnt);
-
-		/* Tell compiler that status_blk fields can change. */
-		barrier();
-		status_idx = (u16) *cp->kcq1.status_idx_ptr;
-		/* status block index must be read first */
-		rmb();
-		cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
-	}
-
-	CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx);
-
-	cnic_chk_pkt_rings(cp);
-
-	return status_idx;
-}
-
-static int cnic_service_bnx2(void *data, void *status_blk)
-{
-	struct cnic_dev *dev = data;
-
-	if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags))) {
-		struct status_block *sblk = status_blk;
-
-		return sblk->status_idx;
-	}
-
-	return cnic_service_bnx2_queues(dev);
-}
-
-static void cnic_service_bnx2_msix(unsigned long data)
-{
-	struct cnic_dev *dev = (struct cnic_dev *) data;
-	struct cnic_local *cp = dev->cnic_priv;
-
-	cp->last_status_idx = cnic_service_bnx2_queues(dev);
-
-	CNIC_WR(dev, BNX2_PCICFG_INT_ACK_CMD, cp->int_num |
-		BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | cp->last_status_idx);
-}
-
-static void cnic_doirq(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-
-	if (likely(test_bit(CNIC_F_CNIC_UP, &dev->flags))) {
-		u16 prod = cp->kcq1.sw_prod_idx & MAX_KCQ_IDX;
-
-		prefetch(cp->status_blk.gen);
-		prefetch(&cp->kcq1.kcq[KCQ_PG(prod)][KCQ_IDX(prod)]);
-
-		tasklet_schedule(&cp->cnic_irq_task);
-	}
-}
-
-static irqreturn_t cnic_irq(int irq, void *dev_instance)
-{
-	struct cnic_dev *dev = dev_instance;
-	struct cnic_local *cp = dev->cnic_priv;
-
-	if (cp->ack_int)
-		cp->ack_int(dev);
-
-	cnic_doirq(dev);
-
-	return IRQ_HANDLED;
-}
-
-static inline void cnic_ack_bnx2x_int(struct cnic_dev *dev, u8 id, u8 storm,
-				      u16 index, u8 op, u8 update)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 hc_addr = (HC_REG_COMMAND_REG + CNIC_PORT(cp) * 32 +
-		       COMMAND_REG_INT_ACK);
-	struct igu_ack_register igu_ack;
-
-	igu_ack.status_block_index = index;
-	igu_ack.sb_id_and_flags =
-			((id << IGU_ACK_REGISTER_STATUS_BLOCK_ID_SHIFT) |
-			 (storm << IGU_ACK_REGISTER_STORM_ID_SHIFT) |
-			 (update << IGU_ACK_REGISTER_UPDATE_INDEX_SHIFT) |
-			 (op << IGU_ACK_REGISTER_INTERRUPT_MODE_SHIFT));
-
-	CNIC_WR(dev, hc_addr, (*(u32 *)&igu_ack));
-}
-
-static void cnic_ack_igu_sb(struct cnic_dev *dev, u8 igu_sb_id, u8 segment,
-			    u16 index, u8 op, u8 update)
-{
-	struct igu_regular cmd_data;
-	u32 igu_addr = BAR_IGU_INTMEM + (IGU_CMD_INT_ACK_BASE + igu_sb_id) * 8;
-
-	cmd_data.sb_id_and_flags =
-		(index << IGU_REGULAR_SB_INDEX_SHIFT) |
-		(segment << IGU_REGULAR_SEGMENT_ACCESS_SHIFT) |
-		(update << IGU_REGULAR_BUPDATE_SHIFT) |
-		(op << IGU_REGULAR_ENABLE_INT_SHIFT);
-
-
-	CNIC_WR(dev, igu_addr, cmd_data.sb_id_and_flags);
-}
-
-static void cnic_ack_bnx2x_msix(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-
-	cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, CSTORM_ID, 0,
-			   IGU_INT_DISABLE, 0);
-}
-
-static void cnic_ack_bnx2x_e2_msix(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-
-	cnic_ack_igu_sb(dev, cp->bnx2x_igu_sb_id, IGU_SEG_ACCESS_DEF, 0,
-			IGU_INT_DISABLE, 0);
-}
-
-static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info)
-{
-	u32 last_status = *info->status_idx_ptr;
-	int kcqe_cnt;
-
-	/* status block index must be read before reading the KCQ */
-	rmb();
-	while ((kcqe_cnt = cnic_get_kcqes(dev, info))) {
-
-		service_kcqes(dev, kcqe_cnt);
-
-		/* Tell compiler that sblk fields can change. */
-		barrier();
-
-		last_status = *info->status_idx_ptr;
-		/* status block index must be read before reading the KCQ */
-		rmb();
-	}
-	return last_status;
-}
-
-static void cnic_service_bnx2x_bh(unsigned long data)
-{
-	struct cnic_dev *dev = (struct cnic_dev *) data;
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 status_idx, new_status_idx;
-
-	if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags)))
-		return;
-
-	while (1) {
-		status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq1);
-
-		CNIC_WR16(dev, cp->kcq1.io_addr,
-			  cp->kcq1.sw_prod_idx + MAX_KCQ_IDX);
-
-		if (!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
-			cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID,
-					   status_idx, IGU_INT_ENABLE, 1);
-			break;
-		}
-
-		new_status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq2);
-
-		if (new_status_idx != status_idx)
-			continue;
-
-		CNIC_WR16(dev, cp->kcq2.io_addr, cp->kcq2.sw_prod_idx +
-			  MAX_KCQ_IDX);
-
-		cnic_ack_igu_sb(dev, cp->bnx2x_igu_sb_id, IGU_SEG_ACCESS_DEF,
-				status_idx, IGU_INT_ENABLE, 1);
-
-		break;
-	}
-}
-
-static int cnic_service_bnx2x(void *data, void *status_blk)
-{
-	struct cnic_dev *dev = data;
-	struct cnic_local *cp = dev->cnic_priv;
-
-	if (!(cp->ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX))
-		cnic_doirq(dev);
-
-	cnic_chk_pkt_rings(cp);
-
-	return 0;
-}
-
-static void cnic_ulp_stop_one(struct cnic_local *cp, int if_type)
-{
-	struct cnic_ulp_ops *ulp_ops;
-
-	if (if_type == CNIC_ULP_ISCSI)
-		cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
-
-	mutex_lock(&cnic_lock);
-	ulp_ops = rcu_dereference_protected(cp->ulp_ops[if_type],
-					    lockdep_is_held(&cnic_lock));
-	if (!ulp_ops) {
-		mutex_unlock(&cnic_lock);
-		return;
-	}
-	set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
-	mutex_unlock(&cnic_lock);
-
-	if (test_and_clear_bit(ULP_F_START, &cp->ulp_flags[if_type]))
-		ulp_ops->cnic_stop(cp->ulp_handle[if_type]);
-
-	clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
-}
-
-static void cnic_ulp_stop(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	int if_type;
-
-	for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++)
-		cnic_ulp_stop_one(cp, if_type);
-}
-
-static void cnic_ulp_start(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	int if_type;
-
-	for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
-		struct cnic_ulp_ops *ulp_ops;
-
-		mutex_lock(&cnic_lock);
-		ulp_ops = 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;
-		}
-		set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
-		mutex_unlock(&cnic_lock);
-
-		if (!test_and_set_bit(ULP_F_START, &cp->ulp_flags[if_type]))
-			ulp_ops->cnic_start(cp->ulp_handle[if_type]);
-
-		clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
-	}
-}
-
-static int cnic_ctl(void *data, struct cnic_ctl_info *info)
-{
-	struct cnic_dev *dev = data;
-
-	switch (info->cmd) {
-	case CNIC_CTL_STOP_CMD:
-		cnic_hold(dev);
-
-		cnic_ulp_stop(dev);
-		cnic_stop_hw(dev);
-
-		cnic_put(dev);
-		break;
-	case CNIC_CTL_START_CMD:
-		cnic_hold(dev);
-
-		if (!cnic_start_hw(dev))
-			cnic_ulp_start(dev);
-
-		cnic_put(dev);
-		break;
-	case CNIC_CTL_STOP_ISCSI_CMD: {
-		struct cnic_local *cp = dev->cnic_priv;
-		set_bit(CNIC_LCL_FL_STOP_ISCSI, &cp->cnic_local_flags);
-		queue_delayed_work(cnic_wq, &cp->delete_task, 0);
-		break;
-	}
-	case CNIC_CTL_COMPLETION_CMD: {
-		struct cnic_ctl_completion *comp = &info->data.comp;
-		u32 cid = BNX2X_SW_CID(comp->cid);
-		u32 l5_cid;
-		struct cnic_local *cp = dev->cnic_priv;
-
-		if (cnic_get_l5_cid(cp, cid, &l5_cid) == 0) {
-			struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
-
-			if (unlikely(comp->error)) {
-				set_bit(CTX_FL_CID_ERROR, &ctx->ctx_flags);
-				netdev_err(dev->netdev,
-					   "CID %x CFC delete comp error %x\n",
-					   cid, comp->error);
-			}
-
-			ctx->wait_cond = 1;
-			wake_up(&ctx->waitq);
-		}
-		break;
-	}
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static void cnic_ulp_init(struct cnic_dev *dev)
-{
-	int i;
-	struct cnic_local *cp = dev->cnic_priv;
-
-	for (i = 0; i < MAX_CNIC_ULP_TYPE_EXT; i++) {
-		struct cnic_ulp_ops *ulp_ops;
-
-		mutex_lock(&cnic_lock);
-		ulp_ops = cnic_ulp_tbl_prot(i);
-		if (!ulp_ops || !ulp_ops->cnic_init) {
-			mutex_unlock(&cnic_lock);
-			continue;
-		}
-		ulp_get(ulp_ops);
-		mutex_unlock(&cnic_lock);
-
-		if (!test_and_set_bit(ULP_F_INIT, &cp->ulp_flags[i]))
-			ulp_ops->cnic_init(dev);
-
-		ulp_put(ulp_ops);
-	}
-}
-
-static void cnic_ulp_exit(struct cnic_dev *dev)
-{
-	int i;
-	struct cnic_local *cp = dev->cnic_priv;
-
-	for (i = 0; i < MAX_CNIC_ULP_TYPE_EXT; i++) {
-		struct cnic_ulp_ops *ulp_ops;
-
-		mutex_lock(&cnic_lock);
-		ulp_ops = cnic_ulp_tbl_prot(i);
-		if (!ulp_ops || !ulp_ops->cnic_exit) {
-			mutex_unlock(&cnic_lock);
-			continue;
-		}
-		ulp_get(ulp_ops);
-		mutex_unlock(&cnic_lock);
-
-		if (test_and_clear_bit(ULP_F_INIT, &cp->ulp_flags[i]))
-			ulp_ops->cnic_exit(dev);
-
-		ulp_put(ulp_ops);
-	}
-}
-
-static int cnic_cm_offload_pg(struct cnic_sock *csk)
-{
-	struct cnic_dev *dev = csk->dev;
-	struct l4_kwq_offload_pg *l4kwqe;
-	struct kwqe *wqes[1];
-
-	l4kwqe = (struct l4_kwq_offload_pg *) &csk->kwqe1;
-	memset(l4kwqe, 0, sizeof(*l4kwqe));
-	wqes[0] = (struct kwqe *) l4kwqe;
-
-	l4kwqe->op_code = L4_KWQE_OPCODE_VALUE_OFFLOAD_PG;
-	l4kwqe->flags =
-		L4_LAYER_CODE << L4_KWQ_OFFLOAD_PG_LAYER_CODE_SHIFT;
-	l4kwqe->l2hdr_nbytes = ETH_HLEN;
-
-	l4kwqe->da0 = csk->ha[0];
-	l4kwqe->da1 = csk->ha[1];
-	l4kwqe->da2 = csk->ha[2];
-	l4kwqe->da3 = csk->ha[3];
-	l4kwqe->da4 = csk->ha[4];
-	l4kwqe->da5 = csk->ha[5];
-
-	l4kwqe->sa0 = dev->mac_addr[0];
-	l4kwqe->sa1 = dev->mac_addr[1];
-	l4kwqe->sa2 = dev->mac_addr[2];
-	l4kwqe->sa3 = dev->mac_addr[3];
-	l4kwqe->sa4 = dev->mac_addr[4];
-	l4kwqe->sa5 = dev->mac_addr[5];
-
-	l4kwqe->etype = ETH_P_IP;
-	l4kwqe->ipid_start = DEF_IPID_START;
-	l4kwqe->host_opaque = csk->l5_cid;
-
-	if (csk->vlan_id) {
-		l4kwqe->pg_flags |= L4_KWQ_OFFLOAD_PG_VLAN_TAGGING;
-		l4kwqe->vlan_tag = csk->vlan_id;
-		l4kwqe->l2hdr_nbytes += 4;
-	}
-
-	return dev->submit_kwqes(dev, wqes, 1);
-}
-
-static int cnic_cm_update_pg(struct cnic_sock *csk)
-{
-	struct cnic_dev *dev = csk->dev;
-	struct l4_kwq_update_pg *l4kwqe;
-	struct kwqe *wqes[1];
-
-	l4kwqe = (struct l4_kwq_update_pg *) &csk->kwqe1;
-	memset(l4kwqe, 0, sizeof(*l4kwqe));
-	wqes[0] = (struct kwqe *) l4kwqe;
-
-	l4kwqe->opcode = L4_KWQE_OPCODE_VALUE_UPDATE_PG;
-	l4kwqe->flags =
-		L4_LAYER_CODE << L4_KWQ_UPDATE_PG_LAYER_CODE_SHIFT;
-	l4kwqe->pg_cid = csk->pg_cid;
-
-	l4kwqe->da0 = csk->ha[0];
-	l4kwqe->da1 = csk->ha[1];
-	l4kwqe->da2 = csk->ha[2];
-	l4kwqe->da3 = csk->ha[3];
-	l4kwqe->da4 = csk->ha[4];
-	l4kwqe->da5 = csk->ha[5];
-
-	l4kwqe->pg_host_opaque = csk->l5_cid;
-	l4kwqe->pg_valids = L4_KWQ_UPDATE_PG_VALIDS_DA;
-
-	return dev->submit_kwqes(dev, wqes, 1);
-}
-
-static int cnic_cm_upload_pg(struct cnic_sock *csk)
-{
-	struct cnic_dev *dev = csk->dev;
-	struct l4_kwq_upload *l4kwqe;
-	struct kwqe *wqes[1];
-
-	l4kwqe = (struct l4_kwq_upload *) &csk->kwqe1;
-	memset(l4kwqe, 0, sizeof(*l4kwqe));
-	wqes[0] = (struct kwqe *) l4kwqe;
-
-	l4kwqe->opcode = L4_KWQE_OPCODE_VALUE_UPLOAD_PG;
-	l4kwqe->flags =
-		L4_LAYER_CODE << L4_KWQ_UPLOAD_LAYER_CODE_SHIFT;
-	l4kwqe->cid = csk->pg_cid;
-
-	return dev->submit_kwqes(dev, wqes, 1);
-}
-
-static int cnic_cm_conn_req(struct cnic_sock *csk)
-{
-	struct cnic_dev *dev = csk->dev;
-	struct l4_kwq_connect_req1 *l4kwqe1;
-	struct l4_kwq_connect_req2 *l4kwqe2;
-	struct l4_kwq_connect_req3 *l4kwqe3;
-	struct kwqe *wqes[3];
-	u8 tcp_flags = 0;
-	int num_wqes = 2;
-
-	l4kwqe1 = (struct l4_kwq_connect_req1 *) &csk->kwqe1;
-	l4kwqe2 = (struct l4_kwq_connect_req2 *) &csk->kwqe2;
-	l4kwqe3 = (struct l4_kwq_connect_req3 *) &csk->kwqe3;
-	memset(l4kwqe1, 0, sizeof(*l4kwqe1));
-	memset(l4kwqe2, 0, sizeof(*l4kwqe2));
-	memset(l4kwqe3, 0, sizeof(*l4kwqe3));
-
-	l4kwqe3->op_code = L4_KWQE_OPCODE_VALUE_CONNECT3;
-	l4kwqe3->flags =
-		L4_LAYER_CODE << L4_KWQ_CONNECT_REQ3_LAYER_CODE_SHIFT;
-	l4kwqe3->ka_timeout = csk->ka_timeout;
-	l4kwqe3->ka_interval = csk->ka_interval;
-	l4kwqe3->ka_max_probe_count = csk->ka_max_probe_count;
-	l4kwqe3->tos = csk->tos;
-	l4kwqe3->ttl = csk->ttl;
-	l4kwqe3->snd_seq_scale = csk->snd_seq_scale;
-	l4kwqe3->pmtu = csk->mtu;
-	l4kwqe3->rcv_buf = csk->rcv_buf;
-	l4kwqe3->snd_buf = csk->snd_buf;
-	l4kwqe3->seed = csk->seed;
-
-	wqes[0] = (struct kwqe *) l4kwqe1;
-	if (test_bit(SK_F_IPV6, &csk->flags)) {
-		wqes[1] = (struct kwqe *) l4kwqe2;
-		wqes[2] = (struct kwqe *) l4kwqe3;
-		num_wqes = 3;
-
-		l4kwqe1->conn_flags = L4_KWQ_CONNECT_REQ1_IP_V6;
-		l4kwqe2->op_code = L4_KWQE_OPCODE_VALUE_CONNECT2;
-		l4kwqe2->flags =
-			L4_KWQ_CONNECT_REQ2_LINKED_WITH_NEXT |
-			L4_LAYER_CODE << L4_KWQ_CONNECT_REQ2_LAYER_CODE_SHIFT;
-		l4kwqe2->src_ip_v6_2 = be32_to_cpu(csk->src_ip[1]);
-		l4kwqe2->src_ip_v6_3 = be32_to_cpu(csk->src_ip[2]);
-		l4kwqe2->src_ip_v6_4 = be32_to_cpu(csk->src_ip[3]);
-		l4kwqe2->dst_ip_v6_2 = be32_to_cpu(csk->dst_ip[1]);
-		l4kwqe2->dst_ip_v6_3 = be32_to_cpu(csk->dst_ip[2]);
-		l4kwqe2->dst_ip_v6_4 = be32_to_cpu(csk->dst_ip[3]);
-		l4kwqe3->mss = l4kwqe3->pmtu - sizeof(struct ipv6hdr) -
-			       sizeof(struct tcphdr);
-	} else {
-		wqes[1] = (struct kwqe *) l4kwqe3;
-		l4kwqe3->mss = l4kwqe3->pmtu - sizeof(struct iphdr) -
-			       sizeof(struct tcphdr);
-	}
-
-	l4kwqe1->op_code = L4_KWQE_OPCODE_VALUE_CONNECT1;
-	l4kwqe1->flags =
-		(L4_LAYER_CODE << L4_KWQ_CONNECT_REQ1_LAYER_CODE_SHIFT) |
-		 L4_KWQ_CONNECT_REQ3_LINKED_WITH_NEXT;
-	l4kwqe1->cid = csk->cid;
-	l4kwqe1->pg_cid = csk->pg_cid;
-	l4kwqe1->src_ip = be32_to_cpu(csk->src_ip[0]);
-	l4kwqe1->dst_ip = be32_to_cpu(csk->dst_ip[0]);
-	l4kwqe1->src_port = be16_to_cpu(csk->src_port);
-	l4kwqe1->dst_port = be16_to_cpu(csk->dst_port);
-	if (csk->tcp_flags & SK_TCP_NO_DELAY_ACK)
-		tcp_flags |= L4_KWQ_CONNECT_REQ1_NO_DELAY_ACK;
-	if (csk->tcp_flags & SK_TCP_KEEP_ALIVE)
-		tcp_flags |= L4_KWQ_CONNECT_REQ1_KEEP_ALIVE;
-	if (csk->tcp_flags & SK_TCP_NAGLE)
-		tcp_flags |= L4_KWQ_CONNECT_REQ1_NAGLE_ENABLE;
-	if (csk->tcp_flags & SK_TCP_TIMESTAMP)
-		tcp_flags |= L4_KWQ_CONNECT_REQ1_TIME_STAMP;
-	if (csk->tcp_flags & SK_TCP_SACK)
-		tcp_flags |= L4_KWQ_CONNECT_REQ1_SACK;
-	if (csk->tcp_flags & SK_TCP_SEG_SCALING)
-		tcp_flags |= L4_KWQ_CONNECT_REQ1_SEG_SCALING;
-
-	l4kwqe1->tcp_flags = tcp_flags;
-
-	return dev->submit_kwqes(dev, wqes, num_wqes);
-}
-
-static int cnic_cm_close_req(struct cnic_sock *csk)
-{
-	struct cnic_dev *dev = csk->dev;
-	struct l4_kwq_close_req *l4kwqe;
-	struct kwqe *wqes[1];
-
-	l4kwqe = (struct l4_kwq_close_req *) &csk->kwqe2;
-	memset(l4kwqe, 0, sizeof(*l4kwqe));
-	wqes[0] = (struct kwqe *) l4kwqe;
-
-	l4kwqe->op_code = L4_KWQE_OPCODE_VALUE_CLOSE;
-	l4kwqe->flags = L4_LAYER_CODE << L4_KWQ_CLOSE_REQ_LAYER_CODE_SHIFT;
-	l4kwqe->cid = csk->cid;
-
-	return dev->submit_kwqes(dev, wqes, 1);
-}
-
-static int cnic_cm_abort_req(struct cnic_sock *csk)
-{
-	struct cnic_dev *dev = csk->dev;
-	struct l4_kwq_reset_req *l4kwqe;
-	struct kwqe *wqes[1];
-
-	l4kwqe = (struct l4_kwq_reset_req *) &csk->kwqe2;
-	memset(l4kwqe, 0, sizeof(*l4kwqe));
-	wqes[0] = (struct kwqe *) l4kwqe;
-
-	l4kwqe->op_code = L4_KWQE_OPCODE_VALUE_RESET;
-	l4kwqe->flags = L4_LAYER_CODE << L4_KWQ_RESET_REQ_LAYER_CODE_SHIFT;
-	l4kwqe->cid = csk->cid;
-
-	return dev->submit_kwqes(dev, wqes, 1);
-}
-
-static int cnic_cm_create(struct cnic_dev *dev, int ulp_type, u32 cid,
-			  u32 l5_cid, struct cnic_sock **csk, void *context)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_sock *csk1;
-
-	if (l5_cid >= MAX_CM_SK_TBL_SZ)
-		return -EINVAL;
-
-	if (cp->ctx_tbl) {
-		struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
-
-		if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
-			return -EAGAIN;
-	}
-
-	csk1 = &cp->csk_tbl[l5_cid];
-	if (atomic_read(&csk1->ref_count))
-		return -EAGAIN;
-
-	if (test_and_set_bit(SK_F_INUSE, &csk1->flags))
-		return -EBUSY;
-
-	csk1->dev = dev;
-	csk1->cid = cid;
-	csk1->l5_cid = l5_cid;
-	csk1->ulp_type = ulp_type;
-	csk1->context = context;
-
-	csk1->ka_timeout = DEF_KA_TIMEOUT;
-	csk1->ka_interval = DEF_KA_INTERVAL;
-	csk1->ka_max_probe_count = DEF_KA_MAX_PROBE_COUNT;
-	csk1->tos = DEF_TOS;
-	csk1->ttl = DEF_TTL;
-	csk1->snd_seq_scale = DEF_SND_SEQ_SCALE;
-	csk1->rcv_buf = DEF_RCV_BUF;
-	csk1->snd_buf = DEF_SND_BUF;
-	csk1->seed = DEF_SEED;
-
-	*csk = csk1;
-	return 0;
-}
-
-static void cnic_cm_cleanup(struct cnic_sock *csk)
-{
-	if (csk->src_port) {
-		struct cnic_dev *dev = csk->dev;
-		struct cnic_local *cp = dev->cnic_priv;
-
-		cnic_free_id(&cp->csk_port_tbl, be16_to_cpu(csk->src_port));
-		csk->src_port = 0;
-	}
-}
-
-static void cnic_close_conn(struct cnic_sock *csk)
-{
-	if (test_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags)) {
-		cnic_cm_upload_pg(csk);
-		clear_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags);
-	}
-	cnic_cm_cleanup(csk);
-}
-
-static int cnic_cm_destroy(struct cnic_sock *csk)
-{
-	if (!cnic_in_use(csk))
-		return -EINVAL;
-
-	csk_hold(csk);
-	clear_bit(SK_F_INUSE, &csk->flags);
-	smp_mb__after_clear_bit();
-	while (atomic_read(&csk->ref_count) != 1)
-		msleep(1);
-	cnic_cm_cleanup(csk);
-
-	csk->flags = 0;
-	csk_put(csk);
-	return 0;
-}
-
-static inline u16 cnic_get_vlan(struct net_device *dev,
-				struct net_device **vlan_dev)
-{
-	if (dev->priv_flags & IFF_802_1Q_VLAN) {
-		*vlan_dev = vlan_dev_real_dev(dev);
-		return vlan_dev_vlan_id(dev);
-	}
-	*vlan_dev = dev;
-	return 0;
-}
-
-static int cnic_get_v4_route(struct sockaddr_in *dst_addr,
-			     struct dst_entry **dst)
-{
-#if defined(CONFIG_INET)
-	struct rtable *rt;
-
-	rt = ip_route_output(&init_net, dst_addr->sin_addr.s_addr, 0, 0, 0);
-	if (!IS_ERR(rt)) {
-		*dst = &rt->dst;
-		return 0;
-	}
-	return PTR_ERR(rt);
-#else
-	return -ENETUNREACH;
-#endif
-}
-
-static int cnic_get_v6_route(struct sockaddr_in6 *dst_addr,
-			     struct dst_entry **dst)
-{
-#if defined(CONFIG_IPV6) || (defined(CONFIG_IPV6_MODULE) && defined(MODULE))
-	struct flowi6 fl6;
-
-	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, &fl6);
-	if (*dst)
-		return 0;
-#endif
-
-	return -ENETUNREACH;
-}
-
-static struct cnic_dev *cnic_cm_select_dev(struct sockaddr_in *dst_addr,
-					   int ulp_type)
-{
-	struct cnic_dev *dev = NULL;
-	struct dst_entry *dst;
-	struct net_device *netdev = NULL;
-	int err = -ENETUNREACH;
-
-	if (dst_addr->sin_family == AF_INET)
-		err = cnic_get_v4_route(dst_addr, &dst);
-	else if (dst_addr->sin_family == AF_INET6) {
-		struct sockaddr_in6 *dst_addr6 =
-			(struct sockaddr_in6 *) dst_addr;
-
-		err = cnic_get_v6_route(dst_addr6, &dst);
-	} else
-		return NULL;
-
-	if (err)
-		return NULL;
-
-	if (!dst->dev)
-		goto done;
-
-	cnic_get_vlan(dst->dev, &netdev);
-
-	dev = cnic_from_netdev(netdev);
-
-done:
-	dst_release(dst);
-	if (dev)
-		cnic_put(dev);
-	return dev;
-}
-
-static int cnic_resolve_addr(struct cnic_sock *csk, struct cnic_sockaddr *saddr)
-{
-	struct cnic_dev *dev = csk->dev;
-	struct cnic_local *cp = dev->cnic_priv;
-
-	return cnic_send_nlmsg(cp, ISCSI_KEVENT_PATH_REQ, csk);
-}
-
-static int cnic_get_route(struct cnic_sock *csk, struct cnic_sockaddr *saddr)
-{
-	struct cnic_dev *dev = csk->dev;
-	struct cnic_local *cp = dev->cnic_priv;
-	int is_v6, rc = 0;
-	struct dst_entry *dst = NULL;
-	struct net_device *realdev;
-	__be16 local_port;
-	u32 port_id;
-
-	if (saddr->local.v6.sin6_family == AF_INET6 &&
-	    saddr->remote.v6.sin6_family == AF_INET6)
-		is_v6 = 1;
-	else if (saddr->local.v4.sin_family == AF_INET &&
-		 saddr->remote.v4.sin_family == AF_INET)
-		is_v6 = 0;
-	else
-		return -EINVAL;
-
-	clear_bit(SK_F_IPV6, &csk->flags);
-
-	if (is_v6) {
-		set_bit(SK_F_IPV6, &csk->flags);
-		cnic_get_v6_route(&saddr->remote.v6, &dst);
-
-		memcpy(&csk->dst_ip[0], &saddr->remote.v6.sin6_addr,
-		       sizeof(struct in6_addr));
-		csk->dst_port = saddr->remote.v6.sin6_port;
-		local_port = saddr->local.v6.sin6_port;
-
-	} else {
-		cnic_get_v4_route(&saddr->remote.v4, &dst);
-
-		csk->dst_ip[0] = saddr->remote.v4.sin_addr.s_addr;
-		csk->dst_port = saddr->remote.v4.sin_port;
-		local_port = saddr->local.v4.sin_port;
-	}
-
-	csk->vlan_id = 0;
-	csk->mtu = dev->netdev->mtu;
-	if (dst && dst->dev) {
-		u16 vlan = cnic_get_vlan(dst->dev, &realdev);
-		if (realdev == dev->netdev) {
-			csk->vlan_id = vlan;
-			csk->mtu = dst_mtu(dst);
-		}
-	}
-
-	port_id = be16_to_cpu(local_port);
-	if (port_id >= CNIC_LOCAL_PORT_MIN &&
-	    port_id < CNIC_LOCAL_PORT_MAX) {
-		if (cnic_alloc_id(&cp->csk_port_tbl, port_id))
-			port_id = 0;
-	} else
-		port_id = 0;
-
-	if (!port_id) {
-		port_id = cnic_alloc_new_id(&cp->csk_port_tbl);
-		if (port_id == -1) {
-			rc = -ENOMEM;
-			goto err_out;
-		}
-		local_port = cpu_to_be16(port_id);
-	}
-	csk->src_port = local_port;
-
-err_out:
-	dst_release(dst);
-	return rc;
-}
-
-static void cnic_init_csk_state(struct cnic_sock *csk)
-{
-	csk->state = 0;
-	clear_bit(SK_F_OFFLD_SCHED, &csk->flags);
-	clear_bit(SK_F_CLOSING, &csk->flags);
-}
-
-static int cnic_cm_connect(struct cnic_sock *csk, struct cnic_sockaddr *saddr)
-{
-	struct cnic_local *cp = csk->dev->cnic_priv;
-	int err = 0;
-
-	if (cp->ethdev->drv_state & CNIC_DRV_STATE_NO_ISCSI)
-		return -EOPNOTSUPP;
-
-	if (!cnic_in_use(csk))
-		return -EINVAL;
-
-	if (test_and_set_bit(SK_F_CONNECT_START, &csk->flags))
-		return -EINVAL;
-
-	cnic_init_csk_state(csk);
-
-	err = cnic_get_route(csk, saddr);
-	if (err)
-		goto err_out;
-
-	err = cnic_resolve_addr(csk, saddr);
-	if (!err)
-		return 0;
-
-err_out:
-	clear_bit(SK_F_CONNECT_START, &csk->flags);
-	return err;
-}
-
-static int cnic_cm_abort(struct cnic_sock *csk)
-{
-	struct cnic_local *cp = csk->dev->cnic_priv;
-	u32 opcode = L4_KCQE_OPCODE_VALUE_RESET_COMP;
-
-	if (!cnic_in_use(csk))
-		return -EINVAL;
-
-	if (cnic_abort_prep(csk))
-		return cnic_cm_abort_req(csk);
-
-	/* Getting here means that we haven't started connect, or
-	 * connect was not successful.
-	 */
-
-	cp->close_conn(csk, opcode);
-	if (csk->state != opcode)
-		return -EALREADY;
-
-	return 0;
-}
-
-static int cnic_cm_close(struct cnic_sock *csk)
-{
-	if (!cnic_in_use(csk))
-		return -EINVAL;
-
-	if (cnic_close_prep(csk)) {
-		csk->state = L4_KCQE_OPCODE_VALUE_CLOSE_COMP;
-		return cnic_cm_close_req(csk);
-	} else {
-		return -EALREADY;
-	}
-	return 0;
-}
-
-static void cnic_cm_upcall(struct cnic_local *cp, struct cnic_sock *csk,
-			   u8 opcode)
-{
-	struct cnic_ulp_ops *ulp_ops;
-	int ulp_type = csk->ulp_type;
-
-	rcu_read_lock();
-	ulp_ops = rcu_dereference(cp->ulp_ops[ulp_type]);
-	if (ulp_ops) {
-		if (opcode == L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE)
-			ulp_ops->cm_connect_complete(csk);
-		else if (opcode == L4_KCQE_OPCODE_VALUE_CLOSE_COMP)
-			ulp_ops->cm_close_complete(csk);
-		else if (opcode == L4_KCQE_OPCODE_VALUE_RESET_RECEIVED)
-			ulp_ops->cm_remote_abort(csk);
-		else if (opcode == L4_KCQE_OPCODE_VALUE_RESET_COMP)
-			ulp_ops->cm_abort_complete(csk);
-		else if (opcode == L4_KCQE_OPCODE_VALUE_CLOSE_RECEIVED)
-			ulp_ops->cm_remote_close(csk);
-	}
-	rcu_read_unlock();
-}
-
-static int cnic_cm_set_pg(struct cnic_sock *csk)
-{
-	if (cnic_offld_prep(csk)) {
-		if (test_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags))
-			cnic_cm_update_pg(csk);
-		else
-			cnic_cm_offload_pg(csk);
-	}
-	return 0;
-}
-
-static void cnic_cm_process_offld_pg(struct cnic_dev *dev, struct l4_kcq *kcqe)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 l5_cid = kcqe->pg_host_opaque;
-	u8 opcode = kcqe->op_code;
-	struct cnic_sock *csk = &cp->csk_tbl[l5_cid];
-
-	csk_hold(csk);
-	if (!cnic_in_use(csk))
-		goto done;
-
-	if (opcode == L4_KCQE_OPCODE_VALUE_UPDATE_PG) {
-		clear_bit(SK_F_OFFLD_SCHED, &csk->flags);
-		goto done;
-	}
-	/* Possible PG kcqe status:  SUCCESS, OFFLOADED_PG, or CTX_ALLOC_FAIL */
-	if (kcqe->status == L4_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAIL) {
-		clear_bit(SK_F_OFFLD_SCHED, &csk->flags);
-		cnic_cm_upcall(cp, csk,
-			       L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE);
-		goto done;
-	}
-
-	csk->pg_cid = kcqe->pg_cid;
-	set_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags);
-	cnic_cm_conn_req(csk);
-
-done:
-	csk_put(csk);
-}
-
-static void cnic_process_fcoe_term_conn(struct cnic_dev *dev, struct kcqe *kcqe)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct fcoe_kcqe *fc_kcqe = (struct fcoe_kcqe *) kcqe;
-	u32 l5_cid = fc_kcqe->fcoe_conn_id + BNX2X_FCOE_L5_CID_BASE;
-	struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
-
-	ctx->timestamp = jiffies;
-	ctx->wait_cond = 1;
-	wake_up(&ctx->waitq);
-}
-
-static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct l4_kcq *l4kcqe = (struct l4_kcq *) kcqe;
-	u8 opcode = l4kcqe->op_code;
-	u32 l5_cid;
-	struct cnic_sock *csk;
-
-	if (opcode == FCOE_RAMROD_CMD_ID_TERMINATE_CONN) {
-		cnic_process_fcoe_term_conn(dev, kcqe);
-		return;
-	}
-	if (opcode == L4_KCQE_OPCODE_VALUE_OFFLOAD_PG ||
-	    opcode == L4_KCQE_OPCODE_VALUE_UPDATE_PG) {
-		cnic_cm_process_offld_pg(dev, l4kcqe);
-		return;
-	}
-
-	l5_cid = l4kcqe->conn_id;
-	if (opcode & 0x80)
-		l5_cid = l4kcqe->cid;
-	if (l5_cid >= MAX_CM_SK_TBL_SZ)
-		return;
-
-	csk = &cp->csk_tbl[l5_cid];
-	csk_hold(csk);
-
-	if (!cnic_in_use(csk)) {
-		csk_put(csk);
-		return;
-	}
-
-	switch (opcode) {
-	case L5CM_RAMROD_CMD_ID_TCP_CONNECT:
-		if (l4kcqe->status != 0) {
-			clear_bit(SK_F_OFFLD_SCHED, &csk->flags);
-			cnic_cm_upcall(cp, csk,
-				       L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE);
-		}
-		break;
-	case L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE:
-		if (l4kcqe->status == 0)
-			set_bit(SK_F_OFFLD_COMPLETE, &csk->flags);
-
-		smp_mb__before_clear_bit();
-		clear_bit(SK_F_OFFLD_SCHED, &csk->flags);
-		cnic_cm_upcall(cp, csk, opcode);
-		break;
-
-	case L4_KCQE_OPCODE_VALUE_RESET_RECEIVED:
-	case L4_KCQE_OPCODE_VALUE_CLOSE_COMP:
-	case L4_KCQE_OPCODE_VALUE_RESET_COMP:
-	case L5CM_RAMROD_CMD_ID_SEARCHER_DELETE:
-	case L5CM_RAMROD_CMD_ID_TERMINATE_OFFLOAD:
-		cp->close_conn(csk, opcode);
-		break;
-
-	case L4_KCQE_OPCODE_VALUE_CLOSE_RECEIVED:
-		/* after we already sent CLOSE_REQ */
-		if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags) &&
-		    !test_bit(SK_F_OFFLD_COMPLETE, &csk->flags) &&
-		    csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP)
-			cp->close_conn(csk, L4_KCQE_OPCODE_VALUE_RESET_COMP);
-		else
-			cnic_cm_upcall(cp, csk, opcode);
-		break;
-	}
-	csk_put(csk);
-}
-
-static void cnic_cm_indicate_kcqe(void *data, struct kcqe *kcqe[], u32 num)
-{
-	struct cnic_dev *dev = data;
-	int i;
-
-	for (i = 0; i < num; i++)
-		cnic_cm_process_kcqe(dev, kcqe[i]);
-}
-
-static struct cnic_ulp_ops cm_ulp_ops = {
-	.indicate_kcqes		= cnic_cm_indicate_kcqe,
-};
-
-static void cnic_cm_free_mem(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-
-	kfree(cp->csk_tbl);
-	cp->csk_tbl = NULL;
-	cnic_free_id_tbl(&cp->csk_port_tbl);
-}
-
-static int cnic_cm_alloc_mem(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 port_id;
-
-	cp->csk_tbl = kzalloc(sizeof(struct cnic_sock) * MAX_CM_SK_TBL_SZ,
-			      GFP_KERNEL);
-	if (!cp->csk_tbl)
-		return -ENOMEM;
-
-	port_id = random32();
-	port_id %= CNIC_LOCAL_PORT_RANGE;
-	if (cnic_init_id_tbl(&cp->csk_port_tbl, CNIC_LOCAL_PORT_RANGE,
-			     CNIC_LOCAL_PORT_MIN, port_id)) {
-		cnic_cm_free_mem(dev);
-		return -ENOMEM;
-	}
-	return 0;
-}
-
-static int cnic_ready_to_close(struct cnic_sock *csk, u32 opcode)
-{
-	if (test_and_clear_bit(SK_F_OFFLD_COMPLETE, &csk->flags)) {
-		/* Unsolicited RESET_COMP or RESET_RECEIVED */
-		opcode = L4_KCQE_OPCODE_VALUE_RESET_RECEIVED;
-		csk->state = opcode;
-	}
-
-	/* 1. If event opcode matches the expected event in csk->state
-	 * 2. If the expected event is CLOSE_COMP or RESET_COMP, we accept any
-	 *    event
-	 * 3. If the expected event is 0, meaning the connection was never
-	 *    never established, we accept the opcode from cm_abort.
-	 */
-	if (opcode == csk->state || csk->state == 0 ||
-	    csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP ||
-	    csk->state == L4_KCQE_OPCODE_VALUE_RESET_COMP) {
-		if (!test_and_set_bit(SK_F_CLOSING, &csk->flags)) {
-			if (csk->state == 0)
-				csk->state = opcode;
-			return 1;
-		}
-	}
-	return 0;
-}
-
-static void cnic_close_bnx2_conn(struct cnic_sock *csk, u32 opcode)
-{
-	struct cnic_dev *dev = csk->dev;
-	struct cnic_local *cp = dev->cnic_priv;
-
-	if (opcode == L4_KCQE_OPCODE_VALUE_RESET_RECEIVED) {
-		cnic_cm_upcall(cp, csk, opcode);
-		return;
-	}
-
-	clear_bit(SK_F_CONNECT_START, &csk->flags);
-	cnic_close_conn(csk);
-	csk->state = opcode;
-	cnic_cm_upcall(cp, csk, opcode);
-}
-
-static void cnic_cm_stop_bnx2_hw(struct cnic_dev *dev)
-{
-}
-
-static int cnic_cm_init_bnx2_hw(struct cnic_dev *dev)
-{
-	u32 seed;
-
-	seed = random32();
-	cnic_ctx_wr(dev, 45, 0, seed);
-	return 0;
-}
-
-static void cnic_close_bnx2x_conn(struct cnic_sock *csk, u32 opcode)
-{
-	struct cnic_dev *dev = csk->dev;
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_context *ctx = &cp->ctx_tbl[csk->l5_cid];
-	union l5cm_specific_data l5_data;
-	u32 cmd = 0;
-	int close_complete = 0;
-
-	switch (opcode) {
-	case L4_KCQE_OPCODE_VALUE_RESET_RECEIVED:
-	case L4_KCQE_OPCODE_VALUE_CLOSE_COMP:
-	case L4_KCQE_OPCODE_VALUE_RESET_COMP:
-		if (cnic_ready_to_close(csk, opcode)) {
-			if (test_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags))
-				cmd = L5CM_RAMROD_CMD_ID_SEARCHER_DELETE;
-			else
-				close_complete = 1;
-		}
-		break;
-	case L5CM_RAMROD_CMD_ID_SEARCHER_DELETE:
-		cmd = L5CM_RAMROD_CMD_ID_TERMINATE_OFFLOAD;
-		break;
-	case L5CM_RAMROD_CMD_ID_TERMINATE_OFFLOAD:
-		close_complete = 1;
-		break;
-	}
-	if (cmd) {
-		memset(&l5_data, 0, sizeof(l5_data));
-
-		cnic_submit_kwqe_16(dev, cmd, csk->cid, ISCSI_CONNECTION_TYPE,
-				    &l5_data);
-	} else if (close_complete) {
-		ctx->timestamp = jiffies;
-		cnic_close_conn(csk);
-		cnic_cm_upcall(cp, csk, csk->state);
-	}
-}
-
-static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-
-	if (!cp->ctx_tbl)
-		return;
-
-	if (!netif_running(dev->netdev))
-		return;
-
-	cnic_bnx2x_delete_wait(dev, 0);
-
-	cancel_delayed_work(&cp->delete_task);
-	flush_workqueue(cnic_wq);
-
-	if (atomic_read(&cp->iscsi_conn) != 0)
-		netdev_warn(dev->netdev, "%d iSCSI connections not destroyed\n",
-			    atomic_read(&cp->iscsi_conn));
-}
-
-static int cnic_cm_init_bnx2x_hw(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 pfid = cp->pfid;
-	u32 port = CNIC_PORT(cp);
-
-	cnic_init_bnx2x_mac(dev);
-	cnic_bnx2x_set_tcp_timestamp(dev, 1);
-
-	CNIC_WR16(dev, BAR_XSTRORM_INTMEM +
-		  XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfid), 0);
-
-	CNIC_WR(dev, BAR_XSTRORM_INTMEM +
-		XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_OFFSET(port), 1);
-	CNIC_WR(dev, BAR_XSTRORM_INTMEM +
-		XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_OFFSET(port),
-		DEF_MAX_DA_COUNT);
-
-	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(pfid), DEF_TTL);
-	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(pfid), DEF_TOS);
-	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(pfid), 2);
-	CNIC_WR(dev, BAR_XSTRORM_INTMEM +
-		XSTORM_TCP_TX_SWS_TIMER_VAL_OFFSET(pfid), DEF_SWS_TIMER);
-
-	CNIC_WR(dev, BAR_TSTRORM_INTMEM + TSTORM_TCP_MAX_CWND_OFFSET(pfid),
-		DEF_MAX_CWND);
-	return 0;
-}
-
-static void cnic_delete_task(struct work_struct *work)
-{
-	struct cnic_local *cp;
-	struct cnic_dev *dev;
-	u32 i;
-	int need_resched = 0;
-
-	cp = container_of(work, struct cnic_local, delete_task.work);
-	dev = cp->dev;
-
-	if (test_and_clear_bit(CNIC_LCL_FL_STOP_ISCSI, &cp->cnic_local_flags)) {
-		struct drv_ctl_info info;
-
-		cnic_ulp_stop_one(cp, CNIC_ULP_ISCSI);
-
-		info.cmd = DRV_CTL_ISCSI_STOPPED_CMD;
-		cp->ethdev->drv_ctl(dev->netdev, &info);
-	}
-
-	for (i = 0; i < cp->max_cid_space; i++) {
-		struct cnic_context *ctx = &cp->ctx_tbl[i];
-		int err;
-
-		if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags) ||
-		    !test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
-			continue;
-
-		if (!time_after(jiffies, ctx->timestamp + (2 * HZ))) {
-			need_resched = 1;
-			continue;
-		}
-
-		if (!test_and_clear_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
-			continue;
-
-		err = cnic_bnx2x_destroy_ramrod(dev, i);
-
-		cnic_free_bnx2x_conn_resc(dev, i);
-		if (!err) {
-			if (ctx->ulp_proto_id == CNIC_ULP_ISCSI)
-				atomic_dec(&cp->iscsi_conn);
-
-			clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
-		}
-	}
-
-	if (need_resched)
-		queue_delayed_work(cnic_wq, &cp->delete_task,
-				   msecs_to_jiffies(10));
-
-}
-
-static int cnic_cm_open(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	int err;
-
-	err = cnic_cm_alloc_mem(dev);
-	if (err)
-		return err;
-
-	err = cp->start_cm(dev);
-
-	if (err)
-		goto err_out;
-
-	INIT_DELAYED_WORK(&cp->delete_task, cnic_delete_task);
-
-	dev->cm_create = cnic_cm_create;
-	dev->cm_destroy = cnic_cm_destroy;
-	dev->cm_connect = cnic_cm_connect;
-	dev->cm_abort = cnic_cm_abort;
-	dev->cm_close = cnic_cm_close;
-	dev->cm_select_dev = cnic_cm_select_dev;
-
-	cp->ulp_handle[CNIC_ULP_L4] = dev;
-	rcu_assign_pointer(cp->ulp_ops[CNIC_ULP_L4], &cm_ulp_ops);
-	return 0;
-
-err_out:
-	cnic_cm_free_mem(dev);
-	return err;
-}
-
-static int cnic_cm_shutdown(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	int i;
-
-	cp->stop_cm(dev);
-
-	if (!cp->csk_tbl)
-		return 0;
-
-	for (i = 0; i < MAX_CM_SK_TBL_SZ; i++) {
-		struct cnic_sock *csk = &cp->csk_tbl[i];
-
-		clear_bit(SK_F_INUSE, &csk->flags);
-		cnic_cm_cleanup(csk);
-	}
-	cnic_cm_free_mem(dev);
-
-	return 0;
-}
-
-static void cnic_init_context(struct cnic_dev *dev, u32 cid)
-{
-	u32 cid_addr;
-	int i;
-
-	cid_addr = GET_CID_ADDR(cid);
-
-	for (i = 0; i < CTX_SIZE; i += 4)
-		cnic_ctx_wr(dev, cid_addr, i, 0);
-}
-
-static int cnic_setup_5709_context(struct cnic_dev *dev, int valid)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	int ret = 0, i;
-	u32 valid_bit = valid ? BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID : 0;
-
-	if (CHIP_NUM(cp) != CHIP_NUM_5709)
-		return 0;
-
-	for (i = 0; i < cp->ctx_blks; i++) {
-		int j;
-		u32 idx = cp->ctx_arr[i].cid / cp->cids_per_blk;
-		u32 val;
-
-		memset(cp->ctx_arr[i].ctx, 0, BCM_PAGE_SIZE);
-
-		CNIC_WR(dev, BNX2_CTX_HOST_PAGE_TBL_DATA0,
-			(cp->ctx_arr[i].mapping & 0xffffffff) | valid_bit);
-		CNIC_WR(dev, BNX2_CTX_HOST_PAGE_TBL_DATA1,
-			(u64) cp->ctx_arr[i].mapping >> 32);
-		CNIC_WR(dev, BNX2_CTX_HOST_PAGE_TBL_CTRL, idx |
-			BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ);
-		for (j = 0; j < 10; j++) {
-
-			val = CNIC_RD(dev, BNX2_CTX_HOST_PAGE_TBL_CTRL);
-			if (!(val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ))
-				break;
-			udelay(5);
-		}
-		if (val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ) {
-			ret = -EBUSY;
-			break;
-		}
-	}
-	return ret;
-}
-
-static void cnic_free_irq(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-
-	if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
-		cp->disable_int_sync(dev);
-		tasklet_kill(&cp->cnic_irq_task);
-		free_irq(ethdev->irq_arr[0].vector, dev);
-	}
-}
-
-static int cnic_request_irq(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	int err;
-
-	err = request_irq(ethdev->irq_arr[0].vector, cnic_irq, 0, "cnic", dev);
-	if (err)
-		tasklet_disable(&cp->cnic_irq_task);
-
-	return err;
-}
-
-static int cnic_init_bnx2_irq(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-
-	if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
-		int err, i = 0;
-		int sblk_num = cp->status_blk_num;
-		u32 base = ((sblk_num - 1) * BNX2_HC_SB_CONFIG_SIZE) +
-			   BNX2_HC_SB_CONFIG_1;
-
-		CNIC_WR(dev, base, BNX2_HC_SB_CONFIG_1_ONE_SHOT);
-
-		CNIC_WR(dev, base + BNX2_HC_COMP_PROD_TRIP_OFF, (2 << 16) | 8);
-		CNIC_WR(dev, base + BNX2_HC_COM_TICKS_OFF, (64 << 16) | 220);
-		CNIC_WR(dev, base + BNX2_HC_CMD_TICKS_OFF, (64 << 16) | 220);
-
-		cp->last_status_idx = cp->status_blk.bnx2->status_idx;
-		tasklet_init(&cp->cnic_irq_task, cnic_service_bnx2_msix,
-			     (unsigned long) dev);
-		err = cnic_request_irq(dev);
-		if (err)
-			return err;
-
-		while (cp->status_blk.bnx2->status_completion_producer_index &&
-		       i < 10) {
-			CNIC_WR(dev, BNX2_HC_COALESCE_NOW,
-				1 << (11 + sblk_num));
-			udelay(10);
-			i++;
-			barrier();
-		}
-		if (cp->status_blk.bnx2->status_completion_producer_index) {
-			cnic_free_irq(dev);
-			goto failed;
-		}
-
-	} else {
-		struct status_block *sblk = cp->status_blk.gen;
-		u32 hc_cmd = CNIC_RD(dev, BNX2_HC_COMMAND);
-		int i = 0;
-
-		while (sblk->status_completion_producer_index && i < 10) {
-			CNIC_WR(dev, BNX2_HC_COMMAND,
-				hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
-			udelay(10);
-			i++;
-			barrier();
-		}
-		if (sblk->status_completion_producer_index)
-			goto failed;
-
-	}
-	return 0;
-
-failed:
-	netdev_err(dev->netdev, "KCQ index not resetting to 0\n");
-	return -EBUSY;
-}
-
-static void cnic_enable_bnx2_int(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-
-	if (!(ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX))
-		return;
-
-	CNIC_WR(dev, BNX2_PCICFG_INT_ACK_CMD, cp->int_num |
-		BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | cp->last_status_idx);
-}
-
-static void cnic_disable_bnx2_int_sync(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-
-	if (!(ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX))
-		return;
-
-	CNIC_WR(dev, BNX2_PCICFG_INT_ACK_CMD, cp->int_num |
-		BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
-	CNIC_RD(dev, BNX2_PCICFG_INT_ACK_CMD);
-	synchronize_irq(ethdev->irq_arr[0].vector);
-}
-
-static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	struct cnic_uio_dev *udev = cp->udev;
-	u32 cid_addr, tx_cid, sb_id;
-	u32 val, offset0, offset1, offset2, offset3;
-	int i;
-	struct tx_bd *txbd;
-	dma_addr_t buf_map, ring_map = udev->l2_ring_map;
-	struct status_block *s_blk = cp->status_blk.gen;
-
-	sb_id = cp->status_blk_num;
-	tx_cid = 20;
-	cp->tx_cons_ptr = &s_blk->status_tx_quick_consumer_index2;
-	if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
-		struct status_block_msix *sblk = cp->status_blk.bnx2;
-
-		tx_cid = TX_TSS_CID + sb_id - 1;
-		CNIC_WR(dev, BNX2_TSCH_TSS_CFG, (sb_id << 24) |
-			(TX_TSS_CID << 7));
-		cp->tx_cons_ptr = &sblk->status_tx_quick_consumer_index;
-	}
-	cp->tx_cons = *cp->tx_cons_ptr;
-
-	cid_addr = GET_CID_ADDR(tx_cid);
-	if (CHIP_NUM(cp) == CHIP_NUM_5709) {
-		u32 cid_addr2 = GET_CID_ADDR(tx_cid + 4) + 0x40;
-
-		for (i = 0; i < PHY_CTX_SIZE; i += 4)
-			cnic_ctx_wr(dev, cid_addr2, i, 0);
-
-		offset0 = BNX2_L2CTX_TYPE_XI;
-		offset1 = BNX2_L2CTX_CMD_TYPE_XI;
-		offset2 = BNX2_L2CTX_TBDR_BHADDR_HI_XI;
-		offset3 = BNX2_L2CTX_TBDR_BHADDR_LO_XI;
-	} else {
-		cnic_init_context(dev, tx_cid);
-		cnic_init_context(dev, tx_cid + 1);
-
-		offset0 = BNX2_L2CTX_TYPE;
-		offset1 = BNX2_L2CTX_CMD_TYPE;
-		offset2 = BNX2_L2CTX_TBDR_BHADDR_HI;
-		offset3 = BNX2_L2CTX_TBDR_BHADDR_LO;
-	}
-	val = BNX2_L2CTX_TYPE_TYPE_L2 | BNX2_L2CTX_TYPE_SIZE_L2;
-	cnic_ctx_wr(dev, cid_addr, offset0, val);
-
-	val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16);
-	cnic_ctx_wr(dev, cid_addr, offset1, val);
-
-	txbd = udev->l2_ring;
-
-	buf_map = udev->l2_buf_map;
-	for (i = 0; i < MAX_TX_DESC_CNT; i++, txbd++) {
-		txbd->tx_bd_haddr_hi = (u64) buf_map >> 32;
-		txbd->tx_bd_haddr_lo = (u64) buf_map & 0xffffffff;
-	}
-	val = (u64) ring_map >> 32;
-	cnic_ctx_wr(dev, cid_addr, offset2, val);
-	txbd->tx_bd_haddr_hi = val;
-
-	val = (u64) ring_map & 0xffffffff;
-	cnic_ctx_wr(dev, cid_addr, offset3, val);
-	txbd->tx_bd_haddr_lo = val;
-}
-
-static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	struct cnic_uio_dev *udev = cp->udev;
-	u32 cid_addr, sb_id, val, coal_reg, coal_val;
-	int i;
-	struct rx_bd *rxbd;
-	struct status_block *s_blk = cp->status_blk.gen;
-	dma_addr_t ring_map = udev->l2_ring_map;
-
-	sb_id = cp->status_blk_num;
-	cnic_init_context(dev, 2);
-	cp->rx_cons_ptr = &s_blk->status_rx_quick_consumer_index2;
-	coal_reg = BNX2_HC_COMMAND;
-	coal_val = CNIC_RD(dev, coal_reg);
-	if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
-		struct status_block_msix *sblk = cp->status_blk.bnx2;
-
-		cp->rx_cons_ptr = &sblk->status_rx_quick_consumer_index;
-		coal_reg = BNX2_HC_COALESCE_NOW;
-		coal_val = 1 << (11 + sb_id);
-	}
-	i = 0;
-	while (!(*cp->rx_cons_ptr != 0) && i < 10) {
-		CNIC_WR(dev, coal_reg, coal_val);
-		udelay(10);
-		i++;
-		barrier();
-	}
-	cp->rx_cons = *cp->rx_cons_ptr;
-
-	cid_addr = GET_CID_ADDR(2);
-	val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE |
-	      BNX2_L2CTX_CTX_TYPE_SIZE_L2 | (0x02 << 8);
-	cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_CTX_TYPE, val);
-
-	if (sb_id == 0)
-		val = 2 << BNX2_L2CTX_L2_STATUSB_NUM_SHIFT;
-	else
-		val = BNX2_L2CTX_L2_STATUSB_NUM(sb_id);
-	cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_HOST_BDIDX, val);
-
-	rxbd = udev->l2_ring + BCM_PAGE_SIZE;
-	for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) {
-		dma_addr_t buf_map;
-		int n = (i % cp->l2_rx_ring_size) + 1;
-
-		buf_map = udev->l2_buf_map + (n * cp->l2_single_buf_size);
-		rxbd->rx_bd_len = cp->l2_single_buf_size;
-		rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
-		rxbd->rx_bd_haddr_hi = (u64) buf_map >> 32;
-		rxbd->rx_bd_haddr_lo = (u64) buf_map & 0xffffffff;
-	}
-	val = (u64) (ring_map + BCM_PAGE_SIZE) >> 32;
-	cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val);
-	rxbd->rx_bd_haddr_hi = val;
-
-	val = (u64) (ring_map + BCM_PAGE_SIZE) & 0xffffffff;
-	cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val);
-	rxbd->rx_bd_haddr_lo = val;
-
-	val = cnic_reg_rd_ind(dev, BNX2_RXP_SCRATCH_RXP_FLOOD);
-	cnic_reg_wr_ind(dev, BNX2_RXP_SCRATCH_RXP_FLOOD, val | (1 << 2));
-}
-
-static void cnic_shutdown_bnx2_rx_ring(struct cnic_dev *dev)
-{
-	struct kwqe *wqes[1], l2kwqe;
-
-	memset(&l2kwqe, 0, sizeof(l2kwqe));
-	wqes[0] = &l2kwqe;
-	l2kwqe.kwqe_op_flag = (L2_LAYER_CODE << KWQE_LAYER_SHIFT) |
-			      (L2_KWQE_OPCODE_VALUE_FLUSH <<
-			       KWQE_OPCODE_SHIFT) | 2;
-	dev->submit_kwqes(dev, wqes, 1);
-}
-
-static void cnic_set_bnx2_mac(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 val;
-
-	val = cp->func << 2;
-
-	cp->shmem_base = cnic_reg_rd_ind(dev, BNX2_SHM_HDR_ADDR_0 + val);
-
-	val = cnic_reg_rd_ind(dev, cp->shmem_base +
-			      BNX2_PORT_HW_CFG_ISCSI_MAC_UPPER);
-	dev->mac_addr[0] = (u8) (val >> 8);
-	dev->mac_addr[1] = (u8) val;
-
-	CNIC_WR(dev, BNX2_EMAC_MAC_MATCH4, val);
-
-	val = cnic_reg_rd_ind(dev, cp->shmem_base +
-			      BNX2_PORT_HW_CFG_ISCSI_MAC_LOWER);
-	dev->mac_addr[2] = (u8) (val >> 24);
-	dev->mac_addr[3] = (u8) (val >> 16);
-	dev->mac_addr[4] = (u8) (val >> 8);
-	dev->mac_addr[5] = (u8) val;
-
-	CNIC_WR(dev, BNX2_EMAC_MAC_MATCH5, val);
-
-	val = 4 | BNX2_RPM_SORT_USER2_BC_EN;
-	if (CHIP_NUM(cp) != CHIP_NUM_5709)
-		val |= BNX2_RPM_SORT_USER2_PROM_VLAN;
-
-	CNIC_WR(dev, BNX2_RPM_SORT_USER2, 0x0);
-	CNIC_WR(dev, BNX2_RPM_SORT_USER2, val);
-	CNIC_WR(dev, BNX2_RPM_SORT_USER2, val | BNX2_RPM_SORT_USER2_ENA);
-}
-
-static int cnic_start_bnx2_hw(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	struct status_block *sblk = cp->status_blk.gen;
-	u32 val, kcq_cid_addr, kwq_cid_addr;
-	int err;
-
-	cnic_set_bnx2_mac(dev);
-
-	val = CNIC_RD(dev, BNX2_MQ_CONFIG);
-	val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE;
-	if (BCM_PAGE_BITS > 12)
-		val |= (12 - 8)  << 4;
-	else
-		val |= (BCM_PAGE_BITS - 8)  << 4;
-
-	CNIC_WR(dev, BNX2_MQ_CONFIG, val);
-
-	CNIC_WR(dev, BNX2_HC_COMP_PROD_TRIP, (2 << 16) | 8);
-	CNIC_WR(dev, BNX2_HC_COM_TICKS, (64 << 16) | 220);
-	CNIC_WR(dev, BNX2_HC_CMD_TICKS, (64 << 16) | 220);
-
-	err = cnic_setup_5709_context(dev, 1);
-	if (err)
-		return err;
-
-	cnic_init_context(dev, KWQ_CID);
-	cnic_init_context(dev, KCQ_CID);
-
-	kwq_cid_addr = GET_CID_ADDR(KWQ_CID);
-	cp->kwq_io_addr = MB_GET_CID_ADDR(KWQ_CID) + L5_KRNLQ_HOST_QIDX;
-
-	cp->max_kwq_idx = MAX_KWQ_IDX;
-	cp->kwq_prod_idx = 0;
-	cp->kwq_con_idx = 0;
-	set_bit(CNIC_LCL_FL_KWQ_INIT, &cp->cnic_local_flags);
-
-	if (CHIP_NUM(cp) == CHIP_NUM_5706 || CHIP_NUM(cp) == CHIP_NUM_5708)
-		cp->kwq_con_idx_ptr = &sblk->status_rx_quick_consumer_index15;
-	else
-		cp->kwq_con_idx_ptr = &sblk->status_cmd_consumer_index;
-
-	/* Initialize the kernel work queue context. */
-	val = KRNLQ_TYPE_TYPE_KRNLQ | KRNLQ_SIZE_TYPE_SIZE |
-	      (BCM_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
-	cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_TYPE, val);
-
-	val = (BCM_PAGE_SIZE / sizeof(struct kwqe) - 1) << 16;
-	cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val);
-
-	val = ((BCM_PAGE_SIZE / sizeof(struct kwqe)) << 16) | KWQ_PAGE_CNT;
-	cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val);
-
-	val = (u32) ((u64) cp->kwq_info.pgtbl_map >> 32);
-	cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_PGTBL_HADDR_HI, val);
-
-	val = (u32) cp->kwq_info.pgtbl_map;
-	cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_PGTBL_HADDR_LO, val);
-
-	kcq_cid_addr = GET_CID_ADDR(KCQ_CID);
-	cp->kcq1.io_addr = MB_GET_CID_ADDR(KCQ_CID) + L5_KRNLQ_HOST_QIDX;
-
-	cp->kcq1.sw_prod_idx = 0;
-	cp->kcq1.hw_prod_idx_ptr =
-		(u16 *) &sblk->status_completion_producer_index;
-
-	cp->kcq1.status_idx_ptr = (u16 *) &sblk->status_idx;
-
-	/* Initialize the kernel complete queue context. */
-	val = KRNLQ_TYPE_TYPE_KRNLQ | KRNLQ_SIZE_TYPE_SIZE |
-	      (BCM_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
-	cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_TYPE, val);
-
-	val = (BCM_PAGE_SIZE / sizeof(struct kcqe) - 1) << 16;
-	cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val);
-
-	val = ((BCM_PAGE_SIZE / sizeof(struct kcqe)) << 16) | KCQ_PAGE_CNT;
-	cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val);
-
-	val = (u32) ((u64) cp->kcq1.dma.pgtbl_map >> 32);
-	cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_PGTBL_HADDR_HI, val);
-
-	val = (u32) cp->kcq1.dma.pgtbl_map;
-	cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_PGTBL_HADDR_LO, val);
-
-	cp->int_num = 0;
-	if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
-		struct status_block_msix *msblk = cp->status_blk.bnx2;
-		u32 sb_id = cp->status_blk_num;
-		u32 sb = BNX2_L2CTX_L5_STATUSB_NUM(sb_id);
-
-		cp->kcq1.hw_prod_idx_ptr =
-			(u16 *) &msblk->status_completion_producer_index;
-		cp->kcq1.status_idx_ptr = (u16 *) &msblk->status_idx;
-		cp->kwq_con_idx_ptr = (u16 *) &msblk->status_cmd_consumer_index;
-		cp->int_num = sb_id << BNX2_PCICFG_INT_ACK_CMD_INT_NUM_SHIFT;
-		cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_HOST_QIDX, sb);
-		cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_HOST_QIDX, sb);
-	}
-
-	/* Enable Commnad Scheduler notification when we write to the
-	 * host producer index of the kernel contexts. */
-	CNIC_WR(dev, BNX2_MQ_KNL_CMD_MASK1, 2);
-
-	/* Enable Command Scheduler notification when we write to either
-	 * the Send Queue or Receive Queue producer indexes of the kernel
-	 * bypass contexts. */
-	CNIC_WR(dev, BNX2_MQ_KNL_BYP_CMD_MASK1, 7);
-	CNIC_WR(dev, BNX2_MQ_KNL_BYP_WRITE_MASK1, 7);
-
-	/* Notify COM when the driver post an application buffer. */
-	CNIC_WR(dev, BNX2_MQ_KNL_RX_V2P_MASK2, 0x2000);
-
-	/* Set the CP and COM doorbells.  These two processors polls the
-	 * doorbell for a non zero value before running.  This must be done
-	 * after setting up the kernel queue contexts. */
-	cnic_reg_wr_ind(dev, BNX2_CP_SCRATCH + 0x20, 1);
-	cnic_reg_wr_ind(dev, BNX2_COM_SCRATCH + 0x20, 1);
-
-	cnic_init_bnx2_tx_ring(dev);
-	cnic_init_bnx2_rx_ring(dev);
-
-	err = cnic_init_bnx2_irq(dev);
-	if (err) {
-		netdev_err(dev->netdev, "cnic_init_irq failed\n");
-		cnic_reg_wr_ind(dev, BNX2_CP_SCRATCH + 0x20, 0);
-		cnic_reg_wr_ind(dev, BNX2_COM_SCRATCH + 0x20, 0);
-		return err;
-	}
-
-	return 0;
-}
-
-static void cnic_setup_bnx2x_context(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	u32 start_offset = ethdev->ctx_tbl_offset;
-	int i;
-
-	for (i = 0; i < cp->ctx_blks; i++) {
-		struct cnic_ctx *ctx = &cp->ctx_arr[i];
-		dma_addr_t map = ctx->mapping;
-
-		if (cp->ctx_align) {
-			unsigned long mask = cp->ctx_align - 1;
-
-			map = (map + mask) & ~mask;
-		}
-
-		cnic_ctx_tbl_wr(dev, start_offset + i, map);
-	}
-}
-
-static int cnic_init_bnx2x_irq(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	int err = 0;
-
-	tasklet_init(&cp->cnic_irq_task, cnic_service_bnx2x_bh,
-		     (unsigned long) dev);
-	if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX)
-		err = cnic_request_irq(dev);
-
-	return err;
-}
-
-static inline void cnic_storm_memset_hc_disable(struct cnic_dev *dev,
-						u16 sb_id, u8 sb_index,
-						u8 disable)
-{
-
-	u32 addr = BAR_CSTRORM_INTMEM +
-			CSTORM_STATUS_BLOCK_DATA_OFFSET(sb_id) +
-			offsetof(struct hc_status_block_data_e1x, index_data) +
-			sizeof(struct hc_index_data)*sb_index +
-			offsetof(struct hc_index_data, flags);
-	u16 flags = CNIC_RD16(dev, addr);
-	/* clear and set */
-	flags &= ~HC_INDEX_DATA_HC_ENABLED;
-	flags |= (((~disable) << HC_INDEX_DATA_HC_ENABLED_SHIFT) &
-		  HC_INDEX_DATA_HC_ENABLED);
-	CNIC_WR16(dev, addr, flags);
-}
-
-static void cnic_enable_bnx2x_int(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	u8 sb_id = cp->status_blk_num;
-
-	CNIC_WR8(dev, BAR_CSTRORM_INTMEM +
-			CSTORM_STATUS_BLOCK_DATA_OFFSET(sb_id) +
-			offsetof(struct hc_status_block_data_e1x, index_data) +
-			sizeof(struct hc_index_data)*HC_INDEX_ISCSI_EQ_CONS +
-			offsetof(struct hc_index_data, timeout), 64 / 4);
-	cnic_storm_memset_hc_disable(dev, sb_id, HC_INDEX_ISCSI_EQ_CONS, 0);
-}
-
-static void cnic_disable_bnx2x_int_sync(struct cnic_dev *dev)
-{
-}
-
-static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,
-				    struct client_init_ramrod_data *data)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_uio_dev *udev = cp->udev;
-	union eth_tx_bd_types *txbd = (union eth_tx_bd_types *) udev->l2_ring;
-	dma_addr_t buf_map, ring_map = udev->l2_ring_map;
-	struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
-	int i;
-	u32 cli = cp->ethdev->iscsi_l2_client_id;
-	u32 val;
-
-	memset(txbd, 0, BCM_PAGE_SIZE);
-
-	buf_map = udev->l2_buf_map;
-	for (i = 0; i < MAX_TX_DESC_CNT; i += 3, txbd += 3) {
-		struct eth_tx_start_bd *start_bd = &txbd->start_bd;
-		struct eth_tx_bd *reg_bd = &((txbd + 2)->reg_bd);
-
-		start_bd->addr_hi = cpu_to_le32((u64) buf_map >> 32);
-		start_bd->addr_lo = cpu_to_le32(buf_map & 0xffffffff);
-		reg_bd->addr_hi = start_bd->addr_hi;
-		reg_bd->addr_lo = start_bd->addr_lo + 0x10;
-		start_bd->nbytes = cpu_to_le16(0x10);
-		start_bd->nbd = cpu_to_le16(3);
-		start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD;
-		start_bd->general_data = (UNICAST_ADDRESS <<
-			ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT);
-		start_bd->general_data |= (1 << ETH_TX_START_BD_HDR_NBDS_SHIFT);
-
-	}
-
-	val = (u64) ring_map >> 32;
-	txbd->next_bd.addr_hi = cpu_to_le32(val);
-
-	data->tx.tx_bd_page_base.hi = cpu_to_le32(val);
-
-	val = (u64) ring_map & 0xffffffff;
-	txbd->next_bd.addr_lo = cpu_to_le32(val);
-
-	data->tx.tx_bd_page_base.lo = cpu_to_le32(val);
-
-	/* Other ramrod params */
-	data->tx.tx_sb_index_number = HC_SP_INDEX_ETH_ISCSI_CQ_CONS;
-	data->tx.tx_status_block_id = BNX2X_DEF_SB_ID;
-
-	/* reset xstorm per client statistics */
-	if (cli < MAX_STAT_COUNTER_ID) {
-		data->general.statistics_zero_flg = 1;
-		data->general.statistics_en_flg = 1;
-		data->general.statistics_counter_id = cli;
-	}
-
-	cp->tx_cons_ptr =
-		&sb->sp_sb.index_values[HC_SP_INDEX_ETH_ISCSI_CQ_CONS];
-}
-
-static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
-				    struct client_init_ramrod_data *data)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_uio_dev *udev = cp->udev;
-	struct eth_rx_bd *rxbd = (struct eth_rx_bd *) (udev->l2_ring +
-				BCM_PAGE_SIZE);
-	struct eth_rx_cqe_next_page *rxcqe = (struct eth_rx_cqe_next_page *)
-				(udev->l2_ring + (2 * BCM_PAGE_SIZE));
-	struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
-	int i;
-	u32 cli = cp->ethdev->iscsi_l2_client_id;
-	int cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);
-	u32 val;
-	dma_addr_t ring_map = udev->l2_ring_map;
-
-	/* General data */
-	data->general.client_id = cli;
-	data->general.activate_flg = 1;
-	data->general.sp_client_id = cli;
-	data->general.mtu = cpu_to_le16(cp->l2_single_buf_size - 14);
-	data->general.func_id = cp->pfid;
-
-	for (i = 0; i < BNX2X_MAX_RX_DESC_CNT; i++, rxbd++) {
-		dma_addr_t buf_map;
-		int n = (i % cp->l2_rx_ring_size) + 1;
-
-		buf_map = udev->l2_buf_map + (n * cp->l2_single_buf_size);
-		rxbd->addr_hi = cpu_to_le32((u64) buf_map >> 32);
-		rxbd->addr_lo = cpu_to_le32(buf_map & 0xffffffff);
-	}
-
-	val = (u64) (ring_map + BCM_PAGE_SIZE) >> 32;
-	rxbd->addr_hi = cpu_to_le32(val);
-	data->rx.bd_page_base.hi = cpu_to_le32(val);
-
-	val = (u64) (ring_map + BCM_PAGE_SIZE) & 0xffffffff;
-	rxbd->addr_lo = cpu_to_le32(val);
-	data->rx.bd_page_base.lo = cpu_to_le32(val);
-
-	rxcqe += BNX2X_MAX_RCQ_DESC_CNT;
-	val = (u64) (ring_map + (2 * BCM_PAGE_SIZE)) >> 32;
-	rxcqe->addr_hi = cpu_to_le32(val);
-	data->rx.cqe_page_base.hi = cpu_to_le32(val);
-
-	val = (u64) (ring_map + (2 * BCM_PAGE_SIZE)) & 0xffffffff;
-	rxcqe->addr_lo = cpu_to_le32(val);
-	data->rx.cqe_page_base.lo = cpu_to_le32(val);
-
-	/* Other ramrod params */
-	data->rx.client_qzone_id = cl_qzone_id;
-	data->rx.rx_sb_index_number = HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS;
-	data->rx.status_block_id = BNX2X_DEF_SB_ID;
-
-	data->rx.cache_line_alignment_log_size = L1_CACHE_SHIFT;
-
-	data->rx.max_bytes_on_bd = cpu_to_le16(cp->l2_single_buf_size);
-	data->rx.outer_vlan_removal_enable_flg = 1;
-	data->rx.silent_vlan_removal_flg = 1;
-	data->rx.silent_vlan_value = 0;
-	data->rx.silent_vlan_mask = 0xffff;
-
-	cp->rx_cons_ptr =
-		&sb->sp_sb.index_values[HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS];
-	cp->rx_cons = *cp->rx_cons_ptr;
-}
-
-static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 pfid = cp->pfid;
-
-	cp->kcq1.io_addr = BAR_CSTRORM_INTMEM +
-			   CSTORM_ISCSI_EQ_PROD_OFFSET(pfid, 0);
-	cp->kcq1.sw_prod_idx = 0;
-
-	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
-		struct host_hc_status_block_e2 *sb = cp->status_blk.gen;
-
-		cp->kcq1.hw_prod_idx_ptr =
-			&sb->sb.index_values[HC_INDEX_ISCSI_EQ_CONS];
-		cp->kcq1.status_idx_ptr =
-			&sb->sb.running_index[SM_RX_ID];
-	} else {
-		struct host_hc_status_block_e1x *sb = cp->status_blk.gen;
-
-		cp->kcq1.hw_prod_idx_ptr =
-			&sb->sb.index_values[HC_INDEX_ISCSI_EQ_CONS];
-		cp->kcq1.status_idx_ptr =
-			&sb->sb.running_index[SM_RX_ID];
-	}
-
-	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
-		struct host_hc_status_block_e2 *sb = cp->status_blk.gen;
-
-		cp->kcq2.io_addr = BAR_USTRORM_INTMEM +
-					USTORM_FCOE_EQ_PROD_OFFSET(pfid);
-		cp->kcq2.sw_prod_idx = 0;
-		cp->kcq2.hw_prod_idx_ptr =
-			&sb->sb.index_values[HC_INDEX_FCOE_EQ_CONS];
-		cp->kcq2.status_idx_ptr =
-			&sb->sb.running_index[SM_RX_ID];
-	}
-}
-
-static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	int func = CNIC_FUNC(cp), ret;
-	u32 pfid;
-
-	cp->port_mode = CHIP_PORT_MODE_NONE;
-
-	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
-		u32 val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN_OVWR);
-
-		if (!(val & 1))
-			val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN);
-		else
-			val = (val >> 1) & 1;
-
-		if (val) {
-			cp->port_mode = CHIP_4_PORT_MODE;
-			cp->pfid = func >> 1;
-		} else {
-			cp->port_mode = CHIP_2_PORT_MODE;
-			cp->pfid = func & 0x6;
-		}
-	} else {
-		cp->pfid = func;
-	}
-	pfid = cp->pfid;
-
-	ret = cnic_init_id_tbl(&cp->cid_tbl, MAX_ISCSI_TBL_SZ,
-			       cp->iscsi_start_cid, 0);
-
-	if (ret)
-		return -ENOMEM;
-
-	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
-		ret = cnic_init_id_tbl(&cp->fcoe_cid_tbl,
-					BNX2X_FCOE_NUM_CONNECTIONS,
-					cp->fcoe_start_cid, 0);
-
-		if (ret)
-			return -ENOMEM;
-	}
-
-	cp->bnx2x_igu_sb_id = ethdev->irq_arr[0].status_blk_num2;
-
-	cnic_init_bnx2x_kcq(dev);
-
-	/* Only 1 EQ */
-	CNIC_WR16(dev, cp->kcq1.io_addr, MAX_KCQ_IDX);
-	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_CONS_OFFSET(pfid, 0), 0);
-	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfid, 0),
-		cp->kcq1.dma.pg_map_arr[1] & 0xffffffff);
-	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfid, 0) + 4,
-		(u64) cp->kcq1.dma.pg_map_arr[1] >> 32);
-	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfid, 0),
-		cp->kcq1.dma.pg_map_arr[0] & 0xffffffff);
-	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfid, 0) + 4,
-		(u64) cp->kcq1.dma.pg_map_arr[0] >> 32);
-	CNIC_WR8(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfid, 0), 1);
-	CNIC_WR16(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfid, 0), cp->status_blk_num);
-	CNIC_WR8(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfid, 0),
-		HC_INDEX_ISCSI_EQ_CONS);
-
-	CNIC_WR(dev, BAR_USTRORM_INTMEM +
-		USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfid),
-		cp->gbl_buf_info.pg_map_arr[0] & 0xffffffff);
-	CNIC_WR(dev, BAR_USTRORM_INTMEM +
-		USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfid) + 4,
-		(u64) cp->gbl_buf_info.pg_map_arr[0] >> 32);
-
-	CNIC_WR(dev, BAR_TSTRORM_INTMEM +
-		TSTORM_ISCSI_TCP_LOCAL_ADV_WND_OFFSET(pfid), DEF_RCV_BUF);
-
-	cnic_setup_bnx2x_context(dev);
-
-	ret = cnic_init_bnx2x_irq(dev);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-static void cnic_init_rings(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_uio_dev *udev = cp->udev;
-
-	if (test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags))
-		return;
-
-	if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) {
-		cnic_init_bnx2_tx_ring(dev);
-		cnic_init_bnx2_rx_ring(dev);
-		set_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
-	} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
-		u32 cli = cp->ethdev->iscsi_l2_client_id;
-		u32 cid = cp->ethdev->iscsi_l2_cid;
-		u32 cl_qzone_id;
-		struct client_init_ramrod_data *data;
-		union l5cm_specific_data l5_data;
-		struct ustorm_eth_rx_producers rx_prods = {0};
-		u32 off, i, *cid_ptr;
-
-		rx_prods.bd_prod = 0;
-		rx_prods.cqe_prod = BNX2X_MAX_RCQ_DESC_CNT;
-		barrier();
-
-		cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);
-
-		off = BAR_USTRORM_INTMEM +
-			(BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ?
-			 USTORM_RX_PRODS_E2_OFFSET(cl_qzone_id) :
-			 USTORM_RX_PRODS_E1X_OFFSET(CNIC_PORT(cp), cli));
-
-		for (i = 0; i < sizeof(struct ustorm_eth_rx_producers) / 4; i++)
-			CNIC_WR(dev, off + i * 4, ((u32 *) &rx_prods)[i]);
-
-		set_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags);
-
-		data = udev->l2_buf;
-		cid_ptr = udev->l2_buf + 12;
-
-		memset(data, 0, sizeof(*data));
-
-		cnic_init_bnx2x_tx_ring(dev, data);
-		cnic_init_bnx2x_rx_ring(dev, data);
-
-		l5_data.phy_address.lo = udev->l2_buf_map & 0xffffffff;
-		l5_data.phy_address.hi = (u64) udev->l2_buf_map >> 32;
-
-		set_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
-
-		cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_CLIENT_SETUP,
-			cid, ETH_CONNECTION_TYPE, &l5_data);
-
-		i = 0;
-		while (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags) &&
-		       ++i < 10)
-			msleep(1);
-
-		if (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags))
-			netdev_err(dev->netdev,
-				"iSCSI CLIENT_SETUP did not complete\n");
-		cnic_spq_completion(dev, DRV_CTL_RET_L2_SPQ_CREDIT_CMD, 1);
-		cnic_ring_ctl(dev, cid, cli, 1);
-		*cid_ptr = cid;
-	}
-}
-
-static void cnic_shutdown_rings(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_uio_dev *udev = cp->udev;
-	void *rx_ring;
-
-	if (!test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags))
-		return;
-
-	if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) {
-		cnic_shutdown_bnx2_rx_ring(dev);
-	} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
-		u32 cli = cp->ethdev->iscsi_l2_client_id;
-		u32 cid = cp->ethdev->iscsi_l2_cid;
-		union l5cm_specific_data l5_data;
-		int i;
-
-		cnic_ring_ctl(dev, cid, cli, 0);
-
-		set_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags);
-
-		l5_data.phy_address.lo = cli;
-		l5_data.phy_address.hi = 0;
-		cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_HALT,
-			cid, ETH_CONNECTION_TYPE, &l5_data);
-		i = 0;
-		while (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags) &&
-		       ++i < 10)
-			msleep(1);
-
-		if (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags))
-			netdev_err(dev->netdev,
-				"iSCSI CLIENT_HALT did not complete\n");
-		cnic_spq_completion(dev, DRV_CTL_RET_L2_SPQ_CREDIT_CMD, 1);
-
-		memset(&l5_data, 0, sizeof(l5_data));
-		cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_COMMON_CFC_DEL,
-			cid, NONE_CONNECTION_TYPE, &l5_data);
-		msleep(10);
-	}
-	clear_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
-	rx_ring = udev->l2_ring + BCM_PAGE_SIZE;
-	memset(rx_ring, 0, BCM_PAGE_SIZE);
-}
-
-static int cnic_register_netdev(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	int err;
-
-	if (!ethdev)
-		return -ENODEV;
-
-	if (ethdev->drv_state & CNIC_DRV_STATE_REGD)
-		return 0;
-
-	err = ethdev->drv_register_cnic(dev->netdev, cp->cnic_ops, dev);
-	if (err)
-		netdev_err(dev->netdev, "register_cnic failed\n");
-
-	return err;
-}
-
-static void cnic_unregister_netdev(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-
-	if (!ethdev)
-		return;
-
-	ethdev->drv_unregister_cnic(dev->netdev);
-}
-
-static int cnic_start_hw(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	struct cnic_eth_dev *ethdev = cp->ethdev;
-	int err;
-
-	if (test_bit(CNIC_F_CNIC_UP, &dev->flags))
-		return -EALREADY;
-
-	dev->regview = ethdev->io_base;
-	pci_dev_get(dev->pcidev);
-	cp->func = PCI_FUNC(dev->pcidev->devfn);
-	cp->status_blk.gen = ethdev->irq_arr[0].status_blk;
-	cp->status_blk_num = ethdev->irq_arr[0].status_blk_num;
-
-	err = cp->alloc_resc(dev);
-	if (err) {
-		netdev_err(dev->netdev, "allocate resource failure\n");
-		goto err1;
-	}
-
-	err = cp->start_hw(dev);
-	if (err)
-		goto err1;
-
-	err = cnic_cm_open(dev);
-	if (err)
-		goto err1;
-
-	set_bit(CNIC_F_CNIC_UP, &dev->flags);
-
-	cp->enable_int(dev);
-
-	return 0;
-
-err1:
-	cp->free_resc(dev);
-	pci_dev_put(dev->pcidev);
-	return err;
-}
-
-static void cnic_stop_bnx2_hw(struct cnic_dev *dev)
-{
-	cnic_disable_bnx2_int_sync(dev);
-
-	cnic_reg_wr_ind(dev, BNX2_CP_SCRATCH + 0x20, 0);
-	cnic_reg_wr_ind(dev, BNX2_COM_SCRATCH + 0x20, 0);
-
-	cnic_init_context(dev, KWQ_CID);
-	cnic_init_context(dev, KCQ_CID);
-
-	cnic_setup_5709_context(dev, 0);
-	cnic_free_irq(dev);
-
-	cnic_free_resc(dev);
-}
-
-
-static void cnic_stop_bnx2x_hw(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-
-	cnic_free_irq(dev);
-	*cp->kcq1.hw_prod_idx_ptr = 0;
-	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_CONS_OFFSET(cp->pfid, 0), 0);
-	CNIC_WR16(dev, cp->kcq1.io_addr, 0);
-	cnic_free_resc(dev);
-}
-
-static void cnic_stop_hw(struct cnic_dev *dev)
-{
-	if (test_bit(CNIC_F_CNIC_UP, &dev->flags)) {
-		struct cnic_local *cp = dev->cnic_priv;
-		int i = 0;
-
-		/* Need to wait for the ring shutdown event to complete
-		 * before clearing the CNIC_UP flag.
-		 */
-		while (cp->udev->uio_dev != -1 && i < 15) {
-			msleep(100);
-			i++;
-		}
-		cnic_shutdown_rings(dev);
-		clear_bit(CNIC_F_CNIC_UP, &dev->flags);
-		rcu_assign_pointer(cp->ulp_ops[CNIC_ULP_L4], NULL);
-		synchronize_rcu();
-		cnic_cm_shutdown(dev);
-		cp->stop_hw(dev);
-		pci_dev_put(dev->pcidev);
-	}
-}
-
-static void cnic_free_dev(struct cnic_dev *dev)
-{
-	int i = 0;
-
-	while ((atomic_read(&dev->ref_count) != 0) && i < 10) {
-		msleep(100);
-		i++;
-	}
-	if (atomic_read(&dev->ref_count) != 0)
-		netdev_err(dev->netdev, "Failed waiting for ref count to go to zero\n");
-
-	netdev_info(dev->netdev, "Removed CNIC device\n");
-	dev_put(dev->netdev);
-	kfree(dev);
-}
-
-static struct cnic_dev *cnic_alloc_dev(struct net_device *dev,
-				       struct pci_dev *pdev)
-{
-	struct cnic_dev *cdev;
-	struct cnic_local *cp;
-	int alloc_size;
-
-	alloc_size = sizeof(struct cnic_dev) + sizeof(struct cnic_local);
-
-	cdev = kzalloc(alloc_size , GFP_KERNEL);
-	if (cdev == NULL) {
-		netdev_err(dev, "allocate dev struct failure\n");
-		return NULL;
-	}
-
-	cdev->netdev = dev;
-	cdev->cnic_priv = (char *)cdev + sizeof(struct cnic_dev);
-	cdev->register_device = cnic_register_device;
-	cdev->unregister_device = cnic_unregister_device;
-	cdev->iscsi_nl_msg_recv = cnic_iscsi_nl_msg_recv;
-
-	cp = cdev->cnic_priv;
-	cp->dev = cdev;
-	cp->l2_single_buf_size = 0x400;
-	cp->l2_rx_ring_size = 3;
-
-	spin_lock_init(&cp->cnic_ulp_lock);
-
-	netdev_info(dev, "Added CNIC device\n");
-
-	return cdev;
-}
-
-static struct cnic_dev *init_bnx2_cnic(struct net_device *dev)
-{
-	struct pci_dev *pdev;
-	struct cnic_dev *cdev;
-	struct cnic_local *cp;
-	struct cnic_eth_dev *ethdev = NULL;
-	struct cnic_eth_dev *(*probe)(struct net_device *) = NULL;
-
-	probe = symbol_get(bnx2_cnic_probe);
-	if (probe) {
-		ethdev = (*probe)(dev);
-		symbol_put(bnx2_cnic_probe);
-	}
-	if (!ethdev)
-		return NULL;
-
-	pdev = ethdev->pdev;
-	if (!pdev)
-		return NULL;
-
-	dev_hold(dev);
-	pci_dev_get(pdev);
-	if ((pdev->device == PCI_DEVICE_ID_NX2_5709 ||
-	     pdev->device == PCI_DEVICE_ID_NX2_5709S) &&
-	    (pdev->revision < 0x10)) {
-		pci_dev_put(pdev);
-		goto cnic_err;
-	}
-	pci_dev_put(pdev);
-
-	cdev = cnic_alloc_dev(dev, pdev);
-	if (cdev == NULL)
-		goto cnic_err;
-
-	set_bit(CNIC_F_BNX2_CLASS, &cdev->flags);
-	cdev->submit_kwqes = cnic_submit_bnx2_kwqes;
-
-	cp = cdev->cnic_priv;
-	cp->ethdev = ethdev;
-	cdev->pcidev = pdev;
-	cp->chip_id = ethdev->chip_id;
-
-	cdev->max_iscsi_conn = ethdev->max_iscsi_conn;
-
-	cp->cnic_ops = &cnic_bnx2_ops;
-	cp->start_hw = cnic_start_bnx2_hw;
-	cp->stop_hw = cnic_stop_bnx2_hw;
-	cp->setup_pgtbl = cnic_setup_page_tbl;
-	cp->alloc_resc = cnic_alloc_bnx2_resc;
-	cp->free_resc = cnic_free_resc;
-	cp->start_cm = cnic_cm_init_bnx2_hw;
-	cp->stop_cm = cnic_cm_stop_bnx2_hw;
-	cp->enable_int = cnic_enable_bnx2_int;
-	cp->disable_int_sync = cnic_disable_bnx2_int_sync;
-	cp->close_conn = cnic_close_bnx2_conn;
-	return cdev;
-
-cnic_err:
-	dev_put(dev);
-	return NULL;
-}
-
-static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev)
-{
-	struct pci_dev *pdev;
-	struct cnic_dev *cdev;
-	struct cnic_local *cp;
-	struct cnic_eth_dev *ethdev = NULL;
-	struct cnic_eth_dev *(*probe)(struct net_device *) = NULL;
-
-	probe = symbol_get(bnx2x_cnic_probe);
-	if (probe) {
-		ethdev = (*probe)(dev);
-		symbol_put(bnx2x_cnic_probe);
-	}
-	if (!ethdev)
-		return NULL;
-
-	pdev = ethdev->pdev;
-	if (!pdev)
-		return NULL;
-
-	dev_hold(dev);
-	cdev = cnic_alloc_dev(dev, pdev);
-	if (cdev == NULL) {
-		dev_put(dev);
-		return NULL;
-	}
-
-	set_bit(CNIC_F_BNX2X_CLASS, &cdev->flags);
-	cdev->submit_kwqes = cnic_submit_bnx2x_kwqes;
-
-	cp = cdev->cnic_priv;
-	cp->ethdev = ethdev;
-	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_PLUS(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;
-	cp->setup_pgtbl = cnic_setup_page_tbl_le;
-	cp->alloc_resc = cnic_alloc_bnx2x_resc;
-	cp->free_resc = cnic_free_resc;
-	cp->start_cm = cnic_cm_init_bnx2x_hw;
-	cp->stop_cm = cnic_cm_stop_bnx2x_hw;
-	cp->enable_int = cnic_enable_bnx2x_int;
-	cp->disable_int_sync = cnic_disable_bnx2x_int_sync;
-	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id))
-		cp->ack_int = cnic_ack_bnx2x_e2_msix;
-	else
-		cp->ack_int = cnic_ack_bnx2x_msix;
-	cp->close_conn = cnic_close_bnx2x_conn;
-	return cdev;
-}
-
-static struct cnic_dev *is_cnic_dev(struct net_device *dev)
-{
-	struct ethtool_drvinfo drvinfo;
-	struct cnic_dev *cdev = NULL;
-
-	if (dev->ethtool_ops && dev->ethtool_ops->get_drvinfo) {
-		memset(&drvinfo, 0, sizeof(drvinfo));
-		dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
-
-		if (!strcmp(drvinfo.driver, "bnx2"))
-			cdev = init_bnx2_cnic(dev);
-		if (!strcmp(drvinfo.driver, "bnx2x"))
-			cdev = init_bnx2x_cnic(dev);
-		if (cdev) {
-			write_lock(&cnic_dev_lock);
-			list_add(&cdev->list, &cnic_dev_list);
-			write_unlock(&cnic_dev_lock);
-		}
-	}
-	return cdev;
-}
-
-static void cnic_rcv_netevent(struct cnic_local *cp, unsigned long event,
-			      u16 vlan_id)
-{
-	int if_type;
-
-	rcu_read_lock();
-	for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
-		struct cnic_ulp_ops *ulp_ops;
-		void *ctx;
-
-		ulp_ops = rcu_dereference(cp->ulp_ops[if_type]);
-		if (!ulp_ops || !ulp_ops->indicate_netevent)
-			continue;
-
-		ctx = cp->ulp_handle[if_type];
-
-		ulp_ops->indicate_netevent(ctx, event, vlan_id);
-	}
-	rcu_read_unlock();
-}
-
-/**
- * netdev event handler
- */
-static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
-							 void *ptr)
-{
-	struct net_device *netdev = ptr;
-	struct cnic_dev *dev;
-	int new_dev = 0;
-
-	dev = cnic_from_netdev(netdev);
-
-	if (!dev && (event == NETDEV_REGISTER || netif_running(netdev))) {
-		/* Check for the hot-plug device */
-		dev = is_cnic_dev(netdev);
-		if (dev) {
-			new_dev = 1;
-			cnic_hold(dev);
-		}
-	}
-	if (dev) {
-		struct cnic_local *cp = dev->cnic_priv;
-
-		if (new_dev)
-			cnic_ulp_init(dev);
-		else if (event == NETDEV_UNREGISTER)
-			cnic_ulp_exit(dev);
-
-		if (event == NETDEV_UP || (new_dev && netif_running(netdev))) {
-			if (cnic_register_netdev(dev) != 0) {
-				cnic_put(dev);
-				goto done;
-			}
-			if (!cnic_start_hw(dev))
-				cnic_ulp_start(dev);
-		}
-
-		cnic_rcv_netevent(cp, event, 0);
-
-		if (event == NETDEV_GOING_DOWN) {
-			cnic_ulp_stop(dev);
-			cnic_stop_hw(dev);
-			cnic_unregister_netdev(dev);
-		} else if (event == NETDEV_UNREGISTER) {
-			write_lock(&cnic_dev_lock);
-			list_del_init(&dev->list);
-			write_unlock(&cnic_dev_lock);
-
-			cnic_put(dev);
-			cnic_free_dev(dev);
-			goto done;
-		}
-		cnic_put(dev);
-	} else {
-		struct net_device *realdev;
-		u16 vid;
-
-		vid = cnic_get_vlan(netdev, &realdev);
-		if (realdev) {
-			dev = cnic_from_netdev(realdev);
-			if (dev) {
-				vid |= VLAN_TAG_PRESENT;
-				cnic_rcv_netevent(dev->cnic_priv, event, vid);
-				cnic_put(dev);
-			}
-		}
-	}
-done:
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block cnic_netdev_notifier = {
-	.notifier_call = cnic_netdev_event
-};
-
-static void cnic_release(void)
-{
-	struct cnic_dev *dev;
-	struct cnic_uio_dev *udev;
-
-	while (!list_empty(&cnic_dev_list)) {
-		dev = list_entry(cnic_dev_list.next, struct cnic_dev, list);
-		if (test_bit(CNIC_F_CNIC_UP, &dev->flags)) {
-			cnic_ulp_stop(dev);
-			cnic_stop_hw(dev);
-		}
-
-		cnic_ulp_exit(dev);
-		cnic_unregister_netdev(dev);
-		list_del_init(&dev->list);
-		cnic_free_dev(dev);
-	}
-	while (!list_empty(&cnic_udev_list)) {
-		udev = list_entry(cnic_udev_list.next, struct cnic_uio_dev,
-				  list);
-		cnic_free_uio(udev);
-	}
-}
-
-static int __init cnic_init(void)
-{
-	int rc = 0;
-
-	pr_info("%s", version);
-
-	rc = register_netdevice_notifier(&cnic_netdev_notifier);
-	if (rc) {
-		cnic_release();
-		return rc;
-	}
-
-	cnic_wq = create_singlethread_workqueue("cnic_wq");
-	if (!cnic_wq) {
-		cnic_release();
-		unregister_netdevice_notifier(&cnic_netdev_notifier);
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
-static void __exit cnic_exit(void)
-{
-	unregister_netdevice_notifier(&cnic_netdev_notifier);
-	cnic_release();
-	destroy_workqueue(cnic_wq);
-}
-
-module_init(cnic_init);
-module_exit(cnic_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/cnic_defs.h linux-libre-3.2-gnu/drivers/net/cnic_defs.h
--- linux-libre-3.1-gnu/drivers/net/cnic_defs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cnic_defs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,5484 +0,0 @@
-
-/* cnic.c: Broadcom CNIC core network driver.
- *
- * Copyright (c) 2006-2009 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation.
- *
- */
-
-#ifndef CNIC_DEFS_H
-#define CNIC_DEFS_H
-
-/* KWQ (kernel work queue) request op codes */
-#define L2_KWQE_OPCODE_VALUE_FLUSH                  (4)
-#define L2_KWQE_OPCODE_VALUE_VM_FREE_RX_QUEUE       (8)
-
-#define L4_KWQE_OPCODE_VALUE_CONNECT1               (50)
-#define L4_KWQE_OPCODE_VALUE_CONNECT2               (51)
-#define L4_KWQE_OPCODE_VALUE_CONNECT3               (52)
-#define L4_KWQE_OPCODE_VALUE_RESET                  (53)
-#define L4_KWQE_OPCODE_VALUE_CLOSE                  (54)
-#define L4_KWQE_OPCODE_VALUE_UPDATE_SECRET          (60)
-#define L4_KWQE_OPCODE_VALUE_INIT_ULP               (61)
-
-#define L4_KWQE_OPCODE_VALUE_OFFLOAD_PG             (1)
-#define L4_KWQE_OPCODE_VALUE_UPDATE_PG              (9)
-#define L4_KWQE_OPCODE_VALUE_UPLOAD_PG              (14)
-
-#define L5CM_RAMROD_CMD_ID_BASE			(0x80)
-#define L5CM_RAMROD_CMD_ID_TCP_CONNECT		(L5CM_RAMROD_CMD_ID_BASE + 3)
-#define L5CM_RAMROD_CMD_ID_CLOSE		(L5CM_RAMROD_CMD_ID_BASE + 12)
-#define L5CM_RAMROD_CMD_ID_ABORT		(L5CM_RAMROD_CMD_ID_BASE + 13)
-#define L5CM_RAMROD_CMD_ID_SEARCHER_DELETE	(L5CM_RAMROD_CMD_ID_BASE + 14)
-#define L5CM_RAMROD_CMD_ID_TERMINATE_OFFLOAD	(L5CM_RAMROD_CMD_ID_BASE + 15)
-
-#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)
-
-#define FCOE_RAMROD_CMD_ID_INIT_FUNC		(FCOE_KCQE_OPCODE_INIT_FUNC)
-#define FCOE_RAMROD_CMD_ID_DESTROY_FUNC		(FCOE_KCQE_OPCODE_DESTROY_FUNC)
-#define FCOE_RAMROD_CMD_ID_STAT_FUNC		(FCOE_KCQE_OPCODE_STAT_FUNC)
-#define FCOE_RAMROD_CMD_ID_OFFLOAD_CONN		(FCOE_KCQE_OPCODE_OFFLOAD_CONN)
-#define FCOE_RAMROD_CMD_ID_ENABLE_CONN		(FCOE_KCQE_OPCODE_ENABLE_CONN)
-#define FCOE_RAMROD_CMD_ID_DISABLE_CONN		(FCOE_KCQE_OPCODE_DISABLE_CONN)
-#define FCOE_RAMROD_CMD_ID_DESTROY_CONN		(FCOE_KCQE_OPCODE_DESTROY_CONN)
-#define FCOE_RAMROD_CMD_ID_TERMINATE_CONN	(0x81)
-
-#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)
-
-#define FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE	(0x3)
-
-/* KCQ (kernel completion queue) response op codes */
-#define L4_KCQE_OPCODE_VALUE_CLOSE_COMP             (53)
-#define L4_KCQE_OPCODE_VALUE_RESET_COMP             (54)
-#define L4_KCQE_OPCODE_VALUE_FW_TCP_UPDATE          (55)
-#define L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE       (56)
-#define L4_KCQE_OPCODE_VALUE_RESET_RECEIVED         (57)
-#define L4_KCQE_OPCODE_VALUE_CLOSE_RECEIVED         (58)
-#define L4_KCQE_OPCODE_VALUE_INIT_ULP               (61)
-
-#define L4_KCQE_OPCODE_VALUE_OFFLOAD_PG             (1)
-#define L4_KCQE_OPCODE_VALUE_UPDATE_PG              (9)
-#define L4_KCQE_OPCODE_VALUE_UPLOAD_PG              (14)
-
-/* KCQ (kernel completion queue) completion status */
-#define L4_KCQE_COMPLETION_STATUS_SUCCESS           (0)
-#define L4_KCQE_COMPLETION_STATUS_TIMEOUT           (0x93)
-
-#define L4_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAIL    (0x83)
-#define L4_KCQE_COMPLETION_STATUS_OFFLOADED_PG      (0x89)
-
-#define L4_KCQE_OPCODE_VALUE_OOO_EVENT_NOTIFICATION (0xa0)
-#define L4_KCQE_OPCODE_VALUE_OOO_FLUSH              (0xa1)
-
-#define L4_LAYER_CODE (4)
-#define L2_LAYER_CODE (2)
-
-/*
- * L4 KCQ CQE
- */
-struct l4_kcq {
-	u32 cid;
-	u32 pg_cid;
-	u32 conn_id;
-	u32 pg_host_opaque;
-#if defined(__BIG_ENDIAN)
-	u16 status;
-	u16 reserved1;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved1;
-	u16 status;
-#endif
-	u32 reserved2[2];
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define L4_KCQ_RESERVED3 (0x7<<0)
-#define L4_KCQ_RESERVED3_SHIFT 0
-#define L4_KCQ_RAMROD_COMPLETION (0x1<<3) /* Everest only */
-#define L4_KCQ_RAMROD_COMPLETION_SHIFT 3
-#define L4_KCQ_LAYER_CODE (0x7<<4)
-#define L4_KCQ_LAYER_CODE_SHIFT 4
-#define L4_KCQ_RESERVED4 (0x1<<7)
-#define L4_KCQ_RESERVED4_SHIFT 7
-	u8 op_code;
-	u16 qe_self_seq;
-#elif defined(__LITTLE_ENDIAN)
-	u16 qe_self_seq;
-	u8 op_code;
-	u8 flags;
-#define L4_KCQ_RESERVED3 (0xF<<0)
-#define L4_KCQ_RESERVED3_SHIFT 0
-#define L4_KCQ_RAMROD_COMPLETION (0x1<<3) /* Everest only */
-#define L4_KCQ_RAMROD_COMPLETION_SHIFT 3
-#define L4_KCQ_LAYER_CODE (0x7<<4)
-#define L4_KCQ_LAYER_CODE_SHIFT 4
-#define L4_KCQ_RESERVED4 (0x1<<7)
-#define L4_KCQ_RESERVED4_SHIFT 7
-#endif
-};
-
-
-/*
- * L4 KCQ CQE PG upload
- */
-struct l4_kcq_upload_pg {
-	u32 pg_cid;
-#if defined(__BIG_ENDIAN)
-	u16 pg_status;
-	u16 pg_ipid_count;
-#elif defined(__LITTLE_ENDIAN)
-	u16 pg_ipid_count;
-	u16 pg_status;
-#endif
-	u32 reserved1[5];
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define L4_KCQ_UPLOAD_PG_RESERVED3 (0xF<<0)
-#define L4_KCQ_UPLOAD_PG_RESERVED3_SHIFT 0
-#define L4_KCQ_UPLOAD_PG_LAYER_CODE (0x7<<4)
-#define L4_KCQ_UPLOAD_PG_LAYER_CODE_SHIFT 4
-#define L4_KCQ_UPLOAD_PG_RESERVED4 (0x1<<7)
-#define L4_KCQ_UPLOAD_PG_RESERVED4_SHIFT 7
-	u8 op_code;
-	u16 qe_self_seq;
-#elif defined(__LITTLE_ENDIAN)
-	u16 qe_self_seq;
-	u8 op_code;
-	u8 flags;
-#define L4_KCQ_UPLOAD_PG_RESERVED3 (0xF<<0)
-#define L4_KCQ_UPLOAD_PG_RESERVED3_SHIFT 0
-#define L4_KCQ_UPLOAD_PG_LAYER_CODE (0x7<<4)
-#define L4_KCQ_UPLOAD_PG_LAYER_CODE_SHIFT 4
-#define L4_KCQ_UPLOAD_PG_RESERVED4 (0x1<<7)
-#define L4_KCQ_UPLOAD_PG_RESERVED4_SHIFT 7
-#endif
-};
-
-
-/*
- * Gracefully close the connection request
- */
-struct l4_kwq_close_req {
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define L4_KWQ_CLOSE_REQ_RESERVED1 (0xF<<0)
-#define L4_KWQ_CLOSE_REQ_RESERVED1_SHIFT 0
-#define L4_KWQ_CLOSE_REQ_LAYER_CODE (0x7<<4)
-#define L4_KWQ_CLOSE_REQ_LAYER_CODE_SHIFT 4
-#define L4_KWQ_CLOSE_REQ_LINKED_WITH_NEXT (0x1<<7)
-#define L4_KWQ_CLOSE_REQ_LINKED_WITH_NEXT_SHIFT 7
-	u8 op_code;
-	u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved0;
-	u8 op_code;
-	u8 flags;
-#define L4_KWQ_CLOSE_REQ_RESERVED1 (0xF<<0)
-#define L4_KWQ_CLOSE_REQ_RESERVED1_SHIFT 0
-#define L4_KWQ_CLOSE_REQ_LAYER_CODE (0x7<<4)
-#define L4_KWQ_CLOSE_REQ_LAYER_CODE_SHIFT 4
-#define L4_KWQ_CLOSE_REQ_LINKED_WITH_NEXT (0x1<<7)
-#define L4_KWQ_CLOSE_REQ_LINKED_WITH_NEXT_SHIFT 7
-#endif
-	u32 cid;
-	u32 reserved2[6];
-};
-
-
-/*
- * The first request to be passed in order to establish connection in option2
- */
-struct l4_kwq_connect_req1 {
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define L4_KWQ_CONNECT_REQ1_RESERVED1 (0xF<<0)
-#define L4_KWQ_CONNECT_REQ1_RESERVED1_SHIFT 0
-#define L4_KWQ_CONNECT_REQ1_LAYER_CODE (0x7<<4)
-#define L4_KWQ_CONNECT_REQ1_LAYER_CODE_SHIFT 4
-#define L4_KWQ_CONNECT_REQ1_LINKED_WITH_NEXT (0x1<<7)
-#define L4_KWQ_CONNECT_REQ1_LINKED_WITH_NEXT_SHIFT 7
-	u8 op_code;
-	u8 reserved0;
-	u8 conn_flags;
-#define L4_KWQ_CONNECT_REQ1_IS_PG_HOST_OPAQUE (0x1<<0)
-#define L4_KWQ_CONNECT_REQ1_IS_PG_HOST_OPAQUE_SHIFT 0
-#define L4_KWQ_CONNECT_REQ1_IP_V6 (0x1<<1)
-#define L4_KWQ_CONNECT_REQ1_IP_V6_SHIFT 1
-#define L4_KWQ_CONNECT_REQ1_PASSIVE_FLAG (0x1<<2)
-#define L4_KWQ_CONNECT_REQ1_PASSIVE_FLAG_SHIFT 2
-#define L4_KWQ_CONNECT_REQ1_RSRV (0x1F<<3)
-#define L4_KWQ_CONNECT_REQ1_RSRV_SHIFT 3
-#elif defined(__LITTLE_ENDIAN)
-	u8 conn_flags;
-#define L4_KWQ_CONNECT_REQ1_IS_PG_HOST_OPAQUE (0x1<<0)
-#define L4_KWQ_CONNECT_REQ1_IS_PG_HOST_OPAQUE_SHIFT 0
-#define L4_KWQ_CONNECT_REQ1_IP_V6 (0x1<<1)
-#define L4_KWQ_CONNECT_REQ1_IP_V6_SHIFT 1
-#define L4_KWQ_CONNECT_REQ1_PASSIVE_FLAG (0x1<<2)
-#define L4_KWQ_CONNECT_REQ1_PASSIVE_FLAG_SHIFT 2
-#define L4_KWQ_CONNECT_REQ1_RSRV (0x1F<<3)
-#define L4_KWQ_CONNECT_REQ1_RSRV_SHIFT 3
-	u8 reserved0;
-	u8 op_code;
-	u8 flags;
-#define L4_KWQ_CONNECT_REQ1_RESERVED1 (0xF<<0)
-#define L4_KWQ_CONNECT_REQ1_RESERVED1_SHIFT 0
-#define L4_KWQ_CONNECT_REQ1_LAYER_CODE (0x7<<4)
-#define L4_KWQ_CONNECT_REQ1_LAYER_CODE_SHIFT 4
-#define L4_KWQ_CONNECT_REQ1_LINKED_WITH_NEXT (0x1<<7)
-#define L4_KWQ_CONNECT_REQ1_LINKED_WITH_NEXT_SHIFT 7
-#endif
-	u32 cid;
-	u32 pg_cid;
-	u32 src_ip;
-	u32 dst_ip;
-#if defined(__BIG_ENDIAN)
-	u16 dst_port;
-	u16 src_port;
-#elif defined(__LITTLE_ENDIAN)
-	u16 src_port;
-	u16 dst_port;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 rsrv1[3];
-	u8 tcp_flags;
-#define L4_KWQ_CONNECT_REQ1_NO_DELAY_ACK (0x1<<0)
-#define L4_KWQ_CONNECT_REQ1_NO_DELAY_ACK_SHIFT 0
-#define L4_KWQ_CONNECT_REQ1_KEEP_ALIVE (0x1<<1)
-#define L4_KWQ_CONNECT_REQ1_KEEP_ALIVE_SHIFT 1
-#define L4_KWQ_CONNECT_REQ1_NAGLE_ENABLE (0x1<<2)
-#define L4_KWQ_CONNECT_REQ1_NAGLE_ENABLE_SHIFT 2
-#define L4_KWQ_CONNECT_REQ1_TIME_STAMP (0x1<<3)
-#define L4_KWQ_CONNECT_REQ1_TIME_STAMP_SHIFT 3
-#define L4_KWQ_CONNECT_REQ1_SACK (0x1<<4)
-#define L4_KWQ_CONNECT_REQ1_SACK_SHIFT 4
-#define L4_KWQ_CONNECT_REQ1_SEG_SCALING (0x1<<5)
-#define L4_KWQ_CONNECT_REQ1_SEG_SCALING_SHIFT 5
-#define L4_KWQ_CONNECT_REQ1_RESERVED2 (0x3<<6)
-#define L4_KWQ_CONNECT_REQ1_RESERVED2_SHIFT 6
-#elif defined(__LITTLE_ENDIAN)
-	u8 tcp_flags;
-#define L4_KWQ_CONNECT_REQ1_NO_DELAY_ACK (0x1<<0)
-#define L4_KWQ_CONNECT_REQ1_NO_DELAY_ACK_SHIFT 0
-#define L4_KWQ_CONNECT_REQ1_KEEP_ALIVE (0x1<<1)
-#define L4_KWQ_CONNECT_REQ1_KEEP_ALIVE_SHIFT 1
-#define L4_KWQ_CONNECT_REQ1_NAGLE_ENABLE (0x1<<2)
-#define L4_KWQ_CONNECT_REQ1_NAGLE_ENABLE_SHIFT 2
-#define L4_KWQ_CONNECT_REQ1_TIME_STAMP (0x1<<3)
-#define L4_KWQ_CONNECT_REQ1_TIME_STAMP_SHIFT 3
-#define L4_KWQ_CONNECT_REQ1_SACK (0x1<<4)
-#define L4_KWQ_CONNECT_REQ1_SACK_SHIFT 4
-#define L4_KWQ_CONNECT_REQ1_SEG_SCALING (0x1<<5)
-#define L4_KWQ_CONNECT_REQ1_SEG_SCALING_SHIFT 5
-#define L4_KWQ_CONNECT_REQ1_RESERVED2 (0x3<<6)
-#define L4_KWQ_CONNECT_REQ1_RESERVED2_SHIFT 6
-	u8 rsrv1[3];
-#endif
-	u32 rsrv2;
-};
-
-
-/*
- * The second ( optional )request to be passed in order to establish
- * connection in option2 - for IPv6 only
- */
-struct l4_kwq_connect_req2 {
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define L4_KWQ_CONNECT_REQ2_RESERVED1 (0xF<<0)
-#define L4_KWQ_CONNECT_REQ2_RESERVED1_SHIFT 0
-#define L4_KWQ_CONNECT_REQ2_LAYER_CODE (0x7<<4)
-#define L4_KWQ_CONNECT_REQ2_LAYER_CODE_SHIFT 4
-#define L4_KWQ_CONNECT_REQ2_LINKED_WITH_NEXT (0x1<<7)
-#define L4_KWQ_CONNECT_REQ2_LINKED_WITH_NEXT_SHIFT 7
-	u8 op_code;
-	u8 reserved0;
-	u8 rsrv;
-#elif defined(__LITTLE_ENDIAN)
-	u8 rsrv;
-	u8 reserved0;
-	u8 op_code;
-	u8 flags;
-#define L4_KWQ_CONNECT_REQ2_RESERVED1 (0xF<<0)
-#define L4_KWQ_CONNECT_REQ2_RESERVED1_SHIFT 0
-#define L4_KWQ_CONNECT_REQ2_LAYER_CODE (0x7<<4)
-#define L4_KWQ_CONNECT_REQ2_LAYER_CODE_SHIFT 4
-#define L4_KWQ_CONNECT_REQ2_LINKED_WITH_NEXT (0x1<<7)
-#define L4_KWQ_CONNECT_REQ2_LINKED_WITH_NEXT_SHIFT 7
-#endif
-	u32 reserved2;
-	u32 src_ip_v6_2;
-	u32 src_ip_v6_3;
-	u32 src_ip_v6_4;
-	u32 dst_ip_v6_2;
-	u32 dst_ip_v6_3;
-	u32 dst_ip_v6_4;
-};
-
-
-/*
- * The third ( and last )request to be passed in order to establish
- * connection in option2
- */
-struct l4_kwq_connect_req3 {
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define L4_KWQ_CONNECT_REQ3_RESERVED1 (0xF<<0)
-#define L4_KWQ_CONNECT_REQ3_RESERVED1_SHIFT 0
-#define L4_KWQ_CONNECT_REQ3_LAYER_CODE (0x7<<4)
-#define L4_KWQ_CONNECT_REQ3_LAYER_CODE_SHIFT 4
-#define L4_KWQ_CONNECT_REQ3_LINKED_WITH_NEXT (0x1<<7)
-#define L4_KWQ_CONNECT_REQ3_LINKED_WITH_NEXT_SHIFT 7
-	u8 op_code;
-	u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved0;
-	u8 op_code;
-	u8 flags;
-#define L4_KWQ_CONNECT_REQ3_RESERVED1 (0xF<<0)
-#define L4_KWQ_CONNECT_REQ3_RESERVED1_SHIFT 0
-#define L4_KWQ_CONNECT_REQ3_LAYER_CODE (0x7<<4)
-#define L4_KWQ_CONNECT_REQ3_LAYER_CODE_SHIFT 4
-#define L4_KWQ_CONNECT_REQ3_LINKED_WITH_NEXT (0x1<<7)
-#define L4_KWQ_CONNECT_REQ3_LINKED_WITH_NEXT_SHIFT 7
-#endif
-	u32 ka_timeout;
-	u32 ka_interval ;
-#if defined(__BIG_ENDIAN)
-	u8 snd_seq_scale;
-	u8 ttl;
-	u8 tos;
-	u8 ka_max_probe_count;
-#elif defined(__LITTLE_ENDIAN)
-	u8 ka_max_probe_count;
-	u8 tos;
-	u8 ttl;
-	u8 snd_seq_scale;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 pmtu;
-	u16 mss;
-#elif defined(__LITTLE_ENDIAN)
-	u16 mss;
-	u16 pmtu;
-#endif
-	u32 rcv_buf;
-	u32 snd_buf;
-	u32 seed;
-};
-
-
-/*
- * a KWQE request to offload a PG connection
- */
-struct l4_kwq_offload_pg {
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define L4_KWQ_OFFLOAD_PG_RESERVED1 (0xF<<0)
-#define L4_KWQ_OFFLOAD_PG_RESERVED1_SHIFT 0
-#define L4_KWQ_OFFLOAD_PG_LAYER_CODE (0x7<<4)
-#define L4_KWQ_OFFLOAD_PG_LAYER_CODE_SHIFT 4
-#define L4_KWQ_OFFLOAD_PG_LINKED_WITH_NEXT (0x1<<7)
-#define L4_KWQ_OFFLOAD_PG_LINKED_WITH_NEXT_SHIFT 7
-	u8 op_code;
-	u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved0;
-	u8 op_code;
-	u8 flags;
-#define L4_KWQ_OFFLOAD_PG_RESERVED1 (0xF<<0)
-#define L4_KWQ_OFFLOAD_PG_RESERVED1_SHIFT 0
-#define L4_KWQ_OFFLOAD_PG_LAYER_CODE (0x7<<4)
-#define L4_KWQ_OFFLOAD_PG_LAYER_CODE_SHIFT 4
-#define L4_KWQ_OFFLOAD_PG_LINKED_WITH_NEXT (0x1<<7)
-#define L4_KWQ_OFFLOAD_PG_LINKED_WITH_NEXT_SHIFT 7
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 l2hdr_nbytes;
-	u8 pg_flags;
-#define L4_KWQ_OFFLOAD_PG_SNAP_ENCAP (0x1<<0)
-#define L4_KWQ_OFFLOAD_PG_SNAP_ENCAP_SHIFT 0
-#define L4_KWQ_OFFLOAD_PG_VLAN_TAGGING (0x1<<1)
-#define L4_KWQ_OFFLOAD_PG_VLAN_TAGGING_SHIFT 1
-#define L4_KWQ_OFFLOAD_PG_RESERVED2 (0x3F<<2)
-#define L4_KWQ_OFFLOAD_PG_RESERVED2_SHIFT 2
-	u8 da0;
-	u8 da1;
-#elif defined(__LITTLE_ENDIAN)
-	u8 da1;
-	u8 da0;
-	u8 pg_flags;
-#define L4_KWQ_OFFLOAD_PG_SNAP_ENCAP (0x1<<0)
-#define L4_KWQ_OFFLOAD_PG_SNAP_ENCAP_SHIFT 0
-#define L4_KWQ_OFFLOAD_PG_VLAN_TAGGING (0x1<<1)
-#define L4_KWQ_OFFLOAD_PG_VLAN_TAGGING_SHIFT 1
-#define L4_KWQ_OFFLOAD_PG_RESERVED2 (0x3F<<2)
-#define L4_KWQ_OFFLOAD_PG_RESERVED2_SHIFT 2
-	u8 l2hdr_nbytes;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 da2;
-	u8 da3;
-	u8 da4;
-	u8 da5;
-#elif defined(__LITTLE_ENDIAN)
-	u8 da5;
-	u8 da4;
-	u8 da3;
-	u8 da2;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 sa0;
-	u8 sa1;
-	u8 sa2;
-	u8 sa3;
-#elif defined(__LITTLE_ENDIAN)
-	u8 sa3;
-	u8 sa2;
-	u8 sa1;
-	u8 sa0;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 sa4;
-	u8 sa5;
-	u16 etype;
-#elif defined(__LITTLE_ENDIAN)
-	u16 etype;
-	u8 sa5;
-	u8 sa4;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 vlan_tag;
-	u16 ipid_start;
-#elif defined(__LITTLE_ENDIAN)
-	u16 ipid_start;
-	u16 vlan_tag;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 ipid_count;
-	u16 reserved3;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved3;
-	u16 ipid_count;
-#endif
-	u32 host_opaque;
-};
-
-
-/*
- * Abortively close the connection request
- */
-struct l4_kwq_reset_req {
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define L4_KWQ_RESET_REQ_RESERVED1 (0xF<<0)
-#define L4_KWQ_RESET_REQ_RESERVED1_SHIFT 0
-#define L4_KWQ_RESET_REQ_LAYER_CODE (0x7<<4)
-#define L4_KWQ_RESET_REQ_LAYER_CODE_SHIFT 4
-#define L4_KWQ_RESET_REQ_LINKED_WITH_NEXT (0x1<<7)
-#define L4_KWQ_RESET_REQ_LINKED_WITH_NEXT_SHIFT 7
-	u8 op_code;
-	u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved0;
-	u8 op_code;
-	u8 flags;
-#define L4_KWQ_RESET_REQ_RESERVED1 (0xF<<0)
-#define L4_KWQ_RESET_REQ_RESERVED1_SHIFT 0
-#define L4_KWQ_RESET_REQ_LAYER_CODE (0x7<<4)
-#define L4_KWQ_RESET_REQ_LAYER_CODE_SHIFT 4
-#define L4_KWQ_RESET_REQ_LINKED_WITH_NEXT (0x1<<7)
-#define L4_KWQ_RESET_REQ_LINKED_WITH_NEXT_SHIFT 7
-#endif
-	u32 cid;
-	u32 reserved2[6];
-};
-
-
-/*
- * a KWQE request to update a PG connection
- */
-struct l4_kwq_update_pg {
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define L4_KWQ_UPDATE_PG_RESERVED1 (0xF<<0)
-#define L4_KWQ_UPDATE_PG_RESERVED1_SHIFT 0
-#define L4_KWQ_UPDATE_PG_LAYER_CODE (0x7<<4)
-#define L4_KWQ_UPDATE_PG_LAYER_CODE_SHIFT 4
-#define L4_KWQ_UPDATE_PG_LINKED_WITH_NEXT (0x1<<7)
-#define L4_KWQ_UPDATE_PG_LINKED_WITH_NEXT_SHIFT 7
-	u8 opcode;
-	u16 oper16;
-#elif defined(__LITTLE_ENDIAN)
-	u16 oper16;
-	u8 opcode;
-	u8 flags;
-#define L4_KWQ_UPDATE_PG_RESERVED1 (0xF<<0)
-#define L4_KWQ_UPDATE_PG_RESERVED1_SHIFT 0
-#define L4_KWQ_UPDATE_PG_LAYER_CODE (0x7<<4)
-#define L4_KWQ_UPDATE_PG_LAYER_CODE_SHIFT 4
-#define L4_KWQ_UPDATE_PG_LINKED_WITH_NEXT (0x1<<7)
-#define L4_KWQ_UPDATE_PG_LINKED_WITH_NEXT_SHIFT 7
-#endif
-	u32 pg_cid;
-	u32 pg_host_opaque;
-#if defined(__BIG_ENDIAN)
-	u8 pg_valids;
-#define L4_KWQ_UPDATE_PG_VALIDS_IPID_COUNT (0x1<<0)
-#define L4_KWQ_UPDATE_PG_VALIDS_IPID_COUNT_SHIFT 0
-#define L4_KWQ_UPDATE_PG_VALIDS_DA (0x1<<1)
-#define L4_KWQ_UPDATE_PG_VALIDS_DA_SHIFT 1
-#define L4_KWQ_UPDATE_PG_RESERVERD2 (0x3F<<2)
-#define L4_KWQ_UPDATE_PG_RESERVERD2_SHIFT 2
-	u8 pg_unused_a;
-	u16 pg_ipid_count;
-#elif defined(__LITTLE_ENDIAN)
-	u16 pg_ipid_count;
-	u8 pg_unused_a;
-	u8 pg_valids;
-#define L4_KWQ_UPDATE_PG_VALIDS_IPID_COUNT (0x1<<0)
-#define L4_KWQ_UPDATE_PG_VALIDS_IPID_COUNT_SHIFT 0
-#define L4_KWQ_UPDATE_PG_VALIDS_DA (0x1<<1)
-#define L4_KWQ_UPDATE_PG_VALIDS_DA_SHIFT 1
-#define L4_KWQ_UPDATE_PG_RESERVERD2 (0x3F<<2)
-#define L4_KWQ_UPDATE_PG_RESERVERD2_SHIFT 2
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 reserverd3;
-	u8 da0;
-	u8 da1;
-#elif defined(__LITTLE_ENDIAN)
-	u8 da1;
-	u8 da0;
-	u16 reserverd3;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 da2;
-	u8 da3;
-	u8 da4;
-	u8 da5;
-#elif defined(__LITTLE_ENDIAN)
-	u8 da5;
-	u8 da4;
-	u8 da3;
-	u8 da2;
-#endif
-	u32 reserved4;
-	u32 reserved5;
-};
-
-
-/*
- * a KWQE request to upload a PG or L4 context
- */
-struct l4_kwq_upload {
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define L4_KWQ_UPLOAD_RESERVED1 (0xF<<0)
-#define L4_KWQ_UPLOAD_RESERVED1_SHIFT 0
-#define L4_KWQ_UPLOAD_LAYER_CODE (0x7<<4)
-#define L4_KWQ_UPLOAD_LAYER_CODE_SHIFT 4
-#define L4_KWQ_UPLOAD_LINKED_WITH_NEXT (0x1<<7)
-#define L4_KWQ_UPLOAD_LINKED_WITH_NEXT_SHIFT 7
-	u8 opcode;
-	u16 oper16;
-#elif defined(__LITTLE_ENDIAN)
-	u16 oper16;
-	u8 opcode;
-	u8 flags;
-#define L4_KWQ_UPLOAD_RESERVED1 (0xF<<0)
-#define L4_KWQ_UPLOAD_RESERVED1_SHIFT 0
-#define L4_KWQ_UPLOAD_LAYER_CODE (0x7<<4)
-#define L4_KWQ_UPLOAD_LAYER_CODE_SHIFT 4
-#define L4_KWQ_UPLOAD_LINKED_WITH_NEXT (0x1<<7)
-#define L4_KWQ_UPLOAD_LINKED_WITH_NEXT_SHIFT 7
-#endif
-	u32 cid;
-	u32 reserved2[6];
-};
-
-/*
- * bnx2x structures
- */
-
-/*
- * The iscsi aggregative context of Cstorm
- */
-struct cstorm_iscsi_ag_context {
-	u32 agg_vars1;
-#define CSTORM_ISCSI_AG_CONTEXT_STATE (0xFF<<0)
-#define CSTORM_ISCSI_AG_CONTEXT_STATE_SHIFT 0
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<8)
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 8
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<9)
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 9
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<10)
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 10
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<11)
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 11
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_SE_CF_EN (0x1<<12)
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_SE_CF_EN_SHIFT 12
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_INV_CF_EN (0x1<<13)
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_INV_CF_EN_SHIFT 13
-#define __CSTORM_ISCSI_AG_CONTEXT_AUX4_CF (0x3<<14)
-#define __CSTORM_ISCSI_AG_CONTEXT_AUX4_CF_SHIFT 14
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED66 (0x3<<16)
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED66_SHIFT 16
-#define __CSTORM_ISCSI_AG_CONTEXT_FIN_RECEIVED_CF_EN (0x1<<18)
-#define __CSTORM_ISCSI_AG_CONTEXT_FIN_RECEIVED_CF_EN_SHIFT 18
-#define __CSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN (0x1<<19)
-#define __CSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN_SHIFT 19
-#define __CSTORM_ISCSI_AG_CONTEXT_AUX2_CF_EN (0x1<<20)
-#define __CSTORM_ISCSI_AG_CONTEXT_AUX2_CF_EN_SHIFT 20
-#define __CSTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<21)
-#define __CSTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 21
-#define __CSTORM_ISCSI_AG_CONTEXT_AUX4_CF_EN (0x1<<22)
-#define __CSTORM_ISCSI_AG_CONTEXT_AUX4_CF_EN_SHIFT 22
-#define __CSTORM_ISCSI_AG_CONTEXT_REL_SEQ_RULE (0x7<<23)
-#define __CSTORM_ISCSI_AG_CONTEXT_REL_SEQ_RULE_SHIFT 23
-#define CSTORM_ISCSI_AG_CONTEXT_HQ_PROD_RULE (0x3<<26)
-#define CSTORM_ISCSI_AG_CONTEXT_HQ_PROD_RULE_SHIFT 26
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED52 (0x3<<28)
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED52_SHIFT 28
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED53 (0x3<<30)
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED53_SHIFT 30
-#if defined(__BIG_ENDIAN)
-	u8 __aux1_th;
-	u8 __aux1_val;
-	u16 __agg_vars2;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_vars2;
-	u8 __aux1_val;
-	u8 __aux1_th;
-#endif
-	u32 rel_seq;
-	u32 rel_seq_th;
-#if defined(__BIG_ENDIAN)
-	u16 hq_cons;
-	u16 hq_prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 hq_prod;
-	u16 hq_cons;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __reserved62;
-	u8 __reserved61;
-	u8 __reserved60;
-	u8 __reserved59;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __reserved59;
-	u8 __reserved60;
-	u8 __reserved61;
-	u8 __reserved62;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __reserved64;
-	u16 cq_u_prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 cq_u_prod;
-	u16 __reserved64;
-#endif
-	u32 __cq_u_prod1;
-#if defined(__BIG_ENDIAN)
-	u16 __agg_vars3;
-	u16 cq_u_pend;
-#elif defined(__LITTLE_ENDIAN)
-	u16 cq_u_pend;
-	u16 __agg_vars3;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __aux2_th;
-	u16 aux2_val;
-#elif defined(__LITTLE_ENDIAN)
-	u16 aux2_val;
-	u16 __aux2_th;
-#endif
-};
-
-/*
- * The fcoe extra aggregative context section of Tstorm
- */
-struct tstorm_fcoe_extra_ag_context_section {
-	u32 __agg_val1;
-#if defined(__BIG_ENDIAN)
-	u8 __tcp_agg_vars2;
-	u8 __agg_val3;
-	u16 __agg_val2;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val2;
-	u8 __agg_val3;
-	u8 __tcp_agg_vars2;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __agg_val5;
-	u8 __agg_val6;
-	u8 __tcp_agg_vars3;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __tcp_agg_vars3;
-	u8 __agg_val6;
-	u16 __agg_val5;
-#endif
-	u32 __lcq_prod;
-	u32 rtt_seq;
-	u32 rtt_time;
-	u32 __reserved66;
-	u32 wnd_right_edge;
-	u32 tcp_agg_vars1;
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<0)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 0
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG (0x1<<1)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG_SHIFT 1
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF (0x3<<2)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_SHIFT 2
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF (0x3<<4)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_SHIFT 4
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_EN (0x1<<6)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_EN_SHIFT 6
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_EN (0x1<<7)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_EN_SHIFT 7
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN (0x1<<8)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN_SHIFT 8
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LCQ_SND_EN (0x1<<9)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LCQ_SND_EN_SHIFT 9
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<10)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 10
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_FLAG (0x1<<11)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_FLAG_SHIFT 11
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_EN (0x1<<12)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_EN_SHIFT 12
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_EN (0x1<<13)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_EN_SHIFT 13
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF (0x3<<14)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_SHIFT 14
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF (0x3<<16)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_SHIFT 16
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_BLOCKED (0x1<<18)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_BLOCKED_SHIFT 18
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<19)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 19
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX11_CF_EN (0x1<<20)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX11_CF_EN_SHIFT 20
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX12_CF_EN (0x1<<21)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX12_CF_EN_SHIFT 21
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED1 (0x3<<22)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED1_SHIFT 22
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ (0xF<<24)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ_SHIFT 24
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ (0xF<<28)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ_SHIFT 28
-	u32 snd_max;
-	u32 __lcq_cons;
-	u32 __reserved2;
-};
-
-/*
- * The fcoe aggregative context of Tstorm
- */
-struct tstorm_fcoe_ag_context {
-#if defined(__BIG_ENDIAN)
-	u16 ulp_credit;
-	u8 agg_vars1;
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF (0x3<<4)
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_SHIFT 4
-#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG (0x1<<6)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG (0x1<<7)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG_SHIFT 7
-	u8 state;
-#elif defined(__LITTLE_ENDIAN)
-	u8 state;
-	u8 agg_vars1;
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF (0x3<<4)
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_SHIFT 4
-#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG (0x1<<6)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG (0x1<<7)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG_SHIFT 7
-	u16 ulp_credit;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __agg_val4;
-	u16 agg_vars2;
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG (0x1<<0)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG_SHIFT 0
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG (0x1<<1)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG_SHIFT 1
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF (0x3<<2)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF_SHIFT 2
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF (0x3<<4)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF_SHIFT 4
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF (0x3<<6)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF_SHIFT 6
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF (0x3<<8)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF_SHIFT 8
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG (0x1<<10)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN (0x1<<11)
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN_SHIFT 11
-#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
-#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
-#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
-#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
-#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
-#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
-#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
-#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
-#elif defined(__LITTLE_ENDIAN)
-	u16 agg_vars2;
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG (0x1<<0)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG_SHIFT 0
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG (0x1<<1)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG_SHIFT 1
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF (0x3<<2)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF_SHIFT 2
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF (0x3<<4)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF_SHIFT 4
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF (0x3<<6)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF_SHIFT 6
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF (0x3<<8)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF_SHIFT 8
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG (0x1<<10)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN (0x1<<11)
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN_SHIFT 11
-#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
-#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
-#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
-#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
-#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
-#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
-#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
-#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
-	u16 __agg_val4;
-#endif
-	struct tstorm_fcoe_extra_ag_context_section __extra_section;
-};
-
-
-
-/*
- * The tcp aggregative context section of Tstorm
- */
-struct tstorm_tcp_tcp_ag_context_section {
-	u32 __agg_val1;
-#if defined(__BIG_ENDIAN)
-	u8 __tcp_agg_vars2;
-	u8 __agg_val3;
-	u16 __agg_val2;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val2;
-	u8 __agg_val3;
-	u8 __tcp_agg_vars2;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __agg_val5;
-	u8 __agg_val6;
-	u8 __tcp_agg_vars3;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __tcp_agg_vars3;
-	u8 __agg_val6;
-	u16 __agg_val5;
-#endif
-	u32 snd_nxt;
-	u32 rtt_seq;
-	u32 rtt_time;
-	u32 __reserved66;
-	u32 wnd_right_edge;
-	u32 tcp_agg_vars1;
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<0)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 0
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG (0x1<<1)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG_SHIFT 1
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF (0x3<<2)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_SHIFT 2
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF (0x3<<4)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_SHIFT 4
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_EN (0x1<<6)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_EN_SHIFT 6
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_EN (0x1<<7)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_EN_SHIFT 7
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN (0x1<<8)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN_SHIFT 8
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_SND_NXT_EN (0x1<<9)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_SND_NXT_EN_SHIFT 9
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<10)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 10
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_FLAG (0x1<<11)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_FLAG_SHIFT 11
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_EN (0x1<<12)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_EN_SHIFT 12
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_EN (0x1<<13)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_EN_SHIFT 13
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF (0x3<<14)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_SHIFT 14
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF (0x3<<16)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_SHIFT 16
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_BLOCKED (0x1<<18)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_BLOCKED_SHIFT 18
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<19)
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 19
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_EN (0x1<<20)
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_EN_SHIFT 20
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_EN (0x1<<21)
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_EN_SHIFT 21
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED1 (0x3<<22)
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED1_SHIFT 22
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ (0xF<<24)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ_SHIFT 24
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ (0xF<<28)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ_SHIFT 28
-	u32 snd_max;
-	u32 snd_una;
-	u32 __reserved2;
-};
-
-/*
- * The iscsi aggregative context of Tstorm
- */
-struct tstorm_iscsi_ag_context {
-#if defined(__BIG_ENDIAN)
-	u16 ulp_credit;
-	u8 agg_vars1;
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
-#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
-	u8 state;
-#elif defined(__LITTLE_ENDIAN)
-	u8 state;
-	u8 agg_vars1;
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
-#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
-	u16 ulp_credit;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __agg_val4;
-	u16 agg_vars2;
-#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
-#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
-#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
-#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
-#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
-#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
-#elif defined(__LITTLE_ENDIAN)
-	u16 agg_vars2;
-#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
-#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
-#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
-#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
-#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
-#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
-	u16 __agg_val4;
-#endif
-	struct tstorm_tcp_tcp_ag_context_section tcp;
-};
-
-
-
-/*
- * The fcoe aggregative context of Ustorm
- */
-struct ustorm_fcoe_ag_context {
-#if defined(__BIG_ENDIAN)
-	u8 __aux_counter_flags;
-	u8 agg_vars2;
-#define USTORM_FCOE_AG_CONTEXT_TX_CF (0x3<<0)
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_SHIFT 0
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF (0x3<<2)
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_SHIFT 2
-#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
-#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
-	u8 agg_vars1;
-#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define USTORM_FCOE_AG_CONTEXT_INV_CF (0x3<<4)
-#define USTORM_FCOE_AG_CONTEXT_INV_CF_SHIFT 4
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF (0x3<<6)
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_SHIFT 6
-	u8 state;
-#elif defined(__LITTLE_ENDIAN)
-	u8 state;
-	u8 agg_vars1;
-#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define USTORM_FCOE_AG_CONTEXT_INV_CF (0x3<<4)
-#define USTORM_FCOE_AG_CONTEXT_INV_CF_SHIFT 4
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF (0x3<<6)
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_SHIFT 6
-	u8 agg_vars2;
-#define USTORM_FCOE_AG_CONTEXT_TX_CF (0x3<<0)
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_SHIFT 0
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF (0x3<<2)
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_SHIFT 2
-#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
-#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
-	u8 __aux_counter_flags;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 cdu_usage;
-	u8 agg_misc2;
-	u16 pbf_tx_seq_ack;
-#elif defined(__LITTLE_ENDIAN)
-	u16 pbf_tx_seq_ack;
-	u8 agg_misc2;
-	u8 cdu_usage;
-#endif
-	u32 agg_misc4;
-#if defined(__BIG_ENDIAN)
-	u8 agg_val3_th;
-	u8 agg_val3;
-	u16 agg_misc3;
-#elif defined(__LITTLE_ENDIAN)
-	u16 agg_misc3;
-	u8 agg_val3;
-	u8 agg_val3_th;
-#endif
-	u32 expired_task_id;
-	u32 agg_misc4_th;
-#if defined(__BIG_ENDIAN)
-	u16 cq_prod;
-	u16 cq_cons;
-#elif defined(__LITTLE_ENDIAN)
-	u16 cq_cons;
-	u16 cq_prod;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __reserved2;
-	u8 decision_rules;
-#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE (0x7<<0)
-#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE_SHIFT 0
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG (0x1<<6)
-#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG_SHIFT 6
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED1 (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED1_SHIFT 7
-	u8 decision_rule_enable_bits;
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN (0x1<<0)
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN_SHIFT 0
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN (0x1<<2)
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN_SHIFT 2
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
-#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<4)
-#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 4
-#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN (0x1<<5)
-#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN_SHIFT 5
-#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
-#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
-#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
-#elif defined(__LITTLE_ENDIAN)
-	u8 decision_rule_enable_bits;
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN (0x1<<0)
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN_SHIFT 0
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN (0x1<<2)
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN_SHIFT 2
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
-#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<4)
-#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 4
-#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN (0x1<<5)
-#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN_SHIFT 5
-#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
-#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
-#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
-	u8 decision_rules;
-#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE (0x7<<0)
-#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE_SHIFT 0
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG (0x1<<6)
-#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG_SHIFT 6
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED1 (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED1_SHIFT 7
-	u16 __reserved2;
-#endif
-};
-
-
-/*
- * The iscsi aggregative context of Ustorm
- */
-struct ustorm_iscsi_ag_context {
-#if defined(__BIG_ENDIAN)
-	u8 __aux_counter_flags;
-	u8 agg_vars2;
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF (0x3<<0)
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_SHIFT 0
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF (0x3<<2)
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_SHIFT 2
-#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
-	u8 agg_vars1;
-#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF (0x3<<4)
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_SHIFT 4
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF (0x3<<6)
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_SHIFT 6
-	u8 state;
-#elif defined(__LITTLE_ENDIAN)
-	u8 state;
-	u8 agg_vars1;
-#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF (0x3<<4)
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_SHIFT 4
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF (0x3<<6)
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_SHIFT 6
-	u8 agg_vars2;
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF (0x3<<0)
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_SHIFT 0
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF (0x3<<2)
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_SHIFT 2
-#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
-	u8 __aux_counter_flags;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 cdu_usage;
-	u8 agg_misc2;
-	u16 __cq_local_comp_itt_val;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __cq_local_comp_itt_val;
-	u8 agg_misc2;
-	u8 cdu_usage;
-#endif
-	u32 agg_misc4;
-#if defined(__BIG_ENDIAN)
-	u8 agg_val3_th;
-	u8 agg_val3;
-	u16 agg_misc3;
-#elif defined(__LITTLE_ENDIAN)
-	u16 agg_misc3;
-	u8 agg_val3;
-	u8 agg_val3_th;
-#endif
-	u32 agg_val1;
-	u32 agg_misc4_th;
-#if defined(__BIG_ENDIAN)
-	u16 agg_val2_th;
-	u16 agg_val2;
-#elif defined(__LITTLE_ENDIAN)
-	u16 agg_val2;
-	u16 agg_val2_th;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __reserved2;
-	u8 decision_rules;
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE (0x7<<0)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
-#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
-	u8 decision_rule_enable_bits;
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN (0x1<<0)
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN_SHIFT 0
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN (0x1<<2)
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN_SHIFT 2
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
-#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN (0x1<<4)
-#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN_SHIFT 4
-#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<5)
-#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 5
-#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
-#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
-#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
-#elif defined(__LITTLE_ENDIAN)
-	u8 decision_rule_enable_bits;
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN (0x1<<0)
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN_SHIFT 0
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN (0x1<<2)
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN_SHIFT 2
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
-#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN (0x1<<4)
-#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN_SHIFT 4
-#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<5)
-#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 5
-#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
-#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
-#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
-	u8 decision_rules;
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE (0x7<<0)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
-#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
-	u16 __reserved2;
-#endif
-};
-
-
-/*
- * The fcoe aggregative context section of Xstorm
- */
-struct xstorm_fcoe_extra_ag_context_section {
-#if defined(__BIG_ENDIAN)
-	u8 tcp_agg_vars1;
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED51 (0x3<<0)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED51_SHIFT 0
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF (0x3<<4)
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_SHIFT 4
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN (0x1<<6)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN_SHIFT 6
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG (0x1<<7)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG_SHIFT 7
-	u8 __reserved_da_cnt;
-	u16 __mtu;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __mtu;
-	u8 __reserved_da_cnt;
-	u8 tcp_agg_vars1;
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED51 (0x3<<0)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED51_SHIFT 0
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF (0x3<<4)
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_SHIFT 4
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN (0x1<<6)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN_SHIFT 6
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG (0x1<<7)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG_SHIFT 7
-#endif
-	u32 snd_nxt;
-	u32 tx_wnd;
-	u32 __reserved55;
-	u32 local_adv_wnd;
-#if defined(__BIG_ENDIAN)
-	u8 __agg_val8_th;
-	u8 __tx_dest;
-	u16 tcp_agg_vars2;
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57 (0x1<<0)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57_SHIFT 0
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED58 (0x1<<1)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED58_SHIFT 1
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED59 (0x1<<2)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED59_SHIFT 2
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX3_FLAG (0x1<<3)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX3_FLAG_SHIFT 3
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX4_FLAG (0x1<<4)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX4_FLAG_SHIFT 4
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED60 (0x1<<5)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED60_SHIFT 5
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN (0x1<<6)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN_SHIFT 6
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN (0x1<<7)
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN_SHIFT 7
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN (0x1<<8)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN_SHIFT 8
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 9
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SET_RTO_CF (0x3<<10)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF (0x3<<14)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_SHIFT 14
-#elif defined(__LITTLE_ENDIAN)
-	u16 tcp_agg_vars2;
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57 (0x1<<0)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57_SHIFT 0
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED58 (0x1<<1)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED58_SHIFT 1
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED59 (0x1<<2)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED59_SHIFT 2
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX3_FLAG (0x1<<3)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX3_FLAG_SHIFT 3
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX4_FLAG (0x1<<4)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX4_FLAG_SHIFT 4
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED60 (0x1<<5)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED60_SHIFT 5
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN (0x1<<6)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN_SHIFT 6
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN (0x1<<7)
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN_SHIFT 7
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN (0x1<<8)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN_SHIFT 8
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 9
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SET_RTO_CF (0x3<<10)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF (0x3<<14)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_SHIFT 14
-	u8 __tx_dest;
-	u8 __agg_val8_th;
-#endif
-	u32 __sq_base_addr_lo;
-	u32 __sq_base_addr_hi;
-	u32 __xfrq_base_addr_lo;
-	u32 __xfrq_base_addr_hi;
-#if defined(__BIG_ENDIAN)
-	u16 __xfrq_cons;
-	u16 __xfrq_prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __xfrq_prod;
-	u16 __xfrq_cons;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __tcp_agg_vars5;
-	u8 __tcp_agg_vars4;
-	u8 __tcp_agg_vars3;
-	u8 __reserved_force_pure_ack_cnt;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __reserved_force_pure_ack_cnt;
-	u8 __tcp_agg_vars3;
-	u8 __tcp_agg_vars4;
-	u8 __tcp_agg_vars5;
-#endif
-	u32 __tcp_agg_vars6;
-#if defined(__BIG_ENDIAN)
-	u16 __agg_misc6;
-	u16 __tcp_agg_vars7;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __tcp_agg_vars7;
-	u16 __agg_misc6;
-#endif
-	u32 __agg_val10;
-	u32 __agg_val10_th;
-#if defined(__BIG_ENDIAN)
-	u16 __reserved3;
-	u8 __reserved2;
-	u8 __da_only_cnt;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __da_only_cnt;
-	u8 __reserved2;
-	u16 __reserved3;
-#endif
-};
-
-/*
- * The fcoe aggregative context of Xstorm
- */
-struct xstorm_fcoe_ag_context {
-#if defined(__BIG_ENDIAN)
-	u16 agg_val1;
-	u8 agg_vars1;
-#define __XSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __XSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define __XSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define __XSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define __XSTORM_FCOE_AG_CONTEXT_RESERVED51 (0x1<<2)
-#define __XSTORM_FCOE_AG_CONTEXT_RESERVED51_SHIFT 2
-#define __XSTORM_FCOE_AG_CONTEXT_RESERVED52 (0x1<<3)
-#define __XSTORM_FCOE_AG_CONTEXT_RESERVED52_SHIFT 3
-#define __XSTORM_FCOE_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
-#define __XSTORM_FCOE_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
-#define XSTORM_FCOE_AG_CONTEXT_NAGLE_EN (0x1<<5)
-#define XSTORM_FCOE_AG_CONTEXT_NAGLE_EN_SHIFT 5
-#define __XSTORM_FCOE_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
-#define __XSTORM_FCOE_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
-#define __XSTORM_FCOE_AG_CONTEXT_RESERVED_UNA_GT_NXT_EN (0x1<<7)
-#define __XSTORM_FCOE_AG_CONTEXT_RESERVED_UNA_GT_NXT_EN_SHIFT 7
-	u8 __state;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __state;
-	u8 agg_vars1;
-#define __XSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __XSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define __XSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define __XSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define __XSTORM_FCOE_AG_CONTEXT_RESERVED51 (0x1<<2)
-#define __XSTORM_FCOE_AG_CONTEXT_RESERVED51_SHIFT 2
-#define __XSTORM_FCOE_AG_CONTEXT_RESERVED52 (0x1<<3)
-#define __XSTORM_FCOE_AG_CONTEXT_RESERVED52_SHIFT 3
-#define __XSTORM_FCOE_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
-#define __XSTORM_FCOE_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
-#define XSTORM_FCOE_AG_CONTEXT_NAGLE_EN (0x1<<5)
-#define XSTORM_FCOE_AG_CONTEXT_NAGLE_EN_SHIFT 5
-#define __XSTORM_FCOE_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
-#define __XSTORM_FCOE_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
-#define __XSTORM_FCOE_AG_CONTEXT_RESERVED_UNA_GT_NXT_EN (0x1<<7)
-#define __XSTORM_FCOE_AG_CONTEXT_RESERVED_UNA_GT_NXT_EN_SHIFT 7
-	u16 agg_val1;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 cdu_reserved;
-	u8 __agg_vars4;
-	u8 agg_vars3;
-#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
-#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
-#define __XSTORM_FCOE_AG_CONTEXT_AUX19_CF (0x3<<6)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX19_CF_SHIFT 6
-	u8 agg_vars2;
-#define __XSTORM_FCOE_AG_CONTEXT_DQ_CF (0x3<<0)
-#define __XSTORM_FCOE_AG_CONTEXT_DQ_CF_SHIFT 0
-#define __XSTORM_FCOE_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
-#define __XSTORM_FCOE_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
-#define __XSTORM_FCOE_AG_CONTEXT_AUX8_FLAG (0x1<<3)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX8_FLAG_SHIFT 3
-#define __XSTORM_FCOE_AG_CONTEXT_AUX9_FLAG (0x1<<4)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX9_FLAG_SHIFT 4
-#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
-#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE1_SHIFT 5
-#define __XSTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __XSTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
-#elif defined(__LITTLE_ENDIAN)
-	u8 agg_vars2;
-#define __XSTORM_FCOE_AG_CONTEXT_DQ_CF (0x3<<0)
-#define __XSTORM_FCOE_AG_CONTEXT_DQ_CF_SHIFT 0
-#define __XSTORM_FCOE_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
-#define __XSTORM_FCOE_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
-#define __XSTORM_FCOE_AG_CONTEXT_AUX8_FLAG (0x1<<3)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX8_FLAG_SHIFT 3
-#define __XSTORM_FCOE_AG_CONTEXT_AUX9_FLAG (0x1<<4)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX9_FLAG_SHIFT 4
-#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
-#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE1_SHIFT 5
-#define __XSTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __XSTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
-	u8 agg_vars3;
-#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
-#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
-#define __XSTORM_FCOE_AG_CONTEXT_AUX19_CF (0x3<<6)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX19_CF_SHIFT 6
-	u8 __agg_vars4;
-	u8 cdu_reserved;
-#endif
-	u32 more_to_send;
-#if defined(__BIG_ENDIAN)
-	u16 agg_vars5;
-#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
-#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE5_SHIFT 0
-#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
-#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
-#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
-#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
-#define __XSTORM_FCOE_AG_CONTEXT_CONFQ_DEC_RULE (0x3<<14)
-#define __XSTORM_FCOE_AG_CONTEXT_CONFQ_DEC_RULE_SHIFT 14
-	u16 sq_cons;
-#elif defined(__LITTLE_ENDIAN)
-	u16 sq_cons;
-	u16 agg_vars5;
-#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
-#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE5_SHIFT 0
-#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
-#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
-#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
-#define XSTORM_FCOE_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
-#define __XSTORM_FCOE_AG_CONTEXT_CONFQ_DEC_RULE (0x3<<14)
-#define __XSTORM_FCOE_AG_CONTEXT_CONFQ_DEC_RULE_SHIFT 14
-#endif
-	struct xstorm_fcoe_extra_ag_context_section __extra_section;
-#if defined(__BIG_ENDIAN)
-	u16 agg_vars7;
-#define __XSTORM_FCOE_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
-#define __XSTORM_FCOE_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
-#define __XSTORM_FCOE_AG_CONTEXT_AUX13_FLAG (0x1<<3)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX13_FLAG_SHIFT 3
-#define __XSTORM_FCOE_AG_CONTEXT_QUEUE0_CF (0x3<<4)
-#define __XSTORM_FCOE_AG_CONTEXT_QUEUE0_CF_SHIFT 4
-#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
-#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE3_SHIFT 6
-#define XSTORM_FCOE_AG_CONTEXT_AUX1_CF (0x3<<8)
-#define XSTORM_FCOE_AG_CONTEXT_AUX1_CF_SHIFT 8
-#define __XSTORM_FCOE_AG_CONTEXT_RESERVED62 (0x1<<10)
-#define __XSTORM_FCOE_AG_CONTEXT_RESERVED62_SHIFT 10
-#define __XSTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
-#define __XSTORM_FCOE_AG_CONTEXT_AUX10_FLAG (0x1<<12)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX10_FLAG_SHIFT 12
-#define __XSTORM_FCOE_AG_CONTEXT_AUX11_FLAG (0x1<<13)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX11_FLAG_SHIFT 13
-#define __XSTORM_FCOE_AG_CONTEXT_AUX12_FLAG (0x1<<14)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX12_FLAG_SHIFT 14
-#define __XSTORM_FCOE_AG_CONTEXT_AUX2_FLAG (0x1<<15)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX2_FLAG_SHIFT 15
-	u8 agg_val3_th;
-	u8 agg_vars6;
-#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
-#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE6_SHIFT 0
-#define __XSTORM_FCOE_AG_CONTEXT_XFRQ_DEC_RULE (0x7<<3)
-#define __XSTORM_FCOE_AG_CONTEXT_XFRQ_DEC_RULE_SHIFT 3
-#define __XSTORM_FCOE_AG_CONTEXT_SQ_DEC_RULE (0x3<<6)
-#define __XSTORM_FCOE_AG_CONTEXT_SQ_DEC_RULE_SHIFT 6
-#elif defined(__LITTLE_ENDIAN)
-	u8 agg_vars6;
-#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
-#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE6_SHIFT 0
-#define __XSTORM_FCOE_AG_CONTEXT_XFRQ_DEC_RULE (0x7<<3)
-#define __XSTORM_FCOE_AG_CONTEXT_XFRQ_DEC_RULE_SHIFT 3
-#define __XSTORM_FCOE_AG_CONTEXT_SQ_DEC_RULE (0x3<<6)
-#define __XSTORM_FCOE_AG_CONTEXT_SQ_DEC_RULE_SHIFT 6
-	u8 agg_val3_th;
-	u16 agg_vars7;
-#define __XSTORM_FCOE_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
-#define __XSTORM_FCOE_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
-#define __XSTORM_FCOE_AG_CONTEXT_AUX13_FLAG (0x1<<3)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX13_FLAG_SHIFT 3
-#define __XSTORM_FCOE_AG_CONTEXT_QUEUE0_CF (0x3<<4)
-#define __XSTORM_FCOE_AG_CONTEXT_QUEUE0_CF_SHIFT 4
-#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
-#define XSTORM_FCOE_AG_CONTEXT_DECISION_RULE3_SHIFT 6
-#define XSTORM_FCOE_AG_CONTEXT_AUX1_CF (0x3<<8)
-#define XSTORM_FCOE_AG_CONTEXT_AUX1_CF_SHIFT 8
-#define __XSTORM_FCOE_AG_CONTEXT_RESERVED62 (0x1<<10)
-#define __XSTORM_FCOE_AG_CONTEXT_RESERVED62_SHIFT 10
-#define __XSTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
-#define __XSTORM_FCOE_AG_CONTEXT_AUX10_FLAG (0x1<<12)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX10_FLAG_SHIFT 12
-#define __XSTORM_FCOE_AG_CONTEXT_AUX11_FLAG (0x1<<13)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX11_FLAG_SHIFT 13
-#define __XSTORM_FCOE_AG_CONTEXT_AUX12_FLAG (0x1<<14)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX12_FLAG_SHIFT 14
-#define __XSTORM_FCOE_AG_CONTEXT_AUX2_FLAG (0x1<<15)
-#define __XSTORM_FCOE_AG_CONTEXT_AUX2_FLAG_SHIFT 15
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __agg_val11_th;
-	u16 __agg_val11;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val11;
-	u16 __agg_val11_th;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __reserved1;
-	u8 __agg_val6_th;
-	u16 __agg_val9;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val9;
-	u8 __agg_val6_th;
-	u8 __reserved1;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 confq_cons;
-	u16 confq_prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 confq_prod;
-	u16 confq_cons;
-#endif
-	u32 agg_vars8;
-#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC2 (0xFFFFFF<<0)
-#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC2_SHIFT 0
-#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC3 (0xFF<<24)
-#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC3_SHIFT 24
-#if defined(__BIG_ENDIAN)
-	u16 agg_misc0;
-	u16 sq_prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 sq_prod;
-	u16 agg_misc0;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 agg_val3;
-	u8 agg_val6;
-	u8 agg_val5_th;
-	u8 agg_val5;
-#elif defined(__LITTLE_ENDIAN)
-	u8 agg_val5;
-	u8 agg_val5_th;
-	u8 agg_val6;
-	u8 agg_val3;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __agg_misc1;
-	u16 agg_limit1;
-#elif defined(__LITTLE_ENDIAN)
-	u16 agg_limit1;
-	u16 __agg_misc1;
-#endif
-	u32 completion_seq;
-	u32 confq_pbl_base_lo;
-	u32 confq_pbl_base_hi;
-};
-
-
-
-/*
- * The tcp aggregative context section of Xstorm
- */
-struct xstorm_tcp_tcp_ag_context_section {
-#if defined(__BIG_ENDIAN)
-	u8 tcp_agg_vars1;
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_DA_TIMER_CF (0x3<<0)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_DA_TIMER_CF_SHIFT 0
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF (0x3<<4)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_SHIFT 4
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CLEAR_DA_TIMER_EN (0x1<<6)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CLEAR_DA_TIMER_EN_SHIFT 6
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_EXPIRATION_FLAG (0x1<<7)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_EXPIRATION_FLAG_SHIFT 7
-	u8 __da_cnt;
-	u16 mss;
-#elif defined(__LITTLE_ENDIAN)
-	u16 mss;
-	u8 __da_cnt;
-	u8 tcp_agg_vars1;
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_DA_TIMER_CF (0x3<<0)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_DA_TIMER_CF_SHIFT 0
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF (0x3<<4)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_SHIFT 4
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CLEAR_DA_TIMER_EN (0x1<<6)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CLEAR_DA_TIMER_EN_SHIFT 6
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_EXPIRATION_FLAG (0x1<<7)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_EXPIRATION_FLAG_SHIFT 7
-#endif
-	u32 snd_nxt;
-	u32 tx_wnd;
-	u32 snd_una;
-	u32 local_adv_wnd;
-#if defined(__BIG_ENDIAN)
-	u8 __agg_val8_th;
-	u8 __tx_dest;
-	u16 tcp_agg_vars2;
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG (0x1<<0)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_SHIFT 0
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED (0x1<<1)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED_SHIFT 1
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE (0x1<<2)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE_SHIFT 2
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG (0x1<<3)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG_SHIFT 3
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG (0x1<<4)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG_SHIFT 4
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE (0x1<<5)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE_SHIFT 5
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN (0x1<<6)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN_SHIFT 6
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN (0x1<<7)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN_SHIFT 7
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN (0x1<<8)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN_SHIFT 8
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 9
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF (0x3<<10)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF (0x3<<14)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_SHIFT 14
-#elif defined(__LITTLE_ENDIAN)
-	u16 tcp_agg_vars2;
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG (0x1<<0)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_SHIFT 0
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED (0x1<<1)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED_SHIFT 1
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE (0x1<<2)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE_SHIFT 2
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG (0x1<<3)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG_SHIFT 3
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG (0x1<<4)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG_SHIFT 4
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE (0x1<<5)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE_SHIFT 5
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN (0x1<<6)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN_SHIFT 6
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN (0x1<<7)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN_SHIFT 7
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN (0x1<<8)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN_SHIFT 8
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 9
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF (0x3<<10)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF (0x3<<14)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_SHIFT 14
-	u8 __tx_dest;
-	u8 __agg_val8_th;
-#endif
-	u32 ack_to_far_end;
-	u32 rto_timer;
-	u32 ka_timer;
-	u32 ts_to_echo;
-#if defined(__BIG_ENDIAN)
-	u16 __agg_val7_th;
-	u16 __agg_val7;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val7;
-	u16 __agg_val7_th;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __tcp_agg_vars5;
-	u8 __tcp_agg_vars4;
-	u8 __tcp_agg_vars3;
-	u8 __force_pure_ack_cnt;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __force_pure_ack_cnt;
-	u8 __tcp_agg_vars3;
-	u8 __tcp_agg_vars4;
-	u8 __tcp_agg_vars5;
-#endif
-	u32 tcp_agg_vars6;
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_CF_EN (0x1<<0)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_CF_EN_SHIFT 0
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_EN (0x1<<1)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_EN_SHIFT 1
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_EN (0x1<<2)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_EN_SHIFT 2
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<3)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 3
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX6_FLAG (0x1<<4)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX6_FLAG_SHIFT 4
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX7_FLAG (0x1<<5)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX7_FLAG_SHIFT 5
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX5_CF (0x3<<6)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX5_CF_SHIFT 6
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF (0x3<<8)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_SHIFT 8
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF (0x3<<10)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_SHIFT 10
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF (0x3<<12)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_SHIFT 12
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF (0x3<<14)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_SHIFT 14
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX13_CF (0x3<<16)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX13_CF_SHIFT 16
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX14_CF (0x3<<18)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX14_CF_SHIFT 18
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX15_CF (0x3<<20)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX15_CF_SHIFT 20
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX16_CF (0x3<<22)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX16_CF_SHIFT 22
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX17_CF (0x3<<24)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX17_CF_SHIFT 24
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ECE_FLAG (0x1<<26)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ECE_FLAG_SHIFT 26
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED71 (0x1<<27)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED71_SHIFT 27
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_FORCE_PURE_ACK_CNT_DIRTY (0x1<<28)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_FORCE_PURE_ACK_CNT_DIRTY_SHIFT 28
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TCP_AUTO_STOP_FLAG (0x1<<29)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TCP_AUTO_STOP_FLAG_SHIFT 29
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DO_TS_UPDATE_FLAG (0x1<<30)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DO_TS_UPDATE_FLAG_SHIFT 30
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CANCEL_RETRANSMIT_FLAG (0x1<<31)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CANCEL_RETRANSMIT_FLAG_SHIFT 31
-#if defined(__BIG_ENDIAN)
-	u16 __agg_misc6;
-	u16 __tcp_agg_vars7;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __tcp_agg_vars7;
-	u16 __agg_misc6;
-#endif
-	u32 __agg_val10;
-	u32 __agg_val10_th;
-#if defined(__BIG_ENDIAN)
-	u16 __reserved3;
-	u8 __reserved2;
-	u8 __da_only_cnt;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __da_only_cnt;
-	u8 __reserved2;
-	u16 __reserved3;
-#endif
-};
-
-/*
- * The iscsi aggregative context of Xstorm
- */
-struct xstorm_iscsi_ag_context {
-#if defined(__BIG_ENDIAN)
-	u16 agg_val1;
-	u8 agg_vars1;
-#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN (0x1<<5)
-#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN_SHIFT 5
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
-#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
-#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
-	u8 state;
-#elif defined(__LITTLE_ENDIAN)
-	u8 state;
-	u8 agg_vars1;
-#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN (0x1<<5)
-#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN_SHIFT 5
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
-#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
-#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
-	u16 agg_val1;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 cdu_reserved;
-	u8 __agg_vars4;
-	u8 agg_vars3;
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
-	u8 agg_vars2;
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF (0x3<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG (0x1<<3)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG (0x1<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1_SHIFT 5
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
-#elif defined(__LITTLE_ENDIAN)
-	u8 agg_vars2;
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF (0x3<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG (0x1<<3)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG (0x1<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1_SHIFT 5
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
-	u8 agg_vars3;
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
-	u8 __agg_vars4;
-	u8 cdu_reserved;
-#endif
-	u32 more_to_send;
-#if defined(__BIG_ENDIAN)
-	u16 agg_vars5;
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2_SHIFT 14
-	u16 sq_cons;
-#elif defined(__LITTLE_ENDIAN)
-	u16 sq_cons;
-	u16 agg_vars5;
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2_SHIFT 14
-#endif
-	struct xstorm_tcp_tcp_ag_context_section tcp;
-#if defined(__BIG_ENDIAN)
-	u16 agg_vars7;
-#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG (0x1<<3)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3_SHIFT 6
-#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF (0x3<<8)
-#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_SHIFT 8
-#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
-#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG (0x1<<12)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG_SHIFT 12
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG (0x1<<13)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG_SHIFT 13
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG (0x1<<14)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG_SHIFT 14
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
-	u8 agg_val3_th;
-	u8 agg_vars6;
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7_SHIFT 3
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4_SHIFT 6
-#elif defined(__LITTLE_ENDIAN)
-	u8 agg_vars6;
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7_SHIFT 3
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4_SHIFT 6
-	u8 agg_val3_th;
-	u16 agg_vars7;
-#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG (0x1<<3)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3_SHIFT 6
-#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF (0x3<<8)
-#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_SHIFT 8
-#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
-#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG (0x1<<12)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG_SHIFT 12
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG (0x1<<13)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG_SHIFT 13
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG (0x1<<14)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG_SHIFT 14
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __agg_val11_th;
-	u16 __gen_data;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __gen_data;
-	u16 __agg_val11_th;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __reserved1;
-	u8 __agg_val6_th;
-	u16 __agg_val9;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val9;
-	u8 __agg_val6_th;
-	u8 __reserved1;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 hq_prod;
-	u16 hq_cons;
-#elif defined(__LITTLE_ENDIAN)
-	u16 hq_cons;
-	u16 hq_prod;
-#endif
-	u32 agg_vars8;
-#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC2 (0xFFFFFF<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC2_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC3 (0xFF<<24)
-#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC3_SHIFT 24
-#if defined(__BIG_ENDIAN)
-	u16 r2tq_prod;
-	u16 sq_prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 sq_prod;
-	u16 r2tq_prod;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 agg_val3;
-	u8 agg_val6;
-	u8 agg_val5_th;
-	u8 agg_val5;
-#elif defined(__LITTLE_ENDIAN)
-	u8 agg_val5;
-	u8 agg_val5_th;
-	u8 agg_val6;
-	u8 agg_val3;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __agg_misc1;
-	u16 agg_limit1;
-#elif defined(__LITTLE_ENDIAN)
-	u16 agg_limit1;
-	u16 __agg_misc1;
-#endif
-	u32 hq_cons_tcp_seq;
-	u32 exp_stat_sn;
-	u32 rst_seq_num;
-};
-
-
-/*
- * The L5cm aggregative context of XStorm
- */
-struct xstorm_l5cm_ag_context {
-#if defined(__BIG_ENDIAN)
-	u16 agg_val1;
-	u8 agg_vars1;
-#define __XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __XSTORM_L5CM_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
-#define __XSTORM_L5CM_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
-#define XSTORM_L5CM_AG_CONTEXT_NAGLE_EN (0x1<<5)
-#define XSTORM_L5CM_AG_CONTEXT_NAGLE_EN_SHIFT 5
-#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
-#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
-#define __XSTORM_L5CM_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
-#define __XSTORM_L5CM_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
-	u8 state;
-#elif defined(__LITTLE_ENDIAN)
-	u8 state;
-	u8 agg_vars1;
-#define __XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __XSTORM_L5CM_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
-#define __XSTORM_L5CM_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
-#define XSTORM_L5CM_AG_CONTEXT_NAGLE_EN (0x1<<5)
-#define XSTORM_L5CM_AG_CONTEXT_NAGLE_EN_SHIFT 5
-#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
-#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
-#define __XSTORM_L5CM_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
-#define __XSTORM_L5CM_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
-	u16 agg_val1;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 cdu_reserved;
-	u8 __agg_vars4;
-	u8 agg_vars3;
-#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
-#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
-#define __XSTORM_L5CM_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
-#define __XSTORM_L5CM_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
-	u8 agg_vars2;
-#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF (0x3<<0)
-#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_SHIFT 0
-#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
-#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
-#define __XSTORM_L5CM_AG_CONTEXT_AUX8_FLAG (0x1<<3)
-#define __XSTORM_L5CM_AG_CONTEXT_AUX8_FLAG_SHIFT 3
-#define __XSTORM_L5CM_AG_CONTEXT_AUX9_FLAG (0x1<<4)
-#define __XSTORM_L5CM_AG_CONTEXT_AUX9_FLAG_SHIFT 4
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE1_SHIFT 5
-#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_EN (0x1<<7)
-#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_EN_SHIFT 7
-#elif defined(__LITTLE_ENDIAN)
-	u8 agg_vars2;
-#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF (0x3<<0)
-#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_SHIFT 0
-#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
-#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
-#define __XSTORM_L5CM_AG_CONTEXT_AUX8_FLAG (0x1<<3)
-#define __XSTORM_L5CM_AG_CONTEXT_AUX8_FLAG_SHIFT 3
-#define __XSTORM_L5CM_AG_CONTEXT_AUX9_FLAG (0x1<<4)
-#define __XSTORM_L5CM_AG_CONTEXT_AUX9_FLAG_SHIFT 4
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE1_SHIFT 5
-#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_EN (0x1<<7)
-#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_EN_SHIFT 7
-	u8 agg_vars3;
-#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
-#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
-#define __XSTORM_L5CM_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
-#define __XSTORM_L5CM_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
-	u8 __agg_vars4;
-	u8 cdu_reserved;
-#endif
-	u32 more_to_send;
-#if defined(__BIG_ENDIAN)
-	u16 agg_vars5;
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE5_SHIFT 0
-#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
-#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
-#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
-#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE2_SHIFT 14
-	u16 agg_val4_th;
-#elif defined(__LITTLE_ENDIAN)
-	u16 agg_val4_th;
-	u16 agg_vars5;
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE5_SHIFT 0
-#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
-#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
-#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
-#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE2_SHIFT 14
-#endif
-	struct xstorm_tcp_tcp_ag_context_section tcp;
-#if defined(__BIG_ENDIAN)
-	u16 agg_vars7;
-#define __XSTORM_L5CM_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
-#define __XSTORM_L5CM_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
-#define __XSTORM_L5CM_AG_CONTEXT_AUX13_FLAG (0x1<<3)
-#define __XSTORM_L5CM_AG_CONTEXT_AUX13_FLAG_SHIFT 3
-#define __XSTORM_L5CM_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
-#define __XSTORM_L5CM_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE3_SHIFT 6
-#define XSTORM_L5CM_AG_CONTEXT_AUX1_CF (0x3<<8)
-#define XSTORM_L5CM_AG_CONTEXT_AUX1_CF_SHIFT 8
-#define __XSTORM_L5CM_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
-#define __XSTORM_L5CM_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
-#define __XSTORM_L5CM_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
-#define __XSTORM_L5CM_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
-#define __XSTORM_L5CM_AG_CONTEXT_AUX10_FLAG (0x1<<12)
-#define __XSTORM_L5CM_AG_CONTEXT_AUX10_FLAG_SHIFT 12
-#define __XSTORM_L5CM_AG_CONTEXT_AUX11_FLAG (0x1<<13)
-#define __XSTORM_L5CM_AG_CONTEXT_AUX11_FLAG_SHIFT 13
-#define __XSTORM_L5CM_AG_CONTEXT_AUX12_FLAG (0x1<<14)
-#define __XSTORM_L5CM_AG_CONTEXT_AUX12_FLAG_SHIFT 14
-#define __XSTORM_L5CM_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
-#define __XSTORM_L5CM_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
-	u8 agg_val3_th;
-	u8 agg_vars6;
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE6_SHIFT 0
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE7_SHIFT 3
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE4_SHIFT 6
-#elif defined(__LITTLE_ENDIAN)
-	u8 agg_vars6;
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE6_SHIFT 0
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE7_SHIFT 3
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE4_SHIFT 6
-	u8 agg_val3_th;
-	u16 agg_vars7;
-#define __XSTORM_L5CM_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
-#define __XSTORM_L5CM_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
-#define __XSTORM_L5CM_AG_CONTEXT_AUX13_FLAG (0x1<<3)
-#define __XSTORM_L5CM_AG_CONTEXT_AUX13_FLAG_SHIFT 3
-#define __XSTORM_L5CM_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
-#define __XSTORM_L5CM_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
-#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE3_SHIFT 6
-#define XSTORM_L5CM_AG_CONTEXT_AUX1_CF (0x3<<8)
-#define XSTORM_L5CM_AG_CONTEXT_AUX1_CF_SHIFT 8
-#define __XSTORM_L5CM_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
-#define __XSTORM_L5CM_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
-#define __XSTORM_L5CM_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
-#define __XSTORM_L5CM_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
-#define __XSTORM_L5CM_AG_CONTEXT_AUX10_FLAG (0x1<<12)
-#define __XSTORM_L5CM_AG_CONTEXT_AUX10_FLAG_SHIFT 12
-#define __XSTORM_L5CM_AG_CONTEXT_AUX11_FLAG (0x1<<13)
-#define __XSTORM_L5CM_AG_CONTEXT_AUX11_FLAG_SHIFT 13
-#define __XSTORM_L5CM_AG_CONTEXT_AUX12_FLAG (0x1<<14)
-#define __XSTORM_L5CM_AG_CONTEXT_AUX12_FLAG_SHIFT 14
-#define __XSTORM_L5CM_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
-#define __XSTORM_L5CM_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __agg_val11_th;
-	u16 __gen_data;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __gen_data;
-	u16 __agg_val11_th;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __reserved1;
-	u8 __agg_val6_th;
-	u16 __agg_val9;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val9;
-	u8 __agg_val6_th;
-	u8 __reserved1;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 agg_val2_th;
-	u16 agg_val2;
-#elif defined(__LITTLE_ENDIAN)
-	u16 agg_val2;
-	u16 agg_val2_th;
-#endif
-	u32 agg_vars8;
-#define XSTORM_L5CM_AG_CONTEXT_AGG_MISC2 (0xFFFFFF<<0)
-#define XSTORM_L5CM_AG_CONTEXT_AGG_MISC2_SHIFT 0
-#define XSTORM_L5CM_AG_CONTEXT_AGG_MISC3 (0xFF<<24)
-#define XSTORM_L5CM_AG_CONTEXT_AGG_MISC3_SHIFT 24
-#if defined(__BIG_ENDIAN)
-	u16 agg_misc0;
-	u16 agg_val4;
-#elif defined(__LITTLE_ENDIAN)
-	u16 agg_val4;
-	u16 agg_misc0;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 agg_val3;
-	u8 agg_val6;
-	u8 agg_val5_th;
-	u8 agg_val5;
-#elif defined(__LITTLE_ENDIAN)
-	u8 agg_val5;
-	u8 agg_val5_th;
-	u8 agg_val6;
-	u8 agg_val3;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __agg_misc1;
-	u16 agg_limit1;
-#elif defined(__LITTLE_ENDIAN)
-	u16 agg_limit1;
-	u16 __agg_misc1;
-#endif
-	u32 completion_seq;
-	u32 agg_misc4;
-	u32 rst_seq_num;
-};
-
-/*
- * ABTS info $$KEEP_ENDIANNESS$$
- */
-struct fcoe_abts_info {
-	__le16 aborted_task_id;
-	__le16 reserved0;
-	__le32 reserved1;
-};
-
-
-/*
- * Fixed size structure in order to plant it in Union structure
- * $$KEEP_ENDIANNESS$$
- */
-struct fcoe_abts_rsp_union {
-	u8 r_ctl;
-	u8 rsrv[3];
-	__le32 abts_rsp_payload[7];
-};
-
-
-/*
- * 4 regs size $$KEEP_ENDIANNESS$$
- */
-struct fcoe_bd_ctx {
-	__le32 buf_addr_hi;
-	__le32 buf_addr_lo;
-	__le16 buf_len;
-	__le16 rsrv0;
-	__le16 flags;
-	__le16 rsrv1;
-};
-
-
-/*
- * FCoE cached sges context $$KEEP_ENDIANNESS$$
- */
-struct fcoe_cached_sge_ctx {
-	struct regpair cur_buf_addr;
-	__le16 cur_buf_rem;
-	__le16 second_buf_rem;
-	struct regpair second_buf_addr;
-};
-
-
-/*
- * Cleanup info $$KEEP_ENDIANNESS$$
- */
-struct fcoe_cleanup_info {
-	__le16 cleaned_task_id;
-	__le16 rolled_tx_seq_cnt;
-	__le32 rolled_tx_data_offset;
-};
-
-
-/*
- * Fcp RSP flags $$KEEP_ENDIANNESS$$
- */
-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
-};
-
-/*
- * Fcp RSP payload $$KEEP_ENDIANNESS$$
- */
-struct fcoe_fcp_rsp_payload {
-	struct regpair reserved0;
-	__le32 fcp_resid;
-	u8 scsi_status_code;
-	struct fcoe_fcp_rsp_flags fcp_flags;
-	__le16 retry_delay_timer;
-	__le32 fcp_rsp_len;
-	__le32 fcp_sns_len;
-};
-
-/*
- * Fixed size structure in order to plant it in Union structure
- * $$KEEP_ENDIANNESS$$
- */
-struct fcoe_fcp_rsp_union {
-	struct fcoe_fcp_rsp_payload payload;
-	struct regpair reserved0;
-};
-
-/*
- * FC header $$KEEP_ENDIANNESS$$
- */
-struct fcoe_fc_hdr {
-	u8 s_id[3];
-	u8 cs_ctl;
-	u8 d_id[3];
-	u8 r_ctl;
-	__le16 seq_cnt;
-	u8 df_ctl;
-	u8 seq_id;
-	u8 f_ctl[3];
-	u8 type;
-	__le32 parameters;
-	__le16 rx_id;
-	__le16 ox_id;
-};
-
-/*
- * FC header union $$KEEP_ENDIANNESS$$
- */
-struct fcoe_mp_rsp_union {
-	struct fcoe_fc_hdr fc_hdr;
-	__le32 mp_payload_len;
-	__le32 rsrv;
-};
-
-/*
- * Completion information $$KEEP_ENDIANNESS$$
- */
-union fcoe_comp_flow_info {
-	struct fcoe_fcp_rsp_union fcp_rsp;
-	struct fcoe_abts_rsp_union abts_rsp;
-	struct fcoe_mp_rsp_union mp_rsp;
-	__le32 opaque[8];
-};
-
-
-/*
- * External ABTS info $$KEEP_ENDIANNESS$$
- */
-struct fcoe_ext_abts_info {
-	__le32 rsrv0[6];
-	struct fcoe_abts_info ctx;
-};
-
-
-/*
- * External cleanup info $$KEEP_ENDIANNESS$$
- */
-struct fcoe_ext_cleanup_info {
-	__le32 rsrv0[6];
-	struct fcoe_cleanup_info ctx;
-};
-
-
-/*
- * Fcoe FW Tx sequence context $$KEEP_ENDIANNESS$$
- */
-struct fcoe_fw_tx_seq_ctx {
-	__le32 data_offset;
-	__le16 seq_cnt;
-	__le16 rsrv0;
-};
-
-/*
- * Fcoe external FW Tx sequence context $$KEEP_ENDIANNESS$$
- */
-struct fcoe_ext_fw_tx_seq_ctx {
-	__le32 rsrv0[6];
-	struct fcoe_fw_tx_seq_ctx ctx;
-};
-
-
-/*
- * FCoE multiple sges context $$KEEP_ENDIANNESS$$
- */
-struct fcoe_mul_sges_ctx {
-	struct regpair cur_sge_addr;
-	__le16 cur_sge_off;
-	u8 cur_sge_idx;
-	u8 sgl_size;
-};
-
-/*
- * FCoE external multiple sges context $$KEEP_ENDIANNESS$$
- */
-struct fcoe_ext_mul_sges_ctx {
-	struct fcoe_mul_sges_ctx mul_sgl;
-	struct regpair rsrv0;
-};
-
-
-/*
- * FCP CMD payload $$KEEP_ENDIANNESS$$
- */
-struct fcoe_fcp_cmd_payload {
-	__le32 opaque[8];
-};
-
-
-
-
-
-/*
- * Fcp xfr rdy payload $$KEEP_ENDIANNESS$$
- */
-struct fcoe_fcp_xfr_rdy_payload {
-	__le32 burst_len;
-	__le32 data_ro;
-};
-
-
-/*
- * FC frame $$KEEP_ENDIANNESS$$
- */
-struct fcoe_fc_frame {
-	struct fcoe_fc_hdr fc_hdr;
-	__le32 reserved0[2];
-};
-
-
-
-
-/*
- * FCoE KCQ CQE parameters $$KEEP_ENDIANNESS$$
- */
-union fcoe_kcqe_params {
-	__le32 reserved0[4];
-};
-
-/*
- * FCoE KCQ CQE $$KEEP_ENDIANNESS$$
- */
-struct fcoe_kcqe {
-	__le32 fcoe_conn_id;
-	__le32 completion_status;
-	__le32 fcoe_conn_context_id;
-	union fcoe_kcqe_params params;
-	__le16 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
-};
-
-
-
-/*
- * FCoE KWQE header $$KEEP_ENDIANNESS$$
- */
-struct fcoe_kwqe_header {
-	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
-};
-
-/*
- * FCoE firmware init request 1 $$KEEP_ENDIANNESS$$
- */
-struct fcoe_kwqe_init1 {
-	__le16 num_tasks;
-	struct fcoe_kwqe_header hdr;
-	__le32 task_list_pbl_addr_lo;
-	__le32 task_list_pbl_addr_hi;
-	__le32 dummy_buffer_addr_lo;
-	__le32 dummy_buffer_addr_hi;
-	__le16 sq_num_wqes;
-	__le16 rq_num_wqes;
-	__le16 rq_buffer_log_size;
-	__le16 cq_num_wqes;
-	__le16 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
-};
-
-/*
- * FCoE firmware init request 2 $$KEEP_ENDIANNESS$$
- */
-struct fcoe_kwqe_init2 {
-	u8 hsi_major_version;
-	u8 hsi_minor_version;
-	struct fcoe_kwqe_header hdr;
-	__le32 hash_tbl_pbl_addr_lo;
-	__le32 hash_tbl_pbl_addr_hi;
-	__le32 t2_hash_tbl_addr_lo;
-	__le32 t2_hash_tbl_addr_hi;
-	__le32 t2_ptr_hash_tbl_addr_lo;
-	__le32 t2_ptr_hash_tbl_addr_hi;
-	__le32 free_list_count;
-};
-
-/*
- * FCoE firmware init request 3 $$KEEP_ENDIANNESS$$
- */
-struct fcoe_kwqe_init3 {
-	__le16 reserved0;
-	struct fcoe_kwqe_header hdr;
-	__le32 error_bit_map_lo;
-	__le32 error_bit_map_hi;
-	u8 perf_config;
-	u8 reserved21[3];
-	__le32 reserved2[4];
-};
-
-/*
- * FCoE connection offload request 1 $$KEEP_ENDIANNESS$$
- */
-struct fcoe_kwqe_conn_offload1 {
-	__le16 fcoe_conn_id;
-	struct fcoe_kwqe_header hdr;
-	__le32 sq_addr_lo;
-	__le32 sq_addr_hi;
-	__le32 rq_pbl_addr_lo;
-	__le32 rq_pbl_addr_hi;
-	__le32 rq_first_pbe_addr_lo;
-	__le32 rq_first_pbe_addr_hi;
-	__le16 rq_prod;
-	__le16 reserved0;
-};
-
-/*
- * FCoE connection offload request 2 $$KEEP_ENDIANNESS$$
- */
-struct fcoe_kwqe_conn_offload2 {
-	__le16 tx_max_fc_pay_len;
-	struct fcoe_kwqe_header hdr;
-	__le32 cq_addr_lo;
-	__le32 cq_addr_hi;
-	__le32 xferq_addr_lo;
-	__le32 xferq_addr_hi;
-	__le32 conn_db_addr_lo;
-	__le32 conn_db_addr_hi;
-	__le32 reserved1;
-};
-
-/*
- * FCoE connection offload request 3 $$KEEP_ENDIANNESS$$
- */
-struct fcoe_kwqe_conn_offload3 {
-	__le16 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;
-	u8 s_id[3];
-	u8 tx_max_conc_seqs_c3;
-	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
-	__le32 reserved;
-	__le32 confq_first_pbe_addr_lo;
-	__le32 confq_first_pbe_addr_hi;
-	__le16 tx_total_conc_seqs;
-	__le16 rx_max_fc_pay_len;
-	__le16 rx_total_conc_seqs;
-	u8 rx_max_conc_seqs_c3;
-	u8 rx_open_seqs_exch_c3;
-};
-
-/*
- * FCoE connection offload request 4 $$KEEP_ENDIANNESS$$
- */
-struct fcoe_kwqe_conn_offload4 {
-	u8 e_d_tov_timer_val;
-	u8 reserved2;
-	struct fcoe_kwqe_header hdr;
-	u8 src_mac_addr_lo[2];
-	u8 src_mac_addr_mid[2];
-	u8 src_mac_addr_hi[2];
-	u8 dst_mac_addr_hi[2];
-	u8 dst_mac_addr_lo[2];
-	u8 dst_mac_addr_mid[2];
-	__le32 lcq_addr_lo;
-	__le32 lcq_addr_hi;
-	__le32 confq_pbl_base_addr_lo;
-	__le32 confq_pbl_base_addr_hi;
-};
-
-/*
- * FCoE connection enable request $$KEEP_ENDIANNESS$$
- */
-struct fcoe_kwqe_conn_enable_disable {
-	__le16 reserved0;
-	struct fcoe_kwqe_header hdr;
-	u8 src_mac_addr_lo[2];
-	u8 src_mac_addr_mid[2];
-	u8 src_mac_addr_hi[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
-	u8 dst_mac_addr_lo[2];
-	u8 dst_mac_addr_mid[2];
-	u8 dst_mac_addr_hi[2];
-	__le16 reserved1;
-	u8 s_id[3];
-	u8 vlan_flag;
-	u8 d_id[3];
-	u8 reserved3;
-	__le32 context_id;
-	__le32 conn_id;
-	__le32 reserved4;
-};
-
-/*
- * FCoE connection destroy request $$KEEP_ENDIANNESS$$
- */
-struct fcoe_kwqe_conn_destroy {
-	__le16 reserved0;
-	struct fcoe_kwqe_header hdr;
-	__le32 context_id;
-	__le32 conn_id;
-	__le32 reserved1[5];
-};
-
-/*
- * FCoe destroy request $$KEEP_ENDIANNESS$$
- */
-struct fcoe_kwqe_destroy {
-	__le16 reserved0;
-	struct fcoe_kwqe_header hdr;
-	__le32 reserved1[7];
-};
-
-/*
- * FCoe statistics request $$KEEP_ENDIANNESS$$
- */
-struct fcoe_kwqe_stat {
-	__le16 reserved0;
-	struct fcoe_kwqe_header hdr;
-	__le32 stat_params_addr_lo;
-	__le32 stat_params_addr_hi;
-	__le32 reserved1[5];
-};
-
-/*
- * FCoE KWQ WQE $$KEEP_ENDIANNESS$$
- */
-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;
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/*
- * TX SGL context $$KEEP_ENDIANNESS$$
- */
-union fcoe_sgl_union_ctx {
-	struct fcoe_cached_sge_ctx cached_sge;
-	struct fcoe_ext_mul_sges_ctx sgl;
-	__le32 opaque[5];
-};
-
-/*
- * Data-In/ELS/BLS information $$KEEP_ENDIANNESS$$
- */
-struct fcoe_read_flow_info {
-	union fcoe_sgl_union_ctx sgl_ctx;
-	__le32 rsrv0[3];
-};
-
-
-/*
- * Fcoe stat context $$KEEP_ENDIANNESS$$
- */
-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
-};
-
-/*
- * Fcoe rx seq context $$KEEP_ENDIANNESS$$
- */
-struct fcoe_rx_seq_ctx {
-	u8 seq_id;
-	struct fcoe_s_stat_ctx s_stat;
-	__le16 seq_cnt;
-	__le32 low_exp_ro;
-	__le32 high_exp_ro;
-};
-
-
-/*
- * Fcoe rx_wr union context $$KEEP_ENDIANNESS$$
- */
-union fcoe_rx_wr_union_ctx {
-	struct fcoe_read_flow_info read_info;
-	union fcoe_comp_flow_info comp_info;
-	__le32 opaque[8];
-};
-
-
-
-/*
- * FCoE SQ element $$KEEP_ENDIANNESS$$
- */
-struct fcoe_sqe {
-	__le16 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
-};
-
-
-
-/*
- * 14 regs $$KEEP_ENDIANNESS$$
- */
-struct fcoe_tce_tx_only {
-	union fcoe_sgl_union_ctx sgl_ctx;
-	__le32 rsrv0;
-};
-
-/*
- * 32 bytes (8 regs) used for TX only purposes $$KEEP_ENDIANNESS$$
- */
-union fcoe_tx_wr_rx_rd_union_ctx {
-	struct fcoe_fc_frame tx_frame;
-	struct fcoe_fcp_cmd_payload fcp_cmd;
-	struct fcoe_ext_cleanup_info cleanup;
-	struct fcoe_ext_abts_info abts;
-	struct fcoe_ext_fw_tx_seq_ctx tx_seq;
-	__le32 opaque[8];
-};
-
-/*
- * tce_tx_wr_rx_rd_const $$KEEP_ENDIANNESS$$
- */
-struct fcoe_tce_tx_wr_rx_rd_const {
-	u8 init_flags;
-#define FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE (0x7<<0)
-#define FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT 0
-#define FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE (0x1<<3)
-#define FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT 3
-#define FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE (0x1<<4)
-#define FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT 4
-#define FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE (0x3<<5)
-#define FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT 5
-#define FCOE_TCE_TX_WR_RX_RD_CONST_SUPPORT_REC_TOV (0x1<<7)
-#define FCOE_TCE_TX_WR_RX_RD_CONST_SUPPORT_REC_TOV_SHIFT 7
-	u8 tx_flags;
-#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_VALID (0x1<<0)
-#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_VALID_SHIFT 0
-#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE (0xF<<1)
-#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT 1
-#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1 (0x1<<5)
-#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1_SHIFT 5
-#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT (0x1<<6)
-#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT_SHIFT 6
-#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2 (0x1<<7)
-#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2_SHIFT 7
-	__le16 rsrv3;
-	__le32 verify_tx_seq;
-};
-
-/*
- * tce_tx_wr_rx_rd $$KEEP_ENDIANNESS$$
- */
-struct fcoe_tce_tx_wr_rx_rd {
-	union fcoe_tx_wr_rx_rd_union_ctx union_ctx;
-	struct fcoe_tce_tx_wr_rx_rd_const const_ctx;
-};
-
-/*
- * tce_rx_wr_tx_rd_const $$KEEP_ENDIANNESS$$
- */
-struct fcoe_tce_rx_wr_tx_rd_const {
-	__le32 data_2_trns;
-	__le32 init_flags;
-#define FCOE_TCE_RX_WR_TX_RD_CONST_CID (0xFFFFFF<<0)
-#define FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT 0
-#define FCOE_TCE_RX_WR_TX_RD_CONST_RSRV0 (0xFF<<24)
-#define FCOE_TCE_RX_WR_TX_RD_CONST_RSRV0_SHIFT 24
-};
-
-/*
- * tce_rx_wr_tx_rd_var $$KEEP_ENDIANNESS$$
- */
-struct fcoe_tce_rx_wr_tx_rd_var {
-	__le16 rx_flags;
-#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV1 (0xF<<0)
-#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV1_SHIFT 0
-#define FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE (0x7<<4)
-#define FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE_SHIFT 4
-#define FCOE_TCE_RX_WR_TX_RD_VAR_CONF_REQ (0x1<<7)
-#define FCOE_TCE_RX_WR_TX_RD_VAR_CONF_REQ_SHIFT 7
-#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE (0xF<<8)
-#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE_SHIFT 8
-#define FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME (0x1<<12)
-#define FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT 12
-#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_SEQ_INIT (0x1<<13)
-#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_SEQ_INIT_SHIFT 13
-#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV2 (0x1<<14)
-#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV2_SHIFT 14
-#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_VALID (0x1<<15)
-#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_VALID_SHIFT 15
-	__le16 rx_id;
-	struct fcoe_fcp_xfr_rdy_payload fcp_xfr_rdy;
-};
-
-/*
- * tce_rx_wr_tx_rd $$KEEP_ENDIANNESS$$
- */
-struct fcoe_tce_rx_wr_tx_rd {
-	struct fcoe_tce_rx_wr_tx_rd_const const_ctx;
-	struct fcoe_tce_rx_wr_tx_rd_var var_ctx;
-};
-
-/*
- * tce_rx_only $$KEEP_ENDIANNESS$$
- */
-struct fcoe_tce_rx_only {
-	struct fcoe_rx_seq_ctx rx_seq_ctx;
-	union fcoe_rx_wr_union_ctx union_ctx;
-};
-
-/*
- * task_ctx_entry $$KEEP_ENDIANNESS$$
- */
-struct fcoe_task_ctx_entry {
-	struct fcoe_tce_tx_only txwr_only;
-	struct fcoe_tce_tx_wr_rx_rd txwr_rxrd;
-	struct fcoe_tce_rx_wr_tx_rd rxwr_txrd;
-	struct fcoe_tce_rx_only rxwr_only;
-};
-
-
-
-
-
-
-
-
-
-
-/*
- * FCoE XFRQ element $$KEEP_ENDIANNESS$$
- */
-struct fcoe_xfrqe {
-	__le16 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
-};
-
-
-/*
- * Cached SGEs $$KEEP_ENDIANNESS$$
- */
-struct common_fcoe_sgl {
-	struct fcoe_bd_ctx sge[3];
-};
-
-
-/*
- * FCoE SQ\XFRQ element
- */
-struct fcoe_cached_wqe {
-	struct fcoe_sqe sqe;
-	struct fcoe_xfrqe xfrqe;
-};
-
-
-/*
- * FCoE connection enable\disable params passed by driver to FW in FCoE enable
- * ramrod $$KEEP_ENDIANNESS$$
- */
-struct fcoe_conn_enable_disable_ramrod_params {
-	struct fcoe_kwqe_conn_enable_disable enable_disable_kwqe;
-};
-
-
-/*
- * FCoE connection offload params passed by driver to FW in FCoE offload ramrod
- * $$KEEP_ENDIANNESS$$
- */
-struct fcoe_conn_offload_ramrod_params {
-	struct fcoe_kwqe_conn_offload1 offload_kwqe1;
-	struct fcoe_kwqe_conn_offload2 offload_kwqe2;
-	struct fcoe_kwqe_conn_offload3 offload_kwqe3;
-	struct fcoe_kwqe_conn_offload4 offload_kwqe4;
-};
-
-
-struct ustorm_fcoe_mng_ctx {
-#if defined(__BIG_ENDIAN)
-	u8 mid_seq_proc_flag;
-	u8 tce_in_cam_flag;
-	u8 tce_on_ior_flag;
-	u8 en_cached_tce_flag;
-#elif defined(__LITTLE_ENDIAN)
-	u8 en_cached_tce_flag;
-	u8 tce_on_ior_flag;
-	u8 tce_in_cam_flag;
-	u8 mid_seq_proc_flag;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 tce_cam_addr;
-	u8 cached_conn_flag;
-	u16 rsrv0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rsrv0;
-	u8 cached_conn_flag;
-	u8 tce_cam_addr;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 dma_tce_ram_addr;
-	u16 tce_ram_addr;
-#elif defined(__LITTLE_ENDIAN)
-	u16 tce_ram_addr;
-	u16 dma_tce_ram_addr;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 ox_id;
-	u16 wr_done_seq;
-#elif defined(__LITTLE_ENDIAN)
-	u16 wr_done_seq;
-	u16 ox_id;
-#endif
-	struct regpair task_addr;
-};
-
-/*
- * Parameters initialized during offloaded according to FLOGI/PLOGI/PRLI and
- * used in FCoE context section
- */
-struct ustorm_fcoe_params {
-#if defined(__BIG_ENDIAN)
-	u16 fcoe_conn_id;
-	u16 flags;
-#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS (0x1<<0)
-#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS_SHIFT 0
-#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES (0x1<<1)
-#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES_SHIFT 1
-#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define USTORM_FCOE_PARAMS_B_CONF_REQ (0x1<<3)
-#define USTORM_FCOE_PARAMS_B_CONF_REQ_SHIFT 3
-#define USTORM_FCOE_PARAMS_B_REC_VALID (0x1<<4)
-#define USTORM_FCOE_PARAMS_B_REC_VALID_SHIFT 4
-#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT (0x1<<5)
-#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT_SHIFT 5
-#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT (0x1<<6)
-#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT_SHIFT 6
-#define USTORM_FCOE_PARAMS_RSRV0 (0x1FF<<7)
-#define USTORM_FCOE_PARAMS_RSRV0_SHIFT 7
-#elif defined(__LITTLE_ENDIAN)
-	u16 flags;
-#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS (0x1<<0)
-#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS_SHIFT 0
-#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES (0x1<<1)
-#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES_SHIFT 1
-#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define USTORM_FCOE_PARAMS_B_CONF_REQ (0x1<<3)
-#define USTORM_FCOE_PARAMS_B_CONF_REQ_SHIFT 3
-#define USTORM_FCOE_PARAMS_B_REC_VALID (0x1<<4)
-#define USTORM_FCOE_PARAMS_B_REC_VALID_SHIFT 4
-#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT (0x1<<5)
-#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT_SHIFT 5
-#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT (0x1<<6)
-#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT_SHIFT 6
-#define USTORM_FCOE_PARAMS_RSRV0 (0x1FF<<7)
-#define USTORM_FCOE_PARAMS_RSRV0_SHIFT 7
-	u16 fcoe_conn_id;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 hc_csdm_byte_en;
-	u8 func_id;
-	u8 port_id;
-	u8 vnic_id;
-#elif defined(__LITTLE_ENDIAN)
-	u8 vnic_id;
-	u8 port_id;
-	u8 func_id;
-	u8 hc_csdm_byte_en;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 rx_total_conc_seqs;
-	u16 rx_max_fc_pay_len;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rx_max_fc_pay_len;
-	u16 rx_total_conc_seqs;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 task_pbe_idx_off;
-	u8 task_in_page_log_size;
-	u16 rx_max_conc_seqs;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rx_max_conc_seqs;
-	u8 task_in_page_log_size;
-	u8 task_pbe_idx_off;
-#endif
-};
-
-/*
- * FCoE 16-bits index structure
- */
-struct fcoe_idx16_fields {
-	u16 fields;
-#define FCOE_IDX16_FIELDS_IDX (0x7FFF<<0)
-#define FCOE_IDX16_FIELDS_IDX_SHIFT 0
-#define FCOE_IDX16_FIELDS_MSB (0x1<<15)
-#define FCOE_IDX16_FIELDS_MSB_SHIFT 15
-};
-
-/*
- * FCoE 16-bits index union
- */
-union fcoe_idx16_field_union {
-	struct fcoe_idx16_fields fields;
-	u16 val;
-};
-
-/*
- * Parameters required for placement according to SGL
- */
-struct ustorm_fcoe_data_place_mng {
-#if defined(__BIG_ENDIAN)
-	u16 sge_off;
-	u8 num_sges;
-	u8 sge_idx;
-#elif defined(__LITTLE_ENDIAN)
-	u8 sge_idx;
-	u8 num_sges;
-	u16 sge_off;
-#endif
-};
-
-/*
- * Parameters required for placement according to SGL
- */
-struct ustorm_fcoe_data_place {
-	struct ustorm_fcoe_data_place_mng cached_mng;
-	struct fcoe_bd_ctx cached_sge[2];
-};
-
-/*
- * TX processing shall write and RX processing shall read from this section
- */
-union fcoe_u_tce_tx_wr_rx_rd_union {
-	struct fcoe_abts_info abts;
-	struct fcoe_cleanup_info cleanup;
-	struct fcoe_fw_tx_seq_ctx tx_seq_ctx;
-	u32 opaque[2];
-};
-
-/*
- * TX processing shall write and RX processing shall read from this section
- */
-struct fcoe_u_tce_tx_wr_rx_rd {
-	union fcoe_u_tce_tx_wr_rx_rd_union union_ctx;
-	struct fcoe_tce_tx_wr_rx_rd_const const_ctx;
-};
-
-struct ustorm_fcoe_tce {
-	struct fcoe_u_tce_tx_wr_rx_rd txwr_rxrd;
-	struct fcoe_tce_rx_wr_tx_rd rxwr_txrd;
-	struct fcoe_tce_rx_only rxwr;
-};
-
-struct ustorm_fcoe_cache_ctx {
-	u32 rsrv0;
-	struct ustorm_fcoe_data_place data_place;
-	struct ustorm_fcoe_tce tce;
-};
-
-/*
- * Ustorm FCoE Storm Context
- */
-struct ustorm_fcoe_st_context {
-	struct ustorm_fcoe_mng_ctx mng_ctx;
-	struct ustorm_fcoe_params fcoe_params;
-	struct regpair cq_base_addr;
-	struct regpair rq_pbl_base;
-	struct regpair rq_cur_page_addr;
-	struct regpair confq_pbl_base_addr;
-	struct regpair conn_db_base;
-	struct regpair xfrq_base_addr;
-	struct regpair lcq_base_addr;
-#if defined(__BIG_ENDIAN)
-	union fcoe_idx16_field_union rq_cons;
-	union fcoe_idx16_field_union rq_prod;
-#elif defined(__LITTLE_ENDIAN)
-	union fcoe_idx16_field_union rq_prod;
-	union fcoe_idx16_field_union rq_cons;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 xfrq_prod;
-	u16 cq_cons;
-#elif defined(__LITTLE_ENDIAN)
-	u16 cq_cons;
-	u16 xfrq_prod;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 lcq_cons;
-	u16 hc_cram_address;
-#elif defined(__LITTLE_ENDIAN)
-	u16 hc_cram_address;
-	u16 lcq_cons;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 sq_xfrq_lcq_confq_size;
-	u16 confq_prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 confq_prod;
-	u16 sq_xfrq_lcq_confq_size;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 hc_csdm_agg_int;
-	u8 rsrv2;
-	u8 available_rqes;
-	u8 sp_q_flush_cnt;
-#elif defined(__LITTLE_ENDIAN)
-	u8 sp_q_flush_cnt;
-	u8 available_rqes;
-	u8 rsrv2;
-	u8 hc_csdm_agg_int;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 num_pend_tasks;
-	u16 pbf_ack_ram_addr;
-#elif defined(__LITTLE_ENDIAN)
-	u16 pbf_ack_ram_addr;
-	u16 num_pend_tasks;
-#endif
-	struct ustorm_fcoe_cache_ctx cache_ctx;
-};
-
-/*
- * The FCoE non-aggregative context of Tstorm
- */
-struct tstorm_fcoe_st_context {
-	struct regpair reserved0;
-	struct regpair reserved1;
-};
-
-/*
- * Ethernet context section
- */
-struct xstorm_fcoe_eth_context_section {
-#if defined(__BIG_ENDIAN)
-	u8 remote_addr_4;
-	u8 remote_addr_5;
-	u8 local_addr_0;
-	u8 local_addr_1;
-#elif defined(__LITTLE_ENDIAN)
-	u8 local_addr_1;
-	u8 local_addr_0;
-	u8 remote_addr_5;
-	u8 remote_addr_4;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 remote_addr_0;
-	u8 remote_addr_1;
-	u8 remote_addr_2;
-	u8 remote_addr_3;
-#elif defined(__LITTLE_ENDIAN)
-	u8 remote_addr_3;
-	u8 remote_addr_2;
-	u8 remote_addr_1;
-	u8 remote_addr_0;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 reserved_vlan_type;
-	u16 params;
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI (0x1<<12)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI_SHIFT 12
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
-#elif defined(__LITTLE_ENDIAN)
-	u16 params;
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI (0x1<<12)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI_SHIFT 12
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
-	u16 reserved_vlan_type;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 local_addr_2;
-	u8 local_addr_3;
-	u8 local_addr_4;
-	u8 local_addr_5;
-#elif defined(__LITTLE_ENDIAN)
-	u8 local_addr_5;
-	u8 local_addr_4;
-	u8 local_addr_3;
-	u8 local_addr_2;
-#endif
-};
-
-/*
- * Flags used in FCoE context section - 1 byte
- */
-struct xstorm_fcoe_context_flags {
-	u8 flags;
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_PROC_Q (0x3<<0)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_PROC_Q_SHIFT 0
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_MID_SEQ (0x1<<2)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_MID_SEQ_SHIFT 2
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_BLOCK_SQ (0x1<<3)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_BLOCK_SQ_SHIFT 3
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_REC_SUPPORT (0x1<<4)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_REC_SUPPORT_SHIFT 4
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_SQ_TOGGLE (0x1<<5)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_SQ_TOGGLE_SHIFT 5
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_XFRQ_TOGGLE (0x1<<6)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_XFRQ_TOGGLE_SHIFT 6
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_VNTAG_VLAN (0x1<<7)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_VNTAG_VLAN_SHIFT 7
-};
-
-struct xstorm_fcoe_tce {
-	struct fcoe_tce_tx_only txwr;
-	struct fcoe_tce_tx_wr_rx_rd txwr_rxrd;
-};
-
-/*
- * FCP_DATA parameters required for transmission
- */
-struct xstorm_fcoe_fcp_data {
-	u32 io_rem;
-#if defined(__BIG_ENDIAN)
-	u16 cached_sge_off;
-	u8 cached_num_sges;
-	u8 cached_sge_idx;
-#elif defined(__LITTLE_ENDIAN)
-	u8 cached_sge_idx;
-	u8 cached_num_sges;
-	u16 cached_sge_off;
-#endif
-	u32 buf_addr_hi_0;
-	u32 buf_addr_lo_0;
-#if defined(__BIG_ENDIAN)
-	u16 num_of_pending_tasks;
-	u16 buf_len_0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 buf_len_0;
-	u16 num_of_pending_tasks;
-#endif
-	u32 buf_addr_hi_1;
-	u32 buf_addr_lo_1;
-#if defined(__BIG_ENDIAN)
-	u16 task_pbe_idx_off;
-	u16 buf_len_1;
-#elif defined(__LITTLE_ENDIAN)
-	u16 buf_len_1;
-	u16 task_pbe_idx_off;
-#endif
-	u32 buf_addr_hi_2;
-	u32 buf_addr_lo_2;
-#if defined(__BIG_ENDIAN)
-	u16 ox_id;
-	u16 buf_len_2;
-#elif defined(__LITTLE_ENDIAN)
-	u16 buf_len_2;
-	u16 ox_id;
-#endif
-};
-
-/*
- * vlan configuration
- */
-struct xstorm_fcoe_vlan_conf {
-	u8 vlan_conf;
-#define XSTORM_FCOE_VLAN_CONF_PRIORITY (0x7<<0)
-#define XSTORM_FCOE_VLAN_CONF_PRIORITY_SHIFT 0
-#define XSTORM_FCOE_VLAN_CONF_INNER_VLAN_FLAG (0x1<<3)
-#define XSTORM_FCOE_VLAN_CONF_INNER_VLAN_FLAG_SHIFT 3
-#define XSTORM_FCOE_VLAN_CONF_RESERVED (0xF<<4)
-#define XSTORM_FCOE_VLAN_CONF_RESERVED_SHIFT 4
-};
-
-/*
- * FCoE 16-bits vlan structure
- */
-struct fcoe_vlan_fields {
-	u16 fields;
-#define FCOE_VLAN_FIELDS_VID (0xFFF<<0)
-#define FCOE_VLAN_FIELDS_VID_SHIFT 0
-#define FCOE_VLAN_FIELDS_CLI (0x1<<12)
-#define FCOE_VLAN_FIELDS_CLI_SHIFT 12
-#define FCOE_VLAN_FIELDS_PRI (0x7<<13)
-#define FCOE_VLAN_FIELDS_PRI_SHIFT 13
-};
-
-/*
- * FCoE 16-bits vlan union
- */
-union fcoe_vlan_field_union {
-	struct fcoe_vlan_fields fields;
-	u16 val;
-};
-
-/*
- * FCoE 16-bits vlan, vif union
- */
-union fcoe_vlan_vif_field_union {
-	union fcoe_vlan_field_union vlan;
-	u16 vif;
-};
-
-/*
- * FCoE context section
- */
-struct xstorm_fcoe_context_section {
-#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 rctl;
-	u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
-	u8 d_id[3];
-	u8 rctl;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 sq_xfrq_lcq_confq_size;
-	u16 tx_max_fc_pay_len;
-#elif defined(__LITTLE_ENDIAN)
-	u16 tx_max_fc_pay_len;
-	u16 sq_xfrq_lcq_confq_size;
-#endif
-	u32 lcq_prod;
-#if defined(__BIG_ENDIAN)
-	u8 port_id;
-	u8 func_id;
-	u8 seq_id;
-	struct xstorm_fcoe_context_flags tx_flags;
-#elif defined(__LITTLE_ENDIAN)
-	struct xstorm_fcoe_context_flags tx_flags;
-	u8 seq_id;
-	u8 func_id;
-	u8 port_id;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 mtu;
-	u8 func_mode;
-	u8 vnic_id;
-#elif defined(__LITTLE_ENDIAN)
-	u8 vnic_id;
-	u8 func_mode;
-	u16 mtu;
-#endif
-	struct regpair confq_curr_page_addr;
-	struct fcoe_cached_wqe cached_wqe[8];
-	struct regpair lcq_base_addr;
-	struct xstorm_fcoe_tce tce;
-	struct xstorm_fcoe_fcp_data fcp_data;
-#if defined(__BIG_ENDIAN)
-	u8 tx_max_conc_seqs_c3;
-	u8 vlan_flag;
-	u8 dcb_val;
-	u8 data_pb_cmd_size;
-#elif defined(__LITTLE_ENDIAN)
-	u8 data_pb_cmd_size;
-	u8 dcb_val;
-	u8 vlan_flag;
-	u8 tx_max_conc_seqs_c3;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 fcoe_tx_stat_params_ram_addr;
-	u16 fcoe_tx_fc_seq_ram_addr;
-#elif defined(__LITTLE_ENDIAN)
-	u16 fcoe_tx_fc_seq_ram_addr;
-	u16 fcoe_tx_stat_params_ram_addr;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 fcp_cmd_line_credit;
-	u8 eth_hdr_size;
-	u16 pbf_addr;
-#elif defined(__LITTLE_ENDIAN)
-	u16 pbf_addr;
-	u8 eth_hdr_size;
-	u8 fcp_cmd_line_credit;
-#endif
-#if defined(__BIG_ENDIAN)
-	union fcoe_vlan_vif_field_union multi_func_val;
-	u8 page_log_size;
-	struct xstorm_fcoe_vlan_conf orig_vlan_conf;
-#elif defined(__LITTLE_ENDIAN)
-	struct xstorm_fcoe_vlan_conf orig_vlan_conf;
-	u8 page_log_size;
-	union fcoe_vlan_vif_field_union multi_func_val;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 fcp_cmd_frame_size;
-	u16 pbf_addr_ff;
-#elif defined(__LITTLE_ENDIAN)
-	u16 pbf_addr_ff;
-	u16 fcp_cmd_frame_size;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 vlan_num;
-	u8 cos;
-	u8 cache_xfrq_cons;
-	u8 cache_sq_cons;
-#elif defined(__LITTLE_ENDIAN)
-	u8 cache_sq_cons;
-	u8 cache_xfrq_cons;
-	u8 cos;
-	u8 vlan_num;
-#endif
-	u32 verify_tx_seq;
-};
-
-/*
- * Xstorm FCoE Storm Context
- */
-struct xstorm_fcoe_st_context {
-	struct xstorm_fcoe_eth_context_section eth;
-	struct xstorm_fcoe_context_section fcoe;
-};
-
-/*
- * Fcoe connection context
- */
-struct fcoe_context {
-	struct ustorm_fcoe_st_context ustorm_st_context;
-	struct tstorm_fcoe_st_context tstorm_st_context;
-	struct xstorm_fcoe_ag_context xstorm_ag_context;
-	struct tstorm_fcoe_ag_context tstorm_ag_context;
-	struct ustorm_fcoe_ag_context ustorm_ag_context;
-	struct timers_block_context timers_context;
-	struct xstorm_fcoe_st_context xstorm_st_context;
-};
-
-/*
- * FCoE init params passed by driver to FW in FCoE init ramrod
- * $$KEEP_ENDIANNESS$$
- */
-struct fcoe_init_ramrod_params {
-	struct fcoe_kwqe_init1 init_kwqe1;
-	struct fcoe_kwqe_init2 init_kwqe2;
-	struct fcoe_kwqe_init3 init_kwqe3;
-	struct regpair eq_pbl_base;
-	__le32 eq_pbl_size;
-	__le32 reserved2;
-	__le16 eq_prod;
-	__le16 sb_num;
-	u8 sb_id;
-	u8 reserved0;
-	__le16 reserved1;
-};
-
-/*
- * FCoE statistics params buffer passed by driver to FW in FCoE statistics
- * ramrod $$KEEP_ENDIANNESS$$
- */
-struct fcoe_stat_ramrod_params {
-	struct fcoe_kwqe_stat stat_kwqe;
-};
-
-/*
- * CQ DB CQ producer and pending completion counter
- */
-struct iscsi_cq_db_prod_pnd_cmpltn_cnt {
-#if defined(__BIG_ENDIAN)
-	u16 cntr;
-	u16 prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 prod;
-	u16 cntr;
-#endif
-};
-
-/*
- * CQ DB pending completion ITT array
- */
-struct iscsi_cq_db_prod_pnd_cmpltn_cnt_arr {
-	struct iscsi_cq_db_prod_pnd_cmpltn_cnt prod_pend_comp[8];
-};
-
-/*
- * Cstorm CQ sequence to notify array, updated by driver
- */
-struct iscsi_cq_db_sqn_2_notify_arr {
-	u16 sqn[8];
-};
-
-/*
- * Cstorm iSCSI Storm Context
- */
-struct cstorm_iscsi_st_context {
-	struct iscsi_cq_db_prod_pnd_cmpltn_cnt_arr cq_c_prod_pend_comp_ctr_arr;
-	struct iscsi_cq_db_sqn_2_notify_arr cq_c_prod_sqn_arr;
-	struct iscsi_cq_db_sqn_2_notify_arr cq_c_sqn_2_notify_arr;
-	struct regpair hq_pbl_base;
-	struct regpair hq_curr_pbe;
-	struct regpair task_pbl_base;
-	struct regpair cq_db_base;
-#if defined(__BIG_ENDIAN)
-	u16 hq_bd_itt;
-	u16 iscsi_conn_id;
-#elif defined(__LITTLE_ENDIAN)
-	u16 iscsi_conn_id;
-	u16 hq_bd_itt;
-#endif
-	u32 hq_bd_data_segment_len;
-	u32 hq_bd_buffer_offset;
-#if defined(__BIG_ENDIAN)
-	u8 rsrv;
-	u8 cq_proc_en_bit_map;
-	u8 cq_pend_comp_itt_valid_bit_map;
-	u8 hq_bd_opcode;
-#elif defined(__LITTLE_ENDIAN)
-	u8 hq_bd_opcode;
-	u8 cq_pend_comp_itt_valid_bit_map;
-	u8 cq_proc_en_bit_map;
-	u8 rsrv;
-#endif
-	u32 hq_tcp_seq;
-#if defined(__BIG_ENDIAN)
-	u16 flags;
-#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN (0x1<<0)
-#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN_SHIFT 0
-#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN (0x1<<1)
-#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN_SHIFT 1
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID (0x1<<2)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID_SHIFT 2
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG (0x1<<3)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG_SHIFT 3
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK (0x1<<4)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK_SHIFT 4
-#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV (0x7FF<<5)
-#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV_SHIFT 5
-	u16 hq_cons;
-#elif defined(__LITTLE_ENDIAN)
-	u16 hq_cons;
-	u16 flags;
-#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN (0x1<<0)
-#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN_SHIFT 0
-#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN (0x1<<1)
-#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN_SHIFT 1
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID (0x1<<2)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID_SHIFT 2
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG (0x1<<3)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG_SHIFT 3
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK (0x1<<4)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK_SHIFT 4
-#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV (0x7FF<<5)
-#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV_SHIFT 5
-#endif
-	struct regpair rsrv1;
-};
-
-
-/*
- * SCSI read/write SQ WQE
- */
-struct iscsi_cmd_pdu_hdr_little_endian {
-#if defined(__BIG_ENDIAN)
-	u8 opcode;
-	u8 op_attr;
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_ATTRIBUTES (0x7<<0)
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_ATTRIBUTES_SHIFT 0
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_RSRV1 (0x3<<3)
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 3
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_WRITE_FLAG (0x1<<5)
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_WRITE_FLAG_SHIFT 5
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_READ_FLAG (0x1<<6)
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_READ_FLAG_SHIFT 6
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG (0x1<<7)
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG_SHIFT 7
-	u16 rsrv0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rsrv0;
-	u8 op_attr;
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_ATTRIBUTES (0x7<<0)
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_ATTRIBUTES_SHIFT 0
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_RSRV1 (0x3<<3)
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 3
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_WRITE_FLAG (0x1<<5)
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_WRITE_FLAG_SHIFT 5
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_READ_FLAG (0x1<<6)
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_READ_FLAG_SHIFT 6
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG (0x1<<7)
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG_SHIFT 7
-	u8 opcode;
-#endif
-	u32 data_fields;
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
-#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
-	struct regpair lun;
-	u32 itt;
-	u32 expected_data_transfer_length;
-	u32 cmd_sn;
-	u32 exp_stat_sn;
-	u32 scsi_command_block[4];
-};
-
-
-/*
- * Buffer per connection, used in Tstorm
- */
-struct iscsi_conn_buf {
-	struct regpair reserved[8];
-};
-
-
-/*
- * iSCSI context region, used only in iSCSI
- */
-struct ustorm_iscsi_rq_db {
-	struct regpair pbl_base;
-	struct regpair curr_pbe;
-};
-
-/*
- * iSCSI context region, used only in iSCSI
- */
-struct ustorm_iscsi_r2tq_db {
-	struct regpair pbl_base;
-	struct regpair curr_pbe;
-};
-
-/*
- * iSCSI context region, used only in iSCSI
- */
-struct ustorm_iscsi_cq_db {
-#if defined(__BIG_ENDIAN)
-	u16 cq_sn;
-	u16 prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 prod;
-	u16 cq_sn;
-#endif
-	struct regpair curr_pbe;
-};
-
-/*
- * iSCSI context region, used only in iSCSI
- */
-struct rings_db {
-	struct ustorm_iscsi_rq_db rq;
-	struct ustorm_iscsi_r2tq_db r2tq;
-	struct ustorm_iscsi_cq_db cq[8];
-#if defined(__BIG_ENDIAN)
-	u16 rq_prod;
-	u16 r2tq_prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 r2tq_prod;
-	u16 rq_prod;
-#endif
-	struct regpair cq_pbl_base;
-};
-
-/*
- * iSCSI context region, used only in iSCSI
- */
-struct ustorm_iscsi_placement_db {
-	u32 sgl_base_lo;
-	u32 sgl_base_hi;
-	u32 local_sge_0_address_hi;
-	u32 local_sge_0_address_lo;
-#if defined(__BIG_ENDIAN)
-	u16 curr_sge_offset;
-	u16 local_sge_0_size;
-#elif defined(__LITTLE_ENDIAN)
-	u16 local_sge_0_size;
-	u16 curr_sge_offset;
-#endif
-	u32 local_sge_1_address_hi;
-	u32 local_sge_1_address_lo;
-#if defined(__BIG_ENDIAN)
-	u8 exp_padding_2b;
-	u8 nal_len_3b;
-	u16 local_sge_1_size;
-#elif defined(__LITTLE_ENDIAN)
-	u16 local_sge_1_size;
-	u8 nal_len_3b;
-	u8 exp_padding_2b;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 sgl_size;
-	u8 local_sge_index_2b;
-	u16 reserved7;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved7;
-	u8 local_sge_index_2b;
-	u8 sgl_size;
-#endif
-	u32 rem_pdu;
-	u32 place_db_bitfield_1;
-#define USTORM_ISCSI_PLACEMENT_DB_REM_PDU_PAYLOAD (0xFFFFFF<<0)
-#define USTORM_ISCSI_PLACEMENT_DB_REM_PDU_PAYLOAD_SHIFT 0
-#define USTORM_ISCSI_PLACEMENT_DB_CQ_ID (0xFF<<24)
-#define USTORM_ISCSI_PLACEMENT_DB_CQ_ID_SHIFT 24
-	u32 place_db_bitfield_2;
-#define USTORM_ISCSI_PLACEMENT_DB_BYTES_2_TRUNCATE (0xFFFFFF<<0)
-#define USTORM_ISCSI_PLACEMENT_DB_BYTES_2_TRUNCATE_SHIFT 0
-#define USTORM_ISCSI_PLACEMENT_DB_HOST_SGE_INDEX (0xFF<<24)
-#define USTORM_ISCSI_PLACEMENT_DB_HOST_SGE_INDEX_SHIFT 24
-	u32 nal;
-#define USTORM_ISCSI_PLACEMENT_DB_REM_SGE_SIZE (0xFFFFFF<<0)
-#define USTORM_ISCSI_PLACEMENT_DB_REM_SGE_SIZE_SHIFT 0
-#define USTORM_ISCSI_PLACEMENT_DB_EXP_DIGEST_3B (0xFF<<24)
-#define USTORM_ISCSI_PLACEMENT_DB_EXP_DIGEST_3B_SHIFT 24
-};
-
-/*
- * Ustorm iSCSI Storm Context
- */
-struct ustorm_iscsi_st_context {
-	u32 exp_stat_sn;
-	u32 exp_data_sn;
-	struct rings_db ring;
-	struct regpair task_pbl_base;
-	struct regpair tce_phy_addr;
-	struct ustorm_iscsi_placement_db place_db;
-	u32 reserved8;
-	u32 rem_rcv_len;
-#if defined(__BIG_ENDIAN)
-	u16 hdr_itt;
-	u16 iscsi_conn_id;
-#elif defined(__LITTLE_ENDIAN)
-	u16 iscsi_conn_id;
-	u16 hdr_itt;
-#endif
-	u32 nal_bytes;
-#if defined(__BIG_ENDIAN)
-	u8 hdr_second_byte_union;
-	u8 bitfield_0;
-#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU (0x1<<0)
-#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU_SHIFT 0
-#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE (0x1<<1)
-#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE_SHIFT 1
-#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC (0x1<<2)
-#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC_SHIFT 2
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x1F<<3)
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 3
-	u8 task_pdu_cache_index;
-	u8 task_pbe_cache_index;
-#elif defined(__LITTLE_ENDIAN)
-	u8 task_pbe_cache_index;
-	u8 task_pdu_cache_index;
-	u8 bitfield_0;
-#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU (0x1<<0)
-#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU_SHIFT 0
-#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE (0x1<<1)
-#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE_SHIFT 1
-#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC (0x1<<2)
-#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC_SHIFT 2
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x1F<<3)
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 3
-	u8 hdr_second_byte_union;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 reserved3;
-	u8 reserved2;
-	u8 acDecrement;
-#elif defined(__LITTLE_ENDIAN)
-	u8 acDecrement;
-	u8 reserved2;
-	u16 reserved3;
-#endif
-	u32 task_stat;
-#if defined(__BIG_ENDIAN)
-	u8 hdr_opcode;
-	u8 num_cqs;
-	u16 reserved5;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved5;
-	u8 num_cqs;
-	u8 hdr_opcode;
-#endif
-	u32 negotiated_rx;
-#define USTORM_ISCSI_ST_CONTEXT_MAX_RECV_PDU_LENGTH (0xFFFFFF<<0)
-#define USTORM_ISCSI_ST_CONTEXT_MAX_RECV_PDU_LENGTH_SHIFT 0
-#define USTORM_ISCSI_ST_CONTEXT_MAX_OUTSTANDING_R2TS (0xFF<<24)
-#define USTORM_ISCSI_ST_CONTEXT_MAX_OUTSTANDING_R2TS_SHIFT 24
-	u32 negotiated_rx_and_flags;
-#define USTORM_ISCSI_ST_CONTEXT_MAX_BURST_LENGTH (0xFFFFFF<<0)
-#define USTORM_ISCSI_ST_CONTEXT_MAX_BURST_LENGTH_SHIFT 0
-#define USTORM_ISCSI_ST_CONTEXT_B_CQE_POSTED_OR_HEADER_CACHED (0x1<<24)
-#define USTORM_ISCSI_ST_CONTEXT_B_CQE_POSTED_OR_HEADER_CACHED_SHIFT 24
-#define USTORM_ISCSI_ST_CONTEXT_B_HDR_DIGEST_EN (0x1<<25)
-#define USTORM_ISCSI_ST_CONTEXT_B_HDR_DIGEST_EN_SHIFT 25
-#define USTORM_ISCSI_ST_CONTEXT_B_DATA_DIGEST_EN (0x1<<26)
-#define USTORM_ISCSI_ST_CONTEXT_B_DATA_DIGEST_EN_SHIFT 26
-#define USTORM_ISCSI_ST_CONTEXT_B_PROTOCOL_ERROR (0x1<<27)
-#define USTORM_ISCSI_ST_CONTEXT_B_PROTOCOL_ERROR_SHIFT 27
-#define USTORM_ISCSI_ST_CONTEXT_B_TASK_VALID (0x1<<28)
-#define USTORM_ISCSI_ST_CONTEXT_B_TASK_VALID_SHIFT 28
-#define USTORM_ISCSI_ST_CONTEXT_TASK_TYPE (0x3<<29)
-#define USTORM_ISCSI_ST_CONTEXT_TASK_TYPE_SHIFT 29
-#define USTORM_ISCSI_ST_CONTEXT_B_ALL_DATA_ACKED (0x1<<31)
-#define USTORM_ISCSI_ST_CONTEXT_B_ALL_DATA_ACKED_SHIFT 31
-};
-
-/*
- * TCP context region, shared in TOE, RDMA and ISCSI
- */
-struct tstorm_tcp_st_context_section {
-	u32 flags1;
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT (0xFFFFFF<<0)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT_SHIFT 0
-#define TSTORM_TCP_ST_CONTEXT_SECTION_PAWS_INVALID (0x1<<24)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_PAWS_INVALID_SHIFT 24
-#define TSTORM_TCP_ST_CONTEXT_SECTION_TIMESTAMP_EXISTS (0x1<<25)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_TIMESTAMP_EXISTS_SHIFT 25
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED0 (0x1<<26)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED0_SHIFT 26
-#define TSTORM_TCP_ST_CONTEXT_SECTION_STOP_RX_PAYLOAD (0x1<<27)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_STOP_RX_PAYLOAD_SHIFT 27
-#define TSTORM_TCP_ST_CONTEXT_SECTION_KA_ENABLED (0x1<<28)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_KA_ENABLED_SHIFT 28
-#define TSTORM_TCP_ST_CONTEXT_SECTION_FIRST_RTO_ESTIMATE (0x1<<29)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_FIRST_RTO_ESTIMATE_SHIFT 29
-#define TSTORM_TCP_ST_CONTEXT_SECTION_MAX_SEG_RETRANSMIT_EN (0x1<<30)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_MAX_SEG_RETRANSMIT_EN_SHIFT 30
-#define TSTORM_TCP_ST_CONTEXT_SECTION_LAST_ISLE_HAS_FIN (0x1<<31)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_LAST_ISLE_HAS_FIN_SHIFT 31
-	u32 flags2;
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION (0xFFFFFF<<0)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION_SHIFT 0
-#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN (0x1<<24)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN_SHIFT 24
-#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_COUNTER_EN (0x1<<25)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_COUNTER_EN_SHIFT 25
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_KA_PROBE_SENT (0x1<<26)
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_KA_PROBE_SENT_SHIFT 26
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_PERSIST_PROBE_SENT (0x1<<27)
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_PERSIST_PROBE_SENT_SHIFT 27
-#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<28)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 28
-#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<29)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 29
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_RST_ATTACK (0x1<<30)
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_RST_ATTACK_SHIFT 30
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_SYN_ATTACK (0x1<<31)
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_SYN_ATTACK_SHIFT 31
-#if defined(__BIG_ENDIAN)
-	u16 mss;
-	u8 tcp_sm_state;
-	u8 rto_exp;
-#elif defined(__LITTLE_ENDIAN)
-	u8 rto_exp;
-	u8 tcp_sm_state;
-	u16 mss;
-#endif
-	u32 rcv_nxt;
-	u32 timestamp_recent;
-	u32 timestamp_recent_time;
-	u32 cwnd;
-	u32 ss_thresh;
-	u32 cwnd_accum;
-	u32 prev_seg_seq;
-	u32 expected_rel_seq;
-	u32 recover;
-#if defined(__BIG_ENDIAN)
-	u8 retransmit_count;
-	u8 ka_max_probe_count;
-	u8 persist_probe_count;
-	u8 ka_probe_count;
-#elif defined(__LITTLE_ENDIAN)
-	u8 ka_probe_count;
-	u8 persist_probe_count;
-	u8 ka_max_probe_count;
-	u8 retransmit_count;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 statistics_counter_id;
-	u8 ooo_support_mode;
-	u8 snd_wnd_scale;
-	u8 dup_ack_count;
-#elif defined(__LITTLE_ENDIAN)
-	u8 dup_ack_count;
-	u8 snd_wnd_scale;
-	u8 ooo_support_mode;
-	u8 statistics_counter_id;
-#endif
-	u32 retransmit_start_time;
-	u32 ka_timeout;
-	u32 ka_interval;
-	u32 isle_start_seq;
-	u32 isle_end_seq;
-#if defined(__BIG_ENDIAN)
-	u16 second_isle_address;
-	u16 recent_seg_wnd;
-#elif defined(__LITTLE_ENDIAN)
-	u16 recent_seg_wnd;
-	u16 second_isle_address;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 max_isles_ever_happened;
-	u8 isles_number;
-	u16 last_isle_address;
-#elif defined(__LITTLE_ENDIAN)
-	u16 last_isle_address;
-	u8 isles_number;
-	u8 max_isles_ever_happened;
-#endif
-	u32 max_rt_time;
-#if defined(__BIG_ENDIAN)
-	u16 lsb_mac_address;
-	u16 vlan_id;
-#elif defined(__LITTLE_ENDIAN)
-	u16 vlan_id;
-	u16 lsb_mac_address;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 msb_mac_address;
-	u16 mid_mac_address;
-#elif defined(__LITTLE_ENDIAN)
-	u16 mid_mac_address;
-	u16 msb_mac_address;
-#endif
-	u32 rightmost_received_seq;
-};
-
-/*
- * Termination variables
- */
-struct iscsi_term_vars {
-	u8 BitMap;
-#define ISCSI_TERM_VARS_TCP_STATE (0xF<<0)
-#define ISCSI_TERM_VARS_TCP_STATE_SHIFT 0
-#define ISCSI_TERM_VARS_FIN_RECEIVED_SBIT (0x1<<4)
-#define ISCSI_TERM_VARS_FIN_RECEIVED_SBIT_SHIFT 4
-#define ISCSI_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT (0x1<<5)
-#define ISCSI_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT_SHIFT 5
-#define ISCSI_TERM_VARS_TERM_ON_CHIP (0x1<<6)
-#define ISCSI_TERM_VARS_TERM_ON_CHIP_SHIFT 6
-#define ISCSI_TERM_VARS_RSRV (0x1<<7)
-#define ISCSI_TERM_VARS_RSRV_SHIFT 7
-};
-
-/*
- * iSCSI context region, used only in iSCSI
- */
-struct tstorm_iscsi_st_context_section {
-	u32 nalPayload;
-	u32 b2nh;
-#if defined(__BIG_ENDIAN)
-	u16 rq_cons;
-	u8 flags;
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN (0x1<<0)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN_SHIFT 0
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN (0x1<<1)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN_SHIFT 1
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER (0x1<<2)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER_SHIFT 2
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE (0x1<<3)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE_SHIFT 3
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS (0x1<<4)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS_SHIFT 4
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_NALLEN (0x3<<5)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_NALLEN_SHIFT 5
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_RSRV0 (0x1<<7)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_RSRV0_SHIFT 7
-	u8 hdr_bytes_2_fetch;
-#elif defined(__LITTLE_ENDIAN)
-	u8 hdr_bytes_2_fetch;
-	u8 flags;
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN (0x1<<0)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN_SHIFT 0
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN (0x1<<1)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN_SHIFT 1
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER (0x1<<2)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER_SHIFT 2
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE (0x1<<3)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE_SHIFT 3
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS (0x1<<4)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS_SHIFT 4
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_NALLEN (0x3<<5)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_NALLEN_SHIFT 5
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_RSRV0 (0x1<<7)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_RSRV0_SHIFT 7
-	u16 rq_cons;
-#endif
-	struct regpair rq_db_phy_addr;
-#if defined(__BIG_ENDIAN)
-	struct iscsi_term_vars term_vars;
-	u8 rsrv1;
-	u16 iscsi_conn_id;
-#elif defined(__LITTLE_ENDIAN)
-	u16 iscsi_conn_id;
-	u8 rsrv1;
-	struct iscsi_term_vars term_vars;
-#endif
-	u32 process_nxt;
-};
-
-/*
- * The iSCSI non-aggregative context of Tstorm
- */
-struct tstorm_iscsi_st_context {
-	struct tstorm_tcp_st_context_section tcp;
-	struct tstorm_iscsi_st_context_section iscsi;
-};
-
-/*
- * Ethernet context section, shared in TOE, RDMA and ISCSI
- */
-struct xstorm_eth_context_section {
-#if defined(__BIG_ENDIAN)
-	u8 remote_addr_4;
-	u8 remote_addr_5;
-	u8 local_addr_0;
-	u8 local_addr_1;
-#elif defined(__LITTLE_ENDIAN)
-	u8 local_addr_1;
-	u8 local_addr_0;
-	u8 remote_addr_5;
-	u8 remote_addr_4;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 remote_addr_0;
-	u8 remote_addr_1;
-	u8 remote_addr_2;
-	u8 remote_addr_3;
-#elif defined(__LITTLE_ENDIAN)
-	u8 remote_addr_3;
-	u8 remote_addr_2;
-	u8 remote_addr_1;
-	u8 remote_addr_0;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 reserved_vlan_type;
-	u16 params;
-#define XSTORM_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
-#define XSTORM_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
-#define XSTORM_ETH_CONTEXT_SECTION_CFI (0x1<<12)
-#define XSTORM_ETH_CONTEXT_SECTION_CFI_SHIFT 12
-#define XSTORM_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
-#define XSTORM_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
-#elif defined(__LITTLE_ENDIAN)
-	u16 params;
-#define XSTORM_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
-#define XSTORM_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
-#define XSTORM_ETH_CONTEXT_SECTION_CFI (0x1<<12)
-#define XSTORM_ETH_CONTEXT_SECTION_CFI_SHIFT 12
-#define XSTORM_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
-#define XSTORM_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
-	u16 reserved_vlan_type;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 local_addr_2;
-	u8 local_addr_3;
-	u8 local_addr_4;
-	u8 local_addr_5;
-#elif defined(__LITTLE_ENDIAN)
-	u8 local_addr_5;
-	u8 local_addr_4;
-	u8 local_addr_3;
-	u8 local_addr_2;
-#endif
-};
-
-/*
- * IpV4 context section, shared in TOE, RDMA and ISCSI
- */
-struct xstorm_ip_v4_context_section {
-#if defined(__BIG_ENDIAN)
-	u16 __pbf_hdr_cmd_rsvd_id;
-	u16 __pbf_hdr_cmd_rsvd_flags_offset;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __pbf_hdr_cmd_rsvd_flags_offset;
-	u16 __pbf_hdr_cmd_rsvd_id;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __pbf_hdr_cmd_rsvd_ver_ihl;
-	u8 tos;
-	u16 __pbf_hdr_cmd_rsvd_length;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __pbf_hdr_cmd_rsvd_length;
-	u8 tos;
-	u8 __pbf_hdr_cmd_rsvd_ver_ihl;
-#endif
-	u32 ip_local_addr;
-#if defined(__BIG_ENDIAN)
-	u8 ttl;
-	u8 __pbf_hdr_cmd_rsvd_protocol;
-	u16 __pbf_hdr_cmd_rsvd_csum;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __pbf_hdr_cmd_rsvd_csum;
-	u8 __pbf_hdr_cmd_rsvd_protocol;
-	u8 ttl;
-#endif
-	u32 __pbf_hdr_cmd_rsvd_1;
-	u32 ip_remote_addr;
-};
-
-/*
- * context section, shared in TOE, RDMA and ISCSI
- */
-struct xstorm_padded_ip_v4_context_section {
-	struct xstorm_ip_v4_context_section ip_v4;
-	u32 reserved1[4];
-};
-
-/*
- * IpV6 context section, shared in TOE, RDMA and ISCSI
- */
-struct xstorm_ip_v6_context_section {
-#if defined(__BIG_ENDIAN)
-	u16 pbf_hdr_cmd_rsvd_payload_len;
-	u8 pbf_hdr_cmd_rsvd_nxt_hdr;
-	u8 hop_limit;
-#elif defined(__LITTLE_ENDIAN)
-	u8 hop_limit;
-	u8 pbf_hdr_cmd_rsvd_nxt_hdr;
-	u16 pbf_hdr_cmd_rsvd_payload_len;
-#endif
-	u32 priority_flow_label;
-#define XSTORM_IP_V6_CONTEXT_SECTION_FLOW_LABEL (0xFFFFF<<0)
-#define XSTORM_IP_V6_CONTEXT_SECTION_FLOW_LABEL_SHIFT 0
-#define XSTORM_IP_V6_CONTEXT_SECTION_TRAFFIC_CLASS (0xFF<<20)
-#define XSTORM_IP_V6_CONTEXT_SECTION_TRAFFIC_CLASS_SHIFT 20
-#define XSTORM_IP_V6_CONTEXT_SECTION_PBF_HDR_CMD_RSVD_VER (0xF<<28)
-#define XSTORM_IP_V6_CONTEXT_SECTION_PBF_HDR_CMD_RSVD_VER_SHIFT 28
-	u32 ip_local_addr_lo_hi;
-	u32 ip_local_addr_lo_lo;
-	u32 ip_local_addr_hi_hi;
-	u32 ip_local_addr_hi_lo;
-	u32 ip_remote_addr_lo_hi;
-	u32 ip_remote_addr_lo_lo;
-	u32 ip_remote_addr_hi_hi;
-	u32 ip_remote_addr_hi_lo;
-};
-
-union xstorm_ip_context_section_types {
-	struct xstorm_padded_ip_v4_context_section padded_ip_v4;
-	struct xstorm_ip_v6_context_section ip_v6;
-};
-
-/*
- * TCP context section, shared in TOE, RDMA and ISCSI
- */
-struct xstorm_tcp_context_section {
-	u32 snd_max;
-#if defined(__BIG_ENDIAN)
-	u16 remote_port;
-	u16 local_port;
-#elif defined(__LITTLE_ENDIAN)
-	u16 local_port;
-	u16 remote_port;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 original_nagle_1b;
-	u8 ts_enabled;
-	u16 tcp_params;
-#define XSTORM_TCP_CONTEXT_SECTION_TOTAL_HEADER_SIZE (0xFF<<0)
-#define XSTORM_TCP_CONTEXT_SECTION_TOTAL_HEADER_SIZE_SHIFT 0
-#define __XSTORM_TCP_CONTEXT_SECTION_ECT_BIT (0x1<<8)
-#define __XSTORM_TCP_CONTEXT_SECTION_ECT_BIT_SHIFT 8
-#define __XSTORM_TCP_CONTEXT_SECTION_ECN_ENABLED (0x1<<9)
-#define __XSTORM_TCP_CONTEXT_SECTION_ECN_ENABLED_SHIFT 9
-#define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED (0x1<<10)
-#define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED_SHIFT 10
-#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV (0x1<<11)
-#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV_SHIFT 11
-#define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<12)
-#define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 12
-#define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED (0x1<<13)
-#define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED_SHIFT 13
-#define XSTORM_TCP_CONTEXT_SECTION_SLOWPATH_QUEUES_FLUSH_COUNTER (0x3<<14)
-#define XSTORM_TCP_CONTEXT_SECTION_SLOWPATH_QUEUES_FLUSH_COUNTER_SHIFT 14
-#elif defined(__LITTLE_ENDIAN)
-	u16 tcp_params;
-#define XSTORM_TCP_CONTEXT_SECTION_TOTAL_HEADER_SIZE (0xFF<<0)
-#define XSTORM_TCP_CONTEXT_SECTION_TOTAL_HEADER_SIZE_SHIFT 0
-#define __XSTORM_TCP_CONTEXT_SECTION_ECT_BIT (0x1<<8)
-#define __XSTORM_TCP_CONTEXT_SECTION_ECT_BIT_SHIFT 8
-#define __XSTORM_TCP_CONTEXT_SECTION_ECN_ENABLED (0x1<<9)
-#define __XSTORM_TCP_CONTEXT_SECTION_ECN_ENABLED_SHIFT 9
-#define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED (0x1<<10)
-#define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED_SHIFT 10
-#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV (0x1<<11)
-#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV_SHIFT 11
-#define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<12)
-#define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 12
-#define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED (0x1<<13)
-#define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED_SHIFT 13
-#define XSTORM_TCP_CONTEXT_SECTION_SLOWPATH_QUEUES_FLUSH_COUNTER (0x3<<14)
-#define XSTORM_TCP_CONTEXT_SECTION_SLOWPATH_QUEUES_FLUSH_COUNTER_SHIFT 14
-	u8 ts_enabled;
-	u8 original_nagle_1b;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 pseudo_csum;
-	u16 window_scaling_factor;
-#elif defined(__LITTLE_ENDIAN)
-	u16 window_scaling_factor;
-	u16 pseudo_csum;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 reserved2;
-	u8 statistics_counter_id;
-	u8 statistics_params;
-#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<0)
-#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 0
-#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<1)
-#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
-#define XSTORM_TCP_CONTEXT_SECTION_RESERVED (0x3F<<2)
-#define XSTORM_TCP_CONTEXT_SECTION_RESERVED_SHIFT 2
-#elif defined(__LITTLE_ENDIAN)
-	u8 statistics_params;
-#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<0)
-#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 0
-#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<1)
-#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
-#define XSTORM_TCP_CONTEXT_SECTION_RESERVED (0x3F<<2)
-#define XSTORM_TCP_CONTEXT_SECTION_RESERVED_SHIFT 2
-	u8 statistics_counter_id;
-	u16 reserved2;
-#endif
-	u32 ts_time_diff;
-	u32 __next_timer_expir;
-};
-
-/*
- * Common context section, shared in TOE, RDMA and ISCSI
- */
-struct xstorm_common_context_section {
-	struct xstorm_eth_context_section ethernet;
-	union xstorm_ip_context_section_types ip_union;
-	struct xstorm_tcp_context_section tcp;
-#if defined(__BIG_ENDIAN)
-	u8 __dcb_val;
-	u8 flags;
-#define XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED (0x1<<0)
-#define XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED_SHIFT 0
-#define XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT (0x7<<1)
-#define XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT_SHIFT 1
-#define XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE (0x1<<4)
-#define XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE_SHIFT 4
-#define XSTORM_COMMON_CONTEXT_SECTION_ORIGINAL_PRIORITY (0x7<<5)
-#define XSTORM_COMMON_CONTEXT_SECTION_ORIGINAL_PRIORITY_SHIFT 5
-	u8 reserved;
-	u8 ip_version_1b;
-#elif defined(__LITTLE_ENDIAN)
-	u8 ip_version_1b;
-	u8 reserved;
-	u8 flags;
-#define XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED (0x1<<0)
-#define XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED_SHIFT 0
-#define XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT (0x7<<1)
-#define XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT_SHIFT 1
-#define XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE (0x1<<4)
-#define XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE_SHIFT 4
-#define XSTORM_COMMON_CONTEXT_SECTION_ORIGINAL_PRIORITY (0x7<<5)
-#define XSTORM_COMMON_CONTEXT_SECTION_ORIGINAL_PRIORITY_SHIFT 5
-	u8 __dcb_val;
-#endif
-};
-
-/*
- * Flags used in ISCSI context section
- */
-struct xstorm_iscsi_context_flags {
-	u8 flags;
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_IMMEDIATE_DATA (0x1<<0)
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_IMMEDIATE_DATA_SHIFT 0
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_INITIAL_R2T (0x1<<1)
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_INITIAL_R2T_SHIFT 1
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_EN_HEADER_DIGEST (0x1<<2)
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_EN_HEADER_DIGEST_SHIFT 2
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_EN_DATA_DIGEST (0x1<<3)
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_EN_DATA_DIGEST_SHIFT 3
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_HQ_BD_WRITTEN (0x1<<4)
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_HQ_BD_WRITTEN_SHIFT 4
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_LAST_OP_SQ (0x1<<5)
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_LAST_OP_SQ_SHIFT 5
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_UPDATE_SND_NXT (0x1<<6)
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_UPDATE_SND_NXT_SHIFT 6
-#define XSTORM_ISCSI_CONTEXT_FLAGS_RESERVED4 (0x1<<7)
-#define XSTORM_ISCSI_CONTEXT_FLAGS_RESERVED4_SHIFT 7
-};
-
-struct iscsi_task_context_entry_x {
-	u32 data_out_buffer_offset;
-	u32 itt;
-	u32 data_sn;
-};
-
-struct iscsi_task_context_entry_xuc_x_write_only {
-	u32 tx_r2t_sn;
-};
-
-struct iscsi_task_context_entry_xuc_xu_write_both {
-	u32 sgl_base_lo;
-	u32 sgl_base_hi;
-#if defined(__BIG_ENDIAN)
-	u8 sgl_size;
-	u8 sge_index;
-	u16 sge_offset;
-#elif defined(__LITTLE_ENDIAN)
-	u16 sge_offset;
-	u8 sge_index;
-	u8 sgl_size;
-#endif
-};
-
-/*
- * iSCSI context section
- */
-struct xstorm_iscsi_context_section {
-	u32 first_burst_length;
-	u32 max_send_pdu_length;
-	struct regpair sq_pbl_base;
-	struct regpair sq_curr_pbe;
-	struct regpair hq_pbl_base;
-	struct regpair hq_curr_pbe_base;
-	struct regpair r2tq_pbl_base;
-	struct regpair r2tq_curr_pbe_base;
-	struct regpair task_pbl_base;
-#if defined(__BIG_ENDIAN)
-	u16 data_out_count;
-	struct xstorm_iscsi_context_flags flags;
-	u8 task_pbl_cache_idx;
-#elif defined(__LITTLE_ENDIAN)
-	u8 task_pbl_cache_idx;
-	struct xstorm_iscsi_context_flags flags;
-	u16 data_out_count;
-#endif
-	u32 seq_more_2_send;
-	u32 pdu_more_2_send;
-	struct iscsi_task_context_entry_x temp_tce_x;
-	struct iscsi_task_context_entry_xuc_x_write_only temp_tce_x_wr;
-	struct iscsi_task_context_entry_xuc_xu_write_both temp_tce_xu_wr;
-	struct regpair lun;
-	u32 exp_data_transfer_len_ttt;
-	u32 pdu_data_2_rxmit;
-	u32 rxmit_bytes_2_dr;
-#if defined(__BIG_ENDIAN)
-	u16 rxmit_sge_offset;
-	u16 hq_rxmit_cons;
-#elif defined(__LITTLE_ENDIAN)
-	u16 hq_rxmit_cons;
-	u16 rxmit_sge_offset;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 r2tq_cons;
-	u8 rxmit_flags;
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_NEW_HQ_BD (0x1<<0)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_NEW_HQ_BD_SHIFT 0
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PDU_HDR (0x1<<1)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PDU_HDR_SHIFT 1
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_END_PDU (0x1<<2)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_END_PDU_SHIFT 2
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_DR (0x1<<3)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_DR_SHIFT 3
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_START_DR (0x1<<4)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_START_DR_SHIFT 4
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PADDING (0x3<<5)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PADDING_SHIFT 5
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_ISCSI_CONT_FAST_RXMIT (0x1<<7)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_ISCSI_CONT_FAST_RXMIT_SHIFT 7
-	u8 rxmit_sge_idx;
-#elif defined(__LITTLE_ENDIAN)
-	u8 rxmit_sge_idx;
-	u8 rxmit_flags;
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_NEW_HQ_BD (0x1<<0)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_NEW_HQ_BD_SHIFT 0
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PDU_HDR (0x1<<1)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PDU_HDR_SHIFT 1
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_END_PDU (0x1<<2)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_END_PDU_SHIFT 2
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_DR (0x1<<3)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_DR_SHIFT 3
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_START_DR (0x1<<4)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_START_DR_SHIFT 4
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PADDING (0x3<<5)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PADDING_SHIFT 5
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_ISCSI_CONT_FAST_RXMIT (0x1<<7)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_ISCSI_CONT_FAST_RXMIT_SHIFT 7
-	u16 r2tq_cons;
-#endif
-	u32 hq_rxmit_tcp_seq;
-};
-
-/*
- * Xstorm iSCSI Storm Context
- */
-struct xstorm_iscsi_st_context {
-	struct xstorm_common_context_section common;
-	struct xstorm_iscsi_context_section iscsi;
-};
-
-/*
- * Iscsi connection context
- */
-struct iscsi_context {
-	struct ustorm_iscsi_st_context ustorm_st_context;
-	struct tstorm_iscsi_st_context tstorm_st_context;
-	struct xstorm_iscsi_ag_context xstorm_ag_context;
-	struct tstorm_iscsi_ag_context tstorm_ag_context;
-	struct cstorm_iscsi_ag_context cstorm_ag_context;
-	struct ustorm_iscsi_ag_context ustorm_ag_context;
-	struct timers_block_context timers_context;
-	struct regpair upb_context;
-	struct xstorm_iscsi_st_context xstorm_st_context;
-	struct regpair xpb_context;
-	struct cstorm_iscsi_st_context cstorm_st_context;
-};
-
-
-/*
- * PDU header of an iSCSI DATA-OUT
- */
-struct iscsi_data_pdu_hdr_little_endian {
-#if defined(__BIG_ENDIAN)
-	u8 opcode;
-	u8 op_attr;
-#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_RSRV1 (0x7F<<0)
-#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
-#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG (0x1<<7)
-#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG_SHIFT 7
-	u16 rsrv0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rsrv0;
-	u8 op_attr;
-#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_RSRV1 (0x7F<<0)
-#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
-#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG (0x1<<7)
-#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG_SHIFT 7
-	u8 opcode;
-#endif
-	u32 data_fields;
-#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
-#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
-#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
-#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
-	struct regpair lun;
-	u32 itt;
-	u32 ttt;
-	u32 rsrv2;
-	u32 exp_stat_sn;
-	u32 rsrv3;
-	u32 data_sn;
-	u32 buffer_offset;
-	u32 rsrv4;
-};
-
-
-/*
- * PDU header of an iSCSI login request
- */
-struct iscsi_login_req_hdr_little_endian {
-#if defined(__BIG_ENDIAN)
-	u8 opcode;
-	u8 op_attr;
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_NSG (0x3<<0)
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_NSG_SHIFT 0
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CSG (0x3<<2)
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CSG_SHIFT 2
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_RSRV0 (0x3<<4)
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_RSRV0_SHIFT 4
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG (0x1<<6)
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG_SHIFT 6
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TRANSIT (0x1<<7)
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TRANSIT_SHIFT 7
-	u8 version_max;
-	u8 version_min;
-#elif defined(__LITTLE_ENDIAN)
-	u8 version_min;
-	u8 version_max;
-	u8 op_attr;
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_NSG (0x3<<0)
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_NSG_SHIFT 0
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CSG (0x3<<2)
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CSG_SHIFT 2
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_RSRV0 (0x3<<4)
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_RSRV0_SHIFT 4
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG (0x1<<6)
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG_SHIFT 6
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TRANSIT (0x1<<7)
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TRANSIT_SHIFT 7
-	u8 opcode;
-#endif
-	u32 data_fields;
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
-#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
-	u32 isid_lo;
-#if defined(__BIG_ENDIAN)
-	u16 isid_hi;
-	u16 tsih;
-#elif defined(__LITTLE_ENDIAN)
-	u16 tsih;
-	u16 isid_hi;
-#endif
-	u32 itt;
-#if defined(__BIG_ENDIAN)
-	u16 cid;
-	u16 rsrv1;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rsrv1;
-	u16 cid;
-#endif
-	u32 cmd_sn;
-	u32 exp_stat_sn;
-	u32 rsrv2[4];
-};
-
-/*
- * PDU header of an iSCSI logout request
- */
-struct iscsi_logout_req_hdr_little_endian {
-#if defined(__BIG_ENDIAN)
-	u8 opcode;
-	u8 op_attr;
-#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_REASON_CODE (0x7F<<0)
-#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_REASON_CODE_SHIFT 0
-#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_RSRV1_1 (0x1<<7)
-#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_RSRV1_1_SHIFT 7
-	u16 rsrv0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rsrv0;
-	u8 op_attr;
-#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_REASON_CODE (0x7F<<0)
-#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_REASON_CODE_SHIFT 0
-#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_RSRV1_1 (0x1<<7)
-#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_RSRV1_1_SHIFT 7
-	u8 opcode;
-#endif
-	u32 data_fields;
-#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
-#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
-#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
-#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
-	u32 rsrv2[2];
-	u32 itt;
-#if defined(__BIG_ENDIAN)
-	u16 cid;
-	u16 rsrv1;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rsrv1;
-	u16 cid;
-#endif
-	u32 cmd_sn;
-	u32 exp_stat_sn;
-	u32 rsrv3[4];
-};
-
-/*
- * PDU header of an iSCSI TMF request
- */
-struct iscsi_tmf_req_hdr_little_endian {
-#if defined(__BIG_ENDIAN)
-	u8 opcode;
-	u8 op_attr;
-#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_FUNCTION (0x7F<<0)
-#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_FUNCTION_SHIFT 0
-#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_RSRV1_1 (0x1<<7)
-#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_RSRV1_1_SHIFT 7
-	u16 rsrv0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rsrv0;
-	u8 op_attr;
-#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_FUNCTION (0x7F<<0)
-#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_FUNCTION_SHIFT 0
-#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_RSRV1_1 (0x1<<7)
-#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_RSRV1_1_SHIFT 7
-	u8 opcode;
-#endif
-	u32 data_fields;
-#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
-#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
-#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
-#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
-	struct regpair lun;
-	u32 itt;
-	u32 referenced_task_tag;
-	u32 cmd_sn;
-	u32 exp_stat_sn;
-	u32 ref_cmd_sn;
-	u32 exp_data_sn;
-	u32 rsrv2[2];
-};
-
-/*
- * PDU header of an iSCSI Text request
- */
-struct iscsi_text_req_hdr_little_endian {
-#if defined(__BIG_ENDIAN)
-	u8 opcode;
-	u8 op_attr;
-#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_RSRV1 (0x3F<<0)
-#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
-#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG (0x1<<6)
-#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG_SHIFT 6
-#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_FINAL (0x1<<7)
-#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_FINAL_SHIFT 7
-	u16 rsrv0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rsrv0;
-	u8 op_attr;
-#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_RSRV1 (0x3F<<0)
-#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
-#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG (0x1<<6)
-#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG_SHIFT 6
-#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_FINAL (0x1<<7)
-#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_FINAL_SHIFT 7
-	u8 opcode;
-#endif
-	u32 data_fields;
-#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
-#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
-#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
-#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
-	struct regpair lun;
-	u32 itt;
-	u32 ttt;
-	u32 cmd_sn;
-	u32 exp_stat_sn;
-	u32 rsrv3[4];
-};
-
-/*
- * PDU header of an iSCSI Nop-Out
- */
-struct iscsi_nop_out_hdr_little_endian {
-#if defined(__BIG_ENDIAN)
-	u8 opcode;
-	u8 op_attr;
-#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV1 (0x7F<<0)
-#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
-#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV2_1 (0x1<<7)
-#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV2_1_SHIFT 7
-	u16 rsrv0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rsrv0;
-	u8 op_attr;
-#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV1 (0x7F<<0)
-#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
-#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV2_1 (0x1<<7)
-#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV2_1_SHIFT 7
-	u8 opcode;
-#endif
-	u32 data_fields;
-#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
-#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
-#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
-#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
-	struct regpair lun;
-	u32 itt;
-	u32 ttt;
-	u32 cmd_sn;
-	u32 exp_stat_sn;
-	u32 rsrv3[4];
-};
-
-/*
- * iscsi pdu headers in little endian form.
- */
-union iscsi_pdu_headers_little_endian {
-	u32 fullHeaderSize[12];
-	struct iscsi_cmd_pdu_hdr_little_endian command_pdu_hdr;
-	struct iscsi_data_pdu_hdr_little_endian data_out_pdu_hdr;
-	struct iscsi_login_req_hdr_little_endian login_req_pdu_hdr;
-	struct iscsi_logout_req_hdr_little_endian logout_req_pdu_hdr;
-	struct iscsi_tmf_req_hdr_little_endian tmf_req_pdu_hdr;
-	struct iscsi_text_req_hdr_little_endian text_req_pdu_hdr;
-	struct iscsi_nop_out_hdr_little_endian nop_out_pdu_hdr;
-};
-
-struct iscsi_hq_bd {
-	union iscsi_pdu_headers_little_endian pdu_header;
-#if defined(__BIG_ENDIAN)
-	u16 reserved1;
-	u16 lcl_cmp_flg;
-#elif defined(__LITTLE_ENDIAN)
-	u16 lcl_cmp_flg;
-	u16 reserved1;
-#endif
-	u32 sgl_base_lo;
-	u32 sgl_base_hi;
-#if defined(__BIG_ENDIAN)
-	u8 sgl_size;
-	u8 sge_index;
-	u16 sge_offset;
-#elif defined(__LITTLE_ENDIAN)
-	u16 sge_offset;
-	u8 sge_index;
-	u8 sgl_size;
-#endif
-};
-
-
-/*
- * CQE data for L2 OOO connection $$KEEP_ENDIANNESS$$
- */
-struct iscsi_l2_ooo_data {
-	__le32 iscsi_cid;
-	u8 drop_isle;
-	u8 drop_size;
-	u8 ooo_opcode;
-	u8 ooo_isle;
-	u8 reserved[8];
-};
-
-
-
-
-
-
-struct iscsi_task_context_entry_xuc_c_write_only {
-	u32 total_data_acked;
-};
-
-struct iscsi_task_context_r2t_table_entry {
-	u32 ttt;
-	u32 desired_data_len;
-};
-
-struct iscsi_task_context_entry_xuc_u_write_only {
-	u32 exp_r2t_sn;
-	struct iscsi_task_context_r2t_table_entry r2t_table[4];
-#if defined(__BIG_ENDIAN)
-	u16 data_in_count;
-	u8 cq_id;
-	u8 valid_1b;
-#elif defined(__LITTLE_ENDIAN)
-	u8 valid_1b;
-	u8 cq_id;
-	u16 data_in_count;
-#endif
-};
-
-struct iscsi_task_context_entry_xuc {
-	struct iscsi_task_context_entry_xuc_c_write_only write_c;
-	u32 exp_data_transfer_len;
-	struct iscsi_task_context_entry_xuc_x_write_only write_x;
-	u32 lun_lo;
-	struct iscsi_task_context_entry_xuc_xu_write_both write_xu;
-	u32 lun_hi;
-	struct iscsi_task_context_entry_xuc_u_write_only write_u;
-};
-
-struct iscsi_task_context_entry_u {
-	u32 exp_r2t_buff_offset;
-	u32 rem_rcv_len;
-	u32 exp_data_sn;
-};
-
-struct iscsi_task_context_entry {
-	struct iscsi_task_context_entry_x tce_x;
-#if defined(__BIG_ENDIAN)
-	u16 data_out_count;
-	u16 rsrv0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rsrv0;
-	u16 data_out_count;
-#endif
-	struct iscsi_task_context_entry_xuc tce_xuc;
-	struct iscsi_task_context_entry_u tce_u;
-	u32 rsrv1[7];
-};
-
-
-
-
-
-
-
-
-struct iscsi_task_context_entry_xuc_x_init_only {
-	struct regpair lun;
-	u32 exp_data_transfer_len;
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/*
- * ipv6 structure
- */
-struct ip_v6_addr {
-	u32 ip_addr_lo_lo;
-	u32 ip_addr_lo_hi;
-	u32 ip_addr_hi_lo;
-	u32 ip_addr_hi_hi;
-};
-
-
-
-/*
- * l5cm- connection identification params
- */
-struct l5cm_conn_addr_params {
-	u32 pmtu;
-#if defined(__BIG_ENDIAN)
-	u8 remote_addr_3;
-	u8 remote_addr_2;
-	u8 remote_addr_1;
-	u8 remote_addr_0;
-#elif defined(__LITTLE_ENDIAN)
-	u8 remote_addr_0;
-	u8 remote_addr_1;
-	u8 remote_addr_2;
-	u8 remote_addr_3;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 params;
-#define L5CM_CONN_ADDR_PARAMS_IP_VERSION (0x1<<0)
-#define L5CM_CONN_ADDR_PARAMS_IP_VERSION_SHIFT 0
-#define L5CM_CONN_ADDR_PARAMS_RSRV (0x7FFF<<1)
-#define L5CM_CONN_ADDR_PARAMS_RSRV_SHIFT 1
-	u8 remote_addr_5;
-	u8 remote_addr_4;
-#elif defined(__LITTLE_ENDIAN)
-	u8 remote_addr_4;
-	u8 remote_addr_5;
-	u16 params;
-#define L5CM_CONN_ADDR_PARAMS_IP_VERSION (0x1<<0)
-#define L5CM_CONN_ADDR_PARAMS_IP_VERSION_SHIFT 0
-#define L5CM_CONN_ADDR_PARAMS_RSRV (0x7FFF<<1)
-#define L5CM_CONN_ADDR_PARAMS_RSRV_SHIFT 1
-#endif
-	struct ip_v6_addr local_ip_addr;
-	struct ip_v6_addr remote_ip_addr;
-	u32 ipv6_flow_label_20b;
-	u32 reserved1;
-#if defined(__BIG_ENDIAN)
-	u16 remote_tcp_port;
-	u16 local_tcp_port;
-#elif defined(__LITTLE_ENDIAN)
-	u16 local_tcp_port;
-	u16 remote_tcp_port;
-#endif
-};
-
-/*
- * l5cm-xstorm connection buffer
- */
-struct l5cm_xstorm_conn_buffer {
-#if defined(__BIG_ENDIAN)
-	u16 rsrv1;
-	u16 params;
-#define L5CM_XSTORM_CONN_BUFFER_NAGLE_ENABLE (0x1<<0)
-#define L5CM_XSTORM_CONN_BUFFER_NAGLE_ENABLE_SHIFT 0
-#define L5CM_XSTORM_CONN_BUFFER_RSRV (0x7FFF<<1)
-#define L5CM_XSTORM_CONN_BUFFER_RSRV_SHIFT 1
-#elif defined(__LITTLE_ENDIAN)
-	u16 params;
-#define L5CM_XSTORM_CONN_BUFFER_NAGLE_ENABLE (0x1<<0)
-#define L5CM_XSTORM_CONN_BUFFER_NAGLE_ENABLE_SHIFT 0
-#define L5CM_XSTORM_CONN_BUFFER_RSRV (0x7FFF<<1)
-#define L5CM_XSTORM_CONN_BUFFER_RSRV_SHIFT 1
-	u16 rsrv1;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 mss;
-	u16 pseudo_header_checksum;
-#elif defined(__LITTLE_ENDIAN)
-	u16 pseudo_header_checksum;
-	u16 mss;
-#endif
-	u32 rcv_buf;
-	u32 rsrv2;
-	struct regpair context_addr;
-};
-
-/*
- * l5cm-tstorm connection buffer
- */
-struct l5cm_tstorm_conn_buffer {
-	u32 rsrv1[2];
-#if defined(__BIG_ENDIAN)
-	u16 params;
-#define L5CM_TSTORM_CONN_BUFFER_DELAYED_ACK_ENABLE (0x1<<0)
-#define L5CM_TSTORM_CONN_BUFFER_DELAYED_ACK_ENABLE_SHIFT 0
-#define L5CM_TSTORM_CONN_BUFFER_RSRV (0x7FFF<<1)
-#define L5CM_TSTORM_CONN_BUFFER_RSRV_SHIFT 1
-	u8 ka_max_probe_count;
-	u8 ka_enable;
-#elif defined(__LITTLE_ENDIAN)
-	u8 ka_enable;
-	u8 ka_max_probe_count;
-	u16 params;
-#define L5CM_TSTORM_CONN_BUFFER_DELAYED_ACK_ENABLE (0x1<<0)
-#define L5CM_TSTORM_CONN_BUFFER_DELAYED_ACK_ENABLE_SHIFT 0
-#define L5CM_TSTORM_CONN_BUFFER_RSRV (0x7FFF<<1)
-#define L5CM_TSTORM_CONN_BUFFER_RSRV_SHIFT 1
-#endif
-	u32 ka_timeout;
-	u32 ka_interval;
-	u32 max_rt_time;
-};
-
-/*
- * l5cm connection buffer for active side
- */
-struct l5cm_active_conn_buffer {
-	struct l5cm_conn_addr_params conn_addr_buf;
-	struct l5cm_xstorm_conn_buffer xstorm_conn_buffer;
-	struct l5cm_tstorm_conn_buffer tstorm_conn_buffer;
-};
-
-
-
-/*
- * The l5cm opaque buffer passed in add new connection ramrod passive side
- */
-struct l5cm_hash_input_string {
-	u32 __opaque1;
-#if defined(__BIG_ENDIAN)
-	u16 __opaque3;
-	u16 __opaque2;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __opaque2;
-	u16 __opaque3;
-#endif
-	struct ip_v6_addr __opaque4;
-	struct ip_v6_addr __opaque5;
-	u32 __opaque6;
-	u32 __opaque7[5];
-};
-
-
-/*
- * syn cookie component
- */
-struct l5cm_syn_cookie_comp {
-	u32 __opaque;
-};
-
-/*
- * data related to listeners of a TCP port
- */
-struct l5cm_port_listener_data {
-	u8 params;
-#define L5CM_PORT_LISTENER_DATA_ENABLE (0x1<<0)
-#define L5CM_PORT_LISTENER_DATA_ENABLE_SHIFT 0
-#define L5CM_PORT_LISTENER_DATA_IP_INDEX (0xF<<1)
-#define L5CM_PORT_LISTENER_DATA_IP_INDEX_SHIFT 1
-#define L5CM_PORT_LISTENER_DATA_NET_FILTER (0x1<<5)
-#define L5CM_PORT_LISTENER_DATA_NET_FILTER_SHIFT 5
-#define L5CM_PORT_LISTENER_DATA_DEFFERED_MODE (0x1<<6)
-#define L5CM_PORT_LISTENER_DATA_DEFFERED_MODE_SHIFT 6
-#define L5CM_PORT_LISTENER_DATA_MPA_MODE (0x1<<7)
-#define L5CM_PORT_LISTENER_DATA_MPA_MODE_SHIFT 7
-};
-
-/*
- * Opaque structure passed from U to X when final ack arrives
- */
-struct l5cm_opaque_buf {
-	u32 __opaque1;
-	u32 __opaque2;
-	u32 __opaque3;
-	u32 __opaque4;
-	struct l5cm_syn_cookie_comp __opaque5;
-#if defined(__BIG_ENDIAN)
-	u16 rsrv2;
-	u8 rsrv;
-	struct l5cm_port_listener_data __opaque6;
-#elif defined(__LITTLE_ENDIAN)
-	struct l5cm_port_listener_data __opaque6;
-	u8 rsrv;
-	u16 rsrv2;
-#endif
-};
-
-
-/*
- * l5cm slow path element
- */
-struct l5cm_packet_size {
-	u32 size;
-	u32 rsrv;
-};
-
-
-/*
- * The final-ack union structure in PCS entry after final ack arrived
- */
-struct l5cm_pcse_ack {
-	struct l5cm_xstorm_conn_buffer tx_socket_params;
-	struct l5cm_opaque_buf opaque_buf;
-	struct l5cm_tstorm_conn_buffer rx_socket_params;
-};
-
-
-/*
- * The syn union structure in PCS entry after syn arrived
- */
-struct l5cm_pcse_syn {
-	struct l5cm_opaque_buf opaque_buf;
-	u32 rsrv[12];
-};
-
-
-/*
- * pcs entry data for passive connections
- */
-struct l5cm_pcs_attributes {
-#if defined(__BIG_ENDIAN)
-	u16 pcs_id;
-	u8 status;
-	u8 flags;
-#define L5CM_PCS_ATTRIBUTES_NET_FILTER (0x1<<0)
-#define L5CM_PCS_ATTRIBUTES_NET_FILTER_SHIFT 0
-#define L5CM_PCS_ATTRIBUTES_CALCULATE_HASH (0x1<<1)
-#define L5CM_PCS_ATTRIBUTES_CALCULATE_HASH_SHIFT 1
-#define L5CM_PCS_ATTRIBUTES_COMPARE_HASH_RESULT (0x1<<2)
-#define L5CM_PCS_ATTRIBUTES_COMPARE_HASH_RESULT_SHIFT 2
-#define L5CM_PCS_ATTRIBUTES_QUERY_ULP_ACCEPT (0x1<<3)
-#define L5CM_PCS_ATTRIBUTES_QUERY_ULP_ACCEPT_SHIFT 3
-#define L5CM_PCS_ATTRIBUTES_FIND_DEST_MAC (0x1<<4)
-#define L5CM_PCS_ATTRIBUTES_FIND_DEST_MAC_SHIFT 4
-#define L5CM_PCS_ATTRIBUTES_L4_OFFLOAD (0x1<<5)
-#define L5CM_PCS_ATTRIBUTES_L4_OFFLOAD_SHIFT 5
-#define L5CM_PCS_ATTRIBUTES_FORWARD_PACKET (0x1<<6)
-#define L5CM_PCS_ATTRIBUTES_FORWARD_PACKET_SHIFT 6
-#define L5CM_PCS_ATTRIBUTES_RSRV (0x1<<7)
-#define L5CM_PCS_ATTRIBUTES_RSRV_SHIFT 7
-#elif defined(__LITTLE_ENDIAN)
-	u8 flags;
-#define L5CM_PCS_ATTRIBUTES_NET_FILTER (0x1<<0)
-#define L5CM_PCS_ATTRIBUTES_NET_FILTER_SHIFT 0
-#define L5CM_PCS_ATTRIBUTES_CALCULATE_HASH (0x1<<1)
-#define L5CM_PCS_ATTRIBUTES_CALCULATE_HASH_SHIFT 1
-#define L5CM_PCS_ATTRIBUTES_COMPARE_HASH_RESULT (0x1<<2)
-#define L5CM_PCS_ATTRIBUTES_COMPARE_HASH_RESULT_SHIFT 2
-#define L5CM_PCS_ATTRIBUTES_QUERY_ULP_ACCEPT (0x1<<3)
-#define L5CM_PCS_ATTRIBUTES_QUERY_ULP_ACCEPT_SHIFT 3
-#define L5CM_PCS_ATTRIBUTES_FIND_DEST_MAC (0x1<<4)
-#define L5CM_PCS_ATTRIBUTES_FIND_DEST_MAC_SHIFT 4
-#define L5CM_PCS_ATTRIBUTES_L4_OFFLOAD (0x1<<5)
-#define L5CM_PCS_ATTRIBUTES_L4_OFFLOAD_SHIFT 5
-#define L5CM_PCS_ATTRIBUTES_FORWARD_PACKET (0x1<<6)
-#define L5CM_PCS_ATTRIBUTES_FORWARD_PACKET_SHIFT 6
-#define L5CM_PCS_ATTRIBUTES_RSRV (0x1<<7)
-#define L5CM_PCS_ATTRIBUTES_RSRV_SHIFT 7
-	u8 status;
-	u16 pcs_id;
-#endif
-};
-
-
-union l5cm_seg_params {
-	struct l5cm_pcse_syn syn_seg_params;
-	struct l5cm_pcse_ack ack_seg_params;
-};
-
-/*
- * pcs entry data for passive connections
- */
-struct l5cm_pcs_hdr {
-	struct l5cm_hash_input_string hash_input_string;
-	struct l5cm_conn_addr_params conn_addr_buf;
-	u32 cid;
-	u32 hash_result;
-	union l5cm_seg_params seg_params;
-	struct l5cm_pcs_attributes att;
-#if defined(__BIG_ENDIAN)
-	u16 rsrv;
-	u16 rx_seg_size;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rx_seg_size;
-	u16 rsrv;
-#endif
-};
-
-/*
- * pcs entry for passive connections
- */
-struct l5cm_pcs_entry {
-	struct l5cm_pcs_hdr hdr;
-	u8 rx_segment[1516];
-};
-
-
-
-
-/*
- * l5cm connection parameters
- */
-union l5cm_reduce_param_union {
-	u32 opaque1;
-	u32 opaque2;
-};
-
-/*
- * l5cm connection parameters
- */
-struct l5cm_reduce_conn {
-	union l5cm_reduce_param_union opaque1;
-	u32 opaque2;
-};
-
-/*
- * l5cm slow path element
- */
-union l5cm_specific_data {
-	u8 protocol_data[8];
-	struct regpair phy_address;
-	struct l5cm_packet_size packet_size;
-	struct l5cm_reduce_conn reduced_conn;
-};
-
-/*
- * l5 slow path element
- */
-struct l5cm_spe {
-	struct spe_hdr hdr;
-	union l5cm_specific_data data;
-};
-
-
-
-
-/*
- * Termination variables
- */
-struct l5cm_term_vars {
-	u8 BitMap;
-#define L5CM_TERM_VARS_TCP_STATE (0xF<<0)
-#define L5CM_TERM_VARS_TCP_STATE_SHIFT 0
-#define L5CM_TERM_VARS_FIN_RECEIVED_SBIT (0x1<<4)
-#define L5CM_TERM_VARS_FIN_RECEIVED_SBIT_SHIFT 4
-#define L5CM_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT (0x1<<5)
-#define L5CM_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT_SHIFT 5
-#define L5CM_TERM_VARS_TERM_ON_CHIP (0x1<<6)
-#define L5CM_TERM_VARS_TERM_ON_CHIP_SHIFT 6
-#define L5CM_TERM_VARS_RSRV (0x1<<7)
-#define L5CM_TERM_VARS_RSRV_SHIFT 7
-};
-
-
-
-
-/*
- * Tstorm Tcp flags
- */
-struct tstorm_l5cm_tcp_flags {
-	u16 flags;
-#define TSTORM_L5CM_TCP_FLAGS_VLAN_ID (0xFFF<<0)
-#define TSTORM_L5CM_TCP_FLAGS_VLAN_ID_SHIFT 0
-#define TSTORM_L5CM_TCP_FLAGS_RSRV0 (0x1<<12)
-#define TSTORM_L5CM_TCP_FLAGS_RSRV0_SHIFT 12
-#define TSTORM_L5CM_TCP_FLAGS_TS_ENABLED (0x1<<13)
-#define TSTORM_L5CM_TCP_FLAGS_TS_ENABLED_SHIFT 13
-#define TSTORM_L5CM_TCP_FLAGS_RSRV1 (0x3<<14)
-#define TSTORM_L5CM_TCP_FLAGS_RSRV1_SHIFT 14
-};
-
-
-/*
- * Xstorm Tcp flags
- */
-struct xstorm_l5cm_tcp_flags {
-	u8 flags;
-#define XSTORM_L5CM_TCP_FLAGS_ENC_ENABLED (0x1<<0)
-#define XSTORM_L5CM_TCP_FLAGS_ENC_ENABLED_SHIFT 0
-#define XSTORM_L5CM_TCP_FLAGS_TS_ENABLED (0x1<<1)
-#define XSTORM_L5CM_TCP_FLAGS_TS_ENABLED_SHIFT 1
-#define XSTORM_L5CM_TCP_FLAGS_WND_SCL_EN (0x1<<2)
-#define XSTORM_L5CM_TCP_FLAGS_WND_SCL_EN_SHIFT 2
-#define XSTORM_L5CM_TCP_FLAGS_RSRV (0x1F<<3)
-#define XSTORM_L5CM_TCP_FLAGS_RSRV_SHIFT 3
-};
-
-
-
-/*
- * Out-of-order states
- */
-enum tcp_ooo_event {
-	TCP_EVENT_ADD_PEN = 0,
-	TCP_EVENT_ADD_NEW_ISLE = 1,
-	TCP_EVENT_ADD_ISLE_RIGHT = 2,
-	TCP_EVENT_ADD_ISLE_LEFT = 3,
-	TCP_EVENT_JOIN = 4,
-	TCP_EVENT_NOP = 5,
-	MAX_TCP_OOO_EVENT
-};
-
-
-/*
- * OOO support modes
- */
-enum tcp_tstorm_ooo {
-	TCP_TSTORM_OOO_DROP_AND_PROC_ACK = 0,
-	TCP_TSTORM_OOO_SEND_PURE_ACK = 1,
-	TCP_TSTORM_OOO_SUPPORTED = 2,
-	MAX_TCP_TSTORM_OOO
-};
-
-
-
-
-
-
-
-
-
-#endif /* __5710_HSI_CNIC_LE__ */
diff -druN linux-libre-3.1-gnu/drivers/net/cnic.h linux-libre-3.2-gnu/drivers/net/cnic.h
--- linux-libre-3.1-gnu/drivers/net/cnic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cnic.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,478 +0,0 @@
-/* cnic.h: Broadcom CNIC core network driver.
- *
- * Copyright (c) 2006-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
- * the Free Software Foundation.
- *
- */
-
-
-#ifndef CNIC_H
-#define CNIC_H
-
-#define HC_INDEX_ISCSI_EQ_CONS			6
-
-#define HC_INDEX_FCOE_EQ_CONS			3
-
-#define HC_SP_INDEX_ETH_ISCSI_CQ_CONS		5
-#define HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS	1
-
-#define KWQ_PAGE_CNT	4
-#define KCQ_PAGE_CNT	16
-
-#define KWQ_CID 		24
-#define KCQ_CID 		25
-
-/*
- *	krnlq_context definition
- */
-#define L5_KRNLQ_FLAGS	0x00000000
-#define L5_KRNLQ_SIZE	0x00000000
-#define L5_KRNLQ_TYPE	0x00000000
-#define KRNLQ_FLAGS_PG_SZ					(0xf<<0)
-#define KRNLQ_FLAGS_PG_SZ_256					(0<<0)
-#define KRNLQ_FLAGS_PG_SZ_512					(1<<0)
-#define KRNLQ_FLAGS_PG_SZ_1K					(2<<0)
-#define KRNLQ_FLAGS_PG_SZ_2K					(3<<0)
-#define KRNLQ_FLAGS_PG_SZ_4K					(4<<0)
-#define KRNLQ_FLAGS_PG_SZ_8K					(5<<0)
-#define KRNLQ_FLAGS_PG_SZ_16K					(6<<0)
-#define KRNLQ_FLAGS_PG_SZ_32K					(7<<0)
-#define KRNLQ_FLAGS_PG_SZ_64K					(8<<0)
-#define KRNLQ_FLAGS_PG_SZ_128K					(9<<0)
-#define KRNLQ_FLAGS_PG_SZ_256K					(10<<0)
-#define KRNLQ_FLAGS_PG_SZ_512K					(11<<0)
-#define KRNLQ_FLAGS_PG_SZ_1M					(12<<0)
-#define KRNLQ_FLAGS_PG_SZ_2M					(13<<0)
-#define KRNLQ_FLAGS_QE_SELF_SEQ					(1<<15)
-#define KRNLQ_SIZE_TYPE_SIZE	((((0x28 + 0x1f) & ~0x1f) / 0x20) << 16)
-#define KRNLQ_TYPE_TYPE						(0xf<<28)
-#define KRNLQ_TYPE_TYPE_EMPTY					(0<<28)
-#define KRNLQ_TYPE_TYPE_KRNLQ					(6<<28)
-
-#define L5_KRNLQ_HOST_QIDX		0x00000004
-#define L5_KRNLQ_HOST_FW_QIDX		0x00000008
-#define L5_KRNLQ_NX_QE_SELF_SEQ 	0x0000000c
-#define L5_KRNLQ_QE_SELF_SEQ_MAX	0x0000000c
-#define L5_KRNLQ_NX_QE_HADDR_HI 	0x00000010
-#define L5_KRNLQ_NX_QE_HADDR_LO 	0x00000014
-#define L5_KRNLQ_PGTBL_PGIDX		0x00000018
-#define L5_KRNLQ_NX_PG_QIDX 		0x00000018
-#define L5_KRNLQ_PGTBL_NPAGES		0x0000001c
-#define L5_KRNLQ_QIDX_INCR		0x0000001c
-#define L5_KRNLQ_PGTBL_HADDR_HI 	0x00000020
-#define L5_KRNLQ_PGTBL_HADDR_LO 	0x00000024
-
-#define BNX2_PG_CTX_MAP			0x1a0034
-#define BNX2_ISCSI_CTX_MAP		0x1a0074
-
-#define MAX_COMPLETED_KCQE	64
-
-#define MAX_CNIC_L5_CONTEXT	256
-
-#define MAX_CM_SK_TBL_SZ	MAX_CNIC_L5_CONTEXT
-
-#define MAX_ISCSI_TBL_SZ	256
-
-#define CNIC_LOCAL_PORT_MIN	60000
-#define CNIC_LOCAL_PORT_MAX	61024
-#define CNIC_LOCAL_PORT_RANGE	(CNIC_LOCAL_PORT_MAX - CNIC_LOCAL_PORT_MIN)
-
-#define KWQE_CNT (BCM_PAGE_SIZE / sizeof(struct kwqe))
-#define KCQE_CNT (BCM_PAGE_SIZE / sizeof(struct kcqe))
-#define MAX_KWQE_CNT (KWQE_CNT - 1)
-#define MAX_KCQE_CNT (KCQE_CNT - 1)
-
-#define MAX_KWQ_IDX	((KWQ_PAGE_CNT * KWQE_CNT) - 1)
-#define MAX_KCQ_IDX	((KCQ_PAGE_CNT * KCQE_CNT) - 1)
-
-#define KWQ_PG(x) (((x) & ~MAX_KWQE_CNT) >> (BCM_PAGE_BITS - 5))
-#define KWQ_IDX(x) ((x) & MAX_KWQE_CNT)
-
-#define KCQ_PG(x) (((x) & ~MAX_KCQE_CNT) >> (BCM_PAGE_BITS - 5))
-#define KCQ_IDX(x) ((x) & MAX_KCQE_CNT)
-
-#define BNX2X_NEXT_KCQE(x) (((x) & (MAX_KCQE_CNT - 1)) ==		\
-		(MAX_KCQE_CNT - 1)) ?					\
-		(x) + 2 : (x) + 1
-
-#define BNX2X_KWQ_DATA_PG(cp, x) ((x) / (cp)->kwq_16_data_pp)
-#define BNX2X_KWQ_DATA_IDX(cp, x) ((x) % (cp)->kwq_16_data_pp)
-#define BNX2X_KWQ_DATA(cp, x)						\
-	&(cp)->kwq_16_data[BNX2X_KWQ_DATA_PG(cp, x)][BNX2X_KWQ_DATA_IDX(cp, x)]
-
-#define DEF_IPID_START		0x8000
-
-#define DEF_KA_TIMEOUT		10000
-#define DEF_KA_INTERVAL		300000
-#define DEF_KA_MAX_PROBE_COUNT	3
-#define DEF_TOS			0
-#define DEF_TTL			0xfe
-#define DEF_SND_SEQ_SCALE	0
-#define DEF_RCV_BUF		0xffff
-#define DEF_SND_BUF		0xffff
-#define DEF_SEED		0
-#define DEF_MAX_RT_TIME		500
-#define DEF_MAX_DA_COUNT	2
-#define DEF_SWS_TIMER		1000
-#define DEF_MAX_CWND		0xffff
-
-struct cnic_ctx {
-	u32		cid;
-	void		*ctx;
-	dma_addr_t	mapping;
-};
-
-#define BNX2_MAX_CID		0x2000
-
-struct cnic_dma {
-	int		num_pages;
-	void		**pg_arr;
-	dma_addr_t	*pg_map_arr;
-	int		pgtbl_size;
-	u32		*pgtbl;
-	dma_addr_t	pgtbl_map;
-};
-
-struct cnic_id_tbl {
-	spinlock_t	lock;
-	u32		start;
-	u32		max;
-	u32		next;
-	unsigned long	*table;
-};
-
-#define CNIC_KWQ16_DATA_SIZE	128
-
-struct kwqe_16_data {
-	u8	data[CNIC_KWQ16_DATA_SIZE];
-};
-
-struct cnic_iscsi {
-	struct cnic_dma		task_array_info;
-	struct cnic_dma		r2tq_info;
-	struct cnic_dma		hq_info;
-};
-
-struct cnic_context {
-	u32			cid;
-	struct kwqe_16_data	*kwqe_data;
-	dma_addr_t		kwqe_data_mapping;
-	wait_queue_head_t	waitq;
-	int			wait_cond;
-	unsigned long		timestamp;
-	unsigned long		ctx_flags;
-#define	CTX_FL_OFFLD_START	0
-#define	CTX_FL_DELETE_WAIT	1
-#define	CTX_FL_CID_ERROR	2
-	u8			ulp_proto_id;
-	union {
-		struct cnic_iscsi	*iscsi;
-	} proto;
-};
-
-struct kcq_info {
-	struct cnic_dma	dma;
-	struct kcqe	**kcq;
-
-	u16		*hw_prod_idx_ptr;
-	u16		sw_prod_idx;
-	u16		*status_idx_ptr;
-	u32		io_addr;
-
-	u16		(*next_idx)(u16);
-	u16		(*hw_idx)(u16);
-};
-
-struct iro {
-	u32 base;
-	u16 m1;
-	u16 m2;
-	u16 m3;
-	u16 size;
-};
-
-struct cnic_uio_dev {
-	struct uio_info		cnic_uinfo;
-	u32			uio_dev;
-
-	int			l2_ring_size;
-	void			*l2_ring;
-	dma_addr_t		l2_ring_map;
-
-	int			l2_buf_size;
-	void			*l2_buf;
-	dma_addr_t		l2_buf_map;
-
-	struct cnic_dev		*dev;
-	struct pci_dev		*pdev;
-	struct list_head	list;
-};
-
-struct cnic_local {
-
-	spinlock_t cnic_ulp_lock;
-	void *ulp_handle[MAX_CNIC_ULP_TYPE];
-	unsigned long ulp_flags[MAX_CNIC_ULP_TYPE];
-#define ULP_F_INIT	0
-#define ULP_F_START	1
-#define ULP_F_CALL_PENDING	2
-	struct cnic_ulp_ops __rcu *ulp_ops[MAX_CNIC_ULP_TYPE];
-
-	unsigned long cnic_local_flags;
-#define	CNIC_LCL_FL_KWQ_INIT		0x0
-#define	CNIC_LCL_FL_L2_WAIT		0x1
-#define	CNIC_LCL_FL_RINGS_INITED	0x2
-#define	CNIC_LCL_FL_STOP_ISCSI		0x4
-
-	struct cnic_dev *dev;
-
-	struct cnic_eth_dev *ethdev;
-
-	struct cnic_uio_dev *udev;
-
-	int		l2_rx_ring_size;
-	int		l2_single_buf_size;
-
-	u16		*rx_cons_ptr;
-	u16		*tx_cons_ptr;
-	u16		rx_cons;
-	u16		tx_cons;
-
-	const struct iro	*iro_arr;
-#define IRO (((struct cnic_local *) dev->cnic_priv)->iro_arr)
-
-	struct cnic_dma		kwq_info;
-	struct kwqe		**kwq;
-
-	struct cnic_dma		kwq_16_data_info;
-
-	u16		max_kwq_idx;
-
-	u16		kwq_prod_idx;
-	u32		kwq_io_addr;
-
-	u16		*kwq_con_idx_ptr;
-	u16		kwq_con_idx;
-
-	struct kcq_info	kcq1;
-	struct kcq_info	kcq2;
-
-	union {
-		void				*gen;
-		struct status_block_msix	*bnx2;
-		struct host_hc_status_block_e1x	*bnx2x_e1x;
-		/* index values - which counter to update */
-		#define SM_RX_ID		0
-		#define SM_TX_ID		1
-	} status_blk;
-
-	struct host_sp_status_block	*bnx2x_def_status_blk;
-
-	u32				status_blk_num;
-	u32				bnx2x_igu_sb_id;
-	u32				int_num;
-	u32				last_status_idx;
-	struct tasklet_struct		cnic_irq_task;
-
-	struct kcqe		*completed_kcq[MAX_COMPLETED_KCQE];
-
-	struct cnic_sock	*csk_tbl;
-	struct cnic_id_tbl	csk_port_tbl;
-
-	struct cnic_dma		gbl_buf_info;
-
-	struct cnic_iscsi	*iscsi_tbl;
-	struct cnic_context	*ctx_tbl;
-	struct cnic_id_tbl	cid_tbl;
-	atomic_t		iscsi_conn;
-	u32			iscsi_start_cid;
-
-	u32			fcoe_init_cid;
-	u32			fcoe_start_cid;
-	struct cnic_id_tbl	fcoe_cid_tbl;
-
-	u32			max_cid_space;
-
-	/* per connection parameters */
-	int			num_iscsi_tasks;
-	int			num_ccells;
-	int			task_array_size;
-	int			r2tq_size;
-	int			hq_size;
-	int			num_cqs;
-
-	struct delayed_work	delete_task;
-
-	struct cnic_ctx		*ctx_arr;
-	int			ctx_blks;
-	int			ctx_blk_size;
-	unsigned long		ctx_align;
-	int			cids_per_blk;
-
-	u32			chip_id;
-	int			func;
-	u32			pfid;
-	u8			port_mode;
-#define CHIP_4_PORT_MODE	0
-#define CHIP_2_PORT_MODE	1
-#define CHIP_PORT_MODE_NONE	2
-
-	u32			shmem_base;
-
-	struct cnic_ops		*cnic_ops;
-	int			(*start_hw)(struct cnic_dev *);
-	void			(*stop_hw)(struct cnic_dev *);
-	void			(*setup_pgtbl)(struct cnic_dev *,
-					       struct cnic_dma *);
-	int			(*alloc_resc)(struct cnic_dev *);
-	void			(*free_resc)(struct cnic_dev *);
-	int			(*start_cm)(struct cnic_dev *);
-	void			(*stop_cm)(struct cnic_dev *);
-	void			(*enable_int)(struct cnic_dev *);
-	void			(*disable_int_sync)(struct cnic_dev *);
-	void			(*ack_int)(struct cnic_dev *);
-	void			(*close_conn)(struct cnic_sock *, u32 opcode);
-};
-
-struct bnx2x_bd_chain_next {
-	u32	addr_lo;
-	u32	addr_hi;
-	u8	reserved[8];
-};
-
-#define ISCSI_DEFAULT_MAX_OUTSTANDING_R2T 	(1)
-
-#define ISCSI_RAMROD_CMD_ID_UPDATE_CONN		(ISCSI_KCQE_OPCODE_UPDATE_CONN)
-#define ISCSI_RAMROD_CMD_ID_INIT		(ISCSI_KCQE_OPCODE_INIT)
-
-#define CDU_REGION_NUMBER_XCM_AG 2
-#define CDU_REGION_NUMBER_UCM_AG 4
-
-#define CDU_VALID_DATA(_cid, _region, _type)	\
-	(((_cid) << 8) | (((_region)&0xf)<<4) | (((_type)&0xf)))
-
-#define CDU_CRC8(_cid, _region, _type)	\
-	(calc_crc8(CDU_VALID_DATA(_cid, _region, _type), 0xff))
-
-#define CDU_RSRVD_VALUE_TYPE_A(_cid, _region, _type)	\
-	(0x80 | ((CDU_CRC8(_cid, _region, _type)) & 0x7f))
-
-#define BNX2X_CONTEXT_MEM_SIZE		1024
-#define BNX2X_FCOE_CID			16
-
-#define BNX2X_ISCSI_START_CID		18
-#define BNX2X_ISCSI_NUM_CONNECTIONS	128
-#define BNX2X_ISCSI_TASK_CONTEXT_SIZE	128
-#define BNX2X_ISCSI_MAX_PENDING_R2TS	4
-#define BNX2X_ISCSI_R2TQE_SIZE		8
-#define BNX2X_ISCSI_HQ_BD_SIZE		64
-#define BNX2X_ISCSI_GLB_BUF_SIZE	64
-#define BNX2X_ISCSI_PBL_NOT_CACHED	0xff
-#define BNX2X_ISCSI_PDU_HEADER_NOT_CACHED	0xff
-
-#define BNX2X_FCOE_NUM_CONNECTIONS	128
-
-#define BNX2X_FCOE_L5_CID_BASE		MAX_ISCSI_TBL_SZ
-
-#define BNX2X_CHIP_NUM_57710		0x164e
-#define BNX2X_CHIP_NUM_57711		0x164f
-#define BNX2X_CHIP_NUM_57711E		0x1650
-#define BNX2X_CHIP_NUM_57712		0x1662
-#define BNX2X_CHIP_NUM_57712E		0x1663
-#define BNX2X_CHIP_NUM_57713		0x1651
-#define BNX2X_CHIP_NUM_57713E		0x1652
-#define BNX2X_CHIP_NUM_57800		0x168a
-#define BNX2X_CHIP_NUM_57810		0x168e
-#define BNX2X_CHIP_NUM_57840		0x168d
-
-#define BNX2X_CHIP_NUM(x)		(x >> 16)
-#define BNX2X_CHIP_IS_57710(x)		\
-	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57710)
-#define BNX2X_CHIP_IS_57711(x)		\
-	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57711)
-#define BNX2X_CHIP_IS_57711E(x)		\
-	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57711E)
-#define BNX2X_CHIP_IS_E1H(x)		\
-	(BNX2X_CHIP_IS_57711(x) || BNX2X_CHIP_IS_57711E(x))
-#define BNX2X_CHIP_IS_57712(x)		\
-	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57712)
-#define BNX2X_CHIP_IS_57712E(x)		\
-	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57712E)
-#define BNX2X_CHIP_IS_57713(x)		\
-	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57713)
-#define BNX2X_CHIP_IS_57713E(x)		\
-	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57713E)
-#define BNX2X_CHIP_IS_57800(x)		\
-	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57800)
-#define BNX2X_CHIP_IS_57810(x)		\
-	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57810)
-#define BNX2X_CHIP_IS_57840(x)		\
-	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57840)
-#define BNX2X_CHIP_IS_E2(x)		\
-	(BNX2X_CHIP_IS_57712(x) || BNX2X_CHIP_IS_57712E(x) || \
-	 BNX2X_CHIP_IS_57713(x) || BNX2X_CHIP_IS_57713E(x))
-#define BNX2X_CHIP_IS_E3(x)			\
-	(BNX2X_CHIP_IS_57800(x) || BNX2X_CHIP_IS_57810(x) || \
-	 BNX2X_CHIP_IS_57840(x))
-#define BNX2X_CHIP_IS_E2_PLUS(x) (BNX2X_CHIP_IS_E2(x) || BNX2X_CHIP_IS_E3(x))
-
-#define IS_E1H_OFFSET       		BNX2X_CHIP_IS_E1H(cp->chip_id)
-
-#define BNX2X_RX_DESC_CNT		(BCM_PAGE_SIZE / sizeof(struct eth_rx_bd))
-#define BNX2X_MAX_RX_DESC_CNT		(BNX2X_RX_DESC_CNT - 2)
-#define BNX2X_RCQ_DESC_CNT		(BCM_PAGE_SIZE / sizeof(union eth_rx_cqe))
-#define BNX2X_MAX_RCQ_DESC_CNT		(BNX2X_RCQ_DESC_CNT - 1)
-
-#define BNX2X_NEXT_RCQE(x) (((x) & BNX2X_MAX_RCQ_DESC_CNT) ==		\
-		(BNX2X_MAX_RCQ_DESC_CNT - 1)) ?				\
-		((x) + 2) : ((x) + 1)
-
-#define BNX2X_DEF_SB_ID			HC_SP_SB_ID
-
-#define BNX2X_SHMEM_MF_BLK_OFFSET	0x7e4
-
-#define BNX2X_SHMEM_ADDR(base, field)	(base + \
-					 offsetof(struct shmem_region, field))
-
-#define BNX2X_SHMEM2_ADDR(base, field)	(base + \
-					 offsetof(struct shmem2_region, field))
-
-#define BNX2X_SHMEM2_HAS(base, field)				\
-		((base) &&					\
-		 (CNIC_RD(dev, BNX2X_SHMEM2_ADDR(base, size)) >	\
-		  offsetof(struct shmem2_region, field)))
-
-#define BNX2X_MF_CFG_ADDR(base, field)				\
-			((base) + offsetof(struct mf_cfg, field))
-
-#ifndef ETH_MAX_RX_CLIENTS_E2
-#define ETH_MAX_RX_CLIENTS_E2 		ETH_MAX_RX_CLIENTS_E1H
-#endif
-
-#define CNIC_PORT(cp)			((cp)->pfid & 1)
-#define CNIC_FUNC(cp)			((cp)->func)
-#define CNIC_PATH(cp)			(!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ? \
-					 0 : (CNIC_FUNC(cp) & 1))
-#define CNIC_E1HVN(cp)			((cp)->pfid >> 1)
-
-#define BNX2X_HW_CID(cp, x)		((CNIC_PORT(cp) << 23) | \
-					 (CNIC_E1HVN(cp) << 17) | (x))
-
-#define BNX2X_SW_CID(x)			(x & 0x1ffff)
-
-#define BNX2X_CL_QZONE_ID(cp, cli)					\
-		(BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ? cli :		\
-		 cli + (CNIC_PORT(cp) * ETH_MAX_RX_CLIENTS_E1H))
-
-#ifndef MAX_STAT_COUNTER_ID
-#define MAX_STAT_COUNTER_ID						\
-	(BNX2X_CHIP_IS_E1H((cp)->chip_id) ? MAX_STAT_COUNTER_ID_E1H :	\
-	 ((BNX2X_CHIP_IS_E2_PLUS((cp)->chip_id)) ? MAX_STAT_COUNTER_ID_E2 :\
-	  MAX_STAT_COUNTER_ID_E1))
-#endif
-
-#endif
-
diff -druN linux-libre-3.1-gnu/drivers/net/cnic_if.h linux-libre-3.2-gnu/drivers/net/cnic_if.h
--- linux-libre-3.1-gnu/drivers/net/cnic_if.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cnic_if.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,340 +0,0 @@
-/* cnic_if.h: Broadcom CNIC core network driver.
- *
- * Copyright (c) 2006-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
- * the Free Software Foundation.
- *
- */
-
-
-#ifndef CNIC_IF_H
-#define CNIC_IF_H
-
-#define CNIC_MODULE_VERSION	"2.5.7"
-#define CNIC_MODULE_RELDATE	"July 20, 2011"
-
-#define CNIC_ULP_RDMA		0
-#define CNIC_ULP_ISCSI		1
-#define CNIC_ULP_FCOE		2
-#define CNIC_ULP_L4		3
-#define MAX_CNIC_ULP_TYPE_EXT	3
-#define MAX_CNIC_ULP_TYPE	4
-
-struct kwqe {
-	u32 kwqe_op_flag;
-
-#define KWQE_QID_SHIFT		8
-#define KWQE_OPCODE_MASK	0x00ff0000
-#define KWQE_OPCODE_SHIFT	16
-#define KWQE_OPCODE(x)		((x & KWQE_OPCODE_MASK) >> KWQE_OPCODE_SHIFT)
-#define KWQE_LAYER_MASK			0x70000000
-#define KWQE_LAYER_SHIFT		28
-#define KWQE_FLAGS_LAYER_MASK_L2	(2<<28)
-#define KWQE_FLAGS_LAYER_MASK_L3	(3<<28)
-#define KWQE_FLAGS_LAYER_MASK_L4	(4<<28)
-#define KWQE_FLAGS_LAYER_MASK_L5_RDMA	(5<<28)
-#define KWQE_FLAGS_LAYER_MASK_L5_ISCSI	(6<<28)
-#define KWQE_FLAGS_LAYER_MASK_L5_FCOE	(7<<28)
-
-	u32 kwqe_info0;
-	u32 kwqe_info1;
-	u32 kwqe_info2;
-	u32 kwqe_info3;
-	u32 kwqe_info4;
-	u32 kwqe_info5;
-	u32 kwqe_info6;
-};
-
-struct kwqe_16 {
-	u32 kwqe_info0;
-	u32 kwqe_info1;
-	u32 kwqe_info2;
-	u32 kwqe_info3;
-};
-
-struct kcqe {
-	u32 kcqe_info0;
-	u32 kcqe_info1;
-	u32 kcqe_info2;
-	u32 kcqe_info3;
-	u32 kcqe_info4;
-	u32 kcqe_info5;
-	u32 kcqe_info6;
-	u32 kcqe_op_flag;
-		#define KCQE_RAMROD_COMPLETION		(0x1<<27) /* Everest */
-		#define KCQE_FLAGS_LAYER_MASK		(0x7<<28)
-		#define KCQE_FLAGS_LAYER_MASK_MISC	(0<<28)
-		#define KCQE_FLAGS_LAYER_MASK_L2	(2<<28)
-		#define KCQE_FLAGS_LAYER_MASK_L3	(3<<28)
-		#define KCQE_FLAGS_LAYER_MASK_L4	(4<<28)
-		#define KCQE_FLAGS_LAYER_MASK_L5_RDMA	(5<<28)
-		#define KCQE_FLAGS_LAYER_MASK_L5_ISCSI	(6<<28)
-		#define KCQE_FLAGS_LAYER_MASK_L5_FCOE	(7<<28)
-		#define KCQE_FLAGS_NEXT 		(1<<31)
-		#define KCQE_FLAGS_OPCODE_MASK		(0xff<<16)
-		#define KCQE_FLAGS_OPCODE_SHIFT		(16)
-		#define KCQE_OPCODE(op)			\
-		(((op) & KCQE_FLAGS_OPCODE_MASK) >> KCQE_FLAGS_OPCODE_SHIFT)
-};
-
-#define MAX_CNIC_CTL_DATA	64
-#define MAX_DRV_CTL_DATA	64
-
-#define CNIC_CTL_STOP_CMD		1
-#define CNIC_CTL_START_CMD		2
-#define CNIC_CTL_COMPLETION_CMD		3
-#define CNIC_CTL_STOP_ISCSI_CMD		4
-
-#define DRV_CTL_IO_WR_CMD		0x101
-#define DRV_CTL_IO_RD_CMD		0x102
-#define DRV_CTL_CTX_WR_CMD		0x103
-#define DRV_CTL_CTXTBL_WR_CMD		0x104
-#define DRV_CTL_RET_L5_SPQ_CREDIT_CMD	0x105
-#define DRV_CTL_START_L2_CMD		0x106
-#define DRV_CTL_STOP_L2_CMD		0x107
-#define DRV_CTL_RET_L2_SPQ_CREDIT_CMD	0x10c
-#define DRV_CTL_ISCSI_STOPPED_CMD	0x10d
-
-struct cnic_ctl_completion {
-	u32	cid;
-	u8	opcode;
-	u8	error;
-};
-
-struct cnic_ctl_info {
-	int	cmd;
-	union {
-		struct cnic_ctl_completion comp;
-		char bytes[MAX_CNIC_CTL_DATA];
-	} data;
-};
-
-struct drv_ctl_spq_credit {
-	u32	credit_count;
-};
-
-struct drv_ctl_io {
-	u32		cid_addr;
-	u32		offset;
-	u32		data;
-	dma_addr_t	dma_addr;
-};
-
-struct drv_ctl_l2_ring {
-	u32		client_id;
-	u32		cid;
-};
-
-struct drv_ctl_info {
-	int	cmd;
-	union {
-		struct drv_ctl_spq_credit credit;
-		struct drv_ctl_io io;
-		struct drv_ctl_l2_ring ring;
-		char bytes[MAX_DRV_CTL_DATA];
-	} data;
-};
-
-struct cnic_ops {
-	struct module	*cnic_owner;
-	/* Calls to these functions are protected by RCU.  When
-	 * unregistering, we wait for any calls to complete before
-	 * continuing.
-	 */
-	int		(*cnic_handler)(void *, void *);
-	int		(*cnic_ctl)(void *, struct cnic_ctl_info *);
-};
-
-#define MAX_CNIC_VEC	8
-
-struct cnic_irq {
-	unsigned int	vector;
-	void		*status_blk;
-	u32		status_blk_num;
-	u32		status_blk_num2;
-	u32		irq_flags;
-#define CNIC_IRQ_FL_MSIX		0x00000001
-};
-
-struct cnic_eth_dev {
-	struct module	*drv_owner;
-	u32		drv_state;
-#define CNIC_DRV_STATE_REGD		0x00000001
-#define CNIC_DRV_STATE_USING_MSIX	0x00000002
-#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;
-	void __iomem	*io_base;
-	void __iomem	*io_base2;
-	const void	*iro_arr;
-
-	u32		ctx_tbl_offset;
-	u32		ctx_tbl_len;
-	int		ctx_blk_size;
-	u32		starting_cid;
-	u32		max_iscsi_conn;
-	u32		max_fcoe_conn;
-	u32		max_rdma_conn;
-	u32		fcoe_init_cid;
-	u32		fcoe_wwn_port_name_hi;
-	u32		fcoe_wwn_port_name_lo;
-	u32		fcoe_wwn_node_name_hi;
-	u32		fcoe_wwn_node_name_lo;
-
-	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];
-	int		(*drv_register_cnic)(struct net_device *,
-					     struct cnic_ops *, void *);
-	int		(*drv_unregister_cnic)(struct net_device *);
-	int		(*drv_submit_kwqes_32)(struct net_device *,
-					       struct kwqe *[], u32);
-	int		(*drv_submit_kwqes_16)(struct net_device *,
-					       struct kwqe_16 *[], u32);
-	int		(*drv_ctl)(struct net_device *, struct drv_ctl_info *);
-	unsigned long	reserved1[2];
-};
-
-struct cnic_sockaddr {
-	union {
-		struct sockaddr_in	v4;
-		struct sockaddr_in6	v6;
-	} local;
-	union {
-		struct sockaddr_in	v4;
-		struct sockaddr_in6	v6;
-	} remote;
-};
-
-struct cnic_sock {
-	struct cnic_dev *dev;
-	void	*context;
-	u32	src_ip[4];
-	u32	dst_ip[4];
-	u16	src_port;
-	u16	dst_port;
-	u16	vlan_id;
-	unsigned char old_ha[6];
-	unsigned char ha[6];
-	u32	mtu;
-	u32	cid;
-	u32	l5_cid;
-	u32	pg_cid;
-	int	ulp_type;
-
-	u32	ka_timeout;
-	u32	ka_interval;
-	u8	ka_max_probe_count;
-	u8	tos;
-	u8	ttl;
-	u8	snd_seq_scale;
-	u32	rcv_buf;
-	u32	snd_buf;
-	u32	seed;
-
-	unsigned long	tcp_flags;
-#define SK_TCP_NO_DELAY_ACK	0x1
-#define SK_TCP_KEEP_ALIVE	0x2
-#define SK_TCP_NAGLE		0x4
-#define SK_TCP_TIMESTAMP	0x8
-#define SK_TCP_SACK		0x10
-#define SK_TCP_SEG_SCALING	0x20
-	unsigned long	flags;
-#define SK_F_INUSE		0
-#define SK_F_OFFLD_COMPLETE	1
-#define SK_F_OFFLD_SCHED	2
-#define SK_F_PG_OFFLD_COMPLETE	3
-#define SK_F_CONNECT_START	4
-#define SK_F_IPV6		5
-#define SK_F_CLOSING		7
-
-	atomic_t ref_count;
-	u32 state;
-	struct kwqe kwqe1;
-	struct kwqe kwqe2;
-	struct kwqe kwqe3;
-};
-
-struct cnic_dev {
-	struct net_device	*netdev;
-	struct pci_dev		*pcidev;
-	void __iomem		*regview;
-	struct list_head	list;
-
-	int (*register_device)(struct cnic_dev *dev, int ulp_type,
-			       void *ulp_ctx);
-	int (*unregister_device)(struct cnic_dev *dev, int ulp_type);
-	int (*submit_kwqes)(struct cnic_dev *dev, struct kwqe *wqes[],
-				u32 num_wqes);
-	int (*submit_kwqes_16)(struct cnic_dev *dev, struct kwqe_16 *wqes[],
-				u32 num_wqes);
-
-	int (*cm_create)(struct cnic_dev *, int, u32, u32, struct cnic_sock **,
-			 void *);
-	int (*cm_destroy)(struct cnic_sock *);
-	int (*cm_connect)(struct cnic_sock *, struct cnic_sockaddr *);
-	int (*cm_abort)(struct cnic_sock *);
-	int (*cm_close)(struct cnic_sock *);
-	struct cnic_dev *(*cm_select_dev)(struct sockaddr_in *, int ulp_type);
-	int (*iscsi_nl_msg_recv)(struct cnic_dev *dev, u32 msg_type,
-				 char *data, u16 data_size);
-	unsigned long	flags;
-#define CNIC_F_CNIC_UP		1
-#define CNIC_F_BNX2_CLASS	3
-#define CNIC_F_BNX2X_CLASS	4
-	atomic_t	ref_count;
-	u8		mac_addr[6];
-
-	int		max_iscsi_conn;
-	int		max_fcoe_conn;
-	int		max_rdma_conn;
-
-	void		*cnic_priv;
-};
-
-#define CNIC_WR(dev, off, val)		writel(val, dev->regview + off)
-#define CNIC_WR16(dev, off, val)	writew(val, dev->regview + off)
-#define CNIC_WR8(dev, off, val)		writeb(val, dev->regview + off)
-#define CNIC_RD(dev, off)		readl(dev->regview + off)
-#define CNIC_RD16(dev, off)		readw(dev->regview + off)
-
-struct cnic_ulp_ops {
-	/* Calls to these functions are protected by RCU.  When
-	 * unregistering, we wait for any calls to complete before
-	 * continuing.
-	 */
-
-	void (*cnic_init)(struct cnic_dev *dev);
-	void (*cnic_exit)(struct cnic_dev *dev);
-	void (*cnic_start)(void *ulp_ctx);
-	void (*cnic_stop)(void *ulp_ctx);
-	void (*indicate_kcqes)(void *ulp_ctx, struct kcqe *cqes[],
-				u32 num_cqes);
-	void (*indicate_netevent)(void *ulp_ctx, unsigned long event, u16 vid);
-	void (*cm_connect_complete)(struct cnic_sock *);
-	void (*cm_close_complete)(struct cnic_sock *);
-	void (*cm_abort_complete)(struct cnic_sock *);
-	void (*cm_remote_close)(struct cnic_sock *);
-	void (*cm_remote_abort)(struct cnic_sock *);
-	int (*iscsi_nl_send_msg)(void *ulp_ctx, u32 msg_type,
-				  char *data, u16 data_size);
-	struct module *owner;
-	atomic_t ref_count;
-};
-
-extern int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops);
-
-extern int cnic_unregister_driver(int ulp_type);
-
-extern struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev);
-extern struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev);
-
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/cpmac.c linux-libre-3.2-gnu/drivers/net/cpmac.c
--- linux-libre-3.1-gnu/drivers/net/cpmac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cpmac.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1305 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Eugene Konev
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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/init.h>
-#include <linux/interrupt.h>
-#include <linux/moduleparam.h>
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-
-#include <linux/netdevice.h>
-#include <linux/if_vlan.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/skbuff.h>
-#include <linux/mii.h>
-#include <linux/phy.h>
-#include <linux/phy_fixed.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk.h>
-#include <linux/gpio.h>
-#include <linux/atomic.h>
-
-MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>");
-MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:cpmac");
-
-static int debug_level = 8;
-static int dumb_switch;
-
-/* Next 2 are only used in cpmac_probe, so it's pointless to change them */
-module_param(debug_level, int, 0444);
-module_param(dumb_switch, int, 0444);
-
-MODULE_PARM_DESC(debug_level, "Number of NETIF_MSG bits to enable");
-MODULE_PARM_DESC(dumb_switch, "Assume switch is not connected to MDIO bus");
-
-#define CPMAC_VERSION "0.5.2"
-/* frame size + 802.1q tag + FCS size */
-#define CPMAC_SKB_SIZE		(ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN)
-#define CPMAC_QUEUES	8
-
-/* Ethernet registers */
-#define CPMAC_TX_CONTROL		0x0004
-#define CPMAC_TX_TEARDOWN		0x0008
-#define CPMAC_RX_CONTROL		0x0014
-#define CPMAC_RX_TEARDOWN		0x0018
-#define CPMAC_MBP			0x0100
-# define MBP_RXPASSCRC			0x40000000
-# define MBP_RXQOS			0x20000000
-# define MBP_RXNOCHAIN			0x10000000
-# define MBP_RXCMF			0x01000000
-# define MBP_RXSHORT			0x00800000
-# define MBP_RXCEF			0x00400000
-# define MBP_RXPROMISC			0x00200000
-# define MBP_PROMISCCHAN(channel)	(((channel) & 0x7) << 16)
-# define MBP_RXBCAST			0x00002000
-# define MBP_BCASTCHAN(channel)		(((channel) & 0x7) << 8)
-# define MBP_RXMCAST			0x00000020
-# define MBP_MCASTCHAN(channel)		((channel) & 0x7)
-#define CPMAC_UNICAST_ENABLE		0x0104
-#define CPMAC_UNICAST_CLEAR		0x0108
-#define CPMAC_MAX_LENGTH		0x010c
-#define CPMAC_BUFFER_OFFSET		0x0110
-#define CPMAC_MAC_CONTROL		0x0160
-# define MAC_TXPTYPE			0x00000200
-# define MAC_TXPACE			0x00000040
-# define MAC_MII			0x00000020
-# define MAC_TXFLOW			0x00000010
-# define MAC_RXFLOW			0x00000008
-# define MAC_MTEST			0x00000004
-# define MAC_LOOPBACK			0x00000002
-# define MAC_FDX			0x00000001
-#define CPMAC_MAC_STATUS		0x0164
-# define MAC_STATUS_QOS			0x00000004
-# define MAC_STATUS_RXFLOW		0x00000002
-# define MAC_STATUS_TXFLOW		0x00000001
-#define CPMAC_TX_INT_ENABLE		0x0178
-#define CPMAC_TX_INT_CLEAR		0x017c
-#define CPMAC_MAC_INT_VECTOR		0x0180
-# define MAC_INT_STATUS			0x00080000
-# define MAC_INT_HOST			0x00040000
-# define MAC_INT_RX			0x00020000
-# define MAC_INT_TX			0x00010000
-#define CPMAC_MAC_EOI_VECTOR		0x0184
-#define CPMAC_RX_INT_ENABLE		0x0198
-#define CPMAC_RX_INT_CLEAR		0x019c
-#define CPMAC_MAC_INT_ENABLE		0x01a8
-#define CPMAC_MAC_INT_CLEAR		0x01ac
-#define CPMAC_MAC_ADDR_LO(channel)	(0x01b0 + (channel) * 4)
-#define CPMAC_MAC_ADDR_MID		0x01d0
-#define CPMAC_MAC_ADDR_HI		0x01d4
-#define CPMAC_MAC_HASH_LO		0x01d8
-#define CPMAC_MAC_HASH_HI		0x01dc
-#define CPMAC_TX_PTR(channel)		(0x0600 + (channel) * 4)
-#define CPMAC_RX_PTR(channel)		(0x0620 + (channel) * 4)
-#define CPMAC_TX_ACK(channel)		(0x0640 + (channel) * 4)
-#define CPMAC_RX_ACK(channel)		(0x0660 + (channel) * 4)
-#define CPMAC_REG_END			0x0680
-/*
- * Rx/Tx statistics
- * TODO: use some of them to fill stats in cpmac_stats()
- */
-#define CPMAC_STATS_RX_GOOD		0x0200
-#define CPMAC_STATS_RX_BCAST		0x0204
-#define CPMAC_STATS_RX_MCAST		0x0208
-#define CPMAC_STATS_RX_PAUSE		0x020c
-#define CPMAC_STATS_RX_CRC		0x0210
-#define CPMAC_STATS_RX_ALIGN		0x0214
-#define CPMAC_STATS_RX_OVER		0x0218
-#define CPMAC_STATS_RX_JABBER		0x021c
-#define CPMAC_STATS_RX_UNDER		0x0220
-#define CPMAC_STATS_RX_FRAG		0x0224
-#define CPMAC_STATS_RX_FILTER		0x0228
-#define CPMAC_STATS_RX_QOSFILTER	0x022c
-#define CPMAC_STATS_RX_OCTETS		0x0230
-
-#define CPMAC_STATS_TX_GOOD		0x0234
-#define CPMAC_STATS_TX_BCAST		0x0238
-#define CPMAC_STATS_TX_MCAST		0x023c
-#define CPMAC_STATS_TX_PAUSE		0x0240
-#define CPMAC_STATS_TX_DEFER		0x0244
-#define CPMAC_STATS_TX_COLLISION	0x0248
-#define CPMAC_STATS_TX_SINGLECOLL	0x024c
-#define CPMAC_STATS_TX_MULTICOLL	0x0250
-#define CPMAC_STATS_TX_EXCESSCOLL	0x0254
-#define CPMAC_STATS_TX_LATECOLL		0x0258
-#define CPMAC_STATS_TX_UNDERRUN		0x025c
-#define CPMAC_STATS_TX_CARRIERSENSE	0x0260
-#define CPMAC_STATS_TX_OCTETS		0x0264
-
-#define cpmac_read(base, reg)		(readl((void __iomem *)(base) + (reg)))
-#define cpmac_write(base, reg, val)	(writel(val, (void __iomem *)(base) + \
-						(reg)))
-
-/* MDIO bus */
-#define CPMAC_MDIO_VERSION		0x0000
-#define CPMAC_MDIO_CONTROL		0x0004
-# define MDIOC_IDLE			0x80000000
-# define MDIOC_ENABLE			0x40000000
-# define MDIOC_PREAMBLE			0x00100000
-# define MDIOC_FAULT			0x00080000
-# define MDIOC_FAULTDETECT		0x00040000
-# define MDIOC_INTTEST			0x00020000
-# define MDIOC_CLKDIV(div)		((div) & 0xff)
-#define CPMAC_MDIO_ALIVE		0x0008
-#define CPMAC_MDIO_LINK			0x000c
-#define CPMAC_MDIO_ACCESS(channel)	(0x0080 + (channel) * 8)
-# define MDIO_BUSY			0x80000000
-# define MDIO_WRITE			0x40000000
-# define MDIO_REG(reg)			(((reg) & 0x1f) << 21)
-# define MDIO_PHY(phy)			(((phy) & 0x1f) << 16)
-# define MDIO_DATA(data)		((data) & 0xffff)
-#define CPMAC_MDIO_PHYSEL(channel)	(0x0084 + (channel) * 8)
-# define PHYSEL_LINKSEL			0x00000040
-# define PHYSEL_LINKINT			0x00000020
-
-struct cpmac_desc {
-	u32 hw_next;
-	u32 hw_data;
-	u16 buflen;
-	u16 bufflags;
-	u16 datalen;
-	u16 dataflags;
-#define CPMAC_SOP			0x8000
-#define CPMAC_EOP			0x4000
-#define CPMAC_OWN			0x2000
-#define CPMAC_EOQ			0x1000
-	struct sk_buff *skb;
-	struct cpmac_desc *next;
-	struct cpmac_desc *prev;
-	dma_addr_t mapping;
-	dma_addr_t data_mapping;
-};
-
-struct cpmac_priv {
-	spinlock_t lock;
-	spinlock_t rx_lock;
-	struct cpmac_desc *rx_head;
-	int ring_size;
-	struct cpmac_desc *desc_ring;
-	dma_addr_t dma_ring;
-	void __iomem *regs;
-	struct mii_bus *mii_bus;
-	struct phy_device *phy;
-	char phy_name[MII_BUS_ID_SIZE + 3];
-	int oldlink, oldspeed, oldduplex;
-	u32 msg_enable;
-	struct net_device *dev;
-	struct work_struct reset_work;
-	struct platform_device *pdev;
-	struct napi_struct napi;
-	atomic_t reset_pending;
-};
-
-static irqreturn_t cpmac_irq(int, void *);
-static void cpmac_hw_start(struct net_device *dev);
-static void cpmac_hw_stop(struct net_device *dev);
-static int cpmac_stop(struct net_device *dev);
-static int cpmac_open(struct net_device *dev);
-
-static void cpmac_dump_regs(struct net_device *dev)
-{
-	int i;
-	struct cpmac_priv *priv = netdev_priv(dev);
-	for (i = 0; i < CPMAC_REG_END; i += 4) {
-		if (i % 16 == 0) {
-			if (i)
-				pr_cont("\n");
-			printk(KERN_DEBUG "%s: reg[%p]:", dev->name,
-			       priv->regs + i);
-		}
-		printk(" %08x", cpmac_read(priv->regs, i));
-	}
-	printk("\n");
-}
-
-static void cpmac_dump_desc(struct net_device *dev, struct cpmac_desc *desc)
-{
-	int i;
-	printk(KERN_DEBUG "%s: desc[%p]:", dev->name, desc);
-	for (i = 0; i < sizeof(*desc) / 4; i++)
-		printk(" %08x", ((u32 *)desc)[i]);
-	printk("\n");
-}
-
-static void cpmac_dump_all_desc(struct net_device *dev)
-{
-	struct cpmac_priv *priv = netdev_priv(dev);
-	struct cpmac_desc *dump = priv->rx_head;
-	do {
-		cpmac_dump_desc(dev, dump);
-		dump = dump->next;
-	} while (dump != priv->rx_head);
-}
-
-static void cpmac_dump_skb(struct net_device *dev, struct sk_buff *skb)
-{
-	int i;
-	printk(KERN_DEBUG "%s: skb 0x%p, len=%d\n", dev->name, skb, skb->len);
-	for (i = 0; i < skb->len; i++) {
-		if (i % 16 == 0) {
-			if (i)
-				pr_cont("\n");
-			printk(KERN_DEBUG "%s: data[%p]:", dev->name,
-			       skb->data + i);
-		}
-		printk(" %02x", ((u8 *)skb->data)[i]);
-	}
-	printk("\n");
-}
-
-static int cpmac_mdio_read(struct mii_bus *bus, int phy_id, int reg)
-{
-	u32 val;
-
-	while (cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0)) & MDIO_BUSY)
-		cpu_relax();
-	cpmac_write(bus->priv, CPMAC_MDIO_ACCESS(0), MDIO_BUSY | MDIO_REG(reg) |
-		    MDIO_PHY(phy_id));
-	while ((val = cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0))) & MDIO_BUSY)
-		cpu_relax();
-	return MDIO_DATA(val);
-}
-
-static int cpmac_mdio_write(struct mii_bus *bus, int phy_id,
-			    int reg, u16 val)
-{
-	while (cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0)) & MDIO_BUSY)
-		cpu_relax();
-	cpmac_write(bus->priv, CPMAC_MDIO_ACCESS(0), MDIO_BUSY | MDIO_WRITE |
-		    MDIO_REG(reg) | MDIO_PHY(phy_id) | MDIO_DATA(val));
-	return 0;
-}
-
-static int cpmac_mdio_reset(struct mii_bus *bus)
-{
-	struct clk *cpmac_clk;
-
-	cpmac_clk = clk_get(&bus->dev, "cpmac");
-	if (IS_ERR(cpmac_clk)) {
-		printk(KERN_ERR "unable to get cpmac clock\n");
-		return -1;
-	}
-	ar7_device_reset(AR7_RESET_BIT_MDIO);
-	cpmac_write(bus->priv, CPMAC_MDIO_CONTROL, MDIOC_ENABLE |
-		    MDIOC_CLKDIV(clk_get_rate(cpmac_clk) / 2200000 - 1));
-	return 0;
-}
-
-static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, };
-
-static struct mii_bus *cpmac_mii;
-
-static int cpmac_config(struct net_device *dev, struct ifmap *map)
-{
-	if (dev->flags & IFF_UP)
-		return -EBUSY;
-
-	/* Don't allow changing the I/O address */
-	if (map->base_addr != dev->base_addr)
-		return -EOPNOTSUPP;
-
-	/* ignore other fields */
-	return 0;
-}
-
-static void cpmac_set_multicast_list(struct net_device *dev)
-{
-	struct netdev_hw_addr *ha;
-	u8 tmp;
-	u32 mbp, bit, hash[2] = { 0, };
-	struct cpmac_priv *priv = netdev_priv(dev);
-
-	mbp = cpmac_read(priv->regs, CPMAC_MBP);
-	if (dev->flags & IFF_PROMISC) {
-		cpmac_write(priv->regs, CPMAC_MBP, (mbp & ~MBP_PROMISCCHAN(0)) |
-			    MBP_RXPROMISC);
-	} else {
-		cpmac_write(priv->regs, CPMAC_MBP, mbp & ~MBP_RXPROMISC);
-		if (dev->flags & IFF_ALLMULTI) {
-			/* enable all multicast mode */
-			cpmac_write(priv->regs, CPMAC_MAC_HASH_LO, 0xffffffff);
-			cpmac_write(priv->regs, CPMAC_MAC_HASH_HI, 0xffffffff);
-		} else {
-			/*
-			 * cpmac uses some strange mac address hashing
-			 * (not crc32)
-			 */
-			netdev_for_each_mc_addr(ha, dev) {
-				bit = 0;
-				tmp = ha->addr[0];
-				bit  ^= (tmp >> 2) ^ (tmp << 4);
-				tmp = ha->addr[1];
-				bit  ^= (tmp >> 4) ^ (tmp << 2);
-				tmp = ha->addr[2];
-				bit  ^= (tmp >> 6) ^ tmp;
-				tmp = ha->addr[3];
-				bit  ^= (tmp >> 2) ^ (tmp << 4);
-				tmp = ha->addr[4];
-				bit  ^= (tmp >> 4) ^ (tmp << 2);
-				tmp = ha->addr[5];
-				bit  ^= (tmp >> 6) ^ tmp;
-				bit &= 0x3f;
-				hash[bit / 32] |= 1 << (bit % 32);
-			}
-
-			cpmac_write(priv->regs, CPMAC_MAC_HASH_LO, hash[0]);
-			cpmac_write(priv->regs, CPMAC_MAC_HASH_HI, hash[1]);
-		}
-	}
-}
-
-static struct sk_buff *cpmac_rx_one(struct cpmac_priv *priv,
-				    struct cpmac_desc *desc)
-{
-	struct sk_buff *skb, *result = NULL;
-
-	if (unlikely(netif_msg_hw(priv)))
-		cpmac_dump_desc(priv->dev, desc);
-	cpmac_write(priv->regs, CPMAC_RX_ACK(0), (u32)desc->mapping);
-	if (unlikely(!desc->datalen)) {
-		if (netif_msg_rx_err(priv) && net_ratelimit())
-			printk(KERN_WARNING "%s: rx: spurious interrupt\n",
-			       priv->dev->name);
-		return NULL;
-	}
-
-	skb = netdev_alloc_skb_ip_align(priv->dev, CPMAC_SKB_SIZE);
-	if (likely(skb)) {
-		skb_put(desc->skb, desc->datalen);
-		desc->skb->protocol = eth_type_trans(desc->skb, priv->dev);
-		skb_checksum_none_assert(desc->skb);
-		priv->dev->stats.rx_packets++;
-		priv->dev->stats.rx_bytes += desc->datalen;
-		result = desc->skb;
-		dma_unmap_single(&priv->dev->dev, desc->data_mapping,
-				 CPMAC_SKB_SIZE, DMA_FROM_DEVICE);
-		desc->skb = skb;
-		desc->data_mapping = dma_map_single(&priv->dev->dev, skb->data,
-						    CPMAC_SKB_SIZE,
-						    DMA_FROM_DEVICE);
-		desc->hw_data = (u32)desc->data_mapping;
-		if (unlikely(netif_msg_pktdata(priv))) {
-			printk(KERN_DEBUG "%s: received packet:\n",
-			       priv->dev->name);
-			cpmac_dump_skb(priv->dev, result);
-		}
-	} else {
-		if (netif_msg_rx_err(priv) && net_ratelimit())
-			printk(KERN_WARNING
-			       "%s: low on skbs, dropping packet\n",
-			       priv->dev->name);
-		priv->dev->stats.rx_dropped++;
-	}
-
-	desc->buflen = CPMAC_SKB_SIZE;
-	desc->dataflags = CPMAC_OWN;
-
-	return result;
-}
-
-static int cpmac_poll(struct napi_struct *napi, int budget)
-{
-	struct sk_buff *skb;
-	struct cpmac_desc *desc, *restart;
-	struct cpmac_priv *priv = container_of(napi, struct cpmac_priv, napi);
-	int received = 0, processed = 0;
-
-	spin_lock(&priv->rx_lock);
-	if (unlikely(!priv->rx_head)) {
-		if (netif_msg_rx_err(priv) && net_ratelimit())
-			printk(KERN_WARNING "%s: rx: polling, but no queue\n",
-			       priv->dev->name);
-		spin_unlock(&priv->rx_lock);
-		napi_complete(napi);
-		return 0;
-	}
-
-	desc = priv->rx_head;
-	restart = NULL;
-	while (((desc->dataflags & CPMAC_OWN) == 0) && (received < budget)) {
-		processed++;
-
-		if ((desc->dataflags & CPMAC_EOQ) != 0) {
-			/* The last update to eoq->hw_next didn't happen
-			* soon enough, and the receiver stopped here.
-			*Remember this descriptor so we can restart
-			* the receiver after freeing some space.
-			*/
-			if (unlikely(restart)) {
-				if (netif_msg_rx_err(priv))
-					printk(KERN_ERR "%s: poll found a"
-						" duplicate EOQ: %p and %p\n",
-						priv->dev->name, restart, desc);
-				goto fatal_error;
-			}
-
-			restart = desc->next;
-		}
-
-		skb = cpmac_rx_one(priv, desc);
-		if (likely(skb)) {
-			netif_receive_skb(skb);
-			received++;
-		}
-		desc = desc->next;
-	}
-
-	if (desc != priv->rx_head) {
-		/* We freed some buffers, but not the whole ring,
-		 * add what we did free to the rx list */
-		desc->prev->hw_next = (u32)0;
-		priv->rx_head->prev->hw_next = priv->rx_head->mapping;
-	}
-
-	/* Optimization: If we did not actually process an EOQ (perhaps because
-	 * of quota limits), check to see if the tail of the queue has EOQ set.
-	* We should immediately restart in that case so that the receiver can
-	* restart and run in parallel with more packet processing.
-	* This lets us handle slightly larger bursts before running
-	* out of ring space (assuming dev->weight < ring_size) */
-
-	if (!restart &&
-	     (priv->rx_head->prev->dataflags & (CPMAC_OWN|CPMAC_EOQ))
-		    == CPMAC_EOQ &&
-	     (priv->rx_head->dataflags & CPMAC_OWN) != 0) {
-		/* reset EOQ so the poll loop (above) doesn't try to
-		* restart this when it eventually gets to this descriptor.
-		*/
-		priv->rx_head->prev->dataflags &= ~CPMAC_EOQ;
-		restart = priv->rx_head;
-	}
-
-	if (restart) {
-		priv->dev->stats.rx_errors++;
-		priv->dev->stats.rx_fifo_errors++;
-		if (netif_msg_rx_err(priv) && net_ratelimit())
-			printk(KERN_WARNING "%s: rx dma ring overrun\n",
-			       priv->dev->name);
-
-		if (unlikely((restart->dataflags & CPMAC_OWN) == 0)) {
-			if (netif_msg_drv(priv))
-				printk(KERN_ERR "%s: cpmac_poll is trying to "
-					"restart rx from a descriptor that's "
-					"not free: %p\n",
-					priv->dev->name, restart);
-			goto fatal_error;
-		}
-
-		cpmac_write(priv->regs, CPMAC_RX_PTR(0), restart->mapping);
-	}
-
-	priv->rx_head = desc;
-	spin_unlock(&priv->rx_lock);
-	if (unlikely(netif_msg_rx_status(priv)))
-		printk(KERN_DEBUG "%s: poll processed %d packets\n",
-		       priv->dev->name, received);
-	if (processed == 0) {
-		/* we ran out of packets to read,
-		 * revert to interrupt-driven mode */
-		napi_complete(napi);
-		cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1);
-		return 0;
-	}
-
-	return 1;
-
-fatal_error:
-	/* Something went horribly wrong.
-	 * Reset hardware to try to recover rather than wedging. */
-
-	if (netif_msg_drv(priv)) {
-		printk(KERN_ERR "%s: cpmac_poll is confused. "
-				"Resetting hardware\n", priv->dev->name);
-		cpmac_dump_all_desc(priv->dev);
-		printk(KERN_DEBUG "%s: RX_PTR(0)=0x%08x RX_ACK(0)=0x%08x\n",
-			priv->dev->name,
-			cpmac_read(priv->regs, CPMAC_RX_PTR(0)),
-			cpmac_read(priv->regs, CPMAC_RX_ACK(0)));
-	}
-
-	spin_unlock(&priv->rx_lock);
-	napi_complete(napi);
-	netif_tx_stop_all_queues(priv->dev);
-	napi_disable(&priv->napi);
-
-	atomic_inc(&priv->reset_pending);
-	cpmac_hw_stop(priv->dev);
-	if (!schedule_work(&priv->reset_work))
-		atomic_dec(&priv->reset_pending);
-	return 0;
-
-}
-
-static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	int queue, len;
-	struct cpmac_desc *desc;
-	struct cpmac_priv *priv = netdev_priv(dev);
-
-	if (unlikely(atomic_read(&priv->reset_pending)))
-		return NETDEV_TX_BUSY;
-
-	if (unlikely(skb_padto(skb, ETH_ZLEN)))
-		return NETDEV_TX_OK;
-
-	len = max(skb->len, ETH_ZLEN);
-	queue = skb_get_queue_mapping(skb);
-	netif_stop_subqueue(dev, queue);
-
-	desc = &priv->desc_ring[queue];
-	if (unlikely(desc->dataflags & CPMAC_OWN)) {
-		if (netif_msg_tx_err(priv) && net_ratelimit())
-			printk(KERN_WARNING "%s: tx dma ring full\n",
-			       dev->name);
-		return NETDEV_TX_BUSY;
-	}
-
-	spin_lock(&priv->lock);
-	spin_unlock(&priv->lock);
-	desc->dataflags = CPMAC_SOP | CPMAC_EOP | CPMAC_OWN;
-	desc->skb = skb;
-	desc->data_mapping = dma_map_single(&dev->dev, skb->data, len,
-					    DMA_TO_DEVICE);
-	desc->hw_data = (u32)desc->data_mapping;
-	desc->datalen = len;
-	desc->buflen = len;
-	if (unlikely(netif_msg_tx_queued(priv)))
-		printk(KERN_DEBUG "%s: sending 0x%p, len=%d\n", dev->name, skb,
-		       skb->len);
-	if (unlikely(netif_msg_hw(priv)))
-		cpmac_dump_desc(dev, desc);
-	if (unlikely(netif_msg_pktdata(priv)))
-		cpmac_dump_skb(dev, skb);
-	cpmac_write(priv->regs, CPMAC_TX_PTR(queue), (u32)desc->mapping);
-
-	return NETDEV_TX_OK;
-}
-
-static void cpmac_end_xmit(struct net_device *dev, int queue)
-{
-	struct cpmac_desc *desc;
-	struct cpmac_priv *priv = netdev_priv(dev);
-
-	desc = &priv->desc_ring[queue];
-	cpmac_write(priv->regs, CPMAC_TX_ACK(queue), (u32)desc->mapping);
-	if (likely(desc->skb)) {
-		spin_lock(&priv->lock);
-		dev->stats.tx_packets++;
-		dev->stats.tx_bytes += desc->skb->len;
-		spin_unlock(&priv->lock);
-		dma_unmap_single(&dev->dev, desc->data_mapping, desc->skb->len,
-				 DMA_TO_DEVICE);
-
-		if (unlikely(netif_msg_tx_done(priv)))
-			printk(KERN_DEBUG "%s: sent 0x%p, len=%d\n", dev->name,
-			       desc->skb, desc->skb->len);
-
-		dev_kfree_skb_irq(desc->skb);
-		desc->skb = NULL;
-		if (__netif_subqueue_stopped(dev, queue))
-			netif_wake_subqueue(dev, queue);
-	} else {
-		if (netif_msg_tx_err(priv) && net_ratelimit())
-			printk(KERN_WARNING
-			       "%s: end_xmit: spurious interrupt\n", dev->name);
-		if (__netif_subqueue_stopped(dev, queue))
-			netif_wake_subqueue(dev, queue);
-	}
-}
-
-static void cpmac_hw_stop(struct net_device *dev)
-{
-	int i;
-	struct cpmac_priv *priv = netdev_priv(dev);
-	struct plat_cpmac_data *pdata = priv->pdev->dev.platform_data;
-
-	ar7_device_reset(pdata->reset_bit);
-	cpmac_write(priv->regs, CPMAC_RX_CONTROL,
-		    cpmac_read(priv->regs, CPMAC_RX_CONTROL) & ~1);
-	cpmac_write(priv->regs, CPMAC_TX_CONTROL,
-		    cpmac_read(priv->regs, CPMAC_TX_CONTROL) & ~1);
-	for (i = 0; i < 8; i++) {
-		cpmac_write(priv->regs, CPMAC_TX_PTR(i), 0);
-		cpmac_write(priv->regs, CPMAC_RX_PTR(i), 0);
-	}
-	cpmac_write(priv->regs, CPMAC_UNICAST_CLEAR, 0xff);
-	cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 0xff);
-	cpmac_write(priv->regs, CPMAC_TX_INT_CLEAR, 0xff);
-	cpmac_write(priv->regs, CPMAC_MAC_INT_CLEAR, 0xff);
-	cpmac_write(priv->regs, CPMAC_MAC_CONTROL,
-		    cpmac_read(priv->regs, CPMAC_MAC_CONTROL) & ~MAC_MII);
-}
-
-static void cpmac_hw_start(struct net_device *dev)
-{
-	int i;
-	struct cpmac_priv *priv = netdev_priv(dev);
-	struct plat_cpmac_data *pdata = priv->pdev->dev.platform_data;
-
-	ar7_device_reset(pdata->reset_bit);
-	for (i = 0; i < 8; i++) {
-		cpmac_write(priv->regs, CPMAC_TX_PTR(i), 0);
-		cpmac_write(priv->regs, CPMAC_RX_PTR(i), 0);
-	}
-	cpmac_write(priv->regs, CPMAC_RX_PTR(0), priv->rx_head->mapping);
-
-	cpmac_write(priv->regs, CPMAC_MBP, MBP_RXSHORT | MBP_RXBCAST |
-		    MBP_RXMCAST);
-	cpmac_write(priv->regs, CPMAC_BUFFER_OFFSET, 0);
-	for (i = 0; i < 8; i++)
-		cpmac_write(priv->regs, CPMAC_MAC_ADDR_LO(i), dev->dev_addr[5]);
-	cpmac_write(priv->regs, CPMAC_MAC_ADDR_MID, dev->dev_addr[4]);
-	cpmac_write(priv->regs, CPMAC_MAC_ADDR_HI, dev->dev_addr[0] |
-		    (dev->dev_addr[1] << 8) | (dev->dev_addr[2] << 16) |
-		    (dev->dev_addr[3] << 24));
-	cpmac_write(priv->regs, CPMAC_MAX_LENGTH, CPMAC_SKB_SIZE);
-	cpmac_write(priv->regs, CPMAC_UNICAST_CLEAR, 0xff);
-	cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 0xff);
-	cpmac_write(priv->regs, CPMAC_TX_INT_CLEAR, 0xff);
-	cpmac_write(priv->regs, CPMAC_MAC_INT_CLEAR, 0xff);
-	cpmac_write(priv->regs, CPMAC_UNICAST_ENABLE, 1);
-	cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1);
-	cpmac_write(priv->regs, CPMAC_TX_INT_ENABLE, 0xff);
-	cpmac_write(priv->regs, CPMAC_MAC_INT_ENABLE, 3);
-
-	cpmac_write(priv->regs, CPMAC_RX_CONTROL,
-		    cpmac_read(priv->regs, CPMAC_RX_CONTROL) | 1);
-	cpmac_write(priv->regs, CPMAC_TX_CONTROL,
-		    cpmac_read(priv->regs, CPMAC_TX_CONTROL) | 1);
-	cpmac_write(priv->regs, CPMAC_MAC_CONTROL,
-		    cpmac_read(priv->regs, CPMAC_MAC_CONTROL) | MAC_MII |
-		    MAC_FDX);
-}
-
-static void cpmac_clear_rx(struct net_device *dev)
-{
-	struct cpmac_priv *priv = netdev_priv(dev);
-	struct cpmac_desc *desc;
-	int i;
-	if (unlikely(!priv->rx_head))
-		return;
-	desc = priv->rx_head;
-	for (i = 0; i < priv->ring_size; i++) {
-		if ((desc->dataflags & CPMAC_OWN) == 0) {
-			if (netif_msg_rx_err(priv) && net_ratelimit())
-				printk(KERN_WARNING "%s: packet dropped\n",
-				       dev->name);
-			if (unlikely(netif_msg_hw(priv)))
-				cpmac_dump_desc(dev, desc);
-			desc->dataflags = CPMAC_OWN;
-			dev->stats.rx_dropped++;
-		}
-		desc->hw_next = desc->next->mapping;
-		desc = desc->next;
-	}
-	priv->rx_head->prev->hw_next = 0;
-}
-
-static void cpmac_clear_tx(struct net_device *dev)
-{
-	struct cpmac_priv *priv = netdev_priv(dev);
-	int i;
-	if (unlikely(!priv->desc_ring))
-		return;
-	for (i = 0; i < CPMAC_QUEUES; i++) {
-		priv->desc_ring[i].dataflags = 0;
-		if (priv->desc_ring[i].skb) {
-			dev_kfree_skb_any(priv->desc_ring[i].skb);
-			priv->desc_ring[i].skb = NULL;
-		}
-	}
-}
-
-static void cpmac_hw_error(struct work_struct *work)
-{
-	struct cpmac_priv *priv =
-		container_of(work, struct cpmac_priv, reset_work);
-
-	spin_lock(&priv->rx_lock);
-	cpmac_clear_rx(priv->dev);
-	spin_unlock(&priv->rx_lock);
-	cpmac_clear_tx(priv->dev);
-	cpmac_hw_start(priv->dev);
-	barrier();
-	atomic_dec(&priv->reset_pending);
-
-	netif_tx_wake_all_queues(priv->dev);
-	cpmac_write(priv->regs, CPMAC_MAC_INT_ENABLE, 3);
-}
-
-static void cpmac_check_status(struct net_device *dev)
-{
-	struct cpmac_priv *priv = netdev_priv(dev);
-
-	u32 macstatus = cpmac_read(priv->regs, CPMAC_MAC_STATUS);
-	int rx_channel = (macstatus >> 8) & 7;
-	int rx_code = (macstatus >> 12) & 15;
-	int tx_channel = (macstatus >> 16) & 7;
-	int tx_code = (macstatus >> 20) & 15;
-
-	if (rx_code || tx_code) {
-		if (netif_msg_drv(priv) && net_ratelimit()) {
-			/* Can't find any documentation on what these
-			 *error codes actually are. So just log them and hope..
-			 */
-			if (rx_code)
-				printk(KERN_WARNING "%s: host error %d on rx "
-				     "channel %d (macstatus %08x), resetting\n",
-				     dev->name, rx_code, rx_channel, macstatus);
-			if (tx_code)
-				printk(KERN_WARNING "%s: host error %d on tx "
-				     "channel %d (macstatus %08x), resetting\n",
-				     dev->name, tx_code, tx_channel, macstatus);
-		}
-
-		netif_tx_stop_all_queues(dev);
-		cpmac_hw_stop(dev);
-		if (schedule_work(&priv->reset_work))
-			atomic_inc(&priv->reset_pending);
-		if (unlikely(netif_msg_hw(priv)))
-			cpmac_dump_regs(dev);
-	}
-	cpmac_write(priv->regs, CPMAC_MAC_INT_CLEAR, 0xff);
-}
-
-static irqreturn_t cpmac_irq(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct cpmac_priv *priv;
-	int queue;
-	u32 status;
-
-	priv = netdev_priv(dev);
-
-	status = cpmac_read(priv->regs, CPMAC_MAC_INT_VECTOR);
-
-	if (unlikely(netif_msg_intr(priv)))
-		printk(KERN_DEBUG "%s: interrupt status: 0x%08x\n", dev->name,
-		       status);
-
-	if (status & MAC_INT_TX)
-		cpmac_end_xmit(dev, (status & 7));
-
-	if (status & MAC_INT_RX) {
-		queue = (status >> 8) & 7;
-		if (napi_schedule_prep(&priv->napi)) {
-			cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 1 << queue);
-			__napi_schedule(&priv->napi);
-		}
-	}
-
-	cpmac_write(priv->regs, CPMAC_MAC_EOI_VECTOR, 0);
-
-	if (unlikely(status & (MAC_INT_HOST | MAC_INT_STATUS)))
-		cpmac_check_status(dev);
-
-	return IRQ_HANDLED;
-}
-
-static void cpmac_tx_timeout(struct net_device *dev)
-{
-	struct cpmac_priv *priv = netdev_priv(dev);
-
-	spin_lock(&priv->lock);
-	dev->stats.tx_errors++;
-	spin_unlock(&priv->lock);
-	if (netif_msg_tx_err(priv) && net_ratelimit())
-		printk(KERN_WARNING "%s: transmit timeout\n", dev->name);
-
-	atomic_inc(&priv->reset_pending);
-	barrier();
-	cpmac_clear_tx(dev);
-	barrier();
-	atomic_dec(&priv->reset_pending);
-
-	netif_tx_wake_all_queues(priv->dev);
-}
-
-static int cpmac_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	struct cpmac_priv *priv = netdev_priv(dev);
-	if (!(netif_running(dev)))
-		return -EINVAL;
-	if (!priv->phy)
-		return -EINVAL;
-
-	return phy_mii_ioctl(priv->phy, ifr, cmd);
-}
-
-static int cpmac_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct cpmac_priv *priv = netdev_priv(dev);
-
-	if (priv->phy)
-		return phy_ethtool_gset(priv->phy, cmd);
-
-	return -EINVAL;
-}
-
-static int cpmac_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct cpmac_priv *priv = netdev_priv(dev);
-
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	if (priv->phy)
-		return phy_ethtool_sset(priv->phy, cmd);
-
-	return -EINVAL;
-}
-
-static void cpmac_get_ringparam(struct net_device *dev,
-						struct ethtool_ringparam *ring)
-{
-	struct cpmac_priv *priv = netdev_priv(dev);
-
-	ring->rx_max_pending = 1024;
-	ring->rx_mini_max_pending = 1;
-	ring->rx_jumbo_max_pending = 1;
-	ring->tx_max_pending = 1;
-
-	ring->rx_pending = priv->ring_size;
-	ring->rx_mini_pending = 1;
-	ring->rx_jumbo_pending = 1;
-	ring->tx_pending = 1;
-}
-
-static int cpmac_set_ringparam(struct net_device *dev,
-						struct ethtool_ringparam *ring)
-{
-	struct cpmac_priv *priv = netdev_priv(dev);
-
-	if (netif_running(dev))
-		return -EBUSY;
-	priv->ring_size = ring->rx_pending;
-	return 0;
-}
-
-static void cpmac_get_drvinfo(struct net_device *dev,
-			      struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, "cpmac");
-	strcpy(info->version, CPMAC_VERSION);
-	info->fw_version[0] = '\0';
-	sprintf(info->bus_info, "%s", "cpmac");
-	info->regdump_len = 0;
-}
-
-static const struct ethtool_ops cpmac_ethtool_ops = {
-	.get_settings = cpmac_get_settings,
-	.set_settings = cpmac_set_settings,
-	.get_drvinfo = cpmac_get_drvinfo,
-	.get_link = ethtool_op_get_link,
-	.get_ringparam = cpmac_get_ringparam,
-	.set_ringparam = cpmac_set_ringparam,
-};
-
-static void cpmac_adjust_link(struct net_device *dev)
-{
-	struct cpmac_priv *priv = netdev_priv(dev);
-	int new_state = 0;
-
-	spin_lock(&priv->lock);
-	if (priv->phy->link) {
-		netif_tx_start_all_queues(dev);
-		if (priv->phy->duplex != priv->oldduplex) {
-			new_state = 1;
-			priv->oldduplex = priv->phy->duplex;
-		}
-
-		if (priv->phy->speed != priv->oldspeed) {
-			new_state = 1;
-			priv->oldspeed = priv->phy->speed;
-		}
-
-		if (!priv->oldlink) {
-			new_state = 1;
-			priv->oldlink = 1;
-		}
-	} else if (priv->oldlink) {
-		new_state = 1;
-		priv->oldlink = 0;
-		priv->oldspeed = 0;
-		priv->oldduplex = -1;
-	}
-
-	if (new_state && netif_msg_link(priv) && net_ratelimit())
-		phy_print_status(priv->phy);
-
-	spin_unlock(&priv->lock);
-}
-
-static int cpmac_open(struct net_device *dev)
-{
-	int i, size, res;
-	struct cpmac_priv *priv = netdev_priv(dev);
-	struct resource *mem;
-	struct cpmac_desc *desc;
-	struct sk_buff *skb;
-
-	mem = platform_get_resource_byname(priv->pdev, IORESOURCE_MEM, "regs");
-	if (!request_mem_region(mem->start, resource_size(mem), dev->name)) {
-		if (netif_msg_drv(priv))
-			printk(KERN_ERR "%s: failed to request registers\n",
-			       dev->name);
-		res = -ENXIO;
-		goto fail_reserve;
-	}
-
-	priv->regs = ioremap(mem->start, resource_size(mem));
-	if (!priv->regs) {
-		if (netif_msg_drv(priv))
-			printk(KERN_ERR "%s: failed to remap registers\n",
-			       dev->name);
-		res = -ENXIO;
-		goto fail_remap;
-	}
-
-	size = priv->ring_size + CPMAC_QUEUES;
-	priv->desc_ring = dma_alloc_coherent(&dev->dev,
-					     sizeof(struct cpmac_desc) * size,
-					     &priv->dma_ring,
-					     GFP_KERNEL);
-	if (!priv->desc_ring) {
-		res = -ENOMEM;
-		goto fail_alloc;
-	}
-
-	for (i = 0; i < size; i++)
-		priv->desc_ring[i].mapping = priv->dma_ring + sizeof(*desc) * i;
-
-	priv->rx_head = &priv->desc_ring[CPMAC_QUEUES];
-	for (i = 0, desc = priv->rx_head; i < priv->ring_size; i++, desc++) {
-		skb = netdev_alloc_skb_ip_align(dev, CPMAC_SKB_SIZE);
-		if (unlikely(!skb)) {
-			res = -ENOMEM;
-			goto fail_desc;
-		}
-		desc->skb = skb;
-		desc->data_mapping = dma_map_single(&dev->dev, skb->data,
-						    CPMAC_SKB_SIZE,
-						    DMA_FROM_DEVICE);
-		desc->hw_data = (u32)desc->data_mapping;
-		desc->buflen = CPMAC_SKB_SIZE;
-		desc->dataflags = CPMAC_OWN;
-		desc->next = &priv->rx_head[(i + 1) % priv->ring_size];
-		desc->next->prev = desc;
-		desc->hw_next = (u32)desc->next->mapping;
-	}
-
-	priv->rx_head->prev->hw_next = (u32)0;
-
-	res = request_irq(dev->irq, cpmac_irq, IRQF_SHARED, dev->name, dev);
-	if (res) {
-		if (netif_msg_drv(priv))
-			printk(KERN_ERR "%s: failed to obtain irq\n",
-			       dev->name);
-		goto fail_irq;
-	}
-
-	atomic_set(&priv->reset_pending, 0);
-	INIT_WORK(&priv->reset_work, cpmac_hw_error);
-	cpmac_hw_start(dev);
-
-	napi_enable(&priv->napi);
-	priv->phy->state = PHY_CHANGELINK;
-	phy_start(priv->phy);
-
-	return 0;
-
-fail_irq:
-fail_desc:
-	for (i = 0; i < priv->ring_size; i++) {
-		if (priv->rx_head[i].skb) {
-			dma_unmap_single(&dev->dev,
-					 priv->rx_head[i].data_mapping,
-					 CPMAC_SKB_SIZE,
-					 DMA_FROM_DEVICE);
-			kfree_skb(priv->rx_head[i].skb);
-		}
-	}
-fail_alloc:
-	kfree(priv->desc_ring);
-	iounmap(priv->regs);
-
-fail_remap:
-	release_mem_region(mem->start, resource_size(mem));
-
-fail_reserve:
-	return res;
-}
-
-static int cpmac_stop(struct net_device *dev)
-{
-	int i;
-	struct cpmac_priv *priv = netdev_priv(dev);
-	struct resource *mem;
-
-	netif_tx_stop_all_queues(dev);
-
-	cancel_work_sync(&priv->reset_work);
-	napi_disable(&priv->napi);
-	phy_stop(priv->phy);
-
-	cpmac_hw_stop(dev);
-
-	for (i = 0; i < 8; i++)
-		cpmac_write(priv->regs, CPMAC_TX_PTR(i), 0);
-	cpmac_write(priv->regs, CPMAC_RX_PTR(0), 0);
-	cpmac_write(priv->regs, CPMAC_MBP, 0);
-
-	free_irq(dev->irq, dev);
-	iounmap(priv->regs);
-	mem = platform_get_resource_byname(priv->pdev, IORESOURCE_MEM, "regs");
-	release_mem_region(mem->start, resource_size(mem));
-	priv->rx_head = &priv->desc_ring[CPMAC_QUEUES];
-	for (i = 0; i < priv->ring_size; i++) {
-		if (priv->rx_head[i].skb) {
-			dma_unmap_single(&dev->dev,
-					 priv->rx_head[i].data_mapping,
-					 CPMAC_SKB_SIZE,
-					 DMA_FROM_DEVICE);
-			kfree_skb(priv->rx_head[i].skb);
-		}
-	}
-
-	dma_free_coherent(&dev->dev, sizeof(struct cpmac_desc) *
-			  (CPMAC_QUEUES + priv->ring_size),
-			  priv->desc_ring, priv->dma_ring);
-	return 0;
-}
-
-static const struct net_device_ops cpmac_netdev_ops = {
-	.ndo_open		= cpmac_open,
-	.ndo_stop		= cpmac_stop,
-	.ndo_start_xmit		= cpmac_start_xmit,
-	.ndo_tx_timeout		= cpmac_tx_timeout,
-	.ndo_set_multicast_list	= cpmac_set_multicast_list,
-	.ndo_do_ioctl		= cpmac_ioctl,
-	.ndo_set_config		= cpmac_config,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address	= eth_mac_addr,
-};
-
-static int external_switch;
-
-static int __devinit cpmac_probe(struct platform_device *pdev)
-{
-	int rc, phy_id;
-	char mdio_bus_id[MII_BUS_ID_SIZE];
-	struct resource *mem;
-	struct cpmac_priv *priv;
-	struct net_device *dev;
-	struct plat_cpmac_data *pdata;
-
-	pdata = pdev->dev.platform_data;
-
-	if (external_switch || dumb_switch) {
-		strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */
-		phy_id = pdev->id;
-	} else {
-		for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
-			if (!(pdata->phy_mask & (1 << phy_id)))
-				continue;
-			if (!cpmac_mii->phy_map[phy_id])
-				continue;
-			strncpy(mdio_bus_id, cpmac_mii->id, MII_BUS_ID_SIZE);
-			break;
-		}
-	}
-
-	if (phy_id == PHY_MAX_ADDR) {
-		dev_err(&pdev->dev, "no PHY present, falling back "
-					"to switch on MDIO bus 0\n");
-		strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */
-		phy_id = pdev->id;
-	}
-
-	dev = alloc_etherdev_mq(sizeof(*priv), CPMAC_QUEUES);
-
-	if (!dev) {
-		printk(KERN_ERR "cpmac: Unable to allocate net_device\n");
-		return -ENOMEM;
-	}
-
-	platform_set_drvdata(pdev, dev);
-	priv = netdev_priv(dev);
-
-	priv->pdev = pdev;
-	mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
-	if (!mem) {
-		rc = -ENODEV;
-		goto fail;
-	}
-
-	dev->irq = platform_get_irq_byname(pdev, "irq");
-
-	dev->netdev_ops = &cpmac_netdev_ops;
-	dev->ethtool_ops = &cpmac_ethtool_ops;
-
-	netif_napi_add(dev, &priv->napi, cpmac_poll, 64);
-
-	spin_lock_init(&priv->lock);
-	spin_lock_init(&priv->rx_lock);
-	priv->dev = dev;
-	priv->ring_size = 64;
-	priv->msg_enable = netif_msg_init(debug_level, 0xff);
-	memcpy(dev->dev_addr, pdata->dev_addr, sizeof(pdata->dev_addr));
-
-	snprintf(priv->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT,
-						mdio_bus_id, phy_id);
-
-	priv->phy = phy_connect(dev, priv->phy_name, cpmac_adjust_link, 0,
-						PHY_INTERFACE_MODE_MII);
-
-	if (IS_ERR(priv->phy)) {
-		if (netif_msg_drv(priv))
-			printk(KERN_ERR "%s: Could not attach to PHY\n",
-			       dev->name);
-		rc = PTR_ERR(priv->phy);
-		goto fail;
-	}
-
-	rc = register_netdev(dev);
-	if (rc) {
-		printk(KERN_ERR "cpmac: error %i registering device %s\n", rc,
-		       dev->name);
-		goto fail;
-	}
-
-	if (netif_msg_probe(priv)) {
-		printk(KERN_INFO
-		       "cpmac: device %s (regs: %p, irq: %d, phy: %s, "
-		       "mac: %pM)\n", dev->name, (void *)mem->start, dev->irq,
-		       priv->phy_name, dev->dev_addr);
-	}
-	return 0;
-
-fail:
-	free_netdev(dev);
-	return rc;
-}
-
-static int __devexit cpmac_remove(struct platform_device *pdev)
-{
-	struct net_device *dev = platform_get_drvdata(pdev);
-	unregister_netdev(dev);
-	free_netdev(dev);
-	return 0;
-}
-
-static struct platform_driver cpmac_driver = {
-	.driver.name = "cpmac",
-	.driver.owner = THIS_MODULE,
-	.probe = cpmac_probe,
-	.remove = __devexit_p(cpmac_remove),
-};
-
-int __devinit cpmac_init(void)
-{
-	u32 mask;
-	int i, res;
-
-	cpmac_mii = mdiobus_alloc();
-	if (cpmac_mii == NULL)
-		return -ENOMEM;
-
-	cpmac_mii->name = "cpmac-mii";
-	cpmac_mii->read = cpmac_mdio_read;
-	cpmac_mii->write = cpmac_mdio_write;
-	cpmac_mii->reset = cpmac_mdio_reset;
-	cpmac_mii->irq = mii_irqs;
-
-	cpmac_mii->priv = ioremap(AR7_REGS_MDIO, 256);
-
-	if (!cpmac_mii->priv) {
-		printk(KERN_ERR "Can't ioremap mdio registers\n");
-		res = -ENXIO;
-		goto fail_alloc;
-	}
-
-#warning FIXME: unhardcode gpio&reset bits
-	ar7_gpio_disable(26);
-	ar7_gpio_disable(27);
-	ar7_device_reset(AR7_RESET_BIT_CPMAC_LO);
-	ar7_device_reset(AR7_RESET_BIT_CPMAC_HI);
-	ar7_device_reset(AR7_RESET_BIT_EPHY);
-
-	cpmac_mii->reset(cpmac_mii);
-
-	for (i = 0; i < 300; i++) {
-		mask = cpmac_read(cpmac_mii->priv, CPMAC_MDIO_ALIVE);
-		if (mask)
-			break;
-		else
-			msleep(10);
-	}
-
-	mask &= 0x7fffffff;
-	if (mask & (mask - 1)) {
-		external_switch = 1;
-		mask = 0;
-	}
-
-	cpmac_mii->phy_mask = ~(mask | 0x80000000);
-	snprintf(cpmac_mii->id, MII_BUS_ID_SIZE, "1");
-
-	res = mdiobus_register(cpmac_mii);
-	if (res)
-		goto fail_mii;
-
-	res = platform_driver_register(&cpmac_driver);
-	if (res)
-		goto fail_cpmac;
-
-	return 0;
-
-fail_cpmac:
-	mdiobus_unregister(cpmac_mii);
-
-fail_mii:
-	iounmap(cpmac_mii->priv);
-
-fail_alloc:
-	mdiobus_free(cpmac_mii);
-
-	return res;
-}
-
-void __devexit cpmac_exit(void)
-{
-	platform_driver_unregister(&cpmac_driver);
-	mdiobus_unregister(cpmac_mii);
-	iounmap(cpmac_mii->priv);
-	mdiobus_free(cpmac_mii);
-}
-
-module_init(cpmac_init);
-module_exit(cpmac_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/cris/eth_v10.c linux-libre-3.2-gnu/drivers/net/cris/eth_v10.c
--- linux-libre-3.1-gnu/drivers/net/cris/eth_v10.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cris/eth_v10.c	2012-01-04 18:55:44.000000000 -0500
@@ -261,7 +261,7 @@
 	.ndo_start_xmit		= e100_send_packet,
 	.ndo_tx_timeout		= e100_tx_timeout,
 	.ndo_get_stats		= e100_get_stats,
-	.ndo_set_multicast_list	= set_multicast_list,
+	.ndo_set_rx_mode	= set_multicast_list,
 	.ndo_do_ioctl		= e100_ioctl,
 	.ndo_set_mac_address	= e100_set_mac_address,
 	.ndo_validate_addr	= eth_validate_addr,
diff -druN linux-libre-3.1-gnu/drivers/net/cs89x0.c linux-libre-3.2-gnu/drivers/net/cs89x0.c
--- linux-libre-3.1-gnu/drivers/net/cs89x0.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cs89x0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1913 +0,0 @@
-/* cs89x0.c: A Crystal Semiconductor (Now Cirrus Logic) CS89[02]0
- *  driver for linux.
- */
-
-/*
-	Written 1996 by Russell Nelson, with reference to skeleton.c
-	written 1993-1994 by Donald Becker.
-
-	This software may be used and distributed according to the terms
-	of the GNU General Public License, incorporated herein by reference.
-
-        The author may be reached at nelson@crynwr.com, Crynwr
-        Software, 521 Pleasant Valley Rd., Potsdam, NY 13676
-
-  Changelog:
-
-  Mike Cruse        : mcruse@cti-ltd.com
-                    : Changes for Linux 2.0 compatibility.
-                    : Added dev_id parameter in net_interrupt(),
-                    : request_irq() and free_irq(). Just NULL for now.
-
-  Mike Cruse        : Added MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT macros
-                    : in net_open() and net_close() so kerneld would know
-                    : that the module is in use and wouldn't eject the
-                    : driver prematurely.
-
-  Mike Cruse        : Rewrote init_module() and cleanup_module using 8390.c
-                    : as an example. Disabled autoprobing in init_module(),
-                    : not a good thing to do to other devices while Linux
-                    : is running from all accounts.
-
-  Russ Nelson       : Jul 13 1998.  Added RxOnly DMA support.
-
-  Melody Lee        : Aug 10 1999.  Changes for Linux 2.2.5 compatibility.
-                    : email: ethernet@crystal.cirrus.com
-
-  Alan Cox          : Removed 1.2 support, added 2.1 extra counters.
-
-  Andrew Morton     : Kernel 2.3.48
-                    : Handle kmalloc() failures
-                    : Other resource allocation fixes
-                    : Add SMP locks
-                    : Integrate Russ Nelson's ALLOW_DMA functionality back in.
-                    : If ALLOW_DMA is true, make DMA runtime selectable
-                    : Folded in changes from Cirrus (Melody Lee
-                    : <klee@crystal.cirrus.com>)
-                    : Don't call netif_wake_queue() in net_send_packet()
-                    : Fixed an out-of-mem bug in dma_rx()
-                    : Updated Documentation/networking/cs89x0.txt
-
-  Andrew Morton     : Kernel 2.3.99-pre1
-                    : Use skb_reserve to longword align IP header (two places)
-                    : Remove a delay loop from dma_rx()
-                    : Replace '100' with HZ
-                    : Clean up a couple of skb API abuses
-                    : Added 'cs89x0_dma=N' kernel boot option
-                    : Correctly initialise lp->lock in non-module compile
-
-  Andrew Morton     : Kernel 2.3.99-pre4-1
-                    : MOD_INC/DEC race fix (see
-                    : http://www.uwsg.indiana.edu/hypermail/linux/kernel/0003.3/1532.html)
-
-  Andrew Morton     : Kernel 2.4.0-test7-pre2
-                    : Enhanced EEPROM support to cover more devices,
-                    :   abstracted IRQ mapping to support CONFIG_ARCH_CLPS7500 arch
-                    :   (Jason Gunthorpe <jgg@ualberta.ca>)
-
-  Andrew Morton     : Kernel 2.4.0-test11-pre4
-                    : Use dev->name in request_*() (Andrey Panin)
-                    : Fix an error-path memleak in init_module()
-                    : Preserve return value from request_irq()
-                    : Fix type of `media' module parm (Keith Owens)
-                    : Use SET_MODULE_OWNER()
-                    : Tidied up strange request_irq() abuse in net_open().
-
-  Andrew Morton     : Kernel 2.4.3-pre1
-                    : Request correct number of pages for DMA (Hugh Dickens)
-                    : Select PP_ChipID _after_ unregister_netdev in cleanup_module()
-                    :  because unregister_netdev() calls get_stats.
-                    : Make `version[]' __initdata
-                    : Uninlined the read/write reg/word functions.
-
-  Oskar Schirmer    : oskar@scara.com
-                    : HiCO.SH4 (superh) support added (irq#1, cs89x0_media=)
-
-  Deepak Saxena     : dsaxena@plexity.net
-                    : Intel IXDP2x01 (XScale ixp2x00 NPU) platform support
-
-  Dmitry Pervushin  : dpervushin@ru.mvista.com
-                    : PNX010X platform support
-
-  Deepak Saxena     : dsaxena@plexity.net
-                    : Intel IXDP2351 platform support
-
-  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
-   or override something. */
-#include <linux/module.h>
-
-/*
- * Set this to zero to disable DMA code
- *
- * Note that even if DMA is turned off we still support the 'dma' and  'use_dma'
- * module options so we don't break any startup scripts.
- */
-#ifndef CONFIG_ISA_DMA_API
-#define ALLOW_DMA	0
-#else
-#define ALLOW_DMA	1
-#endif
-
-/*
- * Set this to zero to remove all the debug statements via
- * dead code elimination
- */
-#define DEBUGGING	1
-
-/*
-  Sources:
-
-	Crynwr packet driver epktisa.
-
-	Crystal Semiconductor data sheets.
-
-*/
-
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/gfp.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#if ALLOW_DMA
-#include <asm/dma.h>
-#endif
-
-#include "cs89x0.h"
-
-static char version[] __initdata =
-"cs89x0.c: v2.4.3-pre1 Russell Nelson <nelson@crynwr.com>, Andrew Morton\n";
-
-#define DRV_NAME "cs89x0"
-
-/* First, a few definitions that the brave might change.
-   A zero-terminated list of I/O addresses to be probed. Some special flags..
-      Addr & 1 = Read back the address port, look for signature and reset
-                 the page window before probing
-      Addr & 3 = Reset the page window and probe
-   The CLPS eval board has the Cirrus chip at 0x80090300, in ARM IO space,
-   but it is possible that a Cirrus board could be plugged into the ISA
-   slots. */
-/* The cs8900 has 4 IRQ pins, software selectable. cs8900_irq_map maps
-   them to system IRQ numbers. This mapping is card specific and is set to
-   the configuration of the Cirrus Eval board for this chip. */
-#if defined(CONFIG_MACH_IXDP2351)
-static unsigned int netcard_portlist[] __used __initdata = {IXDP2351_VIRT_CS8900_BASE, 0};
-static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0};
-#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 = {
-	PBC_BASE_ADDRESS + PBC_CS8900A_IOBASE + 0x300, 0
-};
-static unsigned cs8900_irq_map[] = {EXPIO_INT_ENET_INT, 0, 0, 0};
-#else
-static unsigned int netcard_portlist[] __used __initdata =
-   { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
-static unsigned int cs8900_irq_map[] = {10,11,12,5};
-#endif
-
-#if DEBUGGING
-static unsigned int net_debug = DEBUGGING;
-#else
-#define net_debug 0	/* gcc will remove all the debug code for us */
-#endif
-
-/* The number of low I/O ports used by the ethercard. */
-#define NETCARD_IO_EXTENT	16
-
-/* we allow the user to override various values normally set in the EEPROM */
-#define FORCE_RJ45	0x0001    /* pick one of these three */
-#define FORCE_AUI	0x0002
-#define FORCE_BNC	0x0004
-
-#define FORCE_AUTO	0x0010    /* pick one of these three */
-#define FORCE_HALF	0x0020
-#define FORCE_FULL	0x0030
-
-/* Information that need to be kept for each board. */
-struct net_local {
-	int chip_type;		/* one of: CS8900, CS8920, CS8920M */
-	char chip_revision;	/* revision letter of the chip ('A'...) */
-	int send_cmd;		/* the proper send command: TX_NOW, TX_AFTER_381, or TX_AFTER_ALL */
-	int auto_neg_cnf;	/* auto-negotiation word from EEPROM */
-	int adapter_cnf;	/* adapter configuration from EEPROM */
-	int isa_config;		/* ISA configuration from EEPROM */
-	int irq_map;		/* IRQ map from EEPROM */
-	int rx_mode;		/* what mode are we in? 0, RX_MULTCAST_ACCEPT, or RX_ALL_ACCEPT */
-	int curr_rx_cfg;	/* a copy of PP_RxCFG */
-	int linectl;		/* either 0 or LOW_RX_SQUELCH, depending on configuration. */
-	int send_underrun;	/* keep track of how many underruns in a row we get */
-	int force;		/* force various values; see FORCE* above. */
-	spinlock_t lock;
-#if ALLOW_DMA
-	int use_dma;		/* Flag: we're using dma */
-	int dma;		/* DMA channel */
-	int dmasize;		/* 16 or 64 */
-	unsigned char *dma_buff;	/* points to the beginning of the buffer */
-	unsigned char *end_dma_buff;	/* points to the end of the buffer */
-	unsigned char *rx_dma_ptr;	/* points to the next packet  */
-#endif
-};
-
-/* Index to functions, as function prototypes. */
-
-static int cs89x0_probe1(struct net_device *dev, int ioaddr, int modular);
-static int net_open(struct net_device *dev);
-static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t net_interrupt(int irq, void *dev_id);
-static void set_multicast_list(struct net_device *dev);
-static void net_timeout(struct net_device *dev);
-static void net_rx(struct net_device *dev);
-static int net_close(struct net_device *dev);
-static struct net_device_stats *net_get_stats(struct net_device *dev);
-static void reset_chip(struct net_device *dev);
-static int get_eeprom_data(struct net_device *dev, int off, int len, int *buffer);
-static int get_eeprom_cksum(int off, int len, int *buffer);
-static int set_mac_address(struct net_device *dev, void *addr);
-static void count_rx_errors(int status, struct net_device *dev);
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void net_poll_controller(struct net_device *dev);
-#endif
-#if ALLOW_DMA
-static void get_dma_channel(struct net_device *dev);
-static void release_dma_buff(struct net_local *lp);
-#endif
-
-/* Example routines you must write ;->. */
-#define tx_done(dev) 1
-
-/*
- * Permit 'cs89x0_dma=N' in the kernel boot environment
- */
-#if !defined(MODULE) && (ALLOW_DMA != 0)
-static int g_cs89x0_dma;
-
-static int __init dma_fn(char *str)
-{
-	g_cs89x0_dma = simple_strtol(str,NULL,0);
-	return 1;
-}
-
-__setup("cs89x0_dma=", dma_fn);
-#endif	/* !defined(MODULE) && (ALLOW_DMA != 0) */
-
-#ifndef MODULE
-static int g_cs89x0_media__force;
-
-static int __init media_fn(char *str)
-{
-	if (!strcmp(str, "rj45")) g_cs89x0_media__force = FORCE_RJ45;
-	else if (!strcmp(str, "aui")) g_cs89x0_media__force = FORCE_AUI;
-	else if (!strcmp(str, "bnc")) g_cs89x0_media__force = FORCE_BNC;
-	return 1;
-}
-
-__setup("cs89x0_media=", media_fn);
-
-
-/* Check for a network adaptor of this type, and return '0' iff one exists.
-   If dev->base_addr == 0, probe all likely locations.
-   If dev->base_addr == 1, always return failure.
-   If dev->base_addr == 2, allocate space for the device and return success
-   (detachable devices only).
-   Return 0 on success.
-   */
-
-struct net_device * __init cs89x0_probe(int unit)
-{
-	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
-	unsigned *port;
-	int err = 0;
-	int irq;
-	int io;
-
-	if (!dev)
-		return ERR_PTR(-ENODEV);
-
-	sprintf(dev->name, "eth%d", unit);
-	netdev_boot_setup_check(dev);
-	io = dev->base_addr;
-	irq = dev->irq;
-
-	if (net_debug)
-		printk("cs89x0:cs89x0_probe(0x%x)\n", io);
-
-	if (io > 0x1ff)	{	/* Check a single specified location. */
-		err = cs89x0_probe1(dev, io, 0);
-	} else if (io != 0) {	/* Don't probe at all. */
-		err = -ENXIO;
-	} else {
-		for (port = netcard_portlist; *port; port++) {
-			if (cs89x0_probe1(dev, *port, 0) == 0)
-				break;
-			dev->irq = irq;
-		}
-		if (!*port)
-			err = -ENODEV;
-	}
-	if (err)
-		goto out;
-	return dev;
-out:
-	free_netdev(dev);
-	printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected.  Be sure to disable PnP with SETUP\n");
-	return ERR_PTR(err);
-}
-#endif
-
-#if defined(CONFIG_MACH_IXDP2351)
-static u16
-readword(unsigned long base_addr, int portno)
-{
-	return __raw_readw(base_addr + (portno << 1));
-}
-
-static void
-writeword(unsigned long base_addr, int portno, u16 value)
-{
-	__raw_writew(value, base_addr + (portno << 1));
-}
-#elif defined(CONFIG_ARCH_IXDP2X01)
-static u16
-readword(unsigned long base_addr, int portno)
-{
-	return __raw_readl(base_addr + (portno << 1));
-}
-
-static void
-writeword(unsigned long base_addr, int portno, u16 value)
-{
-	__raw_writel(value, base_addr + (portno << 1));
-}
-#else
-static u16
-readword(unsigned long base_addr, int portno)
-{
-	return inw(base_addr + portno);
-}
-
-static void
-writeword(unsigned long base_addr, int portno, u16 value)
-{
-	outw(value, base_addr + portno);
-}
-#endif
-
-static void
-readwords(unsigned long base_addr, int portno, void *buf, int length)
-{
-	u8 *buf8 = (u8 *)buf;
-
-	do {
-		u16 tmp16;
-
-		tmp16 = readword(base_addr, portno);
-		*buf8++ = (u8)tmp16;
-		*buf8++ = (u8)(tmp16 >> 8);
-	} while (--length);
-}
-
-static void
-writewords(unsigned long base_addr, int portno, void *buf, int length)
-{
-	u8 *buf8 = (u8 *)buf;
-
-	do {
-		u16 tmp16;
-
-		tmp16 = *buf8++;
-		tmp16 |= (*buf8++) << 8;
-		writeword(base_addr, portno, tmp16);
-	} while (--length);
-}
-
-static u16
-readreg(struct net_device *dev, u16 regno)
-{
-	writeword(dev->base_addr, ADD_PORT, regno);
-	return readword(dev->base_addr, DATA_PORT);
-}
-
-static void
-writereg(struct net_device *dev, u16 regno, u16 value)
-{
-	writeword(dev->base_addr, ADD_PORT, regno);
-	writeword(dev->base_addr, DATA_PORT, value);
-}
-
-static int __init
-wait_eeprom_ready(struct net_device *dev)
-{
-	int timeout = jiffies;
-	/* check to see if the EEPROM is ready, a timeout is used -
-	   just in case EEPROM is ready when SI_BUSY in the
-	   PP_SelfST is clear */
-	while(readreg(dev, PP_SelfST) & SI_BUSY)
-		if (jiffies - timeout >= 40)
-			return -1;
-	return 0;
-}
-
-static int __init
-get_eeprom_data(struct net_device *dev, int off, int len, int *buffer)
-{
-	int i;
-
-	if (net_debug > 3) printk("EEPROM data from %x for %x:\n",off,len);
-	for (i = 0; i < len; i++) {
-		if (wait_eeprom_ready(dev) < 0) return -1;
-		/* Now send the EEPROM read command and EEPROM location to read */
-		writereg(dev, PP_EECMD, (off + i) | EEPROM_READ_CMD);
-		if (wait_eeprom_ready(dev) < 0) return -1;
-		buffer[i] = readreg(dev, PP_EEData);
-		if (net_debug > 3) printk("%04x ", buffer[i]);
-	}
-	if (net_debug > 3) printk("\n");
-        return 0;
-}
-
-static int  __init
-get_eeprom_cksum(int off, int len, int *buffer)
-{
-	int i, cksum;
-
-	cksum = 0;
-	for (i = 0; i < len; i++)
-		cksum += buffer[i];
-	cksum &= 0xffff;
-	if (cksum == 0)
-		return 0;
-	return -1;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Polling receive - used by netconsole and other diagnostic tools
- * to allow network i/o with interrupts disabled.
- */
-static void net_poll_controller(struct net_device *dev)
-{
-	disable_irq(dev->irq);
-	net_interrupt(dev->irq, dev);
-	enable_irq(dev->irq);
-}
-#endif
-
-static const struct net_device_ops net_ops = {
-	.ndo_open		= net_open,
-	.ndo_stop		= net_close,
-	.ndo_tx_timeout		= net_timeout,
-	.ndo_start_xmit 	= net_send_packet,
-	.ndo_get_stats		= net_get_stats,
-	.ndo_set_multicast_list = set_multicast_list,
-	.ndo_set_mac_address 	= set_mac_address,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= net_poll_controller,
-#endif
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-/* This is the real probe routine.  Linux has a history of friendly device
-   probes on the ISA bus.  A good device probes avoids doing writes, and
-   verifies that the correct device exists and functions.
-   Return 0 on success.
- */
-
-static int __init
-cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
-{
-	struct net_local *lp = netdev_priv(dev);
-	static unsigned version_printed;
-	int i;
-	int tmp;
-	unsigned rev_type = 0;
-	int eeprom_buff[CHKSUM_LEN];
-	int retval;
-
-	/* Initialize the device structure. */
-	if (!modular) {
-		memset(lp, 0, sizeof(*lp));
-		spin_lock_init(&lp->lock);
-#ifndef MODULE
-#if ALLOW_DMA
-		if (g_cs89x0_dma) {
-			lp->use_dma = 1;
-			lp->dma = g_cs89x0_dma;
-			lp->dmasize = 16;	/* Could make this an option... */
-		}
-#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. */
-	/* WTF is going on here? */
-	if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) {
-		printk(KERN_ERR "%s: request_region(0x%x, 0x%x) failed\n",
-				DRV_NAME, ioaddr, NETCARD_IO_EXTENT);
-		retval = -EBUSY;
-		goto out1;
-	}
-
-	/* if they give us an odd I/O address, then do ONE write to
-           the address port, to get it back to address zero, where we
-           expect to find the EISA signature word. An IO with a base of 0x3
-	   will skip the test for the ADD_PORT. */
-	if (ioaddr & 1) {
-		if (net_debug > 1)
-			printk(KERN_INFO "%s: odd ioaddr 0x%x\n", dev->name, ioaddr);
-	        if ((ioaddr & 2) != 2)
-	        	if ((readword(ioaddr & ~3, ADD_PORT) & ADD_MASK) != ADD_SIG) {
-				printk(KERN_ERR "%s: bad signature 0x%x\n",
-					dev->name, readword(ioaddr & ~3, ADD_PORT));
-		        	retval = -ENODEV;
-				goto out2;
-			}
-	}
-
-	ioaddr &= ~3;
-	printk(KERN_DEBUG "PP_addr at %x[%x]: 0x%x\n",
-			ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT));
-	writeword(ioaddr, ADD_PORT, PP_ChipID);
-
-	tmp = readword(ioaddr, DATA_PORT);
-	if (tmp != CHIP_EISA_ID_SIG) {
-		printk(KERN_DEBUG "%s: incorrect signature at %x[%x]: 0x%x!="
-			CHIP_EISA_ID_SIG_STR "\n",
-			dev->name, ioaddr, DATA_PORT, tmp);
-  		retval = -ENODEV;
-  		goto out2;
-	}
-
-	/* Fill in the 'dev' fields. */
-	dev->base_addr = ioaddr;
-
-	/* get the chip type */
-	rev_type = readreg(dev, PRODUCT_ID_ADD);
-	lp->chip_type = rev_type &~ REVISON_BITS;
-	lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
-
-	/* Check the chip type and revision in order to set the correct send command
-	CS8920 revision C and CS8900 revision F can use the faster send. */
-	lp->send_cmd = TX_AFTER_381;
-	if (lp->chip_type == CS8900 && lp->chip_revision >= 'F')
-		lp->send_cmd = TX_NOW;
-	if (lp->chip_type != CS8900 && lp->chip_revision >= 'C')
-		lp->send_cmd = TX_NOW;
-
-	if (net_debug  &&  version_printed++ == 0)
-		printk(version);
-
-	printk(KERN_INFO "%s: cs89%c0%s rev %c found at %#3lx ",
-	       dev->name,
-	       lp->chip_type==CS8900?'0':'2',
-	       lp->chip_type==CS8920M?"M":"",
-	       lp->chip_revision,
-	       dev->base_addr);
-
-	reset_chip(dev);
-
-        /* Here we read the current configuration of the chip. If there
-	   is no Extended EEPROM then the idea is to not disturb the chip
-	   configuration, it should have been correctly setup by automatic
-	   EEPROM read on reset. So, if the chip says it read the EEPROM
-	   the driver will always do *something* instead of complain that
-	   adapter_cnf is 0. */
-
-
-        if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) ==
-	      (EEPROM_OK|EEPROM_PRESENT)) {
-	        /* Load the MAC. */
-		for (i=0; i < ETH_ALEN/2; i++) {
-	                unsigned int Addr;
-			Addr = readreg(dev, PP_IA+i*2);
-		        dev->dev_addr[i*2] = Addr & 0xFF;
-		        dev->dev_addr[i*2+1] = Addr >> 8;
-		}
-
-	   	/* Load the Adapter Configuration.
-		   Note:  Barring any more specific information from some
-		   other source (ie EEPROM+Schematics), we would not know
-		   how to operate a 10Base2 interface on the AUI port.
-		   However, since we  do read the status of HCB1 and use
-		   settings that always result in calls to control_dc_dc(dev,0)
-		   a BNC interface should work if the enable pin
-		   (dc/dc converter) is on HCB1. It will be called AUI
-		   however. */
-
-		lp->adapter_cnf = 0;
-		i = readreg(dev, PP_LineCTL);
-		/* Preserve the setting of the HCB1 pin. */
-		if ((i & (HCB1 | HCB1_ENBL)) ==  (HCB1 | HCB1_ENBL))
-			lp->adapter_cnf |= A_CNF_DC_DC_POLARITY;
-		/* Save the sqelch bit */
-		if ((i & LOW_RX_SQUELCH) == LOW_RX_SQUELCH)
-			lp->adapter_cnf |= A_CNF_EXTND_10B_2 | A_CNF_LOW_RX_SQUELCH;
-		/* Check if the card is in 10Base-t only mode */
-		if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == 0)
-			lp->adapter_cnf |=  A_CNF_10B_T | A_CNF_MEDIA_10B_T;
-		/* Check if the card is in AUI only mode */
-		if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUI_ONLY)
-			lp->adapter_cnf |=  A_CNF_AUI | A_CNF_MEDIA_AUI;
-		/* Check if the card is in Auto mode. */
-		if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUTO_AUI_10BASET)
-			lp->adapter_cnf |=  A_CNF_AUI | A_CNF_10B_T |
-			A_CNF_MEDIA_AUI | A_CNF_MEDIA_10B_T | A_CNF_MEDIA_AUTO;
-
-		if (net_debug > 1)
-			printk(KERN_INFO "%s: PP_LineCTL=0x%x, adapter_cnf=0x%x\n",
-					dev->name, i, lp->adapter_cnf);
-
-		/* IRQ. Other chips already probe, see below. */
-		if (lp->chip_type == CS8900)
-			lp->isa_config = readreg(dev, PP_CS8900_ISAINT) & INT_NO_MASK;
-
-		printk( "[Cirrus EEPROM] ");
-	}
-
-        printk("\n");
-
-	/* First check to see if an EEPROM is attached. */
-
-	if ((readreg(dev, PP_SelfST) & EEPROM_PRESENT) == 0)
-		printk(KERN_WARNING "cs89x0: No EEPROM, relying on command line....\n");
-	else if (get_eeprom_data(dev, START_EEPROM_DATA,CHKSUM_LEN,eeprom_buff) < 0) {
-		printk(KERN_WARNING "\ncs89x0: EEPROM read failed, relying on command line.\n");
-        } else if (get_eeprom_cksum(START_EEPROM_DATA,CHKSUM_LEN,eeprom_buff) < 0) {
-		/* Check if the chip was able to read its own configuration starting
-		   at 0 in the EEPROM*/
-		if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) !=
-		    (EEPROM_OK|EEPROM_PRESENT))
-                	printk(KERN_WARNING "cs89x0: Extended EEPROM checksum bad and no Cirrus EEPROM, relying on command line\n");
-
-        } else {
-		/* This reads an extended EEPROM that is not documented
-		   in the CS8900 datasheet. */
-
-                /* get transmission control word  but keep the autonegotiation bits */
-                if (!lp->auto_neg_cnf) lp->auto_neg_cnf = eeprom_buff[AUTO_NEG_CNF_OFFSET/2];
-                /* Store adapter configuration */
-                if (!lp->adapter_cnf) lp->adapter_cnf = eeprom_buff[ADAPTER_CNF_OFFSET/2];
-                /* Store ISA configuration */
-                lp->isa_config = eeprom_buff[ISA_CNF_OFFSET/2];
-                dev->mem_start = eeprom_buff[PACKET_PAGE_OFFSET/2] << 8;
-
-                /* eeprom_buff has 32-bit ints, so we can't just memcpy it */
-                /* store the initial memory base address */
-                for (i = 0; i < ETH_ALEN/2; i++) {
-                        dev->dev_addr[i*2] = eeprom_buff[i];
-                        dev->dev_addr[i*2+1] = eeprom_buff[i] >> 8;
-                }
-		if (net_debug > 1)
-			printk(KERN_DEBUG "%s: new adapter_cnf: 0x%x\n",
-				dev->name, lp->adapter_cnf);
-        }
-
-        /* allow them to force multiple transceivers.  If they force multiple, autosense */
-        {
-		int count = 0;
-		if (lp->force & FORCE_RJ45)	{lp->adapter_cnf |= A_CNF_10B_T; count++; }
-		if (lp->force & FORCE_AUI) 	{lp->adapter_cnf |= A_CNF_AUI; count++; }
-		if (lp->force & FORCE_BNC)	{lp->adapter_cnf |= A_CNF_10B_2; count++; }
-		if (count > 1)			{lp->adapter_cnf |= A_CNF_MEDIA_AUTO; }
-		else if (lp->force & FORCE_RJ45){lp->adapter_cnf |= A_CNF_MEDIA_10B_T; }
-		else if (lp->force & FORCE_AUI)	{lp->adapter_cnf |= A_CNF_MEDIA_AUI; }
-		else if (lp->force & FORCE_BNC)	{lp->adapter_cnf |= A_CNF_MEDIA_10B_2; }
-        }
-
-	if (net_debug > 1)
-		printk(KERN_DEBUG "%s: after force 0x%x, adapter_cnf=0x%x\n",
-			dev->name, lp->force, lp->adapter_cnf);
-
-        /* FIXME: We don't let you set dc-dc polarity or low RX squelch from the command line: add it here */
-
-        /* FIXME: We don't let you set the IMM bit from the command line: add it to lp->auto_neg_cnf here */
-
-        /* FIXME: we don't set the Ethernet address on the command line.  Use
-           ifconfig IFACE hw ether AABBCCDDEEFF */
-
-	printk(KERN_INFO "cs89x0 media %s%s%s",
-	       (lp->adapter_cnf & A_CNF_10B_T)?"RJ-45,":"",
-	       (lp->adapter_cnf & A_CNF_AUI)?"AUI,":"",
-	       (lp->adapter_cnf & A_CNF_10B_2)?"BNC,":"");
-
-	lp->irq_map = 0xffff;
-
-	/* If this is a CS8900 then no pnp soft */
-	if (lp->chip_type != CS8900 &&
-	    /* Check if the ISA IRQ has been set  */
-		(i = readreg(dev, PP_CS8920_ISAINT) & 0xff,
-		 (i != 0 && i < CS8920_NO_INTS))) {
-		if (!dev->irq)
-			dev->irq = i;
-	} else {
-		i = lp->isa_config & INT_NO_MASK;
-		if (lp->chip_type == CS8900) {
-#ifdef CONFIG_CS89x0_NONISA_IRQ
-		        i = cs8900_irq_map[0];
-#else
-			/* Translate the IRQ using the IRQ mapping table. */
-			if (i >= ARRAY_SIZE(cs8900_irq_map))
-				printk("\ncs89x0: invalid ISA interrupt number %d\n", i);
-			else
-				i = cs8900_irq_map[i];
-
-			lp->irq_map = CS8900_IRQ_MAP; /* fixed IRQ map for CS8900 */
-		} else {
-			int irq_map_buff[IRQ_MAP_LEN/2];
-
-			if (get_eeprom_data(dev, IRQ_MAP_EEPROM_DATA,
-					    IRQ_MAP_LEN/2,
-					    irq_map_buff) >= 0) {
-				if ((irq_map_buff[0] & 0xff) == PNP_IRQ_FRMT)
-					lp->irq_map = (irq_map_buff[0]>>8) | (irq_map_buff[1] << 8);
-			}
-#endif
-		}
-		if (!dev->irq)
-			dev->irq = i;
-	}
-
-	printk(" IRQ %d", dev->irq);
-
-#if ALLOW_DMA
-	if (lp->use_dma) {
-		get_dma_channel(dev);
-		printk(", DMA %d", dev->dma);
-	}
-	else
-#endif
-	{
-		printk(", programmed I/O");
-	}
-
-	/* print the ethernet address. */
-	printk(", MAC %pM", dev->dev_addr);
-
-	dev->netdev_ops	= &net_ops;
-	dev->watchdog_timeo = HZ;
-
-	printk("\n");
-	if (net_debug)
-		printk("cs89x0_probe1() successful\n");
-
-	retval = register_netdev(dev);
-	if (retval)
-		goto out3;
-	return 0;
-out3:
-	writeword(dev->base_addr, ADD_PORT, PP_ChipID);
-out2:
-	release_region(ioaddr & ~3, NETCARD_IO_EXTENT);
-out1:
-	return retval;
-}
-
-
-/*********************************
- * This page contains DMA routines
-**********************************/
-
-#if ALLOW_DMA
-
-#define dma_page_eq(ptr1, ptr2) ((long)(ptr1)>>17 == (long)(ptr2)>>17)
-
-static void
-get_dma_channel(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-
-	if (lp->dma) {
-		dev->dma = lp->dma;
-		lp->isa_config |= ISA_RxDMA;
-	} else {
-		if ((lp->isa_config & ANY_ISA_DMA) == 0)
-			return;
-		dev->dma = lp->isa_config & DMA_NO_MASK;
-		if (lp->chip_type == CS8900)
-			dev->dma += 5;
-		if (dev->dma < 5 || dev->dma > 7) {
-			lp->isa_config &= ~ANY_ISA_DMA;
-			return;
-		}
-	}
-}
-
-static void
-write_dma(struct net_device *dev, int chip_type, int dma)
-{
-	struct net_local *lp = netdev_priv(dev);
-	if ((lp->isa_config & ANY_ISA_DMA) == 0)
-		return;
-	if (chip_type == CS8900) {
-		writereg(dev, PP_CS8900_ISADMA, dma-5);
-	} else {
-		writereg(dev, PP_CS8920_ISADMA, dma);
-	}
-}
-
-static void
-set_dma_cfg(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-
-	if (lp->use_dma) {
-		if ((lp->isa_config & ANY_ISA_DMA) == 0) {
-			if (net_debug > 3)
-				printk("set_dma_cfg(): no DMA\n");
-			return;
-		}
-		if (lp->isa_config & ISA_RxDMA) {
-			lp->curr_rx_cfg |= RX_DMA_ONLY;
-			if (net_debug > 3)
-				printk("set_dma_cfg(): RX_DMA_ONLY\n");
-		} else {
-			lp->curr_rx_cfg |= AUTO_RX_DMA;	/* not that we support it... */
-			if (net_debug > 3)
-				printk("set_dma_cfg(): AUTO_RX_DMA\n");
-		}
-	}
-}
-
-static int
-dma_bufcfg(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	if (lp->use_dma)
-		return (lp->isa_config & ANY_ISA_DMA)? RX_DMA_ENBL : 0;
-	else
-		return 0;
-}
-
-static int
-dma_busctl(struct net_device *dev)
-{
-	int retval = 0;
-	struct net_local *lp = netdev_priv(dev);
-	if (lp->use_dma) {
-		if (lp->isa_config & ANY_ISA_DMA)
-			retval |= RESET_RX_DMA; /* Reset the DMA pointer */
-		if (lp->isa_config & DMA_BURST)
-			retval |= DMA_BURST_MODE; /* Does ISA config specify DMA burst ? */
-		if (lp->dmasize == 64)
-			retval |= RX_DMA_SIZE_64K; /* did they ask for 64K? */
-		retval |= MEMORY_ON;	/* we need memory enabled to use DMA. */
-	}
-	return retval;
-}
-
-static void
-dma_rx(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	struct sk_buff *skb;
-	int status, length;
-	unsigned char *bp = lp->rx_dma_ptr;
-
-	status = bp[0] + (bp[1]<<8);
-	length = bp[2] + (bp[3]<<8);
-	bp += 4;
-	if (net_debug > 5) {
-		printk(	"%s: receiving DMA packet at %lx, status %x, length %x\n",
-			dev->name, (unsigned long)bp, status, length);
-	}
-	if ((status & RX_OK) == 0) {
-		count_rx_errors(status, dev);
-		goto skip_this_frame;
-	}
-
-	/* Malloc up new buffer. */
-	skb = dev_alloc_skb(length + 2);
-	if (skb == NULL) {
-		if (net_debug)	/* I don't think we want to do this to a stressed system */
-			printk("%s: Memory squeeze, dropping packet.\n", dev->name);
-		dev->stats.rx_dropped++;
-
-		/* AKPM: advance bp to the next frame */
-skip_this_frame:
-		bp += (length + 3) & ~3;
-		if (bp >= lp->end_dma_buff) bp -= lp->dmasize*1024;
-		lp->rx_dma_ptr = bp;
-		return;
-	}
-	skb_reserve(skb, 2);	/* longword align L3 header */
-
-	if (bp + length > lp->end_dma_buff) {
-		int semi_cnt = lp->end_dma_buff - bp;
-		memcpy(skb_put(skb,semi_cnt), bp, semi_cnt);
-		memcpy(skb_put(skb,length - semi_cnt), lp->dma_buff,
-		       length - semi_cnt);
-	} else {
-		memcpy(skb_put(skb,length), bp, length);
-	}
-	bp += (length + 3) & ~3;
-	if (bp >= lp->end_dma_buff) bp -= lp->dmasize*1024;
-	lp->rx_dma_ptr = bp;
-
-	if (net_debug > 3) {
-		printk(	"%s: received %d byte DMA packet of type %x\n",
-			dev->name, length,
-			(skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);
-	}
-        skb->protocol=eth_type_trans(skb,dev);
-	netif_rx(skb);
-	dev->stats.rx_packets++;
-	dev->stats.rx_bytes += length;
-}
-
-#endif	/* ALLOW_DMA */
-
-static void __init reset_chip(struct net_device *dev)
-{
-#if !defined(CONFIG_MACH_MX31ADS)
-#if !defined(CS89x0_NONISA_IRQ)
-	struct net_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-#endif /* CS89x0_NONISA_IRQ */
-	int reset_start_time;
-
-	writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
-
-	/* wait 30 ms */
-	msleep(30);
-
-#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);
-		outb(dev->irq, ioaddr + DATA_PORT);
-		outb(0,      ioaddr + DATA_PORT + 1);
-
-		writeword(ioaddr, ADD_PORT, PP_CS8920_ISAMemB);
-		outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT);
-		outb((dev->mem_start >> 8) & 0xff,   ioaddr + DATA_PORT + 1);
-	}
-#endif /* CS89x0_NONISA_IRQ */
-
-	/* Wait until the chip is reset */
-	reset_start_time = jiffies;
-	while( (readreg(dev, PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 2)
-		;
-#endif /* !CONFIG_MACH_MX31ADS */
-}
-
-
-static void
-control_dc_dc(struct net_device *dev, int on_not_off)
-{
-	struct net_local *lp = netdev_priv(dev);
-	unsigned int selfcontrol;
-	int timenow = jiffies;
-	/* control the DC to DC convertor in the SelfControl register.
-	   Note: This is hooked up to a general purpose pin, might not
-	   always be a DC to DC convertor. */
-
-	selfcontrol = HCB1_ENBL; /* Enable the HCB1 bit as an output */
-	if (((lp->adapter_cnf & A_CNF_DC_DC_POLARITY) != 0) ^ on_not_off)
-		selfcontrol |= HCB1;
-	else
-		selfcontrol &= ~HCB1;
-	writereg(dev, PP_SelfCTL, selfcontrol);
-
-	/* Wait for the DC/DC converter to power up - 500ms */
-	while (jiffies - timenow < HZ)
-		;
-}
-
-#define DETECTED_NONE  0
-#define DETECTED_RJ45H 1
-#define DETECTED_RJ45F 2
-#define DETECTED_AUI   3
-#define DETECTED_BNC   4
-
-static int
-detect_tp(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	int timenow = jiffies;
-	int fdx;
-
-	if (net_debug > 1) printk("%s: Attempting TP\n", dev->name);
-
-        /* If connected to another full duplex capable 10-Base-T card the link pulses
-           seem to be lost when the auto detect bit in the LineCTL is set.
-           To overcome this the auto detect bit will be cleared whilst testing the
-           10-Base-T interface.  This would not be necessary for the sparrow chip but
-           is simpler to do it anyway. */
-	writereg(dev, PP_LineCTL, lp->linectl &~ AUI_ONLY);
-	control_dc_dc(dev, 0);
-
-        /* Delay for the hardware to work out if the TP cable is present - 150ms */
-	for (timenow = jiffies; jiffies - timenow < 15; )
-                ;
-	if ((readreg(dev, PP_LineST) & LINK_OK) == 0)
-		return DETECTED_NONE;
-
-	if (lp->chip_type == CS8900) {
-                switch (lp->force & 0xf0) {
-#if 0
-                case FORCE_AUTO:
-			printk("%s: cs8900 doesn't autonegotiate\n",dev->name);
-                        return DETECTED_NONE;
-#endif
-		/* CS8900 doesn't support AUTO, change to HALF*/
-                case FORCE_AUTO:
-			lp->force &= ~FORCE_AUTO;
-                        lp->force |= FORCE_HALF;
-			break;
-		case FORCE_HALF:
-			break;
-                case FORCE_FULL:
-			writereg(dev, PP_TestCTL, readreg(dev, PP_TestCTL) | FDX_8900);
-			break;
-                }
-		fdx = readreg(dev, PP_TestCTL) & FDX_8900;
-	} else {
-		switch (lp->force & 0xf0) {
-		case FORCE_AUTO:
-			lp->auto_neg_cnf = AUTO_NEG_ENABLE;
-			break;
-		case FORCE_HALF:
-			lp->auto_neg_cnf = 0;
-			break;
-		case FORCE_FULL:
-			lp->auto_neg_cnf = RE_NEG_NOW | ALLOW_FDX;
-			break;
-                }
-
-		writereg(dev, PP_AutoNegCTL, lp->auto_neg_cnf & AUTO_NEG_MASK);
-
-		if ((lp->auto_neg_cnf & AUTO_NEG_BITS) == AUTO_NEG_ENABLE) {
-			printk(KERN_INFO "%s: negotiating duplex...\n",dev->name);
-			while (readreg(dev, PP_AutoNegST) & AUTO_NEG_BUSY) {
-				if (jiffies - timenow > 4000) {
-					printk(KERN_ERR "**** Full / half duplex auto-negotiation timed out ****\n");
-					break;
-				}
-			}
-		}
-		fdx = readreg(dev, PP_AutoNegST) & FDX_ACTIVE;
-	}
-	if (fdx)
-		return DETECTED_RJ45F;
-	else
-		return DETECTED_RJ45H;
-}
-
-/* send a test packet - return true if carrier bits are ok */
-static int
-send_test_pkt(struct net_device *dev)
-{
-	char test_packet[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
-				 0, 46, /* A 46 in network order */
-				 0, 0, /* DSAP=0 & SSAP=0 fields */
-				 0xf3, 0 /* Control (Test Req + P bit set) */ };
-	long timenow = jiffies;
-
-	writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_TX_ON);
-
-	memcpy(test_packet,          dev->dev_addr, ETH_ALEN);
-	memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN);
-
-        writeword(dev->base_addr, TX_CMD_PORT, TX_AFTER_ALL);
-        writeword(dev->base_addr, TX_LEN_PORT, ETH_ZLEN);
-
-	/* Test to see if the chip has allocated memory for the packet */
-	while (jiffies - timenow < 5)
-		if (readreg(dev, PP_BusST) & READY_FOR_TX_NOW)
-			break;
-	if (jiffies - timenow >= 5)
-		return 0;	/* this shouldn't happen */
-
-	/* Write the contents of the packet */
-	writewords(dev->base_addr, TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1);
-
-	if (net_debug > 1) printk("Sending test packet ");
-	/* wait a couple of jiffies for packet to be received */
-	for (timenow = jiffies; jiffies - timenow < 3; )
-                ;
-        if ((readreg(dev, PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {
-                if (net_debug > 1) printk("succeeded\n");
-                return 1;
-        }
-	if (net_debug > 1) printk("failed\n");
-	return 0;
-}
-
-
-static int
-detect_aui(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-
-	if (net_debug > 1) printk("%s: Attempting AUI\n", dev->name);
-	control_dc_dc(dev, 0);
-
-	writereg(dev, PP_LineCTL, (lp->linectl &~ AUTO_AUI_10BASET) | AUI_ONLY);
-
-	if (send_test_pkt(dev))
-		return DETECTED_AUI;
-	else
-		return DETECTED_NONE;
-}
-
-static int
-detect_bnc(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-
-	if (net_debug > 1) printk("%s: Attempting BNC\n", dev->name);
-	control_dc_dc(dev, 1);
-
-	writereg(dev, PP_LineCTL, (lp->linectl &~ AUTO_AUI_10BASET) | AUI_ONLY);
-
-	if (send_test_pkt(dev))
-		return DETECTED_BNC;
-	else
-		return DETECTED_NONE;
-}
-
-
-static void
-write_irq(struct net_device *dev, int chip_type, int irq)
-{
-	int i;
-
-	if (chip_type == CS8900) {
-		/* Search the mapping table for the corresponding IRQ pin. */
-		for (i = 0; i != ARRAY_SIZE(cs8900_irq_map); i++)
-			if (cs8900_irq_map[i] == irq)
-				break;
-		/* Not found */
-		if (i == ARRAY_SIZE(cs8900_irq_map))
-			i = 3;
-		writereg(dev, PP_CS8900_ISAINT, i);
-	} else {
-		writereg(dev, PP_CS8920_ISAINT, irq);
-	}
-}
-
-/* Open/initialize the board.  This is called (in the current kernel)
-   sometime after booting when the 'ifconfig' program is run.
-
-   This routine should set everything up anew at each open, even
-   registers that "should" only need to be set once at boot, so that
-   there is non-reboot way to recover if something goes wrong.
-   */
-
-/* AKPM: do we need to do any locking here? */
-
-static int
-net_open(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	int result = 0;
-	int i;
-	int ret;
-
-	if (dev->irq < 2) {
-		/* Allow interrupts to be generated by the chip */
-/* Cirrus' release had this: */
-#if 0
-		writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );
-#endif
-/* And 2.3.47 had this: */
-		writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
-
-		for (i = 2; i < CS8920_NO_INTS; i++) {
-			if ((1 << i) & lp->irq_map) {
-				if (request_irq(i, net_interrupt, 0, dev->name, dev) == 0) {
-					dev->irq = i;
-					write_irq(dev, lp->chip_type, i);
-					/* writereg(dev, PP_BufCFG, GENERATE_SW_INTERRUPT); */
-					break;
-				}
-			}
-		}
-
-		if (i >= CS8920_NO_INTS) {
-			writereg(dev, PP_BusCTL, 0);	/* disable interrupts. */
-			printk(KERN_ERR "cs89x0: can't get an interrupt\n");
-			ret = -EAGAIN;
-			goto bad_out;
-		}
-	}
-	else
-	{
-#ifndef CONFIG_CS89x0_NONISA_IRQ
-		if (((1 << dev->irq) & lp->irq_map) == 0) {
-			printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
-                               dev->name, dev->irq, lp->irq_map);
-			ret = -EAGAIN;
-			goto bad_out;
-		}
-#endif
-/* FIXME: Cirrus' release had this: */
-		writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );
-/* And 2.3.47 had this: */
-#if 0
-		writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
-#endif
-		write_irq(dev, lp->chip_type, dev->irq);
-		ret = request_irq(dev->irq, net_interrupt, 0, dev->name, dev);
-		if (ret) {
-			printk(KERN_ERR "cs89x0: request_irq(%d) failed\n", dev->irq);
-			goto bad_out;
-		}
-	}
-
-#if ALLOW_DMA
-	if (lp->use_dma) {
-		if (lp->isa_config & ANY_ISA_DMA) {
-			unsigned long flags;
-			lp->dma_buff = (unsigned char *)__get_dma_pages(GFP_KERNEL,
-							get_order(lp->dmasize * 1024));
-
-			if (!lp->dma_buff) {
-				printk(KERN_ERR "%s: cannot get %dK memory for DMA\n", dev->name, lp->dmasize);
-				goto release_irq;
-			}
-			if (net_debug > 1) {
-				printk(	"%s: dma %lx %lx\n",
-					dev->name,
-					(unsigned long)lp->dma_buff,
-					(unsigned long)isa_virt_to_bus(lp->dma_buff));
-			}
-			if ((unsigned long) lp->dma_buff >= MAX_DMA_ADDRESS ||
-			    !dma_page_eq(lp->dma_buff, lp->dma_buff+lp->dmasize*1024-1)) {
-				printk(KERN_ERR "%s: not usable as DMA buffer\n", dev->name);
-				goto release_irq;
-			}
-			memset(lp->dma_buff, 0, lp->dmasize * 1024);	/* Why? */
-			if (request_dma(dev->dma, dev->name)) {
-				printk(KERN_ERR "%s: cannot get dma channel %d\n", dev->name, dev->dma);
-				goto release_irq;
-			}
-			write_dma(dev, lp->chip_type, dev->dma);
-			lp->rx_dma_ptr = lp->dma_buff;
-			lp->end_dma_buff = lp->dma_buff + lp->dmasize*1024;
-			spin_lock_irqsave(&lp->lock, flags);
-			disable_dma(dev->dma);
-			clear_dma_ff(dev->dma);
-			set_dma_mode(dev->dma, DMA_RX_MODE); /* auto_init as well */
-			set_dma_addr(dev->dma, isa_virt_to_bus(lp->dma_buff));
-			set_dma_count(dev->dma, lp->dmasize*1024);
-			enable_dma(dev->dma);
-			spin_unlock_irqrestore(&lp->lock, flags);
-		}
-	}
-#endif	/* ALLOW_DMA */
-
-	/* set the Ethernet address */
-	for (i=0; i < ETH_ALEN/2; i++)
-		writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
-
-	/* while we're testing the interface, leave interrupts disabled */
-	writereg(dev, PP_BusCTL, MEMORY_ON);
-
-	/* Set the LineCTL quintuplet based on adapter configuration read from EEPROM */
-	if ((lp->adapter_cnf & A_CNF_EXTND_10B_2) && (lp->adapter_cnf & A_CNF_LOW_RX_SQUELCH))
-                lp->linectl = LOW_RX_SQUELCH;
-	else
-                lp->linectl = 0;
-
-        /* check to make sure that they have the "right" hardware available */
-	switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
-	case A_CNF_MEDIA_10B_T: result = lp->adapter_cnf & A_CNF_10B_T; break;
-	case A_CNF_MEDIA_AUI:   result = lp->adapter_cnf & A_CNF_AUI; break;
-	case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break;
-        default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2);
-        }
-        if (!result) {
-                printk(KERN_ERR "%s: EEPROM is configured for unavailable media\n", dev->name);
-release_dma:
-#if ALLOW_DMA
-		free_dma(dev->dma);
-release_irq:
-		release_dma_buff(lp);
-#endif
-                writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON));
-                free_irq(dev->irq, dev);
-		ret = -EAGAIN;
-		goto bad_out;
-	}
-
-        /* set the hardware to the configured choice */
-	switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
-	case A_CNF_MEDIA_10B_T:
-                result = detect_tp(dev);
-                if (result==DETECTED_NONE) {
-                        printk(KERN_WARNING "%s: 10Base-T (RJ-45) has no cable\n", dev->name);
-                        if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
-                                result = DETECTED_RJ45H; /* Yes! I don't care if I see a link pulse */
-                }
-		break;
-	case A_CNF_MEDIA_AUI:
-                result = detect_aui(dev);
-                if (result==DETECTED_NONE) {
-                        printk(KERN_WARNING "%s: 10Base-5 (AUI) has no cable\n", dev->name);
-                        if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
-                                result = DETECTED_AUI; /* Yes! I don't care if I see a carrrier */
-                }
-		break;
-	case A_CNF_MEDIA_10B_2:
-                result = detect_bnc(dev);
-                if (result==DETECTED_NONE) {
-                        printk(KERN_WARNING "%s: 10Base-2 (BNC) has no cable\n", dev->name);
-                        if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
-                                result = DETECTED_BNC; /* Yes! I don't care if I can xmit a packet */
-                }
-		break;
-	case A_CNF_MEDIA_AUTO:
-		writereg(dev, PP_LineCTL, lp->linectl | AUTO_AUI_10BASET);
-		if (lp->adapter_cnf & A_CNF_10B_T)
-			if ((result = detect_tp(dev)) != DETECTED_NONE)
-				break;
-		if (lp->adapter_cnf & A_CNF_AUI)
-			if ((result = detect_aui(dev)) != DETECTED_NONE)
-				break;
-		if (lp->adapter_cnf & A_CNF_10B_2)
-			if ((result = detect_bnc(dev)) != DETECTED_NONE)
-				break;
-		printk(KERN_ERR "%s: no media detected\n", dev->name);
-		goto release_dma;
-	}
-	switch(result) {
-	case DETECTED_NONE:
-		printk(KERN_ERR "%s: no network cable attached to configured media\n", dev->name);
-		goto release_dma;
-	case DETECTED_RJ45H:
-		printk(KERN_INFO "%s: using half-duplex 10Base-T (RJ-45)\n", dev->name);
-		break;
-	case DETECTED_RJ45F:
-		printk(KERN_INFO "%s: using full-duplex 10Base-T (RJ-45)\n", dev->name);
-		break;
-	case DETECTED_AUI:
-		printk(KERN_INFO "%s: using 10Base-5 (AUI)\n", dev->name);
-		break;
-	case DETECTED_BNC:
-		printk(KERN_INFO "%s: using 10Base-2 (BNC)\n", dev->name);
-		break;
-	}
-
-	/* Turn on both receive and transmit operations */
-	writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);
-
-	/* Receive only error free packets addressed to this card */
-	lp->rx_mode = 0;
-	writereg(dev, PP_RxCTL, DEF_RX_ACCEPT);
-
-	lp->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL;
-
-	if (lp->isa_config & STREAM_TRANSFER)
-		lp->curr_rx_cfg |= RX_STREAM_ENBL;
-#if ALLOW_DMA
-	set_dma_cfg(dev);
-#endif
-	writereg(dev, PP_RxCFG, lp->curr_rx_cfg);
-
-	writereg(dev, PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL |
-		TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);
-
-	writereg(dev, PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL |
-#if ALLOW_DMA
-		dma_bufcfg(dev) |
-#endif
-		TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL);
-
-	/* now that we've got our act together, enable everything */
-	writereg(dev, PP_BusCTL, ENABLE_IRQ
-		 | (dev->mem_start?MEMORY_ON : 0) /* turn memory on */
-#if ALLOW_DMA
-		 | dma_busctl(dev)
-#endif
-                 );
-        netif_start_queue(dev);
-	if (net_debug > 1)
-		printk("cs89x0: net_open() succeeded\n");
-	return 0;
-bad_out:
-	return ret;
-}
-
-static void net_timeout(struct net_device *dev)
-{
-	/* If we get here, some higher level has decided we are broken.
-	   There should really be a "kick me" function call instead. */
-	if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
-		   tx_done(dev) ? "IRQ conflict ?" : "network cable problem");
-	/* Try to restart the adaptor. */
-	netif_wake_queue(dev);
-}
-
-static netdev_tx_t net_send_packet(struct sk_buff *skb,struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	unsigned long flags;
-
-	if (net_debug > 3) {
-		printk("%s: sent %d byte packet of type %x\n",
-			dev->name, skb->len,
-			(skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);
-	}
-
-	/* keep the upload from being interrupted, since we
-                  ask the chip to start transmitting before the
-                  whole packet has been completely uploaded. */
-
-	spin_lock_irqsave(&lp->lock, flags);
-	netif_stop_queue(dev);
-
-	/* initiate a transmit sequence */
-	writeword(dev->base_addr, TX_CMD_PORT, lp->send_cmd);
-	writeword(dev->base_addr, TX_LEN_PORT, skb->len);
-
-	/* Test to see if the chip has allocated memory for the packet */
-	if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
-		/*
-		 * Gasp!  It hasn't.  But that shouldn't happen since
-		 * we're waiting for TxOk, so return 1 and requeue this packet.
-		 */
-
-		spin_unlock_irqrestore(&lp->lock, flags);
-		if (net_debug) printk("cs89x0: Tx buffer not free!\n");
-		return NETDEV_TX_BUSY;
-	}
-	/* Write the contents of the packet */
-	writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1);
-	spin_unlock_irqrestore(&lp->lock, flags);
-	dev->stats.tx_bytes += skb->len;
-	dev_kfree_skb (skb);
-
-	/*
-	 * We DO NOT call netif_wake_queue() here.
-	 * We also DO NOT call netif_start_queue().
-	 *
-	 * Either of these would cause another bottom half run through
-	 * net_send_packet() before this packet has fully gone out.  That causes
-	 * us to hit the "Gasp!" above and the send is rescheduled.  it runs like
-	 * a dog.  We just return and wait for the Tx completion interrupt handler
-	 * to restart the netdevice layer
-	 */
-
-	return NETDEV_TX_OK;
-}
-
-/* The typical workload of the driver:
-   Handle the network interface interrupts. */
-
-static irqreturn_t net_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct net_local *lp;
-	int ioaddr, status;
- 	int handled = 0;
-
-	ioaddr = dev->base_addr;
-	lp = netdev_priv(dev);
-
-	/* we MUST read all the events out of the ISQ, otherwise we'll never
-           get interrupted again.  As a consequence, we can't have any limit
-           on the number of times we loop in the interrupt handler.  The
-           hardware guarantees that eventually we'll run out of events.  Of
-           course, if you're on a slow machine, and packets are arriving
-           faster than you can read them off, you're screwed.  Hasta la
-           vista, baby!  */
-	while ((status = readword(dev->base_addr, ISQ_PORT))) {
-		if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status);
-		handled = 1;
-		switch(status & ISQ_EVENT_MASK) {
-		case ISQ_RECEIVER_EVENT:
-			/* Got a packet(s). */
-			net_rx(dev);
-			break;
-		case ISQ_TRANSMITTER_EVENT:
-			dev->stats.tx_packets++;
-			netif_wake_queue(dev);	/* Inform upper layers. */
-			if ((status & (	TX_OK |
-					TX_LOST_CRS |
-					TX_SQE_ERROR |
-					TX_LATE_COL |
-					TX_16_COL)) != TX_OK) {
-				if ((status & TX_OK) == 0)
-					dev->stats.tx_errors++;
-				if (status & TX_LOST_CRS)
-					dev->stats.tx_carrier_errors++;
-				if (status & TX_SQE_ERROR)
-					dev->stats.tx_heartbeat_errors++;
-				if (status & TX_LATE_COL)
-					dev->stats.tx_window_errors++;
-				if (status & TX_16_COL)
-					dev->stats.tx_aborted_errors++;
-			}
-			break;
-		case ISQ_BUFFER_EVENT:
-			if (status & READY_FOR_TX) {
-				/* we tried to transmit a packet earlier,
-                                   but inexplicably ran out of buffers.
-                                   That shouldn't happen since we only ever
-                                   load one packet.  Shrug.  Do the right
-                                   thing anyway. */
-				netif_wake_queue(dev);	/* Inform upper layers. */
-			}
-			if (status & TX_UNDERRUN) {
-				if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);
-                                lp->send_underrun++;
-                                if (lp->send_underrun == 3) lp->send_cmd = TX_AFTER_381;
-                                else if (lp->send_underrun == 6) lp->send_cmd = TX_AFTER_ALL;
-				/* transmit cycle is done, although
-				   frame wasn't transmitted - this
-				   avoids having to wait for the upper
-				   layers to timeout on us, in the
-				   event of a tx underrun */
-				netif_wake_queue(dev);	/* Inform upper layers. */
-                        }
-#if ALLOW_DMA
-			if (lp->use_dma && (status & RX_DMA)) {
-				int count = readreg(dev, PP_DmaFrameCnt);
-				while(count) {
-					if (net_debug > 5)
-						printk("%s: receiving %d DMA frames\n", dev->name, count);
-					if (net_debug > 2 && count >1)
-						printk("%s: receiving %d DMA frames\n", dev->name, count);
-					dma_rx(dev);
-					if (--count == 0)
-						count = readreg(dev, PP_DmaFrameCnt);
-					if (net_debug > 2 && count > 0)
-						printk("%s: continuing with %d DMA frames\n", dev->name, count);
-				}
-			}
-#endif
-			break;
-		case ISQ_RX_MISS_EVENT:
-			dev->stats.rx_missed_errors += (status >> 6);
-			break;
-		case ISQ_TX_COL_EVENT:
-			dev->stats.collisions += (status >> 6);
-			break;
-		}
-	}
-	return IRQ_RETVAL(handled);
-}
-
-static void
-count_rx_errors(int status, struct net_device *dev)
-{
-	dev->stats.rx_errors++;
-	if (status & RX_RUNT)
-		dev->stats.rx_length_errors++;
-	if (status & RX_EXTRA_DATA)
-		dev->stats.rx_length_errors++;
-	if ((status & RX_CRC_ERROR) && !(status & (RX_EXTRA_DATA|RX_RUNT)))
-		/* per str 172 */
-		dev->stats.rx_crc_errors++;
-	if (status & RX_DRIBBLE)
-		dev->stats.rx_frame_errors++;
-}
-
-/* We have a good packet(s), get it/them out of the buffers. */
-static void
-net_rx(struct net_device *dev)
-{
-	struct sk_buff *skb;
-	int status, length;
-
-	int ioaddr = dev->base_addr;
-	status = readword(ioaddr, RX_FRAME_PORT);
-	length = readword(ioaddr, RX_FRAME_PORT);
-
-	if ((status & RX_OK) == 0) {
-		count_rx_errors(status, dev);
-		return;
-	}
-
-	/* Malloc up new buffer. */
-	skb = dev_alloc_skb(length + 2);
-	if (skb == NULL) {
-#if 0		/* Again, this seems a cruel thing to do */
-		printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
-#endif
-		dev->stats.rx_dropped++;
-		return;
-	}
-	skb_reserve(skb, 2);	/* longword align L3 header */
-
-	readwords(ioaddr, RX_FRAME_PORT, skb_put(skb, length), length >> 1);
-	if (length & 1)
-		skb->data[length-1] = readword(ioaddr, RX_FRAME_PORT);
-
-	if (net_debug > 3) {
-		printk(	"%s: received %d byte packet of type %x\n",
-			dev->name, length,
-			(skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);
-	}
-
-        skb->protocol=eth_type_trans(skb,dev);
-	netif_rx(skb);
-	dev->stats.rx_packets++;
-	dev->stats.rx_bytes += length;
-}
-
-#if ALLOW_DMA
-static void release_dma_buff(struct net_local *lp)
-{
-	if (lp->dma_buff) {
-		free_pages((unsigned long)(lp->dma_buff), get_order(lp->dmasize * 1024));
-		lp->dma_buff = NULL;
-	}
-}
-#endif
-
-/* The inverse routine to net_open(). */
-static int
-net_close(struct net_device *dev)
-{
-#if ALLOW_DMA
-	struct net_local *lp = netdev_priv(dev);
-#endif
-
-	netif_stop_queue(dev);
-
-	writereg(dev, PP_RxCFG, 0);
-	writereg(dev, PP_TxCFG, 0);
-	writereg(dev, PP_BufCFG, 0);
-	writereg(dev, PP_BusCTL, 0);
-
-	free_irq(dev->irq, dev);
-
-#if ALLOW_DMA
-	if (lp->use_dma && lp->dma) {
-		free_dma(dev->dma);
-		release_dma_buff(lp);
-	}
-#endif
-
-	/* Update the statistics here. */
-	return 0;
-}
-
-/* Get the current statistics.	This may be called with the card open or
-   closed. */
-static struct net_device_stats *
-net_get_stats(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&lp->lock, flags);
-	/* Update the statistics from the device registers. */
-	dev->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
-	dev->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
-	spin_unlock_irqrestore(&lp->lock, flags);
-
-	return &dev->stats;
-}
-
-static void set_multicast_list(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&lp->lock, flags);
-	if(dev->flags&IFF_PROMISC)
-	{
-		lp->rx_mode = RX_ALL_ACCEPT;
-	}
-	else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev))
-	{
-		/* The multicast-accept list is initialized to accept-all, and we
-		   rely on higher-level filtering for now. */
-		lp->rx_mode = RX_MULTCAST_ACCEPT;
-	}
-	else
-		lp->rx_mode = 0;
-
-	writereg(dev, PP_RxCTL, DEF_RX_ACCEPT | lp->rx_mode);
-
-	/* in promiscuous mode, we accept errored packets, so we have to enable interrupts on them also */
-	writereg(dev, PP_RxCFG, lp->curr_rx_cfg |
-	     (lp->rx_mode == RX_ALL_ACCEPT? (RX_CRC_ERROR_ENBL|RX_RUNT_ENBL|RX_EXTRA_DATA_ENBL) : 0));
-	spin_unlock_irqrestore(&lp->lock, flags);
-}
-
-
-static int set_mac_address(struct net_device *dev, void *p)
-{
-	int i;
-	struct sockaddr *addr = p;
-
-	if (netif_running(dev))
-		return -EBUSY;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
-	if (net_debug)
-		printk("%s: Setting MAC address to %pM.\n",
-		       dev->name, dev->dev_addr);
-
-	/* set the Ethernet address */
-	for (i=0; i < ETH_ALEN/2; i++)
-		writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
-
-	return 0;
-}
-
-#ifdef MODULE
-
-static struct net_device *dev_cs89x0;
-
-/*
- * Support the 'debug' module parm even if we're compiled for non-debug to
- * avoid breaking someone's startup scripts
- */
-
-static int io;
-static int irq;
-static int debug;
-static char media[8];
-static int duplex=-1;
-
-static int use_dma;			/* These generate unused var warnings if ALLOW_DMA = 0 */
-static int dma;
-static int dmasize=16;			/* or 64 */
-
-module_param(io, int, 0);
-module_param(irq, int, 0);
-module_param(debug, int, 0);
-module_param_string(media, media, sizeof(media), 0);
-module_param(duplex, int, 0);
-module_param(dma , int, 0);
-module_param(dmasize , int, 0);
-module_param(use_dma , int, 0);
-MODULE_PARM_DESC(io, "cs89x0 I/O base address");
-MODULE_PARM_DESC(irq, "cs89x0 IRQ number");
-#if DEBUGGING
-MODULE_PARM_DESC(debug, "cs89x0 debug level (0-6)");
-#else
-MODULE_PARM_DESC(debug, "(ignored)");
-#endif
-MODULE_PARM_DESC(media, "Set cs89x0 adapter(s) media type(s) (rj45,bnc,aui)");
-/* No other value than -1 for duplex seems to be currently interpreted */
-MODULE_PARM_DESC(duplex, "(ignored)");
-#if ALLOW_DMA
-MODULE_PARM_DESC(dma , "cs89x0 ISA DMA channel; ignored if use_dma=0");
-MODULE_PARM_DESC(dmasize , "cs89x0 DMA size in kB (16,64); ignored if use_dma=0");
-MODULE_PARM_DESC(use_dma , "cs89x0 using DMA (0-1)");
-#else
-MODULE_PARM_DESC(dma , "(ignored)");
-MODULE_PARM_DESC(dmasize , "(ignored)");
-MODULE_PARM_DESC(use_dma , "(ignored)");
-#endif
-
-MODULE_AUTHOR("Mike Cruse, Russwll Nelson <nelson@crynwr.com>, Andrew Morton");
-MODULE_LICENSE("GPL");
-
-
-/*
-* media=t             - specify media type
-   or media=2
-   or media=aui
-   or medai=auto
-* duplex=0            - specify forced half/full/autonegotiate duplex
-* debug=#             - debug level
-
-
-* Default Chip Configuration:
-  * DMA Burst = enabled
-  * IOCHRDY Enabled = enabled
-    * UseSA = enabled
-    * CS8900 defaults to half-duplex if not specified on command-line
-    * CS8920 defaults to autoneg if not specified on command-line
-    * Use reset defaults for other config parameters
-
-* Assumptions:
-  * media type specified is supported (circuitry is present)
-  * if memory address is > 1MB, then required mem decode hw is present
-  * if 10B-2, then agent other than driver will enable DC/DC converter
-    (hw or software util)
-
-
-*/
-
-int __init init_module(void)
-{
-	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
-	struct net_local *lp;
-	int ret = 0;
-
-#if DEBUGGING
-	net_debug = debug;
-#else
-	debug = 0;
-#endif
-	if (!dev)
-		return -ENOMEM;
-
-	dev->irq = irq;
-	dev->base_addr = io;
-	lp = netdev_priv(dev);
-
-#if ALLOW_DMA
-	if (use_dma) {
-		lp->use_dma = use_dma;
-		lp->dma = dma;
-		lp->dmasize = dmasize;
-	}
-#endif
-
-	spin_lock_init(&lp->lock);
-
-        /* boy, they'd better get these right */
-        if (!strcmp(media, "rj45"))
-		lp->adapter_cnf = A_CNF_MEDIA_10B_T | A_CNF_10B_T;
-	else if (!strcmp(media, "aui"))
-		lp->adapter_cnf = A_CNF_MEDIA_AUI   | A_CNF_AUI;
-	else if (!strcmp(media, "bnc"))
-		lp->adapter_cnf = A_CNF_MEDIA_10B_2 | A_CNF_10B_2;
-	else
-		lp->adapter_cnf = A_CNF_MEDIA_10B_T | A_CNF_10B_T;
-
-        if (duplex==-1)
-		lp->auto_neg_cnf = AUTO_NEG_ENABLE;
-
-        if (io == 0) {
-                printk(KERN_ERR "cs89x0.c: Module autoprobing not allowed.\n");
-                printk(KERN_ERR "cs89x0.c: Append io=0xNNN\n");
-                ret = -EPERM;
-		goto out;
-        } else if (io <= 0x1ff) {
-		ret = -ENXIO;
-		goto out;
-	}
-
-#if ALLOW_DMA
-	if (use_dma && dmasize != 16 && dmasize != 64) {
-		printk(KERN_ERR "cs89x0.c: dma size must be either 16K or 64K, not %dK\n", dmasize);
-		ret = -EPERM;
-		goto out;
-	}
-#endif
-	ret = cs89x0_probe1(dev, io, 1);
-	if (ret)
-		goto out;
-
-	dev_cs89x0 = dev;
-	return 0;
-out:
-	free_netdev(dev);
-	return ret;
-}
-
-void __exit
-cleanup_module(void)
-{
-	unregister_netdev(dev_cs89x0);
-	writeword(dev_cs89x0->base_addr, ADD_PORT, PP_ChipID);
-	release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT);
-	free_netdev(dev_cs89x0);
-}
-#endif /* MODULE */
-
-/*
- * Local variables:
- *  version-control: t
- *  kept-new-versions: 5
- *  c-indent-level: 8
- *  tab-width: 8
- * End:
- *
- */
diff -druN linux-libre-3.1-gnu/drivers/net/cs89x0.h linux-libre-3.2-gnu/drivers/net/cs89x0.h
--- linux-libre-3.1-gnu/drivers/net/cs89x0.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cs89x0.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,465 +0,0 @@
-/*  Copyright, 1988-1992, Russell Nelson, Crynwr Software
-
-   This program is free software; 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 1.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You 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 PP_ChipID 0x0000	/* offset   0h -> Corp -ID              */
-				/* offset   2h -> Model/Product Number  */
-				/* offset   3h -> Chip Revision Number  */
-
-#define PP_ISAIOB 0x0020	/*  IO base address */
-#define PP_CS8900_ISAINT 0x0022	/*  ISA interrupt select */
-#define PP_CS8920_ISAINT 0x0370	/*  ISA interrupt select */
-#define PP_CS8900_ISADMA 0x0024	/*  ISA Rec DMA channel */
-#define PP_CS8920_ISADMA 0x0374	/*  ISA Rec DMA channel */
-#define PP_ISASOF 0x0026	/*  ISA DMA offset */
-#define PP_DmaFrameCnt 0x0028	/*  ISA DMA Frame count */
-#define PP_DmaByteCnt 0x002A	/*  ISA DMA Byte count */
-#define PP_CS8900_ISAMemB 0x002C	/*  Memory base */
-#define PP_CS8920_ISAMemB 0x0348 /*  */
-
-#define PP_ISABootBase 0x0030	/*  Boot Prom base  */
-#define PP_ISABootMask 0x0034	/*  Boot Prom Mask */
-
-/* EEPROM data and command registers */
-#define PP_EECMD 0x0040		/*  NVR Interface Command register */
-#define PP_EEData 0x0042	/*  NVR Interface Data Register */
-#define PP_DebugReg 0x0044	/*  Debug Register */
-
-#define PP_RxCFG 0x0102		/*  Rx Bus config */
-#define PP_RxCTL 0x0104		/*  Receive Control Register */
-#define PP_TxCFG 0x0106		/*  Transmit Config Register */
-#define PP_TxCMD 0x0108		/*  Transmit Command Register */
-#define PP_BufCFG 0x010A	/*  Bus configuration Register */
-#define PP_LineCTL 0x0112	/*  Line Config Register */
-#define PP_SelfCTL 0x0114	/*  Self Command Register */
-#define PP_BusCTL 0x0116	/*  ISA bus control Register */
-#define PP_TestCTL 0x0118	/*  Test Register */
-#define PP_AutoNegCTL 0x011C	/*  Auto Negotiation Ctrl */
-
-#define PP_ISQ 0x0120		/*  Interrupt Status */
-#define PP_RxEvent 0x0124	/*  Rx Event Register */
-#define PP_TxEvent 0x0128	/*  Tx Event Register */
-#define PP_BufEvent 0x012C	/*  Bus Event Register */
-#define PP_RxMiss 0x0130	/*  Receive Miss Count */
-#define PP_TxCol 0x0132		/*  Transmit Collision Count */
-#define PP_LineST 0x0134	/*  Line State Register */
-#define PP_SelfST 0x0136	/*  Self State register */
-#define PP_BusST 0x0138		/*  Bus Status */
-#define PP_TDR 0x013C		/*  Time Domain Reflectometry */
-#define PP_AutoNegST 0x013E	/*  Auto Neg Status */
-#define PP_TxCommand 0x0144	/*  Tx Command */
-#define PP_TxLength 0x0146	/*  Tx Length */
-#define PP_LAF 0x0150		/*  Hash Table */
-#define PP_IA 0x0158		/*  Physical Address Register */
-
-#define PP_RxStatus 0x0400	/*  Receive start of frame */
-#define PP_RxLength 0x0402	/*  Receive Length of frame */
-#define PP_RxFrame 0x0404	/*  Receive frame pointer */
-#define PP_TxFrame 0x0A00	/*  Transmit frame pointer */
-
-/*  Primary I/O Base Address. If no I/O base is supplied by the user, then this */
-/*  can be used as the default I/O base to access the PacketPage Area. */
-#define DEFAULTIOBASE 0x0300
-#define FIRST_IO 0x020C		/*  First I/O port to check */
-#define LAST_IO 0x037C		/*  Last I/O port to check (+10h) */
-#define ADD_MASK 0x3000		/*  Mask it use of the ADD_PORT register */
-#define ADD_SIG 0x3000		/*  Expected ID signature */
-
-/* On Macs, we only need use the ISA I/O stuff until we do MEMORY_ON */
-#ifdef CONFIG_MAC
-#define LCSLOTBASE 0xfee00000
-#define MMIOBASE 0x40000
-#endif
-
-#define CHIP_EISA_ID_SIG 0x630E   /*  Product ID Code for Crystal Chip (CS8900 spec 4.3) */
-#define CHIP_EISA_ID_SIG_STR "0x630E"
-
-#ifdef IBMEIPKT
-#define EISA_ID_SIG 0x4D24	/*  IBM */
-#define PART_NO_SIG 0x1010	/*  IBM */
-#define MONGOOSE_BIT 0x0000	/*  IBM */
-#else
-#define EISA_ID_SIG 0x630E	/*  PnP Vendor ID (same as chip id for Crystal board) */
-#define PART_NO_SIG 0x4000	/*  ID code CS8920 board (PnP Vendor Product code) */
-#define MONGOOSE_BIT 0x2000	/*  PART_NO_SIG + MONGOOSE_BUT => ID of mongoose */
-#endif
-
-#define PRODUCT_ID_ADD 0x0002   /*  Address of product ID */
-
-/*  Mask to find out the types of  registers */
-#define REG_TYPE_MASK 0x001F
-
-/*  Eeprom Commands */
-#define ERSE_WR_ENBL 0x00F0
-#define ERSE_WR_DISABLE 0x0000
-
-/*  Defines Control/Config register quintuplet numbers */
-#define RX_BUF_CFG 0x0003
-#define RX_CONTROL 0x0005
-#define TX_CFG 0x0007
-#define TX_COMMAND 0x0009
-#define BUF_CFG 0x000B
-#define LINE_CONTROL 0x0013
-#define SELF_CONTROL 0x0015
-#define BUS_CONTROL 0x0017
-#define TEST_CONTROL 0x0019
-
-/*  Defines Status/Count registers quintuplet numbers */
-#define RX_EVENT 0x0004
-#define TX_EVENT 0x0008
-#define BUF_EVENT 0x000C
-#define RX_MISS_COUNT 0x0010
-#define TX_COL_COUNT 0x0012
-#define LINE_STATUS 0x0014
-#define SELF_STATUS 0x0016
-#define BUS_STATUS 0x0018
-#define TDR 0x001C
-
-/* PP_RxCFG - Receive  Configuration and Interrupt Mask bit definition -  Read/write */
-#define SKIP_1 0x0040
-#define RX_STREAM_ENBL 0x0080
-#define RX_OK_ENBL 0x0100
-#define RX_DMA_ONLY 0x0200
-#define AUTO_RX_DMA 0x0400
-#define BUFFER_CRC 0x0800
-#define RX_CRC_ERROR_ENBL 0x1000
-#define RX_RUNT_ENBL 0x2000
-#define RX_EXTRA_DATA_ENBL 0x4000
-
-/* PP_RxCTL - Receive Control bit definition - Read/write */
-#define RX_IA_HASH_ACCEPT 0x0040
-#define RX_PROM_ACCEPT 0x0080
-#define RX_OK_ACCEPT 0x0100
-#define RX_MULTCAST_ACCEPT 0x0200
-#define RX_IA_ACCEPT 0x0400
-#define RX_BROADCAST_ACCEPT 0x0800
-#define RX_BAD_CRC_ACCEPT 0x1000
-#define RX_RUNT_ACCEPT 0x2000
-#define RX_EXTRA_DATA_ACCEPT 0x4000
-#define RX_ALL_ACCEPT (RX_PROM_ACCEPT|RX_BAD_CRC_ACCEPT|RX_RUNT_ACCEPT|RX_EXTRA_DATA_ACCEPT)
-/*  Default receive mode - individually addressed, broadcast, and error free */
-#define DEF_RX_ACCEPT (RX_IA_ACCEPT | RX_BROADCAST_ACCEPT | RX_OK_ACCEPT)
-
-/* PP_TxCFG - Transmit Configuration Interrupt Mask bit definition - Read/write */
-#define TX_LOST_CRS_ENBL 0x0040
-#define TX_SQE_ERROR_ENBL 0x0080
-#define TX_OK_ENBL 0x0100
-#define TX_LATE_COL_ENBL 0x0200
-#define TX_JBR_ENBL 0x0400
-#define TX_ANY_COL_ENBL 0x0800
-#define TX_16_COL_ENBL 0x8000
-
-/* PP_TxCMD - Transmit Command bit definition - Read-only */
-#define TX_START_4_BYTES 0x0000
-#define TX_START_64_BYTES 0x0040
-#define TX_START_128_BYTES 0x0080
-#define TX_START_ALL_BYTES 0x00C0
-#define TX_FORCE 0x0100
-#define TX_ONE_COL 0x0200
-#define TX_TWO_PART_DEFF_DISABLE 0x0400
-#define TX_NO_CRC 0x1000
-#define TX_RUNT 0x2000
-
-/* PP_BufCFG - Buffer Configuration Interrupt Mask bit definition - Read/write */
-#define GENERATE_SW_INTERRUPT 0x0040
-#define RX_DMA_ENBL 0x0080
-#define READY_FOR_TX_ENBL 0x0100
-#define TX_UNDERRUN_ENBL 0x0200
-#define RX_MISS_ENBL 0x0400
-#define RX_128_BYTE_ENBL 0x0800
-#define TX_COL_COUNT_OVRFLOW_ENBL 0x1000
-#define RX_MISS_COUNT_OVRFLOW_ENBL 0x2000
-#define RX_DEST_MATCH_ENBL 0x8000
-
-/* PP_LineCTL - Line Control bit definition - Read/write */
-#define SERIAL_RX_ON 0x0040
-#define SERIAL_TX_ON 0x0080
-#define AUI_ONLY 0x0100
-#define AUTO_AUI_10BASET 0x0200
-#define MODIFIED_BACKOFF 0x0800
-#define NO_AUTO_POLARITY 0x1000
-#define TWO_PART_DEFDIS 0x2000
-#define LOW_RX_SQUELCH 0x4000
-
-/* PP_SelfCTL - Software Self Control bit definition - Read/write */
-#define POWER_ON_RESET 0x0040
-#define SW_STOP 0x0100
-#define SLEEP_ON 0x0200
-#define AUTO_WAKEUP 0x0400
-#define HCB0_ENBL 0x1000
-#define HCB1_ENBL 0x2000
-#define HCB0 0x4000
-#define HCB1 0x8000
-
-/* PP_BusCTL - ISA Bus Control bit definition - Read/write */
-#define RESET_RX_DMA 0x0040
-#define MEMORY_ON 0x0400
-#define DMA_BURST_MODE 0x0800
-#define IO_CHANNEL_READY_ON 0x1000
-#define RX_DMA_SIZE_64K 0x2000
-#define ENABLE_IRQ 0x8000
-
-/* PP_TestCTL - Test Control bit definition - Read/write */
-#define LINK_OFF 0x0080
-#define ENDEC_LOOPBACK 0x0200
-#define AUI_LOOPBACK 0x0400
-#define BACKOFF_OFF 0x0800
-#define FDX_8900 0x4000
-#define FAST_TEST 0x8000
-
-/* PP_RxEvent - Receive Event Bit definition - Read-only */
-#define RX_IA_HASHED 0x0040
-#define RX_DRIBBLE 0x0080
-#define RX_OK 0x0100
-#define RX_HASHED 0x0200
-#define RX_IA 0x0400
-#define RX_BROADCAST 0x0800
-#define RX_CRC_ERROR 0x1000
-#define RX_RUNT 0x2000
-#define RX_EXTRA_DATA 0x4000
-
-#define HASH_INDEX_MASK 0x0FC00
-
-/* PP_TxEvent - Transmit Event Bit definition - Read-only */
-#define TX_LOST_CRS 0x0040
-#define TX_SQE_ERROR 0x0080
-#define TX_OK 0x0100
-#define TX_LATE_COL 0x0200
-#define TX_JBR 0x0400
-#define TX_16_COL 0x8000
-#define TX_SEND_OK_BITS (TX_OK|TX_LOST_CRS)
-#define TX_COL_COUNT_MASK 0x7800
-
-/* PP_BufEvent - Buffer Event Bit definition - Read-only */
-#define SW_INTERRUPT 0x0040
-#define RX_DMA 0x0080
-#define READY_FOR_TX 0x0100
-#define TX_UNDERRUN 0x0200
-#define RX_MISS 0x0400
-#define RX_128_BYTE 0x0800
-#define TX_COL_OVRFLW 0x1000
-#define RX_MISS_OVRFLW 0x2000
-#define RX_DEST_MATCH 0x8000
-
-/* PP_LineST - Ethernet Line Status bit definition - Read-only */
-#define LINK_OK 0x0080
-#define AUI_ON 0x0100
-#define TENBASET_ON 0x0200
-#define POLARITY_OK 0x1000
-#define CRS_OK 0x4000
-
-/* PP_SelfST - Chip Software Status bit definition */
-#define ACTIVE_33V 0x0040
-#define INIT_DONE 0x0080
-#define SI_BUSY 0x0100
-#define EEPROM_PRESENT 0x0200
-#define EEPROM_OK 0x0400
-#define EL_PRESENT 0x0800
-#define EE_SIZE_64 0x1000
-
-/* PP_BusST - ISA Bus Status bit definition */
-#define TX_BID_ERROR 0x0080
-#define READY_FOR_TX_NOW 0x0100
-
-/* PP_AutoNegCTL - Auto Negotiation Control bit definition */
-#define RE_NEG_NOW 0x0040
-#define ALLOW_FDX 0x0080
-#define AUTO_NEG_ENABLE 0x0100
-#define NLP_ENABLE 0x0200
-#define FORCE_FDX 0x8000
-#define AUTO_NEG_BITS (FORCE_FDX|NLP_ENABLE|AUTO_NEG_ENABLE)
-#define AUTO_NEG_MASK (FORCE_FDX|NLP_ENABLE|AUTO_NEG_ENABLE|ALLOW_FDX|RE_NEG_NOW)
-
-/* PP_AutoNegST - Auto Negotiation Status bit definition */
-#define AUTO_NEG_BUSY 0x0080
-#define FLP_LINK 0x0100
-#define FLP_LINK_GOOD 0x0800
-#define LINK_FAULT 0x1000
-#define HDX_ACTIVE 0x4000
-#define FDX_ACTIVE 0x8000
-
-/*  The following block defines the ISQ event types */
-#define ISQ_RECEIVER_EVENT 0x04
-#define ISQ_TRANSMITTER_EVENT 0x08
-#define ISQ_BUFFER_EVENT 0x0c
-#define ISQ_RX_MISS_EVENT 0x10
-#define ISQ_TX_COL_EVENT 0x12
-
-#define ISQ_EVENT_MASK 0x003F   /*  ISQ mask to find out type of event */
-#define ISQ_HIST 16		/*  small history buffer */
-#define AUTOINCREMENT 0x8000	/*  Bit mask to set bit-15 for autoincrement */
-
-#define TXRXBUFSIZE 0x0600
-#define RXDMABUFSIZE 0x8000
-#define RXDMASIZE 0x4000
-#define TXRX_LENGTH_MASK 0x07FF
-
-/*  rx options bits */
-#define RCV_WITH_RXON	1       /*  Set SerRx ON */
-#define RCV_COUNTS	2       /*  Use Framecnt1 */
-#define RCV_PONG	4       /*  Pong respondent */
-#define RCV_DONG	8       /*  Dong operation */
-#define RCV_POLLING	0x10	/*  Poll RxEvent */
-#define RCV_ISQ		0x20	/*  Use ISQ, int */
-#define RCV_AUTO_DMA	0x100	/*  Set AutoRxDMAE */
-#define RCV_DMA		0x200	/*  Set RxDMA only */
-#define RCV_DMA_ALL	0x400	/*  Copy all DMA'ed */
-#define RCV_FIXED_DATA	0x800	/*  Every frame same */
-#define RCV_IO		0x1000	/*  Use ISA IO only */
-#define RCV_MEMORY	0x2000	/*  Use ISA Memory */
-
-#define RAM_SIZE	0x1000       /*  The card has 4k bytes or RAM */
-#define PKT_START PP_TxFrame  /*  Start of packet RAM */
-
-#define RX_FRAME_PORT	0x0000
-#define TX_FRAME_PORT RX_FRAME_PORT
-#define TX_CMD_PORT	0x0004
-#define TX_NOW		0x0000       /*  Tx packet after   5 bytes copied */
-#define TX_AFTER_381	0x0040       /*  Tx packet after 381 bytes copied */
-#define TX_AFTER_ALL	0x00c0       /*  Tx packet after all bytes copied */
-#define TX_LEN_PORT	0x0006
-#define ISQ_PORT	0x0008
-#define ADD_PORT	0x000A
-#define DATA_PORT	0x000C
-
-#define EEPROM_WRITE_EN		0x00F0
-#define EEPROM_WRITE_DIS	0x0000
-#define EEPROM_WRITE_CMD	0x0100
-#define EEPROM_READ_CMD		0x0200
-
-/*  Receive Header */
-/*  Description of header of each packet in receive area of memory */
-#define RBUF_EVENT_LOW	0   /*  Low byte of RxEvent - status of received frame */
-#define RBUF_EVENT_HIGH	1   /*  High byte of RxEvent - status of received frame */
-#define RBUF_LEN_LOW	2   /*  Length of received data - low byte */
-#define RBUF_LEN_HI	3   /*  Length of received data - high byte */
-#define RBUF_HEAD_LEN	4   /*  Length of this header */
-
-#define CHIP_READ 0x1   /*  Used to mark state of the repins code (chip or dma) */
-#define DMA_READ 0x2   /*  Used to mark state of the repins code (chip or dma) */
-
-/*  for bios scan */
-/*  */
-#ifdef CSDEBUG
-/*  use these values for debugging bios scan */
-#define BIOS_START_SEG 0x00000
-#define BIOS_OFFSET_INC 0x0010
-#else
-#define BIOS_START_SEG 0x0c000
-#define BIOS_OFFSET_INC 0x0200
-#endif
-
-#define BIOS_LAST_OFFSET 0x0fc00
-
-/*  Byte offsets into the EEPROM configuration buffer */
-#define ISA_CNF_OFFSET 0x6
-#define TX_CTL_OFFSET (ISA_CNF_OFFSET + 8)			/*  8900 eeprom */
-#define AUTO_NEG_CNF_OFFSET (ISA_CNF_OFFSET + 8)		/*  8920 eeprom */
-
-  /*  the assumption here is that the bits in the eeprom are generally  */
-  /*  in the same position as those in the autonegctl register. */
-  /*  Of course the IMM bit is not in that register so it must be  */
-  /*  masked out */
-#define EE_FORCE_FDX  0x8000
-#define EE_NLP_ENABLE 0x0200
-#define EE_AUTO_NEG_ENABLE 0x0100
-#define EE_ALLOW_FDX 0x0080
-#define EE_AUTO_NEG_CNF_MASK (EE_FORCE_FDX|EE_NLP_ENABLE|EE_AUTO_NEG_ENABLE|EE_ALLOW_FDX)
-
-#define IMM_BIT 0x0040		/*  ignore missing media	 */
-
-#define ADAPTER_CNF_OFFSET (AUTO_NEG_CNF_OFFSET + 2)
-#define A_CNF_10B_T 0x0001
-#define A_CNF_AUI 0x0002
-#define A_CNF_10B_2 0x0004
-#define A_CNF_MEDIA_TYPE 0x0070
-#define A_CNF_MEDIA_AUTO 0x0070
-#define A_CNF_MEDIA_10B_T 0x0020
-#define A_CNF_MEDIA_AUI 0x0040
-#define A_CNF_MEDIA_10B_2 0x0010
-#define A_CNF_DC_DC_POLARITY 0x0080
-#define A_CNF_NO_AUTO_POLARITY 0x2000
-#define A_CNF_LOW_RX_SQUELCH 0x4000
-#define A_CNF_EXTND_10B_2 0x8000
-
-#define PACKET_PAGE_OFFSET 0x8
-
-/*  Bit definitions for the ISA configuration word from the EEPROM */
-#define INT_NO_MASK 0x000F
-#define DMA_NO_MASK 0x0070
-#define ISA_DMA_SIZE 0x0200
-#define ISA_AUTO_RxDMA 0x0400
-#define ISA_RxDMA 0x0800
-#define DMA_BURST 0x1000
-#define STREAM_TRANSFER 0x2000
-#define ANY_ISA_DMA (ISA_AUTO_RxDMA | ISA_RxDMA)
-
-/*  DMA controller registers */
-#define DMA_BASE 0x00     /*  DMA controller base */
-#define DMA_BASE_2 0x0C0    /*  DMA controller base */
-
-#define DMA_STAT 0x0D0    /*  DMA controller status register */
-#define DMA_MASK 0x0D4    /*  DMA controller mask register */
-#define DMA_MODE 0x0D6    /*  DMA controller mode register */
-#define DMA_RESETFF 0x0D8    /*  DMA controller first/last flip flop */
-
-/*  DMA data */
-#define DMA_DISABLE 0x04     /*  Disable channel n */
-#define DMA_ENABLE 0x00     /*  Enable channel n */
-/*  Demand transfers, incr. address, auto init, writes, ch. n */
-#define DMA_RX_MODE 0x14
-/*  Demand transfers, incr. address, auto init, reads, ch. n */
-#define DMA_TX_MODE 0x18
-
-#define DMA_SIZE (16*1024) /*  Size of dma buffer - 16k */
-
-#define CS8900 0x0000
-#define CS8920 0x4000
-#define CS8920M 0x6000
-#define REVISON_BITS 0x1F00
-#define EEVER_NUMBER 0x12
-#define CHKSUM_LEN 0x14
-#define CHKSUM_VAL 0x0000
-#define START_EEPROM_DATA 0x001c /*  Offset into eeprom for start of data */
-#define IRQ_MAP_EEPROM_DATA 0x0046 /*  Offset into eeprom for the IRQ map */
-#define IRQ_MAP_LEN 0x0004 /*  No of bytes to read for the IRQ map */
-#define PNP_IRQ_FRMT 0x0022 /*  PNP small item IRQ format */
-#define CS8900_IRQ_MAP 0x1c20 /*  This IRQ map is fixed */
-
-#define CS8920_NO_INTS 0x0F   /*  Max CS8920 interrupt select # */
-
-#define PNP_ADD_PORT 0x0279
-#define PNP_WRITE_PORT 0x0A79
-
-#define GET_PNP_ISA_STRUCT 0x40
-#define PNP_ISA_STRUCT_LEN 0x06
-#define PNP_CSN_CNT_OFF 0x01
-#define PNP_RD_PORT_OFF 0x02
-#define PNP_FUNCTION_OK 0x00
-#define PNP_WAKE 0x03
-#define PNP_RSRC_DATA 0x04
-#define PNP_RSRC_READY 0x01
-#define PNP_STATUS 0x05
-#define PNP_ACTIVATE 0x30
-#define PNP_CNF_IO_H 0x60
-#define PNP_CNF_IO_L 0x61
-#define PNP_CNF_INT 0x70
-#define PNP_CNF_DMA 0x74
-#define PNP_CNF_MEM 0x48
-
-#define BIT0 1
-#define BIT15 0x8000
-
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/adapter.h linux-libre-3.2-gnu/drivers/net/cxgb3/adapter.h
--- linux-libre-3.1-gnu/drivers/net/cxgb3/adapter.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/adapter.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,334 +0,0 @@
-/*
- * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* This file should not be included directly.  Include common.h instead. */
-
-#ifndef __T3_ADAPTER_H__
-#define __T3_ADAPTER_H__
-
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/cache.h>
-#include <linux/mutex.h>
-#include <linux/bitops.h>
-#include "t3cdev.h"
-#include <asm/io.h>
-
-struct adapter;
-struct sge_qset;
-struct port_info;
-
-enum mac_idx_types {
-	LAN_MAC_IDX	= 0,
-	SAN_MAC_IDX,
-
-	MAX_MAC_IDX
-};
-
-struct iscsi_config {
-	__u8	mac_addr[ETH_ALEN];
-	__u32	flags;
-	int (*send)(struct port_info *pi, struct sk_buff **skb);
-	int (*recv)(struct port_info *pi, struct sk_buff *skb);
-};
-
-struct port_info {
-	struct adapter *adapter;
-	struct sge_qset *qs;
-	u8 port_id;
-	u8 nqsets;
-	u8 first_qset;
-	struct cphy phy;
-	struct cmac mac;
-	struct link_config link_config;
-	struct net_device_stats netstats;
-	int activity;
-	__be32 iscsi_ipv4addr;
-	struct iscsi_config iscsic;
-
-	int link_fault; /* link fault was detected */
-};
-
-enum {				/* adapter flags */
-	FULL_INIT_DONE = (1 << 0),
-	USING_MSI = (1 << 1),
-	USING_MSIX = (1 << 2),
-	QUEUES_BOUND = (1 << 3),
-	TP_PARITY_INIT = (1 << 4),
-	NAPI_INIT = (1 << 5),
-};
-
-struct fl_pg_chunk {
-	struct page *page;
-	void *va;
-	unsigned int offset;
-	unsigned long *p_cnt;
-	dma_addr_t mapping;
-};
-
-struct rx_desc;
-struct rx_sw_desc;
-
-struct sge_fl {                     /* SGE per free-buffer list state */
-	unsigned int buf_size;      /* size of each Rx buffer */
-	unsigned int credits;       /* # of available Rx buffers */
-	unsigned int pend_cred;     /* new buffers since last FL DB ring */
-	unsigned int size;          /* capacity of free list */
-	unsigned int cidx;          /* consumer index */
-	unsigned int pidx;          /* producer index */
-	unsigned int gen;           /* free list generation */
-	struct fl_pg_chunk pg_chunk;/* page chunk cache */
-	unsigned int use_pages;     /* whether FL uses pages or sk_buffs */
-	unsigned int order;	    /* order of page allocations */
-	unsigned int alloc_size;    /* size of allocated buffer */
-	struct rx_desc *desc;       /* address of HW Rx descriptor ring */
-	struct rx_sw_desc *sdesc;   /* address of SW Rx descriptor ring */
-	dma_addr_t   phys_addr;     /* physical address of HW ring start */
-	unsigned int cntxt_id;      /* SGE context id for the free list */
-	unsigned long empty;        /* # of times queue ran out of buffers */
-	unsigned long alloc_failed; /* # of times buffer allocation failed */
-};
-
-/*
- * Bundle size for grouping offload RX packets for delivery to the stack.
- * Don't make this too big as we do prefetch on each packet in a bundle.
- */
-# define RX_BUNDLE_SIZE 8
-
-struct rsp_desc;
-
-struct sge_rspq {		/* state for an SGE response queue */
-	unsigned int credits;	/* # of pending response credits */
-	unsigned int size;	/* capacity of response queue */
-	unsigned int cidx;	/* consumer index */
-	unsigned int gen;	/* current generation bit */
-	unsigned int polling;	/* is the queue serviced through NAPI? */
-	unsigned int holdoff_tmr;	/* interrupt holdoff timer in 100ns */
-	unsigned int next_holdoff;	/* holdoff time for next interrupt */
-	unsigned int rx_recycle_buf; /* whether recycling occurred
-					within current sop-eop */
-	struct rsp_desc *desc;	/* address of HW response ring */
-	dma_addr_t phys_addr;	/* physical address of the ring */
-	unsigned int cntxt_id;	/* SGE context id for the response q */
-	spinlock_t lock;	/* guards response processing */
-	struct sk_buff_head rx_queue; /* offload packet receive queue */
-	struct sk_buff *pg_skb; /* used to build frag list in napi handler */
-
-	unsigned long offload_pkts;
-	unsigned long offload_bundles;
-	unsigned long eth_pkts;	/* # of ethernet packets */
-	unsigned long pure_rsps;	/* # of pure (non-data) responses */
-	unsigned long imm_data;	/* responses with immediate data */
-	unsigned long rx_drops;	/* # of packets dropped due to no mem */
-	unsigned long async_notif; /* # of asynchronous notification events */
-	unsigned long empty;	/* # of times queue ran out of credits */
-	unsigned long nomem;	/* # of responses deferred due to no mem */
-	unsigned long unhandled_irqs;	/* # of spurious intrs */
-	unsigned long starved;
-	unsigned long restarted;
-};
-
-struct tx_desc;
-struct tx_sw_desc;
-
-struct sge_txq {		/* state for an SGE Tx queue */
-	unsigned long flags;	/* HW DMA fetch status */
-	unsigned int in_use;	/* # of in-use Tx descriptors */
-	unsigned int size;	/* # of descriptors */
-	unsigned int processed;	/* total # of descs HW has processed */
-	unsigned int cleaned;	/* total # of descs SW has reclaimed */
-	unsigned int stop_thres;	/* SW TX queue suspend threshold */
-	unsigned int cidx;	/* consumer index */
-	unsigned int pidx;	/* producer index */
-	unsigned int gen;	/* current value of generation bit */
-	unsigned int unacked;	/* Tx descriptors used since last COMPL */
-	struct tx_desc *desc;	/* address of HW Tx descriptor ring */
-	struct tx_sw_desc *sdesc;	/* address of SW Tx descriptor ring */
-	spinlock_t lock;	/* guards enqueueing of new packets */
-	unsigned int token;	/* WR token */
-	dma_addr_t phys_addr;	/* physical address of the ring */
-	struct sk_buff_head sendq;	/* List of backpressured offload packets */
-	struct tasklet_struct qresume_tsk;	/* restarts the queue */
-	unsigned int cntxt_id;	/* SGE context id for the Tx q */
-	unsigned long stops;	/* # of times q has been stopped */
-	unsigned long restarts;	/* # of queue restarts */
-};
-
-enum {				/* per port SGE statistics */
-	SGE_PSTAT_TSO,		/* # of TSO requests */
-	SGE_PSTAT_RX_CSUM_GOOD,	/* # of successful RX csum offloads */
-	SGE_PSTAT_TX_CSUM,	/* # of TX checksum offloads */
-	SGE_PSTAT_VLANEX,	/* # of VLAN tag extractions */
-	SGE_PSTAT_VLANINS,	/* # of VLAN tag insertions */
-
-	SGE_PSTAT_MAX		/* must be last */
-};
-
-struct napi_gro_fraginfo;
-
-struct sge_qset {		/* an SGE queue set */
-	struct adapter *adap;
-	struct napi_struct napi;
-	struct sge_rspq rspq;
-	struct sge_fl fl[SGE_RXQ_PER_SET];
-	struct sge_txq txq[SGE_TXQ_PER_SET];
-	int nomem;
-	void *lro_va;
-	struct net_device *netdev;
-	struct netdev_queue *tx_q;	/* associated netdev TX queue */
-	unsigned long txq_stopped;	/* which Tx queues are stopped */
-	struct timer_list tx_reclaim_timer;	/* reclaims TX buffers */
-	struct timer_list rx_reclaim_timer;	/* reclaims RX buffers */
-	unsigned long port_stats[SGE_PSTAT_MAX];
-} ____cacheline_aligned;
-
-struct sge {
-	struct sge_qset qs[SGE_QSETS];
-	spinlock_t reg_lock;	/* guards non-atomic SGE registers (eg context) */
-};
-
-struct adapter {
-	struct t3cdev tdev;
-	struct list_head adapter_list;
-	void __iomem *regs;
-	struct pci_dev *pdev;
-	unsigned long registered_device_map;
-	unsigned long open_device_map;
-	unsigned long flags;
-
-	const char *name;
-	int msg_enable;
-	unsigned int mmio_len;
-
-	struct adapter_params params;
-	unsigned int slow_intr_mask;
-	unsigned long irq_stats[IRQ_NUM_STATS];
-
-	int msix_nvectors;
-	struct {
-		unsigned short vec;
-		char desc[22];
-	} msix_info[SGE_QSETS + 1];
-
-	/* T3 modules */
-	struct sge sge;
-	struct mc7 pmrx;
-	struct mc7 pmtx;
-	struct mc7 cm;
-	struct mc5 mc5;
-
-	struct net_device *port[MAX_NPORTS];
-	unsigned int check_task_cnt;
-	struct delayed_work adap_check_task;
-	struct work_struct ext_intr_handler_task;
-	struct work_struct fatal_error_handler_task;
-	struct work_struct link_fault_handler_task;
-
-	struct work_struct db_full_task;
-	struct work_struct db_empty_task;
-	struct work_struct db_drop_task;
-
-	struct dentry *debugfs_root;
-
-	struct mutex mdio_lock;
-	spinlock_t stats_lock;
-	spinlock_t work_lock;
-
-	struct sk_buff *nofail_skb;
-};
-
-static inline u32 t3_read_reg(struct adapter *adapter, u32 reg_addr)
-{
-	u32 val = readl(adapter->regs + reg_addr);
-
-	CH_DBG(adapter, MMIO, "read register 0x%x value 0x%x\n", reg_addr, val);
-	return val;
-}
-
-static inline void t3_write_reg(struct adapter *adapter, u32 reg_addr, u32 val)
-{
-	CH_DBG(adapter, MMIO, "setting register 0x%x to 0x%x\n", reg_addr, val);
-	writel(val, adapter->regs + reg_addr);
-}
-
-static inline struct port_info *adap2pinfo(struct adapter *adap, int idx)
-{
-	return netdev_priv(adap->port[idx]);
-}
-
-static inline int phy2portid(struct cphy *phy)
-{
-	struct adapter *adap = phy->adapter;
-	struct port_info *port0 = adap2pinfo(adap, 0);
-
-	return &port0->phy == phy ? 0 : 1;
-}
-
-#define OFFLOAD_DEVMAP_BIT 15
-
-#define tdev2adap(d) container_of(d, struct adapter, tdev)
-
-static inline int offload_running(struct adapter *adapter)
-{
-	return test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map);
-}
-
-int t3_offload_tx(struct t3cdev *tdev, struct sk_buff *skb);
-
-void t3_os_ext_intr_handler(struct adapter *adapter);
-void t3_os_link_changed(struct adapter *adapter, int port_id, int link_status,
-			int speed, int duplex, int fc);
-void t3_os_phymod_changed(struct adapter *adap, int port_id);
-void t3_os_link_fault(struct adapter *adapter, int port_id, int state);
-void t3_os_link_fault_handler(struct adapter *adapter, int port_id);
-
-void t3_sge_start(struct adapter *adap);
-void t3_sge_stop(struct adapter *adap);
-void t3_start_sge_timers(struct adapter *adap);
-void t3_stop_sge_timers(struct adapter *adap);
-void t3_free_sge_resources(struct adapter *adap);
-void t3_sge_err_intr_handler(struct adapter *adapter);
-irq_handler_t t3_intr_handler(struct adapter *adap, int polling);
-netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev);
-int t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb);
-void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p);
-int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
-		      int irq_vec_idx, const struct qset_params *p,
-		      int ntxq, struct net_device *dev,
-		      struct netdev_queue *netdevq);
-extern struct workqueue_struct *cxgb3_wq;
-
-int t3_get_edc_fw(struct cphy *phy, int edc_idx, int size);
-
-#endif				/* __T3_ADAPTER_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/ael1002.c linux-libre-3.2-gnu/drivers/net/cxgb3/ael1002.c
--- linux-libre-3.1-gnu/drivers/net/cxgb3/ael1002.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/ael1002.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,941 +0,0 @@
-/*
- * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#include "common.h"
-#include "regs.h"
-
-enum {
-	AEL100X_TX_CONFIG1 = 0xc002,
-	AEL1002_PWR_DOWN_HI = 0xc011,
-	AEL1002_PWR_DOWN_LO = 0xc012,
-	AEL1002_XFI_EQL = 0xc015,
-	AEL1002_LB_EN = 0xc017,
-	AEL_OPT_SETTINGS = 0xc017,
-	AEL_I2C_CTRL = 0xc30a,
-	AEL_I2C_DATA = 0xc30b,
-	AEL_I2C_STAT = 0xc30c,
-	AEL2005_GPIO_CTRL = 0xc214,
-	AEL2005_GPIO_STAT = 0xc215,
-
-	AEL2020_GPIO_INTR   = 0xc103,	/* Latch High (LH) */
-	AEL2020_GPIO_CTRL   = 0xc108,	/* Store Clear (SC) */
-	AEL2020_GPIO_STAT   = 0xc10c,	/* Read Only (RO) */
-	AEL2020_GPIO_CFG    = 0xc110,	/* Read Write (RW) */
-
-	AEL2020_GPIO_SDA    = 0,	/* IN: i2c serial data */
-	AEL2020_GPIO_MODDET = 1,	/* IN: Module Detect */
-	AEL2020_GPIO_0      = 3,	/* IN: unassigned */
-	AEL2020_GPIO_1      = 2,	/* OUT: unassigned */
-	AEL2020_GPIO_LSTAT  = AEL2020_GPIO_1, /* wired to link status LED */
-};
-
-enum { edc_none, edc_sr, edc_twinax };
-
-/* PHY module I2C device address */
-enum {
-	MODULE_DEV_ADDR	= 0xa0,
-	SFF_DEV_ADDR	= 0xa2,
-};
-
-/* PHY transceiver type */
-enum {
-	phy_transtype_unknown = 0,
-	phy_transtype_sfp     = 3,
-	phy_transtype_xfp     = 6,
-};
-
-#define AEL2005_MODDET_IRQ 4
-
-struct reg_val {
-	unsigned short mmd_addr;
-	unsigned short reg_addr;
-	unsigned short clear_bits;
-	unsigned short set_bits;
-};
-
-static int set_phy_regs(struct cphy *phy, const struct reg_val *rv)
-{
-	int err;
-
-	for (err = 0; rv->mmd_addr && !err; rv++) {
-		if (rv->clear_bits == 0xffff)
-			err = t3_mdio_write(phy, rv->mmd_addr, rv->reg_addr,
-					    rv->set_bits);
-		else
-			err = t3_mdio_change_bits(phy, rv->mmd_addr,
-						  rv->reg_addr, rv->clear_bits,
-						  rv->set_bits);
-	}
-	return err;
-}
-
-static void ael100x_txon(struct cphy *phy)
-{
-	int tx_on_gpio =
-		phy->mdio.prtad == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
-
-	msleep(100);
-	t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio);
-	msleep(30);
-}
-
-/*
- * Read an 8-bit word from a device attached to the PHY's i2c bus.
- */
-static int ael_i2c_rd(struct cphy *phy, int dev_addr, int word_addr)
-{
-	int i, err;
-	unsigned int stat, data;
-
-	err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL_I2C_CTRL,
-			    (dev_addr << 8) | (1 << 8) | word_addr);
-	if (err)
-		return err;
-
-	for (i = 0; i < 200; i++) {
-		msleep(1);
-		err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_STAT, &stat);
-		if (err)
-			return err;
-		if ((stat & 3) == 1) {
-			err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_DATA,
-					   &data);
-			if (err)
-				return err;
-			return data >> 8;
-		}
-	}
-	CH_WARN(phy->adapter, "PHY %u i2c read of dev.addr %#x.%#x timed out\n",
-		phy->mdio.prtad, dev_addr, word_addr);
-	return -ETIMEDOUT;
-}
-
-static int ael1002_power_down(struct cphy *phy, int enable)
-{
-	int err;
-
-	err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, !!enable);
-	if (!err)
-		err = mdio_set_flag(&phy->mdio, phy->mdio.prtad,
-				    MDIO_MMD_PMAPMD, MDIO_CTRL1,
-				    MDIO_CTRL1_LPOWER, enable);
-	return err;
-}
-
-static int ael1002_reset(struct cphy *phy, int wait)
-{
-	int err;
-
-	if ((err = ael1002_power_down(phy, 0)) ||
-	    (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL100X_TX_CONFIG1, 1)) ||
-	    (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_PWR_DOWN_HI, 0)) ||
-	    (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_PWR_DOWN_LO, 0)) ||
-	    (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_XFI_EQL, 0x18)) ||
-	    (err = t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL1002_LB_EN,
-				       0, 1 << 5)))
-		return err;
-	return 0;
-}
-
-static int ael1002_intr_noop(struct cphy *phy)
-{
-	return 0;
-}
-
-/*
- * Get link status for a 10GBASE-R device.
- */
-static int get_link_status_r(struct cphy *phy, int *link_ok, int *speed,
-			     int *duplex, int *fc)
-{
-	if (link_ok) {
-		unsigned int stat0, stat1, stat2;
-		int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD,
-				       MDIO_PMA_RXDET, &stat0);
-
-		if (!err)
-			err = t3_mdio_read(phy, MDIO_MMD_PCS,
-					   MDIO_PCS_10GBRT_STAT1, &stat1);
-		if (!err)
-			err = t3_mdio_read(phy, MDIO_MMD_PHYXS,
-					   MDIO_PHYXS_LNSTAT, &stat2);
-		if (err)
-			return err;
-		*link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1;
-	}
-	if (speed)
-		*speed = SPEED_10000;
-	if (duplex)
-		*duplex = DUPLEX_FULL;
-	return 0;
-}
-
-static struct cphy_ops ael1002_ops = {
-	.reset = ael1002_reset,
-	.intr_enable = ael1002_intr_noop,
-	.intr_disable = ael1002_intr_noop,
-	.intr_clear = ael1002_intr_noop,
-	.intr_handler = ael1002_intr_noop,
-	.get_link_status = get_link_status_r,
-	.power_down = ael1002_power_down,
-	.mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
-};
-
-int t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter,
-			int phy_addr, const struct mdio_ops *mdio_ops)
-{
-	cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops,
-		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
-		   "10GBASE-R");
-	ael100x_txon(phy);
-	return 0;
-}
-
-static int ael1006_reset(struct cphy *phy, int wait)
-{
-	return t3_phy_reset(phy, MDIO_MMD_PMAPMD, wait);
-}
-
-static struct cphy_ops ael1006_ops = {
-	.reset = ael1006_reset,
-	.intr_enable = t3_phy_lasi_intr_enable,
-	.intr_disable = t3_phy_lasi_intr_disable,
-	.intr_clear = t3_phy_lasi_intr_clear,
-	.intr_handler = t3_phy_lasi_intr_handler,
-	.get_link_status = get_link_status_r,
-	.power_down = ael1002_power_down,
-	.mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
-};
-
-int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter,
-			     int phy_addr, const struct mdio_ops *mdio_ops)
-{
-	cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops,
-		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
-		   "10GBASE-SR");
-	ael100x_txon(phy);
-	return 0;
-}
-
-/*
- * Decode our module type.
- */
-static int ael2xxx_get_module_type(struct cphy *phy, int delay_ms)
-{
-	int v;
-
-	if (delay_ms)
-		msleep(delay_ms);
-
-	/* see SFF-8472 for below */
-	v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 3);
-	if (v < 0)
-		return v;
-
-	if (v == 0x10)
-		return phy_modtype_sr;
-	if (v == 0x20)
-		return phy_modtype_lr;
-	if (v == 0x40)
-		return phy_modtype_lrm;
-
-	v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 6);
-	if (v < 0)
-		return v;
-	if (v != 4)
-		goto unknown;
-
-	v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 10);
-	if (v < 0)
-		return v;
-
-	if (v & 0x80) {
-		v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
-		if (v < 0)
-			return v;
-		return v > 10 ? phy_modtype_twinax_long : phy_modtype_twinax;
-	}
-unknown:
-	return phy_modtype_unknown;
-}
-
-/*
- * Code to support the Aeluros/NetLogic 2005 10Gb PHY.
- */
-static int ael2005_setup_sr_edc(struct cphy *phy)
-{
-	static const struct reg_val regs[] = {
-		{ MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x181 },
-		{ MDIO_MMD_PMAPMD, 0xc010, 0xffff, 0x448a },
-		{ MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5200 },
-		{ 0, 0, 0, 0 }
-	};
-
-	int i, err;
-
-	err = set_phy_regs(phy, regs);
-	if (err)
-		return err;
-
-	msleep(50);
-
-	if (phy->priv != edc_sr)
-		err = t3_get_edc_fw(phy, EDC_OPT_AEL2005,
-				    EDC_OPT_AEL2005_SIZE);
-	if (err)
-		return err;
-
-	for (i = 0; i <  EDC_OPT_AEL2005_SIZE / sizeof(u16) && !err; i += 2)
-		err = t3_mdio_write(phy, MDIO_MMD_PMAPMD,
-				    phy->phy_cache[i],
-				    phy->phy_cache[i + 1]);
-	if (!err)
-		phy->priv = edc_sr;
-	return err;
-}
-
-static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
-{
-	static const struct reg_val regs[] = {
-		{ MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5a00 },
-		{ 0, 0, 0, 0 }
-	};
-	static const struct reg_val preemphasis[] = {
-		{ MDIO_MMD_PMAPMD, 0xc014, 0xffff, 0xfe16 },
-		{ MDIO_MMD_PMAPMD, 0xc015, 0xffff, 0xa000 },
-		{ 0, 0, 0, 0 }
-	};
-	int i, err;
-
-	err = set_phy_regs(phy, regs);
-	if (!err && modtype == phy_modtype_twinax_long)
-		err = set_phy_regs(phy, preemphasis);
-	if (err)
-		return err;
-
-	msleep(50);
-
-	if (phy->priv != edc_twinax)
-		err = t3_get_edc_fw(phy, EDC_TWX_AEL2005,
-				    EDC_TWX_AEL2005_SIZE);
-	if (err)
-		return err;
-
-	for (i = 0; i <  EDC_TWX_AEL2005_SIZE / sizeof(u16) && !err; i += 2)
-		err = t3_mdio_write(phy, MDIO_MMD_PMAPMD,
-				    phy->phy_cache[i],
-				    phy->phy_cache[i + 1]);
-	if (!err)
-		phy->priv = edc_twinax;
-	return err;
-}
-
-static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
-{
-	int v;
-	unsigned int stat;
-
-	v = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, &stat);
-	if (v)
-		return v;
-
-	if (stat & (1 << 8))			/* module absent */
-		return phy_modtype_none;
-
-	return ael2xxx_get_module_type(phy, delay_ms);
-}
-
-static int ael2005_intr_enable(struct cphy *phy)
-{
-	int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x200);
-	return err ? err : t3_phy_lasi_intr_enable(phy);
-}
-
-static int ael2005_intr_disable(struct cphy *phy)
-{
-	int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x100);
-	return err ? err : t3_phy_lasi_intr_disable(phy);
-}
-
-static int ael2005_intr_clear(struct cphy *phy)
-{
-	int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0xd00);
-	return err ? err : t3_phy_lasi_intr_clear(phy);
-}
-
-static int ael2005_reset(struct cphy *phy, int wait)
-{
-	static const struct reg_val regs0[] = {
-		{ MDIO_MMD_PMAPMD, 0xc001, 0, 1 << 5 },
-		{ MDIO_MMD_PMAPMD, 0xc017, 0, 1 << 5 },
-		{ MDIO_MMD_PMAPMD, 0xc013, 0xffff, 0xf341 },
-		{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 },
-		{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8100 },
-		{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 },
-		{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0 },
-		{ 0, 0, 0, 0 }
-	};
-	static const struct reg_val regs1[] = {
-		{ MDIO_MMD_PMAPMD, 0xca00, 0xffff, 0x0080 },
-		{ MDIO_MMD_PMAPMD, 0xca12, 0xffff, 0 },
-		{ 0, 0, 0, 0 }
-	};
-
-	int err;
-	unsigned int lasi_ctrl;
-
-	err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL,
-			   &lasi_ctrl);
-	if (err)
-		return err;
-
-	err = t3_phy_reset(phy, MDIO_MMD_PMAPMD, 0);
-	if (err)
-		return err;
-
-	msleep(125);
-	phy->priv = edc_none;
-	err = set_phy_regs(phy, regs0);
-	if (err)
-		return err;
-
-	msleep(50);
-
-	err = ael2005_get_module_type(phy, 0);
-	if (err < 0)
-		return err;
-	phy->modtype = err;
-
-	if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
-		err = ael2005_setup_twinax_edc(phy, err);
-	else
-		err = ael2005_setup_sr_edc(phy);
-	if (err)
-		return err;
-
-	err = set_phy_regs(phy, regs1);
-	if (err)
-		return err;
-
-	/* reset wipes out interrupts, reenable them if they were on */
-	if (lasi_ctrl & 1)
-		err = ael2005_intr_enable(phy);
-	return err;
-}
-
-static int ael2005_intr_handler(struct cphy *phy)
-{
-	unsigned int stat;
-	int ret, edc_needed, cause = 0;
-
-	ret = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_STAT, &stat);
-	if (ret)
-		return ret;
-
-	if (stat & AEL2005_MODDET_IRQ) {
-		ret = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL,
-				    0xd00);
-		if (ret)
-			return ret;
-
-		/* modules have max 300 ms init time after hot plug */
-		ret = ael2005_get_module_type(phy, 300);
-		if (ret < 0)
-			return ret;
-
-		phy->modtype = ret;
-		if (ret == phy_modtype_none)
-			edc_needed = phy->priv;       /* on unplug retain EDC */
-		else if (ret == phy_modtype_twinax ||
-			 ret == phy_modtype_twinax_long)
-			edc_needed = edc_twinax;
-		else
-			edc_needed = edc_sr;
-
-		if (edc_needed != phy->priv) {
-			ret = ael2005_reset(phy, 0);
-			return ret ? ret : cphy_cause_module_change;
-		}
-		cause = cphy_cause_module_change;
-	}
-
-	ret = t3_phy_lasi_intr_handler(phy);
-	if (ret < 0)
-		return ret;
-
-	ret |= cause;
-	return ret ? ret : cphy_cause_link_change;
-}
-
-static struct cphy_ops ael2005_ops = {
-	.reset           = ael2005_reset,
-	.intr_enable     = ael2005_intr_enable,
-	.intr_disable    = ael2005_intr_disable,
-	.intr_clear      = ael2005_intr_clear,
-	.intr_handler    = ael2005_intr_handler,
-	.get_link_status = get_link_status_r,
-	.power_down      = ael1002_power_down,
-	.mmds            = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
-};
-
-int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter,
-			int phy_addr, const struct mdio_ops *mdio_ops)
-{
-	cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops,
-		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
-		  SUPPORTED_IRQ, "10GBASE-R");
-	msleep(125);
-	return t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL_OPT_SETTINGS, 0,
-				   1 << 5);
-}
-
-/*
- * Setup EDC and other parameters for operation with an optical module.
- */
-static int ael2020_setup_sr_edc(struct cphy *phy)
-{
-	static const struct reg_val regs[] = {
-		/* set CDR offset to 10 */
-		{ MDIO_MMD_PMAPMD, 0xcc01, 0xffff, 0x488a },
-
-		/* adjust 10G RX bias current */
-		{ MDIO_MMD_PMAPMD, 0xcb1b, 0xffff, 0x0200 },
-		{ MDIO_MMD_PMAPMD, 0xcb1c, 0xffff, 0x00f0 },
-		{ MDIO_MMD_PMAPMD, 0xcc06, 0xffff, 0x00e0 },
-
-		/* end */
-		{ 0, 0, 0, 0 }
-	};
-	int err;
-
-	err = set_phy_regs(phy, regs);
-	msleep(50);
-	if (err)
-		return err;
-
-	phy->priv = edc_sr;
-	return 0;
-}
-
-/*
- * Setup EDC and other parameters for operation with an TWINAX module.
- */
-static int ael2020_setup_twinax_edc(struct cphy *phy, int modtype)
-{
-	/* set uC to 40MHz */
-	static const struct reg_val uCclock40MHz[] = {
-		{ MDIO_MMD_PMAPMD, 0xff28, 0xffff, 0x4001 },
-		{ MDIO_MMD_PMAPMD, 0xff2a, 0xffff, 0x0002 },
-		{ 0, 0, 0, 0 }
-	};
-
-	/* activate uC clock */
-	static const struct reg_val uCclockActivate[] = {
-		{ MDIO_MMD_PMAPMD, 0xd000, 0xffff, 0x5200 },
-		{ 0, 0, 0, 0 }
-	};
-
-	/* set PC to start of SRAM and activate uC */
-	static const struct reg_val uCactivate[] = {
-		{ MDIO_MMD_PMAPMD, 0xd080, 0xffff, 0x0100 },
-		{ MDIO_MMD_PMAPMD, 0xd092, 0xffff, 0x0000 },
-		{ 0, 0, 0, 0 }
-	};
-	int i, err;
-
-	/* set uC clock and activate it */
-	err = set_phy_regs(phy, uCclock40MHz);
-	msleep(500);
-	if (err)
-		return err;
-	err = set_phy_regs(phy, uCclockActivate);
-	msleep(500);
-	if (err)
-		return err;
-
-	if (phy->priv != edc_twinax)
-		err = t3_get_edc_fw(phy, EDC_TWX_AEL2020,
-				    EDC_TWX_AEL2020_SIZE);
-	if (err)
-		return err;
-
-	for (i = 0; i <  EDC_TWX_AEL2020_SIZE / sizeof(u16) && !err; i += 2)
-		err = t3_mdio_write(phy, MDIO_MMD_PMAPMD,
-				    phy->phy_cache[i],
-				    phy->phy_cache[i + 1]);
-	/* activate uC */
-	err = set_phy_regs(phy, uCactivate);
-	if (!err)
-		phy->priv = edc_twinax;
-	return err;
-}
-
-/*
- * Return Module Type.
- */
-static int ael2020_get_module_type(struct cphy *phy, int delay_ms)
-{
-	int v;
-	unsigned int stat;
-
-	v = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_STAT, &stat);
-	if (v)
-		return v;
-
-	if (stat & (0x1 << (AEL2020_GPIO_MODDET*4))) {
-		/* module absent */
-		return phy_modtype_none;
-	}
-
-	return ael2xxx_get_module_type(phy, delay_ms);
-}
-
-/*
- * Enable PHY interrupts.  We enable "Module Detection" interrupts (on any
- * state transition) and then generic Link Alarm Status Interrupt (LASI).
- */
-static int ael2020_intr_enable(struct cphy *phy)
-{
-	static const struct reg_val regs[] = {
-		/* output Module's Loss Of Signal (LOS) to LED */
-		{ MDIO_MMD_PMAPMD, AEL2020_GPIO_CFG+AEL2020_GPIO_LSTAT,
-			0xffff, 0x4 },
-		{ MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
-			0xffff, 0x8 << (AEL2020_GPIO_LSTAT*4) },
-
-		 /* enable module detect status change interrupts */
-		{ MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
-			0xffff, 0x2 << (AEL2020_GPIO_MODDET*4) },
-
-		/* end */
-		{ 0, 0, 0, 0 }
-	};
-	int err, link_ok = 0;
-
-	/* set up "link status" LED and enable module change interrupts */
-	err = set_phy_regs(phy, regs);
-	if (err)
-		return err;
-
-	err = get_link_status_r(phy, &link_ok, NULL, NULL, NULL);
-	if (err)
-		return err;
-	if (link_ok)
-		t3_link_changed(phy->adapter,
-				phy2portid(phy));
-
-	err = t3_phy_lasi_intr_enable(phy);
-	if (err)
-		return err;
-
-	return 0;
-}
-
-/*
- * Disable PHY interrupts.  The mirror of the above ...
- */
-static int ael2020_intr_disable(struct cphy *phy)
-{
-	static const struct reg_val regs[] = {
-		/* reset "link status" LED to "off" */
-		{ MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
-			0xffff, 0xb << (AEL2020_GPIO_LSTAT*4) },
-
-		/* disable module detect status change interrupts */
-		{ MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
-			0xffff, 0x1 << (AEL2020_GPIO_MODDET*4) },
-
-		/* end */
-		{ 0, 0, 0, 0 }
-	};
-	int err;
-
-	/* turn off "link status" LED and disable module change interrupts */
-	err = set_phy_regs(phy, regs);
-	if (err)
-		return err;
-
-	return t3_phy_lasi_intr_disable(phy);
-}
-
-/*
- * Clear PHY interrupt state.
- */
-static int ael2020_intr_clear(struct cphy *phy)
-{
-	/*
-	 * The GPIO Interrupt register on the AEL2020 is a "Latching High"
-	 * (LH) register which is cleared to the current state when it's read.
-	 * Thus, we simply read the register and discard the result.
-	 */
-	unsigned int stat;
-	int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_INTR, &stat);
-	return err ? err : t3_phy_lasi_intr_clear(phy);
-}
-
-static const struct reg_val ael2020_reset_regs[] = {
-	/* Erratum #2: CDRLOL asserted, causing PMA link down status */
-	{ MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x3101 },
-
-	/* force XAUI to send LF when RX_LOS is asserted */
-	{ MDIO_MMD_PMAPMD, 0xcd40, 0xffff, 0x0001 },
-
-	/* allow writes to transceiver module EEPROM on i2c bus */
-	{ MDIO_MMD_PMAPMD, 0xff02, 0xffff, 0x0023 },
-	{ MDIO_MMD_PMAPMD, 0xff03, 0xffff, 0x0000 },
-	{ MDIO_MMD_PMAPMD, 0xff04, 0xffff, 0x0000 },
-
-	/* end */
-	{ 0, 0, 0, 0 }
-};
-/*
- * Reset the PHY and put it into a canonical operating state.
- */
-static int ael2020_reset(struct cphy *phy, int wait)
-{
-	int err;
-	unsigned int lasi_ctrl;
-
-	/* grab current interrupt state */
-	err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL,
-			   &lasi_ctrl);
-	if (err)
-		return err;
-
-	err = t3_phy_reset(phy, MDIO_MMD_PMAPMD, 125);
-	if (err)
-		return err;
-	msleep(100);
-
-	/* basic initialization for all module types */
-	phy->priv = edc_none;
-	err = set_phy_regs(phy, ael2020_reset_regs);
-	if (err)
-		return err;
-
-	/* determine module type and perform appropriate initialization */
-	err = ael2020_get_module_type(phy, 0);
-	if (err < 0)
-		return err;
-	phy->modtype = (u8)err;
-	if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
-		err = ael2020_setup_twinax_edc(phy, err);
-	else
-		err = ael2020_setup_sr_edc(phy);
-	if (err)
-		return err;
-
-	/* reset wipes out interrupts, reenable them if they were on */
-	if (lasi_ctrl & 1)
-		err = ael2005_intr_enable(phy);
-	return err;
-}
-
-/*
- * Handle a PHY interrupt.
- */
-static int ael2020_intr_handler(struct cphy *phy)
-{
-	unsigned int stat;
-	int ret, edc_needed, cause = 0;
-
-	ret = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_INTR, &stat);
-	if (ret)
-		return ret;
-
-	if (stat & (0x1 << AEL2020_GPIO_MODDET)) {
-		/* modules have max 300 ms init time after hot plug */
-		ret = ael2020_get_module_type(phy, 300);
-		if (ret < 0)
-			return ret;
-
-		phy->modtype = (u8)ret;
-		if (ret == phy_modtype_none)
-			edc_needed = phy->priv;       /* on unplug retain EDC */
-		else if (ret == phy_modtype_twinax ||
-			 ret == phy_modtype_twinax_long)
-			edc_needed = edc_twinax;
-		else
-			edc_needed = edc_sr;
-
-		if (edc_needed != phy->priv) {
-			ret = ael2020_reset(phy, 0);
-			return ret ? ret : cphy_cause_module_change;
-		}
-		cause = cphy_cause_module_change;
-	}
-
-	ret = t3_phy_lasi_intr_handler(phy);
-	if (ret < 0)
-		return ret;
-
-	ret |= cause;
-	return ret ? ret : cphy_cause_link_change;
-}
-
-static struct cphy_ops ael2020_ops = {
-	.reset           = ael2020_reset,
-	.intr_enable     = ael2020_intr_enable,
-	.intr_disable    = ael2020_intr_disable,
-	.intr_clear      = ael2020_intr_clear,
-	.intr_handler    = ael2020_intr_handler,
-	.get_link_status = get_link_status_r,
-	.power_down      = ael1002_power_down,
-	.mmds		 = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
-};
-
-int t3_ael2020_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr,
-			const struct mdio_ops *mdio_ops)
-{
-	int err;
-
-	cphy_init(phy, adapter, phy_addr, &ael2020_ops, mdio_ops,
-		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
-		  SUPPORTED_IRQ, "10GBASE-R");
-	msleep(125);
-
-	err = set_phy_regs(phy, ael2020_reset_regs);
-	if (err)
-		return err;
-	return 0;
-}
-
-/*
- * Get link status for a 10GBASE-X device.
- */
-static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed,
-			     int *duplex, int *fc)
-{
-	if (link_ok) {
-		unsigned int stat0, stat1, stat2;
-		int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD,
-				       MDIO_PMA_RXDET, &stat0);
-
-		if (!err)
-			err = t3_mdio_read(phy, MDIO_MMD_PCS,
-					   MDIO_PCS_10GBX_STAT1, &stat1);
-		if (!err)
-			err = t3_mdio_read(phy, MDIO_MMD_PHYXS,
-					   MDIO_PHYXS_LNSTAT, &stat2);
-		if (err)
-			return err;
-		*link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1;
-	}
-	if (speed)
-		*speed = SPEED_10000;
-	if (duplex)
-		*duplex = DUPLEX_FULL;
-	return 0;
-}
-
-static struct cphy_ops qt2045_ops = {
-	.reset = ael1006_reset,
-	.intr_enable = t3_phy_lasi_intr_enable,
-	.intr_disable = t3_phy_lasi_intr_disable,
-	.intr_clear = t3_phy_lasi_intr_clear,
-	.intr_handler = t3_phy_lasi_intr_handler,
-	.get_link_status = get_link_status_x,
-	.power_down = ael1002_power_down,
-	.mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
-};
-
-int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter,
-		       int phy_addr, const struct mdio_ops *mdio_ops)
-{
-	unsigned int stat;
-
-	cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops,
-		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
-		  "10GBASE-CX4");
-
-	/*
-	 * Some cards where the PHY is supposed to be at address 0 actually
-	 * have it at 1.
-	 */
-	if (!phy_addr &&
-	    !t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &stat) &&
-	    stat == 0xffff)
-		phy->mdio.prtad = 1;
-	return 0;
-}
-
-static int xaui_direct_reset(struct cphy *phy, int wait)
-{
-	return 0;
-}
-
-static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
-				       int *speed, int *duplex, int *fc)
-{
-	if (link_ok) {
-		unsigned int status;
-		int prtad = phy->mdio.prtad;
-
-		status = t3_read_reg(phy->adapter,
-				     XGM_REG(A_XGM_SERDES_STAT0, prtad)) |
-		    t3_read_reg(phy->adapter,
-				    XGM_REG(A_XGM_SERDES_STAT1, prtad)) |
-		    t3_read_reg(phy->adapter,
-				XGM_REG(A_XGM_SERDES_STAT2, prtad)) |
-		    t3_read_reg(phy->adapter,
-				XGM_REG(A_XGM_SERDES_STAT3, prtad));
-		*link_ok = !(status & F_LOWSIG0);
-	}
-	if (speed)
-		*speed = SPEED_10000;
-	if (duplex)
-		*duplex = DUPLEX_FULL;
-	return 0;
-}
-
-static int xaui_direct_power_down(struct cphy *phy, int enable)
-{
-	return 0;
-}
-
-static struct cphy_ops xaui_direct_ops = {
-	.reset = xaui_direct_reset,
-	.intr_enable = ael1002_intr_noop,
-	.intr_disable = ael1002_intr_noop,
-	.intr_clear = ael1002_intr_noop,
-	.intr_handler = ael1002_intr_noop,
-	.get_link_status = xaui_direct_get_link_status,
-	.power_down = xaui_direct_power_down,
-};
-
-int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
-			    int phy_addr, const struct mdio_ops *mdio_ops)
-{
-	cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops,
-		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
-		  "10GBASE-CX4");
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/aq100x.c linux-libre-3.2-gnu/drivers/net/cxgb3/aq100x.c
--- linux-libre-3.1-gnu/drivers/net/cxgb3/aq100x.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/aq100x.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,354 +0,0 @@
-/*
- * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "common.h"
-#include "regs.h"
-
-enum {
-	/* MDIO_DEV_PMA_PMD registers */
-	AQ_LINK_STAT	= 0xe800,
-	AQ_IMASK_PMA	= 0xf000,
-
-	/* MDIO_DEV_XGXS registers */
-	AQ_XAUI_RX_CFG	= 0xc400,
-	AQ_XAUI_TX_CFG	= 0xe400,
-
-	/* MDIO_DEV_ANEG registers */
-	AQ_1G_CTRL	= 0xc400,
-	AQ_ANEG_STAT	= 0xc800,
-
-	/* MDIO_DEV_VEND1 registers */
-	AQ_FW_VERSION	= 0x0020,
-	AQ_IFLAG_GLOBAL	= 0xfc00,
-	AQ_IMASK_GLOBAL	= 0xff00,
-};
-
-enum {
-	IMASK_PMA	= 1 << 2,
-	IMASK_GLOBAL	= 1 << 15,
-	ADV_1G_FULL	= 1 << 15,
-	ADV_1G_HALF	= 1 << 14,
-	ADV_10G_FULL	= 1 << 12,
-	AQ_RESET	= (1 << 14) | (1 << 15),
-	AQ_LOWPOWER	= 1 << 12,
-};
-
-static int aq100x_reset(struct cphy *phy, int wait)
-{
-	/*
-	 * Ignore the caller specified wait time; always wait for the reset to
-	 * complete. Can take up to 3s.
-	 */
-	int err = t3_phy_reset(phy, MDIO_MMD_VEND1, 3000);
-
-	if (err)
-		CH_WARN(phy->adapter, "PHY%d: reset failed (0x%x).\n",
-			phy->mdio.prtad, err);
-
-	return err;
-}
-
-static int aq100x_intr_enable(struct cphy *phy)
-{
-	int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AQ_IMASK_PMA, IMASK_PMA);
-	if (err)
-		return err;
-
-	err = t3_mdio_write(phy, MDIO_MMD_VEND1, AQ_IMASK_GLOBAL, IMASK_GLOBAL);
-	return err;
-}
-
-static int aq100x_intr_disable(struct cphy *phy)
-{
-	return t3_mdio_write(phy, MDIO_MMD_VEND1, AQ_IMASK_GLOBAL, 0);
-}
-
-static int aq100x_intr_clear(struct cphy *phy)
-{
-	unsigned int v;
-
-	t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_IFLAG_GLOBAL, &v);
-	t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &v);
-
-	return 0;
-}
-
-static int aq100x_intr_handler(struct cphy *phy)
-{
-	int err;
-	unsigned int cause, v;
-
-	err = t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_IFLAG_GLOBAL, &cause);
-	if (err)
-		return err;
-
-	/* Read (and reset) the latching version of the status */
-	t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &v);
-
-	return cphy_cause_link_change;
-}
-
-static int aq100x_power_down(struct cphy *phy, int off)
-{
-	return mdio_set_flag(&phy->mdio, phy->mdio.prtad,
-			     MDIO_MMD_PMAPMD, MDIO_CTRL1,
-			     MDIO_CTRL1_LPOWER, off);
-}
-
-static int aq100x_autoneg_enable(struct cphy *phy)
-{
-	int err;
-
-	err = aq100x_power_down(phy, 0);
-	if (!err)
-		err = mdio_set_flag(&phy->mdio, phy->mdio.prtad,
-				    MDIO_MMD_AN, MDIO_CTRL1,
-				    BMCR_ANENABLE | BMCR_ANRESTART, 1);
-
-	return err;
-}
-
-static int aq100x_autoneg_restart(struct cphy *phy)
-{
-	int err;
-
-	err = aq100x_power_down(phy, 0);
-	if (!err)
-		err = mdio_set_flag(&phy->mdio, phy->mdio.prtad,
-				    MDIO_MMD_AN, MDIO_CTRL1,
-				    BMCR_ANENABLE | BMCR_ANRESTART, 1);
-
-	return err;
-}
-
-static int aq100x_advertise(struct cphy *phy, unsigned int advertise_map)
-{
-	unsigned int adv;
-	int err;
-
-	/* 10G advertisement */
-	adv = 0;
-	if (advertise_map & ADVERTISED_10000baseT_Full)
-		adv |= ADV_10G_FULL;
-	err = t3_mdio_change_bits(phy, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
-				  ADV_10G_FULL, adv);
-	if (err)
-		return err;
-
-	/* 1G advertisement */
-	adv = 0;
-	if (advertise_map & ADVERTISED_1000baseT_Full)
-		adv |= ADV_1G_FULL;
-	if (advertise_map & ADVERTISED_1000baseT_Half)
-		adv |= ADV_1G_HALF;
-	err = t3_mdio_change_bits(phy, MDIO_MMD_AN, AQ_1G_CTRL,
-				  ADV_1G_FULL | ADV_1G_HALF, adv);
-	if (err)
-		return err;
-
-	/* 100M, pause advertisement */
-	adv = 0;
-	if (advertise_map & ADVERTISED_100baseT_Half)
-		adv |= ADVERTISE_100HALF;
-	if (advertise_map & ADVERTISED_100baseT_Full)
-		adv |= ADVERTISE_100FULL;
-	if (advertise_map & ADVERTISED_Pause)
-		adv |= ADVERTISE_PAUSE_CAP;
-	if (advertise_map & ADVERTISED_Asym_Pause)
-		adv |= ADVERTISE_PAUSE_ASYM;
-	err = t3_mdio_change_bits(phy, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
-				  0xfe0, adv);
-
-	return err;
-}
-
-static int aq100x_set_loopback(struct cphy *phy, int mmd, int dir, int enable)
-{
-	return mdio_set_flag(&phy->mdio, phy->mdio.prtad,
-			     MDIO_MMD_PMAPMD, MDIO_CTRL1,
-			     BMCR_LOOPBACK, enable);
-}
-
-static int aq100x_set_speed_duplex(struct cphy *phy, int speed, int duplex)
-{
-	/* no can do */
-	return -1;
-}
-
-static int aq100x_get_link_status(struct cphy *phy, int *link_ok,
-				  int *speed, int *duplex, int *fc)
-{
-	int err;
-	unsigned int v;
-
-	if (link_ok) {
-		err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AQ_LINK_STAT, &v);
-		if (err)
-			return err;
-
-		*link_ok = v & 1;
-		if (!*link_ok)
-			return 0;
-	}
-
-	err = t3_mdio_read(phy, MDIO_MMD_AN, AQ_ANEG_STAT, &v);
-	if (err)
-		return err;
-
-	if (speed) {
-		switch (v & 0x6) {
-		case 0x6:
-			*speed = SPEED_10000;
-			break;
-		case 0x4:
-			*speed = SPEED_1000;
-			break;
-		case 0x2:
-			*speed = SPEED_100;
-			break;
-		case 0x0:
-			*speed = SPEED_10;
-			break;
-		}
-	}
-
-	if (duplex)
-		*duplex = v & 1 ? DUPLEX_FULL : DUPLEX_HALF;
-
-	return 0;
-}
-
-static struct cphy_ops aq100x_ops = {
-	.reset             = aq100x_reset,
-	.intr_enable       = aq100x_intr_enable,
-	.intr_disable      = aq100x_intr_disable,
-	.intr_clear        = aq100x_intr_clear,
-	.intr_handler      = aq100x_intr_handler,
-	.autoneg_enable    = aq100x_autoneg_enable,
-	.autoneg_restart   = aq100x_autoneg_restart,
-	.advertise         = aq100x_advertise,
-	.set_loopback      = aq100x_set_loopback,
-	.set_speed_duplex  = aq100x_set_speed_duplex,
-	.get_link_status   = aq100x_get_link_status,
-	.power_down        = aq100x_power_down,
-	.mmds 		   = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
-};
-
-int t3_aq100x_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr,
-		       const struct mdio_ops *mdio_ops)
-{
-	unsigned int v, v2, gpio, wait;
-	int err;
-
-	cphy_init(phy, adapter, phy_addr, &aq100x_ops, mdio_ops,
-		  SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full |
-		  SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_AUI,
-		  "1000/10GBASE-T");
-
-	/*
-	 * The PHY has been out of reset ever since the system powered up.  So
-	 * we do a hard reset over here.
-	 */
-	gpio = phy_addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL;
-	t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, 0);
-	msleep(1);
-	t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, gpio);
-
-	/*
-	 * Give it enough time to load the firmware and get ready for mdio.
-	 */
-	msleep(1000);
-	wait = 500; /* in 10ms increments */
-	do {
-		err = t3_mdio_read(phy, MDIO_MMD_VEND1, MDIO_CTRL1, &v);
-		if (err || v == 0xffff) {
-
-			/* Allow prep_adapter to succeed when ffff is read */
-
-			CH_WARN(adapter, "PHY%d: reset failed (0x%x, 0x%x).\n",
-				phy_addr, err, v);
-			goto done;
-		}
-
-		v &= AQ_RESET;
-		if (v)
-			msleep(10);
-	} while (v && --wait);
-	if (v) {
-		CH_WARN(adapter, "PHY%d: reset timed out (0x%x).\n",
-			phy_addr, v);
-
-		goto done; /* let prep_adapter succeed */
-	}
-
-	/* Datasheet says 3s max but this has been observed */
-	wait = (500 - wait) * 10 + 1000;
-	if (wait > 3000)
-		CH_WARN(adapter, "PHY%d: reset took %ums\n", phy_addr, wait);
-
-	/* Firmware version check. */
-	t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_FW_VERSION, &v);
-	if (v != 101)
-		CH_WARN(adapter, "PHY%d: unsupported firmware %d\n",
-			phy_addr, v);
-
-	/*
-	 * The PHY should start in really-low-power mode.  Prepare it for normal
-	 * operations.
-	 */
-	err = t3_mdio_read(phy, MDIO_MMD_VEND1, MDIO_CTRL1, &v);
-	if (err)
-		return err;
-	if (v & AQ_LOWPOWER) {
-		err = t3_mdio_change_bits(phy, MDIO_MMD_VEND1, MDIO_CTRL1,
-					  AQ_LOWPOWER, 0);
-		if (err)
-			return err;
-		msleep(10);
-	} else
-		CH_WARN(adapter, "PHY%d does not start in low power mode.\n",
-			phy_addr);
-
-	/*
-	 * Verify XAUI settings, but let prep succeed no matter what.
-	 */
-	v = v2 = 0;
-	t3_mdio_read(phy, MDIO_MMD_PHYXS, AQ_XAUI_RX_CFG, &v);
-	t3_mdio_read(phy, MDIO_MMD_PHYXS, AQ_XAUI_TX_CFG, &v2);
-	if (v != 0x1b || v2 != 0x1b)
-		CH_WARN(adapter,
-			"PHY%d: incorrect XAUI settings (0x%x, 0x%x).\n",
-			phy_addr, v, v2);
-
-done:
-	return err;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/common.h linux-libre-3.2-gnu/drivers/net/cxgb3/common.h
--- linux-libre-3.1-gnu/drivers/net/cxgb3/common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/common.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,775 +0,0 @@
-/*
- * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef __CHELSIO_COMMON_H
-#define __CHELSIO_COMMON_H
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/ctype.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/ethtool.h>
-#include <linux/mdio.h>
-#include "version.h"
-
-#define CH_ERR(adap, fmt, ...)   dev_err(&adap->pdev->dev, fmt, ## __VA_ARGS__)
-#define CH_WARN(adap, fmt, ...)  dev_warn(&adap->pdev->dev, fmt, ## __VA_ARGS__)
-#define CH_ALERT(adap, fmt, ...) \
-	dev_printk(KERN_ALERT, &adap->pdev->dev, fmt, ## __VA_ARGS__)
-
-/*
- * More powerful macro that selectively prints messages based on msg_enable.
- * For info and debugging messages.
- */
-#define CH_MSG(adapter, level, category, fmt, ...) do { \
-	if ((adapter)->msg_enable & NETIF_MSG_##category) \
-		dev_printk(KERN_##level, &adapter->pdev->dev, fmt, \
-			   ## __VA_ARGS__); \
-} while (0)
-
-#ifdef DEBUG
-# define CH_DBG(adapter, category, fmt, ...) \
-	CH_MSG(adapter, DEBUG, category, fmt, ## __VA_ARGS__)
-#else
-# define CH_DBG(adapter, category, fmt, ...)
-#endif
-
-/* Additional NETIF_MSG_* categories */
-#define NETIF_MSG_MMIO 0x8000000
-
-enum {
-	MAX_NPORTS = 2,		/* max # of ports */
-	MAX_FRAME_SIZE = 10240,	/* max MAC frame size, including header + FCS */
-	EEPROMSIZE = 8192,	/* Serial EEPROM size */
-	SERNUM_LEN     = 16,    /* Serial # length */
-	RSS_TABLE_SIZE = 64,	/* size of RSS lookup and mapping tables */
-	TCB_SIZE = 128,		/* TCB size */
-	NMTUS = 16,		/* size of MTU table */
-	NCCTRL_WIN = 32,	/* # of congestion control windows */
-	PROTO_SRAM_LINES = 128, /* size of TP sram */
-};
-
-#define MAX_RX_COALESCING_LEN 12288U
-
-enum {
-	PAUSE_RX = 1 << 0,
-	PAUSE_TX = 1 << 1,
-	PAUSE_AUTONEG = 1 << 2
-};
-
-enum {
-	SUPPORTED_IRQ      = 1 << 24
-};
-
-enum {				/* adapter interrupt-maintained statistics */
-	STAT_ULP_CH0_PBL_OOB,
-	STAT_ULP_CH1_PBL_OOB,
-	STAT_PCI_CORR_ECC,
-
-	IRQ_NUM_STATS		/* keep last */
-};
-
-#define TP_VERSION_MAJOR	1
-#define TP_VERSION_MINOR	1
-#define TP_VERSION_MICRO	0
-
-#define S_TP_VERSION_MAJOR		16
-#define M_TP_VERSION_MAJOR		0xFF
-#define V_TP_VERSION_MAJOR(x)		((x) << S_TP_VERSION_MAJOR)
-#define G_TP_VERSION_MAJOR(x)		\
-	    (((x) >> S_TP_VERSION_MAJOR) & M_TP_VERSION_MAJOR)
-
-#define S_TP_VERSION_MINOR		8
-#define M_TP_VERSION_MINOR		0xFF
-#define V_TP_VERSION_MINOR(x)		((x) << S_TP_VERSION_MINOR)
-#define G_TP_VERSION_MINOR(x)		\
-	    (((x) >> S_TP_VERSION_MINOR) & M_TP_VERSION_MINOR)
-
-#define S_TP_VERSION_MICRO		0
-#define M_TP_VERSION_MICRO		0xFF
-#define V_TP_VERSION_MICRO(x)		((x) << S_TP_VERSION_MICRO)
-#define G_TP_VERSION_MICRO(x)		\
-	    (((x) >> S_TP_VERSION_MICRO) & M_TP_VERSION_MICRO)
-
-enum {
-	SGE_QSETS = 8,		/* # of SGE Tx/Rx/RspQ sets */
-	SGE_RXQ_PER_SET = 2,	/* # of Rx queues per set */
-	SGE_TXQ_PER_SET = 3	/* # of Tx queues per set */
-};
-
-enum sge_context_type {		/* SGE egress context types */
-	SGE_CNTXT_RDMA = 0,
-	SGE_CNTXT_ETH = 2,
-	SGE_CNTXT_OFLD = 4,
-	SGE_CNTXT_CTRL = 5
-};
-
-enum {
-	AN_PKT_SIZE = 32,	/* async notification packet size */
-	IMMED_PKT_SIZE = 48	/* packet size for immediate data */
-};
-
-struct sg_ent {			/* SGE scatter/gather entry */
-	__be32 len[2];
-	__be64 addr[2];
-};
-
-#ifndef SGE_NUM_GENBITS
-/* Must be 1 or 2 */
-# define SGE_NUM_GENBITS 2
-#endif
-
-#define TX_DESC_FLITS 16U
-#define WR_FLITS (TX_DESC_FLITS + 1 - SGE_NUM_GENBITS)
-
-struct cphy;
-struct adapter;
-
-struct mdio_ops {
-	int (*read)(struct net_device *dev, int phy_addr, int mmd_addr,
-		    u16 reg_addr);
-	int (*write)(struct net_device *dev, int phy_addr, int mmd_addr,
-		     u16 reg_addr, u16 val);
-	unsigned mode_support;
-};
-
-struct adapter_info {
-	unsigned char nports0;        /* # of ports on channel 0 */
-	unsigned char nports1;        /* # of ports on channel 1 */
-	unsigned char phy_base_addr;	/* MDIO PHY base address */
-	unsigned int gpio_out;	/* GPIO output settings */
-	unsigned char gpio_intr[MAX_NPORTS]; /* GPIO PHY IRQ pins */
-	unsigned long caps;	/* adapter capabilities */
-	const struct mdio_ops *mdio_ops;	/* MDIO operations */
-	const char *desc;	/* product description */
-};
-
-struct mc5_stats {
-	unsigned long parity_err;
-	unsigned long active_rgn_full;
-	unsigned long nfa_srch_err;
-	unsigned long unknown_cmd;
-	unsigned long reqq_parity_err;
-	unsigned long dispq_parity_err;
-	unsigned long del_act_empty;
-};
-
-struct mc7_stats {
-	unsigned long corr_err;
-	unsigned long uncorr_err;
-	unsigned long parity_err;
-	unsigned long addr_err;
-};
-
-struct mac_stats {
-	u64 tx_octets;		/* total # of octets in good frames */
-	u64 tx_octets_bad;	/* total # of octets in error frames */
-	u64 tx_frames;		/* all good frames */
-	u64 tx_mcast_frames;	/* good multicast frames */
-	u64 tx_bcast_frames;	/* good broadcast frames */
-	u64 tx_pause;		/* # of transmitted pause frames */
-	u64 tx_deferred;	/* frames with deferred transmissions */
-	u64 tx_late_collisions;	/* # of late collisions */
-	u64 tx_total_collisions;	/* # of total collisions */
-	u64 tx_excess_collisions;	/* frame errors from excessive collissions */
-	u64 tx_underrun;	/* # of Tx FIFO underruns */
-	u64 tx_len_errs;	/* # of Tx length errors */
-	u64 tx_mac_internal_errs;	/* # of internal MAC errors on Tx */
-	u64 tx_excess_deferral;	/* # of frames with excessive deferral */
-	u64 tx_fcs_errs;	/* # of frames with bad FCS */
-
-	u64 tx_frames_64;	/* # of Tx frames in a particular range */
-	u64 tx_frames_65_127;
-	u64 tx_frames_128_255;
-	u64 tx_frames_256_511;
-	u64 tx_frames_512_1023;
-	u64 tx_frames_1024_1518;
-	u64 tx_frames_1519_max;
-
-	u64 rx_octets;		/* total # of octets in good frames */
-	u64 rx_octets_bad;	/* total # of octets in error frames */
-	u64 rx_frames;		/* all good frames */
-	u64 rx_mcast_frames;	/* good multicast frames */
-	u64 rx_bcast_frames;	/* good broadcast frames */
-	u64 rx_pause;		/* # of received pause frames */
-	u64 rx_fcs_errs;	/* # of received frames with bad FCS */
-	u64 rx_align_errs;	/* alignment errors */
-	u64 rx_symbol_errs;	/* symbol errors */
-	u64 rx_data_errs;	/* data errors */
-	u64 rx_sequence_errs;	/* sequence errors */
-	u64 rx_runt;		/* # of runt frames */
-	u64 rx_jabber;		/* # of jabber frames */
-	u64 rx_short;		/* # of short frames */
-	u64 rx_too_long;	/* # of oversized frames */
-	u64 rx_mac_internal_errs;	/* # of internal MAC errors on Rx */
-
-	u64 rx_frames_64;	/* # of Rx frames in a particular range */
-	u64 rx_frames_65_127;
-	u64 rx_frames_128_255;
-	u64 rx_frames_256_511;
-	u64 rx_frames_512_1023;
-	u64 rx_frames_1024_1518;
-	u64 rx_frames_1519_max;
-
-	u64 rx_cong_drops;	/* # of Rx drops due to SGE congestion */
-
-	unsigned long tx_fifo_parity_err;
-	unsigned long rx_fifo_parity_err;
-	unsigned long tx_fifo_urun;
-	unsigned long rx_fifo_ovfl;
-	unsigned long serdes_signal_loss;
-	unsigned long xaui_pcs_ctc_err;
-	unsigned long xaui_pcs_align_change;
-
-	unsigned long num_toggled; /* # times toggled TxEn due to stuck TX */
-	unsigned long num_resets;  /* # times reset due to stuck TX */
-
-	unsigned long link_faults;  /* # detected link faults */
-};
-
-struct tp_mib_stats {
-	u32 ipInReceive_hi;
-	u32 ipInReceive_lo;
-	u32 ipInHdrErrors_hi;
-	u32 ipInHdrErrors_lo;
-	u32 ipInAddrErrors_hi;
-	u32 ipInAddrErrors_lo;
-	u32 ipInUnknownProtos_hi;
-	u32 ipInUnknownProtos_lo;
-	u32 ipInDiscards_hi;
-	u32 ipInDiscards_lo;
-	u32 ipInDelivers_hi;
-	u32 ipInDelivers_lo;
-	u32 ipOutRequests_hi;
-	u32 ipOutRequests_lo;
-	u32 ipOutDiscards_hi;
-	u32 ipOutDiscards_lo;
-	u32 ipOutNoRoutes_hi;
-	u32 ipOutNoRoutes_lo;
-	u32 ipReasmTimeout;
-	u32 ipReasmReqds;
-	u32 ipReasmOKs;
-	u32 ipReasmFails;
-
-	u32 reserved[8];
-
-	u32 tcpActiveOpens;
-	u32 tcpPassiveOpens;
-	u32 tcpAttemptFails;
-	u32 tcpEstabResets;
-	u32 tcpOutRsts;
-	u32 tcpCurrEstab;
-	u32 tcpInSegs_hi;
-	u32 tcpInSegs_lo;
-	u32 tcpOutSegs_hi;
-	u32 tcpOutSegs_lo;
-	u32 tcpRetransSeg_hi;
-	u32 tcpRetransSeg_lo;
-	u32 tcpInErrs_hi;
-	u32 tcpInErrs_lo;
-	u32 tcpRtoMin;
-	u32 tcpRtoMax;
-};
-
-struct tp_params {
-	unsigned int nchan;	/* # of channels */
-	unsigned int pmrx_size;	/* total PMRX capacity */
-	unsigned int pmtx_size;	/* total PMTX capacity */
-	unsigned int cm_size;	/* total CM capacity */
-	unsigned int chan_rx_size;	/* per channel Rx size */
-	unsigned int chan_tx_size;	/* per channel Tx size */
-	unsigned int rx_pg_size;	/* Rx page size */
-	unsigned int tx_pg_size;	/* Tx page size */
-	unsigned int rx_num_pgs;	/* # of Rx pages */
-	unsigned int tx_num_pgs;	/* # of Tx pages */
-	unsigned int ntimer_qs;	/* # of timer queues */
-};
-
-struct qset_params {		/* SGE queue set parameters */
-	unsigned int polling;	/* polling/interrupt service for rspq */
-	unsigned int coalesce_usecs;	/* irq coalescing timer */
-	unsigned int rspq_size;	/* # of entries in response queue */
-	unsigned int fl_size;	/* # of entries in regular free list */
-	unsigned int jumbo_size;	/* # of entries in jumbo free list */
-	unsigned int txq_size[SGE_TXQ_PER_SET];	/* Tx queue sizes */
-	unsigned int cong_thres;	/* FL congestion threshold */
-	unsigned int vector;		/* Interrupt (line or vector) number */
-};
-
-struct sge_params {
-	unsigned int max_pkt_size;	/* max offload pkt size */
-	struct qset_params qset[SGE_QSETS];
-};
-
-struct mc5_params {
-	unsigned int mode;	/* selects MC5 width */
-	unsigned int nservers;	/* size of server region */
-	unsigned int nfilters;	/* size of filter region */
-	unsigned int nroutes;	/* size of routing region */
-};
-
-/* Default MC5 region sizes */
-enum {
-	DEFAULT_NSERVERS = 512,
-	DEFAULT_NFILTERS = 128
-};
-
-/* MC5 modes, these must be non-0 */
-enum {
-	MC5_MODE_144_BIT = 1,
-	MC5_MODE_72_BIT = 2
-};
-
-/* MC5 min active region size */
-enum { MC5_MIN_TIDS = 16 };
-
-struct vpd_params {
-	unsigned int cclk;
-	unsigned int mclk;
-	unsigned int uclk;
-	unsigned int mdc;
-	unsigned int mem_timing;
-	u8 sn[SERNUM_LEN + 1];
-	u8 eth_base[6];
-	u8 port_type[MAX_NPORTS];
-	unsigned short xauicfg[2];
-};
-
-struct pci_params {
-	unsigned int vpd_cap_addr;
-	unsigned short speed;
-	unsigned char width;
-	unsigned char variant;
-};
-
-enum {
-	PCI_VARIANT_PCI,
-	PCI_VARIANT_PCIX_MODE1_PARITY,
-	PCI_VARIANT_PCIX_MODE1_ECC,
-	PCI_VARIANT_PCIX_266_MODE2,
-	PCI_VARIANT_PCIE
-};
-
-struct adapter_params {
-	struct sge_params sge;
-	struct mc5_params mc5;
-	struct tp_params tp;
-	struct vpd_params vpd;
-	struct pci_params pci;
-
-	const struct adapter_info *info;
-
-	unsigned short mtus[NMTUS];
-	unsigned short a_wnd[NCCTRL_WIN];
-	unsigned short b_wnd[NCCTRL_WIN];
-
-	unsigned int nports;	/* # of ethernet ports */
-	unsigned int chan_map;  /* bitmap of in-use Tx channels */
-	unsigned int stats_update_period;	/* MAC stats accumulation period */
-	unsigned int linkpoll_period;	/* link poll period in 0.1s */
-	unsigned int rev;	/* chip revision */
-	unsigned int offload;
-};
-
-enum {					    /* chip revisions */
-	T3_REV_A  = 0,
-	T3_REV_B  = 2,
-	T3_REV_B2 = 3,
-	T3_REV_C  = 4,
-};
-
-struct trace_params {
-	u32 sip;
-	u32 sip_mask;
-	u32 dip;
-	u32 dip_mask;
-	u16 sport;
-	u16 sport_mask;
-	u16 dport;
-	u16 dport_mask;
-	u32 vlan:12;
-	u32 vlan_mask:12;
-	u32 intf:4;
-	u32 intf_mask:4;
-	u8 proto;
-	u8 proto_mask;
-};
-
-struct link_config {
-	unsigned int supported;	/* link capabilities */
-	unsigned int advertising;	/* advertised capabilities */
-	unsigned short requested_speed;	/* speed user has requested */
-	unsigned short speed;	/* actual link speed */
-	unsigned char requested_duplex;	/* duplex user has requested */
-	unsigned char duplex;	/* actual link duplex */
-	unsigned char requested_fc;	/* flow control user has requested */
-	unsigned char fc;	/* actual link flow control */
-	unsigned char autoneg;	/* autonegotiating? */
-	unsigned int link_ok;	/* link up? */
-};
-
-#define SPEED_INVALID   0xffff
-#define DUPLEX_INVALID  0xff
-
-struct mc5 {
-	struct adapter *adapter;
-	unsigned int tcam_size;
-	unsigned char part_type;
-	unsigned char parity_enabled;
-	unsigned char mode;
-	struct mc5_stats stats;
-};
-
-static inline unsigned int t3_mc5_size(const struct mc5 *p)
-{
-	return p->tcam_size;
-}
-
-struct mc7 {
-	struct adapter *adapter;	/* backpointer to adapter */
-	unsigned int size;	/* memory size in bytes */
-	unsigned int width;	/* MC7 interface width */
-	unsigned int offset;	/* register address offset for MC7 instance */
-	const char *name;	/* name of MC7 instance */
-	struct mc7_stats stats;	/* MC7 statistics */
-};
-
-static inline unsigned int t3_mc7_size(const struct mc7 *p)
-{
-	return p->size;
-}
-
-struct cmac {
-	struct adapter *adapter;
-	unsigned int offset;
-	unsigned int nucast;	/* # of address filters for unicast MACs */
-	unsigned int tx_tcnt;
-	unsigned int tx_xcnt;
-	u64 tx_mcnt;
-	unsigned int rx_xcnt;
-	unsigned int rx_ocnt;
-	u64 rx_mcnt;
-	unsigned int toggle_cnt;
-	unsigned int txen;
-	u64 rx_pause;
-	struct mac_stats stats;
-};
-
-enum {
-	MAC_DIRECTION_RX = 1,
-	MAC_DIRECTION_TX = 2,
-	MAC_RXFIFO_SIZE = 32768
-};
-
-/* PHY loopback direction */
-enum {
-	PHY_LOOPBACK_TX = 1,
-	PHY_LOOPBACK_RX = 2
-};
-
-/* PHY interrupt types */
-enum {
-	cphy_cause_link_change = 1,
-	cphy_cause_fifo_error = 2,
-	cphy_cause_module_change = 4,
-};
-
-/* PHY module types */
-enum {
-	phy_modtype_none,
-	phy_modtype_sr,
-	phy_modtype_lr,
-	phy_modtype_lrm,
-	phy_modtype_twinax,
-	phy_modtype_twinax_long,
-	phy_modtype_unknown
-};
-
-/* PHY operations */
-struct cphy_ops {
-	int (*reset)(struct cphy *phy, int wait);
-
-	int (*intr_enable)(struct cphy *phy);
-	int (*intr_disable)(struct cphy *phy);
-	int (*intr_clear)(struct cphy *phy);
-	int (*intr_handler)(struct cphy *phy);
-
-	int (*autoneg_enable)(struct cphy *phy);
-	int (*autoneg_restart)(struct cphy *phy);
-
-	int (*advertise)(struct cphy *phy, unsigned int advertise_map);
-	int (*set_loopback)(struct cphy *phy, int mmd, int dir, int enable);
-	int (*set_speed_duplex)(struct cphy *phy, int speed, int duplex);
-	int (*get_link_status)(struct cphy *phy, int *link_ok, int *speed,
-			       int *duplex, int *fc);
-	int (*power_down)(struct cphy *phy, int enable);
-
-	u32 mmds;
-};
-enum {
-	EDC_OPT_AEL2005 = 0,
-	EDC_OPT_AEL2005_SIZE = 1084,
-	EDC_TWX_AEL2005 = 1,
-	EDC_TWX_AEL2005_SIZE = 1464,
-	EDC_TWX_AEL2020 = 2,
-	EDC_TWX_AEL2020_SIZE = 1628,
-	EDC_MAX_SIZE = EDC_TWX_AEL2020_SIZE, /* Max cache size */
-};
-
-/* A PHY instance */
-struct cphy {
-	u8 modtype;			/* PHY module type */
-	short priv;			/* scratch pad */
-	unsigned int caps;		/* PHY capabilities */
-	struct adapter *adapter;	/* associated adapter */
-	const char *desc;		/* PHY description */
-	unsigned long fifo_errors;	/* FIFO over/under-flows */
-	const struct cphy_ops *ops;	/* PHY operations */
-	struct mdio_if_info mdio;
-	u16 phy_cache[EDC_MAX_SIZE];	/* EDC cache */
-};
-
-/* Convenience MDIO read/write wrappers */
-static inline int t3_mdio_read(struct cphy *phy, int mmd, int reg,
-			       unsigned int *valp)
-{
-	int rc = phy->mdio.mdio_read(phy->mdio.dev, phy->mdio.prtad, mmd, reg);
-	*valp = (rc >= 0) ? rc : -1;
-	return (rc >= 0) ? 0 : rc;
-}
-
-static inline int t3_mdio_write(struct cphy *phy, int mmd, int reg,
-				unsigned int val)
-{
-	return phy->mdio.mdio_write(phy->mdio.dev, phy->mdio.prtad, mmd,
-				    reg, val);
-}
-
-/* Convenience initializer */
-static inline void cphy_init(struct cphy *phy, struct adapter *adapter,
-			     int phy_addr, struct cphy_ops *phy_ops,
-			     const struct mdio_ops *mdio_ops,
-			      unsigned int caps, const char *desc)
-{
-	phy->caps = caps;
-	phy->adapter = adapter;
-	phy->desc = desc;
-	phy->ops = phy_ops;
-	if (mdio_ops) {
-		phy->mdio.prtad = phy_addr;
-		phy->mdio.mmds = phy_ops->mmds;
-		phy->mdio.mode_support = mdio_ops->mode_support;
-		phy->mdio.mdio_read = mdio_ops->read;
-		phy->mdio.mdio_write = mdio_ops->write;
-	}
-}
-
-/* Accumulate MAC statistics every 180 seconds.  For 1G we multiply by 10. */
-#define MAC_STATS_ACCUM_SECS 180
-
-#define XGM_REG(reg_addr, idx) \
-	((reg_addr) + (idx) * (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR))
-
-struct addr_val_pair {
-	unsigned int reg_addr;
-	unsigned int val;
-};
-
-#include "adapter.h"
-
-#ifndef PCI_VENDOR_ID_CHELSIO
-# define PCI_VENDOR_ID_CHELSIO 0x1425
-#endif
-
-#define for_each_port(adapter, iter) \
-	for (iter = 0; iter < (adapter)->params.nports; ++iter)
-
-#define adapter_info(adap) ((adap)->params.info)
-
-static inline int uses_xaui(const struct adapter *adap)
-{
-	return adapter_info(adap)->caps & SUPPORTED_AUI;
-}
-
-static inline int is_10G(const struct adapter *adap)
-{
-	return adapter_info(adap)->caps & SUPPORTED_10000baseT_Full;
-}
-
-static inline int is_offload(const struct adapter *adap)
-{
-	return adap->params.offload;
-}
-
-static inline unsigned int core_ticks_per_usec(const struct adapter *adap)
-{
-	return adap->params.vpd.cclk / 1000;
-}
-
-static inline unsigned int is_pcie(const struct adapter *adap)
-{
-	return adap->params.pci.variant == PCI_VARIANT_PCIE;
-}
-
-void t3_set_reg_field(struct adapter *adap, unsigned int addr, u32 mask,
-		      u32 val);
-void t3_write_regs(struct adapter *adapter, const struct addr_val_pair *p,
-		   int n, unsigned int offset);
-int t3_wait_op_done_val(struct adapter *adapter, int reg, u32 mask,
-			int polarity, int attempts, int delay, u32 *valp);
-static inline int t3_wait_op_done(struct adapter *adapter, int reg, u32 mask,
-				  int polarity, int attempts, int delay)
-{
-	return t3_wait_op_done_val(adapter, reg, mask, polarity, attempts,
-				   delay, NULL);
-}
-int t3_mdio_change_bits(struct cphy *phy, int mmd, int reg, unsigned int clear,
-			unsigned int set);
-int t3_phy_reset(struct cphy *phy, int mmd, int wait);
-int t3_phy_advertise(struct cphy *phy, unsigned int advert);
-int t3_phy_advertise_fiber(struct cphy *phy, unsigned int advert);
-int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex);
-int t3_phy_lasi_intr_enable(struct cphy *phy);
-int t3_phy_lasi_intr_disable(struct cphy *phy);
-int t3_phy_lasi_intr_clear(struct cphy *phy);
-int t3_phy_lasi_intr_handler(struct cphy *phy);
-
-void t3_intr_enable(struct adapter *adapter);
-void t3_intr_disable(struct adapter *adapter);
-void t3_intr_clear(struct adapter *adapter);
-void t3_xgm_intr_enable(struct adapter *adapter, int idx);
-void t3_xgm_intr_disable(struct adapter *adapter, int idx);
-void t3_port_intr_enable(struct adapter *adapter, int idx);
-void t3_port_intr_disable(struct adapter *adapter, int idx);
-int t3_slow_intr_handler(struct adapter *adapter);
-int t3_phy_intr_handler(struct adapter *adapter);
-
-void t3_link_changed(struct adapter *adapter, int port_id);
-void t3_link_fault(struct adapter *adapter, int port_id);
-int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc);
-const struct adapter_info *t3_get_adapter_info(unsigned int board_id);
-int t3_seeprom_read(struct adapter *adapter, u32 addr, __le32 *data);
-int t3_seeprom_write(struct adapter *adapter, u32 addr, __le32 data);
-int t3_seeprom_wp(struct adapter *adapter, int enable);
-int t3_get_tp_version(struct adapter *adapter, u32 *vers);
-int t3_check_tpsram_version(struct adapter *adapter);
-int t3_check_tpsram(struct adapter *adapter, const u8 *tp_ram,
-		    unsigned int size);
-int t3_set_proto_sram(struct adapter *adap, const u8 *data);
-int t3_load_fw(struct adapter *adapter, const u8 * fw_data, unsigned int size);
-int t3_get_fw_version(struct adapter *adapter, u32 *vers);
-int t3_check_fw_version(struct adapter *adapter);
-int t3_init_hw(struct adapter *adapter, u32 fw_params);
-int t3_reset_adapter(struct adapter *adapter);
-int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
-		    int reset);
-int t3_replay_prep_adapter(struct adapter *adapter);
-void t3_led_ready(struct adapter *adapter);
-void t3_fatal_err(struct adapter *adapter);
-void t3_set_vlan_accel(struct adapter *adapter, unsigned int ports, int on);
-void t3_config_rss(struct adapter *adapter, unsigned int rss_config,
-		   const u8 * cpus, const u16 *rspq);
-int t3_cim_ctl_blk_read(struct adapter *adap, unsigned int addr,
-			unsigned int n, unsigned int *valp);
-int t3_mc7_bd_read(struct mc7 *mc7, unsigned int start, unsigned int n,
-		   u64 *buf);
-
-int t3_mac_reset(struct cmac *mac);
-void t3b_pcs_reset(struct cmac *mac);
-void t3_mac_disable_exact_filters(struct cmac *mac);
-void t3_mac_enable_exact_filters(struct cmac *mac);
-int t3_mac_enable(struct cmac *mac, int which);
-int t3_mac_disable(struct cmac *mac, int which);
-int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu);
-int t3_mac_set_rx_mode(struct cmac *mac, struct net_device *dev);
-int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6]);
-int t3_mac_set_num_ucast(struct cmac *mac, int n);
-const struct mac_stats *t3_mac_update_stats(struct cmac *mac);
-int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc);
-int t3b2_mac_watchdog_task(struct cmac *mac);
-
-void t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode);
-int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
-		unsigned int nroutes);
-void t3_mc5_intr_handler(struct mc5 *mc5);
-
-void t3_tp_set_offload_mode(struct adapter *adap, int enable);
-void t3_tp_get_mib_stats(struct adapter *adap, struct tp_mib_stats *tps);
-void t3_load_mtus(struct adapter *adap, unsigned short mtus[NMTUS],
-		  unsigned short alpha[NCCTRL_WIN],
-		  unsigned short beta[NCCTRL_WIN], unsigned short mtu_cap);
-void t3_config_trace_filter(struct adapter *adapter,
-			    const struct trace_params *tp, int filter_index,
-			    int invert, int enable);
-int t3_config_sched(struct adapter *adap, unsigned int kbps, int sched);
-
-void t3_sge_prep(struct adapter *adap, struct sge_params *p);
-void t3_sge_init(struct adapter *adap, struct sge_params *p);
-int t3_sge_init_ecntxt(struct adapter *adapter, unsigned int id, int gts_enable,
-		       enum sge_context_type type, int respq, u64 base_addr,
-		       unsigned int size, unsigned int token, int gen,
-		       unsigned int cidx);
-int t3_sge_init_flcntxt(struct adapter *adapter, unsigned int id,
-			int gts_enable, u64 base_addr, unsigned int size,
-			unsigned int esize, unsigned int cong_thres, int gen,
-			unsigned int cidx);
-int t3_sge_init_rspcntxt(struct adapter *adapter, unsigned int id,
-			 int irq_vec_idx, u64 base_addr, unsigned int size,
-			 unsigned int fl_thres, int gen, unsigned int cidx);
-int t3_sge_init_cqcntxt(struct adapter *adapter, unsigned int id, u64 base_addr,
-			unsigned int size, int rspq, int ovfl_mode,
-			unsigned int credits, unsigned int credit_thres);
-int t3_sge_enable_ecntxt(struct adapter *adapter, unsigned int id, int enable);
-int t3_sge_disable_fl(struct adapter *adapter, unsigned int id);
-int t3_sge_disable_rspcntxt(struct adapter *adapter, unsigned int id);
-int t3_sge_disable_cqcntxt(struct adapter *adapter, unsigned int id);
-int t3_sge_cqcntxt_op(struct adapter *adapter, unsigned int id, unsigned int op,
-		      unsigned int credits);
-
-int t3_vsc8211_phy_prep(struct cphy *phy, struct adapter *adapter,
-			int phy_addr, const struct mdio_ops *mdio_ops);
-int t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter,
-			int phy_addr, const struct mdio_ops *mdio_ops);
-int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter,
-			int phy_addr, const struct mdio_ops *mdio_ops);
-int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter,
-			int phy_addr, const struct mdio_ops *mdio_ops);
-int t3_ael2020_phy_prep(struct cphy *phy, struct adapter *adapter,
-			int phy_addr, const struct mdio_ops *mdio_ops);
-int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr,
-		       const struct mdio_ops *mdio_ops);
-int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
-			    int phy_addr, const struct mdio_ops *mdio_ops);
-int t3_aq100x_phy_prep(struct cphy *phy, struct adapter *adapter,
-			    int phy_addr, const struct mdio_ops *mdio_ops);
-#endif				/* __CHELSIO_COMMON_H */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/cxgb3_ctl_defs.h linux-libre-3.2-gnu/drivers/net/cxgb3/cxgb3_ctl_defs.h
--- linux-libre-3.1-gnu/drivers/net/cxgb3/cxgb3_ctl_defs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/cxgb3_ctl_defs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,189 +0,0 @@
-/*
- * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef _CXGB3_OFFLOAD_CTL_DEFS_H
-#define _CXGB3_OFFLOAD_CTL_DEFS_H
-
-enum {
-	GET_MAX_OUTSTANDING_WR 	= 0,
-	GET_TX_MAX_CHUNK	= 1,
-	GET_TID_RANGE		= 2,
-	GET_STID_RANGE		= 3,
-	GET_RTBL_RANGE		= 4,
-	GET_L2T_CAPACITY	= 5,
-	GET_MTUS		= 6,
-	GET_WR_LEN		= 7,
-	GET_IFF_FROM_MAC	= 8,
-	GET_DDP_PARAMS		= 9,
-	GET_PORTS		= 10,
-
-	ULP_ISCSI_GET_PARAMS	= 11,
-	ULP_ISCSI_SET_PARAMS	= 12,
-
-	RDMA_GET_PARAMS		= 13,
-	RDMA_CQ_OP		= 14,
-	RDMA_CQ_SETUP		= 15,
-	RDMA_CQ_DISABLE		= 16,
-	RDMA_CTRL_QP_SETUP	= 17,
-	RDMA_GET_MEM		= 18,
-	RDMA_GET_MIB		= 19,
-
-	GET_RX_PAGE_INFO	= 50,
-	GET_ISCSI_IPV4ADDR	= 51,
-
-	GET_EMBEDDED_INFO	= 70,
-};
-
-/*
- * Structure used to describe a TID range.  Valid TIDs are [base, base+num).
- */
-struct tid_range {
-	unsigned int base;	/* first TID */
-	unsigned int num;	/* number of TIDs in range */
-};
-
-/*
- * Structure used to request the size and contents of the MTU table.
- */
-struct mtutab {
-	unsigned int size;	/* # of entries in the MTU table */
-	const unsigned short *mtus;	/* the MTU table values */
-};
-
-struct net_device;
-
-/*
- * Structure used to request the adapter net_device owning a given MAC address.
- */
-struct iff_mac {
-	struct net_device *dev;	/* the net_device */
-	const unsigned char *mac_addr;	/* MAC address to lookup */
-	u16 vlan_tag;
-};
-
-/* Structure used to request a port's iSCSI IPv4 address */
-struct iscsi_ipv4addr {
-	struct net_device *dev;	/* the net_device */
-	__be32 ipv4addr;	/* the return iSCSI IPv4 address */
-};
-
-struct pci_dev;
-
-/*
- * Structure used to request the TCP DDP parameters.
- */
-struct ddp_params {
-	unsigned int llimit;	/* TDDP region start address */
-	unsigned int ulimit;	/* TDDP region end address */
-	unsigned int tag_mask;	/* TDDP tag mask */
-	struct pci_dev *pdev;
-};
-
-struct adap_ports {
-	unsigned int nports;	/* number of ports on this adapter */
-	struct net_device *lldevs[2];
-};
-
-/*
- * Structure used to return information to the iscsi layer.
- */
-struct ulp_iscsi_info {
-	unsigned int offset;
-	unsigned int llimit;
-	unsigned int ulimit;
-	unsigned int tagmask;
-	u8 pgsz_factor[4];
-	unsigned int max_rxsz;
-	unsigned int max_txsz;
-	struct pci_dev *pdev;
-};
-
-/*
- * Structure used to return information to the RDMA layer.
- */
-struct rdma_info {
-	unsigned int tpt_base;	/* TPT base address */
-	unsigned int tpt_top;	/* TPT last entry address */
-	unsigned int pbl_base;	/* PBL base address */
-	unsigned int pbl_top;	/* PBL last entry address */
-	unsigned int rqt_base;	/* RQT base address */
-	unsigned int rqt_top;	/* RQT last entry address */
-	unsigned int udbell_len;	/* user doorbell region length */
-	unsigned long udbell_physbase;	/* user doorbell physical start addr */
-	void __iomem *kdb_addr;	/* kernel doorbell register address */
-	struct pci_dev *pdev;	/* associated PCI device */
-};
-
-/*
- * Structure used to request an operation on an RDMA completion queue.
- */
-struct rdma_cq_op {
-	unsigned int id;
-	unsigned int op;
-	unsigned int credits;
-};
-
-/*
- * Structure used to setup RDMA completion queues.
- */
-struct rdma_cq_setup {
-	unsigned int id;
-	unsigned long long base_addr;
-	unsigned int size;
-	unsigned int credits;
-	unsigned int credit_thres;
-	unsigned int ovfl_mode;
-};
-
-/*
- * Structure used to setup the RDMA control egress context.
- */
-struct rdma_ctrlqp_setup {
-	unsigned long long base_addr;
-	unsigned int size;
-};
-
-/*
- * Offload TX/RX page information.
- */
-struct ofld_page_info {
-	unsigned int page_size;  /* Page size, should be a power of 2 */
-	unsigned int num;        /* Number of pages */
-};
-
-/*
- * Structure used to get firmware and protocol engine versions.
- */
-struct ch_embedded_info {
-	u32 fw_vers;
-	u32 tp_vers;
-};
-#endif				/* _CXGB3_OFFLOAD_CTL_DEFS_H */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/cxgb3_defs.h linux-libre-3.2-gnu/drivers/net/cxgb3/cxgb3_defs.h
--- linux-libre-3.1-gnu/drivers/net/cxgb3/cxgb3_defs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/cxgb3_defs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2006-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef _CHELSIO_DEFS_H
-#define _CHELSIO_DEFS_H
-
-#include <linux/skbuff.h>
-#include <net/tcp.h>
-
-#include "t3cdev.h"
-
-#include "cxgb3_offload.h"
-
-#define VALIDATE_TID 1
-
-void *cxgb_alloc_mem(unsigned long size);
-void cxgb_free_mem(void *addr);
-
-/*
- * Map an ATID or STID to their entries in the corresponding TID tables.
- */
-static inline union active_open_entry *atid2entry(const struct tid_info *t,
-						  unsigned int atid)
-{
-	return &t->atid_tab[atid - t->atid_base];
-}
-
-static inline union listen_entry *stid2entry(const struct tid_info *t,
-					     unsigned int stid)
-{
-	return &t->stid_tab[stid - t->stid_base];
-}
-
-/*
- * Find the connection corresponding to a TID.
- */
-static inline struct t3c_tid_entry *lookup_tid(const struct tid_info *t,
-					       unsigned int tid)
-{
-	struct t3c_tid_entry *t3c_tid = tid < t->ntids ?
-	    &(t->tid_tab[tid]) : NULL;
-
-	return (t3c_tid && t3c_tid->client) ? t3c_tid : NULL;
-}
-
-/*
- * Find the connection corresponding to a server TID.
- */
-static inline struct t3c_tid_entry *lookup_stid(const struct tid_info *t,
-						unsigned int tid)
-{
-	union listen_entry *e;
-
-	if (tid < t->stid_base || tid >= t->stid_base + t->nstids)
-		return NULL;
-
-	e = stid2entry(t, tid);
-	if ((void *)e->next >= (void *)t->tid_tab &&
-	    (void *)e->next < (void *)&t->atid_tab[t->natids])
-		return NULL;
-
-	return &e->t3c_tid;
-}
-
-/*
- * Find the connection corresponding to an active-open TID.
- */
-static inline struct t3c_tid_entry *lookup_atid(const struct tid_info *t,
-						unsigned int tid)
-{
-	union active_open_entry *e;
-
-	if (tid < t->atid_base || tid >= t->atid_base + t->natids)
-		return NULL;
-
-	e = atid2entry(t, tid);
-	if ((void *)e->next >= (void *)t->tid_tab &&
-	    (void *)e->next < (void *)&t->atid_tab[t->natids])
-		return NULL;
-
-	return &e->t3c_tid;
-}
-
-int attach_t3cdev(struct t3cdev *dev);
-void detach_t3cdev(struct t3cdev *dev);
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/cxgb3_ioctl.h linux-libre-3.2-gnu/drivers/net/cxgb3/cxgb3_ioctl.h
--- linux-libre-3.1-gnu/drivers/net/cxgb3/cxgb3_ioctl.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/cxgb3_ioctl.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef __CHIOCTL_H__
-#define __CHIOCTL_H__
-
-/*
- * Ioctl commands specific to this driver.
- */
-enum {
-	CHELSIO_GETMTUTAB 		= 1029,
-	CHELSIO_SETMTUTAB 		= 1030,
-	CHELSIO_SET_PM 			= 1032,
-	CHELSIO_GET_PM			= 1033,
-	CHELSIO_GET_MEM			= 1038,
-	CHELSIO_LOAD_FW			= 1041,
-	CHELSIO_SET_TRACE_FILTER	= 1044,
-	CHELSIO_SET_QSET_PARAMS		= 1045,
-	CHELSIO_GET_QSET_PARAMS		= 1046,
-	CHELSIO_SET_QSET_NUM		= 1047,
-	CHELSIO_GET_QSET_NUM		= 1048,
-};
-
-struct ch_reg {
-	uint32_t cmd;
-	uint32_t addr;
-	uint32_t val;
-};
-
-struct ch_cntxt {
-	uint32_t cmd;
-	uint32_t cntxt_type;
-	uint32_t cntxt_id;
-	uint32_t data[4];
-};
-
-/* context types */
-enum { CNTXT_TYPE_EGRESS, CNTXT_TYPE_FL, CNTXT_TYPE_RSP, CNTXT_TYPE_CQ };
-
-struct ch_desc {
-	uint32_t cmd;
-	uint32_t queue_num;
-	uint32_t idx;
-	uint32_t size;
-	uint8_t data[128];
-};
-
-struct ch_mem_range {
-	uint32_t cmd;
-	uint32_t mem_id;
-	uint32_t addr;
-	uint32_t len;
-	uint32_t version;
-	uint8_t buf[0];
-};
-
-struct ch_qset_params {
-	uint32_t cmd;
-	uint32_t qset_idx;
-	int32_t txq_size[3];
-	int32_t rspq_size;
-	int32_t fl_size[2];
-	int32_t intr_lat;
-	int32_t polling;
-	int32_t lro;
-	int32_t cong_thres;
-	int32_t  vector;
-	int32_t  qnum;
-};
-
-struct ch_pktsched_params {
-	uint32_t cmd;
-	uint8_t sched;
-	uint8_t idx;
-	uint8_t min;
-	uint8_t max;
-	uint8_t binding;
-};
-
-#ifndef TCB_SIZE
-# define TCB_SIZE   128
-#endif
-
-/* TCB size in 32-bit words */
-#define TCB_WORDS (TCB_SIZE / 4)
-
-enum { MEM_CM, MEM_PMRX, MEM_PMTX };	/* ch_mem_range.mem_id values */
-
-struct ch_mtus {
-	uint32_t cmd;
-	uint32_t nmtus;
-	uint16_t mtus[NMTUS];
-};
-
-struct ch_pm {
-	uint32_t cmd;
-	uint32_t tx_pg_sz;
-	uint32_t tx_num_pg;
-	uint32_t rx_pg_sz;
-	uint32_t rx_num_pg;
-	uint32_t pm_total;
-};
-
-struct ch_tcam {
-	uint32_t cmd;
-	uint32_t tcam_size;
-	uint32_t nservers;
-	uint32_t nroutes;
-	uint32_t nfilters;
-};
-
-struct ch_tcb {
-	uint32_t cmd;
-	uint32_t tcb_index;
-	uint32_t tcb_data[TCB_WORDS];
-};
-
-struct ch_tcam_word {
-	uint32_t cmd;
-	uint32_t addr;
-	uint32_t buf[3];
-};
-
-struct ch_trace {
-	uint32_t cmd;
-	uint32_t sip;
-	uint32_t sip_mask;
-	uint32_t dip;
-	uint32_t dip_mask;
-	uint16_t sport;
-	uint16_t sport_mask;
-	uint16_t dport;
-	uint16_t dport_mask;
-	uint32_t vlan:12;
-	uint32_t vlan_mask:12;
-	uint32_t intf:4;
-	uint32_t intf_mask:4;
-	uint8_t proto;
-	uint8_t proto_mask;
-	uint8_t invert_match:1;
-	uint8_t config_tx:1;
-	uint8_t config_rx:1;
-	uint8_t trace_tx:1;
-	uint8_t trace_rx:1;
-};
-
-#define SIOCCHIOCTL SIOCDEVPRIVATE
-
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/cxgb3_main.c linux-libre-3.2-gnu/drivers/net/cxgb3/cxgb3_main.c
--- linux-libre-3.1-gnu/drivers/net/cxgb3/cxgb3_main.c	2012-03-19 21:43:55.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/cxgb3_main.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3441 +0,0 @@
-/*
- * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_vlan.h>
-#include <linux/mdio.h>
-#include <linux/sockios.h>
-#include <linux/workqueue.h>
-#include <linux/proc_fs.h>
-#include <linux/rtnetlink.h>
-#include <linux/firmware.h>
-#include <linux/log2.h>
-#include <linux/stringify.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <asm/uaccess.h>
-
-#include "common.h"
-#include "cxgb3_ioctl.h"
-#include "regs.h"
-#include "cxgb3_offload.h"
-#include "version.h"
-
-#include "cxgb3_ctl_defs.h"
-#include "t3_cpl.h"
-#include "firmware_exports.h"
-
-enum {
-	MAX_TXQ_ENTRIES = 16384,
-	MAX_CTRL_TXQ_ENTRIES = 1024,
-	MAX_RSPQ_ENTRIES = 16384,
-	MAX_RX_BUFFERS = 16384,
-	MAX_RX_JUMBO_BUFFERS = 16384,
-	MIN_TXQ_ENTRIES = 4,
-	MIN_CTRL_TXQ_ENTRIES = 4,
-	MIN_RSPQ_ENTRIES = 32,
-	MIN_FL_ENTRIES = 32
-};
-
-#define PORT_MASK ((1 << MAX_NPORTS) - 1)
-
-#define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \
-			 NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\
-			 NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
-
-#define EEPROM_MAGIC 0x38E2F10C
-
-#define CH_DEVICE(devid, idx) \
-	{ PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, PCI_ANY_ID, 0, 0, idx }
-
-static DEFINE_PCI_DEVICE_TABLE(cxgb3_pci_tbl) = {
-	CH_DEVICE(0x20, 0),	/* PE9000 */
-	CH_DEVICE(0x21, 1),	/* T302E */
-	CH_DEVICE(0x22, 2),	/* T310E */
-	CH_DEVICE(0x23, 3),	/* T320X */
-	CH_DEVICE(0x24, 1),	/* T302X */
-	CH_DEVICE(0x25, 3),	/* T320E */
-	CH_DEVICE(0x26, 2),	/* T310X */
-	CH_DEVICE(0x30, 2),	/* T3B10 */
-	CH_DEVICE(0x31, 3),	/* T3B20 */
-	CH_DEVICE(0x32, 1),	/* T3B02 */
-	CH_DEVICE(0x35, 6),	/* T3C20-derived T3C10 */
-	CH_DEVICE(0x36, 3),	/* S320E-CR */
-	CH_DEVICE(0x37, 7),	/* N320E-G2 */
-	{0,}
-};
-
-MODULE_DESCRIPTION(DRV_DESC);
-MODULE_AUTHOR("Chelsio Communications");
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_VERSION(DRV_VERSION);
-MODULE_DEVICE_TABLE(pci, cxgb3_pci_tbl);
-
-static int dflt_msg_enable = DFLT_MSG_ENABLE;
-
-module_param(dflt_msg_enable, int, 0644);
-MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T3 default message enable bitmap");
-
-/*
- * The driver uses the best interrupt scheme available on a platform in the
- * order MSI-X, MSI, legacy pin interrupts.  This parameter determines which
- * of these schemes the driver may consider as follows:
- *
- * msi = 2: choose from among all three options
- * msi = 1: only consider MSI and pin interrupts
- * msi = 0: force pin interrupts
- */
-static int msi = 2;
-
-module_param(msi, int, 0644);
-MODULE_PARM_DESC(msi, "whether to use MSI or MSI-X");
-
-/*
- * The driver enables offload as a default.
- * To disable it, use ofld_disable = 1.
- */
-
-static int ofld_disable = 0;
-
-module_param(ofld_disable, int, 0644);
-MODULE_PARM_DESC(ofld_disable, "whether to enable offload at init time or not");
-
-/*
- * We have work elements that we need to cancel when an interface is taken
- * down.  Normally the work elements would be executed by keventd but that
- * can deadlock because of linkwatch.  If our close method takes the rtnl
- * lock and linkwatch is ahead of our work elements in keventd, linkwatch
- * will block keventd as it needs the rtnl lock, and we'll deadlock waiting
- * for our work to complete.  Get our own work queue to solve this.
- */
-struct workqueue_struct *cxgb3_wq;
-
-/**
- *	link_report - show link status and link speed/duplex
- *	@p: the port whose settings are to be reported
- *
- *	Shows the link status, speed, and duplex of a port.
- */
-static void link_report(struct net_device *dev)
-{
-	if (!netif_carrier_ok(dev))
-		printk(KERN_INFO "%s: link down\n", dev->name);
-	else {
-		const char *s = "10Mbps";
-		const struct port_info *p = netdev_priv(dev);
-
-		switch (p->link_config.speed) {
-		case SPEED_10000:
-			s = "10Gbps";
-			break;
-		case SPEED_1000:
-			s = "1000Mbps";
-			break;
-		case SPEED_100:
-			s = "100Mbps";
-			break;
-		}
-
-		printk(KERN_INFO "%s: link up, %s, %s-duplex\n", dev->name, s,
-		       p->link_config.duplex == DUPLEX_FULL ? "full" : "half");
-	}
-}
-
-static void enable_tx_fifo_drain(struct adapter *adapter,
-				 struct port_info *pi)
-{
-	t3_set_reg_field(adapter, A_XGM_TXFIFO_CFG + pi->mac.offset, 0,
-			 F_ENDROPPKT);
-	t3_write_reg(adapter, A_XGM_RX_CTRL + pi->mac.offset, 0);
-	t3_write_reg(adapter, A_XGM_TX_CTRL + pi->mac.offset, F_TXEN);
-	t3_write_reg(adapter, A_XGM_RX_CTRL + pi->mac.offset, F_RXEN);
-}
-
-static void disable_tx_fifo_drain(struct adapter *adapter,
-				  struct port_info *pi)
-{
-	t3_set_reg_field(adapter, A_XGM_TXFIFO_CFG + pi->mac.offset,
-			 F_ENDROPPKT, 0);
-}
-
-void t3_os_link_fault(struct adapter *adap, int port_id, int state)
-{
-	struct net_device *dev = adap->port[port_id];
-	struct port_info *pi = netdev_priv(dev);
-
-	if (state == netif_carrier_ok(dev))
-		return;
-
-	if (state) {
-		struct cmac *mac = &pi->mac;
-
-		netif_carrier_on(dev);
-
-		disable_tx_fifo_drain(adap, pi);
-
-		/* Clear local faults */
-		t3_xgm_intr_disable(adap, pi->port_id);
-		t3_read_reg(adap, A_XGM_INT_STATUS +
-				    pi->mac.offset);
-		t3_write_reg(adap,
-			     A_XGM_INT_CAUSE + pi->mac.offset,
-			     F_XGM_INT);
-
-		t3_set_reg_field(adap,
-				 A_XGM_INT_ENABLE +
-				 pi->mac.offset,
-				 F_XGM_INT, F_XGM_INT);
-		t3_xgm_intr_enable(adap, pi->port_id);
-
-		t3_mac_enable(mac, MAC_DIRECTION_TX);
-	} else {
-		netif_carrier_off(dev);
-
-		/* Flush TX FIFO */
-		enable_tx_fifo_drain(adap, pi);
-	}
-	link_report(dev);
-}
-
-/**
- *	t3_os_link_changed - handle link status changes
- *	@adapter: the adapter associated with the link change
- *	@port_id: the port index whose limk status has changed
- *	@link_stat: the new status of the link
- *	@speed: the new speed setting
- *	@duplex: the new duplex setting
- *	@pause: the new flow-control setting
- *
- *	This is the OS-dependent handler for link status changes.  The OS
- *	neutral handler takes care of most of the processing for these events,
- *	then calls this handler for any OS-specific processing.
- */
-void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat,
-			int speed, int duplex, int pause)
-{
-	struct net_device *dev = adapter->port[port_id];
-	struct port_info *pi = netdev_priv(dev);
-	struct cmac *mac = &pi->mac;
-
-	/* Skip changes from disabled ports. */
-	if (!netif_running(dev))
-		return;
-
-	if (link_stat != netif_carrier_ok(dev)) {
-		if (link_stat) {
-			disable_tx_fifo_drain(adapter, pi);
-
-			t3_mac_enable(mac, MAC_DIRECTION_RX);
-
-			/* Clear local faults */
-			t3_xgm_intr_disable(adapter, pi->port_id);
-			t3_read_reg(adapter, A_XGM_INT_STATUS +
-				    pi->mac.offset);
-			t3_write_reg(adapter,
-				     A_XGM_INT_CAUSE + pi->mac.offset,
-				     F_XGM_INT);
-
-			t3_set_reg_field(adapter,
-					 A_XGM_INT_ENABLE + pi->mac.offset,
-					 F_XGM_INT, F_XGM_INT);
-			t3_xgm_intr_enable(adapter, pi->port_id);
-
-			netif_carrier_on(dev);
-		} else {
-			netif_carrier_off(dev);
-
-			t3_xgm_intr_disable(adapter, pi->port_id);
-			t3_read_reg(adapter, A_XGM_INT_STATUS + pi->mac.offset);
-			t3_set_reg_field(adapter,
-					 A_XGM_INT_ENABLE + pi->mac.offset,
-					 F_XGM_INT, 0);
-
-			if (is_10G(adapter))
-				pi->phy.ops->power_down(&pi->phy, 1);
-
-			t3_read_reg(adapter, A_XGM_INT_STATUS + pi->mac.offset);
-			t3_mac_disable(mac, MAC_DIRECTION_RX);
-			t3_link_start(&pi->phy, mac, &pi->link_config);
-
-			/* Flush TX FIFO */
-			enable_tx_fifo_drain(adapter, pi);
-		}
-
-		link_report(dev);
-	}
-}
-
-/**
- *	t3_os_phymod_changed - handle PHY module changes
- *	@phy: the PHY reporting the module change
- *	@mod_type: new module type
- *
- *	This is the OS-dependent handler for PHY module changes.  It is
- *	invoked when a PHY module is removed or inserted for any OS-specific
- *	processing.
- */
-void t3_os_phymod_changed(struct adapter *adap, int port_id)
-{
-	static const char *mod_str[] = {
-		NULL, "SR", "LR", "LRM", "TWINAX", "TWINAX", "unknown"
-	};
-
-	const struct net_device *dev = adap->port[port_id];
-	const struct port_info *pi = netdev_priv(dev);
-
-	if (pi->phy.modtype == phy_modtype_none)
-		printk(KERN_INFO "%s: PHY module unplugged\n", dev->name);
-	else
-		printk(KERN_INFO "%s: %s PHY module inserted\n", dev->name,
-		       mod_str[pi->phy.modtype]);
-}
-
-static void cxgb_set_rxmode(struct net_device *dev)
-{
-	struct port_info *pi = netdev_priv(dev);
-
-	t3_mac_set_rx_mode(&pi->mac, dev);
-}
-
-/**
- *	link_start - enable a port
- *	@dev: the device to enable
- *
- *	Performs the MAC and PHY actions needed to enable a port.
- */
-static void link_start(struct net_device *dev)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct cmac *mac = &pi->mac;
-
-	t3_mac_reset(mac);
-	t3_mac_set_num_ucast(mac, MAX_MAC_IDX);
-	t3_mac_set_mtu(mac, dev->mtu);
-	t3_mac_set_address(mac, LAN_MAC_IDX, dev->dev_addr);
-	t3_mac_set_address(mac, SAN_MAC_IDX, pi->iscsic.mac_addr);
-	t3_mac_set_rx_mode(mac, dev);
-	t3_link_start(&pi->phy, mac, &pi->link_config);
-	t3_mac_enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
-}
-
-static inline void cxgb_disable_msi(struct adapter *adapter)
-{
-	if (adapter->flags & USING_MSIX) {
-		pci_disable_msix(adapter->pdev);
-		adapter->flags &= ~USING_MSIX;
-	} else if (adapter->flags & USING_MSI) {
-		pci_disable_msi(adapter->pdev);
-		adapter->flags &= ~USING_MSI;
-	}
-}
-
-/*
- * Interrupt handler for asynchronous events used with MSI-X.
- */
-static irqreturn_t t3_async_intr_handler(int irq, void *cookie)
-{
-	t3_slow_intr_handler(cookie);
-	return IRQ_HANDLED;
-}
-
-/*
- * Name the MSI-X interrupts.
- */
-static void name_msix_vecs(struct adapter *adap)
-{
-	int i, j, msi_idx = 1, n = sizeof(adap->msix_info[0].desc) - 1;
-
-	snprintf(adap->msix_info[0].desc, n, "%s", adap->name);
-	adap->msix_info[0].desc[n] = 0;
-
-	for_each_port(adap, j) {
-		struct net_device *d = adap->port[j];
-		const struct port_info *pi = netdev_priv(d);
-
-		for (i = 0; i < pi->nqsets; i++, msi_idx++) {
-			snprintf(adap->msix_info[msi_idx].desc, n,
-				 "%s-%d", d->name, pi->first_qset + i);
-			adap->msix_info[msi_idx].desc[n] = 0;
-		}
-	}
-}
-
-static int request_msix_data_irqs(struct adapter *adap)
-{
-	int i, j, err, qidx = 0;
-
-	for_each_port(adap, i) {
-		int nqsets = adap2pinfo(adap, i)->nqsets;
-
-		for (j = 0; j < nqsets; ++j) {
-			err = request_irq(adap->msix_info[qidx + 1].vec,
-					  t3_intr_handler(adap,
-							  adap->sge.qs[qidx].
-							  rspq.polling), 0,
-					  adap->msix_info[qidx + 1].desc,
-					  &adap->sge.qs[qidx]);
-			if (err) {
-				while (--qidx >= 0)
-					free_irq(adap->msix_info[qidx + 1].vec,
-						 &adap->sge.qs[qidx]);
-				return err;
-			}
-			qidx++;
-		}
-	}
-	return 0;
-}
-
-static void free_irq_resources(struct adapter *adapter)
-{
-	if (adapter->flags & USING_MSIX) {
-		int i, n = 0;
-
-		free_irq(adapter->msix_info[0].vec, adapter);
-		for_each_port(adapter, i)
-			n += adap2pinfo(adapter, i)->nqsets;
-
-		for (i = 0; i < n; ++i)
-			free_irq(adapter->msix_info[i + 1].vec,
-				 &adapter->sge.qs[i]);
-	} else
-		free_irq(adapter->pdev->irq, adapter);
-}
-
-static int await_mgmt_replies(struct adapter *adap, unsigned long init_cnt,
-			      unsigned long n)
-{
-	int attempts = 10;
-
-	while (adap->sge.qs[0].rspq.offload_pkts < init_cnt + n) {
-		if (!--attempts)
-			return -ETIMEDOUT;
-		msleep(10);
-	}
-	return 0;
-}
-
-static int init_tp_parity(struct adapter *adap)
-{
-	int i;
-	struct sk_buff *skb;
-	struct cpl_set_tcb_field *greq;
-	unsigned long cnt = adap->sge.qs[0].rspq.offload_pkts;
-
-	t3_tp_set_offload_mode(adap, 1);
-
-	for (i = 0; i < 16; i++) {
-		struct cpl_smt_write_req *req;
-
-		skb = alloc_skb(sizeof(*req), GFP_KERNEL);
-		if (!skb)
-			skb = adap->nofail_skb;
-		if (!skb)
-			goto alloc_skb_fail;
-
-		req = (struct cpl_smt_write_req *)__skb_put(skb, sizeof(*req));
-		memset(req, 0, sizeof(*req));
-		req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
-		OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SMT_WRITE_REQ, i));
-		req->mtu_idx = NMTUS - 1;
-		req->iff = i;
-		t3_mgmt_tx(adap, skb);
-		if (skb == adap->nofail_skb) {
-			await_mgmt_replies(adap, cnt, i + 1);
-			adap->nofail_skb = alloc_skb(sizeof(*greq), GFP_KERNEL);
-			if (!adap->nofail_skb)
-				goto alloc_skb_fail;
-		}
-	}
-
-	for (i = 0; i < 2048; i++) {
-		struct cpl_l2t_write_req *req;
-
-		skb = alloc_skb(sizeof(*req), GFP_KERNEL);
-		if (!skb)
-			skb = adap->nofail_skb;
-		if (!skb)
-			goto alloc_skb_fail;
-
-		req = (struct cpl_l2t_write_req *)__skb_put(skb, sizeof(*req));
-		memset(req, 0, sizeof(*req));
-		req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
-		OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, i));
-		req->params = htonl(V_L2T_W_IDX(i));
-		t3_mgmt_tx(adap, skb);
-		if (skb == adap->nofail_skb) {
-			await_mgmt_replies(adap, cnt, 16 + i + 1);
-			adap->nofail_skb = alloc_skb(sizeof(*greq), GFP_KERNEL);
-			if (!adap->nofail_skb)
-				goto alloc_skb_fail;
-		}
-	}
-
-	for (i = 0; i < 2048; i++) {
-		struct cpl_rte_write_req *req;
-
-		skb = alloc_skb(sizeof(*req), GFP_KERNEL);
-		if (!skb)
-			skb = adap->nofail_skb;
-		if (!skb)
-			goto alloc_skb_fail;
-
-		req = (struct cpl_rte_write_req *)__skb_put(skb, sizeof(*req));
-		memset(req, 0, sizeof(*req));
-		req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
-		OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RTE_WRITE_REQ, i));
-		req->l2t_idx = htonl(V_L2T_W_IDX(i));
-		t3_mgmt_tx(adap, skb);
-		if (skb == adap->nofail_skb) {
-			await_mgmt_replies(adap, cnt, 16 + 2048 + i + 1);
-			adap->nofail_skb = alloc_skb(sizeof(*greq), GFP_KERNEL);
-			if (!adap->nofail_skb)
-				goto alloc_skb_fail;
-		}
-	}
-
-	skb = alloc_skb(sizeof(*greq), GFP_KERNEL);
-	if (!skb)
-		skb = adap->nofail_skb;
-	if (!skb)
-		goto alloc_skb_fail;
-
-	greq = (struct cpl_set_tcb_field *)__skb_put(skb, sizeof(*greq));
-	memset(greq, 0, sizeof(*greq));
-	greq->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
-	OPCODE_TID(greq) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, 0));
-	greq->mask = cpu_to_be64(1);
-	t3_mgmt_tx(adap, skb);
-
-	i = await_mgmt_replies(adap, cnt, 16 + 2048 + 2048 + 1);
-	if (skb == adap->nofail_skb) {
-		i = await_mgmt_replies(adap, cnt, 16 + 2048 + 2048 + 1);
-		adap->nofail_skb = alloc_skb(sizeof(*greq), GFP_KERNEL);
-	}
-
-	t3_tp_set_offload_mode(adap, 0);
-	return i;
-
-alloc_skb_fail:
-	t3_tp_set_offload_mode(adap, 0);
-	return -ENOMEM;
-}
-
-/**
- *	setup_rss - configure RSS
- *	@adap: the adapter
- *
- *	Sets up RSS to distribute packets to multiple receive queues.  We
- *	configure the RSS CPU lookup table to distribute to the number of HW
- *	receive queues, and the response queue lookup table to narrow that
- *	down to the response queues actually configured for each port.
- *	We always configure the RSS mapping for two ports since the mapping
- *	table has plenty of entries.
- */
-static void setup_rss(struct adapter *adap)
-{
-	int i;
-	unsigned int nq0 = adap2pinfo(adap, 0)->nqsets;
-	unsigned int nq1 = adap->port[1] ? adap2pinfo(adap, 1)->nqsets : 1;
-	u8 cpus[SGE_QSETS + 1];
-	u16 rspq_map[RSS_TABLE_SIZE];
-
-	for (i = 0; i < SGE_QSETS; ++i)
-		cpus[i] = i;
-	cpus[SGE_QSETS] = 0xff;	/* terminator */
-
-	for (i = 0; i < RSS_TABLE_SIZE / 2; ++i) {
-		rspq_map[i] = i % nq0;
-		rspq_map[i + RSS_TABLE_SIZE / 2] = (i % nq1) + nq0;
-	}
-
-	t3_config_rss(adap, F_RQFEEDBACKENABLE | F_TNLLKPEN | F_TNLMAPEN |
-		      F_TNLPRTEN | F_TNL2TUPEN | F_TNL4TUPEN |
-		      V_RRCPLCPUSIZE(6) | F_HASHTOEPLITZ, cpus, rspq_map);
-}
-
-static void ring_dbs(struct adapter *adap)
-{
-	int i, j;
-
-	for (i = 0; i < SGE_QSETS; i++) {
-		struct sge_qset *qs = &adap->sge.qs[i];
-
-		if (qs->adap)
-			for (j = 0; j < SGE_TXQ_PER_SET; j++)
-				t3_write_reg(adap, A_SG_KDOORBELL, F_SELEGRCNTX | V_EGRCNTX(qs->txq[j].cntxt_id));
-	}
-}
-
-static void init_napi(struct adapter *adap)
-{
-	int i;
-
-	for (i = 0; i < SGE_QSETS; i++) {
-		struct sge_qset *qs = &adap->sge.qs[i];
-
-		if (qs->adap)
-			netif_napi_add(qs->netdev, &qs->napi, qs->napi.poll,
-				       64);
-	}
-
-	/*
-	 * netif_napi_add() can be called only once per napi_struct because it
-	 * adds each new napi_struct to a list.  Be careful not to call it a
-	 * second time, e.g., during EEH recovery, by making a note of it.
-	 */
-	adap->flags |= NAPI_INIT;
-}
-
-/*
- * Wait until all NAPI handlers are descheduled.  This includes the handlers of
- * both netdevices representing interfaces and the dummy ones for the extra
- * queues.
- */
-static void quiesce_rx(struct adapter *adap)
-{
-	int i;
-
-	for (i = 0; i < SGE_QSETS; i++)
-		if (adap->sge.qs[i].adap)
-			napi_disable(&adap->sge.qs[i].napi);
-}
-
-static void enable_all_napi(struct adapter *adap)
-{
-	int i;
-	for (i = 0; i < SGE_QSETS; i++)
-		if (adap->sge.qs[i].adap)
-			napi_enable(&adap->sge.qs[i].napi);
-}
-
-/**
- *	setup_sge_qsets - configure SGE Tx/Rx/response queues
- *	@adap: the adapter
- *
- *	Determines how many sets of SGE queues to use and initializes them.
- *	We support multiple queue sets per port if we have MSI-X, otherwise
- *	just one queue set per port.
- */
-static int setup_sge_qsets(struct adapter *adap)
-{
-	int i, j, err, irq_idx = 0, qset_idx = 0;
-	unsigned int ntxq = SGE_TXQ_PER_SET;
-
-	if (adap->params.rev > 0 && !(adap->flags & USING_MSI))
-		irq_idx = -1;
-
-	for_each_port(adap, i) {
-		struct net_device *dev = adap->port[i];
-		struct port_info *pi = netdev_priv(dev);
-
-		pi->qs = &adap->sge.qs[pi->first_qset];
-		for (j = 0; j < pi->nqsets; ++j, ++qset_idx) {
-			err = t3_sge_alloc_qset(adap, qset_idx, 1,
-				(adap->flags & USING_MSIX) ? qset_idx + 1 :
-							     irq_idx,
-				&adap->params.sge.qset[qset_idx], ntxq, dev,
-				netdev_get_tx_queue(dev, j));
-			if (err) {
-				t3_free_sge_resources(adap);
-				return err;
-			}
-		}
-	}
-
-	return 0;
-}
-
-static ssize_t attr_show(struct device *d, char *buf,
-			 ssize_t(*format) (struct net_device *, char *))
-{
-	ssize_t len;
-
-	/* Synchronize with ioctls that may shut down the device */
-	rtnl_lock();
-	len = (*format) (to_net_dev(d), buf);
-	rtnl_unlock();
-	return len;
-}
-
-static ssize_t attr_store(struct device *d,
-			  const char *buf, size_t len,
-			  ssize_t(*set) (struct net_device *, unsigned int),
-			  unsigned int min_val, unsigned int max_val)
-{
-	char *endp;
-	ssize_t ret;
-	unsigned int val;
-
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	val = simple_strtoul(buf, &endp, 0);
-	if (endp == buf || val < min_val || val > max_val)
-		return -EINVAL;
-
-	rtnl_lock();
-	ret = (*set) (to_net_dev(d), val);
-	if (!ret)
-		ret = len;
-	rtnl_unlock();
-	return ret;
-}
-
-#define CXGB3_SHOW(name, val_expr) \
-static ssize_t format_##name(struct net_device *dev, char *buf) \
-{ \
-	struct port_info *pi = netdev_priv(dev); \
-	struct adapter *adap = pi->adapter; \
-	return sprintf(buf, "%u\n", val_expr); \
-} \
-static ssize_t show_##name(struct device *d, struct device_attribute *attr, \
-			   char *buf) \
-{ \
-	return attr_show(d, buf, format_##name); \
-}
-
-static ssize_t set_nfilters(struct net_device *dev, unsigned int val)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adap = pi->adapter;
-	int min_tids = is_offload(adap) ? MC5_MIN_TIDS : 0;
-
-	if (adap->flags & FULL_INIT_DONE)
-		return -EBUSY;
-	if (val && adap->params.rev == 0)
-		return -EINVAL;
-	if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nservers -
-	    min_tids)
-		return -EINVAL;
-	adap->params.mc5.nfilters = val;
-	return 0;
-}
-
-static ssize_t store_nfilters(struct device *d, struct device_attribute *attr,
-			      const char *buf, size_t len)
-{
-	return attr_store(d, buf, len, set_nfilters, 0, ~0);
-}
-
-static ssize_t set_nservers(struct net_device *dev, unsigned int val)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adap = pi->adapter;
-
-	if (adap->flags & FULL_INIT_DONE)
-		return -EBUSY;
-	if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nfilters -
-	    MC5_MIN_TIDS)
-		return -EINVAL;
-	adap->params.mc5.nservers = val;
-	return 0;
-}
-
-static ssize_t store_nservers(struct device *d, struct device_attribute *attr,
-			      const char *buf, size_t len)
-{
-	return attr_store(d, buf, len, set_nservers, 0, ~0);
-}
-
-#define CXGB3_ATTR_R(name, val_expr) \
-CXGB3_SHOW(name, val_expr) \
-static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
-
-#define CXGB3_ATTR_RW(name, val_expr, store_method) \
-CXGB3_SHOW(name, val_expr) \
-static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_method)
-
-CXGB3_ATTR_R(cam_size, t3_mc5_size(&adap->mc5));
-CXGB3_ATTR_RW(nfilters, adap->params.mc5.nfilters, store_nfilters);
-CXGB3_ATTR_RW(nservers, adap->params.mc5.nservers, store_nservers);
-
-static struct attribute *cxgb3_attrs[] = {
-	&dev_attr_cam_size.attr,
-	&dev_attr_nfilters.attr,
-	&dev_attr_nservers.attr,
-	NULL
-};
-
-static struct attribute_group cxgb3_attr_group = {.attrs = cxgb3_attrs };
-
-static ssize_t tm_attr_show(struct device *d,
-			    char *buf, int sched)
-{
-	struct port_info *pi = netdev_priv(to_net_dev(d));
-	struct adapter *adap = pi->adapter;
-	unsigned int v, addr, bpt, cpt;
-	ssize_t len;
-
-	addr = A_TP_TX_MOD_Q1_Q0_RATE_LIMIT - sched / 2;
-	rtnl_lock();
-	t3_write_reg(adap, A_TP_TM_PIO_ADDR, addr);
-	v = t3_read_reg(adap, A_TP_TM_PIO_DATA);
-	if (sched & 1)
-		v >>= 16;
-	bpt = (v >> 8) & 0xff;
-	cpt = v & 0xff;
-	if (!cpt)
-		len = sprintf(buf, "disabled\n");
-	else {
-		v = (adap->params.vpd.cclk * 1000) / cpt;
-		len = sprintf(buf, "%u Kbps\n", (v * bpt) / 125);
-	}
-	rtnl_unlock();
-	return len;
-}
-
-static ssize_t tm_attr_store(struct device *d,
-			     const char *buf, size_t len, int sched)
-{
-	struct port_info *pi = netdev_priv(to_net_dev(d));
-	struct adapter *adap = pi->adapter;
-	unsigned int val;
-	char *endp;
-	ssize_t ret;
-
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	val = simple_strtoul(buf, &endp, 0);
-	if (endp == buf || val > 10000000)
-		return -EINVAL;
-
-	rtnl_lock();
-	ret = t3_config_sched(adap, val, sched);
-	if (!ret)
-		ret = len;
-	rtnl_unlock();
-	return ret;
-}
-
-#define TM_ATTR(name, sched) \
-static ssize_t show_##name(struct device *d, struct device_attribute *attr, \
-			   char *buf) \
-{ \
-	return tm_attr_show(d, buf, sched); \
-} \
-static ssize_t store_##name(struct device *d, struct device_attribute *attr, \
-			    const char *buf, size_t len) \
-{ \
-	return tm_attr_store(d, buf, len, sched); \
-} \
-static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_##name)
-
-TM_ATTR(sched0, 0);
-TM_ATTR(sched1, 1);
-TM_ATTR(sched2, 2);
-TM_ATTR(sched3, 3);
-TM_ATTR(sched4, 4);
-TM_ATTR(sched5, 5);
-TM_ATTR(sched6, 6);
-TM_ATTR(sched7, 7);
-
-static struct attribute *offload_attrs[] = {
-	&dev_attr_sched0.attr,
-	&dev_attr_sched1.attr,
-	&dev_attr_sched2.attr,
-	&dev_attr_sched3.attr,
-	&dev_attr_sched4.attr,
-	&dev_attr_sched5.attr,
-	&dev_attr_sched6.attr,
-	&dev_attr_sched7.attr,
-	NULL
-};
-
-static struct attribute_group offload_attr_group = {.attrs = offload_attrs };
-
-/*
- * Sends an sk_buff to an offload queue driver
- * after dealing with any active network taps.
- */
-static inline int offload_tx(struct t3cdev *tdev, struct sk_buff *skb)
-{
-	int ret;
-
-	local_bh_disable();
-	ret = t3_offload_tx(tdev, skb);
-	local_bh_enable();
-	return ret;
-}
-
-static int write_smt_entry(struct adapter *adapter, int idx)
-{
-	struct cpl_smt_write_req *req;
-	struct port_info *pi = netdev_priv(adapter->port[idx]);
-	struct sk_buff *skb = alloc_skb(sizeof(*req), GFP_KERNEL);
-
-	if (!skb)
-		return -ENOMEM;
-
-	req = (struct cpl_smt_write_req *)__skb_put(skb, sizeof(*req));
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SMT_WRITE_REQ, idx));
-	req->mtu_idx = NMTUS - 1;	/* should be 0 but there's a T3 bug */
-	req->iff = idx;
-	memcpy(req->src_mac0, adapter->port[idx]->dev_addr, ETH_ALEN);
-	memcpy(req->src_mac1, pi->iscsic.mac_addr, ETH_ALEN);
-	skb->priority = 1;
-	offload_tx(&adapter->tdev, skb);
-	return 0;
-}
-
-static int init_smt(struct adapter *adapter)
-{
-	int i;
-
-	for_each_port(adapter, i)
-	    write_smt_entry(adapter, i);
-	return 0;
-}
-
-static void init_port_mtus(struct adapter *adapter)
-{
-	unsigned int mtus = adapter->port[0]->mtu;
-
-	if (adapter->port[1])
-		mtus |= adapter->port[1]->mtu << 16;
-	t3_write_reg(adapter, A_TP_MTU_PORT_TABLE, mtus);
-}
-
-static int send_pktsched_cmd(struct adapter *adap, int sched, int qidx, int lo,
-			      int hi, int port)
-{
-	struct sk_buff *skb;
-	struct mngt_pktsched_wr *req;
-	int ret;
-
-	skb = alloc_skb(sizeof(*req), GFP_KERNEL);
-	if (!skb)
-		skb = adap->nofail_skb;
-	if (!skb)
-		return -ENOMEM;
-
-	req = (struct mngt_pktsched_wr *)skb_put(skb, sizeof(*req));
-	req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_MNGT));
-	req->mngt_opcode = FW_MNGTOPCODE_PKTSCHED_SET;
-	req->sched = sched;
-	req->idx = qidx;
-	req->min = lo;
-	req->max = hi;
-	req->binding = port;
-	ret = t3_mgmt_tx(adap, skb);
-	if (skb == adap->nofail_skb) {
-		adap->nofail_skb = alloc_skb(sizeof(struct cpl_set_tcb_field),
-					     GFP_KERNEL);
-		if (!adap->nofail_skb)
-			ret = -ENOMEM;
-	}
-
-	return ret;
-}
-
-static int bind_qsets(struct adapter *adap)
-{
-	int i, j, err = 0;
-
-	for_each_port(adap, i) {
-		const struct port_info *pi = adap2pinfo(adap, i);
-
-		for (j = 0; j < pi->nqsets; ++j) {
-			int ret = send_pktsched_cmd(adap, 1,
-						    pi->first_qset + j, -1,
-						    -1, i);
-			if (ret)
-				err = ret;
-		}
-	}
-
-	return err;
-}
-
-/*(DEBLOBBED)*/
-#define FW_FNAME "/*(DEBLOBBED)*/"
-/*(DEBLOBBED)*/
-#define TPSRAM_NAME "/*(DEBLOBBED)*/"
-#define AEL2005_OPT_EDC_NAME "/*(DEBLOBBED)*/"
-#define AEL2005_TWX_EDC_NAME "/*(DEBLOBBED)*/"
-#define AEL2020_TWX_EDC_NAME "/*(DEBLOBBED)*/"
-/*(DEBLOBBED)*/
-
-static inline const char *get_edc_fw_name(int edc_idx)
-{
-	const char *fw_name = NULL;
-
-	switch (edc_idx) {
-	case EDC_OPT_AEL2005:
-		fw_name = AEL2005_OPT_EDC_NAME;
-		break;
-	case EDC_TWX_AEL2005:
-		fw_name = AEL2005_TWX_EDC_NAME;
-		break;
-	case EDC_TWX_AEL2020:
-		fw_name = AEL2020_TWX_EDC_NAME;
-		break;
-	}
-	return fw_name;
-}
-
-int t3_get_edc_fw(struct cphy *phy, int edc_idx, int size)
-{
-	struct adapter *adapter = phy->adapter;
-	const struct firmware *fw;
-	char buf[64];
-	u32 csum;
-	const __be32 *p;
-	u16 *cache = phy->phy_cache;
-	int i, ret;
-
-	snprintf(buf, sizeof(buf), get_edc_fw_name(edc_idx));
-
-	ret = reject_firmware(&fw, buf, &adapter->pdev->dev);
-	if (ret < 0) {
-		dev_err(&adapter->pdev->dev,
-			"could not upgrade firmware: unable to load %s\n",
-			buf);
-		return ret;
-	}
-
-	/* check size, take checksum in account */
-	if (fw->size > size + 4) {
-		CH_ERR(adapter, "firmware image too large %u, expected %d\n",
-		       (unsigned int)fw->size, size + 4);
-		ret = -EINVAL;
-	}
-
-	/* compute checksum */
-	p = (const __be32 *)fw->data;
-	for (csum = 0, i = 0; i < fw->size / sizeof(csum); i++)
-		csum += ntohl(p[i]);
-
-	if (csum != 0xffffffff) {
-		CH_ERR(adapter, "corrupted firmware image, checksum %u\n",
-		       csum);
-		ret = -EINVAL;
-	}
-
-	for (i = 0; i < size / 4 ; i++) {
-		*cache++ = (be32_to_cpu(p[i]) & 0xffff0000) >> 16;
-		*cache++ = be32_to_cpu(p[i]) & 0xffff;
-	}
-
-	release_firmware(fw);
-
-	return ret;
-}
-
-static int upgrade_fw(struct adapter *adap)
-{
-	int ret;
-	const struct firmware *fw;
-	struct device *dev = &adap->pdev->dev;
-
-	ret = reject_firmware(&fw, FW_FNAME, dev);
-	if (ret < 0) {
-		dev_err(dev, "could not upgrade firmware: unable to load %s\n",
-			FW_FNAME);
-		return ret;
-	}
-	ret = t3_load_fw(adap, fw->data, fw->size);
-	release_firmware(fw);
-
-	if (ret == 0)
-		dev_info(dev, "successful upgrade to firmware %d.%d.%d\n",
-			 FW_VERSION_MAJOR, FW_VERSION_MINOR, FW_VERSION_MICRO);
-	else
-		dev_err(dev, "failed to upgrade to firmware %d.%d.%d\n",
-			FW_VERSION_MAJOR, FW_VERSION_MINOR, FW_VERSION_MICRO);
-
-	return ret;
-}
-
-static inline char t3rev2char(struct adapter *adapter)
-{
-	char rev = 0;
-
-	switch(adapter->params.rev) {
-	case T3_REV_B:
-	case T3_REV_B2:
-		rev = 'b';
-		break;
-	case T3_REV_C:
-		rev = 'c';
-		break;
-	}
-	return rev;
-}
-
-static int update_tpsram(struct adapter *adap)
-{
-	const struct firmware *tpsram;
-	char buf[64];
-	struct device *dev = &adap->pdev->dev;
-	int ret;
-	char rev;
-
-	rev = t3rev2char(adap);
-	if (!rev)
-		return 0;
-
-	snprintf(buf, sizeof(buf), TPSRAM_NAME, rev);
-
-	ret = reject_firmware(&tpsram, buf, dev);
-	if (ret < 0) {
-		dev_err(dev, "could not load TP SRAM: unable to load %s\n",
-			buf);
-		return ret;
-	}
-
-	ret = t3_check_tpsram(adap, tpsram->data, tpsram->size);
-	if (ret)
-		goto release_tpsram;
-
-	ret = t3_set_proto_sram(adap, tpsram->data);
-	if (ret == 0)
-		dev_info(dev,
-			 "successful update of protocol engine "
-			 "to %d.%d.%d\n",
-			 TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO);
-	else
-		dev_err(dev, "failed to update of protocol engine %d.%d.%d\n",
-			TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO);
-	if (ret)
-		dev_err(dev, "loading protocol SRAM failed\n");
-
-release_tpsram:
-	release_firmware(tpsram);
-
-	return ret;
-}
-
-/**
- *	cxgb_up - enable the adapter
- *	@adapter: adapter being enabled
- *
- *	Called when the first port is enabled, this function performs the
- *	actions necessary to make an adapter operational, such as completing
- *	the initialization of HW modules, and enabling interrupts.
- *
- *	Must be called with the rtnl lock held.
- */
-static int cxgb_up(struct adapter *adap)
-{
-	int err;
-
-	if (!(adap->flags & FULL_INIT_DONE)) {
-		err = t3_check_fw_version(adap);
-		if (err == -EINVAL) {
-			err = upgrade_fw(adap);
-			CH_WARN(adap, "FW upgrade to %d.%d.%d %s\n",
-				FW_VERSION_MAJOR, FW_VERSION_MINOR,
-				FW_VERSION_MICRO, err ? "failed" : "succeeded");
-		}
-
-		err = t3_check_tpsram_version(adap);
-		if (err == -EINVAL) {
-			err = update_tpsram(adap);
-			CH_WARN(adap, "TP upgrade to %d.%d.%d %s\n",
-				TP_VERSION_MAJOR, TP_VERSION_MINOR,
-				TP_VERSION_MICRO, err ? "failed" : "succeeded");
-		}
-
-		/*
-		 * Clear interrupts now to catch errors if t3_init_hw fails.
-		 * We clear them again later as initialization may trigger
-		 * conditions that can interrupt.
-		 */
-		t3_intr_clear(adap);
-
-		err = t3_init_hw(adap, 0);
-		if (err)
-			goto out;
-
-		t3_set_reg_field(adap, A_TP_PARA_REG5, 0, F_RXDDPOFFINIT);
-		t3_write_reg(adap, A_ULPRX_TDDP_PSZ, V_HPZ0(PAGE_SHIFT - 12));
-
-		err = setup_sge_qsets(adap);
-		if (err)
-			goto out;
-
-		setup_rss(adap);
-		if (!(adap->flags & NAPI_INIT))
-			init_napi(adap);
-
-		t3_start_sge_timers(adap);
-		adap->flags |= FULL_INIT_DONE;
-	}
-
-	t3_intr_clear(adap);
-
-	if (adap->flags & USING_MSIX) {
-		name_msix_vecs(adap);
-		err = request_irq(adap->msix_info[0].vec,
-				  t3_async_intr_handler, 0,
-				  adap->msix_info[0].desc, adap);
-		if (err)
-			goto irq_err;
-
-		err = request_msix_data_irqs(adap);
-		if (err) {
-			free_irq(adap->msix_info[0].vec, adap);
-			goto irq_err;
-		}
-	} else if ((err = request_irq(adap->pdev->irq,
-				      t3_intr_handler(adap,
-						      adap->sge.qs[0].rspq.
-						      polling),
-				      (adap->flags & USING_MSI) ?
-				       0 : IRQF_SHARED,
-				      adap->name, adap)))
-		goto irq_err;
-
-	enable_all_napi(adap);
-	t3_sge_start(adap);
-	t3_intr_enable(adap);
-
-	if (adap->params.rev >= T3_REV_C && !(adap->flags & TP_PARITY_INIT) &&
-	    is_offload(adap) && init_tp_parity(adap) == 0)
-		adap->flags |= TP_PARITY_INIT;
-
-	if (adap->flags & TP_PARITY_INIT) {
-		t3_write_reg(adap, A_TP_INT_CAUSE,
-			     F_CMCACHEPERR | F_ARPLUTPERR);
-		t3_write_reg(adap, A_TP_INT_ENABLE, 0x7fbfffff);
-	}
-
-	if (!(adap->flags & QUEUES_BOUND)) {
-		int ret = bind_qsets(adap);
-
-		if (ret < 0) {
-			CH_ERR(adap, "failed to bind qsets, err %d\n", ret);
-			t3_intr_disable(adap);
-			free_irq_resources(adap);
-			err = ret;
-			goto out;
-		}
-		adap->flags |= QUEUES_BOUND;
-	}
-
-out:
-	return err;
-irq_err:
-	CH_ERR(adap, "request_irq failed, err %d\n", err);
-	goto out;
-}
-
-/*
- * Release resources when all the ports and offloading have been stopped.
- */
-static void cxgb_down(struct adapter *adapter, int on_wq)
-{
-	t3_sge_stop(adapter);
-	spin_lock_irq(&adapter->work_lock);	/* sync with PHY intr task */
-	t3_intr_disable(adapter);
-	spin_unlock_irq(&adapter->work_lock);
-
-	free_irq_resources(adapter);
-	quiesce_rx(adapter);
-	t3_sge_stop(adapter);
-	if (!on_wq)
-		flush_workqueue(cxgb3_wq);/* wait for external IRQ handler */
-}
-
-static void schedule_chk_task(struct adapter *adap)
-{
-	unsigned int timeo;
-
-	timeo = adap->params.linkpoll_period ?
-	    (HZ * adap->params.linkpoll_period) / 10 :
-	    adap->params.stats_update_period * HZ;
-	if (timeo)
-		queue_delayed_work(cxgb3_wq, &adap->adap_check_task, timeo);
-}
-
-static int offload_open(struct net_device *dev)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	struct t3cdev *tdev = dev2t3cdev(dev);
-	int adap_up = adapter->open_device_map & PORT_MASK;
-	int err;
-
-	if (test_and_set_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map))
-		return 0;
-
-	if (!adap_up && (err = cxgb_up(adapter)) < 0)
-		goto out;
-
-	t3_tp_set_offload_mode(adapter, 1);
-	tdev->lldev = adapter->port[0];
-	err = cxgb3_offload_activate(adapter);
-	if (err)
-		goto out;
-
-	init_port_mtus(adapter);
-	t3_load_mtus(adapter, adapter->params.mtus, adapter->params.a_wnd,
-		     adapter->params.b_wnd,
-		     adapter->params.rev == 0 ?
-		     adapter->port[0]->mtu : 0xffff);
-	init_smt(adapter);
-
-	if (sysfs_create_group(&tdev->lldev->dev.kobj, &offload_attr_group))
-		dev_dbg(&dev->dev, "cannot create sysfs group\n");
-
-	/* Call back all registered clients */
-	cxgb3_add_clients(tdev);
-
-out:
-	/* restore them in case the offload module has changed them */
-	if (err) {
-		t3_tp_set_offload_mode(adapter, 0);
-		clear_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map);
-		cxgb3_set_dummy_ops(tdev);
-	}
-	return err;
-}
-
-static int offload_close(struct t3cdev *tdev)
-{
-	struct adapter *adapter = tdev2adap(tdev);
-	struct t3c_data *td = T3C_DATA(tdev);
-
-	if (!test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map))
-		return 0;
-
-	/* Call back all registered clients */
-	cxgb3_remove_clients(tdev);
-
-	sysfs_remove_group(&tdev->lldev->dev.kobj, &offload_attr_group);
-
-	/* Flush work scheduled while releasing TIDs */
-	flush_work_sync(&td->tid_release_task);
-
-	tdev->lldev = NULL;
-	cxgb3_set_dummy_ops(tdev);
-	t3_tp_set_offload_mode(adapter, 0);
-	clear_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map);
-
-	if (!adapter->open_device_map)
-		cxgb_down(adapter, 0);
-
-	cxgb3_offload_deactivate(adapter);
-	return 0;
-}
-
-static int cxgb_open(struct net_device *dev)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	int other_ports = adapter->open_device_map & PORT_MASK;
-	int err;
-
-	if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0)
-		return err;
-
-	set_bit(pi->port_id, &adapter->open_device_map);
-	if (is_offload(adapter) && !ofld_disable) {
-		err = offload_open(dev);
-		if (err)
-			printk(KERN_WARNING
-			       "Could not initialize offload capabilities\n");
-	}
-
-	netif_set_real_num_tx_queues(dev, pi->nqsets);
-	err = netif_set_real_num_rx_queues(dev, pi->nqsets);
-	if (err)
-		return err;
-	link_start(dev);
-	t3_port_intr_enable(adapter, pi->port_id);
-	netif_tx_start_all_queues(dev);
-	if (!other_ports)
-		schedule_chk_task(adapter);
-
-	cxgb3_event_notify(&adapter->tdev, OFFLOAD_PORT_UP, pi->port_id);
-	return 0;
-}
-
-static int __cxgb_close(struct net_device *dev, int on_wq)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-
-	
-	if (!adapter->open_device_map)
-		return 0;
-
-	/* Stop link fault interrupts */
-	t3_xgm_intr_disable(adapter, pi->port_id);
-	t3_read_reg(adapter, A_XGM_INT_STATUS + pi->mac.offset);
-
-	t3_port_intr_disable(adapter, pi->port_id);
-	netif_tx_stop_all_queues(dev);
-	pi->phy.ops->power_down(&pi->phy, 1);
-	netif_carrier_off(dev);
-	t3_mac_disable(&pi->mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
-
-	spin_lock_irq(&adapter->work_lock);	/* sync with update task */
-	clear_bit(pi->port_id, &adapter->open_device_map);
-	spin_unlock_irq(&adapter->work_lock);
-
-	if (!(adapter->open_device_map & PORT_MASK))
-		cancel_delayed_work_sync(&adapter->adap_check_task);
-
-	if (!adapter->open_device_map)
-		cxgb_down(adapter, on_wq);
-
-	cxgb3_event_notify(&adapter->tdev, OFFLOAD_PORT_DOWN, pi->port_id);
-	return 0;
-}
-
-static int cxgb_close(struct net_device *dev)
-{
-	return __cxgb_close(dev, 0);
-}
-
-static struct net_device_stats *cxgb_get_stats(struct net_device *dev)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	struct net_device_stats *ns = &pi->netstats;
-	const struct mac_stats *pstats;
-
-	spin_lock(&adapter->stats_lock);
-	pstats = t3_mac_update_stats(&pi->mac);
-	spin_unlock(&adapter->stats_lock);
-
-	ns->tx_bytes = pstats->tx_octets;
-	ns->tx_packets = pstats->tx_frames;
-	ns->rx_bytes = pstats->rx_octets;
-	ns->rx_packets = pstats->rx_frames;
-	ns->multicast = pstats->rx_mcast_frames;
-
-	ns->tx_errors = pstats->tx_underrun;
-	ns->rx_errors = pstats->rx_symbol_errs + pstats->rx_fcs_errs +
-	    pstats->rx_too_long + pstats->rx_jabber + pstats->rx_short +
-	    pstats->rx_fifo_ovfl;
-
-	/* detailed rx_errors */
-	ns->rx_length_errors = pstats->rx_jabber + pstats->rx_too_long;
-	ns->rx_over_errors = 0;
-	ns->rx_crc_errors = pstats->rx_fcs_errs;
-	ns->rx_frame_errors = pstats->rx_symbol_errs;
-	ns->rx_fifo_errors = pstats->rx_fifo_ovfl;
-	ns->rx_missed_errors = pstats->rx_cong_drops;
-
-	/* detailed tx_errors */
-	ns->tx_aborted_errors = 0;
-	ns->tx_carrier_errors = 0;
-	ns->tx_fifo_errors = pstats->tx_underrun;
-	ns->tx_heartbeat_errors = 0;
-	ns->tx_window_errors = 0;
-	return ns;
-}
-
-static u32 get_msglevel(struct net_device *dev)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-
-	return adapter->msg_enable;
-}
-
-static void set_msglevel(struct net_device *dev, u32 val)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-
-	adapter->msg_enable = val;
-}
-
-static char stats_strings[][ETH_GSTRING_LEN] = {
-	"TxOctetsOK         ",
-	"TxFramesOK         ",
-	"TxMulticastFramesOK",
-	"TxBroadcastFramesOK",
-	"TxPauseFrames      ",
-	"TxUnderrun         ",
-	"TxExtUnderrun      ",
-
-	"TxFrames64         ",
-	"TxFrames65To127    ",
-	"TxFrames128To255   ",
-	"TxFrames256To511   ",
-	"TxFrames512To1023  ",
-	"TxFrames1024To1518 ",
-	"TxFrames1519ToMax  ",
-
-	"RxOctetsOK         ",
-	"RxFramesOK         ",
-	"RxMulticastFramesOK",
-	"RxBroadcastFramesOK",
-	"RxPauseFrames      ",
-	"RxFCSErrors        ",
-	"RxSymbolErrors     ",
-	"RxShortErrors      ",
-	"RxJabberErrors     ",
-	"RxLengthErrors     ",
-	"RxFIFOoverflow     ",
-
-	"RxFrames64         ",
-	"RxFrames65To127    ",
-	"RxFrames128To255   ",
-	"RxFrames256To511   ",
-	"RxFrames512To1023  ",
-	"RxFrames1024To1518 ",
-	"RxFrames1519ToMax  ",
-
-	"PhyFIFOErrors      ",
-	"TSO                ",
-	"VLANextractions    ",
-	"VLANinsertions     ",
-	"TxCsumOffload      ",
-	"RxCsumGood         ",
-	"LroAggregated      ",
-	"LroFlushed         ",
-	"LroNoDesc          ",
-	"RxDrops            ",
-
-	"CheckTXEnToggled   ",
-	"CheckResets        ",
-
-	"LinkFaults         ",
-};
-
-static int get_sset_count(struct net_device *dev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		return ARRAY_SIZE(stats_strings);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-#define T3_REGMAP_SIZE (3 * 1024)
-
-static int get_regs_len(struct net_device *dev)
-{
-	return T3_REGMAP_SIZE;
-}
-
-static int get_eeprom_len(struct net_device *dev)
-{
-	return EEPROMSIZE;
-}
-
-static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	u32 fw_vers = 0;
-	u32 tp_vers = 0;
-
-	spin_lock(&adapter->stats_lock);
-	t3_get_fw_version(adapter, &fw_vers);
-	t3_get_tp_version(adapter, &tp_vers);
-	spin_unlock(&adapter->stats_lock);
-
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-	strcpy(info->bus_info, pci_name(adapter->pdev));
-	if (!fw_vers)
-		strcpy(info->fw_version, "N/A");
-	else {
-		snprintf(info->fw_version, sizeof(info->fw_version),
-			 "%s %u.%u.%u TP %u.%u.%u",
-			 G_FW_VERSION_TYPE(fw_vers) ? "T" : "N",
-			 G_FW_VERSION_MAJOR(fw_vers),
-			 G_FW_VERSION_MINOR(fw_vers),
-			 G_FW_VERSION_MICRO(fw_vers),
-			 G_TP_VERSION_MAJOR(tp_vers),
-			 G_TP_VERSION_MINOR(tp_vers),
-			 G_TP_VERSION_MICRO(tp_vers));
-	}
-}
-
-static void get_strings(struct net_device *dev, u32 stringset, u8 * data)
-{
-	if (stringset == ETH_SS_STATS)
-		memcpy(data, stats_strings, sizeof(stats_strings));
-}
-
-static unsigned long collect_sge_port_stats(struct adapter *adapter,
-					    struct port_info *p, int idx)
-{
-	int i;
-	unsigned long tot = 0;
-
-	for (i = p->first_qset; i < p->first_qset + p->nqsets; ++i)
-		tot += adapter->sge.qs[i].port_stats[idx];
-	return tot;
-}
-
-static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
-		      u64 *data)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	const struct mac_stats *s;
-
-	spin_lock(&adapter->stats_lock);
-	s = t3_mac_update_stats(&pi->mac);
-	spin_unlock(&adapter->stats_lock);
-
-	*data++ = s->tx_octets;
-	*data++ = s->tx_frames;
-	*data++ = s->tx_mcast_frames;
-	*data++ = s->tx_bcast_frames;
-	*data++ = s->tx_pause;
-	*data++ = s->tx_underrun;
-	*data++ = s->tx_fifo_urun;
-
-	*data++ = s->tx_frames_64;
-	*data++ = s->tx_frames_65_127;
-	*data++ = s->tx_frames_128_255;
-	*data++ = s->tx_frames_256_511;
-	*data++ = s->tx_frames_512_1023;
-	*data++ = s->tx_frames_1024_1518;
-	*data++ = s->tx_frames_1519_max;
-
-	*data++ = s->rx_octets;
-	*data++ = s->rx_frames;
-	*data++ = s->rx_mcast_frames;
-	*data++ = s->rx_bcast_frames;
-	*data++ = s->rx_pause;
-	*data++ = s->rx_fcs_errs;
-	*data++ = s->rx_symbol_errs;
-	*data++ = s->rx_short;
-	*data++ = s->rx_jabber;
-	*data++ = s->rx_too_long;
-	*data++ = s->rx_fifo_ovfl;
-
-	*data++ = s->rx_frames_64;
-	*data++ = s->rx_frames_65_127;
-	*data++ = s->rx_frames_128_255;
-	*data++ = s->rx_frames_256_511;
-	*data++ = s->rx_frames_512_1023;
-	*data++ = s->rx_frames_1024_1518;
-	*data++ = s->rx_frames_1519_max;
-
-	*data++ = pi->phy.fifo_errors;
-
-	*data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TSO);
-	*data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_VLANEX);
-	*data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_VLANINS);
-	*data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TX_CSUM);
-	*data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_RX_CSUM_GOOD);
-	*data++ = 0;
-	*data++ = 0;
-	*data++ = 0;
-	*data++ = s->rx_cong_drops;
-
-	*data++ = s->num_toggled;
-	*data++ = s->num_resets;
-
-	*data++ = s->link_faults;
-}
-
-static inline void reg_block_dump(struct adapter *ap, void *buf,
-				  unsigned int start, unsigned int end)
-{
-	u32 *p = buf + start;
-
-	for (; start <= end; start += sizeof(u32))
-		*p++ = t3_read_reg(ap, start);
-}
-
-static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
-		     void *buf)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *ap = pi->adapter;
-
-	/*
-	 * Version scheme:
-	 * bits 0..9: chip version
-	 * bits 10..15: chip revision
-	 * bit 31: set for PCIe cards
-	 */
-	regs->version = 3 | (ap->params.rev << 10) | (is_pcie(ap) << 31);
-
-	/*
-	 * We skip the MAC statistics registers because they are clear-on-read.
-	 * Also reading multi-register stats would need to synchronize with the
-	 * periodic mac stats accumulation.  Hard to justify the complexity.
-	 */
-	memset(buf, 0, T3_REGMAP_SIZE);
-	reg_block_dump(ap, buf, 0, A_SG_RSPQ_CREDIT_RETURN);
-	reg_block_dump(ap, buf, A_SG_HI_DRB_HI_THRSH, A_ULPRX_PBL_ULIMIT);
-	reg_block_dump(ap, buf, A_ULPTX_CONFIG, A_MPS_INT_CAUSE);
-	reg_block_dump(ap, buf, A_CPL_SWITCH_CNTRL, A_CPL_MAP_TBL_DATA);
-	reg_block_dump(ap, buf, A_SMB_GLOBAL_TIME_CFG, A_XGM_SERDES_STAT3);
-	reg_block_dump(ap, buf, A_XGM_SERDES_STATUS0,
-		       XGM_REG(A_XGM_SERDES_STAT3, 1));
-	reg_block_dump(ap, buf, XGM_REG(A_XGM_SERDES_STATUS0, 1),
-		       XGM_REG(A_XGM_RX_SPI4_SOP_EOP_CNT, 1));
-}
-
-static int restart_autoneg(struct net_device *dev)
-{
-	struct port_info *p = netdev_priv(dev);
-
-	if (!netif_running(dev))
-		return -EAGAIN;
-	if (p->link_config.autoneg != AUTONEG_ENABLE)
-		return -EINVAL;
-	p->phy.ops->autoneg_restart(&p->phy);
-	return 0;
-}
-
-static int set_phys_id(struct net_device *dev,
-		       enum ethtool_phys_id_state state)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-
-	switch (state) {
-	case ETHTOOL_ID_ACTIVE:
-		return 1;	/* cycle on/off once per second */
-
-	case ETHTOOL_ID_OFF:
-		t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL, 0);
-		break;
-
-	case ETHTOOL_ID_ON:
-	case ETHTOOL_ID_INACTIVE:
-		t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL,
-			 F_GPIO0_OUT_VAL);
-	}
-
-	return 0;
-}
-
-static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct port_info *p = netdev_priv(dev);
-
-	cmd->supported = p->link_config.supported;
-	cmd->advertising = p->link_config.advertising;
-
-	if (netif_carrier_ok(dev)) {
-		ethtool_cmd_speed_set(cmd, p->link_config.speed);
-		cmd->duplex = p->link_config.duplex;
-	} else {
-		ethtool_cmd_speed_set(cmd, -1);
-		cmd->duplex = -1;
-	}
-
-	cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
-	cmd->phy_address = p->phy.mdio.prtad;
-	cmd->transceiver = XCVR_EXTERNAL;
-	cmd->autoneg = p->link_config.autoneg;
-	cmd->maxtxpkt = 0;
-	cmd->maxrxpkt = 0;
-	return 0;
-}
-
-static int speed_duplex_to_caps(int speed, int duplex)
-{
-	int cap = 0;
-
-	switch (speed) {
-	case SPEED_10:
-		if (duplex == DUPLEX_FULL)
-			cap = SUPPORTED_10baseT_Full;
-		else
-			cap = SUPPORTED_10baseT_Half;
-		break;
-	case SPEED_100:
-		if (duplex == DUPLEX_FULL)
-			cap = SUPPORTED_100baseT_Full;
-		else
-			cap = SUPPORTED_100baseT_Half;
-		break;
-	case SPEED_1000:
-		if (duplex == DUPLEX_FULL)
-			cap = SUPPORTED_1000baseT_Full;
-		else
-			cap = SUPPORTED_1000baseT_Half;
-		break;
-	case SPEED_10000:
-		if (duplex == DUPLEX_FULL)
-			cap = SUPPORTED_10000baseT_Full;
-	}
-	return cap;
-}
-
-#define ADVERTISED_MASK (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
-		      ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
-		      ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | \
-		      ADVERTISED_10000baseT_Full)
-
-static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct port_info *p = netdev_priv(dev);
-	struct link_config *lc = &p->link_config;
-
-	if (!(lc->supported & SUPPORTED_Autoneg)) {
-		/*
-		 * PHY offers a single speed/duplex.  See if that's what's
-		 * being requested.
-		 */
-		if (cmd->autoneg == AUTONEG_DISABLE) {
-			u32 speed = ethtool_cmd_speed(cmd);
-			int cap = speed_duplex_to_caps(speed, cmd->duplex);
-			if (lc->supported & cap)
-				return 0;
-		}
-		return -EINVAL;
-	}
-
-	if (cmd->autoneg == AUTONEG_DISABLE) {
-		u32 speed = ethtool_cmd_speed(cmd);
-		int cap = speed_duplex_to_caps(speed, cmd->duplex);
-
-		if (!(lc->supported & cap) || (speed == SPEED_1000))
-			return -EINVAL;
-		lc->requested_speed = speed;
-		lc->requested_duplex = cmd->duplex;
-		lc->advertising = 0;
-	} else {
-		cmd->advertising &= ADVERTISED_MASK;
-		cmd->advertising &= lc->supported;
-		if (!cmd->advertising)
-			return -EINVAL;
-		lc->requested_speed = SPEED_INVALID;
-		lc->requested_duplex = DUPLEX_INVALID;
-		lc->advertising = cmd->advertising | ADVERTISED_Autoneg;
-	}
-	lc->autoneg = cmd->autoneg;
-	if (netif_running(dev))
-		t3_link_start(&p->phy, &p->mac, lc);
-	return 0;
-}
-
-static void get_pauseparam(struct net_device *dev,
-			   struct ethtool_pauseparam *epause)
-{
-	struct port_info *p = netdev_priv(dev);
-
-	epause->autoneg = (p->link_config.requested_fc & PAUSE_AUTONEG) != 0;
-	epause->rx_pause = (p->link_config.fc & PAUSE_RX) != 0;
-	epause->tx_pause = (p->link_config.fc & PAUSE_TX) != 0;
-}
-
-static int set_pauseparam(struct net_device *dev,
-			  struct ethtool_pauseparam *epause)
-{
-	struct port_info *p = netdev_priv(dev);
-	struct link_config *lc = &p->link_config;
-
-	if (epause->autoneg == AUTONEG_DISABLE)
-		lc->requested_fc = 0;
-	else if (lc->supported & SUPPORTED_Autoneg)
-		lc->requested_fc = PAUSE_AUTONEG;
-	else
-		return -EINVAL;
-
-	if (epause->rx_pause)
-		lc->requested_fc |= PAUSE_RX;
-	if (epause->tx_pause)
-		lc->requested_fc |= PAUSE_TX;
-	if (lc->autoneg == AUTONEG_ENABLE) {
-		if (netif_running(dev))
-			t3_link_start(&p->phy, &p->mac, lc);
-	} else {
-		lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
-		if (netif_running(dev))
-			t3_mac_set_speed_duplex_fc(&p->mac, -1, -1, lc->fc);
-	}
-	return 0;
-}
-
-static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	const struct qset_params *q = &adapter->params.sge.qset[pi->first_qset];
-
-	e->rx_max_pending = MAX_RX_BUFFERS;
-	e->rx_mini_max_pending = 0;
-	e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS;
-	e->tx_max_pending = MAX_TXQ_ENTRIES;
-
-	e->rx_pending = q->fl_size;
-	e->rx_mini_pending = q->rspq_size;
-	e->rx_jumbo_pending = q->jumbo_size;
-	e->tx_pending = q->txq_size[0];
-}
-
-static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	struct qset_params *q;
-	int i;
-
-	if (e->rx_pending > MAX_RX_BUFFERS ||
-	    e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS ||
-	    e->tx_pending > MAX_TXQ_ENTRIES ||
-	    e->rx_mini_pending > MAX_RSPQ_ENTRIES ||
-	    e->rx_mini_pending < MIN_RSPQ_ENTRIES ||
-	    e->rx_pending < MIN_FL_ENTRIES ||
-	    e->rx_jumbo_pending < MIN_FL_ENTRIES ||
-	    e->tx_pending < adapter->params.nports * MIN_TXQ_ENTRIES)
-		return -EINVAL;
-
-	if (adapter->flags & FULL_INIT_DONE)
-		return -EBUSY;
-
-	q = &adapter->params.sge.qset[pi->first_qset];
-	for (i = 0; i < pi->nqsets; ++i, ++q) {
-		q->rspq_size = e->rx_mini_pending;
-		q->fl_size = e->rx_pending;
-		q->jumbo_size = e->rx_jumbo_pending;
-		q->txq_size[0] = e->tx_pending;
-		q->txq_size[1] = e->tx_pending;
-		q->txq_size[2] = e->tx_pending;
-	}
-	return 0;
-}
-
-static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	struct qset_params *qsp;
-	struct sge_qset *qs;
-	int i;
-
-	if (c->rx_coalesce_usecs * 10 > M_NEWTIMER)
-		return -EINVAL;
-
-	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;
-}
-
-static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	struct qset_params *q = adapter->params.sge.qset;
-
-	c->rx_coalesce_usecs = q->coalesce_usecs;
-	return 0;
-}
-
-static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
-		      u8 * data)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	int i, err = 0;
-
-	u8 *buf = kmalloc(EEPROMSIZE, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	e->magic = EEPROM_MAGIC;
-	for (i = e->offset & ~3; !err && i < e->offset + e->len; i += 4)
-		err = t3_seeprom_read(adapter, i, (__le32 *) & buf[i]);
-
-	if (!err)
-		memcpy(data, buf + e->offset, e->len);
-	kfree(buf);
-	return err;
-}
-
-static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
-		      u8 * data)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	u32 aligned_offset, aligned_len;
-	__le32 *p;
-	u8 *buf;
-	int err;
-
-	if (eeprom->magic != EEPROM_MAGIC)
-		return -EINVAL;
-
-	aligned_offset = eeprom->offset & ~3;
-	aligned_len = (eeprom->len + (eeprom->offset & 3) + 3) & ~3;
-
-	if (aligned_offset != eeprom->offset || aligned_len != eeprom->len) {
-		buf = kmalloc(aligned_len, GFP_KERNEL);
-		if (!buf)
-			return -ENOMEM;
-		err = t3_seeprom_read(adapter, aligned_offset, (__le32 *) buf);
-		if (!err && aligned_len > 4)
-			err = t3_seeprom_read(adapter,
-					      aligned_offset + aligned_len - 4,
-					      (__le32 *) & buf[aligned_len - 4]);
-		if (err)
-			goto out;
-		memcpy(buf + (eeprom->offset & 3), data, eeprom->len);
-	} else
-		buf = data;
-
-	err = t3_seeprom_wp(adapter, 0);
-	if (err)
-		goto out;
-
-	for (p = (__le32 *) buf; !err && aligned_len; aligned_len -= 4, p++) {
-		err = t3_seeprom_write(adapter, aligned_offset, *p);
-		aligned_offset += 4;
-	}
-
-	if (!err)
-		err = t3_seeprom_wp(adapter, 1);
-out:
-	if (buf != data)
-		kfree(buf);
-	return err;
-}
-
-static void get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-	wol->supported = 0;
-	wol->wolopts = 0;
-	memset(&wol->sopass, 0, sizeof(wol->sopass));
-}
-
-static const struct ethtool_ops cxgb_ethtool_ops = {
-	.get_settings = get_settings,
-	.set_settings = set_settings,
-	.get_drvinfo = get_drvinfo,
-	.get_msglevel = get_msglevel,
-	.set_msglevel = set_msglevel,
-	.get_ringparam = get_sge_param,
-	.set_ringparam = set_sge_param,
-	.get_coalesce = get_coalesce,
-	.set_coalesce = set_coalesce,
-	.get_eeprom_len = get_eeprom_len,
-	.get_eeprom = get_eeprom,
-	.set_eeprom = set_eeprom,
-	.get_pauseparam = get_pauseparam,
-	.set_pauseparam = set_pauseparam,
-	.get_link = ethtool_op_get_link,
-	.get_strings = get_strings,
-	.set_phys_id = set_phys_id,
-	.nway_reset = restart_autoneg,
-	.get_sset_count = get_sset_count,
-	.get_ethtool_stats = get_stats,
-	.get_regs_len = get_regs_len,
-	.get_regs = get_regs,
-	.get_wol = get_wol,
-};
-
-static int in_range(int val, int lo, int hi)
-{
-	return val < 0 || (val <= hi && val >= lo);
-}
-
-static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	u32 cmd;
-	int ret;
-
-	if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
-		return -EFAULT;
-
-	switch (cmd) {
-	case CHELSIO_SET_QSET_PARAMS:{
-		int i;
-		struct qset_params *q;
-		struct ch_qset_params t;
-		int q1 = pi->first_qset;
-		int nqsets = pi->nqsets;
-
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		if (copy_from_user(&t, useraddr, sizeof(t)))
-			return -EFAULT;
-		if (t.qset_idx >= SGE_QSETS)
-			return -EINVAL;
-		if (!in_range(t.intr_lat, 0, M_NEWTIMER) ||
-		    !in_range(t.cong_thres, 0, 255) ||
-		    !in_range(t.txq_size[0], MIN_TXQ_ENTRIES,
-			      MAX_TXQ_ENTRIES) ||
-		    !in_range(t.txq_size[1], MIN_TXQ_ENTRIES,
-			      MAX_TXQ_ENTRIES) ||
-		    !in_range(t.txq_size[2], MIN_CTRL_TXQ_ENTRIES,
-			      MAX_CTRL_TXQ_ENTRIES) ||
-		    !in_range(t.fl_size[0], MIN_FL_ENTRIES,
-			      MAX_RX_BUFFERS) ||
-		    !in_range(t.fl_size[1], MIN_FL_ENTRIES,
-			      MAX_RX_JUMBO_BUFFERS) ||
-		    !in_range(t.rspq_size, MIN_RSPQ_ENTRIES,
-			      MAX_RSPQ_ENTRIES))
-			return -EINVAL;
-
-		if ((adapter->flags & FULL_INIT_DONE) &&
-			(t.rspq_size >= 0 || t.fl_size[0] >= 0 ||
-			t.fl_size[1] >= 0 || t.txq_size[0] >= 0 ||
-			t.txq_size[1] >= 0 || t.txq_size[2] >= 0 ||
-			t.polling >= 0 || t.cong_thres >= 0))
-			return -EBUSY;
-
-		/* Allow setting of any available qset when offload enabled */
-		if (test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) {
-			q1 = 0;
-			for_each_port(adapter, i) {
-				pi = adap2pinfo(adapter, i);
-				nqsets += pi->first_qset + pi->nqsets;
-			}
-		}
-
-		if (t.qset_idx < q1)
-			return -EINVAL;
-		if (t.qset_idx > q1 + nqsets - 1)
-			return -EINVAL;
-
-		q = &adapter->params.sge.qset[t.qset_idx];
-
-		if (t.rspq_size >= 0)
-			q->rspq_size = t.rspq_size;
-		if (t.fl_size[0] >= 0)
-			q->fl_size = t.fl_size[0];
-		if (t.fl_size[1] >= 0)
-			q->jumbo_size = t.fl_size[1];
-		if (t.txq_size[0] >= 0)
-			q->txq_size[0] = t.txq_size[0];
-		if (t.txq_size[1] >= 0)
-			q->txq_size[1] = t.txq_size[1];
-		if (t.txq_size[2] >= 0)
-			q->txq_size[2] = t.txq_size[2];
-		if (t.cong_thres >= 0)
-			q->cong_thres = t.cong_thres;
-		if (t.intr_lat >= 0) {
-			struct sge_qset *qs =
-				&adapter->sge.qs[t.qset_idx];
-
-			q->coalesce_usecs = t.intr_lat;
-			t3_update_qset_coalesce(qs, q);
-		}
-		if (t.polling >= 0) {
-			if (adapter->flags & USING_MSIX)
-				q->polling = t.polling;
-			else {
-				/* No polling with INTx for T3A */
-				if (adapter->params.rev == 0 &&
-					!(adapter->flags & USING_MSI))
-					t.polling = 0;
-
-				for (i = 0; i < SGE_QSETS; i++) {
-					q = &adapter->params.sge.
-						qset[i];
-					q->polling = t.polling;
-				}
-			}
-		}
-
-		if (t.lro >= 0) {
-			if (t.lro)
-				dev->wanted_features |= NETIF_F_GRO;
-			else
-				dev->wanted_features &= ~NETIF_F_GRO;
-			netdev_update_features(dev);
-		}
-
-		break;
-	}
-	case CHELSIO_GET_QSET_PARAMS:{
-		struct qset_params *q;
-		struct ch_qset_params t;
-		int q1 = pi->first_qset;
-		int nqsets = pi->nqsets;
-		int i;
-
-		if (copy_from_user(&t, useraddr, sizeof(t)))
-			return -EFAULT;
-
-		/* Display qsets for all ports when offload enabled */
-		if (test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) {
-			q1 = 0;
-			for_each_port(adapter, i) {
-				pi = adap2pinfo(adapter, i);
-				nqsets = pi->first_qset + pi->nqsets;
-			}
-		}
-
-		if (t.qset_idx >= nqsets)
-			return -EINVAL;
-
-		q = &adapter->params.sge.qset[q1 + t.qset_idx];
-		t.rspq_size = q->rspq_size;
-		t.txq_size[0] = q->txq_size[0];
-		t.txq_size[1] = q->txq_size[1];
-		t.txq_size[2] = q->txq_size[2];
-		t.fl_size[0] = q->fl_size;
-		t.fl_size[1] = q->jumbo_size;
-		t.polling = q->polling;
-		t.lro = !!(dev->features & NETIF_F_GRO);
-		t.intr_lat = q->coalesce_usecs;
-		t.cong_thres = q->cong_thres;
-		t.qnum = q1;
-
-		if (adapter->flags & USING_MSIX)
-			t.vector = adapter->msix_info[q1 + t.qset_idx + 1].vec;
-		else
-			t.vector = adapter->pdev->irq;
-
-		if (copy_to_user(useraddr, &t, sizeof(t)))
-			return -EFAULT;
-		break;
-	}
-	case CHELSIO_SET_QSET_NUM:{
-		struct ch_reg edata;
-		unsigned int i, first_qset = 0, other_qsets = 0;
-
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		if (adapter->flags & FULL_INIT_DONE)
-			return -EBUSY;
-		if (copy_from_user(&edata, useraddr, sizeof(edata)))
-			return -EFAULT;
-		if (edata.val < 1 ||
-			(edata.val > 1 && !(adapter->flags & USING_MSIX)))
-			return -EINVAL;
-
-		for_each_port(adapter, i)
-			if (adapter->port[i] && adapter->port[i] != dev)
-				other_qsets += adap2pinfo(adapter, i)->nqsets;
-
-		if (edata.val + other_qsets > SGE_QSETS)
-			return -EINVAL;
-
-		pi->nqsets = edata.val;
-
-		for_each_port(adapter, i)
-			if (adapter->port[i]) {
-				pi = adap2pinfo(adapter, i);
-				pi->first_qset = first_qset;
-				first_qset += pi->nqsets;
-			}
-		break;
-	}
-	case CHELSIO_GET_QSET_NUM:{
-		struct ch_reg edata;
-
-		memset(&edata, 0, sizeof(struct ch_reg));
-
-		edata.cmd = CHELSIO_GET_QSET_NUM;
-		edata.val = pi->nqsets;
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		break;
-	}
-	case CHELSIO_LOAD_FW:{
-		u8 *fw_data;
-		struct ch_mem_range t;
-
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		if (copy_from_user(&t, useraddr, sizeof(t)))
-			return -EFAULT;
-		/* Check t.len sanity ? */
-		fw_data = memdup_user(useraddr + sizeof(t), t.len);
-		if (IS_ERR(fw_data))
-			return PTR_ERR(fw_data);
-
-		ret = t3_load_fw(adapter, fw_data, t.len);
-		kfree(fw_data);
-		if (ret)
-			return ret;
-		break;
-	}
-	case CHELSIO_SETMTUTAB:{
-		struct ch_mtus m;
-		int i;
-
-		if (!is_offload(adapter))
-			return -EOPNOTSUPP;
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		if (offload_running(adapter))
-			return -EBUSY;
-		if (copy_from_user(&m, useraddr, sizeof(m)))
-			return -EFAULT;
-		if (m.nmtus != NMTUS)
-			return -EINVAL;
-		if (m.mtus[0] < 81)	/* accommodate SACK */
-			return -EINVAL;
-
-		/* MTUs must be in ascending order */
-		for (i = 1; i < NMTUS; ++i)
-			if (m.mtus[i] < m.mtus[i - 1])
-				return -EINVAL;
-
-		memcpy(adapter->params.mtus, m.mtus,
-			sizeof(adapter->params.mtus));
-		break;
-	}
-	case CHELSIO_GET_PM:{
-		struct tp_params *p = &adapter->params.tp;
-		struct ch_pm m = {.cmd = CHELSIO_GET_PM };
-
-		if (!is_offload(adapter))
-			return -EOPNOTSUPP;
-		m.tx_pg_sz = p->tx_pg_size;
-		m.tx_num_pg = p->tx_num_pgs;
-		m.rx_pg_sz = p->rx_pg_size;
-		m.rx_num_pg = p->rx_num_pgs;
-		m.pm_total = p->pmtx_size + p->chan_rx_size * p->nchan;
-		if (copy_to_user(useraddr, &m, sizeof(m)))
-			return -EFAULT;
-		break;
-	}
-	case CHELSIO_SET_PM:{
-		struct ch_pm m;
-		struct tp_params *p = &adapter->params.tp;
-
-		if (!is_offload(adapter))
-			return -EOPNOTSUPP;
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		if (adapter->flags & FULL_INIT_DONE)
-			return -EBUSY;
-		if (copy_from_user(&m, useraddr, sizeof(m)))
-			return -EFAULT;
-		if (!is_power_of_2(m.rx_pg_sz) ||
-			!is_power_of_2(m.tx_pg_sz))
-			return -EINVAL;	/* not power of 2 */
-		if (!(m.rx_pg_sz & 0x14000))
-			return -EINVAL;	/* not 16KB or 64KB */
-		if (!(m.tx_pg_sz & 0x1554000))
-			return -EINVAL;
-		if (m.tx_num_pg == -1)
-			m.tx_num_pg = p->tx_num_pgs;
-		if (m.rx_num_pg == -1)
-			m.rx_num_pg = p->rx_num_pgs;
-		if (m.tx_num_pg % 24 || m.rx_num_pg % 24)
-			return -EINVAL;
-		if (m.rx_num_pg * m.rx_pg_sz > p->chan_rx_size ||
-			m.tx_num_pg * m.tx_pg_sz > p->chan_tx_size)
-			return -EINVAL;
-		p->rx_pg_size = m.rx_pg_sz;
-		p->tx_pg_size = m.tx_pg_sz;
-		p->rx_num_pgs = m.rx_num_pg;
-		p->tx_num_pgs = m.tx_num_pg;
-		break;
-	}
-	case CHELSIO_GET_MEM:{
-		struct ch_mem_range t;
-		struct mc7 *mem;
-		u64 buf[32];
-
-		if (!is_offload(adapter))
-			return -EOPNOTSUPP;
-		if (!(adapter->flags & FULL_INIT_DONE))
-			return -EIO;	/* need the memory controllers */
-		if (copy_from_user(&t, useraddr, sizeof(t)))
-			return -EFAULT;
-		if ((t.addr & 7) || (t.len & 7))
-			return -EINVAL;
-		if (t.mem_id == MEM_CM)
-			mem = &adapter->cm;
-		else if (t.mem_id == MEM_PMRX)
-			mem = &adapter->pmrx;
-		else if (t.mem_id == MEM_PMTX)
-			mem = &adapter->pmtx;
-		else
-			return -EINVAL;
-
-		/*
-		 * Version scheme:
-		 * bits 0..9: chip version
-		 * bits 10..15: chip revision
-		 */
-		t.version = 3 | (adapter->params.rev << 10);
-		if (copy_to_user(useraddr, &t, sizeof(t)))
-			return -EFAULT;
-
-		/*
-		 * Read 256 bytes at a time as len can be large and we don't
-		 * want to use huge intermediate buffers.
-		 */
-		useraddr += sizeof(t);	/* advance to start of buffer */
-		while (t.len) {
-			unsigned int chunk =
-				min_t(unsigned int, t.len, sizeof(buf));
-
-			ret =
-				t3_mc7_bd_read(mem, t.addr / 8, chunk / 8,
-						buf);
-			if (ret)
-				return ret;
-			if (copy_to_user(useraddr, buf, chunk))
-				return -EFAULT;
-			useraddr += chunk;
-			t.addr += chunk;
-			t.len -= chunk;
-		}
-		break;
-	}
-	case CHELSIO_SET_TRACE_FILTER:{
-		struct ch_trace t;
-		const struct trace_params *tp;
-
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		if (!offload_running(adapter))
-			return -EAGAIN;
-		if (copy_from_user(&t, useraddr, sizeof(t)))
-			return -EFAULT;
-
-		tp = (const struct trace_params *)&t.sip;
-		if (t.config_tx)
-			t3_config_trace_filter(adapter, tp, 0,
-						t.invert_match,
-						t.trace_tx);
-		if (t.config_rx)
-			t3_config_trace_filter(adapter, tp, 1,
-						t.invert_match,
-						t.trace_rx);
-		break;
-	}
-	default:
-		return -EOPNOTSUPP;
-	}
-	return 0;
-}
-
-static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
-{
-	struct mii_ioctl_data *data = if_mii(req);
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-
-	switch (cmd) {
-	case SIOCGMIIREG:
-	case SIOCSMIIREG:
-		/* Convert phy_id from older PRTAD/DEVAD format */
-		if (is_10G(adapter) &&
-		    !mdio_phy_id_is_c45(data->phy_id) &&
-		    (data->phy_id & 0x1f00) &&
-		    !(data->phy_id & 0xe0e0))
-			data->phy_id = mdio_phy_id_c45(data->phy_id >> 8,
-						       data->phy_id & 0x1f);
-		/* FALLTHRU */
-	case SIOCGMIIPHY:
-		return mdio_mii_ioctl(&pi->phy.mdio, data, cmd);
-	case SIOCCHIOCTL:
-		return cxgb_extension_ioctl(dev, req->ifr_data);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static int cxgb_change_mtu(struct net_device *dev, int new_mtu)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	int ret;
-
-	if (new_mtu < 81)	/* accommodate SACK */
-		return -EINVAL;
-	if ((ret = t3_mac_set_mtu(&pi->mac, new_mtu)))
-		return ret;
-	dev->mtu = new_mtu;
-	init_port_mtus(adapter);
-	if (adapter->params.rev == 0 && offload_running(adapter))
-		t3_load_mtus(adapter, adapter->params.mtus,
-			     adapter->params.a_wnd, adapter->params.b_wnd,
-			     adapter->port[0]->mtu);
-	return 0;
-}
-
-static int cxgb_set_mac_addr(struct net_device *dev, void *p)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	struct sockaddr *addr = p;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EINVAL;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-	t3_mac_set_address(&pi->mac, LAN_MAC_IDX, dev->dev_addr);
-	if (offload_running(adapter))
-		write_smt_entry(adapter, pi->port_id);
-	return 0;
-}
-
-/**
- * t3_synchronize_rx - wait for current Rx processing on a port to complete
- * @adap: the adapter
- * @p: the port
- *
- * Ensures that current Rx processing on any of the queues associated with
- * the given port completes before returning.  We do this by acquiring and
- * releasing the locks of the response queues associated with the port.
- */
-static void t3_synchronize_rx(struct adapter *adap, const struct port_info *p)
-{
-	int i;
-
-	for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) {
-		struct sge_rspq *q = &adap->sge.qs[i].rspq;
-
-		spin_lock_irq(&q->lock);
-		spin_unlock_irq(&q->lock);
-	}
-}
-
-static void cxgb_vlan_mode(struct net_device *dev, u32 features)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-
-	if (adapter->params.rev > 0) {
-		t3_set_vlan_accel(adapter, 1 << pi->port_id,
-				  features & NETIF_F_HW_VLAN_RX);
-	} else {
-		/* single control for all ports */
-		unsigned int i, have_vlans = features & NETIF_F_HW_VLAN_RX;
-
-		for_each_port(adapter, i)
-			have_vlans |=
-				adapter->port[i]->features & NETIF_F_HW_VLAN_RX;
-
-		t3_set_vlan_accel(adapter, 1, have_vlans);
-	}
-	t3_synchronize_rx(adapter, pi);
-}
-
-static u32 cxgb_fix_features(struct net_device *dev, u32 features)
-{
-	/*
-	 * Since there is no support for separate rx/tx vlan accel
-	 * enable/disable make sure tx flag is always in same state as rx.
-	 */
-	if (features & NETIF_F_HW_VLAN_RX)
-		features |= NETIF_F_HW_VLAN_TX;
-	else
-		features &= ~NETIF_F_HW_VLAN_TX;
-
-	return features;
-}
-
-static int cxgb_set_features(struct net_device *dev, u32 features)
-{
-	u32 changed = dev->features ^ features;
-
-	if (changed & NETIF_F_HW_VLAN_RX)
-		cxgb_vlan_mode(dev, features);
-
-	return 0;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void cxgb_netpoll(struct net_device *dev)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	int qidx;
-
-	for (qidx = pi->first_qset; qidx < pi->first_qset + pi->nqsets; qidx++) {
-		struct sge_qset *qs = &adapter->sge.qs[qidx];
-		void *source;
-
-		if (adapter->flags & USING_MSIX)
-			source = qs;
-		else
-			source = adapter;
-
-		t3_intr_handler(adapter, qs->rspq.polling) (0, source);
-	}
-}
-#endif
-
-/*
- * Periodic accumulation of MAC statistics.
- */
-static void mac_stats_update(struct adapter *adapter)
-{
-	int i;
-
-	for_each_port(adapter, i) {
-		struct net_device *dev = adapter->port[i];
-		struct port_info *p = netdev_priv(dev);
-
-		if (netif_running(dev)) {
-			spin_lock(&adapter->stats_lock);
-			t3_mac_update_stats(&p->mac);
-			spin_unlock(&adapter->stats_lock);
-		}
-	}
-}
-
-static void check_link_status(struct adapter *adapter)
-{
-	int i;
-
-	for_each_port(adapter, i) {
-		struct net_device *dev = adapter->port[i];
-		struct port_info *p = netdev_priv(dev);
-		int link_fault;
-
-		spin_lock_irq(&adapter->work_lock);
-		link_fault = p->link_fault;
-		spin_unlock_irq(&adapter->work_lock);
-
-		if (link_fault) {
-			t3_link_fault(adapter, i);
-			continue;
-		}
-
-		if (!(p->phy.caps & SUPPORTED_IRQ) && netif_running(dev)) {
-			t3_xgm_intr_disable(adapter, i);
-			t3_read_reg(adapter, A_XGM_INT_STATUS + p->mac.offset);
-
-			t3_link_changed(adapter, i);
-			t3_xgm_intr_enable(adapter, i);
-		}
-	}
-}
-
-static void check_t3b2_mac(struct adapter *adapter)
-{
-	int i;
-
-	if (!rtnl_trylock())	/* synchronize with ifdown */
-		return;
-
-	for_each_port(adapter, i) {
-		struct net_device *dev = adapter->port[i];
-		struct port_info *p = netdev_priv(dev);
-		int status;
-
-		if (!netif_running(dev))
-			continue;
-
-		status = 0;
-		if (netif_running(dev) && netif_carrier_ok(dev))
-			status = t3b2_mac_watchdog_task(&p->mac);
-		if (status == 1)
-			p->mac.stats.num_toggled++;
-		else if (status == 2) {
-			struct cmac *mac = &p->mac;
-
-			t3_mac_set_mtu(mac, dev->mtu);
-			t3_mac_set_address(mac, LAN_MAC_IDX, dev->dev_addr);
-			cxgb_set_rxmode(dev);
-			t3_link_start(&p->phy, mac, &p->link_config);
-			t3_mac_enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
-			t3_port_intr_enable(adapter, p->port_id);
-			p->mac.stats.num_resets++;
-		}
-	}
-	rtnl_unlock();
-}
-
-
-static void t3_adap_check_task(struct work_struct *work)
-{
-	struct adapter *adapter = container_of(work, struct adapter,
-					       adap_check_task.work);
-	const struct adapter_params *p = &adapter->params;
-	int port;
-	unsigned int v, status, reset;
-
-	adapter->check_task_cnt++;
-
-	check_link_status(adapter);
-
-	/* Accumulate MAC stats if needed */
-	if (!p->linkpoll_period ||
-	    (adapter->check_task_cnt * p->linkpoll_period) / 10 >=
-	    p->stats_update_period) {
-		mac_stats_update(adapter);
-		adapter->check_task_cnt = 0;
-	}
-
-	if (p->rev == T3_REV_B2)
-		check_t3b2_mac(adapter);
-
-	/*
-	 * Scan the XGMAC's to check for various conditions which we want to
-	 * monitor in a periodic polling manner rather than via an interrupt
-	 * condition.  This is used for conditions which would otherwise flood
-	 * the system with interrupts and we only really need to know that the
-	 * conditions are "happening" ...  For each condition we count the
-	 * detection of the condition and reset it for the next polling loop.
-	 */
-	for_each_port(adapter, port) {
-		struct cmac *mac =  &adap2pinfo(adapter, port)->mac;
-		u32 cause;
-
-		cause = t3_read_reg(adapter, A_XGM_INT_CAUSE + mac->offset);
-		reset = 0;
-		if (cause & F_RXFIFO_OVERFLOW) {
-			mac->stats.rx_fifo_ovfl++;
-			reset |= F_RXFIFO_OVERFLOW;
-		}
-
-		t3_write_reg(adapter, A_XGM_INT_CAUSE + mac->offset, reset);
-	}
-
-	/*
-	 * We do the same as above for FL_EMPTY interrupts.
-	 */
-	status = t3_read_reg(adapter, A_SG_INT_CAUSE);
-	reset = 0;
-
-	if (status & F_FLEMPTY) {
-		struct sge_qset *qs = &adapter->sge.qs[0];
-		int i = 0;
-
-		reset |= F_FLEMPTY;
-
-		v = (t3_read_reg(adapter, A_SG_RSPQ_FL_STATUS) >> S_FL0EMPTY) &
-		    0xffff;
-
-		while (v) {
-			qs->fl[i].empty += (v & 1);
-			if (i)
-				qs++;
-			i ^= 1;
-			v >>= 1;
-		}
-	}
-
-	t3_write_reg(adapter, A_SG_INT_CAUSE, reset);
-
-	/* Schedule the next check update if any port is active. */
-	spin_lock_irq(&adapter->work_lock);
-	if (adapter->open_device_map & PORT_MASK)
-		schedule_chk_task(adapter);
-	spin_unlock_irq(&adapter->work_lock);
-}
-
-static void db_full_task(struct work_struct *work)
-{
-	struct adapter *adapter = container_of(work, struct adapter,
-					       db_full_task);
-
-	cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_FULL, 0);
-}
-
-static void db_empty_task(struct work_struct *work)
-{
-	struct adapter *adapter = container_of(work, struct adapter,
-					       db_empty_task);
-
-	cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_EMPTY, 0);
-}
-
-static void db_drop_task(struct work_struct *work)
-{
-	struct adapter *adapter = container_of(work, struct adapter,
-					       db_drop_task);
-	unsigned long delay = 1000;
-	unsigned short r;
-
-	cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_DROP, 0);
-
-	/*
-	 * Sleep a while before ringing the driver qset dbs.
-	 * The delay is between 1000-2023 usecs.
-	 */
-	get_random_bytes(&r, 2);
-	delay += r & 1023;
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(usecs_to_jiffies(delay));
-	ring_dbs(adapter);
-}
-
-/*
- * Processes external (PHY) interrupts in process context.
- */
-static void ext_intr_task(struct work_struct *work)
-{
-	struct adapter *adapter = container_of(work, struct adapter,
-					       ext_intr_handler_task);
-	int i;
-
-	/* Disable link fault interrupts */
-	for_each_port(adapter, i) {
-		struct net_device *dev = adapter->port[i];
-		struct port_info *p = netdev_priv(dev);
-
-		t3_xgm_intr_disable(adapter, i);
-		t3_read_reg(adapter, A_XGM_INT_STATUS + p->mac.offset);
-	}
-
-	/* Re-enable link fault interrupts */
-	t3_phy_intr_handler(adapter);
-
-	for_each_port(adapter, i)
-		t3_xgm_intr_enable(adapter, i);
-
-	/* Now reenable external interrupts */
-	spin_lock_irq(&adapter->work_lock);
-	if (adapter->slow_intr_mask) {
-		adapter->slow_intr_mask |= F_T3DBG;
-		t3_write_reg(adapter, A_PL_INT_CAUSE0, F_T3DBG);
-		t3_write_reg(adapter, A_PL_INT_ENABLE0,
-			     adapter->slow_intr_mask);
-	}
-	spin_unlock_irq(&adapter->work_lock);
-}
-
-/*
- * Interrupt-context handler for external (PHY) interrupts.
- */
-void t3_os_ext_intr_handler(struct adapter *adapter)
-{
-	/*
-	 * Schedule a task to handle external interrupts as they may be slow
-	 * and we use a mutex to protect MDIO registers.  We disable PHY
-	 * interrupts in the meantime and let the task reenable them when
-	 * it's done.
-	 */
-	spin_lock(&adapter->work_lock);
-	if (adapter->slow_intr_mask) {
-		adapter->slow_intr_mask &= ~F_T3DBG;
-		t3_write_reg(adapter, A_PL_INT_ENABLE0,
-			     adapter->slow_intr_mask);
-		queue_work(cxgb3_wq, &adapter->ext_intr_handler_task);
-	}
-	spin_unlock(&adapter->work_lock);
-}
-
-void t3_os_link_fault_handler(struct adapter *adapter, int port_id)
-{
-	struct net_device *netdev = adapter->port[port_id];
-	struct port_info *pi = netdev_priv(netdev);
-
-	spin_lock(&adapter->work_lock);
-	pi->link_fault = 1;
-	spin_unlock(&adapter->work_lock);
-}
-
-static int t3_adapter_error(struct adapter *adapter, int reset, int on_wq)
-{
-	int i, ret = 0;
-
-	if (is_offload(adapter) &&
-	    test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) {
-		cxgb3_event_notify(&adapter->tdev, OFFLOAD_STATUS_DOWN, 0);
-		offload_close(&adapter->tdev);
-	}
-
-	/* Stop all ports */
-	for_each_port(adapter, i) {
-		struct net_device *netdev = adapter->port[i];
-
-		if (netif_running(netdev))
-			__cxgb_close(netdev, on_wq);
-	}
-
-	/* Stop SGE timers */
-	t3_stop_sge_timers(adapter);
-
-	adapter->flags &= ~FULL_INIT_DONE;
-
-	if (reset)
-		ret = t3_reset_adapter(adapter);
-
-	pci_disable_device(adapter->pdev);
-
-	return ret;
-}
-
-static int t3_reenable_adapter(struct adapter *adapter)
-{
-	if (pci_enable_device(adapter->pdev)) {
-		dev_err(&adapter->pdev->dev,
-			"Cannot re-enable PCI device after reset.\n");
-		goto err;
-	}
-	pci_set_master(adapter->pdev);
-	pci_restore_state(adapter->pdev);
-	pci_save_state(adapter->pdev);
-
-	/* Free sge resources */
-	t3_free_sge_resources(adapter);
-
-	if (t3_replay_prep_adapter(adapter))
-		goto err;
-
-	return 0;
-err:
-	return -1;
-}
-
-static void t3_resume_ports(struct adapter *adapter)
-{
-	int i;
-
-	/* Restart the ports */
-	for_each_port(adapter, i) {
-		struct net_device *netdev = adapter->port[i];
-
-		if (netif_running(netdev)) {
-			if (cxgb_open(netdev)) {
-				dev_err(&adapter->pdev->dev,
-					"can't bring device back up"
-					" after reset\n");
-				continue;
-			}
-		}
-	}
-
-	if (is_offload(adapter) && !ofld_disable)
-		cxgb3_event_notify(&adapter->tdev, OFFLOAD_STATUS_UP, 0);
-}
-
-/*
- * processes a fatal error.
- * Bring the ports down, reset the chip, bring the ports back up.
- */
-static void fatal_error_task(struct work_struct *work)
-{
-	struct adapter *adapter = container_of(work, struct adapter,
-					       fatal_error_handler_task);
-	int err = 0;
-
-	rtnl_lock();
-	err = t3_adapter_error(adapter, 1, 1);
-	if (!err)
-		err = t3_reenable_adapter(adapter);
-	if (!err)
-		t3_resume_ports(adapter);
-
-	CH_ALERT(adapter, "adapter reset %s\n", err ? "failed" : "succeeded");
-	rtnl_unlock();
-}
-
-void t3_fatal_err(struct adapter *adapter)
-{
-	unsigned int fw_status[4];
-
-	if (adapter->flags & FULL_INIT_DONE) {
-		t3_sge_stop(adapter);
-		t3_write_reg(adapter, A_XGM_TX_CTRL, 0);
-		t3_write_reg(adapter, A_XGM_RX_CTRL, 0);
-		t3_write_reg(adapter, XGM_REG(A_XGM_TX_CTRL, 1), 0);
-		t3_write_reg(adapter, XGM_REG(A_XGM_RX_CTRL, 1), 0);
-
-		spin_lock(&adapter->work_lock);
-		t3_intr_disable(adapter);
-		queue_work(cxgb3_wq, &adapter->fatal_error_handler_task);
-		spin_unlock(&adapter->work_lock);
-	}
-	CH_ALERT(adapter, "encountered fatal error, operation suspended\n");
-	if (!t3_cim_ctl_blk_read(adapter, 0xa0, 4, fw_status))
-		CH_ALERT(adapter, "FW status: 0x%x, 0x%x, 0x%x, 0x%x\n",
-			 fw_status[0], fw_status[1],
-			 fw_status[2], fw_status[3]);
-}
-
-/**
- * t3_io_error_detected - called when PCI error is detected
- * @pdev: Pointer to PCI device
- * @state: The current pci connection state
- *
- * This function is called after a PCI bus error affecting
- * this device has been detected.
- */
-static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev,
-					     pci_channel_state_t state)
-{
-	struct adapter *adapter = pci_get_drvdata(pdev);
-
-	if (state == pci_channel_io_perm_failure)
-		return PCI_ERS_RESULT_DISCONNECT;
-
-	t3_adapter_error(adapter, 0, 0);
-
-	/* Request a slot reset. */
-	return PCI_ERS_RESULT_NEED_RESET;
-}
-
-/**
- * t3_io_slot_reset - called after the pci bus has been reset.
- * @pdev: Pointer to PCI device
- *
- * Restart the card from scratch, as if from a cold-boot.
- */
-static pci_ers_result_t t3_io_slot_reset(struct pci_dev *pdev)
-{
-	struct adapter *adapter = pci_get_drvdata(pdev);
-
-	if (!t3_reenable_adapter(adapter))
-		return PCI_ERS_RESULT_RECOVERED;
-
-	return PCI_ERS_RESULT_DISCONNECT;
-}
-
-/**
- * t3_io_resume - called when traffic can start flowing again.
- * @pdev: Pointer to PCI device
- *
- * This callback is called when the error recovery driver tells us that
- * its OK to resume normal operation.
- */
-static void t3_io_resume(struct pci_dev *pdev)
-{
-	struct adapter *adapter = pci_get_drvdata(pdev);
-
-	CH_ALERT(adapter, "adapter recovering, PEX ERR 0x%x\n",
-		 t3_read_reg(adapter, A_PCIE_PEX_ERR));
-
-	t3_resume_ports(adapter);
-}
-
-static struct pci_error_handlers t3_err_handler = {
-	.error_detected = t3_io_error_detected,
-	.slot_reset = t3_io_slot_reset,
-	.resume = t3_io_resume,
-};
-
-/*
- * Set the number of qsets based on the number of CPUs and the number of ports,
- * not to exceed the number of available qsets, assuming there are enough qsets
- * per port in HW.
- */
-static void set_nqsets(struct adapter *adap)
-{
-	int i, j = 0;
-	int num_cpus = num_online_cpus();
-	int hwports = adap->params.nports;
-	int nqsets = adap->msix_nvectors - 1;
-
-	if (adap->params.rev > 0 && adap->flags & USING_MSIX) {
-		if (hwports == 2 &&
-		    (hwports * nqsets > SGE_QSETS ||
-		     num_cpus >= nqsets / hwports))
-			nqsets /= hwports;
-		if (nqsets > num_cpus)
-			nqsets = num_cpus;
-		if (nqsets < 1 || hwports == 4)
-			nqsets = 1;
-	} else
-		nqsets = 1;
-
-	for_each_port(adap, i) {
-		struct port_info *pi = adap2pinfo(adap, i);
-
-		pi->first_qset = j;
-		pi->nqsets = nqsets;
-		j = pi->first_qset + nqsets;
-
-		dev_info(&adap->pdev->dev,
-			 "Port %d using %d queue sets.\n", i, nqsets);
-	}
-}
-
-static int __devinit cxgb_enable_msix(struct adapter *adap)
-{
-	struct msix_entry entries[SGE_QSETS + 1];
-	int vectors;
-	int i, err;
-
-	vectors = ARRAY_SIZE(entries);
-	for (i = 0; i < vectors; ++i)
-		entries[i].entry = i;
-
-	while ((err = pci_enable_msix(adap->pdev, entries, vectors)) > 0)
-		vectors = err;
-
-	if (err < 0)
-		pci_disable_msix(adap->pdev);
-
-	if (!err && vectors < (adap->params.nports + 1)) {
-		pci_disable_msix(adap->pdev);
-		err = -1;
-	}
-
-	if (!err) {
-		for (i = 0; i < vectors; ++i)
-			adap->msix_info[i].vec = entries[i].vector;
-		adap->msix_nvectors = vectors;
-	}
-
-	return err;
-}
-
-static void __devinit print_port_info(struct adapter *adap,
-				      const struct adapter_info *ai)
-{
-	static const char *pci_variant[] = {
-		"PCI", "PCI-X", "PCI-X ECC", "PCI-X 266", "PCI Express"
-	};
-
-	int i;
-	char buf[80];
-
-	if (is_pcie(adap))
-		snprintf(buf, sizeof(buf), "%s x%d",
-			 pci_variant[adap->params.pci.variant],
-			 adap->params.pci.width);
-	else
-		snprintf(buf, sizeof(buf), "%s %dMHz/%d-bit",
-			 pci_variant[adap->params.pci.variant],
-			 adap->params.pci.speed, adap->params.pci.width);
-
-	for_each_port(adap, i) {
-		struct net_device *dev = adap->port[i];
-		const struct port_info *pi = netdev_priv(dev);
-
-		if (!test_bit(i, &adap->registered_device_map))
-			continue;
-		printk(KERN_INFO "%s: %s %s %sNIC (rev %d) %s%s\n",
-		       dev->name, ai->desc, pi->phy.desc,
-		       is_offload(adap) ? "R" : "", adap->params.rev, buf,
-		       (adap->flags & USING_MSIX) ? " MSI-X" :
-		       (adap->flags & USING_MSI) ? " MSI" : "");
-		if (adap->name == dev->name && adap->params.vpd.mclk)
-			printk(KERN_INFO
-			       "%s: %uMB CM, %uMB PMTX, %uMB PMRX, S/N: %s\n",
-			       adap->name, t3_mc7_size(&adap->cm) >> 20,
-			       t3_mc7_size(&adap->pmtx) >> 20,
-			       t3_mc7_size(&adap->pmrx) >> 20,
-			       adap->params.vpd.sn);
-	}
-}
-
-static const struct net_device_ops cxgb_netdev_ops = {
-	.ndo_open		= cxgb_open,
-	.ndo_stop		= cxgb_close,
-	.ndo_start_xmit		= t3_eth_xmit,
-	.ndo_get_stats		= cxgb_get_stats,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_multicast_list	= cxgb_set_rxmode,
-	.ndo_do_ioctl		= cxgb_ioctl,
-	.ndo_change_mtu		= cxgb_change_mtu,
-	.ndo_set_mac_address	= cxgb_set_mac_addr,
-	.ndo_fix_features	= cxgb_fix_features,
-	.ndo_set_features	= cxgb_set_features,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= cxgb_netpoll,
-#endif
-};
-
-static void __devinit cxgb3_init_iscsi_mac(struct net_device *dev)
-{
-	struct port_info *pi = netdev_priv(dev);
-
-	memcpy(pi->iscsic.mac_addr, dev->dev_addr, ETH_ALEN);
-	pi->iscsic.mac_addr[3] |= 0x80;
-}
-
-static int __devinit init_one(struct pci_dev *pdev,
-			      const struct pci_device_id *ent)
-{
-	static int version_printed;
-
-	int i, err, pci_using_dac = 0;
-	resource_size_t mmio_start, mmio_len;
-	const struct adapter_info *ai;
-	struct adapter *adapter = NULL;
-	struct port_info *pi;
-
-	if (!version_printed) {
-		printk(KERN_INFO "%s - version %s\n", DRV_DESC, DRV_VERSION);
-		++version_printed;
-	}
-
-	if (!cxgb3_wq) {
-		cxgb3_wq = create_singlethread_workqueue(DRV_NAME);
-		if (!cxgb3_wq) {
-			printk(KERN_ERR DRV_NAME
-			       ": cannot initialize work queue\n");
-			return -ENOMEM;
-		}
-	}
-
-	err = pci_enable_device(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "cannot enable PCI device\n");
-		goto out;
-	}
-
-	err = pci_request_regions(pdev, DRV_NAME);
-	if (err) {
-		/* Just info, some other driver may have claimed the device. */
-		dev_info(&pdev->dev, "cannot obtain PCI resources\n");
-		goto out_disable_device;
-	}
-
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-		pci_using_dac = 1;
-		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
-		if (err) {
-			dev_err(&pdev->dev, "unable to obtain 64-bit DMA for "
-			       "coherent allocations\n");
-			goto out_release_regions;
-		}
-	} else if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) {
-		dev_err(&pdev->dev, "no usable DMA configuration\n");
-		goto out_release_regions;
-	}
-
-	pci_set_master(pdev);
-	pci_save_state(pdev);
-
-	mmio_start = pci_resource_start(pdev, 0);
-	mmio_len = pci_resource_len(pdev, 0);
-	ai = t3_get_adapter_info(ent->driver_data);
-
-	adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
-	if (!adapter) {
-		err = -ENOMEM;
-		goto out_release_regions;
-	}
-
-	adapter->nofail_skb =
-		alloc_skb(sizeof(struct cpl_set_tcb_field), GFP_KERNEL);
-	if (!adapter->nofail_skb) {
-		dev_err(&pdev->dev, "cannot allocate nofail buffer\n");
-		err = -ENOMEM;
-		goto out_free_adapter;
-	}
-
-	adapter->regs = ioremap_nocache(mmio_start, mmio_len);
-	if (!adapter->regs) {
-		dev_err(&pdev->dev, "cannot map device registers\n");
-		err = -ENOMEM;
-		goto out_free_adapter;
-	}
-
-	adapter->pdev = pdev;
-	adapter->name = pci_name(pdev);
-	adapter->msg_enable = dflt_msg_enable;
-	adapter->mmio_len = mmio_len;
-
-	mutex_init(&adapter->mdio_lock);
-	spin_lock_init(&adapter->work_lock);
-	spin_lock_init(&adapter->stats_lock);
-
-	INIT_LIST_HEAD(&adapter->adapter_list);
-	INIT_WORK(&adapter->ext_intr_handler_task, ext_intr_task);
-	INIT_WORK(&adapter->fatal_error_handler_task, fatal_error_task);
-
-	INIT_WORK(&adapter->db_full_task, db_full_task);
-	INIT_WORK(&adapter->db_empty_task, db_empty_task);
-	INIT_WORK(&adapter->db_drop_task, db_drop_task);
-
-	INIT_DELAYED_WORK(&adapter->adap_check_task, t3_adap_check_task);
-
-	for (i = 0; i < ai->nports0 + ai->nports1; ++i) {
-		struct net_device *netdev;
-
-		netdev = alloc_etherdev_mq(sizeof(struct port_info), SGE_QSETS);
-		if (!netdev) {
-			err = -ENOMEM;
-			goto out_free_dev;
-		}
-
-		SET_NETDEV_DEV(netdev, &pdev->dev);
-
-		adapter->port[i] = netdev;
-		pi = netdev_priv(netdev);
-		pi->adapter = adapter;
-		pi->port_id = i;
-		netif_carrier_off(netdev);
-		netdev->irq = pdev->irq;
-		netdev->mem_start = mmio_start;
-		netdev->mem_end = mmio_start + mmio_len - 1;
-		netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
-			NETIF_F_TSO | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX;
-		netdev->features |= netdev->hw_features | NETIF_F_HW_VLAN_TX;
-		if (pci_using_dac)
-			netdev->features |= NETIF_F_HIGHDMA;
-
-		netdev->netdev_ops = &cxgb_netdev_ops;
-		SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops);
-	}
-
-	pci_set_drvdata(pdev, adapter);
-	if (t3_prep_adapter(adapter, ai, 1) < 0) {
-		err = -ENODEV;
-		goto out_free_dev;
-	}
-
-	/*
-	 * The card is now ready to go.  If any errors occur during device
-	 * registration we do not fail the whole card but rather proceed only
-	 * with the ports we manage to register successfully.  However we must
-	 * register at least one net device.
-	 */
-	for_each_port(adapter, i) {
-		err = register_netdev(adapter->port[i]);
-		if (err)
-			dev_warn(&pdev->dev,
-				 "cannot register net device %s, skipping\n",
-				 adapter->port[i]->name);
-		else {
-			/*
-			 * Change the name we use for messages to the name of
-			 * the first successfully registered interface.
-			 */
-			if (!adapter->registered_device_map)
-				adapter->name = adapter->port[i]->name;
-
-			__set_bit(i, &adapter->registered_device_map);
-		}
-	}
-	if (!adapter->registered_device_map) {
-		dev_err(&pdev->dev, "could not register any net devices\n");
-		goto out_free_dev;
-	}
-
-	for_each_port(adapter, i)
-		cxgb3_init_iscsi_mac(adapter->port[i]);
-
-	/* Driver's ready. Reflect it on LEDs */
-	t3_led_ready(adapter);
-
-	if (is_offload(adapter)) {
-		__set_bit(OFFLOAD_DEVMAP_BIT, &adapter->registered_device_map);
-		cxgb3_adapter_ofld(adapter);
-	}
-
-	/* See what interrupts we'll be using */
-	if (msi > 1 && cxgb_enable_msix(adapter) == 0)
-		adapter->flags |= USING_MSIX;
-	else if (msi > 0 && pci_enable_msi(pdev) == 0)
-		adapter->flags |= USING_MSI;
-
-	set_nqsets(adapter);
-
-	err = sysfs_create_group(&adapter->port[0]->dev.kobj,
-				 &cxgb3_attr_group);
-
-	for_each_port(adapter, i)
-		cxgb_vlan_mode(adapter->port[i], adapter->port[i]->features);
-
-	print_port_info(adapter, ai);
-	return 0;
-
-out_free_dev:
-	iounmap(adapter->regs);
-	for (i = ai->nports0 + ai->nports1 - 1; i >= 0; --i)
-		if (adapter->port[i])
-			free_netdev(adapter->port[i]);
-
-out_free_adapter:
-	kfree(adapter);
-
-out_release_regions:
-	pci_release_regions(pdev);
-out_disable_device:
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-out:
-	return err;
-}
-
-static void __devexit remove_one(struct pci_dev *pdev)
-{
-	struct adapter *adapter = pci_get_drvdata(pdev);
-
-	if (adapter) {
-		int i;
-
-		t3_sge_stop(adapter);
-		sysfs_remove_group(&adapter->port[0]->dev.kobj,
-				   &cxgb3_attr_group);
-
-		if (is_offload(adapter)) {
-			cxgb3_adapter_unofld(adapter);
-			if (test_bit(OFFLOAD_DEVMAP_BIT,
-				     &adapter->open_device_map))
-				offload_close(&adapter->tdev);
-		}
-
-		for_each_port(adapter, i)
-		    if (test_bit(i, &adapter->registered_device_map))
-			unregister_netdev(adapter->port[i]);
-
-		t3_stop_sge_timers(adapter);
-		t3_free_sge_resources(adapter);
-		cxgb_disable_msi(adapter);
-
-		for_each_port(adapter, i)
-			if (adapter->port[i])
-				free_netdev(adapter->port[i]);
-
-		iounmap(adapter->regs);
-		if (adapter->nofail_skb)
-			kfree_skb(adapter->nofail_skb);
-		kfree(adapter);
-		pci_release_regions(pdev);
-		pci_disable_device(pdev);
-		pci_set_drvdata(pdev, NULL);
-	}
-}
-
-static struct pci_driver driver = {
-	.name = DRV_NAME,
-	.id_table = cxgb3_pci_tbl,
-	.probe = init_one,
-	.remove = __devexit_p(remove_one),
-	.err_handler = &t3_err_handler,
-};
-
-static int __init cxgb3_init_module(void)
-{
-	int ret;
-
-	cxgb3_offload_init();
-
-	ret = pci_register_driver(&driver);
-	return ret;
-}
-
-static void __exit cxgb3_cleanup_module(void)
-{
-	pci_unregister_driver(&driver);
-	if (cxgb3_wq)
-		destroy_workqueue(cxgb3_wq);
-}
-
-module_init(cxgb3_init_module);
-module_exit(cxgb3_cleanup_module);
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/cxgb3_offload.c linux-libre-3.2-gnu/drivers/net/cxgb3/cxgb3_offload.c
--- linux-libre-3.1-gnu/drivers/net/cxgb3/cxgb3_offload.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/cxgb3_offload.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1431 +0,0 @@
-/*
- * Copyright (c) 2006-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <net/neighbour.h>
-#include <linux/notifier.h>
-#include <linux/atomic.h>
-#include <linux/proc_fs.h>
-#include <linux/if_vlan.h>
-#include <net/netevent.h>
-#include <linux/highmem.h>
-#include <linux/vmalloc.h>
-
-#include "common.h"
-#include "regs.h"
-#include "cxgb3_ioctl.h"
-#include "cxgb3_ctl_defs.h"
-#include "cxgb3_defs.h"
-#include "l2t.h"
-#include "firmware_exports.h"
-#include "cxgb3_offload.h"
-
-static LIST_HEAD(client_list);
-static LIST_HEAD(ofld_dev_list);
-static DEFINE_MUTEX(cxgb3_db_lock);
-
-static DEFINE_RWLOCK(adapter_list_lock);
-static LIST_HEAD(adapter_list);
-
-static const unsigned int MAX_ATIDS = 64 * 1024;
-static const unsigned int ATID_BASE = 0x10000;
-
-static void cxgb_neigh_update(struct neighbour *neigh);
-static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new);
-
-static inline int offload_activated(struct t3cdev *tdev)
-{
-	const struct adapter *adapter = tdev2adap(tdev);
-
-	return test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map);
-}
-
-/**
- *	cxgb3_register_client - register an offload client
- *	@client: the client
- *
- *	Add the client to the client list,
- *	and call backs the client for each activated offload device
- */
-void cxgb3_register_client(struct cxgb3_client *client)
-{
-	struct t3cdev *tdev;
-
-	mutex_lock(&cxgb3_db_lock);
-	list_add_tail(&client->client_list, &client_list);
-
-	if (client->add) {
-		list_for_each_entry(tdev, &ofld_dev_list, ofld_dev_list) {
-			if (offload_activated(tdev))
-				client->add(tdev);
-		}
-	}
-	mutex_unlock(&cxgb3_db_lock);
-}
-
-EXPORT_SYMBOL(cxgb3_register_client);
-
-/**
- *	cxgb3_unregister_client - unregister an offload client
- *	@client: the client
- *
- *	Remove the client to the client list,
- *	and call backs the client for each activated offload device.
- */
-void cxgb3_unregister_client(struct cxgb3_client *client)
-{
-	struct t3cdev *tdev;
-
-	mutex_lock(&cxgb3_db_lock);
-	list_del(&client->client_list);
-
-	if (client->remove) {
-		list_for_each_entry(tdev, &ofld_dev_list, ofld_dev_list) {
-			if (offload_activated(tdev))
-				client->remove(tdev);
-		}
-	}
-	mutex_unlock(&cxgb3_db_lock);
-}
-
-EXPORT_SYMBOL(cxgb3_unregister_client);
-
-/**
- *	cxgb3_add_clients - activate registered clients for an offload device
- *	@tdev: the offload device
- *
- *	Call backs all registered clients once a offload device is activated
- */
-void cxgb3_add_clients(struct t3cdev *tdev)
-{
-	struct cxgb3_client *client;
-
-	mutex_lock(&cxgb3_db_lock);
-	list_for_each_entry(client, &client_list, client_list) {
-		if (client->add)
-			client->add(tdev);
-	}
-	mutex_unlock(&cxgb3_db_lock);
-}
-
-/**
- *	cxgb3_remove_clients - deactivates registered clients
- *			       for an offload device
- *	@tdev: the offload device
- *
- *	Call backs all registered clients once a offload device is deactivated
- */
-void cxgb3_remove_clients(struct t3cdev *tdev)
-{
-	struct cxgb3_client *client;
-
-	mutex_lock(&cxgb3_db_lock);
-	list_for_each_entry(client, &client_list, client_list) {
-		if (client->remove)
-			client->remove(tdev);
-	}
-	mutex_unlock(&cxgb3_db_lock);
-}
-
-void cxgb3_event_notify(struct t3cdev *tdev, u32 event, u32 port)
-{
-	struct cxgb3_client *client;
-
-	mutex_lock(&cxgb3_db_lock);
-	list_for_each_entry(client, &client_list, client_list) {
-		if (client->event_handler)
-			client->event_handler(tdev, event, port);
-	}
-	mutex_unlock(&cxgb3_db_lock);
-}
-
-static struct net_device *get_iff_from_mac(struct adapter *adapter,
-					   const unsigned char *mac,
-					   unsigned int vlan)
-{
-	int i;
-
-	for_each_port(adapter, i) {
-		struct net_device *dev = adapter->port[i];
-
-		if (!memcmp(dev->dev_addr, mac, ETH_ALEN)) {
-			if (vlan && vlan != VLAN_VID_MASK) {
-				rcu_read_lock();
-				dev = __vlan_find_dev_deep(dev, vlan);
-				rcu_read_unlock();
-			} else if (netif_is_bond_slave(dev)) {
-				while (dev->master)
-					dev = dev->master;
-			}
-			return dev;
-		}
-	}
-	return NULL;
-}
-
-static int cxgb_ulp_iscsi_ctl(struct adapter *adapter, unsigned int req,
-			      void *data)
-{
-	int i;
-	int ret = 0;
-	unsigned int val = 0;
-	struct ulp_iscsi_info *uiip = data;
-
-	switch (req) {
-	case ULP_ISCSI_GET_PARAMS:
-		uiip->pdev = adapter->pdev;
-		uiip->llimit = t3_read_reg(adapter, A_ULPRX_ISCSI_LLIMIT);
-		uiip->ulimit = t3_read_reg(adapter, A_ULPRX_ISCSI_ULIMIT);
-		uiip->tagmask = t3_read_reg(adapter, A_ULPRX_ISCSI_TAGMASK);
-
-		val = t3_read_reg(adapter, A_ULPRX_ISCSI_PSZ);
-		for (i = 0; i < 4; i++, val >>= 8)
-			uiip->pgsz_factor[i] = val & 0xFF;
-
-		val = t3_read_reg(adapter, A_TP_PARA_REG7);
-		uiip->max_txsz =
-		uiip->max_rxsz = min((val >> S_PMMAXXFERLEN0)&M_PMMAXXFERLEN0,
-				     (val >> S_PMMAXXFERLEN1)&M_PMMAXXFERLEN1);
-		/*
-		 * On tx, the iscsi pdu has to be <= tx page size and has to
-		 * fit into the Tx PM FIFO.
-		 */
-		val = min(adapter->params.tp.tx_pg_size,
-			  t3_read_reg(adapter, A_PM1_TX_CFG) >> 17);
-		uiip->max_txsz = min(val, uiip->max_txsz);
-
-		/* set MaxRxData to 16224 */
-		val = t3_read_reg(adapter, A_TP_PARA_REG2);
-		if ((val >> S_MAXRXDATA) != 0x3f60) {
-			val &= (M_RXCOALESCESIZE << S_RXCOALESCESIZE);
-			val |= V_MAXRXDATA(0x3f60);
-			printk(KERN_INFO
-				"%s, iscsi set MaxRxData to 16224 (0x%x).\n",
-				adapter->name, val);
-			t3_write_reg(adapter, A_TP_PARA_REG2, val);
-		}
-
-		/*
-		 * on rx, the iscsi pdu has to be < rx page size and the
-		 * the max rx data length programmed in TP
-		 */
-		val = min(adapter->params.tp.rx_pg_size,
-			  ((t3_read_reg(adapter, A_TP_PARA_REG2)) >>
-				S_MAXRXDATA) & M_MAXRXDATA);
-		uiip->max_rxsz = min(val, uiip->max_rxsz);
-		break;
-	case ULP_ISCSI_SET_PARAMS:
-		t3_write_reg(adapter, A_ULPRX_ISCSI_TAGMASK, uiip->tagmask);
-		/* program the ddp page sizes */
-		for (i = 0; i < 4; i++)
-			val |= (uiip->pgsz_factor[i] & 0xF) << (8 * i);
-		if (val && (val != t3_read_reg(adapter, A_ULPRX_ISCSI_PSZ))) {
-			printk(KERN_INFO
-				"%s, setting iscsi pgsz 0x%x, %u,%u,%u,%u.\n",
-				adapter->name, val, uiip->pgsz_factor[0],
-				uiip->pgsz_factor[1], uiip->pgsz_factor[2],
-				uiip->pgsz_factor[3]);
-			t3_write_reg(adapter, A_ULPRX_ISCSI_PSZ, val);
-		}
-		break;
-	default:
-		ret = -EOPNOTSUPP;
-	}
-	return ret;
-}
-
-/* Response queue used for RDMA events. */
-#define ASYNC_NOTIF_RSPQ 0
-
-static int cxgb_rdma_ctl(struct adapter *adapter, unsigned int req, void *data)
-{
-	int ret = 0;
-
-	switch (req) {
-	case RDMA_GET_PARAMS: {
-		struct rdma_info *rdma = data;
-		struct pci_dev *pdev = adapter->pdev;
-
-		rdma->udbell_physbase = pci_resource_start(pdev, 2);
-		rdma->udbell_len = pci_resource_len(pdev, 2);
-		rdma->tpt_base =
-			t3_read_reg(adapter, A_ULPTX_TPT_LLIMIT);
-		rdma->tpt_top = t3_read_reg(adapter, A_ULPTX_TPT_ULIMIT);
-		rdma->pbl_base =
-			t3_read_reg(adapter, A_ULPTX_PBL_LLIMIT);
-		rdma->pbl_top = t3_read_reg(adapter, A_ULPTX_PBL_ULIMIT);
-		rdma->rqt_base = t3_read_reg(adapter, A_ULPRX_RQ_LLIMIT);
-		rdma->rqt_top = t3_read_reg(adapter, A_ULPRX_RQ_ULIMIT);
-		rdma->kdb_addr = adapter->regs + A_SG_KDOORBELL;
-		rdma->pdev = pdev;
-		break;
-	}
-	case RDMA_CQ_OP:{
-		unsigned long flags;
-		struct rdma_cq_op *rdma = data;
-
-		/* may be called in any context */
-		spin_lock_irqsave(&adapter->sge.reg_lock, flags);
-		ret = t3_sge_cqcntxt_op(adapter, rdma->id, rdma->op,
-					rdma->credits);
-		spin_unlock_irqrestore(&adapter->sge.reg_lock, flags);
-		break;
-	}
-	case RDMA_GET_MEM:{
-		struct ch_mem_range *t = data;
-		struct mc7 *mem;
-
-		if ((t->addr & 7) || (t->len & 7))
-			return -EINVAL;
-		if (t->mem_id == MEM_CM)
-			mem = &adapter->cm;
-		else if (t->mem_id == MEM_PMRX)
-			mem = &adapter->pmrx;
-		else if (t->mem_id == MEM_PMTX)
-			mem = &adapter->pmtx;
-		else
-			return -EINVAL;
-
-		ret =
-			t3_mc7_bd_read(mem, t->addr / 8, t->len / 8,
-					(u64 *) t->buf);
-		if (ret)
-			return ret;
-		break;
-	}
-	case RDMA_CQ_SETUP:{
-		struct rdma_cq_setup *rdma = data;
-
-		spin_lock_irq(&adapter->sge.reg_lock);
-		ret =
-			t3_sge_init_cqcntxt(adapter, rdma->id,
-					rdma->base_addr, rdma->size,
-					ASYNC_NOTIF_RSPQ,
-					rdma->ovfl_mode, rdma->credits,
-					rdma->credit_thres);
-		spin_unlock_irq(&adapter->sge.reg_lock);
-		break;
-	}
-	case RDMA_CQ_DISABLE:
-		spin_lock_irq(&adapter->sge.reg_lock);
-		ret = t3_sge_disable_cqcntxt(adapter, *(unsigned int *)data);
-		spin_unlock_irq(&adapter->sge.reg_lock);
-		break;
-	case RDMA_CTRL_QP_SETUP:{
-		struct rdma_ctrlqp_setup *rdma = data;
-
-		spin_lock_irq(&adapter->sge.reg_lock);
-		ret = t3_sge_init_ecntxt(adapter, FW_RI_SGEEC_START, 0,
-						SGE_CNTXT_RDMA,
-						ASYNC_NOTIF_RSPQ,
-						rdma->base_addr, rdma->size,
-						FW_RI_TID_START, 1, 0);
-		spin_unlock_irq(&adapter->sge.reg_lock);
-		break;
-	}
-	case RDMA_GET_MIB: {
-		spin_lock(&adapter->stats_lock);
-		t3_tp_get_mib_stats(adapter, (struct tp_mib_stats *)data);
-		spin_unlock(&adapter->stats_lock);
-		break;
-	}
-	default:
-		ret = -EOPNOTSUPP;
-	}
-	return ret;
-}
-
-static int cxgb_offload_ctl(struct t3cdev *tdev, unsigned int req, void *data)
-{
-	struct adapter *adapter = tdev2adap(tdev);
-	struct tid_range *tid;
-	struct mtutab *mtup;
-	struct iff_mac *iffmacp;
-	struct ddp_params *ddpp;
-	struct adap_ports *ports;
-	struct ofld_page_info *rx_page_info;
-	struct tp_params *tp = &adapter->params.tp;
-	int i;
-
-	switch (req) {
-	case GET_MAX_OUTSTANDING_WR:
-		*(unsigned int *)data = FW_WR_NUM;
-		break;
-	case GET_WR_LEN:
-		*(unsigned int *)data = WR_FLITS;
-		break;
-	case GET_TX_MAX_CHUNK:
-		*(unsigned int *)data = 1 << 20;	/* 1MB */
-		break;
-	case GET_TID_RANGE:
-		tid = data;
-		tid->num = t3_mc5_size(&adapter->mc5) -
-		    adapter->params.mc5.nroutes -
-		    adapter->params.mc5.nfilters - adapter->params.mc5.nservers;
-		tid->base = 0;
-		break;
-	case GET_STID_RANGE:
-		tid = data;
-		tid->num = adapter->params.mc5.nservers;
-		tid->base = t3_mc5_size(&adapter->mc5) - tid->num -
-		    adapter->params.mc5.nfilters - adapter->params.mc5.nroutes;
-		break;
-	case GET_L2T_CAPACITY:
-		*(unsigned int *)data = 2048;
-		break;
-	case GET_MTUS:
-		mtup = data;
-		mtup->size = NMTUS;
-		mtup->mtus = adapter->params.mtus;
-		break;
-	case GET_IFF_FROM_MAC:
-		iffmacp = data;
-		iffmacp->dev = get_iff_from_mac(adapter, iffmacp->mac_addr,
-						iffmacp->vlan_tag &
-						VLAN_VID_MASK);
-		break;
-	case GET_DDP_PARAMS:
-		ddpp = data;
-		ddpp->llimit = t3_read_reg(adapter, A_ULPRX_TDDP_LLIMIT);
-		ddpp->ulimit = t3_read_reg(adapter, A_ULPRX_TDDP_ULIMIT);
-		ddpp->tag_mask = t3_read_reg(adapter, A_ULPRX_TDDP_TAGMASK);
-		break;
-	case GET_PORTS:
-		ports = data;
-		ports->nports = adapter->params.nports;
-		for_each_port(adapter, i)
-			ports->lldevs[i] = adapter->port[i];
-		break;
-	case ULP_ISCSI_GET_PARAMS:
-	case ULP_ISCSI_SET_PARAMS:
-		if (!offload_running(adapter))
-			return -EAGAIN;
-		return cxgb_ulp_iscsi_ctl(adapter, req, data);
-	case RDMA_GET_PARAMS:
-	case RDMA_CQ_OP:
-	case RDMA_CQ_SETUP:
-	case RDMA_CQ_DISABLE:
-	case RDMA_CTRL_QP_SETUP:
-	case RDMA_GET_MEM:
-	case RDMA_GET_MIB:
-		if (!offload_running(adapter))
-			return -EAGAIN;
-		return cxgb_rdma_ctl(adapter, req, data);
-	case GET_RX_PAGE_INFO:
-		rx_page_info = data;
-		rx_page_info->page_size = tp->rx_pg_size;
-		rx_page_info->num = tp->rx_num_pgs;
-		break;
-	case GET_ISCSI_IPV4ADDR: {
-		struct iscsi_ipv4addr *p = data;
-		struct port_info *pi = netdev_priv(p->dev);
-		p->ipv4addr = pi->iscsi_ipv4addr;
-		break;
-	}
-	case GET_EMBEDDED_INFO: {
-		struct ch_embedded_info *e = data;
-
-		spin_lock(&adapter->stats_lock);
-		t3_get_fw_version(adapter, &e->fw_vers);
-		t3_get_tp_version(adapter, &e->tp_vers);
-		spin_unlock(&adapter->stats_lock);
-		break;
-	}
-	default:
-		return -EOPNOTSUPP;
-	}
-	return 0;
-}
-
-/*
- * Dummy handler for Rx offload packets in case we get an offload packet before
- * proper processing is setup.  This complains and drops the packet as it isn't
- * normal to get offload packets at this stage.
- */
-static int rx_offload_blackhole(struct t3cdev *dev, struct sk_buff **skbs,
-				int n)
-{
-	while (n--)
-		dev_kfree_skb_any(skbs[n]);
-	return 0;
-}
-
-static void dummy_neigh_update(struct t3cdev *dev, struct neighbour *neigh)
-{
-}
-
-void cxgb3_set_dummy_ops(struct t3cdev *dev)
-{
-	dev->recv = rx_offload_blackhole;
-	dev->neigh_update = dummy_neigh_update;
-}
-
-/*
- * Free an active-open TID.
- */
-void *cxgb3_free_atid(struct t3cdev *tdev, int atid)
-{
-	struct tid_info *t = &(T3C_DATA(tdev))->tid_maps;
-	union active_open_entry *p = atid2entry(t, atid);
-	void *ctx = p->t3c_tid.ctx;
-
-	spin_lock_bh(&t->atid_lock);
-	p->next = t->afree;
-	t->afree = p;
-	t->atids_in_use--;
-	spin_unlock_bh(&t->atid_lock);
-
-	return ctx;
-}
-
-EXPORT_SYMBOL(cxgb3_free_atid);
-
-/*
- * Free a server TID and return it to the free pool.
- */
-void cxgb3_free_stid(struct t3cdev *tdev, int stid)
-{
-	struct tid_info *t = &(T3C_DATA(tdev))->tid_maps;
-	union listen_entry *p = stid2entry(t, stid);
-
-	spin_lock_bh(&t->stid_lock);
-	p->next = t->sfree;
-	t->sfree = p;
-	t->stids_in_use--;
-	spin_unlock_bh(&t->stid_lock);
-}
-
-EXPORT_SYMBOL(cxgb3_free_stid);
-
-void cxgb3_insert_tid(struct t3cdev *tdev, struct cxgb3_client *client,
-		      void *ctx, unsigned int tid)
-{
-	struct tid_info *t = &(T3C_DATA(tdev))->tid_maps;
-
-	t->tid_tab[tid].client = client;
-	t->tid_tab[tid].ctx = ctx;
-	atomic_inc(&t->tids_in_use);
-}
-
-EXPORT_SYMBOL(cxgb3_insert_tid);
-
-/*
- * Populate a TID_RELEASE WR.  The skb must be already propely sized.
- */
-static inline void mk_tid_release(struct sk_buff *skb, unsigned int tid)
-{
-	struct cpl_tid_release *req;
-
-	skb->priority = CPL_PRIORITY_SETUP;
-	req = (struct cpl_tid_release *)__skb_put(skb, sizeof(*req));
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_TID_RELEASE, tid));
-}
-
-static void t3_process_tid_release_list(struct work_struct *work)
-{
-	struct t3c_data *td = container_of(work, struct t3c_data,
-					   tid_release_task);
-	struct sk_buff *skb;
-	struct t3cdev *tdev = td->dev;
-
-
-	spin_lock_bh(&td->tid_release_lock);
-	while (td->tid_release_list) {
-		struct t3c_tid_entry *p = td->tid_release_list;
-
-		td->tid_release_list = p->ctx;
-		spin_unlock_bh(&td->tid_release_lock);
-
-		skb = alloc_skb(sizeof(struct cpl_tid_release),
-				GFP_KERNEL);
-		if (!skb)
-			skb = td->nofail_skb;
-		if (!skb) {
-			spin_lock_bh(&td->tid_release_lock);
-			p->ctx = (void *)td->tid_release_list;
-			td->tid_release_list = (struct t3c_tid_entry *)p;
-			break;
-		}
-		mk_tid_release(skb, p - td->tid_maps.tid_tab);
-		cxgb3_ofld_send(tdev, skb);
-		p->ctx = NULL;
-		if (skb == td->nofail_skb)
-			td->nofail_skb =
-				alloc_skb(sizeof(struct cpl_tid_release),
-					GFP_KERNEL);
-		spin_lock_bh(&td->tid_release_lock);
-	}
-	td->release_list_incomplete = (td->tid_release_list == NULL) ? 0 : 1;
-	spin_unlock_bh(&td->tid_release_lock);
-
-	if (!td->nofail_skb)
-		td->nofail_skb =
-			alloc_skb(sizeof(struct cpl_tid_release),
-				GFP_KERNEL);
-}
-
-/* use ctx as a next pointer in the tid release list */
-void cxgb3_queue_tid_release(struct t3cdev *tdev, unsigned int tid)
-{
-	struct t3c_data *td = T3C_DATA(tdev);
-	struct t3c_tid_entry *p = &td->tid_maps.tid_tab[tid];
-
-	spin_lock_bh(&td->tid_release_lock);
-	p->ctx = (void *)td->tid_release_list;
-	p->client = NULL;
-	td->tid_release_list = p;
-	if (!p->ctx || td->release_list_incomplete)
-		schedule_work(&td->tid_release_task);
-	spin_unlock_bh(&td->tid_release_lock);
-}
-
-EXPORT_SYMBOL(cxgb3_queue_tid_release);
-
-/*
- * Remove a tid from the TID table.  A client may defer processing its last
- * CPL message if it is locked at the time it arrives, and while the message
- * sits in the client's backlog the TID may be reused for another connection.
- * To handle this we atomically switch the TID association if it still points
- * to the original client context.
- */
-void cxgb3_remove_tid(struct t3cdev *tdev, void *ctx, unsigned int tid)
-{
-	struct tid_info *t = &(T3C_DATA(tdev))->tid_maps;
-
-	BUG_ON(tid >= t->ntids);
-	if (tdev->type == T3A)
-		(void)cmpxchg(&t->tid_tab[tid].ctx, ctx, NULL);
-	else {
-		struct sk_buff *skb;
-
-		skb = alloc_skb(sizeof(struct cpl_tid_release), GFP_ATOMIC);
-		if (likely(skb)) {
-			mk_tid_release(skb, tid);
-			cxgb3_ofld_send(tdev, skb);
-			t->tid_tab[tid].ctx = NULL;
-		} else
-			cxgb3_queue_tid_release(tdev, tid);
-	}
-	atomic_dec(&t->tids_in_use);
-}
-
-EXPORT_SYMBOL(cxgb3_remove_tid);
-
-int cxgb3_alloc_atid(struct t3cdev *tdev, struct cxgb3_client *client,
-		     void *ctx)
-{
-	int atid = -1;
-	struct tid_info *t = &(T3C_DATA(tdev))->tid_maps;
-
-	spin_lock_bh(&t->atid_lock);
-	if (t->afree &&
-	    t->atids_in_use + atomic_read(&t->tids_in_use) + MC5_MIN_TIDS <=
-	    t->ntids) {
-		union active_open_entry *p = t->afree;
-
-		atid = (p - t->atid_tab) + t->atid_base;
-		t->afree = p->next;
-		p->t3c_tid.ctx = ctx;
-		p->t3c_tid.client = client;
-		t->atids_in_use++;
-	}
-	spin_unlock_bh(&t->atid_lock);
-	return atid;
-}
-
-EXPORT_SYMBOL(cxgb3_alloc_atid);
-
-int cxgb3_alloc_stid(struct t3cdev *tdev, struct cxgb3_client *client,
-		     void *ctx)
-{
-	int stid = -1;
-	struct tid_info *t = &(T3C_DATA(tdev))->tid_maps;
-
-	spin_lock_bh(&t->stid_lock);
-	if (t->sfree) {
-		union listen_entry *p = t->sfree;
-
-		stid = (p - t->stid_tab) + t->stid_base;
-		t->sfree = p->next;
-		p->t3c_tid.ctx = ctx;
-		p->t3c_tid.client = client;
-		t->stids_in_use++;
-	}
-	spin_unlock_bh(&t->stid_lock);
-	return stid;
-}
-
-EXPORT_SYMBOL(cxgb3_alloc_stid);
-
-/* Get the t3cdev associated with a net_device */
-struct t3cdev *dev2t3cdev(struct net_device *dev)
-{
-	const struct port_info *pi = netdev_priv(dev);
-
-	return (struct t3cdev *)pi->adapter;
-}
-
-EXPORT_SYMBOL(dev2t3cdev);
-
-static int do_smt_write_rpl(struct t3cdev *dev, struct sk_buff *skb)
-{
-	struct cpl_smt_write_rpl *rpl = cplhdr(skb);
-
-	if (rpl->status != CPL_ERR_NONE)
-		printk(KERN_ERR
-		       "Unexpected SMT_WRITE_RPL status %u for entry %u\n",
-		       rpl->status, GET_TID(rpl));
-
-	return CPL_RET_BUF_DONE;
-}
-
-static int do_l2t_write_rpl(struct t3cdev *dev, struct sk_buff *skb)
-{
-	struct cpl_l2t_write_rpl *rpl = cplhdr(skb);
-
-	if (rpl->status != CPL_ERR_NONE)
-		printk(KERN_ERR
-		       "Unexpected L2T_WRITE_RPL status %u for entry %u\n",
-		       rpl->status, GET_TID(rpl));
-
-	return CPL_RET_BUF_DONE;
-}
-
-static int do_rte_write_rpl(struct t3cdev *dev, struct sk_buff *skb)
-{
-	struct cpl_rte_write_rpl *rpl = cplhdr(skb);
-
-	if (rpl->status != CPL_ERR_NONE)
-		printk(KERN_ERR
-		       "Unexpected RTE_WRITE_RPL status %u for entry %u\n",
-		       rpl->status, GET_TID(rpl));
-
-	return CPL_RET_BUF_DONE;
-}
-
-static int do_act_open_rpl(struct t3cdev *dev, struct sk_buff *skb)
-{
-	struct cpl_act_open_rpl *rpl = cplhdr(skb);
-	unsigned int atid = G_TID(ntohl(rpl->atid));
-	struct t3c_tid_entry *t3c_tid;
-
-	t3c_tid = lookup_atid(&(T3C_DATA(dev))->tid_maps, atid);
-	if (t3c_tid && t3c_tid->ctx && t3c_tid->client &&
-	    t3c_tid->client->handlers &&
-	    t3c_tid->client->handlers[CPL_ACT_OPEN_RPL]) {
-		return t3c_tid->client->handlers[CPL_ACT_OPEN_RPL] (dev, skb,
-								    t3c_tid->
-								    ctx);
-	} else {
-		printk(KERN_ERR "%s: received clientless CPL command 0x%x\n",
-		       dev->name, CPL_ACT_OPEN_RPL);
-		return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG;
-	}
-}
-
-static int do_stid_rpl(struct t3cdev *dev, struct sk_buff *skb)
-{
-	union opcode_tid *p = cplhdr(skb);
-	unsigned int stid = G_TID(ntohl(p->opcode_tid));
-	struct t3c_tid_entry *t3c_tid;
-
-	t3c_tid = lookup_stid(&(T3C_DATA(dev))->tid_maps, stid);
-	if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers &&
-	    t3c_tid->client->handlers[p->opcode]) {
-		return t3c_tid->client->handlers[p->opcode] (dev, skb,
-							     t3c_tid->ctx);
-	} else {
-		printk(KERN_ERR "%s: received clientless CPL command 0x%x\n",
-		       dev->name, p->opcode);
-		return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG;
-	}
-}
-
-static int do_hwtid_rpl(struct t3cdev *dev, struct sk_buff *skb)
-{
-	union opcode_tid *p = cplhdr(skb);
-	unsigned int hwtid = G_TID(ntohl(p->opcode_tid));
-	struct t3c_tid_entry *t3c_tid;
-
-	t3c_tid = lookup_tid(&(T3C_DATA(dev))->tid_maps, hwtid);
-	if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers &&
-	    t3c_tid->client->handlers[p->opcode]) {
-		return t3c_tid->client->handlers[p->opcode]
-		    (dev, skb, t3c_tid->ctx);
-	} else {
-		printk(KERN_ERR "%s: received clientless CPL command 0x%x\n",
-		       dev->name, p->opcode);
-		return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG;
-	}
-}
-
-static int do_cr(struct t3cdev *dev, struct sk_buff *skb)
-{
-	struct cpl_pass_accept_req *req = cplhdr(skb);
-	unsigned int stid = G_PASS_OPEN_TID(ntohl(req->tos_tid));
-	struct tid_info *t = &(T3C_DATA(dev))->tid_maps;
-	struct t3c_tid_entry *t3c_tid;
-	unsigned int tid = GET_TID(req);
-
-	if (unlikely(tid >= t->ntids)) {
-		printk("%s: passive open TID %u too large\n",
-		       dev->name, tid);
-		t3_fatal_err(tdev2adap(dev));
-		return CPL_RET_BUF_DONE;
-	}
-
-	t3c_tid = lookup_stid(t, stid);
-	if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers &&
-	    t3c_tid->client->handlers[CPL_PASS_ACCEPT_REQ]) {
-		return t3c_tid->client->handlers[CPL_PASS_ACCEPT_REQ]
-		    (dev, skb, t3c_tid->ctx);
-	} else {
-		printk(KERN_ERR "%s: received clientless CPL command 0x%x\n",
-		       dev->name, CPL_PASS_ACCEPT_REQ);
-		return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG;
-	}
-}
-
-/*
- * Returns an sk_buff for a reply CPL message of size len.  If the input
- * sk_buff has no other users it is trimmed and reused, otherwise a new buffer
- * is allocated.  The input skb must be of size at least len.  Note that this
- * operation does not destroy the original skb data even if it decides to reuse
- * the buffer.
- */
-static struct sk_buff *cxgb3_get_cpl_reply_skb(struct sk_buff *skb, size_t len,
-					       gfp_t gfp)
-{
-	if (likely(!skb_cloned(skb))) {
-		BUG_ON(skb->len < len);
-		__skb_trim(skb, len);
-		skb_get(skb);
-	} else {
-		skb = alloc_skb(len, gfp);
-		if (skb)
-			__skb_put(skb, len);
-	}
-	return skb;
-}
-
-static int do_abort_req_rss(struct t3cdev *dev, struct sk_buff *skb)
-{
-	union opcode_tid *p = cplhdr(skb);
-	unsigned int hwtid = G_TID(ntohl(p->opcode_tid));
-	struct t3c_tid_entry *t3c_tid;
-
-	t3c_tid = lookup_tid(&(T3C_DATA(dev))->tid_maps, hwtid);
-	if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers &&
-	    t3c_tid->client->handlers[p->opcode]) {
-		return t3c_tid->client->handlers[p->opcode]
-		    (dev, skb, t3c_tid->ctx);
-	} else {
-		struct cpl_abort_req_rss *req = cplhdr(skb);
-		struct cpl_abort_rpl *rpl;
-		struct sk_buff *reply_skb;
-		unsigned int tid = GET_TID(req);
-		u8 cmd = req->status;
-
-		if (req->status == CPL_ERR_RTX_NEG_ADVICE ||
-		    req->status == CPL_ERR_PERSIST_NEG_ADVICE)
-			goto out;
-
-		reply_skb = cxgb3_get_cpl_reply_skb(skb,
-						    sizeof(struct
-							   cpl_abort_rpl),
-						    GFP_ATOMIC);
-
-		if (!reply_skb) {
-			printk("do_abort_req_rss: couldn't get skb!\n");
-			goto out;
-		}
-		reply_skb->priority = CPL_PRIORITY_DATA;
-		__skb_put(reply_skb, sizeof(struct cpl_abort_rpl));
-		rpl = cplhdr(reply_skb);
-		rpl->wr.wr_hi =
-		    htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_RPL));
-		rpl->wr.wr_lo = htonl(V_WR_TID(tid));
-		OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, tid));
-		rpl->cmd = cmd;
-		cxgb3_ofld_send(dev, reply_skb);
-out:
-		return CPL_RET_BUF_DONE;
-	}
-}
-
-static int do_act_establish(struct t3cdev *dev, struct sk_buff *skb)
-{
-	struct cpl_act_establish *req = cplhdr(skb);
-	unsigned int atid = G_PASS_OPEN_TID(ntohl(req->tos_tid));
-	struct tid_info *t = &(T3C_DATA(dev))->tid_maps;
-	struct t3c_tid_entry *t3c_tid;
-	unsigned int tid = GET_TID(req);
-
-	if (unlikely(tid >= t->ntids)) {
-		printk("%s: active establish TID %u too large\n",
-		       dev->name, tid);
-		t3_fatal_err(tdev2adap(dev));
-		return CPL_RET_BUF_DONE;
-	}
-
-	t3c_tid = lookup_atid(t, atid);
-	if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers &&
-	    t3c_tid->client->handlers[CPL_ACT_ESTABLISH]) {
-		return t3c_tid->client->handlers[CPL_ACT_ESTABLISH]
-		    (dev, skb, t3c_tid->ctx);
-	} else {
-		printk(KERN_ERR "%s: received clientless CPL command 0x%x\n",
-		       dev->name, CPL_ACT_ESTABLISH);
-		return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG;
-	}
-}
-
-static int do_trace(struct t3cdev *dev, struct sk_buff *skb)
-{
-	struct cpl_trace_pkt *p = cplhdr(skb);
-
-	skb->protocol = htons(0xffff);
-	skb->dev = dev->lldev;
-	skb_pull(skb, sizeof(*p));
-	skb_reset_mac_header(skb);
-	netif_receive_skb(skb);
-	return 0;
-}
-
-/*
- * That skb would better have come from process_responses() where we abuse
- * ->priority and ->csum to carry our data.  NB: if we get to per-arch
- * ->csum, the things might get really interesting here.
- */
-
-static inline u32 get_hwtid(struct sk_buff *skb)
-{
-	return ntohl((__force __be32)skb->priority) >> 8 & 0xfffff;
-}
-
-static inline u32 get_opcode(struct sk_buff *skb)
-{
-	return G_OPCODE(ntohl((__force __be32)skb->csum));
-}
-
-static int do_term(struct t3cdev *dev, struct sk_buff *skb)
-{
-	unsigned int hwtid = get_hwtid(skb);
-	unsigned int opcode = get_opcode(skb);
-	struct t3c_tid_entry *t3c_tid;
-
-	t3c_tid = lookup_tid(&(T3C_DATA(dev))->tid_maps, hwtid);
-	if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers &&
-	    t3c_tid->client->handlers[opcode]) {
-		return t3c_tid->client->handlers[opcode] (dev, skb,
-							  t3c_tid->ctx);
-	} else {
-		printk(KERN_ERR "%s: received clientless CPL command 0x%x\n",
-		       dev->name, opcode);
-		return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG;
-	}
-}
-
-static int nb_callback(struct notifier_block *self, unsigned long event,
-		       void *ctx)
-{
-	switch (event) {
-	case (NETEVENT_NEIGH_UPDATE):{
-		cxgb_neigh_update((struct neighbour *)ctx);
-		break;
-	}
-	case (NETEVENT_REDIRECT):{
-		struct netevent_redirect *nr = ctx;
-		cxgb_redirect(nr->old, nr->new);
-		cxgb_neigh_update(dst_get_neighbour(nr->new));
-		break;
-	}
-	default:
-		break;
-	}
-	return 0;
-}
-
-static struct notifier_block nb = {
-	.notifier_call = nb_callback
-};
-
-/*
- * Process a received packet with an unknown/unexpected CPL opcode.
- */
-static int do_bad_cpl(struct t3cdev *dev, struct sk_buff *skb)
-{
-	printk(KERN_ERR "%s: received bad CPL command 0x%x\n", dev->name,
-	       *skb->data);
-	return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG;
-}
-
-/*
- * Handlers for each CPL opcode
- */
-static cpl_handler_func cpl_handlers[NUM_CPL_CMDS];
-
-/*
- * Add a new handler to the CPL dispatch table.  A NULL handler may be supplied
- * to unregister an existing handler.
- */
-void t3_register_cpl_handler(unsigned int opcode, cpl_handler_func h)
-{
-	if (opcode < NUM_CPL_CMDS)
-		cpl_handlers[opcode] = h ? h : do_bad_cpl;
-	else
-		printk(KERN_ERR "T3C: handler registration for "
-		       "opcode %x failed\n", opcode);
-}
-
-EXPORT_SYMBOL(t3_register_cpl_handler);
-
-/*
- * T3CDEV's receive method.
- */
-static int process_rx(struct t3cdev *dev, struct sk_buff **skbs, int n)
-{
-	while (n--) {
-		struct sk_buff *skb = *skbs++;
-		unsigned int opcode = get_opcode(skb);
-		int ret = cpl_handlers[opcode] (dev, skb);
-
-#if VALIDATE_TID
-		if (ret & CPL_RET_UNKNOWN_TID) {
-			union opcode_tid *p = cplhdr(skb);
-
-			printk(KERN_ERR "%s: CPL message (opcode %u) had "
-			       "unknown TID %u\n", dev->name, opcode,
-			       G_TID(ntohl(p->opcode_tid)));
-		}
-#endif
-		if (ret & CPL_RET_BUF_DONE)
-			kfree_skb(skb);
-	}
-	return 0;
-}
-
-/*
- * Sends an sk_buff to a T3C driver after dealing with any active network taps.
- */
-int cxgb3_ofld_send(struct t3cdev *dev, struct sk_buff *skb)
-{
-	int r;
-
-	local_bh_disable();
-	r = dev->send(dev, skb);
-	local_bh_enable();
-	return r;
-}
-
-EXPORT_SYMBOL(cxgb3_ofld_send);
-
-static int is_offloading(struct net_device *dev)
-{
-	struct adapter *adapter;
-	int i;
-
-	read_lock_bh(&adapter_list_lock);
-	list_for_each_entry(adapter, &adapter_list, adapter_list) {
-		for_each_port(adapter, i) {
-			if (dev == adapter->port[i]) {
-				read_unlock_bh(&adapter_list_lock);
-				return 1;
-			}
-		}
-	}
-	read_unlock_bh(&adapter_list_lock);
-	return 0;
-}
-
-static void cxgb_neigh_update(struct neighbour *neigh)
-{
-	struct net_device *dev = neigh->dev;
-
-	if (dev && (is_offloading(dev))) {
-		struct t3cdev *tdev = dev2t3cdev(dev);
-
-		BUG_ON(!tdev);
-		t3_l2t_update(tdev, neigh);
-	}
-}
-
-static void set_l2t_ix(struct t3cdev *tdev, u32 tid, struct l2t_entry *e)
-{
-	struct sk_buff *skb;
-	struct cpl_set_tcb_field *req;
-
-	skb = alloc_skb(sizeof(*req), GFP_ATOMIC);
-	if (!skb) {
-		printk(KERN_ERR "%s: cannot allocate skb!\n", __func__);
-		return;
-	}
-	skb->priority = CPL_PRIORITY_CONTROL;
-	req = (struct cpl_set_tcb_field *)skb_put(skb, sizeof(*req));
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
-	req->reply = 0;
-	req->cpu_idx = 0;
-	req->word = htons(W_TCB_L2T_IX);
-	req->mask = cpu_to_be64(V_TCB_L2T_IX(M_TCB_L2T_IX));
-	req->val = cpu_to_be64(V_TCB_L2T_IX(e->idx));
-	tdev->send(tdev, skb);
-}
-
-static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
-{
-	struct net_device *olddev, *newdev;
-	struct tid_info *ti;
-	struct t3cdev *tdev;
-	u32 tid;
-	int update_tcb;
-	struct l2t_entry *e;
-	struct t3c_tid_entry *te;
-
-	olddev = dst_get_neighbour(old)->dev;
-	newdev = dst_get_neighbour(new)->dev;
-	if (!is_offloading(olddev))
-		return;
-	if (!is_offloading(newdev)) {
-		printk(KERN_WARNING "%s: Redirect to non-offload "
-		       "device ignored.\n", __func__);
-		return;
-	}
-	tdev = dev2t3cdev(olddev);
-	BUG_ON(!tdev);
-	if (tdev != dev2t3cdev(newdev)) {
-		printk(KERN_WARNING "%s: Redirect to different "
-		       "offload device ignored.\n", __func__);
-		return;
-	}
-
-	/* Add new L2T entry */
-	e = t3_l2t_get(tdev, dst_get_neighbour(new), newdev);
-	if (!e) {
-		printk(KERN_ERR "%s: couldn't allocate new l2t entry!\n",
-		       __func__);
-		return;
-	}
-
-	/* Walk tid table and notify clients of dst change. */
-	ti = &(T3C_DATA(tdev))->tid_maps;
-	for (tid = 0; tid < ti->ntids; tid++) {
-		te = lookup_tid(ti, tid);
-		BUG_ON(!te);
-		if (te && te->ctx && te->client && te->client->redirect) {
-			update_tcb = te->client->redirect(te->ctx, old, new, e);
-			if (update_tcb) {
-				rcu_read_lock();
-				l2t_hold(L2DATA(tdev), e);
-				rcu_read_unlock();
-				set_l2t_ix(tdev, tid, e);
-			}
-		}
-	}
-	l2t_release(tdev, e);
-}
-
-/*
- * Allocate a chunk of memory using kmalloc or, if that fails, vmalloc.
- * The allocated memory is cleared.
- */
-void *cxgb_alloc_mem(unsigned long size)
-{
-	void *p = kzalloc(size, GFP_KERNEL);
-
-	if (!p)
-		p = vzalloc(size);
-	return p;
-}
-
-/*
- * Free memory allocated through t3_alloc_mem().
- */
-void cxgb_free_mem(void *addr)
-{
-	if (is_vmalloc_addr(addr))
-		vfree(addr);
-	else
-		kfree(addr);
-}
-
-/*
- * Allocate and initialize the TID tables.  Returns 0 on success.
- */
-static int init_tid_tabs(struct tid_info *t, unsigned int ntids,
-			 unsigned int natids, unsigned int nstids,
-			 unsigned int atid_base, unsigned int stid_base)
-{
-	unsigned long size = ntids * sizeof(*t->tid_tab) +
-	    natids * sizeof(*t->atid_tab) + nstids * sizeof(*t->stid_tab);
-
-	t->tid_tab = cxgb_alloc_mem(size);
-	if (!t->tid_tab)
-		return -ENOMEM;
-
-	t->stid_tab = (union listen_entry *)&t->tid_tab[ntids];
-	t->atid_tab = (union active_open_entry *)&t->stid_tab[nstids];
-	t->ntids = ntids;
-	t->nstids = nstids;
-	t->stid_base = stid_base;
-	t->sfree = NULL;
-	t->natids = natids;
-	t->atid_base = atid_base;
-	t->afree = NULL;
-	t->stids_in_use = t->atids_in_use = 0;
-	atomic_set(&t->tids_in_use, 0);
-	spin_lock_init(&t->stid_lock);
-	spin_lock_init(&t->atid_lock);
-
-	/*
-	 * Setup the free lists for stid_tab and atid_tab.
-	 */
-	if (nstids) {
-		while (--nstids)
-			t->stid_tab[nstids - 1].next = &t->stid_tab[nstids];
-		t->sfree = t->stid_tab;
-	}
-	if (natids) {
-		while (--natids)
-			t->atid_tab[natids - 1].next = &t->atid_tab[natids];
-		t->afree = t->atid_tab;
-	}
-	return 0;
-}
-
-static void free_tid_maps(struct tid_info *t)
-{
-	cxgb_free_mem(t->tid_tab);
-}
-
-static inline void add_adapter(struct adapter *adap)
-{
-	write_lock_bh(&adapter_list_lock);
-	list_add_tail(&adap->adapter_list, &adapter_list);
-	write_unlock_bh(&adapter_list_lock);
-}
-
-static inline void remove_adapter(struct adapter *adap)
-{
-	write_lock_bh(&adapter_list_lock);
-	list_del(&adap->adapter_list);
-	write_unlock_bh(&adapter_list_lock);
-}
-
-int cxgb3_offload_activate(struct adapter *adapter)
-{
-	struct t3cdev *dev = &adapter->tdev;
-	int natids, err;
-	struct t3c_data *t;
-	struct tid_range stid_range, tid_range;
-	struct mtutab mtutab;
-	unsigned int l2t_capacity;
-
-	t = kzalloc(sizeof(*t), GFP_KERNEL);
-	if (!t)
-		return -ENOMEM;
-
-	err = -EOPNOTSUPP;
-	if (dev->ctl(dev, GET_TX_MAX_CHUNK, &t->tx_max_chunk) < 0 ||
-	    dev->ctl(dev, GET_MAX_OUTSTANDING_WR, &t->max_wrs) < 0 ||
-	    dev->ctl(dev, GET_L2T_CAPACITY, &l2t_capacity) < 0 ||
-	    dev->ctl(dev, GET_MTUS, &mtutab) < 0 ||
-	    dev->ctl(dev, GET_TID_RANGE, &tid_range) < 0 ||
-	    dev->ctl(dev, GET_STID_RANGE, &stid_range) < 0)
-		goto out_free;
-
-	err = -ENOMEM;
-	RCU_INIT_POINTER(dev->l2opt, t3_init_l2t(l2t_capacity));
-	if (!L2DATA(dev))
-		goto out_free;
-
-	natids = min(tid_range.num / 2, MAX_ATIDS);
-	err = init_tid_tabs(&t->tid_maps, tid_range.num, natids,
-			    stid_range.num, ATID_BASE, stid_range.base);
-	if (err)
-		goto out_free_l2t;
-
-	t->mtus = mtutab.mtus;
-	t->nmtus = mtutab.size;
-
-	INIT_WORK(&t->tid_release_task, t3_process_tid_release_list);
-	spin_lock_init(&t->tid_release_lock);
-	INIT_LIST_HEAD(&t->list_node);
-	t->dev = dev;
-
-	T3C_DATA(dev) = t;
-	dev->recv = process_rx;
-	dev->neigh_update = t3_l2t_update;
-
-	/* Register netevent handler once */
-	if (list_empty(&adapter_list))
-		register_netevent_notifier(&nb);
-
-	t->nofail_skb = alloc_skb(sizeof(struct cpl_tid_release), GFP_KERNEL);
-	t->release_list_incomplete = 0;
-
-	add_adapter(adapter);
-	return 0;
-
-out_free_l2t:
-	t3_free_l2t(L2DATA(dev));
-	rcu_assign_pointer(dev->l2opt, NULL);
-out_free:
-	kfree(t);
-	return err;
-}
-
-static void clean_l2_data(struct rcu_head *head)
-{
-	struct l2t_data *d = container_of(head, struct l2t_data, rcu_head);
-	t3_free_l2t(d);
-}
-
-
-void cxgb3_offload_deactivate(struct adapter *adapter)
-{
-	struct t3cdev *tdev = &adapter->tdev;
-	struct t3c_data *t = T3C_DATA(tdev);
-	struct l2t_data *d;
-
-	remove_adapter(adapter);
-	if (list_empty(&adapter_list))
-		unregister_netevent_notifier(&nb);
-
-	free_tid_maps(&t->tid_maps);
-	T3C_DATA(tdev) = NULL;
-	rcu_read_lock();
-	d = L2DATA(tdev);
-	rcu_read_unlock();
-	rcu_assign_pointer(tdev->l2opt, NULL);
-	call_rcu(&d->rcu_head, clean_l2_data);
-	if (t->nofail_skb)
-		kfree_skb(t->nofail_skb);
-	kfree(t);
-}
-
-static inline void register_tdev(struct t3cdev *tdev)
-{
-	static int unit;
-
-	mutex_lock(&cxgb3_db_lock);
-	snprintf(tdev->name, sizeof(tdev->name), "ofld_dev%d", unit++);
-	list_add_tail(&tdev->ofld_dev_list, &ofld_dev_list);
-	mutex_unlock(&cxgb3_db_lock);
-}
-
-static inline void unregister_tdev(struct t3cdev *tdev)
-{
-	mutex_lock(&cxgb3_db_lock);
-	list_del(&tdev->ofld_dev_list);
-	mutex_unlock(&cxgb3_db_lock);
-}
-
-static inline int adap2type(struct adapter *adapter)
-{
-	int type = 0;
-
-	switch (adapter->params.rev) {
-	case T3_REV_A:
-		type = T3A;
-		break;
-	case T3_REV_B:
-	case T3_REV_B2:
-		type = T3B;
-		break;
-	case T3_REV_C:
-		type = T3C;
-		break;
-	}
-	return type;
-}
-
-void __devinit cxgb3_adapter_ofld(struct adapter *adapter)
-{
-	struct t3cdev *tdev = &adapter->tdev;
-
-	INIT_LIST_HEAD(&tdev->ofld_dev_list);
-
-	cxgb3_set_dummy_ops(tdev);
-	tdev->send = t3_offload_tx;
-	tdev->ctl = cxgb_offload_ctl;
-	tdev->type = adap2type(adapter);
-
-	register_tdev(tdev);
-}
-
-void __devexit cxgb3_adapter_unofld(struct adapter *adapter)
-{
-	struct t3cdev *tdev = &adapter->tdev;
-
-	tdev->recv = NULL;
-	tdev->neigh_update = NULL;
-
-	unregister_tdev(tdev);
-}
-
-void __init cxgb3_offload_init(void)
-{
-	int i;
-
-	for (i = 0; i < NUM_CPL_CMDS; ++i)
-		cpl_handlers[i] = do_bad_cpl;
-
-	t3_register_cpl_handler(CPL_SMT_WRITE_RPL, do_smt_write_rpl);
-	t3_register_cpl_handler(CPL_L2T_WRITE_RPL, do_l2t_write_rpl);
-	t3_register_cpl_handler(CPL_RTE_WRITE_RPL, do_rte_write_rpl);
-	t3_register_cpl_handler(CPL_PASS_OPEN_RPL, do_stid_rpl);
-	t3_register_cpl_handler(CPL_CLOSE_LISTSRV_RPL, do_stid_rpl);
-	t3_register_cpl_handler(CPL_PASS_ACCEPT_REQ, do_cr);
-	t3_register_cpl_handler(CPL_PASS_ESTABLISH, do_hwtid_rpl);
-	t3_register_cpl_handler(CPL_ABORT_RPL_RSS, do_hwtid_rpl);
-	t3_register_cpl_handler(CPL_ABORT_RPL, do_hwtid_rpl);
-	t3_register_cpl_handler(CPL_RX_URG_NOTIFY, do_hwtid_rpl);
-	t3_register_cpl_handler(CPL_RX_DATA, do_hwtid_rpl);
-	t3_register_cpl_handler(CPL_TX_DATA_ACK, do_hwtid_rpl);
-	t3_register_cpl_handler(CPL_TX_DMA_ACK, do_hwtid_rpl);
-	t3_register_cpl_handler(CPL_ACT_OPEN_RPL, do_act_open_rpl);
-	t3_register_cpl_handler(CPL_PEER_CLOSE, do_hwtid_rpl);
-	t3_register_cpl_handler(CPL_CLOSE_CON_RPL, do_hwtid_rpl);
-	t3_register_cpl_handler(CPL_ABORT_REQ_RSS, do_abort_req_rss);
-	t3_register_cpl_handler(CPL_ACT_ESTABLISH, do_act_establish);
-	t3_register_cpl_handler(CPL_SET_TCB_RPL, do_hwtid_rpl);
-	t3_register_cpl_handler(CPL_GET_TCB_RPL, do_hwtid_rpl);
-	t3_register_cpl_handler(CPL_RDMA_TERMINATE, do_term);
-	t3_register_cpl_handler(CPL_RDMA_EC_STATUS, do_hwtid_rpl);
-	t3_register_cpl_handler(CPL_TRACE_PKT, do_trace);
-	t3_register_cpl_handler(CPL_RX_DATA_DDP, do_hwtid_rpl);
-	t3_register_cpl_handler(CPL_RX_DDP_COMPLETE, do_hwtid_rpl);
-	t3_register_cpl_handler(CPL_ISCSI_HDR, do_hwtid_rpl);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/cxgb3_offload.h linux-libre-3.2-gnu/drivers/net/cxgb3/cxgb3_offload.h
--- linux-libre-3.1-gnu/drivers/net/cxgb3/cxgb3_offload.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/cxgb3_offload.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,209 +0,0 @@
-/*
- * Copyright (c) 2006-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef _CXGB3_OFFLOAD_H
-#define _CXGB3_OFFLOAD_H
-
-#include <linux/list.h>
-#include <linux/skbuff.h>
-
-#include "l2t.h"
-
-#include "t3cdev.h"
-#include "t3_cpl.h"
-
-struct adapter;
-
-void cxgb3_offload_init(void);
-
-void cxgb3_adapter_ofld(struct adapter *adapter);
-void cxgb3_adapter_unofld(struct adapter *adapter);
-int cxgb3_offload_activate(struct adapter *adapter);
-void cxgb3_offload_deactivate(struct adapter *adapter);
-
-void cxgb3_set_dummy_ops(struct t3cdev *dev);
-
-struct t3cdev *dev2t3cdev(struct net_device *dev);
-
-/*
- * Client registration.  Users of T3 driver must register themselves.
- * The T3 driver will call the add function of every client for each T3
- * adapter activated, passing up the t3cdev ptr.  Each client fills out an
- * array of callback functions to process CPL messages.
- */
-
-void cxgb3_register_client(struct cxgb3_client *client);
-void cxgb3_unregister_client(struct cxgb3_client *client);
-void cxgb3_add_clients(struct t3cdev *tdev);
-void cxgb3_remove_clients(struct t3cdev *tdev);
-void cxgb3_event_notify(struct t3cdev *tdev, u32 event, u32 port);
-
-typedef int (*cxgb3_cpl_handler_func)(struct t3cdev *dev,
-				      struct sk_buff *skb, void *ctx);
-
-enum {
-	OFFLOAD_STATUS_UP,
-	OFFLOAD_STATUS_DOWN,
-	OFFLOAD_PORT_DOWN,
-	OFFLOAD_PORT_UP,
-	OFFLOAD_DB_FULL,
-	OFFLOAD_DB_EMPTY,
-	OFFLOAD_DB_DROP
-};
-
-struct cxgb3_client {
-	char *name;
-	void (*add) (struct t3cdev *);
-	void (*remove) (struct t3cdev *);
-	cxgb3_cpl_handler_func *handlers;
-	int (*redirect)(void *ctx, struct dst_entry *old,
-			struct dst_entry *new, struct l2t_entry *l2t);
-	struct list_head client_list;
-	void (*event_handler)(struct t3cdev *tdev, u32 event, u32 port);
-};
-
-/*
- * TID allocation services.
- */
-int cxgb3_alloc_atid(struct t3cdev *dev, struct cxgb3_client *client,
-		     void *ctx);
-int cxgb3_alloc_stid(struct t3cdev *dev, struct cxgb3_client *client,
-		     void *ctx);
-void *cxgb3_free_atid(struct t3cdev *dev, int atid);
-void cxgb3_free_stid(struct t3cdev *dev, int stid);
-void cxgb3_insert_tid(struct t3cdev *dev, struct cxgb3_client *client,
-		      void *ctx, unsigned int tid);
-void cxgb3_queue_tid_release(struct t3cdev *dev, unsigned int tid);
-void cxgb3_remove_tid(struct t3cdev *dev, void *ctx, unsigned int tid);
-
-struct t3c_tid_entry {
-	struct cxgb3_client *client;
-	void *ctx;
-};
-
-/* CPL message priority levels */
-enum {
-	CPL_PRIORITY_DATA = 0,	/* data messages */
-	CPL_PRIORITY_SETUP = 1,	/* connection setup messages */
-	CPL_PRIORITY_TEARDOWN = 0,	/* connection teardown messages */
-	CPL_PRIORITY_LISTEN = 1,	/* listen start/stop messages */
-	CPL_PRIORITY_ACK = 1,	/* RX ACK messages */
-	CPL_PRIORITY_CONTROL = 1	/* offload control messages */
-};
-
-/* Flags for return value of CPL message handlers */
-enum {
-	CPL_RET_BUF_DONE = 1, /* buffer processing done, buffer may be freed */
-	CPL_RET_BAD_MSG = 2,  /* bad CPL message (e.g., unknown opcode) */
-	CPL_RET_UNKNOWN_TID = 4	/* unexpected unknown TID */
-};
-
-typedef int (*cpl_handler_func)(struct t3cdev *dev, struct sk_buff *skb);
-
-/*
- * Returns a pointer to the first byte of the CPL header in an sk_buff that
- * contains a CPL message.
- */
-static inline void *cplhdr(struct sk_buff *skb)
-{
-	return skb->data;
-}
-
-void t3_register_cpl_handler(unsigned int opcode, cpl_handler_func h);
-
-union listen_entry {
-	struct t3c_tid_entry t3c_tid;
-	union listen_entry *next;
-};
-
-union active_open_entry {
-	struct t3c_tid_entry t3c_tid;
-	union active_open_entry *next;
-};
-
-/*
- * Holds the size, base address, free list start, etc of the TID, server TID,
- * and active-open TID tables for a offload device.
- * The tables themselves are allocated dynamically.
- */
-struct tid_info {
-	struct t3c_tid_entry *tid_tab;
-	unsigned int ntids;
-	atomic_t tids_in_use;
-
-	union listen_entry *stid_tab;
-	unsigned int nstids;
-	unsigned int stid_base;
-
-	union active_open_entry *atid_tab;
-	unsigned int natids;
-	unsigned int atid_base;
-
-	/*
-	 * The following members are accessed R/W so we put them in their own
-	 * cache lines.
-	 *
-	 * XXX We could combine the atid fields above with the lock here since
-	 * atids are use once (unlike other tids).  OTOH the above fields are
-	 * usually in cache due to tid_tab.
-	 */
-	spinlock_t atid_lock ____cacheline_aligned_in_smp;
-	union active_open_entry *afree;
-	unsigned int atids_in_use;
-
-	spinlock_t stid_lock ____cacheline_aligned;
-	union listen_entry *sfree;
-	unsigned int stids_in_use;
-};
-
-struct t3c_data {
-	struct list_head list_node;
-	struct t3cdev *dev;
-	unsigned int tx_max_chunk;	/* max payload for TX_DATA */
-	unsigned int max_wrs;	/* max in-flight WRs per connection */
-	unsigned int nmtus;
-	const unsigned short *mtus;
-	struct tid_info tid_maps;
-
-	struct t3c_tid_entry *tid_release_list;
-	spinlock_t tid_release_lock;
-	struct work_struct tid_release_task;
-
-	struct sk_buff *nofail_skb;
-	unsigned int release_list_incomplete;
-};
-
-/*
- * t3cdev -> t3c_data accessor
- */
-#define T3C_DATA(dev) (*(struct t3c_data **)&(dev)->l4opt)
-
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/firmware_exports.h linux-libre-3.2-gnu/drivers/net/cxgb3/firmware_exports.h
--- linux-libre-3.1-gnu/drivers/net/cxgb3/firmware_exports.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/firmware_exports.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2004-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef _FIRMWARE_EXPORTS_H_
-#define _FIRMWARE_EXPORTS_H_
-
-/* WR OPCODES supported by the firmware.
- */
-#define	FW_WROPCODE_FORWARD			0x01
-#define FW_WROPCODE_BYPASS			0x05
-
-#define FW_WROPCODE_TUNNEL_TX_PKT		0x03
-
-#define FW_WROPOCDE_ULPTX_DATA_SGL		0x00
-#define FW_WROPCODE_ULPTX_MEM_READ		0x02
-#define FW_WROPCODE_ULPTX_PKT			0x04
-#define FW_WROPCODE_ULPTX_INVALIDATE		0x06
-
-#define FW_WROPCODE_TUNNEL_RX_PKT		0x07
-
-#define FW_WROPCODE_OFLD_GETTCB_RPL		0x08
-#define FW_WROPCODE_OFLD_CLOSE_CON		0x09
-#define FW_WROPCODE_OFLD_TP_ABORT_CON_REQ	0x0A
-#define FW_WROPCODE_OFLD_HOST_ABORT_CON_RPL	0x0F
-#define FW_WROPCODE_OFLD_HOST_ABORT_CON_REQ	0x0B
-#define FW_WROPCODE_OFLD_TP_ABORT_CON_RPL	0x0C
-#define FW_WROPCODE_OFLD_TX_DATA		0x0D
-#define FW_WROPCODE_OFLD_TX_DATA_ACK		0x0E
-
-#define FW_WROPCODE_RI_RDMA_INIT		0x10
-#define FW_WROPCODE_RI_RDMA_WRITE		0x11
-#define FW_WROPCODE_RI_RDMA_READ_REQ		0x12
-#define FW_WROPCODE_RI_RDMA_READ_RESP		0x13
-#define FW_WROPCODE_RI_SEND			0x14
-#define FW_WROPCODE_RI_TERMINATE		0x15
-#define FW_WROPCODE_RI_RDMA_READ		0x16
-#define FW_WROPCODE_RI_RECEIVE			0x17
-#define FW_WROPCODE_RI_BIND_MW			0x18
-#define FW_WROPCODE_RI_FASTREGISTER_MR		0x19
-#define FW_WROPCODE_RI_LOCAL_INV		0x1A
-#define FW_WROPCODE_RI_MODIFY_QP		0x1B
-#define FW_WROPCODE_RI_BYPASS			0x1C
-
-#define FW_WROPOCDE_RSVD			0x1E
-
-#define FW_WROPCODE_SGE_EGRESSCONTEXT_RR	0x1F
-
-#define FW_WROPCODE_MNGT			0x1D
-#define FW_MNGTOPCODE_PKTSCHED_SET		0x00
-
-/* Maximum size of a WR sent from the host, limited by the SGE.
- *
- * Note: WR coming from ULP or TP are only limited by CIM.
- */
-#define FW_WR_SIZE			128
-
-/* Maximum number of outstanding WRs sent from the host. Value must be
- * programmed in the CTRL/TUNNEL/QP SGE Egress Context and used by
- * offload modules to limit the number of WRs per connection.
- */
-#define FW_T3_WR_NUM			16
-#define FW_N3_WR_NUM			7
-
-#ifndef N3
-# define FW_WR_NUM			FW_T3_WR_NUM
-#else
-# define FW_WR_NUM			FW_N3_WR_NUM
-#endif
-
-/* FW_TUNNEL_NUM corresponds to the number of supported TUNNEL Queues. These
- * queues must start at SGE Egress Context FW_TUNNEL_SGEEC_START and must
- * start at 'TID' (or 'uP Token') FW_TUNNEL_TID_START.
- *
- * Ingress Traffic (e.g. DMA completion credit)  for TUNNEL Queue[i] is sent
- * to RESP Queue[i].
- */
-#define FW_TUNNEL_NUM			8
-#define FW_TUNNEL_SGEEC_START		8
-#define FW_TUNNEL_TID_START		65544
-
-/* FW_CTRL_NUM corresponds to the number of supported CTRL Queues. These queues
- * must start at SGE Egress Context FW_CTRL_SGEEC_START and must start at 'TID'
- * (or 'uP Token') FW_CTRL_TID_START.
- *
- * Ingress Traffic for CTRL Queue[i] is sent to RESP Queue[i].
- */
-#define FW_CTRL_NUM			8
-#define FW_CTRL_SGEEC_START		65528
-#define FW_CTRL_TID_START		65536
-
-/* FW_OFLD_NUM corresponds to the number of supported OFFLOAD Queues. These
- * queues must start at SGE Egress Context FW_OFLD_SGEEC_START.
- *
- * Note: the 'uP Token' in the SGE Egress Context fields is irrelevant for
- * OFFLOAD Queues, as the host is responsible for providing the correct TID in
- * every WR.
- *
- * Ingress Trafffic for OFFLOAD Queue[i] is sent to RESP Queue[i].
- */
-#define FW_OFLD_NUM			8
-#define FW_OFLD_SGEEC_START		0
-
-/*
- *
- */
-#define FW_RI_NUM			1
-#define FW_RI_SGEEC_START		65527
-#define FW_RI_TID_START			65552
-
-/*
- * The RX_PKT_TID
- */
-#define FW_RX_PKT_NUM			1
-#define FW_RX_PKT_TID_START		65553
-
-/* FW_WRC_NUM corresponds to the number of Work Request Context that supported
- * by the firmware.
- */
-#define FW_WRC_NUM			\
-    (65536 + FW_TUNNEL_NUM + FW_CTRL_NUM + FW_RI_NUM + FW_RX_PKT_NUM)
-
-/*
- * FW type and version.
- */
-#define S_FW_VERSION_TYPE		28
-#define M_FW_VERSION_TYPE		0xF
-#define V_FW_VERSION_TYPE(x)		((x) << S_FW_VERSION_TYPE)
-#define G_FW_VERSION_TYPE(x)		\
-    (((x) >> S_FW_VERSION_TYPE) & M_FW_VERSION_TYPE)
-
-#define S_FW_VERSION_MAJOR		16
-#define M_FW_VERSION_MAJOR		0xFFF
-#define V_FW_VERSION_MAJOR(x)		((x) << S_FW_VERSION_MAJOR)
-#define G_FW_VERSION_MAJOR(x)		\
-    (((x) >> S_FW_VERSION_MAJOR) & M_FW_VERSION_MAJOR)
-
-#define S_FW_VERSION_MINOR		8
-#define M_FW_VERSION_MINOR		0xFF
-#define V_FW_VERSION_MINOR(x)		((x) << S_FW_VERSION_MINOR)
-#define G_FW_VERSION_MINOR(x)		\
-    (((x) >> S_FW_VERSION_MINOR) & M_FW_VERSION_MINOR)
-
-#define S_FW_VERSION_MICRO		0
-#define M_FW_VERSION_MICRO		0xFF
-#define V_FW_VERSION_MICRO(x)		((x) << S_FW_VERSION_MICRO)
-#define G_FW_VERSION_MICRO(x)		\
-    (((x) >> S_FW_VERSION_MICRO) & M_FW_VERSION_MICRO)
-
-#endif				/* _FIRMWARE_EXPORTS_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/l2t.c linux-libre-3.2-gnu/drivers/net/cxgb3/l2t.c
--- linux-libre-3.1-gnu/drivers/net/cxgb3/l2t.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/l2t.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,454 +0,0 @@
-/*
- * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/if.h>
-#include <linux/if_vlan.h>
-#include <linux/jhash.h>
-#include <linux/slab.h>
-#include <net/neighbour.h>
-#include "common.h"
-#include "t3cdev.h"
-#include "cxgb3_defs.h"
-#include "l2t.h"
-#include "t3_cpl.h"
-#include "firmware_exports.h"
-
-#define VLAN_NONE 0xfff
-
-/*
- * Module locking notes:  There is a RW lock protecting the L2 table as a
- * whole plus a spinlock per L2T entry.  Entry lookups and allocations happen
- * under the protection of the table lock, individual entry changes happen
- * while holding that entry's spinlock.  The table lock nests outside the
- * entry locks.  Allocations of new entries take the table lock as writers so
- * no other lookups can happen while allocating new entries.  Entry updates
- * take the table lock as readers so multiple entries can be updated in
- * parallel.  An L2T entry can be dropped by decrementing its reference count
- * and therefore can happen in parallel with entry allocation but no entry
- * can change state or increment its ref count during allocation as both of
- * these perform lookups.
- */
-
-static inline unsigned int vlan_prio(const struct l2t_entry *e)
-{
-	return e->vlan >> 13;
-}
-
-static inline unsigned int arp_hash(u32 key, int ifindex,
-				    const struct l2t_data *d)
-{
-	return jhash_2words(key, ifindex, 0) & (d->nentries - 1);
-}
-
-static inline void neigh_replace(struct l2t_entry *e, struct neighbour *n)
-{
-	neigh_hold(n);
-	if (e->neigh)
-		neigh_release(e->neigh);
-	e->neigh = n;
-}
-
-/*
- * Set up an L2T entry and send any packets waiting in the arp queue.  The
- * supplied skb is used for the CPL_L2T_WRITE_REQ.  Must be called with the
- * entry locked.
- */
-static int setup_l2e_send_pending(struct t3cdev *dev, struct sk_buff *skb,
-				  struct l2t_entry *e)
-{
-	struct cpl_l2t_write_req *req;
-	struct sk_buff *tmp;
-
-	if (!skb) {
-		skb = alloc_skb(sizeof(*req), GFP_ATOMIC);
-		if (!skb)
-			return -ENOMEM;
-	}
-
-	req = (struct cpl_l2t_write_req *)__skb_put(skb, sizeof(*req));
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, e->idx));
-	req->params = htonl(V_L2T_W_IDX(e->idx) | V_L2T_W_IFF(e->smt_idx) |
-			    V_L2T_W_VLAN(e->vlan & VLAN_VID_MASK) |
-			    V_L2T_W_PRIO(vlan_prio(e)));
-	memcpy(e->dmac, e->neigh->ha, sizeof(e->dmac));
-	memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac));
-	skb->priority = CPL_PRIORITY_CONTROL;
-	cxgb3_ofld_send(dev, skb);
-
-	skb_queue_walk_safe(&e->arpq, skb, tmp) {
-		__skb_unlink(skb, &e->arpq);
-		cxgb3_ofld_send(dev, skb);
-	}
-	e->state = L2T_STATE_VALID;
-
-	return 0;
-}
-
-/*
- * Add a packet to the an L2T entry's queue of packets awaiting resolution.
- * Must be called with the entry's lock held.
- */
-static inline void arpq_enqueue(struct l2t_entry *e, struct sk_buff *skb)
-{
-	__skb_queue_tail(&e->arpq, skb);
-}
-
-int t3_l2t_send_slow(struct t3cdev *dev, struct sk_buff *skb,
-		     struct l2t_entry *e)
-{
-again:
-	switch (e->state) {
-	case L2T_STATE_STALE:	/* entry is stale, kick off revalidation */
-		neigh_event_send(e->neigh, NULL);
-		spin_lock_bh(&e->lock);
-		if (e->state == L2T_STATE_STALE)
-			e->state = L2T_STATE_VALID;
-		spin_unlock_bh(&e->lock);
-	case L2T_STATE_VALID:	/* fast-path, send the packet on */
-		return cxgb3_ofld_send(dev, skb);
-	case L2T_STATE_RESOLVING:
-		spin_lock_bh(&e->lock);
-		if (e->state != L2T_STATE_RESOLVING) {
-			/* ARP already completed */
-			spin_unlock_bh(&e->lock);
-			goto again;
-		}
-		arpq_enqueue(e, skb);
-		spin_unlock_bh(&e->lock);
-
-		/*
-		 * Only the first packet added to the arpq should kick off
-		 * resolution.  However, because the alloc_skb below can fail,
-		 * we allow each packet added to the arpq to retry resolution
-		 * as a way of recovering from transient memory exhaustion.
-		 * A better way would be to use a work request to retry L2T
-		 * entries when there's no memory.
-		 */
-		if (!neigh_event_send(e->neigh, NULL)) {
-			skb = alloc_skb(sizeof(struct cpl_l2t_write_req),
-					GFP_ATOMIC);
-			if (!skb)
-				break;
-
-			spin_lock_bh(&e->lock);
-			if (!skb_queue_empty(&e->arpq))
-				setup_l2e_send_pending(dev, skb, e);
-			else	/* we lost the race */
-				__kfree_skb(skb);
-			spin_unlock_bh(&e->lock);
-		}
-	}
-	return 0;
-}
-
-EXPORT_SYMBOL(t3_l2t_send_slow);
-
-void t3_l2t_send_event(struct t3cdev *dev, struct l2t_entry *e)
-{
-again:
-	switch (e->state) {
-	case L2T_STATE_STALE:	/* entry is stale, kick off revalidation */
-		neigh_event_send(e->neigh, NULL);
-		spin_lock_bh(&e->lock);
-		if (e->state == L2T_STATE_STALE) {
-			e->state = L2T_STATE_VALID;
-		}
-		spin_unlock_bh(&e->lock);
-		return;
-	case L2T_STATE_VALID:	/* fast-path, send the packet on */
-		return;
-	case L2T_STATE_RESOLVING:
-		spin_lock_bh(&e->lock);
-		if (e->state != L2T_STATE_RESOLVING) {
-			/* ARP already completed */
-			spin_unlock_bh(&e->lock);
-			goto again;
-		}
-		spin_unlock_bh(&e->lock);
-
-		/*
-		 * Only the first packet added to the arpq should kick off
-		 * resolution.  However, because the alloc_skb below can fail,
-		 * we allow each packet added to the arpq to retry resolution
-		 * as a way of recovering from transient memory exhaustion.
-		 * A better way would be to use a work request to retry L2T
-		 * entries when there's no memory.
-		 */
-		neigh_event_send(e->neigh, NULL);
-	}
-}
-
-EXPORT_SYMBOL(t3_l2t_send_event);
-
-/*
- * Allocate a free L2T entry.  Must be called with l2t_data.lock held.
- */
-static struct l2t_entry *alloc_l2e(struct l2t_data *d)
-{
-	struct l2t_entry *end, *e, **p;
-
-	if (!atomic_read(&d->nfree))
-		return NULL;
-
-	/* there's definitely a free entry */
-	for (e = d->rover, end = &d->l2tab[d->nentries]; e != end; ++e)
-		if (atomic_read(&e->refcnt) == 0)
-			goto found;
-
-	for (e = &d->l2tab[1]; atomic_read(&e->refcnt); ++e) ;
-found:
-	d->rover = e + 1;
-	atomic_dec(&d->nfree);
-
-	/*
-	 * The entry we found may be an inactive entry that is
-	 * presently in the hash table.  We need to remove it.
-	 */
-	if (e->state != L2T_STATE_UNUSED) {
-		int hash = arp_hash(e->addr, e->ifindex, d);
-
-		for (p = &d->l2tab[hash].first; *p; p = &(*p)->next)
-			if (*p == e) {
-				*p = e->next;
-				break;
-			}
-		e->state = L2T_STATE_UNUSED;
-	}
-	return e;
-}
-
-/*
- * Called when an L2T entry has no more users.  The entry is left in the hash
- * table since it is likely to be reused but we also bump nfree to indicate
- * that the entry can be reallocated for a different neighbor.  We also drop
- * the existing neighbor reference in case the neighbor is going away and is
- * waiting on our reference.
- *
- * Because entries can be reallocated to other neighbors once their ref count
- * drops to 0 we need to take the entry's lock to avoid races with a new
- * incarnation.
- */
-void t3_l2e_free(struct l2t_data *d, struct l2t_entry *e)
-{
-	spin_lock_bh(&e->lock);
-	if (atomic_read(&e->refcnt) == 0) {	/* hasn't been recycled */
-		if (e->neigh) {
-			neigh_release(e->neigh);
-			e->neigh = NULL;
-		}
-	}
-	spin_unlock_bh(&e->lock);
-	atomic_inc(&d->nfree);
-}
-
-EXPORT_SYMBOL(t3_l2e_free);
-
-/*
- * Update an L2T entry that was previously used for the same next hop as neigh.
- * Must be called with softirqs disabled.
- */
-static inline void reuse_entry(struct l2t_entry *e, struct neighbour *neigh)
-{
-	unsigned int nud_state;
-
-	spin_lock(&e->lock);	/* avoid race with t3_l2t_free */
-
-	if (neigh != e->neigh)
-		neigh_replace(e, neigh);
-	nud_state = neigh->nud_state;
-	if (memcmp(e->dmac, neigh->ha, sizeof(e->dmac)) ||
-	    !(nud_state & NUD_VALID))
-		e->state = L2T_STATE_RESOLVING;
-	else if (nud_state & NUD_CONNECTED)
-		e->state = L2T_STATE_VALID;
-	else
-		e->state = L2T_STATE_STALE;
-	spin_unlock(&e->lock);
-}
-
-struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh,
-			     struct net_device *dev)
-{
-	struct l2t_entry *e = NULL;
-	struct l2t_data *d;
-	int hash;
-	u32 addr = *(u32 *) neigh->primary_key;
-	int ifidx = neigh->dev->ifindex;
-	struct port_info *p = netdev_priv(dev);
-	int smt_idx = p->port_id;
-
-	rcu_read_lock();
-	d = L2DATA(cdev);
-	if (!d)
-		goto done_rcu;
-
-	hash = arp_hash(addr, ifidx, d);
-
-	write_lock_bh(&d->lock);
-	for (e = d->l2tab[hash].first; e; e = e->next)
-		if (e->addr == addr && e->ifindex == ifidx &&
-		    e->smt_idx == smt_idx) {
-			l2t_hold(d, e);
-			if (atomic_read(&e->refcnt) == 1)
-				reuse_entry(e, neigh);
-			goto done;
-		}
-
-	/* Need to allocate a new entry */
-	e = alloc_l2e(d);
-	if (e) {
-		spin_lock(&e->lock);	/* avoid race with t3_l2t_free */
-		e->next = d->l2tab[hash].first;
-		d->l2tab[hash].first = e;
-		e->state = L2T_STATE_RESOLVING;
-		e->addr = addr;
-		e->ifindex = ifidx;
-		e->smt_idx = smt_idx;
-		atomic_set(&e->refcnt, 1);
-		neigh_replace(e, neigh);
-		if (neigh->dev->priv_flags & IFF_802_1Q_VLAN)
-			e->vlan = vlan_dev_vlan_id(neigh->dev);
-		else
-			e->vlan = VLAN_NONE;
-		spin_unlock(&e->lock);
-	}
-done:
-	write_unlock_bh(&d->lock);
-done_rcu:
-	rcu_read_unlock();
-	return e;
-}
-
-EXPORT_SYMBOL(t3_l2t_get);
-
-/*
- * Called when address resolution fails for an L2T entry to handle packets
- * on the arpq head.  If a packet specifies a failure handler it is invoked,
- * otherwise the packets is sent to the offload device.
- *
- * XXX: maybe we should abandon the latter behavior and just require a failure
- * handler.
- */
-static void handle_failed_resolution(struct t3cdev *dev, struct sk_buff_head *arpq)
-{
-	struct sk_buff *skb, *tmp;
-
-	skb_queue_walk_safe(arpq, skb, tmp) {
-		struct l2t_skb_cb *cb = L2T_SKB_CB(skb);
-
-		__skb_unlink(skb, arpq);
-		if (cb->arp_failure_handler)
-			cb->arp_failure_handler(dev, skb);
-		else
-			cxgb3_ofld_send(dev, skb);
-	}
-}
-
-/*
- * Called when the host's ARP layer makes a change to some entry that is
- * loaded into the HW L2 table.
- */
-void t3_l2t_update(struct t3cdev *dev, struct neighbour *neigh)
-{
-	struct sk_buff_head arpq;
-	struct l2t_entry *e;
-	struct l2t_data *d = L2DATA(dev);
-	u32 addr = *(u32 *) neigh->primary_key;
-	int ifidx = neigh->dev->ifindex;
-	int hash = arp_hash(addr, ifidx, d);
-
-	read_lock_bh(&d->lock);
-	for (e = d->l2tab[hash].first; e; e = e->next)
-		if (e->addr == addr && e->ifindex == ifidx) {
-			spin_lock(&e->lock);
-			goto found;
-		}
-	read_unlock_bh(&d->lock);
-	return;
-
-found:
-	__skb_queue_head_init(&arpq);
-
-	read_unlock(&d->lock);
-	if (atomic_read(&e->refcnt)) {
-		if (neigh != e->neigh)
-			neigh_replace(e, neigh);
-
-		if (e->state == L2T_STATE_RESOLVING) {
-			if (neigh->nud_state & NUD_FAILED) {
-				skb_queue_splice_init(&e->arpq, &arpq);
-			} else if (neigh->nud_state & (NUD_CONNECTED|NUD_STALE))
-				setup_l2e_send_pending(dev, NULL, e);
-		} else {
-			e->state = neigh->nud_state & NUD_CONNECTED ?
-			    L2T_STATE_VALID : L2T_STATE_STALE;
-			if (memcmp(e->dmac, neigh->ha, 6))
-				setup_l2e_send_pending(dev, NULL, e);
-		}
-	}
-	spin_unlock_bh(&e->lock);
-
-	if (!skb_queue_empty(&arpq))
-		handle_failed_resolution(dev, &arpq);
-}
-
-struct l2t_data *t3_init_l2t(unsigned int l2t_capacity)
-{
-	struct l2t_data *d;
-	int i, size = sizeof(*d) + l2t_capacity * sizeof(struct l2t_entry);
-
-	d = cxgb_alloc_mem(size);
-	if (!d)
-		return NULL;
-
-	d->nentries = l2t_capacity;
-	d->rover = &d->l2tab[1];	/* entry 0 is not used */
-	atomic_set(&d->nfree, l2t_capacity - 1);
-	rwlock_init(&d->lock);
-
-	for (i = 0; i < l2t_capacity; ++i) {
-		d->l2tab[i].idx = i;
-		d->l2tab[i].state = L2T_STATE_UNUSED;
-		__skb_queue_head_init(&d->l2tab[i].arpq);
-		spin_lock_init(&d->l2tab[i].lock);
-		atomic_set(&d->l2tab[i].refcnt, 0);
-	}
-	return d;
-}
-
-void t3_free_l2t(struct l2t_data *d)
-{
-	cxgb_free_mem(d);
-}
-
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/l2t.h linux-libre-3.2-gnu/drivers/net/cxgb3/l2t.h
--- linux-libre-3.1-gnu/drivers/net/cxgb3/l2t.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/l2t.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,149 +0,0 @@
-/*
- * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef _CHELSIO_L2T_H
-#define _CHELSIO_L2T_H
-
-#include <linux/spinlock.h>
-#include "t3cdev.h"
-#include <linux/atomic.h>
-
-enum {
-	L2T_STATE_VALID,	/* entry is up to date */
-	L2T_STATE_STALE,	/* entry may be used but needs revalidation */
-	L2T_STATE_RESOLVING,	/* entry needs address resolution */
-	L2T_STATE_UNUSED	/* entry not in use */
-};
-
-struct neighbour;
-struct sk_buff;
-
-/*
- * Each L2T entry plays multiple roles.  First of all, it keeps state for the
- * corresponding entry of the HW L2 table and maintains a queue of offload
- * packets awaiting address resolution.  Second, it is a node of a hash table
- * chain, where the nodes of the chain are linked together through their next
- * pointer.  Finally, each node is a bucket of a hash table, pointing to the
- * first element in its chain through its first pointer.
- */
-struct l2t_entry {
-	u16 state;		/* entry state */
-	u16 idx;		/* entry index */
-	u32 addr;		/* dest IP address */
-	int ifindex;		/* neighbor's net_device's ifindex */
-	u16 smt_idx;		/* SMT index */
-	u16 vlan;		/* VLAN TCI (id: bits 0-11, prio: 13-15 */
-	struct neighbour *neigh;	/* associated neighbour */
-	struct l2t_entry *first;	/* start of hash chain */
-	struct l2t_entry *next;	/* next l2t_entry on chain */
-	struct sk_buff_head arpq;	/* queue of packets awaiting resolution */
-	spinlock_t lock;
-	atomic_t refcnt;	/* entry reference count */
-	u8 dmac[6];		/* neighbour's MAC address */
-};
-
-struct l2t_data {
-	unsigned int nentries;	/* number of entries */
-	struct l2t_entry *rover;	/* starting point for next allocation */
-	atomic_t nfree;		/* number of free entries */
-	rwlock_t lock;
-	struct l2t_entry l2tab[0];
-	struct rcu_head rcu_head;	/* to handle rcu cleanup */
-};
-
-typedef void (*arp_failure_handler_func)(struct t3cdev * dev,
-					 struct sk_buff * skb);
-
-/*
- * Callback stored in an skb to handle address resolution failure.
- */
-struct l2t_skb_cb {
-	arp_failure_handler_func arp_failure_handler;
-};
-
-#define L2T_SKB_CB(skb) ((struct l2t_skb_cb *)(skb)->cb)
-
-static inline void set_arp_failure_handler(struct sk_buff *skb,
-					   arp_failure_handler_func hnd)
-{
-	L2T_SKB_CB(skb)->arp_failure_handler = hnd;
-}
-
-/*
- * Getting to the L2 data from an offload device.
- */
-#define L2DATA(cdev) (rcu_dereference((cdev)->l2opt))
-
-#define W_TCB_L2T_IX    0
-#define S_TCB_L2T_IX    7
-#define M_TCB_L2T_IX    0x7ffULL
-#define V_TCB_L2T_IX(x) ((x) << S_TCB_L2T_IX)
-
-void t3_l2e_free(struct l2t_data *d, struct l2t_entry *e);
-void t3_l2t_update(struct t3cdev *dev, struct neighbour *neigh);
-struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh,
-			     struct net_device *dev);
-int t3_l2t_send_slow(struct t3cdev *dev, struct sk_buff *skb,
-		     struct l2t_entry *e);
-void t3_l2t_send_event(struct t3cdev *dev, struct l2t_entry *e);
-struct l2t_data *t3_init_l2t(unsigned int l2t_capacity);
-void t3_free_l2t(struct l2t_data *d);
-
-int cxgb3_ofld_send(struct t3cdev *dev, struct sk_buff *skb);
-
-static inline int l2t_send(struct t3cdev *dev, struct sk_buff *skb,
-			   struct l2t_entry *e)
-{
-	if (likely(e->state == L2T_STATE_VALID))
-		return cxgb3_ofld_send(dev, skb);
-	return t3_l2t_send_slow(dev, skb, e);
-}
-
-static inline void l2t_release(struct t3cdev *t, struct l2t_entry *e)
-{
-	struct l2t_data *d;
-
-	rcu_read_lock();
-	d = L2DATA(t);
-
-	if (atomic_dec_and_test(&e->refcnt) && d)
-		t3_l2e_free(d, e);
-
-	rcu_read_unlock();
-}
-
-static inline void l2t_hold(struct l2t_data *d, struct l2t_entry *e)
-{
-	if (d && atomic_add_return(1, &e->refcnt) == 1)	/* 0 -> 1 transition */
-		atomic_dec(&d->nfree);
-}
-
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/Makefile linux-libre-3.2-gnu/drivers/net/cxgb3/Makefile
--- linux-libre-3.1-gnu/drivers/net/cxgb3/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,8 +0,0 @@
-#
-# Chelsio T3 driver
-#
-
-obj-$(CONFIG_CHELSIO_T3) += cxgb3.o
-
-cxgb3-objs := cxgb3_main.o ael1002.o vsc8211.o t3_hw.o mc5.o \
-	      xgmac.o sge.o l2t.o cxgb3_offload.o aq100x.o
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/mc5.c linux-libre-3.2-gnu/drivers/net/cxgb3/mc5.c
--- linux-libre-3.1-gnu/drivers/net/cxgb3/mc5.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/mc5.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,438 +0,0 @@
-/*
- * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#include "common.h"
-#include "regs.h"
-
-enum {
-	IDT75P52100 = 4,
-	IDT75N43102 = 5
-};
-
-/* DBGI command mode */
-enum {
-	DBGI_MODE_MBUS = 0,
-	DBGI_MODE_IDT52100 = 5
-};
-
-/* IDT 75P52100 commands */
-#define IDT_CMD_READ   0
-#define IDT_CMD_WRITE  1
-#define IDT_CMD_SEARCH 2
-#define IDT_CMD_LEARN  3
-
-/* IDT LAR register address and value for 144-bit mode (low 32 bits) */
-#define IDT_LAR_ADR0   	0x180006
-#define IDT_LAR_MODE144	0xffff0000
-
-/* IDT SCR and SSR addresses (low 32 bits) */
-#define IDT_SCR_ADR0  0x180000
-#define IDT_SSR0_ADR0 0x180002
-#define IDT_SSR1_ADR0 0x180004
-
-/* IDT GMR base address (low 32 bits) */
-#define IDT_GMR_BASE_ADR0 0x180020
-
-/* IDT data and mask array base addresses (low 32 bits) */
-#define IDT_DATARY_BASE_ADR0 0
-#define IDT_MSKARY_BASE_ADR0 0x80000
-
-/* IDT 75N43102 commands */
-#define IDT4_CMD_SEARCH144 3
-#define IDT4_CMD_WRITE     4
-#define IDT4_CMD_READ      5
-
-/* IDT 75N43102 SCR address (low 32 bits) */
-#define IDT4_SCR_ADR0  0x3
-
-/* IDT 75N43102 GMR base addresses (low 32 bits) */
-#define IDT4_GMR_BASE0 0x10
-#define IDT4_GMR_BASE1 0x20
-#define IDT4_GMR_BASE2 0x30
-
-/* IDT 75N43102 data and mask array base addresses (low 32 bits) */
-#define IDT4_DATARY_BASE_ADR0 0x1000000
-#define IDT4_MSKARY_BASE_ADR0 0x2000000
-
-#define MAX_WRITE_ATTEMPTS 5
-
-#define MAX_ROUTES 2048
-
-/*
- * Issue a command to the TCAM and wait for its completion.  The address and
- * any data required by the command must have been setup by the caller.
- */
-static int mc5_cmd_write(struct adapter *adapter, u32 cmd)
-{
-	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_CMD, cmd);
-	return t3_wait_op_done(adapter, A_MC5_DB_DBGI_RSP_STATUS,
-			       F_DBGIRSPVALID, 1, MAX_WRITE_ATTEMPTS, 1);
-}
-
-static inline void dbgi_wr_addr3(struct adapter *adapter, u32 v1, u32 v2,
-				 u32 v3)
-{
-	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, v1);
-	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR1, v2);
-	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR2, v3);
-}
-
-static inline void dbgi_wr_data3(struct adapter *adapter, u32 v1, u32 v2,
-				 u32 v3)
-{
-	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA0, v1);
-	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA1, v2);
-	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA2, v3);
-}
-
-static inline void dbgi_rd_rsp3(struct adapter *adapter, u32 *v1, u32 *v2,
-				u32 *v3)
-{
-	*v1 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA0);
-	*v2 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA1);
-	*v3 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA2);
-}
-
-/*
- * Write data to the TCAM register at address (0, 0, addr_lo) using the TCAM
- * command cmd.  The data to be written must have been set up by the caller.
- * Returns -1 on failure, 0 on success.
- */
-static int mc5_write(struct adapter *adapter, u32 addr_lo, u32 cmd)
-{
-	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, addr_lo);
-	if (mc5_cmd_write(adapter, cmd) == 0)
-		return 0;
-	CH_ERR(adapter, "MC5 timeout writing to TCAM address 0x%x\n",
-	       addr_lo);
-	return -1;
-}
-
-static int init_mask_data_array(struct mc5 *mc5, u32 mask_array_base,
-				u32 data_array_base, u32 write_cmd,
-				int addr_shift)
-{
-	unsigned int i;
-	struct adapter *adap = mc5->adapter;
-
-	/*
-	 * We need the size of the TCAM data and mask arrays in terms of
-	 * 72-bit entries.
-	 */
-	unsigned int size72 = mc5->tcam_size;
-	unsigned int server_base = t3_read_reg(adap, A_MC5_DB_SERVER_INDEX);
-
-	if (mc5->mode == MC5_MODE_144_BIT) {
-		size72 *= 2;	/* 1 144-bit entry is 2 72-bit entries */
-		server_base *= 2;
-	}
-
-	/* Clear the data array */
-	dbgi_wr_data3(adap, 0, 0, 0);
-	for (i = 0; i < size72; i++)
-		if (mc5_write(adap, data_array_base + (i << addr_shift),
-			      write_cmd))
-			return -1;
-
-	/* Initialize the mask array. */
-	dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
-	for (i = 0; i < size72; i++) {
-		if (i == server_base)	/* entering server or routing region */
-			t3_write_reg(adap, A_MC5_DB_DBGI_REQ_DATA0,
-				     mc5->mode == MC5_MODE_144_BIT ?
-				     0xfffffff9 : 0xfffffffd);
-		if (mc5_write(adap, mask_array_base + (i << addr_shift),
-			      write_cmd))
-			return -1;
-	}
-	return 0;
-}
-
-static int init_idt52100(struct mc5 *mc5)
-{
-	int i;
-	struct adapter *adap = mc5->adapter;
-
-	t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
-		     V_RDLAT(0x15) | V_LRNLAT(0x15) | V_SRCHLAT(0x15));
-	t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 2);
-
-	/*
-	 * Use GMRs 14-15 for ELOOKUP, GMRs 12-13 for SYN lookups, and
-	 * GMRs 8-9 for ACK- and AOPEN searches.
-	 */
-	t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT_CMD_WRITE);
-	t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT_CMD_WRITE);
-	t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD, IDT_CMD_SEARCH);
-	t3_write_reg(adap, A_MC5_DB_AOPEN_LRN_CMD, IDT_CMD_LEARN);
-	t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT_CMD_SEARCH | 0x6000);
-	t3_write_reg(adap, A_MC5_DB_SYN_LRN_CMD, IDT_CMD_LEARN);
-	t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT_CMD_SEARCH);
-	t3_write_reg(adap, A_MC5_DB_ACK_LRN_CMD, IDT_CMD_LEARN);
-	t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT_CMD_SEARCH);
-	t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT_CMD_SEARCH | 0x7000);
-	t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT_CMD_WRITE);
-	t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT_CMD_READ);
-
-	/* Set DBGI command mode for IDT TCAM. */
-	t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
-
-	/* Set up LAR */
-	dbgi_wr_data3(adap, IDT_LAR_MODE144, 0, 0);
-	if (mc5_write(adap, IDT_LAR_ADR0, IDT_CMD_WRITE))
-		goto err;
-
-	/* Set up SSRs */
-	dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0);
-	if (mc5_write(adap, IDT_SSR0_ADR0, IDT_CMD_WRITE) ||
-	    mc5_write(adap, IDT_SSR1_ADR0, IDT_CMD_WRITE))
-		goto err;
-
-	/* Set up GMRs */
-	for (i = 0; i < 32; ++i) {
-		if (i >= 12 && i < 15)
-			dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
-		else if (i == 15)
-			dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
-		else
-			dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
-
-		if (mc5_write(adap, IDT_GMR_BASE_ADR0 + i, IDT_CMD_WRITE))
-			goto err;
-	}
-
-	/* Set up SCR */
-	dbgi_wr_data3(adap, 1, 0, 0);
-	if (mc5_write(adap, IDT_SCR_ADR0, IDT_CMD_WRITE))
-		goto err;
-
-	return init_mask_data_array(mc5, IDT_MSKARY_BASE_ADR0,
-				    IDT_DATARY_BASE_ADR0, IDT_CMD_WRITE, 0);
-err:
-	return -EIO;
-}
-
-static int init_idt43102(struct mc5 *mc5)
-{
-	int i;
-	struct adapter *adap = mc5->adapter;
-
-	t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
-		     adap->params.rev == 0 ? V_RDLAT(0xd) | V_SRCHLAT(0x11) :
-		     V_RDLAT(0xd) | V_SRCHLAT(0x12));
-
-	/*
-	 * Use GMRs 24-25 for ELOOKUP, GMRs 20-21 for SYN lookups, and no mask
-	 * for ACK- and AOPEN searches.
-	 */
-	t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT4_CMD_WRITE);
-	t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT4_CMD_WRITE);
-	t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD,
-		     IDT4_CMD_SEARCH144 | 0x3800);
-	t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT4_CMD_SEARCH144);
-	t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT4_CMD_SEARCH144 | 0x3800);
-	t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x3800);
-	t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x800);
-	t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT4_CMD_WRITE);
-	t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT4_CMD_READ);
-
-	t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 3);
-
-	/* Set DBGI command mode for IDT TCAM. */
-	t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
-
-	/* Set up GMRs */
-	dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
-	for (i = 0; i < 7; ++i)
-		if (mc5_write(adap, IDT4_GMR_BASE0 + i, IDT4_CMD_WRITE))
-			goto err;
-
-	for (i = 0; i < 4; ++i)
-		if (mc5_write(adap, IDT4_GMR_BASE2 + i, IDT4_CMD_WRITE))
-			goto err;
-
-	dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
-	if (mc5_write(adap, IDT4_GMR_BASE1, IDT4_CMD_WRITE) ||
-	    mc5_write(adap, IDT4_GMR_BASE1 + 1, IDT4_CMD_WRITE) ||
-	    mc5_write(adap, IDT4_GMR_BASE1 + 4, IDT4_CMD_WRITE))
-		goto err;
-
-	dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
-	if (mc5_write(adap, IDT4_GMR_BASE1 + 5, IDT4_CMD_WRITE))
-		goto err;
-
-	/* Set up SCR */
-	dbgi_wr_data3(adap, 0xf0000000, 0, 0);
-	if (mc5_write(adap, IDT4_SCR_ADR0, IDT4_CMD_WRITE))
-		goto err;
-
-	return init_mask_data_array(mc5, IDT4_MSKARY_BASE_ADR0,
-				    IDT4_DATARY_BASE_ADR0, IDT4_CMD_WRITE, 1);
-err:
-	return -EIO;
-}
-
-/* Put MC5 in DBGI mode. */
-static inline void mc5_dbgi_mode_enable(const struct mc5 *mc5)
-{
-	t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG,
-		     V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_DBGIEN);
-}
-
-/* Put MC5 in M-Bus mode. */
-static void mc5_dbgi_mode_disable(const struct mc5 *mc5)
-{
-	t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG,
-		     V_TMMODE(mc5->mode == MC5_MODE_72_BIT) |
-		     V_COMPEN(mc5->mode == MC5_MODE_72_BIT) |
-		     V_PRTYEN(mc5->parity_enabled) | F_MBUSEN);
-}
-
-/*
- * Initialization that requires the OS and protocol layers to already
- * be initialized goes here.
- */
-int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
-		unsigned int nroutes)
-{
-	u32 cfg;
-	int err;
-	unsigned int tcam_size = mc5->tcam_size;
-	struct adapter *adap = mc5->adapter;
-
-	if (!tcam_size)
-		return 0;
-
-	if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size)
-		return -EINVAL;
-
-	/* Reset the TCAM */
-	cfg = t3_read_reg(adap, A_MC5_DB_CONFIG) & ~F_TMMODE;
-	cfg |= V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_TMRST;
-	t3_write_reg(adap, A_MC5_DB_CONFIG, cfg);
-	if (t3_wait_op_done(adap, A_MC5_DB_CONFIG, F_TMRDY, 1, 500, 0)) {
-		CH_ERR(adap, "TCAM reset timed out\n");
-		return -1;
-	}
-
-	t3_write_reg(adap, A_MC5_DB_ROUTING_TABLE_INDEX, tcam_size - nroutes);
-	t3_write_reg(adap, A_MC5_DB_FILTER_TABLE,
-		     tcam_size - nroutes - nfilters);
-	t3_write_reg(adap, A_MC5_DB_SERVER_INDEX,
-		     tcam_size - nroutes - nfilters - nservers);
-
-	mc5->parity_enabled = 1;
-
-	/* All the TCAM addresses we access have only the low 32 bits non 0 */
-	t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR1, 0);
-	t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR2, 0);
-
-	mc5_dbgi_mode_enable(mc5);
-
-	switch (mc5->part_type) {
-	case IDT75P52100:
-		err = init_idt52100(mc5);
-		break;
-	case IDT75N43102:
-		err = init_idt43102(mc5);
-		break;
-	default:
-		CH_ERR(adap, "Unsupported TCAM type %d\n", mc5->part_type);
-		err = -EINVAL;
-		break;
-	}
-
-	mc5_dbgi_mode_disable(mc5);
-	return err;
-}
-
-
-#define MC5_INT_FATAL (F_PARITYERR | F_REQQPARERR | F_DISPQPARERR)
-
-/*
- * MC5 interrupt handler
- */
-void t3_mc5_intr_handler(struct mc5 *mc5)
-{
-	struct adapter *adap = mc5->adapter;
-	u32 cause = t3_read_reg(adap, A_MC5_DB_INT_CAUSE);
-
-	if ((cause & F_PARITYERR) && mc5->parity_enabled) {
-		CH_ALERT(adap, "MC5 parity error\n");
-		mc5->stats.parity_err++;
-	}
-
-	if (cause & F_REQQPARERR) {
-		CH_ALERT(adap, "MC5 request queue parity error\n");
-		mc5->stats.reqq_parity_err++;
-	}
-
-	if (cause & F_DISPQPARERR) {
-		CH_ALERT(adap, "MC5 dispatch queue parity error\n");
-		mc5->stats.dispq_parity_err++;
-	}
-
-	if (cause & F_ACTRGNFULL)
-		mc5->stats.active_rgn_full++;
-	if (cause & F_NFASRCHFAIL)
-		mc5->stats.nfa_srch_err++;
-	if (cause & F_UNKNOWNCMD)
-		mc5->stats.unknown_cmd++;
-	if (cause & F_DELACTEMPTY)
-		mc5->stats.del_act_empty++;
-	if (cause & MC5_INT_FATAL)
-		t3_fatal_err(adap);
-
-	t3_write_reg(adap, A_MC5_DB_INT_CAUSE, cause);
-}
-
-void t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode)
-{
-#define K * 1024
-
-	static unsigned int tcam_part_size[] = {	/* in K 72-bit entries */
-		64 K, 128 K, 256 K, 32 K
-	};
-
-#undef K
-
-	u32 cfg = t3_read_reg(adapter, A_MC5_DB_CONFIG);
-
-	mc5->adapter = adapter;
-	mc5->mode = (unsigned char)mode;
-	mc5->part_type = (unsigned char)G_TMTYPE(cfg);
-	if (cfg & F_TMTYPEHI)
-		mc5->part_type |= 4;
-
-	mc5->tcam_size = tcam_part_size[G_TMPARTSIZE(cfg)];
-	if (mode == MC5_MODE_144_BIT)
-		mc5->tcam_size /= 2;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/regs.h linux-libre-3.2-gnu/drivers/net/cxgb3/regs.h
--- linux-libre-3.1-gnu/drivers/net/cxgb3/regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/regs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,2598 +0,0 @@
-#define A_SG_CONTROL 0x0
-
-#define S_CONGMODE    29
-#define V_CONGMODE(x) ((x) << S_CONGMODE)
-#define F_CONGMODE    V_CONGMODE(1U)
-
-#define S_TNLFLMODE    28
-#define V_TNLFLMODE(x) ((x) << S_TNLFLMODE)
-#define F_TNLFLMODE    V_TNLFLMODE(1U)
-
-#define S_FATLPERREN    27
-#define V_FATLPERREN(x) ((x) << S_FATLPERREN)
-#define F_FATLPERREN    V_FATLPERREN(1U)
-
-#define S_DROPPKT    20
-#define V_DROPPKT(x) ((x) << S_DROPPKT)
-#define F_DROPPKT    V_DROPPKT(1U)
-
-#define S_EGRGENCTRL    19
-#define V_EGRGENCTRL(x) ((x) << S_EGRGENCTRL)
-#define F_EGRGENCTRL    V_EGRGENCTRL(1U)
-
-#define S_USERSPACESIZE    14
-#define M_USERSPACESIZE    0x1f
-#define V_USERSPACESIZE(x) ((x) << S_USERSPACESIZE)
-
-#define S_HOSTPAGESIZE    11
-#define M_HOSTPAGESIZE    0x7
-#define V_HOSTPAGESIZE(x) ((x) << S_HOSTPAGESIZE)
-
-#define S_FLMODE    9
-#define V_FLMODE(x) ((x) << S_FLMODE)
-#define F_FLMODE    V_FLMODE(1U)
-
-#define S_PKTSHIFT    6
-#define M_PKTSHIFT    0x7
-#define V_PKTSHIFT(x) ((x) << S_PKTSHIFT)
-
-#define S_ONEINTMULTQ    5
-#define V_ONEINTMULTQ(x) ((x) << S_ONEINTMULTQ)
-#define F_ONEINTMULTQ    V_ONEINTMULTQ(1U)
-
-#define S_BIGENDIANINGRESS    2
-#define V_BIGENDIANINGRESS(x) ((x) << S_BIGENDIANINGRESS)
-#define F_BIGENDIANINGRESS    V_BIGENDIANINGRESS(1U)
-
-#define S_ISCSICOALESCING    1
-#define V_ISCSICOALESCING(x) ((x) << S_ISCSICOALESCING)
-#define F_ISCSICOALESCING    V_ISCSICOALESCING(1U)
-
-#define S_GLOBALENABLE    0
-#define V_GLOBALENABLE(x) ((x) << S_GLOBALENABLE)
-#define F_GLOBALENABLE    V_GLOBALENABLE(1U)
-
-#define S_AVOIDCQOVFL    24
-#define V_AVOIDCQOVFL(x) ((x) << S_AVOIDCQOVFL)
-#define F_AVOIDCQOVFL    V_AVOIDCQOVFL(1U)
-
-#define S_OPTONEINTMULTQ    23
-#define V_OPTONEINTMULTQ(x) ((x) << S_OPTONEINTMULTQ)
-#define F_OPTONEINTMULTQ    V_OPTONEINTMULTQ(1U)
-
-#define S_CQCRDTCTRL    22
-#define V_CQCRDTCTRL(x) ((x) << S_CQCRDTCTRL)
-#define F_CQCRDTCTRL    V_CQCRDTCTRL(1U)
-
-#define A_SG_KDOORBELL 0x4
-
-#define S_SELEGRCNTX    31
-#define V_SELEGRCNTX(x) ((x) << S_SELEGRCNTX)
-#define F_SELEGRCNTX    V_SELEGRCNTX(1U)
-
-#define S_EGRCNTX    0
-#define M_EGRCNTX    0xffff
-#define V_EGRCNTX(x) ((x) << S_EGRCNTX)
-
-#define A_SG_GTS 0x8
-
-#define S_RSPQ    29
-#define M_RSPQ    0x7
-#define V_RSPQ(x) ((x) << S_RSPQ)
-#define G_RSPQ(x) (((x) >> S_RSPQ) & M_RSPQ)
-
-#define S_NEWTIMER    16
-#define M_NEWTIMER    0x1fff
-#define V_NEWTIMER(x) ((x) << S_NEWTIMER)
-
-#define S_NEWINDEX    0
-#define M_NEWINDEX    0xffff
-#define V_NEWINDEX(x) ((x) << S_NEWINDEX)
-
-#define A_SG_CONTEXT_CMD 0xc
-
-#define S_CONTEXT_CMD_OPCODE    28
-#define M_CONTEXT_CMD_OPCODE    0xf
-#define V_CONTEXT_CMD_OPCODE(x) ((x) << S_CONTEXT_CMD_OPCODE)
-
-#define S_CONTEXT_CMD_BUSY    27
-#define V_CONTEXT_CMD_BUSY(x) ((x) << S_CONTEXT_CMD_BUSY)
-#define F_CONTEXT_CMD_BUSY    V_CONTEXT_CMD_BUSY(1U)
-
-#define S_CQ_CREDIT    20
-
-#define M_CQ_CREDIT    0x7f
-
-#define V_CQ_CREDIT(x) ((x) << S_CQ_CREDIT)
-
-#define G_CQ_CREDIT(x) (((x) >> S_CQ_CREDIT) & M_CQ_CREDIT)
-
-#define S_CQ    19
-
-#define V_CQ(x) ((x) << S_CQ)
-#define F_CQ    V_CQ(1U)
-
-#define S_RESPONSEQ    18
-#define V_RESPONSEQ(x) ((x) << S_RESPONSEQ)
-#define F_RESPONSEQ    V_RESPONSEQ(1U)
-
-#define S_EGRESS    17
-#define V_EGRESS(x) ((x) << S_EGRESS)
-#define F_EGRESS    V_EGRESS(1U)
-
-#define S_FREELIST    16
-#define V_FREELIST(x) ((x) << S_FREELIST)
-#define F_FREELIST    V_FREELIST(1U)
-
-#define S_CONTEXT    0
-#define M_CONTEXT    0xffff
-#define V_CONTEXT(x) ((x) << S_CONTEXT)
-
-#define G_CONTEXT(x) (((x) >> S_CONTEXT) & M_CONTEXT)
-
-#define A_SG_CONTEXT_DATA0 0x10
-
-#define A_SG_CONTEXT_DATA1 0x14
-
-#define A_SG_CONTEXT_DATA2 0x18
-
-#define A_SG_CONTEXT_DATA3 0x1c
-
-#define A_SG_CONTEXT_MASK0 0x20
-
-#define A_SG_CONTEXT_MASK1 0x24
-
-#define A_SG_CONTEXT_MASK2 0x28
-
-#define A_SG_CONTEXT_MASK3 0x2c
-
-#define A_SG_RSPQ_CREDIT_RETURN 0x30
-
-#define S_CREDITS    0
-#define M_CREDITS    0xffff
-#define V_CREDITS(x) ((x) << S_CREDITS)
-
-#define A_SG_DATA_INTR 0x34
-
-#define S_ERRINTR    31
-#define V_ERRINTR(x) ((x) << S_ERRINTR)
-#define F_ERRINTR    V_ERRINTR(1U)
-
-#define A_SG_HI_DRB_HI_THRSH 0x38
-
-#define A_SG_HI_DRB_LO_THRSH 0x3c
-
-#define A_SG_LO_DRB_HI_THRSH 0x40
-
-#define A_SG_LO_DRB_LO_THRSH 0x44
-
-#define A_SG_RSPQ_FL_STATUS 0x4c
-
-#define S_RSPQ0DISABLED    8
-
-#define S_FL0EMPTY    16
-#define V_FL0EMPTY(x) ((x) << S_FL0EMPTY)
-#define F_FL0EMPTY    V_FL0EMPTY(1U)
-
-#define A_SG_EGR_RCQ_DRB_THRSH 0x54
-
-#define S_HIRCQDRBTHRSH    16
-#define M_HIRCQDRBTHRSH    0x7ff
-#define V_HIRCQDRBTHRSH(x) ((x) << S_HIRCQDRBTHRSH)
-
-#define S_LORCQDRBTHRSH    0
-#define M_LORCQDRBTHRSH    0x7ff
-#define V_LORCQDRBTHRSH(x) ((x) << S_LORCQDRBTHRSH)
-
-#define A_SG_EGR_CNTX_BADDR 0x58
-
-#define A_SG_INT_CAUSE 0x5c
-
-#define S_HIRCQPARITYERROR    31
-#define V_HIRCQPARITYERROR(x) ((x) << S_HIRCQPARITYERROR)
-#define F_HIRCQPARITYERROR    V_HIRCQPARITYERROR(1U)
-
-#define S_LORCQPARITYERROR    30
-#define V_LORCQPARITYERROR(x) ((x) << S_LORCQPARITYERROR)
-#define F_LORCQPARITYERROR    V_LORCQPARITYERROR(1U)
-
-#define S_HIDRBPARITYERROR    29
-#define V_HIDRBPARITYERROR(x) ((x) << S_HIDRBPARITYERROR)
-#define F_HIDRBPARITYERROR    V_HIDRBPARITYERROR(1U)
-
-#define S_LODRBPARITYERROR    28
-#define V_LODRBPARITYERROR(x) ((x) << S_LODRBPARITYERROR)
-#define F_LODRBPARITYERROR    V_LODRBPARITYERROR(1U)
-
-#define S_FLPARITYERROR    22
-#define M_FLPARITYERROR    0x3f
-#define V_FLPARITYERROR(x) ((x) << S_FLPARITYERROR)
-#define G_FLPARITYERROR(x) (((x) >> S_FLPARITYERROR) & M_FLPARITYERROR)
-
-#define S_ITPARITYERROR    20
-#define M_ITPARITYERROR    0x3
-#define V_ITPARITYERROR(x) ((x) << S_ITPARITYERROR)
-#define G_ITPARITYERROR(x) (((x) >> S_ITPARITYERROR) & M_ITPARITYERROR)
-
-#define S_IRPARITYERROR    19
-#define V_IRPARITYERROR(x) ((x) << S_IRPARITYERROR)
-#define F_IRPARITYERROR    V_IRPARITYERROR(1U)
-
-#define S_RCPARITYERROR    18
-#define V_RCPARITYERROR(x) ((x) << S_RCPARITYERROR)
-#define F_RCPARITYERROR    V_RCPARITYERROR(1U)
-
-#define S_OCPARITYERROR    17
-#define V_OCPARITYERROR(x) ((x) << S_OCPARITYERROR)
-#define F_OCPARITYERROR    V_OCPARITYERROR(1U)
-
-#define S_CPPARITYERROR    16
-#define V_CPPARITYERROR(x) ((x) << S_CPPARITYERROR)
-#define F_CPPARITYERROR    V_CPPARITYERROR(1U)
-
-#define S_R_REQ_FRAMINGERROR    15
-#define V_R_REQ_FRAMINGERROR(x) ((x) << S_R_REQ_FRAMINGERROR)
-#define F_R_REQ_FRAMINGERROR    V_R_REQ_FRAMINGERROR(1U)
-
-#define S_UC_REQ_FRAMINGERROR    14
-#define V_UC_REQ_FRAMINGERROR(x) ((x) << S_UC_REQ_FRAMINGERROR)
-#define F_UC_REQ_FRAMINGERROR    V_UC_REQ_FRAMINGERROR(1U)
-
-#define S_HICTLDRBDROPERR    13
-#define V_HICTLDRBDROPERR(x) ((x) << S_HICTLDRBDROPERR)
-#define F_HICTLDRBDROPERR    V_HICTLDRBDROPERR(1U)
-
-#define S_LOCTLDRBDROPERR    12
-#define V_LOCTLDRBDROPERR(x) ((x) << S_LOCTLDRBDROPERR)
-#define F_LOCTLDRBDROPERR    V_LOCTLDRBDROPERR(1U)
-
-#define S_HIPIODRBDROPERR    11
-#define V_HIPIODRBDROPERR(x) ((x) << S_HIPIODRBDROPERR)
-#define F_HIPIODRBDROPERR    V_HIPIODRBDROPERR(1U)
-
-#define S_LOPIODRBDROPERR    10
-#define V_LOPIODRBDROPERR(x) ((x) << S_LOPIODRBDROPERR)
-#define F_LOPIODRBDROPERR    V_LOPIODRBDROPERR(1U)
-
-#define S_HIPRIORITYDBFULL    7
-#define V_HIPRIORITYDBFULL(x) ((x) << S_HIPRIORITYDBFULL)
-#define F_HIPRIORITYDBFULL    V_HIPRIORITYDBFULL(1U)
-
-#define S_HIPRIORITYDBEMPTY   6
-#define V_HIPRIORITYDBEMPTY(x) ((x) << S_HIPRIORITYDBEMPTY)
-#define F_HIPRIORITYDBEMPTY    V_HIPRIORITYDBEMPTY(1U)
-
-#define S_LOPRIORITYDBFULL    5
-#define V_LOPRIORITYDBFULL(x) ((x) << S_LOPRIORITYDBFULL)
-#define F_LOPRIORITYDBFULL    V_LOPRIORITYDBFULL(1U)
-
-#define S_LOPRIORITYDBEMPTY   4
-#define V_LOPRIORITYDBEMPTY(x) ((x) << S_LOPRIORITYDBEMPTY)
-#define F_LOPRIORITYDBEMPTY    V_LOPRIORITYDBEMPTY(1U)
-
-#define S_RSPQDISABLED    3
-#define V_RSPQDISABLED(x) ((x) << S_RSPQDISABLED)
-#define F_RSPQDISABLED    V_RSPQDISABLED(1U)
-
-#define S_RSPQCREDITOVERFOW    2
-#define V_RSPQCREDITOVERFOW(x) ((x) << S_RSPQCREDITOVERFOW)
-#define F_RSPQCREDITOVERFOW    V_RSPQCREDITOVERFOW(1U)
-
-#define S_FLEMPTY    1
-#define V_FLEMPTY(x) ((x) << S_FLEMPTY)
-#define F_FLEMPTY    V_FLEMPTY(1U)
-
-#define A_SG_INT_ENABLE 0x60
-
-#define A_SG_CMDQ_CREDIT_TH 0x64
-
-#define S_TIMEOUT    8
-#define M_TIMEOUT    0xffffff
-#define V_TIMEOUT(x) ((x) << S_TIMEOUT)
-
-#define S_THRESHOLD    0
-#define M_THRESHOLD    0xff
-#define V_THRESHOLD(x) ((x) << S_THRESHOLD)
-
-#define A_SG_TIMER_TICK 0x68
-
-#define A_SG_CQ_CONTEXT_BADDR 0x6c
-
-#define A_SG_OCO_BASE 0x70
-
-#define S_BASE1    16
-#define M_BASE1    0xffff
-#define V_BASE1(x) ((x) << S_BASE1)
-
-#define A_SG_DRB_PRI_THRESH 0x74
-
-#define A_PCIX_INT_ENABLE 0x80
-
-#define S_MSIXPARERR    22
-#define M_MSIXPARERR    0x7
-
-#define V_MSIXPARERR(x) ((x) << S_MSIXPARERR)
-
-#define S_CFPARERR    18
-#define M_CFPARERR    0xf
-
-#define V_CFPARERR(x) ((x) << S_CFPARERR)
-
-#define S_RFPARERR    14
-#define M_RFPARERR    0xf
-
-#define V_RFPARERR(x) ((x) << S_RFPARERR)
-
-#define S_WFPARERR    12
-#define M_WFPARERR    0x3
-
-#define V_WFPARERR(x) ((x) << S_WFPARERR)
-
-#define S_PIOPARERR    11
-#define V_PIOPARERR(x) ((x) << S_PIOPARERR)
-#define F_PIOPARERR    V_PIOPARERR(1U)
-
-#define S_DETUNCECCERR    10
-#define V_DETUNCECCERR(x) ((x) << S_DETUNCECCERR)
-#define F_DETUNCECCERR    V_DETUNCECCERR(1U)
-
-#define S_DETCORECCERR    9
-#define V_DETCORECCERR(x) ((x) << S_DETCORECCERR)
-#define F_DETCORECCERR    V_DETCORECCERR(1U)
-
-#define S_RCVSPLCMPERR    8
-#define V_RCVSPLCMPERR(x) ((x) << S_RCVSPLCMPERR)
-#define F_RCVSPLCMPERR    V_RCVSPLCMPERR(1U)
-
-#define S_UNXSPLCMP    7
-#define V_UNXSPLCMP(x) ((x) << S_UNXSPLCMP)
-#define F_UNXSPLCMP    V_UNXSPLCMP(1U)
-
-#define S_SPLCMPDIS    6
-#define V_SPLCMPDIS(x) ((x) << S_SPLCMPDIS)
-#define F_SPLCMPDIS    V_SPLCMPDIS(1U)
-
-#define S_DETPARERR    5
-#define V_DETPARERR(x) ((x) << S_DETPARERR)
-#define F_DETPARERR    V_DETPARERR(1U)
-
-#define S_SIGSYSERR    4
-#define V_SIGSYSERR(x) ((x) << S_SIGSYSERR)
-#define F_SIGSYSERR    V_SIGSYSERR(1U)
-
-#define S_RCVMSTABT    3
-#define V_RCVMSTABT(x) ((x) << S_RCVMSTABT)
-#define F_RCVMSTABT    V_RCVMSTABT(1U)
-
-#define S_RCVTARABT    2
-#define V_RCVTARABT(x) ((x) << S_RCVTARABT)
-#define F_RCVTARABT    V_RCVTARABT(1U)
-
-#define S_SIGTARABT    1
-#define V_SIGTARABT(x) ((x) << S_SIGTARABT)
-#define F_SIGTARABT    V_SIGTARABT(1U)
-
-#define S_MSTDETPARERR    0
-#define V_MSTDETPARERR(x) ((x) << S_MSTDETPARERR)
-#define F_MSTDETPARERR    V_MSTDETPARERR(1U)
-
-#define A_PCIX_INT_CAUSE 0x84
-
-#define A_PCIX_CFG 0x88
-
-#define S_DMASTOPEN    19
-#define V_DMASTOPEN(x) ((x) << S_DMASTOPEN)
-#define F_DMASTOPEN    V_DMASTOPEN(1U)
-
-#define S_CLIDECEN    18
-#define V_CLIDECEN(x) ((x) << S_CLIDECEN)
-#define F_CLIDECEN    V_CLIDECEN(1U)
-
-#define A_PCIX_MODE 0x8c
-
-#define S_PCLKRANGE    6
-#define M_PCLKRANGE    0x3
-#define V_PCLKRANGE(x) ((x) << S_PCLKRANGE)
-#define G_PCLKRANGE(x) (((x) >> S_PCLKRANGE) & M_PCLKRANGE)
-
-#define S_PCIXINITPAT    2
-#define M_PCIXINITPAT    0xf
-#define V_PCIXINITPAT(x) ((x) << S_PCIXINITPAT)
-#define G_PCIXINITPAT(x) (((x) >> S_PCIXINITPAT) & M_PCIXINITPAT)
-
-#define S_64BIT    0
-#define V_64BIT(x) ((x) << S_64BIT)
-#define F_64BIT    V_64BIT(1U)
-
-#define A_PCIE_INT_ENABLE 0x80
-
-#define S_BISTERR    15
-#define M_BISTERR    0xff
-
-#define V_BISTERR(x) ((x) << S_BISTERR)
-
-#define S_TXPARERR    18
-#define V_TXPARERR(x) ((x) << S_TXPARERR)
-#define F_TXPARERR    V_TXPARERR(1U)
-
-#define S_RXPARERR    17
-#define V_RXPARERR(x) ((x) << S_RXPARERR)
-#define F_RXPARERR    V_RXPARERR(1U)
-
-#define S_RETRYLUTPARERR    16
-#define V_RETRYLUTPARERR(x) ((x) << S_RETRYLUTPARERR)
-#define F_RETRYLUTPARERR    V_RETRYLUTPARERR(1U)
-
-#define S_RETRYBUFPARERR    15
-#define V_RETRYBUFPARERR(x) ((x) << S_RETRYBUFPARERR)
-#define F_RETRYBUFPARERR    V_RETRYBUFPARERR(1U)
-
-#define S_PCIE_MSIXPARERR    12
-#define M_PCIE_MSIXPARERR    0x7
-
-#define V_PCIE_MSIXPARERR(x) ((x) << S_PCIE_MSIXPARERR)
-
-#define S_PCIE_CFPARERR    11
-#define V_PCIE_CFPARERR(x) ((x) << S_PCIE_CFPARERR)
-#define F_PCIE_CFPARERR    V_PCIE_CFPARERR(1U)
-
-#define S_PCIE_RFPARERR    10
-#define V_PCIE_RFPARERR(x) ((x) << S_PCIE_RFPARERR)
-#define F_PCIE_RFPARERR    V_PCIE_RFPARERR(1U)
-
-#define S_PCIE_WFPARERR    9
-#define V_PCIE_WFPARERR(x) ((x) << S_PCIE_WFPARERR)
-#define F_PCIE_WFPARERR    V_PCIE_WFPARERR(1U)
-
-#define S_PCIE_PIOPARERR    8
-#define V_PCIE_PIOPARERR(x) ((x) << S_PCIE_PIOPARERR)
-#define F_PCIE_PIOPARERR    V_PCIE_PIOPARERR(1U)
-
-#define S_UNXSPLCPLERRC    7
-#define V_UNXSPLCPLERRC(x) ((x) << S_UNXSPLCPLERRC)
-#define F_UNXSPLCPLERRC    V_UNXSPLCPLERRC(1U)
-
-#define S_UNXSPLCPLERRR    6
-#define V_UNXSPLCPLERRR(x) ((x) << S_UNXSPLCPLERRR)
-#define F_UNXSPLCPLERRR    V_UNXSPLCPLERRR(1U)
-
-#define S_PEXERR    0
-#define V_PEXERR(x) ((x) << S_PEXERR)
-#define F_PEXERR    V_PEXERR(1U)
-
-#define A_PCIE_INT_CAUSE 0x84
-
-#define S_PCIE_DMASTOPEN    24
-#define V_PCIE_DMASTOPEN(x) ((x) << S_PCIE_DMASTOPEN)
-#define F_PCIE_DMASTOPEN    V_PCIE_DMASTOPEN(1U)
-
-#define A_PCIE_CFG 0x88
-
-#define S_ENABLELINKDWNDRST    21
-#define V_ENABLELINKDWNDRST(x) ((x) << S_ENABLELINKDWNDRST)
-#define F_ENABLELINKDWNDRST    V_ENABLELINKDWNDRST(1U)
-
-#define S_ENABLELINKDOWNRST    20
-#define V_ENABLELINKDOWNRST(x) ((x) << S_ENABLELINKDOWNRST)
-#define F_ENABLELINKDOWNRST    V_ENABLELINKDOWNRST(1U)
-
-#define S_PCIE_CLIDECEN    16
-#define V_PCIE_CLIDECEN(x) ((x) << S_PCIE_CLIDECEN)
-#define F_PCIE_CLIDECEN    V_PCIE_CLIDECEN(1U)
-
-#define S_CRSTWRMMODE    0
-#define V_CRSTWRMMODE(x) ((x) << S_CRSTWRMMODE)
-#define F_CRSTWRMMODE    V_CRSTWRMMODE(1U)
-
-#define A_PCIE_MODE 0x8c
-
-#define S_NUMFSTTRNSEQRX    10
-#define M_NUMFSTTRNSEQRX    0xff
-#define V_NUMFSTTRNSEQRX(x) ((x) << S_NUMFSTTRNSEQRX)
-#define G_NUMFSTTRNSEQRX(x) (((x) >> S_NUMFSTTRNSEQRX) & M_NUMFSTTRNSEQRX)
-
-#define A_PCIE_PEX_CTRL0 0x98
-
-#define S_NUMFSTTRNSEQ    22
-#define M_NUMFSTTRNSEQ    0xff
-#define V_NUMFSTTRNSEQ(x) ((x) << S_NUMFSTTRNSEQ)
-#define G_NUMFSTTRNSEQ(x) (((x) >> S_NUMFSTTRNSEQ) & M_NUMFSTTRNSEQ)
-
-#define S_REPLAYLMT    2
-#define M_REPLAYLMT    0xfffff
-
-#define V_REPLAYLMT(x) ((x) << S_REPLAYLMT)
-
-#define A_PCIE_PEX_CTRL1 0x9c
-
-#define S_T3A_ACKLAT    0
-#define M_T3A_ACKLAT    0x7ff
-
-#define V_T3A_ACKLAT(x) ((x) << S_T3A_ACKLAT)
-
-#define S_ACKLAT    0
-#define M_ACKLAT    0x1fff
-
-#define V_ACKLAT(x) ((x) << S_ACKLAT)
-
-#define A_PCIE_PEX_ERR 0xa4
-
-#define A_T3DBG_GPIO_EN 0xd0
-
-#define S_GPIO11_OEN    27
-#define V_GPIO11_OEN(x) ((x) << S_GPIO11_OEN)
-#define F_GPIO11_OEN    V_GPIO11_OEN(1U)
-
-#define S_GPIO10_OEN    26
-#define V_GPIO10_OEN(x) ((x) << S_GPIO10_OEN)
-#define F_GPIO10_OEN    V_GPIO10_OEN(1U)
-
-#define S_GPIO7_OEN    23
-#define V_GPIO7_OEN(x) ((x) << S_GPIO7_OEN)
-#define F_GPIO7_OEN    V_GPIO7_OEN(1U)
-
-#define S_GPIO6_OEN    22
-#define V_GPIO6_OEN(x) ((x) << S_GPIO6_OEN)
-#define F_GPIO6_OEN    V_GPIO6_OEN(1U)
-
-#define S_GPIO5_OEN    21
-#define V_GPIO5_OEN(x) ((x) << S_GPIO5_OEN)
-#define F_GPIO5_OEN    V_GPIO5_OEN(1U)
-
-#define S_GPIO4_OEN    20
-#define V_GPIO4_OEN(x) ((x) << S_GPIO4_OEN)
-#define F_GPIO4_OEN    V_GPIO4_OEN(1U)
-
-#define S_GPIO2_OEN    18
-#define V_GPIO2_OEN(x) ((x) << S_GPIO2_OEN)
-#define F_GPIO2_OEN    V_GPIO2_OEN(1U)
-
-#define S_GPIO1_OEN    17
-#define V_GPIO1_OEN(x) ((x) << S_GPIO1_OEN)
-#define F_GPIO1_OEN    V_GPIO1_OEN(1U)
-
-#define S_GPIO0_OEN    16
-#define V_GPIO0_OEN(x) ((x) << S_GPIO0_OEN)
-#define F_GPIO0_OEN    V_GPIO0_OEN(1U)
-
-#define S_GPIO10_OUT_VAL    10
-#define V_GPIO10_OUT_VAL(x) ((x) << S_GPIO10_OUT_VAL)
-#define F_GPIO10_OUT_VAL    V_GPIO10_OUT_VAL(1U)
-
-#define S_GPIO7_OUT_VAL    7
-#define V_GPIO7_OUT_VAL(x) ((x) << S_GPIO7_OUT_VAL)
-#define F_GPIO7_OUT_VAL    V_GPIO7_OUT_VAL(1U)
-
-#define S_GPIO6_OUT_VAL    6
-#define V_GPIO6_OUT_VAL(x) ((x) << S_GPIO6_OUT_VAL)
-#define F_GPIO6_OUT_VAL    V_GPIO6_OUT_VAL(1U)
-
-#define S_GPIO5_OUT_VAL    5
-#define V_GPIO5_OUT_VAL(x) ((x) << S_GPIO5_OUT_VAL)
-#define F_GPIO5_OUT_VAL    V_GPIO5_OUT_VAL(1U)
-
-#define S_GPIO4_OUT_VAL    4
-#define V_GPIO4_OUT_VAL(x) ((x) << S_GPIO4_OUT_VAL)
-#define F_GPIO4_OUT_VAL    V_GPIO4_OUT_VAL(1U)
-
-#define S_GPIO2_OUT_VAL    2
-#define V_GPIO2_OUT_VAL(x) ((x) << S_GPIO2_OUT_VAL)
-#define F_GPIO2_OUT_VAL    V_GPIO2_OUT_VAL(1U)
-
-#define S_GPIO1_OUT_VAL    1
-#define V_GPIO1_OUT_VAL(x) ((x) << S_GPIO1_OUT_VAL)
-#define F_GPIO1_OUT_VAL    V_GPIO1_OUT_VAL(1U)
-
-#define S_GPIO0_OUT_VAL    0
-#define V_GPIO0_OUT_VAL(x) ((x) << S_GPIO0_OUT_VAL)
-#define F_GPIO0_OUT_VAL    V_GPIO0_OUT_VAL(1U)
-
-#define A_T3DBG_INT_ENABLE 0xd8
-
-#define S_GPIO11    11
-#define V_GPIO11(x) ((x) << S_GPIO11)
-#define F_GPIO11    V_GPIO11(1U)
-
-#define S_GPIO10    10
-#define V_GPIO10(x) ((x) << S_GPIO10)
-#define F_GPIO10    V_GPIO10(1U)
-
-#define S_GPIO9    9
-#define V_GPIO9(x) ((x) << S_GPIO9)
-#define F_GPIO9    V_GPIO9(1U)
-
-#define S_GPIO7    7
-#define V_GPIO7(x) ((x) << S_GPIO7)
-#define F_GPIO7    V_GPIO7(1U)
-
-#define S_GPIO6    6
-#define V_GPIO6(x) ((x) << S_GPIO6)
-#define F_GPIO6    V_GPIO6(1U)
-
-#define S_GPIO5    5
-#define V_GPIO5(x) ((x) << S_GPIO5)
-#define F_GPIO5    V_GPIO5(1U)
-
-#define S_GPIO4    4
-#define V_GPIO4(x) ((x) << S_GPIO4)
-#define F_GPIO4    V_GPIO4(1U)
-
-#define S_GPIO3    3
-#define V_GPIO3(x) ((x) << S_GPIO3)
-#define F_GPIO3    V_GPIO3(1U)
-
-#define S_GPIO2    2
-#define V_GPIO2(x) ((x) << S_GPIO2)
-#define F_GPIO2    V_GPIO2(1U)
-
-#define S_GPIO1    1
-#define V_GPIO1(x) ((x) << S_GPIO1)
-#define F_GPIO1    V_GPIO1(1U)
-
-#define S_GPIO0    0
-#define V_GPIO0(x) ((x) << S_GPIO0)
-#define F_GPIO0    V_GPIO0(1U)
-
-#define A_T3DBG_INT_CAUSE 0xdc
-
-#define A_T3DBG_GPIO_ACT_LOW 0xf0
-
-#define MC7_PMRX_BASE_ADDR 0x100
-
-#define A_MC7_CFG 0x100
-
-#define S_IFEN    13
-#define V_IFEN(x) ((x) << S_IFEN)
-#define F_IFEN    V_IFEN(1U)
-
-#define S_TERM150    11
-#define V_TERM150(x) ((x) << S_TERM150)
-#define F_TERM150    V_TERM150(1U)
-
-#define S_SLOW    10
-#define V_SLOW(x) ((x) << S_SLOW)
-#define F_SLOW    V_SLOW(1U)
-
-#define S_WIDTH    8
-#define M_WIDTH    0x3
-#define V_WIDTH(x) ((x) << S_WIDTH)
-#define G_WIDTH(x) (((x) >> S_WIDTH) & M_WIDTH)
-
-#define S_BKS    6
-#define V_BKS(x) ((x) << S_BKS)
-#define F_BKS    V_BKS(1U)
-
-#define S_ORG    5
-#define V_ORG(x) ((x) << S_ORG)
-#define F_ORG    V_ORG(1U)
-
-#define S_DEN    2
-#define M_DEN    0x7
-#define V_DEN(x) ((x) << S_DEN)
-#define G_DEN(x) (((x) >> S_DEN) & M_DEN)
-
-#define S_RDY    1
-#define V_RDY(x) ((x) << S_RDY)
-#define F_RDY    V_RDY(1U)
-
-#define S_CLKEN    0
-#define V_CLKEN(x) ((x) << S_CLKEN)
-#define F_CLKEN    V_CLKEN(1U)
-
-#define A_MC7_MODE 0x104
-
-#define S_BUSY    31
-#define V_BUSY(x) ((x) << S_BUSY)
-#define F_BUSY    V_BUSY(1U)
-
-#define S_BUSY    31
-#define V_BUSY(x) ((x) << S_BUSY)
-#define F_BUSY    V_BUSY(1U)
-
-#define A_MC7_EXT_MODE1 0x108
-
-#define A_MC7_EXT_MODE2 0x10c
-
-#define A_MC7_EXT_MODE3 0x110
-
-#define A_MC7_PRE 0x114
-
-#define A_MC7_REF 0x118
-
-#define S_PREREFDIV    1
-#define M_PREREFDIV    0x3fff
-#define V_PREREFDIV(x) ((x) << S_PREREFDIV)
-
-#define S_PERREFEN    0
-#define V_PERREFEN(x) ((x) << S_PERREFEN)
-#define F_PERREFEN    V_PERREFEN(1U)
-
-#define A_MC7_DLL 0x11c
-
-#define S_DLLENB    1
-#define V_DLLENB(x) ((x) << S_DLLENB)
-#define F_DLLENB    V_DLLENB(1U)
-
-#define S_DLLRST    0
-#define V_DLLRST(x) ((x) << S_DLLRST)
-#define F_DLLRST    V_DLLRST(1U)
-
-#define A_MC7_PARM 0x120
-
-#define S_ACTTOPREDLY    26
-#define M_ACTTOPREDLY    0xf
-#define V_ACTTOPREDLY(x) ((x) << S_ACTTOPREDLY)
-
-#define S_ACTTORDWRDLY    23
-#define M_ACTTORDWRDLY    0x7
-#define V_ACTTORDWRDLY(x) ((x) << S_ACTTORDWRDLY)
-
-#define S_PRECYC    20
-#define M_PRECYC    0x7
-#define V_PRECYC(x) ((x) << S_PRECYC)
-
-#define S_REFCYC    13
-#define M_REFCYC    0x7f
-#define V_REFCYC(x) ((x) << S_REFCYC)
-
-#define S_BKCYC    8
-#define M_BKCYC    0x1f
-#define V_BKCYC(x) ((x) << S_BKCYC)
-
-#define S_WRTORDDLY    4
-#define M_WRTORDDLY    0xf
-#define V_WRTORDDLY(x) ((x) << S_WRTORDDLY)
-
-#define S_RDTOWRDLY    0
-#define M_RDTOWRDLY    0xf
-#define V_RDTOWRDLY(x) ((x) << S_RDTOWRDLY)
-
-#define A_MC7_CAL 0x128
-
-#define S_BUSY    31
-#define V_BUSY(x) ((x) << S_BUSY)
-#define F_BUSY    V_BUSY(1U)
-
-#define S_BUSY    31
-#define V_BUSY(x) ((x) << S_BUSY)
-#define F_BUSY    V_BUSY(1U)
-
-#define S_CAL_FAULT    30
-#define V_CAL_FAULT(x) ((x) << S_CAL_FAULT)
-#define F_CAL_FAULT    V_CAL_FAULT(1U)
-
-#define S_SGL_CAL_EN    20
-#define V_SGL_CAL_EN(x) ((x) << S_SGL_CAL_EN)
-#define F_SGL_CAL_EN    V_SGL_CAL_EN(1U)
-
-#define A_MC7_ERR_ADDR 0x12c
-
-#define A_MC7_ECC 0x130
-
-#define S_ECCCHKEN    1
-#define V_ECCCHKEN(x) ((x) << S_ECCCHKEN)
-#define F_ECCCHKEN    V_ECCCHKEN(1U)
-
-#define S_ECCGENEN    0
-#define V_ECCGENEN(x) ((x) << S_ECCGENEN)
-#define F_ECCGENEN    V_ECCGENEN(1U)
-
-#define A_MC7_CE_ADDR 0x134
-
-#define A_MC7_CE_DATA0 0x138
-
-#define A_MC7_CE_DATA1 0x13c
-
-#define A_MC7_CE_DATA2 0x140
-
-#define S_DATA    0
-#define M_DATA    0xff
-
-#define G_DATA(x) (((x) >> S_DATA) & M_DATA)
-
-#define A_MC7_UE_ADDR 0x144
-
-#define A_MC7_UE_DATA0 0x148
-
-#define A_MC7_UE_DATA1 0x14c
-
-#define A_MC7_UE_DATA2 0x150
-
-#define A_MC7_BD_ADDR 0x154
-
-#define S_ADDR    3
-
-#define M_ADDR    0x1fffffff
-
-#define A_MC7_BD_DATA0 0x158
-
-#define A_MC7_BD_DATA1 0x15c
-
-#define A_MC7_BD_OP 0x164
-
-#define S_OP    0
-
-#define V_OP(x) ((x) << S_OP)
-#define F_OP    V_OP(1U)
-
-#define F_OP    V_OP(1U)
-#define A_SF_OP 0x6dc
-
-#define A_MC7_BIST_ADDR_BEG 0x168
-
-#define A_MC7_BIST_ADDR_END 0x16c
-
-#define A_MC7_BIST_DATA 0x170
-
-#define A_MC7_BIST_OP 0x174
-
-#define S_CONT    3
-#define V_CONT(x) ((x) << S_CONT)
-#define F_CONT    V_CONT(1U)
-
-#define F_CONT    V_CONT(1U)
-
-#define A_MC7_INT_ENABLE 0x178
-
-#define S_AE    17
-#define V_AE(x) ((x) << S_AE)
-#define F_AE    V_AE(1U)
-
-#define S_PE    2
-#define M_PE    0x7fff
-
-#define V_PE(x) ((x) << S_PE)
-
-#define G_PE(x) (((x) >> S_PE) & M_PE)
-
-#define S_UE    1
-#define V_UE(x) ((x) << S_UE)
-#define F_UE    V_UE(1U)
-
-#define S_CE    0
-#define V_CE(x) ((x) << S_CE)
-#define F_CE    V_CE(1U)
-
-#define A_MC7_INT_CAUSE 0x17c
-
-#define MC7_PMTX_BASE_ADDR 0x180
-
-#define MC7_CM_BASE_ADDR 0x200
-
-#define A_CIM_BOOT_CFG 0x280
-
-#define S_BOOTADDR    2
-#define M_BOOTADDR    0x3fffffff
-#define V_BOOTADDR(x) ((x) << S_BOOTADDR)
-
-#define A_CIM_SDRAM_BASE_ADDR 0x28c
-
-#define A_CIM_SDRAM_ADDR_SIZE 0x290
-
-#define A_CIM_HOST_INT_ENABLE 0x298
-
-#define S_DTAGPARERR    28
-#define V_DTAGPARERR(x) ((x) << S_DTAGPARERR)
-#define F_DTAGPARERR    V_DTAGPARERR(1U)
-
-#define S_ITAGPARERR    27
-#define V_ITAGPARERR(x) ((x) << S_ITAGPARERR)
-#define F_ITAGPARERR    V_ITAGPARERR(1U)
-
-#define S_IBQTPPARERR    26
-#define V_IBQTPPARERR(x) ((x) << S_IBQTPPARERR)
-#define F_IBQTPPARERR    V_IBQTPPARERR(1U)
-
-#define S_IBQULPPARERR    25
-#define V_IBQULPPARERR(x) ((x) << S_IBQULPPARERR)
-#define F_IBQULPPARERR    V_IBQULPPARERR(1U)
-
-#define S_IBQSGEHIPARERR    24
-#define V_IBQSGEHIPARERR(x) ((x) << S_IBQSGEHIPARERR)
-#define F_IBQSGEHIPARERR    V_IBQSGEHIPARERR(1U)
-
-#define S_IBQSGELOPARERR    23
-#define V_IBQSGELOPARERR(x) ((x) << S_IBQSGELOPARERR)
-#define F_IBQSGELOPARERR    V_IBQSGELOPARERR(1U)
-
-#define S_OBQULPLOPARERR    22
-#define V_OBQULPLOPARERR(x) ((x) << S_OBQULPLOPARERR)
-#define F_OBQULPLOPARERR    V_OBQULPLOPARERR(1U)
-
-#define S_OBQULPHIPARERR    21
-#define V_OBQULPHIPARERR(x) ((x) << S_OBQULPHIPARERR)
-#define F_OBQULPHIPARERR    V_OBQULPHIPARERR(1U)
-
-#define S_OBQSGEPARERR    20
-#define V_OBQSGEPARERR(x) ((x) << S_OBQSGEPARERR)
-#define F_OBQSGEPARERR    V_OBQSGEPARERR(1U)
-
-#define S_DCACHEPARERR    19
-#define V_DCACHEPARERR(x) ((x) << S_DCACHEPARERR)
-#define F_DCACHEPARERR    V_DCACHEPARERR(1U)
-
-#define S_ICACHEPARERR    18
-#define V_ICACHEPARERR(x) ((x) << S_ICACHEPARERR)
-#define F_ICACHEPARERR    V_ICACHEPARERR(1U)
-
-#define S_DRAMPARERR    17
-#define V_DRAMPARERR(x) ((x) << S_DRAMPARERR)
-#define F_DRAMPARERR    V_DRAMPARERR(1U)
-
-#define A_CIM_HOST_INT_CAUSE 0x29c
-
-#define S_BLKWRPLINT    12
-#define V_BLKWRPLINT(x) ((x) << S_BLKWRPLINT)
-#define F_BLKWRPLINT    V_BLKWRPLINT(1U)
-
-#define S_BLKRDPLINT    11
-#define V_BLKRDPLINT(x) ((x) << S_BLKRDPLINT)
-#define F_BLKRDPLINT    V_BLKRDPLINT(1U)
-
-#define S_BLKWRCTLINT    10
-#define V_BLKWRCTLINT(x) ((x) << S_BLKWRCTLINT)
-#define F_BLKWRCTLINT    V_BLKWRCTLINT(1U)
-
-#define S_BLKRDCTLINT    9
-#define V_BLKRDCTLINT(x) ((x) << S_BLKRDCTLINT)
-#define F_BLKRDCTLINT    V_BLKRDCTLINT(1U)
-
-#define S_BLKWRFLASHINT    8
-#define V_BLKWRFLASHINT(x) ((x) << S_BLKWRFLASHINT)
-#define F_BLKWRFLASHINT    V_BLKWRFLASHINT(1U)
-
-#define S_BLKRDFLASHINT    7
-#define V_BLKRDFLASHINT(x) ((x) << S_BLKRDFLASHINT)
-#define F_BLKRDFLASHINT    V_BLKRDFLASHINT(1U)
-
-#define S_SGLWRFLASHINT    6
-#define V_SGLWRFLASHINT(x) ((x) << S_SGLWRFLASHINT)
-#define F_SGLWRFLASHINT    V_SGLWRFLASHINT(1U)
-
-#define S_WRBLKFLASHINT    5
-#define V_WRBLKFLASHINT(x) ((x) << S_WRBLKFLASHINT)
-#define F_WRBLKFLASHINT    V_WRBLKFLASHINT(1U)
-
-#define S_BLKWRBOOTINT    4
-#define V_BLKWRBOOTINT(x) ((x) << S_BLKWRBOOTINT)
-#define F_BLKWRBOOTINT    V_BLKWRBOOTINT(1U)
-
-#define S_FLASHRANGEINT    2
-#define V_FLASHRANGEINT(x) ((x) << S_FLASHRANGEINT)
-#define F_FLASHRANGEINT    V_FLASHRANGEINT(1U)
-
-#define S_SDRAMRANGEINT    1
-#define V_SDRAMRANGEINT(x) ((x) << S_SDRAMRANGEINT)
-#define F_SDRAMRANGEINT    V_SDRAMRANGEINT(1U)
-
-#define S_RSVDSPACEINT    0
-#define V_RSVDSPACEINT(x) ((x) << S_RSVDSPACEINT)
-#define F_RSVDSPACEINT    V_RSVDSPACEINT(1U)
-
-#define A_CIM_HOST_ACC_CTRL 0x2b0
-
-#define S_HOSTBUSY    17
-#define V_HOSTBUSY(x) ((x) << S_HOSTBUSY)
-#define F_HOSTBUSY    V_HOSTBUSY(1U)
-
-#define A_CIM_HOST_ACC_DATA 0x2b4
-
-#define A_CIM_IBQ_DBG_CFG 0x2c0
-
-#define S_IBQDBGADDR    16
-#define M_IBQDBGADDR    0x1ff
-#define V_IBQDBGADDR(x) ((x) << S_IBQDBGADDR)
-#define G_IBQDBGADDR(x) (((x) >> S_IBQDBGADDR) & M_IBQDBGADDR)
-
-#define S_IBQDBGQID    3
-#define M_IBQDBGQID    0x3
-#define V_IBQDBGQID(x) ((x) << S_IBQDBGQID)
-#define G_IBQDBGQID(x) (((x) >> S_IBQDBGQID) & M_IBQDBGQID)
-
-#define S_IBQDBGWR    2
-#define V_IBQDBGWR(x) ((x) << S_IBQDBGWR)
-#define F_IBQDBGWR    V_IBQDBGWR(1U)
-
-#define S_IBQDBGBUSY    1
-#define V_IBQDBGBUSY(x) ((x) << S_IBQDBGBUSY)
-#define F_IBQDBGBUSY    V_IBQDBGBUSY(1U)
-
-#define S_IBQDBGEN    0
-#define V_IBQDBGEN(x) ((x) << S_IBQDBGEN)
-#define F_IBQDBGEN    V_IBQDBGEN(1U)
-
-#define A_CIM_IBQ_DBG_DATA 0x2c8
-
-#define A_TP_IN_CONFIG 0x300
-
-#define S_RXFBARBPRIO    25
-#define V_RXFBARBPRIO(x) ((x) << S_RXFBARBPRIO)
-#define F_RXFBARBPRIO    V_RXFBARBPRIO(1U)
-
-#define S_TXFBARBPRIO    24
-#define V_TXFBARBPRIO(x) ((x) << S_TXFBARBPRIO)
-#define F_TXFBARBPRIO    V_TXFBARBPRIO(1U)
-
-#define S_NICMODE    14
-#define V_NICMODE(x) ((x) << S_NICMODE)
-#define F_NICMODE    V_NICMODE(1U)
-
-#define F_NICMODE    V_NICMODE(1U)
-
-#define S_IPV6ENABLE    15
-#define V_IPV6ENABLE(x) ((x) << S_IPV6ENABLE)
-#define F_IPV6ENABLE    V_IPV6ENABLE(1U)
-
-#define A_TP_OUT_CONFIG 0x304
-
-#define S_VLANEXTRACTIONENABLE    12
-
-#define A_TP_GLOBAL_CONFIG 0x308
-
-#define S_TXPACINGENABLE    24
-#define V_TXPACINGENABLE(x) ((x) << S_TXPACINGENABLE)
-#define F_TXPACINGENABLE    V_TXPACINGENABLE(1U)
-
-#define S_PATHMTU    15
-#define V_PATHMTU(x) ((x) << S_PATHMTU)
-#define F_PATHMTU    V_PATHMTU(1U)
-
-#define S_IPCHECKSUMOFFLOAD    13
-#define V_IPCHECKSUMOFFLOAD(x) ((x) << S_IPCHECKSUMOFFLOAD)
-#define F_IPCHECKSUMOFFLOAD    V_IPCHECKSUMOFFLOAD(1U)
-
-#define S_UDPCHECKSUMOFFLOAD    12
-#define V_UDPCHECKSUMOFFLOAD(x) ((x) << S_UDPCHECKSUMOFFLOAD)
-#define F_UDPCHECKSUMOFFLOAD    V_UDPCHECKSUMOFFLOAD(1U)
-
-#define S_TCPCHECKSUMOFFLOAD    11
-#define V_TCPCHECKSUMOFFLOAD(x) ((x) << S_TCPCHECKSUMOFFLOAD)
-#define F_TCPCHECKSUMOFFLOAD    V_TCPCHECKSUMOFFLOAD(1U)
-
-#define S_IPTTL    0
-#define M_IPTTL    0xff
-#define V_IPTTL(x) ((x) << S_IPTTL)
-
-#define A_TP_CMM_MM_BASE 0x314
-
-#define A_TP_CMM_TIMER_BASE 0x318
-
-#define S_CMTIMERMAXNUM    28
-#define M_CMTIMERMAXNUM    0x3
-#define V_CMTIMERMAXNUM(x) ((x) << S_CMTIMERMAXNUM)
-
-#define A_TP_PMM_SIZE 0x31c
-
-#define A_TP_PMM_TX_BASE 0x320
-
-#define A_TP_PMM_RX_BASE 0x328
-
-#define A_TP_PMM_RX_PAGE_SIZE 0x32c
-
-#define A_TP_PMM_RX_MAX_PAGE 0x330
-
-#define A_TP_PMM_TX_PAGE_SIZE 0x334
-
-#define A_TP_PMM_TX_MAX_PAGE 0x338
-
-#define A_TP_TCP_OPTIONS 0x340
-
-#define S_MTUDEFAULT    16
-#define M_MTUDEFAULT    0xffff
-#define V_MTUDEFAULT(x) ((x) << S_MTUDEFAULT)
-
-#define S_MTUENABLE    10
-#define V_MTUENABLE(x) ((x) << S_MTUENABLE)
-#define F_MTUENABLE    V_MTUENABLE(1U)
-
-#define S_SACKRX    8
-#define V_SACKRX(x) ((x) << S_SACKRX)
-#define F_SACKRX    V_SACKRX(1U)
-
-#define S_SACKMODE    4
-
-#define M_SACKMODE    0x3
-
-#define V_SACKMODE(x) ((x) << S_SACKMODE)
-
-#define S_WINDOWSCALEMODE    2
-#define M_WINDOWSCALEMODE    0x3
-#define V_WINDOWSCALEMODE(x) ((x) << S_WINDOWSCALEMODE)
-
-#define S_TIMESTAMPSMODE    0
-
-#define M_TIMESTAMPSMODE    0x3
-
-#define V_TIMESTAMPSMODE(x) ((x) << S_TIMESTAMPSMODE)
-
-#define A_TP_DACK_CONFIG 0x344
-
-#define S_AUTOSTATE3    30
-#define M_AUTOSTATE3    0x3
-#define V_AUTOSTATE3(x) ((x) << S_AUTOSTATE3)
-
-#define S_AUTOSTATE2    28
-#define M_AUTOSTATE2    0x3
-#define V_AUTOSTATE2(x) ((x) << S_AUTOSTATE2)
-
-#define S_AUTOSTATE1    26
-#define M_AUTOSTATE1    0x3
-#define V_AUTOSTATE1(x) ((x) << S_AUTOSTATE1)
-
-#define S_BYTETHRESHOLD    5
-#define M_BYTETHRESHOLD    0xfffff
-#define V_BYTETHRESHOLD(x) ((x) << S_BYTETHRESHOLD)
-
-#define S_MSSTHRESHOLD    3
-#define M_MSSTHRESHOLD    0x3
-#define V_MSSTHRESHOLD(x) ((x) << S_MSSTHRESHOLD)
-
-#define S_AUTOCAREFUL    2
-#define V_AUTOCAREFUL(x) ((x) << S_AUTOCAREFUL)
-#define F_AUTOCAREFUL    V_AUTOCAREFUL(1U)
-
-#define S_AUTOENABLE    1
-#define V_AUTOENABLE(x) ((x) << S_AUTOENABLE)
-#define F_AUTOENABLE    V_AUTOENABLE(1U)
-
-#define S_DACK_MODE    0
-#define V_DACK_MODE(x) ((x) << S_DACK_MODE)
-#define F_DACK_MODE    V_DACK_MODE(1U)
-
-#define A_TP_PC_CONFIG 0x348
-
-#define S_TXTOSQUEUEMAPMODE    26
-#define V_TXTOSQUEUEMAPMODE(x) ((x) << S_TXTOSQUEUEMAPMODE)
-#define F_TXTOSQUEUEMAPMODE    V_TXTOSQUEUEMAPMODE(1U)
-
-#define S_ENABLEEPCMDAFULL    23
-#define V_ENABLEEPCMDAFULL(x) ((x) << S_ENABLEEPCMDAFULL)
-#define F_ENABLEEPCMDAFULL    V_ENABLEEPCMDAFULL(1U)
-
-#define S_MODULATEUNIONMODE    22
-#define V_MODULATEUNIONMODE(x) ((x) << S_MODULATEUNIONMODE)
-#define F_MODULATEUNIONMODE    V_MODULATEUNIONMODE(1U)
-
-#define S_TXDEFERENABLE    20
-#define V_TXDEFERENABLE(x) ((x) << S_TXDEFERENABLE)
-#define F_TXDEFERENABLE    V_TXDEFERENABLE(1U)
-
-#define S_RXCONGESTIONMODE    19
-#define V_RXCONGESTIONMODE(x) ((x) << S_RXCONGESTIONMODE)
-#define F_RXCONGESTIONMODE    V_RXCONGESTIONMODE(1U)
-
-#define S_HEARBEATDACK    16
-#define V_HEARBEATDACK(x) ((x) << S_HEARBEATDACK)
-#define F_HEARBEATDACK    V_HEARBEATDACK(1U)
-
-#define S_TXCONGESTIONMODE    15
-#define V_TXCONGESTIONMODE(x) ((x) << S_TXCONGESTIONMODE)
-#define F_TXCONGESTIONMODE    V_TXCONGESTIONMODE(1U)
-
-#define S_ENABLEOCSPIFULL    30
-#define V_ENABLEOCSPIFULL(x) ((x) << S_ENABLEOCSPIFULL)
-#define F_ENABLEOCSPIFULL    V_ENABLEOCSPIFULL(1U)
-
-#define S_LOCKTID    28
-#define V_LOCKTID(x) ((x) << S_LOCKTID)
-#define F_LOCKTID    V_LOCKTID(1U)
-
-#define S_TABLELATENCYDELTA    0
-#define M_TABLELATENCYDELTA    0xf
-#define V_TABLELATENCYDELTA(x) ((x) << S_TABLELATENCYDELTA)
-#define G_TABLELATENCYDELTA(x) \
-	(((x) >> S_TABLELATENCYDELTA) & M_TABLELATENCYDELTA)
-
-#define A_TP_PC_CONFIG2 0x34c
-
-#define S_DISBLEDAPARBIT0    15
-#define V_DISBLEDAPARBIT0(x) ((x) << S_DISBLEDAPARBIT0)
-#define F_DISBLEDAPARBIT0    V_DISBLEDAPARBIT0(1U)
-
-#define S_ENABLEARPMISS    13
-#define V_ENABLEARPMISS(x) ((x) << S_ENABLEARPMISS)
-#define F_ENABLEARPMISS    V_ENABLEARPMISS(1U)
-
-#define S_ENABLENONOFDTNLSYN    12
-#define V_ENABLENONOFDTNLSYN(x) ((x) << S_ENABLENONOFDTNLSYN)
-#define F_ENABLENONOFDTNLSYN    V_ENABLENONOFDTNLSYN(1U)
-
-#define S_ENABLEIPV6RSS    11
-#define V_ENABLEIPV6RSS(x) ((x) << S_ENABLEIPV6RSS)
-#define F_ENABLEIPV6RSS    V_ENABLEIPV6RSS(1U)
-
-#define S_CHDRAFULL    4
-#define V_CHDRAFULL(x) ((x) << S_CHDRAFULL)
-#define F_CHDRAFULL    V_CHDRAFULL(1U)
-
-#define A_TP_TCP_BACKOFF_REG0 0x350
-
-#define A_TP_TCP_BACKOFF_REG1 0x354
-
-#define A_TP_TCP_BACKOFF_REG2 0x358
-
-#define A_TP_TCP_BACKOFF_REG3 0x35c
-
-#define A_TP_PARA_REG2 0x368
-
-#define S_MAXRXDATA    16
-#define M_MAXRXDATA    0xffff
-#define V_MAXRXDATA(x) ((x) << S_MAXRXDATA)
-
-#define S_RXCOALESCESIZE    0
-#define M_RXCOALESCESIZE    0xffff
-#define V_RXCOALESCESIZE(x) ((x) << S_RXCOALESCESIZE)
-
-#define A_TP_PARA_REG3 0x36c
-
-#define S_TXDATAACKIDX    16
-#define M_TXDATAACKIDX    0xf
-
-#define V_TXDATAACKIDX(x) ((x) << S_TXDATAACKIDX)
-
-#define S_TXPACEAUTOSTRICT    10
-#define V_TXPACEAUTOSTRICT(x) ((x) << S_TXPACEAUTOSTRICT)
-#define F_TXPACEAUTOSTRICT    V_TXPACEAUTOSTRICT(1U)
-
-#define S_TXPACEFIXED    9
-#define V_TXPACEFIXED(x) ((x) << S_TXPACEFIXED)
-#define F_TXPACEFIXED    V_TXPACEFIXED(1U)
-
-#define S_TXPACEAUTO    8
-#define V_TXPACEAUTO(x) ((x) << S_TXPACEAUTO)
-#define F_TXPACEAUTO    V_TXPACEAUTO(1U)
-
-#define S_RXCOALESCEENABLE    1
-#define V_RXCOALESCEENABLE(x) ((x) << S_RXCOALESCEENABLE)
-#define F_RXCOALESCEENABLE    V_RXCOALESCEENABLE(1U)
-
-#define S_RXCOALESCEPSHEN    0
-#define V_RXCOALESCEPSHEN(x) ((x) << S_RXCOALESCEPSHEN)
-#define F_RXCOALESCEPSHEN    V_RXCOALESCEPSHEN(1U)
-
-#define A_TP_PARA_REG4 0x370
-
-#define A_TP_PARA_REG5 0x374
-
-#define S_RXDDPOFFINIT    3
-#define V_RXDDPOFFINIT(x) ((x) << S_RXDDPOFFINIT)
-#define F_RXDDPOFFINIT    V_RXDDPOFFINIT(1U)
-
-#define A_TP_PARA_REG6 0x378
-
-#define S_T3A_ENABLEESND    13
-#define V_T3A_ENABLEESND(x) ((x) << S_T3A_ENABLEESND)
-#define F_T3A_ENABLEESND    V_T3A_ENABLEESND(1U)
-
-#define S_ENABLEESND    11
-#define V_ENABLEESND(x) ((x) << S_ENABLEESND)
-#define F_ENABLEESND    V_ENABLEESND(1U)
-
-#define A_TP_PARA_REG7 0x37c
-
-#define S_PMMAXXFERLEN1    16
-#define M_PMMAXXFERLEN1    0xffff
-#define V_PMMAXXFERLEN1(x) ((x) << S_PMMAXXFERLEN1)
-
-#define S_PMMAXXFERLEN0    0
-#define M_PMMAXXFERLEN0    0xffff
-#define V_PMMAXXFERLEN0(x) ((x) << S_PMMAXXFERLEN0)
-
-#define A_TP_TIMER_RESOLUTION 0x390
-
-#define S_TIMERRESOLUTION    16
-#define M_TIMERRESOLUTION    0xff
-#define V_TIMERRESOLUTION(x) ((x) << S_TIMERRESOLUTION)
-
-#define S_TIMESTAMPRESOLUTION    8
-#define M_TIMESTAMPRESOLUTION    0xff
-#define V_TIMESTAMPRESOLUTION(x) ((x) << S_TIMESTAMPRESOLUTION)
-
-#define S_DELAYEDACKRESOLUTION    0
-#define M_DELAYEDACKRESOLUTION    0xff
-#define V_DELAYEDACKRESOLUTION(x) ((x) << S_DELAYEDACKRESOLUTION)
-
-#define A_TP_MSL 0x394
-
-#define A_TP_RXT_MIN 0x398
-
-#define A_TP_RXT_MAX 0x39c
-
-#define A_TP_PERS_MIN 0x3a0
-
-#define A_TP_PERS_MAX 0x3a4
-
-#define A_TP_KEEP_IDLE 0x3a8
-
-#define A_TP_KEEP_INTVL 0x3ac
-
-#define A_TP_INIT_SRTT 0x3b0
-
-#define A_TP_DACK_TIMER 0x3b4
-
-#define A_TP_FINWAIT2_TIMER 0x3b8
-
-#define A_TP_SHIFT_CNT 0x3c0
-
-#define S_SYNSHIFTMAX    24
-
-#define M_SYNSHIFTMAX    0xff
-
-#define V_SYNSHIFTMAX(x) ((x) << S_SYNSHIFTMAX)
-
-#define S_RXTSHIFTMAXR1    20
-
-#define M_RXTSHIFTMAXR1    0xf
-
-#define V_RXTSHIFTMAXR1(x) ((x) << S_RXTSHIFTMAXR1)
-
-#define S_RXTSHIFTMAXR2    16
-
-#define M_RXTSHIFTMAXR2    0xf
-
-#define V_RXTSHIFTMAXR2(x) ((x) << S_RXTSHIFTMAXR2)
-
-#define S_PERSHIFTBACKOFFMAX    12
-#define M_PERSHIFTBACKOFFMAX    0xf
-#define V_PERSHIFTBACKOFFMAX(x) ((x) << S_PERSHIFTBACKOFFMAX)
-
-#define S_PERSHIFTMAX    8
-#define M_PERSHIFTMAX    0xf
-#define V_PERSHIFTMAX(x) ((x) << S_PERSHIFTMAX)
-
-#define S_KEEPALIVEMAX    0
-
-#define M_KEEPALIVEMAX    0xff
-
-#define V_KEEPALIVEMAX(x) ((x) << S_KEEPALIVEMAX)
-
-#define A_TP_MTU_PORT_TABLE 0x3d0
-
-#define A_TP_CCTRL_TABLE 0x3dc
-
-#define A_TP_MTU_TABLE 0x3e4
-
-#define A_TP_RSS_MAP_TABLE 0x3e8
-
-#define A_TP_RSS_LKP_TABLE 0x3ec
-
-#define A_TP_RSS_CONFIG 0x3f0
-
-#define S_TNL4TUPEN    29
-#define V_TNL4TUPEN(x) ((x) << S_TNL4TUPEN)
-#define F_TNL4TUPEN    V_TNL4TUPEN(1U)
-
-#define S_TNL2TUPEN    28
-#define V_TNL2TUPEN(x) ((x) << S_TNL2TUPEN)
-#define F_TNL2TUPEN    V_TNL2TUPEN(1U)
-
-#define S_TNLPRTEN    26
-#define V_TNLPRTEN(x) ((x) << S_TNLPRTEN)
-#define F_TNLPRTEN    V_TNLPRTEN(1U)
-
-#define S_TNLMAPEN    25
-#define V_TNLMAPEN(x) ((x) << S_TNLMAPEN)
-#define F_TNLMAPEN    V_TNLMAPEN(1U)
-
-#define S_TNLLKPEN    24
-#define V_TNLLKPEN(x) ((x) << S_TNLLKPEN)
-#define F_TNLLKPEN    V_TNLLKPEN(1U)
-
-#define S_RRCPLMAPEN    7
-#define V_RRCPLMAPEN(x) ((x) << S_RRCPLMAPEN)
-#define F_RRCPLMAPEN    V_RRCPLMAPEN(1U)
-
-#define S_RRCPLCPUSIZE    4
-#define M_RRCPLCPUSIZE    0x7
-#define V_RRCPLCPUSIZE(x) ((x) << S_RRCPLCPUSIZE)
-
-#define S_RQFEEDBACKENABLE    3
-#define V_RQFEEDBACKENABLE(x) ((x) << S_RQFEEDBACKENABLE)
-#define F_RQFEEDBACKENABLE    V_RQFEEDBACKENABLE(1U)
-
-#define S_HASHTOEPLITZ    2
-#define V_HASHTOEPLITZ(x) ((x) << S_HASHTOEPLITZ)
-#define F_HASHTOEPLITZ    V_HASHTOEPLITZ(1U)
-
-#define S_DISABLE    0
-
-#define A_TP_TM_PIO_ADDR 0x418
-
-#define A_TP_TM_PIO_DATA 0x41c
-
-#define A_TP_TX_MOD_QUE_TABLE 0x420
-
-#define A_TP_TX_RESOURCE_LIMIT 0x424
-
-#define A_TP_TX_MOD_QUEUE_REQ_MAP 0x428
-
-#define S_TX_MOD_QUEUE_REQ_MAP    0
-#define M_TX_MOD_QUEUE_REQ_MAP    0xff
-#define V_TX_MOD_QUEUE_REQ_MAP(x) ((x) << S_TX_MOD_QUEUE_REQ_MAP)
-
-#define A_TP_TX_MOD_QUEUE_WEIGHT1 0x42c
-
-#define A_TP_TX_MOD_QUEUE_WEIGHT0 0x430
-
-#define A_TP_MOD_CHANNEL_WEIGHT 0x434
-
-#define A_TP_MOD_RATE_LIMIT 0x438
-
-#define A_TP_PIO_ADDR 0x440
-
-#define A_TP_PIO_DATA 0x444
-
-#define A_TP_RESET 0x44c
-
-#define S_FLSTINITENABLE    1
-#define V_FLSTINITENABLE(x) ((x) << S_FLSTINITENABLE)
-#define F_FLSTINITENABLE    V_FLSTINITENABLE(1U)
-
-#define S_TPRESET    0
-#define V_TPRESET(x) ((x) << S_TPRESET)
-#define F_TPRESET    V_TPRESET(1U)
-
-#define A_TP_CMM_MM_RX_FLST_BASE 0x460
-
-#define A_TP_CMM_MM_TX_FLST_BASE 0x464
-
-#define A_TP_CMM_MM_PS_FLST_BASE 0x468
-
-#define A_TP_MIB_INDEX 0x450
-
-#define A_TP_MIB_RDATA 0x454
-
-#define A_TP_CMM_MM_MAX_PSTRUCT 0x46c
-
-#define A_TP_INT_ENABLE 0x470
-
-#define S_FLMTXFLSTEMPTY    30
-#define V_FLMTXFLSTEMPTY(x) ((x) << S_FLMTXFLSTEMPTY)
-#define F_FLMTXFLSTEMPTY    V_FLMTXFLSTEMPTY(1U)
-
-#define S_FLMRXFLSTEMPTY    29
-#define V_FLMRXFLSTEMPTY(x) ((x) << S_FLMRXFLSTEMPTY)
-#define F_FLMRXFLSTEMPTY    V_FLMRXFLSTEMPTY(1U)
-
-#define S_ARPLUTPERR    26
-#define V_ARPLUTPERR(x) ((x) << S_ARPLUTPERR)
-#define F_ARPLUTPERR    V_ARPLUTPERR(1U)
-
-#define S_CMCACHEPERR    24
-#define V_CMCACHEPERR(x) ((x) << S_CMCACHEPERR)
-#define F_CMCACHEPERR    V_CMCACHEPERR(1U)
-
-#define A_TP_INT_CAUSE 0x474
-
-#define A_TP_TX_MOD_Q1_Q0_RATE_LIMIT 0x8
-
-#define A_TP_TX_DROP_CFG_CH0 0x12b
-
-#define A_TP_TX_DROP_MODE 0x12f
-
-#define A_TP_EGRESS_CONFIG 0x145
-
-#define S_REWRITEFORCETOSIZE    0
-#define V_REWRITEFORCETOSIZE(x) ((x) << S_REWRITEFORCETOSIZE)
-#define F_REWRITEFORCETOSIZE    V_REWRITEFORCETOSIZE(1U)
-
-#define A_TP_TX_TRC_KEY0 0x20
-
-#define A_TP_RX_TRC_KEY0 0x120
-
-#define A_TP_TX_DROP_CNT_CH0 0x12d
-
-#define S_TXDROPCNTCH0RCVD    0
-#define M_TXDROPCNTCH0RCVD    0xffff
-#define V_TXDROPCNTCH0RCVD(x) ((x) << S_TXDROPCNTCH0RCVD)
-#define G_TXDROPCNTCH0RCVD(x) (((x) >> S_TXDROPCNTCH0RCVD) & \
-			       M_TXDROPCNTCH0RCVD)
-
-#define A_TP_PROXY_FLOW_CNTL 0x4b0
-
-#define A_TP_EMBED_OP_FIELD0 0x4e8
-#define A_TP_EMBED_OP_FIELD1 0x4ec
-#define A_TP_EMBED_OP_FIELD2 0x4f0
-#define A_TP_EMBED_OP_FIELD3 0x4f4
-#define A_TP_EMBED_OP_FIELD4 0x4f8
-#define A_TP_EMBED_OP_FIELD5 0x4fc
-
-#define A_ULPRX_CTL 0x500
-
-#define S_ROUND_ROBIN    4
-#define V_ROUND_ROBIN(x) ((x) << S_ROUND_ROBIN)
-#define F_ROUND_ROBIN    V_ROUND_ROBIN(1U)
-
-#define A_ULPRX_INT_ENABLE 0x504
-
-#define S_DATASELFRAMEERR0    7
-#define V_DATASELFRAMEERR0(x) ((x) << S_DATASELFRAMEERR0)
-#define F_DATASELFRAMEERR0    V_DATASELFRAMEERR0(1U)
-
-#define S_DATASELFRAMEERR1    6
-#define V_DATASELFRAMEERR1(x) ((x) << S_DATASELFRAMEERR1)
-#define F_DATASELFRAMEERR1    V_DATASELFRAMEERR1(1U)
-
-#define S_PCMDMUXPERR    5
-#define V_PCMDMUXPERR(x) ((x) << S_PCMDMUXPERR)
-#define F_PCMDMUXPERR    V_PCMDMUXPERR(1U)
-
-#define S_ARBFPERR    4
-#define V_ARBFPERR(x) ((x) << S_ARBFPERR)
-#define F_ARBFPERR    V_ARBFPERR(1U)
-
-#define S_ARBPF0PERR    3
-#define V_ARBPF0PERR(x) ((x) << S_ARBPF0PERR)
-#define F_ARBPF0PERR    V_ARBPF0PERR(1U)
-
-#define S_ARBPF1PERR    2
-#define V_ARBPF1PERR(x) ((x) << S_ARBPF1PERR)
-#define F_ARBPF1PERR    V_ARBPF1PERR(1U)
-
-#define S_PARERRPCMD    1
-#define V_PARERRPCMD(x) ((x) << S_PARERRPCMD)
-#define F_PARERRPCMD    V_PARERRPCMD(1U)
-
-#define S_PARERRDATA    0
-#define V_PARERRDATA(x) ((x) << S_PARERRDATA)
-#define F_PARERRDATA    V_PARERRDATA(1U)
-
-#define A_ULPRX_INT_CAUSE 0x508
-
-#define A_ULPRX_ISCSI_LLIMIT 0x50c
-
-#define A_ULPRX_ISCSI_ULIMIT 0x510
-
-#define A_ULPRX_ISCSI_TAGMASK 0x514
-
-#define A_ULPRX_ISCSI_PSZ 0x518
-
-#define A_ULPRX_TDDP_LLIMIT 0x51c
-
-#define A_ULPRX_TDDP_ULIMIT 0x520
-#define A_ULPRX_TDDP_PSZ 0x528
-
-#define S_HPZ0    0
-#define M_HPZ0    0xf
-#define V_HPZ0(x) ((x) << S_HPZ0)
-#define G_HPZ0(x) (((x) >> S_HPZ0) & M_HPZ0)
-
-#define A_ULPRX_STAG_LLIMIT 0x52c
-
-#define A_ULPRX_STAG_ULIMIT 0x530
-
-#define A_ULPRX_RQ_LLIMIT 0x534
-#define A_ULPRX_RQ_LLIMIT 0x534
-
-#define A_ULPRX_RQ_ULIMIT 0x538
-#define A_ULPRX_RQ_ULIMIT 0x538
-
-#define A_ULPRX_PBL_LLIMIT 0x53c
-
-#define A_ULPRX_PBL_ULIMIT 0x540
-#define A_ULPRX_PBL_ULIMIT 0x540
-
-#define A_ULPRX_TDDP_TAGMASK 0x524
-
-#define A_ULPRX_RQ_LLIMIT 0x534
-#define A_ULPRX_RQ_LLIMIT 0x534
-
-#define A_ULPRX_RQ_ULIMIT 0x538
-#define A_ULPRX_RQ_ULIMIT 0x538
-
-#define A_ULPRX_PBL_ULIMIT 0x540
-#define A_ULPRX_PBL_ULIMIT 0x540
-
-#define A_ULPTX_CONFIG 0x580
-
-#define S_CFG_CQE_SOP_MASK    1
-#define V_CFG_CQE_SOP_MASK(x) ((x) << S_CFG_CQE_SOP_MASK)
-#define F_CFG_CQE_SOP_MASK    V_CFG_CQE_SOP_MASK(1U)
-
-#define S_CFG_RR_ARB    0
-#define V_CFG_RR_ARB(x) ((x) << S_CFG_RR_ARB)
-#define F_CFG_RR_ARB    V_CFG_RR_ARB(1U)
-
-#define A_ULPTX_INT_ENABLE 0x584
-
-#define S_PBL_BOUND_ERR_CH1    1
-#define V_PBL_BOUND_ERR_CH1(x) ((x) << S_PBL_BOUND_ERR_CH1)
-#define F_PBL_BOUND_ERR_CH1    V_PBL_BOUND_ERR_CH1(1U)
-
-#define S_PBL_BOUND_ERR_CH0    0
-#define V_PBL_BOUND_ERR_CH0(x) ((x) << S_PBL_BOUND_ERR_CH0)
-#define F_PBL_BOUND_ERR_CH0    V_PBL_BOUND_ERR_CH0(1U)
-
-#define A_ULPTX_INT_CAUSE 0x588
-
-#define A_ULPTX_TPT_LLIMIT 0x58c
-
-#define A_ULPTX_TPT_ULIMIT 0x590
-
-#define A_ULPTX_PBL_LLIMIT 0x594
-
-#define A_ULPTX_PBL_ULIMIT 0x598
-
-#define A_ULPTX_DMA_WEIGHT 0x5ac
-
-#define S_D1_WEIGHT    16
-#define M_D1_WEIGHT    0xffff
-#define V_D1_WEIGHT(x) ((x) << S_D1_WEIGHT)
-
-#define S_D0_WEIGHT    0
-#define M_D0_WEIGHT    0xffff
-#define V_D0_WEIGHT(x) ((x) << S_D0_WEIGHT)
-
-#define A_PM1_RX_CFG 0x5c0
-#define A_PM1_RX_MODE 0x5c4
-
-#define A_PM1_RX_INT_ENABLE 0x5d8
-
-#define S_ZERO_E_CMD_ERROR    18
-#define V_ZERO_E_CMD_ERROR(x) ((x) << S_ZERO_E_CMD_ERROR)
-#define F_ZERO_E_CMD_ERROR    V_ZERO_E_CMD_ERROR(1U)
-
-#define S_IESPI0_FIFO2X_RX_FRAMING_ERROR    17
-#define V_IESPI0_FIFO2X_RX_FRAMING_ERROR(x) ((x) << S_IESPI0_FIFO2X_RX_FRAMING_ERROR)
-#define F_IESPI0_FIFO2X_RX_FRAMING_ERROR    V_IESPI0_FIFO2X_RX_FRAMING_ERROR(1U)
-
-#define S_IESPI1_FIFO2X_RX_FRAMING_ERROR    16
-#define V_IESPI1_FIFO2X_RX_FRAMING_ERROR(x) ((x) << S_IESPI1_FIFO2X_RX_FRAMING_ERROR)
-#define F_IESPI1_FIFO2X_RX_FRAMING_ERROR    V_IESPI1_FIFO2X_RX_FRAMING_ERROR(1U)
-
-#define S_IESPI0_RX_FRAMING_ERROR    15
-#define V_IESPI0_RX_FRAMING_ERROR(x) ((x) << S_IESPI0_RX_FRAMING_ERROR)
-#define F_IESPI0_RX_FRAMING_ERROR    V_IESPI0_RX_FRAMING_ERROR(1U)
-
-#define S_IESPI1_RX_FRAMING_ERROR    14
-#define V_IESPI1_RX_FRAMING_ERROR(x) ((x) << S_IESPI1_RX_FRAMING_ERROR)
-#define F_IESPI1_RX_FRAMING_ERROR    V_IESPI1_RX_FRAMING_ERROR(1U)
-
-#define S_IESPI0_TX_FRAMING_ERROR    13
-#define V_IESPI0_TX_FRAMING_ERROR(x) ((x) << S_IESPI0_TX_FRAMING_ERROR)
-#define F_IESPI0_TX_FRAMING_ERROR    V_IESPI0_TX_FRAMING_ERROR(1U)
-
-#define S_IESPI1_TX_FRAMING_ERROR    12
-#define V_IESPI1_TX_FRAMING_ERROR(x) ((x) << S_IESPI1_TX_FRAMING_ERROR)
-#define F_IESPI1_TX_FRAMING_ERROR    V_IESPI1_TX_FRAMING_ERROR(1U)
-
-#define S_OCSPI0_RX_FRAMING_ERROR    11
-#define V_OCSPI0_RX_FRAMING_ERROR(x) ((x) << S_OCSPI0_RX_FRAMING_ERROR)
-#define F_OCSPI0_RX_FRAMING_ERROR    V_OCSPI0_RX_FRAMING_ERROR(1U)
-
-#define S_OCSPI1_RX_FRAMING_ERROR    10
-#define V_OCSPI1_RX_FRAMING_ERROR(x) ((x) << S_OCSPI1_RX_FRAMING_ERROR)
-#define F_OCSPI1_RX_FRAMING_ERROR    V_OCSPI1_RX_FRAMING_ERROR(1U)
-
-#define S_OCSPI0_TX_FRAMING_ERROR    9
-#define V_OCSPI0_TX_FRAMING_ERROR(x) ((x) << S_OCSPI0_TX_FRAMING_ERROR)
-#define F_OCSPI0_TX_FRAMING_ERROR    V_OCSPI0_TX_FRAMING_ERROR(1U)
-
-#define S_OCSPI1_TX_FRAMING_ERROR    8
-#define V_OCSPI1_TX_FRAMING_ERROR(x) ((x) << S_OCSPI1_TX_FRAMING_ERROR)
-#define F_OCSPI1_TX_FRAMING_ERROR    V_OCSPI1_TX_FRAMING_ERROR(1U)
-
-#define S_OCSPI0_OFIFO2X_TX_FRAMING_ERROR    7
-#define V_OCSPI0_OFIFO2X_TX_FRAMING_ERROR(x) ((x) << S_OCSPI0_OFIFO2X_TX_FRAMING_ERROR)
-#define F_OCSPI0_OFIFO2X_TX_FRAMING_ERROR    V_OCSPI0_OFIFO2X_TX_FRAMING_ERROR(1U)
-
-#define S_OCSPI1_OFIFO2X_TX_FRAMING_ERROR    6
-#define V_OCSPI1_OFIFO2X_TX_FRAMING_ERROR(x) ((x) << S_OCSPI1_OFIFO2X_TX_FRAMING_ERROR)
-#define F_OCSPI1_OFIFO2X_TX_FRAMING_ERROR    V_OCSPI1_OFIFO2X_TX_FRAMING_ERROR(1U)
-
-#define S_IESPI_PAR_ERROR    3
-#define M_IESPI_PAR_ERROR    0x7
-
-#define V_IESPI_PAR_ERROR(x) ((x) << S_IESPI_PAR_ERROR)
-
-#define S_OCSPI_PAR_ERROR    0
-#define M_OCSPI_PAR_ERROR    0x7
-
-#define V_OCSPI_PAR_ERROR(x) ((x) << S_OCSPI_PAR_ERROR)
-
-#define A_PM1_RX_INT_CAUSE 0x5dc
-
-#define A_PM1_TX_CFG 0x5e0
-#define A_PM1_TX_MODE 0x5e4
-
-#define A_PM1_TX_INT_ENABLE 0x5f8
-
-#define S_ZERO_C_CMD_ERROR    18
-#define V_ZERO_C_CMD_ERROR(x) ((x) << S_ZERO_C_CMD_ERROR)
-#define F_ZERO_C_CMD_ERROR    V_ZERO_C_CMD_ERROR(1U)
-
-#define S_ICSPI0_FIFO2X_RX_FRAMING_ERROR    17
-#define V_ICSPI0_FIFO2X_RX_FRAMING_ERROR(x) ((x) << S_ICSPI0_FIFO2X_RX_FRAMING_ERROR)
-#define F_ICSPI0_FIFO2X_RX_FRAMING_ERROR    V_ICSPI0_FIFO2X_RX_FRAMING_ERROR(1U)
-
-#define S_ICSPI1_FIFO2X_RX_FRAMING_ERROR    16
-#define V_ICSPI1_FIFO2X_RX_FRAMING_ERROR(x) ((x) << S_ICSPI1_FIFO2X_RX_FRAMING_ERROR)
-#define F_ICSPI1_FIFO2X_RX_FRAMING_ERROR    V_ICSPI1_FIFO2X_RX_FRAMING_ERROR(1U)
-
-#define S_ICSPI0_RX_FRAMING_ERROR    15
-#define V_ICSPI0_RX_FRAMING_ERROR(x) ((x) << S_ICSPI0_RX_FRAMING_ERROR)
-#define F_ICSPI0_RX_FRAMING_ERROR    V_ICSPI0_RX_FRAMING_ERROR(1U)
-
-#define S_ICSPI1_RX_FRAMING_ERROR    14
-#define V_ICSPI1_RX_FRAMING_ERROR(x) ((x) << S_ICSPI1_RX_FRAMING_ERROR)
-#define F_ICSPI1_RX_FRAMING_ERROR    V_ICSPI1_RX_FRAMING_ERROR(1U)
-
-#define S_ICSPI0_TX_FRAMING_ERROR    13
-#define V_ICSPI0_TX_FRAMING_ERROR(x) ((x) << S_ICSPI0_TX_FRAMING_ERROR)
-#define F_ICSPI0_TX_FRAMING_ERROR    V_ICSPI0_TX_FRAMING_ERROR(1U)
-
-#define S_ICSPI1_TX_FRAMING_ERROR    12
-#define V_ICSPI1_TX_FRAMING_ERROR(x) ((x) << S_ICSPI1_TX_FRAMING_ERROR)
-#define F_ICSPI1_TX_FRAMING_ERROR    V_ICSPI1_TX_FRAMING_ERROR(1U)
-
-#define S_OESPI0_RX_FRAMING_ERROR    11
-#define V_OESPI0_RX_FRAMING_ERROR(x) ((x) << S_OESPI0_RX_FRAMING_ERROR)
-#define F_OESPI0_RX_FRAMING_ERROR    V_OESPI0_RX_FRAMING_ERROR(1U)
-
-#define S_OESPI1_RX_FRAMING_ERROR    10
-#define V_OESPI1_RX_FRAMING_ERROR(x) ((x) << S_OESPI1_RX_FRAMING_ERROR)
-#define F_OESPI1_RX_FRAMING_ERROR    V_OESPI1_RX_FRAMING_ERROR(1U)
-
-#define S_OESPI0_TX_FRAMING_ERROR    9
-#define V_OESPI0_TX_FRAMING_ERROR(x) ((x) << S_OESPI0_TX_FRAMING_ERROR)
-#define F_OESPI0_TX_FRAMING_ERROR    V_OESPI0_TX_FRAMING_ERROR(1U)
-
-#define S_OESPI1_TX_FRAMING_ERROR    8
-#define V_OESPI1_TX_FRAMING_ERROR(x) ((x) << S_OESPI1_TX_FRAMING_ERROR)
-#define F_OESPI1_TX_FRAMING_ERROR    V_OESPI1_TX_FRAMING_ERROR(1U)
-
-#define S_OESPI0_OFIFO2X_TX_FRAMING_ERROR    7
-#define V_OESPI0_OFIFO2X_TX_FRAMING_ERROR(x) ((x) << S_OESPI0_OFIFO2X_TX_FRAMING_ERROR)
-#define F_OESPI0_OFIFO2X_TX_FRAMING_ERROR    V_OESPI0_OFIFO2X_TX_FRAMING_ERROR(1U)
-
-#define S_OESPI1_OFIFO2X_TX_FRAMING_ERROR    6
-#define V_OESPI1_OFIFO2X_TX_FRAMING_ERROR(x) ((x) << S_OESPI1_OFIFO2X_TX_FRAMING_ERROR)
-#define F_OESPI1_OFIFO2X_TX_FRAMING_ERROR    V_OESPI1_OFIFO2X_TX_FRAMING_ERROR(1U)
-
-#define S_ICSPI_PAR_ERROR    3
-#define M_ICSPI_PAR_ERROR    0x7
-
-#define V_ICSPI_PAR_ERROR(x) ((x) << S_ICSPI_PAR_ERROR)
-
-#define S_OESPI_PAR_ERROR    0
-#define M_OESPI_PAR_ERROR    0x7
-
-#define V_OESPI_PAR_ERROR(x) ((x) << S_OESPI_PAR_ERROR)
-
-#define A_PM1_TX_INT_CAUSE 0x5fc
-
-#define A_MPS_CFG 0x600
-
-#define S_TPRXPORTEN    4
-#define V_TPRXPORTEN(x) ((x) << S_TPRXPORTEN)
-#define F_TPRXPORTEN    V_TPRXPORTEN(1U)
-
-#define S_TPTXPORT1EN    3
-#define V_TPTXPORT1EN(x) ((x) << S_TPTXPORT1EN)
-#define F_TPTXPORT1EN    V_TPTXPORT1EN(1U)
-
-#define S_TPTXPORT0EN    2
-#define V_TPTXPORT0EN(x) ((x) << S_TPTXPORT0EN)
-#define F_TPTXPORT0EN    V_TPTXPORT0EN(1U)
-
-#define S_PORT1ACTIVE    1
-#define V_PORT1ACTIVE(x) ((x) << S_PORT1ACTIVE)
-#define F_PORT1ACTIVE    V_PORT1ACTIVE(1U)
-
-#define S_PORT0ACTIVE    0
-#define V_PORT0ACTIVE(x) ((x) << S_PORT0ACTIVE)
-#define F_PORT0ACTIVE    V_PORT0ACTIVE(1U)
-
-#define S_ENFORCEPKT    11
-#define V_ENFORCEPKT(x) ((x) << S_ENFORCEPKT)
-#define F_ENFORCEPKT    V_ENFORCEPKT(1U)
-
-#define A_MPS_INT_ENABLE 0x61c
-
-#define S_MCAPARERRENB    6
-#define M_MCAPARERRENB    0x7
-
-#define V_MCAPARERRENB(x) ((x) << S_MCAPARERRENB)
-
-#define S_RXTPPARERRENB    4
-#define M_RXTPPARERRENB    0x3
-
-#define V_RXTPPARERRENB(x) ((x) << S_RXTPPARERRENB)
-
-#define S_TX1TPPARERRENB    2
-#define M_TX1TPPARERRENB    0x3
-
-#define V_TX1TPPARERRENB(x) ((x) << S_TX1TPPARERRENB)
-
-#define S_TX0TPPARERRENB    0
-#define M_TX0TPPARERRENB    0x3
-
-#define V_TX0TPPARERRENB(x) ((x) << S_TX0TPPARERRENB)
-
-#define A_MPS_INT_CAUSE 0x620
-
-#define S_MCAPARERR    6
-#define M_MCAPARERR    0x7
-
-#define V_MCAPARERR(x) ((x) << S_MCAPARERR)
-
-#define S_RXTPPARERR    4
-#define M_RXTPPARERR    0x3
-
-#define V_RXTPPARERR(x) ((x) << S_RXTPPARERR)
-
-#define S_TX1TPPARERR    2
-#define M_TX1TPPARERR    0x3
-
-#define V_TX1TPPARERR(x) ((x) << S_TX1TPPARERR)
-
-#define S_TX0TPPARERR    0
-#define M_TX0TPPARERR    0x3
-
-#define V_TX0TPPARERR(x) ((x) << S_TX0TPPARERR)
-
-#define A_CPL_SWITCH_CNTRL 0x640
-
-#define A_CPL_INTR_ENABLE 0x650
-
-#define S_CIM_OP_MAP_PERR    5
-#define V_CIM_OP_MAP_PERR(x) ((x) << S_CIM_OP_MAP_PERR)
-#define F_CIM_OP_MAP_PERR    V_CIM_OP_MAP_PERR(1U)
-
-#define S_CIM_OVFL_ERROR    4
-#define V_CIM_OVFL_ERROR(x) ((x) << S_CIM_OVFL_ERROR)
-#define F_CIM_OVFL_ERROR    V_CIM_OVFL_ERROR(1U)
-
-#define S_TP_FRAMING_ERROR    3
-#define V_TP_FRAMING_ERROR(x) ((x) << S_TP_FRAMING_ERROR)
-#define F_TP_FRAMING_ERROR    V_TP_FRAMING_ERROR(1U)
-
-#define S_SGE_FRAMING_ERROR    2
-#define V_SGE_FRAMING_ERROR(x) ((x) << S_SGE_FRAMING_ERROR)
-#define F_SGE_FRAMING_ERROR    V_SGE_FRAMING_ERROR(1U)
-
-#define S_CIM_FRAMING_ERROR    1
-#define V_CIM_FRAMING_ERROR(x) ((x) << S_CIM_FRAMING_ERROR)
-#define F_CIM_FRAMING_ERROR    V_CIM_FRAMING_ERROR(1U)
-
-#define S_ZERO_SWITCH_ERROR    0
-#define V_ZERO_SWITCH_ERROR(x) ((x) << S_ZERO_SWITCH_ERROR)
-#define F_ZERO_SWITCH_ERROR    V_ZERO_SWITCH_ERROR(1U)
-
-#define A_CPL_INTR_CAUSE 0x654
-
-#define A_CPL_MAP_TBL_DATA 0x65c
-
-#define A_SMB_GLOBAL_TIME_CFG 0x660
-
-#define A_I2C_CFG 0x6a0
-
-#define S_I2C_CLKDIV    0
-#define M_I2C_CLKDIV    0xfff
-#define V_I2C_CLKDIV(x) ((x) << S_I2C_CLKDIV)
-
-#define A_MI1_CFG 0x6b0
-
-#define S_CLKDIV    5
-#define M_CLKDIV    0xff
-#define V_CLKDIV(x) ((x) << S_CLKDIV)
-
-#define S_ST    3
-
-#define M_ST    0x3
-
-#define V_ST(x) ((x) << S_ST)
-
-#define G_ST(x) (((x) >> S_ST) & M_ST)
-
-#define S_PREEN    2
-#define V_PREEN(x) ((x) << S_PREEN)
-#define F_PREEN    V_PREEN(1U)
-
-#define S_MDIINV    1
-#define V_MDIINV(x) ((x) << S_MDIINV)
-#define F_MDIINV    V_MDIINV(1U)
-
-#define S_MDIEN    0
-#define V_MDIEN(x) ((x) << S_MDIEN)
-#define F_MDIEN    V_MDIEN(1U)
-
-#define A_MI1_ADDR 0x6b4
-
-#define S_PHYADDR    5
-#define M_PHYADDR    0x1f
-#define V_PHYADDR(x) ((x) << S_PHYADDR)
-
-#define S_REGADDR    0
-#define M_REGADDR    0x1f
-#define V_REGADDR(x) ((x) << S_REGADDR)
-
-#define A_MI1_DATA 0x6b8
-
-#define A_MI1_OP 0x6bc
-
-#define S_MDI_OP    0
-#define M_MDI_OP    0x3
-#define V_MDI_OP(x) ((x) << S_MDI_OP)
-
-#define A_SF_DATA 0x6d8
-
-#define A_SF_OP 0x6dc
-
-#define S_BYTECNT    1
-#define M_BYTECNT    0x3
-#define V_BYTECNT(x) ((x) << S_BYTECNT)
-
-#define A_PL_INT_ENABLE0 0x6e0
-
-#define S_T3DBG    23
-#define V_T3DBG(x) ((x) << S_T3DBG)
-#define F_T3DBG    V_T3DBG(1U)
-
-#define S_XGMAC0_1    20
-#define V_XGMAC0_1(x) ((x) << S_XGMAC0_1)
-#define F_XGMAC0_1    V_XGMAC0_1(1U)
-
-#define S_XGMAC0_0    19
-#define V_XGMAC0_0(x) ((x) << S_XGMAC0_0)
-#define F_XGMAC0_0    V_XGMAC0_0(1U)
-
-#define S_MC5A    18
-#define V_MC5A(x) ((x) << S_MC5A)
-#define F_MC5A    V_MC5A(1U)
-
-#define S_CPL_SWITCH    12
-#define V_CPL_SWITCH(x) ((x) << S_CPL_SWITCH)
-#define F_CPL_SWITCH    V_CPL_SWITCH(1U)
-
-#define S_MPS0    11
-#define V_MPS0(x) ((x) << S_MPS0)
-#define F_MPS0    V_MPS0(1U)
-
-#define S_PM1_TX    10
-#define V_PM1_TX(x) ((x) << S_PM1_TX)
-#define F_PM1_TX    V_PM1_TX(1U)
-
-#define S_PM1_RX    9
-#define V_PM1_RX(x) ((x) << S_PM1_RX)
-#define F_PM1_RX    V_PM1_RX(1U)
-
-#define S_ULP2_TX    8
-#define V_ULP2_TX(x) ((x) << S_ULP2_TX)
-#define F_ULP2_TX    V_ULP2_TX(1U)
-
-#define S_ULP2_RX    7
-#define V_ULP2_RX(x) ((x) << S_ULP2_RX)
-#define F_ULP2_RX    V_ULP2_RX(1U)
-
-#define S_TP1    6
-#define V_TP1(x) ((x) << S_TP1)
-#define F_TP1    V_TP1(1U)
-
-#define S_CIM    5
-#define V_CIM(x) ((x) << S_CIM)
-#define F_CIM    V_CIM(1U)
-
-#define S_MC7_CM    4
-#define V_MC7_CM(x) ((x) << S_MC7_CM)
-#define F_MC7_CM    V_MC7_CM(1U)
-
-#define S_MC7_PMTX    3
-#define V_MC7_PMTX(x) ((x) << S_MC7_PMTX)
-#define F_MC7_PMTX    V_MC7_PMTX(1U)
-
-#define S_MC7_PMRX    2
-#define V_MC7_PMRX(x) ((x) << S_MC7_PMRX)
-#define F_MC7_PMRX    V_MC7_PMRX(1U)
-
-#define S_PCIM0    1
-#define V_PCIM0(x) ((x) << S_PCIM0)
-#define F_PCIM0    V_PCIM0(1U)
-
-#define S_SGE3    0
-#define V_SGE3(x) ((x) << S_SGE3)
-#define F_SGE3    V_SGE3(1U)
-
-#define A_PL_INT_CAUSE0 0x6e4
-
-#define A_PL_RST 0x6f0
-
-#define S_FATALPERREN    4
-#define V_FATALPERREN(x) ((x) << S_FATALPERREN)
-#define F_FATALPERREN    V_FATALPERREN(1U)
-
-#define S_CRSTWRM    1
-#define V_CRSTWRM(x) ((x) << S_CRSTWRM)
-#define F_CRSTWRM    V_CRSTWRM(1U)
-
-#define A_PL_REV 0x6f4
-
-#define A_PL_CLI 0x6f8
-
-#define A_MC5_DB_CONFIG 0x704
-
-#define S_TMTYPEHI    30
-#define V_TMTYPEHI(x) ((x) << S_TMTYPEHI)
-#define F_TMTYPEHI    V_TMTYPEHI(1U)
-
-#define S_TMPARTSIZE    28
-#define M_TMPARTSIZE    0x3
-#define V_TMPARTSIZE(x) ((x) << S_TMPARTSIZE)
-#define G_TMPARTSIZE(x) (((x) >> S_TMPARTSIZE) & M_TMPARTSIZE)
-
-#define S_TMTYPE    26
-#define M_TMTYPE    0x3
-#define V_TMTYPE(x) ((x) << S_TMTYPE)
-#define G_TMTYPE(x) (((x) >> S_TMTYPE) & M_TMTYPE)
-
-#define S_COMPEN    17
-#define V_COMPEN(x) ((x) << S_COMPEN)
-#define F_COMPEN    V_COMPEN(1U)
-
-#define S_PRTYEN    6
-#define V_PRTYEN(x) ((x) << S_PRTYEN)
-#define F_PRTYEN    V_PRTYEN(1U)
-
-#define S_MBUSEN    5
-#define V_MBUSEN(x) ((x) << S_MBUSEN)
-#define F_MBUSEN    V_MBUSEN(1U)
-
-#define S_DBGIEN    4
-#define V_DBGIEN(x) ((x) << S_DBGIEN)
-#define F_DBGIEN    V_DBGIEN(1U)
-
-#define S_TMRDY    2
-#define V_TMRDY(x) ((x) << S_TMRDY)
-#define F_TMRDY    V_TMRDY(1U)
-
-#define S_TMRST    1
-#define V_TMRST(x) ((x) << S_TMRST)
-#define F_TMRST    V_TMRST(1U)
-
-#define S_TMMODE    0
-#define V_TMMODE(x) ((x) << S_TMMODE)
-#define F_TMMODE    V_TMMODE(1U)
-
-#define F_TMMODE    V_TMMODE(1U)
-
-#define A_MC5_DB_ROUTING_TABLE_INDEX 0x70c
-
-#define A_MC5_DB_FILTER_TABLE 0x710
-
-#define A_MC5_DB_SERVER_INDEX 0x714
-
-#define A_MC5_DB_RSP_LATENCY 0x720
-
-#define S_RDLAT    16
-#define M_RDLAT    0x1f
-#define V_RDLAT(x) ((x) << S_RDLAT)
-
-#define S_LRNLAT    8
-#define M_LRNLAT    0x1f
-#define V_LRNLAT(x) ((x) << S_LRNLAT)
-
-#define S_SRCHLAT    0
-#define M_SRCHLAT    0x1f
-#define V_SRCHLAT(x) ((x) << S_SRCHLAT)
-
-#define A_MC5_DB_PART_ID_INDEX 0x72c
-
-#define A_MC5_DB_INT_ENABLE 0x740
-
-#define S_DELACTEMPTY    18
-#define V_DELACTEMPTY(x) ((x) << S_DELACTEMPTY)
-#define F_DELACTEMPTY    V_DELACTEMPTY(1U)
-
-#define S_DISPQPARERR    17
-#define V_DISPQPARERR(x) ((x) << S_DISPQPARERR)
-#define F_DISPQPARERR    V_DISPQPARERR(1U)
-
-#define S_REQQPARERR    16
-#define V_REQQPARERR(x) ((x) << S_REQQPARERR)
-#define F_REQQPARERR    V_REQQPARERR(1U)
-
-#define S_UNKNOWNCMD    15
-#define V_UNKNOWNCMD(x) ((x) << S_UNKNOWNCMD)
-#define F_UNKNOWNCMD    V_UNKNOWNCMD(1U)
-
-#define S_NFASRCHFAIL    8
-#define V_NFASRCHFAIL(x) ((x) << S_NFASRCHFAIL)
-#define F_NFASRCHFAIL    V_NFASRCHFAIL(1U)
-
-#define S_ACTRGNFULL    7
-#define V_ACTRGNFULL(x) ((x) << S_ACTRGNFULL)
-#define F_ACTRGNFULL    V_ACTRGNFULL(1U)
-
-#define S_PARITYERR    6
-#define V_PARITYERR(x) ((x) << S_PARITYERR)
-#define F_PARITYERR    V_PARITYERR(1U)
-
-#define A_MC5_DB_INT_CAUSE 0x744
-
-#define A_MC5_DB_DBGI_CONFIG 0x774
-
-#define A_MC5_DB_DBGI_REQ_CMD 0x778
-
-#define A_MC5_DB_DBGI_REQ_ADDR0 0x77c
-
-#define A_MC5_DB_DBGI_REQ_ADDR1 0x780
-
-#define A_MC5_DB_DBGI_REQ_ADDR2 0x784
-
-#define A_MC5_DB_DBGI_REQ_DATA0 0x788
-
-#define A_MC5_DB_DBGI_REQ_DATA1 0x78c
-
-#define A_MC5_DB_DBGI_REQ_DATA2 0x790
-
-#define A_MC5_DB_DBGI_RSP_STATUS 0x7b0
-
-#define S_DBGIRSPVALID    0
-#define V_DBGIRSPVALID(x) ((x) << S_DBGIRSPVALID)
-#define F_DBGIRSPVALID    V_DBGIRSPVALID(1U)
-
-#define A_MC5_DB_DBGI_RSP_DATA0 0x7b4
-
-#define A_MC5_DB_DBGI_RSP_DATA1 0x7b8
-
-#define A_MC5_DB_DBGI_RSP_DATA2 0x7bc
-
-#define A_MC5_DB_POPEN_DATA_WR_CMD 0x7cc
-
-#define A_MC5_DB_POPEN_MASK_WR_CMD 0x7d0
-
-#define A_MC5_DB_AOPEN_SRCH_CMD 0x7d4
-
-#define A_MC5_DB_AOPEN_LRN_CMD 0x7d8
-
-#define A_MC5_DB_SYN_SRCH_CMD 0x7dc
-
-#define A_MC5_DB_SYN_LRN_CMD 0x7e0
-
-#define A_MC5_DB_ACK_SRCH_CMD 0x7e4
-
-#define A_MC5_DB_ACK_LRN_CMD 0x7e8
-
-#define A_MC5_DB_ILOOKUP_CMD 0x7ec
-
-#define A_MC5_DB_ELOOKUP_CMD 0x7f0
-
-#define A_MC5_DB_DATA_WRITE_CMD 0x7f4
-
-#define A_MC5_DB_DATA_READ_CMD 0x7f8
-
-#define XGMAC0_0_BASE_ADDR 0x800
-
-#define A_XGM_TX_CTRL 0x800
-
-#define S_TXEN    0
-#define V_TXEN(x) ((x) << S_TXEN)
-#define F_TXEN    V_TXEN(1U)
-
-#define A_XGM_TX_CFG 0x804
-
-#define S_TXPAUSEEN    0
-#define V_TXPAUSEEN(x) ((x) << S_TXPAUSEEN)
-#define F_TXPAUSEEN    V_TXPAUSEEN(1U)
-
-#define A_XGM_TX_PAUSE_QUANTA 0x808
-
-#define A_XGM_RX_CTRL 0x80c
-
-#define S_RXEN    0
-#define V_RXEN(x) ((x) << S_RXEN)
-#define F_RXEN    V_RXEN(1U)
-
-#define A_XGM_RX_CFG 0x810
-
-#define S_DISPAUSEFRAMES    9
-#define V_DISPAUSEFRAMES(x) ((x) << S_DISPAUSEFRAMES)
-#define F_DISPAUSEFRAMES    V_DISPAUSEFRAMES(1U)
-
-#define S_EN1536BFRAMES    8
-#define V_EN1536BFRAMES(x) ((x) << S_EN1536BFRAMES)
-#define F_EN1536BFRAMES    V_EN1536BFRAMES(1U)
-
-#define S_ENJUMBO    7
-#define V_ENJUMBO(x) ((x) << S_ENJUMBO)
-#define F_ENJUMBO    V_ENJUMBO(1U)
-
-#define S_RMFCS    6
-#define V_RMFCS(x) ((x) << S_RMFCS)
-#define F_RMFCS    V_RMFCS(1U)
-
-#define S_ENHASHMCAST    2
-#define V_ENHASHMCAST(x) ((x) << S_ENHASHMCAST)
-#define F_ENHASHMCAST    V_ENHASHMCAST(1U)
-
-#define S_COPYALLFRAMES    0
-#define V_COPYALLFRAMES(x) ((x) << S_COPYALLFRAMES)
-#define F_COPYALLFRAMES    V_COPYALLFRAMES(1U)
-
-#define S_DISBCAST    1
-#define V_DISBCAST(x) ((x) << S_DISBCAST)
-#define F_DISBCAST    V_DISBCAST(1U)
-
-#define A_XGM_RX_HASH_LOW 0x814
-
-#define A_XGM_RX_HASH_HIGH 0x818
-
-#define A_XGM_RX_EXACT_MATCH_LOW_1 0x81c
-
-#define A_XGM_RX_EXACT_MATCH_HIGH_1 0x820
-
-#define A_XGM_RX_EXACT_MATCH_LOW_2 0x824
-
-#define A_XGM_RX_EXACT_MATCH_LOW_3 0x82c
-
-#define A_XGM_RX_EXACT_MATCH_LOW_4 0x834
-
-#define A_XGM_RX_EXACT_MATCH_LOW_5 0x83c
-
-#define A_XGM_RX_EXACT_MATCH_LOW_6 0x844
-
-#define A_XGM_RX_EXACT_MATCH_LOW_7 0x84c
-
-#define A_XGM_RX_EXACT_MATCH_LOW_8 0x854
-
-#define A_XGM_INT_STATUS 0x86c
-
-#define S_LINKFAULTCHANGE    9
-#define V_LINKFAULTCHANGE(x) ((x) << S_LINKFAULTCHANGE)
-#define F_LINKFAULTCHANGE    V_LINKFAULTCHANGE(1U)
-
-#define A_XGM_XGM_INT_ENABLE 0x874
-#define A_XGM_XGM_INT_DISABLE 0x878
-
-#define A_XGM_STAT_CTRL 0x880
-
-#define S_CLRSTATS    2
-#define V_CLRSTATS(x) ((x) << S_CLRSTATS)
-#define F_CLRSTATS    V_CLRSTATS(1U)
-
-#define A_XGM_RXFIFO_CFG 0x884
-
-#define S_RXFIFO_EMPTY    31
-#define V_RXFIFO_EMPTY(x) ((x) << S_RXFIFO_EMPTY)
-#define F_RXFIFO_EMPTY    V_RXFIFO_EMPTY(1U)
-
-#define S_RXFIFOPAUSEHWM    17
-#define M_RXFIFOPAUSEHWM    0xfff
-
-#define V_RXFIFOPAUSEHWM(x) ((x) << S_RXFIFOPAUSEHWM)
-
-#define G_RXFIFOPAUSEHWM(x) (((x) >> S_RXFIFOPAUSEHWM) & M_RXFIFOPAUSEHWM)
-
-#define S_RXFIFOPAUSELWM    5
-#define M_RXFIFOPAUSELWM    0xfff
-
-#define V_RXFIFOPAUSELWM(x) ((x) << S_RXFIFOPAUSELWM)
-
-#define G_RXFIFOPAUSELWM(x) (((x) >> S_RXFIFOPAUSELWM) & M_RXFIFOPAUSELWM)
-
-#define S_RXSTRFRWRD    1
-#define V_RXSTRFRWRD(x) ((x) << S_RXSTRFRWRD)
-#define F_RXSTRFRWRD    V_RXSTRFRWRD(1U)
-
-#define S_DISERRFRAMES    0
-#define V_DISERRFRAMES(x) ((x) << S_DISERRFRAMES)
-#define F_DISERRFRAMES    V_DISERRFRAMES(1U)
-
-#define A_XGM_TXFIFO_CFG 0x888
-
-#define S_UNDERUNFIX    22
-#define V_UNDERUNFIX(x) ((x) << S_UNDERUNFIX)
-#define F_UNDERUNFIX    V_UNDERUNFIX(1U)
-
-#define S_TXIPG    13
-#define M_TXIPG    0xff
-#define V_TXIPG(x) ((x) << S_TXIPG)
-#define G_TXIPG(x) (((x) >> S_TXIPG) & M_TXIPG)
-
-#define S_TXFIFOTHRESH    4
-#define M_TXFIFOTHRESH    0x1ff
-
-#define V_TXFIFOTHRESH(x) ((x) << S_TXFIFOTHRESH)
-
-#define S_ENDROPPKT    21
-#define V_ENDROPPKT(x) ((x) << S_ENDROPPKT)
-#define F_ENDROPPKT    V_ENDROPPKT(1U)
-
-#define A_XGM_SERDES_CTRL 0x890
-#define A_XGM_SERDES_CTRL0 0x8e0
-
-#define S_SERDESRESET_    24
-#define V_SERDESRESET_(x) ((x) << S_SERDESRESET_)
-#define F_SERDESRESET_    V_SERDESRESET_(1U)
-
-#define S_RXENABLE    4
-#define V_RXENABLE(x) ((x) << S_RXENABLE)
-#define F_RXENABLE    V_RXENABLE(1U)
-
-#define S_TXENABLE    3
-#define V_TXENABLE(x) ((x) << S_TXENABLE)
-#define F_TXENABLE    V_TXENABLE(1U)
-
-#define A_XGM_PAUSE_TIMER 0x890
-
-#define A_XGM_RGMII_IMP 0x89c
-
-#define S_XGM_IMPSETUPDATE    6
-#define V_XGM_IMPSETUPDATE(x) ((x) << S_XGM_IMPSETUPDATE)
-#define F_XGM_IMPSETUPDATE    V_XGM_IMPSETUPDATE(1U)
-
-#define S_RGMIIIMPPD    3
-#define M_RGMIIIMPPD    0x7
-#define V_RGMIIIMPPD(x) ((x) << S_RGMIIIMPPD)
-
-#define S_RGMIIIMPPU    0
-#define M_RGMIIIMPPU    0x7
-#define V_RGMIIIMPPU(x) ((x) << S_RGMIIIMPPU)
-
-#define S_CALRESET    8
-#define V_CALRESET(x) ((x) << S_CALRESET)
-#define F_CALRESET    V_CALRESET(1U)
-
-#define S_CALUPDATE    7
-#define V_CALUPDATE(x) ((x) << S_CALUPDATE)
-#define F_CALUPDATE    V_CALUPDATE(1U)
-
-#define A_XGM_XAUI_IMP 0x8a0
-
-#define S_CALBUSY    31
-#define V_CALBUSY(x) ((x) << S_CALBUSY)
-#define F_CALBUSY    V_CALBUSY(1U)
-
-#define S_XGM_CALFAULT    29
-#define V_XGM_CALFAULT(x) ((x) << S_XGM_CALFAULT)
-#define F_XGM_CALFAULT    V_XGM_CALFAULT(1U)
-
-#define S_CALIMP    24
-#define M_CALIMP    0x1f
-#define V_CALIMP(x) ((x) << S_CALIMP)
-#define G_CALIMP(x) (((x) >> S_CALIMP) & M_CALIMP)
-
-#define S_XAUIIMP    0
-#define M_XAUIIMP    0x7
-#define V_XAUIIMP(x) ((x) << S_XAUIIMP)
-
-#define A_XGM_RX_MAX_PKT_SIZE 0x8a8
-
-#define S_RXMAXFRAMERSIZE    17
-#define M_RXMAXFRAMERSIZE    0x3fff
-#define V_RXMAXFRAMERSIZE(x) ((x) << S_RXMAXFRAMERSIZE)
-#define G_RXMAXFRAMERSIZE(x) (((x) >> S_RXMAXFRAMERSIZE) & M_RXMAXFRAMERSIZE)
-
-#define S_RXENFRAMER    14
-#define V_RXENFRAMER(x) ((x) << S_RXENFRAMER)
-#define F_RXENFRAMER    V_RXENFRAMER(1U)
-
-#define S_RXMAXPKTSIZE    0
-#define M_RXMAXPKTSIZE    0x3fff
-#define V_RXMAXPKTSIZE(x) ((x) << S_RXMAXPKTSIZE)
-#define G_RXMAXPKTSIZE(x) (((x) >> S_RXMAXPKTSIZE) & M_RXMAXPKTSIZE)
-
-#define A_XGM_RESET_CTRL 0x8ac
-
-#define S_XGMAC_STOP_EN    4
-#define V_XGMAC_STOP_EN(x) ((x) << S_XGMAC_STOP_EN)
-#define F_XGMAC_STOP_EN    V_XGMAC_STOP_EN(1U)
-
-#define S_XG2G_RESET_    3
-#define V_XG2G_RESET_(x) ((x) << S_XG2G_RESET_)
-#define F_XG2G_RESET_    V_XG2G_RESET_(1U)
-
-#define S_RGMII_RESET_    2
-#define V_RGMII_RESET_(x) ((x) << S_RGMII_RESET_)
-#define F_RGMII_RESET_    V_RGMII_RESET_(1U)
-
-#define S_PCS_RESET_    1
-#define V_PCS_RESET_(x) ((x) << S_PCS_RESET_)
-#define F_PCS_RESET_    V_PCS_RESET_(1U)
-
-#define S_MAC_RESET_    0
-#define V_MAC_RESET_(x) ((x) << S_MAC_RESET_)
-#define F_MAC_RESET_    V_MAC_RESET_(1U)
-
-#define A_XGM_PORT_CFG 0x8b8
-
-#define S_CLKDIVRESET_    3
-#define V_CLKDIVRESET_(x) ((x) << S_CLKDIVRESET_)
-#define F_CLKDIVRESET_    V_CLKDIVRESET_(1U)
-
-#define S_PORTSPEED    1
-#define M_PORTSPEED    0x3
-
-#define V_PORTSPEED(x) ((x) << S_PORTSPEED)
-
-#define S_ENRGMII    0
-#define V_ENRGMII(x) ((x) << S_ENRGMII)
-#define F_ENRGMII    V_ENRGMII(1U)
-
-#define A_XGM_INT_ENABLE 0x8d4
-
-#define S_TXFIFO_PRTY_ERR    17
-#define M_TXFIFO_PRTY_ERR    0x7
-
-#define V_TXFIFO_PRTY_ERR(x) ((x) << S_TXFIFO_PRTY_ERR)
-
-#define S_RXFIFO_PRTY_ERR    14
-#define M_RXFIFO_PRTY_ERR    0x7
-
-#define V_RXFIFO_PRTY_ERR(x) ((x) << S_RXFIFO_PRTY_ERR)
-
-#define S_TXFIFO_UNDERRUN    13
-#define V_TXFIFO_UNDERRUN(x) ((x) << S_TXFIFO_UNDERRUN)
-#define F_TXFIFO_UNDERRUN    V_TXFIFO_UNDERRUN(1U)
-
-#define S_RXFIFO_OVERFLOW    12
-#define V_RXFIFO_OVERFLOW(x) ((x) << S_RXFIFO_OVERFLOW)
-#define F_RXFIFO_OVERFLOW    V_RXFIFO_OVERFLOW(1U)
-
-#define S_SERDES_LOS    4
-#define M_SERDES_LOS    0xf
-
-#define V_SERDES_LOS(x) ((x) << S_SERDES_LOS)
-
-#define S_XAUIPCSCTCERR    3
-#define V_XAUIPCSCTCERR(x) ((x) << S_XAUIPCSCTCERR)
-#define F_XAUIPCSCTCERR    V_XAUIPCSCTCERR(1U)
-
-#define S_XAUIPCSALIGNCHANGE    2
-#define V_XAUIPCSALIGNCHANGE(x) ((x) << S_XAUIPCSALIGNCHANGE)
-#define F_XAUIPCSALIGNCHANGE    V_XAUIPCSALIGNCHANGE(1U)
-
-#define S_XGM_INT    0
-#define V_XGM_INT(x) ((x) << S_XGM_INT)
-#define F_XGM_INT    V_XGM_INT(1U)
-
-#define A_XGM_INT_CAUSE 0x8d8
-
-#define A_XGM_XAUI_ACT_CTRL 0x8dc
-
-#define S_TXACTENABLE    1
-#define V_TXACTENABLE(x) ((x) << S_TXACTENABLE)
-#define F_TXACTENABLE    V_TXACTENABLE(1U)
-
-#define A_XGM_SERDES_CTRL0 0x8e0
-
-#define S_RESET3    23
-#define V_RESET3(x) ((x) << S_RESET3)
-#define F_RESET3    V_RESET3(1U)
-
-#define S_RESET2    22
-#define V_RESET2(x) ((x) << S_RESET2)
-#define F_RESET2    V_RESET2(1U)
-
-#define S_RESET1    21
-#define V_RESET1(x) ((x) << S_RESET1)
-#define F_RESET1    V_RESET1(1U)
-
-#define S_RESET0    20
-#define V_RESET0(x) ((x) << S_RESET0)
-#define F_RESET0    V_RESET0(1U)
-
-#define S_PWRDN3    19
-#define V_PWRDN3(x) ((x) << S_PWRDN3)
-#define F_PWRDN3    V_PWRDN3(1U)
-
-#define S_PWRDN2    18
-#define V_PWRDN2(x) ((x) << S_PWRDN2)
-#define F_PWRDN2    V_PWRDN2(1U)
-
-#define S_PWRDN1    17
-#define V_PWRDN1(x) ((x) << S_PWRDN1)
-#define F_PWRDN1    V_PWRDN1(1U)
-
-#define S_PWRDN0    16
-#define V_PWRDN0(x) ((x) << S_PWRDN0)
-#define F_PWRDN0    V_PWRDN0(1U)
-
-#define S_RESETPLL23    15
-#define V_RESETPLL23(x) ((x) << S_RESETPLL23)
-#define F_RESETPLL23    V_RESETPLL23(1U)
-
-#define S_RESETPLL01    14
-#define V_RESETPLL01(x) ((x) << S_RESETPLL01)
-#define F_RESETPLL01    V_RESETPLL01(1U)
-
-#define A_XGM_SERDES_STAT0 0x8f0
-#define A_XGM_SERDES_STAT1 0x8f4
-#define A_XGM_SERDES_STAT2 0x8f8
-
-#define S_LOWSIG0    0
-#define V_LOWSIG0(x) ((x) << S_LOWSIG0)
-#define F_LOWSIG0    V_LOWSIG0(1U)
-
-#define A_XGM_SERDES_STAT3 0x8fc
-
-#define A_XGM_STAT_TX_BYTE_LOW 0x900
-
-#define A_XGM_STAT_TX_BYTE_HIGH 0x904
-
-#define A_XGM_STAT_TX_FRAME_LOW 0x908
-
-#define A_XGM_STAT_TX_FRAME_HIGH 0x90c
-
-#define A_XGM_STAT_TX_BCAST 0x910
-
-#define A_XGM_STAT_TX_MCAST 0x914
-
-#define A_XGM_STAT_TX_PAUSE 0x918
-
-#define A_XGM_STAT_TX_64B_FRAMES 0x91c
-
-#define A_XGM_STAT_TX_65_127B_FRAMES 0x920
-
-#define A_XGM_STAT_TX_128_255B_FRAMES 0x924
-
-#define A_XGM_STAT_TX_256_511B_FRAMES 0x928
-
-#define A_XGM_STAT_TX_512_1023B_FRAMES 0x92c
-
-#define A_XGM_STAT_TX_1024_1518B_FRAMES 0x930
-
-#define A_XGM_STAT_TX_1519_MAXB_FRAMES 0x934
-
-#define A_XGM_STAT_TX_ERR_FRAMES 0x938
-
-#define A_XGM_STAT_RX_BYTES_LOW 0x93c
-
-#define A_XGM_STAT_RX_BYTES_HIGH 0x940
-
-#define A_XGM_STAT_RX_FRAMES_LOW 0x944
-
-#define A_XGM_STAT_RX_FRAMES_HIGH 0x948
-
-#define A_XGM_STAT_RX_BCAST_FRAMES 0x94c
-
-#define A_XGM_STAT_RX_MCAST_FRAMES 0x950
-
-#define A_XGM_STAT_RX_PAUSE_FRAMES 0x954
-
-#define A_XGM_STAT_RX_64B_FRAMES 0x958
-
-#define A_XGM_STAT_RX_65_127B_FRAMES 0x95c
-
-#define A_XGM_STAT_RX_128_255B_FRAMES 0x960
-
-#define A_XGM_STAT_RX_256_511B_FRAMES 0x964
-
-#define A_XGM_STAT_RX_512_1023B_FRAMES 0x968
-
-#define A_XGM_STAT_RX_1024_1518B_FRAMES 0x96c
-
-#define A_XGM_STAT_RX_1519_MAXB_FRAMES 0x970
-
-#define A_XGM_STAT_RX_SHORT_FRAMES 0x974
-
-#define A_XGM_STAT_RX_OVERSIZE_FRAMES 0x978
-
-#define A_XGM_STAT_RX_JABBER_FRAMES 0x97c
-
-#define A_XGM_STAT_RX_CRC_ERR_FRAMES 0x980
-
-#define A_XGM_STAT_RX_LENGTH_ERR_FRAMES 0x984
-
-#define A_XGM_STAT_RX_SYM_CODE_ERR_FRAMES 0x988
-
-#define A_XGM_SERDES_STATUS0 0x98c
-
-#define A_XGM_SERDES_STATUS1 0x990
-
-#define S_CMULOCK    31
-#define V_CMULOCK(x) ((x) << S_CMULOCK)
-#define F_CMULOCK    V_CMULOCK(1U)
-
-#define A_XGM_RX_MAX_PKT_SIZE_ERR_CNT 0x9a4
-
-#define A_XGM_TX_SPI4_SOP_EOP_CNT 0x9a8
-
-#define S_TXSPI4SOPCNT    16
-#define M_TXSPI4SOPCNT    0xffff
-#define V_TXSPI4SOPCNT(x) ((x) << S_TXSPI4SOPCNT)
-#define G_TXSPI4SOPCNT(x) (((x) >> S_TXSPI4SOPCNT) & M_TXSPI4SOPCNT)
-
-#define A_XGM_RX_SPI4_SOP_EOP_CNT 0x9ac
-
-#define XGMAC0_1_BASE_ADDR 0xa00
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/sge.c linux-libre-3.2-gnu/drivers/net/cxgb3/sge.c
--- linux-libre-3.1-gnu/drivers/net/cxgb3/sge.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/sge.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3303 +0,0 @@
-/*
- * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_vlan.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/dma-mapping.h>
-#include <linux/slab.h>
-#include <linux/prefetch.h>
-#include <net/arp.h>
-#include "common.h"
-#include "regs.h"
-#include "sge_defs.h"
-#include "t3_cpl.h"
-#include "firmware_exports.h"
-#include "cxgb3_offload.h"
-
-#define USE_GTS 0
-
-#define SGE_RX_SM_BUF_SIZE 1536
-
-#define SGE_RX_COPY_THRES  256
-#define SGE_RX_PULL_LEN    128
-
-#define SGE_PG_RSVD SMP_CACHE_BYTES
-/*
- * Page chunk size for FL0 buffers if FL0 is to be populated with page chunks.
- * It must be a divisor of PAGE_SIZE.  If set to 0 FL0 will use sk_buffs
- * directly.
- */
-#define FL0_PG_CHUNK_SIZE  2048
-#define FL0_PG_ORDER 0
-#define FL0_PG_ALLOC_SIZE (PAGE_SIZE << FL0_PG_ORDER)
-#define FL1_PG_CHUNK_SIZE (PAGE_SIZE > 8192 ? 16384 : 8192)
-#define FL1_PG_ORDER (PAGE_SIZE > 8192 ? 0 : 1)
-#define FL1_PG_ALLOC_SIZE (PAGE_SIZE << FL1_PG_ORDER)
-
-#define SGE_RX_DROP_THRES 16
-#define RX_RECLAIM_PERIOD (HZ/4)
-
-/*
- * Max number of Rx buffers we replenish at a time.
- */
-#define MAX_RX_REFILL 16U
-/*
- * Period of the Tx buffer reclaim timer.  This timer does not need to run
- * frequently as Tx buffers are usually reclaimed by new Tx packets.
- */
-#define TX_RECLAIM_PERIOD (HZ / 4)
-#define TX_RECLAIM_TIMER_CHUNK 64U
-#define TX_RECLAIM_CHUNK 16U
-
-/* WR size in bytes */
-#define WR_LEN (WR_FLITS * 8)
-
-/*
- * Types of Tx queues in each queue set.  Order here matters, do not change.
- */
-enum { TXQ_ETH, TXQ_OFLD, TXQ_CTRL };
-
-/* Values for sge_txq.flags */
-enum {
-	TXQ_RUNNING = 1 << 0,	/* fetch engine is running */
-	TXQ_LAST_PKT_DB = 1 << 1,	/* last packet rang the doorbell */
-};
-
-struct tx_desc {
-	__be64 flit[TX_DESC_FLITS];
-};
-
-struct rx_desc {
-	__be32 addr_lo;
-	__be32 len_gen;
-	__be32 gen2;
-	__be32 addr_hi;
-};
-
-struct tx_sw_desc {		/* SW state per Tx descriptor */
-	struct sk_buff *skb;
-	u8 eop;       /* set if last descriptor for packet */
-	u8 addr_idx;  /* buffer index of first SGL entry in descriptor */
-	u8 fragidx;   /* first page fragment associated with descriptor */
-	s8 sflit;     /* start flit of first SGL entry in descriptor */
-};
-
-struct rx_sw_desc {                /* SW state per Rx descriptor */
-	union {
-		struct sk_buff *skb;
-		struct fl_pg_chunk pg_chunk;
-	};
-	DEFINE_DMA_UNMAP_ADDR(dma_addr);
-};
-
-struct rsp_desc {		/* response queue descriptor */
-	struct rss_header rss_hdr;
-	__be32 flags;
-	__be32 len_cq;
-	u8 imm_data[47];
-	u8 intr_gen;
-};
-
-/*
- * Holds unmapping information for Tx packets that need deferred unmapping.
- * This structure lives at skb->head and must be allocated by callers.
- */
-struct deferred_unmap_info {
-	struct pci_dev *pdev;
-	dma_addr_t addr[MAX_SKB_FRAGS + 1];
-};
-
-/*
- * Maps a number of flits to the number of Tx descriptors that can hold them.
- * The formula is
- *
- * desc = 1 + (flits - 2) / (WR_FLITS - 1).
- *
- * HW allows up to 4 descriptors to be combined into a WR.
- */
-static u8 flit_desc_map[] = {
-	0,
-#if SGE_NUM_GENBITS == 1
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
-#elif SGE_NUM_GENBITS == 2
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-#else
-# error "SGE_NUM_GENBITS must be 1 or 2"
-#endif
-};
-
-static inline struct sge_qset *fl_to_qset(const struct sge_fl *q, int qidx)
-{
-	return container_of(q, struct sge_qset, fl[qidx]);
-}
-
-static inline struct sge_qset *rspq_to_qset(const struct sge_rspq *q)
-{
-	return container_of(q, struct sge_qset, rspq);
-}
-
-static inline struct sge_qset *txq_to_qset(const struct sge_txq *q, int qidx)
-{
-	return container_of(q, struct sge_qset, txq[qidx]);
-}
-
-/**
- *	refill_rspq - replenish an SGE response queue
- *	@adapter: the adapter
- *	@q: the response queue to replenish
- *	@credits: how many new responses to make available
- *
- *	Replenishes a response queue by making the supplied number of responses
- *	available to HW.
- */
-static inline void refill_rspq(struct adapter *adapter,
-			       const struct sge_rspq *q, unsigned int credits)
-{
-	rmb();
-	t3_write_reg(adapter, A_SG_RSPQ_CREDIT_RETURN,
-		     V_RSPQ(q->cntxt_id) | V_CREDITS(credits));
-}
-
-/**
- *	need_skb_unmap - does the platform need unmapping of sk_buffs?
- *
- *	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)
-{
-#ifdef CONFIG_NEED_DMA_MAP_STATE
-	return 1;
-#else
-	return 0;
-#endif
-}
-
-/**
- *	unmap_skb - unmap a packet main body and its page fragments
- *	@skb: the packet
- *	@q: the Tx queue containing Tx descriptors for the packet
- *	@cidx: index of Tx descriptor
- *	@pdev: the PCI device
- *
- *	Unmap the main body of an sk_buff and its page fragments, if any.
- *	Because of the fairly complicated structure of our SGLs and the desire
- *	to conserve space for metadata, the information necessary to unmap an
- *	sk_buff is spread across the sk_buff itself (buffer lengths), the HW Tx
- *	descriptors (the physical addresses of the various data buffers), and
- *	the SW descriptor state (assorted indices).  The send functions
- *	initialize the indices for the first packet descriptor so we can unmap
- *	the buffers held in the first Tx descriptor here, and we have enough
- *	information at this point to set the state for the next Tx descriptor.
- *
- *	Note that it is possible to clean up the first descriptor of a packet
- *	before the send routines have written the next descriptors, but this
- *	race does not cause any problem.  We just end up writing the unmapping
- *	info for the descriptor first.
- */
-static inline void unmap_skb(struct sk_buff *skb, struct sge_txq *q,
-			     unsigned int cidx, struct pci_dev *pdev)
-{
-	const struct sg_ent *sgp;
-	struct tx_sw_desc *d = &q->sdesc[cidx];
-	int nfrags, frag_idx, curflit, j = d->addr_idx;
-
-	sgp = (struct sg_ent *)&q->desc[cidx].flit[d->sflit];
-	frag_idx = d->fragidx;
-
-	if (frag_idx == 0 && skb_headlen(skb)) {
-		pci_unmap_single(pdev, be64_to_cpu(sgp->addr[0]),
-				 skb_headlen(skb), PCI_DMA_TODEVICE);
-		j = 1;
-	}
-
-	curflit = d->sflit + 1 + j;
-	nfrags = skb_shinfo(skb)->nr_frags;
-
-	while (frag_idx < nfrags && curflit < WR_FLITS) {
-		pci_unmap_page(pdev, be64_to_cpu(sgp->addr[j]),
-			       skb_shinfo(skb)->frags[frag_idx].size,
-			       PCI_DMA_TODEVICE);
-		j ^= 1;
-		if (j == 0) {
-			sgp++;
-			curflit++;
-		}
-		curflit++;
-		frag_idx++;
-	}
-
-	if (frag_idx < nfrags) {   /* SGL continues into next Tx descriptor */
-		d = cidx + 1 == q->size ? q->sdesc : d + 1;
-		d->fragidx = frag_idx;
-		d->addr_idx = j;
-		d->sflit = curflit - WR_FLITS - j; /* sflit can be -1 */
-	}
-}
-
-/**
- *	free_tx_desc - reclaims Tx descriptors and their buffers
- *	@adapter: the adapter
- *	@q: the Tx queue to reclaim descriptors from
- *	@n: the number of descriptors to reclaim
- *
- *	Reclaims Tx descriptors from an SGE Tx queue and frees the associated
- *	Tx buffers.  Called with the Tx queue lock held.
- */
-static void free_tx_desc(struct adapter *adapter, struct sge_txq *q,
-			 unsigned int n)
-{
-	struct tx_sw_desc *d;
-	struct pci_dev *pdev = adapter->pdev;
-	unsigned int cidx = q->cidx;
-
-	const int need_unmap = need_skb_unmap() &&
-			       q->cntxt_id >= FW_TUNNEL_SGEEC_START;
-
-	d = &q->sdesc[cidx];
-	while (n--) {
-		if (d->skb) {	/* an SGL is present */
-			if (need_unmap)
-				unmap_skb(d->skb, q, cidx, pdev);
-			if (d->eop) {
-				kfree_skb(d->skb);
-				d->skb = NULL;
-			}
-		}
-		++d;
-		if (++cidx == q->size) {
-			cidx = 0;
-			d = q->sdesc;
-		}
-	}
-	q->cidx = cidx;
-}
-
-/**
- *	reclaim_completed_tx - reclaims completed Tx descriptors
- *	@adapter: the adapter
- *	@q: the Tx queue to reclaim completed descriptors from
- *	@chunk: maximum number of descriptors to reclaim
- *
- *	Reclaims Tx descriptors that the SGE has indicated it has processed,
- *	and frees the associated buffers if possible.  Called with the Tx
- *	queue's lock held.
- */
-static inline unsigned int reclaim_completed_tx(struct adapter *adapter,
-						struct sge_txq *q,
-						unsigned int chunk)
-{
-	unsigned int reclaim = q->processed - q->cleaned;
-
-	reclaim = min(chunk, reclaim);
-	if (reclaim) {
-		free_tx_desc(adapter, q, reclaim);
-		q->cleaned += reclaim;
-		q->in_use -= reclaim;
-	}
-	return q->processed - q->cleaned;
-}
-
-/**
- *	should_restart_tx - are there enough resources to restart a Tx queue?
- *	@q: the Tx queue
- *
- *	Checks if there are enough descriptors to restart a suspended Tx queue.
- */
-static inline int should_restart_tx(const struct sge_txq *q)
-{
-	unsigned int r = q->processed - q->cleaned;
-
-	return q->in_use - r < (q->size >> 1);
-}
-
-static void clear_rx_desc(struct pci_dev *pdev, const struct sge_fl *q,
-			  struct rx_sw_desc *d)
-{
-	if (q->use_pages && d->pg_chunk.page) {
-		(*d->pg_chunk.p_cnt)--;
-		if (!*d->pg_chunk.p_cnt)
-			pci_unmap_page(pdev,
-				       d->pg_chunk.mapping,
-				       q->alloc_size, PCI_DMA_FROMDEVICE);
-
-		put_page(d->pg_chunk.page);
-		d->pg_chunk.page = NULL;
-	} else {
-		pci_unmap_single(pdev, dma_unmap_addr(d, dma_addr),
-				 q->buf_size, PCI_DMA_FROMDEVICE);
-		kfree_skb(d->skb);
-		d->skb = NULL;
-	}
-}
-
-/**
- *	free_rx_bufs - free the Rx buffers on an SGE free list
- *	@pdev: the PCI device associated with the adapter
- *	@rxq: the SGE free list to clean up
- *
- *	Release the buffers on an SGE free-buffer Rx queue.  HW fetching from
- *	this queue should be stopped before calling this function.
- */
-static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q)
-{
-	unsigned int cidx = q->cidx;
-
-	while (q->credits--) {
-		struct rx_sw_desc *d = &q->sdesc[cidx];
-
-
-		clear_rx_desc(pdev, q, d);
-		if (++cidx == q->size)
-			cidx = 0;
-	}
-
-	if (q->pg_chunk.page) {
-		__free_pages(q->pg_chunk.page, q->order);
-		q->pg_chunk.page = NULL;
-	}
-}
-
-/**
- *	add_one_rx_buf - add a packet buffer to a free-buffer list
- *	@va:  buffer start VA
- *	@len: the buffer length
- *	@d: the HW Rx descriptor to write
- *	@sd: the SW Rx descriptor to write
- *	@gen: the generation bit value
- *	@pdev: the PCI device associated with the adapter
- *
- *	Add a buffer of the given length to the supplied HW and SW Rx
- *	descriptors.
- */
-static inline int add_one_rx_buf(void *va, unsigned int len,
-				 struct rx_desc *d, struct rx_sw_desc *sd,
-				 unsigned int gen, struct pci_dev *pdev)
-{
-	dma_addr_t mapping;
-
-	mapping = pci_map_single(pdev, va, len, PCI_DMA_FROMDEVICE);
-	if (unlikely(pci_dma_mapping_error(pdev, mapping)))
-		return -ENOMEM;
-
-	dma_unmap_addr_set(sd, dma_addr, mapping);
-
-	d->addr_lo = cpu_to_be32(mapping);
-	d->addr_hi = cpu_to_be32((u64) mapping >> 32);
-	wmb();
-	d->len_gen = cpu_to_be32(V_FLD_GEN1(gen));
-	d->gen2 = cpu_to_be32(V_FLD_GEN2(gen));
-	return 0;
-}
-
-static inline int add_one_rx_chunk(dma_addr_t mapping, struct rx_desc *d,
-				   unsigned int gen)
-{
-	d->addr_lo = cpu_to_be32(mapping);
-	d->addr_hi = cpu_to_be32((u64) mapping >> 32);
-	wmb();
-	d->len_gen = cpu_to_be32(V_FLD_GEN1(gen));
-	d->gen2 = cpu_to_be32(V_FLD_GEN2(gen));
-	return 0;
-}
-
-static int alloc_pg_chunk(struct adapter *adapter, struct sge_fl *q,
-			  struct rx_sw_desc *sd, gfp_t gfp,
-			  unsigned int order)
-{
-	if (!q->pg_chunk.page) {
-		dma_addr_t mapping;
-
-		q->pg_chunk.page = alloc_pages(gfp, order);
-		if (unlikely(!q->pg_chunk.page))
-			return -ENOMEM;
-		q->pg_chunk.va = page_address(q->pg_chunk.page);
-		q->pg_chunk.p_cnt = q->pg_chunk.va + (PAGE_SIZE << order) -
-				    SGE_PG_RSVD;
-		q->pg_chunk.offset = 0;
-		mapping = pci_map_page(adapter->pdev, q->pg_chunk.page,
-				       0, q->alloc_size, PCI_DMA_FROMDEVICE);
-		q->pg_chunk.mapping = mapping;
-	}
-	sd->pg_chunk = q->pg_chunk;
-
-	prefetch(sd->pg_chunk.p_cnt);
-
-	q->pg_chunk.offset += q->buf_size;
-	if (q->pg_chunk.offset == (PAGE_SIZE << order))
-		q->pg_chunk.page = NULL;
-	else {
-		q->pg_chunk.va += q->buf_size;
-		get_page(q->pg_chunk.page);
-	}
-
-	if (sd->pg_chunk.offset == 0)
-		*sd->pg_chunk.p_cnt = 1;
-	else
-		*sd->pg_chunk.p_cnt += 1;
-
-	return 0;
-}
-
-static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q)
-{
-	if (q->pend_cred >= q->credits / 4) {
-		q->pend_cred = 0;
-		wmb();
-		t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id));
-	}
-}
-
-/**
- *	refill_fl - refill an SGE free-buffer list
- *	@adapter: the adapter
- *	@q: the free-list to refill
- *	@n: the number of new buffers to allocate
- *	@gfp: the gfp flags for allocating new buffers
- *
- *	(Re)populate an SGE free-buffer list with up to @n new packet buffers,
- *	allocated with the supplied gfp flags.  The caller must assure that
- *	@n does not exceed the queue's capacity.
- */
-static int refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp)
-{
-	struct rx_sw_desc *sd = &q->sdesc[q->pidx];
-	struct rx_desc *d = &q->desc[q->pidx];
-	unsigned int count = 0;
-
-	while (n--) {
-		dma_addr_t mapping;
-		int err;
-
-		if (q->use_pages) {
-			if (unlikely(alloc_pg_chunk(adap, q, sd, gfp,
-						    q->order))) {
-nomem:				q->alloc_failed++;
-				break;
-			}
-			mapping = sd->pg_chunk.mapping + sd->pg_chunk.offset;
-			dma_unmap_addr_set(sd, dma_addr, mapping);
-
-			add_one_rx_chunk(mapping, d, q->gen);
-			pci_dma_sync_single_for_device(adap->pdev, mapping,
-						q->buf_size - SGE_PG_RSVD,
-						PCI_DMA_FROMDEVICE);
-		} else {
-			void *buf_start;
-
-			struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
-			if (!skb)
-				goto nomem;
-
-			sd->skb = skb;
-			buf_start = skb->data;
-			err = add_one_rx_buf(buf_start, q->buf_size, d, sd,
-					     q->gen, adap->pdev);
-			if (unlikely(err)) {
-				clear_rx_desc(adap->pdev, q, sd);
-				break;
-			}
-		}
-
-		d++;
-		sd++;
-		if (++q->pidx == q->size) {
-			q->pidx = 0;
-			q->gen ^= 1;
-			sd = q->sdesc;
-			d = q->desc;
-		}
-		count++;
-	}
-
-	q->credits += count;
-	q->pend_cred += count;
-	ring_fl_db(adap, q);
-
-	return count;
-}
-
-static inline void __refill_fl(struct adapter *adap, struct sge_fl *fl)
-{
-	refill_fl(adap, fl, min(MAX_RX_REFILL, fl->size - fl->credits),
-		  GFP_ATOMIC | __GFP_COMP);
-}
-
-/**
- *	recycle_rx_buf - recycle a receive buffer
- *	@adapter: the adapter
- *	@q: the SGE free list
- *	@idx: index of buffer to recycle
- *
- *	Recycles the specified buffer on the given free list by adding it at
- *	the next available slot on the list.
- */
-static void recycle_rx_buf(struct adapter *adap, struct sge_fl *q,
-			   unsigned int idx)
-{
-	struct rx_desc *from = &q->desc[idx];
-	struct rx_desc *to = &q->desc[q->pidx];
-
-	q->sdesc[q->pidx] = q->sdesc[idx];
-	to->addr_lo = from->addr_lo;	/* already big endian */
-	to->addr_hi = from->addr_hi;	/* likewise */
-	wmb();
-	to->len_gen = cpu_to_be32(V_FLD_GEN1(q->gen));
-	to->gen2 = cpu_to_be32(V_FLD_GEN2(q->gen));
-
-	if (++q->pidx == q->size) {
-		q->pidx = 0;
-		q->gen ^= 1;
-	}
-
-	q->credits++;
-	q->pend_cred++;
-	ring_fl_db(adap, q);
-}
-
-/**
- *	alloc_ring - allocate resources for an SGE descriptor ring
- *	@pdev: the PCI device
- *	@nelem: the number of descriptors
- *	@elem_size: the size of each descriptor
- *	@sw_size: the size of the SW state associated with each ring element
- *	@phys: the physical address of the allocated ring
- *	@metadata: address of the array holding the SW state for the ring
- *
- *	Allocates resources for an SGE descriptor ring, such as Tx queues,
- *	free buffer lists, or response queues.  Each SGE ring requires
- *	space for its HW descriptors plus, optionally, space for the SW state
- *	associated with each HW entry (the metadata).  The function returns
- *	three values: the virtual address for the HW ring (the return value
- *	of the function), the physical address of the HW ring, and the address
- *	of the SW ring.
- */
-static void *alloc_ring(struct pci_dev *pdev, size_t nelem, size_t elem_size,
-			size_t sw_size, dma_addr_t * phys, void *metadata)
-{
-	size_t len = nelem * elem_size;
-	void *s = NULL;
-	void *p = dma_alloc_coherent(&pdev->dev, len, phys, GFP_KERNEL);
-
-	if (!p)
-		return NULL;
-	if (sw_size && metadata) {
-		s = kcalloc(nelem, sw_size, GFP_KERNEL);
-
-		if (!s) {
-			dma_free_coherent(&pdev->dev, len, p, *phys);
-			return NULL;
-		}
-		*(void **)metadata = s;
-	}
-	memset(p, 0, len);
-	return p;
-}
-
-/**
- *	t3_reset_qset - reset a sge qset
- *	@q: the queue set
- *
- *	Reset the qset structure.
- *	the NAPI structure is preserved in the event of
- *	the qset's reincarnation, for example during EEH recovery.
- */
-static void t3_reset_qset(struct sge_qset *q)
-{
-	if (q->adap &&
-	    !(q->adap->flags & NAPI_INIT)) {
-		memset(q, 0, sizeof(*q));
-		return;
-	}
-
-	q->adap = NULL;
-	memset(&q->rspq, 0, sizeof(q->rspq));
-	memset(q->fl, 0, sizeof(struct sge_fl) * SGE_RXQ_PER_SET);
-	memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET);
-	q->txq_stopped = 0;
-	q->tx_reclaim_timer.function = NULL; /* for t3_stop_sge_timers() */
-	q->rx_reclaim_timer.function = NULL;
-	q->nomem = 0;
-	napi_free_frags(&q->napi);
-}
-
-
-/**
- *	free_qset - free the resources of an SGE queue set
- *	@adapter: the adapter owning the queue set
- *	@q: the queue set
- *
- *	Release the HW and SW resources associated with an SGE queue set, such
- *	as HW contexts, packet buffers, and descriptor rings.  Traffic to the
- *	queue set must be quiesced prior to calling this.
- */
-static void t3_free_qset(struct adapter *adapter, struct sge_qset *q)
-{
-	int i;
-	struct pci_dev *pdev = adapter->pdev;
-
-	for (i = 0; i < SGE_RXQ_PER_SET; ++i)
-		if (q->fl[i].desc) {
-			spin_lock_irq(&adapter->sge.reg_lock);
-			t3_sge_disable_fl(adapter, q->fl[i].cntxt_id);
-			spin_unlock_irq(&adapter->sge.reg_lock);
-			free_rx_bufs(pdev, &q->fl[i]);
-			kfree(q->fl[i].sdesc);
-			dma_free_coherent(&pdev->dev,
-					  q->fl[i].size *
-					  sizeof(struct rx_desc), q->fl[i].desc,
-					  q->fl[i].phys_addr);
-		}
-
-	for (i = 0; i < SGE_TXQ_PER_SET; ++i)
-		if (q->txq[i].desc) {
-			spin_lock_irq(&adapter->sge.reg_lock);
-			t3_sge_enable_ecntxt(adapter, q->txq[i].cntxt_id, 0);
-			spin_unlock_irq(&adapter->sge.reg_lock);
-			if (q->txq[i].sdesc) {
-				free_tx_desc(adapter, &q->txq[i],
-					     q->txq[i].in_use);
-				kfree(q->txq[i].sdesc);
-			}
-			dma_free_coherent(&pdev->dev,
-					  q->txq[i].size *
-					  sizeof(struct tx_desc),
-					  q->txq[i].desc, q->txq[i].phys_addr);
-			__skb_queue_purge(&q->txq[i].sendq);
-		}
-
-	if (q->rspq.desc) {
-		spin_lock_irq(&adapter->sge.reg_lock);
-		t3_sge_disable_rspcntxt(adapter, q->rspq.cntxt_id);
-		spin_unlock_irq(&adapter->sge.reg_lock);
-		dma_free_coherent(&pdev->dev,
-				  q->rspq.size * sizeof(struct rsp_desc),
-				  q->rspq.desc, q->rspq.phys_addr);
-	}
-
-	t3_reset_qset(q);
-}
-
-/**
- *	init_qset_cntxt - initialize an SGE queue set context info
- *	@qs: the queue set
- *	@id: the queue set id
- *
- *	Initializes the TIDs and context ids for the queues of a queue set.
- */
-static void init_qset_cntxt(struct sge_qset *qs, unsigned int id)
-{
-	qs->rspq.cntxt_id = id;
-	qs->fl[0].cntxt_id = 2 * id;
-	qs->fl[1].cntxt_id = 2 * id + 1;
-	qs->txq[TXQ_ETH].cntxt_id = FW_TUNNEL_SGEEC_START + id;
-	qs->txq[TXQ_ETH].token = FW_TUNNEL_TID_START + id;
-	qs->txq[TXQ_OFLD].cntxt_id = FW_OFLD_SGEEC_START + id;
-	qs->txq[TXQ_CTRL].cntxt_id = FW_CTRL_SGEEC_START + id;
-	qs->txq[TXQ_CTRL].token = FW_CTRL_TID_START + id;
-}
-
-/**
- *	sgl_len - calculates the size of an SGL of the given capacity
- *	@n: the number of SGL entries
- *
- *	Calculates the number of flits needed for a scatter/gather list that
- *	can hold the given number of entries.
- */
-static inline unsigned int sgl_len(unsigned int n)
-{
-	/* alternatively: 3 * (n / 2) + 2 * (n & 1) */
-	return (3 * n) / 2 + (n & 1);
-}
-
-/**
- *	flits_to_desc - returns the num of Tx descriptors for the given flits
- *	@n: the number of flits
- *
- *	Calculates the number of Tx descriptors needed for the supplied number
- *	of flits.
- */
-static inline unsigned int flits_to_desc(unsigned int n)
-{
-	BUG_ON(n >= ARRAY_SIZE(flit_desc_map));
-	return flit_desc_map[n];
-}
-
-/**
- *	get_packet - return the next ingress packet buffer from a free list
- *	@adap: the adapter that received the packet
- *	@fl: the SGE free list holding the packet
- *	@len: the packet length including any SGE padding
- *	@drop_thres: # of remaining buffers before we start dropping packets
- *
- *	Get the next packet from a free list and complete setup of the
- *	sk_buff.  If the packet is small we make a copy and recycle the
- *	original buffer, otherwise we use the original buffer itself.  If a
- *	positive drop threshold is supplied packets are dropped and their
- *	buffers recycled if (a) the number of remaining buffers is under the
- *	threshold and the packet is too big to copy, or (b) the packet should
- *	be copied but there is no memory for the copy.
- */
-static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
-				  unsigned int len, unsigned int drop_thres)
-{
-	struct sk_buff *skb = NULL;
-	struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
-
-	prefetch(sd->skb->data);
-	fl->credits--;
-
-	if (len <= SGE_RX_COPY_THRES) {
-		skb = alloc_skb(len, GFP_ATOMIC);
-		if (likely(skb != NULL)) {
-			__skb_put(skb, len);
-			pci_dma_sync_single_for_cpu(adap->pdev,
-					    dma_unmap_addr(sd, dma_addr), len,
-					    PCI_DMA_FROMDEVICE);
-			memcpy(skb->data, sd->skb->data, len);
-			pci_dma_sync_single_for_device(adap->pdev,
-					    dma_unmap_addr(sd, dma_addr), len,
-					    PCI_DMA_FROMDEVICE);
-		} else if (!drop_thres)
-			goto use_orig_buf;
-recycle:
-		recycle_rx_buf(adap, fl, fl->cidx);
-		return skb;
-	}
-
-	if (unlikely(fl->credits < drop_thres) &&
-	    refill_fl(adap, fl, min(MAX_RX_REFILL, fl->size - fl->credits - 1),
-		      GFP_ATOMIC | __GFP_COMP) == 0)
-		goto recycle;
-
-use_orig_buf:
-	pci_unmap_single(adap->pdev, dma_unmap_addr(sd, dma_addr),
-			 fl->buf_size, PCI_DMA_FROMDEVICE);
-	skb = sd->skb;
-	skb_put(skb, len);
-	__refill_fl(adap, fl);
-	return skb;
-}
-
-/**
- *	get_packet_pg - return the next ingress packet buffer from a free list
- *	@adap: the adapter that received the packet
- *	@fl: the SGE free list holding the packet
- *	@len: the packet length including any SGE padding
- *	@drop_thres: # of remaining buffers before we start dropping packets
- *
- *	Get the next packet from a free list populated with page chunks.
- *	If the packet is small we make a copy and recycle the original buffer,
- *	otherwise we attach the original buffer as a page fragment to a fresh
- *	sk_buff.  If a positive drop threshold is supplied packets are dropped
- *	and their buffers recycled if (a) the number of remaining buffers is
- *	under the threshold and the packet is too big to copy, or (b) there's
- *	no system memory.
- *
- * 	Note: this function is similar to @get_packet but deals with Rx buffers
- * 	that are page chunks rather than sk_buffs.
- */
-static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl,
-				     struct sge_rspq *q, unsigned int len,
-				     unsigned int drop_thres)
-{
-	struct sk_buff *newskb, *skb;
-	struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
-
-	dma_addr_t dma_addr = dma_unmap_addr(sd, dma_addr);
-
-	newskb = skb = q->pg_skb;
-	if (!skb && (len <= SGE_RX_COPY_THRES)) {
-		newskb = alloc_skb(len, GFP_ATOMIC);
-		if (likely(newskb != NULL)) {
-			__skb_put(newskb, len);
-			pci_dma_sync_single_for_cpu(adap->pdev, dma_addr, len,
-					    PCI_DMA_FROMDEVICE);
-			memcpy(newskb->data, sd->pg_chunk.va, len);
-			pci_dma_sync_single_for_device(adap->pdev, dma_addr,
-						       len,
-						       PCI_DMA_FROMDEVICE);
-		} else if (!drop_thres)
-			return NULL;
-recycle:
-		fl->credits--;
-		recycle_rx_buf(adap, fl, fl->cidx);
-		q->rx_recycle_buf++;
-		return newskb;
-	}
-
-	if (unlikely(q->rx_recycle_buf || (!skb && fl->credits <= drop_thres)))
-		goto recycle;
-
-	prefetch(sd->pg_chunk.p_cnt);
-
-	if (!skb)
-		newskb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC);
-
-	if (unlikely(!newskb)) {
-		if (!drop_thres)
-			return NULL;
-		goto recycle;
-	}
-
-	pci_dma_sync_single_for_cpu(adap->pdev, dma_addr, len,
-				    PCI_DMA_FROMDEVICE);
-	(*sd->pg_chunk.p_cnt)--;
-	if (!*sd->pg_chunk.p_cnt && sd->pg_chunk.page != fl->pg_chunk.page)
-		pci_unmap_page(adap->pdev,
-			       sd->pg_chunk.mapping,
-			       fl->alloc_size,
-			       PCI_DMA_FROMDEVICE);
-	if (!skb) {
-		__skb_put(newskb, SGE_RX_PULL_LEN);
-		memcpy(newskb->data, sd->pg_chunk.va, SGE_RX_PULL_LEN);
-		skb_fill_page_desc(newskb, 0, sd->pg_chunk.page,
-				   sd->pg_chunk.offset + SGE_RX_PULL_LEN,
-				   len - SGE_RX_PULL_LEN);
-		newskb->len = len;
-		newskb->data_len = len - SGE_RX_PULL_LEN;
-		newskb->truesize += newskb->data_len;
-	} else {
-		skb_fill_page_desc(newskb, skb_shinfo(newskb)->nr_frags,
-				   sd->pg_chunk.page,
-				   sd->pg_chunk.offset, len);
-		newskb->len += len;
-		newskb->data_len += len;
-		newskb->truesize += len;
-	}
-
-	fl->credits--;
-	/*
-	 * We do not refill FLs here, we let the caller do it to overlap a
-	 * prefetch.
-	 */
-	return newskb;
-}
-
-/**
- *	get_imm_packet - return the next ingress packet buffer from a response
- *	@resp: the response descriptor containing the packet data
- *
- *	Return a packet containing the immediate data of the given response.
- */
-static inline struct sk_buff *get_imm_packet(const struct rsp_desc *resp)
-{
-	struct sk_buff *skb = alloc_skb(IMMED_PKT_SIZE, GFP_ATOMIC);
-
-	if (skb) {
-		__skb_put(skb, IMMED_PKT_SIZE);
-		skb_copy_to_linear_data(skb, resp->imm_data, IMMED_PKT_SIZE);
-	}
-	return skb;
-}
-
-/**
- *	calc_tx_descs - calculate the number of Tx descriptors for a packet
- *	@skb: the packet
- *
- * 	Returns the number of Tx descriptors needed for the given Ethernet
- * 	packet.  Ethernet packets require addition of WR and CPL headers.
- */
-static inline unsigned int calc_tx_descs(const struct sk_buff *skb)
-{
-	unsigned int flits;
-
-	if (skb->len <= WR_LEN - sizeof(struct cpl_tx_pkt))
-		return 1;
-
-	flits = sgl_len(skb_shinfo(skb)->nr_frags + 1) + 2;
-	if (skb_shinfo(skb)->gso_size)
-		flits++;
-	return flits_to_desc(flits);
-}
-
-/**
- *	make_sgl - populate a scatter/gather list for a packet
- *	@skb: the packet
- *	@sgp: the SGL to populate
- *	@start: start address of skb main body data to include in the SGL
- *	@len: length of skb main body data to include in the SGL
- *	@pdev: the PCI device
- *
- *	Generates a scatter/gather list for the buffers that make up a packet
- *	and returns the SGL size in 8-byte words.  The caller must size the SGL
- *	appropriately.
- */
-static inline unsigned int make_sgl(const struct sk_buff *skb,
-				    struct sg_ent *sgp, unsigned char *start,
-				    unsigned int len, struct pci_dev *pdev)
-{
-	dma_addr_t mapping;
-	unsigned int i, j = 0, nfrags;
-
-	if (len) {
-		mapping = pci_map_single(pdev, start, len, PCI_DMA_TODEVICE);
-		sgp->len[0] = cpu_to_be32(len);
-		sgp->addr[0] = cpu_to_be64(mapping);
-		j = 1;
-	}
-
-	nfrags = skb_shinfo(skb)->nr_frags;
-	for (i = 0; i < nfrags; i++) {
-		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
-		mapping = pci_map_page(pdev, frag->page, frag->page_offset,
-				       frag->size, PCI_DMA_TODEVICE);
-		sgp->len[j] = cpu_to_be32(frag->size);
-		sgp->addr[j] = cpu_to_be64(mapping);
-		j ^= 1;
-		if (j == 0)
-			++sgp;
-	}
-	if (j)
-		sgp->len[j] = 0;
-	return ((nfrags + (len != 0)) * 3) / 2 + j;
-}
-
-/**
- *	check_ring_tx_db - check and potentially ring a Tx queue's doorbell
- *	@adap: the adapter
- *	@q: the Tx queue
- *
- *	Ring the doorbel if a Tx queue is asleep.  There is a natural race,
- *	where the HW is going to sleep just after we checked, however,
- *	then the interrupt handler will detect the outstanding TX packet
- *	and ring the doorbell for us.
- *
- *	When GTS is disabled we unconditionally ring the doorbell.
- */
-static inline void check_ring_tx_db(struct adapter *adap, struct sge_txq *q)
-{
-#if USE_GTS
-	clear_bit(TXQ_LAST_PKT_DB, &q->flags);
-	if (test_and_set_bit(TXQ_RUNNING, &q->flags) == 0) {
-		set_bit(TXQ_LAST_PKT_DB, &q->flags);
-		t3_write_reg(adap, A_SG_KDOORBELL,
-			     F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
-	}
-#else
-	wmb();			/* write descriptors before telling HW */
-	t3_write_reg(adap, A_SG_KDOORBELL,
-		     F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
-#endif
-}
-
-static inline void wr_gen2(struct tx_desc *d, unsigned int gen)
-{
-#if SGE_NUM_GENBITS == 2
-	d->flit[TX_DESC_FLITS - 1] = cpu_to_be64(gen);
-#endif
-}
-
-/**
- *	write_wr_hdr_sgl - write a WR header and, optionally, SGL
- *	@ndesc: number of Tx descriptors spanned by the SGL
- *	@skb: the packet corresponding to the WR
- *	@d: first Tx descriptor to be written
- *	@pidx: index of above descriptors
- *	@q: the SGE Tx queue
- *	@sgl: the SGL
- *	@flits: number of flits to the start of the SGL in the first descriptor
- *	@sgl_flits: the SGL size in flits
- *	@gen: the Tx descriptor generation
- *	@wr_hi: top 32 bits of WR header based on WR type (big endian)
- *	@wr_lo: low 32 bits of WR header based on WR type (big endian)
- *
- *	Write a work request header and an associated SGL.  If the SGL is
- *	small enough to fit into one Tx descriptor it has already been written
- *	and we just need to write the WR header.  Otherwise we distribute the
- *	SGL across the number of descriptors it spans.
- */
-static void write_wr_hdr_sgl(unsigned int ndesc, struct sk_buff *skb,
-			     struct tx_desc *d, unsigned int pidx,
-			     const struct sge_txq *q,
-			     const struct sg_ent *sgl,
-			     unsigned int flits, unsigned int sgl_flits,
-			     unsigned int gen, __be32 wr_hi,
-			     __be32 wr_lo)
-{
-	struct work_request_hdr *wrp = (struct work_request_hdr *)d;
-	struct tx_sw_desc *sd = &q->sdesc[pidx];
-
-	sd->skb = skb;
-	if (need_skb_unmap()) {
-		sd->fragidx = 0;
-		sd->addr_idx = 0;
-		sd->sflit = flits;
-	}
-
-	if (likely(ndesc == 1)) {
-		sd->eop = 1;
-		wrp->wr_hi = htonl(F_WR_SOP | F_WR_EOP | V_WR_DATATYPE(1) |
-				   V_WR_SGLSFLT(flits)) | wr_hi;
-		wmb();
-		wrp->wr_lo = htonl(V_WR_LEN(flits + sgl_flits) |
-				   V_WR_GEN(gen)) | wr_lo;
-		wr_gen2(d, gen);
-	} else {
-		unsigned int ogen = gen;
-		const u64 *fp = (const u64 *)sgl;
-		struct work_request_hdr *wp = wrp;
-
-		wrp->wr_hi = htonl(F_WR_SOP | V_WR_DATATYPE(1) |
-				   V_WR_SGLSFLT(flits)) | wr_hi;
-
-		while (sgl_flits) {
-			unsigned int avail = WR_FLITS - flits;
-
-			if (avail > sgl_flits)
-				avail = sgl_flits;
-			memcpy(&d->flit[flits], fp, avail * sizeof(*fp));
-			sgl_flits -= avail;
-			ndesc--;
-			if (!sgl_flits)
-				break;
-
-			fp += avail;
-			d++;
-			sd->eop = 0;
-			sd++;
-			if (++pidx == q->size) {
-				pidx = 0;
-				gen ^= 1;
-				d = q->desc;
-				sd = q->sdesc;
-			}
-
-			sd->skb = skb;
-			wrp = (struct work_request_hdr *)d;
-			wrp->wr_hi = htonl(V_WR_DATATYPE(1) |
-					   V_WR_SGLSFLT(1)) | wr_hi;
-			wrp->wr_lo = htonl(V_WR_LEN(min(WR_FLITS,
-							sgl_flits + 1)) |
-					   V_WR_GEN(gen)) | wr_lo;
-			wr_gen2(d, gen);
-			flits = 1;
-		}
-		sd->eop = 1;
-		wrp->wr_hi |= htonl(F_WR_EOP);
-		wmb();
-		wp->wr_lo = htonl(V_WR_LEN(WR_FLITS) | V_WR_GEN(ogen)) | wr_lo;
-		wr_gen2((struct tx_desc *)wp, ogen);
-		WARN_ON(ndesc != 0);
-	}
-}
-
-/**
- *	write_tx_pkt_wr - write a TX_PKT work request
- *	@adap: the adapter
- *	@skb: the packet to send
- *	@pi: the egress interface
- *	@pidx: index of the first Tx descriptor to write
- *	@gen: the generation value to use
- *	@q: the Tx queue
- *	@ndesc: number of descriptors the packet will occupy
- *	@compl: the value of the COMPL bit to use
- *
- *	Generate a TX_PKT work request to send the supplied packet.
- */
-static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb,
-			    const struct port_info *pi,
-			    unsigned int pidx, unsigned int gen,
-			    struct sge_txq *q, unsigned int ndesc,
-			    unsigned int compl)
-{
-	unsigned int flits, sgl_flits, cntrl, tso_info;
-	struct sg_ent *sgp, sgl[MAX_SKB_FRAGS / 2 + 1];
-	struct tx_desc *d = &q->desc[pidx];
-	struct cpl_tx_pkt *cpl = (struct cpl_tx_pkt *)d;
-
-	cpl->len = htonl(skb->len);
-	cntrl = V_TXPKT_INTF(pi->port_id);
-
-	if (vlan_tx_tag_present(skb))
-		cntrl |= F_TXPKT_VLAN_VLD | V_TXPKT_VLAN(vlan_tx_tag_get(skb));
-
-	tso_info = V_LSO_MSS(skb_shinfo(skb)->gso_size);
-	if (tso_info) {
-		int eth_type;
-		struct cpl_tx_pkt_lso *hdr = (struct cpl_tx_pkt_lso *)cpl;
-
-		d->flit[2] = 0;
-		cntrl |= V_TXPKT_OPCODE(CPL_TX_PKT_LSO);
-		hdr->cntrl = htonl(cntrl);
-		eth_type = skb_network_offset(skb) == ETH_HLEN ?
-		    CPL_ETH_II : CPL_ETH_II_VLAN;
-		tso_info |= V_LSO_ETH_TYPE(eth_type) |
-		    V_LSO_IPHDR_WORDS(ip_hdr(skb)->ihl) |
-		    V_LSO_TCPHDR_WORDS(tcp_hdr(skb)->doff);
-		hdr->lso_info = htonl(tso_info);
-		flits = 3;
-	} else {
-		cntrl |= V_TXPKT_OPCODE(CPL_TX_PKT);
-		cntrl |= F_TXPKT_IPCSUM_DIS;	/* SW calculates IP csum */
-		cntrl |= V_TXPKT_L4CSUM_DIS(skb->ip_summed != CHECKSUM_PARTIAL);
-		cpl->cntrl = htonl(cntrl);
-
-		if (skb->len <= WR_LEN - sizeof(*cpl)) {
-			q->sdesc[pidx].skb = NULL;
-			if (!skb->data_len)
-				skb_copy_from_linear_data(skb, &d->flit[2],
-							  skb->len);
-			else
-				skb_copy_bits(skb, 0, &d->flit[2], skb->len);
-
-			flits = (skb->len + 7) / 8 + 2;
-			cpl->wr.wr_hi = htonl(V_WR_BCNTLFLT(skb->len & 7) |
-					      V_WR_OP(FW_WROPCODE_TUNNEL_TX_PKT)
-					      | F_WR_SOP | F_WR_EOP | compl);
-			wmb();
-			cpl->wr.wr_lo = htonl(V_WR_LEN(flits) | V_WR_GEN(gen) |
-					      V_WR_TID(q->token));
-			wr_gen2(d, gen);
-			kfree_skb(skb);
-			return;
-		}
-
-		flits = 2;
-	}
-
-	sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl;
-	sgl_flits = make_sgl(skb, sgp, skb->data, skb_headlen(skb), adap->pdev);
-
-	write_wr_hdr_sgl(ndesc, skb, d, pidx, q, sgl, flits, sgl_flits, gen,
-			 htonl(V_WR_OP(FW_WROPCODE_TUNNEL_TX_PKT) | compl),
-			 htonl(V_WR_TID(q->token)));
-}
-
-static inline void t3_stop_tx_queue(struct netdev_queue *txq,
-				    struct sge_qset *qs, struct sge_txq *q)
-{
-	netif_tx_stop_queue(txq);
-	set_bit(TXQ_ETH, &qs->txq_stopped);
-	q->stops++;
-}
-
-/**
- *	eth_xmit - add a packet to the Ethernet Tx queue
- *	@skb: the packet
- *	@dev: the egress net device
- *
- *	Add a packet to an SGE Tx queue.  Runs with softirqs disabled.
- */
-netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	int qidx;
-	unsigned int ndesc, pidx, credits, gen, compl;
-	const struct port_info *pi = netdev_priv(dev);
-	struct adapter *adap = pi->adapter;
-	struct netdev_queue *txq;
-	struct sge_qset *qs;
-	struct sge_txq *q;
-
-	/*
-	 * The chip min packet length is 9 octets but play safe and reject
-	 * anything shorter than an Ethernet header.
-	 */
-	if (unlikely(skb->len < ETH_HLEN)) {
-		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-
-	qidx = skb_get_queue_mapping(skb);
-	qs = &pi->qs[qidx];
-	q = &qs->txq[TXQ_ETH];
-	txq = netdev_get_tx_queue(dev, qidx);
-
-	reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
-
-	credits = q->size - q->in_use;
-	ndesc = calc_tx_descs(skb);
-
-	if (unlikely(credits < ndesc)) {
-		t3_stop_tx_queue(txq, qs, q);
-		dev_err(&adap->pdev->dev,
-			"%s: Tx ring %u full while queue awake!\n",
-			dev->name, q->cntxt_id & 7);
-		return NETDEV_TX_BUSY;
-	}
-
-	q->in_use += ndesc;
-	if (unlikely(credits - ndesc < q->stop_thres)) {
-		t3_stop_tx_queue(txq, qs, q);
-
-		if (should_restart_tx(q) &&
-		    test_and_clear_bit(TXQ_ETH, &qs->txq_stopped)) {
-			q->restarts++;
-			netif_tx_start_queue(txq);
-		}
-	}
-
-	gen = q->gen;
-	q->unacked += ndesc;
-	compl = (q->unacked & 8) << (S_WR_COMPL - 3);
-	q->unacked &= 7;
-	pidx = q->pidx;
-	q->pidx += ndesc;
-	if (q->pidx >= q->size) {
-		q->pidx -= q->size;
-		q->gen ^= 1;
-	}
-
-	/* update port statistics */
-	if (skb->ip_summed == CHECKSUM_COMPLETE)
-		qs->port_stats[SGE_PSTAT_TX_CSUM]++;
-	if (skb_shinfo(skb)->gso_size)
-		qs->port_stats[SGE_PSTAT_TSO]++;
-	if (vlan_tx_tag_present(skb))
-		qs->port_stats[SGE_PSTAT_VLANINS]++;
-
-	/*
-	 * We do not use Tx completion interrupts to free DMAd Tx packets.
-	 * This is good for performance but means that we rely on new Tx
-	 * packets arriving to run the destructors of completed packets,
-	 * which open up space in their sockets' send queues.  Sometimes
-	 * we do not get such new packets causing Tx to stall.  A single
-	 * UDP transmitter is a good example of this situation.  We have
-	 * a clean up timer that periodically reclaims completed packets
-	 * but it doesn't run often enough (nor do we want it to) to prevent
-	 * lengthy stalls.  A solution to this problem is to run the
-	 * destructor early, after the packet is queued but before it's DMAd.
-	 * A cons is that we lie to socket memory accounting, but the amount
-	 * of extra memory is reasonable (limited by the number of Tx
-	 * descriptors), the packets do actually get freed quickly by new
-	 * packets almost always, and for protocols like TCP that wait for
-	 * acks to really free up the data the extra memory is even less.
-	 * On the positive side we run the destructors on the sending CPU
-	 * rather than on a potentially different completing CPU, usually a
-	 * good thing.  We also run them without holding our Tx queue lock,
-	 * unlike what reclaim_completed_tx() would otherwise do.
-	 *
-	 * Run the destructor before telling the DMA engine about the packet
-	 * to make sure it doesn't complete and get freed prematurely.
-	 */
-	if (likely(!skb_shared(skb)))
-		skb_orphan(skb);
-
-	write_tx_pkt_wr(adap, skb, pi, pidx, gen, q, ndesc, compl);
-	check_ring_tx_db(adap, q);
-	return NETDEV_TX_OK;
-}
-
-/**
- *	write_imm - write a packet into a Tx descriptor as immediate data
- *	@d: the Tx descriptor to write
- *	@skb: the packet
- *	@len: the length of packet data to write as immediate data
- *	@gen: the generation bit value to write
- *
- *	Writes a packet as immediate data into a Tx descriptor.  The packet
- *	contains a work request at its beginning.  We must write the packet
- *	carefully so the SGE doesn't read it accidentally before it's written
- *	in its entirety.
- */
-static inline void write_imm(struct tx_desc *d, struct sk_buff *skb,
-			     unsigned int len, unsigned int gen)
-{
-	struct work_request_hdr *from = (struct work_request_hdr *)skb->data;
-	struct work_request_hdr *to = (struct work_request_hdr *)d;
-
-	if (likely(!skb->data_len))
-		memcpy(&to[1], &from[1], len - sizeof(*from));
-	else
-		skb_copy_bits(skb, sizeof(*from), &to[1], len - sizeof(*from));
-
-	to->wr_hi = from->wr_hi | htonl(F_WR_SOP | F_WR_EOP |
-					V_WR_BCNTLFLT(len & 7));
-	wmb();
-	to->wr_lo = from->wr_lo | htonl(V_WR_GEN(gen) |
-					V_WR_LEN((len + 7) / 8));
-	wr_gen2(d, gen);
-	kfree_skb(skb);
-}
-
-/**
- *	check_desc_avail - check descriptor availability on a send queue
- *	@adap: the adapter
- *	@q: the send queue
- *	@skb: the packet needing the descriptors
- *	@ndesc: the number of Tx descriptors needed
- *	@qid: the Tx queue number in its queue set (TXQ_OFLD or TXQ_CTRL)
- *
- *	Checks if the requested number of Tx descriptors is available on an
- *	SGE send queue.  If the queue is already suspended or not enough
- *	descriptors are available the packet is queued for later transmission.
- *	Must be called with the Tx queue locked.
- *
- *	Returns 0 if enough descriptors are available, 1 if there aren't
- *	enough descriptors and the packet has been queued, and 2 if the caller
- *	needs to retry because there weren't enough descriptors at the
- *	beginning of the call but some freed up in the mean time.
- */
-static inline int check_desc_avail(struct adapter *adap, struct sge_txq *q,
-				   struct sk_buff *skb, unsigned int ndesc,
-				   unsigned int qid)
-{
-	if (unlikely(!skb_queue_empty(&q->sendq))) {
-	      addq_exit:__skb_queue_tail(&q->sendq, skb);
-		return 1;
-	}
-	if (unlikely(q->size - q->in_use < ndesc)) {
-		struct sge_qset *qs = txq_to_qset(q, qid);
-
-		set_bit(qid, &qs->txq_stopped);
-		smp_mb__after_clear_bit();
-
-		if (should_restart_tx(q) &&
-		    test_and_clear_bit(qid, &qs->txq_stopped))
-			return 2;
-
-		q->stops++;
-		goto addq_exit;
-	}
-	return 0;
-}
-
-/**
- *	reclaim_completed_tx_imm - reclaim completed control-queue Tx descs
- *	@q: the SGE control Tx queue
- *
- *	This is a variant of reclaim_completed_tx() that is used for Tx queues
- *	that send only immediate data (presently just the control queues) and
- *	thus do not have any sk_buffs to release.
- */
-static inline void reclaim_completed_tx_imm(struct sge_txq *q)
-{
-	unsigned int reclaim = q->processed - q->cleaned;
-
-	q->in_use -= reclaim;
-	q->cleaned += reclaim;
-}
-
-static inline int immediate(const struct sk_buff *skb)
-{
-	return skb->len <= WR_LEN;
-}
-
-/**
- *	ctrl_xmit - send a packet through an SGE control Tx queue
- *	@adap: the adapter
- *	@q: the control queue
- *	@skb: the packet
- *
- *	Send a packet through an SGE control Tx queue.  Packets sent through
- *	a control queue must fit entirely as immediate data in a single Tx
- *	descriptor and have no page fragments.
- */
-static int ctrl_xmit(struct adapter *adap, struct sge_txq *q,
-		     struct sk_buff *skb)
-{
-	int ret;
-	struct work_request_hdr *wrp = (struct work_request_hdr *)skb->data;
-
-	if (unlikely(!immediate(skb))) {
-		WARN_ON(1);
-		dev_kfree_skb(skb);
-		return NET_XMIT_SUCCESS;
-	}
-
-	wrp->wr_hi |= htonl(F_WR_SOP | F_WR_EOP);
-	wrp->wr_lo = htonl(V_WR_TID(q->token));
-
-	spin_lock(&q->lock);
-      again:reclaim_completed_tx_imm(q);
-
-	ret = check_desc_avail(adap, q, skb, 1, TXQ_CTRL);
-	if (unlikely(ret)) {
-		if (ret == 1) {
-			spin_unlock(&q->lock);
-			return NET_XMIT_CN;
-		}
-		goto again;
-	}
-
-	write_imm(&q->desc[q->pidx], skb, skb->len, q->gen);
-
-	q->in_use++;
-	if (++q->pidx >= q->size) {
-		q->pidx = 0;
-		q->gen ^= 1;
-	}
-	spin_unlock(&q->lock);
-	wmb();
-	t3_write_reg(adap, A_SG_KDOORBELL,
-		     F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
-	return NET_XMIT_SUCCESS;
-}
-
-/**
- *	restart_ctrlq - restart a suspended control queue
- *	@qs: the queue set cotaining the control queue
- *
- *	Resumes transmission on a suspended Tx control queue.
- */
-static void restart_ctrlq(unsigned long data)
-{
-	struct sk_buff *skb;
-	struct sge_qset *qs = (struct sge_qset *)data;
-	struct sge_txq *q = &qs->txq[TXQ_CTRL];
-
-	spin_lock(&q->lock);
-      again:reclaim_completed_tx_imm(q);
-
-	while (q->in_use < q->size &&
-	       (skb = __skb_dequeue(&q->sendq)) != NULL) {
-
-		write_imm(&q->desc[q->pidx], skb, skb->len, q->gen);
-
-		if (++q->pidx >= q->size) {
-			q->pidx = 0;
-			q->gen ^= 1;
-		}
-		q->in_use++;
-	}
-
-	if (!skb_queue_empty(&q->sendq)) {
-		set_bit(TXQ_CTRL, &qs->txq_stopped);
-		smp_mb__after_clear_bit();
-
-		if (should_restart_tx(q) &&
-		    test_and_clear_bit(TXQ_CTRL, &qs->txq_stopped))
-			goto again;
-		q->stops++;
-	}
-
-	spin_unlock(&q->lock);
-	wmb();
-	t3_write_reg(qs->adap, A_SG_KDOORBELL,
-		     F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
-}
-
-/*
- * Send a management message through control queue 0
- */
-int t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb)
-{
-	int ret;
-	local_bh_disable();
-	ret = ctrl_xmit(adap, &adap->sge.qs[0].txq[TXQ_CTRL], skb);
-	local_bh_enable();
-
-	return ret;
-}
-
-/**
- *	deferred_unmap_destructor - unmap a packet when it is freed
- *	@skb: the packet
- *
- *	This is the packet destructor used for Tx packets that need to remain
- *	mapped until they are freed rather than until their Tx descriptors are
- *	freed.
- */
-static void deferred_unmap_destructor(struct sk_buff *skb)
-{
-	int i;
-	const dma_addr_t *p;
-	const struct skb_shared_info *si;
-	const struct deferred_unmap_info *dui;
-
-	dui = (struct deferred_unmap_info *)skb->head;
-	p = dui->addr;
-
-	if (skb->tail - skb->transport_header)
-		pci_unmap_single(dui->pdev, *p++,
-				 skb->tail - skb->transport_header,
-				 PCI_DMA_TODEVICE);
-
-	si = skb_shinfo(skb);
-	for (i = 0; i < si->nr_frags; i++)
-		pci_unmap_page(dui->pdev, *p++, si->frags[i].size,
-			       PCI_DMA_TODEVICE);
-}
-
-static void setup_deferred_unmapping(struct sk_buff *skb, struct pci_dev *pdev,
-				     const struct sg_ent *sgl, int sgl_flits)
-{
-	dma_addr_t *p;
-	struct deferred_unmap_info *dui;
-
-	dui = (struct deferred_unmap_info *)skb->head;
-	dui->pdev = pdev;
-	for (p = dui->addr; sgl_flits >= 3; sgl++, sgl_flits -= 3) {
-		*p++ = be64_to_cpu(sgl->addr[0]);
-		*p++ = be64_to_cpu(sgl->addr[1]);
-	}
-	if (sgl_flits)
-		*p = be64_to_cpu(sgl->addr[0]);
-}
-
-/**
- *	write_ofld_wr - write an offload work request
- *	@adap: the adapter
- *	@skb: the packet to send
- *	@q: the Tx queue
- *	@pidx: index of the first Tx descriptor to write
- *	@gen: the generation value to use
- *	@ndesc: number of descriptors the packet will occupy
- *
- *	Write an offload work request to send the supplied packet.  The packet
- *	data already carry the work request with most fields populated.
- */
-static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb,
-			  struct sge_txq *q, unsigned int pidx,
-			  unsigned int gen, unsigned int ndesc)
-{
-	unsigned int sgl_flits, flits;
-	struct work_request_hdr *from;
-	struct sg_ent *sgp, sgl[MAX_SKB_FRAGS / 2 + 1];
-	struct tx_desc *d = &q->desc[pidx];
-
-	if (immediate(skb)) {
-		q->sdesc[pidx].skb = NULL;
-		write_imm(d, skb, skb->len, gen);
-		return;
-	}
-
-	/* Only TX_DATA builds SGLs */
-
-	from = (struct work_request_hdr *)skb->data;
-	memcpy(&d->flit[1], &from[1],
-	       skb_transport_offset(skb) - sizeof(*from));
-
-	flits = skb_transport_offset(skb) / 8;
-	sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl;
-	sgl_flits = make_sgl(skb, sgp, skb_transport_header(skb),
-			     skb->tail - skb->transport_header,
-			     adap->pdev);
-	if (need_skb_unmap()) {
-		setup_deferred_unmapping(skb, adap->pdev, sgp, sgl_flits);
-		skb->destructor = deferred_unmap_destructor;
-	}
-
-	write_wr_hdr_sgl(ndesc, skb, d, pidx, q, sgl, flits, sgl_flits,
-			 gen, from->wr_hi, from->wr_lo);
-}
-
-/**
- *	calc_tx_descs_ofld - calculate # of Tx descriptors for an offload packet
- *	@skb: the packet
- *
- * 	Returns the number of Tx descriptors needed for the given offload
- * 	packet.  These packets are already fully constructed.
- */
-static inline unsigned int calc_tx_descs_ofld(const struct sk_buff *skb)
-{
-	unsigned int flits, cnt;
-
-	if (skb->len <= WR_LEN)
-		return 1;	/* packet fits as immediate data */
-
-	flits = skb_transport_offset(skb) / 8;	/* headers */
-	cnt = skb_shinfo(skb)->nr_frags;
-	if (skb->tail != skb->transport_header)
-		cnt++;
-	return flits_to_desc(flits + sgl_len(cnt));
-}
-
-/**
- *	ofld_xmit - send a packet through an offload queue
- *	@adap: the adapter
- *	@q: the Tx offload queue
- *	@skb: the packet
- *
- *	Send an offload packet through an SGE offload queue.
- */
-static int ofld_xmit(struct adapter *adap, struct sge_txq *q,
-		     struct sk_buff *skb)
-{
-	int ret;
-	unsigned int ndesc = calc_tx_descs_ofld(skb), pidx, gen;
-
-	spin_lock(&q->lock);
-again:	reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
-
-	ret = check_desc_avail(adap, q, skb, ndesc, TXQ_OFLD);
-	if (unlikely(ret)) {
-		if (ret == 1) {
-			skb->priority = ndesc;	/* save for restart */
-			spin_unlock(&q->lock);
-			return NET_XMIT_CN;
-		}
-		goto again;
-	}
-
-	gen = q->gen;
-	q->in_use += ndesc;
-	pidx = q->pidx;
-	q->pidx += ndesc;
-	if (q->pidx >= q->size) {
-		q->pidx -= q->size;
-		q->gen ^= 1;
-	}
-	spin_unlock(&q->lock);
-
-	write_ofld_wr(adap, skb, q, pidx, gen, ndesc);
-	check_ring_tx_db(adap, q);
-	return NET_XMIT_SUCCESS;
-}
-
-/**
- *	restart_offloadq - restart a suspended offload queue
- *	@qs: the queue set cotaining the offload queue
- *
- *	Resumes transmission on a suspended Tx offload queue.
- */
-static void restart_offloadq(unsigned long data)
-{
-	struct sk_buff *skb;
-	struct sge_qset *qs = (struct sge_qset *)data;
-	struct sge_txq *q = &qs->txq[TXQ_OFLD];
-	const struct port_info *pi = netdev_priv(qs->netdev);
-	struct adapter *adap = pi->adapter;
-
-	spin_lock(&q->lock);
-again:	reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
-
-	while ((skb = skb_peek(&q->sendq)) != NULL) {
-		unsigned int gen, pidx;
-		unsigned int ndesc = skb->priority;
-
-		if (unlikely(q->size - q->in_use < ndesc)) {
-			set_bit(TXQ_OFLD, &qs->txq_stopped);
-			smp_mb__after_clear_bit();
-
-			if (should_restart_tx(q) &&
-			    test_and_clear_bit(TXQ_OFLD, &qs->txq_stopped))
-				goto again;
-			q->stops++;
-			break;
-		}
-
-		gen = q->gen;
-		q->in_use += ndesc;
-		pidx = q->pidx;
-		q->pidx += ndesc;
-		if (q->pidx >= q->size) {
-			q->pidx -= q->size;
-			q->gen ^= 1;
-		}
-		__skb_unlink(skb, &q->sendq);
-		spin_unlock(&q->lock);
-
-		write_ofld_wr(adap, skb, q, pidx, gen, ndesc);
-		spin_lock(&q->lock);
-	}
-	spin_unlock(&q->lock);
-
-#if USE_GTS
-	set_bit(TXQ_RUNNING, &q->flags);
-	set_bit(TXQ_LAST_PKT_DB, &q->flags);
-#endif
-	wmb();
-	t3_write_reg(adap, A_SG_KDOORBELL,
-		     F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
-}
-
-/**
- *	queue_set - return the queue set a packet should use
- *	@skb: the packet
- *
- *	Maps a packet to the SGE queue set it should use.  The desired queue
- *	set is carried in bits 1-3 in the packet's priority.
- */
-static inline int queue_set(const struct sk_buff *skb)
-{
-	return skb->priority >> 1;
-}
-
-/**
- *	is_ctrl_pkt - return whether an offload packet is a control packet
- *	@skb: the packet
- *
- *	Determines whether an offload packet should use an OFLD or a CTRL
- *	Tx queue.  This is indicated by bit 0 in the packet's priority.
- */
-static inline int is_ctrl_pkt(const struct sk_buff *skb)
-{
-	return skb->priority & 1;
-}
-
-/**
- *	t3_offload_tx - send an offload packet
- *	@tdev: the offload device to send to
- *	@skb: the packet
- *
- *	Sends an offload packet.  We use the packet priority to select the
- *	appropriate Tx queue as follows: bit 0 indicates whether the packet
- *	should be sent as regular or control, bits 1-3 select the queue set.
- */
-int t3_offload_tx(struct t3cdev *tdev, struct sk_buff *skb)
-{
-	struct adapter *adap = tdev2adap(tdev);
-	struct sge_qset *qs = &adap->sge.qs[queue_set(skb)];
-
-	if (unlikely(is_ctrl_pkt(skb)))
-		return ctrl_xmit(adap, &qs->txq[TXQ_CTRL], skb);
-
-	return ofld_xmit(adap, &qs->txq[TXQ_OFLD], skb);
-}
-
-/**
- *	offload_enqueue - add an offload packet to an SGE offload receive queue
- *	@q: the SGE response queue
- *	@skb: the packet
- *
- *	Add a new offload packet to an SGE response queue's offload packet
- *	queue.  If the packet is the first on the queue it schedules the RX
- *	softirq to process the queue.
- */
-static inline void offload_enqueue(struct sge_rspq *q, struct sk_buff *skb)
-{
-	int was_empty = skb_queue_empty(&q->rx_queue);
-
-	__skb_queue_tail(&q->rx_queue, skb);
-
-	if (was_empty) {
-		struct sge_qset *qs = rspq_to_qset(q);
-
-		napi_schedule(&qs->napi);
-	}
-}
-
-/**
- *	deliver_partial_bundle - deliver a (partial) bundle of Rx offload pkts
- *	@tdev: the offload device that will be receiving the packets
- *	@q: the SGE response queue that assembled the bundle
- *	@skbs: the partial bundle
- *	@n: the number of packets in the bundle
- *
- *	Delivers a (partial) bundle of Rx offload packets to an offload device.
- */
-static inline void deliver_partial_bundle(struct t3cdev *tdev,
-					  struct sge_rspq *q,
-					  struct sk_buff *skbs[], int n)
-{
-	if (n) {
-		q->offload_bundles++;
-		tdev->recv(tdev, skbs, n);
-	}
-}
-
-/**
- *	ofld_poll - NAPI handler for offload packets in interrupt mode
- *	@dev: the network device doing the polling
- *	@budget: polling budget
- *
- *	The NAPI handler for offload packets when a response queue is serviced
- *	by the hard interrupt handler, i.e., when it's operating in non-polling
- *	mode.  Creates small packet batches and sends them through the offload
- *	receive handler.  Batches need to be of modest size as we do prefetches
- *	on the packets in each.
- */
-static int ofld_poll(struct napi_struct *napi, int budget)
-{
-	struct sge_qset *qs = container_of(napi, struct sge_qset, napi);
-	struct sge_rspq *q = &qs->rspq;
-	struct adapter *adapter = qs->adap;
-	int work_done = 0;
-
-	while (work_done < budget) {
-		struct sk_buff *skb, *tmp, *skbs[RX_BUNDLE_SIZE];
-		struct sk_buff_head queue;
-		int ngathered;
-
-		spin_lock_irq(&q->lock);
-		__skb_queue_head_init(&queue);
-		skb_queue_splice_init(&q->rx_queue, &queue);
-		if (skb_queue_empty(&queue)) {
-			napi_complete(napi);
-			spin_unlock_irq(&q->lock);
-			return work_done;
-		}
-		spin_unlock_irq(&q->lock);
-
-		ngathered = 0;
-		skb_queue_walk_safe(&queue, skb, tmp) {
-			if (work_done >= budget)
-				break;
-			work_done++;
-
-			__skb_unlink(skb, &queue);
-			prefetch(skb->data);
-			skbs[ngathered] = skb;
-			if (++ngathered == RX_BUNDLE_SIZE) {
-				q->offload_bundles++;
-				adapter->tdev.recv(&adapter->tdev, skbs,
-						   ngathered);
-				ngathered = 0;
-			}
-		}
-		if (!skb_queue_empty(&queue)) {
-			/* splice remaining packets back onto Rx queue */
-			spin_lock_irq(&q->lock);
-			skb_queue_splice(&queue, &q->rx_queue);
-			spin_unlock_irq(&q->lock);
-		}
-		deliver_partial_bundle(&adapter->tdev, q, skbs, ngathered);
-	}
-
-	return work_done;
-}
-
-/**
- *	rx_offload - process a received offload packet
- *	@tdev: the offload device receiving the packet
- *	@rq: the response queue that received the packet
- *	@skb: the packet
- *	@rx_gather: a gather list of packets if we are building a bundle
- *	@gather_idx: index of the next available slot in the bundle
- *
- *	Process an ingress offload pakcet and add it to the offload ingress
- *	queue. 	Returns the index of the next available slot in the bundle.
- */
-static inline int rx_offload(struct t3cdev *tdev, struct sge_rspq *rq,
-			     struct sk_buff *skb, struct sk_buff *rx_gather[],
-			     unsigned int gather_idx)
-{
-	skb_reset_mac_header(skb);
-	skb_reset_network_header(skb);
-	skb_reset_transport_header(skb);
-
-	if (rq->polling) {
-		rx_gather[gather_idx++] = skb;
-		if (gather_idx == RX_BUNDLE_SIZE) {
-			tdev->recv(tdev, rx_gather, RX_BUNDLE_SIZE);
-			gather_idx = 0;
-			rq->offload_bundles++;
-		}
-	} else
-		offload_enqueue(rq, skb);
-
-	return gather_idx;
-}
-
-/**
- *	restart_tx - check whether to restart suspended Tx queues
- *	@qs: the queue set to resume
- *
- *	Restarts suspended Tx queues of an SGE queue set if they have enough
- *	free resources to resume operation.
- */
-static void restart_tx(struct sge_qset *qs)
-{
-	if (test_bit(TXQ_ETH, &qs->txq_stopped) &&
-	    should_restart_tx(&qs->txq[TXQ_ETH]) &&
-	    test_and_clear_bit(TXQ_ETH, &qs->txq_stopped)) {
-		qs->txq[TXQ_ETH].restarts++;
-		if (netif_running(qs->netdev))
-			netif_tx_wake_queue(qs->tx_q);
-	}
-
-	if (test_bit(TXQ_OFLD, &qs->txq_stopped) &&
-	    should_restart_tx(&qs->txq[TXQ_OFLD]) &&
-	    test_and_clear_bit(TXQ_OFLD, &qs->txq_stopped)) {
-		qs->txq[TXQ_OFLD].restarts++;
-		tasklet_schedule(&qs->txq[TXQ_OFLD].qresume_tsk);
-	}
-	if (test_bit(TXQ_CTRL, &qs->txq_stopped) &&
-	    should_restart_tx(&qs->txq[TXQ_CTRL]) &&
-	    test_and_clear_bit(TXQ_CTRL, &qs->txq_stopped)) {
-		qs->txq[TXQ_CTRL].restarts++;
-		tasklet_schedule(&qs->txq[TXQ_CTRL].qresume_tsk);
-	}
-}
-
-/**
- *	cxgb3_arp_process - process an ARP request probing a private IP address
- *	@adapter: the adapter
- *	@skb: the skbuff containing the ARP request
- *
- *	Check if the ARP request is probing the private IP address
- *	dedicated to iSCSI, generate an ARP reply if so.
- */
-static void cxgb3_arp_process(struct port_info *pi, struct sk_buff *skb)
-{
-	struct net_device *dev = skb->dev;
-	struct arphdr *arp;
-	unsigned char *arp_ptr;
-	unsigned char *sha;
-	__be32 sip, tip;
-
-	if (!dev)
-		return;
-
-	skb_reset_network_header(skb);
-	arp = arp_hdr(skb);
-
-	if (arp->ar_op != htons(ARPOP_REQUEST))
-		return;
-
-	arp_ptr = (unsigned char *)(arp + 1);
-	sha = arp_ptr;
-	arp_ptr += dev->addr_len;
-	memcpy(&sip, arp_ptr, sizeof(sip));
-	arp_ptr += sizeof(sip);
-	arp_ptr += dev->addr_len;
-	memcpy(&tip, arp_ptr, sizeof(tip));
-
-	if (tip != pi->iscsi_ipv4addr)
-		return;
-
-	arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
-		 pi->iscsic.mac_addr, sha);
-
-}
-
-static inline int is_arp(struct sk_buff *skb)
-{
-	return skb->protocol == htons(ETH_P_ARP);
-}
-
-static void cxgb3_process_iscsi_prov_pack(struct port_info *pi,
-					struct sk_buff *skb)
-{
-	if (is_arp(skb)) {
-		cxgb3_arp_process(pi, skb);
-		return;
-	}
-
-	if (pi->iscsic.recv)
-		pi->iscsic.recv(pi, skb);
-
-}
-
-/**
- *	rx_eth - process an ingress ethernet packet
- *	@adap: the adapter
- *	@rq: the response queue that received the packet
- *	@skb: the packet
- *	@pad: amount of padding at the start of the buffer
- *
- *	Process an ingress ethernet pakcet and deliver it to the stack.
- *	The padding is 2 if the packet was delivered in an Rx buffer and 0
- *	if it was immediate data in a response.
- */
-static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
-		   struct sk_buff *skb, int pad, int lro)
-{
-	struct cpl_rx_pkt *p = (struct cpl_rx_pkt *)(skb->data + pad);
-	struct sge_qset *qs = rspq_to_qset(rq);
-	struct port_info *pi;
-
-	skb_pull(skb, sizeof(*p) + pad);
-	skb->protocol = eth_type_trans(skb, adap->port[p->iff]);
-	pi = netdev_priv(skb->dev);
-	if ((skb->dev->features & NETIF_F_RXCSUM) && p->csum_valid &&
-	    p->csum == htons(0xffff) && !p->fragment) {
-		qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	} else
-		skb_checksum_none_assert(skb);
-	skb_record_rx_queue(skb, qs - &adap->sge.qs[pi->first_qset]);
-
-	if (p->vlan_valid) {
-		qs->port_stats[SGE_PSTAT_VLANEX]++;
-		__vlan_hwaccel_put_tag(skb, ntohs(p->vlan));
-	}
-	if (rq->polling) {
-		if (lro)
-			napi_gro_receive(&qs->napi, skb);
-		else {
-			if (unlikely(pi->iscsic.flags))
-				cxgb3_process_iscsi_prov_pack(pi, skb);
-			netif_receive_skb(skb);
-		}
-	} else
-		netif_rx(skb);
-}
-
-static inline int is_eth_tcp(u32 rss)
-{
-	return G_HASHTYPE(ntohl(rss)) == RSS_HASH_4_TUPLE;
-}
-
-/**
- *	lro_add_page - add a page chunk to an LRO session
- *	@adap: the adapter
- *	@qs: the associated queue set
- *	@fl: the free list containing the page chunk to add
- *	@len: packet length
- *	@complete: Indicates the last fragment of a frame
- *
- *	Add a received packet contained in a page chunk to an existing LRO
- *	session.
- */
-static void lro_add_page(struct adapter *adap, struct sge_qset *qs,
-			 struct sge_fl *fl, int len, int complete)
-{
-	struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
-	struct port_info *pi = netdev_priv(qs->netdev);
-	struct sk_buff *skb = NULL;
-	struct cpl_rx_pkt *cpl;
-	struct skb_frag_struct *rx_frag;
-	int nr_frags;
-	int offset = 0;
-
-	if (!qs->nomem) {
-		skb = napi_get_frags(&qs->napi);
-		qs->nomem = !skb;
-	}
-
-	fl->credits--;
-
-	pci_dma_sync_single_for_cpu(adap->pdev,
-				    dma_unmap_addr(sd, dma_addr),
-				    fl->buf_size - SGE_PG_RSVD,
-				    PCI_DMA_FROMDEVICE);
-
-	(*sd->pg_chunk.p_cnt)--;
-	if (!*sd->pg_chunk.p_cnt && sd->pg_chunk.page != fl->pg_chunk.page)
-		pci_unmap_page(adap->pdev,
-			       sd->pg_chunk.mapping,
-			       fl->alloc_size,
-			       PCI_DMA_FROMDEVICE);
-
-	if (!skb) {
-		put_page(sd->pg_chunk.page);
-		if (complete)
-			qs->nomem = 0;
-		return;
-	}
-
-	rx_frag = skb_shinfo(skb)->frags;
-	nr_frags = skb_shinfo(skb)->nr_frags;
-
-	if (!nr_frags) {
-		offset = 2 + sizeof(struct cpl_rx_pkt);
-		cpl = qs->lro_va = sd->pg_chunk.va + 2;
-
-		if ((qs->netdev->features & NETIF_F_RXCSUM) &&
-		     cpl->csum_valid && cpl->csum == htons(0xffff)) {
-			skb->ip_summed = CHECKSUM_UNNECESSARY;
-			qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
-		} else
-			skb->ip_summed = CHECKSUM_NONE;
-	} else
-		cpl = qs->lro_va;
-
-	len -= offset;
-
-	rx_frag += nr_frags;
-	rx_frag->page = sd->pg_chunk.page;
-	rx_frag->page_offset = sd->pg_chunk.offset + offset;
-	rx_frag->size = len;
-
-	skb->len += len;
-	skb->data_len += len;
-	skb->truesize += len;
-	skb_shinfo(skb)->nr_frags++;
-
-	if (!complete)
-		return;
-
-	skb_record_rx_queue(skb, qs - &adap->sge.qs[pi->first_qset]);
-
-	if (cpl->vlan_valid)
-		__vlan_hwaccel_put_tag(skb, ntohs(cpl->vlan));
-	napi_gro_frags(&qs->napi);
-}
-
-/**
- *	handle_rsp_cntrl_info - handles control information in a response
- *	@qs: the queue set corresponding to the response
- *	@flags: the response control flags
- *
- *	Handles the control information of an SGE response, such as GTS
- *	indications and completion credits for the queue set's Tx queues.
- *	HW coalesces credits, we don't do any extra SW coalescing.
- */
-static inline void handle_rsp_cntrl_info(struct sge_qset *qs, u32 flags)
-{
-	unsigned int credits;
-
-#if USE_GTS
-	if (flags & F_RSPD_TXQ0_GTS)
-		clear_bit(TXQ_RUNNING, &qs->txq[TXQ_ETH].flags);
-#endif
-
-	credits = G_RSPD_TXQ0_CR(flags);
-	if (credits)
-		qs->txq[TXQ_ETH].processed += credits;
-
-	credits = G_RSPD_TXQ2_CR(flags);
-	if (credits)
-		qs->txq[TXQ_CTRL].processed += credits;
-
-# if USE_GTS
-	if (flags & F_RSPD_TXQ1_GTS)
-		clear_bit(TXQ_RUNNING, &qs->txq[TXQ_OFLD].flags);
-# endif
-	credits = G_RSPD_TXQ1_CR(flags);
-	if (credits)
-		qs->txq[TXQ_OFLD].processed += credits;
-}
-
-/**
- *	check_ring_db - check if we need to ring any doorbells
- *	@adapter: the adapter
- *	@qs: the queue set whose Tx queues are to be examined
- *	@sleeping: indicates which Tx queue sent GTS
- *
- *	Checks if some of a queue set's Tx queues need to ring their doorbells
- *	to resume transmission after idling while they still have unprocessed
- *	descriptors.
- */
-static void check_ring_db(struct adapter *adap, struct sge_qset *qs,
-			  unsigned int sleeping)
-{
-	if (sleeping & F_RSPD_TXQ0_GTS) {
-		struct sge_txq *txq = &qs->txq[TXQ_ETH];
-
-		if (txq->cleaned + txq->in_use != txq->processed &&
-		    !test_and_set_bit(TXQ_LAST_PKT_DB, &txq->flags)) {
-			set_bit(TXQ_RUNNING, &txq->flags);
-			t3_write_reg(adap, A_SG_KDOORBELL, F_SELEGRCNTX |
-				     V_EGRCNTX(txq->cntxt_id));
-		}
-	}
-
-	if (sleeping & F_RSPD_TXQ1_GTS) {
-		struct sge_txq *txq = &qs->txq[TXQ_OFLD];
-
-		if (txq->cleaned + txq->in_use != txq->processed &&
-		    !test_and_set_bit(TXQ_LAST_PKT_DB, &txq->flags)) {
-			set_bit(TXQ_RUNNING, &txq->flags);
-			t3_write_reg(adap, A_SG_KDOORBELL, F_SELEGRCNTX |
-				     V_EGRCNTX(txq->cntxt_id));
-		}
-	}
-}
-
-/**
- *	is_new_response - check if a response is newly written
- *	@r: the response descriptor
- *	@q: the response queue
- *
- *	Returns true if a response descriptor contains a yet unprocessed
- *	response.
- */
-static inline int is_new_response(const struct rsp_desc *r,
-				  const struct sge_rspq *q)
-{
-	return (r->intr_gen & F_RSPD_GEN2) == q->gen;
-}
-
-static inline void clear_rspq_bufstate(struct sge_rspq * const q)
-{
-	q->pg_skb = NULL;
-	q->rx_recycle_buf = 0;
-}
-
-#define RSPD_GTS_MASK  (F_RSPD_TXQ0_GTS | F_RSPD_TXQ1_GTS)
-#define RSPD_CTRL_MASK (RSPD_GTS_MASK | \
-			V_RSPD_TXQ0_CR(M_RSPD_TXQ0_CR) | \
-			V_RSPD_TXQ1_CR(M_RSPD_TXQ1_CR) | \
-			V_RSPD_TXQ2_CR(M_RSPD_TXQ2_CR))
-
-/* How long to delay the next interrupt in case of memory shortage, in 0.1us. */
-#define NOMEM_INTR_DELAY 2500
-
-/**
- *	process_responses - process responses from an SGE response queue
- *	@adap: the adapter
- *	@qs: the queue set to which the response queue belongs
- *	@budget: how many responses can be processed in this round
- *
- *	Process responses from an SGE response queue up to the supplied budget.
- *	Responses include received packets as well as credits and other events
- *	for the queues that belong to the response queue's queue set.
- *	A negative budget is effectively unlimited.
- *
- *	Additionally choose the interrupt holdoff time for the next interrupt
- *	on this queue.  If the system is under memory shortage use a fairly
- *	long delay to help recovery.
- */
-static int process_responses(struct adapter *adap, struct sge_qset *qs,
-			     int budget)
-{
-	struct sge_rspq *q = &qs->rspq;
-	struct rsp_desc *r = &q->desc[q->cidx];
-	int budget_left = budget;
-	unsigned int sleeping = 0;
-	struct sk_buff *offload_skbs[RX_BUNDLE_SIZE];
-	int ngathered = 0;
-
-	q->next_holdoff = q->holdoff_tmr;
-
-	while (likely(budget_left && is_new_response(r, q))) {
-		int packet_complete, eth, ethpad = 2;
-		int lro = !!(qs->netdev->features & NETIF_F_GRO);
-		struct sk_buff *skb = NULL;
-		u32 len, flags;
-		__be32 rss_hi, rss_lo;
-
-		rmb();
-		eth = r->rss_hdr.opcode == CPL_RX_PKT;
-		rss_hi = *(const __be32 *)r;
-		rss_lo = r->rss_hdr.rss_hash_val;
-		flags = ntohl(r->flags);
-
-		if (unlikely(flags & F_RSPD_ASYNC_NOTIF)) {
-			skb = alloc_skb(AN_PKT_SIZE, GFP_ATOMIC);
-			if (!skb)
-				goto no_mem;
-
-			memcpy(__skb_put(skb, AN_PKT_SIZE), r, AN_PKT_SIZE);
-			skb->data[0] = CPL_ASYNC_NOTIF;
-			rss_hi = htonl(CPL_ASYNC_NOTIF << 24);
-			q->async_notif++;
-		} else if (flags & F_RSPD_IMM_DATA_VALID) {
-			skb = get_imm_packet(r);
-			if (unlikely(!skb)) {
-no_mem:
-				q->next_holdoff = NOMEM_INTR_DELAY;
-				q->nomem++;
-				/* consume one credit since we tried */
-				budget_left--;
-				break;
-			}
-			q->imm_data++;
-			ethpad = 0;
-		} else if ((len = ntohl(r->len_cq)) != 0) {
-			struct sge_fl *fl;
-
-			lro &= eth && is_eth_tcp(rss_hi);
-
-			fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
-			if (fl->use_pages) {
-				void *addr = fl->sdesc[fl->cidx].pg_chunk.va;
-
-				prefetch(addr);
-#if L1_CACHE_BYTES < 128
-				prefetch(addr + L1_CACHE_BYTES);
-#endif
-				__refill_fl(adap, fl);
-				if (lro > 0) {
-					lro_add_page(adap, qs, fl,
-						     G_RSPD_LEN(len),
-						     flags & F_RSPD_EOP);
-					 goto next_fl;
-				}
-
-				skb = get_packet_pg(adap, fl, q,
-						    G_RSPD_LEN(len),
-						    eth ?
-						    SGE_RX_DROP_THRES : 0);
-				q->pg_skb = skb;
-			} else
-				skb = get_packet(adap, fl, G_RSPD_LEN(len),
-						 eth ? SGE_RX_DROP_THRES : 0);
-			if (unlikely(!skb)) {
-				if (!eth)
-					goto no_mem;
-				q->rx_drops++;
-			} else if (unlikely(r->rss_hdr.opcode == CPL_TRACE_PKT))
-				__skb_pull(skb, 2);
-next_fl:
-			if (++fl->cidx == fl->size)
-				fl->cidx = 0;
-		} else
-			q->pure_rsps++;
-
-		if (flags & RSPD_CTRL_MASK) {
-			sleeping |= flags & RSPD_GTS_MASK;
-			handle_rsp_cntrl_info(qs, flags);
-		}
-
-		r++;
-		if (unlikely(++q->cidx == q->size)) {
-			q->cidx = 0;
-			q->gen ^= 1;
-			r = q->desc;
-		}
-		prefetch(r);
-
-		if (++q->credits >= (q->size / 4)) {
-			refill_rspq(adap, q, q->credits);
-			q->credits = 0;
-		}
-
-		packet_complete = flags &
-				  (F_RSPD_EOP | F_RSPD_IMM_DATA_VALID |
-				   F_RSPD_ASYNC_NOTIF);
-
-		if (skb != NULL && packet_complete) {
-			if (eth)
-				rx_eth(adap, q, skb, ethpad, lro);
-			else {
-				q->offload_pkts++;
-				/* Preserve the RSS info in csum & priority */
-				skb->csum = rss_hi;
-				skb->priority = rss_lo;
-				ngathered = rx_offload(&adap->tdev, q, skb,
-						       offload_skbs,
-						       ngathered);
-			}
-
-			if (flags & F_RSPD_EOP)
-				clear_rspq_bufstate(q);
-		}
-		--budget_left;
-	}
-
-	deliver_partial_bundle(&adap->tdev, q, offload_skbs, ngathered);
-
-	if (sleeping)
-		check_ring_db(adap, qs, sleeping);
-
-	smp_mb();		/* commit Tx queue .processed updates */
-	if (unlikely(qs->txq_stopped != 0))
-		restart_tx(qs);
-
-	budget -= budget_left;
-	return budget;
-}
-
-static inline int is_pure_response(const struct rsp_desc *r)
-{
-	__be32 n = r->flags & htonl(F_RSPD_ASYNC_NOTIF | F_RSPD_IMM_DATA_VALID);
-
-	return (n | r->len_cq) == 0;
-}
-
-/**
- *	napi_rx_handler - the NAPI handler for Rx processing
- *	@napi: the napi instance
- *	@budget: how many packets we can process in this round
- *
- *	Handler for new data events when using NAPI.
- */
-static int napi_rx_handler(struct napi_struct *napi, int budget)
-{
-	struct sge_qset *qs = container_of(napi, struct sge_qset, napi);
-	struct adapter *adap = qs->adap;
-	int work_done = process_responses(adap, qs, budget);
-
-	if (likely(work_done < budget)) {
-		napi_complete(napi);
-
-		/*
-		 * Because we don't atomically flush the following
-		 * write it is possible that in very rare cases it can
-		 * reach the device in a way that races with a new
-		 * response being written plus an error interrupt
-		 * causing the NAPI interrupt handler below to return
-		 * unhandled status to the OS.  To protect against
-		 * this would require flushing the write and doing
-		 * both the write and the flush with interrupts off.
-		 * Way too expensive and unjustifiable given the
-		 * rarity of the race.
-		 *
-		 * The race cannot happen at all with MSI-X.
-		 */
-		t3_write_reg(adap, A_SG_GTS, V_RSPQ(qs->rspq.cntxt_id) |
-			     V_NEWTIMER(qs->rspq.next_holdoff) |
-			     V_NEWINDEX(qs->rspq.cidx));
-	}
-	return work_done;
-}
-
-/*
- * Returns true if the device is already scheduled for polling.
- */
-static inline int napi_is_scheduled(struct napi_struct *napi)
-{
-	return test_bit(NAPI_STATE_SCHED, &napi->state);
-}
-
-/**
- *	process_pure_responses - process pure responses from a response queue
- *	@adap: the adapter
- *	@qs: the queue set owning the response queue
- *	@r: the first pure response to process
- *
- *	A simpler version of process_responses() that handles only pure (i.e.,
- *	non data-carrying) responses.  Such respones are too light-weight to
- *	justify calling a softirq under NAPI, so we handle them specially in
- *	the interrupt handler.  The function is called with a pointer to a
- *	response, which the caller must ensure is a valid pure response.
- *
- *	Returns 1 if it encounters a valid data-carrying response, 0 otherwise.
- */
-static int process_pure_responses(struct adapter *adap, struct sge_qset *qs,
-				  struct rsp_desc *r)
-{
-	struct sge_rspq *q = &qs->rspq;
-	unsigned int sleeping = 0;
-
-	do {
-		u32 flags = ntohl(r->flags);
-
-		r++;
-		if (unlikely(++q->cidx == q->size)) {
-			q->cidx = 0;
-			q->gen ^= 1;
-			r = q->desc;
-		}
-		prefetch(r);
-
-		if (flags & RSPD_CTRL_MASK) {
-			sleeping |= flags & RSPD_GTS_MASK;
-			handle_rsp_cntrl_info(qs, flags);
-		}
-
-		q->pure_rsps++;
-		if (++q->credits >= (q->size / 4)) {
-			refill_rspq(adap, q, q->credits);
-			q->credits = 0;
-		}
-		if (!is_new_response(r, q))
-			break;
-		rmb();
-	} while (is_pure_response(r));
-
-	if (sleeping)
-		check_ring_db(adap, qs, sleeping);
-
-	smp_mb();		/* commit Tx queue .processed updates */
-	if (unlikely(qs->txq_stopped != 0))
-		restart_tx(qs);
-
-	return is_new_response(r, q);
-}
-
-/**
- *	handle_responses - decide what to do with new responses in NAPI mode
- *	@adap: the adapter
- *	@q: the response queue
- *
- *	This is used by the NAPI interrupt handlers to decide what to do with
- *	new SGE responses.  If there are no new responses it returns -1.  If
- *	there are new responses and they are pure (i.e., non-data carrying)
- *	it handles them straight in hard interrupt context as they are very
- *	cheap and don't deliver any packets.  Finally, if there are any data
- *	signaling responses it schedules the NAPI handler.  Returns 1 if it
- *	schedules NAPI, 0 if all new responses were pure.
- *
- *	The caller must ascertain NAPI is not already running.
- */
-static inline int handle_responses(struct adapter *adap, struct sge_rspq *q)
-{
-	struct sge_qset *qs = rspq_to_qset(q);
-	struct rsp_desc *r = &q->desc[q->cidx];
-
-	if (!is_new_response(r, q))
-		return -1;
-	rmb();
-	if (is_pure_response(r) && process_pure_responses(adap, qs, r) == 0) {
-		t3_write_reg(adap, A_SG_GTS, V_RSPQ(q->cntxt_id) |
-			     V_NEWTIMER(q->holdoff_tmr) | V_NEWINDEX(q->cidx));
-		return 0;
-	}
-	napi_schedule(&qs->napi);
-	return 1;
-}
-
-/*
- * The MSI-X interrupt handler for an SGE response queue for the non-NAPI case
- * (i.e., response queue serviced in hard interrupt).
- */
-static irqreturn_t t3_sge_intr_msix(int irq, void *cookie)
-{
-	struct sge_qset *qs = cookie;
-	struct adapter *adap = qs->adap;
-	struct sge_rspq *q = &qs->rspq;
-
-	spin_lock(&q->lock);
-	if (process_responses(adap, qs, -1) == 0)
-		q->unhandled_irqs++;
-	t3_write_reg(adap, A_SG_GTS, V_RSPQ(q->cntxt_id) |
-		     V_NEWTIMER(q->next_holdoff) | V_NEWINDEX(q->cidx));
-	spin_unlock(&q->lock);
-	return IRQ_HANDLED;
-}
-
-/*
- * The MSI-X interrupt handler for an SGE response queue for the NAPI case
- * (i.e., response queue serviced by NAPI polling).
- */
-static irqreturn_t t3_sge_intr_msix_napi(int irq, void *cookie)
-{
-	struct sge_qset *qs = cookie;
-	struct sge_rspq *q = &qs->rspq;
-
-	spin_lock(&q->lock);
-
-	if (handle_responses(qs->adap, q) < 0)
-		q->unhandled_irqs++;
-	spin_unlock(&q->lock);
-	return IRQ_HANDLED;
-}
-
-/*
- * The non-NAPI MSI interrupt handler.  This needs to handle data events from
- * SGE response queues as well as error and other async events as they all use
- * the same MSI vector.  We use one SGE response queue per port in this mode
- * and protect all response queues with queue 0's lock.
- */
-static irqreturn_t t3_intr_msi(int irq, void *cookie)
-{
-	int new_packets = 0;
-	struct adapter *adap = cookie;
-	struct sge_rspq *q = &adap->sge.qs[0].rspq;
-
-	spin_lock(&q->lock);
-
-	if (process_responses(adap, &adap->sge.qs[0], -1)) {
-		t3_write_reg(adap, A_SG_GTS, V_RSPQ(q->cntxt_id) |
-			     V_NEWTIMER(q->next_holdoff) | V_NEWINDEX(q->cidx));
-		new_packets = 1;
-	}
-
-	if (adap->params.nports == 2 &&
-	    process_responses(adap, &adap->sge.qs[1], -1)) {
-		struct sge_rspq *q1 = &adap->sge.qs[1].rspq;
-
-		t3_write_reg(adap, A_SG_GTS, V_RSPQ(q1->cntxt_id) |
-			     V_NEWTIMER(q1->next_holdoff) |
-			     V_NEWINDEX(q1->cidx));
-		new_packets = 1;
-	}
-
-	if (!new_packets && t3_slow_intr_handler(adap) == 0)
-		q->unhandled_irqs++;
-
-	spin_unlock(&q->lock);
-	return IRQ_HANDLED;
-}
-
-static int rspq_check_napi(struct sge_qset *qs)
-{
-	struct sge_rspq *q = &qs->rspq;
-
-	if (!napi_is_scheduled(&qs->napi) &&
-	    is_new_response(&q->desc[q->cidx], q)) {
-		napi_schedule(&qs->napi);
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * The MSI interrupt handler for the NAPI case (i.e., response queues serviced
- * by NAPI polling).  Handles data events from SGE response queues as well as
- * error and other async events as they all use the same MSI vector.  We use
- * one SGE response queue per port in this mode and protect all response
- * queues with queue 0's lock.
- */
-static irqreturn_t t3_intr_msi_napi(int irq, void *cookie)
-{
-	int new_packets;
-	struct adapter *adap = cookie;
-	struct sge_rspq *q = &adap->sge.qs[0].rspq;
-
-	spin_lock(&q->lock);
-
-	new_packets = rspq_check_napi(&adap->sge.qs[0]);
-	if (adap->params.nports == 2)
-		new_packets += rspq_check_napi(&adap->sge.qs[1]);
-	if (!new_packets && t3_slow_intr_handler(adap) == 0)
-		q->unhandled_irqs++;
-
-	spin_unlock(&q->lock);
-	return IRQ_HANDLED;
-}
-
-/*
- * A helper function that processes responses and issues GTS.
- */
-static inline int process_responses_gts(struct adapter *adap,
-					struct sge_rspq *rq)
-{
-	int work;
-
-	work = process_responses(adap, rspq_to_qset(rq), -1);
-	t3_write_reg(adap, A_SG_GTS, V_RSPQ(rq->cntxt_id) |
-		     V_NEWTIMER(rq->next_holdoff) | V_NEWINDEX(rq->cidx));
-	return work;
-}
-
-/*
- * The legacy INTx interrupt handler.  This needs to handle data events from
- * SGE response queues as well as error and other async events as they all use
- * the same interrupt pin.  We use one SGE response queue per port in this mode
- * and protect all response queues with queue 0's lock.
- */
-static irqreturn_t t3_intr(int irq, void *cookie)
-{
-	int work_done, w0, w1;
-	struct adapter *adap = cookie;
-	struct sge_rspq *q0 = &adap->sge.qs[0].rspq;
-	struct sge_rspq *q1 = &adap->sge.qs[1].rspq;
-
-	spin_lock(&q0->lock);
-
-	w0 = is_new_response(&q0->desc[q0->cidx], q0);
-	w1 = adap->params.nports == 2 &&
-	    is_new_response(&q1->desc[q1->cidx], q1);
-
-	if (likely(w0 | w1)) {
-		t3_write_reg(adap, A_PL_CLI, 0);
-		t3_read_reg(adap, A_PL_CLI);	/* flush */
-
-		if (likely(w0))
-			process_responses_gts(adap, q0);
-
-		if (w1)
-			process_responses_gts(adap, q1);
-
-		work_done = w0 | w1;
-	} else
-		work_done = t3_slow_intr_handler(adap);
-
-	spin_unlock(&q0->lock);
-	return IRQ_RETVAL(work_done != 0);
-}
-
-/*
- * Interrupt handler for legacy INTx interrupts for T3B-based cards.
- * Handles data events from SGE response queues as well as error and other
- * async events as they all use the same interrupt pin.  We use one SGE
- * response queue per port in this mode and protect all response queues with
- * queue 0's lock.
- */
-static irqreturn_t t3b_intr(int irq, void *cookie)
-{
-	u32 map;
-	struct adapter *adap = cookie;
-	struct sge_rspq *q0 = &adap->sge.qs[0].rspq;
-
-	t3_write_reg(adap, A_PL_CLI, 0);
-	map = t3_read_reg(adap, A_SG_DATA_INTR);
-
-	if (unlikely(!map))	/* shared interrupt, most likely */
-		return IRQ_NONE;
-
-	spin_lock(&q0->lock);
-
-	if (unlikely(map & F_ERRINTR))
-		t3_slow_intr_handler(adap);
-
-	if (likely(map & 1))
-		process_responses_gts(adap, q0);
-
-	if (map & 2)
-		process_responses_gts(adap, &adap->sge.qs[1].rspq);
-
-	spin_unlock(&q0->lock);
-	return IRQ_HANDLED;
-}
-
-/*
- * NAPI interrupt handler for legacy INTx interrupts for T3B-based cards.
- * Handles data events from SGE response queues as well as error and other
- * async events as they all use the same interrupt pin.  We use one SGE
- * response queue per port in this mode and protect all response queues with
- * queue 0's lock.
- */
-static irqreturn_t t3b_intr_napi(int irq, void *cookie)
-{
-	u32 map;
-	struct adapter *adap = cookie;
-	struct sge_qset *qs0 = &adap->sge.qs[0];
-	struct sge_rspq *q0 = &qs0->rspq;
-
-	t3_write_reg(adap, A_PL_CLI, 0);
-	map = t3_read_reg(adap, A_SG_DATA_INTR);
-
-	if (unlikely(!map))	/* shared interrupt, most likely */
-		return IRQ_NONE;
-
-	spin_lock(&q0->lock);
-
-	if (unlikely(map & F_ERRINTR))
-		t3_slow_intr_handler(adap);
-
-	if (likely(map & 1))
-		napi_schedule(&qs0->napi);
-
-	if (map & 2)
-		napi_schedule(&adap->sge.qs[1].napi);
-
-	spin_unlock(&q0->lock);
-	return IRQ_HANDLED;
-}
-
-/**
- *	t3_intr_handler - select the top-level interrupt handler
- *	@adap: the adapter
- *	@polling: whether using NAPI to service response queues
- *
- *	Selects the top-level interrupt handler based on the type of interrupts
- *	(MSI-X, MSI, or legacy) and whether NAPI will be used to service the
- *	response queues.
- */
-irq_handler_t t3_intr_handler(struct adapter *adap, int polling)
-{
-	if (adap->flags & USING_MSIX)
-		return polling ? t3_sge_intr_msix_napi : t3_sge_intr_msix;
-	if (adap->flags & USING_MSI)
-		return polling ? t3_intr_msi_napi : t3_intr_msi;
-	if (adap->params.rev > 0)
-		return polling ? t3b_intr_napi : t3b_intr;
-	return t3_intr;
-}
-
-#define SGE_PARERR (F_CPPARITYERROR | F_OCPARITYERROR | F_RCPARITYERROR | \
-		    F_IRPARITYERROR | V_ITPARITYERROR(M_ITPARITYERROR) | \
-		    V_FLPARITYERROR(M_FLPARITYERROR) | F_LODRBPARITYERROR | \
-		    F_HIDRBPARITYERROR | F_LORCQPARITYERROR | \
-		    F_HIRCQPARITYERROR)
-#define SGE_FRAMINGERR (F_UC_REQ_FRAMINGERROR | F_R_REQ_FRAMINGERROR)
-#define SGE_FATALERR (SGE_PARERR | SGE_FRAMINGERR | F_RSPQCREDITOVERFOW | \
-		      F_RSPQDISABLED)
-
-/**
- *	t3_sge_err_intr_handler - SGE async event interrupt handler
- *	@adapter: the adapter
- *
- *	Interrupt handler for SGE asynchronous (non-data) events.
- */
-void t3_sge_err_intr_handler(struct adapter *adapter)
-{
-	unsigned int v, status = t3_read_reg(adapter, A_SG_INT_CAUSE) &
-				 ~F_FLEMPTY;
-
-	if (status & SGE_PARERR)
-		CH_ALERT(adapter, "SGE parity error (0x%x)\n",
-			 status & SGE_PARERR);
-	if (status & SGE_FRAMINGERR)
-		CH_ALERT(adapter, "SGE framing error (0x%x)\n",
-			 status & SGE_FRAMINGERR);
-
-	if (status & F_RSPQCREDITOVERFOW)
-		CH_ALERT(adapter, "SGE response queue credit overflow\n");
-
-	if (status & F_RSPQDISABLED) {
-		v = t3_read_reg(adapter, A_SG_RSPQ_FL_STATUS);
-
-		CH_ALERT(adapter,
-			 "packet delivered to disabled response queue "
-			 "(0x%x)\n", (v >> S_RSPQ0DISABLED) & 0xff);
-	}
-
-	if (status & (F_HIPIODRBDROPERR | F_LOPIODRBDROPERR))
-		queue_work(cxgb3_wq, &adapter->db_drop_task);
-
-	if (status & (F_HIPRIORITYDBFULL | F_LOPRIORITYDBFULL))
-		queue_work(cxgb3_wq, &adapter->db_full_task);
-
-	if (status & (F_HIPRIORITYDBEMPTY | F_LOPRIORITYDBEMPTY))
-		queue_work(cxgb3_wq, &adapter->db_empty_task);
-
-	t3_write_reg(adapter, A_SG_INT_CAUSE, status);
-	if (status &  SGE_FATALERR)
-		t3_fatal_err(adapter);
-}
-
-/**
- *	sge_timer_tx - perform periodic maintenance of an SGE qset
- *	@data: the SGE queue set to maintain
- *
- *	Runs periodically from a timer to perform maintenance of an SGE queue
- *	set.  It performs two tasks:
- *
- *	Cleans up any completed Tx descriptors that may still be pending.
- *	Normal descriptor cleanup happens when new packets are added to a Tx
- *	queue so this timer is relatively infrequent and does any cleanup only
- *	if the Tx queue has not seen any new packets in a while.  We make a
- *	best effort attempt to reclaim descriptors, in that we don't wait
- *	around if we cannot get a queue's lock (which most likely is because
- *	someone else is queueing new packets and so will also handle the clean
- *	up).  Since control queues use immediate data exclusively we don't
- *	bother cleaning them up here.
- *
- */
-static void sge_timer_tx(unsigned long data)
-{
-	struct sge_qset *qs = (struct sge_qset *)data;
-	struct port_info *pi = netdev_priv(qs->netdev);
-	struct adapter *adap = pi->adapter;
-	unsigned int tbd[SGE_TXQ_PER_SET] = {0, 0};
-	unsigned long next_period;
-
-	if (__netif_tx_trylock(qs->tx_q)) {
-                tbd[TXQ_ETH] = reclaim_completed_tx(adap, &qs->txq[TXQ_ETH],
-                                                     TX_RECLAIM_TIMER_CHUNK);
-		__netif_tx_unlock(qs->tx_q);
-	}
-
-	if (spin_trylock(&qs->txq[TXQ_OFLD].lock)) {
-		tbd[TXQ_OFLD] = reclaim_completed_tx(adap, &qs->txq[TXQ_OFLD],
-						     TX_RECLAIM_TIMER_CHUNK);
-		spin_unlock(&qs->txq[TXQ_OFLD].lock);
-	}
-
-	next_period = TX_RECLAIM_PERIOD >>
-                      (max(tbd[TXQ_ETH], tbd[TXQ_OFLD]) /
-                      TX_RECLAIM_TIMER_CHUNK);
-	mod_timer(&qs->tx_reclaim_timer, jiffies + next_period);
-}
-
-/*
- *	sge_timer_rx - perform periodic maintenance of an SGE qset
- *	@data: the SGE queue set to maintain
- *
- *	a) Replenishes Rx queues that have run out due to memory shortage.
- *	Normally new Rx buffers are added when existing ones are consumed but
- *	when out of memory a queue can become empty.  We try to add only a few
- *	buffers here, the queue will be replenished fully as these new buffers
- *	are used up if memory shortage has subsided.
- *
- *	b) Return coalesced response queue credits in case a response queue is
- *	starved.
- *
- */
-static void sge_timer_rx(unsigned long data)
-{
-	spinlock_t *lock;
-	struct sge_qset *qs = (struct sge_qset *)data;
-	struct port_info *pi = netdev_priv(qs->netdev);
-	struct adapter *adap = pi->adapter;
-	u32 status;
-
-	lock = adap->params.rev > 0 ?
-	       &qs->rspq.lock : &adap->sge.qs[0].rspq.lock;
-
-	if (!spin_trylock_irq(lock))
-		goto out;
-
-	if (napi_is_scheduled(&qs->napi))
-		goto unlock;
-
-	if (adap->params.rev < 4) {
-		status = t3_read_reg(adap, A_SG_RSPQ_FL_STATUS);
-
-		if (status & (1 << qs->rspq.cntxt_id)) {
-			qs->rspq.starved++;
-			if (qs->rspq.credits) {
-				qs->rspq.credits--;
-				refill_rspq(adap, &qs->rspq, 1);
-				qs->rspq.restarted++;
-				t3_write_reg(adap, A_SG_RSPQ_FL_STATUS,
-					     1 << qs->rspq.cntxt_id);
-			}
-		}
-	}
-
-	if (qs->fl[0].credits < qs->fl[0].size)
-		__refill_fl(adap, &qs->fl[0]);
-	if (qs->fl[1].credits < qs->fl[1].size)
-		__refill_fl(adap, &qs->fl[1]);
-
-unlock:
-	spin_unlock_irq(lock);
-out:
-	mod_timer(&qs->rx_reclaim_timer, jiffies + RX_RECLAIM_PERIOD);
-}
-
-/**
- *	t3_update_qset_coalesce - update coalescing settings for a queue set
- *	@qs: the SGE queue set
- *	@p: new queue set parameters
- *
- *	Update the coalescing settings for an SGE queue set.  Nothing is done
- *	if the queue set is not initialized yet.
- */
-void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p)
-{
-	qs->rspq.holdoff_tmr = max(p->coalesce_usecs * 10, 1U);/* can't be 0 */
-	qs->rspq.polling = p->polling;
-	qs->napi.poll = p->polling ? napi_rx_handler : ofld_poll;
-}
-
-/**
- *	t3_sge_alloc_qset - initialize an SGE queue set
- *	@adapter: the adapter
- *	@id: the queue set id
- *	@nports: how many Ethernet ports will be using this queue set
- *	@irq_vec_idx: the IRQ vector index for response queue interrupts
- *	@p: configuration parameters for this queue set
- *	@ntxq: number of Tx queues for the queue set
- *	@netdev: net device associated with this queue set
- *	@netdevq: net device TX queue associated with this queue set
- *
- *	Allocate resources and initialize an SGE queue set.  A queue set
- *	comprises a response queue, two Rx free-buffer queues, and up to 3
- *	Tx queues.  The Tx queues are assigned roles in the order Ethernet
- *	queue, offload queue, and control queue.
- */
-int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
-		      int irq_vec_idx, const struct qset_params *p,
-		      int ntxq, struct net_device *dev,
-		      struct netdev_queue *netdevq)
-{
-	int i, avail, ret = -ENOMEM;
-	struct sge_qset *q = &adapter->sge.qs[id];
-
-	init_qset_cntxt(q, id);
-	setup_timer(&q->tx_reclaim_timer, sge_timer_tx, (unsigned long)q);
-	setup_timer(&q->rx_reclaim_timer, sge_timer_rx, (unsigned long)q);
-
-	q->fl[0].desc = alloc_ring(adapter->pdev, p->fl_size,
-				   sizeof(struct rx_desc),
-				   sizeof(struct rx_sw_desc),
-				   &q->fl[0].phys_addr, &q->fl[0].sdesc);
-	if (!q->fl[0].desc)
-		goto err;
-
-	q->fl[1].desc = alloc_ring(adapter->pdev, p->jumbo_size,
-				   sizeof(struct rx_desc),
-				   sizeof(struct rx_sw_desc),
-				   &q->fl[1].phys_addr, &q->fl[1].sdesc);
-	if (!q->fl[1].desc)
-		goto err;
-
-	q->rspq.desc = alloc_ring(adapter->pdev, p->rspq_size,
-				  sizeof(struct rsp_desc), 0,
-				  &q->rspq.phys_addr, NULL);
-	if (!q->rspq.desc)
-		goto err;
-
-	for (i = 0; i < ntxq; ++i) {
-		/*
-		 * The control queue always uses immediate data so does not
-		 * need to keep track of any sk_buffs.
-		 */
-		size_t sz = i == TXQ_CTRL ? 0 : sizeof(struct tx_sw_desc);
-
-		q->txq[i].desc = alloc_ring(adapter->pdev, p->txq_size[i],
-					    sizeof(struct tx_desc), sz,
-					    &q->txq[i].phys_addr,
-					    &q->txq[i].sdesc);
-		if (!q->txq[i].desc)
-			goto err;
-
-		q->txq[i].gen = 1;
-		q->txq[i].size = p->txq_size[i];
-		spin_lock_init(&q->txq[i].lock);
-		skb_queue_head_init(&q->txq[i].sendq);
-	}
-
-	tasklet_init(&q->txq[TXQ_OFLD].qresume_tsk, restart_offloadq,
-		     (unsigned long)q);
-	tasklet_init(&q->txq[TXQ_CTRL].qresume_tsk, restart_ctrlq,
-		     (unsigned long)q);
-
-	q->fl[0].gen = q->fl[1].gen = 1;
-	q->fl[0].size = p->fl_size;
-	q->fl[1].size = p->jumbo_size;
-
-	q->rspq.gen = 1;
-	q->rspq.size = p->rspq_size;
-	spin_lock_init(&q->rspq.lock);
-	skb_queue_head_init(&q->rspq.rx_queue);
-
-	q->txq[TXQ_ETH].stop_thres = nports *
-	    flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3);
-
-#if FL0_PG_CHUNK_SIZE > 0
-	q->fl[0].buf_size = FL0_PG_CHUNK_SIZE;
-#else
-	q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + sizeof(struct cpl_rx_data);
-#endif
-#if FL1_PG_CHUNK_SIZE > 0
-	q->fl[1].buf_size = FL1_PG_CHUNK_SIZE;
-#else
-	q->fl[1].buf_size = is_offload(adapter) ?
-		(16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) :
-		MAX_FRAME_SIZE + 2 + sizeof(struct cpl_rx_pkt);
-#endif
-
-	q->fl[0].use_pages = FL0_PG_CHUNK_SIZE > 0;
-	q->fl[1].use_pages = FL1_PG_CHUNK_SIZE > 0;
-	q->fl[0].order = FL0_PG_ORDER;
-	q->fl[1].order = FL1_PG_ORDER;
-	q->fl[0].alloc_size = FL0_PG_ALLOC_SIZE;
-	q->fl[1].alloc_size = FL1_PG_ALLOC_SIZE;
-
-	spin_lock_irq(&adapter->sge.reg_lock);
-
-	/* FL threshold comparison uses < */
-	ret = t3_sge_init_rspcntxt(adapter, q->rspq.cntxt_id, irq_vec_idx,
-				   q->rspq.phys_addr, q->rspq.size,
-				   q->fl[0].buf_size - SGE_PG_RSVD, 1, 0);
-	if (ret)
-		goto err_unlock;
-
-	for (i = 0; i < SGE_RXQ_PER_SET; ++i) {
-		ret = t3_sge_init_flcntxt(adapter, q->fl[i].cntxt_id, 0,
-					  q->fl[i].phys_addr, q->fl[i].size,
-					  q->fl[i].buf_size - SGE_PG_RSVD,
-					  p->cong_thres, 1, 0);
-		if (ret)
-			goto err_unlock;
-	}
-
-	ret = t3_sge_init_ecntxt(adapter, q->txq[TXQ_ETH].cntxt_id, USE_GTS,
-				 SGE_CNTXT_ETH, id, q->txq[TXQ_ETH].phys_addr,
-				 q->txq[TXQ_ETH].size, q->txq[TXQ_ETH].token,
-				 1, 0);
-	if (ret)
-		goto err_unlock;
-
-	if (ntxq > 1) {
-		ret = t3_sge_init_ecntxt(adapter, q->txq[TXQ_OFLD].cntxt_id,
-					 USE_GTS, SGE_CNTXT_OFLD, id,
-					 q->txq[TXQ_OFLD].phys_addr,
-					 q->txq[TXQ_OFLD].size, 0, 1, 0);
-		if (ret)
-			goto err_unlock;
-	}
-
-	if (ntxq > 2) {
-		ret = t3_sge_init_ecntxt(adapter, q->txq[TXQ_CTRL].cntxt_id, 0,
-					 SGE_CNTXT_CTRL, id,
-					 q->txq[TXQ_CTRL].phys_addr,
-					 q->txq[TXQ_CTRL].size,
-					 q->txq[TXQ_CTRL].token, 1, 0);
-		if (ret)
-			goto err_unlock;
-	}
-
-	spin_unlock_irq(&adapter->sge.reg_lock);
-
-	q->adap = adapter;
-	q->netdev = dev;
-	q->tx_q = netdevq;
-	t3_update_qset_coalesce(q, p);
-
-	avail = refill_fl(adapter, &q->fl[0], q->fl[0].size,
-			  GFP_KERNEL | __GFP_COMP);
-	if (!avail) {
-		CH_ALERT(adapter, "free list queue 0 initialization failed\n");
-		goto err;
-	}
-	if (avail < q->fl[0].size)
-		CH_WARN(adapter, "free list queue 0 enabled with %d credits\n",
-			avail);
-
-	avail = refill_fl(adapter, &q->fl[1], q->fl[1].size,
-			  GFP_KERNEL | __GFP_COMP);
-	if (avail < q->fl[1].size)
-		CH_WARN(adapter, "free list queue 1 enabled with %d credits\n",
-			avail);
-	refill_rspq(adapter, &q->rspq, q->rspq.size - 1);
-
-	t3_write_reg(adapter, A_SG_GTS, V_RSPQ(q->rspq.cntxt_id) |
-		     V_NEWTIMER(q->rspq.holdoff_tmr));
-
-	return 0;
-
-err_unlock:
-	spin_unlock_irq(&adapter->sge.reg_lock);
-err:
-	t3_free_qset(adapter, q);
-	return ret;
-}
-
-/**
- *      t3_start_sge_timers - start SGE timer call backs
- *      @adap: the adapter
- *
- *      Starts each SGE queue set's timer call back
- */
-void t3_start_sge_timers(struct adapter *adap)
-{
-	int i;
-
-	for (i = 0; i < SGE_QSETS; ++i) {
-		struct sge_qset *q = &adap->sge.qs[i];
-
-	if (q->tx_reclaim_timer.function)
-		mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD);
-
-	if (q->rx_reclaim_timer.function)
-		mod_timer(&q->rx_reclaim_timer, jiffies + RX_RECLAIM_PERIOD);
-	}
-}
-
-/**
- *	t3_stop_sge_timers - stop SGE timer call backs
- *	@adap: the adapter
- *
- *	Stops each SGE queue set's timer call back
- */
-void t3_stop_sge_timers(struct adapter *adap)
-{
-	int i;
-
-	for (i = 0; i < SGE_QSETS; ++i) {
-		struct sge_qset *q = &adap->sge.qs[i];
-
-		if (q->tx_reclaim_timer.function)
-			del_timer_sync(&q->tx_reclaim_timer);
-		if (q->rx_reclaim_timer.function)
-			del_timer_sync(&q->rx_reclaim_timer);
-	}
-}
-
-/**
- *	t3_free_sge_resources - free SGE resources
- *	@adap: the adapter
- *
- *	Frees resources used by the SGE queue sets.
- */
-void t3_free_sge_resources(struct adapter *adap)
-{
-	int i;
-
-	for (i = 0; i < SGE_QSETS; ++i)
-		t3_free_qset(adap, &adap->sge.qs[i]);
-}
-
-/**
- *	t3_sge_start - enable SGE
- *	@adap: the adapter
- *
- *	Enables the SGE for DMAs.  This is the last step in starting packet
- *	transfers.
- */
-void t3_sge_start(struct adapter *adap)
-{
-	t3_set_reg_field(adap, A_SG_CONTROL, F_GLOBALENABLE, F_GLOBALENABLE);
-}
-
-/**
- *	t3_sge_stop - disable SGE operation
- *	@adap: the adapter
- *
- *	Disables the DMA engine.  This can be called in emeregencies (e.g.,
- *	from error interrupts) or from normal process context.  In the latter
- *	case it also disables any pending queue restart tasklets.  Note that
- *	if it is called in interrupt context it cannot disable the restart
- *	tasklets as it cannot wait, however the tasklets will have no effect
- *	since the doorbells are disabled and the driver will call this again
- *	later from process context, at which time the tasklets will be stopped
- *	if they are still running.
- */
-void t3_sge_stop(struct adapter *adap)
-{
-	t3_set_reg_field(adap, A_SG_CONTROL, F_GLOBALENABLE, 0);
-	if (!in_interrupt()) {
-		int i;
-
-		for (i = 0; i < SGE_QSETS; ++i) {
-			struct sge_qset *qs = &adap->sge.qs[i];
-
-			tasklet_kill(&qs->txq[TXQ_OFLD].qresume_tsk);
-			tasklet_kill(&qs->txq[TXQ_CTRL].qresume_tsk);
-		}
-	}
-}
-
-/**
- *	t3_sge_init - initialize SGE
- *	@adap: the adapter
- *	@p: the SGE parameters
- *
- *	Performs SGE initialization needed every time after a chip reset.
- *	We do not initialize any of the queue sets here, instead the driver
- *	top-level must request those individually.  We also do not enable DMA
- *	here, that should be done after the queues have been set up.
- */
-void t3_sge_init(struct adapter *adap, struct sge_params *p)
-{
-	unsigned int ctrl, ups = ffs(pci_resource_len(adap->pdev, 2) >> 12);
-
-	ctrl = F_DROPPKT | V_PKTSHIFT(2) | F_FLMODE | F_AVOIDCQOVFL |
-	    F_CQCRDTCTRL | F_CONGMODE | F_TNLFLMODE | F_FATLPERREN |
-	    V_HOSTPAGESIZE(PAGE_SHIFT - 11) | F_BIGENDIANINGRESS |
-	    V_USERSPACESIZE(ups ? ups - 1 : 0) | F_ISCSICOALESCING;
-#if SGE_NUM_GENBITS == 1
-	ctrl |= F_EGRGENCTRL;
-#endif
-	if (adap->params.rev > 0) {
-		if (!(adap->flags & (USING_MSIX | USING_MSI)))
-			ctrl |= F_ONEINTMULTQ | F_OPTONEINTMULTQ;
-	}
-	t3_write_reg(adap, A_SG_CONTROL, ctrl);
-	t3_write_reg(adap, A_SG_EGR_RCQ_DRB_THRSH, V_HIRCQDRBTHRSH(512) |
-		     V_LORCQDRBTHRSH(512));
-	t3_write_reg(adap, A_SG_TIMER_TICK, core_ticks_per_usec(adap) / 10);
-	t3_write_reg(adap, A_SG_CMDQ_CREDIT_TH, V_THRESHOLD(32) |
-		     V_TIMEOUT(200 * core_ticks_per_usec(adap)));
-	t3_write_reg(adap, A_SG_HI_DRB_HI_THRSH,
-		     adap->params.rev < T3_REV_C ? 1000 : 500);
-	t3_write_reg(adap, A_SG_HI_DRB_LO_THRSH, 256);
-	t3_write_reg(adap, A_SG_LO_DRB_HI_THRSH, 1000);
-	t3_write_reg(adap, A_SG_LO_DRB_LO_THRSH, 256);
-	t3_write_reg(adap, A_SG_OCO_BASE, V_BASE1(0xfff));
-	t3_write_reg(adap, A_SG_DRB_PRI_THRESH, 63 * 1024);
-}
-
-/**
- *	t3_sge_prep - one-time SGE initialization
- *	@adap: the associated adapter
- *	@p: SGE parameters
- *
- *	Performs one-time initialization of SGE SW state.  Includes determining
- *	defaults for the assorted SGE parameters, which admins can change until
- *	they are used to initialize the SGE.
- */
-void t3_sge_prep(struct adapter *adap, struct sge_params *p)
-{
-	int i;
-
-	p->max_pkt_size = (16 * 1024) - sizeof(struct cpl_rx_data) -
-	    SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
-
-	for (i = 0; i < SGE_QSETS; ++i) {
-		struct qset_params *q = p->qset + i;
-
-		q->polling = adap->params.rev > 0;
-		q->coalesce_usecs = 5;
-		q->rspq_size = 1024;
-		q->fl_size = 1024;
- 		q->jumbo_size = 512;
-		q->txq_size[TXQ_ETH] = 1024;
-		q->txq_size[TXQ_OFLD] = 1024;
-		q->txq_size[TXQ_CTRL] = 256;
-		q->cong_thres = 0;
-	}
-
-	spin_lock_init(&adap->sge.reg_lock);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/sge_defs.h linux-libre-3.2-gnu/drivers/net/cxgb3/sge_defs.h
--- linux-libre-3.1-gnu/drivers/net/cxgb3/sge_defs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/sge_defs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,255 +0,0 @@
-/*
- * This file is automatically generated --- any changes will be lost.
- */
-
-#ifndef _SGE_DEFS_H
-#define _SGE_DEFS_H
-
-#define S_EC_CREDITS    0
-#define M_EC_CREDITS    0x7FFF
-#define V_EC_CREDITS(x) ((x) << S_EC_CREDITS)
-#define G_EC_CREDITS(x) (((x) >> S_EC_CREDITS) & M_EC_CREDITS)
-
-#define S_EC_GTS    15
-#define V_EC_GTS(x) ((x) << S_EC_GTS)
-#define F_EC_GTS    V_EC_GTS(1U)
-
-#define S_EC_INDEX    16
-#define M_EC_INDEX    0xFFFF
-#define V_EC_INDEX(x) ((x) << S_EC_INDEX)
-#define G_EC_INDEX(x) (((x) >> S_EC_INDEX) & M_EC_INDEX)
-
-#define S_EC_SIZE    0
-#define M_EC_SIZE    0xFFFF
-#define V_EC_SIZE(x) ((x) << S_EC_SIZE)
-#define G_EC_SIZE(x) (((x) >> S_EC_SIZE) & M_EC_SIZE)
-
-#define S_EC_BASE_LO    16
-#define M_EC_BASE_LO    0xFFFF
-#define V_EC_BASE_LO(x) ((x) << S_EC_BASE_LO)
-#define G_EC_BASE_LO(x) (((x) >> S_EC_BASE_LO) & M_EC_BASE_LO)
-
-#define S_EC_BASE_HI    0
-#define M_EC_BASE_HI    0xF
-#define V_EC_BASE_HI(x) ((x) << S_EC_BASE_HI)
-#define G_EC_BASE_HI(x) (((x) >> S_EC_BASE_HI) & M_EC_BASE_HI)
-
-#define S_EC_RESPQ    4
-#define M_EC_RESPQ    0x7
-#define V_EC_RESPQ(x) ((x) << S_EC_RESPQ)
-#define G_EC_RESPQ(x) (((x) >> S_EC_RESPQ) & M_EC_RESPQ)
-
-#define S_EC_TYPE    7
-#define M_EC_TYPE    0x7
-#define V_EC_TYPE(x) ((x) << S_EC_TYPE)
-#define G_EC_TYPE(x) (((x) >> S_EC_TYPE) & M_EC_TYPE)
-
-#define S_EC_GEN    10
-#define V_EC_GEN(x) ((x) << S_EC_GEN)
-#define F_EC_GEN    V_EC_GEN(1U)
-
-#define S_EC_UP_TOKEN    11
-#define M_EC_UP_TOKEN    0xFFFFF
-#define V_EC_UP_TOKEN(x) ((x) << S_EC_UP_TOKEN)
-#define G_EC_UP_TOKEN(x) (((x) >> S_EC_UP_TOKEN) & M_EC_UP_TOKEN)
-
-#define S_EC_VALID    31
-#define V_EC_VALID(x) ((x) << S_EC_VALID)
-#define F_EC_VALID    V_EC_VALID(1U)
-
-#define S_RQ_MSI_VEC    20
-#define M_RQ_MSI_VEC    0x3F
-#define V_RQ_MSI_VEC(x) ((x) << S_RQ_MSI_VEC)
-#define G_RQ_MSI_VEC(x) (((x) >> S_RQ_MSI_VEC) & M_RQ_MSI_VEC)
-
-#define S_RQ_INTR_EN    26
-#define V_RQ_INTR_EN(x) ((x) << S_RQ_INTR_EN)
-#define F_RQ_INTR_EN    V_RQ_INTR_EN(1U)
-
-#define S_RQ_GEN    28
-#define V_RQ_GEN(x) ((x) << S_RQ_GEN)
-#define F_RQ_GEN    V_RQ_GEN(1U)
-
-#define S_CQ_INDEX    0
-#define M_CQ_INDEX    0xFFFF
-#define V_CQ_INDEX(x) ((x) << S_CQ_INDEX)
-#define G_CQ_INDEX(x) (((x) >> S_CQ_INDEX) & M_CQ_INDEX)
-
-#define S_CQ_SIZE    16
-#define M_CQ_SIZE    0xFFFF
-#define V_CQ_SIZE(x) ((x) << S_CQ_SIZE)
-#define G_CQ_SIZE(x) (((x) >> S_CQ_SIZE) & M_CQ_SIZE)
-
-#define S_CQ_BASE_HI    0
-#define M_CQ_BASE_HI    0xFFFFF
-#define V_CQ_BASE_HI(x) ((x) << S_CQ_BASE_HI)
-#define G_CQ_BASE_HI(x) (((x) >> S_CQ_BASE_HI) & M_CQ_BASE_HI)
-
-#define S_CQ_RSPQ    20
-#define M_CQ_RSPQ    0x3F
-#define V_CQ_RSPQ(x) ((x) << S_CQ_RSPQ)
-#define G_CQ_RSPQ(x) (((x) >> S_CQ_RSPQ) & M_CQ_RSPQ)
-
-#define S_CQ_ASYNC_NOTIF    26
-#define V_CQ_ASYNC_NOTIF(x) ((x) << S_CQ_ASYNC_NOTIF)
-#define F_CQ_ASYNC_NOTIF    V_CQ_ASYNC_NOTIF(1U)
-
-#define S_CQ_ARMED    27
-#define V_CQ_ARMED(x) ((x) << S_CQ_ARMED)
-#define F_CQ_ARMED    V_CQ_ARMED(1U)
-
-#define S_CQ_ASYNC_NOTIF_SOL    28
-#define V_CQ_ASYNC_NOTIF_SOL(x) ((x) << S_CQ_ASYNC_NOTIF_SOL)
-#define F_CQ_ASYNC_NOTIF_SOL    V_CQ_ASYNC_NOTIF_SOL(1U)
-
-#define S_CQ_GEN    29
-#define V_CQ_GEN(x) ((x) << S_CQ_GEN)
-#define F_CQ_GEN    V_CQ_GEN(1U)
-
-#define S_CQ_ERR    30
-#define V_CQ_ERR(x) ((x) << S_CQ_ERR)
-#define F_CQ_ERR    V_CQ_ERR(1U)
-
-#define S_CQ_OVERFLOW_MODE    31
-#define V_CQ_OVERFLOW_MODE(x) ((x) << S_CQ_OVERFLOW_MODE)
-#define F_CQ_OVERFLOW_MODE    V_CQ_OVERFLOW_MODE(1U)
-
-#define S_CQ_CREDITS    0
-#define M_CQ_CREDITS    0xFFFF
-#define V_CQ_CREDITS(x) ((x) << S_CQ_CREDITS)
-#define G_CQ_CREDITS(x) (((x) >> S_CQ_CREDITS) & M_CQ_CREDITS)
-
-#define S_CQ_CREDIT_THRES    16
-#define M_CQ_CREDIT_THRES    0x1FFF
-#define V_CQ_CREDIT_THRES(x) ((x) << S_CQ_CREDIT_THRES)
-#define G_CQ_CREDIT_THRES(x) (((x) >> S_CQ_CREDIT_THRES) & M_CQ_CREDIT_THRES)
-
-#define S_FL_BASE_HI    0
-#define M_FL_BASE_HI    0xFFFFF
-#define V_FL_BASE_HI(x) ((x) << S_FL_BASE_HI)
-#define G_FL_BASE_HI(x) (((x) >> S_FL_BASE_HI) & M_FL_BASE_HI)
-
-#define S_FL_INDEX_LO    20
-#define M_FL_INDEX_LO    0xFFF
-#define V_FL_INDEX_LO(x) ((x) << S_FL_INDEX_LO)
-#define G_FL_INDEX_LO(x) (((x) >> S_FL_INDEX_LO) & M_FL_INDEX_LO)
-
-#define S_FL_INDEX_HI    0
-#define M_FL_INDEX_HI    0xF
-#define V_FL_INDEX_HI(x) ((x) << S_FL_INDEX_HI)
-#define G_FL_INDEX_HI(x) (((x) >> S_FL_INDEX_HI) & M_FL_INDEX_HI)
-
-#define S_FL_SIZE    4
-#define M_FL_SIZE    0xFFFF
-#define V_FL_SIZE(x) ((x) << S_FL_SIZE)
-#define G_FL_SIZE(x) (((x) >> S_FL_SIZE) & M_FL_SIZE)
-
-#define S_FL_GEN    20
-#define V_FL_GEN(x) ((x) << S_FL_GEN)
-#define F_FL_GEN    V_FL_GEN(1U)
-
-#define S_FL_ENTRY_SIZE_LO    21
-#define M_FL_ENTRY_SIZE_LO    0x7FF
-#define V_FL_ENTRY_SIZE_LO(x) ((x) << S_FL_ENTRY_SIZE_LO)
-#define G_FL_ENTRY_SIZE_LO(x) (((x) >> S_FL_ENTRY_SIZE_LO) & M_FL_ENTRY_SIZE_LO)
-
-#define S_FL_ENTRY_SIZE_HI    0
-#define M_FL_ENTRY_SIZE_HI    0x1FFFFF
-#define V_FL_ENTRY_SIZE_HI(x) ((x) << S_FL_ENTRY_SIZE_HI)
-#define G_FL_ENTRY_SIZE_HI(x) (((x) >> S_FL_ENTRY_SIZE_HI) & M_FL_ENTRY_SIZE_HI)
-
-#define S_FL_CONG_THRES    21
-#define M_FL_CONG_THRES    0x3FF
-#define V_FL_CONG_THRES(x) ((x) << S_FL_CONG_THRES)
-#define G_FL_CONG_THRES(x) (((x) >> S_FL_CONG_THRES) & M_FL_CONG_THRES)
-
-#define S_FL_GTS    31
-#define V_FL_GTS(x) ((x) << S_FL_GTS)
-#define F_FL_GTS    V_FL_GTS(1U)
-
-#define S_FLD_GEN1    31
-#define V_FLD_GEN1(x) ((x) << S_FLD_GEN1)
-#define F_FLD_GEN1    V_FLD_GEN1(1U)
-
-#define S_FLD_GEN2    0
-#define V_FLD_GEN2(x) ((x) << S_FLD_GEN2)
-#define F_FLD_GEN2    V_FLD_GEN2(1U)
-
-#define S_RSPD_TXQ1_CR    0
-#define M_RSPD_TXQ1_CR    0x7F
-#define V_RSPD_TXQ1_CR(x) ((x) << S_RSPD_TXQ1_CR)
-#define G_RSPD_TXQ1_CR(x) (((x) >> S_RSPD_TXQ1_CR) & M_RSPD_TXQ1_CR)
-
-#define S_RSPD_TXQ1_GTS    7
-#define V_RSPD_TXQ1_GTS(x) ((x) << S_RSPD_TXQ1_GTS)
-#define F_RSPD_TXQ1_GTS    V_RSPD_TXQ1_GTS(1U)
-
-#define S_RSPD_TXQ2_CR    8
-#define M_RSPD_TXQ2_CR    0x7F
-#define V_RSPD_TXQ2_CR(x) ((x) << S_RSPD_TXQ2_CR)
-#define G_RSPD_TXQ2_CR(x) (((x) >> S_RSPD_TXQ2_CR) & M_RSPD_TXQ2_CR)
-
-#define S_RSPD_TXQ2_GTS    15
-#define V_RSPD_TXQ2_GTS(x) ((x) << S_RSPD_TXQ2_GTS)
-#define F_RSPD_TXQ2_GTS    V_RSPD_TXQ2_GTS(1U)
-
-#define S_RSPD_TXQ0_CR    16
-#define M_RSPD_TXQ0_CR    0x7F
-#define V_RSPD_TXQ0_CR(x) ((x) << S_RSPD_TXQ0_CR)
-#define G_RSPD_TXQ0_CR(x) (((x) >> S_RSPD_TXQ0_CR) & M_RSPD_TXQ0_CR)
-
-#define S_RSPD_TXQ0_GTS    23
-#define V_RSPD_TXQ0_GTS(x) ((x) << S_RSPD_TXQ0_GTS)
-#define F_RSPD_TXQ0_GTS    V_RSPD_TXQ0_GTS(1U)
-
-#define S_RSPD_EOP    24
-#define V_RSPD_EOP(x) ((x) << S_RSPD_EOP)
-#define F_RSPD_EOP    V_RSPD_EOP(1U)
-
-#define S_RSPD_SOP    25
-#define V_RSPD_SOP(x) ((x) << S_RSPD_SOP)
-#define F_RSPD_SOP    V_RSPD_SOP(1U)
-
-#define S_RSPD_ASYNC_NOTIF    26
-#define V_RSPD_ASYNC_NOTIF(x) ((x) << S_RSPD_ASYNC_NOTIF)
-#define F_RSPD_ASYNC_NOTIF    V_RSPD_ASYNC_NOTIF(1U)
-
-#define S_RSPD_FL0_GTS    27
-#define V_RSPD_FL0_GTS(x) ((x) << S_RSPD_FL0_GTS)
-#define F_RSPD_FL0_GTS    V_RSPD_FL0_GTS(1U)
-
-#define S_RSPD_FL1_GTS    28
-#define V_RSPD_FL1_GTS(x) ((x) << S_RSPD_FL1_GTS)
-#define F_RSPD_FL1_GTS    V_RSPD_FL1_GTS(1U)
-
-#define S_RSPD_IMM_DATA_VALID    29
-#define V_RSPD_IMM_DATA_VALID(x) ((x) << S_RSPD_IMM_DATA_VALID)
-#define F_RSPD_IMM_DATA_VALID    V_RSPD_IMM_DATA_VALID(1U)
-
-#define S_RSPD_OFFLOAD    30
-#define V_RSPD_OFFLOAD(x) ((x) << S_RSPD_OFFLOAD)
-#define F_RSPD_OFFLOAD    V_RSPD_OFFLOAD(1U)
-
-#define S_RSPD_GEN1    31
-#define V_RSPD_GEN1(x) ((x) << S_RSPD_GEN1)
-#define F_RSPD_GEN1    V_RSPD_GEN1(1U)
-
-#define S_RSPD_LEN    0
-#define M_RSPD_LEN    0x7FFFFFFF
-#define V_RSPD_LEN(x) ((x) << S_RSPD_LEN)
-#define G_RSPD_LEN(x) (((x) >> S_RSPD_LEN) & M_RSPD_LEN)
-
-#define S_RSPD_FLQ    31
-#define V_RSPD_FLQ(x) ((x) << S_RSPD_FLQ)
-#define F_RSPD_FLQ    V_RSPD_FLQ(1U)
-
-#define S_RSPD_GEN2    0
-#define V_RSPD_GEN2(x) ((x) << S_RSPD_GEN2)
-#define F_RSPD_GEN2    V_RSPD_GEN2(1U)
-
-#define S_RSPD_INR_VEC    1
-#define M_RSPD_INR_VEC    0x7F
-#define V_RSPD_INR_VEC(x) ((x) << S_RSPD_INR_VEC)
-#define G_RSPD_INR_VEC(x) (((x) >> S_RSPD_INR_VEC) & M_RSPD_INR_VEC)
-
-#endif				/* _SGE_DEFS_H */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/t3cdev.h linux-libre-3.2-gnu/drivers/net/cxgb3/t3cdev.h
--- linux-libre-3.1-gnu/drivers/net/cxgb3/t3cdev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/t3cdev.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2006-2008 Chelsio Communications.  All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef _T3CDEV_H_
-#define _T3CDEV_H_
-
-#include <linux/list.h>
-#include <linux/atomic.h>
-#include <linux/netdevice.h>
-#include <linux/proc_fs.h>
-#include <linux/skbuff.h>
-#include <net/neighbour.h>
-
-#define T3CNAMSIZ 16
-
-struct cxgb3_client;
-
-enum t3ctype {
-	T3A = 0,
-	T3B,
-	T3C,
-};
-
-struct t3cdev {
-	char name[T3CNAMSIZ];	/* T3C device name */
-	enum t3ctype type;
-	struct list_head ofld_dev_list;	/* for list linking */
-	struct net_device *lldev;	/* LL dev associated with T3C messages */
-	struct proc_dir_entry *proc_dir;	/* root of proc dir for this T3C */
-	int (*send)(struct t3cdev *dev, struct sk_buff *skb);
-	int (*recv)(struct t3cdev *dev, struct sk_buff **skb, int n);
-	int (*ctl)(struct t3cdev *dev, unsigned int req, void *data);
-	void (*neigh_update)(struct t3cdev *dev, struct neighbour *neigh);
-	void *priv;		/* driver private data */
-	void *l2opt;		/* optional layer 2 data */
-	void *l3opt;		/* optional layer 3 data */
-	void *l4opt;		/* optional layer 4 data */
-	void *ulp;		/* ulp stuff */
-	void *ulp_iscsi;	/* ulp iscsi */
-};
-
-#endif				/* _T3CDEV_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/t3_cpl.h linux-libre-3.2-gnu/drivers/net/cxgb3/t3_cpl.h
--- linux-libre-3.1-gnu/drivers/net/cxgb3/t3_cpl.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/t3_cpl.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1495 +0,0 @@
-/*
- * Copyright (c) 2004-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef T3_CPL_H
-#define T3_CPL_H
-
-#if !defined(__LITTLE_ENDIAN_BITFIELD) && !defined(__BIG_ENDIAN_BITFIELD)
-# include <asm/byteorder.h>
-#endif
-
-enum CPL_opcode {
-	CPL_PASS_OPEN_REQ = 0x1,
-	CPL_PASS_ACCEPT_RPL = 0x2,
-	CPL_ACT_OPEN_REQ = 0x3,
-	CPL_SET_TCB = 0x4,
-	CPL_SET_TCB_FIELD = 0x5,
-	CPL_GET_TCB = 0x6,
-	CPL_PCMD = 0x7,
-	CPL_CLOSE_CON_REQ = 0x8,
-	CPL_CLOSE_LISTSRV_REQ = 0x9,
-	CPL_ABORT_REQ = 0xA,
-	CPL_ABORT_RPL = 0xB,
-	CPL_TX_DATA = 0xC,
-	CPL_RX_DATA_ACK = 0xD,
-	CPL_TX_PKT = 0xE,
-	CPL_RTE_DELETE_REQ = 0xF,
-	CPL_RTE_WRITE_REQ = 0x10,
-	CPL_RTE_READ_REQ = 0x11,
-	CPL_L2T_WRITE_REQ = 0x12,
-	CPL_L2T_READ_REQ = 0x13,
-	CPL_SMT_WRITE_REQ = 0x14,
-	CPL_SMT_READ_REQ = 0x15,
-	CPL_TX_PKT_LSO = 0x16,
-	CPL_PCMD_READ = 0x17,
-	CPL_BARRIER = 0x18,
-	CPL_TID_RELEASE = 0x1A,
-
-	CPL_CLOSE_LISTSRV_RPL = 0x20,
-	CPL_ERROR = 0x21,
-	CPL_GET_TCB_RPL = 0x22,
-	CPL_L2T_WRITE_RPL = 0x23,
-	CPL_PCMD_READ_RPL = 0x24,
-	CPL_PCMD_RPL = 0x25,
-	CPL_PEER_CLOSE = 0x26,
-	CPL_RTE_DELETE_RPL = 0x27,
-	CPL_RTE_WRITE_RPL = 0x28,
-	CPL_RX_DDP_COMPLETE = 0x29,
-	CPL_RX_PHYS_ADDR = 0x2A,
-	CPL_RX_PKT = 0x2B,
-	CPL_RX_URG_NOTIFY = 0x2C,
-	CPL_SET_TCB_RPL = 0x2D,
-	CPL_SMT_WRITE_RPL = 0x2E,
-	CPL_TX_DATA_ACK = 0x2F,
-
-	CPL_ABORT_REQ_RSS = 0x30,
-	CPL_ABORT_RPL_RSS = 0x31,
-	CPL_CLOSE_CON_RPL = 0x32,
-	CPL_ISCSI_HDR = 0x33,
-	CPL_L2T_READ_RPL = 0x34,
-	CPL_RDMA_CQE = 0x35,
-	CPL_RDMA_CQE_READ_RSP = 0x36,
-	CPL_RDMA_CQE_ERR = 0x37,
-	CPL_RTE_READ_RPL = 0x38,
-	CPL_RX_DATA = 0x39,
-
-	CPL_ACT_OPEN_RPL = 0x40,
-	CPL_PASS_OPEN_RPL = 0x41,
-	CPL_RX_DATA_DDP = 0x42,
-	CPL_SMT_READ_RPL = 0x43,
-
-	CPL_ACT_ESTABLISH = 0x50,
-	CPL_PASS_ESTABLISH = 0x51,
-
-	CPL_PASS_ACCEPT_REQ = 0x70,
-
-	CPL_ASYNC_NOTIF = 0x80,	/* fake opcode for async notifications */
-
-	CPL_TX_DMA_ACK = 0xA0,
-	CPL_RDMA_READ_REQ = 0xA1,
-	CPL_RDMA_TERMINATE = 0xA2,
-	CPL_TRACE_PKT = 0xA3,
-	CPL_RDMA_EC_STATUS = 0xA5,
-
-	NUM_CPL_CMDS		/* must be last and previous entries must be sorted */
-};
-
-enum CPL_error {
-	CPL_ERR_NONE = 0,
-	CPL_ERR_TCAM_PARITY = 1,
-	CPL_ERR_TCAM_FULL = 3,
-	CPL_ERR_CONN_RESET = 20,
-	CPL_ERR_CONN_EXIST = 22,
-	CPL_ERR_ARP_MISS = 23,
-	CPL_ERR_BAD_SYN = 24,
-	CPL_ERR_CONN_TIMEDOUT = 30,
-	CPL_ERR_XMIT_TIMEDOUT = 31,
-	CPL_ERR_PERSIST_TIMEDOUT = 32,
-	CPL_ERR_FINWAIT2_TIMEDOUT = 33,
-	CPL_ERR_KEEPALIVE_TIMEDOUT = 34,
-	CPL_ERR_RTX_NEG_ADVICE = 35,
-	CPL_ERR_PERSIST_NEG_ADVICE = 36,
-	CPL_ERR_ABORT_FAILED = 42,
-	CPL_ERR_GENERAL = 99
-};
-
-enum {
-	CPL_CONN_POLICY_AUTO = 0,
-	CPL_CONN_POLICY_ASK = 1,
-	CPL_CONN_POLICY_DENY = 3
-};
-
-enum {
-	ULP_MODE_NONE = 0,
-	ULP_MODE_ISCSI = 2,
-	ULP_MODE_RDMA = 4,
-	ULP_MODE_TCPDDP = 5
-};
-
-enum {
-	ULP_CRC_HEADER = 1 << 0,
-	ULP_CRC_DATA = 1 << 1
-};
-
-enum {
-	CPL_PASS_OPEN_ACCEPT,
-	CPL_PASS_OPEN_REJECT
-};
-
-enum {
-	CPL_ABORT_SEND_RST = 0,
-	CPL_ABORT_NO_RST,
-	CPL_ABORT_POST_CLOSE_REQ = 2
-};
-
-enum {				/* TX_PKT_LSO ethernet types */
-	CPL_ETH_II,
-	CPL_ETH_II_VLAN,
-	CPL_ETH_802_3,
-	CPL_ETH_802_3_VLAN
-};
-
-enum {				/* TCP congestion control algorithms */
-	CONG_ALG_RENO,
-	CONG_ALG_TAHOE,
-	CONG_ALG_NEWRENO,
-	CONG_ALG_HIGHSPEED
-};
-
-enum {			/* RSS hash type */
-	RSS_HASH_NONE = 0,
-	RSS_HASH_2_TUPLE = 1,
-	RSS_HASH_4_TUPLE = 2,
-	RSS_HASH_TCPV6 = 3
-};
-
-union opcode_tid {
-	__be32 opcode_tid;
-	__u8 opcode;
-};
-
-#define S_OPCODE 24
-#define V_OPCODE(x) ((x) << S_OPCODE)
-#define G_OPCODE(x) (((x) >> S_OPCODE) & 0xFF)
-#define G_TID(x)    ((x) & 0xFFFFFF)
-
-#define S_QNUM 0
-#define G_QNUM(x) (((x) >> S_QNUM) & 0xFFFF)
-
-#define S_HASHTYPE 22
-#define M_HASHTYPE 0x3
-#define G_HASHTYPE(x) (((x) >> S_HASHTYPE) & M_HASHTYPE)
-
-/* tid is assumed to be 24-bits */
-#define MK_OPCODE_TID(opcode, tid) (V_OPCODE(opcode) | (tid))
-
-#define OPCODE_TID(cmd) ((cmd)->ot.opcode_tid)
-
-/* extract the TID from a CPL command */
-#define GET_TID(cmd) (G_TID(ntohl(OPCODE_TID(cmd))))
-
-struct tcp_options {
-	__be16 mss;
-	__u8 wsf;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	 __u8:5;
-	__u8 ecn:1;
-	__u8 sack:1;
-	__u8 tstamp:1;
-#else
-	__u8 tstamp:1;
-	__u8 sack:1;
-	__u8 ecn:1;
-	 __u8:5;
-#endif
-};
-
-struct rss_header {
-	__u8 opcode;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8 cpu_idx:6;
-	__u8 hash_type:2;
-#else
-	__u8 hash_type:2;
-	__u8 cpu_idx:6;
-#endif
-	__be16 cq_idx;
-	__be32 rss_hash_val;
-};
-
-#ifndef CHELSIO_FW
-struct work_request_hdr {
-	__be32 wr_hi;
-	__be32 wr_lo;
-};
-
-/* wr_hi fields */
-#define S_WR_SGE_CREDITS    0
-#define M_WR_SGE_CREDITS    0xFF
-#define V_WR_SGE_CREDITS(x) ((x) << S_WR_SGE_CREDITS)
-#define G_WR_SGE_CREDITS(x) (((x) >> S_WR_SGE_CREDITS) & M_WR_SGE_CREDITS)
-
-#define S_WR_SGLSFLT    8
-#define M_WR_SGLSFLT    0xFF
-#define V_WR_SGLSFLT(x) ((x) << S_WR_SGLSFLT)
-#define G_WR_SGLSFLT(x) (((x) >> S_WR_SGLSFLT) & M_WR_SGLSFLT)
-
-#define S_WR_BCNTLFLT    16
-#define M_WR_BCNTLFLT    0xF
-#define V_WR_BCNTLFLT(x) ((x) << S_WR_BCNTLFLT)
-#define G_WR_BCNTLFLT(x) (((x) >> S_WR_BCNTLFLT) & M_WR_BCNTLFLT)
-
-#define S_WR_DATATYPE    20
-#define V_WR_DATATYPE(x) ((x) << S_WR_DATATYPE)
-#define F_WR_DATATYPE    V_WR_DATATYPE(1U)
-
-#define S_WR_COMPL    21
-#define V_WR_COMPL(x) ((x) << S_WR_COMPL)
-#define F_WR_COMPL    V_WR_COMPL(1U)
-
-#define S_WR_EOP    22
-#define V_WR_EOP(x) ((x) << S_WR_EOP)
-#define F_WR_EOP    V_WR_EOP(1U)
-
-#define S_WR_SOP    23
-#define V_WR_SOP(x) ((x) << S_WR_SOP)
-#define F_WR_SOP    V_WR_SOP(1U)
-
-#define S_WR_OP    24
-#define M_WR_OP    0xFF
-#define V_WR_OP(x) ((x) << S_WR_OP)
-#define G_WR_OP(x) (((x) >> S_WR_OP) & M_WR_OP)
-
-/* wr_lo fields */
-#define S_WR_LEN    0
-#define M_WR_LEN    0xFF
-#define V_WR_LEN(x) ((x) << S_WR_LEN)
-#define G_WR_LEN(x) (((x) >> S_WR_LEN) & M_WR_LEN)
-
-#define S_WR_TID    8
-#define M_WR_TID    0xFFFFF
-#define V_WR_TID(x) ((x) << S_WR_TID)
-#define G_WR_TID(x) (((x) >> S_WR_TID) & M_WR_TID)
-
-#define S_WR_CR_FLUSH    30
-#define V_WR_CR_FLUSH(x) ((x) << S_WR_CR_FLUSH)
-#define F_WR_CR_FLUSH    V_WR_CR_FLUSH(1U)
-
-#define S_WR_GEN    31
-#define V_WR_GEN(x) ((x) << S_WR_GEN)
-#define F_WR_GEN    V_WR_GEN(1U)
-
-# define WR_HDR struct work_request_hdr wr
-# define RSS_HDR
-#else
-# define WR_HDR
-# define RSS_HDR struct rss_header rss_hdr;
-#endif
-
-/* option 0 lower-half fields */
-#define S_CPL_STATUS    0
-#define M_CPL_STATUS    0xFF
-#define V_CPL_STATUS(x) ((x) << S_CPL_STATUS)
-#define G_CPL_STATUS(x) (((x) >> S_CPL_STATUS) & M_CPL_STATUS)
-
-#define S_INJECT_TIMER    6
-#define V_INJECT_TIMER(x) ((x) << S_INJECT_TIMER)
-#define F_INJECT_TIMER    V_INJECT_TIMER(1U)
-
-#define S_NO_OFFLOAD    7
-#define V_NO_OFFLOAD(x) ((x) << S_NO_OFFLOAD)
-#define F_NO_OFFLOAD    V_NO_OFFLOAD(1U)
-
-#define S_ULP_MODE    8
-#define M_ULP_MODE    0xF
-#define V_ULP_MODE(x) ((x) << S_ULP_MODE)
-#define G_ULP_MODE(x) (((x) >> S_ULP_MODE) & M_ULP_MODE)
-
-#define S_RCV_BUFSIZ    12
-#define M_RCV_BUFSIZ    0x3FFF
-#define V_RCV_BUFSIZ(x) ((x) << S_RCV_BUFSIZ)
-#define G_RCV_BUFSIZ(x) (((x) >> S_RCV_BUFSIZ) & M_RCV_BUFSIZ)
-
-#define S_TOS    26
-#define M_TOS    0x3F
-#define V_TOS(x) ((x) << S_TOS)
-#define G_TOS(x) (((x) >> S_TOS) & M_TOS)
-
-/* option 0 upper-half fields */
-#define S_DELACK    0
-#define V_DELACK(x) ((x) << S_DELACK)
-#define F_DELACK    V_DELACK(1U)
-
-#define S_NO_CONG    1
-#define V_NO_CONG(x) ((x) << S_NO_CONG)
-#define F_NO_CONG    V_NO_CONG(1U)
-
-#define S_SRC_MAC_SEL    2
-#define M_SRC_MAC_SEL    0x3
-#define V_SRC_MAC_SEL(x) ((x) << S_SRC_MAC_SEL)
-#define G_SRC_MAC_SEL(x) (((x) >> S_SRC_MAC_SEL) & M_SRC_MAC_SEL)
-
-#define S_L2T_IDX    4
-#define M_L2T_IDX    0x7FF
-#define V_L2T_IDX(x) ((x) << S_L2T_IDX)
-#define G_L2T_IDX(x) (((x) >> S_L2T_IDX) & M_L2T_IDX)
-
-#define S_TX_CHANNEL    15
-#define V_TX_CHANNEL(x) ((x) << S_TX_CHANNEL)
-#define F_TX_CHANNEL    V_TX_CHANNEL(1U)
-
-#define S_TCAM_BYPASS    16
-#define V_TCAM_BYPASS(x) ((x) << S_TCAM_BYPASS)
-#define F_TCAM_BYPASS    V_TCAM_BYPASS(1U)
-
-#define S_NAGLE    17
-#define V_NAGLE(x) ((x) << S_NAGLE)
-#define F_NAGLE    V_NAGLE(1U)
-
-#define S_WND_SCALE    18
-#define M_WND_SCALE    0xF
-#define V_WND_SCALE(x) ((x) << S_WND_SCALE)
-#define G_WND_SCALE(x) (((x) >> S_WND_SCALE) & M_WND_SCALE)
-
-#define S_KEEP_ALIVE    22
-#define V_KEEP_ALIVE(x) ((x) << S_KEEP_ALIVE)
-#define F_KEEP_ALIVE    V_KEEP_ALIVE(1U)
-
-#define S_MAX_RETRANS    23
-#define M_MAX_RETRANS    0xF
-#define V_MAX_RETRANS(x) ((x) << S_MAX_RETRANS)
-#define G_MAX_RETRANS(x) (((x) >> S_MAX_RETRANS) & M_MAX_RETRANS)
-
-#define S_MAX_RETRANS_OVERRIDE    27
-#define V_MAX_RETRANS_OVERRIDE(x) ((x) << S_MAX_RETRANS_OVERRIDE)
-#define F_MAX_RETRANS_OVERRIDE    V_MAX_RETRANS_OVERRIDE(1U)
-
-#define S_MSS_IDX    28
-#define M_MSS_IDX    0xF
-#define V_MSS_IDX(x) ((x) << S_MSS_IDX)
-#define G_MSS_IDX(x) (((x) >> S_MSS_IDX) & M_MSS_IDX)
-
-/* option 1 fields */
-#define S_RSS_ENABLE    0
-#define V_RSS_ENABLE(x) ((x) << S_RSS_ENABLE)
-#define F_RSS_ENABLE    V_RSS_ENABLE(1U)
-
-#define S_RSS_MASK_LEN    1
-#define M_RSS_MASK_LEN    0x7
-#define V_RSS_MASK_LEN(x) ((x) << S_RSS_MASK_LEN)
-#define G_RSS_MASK_LEN(x) (((x) >> S_RSS_MASK_LEN) & M_RSS_MASK_LEN)
-
-#define S_CPU_IDX    4
-#define M_CPU_IDX    0x3F
-#define V_CPU_IDX(x) ((x) << S_CPU_IDX)
-#define G_CPU_IDX(x) (((x) >> S_CPU_IDX) & M_CPU_IDX)
-
-#define S_MAC_MATCH_VALID    18
-#define V_MAC_MATCH_VALID(x) ((x) << S_MAC_MATCH_VALID)
-#define F_MAC_MATCH_VALID    V_MAC_MATCH_VALID(1U)
-
-#define S_CONN_POLICY    19
-#define M_CONN_POLICY    0x3
-#define V_CONN_POLICY(x) ((x) << S_CONN_POLICY)
-#define G_CONN_POLICY(x) (((x) >> S_CONN_POLICY) & M_CONN_POLICY)
-
-#define S_SYN_DEFENSE    21
-#define V_SYN_DEFENSE(x) ((x) << S_SYN_DEFENSE)
-#define F_SYN_DEFENSE    V_SYN_DEFENSE(1U)
-
-#define S_VLAN_PRI    22
-#define M_VLAN_PRI    0x3
-#define V_VLAN_PRI(x) ((x) << S_VLAN_PRI)
-#define G_VLAN_PRI(x) (((x) >> S_VLAN_PRI) & M_VLAN_PRI)
-
-#define S_VLAN_PRI_VALID    24
-#define V_VLAN_PRI_VALID(x) ((x) << S_VLAN_PRI_VALID)
-#define F_VLAN_PRI_VALID    V_VLAN_PRI_VALID(1U)
-
-#define S_PKT_TYPE    25
-#define M_PKT_TYPE    0x3
-#define V_PKT_TYPE(x) ((x) << S_PKT_TYPE)
-#define G_PKT_TYPE(x) (((x) >> S_PKT_TYPE) & M_PKT_TYPE)
-
-#define S_MAC_MATCH    27
-#define M_MAC_MATCH    0x1F
-#define V_MAC_MATCH(x) ((x) << S_MAC_MATCH)
-#define G_MAC_MATCH(x) (((x) >> S_MAC_MATCH) & M_MAC_MATCH)
-
-/* option 2 fields */
-#define S_CPU_INDEX    0
-#define M_CPU_INDEX    0x7F
-#define V_CPU_INDEX(x) ((x) << S_CPU_INDEX)
-#define G_CPU_INDEX(x) (((x) >> S_CPU_INDEX) & M_CPU_INDEX)
-
-#define S_CPU_INDEX_VALID    7
-#define V_CPU_INDEX_VALID(x) ((x) << S_CPU_INDEX_VALID)
-#define F_CPU_INDEX_VALID    V_CPU_INDEX_VALID(1U)
-
-#define S_RX_COALESCE    8
-#define M_RX_COALESCE    0x3
-#define V_RX_COALESCE(x) ((x) << S_RX_COALESCE)
-#define G_RX_COALESCE(x) (((x) >> S_RX_COALESCE) & M_RX_COALESCE)
-
-#define S_RX_COALESCE_VALID    10
-#define V_RX_COALESCE_VALID(x) ((x) << S_RX_COALESCE_VALID)
-#define F_RX_COALESCE_VALID    V_RX_COALESCE_VALID(1U)
-
-#define S_CONG_CONTROL_FLAVOR    11
-#define M_CONG_CONTROL_FLAVOR    0x3
-#define V_CONG_CONTROL_FLAVOR(x) ((x) << S_CONG_CONTROL_FLAVOR)
-#define G_CONG_CONTROL_FLAVOR(x) (((x) >> S_CONG_CONTROL_FLAVOR) & M_CONG_CONTROL_FLAVOR)
-
-#define S_PACING_FLAVOR    13
-#define M_PACING_FLAVOR    0x3
-#define V_PACING_FLAVOR(x) ((x) << S_PACING_FLAVOR)
-#define G_PACING_FLAVOR(x) (((x) >> S_PACING_FLAVOR) & M_PACING_FLAVOR)
-
-#define S_FLAVORS_VALID    15
-#define V_FLAVORS_VALID(x) ((x) << S_FLAVORS_VALID)
-#define F_FLAVORS_VALID    V_FLAVORS_VALID(1U)
-
-#define S_RX_FC_DISABLE    16
-#define V_RX_FC_DISABLE(x) ((x) << S_RX_FC_DISABLE)
-#define F_RX_FC_DISABLE    V_RX_FC_DISABLE(1U)
-
-#define S_RX_FC_VALID    17
-#define V_RX_FC_VALID(x) ((x) << S_RX_FC_VALID)
-#define F_RX_FC_VALID    V_RX_FC_VALID(1U)
-
-struct cpl_pass_open_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__be16 local_port;
-	__be16 peer_port;
-	__be32 local_ip;
-	__be32 peer_ip;
-	__be32 opt0h;
-	__be32 opt0l;
-	__be32 peer_netmask;
-	__be32 opt1;
-};
-
-struct cpl_pass_open_rpl {
-	RSS_HDR union opcode_tid ot;
-	__be16 local_port;
-	__be16 peer_port;
-	__be32 local_ip;
-	__be32 peer_ip;
-	__u8 resvd[7];
-	__u8 status;
-};
-
-struct cpl_pass_establish {
-	RSS_HDR union opcode_tid ot;
-	__be16 local_port;
-	__be16 peer_port;
-	__be32 local_ip;
-	__be32 peer_ip;
-	__be32 tos_tid;
-	__be16 l2t_idx;
-	__be16 tcp_opt;
-	__be32 snd_isn;
-	__be32 rcv_isn;
-};
-
-/* cpl_pass_establish.tos_tid fields */
-#define S_PASS_OPEN_TID    0
-#define M_PASS_OPEN_TID    0xFFFFFF
-#define V_PASS_OPEN_TID(x) ((x) << S_PASS_OPEN_TID)
-#define G_PASS_OPEN_TID(x) (((x) >> S_PASS_OPEN_TID) & M_PASS_OPEN_TID)
-
-#define S_PASS_OPEN_TOS    24
-#define M_PASS_OPEN_TOS    0xFF
-#define V_PASS_OPEN_TOS(x) ((x) << S_PASS_OPEN_TOS)
-#define G_PASS_OPEN_TOS(x) (((x) >> S_PASS_OPEN_TOS) & M_PASS_OPEN_TOS)
-
-/* cpl_pass_establish.l2t_idx fields */
-#define S_L2T_IDX16    5
-#define M_L2T_IDX16    0x7FF
-#define V_L2T_IDX16(x) ((x) << S_L2T_IDX16)
-#define G_L2T_IDX16(x) (((x) >> S_L2T_IDX16) & M_L2T_IDX16)
-
-/* cpl_pass_establish.tcp_opt fields (also applies act_open_establish) */
-#define G_TCPOPT_WSCALE_OK(x)  (((x) >> 5) & 1)
-#define G_TCPOPT_SACK(x)       (((x) >> 6) & 1)
-#define G_TCPOPT_TSTAMP(x)     (((x) >> 7) & 1)
-#define G_TCPOPT_SND_WSCALE(x) (((x) >> 8) & 0xf)
-#define G_TCPOPT_MSS(x)        (((x) >> 12) & 0xf)
-
-struct cpl_pass_accept_req {
-	RSS_HDR union opcode_tid ot;
-	__be16 local_port;
-	__be16 peer_port;
-	__be32 local_ip;
-	__be32 peer_ip;
-	__be32 tos_tid;
-	struct tcp_options tcp_options;
-	__u8 dst_mac[6];
-	__be16 vlan_tag;
-	__u8 src_mac[6];
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	 __u8:3;
-	__u8 addr_idx:3;
-	__u8 port_idx:1;
-	__u8 exact_match:1;
-#else
-	__u8 exact_match:1;
-	__u8 port_idx:1;
-	__u8 addr_idx:3;
-	 __u8:3;
-#endif
-	__u8 rsvd;
-	__be32 rcv_isn;
-	__be32 rsvd2;
-};
-
-struct cpl_pass_accept_rpl {
-	WR_HDR;
-	union opcode_tid ot;
-	__be32 opt2;
-	__be32 rsvd;
-	__be32 peer_ip;
-	__be32 opt0h;
-	__be32 opt0l_status;
-};
-
-struct cpl_act_open_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__be16 local_port;
-	__be16 peer_port;
-	__be32 local_ip;
-	__be32 peer_ip;
-	__be32 opt0h;
-	__be32 opt0l;
-	__be32 params;
-	__be32 opt2;
-};
-
-/* cpl_act_open_req.params fields */
-#define S_AOPEN_VLAN_PRI    9
-#define M_AOPEN_VLAN_PRI    0x3
-#define V_AOPEN_VLAN_PRI(x) ((x) << S_AOPEN_VLAN_PRI)
-#define G_AOPEN_VLAN_PRI(x) (((x) >> S_AOPEN_VLAN_PRI) & M_AOPEN_VLAN_PRI)
-
-#define S_AOPEN_VLAN_PRI_VALID    11
-#define V_AOPEN_VLAN_PRI_VALID(x) ((x) << S_AOPEN_VLAN_PRI_VALID)
-#define F_AOPEN_VLAN_PRI_VALID    V_AOPEN_VLAN_PRI_VALID(1U)
-
-#define S_AOPEN_PKT_TYPE    12
-#define M_AOPEN_PKT_TYPE    0x3
-#define V_AOPEN_PKT_TYPE(x) ((x) << S_AOPEN_PKT_TYPE)
-#define G_AOPEN_PKT_TYPE(x) (((x) >> S_AOPEN_PKT_TYPE) & M_AOPEN_PKT_TYPE)
-
-#define S_AOPEN_MAC_MATCH    14
-#define M_AOPEN_MAC_MATCH    0x1F
-#define V_AOPEN_MAC_MATCH(x) ((x) << S_AOPEN_MAC_MATCH)
-#define G_AOPEN_MAC_MATCH(x) (((x) >> S_AOPEN_MAC_MATCH) & M_AOPEN_MAC_MATCH)
-
-#define S_AOPEN_MAC_MATCH_VALID    19
-#define V_AOPEN_MAC_MATCH_VALID(x) ((x) << S_AOPEN_MAC_MATCH_VALID)
-#define F_AOPEN_MAC_MATCH_VALID    V_AOPEN_MAC_MATCH_VALID(1U)
-
-#define S_AOPEN_IFF_VLAN    20
-#define M_AOPEN_IFF_VLAN    0xFFF
-#define V_AOPEN_IFF_VLAN(x) ((x) << S_AOPEN_IFF_VLAN)
-#define G_AOPEN_IFF_VLAN(x) (((x) >> S_AOPEN_IFF_VLAN) & M_AOPEN_IFF_VLAN)
-
-struct cpl_act_open_rpl {
-	RSS_HDR union opcode_tid ot;
-	__be16 local_port;
-	__be16 peer_port;
-	__be32 local_ip;
-	__be32 peer_ip;
-	__be32 atid;
-	__u8 rsvd[3];
-	__u8 status;
-};
-
-struct cpl_act_establish {
-	RSS_HDR union opcode_tid ot;
-	__be16 local_port;
-	__be16 peer_port;
-	__be32 local_ip;
-	__be32 peer_ip;
-	__be32 tos_tid;
-	__be16 l2t_idx;
-	__be16 tcp_opt;
-	__be32 snd_isn;
-	__be32 rcv_isn;
-};
-
-struct cpl_get_tcb {
-	WR_HDR;
-	union opcode_tid ot;
-	__be16 cpuno;
-	__be16 rsvd;
-};
-
-struct cpl_get_tcb_rpl {
-	RSS_HDR union opcode_tid ot;
-	__u8 rsvd;
-	__u8 status;
-	__be16 len;
-};
-
-struct cpl_set_tcb {
-	WR_HDR;
-	union opcode_tid ot;
-	__u8 reply;
-	__u8 cpu_idx;
-	__be16 len;
-};
-
-/* cpl_set_tcb.reply fields */
-#define S_NO_REPLY    7
-#define V_NO_REPLY(x) ((x) << S_NO_REPLY)
-#define F_NO_REPLY    V_NO_REPLY(1U)
-
-struct cpl_set_tcb_field {
-	WR_HDR;
-	union opcode_tid ot;
-	__u8 reply;
-	__u8 cpu_idx;
-	__be16 word;
-	__be64 mask;
-	__be64 val;
-};
-
-struct cpl_set_tcb_rpl {
-	RSS_HDR union opcode_tid ot;
-	__u8 rsvd[3];
-	__u8 status;
-};
-
-struct cpl_pcmd {
-	WR_HDR;
-	union opcode_tid ot;
-	__u8 rsvd[3];
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8 src:1;
-	__u8 bundle:1;
-	__u8 channel:1;
-	 __u8:5;
-#else
-	 __u8:5;
-	__u8 channel:1;
-	__u8 bundle:1;
-	__u8 src:1;
-#endif
-	__be32 pcmd_parm[2];
-};
-
-struct cpl_pcmd_reply {
-	RSS_HDR union opcode_tid ot;
-	__u8 status;
-	__u8 rsvd;
-	__be16 len;
-};
-
-struct cpl_close_con_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__be32 rsvd;
-};
-
-struct cpl_close_con_rpl {
-	RSS_HDR union opcode_tid ot;
-	__u8 rsvd[3];
-	__u8 status;
-	__be32 snd_nxt;
-	__be32 rcv_nxt;
-};
-
-struct cpl_close_listserv_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__u8 rsvd0;
-	__u8 cpu_idx;
-	__be16 rsvd1;
-};
-
-struct cpl_close_listserv_rpl {
-	RSS_HDR union opcode_tid ot;
-	__u8 rsvd[3];
-	__u8 status;
-};
-
-struct cpl_abort_req_rss {
-	RSS_HDR union opcode_tid ot;
-	__be32 rsvd0;
-	__u8 rsvd1;
-	__u8 status;
-	__u8 rsvd2[6];
-};
-
-struct cpl_abort_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__be32 rsvd0;
-	__u8 rsvd1;
-	__u8 cmd;
-	__u8 rsvd2[6];
-};
-
-struct cpl_abort_rpl_rss {
-	RSS_HDR union opcode_tid ot;
-	__be32 rsvd0;
-	__u8 rsvd1;
-	__u8 status;
-	__u8 rsvd2[6];
-};
-
-struct cpl_abort_rpl {
-	WR_HDR;
-	union opcode_tid ot;
-	__be32 rsvd0;
-	__u8 rsvd1;
-	__u8 cmd;
-	__u8 rsvd2[6];
-};
-
-struct cpl_peer_close {
-	RSS_HDR union opcode_tid ot;
-	__be32 rcv_nxt;
-};
-
-struct tx_data_wr {
-	__be32 wr_hi;
-	__be32 wr_lo;
-	__be32 len;
-	__be32 flags;
-	__be32 sndseq;
-	__be32 param;
-};
-
-/* tx_data_wr.flags fields */
-#define S_TX_ACK_PAGES	21
-#define M_TX_ACK_PAGES	0x7
-#define V_TX_ACK_PAGES(x) ((x) << S_TX_ACK_PAGES)
-#define G_TX_ACK_PAGES(x) (((x) >> S_TX_ACK_PAGES) & M_TX_ACK_PAGES)
-
-/* tx_data_wr.param fields */
-#define S_TX_PORT    0
-#define M_TX_PORT    0x7
-#define V_TX_PORT(x) ((x) << S_TX_PORT)
-#define G_TX_PORT(x) (((x) >> S_TX_PORT) & M_TX_PORT)
-
-#define S_TX_MSS    4
-#define M_TX_MSS    0xF
-#define V_TX_MSS(x) ((x) << S_TX_MSS)
-#define G_TX_MSS(x) (((x) >> S_TX_MSS) & M_TX_MSS)
-
-#define S_TX_QOS    8
-#define M_TX_QOS    0xFF
-#define V_TX_QOS(x) ((x) << S_TX_QOS)
-#define G_TX_QOS(x) (((x) >> S_TX_QOS) & M_TX_QOS)
-
-#define S_TX_SNDBUF 16
-#define M_TX_SNDBUF 0xFFFF
-#define V_TX_SNDBUF(x) ((x) << S_TX_SNDBUF)
-#define G_TX_SNDBUF(x) (((x) >> S_TX_SNDBUF) & M_TX_SNDBUF)
-
-struct cpl_tx_data {
-	union opcode_tid ot;
-	__be32 len;
-	__be32 rsvd;
-	__be16 urg;
-	__be16 flags;
-};
-
-/* cpl_tx_data.flags fields */
-#define S_TX_ULP_SUBMODE    6
-#define M_TX_ULP_SUBMODE    0xF
-#define V_TX_ULP_SUBMODE(x) ((x) << S_TX_ULP_SUBMODE)
-#define G_TX_ULP_SUBMODE(x) (((x) >> S_TX_ULP_SUBMODE) & M_TX_ULP_SUBMODE)
-
-#define S_TX_ULP_MODE    10
-#define M_TX_ULP_MODE    0xF
-#define V_TX_ULP_MODE(x) ((x) << S_TX_ULP_MODE)
-#define G_TX_ULP_MODE(x) (((x) >> S_TX_ULP_MODE) & M_TX_ULP_MODE)
-
-#define S_TX_SHOVE    14
-#define V_TX_SHOVE(x) ((x) << S_TX_SHOVE)
-#define F_TX_SHOVE    V_TX_SHOVE(1U)
-
-#define S_TX_MORE    15
-#define V_TX_MORE(x) ((x) << S_TX_MORE)
-#define F_TX_MORE    V_TX_MORE(1U)
-
-/* additional tx_data_wr.flags fields */
-#define S_TX_CPU_IDX    0
-#define M_TX_CPU_IDX    0x3F
-#define V_TX_CPU_IDX(x) ((x) << S_TX_CPU_IDX)
-#define G_TX_CPU_IDX(x) (((x) >> S_TX_CPU_IDX) & M_TX_CPU_IDX)
-
-#define S_TX_URG    16
-#define V_TX_URG(x) ((x) << S_TX_URG)
-#define F_TX_URG    V_TX_URG(1U)
-
-#define S_TX_CLOSE    17
-#define V_TX_CLOSE(x) ((x) << S_TX_CLOSE)
-#define F_TX_CLOSE    V_TX_CLOSE(1U)
-
-#define S_TX_INIT    18
-#define V_TX_INIT(x) ((x) << S_TX_INIT)
-#define F_TX_INIT    V_TX_INIT(1U)
-
-#define S_TX_IMM_ACK    19
-#define V_TX_IMM_ACK(x) ((x) << S_TX_IMM_ACK)
-#define F_TX_IMM_ACK    V_TX_IMM_ACK(1U)
-
-#define S_TX_IMM_DMA    20
-#define V_TX_IMM_DMA(x) ((x) << S_TX_IMM_DMA)
-#define F_TX_IMM_DMA    V_TX_IMM_DMA(1U)
-
-struct cpl_tx_data_ack {
-	RSS_HDR union opcode_tid ot;
-	__be32 ack_seq;
-};
-
-struct cpl_wr_ack {
-	RSS_HDR union opcode_tid ot;
-	__be16 credits;
-	__be16 rsvd;
-	__be32 snd_nxt;
-	__be32 snd_una;
-};
-
-struct cpl_rdma_ec_status {
-	RSS_HDR union opcode_tid ot;
-	__u8 rsvd[3];
-	__u8 status;
-};
-
-struct mngt_pktsched_wr {
-	__be32 wr_hi;
-	__be32 wr_lo;
-	__u8 mngt_opcode;
-	__u8 rsvd[7];
-	__u8 sched;
-	__u8 idx;
-	__u8 min;
-	__u8 max;
-	__u8 binding;
-	__u8 rsvd1[3];
-};
-
-struct cpl_iscsi_hdr {
-	RSS_HDR union opcode_tid ot;
-	__be16 pdu_len_ddp;
-	__be16 len;
-	__be32 seq;
-	__be16 urg;
-	__u8 rsvd;
-	__u8 status;
-};
-
-/* cpl_iscsi_hdr.pdu_len_ddp fields */
-#define S_ISCSI_PDU_LEN    0
-#define M_ISCSI_PDU_LEN    0x7FFF
-#define V_ISCSI_PDU_LEN(x) ((x) << S_ISCSI_PDU_LEN)
-#define G_ISCSI_PDU_LEN(x) (((x) >> S_ISCSI_PDU_LEN) & M_ISCSI_PDU_LEN)
-
-#define S_ISCSI_DDP    15
-#define V_ISCSI_DDP(x) ((x) << S_ISCSI_DDP)
-#define F_ISCSI_DDP    V_ISCSI_DDP(1U)
-
-struct cpl_rx_data {
-	RSS_HDR union opcode_tid ot;
-	__be16 rsvd;
-	__be16 len;
-	__be32 seq;
-	__be16 urg;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8 dack_mode:2;
-	__u8 psh:1;
-	__u8 heartbeat:1;
-	 __u8:4;
-#else
-	 __u8:4;
-	__u8 heartbeat:1;
-	__u8 psh:1;
-	__u8 dack_mode:2;
-#endif
-	__u8 status;
-};
-
-struct cpl_rx_data_ack {
-	WR_HDR;
-	union opcode_tid ot;
-	__be32 credit_dack;
-};
-
-/* cpl_rx_data_ack.ack_seq fields */
-#define S_RX_CREDITS    0
-#define M_RX_CREDITS    0x7FFFFFF
-#define V_RX_CREDITS(x) ((x) << S_RX_CREDITS)
-#define G_RX_CREDITS(x) (((x) >> S_RX_CREDITS) & M_RX_CREDITS)
-
-#define S_RX_MODULATE    27
-#define V_RX_MODULATE(x) ((x) << S_RX_MODULATE)
-#define F_RX_MODULATE    V_RX_MODULATE(1U)
-
-#define S_RX_FORCE_ACK    28
-#define V_RX_FORCE_ACK(x) ((x) << S_RX_FORCE_ACK)
-#define F_RX_FORCE_ACK    V_RX_FORCE_ACK(1U)
-
-#define S_RX_DACK_MODE    29
-#define M_RX_DACK_MODE    0x3
-#define V_RX_DACK_MODE(x) ((x) << S_RX_DACK_MODE)
-#define G_RX_DACK_MODE(x) (((x) >> S_RX_DACK_MODE) & M_RX_DACK_MODE)
-
-#define S_RX_DACK_CHANGE    31
-#define V_RX_DACK_CHANGE(x) ((x) << S_RX_DACK_CHANGE)
-#define F_RX_DACK_CHANGE    V_RX_DACK_CHANGE(1U)
-
-struct cpl_rx_urg_notify {
-	RSS_HDR union opcode_tid ot;
-	__be32 seq;
-};
-
-struct cpl_rx_ddp_complete {
-	RSS_HDR union opcode_tid ot;
-	__be32 ddp_report;
-};
-
-struct cpl_rx_data_ddp {
-	RSS_HDR union opcode_tid ot;
-	__be16 urg;
-	__be16 len;
-	__be32 seq;
-	union {
-		__be32 nxt_seq;
-		__be32 ddp_report;
-	};
-	__be32 ulp_crc;
-	__be32 ddpvld_status;
-};
-
-/* cpl_rx_data_ddp.ddpvld_status fields */
-#define S_DDP_STATUS    0
-#define M_DDP_STATUS    0xFF
-#define V_DDP_STATUS(x) ((x) << S_DDP_STATUS)
-#define G_DDP_STATUS(x) (((x) >> S_DDP_STATUS) & M_DDP_STATUS)
-
-#define S_DDP_VALID    15
-#define M_DDP_VALID    0x1FFFF
-#define V_DDP_VALID(x) ((x) << S_DDP_VALID)
-#define G_DDP_VALID(x) (((x) >> S_DDP_VALID) & M_DDP_VALID)
-
-#define S_DDP_PPOD_MISMATCH    15
-#define V_DDP_PPOD_MISMATCH(x) ((x) << S_DDP_PPOD_MISMATCH)
-#define F_DDP_PPOD_MISMATCH    V_DDP_PPOD_MISMATCH(1U)
-
-#define S_DDP_PDU    16
-#define V_DDP_PDU(x) ((x) << S_DDP_PDU)
-#define F_DDP_PDU    V_DDP_PDU(1U)
-
-#define S_DDP_LLIMIT_ERR    17
-#define V_DDP_LLIMIT_ERR(x) ((x) << S_DDP_LLIMIT_ERR)
-#define F_DDP_LLIMIT_ERR    V_DDP_LLIMIT_ERR(1U)
-
-#define S_DDP_PPOD_PARITY_ERR    18
-#define V_DDP_PPOD_PARITY_ERR(x) ((x) << S_DDP_PPOD_PARITY_ERR)
-#define F_DDP_PPOD_PARITY_ERR    V_DDP_PPOD_PARITY_ERR(1U)
-
-#define S_DDP_PADDING_ERR    19
-#define V_DDP_PADDING_ERR(x) ((x) << S_DDP_PADDING_ERR)
-#define F_DDP_PADDING_ERR    V_DDP_PADDING_ERR(1U)
-
-#define S_DDP_HDRCRC_ERR    20
-#define V_DDP_HDRCRC_ERR(x) ((x) << S_DDP_HDRCRC_ERR)
-#define F_DDP_HDRCRC_ERR    V_DDP_HDRCRC_ERR(1U)
-
-#define S_DDP_DATACRC_ERR    21
-#define V_DDP_DATACRC_ERR(x) ((x) << S_DDP_DATACRC_ERR)
-#define F_DDP_DATACRC_ERR    V_DDP_DATACRC_ERR(1U)
-
-#define S_DDP_INVALID_TAG    22
-#define V_DDP_INVALID_TAG(x) ((x) << S_DDP_INVALID_TAG)
-#define F_DDP_INVALID_TAG    V_DDP_INVALID_TAG(1U)
-
-#define S_DDP_ULIMIT_ERR    23
-#define V_DDP_ULIMIT_ERR(x) ((x) << S_DDP_ULIMIT_ERR)
-#define F_DDP_ULIMIT_ERR    V_DDP_ULIMIT_ERR(1U)
-
-#define S_DDP_OFFSET_ERR    24
-#define V_DDP_OFFSET_ERR(x) ((x) << S_DDP_OFFSET_ERR)
-#define F_DDP_OFFSET_ERR    V_DDP_OFFSET_ERR(1U)
-
-#define S_DDP_COLOR_ERR    25
-#define V_DDP_COLOR_ERR(x) ((x) << S_DDP_COLOR_ERR)
-#define F_DDP_COLOR_ERR    V_DDP_COLOR_ERR(1U)
-
-#define S_DDP_TID_MISMATCH    26
-#define V_DDP_TID_MISMATCH(x) ((x) << S_DDP_TID_MISMATCH)
-#define F_DDP_TID_MISMATCH    V_DDP_TID_MISMATCH(1U)
-
-#define S_DDP_INVALID_PPOD    27
-#define V_DDP_INVALID_PPOD(x) ((x) << S_DDP_INVALID_PPOD)
-#define F_DDP_INVALID_PPOD    V_DDP_INVALID_PPOD(1U)
-
-#define S_DDP_ULP_MODE    28
-#define M_DDP_ULP_MODE    0xF
-#define V_DDP_ULP_MODE(x) ((x) << S_DDP_ULP_MODE)
-#define G_DDP_ULP_MODE(x) (((x) >> S_DDP_ULP_MODE) & M_DDP_ULP_MODE)
-
-/* cpl_rx_data_ddp.ddp_report fields */
-#define S_DDP_OFFSET    0
-#define M_DDP_OFFSET    0x3FFFFF
-#define V_DDP_OFFSET(x) ((x) << S_DDP_OFFSET)
-#define G_DDP_OFFSET(x) (((x) >> S_DDP_OFFSET) & M_DDP_OFFSET)
-
-#define S_DDP_URG    24
-#define V_DDP_URG(x) ((x) << S_DDP_URG)
-#define F_DDP_URG    V_DDP_URG(1U)
-
-#define S_DDP_PSH    25
-#define V_DDP_PSH(x) ((x) << S_DDP_PSH)
-#define F_DDP_PSH    V_DDP_PSH(1U)
-
-#define S_DDP_BUF_COMPLETE    26
-#define V_DDP_BUF_COMPLETE(x) ((x) << S_DDP_BUF_COMPLETE)
-#define F_DDP_BUF_COMPLETE    V_DDP_BUF_COMPLETE(1U)
-
-#define S_DDP_BUF_TIMED_OUT    27
-#define V_DDP_BUF_TIMED_OUT(x) ((x) << S_DDP_BUF_TIMED_OUT)
-#define F_DDP_BUF_TIMED_OUT    V_DDP_BUF_TIMED_OUT(1U)
-
-#define S_DDP_BUF_IDX    28
-#define V_DDP_BUF_IDX(x) ((x) << S_DDP_BUF_IDX)
-#define F_DDP_BUF_IDX    V_DDP_BUF_IDX(1U)
-
-struct cpl_tx_pkt {
-	WR_HDR;
-	__be32 cntrl;
-	__be32 len;
-};
-
-struct cpl_tx_pkt_lso {
-	WR_HDR;
-	__be32 cntrl;
-	__be32 len;
-
-	__be32 rsvd;
-	__be32 lso_info;
-};
-
-/* cpl_tx_pkt*.cntrl fields */
-#define S_TXPKT_VLAN    0
-#define M_TXPKT_VLAN    0xFFFF
-#define V_TXPKT_VLAN(x) ((x) << S_TXPKT_VLAN)
-#define G_TXPKT_VLAN(x) (((x) >> S_TXPKT_VLAN) & M_TXPKT_VLAN)
-
-#define S_TXPKT_INTF    16
-#define M_TXPKT_INTF    0xF
-#define V_TXPKT_INTF(x) ((x) << S_TXPKT_INTF)
-#define G_TXPKT_INTF(x) (((x) >> S_TXPKT_INTF) & M_TXPKT_INTF)
-
-#define S_TXPKT_IPCSUM_DIS    20
-#define V_TXPKT_IPCSUM_DIS(x) ((x) << S_TXPKT_IPCSUM_DIS)
-#define F_TXPKT_IPCSUM_DIS    V_TXPKT_IPCSUM_DIS(1U)
-
-#define S_TXPKT_L4CSUM_DIS    21
-#define V_TXPKT_L4CSUM_DIS(x) ((x) << S_TXPKT_L4CSUM_DIS)
-#define F_TXPKT_L4CSUM_DIS    V_TXPKT_L4CSUM_DIS(1U)
-
-#define S_TXPKT_VLAN_VLD    22
-#define V_TXPKT_VLAN_VLD(x) ((x) << S_TXPKT_VLAN_VLD)
-#define F_TXPKT_VLAN_VLD    V_TXPKT_VLAN_VLD(1U)
-
-#define S_TXPKT_LOOPBACK    23
-#define V_TXPKT_LOOPBACK(x) ((x) << S_TXPKT_LOOPBACK)
-#define F_TXPKT_LOOPBACK    V_TXPKT_LOOPBACK(1U)
-
-#define S_TXPKT_OPCODE    24
-#define M_TXPKT_OPCODE    0xFF
-#define V_TXPKT_OPCODE(x) ((x) << S_TXPKT_OPCODE)
-#define G_TXPKT_OPCODE(x) (((x) >> S_TXPKT_OPCODE) & M_TXPKT_OPCODE)
-
-/* cpl_tx_pkt_lso.lso_info fields */
-#define S_LSO_MSS    0
-#define M_LSO_MSS    0x3FFF
-#define V_LSO_MSS(x) ((x) << S_LSO_MSS)
-#define G_LSO_MSS(x) (((x) >> S_LSO_MSS) & M_LSO_MSS)
-
-#define S_LSO_ETH_TYPE    14
-#define M_LSO_ETH_TYPE    0x3
-#define V_LSO_ETH_TYPE(x) ((x) << S_LSO_ETH_TYPE)
-#define G_LSO_ETH_TYPE(x) (((x) >> S_LSO_ETH_TYPE) & M_LSO_ETH_TYPE)
-
-#define S_LSO_TCPHDR_WORDS    16
-#define M_LSO_TCPHDR_WORDS    0xF
-#define V_LSO_TCPHDR_WORDS(x) ((x) << S_LSO_TCPHDR_WORDS)
-#define G_LSO_TCPHDR_WORDS(x) (((x) >> S_LSO_TCPHDR_WORDS) & M_LSO_TCPHDR_WORDS)
-
-#define S_LSO_IPHDR_WORDS    20
-#define M_LSO_IPHDR_WORDS    0xF
-#define V_LSO_IPHDR_WORDS(x) ((x) << S_LSO_IPHDR_WORDS)
-#define G_LSO_IPHDR_WORDS(x) (((x) >> S_LSO_IPHDR_WORDS) & M_LSO_IPHDR_WORDS)
-
-#define S_LSO_IPV6    24
-#define V_LSO_IPV6(x) ((x) << S_LSO_IPV6)
-#define F_LSO_IPV6    V_LSO_IPV6(1U)
-
-struct cpl_trace_pkt {
-#ifdef CHELSIO_FW
-	__u8 rss_opcode;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8 err:1;
-	 __u8:7;
-#else
-	 __u8:7;
-	__u8 err:1;
-#endif
-	__u8 rsvd0;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8 qid:4;
-	 __u8:4;
-#else
-	 __u8:4;
-	__u8 qid:4;
-#endif
-	__be32 tstamp;
-#endif				/* CHELSIO_FW */
-
-	__u8 opcode;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8 iff:4;
-	 __u8:4;
-#else
-	 __u8:4;
-	__u8 iff:4;
-#endif
-	__u8 rsvd[4];
-	__be16 len;
-};
-
-struct cpl_rx_pkt {
-	RSS_HDR __u8 opcode;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8 iff:4;
-	__u8 csum_valid:1;
-	__u8 ipmi_pkt:1;
-	__u8 vlan_valid:1;
-	__u8 fragment:1;
-#else
-	__u8 fragment:1;
-	__u8 vlan_valid:1;
-	__u8 ipmi_pkt:1;
-	__u8 csum_valid:1;
-	__u8 iff:4;
-#endif
-	__be16 csum;
-	__be16 vlan;
-	__be16 len;
-};
-
-struct cpl_l2t_write_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__be32 params;
-	__u8 rsvd[2];
-	__u8 dst_mac[6];
-};
-
-/* cpl_l2t_write_req.params fields */
-#define S_L2T_W_IDX    0
-#define M_L2T_W_IDX    0x7FF
-#define V_L2T_W_IDX(x) ((x) << S_L2T_W_IDX)
-#define G_L2T_W_IDX(x) (((x) >> S_L2T_W_IDX) & M_L2T_W_IDX)
-
-#define S_L2T_W_VLAN    11
-#define M_L2T_W_VLAN    0xFFF
-#define V_L2T_W_VLAN(x) ((x) << S_L2T_W_VLAN)
-#define G_L2T_W_VLAN(x) (((x) >> S_L2T_W_VLAN) & M_L2T_W_VLAN)
-
-#define S_L2T_W_IFF    23
-#define M_L2T_W_IFF    0xF
-#define V_L2T_W_IFF(x) ((x) << S_L2T_W_IFF)
-#define G_L2T_W_IFF(x) (((x) >> S_L2T_W_IFF) & M_L2T_W_IFF)
-
-#define S_L2T_W_PRIO    27
-#define M_L2T_W_PRIO    0x7
-#define V_L2T_W_PRIO(x) ((x) << S_L2T_W_PRIO)
-#define G_L2T_W_PRIO(x) (((x) >> S_L2T_W_PRIO) & M_L2T_W_PRIO)
-
-struct cpl_l2t_write_rpl {
-	RSS_HDR union opcode_tid ot;
-	__u8 status;
-	__u8 rsvd[3];
-};
-
-struct cpl_l2t_read_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__be16 rsvd;
-	__be16 l2t_idx;
-};
-
-struct cpl_l2t_read_rpl {
-	RSS_HDR union opcode_tid ot;
-	__be32 params;
-	__u8 rsvd[2];
-	__u8 dst_mac[6];
-};
-
-/* cpl_l2t_read_rpl.params fields */
-#define S_L2T_R_PRIO    0
-#define M_L2T_R_PRIO    0x7
-#define V_L2T_R_PRIO(x) ((x) << S_L2T_R_PRIO)
-#define G_L2T_R_PRIO(x) (((x) >> S_L2T_R_PRIO) & M_L2T_R_PRIO)
-
-#define S_L2T_R_VLAN    8
-#define M_L2T_R_VLAN    0xFFF
-#define V_L2T_R_VLAN(x) ((x) << S_L2T_R_VLAN)
-#define G_L2T_R_VLAN(x) (((x) >> S_L2T_R_VLAN) & M_L2T_R_VLAN)
-
-#define S_L2T_R_IFF    20
-#define M_L2T_R_IFF    0xF
-#define V_L2T_R_IFF(x) ((x) << S_L2T_R_IFF)
-#define G_L2T_R_IFF(x) (((x) >> S_L2T_R_IFF) & M_L2T_R_IFF)
-
-#define S_L2T_STATUS    24
-#define M_L2T_STATUS    0xFF
-#define V_L2T_STATUS(x) ((x) << S_L2T_STATUS)
-#define G_L2T_STATUS(x) (((x) >> S_L2T_STATUS) & M_L2T_STATUS)
-
-struct cpl_smt_write_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__u8 rsvd0;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8 mtu_idx:4;
-	__u8 iff:4;
-#else
-	__u8 iff:4;
-	__u8 mtu_idx:4;
-#endif
-	__be16 rsvd2;
-	__be16 rsvd3;
-	__u8 src_mac1[6];
-	__be16 rsvd4;
-	__u8 src_mac0[6];
-};
-
-struct cpl_smt_write_rpl {
-	RSS_HDR union opcode_tid ot;
-	__u8 status;
-	__u8 rsvd[3];
-};
-
-struct cpl_smt_read_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__u8 rsvd0;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	 __u8:4;
-	__u8 iff:4;
-#else
-	__u8 iff:4;
-	 __u8:4;
-#endif
-	__be16 rsvd2;
-};
-
-struct cpl_smt_read_rpl {
-	RSS_HDR union opcode_tid ot;
-	__u8 status;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8 mtu_idx:4;
-	 __u8:4;
-#else
-	 __u8:4;
-	__u8 mtu_idx:4;
-#endif
-	__be16 rsvd2;
-	__be16 rsvd3;
-	__u8 src_mac1[6];
-	__be16 rsvd4;
-	__u8 src_mac0[6];
-};
-
-struct cpl_rte_delete_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__be32 params;
-};
-
-/* { cpl_rte_delete_req, cpl_rte_read_req }.params fields */
-#define S_RTE_REQ_LUT_IX    8
-#define M_RTE_REQ_LUT_IX    0x7FF
-#define V_RTE_REQ_LUT_IX(x) ((x) << S_RTE_REQ_LUT_IX)
-#define G_RTE_REQ_LUT_IX(x) (((x) >> S_RTE_REQ_LUT_IX) & M_RTE_REQ_LUT_IX)
-
-#define S_RTE_REQ_LUT_BASE    19
-#define M_RTE_REQ_LUT_BASE    0x7FF
-#define V_RTE_REQ_LUT_BASE(x) ((x) << S_RTE_REQ_LUT_BASE)
-#define G_RTE_REQ_LUT_BASE(x) (((x) >> S_RTE_REQ_LUT_BASE) & M_RTE_REQ_LUT_BASE)
-
-#define S_RTE_READ_REQ_SELECT    31
-#define V_RTE_READ_REQ_SELECT(x) ((x) << S_RTE_READ_REQ_SELECT)
-#define F_RTE_READ_REQ_SELECT    V_RTE_READ_REQ_SELECT(1U)
-
-struct cpl_rte_delete_rpl {
-	RSS_HDR union opcode_tid ot;
-	__u8 status;
-	__u8 rsvd[3];
-};
-
-struct cpl_rte_write_req {
-	WR_HDR;
-	union opcode_tid ot;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	 __u8:6;
-	__u8 write_tcam:1;
-	__u8 write_l2t_lut:1;
-#else
-	__u8 write_l2t_lut:1;
-	__u8 write_tcam:1;
-	 __u8:6;
-#endif
-	__u8 rsvd[3];
-	__be32 lut_params;
-	__be16 rsvd2;
-	__be16 l2t_idx;
-	__be32 netmask;
-	__be32 faddr;
-};
-
-/* cpl_rte_write_req.lut_params fields */
-#define S_RTE_WRITE_REQ_LUT_IX    10
-#define M_RTE_WRITE_REQ_LUT_IX    0x7FF
-#define V_RTE_WRITE_REQ_LUT_IX(x) ((x) << S_RTE_WRITE_REQ_LUT_IX)
-#define G_RTE_WRITE_REQ_LUT_IX(x) (((x) >> S_RTE_WRITE_REQ_LUT_IX) & M_RTE_WRITE_REQ_LUT_IX)
-
-#define S_RTE_WRITE_REQ_LUT_BASE    21
-#define M_RTE_WRITE_REQ_LUT_BASE    0x7FF
-#define V_RTE_WRITE_REQ_LUT_BASE(x) ((x) << S_RTE_WRITE_REQ_LUT_BASE)
-#define G_RTE_WRITE_REQ_LUT_BASE(x) (((x) >> S_RTE_WRITE_REQ_LUT_BASE) & M_RTE_WRITE_REQ_LUT_BASE)
-
-struct cpl_rte_write_rpl {
-	RSS_HDR union opcode_tid ot;
-	__u8 status;
-	__u8 rsvd[3];
-};
-
-struct cpl_rte_read_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__be32 params;
-};
-
-struct cpl_rte_read_rpl {
-	RSS_HDR union opcode_tid ot;
-	__u8 status;
-	__u8 rsvd0;
-	__be16 l2t_idx;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	 __u8:7;
-	__u8 select:1;
-#else
-	__u8 select:1;
-	 __u8:7;
-#endif
-	__u8 rsvd2[3];
-	__be32 addr;
-};
-
-struct cpl_tid_release {
-	WR_HDR;
-	union opcode_tid ot;
-	__be32 rsvd;
-};
-
-struct cpl_barrier {
-	WR_HDR;
-	__u8 opcode;
-	__u8 rsvd[7];
-};
-
-struct cpl_rdma_read_req {
-	__u8 opcode;
-	__u8 rsvd[15];
-};
-
-struct cpl_rdma_terminate {
-#ifdef CHELSIO_FW
-	__u8 opcode;
-	__u8 rsvd[2];
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8 rspq:3;
-	 __u8:5;
-#else
-	 __u8:5;
-	__u8 rspq:3;
-#endif
-	__be32 tid_len;
-#endif
-	__be32 msn;
-	__be32 mo;
-	__u8 data[0];
-};
-
-/* cpl_rdma_terminate.tid_len fields */
-#define S_FLIT_CNT    0
-#define M_FLIT_CNT    0xFF
-#define V_FLIT_CNT(x) ((x) << S_FLIT_CNT)
-#define G_FLIT_CNT(x) (((x) >> S_FLIT_CNT) & M_FLIT_CNT)
-
-#define S_TERM_TID    8
-#define M_TERM_TID    0xFFFFF
-#define V_TERM_TID(x) ((x) << S_TERM_TID)
-#define G_TERM_TID(x) (((x) >> S_TERM_TID) & M_TERM_TID)
-
-/* ULP_TX opcodes */
-enum { ULP_MEM_READ = 2, ULP_MEM_WRITE = 3, ULP_TXPKT = 4 };
-
-#define S_ULPTX_CMD	28
-#define M_ULPTX_CMD	0xF
-#define V_ULPTX_CMD(x)	((x) << S_ULPTX_CMD)
-
-#define S_ULPTX_NFLITS	0
-#define M_ULPTX_NFLITS	0xFF
-#define V_ULPTX_NFLITS(x) ((x) << S_ULPTX_NFLITS)
-
-struct ulp_mem_io {
-	WR_HDR;
-	__be32 cmd_lock_addr;
-	__be32 len;
-};
-
-/* ulp_mem_io.cmd_lock_addr fields */
-#define S_ULP_MEMIO_ADDR	0
-#define M_ULP_MEMIO_ADDR	0x7FFFFFF
-#define V_ULP_MEMIO_ADDR(x)	((x) << S_ULP_MEMIO_ADDR)
-#define S_ULP_MEMIO_LOCK	27
-#define V_ULP_MEMIO_LOCK(x)	((x) << S_ULP_MEMIO_LOCK)
-#define F_ULP_MEMIO_LOCK	V_ULP_MEMIO_LOCK(1U)
-
-/* ulp_mem_io.len fields */
-#define S_ULP_MEMIO_DATA_LEN	28
-#define M_ULP_MEMIO_DATA_LEN	0xF
-#define V_ULP_MEMIO_DATA_LEN(x)	((x) << S_ULP_MEMIO_DATA_LEN)
-
-#endif				/* T3_CPL_H */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/t3_hw.c linux-libre-3.2-gnu/drivers/net/cxgb3/t3_hw.c
--- linux-libre-3.1-gnu/drivers/net/cxgb3/t3_hw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/t3_hw.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3785 +0,0 @@
-/*
- * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#include "common.h"
-#include "regs.h"
-#include "sge_defs.h"
-#include "firmware_exports.h"
-
-static void t3_port_intr_clear(struct adapter *adapter, int idx);
-
-/**
- *	t3_wait_op_done_val - wait until an operation is completed
- *	@adapter: the adapter performing the operation
- *	@reg: the register to check for completion
- *	@mask: a single-bit field within @reg that indicates completion
- *	@polarity: the value of the field when the operation is completed
- *	@attempts: number of check iterations
- *	@delay: delay in usecs between iterations
- *	@valp: where to store the value of the register at completion time
- *
- *	Wait until an operation is completed by checking a bit in a register
- *	up to @attempts times.  If @valp is not NULL the value of the register
- *	at the time it indicated completion is stored there.  Returns 0 if the
- *	operation completes and -EAGAIN otherwise.
- */
-
-int t3_wait_op_done_val(struct adapter *adapter, int reg, u32 mask,
-			int polarity, int attempts, int delay, u32 *valp)
-{
-	while (1) {
-		u32 val = t3_read_reg(adapter, reg);
-
-		if (!!(val & mask) == polarity) {
-			if (valp)
-				*valp = val;
-			return 0;
-		}
-		if (--attempts == 0)
-			return -EAGAIN;
-		if (delay)
-			udelay(delay);
-	}
-}
-
-/**
- *	t3_write_regs - write a bunch of registers
- *	@adapter: the adapter to program
- *	@p: an array of register address/register value pairs
- *	@n: the number of address/value pairs
- *	@offset: register address offset
- *
- *	Takes an array of register address/register value pairs and writes each
- *	value to the corresponding register.  Register addresses are adjusted
- *	by the supplied offset.
- */
-void t3_write_regs(struct adapter *adapter, const struct addr_val_pair *p,
-		   int n, unsigned int offset)
-{
-	while (n--) {
-		t3_write_reg(adapter, p->reg_addr + offset, p->val);
-		p++;
-	}
-}
-
-/**
- *	t3_set_reg_field - set a register field to a value
- *	@adapter: the adapter to program
- *	@addr: the register address
- *	@mask: specifies the portion of the register to modify
- *	@val: the new value for the register field
- *
- *	Sets a register field specified by the supplied mask to the
- *	given value.
- */
-void t3_set_reg_field(struct adapter *adapter, unsigned int addr, u32 mask,
-		      u32 val)
-{
-	u32 v = t3_read_reg(adapter, addr) & ~mask;
-
-	t3_write_reg(adapter, addr, v | val);
-	t3_read_reg(adapter, addr);	/* flush */
-}
-
-/**
- *	t3_read_indirect - read indirectly addressed registers
- *	@adap: the adapter
- *	@addr_reg: register holding the indirect address
- *	@data_reg: register holding the value of the indirect register
- *	@vals: where the read register values are stored
- *	@start_idx: index of first indirect register to read
- *	@nregs: how many indirect registers to read
- *
- *	Reads registers that are accessed indirectly through an address/data
- *	register pair.
- */
-static void t3_read_indirect(struct adapter *adap, unsigned int addr_reg,
-			     unsigned int data_reg, u32 *vals,
-			     unsigned int nregs, unsigned int start_idx)
-{
-	while (nregs--) {
-		t3_write_reg(adap, addr_reg, start_idx);
-		*vals++ = t3_read_reg(adap, data_reg);
-		start_idx++;
-	}
-}
-
-/**
- *	t3_mc7_bd_read - read from MC7 through backdoor accesses
- *	@mc7: identifies MC7 to read from
- *	@start: index of first 64-bit word to read
- *	@n: number of 64-bit words to read
- *	@buf: where to store the read result
- *
- *	Read n 64-bit words from MC7 starting at word start, using backdoor
- *	accesses.
- */
-int t3_mc7_bd_read(struct mc7 *mc7, unsigned int start, unsigned int n,
-		   u64 *buf)
-{
-	static const int shift[] = { 0, 0, 16, 24 };
-	static const int step[] = { 0, 32, 16, 8 };
-
-	unsigned int size64 = mc7->size / 8;	/* # of 64-bit words */
-	struct adapter *adap = mc7->adapter;
-
-	if (start >= size64 || start + n > size64)
-		return -EINVAL;
-
-	start *= (8 << mc7->width);
-	while (n--) {
-		int i;
-		u64 val64 = 0;
-
-		for (i = (1 << mc7->width) - 1; i >= 0; --i) {
-			int attempts = 10;
-			u32 val;
-
-			t3_write_reg(adap, mc7->offset + A_MC7_BD_ADDR, start);
-			t3_write_reg(adap, mc7->offset + A_MC7_BD_OP, 0);
-			val = t3_read_reg(adap, mc7->offset + A_MC7_BD_OP);
-			while ((val & F_BUSY) && attempts--)
-				val = t3_read_reg(adap,
-						  mc7->offset + A_MC7_BD_OP);
-			if (val & F_BUSY)
-				return -EIO;
-
-			val = t3_read_reg(adap, mc7->offset + A_MC7_BD_DATA1);
-			if (mc7->width == 0) {
-				val64 = t3_read_reg(adap,
-						    mc7->offset +
-						    A_MC7_BD_DATA0);
-				val64 |= (u64) val << 32;
-			} else {
-				if (mc7->width > 1)
-					val >>= shift[mc7->width];
-				val64 |= (u64) val << (step[mc7->width] * i);
-			}
-			start += 8;
-		}
-		*buf++ = val64;
-	}
-	return 0;
-}
-
-/*
- * Initialize MI1.
- */
-static void mi1_init(struct adapter *adap, const struct adapter_info *ai)
-{
-	u32 clkdiv = adap->params.vpd.cclk / (2 * adap->params.vpd.mdc) - 1;
-	u32 val = F_PREEN | V_CLKDIV(clkdiv);
-
-	t3_write_reg(adap, A_MI1_CFG, val);
-}
-
-#define MDIO_ATTEMPTS 20
-
-/*
- * MI1 read/write operations for clause 22 PHYs.
- */
-static int t3_mi1_read(struct net_device *dev, int phy_addr, int mmd_addr,
-		       u16 reg_addr)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	int ret;
-	u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr);
-
-	mutex_lock(&adapter->mdio_lock);
-	t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1));
-	t3_write_reg(adapter, A_MI1_ADDR, addr);
-	t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(2));
-	ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10);
-	if (!ret)
-		ret = t3_read_reg(adapter, A_MI1_DATA);
-	mutex_unlock(&adapter->mdio_lock);
-	return ret;
-}
-
-static int t3_mi1_write(struct net_device *dev, int phy_addr, int mmd_addr,
-			u16 reg_addr, u16 val)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	int ret;
-	u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr);
-
-	mutex_lock(&adapter->mdio_lock);
-	t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1));
-	t3_write_reg(adapter, A_MI1_ADDR, addr);
-	t3_write_reg(adapter, A_MI1_DATA, val);
-	t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1));
-	ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10);
-	mutex_unlock(&adapter->mdio_lock);
-	return ret;
-}
-
-static const struct mdio_ops mi1_mdio_ops = {
-	.read = t3_mi1_read,
-	.write = t3_mi1_write,
-	.mode_support = MDIO_SUPPORTS_C22
-};
-
-/*
- * Performs the address cycle for clause 45 PHYs.
- * Must be called with the MDIO_LOCK held.
- */
-static int mi1_wr_addr(struct adapter *adapter, int phy_addr, int mmd_addr,
-		       int reg_addr)
-{
-	u32 addr = V_REGADDR(mmd_addr) | V_PHYADDR(phy_addr);
-
-	t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), 0);
-	t3_write_reg(adapter, A_MI1_ADDR, addr);
-	t3_write_reg(adapter, A_MI1_DATA, reg_addr);
-	t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(0));
-	return t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0,
-			       MDIO_ATTEMPTS, 10);
-}
-
-/*
- * MI1 read/write operations for indirect-addressed PHYs.
- */
-static int mi1_ext_read(struct net_device *dev, int phy_addr, int mmd_addr,
-			u16 reg_addr)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	int ret;
-
-	mutex_lock(&adapter->mdio_lock);
-	ret = mi1_wr_addr(adapter, phy_addr, mmd_addr, reg_addr);
-	if (!ret) {
-		t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(3));
-		ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0,
-				      MDIO_ATTEMPTS, 10);
-		if (!ret)
-			ret = t3_read_reg(adapter, A_MI1_DATA);
-	}
-	mutex_unlock(&adapter->mdio_lock);
-	return ret;
-}
-
-static int mi1_ext_write(struct net_device *dev, int phy_addr, int mmd_addr,
-			 u16 reg_addr, u16 val)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	int ret;
-
-	mutex_lock(&adapter->mdio_lock);
-	ret = mi1_wr_addr(adapter, phy_addr, mmd_addr, reg_addr);
-	if (!ret) {
-		t3_write_reg(adapter, A_MI1_DATA, val);
-		t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1));
-		ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0,
-				      MDIO_ATTEMPTS, 10);
-	}
-	mutex_unlock(&adapter->mdio_lock);
-	return ret;
-}
-
-static const struct mdio_ops mi1_mdio_ext_ops = {
-	.read = mi1_ext_read,
-	.write = mi1_ext_write,
-	.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22
-};
-
-/**
- *	t3_mdio_change_bits - modify the value of a PHY register
- *	@phy: the PHY to operate on
- *	@mmd: the device address
- *	@reg: the register address
- *	@clear: what part of the register value to mask off
- *	@set: what part of the register value to set
- *
- *	Changes the value of a PHY register by applying a mask to its current
- *	value and ORing the result with a new value.
- */
-int t3_mdio_change_bits(struct cphy *phy, int mmd, int reg, unsigned int clear,
-			unsigned int set)
-{
-	int ret;
-	unsigned int val;
-
-	ret = t3_mdio_read(phy, mmd, reg, &val);
-	if (!ret) {
-		val &= ~clear;
-		ret = t3_mdio_write(phy, mmd, reg, val | set);
-	}
-	return ret;
-}
-
-/**
- *	t3_phy_reset - reset a PHY block
- *	@phy: the PHY to operate on
- *	@mmd: the device address of the PHY block to reset
- *	@wait: how long to wait for the reset to complete in 1ms increments
- *
- *	Resets a PHY block and optionally waits for the reset to complete.
- *	@mmd should be 0 for 10/100/1000 PHYs and the device address to reset
- *	for 10G PHYs.
- */
-int t3_phy_reset(struct cphy *phy, int mmd, int wait)
-{
-	int err;
-	unsigned int ctl;
-
-	err = t3_mdio_change_bits(phy, mmd, MDIO_CTRL1, MDIO_CTRL1_LPOWER,
-				  MDIO_CTRL1_RESET);
-	if (err || !wait)
-		return err;
-
-	do {
-		err = t3_mdio_read(phy, mmd, MDIO_CTRL1, &ctl);
-		if (err)
-			return err;
-		ctl &= MDIO_CTRL1_RESET;
-		if (ctl)
-			msleep(1);
-	} while (ctl && --wait);
-
-	return ctl ? -1 : 0;
-}
-
-/**
- *	t3_phy_advertise - set the PHY advertisement registers for autoneg
- *	@phy: the PHY to operate on
- *	@advert: bitmap of capabilities the PHY should advertise
- *
- *	Sets a 10/100/1000 PHY's advertisement registers to advertise the
- *	requested capabilities.
- */
-int t3_phy_advertise(struct cphy *phy, unsigned int advert)
-{
-	int err;
-	unsigned int val = 0;
-
-	err = t3_mdio_read(phy, MDIO_DEVAD_NONE, MII_CTRL1000, &val);
-	if (err)
-		return err;
-
-	val &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
-	if (advert & ADVERTISED_1000baseT_Half)
-		val |= ADVERTISE_1000HALF;
-	if (advert & ADVERTISED_1000baseT_Full)
-		val |= ADVERTISE_1000FULL;
-
-	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_CTRL1000, val);
-	if (err)
-		return err;
-
-	val = 1;
-	if (advert & ADVERTISED_10baseT_Half)
-		val |= ADVERTISE_10HALF;
-	if (advert & ADVERTISED_10baseT_Full)
-		val |= ADVERTISE_10FULL;
-	if (advert & ADVERTISED_100baseT_Half)
-		val |= ADVERTISE_100HALF;
-	if (advert & ADVERTISED_100baseT_Full)
-		val |= ADVERTISE_100FULL;
-	if (advert & ADVERTISED_Pause)
-		val |= ADVERTISE_PAUSE_CAP;
-	if (advert & ADVERTISED_Asym_Pause)
-		val |= ADVERTISE_PAUSE_ASYM;
-	return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_ADVERTISE, val);
-}
-
-/**
- *	t3_phy_advertise_fiber - set fiber PHY advertisement register
- *	@phy: the PHY to operate on
- *	@advert: bitmap of capabilities the PHY should advertise
- *
- *	Sets a fiber PHY's advertisement register to advertise the
- *	requested capabilities.
- */
-int t3_phy_advertise_fiber(struct cphy *phy, unsigned int advert)
-{
-	unsigned int val = 0;
-
-	if (advert & ADVERTISED_1000baseT_Half)
-		val |= ADVERTISE_1000XHALF;
-	if (advert & ADVERTISED_1000baseT_Full)
-		val |= ADVERTISE_1000XFULL;
-	if (advert & ADVERTISED_Pause)
-		val |= ADVERTISE_1000XPAUSE;
-	if (advert & ADVERTISED_Asym_Pause)
-		val |= ADVERTISE_1000XPSE_ASYM;
-	return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_ADVERTISE, val);
-}
-
-/**
- *	t3_set_phy_speed_duplex - force PHY speed and duplex
- *	@phy: the PHY to operate on
- *	@speed: requested PHY speed
- *	@duplex: requested PHY duplex
- *
- *	Force a 10/100/1000 PHY's speed and duplex.  This also disables
- *	auto-negotiation except for GigE, where auto-negotiation is mandatory.
- */
-int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex)
-{
-	int err;
-	unsigned int ctl;
-
-	err = t3_mdio_read(phy, MDIO_DEVAD_NONE, MII_BMCR, &ctl);
-	if (err)
-		return err;
-
-	if (speed >= 0) {
-		ctl &= ~(BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
-		if (speed == SPEED_100)
-			ctl |= BMCR_SPEED100;
-		else if (speed == SPEED_1000)
-			ctl |= BMCR_SPEED1000;
-	}
-	if (duplex >= 0) {
-		ctl &= ~(BMCR_FULLDPLX | BMCR_ANENABLE);
-		if (duplex == DUPLEX_FULL)
-			ctl |= BMCR_FULLDPLX;
-	}
-	if (ctl & BMCR_SPEED1000) /* auto-negotiation required for GigE */
-		ctl |= BMCR_ANENABLE;
-	return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_BMCR, ctl);
-}
-
-int t3_phy_lasi_intr_enable(struct cphy *phy)
-{
-	return t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL,
-			     MDIO_PMA_LASI_LSALARM);
-}
-
-int t3_phy_lasi_intr_disable(struct cphy *phy)
-{
-	return t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0);
-}
-
-int t3_phy_lasi_intr_clear(struct cphy *phy)
-{
-	u32 val;
-
-	return t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val);
-}
-
-int t3_phy_lasi_intr_handler(struct cphy *phy)
-{
-	unsigned int status;
-	int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT,
-			       &status);
-
-	if (err)
-		return err;
-	return (status & MDIO_PMA_LASI_LSALARM) ? cphy_cause_link_change : 0;
-}
-
-static const struct adapter_info t3_adap_info[] = {
-	{1, 1, 0,
-	 F_GPIO2_OEN | F_GPIO4_OEN |
-	 F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, { S_GPIO3, S_GPIO5 }, 0,
-	 &mi1_mdio_ops, "Chelsio PE9000"},
-	{1, 1, 0,
-	 F_GPIO2_OEN | F_GPIO4_OEN |
-	 F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, { S_GPIO3, S_GPIO5 }, 0,
-	 &mi1_mdio_ops, "Chelsio T302"},
-	{1, 0, 0,
-	 F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN |
-	 F_GPIO11_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL,
-	 { 0 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
-	 &mi1_mdio_ext_ops, "Chelsio T310"},
-	{1, 1, 0,
-	 F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN |
-	 F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL |
-	 F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL,
-	 { S_GPIO9, S_GPIO3 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
-	 &mi1_mdio_ext_ops, "Chelsio T320"},
-	{},
-	{},
-	{1, 0, 0,
-	 F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO6_OEN | F_GPIO7_OEN |
-	 F_GPIO10_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL,
-	 { S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
-	 &mi1_mdio_ext_ops, "Chelsio T310" },
-	{1, 0, 0,
-	 F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN |
-	 F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL,
-	 { S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
-	 &mi1_mdio_ext_ops, "Chelsio N320E-G2" },
-};
-
-/*
- * Return the adapter_info structure with a given index.  Out-of-range indices
- * return NULL.
- */
-const struct adapter_info *t3_get_adapter_info(unsigned int id)
-{
-	return id < ARRAY_SIZE(t3_adap_info) ? &t3_adap_info[id] : NULL;
-}
-
-struct port_type_info {
-	int (*phy_prep)(struct cphy *phy, struct adapter *adapter,
-			int phy_addr, const struct mdio_ops *ops);
-};
-
-static const struct port_type_info port_types[] = {
-	{ NULL },
-	{ t3_ael1002_phy_prep },
-	{ t3_vsc8211_phy_prep },
-	{ NULL},
-	{ t3_xaui_direct_phy_prep },
-	{ t3_ael2005_phy_prep },
-	{ t3_qt2045_phy_prep },
-	{ t3_ael1006_phy_prep },
-	{ NULL },
-	{ t3_aq100x_phy_prep },
-	{ t3_ael2020_phy_prep },
-};
-
-#define VPD_ENTRY(name, len) \
-	u8 name##_kword[2]; u8 name##_len; u8 name##_data[len]
-
-/*
- * Partial EEPROM Vital Product Data structure.  Includes only the ID and
- * VPD-R sections.
- */
-struct t3_vpd {
-	u8 id_tag;
-	u8 id_len[2];
-	u8 id_data[16];
-	u8 vpdr_tag;
-	u8 vpdr_len[2];
-	VPD_ENTRY(pn, 16);	/* part number */
-	VPD_ENTRY(ec, 16);	/* EC level */
-	VPD_ENTRY(sn, SERNUM_LEN); /* serial number */
-	VPD_ENTRY(na, 12);	/* MAC address base */
-	VPD_ENTRY(cclk, 6);	/* core clock */
-	VPD_ENTRY(mclk, 6);	/* mem clock */
-	VPD_ENTRY(uclk, 6);	/* uP clk */
-	VPD_ENTRY(mdc, 6);	/* MDIO clk */
-	VPD_ENTRY(mt, 2);	/* mem timing */
-	VPD_ENTRY(xaui0cfg, 6);	/* XAUI0 config */
-	VPD_ENTRY(xaui1cfg, 6);	/* XAUI1 config */
-	VPD_ENTRY(port0, 2);	/* PHY0 complex */
-	VPD_ENTRY(port1, 2);	/* PHY1 complex */
-	VPD_ENTRY(port2, 2);	/* PHY2 complex */
-	VPD_ENTRY(port3, 2);	/* PHY3 complex */
-	VPD_ENTRY(rv, 1);	/* csum */
-	u32 pad;		/* for multiple-of-4 sizing and alignment */
-};
-
-#define EEPROM_MAX_POLL   40
-#define EEPROM_STAT_ADDR  0x4000
-#define VPD_BASE          0xc00
-
-/**
- *	t3_seeprom_read - read a VPD EEPROM location
- *	@adapter: adapter to read
- *	@addr: EEPROM address
- *	@data: where to store the read data
- *
- *	Read a 32-bit word from a location in VPD EEPROM using the card's PCI
- *	VPD ROM capability.  A zero is written to the flag bit when the
- *	address is written to the control register.  The hardware device will
- *	set the flag to 1 when 4 bytes have been read into the data register.
- */
-int t3_seeprom_read(struct adapter *adapter, u32 addr, __le32 *data)
-{
-	u16 val;
-	int attempts = EEPROM_MAX_POLL;
-	u32 v;
-	unsigned int base = adapter->params.pci.vpd_cap_addr;
-
-	if ((addr >= EEPROMSIZE && addr != EEPROM_STAT_ADDR) || (addr & 3))
-		return -EINVAL;
-
-	pci_write_config_word(adapter->pdev, base + PCI_VPD_ADDR, addr);
-	do {
-		udelay(10);
-		pci_read_config_word(adapter->pdev, base + PCI_VPD_ADDR, &val);
-	} while (!(val & PCI_VPD_ADDR_F) && --attempts);
-
-	if (!(val & PCI_VPD_ADDR_F)) {
-		CH_ERR(adapter, "reading EEPROM address 0x%x failed\n", addr);
-		return -EIO;
-	}
-	pci_read_config_dword(adapter->pdev, base + PCI_VPD_DATA, &v);
-	*data = cpu_to_le32(v);
-	return 0;
-}
-
-/**
- *	t3_seeprom_write - write a VPD EEPROM location
- *	@adapter: adapter to write
- *	@addr: EEPROM address
- *	@data: value to write
- *
- *	Write a 32-bit word to a location in VPD EEPROM using the card's PCI
- *	VPD ROM capability.
- */
-int t3_seeprom_write(struct adapter *adapter, u32 addr, __le32 data)
-{
-	u16 val;
-	int attempts = EEPROM_MAX_POLL;
-	unsigned int base = adapter->params.pci.vpd_cap_addr;
-
-	if ((addr >= EEPROMSIZE && addr != EEPROM_STAT_ADDR) || (addr & 3))
-		return -EINVAL;
-
-	pci_write_config_dword(adapter->pdev, base + PCI_VPD_DATA,
-			       le32_to_cpu(data));
-	pci_write_config_word(adapter->pdev,base + PCI_VPD_ADDR,
-			      addr | PCI_VPD_ADDR_F);
-	do {
-		msleep(1);
-		pci_read_config_word(adapter->pdev, base + PCI_VPD_ADDR, &val);
-	} while ((val & PCI_VPD_ADDR_F) && --attempts);
-
-	if (val & PCI_VPD_ADDR_F) {
-		CH_ERR(adapter, "write to EEPROM address 0x%x failed\n", addr);
-		return -EIO;
-	}
-	return 0;
-}
-
-/**
- *	t3_seeprom_wp - enable/disable EEPROM write protection
- *	@adapter: the adapter
- *	@enable: 1 to enable write protection, 0 to disable it
- *
- *	Enables or disables write protection on the serial EEPROM.
- */
-int t3_seeprom_wp(struct adapter *adapter, int enable)
-{
-	return t3_seeprom_write(adapter, EEPROM_STAT_ADDR, enable ? 0xc : 0);
-}
-
-/**
- *	get_vpd_params - read VPD parameters from VPD EEPROM
- *	@adapter: adapter to read
- *	@p: where to store the parameters
- *
- *	Reads card parameters stored in VPD EEPROM.
- */
-static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
-{
-	int i, addr, ret;
-	struct t3_vpd vpd;
-
-	/*
-	 * Card information is normally at VPD_BASE but some early cards had
-	 * it at 0.
-	 */
-	ret = t3_seeprom_read(adapter, VPD_BASE, (__le32 *)&vpd);
-	if (ret)
-		return ret;
-	addr = vpd.id_tag == 0x82 ? VPD_BASE : 0;
-
-	for (i = 0; i < sizeof(vpd); i += 4) {
-		ret = t3_seeprom_read(adapter, addr + i,
-				      (__le32 *)((u8 *)&vpd + i));
-		if (ret)
-			return ret;
-	}
-
-	p->cclk = simple_strtoul(vpd.cclk_data, NULL, 10);
-	p->mclk = simple_strtoul(vpd.mclk_data, NULL, 10);
-	p->uclk = simple_strtoul(vpd.uclk_data, NULL, 10);
-	p->mdc = simple_strtoul(vpd.mdc_data, NULL, 10);
-	p->mem_timing = simple_strtoul(vpd.mt_data, NULL, 10);
-	memcpy(p->sn, vpd.sn_data, SERNUM_LEN);
-
-	/* Old eeproms didn't have port information */
-	if (adapter->params.rev == 0 && !vpd.port0_data[0]) {
-		p->port_type[0] = uses_xaui(adapter) ? 1 : 2;
-		p->port_type[1] = uses_xaui(adapter) ? 6 : 2;
-	} else {
-		p->port_type[0] = hex_to_bin(vpd.port0_data[0]);
-		p->port_type[1] = hex_to_bin(vpd.port1_data[0]);
-		p->xauicfg[0] = simple_strtoul(vpd.xaui0cfg_data, NULL, 16);
-		p->xauicfg[1] = simple_strtoul(vpd.xaui1cfg_data, NULL, 16);
-	}
-
-	for (i = 0; i < 6; i++)
-		p->eth_base[i] = hex_to_bin(vpd.na_data[2 * i]) * 16 +
-				 hex_to_bin(vpd.na_data[2 * i + 1]);
-	return 0;
-}
-
-/* serial flash and firmware constants */
-enum {
-	SF_ATTEMPTS = 5,	/* max retries for SF1 operations */
-	SF_SEC_SIZE = 64 * 1024,	/* serial flash sector size */
-	SF_SIZE = SF_SEC_SIZE * 8,	/* serial flash size */
-
-	/* flash command opcodes */
-	SF_PROG_PAGE = 2,	/* program page */
-	SF_WR_DISABLE = 4,	/* disable writes */
-	SF_RD_STATUS = 5,	/* read status register */
-	SF_WR_ENABLE = 6,	/* enable writes */
-	SF_RD_DATA_FAST = 0xb,	/* read flash */
-	SF_ERASE_SECTOR = 0xd8,	/* erase sector */
-
-	FW_FLASH_BOOT_ADDR = 0x70000,	/* start address of FW in flash */
-	FW_VERS_ADDR = 0x7fffc,    /* flash address holding FW version */
-	FW_MIN_SIZE = 8            /* at least version and csum */
-};
-
-/**
- *	sf1_read - read data from the serial flash
- *	@adapter: the adapter
- *	@byte_cnt: number of bytes to read
- *	@cont: whether another operation will be chained
- *	@valp: where to store the read data
- *
- *	Reads up to 4 bytes of data from the serial flash.  The location of
- *	the read needs to be specified prior to calling this by issuing the
- *	appropriate commands to the serial flash.
- */
-static int sf1_read(struct adapter *adapter, unsigned int byte_cnt, int cont,
-		    u32 *valp)
-{
-	int ret;
-
-	if (!byte_cnt || byte_cnt > 4)
-		return -EINVAL;
-	if (t3_read_reg(adapter, A_SF_OP) & F_BUSY)
-		return -EBUSY;
-	t3_write_reg(adapter, A_SF_OP, V_CONT(cont) | V_BYTECNT(byte_cnt - 1));
-	ret = t3_wait_op_done(adapter, A_SF_OP, F_BUSY, 0, SF_ATTEMPTS, 10);
-	if (!ret)
-		*valp = t3_read_reg(adapter, A_SF_DATA);
-	return ret;
-}
-
-/**
- *	sf1_write - write data to the serial flash
- *	@adapter: the adapter
- *	@byte_cnt: number of bytes to write
- *	@cont: whether another operation will be chained
- *	@val: value to write
- *
- *	Writes up to 4 bytes of data to the serial flash.  The location of
- *	the write needs to be specified prior to calling this by issuing the
- *	appropriate commands to the serial flash.
- */
-static int sf1_write(struct adapter *adapter, unsigned int byte_cnt, int cont,
-		     u32 val)
-{
-	if (!byte_cnt || byte_cnt > 4)
-		return -EINVAL;
-	if (t3_read_reg(adapter, A_SF_OP) & F_BUSY)
-		return -EBUSY;
-	t3_write_reg(adapter, A_SF_DATA, val);
-	t3_write_reg(adapter, A_SF_OP,
-		     V_CONT(cont) | V_BYTECNT(byte_cnt - 1) | V_OP(1));
-	return t3_wait_op_done(adapter, A_SF_OP, F_BUSY, 0, SF_ATTEMPTS, 10);
-}
-
-/**
- *	flash_wait_op - wait for a flash operation to complete
- *	@adapter: the adapter
- *	@attempts: max number of polls of the status register
- *	@delay: delay between polls in ms
- *
- *	Wait for a flash operation to complete by polling the status register.
- */
-static int flash_wait_op(struct adapter *adapter, int attempts, int delay)
-{
-	int ret;
-	u32 status;
-
-	while (1) {
-		if ((ret = sf1_write(adapter, 1, 1, SF_RD_STATUS)) != 0 ||
-		    (ret = sf1_read(adapter, 1, 0, &status)) != 0)
-			return ret;
-		if (!(status & 1))
-			return 0;
-		if (--attempts == 0)
-			return -EAGAIN;
-		if (delay)
-			msleep(delay);
-	}
-}
-
-/**
- *	t3_read_flash - read words from serial flash
- *	@adapter: the adapter
- *	@addr: the start address for the read
- *	@nwords: how many 32-bit words to read
- *	@data: where to store the read data
- *	@byte_oriented: whether to store data as bytes or as words
- *
- *	Read the specified number of 32-bit words from the serial flash.
- *	If @byte_oriented is set the read data is stored as a byte array
- *	(i.e., big-endian), otherwise as 32-bit words in the platform's
- *	natural endianess.
- */
-static int t3_read_flash(struct adapter *adapter, unsigned int addr,
-			 unsigned int nwords, u32 *data, int byte_oriented)
-{
-	int ret;
-
-	if (addr + nwords * sizeof(u32) > SF_SIZE || (addr & 3))
-		return -EINVAL;
-
-	addr = swab32(addr) | SF_RD_DATA_FAST;
-
-	if ((ret = sf1_write(adapter, 4, 1, addr)) != 0 ||
-	    (ret = sf1_read(adapter, 1, 1, data)) != 0)
-		return ret;
-
-	for (; nwords; nwords--, data++) {
-		ret = sf1_read(adapter, 4, nwords > 1, data);
-		if (ret)
-			return ret;
-		if (byte_oriented)
-			*data = htonl(*data);
-	}
-	return 0;
-}
-
-/**
- *	t3_write_flash - write up to a page of data to the serial flash
- *	@adapter: the adapter
- *	@addr: the start address to write
- *	@n: length of data to write
- *	@data: the data to write
- *
- *	Writes up to a page of data (256 bytes) to the serial flash starting
- *	at the given address.
- */
-static int t3_write_flash(struct adapter *adapter, unsigned int addr,
-			  unsigned int n, const u8 *data)
-{
-	int ret;
-	u32 buf[64];
-	unsigned int i, c, left, val, offset = addr & 0xff;
-
-	if (addr + n > SF_SIZE || offset + n > 256)
-		return -EINVAL;
-
-	val = swab32(addr) | SF_PROG_PAGE;
-
-	if ((ret = sf1_write(adapter, 1, 0, SF_WR_ENABLE)) != 0 ||
-	    (ret = sf1_write(adapter, 4, 1, val)) != 0)
-		return ret;
-
-	for (left = n; left; left -= c) {
-		c = min(left, 4U);
-		for (val = 0, i = 0; i < c; ++i)
-			val = (val << 8) + *data++;
-
-		ret = sf1_write(adapter, c, c != left, val);
-		if (ret)
-			return ret;
-	}
-	if ((ret = flash_wait_op(adapter, 5, 1)) != 0)
-		return ret;
-
-	/* Read the page to verify the write succeeded */
-	ret = t3_read_flash(adapter, addr & ~0xff, ARRAY_SIZE(buf), buf, 1);
-	if (ret)
-		return ret;
-
-	if (memcmp(data - n, (u8 *) buf + offset, n))
-		return -EIO;
-	return 0;
-}
-
-/**
- *	t3_get_tp_version - read the tp sram version
- *	@adapter: the adapter
- *	@vers: where to place the version
- *
- *	Reads the protocol sram version from sram.
- */
-int t3_get_tp_version(struct adapter *adapter, u32 *vers)
-{
-	int ret;
-
-	/* Get version loaded in SRAM */
-	t3_write_reg(adapter, A_TP_EMBED_OP_FIELD0, 0);
-	ret = t3_wait_op_done(adapter, A_TP_EMBED_OP_FIELD0,
-			      1, 1, 5, 1);
-	if (ret)
-		return ret;
-
-	*vers = t3_read_reg(adapter, A_TP_EMBED_OP_FIELD1);
-
-	return 0;
-}
-
-/**
- *	t3_check_tpsram_version - read the tp sram version
- *	@adapter: the adapter
- *
- *	Reads the protocol sram version from flash.
- */
-int t3_check_tpsram_version(struct adapter *adapter)
-{
-	int ret;
-	u32 vers;
-	unsigned int major, minor;
-
-	if (adapter->params.rev == T3_REV_A)
-		return 0;
-
-
-	ret = t3_get_tp_version(adapter, &vers);
-	if (ret)
-		return ret;
-
-	major = G_TP_VERSION_MAJOR(vers);
-	minor = G_TP_VERSION_MINOR(vers);
-
-	if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR)
-		return 0;
-	else {
-		CH_ERR(adapter, "found wrong TP version (%u.%u), "
-		       "driver compiled for version %d.%d\n", major, minor,
-		       TP_VERSION_MAJOR, TP_VERSION_MINOR);
-	}
-	return -EINVAL;
-}
-
-/**
- *	t3_check_tpsram - check if provided protocol SRAM
- *			  is compatible with this driver
- *	@adapter: the adapter
- *	@tp_sram: the firmware image to write
- *	@size: image size
- *
- *	Checks if an adapter's tp sram is compatible with the driver.
- *	Returns 0 if the versions are compatible, a negative error otherwise.
- */
-int t3_check_tpsram(struct adapter *adapter, const u8 *tp_sram,
-		    unsigned int size)
-{
-	u32 csum;
-	unsigned int i;
-	const __be32 *p = (const __be32 *)tp_sram;
-
-	/* Verify checksum */
-	for (csum = 0, i = 0; i < size / sizeof(csum); i++)
-		csum += ntohl(p[i]);
-	if (csum != 0xffffffff) {
-		CH_ERR(adapter, "corrupted protocol SRAM image, checksum %u\n",
-		       csum);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-enum fw_version_type {
-	FW_VERSION_N3,
-	FW_VERSION_T3
-};
-
-/**
- *	t3_get_fw_version - read the firmware version
- *	@adapter: the adapter
- *	@vers: where to place the version
- *
- *	Reads the FW version from flash.
- */
-int t3_get_fw_version(struct adapter *adapter, u32 *vers)
-{
-	return t3_read_flash(adapter, FW_VERS_ADDR, 1, vers, 0);
-}
-
-/**
- *	t3_check_fw_version - check if the FW is compatible with this driver
- *	@adapter: the adapter
- *
- *	Checks if an adapter's FW is compatible with the driver.  Returns 0
- *	if the versions are compatible, a negative error otherwise.
- */
-int t3_check_fw_version(struct adapter *adapter)
-{
-	int ret;
-	u32 vers;
-	unsigned int type, major, minor;
-
-	ret = t3_get_fw_version(adapter, &vers);
-	if (ret)
-		return ret;
-
-	type = G_FW_VERSION_TYPE(vers);
-	major = G_FW_VERSION_MAJOR(vers);
-	minor = G_FW_VERSION_MINOR(vers);
-
-	if (type == FW_VERSION_T3 && major == FW_VERSION_MAJOR &&
-	    minor == FW_VERSION_MINOR)
-		return 0;
-	else if (major != FW_VERSION_MAJOR || minor < FW_VERSION_MINOR)
-		CH_WARN(adapter, "found old FW minor version(%u.%u), "
-		        "driver compiled for version %u.%u\n", major, minor,
-			FW_VERSION_MAJOR, FW_VERSION_MINOR);
-	else {
-		CH_WARN(adapter, "found newer FW version(%u.%u), "
-		        "driver compiled for version %u.%u\n", major, minor,
-			FW_VERSION_MAJOR, FW_VERSION_MINOR);
-			return 0;
-	}
-	return -EINVAL;
-}
-
-/**
- *	t3_flash_erase_sectors - erase a range of flash sectors
- *	@adapter: the adapter
- *	@start: the first sector to erase
- *	@end: the last sector to erase
- *
- *	Erases the sectors in the given range.
- */
-static int t3_flash_erase_sectors(struct adapter *adapter, int start, int end)
-{
-	while (start <= end) {
-		int ret;
-
-		if ((ret = sf1_write(adapter, 1, 0, SF_WR_ENABLE)) != 0 ||
-		    (ret = sf1_write(adapter, 4, 0,
-				     SF_ERASE_SECTOR | (start << 8))) != 0 ||
-		    (ret = flash_wait_op(adapter, 5, 500)) != 0)
-			return ret;
-		start++;
-	}
-	return 0;
-}
-
-/*
- *	t3_load_fw - download firmware
- *	@adapter: the adapter
- *	@fw_data: the firmware image to write
- *	@size: image size
- *
- *	Write the supplied firmware image to the card's serial flash.
- *	The FW image has the following sections: @size - 8 bytes of code and
- *	data, followed by 4 bytes of FW version, followed by the 32-bit
- *	1's complement checksum of the whole image.
- */
-int t3_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size)
-{
-	u32 csum;
-	unsigned int i;
-	const __be32 *p = (const __be32 *)fw_data;
-	int ret, addr, fw_sector = FW_FLASH_BOOT_ADDR >> 16;
-
-	if ((size & 3) || size < FW_MIN_SIZE)
-		return -EINVAL;
-	if (size > FW_VERS_ADDR + 8 - FW_FLASH_BOOT_ADDR)
-		return -EFBIG;
-
-	for (csum = 0, i = 0; i < size / sizeof(csum); i++)
-		csum += ntohl(p[i]);
-	if (csum != 0xffffffff) {
-		CH_ERR(adapter, "corrupted firmware image, checksum %u\n",
-		       csum);
-		return -EINVAL;
-	}
-
-	ret = t3_flash_erase_sectors(adapter, fw_sector, fw_sector);
-	if (ret)
-		goto out;
-
-	size -= 8;		/* trim off version and checksum */
-	for (addr = FW_FLASH_BOOT_ADDR; size;) {
-		unsigned int chunk_size = min(size, 256U);
-
-		ret = t3_write_flash(adapter, addr, chunk_size, fw_data);
-		if (ret)
-			goto out;
-
-		addr += chunk_size;
-		fw_data += chunk_size;
-		size -= chunk_size;
-	}
-
-	ret = t3_write_flash(adapter, FW_VERS_ADDR, 4, fw_data);
-out:
-	if (ret)
-		CH_ERR(adapter, "firmware download failed, error %d\n", ret);
-	return ret;
-}
-
-#define CIM_CTL_BASE 0x2000
-
-/**
- *      t3_cim_ctl_blk_read - read a block from CIM control region
- *
- *      @adap: the adapter
- *      @addr: the start address within the CIM control region
- *      @n: number of words to read
- *      @valp: where to store the result
- *
- *      Reads a block of 4-byte words from the CIM control region.
- */
-int t3_cim_ctl_blk_read(struct adapter *adap, unsigned int addr,
-			unsigned int n, unsigned int *valp)
-{
-	int ret = 0;
-
-	if (t3_read_reg(adap, A_CIM_HOST_ACC_CTRL) & F_HOSTBUSY)
-		return -EBUSY;
-
-	for ( ; !ret && n--; addr += 4) {
-		t3_write_reg(adap, A_CIM_HOST_ACC_CTRL, CIM_CTL_BASE + addr);
-		ret = t3_wait_op_done(adap, A_CIM_HOST_ACC_CTRL, F_HOSTBUSY,
-				      0, 5, 2);
-		if (!ret)
-			*valp++ = t3_read_reg(adap, A_CIM_HOST_ACC_DATA);
-	}
-	return ret;
-}
-
-static void t3_gate_rx_traffic(struct cmac *mac, u32 *rx_cfg,
-			       u32 *rx_hash_high, u32 *rx_hash_low)
-{
-	/* stop Rx unicast traffic */
-	t3_mac_disable_exact_filters(mac);
-
-	/* stop broadcast, multicast, promiscuous mode traffic */
-	*rx_cfg = t3_read_reg(mac->adapter, A_XGM_RX_CFG);
-	t3_set_reg_field(mac->adapter, A_XGM_RX_CFG,
-			 F_ENHASHMCAST | F_DISBCAST | F_COPYALLFRAMES,
-			 F_DISBCAST);
-
-	*rx_hash_high = t3_read_reg(mac->adapter, A_XGM_RX_HASH_HIGH);
-	t3_write_reg(mac->adapter, A_XGM_RX_HASH_HIGH, 0);
-
-	*rx_hash_low = t3_read_reg(mac->adapter, A_XGM_RX_HASH_LOW);
-	t3_write_reg(mac->adapter, A_XGM_RX_HASH_LOW, 0);
-
-	/* Leave time to drain max RX fifo */
-	msleep(1);
-}
-
-static void t3_open_rx_traffic(struct cmac *mac, u32 rx_cfg,
-			       u32 rx_hash_high, u32 rx_hash_low)
-{
-	t3_mac_enable_exact_filters(mac);
-	t3_set_reg_field(mac->adapter, A_XGM_RX_CFG,
-			 F_ENHASHMCAST | F_DISBCAST | F_COPYALLFRAMES,
-			 rx_cfg);
-	t3_write_reg(mac->adapter, A_XGM_RX_HASH_HIGH, rx_hash_high);
-	t3_write_reg(mac->adapter, A_XGM_RX_HASH_LOW, rx_hash_low);
-}
-
-/**
- *	t3_link_changed - handle interface link changes
- *	@adapter: the adapter
- *	@port_id: the port index that changed link state
- *
- *	Called when a port's link settings change to propagate the new values
- *	to the associated PHY and MAC.  After performing the common tasks it
- *	invokes an OS-specific handler.
- */
-void t3_link_changed(struct adapter *adapter, int port_id)
-{
-	int link_ok, speed, duplex, fc;
-	struct port_info *pi = adap2pinfo(adapter, port_id);
-	struct cphy *phy = &pi->phy;
-	struct cmac *mac = &pi->mac;
-	struct link_config *lc = &pi->link_config;
-
-	phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
-
-	if (!lc->link_ok && link_ok) {
-		u32 rx_cfg, rx_hash_high, rx_hash_low;
-		u32 status;
-
-		t3_xgm_intr_enable(adapter, port_id);
-		t3_gate_rx_traffic(mac, &rx_cfg, &rx_hash_high, &rx_hash_low);
-		t3_write_reg(adapter, A_XGM_RX_CTRL + mac->offset, 0);
-		t3_mac_enable(mac, MAC_DIRECTION_RX);
-
-		status = t3_read_reg(adapter, A_XGM_INT_STATUS + mac->offset);
-		if (status & F_LINKFAULTCHANGE) {
-			mac->stats.link_faults++;
-			pi->link_fault = 1;
-		}
-		t3_open_rx_traffic(mac, rx_cfg, rx_hash_high, rx_hash_low);
-	}
-
-	if (lc->requested_fc & PAUSE_AUTONEG)
-		fc &= lc->requested_fc;
-	else
-		fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
-
-	if (link_ok == lc->link_ok && speed == lc->speed &&
-	    duplex == lc->duplex && fc == lc->fc)
-		return;                            /* nothing changed */
-
-	if (link_ok != lc->link_ok && adapter->params.rev > 0 &&
-	    uses_xaui(adapter)) {
-		if (link_ok)
-			t3b_pcs_reset(mac);
-		t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset,
-			     link_ok ? F_TXACTENABLE | F_RXEN : 0);
-	}
-	lc->link_ok = link_ok;
-	lc->speed = speed < 0 ? SPEED_INVALID : speed;
-	lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
-
-	if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) {
-		/* Set MAC speed, duplex, and flow control to match PHY. */
-		t3_mac_set_speed_duplex_fc(mac, speed, duplex, fc);
-		lc->fc = fc;
-	}
-
-	t3_os_link_changed(adapter, port_id, link_ok && !pi->link_fault,
-			   speed, duplex, fc);
-}
-
-void t3_link_fault(struct adapter *adapter, int port_id)
-{
-	struct port_info *pi = adap2pinfo(adapter, port_id);
-	struct cmac *mac = &pi->mac;
-	struct cphy *phy = &pi->phy;
-	struct link_config *lc = &pi->link_config;
-	int link_ok, speed, duplex, fc, link_fault;
-	u32 rx_cfg, rx_hash_high, rx_hash_low;
-
-	t3_gate_rx_traffic(mac, &rx_cfg, &rx_hash_high, &rx_hash_low);
-
-	if (adapter->params.rev > 0 && uses_xaui(adapter))
-		t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset, 0);
-
-	t3_write_reg(adapter, A_XGM_RX_CTRL + mac->offset, 0);
-	t3_mac_enable(mac, MAC_DIRECTION_RX);
-
-	t3_open_rx_traffic(mac, rx_cfg, rx_hash_high, rx_hash_low);
-
-	link_fault = t3_read_reg(adapter,
-				 A_XGM_INT_STATUS + mac->offset);
-	link_fault &= F_LINKFAULTCHANGE;
-
-	link_ok = lc->link_ok;
-	speed = lc->speed;
-	duplex = lc->duplex;
-	fc = lc->fc;
-
-	phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
-
-	if (link_fault) {
-		lc->link_ok = 0;
-		lc->speed = SPEED_INVALID;
-		lc->duplex = DUPLEX_INVALID;
-
-		t3_os_link_fault(adapter, port_id, 0);
-
-		/* Account link faults only when the phy reports a link up */
-		if (link_ok)
-			mac->stats.link_faults++;
-	} else {
-		if (link_ok)
-			t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset,
-				     F_TXACTENABLE | F_RXEN);
-
-		pi->link_fault = 0;
-		lc->link_ok = (unsigned char)link_ok;
-		lc->speed = speed < 0 ? SPEED_INVALID : speed;
-		lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
-		t3_os_link_fault(adapter, port_id, link_ok);
-	}
-}
-
-/**
- *	t3_link_start - apply link configuration to MAC/PHY
- *	@phy: the PHY to setup
- *	@mac: the MAC to setup
- *	@lc: the requested link configuration
- *
- *	Set up a port's MAC and PHY according to a desired link configuration.
- *	- If the PHY can auto-negotiate first decide what to advertise, then
- *	  enable/disable auto-negotiation as desired, and reset.
- *	- If the PHY does not auto-negotiate just reset it.
- *	- If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
- *	  otherwise do it later based on the outcome of auto-negotiation.
- */
-int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc)
-{
-	unsigned int fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
-
-	lc->link_ok = 0;
-	if (lc->supported & SUPPORTED_Autoneg) {
-		lc->advertising &= ~(ADVERTISED_Asym_Pause | ADVERTISED_Pause);
-		if (fc) {
-			lc->advertising |= ADVERTISED_Asym_Pause;
-			if (fc & PAUSE_RX)
-				lc->advertising |= ADVERTISED_Pause;
-		}
-		phy->ops->advertise(phy, lc->advertising);
-
-		if (lc->autoneg == AUTONEG_DISABLE) {
-			lc->speed = lc->requested_speed;
-			lc->duplex = lc->requested_duplex;
-			lc->fc = (unsigned char)fc;
-			t3_mac_set_speed_duplex_fc(mac, lc->speed, lc->duplex,
-						   fc);
-			/* Also disables autoneg */
-			phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex);
-		} else
-			phy->ops->autoneg_enable(phy);
-	} else {
-		t3_mac_set_speed_duplex_fc(mac, -1, -1, fc);
-		lc->fc = (unsigned char)fc;
-		phy->ops->reset(phy, 0);
-	}
-	return 0;
-}
-
-/**
- *	t3_set_vlan_accel - control HW VLAN extraction
- *	@adapter: the adapter
- *	@ports: bitmap of adapter ports to operate on
- *	@on: enable (1) or disable (0) HW VLAN extraction
- *
- *	Enables or disables HW extraction of VLAN tags for the given port.
- */
-void t3_set_vlan_accel(struct adapter *adapter, unsigned int ports, int on)
-{
-	t3_set_reg_field(adapter, A_TP_OUT_CONFIG,
-			 ports << S_VLANEXTRACTIONENABLE,
-			 on ? (ports << S_VLANEXTRACTIONENABLE) : 0);
-}
-
-struct intr_info {
-	unsigned int mask;	/* bits to check in interrupt status */
-	const char *msg;	/* message to print or NULL */
-	short stat_idx;		/* stat counter to increment or -1 */
-	unsigned short fatal;	/* whether the condition reported is fatal */
-};
-
-/**
- *	t3_handle_intr_status - table driven interrupt handler
- *	@adapter: the adapter that generated the interrupt
- *	@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 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 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.
- */
-static int t3_handle_intr_status(struct adapter *adapter, unsigned int reg,
-				 unsigned int mask,
-				 const struct intr_info *acts,
-				 unsigned long *stats)
-{
-	int fatal = 0;
-	unsigned int status = t3_read_reg(adapter, reg) & mask;
-
-	for (; acts->mask; ++acts) {
-		if (!(status & acts->mask))
-			continue;
-		if (acts->fatal) {
-			fatal++;
-			CH_ALERT(adapter, "%s (0x%x)\n",
-				 acts->msg, status & acts->mask);
-			status &= ~acts->mask;
-		} else if (acts->msg)
-			CH_WARN(adapter, "%s (0x%x)\n",
-				acts->msg, status & acts->mask);
-		if (acts->stat_idx >= 0)
-			stats[acts->stat_idx]++;
-	}
-	if (status)		/* clear processed interrupts */
-		t3_write_reg(adapter, reg, status);
-	return fatal;
-}
-
-#define SGE_INTR_MASK (F_RSPQDISABLED | \
-		       F_UC_REQ_FRAMINGERROR | F_R_REQ_FRAMINGERROR | \
-		       F_CPPARITYERROR | F_OCPARITYERROR | F_RCPARITYERROR | \
-		       F_IRPARITYERROR | V_ITPARITYERROR(M_ITPARITYERROR) | \
-		       V_FLPARITYERROR(M_FLPARITYERROR) | F_LODRBPARITYERROR | \
-		       F_HIDRBPARITYERROR | F_LORCQPARITYERROR | \
-		       F_HIRCQPARITYERROR | F_LOPRIORITYDBFULL | \
-		       F_HIPRIORITYDBFULL | F_LOPRIORITYDBEMPTY | \
-		       F_HIPRIORITYDBEMPTY | F_HIPIODRBDROPERR | \
-		       F_LOPIODRBDROPERR)
-#define MC5_INTR_MASK (F_PARITYERR | F_ACTRGNFULL | F_UNKNOWNCMD | \
-		       F_REQQPARERR | F_DISPQPARERR | F_DELACTEMPTY | \
-		       F_NFASRCHFAIL)
-#define MC7_INTR_MASK (F_AE | F_UE | F_CE | V_PE(M_PE))
-#define XGM_INTR_MASK (V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR) | \
-		       V_RXFIFO_PRTY_ERR(M_RXFIFO_PRTY_ERR) | \
-		       F_TXFIFO_UNDERRUN)
-#define PCIX_INTR_MASK (F_MSTDETPARERR | F_SIGTARABT | F_RCVTARABT | \
-			F_RCVMSTABT | F_SIGSYSERR | F_DETPARERR | \
-			F_SPLCMPDIS | F_UNXSPLCMP | F_RCVSPLCMPERR | \
-			F_DETCORECCERR | F_DETUNCECCERR | F_PIOPARERR | \
-			V_WFPARERR(M_WFPARERR) | V_RFPARERR(M_RFPARERR) | \
-			V_CFPARERR(M_CFPARERR) /* | V_MSIXPARERR(M_MSIXPARERR) */)
-#define PCIE_INTR_MASK (F_UNXSPLCPLERRR | F_UNXSPLCPLERRC | F_PCIE_PIOPARERR |\
-			F_PCIE_WFPARERR | F_PCIE_RFPARERR | F_PCIE_CFPARERR | \
-			/* V_PCIE_MSIXPARERR(M_PCIE_MSIXPARERR) | */ \
-			F_RETRYBUFPARERR | F_RETRYLUTPARERR | F_RXPARERR | \
-			F_TXPARERR | V_BISTERR(M_BISTERR))
-#define ULPRX_INTR_MASK (F_PARERRDATA | F_PARERRPCMD | F_ARBPF1PERR | \
-			 F_ARBPF0PERR | F_ARBFPERR | F_PCMDMUXPERR | \
-			 F_DATASELFRAMEERR1 | F_DATASELFRAMEERR0)
-#define ULPTX_INTR_MASK 0xfc
-#define CPLSW_INTR_MASK (F_CIM_OP_MAP_PERR | F_TP_FRAMING_ERROR | \
-			 F_SGE_FRAMING_ERROR | F_CIM_FRAMING_ERROR | \
-			 F_ZERO_SWITCH_ERROR)
-#define CIM_INTR_MASK (F_BLKWRPLINT | F_BLKRDPLINT | F_BLKWRCTLINT | \
-		       F_BLKRDCTLINT | F_BLKWRFLASHINT | F_BLKRDFLASHINT | \
-		       F_SGLWRFLASHINT | F_WRBLKFLASHINT | F_BLKWRBOOTINT | \
-	 	       F_FLASHRANGEINT | F_SDRAMRANGEINT | F_RSVDSPACEINT | \
-		       F_DRAMPARERR | F_ICACHEPARERR | F_DCACHEPARERR | \
-		       F_OBQSGEPARERR | F_OBQULPHIPARERR | F_OBQULPLOPARERR | \
-		       F_IBQSGELOPARERR | F_IBQSGEHIPARERR | F_IBQULPPARERR | \
-		       F_IBQTPPARERR | F_ITAGPARERR | F_DTAGPARERR)
-#define PMTX_INTR_MASK (F_ZERO_C_CMD_ERROR | ICSPI_FRM_ERR | OESPI_FRM_ERR | \
-			V_ICSPI_PAR_ERROR(M_ICSPI_PAR_ERROR) | \
-			V_OESPI_PAR_ERROR(M_OESPI_PAR_ERROR))
-#define PMRX_INTR_MASK (F_ZERO_E_CMD_ERROR | IESPI_FRM_ERR | OCSPI_FRM_ERR | \
-			V_IESPI_PAR_ERROR(M_IESPI_PAR_ERROR) | \
-			V_OCSPI_PAR_ERROR(M_OCSPI_PAR_ERROR))
-#define MPS_INTR_MASK (V_TX0TPPARERRENB(M_TX0TPPARERRENB) | \
-		       V_TX1TPPARERRENB(M_TX1TPPARERRENB) | \
-		       V_RXTPPARERRENB(M_RXTPPARERRENB) | \
-		       V_MCAPARERRENB(M_MCAPARERRENB))
-#define XGM_EXTRA_INTR_MASK (F_LINKFAULTCHANGE)
-#define PL_INTR_MASK (F_T3DBG | F_XGMAC0_0 | F_XGMAC0_1 | F_MC5A | F_PM1_TX | \
-		      F_PM1_RX | F_ULP2_TX | F_ULP2_RX | F_TP1 | F_CIM | \
-		      F_MC7_CM | F_MC7_PMTX | F_MC7_PMRX | F_SGE3 | F_PCIM0 | \
-		      F_MPS0 | F_CPL_SWITCH)
-/*
- * Interrupt handler for the PCIX1 module.
- */
-static void pci_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info pcix1_intr_info[] = {
-		{F_MSTDETPARERR, "PCI master detected parity error", -1, 1},
-		{F_SIGTARABT, "PCI signaled target abort", -1, 1},
-		{F_RCVTARABT, "PCI received target abort", -1, 1},
-		{F_RCVMSTABT, "PCI received master abort", -1, 1},
-		{F_SIGSYSERR, "PCI signaled system error", -1, 1},
-		{F_DETPARERR, "PCI detected parity error", -1, 1},
-		{F_SPLCMPDIS, "PCI split completion discarded", -1, 1},
-		{F_UNXSPLCMP, "PCI unexpected split completion error", -1, 1},
-		{F_RCVSPLCMPERR, "PCI received split completion error", -1,
-		 1},
-		{F_DETCORECCERR, "PCI correctable ECC error",
-		 STAT_PCI_CORR_ECC, 0},
-		{F_DETUNCECCERR, "PCI uncorrectable ECC error", -1, 1},
-		{F_PIOPARERR, "PCI PIO FIFO parity error", -1, 1},
-		{V_WFPARERR(M_WFPARERR), "PCI write FIFO parity error", -1,
-		 1},
-		{V_RFPARERR(M_RFPARERR), "PCI read FIFO parity error", -1,
-		 1},
-		{V_CFPARERR(M_CFPARERR), "PCI command FIFO parity error", -1,
-		 1},
-		{V_MSIXPARERR(M_MSIXPARERR), "PCI MSI-X table/PBA parity "
-		 "error", -1, 1},
-		{0}
-	};
-
-	if (t3_handle_intr_status(adapter, A_PCIX_INT_CAUSE, PCIX_INTR_MASK,
-				  pcix1_intr_info, adapter->irq_stats))
-		t3_fatal_err(adapter);
-}
-
-/*
- * Interrupt handler for the PCIE module.
- */
-static void pcie_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info pcie_intr_info[] = {
-		{F_PEXERR, "PCI PEX error", -1, 1},
-		{F_UNXSPLCPLERRR,
-		 "PCI unexpected split completion DMA read error", -1, 1},
-		{F_UNXSPLCPLERRC,
-		 "PCI unexpected split completion DMA command error", -1, 1},
-		{F_PCIE_PIOPARERR, "PCI PIO FIFO parity error", -1, 1},
-		{F_PCIE_WFPARERR, "PCI write FIFO parity error", -1, 1},
-		{F_PCIE_RFPARERR, "PCI read FIFO parity error", -1, 1},
-		{F_PCIE_CFPARERR, "PCI command FIFO parity error", -1, 1},
-		{V_PCIE_MSIXPARERR(M_PCIE_MSIXPARERR),
-		 "PCI MSI-X table/PBA parity error", -1, 1},
-		{F_RETRYBUFPARERR, "PCI retry buffer parity error", -1, 1},
-		{F_RETRYLUTPARERR, "PCI retry LUT parity error", -1, 1},
-		{F_RXPARERR, "PCI Rx parity error", -1, 1},
-		{F_TXPARERR, "PCI Tx parity error", -1, 1},
-		{V_BISTERR(M_BISTERR), "PCI BIST error", -1, 1},
-		{0}
-	};
-
-	if (t3_read_reg(adapter, A_PCIE_INT_CAUSE) & F_PEXERR)
-		CH_ALERT(adapter, "PEX error code 0x%x\n",
-			 t3_read_reg(adapter, A_PCIE_PEX_ERR));
-
-	if (t3_handle_intr_status(adapter, A_PCIE_INT_CAUSE, PCIE_INTR_MASK,
-				  pcie_intr_info, adapter->irq_stats))
-		t3_fatal_err(adapter);
-}
-
-/*
- * TP interrupt handler.
- */
-static void tp_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info tp_intr_info[] = {
-		{0xffffff, "TP parity error", -1, 1},
-		{0x1000000, "TP out of Rx pages", -1, 1},
-		{0x2000000, "TP out of Tx pages", -1, 1},
-		{0}
-	};
-
-	static const struct intr_info tp_intr_info_t3c[] = {
-		{0x1fffffff, "TP parity error", -1, 1},
-		{F_FLMRXFLSTEMPTY, "TP out of Rx pages", -1, 1},
-		{F_FLMTXFLSTEMPTY, "TP out of Tx pages", -1, 1},
-		{0}
-	};
-
-	if (t3_handle_intr_status(adapter, A_TP_INT_CAUSE, 0xffffffff,
-				  adapter->params.rev < T3_REV_C ?
-				  tp_intr_info : tp_intr_info_t3c, NULL))
-		t3_fatal_err(adapter);
-}
-
-/*
- * CIM interrupt handler.
- */
-static void cim_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info cim_intr_info[] = {
-		{F_RSVDSPACEINT, "CIM reserved space write", -1, 1},
-		{F_SDRAMRANGEINT, "CIM SDRAM address out of range", -1, 1},
-		{F_FLASHRANGEINT, "CIM flash address out of range", -1, 1},
-		{F_BLKWRBOOTINT, "CIM block write to boot space", -1, 1},
-		{F_WRBLKFLASHINT, "CIM write to cached flash space", -1, 1},
-		{F_SGLWRFLASHINT, "CIM single write to flash space", -1, 1},
-		{F_BLKRDFLASHINT, "CIM block read from flash space", -1, 1},
-		{F_BLKWRFLASHINT, "CIM block write to flash space", -1, 1},
-		{F_BLKRDCTLINT, "CIM block read from CTL space", -1, 1},
-		{F_BLKWRCTLINT, "CIM block write to CTL space", -1, 1},
-		{F_BLKRDPLINT, "CIM block read from PL space", -1, 1},
-		{F_BLKWRPLINT, "CIM block write to PL space", -1, 1},
-		{F_DRAMPARERR, "CIM DRAM parity error", -1, 1},
-		{F_ICACHEPARERR, "CIM icache parity error", -1, 1},
-		{F_DCACHEPARERR, "CIM dcache parity error", -1, 1},
-		{F_OBQSGEPARERR, "CIM OBQ SGE parity error", -1, 1},
-		{F_OBQULPHIPARERR, "CIM OBQ ULPHI parity error", -1, 1},
-		{F_OBQULPLOPARERR, "CIM OBQ ULPLO parity error", -1, 1},
-		{F_IBQSGELOPARERR, "CIM IBQ SGELO parity error", -1, 1},
-		{F_IBQSGEHIPARERR, "CIM IBQ SGEHI parity error", -1, 1},
-		{F_IBQULPPARERR, "CIM IBQ ULP parity error", -1, 1},
-		{F_IBQTPPARERR, "CIM IBQ TP parity error", -1, 1},
-		{F_ITAGPARERR, "CIM itag parity error", -1, 1},
-		{F_DTAGPARERR, "CIM dtag parity error", -1, 1},
-		{0}
-	};
-
-	if (t3_handle_intr_status(adapter, A_CIM_HOST_INT_CAUSE, 0xffffffff,
-				  cim_intr_info, NULL))
-		t3_fatal_err(adapter);
-}
-
-/*
- * ULP RX interrupt handler.
- */
-static void ulprx_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info ulprx_intr_info[] = {
-		{F_PARERRDATA, "ULP RX data parity error", -1, 1},
-		{F_PARERRPCMD, "ULP RX command parity error", -1, 1},
-		{F_ARBPF1PERR, "ULP RX ArbPF1 parity error", -1, 1},
-		{F_ARBPF0PERR, "ULP RX ArbPF0 parity error", -1, 1},
-		{F_ARBFPERR, "ULP RX ArbF parity error", -1, 1},
-		{F_PCMDMUXPERR, "ULP RX PCMDMUX parity error", -1, 1},
-		{F_DATASELFRAMEERR1, "ULP RX frame error", -1, 1},
-		{F_DATASELFRAMEERR0, "ULP RX frame error", -1, 1},
-		{0}
-	};
-
-	if (t3_handle_intr_status(adapter, A_ULPRX_INT_CAUSE, 0xffffffff,
-				  ulprx_intr_info, NULL))
-		t3_fatal_err(adapter);
-}
-
-/*
- * ULP TX interrupt handler.
- */
-static void ulptx_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info ulptx_intr_info[] = {
-		{F_PBL_BOUND_ERR_CH0, "ULP TX channel 0 PBL out of bounds",
-		 STAT_ULP_CH0_PBL_OOB, 0},
-		{F_PBL_BOUND_ERR_CH1, "ULP TX channel 1 PBL out of bounds",
-		 STAT_ULP_CH1_PBL_OOB, 0},
-		{0xfc, "ULP TX parity error", -1, 1},
-		{0}
-	};
-
-	if (t3_handle_intr_status(adapter, A_ULPTX_INT_CAUSE, 0xffffffff,
-				  ulptx_intr_info, adapter->irq_stats))
-		t3_fatal_err(adapter);
-}
-
-#define ICSPI_FRM_ERR (F_ICSPI0_FIFO2X_RX_FRAMING_ERROR | \
-	F_ICSPI1_FIFO2X_RX_FRAMING_ERROR | F_ICSPI0_RX_FRAMING_ERROR | \
-	F_ICSPI1_RX_FRAMING_ERROR | F_ICSPI0_TX_FRAMING_ERROR | \
-	F_ICSPI1_TX_FRAMING_ERROR)
-#define OESPI_FRM_ERR (F_OESPI0_RX_FRAMING_ERROR | \
-	F_OESPI1_RX_FRAMING_ERROR | F_OESPI0_TX_FRAMING_ERROR | \
-	F_OESPI1_TX_FRAMING_ERROR | F_OESPI0_OFIFO2X_TX_FRAMING_ERROR | \
-	F_OESPI1_OFIFO2X_TX_FRAMING_ERROR)
-
-/*
- * PM TX interrupt handler.
- */
-static void pmtx_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info pmtx_intr_info[] = {
-		{F_ZERO_C_CMD_ERROR, "PMTX 0-length pcmd", -1, 1},
-		{ICSPI_FRM_ERR, "PMTX ispi framing error", -1, 1},
-		{OESPI_FRM_ERR, "PMTX ospi framing error", -1, 1},
-		{V_ICSPI_PAR_ERROR(M_ICSPI_PAR_ERROR),
-		 "PMTX ispi parity error", -1, 1},
-		{V_OESPI_PAR_ERROR(M_OESPI_PAR_ERROR),
-		 "PMTX ospi parity error", -1, 1},
-		{0}
-	};
-
-	if (t3_handle_intr_status(adapter, A_PM1_TX_INT_CAUSE, 0xffffffff,
-				  pmtx_intr_info, NULL))
-		t3_fatal_err(adapter);
-}
-
-#define IESPI_FRM_ERR (F_IESPI0_FIFO2X_RX_FRAMING_ERROR | \
-	F_IESPI1_FIFO2X_RX_FRAMING_ERROR | F_IESPI0_RX_FRAMING_ERROR | \
-	F_IESPI1_RX_FRAMING_ERROR | F_IESPI0_TX_FRAMING_ERROR | \
-	F_IESPI1_TX_FRAMING_ERROR)
-#define OCSPI_FRM_ERR (F_OCSPI0_RX_FRAMING_ERROR | \
-	F_OCSPI1_RX_FRAMING_ERROR | F_OCSPI0_TX_FRAMING_ERROR | \
-	F_OCSPI1_TX_FRAMING_ERROR | F_OCSPI0_OFIFO2X_TX_FRAMING_ERROR | \
-	F_OCSPI1_OFIFO2X_TX_FRAMING_ERROR)
-
-/*
- * PM RX interrupt handler.
- */
-static void pmrx_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info pmrx_intr_info[] = {
-		{F_ZERO_E_CMD_ERROR, "PMRX 0-length pcmd", -1, 1},
-		{IESPI_FRM_ERR, "PMRX ispi framing error", -1, 1},
-		{OCSPI_FRM_ERR, "PMRX ospi framing error", -1, 1},
-		{V_IESPI_PAR_ERROR(M_IESPI_PAR_ERROR),
-		 "PMRX ispi parity error", -1, 1},
-		{V_OCSPI_PAR_ERROR(M_OCSPI_PAR_ERROR),
-		 "PMRX ospi parity error", -1, 1},
-		{0}
-	};
-
-	if (t3_handle_intr_status(adapter, A_PM1_RX_INT_CAUSE, 0xffffffff,
-				  pmrx_intr_info, NULL))
-		t3_fatal_err(adapter);
-}
-
-/*
- * CPL switch interrupt handler.
- */
-static void cplsw_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info cplsw_intr_info[] = {
-		{F_CIM_OP_MAP_PERR, "CPL switch CIM parity error", -1, 1},
-		{F_CIM_OVFL_ERROR, "CPL switch CIM overflow", -1, 1},
-		{F_TP_FRAMING_ERROR, "CPL switch TP framing error", -1, 1},
-		{F_SGE_FRAMING_ERROR, "CPL switch SGE framing error", -1, 1},
-		{F_CIM_FRAMING_ERROR, "CPL switch CIM framing error", -1, 1},
-		{F_ZERO_SWITCH_ERROR, "CPL switch no-switch error", -1, 1},
-		{0}
-	};
-
-	if (t3_handle_intr_status(adapter, A_CPL_INTR_CAUSE, 0xffffffff,
-				  cplsw_intr_info, NULL))
-		t3_fatal_err(adapter);
-}
-
-/*
- * MPS interrupt handler.
- */
-static void mps_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info mps_intr_info[] = {
-		{0x1ff, "MPS parity error", -1, 1},
-		{0}
-	};
-
-	if (t3_handle_intr_status(adapter, A_MPS_INT_CAUSE, 0xffffffff,
-				  mps_intr_info, NULL))
-		t3_fatal_err(adapter);
-}
-
-#define MC7_INTR_FATAL (F_UE | V_PE(M_PE) | F_AE)
-
-/*
- * MC7 interrupt handler.
- */
-static void mc7_intr_handler(struct mc7 *mc7)
-{
-	struct adapter *adapter = mc7->adapter;
-	u32 cause = t3_read_reg(adapter, mc7->offset + A_MC7_INT_CAUSE);
-
-	if (cause & F_CE) {
-		mc7->stats.corr_err++;
-		CH_WARN(adapter, "%s MC7 correctable error at addr 0x%x, "
-			"data 0x%x 0x%x 0x%x\n", mc7->name,
-			t3_read_reg(adapter, mc7->offset + A_MC7_CE_ADDR),
-			t3_read_reg(adapter, mc7->offset + A_MC7_CE_DATA0),
-			t3_read_reg(adapter, mc7->offset + A_MC7_CE_DATA1),
-			t3_read_reg(adapter, mc7->offset + A_MC7_CE_DATA2));
-	}
-
-	if (cause & F_UE) {
-		mc7->stats.uncorr_err++;
-		CH_ALERT(adapter, "%s MC7 uncorrectable error at addr 0x%x, "
-			 "data 0x%x 0x%x 0x%x\n", mc7->name,
-			 t3_read_reg(adapter, mc7->offset + A_MC7_UE_ADDR),
-			 t3_read_reg(adapter, mc7->offset + A_MC7_UE_DATA0),
-			 t3_read_reg(adapter, mc7->offset + A_MC7_UE_DATA1),
-			 t3_read_reg(adapter, mc7->offset + A_MC7_UE_DATA2));
-	}
-
-	if (G_PE(cause)) {
-		mc7->stats.parity_err++;
-		CH_ALERT(adapter, "%s MC7 parity error 0x%x\n",
-			 mc7->name, G_PE(cause));
-	}
-
-	if (cause & F_AE) {
-		u32 addr = 0;
-
-		if (adapter->params.rev > 0)
-			addr = t3_read_reg(adapter,
-					   mc7->offset + A_MC7_ERR_ADDR);
-		mc7->stats.addr_err++;
-		CH_ALERT(adapter, "%s MC7 address error: 0x%x\n",
-			 mc7->name, addr);
-	}
-
-	if (cause & MC7_INTR_FATAL)
-		t3_fatal_err(adapter);
-
-	t3_write_reg(adapter, mc7->offset + A_MC7_INT_CAUSE, cause);
-}
-
-#define XGM_INTR_FATAL (V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR) | \
-			V_RXFIFO_PRTY_ERR(M_RXFIFO_PRTY_ERR))
-/*
- * XGMAC interrupt handler.
- */
-static int mac_intr_handler(struct adapter *adap, unsigned int idx)
-{
-	struct cmac *mac = &adap2pinfo(adap, idx)->mac;
-	/*
-	 * We mask out interrupt causes for which we're not taking interrupts.
-	 * This allows us to use polling logic to monitor some of the other
-	 * conditions when taking interrupts would impose too much load on the
-	 * system.
-	 */
-	u32 cause = t3_read_reg(adap, A_XGM_INT_CAUSE + mac->offset) &
-		    ~F_RXFIFO_OVERFLOW;
-
-	if (cause & V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR)) {
-		mac->stats.tx_fifo_parity_err++;
-		CH_ALERT(adap, "port%d: MAC TX FIFO parity error\n", idx);
-	}
-	if (cause & V_RXFIFO_PRTY_ERR(M_RXFIFO_PRTY_ERR)) {
-		mac->stats.rx_fifo_parity_err++;
-		CH_ALERT(adap, "port%d: MAC RX FIFO parity error\n", idx);
-	}
-	if (cause & F_TXFIFO_UNDERRUN)
-		mac->stats.tx_fifo_urun++;
-	if (cause & F_RXFIFO_OVERFLOW)
-		mac->stats.rx_fifo_ovfl++;
-	if (cause & V_SERDES_LOS(M_SERDES_LOS))
-		mac->stats.serdes_signal_loss++;
-	if (cause & F_XAUIPCSCTCERR)
-		mac->stats.xaui_pcs_ctc_err++;
-	if (cause & F_XAUIPCSALIGNCHANGE)
-		mac->stats.xaui_pcs_align_change++;
-	if (cause & F_XGM_INT) {
-		t3_set_reg_field(adap,
-				 A_XGM_INT_ENABLE + mac->offset,
-				 F_XGM_INT, 0);
-		mac->stats.link_faults++;
-
-		t3_os_link_fault_handler(adap, idx);
-	}
-
-	if (cause & XGM_INTR_FATAL)
-		t3_fatal_err(adap);
-
-	t3_write_reg(adap, A_XGM_INT_CAUSE + mac->offset, cause);
-	return cause != 0;
-}
-
-/*
- * Interrupt handler for PHY events.
- */
-int t3_phy_intr_handler(struct adapter *adapter)
-{
-	u32 i, cause = t3_read_reg(adapter, A_T3DBG_INT_CAUSE);
-
-	for_each_port(adapter, i) {
-		struct port_info *p = adap2pinfo(adapter, i);
-
-		if (!(p->phy.caps & SUPPORTED_IRQ))
-			continue;
-
-		if (cause & (1 << adapter_info(adapter)->gpio_intr[i])) {
-			int phy_cause = p->phy.ops->intr_handler(&p->phy);
-
-			if (phy_cause & cphy_cause_link_change)
-				t3_link_changed(adapter, i);
-			if (phy_cause & cphy_cause_fifo_error)
-				p->phy.fifo_errors++;
-			if (phy_cause & cphy_cause_module_change)
-				t3_os_phymod_changed(adapter, i);
-		}
-	}
-
-	t3_write_reg(adapter, A_T3DBG_INT_CAUSE, cause);
-	return 0;
-}
-
-/*
- * T3 slow path (non-data) interrupt handler.
- */
-int t3_slow_intr_handler(struct adapter *adapter)
-{
-	u32 cause = t3_read_reg(adapter, A_PL_INT_CAUSE0);
-
-	cause &= adapter->slow_intr_mask;
-	if (!cause)
-		return 0;
-	if (cause & F_PCIM0) {
-		if (is_pcie(adapter))
-			pcie_intr_handler(adapter);
-		else
-			pci_intr_handler(adapter);
-	}
-	if (cause & F_SGE3)
-		t3_sge_err_intr_handler(adapter);
-	if (cause & F_MC7_PMRX)
-		mc7_intr_handler(&adapter->pmrx);
-	if (cause & F_MC7_PMTX)
-		mc7_intr_handler(&adapter->pmtx);
-	if (cause & F_MC7_CM)
-		mc7_intr_handler(&adapter->cm);
-	if (cause & F_CIM)
-		cim_intr_handler(adapter);
-	if (cause & F_TP1)
-		tp_intr_handler(adapter);
-	if (cause & F_ULP2_RX)
-		ulprx_intr_handler(adapter);
-	if (cause & F_ULP2_TX)
-		ulptx_intr_handler(adapter);
-	if (cause & F_PM1_RX)
-		pmrx_intr_handler(adapter);
-	if (cause & F_PM1_TX)
-		pmtx_intr_handler(adapter);
-	if (cause & F_CPL_SWITCH)
-		cplsw_intr_handler(adapter);
-	if (cause & F_MPS0)
-		mps_intr_handler(adapter);
-	if (cause & F_MC5A)
-		t3_mc5_intr_handler(&adapter->mc5);
-	if (cause & F_XGMAC0_0)
-		mac_intr_handler(adapter, 0);
-	if (cause & F_XGMAC0_1)
-		mac_intr_handler(adapter, 1);
-	if (cause & F_T3DBG)
-		t3_os_ext_intr_handler(adapter);
-
-	/* Clear the interrupts just processed. */
-	t3_write_reg(adapter, A_PL_INT_CAUSE0, cause);
-	t3_read_reg(adapter, A_PL_INT_CAUSE0);	/* flush */
-	return 1;
-}
-
-static unsigned int calc_gpio_intr(struct adapter *adap)
-{
-	unsigned int i, gpi_intr = 0;
-
-	for_each_port(adap, i)
-		if ((adap2pinfo(adap, i)->phy.caps & SUPPORTED_IRQ) &&
-		    adapter_info(adap)->gpio_intr[i])
-			gpi_intr |= 1 << adapter_info(adap)->gpio_intr[i];
-	return gpi_intr;
-}
-
-/**
- *	t3_intr_enable - enable interrupts
- *	@adapter: the adapter whose interrupts should be enabled
- *
- *	Enable interrupts by setting the interrupt enable registers of the
- *	various HW modules and then enabling the top-level interrupt
- *	concentrator.
- */
-void t3_intr_enable(struct adapter *adapter)
-{
-	static const struct addr_val_pair intr_en_avp[] = {
-		{A_SG_INT_ENABLE, SGE_INTR_MASK},
-		{A_MC7_INT_ENABLE, MC7_INTR_MASK},
-		{A_MC7_INT_ENABLE - MC7_PMRX_BASE_ADDR + MC7_PMTX_BASE_ADDR,
-		 MC7_INTR_MASK},
-		{A_MC7_INT_ENABLE - MC7_PMRX_BASE_ADDR + MC7_CM_BASE_ADDR,
-		 MC7_INTR_MASK},
-		{A_MC5_DB_INT_ENABLE, MC5_INTR_MASK},
-		{A_ULPRX_INT_ENABLE, ULPRX_INTR_MASK},
-		{A_PM1_TX_INT_ENABLE, PMTX_INTR_MASK},
-		{A_PM1_RX_INT_ENABLE, PMRX_INTR_MASK},
-		{A_CIM_HOST_INT_ENABLE, CIM_INTR_MASK},
-		{A_MPS_INT_ENABLE, MPS_INTR_MASK},
-	};
-
-	adapter->slow_intr_mask = PL_INTR_MASK;
-
-	t3_write_regs(adapter, intr_en_avp, ARRAY_SIZE(intr_en_avp), 0);
-	t3_write_reg(adapter, A_TP_INT_ENABLE,
-		     adapter->params.rev >= T3_REV_C ? 0x2bfffff : 0x3bfffff);
-
-	if (adapter->params.rev > 0) {
-		t3_write_reg(adapter, A_CPL_INTR_ENABLE,
-			     CPLSW_INTR_MASK | F_CIM_OVFL_ERROR);
-		t3_write_reg(adapter, A_ULPTX_INT_ENABLE,
-			     ULPTX_INTR_MASK | F_PBL_BOUND_ERR_CH0 |
-			     F_PBL_BOUND_ERR_CH1);
-	} else {
-		t3_write_reg(adapter, A_CPL_INTR_ENABLE, CPLSW_INTR_MASK);
-		t3_write_reg(adapter, A_ULPTX_INT_ENABLE, ULPTX_INTR_MASK);
-	}
-
-	t3_write_reg(adapter, A_T3DBG_INT_ENABLE, calc_gpio_intr(adapter));
-
-	if (is_pcie(adapter))
-		t3_write_reg(adapter, A_PCIE_INT_ENABLE, PCIE_INTR_MASK);
-	else
-		t3_write_reg(adapter, A_PCIX_INT_ENABLE, PCIX_INTR_MASK);
-	t3_write_reg(adapter, A_PL_INT_ENABLE0, adapter->slow_intr_mask);
-	t3_read_reg(adapter, A_PL_INT_ENABLE0);	/* flush */
-}
-
-/**
- *	t3_intr_disable - disable a card's interrupts
- *	@adapter: the adapter whose interrupts should be disabled
- *
- *	Disable interrupts.  We only disable the top-level interrupt
- *	concentrator and the SGE data interrupts.
- */
-void t3_intr_disable(struct adapter *adapter)
-{
-	t3_write_reg(adapter, A_PL_INT_ENABLE0, 0);
-	t3_read_reg(adapter, A_PL_INT_ENABLE0);	/* flush */
-	adapter->slow_intr_mask = 0;
-}
-
-/**
- *	t3_intr_clear - clear all interrupts
- *	@adapter: the adapter whose interrupts should be cleared
- *
- *	Clears all interrupts.
- */
-void t3_intr_clear(struct adapter *adapter)
-{
-	static const unsigned int cause_reg_addr[] = {
-		A_SG_INT_CAUSE,
-		A_SG_RSPQ_FL_STATUS,
-		A_PCIX_INT_CAUSE,
-		A_MC7_INT_CAUSE,
-		A_MC7_INT_CAUSE - MC7_PMRX_BASE_ADDR + MC7_PMTX_BASE_ADDR,
-		A_MC7_INT_CAUSE - MC7_PMRX_BASE_ADDR + MC7_CM_BASE_ADDR,
-		A_CIM_HOST_INT_CAUSE,
-		A_TP_INT_CAUSE,
-		A_MC5_DB_INT_CAUSE,
-		A_ULPRX_INT_CAUSE,
-		A_ULPTX_INT_CAUSE,
-		A_CPL_INTR_CAUSE,
-		A_PM1_TX_INT_CAUSE,
-		A_PM1_RX_INT_CAUSE,
-		A_MPS_INT_CAUSE,
-		A_T3DBG_INT_CAUSE,
-	};
-	unsigned int i;
-
-	/* Clear PHY and MAC interrupts for each port. */
-	for_each_port(adapter, i)
-	    t3_port_intr_clear(adapter, i);
-
-	for (i = 0; i < ARRAY_SIZE(cause_reg_addr); ++i)
-		t3_write_reg(adapter, cause_reg_addr[i], 0xffffffff);
-
-	if (is_pcie(adapter))
-		t3_write_reg(adapter, A_PCIE_PEX_ERR, 0xffffffff);
-	t3_write_reg(adapter, A_PL_INT_CAUSE0, 0xffffffff);
-	t3_read_reg(adapter, A_PL_INT_CAUSE0);	/* flush */
-}
-
-void t3_xgm_intr_enable(struct adapter *adapter, int idx)
-{
-	struct port_info *pi = adap2pinfo(adapter, idx);
-
-	t3_write_reg(adapter, A_XGM_XGM_INT_ENABLE + pi->mac.offset,
-		     XGM_EXTRA_INTR_MASK);
-}
-
-void t3_xgm_intr_disable(struct adapter *adapter, int idx)
-{
-	struct port_info *pi = adap2pinfo(adapter, idx);
-
-	t3_write_reg(adapter, A_XGM_XGM_INT_DISABLE + pi->mac.offset,
-		     0x7ff);
-}
-
-/**
- *	t3_port_intr_enable - enable port-specific interrupts
- *	@adapter: associated adapter
- *	@idx: index of port whose interrupts should be enabled
- *
- *	Enable port-specific (i.e., MAC and PHY) interrupts for the given
- *	adapter port.
- */
-void t3_port_intr_enable(struct adapter *adapter, int idx)
-{
-	struct cphy *phy = &adap2pinfo(adapter, idx)->phy;
-
-	t3_write_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx), XGM_INTR_MASK);
-	t3_read_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx)); /* flush */
-	phy->ops->intr_enable(phy);
-}
-
-/**
- *	t3_port_intr_disable - disable port-specific interrupts
- *	@adapter: associated adapter
- *	@idx: index of port whose interrupts should be disabled
- *
- *	Disable port-specific (i.e., MAC and PHY) interrupts for the given
- *	adapter port.
- */
-void t3_port_intr_disable(struct adapter *adapter, int idx)
-{
-	struct cphy *phy = &adap2pinfo(adapter, idx)->phy;
-
-	t3_write_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx), 0);
-	t3_read_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx)); /* flush */
-	phy->ops->intr_disable(phy);
-}
-
-/**
- *	t3_port_intr_clear - clear port-specific interrupts
- *	@adapter: associated adapter
- *	@idx: index of port whose interrupts to clear
- *
- *	Clear port-specific (i.e., MAC and PHY) interrupts for the given
- *	adapter port.
- */
-static void t3_port_intr_clear(struct adapter *adapter, int idx)
-{
-	struct cphy *phy = &adap2pinfo(adapter, idx)->phy;
-
-	t3_write_reg(adapter, XGM_REG(A_XGM_INT_CAUSE, idx), 0xffffffff);
-	t3_read_reg(adapter, XGM_REG(A_XGM_INT_CAUSE, idx)); /* flush */
-	phy->ops->intr_clear(phy);
-}
-
-#define SG_CONTEXT_CMD_ATTEMPTS 100
-
-/**
- * 	t3_sge_write_context - write an SGE context
- * 	@adapter: the adapter
- * 	@id: the context id
- * 	@type: the context type
- *
- * 	Program an SGE context with the values already loaded in the
- * 	CONTEXT_DATA? registers.
- */
-static int t3_sge_write_context(struct adapter *adapter, unsigned int id,
-				unsigned int type)
-{
-	if (type == F_RESPONSEQ) {
-		/*
-		 * Can't write the Response Queue Context bits for
-		 * Interrupt Armed or the Reserve bits after the chip
-		 * has been initialized out of reset.  Writing to these
-		 * bits can confuse the hardware.
-		 */
-		t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0xffffffff);
-		t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0xffffffff);
-		t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0x17ffffff);
-		t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0xffffffff);
-	} else {
-		t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0xffffffff);
-		t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0xffffffff);
-		t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0xffffffff);
-		t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0xffffffff);
-	}
-	t3_write_reg(adapter, A_SG_CONTEXT_CMD,
-		     V_CONTEXT_CMD_OPCODE(1) | type | V_CONTEXT(id));
-	return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY,
-			       0, SG_CONTEXT_CMD_ATTEMPTS, 1);
-}
-
-/**
- *	clear_sge_ctxt - completely clear an SGE context
- *	@adapter: the adapter
- *	@id: the context id
- *	@type: the context type
- *
- *	Completely clear an SGE context.  Used predominantly at post-reset
- *	initialization.  Note in particular that we don't skip writing to any
- *	"sensitive bits" in the contexts the way that t3_sge_write_context()
- *	does ...
- */
-static int clear_sge_ctxt(struct adapter *adap, unsigned int id,
-			  unsigned int type)
-{
-	t3_write_reg(adap, A_SG_CONTEXT_DATA0, 0);
-	t3_write_reg(adap, A_SG_CONTEXT_DATA1, 0);
-	t3_write_reg(adap, A_SG_CONTEXT_DATA2, 0);
-	t3_write_reg(adap, A_SG_CONTEXT_DATA3, 0);
-	t3_write_reg(adap, A_SG_CONTEXT_MASK0, 0xffffffff);
-	t3_write_reg(adap, A_SG_CONTEXT_MASK1, 0xffffffff);
-	t3_write_reg(adap, A_SG_CONTEXT_MASK2, 0xffffffff);
-	t3_write_reg(adap, A_SG_CONTEXT_MASK3, 0xffffffff);
-	t3_write_reg(adap, A_SG_CONTEXT_CMD,
-		     V_CONTEXT_CMD_OPCODE(1) | type | V_CONTEXT(id));
-	return t3_wait_op_done(adap, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY,
-			       0, SG_CONTEXT_CMD_ATTEMPTS, 1);
-}
-
-/**
- *	t3_sge_init_ecntxt - initialize an SGE egress context
- *	@adapter: the adapter to configure
- *	@id: the context id
- *	@gts_enable: whether to enable GTS for the context
- *	@type: the egress context type
- *	@respq: associated response queue
- *	@base_addr: base address of queue
- *	@size: number of queue entries
- *	@token: uP token
- *	@gen: initial generation value for the context
- *	@cidx: consumer pointer
- *
- *	Initialize an SGE egress context and make it ready for use.  If the
- *	platform allows concurrent context operations, the caller is
- *	responsible for appropriate locking.
- */
-int t3_sge_init_ecntxt(struct adapter *adapter, unsigned int id, int gts_enable,
-		       enum sge_context_type type, int respq, u64 base_addr,
-		       unsigned int size, unsigned int token, int gen,
-		       unsigned int cidx)
-{
-	unsigned int credits = type == SGE_CNTXT_OFLD ? 0 : FW_WR_NUM;
-
-	if (base_addr & 0xfff)	/* must be 4K aligned */
-		return -EINVAL;
-	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
-		return -EBUSY;
-
-	base_addr >>= 12;
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA0, V_EC_INDEX(cidx) |
-		     V_EC_CREDITS(credits) | V_EC_GTS(gts_enable));
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA1, V_EC_SIZE(size) |
-		     V_EC_BASE_LO(base_addr & 0xffff));
-	base_addr >>= 16;
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA2, base_addr);
-	base_addr >>= 32;
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA3,
-		     V_EC_BASE_HI(base_addr & 0xf) | V_EC_RESPQ(respq) |
-		     V_EC_TYPE(type) | V_EC_GEN(gen) | V_EC_UP_TOKEN(token) |
-		     F_EC_VALID);
-	return t3_sge_write_context(adapter, id, F_EGRESS);
-}
-
-/**
- *	t3_sge_init_flcntxt - initialize an SGE free-buffer list context
- *	@adapter: the adapter to configure
- *	@id: the context id
- *	@gts_enable: whether to enable GTS for the context
- *	@base_addr: base address of queue
- *	@size: number of queue entries
- *	@bsize: size of each buffer for this queue
- *	@cong_thres: threshold to signal congestion to upstream producers
- *	@gen: initial generation value for the context
- *	@cidx: consumer pointer
- *
- *	Initialize an SGE free list context and make it ready for use.  The
- *	caller is responsible for ensuring only one context operation occurs
- *	at a time.
- */
-int t3_sge_init_flcntxt(struct adapter *adapter, unsigned int id,
-			int gts_enable, u64 base_addr, unsigned int size,
-			unsigned int bsize, unsigned int cong_thres, int gen,
-			unsigned int cidx)
-{
-	if (base_addr & 0xfff)	/* must be 4K aligned */
-		return -EINVAL;
-	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
-		return -EBUSY;
-
-	base_addr >>= 12;
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA0, base_addr);
-	base_addr >>= 32;
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA1,
-		     V_FL_BASE_HI((u32) base_addr) |
-		     V_FL_INDEX_LO(cidx & M_FL_INDEX_LO));
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA2, V_FL_SIZE(size) |
-		     V_FL_GEN(gen) | V_FL_INDEX_HI(cidx >> 12) |
-		     V_FL_ENTRY_SIZE_LO(bsize & M_FL_ENTRY_SIZE_LO));
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA3,
-		     V_FL_ENTRY_SIZE_HI(bsize >> (32 - S_FL_ENTRY_SIZE_LO)) |
-		     V_FL_CONG_THRES(cong_thres) | V_FL_GTS(gts_enable));
-	return t3_sge_write_context(adapter, id, F_FREELIST);
-}
-
-/**
- *	t3_sge_init_rspcntxt - initialize an SGE response queue context
- *	@adapter: the adapter to configure
- *	@id: the context id
- *	@irq_vec_idx: MSI-X interrupt vector index, 0 if no MSI-X, -1 if no IRQ
- *	@base_addr: base address of queue
- *	@size: number of queue entries
- *	@fl_thres: threshold for selecting the normal or jumbo free list
- *	@gen: initial generation value for the context
- *	@cidx: consumer pointer
- *
- *	Initialize an SGE response queue context and make it ready for use.
- *	The caller is responsible for ensuring only one context operation
- *	occurs at a time.
- */
-int t3_sge_init_rspcntxt(struct adapter *adapter, unsigned int id,
-			 int irq_vec_idx, u64 base_addr, unsigned int size,
-			 unsigned int fl_thres, int gen, unsigned int cidx)
-{
-	unsigned int intr = 0;
-
-	if (base_addr & 0xfff)	/* must be 4K aligned */
-		return -EINVAL;
-	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
-		return -EBUSY;
-
-	base_addr >>= 12;
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA0, V_CQ_SIZE(size) |
-		     V_CQ_INDEX(cidx));
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA1, base_addr);
-	base_addr >>= 32;
-	if (irq_vec_idx >= 0)
-		intr = V_RQ_MSI_VEC(irq_vec_idx) | F_RQ_INTR_EN;
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA2,
-		     V_CQ_BASE_HI((u32) base_addr) | intr | V_RQ_GEN(gen));
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA3, fl_thres);
-	return t3_sge_write_context(adapter, id, F_RESPONSEQ);
-}
-
-/**
- *	t3_sge_init_cqcntxt - initialize an SGE completion queue context
- *	@adapter: the adapter to configure
- *	@id: the context id
- *	@base_addr: base address of queue
- *	@size: number of queue entries
- *	@rspq: response queue for async notifications
- *	@ovfl_mode: CQ overflow mode
- *	@credits: completion queue credits
- *	@credit_thres: the credit threshold
- *
- *	Initialize an SGE completion queue context and make it ready for use.
- *	The caller is responsible for ensuring only one context operation
- *	occurs at a time.
- */
-int t3_sge_init_cqcntxt(struct adapter *adapter, unsigned int id, u64 base_addr,
-			unsigned int size, int rspq, int ovfl_mode,
-			unsigned int credits, unsigned int credit_thres)
-{
-	if (base_addr & 0xfff)	/* must be 4K aligned */
-		return -EINVAL;
-	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
-		return -EBUSY;
-
-	base_addr >>= 12;
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA0, V_CQ_SIZE(size));
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA1, base_addr);
-	base_addr >>= 32;
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA2,
-		     V_CQ_BASE_HI((u32) base_addr) | V_CQ_RSPQ(rspq) |
-		     V_CQ_GEN(1) | V_CQ_OVERFLOW_MODE(ovfl_mode) |
-		     V_CQ_ERR(ovfl_mode));
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA3, V_CQ_CREDITS(credits) |
-		     V_CQ_CREDIT_THRES(credit_thres));
-	return t3_sge_write_context(adapter, id, F_CQ);
-}
-
-/**
- *	t3_sge_enable_ecntxt - enable/disable an SGE egress context
- *	@adapter: the adapter
- *	@id: the egress context id
- *	@enable: enable (1) or disable (0) the context
- *
- *	Enable or disable an SGE egress context.  The caller is responsible for
- *	ensuring only one context operation occurs at a time.
- */
-int t3_sge_enable_ecntxt(struct adapter *adapter, unsigned int id, int enable)
-{
-	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
-		return -EBUSY;
-
-	t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0);
-	t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0);
-	t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0);
-	t3_write_reg(adapter, A_SG_CONTEXT_MASK3, F_EC_VALID);
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA3, V_EC_VALID(enable));
-	t3_write_reg(adapter, A_SG_CONTEXT_CMD,
-		     V_CONTEXT_CMD_OPCODE(1) | F_EGRESS | V_CONTEXT(id));
-	return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY,
-			       0, SG_CONTEXT_CMD_ATTEMPTS, 1);
-}
-
-/**
- *	t3_sge_disable_fl - disable an SGE free-buffer list
- *	@adapter: the adapter
- *	@id: the free list context id
- *
- *	Disable an SGE free-buffer list.  The caller is responsible for
- *	ensuring only one context operation occurs at a time.
- */
-int t3_sge_disable_fl(struct adapter *adapter, unsigned int id)
-{
-	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
-		return -EBUSY;
-
-	t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0);
-	t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0);
-	t3_write_reg(adapter, A_SG_CONTEXT_MASK2, V_FL_SIZE(M_FL_SIZE));
-	t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0);
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA2, 0);
-	t3_write_reg(adapter, A_SG_CONTEXT_CMD,
-		     V_CONTEXT_CMD_OPCODE(1) | F_FREELIST | V_CONTEXT(id));
-	return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY,
-			       0, SG_CONTEXT_CMD_ATTEMPTS, 1);
-}
-
-/**
- *	t3_sge_disable_rspcntxt - disable an SGE response queue
- *	@adapter: the adapter
- *	@id: the response queue context id
- *
- *	Disable an SGE response queue.  The caller is responsible for
- *	ensuring only one context operation occurs at a time.
- */
-int t3_sge_disable_rspcntxt(struct adapter *adapter, unsigned int id)
-{
-	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
-		return -EBUSY;
-
-	t3_write_reg(adapter, A_SG_CONTEXT_MASK0, V_CQ_SIZE(M_CQ_SIZE));
-	t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0);
-	t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0);
-	t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0);
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA0, 0);
-	t3_write_reg(adapter, A_SG_CONTEXT_CMD,
-		     V_CONTEXT_CMD_OPCODE(1) | F_RESPONSEQ | V_CONTEXT(id));
-	return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY,
-			       0, SG_CONTEXT_CMD_ATTEMPTS, 1);
-}
-
-/**
- *	t3_sge_disable_cqcntxt - disable an SGE completion queue
- *	@adapter: the adapter
- *	@id: the completion queue context id
- *
- *	Disable an SGE completion queue.  The caller is responsible for
- *	ensuring only one context operation occurs at a time.
- */
-int t3_sge_disable_cqcntxt(struct adapter *adapter, unsigned int id)
-{
-	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
-		return -EBUSY;
-
-	t3_write_reg(adapter, A_SG_CONTEXT_MASK0, V_CQ_SIZE(M_CQ_SIZE));
-	t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0);
-	t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0);
-	t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0);
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA0, 0);
-	t3_write_reg(adapter, A_SG_CONTEXT_CMD,
-		     V_CONTEXT_CMD_OPCODE(1) | F_CQ | V_CONTEXT(id));
-	return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY,
-			       0, SG_CONTEXT_CMD_ATTEMPTS, 1);
-}
-
-/**
- *	t3_sge_cqcntxt_op - perform an operation on a completion queue context
- *	@adapter: the adapter
- *	@id: the context id
- *	@op: the operation to perform
- *
- *	Perform the selected operation on an SGE completion queue context.
- *	The caller is responsible for ensuring only one context operation
- *	occurs at a time.
- */
-int t3_sge_cqcntxt_op(struct adapter *adapter, unsigned int id, unsigned int op,
-		      unsigned int credits)
-{
-	u32 val;
-
-	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
-		return -EBUSY;
-
-	t3_write_reg(adapter, A_SG_CONTEXT_DATA0, credits << 16);
-	t3_write_reg(adapter, A_SG_CONTEXT_CMD, V_CONTEXT_CMD_OPCODE(op) |
-		     V_CONTEXT(id) | F_CQ);
-	if (t3_wait_op_done_val(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY,
-				0, SG_CONTEXT_CMD_ATTEMPTS, 1, &val))
-		return -EIO;
-
-	if (op >= 2 && op < 7) {
-		if (adapter->params.rev > 0)
-			return G_CQ_INDEX(val);
-
-		t3_write_reg(adapter, A_SG_CONTEXT_CMD,
-			     V_CONTEXT_CMD_OPCODE(0) | F_CQ | V_CONTEXT(id));
-		if (t3_wait_op_done(adapter, A_SG_CONTEXT_CMD,
-				    F_CONTEXT_CMD_BUSY, 0,
-				    SG_CONTEXT_CMD_ATTEMPTS, 1))
-			return -EIO;
-		return G_CQ_INDEX(t3_read_reg(adapter, A_SG_CONTEXT_DATA0));
-	}
-	return 0;
-}
-
-/**
- *	t3_config_rss - configure Rx packet steering
- *	@adapter: the adapter
- *	@rss_config: RSS settings (written to TP_RSS_CONFIG)
- *	@cpus: values for the CPU lookup table (0xff terminated)
- *	@rspq: values for the response queue lookup table (0xffff terminated)
- *
- *	Programs the receive packet steering logic.  @cpus and @rspq provide
- *	the values for the CPU and response queue lookup tables.  If they
- *	provide fewer values than the size of the tables the supplied values
- *	are used repeatedly until the tables are fully populated.
- */
-void t3_config_rss(struct adapter *adapter, unsigned int rss_config,
-		   const u8 * cpus, const u16 *rspq)
-{
-	int i, j, cpu_idx = 0, q_idx = 0;
-
-	if (cpus)
-		for (i = 0; i < RSS_TABLE_SIZE; ++i) {
-			u32 val = i << 16;
-
-			for (j = 0; j < 2; ++j) {
-				val |= (cpus[cpu_idx++] & 0x3f) << (8 * j);
-				if (cpus[cpu_idx] == 0xff)
-					cpu_idx = 0;
-			}
-			t3_write_reg(adapter, A_TP_RSS_LKP_TABLE, val);
-		}
-
-	if (rspq)
-		for (i = 0; i < RSS_TABLE_SIZE; ++i) {
-			t3_write_reg(adapter, A_TP_RSS_MAP_TABLE,
-				     (i << 16) | rspq[q_idx++]);
-			if (rspq[q_idx] == 0xffff)
-				q_idx = 0;
-		}
-
-	t3_write_reg(adapter, A_TP_RSS_CONFIG, rss_config);
-}
-
-/**
- *	t3_tp_set_offload_mode - put TP in NIC/offload mode
- *	@adap: the adapter
- *	@enable: 1 to select offload mode, 0 for regular NIC
- *
- *	Switches TP to NIC/offload mode.
- */
-void t3_tp_set_offload_mode(struct adapter *adap, int enable)
-{
-	if (is_offload(adap) || !enable)
-		t3_set_reg_field(adap, A_TP_IN_CONFIG, F_NICMODE,
-				 V_NICMODE(!enable));
-}
-
-/**
- *	pm_num_pages - calculate the number of pages of the payload memory
- *	@mem_size: the size of the payload memory
- *	@pg_size: the size of each payload memory page
- *
- *	Calculate the number of pages, each of the given size, that fit in a
- *	memory of the specified size, respecting the HW requirement that the
- *	number of pages must be a multiple of 24.
- */
-static inline unsigned int pm_num_pages(unsigned int mem_size,
-					unsigned int pg_size)
-{
-	unsigned int n = mem_size / pg_size;
-
-	return n - n % 24;
-}
-
-#define mem_region(adap, start, size, reg) \
-	t3_write_reg((adap), A_ ## reg, (start)); \
-	start += size
-
-/**
- *	partition_mem - partition memory and configure TP memory settings
- *	@adap: the adapter
- *	@p: the TP parameters
- *
- *	Partitions context and payload memory and configures TP's memory
- *	registers.
- */
-static void partition_mem(struct adapter *adap, const struct tp_params *p)
-{
-	unsigned int m, pstructs, tids = t3_mc5_size(&adap->mc5);
-	unsigned int timers = 0, timers_shift = 22;
-
-	if (adap->params.rev > 0) {
-		if (tids <= 16 * 1024) {
-			timers = 1;
-			timers_shift = 16;
-		} else if (tids <= 64 * 1024) {
-			timers = 2;
-			timers_shift = 18;
-		} else if (tids <= 256 * 1024) {
-			timers = 3;
-			timers_shift = 20;
-		}
-	}
-
-	t3_write_reg(adap, A_TP_PMM_SIZE,
-		     p->chan_rx_size | (p->chan_tx_size >> 16));
-
-	t3_write_reg(adap, A_TP_PMM_TX_BASE, 0);
-	t3_write_reg(adap, A_TP_PMM_TX_PAGE_SIZE, p->tx_pg_size);
-	t3_write_reg(adap, A_TP_PMM_TX_MAX_PAGE, p->tx_num_pgs);
-	t3_set_reg_field(adap, A_TP_PARA_REG3, V_TXDATAACKIDX(M_TXDATAACKIDX),
-			 V_TXDATAACKIDX(fls(p->tx_pg_size) - 12));
-
-	t3_write_reg(adap, A_TP_PMM_RX_BASE, 0);
-	t3_write_reg(adap, A_TP_PMM_RX_PAGE_SIZE, p->rx_pg_size);
-	t3_write_reg(adap, A_TP_PMM_RX_MAX_PAGE, p->rx_num_pgs);
-
-	pstructs = p->rx_num_pgs + p->tx_num_pgs;
-	/* Add a bit of headroom and make multiple of 24 */
-	pstructs += 48;
-	pstructs -= pstructs % 24;
-	t3_write_reg(adap, A_TP_CMM_MM_MAX_PSTRUCT, pstructs);
-
-	m = tids * TCB_SIZE;
-	mem_region(adap, m, (64 << 10) * 64, SG_EGR_CNTX_BADDR);
-	mem_region(adap, m, (64 << 10) * 64, SG_CQ_CONTEXT_BADDR);
-	t3_write_reg(adap, A_TP_CMM_TIMER_BASE, V_CMTIMERMAXNUM(timers) | m);
-	m += ((p->ntimer_qs - 1) << timers_shift) + (1 << 22);
-	mem_region(adap, m, pstructs * 64, TP_CMM_MM_BASE);
-	mem_region(adap, m, 64 * (pstructs / 24), TP_CMM_MM_PS_FLST_BASE);
-	mem_region(adap, m, 64 * (p->rx_num_pgs / 24), TP_CMM_MM_RX_FLST_BASE);
-	mem_region(adap, m, 64 * (p->tx_num_pgs / 24), TP_CMM_MM_TX_FLST_BASE);
-
-	m = (m + 4095) & ~0xfff;
-	t3_write_reg(adap, A_CIM_SDRAM_BASE_ADDR, m);
-	t3_write_reg(adap, A_CIM_SDRAM_ADDR_SIZE, p->cm_size - m);
-
-	tids = (p->cm_size - m - (3 << 20)) / 3072 - 32;
-	m = t3_mc5_size(&adap->mc5) - adap->params.mc5.nservers -
-	    adap->params.mc5.nfilters - adap->params.mc5.nroutes;
-	if (tids < m)
-		adap->params.mc5.nservers += m - tids;
-}
-
-static inline void tp_wr_indirect(struct adapter *adap, unsigned int addr,
-				  u32 val)
-{
-	t3_write_reg(adap, A_TP_PIO_ADDR, addr);
-	t3_write_reg(adap, A_TP_PIO_DATA, val);
-}
-
-static void tp_config(struct adapter *adap, const struct tp_params *p)
-{
-	t3_write_reg(adap, A_TP_GLOBAL_CONFIG, F_TXPACINGENABLE | F_PATHMTU |
-		     F_IPCHECKSUMOFFLOAD | F_UDPCHECKSUMOFFLOAD |
-		     F_TCPCHECKSUMOFFLOAD | V_IPTTL(64));
-	t3_write_reg(adap, A_TP_TCP_OPTIONS, V_MTUDEFAULT(576) |
-		     F_MTUENABLE | V_WINDOWSCALEMODE(1) |
-		     V_TIMESTAMPSMODE(1) | V_SACKMODE(1) | V_SACKRX(1));
-	t3_write_reg(adap, A_TP_DACK_CONFIG, V_AUTOSTATE3(1) |
-		     V_AUTOSTATE2(1) | V_AUTOSTATE1(0) |
-		     V_BYTETHRESHOLD(26880) | V_MSSTHRESHOLD(2) |
-		     F_AUTOCAREFUL | F_AUTOENABLE | V_DACK_MODE(1));
-	t3_set_reg_field(adap, A_TP_IN_CONFIG, F_RXFBARBPRIO | F_TXFBARBPRIO,
-			 F_IPV6ENABLE | F_NICMODE);
-	t3_write_reg(adap, A_TP_TX_RESOURCE_LIMIT, 0x18141814);
-	t3_write_reg(adap, A_TP_PARA_REG4, 0x5050105);
-	t3_set_reg_field(adap, A_TP_PARA_REG6, 0,
-			 adap->params.rev > 0 ? F_ENABLEESND :
-			 F_T3A_ENABLEESND);
-
-	t3_set_reg_field(adap, A_TP_PC_CONFIG,
-			 F_ENABLEEPCMDAFULL,
-			 F_ENABLEOCSPIFULL |F_TXDEFERENABLE | F_HEARBEATDACK |
-			 F_TXCONGESTIONMODE | F_RXCONGESTIONMODE);
-	t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL,
-			 F_ENABLEIPV6RSS | F_ENABLENONOFDTNLSYN |
-			 F_ENABLEARPMISS | F_DISBLEDAPARBIT0);
-	t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1080);
-	t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1000);
-
-	if (adap->params.rev > 0) {
-		tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE);
-		t3_set_reg_field(adap, A_TP_PARA_REG3, F_TXPACEAUTO,
-				 F_TXPACEAUTO);
-		t3_set_reg_field(adap, A_TP_PC_CONFIG, F_LOCKTID, F_LOCKTID);
-		t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEAUTOSTRICT);
-	} else
-		t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEFIXED);
-
-	if (adap->params.rev == T3_REV_C)
-		t3_set_reg_field(adap, A_TP_PC_CONFIG,
-				 V_TABLELATENCYDELTA(M_TABLELATENCYDELTA),
-				 V_TABLELATENCYDELTA(4));
-
-	t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0);
-	t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0);
-	t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0);
-	t3_write_reg(adap, A_TP_MOD_RATE_LIMIT, 0xf2200000);
-}
-
-/* Desired TP timer resolution in usec */
-#define TP_TMR_RES 50
-
-/* TCP timer values in ms */
-#define TP_DACK_TIMER 50
-#define TP_RTO_MIN    250
-
-/**
- *	tp_set_timers - set TP timing parameters
- *	@adap: the adapter to set
- *	@core_clk: the core clock frequency in Hz
- *
- *	Set TP's timing parameters, such as the various timer resolutions and
- *	the TCP timer values.
- */
-static void tp_set_timers(struct adapter *adap, unsigned int core_clk)
-{
-	unsigned int tre = fls(core_clk / (1000000 / TP_TMR_RES)) - 1;
-	unsigned int dack_re = fls(core_clk / 5000) - 1;	/* 200us */
-	unsigned int tstamp_re = fls(core_clk / 1000);	/* 1ms, at least */
-	unsigned int tps = core_clk >> tre;
-
-	t3_write_reg(adap, A_TP_TIMER_RESOLUTION, V_TIMERRESOLUTION(tre) |
-		     V_DELAYEDACKRESOLUTION(dack_re) |
-		     V_TIMESTAMPRESOLUTION(tstamp_re));
-	t3_write_reg(adap, A_TP_DACK_TIMER,
-		     (core_clk >> dack_re) / (1000 / TP_DACK_TIMER));
-	t3_write_reg(adap, A_TP_TCP_BACKOFF_REG0, 0x3020100);
-	t3_write_reg(adap, A_TP_TCP_BACKOFF_REG1, 0x7060504);
-	t3_write_reg(adap, A_TP_TCP_BACKOFF_REG2, 0xb0a0908);
-	t3_write_reg(adap, A_TP_TCP_BACKOFF_REG3, 0xf0e0d0c);
-	t3_write_reg(adap, A_TP_SHIFT_CNT, V_SYNSHIFTMAX(6) |
-		     V_RXTSHIFTMAXR1(4) | V_RXTSHIFTMAXR2(15) |
-		     V_PERSHIFTBACKOFFMAX(8) | V_PERSHIFTMAX(8) |
-		     V_KEEPALIVEMAX(9));
-
-#define SECONDS * tps
-
-	t3_write_reg(adap, A_TP_MSL, adap->params.rev > 0 ? 0 : 2 SECONDS);
-	t3_write_reg(adap, A_TP_RXT_MIN, tps / (1000 / TP_RTO_MIN));
-	t3_write_reg(adap, A_TP_RXT_MAX, 64 SECONDS);
-	t3_write_reg(adap, A_TP_PERS_MIN, 5 SECONDS);
-	t3_write_reg(adap, A_TP_PERS_MAX, 64 SECONDS);
-	t3_write_reg(adap, A_TP_KEEP_IDLE, 7200 SECONDS);
-	t3_write_reg(adap, A_TP_KEEP_INTVL, 75 SECONDS);
-	t3_write_reg(adap, A_TP_INIT_SRTT, 3 SECONDS);
-	t3_write_reg(adap, A_TP_FINWAIT2_TIMER, 600 SECONDS);
-
-#undef SECONDS
-}
-
-/**
- *	t3_tp_set_coalescing_size - set receive coalescing size
- *	@adap: the adapter
- *	@size: the receive coalescing size
- *	@psh: whether a set PSH bit should deliver coalesced data
- *
- *	Set the receive coalescing size and PSH bit handling.
- */
-static int t3_tp_set_coalescing_size(struct adapter *adap,
-				     unsigned int size, int psh)
-{
-	u32 val;
-
-	if (size > MAX_RX_COALESCING_LEN)
-		return -EINVAL;
-
-	val = t3_read_reg(adap, A_TP_PARA_REG3);
-	val &= ~(F_RXCOALESCEENABLE | F_RXCOALESCEPSHEN);
-
-	if (size) {
-		val |= F_RXCOALESCEENABLE;
-		if (psh)
-			val |= F_RXCOALESCEPSHEN;
-		size = min(MAX_RX_COALESCING_LEN, size);
-		t3_write_reg(adap, A_TP_PARA_REG2, V_RXCOALESCESIZE(size) |
-			     V_MAXRXDATA(MAX_RX_COALESCING_LEN));
-	}
-	t3_write_reg(adap, A_TP_PARA_REG3, val);
-	return 0;
-}
-
-/**
- *	t3_tp_set_max_rxsize - set the max receive size
- *	@adap: the adapter
- *	@size: the max receive size
- *
- *	Set TP's max receive size.  This is the limit that applies when
- *	receive coalescing is disabled.
- */
-static void t3_tp_set_max_rxsize(struct adapter *adap, unsigned int size)
-{
-	t3_write_reg(adap, A_TP_PARA_REG7,
-		     V_PMMAXXFERLEN0(size) | V_PMMAXXFERLEN1(size));
-}
-
-static void init_mtus(unsigned short mtus[])
-{
-	/*
-	 * See draft-mathis-plpmtud-00.txt for the values.  The min is 88 so
-	 * 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;
-	mtus[1] = 88;
-	mtus[2] = 256;
-	mtus[3] = 512;
-	mtus[4] = 576;
-	mtus[5] = 1024;
-	mtus[6] = 1280;
-	mtus[7] = 1492;
-	mtus[8] = 1500;
-	mtus[9] = 2002;
-	mtus[10] = 2048;
-	mtus[11] = 4096;
-	mtus[12] = 4352;
-	mtus[13] = 8192;
-	mtus[14] = 9000;
-	mtus[15] = 9600;
-}
-
-/*
- * Initial congestion control parameters.
- */
-static void init_cong_ctrl(unsigned short *a, unsigned short *b)
-{
-	a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = a[8] = 1;
-	a[9] = 2;
-	a[10] = 3;
-	a[11] = 4;
-	a[12] = 5;
-	a[13] = 6;
-	a[14] = 7;
-	a[15] = 8;
-	a[16] = 9;
-	a[17] = 10;
-	a[18] = 14;
-	a[19] = 17;
-	a[20] = 21;
-	a[21] = 25;
-	a[22] = 30;
-	a[23] = 35;
-	a[24] = 45;
-	a[25] = 60;
-	a[26] = 80;
-	a[27] = 100;
-	a[28] = 200;
-	a[29] = 300;
-	a[30] = 400;
-	a[31] = 500;
-
-	b[0] = b[1] = b[2] = b[3] = b[4] = b[5] = b[6] = b[7] = b[8] = 0;
-	b[9] = b[10] = 1;
-	b[11] = b[12] = 2;
-	b[13] = b[14] = b[15] = b[16] = 3;
-	b[17] = b[18] = b[19] = b[20] = b[21] = 4;
-	b[22] = b[23] = b[24] = b[25] = b[26] = b[27] = 5;
-	b[28] = b[29] = 6;
-	b[30] = b[31] = 7;
-}
-
-/* The minimum additive increment value for the congestion control table */
-#define CC_MIN_INCR 2U
-
-/**
- *	t3_load_mtus - write the MTU and congestion control HW tables
- *	@adap: the adapter
- *	@mtus: the unrestricted values for the MTU table
- *	@alphs: the values for the congestion control alpha parameter
- *	@beta: the values for the congestion control beta parameter
- *	@mtu_cap: the maximum permitted effective MTU
- *
- *	Write the MTU table with the supplied MTUs capping each at &mtu_cap.
- *	Update the high-speed congestion control table with the supplied alpha,
- * 	beta, and MTUs.
- */
-void t3_load_mtus(struct adapter *adap, unsigned short mtus[NMTUS],
-		  unsigned short alpha[NCCTRL_WIN],
-		  unsigned short beta[NCCTRL_WIN], unsigned short mtu_cap)
-{
-	static const unsigned int avg_pkts[NCCTRL_WIN] = {
-		2, 6, 10, 14, 20, 28, 40, 56, 80, 112, 160, 224, 320, 448, 640,
-		896, 1281, 1792, 2560, 3584, 5120, 7168, 10240, 14336, 20480,
-		28672, 40960, 57344, 81920, 114688, 163840, 229376
-	};
-
-	unsigned int i, w;
-
-	for (i = 0; i < NMTUS; ++i) {
-		unsigned int mtu = min(mtus[i], mtu_cap);
-		unsigned int log2 = fls(mtu);
-
-		if (!(mtu & ((1 << log2) >> 2)))	/* round */
-			log2--;
-		t3_write_reg(adap, A_TP_MTU_TABLE,
-			     (i << 24) | (log2 << 16) | mtu);
-
-		for (w = 0; w < NCCTRL_WIN; ++w) {
-			unsigned int inc;
-
-			inc = max(((mtu - 40) * alpha[w]) / avg_pkts[w],
-				  CC_MIN_INCR);
-
-			t3_write_reg(adap, A_TP_CCTRL_TABLE, (i << 21) |
-				     (w << 16) | (beta[w] << 13) | inc);
-		}
-	}
-}
-
-/**
- *	t3_tp_get_mib_stats - read TP's MIB counters
- *	@adap: the adapter
- *	@tps: holds the returned counter values
- *
- *	Returns the values of TP's MIB counters.
- */
-void t3_tp_get_mib_stats(struct adapter *adap, struct tp_mib_stats *tps)
-{
-	t3_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_RDATA, (u32 *) tps,
-			 sizeof(*tps) / sizeof(u32), 0);
-}
-
-#define ulp_region(adap, name, start, len) \
-	t3_write_reg((adap), A_ULPRX_ ## name ## _LLIMIT, (start)); \
-	t3_write_reg((adap), A_ULPRX_ ## name ## _ULIMIT, \
-		     (start) + (len) - 1); \
-	start += len
-
-#define ulptx_region(adap, name, start, len) \
-	t3_write_reg((adap), A_ULPTX_ ## name ## _LLIMIT, (start)); \
-	t3_write_reg((adap), A_ULPTX_ ## name ## _ULIMIT, \
-		     (start) + (len) - 1)
-
-static void ulp_config(struct adapter *adap, const struct tp_params *p)
-{
-	unsigned int m = p->chan_rx_size;
-
-	ulp_region(adap, ISCSI, m, p->chan_rx_size / 8);
-	ulp_region(adap, TDDP, m, p->chan_rx_size / 8);
-	ulptx_region(adap, TPT, m, p->chan_rx_size / 4);
-	ulp_region(adap, STAG, m, p->chan_rx_size / 4);
-	ulp_region(adap, RQ, m, p->chan_rx_size / 4);
-	ulptx_region(adap, PBL, m, p->chan_rx_size / 4);
-	ulp_region(adap, PBL, m, p->chan_rx_size / 4);
-	t3_write_reg(adap, A_ULPRX_TDDP_TAGMASK, 0xffffffff);
-}
-
-/**
- *	t3_set_proto_sram - set the contents of the protocol sram
- *	@adapter: the adapter
- *	@data: the protocol image
- *
- *	Write the contents of the protocol SRAM.
- */
-int t3_set_proto_sram(struct adapter *adap, const u8 *data)
-{
-	int i;
-	const __be32 *buf = (const __be32 *)data;
-
-	for (i = 0; i < PROTO_SRAM_LINES; i++) {
-		t3_write_reg(adap, A_TP_EMBED_OP_FIELD5, be32_to_cpu(*buf++));
-		t3_write_reg(adap, A_TP_EMBED_OP_FIELD4, be32_to_cpu(*buf++));
-		t3_write_reg(adap, A_TP_EMBED_OP_FIELD3, be32_to_cpu(*buf++));
-		t3_write_reg(adap, A_TP_EMBED_OP_FIELD2, be32_to_cpu(*buf++));
-		t3_write_reg(adap, A_TP_EMBED_OP_FIELD1, be32_to_cpu(*buf++));
-
-		t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, i << 1 | 1 << 31);
-		if (t3_wait_op_done(adap, A_TP_EMBED_OP_FIELD0, 1, 1, 5, 1))
-			return -EIO;
-	}
-	t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, 0);
-
-	return 0;
-}
-
-void t3_config_trace_filter(struct adapter *adapter,
-			    const struct trace_params *tp, int filter_index,
-			    int invert, int enable)
-{
-	u32 addr, key[4], mask[4];
-
-	key[0] = tp->sport | (tp->sip << 16);
-	key[1] = (tp->sip >> 16) | (tp->dport << 16);
-	key[2] = tp->dip;
-	key[3] = tp->proto | (tp->vlan << 8) | (tp->intf << 20);
-
-	mask[0] = tp->sport_mask | (tp->sip_mask << 16);
-	mask[1] = (tp->sip_mask >> 16) | (tp->dport_mask << 16);
-	mask[2] = tp->dip_mask;
-	mask[3] = tp->proto_mask | (tp->vlan_mask << 8) | (tp->intf_mask << 20);
-
-	if (invert)
-		key[3] |= (1 << 29);
-	if (enable)
-		key[3] |= (1 << 28);
-
-	addr = filter_index ? A_TP_RX_TRC_KEY0 : A_TP_TX_TRC_KEY0;
-	tp_wr_indirect(adapter, addr++, key[0]);
-	tp_wr_indirect(adapter, addr++, mask[0]);
-	tp_wr_indirect(adapter, addr++, key[1]);
-	tp_wr_indirect(adapter, addr++, mask[1]);
-	tp_wr_indirect(adapter, addr++, key[2]);
-	tp_wr_indirect(adapter, addr++, mask[2]);
-	tp_wr_indirect(adapter, addr++, key[3]);
-	tp_wr_indirect(adapter, addr, mask[3]);
-	t3_read_reg(adapter, A_TP_PIO_DATA);
-}
-
-/**
- *	t3_config_sched - configure a HW traffic scheduler
- *	@adap: the adapter
- *	@kbps: target rate in Kbps
- *	@sched: the scheduler index
- *
- *	Configure a HW scheduler for the target rate
- */
-int t3_config_sched(struct adapter *adap, unsigned int kbps, int sched)
-{
-	unsigned int v, tps, cpt, bpt, delta, mindelta = ~0;
-	unsigned int clk = adap->params.vpd.cclk * 1000;
-	unsigned int selected_cpt = 0, selected_bpt = 0;
-
-	if (kbps > 0) {
-		kbps *= 125;	/* -> bytes */
-		for (cpt = 1; cpt <= 255; cpt++) {
-			tps = clk / cpt;
-			bpt = (kbps + tps / 2) / tps;
-			if (bpt > 0 && bpt <= 255) {
-				v = bpt * tps;
-				delta = v >= kbps ? v - kbps : kbps - v;
-				if (delta <= mindelta) {
-					mindelta = delta;
-					selected_cpt = cpt;
-					selected_bpt = bpt;
-				}
-			} else if (selected_cpt)
-				break;
-		}
-		if (!selected_cpt)
-			return -EINVAL;
-	}
-	t3_write_reg(adap, A_TP_TM_PIO_ADDR,
-		     A_TP_TX_MOD_Q1_Q0_RATE_LIMIT - sched / 2);
-	v = t3_read_reg(adap, A_TP_TM_PIO_DATA);
-	if (sched & 1)
-		v = (v & 0xffff) | (selected_cpt << 16) | (selected_bpt << 24);
-	else
-		v = (v & 0xffff0000) | selected_cpt | (selected_bpt << 8);
-	t3_write_reg(adap, A_TP_TM_PIO_DATA, v);
-	return 0;
-}
-
-static int tp_init(struct adapter *adap, const struct tp_params *p)
-{
-	int busy = 0;
-
-	tp_config(adap, p);
-	t3_set_vlan_accel(adap, 3, 0);
-
-	if (is_offload(adap)) {
-		tp_set_timers(adap, adap->params.vpd.cclk * 1000);
-		t3_write_reg(adap, A_TP_RESET, F_FLSTINITENABLE);
-		busy = t3_wait_op_done(adap, A_TP_RESET, F_FLSTINITENABLE,
-				       0, 1000, 5);
-		if (busy)
-			CH_ERR(adap, "TP initialization timed out\n");
-	}
-
-	if (!busy)
-		t3_write_reg(adap, A_TP_RESET, F_TPRESET);
-	return busy;
-}
-
-/*
- * Perform the bits of HW initialization that are dependent on the Tx
- * channels being used.
- */
-static void chan_init_hw(struct adapter *adap, unsigned int chan_map)
-{
-	int i;
-
-	if (chan_map != 3) {                                 /* one channel */
-		t3_set_reg_field(adap, A_ULPRX_CTL, F_ROUND_ROBIN, 0);
-		t3_set_reg_field(adap, A_ULPTX_CONFIG, F_CFG_RR_ARB, 0);
-		t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_ENFORCEPKT |
-			     (chan_map == 1 ? F_TPTXPORT0EN | F_PORT0ACTIVE :
-					      F_TPTXPORT1EN | F_PORT1ACTIVE));
-		t3_write_reg(adap, A_PM1_TX_CFG,
-			     chan_map == 1 ? 0xffffffff : 0);
-	} else {                                             /* two channels */
-		t3_set_reg_field(adap, A_ULPRX_CTL, 0, F_ROUND_ROBIN);
-		t3_set_reg_field(adap, A_ULPTX_CONFIG, 0, F_CFG_RR_ARB);
-		t3_write_reg(adap, A_ULPTX_DMA_WEIGHT,
-			     V_D1_WEIGHT(16) | V_D0_WEIGHT(16));
-		t3_write_reg(adap, A_MPS_CFG, F_TPTXPORT0EN | F_TPTXPORT1EN |
-			     F_TPRXPORTEN | F_PORT0ACTIVE | F_PORT1ACTIVE |
-			     F_ENFORCEPKT);
-		t3_write_reg(adap, A_PM1_TX_CFG, 0x80008000);
-		t3_set_reg_field(adap, A_TP_PC_CONFIG, 0, F_TXTOSQUEUEMAPMODE);
-		t3_write_reg(adap, A_TP_TX_MOD_QUEUE_REQ_MAP,
-			     V_TX_MOD_QUEUE_REQ_MAP(0xaa));
-		for (i = 0; i < 16; i++)
-			t3_write_reg(adap, A_TP_TX_MOD_QUE_TABLE,
-				     (i << 16) | 0x1010);
-	}
-}
-
-static int calibrate_xgm(struct adapter *adapter)
-{
-	if (uses_xaui(adapter)) {
-		unsigned int v, i;
-
-		for (i = 0; i < 5; ++i) {
-			t3_write_reg(adapter, A_XGM_XAUI_IMP, 0);
-			t3_read_reg(adapter, A_XGM_XAUI_IMP);
-			msleep(1);
-			v = t3_read_reg(adapter, A_XGM_XAUI_IMP);
-			if (!(v & (F_XGM_CALFAULT | F_CALBUSY))) {
-				t3_write_reg(adapter, A_XGM_XAUI_IMP,
-					     V_XAUIIMP(G_CALIMP(v) >> 2));
-				return 0;
-			}
-		}
-		CH_ERR(adapter, "MAC calibration failed\n");
-		return -1;
-	} else {
-		t3_write_reg(adapter, A_XGM_RGMII_IMP,
-			     V_RGMIIIMPPD(2) | V_RGMIIIMPPU(3));
-		t3_set_reg_field(adapter, A_XGM_RGMII_IMP, F_XGM_IMPSETUPDATE,
-				 F_XGM_IMPSETUPDATE);
-	}
-	return 0;
-}
-
-static void calibrate_xgm_t3b(struct adapter *adapter)
-{
-	if (!uses_xaui(adapter)) {
-		t3_write_reg(adapter, A_XGM_RGMII_IMP, F_CALRESET |
-			     F_CALUPDATE | V_RGMIIIMPPD(2) | V_RGMIIIMPPU(3));
-		t3_set_reg_field(adapter, A_XGM_RGMII_IMP, F_CALRESET, 0);
-		t3_set_reg_field(adapter, A_XGM_RGMII_IMP, 0,
-				 F_XGM_IMPSETUPDATE);
-		t3_set_reg_field(adapter, A_XGM_RGMII_IMP, F_XGM_IMPSETUPDATE,
-				 0);
-		t3_set_reg_field(adapter, A_XGM_RGMII_IMP, F_CALUPDATE, 0);
-		t3_set_reg_field(adapter, A_XGM_RGMII_IMP, 0, F_CALUPDATE);
-	}
-}
-
-struct mc7_timing_params {
-	unsigned char ActToPreDly;
-	unsigned char ActToRdWrDly;
-	unsigned char PreCyc;
-	unsigned char RefCyc[5];
-	unsigned char BkCyc;
-	unsigned char WrToRdDly;
-	unsigned char RdToWrDly;
-};
-
-/*
- * Write a value to a register and check that the write completed.  These
- * writes normally complete in a cycle or two, so one read should suffice.
- * The very first read exists to flush the posted write to the device.
- */
-static int wrreg_wait(struct adapter *adapter, unsigned int addr, u32 val)
-{
-	t3_write_reg(adapter, addr, val);
-	t3_read_reg(adapter, addr);	/* flush */
-	if (!(t3_read_reg(adapter, addr) & F_BUSY))
-		return 0;
-	CH_ERR(adapter, "write to MC7 register 0x%x timed out\n", addr);
-	return -EIO;
-}
-
-static int mc7_init(struct mc7 *mc7, unsigned int mc7_clock, int mem_type)
-{
-	static const unsigned int mc7_mode[] = {
-		0x632, 0x642, 0x652, 0x432, 0x442
-	};
-	static const struct mc7_timing_params mc7_timings[] = {
-		{12, 3, 4, {20, 28, 34, 52, 0}, 15, 6, 4},
-		{12, 4, 5, {20, 28, 34, 52, 0}, 16, 7, 4},
-		{12, 5, 6, {20, 28, 34, 52, 0}, 17, 8, 4},
-		{9, 3, 4, {15, 21, 26, 39, 0}, 12, 6, 4},
-		{9, 4, 5, {15, 21, 26, 39, 0}, 13, 7, 4}
-	};
-
-	u32 val;
-	unsigned int width, density, slow, attempts;
-	struct adapter *adapter = mc7->adapter;
-	const struct mc7_timing_params *p = &mc7_timings[mem_type];
-
-	if (!mc7->size)
-		return 0;
-
-	val = t3_read_reg(adapter, mc7->offset + A_MC7_CFG);
-	slow = val & F_SLOW;
-	width = G_WIDTH(val);
-	density = G_DEN(val);
-
-	t3_write_reg(adapter, mc7->offset + A_MC7_CFG, val | F_IFEN);
-	val = t3_read_reg(adapter, mc7->offset + A_MC7_CFG);	/* flush */
-	msleep(1);
-
-	if (!slow) {
-		t3_write_reg(adapter, mc7->offset + A_MC7_CAL, F_SGL_CAL_EN);
-		t3_read_reg(adapter, mc7->offset + A_MC7_CAL);
-		msleep(1);
-		if (t3_read_reg(adapter, mc7->offset + A_MC7_CAL) &
-		    (F_BUSY | F_SGL_CAL_EN | F_CAL_FAULT)) {
-			CH_ERR(adapter, "%s MC7 calibration timed out\n",
-			       mc7->name);
-			goto out_fail;
-		}
-	}
-
-	t3_write_reg(adapter, mc7->offset + A_MC7_PARM,
-		     V_ACTTOPREDLY(p->ActToPreDly) |
-		     V_ACTTORDWRDLY(p->ActToRdWrDly) | V_PRECYC(p->PreCyc) |
-		     V_REFCYC(p->RefCyc[density]) | V_BKCYC(p->BkCyc) |
-		     V_WRTORDDLY(p->WrToRdDly) | V_RDTOWRDLY(p->RdToWrDly));
-
-	t3_write_reg(adapter, mc7->offset + A_MC7_CFG,
-		     val | F_CLKEN | F_TERM150);
-	t3_read_reg(adapter, mc7->offset + A_MC7_CFG);	/* flush */
-
-	if (!slow)
-		t3_set_reg_field(adapter, mc7->offset + A_MC7_DLL, F_DLLENB,
-				 F_DLLENB);
-	udelay(1);
-
-	val = slow ? 3 : 6;
-	if (wrreg_wait(adapter, mc7->offset + A_MC7_PRE, 0) ||
-	    wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE2, 0) ||
-	    wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE3, 0) ||
-	    wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE1, val))
-		goto out_fail;
-
-	if (!slow) {
-		t3_write_reg(adapter, mc7->offset + A_MC7_MODE, 0x100);
-		t3_set_reg_field(adapter, mc7->offset + A_MC7_DLL, F_DLLRST, 0);
-		udelay(5);
-	}
-
-	if (wrreg_wait(adapter, mc7->offset + A_MC7_PRE, 0) ||
-	    wrreg_wait(adapter, mc7->offset + A_MC7_REF, 0) ||
-	    wrreg_wait(adapter, mc7->offset + A_MC7_REF, 0) ||
-	    wrreg_wait(adapter, mc7->offset + A_MC7_MODE,
-		       mc7_mode[mem_type]) ||
-	    wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE1, val | 0x380) ||
-	    wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE1, val))
-		goto out_fail;
-
-	/* clock value is in KHz */
-	mc7_clock = mc7_clock * 7812 + mc7_clock / 2;	/* ns */
-	mc7_clock /= 1000000;	/* KHz->MHz, ns->us */
-
-	t3_write_reg(adapter, mc7->offset + A_MC7_REF,
-		     F_PERREFEN | V_PREREFDIV(mc7_clock));
-	t3_read_reg(adapter, mc7->offset + A_MC7_REF);	/* flush */
-
-	t3_write_reg(adapter, mc7->offset + A_MC7_ECC, F_ECCGENEN | F_ECCCHKEN);
-	t3_write_reg(adapter, mc7->offset + A_MC7_BIST_DATA, 0);
-	t3_write_reg(adapter, mc7->offset + A_MC7_BIST_ADDR_BEG, 0);
-	t3_write_reg(adapter, mc7->offset + A_MC7_BIST_ADDR_END,
-		     (mc7->size << width) - 1);
-	t3_write_reg(adapter, mc7->offset + A_MC7_BIST_OP, V_OP(1));
-	t3_read_reg(adapter, mc7->offset + A_MC7_BIST_OP);	/* flush */
-
-	attempts = 50;
-	do {
-		msleep(250);
-		val = t3_read_reg(adapter, mc7->offset + A_MC7_BIST_OP);
-	} while ((val & F_BUSY) && --attempts);
-	if (val & F_BUSY) {
-		CH_ERR(adapter, "%s MC7 BIST timed out\n", mc7->name);
-		goto out_fail;
-	}
-
-	/* Enable normal memory accesses. */
-	t3_set_reg_field(adapter, mc7->offset + A_MC7_CFG, 0, F_RDY);
-	return 0;
-
-out_fail:
-	return -1;
-}
-
-static void config_pcie(struct adapter *adap)
-{
-	static const u16 ack_lat[4][6] = {
-		{237, 416, 559, 1071, 2095, 4143},
-		{128, 217, 289, 545, 1057, 2081},
-		{73, 118, 154, 282, 538, 1050},
-		{67, 107, 86, 150, 278, 534}
-	};
-	static const u16 rpl_tmr[4][6] = {
-		{711, 1248, 1677, 3213, 6285, 12429},
-		{384, 651, 867, 1635, 3171, 6243},
-		{219, 354, 462, 846, 1614, 3150},
-		{201, 321, 258, 450, 834, 1602}
-	};
-
-	u16 val, devid;
-	unsigned int log2_width, pldsize;
-	unsigned int fst_trn_rx, fst_trn_tx, acklat, rpllmt;
-
-	pci_read_config_word(adap->pdev,
-			     adap->pdev->pcie_cap + PCI_EXP_DEVCTL,
-			     &val);
-	pldsize = (val & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
-
-	pci_read_config_word(adap->pdev, 0x2, &devid);
-	if (devid == 0x37) {
-		pci_write_config_word(adap->pdev,
-				      adap->pdev->pcie_cap + PCI_EXP_DEVCTL,
-				      val & ~PCI_EXP_DEVCTL_READRQ &
-				      ~PCI_EXP_DEVCTL_PAYLOAD);
-		pldsize = 0;
-	}
-
-	pci_read_config_word(adap->pdev, adap->pdev->pcie_cap + PCI_EXP_LNKCTL,
-			     &val);
-
-	fst_trn_tx = G_NUMFSTTRNSEQ(t3_read_reg(adap, A_PCIE_PEX_CTRL0));
-	fst_trn_rx = adap->params.rev == 0 ? fst_trn_tx :
-	    G_NUMFSTTRNSEQRX(t3_read_reg(adap, A_PCIE_MODE));
-	log2_width = fls(adap->params.pci.width) - 1;
-	acklat = ack_lat[log2_width][pldsize];
-	if (val & 1)		/* check LOsEnable */
-		acklat += fst_trn_tx * 4;
-	rpllmt = rpl_tmr[log2_width][pldsize] + fst_trn_rx * 4;
-
-	if (adap->params.rev == 0)
-		t3_set_reg_field(adap, A_PCIE_PEX_CTRL1,
-				 V_T3A_ACKLAT(M_T3A_ACKLAT),
-				 V_T3A_ACKLAT(acklat));
-	else
-		t3_set_reg_field(adap, A_PCIE_PEX_CTRL1, V_ACKLAT(M_ACKLAT),
-				 V_ACKLAT(acklat));
-
-	t3_set_reg_field(adap, A_PCIE_PEX_CTRL0, V_REPLAYLMT(M_REPLAYLMT),
-			 V_REPLAYLMT(rpllmt));
-
-	t3_write_reg(adap, A_PCIE_PEX_ERR, 0xffffffff);
-	t3_set_reg_field(adap, A_PCIE_CFG, 0,
-			 F_ENABLELINKDWNDRST | F_ENABLELINKDOWNRST |
-			 F_PCIE_DMASTOPEN | F_PCIE_CLIDECEN);
-}
-
-/*
- * Initialize and configure T3 HW modules.  This performs the
- * initialization steps that need to be done once after a card is reset.
- * MAC and PHY initialization is handled separarely whenever a port is enabled.
- *
- * fw_params are passed to FW and their value is platform dependent.  Only the
- * top 8 bits are available for use, the rest must be 0.
- */
-int t3_init_hw(struct adapter *adapter, u32 fw_params)
-{
-	int err = -EIO, attempts, i;
-	const struct vpd_params *vpd = &adapter->params.vpd;
-
-	if (adapter->params.rev > 0)
-		calibrate_xgm_t3b(adapter);
-	else if (calibrate_xgm(adapter))
-		goto out_err;
-
-	if (vpd->mclk) {
-		partition_mem(adapter, &adapter->params.tp);
-
-		if (mc7_init(&adapter->pmrx, vpd->mclk, vpd->mem_timing) ||
-		    mc7_init(&adapter->pmtx, vpd->mclk, vpd->mem_timing) ||
-		    mc7_init(&adapter->cm, vpd->mclk, vpd->mem_timing) ||
-		    t3_mc5_init(&adapter->mc5, adapter->params.mc5.nservers,
-				adapter->params.mc5.nfilters,
-				adapter->params.mc5.nroutes))
-			goto out_err;
-
-		for (i = 0; i < 32; i++)
-			if (clear_sge_ctxt(adapter, i, F_CQ))
-				goto out_err;
-	}
-
-	if (tp_init(adapter, &adapter->params.tp))
-		goto out_err;
-
-	t3_tp_set_coalescing_size(adapter,
-				  min(adapter->params.sge.max_pkt_size,
-				      MAX_RX_COALESCING_LEN), 1);
-	t3_tp_set_max_rxsize(adapter,
-			     min(adapter->params.sge.max_pkt_size, 16384U));
-	ulp_config(adapter, &adapter->params.tp);
-
-	if (is_pcie(adapter))
-		config_pcie(adapter);
-	else
-		t3_set_reg_field(adapter, A_PCIX_CFG, 0,
-				 F_DMASTOPEN | F_CLIDECEN);
-
-	if (adapter->params.rev == T3_REV_C)
-		t3_set_reg_field(adapter, A_ULPTX_CONFIG, 0,
-				 F_CFG_CQE_SOP_MASK);
-
-	t3_write_reg(adapter, A_PM1_RX_CFG, 0xffffffff);
-	t3_write_reg(adapter, A_PM1_RX_MODE, 0);
-	t3_write_reg(adapter, A_PM1_TX_MODE, 0);
-	chan_init_hw(adapter, adapter->params.chan_map);
-	t3_sge_init(adapter, &adapter->params.sge);
-	t3_set_reg_field(adapter, A_PL_RST, 0, F_FATALPERREN);
-
-	t3_write_reg(adapter, A_T3DBG_GPIO_ACT_LOW, calc_gpio_intr(adapter));
-
-	t3_write_reg(adapter, A_CIM_HOST_ACC_DATA, vpd->uclk | fw_params);
-	t3_write_reg(adapter, A_CIM_BOOT_CFG,
-		     V_BOOTADDR(FW_FLASH_BOOT_ADDR >> 2));
-	t3_read_reg(adapter, A_CIM_BOOT_CFG);	/* flush */
-
-	attempts = 100;
-	do {			/* wait for uP to initialize */
-		msleep(20);
-	} while (t3_read_reg(adapter, A_CIM_HOST_ACC_DATA) && --attempts);
-	if (!attempts) {
-		CH_ERR(adapter, "uP initialization timed out\n");
-		goto out_err;
-	}
-
-	err = 0;
-out_err:
-	return err;
-}
-
-/**
- *	get_pci_mode - determine a card's PCI mode
- *	@adapter: the adapter
- *	@p: where to store the PCI settings
- *
- *	Determines a card's PCI mode and associated parameters, such as speed
- *	and width.
- */
-static void get_pci_mode(struct adapter *adapter, struct pci_params *p)
-{
-	static unsigned short speed_map[] = { 33, 66, 100, 133 };
-	u32 pci_mode, pcie_cap;
-
-	pcie_cap = pci_pcie_cap(adapter->pdev);
-	if (pcie_cap) {
-		u16 val;
-
-		p->variant = PCI_VARIANT_PCIE;
-		pci_read_config_word(adapter->pdev, pcie_cap + PCI_EXP_LNKSTA,
-					&val);
-		p->width = (val >> 4) & 0x3f;
-		return;
-	}
-
-	pci_mode = t3_read_reg(adapter, A_PCIX_MODE);
-	p->speed = speed_map[G_PCLKRANGE(pci_mode)];
-	p->width = (pci_mode & F_64BIT) ? 64 : 32;
-	pci_mode = G_PCIXINITPAT(pci_mode);
-	if (pci_mode == 0)
-		p->variant = PCI_VARIANT_PCI;
-	else if (pci_mode < 4)
-		p->variant = PCI_VARIANT_PCIX_MODE1_PARITY;
-	else if (pci_mode < 8)
-		p->variant = PCI_VARIANT_PCIX_MODE1_ECC;
-	else
-		p->variant = PCI_VARIANT_PCIX_266_MODE2;
-}
-
-/**
- *	init_link_config - initialize a link's SW state
- *	@lc: structure holding the link state
- *	@ai: information about the current card
- *
- *	Initializes the SW state maintained for each link, including the link's
- *	capabilities and default speed/duplex/flow-control/autonegotiation
- *	settings.
- */
-static void init_link_config(struct link_config *lc, unsigned int caps)
-{
-	lc->supported = caps;
-	lc->requested_speed = lc->speed = SPEED_INVALID;
-	lc->requested_duplex = lc->duplex = DUPLEX_INVALID;
-	lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX;
-	if (lc->supported & SUPPORTED_Autoneg) {
-		lc->advertising = lc->supported;
-		lc->autoneg = AUTONEG_ENABLE;
-		lc->requested_fc |= PAUSE_AUTONEG;
-	} else {
-		lc->advertising = 0;
-		lc->autoneg = AUTONEG_DISABLE;
-	}
-}
-
-/**
- *	mc7_calc_size - calculate MC7 memory size
- *	@cfg: the MC7 configuration
- *
- *	Calculates the size of an MC7 memory in bytes from the value of its
- *	configuration register.
- */
-static unsigned int mc7_calc_size(u32 cfg)
-{
-	unsigned int width = G_WIDTH(cfg);
-	unsigned int banks = !!(cfg & F_BKS) + 1;
-	unsigned int org = !!(cfg & F_ORG) + 1;
-	unsigned int density = G_DEN(cfg);
-	unsigned int MBs = ((256 << density) * banks) / (org << width);
-
-	return MBs << 20;
-}
-
-static void mc7_prep(struct adapter *adapter, struct mc7 *mc7,
-		     unsigned int base_addr, const char *name)
-{
-	u32 cfg;
-
-	mc7->adapter = adapter;
-	mc7->name = name;
-	mc7->offset = base_addr - MC7_PMRX_BASE_ADDR;
-	cfg = t3_read_reg(adapter, mc7->offset + A_MC7_CFG);
-	mc7->size = G_DEN(cfg) == M_DEN ? 0 : mc7_calc_size(cfg);
-	mc7->width = G_WIDTH(cfg);
-}
-
-static void mac_prep(struct cmac *mac, struct adapter *adapter, int index)
-{
-	u16 devid;
-
-	mac->adapter = adapter;
-	pci_read_config_word(adapter->pdev, 0x2, &devid);
-
-	if (devid == 0x37 && !adapter->params.vpd.xauicfg[1])
-		index = 0;
-	mac->offset = (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR) * index;
-	mac->nucast = 1;
-
-	if (adapter->params.rev == 0 && uses_xaui(adapter)) {
-		t3_write_reg(adapter, A_XGM_SERDES_CTRL + mac->offset,
-			     is_10G(adapter) ? 0x2901c04 : 0x2301c04);
-		t3_set_reg_field(adapter, A_XGM_PORT_CFG + mac->offset,
-				 F_ENRGMII, 0);
-	}
-}
-
-static void early_hw_init(struct adapter *adapter,
-			  const struct adapter_info *ai)
-{
-	u32 val = V_PORTSPEED(is_10G(adapter) ? 3 : 2);
-
-	mi1_init(adapter, ai);
-	t3_write_reg(adapter, A_I2C_CFG,	/* set for 80KHz */
-		     V_I2C_CLKDIV(adapter->params.vpd.cclk / 80 - 1));
-	t3_write_reg(adapter, A_T3DBG_GPIO_EN,
-		     ai->gpio_out | F_GPIO0_OEN | F_GPIO0_OUT_VAL);
-	t3_write_reg(adapter, A_MC5_DB_SERVER_INDEX, 0);
-	t3_write_reg(adapter, A_SG_OCO_BASE, V_BASE1(0xfff));
-
-	if (adapter->params.rev == 0 || !uses_xaui(adapter))
-		val |= F_ENRGMII;
-
-	/* Enable MAC clocks so we can access the registers */
-	t3_write_reg(adapter, A_XGM_PORT_CFG, val);
-	t3_read_reg(adapter, A_XGM_PORT_CFG);
-
-	val |= F_CLKDIVRESET_;
-	t3_write_reg(adapter, A_XGM_PORT_CFG, val);
-	t3_read_reg(adapter, A_XGM_PORT_CFG);
-	t3_write_reg(adapter, XGM_REG(A_XGM_PORT_CFG, 1), val);
-	t3_read_reg(adapter, A_XGM_PORT_CFG);
-}
-
-/*
- * Reset the adapter.
- * Older PCIe cards lose their config space during reset, PCI-X
- * ones don't.
- */
-int t3_reset_adapter(struct adapter *adapter)
-{
-	int i, save_and_restore_pcie =
-	    adapter->params.rev < T3_REV_B2 && is_pcie(adapter);
-	uint16_t devid = 0;
-
-	if (save_and_restore_pcie)
-		pci_save_state(adapter->pdev);
-	t3_write_reg(adapter, A_PL_RST, F_CRSTWRM | F_CRSTWRMMODE);
-
-	/*
-	 * Delay. Give Some time to device to reset fully.
-	 * XXX The delay time should be modified.
-	 */
-	for (i = 0; i < 10; i++) {
-		msleep(50);
-		pci_read_config_word(adapter->pdev, 0x00, &devid);
-		if (devid == 0x1425)
-			break;
-	}
-
-	if (devid != 0x1425)
-		return -1;
-
-	if (save_and_restore_pcie)
-		pci_restore_state(adapter->pdev);
-	return 0;
-}
-
-static int init_parity(struct adapter *adap)
-{
-		int i, err, addr;
-
-	if (t3_read_reg(adap, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
-		return -EBUSY;
-
-	for (err = i = 0; !err && i < 16; i++)
-		err = clear_sge_ctxt(adap, i, F_EGRESS);
-	for (i = 0xfff0; !err && i <= 0xffff; i++)
-		err = clear_sge_ctxt(adap, i, F_EGRESS);
-	for (i = 0; !err && i < SGE_QSETS; i++)
-		err = clear_sge_ctxt(adap, i, F_RESPONSEQ);
-	if (err)
-		return err;
-
-	t3_write_reg(adap, A_CIM_IBQ_DBG_DATA, 0);
-	for (i = 0; i < 4; i++)
-		for (addr = 0; addr <= M_IBQDBGADDR; addr++) {
-			t3_write_reg(adap, A_CIM_IBQ_DBG_CFG, F_IBQDBGEN |
-				     F_IBQDBGWR | V_IBQDBGQID(i) |
-				     V_IBQDBGADDR(addr));
-			err = t3_wait_op_done(adap, A_CIM_IBQ_DBG_CFG,
-					      F_IBQDBGBUSY, 0, 2, 1);
-			if (err)
-				return err;
-		}
-	return 0;
-}
-
-/*
- * Initialize adapter SW state for the various HW modules, set initial values
- * for some adapter tunables, take PHYs out of reset, and initialize the MDIO
- * interface.
- */
-int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
-		    int reset)
-{
-	int ret;
-	unsigned int i, j = -1;
-
-	get_pci_mode(adapter, &adapter->params.pci);
-
-	adapter->params.info = ai;
-	adapter->params.nports = ai->nports0 + ai->nports1;
-	adapter->params.chan_map = (!!ai->nports0) | (!!ai->nports1 << 1);
-	adapter->params.rev = t3_read_reg(adapter, A_PL_REV);
-	/*
-	 * We used to only run the "adapter check task" once a second if
-	 * we had PHYs which didn't support interrupts (we would check
-	 * their link status once a second).  Now we check other conditions
-	 * in that routine which could potentially impose a very high
-	 * interrupt load on the system.  As such, we now always scan the
-	 * adapter state once a second ...
-	 */
-	adapter->params.linkpoll_period = 10;
-	adapter->params.stats_update_period = is_10G(adapter) ?
-	    MAC_STATS_ACCUM_SECS : (MAC_STATS_ACCUM_SECS * 10);
-	adapter->params.pci.vpd_cap_addr =
-	    pci_find_capability(adapter->pdev, PCI_CAP_ID_VPD);
-	ret = get_vpd_params(adapter, &adapter->params.vpd);
-	if (ret < 0)
-		return ret;
-
-	if (reset && t3_reset_adapter(adapter))
-		return -1;
-
-	t3_sge_prep(adapter, &adapter->params.sge);
-
-	if (adapter->params.vpd.mclk) {
-		struct tp_params *p = &adapter->params.tp;
-
-		mc7_prep(adapter, &adapter->pmrx, MC7_PMRX_BASE_ADDR, "PMRX");
-		mc7_prep(adapter, &adapter->pmtx, MC7_PMTX_BASE_ADDR, "PMTX");
-		mc7_prep(adapter, &adapter->cm, MC7_CM_BASE_ADDR, "CM");
-
-		p->nchan = adapter->params.chan_map == 3 ? 2 : 1;
-		p->pmrx_size = t3_mc7_size(&adapter->pmrx);
-		p->pmtx_size = t3_mc7_size(&adapter->pmtx);
-		p->cm_size = t3_mc7_size(&adapter->cm);
-		p->chan_rx_size = p->pmrx_size / 2;	/* only 1 Rx channel */
-		p->chan_tx_size = p->pmtx_size / p->nchan;
-		p->rx_pg_size = 64 * 1024;
-		p->tx_pg_size = is_10G(adapter) ? 64 * 1024 : 16 * 1024;
-		p->rx_num_pgs = pm_num_pages(p->chan_rx_size, p->rx_pg_size);
-		p->tx_num_pgs = pm_num_pages(p->chan_tx_size, p->tx_pg_size);
-		p->ntimer_qs = p->cm_size >= (128 << 20) ||
-		    adapter->params.rev > 0 ? 12 : 6;
-	}
-
-	adapter->params.offload = t3_mc7_size(&adapter->pmrx) &&
-				  t3_mc7_size(&adapter->pmtx) &&
-				  t3_mc7_size(&adapter->cm);
-
-	if (is_offload(adapter)) {
-		adapter->params.mc5.nservers = DEFAULT_NSERVERS;
-		adapter->params.mc5.nfilters = adapter->params.rev > 0 ?
-		    DEFAULT_NFILTERS : 0;
-		adapter->params.mc5.nroutes = 0;
-		t3_mc5_prep(adapter, &adapter->mc5, MC5_MODE_144_BIT);
-
-		init_mtus(adapter->params.mtus);
-		init_cong_ctrl(adapter->params.a_wnd, adapter->params.b_wnd);
-	}
-
-	early_hw_init(adapter, ai);
-	ret = init_parity(adapter);
-	if (ret)
-		return ret;
-
-	for_each_port(adapter, i) {
-		u8 hw_addr[6];
-		const struct port_type_info *pti;
-		struct port_info *p = adap2pinfo(adapter, i);
-
-		while (!adapter->params.vpd.port_type[++j])
-			;
-
-		pti = &port_types[adapter->params.vpd.port_type[j]];
-		if (!pti->phy_prep) {
-			CH_ALERT(adapter, "Invalid port type index %d\n",
-				 adapter->params.vpd.port_type[j]);
-			return -EINVAL;
-		}
-
-		p->phy.mdio.dev = adapter->port[i];
-		ret = pti->phy_prep(&p->phy, adapter, ai->phy_base_addr + j,
-				    ai->mdio_ops);
-		if (ret)
-			return ret;
-		mac_prep(&p->mac, adapter, j);
-
-		/*
-		 * The VPD EEPROM stores the base Ethernet address for the
-		 * card.  A port's address is derived from the base by adding
-		 * the port's index to the base's low octet.
-		 */
-		memcpy(hw_addr, adapter->params.vpd.eth_base, 5);
-		hw_addr[5] = adapter->params.vpd.eth_base[5] + i;
-
-		memcpy(adapter->port[i]->dev_addr, hw_addr,
-		       ETH_ALEN);
-		memcpy(adapter->port[i]->perm_addr, hw_addr,
-		       ETH_ALEN);
-		init_link_config(&p->link_config, p->phy.caps);
-		p->phy.ops->power_down(&p->phy, 1);
-
-		/*
-		 * If the PHY doesn't support interrupts for link status
-		 * changes, schedule a scan of the adapter links at least
-		 * once a second.
-		 */
-		if (!(p->phy.caps & SUPPORTED_IRQ) &&
-		    adapter->params.linkpoll_period > 10)
-			adapter->params.linkpoll_period = 10;
-	}
-
-	return 0;
-}
-
-void t3_led_ready(struct adapter *adapter)
-{
-	t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL,
-			 F_GPIO0_OUT_VAL);
-}
-
-int t3_replay_prep_adapter(struct adapter *adapter)
-{
-	const struct adapter_info *ai = adapter->params.info;
-	unsigned int i, j = -1;
-	int ret;
-
-	early_hw_init(adapter, ai);
-	ret = init_parity(adapter);
-	if (ret)
-		return ret;
-
-	for_each_port(adapter, i) {
-		const struct port_type_info *pti;
-		struct port_info *p = adap2pinfo(adapter, i);
-
-		while (!adapter->params.vpd.port_type[++j])
-			;
-
-		pti = &port_types[adapter->params.vpd.port_type[j]];
-		ret = pti->phy_prep(&p->phy, adapter, p->phy.mdio.prtad, NULL);
-		if (ret)
-			return ret;
-		p->phy.ops->power_down(&p->phy, 1);
-	}
-
-return 0;
-}
-
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/version.h linux-libre-3.2-gnu/drivers/net/cxgb3/version.h
--- linux-libre-3.1-gnu/drivers/net/cxgb3/version.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/version.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-/* $Date: 2006/10/31 18:57:51 $ $RCSfile: version.h,v $ $Revision: 1.3 $ */
-#ifndef __CHELSIO_VERSION_H
-#define __CHELSIO_VERSION_H
-#define DRV_DESC "Chelsio T3 Network Driver"
-#define DRV_NAME "cxgb3"
-/* Driver version */
-#define DRV_VERSION "1.1.4-ko"
-
-/* Firmware version */
-#define FW_VERSION_MAJOR 7
-#define FW_VERSION_MINOR 10
-#define FW_VERSION_MICRO 0
-#endif				/* __CHELSIO_VERSION_H */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/vsc8211.c linux-libre-3.2-gnu/drivers/net/cxgb3/vsc8211.c
--- linux-libre-3.1-gnu/drivers/net/cxgb3/vsc8211.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/vsc8211.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,416 +0,0 @@
-/*
- * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#include "common.h"
-
-/* VSC8211 PHY specific registers. */
-enum {
-	VSC8211_SIGDET_CTRL = 19,
-	VSC8211_EXT_CTRL = 23,
-	VSC8211_INTR_ENABLE = 25,
-	VSC8211_INTR_STATUS = 26,
-	VSC8211_LED_CTRL = 27,
-	VSC8211_AUX_CTRL_STAT = 28,
-	VSC8211_EXT_PAGE_AXS = 31,
-};
-
-enum {
-	VSC_INTR_RX_ERR = 1 << 0,
-	VSC_INTR_MS_ERR = 1 << 1,  /* master/slave resolution error */
-	VSC_INTR_CABLE = 1 << 2,  /* cable impairment */
-	VSC_INTR_FALSE_CARR = 1 << 3,  /* false carrier */
-	VSC_INTR_MEDIA_CHG = 1 << 4,  /* AMS media change */
-	VSC_INTR_RX_FIFO = 1 << 5,  /* Rx FIFO over/underflow */
-	VSC_INTR_TX_FIFO = 1 << 6,  /* Tx FIFO over/underflow */
-	VSC_INTR_DESCRAMBL = 1 << 7,  /* descrambler lock-lost */
-	VSC_INTR_SYMBOL_ERR = 1 << 8,  /* symbol error */
-	VSC_INTR_NEG_DONE = 1 << 10, /* autoneg done */
-	VSC_INTR_NEG_ERR = 1 << 11, /* autoneg error */
-	VSC_INTR_DPLX_CHG = 1 << 12, /* duplex change */
-	VSC_INTR_LINK_CHG = 1 << 13, /* link change */
-	VSC_INTR_SPD_CHG = 1 << 14, /* speed change */
-	VSC_INTR_ENABLE = 1 << 15, /* interrupt enable */
-};
-
-enum {
-	VSC_CTRL_CLAUSE37_VIEW = 1 << 4,   /* Switch to Clause 37 view */
-	VSC_CTRL_MEDIA_MODE_HI = 0xf000    /* High part of media mode select */
-};
-
-#define CFG_CHG_INTR_MASK (VSC_INTR_LINK_CHG | VSC_INTR_NEG_ERR | \
-			   VSC_INTR_DPLX_CHG | VSC_INTR_SPD_CHG | \
-	 		   VSC_INTR_NEG_DONE)
-#define INTR_MASK (CFG_CHG_INTR_MASK | VSC_INTR_TX_FIFO | VSC_INTR_RX_FIFO | \
-		   VSC_INTR_ENABLE)
-
-/* PHY specific auxiliary control & status register fields */
-#define S_ACSR_ACTIPHY_TMR    0
-#define M_ACSR_ACTIPHY_TMR    0x3
-#define V_ACSR_ACTIPHY_TMR(x) ((x) << S_ACSR_ACTIPHY_TMR)
-
-#define S_ACSR_SPEED    3
-#define M_ACSR_SPEED    0x3
-#define G_ACSR_SPEED(x) (((x) >> S_ACSR_SPEED) & M_ACSR_SPEED)
-
-#define S_ACSR_DUPLEX 5
-#define F_ACSR_DUPLEX (1 << S_ACSR_DUPLEX)
-
-#define S_ACSR_ACTIPHY 6
-#define F_ACSR_ACTIPHY (1 << S_ACSR_ACTIPHY)
-
-/*
- * Reset the PHY.  This PHY completes reset immediately so we never wait.
- */
-static int vsc8211_reset(struct cphy *cphy, int wait)
-{
-	return t3_phy_reset(cphy, MDIO_DEVAD_NONE, 0);
-}
-
-static int vsc8211_intr_enable(struct cphy *cphy)
-{
-	return t3_mdio_write(cphy, MDIO_DEVAD_NONE, VSC8211_INTR_ENABLE,
-			     INTR_MASK);
-}
-
-static int vsc8211_intr_disable(struct cphy *cphy)
-{
-	return t3_mdio_write(cphy, MDIO_DEVAD_NONE, VSC8211_INTR_ENABLE, 0);
-}
-
-static int vsc8211_intr_clear(struct cphy *cphy)
-{
-	u32 val;
-
-	/* Clear PHY interrupts by reading the register. */
-	return t3_mdio_read(cphy, MDIO_DEVAD_NONE, VSC8211_INTR_STATUS, &val);
-}
-
-static int vsc8211_autoneg_enable(struct cphy *cphy)
-{
-	return t3_mdio_change_bits(cphy, MDIO_DEVAD_NONE, MII_BMCR,
-				   BMCR_PDOWN | BMCR_ISOLATE,
-				   BMCR_ANENABLE | BMCR_ANRESTART);
-}
-
-static int vsc8211_autoneg_restart(struct cphy *cphy)
-{
-	return t3_mdio_change_bits(cphy, MDIO_DEVAD_NONE, MII_BMCR,
-				   BMCR_PDOWN | BMCR_ISOLATE,
-				   BMCR_ANRESTART);
-}
-
-static int vsc8211_get_link_status(struct cphy *cphy, int *link_ok,
-				   int *speed, int *duplex, int *fc)
-{
-	unsigned int bmcr, status, lpa, adv;
-	int err, sp = -1, dplx = -1, pause = 0;
-
-	err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMCR, &bmcr);
-	if (!err)
-		err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMSR, &status);
-	if (err)
-		return err;
-
-	if (link_ok) {
-		/*
-		 * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it
-		 * once more to get the current link state.
-		 */
-		if (!(status & BMSR_LSTATUS))
-			err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMSR,
-					   &status);
-		if (err)
-			return err;
-		*link_ok = (status & BMSR_LSTATUS) != 0;
-	}
-	if (!(bmcr & BMCR_ANENABLE)) {
-		dplx = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
-		if (bmcr & BMCR_SPEED1000)
-			sp = SPEED_1000;
-		else if (bmcr & BMCR_SPEED100)
-			sp = SPEED_100;
-		else
-			sp = SPEED_10;
-	} else if (status & BMSR_ANEGCOMPLETE) {
-		err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, VSC8211_AUX_CTRL_STAT,
-				   &status);
-		if (err)
-			return err;
-
-		dplx = (status & F_ACSR_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF;
-		sp = G_ACSR_SPEED(status);
-		if (sp == 0)
-			sp = SPEED_10;
-		else if (sp == 1)
-			sp = SPEED_100;
-		else
-			sp = SPEED_1000;
-
-		if (fc && dplx == DUPLEX_FULL) {
-			err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_LPA,
-					   &lpa);
-			if (!err)
-				err = t3_mdio_read(cphy, MDIO_DEVAD_NONE,
-						   MII_ADVERTISE, &adv);
-			if (err)
-				return err;
-
-			if (lpa & adv & ADVERTISE_PAUSE_CAP)
-				pause = PAUSE_RX | PAUSE_TX;
-			else if ((lpa & ADVERTISE_PAUSE_CAP) &&
-				 (lpa & ADVERTISE_PAUSE_ASYM) &&
-				 (adv & ADVERTISE_PAUSE_ASYM))
-				pause = PAUSE_TX;
-			else if ((lpa & ADVERTISE_PAUSE_ASYM) &&
-				 (adv & ADVERTISE_PAUSE_CAP))
-				pause = PAUSE_RX;
-		}
-	}
-	if (speed)
-		*speed = sp;
-	if (duplex)
-		*duplex = dplx;
-	if (fc)
-		*fc = pause;
-	return 0;
-}
-
-static int vsc8211_get_link_status_fiber(struct cphy *cphy, int *link_ok,
-					 int *speed, int *duplex, int *fc)
-{
-	unsigned int bmcr, status, lpa, adv;
-	int err, sp = -1, dplx = -1, pause = 0;
-
-	err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMCR, &bmcr);
-	if (!err)
-		err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMSR, &status);
-	if (err)
-		return err;
-
-	if (link_ok) {
-		/*
-		 * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it
-		 * once more to get the current link state.
-		 */
-		if (!(status & BMSR_LSTATUS))
-			err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMSR,
-					   &status);
-		if (err)
-			return err;
-		*link_ok = (status & BMSR_LSTATUS) != 0;
-	}
-	if (!(bmcr & BMCR_ANENABLE)) {
-		dplx = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
-		if (bmcr & BMCR_SPEED1000)
-			sp = SPEED_1000;
-		else if (bmcr & BMCR_SPEED100)
-			sp = SPEED_100;
-		else
-			sp = SPEED_10;
-	} else if (status & BMSR_ANEGCOMPLETE) {
-		err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_LPA, &lpa);
-		if (!err)
-			err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_ADVERTISE,
-					   &adv);
-		if (err)
-			return err;
-
-		if (adv & lpa & ADVERTISE_1000XFULL) {
-			dplx = DUPLEX_FULL;
-			sp = SPEED_1000;
-		} else if (adv & lpa & ADVERTISE_1000XHALF) {
-			dplx = DUPLEX_HALF;
-			sp = SPEED_1000;
-		}
-
-		if (fc && dplx == DUPLEX_FULL) {
-			if (lpa & adv & ADVERTISE_1000XPAUSE)
-				pause = PAUSE_RX | PAUSE_TX;
-			else if ((lpa & ADVERTISE_1000XPAUSE) &&
-				 (adv & lpa & ADVERTISE_1000XPSE_ASYM))
-				pause = PAUSE_TX;
-			else if ((lpa & ADVERTISE_1000XPSE_ASYM) &&
-				 (adv & ADVERTISE_1000XPAUSE))
-				pause = PAUSE_RX;
-		}
-	}
-	if (speed)
-		*speed = sp;
-	if (duplex)
-		*duplex = dplx;
-	if (fc)
-		*fc = pause;
-	return 0;
-}
-
-#ifdef UNUSED
-/*
- * Enable/disable auto MDI/MDI-X in forced link speed mode.
- */
-static int vsc8211_set_automdi(struct cphy *phy, int enable)
-{
-	int err;
-
-	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_PAGE_AXS, 0x52b5);
-	if (err)
-		return err;
-
-	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, 18, 0x12);
-	if (err)
-		return err;
-
-	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, 17, enable ? 0x2803 : 0x3003);
-	if (err)
-		return err;
-
-	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, 16, 0x87fa);
-	if (err)
-		return err;
-
-	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_PAGE_AXS, 0);
-	if (err)
-		return err;
-
-	return 0;
-}
-
-int vsc8211_set_speed_duplex(struct cphy *phy, int speed, int duplex)
-{
-	int err;
-
-	err = t3_set_phy_speed_duplex(phy, speed, duplex);
-	if (!err)
-		err = vsc8211_set_automdi(phy, 1);
-	return err;
-}
-#endif /* UNUSED */
-
-static int vsc8211_power_down(struct cphy *cphy, int enable)
-{
-	return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN,
-				   enable ? BMCR_PDOWN : 0);
-}
-
-static int vsc8211_intr_handler(struct cphy *cphy)
-{
-	unsigned int cause;
-	int err, cphy_cause = 0;
-
-	err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, VSC8211_INTR_STATUS, &cause);
-	if (err)
-		return err;
-
-	cause &= INTR_MASK;
-	if (cause & CFG_CHG_INTR_MASK)
-		cphy_cause |= cphy_cause_link_change;
-	if (cause & (VSC_INTR_RX_FIFO | VSC_INTR_TX_FIFO))
-		cphy_cause |= cphy_cause_fifo_error;
-	return cphy_cause;
-}
-
-static struct cphy_ops vsc8211_ops = {
-	.reset = vsc8211_reset,
-	.intr_enable = vsc8211_intr_enable,
-	.intr_disable = vsc8211_intr_disable,
-	.intr_clear = vsc8211_intr_clear,
-	.intr_handler = vsc8211_intr_handler,
-	.autoneg_enable = vsc8211_autoneg_enable,
-	.autoneg_restart = vsc8211_autoneg_restart,
-	.advertise = t3_phy_advertise,
-	.set_speed_duplex = t3_set_phy_speed_duplex,
-	.get_link_status = vsc8211_get_link_status,
-	.power_down = vsc8211_power_down,
-};
-
-static struct cphy_ops vsc8211_fiber_ops = {
-	.reset = vsc8211_reset,
-	.intr_enable = vsc8211_intr_enable,
-	.intr_disable = vsc8211_intr_disable,
-	.intr_clear = vsc8211_intr_clear,
-	.intr_handler = vsc8211_intr_handler,
-	.autoneg_enable = vsc8211_autoneg_enable,
-	.autoneg_restart = vsc8211_autoneg_restart,
-	.advertise = t3_phy_advertise_fiber,
-	.set_speed_duplex = t3_set_phy_speed_duplex,
-	.get_link_status = vsc8211_get_link_status_fiber,
-	.power_down = vsc8211_power_down,
-};
-
-int t3_vsc8211_phy_prep(struct cphy *phy, struct adapter *adapter,
-			int phy_addr, const struct mdio_ops *mdio_ops)
-{
-	int err;
-	unsigned int val;
-
-	cphy_init(phy, adapter, phy_addr, &vsc8211_ops, mdio_ops,
-		  SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full |
-		  SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII |
-		  SUPPORTED_TP | SUPPORTED_IRQ, "10/100/1000BASE-T");
-	msleep(20);       /* PHY needs ~10ms to start responding to MDIO */
-
-	err = t3_mdio_read(phy, MDIO_DEVAD_NONE, VSC8211_EXT_CTRL, &val);
-	if (err)
-		return err;
-	if (val & VSC_CTRL_MEDIA_MODE_HI) {
-		/* copper interface, just need to configure the LEDs */
-		return t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_LED_CTRL,
-				     0x100);
-	}
-
-	phy->caps = SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
-		    SUPPORTED_MII | SUPPORTED_FIBRE | SUPPORTED_IRQ;
-	phy->desc = "1000BASE-X";
-	phy->ops = &vsc8211_fiber_ops;
-
-	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_PAGE_AXS, 1);
-	if (err)
-		return err;
-
-	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_SIGDET_CTRL, 1);
-	if (err)
-		return err;
-
-	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_PAGE_AXS, 0);
-	if (err)
-		return err;
-
-	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_CTRL,
-			    val | VSC_CTRL_CLAUSE37_VIEW);
-	if (err)
-		return err;
-
-	err = vsc8211_reset(phy, 0);
-	if (err)
-		return err;
-
-	udelay(5); /* delay after reset before next SMI */
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb3/xgmac.c linux-libre-3.2-gnu/drivers/net/cxgb3/xgmac.c
--- linux-libre-3.1-gnu/drivers/net/cxgb3/xgmac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb3/xgmac.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,657 +0,0 @@
-/*
- * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#include "common.h"
-#include "regs.h"
-
-/*
- * # of exact address filters.  The first one is used for the station address,
- * the rest are available for multicast addresses.
- */
-#define EXACT_ADDR_FILTERS 8
-
-static inline int macidx(const struct cmac *mac)
-{
-	return mac->offset / (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR);
-}
-
-static void xaui_serdes_reset(struct cmac *mac)
-{
-	static const unsigned int clear[] = {
-		F_PWRDN0 | F_PWRDN1, F_RESETPLL01, F_RESET0 | F_RESET1,
-		F_PWRDN2 | F_PWRDN3, F_RESETPLL23, F_RESET2 | F_RESET3
-	};
-
-	int i;
-	struct adapter *adap = mac->adapter;
-	u32 ctrl = A_XGM_SERDES_CTRL0 + mac->offset;
-
-	t3_write_reg(adap, ctrl, adap->params.vpd.xauicfg[macidx(mac)] |
-		     F_RESET3 | F_RESET2 | F_RESET1 | F_RESET0 |
-		     F_PWRDN3 | F_PWRDN2 | F_PWRDN1 | F_PWRDN0 |
-		     F_RESETPLL23 | F_RESETPLL01);
-	t3_read_reg(adap, ctrl);
-	udelay(15);
-
-	for (i = 0; i < ARRAY_SIZE(clear); i++) {
-		t3_set_reg_field(adap, ctrl, clear[i], 0);
-		udelay(15);
-	}
-}
-
-void t3b_pcs_reset(struct cmac *mac)
-{
-	t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
-			 F_PCS_RESET_, 0);
-	udelay(20);
-	t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 0,
-			 F_PCS_RESET_);
-}
-
-int t3_mac_reset(struct cmac *mac)
-{
-	static const struct addr_val_pair mac_reset_avp[] = {
-		{A_XGM_TX_CTRL, 0},
-		{A_XGM_RX_CTRL, 0},
-		{A_XGM_RX_CFG, F_DISPAUSEFRAMES | F_EN1536BFRAMES |
-		 F_RMFCS | F_ENJUMBO | F_ENHASHMCAST},
-		{A_XGM_RX_HASH_LOW, 0},
-		{A_XGM_RX_HASH_HIGH, 0},
-		{A_XGM_RX_EXACT_MATCH_LOW_1, 0},
-		{A_XGM_RX_EXACT_MATCH_LOW_2, 0},
-		{A_XGM_RX_EXACT_MATCH_LOW_3, 0},
-		{A_XGM_RX_EXACT_MATCH_LOW_4, 0},
-		{A_XGM_RX_EXACT_MATCH_LOW_5, 0},
-		{A_XGM_RX_EXACT_MATCH_LOW_6, 0},
-		{A_XGM_RX_EXACT_MATCH_LOW_7, 0},
-		{A_XGM_RX_EXACT_MATCH_LOW_8, 0},
-		{A_XGM_STAT_CTRL, F_CLRSTATS}
-	};
-	u32 val;
-	struct adapter *adap = mac->adapter;
-	unsigned int oft = mac->offset;
-
-	t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_);
-	t3_read_reg(adap, A_XGM_RESET_CTRL + oft);	/* flush */
-
-	t3_write_regs(adap, mac_reset_avp, ARRAY_SIZE(mac_reset_avp), oft);
-	t3_set_reg_field(adap, A_XGM_RXFIFO_CFG + oft,
-			 F_RXSTRFRWRD | F_DISERRFRAMES,
-			 uses_xaui(adap) ? 0 : F_RXSTRFRWRD);
-	t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft, 0, F_UNDERUNFIX);
-
-	if (uses_xaui(adap)) {
-		if (adap->params.rev == 0) {
-			t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0,
-					 F_RXENABLE | F_TXENABLE);
-			if (t3_wait_op_done(adap, A_XGM_SERDES_STATUS1 + oft,
-					    F_CMULOCK, 1, 5, 2)) {
-				CH_ERR(adap,
-				       "MAC %d XAUI SERDES CMU lock failed\n",
-				       macidx(mac));
-				return -1;
-			}
-			t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0,
-					 F_SERDESRESET_);
-		} else
-			xaui_serdes_reset(mac);
-	}
-
-	t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + oft,
-			 V_RXMAXFRAMERSIZE(M_RXMAXFRAMERSIZE),
-			 V_RXMAXFRAMERSIZE(MAX_FRAME_SIZE) | F_RXENFRAMER);
-	val = F_MAC_RESET_ | F_XGMAC_STOP_EN;
-
-	if (is_10G(adap))
-		val |= F_PCS_RESET_;
-	else if (uses_xaui(adap))
-		val |= F_PCS_RESET_ | F_XG2G_RESET_;
-	else
-		val |= F_RGMII_RESET_ | F_XG2G_RESET_;
-	t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
-	t3_read_reg(adap, A_XGM_RESET_CTRL + oft);	/* flush */
-	if ((val & F_PCS_RESET_) && adap->params.rev) {
-		msleep(1);
-		t3b_pcs_reset(mac);
-	}
-
-	memset(&mac->stats, 0, sizeof(mac->stats));
-	return 0;
-}
-
-static int t3b2_mac_reset(struct cmac *mac)
-{
-	struct adapter *adap = mac->adapter;
-	unsigned int oft = mac->offset, store;
-	int idx = macidx(mac);
-	u32 val;
-
-	if (!macidx(mac))
-		t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0);
-	else
-		t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0);
-
-	/* Stop NIC traffic to reduce the number of TXTOGGLES */
-	t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 0);
-	/* Ensure TX drains */
-	t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, 0);
-
-	t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_);
-	t3_read_reg(adap, A_XGM_RESET_CTRL + oft);    /* flush */
-
-	/* Store A_TP_TX_DROP_CFG_CH0 */
-	t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
-	store = t3_read_reg(adap, A_TP_TX_DROP_CFG_CH0 + idx);
-
-	msleep(10);
-
-	/* Change DROP_CFG to 0xc0000011 */
-	t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
-	t3_write_reg(adap, A_TP_PIO_DATA, 0xc0000011);
-
-	/* Check for xgm Rx fifo empty */
-	/* Increased loop count to 1000 from 5 cover 1G and 100Mbps case */
-	if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft,
-			    0x80000000, 1, 1000, 2)) {
-		CH_ERR(adap, "MAC %d Rx fifo drain failed\n",
-		       macidx(mac));
-		return -1;
-	}
-
-	t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0);
-	t3_read_reg(adap, A_XGM_RESET_CTRL + oft);    /* flush */
-
-	val = F_MAC_RESET_;
-	if (is_10G(adap))
-		val |= F_PCS_RESET_;
-	else if (uses_xaui(adap))
-		val |= F_PCS_RESET_ | F_XG2G_RESET_;
-	else
-		val |= F_RGMII_RESET_ | F_XG2G_RESET_;
-	t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
-	t3_read_reg(adap, A_XGM_RESET_CTRL + oft);  /* flush */
-	if ((val & F_PCS_RESET_) && adap->params.rev) {
-		msleep(1);
-		t3b_pcs_reset(mac);
-	}
-	t3_write_reg(adap, A_XGM_RX_CFG + oft,
-		     F_DISPAUSEFRAMES | F_EN1536BFRAMES |
-		     F_RMFCS | F_ENJUMBO | F_ENHASHMCAST);
-
-	/* Restore the DROP_CFG */
-	t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
-	t3_write_reg(adap, A_TP_PIO_DATA, store);
-
-	if (!idx)
-		t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE);
-	else
-		t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE);
-
-	/* re-enable nic traffic */
-	t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1);
-
-	/*  Set: re-enable NIC traffic */
-	t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1);
-
-	return 0;
-}
-
-/*
- * Set the exact match register 'idx' to recognize the given Ethernet address.
- */
-static void set_addr_filter(struct cmac *mac, int idx, const u8 * addr)
-{
-	u32 addr_lo, addr_hi;
-	unsigned int oft = mac->offset + idx * 8;
-
-	addr_lo = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
-	addr_hi = (addr[5] << 8) | addr[4];
-
-	t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1 + oft, addr_lo);
-	t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_HIGH_1 + oft, addr_hi);
-}
-
-/* Set one of the station's unicast MAC addresses. */
-int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6])
-{
-	if (idx >= mac->nucast)
-		return -EINVAL;
-	set_addr_filter(mac, idx, addr);
-	return 0;
-}
-
-/*
- * Specify the number of exact address filters that should be reserved for
- * unicast addresses.  Caller should reload the unicast and multicast addresses
- * after calling this.
- */
-int t3_mac_set_num_ucast(struct cmac *mac, int n)
-{
-	if (n > EXACT_ADDR_FILTERS)
-		return -EINVAL;
-	mac->nucast = n;
-	return 0;
-}
-
-void t3_mac_disable_exact_filters(struct cmac *mac)
-{
-	unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_LOW_1;
-
-	for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
-		u32 v = t3_read_reg(mac->adapter, reg);
-		t3_write_reg(mac->adapter, reg, v);
-	}
-	t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1);	/* flush */
-}
-
-void t3_mac_enable_exact_filters(struct cmac *mac)
-{
-	unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_HIGH_1;
-
-	for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
-		u32 v = t3_read_reg(mac->adapter, reg);
-		t3_write_reg(mac->adapter, reg, v);
-	}
-	t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1);	/* flush */
-}
-
-/* Calculate the RX hash filter index of an Ethernet address */
-static int hash_hw_addr(const u8 * addr)
-{
-	int hash = 0, octet, bit, i = 0, c;
-
-	for (octet = 0; octet < 6; ++octet)
-		for (c = addr[octet], bit = 0; bit < 8; c >>= 1, ++bit) {
-			hash ^= (c & 1) << i;
-			if (++i == 6)
-				i = 0;
-		}
-	return hash;
-}
-
-int t3_mac_set_rx_mode(struct cmac *mac, struct net_device *dev)
-{
-	u32 val, hash_lo, hash_hi;
-	struct adapter *adap = mac->adapter;
-	unsigned int oft = mac->offset;
-
-	val = t3_read_reg(adap, A_XGM_RX_CFG + oft) & ~F_COPYALLFRAMES;
-	if (dev->flags & IFF_PROMISC)
-		val |= F_COPYALLFRAMES;
-	t3_write_reg(adap, A_XGM_RX_CFG + oft, val);
-
-	if (dev->flags & IFF_ALLMULTI)
-		hash_lo = hash_hi = 0xffffffff;
-	else {
-		struct netdev_hw_addr *ha;
-		int exact_addr_idx = mac->nucast;
-
-		hash_lo = hash_hi = 0;
-		netdev_for_each_mc_addr(ha, dev)
-			if (exact_addr_idx < EXACT_ADDR_FILTERS)
-				set_addr_filter(mac, exact_addr_idx++,
-						ha->addr);
-			else {
-				int hash = hash_hw_addr(ha->addr);
-
-				if (hash < 32)
-					hash_lo |= (1 << hash);
-				else
-					hash_hi |= (1 << (hash - 32));
-			}
-	}
-
-	t3_write_reg(adap, A_XGM_RX_HASH_LOW + oft, hash_lo);
-	t3_write_reg(adap, A_XGM_RX_HASH_HIGH + oft, hash_hi);
-	return 0;
-}
-
-static int rx_fifo_hwm(int mtu)
-{
-	int hwm;
-
-	hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, (MAC_RXFIFO_SIZE * 38) / 100);
-	return min(hwm, MAC_RXFIFO_SIZE - 8192);
-}
-
-int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
-{
-	int hwm, lwm, divisor;
-	int ipg;
-	unsigned int thres, v, reg;
-	struct adapter *adap = mac->adapter;
-
-	/*
-	 * MAX_FRAME_SIZE inludes header + FCS, mtu doesn't.  The HW max
-	 * packet size register includes header, but not FCS.
-	 */
-	mtu += 14;
-	if (mtu > 1536)
-		mtu += 4;
-
-	if (mtu > MAX_FRAME_SIZE - 4)
-		return -EINVAL;
-	t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu);
-
-	if (adap->params.rev >= T3_REV_B2 &&
-	    (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) {
-		t3_mac_disable_exact_filters(mac);
-		v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset);
-		t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset,
-				 F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST);
-
-		reg = adap->params.rev == T3_REV_B2 ?
-			A_XGM_RX_MAX_PKT_SIZE_ERR_CNT : A_XGM_RXFIFO_CFG;
-
-		/* drain RX FIFO */
-		if (t3_wait_op_done(adap, reg + mac->offset,
-				    F_RXFIFO_EMPTY, 1, 20, 5)) {
-			t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
-			t3_mac_enable_exact_filters(mac);
-			return -EIO;
-		}
-		t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset,
-				 V_RXMAXPKTSIZE(M_RXMAXPKTSIZE),
-				 V_RXMAXPKTSIZE(mtu));
-		t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
-		t3_mac_enable_exact_filters(mac);
-	} else
-		t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset,
-				 V_RXMAXPKTSIZE(M_RXMAXPKTSIZE),
-				 V_RXMAXPKTSIZE(mtu));
-
-	/*
-	 * Adjust the PAUSE frame watermarks.  We always set the LWM, and the
-	 * HWM only if flow-control is enabled.
-	 */
-	hwm = rx_fifo_hwm(mtu);
-	lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4);
-	v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset);
-	v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM);
-	v |= V_RXFIFOPAUSELWM(lwm / 8);
-	if (G_RXFIFOPAUSEHWM(v))
-		v = (v & ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM)) |
-		    V_RXFIFOPAUSEHWM(hwm / 8);
-
-	t3_write_reg(adap, A_XGM_RXFIFO_CFG + mac->offset, v);
-
-	/* Adjust the TX FIFO threshold based on the MTU */
-	thres = (adap->params.vpd.cclk * 1000) / 15625;
-	thres = (thres * mtu) / 1000;
-	if (is_10G(adap))
-		thres /= 10;
-	thres = mtu > thres ? (mtu - thres + 7) / 8 : 0;
-	thres = max(thres, 8U);	/* need at least 8 */
-	ipg = (adap->params.rev == T3_REV_C) ? 0 : 1;
-	t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset,
-			 V_TXFIFOTHRESH(M_TXFIFOTHRESH) | V_TXIPG(M_TXIPG),
-			 V_TXFIFOTHRESH(thres) | V_TXIPG(ipg));
-
-	if (adap->params.rev > 0) {
-		divisor = (adap->params.rev == T3_REV_C) ? 64 : 8;
-		t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset,
-			     (hwm - lwm) * 4 / divisor);
-	}
-	t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset,
-		     MAC_RXFIFO_SIZE * 4 * 8 / 512);
-	return 0;
-}
-
-int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc)
-{
-	u32 val;
-	struct adapter *adap = mac->adapter;
-	unsigned int oft = mac->offset;
-
-	if (duplex >= 0 && duplex != DUPLEX_FULL)
-		return -EINVAL;
-	if (speed >= 0) {
-		if (speed == SPEED_10)
-			val = V_PORTSPEED(0);
-		else if (speed == SPEED_100)
-			val = V_PORTSPEED(1);
-		else if (speed == SPEED_1000)
-			val = V_PORTSPEED(2);
-		else if (speed == SPEED_10000)
-			val = V_PORTSPEED(3);
-		else
-			return -EINVAL;
-
-		t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
-				 V_PORTSPEED(M_PORTSPEED), val);
-	}
-
-	val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
-	val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
-	if (fc & PAUSE_TX) {
-		u32 rx_max_pkt_size =
-		    G_RXMAXPKTSIZE(t3_read_reg(adap,
-					       A_XGM_RX_MAX_PKT_SIZE + oft));
-		val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8);
-	}
-	t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
-
-	t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
-			 (fc & PAUSE_RX) ? F_TXPAUSEEN : 0);
-	return 0;
-}
-
-int t3_mac_enable(struct cmac *mac, int which)
-{
-	int idx = macidx(mac);
-	struct adapter *adap = mac->adapter;
-	unsigned int oft = mac->offset;
-	struct mac_stats *s = &mac->stats;
-
-	if (which & MAC_DIRECTION_TX) {
-		t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
-		t3_write_reg(adap, A_TP_PIO_DATA,
-			     adap->params.rev == T3_REV_C ?
-			     0xc4ffff01 : 0xc0ede401);
-		t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE);
-		t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx,
-				 adap->params.rev == T3_REV_C ? 0 : 1 << idx);
-
-		t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN);
-
-		t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx);
-		mac->tx_mcnt = s->tx_frames;
-		mac->tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
-							A_TP_PIO_DATA)));
-		mac->tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
-						A_XGM_TX_SPI4_SOP_EOP_CNT +
-						oft)));
-		mac->rx_mcnt = s->rx_frames;
-		mac->rx_pause = s->rx_pause;
-		mac->rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
-						A_XGM_RX_SPI4_SOP_EOP_CNT +
-						oft)));
-		mac->rx_ocnt = s->rx_fifo_ovfl;
-		mac->txen = F_TXEN;
-		mac->toggle_cnt = 0;
-	}
-	if (which & MAC_DIRECTION_RX)
-		t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN);
-	return 0;
-}
-
-int t3_mac_disable(struct cmac *mac, int which)
-{
-	struct adapter *adap = mac->adapter;
-
-	if (which & MAC_DIRECTION_TX) {
-		t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
-		mac->txen = 0;
-	}
-	if (which & MAC_DIRECTION_RX) {
-		int val = F_MAC_RESET_;
-
-		t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
-				 F_PCS_RESET_, 0);
-		msleep(100);
-		t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0);
-		if (is_10G(adap))
-			val |= F_PCS_RESET_;
-		else if (uses_xaui(adap))
-			val |= F_PCS_RESET_ | F_XG2G_RESET_;
-		else
-			val |= F_RGMII_RESET_ | F_XG2G_RESET_;
-		t3_write_reg(mac->adapter, A_XGM_RESET_CTRL + mac->offset, val);
-	}
-	return 0;
-}
-
-int t3b2_mac_watchdog_task(struct cmac *mac)
-{
-	struct adapter *adap = mac->adapter;
-	struct mac_stats *s = &mac->stats;
-	unsigned int tx_tcnt, tx_xcnt;
-	u64 tx_mcnt = s->tx_frames;
-	int status;
-
-	status = 0;
-	tx_xcnt = 1;		/* By default tx_xcnt is making progress */
-	tx_tcnt = mac->tx_tcnt;	/* If tx_mcnt is progressing ignore tx_tcnt */
-	if (tx_mcnt == mac->tx_mcnt && mac->rx_pause == s->rx_pause) {
-		tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
-						A_XGM_TX_SPI4_SOP_EOP_CNT +
-					       	mac->offset)));
-		if (tx_xcnt == 0) {
-			t3_write_reg(adap, A_TP_PIO_ADDR,
-				     A_TP_TX_DROP_CNT_CH0 + macidx(mac));
-			tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
-						      A_TP_PIO_DATA)));
-		} else {
-			goto out;
-		}
-	} else {
-		mac->toggle_cnt = 0;
-		goto out;
-	}
-
-	if ((tx_tcnt != mac->tx_tcnt) && (mac->tx_xcnt == 0)) {
-		if (mac->toggle_cnt > 4) {
-			status = 2;
-			goto out;
-		} else {
-			status = 1;
-			goto out;
-		}
-	} else {
-		mac->toggle_cnt = 0;
-		goto out;
-	}
-
-out:
-	mac->tx_tcnt = tx_tcnt;
-	mac->tx_xcnt = tx_xcnt;
-	mac->tx_mcnt = s->tx_frames;
-	mac->rx_pause = s->rx_pause;
-	if (status == 1) {
-		t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
-		t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset);  /* flush */
-		t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, mac->txen);
-		t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset);  /* flush */
-		mac->toggle_cnt++;
-	} else if (status == 2) {
-		t3b2_mac_reset(mac);
-		mac->toggle_cnt = 0;
-	}
-	return status;
-}
-
-/*
- * This function is called periodically to accumulate the current values of the
- * RMON counters into the port statistics.  Since the packet counters are only
- * 32 bits they can overflow in ~286 secs at 10G, so the function should be
- * called more frequently than that.  The byte counters are 45-bit wide, they
- * would overflow in ~7.8 hours.
- */
-const struct mac_stats *t3_mac_update_stats(struct cmac *mac)
-{
-#define RMON_READ(mac, addr) t3_read_reg(mac->adapter, addr + mac->offset)
-#define RMON_UPDATE(mac, name, reg) \
-	(mac)->stats.name += (u64)RMON_READ(mac, A_XGM_STAT_##reg)
-#define RMON_UPDATE64(mac, name, reg_lo, reg_hi) \
-	(mac)->stats.name += RMON_READ(mac, A_XGM_STAT_##reg_lo) + \
-			     ((u64)RMON_READ(mac, A_XGM_STAT_##reg_hi) << 32)
-
-	u32 v, lo;
-
-	RMON_UPDATE64(mac, rx_octets, RX_BYTES_LOW, RX_BYTES_HIGH);
-	RMON_UPDATE64(mac, rx_frames, RX_FRAMES_LOW, RX_FRAMES_HIGH);
-	RMON_UPDATE(mac, rx_mcast_frames, RX_MCAST_FRAMES);
-	RMON_UPDATE(mac, rx_bcast_frames, RX_BCAST_FRAMES);
-	RMON_UPDATE(mac, rx_fcs_errs, RX_CRC_ERR_FRAMES);
-	RMON_UPDATE(mac, rx_pause, RX_PAUSE_FRAMES);
-	RMON_UPDATE(mac, rx_jabber, RX_JABBER_FRAMES);
-	RMON_UPDATE(mac, rx_short, RX_SHORT_FRAMES);
-	RMON_UPDATE(mac, rx_symbol_errs, RX_SYM_CODE_ERR_FRAMES);
-
-	RMON_UPDATE(mac, rx_too_long, RX_OVERSIZE_FRAMES);
-
-	v = RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT);
-	if (mac->adapter->params.rev == T3_REV_B2)
-		v &= 0x7fffffff;
-	mac->stats.rx_too_long += v;
-
-	RMON_UPDATE(mac, rx_frames_64, RX_64B_FRAMES);
-	RMON_UPDATE(mac, rx_frames_65_127, RX_65_127B_FRAMES);
-	RMON_UPDATE(mac, rx_frames_128_255, RX_128_255B_FRAMES);
-	RMON_UPDATE(mac, rx_frames_256_511, RX_256_511B_FRAMES);
-	RMON_UPDATE(mac, rx_frames_512_1023, RX_512_1023B_FRAMES);
-	RMON_UPDATE(mac, rx_frames_1024_1518, RX_1024_1518B_FRAMES);
-	RMON_UPDATE(mac, rx_frames_1519_max, RX_1519_MAXB_FRAMES);
-
-	RMON_UPDATE64(mac, tx_octets, TX_BYTE_LOW, TX_BYTE_HIGH);
-	RMON_UPDATE64(mac, tx_frames, TX_FRAME_LOW, TX_FRAME_HIGH);
-	RMON_UPDATE(mac, tx_mcast_frames, TX_MCAST);
-	RMON_UPDATE(mac, tx_bcast_frames, TX_BCAST);
-	RMON_UPDATE(mac, tx_pause, TX_PAUSE);
-	/* This counts error frames in general (bad FCS, underrun, etc). */
-	RMON_UPDATE(mac, tx_underrun, TX_ERR_FRAMES);
-
-	RMON_UPDATE(mac, tx_frames_64, TX_64B_FRAMES);
-	RMON_UPDATE(mac, tx_frames_65_127, TX_65_127B_FRAMES);
-	RMON_UPDATE(mac, tx_frames_128_255, TX_128_255B_FRAMES);
-	RMON_UPDATE(mac, tx_frames_256_511, TX_256_511B_FRAMES);
-	RMON_UPDATE(mac, tx_frames_512_1023, TX_512_1023B_FRAMES);
-	RMON_UPDATE(mac, tx_frames_1024_1518, TX_1024_1518B_FRAMES);
-	RMON_UPDATE(mac, tx_frames_1519_max, TX_1519_MAXB_FRAMES);
-
-	/* The next stat isn't clear-on-read. */
-	t3_write_reg(mac->adapter, A_TP_MIB_INDEX, mac->offset ? 51 : 50);
-	v = t3_read_reg(mac->adapter, A_TP_MIB_RDATA);
-	lo = (u32) mac->stats.rx_cong_drops;
-	mac->stats.rx_cong_drops += (u64) (v - lo);
-
-	return &mac->stats;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4/cxgb4.h linux-libre-3.2-gnu/drivers/net/cxgb4/cxgb4.h
--- linux-libre-3.1-gnu/drivers/net/cxgb4/cxgb4.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4/cxgb4.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,722 +0,0 @@
-/*
- * This file is part of the Chelsio T4 Ethernet driver for Linux.
- *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __CXGB4_H__
-#define __CXGB4_H__
-
-#include <linux/bitops.h>
-#include <linux/cache.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/timer.h>
-#include <asm/io.h>
-#include "cxgb4_uld.h"
-#include "t4_hw.h"
-
-#define FW_VERSION_MAJOR 1
-#define FW_VERSION_MINOR 1
-#define FW_VERSION_MICRO 0
-
-enum {
-	MAX_NPORTS = 4,     /* max # of ports */
-	SERNUM_LEN = 24,    /* Serial # length */
-	EC_LEN     = 16,    /* E/C length */
-	ID_LEN     = 16,    /* ID length */
-};
-
-enum {
-	MEM_EDC0,
-	MEM_EDC1,
-	MEM_MC
-};
-
-enum dev_master {
-	MASTER_CANT,
-	MASTER_MAY,
-	MASTER_MUST
-};
-
-enum dev_state {
-	DEV_STATE_UNINIT,
-	DEV_STATE_INIT,
-	DEV_STATE_ERR
-};
-
-enum {
-	PAUSE_RX      = 1 << 0,
-	PAUSE_TX      = 1 << 1,
-	PAUSE_AUTONEG = 1 << 2
-};
-
-struct port_stats {
-	u64 tx_octets;            /* total # of octets in good frames */
-	u64 tx_frames;            /* all good frames */
-	u64 tx_bcast_frames;      /* all broadcast frames */
-	u64 tx_mcast_frames;      /* all multicast frames */
-	u64 tx_ucast_frames;      /* all unicast frames */
-	u64 tx_error_frames;      /* all error frames */
-
-	u64 tx_frames_64;         /* # of Tx frames in a particular range */
-	u64 tx_frames_65_127;
-	u64 tx_frames_128_255;
-	u64 tx_frames_256_511;
-	u64 tx_frames_512_1023;
-	u64 tx_frames_1024_1518;
-	u64 tx_frames_1519_max;
-
-	u64 tx_drop;              /* # of dropped Tx frames */
-	u64 tx_pause;             /* # of transmitted pause frames */
-	u64 tx_ppp0;              /* # of transmitted PPP prio 0 frames */
-	u64 tx_ppp1;              /* # of transmitted PPP prio 1 frames */
-	u64 tx_ppp2;              /* # of transmitted PPP prio 2 frames */
-	u64 tx_ppp3;              /* # of transmitted PPP prio 3 frames */
-	u64 tx_ppp4;              /* # of transmitted PPP prio 4 frames */
-	u64 tx_ppp5;              /* # of transmitted PPP prio 5 frames */
-	u64 tx_ppp6;              /* # of transmitted PPP prio 6 frames */
-	u64 tx_ppp7;              /* # of transmitted PPP prio 7 frames */
-
-	u64 rx_octets;            /* total # of octets in good frames */
-	u64 rx_frames;            /* all good frames */
-	u64 rx_bcast_frames;      /* all broadcast frames */
-	u64 rx_mcast_frames;      /* all multicast frames */
-	u64 rx_ucast_frames;      /* all unicast frames */
-	u64 rx_too_long;          /* # of frames exceeding MTU */
-	u64 rx_jabber;            /* # of jabber frames */
-	u64 rx_fcs_err;           /* # of received frames with bad FCS */
-	u64 rx_len_err;           /* # of received frames with length error */
-	u64 rx_symbol_err;        /* symbol errors */
-	u64 rx_runt;              /* # of short frames */
-
-	u64 rx_frames_64;         /* # of Rx frames in a particular range */
-	u64 rx_frames_65_127;
-	u64 rx_frames_128_255;
-	u64 rx_frames_256_511;
-	u64 rx_frames_512_1023;
-	u64 rx_frames_1024_1518;
-	u64 rx_frames_1519_max;
-
-	u64 rx_pause;             /* # of received pause frames */
-	u64 rx_ppp0;              /* # of received PPP prio 0 frames */
-	u64 rx_ppp1;              /* # of received PPP prio 1 frames */
-	u64 rx_ppp2;              /* # of received PPP prio 2 frames */
-	u64 rx_ppp3;              /* # of received PPP prio 3 frames */
-	u64 rx_ppp4;              /* # of received PPP prio 4 frames */
-	u64 rx_ppp5;              /* # of received PPP prio 5 frames */
-	u64 rx_ppp6;              /* # of received PPP prio 6 frames */
-	u64 rx_ppp7;              /* # of received PPP prio 7 frames */
-
-	u64 rx_ovflow0;           /* drops due to buffer-group 0 overflows */
-	u64 rx_ovflow1;           /* drops due to buffer-group 1 overflows */
-	u64 rx_ovflow2;           /* drops due to buffer-group 2 overflows */
-	u64 rx_ovflow3;           /* drops due to buffer-group 3 overflows */
-	u64 rx_trunc0;            /* buffer-group 0 truncated packets */
-	u64 rx_trunc1;            /* buffer-group 1 truncated packets */
-	u64 rx_trunc2;            /* buffer-group 2 truncated packets */
-	u64 rx_trunc3;            /* buffer-group 3 truncated packets */
-};
-
-struct lb_port_stats {
-	u64 octets;
-	u64 frames;
-	u64 bcast_frames;
-	u64 mcast_frames;
-	u64 ucast_frames;
-	u64 error_frames;
-
-	u64 frames_64;
-	u64 frames_65_127;
-	u64 frames_128_255;
-	u64 frames_256_511;
-	u64 frames_512_1023;
-	u64 frames_1024_1518;
-	u64 frames_1519_max;
-
-	u64 drop;
-
-	u64 ovflow0;
-	u64 ovflow1;
-	u64 ovflow2;
-	u64 ovflow3;
-	u64 trunc0;
-	u64 trunc1;
-	u64 trunc2;
-	u64 trunc3;
-};
-
-struct tp_tcp_stats {
-	u32 tcpOutRsts;
-	u64 tcpInSegs;
-	u64 tcpOutSegs;
-	u64 tcpRetransSegs;
-};
-
-struct tp_err_stats {
-	u32 macInErrs[4];
-	u32 hdrInErrs[4];
-	u32 tcpInErrs[4];
-	u32 tnlCongDrops[4];
-	u32 ofldChanDrops[4];
-	u32 tnlTxDrops[4];
-	u32 ofldVlanDrops[4];
-	u32 tcp6InErrs[4];
-	u32 ofldNoNeigh;
-	u32 ofldCongDefer;
-};
-
-struct tp_params {
-	unsigned int ntxchan;        /* # of Tx channels */
-	unsigned int tre;            /* log2 of core clocks per TP tick */
-};
-
-struct vpd_params {
-	unsigned int cclk;
-	u8 ec[EC_LEN + 1];
-	u8 sn[SERNUM_LEN + 1];
-	u8 id[ID_LEN + 1];
-};
-
-struct pci_params {
-	unsigned char speed;
-	unsigned char width;
-};
-
-struct adapter_params {
-	struct tp_params  tp;
-	struct vpd_params vpd;
-	struct pci_params pci;
-
-	unsigned int sf_size;             /* serial flash size in bytes */
-	unsigned int sf_nsec;             /* # of flash sectors */
-	unsigned int sf_fw_start;         /* start of FW image in flash */
-
-	unsigned int fw_vers;
-	unsigned int tp_vers;
-	u8 api_vers[7];
-
-	unsigned short mtus[NMTUS];
-	unsigned short a_wnd[NCCTRL_WIN];
-	unsigned short b_wnd[NCCTRL_WIN];
-
-	unsigned char nports;             /* # of ethernet ports */
-	unsigned char portvec;
-	unsigned char rev;                /* chip revision */
-	unsigned char offload;
-
-	unsigned int ofldq_wr_cred;
-};
-
-struct trace_params {
-	u32 data[TRACE_LEN / 4];
-	u32 mask[TRACE_LEN / 4];
-	unsigned short snap_len;
-	unsigned short min_len;
-	unsigned char skip_ofst;
-	unsigned char skip_len;
-	unsigned char invert;
-	unsigned char port;
-};
-
-struct link_config {
-	unsigned short supported;        /* link capabilities */
-	unsigned short advertising;      /* advertised capabilities */
-	unsigned short requested_speed;  /* speed user has requested */
-	unsigned short speed;            /* actual link speed */
-	unsigned char  requested_fc;     /* flow control user has requested */
-	unsigned char  fc;               /* actual link flow control */
-	unsigned char  autoneg;          /* autonegotiating? */
-	unsigned char  link_ok;          /* link up? */
-};
-
-#define FW_LEN16(fw_struct) FW_CMD_LEN16(sizeof(fw_struct) / 16)
-
-enum {
-	MAX_ETH_QSETS = 32,           /* # of Ethernet Tx/Rx queue sets */
-	MAX_OFLD_QSETS = 16,          /* # of offload Tx/Rx queue sets */
-	MAX_CTRL_QUEUES = NCHAN,      /* # of control Tx queues */
-	MAX_RDMA_QUEUES = NCHAN,      /* # of streaming RDMA Rx queues */
-};
-
-enum {
-	MAX_EGRQ = 128,         /* max # of egress queues, including FLs */
-	MAX_INGQ = 64           /* max # of interrupt-capable ingress queues */
-};
-
-struct adapter;
-struct sge_rspq;
-
-struct port_info {
-	struct adapter *adapter;
-	u16    viid;
-	s16    xact_addr_filt;        /* index of exact MAC address filter */
-	u16    rss_size;              /* size of VI's RSS table slice */
-	s8     mdio_addr;
-	u8     port_type;
-	u8     mod_type;
-	u8     port_id;
-	u8     tx_chan;
-	u8     lport;                 /* associated offload logical port */
-	u8     nqsets;                /* # of qsets */
-	u8     first_qset;            /* index of first qset */
-	u8     rss_mode;
-	struct link_config link_cfg;
-	u16   *rss;
-};
-
-struct dentry;
-struct work_struct;
-
-enum {                                 /* adapter flags */
-	FULL_INIT_DONE     = (1 << 0),
-	USING_MSI          = (1 << 1),
-	USING_MSIX         = (1 << 2),
-	FW_OK              = (1 << 4),
-};
-
-struct rx_sw_desc;
-
-struct sge_fl {                     /* SGE free-buffer queue state */
-	unsigned int avail;         /* # of available Rx buffers */
-	unsigned int pend_cred;     /* new buffers since last FL DB ring */
-	unsigned int cidx;          /* consumer index */
-	unsigned int pidx;          /* producer index */
-	unsigned long alloc_failed; /* # of times buffer allocation failed */
-	unsigned long large_alloc_failed;
-	unsigned long starving;
-	/* RO fields */
-	unsigned int cntxt_id;      /* SGE context id for the free list */
-	unsigned int size;          /* capacity of free list */
-	struct rx_sw_desc *sdesc;   /* address of SW Rx descriptor ring */
-	__be64 *desc;               /* address of HW Rx descriptor ring */
-	dma_addr_t addr;            /* bus address of HW ring start */
-};
-
-/* A packet gather list */
-struct pkt_gl {
-	skb_frag_t frags[MAX_SKB_FRAGS];
-	void *va;                         /* virtual address of first byte */
-	unsigned int nfrags;              /* # of fragments */
-	unsigned int tot_len;             /* total length of fragments */
-};
-
-typedef int (*rspq_handler_t)(struct sge_rspq *q, const __be64 *rsp,
-			      const struct pkt_gl *gl);
-
-struct sge_rspq {                   /* state for an SGE response queue */
-	struct napi_struct napi;
-	const __be64 *cur_desc;     /* current descriptor in queue */
-	unsigned int cidx;          /* consumer index */
-	u8 gen;                     /* current generation bit */
-	u8 intr_params;             /* interrupt holdoff parameters */
-	u8 next_intr_params;        /* holdoff params for next interrupt */
-	u8 pktcnt_idx;              /* interrupt packet threshold */
-	u8 uld;                     /* ULD handling this queue */
-	u8 idx;                     /* queue index within its group */
-	int offset;                 /* offset into current Rx buffer */
-	u16 cntxt_id;               /* SGE context id for the response q */
-	u16 abs_id;                 /* absolute SGE id for the response q */
-	__be64 *desc;               /* address of HW response ring */
-	dma_addr_t phys_addr;       /* physical address of the ring */
-	unsigned int iqe_len;       /* entry size */
-	unsigned int size;          /* capacity of response queue */
-	struct adapter *adap;
-	struct net_device *netdev;  /* associated net device */
-	rspq_handler_t handler;
-};
-
-struct sge_eth_stats {              /* Ethernet queue statistics */
-	unsigned long pkts;         /* # of ethernet packets */
-	unsigned long lro_pkts;     /* # of LRO super packets */
-	unsigned long lro_merged;   /* # of wire packets merged by LRO */
-	unsigned long rx_cso;       /* # of Rx checksum offloads */
-	unsigned long vlan_ex;      /* # of Rx VLAN extractions */
-	unsigned long rx_drops;     /* # of packets dropped due to no mem */
-};
-
-struct sge_eth_rxq {                /* SW Ethernet Rx queue */
-	struct sge_rspq rspq;
-	struct sge_fl fl;
-	struct sge_eth_stats stats;
-} ____cacheline_aligned_in_smp;
-
-struct sge_ofld_stats {             /* offload queue statistics */
-	unsigned long pkts;         /* # of packets */
-	unsigned long imm;          /* # of immediate-data packets */
-	unsigned long an;           /* # of asynchronous notifications */
-	unsigned long nomem;        /* # of responses deferred due to no mem */
-};
-
-struct sge_ofld_rxq {               /* SW offload Rx queue */
-	struct sge_rspq rspq;
-	struct sge_fl fl;
-	struct sge_ofld_stats stats;
-} ____cacheline_aligned_in_smp;
-
-struct tx_desc {
-	__be64 flit[8];
-};
-
-struct tx_sw_desc;
-
-struct sge_txq {
-	unsigned int  in_use;       /* # of in-use Tx descriptors */
-	unsigned int  size;         /* # of descriptors */
-	unsigned int  cidx;         /* SW consumer index */
-	unsigned int  pidx;         /* producer index */
-	unsigned long stops;        /* # of times q has been stopped */
-	unsigned long restarts;     /* # of queue restarts */
-	unsigned int  cntxt_id;     /* SGE context id for the Tx q */
-	struct tx_desc *desc;       /* address of HW Tx descriptor ring */
-	struct tx_sw_desc *sdesc;   /* address of SW Tx descriptor ring */
-	struct sge_qstat *stat;     /* queue status entry */
-	dma_addr_t    phys_addr;    /* physical address of the ring */
-};
-
-struct sge_eth_txq {                /* state for an SGE Ethernet Tx queue */
-	struct sge_txq q;
-	struct netdev_queue *txq;   /* associated netdev TX queue */
-	unsigned long tso;          /* # of TSO requests */
-	unsigned long tx_cso;       /* # of Tx checksum offloads */
-	unsigned long vlan_ins;     /* # of Tx VLAN insertions */
-	unsigned long mapping_err;  /* # of I/O MMU packet mapping errors */
-} ____cacheline_aligned_in_smp;
-
-struct sge_ofld_txq {               /* state for an SGE offload Tx queue */
-	struct sge_txq q;
-	struct adapter *adap;
-	struct sk_buff_head sendq;  /* list of backpressured packets */
-	struct tasklet_struct qresume_tsk; /* restarts the queue */
-	u8 full;                    /* the Tx ring is full */
-	unsigned long mapping_err;  /* # of I/O MMU packet mapping errors */
-} ____cacheline_aligned_in_smp;
-
-struct sge_ctrl_txq {               /* state for an SGE control Tx queue */
-	struct sge_txq q;
-	struct adapter *adap;
-	struct sk_buff_head sendq;  /* list of backpressured packets */
-	struct tasklet_struct qresume_tsk; /* restarts the queue */
-	u8 full;                    /* the Tx ring is full */
-} ____cacheline_aligned_in_smp;
-
-struct sge {
-	struct sge_eth_txq ethtxq[MAX_ETH_QSETS];
-	struct sge_ofld_txq ofldtxq[MAX_OFLD_QSETS];
-	struct sge_ctrl_txq ctrlq[MAX_CTRL_QUEUES];
-
-	struct sge_eth_rxq ethrxq[MAX_ETH_QSETS];
-	struct sge_ofld_rxq ofldrxq[MAX_OFLD_QSETS];
-	struct sge_ofld_rxq rdmarxq[MAX_RDMA_QUEUES];
-	struct sge_rspq fw_evtq ____cacheline_aligned_in_smp;
-
-	struct sge_rspq intrq ____cacheline_aligned_in_smp;
-	spinlock_t intrq_lock;
-
-	u16 max_ethqsets;           /* # of available Ethernet queue sets */
-	u16 ethqsets;               /* # of active Ethernet queue sets */
-	u16 ethtxq_rover;           /* Tx queue to clean up next */
-	u16 ofldqsets;              /* # of active offload queue sets */
-	u16 rdmaqs;                 /* # of available RDMA Rx queues */
-	u16 ofld_rxq[MAX_OFLD_QSETS];
-	u16 rdma_rxq[NCHAN];
-	u16 timer_val[SGE_NTIMERS];
-	u8 counter_val[SGE_NCOUNTERS];
-	unsigned int starve_thres;
-	u8 idma_state[2];
-	unsigned int egr_start;
-	unsigned int ingr_start;
-	void *egr_map[MAX_EGRQ];    /* qid->queue egress queue map */
-	struct sge_rspq *ingr_map[MAX_INGQ]; /* qid->queue ingress queue map */
-	DECLARE_BITMAP(starving_fl, MAX_EGRQ);
-	DECLARE_BITMAP(txq_maperr, MAX_EGRQ);
-	struct timer_list rx_timer; /* refills starving FLs */
-	struct timer_list tx_timer; /* checks Tx queues */
-};
-
-#define for_each_ethrxq(sge, i) for (i = 0; i < (sge)->ethqsets; i++)
-#define for_each_ofldrxq(sge, i) for (i = 0; i < (sge)->ofldqsets; i++)
-#define for_each_rdmarxq(sge, i) for (i = 0; i < (sge)->rdmaqs; i++)
-
-struct l2t_data;
-
-struct adapter {
-	void __iomem *regs;
-	struct pci_dev *pdev;
-	struct device *pdev_dev;
-	unsigned int fn;
-	unsigned int flags;
-
-	int msg_enable;
-
-	struct adapter_params params;
-	struct cxgb4_virt_res vres;
-	unsigned int swintr;
-
-	unsigned int wol;
-
-	struct {
-		unsigned short vec;
-		char desc[IFNAMSIZ + 10];
-	} msix_info[MAX_INGQ + 1];
-
-	struct sge sge;
-
-	struct net_device *port[MAX_NPORTS];
-	u8 chan_map[NCHAN];                   /* channel -> port map */
-
-	struct l2t_data *l2t;
-	void *uld_handle[CXGB4_ULD_MAX];
-	struct list_head list_node;
-
-	struct tid_info tids;
-	void **tid_release_head;
-	spinlock_t tid_release_lock;
-	struct work_struct tid_release_task;
-	bool tid_release_task_busy;
-
-	struct dentry *debugfs_root;
-
-	spinlock_t stats_lock;
-};
-
-static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr)
-{
-	return readl(adap->regs + reg_addr);
-}
-
-static inline void t4_write_reg(struct adapter *adap, u32 reg_addr, u32 val)
-{
-	writel(val, adap->regs + reg_addr);
-}
-
-#ifndef readq
-static inline u64 readq(const volatile void __iomem *addr)
-{
-	return readl(addr) + ((u64)readl(addr + 4) << 32);
-}
-
-static inline void writeq(u64 val, volatile void __iomem *addr)
-{
-	writel(val, addr);
-	writel(val >> 32, addr + 4);
-}
-#endif
-
-static inline u64 t4_read_reg64(struct adapter *adap, u32 reg_addr)
-{
-	return readq(adap->regs + reg_addr);
-}
-
-static inline void t4_write_reg64(struct adapter *adap, u32 reg_addr, u64 val)
-{
-	writeq(val, adap->regs + reg_addr);
-}
-
-/**
- * netdev2pinfo - return the port_info structure associated with a net_device
- * @dev: the netdev
- *
- * Return the struct port_info associated with a net_device
- */
-static inline struct port_info *netdev2pinfo(const struct net_device *dev)
-{
-	return netdev_priv(dev);
-}
-
-/**
- * adap2pinfo - return the port_info of a port
- * @adap: the adapter
- * @idx: the port index
- *
- * Return the port_info structure for the port of the given index.
- */
-static inline struct port_info *adap2pinfo(struct adapter *adap, int idx)
-{
-	return netdev_priv(adap->port[idx]);
-}
-
-/**
- * netdev2adap - return the adapter structure associated with a net_device
- * @dev: the netdev
- *
- * Return the struct adapter associated with a net_device
- */
-static inline struct adapter *netdev2adap(const struct net_device *dev)
-{
-	return netdev2pinfo(dev)->adapter;
-}
-
-void t4_os_portmod_changed(const struct adapter *adap, int port_id);
-void t4_os_link_changed(struct adapter *adap, int port_id, int link_stat);
-
-void *t4_alloc_mem(size_t size);
-
-void t4_free_sge_resources(struct adapter *adap);
-irq_handler_t t4_intr_handler(struct adapter *adap);
-netdev_tx_t t4_eth_xmit(struct sk_buff *skb, struct net_device *dev);
-int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
-		     const struct pkt_gl *gl);
-int t4_mgmt_tx(struct adapter *adap, struct sk_buff *skb);
-int t4_ofld_send(struct adapter *adap, struct sk_buff *skb);
-int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
-		     struct net_device *dev, int intr_idx,
-		     struct sge_fl *fl, rspq_handler_t hnd);
-int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq,
-			 struct net_device *dev, struct netdev_queue *netdevq,
-			 unsigned int iqid);
-int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq,
-			  struct net_device *dev, unsigned int iqid,
-			  unsigned int cmplqid);
-int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq,
-			  struct net_device *dev, unsigned int iqid);
-irqreturn_t t4_sge_intr_msix(int irq, void *cookie);
-void t4_sge_init(struct adapter *adap);
-void t4_sge_start(struct adapter *adap);
-void t4_sge_stop(struct adapter *adap);
-
-#define for_each_port(adapter, iter) \
-	for (iter = 0; iter < (adapter)->params.nports; ++iter)
-
-static inline unsigned int core_ticks_per_usec(const struct adapter *adap)
-{
-	return adap->params.vpd.cclk / 1000;
-}
-
-static inline unsigned int us_to_core_ticks(const struct adapter *adap,
-					    unsigned int us)
-{
-	return (us * adap->params.vpd.cclk) / 1000;
-}
-
-void t4_set_reg_field(struct adapter *adap, unsigned int addr, u32 mask,
-		      u32 val);
-
-int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
-		    void *rpl, bool sleep_ok);
-
-static inline int t4_wr_mbox(struct adapter *adap, int mbox, const void *cmd,
-			     int size, void *rpl)
-{
-	return t4_wr_mbox_meat(adap, mbox, cmd, size, rpl, true);
-}
-
-static inline int t4_wr_mbox_ns(struct adapter *adap, int mbox, const void *cmd,
-				int size, void *rpl)
-{
-	return t4_wr_mbox_meat(adap, mbox, cmd, size, rpl, false);
-}
-
-void t4_intr_enable(struct adapter *adapter);
-void t4_intr_disable(struct adapter *adapter);
-int t4_slow_intr_handler(struct adapter *adapter);
-
-int t4_wait_dev_ready(struct adapter *adap);
-int t4_link_start(struct adapter *adap, unsigned int mbox, unsigned int port,
-		  struct link_config *lc);
-int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port);
-int t4_seeprom_wp(struct adapter *adapter, bool enable);
-int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
-int t4_check_fw_version(struct adapter *adapter);
-int t4_prep_adapter(struct adapter *adapter);
-int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
-void t4_fatal_err(struct adapter *adapter);
-int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
-			int start, int n, const u16 *rspq, unsigned int nrspq);
-int t4_config_glbl_rss(struct adapter *adapter, int mbox, unsigned int mode,
-		       unsigned int flags);
-int t4_mc_read(struct adapter *adap, u32 addr, __be32 *data, u64 *parity);
-int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data,
-		u64 *parity);
-
-void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p);
-void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log);
-void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
-			 struct tp_tcp_stats *v6);
-void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
-		  const unsigned short *alpha, const unsigned short *beta);
-
-void t4_wol_magic_enable(struct adapter *adap, unsigned int port,
-			 const u8 *addr);
-int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
-		      u64 mask0, u64 mask1, unsigned int crc, bool enable);
-
-int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox,
-		enum dev_master master, enum dev_state *state);
-int t4_fw_bye(struct adapter *adap, unsigned int mbox);
-int t4_early_init(struct adapter *adap, unsigned int mbox);
-int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset);
-int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
-		    unsigned int vf, unsigned int nparams, const u32 *params,
-		    u32 *val);
-int t4_set_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
-		  unsigned int vf, unsigned int nparams, const u32 *params,
-		  const u32 *val);
-int t4_cfg_pfvf(struct adapter *adap, unsigned int mbox, unsigned int pf,
-		unsigned int vf, unsigned int txq, unsigned int txq_eth_ctrl,
-		unsigned int rxqi, unsigned int rxq, unsigned int tc,
-		unsigned int vi, unsigned int cmask, unsigned int pmask,
-		unsigned int nexact, unsigned int rcaps, unsigned int wxcaps);
-int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port,
-		unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac,
-		unsigned int *rss_size);
-int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid,
-		int mtu, int promisc, int all_multi, int bcast, int vlanex,
-		bool sleep_ok);
-int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
-		      unsigned int viid, bool free, unsigned int naddr,
-		      const u8 **addr, u16 *idx, u64 *hash, bool sleep_ok);
-int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid,
-		  int idx, const u8 *addr, bool persist, bool add_smt);
-int t4_set_addr_hash(struct adapter *adap, unsigned int mbox, unsigned int viid,
-		     bool ucast, u64 vec, bool sleep_ok);
-int t4_enable_vi(struct adapter *adap, unsigned int mbox, unsigned int viid,
-		 bool rx_en, bool tx_en);
-int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid,
-		     unsigned int nblinks);
-int t4_mdio_rd(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
-	       unsigned int mmd, unsigned int reg, u16 *valp);
-int t4_mdio_wr(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
-	       unsigned int mmd, unsigned int reg, u16 val);
-int t4_iq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
-	       unsigned int vf, unsigned int iqtype, unsigned int iqid,
-	       unsigned int fl0id, unsigned int fl1id);
-int t4_eth_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
-		   unsigned int vf, unsigned int eqid);
-int t4_ctrl_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
-		    unsigned int vf, unsigned int eqid);
-int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
-		    unsigned int vf, unsigned int eqid);
-int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
-#endif /* __CXGB4_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4/cxgb4_main.c linux-libre-3.2-gnu/drivers/net/cxgb4/cxgb4_main.c
--- linux-libre-3.1-gnu/drivers/net/cxgb4/cxgb4_main.c	2012-03-19 21:44:06.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4/cxgb4_main.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3809 +0,0 @@
-/*
- * This file is part of the Chelsio T4 Ethernet driver for Linux.
- *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/bitmap.h>
-#include <linux/crc32.h>
-#include <linux/ctype.h>
-#include <linux/debugfs.h>
-#include <linux/err.h>
-#include <linux/etherdevice.h>
-#include <linux/firmware.h>
-#include <linux/if_vlan.h>
-#include <linux/init.h>
-#include <linux/log2.h>
-#include <linux/mdio.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/mutex.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/aer.h>
-#include <linux/rtnetlink.h>
-#include <linux/sched.h>
-#include <linux/seq_file.h>
-#include <linux/sockios.h>
-#include <linux/vmalloc.h>
-#include <linux/workqueue.h>
-#include <net/neighbour.h>
-#include <net/netevent.h>
-#include <asm/uaccess.h>
-
-#include "cxgb4.h"
-#include "t4_regs.h"
-#include "t4_msg.h"
-#include "t4fw_api.h"
-#include "l2t.h"
-
-#define DRV_VERSION "1.3.0-ko"
-#define DRV_DESC "Chelsio T4 Network Driver"
-
-/*
- * Max interrupt hold-off timer value in us.  Queues fall back to this value
- * under extreme memory pressure so it's largish to give the system time to
- * recover.
- */
-#define MAX_SGE_TIMERVAL 200U
-
-#ifdef CONFIG_PCI_IOV
-/*
- * Virtual Function provisioning constants.  We need two extra Ingress Queues
- * with Interrupt capability to serve as the VF's Firmware Event Queue and
- * Forwarded Interrupt Queue (when using MSI mode) -- neither will have Free
- * Lists associated with them).  For each Ethernet/Control Egress Queue and
- * for each Free List, we need an Egress Context.
- */
-enum {
-	VFRES_NPORTS = 1,		/* # of "ports" per VF */
-	VFRES_NQSETS = 2,		/* # of "Queue Sets" per VF */
-
-	VFRES_NVI = VFRES_NPORTS,	/* # of Virtual Interfaces */
-	VFRES_NETHCTRL = VFRES_NQSETS,	/* # of EQs used for ETH or CTRL Qs */
-	VFRES_NIQFLINT = VFRES_NQSETS+2,/* # of ingress Qs/w Free List(s)/intr */
-	VFRES_NIQ = 0,			/* # of non-fl/int ingress queues */
-	VFRES_NEQ = VFRES_NQSETS*2,	/* # of egress queues */
-	VFRES_TC = 0,			/* PCI-E traffic class */
-	VFRES_NEXACTF = 16,		/* # of exact MPS filters */
-
-	VFRES_R_CAPS = FW_CMD_CAP_DMAQ|FW_CMD_CAP_VF|FW_CMD_CAP_PORT,
-	VFRES_WX_CAPS = FW_CMD_CAP_DMAQ|FW_CMD_CAP_VF,
-};
-
-/*
- * Provide a Port Access Rights Mask for the specified PF/VF.  This is very
- * static and likely not to be useful in the long run.  We really need to
- * implement some form of persistent configuration which the firmware
- * controls.
- */
-static unsigned int pfvfres_pmask(struct adapter *adapter,
-				  unsigned int pf, unsigned int vf)
-{
-	unsigned int portn, portvec;
-
-	/*
-	 * Give PF's access to all of the ports.
-	 */
-	if (vf == 0)
-		return FW_PFVF_CMD_PMASK_MASK;
-
-	/*
-	 * For VFs, we'll assign them access to the ports based purely on the
-	 * PF.  We assign active ports in order, wrapping around if there are
-	 * fewer active ports than PFs: e.g. active port[pf % nports].
-	 * Unfortunately the adapter's port_info structs haven't been
-	 * initialized yet so we have to compute this.
-	 */
-	if (adapter->params.nports == 0)
-		return 0;
-
-	portn = pf % adapter->params.nports;
-	portvec = adapter->params.portvec;
-	for (;;) {
-		/*
-		 * Isolate the lowest set bit in the port vector.  If we're at
-		 * the port number that we want, return that as the pmask.
-		 * otherwise mask that bit out of the port vector and
-		 * decrement our port number ...
-		 */
-		unsigned int pmask = portvec ^ (portvec & (portvec-1));
-		if (portn == 0)
-			return pmask;
-		portn--;
-		portvec &= ~pmask;
-	}
-	/*NOTREACHED*/
-}
-#endif
-
-enum {
-	MEMWIN0_APERTURE = 65536,
-	MEMWIN0_BASE     = 0x30000,
-	MEMWIN1_APERTURE = 32768,
-	MEMWIN1_BASE     = 0x28000,
-	MEMWIN2_APERTURE = 2048,
-	MEMWIN2_BASE     = 0x1b800,
-};
-
-enum {
-	MAX_TXQ_ENTRIES      = 16384,
-	MAX_CTRL_TXQ_ENTRIES = 1024,
-	MAX_RSPQ_ENTRIES     = 16384,
-	MAX_RX_BUFFERS       = 16384,
-	MIN_TXQ_ENTRIES      = 32,
-	MIN_CTRL_TXQ_ENTRIES = 32,
-	MIN_RSPQ_ENTRIES     = 128,
-	MIN_FL_ENTRIES       = 16
-};
-
-#define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \
-			 NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\
-			 NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
-
-#define CH_DEVICE(devid, data) { PCI_VDEVICE(CHELSIO, devid), (data) }
-
-static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
-	CH_DEVICE(0xa000, 0),  /* PE10K */
-	CH_DEVICE(0x4001, -1),
-	CH_DEVICE(0x4002, -1),
-	CH_DEVICE(0x4003, -1),
-	CH_DEVICE(0x4004, -1),
-	CH_DEVICE(0x4005, -1),
-	CH_DEVICE(0x4006, -1),
-	CH_DEVICE(0x4007, -1),
-	CH_DEVICE(0x4008, -1),
-	CH_DEVICE(0x4009, -1),
-	CH_DEVICE(0x400a, -1),
-	CH_DEVICE(0x4401, 4),
-	CH_DEVICE(0x4402, 4),
-	CH_DEVICE(0x4403, 4),
-	CH_DEVICE(0x4404, 4),
-	CH_DEVICE(0x4405, 4),
-	CH_DEVICE(0x4406, 4),
-	CH_DEVICE(0x4407, 4),
-	CH_DEVICE(0x4408, 4),
-	CH_DEVICE(0x4409, 4),
-	CH_DEVICE(0x440a, 4),
-	{ 0, }
-};
-
-#define FW_FNAME "/*(DEBLOBBED)*/"
-
-MODULE_DESCRIPTION(DRV_DESC);
-MODULE_AUTHOR("Chelsio Communications");
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_VERSION(DRV_VERSION);
-MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl);
-/*(DEBLOBBED)*/
-
-static int dflt_msg_enable = DFLT_MSG_ENABLE;
-
-module_param(dflt_msg_enable, int, 0644);
-MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T4 default message enable bitmap");
-
-/*
- * The driver uses the best interrupt scheme available on a platform in the
- * order MSI-X, MSI, legacy INTx interrupts.  This parameter determines which
- * of these schemes the driver may consider as follows:
- *
- * msi = 2: choose from among all three options
- * msi = 1: only consider MSI and INTx interrupts
- * msi = 0: force INTx interrupts
- */
-static int msi = 2;
-
-module_param(msi, int, 0644);
-MODULE_PARM_DESC(msi, "whether to use INTx (0), MSI (1) or MSI-X (2)");
-
-/*
- * Queue interrupt hold-off timer values.  Queues default to the first of these
- * upon creation.
- */
-static unsigned int intr_holdoff[SGE_NTIMERS - 1] = { 5, 10, 20, 50, 100 };
-
-module_param_array(intr_holdoff, uint, NULL, 0644);
-MODULE_PARM_DESC(intr_holdoff, "values for queue interrupt hold-off timers "
-		 "0..4 in microseconds");
-
-static unsigned int intr_cnt[SGE_NCOUNTERS - 1] = { 4, 8, 16 };
-
-module_param_array(intr_cnt, uint, NULL, 0644);
-MODULE_PARM_DESC(intr_cnt,
-		 "thresholds 1..3 for queue interrupt packet counters");
-
-static int vf_acls;
-
-#ifdef CONFIG_PCI_IOV
-module_param(vf_acls, bool, 0644);
-MODULE_PARM_DESC(vf_acls, "if set enable virtualization L2 ACL enforcement");
-
-static unsigned int num_vf[4];
-
-module_param_array(num_vf, uint, NULL, 0644);
-MODULE_PARM_DESC(num_vf, "number of VFs for each of PFs 0-3");
-#endif
-
-static struct dentry *cxgb4_debugfs_root;
-
-static LIST_HEAD(adapter_list);
-static DEFINE_MUTEX(uld_mutex);
-static struct cxgb4_uld_info ulds[CXGB4_ULD_MAX];
-static const char *uld_str[] = { "RDMA", "iSCSI" };
-
-static void link_report(struct net_device *dev)
-{
-	if (!netif_carrier_ok(dev))
-		netdev_info(dev, "link down\n");
-	else {
-		static const char *fc[] = { "no", "Rx", "Tx", "Tx/Rx" };
-
-		const char *s = "10Mbps";
-		const struct port_info *p = netdev_priv(dev);
-
-		switch (p->link_cfg.speed) {
-		case SPEED_10000:
-			s = "10Gbps";
-			break;
-		case SPEED_1000:
-			s = "1000Mbps";
-			break;
-		case SPEED_100:
-			s = "100Mbps";
-			break;
-		}
-
-		netdev_info(dev, "link up, %s, full-duplex, %s PAUSE\n", s,
-			    fc[p->link_cfg.fc]);
-	}
-}
-
-void t4_os_link_changed(struct adapter *adapter, int port_id, int link_stat)
-{
-	struct net_device *dev = adapter->port[port_id];
-
-	/* Skip changes from disabled ports. */
-	if (netif_running(dev) && link_stat != netif_carrier_ok(dev)) {
-		if (link_stat)
-			netif_carrier_on(dev);
-		else
-			netif_carrier_off(dev);
-
-		link_report(dev);
-	}
-}
-
-void t4_os_portmod_changed(const struct adapter *adap, int port_id)
-{
-	static const char *mod_str[] = {
-		NULL, "LR", "SR", "ER", "passive DA", "active DA", "LRM"
-	};
-
-	const struct net_device *dev = adap->port[port_id];
-	const struct port_info *pi = netdev_priv(dev);
-
-	if (pi->mod_type == FW_PORT_MOD_TYPE_NONE)
-		netdev_info(dev, "port module unplugged\n");
-	else if (pi->mod_type < ARRAY_SIZE(mod_str))
-		netdev_info(dev, "%s module inserted\n", mod_str[pi->mod_type]);
-}
-
-/*
- * Configure the exact and hash address filters to handle a port's multicast
- * and secondary unicast MAC addresses.
- */
-static int set_addr_filters(const struct net_device *dev, bool sleep)
-{
-	u64 mhash = 0;
-	u64 uhash = 0;
-	bool free = true;
-	u16 filt_idx[7];
-	const u8 *addr[7];
-	int ret, naddr = 0;
-	const struct netdev_hw_addr *ha;
-	int uc_cnt = netdev_uc_count(dev);
-	int mc_cnt = netdev_mc_count(dev);
-	const struct port_info *pi = netdev_priv(dev);
-	unsigned int mb = pi->adapter->fn;
-
-	/* first do the secondary unicast addresses */
-	netdev_for_each_uc_addr(ha, dev) {
-		addr[naddr++] = ha->addr;
-		if (--uc_cnt == 0 || naddr >= ARRAY_SIZE(addr)) {
-			ret = t4_alloc_mac_filt(pi->adapter, mb, pi->viid, free,
-					naddr, addr, filt_idx, &uhash, sleep);
-			if (ret < 0)
-				return ret;
-
-			free = false;
-			naddr = 0;
-		}
-	}
-
-	/* next set up the multicast addresses */
-	netdev_for_each_mc_addr(ha, dev) {
-		addr[naddr++] = ha->addr;
-		if (--mc_cnt == 0 || naddr >= ARRAY_SIZE(addr)) {
-			ret = t4_alloc_mac_filt(pi->adapter, mb, pi->viid, free,
-					naddr, addr, filt_idx, &mhash, sleep);
-			if (ret < 0)
-				return ret;
-
-			free = false;
-			naddr = 0;
-		}
-	}
-
-	return t4_set_addr_hash(pi->adapter, mb, pi->viid, uhash != 0,
-				uhash | mhash, sleep);
-}
-
-/*
- * Set Rx properties of a port, such as promiscruity, address filters, and MTU.
- * If @mtu is -1 it is left unchanged.
- */
-static int set_rxmode(struct net_device *dev, int mtu, bool sleep_ok)
-{
-	int ret;
-	struct port_info *pi = netdev_priv(dev);
-
-	ret = set_addr_filters(dev, sleep_ok);
-	if (ret == 0)
-		ret = t4_set_rxmode(pi->adapter, pi->adapter->fn, pi->viid, mtu,
-				    (dev->flags & IFF_PROMISC) ? 1 : 0,
-				    (dev->flags & IFF_ALLMULTI) ? 1 : 0, 1, -1,
-				    sleep_ok);
-	return ret;
-}
-
-/**
- *	link_start - enable a port
- *	@dev: the port to enable
- *
- *	Performs the MAC and PHY actions needed to enable a port.
- */
-static int link_start(struct net_device *dev)
-{
-	int ret;
-	struct port_info *pi = netdev_priv(dev);
-	unsigned int mb = pi->adapter->fn;
-
-	/*
-	 * We do not set address filters and promiscuity here, the stack does
-	 * that step explicitly.
-	 */
-	ret = t4_set_rxmode(pi->adapter, mb, pi->viid, dev->mtu, -1, -1, -1,
-			    !!(dev->features & NETIF_F_HW_VLAN_RX), true);
-	if (ret == 0) {
-		ret = t4_change_mac(pi->adapter, mb, pi->viid,
-				    pi->xact_addr_filt, dev->dev_addr, true,
-				    true);
-		if (ret >= 0) {
-			pi->xact_addr_filt = ret;
-			ret = 0;
-		}
-	}
-	if (ret == 0)
-		ret = t4_link_start(pi->adapter, mb, pi->tx_chan,
-				    &pi->link_cfg);
-	if (ret == 0)
-		ret = t4_enable_vi(pi->adapter, mb, pi->viid, true, true);
-	return ret;
-}
-
-/*
- * Response queue handler for the FW event queue.
- */
-static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,
-			  const struct pkt_gl *gl)
-{
-	u8 opcode = ((const struct rss_header *)rsp)->opcode;
-
-	rsp++;                                          /* skip RSS header */
-	if (likely(opcode == CPL_SGE_EGR_UPDATE)) {
-		const struct cpl_sge_egr_update *p = (void *)rsp;
-		unsigned int qid = EGR_QID(ntohl(p->opcode_qid));
-		struct sge_txq *txq;
-
-		txq = q->adap->sge.egr_map[qid - q->adap->sge.egr_start];
-		txq->restarts++;
-		if ((u8 *)txq < (u8 *)q->adap->sge.ofldtxq) {
-			struct sge_eth_txq *eq;
-
-			eq = container_of(txq, struct sge_eth_txq, q);
-			netif_tx_wake_queue(eq->txq);
-		} else {
-			struct sge_ofld_txq *oq;
-
-			oq = container_of(txq, struct sge_ofld_txq, q);
-			tasklet_schedule(&oq->qresume_tsk);
-		}
-	} else if (opcode == CPL_FW6_MSG || opcode == CPL_FW4_MSG) {
-		const struct cpl_fw6_msg *p = (void *)rsp;
-
-		if (p->type == 0)
-			t4_handle_fw_rpl(q->adap, p->data);
-	} else if (opcode == CPL_L2T_WRITE_RPL) {
-		const struct cpl_l2t_write_rpl *p = (void *)rsp;
-
-		do_l2t_write_rpl(q->adap, p);
-	} else
-		dev_err(q->adap->pdev_dev,
-			"unexpected CPL %#x on FW event queue\n", opcode);
-	return 0;
-}
-
-/**
- *	uldrx_handler - response queue handler for ULD queues
- *	@q: the response queue that received the packet
- *	@rsp: the response queue descriptor holding the offload message
- *	@gl: the gather list of packet fragments
- *
- *	Deliver an ingress offload packet to a ULD.  All processing is done by
- *	the ULD, we just maintain statistics.
- */
-static int uldrx_handler(struct sge_rspq *q, const __be64 *rsp,
-			 const struct pkt_gl *gl)
-{
-	struct sge_ofld_rxq *rxq = container_of(q, struct sge_ofld_rxq, rspq);
-
-	if (ulds[q->uld].rx_handler(q->adap->uld_handle[q->uld], rsp, gl)) {
-		rxq->stats.nomem++;
-		return -1;
-	}
-	if (gl == NULL)
-		rxq->stats.imm++;
-	else if (gl == CXGB4_MSG_AN)
-		rxq->stats.an++;
-	else
-		rxq->stats.pkts++;
-	return 0;
-}
-
-static void disable_msi(struct adapter *adapter)
-{
-	if (adapter->flags & USING_MSIX) {
-		pci_disable_msix(adapter->pdev);
-		adapter->flags &= ~USING_MSIX;
-	} else if (adapter->flags & USING_MSI) {
-		pci_disable_msi(adapter->pdev);
-		adapter->flags &= ~USING_MSI;
-	}
-}
-
-/*
- * Interrupt handler for non-data events used with MSI-X.
- */
-static irqreturn_t t4_nondata_intr(int irq, void *cookie)
-{
-	struct adapter *adap = cookie;
-
-	u32 v = t4_read_reg(adap, MYPF_REG(PL_PF_INT_CAUSE));
-	if (v & PFSW) {
-		adap->swintr = 1;
-		t4_write_reg(adap, MYPF_REG(PL_PF_INT_CAUSE), v);
-	}
-	t4_slow_intr_handler(adap);
-	return IRQ_HANDLED;
-}
-
-/*
- * Name the MSI-X interrupts.
- */
-static void name_msix_vecs(struct adapter *adap)
-{
-	int i, j, msi_idx = 2, n = sizeof(adap->msix_info[0].desc);
-
-	/* non-data interrupts */
-	snprintf(adap->msix_info[0].desc, n, "%s", adap->port[0]->name);
-
-	/* FW events */
-	snprintf(adap->msix_info[1].desc, n, "%s-FWeventq",
-		 adap->port[0]->name);
-
-	/* Ethernet queues */
-	for_each_port(adap, j) {
-		struct net_device *d = adap->port[j];
-		const struct port_info *pi = netdev_priv(d);
-
-		for (i = 0; i < pi->nqsets; i++, msi_idx++)
-			snprintf(adap->msix_info[msi_idx].desc, n, "%s-Rx%d",
-				 d->name, i);
-	}
-
-	/* offload queues */
-	for_each_ofldrxq(&adap->sge, i)
-		snprintf(adap->msix_info[msi_idx++].desc, n, "%s-ofld%d",
-			 adap->port[0]->name, i);
-
-	for_each_rdmarxq(&adap->sge, i)
-		snprintf(adap->msix_info[msi_idx++].desc, n, "%s-rdma%d",
-			 adap->port[0]->name, i);
-}
-
-static int request_msix_queue_irqs(struct adapter *adap)
-{
-	struct sge *s = &adap->sge;
-	int err, ethqidx, ofldqidx = 0, rdmaqidx = 0, msi = 2;
-
-	err = request_irq(adap->msix_info[1].vec, t4_sge_intr_msix, 0,
-			  adap->msix_info[1].desc, &s->fw_evtq);
-	if (err)
-		return err;
-
-	for_each_ethrxq(s, ethqidx) {
-		err = request_irq(adap->msix_info[msi].vec, t4_sge_intr_msix, 0,
-				  adap->msix_info[msi].desc,
-				  &s->ethrxq[ethqidx].rspq);
-		if (err)
-			goto unwind;
-		msi++;
-	}
-	for_each_ofldrxq(s, ofldqidx) {
-		err = request_irq(adap->msix_info[msi].vec, t4_sge_intr_msix, 0,
-				  adap->msix_info[msi].desc,
-				  &s->ofldrxq[ofldqidx].rspq);
-		if (err)
-			goto unwind;
-		msi++;
-	}
-	for_each_rdmarxq(s, rdmaqidx) {
-		err = request_irq(adap->msix_info[msi].vec, t4_sge_intr_msix, 0,
-				  adap->msix_info[msi].desc,
-				  &s->rdmarxq[rdmaqidx].rspq);
-		if (err)
-			goto unwind;
-		msi++;
-	}
-	return 0;
-
-unwind:
-	while (--rdmaqidx >= 0)
-		free_irq(adap->msix_info[--msi].vec,
-			 &s->rdmarxq[rdmaqidx].rspq);
-	while (--ofldqidx >= 0)
-		free_irq(adap->msix_info[--msi].vec,
-			 &s->ofldrxq[ofldqidx].rspq);
-	while (--ethqidx >= 0)
-		free_irq(adap->msix_info[--msi].vec, &s->ethrxq[ethqidx].rspq);
-	free_irq(adap->msix_info[1].vec, &s->fw_evtq);
-	return err;
-}
-
-static void free_msix_queue_irqs(struct adapter *adap)
-{
-	int i, msi = 2;
-	struct sge *s = &adap->sge;
-
-	free_irq(adap->msix_info[1].vec, &s->fw_evtq);
-	for_each_ethrxq(s, i)
-		free_irq(adap->msix_info[msi++].vec, &s->ethrxq[i].rspq);
-	for_each_ofldrxq(s, i)
-		free_irq(adap->msix_info[msi++].vec, &s->ofldrxq[i].rspq);
-	for_each_rdmarxq(s, i)
-		free_irq(adap->msix_info[msi++].vec, &s->rdmarxq[i].rspq);
-}
-
-/**
- *	write_rss - write the RSS table for a given port
- *	@pi: the port
- *	@queues: array of queue indices for RSS
- *
- *	Sets up the portion of the HW RSS table for the port's VI to distribute
- *	packets to the Rx queues in @queues.
- */
-static int write_rss(const struct port_info *pi, const u16 *queues)
-{
-	u16 *rss;
-	int i, err;
-	const struct sge_eth_rxq *q = &pi->adapter->sge.ethrxq[pi->first_qset];
-
-	rss = kmalloc(pi->rss_size * sizeof(u16), GFP_KERNEL);
-	if (!rss)
-		return -ENOMEM;
-
-	/* map the queue indices to queue ids */
-	for (i = 0; i < pi->rss_size; i++, queues++)
-		rss[i] = q[*queues].rspq.abs_id;
-
-	err = t4_config_rss_range(pi->adapter, pi->adapter->fn, pi->viid, 0,
-				  pi->rss_size, rss, pi->rss_size);
-	kfree(rss);
-	return err;
-}
-
-/**
- *	setup_rss - configure RSS
- *	@adap: the adapter
- *
- *	Sets up RSS for each port.
- */
-static int setup_rss(struct adapter *adap)
-{
-	int i, err;
-
-	for_each_port(adap, i) {
-		const struct port_info *pi = adap2pinfo(adap, i);
-
-		err = write_rss(pi, pi->rss);
-		if (err)
-			return err;
-	}
-	return 0;
-}
-
-/*
- * Return the channel of the ingress queue with the given qid.
- */
-static unsigned int rxq_to_chan(const struct sge *p, unsigned int qid)
-{
-	qid -= p->ingr_start;
-	return netdev2pinfo(p->ingr_map[qid]->netdev)->tx_chan;
-}
-
-/*
- * Wait until all NAPI handlers are descheduled.
- */
-static void quiesce_rx(struct adapter *adap)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(adap->sge.ingr_map); i++) {
-		struct sge_rspq *q = adap->sge.ingr_map[i];
-
-		if (q && q->handler)
-			napi_disable(&q->napi);
-	}
-}
-
-/*
- * Enable NAPI scheduling and interrupt generation for all Rx queues.
- */
-static void enable_rx(struct adapter *adap)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(adap->sge.ingr_map); i++) {
-		struct sge_rspq *q = adap->sge.ingr_map[i];
-
-		if (!q)
-			continue;
-		if (q->handler)
-			napi_enable(&q->napi);
-		/* 0-increment GTS to start the timer and enable interrupts */
-		t4_write_reg(adap, MYPF_REG(SGE_PF_GTS),
-			     SEINTARM(q->intr_params) |
-			     INGRESSQID(q->cntxt_id));
-	}
-}
-
-/**
- *	setup_sge_queues - configure SGE Tx/Rx/response queues
- *	@adap: the adapter
- *
- *	Determines how many sets of SGE queues to use and initializes them.
- *	We support multiple queue sets per port if we have MSI-X, otherwise
- *	just one queue set per port.
- */
-static int setup_sge_queues(struct adapter *adap)
-{
-	int err, msi_idx, i, j;
-	struct sge *s = &adap->sge;
-
-	bitmap_zero(s->starving_fl, MAX_EGRQ);
-	bitmap_zero(s->txq_maperr, MAX_EGRQ);
-
-	if (adap->flags & USING_MSIX)
-		msi_idx = 1;         /* vector 0 is for non-queue interrupts */
-	else {
-		err = t4_sge_alloc_rxq(adap, &s->intrq, false, adap->port[0], 0,
-				       NULL, NULL);
-		if (err)
-			return err;
-		msi_idx = -((int)s->intrq.abs_id + 1);
-	}
-
-	err = t4_sge_alloc_rxq(adap, &s->fw_evtq, true, adap->port[0],
-			       msi_idx, NULL, fwevtq_handler);
-	if (err) {
-freeout:	t4_free_sge_resources(adap);
-		return err;
-	}
-
-	for_each_port(adap, i) {
-		struct net_device *dev = adap->port[i];
-		struct port_info *pi = netdev_priv(dev);
-		struct sge_eth_rxq *q = &s->ethrxq[pi->first_qset];
-		struct sge_eth_txq *t = &s->ethtxq[pi->first_qset];
-
-		for (j = 0; j < pi->nqsets; j++, q++) {
-			if (msi_idx > 0)
-				msi_idx++;
-			err = t4_sge_alloc_rxq(adap, &q->rspq, false, dev,
-					       msi_idx, &q->fl,
-					       t4_ethrx_handler);
-			if (err)
-				goto freeout;
-			q->rspq.idx = j;
-			memset(&q->stats, 0, sizeof(q->stats));
-		}
-		for (j = 0; j < pi->nqsets; j++, t++) {
-			err = t4_sge_alloc_eth_txq(adap, t, dev,
-					netdev_get_tx_queue(dev, j),
-					s->fw_evtq.cntxt_id);
-			if (err)
-				goto freeout;
-		}
-	}
-
-	j = s->ofldqsets / adap->params.nports; /* ofld queues per channel */
-	for_each_ofldrxq(s, i) {
-		struct sge_ofld_rxq *q = &s->ofldrxq[i];
-		struct net_device *dev = adap->port[i / j];
-
-		if (msi_idx > 0)
-			msi_idx++;
-		err = t4_sge_alloc_rxq(adap, &q->rspq, false, dev, msi_idx,
-				       &q->fl, uldrx_handler);
-		if (err)
-			goto freeout;
-		memset(&q->stats, 0, sizeof(q->stats));
-		s->ofld_rxq[i] = q->rspq.abs_id;
-		err = t4_sge_alloc_ofld_txq(adap, &s->ofldtxq[i], dev,
-					    s->fw_evtq.cntxt_id);
-		if (err)
-			goto freeout;
-	}
-
-	for_each_rdmarxq(s, i) {
-		struct sge_ofld_rxq *q = &s->rdmarxq[i];
-
-		if (msi_idx > 0)
-			msi_idx++;
-		err = t4_sge_alloc_rxq(adap, &q->rspq, false, adap->port[i],
-				       msi_idx, &q->fl, uldrx_handler);
-		if (err)
-			goto freeout;
-		memset(&q->stats, 0, sizeof(q->stats));
-		s->rdma_rxq[i] = q->rspq.abs_id;
-	}
-
-	for_each_port(adap, i) {
-		/*
-		 * Note that ->rdmarxq[i].rspq.cntxt_id below is 0 if we don't
-		 * have RDMA queues, and that's the right value.
-		 */
-		err = t4_sge_alloc_ctrl_txq(adap, &s->ctrlq[i], adap->port[i],
-					    s->fw_evtq.cntxt_id,
-					    s->rdmarxq[i].rspq.cntxt_id);
-		if (err)
-			goto freeout;
-	}
-
-	t4_write_reg(adap, MPS_TRC_RSS_CONTROL,
-		     RSSCONTROL(netdev2pinfo(adap->port[0])->tx_chan) |
-		     QUEUENUMBER(s->ethrxq[0].rspq.abs_id));
-	return 0;
-}
-
-/*
- * Returns 0 if new FW was successfully loaded, a positive errno if a load was
- * started but failed, and a negative errno if flash load couldn't start.
- */
-static int upgrade_fw(struct adapter *adap)
-{
-	int ret;
-	u32 vers;
-	const struct fw_hdr *hdr;
-	const struct firmware *fw;
-	struct device *dev = adap->pdev_dev;
-
-	ret = reject_firmware(&fw, FW_FNAME, dev);
-	if (ret < 0) {
-		dev_err(dev, "unable to load firmware image " FW_FNAME
-			", error %d\n", ret);
-		return ret;
-	}
-
-	hdr = (const struct fw_hdr *)fw->data;
-	vers = ntohl(hdr->fw_ver);
-	if (FW_HDR_FW_VER_MAJOR_GET(vers) != FW_VERSION_MAJOR) {
-		ret = -EINVAL;              /* wrong major version, won't do */
-		goto out;
-	}
-
-	/*
-	 * If the flash FW is unusable or we found something newer, load it.
-	 */
-	if (FW_HDR_FW_VER_MAJOR_GET(adap->params.fw_vers) != FW_VERSION_MAJOR ||
-	    vers > adap->params.fw_vers) {
-		ret = -t4_load_fw(adap, fw->data, fw->size);
-		if (!ret)
-			dev_info(dev, "firmware upgraded to version %pI4 from "
-				 FW_FNAME "\n", &hdr->fw_ver);
-	}
-out:	release_firmware(fw);
-	return ret;
-}
-
-/*
- * Allocate a chunk of memory using kmalloc or, if that fails, vmalloc.
- * The allocated memory is cleared.
- */
-void *t4_alloc_mem(size_t size)
-{
-	void *p = kzalloc(size, GFP_KERNEL);
-
-	if (!p)
-		p = vzalloc(size);
-	return p;
-}
-
-/*
- * Free memory allocated through alloc_mem().
- */
-static void t4_free_mem(void *addr)
-{
-	if (is_vmalloc_addr(addr))
-		vfree(addr);
-	else
-		kfree(addr);
-}
-
-static inline int is_offload(const struct adapter *adap)
-{
-	return adap->params.offload;
-}
-
-/*
- * Implementation of ethtool operations.
- */
-
-static u32 get_msglevel(struct net_device *dev)
-{
-	return netdev2adap(dev)->msg_enable;
-}
-
-static void set_msglevel(struct net_device *dev, u32 val)
-{
-	netdev2adap(dev)->msg_enable = val;
-}
-
-static char stats_strings[][ETH_GSTRING_LEN] = {
-	"TxOctetsOK         ",
-	"TxFramesOK         ",
-	"TxBroadcastFrames  ",
-	"TxMulticastFrames  ",
-	"TxUnicastFrames    ",
-	"TxErrorFrames      ",
-
-	"TxFrames64         ",
-	"TxFrames65To127    ",
-	"TxFrames128To255   ",
-	"TxFrames256To511   ",
-	"TxFrames512To1023  ",
-	"TxFrames1024To1518 ",
-	"TxFrames1519ToMax  ",
-
-	"TxFramesDropped    ",
-	"TxPauseFrames      ",
-	"TxPPP0Frames       ",
-	"TxPPP1Frames       ",
-	"TxPPP2Frames       ",
-	"TxPPP3Frames       ",
-	"TxPPP4Frames       ",
-	"TxPPP5Frames       ",
-	"TxPPP6Frames       ",
-	"TxPPP7Frames       ",
-
-	"RxOctetsOK         ",
-	"RxFramesOK         ",
-	"RxBroadcastFrames  ",
-	"RxMulticastFrames  ",
-	"RxUnicastFrames    ",
-
-	"RxFramesTooLong    ",
-	"RxJabberErrors     ",
-	"RxFCSErrors        ",
-	"RxLengthErrors     ",
-	"RxSymbolErrors     ",
-	"RxRuntFrames       ",
-
-	"RxFrames64         ",
-	"RxFrames65To127    ",
-	"RxFrames128To255   ",
-	"RxFrames256To511   ",
-	"RxFrames512To1023  ",
-	"RxFrames1024To1518 ",
-	"RxFrames1519ToMax  ",
-
-	"RxPauseFrames      ",
-	"RxPPP0Frames       ",
-	"RxPPP1Frames       ",
-	"RxPPP2Frames       ",
-	"RxPPP3Frames       ",
-	"RxPPP4Frames       ",
-	"RxPPP5Frames       ",
-	"RxPPP6Frames       ",
-	"RxPPP7Frames       ",
-
-	"RxBG0FramesDropped ",
-	"RxBG1FramesDropped ",
-	"RxBG2FramesDropped ",
-	"RxBG3FramesDropped ",
-	"RxBG0FramesTrunc   ",
-	"RxBG1FramesTrunc   ",
-	"RxBG2FramesTrunc   ",
-	"RxBG3FramesTrunc   ",
-
-	"TSO                ",
-	"TxCsumOffload      ",
-	"RxCsumGood         ",
-	"VLANextractions    ",
-	"VLANinsertions     ",
-	"GROpackets         ",
-	"GROmerged          ",
-};
-
-static int get_sset_count(struct net_device *dev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		return ARRAY_SIZE(stats_strings);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-#define T4_REGMAP_SIZE (160 * 1024)
-
-static int get_regs_len(struct net_device *dev)
-{
-	return T4_REGMAP_SIZE;
-}
-
-static int get_eeprom_len(struct net_device *dev)
-{
-	return EEPROMSIZE;
-}
-
-static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct adapter *adapter = netdev2adap(dev);
-
-	strcpy(info->driver, KBUILD_MODNAME);
-	strcpy(info->version, DRV_VERSION);
-	strcpy(info->bus_info, pci_name(adapter->pdev));
-
-	if (!adapter->params.fw_vers)
-		strcpy(info->fw_version, "N/A");
-	else
-		snprintf(info->fw_version, sizeof(info->fw_version),
-			"%u.%u.%u.%u, TP %u.%u.%u.%u",
-			FW_HDR_FW_VER_MAJOR_GET(adapter->params.fw_vers),
-			FW_HDR_FW_VER_MINOR_GET(adapter->params.fw_vers),
-			FW_HDR_FW_VER_MICRO_GET(adapter->params.fw_vers),
-			FW_HDR_FW_VER_BUILD_GET(adapter->params.fw_vers),
-			FW_HDR_FW_VER_MAJOR_GET(adapter->params.tp_vers),
-			FW_HDR_FW_VER_MINOR_GET(adapter->params.tp_vers),
-			FW_HDR_FW_VER_MICRO_GET(adapter->params.tp_vers),
-			FW_HDR_FW_VER_BUILD_GET(adapter->params.tp_vers));
-}
-
-static void get_strings(struct net_device *dev, u32 stringset, u8 *data)
-{
-	if (stringset == ETH_SS_STATS)
-		memcpy(data, stats_strings, sizeof(stats_strings));
-}
-
-/*
- * port stats maintained per queue of the port.  They should be in the same
- * order as in stats_strings above.
- */
-struct queue_port_stats {
-	u64 tso;
-	u64 tx_csum;
-	u64 rx_csum;
-	u64 vlan_ex;
-	u64 vlan_ins;
-	u64 gro_pkts;
-	u64 gro_merged;
-};
-
-static void collect_sge_port_stats(const struct adapter *adap,
-		const struct port_info *p, struct queue_port_stats *s)
-{
-	int i;
-	const struct sge_eth_txq *tx = &adap->sge.ethtxq[p->first_qset];
-	const struct sge_eth_rxq *rx = &adap->sge.ethrxq[p->first_qset];
-
-	memset(s, 0, sizeof(*s));
-	for (i = 0; i < p->nqsets; i++, rx++, tx++) {
-		s->tso += tx->tso;
-		s->tx_csum += tx->tx_cso;
-		s->rx_csum += rx->stats.rx_cso;
-		s->vlan_ex += rx->stats.vlan_ex;
-		s->vlan_ins += tx->vlan_ins;
-		s->gro_pkts += rx->stats.lro_pkts;
-		s->gro_merged += rx->stats.lro_merged;
-	}
-}
-
-static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
-		      u64 *data)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-
-	t4_get_port_stats(adapter, pi->tx_chan, (struct port_stats *)data);
-
-	data += sizeof(struct port_stats) / sizeof(u64);
-	collect_sge_port_stats(adapter, pi, (struct queue_port_stats *)data);
-}
-
-/*
- * Return a version number to identify the type of adapter.  The scheme is:
- * - bits 0..9: chip version
- * - bits 10..15: chip revision
- * - bits 16..23: register dump version
- */
-static inline unsigned int mk_adap_vers(const struct adapter *ap)
-{
-	return 4 | (ap->params.rev << 10) | (1 << 16);
-}
-
-static void reg_block_dump(struct adapter *ap, void *buf, unsigned int start,
-			   unsigned int end)
-{
-	u32 *p = buf + start;
-
-	for ( ; start <= end; start += sizeof(u32))
-		*p++ = t4_read_reg(ap, start);
-}
-
-static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
-		     void *buf)
-{
-	static const unsigned int reg_ranges[] = {
-		0x1008, 0x1108,
-		0x1180, 0x11b4,
-		0x11fc, 0x123c,
-		0x1300, 0x173c,
-		0x1800, 0x18fc,
-		0x3000, 0x30d8,
-		0x30e0, 0x5924,
-		0x5960, 0x59d4,
-		0x5a00, 0x5af8,
-		0x6000, 0x6098,
-		0x6100, 0x6150,
-		0x6200, 0x6208,
-		0x6240, 0x6248,
-		0x6280, 0x6338,
-		0x6370, 0x638c,
-		0x6400, 0x643c,
-		0x6500, 0x6524,
-		0x6a00, 0x6a38,
-		0x6a60, 0x6a78,
-		0x6b00, 0x6b84,
-		0x6bf0, 0x6c84,
-		0x6cf0, 0x6d84,
-		0x6df0, 0x6e84,
-		0x6ef0, 0x6f84,
-		0x6ff0, 0x7084,
-		0x70f0, 0x7184,
-		0x71f0, 0x7284,
-		0x72f0, 0x7384,
-		0x73f0, 0x7450,
-		0x7500, 0x7530,
-		0x7600, 0x761c,
-		0x7680, 0x76cc,
-		0x7700, 0x7798,
-		0x77c0, 0x77fc,
-		0x7900, 0x79fc,
-		0x7b00, 0x7c38,
-		0x7d00, 0x7efc,
-		0x8dc0, 0x8e1c,
-		0x8e30, 0x8e78,
-		0x8ea0, 0x8f6c,
-		0x8fc0, 0x9074,
-		0x90fc, 0x90fc,
-		0x9400, 0x9458,
-		0x9600, 0x96bc,
-		0x9800, 0x9808,
-		0x9820, 0x983c,
-		0x9850, 0x9864,
-		0x9c00, 0x9c6c,
-		0x9c80, 0x9cec,
-		0x9d00, 0x9d6c,
-		0x9d80, 0x9dec,
-		0x9e00, 0x9e6c,
-		0x9e80, 0x9eec,
-		0x9f00, 0x9f6c,
-		0x9f80, 0x9fec,
-		0xd004, 0xd03c,
-		0xdfc0, 0xdfe0,
-		0xe000, 0xea7c,
-		0xf000, 0x11190,
-		0x19040, 0x1906c,
-		0x19078, 0x19080,
-		0x1908c, 0x19124,
-		0x19150, 0x191b0,
-		0x191d0, 0x191e8,
-		0x19238, 0x1924c,
-		0x193f8, 0x19474,
-		0x19490, 0x194f8,
-		0x19800, 0x19f30,
-		0x1a000, 0x1a06c,
-		0x1a0b0, 0x1a120,
-		0x1a128, 0x1a138,
-		0x1a190, 0x1a1c4,
-		0x1a1fc, 0x1a1fc,
-		0x1e040, 0x1e04c,
-		0x1e284, 0x1e28c,
-		0x1e2c0, 0x1e2c0,
-		0x1e2e0, 0x1e2e0,
-		0x1e300, 0x1e384,
-		0x1e3c0, 0x1e3c8,
-		0x1e440, 0x1e44c,
-		0x1e684, 0x1e68c,
-		0x1e6c0, 0x1e6c0,
-		0x1e6e0, 0x1e6e0,
-		0x1e700, 0x1e784,
-		0x1e7c0, 0x1e7c8,
-		0x1e840, 0x1e84c,
-		0x1ea84, 0x1ea8c,
-		0x1eac0, 0x1eac0,
-		0x1eae0, 0x1eae0,
-		0x1eb00, 0x1eb84,
-		0x1ebc0, 0x1ebc8,
-		0x1ec40, 0x1ec4c,
-		0x1ee84, 0x1ee8c,
-		0x1eec0, 0x1eec0,
-		0x1eee0, 0x1eee0,
-		0x1ef00, 0x1ef84,
-		0x1efc0, 0x1efc8,
-		0x1f040, 0x1f04c,
-		0x1f284, 0x1f28c,
-		0x1f2c0, 0x1f2c0,
-		0x1f2e0, 0x1f2e0,
-		0x1f300, 0x1f384,
-		0x1f3c0, 0x1f3c8,
-		0x1f440, 0x1f44c,
-		0x1f684, 0x1f68c,
-		0x1f6c0, 0x1f6c0,
-		0x1f6e0, 0x1f6e0,
-		0x1f700, 0x1f784,
-		0x1f7c0, 0x1f7c8,
-		0x1f840, 0x1f84c,
-		0x1fa84, 0x1fa8c,
-		0x1fac0, 0x1fac0,
-		0x1fae0, 0x1fae0,
-		0x1fb00, 0x1fb84,
-		0x1fbc0, 0x1fbc8,
-		0x1fc40, 0x1fc4c,
-		0x1fe84, 0x1fe8c,
-		0x1fec0, 0x1fec0,
-		0x1fee0, 0x1fee0,
-		0x1ff00, 0x1ff84,
-		0x1ffc0, 0x1ffc8,
-		0x20000, 0x2002c,
-		0x20100, 0x2013c,
-		0x20190, 0x201c8,
-		0x20200, 0x20318,
-		0x20400, 0x20528,
-		0x20540, 0x20614,
-		0x21000, 0x21040,
-		0x2104c, 0x21060,
-		0x210c0, 0x210ec,
-		0x21200, 0x21268,
-		0x21270, 0x21284,
-		0x212fc, 0x21388,
-		0x21400, 0x21404,
-		0x21500, 0x21518,
-		0x2152c, 0x2153c,
-		0x21550, 0x21554,
-		0x21600, 0x21600,
-		0x21608, 0x21628,
-		0x21630, 0x2163c,
-		0x21700, 0x2171c,
-		0x21780, 0x2178c,
-		0x21800, 0x21c38,
-		0x21c80, 0x21d7c,
-		0x21e00, 0x21e04,
-		0x22000, 0x2202c,
-		0x22100, 0x2213c,
-		0x22190, 0x221c8,
-		0x22200, 0x22318,
-		0x22400, 0x22528,
-		0x22540, 0x22614,
-		0x23000, 0x23040,
-		0x2304c, 0x23060,
-		0x230c0, 0x230ec,
-		0x23200, 0x23268,
-		0x23270, 0x23284,
-		0x232fc, 0x23388,
-		0x23400, 0x23404,
-		0x23500, 0x23518,
-		0x2352c, 0x2353c,
-		0x23550, 0x23554,
-		0x23600, 0x23600,
-		0x23608, 0x23628,
-		0x23630, 0x2363c,
-		0x23700, 0x2371c,
-		0x23780, 0x2378c,
-		0x23800, 0x23c38,
-		0x23c80, 0x23d7c,
-		0x23e00, 0x23e04,
-		0x24000, 0x2402c,
-		0x24100, 0x2413c,
-		0x24190, 0x241c8,
-		0x24200, 0x24318,
-		0x24400, 0x24528,
-		0x24540, 0x24614,
-		0x25000, 0x25040,
-		0x2504c, 0x25060,
-		0x250c0, 0x250ec,
-		0x25200, 0x25268,
-		0x25270, 0x25284,
-		0x252fc, 0x25388,
-		0x25400, 0x25404,
-		0x25500, 0x25518,
-		0x2552c, 0x2553c,
-		0x25550, 0x25554,
-		0x25600, 0x25600,
-		0x25608, 0x25628,
-		0x25630, 0x2563c,
-		0x25700, 0x2571c,
-		0x25780, 0x2578c,
-		0x25800, 0x25c38,
-		0x25c80, 0x25d7c,
-		0x25e00, 0x25e04,
-		0x26000, 0x2602c,
-		0x26100, 0x2613c,
-		0x26190, 0x261c8,
-		0x26200, 0x26318,
-		0x26400, 0x26528,
-		0x26540, 0x26614,
-		0x27000, 0x27040,
-		0x2704c, 0x27060,
-		0x270c0, 0x270ec,
-		0x27200, 0x27268,
-		0x27270, 0x27284,
-		0x272fc, 0x27388,
-		0x27400, 0x27404,
-		0x27500, 0x27518,
-		0x2752c, 0x2753c,
-		0x27550, 0x27554,
-		0x27600, 0x27600,
-		0x27608, 0x27628,
-		0x27630, 0x2763c,
-		0x27700, 0x2771c,
-		0x27780, 0x2778c,
-		0x27800, 0x27c38,
-		0x27c80, 0x27d7c,
-		0x27e00, 0x27e04
-	};
-
-	int i;
-	struct adapter *ap = netdev2adap(dev);
-
-	regs->version = mk_adap_vers(ap);
-
-	memset(buf, 0, T4_REGMAP_SIZE);
-	for (i = 0; i < ARRAY_SIZE(reg_ranges); i += 2)
-		reg_block_dump(ap, buf, reg_ranges[i], reg_ranges[i + 1]);
-}
-
-static int restart_autoneg(struct net_device *dev)
-{
-	struct port_info *p = netdev_priv(dev);
-
-	if (!netif_running(dev))
-		return -EAGAIN;
-	if (p->link_cfg.autoneg != AUTONEG_ENABLE)
-		return -EINVAL;
-	t4_restart_aneg(p->adapter, p->adapter->fn, p->tx_chan);
-	return 0;
-}
-
-static int identify_port(struct net_device *dev,
-			 enum ethtool_phys_id_state state)
-{
-	unsigned int val;
-	struct adapter *adap = netdev2adap(dev);
-
-	if (state == ETHTOOL_ID_ACTIVE)
-		val = 0xffff;
-	else if (state == ETHTOOL_ID_INACTIVE)
-		val = 0;
-	else
-		return -EINVAL;
-
-	return t4_identify_port(adap, adap->fn, netdev2pinfo(dev)->viid, val);
-}
-
-static unsigned int from_fw_linkcaps(unsigned int type, unsigned int caps)
-{
-	unsigned int v = 0;
-
-	if (type == FW_PORT_TYPE_BT_SGMII || type == FW_PORT_TYPE_BT_XFI ||
-	    type == FW_PORT_TYPE_BT_XAUI) {
-		v |= SUPPORTED_TP;
-		if (caps & FW_PORT_CAP_SPEED_100M)
-			v |= SUPPORTED_100baseT_Full;
-		if (caps & FW_PORT_CAP_SPEED_1G)
-			v |= SUPPORTED_1000baseT_Full;
-		if (caps & FW_PORT_CAP_SPEED_10G)
-			v |= SUPPORTED_10000baseT_Full;
-	} else if (type == FW_PORT_TYPE_KX4 || type == FW_PORT_TYPE_KX) {
-		v |= SUPPORTED_Backplane;
-		if (caps & FW_PORT_CAP_SPEED_1G)
-			v |= SUPPORTED_1000baseKX_Full;
-		if (caps & FW_PORT_CAP_SPEED_10G)
-			v |= SUPPORTED_10000baseKX4_Full;
-	} else if (type == FW_PORT_TYPE_KR)
-		v |= SUPPORTED_Backplane | SUPPORTED_10000baseKR_Full;
-	else if (type == FW_PORT_TYPE_BP_AP)
-		v |= SUPPORTED_Backplane | SUPPORTED_10000baseR_FEC |
-		     SUPPORTED_10000baseKR_Full | SUPPORTED_1000baseKX_Full;
-	else if (type == FW_PORT_TYPE_BP4_AP)
-		v |= SUPPORTED_Backplane | SUPPORTED_10000baseR_FEC |
-		     SUPPORTED_10000baseKR_Full | SUPPORTED_1000baseKX_Full |
-		     SUPPORTED_10000baseKX4_Full;
-	else if (type == FW_PORT_TYPE_FIBER_XFI ||
-		 type == FW_PORT_TYPE_FIBER_XAUI || type == FW_PORT_TYPE_SFP)
-		v |= SUPPORTED_FIBRE;
-
-	if (caps & FW_PORT_CAP_ANEG)
-		v |= SUPPORTED_Autoneg;
-	return v;
-}
-
-static unsigned int to_fw_linkcaps(unsigned int caps)
-{
-	unsigned int v = 0;
-
-	if (caps & ADVERTISED_100baseT_Full)
-		v |= FW_PORT_CAP_SPEED_100M;
-	if (caps & ADVERTISED_1000baseT_Full)
-		v |= FW_PORT_CAP_SPEED_1G;
-	if (caps & ADVERTISED_10000baseT_Full)
-		v |= FW_PORT_CAP_SPEED_10G;
-	return v;
-}
-
-static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	const struct port_info *p = netdev_priv(dev);
-
-	if (p->port_type == FW_PORT_TYPE_BT_SGMII ||
-	    p->port_type == FW_PORT_TYPE_BT_XFI ||
-	    p->port_type == FW_PORT_TYPE_BT_XAUI)
-		cmd->port = PORT_TP;
-	else if (p->port_type == FW_PORT_TYPE_FIBER_XFI ||
-		 p->port_type == FW_PORT_TYPE_FIBER_XAUI)
-		cmd->port = PORT_FIBRE;
-	else if (p->port_type == FW_PORT_TYPE_SFP) {
-		if (p->mod_type == FW_PORT_MOD_TYPE_TWINAX_PASSIVE ||
-		    p->mod_type == FW_PORT_MOD_TYPE_TWINAX_ACTIVE)
-			cmd->port = PORT_DA;
-		else
-			cmd->port = PORT_FIBRE;
-	} else
-		cmd->port = PORT_OTHER;
-
-	if (p->mdio_addr >= 0) {
-		cmd->phy_address = p->mdio_addr;
-		cmd->transceiver = XCVR_EXTERNAL;
-		cmd->mdio_support = p->port_type == FW_PORT_TYPE_BT_SGMII ?
-			MDIO_SUPPORTS_C22 : MDIO_SUPPORTS_C45;
-	} else {
-		cmd->phy_address = 0;  /* not really, but no better option */
-		cmd->transceiver = XCVR_INTERNAL;
-		cmd->mdio_support = 0;
-	}
-
-	cmd->supported = from_fw_linkcaps(p->port_type, p->link_cfg.supported);
-	cmd->advertising = from_fw_linkcaps(p->port_type,
-					    p->link_cfg.advertising);
-	ethtool_cmd_speed_set(cmd,
-			      netif_carrier_ok(dev) ? p->link_cfg.speed : 0);
-	cmd->duplex = DUPLEX_FULL;
-	cmd->autoneg = p->link_cfg.autoneg;
-	cmd->maxtxpkt = 0;
-	cmd->maxrxpkt = 0;
-	return 0;
-}
-
-static unsigned int speed_to_caps(int speed)
-{
-	if (speed == SPEED_100)
-		return FW_PORT_CAP_SPEED_100M;
-	if (speed == SPEED_1000)
-		return FW_PORT_CAP_SPEED_1G;
-	if (speed == SPEED_10000)
-		return FW_PORT_CAP_SPEED_10G;
-	return 0;
-}
-
-static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	unsigned int cap;
-	struct port_info *p = netdev_priv(dev);
-	struct link_config *lc = &p->link_cfg;
-	u32 speed = ethtool_cmd_speed(cmd);
-
-	if (cmd->duplex != DUPLEX_FULL)     /* only full-duplex supported */
-		return -EINVAL;
-
-	if (!(lc->supported & FW_PORT_CAP_ANEG)) {
-		/*
-		 * PHY offers a single speed.  See if that's what's
-		 * being requested.
-		 */
-		if (cmd->autoneg == AUTONEG_DISABLE &&
-		    (lc->supported & speed_to_caps(speed)))
-			return 0;
-		return -EINVAL;
-	}
-
-	if (cmd->autoneg == AUTONEG_DISABLE) {
-		cap = speed_to_caps(speed);
-
-		if (!(lc->supported & cap) || (speed == SPEED_1000) ||
-		    (speed == SPEED_10000))
-			return -EINVAL;
-		lc->requested_speed = cap;
-		lc->advertising = 0;
-	} else {
-		cap = to_fw_linkcaps(cmd->advertising);
-		if (!(lc->supported & cap))
-			return -EINVAL;
-		lc->requested_speed = 0;
-		lc->advertising = cap | FW_PORT_CAP_ANEG;
-	}
-	lc->autoneg = cmd->autoneg;
-
-	if (netif_running(dev))
-		return t4_link_start(p->adapter, p->adapter->fn, p->tx_chan,
-				     lc);
-	return 0;
-}
-
-static void get_pauseparam(struct net_device *dev,
-			   struct ethtool_pauseparam *epause)
-{
-	struct port_info *p = netdev_priv(dev);
-
-	epause->autoneg = (p->link_cfg.requested_fc & PAUSE_AUTONEG) != 0;
-	epause->rx_pause = (p->link_cfg.fc & PAUSE_RX) != 0;
-	epause->tx_pause = (p->link_cfg.fc & PAUSE_TX) != 0;
-}
-
-static int set_pauseparam(struct net_device *dev,
-			  struct ethtool_pauseparam *epause)
-{
-	struct port_info *p = netdev_priv(dev);
-	struct link_config *lc = &p->link_cfg;
-
-	if (epause->autoneg == AUTONEG_DISABLE)
-		lc->requested_fc = 0;
-	else if (lc->supported & FW_PORT_CAP_ANEG)
-		lc->requested_fc = PAUSE_AUTONEG;
-	else
-		return -EINVAL;
-
-	if (epause->rx_pause)
-		lc->requested_fc |= PAUSE_RX;
-	if (epause->tx_pause)
-		lc->requested_fc |= PAUSE_TX;
-	if (netif_running(dev))
-		return t4_link_start(p->adapter, p->adapter->fn, p->tx_chan,
-				     lc);
-	return 0;
-}
-
-static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
-{
-	const struct port_info *pi = netdev_priv(dev);
-	const struct sge *s = &pi->adapter->sge;
-
-	e->rx_max_pending = MAX_RX_BUFFERS;
-	e->rx_mini_max_pending = MAX_RSPQ_ENTRIES;
-	e->rx_jumbo_max_pending = 0;
-	e->tx_max_pending = MAX_TXQ_ENTRIES;
-
-	e->rx_pending = s->ethrxq[pi->first_qset].fl.size - 8;
-	e->rx_mini_pending = s->ethrxq[pi->first_qset].rspq.size;
-	e->rx_jumbo_pending = 0;
-	e->tx_pending = s->ethtxq[pi->first_qset].q.size;
-}
-
-static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
-{
-	int i;
-	const struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	struct sge *s = &adapter->sge;
-
-	if (e->rx_pending > MAX_RX_BUFFERS || e->rx_jumbo_pending ||
-	    e->tx_pending > MAX_TXQ_ENTRIES ||
-	    e->rx_mini_pending > MAX_RSPQ_ENTRIES ||
-	    e->rx_mini_pending < MIN_RSPQ_ENTRIES ||
-	    e->rx_pending < MIN_FL_ENTRIES || e->tx_pending < MIN_TXQ_ENTRIES)
-		return -EINVAL;
-
-	if (adapter->flags & FULL_INIT_DONE)
-		return -EBUSY;
-
-	for (i = 0; i < pi->nqsets; ++i) {
-		s->ethtxq[pi->first_qset + i].q.size = e->tx_pending;
-		s->ethrxq[pi->first_qset + i].fl.size = e->rx_pending + 8;
-		s->ethrxq[pi->first_qset + i].rspq.size = e->rx_mini_pending;
-	}
-	return 0;
-}
-
-static int closest_timer(const struct sge *s, int time)
-{
-	int i, delta, match = 0, min_delta = INT_MAX;
-
-	for (i = 0; i < ARRAY_SIZE(s->timer_val); i++) {
-		delta = time - s->timer_val[i];
-		if (delta < 0)
-			delta = -delta;
-		if (delta < min_delta) {
-			min_delta = delta;
-			match = i;
-		}
-	}
-	return match;
-}
-
-static int closest_thres(const struct sge *s, int thres)
-{
-	int i, delta, match = 0, min_delta = INT_MAX;
-
-	for (i = 0; i < ARRAY_SIZE(s->counter_val); i++) {
-		delta = thres - s->counter_val[i];
-		if (delta < 0)
-			delta = -delta;
-		if (delta < min_delta) {
-			min_delta = delta;
-			match = i;
-		}
-	}
-	return match;
-}
-
-/*
- * Return a queue's interrupt hold-off time in us.  0 means no timer.
- */
-static unsigned int qtimer_val(const struct adapter *adap,
-			       const struct sge_rspq *q)
-{
-	unsigned int idx = q->intr_params >> 1;
-
-	return idx < SGE_NTIMERS ? adap->sge.timer_val[idx] : 0;
-}
-
-/**
- *	set_rxq_intr_params - set a queue's interrupt holdoff parameters
- *	@adap: the adapter
- *	@q: the Rx queue
- *	@us: the hold-off time in us, or 0 to disable timer
- *	@cnt: the hold-off packet count, or 0 to disable counter
- *
- *	Sets an Rx queue's interrupt hold-off time and packet count.  At least
- *	one of the two needs to be enabled for the queue to generate interrupts.
- */
-static int set_rxq_intr_params(struct adapter *adap, struct sge_rspq *q,
-			       unsigned int us, unsigned int cnt)
-{
-	if ((us | cnt) == 0)
-		cnt = 1;
-
-	if (cnt) {
-		int err;
-		u32 v, new_idx;
-
-		new_idx = closest_thres(&adap->sge, cnt);
-		if (q->desc && q->pktcnt_idx != new_idx) {
-			/* the queue has already been created, update it */
-			v = FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) |
-			    FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_IQ_INTCNTTHRESH) |
-			    FW_PARAMS_PARAM_YZ(q->cntxt_id);
-			err = t4_set_params(adap, adap->fn, adap->fn, 0, 1, &v,
-					    &new_idx);
-			if (err)
-				return err;
-		}
-		q->pktcnt_idx = new_idx;
-	}
-
-	us = us == 0 ? 6 : closest_timer(&adap->sge, us);
-	q->intr_params = QINTR_TIMER_IDX(us) | (cnt > 0 ? QINTR_CNT_EN : 0);
-	return 0;
-}
-
-static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
-{
-	const struct port_info *pi = netdev_priv(dev);
-	struct adapter *adap = pi->adapter;
-
-	return set_rxq_intr_params(adap, &adap->sge.ethrxq[pi->first_qset].rspq,
-			c->rx_coalesce_usecs, c->rx_max_coalesced_frames);
-}
-
-static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
-{
-	const struct port_info *pi = netdev_priv(dev);
-	const struct adapter *adap = pi->adapter;
-	const struct sge_rspq *rq = &adap->sge.ethrxq[pi->first_qset].rspq;
-
-	c->rx_coalesce_usecs = qtimer_val(adap, rq);
-	c->rx_max_coalesced_frames = (rq->intr_params & QINTR_CNT_EN) ?
-		adap->sge.counter_val[rq->pktcnt_idx] : 0;
-	return 0;
-}
-
-/**
- *	eeprom_ptov - translate a physical EEPROM address to virtual
- *	@phys_addr: the physical EEPROM address
- *	@fn: the PCI function number
- *	@sz: size of function-specific area
- *
- *	Translate a physical EEPROM address to virtual.  The first 1K is
- *	accessed through virtual addresses starting at 31K, the rest is
- *	accessed through virtual addresses starting at 0.
- *
- *	The mapping is as follows:
- *	[0..1K) -> [31K..32K)
- *	[1K..1K+A) -> [31K-A..31K)
- *	[1K+A..ES) -> [0..ES-A-1K)
- *
- *	where A = @fn * @sz, and ES = EEPROM size.
- */
-static int eeprom_ptov(unsigned int phys_addr, unsigned int fn, unsigned int sz)
-{
-	fn *= sz;
-	if (phys_addr < 1024)
-		return phys_addr + (31 << 10);
-	if (phys_addr < 1024 + fn)
-		return 31744 - fn + phys_addr - 1024;
-	if (phys_addr < EEPROMSIZE)
-		return phys_addr - 1024 - fn;
-	return -EINVAL;
-}
-
-/*
- * The next two routines implement eeprom read/write from physical addresses.
- */
-static int eeprom_rd_phys(struct adapter *adap, unsigned int phys_addr, u32 *v)
-{
-	int vaddr = eeprom_ptov(phys_addr, adap->fn, EEPROMPFSIZE);
-
-	if (vaddr >= 0)
-		vaddr = pci_read_vpd(adap->pdev, vaddr, sizeof(u32), v);
-	return vaddr < 0 ? vaddr : 0;
-}
-
-static int eeprom_wr_phys(struct adapter *adap, unsigned int phys_addr, u32 v)
-{
-	int vaddr = eeprom_ptov(phys_addr, adap->fn, EEPROMPFSIZE);
-
-	if (vaddr >= 0)
-		vaddr = pci_write_vpd(adap->pdev, vaddr, sizeof(u32), &v);
-	return vaddr < 0 ? vaddr : 0;
-}
-
-#define EEPROM_MAGIC 0x38E2F10C
-
-static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
-		      u8 *data)
-{
-	int i, err = 0;
-	struct adapter *adapter = netdev2adap(dev);
-
-	u8 *buf = kmalloc(EEPROMSIZE, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	e->magic = EEPROM_MAGIC;
-	for (i = e->offset & ~3; !err && i < e->offset + e->len; i += 4)
-		err = eeprom_rd_phys(adapter, i, (u32 *)&buf[i]);
-
-	if (!err)
-		memcpy(data, buf + e->offset, e->len);
-	kfree(buf);
-	return err;
-}
-
-static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
-		      u8 *data)
-{
-	u8 *buf;
-	int err = 0;
-	u32 aligned_offset, aligned_len, *p;
-	struct adapter *adapter = netdev2adap(dev);
-
-	if (eeprom->magic != EEPROM_MAGIC)
-		return -EINVAL;
-
-	aligned_offset = eeprom->offset & ~3;
-	aligned_len = (eeprom->len + (eeprom->offset & 3) + 3) & ~3;
-
-	if (adapter->fn > 0) {
-		u32 start = 1024 + adapter->fn * EEPROMPFSIZE;
-
-		if (aligned_offset < start ||
-		    aligned_offset + aligned_len > start + EEPROMPFSIZE)
-			return -EPERM;
-	}
-
-	if (aligned_offset != eeprom->offset || aligned_len != eeprom->len) {
-		/*
-		 * RMW possibly needed for first or last words.
-		 */
-		buf = kmalloc(aligned_len, GFP_KERNEL);
-		if (!buf)
-			return -ENOMEM;
-		err = eeprom_rd_phys(adapter, aligned_offset, (u32 *)buf);
-		if (!err && aligned_len > 4)
-			err = eeprom_rd_phys(adapter,
-					     aligned_offset + aligned_len - 4,
-					     (u32 *)&buf[aligned_len - 4]);
-		if (err)
-			goto out;
-		memcpy(buf + (eeprom->offset & 3), data, eeprom->len);
-	} else
-		buf = data;
-
-	err = t4_seeprom_wp(adapter, false);
-	if (err)
-		goto out;
-
-	for (p = (u32 *)buf; !err && aligned_len; aligned_len -= 4, p++) {
-		err = eeprom_wr_phys(adapter, aligned_offset, *p);
-		aligned_offset += 4;
-	}
-
-	if (!err)
-		err = t4_seeprom_wp(adapter, true);
-out:
-	if (buf != data)
-		kfree(buf);
-	return err;
-}
-
-static int set_flash(struct net_device *netdev, struct ethtool_flash *ef)
-{
-	int ret;
-	const struct firmware *fw;
-	struct adapter *adap = netdev2adap(netdev);
-
-	ef->data[sizeof(ef->data) - 1] = '\0';
-	ret = reject_firmware(&fw, ef->data, adap->pdev_dev);
-	if (ret < 0)
-		return ret;
-
-	ret = t4_load_fw(adap, fw->data, fw->size);
-	release_firmware(fw);
-	if (!ret)
-		dev_info(adap->pdev_dev, "loaded firmware %s\n", ef->data);
-	return ret;
-}
-
-#define WOL_SUPPORTED (WAKE_BCAST | WAKE_MAGIC)
-#define BCAST_CRC 0xa0ccc1a6
-
-static void get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-	wol->supported = WAKE_BCAST | WAKE_MAGIC;
-	wol->wolopts = netdev2adap(dev)->wol;
-	memset(&wol->sopass, 0, sizeof(wol->sopass));
-}
-
-static int set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-	int err = 0;
-	struct port_info *pi = netdev_priv(dev);
-
-	if (wol->wolopts & ~WOL_SUPPORTED)
-		return -EINVAL;
-	t4_wol_magic_enable(pi->adapter, pi->tx_chan,
-			    (wol->wolopts & WAKE_MAGIC) ? dev->dev_addr : NULL);
-	if (wol->wolopts & WAKE_BCAST) {
-		err = t4_wol_pat_enable(pi->adapter, pi->tx_chan, 0xfe, ~0ULL,
-					~0ULL, 0, false);
-		if (!err)
-			err = t4_wol_pat_enable(pi->adapter, pi->tx_chan, 1,
-						~6ULL, ~0ULL, BCAST_CRC, true);
-	} else
-		t4_wol_pat_enable(pi->adapter, pi->tx_chan, 0, 0, 0, 0, false);
-	return err;
-}
-
-static int cxgb_set_features(struct net_device *dev, u32 features)
-{
-	const struct port_info *pi = netdev_priv(dev);
-	u32 changed = dev->features ^ features;
-	int err;
-
-	if (!(changed & NETIF_F_HW_VLAN_RX))
-		return 0;
-
-	err = t4_set_rxmode(pi->adapter, pi->adapter->fn, pi->viid, -1,
-			    -1, -1, -1,
-			    !!(features & NETIF_F_HW_VLAN_RX), true);
-	if (unlikely(err))
-		dev->features = features ^ NETIF_F_HW_VLAN_RX;
-	return err;
-}
-
-static int get_rss_table(struct net_device *dev, struct ethtool_rxfh_indir *p)
-{
-	const struct port_info *pi = netdev_priv(dev);
-	unsigned int n = min_t(unsigned int, p->size, pi->rss_size);
-
-	p->size = pi->rss_size;
-	while (n--)
-		p->ring_index[n] = pi->rss[n];
-	return 0;
-}
-
-static int set_rss_table(struct net_device *dev,
-			 const struct ethtool_rxfh_indir *p)
-{
-	unsigned int i;
-	struct port_info *pi = netdev_priv(dev);
-
-	if (p->size != pi->rss_size)
-		return -EINVAL;
-	for (i = 0; i < p->size; i++)
-		if (p->ring_index[i] >= pi->nqsets)
-			return -EINVAL;
-	for (i = 0; i < p->size; i++)
-		pi->rss[i] = p->ring_index[i];
-	if (pi->adapter->flags & FULL_INIT_DONE)
-		return write_rss(pi, pi->rss);
-	return 0;
-}
-
-static int get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
-		     void *rules)
-{
-	const struct port_info *pi = netdev_priv(dev);
-
-	switch (info->cmd) {
-	case ETHTOOL_GRXFH: {
-		unsigned int v = pi->rss_mode;
-
-		info->data = 0;
-		switch (info->flow_type) {
-		case TCP_V4_FLOW:
-			if (v & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN)
-				info->data = RXH_IP_SRC | RXH_IP_DST |
-					     RXH_L4_B_0_1 | RXH_L4_B_2_3;
-			else if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN)
-				info->data = RXH_IP_SRC | RXH_IP_DST;
-			break;
-		case UDP_V4_FLOW:
-			if ((v & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN) &&
-			    (v & FW_RSS_VI_CONFIG_CMD_UDPEN))
-				info->data = RXH_IP_SRC | RXH_IP_DST |
-					     RXH_L4_B_0_1 | RXH_L4_B_2_3;
-			else if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN)
-				info->data = RXH_IP_SRC | RXH_IP_DST;
-			break;
-		case SCTP_V4_FLOW:
-		case AH_ESP_V4_FLOW:
-		case IPV4_FLOW:
-			if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN)
-				info->data = RXH_IP_SRC | RXH_IP_DST;
-			break;
-		case TCP_V6_FLOW:
-			if (v & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN)
-				info->data = RXH_IP_SRC | RXH_IP_DST |
-					     RXH_L4_B_0_1 | RXH_L4_B_2_3;
-			else if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN)
-				info->data = RXH_IP_SRC | RXH_IP_DST;
-			break;
-		case UDP_V6_FLOW:
-			if ((v & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN) &&
-			    (v & FW_RSS_VI_CONFIG_CMD_UDPEN))
-				info->data = RXH_IP_SRC | RXH_IP_DST |
-					     RXH_L4_B_0_1 | RXH_L4_B_2_3;
-			else if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN)
-				info->data = RXH_IP_SRC | RXH_IP_DST;
-			break;
-		case SCTP_V6_FLOW:
-		case AH_ESP_V6_FLOW:
-		case IPV6_FLOW:
-			if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN)
-				info->data = RXH_IP_SRC | RXH_IP_DST;
-			break;
-		}
-		return 0;
-	}
-	case ETHTOOL_GRXRINGS:
-		info->data = pi->nqsets;
-		return 0;
-	}
-	return -EOPNOTSUPP;
-}
-
-static struct ethtool_ops cxgb_ethtool_ops = {
-	.get_settings      = get_settings,
-	.set_settings      = set_settings,
-	.get_drvinfo       = get_drvinfo,
-	.get_msglevel      = get_msglevel,
-	.set_msglevel      = set_msglevel,
-	.get_ringparam     = get_sge_param,
-	.set_ringparam     = set_sge_param,
-	.get_coalesce      = get_coalesce,
-	.set_coalesce      = set_coalesce,
-	.get_eeprom_len    = get_eeprom_len,
-	.get_eeprom        = get_eeprom,
-	.set_eeprom        = set_eeprom,
-	.get_pauseparam    = get_pauseparam,
-	.set_pauseparam    = set_pauseparam,
-	.get_link          = ethtool_op_get_link,
-	.get_strings       = get_strings,
-	.set_phys_id       = identify_port,
-	.nway_reset        = restart_autoneg,
-	.get_sset_count    = get_sset_count,
-	.get_ethtool_stats = get_stats,
-	.get_regs_len      = get_regs_len,
-	.get_regs          = get_regs,
-	.get_wol           = get_wol,
-	.set_wol           = set_wol,
-	.get_rxnfc         = get_rxnfc,
-	.get_rxfh_indir    = get_rss_table,
-	.set_rxfh_indir    = set_rss_table,
-	.flash_device      = set_flash,
-};
-
-/*
- * debugfs support
- */
-
-static int mem_open(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-static ssize_t mem_read(struct file *file, char __user *buf, size_t count,
-			loff_t *ppos)
-{
-	loff_t pos = *ppos;
-	loff_t avail = file->f_path.dentry->d_inode->i_size;
-	unsigned int mem = (uintptr_t)file->private_data & 3;
-	struct adapter *adap = file->private_data - mem;
-
-	if (pos < 0)
-		return -EINVAL;
-	if (pos >= avail)
-		return 0;
-	if (count > avail - pos)
-		count = avail - pos;
-
-	while (count) {
-		size_t len;
-		int ret, ofst;
-		__be32 data[16];
-
-		if (mem == MEM_MC)
-			ret = t4_mc_read(adap, pos, data, NULL);
-		else
-			ret = t4_edc_read(adap, mem, pos, data, NULL);
-		if (ret)
-			return ret;
-
-		ofst = pos % sizeof(data);
-		len = min(count, sizeof(data) - ofst);
-		if (copy_to_user(buf, (u8 *)data + ofst, len))
-			return -EFAULT;
-
-		buf += len;
-		pos += len;
-		count -= len;
-	}
-	count = pos - *ppos;
-	*ppos = pos;
-	return count;
-}
-
-static const struct file_operations mem_debugfs_fops = {
-	.owner   = THIS_MODULE,
-	.open    = mem_open,
-	.read    = mem_read,
-	.llseek  = default_llseek,
-};
-
-static void __devinit add_debugfs_mem(struct adapter *adap, const char *name,
-				      unsigned int idx, unsigned int size_mb)
-{
-	struct dentry *de;
-
-	de = debugfs_create_file(name, S_IRUSR, adap->debugfs_root,
-				 (void *)adap + idx, &mem_debugfs_fops);
-	if (de && de->d_inode)
-		de->d_inode->i_size = size_mb << 20;
-}
-
-static int __devinit setup_debugfs(struct adapter *adap)
-{
-	int i;
-
-	if (IS_ERR_OR_NULL(adap->debugfs_root))
-		return -1;
-
-	i = t4_read_reg(adap, MA_TARGET_MEM_ENABLE);
-	if (i & EDRAM0_ENABLE)
-		add_debugfs_mem(adap, "edc0", MEM_EDC0, 5);
-	if (i & EDRAM1_ENABLE)
-		add_debugfs_mem(adap, "edc1", MEM_EDC1, 5);
-	if (i & EXT_MEM_ENABLE)
-		add_debugfs_mem(adap, "mc", MEM_MC,
-			EXT_MEM_SIZE_GET(t4_read_reg(adap, MA_EXT_MEMORY_BAR)));
-	if (adap->l2t)
-		debugfs_create_file("l2t", S_IRUSR, adap->debugfs_root, adap,
-				    &t4_l2t_fops);
-	return 0;
-}
-
-/*
- * upper-layer driver support
- */
-
-/*
- * Allocate an active-open TID and set it to the supplied value.
- */
-int cxgb4_alloc_atid(struct tid_info *t, void *data)
-{
-	int atid = -1;
-
-	spin_lock_bh(&t->atid_lock);
-	if (t->afree) {
-		union aopen_entry *p = t->afree;
-
-		atid = p - t->atid_tab;
-		t->afree = p->next;
-		p->data = data;
-		t->atids_in_use++;
-	}
-	spin_unlock_bh(&t->atid_lock);
-	return atid;
-}
-EXPORT_SYMBOL(cxgb4_alloc_atid);
-
-/*
- * Release an active-open TID.
- */
-void cxgb4_free_atid(struct tid_info *t, unsigned int atid)
-{
-	union aopen_entry *p = &t->atid_tab[atid];
-
-	spin_lock_bh(&t->atid_lock);
-	p->next = t->afree;
-	t->afree = p;
-	t->atids_in_use--;
-	spin_unlock_bh(&t->atid_lock);
-}
-EXPORT_SYMBOL(cxgb4_free_atid);
-
-/*
- * Allocate a server TID and set it to the supplied value.
- */
-int cxgb4_alloc_stid(struct tid_info *t, int family, void *data)
-{
-	int stid;
-
-	spin_lock_bh(&t->stid_lock);
-	if (family == PF_INET) {
-		stid = find_first_zero_bit(t->stid_bmap, t->nstids);
-		if (stid < t->nstids)
-			__set_bit(stid, t->stid_bmap);
-		else
-			stid = -1;
-	} else {
-		stid = bitmap_find_free_region(t->stid_bmap, t->nstids, 2);
-		if (stid < 0)
-			stid = -1;
-	}
-	if (stid >= 0) {
-		t->stid_tab[stid].data = data;
-		stid += t->stid_base;
-		t->stids_in_use++;
-	}
-	spin_unlock_bh(&t->stid_lock);
-	return stid;
-}
-EXPORT_SYMBOL(cxgb4_alloc_stid);
-
-/*
- * Release a server TID.
- */
-void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family)
-{
-	stid -= t->stid_base;
-	spin_lock_bh(&t->stid_lock);
-	if (family == PF_INET)
-		__clear_bit(stid, t->stid_bmap);
-	else
-		bitmap_release_region(t->stid_bmap, stid, 2);
-	t->stid_tab[stid].data = NULL;
-	t->stids_in_use--;
-	spin_unlock_bh(&t->stid_lock);
-}
-EXPORT_SYMBOL(cxgb4_free_stid);
-
-/*
- * Populate a TID_RELEASE WR.  Caller must properly size the skb.
- */
-static void mk_tid_release(struct sk_buff *skb, unsigned int chan,
-			   unsigned int tid)
-{
-	struct cpl_tid_release *req;
-
-	set_wr_txq(skb, CPL_PRIORITY_SETUP, chan);
-	req = (struct cpl_tid_release *)__skb_put(skb, sizeof(*req));
-	INIT_TP_WR(req, tid);
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_TID_RELEASE, tid));
-}
-
-/*
- * Queue a TID release request and if necessary schedule a work queue to
- * process it.
- */
-static void cxgb4_queue_tid_release(struct tid_info *t, unsigned int chan,
-				    unsigned int tid)
-{
-	void **p = &t->tid_tab[tid];
-	struct adapter *adap = container_of(t, struct adapter, tids);
-
-	spin_lock_bh(&adap->tid_release_lock);
-	*p = adap->tid_release_head;
-	/* Low 2 bits encode the Tx channel number */
-	adap->tid_release_head = (void **)((uintptr_t)p | chan);
-	if (!adap->tid_release_task_busy) {
-		adap->tid_release_task_busy = true;
-		schedule_work(&adap->tid_release_task);
-	}
-	spin_unlock_bh(&adap->tid_release_lock);
-}
-
-/*
- * Process the list of pending TID release requests.
- */
-static void process_tid_release_list(struct work_struct *work)
-{
-	struct sk_buff *skb;
-	struct adapter *adap;
-
-	adap = container_of(work, struct adapter, tid_release_task);
-
-	spin_lock_bh(&adap->tid_release_lock);
-	while (adap->tid_release_head) {
-		void **p = adap->tid_release_head;
-		unsigned int chan = (uintptr_t)p & 3;
-		p = (void *)p - chan;
-
-		adap->tid_release_head = *p;
-		*p = NULL;
-		spin_unlock_bh(&adap->tid_release_lock);
-
-		while (!(skb = alloc_skb(sizeof(struct cpl_tid_release),
-					 GFP_KERNEL)))
-			schedule_timeout_uninterruptible(1);
-
-		mk_tid_release(skb, chan, p - adap->tids.tid_tab);
-		t4_ofld_send(adap, skb);
-		spin_lock_bh(&adap->tid_release_lock);
-	}
-	adap->tid_release_task_busy = false;
-	spin_unlock_bh(&adap->tid_release_lock);
-}
-
-/*
- * Release a TID and inform HW.  If we are unable to allocate the release
- * message we defer to a work queue.
- */
-void cxgb4_remove_tid(struct tid_info *t, unsigned int chan, unsigned int tid)
-{
-	void *old;
-	struct sk_buff *skb;
-	struct adapter *adap = container_of(t, struct adapter, tids);
-
-	old = t->tid_tab[tid];
-	skb = alloc_skb(sizeof(struct cpl_tid_release), GFP_ATOMIC);
-	if (likely(skb)) {
-		t->tid_tab[tid] = NULL;
-		mk_tid_release(skb, chan, tid);
-		t4_ofld_send(adap, skb);
-	} else
-		cxgb4_queue_tid_release(t, chan, tid);
-	if (old)
-		atomic_dec(&t->tids_in_use);
-}
-EXPORT_SYMBOL(cxgb4_remove_tid);
-
-/*
- * Allocate and initialize the TID tables.  Returns 0 on success.
- */
-static int tid_init(struct tid_info *t)
-{
-	size_t size;
-	unsigned int natids = t->natids;
-
-	size = t->ntids * sizeof(*t->tid_tab) + natids * sizeof(*t->atid_tab) +
-	       t->nstids * sizeof(*t->stid_tab) +
-	       BITS_TO_LONGS(t->nstids) * sizeof(long);
-	t->tid_tab = t4_alloc_mem(size);
-	if (!t->tid_tab)
-		return -ENOMEM;
-
-	t->atid_tab = (union aopen_entry *)&t->tid_tab[t->ntids];
-	t->stid_tab = (struct serv_entry *)&t->atid_tab[natids];
-	t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids];
-	spin_lock_init(&t->stid_lock);
-	spin_lock_init(&t->atid_lock);
-
-	t->stids_in_use = 0;
-	t->afree = NULL;
-	t->atids_in_use = 0;
-	atomic_set(&t->tids_in_use, 0);
-
-	/* Setup the free list for atid_tab and clear the stid bitmap. */
-	if (natids) {
-		while (--natids)
-			t->atid_tab[natids - 1].next = &t->atid_tab[natids];
-		t->afree = t->atid_tab;
-	}
-	bitmap_zero(t->stid_bmap, t->nstids);
-	return 0;
-}
-
-/**
- *	cxgb4_create_server - create an IP server
- *	@dev: the device
- *	@stid: the server TID
- *	@sip: local IP address to bind server to
- *	@sport: the server's TCP port
- *	@queue: queue to direct messages from this server to
- *
- *	Create an IP server for the given port and address.
- *	Returns <0 on error and one of the %NET_XMIT_* values on success.
- */
-int cxgb4_create_server(const struct net_device *dev, unsigned int stid,
-			__be32 sip, __be16 sport, unsigned int queue)
-{
-	unsigned int chan;
-	struct sk_buff *skb;
-	struct adapter *adap;
-	struct cpl_pass_open_req *req;
-
-	skb = alloc_skb(sizeof(*req), GFP_KERNEL);
-	if (!skb)
-		return -ENOMEM;
-
-	adap = netdev2adap(dev);
-	req = (struct cpl_pass_open_req *)__skb_put(skb, sizeof(*req));
-	INIT_TP_WR(req, 0);
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_OPEN_REQ, stid));
-	req->local_port = sport;
-	req->peer_port = htons(0);
-	req->local_ip = sip;
-	req->peer_ip = htonl(0);
-	chan = rxq_to_chan(&adap->sge, queue);
-	req->opt0 = cpu_to_be64(TX_CHAN(chan));
-	req->opt1 = cpu_to_be64(CONN_POLICY_ASK |
-				SYN_RSS_ENABLE | SYN_RSS_QUEUE(queue));
-	return t4_mgmt_tx(adap, skb);
-}
-EXPORT_SYMBOL(cxgb4_create_server);
-
-/**
- *	cxgb4_best_mtu - find the entry in the MTU table closest to an MTU
- *	@mtus: the HW MTU table
- *	@mtu: the target MTU
- *	@idx: index of selected entry in the MTU table
- *
- *	Returns the index and the value in the HW MTU table that is closest to
- *	but does not exceed @mtu, unless @mtu is smaller than any value in the
- *	table, in which case that smallest available value is selected.
- */
-unsigned int cxgb4_best_mtu(const unsigned short *mtus, unsigned short mtu,
-			    unsigned int *idx)
-{
-	unsigned int i = 0;
-
-	while (i < NMTUS - 1 && mtus[i + 1] <= mtu)
-		++i;
-	if (idx)
-		*idx = i;
-	return mtus[i];
-}
-EXPORT_SYMBOL(cxgb4_best_mtu);
-
-/**
- *	cxgb4_port_chan - get the HW channel of a port
- *	@dev: the net device for the port
- *
- *	Return the HW Tx channel of the given port.
- */
-unsigned int cxgb4_port_chan(const struct net_device *dev)
-{
-	return netdev2pinfo(dev)->tx_chan;
-}
-EXPORT_SYMBOL(cxgb4_port_chan);
-
-/**
- *	cxgb4_port_viid - get the VI id of a port
- *	@dev: the net device for the port
- *
- *	Return the VI id of the given port.
- */
-unsigned int cxgb4_port_viid(const struct net_device *dev)
-{
-	return netdev2pinfo(dev)->viid;
-}
-EXPORT_SYMBOL(cxgb4_port_viid);
-
-/**
- *	cxgb4_port_idx - get the index of a port
- *	@dev: the net device for the port
- *
- *	Return the index of the given port.
- */
-unsigned int cxgb4_port_idx(const struct net_device *dev)
-{
-	return netdev2pinfo(dev)->port_id;
-}
-EXPORT_SYMBOL(cxgb4_port_idx);
-
-void cxgb4_get_tcp_stats(struct pci_dev *pdev, struct tp_tcp_stats *v4,
-			 struct tp_tcp_stats *v6)
-{
-	struct adapter *adap = pci_get_drvdata(pdev);
-
-	spin_lock(&adap->stats_lock);
-	t4_tp_get_tcp_stats(adap, v4, v6);
-	spin_unlock(&adap->stats_lock);
-}
-EXPORT_SYMBOL(cxgb4_get_tcp_stats);
-
-void cxgb4_iscsi_init(struct net_device *dev, unsigned int tag_mask,
-		      const unsigned int *pgsz_order)
-{
-	struct adapter *adap = netdev2adap(dev);
-
-	t4_write_reg(adap, ULP_RX_ISCSI_TAGMASK, tag_mask);
-	t4_write_reg(adap, ULP_RX_ISCSI_PSZ, HPZ0(pgsz_order[0]) |
-		     HPZ1(pgsz_order[1]) | HPZ2(pgsz_order[2]) |
-		     HPZ3(pgsz_order[3]));
-}
-EXPORT_SYMBOL(cxgb4_iscsi_init);
-
-static struct pci_driver cxgb4_driver;
-
-static void check_neigh_update(struct neighbour *neigh)
-{
-	const struct device *parent;
-	const struct net_device *netdev = neigh->dev;
-
-	if (netdev->priv_flags & IFF_802_1Q_VLAN)
-		netdev = vlan_dev_real_dev(netdev);
-	parent = netdev->dev.parent;
-	if (parent && parent->driver == &cxgb4_driver.driver)
-		t4_l2t_update(dev_get_drvdata(parent), neigh);
-}
-
-static int netevent_cb(struct notifier_block *nb, unsigned long event,
-		       void *data)
-{
-	switch (event) {
-	case NETEVENT_NEIGH_UPDATE:
-		check_neigh_update(data);
-		break;
-	case NETEVENT_REDIRECT:
-	default:
-		break;
-	}
-	return 0;
-}
-
-static bool netevent_registered;
-static struct notifier_block cxgb4_netevent_nb = {
-	.notifier_call = netevent_cb
-};
-
-static void uld_attach(struct adapter *adap, unsigned int uld)
-{
-	void *handle;
-	struct cxgb4_lld_info lli;
-
-	lli.pdev = adap->pdev;
-	lli.l2t = adap->l2t;
-	lli.tids = &adap->tids;
-	lli.ports = adap->port;
-	lli.vr = &adap->vres;
-	lli.mtus = adap->params.mtus;
-	if (uld == CXGB4_ULD_RDMA) {
-		lli.rxq_ids = adap->sge.rdma_rxq;
-		lli.nrxq = adap->sge.rdmaqs;
-	} else if (uld == CXGB4_ULD_ISCSI) {
-		lli.rxq_ids = adap->sge.ofld_rxq;
-		lli.nrxq = adap->sge.ofldqsets;
-	}
-	lli.ntxq = adap->sge.ofldqsets;
-	lli.nchan = adap->params.nports;
-	lli.nports = adap->params.nports;
-	lli.wr_cred = adap->params.ofldq_wr_cred;
-	lli.adapter_type = adap->params.rev;
-	lli.iscsi_iolen = MAXRXDATA_GET(t4_read_reg(adap, TP_PARA_REG2));
-	lli.udb_density = 1 << QUEUESPERPAGEPF0_GET(
-			t4_read_reg(adap, SGE_EGRESS_QUEUES_PER_PAGE_PF) >>
-			(adap->fn * 4));
-	lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET(
-			t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >>
-			(adap->fn * 4));
-	lli.gts_reg = adap->regs + MYPF_REG(SGE_PF_GTS);
-	lli.db_reg = adap->regs + MYPF_REG(SGE_PF_KDOORBELL);
-	lli.fw_vers = adap->params.fw_vers;
-
-	handle = ulds[uld].add(&lli);
-	if (IS_ERR(handle)) {
-		dev_warn(adap->pdev_dev,
-			 "could not attach to the %s driver, error %ld\n",
-			 uld_str[uld], PTR_ERR(handle));
-		return;
-	}
-
-	adap->uld_handle[uld] = handle;
-
-	if (!netevent_registered) {
-		register_netevent_notifier(&cxgb4_netevent_nb);
-		netevent_registered = true;
-	}
-
-	if (adap->flags & FULL_INIT_DONE)
-		ulds[uld].state_change(handle, CXGB4_STATE_UP);
-}
-
-static void attach_ulds(struct adapter *adap)
-{
-	unsigned int i;
-
-	mutex_lock(&uld_mutex);
-	list_add_tail(&adap->list_node, &adapter_list);
-	for (i = 0; i < CXGB4_ULD_MAX; i++)
-		if (ulds[i].add)
-			uld_attach(adap, i);
-	mutex_unlock(&uld_mutex);
-}
-
-static void detach_ulds(struct adapter *adap)
-{
-	unsigned int i;
-
-	mutex_lock(&uld_mutex);
-	list_del(&adap->list_node);
-	for (i = 0; i < CXGB4_ULD_MAX; i++)
-		if (adap->uld_handle[i]) {
-			ulds[i].state_change(adap->uld_handle[i],
-					     CXGB4_STATE_DETACH);
-			adap->uld_handle[i] = NULL;
-		}
-	if (netevent_registered && list_empty(&adapter_list)) {
-		unregister_netevent_notifier(&cxgb4_netevent_nb);
-		netevent_registered = false;
-	}
-	mutex_unlock(&uld_mutex);
-}
-
-static void notify_ulds(struct adapter *adap, enum cxgb4_state new_state)
-{
-	unsigned int i;
-
-	mutex_lock(&uld_mutex);
-	for (i = 0; i < CXGB4_ULD_MAX; i++)
-		if (adap->uld_handle[i])
-			ulds[i].state_change(adap->uld_handle[i], new_state);
-	mutex_unlock(&uld_mutex);
-}
-
-/**
- *	cxgb4_register_uld - register an upper-layer driver
- *	@type: the ULD type
- *	@p: the ULD methods
- *
- *	Registers an upper-layer driver with this driver and notifies the ULD
- *	about any presently available devices that support its type.  Returns
- *	%-EBUSY if a ULD of the same type is already registered.
- */
-int cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p)
-{
-	int ret = 0;
-	struct adapter *adap;
-
-	if (type >= CXGB4_ULD_MAX)
-		return -EINVAL;
-	mutex_lock(&uld_mutex);
-	if (ulds[type].add) {
-		ret = -EBUSY;
-		goto out;
-	}
-	ulds[type] = *p;
-	list_for_each_entry(adap, &adapter_list, list_node)
-		uld_attach(adap, type);
-out:	mutex_unlock(&uld_mutex);
-	return ret;
-}
-EXPORT_SYMBOL(cxgb4_register_uld);
-
-/**
- *	cxgb4_unregister_uld - unregister an upper-layer driver
- *	@type: the ULD type
- *
- *	Unregisters an existing upper-layer driver.
- */
-int cxgb4_unregister_uld(enum cxgb4_uld type)
-{
-	struct adapter *adap;
-
-	if (type >= CXGB4_ULD_MAX)
-		return -EINVAL;
-	mutex_lock(&uld_mutex);
-	list_for_each_entry(adap, &adapter_list, list_node)
-		adap->uld_handle[type] = NULL;
-	ulds[type].add = NULL;
-	mutex_unlock(&uld_mutex);
-	return 0;
-}
-EXPORT_SYMBOL(cxgb4_unregister_uld);
-
-/**
- *	cxgb_up - enable the adapter
- *	@adap: adapter being enabled
- *
- *	Called when the first port is enabled, this function performs the
- *	actions necessary to make an adapter operational, such as completing
- *	the initialization of HW modules, and enabling interrupts.
- *
- *	Must be called with the rtnl lock held.
- */
-static int cxgb_up(struct adapter *adap)
-{
-	int err;
-
-	err = setup_sge_queues(adap);
-	if (err)
-		goto out;
-	err = setup_rss(adap);
-	if (err)
-		goto freeq;
-
-	if (adap->flags & USING_MSIX) {
-		name_msix_vecs(adap);
-		err = request_irq(adap->msix_info[0].vec, t4_nondata_intr, 0,
-				  adap->msix_info[0].desc, adap);
-		if (err)
-			goto irq_err;
-
-		err = request_msix_queue_irqs(adap);
-		if (err) {
-			free_irq(adap->msix_info[0].vec, adap);
-			goto irq_err;
-		}
-	} else {
-		err = request_irq(adap->pdev->irq, t4_intr_handler(adap),
-				  (adap->flags & USING_MSI) ? 0 : IRQF_SHARED,
-				  adap->port[0]->name, adap);
-		if (err)
-			goto irq_err;
-	}
-	enable_rx(adap);
-	t4_sge_start(adap);
-	t4_intr_enable(adap);
-	adap->flags |= FULL_INIT_DONE;
-	notify_ulds(adap, CXGB4_STATE_UP);
- out:
-	return err;
- irq_err:
-	dev_err(adap->pdev_dev, "request_irq failed, err %d\n", err);
- freeq:
-	t4_free_sge_resources(adap);
-	goto out;
-}
-
-static void cxgb_down(struct adapter *adapter)
-{
-	t4_intr_disable(adapter);
-	cancel_work_sync(&adapter->tid_release_task);
-	adapter->tid_release_task_busy = false;
-	adapter->tid_release_head = NULL;
-
-	if (adapter->flags & USING_MSIX) {
-		free_msix_queue_irqs(adapter);
-		free_irq(adapter->msix_info[0].vec, adapter);
-	} else
-		free_irq(adapter->pdev->irq, adapter);
-	quiesce_rx(adapter);
-	t4_sge_stop(adapter);
-	t4_free_sge_resources(adapter);
-	adapter->flags &= ~FULL_INIT_DONE;
-}
-
-/*
- * net_device operations
- */
-static int cxgb_open(struct net_device *dev)
-{
-	int err;
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-
-	netif_carrier_off(dev);
-
-	if (!(adapter->flags & FULL_INIT_DONE)) {
-		err = cxgb_up(adapter);
-		if (err < 0)
-			return err;
-	}
-
-	err = link_start(dev);
-	if (!err)
-		netif_tx_start_all_queues(dev);
-	return err;
-}
-
-static int cxgb_close(struct net_device *dev)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-
-	netif_tx_stop_all_queues(dev);
-	netif_carrier_off(dev);
-	return t4_enable_vi(adapter, adapter->fn, pi->viid, false, false);
-}
-
-static struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev,
-						struct rtnl_link_stats64 *ns)
-{
-	struct port_stats stats;
-	struct port_info *p = netdev_priv(dev);
-	struct adapter *adapter = p->adapter;
-
-	spin_lock(&adapter->stats_lock);
-	t4_get_port_stats(adapter, p->tx_chan, &stats);
-	spin_unlock(&adapter->stats_lock);
-
-	ns->tx_bytes   = stats.tx_octets;
-	ns->tx_packets = stats.tx_frames;
-	ns->rx_bytes   = stats.rx_octets;
-	ns->rx_packets = stats.rx_frames;
-	ns->multicast  = stats.rx_mcast_frames;
-
-	/* detailed rx_errors */
-	ns->rx_length_errors = stats.rx_jabber + stats.rx_too_long +
-			       stats.rx_runt;
-	ns->rx_over_errors   = 0;
-	ns->rx_crc_errors    = stats.rx_fcs_err;
-	ns->rx_frame_errors  = stats.rx_symbol_err;
-	ns->rx_fifo_errors   = stats.rx_ovflow0 + stats.rx_ovflow1 +
-			       stats.rx_ovflow2 + stats.rx_ovflow3 +
-			       stats.rx_trunc0 + stats.rx_trunc1 +
-			       stats.rx_trunc2 + stats.rx_trunc3;
-	ns->rx_missed_errors = 0;
-
-	/* detailed tx_errors */
-	ns->tx_aborted_errors   = 0;
-	ns->tx_carrier_errors   = 0;
-	ns->tx_fifo_errors      = 0;
-	ns->tx_heartbeat_errors = 0;
-	ns->tx_window_errors    = 0;
-
-	ns->tx_errors = stats.tx_error_frames;
-	ns->rx_errors = stats.rx_symbol_err + stats.rx_fcs_err +
-		ns->rx_length_errors + stats.rx_len_err + ns->rx_fifo_errors;
-	return ns;
-}
-
-static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
-{
-	unsigned int mbox;
-	int ret = 0, prtad, devad;
-	struct port_info *pi = netdev_priv(dev);
-	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&req->ifr_data;
-
-	switch (cmd) {
-	case SIOCGMIIPHY:
-		if (pi->mdio_addr < 0)
-			return -EOPNOTSUPP;
-		data->phy_id = pi->mdio_addr;
-		break;
-	case SIOCGMIIREG:
-	case SIOCSMIIREG:
-		if (mdio_phy_id_is_c45(data->phy_id)) {
-			prtad = mdio_phy_id_prtad(data->phy_id);
-			devad = mdio_phy_id_devad(data->phy_id);
-		} else if (data->phy_id < 32) {
-			prtad = data->phy_id;
-			devad = 0;
-			data->reg_num &= 0x1f;
-		} else
-			return -EINVAL;
-
-		mbox = pi->adapter->fn;
-		if (cmd == SIOCGMIIREG)
-			ret = t4_mdio_rd(pi->adapter, mbox, prtad, devad,
-					 data->reg_num, &data->val_out);
-		else
-			ret = t4_mdio_wr(pi->adapter, mbox, prtad, devad,
-					 data->reg_num, data->val_in);
-		break;
-	default:
-		return -EOPNOTSUPP;
-	}
-	return ret;
-}
-
-static void cxgb_set_rxmode(struct net_device *dev)
-{
-	/* unfortunately we can't return errors to the stack */
-	set_rxmode(dev, -1, false);
-}
-
-static int cxgb_change_mtu(struct net_device *dev, int new_mtu)
-{
-	int ret;
-	struct port_info *pi = netdev_priv(dev);
-
-	if (new_mtu < 81 || new_mtu > MAX_MTU)         /* accommodate SACK */
-		return -EINVAL;
-	ret = t4_set_rxmode(pi->adapter, pi->adapter->fn, pi->viid, new_mtu, -1,
-			    -1, -1, -1, true);
-	if (!ret)
-		dev->mtu = new_mtu;
-	return ret;
-}
-
-static int cxgb_set_mac_addr(struct net_device *dev, void *p)
-{
-	int ret;
-	struct sockaddr *addr = p;
-	struct port_info *pi = netdev_priv(dev);
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EINVAL;
-
-	ret = t4_change_mac(pi->adapter, pi->adapter->fn, pi->viid,
-			    pi->xact_addr_filt, addr->sa_data, true, true);
-	if (ret < 0)
-		return ret;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-	pi->xact_addr_filt = ret;
-	return 0;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void cxgb_netpoll(struct net_device *dev)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adap = pi->adapter;
-
-	if (adap->flags & USING_MSIX) {
-		int i;
-		struct sge_eth_rxq *rx = &adap->sge.ethrxq[pi->first_qset];
-
-		for (i = pi->nqsets; i; i--, rx++)
-			t4_sge_intr_msix(0, &rx->rspq);
-	} else
-		t4_intr_handler(adap)(0, adap);
-}
-#endif
-
-static const struct net_device_ops cxgb4_netdev_ops = {
-	.ndo_open             = cxgb_open,
-	.ndo_stop             = cxgb_close,
-	.ndo_start_xmit       = t4_eth_xmit,
-	.ndo_get_stats64      = cxgb_get_stats,
-	.ndo_set_rx_mode      = cxgb_set_rxmode,
-	.ndo_set_mac_address  = cxgb_set_mac_addr,
-	.ndo_set_features     = cxgb_set_features,
-	.ndo_validate_addr    = eth_validate_addr,
-	.ndo_do_ioctl         = cxgb_ioctl,
-	.ndo_change_mtu       = cxgb_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller  = cxgb_netpoll,
-#endif
-};
-
-void t4_fatal_err(struct adapter *adap)
-{
-	t4_set_reg_field(adap, SGE_CONTROL, GLOBALENABLE, 0);
-	t4_intr_disable(adap);
-	dev_alert(adap->pdev_dev, "encountered fatal error, adapter stopped\n");
-}
-
-static void setup_memwin(struct adapter *adap)
-{
-	u32 bar0;
-
-	bar0 = pci_resource_start(adap->pdev, 0);  /* truncation intentional */
-	t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 0),
-		     (bar0 + MEMWIN0_BASE) | BIR(0) |
-		     WINDOW(ilog2(MEMWIN0_APERTURE) - 10));
-	t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 1),
-		     (bar0 + MEMWIN1_BASE) | BIR(0) |
-		     WINDOW(ilog2(MEMWIN1_APERTURE) - 10));
-	t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2),
-		     (bar0 + MEMWIN2_BASE) | BIR(0) |
-		     WINDOW(ilog2(MEMWIN2_APERTURE) - 10));
-	if (adap->vres.ocq.size) {
-		unsigned int start, sz_kb;
-
-		start = pci_resource_start(adap->pdev, 2) +
-			OCQ_WIN_OFFSET(adap->pdev, &adap->vres);
-		sz_kb = roundup_pow_of_two(adap->vres.ocq.size) >> 10;
-		t4_write_reg(adap,
-			     PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 3),
-			     start | BIR(1) | WINDOW(ilog2(sz_kb)));
-		t4_write_reg(adap,
-			     PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, 3),
-			     adap->vres.ocq.start);
-		t4_read_reg(adap,
-			    PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, 3));
-	}
-}
-
-static int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c)
-{
-	u32 v;
-	int ret;
-
-	/* get device capabilities */
-	memset(c, 0, sizeof(*c));
-	c->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
-			       FW_CMD_REQUEST | FW_CMD_READ);
-	c->retval_len16 = htonl(FW_LEN16(*c));
-	ret = t4_wr_mbox(adap, adap->fn, c, sizeof(*c), c);
-	if (ret < 0)
-		return ret;
-
-	/* select capabilities we'll be using */
-	if (c->niccaps & htons(FW_CAPS_CONFIG_NIC_VM)) {
-		if (!vf_acls)
-			c->niccaps ^= htons(FW_CAPS_CONFIG_NIC_VM);
-		else
-			c->niccaps = htons(FW_CAPS_CONFIG_NIC_VM);
-	} else if (vf_acls) {
-		dev_err(adap->pdev_dev, "virtualization ACLs not supported");
-		return ret;
-	}
-	c->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
-			       FW_CMD_REQUEST | FW_CMD_WRITE);
-	ret = t4_wr_mbox(adap, adap->fn, c, sizeof(*c), NULL);
-	if (ret < 0)
-		return ret;
-
-	ret = t4_config_glbl_rss(adap, adap->fn,
-				 FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL,
-				 FW_RSS_GLB_CONFIG_CMD_TNLMAPEN |
-				 FW_RSS_GLB_CONFIG_CMD_TNLALLLKP);
-	if (ret < 0)
-		return ret;
-
-	ret = t4_cfg_pfvf(adap, adap->fn, adap->fn, 0, MAX_EGRQ, 64, MAX_INGQ,
-			  0, 0, 4, 0xf, 0xf, 16, FW_CMD_CAP_PF, FW_CMD_CAP_PF);
-	if (ret < 0)
-		return ret;
-
-	t4_sge_init(adap);
-
-	/* tweak some settings */
-	t4_write_reg(adap, TP_SHIFT_CNT, 0x64f8849);
-	t4_write_reg(adap, ULP_RX_TDDP_PSZ, HPZ0(PAGE_SHIFT - 12));
-	t4_write_reg(adap, TP_PIO_ADDR, TP_INGRESS_CONFIG);
-	v = t4_read_reg(adap, TP_PIO_DATA);
-	t4_write_reg(adap, TP_PIO_DATA, v & ~CSUM_HAS_PSEUDO_HDR);
-
-	/* get basic stuff going */
-	return t4_early_init(adap, adap->fn);
-}
-
-/*
- * Max # of ATIDs.  The absolute HW max is 16K but we keep it lower.
- */
-#define MAX_ATIDS 8192U
-
-/*
- * Phase 0 of initialization: contact FW, obtain config, perform basic init.
- */
-static int adap_init0(struct adapter *adap)
-{
-	int ret;
-	u32 v, port_vec;
-	enum dev_state state;
-	u32 params[7], val[7];
-	struct fw_caps_config_cmd c;
-
-	ret = t4_check_fw_version(adap);
-	if (ret == -EINVAL || ret > 0) {
-		if (upgrade_fw(adap) >= 0)             /* recache FW version */
-			ret = t4_check_fw_version(adap);
-	}
-	if (ret < 0)
-		return ret;
-
-	/* contact FW, request master */
-	ret = t4_fw_hello(adap, adap->fn, adap->fn, MASTER_MUST, &state);
-	if (ret < 0) {
-		dev_err(adap->pdev_dev, "could not connect to FW, error %d\n",
-			ret);
-		return ret;
-	}
-
-	/* reset device */
-	ret = t4_fw_reset(adap, adap->fn, PIORSTMODE | PIORST);
-	if (ret < 0)
-		goto bye;
-
-	for (v = 0; v < SGE_NTIMERS - 1; v++)
-		adap->sge.timer_val[v] = min(intr_holdoff[v], MAX_SGE_TIMERVAL);
-	adap->sge.timer_val[SGE_NTIMERS - 1] = MAX_SGE_TIMERVAL;
-	adap->sge.counter_val[0] = 1;
-	for (v = 1; v < SGE_NCOUNTERS; v++)
-		adap->sge.counter_val[v] = min(intr_cnt[v - 1],
-					       THRESHOLD_3_MASK);
-#define FW_PARAM_DEV(param) \
-	(FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \
-	 FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param))
-
-	params[0] = FW_PARAM_DEV(CCLK);
-	ret = t4_query_params(adap, adap->fn, adap->fn, 0, 1, params, val);
-	if (ret < 0)
-		goto bye;
-	adap->params.vpd.cclk = val[0];
-
-	ret = adap_init1(adap, &c);
-	if (ret < 0)
-		goto bye;
-
-#define FW_PARAM_PFVF(param) \
-	(FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \
-	 FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param) | \
-	 FW_PARAMS_PARAM_Y(adap->fn))
-
-	params[0] = FW_PARAM_DEV(PORTVEC);
-	params[1] = FW_PARAM_PFVF(L2T_START);
-	params[2] = FW_PARAM_PFVF(L2T_END);
-	params[3] = FW_PARAM_PFVF(FILTER_START);
-	params[4] = FW_PARAM_PFVF(FILTER_END);
-	params[5] = FW_PARAM_PFVF(IQFLINT_START);
-	params[6] = FW_PARAM_PFVF(EQ_START);
-	ret = t4_query_params(adap, adap->fn, adap->fn, 0, 7, params, val);
-	if (ret < 0)
-		goto bye;
-	port_vec = val[0];
-	adap->tids.ftid_base = val[3];
-	adap->tids.nftids = val[4] - val[3] + 1;
-	adap->sge.ingr_start = val[5];
-	adap->sge.egr_start = val[6];
-
-	if (c.ofldcaps) {
-		/* query offload-related parameters */
-		params[0] = FW_PARAM_DEV(NTID);
-		params[1] = FW_PARAM_PFVF(SERVER_START);
-		params[2] = FW_PARAM_PFVF(SERVER_END);
-		params[3] = FW_PARAM_PFVF(TDDP_START);
-		params[4] = FW_PARAM_PFVF(TDDP_END);
-		params[5] = FW_PARAM_DEV(FLOWC_BUFFIFO_SZ);
-		ret = t4_query_params(adap, adap->fn, adap->fn, 0, 6, params,
-				      val);
-		if (ret < 0)
-			goto bye;
-		adap->tids.ntids = val[0];
-		adap->tids.natids = min(adap->tids.ntids / 2, MAX_ATIDS);
-		adap->tids.stid_base = val[1];
-		adap->tids.nstids = val[2] - val[1] + 1;
-		adap->vres.ddp.start = val[3];
-		adap->vres.ddp.size = val[4] - val[3] + 1;
-		adap->params.ofldq_wr_cred = val[5];
-		adap->params.offload = 1;
-	}
-	if (c.rdmacaps) {
-		params[0] = FW_PARAM_PFVF(STAG_START);
-		params[1] = FW_PARAM_PFVF(STAG_END);
-		params[2] = FW_PARAM_PFVF(RQ_START);
-		params[3] = FW_PARAM_PFVF(RQ_END);
-		params[4] = FW_PARAM_PFVF(PBL_START);
-		params[5] = FW_PARAM_PFVF(PBL_END);
-		ret = t4_query_params(adap, adap->fn, adap->fn, 0, 6, params,
-				      val);
-		if (ret < 0)
-			goto bye;
-		adap->vres.stag.start = val[0];
-		adap->vres.stag.size = val[1] - val[0] + 1;
-		adap->vres.rq.start = val[2];
-		adap->vres.rq.size = val[3] - val[2] + 1;
-		adap->vres.pbl.start = val[4];
-		adap->vres.pbl.size = val[5] - val[4] + 1;
-
-		params[0] = FW_PARAM_PFVF(SQRQ_START);
-		params[1] = FW_PARAM_PFVF(SQRQ_END);
-		params[2] = FW_PARAM_PFVF(CQ_START);
-		params[3] = FW_PARAM_PFVF(CQ_END);
-		params[4] = FW_PARAM_PFVF(OCQ_START);
-		params[5] = FW_PARAM_PFVF(OCQ_END);
-		ret = t4_query_params(adap, adap->fn, adap->fn, 0, 6, params,
-				      val);
-		if (ret < 0)
-			goto bye;
-		adap->vres.qp.start = val[0];
-		adap->vres.qp.size = val[1] - val[0] + 1;
-		adap->vres.cq.start = val[2];
-		adap->vres.cq.size = val[3] - val[2] + 1;
-		adap->vres.ocq.start = val[4];
-		adap->vres.ocq.size = val[5] - val[4] + 1;
-	}
-	if (c.iscsicaps) {
-		params[0] = FW_PARAM_PFVF(ISCSI_START);
-		params[1] = FW_PARAM_PFVF(ISCSI_END);
-		ret = t4_query_params(adap, adap->fn, adap->fn, 0, 2, params,
-				      val);
-		if (ret < 0)
-			goto bye;
-		adap->vres.iscsi.start = val[0];
-		adap->vres.iscsi.size = val[1] - val[0] + 1;
-	}
-#undef FW_PARAM_PFVF
-#undef FW_PARAM_DEV
-
-	adap->params.nports = hweight32(port_vec);
-	adap->params.portvec = port_vec;
-	adap->flags |= FW_OK;
-
-	/* These are finalized by FW initialization, load their values now */
-	v = t4_read_reg(adap, TP_TIMER_RESOLUTION);
-	adap->params.tp.tre = TIMERRESOLUTION_GET(v);
-	t4_read_mtu_tbl(adap, adap->params.mtus, NULL);
-	t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd,
-		     adap->params.b_wnd);
-
-#ifdef CONFIG_PCI_IOV
-	/*
-	 * Provision resource limits for Virtual Functions.  We currently
-	 * grant them all the same static resource limits except for the Port
-	 * Access Rights Mask which we're assigning based on the PF.  All of
-	 * the static provisioning stuff for both the PF and VF really needs
-	 * to be managed in a persistent manner for each device which the
-	 * firmware controls.
-	 */
-	{
-		int pf, vf;
-
-		for (pf = 0; pf < ARRAY_SIZE(num_vf); pf++) {
-			if (num_vf[pf] <= 0)
-				continue;
-
-			/* VF numbering starts at 1! */
-			for (vf = 1; vf <= num_vf[pf]; vf++) {
-				ret = t4_cfg_pfvf(adap, adap->fn, pf, vf,
-						  VFRES_NEQ, VFRES_NETHCTRL,
-						  VFRES_NIQFLINT, VFRES_NIQ,
-						  VFRES_TC, VFRES_NVI,
-						  FW_PFVF_CMD_CMASK_MASK,
-						  pfvfres_pmask(adap, pf, vf),
-						  VFRES_NEXACTF,
-						  VFRES_R_CAPS, VFRES_WX_CAPS);
-				if (ret < 0)
-					dev_warn(adap->pdev_dev, "failed to "
-						 "provision pf/vf=%d/%d; "
-						 "err=%d\n", pf, vf, ret);
-			}
-		}
-	}
-#endif
-
-	setup_memwin(adap);
-	return 0;
-
-	/*
-	 * If a command timed out or failed with EIO FW does not operate within
-	 * its spec or something catastrophic happened to HW/FW, stop issuing
-	 * commands.
-	 */
-bye:	if (ret != -ETIMEDOUT && ret != -EIO)
-		t4_fw_bye(adap, adap->fn);
-	return ret;
-}
-
-/* EEH callbacks */
-
-static pci_ers_result_t eeh_err_detected(struct pci_dev *pdev,
-					 pci_channel_state_t state)
-{
-	int i;
-	struct adapter *adap = pci_get_drvdata(pdev);
-
-	if (!adap)
-		goto out;
-
-	rtnl_lock();
-	adap->flags &= ~FW_OK;
-	notify_ulds(adap, CXGB4_STATE_START_RECOVERY);
-	for_each_port(adap, i) {
-		struct net_device *dev = adap->port[i];
-
-		netif_device_detach(dev);
-		netif_carrier_off(dev);
-	}
-	if (adap->flags & FULL_INIT_DONE)
-		cxgb_down(adap);
-	rtnl_unlock();
-	pci_disable_device(pdev);
-out:	return state == pci_channel_io_perm_failure ?
-		PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET;
-}
-
-static pci_ers_result_t eeh_slot_reset(struct pci_dev *pdev)
-{
-	int i, ret;
-	struct fw_caps_config_cmd c;
-	struct adapter *adap = pci_get_drvdata(pdev);
-
-	if (!adap) {
-		pci_restore_state(pdev);
-		pci_save_state(pdev);
-		return PCI_ERS_RESULT_RECOVERED;
-	}
-
-	if (pci_enable_device(pdev)) {
-		dev_err(&pdev->dev, "cannot reenable PCI device after reset\n");
-		return PCI_ERS_RESULT_DISCONNECT;
-	}
-
-	pci_set_master(pdev);
-	pci_restore_state(pdev);
-	pci_save_state(pdev);
-	pci_cleanup_aer_uncorrect_error_status(pdev);
-
-	if (t4_wait_dev_ready(adap) < 0)
-		return PCI_ERS_RESULT_DISCONNECT;
-	if (t4_fw_hello(adap, adap->fn, adap->fn, MASTER_MUST, NULL))
-		return PCI_ERS_RESULT_DISCONNECT;
-	adap->flags |= FW_OK;
-	if (adap_init1(adap, &c))
-		return PCI_ERS_RESULT_DISCONNECT;
-
-	for_each_port(adap, i) {
-		struct port_info *p = adap2pinfo(adap, i);
-
-		ret = t4_alloc_vi(adap, adap->fn, p->tx_chan, adap->fn, 0, 1,
-				  NULL, NULL);
-		if (ret < 0)
-			return PCI_ERS_RESULT_DISCONNECT;
-		p->viid = ret;
-		p->xact_addr_filt = -1;
-	}
-
-	t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd,
-		     adap->params.b_wnd);
-	setup_memwin(adap);
-	if (cxgb_up(adap))
-		return PCI_ERS_RESULT_DISCONNECT;
-	return PCI_ERS_RESULT_RECOVERED;
-}
-
-static void eeh_resume(struct pci_dev *pdev)
-{
-	int i;
-	struct adapter *adap = pci_get_drvdata(pdev);
-
-	if (!adap)
-		return;
-
-	rtnl_lock();
-	for_each_port(adap, i) {
-		struct net_device *dev = adap->port[i];
-
-		if (netif_running(dev)) {
-			link_start(dev);
-			cxgb_set_rxmode(dev);
-		}
-		netif_device_attach(dev);
-	}
-	rtnl_unlock();
-}
-
-static struct pci_error_handlers cxgb4_eeh = {
-	.error_detected = eeh_err_detected,
-	.slot_reset     = eeh_slot_reset,
-	.resume         = eeh_resume,
-};
-
-static inline bool is_10g_port(const struct link_config *lc)
-{
-	return (lc->supported & FW_PORT_CAP_SPEED_10G) != 0;
-}
-
-static inline void init_rspq(struct sge_rspq *q, u8 timer_idx, u8 pkt_cnt_idx,
-			     unsigned int size, unsigned int iqe_size)
-{
-	q->intr_params = QINTR_TIMER_IDX(timer_idx) |
-			 (pkt_cnt_idx < SGE_NCOUNTERS ? QINTR_CNT_EN : 0);
-	q->pktcnt_idx = pkt_cnt_idx < SGE_NCOUNTERS ? pkt_cnt_idx : 0;
-	q->iqe_len = iqe_size;
-	q->size = size;
-}
-
-/*
- * Perform default configuration of DMA queues depending on the number and type
- * of ports we found and the number of available CPUs.  Most settings can be
- * modified by the admin prior to actual use.
- */
-static void __devinit cfg_queues(struct adapter *adap)
-{
-	struct sge *s = &adap->sge;
-	int i, q10g = 0, n10g = 0, qidx = 0;
-
-	for_each_port(adap, i)
-		n10g += is_10g_port(&adap2pinfo(adap, i)->link_cfg);
-
-	/*
-	 * We default to 1 queue per non-10G port and up to # of cores queues
-	 * per 10G port.
-	 */
-	if (n10g)
-		q10g = (MAX_ETH_QSETS - (adap->params.nports - n10g)) / n10g;
-	if (q10g > num_online_cpus())
-		q10g = num_online_cpus();
-
-	for_each_port(adap, i) {
-		struct port_info *pi = adap2pinfo(adap, i);
-
-		pi->first_qset = qidx;
-		pi->nqsets = is_10g_port(&pi->link_cfg) ? q10g : 1;
-		qidx += pi->nqsets;
-	}
-
-	s->ethqsets = qidx;
-	s->max_ethqsets = qidx;   /* MSI-X may lower it later */
-
-	if (is_offload(adap)) {
-		/*
-		 * For offload we use 1 queue/channel if all ports are up to 1G,
-		 * otherwise we divide all available queues amongst the channels
-		 * capped by the number of available cores.
-		 */
-		if (n10g) {
-			i = min_t(int, ARRAY_SIZE(s->ofldrxq),
-				  num_online_cpus());
-			s->ofldqsets = roundup(i, adap->params.nports);
-		} else
-			s->ofldqsets = adap->params.nports;
-		/* For RDMA one Rx queue per channel suffices */
-		s->rdmaqs = adap->params.nports;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(s->ethrxq); i++) {
-		struct sge_eth_rxq *r = &s->ethrxq[i];
-
-		init_rspq(&r->rspq, 0, 0, 1024, 64);
-		r->fl.size = 72;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(s->ethtxq); i++)
-		s->ethtxq[i].q.size = 1024;
-
-	for (i = 0; i < ARRAY_SIZE(s->ctrlq); i++)
-		s->ctrlq[i].q.size = 512;
-
-	for (i = 0; i < ARRAY_SIZE(s->ofldtxq); i++)
-		s->ofldtxq[i].q.size = 1024;
-
-	for (i = 0; i < ARRAY_SIZE(s->ofldrxq); i++) {
-		struct sge_ofld_rxq *r = &s->ofldrxq[i];
-
-		init_rspq(&r->rspq, 0, 0, 1024, 64);
-		r->rspq.uld = CXGB4_ULD_ISCSI;
-		r->fl.size = 72;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(s->rdmarxq); i++) {
-		struct sge_ofld_rxq *r = &s->rdmarxq[i];
-
-		init_rspq(&r->rspq, 0, 0, 511, 64);
-		r->rspq.uld = CXGB4_ULD_RDMA;
-		r->fl.size = 72;
-	}
-
-	init_rspq(&s->fw_evtq, 6, 0, 512, 64);
-	init_rspq(&s->intrq, 6, 0, 2 * MAX_INGQ, 64);
-}
-
-/*
- * Reduce the number of Ethernet queues across all ports to at most n.
- * n provides at least one queue per port.
- */
-static void __devinit reduce_ethqs(struct adapter *adap, int n)
-{
-	int i;
-	struct port_info *pi;
-
-	while (n < adap->sge.ethqsets)
-		for_each_port(adap, i) {
-			pi = adap2pinfo(adap, i);
-			if (pi->nqsets > 1) {
-				pi->nqsets--;
-				adap->sge.ethqsets--;
-				if (adap->sge.ethqsets <= n)
-					break;
-			}
-		}
-
-	n = 0;
-	for_each_port(adap, i) {
-		pi = adap2pinfo(adap, i);
-		pi->first_qset = n;
-		n += pi->nqsets;
-	}
-}
-
-/* 2 MSI-X vectors needed for the FW queue and non-data interrupts */
-#define EXTRA_VECS 2
-
-static int __devinit enable_msix(struct adapter *adap)
-{
-	int ofld_need = 0;
-	int i, err, want, need;
-	struct sge *s = &adap->sge;
-	unsigned int nchan = adap->params.nports;
-	struct msix_entry entries[MAX_INGQ + 1];
-
-	for (i = 0; i < ARRAY_SIZE(entries); ++i)
-		entries[i].entry = i;
-
-	want = s->max_ethqsets + EXTRA_VECS;
-	if (is_offload(adap)) {
-		want += s->rdmaqs + s->ofldqsets;
-		/* need nchan for each possible ULD */
-		ofld_need = 2 * nchan;
-	}
-	need = adap->params.nports + EXTRA_VECS + ofld_need;
-
-	while ((err = pci_enable_msix(adap->pdev, entries, want)) >= need)
-		want = err;
-
-	if (!err) {
-		/*
-		 * Distribute available vectors to the various queue groups.
-		 * Every group gets its minimum requirement and NIC gets top
-		 * priority for leftovers.
-		 */
-		i = want - EXTRA_VECS - ofld_need;
-		if (i < s->max_ethqsets) {
-			s->max_ethqsets = i;
-			if (i < s->ethqsets)
-				reduce_ethqs(adap, i);
-		}
-		if (is_offload(adap)) {
-			i = want - EXTRA_VECS - s->max_ethqsets;
-			i -= ofld_need - nchan;
-			s->ofldqsets = (i / nchan) * nchan;  /* round down */
-		}
-		for (i = 0; i < want; ++i)
-			adap->msix_info[i].vec = entries[i].vector;
-	} else if (err > 0)
-		dev_info(adap->pdev_dev,
-			 "only %d MSI-X vectors left, not using MSI-X\n", err);
-	return err;
-}
-
-#undef EXTRA_VECS
-
-static int __devinit init_rss(struct adapter *adap)
-{
-	unsigned int i, j;
-
-	for_each_port(adap, i) {
-		struct port_info *pi = adap2pinfo(adap, i);
-
-		pi->rss = kcalloc(pi->rss_size, sizeof(u16), GFP_KERNEL);
-		if (!pi->rss)
-			return -ENOMEM;
-		for (j = 0; j < pi->rss_size; j++)
-			pi->rss[j] = j % pi->nqsets;
-	}
-	return 0;
-}
-
-static void __devinit print_port_info(const struct net_device *dev)
-{
-	static const char *base[] = {
-		"R XFI", "R XAUI", "T SGMII", "T XFI", "T XAUI", "KX4", "CX4",
-		"KX", "KR", "R SFP+", "KR/KX", "KR/KX/KX4"
-	};
-
-	char buf[80];
-	char *bufp = buf;
-	const char *spd = "";
-	const struct port_info *pi = netdev_priv(dev);
-	const struct adapter *adap = pi->adapter;
-
-	if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_2_5GB)
-		spd = " 2.5 GT/s";
-	else if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_5_0GB)
-		spd = " 5 GT/s";
-
-	if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_100M)
-		bufp += sprintf(bufp, "100/");
-	if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_1G)
-		bufp += sprintf(bufp, "1000/");
-	if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G)
-		bufp += sprintf(bufp, "10G/");
-	if (bufp != buf)
-		--bufp;
-	sprintf(bufp, "BASE-%s", base[pi->port_type]);
-
-	netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s%s\n",
-		    adap->params.vpd.id, adap->params.rev, buf,
-		    is_offload(adap) ? "R" : "", adap->params.pci.width, spd,
-		    (adap->flags & USING_MSIX) ? " MSI-X" :
-		    (adap->flags & USING_MSI) ? " MSI" : "");
-	netdev_info(dev, "S/N: %s, E/C: %s\n",
-		    adap->params.vpd.sn, adap->params.vpd.ec);
-}
-
-static void __devinit enable_pcie_relaxed_ordering(struct pci_dev *dev)
-{
-	u16 v;
-	int pos;
-
-	pos = pci_pcie_cap(dev);
-	if (pos > 0) {
-		pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &v);
-		v |= PCI_EXP_DEVCTL_RELAX_EN;
-		pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, v);
-	}
-}
-
-/*
- * Free the following resources:
- * - memory used for tables
- * - MSI/MSI-X
- * - net devices
- * - resources FW is holding for us
- */
-static void free_some_resources(struct adapter *adapter)
-{
-	unsigned int i;
-
-	t4_free_mem(adapter->l2t);
-	t4_free_mem(adapter->tids.tid_tab);
-	disable_msi(adapter);
-
-	for_each_port(adapter, i)
-		if (adapter->port[i]) {
-			kfree(adap2pinfo(adapter, i)->rss);
-			free_netdev(adapter->port[i]);
-		}
-	if (adapter->flags & FW_OK)
-		t4_fw_bye(adapter, adapter->fn);
-}
-
-#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
-#define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \
-		   NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
-
-static int __devinit init_one(struct pci_dev *pdev,
-			      const struct pci_device_id *ent)
-{
-	int func, i, err;
-	struct port_info *pi;
-	unsigned int highdma = 0;
-	struct adapter *adapter = NULL;
-
-	printk_once(KERN_INFO "%s - version %s\n", DRV_DESC, DRV_VERSION);
-
-	err = pci_request_regions(pdev, KBUILD_MODNAME);
-	if (err) {
-		/* Just info, some other driver may have claimed the device. */
-		dev_info(&pdev->dev, "cannot obtain PCI resources\n");
-		return err;
-	}
-
-	/* We control everything through one PF */
-	func = PCI_FUNC(pdev->devfn);
-	if (func != ent->driver_data) {
-		pci_save_state(pdev);        /* to restore SR-IOV later */
-		goto sriov;
-	}
-
-	err = pci_enable_device(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "cannot enable PCI device\n");
-		goto out_release_regions;
-	}
-
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-		highdma = NETIF_F_HIGHDMA;
-		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
-		if (err) {
-			dev_err(&pdev->dev, "unable to obtain 64-bit DMA for "
-				"coherent allocations\n");
-			goto out_disable_device;
-		}
-	} else {
-		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-		if (err) {
-			dev_err(&pdev->dev, "no usable DMA configuration\n");
-			goto out_disable_device;
-		}
-	}
-
-	pci_enable_pcie_error_reporting(pdev);
-	enable_pcie_relaxed_ordering(pdev);
-	pci_set_master(pdev);
-	pci_save_state(pdev);
-
-	adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
-	if (!adapter) {
-		err = -ENOMEM;
-		goto out_disable_device;
-	}
-
-	adapter->regs = pci_ioremap_bar(pdev, 0);
-	if (!adapter->regs) {
-		dev_err(&pdev->dev, "cannot map device registers\n");
-		err = -ENOMEM;
-		goto out_free_adapter;
-	}
-
-	adapter->pdev = pdev;
-	adapter->pdev_dev = &pdev->dev;
-	adapter->fn = func;
-	adapter->msg_enable = dflt_msg_enable;
-	memset(adapter->chan_map, 0xff, sizeof(adapter->chan_map));
-
-	spin_lock_init(&adapter->stats_lock);
-	spin_lock_init(&adapter->tid_release_lock);
-
-	INIT_WORK(&adapter->tid_release_task, process_tid_release_list);
-
-	err = t4_prep_adapter(adapter);
-	if (err)
-		goto out_unmap_bar;
-	err = adap_init0(adapter);
-	if (err)
-		goto out_unmap_bar;
-
-	for_each_port(adapter, i) {
-		struct net_device *netdev;
-
-		netdev = alloc_etherdev_mq(sizeof(struct port_info),
-					   MAX_ETH_QSETS);
-		if (!netdev) {
-			err = -ENOMEM;
-			goto out_free_dev;
-		}
-
-		SET_NETDEV_DEV(netdev, &pdev->dev);
-
-		adapter->port[i] = netdev;
-		pi = netdev_priv(netdev);
-		pi->adapter = adapter;
-		pi->xact_addr_filt = -1;
-		pi->port_id = i;
-		netdev->irq = pdev->irq;
-
-		netdev->hw_features = NETIF_F_SG | TSO_FLAGS |
-			NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-			NETIF_F_RXCSUM | NETIF_F_RXHASH |
-			NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-		netdev->features |= netdev->hw_features | highdma;
-		netdev->vlan_features = netdev->features & VLAN_FEAT;
-
-		netdev->netdev_ops = &cxgb4_netdev_ops;
-		SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops);
-	}
-
-	pci_set_drvdata(pdev, adapter);
-
-	if (adapter->flags & FW_OK) {
-		err = t4_port_init(adapter, func, func, 0);
-		if (err)
-			goto out_free_dev;
-	}
-
-	/*
-	 * Configure queues and allocate tables now, they can be needed as
-	 * soon as the first register_netdev completes.
-	 */
-	cfg_queues(adapter);
-
-	adapter->l2t = t4_init_l2t();
-	if (!adapter->l2t) {
-		/* We tolerate a lack of L2T, giving up some functionality */
-		dev_warn(&pdev->dev, "could not allocate L2T, continuing\n");
-		adapter->params.offload = 0;
-	}
-
-	if (is_offload(adapter) && tid_init(&adapter->tids) < 0) {
-		dev_warn(&pdev->dev, "could not allocate TID table, "
-			 "continuing\n");
-		adapter->params.offload = 0;
-	}
-
-	/* See what interrupts we'll be using */
-	if (msi > 1 && enable_msix(adapter) == 0)
-		adapter->flags |= USING_MSIX;
-	else if (msi > 0 && pci_enable_msi(pdev) == 0)
-		adapter->flags |= USING_MSI;
-
-	err = init_rss(adapter);
-	if (err)
-		goto out_free_dev;
-
-	/*
-	 * The card is now ready to go.  If any errors occur during device
-	 * registration we do not fail the whole card but rather proceed only
-	 * with the ports we manage to register successfully.  However we must
-	 * register at least one net device.
-	 */
-	for_each_port(adapter, i) {
-		pi = adap2pinfo(adapter, i);
-		netif_set_real_num_tx_queues(adapter->port[i], pi->nqsets);
-		netif_set_real_num_rx_queues(adapter->port[i], pi->nqsets);
-
-		err = register_netdev(adapter->port[i]);
-		if (err)
-			break;
-		adapter->chan_map[pi->tx_chan] = i;
-		print_port_info(adapter->port[i]);
-	}
-	if (i == 0) {
-		dev_err(&pdev->dev, "could not register any net devices\n");
-		goto out_free_dev;
-	}
-	if (err) {
-		dev_warn(&pdev->dev, "only %d net devices registered\n", i);
-		err = 0;
-	}
-
-	if (cxgb4_debugfs_root) {
-		adapter->debugfs_root = debugfs_create_dir(pci_name(pdev),
-							   cxgb4_debugfs_root);
-		setup_debugfs(adapter);
-	}
-
-	/* PCIe EEH recovery on powerpc platforms needs fundamental reset */
-	pdev->needs_freset = 1;
-
-	if (is_offload(adapter))
-		attach_ulds(adapter);
-
-sriov:
-#ifdef CONFIG_PCI_IOV
-	if (func < ARRAY_SIZE(num_vf) && num_vf[func] > 0)
-		if (pci_enable_sriov(pdev, num_vf[func]) == 0)
-			dev_info(&pdev->dev,
-				 "instantiated %u virtual functions\n",
-				 num_vf[func]);
-#endif
-	return 0;
-
- out_free_dev:
-	free_some_resources(adapter);
- out_unmap_bar:
-	iounmap(adapter->regs);
- out_free_adapter:
-	kfree(adapter);
- out_disable_device:
-	pci_disable_pcie_error_reporting(pdev);
-	pci_disable_device(pdev);
- out_release_regions:
-	pci_release_regions(pdev);
-	pci_set_drvdata(pdev, NULL);
-	return err;
-}
-
-static void __devexit remove_one(struct pci_dev *pdev)
-{
-	struct adapter *adapter = pci_get_drvdata(pdev);
-
-	pci_disable_sriov(pdev);
-
-	if (adapter) {
-		int i;
-
-		if (is_offload(adapter))
-			detach_ulds(adapter);
-
-		for_each_port(adapter, i)
-			if (adapter->port[i]->reg_state == NETREG_REGISTERED)
-				unregister_netdev(adapter->port[i]);
-
-		if (adapter->debugfs_root)
-			debugfs_remove_recursive(adapter->debugfs_root);
-
-		if (adapter->flags & FULL_INIT_DONE)
-			cxgb_down(adapter);
-
-		free_some_resources(adapter);
-		iounmap(adapter->regs);
-		kfree(adapter);
-		pci_disable_pcie_error_reporting(pdev);
-		pci_disable_device(pdev);
-		pci_release_regions(pdev);
-		pci_set_drvdata(pdev, NULL);
-	} else
-		pci_release_regions(pdev);
-}
-
-static struct pci_driver cxgb4_driver = {
-	.name     = KBUILD_MODNAME,
-	.id_table = cxgb4_pci_tbl,
-	.probe    = init_one,
-	.remove   = __devexit_p(remove_one),
-	.err_handler = &cxgb4_eeh,
-};
-
-static int __init cxgb4_init_module(void)
-{
-	int ret;
-
-	/* Debugfs support is optional, just warn if this fails */
-	cxgb4_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
-	if (!cxgb4_debugfs_root)
-		pr_warning("could not create debugfs entry, continuing\n");
-
-	ret = pci_register_driver(&cxgb4_driver);
-	if (ret < 0)
-		debugfs_remove(cxgb4_debugfs_root);
-	return ret;
-}
-
-static void __exit cxgb4_cleanup_module(void)
-{
-	pci_unregister_driver(&cxgb4_driver);
-	debugfs_remove(cxgb4_debugfs_root);  /* NULL ok */
-}
-
-module_init(cxgb4_init_module);
-module_exit(cxgb4_cleanup_module);
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4/cxgb4_uld.h linux-libre-3.2-gnu/drivers/net/cxgb4/cxgb4_uld.h
--- linux-libre-3.1-gnu/drivers/net/cxgb4/cxgb4_uld.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4/cxgb4_uld.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,239 +0,0 @@
-/*
- * This file is part of the Chelsio T4 Ethernet driver for Linux.
- *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __CXGB4_OFLD_H
-#define __CXGB4_OFLD_H
-
-#include <linux/cache.h>
-#include <linux/spinlock.h>
-#include <linux/skbuff.h>
-#include <linux/atomic.h>
-
-/* CPL message priority levels */
-enum {
-	CPL_PRIORITY_DATA     = 0,  /* data messages */
-	CPL_PRIORITY_SETUP    = 1,  /* connection setup messages */
-	CPL_PRIORITY_TEARDOWN = 0,  /* connection teardown messages */
-	CPL_PRIORITY_LISTEN   = 1,  /* listen start/stop messages */
-	CPL_PRIORITY_ACK      = 1,  /* RX ACK messages */
-	CPL_PRIORITY_CONTROL  = 1   /* control messages */
-};
-
-#define INIT_TP_WR(w, tid) do { \
-	(w)->wr.wr_hi = htonl(FW_WR_OP(FW_TP_WR) | \
-			      FW_WR_IMMDLEN(sizeof(*w) - sizeof(w->wr))); \
-	(w)->wr.wr_mid = htonl(FW_WR_LEN16(DIV_ROUND_UP(sizeof(*w), 16)) | \
-			       FW_WR_FLOWID(tid)); \
-	(w)->wr.wr_lo = cpu_to_be64(0); \
-} while (0)
-
-#define INIT_TP_WR_CPL(w, cpl, tid) do { \
-	INIT_TP_WR(w, tid); \
-	OPCODE_TID(w) = htonl(MK_OPCODE_TID(cpl, tid)); \
-} while (0)
-
-#define INIT_ULPTX_WR(w, wrlen, atomic, tid) do { \
-	(w)->wr.wr_hi = htonl(FW_WR_OP(FW_ULPTX_WR) | FW_WR_ATOMIC(atomic)); \
-	(w)->wr.wr_mid = htonl(FW_WR_LEN16(DIV_ROUND_UP(wrlen, 16)) | \
-			       FW_WR_FLOWID(tid)); \
-	(w)->wr.wr_lo = cpu_to_be64(0); \
-} while (0)
-
-/* Special asynchronous notification message */
-#define CXGB4_MSG_AN ((void *)1)
-
-struct serv_entry {
-	void *data;
-};
-
-union aopen_entry {
-	void *data;
-	union aopen_entry *next;
-};
-
-/*
- * Holds the size, base address, free list start, etc of the TID, server TID,
- * and active-open TID tables.  The tables themselves are allocated dynamically.
- */
-struct tid_info {
-	void **tid_tab;
-	unsigned int ntids;
-
-	struct serv_entry *stid_tab;
-	unsigned long *stid_bmap;
-	unsigned int nstids;
-	unsigned int stid_base;
-
-	union aopen_entry *atid_tab;
-	unsigned int natids;
-
-	unsigned int nftids;
-	unsigned int ftid_base;
-
-	spinlock_t atid_lock ____cacheline_aligned_in_smp;
-	union aopen_entry *afree;
-	unsigned int atids_in_use;
-
-	spinlock_t stid_lock;
-	unsigned int stids_in_use;
-
-	atomic_t tids_in_use;
-};
-
-static inline void *lookup_tid(const struct tid_info *t, unsigned int tid)
-{
-	return tid < t->ntids ? t->tid_tab[tid] : NULL;
-}
-
-static inline void *lookup_atid(const struct tid_info *t, unsigned int atid)
-{
-	return atid < t->natids ? t->atid_tab[atid].data : NULL;
-}
-
-static inline void *lookup_stid(const struct tid_info *t, unsigned int stid)
-{
-	stid -= t->stid_base;
-	return stid < t->nstids ? t->stid_tab[stid].data : NULL;
-}
-
-static inline void cxgb4_insert_tid(struct tid_info *t, void *data,
-				    unsigned int tid)
-{
-	t->tid_tab[tid] = data;
-	atomic_inc(&t->tids_in_use);
-}
-
-int cxgb4_alloc_atid(struct tid_info *t, void *data);
-int cxgb4_alloc_stid(struct tid_info *t, int family, void *data);
-void cxgb4_free_atid(struct tid_info *t, unsigned int atid);
-void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family);
-void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid);
-
-struct in6_addr;
-
-int cxgb4_create_server(const struct net_device *dev, unsigned int stid,
-			__be32 sip, __be16 sport, unsigned int queue);
-
-static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue)
-{
-	skb_set_queue_mapping(skb, (queue << 1) | prio);
-}
-
-enum cxgb4_uld {
-	CXGB4_ULD_RDMA,
-	CXGB4_ULD_ISCSI,
-	CXGB4_ULD_MAX
-};
-
-enum cxgb4_state {
-	CXGB4_STATE_UP,
-	CXGB4_STATE_START_RECOVERY,
-	CXGB4_STATE_DOWN,
-	CXGB4_STATE_DETACH
-};
-
-struct pci_dev;
-struct l2t_data;
-struct net_device;
-struct pkt_gl;
-struct tp_tcp_stats;
-
-struct cxgb4_range {
-	unsigned int start;
-	unsigned int size;
-};
-
-struct cxgb4_virt_res {                      /* virtualized HW resources */
-	struct cxgb4_range ddp;
-	struct cxgb4_range iscsi;
-	struct cxgb4_range stag;
-	struct cxgb4_range rq;
-	struct cxgb4_range pbl;
-	struct cxgb4_range qp;
-	struct cxgb4_range cq;
-	struct cxgb4_range ocq;
-};
-
-#define OCQ_WIN_OFFSET(pdev, vres) \
-	(pci_resource_len((pdev), 2) - roundup_pow_of_two((vres)->ocq.size))
-
-/*
- * Block of information the LLD provides to ULDs attaching to a device.
- */
-struct cxgb4_lld_info {
-	struct pci_dev *pdev;                /* associated PCI device */
-	struct l2t_data *l2t;                /* L2 table */
-	struct tid_info *tids;               /* TID table */
-	struct net_device **ports;           /* device ports */
-	const struct cxgb4_virt_res *vr;     /* assorted HW resources */
-	const unsigned short *mtus;          /* MTU table */
-	const unsigned short *rxq_ids;       /* the ULD's Rx queue ids */
-	unsigned short nrxq;                 /* # of Rx queues */
-	unsigned short ntxq;                 /* # of Tx queues */
-	unsigned char nchan:4;               /* # of channels */
-	unsigned char nports:4;              /* # of ports */
-	unsigned char wr_cred;               /* WR 16-byte credits */
-	unsigned char adapter_type;          /* type of adapter */
-	unsigned char fw_api_ver;            /* FW API version */
-	unsigned int fw_vers;                /* FW version */
-	unsigned int iscsi_iolen;            /* iSCSI max I/O length */
-	unsigned short udb_density;          /* # of user DB/page */
-	unsigned short ucq_density;          /* # of user CQs/page */
-	void __iomem *gts_reg;               /* address of GTS register */
-	void __iomem *db_reg;                /* address of kernel doorbell */
-};
-
-struct cxgb4_uld_info {
-	const char *name;
-	void *(*add)(const struct cxgb4_lld_info *p);
-	int (*rx_handler)(void *handle, const __be64 *rsp,
-			  const struct pkt_gl *gl);
-	int (*state_change)(void *handle, enum cxgb4_state new_state);
-};
-
-int cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p);
-int cxgb4_unregister_uld(enum cxgb4_uld type);
-int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb);
-unsigned int cxgb4_port_chan(const struct net_device *dev);
-unsigned int cxgb4_port_viid(const struct net_device *dev);
-unsigned int cxgb4_port_idx(const struct net_device *dev);
-unsigned int cxgb4_best_mtu(const unsigned short *mtus, unsigned short mtu,
-			    unsigned int *idx);
-void cxgb4_get_tcp_stats(struct pci_dev *pdev, struct tp_tcp_stats *v4,
-			 struct tp_tcp_stats *v6);
-void cxgb4_iscsi_init(struct net_device *dev, unsigned int tag_mask,
-		      const unsigned int *pgsz_order);
-struct sk_buff *cxgb4_pktgl_to_skb(const struct pkt_gl *gl,
-				   unsigned int skb_len, unsigned int pull_len);
-#endif  /* !__CXGB4_OFLD_H */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4/l2t.c linux-libre-3.2-gnu/drivers/net/cxgb4/l2t.c
--- linux-libre-3.1-gnu/drivers/net/cxgb4/l2t.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4/l2t.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,597 +0,0 @@
-/*
- * This file is part of the Chelsio T4 Ethernet driver for Linux.
- *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/if.h>
-#include <linux/if_vlan.h>
-#include <linux/jhash.h>
-#include <net/neighbour.h>
-#include "cxgb4.h"
-#include "l2t.h"
-#include "t4_msg.h"
-#include "t4fw_api.h"
-
-#define VLAN_NONE 0xfff
-
-/* identifies sync vs async L2T_WRITE_REQs */
-#define F_SYNC_WR    (1 << 12)
-
-enum {
-	L2T_STATE_VALID,      /* entry is up to date */
-	L2T_STATE_STALE,      /* entry may be used but needs revalidation */
-	L2T_STATE_RESOLVING,  /* entry needs address resolution */
-	L2T_STATE_SYNC_WRITE, /* synchronous write of entry underway */
-
-	/* when state is one of the below the entry is not hashed */
-	L2T_STATE_SWITCHING,  /* entry is being used by a switching filter */
-	L2T_STATE_UNUSED      /* entry not in use */
-};
-
-struct l2t_data {
-	rwlock_t lock;
-	atomic_t nfree;             /* number of free entries */
-	struct l2t_entry *rover;    /* starting point for next allocation */
-	struct l2t_entry l2tab[L2T_SIZE];
-};
-
-static inline unsigned int vlan_prio(const struct l2t_entry *e)
-{
-	return e->vlan >> 13;
-}
-
-static inline void l2t_hold(struct l2t_data *d, struct l2t_entry *e)
-{
-	if (atomic_add_return(1, &e->refcnt) == 1)  /* 0 -> 1 transition */
-		atomic_dec(&d->nfree);
-}
-
-/*
- * To avoid having to check address families we do not allow v4 and v6
- * neighbors to be on the same hash chain.  We keep v4 entries in the first
- * half of available hash buckets and v6 in the second.
- */
-enum {
-	L2T_SZ_HALF = L2T_SIZE / 2,
-	L2T_HASH_MASK = L2T_SZ_HALF - 1
-};
-
-static inline unsigned int arp_hash(const u32 *key, int ifindex)
-{
-	return jhash_2words(*key, ifindex, 0) & L2T_HASH_MASK;
-}
-
-static inline unsigned int ipv6_hash(const u32 *key, int ifindex)
-{
-	u32 xor = key[0] ^ key[1] ^ key[2] ^ key[3];
-
-	return L2T_SZ_HALF + (jhash_2words(xor, ifindex, 0) & L2T_HASH_MASK);
-}
-
-static unsigned int addr_hash(const u32 *addr, int addr_len, int ifindex)
-{
-	return addr_len == 4 ? arp_hash(addr, ifindex) :
-			       ipv6_hash(addr, ifindex);
-}
-
-/*
- * Checks if an L2T entry is for the given IP/IPv6 address.  It does not check
- * whether the L2T entry and the address are of the same address family.
- * Callers ensure an address is only checked against L2T entries of the same
- * family, something made trivial by the separation of IP and IPv6 hash chains
- * mentioned above.  Returns 0 if there's a match,
- */
-static int addreq(const struct l2t_entry *e, const u32 *addr)
-{
-	if (e->v6)
-		return (e->addr[0] ^ addr[0]) | (e->addr[1] ^ addr[1]) |
-		       (e->addr[2] ^ addr[2]) | (e->addr[3] ^ addr[3]);
-	return e->addr[0] ^ addr[0];
-}
-
-static void neigh_replace(struct l2t_entry *e, struct neighbour *n)
-{
-	neigh_hold(n);
-	if (e->neigh)
-		neigh_release(e->neigh);
-	e->neigh = n;
-}
-
-/*
- * Write an L2T entry.  Must be called with the entry locked.
- * The write may be synchronous or asynchronous.
- */
-static int write_l2e(struct adapter *adap, struct l2t_entry *e, int sync)
-{
-	struct sk_buff *skb;
-	struct cpl_l2t_write_req *req;
-
-	skb = alloc_skb(sizeof(*req), GFP_ATOMIC);
-	if (!skb)
-		return -ENOMEM;
-
-	req = (struct cpl_l2t_write_req *)__skb_put(skb, sizeof(*req));
-	INIT_TP_WR(req, 0);
-
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ,
-					e->idx | (sync ? F_SYNC_WR : 0) |
-					TID_QID(adap->sge.fw_evtq.abs_id)));
-	req->params = htons(L2T_W_PORT(e->lport) | L2T_W_NOREPLY(!sync));
-	req->l2t_idx = htons(e->idx);
-	req->vlan = htons(e->vlan);
-	if (e->neigh)
-		memcpy(e->dmac, e->neigh->ha, sizeof(e->dmac));
-	memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac));
-
-	set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0);
-	t4_ofld_send(adap, skb);
-
-	if (sync && e->state != L2T_STATE_SWITCHING)
-		e->state = L2T_STATE_SYNC_WRITE;
-	return 0;
-}
-
-/*
- * Send packets waiting in an L2T entry's ARP queue.  Must be called with the
- * entry locked.
- */
-static void send_pending(struct adapter *adap, struct l2t_entry *e)
-{
-	while (e->arpq_head) {
-		struct sk_buff *skb = e->arpq_head;
-
-		e->arpq_head = skb->next;
-		skb->next = NULL;
-		t4_ofld_send(adap, skb);
-	}
-	e->arpq_tail = NULL;
-}
-
-/*
- * Process a CPL_L2T_WRITE_RPL.  Wake up the ARP queue if it completes a
- * synchronous L2T_WRITE.  Note that the TID in the reply is really the L2T
- * index it refers to.
- */
-void do_l2t_write_rpl(struct adapter *adap, const struct cpl_l2t_write_rpl *rpl)
-{
-	unsigned int tid = GET_TID(rpl);
-	unsigned int idx = tid & (L2T_SIZE - 1);
-
-	if (unlikely(rpl->status != CPL_ERR_NONE)) {
-		dev_err(adap->pdev_dev,
-			"Unexpected L2T_WRITE_RPL status %u for entry %u\n",
-			rpl->status, idx);
-		return;
-	}
-
-	if (tid & F_SYNC_WR) {
-		struct l2t_entry *e = &adap->l2t->l2tab[idx];
-
-		spin_lock(&e->lock);
-		if (e->state != L2T_STATE_SWITCHING) {
-			send_pending(adap, e);
-			e->state = (e->neigh->nud_state & NUD_STALE) ?
-					L2T_STATE_STALE : L2T_STATE_VALID;
-		}
-		spin_unlock(&e->lock);
-	}
-}
-
-/*
- * Add a packet to an L2T entry's queue of packets awaiting resolution.
- * Must be called with the entry's lock held.
- */
-static inline void arpq_enqueue(struct l2t_entry *e, struct sk_buff *skb)
-{
-	skb->next = NULL;
-	if (e->arpq_head)
-		e->arpq_tail->next = skb;
-	else
-		e->arpq_head = skb;
-	e->arpq_tail = skb;
-}
-
-int cxgb4_l2t_send(struct net_device *dev, struct sk_buff *skb,
-		   struct l2t_entry *e)
-{
-	struct adapter *adap = netdev2adap(dev);
-
-again:
-	switch (e->state) {
-	case L2T_STATE_STALE:     /* entry is stale, kick off revalidation */
-		neigh_event_send(e->neigh, NULL);
-		spin_lock_bh(&e->lock);
-		if (e->state == L2T_STATE_STALE)
-			e->state = L2T_STATE_VALID;
-		spin_unlock_bh(&e->lock);
-	case L2T_STATE_VALID:     /* fast-path, send the packet on */
-		return t4_ofld_send(adap, skb);
-	case L2T_STATE_RESOLVING:
-	case L2T_STATE_SYNC_WRITE:
-		spin_lock_bh(&e->lock);
-		if (e->state != L2T_STATE_SYNC_WRITE &&
-		    e->state != L2T_STATE_RESOLVING) {
-			spin_unlock_bh(&e->lock);
-			goto again;
-		}
-		arpq_enqueue(e, skb);
-		spin_unlock_bh(&e->lock);
-
-		if (e->state == L2T_STATE_RESOLVING &&
-		    !neigh_event_send(e->neigh, NULL)) {
-			spin_lock_bh(&e->lock);
-			if (e->state == L2T_STATE_RESOLVING && e->arpq_head)
-				write_l2e(adap, e, 1);
-			spin_unlock_bh(&e->lock);
-		}
-	}
-	return 0;
-}
-EXPORT_SYMBOL(cxgb4_l2t_send);
-
-/*
- * Allocate a free L2T entry.  Must be called with l2t_data.lock held.
- */
-static struct l2t_entry *alloc_l2e(struct l2t_data *d)
-{
-	struct l2t_entry *end, *e, **p;
-
-	if (!atomic_read(&d->nfree))
-		return NULL;
-
-	/* there's definitely a free entry */
-	for (e = d->rover, end = &d->l2tab[L2T_SIZE]; e != end; ++e)
-		if (atomic_read(&e->refcnt) == 0)
-			goto found;
-
-	for (e = d->l2tab; atomic_read(&e->refcnt); ++e)
-		;
-found:
-	d->rover = e + 1;
-	atomic_dec(&d->nfree);
-
-	/*
-	 * The entry we found may be an inactive entry that is
-	 * presently in the hash table.  We need to remove it.
-	 */
-	if (e->state < L2T_STATE_SWITCHING)
-		for (p = &d->l2tab[e->hash].first; *p; p = &(*p)->next)
-			if (*p == e) {
-				*p = e->next;
-				e->next = NULL;
-				break;
-			}
-
-	e->state = L2T_STATE_UNUSED;
-	return e;
-}
-
-/*
- * Called when an L2T entry has no more users.
- */
-static void t4_l2e_free(struct l2t_entry *e)
-{
-	struct l2t_data *d;
-
-	spin_lock_bh(&e->lock);
-	if (atomic_read(&e->refcnt) == 0) {  /* hasn't been recycled */
-		if (e->neigh) {
-			neigh_release(e->neigh);
-			e->neigh = NULL;
-		}
-		while (e->arpq_head) {
-			struct sk_buff *skb = e->arpq_head;
-
-			e->arpq_head = skb->next;
-			kfree_skb(skb);
-		}
-		e->arpq_tail = NULL;
-	}
-	spin_unlock_bh(&e->lock);
-
-	d = container_of(e, struct l2t_data, l2tab[e->idx]);
-	atomic_inc(&d->nfree);
-}
-
-void cxgb4_l2t_release(struct l2t_entry *e)
-{
-	if (atomic_dec_and_test(&e->refcnt))
-		t4_l2e_free(e);
-}
-EXPORT_SYMBOL(cxgb4_l2t_release);
-
-/*
- * Update an L2T entry that was previously used for the same next hop as neigh.
- * Must be called with softirqs disabled.
- */
-static void reuse_entry(struct l2t_entry *e, struct neighbour *neigh)
-{
-	unsigned int nud_state;
-
-	spin_lock(&e->lock);                /* avoid race with t4_l2t_free */
-	if (neigh != e->neigh)
-		neigh_replace(e, neigh);
-	nud_state = neigh->nud_state;
-	if (memcmp(e->dmac, neigh->ha, sizeof(e->dmac)) ||
-	    !(nud_state & NUD_VALID))
-		e->state = L2T_STATE_RESOLVING;
-	else if (nud_state & NUD_CONNECTED)
-		e->state = L2T_STATE_VALID;
-	else
-		e->state = L2T_STATE_STALE;
-	spin_unlock(&e->lock);
-}
-
-struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh,
-				const struct net_device *physdev,
-				unsigned int priority)
-{
-	u8 lport;
-	u16 vlan;
-	struct l2t_entry *e;
-	int addr_len = neigh->tbl->key_len;
-	u32 *addr = (u32 *)neigh->primary_key;
-	int ifidx = neigh->dev->ifindex;
-	int hash = addr_hash(addr, addr_len, ifidx);
-
-	if (neigh->dev->flags & IFF_LOOPBACK)
-		lport = netdev2pinfo(physdev)->tx_chan + 4;
-	else
-		lport = netdev2pinfo(physdev)->lport;
-
-	if (neigh->dev->priv_flags & IFF_802_1Q_VLAN)
-		vlan = vlan_dev_vlan_id(neigh->dev);
-	else
-		vlan = VLAN_NONE;
-
-	write_lock_bh(&d->lock);
-	for (e = d->l2tab[hash].first; e; e = e->next)
-		if (!addreq(e, addr) && e->ifindex == ifidx &&
-		    e->vlan == vlan && e->lport == lport) {
-			l2t_hold(d, e);
-			if (atomic_read(&e->refcnt) == 1)
-				reuse_entry(e, neigh);
-			goto done;
-		}
-
-	/* Need to allocate a new entry */
-	e = alloc_l2e(d);
-	if (e) {
-		spin_lock(&e->lock);          /* avoid race with t4_l2t_free */
-		e->state = L2T_STATE_RESOLVING;
-		memcpy(e->addr, addr, addr_len);
-		e->ifindex = ifidx;
-		e->hash = hash;
-		e->lport = lport;
-		e->v6 = addr_len == 16;
-		atomic_set(&e->refcnt, 1);
-		neigh_replace(e, neigh);
-		e->vlan = vlan;
-		e->next = d->l2tab[hash].first;
-		d->l2tab[hash].first = e;
-		spin_unlock(&e->lock);
-	}
-done:
-	write_unlock_bh(&d->lock);
-	return e;
-}
-EXPORT_SYMBOL(cxgb4_l2t_get);
-
-/*
- * Called when address resolution fails for an L2T entry to handle packets
- * on the arpq head.  If a packet specifies a failure handler it is invoked,
- * otherwise the packet is sent to the device.
- */
-static void handle_failed_resolution(struct adapter *adap, struct sk_buff *arpq)
-{
-	while (arpq) {
-		struct sk_buff *skb = arpq;
-		const struct l2t_skb_cb *cb = L2T_SKB_CB(skb);
-
-		arpq = skb->next;
-		skb->next = NULL;
-		if (cb->arp_err_handler)
-			cb->arp_err_handler(cb->handle, skb);
-		else
-			t4_ofld_send(adap, skb);
-	}
-}
-
-/*
- * Called when the host's neighbor layer makes a change to some entry that is
- * loaded into the HW L2 table.
- */
-void t4_l2t_update(struct adapter *adap, struct neighbour *neigh)
-{
-	struct l2t_entry *e;
-	struct sk_buff *arpq = NULL;
-	struct l2t_data *d = adap->l2t;
-	int addr_len = neigh->tbl->key_len;
-	u32 *addr = (u32 *) neigh->primary_key;
-	int ifidx = neigh->dev->ifindex;
-	int hash = addr_hash(addr, addr_len, ifidx);
-
-	read_lock_bh(&d->lock);
-	for (e = d->l2tab[hash].first; e; e = e->next)
-		if (!addreq(e, addr) && e->ifindex == ifidx) {
-			spin_lock(&e->lock);
-			if (atomic_read(&e->refcnt))
-				goto found;
-			spin_unlock(&e->lock);
-			break;
-		}
-	read_unlock_bh(&d->lock);
-	return;
-
- found:
-	read_unlock(&d->lock);
-
-	if (neigh != e->neigh)
-		neigh_replace(e, neigh);
-
-	if (e->state == L2T_STATE_RESOLVING) {
-		if (neigh->nud_state & NUD_FAILED) {
-			arpq = e->arpq_head;
-			e->arpq_head = e->arpq_tail = NULL;
-		} else if ((neigh->nud_state & (NUD_CONNECTED | NUD_STALE)) &&
-			   e->arpq_head) {
-			write_l2e(adap, e, 1);
-		}
-	} else {
-		e->state = neigh->nud_state & NUD_CONNECTED ?
-			L2T_STATE_VALID : L2T_STATE_STALE;
-		if (memcmp(e->dmac, neigh->ha, sizeof(e->dmac)))
-			write_l2e(adap, e, 0);
-	}
-
-	spin_unlock_bh(&e->lock);
-
-	if (arpq)
-		handle_failed_resolution(adap, arpq);
-}
-
-struct l2t_data *t4_init_l2t(void)
-{
-	int i;
-	struct l2t_data *d;
-
-	d = t4_alloc_mem(sizeof(*d));
-	if (!d)
-		return NULL;
-
-	d->rover = d->l2tab;
-	atomic_set(&d->nfree, L2T_SIZE);
-	rwlock_init(&d->lock);
-
-	for (i = 0; i < L2T_SIZE; ++i) {
-		d->l2tab[i].idx = i;
-		d->l2tab[i].state = L2T_STATE_UNUSED;
-		spin_lock_init(&d->l2tab[i].lock);
-		atomic_set(&d->l2tab[i].refcnt, 0);
-	}
-	return d;
-}
-
-#include <linux/module.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-static inline void *l2t_get_idx(struct seq_file *seq, loff_t pos)
-{
-	struct l2t_entry *l2tab = seq->private;
-
-	return pos >= L2T_SIZE ? NULL : &l2tab[pos];
-}
-
-static void *l2t_seq_start(struct seq_file *seq, loff_t *pos)
-{
-	return *pos ? l2t_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
-}
-
-static void *l2t_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-	v = l2t_get_idx(seq, *pos);
-	if (v)
-		++*pos;
-	return v;
-}
-
-static void l2t_seq_stop(struct seq_file *seq, void *v)
-{
-}
-
-static char l2e_state(const struct l2t_entry *e)
-{
-	switch (e->state) {
-	case L2T_STATE_VALID: return 'V';
-	case L2T_STATE_STALE: return 'S';
-	case L2T_STATE_SYNC_WRITE: return 'W';
-	case L2T_STATE_RESOLVING: return e->arpq_head ? 'A' : 'R';
-	case L2T_STATE_SWITCHING: return 'X';
-	default:
-		return 'U';
-	}
-}
-
-static int l2t_seq_show(struct seq_file *seq, void *v)
-{
-	if (v == SEQ_START_TOKEN)
-		seq_puts(seq, " Idx IP address                "
-			 "Ethernet address  VLAN/P LP State Users Port\n");
-	else {
-		char ip[60];
-		struct l2t_entry *e = v;
-
-		spin_lock_bh(&e->lock);
-		if (e->state == L2T_STATE_SWITCHING)
-			ip[0] = '\0';
-		else
-			sprintf(ip, e->v6 ? "%pI6c" : "%pI4", e->addr);
-		seq_printf(seq, "%4u %-25s %17pM %4d %u %2u   %c   %5u %s\n",
-			   e->idx, ip, e->dmac,
-			   e->vlan & VLAN_VID_MASK, vlan_prio(e), e->lport,
-			   l2e_state(e), atomic_read(&e->refcnt),
-			   e->neigh ? e->neigh->dev->name : "");
-		spin_unlock_bh(&e->lock);
-	}
-	return 0;
-}
-
-static const struct seq_operations l2t_seq_ops = {
-	.start = l2t_seq_start,
-	.next = l2t_seq_next,
-	.stop = l2t_seq_stop,
-	.show = l2t_seq_show
-};
-
-static int l2t_seq_open(struct inode *inode, struct file *file)
-{
-	int rc = seq_open(file, &l2t_seq_ops);
-
-	if (!rc) {
-		struct adapter *adap = inode->i_private;
-		struct seq_file *seq = file->private_data;
-
-		seq->private = adap->l2t->l2tab;
-	}
-	return rc;
-}
-
-const struct file_operations t4_l2t_fops = {
-	.owner = THIS_MODULE,
-	.open = l2t_seq_open,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = seq_release,
-};
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4/l2t.h linux-libre-3.2-gnu/drivers/net/cxgb4/l2t.h
--- linux-libre-3.1-gnu/drivers/net/cxgb4/l2t.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4/l2t.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,107 +0,0 @@
-/*
- * This file is part of the Chelsio T4 Ethernet driver for Linux.
- *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __CXGB4_L2T_H
-#define __CXGB4_L2T_H
-
-#include <linux/spinlock.h>
-#include <linux/if_ether.h>
-#include <linux/atomic.h>
-
-struct adapter;
-struct l2t_data;
-struct neighbour;
-struct net_device;
-struct file_operations;
-struct cpl_l2t_write_rpl;
-
-/*
- * Each L2T entry plays multiple roles.  First of all, it keeps state for the
- * corresponding entry of the HW L2 table and maintains a queue of offload
- * packets awaiting address resolution.  Second, it is a node of a hash table
- * chain, where the nodes of the chain are linked together through their next
- * pointer.  Finally, each node is a bucket of a hash table, pointing to the
- * first element in its chain through its first pointer.
- */
-struct l2t_entry {
-	u16 state;                  /* entry state */
-	u16 idx;                    /* entry index */
-	u32 addr[4];                /* next hop IP or IPv6 address */
-	int ifindex;                /* neighbor's net_device's ifindex */
-	struct neighbour *neigh;    /* associated neighbour */
-	struct l2t_entry *first;    /* start of hash chain */
-	struct l2t_entry *next;     /* next l2t_entry on chain */
-	struct sk_buff *arpq_head;  /* queue of packets awaiting resolution */
-	struct sk_buff *arpq_tail;
-	spinlock_t lock;
-	atomic_t refcnt;            /* entry reference count */
-	u16 hash;                   /* hash bucket the entry is on */
-	u16 vlan;                   /* VLAN TCI (id: bits 0-11, prio: 13-15 */
-	u8 v6;                      /* whether entry is for IPv6 */
-	u8 lport;                   /* associated offload logical interface */
-	u8 dmac[ETH_ALEN];          /* neighbour's MAC address */
-};
-
-typedef void (*arp_err_handler_t)(void *handle, struct sk_buff *skb);
-
-/*
- * Callback stored in an skb to handle address resolution failure.
- */
-struct l2t_skb_cb {
-	void *handle;
-	arp_err_handler_t arp_err_handler;
-};
-
-#define L2T_SKB_CB(skb) ((struct l2t_skb_cb *)(skb)->cb)
-
-static inline void t4_set_arp_err_handler(struct sk_buff *skb, void *handle,
-					  arp_err_handler_t handler)
-{
-	L2T_SKB_CB(skb)->handle = handle;
-	L2T_SKB_CB(skb)->arp_err_handler = handler;
-}
-
-void cxgb4_l2t_release(struct l2t_entry *e);
-int cxgb4_l2t_send(struct net_device *dev, struct sk_buff *skb,
-		   struct l2t_entry *e);
-struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh,
-				const struct net_device *physdev,
-				unsigned int priority);
-
-void t4_l2t_update(struct adapter *adap, struct neighbour *neigh);
-struct l2t_data *t4_init_l2t(void);
-void do_l2t_write_rpl(struct adapter *p, const struct cpl_l2t_write_rpl *rpl);
-
-extern const struct file_operations t4_l2t_fops;
-#endif  /* __CXGB4_L2T_H */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4/Makefile linux-libre-3.2-gnu/drivers/net/cxgb4/Makefile
--- linux-libre-3.1-gnu/drivers/net/cxgb4/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#
-# Chelsio T4 driver
-#
-
-obj-$(CONFIG_CHELSIO_T4) += cxgb4.o
-
-cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4/sge.c linux-libre-3.2-gnu/drivers/net/cxgb4/sge.c
--- linux-libre-3.1-gnu/drivers/net/cxgb4/sge.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4/sge.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2442 +0,0 @@
-/*
- * This file is part of the Chelsio T4 Ethernet driver for Linux.
- *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_vlan.h>
-#include <linux/ip.h>
-#include <linux/dma-mapping.h>
-#include <linux/jiffies.h>
-#include <linux/prefetch.h>
-#include <net/ipv6.h>
-#include <net/tcp.h>
-#include "cxgb4.h"
-#include "t4_regs.h"
-#include "t4_msg.h"
-#include "t4fw_api.h"
-
-/*
- * Rx buffer size.  We use largish buffers if possible but settle for single
- * pages under memory shortage.
- */
-#if PAGE_SHIFT >= 16
-# define FL_PG_ORDER 0
-#else
-# define FL_PG_ORDER (16 - PAGE_SHIFT)
-#endif
-
-/* RX_PULL_LEN should be <= RX_COPY_THRES */
-#define RX_COPY_THRES    256
-#define RX_PULL_LEN      128
-
-/*
- * Main body length for sk_buffs used for Rx Ethernet packets with fragments.
- * Should be >= RX_PULL_LEN but possibly bigger to give pskb_may_pull some room.
- */
-#define RX_PKT_SKB_LEN   512
-
-/* Ethernet header padding prepended to RX_PKTs */
-#define RX_PKT_PAD 2
-
-/*
- * Max number of Tx descriptors we clean up at a time.  Should be modest as
- * freeing skbs isn't cheap and it happens while holding locks.  We just need
- * to free packets faster than they arrive, we eventually catch up and keep
- * the amortized cost reasonable.  Must be >= 2 * TXQ_STOP_THRES.
- */
-#define MAX_TX_RECLAIM 16
-
-/*
- * Max number of Rx buffers we replenish at a time.  Again keep this modest,
- * allocating buffers isn't cheap either.
- */
-#define MAX_RX_REFILL 16U
-
-/*
- * Period of the Rx queue check timer.  This timer is infrequent as it has
- * something to do only when the system experiences severe memory shortage.
- */
-#define RX_QCHECK_PERIOD (HZ / 2)
-
-/*
- * Period of the Tx queue check timer.
- */
-#define TX_QCHECK_PERIOD (HZ / 2)
-
-/*
- * Max number of Tx descriptors to be reclaimed by the Tx timer.
- */
-#define MAX_TIMER_TX_RECLAIM 100
-
-/*
- * Timer index used when backing off due to memory shortage.
- */
-#define NOMEM_TMR_IDX (SGE_NTIMERS - 1)
-
-/*
- * An FL with <= FL_STARVE_THRES buffers is starving and a periodic timer will
- * attempt to refill it.
- */
-#define FL_STARVE_THRES 4
-
-/*
- * Suspend an Ethernet Tx queue with fewer available descriptors than this.
- * This is the same as calc_tx_descs() for a TSO packet with
- * nr_frags == MAX_SKB_FRAGS.
- */
-#define ETHTXQ_STOP_THRES \
-	(1 + DIV_ROUND_UP((3 * MAX_SKB_FRAGS) / 2 + (MAX_SKB_FRAGS & 1), 8))
-
-/*
- * Suspension threshold for non-Ethernet Tx queues.  We require enough room
- * for a full sized WR.
- */
-#define TXQ_STOP_THRES (SGE_MAX_WR_LEN / sizeof(struct tx_desc))
-
-/*
- * Max Tx descriptor space we allow for an Ethernet packet to be inlined
- * into a WR.
- */
-#define MAX_IMM_TX_PKT_LEN 128
-
-/*
- * Max size of a WR sent through a control Tx queue.
- */
-#define MAX_CTRL_WR_LEN SGE_MAX_WR_LEN
-
-enum {
-	/* packet alignment in FL buffers */
-	FL_ALIGN = L1_CACHE_BYTES < 32 ? 32 : L1_CACHE_BYTES,
-	/* egress status entry size */
-	STAT_LEN = L1_CACHE_BYTES > 64 ? 128 : 64
-};
-
-struct tx_sw_desc {                /* SW state per Tx descriptor */
-	struct sk_buff *skb;
-	struct ulptx_sgl *sgl;
-};
-
-struct rx_sw_desc {                /* SW state per Rx descriptor */
-	struct page *page;
-	dma_addr_t dma_addr;
-};
-
-/*
- * The low bits of rx_sw_desc.dma_addr have special meaning.
- */
-enum {
-	RX_LARGE_BUF    = 1 << 0, /* buffer is larger than PAGE_SIZE */
-	RX_UNMAPPED_BUF = 1 << 1, /* buffer is not mapped */
-};
-
-static inline dma_addr_t get_buf_addr(const struct rx_sw_desc *d)
-{
-	return d->dma_addr & ~(dma_addr_t)(RX_LARGE_BUF | RX_UNMAPPED_BUF);
-}
-
-static inline bool is_buf_mapped(const struct rx_sw_desc *d)
-{
-	return !(d->dma_addr & RX_UNMAPPED_BUF);
-}
-
-/**
- *	txq_avail - return the number of available slots in a Tx queue
- *	@q: the Tx queue
- *
- *	Returns the number of descriptors in a Tx queue available to write new
- *	packets.
- */
-static inline unsigned int txq_avail(const struct sge_txq *q)
-{
-	return q->size - 1 - q->in_use;
-}
-
-/**
- *	fl_cap - return the capacity of a free-buffer list
- *	@fl: the FL
- *
- *	Returns the capacity of a free-buffer list.  The capacity is less than
- *	the size because one descriptor needs to be left unpopulated, otherwise
- *	HW will think the FL is empty.
- */
-static inline unsigned int fl_cap(const struct sge_fl *fl)
-{
-	return fl->size - 8;   /* 1 descriptor = 8 buffers */
-}
-
-static inline bool fl_starving(const struct sge_fl *fl)
-{
-	return fl->avail - fl->pend_cred <= FL_STARVE_THRES;
-}
-
-static int map_skb(struct device *dev, const struct sk_buff *skb,
-		   dma_addr_t *addr)
-{
-	const skb_frag_t *fp, *end;
-	const struct skb_shared_info *si;
-
-	*addr = dma_map_single(dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
-	if (dma_mapping_error(dev, *addr))
-		goto out_err;
-
-	si = skb_shinfo(skb);
-	end = &si->frags[si->nr_frags];
-
-	for (fp = si->frags; fp < end; fp++) {
-		*++addr = dma_map_page(dev, fp->page, fp->page_offset, fp->size,
-				       DMA_TO_DEVICE);
-		if (dma_mapping_error(dev, *addr))
-			goto unwind;
-	}
-	return 0;
-
-unwind:
-	while (fp-- > si->frags)
-		dma_unmap_page(dev, *--addr, fp->size, DMA_TO_DEVICE);
-
-	dma_unmap_single(dev, addr[-1], skb_headlen(skb), DMA_TO_DEVICE);
-out_err:
-	return -ENOMEM;
-}
-
-#ifdef CONFIG_NEED_DMA_MAP_STATE
-static void unmap_skb(struct device *dev, const struct sk_buff *skb,
-		      const dma_addr_t *addr)
-{
-	const skb_frag_t *fp, *end;
-	const struct skb_shared_info *si;
-
-	dma_unmap_single(dev, *addr++, skb_headlen(skb), DMA_TO_DEVICE);
-
-	si = skb_shinfo(skb);
-	end = &si->frags[si->nr_frags];
-	for (fp = si->frags; fp < end; fp++)
-		dma_unmap_page(dev, *addr++, fp->size, DMA_TO_DEVICE);
-}
-
-/**
- *	deferred_unmap_destructor - unmap a packet when it is freed
- *	@skb: the packet
- *
- *	This is the packet destructor used for Tx packets that need to remain
- *	mapped until they are freed rather than until their Tx descriptors are
- *	freed.
- */
-static void deferred_unmap_destructor(struct sk_buff *skb)
-{
-	unmap_skb(skb->dev->dev.parent, skb, (dma_addr_t *)skb->head);
-}
-#endif
-
-static void unmap_sgl(struct device *dev, const struct sk_buff *skb,
-		      const struct ulptx_sgl *sgl, const struct sge_txq *q)
-{
-	const struct ulptx_sge_pair *p;
-	unsigned int nfrags = skb_shinfo(skb)->nr_frags;
-
-	if (likely(skb_headlen(skb)))
-		dma_unmap_single(dev, be64_to_cpu(sgl->addr0), ntohl(sgl->len0),
-				 DMA_TO_DEVICE);
-	else {
-		dma_unmap_page(dev, be64_to_cpu(sgl->addr0), ntohl(sgl->len0),
-			       DMA_TO_DEVICE);
-		nfrags--;
-	}
-
-	/*
-	 * the complexity below is because of the possibility of a wrap-around
-	 * in the middle of an SGL
-	 */
-	for (p = sgl->sge; nfrags >= 2; nfrags -= 2) {
-		if (likely((u8 *)(p + 1) <= (u8 *)q->stat)) {
-unmap:			dma_unmap_page(dev, be64_to_cpu(p->addr[0]),
-				       ntohl(p->len[0]), DMA_TO_DEVICE);
-			dma_unmap_page(dev, be64_to_cpu(p->addr[1]),
-				       ntohl(p->len[1]), DMA_TO_DEVICE);
-			p++;
-		} else if ((u8 *)p == (u8 *)q->stat) {
-			p = (const struct ulptx_sge_pair *)q->desc;
-			goto unmap;
-		} else if ((u8 *)p + 8 == (u8 *)q->stat) {
-			const __be64 *addr = (const __be64 *)q->desc;
-
-			dma_unmap_page(dev, be64_to_cpu(addr[0]),
-				       ntohl(p->len[0]), DMA_TO_DEVICE);
-			dma_unmap_page(dev, be64_to_cpu(addr[1]),
-				       ntohl(p->len[1]), DMA_TO_DEVICE);
-			p = (const struct ulptx_sge_pair *)&addr[2];
-		} else {
-			const __be64 *addr = (const __be64 *)q->desc;
-
-			dma_unmap_page(dev, be64_to_cpu(p->addr[0]),
-				       ntohl(p->len[0]), DMA_TO_DEVICE);
-			dma_unmap_page(dev, be64_to_cpu(addr[0]),
-				       ntohl(p->len[1]), DMA_TO_DEVICE);
-			p = (const struct ulptx_sge_pair *)&addr[1];
-		}
-	}
-	if (nfrags) {
-		__be64 addr;
-
-		if ((u8 *)p == (u8 *)q->stat)
-			p = (const struct ulptx_sge_pair *)q->desc;
-		addr = (u8 *)p + 16 <= (u8 *)q->stat ? p->addr[0] :
-						       *(const __be64 *)q->desc;
-		dma_unmap_page(dev, be64_to_cpu(addr), ntohl(p->len[0]),
-			       DMA_TO_DEVICE);
-	}
-}
-
-/**
- *	free_tx_desc - reclaims Tx descriptors and their buffers
- *	@adapter: the adapter
- *	@q: the Tx queue to reclaim descriptors from
- *	@n: the number of descriptors to reclaim
- *	@unmap: whether the buffers should be unmapped for DMA
- *
- *	Reclaims Tx descriptors from an SGE Tx queue and frees the associated
- *	Tx buffers.  Called with the Tx queue lock held.
- */
-static void free_tx_desc(struct adapter *adap, struct sge_txq *q,
-			 unsigned int n, bool unmap)
-{
-	struct tx_sw_desc *d;
-	unsigned int cidx = q->cidx;
-	struct device *dev = adap->pdev_dev;
-
-	d = &q->sdesc[cidx];
-	while (n--) {
-		if (d->skb) {                       /* an SGL is present */
-			if (unmap)
-				unmap_sgl(dev, d->skb, d->sgl, q);
-			kfree_skb(d->skb);
-			d->skb = NULL;
-		}
-		++d;
-		if (++cidx == q->size) {
-			cidx = 0;
-			d = q->sdesc;
-		}
-	}
-	q->cidx = cidx;
-}
-
-/*
- * Return the number of reclaimable descriptors in a Tx queue.
- */
-static inline int reclaimable(const struct sge_txq *q)
-{
-	int hw_cidx = ntohs(q->stat->cidx);
-	hw_cidx -= q->cidx;
-	return hw_cidx < 0 ? hw_cidx + q->size : hw_cidx;
-}
-
-/**
- *	reclaim_completed_tx - reclaims completed Tx descriptors
- *	@adap: the adapter
- *	@q: the Tx queue to reclaim completed descriptors from
- *	@unmap: whether the buffers should be unmapped for DMA
- *
- *	Reclaims Tx descriptors that the SGE has indicated it has processed,
- *	and frees the associated buffers if possible.  Called with the Tx
- *	queue locked.
- */
-static inline void reclaim_completed_tx(struct adapter *adap, struct sge_txq *q,
-					bool unmap)
-{
-	int avail = reclaimable(q);
-
-	if (avail) {
-		/*
-		 * Limit the amount of clean up work we do at a time to keep
-		 * the Tx lock hold time O(1).
-		 */
-		if (avail > MAX_TX_RECLAIM)
-			avail = MAX_TX_RECLAIM;
-
-		free_tx_desc(adap, q, avail, unmap);
-		q->in_use -= avail;
-	}
-}
-
-static inline int get_buf_size(const struct rx_sw_desc *d)
-{
-#if FL_PG_ORDER > 0
-	return (d->dma_addr & RX_LARGE_BUF) ? (PAGE_SIZE << FL_PG_ORDER) :
-					      PAGE_SIZE;
-#else
-	return PAGE_SIZE;
-#endif
-}
-
-/**
- *	free_rx_bufs - free the Rx buffers on an SGE free list
- *	@adap: the adapter
- *	@q: the SGE free list to free buffers from
- *	@n: how many buffers to free
- *
- *	Release the next @n buffers on an SGE free-buffer Rx queue.   The
- *	buffers must be made inaccessible to HW before calling this function.
- */
-static void free_rx_bufs(struct adapter *adap, struct sge_fl *q, int n)
-{
-	while (n--) {
-		struct rx_sw_desc *d = &q->sdesc[q->cidx];
-
-		if (is_buf_mapped(d))
-			dma_unmap_page(adap->pdev_dev, get_buf_addr(d),
-				       get_buf_size(d), PCI_DMA_FROMDEVICE);
-		put_page(d->page);
-		d->page = NULL;
-		if (++q->cidx == q->size)
-			q->cidx = 0;
-		q->avail--;
-	}
-}
-
-/**
- *	unmap_rx_buf - unmap the current Rx buffer on an SGE free list
- *	@adap: the adapter
- *	@q: the SGE free list
- *
- *	Unmap the current buffer on an SGE free-buffer Rx queue.   The
- *	buffer must be made inaccessible to HW before calling this function.
- *
- *	This is similar to @free_rx_bufs above but does not free the buffer.
- *	Do note that the FL still loses any further access to the buffer.
- */
-static void unmap_rx_buf(struct adapter *adap, struct sge_fl *q)
-{
-	struct rx_sw_desc *d = &q->sdesc[q->cidx];
-
-	if (is_buf_mapped(d))
-		dma_unmap_page(adap->pdev_dev, get_buf_addr(d),
-			       get_buf_size(d), PCI_DMA_FROMDEVICE);
-	d->page = NULL;
-	if (++q->cidx == q->size)
-		q->cidx = 0;
-	q->avail--;
-}
-
-static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q)
-{
-	if (q->pend_cred >= 8) {
-		wmb();
-		t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), DBPRIO |
-			     QID(q->cntxt_id) | PIDX(q->pend_cred / 8));
-		q->pend_cred &= 7;
-	}
-}
-
-static inline void set_rx_sw_desc(struct rx_sw_desc *sd, struct page *pg,
-				  dma_addr_t mapping)
-{
-	sd->page = pg;
-	sd->dma_addr = mapping;      /* includes size low bits */
-}
-
-/**
- *	refill_fl - refill an SGE Rx buffer ring
- *	@adap: the adapter
- *	@q: the ring to refill
- *	@n: the number of new buffers to allocate
- *	@gfp: the gfp flags for the allocations
- *
- *	(Re)populate an SGE free-buffer queue with up to @n new packet buffers,
- *	allocated with the supplied gfp flags.  The caller must assure that
- *	@n does not exceed the queue's capacity.  If afterwards the queue is
- *	found critically low mark it as starving in the bitmap of starving FLs.
- *
- *	Returns the number of buffers allocated.
- */
-static unsigned int refill_fl(struct adapter *adap, struct sge_fl *q, int n,
-			      gfp_t gfp)
-{
-	struct page *pg;
-	dma_addr_t mapping;
-	unsigned int cred = q->avail;
-	__be64 *d = &q->desc[q->pidx];
-	struct rx_sw_desc *sd = &q->sdesc[q->pidx];
-
-	gfp |= __GFP_NOWARN;         /* failures are expected */
-
-#if FL_PG_ORDER > 0
-	/*
-	 * Prefer large buffers
-	 */
-	while (n) {
-		pg = alloc_pages(gfp | __GFP_COMP, FL_PG_ORDER);
-		if (unlikely(!pg)) {
-			q->large_alloc_failed++;
-			break;       /* fall back to single pages */
-		}
-
-		mapping = dma_map_page(adap->pdev_dev, pg, 0,
-				       PAGE_SIZE << FL_PG_ORDER,
-				       PCI_DMA_FROMDEVICE);
-		if (unlikely(dma_mapping_error(adap->pdev_dev, mapping))) {
-			__free_pages(pg, FL_PG_ORDER);
-			goto out;   /* do not try small pages for this error */
-		}
-		mapping |= RX_LARGE_BUF;
-		*d++ = cpu_to_be64(mapping);
-
-		set_rx_sw_desc(sd, pg, mapping);
-		sd++;
-
-		q->avail++;
-		if (++q->pidx == q->size) {
-			q->pidx = 0;
-			sd = q->sdesc;
-			d = q->desc;
-		}
-		n--;
-	}
-#endif
-
-	while (n--) {
-		pg = __netdev_alloc_page(adap->port[0], gfp);
-		if (unlikely(!pg)) {
-			q->alloc_failed++;
-			break;
-		}
-
-		mapping = dma_map_page(adap->pdev_dev, pg, 0, PAGE_SIZE,
-				       PCI_DMA_FROMDEVICE);
-		if (unlikely(dma_mapping_error(adap->pdev_dev, mapping))) {
-			netdev_free_page(adap->port[0], pg);
-			goto out;
-		}
-		*d++ = cpu_to_be64(mapping);
-
-		set_rx_sw_desc(sd, pg, mapping);
-		sd++;
-
-		q->avail++;
-		if (++q->pidx == q->size) {
-			q->pidx = 0;
-			sd = q->sdesc;
-			d = q->desc;
-		}
-	}
-
-out:	cred = q->avail - cred;
-	q->pend_cred += cred;
-	ring_fl_db(adap, q);
-
-	if (unlikely(fl_starving(q))) {
-		smp_wmb();
-		set_bit(q->cntxt_id - adap->sge.egr_start,
-			adap->sge.starving_fl);
-	}
-
-	return cred;
-}
-
-static inline void __refill_fl(struct adapter *adap, struct sge_fl *fl)
-{
-	refill_fl(adap, fl, min(MAX_RX_REFILL, fl_cap(fl) - fl->avail),
-		  GFP_ATOMIC);
-}
-
-/**
- *	alloc_ring - allocate resources for an SGE descriptor ring
- *	@dev: the PCI device's core device
- *	@nelem: the number of descriptors
- *	@elem_size: the size of each descriptor
- *	@sw_size: the size of the SW state associated with each ring element
- *	@phys: the physical address of the allocated ring
- *	@metadata: address of the array holding the SW state for the ring
- *	@stat_size: extra space in HW ring for status information
- *	@node: preferred node for memory allocations
- *
- *	Allocates resources for an SGE descriptor ring, such as Tx queues,
- *	free buffer lists, or response queues.  Each SGE ring requires
- *	space for its HW descriptors plus, optionally, space for the SW state
- *	associated with each HW entry (the metadata).  The function returns
- *	three values: the virtual address for the HW ring (the return value
- *	of the function), the bus address of the HW ring, and the address
- *	of the SW ring.
- */
-static void *alloc_ring(struct device *dev, size_t nelem, size_t elem_size,
-			size_t sw_size, dma_addr_t *phys, void *metadata,
-			size_t stat_size, int node)
-{
-	size_t len = nelem * elem_size + stat_size;
-	void *s = NULL;
-	void *p = dma_alloc_coherent(dev, len, phys, GFP_KERNEL);
-
-	if (!p)
-		return NULL;
-	if (sw_size) {
-		s = kzalloc_node(nelem * sw_size, GFP_KERNEL, node);
-
-		if (!s) {
-			dma_free_coherent(dev, len, p, *phys);
-			return NULL;
-		}
-	}
-	if (metadata)
-		*(void **)metadata = s;
-	memset(p, 0, len);
-	return p;
-}
-
-/**
- *	sgl_len - calculates the size of an SGL of the given capacity
- *	@n: the number of SGL entries
- *
- *	Calculates the number of flits needed for a scatter/gather list that
- *	can hold the given number of entries.
- */
-static inline unsigned int sgl_len(unsigned int n)
-{
-	n--;
-	return (3 * n) / 2 + (n & 1) + 2;
-}
-
-/**
- *	flits_to_desc - returns the num of Tx descriptors for the given flits
- *	@n: the number of flits
- *
- *	Returns the number of Tx descriptors needed for the supplied number
- *	of flits.
- */
-static inline unsigned int flits_to_desc(unsigned int n)
-{
-	BUG_ON(n > SGE_MAX_WR_LEN / 8);
-	return DIV_ROUND_UP(n, 8);
-}
-
-/**
- *	is_eth_imm - can an Ethernet packet be sent as immediate data?
- *	@skb: the packet
- *
- *	Returns whether an Ethernet packet is small enough to fit as
- *	immediate data.
- */
-static inline int is_eth_imm(const struct sk_buff *skb)
-{
-	return skb->len <= MAX_IMM_TX_PKT_LEN - sizeof(struct cpl_tx_pkt);
-}
-
-/**
- *	calc_tx_flits - calculate the number of flits for a packet Tx WR
- *	@skb: the packet
- *
- *	Returns the number of flits needed for a Tx WR for the given Ethernet
- *	packet, including the needed WR and CPL headers.
- */
-static inline unsigned int calc_tx_flits(const struct sk_buff *skb)
-{
-	unsigned int flits;
-
-	if (is_eth_imm(skb))
-		return DIV_ROUND_UP(skb->len + sizeof(struct cpl_tx_pkt), 8);
-
-	flits = sgl_len(skb_shinfo(skb)->nr_frags + 1) + 4;
-	if (skb_shinfo(skb)->gso_size)
-		flits += 2;
-	return flits;
-}
-
-/**
- *	calc_tx_descs - calculate the number of Tx descriptors for a packet
- *	@skb: the packet
- *
- *	Returns the number of Tx descriptors needed for the given Ethernet
- *	packet, including the needed WR and CPL headers.
- */
-static inline unsigned int calc_tx_descs(const struct sk_buff *skb)
-{
-	return flits_to_desc(calc_tx_flits(skb));
-}
-
-/**
- *	write_sgl - populate a scatter/gather list for a packet
- *	@skb: the packet
- *	@q: the Tx queue we are writing into
- *	@sgl: starting location for writing the SGL
- *	@end: points right after the end of the SGL
- *	@start: start offset into skb main-body data to include in the SGL
- *	@addr: the list of bus addresses for the SGL elements
- *
- *	Generates a gather list for the buffers that make up a packet.
- *	The caller must provide adequate space for the SGL that will be written.
- *	The SGL includes all of the packet's page fragments and the data in its
- *	main body except for the first @start bytes.  @sgl must be 16-byte
- *	aligned and within a Tx descriptor with available space.  @end points
- *	right after the end of the SGL but does not account for any potential
- *	wrap around, i.e., @end > @sgl.
- */
-static void write_sgl(const struct sk_buff *skb, struct sge_txq *q,
-		      struct ulptx_sgl *sgl, u64 *end, unsigned int start,
-		      const dma_addr_t *addr)
-{
-	unsigned int i, len;
-	struct ulptx_sge_pair *to;
-	const struct skb_shared_info *si = skb_shinfo(skb);
-	unsigned int nfrags = si->nr_frags;
-	struct ulptx_sge_pair buf[MAX_SKB_FRAGS / 2 + 1];
-
-	len = skb_headlen(skb) - start;
-	if (likely(len)) {
-		sgl->len0 = htonl(len);
-		sgl->addr0 = cpu_to_be64(addr[0] + start);
-		nfrags++;
-	} else {
-		sgl->len0 = htonl(si->frags[0].size);
-		sgl->addr0 = cpu_to_be64(addr[1]);
-	}
-
-	sgl->cmd_nsge = htonl(ULPTX_CMD(ULP_TX_SC_DSGL) | ULPTX_NSGE(nfrags));
-	if (likely(--nfrags == 0))
-		return;
-	/*
-	 * Most of the complexity below deals with the possibility we hit the
-	 * end of the queue in the middle of writing the SGL.  For this case
-	 * only we create the SGL in a temporary buffer and then copy it.
-	 */
-	to = (u8 *)end > (u8 *)q->stat ? buf : sgl->sge;
-
-	for (i = (nfrags != si->nr_frags); nfrags >= 2; nfrags -= 2, to++) {
-		to->len[0] = cpu_to_be32(si->frags[i].size);
-		to->len[1] = cpu_to_be32(si->frags[++i].size);
-		to->addr[0] = cpu_to_be64(addr[i]);
-		to->addr[1] = cpu_to_be64(addr[++i]);
-	}
-	if (nfrags) {
-		to->len[0] = cpu_to_be32(si->frags[i].size);
-		to->len[1] = cpu_to_be32(0);
-		to->addr[0] = cpu_to_be64(addr[i + 1]);
-	}
-	if (unlikely((u8 *)end > (u8 *)q->stat)) {
-		unsigned int part0 = (u8 *)q->stat - (u8 *)sgl->sge, part1;
-
-		if (likely(part0))
-			memcpy(sgl->sge, buf, part0);
-		part1 = (u8 *)end - (u8 *)q->stat;
-		memcpy(q->desc, (u8 *)buf + part0, part1);
-		end = (void *)q->desc + part1;
-	}
-	if ((uintptr_t)end & 8)           /* 0-pad to multiple of 16 */
-		*(u64 *)end = 0;
-}
-
-/**
- *	ring_tx_db - check and potentially ring a Tx queue's doorbell
- *	@adap: the adapter
- *	@q: the Tx queue
- *	@n: number of new descriptors to give to HW
- *
- *	Ring the doorbel for a Tx queue.
- */
-static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n)
-{
-	wmb();            /* write descriptors before telling HW */
-	t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL),
-		     QID(q->cntxt_id) | PIDX(n));
-}
-
-/**
- *	inline_tx_skb - inline a packet's data into Tx descriptors
- *	@skb: the packet
- *	@q: the Tx queue where the packet will be inlined
- *	@pos: starting position in the Tx queue where to inline the packet
- *
- *	Inline a packet's contents directly into Tx descriptors, starting at
- *	the given position within the Tx DMA ring.
- *	Most of the complexity of this operation is dealing with wrap arounds
- *	in the middle of the packet we want to inline.
- */
-static void inline_tx_skb(const struct sk_buff *skb, const struct sge_txq *q,
-			  void *pos)
-{
-	u64 *p;
-	int left = (void *)q->stat - pos;
-
-	if (likely(skb->len <= left)) {
-		if (likely(!skb->data_len))
-			skb_copy_from_linear_data(skb, pos, skb->len);
-		else
-			skb_copy_bits(skb, 0, pos, skb->len);
-		pos += skb->len;
-	} else {
-		skb_copy_bits(skb, 0, pos, left);
-		skb_copy_bits(skb, left, q->desc, skb->len - left);
-		pos = (void *)q->desc + (skb->len - left);
-	}
-
-	/* 0-pad to multiple of 16 */
-	p = PTR_ALIGN(pos, 8);
-	if ((uintptr_t)p & 8)
-		*p = 0;
-}
-
-/*
- * Figure out what HW csum a packet wants and return the appropriate control
- * bits.
- */
-static u64 hwcsum(const struct sk_buff *skb)
-{
-	int csum_type;
-	const struct iphdr *iph = ip_hdr(skb);
-
-	if (iph->version == 4) {
-		if (iph->protocol == IPPROTO_TCP)
-			csum_type = TX_CSUM_TCPIP;
-		else if (iph->protocol == IPPROTO_UDP)
-			csum_type = TX_CSUM_UDPIP;
-		else {
-nocsum:			/*
-			 * unknown protocol, disable HW csum
-			 * and hope a bad packet is detected
-			 */
-			return TXPKT_L4CSUM_DIS;
-		}
-	} else {
-		/*
-		 * this doesn't work with extension headers
-		 */
-		const struct ipv6hdr *ip6h = (const struct ipv6hdr *)iph;
-
-		if (ip6h->nexthdr == IPPROTO_TCP)
-			csum_type = TX_CSUM_TCPIP6;
-		else if (ip6h->nexthdr == IPPROTO_UDP)
-			csum_type = TX_CSUM_UDPIP6;
-		else
-			goto nocsum;
-	}
-
-	if (likely(csum_type >= TX_CSUM_TCPIP))
-		return TXPKT_CSUM_TYPE(csum_type) |
-			TXPKT_IPHDR_LEN(skb_network_header_len(skb)) |
-			TXPKT_ETHHDR_LEN(skb_network_offset(skb) - ETH_HLEN);
-	else {
-		int start = skb_transport_offset(skb);
-
-		return TXPKT_CSUM_TYPE(csum_type) | TXPKT_CSUM_START(start) |
-			TXPKT_CSUM_LOC(start + skb->csum_offset);
-	}
-}
-
-static void eth_txq_stop(struct sge_eth_txq *q)
-{
-	netif_tx_stop_queue(q->txq);
-	q->q.stops++;
-}
-
-static inline void txq_advance(struct sge_txq *q, unsigned int n)
-{
-	q->in_use += n;
-	q->pidx += n;
-	if (q->pidx >= q->size)
-		q->pidx -= q->size;
-}
-
-/**
- *	t4_eth_xmit - add a packet to an Ethernet Tx queue
- *	@skb: the packet
- *	@dev: the egress net device
- *
- *	Add a packet to an SGE Ethernet Tx queue.  Runs with softirqs disabled.
- */
-netdev_tx_t t4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	u32 wr_mid;
-	u64 cntrl, *end;
-	int qidx, credits;
-	unsigned int flits, ndesc;
-	struct adapter *adap;
-	struct sge_eth_txq *q;
-	const struct port_info *pi;
-	struct fw_eth_tx_pkt_wr *wr;
-	struct cpl_tx_pkt_core *cpl;
-	const struct skb_shared_info *ssi;
-	dma_addr_t addr[MAX_SKB_FRAGS + 1];
-
-	/*
-	 * The chip min packet length is 10 octets but play safe and reject
-	 * anything shorter than an Ethernet header.
-	 */
-	if (unlikely(skb->len < ETH_HLEN)) {
-out_free:	dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-
-	pi = netdev_priv(dev);
-	adap = pi->adapter;
-	qidx = skb_get_queue_mapping(skb);
-	q = &adap->sge.ethtxq[qidx + pi->first_qset];
-
-	reclaim_completed_tx(adap, &q->q, true);
-
-	flits = calc_tx_flits(skb);
-	ndesc = flits_to_desc(flits);
-	credits = txq_avail(&q->q) - ndesc;
-
-	if (unlikely(credits < 0)) {
-		eth_txq_stop(q);
-		dev_err(adap->pdev_dev,
-			"%s: Tx ring %u full while queue awake!\n",
-			dev->name, qidx);
-		return NETDEV_TX_BUSY;
-	}
-
-	if (!is_eth_imm(skb) &&
-	    unlikely(map_skb(adap->pdev_dev, skb, addr) < 0)) {
-		q->mapping_err++;
-		goto out_free;
-	}
-
-	wr_mid = FW_WR_LEN16(DIV_ROUND_UP(flits, 2));
-	if (unlikely(credits < ETHTXQ_STOP_THRES)) {
-		eth_txq_stop(q);
-		wr_mid |= FW_WR_EQUEQ | FW_WR_EQUIQ;
-	}
-
-	wr = (void *)&q->q.desc[q->q.pidx];
-	wr->equiq_to_len16 = htonl(wr_mid);
-	wr->r3 = cpu_to_be64(0);
-	end = (u64 *)wr + flits;
-
-	ssi = skb_shinfo(skb);
-	if (ssi->gso_size) {
-		struct cpl_tx_pkt_lso *lso = (void *)wr;
-		bool v6 = (ssi->gso_type & SKB_GSO_TCPV6) != 0;
-		int l3hdr_len = skb_network_header_len(skb);
-		int eth_xtra_len = skb_network_offset(skb) - ETH_HLEN;
-
-		wr->op_immdlen = htonl(FW_WR_OP(FW_ETH_TX_PKT_WR) |
-				       FW_WR_IMMDLEN(sizeof(*lso)));
-		lso->c.lso_ctrl = htonl(LSO_OPCODE(CPL_TX_PKT_LSO) |
-					LSO_FIRST_SLICE | LSO_LAST_SLICE |
-					LSO_IPV6(v6) |
-					LSO_ETHHDR_LEN(eth_xtra_len / 4) |
-					LSO_IPHDR_LEN(l3hdr_len / 4) |
-					LSO_TCPHDR_LEN(tcp_hdr(skb)->doff));
-		lso->c.ipid_ofst = htons(0);
-		lso->c.mss = htons(ssi->gso_size);
-		lso->c.seqno_offset = htonl(0);
-		lso->c.len = htonl(skb->len);
-		cpl = (void *)(lso + 1);
-		cntrl = TXPKT_CSUM_TYPE(v6 ? TX_CSUM_TCPIP6 : TX_CSUM_TCPIP) |
-			TXPKT_IPHDR_LEN(l3hdr_len) |
-			TXPKT_ETHHDR_LEN(eth_xtra_len);
-		q->tso++;
-		q->tx_cso += ssi->gso_segs;
-	} else {
-		int len;
-
-		len = is_eth_imm(skb) ? skb->len + sizeof(*cpl) : sizeof(*cpl);
-		wr->op_immdlen = htonl(FW_WR_OP(FW_ETH_TX_PKT_WR) |
-				       FW_WR_IMMDLEN(len));
-		cpl = (void *)(wr + 1);
-		if (skb->ip_summed == CHECKSUM_PARTIAL) {
-			cntrl = hwcsum(skb) | TXPKT_IPCSUM_DIS;
-			q->tx_cso++;
-		} else
-			cntrl = TXPKT_L4CSUM_DIS | TXPKT_IPCSUM_DIS;
-	}
-
-	if (vlan_tx_tag_present(skb)) {
-		q->vlan_ins++;
-		cntrl |= TXPKT_VLAN_VLD | TXPKT_VLAN(vlan_tx_tag_get(skb));
-	}
-
-	cpl->ctrl0 = htonl(TXPKT_OPCODE(CPL_TX_PKT_XT) |
-			   TXPKT_INTF(pi->tx_chan) | TXPKT_PF(adap->fn));
-	cpl->pack = htons(0);
-	cpl->len = htons(skb->len);
-	cpl->ctrl1 = cpu_to_be64(cntrl);
-
-	if (is_eth_imm(skb)) {
-		inline_tx_skb(skb, &q->q, cpl + 1);
-		dev_kfree_skb(skb);
-	} else {
-		int last_desc;
-
-		write_sgl(skb, &q->q, (struct ulptx_sgl *)(cpl + 1), end, 0,
-			  addr);
-		skb_orphan(skb);
-
-		last_desc = q->q.pidx + ndesc - 1;
-		if (last_desc >= q->q.size)
-			last_desc -= q->q.size;
-		q->q.sdesc[last_desc].skb = skb;
-		q->q.sdesc[last_desc].sgl = (struct ulptx_sgl *)(cpl + 1);
-	}
-
-	txq_advance(&q->q, ndesc);
-
-	ring_tx_db(adap, &q->q, ndesc);
-	return NETDEV_TX_OK;
-}
-
-/**
- *	reclaim_completed_tx_imm - reclaim completed control-queue Tx descs
- *	@q: the SGE control Tx queue
- *
- *	This is a variant of reclaim_completed_tx() that is used for Tx queues
- *	that send only immediate data (presently just the control queues) and
- *	thus do not have any sk_buffs to release.
- */
-static inline void reclaim_completed_tx_imm(struct sge_txq *q)
-{
-	int hw_cidx = ntohs(q->stat->cidx);
-	int reclaim = hw_cidx - q->cidx;
-
-	if (reclaim < 0)
-		reclaim += q->size;
-
-	q->in_use -= reclaim;
-	q->cidx = hw_cidx;
-}
-
-/**
- *	is_imm - check whether a packet can be sent as immediate data
- *	@skb: the packet
- *
- *	Returns true if a packet can be sent as a WR with immediate data.
- */
-static inline int is_imm(const struct sk_buff *skb)
-{
-	return skb->len <= MAX_CTRL_WR_LEN;
-}
-
-/**
- *	ctrlq_check_stop - check if a control queue is full and should stop
- *	@q: the queue
- *	@wr: most recent WR written to the queue
- *
- *	Check if a control queue has become full and should be stopped.
- *	We clean up control queue descriptors very lazily, only when we are out.
- *	If the queue is still full after reclaiming any completed descriptors
- *	we suspend it and have the last WR wake it up.
- */
-static void ctrlq_check_stop(struct sge_ctrl_txq *q, struct fw_wr_hdr *wr)
-{
-	reclaim_completed_tx_imm(&q->q);
-	if (unlikely(txq_avail(&q->q) < TXQ_STOP_THRES)) {
-		wr->lo |= htonl(FW_WR_EQUEQ | FW_WR_EQUIQ);
-		q->q.stops++;
-		q->full = 1;
-	}
-}
-
-/**
- *	ctrl_xmit - send a packet through an SGE control Tx queue
- *	@q: the control queue
- *	@skb: the packet
- *
- *	Send a packet through an SGE control Tx queue.  Packets sent through
- *	a control queue must fit entirely as immediate data.
- */
-static int ctrl_xmit(struct sge_ctrl_txq *q, struct sk_buff *skb)
-{
-	unsigned int ndesc;
-	struct fw_wr_hdr *wr;
-
-	if (unlikely(!is_imm(skb))) {
-		WARN_ON(1);
-		dev_kfree_skb(skb);
-		return NET_XMIT_DROP;
-	}
-
-	ndesc = DIV_ROUND_UP(skb->len, sizeof(struct tx_desc));
-	spin_lock(&q->sendq.lock);
-
-	if (unlikely(q->full)) {
-		skb->priority = ndesc;                  /* save for restart */
-		__skb_queue_tail(&q->sendq, skb);
-		spin_unlock(&q->sendq.lock);
-		return NET_XMIT_CN;
-	}
-
-	wr = (struct fw_wr_hdr *)&q->q.desc[q->q.pidx];
-	inline_tx_skb(skb, &q->q, wr);
-
-	txq_advance(&q->q, ndesc);
-	if (unlikely(txq_avail(&q->q) < TXQ_STOP_THRES))
-		ctrlq_check_stop(q, wr);
-
-	ring_tx_db(q->adap, &q->q, ndesc);
-	spin_unlock(&q->sendq.lock);
-
-	kfree_skb(skb);
-	return NET_XMIT_SUCCESS;
-}
-
-/**
- *	restart_ctrlq - restart a suspended control queue
- *	@data: the control queue to restart
- *
- *	Resumes transmission on a suspended Tx control queue.
- */
-static void restart_ctrlq(unsigned long data)
-{
-	struct sk_buff *skb;
-	unsigned int written = 0;
-	struct sge_ctrl_txq *q = (struct sge_ctrl_txq *)data;
-
-	spin_lock(&q->sendq.lock);
-	reclaim_completed_tx_imm(&q->q);
-	BUG_ON(txq_avail(&q->q) < TXQ_STOP_THRES);  /* q should be empty */
-
-	while ((skb = __skb_dequeue(&q->sendq)) != NULL) {
-		struct fw_wr_hdr *wr;
-		unsigned int ndesc = skb->priority;     /* previously saved */
-
-		/*
-		 * Write descriptors and free skbs outside the lock to limit
-		 * wait times.  q->full is still set so new skbs will be queued.
-		 */
-		spin_unlock(&q->sendq.lock);
-
-		wr = (struct fw_wr_hdr *)&q->q.desc[q->q.pidx];
-		inline_tx_skb(skb, &q->q, wr);
-		kfree_skb(skb);
-
-		written += ndesc;
-		txq_advance(&q->q, ndesc);
-		if (unlikely(txq_avail(&q->q) < TXQ_STOP_THRES)) {
-			unsigned long old = q->q.stops;
-
-			ctrlq_check_stop(q, wr);
-			if (q->q.stops != old) {          /* suspended anew */
-				spin_lock(&q->sendq.lock);
-				goto ringdb;
-			}
-		}
-		if (written > 16) {
-			ring_tx_db(q->adap, &q->q, written);
-			written = 0;
-		}
-		spin_lock(&q->sendq.lock);
-	}
-	q->full = 0;
-ringdb: if (written)
-		ring_tx_db(q->adap, &q->q, written);
-	spin_unlock(&q->sendq.lock);
-}
-
-/**
- *	t4_mgmt_tx - send a management message
- *	@adap: the adapter
- *	@skb: the packet containing the management message
- *
- *	Send a management message through control queue 0.
- */
-int t4_mgmt_tx(struct adapter *adap, struct sk_buff *skb)
-{
-	int ret;
-
-	local_bh_disable();
-	ret = ctrl_xmit(&adap->sge.ctrlq[0], skb);
-	local_bh_enable();
-	return ret;
-}
-
-/**
- *	is_ofld_imm - check whether a packet can be sent as immediate data
- *	@skb: the packet
- *
- *	Returns true if a packet can be sent as an offload WR with immediate
- *	data.  We currently use the same limit as for Ethernet packets.
- */
-static inline int is_ofld_imm(const struct sk_buff *skb)
-{
-	return skb->len <= MAX_IMM_TX_PKT_LEN;
-}
-
-/**
- *	calc_tx_flits_ofld - calculate # of flits for an offload packet
- *	@skb: the packet
- *
- *	Returns the number of flits needed for the given offload packet.
- *	These packets are already fully constructed and no additional headers
- *	will be added.
- */
-static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb)
-{
-	unsigned int flits, cnt;
-
-	if (is_ofld_imm(skb))
-		return DIV_ROUND_UP(skb->len, 8);
-
-	flits = skb_transport_offset(skb) / 8U;   /* headers */
-	cnt = skb_shinfo(skb)->nr_frags;
-	if (skb->tail != skb->transport_header)
-		cnt++;
-	return flits + sgl_len(cnt);
-}
-
-/**
- *	txq_stop_maperr - stop a Tx queue due to I/O MMU exhaustion
- *	@adap: the adapter
- *	@q: the queue to stop
- *
- *	Mark a Tx queue stopped due to I/O MMU exhaustion and resulting
- *	inability to map packets.  A periodic timer attempts to restart
- *	queues so marked.
- */
-static void txq_stop_maperr(struct sge_ofld_txq *q)
-{
-	q->mapping_err++;
-	q->q.stops++;
-	set_bit(q->q.cntxt_id - q->adap->sge.egr_start,
-		q->adap->sge.txq_maperr);
-}
-
-/**
- *	ofldtxq_stop - stop an offload Tx queue that has become full
- *	@q: the queue to stop
- *	@skb: the packet causing the queue to become full
- *
- *	Stops an offload Tx queue that has become full and modifies the packet
- *	being written to request a wakeup.
- */
-static void ofldtxq_stop(struct sge_ofld_txq *q, struct sk_buff *skb)
-{
-	struct fw_wr_hdr *wr = (struct fw_wr_hdr *)skb->data;
-
-	wr->lo |= htonl(FW_WR_EQUEQ | FW_WR_EQUIQ);
-	q->q.stops++;
-	q->full = 1;
-}
-
-/**
- *	service_ofldq - restart a suspended offload queue
- *	@q: the offload queue
- *
- *	Services an offload Tx queue by moving packets from its packet queue
- *	to the HW Tx ring.  The function starts and ends with the queue locked.
- */
-static void service_ofldq(struct sge_ofld_txq *q)
-{
-	u64 *pos;
-	int credits;
-	struct sk_buff *skb;
-	unsigned int written = 0;
-	unsigned int flits, ndesc;
-
-	while ((skb = skb_peek(&q->sendq)) != NULL && !q->full) {
-		/*
-		 * We drop the lock but leave skb on sendq, thus retaining
-		 * exclusive access to the state of the queue.
-		 */
-		spin_unlock(&q->sendq.lock);
-
-		reclaim_completed_tx(q->adap, &q->q, false);
-
-		flits = skb->priority;                /* previously saved */
-		ndesc = flits_to_desc(flits);
-		credits = txq_avail(&q->q) - ndesc;
-		BUG_ON(credits < 0);
-		if (unlikely(credits < TXQ_STOP_THRES))
-			ofldtxq_stop(q, skb);
-
-		pos = (u64 *)&q->q.desc[q->q.pidx];
-		if (is_ofld_imm(skb))
-			inline_tx_skb(skb, &q->q, pos);
-		else if (map_skb(q->adap->pdev_dev, skb,
-				 (dma_addr_t *)skb->head)) {
-			txq_stop_maperr(q);
-			spin_lock(&q->sendq.lock);
-			break;
-		} else {
-			int last_desc, hdr_len = skb_transport_offset(skb);
-
-			memcpy(pos, skb->data, hdr_len);
-			write_sgl(skb, &q->q, (void *)pos + hdr_len,
-				  pos + flits, hdr_len,
-				  (dma_addr_t *)skb->head);
-#ifdef CONFIG_NEED_DMA_MAP_STATE
-			skb->dev = q->adap->port[0];
-			skb->destructor = deferred_unmap_destructor;
-#endif
-			last_desc = q->q.pidx + ndesc - 1;
-			if (last_desc >= q->q.size)
-				last_desc -= q->q.size;
-			q->q.sdesc[last_desc].skb = skb;
-		}
-
-		txq_advance(&q->q, ndesc);
-		written += ndesc;
-		if (unlikely(written > 32)) {
-			ring_tx_db(q->adap, &q->q, written);
-			written = 0;
-		}
-
-		spin_lock(&q->sendq.lock);
-		__skb_unlink(skb, &q->sendq);
-		if (is_ofld_imm(skb))
-			kfree_skb(skb);
-	}
-	if (likely(written))
-		ring_tx_db(q->adap, &q->q, written);
-}
-
-/**
- *	ofld_xmit - send a packet through an offload queue
- *	@q: the Tx offload queue
- *	@skb: the packet
- *
- *	Send an offload packet through an SGE offload queue.
- */
-static int ofld_xmit(struct sge_ofld_txq *q, struct sk_buff *skb)
-{
-	skb->priority = calc_tx_flits_ofld(skb);       /* save for restart */
-	spin_lock(&q->sendq.lock);
-	__skb_queue_tail(&q->sendq, skb);
-	if (q->sendq.qlen == 1)
-		service_ofldq(q);
-	spin_unlock(&q->sendq.lock);
-	return NET_XMIT_SUCCESS;
-}
-
-/**
- *	restart_ofldq - restart a suspended offload queue
- *	@data: the offload queue to restart
- *
- *	Resumes transmission on a suspended Tx offload queue.
- */
-static void restart_ofldq(unsigned long data)
-{
-	struct sge_ofld_txq *q = (struct sge_ofld_txq *)data;
-
-	spin_lock(&q->sendq.lock);
-	q->full = 0;            /* the queue actually is completely empty now */
-	service_ofldq(q);
-	spin_unlock(&q->sendq.lock);
-}
-
-/**
- *	skb_txq - return the Tx queue an offload packet should use
- *	@skb: the packet
- *
- *	Returns the Tx queue an offload packet should use as indicated by bits
- *	1-15 in the packet's queue_mapping.
- */
-static inline unsigned int skb_txq(const struct sk_buff *skb)
-{
-	return skb->queue_mapping >> 1;
-}
-
-/**
- *	is_ctrl_pkt - return whether an offload packet is a control packet
- *	@skb: the packet
- *
- *	Returns whether an offload packet should use an OFLD or a CTRL
- *	Tx queue as indicated by bit 0 in the packet's queue_mapping.
- */
-static inline unsigned int is_ctrl_pkt(const struct sk_buff *skb)
-{
-	return skb->queue_mapping & 1;
-}
-
-static inline int ofld_send(struct adapter *adap, struct sk_buff *skb)
-{
-	unsigned int idx = skb_txq(skb);
-
-	if (unlikely(is_ctrl_pkt(skb)))
-		return ctrl_xmit(&adap->sge.ctrlq[idx], skb);
-	return ofld_xmit(&adap->sge.ofldtxq[idx], skb);
-}
-
-/**
- *	t4_ofld_send - send an offload packet
- *	@adap: the adapter
- *	@skb: the packet
- *
- *	Sends an offload packet.  We use the packet queue_mapping to select the
- *	appropriate Tx queue as follows: bit 0 indicates whether the packet
- *	should be sent as regular or control, bits 1-15 select the queue.
- */
-int t4_ofld_send(struct adapter *adap, struct sk_buff *skb)
-{
-	int ret;
-
-	local_bh_disable();
-	ret = ofld_send(adap, skb);
-	local_bh_enable();
-	return ret;
-}
-
-/**
- *	cxgb4_ofld_send - send an offload packet
- *	@dev: the net device
- *	@skb: the packet
- *
- *	Sends an offload packet.  This is an exported version of @t4_ofld_send,
- *	intended for ULDs.
- */
-int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb)
-{
-	return t4_ofld_send(netdev2adap(dev), skb);
-}
-EXPORT_SYMBOL(cxgb4_ofld_send);
-
-static inline void copy_frags(struct skb_shared_info *ssi,
-			      const struct pkt_gl *gl, unsigned int offset)
-{
-	unsigned int n;
-
-	/* usually there's just one frag */
-	ssi->frags[0].page = gl->frags[0].page;
-	ssi->frags[0].page_offset = gl->frags[0].page_offset + offset;
-	ssi->frags[0].size = gl->frags[0].size - offset;
-	ssi->nr_frags = gl->nfrags;
-	n = gl->nfrags - 1;
-	if (n)
-		memcpy(&ssi->frags[1], &gl->frags[1], n * sizeof(skb_frag_t));
-
-	/* get a reference to the last page, we don't own it */
-	get_page(gl->frags[n].page);
-}
-
-/**
- *	cxgb4_pktgl_to_skb - build an sk_buff from a packet gather list
- *	@gl: the gather list
- *	@skb_len: size of sk_buff main body if it carries fragments
- *	@pull_len: amount of data to move to the sk_buff's main body
- *
- *	Builds an sk_buff from the given packet gather list.  Returns the
- *	sk_buff or %NULL if sk_buff allocation failed.
- */
-struct sk_buff *cxgb4_pktgl_to_skb(const struct pkt_gl *gl,
-				   unsigned int skb_len, unsigned int pull_len)
-{
-	struct sk_buff *skb;
-
-	/*
-	 * Below we rely on RX_COPY_THRES being less than the smallest Rx buffer
-	 * size, which is expected since buffers are at least PAGE_SIZEd.
-	 * In this case packets up to RX_COPY_THRES have only one fragment.
-	 */
-	if (gl->tot_len <= RX_COPY_THRES) {
-		skb = dev_alloc_skb(gl->tot_len);
-		if (unlikely(!skb))
-			goto out;
-		__skb_put(skb, gl->tot_len);
-		skb_copy_to_linear_data(skb, gl->va, gl->tot_len);
-	} else {
-		skb = dev_alloc_skb(skb_len);
-		if (unlikely(!skb))
-			goto out;
-		__skb_put(skb, pull_len);
-		skb_copy_to_linear_data(skb, gl->va, pull_len);
-
-		copy_frags(skb_shinfo(skb), gl, pull_len);
-		skb->len = gl->tot_len;
-		skb->data_len = skb->len - pull_len;
-		skb->truesize += skb->data_len;
-	}
-out:	return skb;
-}
-EXPORT_SYMBOL(cxgb4_pktgl_to_skb);
-
-/**
- *	t4_pktgl_free - free a packet gather list
- *	@gl: the gather list
- *
- *	Releases the pages of a packet gather list.  We do not own the last
- *	page on the list and do not free it.
- */
-static void t4_pktgl_free(const struct pkt_gl *gl)
-{
-	int n;
-	const skb_frag_t *p;
-
-	for (p = gl->frags, n = gl->nfrags - 1; n--; p++)
-		put_page(p->page);
-}
-
-/*
- * Process an MPS trace packet.  Give it an unused protocol number so it won't
- * be delivered to anyone and send it to the stack for capture.
- */
-static noinline int handle_trace_pkt(struct adapter *adap,
-				     const struct pkt_gl *gl)
-{
-	struct sk_buff *skb;
-	struct cpl_trace_pkt *p;
-
-	skb = cxgb4_pktgl_to_skb(gl, RX_PULL_LEN, RX_PULL_LEN);
-	if (unlikely(!skb)) {
-		t4_pktgl_free(gl);
-		return 0;
-	}
-
-	p = (struct cpl_trace_pkt *)skb->data;
-	__skb_pull(skb, sizeof(*p));
-	skb_reset_mac_header(skb);
-	skb->protocol = htons(0xffff);
-	skb->dev = adap->port[0];
-	netif_receive_skb(skb);
-	return 0;
-}
-
-static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
-		   const struct cpl_rx_pkt *pkt)
-{
-	int ret;
-	struct sk_buff *skb;
-
-	skb = napi_get_frags(&rxq->rspq.napi);
-	if (unlikely(!skb)) {
-		t4_pktgl_free(gl);
-		rxq->stats.rx_drops++;
-		return;
-	}
-
-	copy_frags(skb_shinfo(skb), gl, RX_PKT_PAD);
-	skb->len = gl->tot_len - RX_PKT_PAD;
-	skb->data_len = skb->len;
-	skb->truesize += skb->data_len;
-	skb->ip_summed = CHECKSUM_UNNECESSARY;
-	skb_record_rx_queue(skb, rxq->rspq.idx);
-	if (rxq->rspq.netdev->features & NETIF_F_RXHASH)
-		skb->rxhash = (__force u32)pkt->rsshdr.hash_val;
-
-	if (unlikely(pkt->vlan_ex)) {
-		__vlan_hwaccel_put_tag(skb, ntohs(pkt->vlan));
-		rxq->stats.vlan_ex++;
-	}
-	ret = napi_gro_frags(&rxq->rspq.napi);
-	if (ret == GRO_HELD)
-		rxq->stats.lro_pkts++;
-	else if (ret == GRO_MERGED || ret == GRO_MERGED_FREE)
-		rxq->stats.lro_merged++;
-	rxq->stats.pkts++;
-	rxq->stats.rx_cso++;
-}
-
-/**
- *	t4_ethrx_handler - process an ingress ethernet packet
- *	@q: the response queue that received the packet
- *	@rsp: the response queue descriptor holding the RX_PKT message
- *	@si: the gather list of packet fragments
- *
- *	Process an ingress ethernet packet and deliver it to the stack.
- */
-int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
-		     const struct pkt_gl *si)
-{
-	bool csum_ok;
-	struct sk_buff *skb;
-	const struct cpl_rx_pkt *pkt;
-	struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq);
-
-	if (unlikely(*(u8 *)rsp == CPL_TRACE_PKT))
-		return handle_trace_pkt(q->adap, si);
-
-	pkt = (const struct cpl_rx_pkt *)rsp;
-	csum_ok = pkt->csum_calc && !pkt->err_vec;
-	if ((pkt->l2info & htonl(RXF_TCP)) &&
-	    (q->netdev->features & NETIF_F_GRO) && csum_ok && !pkt->ip_frag) {
-		do_gro(rxq, si, pkt);
-		return 0;
-	}
-
-	skb = cxgb4_pktgl_to_skb(si, RX_PKT_SKB_LEN, RX_PULL_LEN);
-	if (unlikely(!skb)) {
-		t4_pktgl_free(si);
-		rxq->stats.rx_drops++;
-		return 0;
-	}
-
-	__skb_pull(skb, RX_PKT_PAD);      /* remove ethernet header padding */
-	skb->protocol = eth_type_trans(skb, q->netdev);
-	skb_record_rx_queue(skb, q->idx);
-	if (skb->dev->features & NETIF_F_RXHASH)
-		skb->rxhash = (__force u32)pkt->rsshdr.hash_val;
-
-	rxq->stats.pkts++;
-
-	if (csum_ok && (q->netdev->features & NETIF_F_RXCSUM) &&
-	    (pkt->l2info & htonl(RXF_UDP | RXF_TCP))) {
-		if (!pkt->ip_frag) {
-			skb->ip_summed = CHECKSUM_UNNECESSARY;
-			rxq->stats.rx_cso++;
-		} else if (pkt->l2info & htonl(RXF_IP)) {
-			__sum16 c = (__force __sum16)pkt->csum;
-			skb->csum = csum_unfold(c);
-			skb->ip_summed = CHECKSUM_COMPLETE;
-			rxq->stats.rx_cso++;
-		}
-	} else
-		skb_checksum_none_assert(skb);
-
-	if (unlikely(pkt->vlan_ex)) {
-		__vlan_hwaccel_put_tag(skb, ntohs(pkt->vlan));
-		rxq->stats.vlan_ex++;
-	}
-	netif_receive_skb(skb);
-	return 0;
-}
-
-/**
- *	restore_rx_bufs - put back a packet's Rx buffers
- *	@si: the packet gather list
- *	@q: the SGE free list
- *	@frags: number of FL buffers to restore
- *
- *	Puts back on an FL the Rx buffers associated with @si.  The buffers
- *	have already been unmapped and are left unmapped, we mark them so to
- *	prevent further unmapping attempts.
- *
- *	This function undoes a series of @unmap_rx_buf calls when we find out
- *	that the current packet can't be processed right away afterall and we
- *	need to come back to it later.  This is a very rare event and there's
- *	no effort to make this particularly efficient.
- */
-static void restore_rx_bufs(const struct pkt_gl *si, struct sge_fl *q,
-			    int frags)
-{
-	struct rx_sw_desc *d;
-
-	while (frags--) {
-		if (q->cidx == 0)
-			q->cidx = q->size - 1;
-		else
-			q->cidx--;
-		d = &q->sdesc[q->cidx];
-		d->page = si->frags[frags].page;
-		d->dma_addr |= RX_UNMAPPED_BUF;
-		q->avail++;
-	}
-}
-
-/**
- *	is_new_response - check if a response is newly written
- *	@r: the response descriptor
- *	@q: the response queue
- *
- *	Returns true if a response descriptor contains a yet unprocessed
- *	response.
- */
-static inline bool is_new_response(const struct rsp_ctrl *r,
-				   const struct sge_rspq *q)
-{
-	return RSPD_GEN(r->type_gen) == q->gen;
-}
-
-/**
- *	rspq_next - advance to the next entry in a response queue
- *	@q: the queue
- *
- *	Updates the state of a response queue to advance it to the next entry.
- */
-static inline void rspq_next(struct sge_rspq *q)
-{
-	q->cur_desc = (void *)q->cur_desc + q->iqe_len;
-	if (unlikely(++q->cidx == q->size)) {
-		q->cidx = 0;
-		q->gen ^= 1;
-		q->cur_desc = q->desc;
-	}
-}
-
-/**
- *	process_responses - process responses from an SGE response queue
- *	@q: the ingress queue to process
- *	@budget: how many responses can be processed in this round
- *
- *	Process responses from an SGE response queue up to the supplied budget.
- *	Responses include received packets as well as control messages from FW
- *	or HW.
- *
- *	Additionally choose the interrupt holdoff time for the next interrupt
- *	on this queue.  If the system is under memory shortage use a fairly
- *	long delay to help recovery.
- */
-static int process_responses(struct sge_rspq *q, int budget)
-{
-	int ret, rsp_type;
-	int budget_left = budget;
-	const struct rsp_ctrl *rc;
-	struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq);
-
-	while (likely(budget_left)) {
-		rc = (void *)q->cur_desc + (q->iqe_len - sizeof(*rc));
-		if (!is_new_response(rc, q))
-			break;
-
-		rmb();
-		rsp_type = RSPD_TYPE(rc->type_gen);
-		if (likely(rsp_type == RSP_TYPE_FLBUF)) {
-			skb_frag_t *fp;
-			struct pkt_gl si;
-			const struct rx_sw_desc *rsd;
-			u32 len = ntohl(rc->pldbuflen_qid), bufsz, frags;
-
-			if (len & RSPD_NEWBUF) {
-				if (likely(q->offset > 0)) {
-					free_rx_bufs(q->adap, &rxq->fl, 1);
-					q->offset = 0;
-				}
-				len = RSPD_LEN(len);
-			}
-			si.tot_len = len;
-
-			/* gather packet fragments */
-			for (frags = 0, fp = si.frags; ; frags++, fp++) {
-				rsd = &rxq->fl.sdesc[rxq->fl.cidx];
-				bufsz = get_buf_size(rsd);
-				fp->page = rsd->page;
-				fp->page_offset = q->offset;
-				fp->size = min(bufsz, len);
-				len -= fp->size;
-				if (!len)
-					break;
-				unmap_rx_buf(q->adap, &rxq->fl);
-			}
-
-			/*
-			 * Last buffer remains mapped so explicitly make it
-			 * coherent for CPU access.
-			 */
-			dma_sync_single_for_cpu(q->adap->pdev_dev,
-						get_buf_addr(rsd),
-						fp->size, DMA_FROM_DEVICE);
-
-			si.va = page_address(si.frags[0].page) +
-				si.frags[0].page_offset;
-			prefetch(si.va);
-
-			si.nfrags = frags + 1;
-			ret = q->handler(q, q->cur_desc, &si);
-			if (likely(ret == 0))
-				q->offset += ALIGN(fp->size, FL_ALIGN);
-			else
-				restore_rx_bufs(&si, &rxq->fl, frags);
-		} else if (likely(rsp_type == RSP_TYPE_CPL)) {
-			ret = q->handler(q, q->cur_desc, NULL);
-		} else {
-			ret = q->handler(q, (const __be64 *)rc, CXGB4_MSG_AN);
-		}
-
-		if (unlikely(ret)) {
-			/* couldn't process descriptor, back off for recovery */
-			q->next_intr_params = QINTR_TIMER_IDX(NOMEM_TMR_IDX);
-			break;
-		}
-
-		rspq_next(q);
-		budget_left--;
-	}
-
-	if (q->offset >= 0 && rxq->fl.size - rxq->fl.avail >= 16)
-		__refill_fl(q->adap, &rxq->fl);
-	return budget - budget_left;
-}
-
-/**
- *	napi_rx_handler - the NAPI handler for Rx processing
- *	@napi: the napi instance
- *	@budget: how many packets we can process in this round
- *
- *	Handler for new data events when using NAPI.  This does not need any
- *	locking or protection from interrupts as data interrupts are off at
- *	this point and other adapter interrupts do not interfere (the latter
- *	in not a concern at all with MSI-X as non-data interrupts then have
- *	a separate handler).
- */
-static int napi_rx_handler(struct napi_struct *napi, int budget)
-{
-	unsigned int params;
-	struct sge_rspq *q = container_of(napi, struct sge_rspq, napi);
-	int work_done = process_responses(q, budget);
-
-	if (likely(work_done < budget)) {
-		napi_complete(napi);
-		params = q->next_intr_params;
-		q->next_intr_params = q->intr_params;
-	} else
-		params = QINTR_TIMER_IDX(7);
-
-	t4_write_reg(q->adap, MYPF_REG(SGE_PF_GTS), CIDXINC(work_done) |
-		     INGRESSQID((u32)q->cntxt_id) | SEINTARM(params));
-	return work_done;
-}
-
-/*
- * The MSI-X interrupt handler for an SGE response queue.
- */
-irqreturn_t t4_sge_intr_msix(int irq, void *cookie)
-{
-	struct sge_rspq *q = cookie;
-
-	napi_schedule(&q->napi);
-	return IRQ_HANDLED;
-}
-
-/*
- * Process the indirect interrupt entries in the interrupt queue and kick off
- * NAPI for each queue that has generated an entry.
- */
-static unsigned int process_intrq(struct adapter *adap)
-{
-	unsigned int credits;
-	const struct rsp_ctrl *rc;
-	struct sge_rspq *q = &adap->sge.intrq;
-
-	spin_lock(&adap->sge.intrq_lock);
-	for (credits = 0; ; credits++) {
-		rc = (void *)q->cur_desc + (q->iqe_len - sizeof(*rc));
-		if (!is_new_response(rc, q))
-			break;
-
-		rmb();
-		if (RSPD_TYPE(rc->type_gen) == RSP_TYPE_INTR) {
-			unsigned int qid = ntohl(rc->pldbuflen_qid);
-
-			qid -= adap->sge.ingr_start;
-			napi_schedule(&adap->sge.ingr_map[qid]->napi);
-		}
-
-		rspq_next(q);
-	}
-
-	t4_write_reg(adap, MYPF_REG(SGE_PF_GTS), CIDXINC(credits) |
-		     INGRESSQID(q->cntxt_id) | SEINTARM(q->intr_params));
-	spin_unlock(&adap->sge.intrq_lock);
-	return credits;
-}
-
-/*
- * The MSI interrupt handler, which handles data events from SGE response queues
- * as well as error and other async events as they all use the same MSI vector.
- */
-static irqreturn_t t4_intr_msi(int irq, void *cookie)
-{
-	struct adapter *adap = cookie;
-
-	t4_slow_intr_handler(adap);
-	process_intrq(adap);
-	return IRQ_HANDLED;
-}
-
-/*
- * Interrupt handler for legacy INTx interrupts.
- * Handles data events from SGE response queues as well as error and other
- * async events as they all use the same interrupt line.
- */
-static irqreturn_t t4_intr_intx(int irq, void *cookie)
-{
-	struct adapter *adap = cookie;
-
-	t4_write_reg(adap, MYPF_REG(PCIE_PF_CLI), 0);
-	if (t4_slow_intr_handler(adap) | process_intrq(adap))
-		return IRQ_HANDLED;
-	return IRQ_NONE;             /* probably shared interrupt */
-}
-
-/**
- *	t4_intr_handler - select the top-level interrupt handler
- *	@adap: the adapter
- *
- *	Selects the top-level interrupt handler based on the type of interrupts
- *	(MSI-X, MSI, or INTx).
- */
-irq_handler_t t4_intr_handler(struct adapter *adap)
-{
-	if (adap->flags & USING_MSIX)
-		return t4_sge_intr_msix;
-	if (adap->flags & USING_MSI)
-		return t4_intr_msi;
-	return t4_intr_intx;
-}
-
-static void sge_rx_timer_cb(unsigned long data)
-{
-	unsigned long m;
-	unsigned int i, cnt[2];
-	struct adapter *adap = (struct adapter *)data;
-	struct sge *s = &adap->sge;
-
-	for (i = 0; i < ARRAY_SIZE(s->starving_fl); i++)
-		for (m = s->starving_fl[i]; m; m &= m - 1) {
-			struct sge_eth_rxq *rxq;
-			unsigned int id = __ffs(m) + i * BITS_PER_LONG;
-			struct sge_fl *fl = s->egr_map[id];
-
-			clear_bit(id, s->starving_fl);
-			smp_mb__after_clear_bit();
-
-			if (fl_starving(fl)) {
-				rxq = container_of(fl, struct sge_eth_rxq, fl);
-				if (napi_reschedule(&rxq->rspq.napi))
-					fl->starving++;
-				else
-					set_bit(id, s->starving_fl);
-			}
-		}
-
-	t4_write_reg(adap, SGE_DEBUG_INDEX, 13);
-	cnt[0] = t4_read_reg(adap, SGE_DEBUG_DATA_HIGH);
-	cnt[1] = t4_read_reg(adap, SGE_DEBUG_DATA_LOW);
-
-	for (i = 0; i < 2; i++)
-		if (cnt[i] >= s->starve_thres) {
-			if (s->idma_state[i] || cnt[i] == 0xffffffff)
-				continue;
-			s->idma_state[i] = 1;
-			t4_write_reg(adap, SGE_DEBUG_INDEX, 11);
-			m = t4_read_reg(adap, SGE_DEBUG_DATA_LOW) >> (i * 16);
-			dev_warn(adap->pdev_dev,
-				 "SGE idma%u starvation detected for "
-				 "queue %lu\n", i, m & 0xffff);
-		} else if (s->idma_state[i])
-			s->idma_state[i] = 0;
-
-	mod_timer(&s->rx_timer, jiffies + RX_QCHECK_PERIOD);
-}
-
-static void sge_tx_timer_cb(unsigned long data)
-{
-	unsigned long m;
-	unsigned int i, budget;
-	struct adapter *adap = (struct adapter *)data;
-	struct sge *s = &adap->sge;
-
-	for (i = 0; i < ARRAY_SIZE(s->txq_maperr); i++)
-		for (m = s->txq_maperr[i]; m; m &= m - 1) {
-			unsigned long id = __ffs(m) + i * BITS_PER_LONG;
-			struct sge_ofld_txq *txq = s->egr_map[id];
-
-			clear_bit(id, s->txq_maperr);
-			tasklet_schedule(&txq->qresume_tsk);
-		}
-
-	budget = MAX_TIMER_TX_RECLAIM;
-	i = s->ethtxq_rover;
-	do {
-		struct sge_eth_txq *q = &s->ethtxq[i];
-
-		if (q->q.in_use &&
-		    time_after_eq(jiffies, q->txq->trans_start + HZ / 100) &&
-		    __netif_tx_trylock(q->txq)) {
-			int avail = reclaimable(&q->q);
-
-			if (avail) {
-				if (avail > budget)
-					avail = budget;
-
-				free_tx_desc(adap, &q->q, avail, true);
-				q->q.in_use -= avail;
-				budget -= avail;
-			}
-			__netif_tx_unlock(q->txq);
-		}
-
-		if (++i >= s->ethqsets)
-			i = 0;
-	} while (budget && i != s->ethtxq_rover);
-	s->ethtxq_rover = i;
-	mod_timer(&s->tx_timer, jiffies + (budget ? TX_QCHECK_PERIOD : 2));
-}
-
-int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
-		     struct net_device *dev, int intr_idx,
-		     struct sge_fl *fl, rspq_handler_t hnd)
-{
-	int ret, flsz = 0;
-	struct fw_iq_cmd c;
-	struct port_info *pi = netdev_priv(dev);
-
-	/* Size needs to be multiple of 16, including status entry. */
-	iq->size = roundup(iq->size, 16);
-
-	iq->desc = alloc_ring(adap->pdev_dev, iq->size, iq->iqe_len, 0,
-			      &iq->phys_addr, NULL, 0, NUMA_NO_NODE);
-	if (!iq->desc)
-		return -ENOMEM;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_vfn = htonl(FW_CMD_OP(FW_IQ_CMD) | FW_CMD_REQUEST |
-			    FW_CMD_WRITE | FW_CMD_EXEC |
-			    FW_IQ_CMD_PFN(adap->fn) | FW_IQ_CMD_VFN(0));
-	c.alloc_to_len16 = htonl(FW_IQ_CMD_ALLOC | FW_IQ_CMD_IQSTART(1) |
-				 FW_LEN16(c));
-	c.type_to_iqandstindex = htonl(FW_IQ_CMD_TYPE(FW_IQ_TYPE_FL_INT_CAP) |
-		FW_IQ_CMD_IQASYNCH(fwevtq) | FW_IQ_CMD_VIID(pi->viid) |
-		FW_IQ_CMD_IQANDST(intr_idx < 0) | FW_IQ_CMD_IQANUD(1) |
-		FW_IQ_CMD_IQANDSTINDEX(intr_idx >= 0 ? intr_idx :
-							-intr_idx - 1));
-	c.iqdroprss_to_iqesize = htons(FW_IQ_CMD_IQPCIECH(pi->tx_chan) |
-		FW_IQ_CMD_IQGTSMODE |
-		FW_IQ_CMD_IQINTCNTTHRESH(iq->pktcnt_idx) |
-		FW_IQ_CMD_IQESIZE(ilog2(iq->iqe_len) - 4));
-	c.iqsize = htons(iq->size);
-	c.iqaddr = cpu_to_be64(iq->phys_addr);
-
-	if (fl) {
-		fl->size = roundup(fl->size, 8);
-		fl->desc = alloc_ring(adap->pdev_dev, fl->size, sizeof(__be64),
-				      sizeof(struct rx_sw_desc), &fl->addr,
-				      &fl->sdesc, STAT_LEN, NUMA_NO_NODE);
-		if (!fl->desc)
-			goto fl_nomem;
-
-		flsz = fl->size / 8 + STAT_LEN / sizeof(struct tx_desc);
-		c.iqns_to_fl0congen = htonl(FW_IQ_CMD_FL0PACKEN |
-					    FW_IQ_CMD_FL0FETCHRO(1) |
-					    FW_IQ_CMD_FL0DATARO(1) |
-					    FW_IQ_CMD_FL0PADEN);
-		c.fl0dcaen_to_fl0cidxfthresh = htons(FW_IQ_CMD_FL0FBMIN(2) |
-				FW_IQ_CMD_FL0FBMAX(3));
-		c.fl0size = htons(flsz);
-		c.fl0addr = cpu_to_be64(fl->addr);
-	}
-
-	ret = t4_wr_mbox(adap, adap->fn, &c, sizeof(c), &c);
-	if (ret)
-		goto err;
-
-	netif_napi_add(dev, &iq->napi, napi_rx_handler, 64);
-	iq->cur_desc = iq->desc;
-	iq->cidx = 0;
-	iq->gen = 1;
-	iq->next_intr_params = iq->intr_params;
-	iq->cntxt_id = ntohs(c.iqid);
-	iq->abs_id = ntohs(c.physiqid);
-	iq->size--;                           /* subtract status entry */
-	iq->adap = adap;
-	iq->netdev = dev;
-	iq->handler = hnd;
-
-	/* set offset to -1 to distinguish ingress queues without FL */
-	iq->offset = fl ? 0 : -1;
-
-	adap->sge.ingr_map[iq->cntxt_id - adap->sge.ingr_start] = iq;
-
-	if (fl) {
-		fl->cntxt_id = ntohs(c.fl0id);
-		fl->avail = fl->pend_cred = 0;
-		fl->pidx = fl->cidx = 0;
-		fl->alloc_failed = fl->large_alloc_failed = fl->starving = 0;
-		adap->sge.egr_map[fl->cntxt_id - adap->sge.egr_start] = fl;
-		refill_fl(adap, fl, fl_cap(fl), GFP_KERNEL);
-	}
-	return 0;
-
-fl_nomem:
-	ret = -ENOMEM;
-err:
-	if (iq->desc) {
-		dma_free_coherent(adap->pdev_dev, iq->size * iq->iqe_len,
-				  iq->desc, iq->phys_addr);
-		iq->desc = NULL;
-	}
-	if (fl && fl->desc) {
-		kfree(fl->sdesc);
-		fl->sdesc = NULL;
-		dma_free_coherent(adap->pdev_dev, flsz * sizeof(struct tx_desc),
-				  fl->desc, fl->addr);
-		fl->desc = NULL;
-	}
-	return ret;
-}
-
-static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id)
-{
-	q->in_use = 0;
-	q->cidx = q->pidx = 0;
-	q->stops = q->restarts = 0;
-	q->stat = (void *)&q->desc[q->size];
-	q->cntxt_id = id;
-	adap->sge.egr_map[id - adap->sge.egr_start] = q;
-}
-
-int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq,
-			 struct net_device *dev, struct netdev_queue *netdevq,
-			 unsigned int iqid)
-{
-	int ret, nentries;
-	struct fw_eq_eth_cmd c;
-	struct port_info *pi = netdev_priv(dev);
-
-	/* Add status entries */
-	nentries = txq->q.size + STAT_LEN / sizeof(struct tx_desc);
-
-	txq->q.desc = alloc_ring(adap->pdev_dev, txq->q.size,
-			sizeof(struct tx_desc), sizeof(struct tx_sw_desc),
-			&txq->q.phys_addr, &txq->q.sdesc, STAT_LEN,
-			netdev_queue_numa_node_read(netdevq));
-	if (!txq->q.desc)
-		return -ENOMEM;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_vfn = htonl(FW_CMD_OP(FW_EQ_ETH_CMD) | FW_CMD_REQUEST |
-			    FW_CMD_WRITE | FW_CMD_EXEC |
-			    FW_EQ_ETH_CMD_PFN(adap->fn) | FW_EQ_ETH_CMD_VFN(0));
-	c.alloc_to_len16 = htonl(FW_EQ_ETH_CMD_ALLOC |
-				 FW_EQ_ETH_CMD_EQSTART | FW_LEN16(c));
-	c.viid_pkd = htonl(FW_EQ_ETH_CMD_VIID(pi->viid));
-	c.fetchszm_to_iqid = htonl(FW_EQ_ETH_CMD_HOSTFCMODE(2) |
-				   FW_EQ_ETH_CMD_PCIECHN(pi->tx_chan) |
-				   FW_EQ_ETH_CMD_FETCHRO(1) |
-				   FW_EQ_ETH_CMD_IQID(iqid));
-	c.dcaen_to_eqsize = htonl(FW_EQ_ETH_CMD_FBMIN(2) |
-				  FW_EQ_ETH_CMD_FBMAX(3) |
-				  FW_EQ_ETH_CMD_CIDXFTHRESH(5) |
-				  FW_EQ_ETH_CMD_EQSIZE(nentries));
-	c.eqaddr = cpu_to_be64(txq->q.phys_addr);
-
-	ret = t4_wr_mbox(adap, adap->fn, &c, sizeof(c), &c);
-	if (ret) {
-		kfree(txq->q.sdesc);
-		txq->q.sdesc = NULL;
-		dma_free_coherent(adap->pdev_dev,
-				  nentries * sizeof(struct tx_desc),
-				  txq->q.desc, txq->q.phys_addr);
-		txq->q.desc = NULL;
-		return ret;
-	}
-
-	init_txq(adap, &txq->q, FW_EQ_ETH_CMD_EQID_GET(ntohl(c.eqid_pkd)));
-	txq->txq = netdevq;
-	txq->tso = txq->tx_cso = txq->vlan_ins = 0;
-	txq->mapping_err = 0;
-	return 0;
-}
-
-int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq,
-			  struct net_device *dev, unsigned int iqid,
-			  unsigned int cmplqid)
-{
-	int ret, nentries;
-	struct fw_eq_ctrl_cmd c;
-	struct port_info *pi = netdev_priv(dev);
-
-	/* Add status entries */
-	nentries = txq->q.size + STAT_LEN / sizeof(struct tx_desc);
-
-	txq->q.desc = alloc_ring(adap->pdev_dev, nentries,
-				 sizeof(struct tx_desc), 0, &txq->q.phys_addr,
-				 NULL, 0, NUMA_NO_NODE);
-	if (!txq->q.desc)
-		return -ENOMEM;
-
-	c.op_to_vfn = htonl(FW_CMD_OP(FW_EQ_CTRL_CMD) | FW_CMD_REQUEST |
-			    FW_CMD_WRITE | FW_CMD_EXEC |
-			    FW_EQ_CTRL_CMD_PFN(adap->fn) |
-			    FW_EQ_CTRL_CMD_VFN(0));
-	c.alloc_to_len16 = htonl(FW_EQ_CTRL_CMD_ALLOC |
-				 FW_EQ_CTRL_CMD_EQSTART | FW_LEN16(c));
-	c.cmpliqid_eqid = htonl(FW_EQ_CTRL_CMD_CMPLIQID(cmplqid));
-	c.physeqid_pkd = htonl(0);
-	c.fetchszm_to_iqid = htonl(FW_EQ_CTRL_CMD_HOSTFCMODE(2) |
-				   FW_EQ_CTRL_CMD_PCIECHN(pi->tx_chan) |
-				   FW_EQ_CTRL_CMD_FETCHRO |
-				   FW_EQ_CTRL_CMD_IQID(iqid));
-	c.dcaen_to_eqsize = htonl(FW_EQ_CTRL_CMD_FBMIN(2) |
-				  FW_EQ_CTRL_CMD_FBMAX(3) |
-				  FW_EQ_CTRL_CMD_CIDXFTHRESH(5) |
-				  FW_EQ_CTRL_CMD_EQSIZE(nentries));
-	c.eqaddr = cpu_to_be64(txq->q.phys_addr);
-
-	ret = t4_wr_mbox(adap, adap->fn, &c, sizeof(c), &c);
-	if (ret) {
-		dma_free_coherent(adap->pdev_dev,
-				  nentries * sizeof(struct tx_desc),
-				  txq->q.desc, txq->q.phys_addr);
-		txq->q.desc = NULL;
-		return ret;
-	}
-
-	init_txq(adap, &txq->q, FW_EQ_CTRL_CMD_EQID_GET(ntohl(c.cmpliqid_eqid)));
-	txq->adap = adap;
-	skb_queue_head_init(&txq->sendq);
-	tasklet_init(&txq->qresume_tsk, restart_ctrlq, (unsigned long)txq);
-	txq->full = 0;
-	return 0;
-}
-
-int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq,
-			  struct net_device *dev, unsigned int iqid)
-{
-	int ret, nentries;
-	struct fw_eq_ofld_cmd c;
-	struct port_info *pi = netdev_priv(dev);
-
-	/* Add status entries */
-	nentries = txq->q.size + STAT_LEN / sizeof(struct tx_desc);
-
-	txq->q.desc = alloc_ring(adap->pdev_dev, txq->q.size,
-			sizeof(struct tx_desc), sizeof(struct tx_sw_desc),
-			&txq->q.phys_addr, &txq->q.sdesc, STAT_LEN,
-			NUMA_NO_NODE);
-	if (!txq->q.desc)
-		return -ENOMEM;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_vfn = htonl(FW_CMD_OP(FW_EQ_OFLD_CMD) | FW_CMD_REQUEST |
-			    FW_CMD_WRITE | FW_CMD_EXEC |
-			    FW_EQ_OFLD_CMD_PFN(adap->fn) |
-			    FW_EQ_OFLD_CMD_VFN(0));
-	c.alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_ALLOC |
-				 FW_EQ_OFLD_CMD_EQSTART | FW_LEN16(c));
-	c.fetchszm_to_iqid = htonl(FW_EQ_OFLD_CMD_HOSTFCMODE(2) |
-				   FW_EQ_OFLD_CMD_PCIECHN(pi->tx_chan) |
-				   FW_EQ_OFLD_CMD_FETCHRO(1) |
-				   FW_EQ_OFLD_CMD_IQID(iqid));
-	c.dcaen_to_eqsize = htonl(FW_EQ_OFLD_CMD_FBMIN(2) |
-				  FW_EQ_OFLD_CMD_FBMAX(3) |
-				  FW_EQ_OFLD_CMD_CIDXFTHRESH(5) |
-				  FW_EQ_OFLD_CMD_EQSIZE(nentries));
-	c.eqaddr = cpu_to_be64(txq->q.phys_addr);
-
-	ret = t4_wr_mbox(adap, adap->fn, &c, sizeof(c), &c);
-	if (ret) {
-		kfree(txq->q.sdesc);
-		txq->q.sdesc = NULL;
-		dma_free_coherent(adap->pdev_dev,
-				  nentries * sizeof(struct tx_desc),
-				  txq->q.desc, txq->q.phys_addr);
-		txq->q.desc = NULL;
-		return ret;
-	}
-
-	init_txq(adap, &txq->q, FW_EQ_OFLD_CMD_EQID_GET(ntohl(c.eqid_pkd)));
-	txq->adap = adap;
-	skb_queue_head_init(&txq->sendq);
-	tasklet_init(&txq->qresume_tsk, restart_ofldq, (unsigned long)txq);
-	txq->full = 0;
-	txq->mapping_err = 0;
-	return 0;
-}
-
-static void free_txq(struct adapter *adap, struct sge_txq *q)
-{
-	dma_free_coherent(adap->pdev_dev,
-			  q->size * sizeof(struct tx_desc) + STAT_LEN,
-			  q->desc, q->phys_addr);
-	q->cntxt_id = 0;
-	q->sdesc = NULL;
-	q->desc = NULL;
-}
-
-static void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq,
-			 struct sge_fl *fl)
-{
-	unsigned int fl_id = fl ? fl->cntxt_id : 0xffff;
-
-	adap->sge.ingr_map[rq->cntxt_id - adap->sge.ingr_start] = NULL;
-	t4_iq_free(adap, adap->fn, adap->fn, 0, FW_IQ_TYPE_FL_INT_CAP,
-		   rq->cntxt_id, fl_id, 0xffff);
-	dma_free_coherent(adap->pdev_dev, (rq->size + 1) * rq->iqe_len,
-			  rq->desc, rq->phys_addr);
-	netif_napi_del(&rq->napi);
-	rq->netdev = NULL;
-	rq->cntxt_id = rq->abs_id = 0;
-	rq->desc = NULL;
-
-	if (fl) {
-		free_rx_bufs(adap, fl, fl->avail);
-		dma_free_coherent(adap->pdev_dev, fl->size * 8 + STAT_LEN,
-				  fl->desc, fl->addr);
-		kfree(fl->sdesc);
-		fl->sdesc = NULL;
-		fl->cntxt_id = 0;
-		fl->desc = NULL;
-	}
-}
-
-/**
- *	t4_free_sge_resources - free SGE resources
- *	@adap: the adapter
- *
- *	Frees resources used by the SGE queue sets.
- */
-void t4_free_sge_resources(struct adapter *adap)
-{
-	int i;
-	struct sge_eth_rxq *eq = adap->sge.ethrxq;
-	struct sge_eth_txq *etq = adap->sge.ethtxq;
-	struct sge_ofld_rxq *oq = adap->sge.ofldrxq;
-
-	/* clean up Ethernet Tx/Rx queues */
-	for (i = 0; i < adap->sge.ethqsets; i++, eq++, etq++) {
-		if (eq->rspq.desc)
-			free_rspq_fl(adap, &eq->rspq, &eq->fl);
-		if (etq->q.desc) {
-			t4_eth_eq_free(adap, adap->fn, adap->fn, 0,
-				       etq->q.cntxt_id);
-			free_tx_desc(adap, &etq->q, etq->q.in_use, true);
-			kfree(etq->q.sdesc);
-			free_txq(adap, &etq->q);
-		}
-	}
-
-	/* clean up RDMA and iSCSI Rx queues */
-	for (i = 0; i < adap->sge.ofldqsets; i++, oq++) {
-		if (oq->rspq.desc)
-			free_rspq_fl(adap, &oq->rspq, &oq->fl);
-	}
-	for (i = 0, oq = adap->sge.rdmarxq; i < adap->sge.rdmaqs; i++, oq++) {
-		if (oq->rspq.desc)
-			free_rspq_fl(adap, &oq->rspq, &oq->fl);
-	}
-
-	/* clean up offload Tx queues */
-	for (i = 0; i < ARRAY_SIZE(adap->sge.ofldtxq); i++) {
-		struct sge_ofld_txq *q = &adap->sge.ofldtxq[i];
-
-		if (q->q.desc) {
-			tasklet_kill(&q->qresume_tsk);
-			t4_ofld_eq_free(adap, adap->fn, adap->fn, 0,
-					q->q.cntxt_id);
-			free_tx_desc(adap, &q->q, q->q.in_use, false);
-			kfree(q->q.sdesc);
-			__skb_queue_purge(&q->sendq);
-			free_txq(adap, &q->q);
-		}
-	}
-
-	/* clean up control Tx queues */
-	for (i = 0; i < ARRAY_SIZE(adap->sge.ctrlq); i++) {
-		struct sge_ctrl_txq *cq = &adap->sge.ctrlq[i];
-
-		if (cq->q.desc) {
-			tasklet_kill(&cq->qresume_tsk);
-			t4_ctrl_eq_free(adap, adap->fn, adap->fn, 0,
-					cq->q.cntxt_id);
-			__skb_queue_purge(&cq->sendq);
-			free_txq(adap, &cq->q);
-		}
-	}
-
-	if (adap->sge.fw_evtq.desc)
-		free_rspq_fl(adap, &adap->sge.fw_evtq, NULL);
-
-	if (adap->sge.intrq.desc)
-		free_rspq_fl(adap, &adap->sge.intrq, NULL);
-
-	/* clear the reverse egress queue map */
-	memset(adap->sge.egr_map, 0, sizeof(adap->sge.egr_map));
-}
-
-void t4_sge_start(struct adapter *adap)
-{
-	adap->sge.ethtxq_rover = 0;
-	mod_timer(&adap->sge.rx_timer, jiffies + RX_QCHECK_PERIOD);
-	mod_timer(&adap->sge.tx_timer, jiffies + TX_QCHECK_PERIOD);
-}
-
-/**
- *	t4_sge_stop - disable SGE operation
- *	@adap: the adapter
- *
- *	Stop tasklets and timers associated with the DMA engine.  Note that
- *	this is effective only if measures have been taken to disable any HW
- *	events that may restart them.
- */
-void t4_sge_stop(struct adapter *adap)
-{
-	int i;
-	struct sge *s = &adap->sge;
-
-	if (in_interrupt())  /* actions below require waiting */
-		return;
-
-	if (s->rx_timer.function)
-		del_timer_sync(&s->rx_timer);
-	if (s->tx_timer.function)
-		del_timer_sync(&s->tx_timer);
-
-	for (i = 0; i < ARRAY_SIZE(s->ofldtxq); i++) {
-		struct sge_ofld_txq *q = &s->ofldtxq[i];
-
-		if (q->q.desc)
-			tasklet_kill(&q->qresume_tsk);
-	}
-	for (i = 0; i < ARRAY_SIZE(s->ctrlq); i++) {
-		struct sge_ctrl_txq *cq = &s->ctrlq[i];
-
-		if (cq->q.desc)
-			tasklet_kill(&cq->qresume_tsk);
-	}
-}
-
-/**
- *	t4_sge_init - initialize SGE
- *	@adap: the adapter
- *
- *	Performs SGE initialization needed every time after a chip reset.
- *	We do not initialize any of the queues here, instead the driver
- *	top-level must request them individually.
- */
-void t4_sge_init(struct adapter *adap)
-{
-	unsigned int i, v;
-	struct sge *s = &adap->sge;
-	unsigned int fl_align_log = ilog2(FL_ALIGN);
-
-	t4_set_reg_field(adap, SGE_CONTROL, PKTSHIFT_MASK |
-			 INGPADBOUNDARY_MASK | EGRSTATUSPAGESIZE,
-			 INGPADBOUNDARY(fl_align_log - 5) | PKTSHIFT(2) |
-			 RXPKTCPLMODE |
-			 (STAT_LEN == 128 ? EGRSTATUSPAGESIZE : 0));
-
-	for (i = v = 0; i < 32; i += 4)
-		v |= (PAGE_SHIFT - 10) << i;
-	t4_write_reg(adap, SGE_HOST_PAGE_SIZE, v);
-	t4_write_reg(adap, SGE_FL_BUFFER_SIZE0, PAGE_SIZE);
-#if FL_PG_ORDER > 0
-	t4_write_reg(adap, SGE_FL_BUFFER_SIZE1, PAGE_SIZE << FL_PG_ORDER);
-#endif
-	t4_write_reg(adap, SGE_INGRESS_RX_THRESHOLD,
-		     THRESHOLD_0(s->counter_val[0]) |
-		     THRESHOLD_1(s->counter_val[1]) |
-		     THRESHOLD_2(s->counter_val[2]) |
-		     THRESHOLD_3(s->counter_val[3]));
-	t4_write_reg(adap, SGE_TIMER_VALUE_0_AND_1,
-		     TIMERVALUE0(us_to_core_ticks(adap, s->timer_val[0])) |
-		     TIMERVALUE1(us_to_core_ticks(adap, s->timer_val[1])));
-	t4_write_reg(adap, SGE_TIMER_VALUE_2_AND_3,
-		     TIMERVALUE0(us_to_core_ticks(adap, s->timer_val[2])) |
-		     TIMERVALUE1(us_to_core_ticks(adap, s->timer_val[3])));
-	t4_write_reg(adap, SGE_TIMER_VALUE_4_AND_5,
-		     TIMERVALUE0(us_to_core_ticks(adap, s->timer_val[4])) |
-		     TIMERVALUE1(us_to_core_ticks(adap, s->timer_val[5])));
-	setup_timer(&s->rx_timer, sge_rx_timer_cb, (unsigned long)adap);
-	setup_timer(&s->tx_timer, sge_tx_timer_cb, (unsigned long)adap);
-	s->starve_thres = core_ticks_per_usec(adap) * 1000000;  /* 1 s */
-	s->idma_state[0] = s->idma_state[1] = 0;
-	spin_lock_init(&s->intrq_lock);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4/t4fw_api.h linux-libre-3.2-gnu/drivers/net/cxgb4/t4fw_api.h
--- linux-libre-3.1-gnu/drivers/net/cxgb4/t4fw_api.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4/t4fw_api.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1623 +0,0 @@
-/*
- * This file is part of the Chelsio T4 Ethernet driver for Linux.
- *
- * Copyright (c) 2009-2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef _T4FW_INTERFACE_H_
-#define _T4FW_INTERFACE_H_
-
-#define FW_T4VF_SGE_BASE_ADDR      0x0000
-#define FW_T4VF_MPS_BASE_ADDR      0x0100
-#define FW_T4VF_PL_BASE_ADDR       0x0200
-#define FW_T4VF_MBDATA_BASE_ADDR   0x0240
-#define FW_T4VF_CIM_BASE_ADDR      0x0300
-
-enum fw_wr_opcodes {
-	FW_FILTER_WR                   = 0x02,
-	FW_ULPTX_WR                    = 0x04,
-	FW_TP_WR                       = 0x05,
-	FW_ETH_TX_PKT_WR               = 0x08,
-	FW_FLOWC_WR                    = 0x0a,
-	FW_OFLD_TX_DATA_WR             = 0x0b,
-	FW_CMD_WR                      = 0x10,
-	FW_ETH_TX_PKT_VM_WR            = 0x11,
-	FW_RI_RES_WR                   = 0x0c,
-	FW_RI_INIT_WR                  = 0x0d,
-	FW_RI_RDMA_WRITE_WR            = 0x14,
-	FW_RI_SEND_WR                  = 0x15,
-	FW_RI_RDMA_READ_WR             = 0x16,
-	FW_RI_RECV_WR                  = 0x17,
-	FW_RI_BIND_MW_WR               = 0x18,
-	FW_RI_FR_NSMR_WR               = 0x19,
-	FW_RI_INV_LSTAG_WR             = 0x1a,
-	FW_LASTC2E_WR                  = 0x40
-};
-
-struct fw_wr_hdr {
-	__be32 hi;
-	__be32 lo;
-};
-
-#define FW_WR_OP(x)	 ((x) << 24)
-#define FW_WR_ATOMIC(x)	 ((x) << 23)
-#define FW_WR_FLUSH(x)   ((x) << 22)
-#define FW_WR_COMPL(x)   ((x) << 21)
-#define FW_WR_IMMDLEN_MASK 0xff
-#define FW_WR_IMMDLEN(x) ((x) << 0)
-
-#define FW_WR_EQUIQ	(1U << 31)
-#define FW_WR_EQUEQ	(1U << 30)
-#define FW_WR_FLOWID(x)	((x) << 8)
-#define FW_WR_LEN16(x)	((x) << 0)
-
-struct fw_ulptx_wr {
-	__be32 op_to_compl;
-	__be32 flowid_len16;
-	u64 cookie;
-};
-
-struct fw_tp_wr {
-	__be32 op_to_immdlen;
-	__be32 flowid_len16;
-	u64 cookie;
-};
-
-struct fw_eth_tx_pkt_wr {
-	__be32 op_immdlen;
-	__be32 equiq_to_len16;
-	__be64 r3;
-};
-
-enum fw_flowc_mnem {
-	FW_FLOWC_MNEM_PFNVFN,		/* PFN [15:8] VFN [7:0] */
-	FW_FLOWC_MNEM_CH,
-	FW_FLOWC_MNEM_PORT,
-	FW_FLOWC_MNEM_IQID,
-	FW_FLOWC_MNEM_SNDNXT,
-	FW_FLOWC_MNEM_RCVNXT,
-	FW_FLOWC_MNEM_SNDBUF,
-	FW_FLOWC_MNEM_MSS,
-};
-
-struct fw_flowc_mnemval {
-	u8 mnemonic;
-	u8 r4[3];
-	__be32 val;
-};
-
-struct fw_flowc_wr {
-	__be32 op_to_nparams;
-#define FW_FLOWC_WR_NPARAMS(x)	((x) << 0)
-	__be32 flowid_len16;
-	struct fw_flowc_mnemval mnemval[0];
-};
-
-struct fw_ofld_tx_data_wr {
-	__be32 op_to_immdlen;
-	__be32 flowid_len16;
-	__be32 plen;
-	__be32 tunnel_to_proxy;
-#define FW_OFLD_TX_DATA_WR_TUNNEL(x)	 ((x) << 19)
-#define FW_OFLD_TX_DATA_WR_SAVE(x)	 ((x) << 18)
-#define FW_OFLD_TX_DATA_WR_FLUSH(x)	 ((x) << 17)
-#define FW_OFLD_TX_DATA_WR_URGENT(x)	 ((x) << 16)
-#define FW_OFLD_TX_DATA_WR_MORE(x)	 ((x) << 15)
-#define FW_OFLD_TX_DATA_WR_SHOVE(x)	 ((x) << 14)
-#define FW_OFLD_TX_DATA_WR_ULPMODE(x)	 ((x) << 10)
-#define FW_OFLD_TX_DATA_WR_ULPSUBMODE(x) ((x) << 6)
-};
-
-struct fw_cmd_wr {
-	__be32 op_dma;
-#define FW_CMD_WR_DMA (1U << 17)
-	__be32 len16_pkd;
-	__be64 cookie_daddr;
-};
-
-struct fw_eth_tx_pkt_vm_wr {
-	__be32 op_immdlen;
-	__be32 equiq_to_len16;
-	__be32 r3[2];
-	u8 ethmacdst[6];
-	u8 ethmacsrc[6];
-	__be16 ethtype;
-	__be16 vlantci;
-};
-
-#define FW_CMD_MAX_TIMEOUT 3000
-
-enum fw_cmd_opcodes {
-	FW_LDST_CMD                    = 0x01,
-	FW_RESET_CMD                   = 0x03,
-	FW_HELLO_CMD                   = 0x04,
-	FW_BYE_CMD                     = 0x05,
-	FW_INITIALIZE_CMD              = 0x06,
-	FW_CAPS_CONFIG_CMD             = 0x07,
-	FW_PARAMS_CMD                  = 0x08,
-	FW_PFVF_CMD                    = 0x09,
-	FW_IQ_CMD                      = 0x10,
-	FW_EQ_MNGT_CMD                 = 0x11,
-	FW_EQ_ETH_CMD                  = 0x12,
-	FW_EQ_CTRL_CMD                 = 0x13,
-	FW_EQ_OFLD_CMD                 = 0x21,
-	FW_VI_CMD                      = 0x14,
-	FW_VI_MAC_CMD                  = 0x15,
-	FW_VI_RXMODE_CMD               = 0x16,
-	FW_VI_ENABLE_CMD               = 0x17,
-	FW_ACL_MAC_CMD                 = 0x18,
-	FW_ACL_VLAN_CMD                = 0x19,
-	FW_VI_STATS_CMD                = 0x1a,
-	FW_PORT_CMD                    = 0x1b,
-	FW_PORT_STATS_CMD              = 0x1c,
-	FW_PORT_LB_STATS_CMD           = 0x1d,
-	FW_PORT_TRACE_CMD              = 0x1e,
-	FW_PORT_TRACE_MMAP_CMD         = 0x1f,
-	FW_RSS_IND_TBL_CMD             = 0x20,
-	FW_RSS_GLB_CONFIG_CMD          = 0x22,
-	FW_RSS_VI_CONFIG_CMD           = 0x23,
-	FW_LASTC2E_CMD                 = 0x40,
-	FW_ERROR_CMD                   = 0x80,
-	FW_DEBUG_CMD                   = 0x81,
-};
-
-enum fw_cmd_cap {
-	FW_CMD_CAP_PF                  = 0x01,
-	FW_CMD_CAP_DMAQ                = 0x02,
-	FW_CMD_CAP_PORT                = 0x04,
-	FW_CMD_CAP_PORTPROMISC         = 0x08,
-	FW_CMD_CAP_PORTSTATS           = 0x10,
-	FW_CMD_CAP_VF                  = 0x80,
-};
-
-/*
- * Generic command header flit0
- */
-struct fw_cmd_hdr {
-	__be32 hi;
-	__be32 lo;
-};
-
-#define FW_CMD_OP(x)		((x) << 24)
-#define FW_CMD_OP_GET(x)        (((x) >> 24) & 0xff)
-#define FW_CMD_REQUEST          (1U << 23)
-#define FW_CMD_READ		(1U << 22)
-#define FW_CMD_WRITE		(1U << 21)
-#define FW_CMD_EXEC		(1U << 20)
-#define FW_CMD_RAMASK(x)	((x) << 20)
-#define FW_CMD_RETVAL(x)	((x) << 8)
-#define FW_CMD_RETVAL_GET(x)	(((x) >> 8) & 0xff)
-#define FW_CMD_LEN16(x)         ((x) << 0)
-
-enum fw_ldst_addrspc {
-	FW_LDST_ADDRSPC_FIRMWARE  = 0x0001,
-	FW_LDST_ADDRSPC_SGE_EGRC  = 0x0008,
-	FW_LDST_ADDRSPC_SGE_INGC  = 0x0009,
-	FW_LDST_ADDRSPC_SGE_FLMC  = 0x000a,
-	FW_LDST_ADDRSPC_SGE_CONMC = 0x000b,
-	FW_LDST_ADDRSPC_TP_PIO    = 0x0010,
-	FW_LDST_ADDRSPC_TP_TM_PIO = 0x0011,
-	FW_LDST_ADDRSPC_TP_MIB    = 0x0012,
-	FW_LDST_ADDRSPC_MDIO      = 0x0018,
-	FW_LDST_ADDRSPC_MPS       = 0x0020,
-	FW_LDST_ADDRSPC_FUNC      = 0x0028
-};
-
-enum fw_ldst_mps_fid {
-	FW_LDST_MPS_ATRB,
-	FW_LDST_MPS_RPLC
-};
-
-enum fw_ldst_func_access_ctl {
-	FW_LDST_FUNC_ACC_CTL_VIID,
-	FW_LDST_FUNC_ACC_CTL_FID
-};
-
-enum fw_ldst_func_mod_index {
-	FW_LDST_FUNC_MPS
-};
-
-struct fw_ldst_cmd {
-	__be32 op_to_addrspace;
-#define FW_LDST_CMD_ADDRSPACE(x) ((x) << 0)
-	__be32 cycles_to_len16;
-	union fw_ldst {
-		struct fw_ldst_addrval {
-			__be32 addr;
-			__be32 val;
-		} addrval;
-		struct fw_ldst_idctxt {
-			__be32 physid;
-			__be32 msg_pkd;
-			__be32 ctxt_data7;
-			__be32 ctxt_data6;
-			__be32 ctxt_data5;
-			__be32 ctxt_data4;
-			__be32 ctxt_data3;
-			__be32 ctxt_data2;
-			__be32 ctxt_data1;
-			__be32 ctxt_data0;
-		} idctxt;
-		struct fw_ldst_mdio {
-			__be16 paddr_mmd;
-			__be16 raddr;
-			__be16 vctl;
-			__be16 rval;
-		} mdio;
-		struct fw_ldst_mps {
-			__be16 fid_ctl;
-			__be16 rplcpf_pkd;
-			__be32 rplc127_96;
-			__be32 rplc95_64;
-			__be32 rplc63_32;
-			__be32 rplc31_0;
-			__be32 atrb;
-			__be16 vlan[16];
-		} mps;
-		struct fw_ldst_func {
-			u8 access_ctl;
-			u8 mod_index;
-			__be16 ctl_id;
-			__be32 offset;
-			__be64 data0;
-			__be64 data1;
-		} func;
-	} u;
-};
-
-#define FW_LDST_CMD_MSG(x)	((x) << 31)
-#define FW_LDST_CMD_PADDR(x)	((x) << 8)
-#define FW_LDST_CMD_MMD(x)	((x) << 0)
-#define FW_LDST_CMD_FID(x)	((x) << 15)
-#define FW_LDST_CMD_CTL(x)	((x) << 0)
-#define FW_LDST_CMD_RPLCPF(x)	((x) << 0)
-
-struct fw_reset_cmd {
-	__be32 op_to_write;
-	__be32 retval_len16;
-	__be32 val;
-	__be32 r3;
-};
-
-struct fw_hello_cmd {
-	__be32 op_to_write;
-	__be32 retval_len16;
-	__be32 err_to_mbasyncnot;
-#define FW_HELLO_CMD_ERR	    (1U << 31)
-#define FW_HELLO_CMD_INIT	    (1U << 30)
-#define FW_HELLO_CMD_MASTERDIS(x)   ((x) << 29)
-#define FW_HELLO_CMD_MASTERFORCE(x) ((x) << 28)
-#define FW_HELLO_CMD_MBMASTER(x)    ((x) << 24)
-#define FW_HELLO_CMD_MBASYNCNOT(x)  ((x) << 20)
-	__be32 fwrev;
-};
-
-struct fw_bye_cmd {
-	__be32 op_to_write;
-	__be32 retval_len16;
-	__be64 r3;
-};
-
-struct fw_initialize_cmd {
-	__be32 op_to_write;
-	__be32 retval_len16;
-	__be64 r3;
-};
-
-enum fw_caps_config_hm {
-	FW_CAPS_CONFIG_HM_PCIE		= 0x00000001,
-	FW_CAPS_CONFIG_HM_PL		= 0x00000002,
-	FW_CAPS_CONFIG_HM_SGE		= 0x00000004,
-	FW_CAPS_CONFIG_HM_CIM		= 0x00000008,
-	FW_CAPS_CONFIG_HM_ULPTX		= 0x00000010,
-	FW_CAPS_CONFIG_HM_TP		= 0x00000020,
-	FW_CAPS_CONFIG_HM_ULPRX		= 0x00000040,
-	FW_CAPS_CONFIG_HM_PMRX		= 0x00000080,
-	FW_CAPS_CONFIG_HM_PMTX		= 0x00000100,
-	FW_CAPS_CONFIG_HM_MC		= 0x00000200,
-	FW_CAPS_CONFIG_HM_LE		= 0x00000400,
-	FW_CAPS_CONFIG_HM_MPS		= 0x00000800,
-	FW_CAPS_CONFIG_HM_XGMAC		= 0x00001000,
-	FW_CAPS_CONFIG_HM_CPLSWITCH	= 0x00002000,
-	FW_CAPS_CONFIG_HM_T4DBG		= 0x00004000,
-	FW_CAPS_CONFIG_HM_MI		= 0x00008000,
-	FW_CAPS_CONFIG_HM_I2CM		= 0x00010000,
-	FW_CAPS_CONFIG_HM_NCSI		= 0x00020000,
-	FW_CAPS_CONFIG_HM_SMB		= 0x00040000,
-	FW_CAPS_CONFIG_HM_MA		= 0x00080000,
-	FW_CAPS_CONFIG_HM_EDRAM		= 0x00100000,
-	FW_CAPS_CONFIG_HM_PMU		= 0x00200000,
-	FW_CAPS_CONFIG_HM_UART		= 0x00400000,
-	FW_CAPS_CONFIG_HM_SF		= 0x00800000,
-};
-
-enum fw_caps_config_nbm {
-	FW_CAPS_CONFIG_NBM_IPMI		= 0x00000001,
-	FW_CAPS_CONFIG_NBM_NCSI		= 0x00000002,
-};
-
-enum fw_caps_config_link {
-	FW_CAPS_CONFIG_LINK_PPP		= 0x00000001,
-	FW_CAPS_CONFIG_LINK_QFC		= 0x00000002,
-	FW_CAPS_CONFIG_LINK_DCBX	= 0x00000004,
-};
-
-enum fw_caps_config_switch {
-	FW_CAPS_CONFIG_SWITCH_INGRESS	= 0x00000001,
-	FW_CAPS_CONFIG_SWITCH_EGRESS	= 0x00000002,
-};
-
-enum fw_caps_config_nic {
-	FW_CAPS_CONFIG_NIC		= 0x00000001,
-	FW_CAPS_CONFIG_NIC_VM		= 0x00000002,
-};
-
-enum fw_caps_config_ofld {
-	FW_CAPS_CONFIG_OFLD		= 0x00000001,
-};
-
-enum fw_caps_config_rdma {
-	FW_CAPS_CONFIG_RDMA_RDDP	= 0x00000001,
-	FW_CAPS_CONFIG_RDMA_RDMAC	= 0x00000002,
-};
-
-enum fw_caps_config_iscsi {
-	FW_CAPS_CONFIG_ISCSI_INITIATOR_PDU = 0x00000001,
-	FW_CAPS_CONFIG_ISCSI_TARGET_PDU = 0x00000002,
-	FW_CAPS_CONFIG_ISCSI_INITIATOR_CNXOFLD = 0x00000004,
-	FW_CAPS_CONFIG_ISCSI_TARGET_CNXOFLD = 0x00000008,
-};
-
-enum fw_caps_config_fcoe {
-	FW_CAPS_CONFIG_FCOE_INITIATOR	= 0x00000001,
-	FW_CAPS_CONFIG_FCOE_TARGET	= 0x00000002,
-};
-
-struct fw_caps_config_cmd {
-	__be32 op_to_write;
-	__be32 retval_len16;
-	__be32 r2;
-	__be32 hwmbitmap;
-	__be16 nbmcaps;
-	__be16 linkcaps;
-	__be16 switchcaps;
-	__be16 r3;
-	__be16 niccaps;
-	__be16 ofldcaps;
-	__be16 rdmacaps;
-	__be16 r4;
-	__be16 iscsicaps;
-	__be16 fcoecaps;
-	__be32 r5;
-	__be64 r6;
-};
-
-/*
- * params command mnemonics
- */
-enum fw_params_mnem {
-	FW_PARAMS_MNEM_DEV		= 1,	/* device params */
-	FW_PARAMS_MNEM_PFVF		= 2,	/* function params */
-	FW_PARAMS_MNEM_REG		= 3,	/* limited register access */
-	FW_PARAMS_MNEM_DMAQ		= 4,	/* dma queue params */
-	FW_PARAMS_MNEM_LAST
-};
-
-/*
- * device parameters
- */
-enum fw_params_param_dev {
-	FW_PARAMS_PARAM_DEV_CCLK	= 0x00, /* chip core clock in khz */
-	FW_PARAMS_PARAM_DEV_PORTVEC	= 0x01, /* the port vector */
-	FW_PARAMS_PARAM_DEV_NTID	= 0x02, /* reads the number of TIDs
-						 * allocated by the device's
-						 * Lookup Engine
-						 */
-	FW_PARAMS_PARAM_DEV_FLOWC_BUFFIFO_SZ = 0x03,
-	FW_PARAMS_PARAM_DEV_INTVER_NIC	= 0x04,
-	FW_PARAMS_PARAM_DEV_INTVER_VNIC = 0x05,
-	FW_PARAMS_PARAM_DEV_INTVER_OFLD = 0x06,
-	FW_PARAMS_PARAM_DEV_INTVER_RI	= 0x07,
-	FW_PARAMS_PARAM_DEV_INTVER_ISCSIPDU = 0x08,
-	FW_PARAMS_PARAM_DEV_INTVER_ISCSI = 0x09,
-	FW_PARAMS_PARAM_DEV_INTVER_FCOE = 0x0A,
-	FW_PARAMS_PARAM_DEV_FWREV = 0x0B,
-	FW_PARAMS_PARAM_DEV_TPREV = 0x0C,
-};
-
-/*
- * physical and virtual function parameters
- */
-enum fw_params_param_pfvf {
-	FW_PARAMS_PARAM_PFVF_RWXCAPS	= 0x00,
-	FW_PARAMS_PARAM_PFVF_ROUTE_START = 0x01,
-	FW_PARAMS_PARAM_PFVF_ROUTE_END = 0x02,
-	FW_PARAMS_PARAM_PFVF_CLIP_START = 0x03,
-	FW_PARAMS_PARAM_PFVF_CLIP_END = 0x04,
-	FW_PARAMS_PARAM_PFVF_FILTER_START = 0x05,
-	FW_PARAMS_PARAM_PFVF_FILTER_END = 0x06,
-	FW_PARAMS_PARAM_PFVF_SERVER_START = 0x07,
-	FW_PARAMS_PARAM_PFVF_SERVER_END = 0x08,
-	FW_PARAMS_PARAM_PFVF_TDDP_START = 0x09,
-	FW_PARAMS_PARAM_PFVF_TDDP_END = 0x0A,
-	FW_PARAMS_PARAM_PFVF_ISCSI_START = 0x0B,
-	FW_PARAMS_PARAM_PFVF_ISCSI_END = 0x0C,
-	FW_PARAMS_PARAM_PFVF_STAG_START = 0x0D,
-	FW_PARAMS_PARAM_PFVF_STAG_END = 0x0E,
-	FW_PARAMS_PARAM_PFVF_RQ_START = 0x1F,
-	FW_PARAMS_PARAM_PFVF_RQ_END	= 0x10,
-	FW_PARAMS_PARAM_PFVF_PBL_START = 0x11,
-	FW_PARAMS_PARAM_PFVF_PBL_END	= 0x12,
-	FW_PARAMS_PARAM_PFVF_L2T_START = 0x13,
-	FW_PARAMS_PARAM_PFVF_L2T_END = 0x14,
-	FW_PARAMS_PARAM_PFVF_SQRQ_START = 0x15,
-	FW_PARAMS_PARAM_PFVF_SQRQ_END	= 0x16,
-	FW_PARAMS_PARAM_PFVF_CQ_START	= 0x17,
-	FW_PARAMS_PARAM_PFVF_CQ_END	= 0x18,
-	FW_PARAMS_PARAM_PFVF_SCHEDCLASS_ETH = 0x20,
-	FW_PARAMS_PARAM_PFVF_VIID       = 0x24,
-	FW_PARAMS_PARAM_PFVF_CPMASK     = 0x25,
-	FW_PARAMS_PARAM_PFVF_OCQ_START  = 0x26,
-	FW_PARAMS_PARAM_PFVF_OCQ_END    = 0x27,
-	FW_PARAMS_PARAM_PFVF_CONM_MAP   = 0x28,
-	FW_PARAMS_PARAM_PFVF_IQFLINT_START = 0x29,
-	FW_PARAMS_PARAM_PFVF_IQFLINT_END = 0x2A,
-	FW_PARAMS_PARAM_PFVF_EQ_START	= 0x2B,
-	FW_PARAMS_PARAM_PFVF_EQ_END	= 0x2C,
-};
-
-/*
- * dma queue parameters
- */
-enum fw_params_param_dmaq {
-	FW_PARAMS_PARAM_DMAQ_IQ_DCAEN_DCACPU = 0x00,
-	FW_PARAMS_PARAM_DMAQ_IQ_INTCNTTHRESH = 0x01,
-	FW_PARAMS_PARAM_DMAQ_EQ_CMPLIQID_MNGT = 0x10,
-	FW_PARAMS_PARAM_DMAQ_EQ_CMPLIQID_CTRL = 0x11,
-	FW_PARAMS_PARAM_DMAQ_EQ_SCHEDCLASS_ETH = 0x12,
-};
-
-#define FW_PARAMS_MNEM(x)      ((x) << 24)
-#define FW_PARAMS_PARAM_X(x)   ((x) << 16)
-#define FW_PARAMS_PARAM_Y(x)   ((x) << 8)
-#define FW_PARAMS_PARAM_Z(x)   ((x) << 0)
-#define FW_PARAMS_PARAM_XYZ(x) ((x) << 0)
-#define FW_PARAMS_PARAM_YZ(x)  ((x) << 0)
-
-struct fw_params_cmd {
-	__be32 op_to_vfn;
-	__be32 retval_len16;
-	struct fw_params_param {
-		__be32 mnem;
-		__be32 val;
-	} param[7];
-};
-
-#define FW_PARAMS_CMD_PFN(x) ((x) << 8)
-#define FW_PARAMS_CMD_VFN(x) ((x) << 0)
-
-struct fw_pfvf_cmd {
-	__be32 op_to_vfn;
-	__be32 retval_len16;
-	__be32 niqflint_niq;
-	__be32 type_to_neq;
-	__be32 tc_to_nexactf;
-	__be32 r_caps_to_nethctrl;
-	__be16 nricq;
-	__be16 nriqp;
-	__be32 r4;
-};
-
-#define FW_PFVF_CMD_PFN(x) ((x) << 8)
-#define FW_PFVF_CMD_VFN(x) ((x) << 0)
-
-#define FW_PFVF_CMD_NIQFLINT(x) ((x) << 20)
-#define FW_PFVF_CMD_NIQFLINT_GET(x) (((x) >> 20) & 0xfff)
-
-#define FW_PFVF_CMD_NIQ(x) ((x) << 0)
-#define FW_PFVF_CMD_NIQ_GET(x) (((x) >> 0) & 0xfffff)
-
-#define FW_PFVF_CMD_TYPE (1 << 31)
-#define FW_PFVF_CMD_TYPE_GET(x) (((x) >> 31) & 0x1)
-
-#define FW_PFVF_CMD_CMASK(x) ((x) << 24)
-#define FW_PFVF_CMD_CMASK_MASK 0xf
-#define FW_PFVF_CMD_CMASK_GET(x) (((x) >> 24) & FW_PFVF_CMD_CMASK_MASK)
-
-#define FW_PFVF_CMD_PMASK(x) ((x) << 20)
-#define FW_PFVF_CMD_PMASK_MASK 0xf
-#define FW_PFVF_CMD_PMASK_GET(x) (((x) >> 20) & FW_PFVF_CMD_PMASK_MASK)
-
-#define FW_PFVF_CMD_NEQ(x) ((x) << 0)
-#define FW_PFVF_CMD_NEQ_GET(x) (((x) >> 0) & 0xfffff)
-
-#define FW_PFVF_CMD_TC(x) ((x) << 24)
-#define FW_PFVF_CMD_TC_GET(x) (((x) >> 24) & 0xff)
-
-#define FW_PFVF_CMD_NVI(x) ((x) << 16)
-#define FW_PFVF_CMD_NVI_GET(x) (((x) >> 16) & 0xff)
-
-#define FW_PFVF_CMD_NEXACTF(x) ((x) << 0)
-#define FW_PFVF_CMD_NEXACTF_GET(x) (((x) >> 0) & 0xffff)
-
-#define FW_PFVF_CMD_R_CAPS(x) ((x) << 24)
-#define FW_PFVF_CMD_R_CAPS_GET(x) (((x) >> 24) & 0xff)
-
-#define FW_PFVF_CMD_WX_CAPS(x) ((x) << 16)
-#define FW_PFVF_CMD_WX_CAPS_GET(x) (((x) >> 16) & 0xff)
-
-#define FW_PFVF_CMD_NETHCTRL(x) ((x) << 0)
-#define FW_PFVF_CMD_NETHCTRL_GET(x) (((x) >> 0) & 0xffff)
-
-enum fw_iq_type {
-	FW_IQ_TYPE_FL_INT_CAP,
-	FW_IQ_TYPE_NO_FL_INT_CAP
-};
-
-struct fw_iq_cmd {
-	__be32 op_to_vfn;
-	__be32 alloc_to_len16;
-	__be16 physiqid;
-	__be16 iqid;
-	__be16 fl0id;
-	__be16 fl1id;
-	__be32 type_to_iqandstindex;
-	__be16 iqdroprss_to_iqesize;
-	__be16 iqsize;
-	__be64 iqaddr;
-	__be32 iqns_to_fl0congen;
-	__be16 fl0dcaen_to_fl0cidxfthresh;
-	__be16 fl0size;
-	__be64 fl0addr;
-	__be32 fl1cngchmap_to_fl1congen;
-	__be16 fl1dcaen_to_fl1cidxfthresh;
-	__be16 fl1size;
-	__be64 fl1addr;
-};
-
-#define FW_IQ_CMD_PFN(x) ((x) << 8)
-#define FW_IQ_CMD_VFN(x) ((x) << 0)
-
-#define FW_IQ_CMD_ALLOC (1U << 31)
-#define FW_IQ_CMD_FREE (1U << 30)
-#define FW_IQ_CMD_MODIFY (1U << 29)
-#define FW_IQ_CMD_IQSTART(x) ((x) << 28)
-#define FW_IQ_CMD_IQSTOP(x) ((x) << 27)
-
-#define FW_IQ_CMD_TYPE(x) ((x) << 29)
-#define FW_IQ_CMD_IQASYNCH(x) ((x) << 28)
-#define FW_IQ_CMD_VIID(x) ((x) << 16)
-#define FW_IQ_CMD_IQANDST(x) ((x) << 15)
-#define FW_IQ_CMD_IQANUS(x) ((x) << 14)
-#define FW_IQ_CMD_IQANUD(x) ((x) << 12)
-#define FW_IQ_CMD_IQANDSTINDEX(x) ((x) << 0)
-
-#define FW_IQ_CMD_IQDROPRSS (1U << 15)
-#define FW_IQ_CMD_IQGTSMODE (1U << 14)
-#define FW_IQ_CMD_IQPCIECH(x) ((x) << 12)
-#define FW_IQ_CMD_IQDCAEN(x) ((x) << 11)
-#define FW_IQ_CMD_IQDCACPU(x) ((x) << 6)
-#define FW_IQ_CMD_IQINTCNTTHRESH(x) ((x) << 4)
-#define FW_IQ_CMD_IQO (1U << 3)
-#define FW_IQ_CMD_IQCPRIO(x) ((x) << 2)
-#define FW_IQ_CMD_IQESIZE(x) ((x) << 0)
-
-#define FW_IQ_CMD_IQNS(x) ((x) << 31)
-#define FW_IQ_CMD_IQRO(x) ((x) << 30)
-#define FW_IQ_CMD_IQFLINTIQHSEN(x) ((x) << 28)
-#define FW_IQ_CMD_IQFLINTCONGEN(x) ((x) << 27)
-#define FW_IQ_CMD_IQFLINTISCSIC(x) ((x) << 26)
-#define FW_IQ_CMD_FL0CNGCHMAP(x) ((x) << 20)
-#define FW_IQ_CMD_FL0CACHELOCK(x) ((x) << 15)
-#define FW_IQ_CMD_FL0DBP(x) ((x) << 14)
-#define FW_IQ_CMD_FL0DATANS(x) ((x) << 13)
-#define FW_IQ_CMD_FL0DATARO(x) ((x) << 12)
-#define FW_IQ_CMD_FL0CONGCIF(x) ((x) << 11)
-#define FW_IQ_CMD_FL0ONCHIP(x) ((x) << 10)
-#define FW_IQ_CMD_FL0STATUSPGNS(x) ((x) << 9)
-#define FW_IQ_CMD_FL0STATUSPGRO(x) ((x) << 8)
-#define FW_IQ_CMD_FL0FETCHNS(x) ((x) << 7)
-#define FW_IQ_CMD_FL0FETCHRO(x) ((x) << 6)
-#define FW_IQ_CMD_FL0HOSTFCMODE(x) ((x) << 4)
-#define FW_IQ_CMD_FL0CPRIO(x) ((x) << 3)
-#define FW_IQ_CMD_FL0PADEN (1U << 2)
-#define FW_IQ_CMD_FL0PACKEN (1U << 1)
-#define FW_IQ_CMD_FL0CONGEN (1U << 0)
-
-#define FW_IQ_CMD_FL0DCAEN(x) ((x) << 15)
-#define FW_IQ_CMD_FL0DCACPU(x) ((x) << 10)
-#define FW_IQ_CMD_FL0FBMIN(x) ((x) << 7)
-#define FW_IQ_CMD_FL0FBMAX(x) ((x) << 4)
-#define FW_IQ_CMD_FL0CIDXFTHRESHO (1U << 3)
-#define FW_IQ_CMD_FL0CIDXFTHRESH(x) ((x) << 0)
-
-#define FW_IQ_CMD_FL1CNGCHMAP(x) ((x) << 20)
-#define FW_IQ_CMD_FL1CACHELOCK(x) ((x) << 15)
-#define FW_IQ_CMD_FL1DBP(x) ((x) << 14)
-#define FW_IQ_CMD_FL1DATANS(x) ((x) << 13)
-#define FW_IQ_CMD_FL1DATARO(x) ((x) << 12)
-#define FW_IQ_CMD_FL1CONGCIF(x) ((x) << 11)
-#define FW_IQ_CMD_FL1ONCHIP(x) ((x) << 10)
-#define FW_IQ_CMD_FL1STATUSPGNS(x) ((x) << 9)
-#define FW_IQ_CMD_FL1STATUSPGRO(x) ((x) << 8)
-#define FW_IQ_CMD_FL1FETCHNS(x) ((x) << 7)
-#define FW_IQ_CMD_FL1FETCHRO(x) ((x) << 6)
-#define FW_IQ_CMD_FL1HOSTFCMODE(x) ((x) << 4)
-#define FW_IQ_CMD_FL1CPRIO(x) ((x) << 3)
-#define FW_IQ_CMD_FL1PADEN (1U << 2)
-#define FW_IQ_CMD_FL1PACKEN (1U << 1)
-#define FW_IQ_CMD_FL1CONGEN (1U << 0)
-
-#define FW_IQ_CMD_FL1DCAEN(x) ((x) << 15)
-#define FW_IQ_CMD_FL1DCACPU(x) ((x) << 10)
-#define FW_IQ_CMD_FL1FBMIN(x) ((x) << 7)
-#define FW_IQ_CMD_FL1FBMAX(x) ((x) << 4)
-#define FW_IQ_CMD_FL1CIDXFTHRESHO (1U << 3)
-#define FW_IQ_CMD_FL1CIDXFTHRESH(x) ((x) << 0)
-
-struct fw_eq_eth_cmd {
-	__be32 op_to_vfn;
-	__be32 alloc_to_len16;
-	__be32 eqid_pkd;
-	__be32 physeqid_pkd;
-	__be32 fetchszm_to_iqid;
-	__be32 dcaen_to_eqsize;
-	__be64 eqaddr;
-	__be32 viid_pkd;
-	__be32 r8_lo;
-	__be64 r9;
-};
-
-#define FW_EQ_ETH_CMD_PFN(x) ((x) << 8)
-#define FW_EQ_ETH_CMD_VFN(x) ((x) << 0)
-#define FW_EQ_ETH_CMD_ALLOC (1U << 31)
-#define FW_EQ_ETH_CMD_FREE (1U << 30)
-#define FW_EQ_ETH_CMD_MODIFY (1U << 29)
-#define FW_EQ_ETH_CMD_EQSTART (1U << 28)
-#define FW_EQ_ETH_CMD_EQSTOP (1U << 27)
-
-#define FW_EQ_ETH_CMD_EQID(x) ((x) << 0)
-#define FW_EQ_ETH_CMD_EQID_GET(x) (((x) >> 0) & 0xfffff)
-#define FW_EQ_ETH_CMD_PHYSEQID(x) ((x) << 0)
-#define FW_EQ_ETH_CMD_PHYSEQID_GET(x) (((x) >> 0) & 0xfffff)
-
-#define FW_EQ_ETH_CMD_FETCHSZM(x) ((x) << 26)
-#define FW_EQ_ETH_CMD_STATUSPGNS(x) ((x) << 25)
-#define FW_EQ_ETH_CMD_STATUSPGRO(x) ((x) << 24)
-#define FW_EQ_ETH_CMD_FETCHNS(x) ((x) << 23)
-#define FW_EQ_ETH_CMD_FETCHRO(x) ((x) << 22)
-#define FW_EQ_ETH_CMD_HOSTFCMODE(x) ((x) << 20)
-#define FW_EQ_ETH_CMD_CPRIO(x) ((x) << 19)
-#define FW_EQ_ETH_CMD_ONCHIP(x) ((x) << 18)
-#define FW_EQ_ETH_CMD_PCIECHN(x) ((x) << 16)
-#define FW_EQ_ETH_CMD_IQID(x) ((x) << 0)
-
-#define FW_EQ_ETH_CMD_DCAEN(x) ((x) << 31)
-#define FW_EQ_ETH_CMD_DCACPU(x) ((x) << 26)
-#define FW_EQ_ETH_CMD_FBMIN(x) ((x) << 23)
-#define FW_EQ_ETH_CMD_FBMAX(x) ((x) << 20)
-#define FW_EQ_ETH_CMD_CIDXFTHRESHO(x) ((x) << 19)
-#define FW_EQ_ETH_CMD_CIDXFTHRESH(x) ((x) << 16)
-#define FW_EQ_ETH_CMD_EQSIZE(x) ((x) << 0)
-
-#define FW_EQ_ETH_CMD_VIID(x) ((x) << 16)
-
-struct fw_eq_ctrl_cmd {
-	__be32 op_to_vfn;
-	__be32 alloc_to_len16;
-	__be32 cmpliqid_eqid;
-	__be32 physeqid_pkd;
-	__be32 fetchszm_to_iqid;
-	__be32 dcaen_to_eqsize;
-	__be64 eqaddr;
-};
-
-#define FW_EQ_CTRL_CMD_PFN(x) ((x) << 8)
-#define FW_EQ_CTRL_CMD_VFN(x) ((x) << 0)
-
-#define FW_EQ_CTRL_CMD_ALLOC (1U << 31)
-#define FW_EQ_CTRL_CMD_FREE (1U << 30)
-#define FW_EQ_CTRL_CMD_MODIFY (1U << 29)
-#define FW_EQ_CTRL_CMD_EQSTART (1U << 28)
-#define FW_EQ_CTRL_CMD_EQSTOP (1U << 27)
-
-#define FW_EQ_CTRL_CMD_CMPLIQID(x) ((x) << 20)
-#define FW_EQ_CTRL_CMD_EQID(x) ((x) << 0)
-#define FW_EQ_CTRL_CMD_EQID_GET(x) (((x) >> 0) & 0xfffff)
-#define FW_EQ_CTRL_CMD_PHYSEQID_GET(x) (((x) >> 0) & 0xfffff)
-
-#define FW_EQ_CTRL_CMD_FETCHSZM (1U << 26)
-#define FW_EQ_CTRL_CMD_STATUSPGNS (1U << 25)
-#define FW_EQ_CTRL_CMD_STATUSPGRO (1U << 24)
-#define FW_EQ_CTRL_CMD_FETCHNS (1U << 23)
-#define FW_EQ_CTRL_CMD_FETCHRO (1U << 22)
-#define FW_EQ_CTRL_CMD_HOSTFCMODE(x) ((x) << 20)
-#define FW_EQ_CTRL_CMD_CPRIO(x) ((x) << 19)
-#define FW_EQ_CTRL_CMD_ONCHIP(x) ((x) << 18)
-#define FW_EQ_CTRL_CMD_PCIECHN(x) ((x) << 16)
-#define FW_EQ_CTRL_CMD_IQID(x) ((x) << 0)
-
-#define FW_EQ_CTRL_CMD_DCAEN(x) ((x) << 31)
-#define FW_EQ_CTRL_CMD_DCACPU(x) ((x) << 26)
-#define FW_EQ_CTRL_CMD_FBMIN(x) ((x) << 23)
-#define FW_EQ_CTRL_CMD_FBMAX(x) ((x) << 20)
-#define FW_EQ_CTRL_CMD_CIDXFTHRESHO(x) ((x) << 19)
-#define FW_EQ_CTRL_CMD_CIDXFTHRESH(x) ((x) << 16)
-#define FW_EQ_CTRL_CMD_EQSIZE(x) ((x) << 0)
-
-struct fw_eq_ofld_cmd {
-	__be32 op_to_vfn;
-	__be32 alloc_to_len16;
-	__be32 eqid_pkd;
-	__be32 physeqid_pkd;
-	__be32 fetchszm_to_iqid;
-	__be32 dcaen_to_eqsize;
-	__be64 eqaddr;
-};
-
-#define FW_EQ_OFLD_CMD_PFN(x) ((x) << 8)
-#define FW_EQ_OFLD_CMD_VFN(x) ((x) << 0)
-
-#define FW_EQ_OFLD_CMD_ALLOC (1U << 31)
-#define FW_EQ_OFLD_CMD_FREE (1U << 30)
-#define FW_EQ_OFLD_CMD_MODIFY (1U << 29)
-#define FW_EQ_OFLD_CMD_EQSTART (1U << 28)
-#define FW_EQ_OFLD_CMD_EQSTOP (1U << 27)
-
-#define FW_EQ_OFLD_CMD_EQID(x) ((x) << 0)
-#define FW_EQ_OFLD_CMD_EQID_GET(x) (((x) >> 0) & 0xfffff)
-#define FW_EQ_OFLD_CMD_PHYSEQID_GET(x) (((x) >> 0) & 0xfffff)
-
-#define FW_EQ_OFLD_CMD_FETCHSZM(x) ((x) << 26)
-#define FW_EQ_OFLD_CMD_STATUSPGNS(x) ((x) << 25)
-#define FW_EQ_OFLD_CMD_STATUSPGRO(x) ((x) << 24)
-#define FW_EQ_OFLD_CMD_FETCHNS(x) ((x) << 23)
-#define FW_EQ_OFLD_CMD_FETCHRO(x) ((x) << 22)
-#define FW_EQ_OFLD_CMD_HOSTFCMODE(x) ((x) << 20)
-#define FW_EQ_OFLD_CMD_CPRIO(x) ((x) << 19)
-#define FW_EQ_OFLD_CMD_ONCHIP(x) ((x) << 18)
-#define FW_EQ_OFLD_CMD_PCIECHN(x) ((x) << 16)
-#define FW_EQ_OFLD_CMD_IQID(x) ((x) << 0)
-
-#define FW_EQ_OFLD_CMD_DCAEN(x) ((x) << 31)
-#define FW_EQ_OFLD_CMD_DCACPU(x) ((x) << 26)
-#define FW_EQ_OFLD_CMD_FBMIN(x) ((x) << 23)
-#define FW_EQ_OFLD_CMD_FBMAX(x) ((x) << 20)
-#define FW_EQ_OFLD_CMD_CIDXFTHRESHO(x) ((x) << 19)
-#define FW_EQ_OFLD_CMD_CIDXFTHRESH(x) ((x) << 16)
-#define FW_EQ_OFLD_CMD_EQSIZE(x) ((x) << 0)
-
-/*
- * Macros for VIID parsing:
- * VIID - [10:8] PFN, [7] VI Valid, [6:0] VI number
- */
-#define FW_VIID_PFN_GET(x) (((x) >> 8) & 0x7)
-#define FW_VIID_VIVLD_GET(x) (((x) >> 7) & 0x1)
-#define FW_VIID_VIN_GET(x) (((x) >> 0) & 0x7F)
-
-struct fw_vi_cmd {
-	__be32 op_to_vfn;
-	__be32 alloc_to_len16;
-	__be16 type_viid;
-	u8 mac[6];
-	u8 portid_pkd;
-	u8 nmac;
-	u8 nmac0[6];
-	__be16 rsssize_pkd;
-	u8 nmac1[6];
-	__be16 idsiiq_pkd;
-	u8 nmac2[6];
-	__be16 idseiq_pkd;
-	u8 nmac3[6];
-	__be64 r9;
-	__be64 r10;
-};
-
-#define FW_VI_CMD_PFN(x) ((x) << 8)
-#define FW_VI_CMD_VFN(x) ((x) << 0)
-#define FW_VI_CMD_ALLOC (1U << 31)
-#define FW_VI_CMD_FREE (1U << 30)
-#define FW_VI_CMD_VIID(x) ((x) << 0)
-#define FW_VI_CMD_VIID_GET(x) ((x) & 0xfff)
-#define FW_VI_CMD_PORTID(x) ((x) << 4)
-#define FW_VI_CMD_PORTID_GET(x) (((x) >> 4) & 0xf)
-#define FW_VI_CMD_RSSSIZE_GET(x) (((x) >> 0) & 0x7ff)
-
-/* Special VI_MAC command index ids */
-#define FW_VI_MAC_ADD_MAC		0x3FF
-#define FW_VI_MAC_ADD_PERSIST_MAC	0x3FE
-#define FW_VI_MAC_MAC_BASED_FREE	0x3FD
-#define FW_CLS_TCAM_NUM_ENTRIES		336
-
-enum fw_vi_mac_smac {
-	FW_VI_MAC_MPS_TCAM_ENTRY,
-	FW_VI_MAC_MPS_TCAM_ONLY,
-	FW_VI_MAC_SMT_ONLY,
-	FW_VI_MAC_SMT_AND_MPSTCAM
-};
-
-enum fw_vi_mac_result {
-	FW_VI_MAC_R_SUCCESS,
-	FW_VI_MAC_R_F_NONEXISTENT_NOMEM,
-	FW_VI_MAC_R_SMAC_FAIL,
-	FW_VI_MAC_R_F_ACL_CHECK
-};
-
-struct fw_vi_mac_cmd {
-	__be32 op_to_viid;
-	__be32 freemacs_to_len16;
-	union fw_vi_mac {
-		struct fw_vi_mac_exact {
-			__be16 valid_to_idx;
-			u8 macaddr[6];
-		} exact[7];
-		struct fw_vi_mac_hash {
-			__be64 hashvec;
-		} hash;
-	} u;
-};
-
-#define FW_VI_MAC_CMD_VIID(x) ((x) << 0)
-#define FW_VI_MAC_CMD_FREEMACS(x) ((x) << 31)
-#define FW_VI_MAC_CMD_HASHVECEN (1U << 23)
-#define FW_VI_MAC_CMD_HASHUNIEN(x) ((x) << 22)
-#define FW_VI_MAC_CMD_VALID (1U << 15)
-#define FW_VI_MAC_CMD_PRIO(x) ((x) << 12)
-#define FW_VI_MAC_CMD_SMAC_RESULT(x) ((x) << 10)
-#define FW_VI_MAC_CMD_SMAC_RESULT_GET(x) (((x) >> 10) & 0x3)
-#define FW_VI_MAC_CMD_IDX(x) ((x) << 0)
-#define FW_VI_MAC_CMD_IDX_GET(x) (((x) >> 0) & 0x3ff)
-
-#define FW_RXMODE_MTU_NO_CHG	65535
-
-struct fw_vi_rxmode_cmd {
-	__be32 op_to_viid;
-	__be32 retval_len16;
-	__be32 mtu_to_vlanexen;
-	__be32 r4_lo;
-};
-
-#define FW_VI_RXMODE_CMD_VIID(x) ((x) << 0)
-#define FW_VI_RXMODE_CMD_MTU_MASK 0xffff
-#define FW_VI_RXMODE_CMD_MTU(x) ((x) << 16)
-#define FW_VI_RXMODE_CMD_PROMISCEN_MASK 0x3
-#define FW_VI_RXMODE_CMD_PROMISCEN(x) ((x) << 14)
-#define FW_VI_RXMODE_CMD_ALLMULTIEN_MASK 0x3
-#define FW_VI_RXMODE_CMD_ALLMULTIEN(x) ((x) << 12)
-#define FW_VI_RXMODE_CMD_BROADCASTEN_MASK 0x3
-#define FW_VI_RXMODE_CMD_BROADCASTEN(x) ((x) << 10)
-#define FW_VI_RXMODE_CMD_VLANEXEN_MASK 0x3
-#define FW_VI_RXMODE_CMD_VLANEXEN(x) ((x) << 8)
-
-struct fw_vi_enable_cmd {
-	__be32 op_to_viid;
-	__be32 ien_to_len16;
-	__be16 blinkdur;
-	__be16 r3;
-	__be32 r4;
-};
-
-#define FW_VI_ENABLE_CMD_VIID(x) ((x) << 0)
-#define FW_VI_ENABLE_CMD_IEN(x) ((x) << 31)
-#define FW_VI_ENABLE_CMD_EEN(x) ((x) << 30)
-#define FW_VI_ENABLE_CMD_LED (1U << 29)
-
-/* VI VF stats offset definitions */
-#define VI_VF_NUM_STATS	16
-enum fw_vi_stats_vf_index {
-	FW_VI_VF_STAT_TX_BCAST_BYTES_IX,
-	FW_VI_VF_STAT_TX_BCAST_FRAMES_IX,
-	FW_VI_VF_STAT_TX_MCAST_BYTES_IX,
-	FW_VI_VF_STAT_TX_MCAST_FRAMES_IX,
-	FW_VI_VF_STAT_TX_UCAST_BYTES_IX,
-	FW_VI_VF_STAT_TX_UCAST_FRAMES_IX,
-	FW_VI_VF_STAT_TX_DROP_FRAMES_IX,
-	FW_VI_VF_STAT_TX_OFLD_BYTES_IX,
-	FW_VI_VF_STAT_TX_OFLD_FRAMES_IX,
-	FW_VI_VF_STAT_RX_BCAST_BYTES_IX,
-	FW_VI_VF_STAT_RX_BCAST_FRAMES_IX,
-	FW_VI_VF_STAT_RX_MCAST_BYTES_IX,
-	FW_VI_VF_STAT_RX_MCAST_FRAMES_IX,
-	FW_VI_VF_STAT_RX_UCAST_BYTES_IX,
-	FW_VI_VF_STAT_RX_UCAST_FRAMES_IX,
-	FW_VI_VF_STAT_RX_ERR_FRAMES_IX
-};
-
-/* VI PF stats offset definitions */
-#define VI_PF_NUM_STATS	17
-enum fw_vi_stats_pf_index {
-	FW_VI_PF_STAT_TX_BCAST_BYTES_IX,
-	FW_VI_PF_STAT_TX_BCAST_FRAMES_IX,
-	FW_VI_PF_STAT_TX_MCAST_BYTES_IX,
-	FW_VI_PF_STAT_TX_MCAST_FRAMES_IX,
-	FW_VI_PF_STAT_TX_UCAST_BYTES_IX,
-	FW_VI_PF_STAT_TX_UCAST_FRAMES_IX,
-	FW_VI_PF_STAT_TX_OFLD_BYTES_IX,
-	FW_VI_PF_STAT_TX_OFLD_FRAMES_IX,
-	FW_VI_PF_STAT_RX_BYTES_IX,
-	FW_VI_PF_STAT_RX_FRAMES_IX,
-	FW_VI_PF_STAT_RX_BCAST_BYTES_IX,
-	FW_VI_PF_STAT_RX_BCAST_FRAMES_IX,
-	FW_VI_PF_STAT_RX_MCAST_BYTES_IX,
-	FW_VI_PF_STAT_RX_MCAST_FRAMES_IX,
-	FW_VI_PF_STAT_RX_UCAST_BYTES_IX,
-	FW_VI_PF_STAT_RX_UCAST_FRAMES_IX,
-	FW_VI_PF_STAT_RX_ERR_FRAMES_IX
-};
-
-struct fw_vi_stats_cmd {
-	__be32 op_to_viid;
-	__be32 retval_len16;
-	union fw_vi_stats {
-		struct fw_vi_stats_ctl {
-			__be16 nstats_ix;
-			__be16 r6;
-			__be32 r7;
-			__be64 stat0;
-			__be64 stat1;
-			__be64 stat2;
-			__be64 stat3;
-			__be64 stat4;
-			__be64 stat5;
-		} ctl;
-		struct fw_vi_stats_pf {
-			__be64 tx_bcast_bytes;
-			__be64 tx_bcast_frames;
-			__be64 tx_mcast_bytes;
-			__be64 tx_mcast_frames;
-			__be64 tx_ucast_bytes;
-			__be64 tx_ucast_frames;
-			__be64 tx_offload_bytes;
-			__be64 tx_offload_frames;
-			__be64 rx_pf_bytes;
-			__be64 rx_pf_frames;
-			__be64 rx_bcast_bytes;
-			__be64 rx_bcast_frames;
-			__be64 rx_mcast_bytes;
-			__be64 rx_mcast_frames;
-			__be64 rx_ucast_bytes;
-			__be64 rx_ucast_frames;
-			__be64 rx_err_frames;
-		} pf;
-		struct fw_vi_stats_vf {
-			__be64 tx_bcast_bytes;
-			__be64 tx_bcast_frames;
-			__be64 tx_mcast_bytes;
-			__be64 tx_mcast_frames;
-			__be64 tx_ucast_bytes;
-			__be64 tx_ucast_frames;
-			__be64 tx_drop_frames;
-			__be64 tx_offload_bytes;
-			__be64 tx_offload_frames;
-			__be64 rx_bcast_bytes;
-			__be64 rx_bcast_frames;
-			__be64 rx_mcast_bytes;
-			__be64 rx_mcast_frames;
-			__be64 rx_ucast_bytes;
-			__be64 rx_ucast_frames;
-			__be64 rx_err_frames;
-		} vf;
-	} u;
-};
-
-#define FW_VI_STATS_CMD_VIID(x) ((x) << 0)
-#define FW_VI_STATS_CMD_NSTATS(x) ((x) << 12)
-#define FW_VI_STATS_CMD_IX(x) ((x) << 0)
-
-struct fw_acl_mac_cmd {
-	__be32 op_to_vfn;
-	__be32 en_to_len16;
-	u8 nmac;
-	u8 r3[7];
-	__be16 r4;
-	u8 macaddr0[6];
-	__be16 r5;
-	u8 macaddr1[6];
-	__be16 r6;
-	u8 macaddr2[6];
-	__be16 r7;
-	u8 macaddr3[6];
-};
-
-#define FW_ACL_MAC_CMD_PFN(x) ((x) << 8)
-#define FW_ACL_MAC_CMD_VFN(x) ((x) << 0)
-#define FW_ACL_MAC_CMD_EN(x) ((x) << 31)
-
-struct fw_acl_vlan_cmd {
-	__be32 op_to_vfn;
-	__be32 en_to_len16;
-	u8 nvlan;
-	u8 dropnovlan_fm;
-	u8 r3_lo[6];
-	__be16 vlanid[16];
-};
-
-#define FW_ACL_VLAN_CMD_PFN(x) ((x) << 8)
-#define FW_ACL_VLAN_CMD_VFN(x) ((x) << 0)
-#define FW_ACL_VLAN_CMD_EN(x) ((x) << 31)
-#define FW_ACL_VLAN_CMD_DROPNOVLAN(x) ((x) << 7)
-#define FW_ACL_VLAN_CMD_FM(x) ((x) << 6)
-
-enum fw_port_cap {
-	FW_PORT_CAP_SPEED_100M		= 0x0001,
-	FW_PORT_CAP_SPEED_1G		= 0x0002,
-	FW_PORT_CAP_SPEED_2_5G		= 0x0004,
-	FW_PORT_CAP_SPEED_10G		= 0x0008,
-	FW_PORT_CAP_SPEED_40G		= 0x0010,
-	FW_PORT_CAP_SPEED_100G		= 0x0020,
-	FW_PORT_CAP_FC_RX		= 0x0040,
-	FW_PORT_CAP_FC_TX		= 0x0080,
-	FW_PORT_CAP_ANEG		= 0x0100,
-	FW_PORT_CAP_MDI_0		= 0x0200,
-	FW_PORT_CAP_MDI_1		= 0x0400,
-	FW_PORT_CAP_BEAN		= 0x0800,
-	FW_PORT_CAP_PMA_LPBK		= 0x1000,
-	FW_PORT_CAP_PCS_LPBK		= 0x2000,
-	FW_PORT_CAP_PHYXS_LPBK		= 0x4000,
-	FW_PORT_CAP_FAR_END_LPBK	= 0x8000,
-};
-
-enum fw_port_mdi {
-	FW_PORT_MDI_UNCHANGED,
-	FW_PORT_MDI_AUTO,
-	FW_PORT_MDI_F_STRAIGHT,
-	FW_PORT_MDI_F_CROSSOVER
-};
-
-#define FW_PORT_MDI(x) ((x) << 9)
-
-enum fw_port_action {
-	FW_PORT_ACTION_L1_CFG		= 0x0001,
-	FW_PORT_ACTION_L2_CFG		= 0x0002,
-	FW_PORT_ACTION_GET_PORT_INFO	= 0x0003,
-	FW_PORT_ACTION_L2_PPP_CFG	= 0x0004,
-	FW_PORT_ACTION_L2_DCB_CFG	= 0x0005,
-	FW_PORT_ACTION_LOW_PWR_TO_NORMAL = 0x0010,
-	FW_PORT_ACTION_L1_LOW_PWR_EN	= 0x0011,
-	FW_PORT_ACTION_L2_WOL_MODE_EN	= 0x0012,
-	FW_PORT_ACTION_LPBK_TO_NORMAL	= 0x0020,
-	FW_PORT_ACTION_L1_LPBK		= 0x0021,
-	FW_PORT_ACTION_L1_PMA_LPBK	= 0x0022,
-	FW_PORT_ACTION_L1_PCS_LPBK	= 0x0023,
-	FW_PORT_ACTION_L1_PHYXS_CSIDE_LPBK = 0x0024,
-	FW_PORT_ACTION_L1_PHYXS_ESIDE_LPBK = 0x0025,
-	FW_PORT_ACTION_PHY_RESET	= 0x0040,
-	FW_PORT_ACTION_PMA_RESET	= 0x0041,
-	FW_PORT_ACTION_PCS_RESET	= 0x0042,
-	FW_PORT_ACTION_PHYXS_RESET	= 0x0043,
-	FW_PORT_ACTION_DTEXS_REEST	= 0x0044,
-	FW_PORT_ACTION_AN_RESET		= 0x0045
-};
-
-enum fw_port_l2cfg_ctlbf {
-	FW_PORT_L2_CTLBF_OVLAN0	= 0x01,
-	FW_PORT_L2_CTLBF_OVLAN1	= 0x02,
-	FW_PORT_L2_CTLBF_OVLAN2	= 0x04,
-	FW_PORT_L2_CTLBF_OVLAN3	= 0x08,
-	FW_PORT_L2_CTLBF_IVLAN	= 0x10,
-	FW_PORT_L2_CTLBF_TXIPG	= 0x20
-};
-
-enum fw_port_dcb_cfg {
-	FW_PORT_DCB_CFG_PG	= 0x01,
-	FW_PORT_DCB_CFG_PFC	= 0x02,
-	FW_PORT_DCB_CFG_APPL	= 0x04
-};
-
-enum fw_port_dcb_cfg_rc {
-	FW_PORT_DCB_CFG_SUCCESS	= 0x0,
-	FW_PORT_DCB_CFG_ERROR	= 0x1
-};
-
-struct fw_port_cmd {
-	__be32 op_to_portid;
-	__be32 action_to_len16;
-	union fw_port {
-		struct fw_port_l1cfg {
-			__be32 rcap;
-			__be32 r;
-		} l1cfg;
-		struct fw_port_l2cfg {
-			__be16 ctlbf_to_ivlan0;
-			__be16 ivlantype;
-			__be32 txipg_pkd;
-			__be16 ovlan0mask;
-			__be16 ovlan0type;
-			__be16 ovlan1mask;
-			__be16 ovlan1type;
-			__be16 ovlan2mask;
-			__be16 ovlan2type;
-			__be16 ovlan3mask;
-			__be16 ovlan3type;
-		} l2cfg;
-		struct fw_port_info {
-			__be32 lstatus_to_modtype;
-			__be16 pcap;
-			__be16 acap;
-			__be16 mtu;
-			__u8   cbllen;
-			__u8   r9;
-			__be32 r10;
-			__be64 r11;
-		} info;
-		struct fw_port_ppp {
-			__be32 pppen_to_ncsich;
-			__be32 r11;
-		} ppp;
-		struct fw_port_dcb {
-			__be16 cfg;
-			u8 up_map;
-			u8 sf_cfgrc;
-			__be16 prot_ix;
-			u8 pe7_to_pe0;
-			u8 numTCPFCs;
-			__be32 pgid0_to_pgid7;
-			__be32 numTCs_oui;
-			u8 pgpc[8];
-		} dcb;
-	} u;
-};
-
-#define FW_PORT_CMD_READ (1U << 22)
-
-#define FW_PORT_CMD_PORTID(x) ((x) << 0)
-#define FW_PORT_CMD_PORTID_GET(x) (((x) >> 0) & 0xf)
-
-#define FW_PORT_CMD_ACTION(x) ((x) << 16)
-#define FW_PORT_CMD_ACTION_GET(x) (((x) >> 16) & 0xffff)
-
-#define FW_PORT_CMD_CTLBF(x) ((x) << 10)
-#define FW_PORT_CMD_OVLAN3(x) ((x) << 7)
-#define FW_PORT_CMD_OVLAN2(x) ((x) << 6)
-#define FW_PORT_CMD_OVLAN1(x) ((x) << 5)
-#define FW_PORT_CMD_OVLAN0(x) ((x) << 4)
-#define FW_PORT_CMD_IVLAN0(x) ((x) << 3)
-
-#define FW_PORT_CMD_TXIPG(x) ((x) << 19)
-
-#define FW_PORT_CMD_LSTATUS (1U << 31)
-#define FW_PORT_CMD_LSPEED(x) ((x) << 24)
-#define FW_PORT_CMD_LSPEED_GET(x) (((x) >> 24) & 0x3f)
-#define FW_PORT_CMD_TXPAUSE (1U << 23)
-#define FW_PORT_CMD_RXPAUSE (1U << 22)
-#define FW_PORT_CMD_MDIOCAP (1U << 21)
-#define FW_PORT_CMD_MDIOADDR_GET(x) (((x) >> 16) & 0x1f)
-#define FW_PORT_CMD_LPTXPAUSE (1U << 15)
-#define FW_PORT_CMD_LPRXPAUSE (1U << 14)
-#define FW_PORT_CMD_PTYPE_MASK 0x1f
-#define FW_PORT_CMD_PTYPE_GET(x) (((x) >> 8) & FW_PORT_CMD_PTYPE_MASK)
-#define FW_PORT_CMD_MODTYPE_MASK 0x1f
-#define FW_PORT_CMD_MODTYPE_GET(x) (((x) >> 0) & FW_PORT_CMD_MODTYPE_MASK)
-
-#define FW_PORT_CMD_PPPEN(x) ((x) << 31)
-#define FW_PORT_CMD_TPSRC(x) ((x) << 28)
-#define FW_PORT_CMD_NCSISRC(x) ((x) << 24)
-
-#define FW_PORT_CMD_CH0(x) ((x) << 20)
-#define FW_PORT_CMD_CH1(x) ((x) << 16)
-#define FW_PORT_CMD_CH2(x) ((x) << 12)
-#define FW_PORT_CMD_CH3(x) ((x) << 8)
-#define FW_PORT_CMD_NCSICH(x) ((x) << 4)
-
-enum fw_port_type {
-	FW_PORT_TYPE_FIBER_XFI,
-	FW_PORT_TYPE_FIBER_XAUI,
-	FW_PORT_TYPE_BT_SGMII,
-	FW_PORT_TYPE_BT_XFI,
-	FW_PORT_TYPE_BT_XAUI,
-	FW_PORT_TYPE_KX4,
-	FW_PORT_TYPE_CX4,
-	FW_PORT_TYPE_KX,
-	FW_PORT_TYPE_KR,
-	FW_PORT_TYPE_SFP,
-	FW_PORT_TYPE_BP_AP,
-	FW_PORT_TYPE_BP4_AP,
-
-	FW_PORT_TYPE_NONE = FW_PORT_CMD_PTYPE_MASK
-};
-
-enum fw_port_module_type {
-	FW_PORT_MOD_TYPE_NA,
-	FW_PORT_MOD_TYPE_LR,
-	FW_PORT_MOD_TYPE_SR,
-	FW_PORT_MOD_TYPE_ER,
-	FW_PORT_MOD_TYPE_TWINAX_PASSIVE,
-	FW_PORT_MOD_TYPE_TWINAX_ACTIVE,
-	FW_PORT_MOD_TYPE_LRM,
-
-	FW_PORT_MOD_TYPE_NONE = FW_PORT_CMD_MODTYPE_MASK
-};
-
-/* port stats */
-#define FW_NUM_PORT_STATS 50
-#define FW_NUM_PORT_TX_STATS 23
-#define FW_NUM_PORT_RX_STATS 27
-
-enum fw_port_stats_tx_index {
-	FW_STAT_TX_PORT_BYTES_IX,
-	FW_STAT_TX_PORT_FRAMES_IX,
-	FW_STAT_TX_PORT_BCAST_IX,
-	FW_STAT_TX_PORT_MCAST_IX,
-	FW_STAT_TX_PORT_UCAST_IX,
-	FW_STAT_TX_PORT_ERROR_IX,
-	FW_STAT_TX_PORT_64B_IX,
-	FW_STAT_TX_PORT_65B_127B_IX,
-	FW_STAT_TX_PORT_128B_255B_IX,
-	FW_STAT_TX_PORT_256B_511B_IX,
-	FW_STAT_TX_PORT_512B_1023B_IX,
-	FW_STAT_TX_PORT_1024B_1518B_IX,
-	FW_STAT_TX_PORT_1519B_MAX_IX,
-	FW_STAT_TX_PORT_DROP_IX,
-	FW_STAT_TX_PORT_PAUSE_IX,
-	FW_STAT_TX_PORT_PPP0_IX,
-	FW_STAT_TX_PORT_PPP1_IX,
-	FW_STAT_TX_PORT_PPP2_IX,
-	FW_STAT_TX_PORT_PPP3_IX,
-	FW_STAT_TX_PORT_PPP4_IX,
-	FW_STAT_TX_PORT_PPP5_IX,
-	FW_STAT_TX_PORT_PPP6_IX,
-	FW_STAT_TX_PORT_PPP7_IX
-};
-
-enum fw_port_stat_rx_index {
-	FW_STAT_RX_PORT_BYTES_IX,
-	FW_STAT_RX_PORT_FRAMES_IX,
-	FW_STAT_RX_PORT_BCAST_IX,
-	FW_STAT_RX_PORT_MCAST_IX,
-	FW_STAT_RX_PORT_UCAST_IX,
-	FW_STAT_RX_PORT_MTU_ERROR_IX,
-	FW_STAT_RX_PORT_MTU_CRC_ERROR_IX,
-	FW_STAT_RX_PORT_CRC_ERROR_IX,
-	FW_STAT_RX_PORT_LEN_ERROR_IX,
-	FW_STAT_RX_PORT_SYM_ERROR_IX,
-	FW_STAT_RX_PORT_64B_IX,
-	FW_STAT_RX_PORT_65B_127B_IX,
-	FW_STAT_RX_PORT_128B_255B_IX,
-	FW_STAT_RX_PORT_256B_511B_IX,
-	FW_STAT_RX_PORT_512B_1023B_IX,
-	FW_STAT_RX_PORT_1024B_1518B_IX,
-	FW_STAT_RX_PORT_1519B_MAX_IX,
-	FW_STAT_RX_PORT_PAUSE_IX,
-	FW_STAT_RX_PORT_PPP0_IX,
-	FW_STAT_RX_PORT_PPP1_IX,
-	FW_STAT_RX_PORT_PPP2_IX,
-	FW_STAT_RX_PORT_PPP3_IX,
-	FW_STAT_RX_PORT_PPP4_IX,
-	FW_STAT_RX_PORT_PPP5_IX,
-	FW_STAT_RX_PORT_PPP6_IX,
-	FW_STAT_RX_PORT_PPP7_IX,
-	FW_STAT_RX_PORT_LESS_64B_IX
-};
-
-struct fw_port_stats_cmd {
-	__be32 op_to_portid;
-	__be32 retval_len16;
-	union fw_port_stats {
-		struct fw_port_stats_ctl {
-			u8 nstats_bg_bm;
-			u8 tx_ix;
-			__be16 r6;
-			__be32 r7;
-			__be64 stat0;
-			__be64 stat1;
-			__be64 stat2;
-			__be64 stat3;
-			__be64 stat4;
-			__be64 stat5;
-		} ctl;
-		struct fw_port_stats_all {
-			__be64 tx_bytes;
-			__be64 tx_frames;
-			__be64 tx_bcast;
-			__be64 tx_mcast;
-			__be64 tx_ucast;
-			__be64 tx_error;
-			__be64 tx_64b;
-			__be64 tx_65b_127b;
-			__be64 tx_128b_255b;
-			__be64 tx_256b_511b;
-			__be64 tx_512b_1023b;
-			__be64 tx_1024b_1518b;
-			__be64 tx_1519b_max;
-			__be64 tx_drop;
-			__be64 tx_pause;
-			__be64 tx_ppp0;
-			__be64 tx_ppp1;
-			__be64 tx_ppp2;
-			__be64 tx_ppp3;
-			__be64 tx_ppp4;
-			__be64 tx_ppp5;
-			__be64 tx_ppp6;
-			__be64 tx_ppp7;
-			__be64 rx_bytes;
-			__be64 rx_frames;
-			__be64 rx_bcast;
-			__be64 rx_mcast;
-			__be64 rx_ucast;
-			__be64 rx_mtu_error;
-			__be64 rx_mtu_crc_error;
-			__be64 rx_crc_error;
-			__be64 rx_len_error;
-			__be64 rx_sym_error;
-			__be64 rx_64b;
-			__be64 rx_65b_127b;
-			__be64 rx_128b_255b;
-			__be64 rx_256b_511b;
-			__be64 rx_512b_1023b;
-			__be64 rx_1024b_1518b;
-			__be64 rx_1519b_max;
-			__be64 rx_pause;
-			__be64 rx_ppp0;
-			__be64 rx_ppp1;
-			__be64 rx_ppp2;
-			__be64 rx_ppp3;
-			__be64 rx_ppp4;
-			__be64 rx_ppp5;
-			__be64 rx_ppp6;
-			__be64 rx_ppp7;
-			__be64 rx_less_64b;
-			__be64 rx_bg_drop;
-			__be64 rx_bg_trunc;
-		} all;
-	} u;
-};
-
-#define FW_PORT_STATS_CMD_NSTATS(x) ((x) << 4)
-#define FW_PORT_STATS_CMD_BG_BM(x) ((x) << 0)
-#define FW_PORT_STATS_CMD_TX(x) ((x) << 7)
-#define FW_PORT_STATS_CMD_IX(x) ((x) << 0)
-
-/* port loopback stats */
-#define FW_NUM_LB_STATS 16
-enum fw_port_lb_stats_index {
-	FW_STAT_LB_PORT_BYTES_IX,
-	FW_STAT_LB_PORT_FRAMES_IX,
-	FW_STAT_LB_PORT_BCAST_IX,
-	FW_STAT_LB_PORT_MCAST_IX,
-	FW_STAT_LB_PORT_UCAST_IX,
-	FW_STAT_LB_PORT_ERROR_IX,
-	FW_STAT_LB_PORT_64B_IX,
-	FW_STAT_LB_PORT_65B_127B_IX,
-	FW_STAT_LB_PORT_128B_255B_IX,
-	FW_STAT_LB_PORT_256B_511B_IX,
-	FW_STAT_LB_PORT_512B_1023B_IX,
-	FW_STAT_LB_PORT_1024B_1518B_IX,
-	FW_STAT_LB_PORT_1519B_MAX_IX,
-	FW_STAT_LB_PORT_DROP_FRAMES_IX
-};
-
-struct fw_port_lb_stats_cmd {
-	__be32 op_to_lbport;
-	__be32 retval_len16;
-	union fw_port_lb_stats {
-		struct fw_port_lb_stats_ctl {
-			u8 nstats_bg_bm;
-			u8 ix_pkd;
-			__be16 r6;
-			__be32 r7;
-			__be64 stat0;
-			__be64 stat1;
-			__be64 stat2;
-			__be64 stat3;
-			__be64 stat4;
-			__be64 stat5;
-		} ctl;
-		struct fw_port_lb_stats_all {
-			__be64 tx_bytes;
-			__be64 tx_frames;
-			__be64 tx_bcast;
-			__be64 tx_mcast;
-			__be64 tx_ucast;
-			__be64 tx_error;
-			__be64 tx_64b;
-			__be64 tx_65b_127b;
-			__be64 tx_128b_255b;
-			__be64 tx_256b_511b;
-			__be64 tx_512b_1023b;
-			__be64 tx_1024b_1518b;
-			__be64 tx_1519b_max;
-			__be64 rx_lb_drop;
-			__be64 rx_lb_trunc;
-		} all;
-	} u;
-};
-
-#define FW_PORT_LB_STATS_CMD_LBPORT(x) ((x) << 0)
-#define FW_PORT_LB_STATS_CMD_NSTATS(x) ((x) << 4)
-#define FW_PORT_LB_STATS_CMD_BG_BM(x) ((x) << 0)
-#define FW_PORT_LB_STATS_CMD_IX(x) ((x) << 0)
-
-struct fw_rss_ind_tbl_cmd {
-	__be32 op_to_viid;
-#define FW_RSS_IND_TBL_CMD_VIID(x) ((x) << 0)
-	__be32 retval_len16;
-	__be16 niqid;
-	__be16 startidx;
-	__be32 r3;
-	__be32 iq0_to_iq2;
-#define FW_RSS_IND_TBL_CMD_IQ0(x) ((x) << 20)
-#define FW_RSS_IND_TBL_CMD_IQ1(x) ((x) << 10)
-#define FW_RSS_IND_TBL_CMD_IQ2(x) ((x) << 0)
-	__be32 iq3_to_iq5;
-	__be32 iq6_to_iq8;
-	__be32 iq9_to_iq11;
-	__be32 iq12_to_iq14;
-	__be32 iq15_to_iq17;
-	__be32 iq18_to_iq20;
-	__be32 iq21_to_iq23;
-	__be32 iq24_to_iq26;
-	__be32 iq27_to_iq29;
-	__be32 iq30_iq31;
-	__be32 r15_lo;
-};
-
-struct fw_rss_glb_config_cmd {
-	__be32 op_to_write;
-	__be32 retval_len16;
-	union fw_rss_glb_config {
-		struct fw_rss_glb_config_manual {
-			__be32 mode_pkd;
-			__be32 r3;
-			__be64 r4;
-			__be64 r5;
-		} manual;
-		struct fw_rss_glb_config_basicvirtual {
-			__be32 mode_pkd;
-			__be32 synmapen_to_hashtoeplitz;
-#define FW_RSS_GLB_CONFIG_CMD_SYNMAPEN      (1U << 8)
-#define FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV6 (1U << 7)
-#define FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV6 (1U << 6)
-#define FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV4 (1U << 5)
-#define FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV4 (1U << 4)
-#define FW_RSS_GLB_CONFIG_CMD_OFDMAPEN      (1U << 3)
-#define FW_RSS_GLB_CONFIG_CMD_TNLMAPEN      (1U << 2)
-#define FW_RSS_GLB_CONFIG_CMD_TNLALLLKP     (1U << 1)
-#define FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ  (1U << 0)
-			__be64 r8;
-			__be64 r9;
-		} basicvirtual;
-	} u;
-};
-
-#define FW_RSS_GLB_CONFIG_CMD_MODE(x)	((x) << 28)
-#define FW_RSS_GLB_CONFIG_CMD_MODE_GET(x) (((x) >> 28) & 0xf)
-
-#define FW_RSS_GLB_CONFIG_CMD_MODE_MANUAL	0
-#define FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL	1
-
-struct fw_rss_vi_config_cmd {
-	__be32 op_to_viid;
-#define FW_RSS_VI_CONFIG_CMD_VIID(x) ((x) << 0)
-	__be32 retval_len16;
-	union fw_rss_vi_config {
-		struct fw_rss_vi_config_manual {
-			__be64 r3;
-			__be64 r4;
-			__be64 r5;
-		} manual;
-		struct fw_rss_vi_config_basicvirtual {
-			__be32 r6;
-			__be32 defaultq_to_udpen;
-#define FW_RSS_VI_CONFIG_CMD_DEFAULTQ(x)  ((x) << 16)
-#define FW_RSS_VI_CONFIG_CMD_DEFAULTQ_GET(x) (((x) >> 16) & 0x3ff)
-#define FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN (1U << 4)
-#define FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN  (1U << 3)
-#define FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN (1U << 2)
-#define FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN  (1U << 1)
-#define FW_RSS_VI_CONFIG_CMD_UDPEN        (1U << 0)
-			__be64 r9;
-			__be64 r10;
-		} basicvirtual;
-	} u;
-};
-
-enum fw_error_type {
-	FW_ERROR_TYPE_EXCEPTION		= 0x0,
-	FW_ERROR_TYPE_HWMODULE		= 0x1,
-	FW_ERROR_TYPE_WR		= 0x2,
-	FW_ERROR_TYPE_ACL		= 0x3,
-};
-
-struct fw_error_cmd {
-	__be32 op_to_type;
-	__be32 len16_pkd;
-	union fw_error {
-		struct fw_error_exception {
-			__be32 info[6];
-		} exception;
-		struct fw_error_hwmodule {
-			__be32 regaddr;
-			__be32 regval;
-		} hwmodule;
-		struct fw_error_wr {
-			__be16 cidx;
-			__be16 pfn_vfn;
-			__be32 eqid;
-			u8 wrhdr[16];
-		} wr;
-		struct fw_error_acl {
-			__be16 cidx;
-			__be16 pfn_vfn;
-			__be32 eqid;
-			__be16 mv_pkd;
-			u8 val[6];
-			__be64 r4;
-		} acl;
-	} u;
-};
-
-struct fw_debug_cmd {
-	__be32 op_type;
-#define FW_DEBUG_CMD_TYPE_GET(x) ((x) & 0xff)
-	__be32 len16_pkd;
-	union fw_debug {
-		struct fw_debug_assert {
-			__be32 fcid;
-			__be32 line;
-			__be32 x;
-			__be32 y;
-			u8 filename_0_7[8];
-			u8 filename_8_15[8];
-			__be64 r3;
-		} assert;
-		struct fw_debug_prt {
-			__be16 dprtstridx;
-			__be16 r3[3];
-			__be32 dprtstrparam0;
-			__be32 dprtstrparam1;
-			__be32 dprtstrparam2;
-			__be32 dprtstrparam3;
-		} prt;
-	} u;
-};
-
-struct fw_hdr {
-	u8 ver;
-	u8 reserved1;
-	__be16	len512;			/* bin length in units of 512-bytes */
-	__be32	fw_ver;			/* firmware version */
-	__be32	tp_microcode_ver;
-	u8 intfver_nic;
-	u8 intfver_vnic;
-	u8 intfver_ofld;
-	u8 intfver_ri;
-	u8 intfver_iscsipdu;
-	u8 intfver_iscsi;
-	u8 intfver_fcoe;
-	u8 reserved2;
-	__be32  reserved3[27];
-};
-
-#define FW_HDR_FW_VER_MAJOR_GET(x) (((x) >> 24) & 0xff)
-#define FW_HDR_FW_VER_MINOR_GET(x) (((x) >> 16) & 0xff)
-#define FW_HDR_FW_VER_MICRO_GET(x) (((x) >> 8) & 0xff)
-#define FW_HDR_FW_VER_BUILD_GET(x) (((x) >> 0) & 0xff)
-#endif /* _T4FW_INTERFACE_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4/t4_hw.c linux-libre-3.2-gnu/drivers/net/cxgb4/t4_hw.c
--- linux-libre-3.1-gnu/drivers/net/cxgb4/t4_hw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4/t4_hw.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2856 +0,0 @@
-/*
- * This file is part of the Chelsio T4 Ethernet driver for Linux.
- *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <linux/init.h>
-#include <linux/delay.h>
-#include "cxgb4.h"
-#include "t4_regs.h"
-#include "t4fw_api.h"
-
-/**
- *	t4_wait_op_done_val - wait until an operation is completed
- *	@adapter: the adapter performing the operation
- *	@reg: the register to check for completion
- *	@mask: a single-bit field within @reg that indicates completion
- *	@polarity: the value of the field when the operation is completed
- *	@attempts: number of check iterations
- *	@delay: delay in usecs between iterations
- *	@valp: where to store the value of the register at completion time
- *
- *	Wait until an operation is completed by checking a bit in a register
- *	up to @attempts times.  If @valp is not NULL the value of the register
- *	at the time it indicated completion is stored there.  Returns 0 if the
- *	operation completes and	-EAGAIN	otherwise.
- */
-static int t4_wait_op_done_val(struct adapter *adapter, int reg, u32 mask,
-			       int polarity, int attempts, int delay, u32 *valp)
-{
-	while (1) {
-		u32 val = t4_read_reg(adapter, reg);
-
-		if (!!(val & mask) == polarity) {
-			if (valp)
-				*valp = val;
-			return 0;
-		}
-		if (--attempts == 0)
-			return -EAGAIN;
-		if (delay)
-			udelay(delay);
-	}
-}
-
-static inline int t4_wait_op_done(struct adapter *adapter, int reg, u32 mask,
-				  int polarity, int attempts, int delay)
-{
-	return t4_wait_op_done_val(adapter, reg, mask, polarity, attempts,
-				   delay, NULL);
-}
-
-/**
- *	t4_set_reg_field - set a register field to a value
- *	@adapter: the adapter to program
- *	@addr: the register address
- *	@mask: specifies the portion of the register to modify
- *	@val: the new value for the register field
- *
- *	Sets a register field specified by the supplied mask to the
- *	given value.
- */
-void t4_set_reg_field(struct adapter *adapter, unsigned int addr, u32 mask,
-		      u32 val)
-{
-	u32 v = t4_read_reg(adapter, addr) & ~mask;
-
-	t4_write_reg(adapter, addr, v | val);
-	(void) t4_read_reg(adapter, addr);      /* flush */
-}
-
-/**
- *	t4_read_indirect - read indirectly addressed registers
- *	@adap: the adapter
- *	@addr_reg: register holding the indirect address
- *	@data_reg: register holding the value of the indirect register
- *	@vals: where the read register values are stored
- *	@nregs: how many indirect registers to read
- *	@start_idx: index of first indirect register to read
- *
- *	Reads registers that are accessed indirectly through an address/data
- *	register pair.
- */
-static void t4_read_indirect(struct adapter *adap, unsigned int addr_reg,
-			     unsigned int data_reg, u32 *vals,
-			     unsigned int nregs, unsigned int start_idx)
-{
-	while (nregs--) {
-		t4_write_reg(adap, addr_reg, start_idx);
-		*vals++ = t4_read_reg(adap, data_reg);
-		start_idx++;
-	}
-}
-
-/*
- * Get the reply to a mailbox command and store it in @rpl in big-endian order.
- */
-static void get_mbox_rpl(struct adapter *adap, __be64 *rpl, int nflit,
-			 u32 mbox_addr)
-{
-	for ( ; nflit; nflit--, mbox_addr += 8)
-		*rpl++ = cpu_to_be64(t4_read_reg64(adap, mbox_addr));
-}
-
-/*
- * Handle a FW assertion reported in a mailbox.
- */
-static void fw_asrt(struct adapter *adap, u32 mbox_addr)
-{
-	struct fw_debug_cmd asrt;
-
-	get_mbox_rpl(adap, (__be64 *)&asrt, sizeof(asrt) / 8, mbox_addr);
-	dev_alert(adap->pdev_dev,
-		  "FW assertion at %.16s:%u, val0 %#x, val1 %#x\n",
-		  asrt.u.assert.filename_0_7, ntohl(asrt.u.assert.line),
-		  ntohl(asrt.u.assert.x), ntohl(asrt.u.assert.y));
-}
-
-static void dump_mbox(struct adapter *adap, int mbox, u32 data_reg)
-{
-	dev_err(adap->pdev_dev,
-		"mbox %d: %llx %llx %llx %llx %llx %llx %llx %llx\n", mbox,
-		(unsigned long long)t4_read_reg64(adap, data_reg),
-		(unsigned long long)t4_read_reg64(adap, data_reg + 8),
-		(unsigned long long)t4_read_reg64(adap, data_reg + 16),
-		(unsigned long long)t4_read_reg64(adap, data_reg + 24),
-		(unsigned long long)t4_read_reg64(adap, data_reg + 32),
-		(unsigned long long)t4_read_reg64(adap, data_reg + 40),
-		(unsigned long long)t4_read_reg64(adap, data_reg + 48),
-		(unsigned long long)t4_read_reg64(adap, data_reg + 56));
-}
-
-/**
- *	t4_wr_mbox_meat - send a command to FW through the given mailbox
- *	@adap: the adapter
- *	@mbox: index of the mailbox to use
- *	@cmd: the command to write
- *	@size: command length in bytes
- *	@rpl: where to optionally store the reply
- *	@sleep_ok: if true we may sleep while awaiting command completion
- *
- *	Sends the given command to FW through the selected mailbox and waits
- *	for the FW to execute the command.  If @rpl is not %NULL it is used to
- *	store the FW's reply to the command.  The command and its optional
- *	reply are of the same length.  FW can take up to %FW_CMD_MAX_TIMEOUT ms
- *	to respond.  @sleep_ok determines whether we may sleep while awaiting
- *	the response.  If sleeping is allowed we use progressive backoff
- *	otherwise we spin.
- *
- *	The return value is 0 on success or a negative errno on failure.  A
- *	failure can happen either because we are not able to execute the
- *	command or FW executes it but signals an error.  In the latter case
- *	the return value is the error code indicated by FW (negated).
- */
-int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
-		    void *rpl, bool sleep_ok)
-{
-	static const int delay[] = {
-		1, 1, 3, 5, 10, 10, 20, 50, 100, 200
-	};
-
-	u32 v;
-	u64 res;
-	int i, ms, delay_idx;
-	const __be64 *p = cmd;
-	u32 data_reg = PF_REG(mbox, CIM_PF_MAILBOX_DATA);
-	u32 ctl_reg = PF_REG(mbox, CIM_PF_MAILBOX_CTRL);
-
-	if ((size & 15) || size > MBOX_LEN)
-		return -EINVAL;
-
-	/*
-	 * If the device is off-line, as in EEH, commands will time out.
-	 * Fail them early so we don't waste time waiting.
-	 */
-	if (adap->pdev->error_state != pci_channel_io_normal)
-		return -EIO;
-
-	v = MBOWNER_GET(t4_read_reg(adap, ctl_reg));
-	for (i = 0; v == MBOX_OWNER_NONE && i < 3; i++)
-		v = MBOWNER_GET(t4_read_reg(adap, ctl_reg));
-
-	if (v != MBOX_OWNER_DRV)
-		return v ? -EBUSY : -ETIMEDOUT;
-
-	for (i = 0; i < size; i += 8)
-		t4_write_reg64(adap, data_reg + i, be64_to_cpu(*p++));
-
-	t4_write_reg(adap, ctl_reg, MBMSGVALID | MBOWNER(MBOX_OWNER_FW));
-	t4_read_reg(adap, ctl_reg);          /* flush write */
-
-	delay_idx = 0;
-	ms = delay[0];
-
-	for (i = 0; i < FW_CMD_MAX_TIMEOUT; i += ms) {
-		if (sleep_ok) {
-			ms = delay[delay_idx];  /* last element may repeat */
-			if (delay_idx < ARRAY_SIZE(delay) - 1)
-				delay_idx++;
-			msleep(ms);
-		} else
-			mdelay(ms);
-
-		v = t4_read_reg(adap, ctl_reg);
-		if (MBOWNER_GET(v) == MBOX_OWNER_DRV) {
-			if (!(v & MBMSGVALID)) {
-				t4_write_reg(adap, ctl_reg, 0);
-				continue;
-			}
-
-			res = t4_read_reg64(adap, data_reg);
-			if (FW_CMD_OP_GET(res >> 32) == FW_DEBUG_CMD) {
-				fw_asrt(adap, data_reg);
-				res = FW_CMD_RETVAL(EIO);
-			} else if (rpl)
-				get_mbox_rpl(adap, rpl, size / 8, data_reg);
-
-			if (FW_CMD_RETVAL_GET((int)res))
-				dump_mbox(adap, mbox, data_reg);
-			t4_write_reg(adap, ctl_reg, 0);
-			return -FW_CMD_RETVAL_GET((int)res);
-		}
-	}
-
-	dump_mbox(adap, mbox, data_reg);
-	dev_err(adap->pdev_dev, "command %#x in mailbox %d timed out\n",
-		*(const u8 *)cmd, mbox);
-	return -ETIMEDOUT;
-}
-
-/**
- *	t4_mc_read - read from MC through backdoor accesses
- *	@adap: the adapter
- *	@addr: address of first byte requested
- *	@data: 64 bytes of data containing the requested address
- *	@ecc: where to store the corresponding 64-bit ECC word
- *
- *	Read 64 bytes of data from MC starting at a 64-byte-aligned address
- *	that covers the requested address @addr.  If @parity is not %NULL it
- *	is assigned the 64-bit ECC word for the read data.
- */
-int t4_mc_read(struct adapter *adap, u32 addr, __be32 *data, u64 *ecc)
-{
-	int i;
-
-	if (t4_read_reg(adap, MC_BIST_CMD) & START_BIST)
-		return -EBUSY;
-	t4_write_reg(adap, MC_BIST_CMD_ADDR, addr & ~0x3fU);
-	t4_write_reg(adap, MC_BIST_CMD_LEN, 64);
-	t4_write_reg(adap, MC_BIST_DATA_PATTERN, 0xc);
-	t4_write_reg(adap, MC_BIST_CMD, BIST_OPCODE(1) | START_BIST |
-		     BIST_CMD_GAP(1));
-	i = t4_wait_op_done(adap, MC_BIST_CMD, START_BIST, 0, 10, 1);
-	if (i)
-		return i;
-
-#define MC_DATA(i) MC_BIST_STATUS_REG(MC_BIST_STATUS_RDATA, i)
-
-	for (i = 15; i >= 0; i--)
-		*data++ = htonl(t4_read_reg(adap, MC_DATA(i)));
-	if (ecc)
-		*ecc = t4_read_reg64(adap, MC_DATA(16));
-#undef MC_DATA
-	return 0;
-}
-
-/**
- *	t4_edc_read - read from EDC through backdoor accesses
- *	@adap: the adapter
- *	@idx: which EDC to access
- *	@addr: address of first byte requested
- *	@data: 64 bytes of data containing the requested address
- *	@ecc: where to store the corresponding 64-bit ECC word
- *
- *	Read 64 bytes of data from EDC starting at a 64-byte-aligned address
- *	that covers the requested address @addr.  If @parity is not %NULL it
- *	is assigned the 64-bit ECC word for the read data.
- */
-int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
-{
-	int i;
-
-	idx *= EDC_STRIDE;
-	if (t4_read_reg(adap, EDC_BIST_CMD + idx) & START_BIST)
-		return -EBUSY;
-	t4_write_reg(adap, EDC_BIST_CMD_ADDR + idx, addr & ~0x3fU);
-	t4_write_reg(adap, EDC_BIST_CMD_LEN + idx, 64);
-	t4_write_reg(adap, EDC_BIST_DATA_PATTERN + idx, 0xc);
-	t4_write_reg(adap, EDC_BIST_CMD + idx,
-		     BIST_OPCODE(1) | BIST_CMD_GAP(1) | START_BIST);
-	i = t4_wait_op_done(adap, EDC_BIST_CMD + idx, START_BIST, 0, 10, 1);
-	if (i)
-		return i;
-
-#define EDC_DATA(i) (EDC_BIST_STATUS_REG(EDC_BIST_STATUS_RDATA, i) + idx)
-
-	for (i = 15; i >= 0; i--)
-		*data++ = htonl(t4_read_reg(adap, EDC_DATA(i)));
-	if (ecc)
-		*ecc = t4_read_reg64(adap, EDC_DATA(16));
-#undef EDC_DATA
-	return 0;
-}
-
-#define EEPROM_STAT_ADDR   0x7bfc
-#define VPD_BASE           0
-#define VPD_LEN            512
-
-/**
- *	t4_seeprom_wp - enable/disable EEPROM write protection
- *	@adapter: the adapter
- *	@enable: whether to enable or disable write protection
- *
- *	Enables or disables write protection on the serial EEPROM.
- */
-int t4_seeprom_wp(struct adapter *adapter, bool enable)
-{
-	unsigned int v = enable ? 0xc : 0;
-	int ret = pci_write_vpd(adapter->pdev, EEPROM_STAT_ADDR, 4, &v);
-	return ret < 0 ? ret : 0;
-}
-
-/**
- *	get_vpd_params - read VPD parameters from VPD EEPROM
- *	@adapter: adapter to read
- *	@p: where to store the parameters
- *
- *	Reads card parameters stored in VPD EEPROM.
- */
-static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
-{
-	int i, ret;
-	int ec, sn;
-	u8 vpd[VPD_LEN], csum;
-	unsigned int vpdr_len, kw_offset, id_len;
-
-	ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(vpd), vpd);
-	if (ret < 0)
-		return ret;
-
-	if (vpd[0] != PCI_VPD_LRDT_ID_STRING) {
-		dev_err(adapter->pdev_dev, "missing VPD ID string\n");
-		return -EINVAL;
-	}
-
-	id_len = pci_vpd_lrdt_size(vpd);
-	if (id_len > ID_LEN)
-		id_len = ID_LEN;
-
-	i = pci_vpd_find_tag(vpd, 0, VPD_LEN, PCI_VPD_LRDT_RO_DATA);
-	if (i < 0) {
-		dev_err(adapter->pdev_dev, "missing VPD-R section\n");
-		return -EINVAL;
-	}
-
-	vpdr_len = pci_vpd_lrdt_size(&vpd[i]);
-	kw_offset = i + PCI_VPD_LRDT_TAG_SIZE;
-	if (vpdr_len + kw_offset > VPD_LEN) {
-		dev_err(adapter->pdev_dev, "bad VPD-R length %u\n", vpdr_len);
-		return -EINVAL;
-	}
-
-#define FIND_VPD_KW(var, name) do { \
-	var = pci_vpd_find_info_keyword(vpd, kw_offset, vpdr_len, name); \
-	if (var < 0) { \
-		dev_err(adapter->pdev_dev, "missing VPD keyword " name "\n"); \
-		return -EINVAL; \
-	} \
-	var += PCI_VPD_INFO_FLD_HDR_SIZE; \
-} while (0)
-
-	FIND_VPD_KW(i, "RV");
-	for (csum = 0; i >= 0; i--)
-		csum += vpd[i];
-
-	if (csum) {
-		dev_err(adapter->pdev_dev,
-			"corrupted VPD EEPROM, actual csum %u\n", csum);
-		return -EINVAL;
-	}
-
-	FIND_VPD_KW(ec, "EC");
-	FIND_VPD_KW(sn, "SN");
-#undef FIND_VPD_KW
-
-	memcpy(p->id, vpd + PCI_VPD_LRDT_TAG_SIZE, id_len);
-	strim(p->id);
-	memcpy(p->ec, vpd + ec, EC_LEN);
-	strim(p->ec);
-	i = pci_vpd_info_field_size(vpd + sn - PCI_VPD_INFO_FLD_HDR_SIZE);
-	memcpy(p->sn, vpd + sn, min(i, SERNUM_LEN));
-	strim(p->sn);
-	return 0;
-}
-
-/* serial flash and firmware constants */
-enum {
-	SF_ATTEMPTS = 10,             /* max retries for SF operations */
-
-	/* flash command opcodes */
-	SF_PROG_PAGE    = 2,          /* program page */
-	SF_WR_DISABLE   = 4,          /* disable writes */
-	SF_RD_STATUS    = 5,          /* read status register */
-	SF_WR_ENABLE    = 6,          /* enable writes */
-	SF_RD_DATA_FAST = 0xb,        /* read flash */
-	SF_RD_ID        = 0x9f,       /* read ID */
-	SF_ERASE_SECTOR = 0xd8,       /* erase sector */
-
-	FW_MAX_SIZE = 512 * 1024,
-};
-
-/**
- *	sf1_read - read data from the serial flash
- *	@adapter: the adapter
- *	@byte_cnt: number of bytes to read
- *	@cont: whether another operation will be chained
- *	@lock: whether to lock SF for PL access only
- *	@valp: where to store the read data
- *
- *	Reads up to 4 bytes of data from the serial flash.  The location of
- *	the read needs to be specified prior to calling this by issuing the
- *	appropriate commands to the serial flash.
- */
-static int sf1_read(struct adapter *adapter, unsigned int byte_cnt, int cont,
-		    int lock, u32 *valp)
-{
-	int ret;
-
-	if (!byte_cnt || byte_cnt > 4)
-		return -EINVAL;
-	if (t4_read_reg(adapter, SF_OP) & BUSY)
-		return -EBUSY;
-	cont = cont ? SF_CONT : 0;
-	lock = lock ? SF_LOCK : 0;
-	t4_write_reg(adapter, SF_OP, lock | cont | BYTECNT(byte_cnt - 1));
-	ret = t4_wait_op_done(adapter, SF_OP, BUSY, 0, SF_ATTEMPTS, 5);
-	if (!ret)
-		*valp = t4_read_reg(adapter, SF_DATA);
-	return ret;
-}
-
-/**
- *	sf1_write - write data to the serial flash
- *	@adapter: the adapter
- *	@byte_cnt: number of bytes to write
- *	@cont: whether another operation will be chained
- *	@lock: whether to lock SF for PL access only
- *	@val: value to write
- *
- *	Writes up to 4 bytes of data to the serial flash.  The location of
- *	the write needs to be specified prior to calling this by issuing the
- *	appropriate commands to the serial flash.
- */
-static int sf1_write(struct adapter *adapter, unsigned int byte_cnt, int cont,
-		     int lock, u32 val)
-{
-	if (!byte_cnt || byte_cnt > 4)
-		return -EINVAL;
-	if (t4_read_reg(adapter, SF_OP) & BUSY)
-		return -EBUSY;
-	cont = cont ? SF_CONT : 0;
-	lock = lock ? SF_LOCK : 0;
-	t4_write_reg(adapter, SF_DATA, val);
-	t4_write_reg(adapter, SF_OP, lock |
-		     cont | BYTECNT(byte_cnt - 1) | OP_WR);
-	return t4_wait_op_done(adapter, SF_OP, BUSY, 0, SF_ATTEMPTS, 5);
-}
-
-/**
- *	flash_wait_op - wait for a flash operation to complete
- *	@adapter: the adapter
- *	@attempts: max number of polls of the status register
- *	@delay: delay between polls in ms
- *
- *	Wait for a flash operation to complete by polling the status register.
- */
-static int flash_wait_op(struct adapter *adapter, int attempts, int delay)
-{
-	int ret;
-	u32 status;
-
-	while (1) {
-		if ((ret = sf1_write(adapter, 1, 1, 1, SF_RD_STATUS)) != 0 ||
-		    (ret = sf1_read(adapter, 1, 0, 1, &status)) != 0)
-			return ret;
-		if (!(status & 1))
-			return 0;
-		if (--attempts == 0)
-			return -EAGAIN;
-		if (delay)
-			msleep(delay);
-	}
-}
-
-/**
- *	t4_read_flash - read words from serial flash
- *	@adapter: the adapter
- *	@addr: the start address for the read
- *	@nwords: how many 32-bit words to read
- *	@data: where to store the read data
- *	@byte_oriented: whether to store data as bytes or as words
- *
- *	Read the specified number of 32-bit words from the serial flash.
- *	If @byte_oriented is set the read data is stored as a byte array
- *	(i.e., big-endian), otherwise as 32-bit words in the platform's
- *	natural endianess.
- */
-static int t4_read_flash(struct adapter *adapter, unsigned int addr,
-			 unsigned int nwords, u32 *data, int byte_oriented)
-{
-	int ret;
-
-	if (addr + nwords * sizeof(u32) > adapter->params.sf_size || (addr & 3))
-		return -EINVAL;
-
-	addr = swab32(addr) | SF_RD_DATA_FAST;
-
-	if ((ret = sf1_write(adapter, 4, 1, 0, addr)) != 0 ||
-	    (ret = sf1_read(adapter, 1, 1, 0, data)) != 0)
-		return ret;
-
-	for ( ; nwords; nwords--, data++) {
-		ret = sf1_read(adapter, 4, nwords > 1, nwords == 1, data);
-		if (nwords == 1)
-			t4_write_reg(adapter, SF_OP, 0);    /* unlock SF */
-		if (ret)
-			return ret;
-		if (byte_oriented)
-			*data = htonl(*data);
-	}
-	return 0;
-}
-
-/**
- *	t4_write_flash - write up to a page of data to the serial flash
- *	@adapter: the adapter
- *	@addr: the start address to write
- *	@n: length of data to write in bytes
- *	@data: the data to write
- *
- *	Writes up to a page of data (256 bytes) to the serial flash starting
- *	at the given address.  All the data must be written to the same page.
- */
-static int t4_write_flash(struct adapter *adapter, unsigned int addr,
-			  unsigned int n, const u8 *data)
-{
-	int ret;
-	u32 buf[64];
-	unsigned int i, c, left, val, offset = addr & 0xff;
-
-	if (addr >= adapter->params.sf_size || offset + n > SF_PAGE_SIZE)
-		return -EINVAL;
-
-	val = swab32(addr) | SF_PROG_PAGE;
-
-	if ((ret = sf1_write(adapter, 1, 0, 1, SF_WR_ENABLE)) != 0 ||
-	    (ret = sf1_write(adapter, 4, 1, 1, val)) != 0)
-		goto unlock;
-
-	for (left = n; left; left -= c) {
-		c = min(left, 4U);
-		for (val = 0, i = 0; i < c; ++i)
-			val = (val << 8) + *data++;
-
-		ret = sf1_write(adapter, c, c != left, 1, val);
-		if (ret)
-			goto unlock;
-	}
-	ret = flash_wait_op(adapter, 8, 1);
-	if (ret)
-		goto unlock;
-
-	t4_write_reg(adapter, SF_OP, 0);    /* unlock SF */
-
-	/* Read the page to verify the write succeeded */
-	ret = t4_read_flash(adapter, addr & ~0xff, ARRAY_SIZE(buf), buf, 1);
-	if (ret)
-		return ret;
-
-	if (memcmp(data - n, (u8 *)buf + offset, n)) {
-		dev_err(adapter->pdev_dev,
-			"failed to correctly write the flash page at %#x\n",
-			addr);
-		return -EIO;
-	}
-	return 0;
-
-unlock:
-	t4_write_reg(adapter, SF_OP, 0);    /* unlock SF */
-	return ret;
-}
-
-/**
- *	get_fw_version - read the firmware version
- *	@adapter: the adapter
- *	@vers: where to place the version
- *
- *	Reads the FW version from flash.
- */
-static int get_fw_version(struct adapter *adapter, u32 *vers)
-{
-	return t4_read_flash(adapter, adapter->params.sf_fw_start +
-			     offsetof(struct fw_hdr, fw_ver), 1, vers, 0);
-}
-
-/**
- *	get_tp_version - read the TP microcode version
- *	@adapter: the adapter
- *	@vers: where to place the version
- *
- *	Reads the TP microcode version from flash.
- */
-static int get_tp_version(struct adapter *adapter, u32 *vers)
-{
-	return t4_read_flash(adapter, adapter->params.sf_fw_start +
-			     offsetof(struct fw_hdr, tp_microcode_ver),
-			     1, vers, 0);
-}
-
-/**
- *	t4_check_fw_version - check if the FW is compatible with this driver
- *	@adapter: the adapter
- *
- *	Checks if an adapter's FW is compatible with the driver.  Returns 0
- *	if there's exact match, a negative error if the version could not be
- *	read or there's a major version mismatch, and a positive value if the
- *	expected major version is found but there's a minor version mismatch.
- */
-int t4_check_fw_version(struct adapter *adapter)
-{
-	u32 api_vers[2];
-	int ret, major, minor, micro;
-
-	ret = get_fw_version(adapter, &adapter->params.fw_vers);
-	if (!ret)
-		ret = get_tp_version(adapter, &adapter->params.tp_vers);
-	if (!ret)
-		ret = t4_read_flash(adapter, adapter->params.sf_fw_start +
-				    offsetof(struct fw_hdr, intfver_nic),
-				    2, api_vers, 1);
-	if (ret)
-		return ret;
-
-	major = FW_HDR_FW_VER_MAJOR_GET(adapter->params.fw_vers);
-	minor = FW_HDR_FW_VER_MINOR_GET(adapter->params.fw_vers);
-	micro = FW_HDR_FW_VER_MICRO_GET(adapter->params.fw_vers);
-	memcpy(adapter->params.api_vers, api_vers,
-	       sizeof(adapter->params.api_vers));
-
-	if (major != FW_VERSION_MAJOR) {            /* major mismatch - fail */
-		dev_err(adapter->pdev_dev,
-			"card FW has major version %u, driver wants %u\n",
-			major, FW_VERSION_MAJOR);
-		return -EINVAL;
-	}
-
-	if (minor == FW_VERSION_MINOR && micro == FW_VERSION_MICRO)
-		return 0;                                   /* perfect match */
-
-	/* Minor/micro version mismatch.  Report it but often it's OK. */
-	return 1;
-}
-
-/**
- *	t4_flash_erase_sectors - erase a range of flash sectors
- *	@adapter: the adapter
- *	@start: the first sector to erase
- *	@end: the last sector to erase
- *
- *	Erases the sectors in the given inclusive range.
- */
-static int t4_flash_erase_sectors(struct adapter *adapter, int start, int end)
-{
-	int ret = 0;
-
-	while (start <= end) {
-		if ((ret = sf1_write(adapter, 1, 0, 1, SF_WR_ENABLE)) != 0 ||
-		    (ret = sf1_write(adapter, 4, 0, 1,
-				     SF_ERASE_SECTOR | (start << 8))) != 0 ||
-		    (ret = flash_wait_op(adapter, 14, 500)) != 0) {
-			dev_err(adapter->pdev_dev,
-				"erase of flash sector %d failed, error %d\n",
-				start, ret);
-			break;
-		}
-		start++;
-	}
-	t4_write_reg(adapter, SF_OP, 0);    /* unlock SF */
-	return ret;
-}
-
-/**
- *	t4_load_fw - download firmware
- *	@adap: the adapter
- *	@fw_data: the firmware image to write
- *	@size: image size
- *
- *	Write the supplied firmware image to the card's serial flash.
- */
-int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size)
-{
-	u32 csum;
-	int ret, addr;
-	unsigned int i;
-	u8 first_page[SF_PAGE_SIZE];
-	const u32 *p = (const u32 *)fw_data;
-	const struct fw_hdr *hdr = (const struct fw_hdr *)fw_data;
-	unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
-	unsigned int fw_img_start = adap->params.sf_fw_start;
-	unsigned int fw_start_sec = fw_img_start / sf_sec_size;
-
-	if (!size) {
-		dev_err(adap->pdev_dev, "FW image has no data\n");
-		return -EINVAL;
-	}
-	if (size & 511) {
-		dev_err(adap->pdev_dev,
-			"FW image size not multiple of 512 bytes\n");
-		return -EINVAL;
-	}
-	if (ntohs(hdr->len512) * 512 != size) {
-		dev_err(adap->pdev_dev,
-			"FW image size differs from size in FW header\n");
-		return -EINVAL;
-	}
-	if (size > FW_MAX_SIZE) {
-		dev_err(adap->pdev_dev, "FW image too large, max is %u bytes\n",
-			FW_MAX_SIZE);
-		return -EFBIG;
-	}
-
-	for (csum = 0, i = 0; i < size / sizeof(csum); i++)
-		csum += ntohl(p[i]);
-
-	if (csum != 0xffffffff) {
-		dev_err(adap->pdev_dev,
-			"corrupted firmware image, checksum %#x\n", csum);
-		return -EINVAL;
-	}
-
-	i = DIV_ROUND_UP(size, sf_sec_size);        /* # of sectors spanned */
-	ret = t4_flash_erase_sectors(adap, fw_start_sec, fw_start_sec + i - 1);
-	if (ret)
-		goto out;
-
-	/*
-	 * We write the correct version at the end so the driver can see a bad
-	 * version if the FW write fails.  Start by writing a copy of the
-	 * first page with a bad version.
-	 */
-	memcpy(first_page, fw_data, SF_PAGE_SIZE);
-	((struct fw_hdr *)first_page)->fw_ver = htonl(0xffffffff);
-	ret = t4_write_flash(adap, fw_img_start, SF_PAGE_SIZE, first_page);
-	if (ret)
-		goto out;
-
-	addr = fw_img_start;
-	for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) {
-		addr += SF_PAGE_SIZE;
-		fw_data += SF_PAGE_SIZE;
-		ret = t4_write_flash(adap, addr, SF_PAGE_SIZE, fw_data);
-		if (ret)
-			goto out;
-	}
-
-	ret = t4_write_flash(adap,
-			     fw_img_start + offsetof(struct fw_hdr, fw_ver),
-			     sizeof(hdr->fw_ver), (const u8 *)&hdr->fw_ver);
-out:
-	if (ret)
-		dev_err(adap->pdev_dev, "firmware download failed, error %d\n",
-			ret);
-	return ret;
-}
-
-#define ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\
-		     FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_ANEG)
-
-/**
- *	t4_link_start - apply link configuration to MAC/PHY
- *	@phy: the PHY to setup
- *	@mac: the MAC to setup
- *	@lc: the requested link configuration
- *
- *	Set up a port's MAC and PHY according to a desired link configuration.
- *	- If the PHY can auto-negotiate first decide what to advertise, then
- *	  enable/disable auto-negotiation as desired, and reset.
- *	- If the PHY does not auto-negotiate just reset it.
- *	- If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
- *	  otherwise do it later based on the outcome of auto-negotiation.
- */
-int t4_link_start(struct adapter *adap, unsigned int mbox, unsigned int port,
-		  struct link_config *lc)
-{
-	struct fw_port_cmd c;
-	unsigned int fc = 0, mdi = FW_PORT_MDI(FW_PORT_MDI_AUTO);
-
-	lc->link_ok = 0;
-	if (lc->requested_fc & PAUSE_RX)
-		fc |= FW_PORT_CAP_FC_RX;
-	if (lc->requested_fc & PAUSE_TX)
-		fc |= FW_PORT_CAP_FC_TX;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_portid = htonl(FW_CMD_OP(FW_PORT_CMD) | FW_CMD_REQUEST |
-			       FW_CMD_EXEC | FW_PORT_CMD_PORTID(port));
-	c.action_to_len16 = htonl(FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) |
-				  FW_LEN16(c));
-
-	if (!(lc->supported & FW_PORT_CAP_ANEG)) {
-		c.u.l1cfg.rcap = htonl((lc->supported & ADVERT_MASK) | fc);
-		lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
-	} else if (lc->autoneg == AUTONEG_DISABLE) {
-		c.u.l1cfg.rcap = htonl(lc->requested_speed | fc | mdi);
-		lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
-	} else
-		c.u.l1cfg.rcap = htonl(lc->advertising | fc | mdi);
-
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-}
-
-/**
- *	t4_restart_aneg - restart autonegotiation
- *	@adap: the adapter
- *	@mbox: mbox to use for the FW command
- *	@port: the port id
- *
- *	Restarts autonegotiation for the selected port.
- */
-int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port)
-{
-	struct fw_port_cmd c;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_portid = htonl(FW_CMD_OP(FW_PORT_CMD) | FW_CMD_REQUEST |
-			       FW_CMD_EXEC | FW_PORT_CMD_PORTID(port));
-	c.action_to_len16 = htonl(FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) |
-				  FW_LEN16(c));
-	c.u.l1cfg.rcap = htonl(FW_PORT_CAP_ANEG);
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-}
-
-struct intr_info {
-	unsigned int mask;       /* bits to check in interrupt status */
-	const char *msg;         /* message to print or NULL */
-	short stat_idx;          /* stat counter to increment or -1 */
-	unsigned short fatal;    /* whether the condition reported is fatal */
-};
-
-/**
- *	t4_handle_intr_status - table driven interrupt handler
- *	@adapter: the adapter that generated the interrupt
- *	@reg: the interrupt status register to process
- *	@acts: table of interrupt actions
- *
- *	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 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.
- */
-static int t4_handle_intr_status(struct adapter *adapter, unsigned int reg,
-				 const struct intr_info *acts)
-{
-	int fatal = 0;
-	unsigned int mask = 0;
-	unsigned int status = t4_read_reg(adapter, reg);
-
-	for ( ; acts->mask; ++acts) {
-		if (!(status & acts->mask))
-			continue;
-		if (acts->fatal) {
-			fatal++;
-			dev_alert(adapter->pdev_dev, "%s (0x%x)\n", acts->msg,
-				  status & acts->mask);
-		} else if (acts->msg && printk_ratelimit())
-			dev_warn(adapter->pdev_dev, "%s (0x%x)\n", acts->msg,
-				 status & acts->mask);
-		mask |= acts->mask;
-	}
-	status &= mask;
-	if (status)                           /* clear processed interrupts */
-		t4_write_reg(adapter, reg, status);
-	return fatal;
-}
-
-/*
- * Interrupt handler for the PCIE module.
- */
-static void pcie_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info sysbus_intr_info[] = {
-		{ RNPP, "RXNP array parity error", -1, 1 },
-		{ RPCP, "RXPC array parity error", -1, 1 },
-		{ RCIP, "RXCIF array parity error", -1, 1 },
-		{ RCCP, "Rx completions control array parity error", -1, 1 },
-		{ RFTP, "RXFT array parity error", -1, 1 },
-		{ 0 }
-	};
-	static const struct intr_info pcie_port_intr_info[] = {
-		{ TPCP, "TXPC array parity error", -1, 1 },
-		{ TNPP, "TXNP array parity error", -1, 1 },
-		{ TFTP, "TXFT array parity error", -1, 1 },
-		{ TCAP, "TXCA array parity error", -1, 1 },
-		{ TCIP, "TXCIF array parity error", -1, 1 },
-		{ RCAP, "RXCA array parity error", -1, 1 },
-		{ OTDD, "outbound request TLP discarded", -1, 1 },
-		{ RDPE, "Rx data parity error", -1, 1 },
-		{ TDUE, "Tx uncorrectable data error", -1, 1 },
-		{ 0 }
-	};
-	static const struct intr_info pcie_intr_info[] = {
-		{ MSIADDRLPERR, "MSI AddrL parity error", -1, 1 },
-		{ MSIADDRHPERR, "MSI AddrH parity error", -1, 1 },
-		{ MSIDATAPERR, "MSI data parity error", -1, 1 },
-		{ MSIXADDRLPERR, "MSI-X AddrL parity error", -1, 1 },
-		{ MSIXADDRHPERR, "MSI-X AddrH parity error", -1, 1 },
-		{ MSIXDATAPERR, "MSI-X data parity error", -1, 1 },
-		{ MSIXDIPERR, "MSI-X DI parity error", -1, 1 },
-		{ PIOCPLPERR, "PCI PIO completion FIFO parity error", -1, 1 },
-		{ PIOREQPERR, "PCI PIO request FIFO parity error", -1, 1 },
-		{ TARTAGPERR, "PCI PCI target tag FIFO parity error", -1, 1 },
-		{ CCNTPERR, "PCI CMD channel count parity error", -1, 1 },
-		{ CREQPERR, "PCI CMD channel request parity error", -1, 1 },
-		{ CRSPPERR, "PCI CMD channel response parity error", -1, 1 },
-		{ DCNTPERR, "PCI DMA channel count parity error", -1, 1 },
-		{ DREQPERR, "PCI DMA channel request parity error", -1, 1 },
-		{ DRSPPERR, "PCI DMA channel response parity error", -1, 1 },
-		{ HCNTPERR, "PCI HMA channel count parity error", -1, 1 },
-		{ HREQPERR, "PCI HMA channel request parity error", -1, 1 },
-		{ HRSPPERR, "PCI HMA channel response parity error", -1, 1 },
-		{ CFGSNPPERR, "PCI config snoop FIFO parity error", -1, 1 },
-		{ FIDPERR, "PCI FID parity error", -1, 1 },
-		{ INTXCLRPERR, "PCI INTx clear parity error", -1, 1 },
-		{ MATAGPERR, "PCI MA tag parity error", -1, 1 },
-		{ PIOTAGPERR, "PCI PIO tag parity error", -1, 1 },
-		{ RXCPLPERR, "PCI Rx completion parity error", -1, 1 },
-		{ RXWRPERR, "PCI Rx write parity error", -1, 1 },
-		{ RPLPERR, "PCI replay buffer parity error", -1, 1 },
-		{ PCIESINT, "PCI core secondary fault", -1, 1 },
-		{ PCIEPINT, "PCI core primary fault", -1, 1 },
-		{ UNXSPLCPLERR, "PCI unexpected split completion error", -1, 0 },
-		{ 0 }
-	};
-
-	int fat;
-
-	fat = t4_handle_intr_status(adapter,
-				    PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
-				    sysbus_intr_info) +
-	      t4_handle_intr_status(adapter,
-				    PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
-				    pcie_port_intr_info) +
-	      t4_handle_intr_status(adapter, PCIE_INT_CAUSE, pcie_intr_info);
-	if (fat)
-		t4_fatal_err(adapter);
-}
-
-/*
- * TP interrupt handler.
- */
-static void tp_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info tp_intr_info[] = {
-		{ 0x3fffffff, "TP parity error", -1, 1 },
-		{ FLMTXFLSTEMPTY, "TP out of Tx pages", -1, 1 },
-		{ 0 }
-	};
-
-	if (t4_handle_intr_status(adapter, TP_INT_CAUSE, tp_intr_info))
-		t4_fatal_err(adapter);
-}
-
-/*
- * SGE interrupt handler.
- */
-static void sge_intr_handler(struct adapter *adapter)
-{
-	u64 v;
-
-	static const struct intr_info sge_intr_info[] = {
-		{ ERR_CPL_EXCEED_IQE_SIZE,
-		  "SGE received CPL exceeding IQE size", -1, 1 },
-		{ ERR_INVALID_CIDX_INC,
-		  "SGE GTS CIDX increment too large", -1, 0 },
-		{ ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 },
-		{ ERR_DROPPED_DB, "SGE doorbell dropped", -1, 0 },
-		{ ERR_DATA_CPL_ON_HIGH_QID1 | ERR_DATA_CPL_ON_HIGH_QID0,
-		  "SGE IQID > 1023 received CPL for FL", -1, 0 },
-		{ ERR_BAD_DB_PIDX3, "SGE DBP 3 pidx increment too large", -1,
-		  0 },
-		{ ERR_BAD_DB_PIDX2, "SGE DBP 2 pidx increment too large", -1,
-		  0 },
-		{ ERR_BAD_DB_PIDX1, "SGE DBP 1 pidx increment too large", -1,
-		  0 },
-		{ ERR_BAD_DB_PIDX0, "SGE DBP 0 pidx increment too large", -1,
-		  0 },
-		{ ERR_ING_CTXT_PRIO,
-		  "SGE too many priority ingress contexts", -1, 0 },
-		{ ERR_EGR_CTXT_PRIO,
-		  "SGE too many priority egress contexts", -1, 0 },
-		{ INGRESS_SIZE_ERR, "SGE illegal ingress QID", -1, 0 },
-		{ EGRESS_SIZE_ERR, "SGE illegal egress QID", -1, 0 },
-		{ 0 }
-	};
-
-	v = (u64)t4_read_reg(adapter, SGE_INT_CAUSE1) |
-	    ((u64)t4_read_reg(adapter, SGE_INT_CAUSE2) << 32);
-	if (v) {
-		dev_alert(adapter->pdev_dev, "SGE parity error (%#llx)\n",
-			 (unsigned long long)v);
-		t4_write_reg(adapter, SGE_INT_CAUSE1, v);
-		t4_write_reg(adapter, SGE_INT_CAUSE2, v >> 32);
-	}
-
-	if (t4_handle_intr_status(adapter, SGE_INT_CAUSE3, sge_intr_info) ||
-	    v != 0)
-		t4_fatal_err(adapter);
-}
-
-/*
- * CIM interrupt handler.
- */
-static void cim_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info cim_intr_info[] = {
-		{ PREFDROPINT, "CIM control register prefetch drop", -1, 1 },
-		{ OBQPARERR, "CIM OBQ parity error", -1, 1 },
-		{ IBQPARERR, "CIM IBQ parity error", -1, 1 },
-		{ MBUPPARERR, "CIM mailbox uP parity error", -1, 1 },
-		{ MBHOSTPARERR, "CIM mailbox host parity error", -1, 1 },
-		{ TIEQINPARERRINT, "CIM TIEQ outgoing parity error", -1, 1 },
-		{ TIEQOUTPARERRINT, "CIM TIEQ incoming parity error", -1, 1 },
-		{ 0 }
-	};
-	static const struct intr_info cim_upintr_info[] = {
-		{ RSVDSPACEINT, "CIM reserved space access", -1, 1 },
-		{ ILLTRANSINT, "CIM illegal transaction", -1, 1 },
-		{ ILLWRINT, "CIM illegal write", -1, 1 },
-		{ ILLRDINT, "CIM illegal read", -1, 1 },
-		{ ILLRDBEINT, "CIM illegal read BE", -1, 1 },
-		{ ILLWRBEINT, "CIM illegal write BE", -1, 1 },
-		{ SGLRDBOOTINT, "CIM single read from boot space", -1, 1 },
-		{ SGLWRBOOTINT, "CIM single write to boot space", -1, 1 },
-		{ BLKWRBOOTINT, "CIM block write to boot space", -1, 1 },
-		{ SGLRDFLASHINT, "CIM single read from flash space", -1, 1 },
-		{ SGLWRFLASHINT, "CIM single write to flash space", -1, 1 },
-		{ BLKWRFLASHINT, "CIM block write to flash space", -1, 1 },
-		{ SGLRDEEPROMINT, "CIM single EEPROM read", -1, 1 },
-		{ SGLWREEPROMINT, "CIM single EEPROM write", -1, 1 },
-		{ BLKRDEEPROMINT, "CIM block EEPROM read", -1, 1 },
-		{ BLKWREEPROMINT, "CIM block EEPROM write", -1, 1 },
-		{ SGLRDCTLINT , "CIM single read from CTL space", -1, 1 },
-		{ SGLWRCTLINT , "CIM single write to CTL space", -1, 1 },
-		{ BLKRDCTLINT , "CIM block read from CTL space", -1, 1 },
-		{ BLKWRCTLINT , "CIM block write to CTL space", -1, 1 },
-		{ SGLRDPLINT , "CIM single read from PL space", -1, 1 },
-		{ SGLWRPLINT , "CIM single write to PL space", -1, 1 },
-		{ BLKRDPLINT , "CIM block read from PL space", -1, 1 },
-		{ BLKWRPLINT , "CIM block write to PL space", -1, 1 },
-		{ REQOVRLOOKUPINT , "CIM request FIFO overwrite", -1, 1 },
-		{ RSPOVRLOOKUPINT , "CIM response FIFO overwrite", -1, 1 },
-		{ TIMEOUTINT , "CIM PIF timeout", -1, 1 },
-		{ TIMEOUTMAINT , "CIM PIF MA timeout", -1, 1 },
-		{ 0 }
-	};
-
-	int fat;
-
-	fat = t4_handle_intr_status(adapter, CIM_HOST_INT_CAUSE,
-				    cim_intr_info) +
-	      t4_handle_intr_status(adapter, CIM_HOST_UPACC_INT_CAUSE,
-				    cim_upintr_info);
-	if (fat)
-		t4_fatal_err(adapter);
-}
-
-/*
- * ULP RX interrupt handler.
- */
-static void ulprx_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info ulprx_intr_info[] = {
-		{ 0x1800000, "ULPRX context error", -1, 1 },
-		{ 0x7fffff, "ULPRX parity error", -1, 1 },
-		{ 0 }
-	};
-
-	if (t4_handle_intr_status(adapter, ULP_RX_INT_CAUSE, ulprx_intr_info))
-		t4_fatal_err(adapter);
-}
-
-/*
- * ULP TX interrupt handler.
- */
-static void ulptx_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info ulptx_intr_info[] = {
-		{ PBL_BOUND_ERR_CH3, "ULPTX channel 3 PBL out of bounds", -1,
-		  0 },
-		{ PBL_BOUND_ERR_CH2, "ULPTX channel 2 PBL out of bounds", -1,
-		  0 },
-		{ PBL_BOUND_ERR_CH1, "ULPTX channel 1 PBL out of bounds", -1,
-		  0 },
-		{ PBL_BOUND_ERR_CH0, "ULPTX channel 0 PBL out of bounds", -1,
-		  0 },
-		{ 0xfffffff, "ULPTX parity error", -1, 1 },
-		{ 0 }
-	};
-
-	if (t4_handle_intr_status(adapter, ULP_TX_INT_CAUSE, ulptx_intr_info))
-		t4_fatal_err(adapter);
-}
-
-/*
- * PM TX interrupt handler.
- */
-static void pmtx_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info pmtx_intr_info[] = {
-		{ PCMD_LEN_OVFL0, "PMTX channel 0 pcmd too large", -1, 1 },
-		{ PCMD_LEN_OVFL1, "PMTX channel 1 pcmd too large", -1, 1 },
-		{ PCMD_LEN_OVFL2, "PMTX channel 2 pcmd too large", -1, 1 },
-		{ ZERO_C_CMD_ERROR, "PMTX 0-length pcmd", -1, 1 },
-		{ PMTX_FRAMING_ERROR, "PMTX framing error", -1, 1 },
-		{ OESPI_PAR_ERROR, "PMTX oespi parity error", -1, 1 },
-		{ DB_OPTIONS_PAR_ERROR, "PMTX db_options parity error", -1, 1 },
-		{ ICSPI_PAR_ERROR, "PMTX icspi parity error", -1, 1 },
-		{ C_PCMD_PAR_ERROR, "PMTX c_pcmd parity error", -1, 1},
-		{ 0 }
-	};
-
-	if (t4_handle_intr_status(adapter, PM_TX_INT_CAUSE, pmtx_intr_info))
-		t4_fatal_err(adapter);
-}
-
-/*
- * PM RX interrupt handler.
- */
-static void pmrx_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info pmrx_intr_info[] = {
-		{ ZERO_E_CMD_ERROR, "PMRX 0-length pcmd", -1, 1 },
-		{ PMRX_FRAMING_ERROR, "PMRX framing error", -1, 1 },
-		{ OCSPI_PAR_ERROR, "PMRX ocspi parity error", -1, 1 },
-		{ DB_OPTIONS_PAR_ERROR, "PMRX db_options parity error", -1, 1 },
-		{ IESPI_PAR_ERROR, "PMRX iespi parity error", -1, 1 },
-		{ E_PCMD_PAR_ERROR, "PMRX e_pcmd parity error", -1, 1},
-		{ 0 }
-	};
-
-	if (t4_handle_intr_status(adapter, PM_RX_INT_CAUSE, pmrx_intr_info))
-		t4_fatal_err(adapter);
-}
-
-/*
- * CPL switch interrupt handler.
- */
-static void cplsw_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info cplsw_intr_info[] = {
-		{ CIM_OP_MAP_PERR, "CPLSW CIM op_map parity error", -1, 1 },
-		{ CIM_OVFL_ERROR, "CPLSW CIM overflow", -1, 1 },
-		{ TP_FRAMING_ERROR, "CPLSW TP framing error", -1, 1 },
-		{ SGE_FRAMING_ERROR, "CPLSW SGE framing error", -1, 1 },
-		{ CIM_FRAMING_ERROR, "CPLSW CIM framing error", -1, 1 },
-		{ ZERO_SWITCH_ERROR, "CPLSW no-switch error", -1, 1 },
-		{ 0 }
-	};
-
-	if (t4_handle_intr_status(adapter, CPL_INTR_CAUSE, cplsw_intr_info))
-		t4_fatal_err(adapter);
-}
-
-/*
- * LE interrupt handler.
- */
-static void le_intr_handler(struct adapter *adap)
-{
-	static const struct intr_info le_intr_info[] = {
-		{ LIPMISS, "LE LIP miss", -1, 0 },
-		{ LIP0, "LE 0 LIP error", -1, 0 },
-		{ PARITYERR, "LE parity error", -1, 1 },
-		{ UNKNOWNCMD, "LE unknown command", -1, 1 },
-		{ REQQPARERR, "LE request queue parity error", -1, 1 },
-		{ 0 }
-	};
-
-	if (t4_handle_intr_status(adap, LE_DB_INT_CAUSE, le_intr_info))
-		t4_fatal_err(adap);
-}
-
-/*
- * MPS interrupt handler.
- */
-static void mps_intr_handler(struct adapter *adapter)
-{
-	static const struct intr_info mps_rx_intr_info[] = {
-		{ 0xffffff, "MPS Rx parity error", -1, 1 },
-		{ 0 }
-	};
-	static const struct intr_info mps_tx_intr_info[] = {
-		{ TPFIFO, "MPS Tx TP FIFO parity error", -1, 1 },
-		{ NCSIFIFO, "MPS Tx NC-SI FIFO parity error", -1, 1 },
-		{ TXDATAFIFO, "MPS Tx data FIFO parity error", -1, 1 },
-		{ TXDESCFIFO, "MPS Tx desc FIFO parity error", -1, 1 },
-		{ BUBBLE, "MPS Tx underflow", -1, 1 },
-		{ SECNTERR, "MPS Tx SOP/EOP error", -1, 1 },
-		{ FRMERR, "MPS Tx framing error", -1, 1 },
-		{ 0 }
-	};
-	static const struct intr_info mps_trc_intr_info[] = {
-		{ FILTMEM, "MPS TRC filter parity error", -1, 1 },
-		{ PKTFIFO, "MPS TRC packet FIFO parity error", -1, 1 },
-		{ MISCPERR, "MPS TRC misc parity error", -1, 1 },
-		{ 0 }
-	};
-	static const struct intr_info mps_stat_sram_intr_info[] = {
-		{ 0x1fffff, "MPS statistics SRAM parity error", -1, 1 },
-		{ 0 }
-	};
-	static const struct intr_info mps_stat_tx_intr_info[] = {
-		{ 0xfffff, "MPS statistics Tx FIFO parity error", -1, 1 },
-		{ 0 }
-	};
-	static const struct intr_info mps_stat_rx_intr_info[] = {
-		{ 0xffffff, "MPS statistics Rx FIFO parity error", -1, 1 },
-		{ 0 }
-	};
-	static const struct intr_info mps_cls_intr_info[] = {
-		{ MATCHSRAM, "MPS match SRAM parity error", -1, 1 },
-		{ MATCHTCAM, "MPS match TCAM parity error", -1, 1 },
-		{ HASHSRAM, "MPS hash SRAM parity error", -1, 1 },
-		{ 0 }
-	};
-
-	int fat;
-
-	fat = t4_handle_intr_status(adapter, MPS_RX_PERR_INT_CAUSE,
-				    mps_rx_intr_info) +
-	      t4_handle_intr_status(adapter, MPS_TX_INT_CAUSE,
-				    mps_tx_intr_info) +
-	      t4_handle_intr_status(adapter, MPS_TRC_INT_CAUSE,
-				    mps_trc_intr_info) +
-	      t4_handle_intr_status(adapter, MPS_STAT_PERR_INT_CAUSE_SRAM,
-				    mps_stat_sram_intr_info) +
-	      t4_handle_intr_status(adapter, MPS_STAT_PERR_INT_CAUSE_TX_FIFO,
-				    mps_stat_tx_intr_info) +
-	      t4_handle_intr_status(adapter, MPS_STAT_PERR_INT_CAUSE_RX_FIFO,
-				    mps_stat_rx_intr_info) +
-	      t4_handle_intr_status(adapter, MPS_CLS_INT_CAUSE,
-				    mps_cls_intr_info);
-
-	t4_write_reg(adapter, MPS_INT_CAUSE, CLSINT | TRCINT |
-		     RXINT | TXINT | STATINT);
-	t4_read_reg(adapter, MPS_INT_CAUSE);                    /* flush */
-	if (fat)
-		t4_fatal_err(adapter);
-}
-
-#define MEM_INT_MASK (PERR_INT_CAUSE | ECC_CE_INT_CAUSE | ECC_UE_INT_CAUSE)
-
-/*
- * EDC/MC interrupt handler.
- */
-static void mem_intr_handler(struct adapter *adapter, int idx)
-{
-	static const char name[3][5] = { "EDC0", "EDC1", "MC" };
-
-	unsigned int addr, cnt_addr, v;
-
-	if (idx <= MEM_EDC1) {
-		addr = EDC_REG(EDC_INT_CAUSE, idx);
-		cnt_addr = EDC_REG(EDC_ECC_STATUS, idx);
-	} else {
-		addr = MC_INT_CAUSE;
-		cnt_addr = MC_ECC_STATUS;
-	}
-
-	v = t4_read_reg(adapter, addr) & MEM_INT_MASK;
-	if (v & PERR_INT_CAUSE)
-		dev_alert(adapter->pdev_dev, "%s FIFO parity error\n",
-			  name[idx]);
-	if (v & ECC_CE_INT_CAUSE) {
-		u32 cnt = ECC_CECNT_GET(t4_read_reg(adapter, cnt_addr));
-
-		t4_write_reg(adapter, cnt_addr, ECC_CECNT_MASK);
-		if (printk_ratelimit())
-			dev_warn(adapter->pdev_dev,
-				 "%u %s correctable ECC data error%s\n",
-				 cnt, name[idx], cnt > 1 ? "s" : "");
-	}
-	if (v & ECC_UE_INT_CAUSE)
-		dev_alert(adapter->pdev_dev,
-			  "%s uncorrectable ECC data error\n", name[idx]);
-
-	t4_write_reg(adapter, addr, v);
-	if (v & (PERR_INT_CAUSE | ECC_UE_INT_CAUSE))
-		t4_fatal_err(adapter);
-}
-
-/*
- * MA interrupt handler.
- */
-static void ma_intr_handler(struct adapter *adap)
-{
-	u32 v, status = t4_read_reg(adap, MA_INT_CAUSE);
-
-	if (status & MEM_PERR_INT_CAUSE)
-		dev_alert(adap->pdev_dev,
-			  "MA parity error, parity status %#x\n",
-			  t4_read_reg(adap, MA_PARITY_ERROR_STATUS));
-	if (status & MEM_WRAP_INT_CAUSE) {
-		v = t4_read_reg(adap, MA_INT_WRAP_STATUS);
-		dev_alert(adap->pdev_dev, "MA address wrap-around error by "
-			  "client %u to address %#x\n",
-			  MEM_WRAP_CLIENT_NUM_GET(v),
-			  MEM_WRAP_ADDRESS_GET(v) << 4);
-	}
-	t4_write_reg(adap, MA_INT_CAUSE, status);
-	t4_fatal_err(adap);
-}
-
-/*
- * SMB interrupt handler.
- */
-static void smb_intr_handler(struct adapter *adap)
-{
-	static const struct intr_info smb_intr_info[] = {
-		{ MSTTXFIFOPARINT, "SMB master Tx FIFO parity error", -1, 1 },
-		{ MSTRXFIFOPARINT, "SMB master Rx FIFO parity error", -1, 1 },
-		{ SLVFIFOPARINT, "SMB slave FIFO parity error", -1, 1 },
-		{ 0 }
-	};
-
-	if (t4_handle_intr_status(adap, SMB_INT_CAUSE, smb_intr_info))
-		t4_fatal_err(adap);
-}
-
-/*
- * NC-SI interrupt handler.
- */
-static void ncsi_intr_handler(struct adapter *adap)
-{
-	static const struct intr_info ncsi_intr_info[] = {
-		{ CIM_DM_PRTY_ERR, "NC-SI CIM parity error", -1, 1 },
-		{ MPS_DM_PRTY_ERR, "NC-SI MPS parity error", -1, 1 },
-		{ TXFIFO_PRTY_ERR, "NC-SI Tx FIFO parity error", -1, 1 },
-		{ RXFIFO_PRTY_ERR, "NC-SI Rx FIFO parity error", -1, 1 },
-		{ 0 }
-	};
-
-	if (t4_handle_intr_status(adap, NCSI_INT_CAUSE, ncsi_intr_info))
-		t4_fatal_err(adap);
-}
-
-/*
- * XGMAC interrupt handler.
- */
-static void xgmac_intr_handler(struct adapter *adap, int port)
-{
-	u32 v = t4_read_reg(adap, PORT_REG(port, XGMAC_PORT_INT_CAUSE));
-
-	v &= TXFIFO_PRTY_ERR | RXFIFO_PRTY_ERR;
-	if (!v)
-		return;
-
-	if (v & TXFIFO_PRTY_ERR)
-		dev_alert(adap->pdev_dev, "XGMAC %d Tx FIFO parity error\n",
-			  port);
-	if (v & RXFIFO_PRTY_ERR)
-		dev_alert(adap->pdev_dev, "XGMAC %d Rx FIFO parity error\n",
-			  port);
-	t4_write_reg(adap, PORT_REG(port, XGMAC_PORT_INT_CAUSE), v);
-	t4_fatal_err(adap);
-}
-
-/*
- * PL interrupt handler.
- */
-static void pl_intr_handler(struct adapter *adap)
-{
-	static const struct intr_info pl_intr_info[] = {
-		{ FATALPERR, "T4 fatal parity error", -1, 1 },
-		{ PERRVFID, "PL VFID_MAP parity error", -1, 1 },
-		{ 0 }
-	};
-
-	if (t4_handle_intr_status(adap, PL_PL_INT_CAUSE, pl_intr_info))
-		t4_fatal_err(adap);
-}
-
-#define PF_INTR_MASK (PFSW)
-#define GLBL_INTR_MASK (CIM | MPS | PL | PCIE | MC | EDC0 | \
-		EDC1 | LE | TP | MA | PM_TX | PM_RX | ULP_RX | \
-		CPL_SWITCH | SGE | ULP_TX)
-
-/**
- *	t4_slow_intr_handler - control path interrupt handler
- *	@adapter: the adapter
- *
- *	T4 interrupt handler for non-data global interrupt events, e.g., errors.
- *	The designation 'slow' is because it involves register reads, while
- *	data interrupts typically don't involve any MMIOs.
- */
-int t4_slow_intr_handler(struct adapter *adapter)
-{
-	u32 cause = t4_read_reg(adapter, PL_INT_CAUSE);
-
-	if (!(cause & GLBL_INTR_MASK))
-		return 0;
-	if (cause & CIM)
-		cim_intr_handler(adapter);
-	if (cause & MPS)
-		mps_intr_handler(adapter);
-	if (cause & NCSI)
-		ncsi_intr_handler(adapter);
-	if (cause & PL)
-		pl_intr_handler(adapter);
-	if (cause & SMB)
-		smb_intr_handler(adapter);
-	if (cause & XGMAC0)
-		xgmac_intr_handler(adapter, 0);
-	if (cause & XGMAC1)
-		xgmac_intr_handler(adapter, 1);
-	if (cause & XGMAC_KR0)
-		xgmac_intr_handler(adapter, 2);
-	if (cause & XGMAC_KR1)
-		xgmac_intr_handler(adapter, 3);
-	if (cause & PCIE)
-		pcie_intr_handler(adapter);
-	if (cause & MC)
-		mem_intr_handler(adapter, MEM_MC);
-	if (cause & EDC0)
-		mem_intr_handler(adapter, MEM_EDC0);
-	if (cause & EDC1)
-		mem_intr_handler(adapter, MEM_EDC1);
-	if (cause & LE)
-		le_intr_handler(adapter);
-	if (cause & TP)
-		tp_intr_handler(adapter);
-	if (cause & MA)
-		ma_intr_handler(adapter);
-	if (cause & PM_TX)
-		pmtx_intr_handler(adapter);
-	if (cause & PM_RX)
-		pmrx_intr_handler(adapter);
-	if (cause & ULP_RX)
-		ulprx_intr_handler(adapter);
-	if (cause & CPL_SWITCH)
-		cplsw_intr_handler(adapter);
-	if (cause & SGE)
-		sge_intr_handler(adapter);
-	if (cause & ULP_TX)
-		ulptx_intr_handler(adapter);
-
-	/* Clear the interrupts just processed for which we are the master. */
-	t4_write_reg(adapter, PL_INT_CAUSE, cause & GLBL_INTR_MASK);
-	(void) t4_read_reg(adapter, PL_INT_CAUSE); /* flush */
-	return 1;
-}
-
-/**
- *	t4_intr_enable - enable interrupts
- *	@adapter: the adapter whose interrupts should be enabled
- *
- *	Enable PF-specific interrupts for the calling function and the top-level
- *	interrupt concentrator for global interrupts.  Interrupts are already
- *	enabled at each module,	here we just enable the roots of the interrupt
- *	hierarchies.
- *
- *	Note: this function should be called only when the driver manages
- *	non PF-specific interrupts from the various HW modules.  Only one PCI
- *	function at a time should be doing this.
- */
-void t4_intr_enable(struct adapter *adapter)
-{
-	u32 pf = SOURCEPF_GET(t4_read_reg(adapter, PL_WHOAMI));
-
-	t4_write_reg(adapter, SGE_INT_ENABLE3, ERR_CPL_EXCEED_IQE_SIZE |
-		     ERR_INVALID_CIDX_INC | ERR_CPL_OPCODE_0 |
-		     ERR_DROPPED_DB | ERR_DATA_CPL_ON_HIGH_QID1 |
-		     ERR_DATA_CPL_ON_HIGH_QID0 | ERR_BAD_DB_PIDX3 |
-		     ERR_BAD_DB_PIDX2 | ERR_BAD_DB_PIDX1 |
-		     ERR_BAD_DB_PIDX0 | ERR_ING_CTXT_PRIO |
-		     ERR_EGR_CTXT_PRIO | INGRESS_SIZE_ERR |
-		     EGRESS_SIZE_ERR);
-	t4_write_reg(adapter, MYPF_REG(PL_PF_INT_ENABLE), PF_INTR_MASK);
-	t4_set_reg_field(adapter, PL_INT_MAP0, 0, 1 << pf);
-}
-
-/**
- *	t4_intr_disable - disable interrupts
- *	@adapter: the adapter whose interrupts should be disabled
- *
- *	Disable interrupts.  We only disable the top-level interrupt
- *	concentrators.  The caller must be a PCI function managing global
- *	interrupts.
- */
-void t4_intr_disable(struct adapter *adapter)
-{
-	u32 pf = SOURCEPF_GET(t4_read_reg(adapter, PL_WHOAMI));
-
-	t4_write_reg(adapter, MYPF_REG(PL_PF_INT_ENABLE), 0);
-	t4_set_reg_field(adapter, PL_INT_MAP0, 1 << pf, 0);
-}
-
-/**
- *	hash_mac_addr - return the hash value of a MAC address
- *	@addr: the 48-bit Ethernet MAC address
- *
- *	Hashes a MAC address according to the hash function used by HW inexact
- *	(hash) address matching.
- */
-static int hash_mac_addr(const u8 *addr)
-{
-	u32 a = ((u32)addr[0] << 16) | ((u32)addr[1] << 8) | addr[2];
-	u32 b = ((u32)addr[3] << 16) | ((u32)addr[4] << 8) | addr[5];
-	a ^= b;
-	a ^= (a >> 12);
-	a ^= (a >> 6);
-	return a & 0x3f;
-}
-
-/**
- *	t4_config_rss_range - configure a portion of the RSS mapping table
- *	@adapter: the adapter
- *	@mbox: mbox to use for the FW command
- *	@viid: virtual interface whose RSS subtable is to be written
- *	@start: start entry in the table to write
- *	@n: how many table entries to write
- *	@rspq: values for the response queue lookup table
- *	@nrspq: number of values in @rspq
- *
- *	Programs the selected part of the VI's RSS mapping table with the
- *	provided values.  If @nrspq < @n the supplied values are used repeatedly
- *	until the full table range is populated.
- *
- *	The caller must ensure the values in @rspq are in the range allowed for
- *	@viid.
- */
-int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
-			int start, int n, const u16 *rspq, unsigned int nrspq)
-{
-	int ret;
-	const u16 *rsp = rspq;
-	const u16 *rsp_end = rspq + nrspq;
-	struct fw_rss_ind_tbl_cmd cmd;
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_viid = htonl(FW_CMD_OP(FW_RSS_IND_TBL_CMD) |
-			       FW_CMD_REQUEST | FW_CMD_WRITE |
-			       FW_RSS_IND_TBL_CMD_VIID(viid));
-	cmd.retval_len16 = htonl(FW_LEN16(cmd));
-
-	/* each fw_rss_ind_tbl_cmd takes up to 32 entries */
-	while (n > 0) {
-		int nq = min(n, 32);
-		__be32 *qp = &cmd.iq0_to_iq2;
-
-		cmd.niqid = htons(nq);
-		cmd.startidx = htons(start);
-
-		start += nq;
-		n -= nq;
-
-		while (nq > 0) {
-			unsigned int v;
-
-			v = FW_RSS_IND_TBL_CMD_IQ0(*rsp);
-			if (++rsp >= rsp_end)
-				rsp = rspq;
-			v |= FW_RSS_IND_TBL_CMD_IQ1(*rsp);
-			if (++rsp >= rsp_end)
-				rsp = rspq;
-			v |= FW_RSS_IND_TBL_CMD_IQ2(*rsp);
-			if (++rsp >= rsp_end)
-				rsp = rspq;
-
-			*qp++ = htonl(v);
-			nq -= 3;
-		}
-
-		ret = t4_wr_mbox(adapter, mbox, &cmd, sizeof(cmd), NULL);
-		if (ret)
-			return ret;
-	}
-	return 0;
-}
-
-/**
- *	t4_config_glbl_rss - configure the global RSS mode
- *	@adapter: the adapter
- *	@mbox: mbox to use for the FW command
- *	@mode: global RSS mode
- *	@flags: mode-specific flags
- *
- *	Sets the global RSS mode.
- */
-int t4_config_glbl_rss(struct adapter *adapter, int mbox, unsigned int mode,
-		       unsigned int flags)
-{
-	struct fw_rss_glb_config_cmd c;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_write = htonl(FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) |
-			      FW_CMD_REQUEST | FW_CMD_WRITE);
-	c.retval_len16 = htonl(FW_LEN16(c));
-	if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_MANUAL) {
-		c.u.manual.mode_pkd = htonl(FW_RSS_GLB_CONFIG_CMD_MODE(mode));
-	} else if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL) {
-		c.u.basicvirtual.mode_pkd =
-			htonl(FW_RSS_GLB_CONFIG_CMD_MODE(mode));
-		c.u.basicvirtual.synmapen_to_hashtoeplitz = htonl(flags);
-	} else
-		return -EINVAL;
-	return t4_wr_mbox(adapter, mbox, &c, sizeof(c), NULL);
-}
-
-/**
- *	t4_tp_get_tcp_stats - read TP's TCP MIB counters
- *	@adap: the adapter
- *	@v4: holds the TCP/IP counter values
- *	@v6: holds the TCP/IPv6 counter values
- *
- *	Returns the values of TP's TCP/IP and TCP/IPv6 MIB counters.
- *	Either @v4 or @v6 may be %NULL to skip the corresponding stats.
- */
-void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
-			 struct tp_tcp_stats *v6)
-{
-	u32 val[TP_MIB_TCP_RXT_SEG_LO - TP_MIB_TCP_OUT_RST + 1];
-
-#define STAT_IDX(x) ((TP_MIB_TCP_##x) - TP_MIB_TCP_OUT_RST)
-#define STAT(x)     val[STAT_IDX(x)]
-#define STAT64(x)   (((u64)STAT(x##_HI) << 32) | STAT(x##_LO))
-
-	if (v4) {
-		t4_read_indirect(adap, TP_MIB_INDEX, TP_MIB_DATA, val,
-				 ARRAY_SIZE(val), TP_MIB_TCP_OUT_RST);
-		v4->tcpOutRsts = STAT(OUT_RST);
-		v4->tcpInSegs  = STAT64(IN_SEG);
-		v4->tcpOutSegs = STAT64(OUT_SEG);
-		v4->tcpRetransSegs = STAT64(RXT_SEG);
-	}
-	if (v6) {
-		t4_read_indirect(adap, TP_MIB_INDEX, TP_MIB_DATA, val,
-				 ARRAY_SIZE(val), TP_MIB_TCP_V6OUT_RST);
-		v6->tcpOutRsts = STAT(OUT_RST);
-		v6->tcpInSegs  = STAT64(IN_SEG);
-		v6->tcpOutSegs = STAT64(OUT_SEG);
-		v6->tcpRetransSegs = STAT64(RXT_SEG);
-	}
-#undef STAT64
-#undef STAT
-#undef STAT_IDX
-}
-
-/**
- *	t4_read_mtu_tbl - returns the values in the HW path MTU table
- *	@adap: the adapter
- *	@mtus: where to store the MTU values
- *	@mtu_log: where to store the MTU base-2 log (may be %NULL)
- *
- *	Reads the HW path MTU table.
- */
-void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log)
-{
-	u32 v;
-	int i;
-
-	for (i = 0; i < NMTUS; ++i) {
-		t4_write_reg(adap, TP_MTU_TABLE,
-			     MTUINDEX(0xff) | MTUVALUE(i));
-		v = t4_read_reg(adap, TP_MTU_TABLE);
-		mtus[i] = MTUVALUE_GET(v);
-		if (mtu_log)
-			mtu_log[i] = MTUWIDTH_GET(v);
-	}
-}
-
-/**
- *	init_cong_ctrl - initialize congestion control parameters
- *	@a: the alpha values for congestion control
- *	@b: the beta values for congestion control
- *
- *	Initialize the congestion control parameters.
- */
-static void __devinit init_cong_ctrl(unsigned short *a, unsigned short *b)
-{
-	a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = a[8] = 1;
-	a[9] = 2;
-	a[10] = 3;
-	a[11] = 4;
-	a[12] = 5;
-	a[13] = 6;
-	a[14] = 7;
-	a[15] = 8;
-	a[16] = 9;
-	a[17] = 10;
-	a[18] = 14;
-	a[19] = 17;
-	a[20] = 21;
-	a[21] = 25;
-	a[22] = 30;
-	a[23] = 35;
-	a[24] = 45;
-	a[25] = 60;
-	a[26] = 80;
-	a[27] = 100;
-	a[28] = 200;
-	a[29] = 300;
-	a[30] = 400;
-	a[31] = 500;
-
-	b[0] = b[1] = b[2] = b[3] = b[4] = b[5] = b[6] = b[7] = b[8] = 0;
-	b[9] = b[10] = 1;
-	b[11] = b[12] = 2;
-	b[13] = b[14] = b[15] = b[16] = 3;
-	b[17] = b[18] = b[19] = b[20] = b[21] = 4;
-	b[22] = b[23] = b[24] = b[25] = b[26] = b[27] = 5;
-	b[28] = b[29] = 6;
-	b[30] = b[31] = 7;
-}
-
-/* The minimum additive increment value for the congestion control table */
-#define CC_MIN_INCR 2U
-
-/**
- *	t4_load_mtus - write the MTU and congestion control HW tables
- *	@adap: the adapter
- *	@mtus: the values for the MTU table
- *	@alpha: the values for the congestion control alpha parameter
- *	@beta: the values for the congestion control beta parameter
- *
- *	Write the HW MTU table with the supplied MTUs and the high-speed
- *	congestion control table with the supplied alpha, beta, and MTUs.
- *	We write the two tables together because the additive increments
- *	depend on the MTUs.
- */
-void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
-		  const unsigned short *alpha, const unsigned short *beta)
-{
-	static const unsigned int avg_pkts[NCCTRL_WIN] = {
-		2, 6, 10, 14, 20, 28, 40, 56, 80, 112, 160, 224, 320, 448, 640,
-		896, 1281, 1792, 2560, 3584, 5120, 7168, 10240, 14336, 20480,
-		28672, 40960, 57344, 81920, 114688, 163840, 229376
-	};
-
-	unsigned int i, w;
-
-	for (i = 0; i < NMTUS; ++i) {
-		unsigned int mtu = mtus[i];
-		unsigned int log2 = fls(mtu);
-
-		if (!(mtu & ((1 << log2) >> 2)))     /* round */
-			log2--;
-		t4_write_reg(adap, TP_MTU_TABLE, MTUINDEX(i) |
-			     MTUWIDTH(log2) | MTUVALUE(mtu));
-
-		for (w = 0; w < NCCTRL_WIN; ++w) {
-			unsigned int inc;
-
-			inc = max(((mtu - 40) * alpha[w]) / avg_pkts[w],
-				  CC_MIN_INCR);
-
-			t4_write_reg(adap, TP_CCTRL_TABLE, (i << 21) |
-				     (w << 16) | (beta[w] << 13) | inc);
-		}
-	}
-}
-
-/**
- *	get_mps_bg_map - return the buffer groups associated with a port
- *	@adap: the adapter
- *	@idx: the port index
- *
- *	Returns a bitmap indicating which MPS buffer groups are associated
- *	with the given port.  Bit i is set if buffer group i is used by the
- *	port.
- */
-static unsigned int get_mps_bg_map(struct adapter *adap, int idx)
-{
-	u32 n = NUMPORTS_GET(t4_read_reg(adap, MPS_CMN_CTL));
-
-	if (n == 0)
-		return idx == 0 ? 0xf : 0;
-	if (n == 1)
-		return idx < 2 ? (3 << (2 * idx)) : 0;
-	return 1 << idx;
-}
-
-/**
- *	t4_get_port_stats - collect port statistics
- *	@adap: the adapter
- *	@idx: the port index
- *	@p: the stats structure to fill
- *
- *	Collect statistics related to the given port from HW.
- */
-void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
-{
-	u32 bgmap = get_mps_bg_map(adap, idx);
-
-#define GET_STAT(name) \
-	t4_read_reg64(adap, PORT_REG(idx, MPS_PORT_STAT_##name##_L))
-#define GET_STAT_COM(name) t4_read_reg64(adap, MPS_STAT_##name##_L)
-
-	p->tx_octets           = GET_STAT(TX_PORT_BYTES);
-	p->tx_frames           = GET_STAT(TX_PORT_FRAMES);
-	p->tx_bcast_frames     = GET_STAT(TX_PORT_BCAST);
-	p->tx_mcast_frames     = GET_STAT(TX_PORT_MCAST);
-	p->tx_ucast_frames     = GET_STAT(TX_PORT_UCAST);
-	p->tx_error_frames     = GET_STAT(TX_PORT_ERROR);
-	p->tx_frames_64        = GET_STAT(TX_PORT_64B);
-	p->tx_frames_65_127    = GET_STAT(TX_PORT_65B_127B);
-	p->tx_frames_128_255   = GET_STAT(TX_PORT_128B_255B);
-	p->tx_frames_256_511   = GET_STAT(TX_PORT_256B_511B);
-	p->tx_frames_512_1023  = GET_STAT(TX_PORT_512B_1023B);
-	p->tx_frames_1024_1518 = GET_STAT(TX_PORT_1024B_1518B);
-	p->tx_frames_1519_max  = GET_STAT(TX_PORT_1519B_MAX);
-	p->tx_drop             = GET_STAT(TX_PORT_DROP);
-	p->tx_pause            = GET_STAT(TX_PORT_PAUSE);
-	p->tx_ppp0             = GET_STAT(TX_PORT_PPP0);
-	p->tx_ppp1             = GET_STAT(TX_PORT_PPP1);
-	p->tx_ppp2             = GET_STAT(TX_PORT_PPP2);
-	p->tx_ppp3             = GET_STAT(TX_PORT_PPP3);
-	p->tx_ppp4             = GET_STAT(TX_PORT_PPP4);
-	p->tx_ppp5             = GET_STAT(TX_PORT_PPP5);
-	p->tx_ppp6             = GET_STAT(TX_PORT_PPP6);
-	p->tx_ppp7             = GET_STAT(TX_PORT_PPP7);
-
-	p->rx_octets           = GET_STAT(RX_PORT_BYTES);
-	p->rx_frames           = GET_STAT(RX_PORT_FRAMES);
-	p->rx_bcast_frames     = GET_STAT(RX_PORT_BCAST);
-	p->rx_mcast_frames     = GET_STAT(RX_PORT_MCAST);
-	p->rx_ucast_frames     = GET_STAT(RX_PORT_UCAST);
-	p->rx_too_long         = GET_STAT(RX_PORT_MTU_ERROR);
-	p->rx_jabber           = GET_STAT(RX_PORT_MTU_CRC_ERROR);
-	p->rx_fcs_err          = GET_STAT(RX_PORT_CRC_ERROR);
-	p->rx_len_err          = GET_STAT(RX_PORT_LEN_ERROR);
-	p->rx_symbol_err       = GET_STAT(RX_PORT_SYM_ERROR);
-	p->rx_runt             = GET_STAT(RX_PORT_LESS_64B);
-	p->rx_frames_64        = GET_STAT(RX_PORT_64B);
-	p->rx_frames_65_127    = GET_STAT(RX_PORT_65B_127B);
-	p->rx_frames_128_255   = GET_STAT(RX_PORT_128B_255B);
-	p->rx_frames_256_511   = GET_STAT(RX_PORT_256B_511B);
-	p->rx_frames_512_1023  = GET_STAT(RX_PORT_512B_1023B);
-	p->rx_frames_1024_1518 = GET_STAT(RX_PORT_1024B_1518B);
-	p->rx_frames_1519_max  = GET_STAT(RX_PORT_1519B_MAX);
-	p->rx_pause            = GET_STAT(RX_PORT_PAUSE);
-	p->rx_ppp0             = GET_STAT(RX_PORT_PPP0);
-	p->rx_ppp1             = GET_STAT(RX_PORT_PPP1);
-	p->rx_ppp2             = GET_STAT(RX_PORT_PPP2);
-	p->rx_ppp3             = GET_STAT(RX_PORT_PPP3);
-	p->rx_ppp4             = GET_STAT(RX_PORT_PPP4);
-	p->rx_ppp5             = GET_STAT(RX_PORT_PPP5);
-	p->rx_ppp6             = GET_STAT(RX_PORT_PPP6);
-	p->rx_ppp7             = GET_STAT(RX_PORT_PPP7);
-
-	p->rx_ovflow0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_MAC_DROP_FRAME) : 0;
-	p->rx_ovflow1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_MAC_DROP_FRAME) : 0;
-	p->rx_ovflow2 = (bgmap & 4) ? GET_STAT_COM(RX_BG_2_MAC_DROP_FRAME) : 0;
-	p->rx_ovflow3 = (bgmap & 8) ? GET_STAT_COM(RX_BG_3_MAC_DROP_FRAME) : 0;
-	p->rx_trunc0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_MAC_TRUNC_FRAME) : 0;
-	p->rx_trunc1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_MAC_TRUNC_FRAME) : 0;
-	p->rx_trunc2 = (bgmap & 4) ? GET_STAT_COM(RX_BG_2_MAC_TRUNC_FRAME) : 0;
-	p->rx_trunc3 = (bgmap & 8) ? GET_STAT_COM(RX_BG_3_MAC_TRUNC_FRAME) : 0;
-
-#undef GET_STAT
-#undef GET_STAT_COM
-}
-
-/**
- *	t4_wol_magic_enable - enable/disable magic packet WoL
- *	@adap: the adapter
- *	@port: the physical port index
- *	@addr: MAC address expected in magic packets, %NULL to disable
- *
- *	Enables/disables magic packet wake-on-LAN for the selected port.
- */
-void t4_wol_magic_enable(struct adapter *adap, unsigned int port,
-			 const u8 *addr)
-{
-	if (addr) {
-		t4_write_reg(adap, PORT_REG(port, XGMAC_PORT_MAGIC_MACID_LO),
-			     (addr[2] << 24) | (addr[3] << 16) |
-			     (addr[4] << 8) | addr[5]);
-		t4_write_reg(adap, PORT_REG(port, XGMAC_PORT_MAGIC_MACID_HI),
-			     (addr[0] << 8) | addr[1]);
-	}
-	t4_set_reg_field(adap, PORT_REG(port, XGMAC_PORT_CFG2), MAGICEN,
-			 addr ? MAGICEN : 0);
-}
-
-/**
- *	t4_wol_pat_enable - enable/disable pattern-based WoL
- *	@adap: the adapter
- *	@port: the physical port index
- *	@map: bitmap of which HW pattern filters to set
- *	@mask0: byte mask for bytes 0-63 of a packet
- *	@mask1: byte mask for bytes 64-127 of a packet
- *	@crc: Ethernet CRC for selected bytes
- *	@enable: enable/disable switch
- *
- *	Sets the pattern filters indicated in @map to mask out the bytes
- *	specified in @mask0/@mask1 in received packets and compare the CRC of
- *	the resulting packet against @crc.  If @enable is %true pattern-based
- *	WoL is enabled, otherwise disabled.
- */
-int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
-		      u64 mask0, u64 mask1, unsigned int crc, bool enable)
-{
-	int i;
-
-	if (!enable) {
-		t4_set_reg_field(adap, PORT_REG(port, XGMAC_PORT_CFG2),
-				 PATEN, 0);
-		return 0;
-	}
-	if (map > 0xff)
-		return -EINVAL;
-
-#define EPIO_REG(name) PORT_REG(port, XGMAC_PORT_EPIO_##name)
-
-	t4_write_reg(adap, EPIO_REG(DATA1), mask0 >> 32);
-	t4_write_reg(adap, EPIO_REG(DATA2), mask1);
-	t4_write_reg(adap, EPIO_REG(DATA3), mask1 >> 32);
-
-	for (i = 0; i < NWOL_PAT; i++, map >>= 1) {
-		if (!(map & 1))
-			continue;
-
-		/* write byte masks */
-		t4_write_reg(adap, EPIO_REG(DATA0), mask0);
-		t4_write_reg(adap, EPIO_REG(OP), ADDRESS(i) | EPIOWR);
-		t4_read_reg(adap, EPIO_REG(OP));                /* flush */
-		if (t4_read_reg(adap, EPIO_REG(OP)) & BUSY)
-			return -ETIMEDOUT;
-
-		/* write CRC */
-		t4_write_reg(adap, EPIO_REG(DATA0), crc);
-		t4_write_reg(adap, EPIO_REG(OP), ADDRESS(i + 32) | EPIOWR);
-		t4_read_reg(adap, EPIO_REG(OP));                /* flush */
-		if (t4_read_reg(adap, EPIO_REG(OP)) & BUSY)
-			return -ETIMEDOUT;
-	}
-#undef EPIO_REG
-
-	t4_set_reg_field(adap, PORT_REG(port, XGMAC_PORT_CFG2), 0, PATEN);
-	return 0;
-}
-
-#define INIT_CMD(var, cmd, rd_wr) do { \
-	(var).op_to_write = htonl(FW_CMD_OP(FW_##cmd##_CMD) | \
-				  FW_CMD_REQUEST | FW_CMD_##rd_wr); \
-	(var).retval_len16 = htonl(FW_LEN16(var)); \
-} while (0)
-
-/**
- *	t4_mdio_rd - read a PHY register through MDIO
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@phy_addr: the PHY address
- *	@mmd: the PHY MMD to access (0 for clause 22 PHYs)
- *	@reg: the register to read
- *	@valp: where to store the value
- *
- *	Issues a FW command through the given mailbox to read a PHY register.
- */
-int t4_mdio_rd(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
-	       unsigned int mmd, unsigned int reg, u16 *valp)
-{
-	int ret;
-	struct fw_ldst_cmd c;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_addrspace = htonl(FW_CMD_OP(FW_LDST_CMD) | FW_CMD_REQUEST |
-		FW_CMD_READ | FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_MDIO));
-	c.cycles_to_len16 = htonl(FW_LEN16(c));
-	c.u.mdio.paddr_mmd = htons(FW_LDST_CMD_PADDR(phy_addr) |
-				   FW_LDST_CMD_MMD(mmd));
-	c.u.mdio.raddr = htons(reg);
-
-	ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
-	if (ret == 0)
-		*valp = ntohs(c.u.mdio.rval);
-	return ret;
-}
-
-/**
- *	t4_mdio_wr - write a PHY register through MDIO
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@phy_addr: the PHY address
- *	@mmd: the PHY MMD to access (0 for clause 22 PHYs)
- *	@reg: the register to write
- *	@valp: value to write
- *
- *	Issues a FW command through the given mailbox to write a PHY register.
- */
-int t4_mdio_wr(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
-	       unsigned int mmd, unsigned int reg, u16 val)
-{
-	struct fw_ldst_cmd c;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_addrspace = htonl(FW_CMD_OP(FW_LDST_CMD) | FW_CMD_REQUEST |
-		FW_CMD_WRITE | FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_MDIO));
-	c.cycles_to_len16 = htonl(FW_LEN16(c));
-	c.u.mdio.paddr_mmd = htons(FW_LDST_CMD_PADDR(phy_addr) |
-				   FW_LDST_CMD_MMD(mmd));
-	c.u.mdio.raddr = htons(reg);
-	c.u.mdio.rval = htons(val);
-
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-}
-
-/**
- *	t4_fw_hello - establish communication with FW
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@evt_mbox: mailbox to receive async FW events
- *	@master: specifies the caller's willingness to be the device master
- *	@state: returns the current device state
- *
- *	Issues a command to establish communication with FW.
- */
-int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox,
-		enum dev_master master, enum dev_state *state)
-{
-	int ret;
-	struct fw_hello_cmd c;
-
-	INIT_CMD(c, HELLO, WRITE);
-	c.err_to_mbasyncnot = htonl(
-		FW_HELLO_CMD_MASTERDIS(master == MASTER_CANT) |
-		FW_HELLO_CMD_MASTERFORCE(master == MASTER_MUST) |
-		FW_HELLO_CMD_MBMASTER(master == MASTER_MUST ? mbox : 0xff) |
-		FW_HELLO_CMD_MBASYNCNOT(evt_mbox));
-
-	ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
-	if (ret == 0 && state) {
-		u32 v = ntohl(c.err_to_mbasyncnot);
-		if (v & FW_HELLO_CMD_INIT)
-			*state = DEV_STATE_INIT;
-		else if (v & FW_HELLO_CMD_ERR)
-			*state = DEV_STATE_ERR;
-		else
-			*state = DEV_STATE_UNINIT;
-	}
-	return ret;
-}
-
-/**
- *	t4_fw_bye - end communication with FW
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *
- *	Issues a command to terminate communication with FW.
- */
-int t4_fw_bye(struct adapter *adap, unsigned int mbox)
-{
-	struct fw_bye_cmd c;
-
-	INIT_CMD(c, BYE, WRITE);
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-}
-
-/**
- *	t4_init_cmd - ask FW to initialize the device
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *
- *	Issues a command to FW to partially initialize the device.  This
- *	performs initialization that generally doesn't depend on user input.
- */
-int t4_early_init(struct adapter *adap, unsigned int mbox)
-{
-	struct fw_initialize_cmd c;
-
-	INIT_CMD(c, INITIALIZE, WRITE);
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-}
-
-/**
- *	t4_fw_reset - issue a reset to FW
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@reset: specifies the type of reset to perform
- *
- *	Issues a reset command of the specified type to FW.
- */
-int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset)
-{
-	struct fw_reset_cmd c;
-
-	INIT_CMD(c, RESET, WRITE);
-	c.val = htonl(reset);
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-}
-
-/**
- *	t4_query_params - query FW or device parameters
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@pf: the PF
- *	@vf: the VF
- *	@nparams: the number of parameters
- *	@params: the parameter names
- *	@val: the parameter values
- *
- *	Reads the value of FW or device parameters.  Up to 7 parameters can be
- *	queried at once.
- */
-int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
-		    unsigned int vf, unsigned int nparams, const u32 *params,
-		    u32 *val)
-{
-	int i, ret;
-	struct fw_params_cmd c;
-	__be32 *p = &c.param[0].mnem;
-
-	if (nparams > 7)
-		return -EINVAL;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_vfn = htonl(FW_CMD_OP(FW_PARAMS_CMD) | FW_CMD_REQUEST |
-			    FW_CMD_READ | FW_PARAMS_CMD_PFN(pf) |
-			    FW_PARAMS_CMD_VFN(vf));
-	c.retval_len16 = htonl(FW_LEN16(c));
-	for (i = 0; i < nparams; i++, p += 2)
-		*p = htonl(*params++);
-
-	ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
-	if (ret == 0)
-		for (i = 0, p = &c.param[0].val; i < nparams; i++, p += 2)
-			*val++ = ntohl(*p);
-	return ret;
-}
-
-/**
- *	t4_set_params - sets FW or device parameters
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@pf: the PF
- *	@vf: the VF
- *	@nparams: the number of parameters
- *	@params: the parameter names
- *	@val: the parameter values
- *
- *	Sets the value of FW or device parameters.  Up to 7 parameters can be
- *	specified at once.
- */
-int t4_set_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
-		  unsigned int vf, unsigned int nparams, const u32 *params,
-		  const u32 *val)
-{
-	struct fw_params_cmd c;
-	__be32 *p = &c.param[0].mnem;
-
-	if (nparams > 7)
-		return -EINVAL;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_vfn = htonl(FW_CMD_OP(FW_PARAMS_CMD) | FW_CMD_REQUEST |
-			    FW_CMD_WRITE | FW_PARAMS_CMD_PFN(pf) |
-			    FW_PARAMS_CMD_VFN(vf));
-	c.retval_len16 = htonl(FW_LEN16(c));
-	while (nparams--) {
-		*p++ = htonl(*params++);
-		*p++ = htonl(*val++);
-	}
-
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-}
-
-/**
- *	t4_cfg_pfvf - configure PF/VF resource limits
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@pf: the PF being configured
- *	@vf: the VF being configured
- *	@txq: the max number of egress queues
- *	@txq_eth_ctrl: the max number of egress Ethernet or control queues
- *	@rxqi: the max number of interrupt-capable ingress queues
- *	@rxq: the max number of interruptless ingress queues
- *	@tc: the PCI traffic class
- *	@vi: the max number of virtual interfaces
- *	@cmask: the channel access rights mask for the PF/VF
- *	@pmask: the port access rights mask for the PF/VF
- *	@nexact: the maximum number of exact MPS filters
- *	@rcaps: read capabilities
- *	@wxcaps: write/execute capabilities
- *
- *	Configures resource limits and capabilities for a physical or virtual
- *	function.
- */
-int t4_cfg_pfvf(struct adapter *adap, unsigned int mbox, unsigned int pf,
-		unsigned int vf, unsigned int txq, unsigned int txq_eth_ctrl,
-		unsigned int rxqi, unsigned int rxq, unsigned int tc,
-		unsigned int vi, unsigned int cmask, unsigned int pmask,
-		unsigned int nexact, unsigned int rcaps, unsigned int wxcaps)
-{
-	struct fw_pfvf_cmd c;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_vfn = htonl(FW_CMD_OP(FW_PFVF_CMD) | FW_CMD_REQUEST |
-			    FW_CMD_WRITE | FW_PFVF_CMD_PFN(pf) |
-			    FW_PFVF_CMD_VFN(vf));
-	c.retval_len16 = htonl(FW_LEN16(c));
-	c.niqflint_niq = htonl(FW_PFVF_CMD_NIQFLINT(rxqi) |
-			       FW_PFVF_CMD_NIQ(rxq));
-	c.type_to_neq = htonl(FW_PFVF_CMD_CMASK(cmask) |
-			       FW_PFVF_CMD_PMASK(pmask) |
-			       FW_PFVF_CMD_NEQ(txq));
-	c.tc_to_nexactf = htonl(FW_PFVF_CMD_TC(tc) | FW_PFVF_CMD_NVI(vi) |
-				FW_PFVF_CMD_NEXACTF(nexact));
-	c.r_caps_to_nethctrl = htonl(FW_PFVF_CMD_R_CAPS(rcaps) |
-				     FW_PFVF_CMD_WX_CAPS(wxcaps) |
-				     FW_PFVF_CMD_NETHCTRL(txq_eth_ctrl));
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-}
-
-/**
- *	t4_alloc_vi - allocate a virtual interface
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@port: physical port associated with the VI
- *	@pf: the PF owning the VI
- *	@vf: the VF owning the VI
- *	@nmac: number of MAC addresses needed (1 to 5)
- *	@mac: the MAC addresses of the VI
- *	@rss_size: size of RSS table slice associated with this VI
- *
- *	Allocates a virtual interface for the given physical port.  If @mac is
- *	not %NULL it contains the MAC addresses of the VI as assigned by FW.
- *	@mac should be large enough to hold @nmac Ethernet addresses, they are
- *	stored consecutively so the space needed is @nmac * 6 bytes.
- *	Returns a negative error number or the non-negative VI id.
- */
-int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port,
-		unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac,
-		unsigned int *rss_size)
-{
-	int ret;
-	struct fw_vi_cmd c;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_vfn = htonl(FW_CMD_OP(FW_VI_CMD) | FW_CMD_REQUEST |
-			    FW_CMD_WRITE | FW_CMD_EXEC |
-			    FW_VI_CMD_PFN(pf) | FW_VI_CMD_VFN(vf));
-	c.alloc_to_len16 = htonl(FW_VI_CMD_ALLOC | FW_LEN16(c));
-	c.portid_pkd = FW_VI_CMD_PORTID(port);
-	c.nmac = nmac - 1;
-
-	ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
-	if (ret)
-		return ret;
-
-	if (mac) {
-		memcpy(mac, c.mac, sizeof(c.mac));
-		switch (nmac) {
-		case 5:
-			memcpy(mac + 24, c.nmac3, sizeof(c.nmac3));
-		case 4:
-			memcpy(mac + 18, c.nmac2, sizeof(c.nmac2));
-		case 3:
-			memcpy(mac + 12, c.nmac1, sizeof(c.nmac1));
-		case 2:
-			memcpy(mac + 6,  c.nmac0, sizeof(c.nmac0));
-		}
-	}
-	if (rss_size)
-		*rss_size = FW_VI_CMD_RSSSIZE_GET(ntohs(c.rsssize_pkd));
-	return FW_VI_CMD_VIID_GET(ntohs(c.type_viid));
-}
-
-/**
- *	t4_set_rxmode - set Rx properties of a virtual interface
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@viid: the VI id
- *	@mtu: the new MTU or -1
- *	@promisc: 1 to enable promiscuous mode, 0 to disable it, -1 no change
- *	@all_multi: 1 to enable all-multi mode, 0 to disable it, -1 no change
- *	@bcast: 1 to enable broadcast Rx, 0 to disable it, -1 no change
- *	@vlanex: 1 to enable HW VLAN extraction, 0 to disable it, -1 no change
- *	@sleep_ok: if true we may sleep while awaiting command completion
- *
- *	Sets Rx properties of a virtual interface.
- */
-int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid,
-		  int mtu, int promisc, int all_multi, int bcast, int vlanex,
-		  bool sleep_ok)
-{
-	struct fw_vi_rxmode_cmd c;
-
-	/* convert to FW values */
-	if (mtu < 0)
-		mtu = FW_RXMODE_MTU_NO_CHG;
-	if (promisc < 0)
-		promisc = FW_VI_RXMODE_CMD_PROMISCEN_MASK;
-	if (all_multi < 0)
-		all_multi = FW_VI_RXMODE_CMD_ALLMULTIEN_MASK;
-	if (bcast < 0)
-		bcast = FW_VI_RXMODE_CMD_BROADCASTEN_MASK;
-	if (vlanex < 0)
-		vlanex = FW_VI_RXMODE_CMD_VLANEXEN_MASK;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_viid = htonl(FW_CMD_OP(FW_VI_RXMODE_CMD) | FW_CMD_REQUEST |
-			     FW_CMD_WRITE | FW_VI_RXMODE_CMD_VIID(viid));
-	c.retval_len16 = htonl(FW_LEN16(c));
-	c.mtu_to_vlanexen = htonl(FW_VI_RXMODE_CMD_MTU(mtu) |
-				  FW_VI_RXMODE_CMD_PROMISCEN(promisc) |
-				  FW_VI_RXMODE_CMD_ALLMULTIEN(all_multi) |
-				  FW_VI_RXMODE_CMD_BROADCASTEN(bcast) |
-				  FW_VI_RXMODE_CMD_VLANEXEN(vlanex));
-	return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok);
-}
-
-/**
- *	t4_alloc_mac_filt - allocates exact-match filters for MAC addresses
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@viid: the VI id
- *	@free: if true any existing filters for this VI id are first removed
- *	@naddr: the number of MAC addresses to allocate filters for (up to 7)
- *	@addr: the MAC address(es)
- *	@idx: where to store the index of each allocated filter
- *	@hash: pointer to hash address filter bitmap
- *	@sleep_ok: call is allowed to sleep
- *
- *	Allocates an exact-match filter for each of the supplied addresses and
- *	sets it to the corresponding address.  If @idx is not %NULL it should
- *	have at least @naddr entries, each of which will be set to the index of
- *	the filter allocated for the corresponding MAC address.  If a filter
- *	could not be allocated for an address its index is set to 0xffff.
- *	If @hash is not %NULL addresses that fail to allocate an exact filter
- *	are hashed and update the hash filter bitmap pointed at by @hash.
- *
- *	Returns a negative error number or the number of filters allocated.
- */
-int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
-		      unsigned int viid, bool free, unsigned int naddr,
-		      const u8 **addr, u16 *idx, u64 *hash, bool sleep_ok)
-{
-	int i, ret;
-	struct fw_vi_mac_cmd c;
-	struct fw_vi_mac_exact *p;
-
-	if (naddr > 7)
-		return -EINVAL;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_viid = htonl(FW_CMD_OP(FW_VI_MAC_CMD) | FW_CMD_REQUEST |
-			     FW_CMD_WRITE | (free ? FW_CMD_EXEC : 0) |
-			     FW_VI_MAC_CMD_VIID(viid));
-	c.freemacs_to_len16 = htonl(FW_VI_MAC_CMD_FREEMACS(free) |
-				    FW_CMD_LEN16((naddr + 2) / 2));
-
-	for (i = 0, p = c.u.exact; i < naddr; i++, p++) {
-		p->valid_to_idx = htons(FW_VI_MAC_CMD_VALID |
-				      FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
-		memcpy(p->macaddr, addr[i], sizeof(p->macaddr));
-	}
-
-	ret = t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), &c, sleep_ok);
-	if (ret)
-		return ret;
-
-	for (i = 0, p = c.u.exact; i < naddr; i++, p++) {
-		u16 index = FW_VI_MAC_CMD_IDX_GET(ntohs(p->valid_to_idx));
-
-		if (idx)
-			idx[i] = index >= NEXACT_MAC ? 0xffff : index;
-		if (index < NEXACT_MAC)
-			ret++;
-		else if (hash)
-			*hash |= (1ULL << hash_mac_addr(addr[i]));
-	}
-	return ret;
-}
-
-/**
- *	t4_change_mac - modifies the exact-match filter for a MAC address
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@viid: the VI id
- *	@idx: index of existing filter for old value of MAC address, or -1
- *	@addr: the new MAC address value
- *	@persist: whether a new MAC allocation should be persistent
- *	@add_smt: if true also add the address to the HW SMT
- *
- *	Modifies an exact-match filter and sets it to the new MAC address.
- *	Note that in general it is not possible to modify the value of a given
- *	filter so the generic way to modify an address filter is to free the one
- *	being used by the old address value and allocate a new filter for the
- *	new address value.  @idx can be -1 if the address is a new addition.
- *
- *	Returns a negative error number or the index of the filter with the new
- *	MAC value.
- */
-int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid,
-		  int idx, const u8 *addr, bool persist, bool add_smt)
-{
-	int ret, mode;
-	struct fw_vi_mac_cmd c;
-	struct fw_vi_mac_exact *p = c.u.exact;
-
-	if (idx < 0)                             /* new allocation */
-		idx = persist ? FW_VI_MAC_ADD_PERSIST_MAC : FW_VI_MAC_ADD_MAC;
-	mode = add_smt ? FW_VI_MAC_SMT_AND_MPSTCAM : FW_VI_MAC_MPS_TCAM_ENTRY;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_viid = htonl(FW_CMD_OP(FW_VI_MAC_CMD) | FW_CMD_REQUEST |
-			     FW_CMD_WRITE | FW_VI_MAC_CMD_VIID(viid));
-	c.freemacs_to_len16 = htonl(FW_CMD_LEN16(1));
-	p->valid_to_idx = htons(FW_VI_MAC_CMD_VALID |
-				FW_VI_MAC_CMD_SMAC_RESULT(mode) |
-				FW_VI_MAC_CMD_IDX(idx));
-	memcpy(p->macaddr, addr, sizeof(p->macaddr));
-
-	ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
-	if (ret == 0) {
-		ret = FW_VI_MAC_CMD_IDX_GET(ntohs(p->valid_to_idx));
-		if (ret >= NEXACT_MAC)
-			ret = -ENOMEM;
-	}
-	return ret;
-}
-
-/**
- *	t4_set_addr_hash - program the MAC inexact-match hash filter
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@viid: the VI id
- *	@ucast: whether the hash filter should also match unicast addresses
- *	@vec: the value to be written to the hash filter
- *	@sleep_ok: call is allowed to sleep
- *
- *	Sets the 64-bit inexact-match hash filter for a virtual interface.
- */
-int t4_set_addr_hash(struct adapter *adap, unsigned int mbox, unsigned int viid,
-		     bool ucast, u64 vec, bool sleep_ok)
-{
-	struct fw_vi_mac_cmd c;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_viid = htonl(FW_CMD_OP(FW_VI_MAC_CMD) | FW_CMD_REQUEST |
-			     FW_CMD_WRITE | FW_VI_ENABLE_CMD_VIID(viid));
-	c.freemacs_to_len16 = htonl(FW_VI_MAC_CMD_HASHVECEN |
-				    FW_VI_MAC_CMD_HASHUNIEN(ucast) |
-				    FW_CMD_LEN16(1));
-	c.u.hash.hashvec = cpu_to_be64(vec);
-	return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok);
-}
-
-/**
- *	t4_enable_vi - enable/disable a virtual interface
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@viid: the VI id
- *	@rx_en: 1=enable Rx, 0=disable Rx
- *	@tx_en: 1=enable Tx, 0=disable Tx
- *
- *	Enables/disables a virtual interface.
- */
-int t4_enable_vi(struct adapter *adap, unsigned int mbox, unsigned int viid,
-		 bool rx_en, bool tx_en)
-{
-	struct fw_vi_enable_cmd c;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST |
-			     FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid));
-	c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_IEN(rx_en) |
-			       FW_VI_ENABLE_CMD_EEN(tx_en) | FW_LEN16(c));
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-}
-
-/**
- *	t4_identify_port - identify a VI's port by blinking its LED
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@viid: the VI id
- *	@nblinks: how many times to blink LED at 2.5 Hz
- *
- *	Identifies a VI's port by blinking its LED.
- */
-int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid,
-		     unsigned int nblinks)
-{
-	struct fw_vi_enable_cmd c;
-
-	c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST |
-			     FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid));
-	c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_LED | FW_LEN16(c));
-	c.blinkdur = htons(nblinks);
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-}
-
-/**
- *	t4_iq_free - free an ingress queue and its FLs
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@pf: the PF owning the queues
- *	@vf: the VF owning the queues
- *	@iqtype: the ingress queue type
- *	@iqid: ingress queue id
- *	@fl0id: FL0 queue id or 0xffff if no attached FL0
- *	@fl1id: FL1 queue id or 0xffff if no attached FL1
- *
- *	Frees an ingress queue and its associated FLs, if any.
- */
-int t4_iq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
-	       unsigned int vf, unsigned int iqtype, unsigned int iqid,
-	       unsigned int fl0id, unsigned int fl1id)
-{
-	struct fw_iq_cmd c;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_vfn = htonl(FW_CMD_OP(FW_IQ_CMD) | FW_CMD_REQUEST |
-			    FW_CMD_EXEC | FW_IQ_CMD_PFN(pf) |
-			    FW_IQ_CMD_VFN(vf));
-	c.alloc_to_len16 = htonl(FW_IQ_CMD_FREE | FW_LEN16(c));
-	c.type_to_iqandstindex = htonl(FW_IQ_CMD_TYPE(iqtype));
-	c.iqid = htons(iqid);
-	c.fl0id = htons(fl0id);
-	c.fl1id = htons(fl1id);
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-}
-
-/**
- *	t4_eth_eq_free - free an Ethernet egress queue
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@pf: the PF owning the queue
- *	@vf: the VF owning the queue
- *	@eqid: egress queue id
- *
- *	Frees an Ethernet egress queue.
- */
-int t4_eth_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
-		   unsigned int vf, unsigned int eqid)
-{
-	struct fw_eq_eth_cmd c;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_vfn = htonl(FW_CMD_OP(FW_EQ_ETH_CMD) | FW_CMD_REQUEST |
-			    FW_CMD_EXEC | FW_EQ_ETH_CMD_PFN(pf) |
-			    FW_EQ_ETH_CMD_VFN(vf));
-	c.alloc_to_len16 = htonl(FW_EQ_ETH_CMD_FREE | FW_LEN16(c));
-	c.eqid_pkd = htonl(FW_EQ_ETH_CMD_EQID(eqid));
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-}
-
-/**
- *	t4_ctrl_eq_free - free a control egress queue
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@pf: the PF owning the queue
- *	@vf: the VF owning the queue
- *	@eqid: egress queue id
- *
- *	Frees a control egress queue.
- */
-int t4_ctrl_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
-		    unsigned int vf, unsigned int eqid)
-{
-	struct fw_eq_ctrl_cmd c;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_vfn = htonl(FW_CMD_OP(FW_EQ_CTRL_CMD) | FW_CMD_REQUEST |
-			    FW_CMD_EXEC | FW_EQ_CTRL_CMD_PFN(pf) |
-			    FW_EQ_CTRL_CMD_VFN(vf));
-	c.alloc_to_len16 = htonl(FW_EQ_CTRL_CMD_FREE | FW_LEN16(c));
-	c.cmpliqid_eqid = htonl(FW_EQ_CTRL_CMD_EQID(eqid));
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-}
-
-/**
- *	t4_ofld_eq_free - free an offload egress queue
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@pf: the PF owning the queue
- *	@vf: the VF owning the queue
- *	@eqid: egress queue id
- *
- *	Frees a control egress queue.
- */
-int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
-		    unsigned int vf, unsigned int eqid)
-{
-	struct fw_eq_ofld_cmd c;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_vfn = htonl(FW_CMD_OP(FW_EQ_OFLD_CMD) | FW_CMD_REQUEST |
-			    FW_CMD_EXEC | FW_EQ_OFLD_CMD_PFN(pf) |
-			    FW_EQ_OFLD_CMD_VFN(vf));
-	c.alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_FREE | FW_LEN16(c));
-	c.eqid_pkd = htonl(FW_EQ_OFLD_CMD_EQID(eqid));
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-}
-
-/**
- *	t4_handle_fw_rpl - process a FW reply message
- *	@adap: the adapter
- *	@rpl: start of the FW message
- *
- *	Processes a FW message, such as link state change messages.
- */
-int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
-{
-	u8 opcode = *(const u8 *)rpl;
-
-	if (opcode == FW_PORT_CMD) {    /* link/module state change message */
-		int speed = 0, fc = 0;
-		const struct fw_port_cmd *p = (void *)rpl;
-		int chan = FW_PORT_CMD_PORTID_GET(ntohl(p->op_to_portid));
-		int port = adap->chan_map[chan];
-		struct port_info *pi = adap2pinfo(adap, port);
-		struct link_config *lc = &pi->link_cfg;
-		u32 stat = ntohl(p->u.info.lstatus_to_modtype);
-		int link_ok = (stat & FW_PORT_CMD_LSTATUS) != 0;
-		u32 mod = FW_PORT_CMD_MODTYPE_GET(stat);
-
-		if (stat & FW_PORT_CMD_RXPAUSE)
-			fc |= PAUSE_RX;
-		if (stat & FW_PORT_CMD_TXPAUSE)
-			fc |= PAUSE_TX;
-		if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100M))
-			speed = SPEED_100;
-		else if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_1G))
-			speed = SPEED_1000;
-		else if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G))
-			speed = SPEED_10000;
-
-		if (link_ok != lc->link_ok || speed != lc->speed ||
-		    fc != lc->fc) {                    /* something changed */
-			lc->link_ok = link_ok;
-			lc->speed = speed;
-			lc->fc = fc;
-			t4_os_link_changed(adap, port, link_ok);
-		}
-		if (mod != pi->mod_type) {
-			pi->mod_type = mod;
-			t4_os_portmod_changed(adap, port);
-		}
-	}
-	return 0;
-}
-
-static void __devinit get_pci_mode(struct adapter *adapter,
-				   struct pci_params *p)
-{
-	u16 val;
-	u32 pcie_cap = pci_pcie_cap(adapter->pdev);
-
-	if (pcie_cap) {
-		pci_read_config_word(adapter->pdev, pcie_cap + PCI_EXP_LNKSTA,
-				     &val);
-		p->speed = val & PCI_EXP_LNKSTA_CLS;
-		p->width = (val & PCI_EXP_LNKSTA_NLW) >> 4;
-	}
-}
-
-/**
- *	init_link_config - initialize a link's SW state
- *	@lc: structure holding the link state
- *	@caps: link capabilities
- *
- *	Initializes the SW state maintained for each link, including the link's
- *	capabilities and default speed/flow-control/autonegotiation settings.
- */
-static void __devinit init_link_config(struct link_config *lc,
-				       unsigned int caps)
-{
-	lc->supported = caps;
-	lc->requested_speed = 0;
-	lc->speed = 0;
-	lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX;
-	if (lc->supported & FW_PORT_CAP_ANEG) {
-		lc->advertising = lc->supported & ADVERT_MASK;
-		lc->autoneg = AUTONEG_ENABLE;
-		lc->requested_fc |= PAUSE_AUTONEG;
-	} else {
-		lc->advertising = 0;
-		lc->autoneg = AUTONEG_DISABLE;
-	}
-}
-
-int t4_wait_dev_ready(struct adapter *adap)
-{
-	if (t4_read_reg(adap, PL_WHOAMI) != 0xffffffff)
-		return 0;
-	msleep(500);
-	return t4_read_reg(adap, PL_WHOAMI) != 0xffffffff ? 0 : -EIO;
-}
-
-static int __devinit get_flash_params(struct adapter *adap)
-{
-	int ret;
-	u32 info;
-
-	ret = sf1_write(adap, 1, 1, 0, SF_RD_ID);
-	if (!ret)
-		ret = sf1_read(adap, 3, 0, 1, &info);
-	t4_write_reg(adap, SF_OP, 0);                    /* unlock SF */
-	if (ret)
-		return ret;
-
-	if ((info & 0xff) != 0x20)             /* not a Numonix flash */
-		return -EINVAL;
-	info >>= 16;                           /* log2 of size */
-	if (info >= 0x14 && info < 0x18)
-		adap->params.sf_nsec = 1 << (info - 16);
-	else if (info == 0x18)
-		adap->params.sf_nsec = 64;
-	else
-		return -EINVAL;
-	adap->params.sf_size = 1 << info;
-	adap->params.sf_fw_start =
-		t4_read_reg(adap, CIM_BOOT_CFG) & BOOTADDR_MASK;
-	return 0;
-}
-
-/**
- *	t4_prep_adapter - prepare SW and HW for operation
- *	@adapter: the adapter
- *	@reset: if true perform a HW reset
- *
- *	Initialize adapter SW state for the various HW modules, set initial
- *	values for some adapter tunables, take PHYs out of reset, and
- *	initialize the MDIO interface.
- */
-int __devinit t4_prep_adapter(struct adapter *adapter)
-{
-	int ret;
-
-	ret = t4_wait_dev_ready(adapter);
-	if (ret < 0)
-		return ret;
-
-	get_pci_mode(adapter, &adapter->params.pci);
-	adapter->params.rev = t4_read_reg(adapter, PL_REV);
-
-	ret = get_flash_params(adapter);
-	if (ret < 0) {
-		dev_err(adapter->pdev_dev, "error %d identifying flash\n", ret);
-		return ret;
-	}
-
-	ret = get_vpd_params(adapter, &adapter->params.vpd);
-	if (ret < 0)
-		return ret;
-
-	init_cong_ctrl(adapter->params.a_wnd, adapter->params.b_wnd);
-
-	/*
-	 * Default port for debugging in case we can't reach FW.
-	 */
-	adapter->params.nports = 1;
-	adapter->params.portvec = 1;
-	return 0;
-}
-
-int __devinit t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
-{
-	u8 addr[6];
-	int ret, i, j = 0;
-	struct fw_port_cmd c;
-	struct fw_rss_vi_config_cmd rvc;
-
-	memset(&c, 0, sizeof(c));
-	memset(&rvc, 0, sizeof(rvc));
-
-	for_each_port(adap, i) {
-		unsigned int rss_size;
-		struct port_info *p = adap2pinfo(adap, i);
-
-		while ((adap->params.portvec & (1 << j)) == 0)
-			j++;
-
-		c.op_to_portid = htonl(FW_CMD_OP(FW_PORT_CMD) |
-				       FW_CMD_REQUEST | FW_CMD_READ |
-				       FW_PORT_CMD_PORTID(j));
-		c.action_to_len16 = htonl(
-			FW_PORT_CMD_ACTION(FW_PORT_ACTION_GET_PORT_INFO) |
-			FW_LEN16(c));
-		ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
-		if (ret)
-			return ret;
-
-		ret = t4_alloc_vi(adap, mbox, j, pf, vf, 1, addr, &rss_size);
-		if (ret < 0)
-			return ret;
-
-		p->viid = ret;
-		p->tx_chan = j;
-		p->lport = j;
-		p->rss_size = rss_size;
-		memcpy(adap->port[i]->dev_addr, addr, ETH_ALEN);
-		memcpy(adap->port[i]->perm_addr, addr, ETH_ALEN);
-		adap->port[i]->dev_id = j;
-
-		ret = ntohl(c.u.info.lstatus_to_modtype);
-		p->mdio_addr = (ret & FW_PORT_CMD_MDIOCAP) ?
-			FW_PORT_CMD_MDIOADDR_GET(ret) : -1;
-		p->port_type = FW_PORT_CMD_PTYPE_GET(ret);
-		p->mod_type = FW_PORT_MOD_TYPE_NA;
-
-		rvc.op_to_viid = htonl(FW_CMD_OP(FW_RSS_VI_CONFIG_CMD) |
-				       FW_CMD_REQUEST | FW_CMD_READ |
-				       FW_RSS_VI_CONFIG_CMD_VIID(p->viid));
-		rvc.retval_len16 = htonl(FW_LEN16(rvc));
-		ret = t4_wr_mbox(adap, mbox, &rvc, sizeof(rvc), &rvc);
-		if (ret)
-			return ret;
-		p->rss_mode = ntohl(rvc.u.basicvirtual.defaultq_to_udpen);
-
-		init_link_config(&p->link_cfg, ntohs(c.u.info.pcap));
-		j++;
-	}
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4/t4_hw.h linux-libre-3.2-gnu/drivers/net/cxgb4/t4_hw.h
--- linux-libre-3.1-gnu/drivers/net/cxgb4/t4_hw.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4/t4_hw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,140 +0,0 @@
-/*
- * This file is part of the Chelsio T4 Ethernet driver for Linux.
- *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __T4_HW_H
-#define __T4_HW_H
-
-#include <linux/types.h>
-
-enum {
-	NCHAN          = 4,     /* # of HW channels */
-	MAX_MTU        = 9600,  /* max MAC MTU, excluding header + FCS */
-	EEPROMSIZE     = 17408, /* Serial EEPROM physical size */
-	EEPROMVSIZE    = 32768, /* Serial EEPROM virtual address space size */
-	EEPROMPFSIZE   = 1024,  /* EEPROM writable area size for PFn, n>0 */
-	RSS_NENTRIES   = 2048,  /* # of entries in RSS mapping table */
-	TCB_SIZE       = 128,   /* TCB size */
-	NMTUS          = 16,    /* size of MTU table */
-	NCCTRL_WIN     = 32,    /* # of congestion control windows */
-	NEXACT_MAC     = 336,   /* # of exact MAC address filters */
-	L2T_SIZE       = 4096,  /* # of L2T entries */
-	MBOX_LEN       = 64,    /* mailbox size in bytes */
-	TRACE_LEN      = 112,   /* length of trace data and mask */
-	FILTER_OPT_LEN = 36,    /* filter tuple width for optional components */
-	NWOL_PAT       = 8,     /* # of WoL patterns */
-	WOL_PAT_LEN    = 128,   /* length of WoL patterns */
-};
-
-enum {
-	SF_PAGE_SIZE = 256,           /* serial flash page size */
-};
-
-enum { RSP_TYPE_FLBUF, RSP_TYPE_CPL, RSP_TYPE_INTR }; /* response entry types */
-
-enum { MBOX_OWNER_NONE, MBOX_OWNER_FW, MBOX_OWNER_DRV };    /* mailbox owners */
-
-enum {
-	SGE_MAX_WR_LEN = 512,     /* max WR size in bytes */
-	SGE_NTIMERS = 6,          /* # of interrupt holdoff timer values */
-	SGE_NCOUNTERS = 4,        /* # of interrupt packet counter values */
-
-	SGE_TIMER_RSTRT_CNTR = 6, /* restart RX packet threshold counter */
-	SGE_TIMER_UPD_CIDX = 7,   /* update cidx only */
-
-	SGE_EQ_IDXSIZE = 64,      /* egress queue pidx/cidx unit size */
-
-	SGE_INTRDST_PCI = 0,      /* interrupt destination is PCI-E */
-	SGE_INTRDST_IQ = 1,       /*   destination is an ingress queue */
-
-	SGE_UPDATEDEL_NONE = 0,   /* ingress queue pidx update delivery */
-	SGE_UPDATEDEL_INTR = 1,   /*   interrupt */
-	SGE_UPDATEDEL_STPG = 2,   /*   status page */
-	SGE_UPDATEDEL_BOTH = 3,   /*   interrupt and status page */
-
-	SGE_HOSTFCMODE_NONE = 0,  /* egress queue cidx updates */
-	SGE_HOSTFCMODE_IQ = 1,    /*   sent to ingress queue */
-	SGE_HOSTFCMODE_STPG = 2,  /*   sent to status page */
-	SGE_HOSTFCMODE_BOTH = 3,  /*   ingress queue and status page */
-
-	SGE_FETCHBURSTMIN_16B = 0,/* egress queue descriptor fetch minimum */
-	SGE_FETCHBURSTMIN_32B = 1,
-	SGE_FETCHBURSTMIN_64B = 2,
-	SGE_FETCHBURSTMIN_128B = 3,
-
-	SGE_FETCHBURSTMAX_64B = 0,/* egress queue descriptor fetch maximum */
-	SGE_FETCHBURSTMAX_128B = 1,
-	SGE_FETCHBURSTMAX_256B = 2,
-	SGE_FETCHBURSTMAX_512B = 3,
-
-	SGE_CIDXFLUSHTHRESH_1 = 0,/* egress queue cidx flush threshold */
-	SGE_CIDXFLUSHTHRESH_2 = 1,
-	SGE_CIDXFLUSHTHRESH_4 = 2,
-	SGE_CIDXFLUSHTHRESH_8 = 3,
-	SGE_CIDXFLUSHTHRESH_16 = 4,
-	SGE_CIDXFLUSHTHRESH_32 = 5,
-	SGE_CIDXFLUSHTHRESH_64 = 6,
-	SGE_CIDXFLUSHTHRESH_128 = 7,
-
-	SGE_INGPADBOUNDARY_SHIFT = 5,/* ingress queue pad boundary */
-};
-
-struct sge_qstat {                /* data written to SGE queue status entries */
-	__be32 qid;
-	__be16 cidx;
-	__be16 pidx;
-};
-
-/*
- * Structure for last 128 bits of response descriptors
- */
-struct rsp_ctrl {
-	__be32 hdrbuflen_pidx;
-	__be32 pldbuflen_qid;
-	union {
-		u8 type_gen;
-		__be64 last_flit;
-	};
-};
-
-#define RSPD_NEWBUF 0x80000000U
-#define RSPD_LEN(x) (((x) >> 0) & 0x7fffffffU)
-#define RSPD_QID(x) RSPD_LEN(x)
-
-#define RSPD_GEN(x)  ((x) >> 7)
-#define RSPD_TYPE(x) (((x) >> 4) & 3)
-
-#define QINTR_CNT_EN       0x1
-#define QINTR_TIMER_IDX(x) ((x) << 1)
-#define QINTR_TIMER_IDX_GET(x) (((x) >> 1) & 0x7)
-#endif /* __T4_HW_H */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4/t4_msg.h linux-libre-3.2-gnu/drivers/net/cxgb4/t4_msg.h
--- linux-libre-3.1-gnu/drivers/net/cxgb4/t4_msg.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4/t4_msg.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,678 +0,0 @@
-/*
- * This file is part of the Chelsio T4 Ethernet driver for Linux.
- *
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __T4_MSG_H
-#define __T4_MSG_H
-
-#include <linux/types.h>
-
-enum {
-	CPL_PASS_OPEN_REQ     = 0x1,
-	CPL_PASS_ACCEPT_RPL   = 0x2,
-	CPL_ACT_OPEN_REQ      = 0x3,
-	CPL_SET_TCB_FIELD     = 0x5,
-	CPL_GET_TCB           = 0x6,
-	CPL_CLOSE_CON_REQ     = 0x8,
-	CPL_CLOSE_LISTSRV_REQ = 0x9,
-	CPL_ABORT_REQ         = 0xA,
-	CPL_ABORT_RPL         = 0xB,
-	CPL_RX_DATA_ACK       = 0xD,
-	CPL_TX_PKT            = 0xE,
-	CPL_L2T_WRITE_REQ     = 0x12,
-	CPL_TID_RELEASE       = 0x1A,
-
-	CPL_CLOSE_LISTSRV_RPL = 0x20,
-	CPL_L2T_WRITE_RPL     = 0x23,
-	CPL_PASS_OPEN_RPL     = 0x24,
-	CPL_ACT_OPEN_RPL      = 0x25,
-	CPL_PEER_CLOSE        = 0x26,
-	CPL_ABORT_REQ_RSS     = 0x2B,
-	CPL_ABORT_RPL_RSS     = 0x2D,
-
-	CPL_CLOSE_CON_RPL     = 0x32,
-	CPL_ISCSI_HDR         = 0x33,
-	CPL_RDMA_CQE          = 0x35,
-	CPL_RDMA_CQE_READ_RSP = 0x36,
-	CPL_RDMA_CQE_ERR      = 0x37,
-	CPL_RX_DATA           = 0x39,
-	CPL_SET_TCB_RPL       = 0x3A,
-	CPL_RX_PKT            = 0x3B,
-	CPL_RX_DDP_COMPLETE   = 0x3F,
-
-	CPL_ACT_ESTABLISH     = 0x40,
-	CPL_PASS_ESTABLISH    = 0x41,
-	CPL_RX_DATA_DDP       = 0x42,
-	CPL_PASS_ACCEPT_REQ   = 0x44,
-
-	CPL_RDMA_READ_REQ     = 0x60,
-
-	CPL_PASS_OPEN_REQ6    = 0x81,
-	CPL_ACT_OPEN_REQ6     = 0x83,
-
-	CPL_RDMA_TERMINATE    = 0xA2,
-	CPL_RDMA_WRITE        = 0xA4,
-	CPL_SGE_EGR_UPDATE    = 0xA5,
-
-	CPL_TRACE_PKT         = 0xB0,
-
-	CPL_FW4_MSG           = 0xC0,
-	CPL_FW4_PLD           = 0xC1,
-	CPL_FW4_ACK           = 0xC3,
-
-	CPL_FW6_MSG           = 0xE0,
-	CPL_FW6_PLD           = 0xE1,
-	CPL_TX_PKT_LSO        = 0xED,
-	CPL_TX_PKT_XT         = 0xEE,
-
-	NUM_CPL_CMDS
-};
-
-enum CPL_error {
-	CPL_ERR_NONE               = 0,
-	CPL_ERR_TCAM_FULL          = 3,
-	CPL_ERR_BAD_LENGTH         = 15,
-	CPL_ERR_BAD_ROUTE          = 18,
-	CPL_ERR_CONN_RESET         = 20,
-	CPL_ERR_CONN_EXIST_SYNRECV = 21,
-	CPL_ERR_CONN_EXIST         = 22,
-	CPL_ERR_ARP_MISS           = 23,
-	CPL_ERR_BAD_SYN            = 24,
-	CPL_ERR_CONN_TIMEDOUT      = 30,
-	CPL_ERR_XMIT_TIMEDOUT      = 31,
-	CPL_ERR_PERSIST_TIMEDOUT   = 32,
-	CPL_ERR_FINWAIT2_TIMEDOUT  = 33,
-	CPL_ERR_KEEPALIVE_TIMEDOUT = 34,
-	CPL_ERR_RTX_NEG_ADVICE     = 35,
-	CPL_ERR_PERSIST_NEG_ADVICE = 36,
-	CPL_ERR_ABORT_FAILED       = 42,
-	CPL_ERR_IWARP_FLM          = 50,
-};
-
-enum {
-	ULP_MODE_NONE          = 0,
-	ULP_MODE_ISCSI         = 2,
-	ULP_MODE_RDMA          = 4,
-	ULP_MODE_TCPDDP	       = 5,
-	ULP_MODE_FCOE          = 6,
-};
-
-enum {
-	ULP_CRC_HEADER = 1 << 0,
-	ULP_CRC_DATA   = 1 << 1
-};
-
-enum {
-	CPL_ABORT_SEND_RST = 0,
-	CPL_ABORT_NO_RST,
-};
-
-enum {                     /* TX_PKT_XT checksum types */
-	TX_CSUM_TCP    = 0,
-	TX_CSUM_UDP    = 1,
-	TX_CSUM_CRC16  = 4,
-	TX_CSUM_CRC32  = 5,
-	TX_CSUM_CRC32C = 6,
-	TX_CSUM_FCOE   = 7,
-	TX_CSUM_TCPIP  = 8,
-	TX_CSUM_UDPIP  = 9,
-	TX_CSUM_TCPIP6 = 10,
-	TX_CSUM_UDPIP6 = 11,
-	TX_CSUM_IP     = 12,
-};
-
-union opcode_tid {
-	__be32 opcode_tid;
-	u8 opcode;
-};
-
-#define CPL_OPCODE(x) ((x) << 24)
-#define MK_OPCODE_TID(opcode, tid) (CPL_OPCODE(opcode) | (tid))
-#define OPCODE_TID(cmd) ((cmd)->ot.opcode_tid)
-#define GET_TID(cmd) (ntohl(OPCODE_TID(cmd)) & 0xFFFFFF)
-
-/* partitioning of TID fields that also carry a queue id */
-#define GET_TID_TID(x) ((x) & 0x3fff)
-#define GET_TID_QID(x) (((x) >> 14) & 0x3ff)
-#define TID_QID(x)     ((x) << 14)
-
-struct rss_header {
-	u8 opcode;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8 channel:2;
-	u8 filter_hit:1;
-	u8 filter_tid:1;
-	u8 hash_type:2;
-	u8 ipv6:1;
-	u8 send2fw:1;
-#else
-	u8 send2fw:1;
-	u8 ipv6:1;
-	u8 hash_type:2;
-	u8 filter_tid:1;
-	u8 filter_hit:1;
-	u8 channel:2;
-#endif
-	__be16 qid;
-	__be32 hash_val;
-};
-
-struct work_request_hdr {
-	__be32 wr_hi;
-	__be32 wr_mid;
-	__be64 wr_lo;
-};
-
-#define WR_HDR struct work_request_hdr wr
-
-struct cpl_pass_open_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__be16 local_port;
-	__be16 peer_port;
-	__be32 local_ip;
-	__be32 peer_ip;
-	__be64 opt0;
-#define TX_CHAN(x)    ((x) << 2)
-#define DELACK(x)     ((x) << 5)
-#define ULP_MODE(x)   ((x) << 8)
-#define RCV_BUFSIZ(x) ((x) << 12)
-#define DSCP(x)       ((x) << 22)
-#define SMAC_SEL(x)   ((u64)(x) << 28)
-#define L2T_IDX(x)    ((u64)(x) << 36)
-#define NAGLE(x)      ((u64)(x) << 49)
-#define WND_SCALE(x)  ((u64)(x) << 50)
-#define KEEP_ALIVE(x) ((u64)(x) << 54)
-#define MSS_IDX(x)    ((u64)(x) << 60)
-	__be64 opt1;
-#define SYN_RSS_ENABLE   (1 << 0)
-#define SYN_RSS_QUEUE(x) ((x) << 2)
-#define CONN_POLICY_ASK  (1 << 22)
-};
-
-struct cpl_pass_open_req6 {
-	WR_HDR;
-	union opcode_tid ot;
-	__be16 local_port;
-	__be16 peer_port;
-	__be64 local_ip_hi;
-	__be64 local_ip_lo;
-	__be64 peer_ip_hi;
-	__be64 peer_ip_lo;
-	__be64 opt0;
-	__be64 opt1;
-};
-
-struct cpl_pass_open_rpl {
-	union opcode_tid ot;
-	u8 rsvd[3];
-	u8 status;
-};
-
-struct cpl_pass_accept_rpl {
-	WR_HDR;
-	union opcode_tid ot;
-	__be32 opt2;
-#define RSS_QUEUE(x)         ((x) << 0)
-#define RSS_QUEUE_VALID      (1 << 10)
-#define RX_COALESCE_VALID(x) ((x) << 11)
-#define RX_COALESCE(x)       ((x) << 12)
-#define TX_QUEUE(x)          ((x) << 23)
-#define RX_CHANNEL(x)        ((x) << 26)
-#define WND_SCALE_EN(x)      ((x) << 28)
-#define TSTAMPS_EN(x)        ((x) << 29)
-#define SACK_EN(x)           ((x) << 30)
-	__be64 opt0;
-};
-
-struct cpl_act_open_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__be16 local_port;
-	__be16 peer_port;
-	__be32 local_ip;
-	__be32 peer_ip;
-	__be64 opt0;
-	__be32 params;
-	__be32 opt2;
-};
-
-struct cpl_act_open_req6 {
-	WR_HDR;
-	union opcode_tid ot;
-	__be16 local_port;
-	__be16 peer_port;
-	__be64 local_ip_hi;
-	__be64 local_ip_lo;
-	__be64 peer_ip_hi;
-	__be64 peer_ip_lo;
-	__be64 opt0;
-	__be32 params;
-	__be32 opt2;
-};
-
-struct cpl_act_open_rpl {
-	union opcode_tid ot;
-	__be32 atid_status;
-#define GET_AOPEN_STATUS(x) ((x) & 0xff)
-#define GET_AOPEN_ATID(x)   (((x) >> 8) & 0xffffff)
-};
-
-struct cpl_pass_establish {
-	union opcode_tid ot;
-	__be32 rsvd;
-	__be32 tos_stid;
-#define GET_POPEN_TID(x) ((x) & 0xffffff)
-#define GET_POPEN_TOS(x) (((x) >> 24) & 0xff)
-	__be16 mac_idx;
-	__be16 tcp_opt;
-#define GET_TCPOPT_WSCALE_OK(x)  (((x) >> 5) & 1)
-#define GET_TCPOPT_SACK(x)       (((x) >> 6) & 1)
-#define GET_TCPOPT_TSTAMP(x)     (((x) >> 7) & 1)
-#define GET_TCPOPT_SND_WSCALE(x) (((x) >> 8) & 0xf)
-#define GET_TCPOPT_MSS(x)        (((x) >> 12) & 0xf)
-	__be32 snd_isn;
-	__be32 rcv_isn;
-};
-
-struct cpl_act_establish {
-	union opcode_tid ot;
-	__be32 rsvd;
-	__be32 tos_atid;
-	__be16 mac_idx;
-	__be16 tcp_opt;
-	__be32 snd_isn;
-	__be32 rcv_isn;
-};
-
-struct cpl_get_tcb {
-	WR_HDR;
-	union opcode_tid ot;
-	__be16 reply_ctrl;
-#define QUEUENO(x)    ((x) << 0)
-#define REPLY_CHAN(x) ((x) << 14)
-#define NO_REPLY(x)   ((x) << 15)
-	__be16 cookie;
-};
-
-struct cpl_set_tcb_field {
-	WR_HDR;
-	union opcode_tid ot;
-	__be16 reply_ctrl;
-	__be16 word_cookie;
-#define TCB_WORD(x)   ((x) << 0)
-#define TCB_COOKIE(x) ((x) << 5)
-	__be64 mask;
-	__be64 val;
-};
-
-struct cpl_set_tcb_rpl {
-	union opcode_tid ot;
-	__be16 rsvd;
-	u8 cookie;
-	u8 status;
-	__be64 oldval;
-};
-
-struct cpl_close_con_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__be32 rsvd;
-};
-
-struct cpl_close_con_rpl {
-	union opcode_tid ot;
-	u8 rsvd[3];
-	u8 status;
-	__be32 snd_nxt;
-	__be32 rcv_nxt;
-};
-
-struct cpl_close_listsvr_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__be16 reply_ctrl;
-#define LISTSVR_IPV6 (1 << 14)
-	__be16 rsvd;
-};
-
-struct cpl_close_listsvr_rpl {
-	union opcode_tid ot;
-	u8 rsvd[3];
-	u8 status;
-};
-
-struct cpl_abort_req_rss {
-	union opcode_tid ot;
-	u8 rsvd[3];
-	u8 status;
-};
-
-struct cpl_abort_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__be32 rsvd0;
-	u8 rsvd1;
-	u8 cmd;
-	u8 rsvd2[6];
-};
-
-struct cpl_abort_rpl_rss {
-	union opcode_tid ot;
-	u8 rsvd[3];
-	u8 status;
-};
-
-struct cpl_abort_rpl {
-	WR_HDR;
-	union opcode_tid ot;
-	__be32 rsvd0;
-	u8 rsvd1;
-	u8 cmd;
-	u8 rsvd2[6];
-};
-
-struct cpl_peer_close {
-	union opcode_tid ot;
-	__be32 rcv_nxt;
-};
-
-struct cpl_tid_release {
-	WR_HDR;
-	union opcode_tid ot;
-	__be32 rsvd;
-};
-
-struct cpl_tx_pkt_core {
-	__be32 ctrl0;
-#define TXPKT_VF(x)        ((x) << 0)
-#define TXPKT_PF(x)        ((x) << 8)
-#define TXPKT_VF_VLD       (1 << 11)
-#define TXPKT_OVLAN_IDX(x) ((x) << 12)
-#define TXPKT_INTF(x)      ((x) << 16)
-#define TXPKT_INS_OVLAN    (1 << 21)
-#define TXPKT_OPCODE(x)    ((x) << 24)
-	__be16 pack;
-	__be16 len;
-	__be64 ctrl1;
-#define TXPKT_CSUM_END(x)   ((x) << 12)
-#define TXPKT_CSUM_START(x) ((x) << 20)
-#define TXPKT_IPHDR_LEN(x)  ((u64)(x) << 20)
-#define TXPKT_CSUM_LOC(x)   ((u64)(x) << 30)
-#define TXPKT_ETHHDR_LEN(x) ((u64)(x) << 34)
-#define TXPKT_CSUM_TYPE(x)  ((u64)(x) << 40)
-#define TXPKT_VLAN(x)       ((u64)(x) << 44)
-#define TXPKT_VLAN_VLD      (1ULL << 60)
-#define TXPKT_IPCSUM_DIS    (1ULL << 62)
-#define TXPKT_L4CSUM_DIS    (1ULL << 63)
-};
-
-struct cpl_tx_pkt {
-	WR_HDR;
-	struct cpl_tx_pkt_core c;
-};
-
-#define cpl_tx_pkt_xt cpl_tx_pkt
-
-struct cpl_tx_pkt_lso_core {
-	__be32 lso_ctrl;
-#define LSO_TCPHDR_LEN(x) ((x) << 0)
-#define LSO_IPHDR_LEN(x)  ((x) << 4)
-#define LSO_ETHHDR_LEN(x) ((x) << 16)
-#define LSO_IPV6(x)       ((x) << 20)
-#define LSO_LAST_SLICE    (1 << 22)
-#define LSO_FIRST_SLICE   (1 << 23)
-#define LSO_OPCODE(x)     ((x) << 24)
-	__be16 ipid_ofst;
-	__be16 mss;
-	__be32 seqno_offset;
-	__be32 len;
-	/* encapsulated CPL (TX_PKT, TX_PKT_XT or TX_DATA) follows here */
-};
-
-struct cpl_tx_pkt_lso {
-	WR_HDR;
-	struct cpl_tx_pkt_lso_core c;
-	/* encapsulated CPL (TX_PKT, TX_PKT_XT or TX_DATA) follows here */
-};
-
-struct cpl_iscsi_hdr {
-	union opcode_tid ot;
-	__be16 pdu_len_ddp;
-#define ISCSI_PDU_LEN(x) ((x) & 0x7FFF)
-#define ISCSI_DDP        (1 << 15)
-	__be16 len;
-	__be32 seq;
-	__be16 urg;
-	u8 rsvd;
-	u8 status;
-};
-
-struct cpl_rx_data {
-	union opcode_tid ot;
-	__be16 rsvd;
-	__be16 len;
-	__be32 seq;
-	__be16 urg;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8 dack_mode:2;
-	u8 psh:1;
-	u8 heartbeat:1;
-	u8 ddp_off:1;
-	u8 :3;
-#else
-	u8 :3;
-	u8 ddp_off:1;
-	u8 heartbeat:1;
-	u8 psh:1;
-	u8 dack_mode:2;
-#endif
-	u8 status;
-};
-
-struct cpl_rx_data_ack {
-	WR_HDR;
-	union opcode_tid ot;
-	__be32 credit_dack;
-#define RX_CREDITS(x)   ((x) << 0)
-#define RX_FORCE_ACK(x) ((x) << 28)
-};
-
-struct cpl_rx_pkt {
-	struct rss_header rsshdr;
-	u8 opcode;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8 iff:4;
-	u8 csum_calc:1;
-	u8 ipmi_pkt:1;
-	u8 vlan_ex:1;
-	u8 ip_frag:1;
-#else
-	u8 ip_frag:1;
-	u8 vlan_ex:1;
-	u8 ipmi_pkt:1;
-	u8 csum_calc:1;
-	u8 iff:4;
-#endif
-	__be16 csum;
-	__be16 vlan;
-	__be16 len;
-	__be32 l2info;
-#define RXF_UDP (1 << 22)
-#define RXF_TCP (1 << 23)
-#define RXF_IP  (1 << 24)
-#define RXF_IP6 (1 << 25)
-	__be16 hdr_len;
-	__be16 err_vec;
-};
-
-struct cpl_trace_pkt {
-	u8 opcode;
-	u8 intf;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	u8 runt:4;
-	u8 filter_hit:4;
-	u8 :6;
-	u8 err:1;
-	u8 trunc:1;
-#else
-	u8 filter_hit:4;
-	u8 runt:4;
-	u8 trunc:1;
-	u8 err:1;
-	u8 :6;
-#endif
-	__be16 rsvd;
-	__be16 len;
-	__be64 tstamp;
-};
-
-struct cpl_l2t_write_req {
-	WR_HDR;
-	union opcode_tid ot;
-	__be16 params;
-#define L2T_W_INFO(x)    ((x) << 2)
-#define L2T_W_PORT(x)    ((x) << 8)
-#define L2T_W_NOREPLY(x) ((x) << 15)
-	__be16 l2t_idx;
-	__be16 vlan;
-	u8 dst_mac[6];
-};
-
-struct cpl_l2t_write_rpl {
-	union opcode_tid ot;
-	u8 status;
-	u8 rsvd[3];
-};
-
-struct cpl_rdma_terminate {
-	union opcode_tid ot;
-	__be16 rsvd;
-	__be16 len;
-};
-
-struct cpl_sge_egr_update {
-	__be32 opcode_qid;
-#define EGR_QID(x) ((x) & 0x1FFFF)
-	__be16 cidx;
-	__be16 pidx;
-};
-
-struct cpl_fw4_pld {
-	u8 opcode;
-	u8 rsvd0[3];
-	u8 type;
-	u8 rsvd1;
-	__be16 len;
-	__be64 data;
-	__be64 rsvd2;
-};
-
-struct cpl_fw6_pld {
-	u8 opcode;
-	u8 rsvd[5];
-	__be16 len;
-	__be64 data[4];
-};
-
-struct cpl_fw4_msg {
-	u8 opcode;
-	u8 type;
-	__be16 rsvd0;
-	__be32 rsvd1;
-	__be64 data[2];
-};
-
-struct cpl_fw4_ack {
-	union opcode_tid ot;
-	u8 credits;
-	u8 rsvd0[2];
-	u8 seq_vld;
-	__be32 snd_nxt;
-	__be32 snd_una;
-	__be64 rsvd1;
-};
-
-struct cpl_fw6_msg {
-	u8 opcode;
-	u8 type;
-	__be16 rsvd0;
-	__be32 rsvd1;
-	__be64 data[4];
-};
-
-/* cpl_fw6_msg.type values */
-enum {
-	FW6_TYPE_CMD_RPL = 0,
-};
-
-enum {
-	ULP_TX_MEM_READ = 2,
-	ULP_TX_MEM_WRITE = 3,
-	ULP_TX_PKT = 4
-};
-
-enum {
-	ULP_TX_SC_NOOP = 0x80,
-	ULP_TX_SC_IMM  = 0x81,
-	ULP_TX_SC_DSGL = 0x82,
-	ULP_TX_SC_ISGL = 0x83
-};
-
-struct ulptx_sge_pair {
-	__be32 len[2];
-	__be64 addr[2];
-};
-
-struct ulptx_sgl {
-	__be32 cmd_nsge;
-#define ULPTX_CMD(x) ((x) << 24)
-#define ULPTX_NSGE(x) ((x) << 0)
-	__be32 len0;
-	__be64 addr0;
-	struct ulptx_sge_pair sge[0];
-};
-
-struct ulp_mem_io {
-	WR_HDR;
-	__be32 cmd;
-#define ULP_MEMIO_ORDER(x) ((x) << 23)
-	__be32 len16;             /* command length */
-	__be32 dlen;              /* data length in 32-byte units */
-#define ULP_MEMIO_DATA_LEN(x) ((x) << 0)
-	__be32 lock_addr;
-#define ULP_MEMIO_ADDR(x) ((x) << 0)
-#define ULP_MEMIO_LOCK(x) ((x) << 31)
-};
-
-#endif  /* __T4_MSG_H */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4/t4_regs.h linux-libre-3.2-gnu/drivers/net/cxgb4/t4_regs.h
--- linux-libre-3.1-gnu/drivers/net/cxgb4/t4_regs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4/t4_regs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,885 +0,0 @@
-/*
- * This file is part of the Chelsio T4 Ethernet driver for Linux.
- *
- * Copyright (c) 2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __T4_REGS_H
-#define __T4_REGS_H
-
-#define MYPF_BASE 0x1b000
-#define MYPF_REG(reg_addr) (MYPF_BASE + (reg_addr))
-
-#define PF0_BASE 0x1e000
-#define PF0_REG(reg_addr) (PF0_BASE + (reg_addr))
-
-#define PF_STRIDE 0x400
-#define PF_BASE(idx) (PF0_BASE + (idx) * PF_STRIDE)
-#define PF_REG(idx, reg) (PF_BASE(idx) + (reg))
-
-#define MYPORT_BASE 0x1c000
-#define MYPORT_REG(reg_addr) (MYPORT_BASE + (reg_addr))
-
-#define PORT0_BASE 0x20000
-#define PORT0_REG(reg_addr) (PORT0_BASE + (reg_addr))
-
-#define PORT_STRIDE 0x2000
-#define PORT_BASE(idx) (PORT0_BASE + (idx) * PORT_STRIDE)
-#define PORT_REG(idx, reg) (PORT_BASE(idx) + (reg))
-
-#define EDC_STRIDE (EDC_1_BASE_ADDR - EDC_0_BASE_ADDR)
-#define EDC_REG(reg, idx) (reg + EDC_STRIDE * idx)
-
-#define PCIE_MEM_ACCESS_REG(reg_addr, idx) ((reg_addr) + (idx) * 8)
-#define PCIE_MAILBOX_REG(reg_addr, idx) ((reg_addr) + (idx) * 8)
-#define MC_BIST_STATUS_REG(reg_addr, idx) ((reg_addr) + (idx) * 4)
-#define EDC_BIST_STATUS_REG(reg_addr, idx) ((reg_addr) + (idx) * 4)
-
-#define SGE_PF_KDOORBELL 0x0
-#define  QID_MASK    0xffff8000U
-#define  QID_SHIFT   15
-#define  QID(x)      ((x) << QID_SHIFT)
-#define  DBPRIO      0x00004000U
-#define  PIDX_MASK   0x00003fffU
-#define  PIDX_SHIFT  0
-#define  PIDX(x)     ((x) << PIDX_SHIFT)
-
-#define SGE_PF_GTS 0x4
-#define  INGRESSQID_MASK   0xffff0000U
-#define  INGRESSQID_SHIFT  16
-#define  INGRESSQID(x)     ((x) << INGRESSQID_SHIFT)
-#define  TIMERREG_MASK     0x0000e000U
-#define  TIMERREG_SHIFT    13
-#define  TIMERREG(x)       ((x) << TIMERREG_SHIFT)
-#define  SEINTARM_MASK     0x00001000U
-#define  SEINTARM_SHIFT    12
-#define  SEINTARM(x)       ((x) << SEINTARM_SHIFT)
-#define  CIDXINC_MASK      0x00000fffU
-#define  CIDXINC_SHIFT     0
-#define  CIDXINC(x)        ((x) << CIDXINC_SHIFT)
-
-#define SGE_CONTROL 0x1008
-#define  DCASYSTYPE             0x00080000U
-#define  RXPKTCPLMODE           0x00040000U
-#define  EGRSTATUSPAGESIZE      0x00020000U
-#define  PKTSHIFT_MASK          0x00001c00U
-#define  PKTSHIFT_SHIFT         10
-#define  PKTSHIFT(x)            ((x) << PKTSHIFT_SHIFT)
-#define  PKTSHIFT_GET(x)	(((x) & PKTSHIFT_MASK) >> PKTSHIFT_SHIFT)
-#define  INGPCIEBOUNDARY_MASK   0x00000380U
-#define  INGPCIEBOUNDARY_SHIFT  7
-#define  INGPCIEBOUNDARY(x)     ((x) << INGPCIEBOUNDARY_SHIFT)
-#define  INGPADBOUNDARY_MASK    0x00000070U
-#define  INGPADBOUNDARY_SHIFT   4
-#define  INGPADBOUNDARY(x)      ((x) << INGPADBOUNDARY_SHIFT)
-#define  INGPADBOUNDARY_GET(x)	(((x) & INGPADBOUNDARY_MASK) \
-				 >> INGPADBOUNDARY_SHIFT)
-#define  EGRPCIEBOUNDARY_MASK   0x0000000eU
-#define  EGRPCIEBOUNDARY_SHIFT  1
-#define  EGRPCIEBOUNDARY(x)     ((x) << EGRPCIEBOUNDARY_SHIFT)
-#define  GLOBALENABLE           0x00000001U
-
-#define SGE_HOST_PAGE_SIZE 0x100c
-#define  HOSTPAGESIZEPF0_MASK   0x0000000fU
-#define  HOSTPAGESIZEPF0_SHIFT  0
-#define  HOSTPAGESIZEPF0(x)     ((x) << HOSTPAGESIZEPF0_SHIFT)
-
-#define SGE_EGRESS_QUEUES_PER_PAGE_PF 0x1010
-#define  QUEUESPERPAGEPF0_MASK   0x0000000fU
-#define  QUEUESPERPAGEPF0_GET(x) ((x) & QUEUESPERPAGEPF0_MASK)
-
-#define SGE_INT_CAUSE1 0x1024
-#define SGE_INT_CAUSE2 0x1030
-#define SGE_INT_CAUSE3 0x103c
-#define  ERR_FLM_DBP               0x80000000U
-#define  ERR_FLM_IDMA1             0x40000000U
-#define  ERR_FLM_IDMA0             0x20000000U
-#define  ERR_FLM_HINT              0x10000000U
-#define  ERR_PCIE_ERROR3           0x08000000U
-#define  ERR_PCIE_ERROR2           0x04000000U
-#define  ERR_PCIE_ERROR1           0x02000000U
-#define  ERR_PCIE_ERROR0           0x01000000U
-#define  ERR_TIMER_ABOVE_MAX_QID   0x00800000U
-#define  ERR_CPL_EXCEED_IQE_SIZE   0x00400000U
-#define  ERR_INVALID_CIDX_INC      0x00200000U
-#define  ERR_ITP_TIME_PAUSED       0x00100000U
-#define  ERR_CPL_OPCODE_0          0x00080000U
-#define  ERR_DROPPED_DB            0x00040000U
-#define  ERR_DATA_CPL_ON_HIGH_QID1 0x00020000U
-#define  ERR_DATA_CPL_ON_HIGH_QID0 0x00010000U
-#define  ERR_BAD_DB_PIDX3          0x00008000U
-#define  ERR_BAD_DB_PIDX2          0x00004000U
-#define  ERR_BAD_DB_PIDX1          0x00002000U
-#define  ERR_BAD_DB_PIDX0          0x00001000U
-#define  ERR_ING_PCIE_CHAN         0x00000800U
-#define  ERR_ING_CTXT_PRIO         0x00000400U
-#define  ERR_EGR_CTXT_PRIO         0x00000200U
-#define  DBFIFO_HP_INT             0x00000100U
-#define  DBFIFO_LP_INT             0x00000080U
-#define  REG_ADDRESS_ERR           0x00000040U
-#define  INGRESS_SIZE_ERR          0x00000020U
-#define  EGRESS_SIZE_ERR           0x00000010U
-#define  ERR_INV_CTXT3             0x00000008U
-#define  ERR_INV_CTXT2             0x00000004U
-#define  ERR_INV_CTXT1             0x00000002U
-#define  ERR_INV_CTXT0             0x00000001U
-
-#define SGE_INT_ENABLE3 0x1040
-#define SGE_FL_BUFFER_SIZE0 0x1044
-#define SGE_FL_BUFFER_SIZE1 0x1048
-#define SGE_INGRESS_RX_THRESHOLD 0x10a0
-#define  THRESHOLD_0_MASK   0x3f000000U
-#define  THRESHOLD_0_SHIFT  24
-#define  THRESHOLD_0(x)     ((x) << THRESHOLD_0_SHIFT)
-#define  THRESHOLD_0_GET(x) (((x) & THRESHOLD_0_MASK) >> THRESHOLD_0_SHIFT)
-#define  THRESHOLD_1_MASK   0x003f0000U
-#define  THRESHOLD_1_SHIFT  16
-#define  THRESHOLD_1(x)     ((x) << THRESHOLD_1_SHIFT)
-#define  THRESHOLD_1_GET(x) (((x) & THRESHOLD_1_MASK) >> THRESHOLD_1_SHIFT)
-#define  THRESHOLD_2_MASK   0x00003f00U
-#define  THRESHOLD_2_SHIFT  8
-#define  THRESHOLD_2(x)     ((x) << THRESHOLD_2_SHIFT)
-#define  THRESHOLD_2_GET(x) (((x) & THRESHOLD_2_MASK) >> THRESHOLD_2_SHIFT)
-#define  THRESHOLD_3_MASK   0x0000003fU
-#define  THRESHOLD_3_SHIFT  0
-#define  THRESHOLD_3(x)     ((x) << THRESHOLD_3_SHIFT)
-#define  THRESHOLD_3_GET(x) (((x) & THRESHOLD_3_MASK) >> THRESHOLD_3_SHIFT)
-
-#define SGE_TIMER_VALUE_0_AND_1 0x10b8
-#define  TIMERVALUE0_MASK   0xffff0000U
-#define  TIMERVALUE0_SHIFT  16
-#define  TIMERVALUE0(x)     ((x) << TIMERVALUE0_SHIFT)
-#define  TIMERVALUE0_GET(x) (((x) & TIMERVALUE0_MASK) >> TIMERVALUE0_SHIFT)
-#define  TIMERVALUE1_MASK   0x0000ffffU
-#define  TIMERVALUE1_SHIFT  0
-#define  TIMERVALUE1(x)     ((x) << TIMERVALUE1_SHIFT)
-#define  TIMERVALUE1_GET(x) (((x) & TIMERVALUE1_MASK) >> TIMERVALUE1_SHIFT)
-
-#define SGE_TIMER_VALUE_2_AND_3 0x10bc
-#define SGE_TIMER_VALUE_4_AND_5 0x10c0
-#define SGE_DEBUG_INDEX 0x10cc
-#define SGE_DEBUG_DATA_HIGH 0x10d0
-#define SGE_DEBUG_DATA_LOW 0x10d4
-#define SGE_INGRESS_QUEUES_PER_PAGE_PF 0x10f4
-
-#define PCIE_PF_CLI 0x44
-#define PCIE_INT_CAUSE 0x3004
-#define  UNXSPLCPLERR  0x20000000U
-#define  PCIEPINT      0x10000000U
-#define  PCIESINT      0x08000000U
-#define  RPLPERR       0x04000000U
-#define  RXWRPERR      0x02000000U
-#define  RXCPLPERR     0x01000000U
-#define  PIOTAGPERR    0x00800000U
-#define  MATAGPERR     0x00400000U
-#define  INTXCLRPERR   0x00200000U
-#define  FIDPERR       0x00100000U
-#define  CFGSNPPERR    0x00080000U
-#define  HRSPPERR      0x00040000U
-#define  HREQPERR      0x00020000U
-#define  HCNTPERR      0x00010000U
-#define  DRSPPERR      0x00008000U
-#define  DREQPERR      0x00004000U
-#define  DCNTPERR      0x00002000U
-#define  CRSPPERR      0x00001000U
-#define  CREQPERR      0x00000800U
-#define  CCNTPERR      0x00000400U
-#define  TARTAGPERR    0x00000200U
-#define  PIOREQPERR    0x00000100U
-#define  PIOCPLPERR    0x00000080U
-#define  MSIXDIPERR    0x00000040U
-#define  MSIXDATAPERR  0x00000020U
-#define  MSIXADDRHPERR 0x00000010U
-#define  MSIXADDRLPERR 0x00000008U
-#define  MSIDATAPERR   0x00000004U
-#define  MSIADDRHPERR  0x00000002U
-#define  MSIADDRLPERR  0x00000001U
-
-#define PCIE_NONFAT_ERR 0x3010
-#define PCIE_MEM_ACCESS_BASE_WIN 0x3068
-#define  PCIEOFST_MASK   0xfffffc00U
-#define  BIR_MASK        0x00000300U
-#define  BIR_SHIFT       8
-#define  BIR(x)          ((x) << BIR_SHIFT)
-#define  WINDOW_MASK     0x000000ffU
-#define  WINDOW_SHIFT    0
-#define  WINDOW(x)       ((x) << WINDOW_SHIFT)
-#define PCIE_MEM_ACCESS_OFFSET 0x306c
-
-#define PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS 0x5908
-#define  RNPP 0x80000000U
-#define  RPCP 0x20000000U
-#define  RCIP 0x08000000U
-#define  RCCP 0x04000000U
-#define  RFTP 0x00800000U
-#define  PTRP 0x00100000U
-
-#define PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS 0x59a4
-#define  TPCP 0x40000000U
-#define  TNPP 0x20000000U
-#define  TFTP 0x10000000U
-#define  TCAP 0x08000000U
-#define  TCIP 0x04000000U
-#define  RCAP 0x02000000U
-#define  PLUP 0x00800000U
-#define  PLDN 0x00400000U
-#define  OTDD 0x00200000U
-#define  GTRP 0x00100000U
-#define  RDPE 0x00040000U
-#define  TDCE 0x00020000U
-#define  TDUE 0x00010000U
-
-#define MC_INT_CAUSE 0x7518
-#define  ECC_UE_INT_CAUSE 0x00000004U
-#define  ECC_CE_INT_CAUSE 0x00000002U
-#define  PERR_INT_CAUSE   0x00000001U
-
-#define MC_ECC_STATUS 0x751c
-#define  ECC_CECNT_MASK   0xffff0000U
-#define  ECC_CECNT_SHIFT  16
-#define  ECC_CECNT(x)     ((x) << ECC_CECNT_SHIFT)
-#define  ECC_CECNT_GET(x) (((x) & ECC_CECNT_MASK) >> ECC_CECNT_SHIFT)
-#define  ECC_UECNT_MASK   0x0000ffffU
-#define  ECC_UECNT_SHIFT  0
-#define  ECC_UECNT(x)     ((x) << ECC_UECNT_SHIFT)
-#define  ECC_UECNT_GET(x) (((x) & ECC_UECNT_MASK) >> ECC_UECNT_SHIFT)
-
-#define MC_BIST_CMD 0x7600
-#define  START_BIST          0x80000000U
-#define  BIST_CMD_GAP_MASK   0x0000ff00U
-#define  BIST_CMD_GAP_SHIFT  8
-#define  BIST_CMD_GAP(x)     ((x) << BIST_CMD_GAP_SHIFT)
-#define  BIST_OPCODE_MASK    0x00000003U
-#define  BIST_OPCODE_SHIFT   0
-#define  BIST_OPCODE(x)      ((x) << BIST_OPCODE_SHIFT)
-
-#define MC_BIST_CMD_ADDR 0x7604
-#define MC_BIST_CMD_LEN 0x7608
-#define MC_BIST_DATA_PATTERN 0x760c
-#define  BIST_DATA_TYPE_MASK   0x0000000fU
-#define  BIST_DATA_TYPE_SHIFT  0
-#define  BIST_DATA_TYPE(x)     ((x) << BIST_DATA_TYPE_SHIFT)
-
-#define MC_BIST_STATUS_RDATA 0x7688
-
-#define MA_EXT_MEMORY_BAR 0x77c8
-#define  EXT_MEM_SIZE_MASK   0x00000fffU
-#define  EXT_MEM_SIZE_SHIFT  0
-#define  EXT_MEM_SIZE_GET(x) (((x) & EXT_MEM_SIZE_MASK) >> EXT_MEM_SIZE_SHIFT)
-
-#define MA_TARGET_MEM_ENABLE 0x77d8
-#define  EXT_MEM_ENABLE 0x00000004U
-#define  EDRAM1_ENABLE  0x00000002U
-#define  EDRAM0_ENABLE  0x00000001U
-
-#define MA_INT_CAUSE 0x77e0
-#define  MEM_PERR_INT_CAUSE 0x00000002U
-#define  MEM_WRAP_INT_CAUSE 0x00000001U
-
-#define MA_INT_WRAP_STATUS 0x77e4
-#define  MEM_WRAP_ADDRESS_MASK   0xfffffff0U
-#define  MEM_WRAP_ADDRESS_SHIFT  4
-#define  MEM_WRAP_ADDRESS_GET(x) (((x) & MEM_WRAP_ADDRESS_MASK) >> MEM_WRAP_ADDRESS_SHIFT)
-#define  MEM_WRAP_CLIENT_NUM_MASK   0x0000000fU
-#define  MEM_WRAP_CLIENT_NUM_SHIFT  0
-#define  MEM_WRAP_CLIENT_NUM_GET(x) (((x) & MEM_WRAP_CLIENT_NUM_MASK) >> MEM_WRAP_CLIENT_NUM_SHIFT)
-
-#define MA_PARITY_ERROR_STATUS 0x77f4
-
-#define EDC_0_BASE_ADDR 0x7900
-
-#define EDC_BIST_CMD 0x7904
-#define EDC_BIST_CMD_ADDR 0x7908
-#define EDC_BIST_CMD_LEN 0x790c
-#define EDC_BIST_DATA_PATTERN 0x7910
-#define EDC_BIST_STATUS_RDATA 0x7928
-#define EDC_INT_CAUSE 0x7978
-#define  ECC_UE_PAR     0x00000020U
-#define  ECC_CE_PAR     0x00000010U
-#define  PERR_PAR_CAUSE 0x00000008U
-
-#define EDC_ECC_STATUS 0x797c
-
-#define EDC_1_BASE_ADDR 0x7980
-
-#define CIM_BOOT_CFG 0x7b00
-#define  BOOTADDR_MASK 0xffffff00U
-
-#define CIM_PF_MAILBOX_DATA 0x240
-#define CIM_PF_MAILBOX_CTRL 0x280
-#define  MBMSGVALID     0x00000008U
-#define  MBINTREQ       0x00000004U
-#define  MBOWNER_MASK   0x00000003U
-#define  MBOWNER_SHIFT  0
-#define  MBOWNER(x)     ((x) << MBOWNER_SHIFT)
-#define  MBOWNER_GET(x) (((x) & MBOWNER_MASK) >> MBOWNER_SHIFT)
-
-#define CIM_PF_HOST_INT_CAUSE 0x28c
-#define  MBMSGRDYINT 0x00080000U
-
-#define CIM_HOST_INT_CAUSE 0x7b2c
-#define  TIEQOUTPARERRINT  0x00100000U
-#define  TIEQINPARERRINT   0x00080000U
-#define  MBHOSTPARERR      0x00040000U
-#define  MBUPPARERR        0x00020000U
-#define  IBQPARERR         0x0001f800U
-#define  IBQTP0PARERR      0x00010000U
-#define  IBQTP1PARERR      0x00008000U
-#define  IBQULPPARERR      0x00004000U
-#define  IBQSGELOPARERR    0x00002000U
-#define  IBQSGEHIPARERR    0x00001000U
-#define  IBQNCSIPARERR     0x00000800U
-#define  OBQPARERR         0x000007e0U
-#define  OBQULP0PARERR     0x00000400U
-#define  OBQULP1PARERR     0x00000200U
-#define  OBQULP2PARERR     0x00000100U
-#define  OBQULP3PARERR     0x00000080U
-#define  OBQSGEPARERR      0x00000040U
-#define  OBQNCSIPARERR     0x00000020U
-#define  PREFDROPINT       0x00000002U
-#define  UPACCNONZERO      0x00000001U
-
-#define CIM_HOST_UPACC_INT_CAUSE 0x7b34
-#define  EEPROMWRINT      0x40000000U
-#define  TIMEOUTMAINT     0x20000000U
-#define  TIMEOUTINT       0x10000000U
-#define  RSPOVRLOOKUPINT  0x08000000U
-#define  REQOVRLOOKUPINT  0x04000000U
-#define  BLKWRPLINT       0x02000000U
-#define  BLKRDPLINT       0x01000000U
-#define  SGLWRPLINT       0x00800000U
-#define  SGLRDPLINT       0x00400000U
-#define  BLKWRCTLINT      0x00200000U
-#define  BLKRDCTLINT      0x00100000U
-#define  SGLWRCTLINT      0x00080000U
-#define  SGLRDCTLINT      0x00040000U
-#define  BLKWREEPROMINT   0x00020000U
-#define  BLKRDEEPROMINT   0x00010000U
-#define  SGLWREEPROMINT   0x00008000U
-#define  SGLRDEEPROMINT   0x00004000U
-#define  BLKWRFLASHINT    0x00002000U
-#define  BLKRDFLASHINT    0x00001000U
-#define  SGLWRFLASHINT    0x00000800U
-#define  SGLRDFLASHINT    0x00000400U
-#define  BLKWRBOOTINT     0x00000200U
-#define  BLKRDBOOTINT     0x00000100U
-#define  SGLWRBOOTINT     0x00000080U
-#define  SGLRDBOOTINT     0x00000040U
-#define  ILLWRBEINT       0x00000020U
-#define  ILLRDBEINT       0x00000010U
-#define  ILLRDINT         0x00000008U
-#define  ILLWRINT         0x00000004U
-#define  ILLTRANSINT      0x00000002U
-#define  RSVDSPACEINT     0x00000001U
-
-#define TP_OUT_CONFIG 0x7d04
-#define  VLANEXTENABLE_MASK  0x0000f000U
-#define  VLANEXTENABLE_SHIFT 12
-
-#define TP_PARA_REG2 0x7d68
-#define  MAXRXDATA_MASK    0xffff0000U
-#define  MAXRXDATA_SHIFT   16
-#define  MAXRXDATA_GET(x) (((x) & MAXRXDATA_MASK) >> MAXRXDATA_SHIFT)
-
-#define TP_TIMER_RESOLUTION 0x7d90
-#define  TIMERRESOLUTION_MASK   0x00ff0000U
-#define  TIMERRESOLUTION_SHIFT  16
-#define  TIMERRESOLUTION_GET(x) (((x) & TIMERRESOLUTION_MASK) >> TIMERRESOLUTION_SHIFT)
-
-#define TP_SHIFT_CNT 0x7dc0
-
-#define TP_CCTRL_TABLE 0x7ddc
-#define TP_MTU_TABLE 0x7de4
-#define  MTUINDEX_MASK   0xff000000U
-#define  MTUINDEX_SHIFT  24
-#define  MTUINDEX(x)     ((x) << MTUINDEX_SHIFT)
-#define  MTUWIDTH_MASK   0x000f0000U
-#define  MTUWIDTH_SHIFT  16
-#define  MTUWIDTH(x)     ((x) << MTUWIDTH_SHIFT)
-#define  MTUWIDTH_GET(x) (((x) & MTUWIDTH_MASK) >> MTUWIDTH_SHIFT)
-#define  MTUVALUE_MASK   0x00003fffU
-#define  MTUVALUE_SHIFT  0
-#define  MTUVALUE(x)     ((x) << MTUVALUE_SHIFT)
-#define  MTUVALUE_GET(x) (((x) & MTUVALUE_MASK) >> MTUVALUE_SHIFT)
-
-#define TP_RSS_LKP_TABLE 0x7dec
-#define  LKPTBLROWVLD        0x80000000U
-#define  LKPTBLQUEUE1_MASK   0x000ffc00U
-#define  LKPTBLQUEUE1_SHIFT  10
-#define  LKPTBLQUEUE1(x)     ((x) << LKPTBLQUEUE1_SHIFT)
-#define  LKPTBLQUEUE1_GET(x) (((x) & LKPTBLQUEUE1_MASK) >> LKPTBLQUEUE1_SHIFT)
-#define  LKPTBLQUEUE0_MASK   0x000003ffU
-#define  LKPTBLQUEUE0_SHIFT  0
-#define  LKPTBLQUEUE0(x)     ((x) << LKPTBLQUEUE0_SHIFT)
-#define  LKPTBLQUEUE0_GET(x) (((x) & LKPTBLQUEUE0_MASK) >> LKPTBLQUEUE0_SHIFT)
-
-#define TP_PIO_ADDR 0x7e40
-#define TP_PIO_DATA 0x7e44
-#define TP_MIB_INDEX 0x7e50
-#define TP_MIB_DATA 0x7e54
-#define TP_INT_CAUSE 0x7e74
-#define  FLMTXFLSTEMPTY 0x40000000U
-
-#define TP_INGRESS_CONFIG 0x141
-#define  VNIC                0x00000800U
-#define  CSUM_HAS_PSEUDO_HDR 0x00000400U
-#define  RM_OVLAN            0x00000200U
-#define  LOOKUPEVERYPKT      0x00000100U
-
-#define TP_MIB_MAC_IN_ERR_0 0x0
-#define TP_MIB_TCP_OUT_RST 0xc
-#define TP_MIB_TCP_IN_SEG_HI 0x10
-#define TP_MIB_TCP_IN_SEG_LO 0x11
-#define TP_MIB_TCP_OUT_SEG_HI 0x12
-#define TP_MIB_TCP_OUT_SEG_LO 0x13
-#define TP_MIB_TCP_RXT_SEG_HI 0x14
-#define TP_MIB_TCP_RXT_SEG_LO 0x15
-#define TP_MIB_TNL_CNG_DROP_0 0x18
-#define TP_MIB_TCP_V6IN_ERR_0 0x28
-#define TP_MIB_TCP_V6OUT_RST 0x2c
-#define TP_MIB_OFD_ARP_DROP 0x36
-#define TP_MIB_TNL_DROP_0 0x44
-#define TP_MIB_OFD_VLN_DROP_0 0x58
-
-#define ULP_TX_INT_CAUSE 0x8dcc
-#define  PBL_BOUND_ERR_CH3 0x80000000U
-#define  PBL_BOUND_ERR_CH2 0x40000000U
-#define  PBL_BOUND_ERR_CH1 0x20000000U
-#define  PBL_BOUND_ERR_CH0 0x10000000U
-
-#define PM_RX_INT_CAUSE 0x8fdc
-#define  ZERO_E_CMD_ERROR     0x00400000U
-#define  PMRX_FRAMING_ERROR   0x003ffff0U
-#define  OCSPI_PAR_ERROR      0x00000008U
-#define  DB_OPTIONS_PAR_ERROR 0x00000004U
-#define  IESPI_PAR_ERROR      0x00000002U
-#define  E_PCMD_PAR_ERROR     0x00000001U
-
-#define PM_TX_INT_CAUSE 0x8ffc
-#define  PCMD_LEN_OVFL0     0x80000000U
-#define  PCMD_LEN_OVFL1     0x40000000U
-#define  PCMD_LEN_OVFL2     0x20000000U
-#define  ZERO_C_CMD_ERROR   0x10000000U
-#define  PMTX_FRAMING_ERROR 0x0ffffff0U
-#define  OESPI_PAR_ERROR    0x00000008U
-#define  ICSPI_PAR_ERROR    0x00000002U
-#define  C_PCMD_PAR_ERROR   0x00000001U
-
-#define MPS_PORT_STAT_TX_PORT_BYTES_L 0x400
-#define MPS_PORT_STAT_TX_PORT_BYTES_H 0x404
-#define MPS_PORT_STAT_TX_PORT_FRAMES_L 0x408
-#define MPS_PORT_STAT_TX_PORT_FRAMES_H 0x40c
-#define MPS_PORT_STAT_TX_PORT_BCAST_L 0x410
-#define MPS_PORT_STAT_TX_PORT_BCAST_H 0x414
-#define MPS_PORT_STAT_TX_PORT_MCAST_L 0x418
-#define MPS_PORT_STAT_TX_PORT_MCAST_H 0x41c
-#define MPS_PORT_STAT_TX_PORT_UCAST_L 0x420
-#define MPS_PORT_STAT_TX_PORT_UCAST_H 0x424
-#define MPS_PORT_STAT_TX_PORT_ERROR_L 0x428
-#define MPS_PORT_STAT_TX_PORT_ERROR_H 0x42c
-#define MPS_PORT_STAT_TX_PORT_64B_L 0x430
-#define MPS_PORT_STAT_TX_PORT_64B_H 0x434
-#define MPS_PORT_STAT_TX_PORT_65B_127B_L 0x438
-#define MPS_PORT_STAT_TX_PORT_65B_127B_H 0x43c
-#define MPS_PORT_STAT_TX_PORT_128B_255B_L 0x440
-#define MPS_PORT_STAT_TX_PORT_128B_255B_H 0x444
-#define MPS_PORT_STAT_TX_PORT_256B_511B_L 0x448
-#define MPS_PORT_STAT_TX_PORT_256B_511B_H 0x44c
-#define MPS_PORT_STAT_TX_PORT_512B_1023B_L 0x450
-#define MPS_PORT_STAT_TX_PORT_512B_1023B_H 0x454
-#define MPS_PORT_STAT_TX_PORT_1024B_1518B_L 0x458
-#define MPS_PORT_STAT_TX_PORT_1024B_1518B_H 0x45c
-#define MPS_PORT_STAT_TX_PORT_1519B_MAX_L 0x460
-#define MPS_PORT_STAT_TX_PORT_1519B_MAX_H 0x464
-#define MPS_PORT_STAT_TX_PORT_DROP_L 0x468
-#define MPS_PORT_STAT_TX_PORT_DROP_H 0x46c
-#define MPS_PORT_STAT_TX_PORT_PAUSE_L 0x470
-#define MPS_PORT_STAT_TX_PORT_PAUSE_H 0x474
-#define MPS_PORT_STAT_TX_PORT_PPP0_L 0x478
-#define MPS_PORT_STAT_TX_PORT_PPP0_H 0x47c
-#define MPS_PORT_STAT_TX_PORT_PPP1_L 0x480
-#define MPS_PORT_STAT_TX_PORT_PPP1_H 0x484
-#define MPS_PORT_STAT_TX_PORT_PPP2_L 0x488
-#define MPS_PORT_STAT_TX_PORT_PPP2_H 0x48c
-#define MPS_PORT_STAT_TX_PORT_PPP3_L 0x490
-#define MPS_PORT_STAT_TX_PORT_PPP3_H 0x494
-#define MPS_PORT_STAT_TX_PORT_PPP4_L 0x498
-#define MPS_PORT_STAT_TX_PORT_PPP4_H 0x49c
-#define MPS_PORT_STAT_TX_PORT_PPP5_L 0x4a0
-#define MPS_PORT_STAT_TX_PORT_PPP5_H 0x4a4
-#define MPS_PORT_STAT_TX_PORT_PPP6_L 0x4a8
-#define MPS_PORT_STAT_TX_PORT_PPP6_H 0x4ac
-#define MPS_PORT_STAT_TX_PORT_PPP7_L 0x4b0
-#define MPS_PORT_STAT_TX_PORT_PPP7_H 0x4b4
-#define MPS_PORT_STAT_LB_PORT_BYTES_L 0x4c0
-#define MPS_PORT_STAT_LB_PORT_BYTES_H 0x4c4
-#define MPS_PORT_STAT_LB_PORT_FRAMES_L 0x4c8
-#define MPS_PORT_STAT_LB_PORT_FRAMES_H 0x4cc
-#define MPS_PORT_STAT_LB_PORT_BCAST_L 0x4d0
-#define MPS_PORT_STAT_LB_PORT_BCAST_H 0x4d4
-#define MPS_PORT_STAT_LB_PORT_MCAST_L 0x4d8
-#define MPS_PORT_STAT_LB_PORT_MCAST_H 0x4dc
-#define MPS_PORT_STAT_LB_PORT_UCAST_L 0x4e0
-#define MPS_PORT_STAT_LB_PORT_UCAST_H 0x4e4
-#define MPS_PORT_STAT_LB_PORT_ERROR_L 0x4e8
-#define MPS_PORT_STAT_LB_PORT_ERROR_H 0x4ec
-#define MPS_PORT_STAT_LB_PORT_64B_L 0x4f0
-#define MPS_PORT_STAT_LB_PORT_64B_H 0x4f4
-#define MPS_PORT_STAT_LB_PORT_65B_127B_L 0x4f8
-#define MPS_PORT_STAT_LB_PORT_65B_127B_H 0x4fc
-#define MPS_PORT_STAT_LB_PORT_128B_255B_L 0x500
-#define MPS_PORT_STAT_LB_PORT_128B_255B_H 0x504
-#define MPS_PORT_STAT_LB_PORT_256B_511B_L 0x508
-#define MPS_PORT_STAT_LB_PORT_256B_511B_H 0x50c
-#define MPS_PORT_STAT_LB_PORT_512B_1023B_L 0x510
-#define MPS_PORT_STAT_LB_PORT_512B_1023B_H 0x514
-#define MPS_PORT_STAT_LB_PORT_1024B_1518B_L 0x518
-#define MPS_PORT_STAT_LB_PORT_1024B_1518B_H 0x51c
-#define MPS_PORT_STAT_LB_PORT_1519B_MAX_L 0x520
-#define MPS_PORT_STAT_LB_PORT_1519B_MAX_H 0x524
-#define MPS_PORT_STAT_LB_PORT_DROP_FRAMES 0x528
-#define MPS_PORT_STAT_RX_PORT_BYTES_L 0x540
-#define MPS_PORT_STAT_RX_PORT_BYTES_H 0x544
-#define MPS_PORT_STAT_RX_PORT_FRAMES_L 0x548
-#define MPS_PORT_STAT_RX_PORT_FRAMES_H 0x54c
-#define MPS_PORT_STAT_RX_PORT_BCAST_L 0x550
-#define MPS_PORT_STAT_RX_PORT_BCAST_H 0x554
-#define MPS_PORT_STAT_RX_PORT_MCAST_L 0x558
-#define MPS_PORT_STAT_RX_PORT_MCAST_H 0x55c
-#define MPS_PORT_STAT_RX_PORT_UCAST_L 0x560
-#define MPS_PORT_STAT_RX_PORT_UCAST_H 0x564
-#define MPS_PORT_STAT_RX_PORT_MTU_ERROR_L 0x568
-#define MPS_PORT_STAT_RX_PORT_MTU_ERROR_H 0x56c
-#define MPS_PORT_STAT_RX_PORT_MTU_CRC_ERROR_L 0x570
-#define MPS_PORT_STAT_RX_PORT_MTU_CRC_ERROR_H 0x574
-#define MPS_PORT_STAT_RX_PORT_CRC_ERROR_L 0x578
-#define MPS_PORT_STAT_RX_PORT_CRC_ERROR_H 0x57c
-#define MPS_PORT_STAT_RX_PORT_LEN_ERROR_L 0x580
-#define MPS_PORT_STAT_RX_PORT_LEN_ERROR_H 0x584
-#define MPS_PORT_STAT_RX_PORT_SYM_ERROR_L 0x588
-#define MPS_PORT_STAT_RX_PORT_SYM_ERROR_H 0x58c
-#define MPS_PORT_STAT_RX_PORT_64B_L 0x590
-#define MPS_PORT_STAT_RX_PORT_64B_H 0x594
-#define MPS_PORT_STAT_RX_PORT_65B_127B_L 0x598
-#define MPS_PORT_STAT_RX_PORT_65B_127B_H 0x59c
-#define MPS_PORT_STAT_RX_PORT_128B_255B_L 0x5a0
-#define MPS_PORT_STAT_RX_PORT_128B_255B_H 0x5a4
-#define MPS_PORT_STAT_RX_PORT_256B_511B_L 0x5a8
-#define MPS_PORT_STAT_RX_PORT_256B_511B_H 0x5ac
-#define MPS_PORT_STAT_RX_PORT_512B_1023B_L 0x5b0
-#define MPS_PORT_STAT_RX_PORT_512B_1023B_H 0x5b4
-#define MPS_PORT_STAT_RX_PORT_1024B_1518B_L 0x5b8
-#define MPS_PORT_STAT_RX_PORT_1024B_1518B_H 0x5bc
-#define MPS_PORT_STAT_RX_PORT_1519B_MAX_L 0x5c0
-#define MPS_PORT_STAT_RX_PORT_1519B_MAX_H 0x5c4
-#define MPS_PORT_STAT_RX_PORT_PAUSE_L 0x5c8
-#define MPS_PORT_STAT_RX_PORT_PAUSE_H 0x5cc
-#define MPS_PORT_STAT_RX_PORT_PPP0_L 0x5d0
-#define MPS_PORT_STAT_RX_PORT_PPP0_H 0x5d4
-#define MPS_PORT_STAT_RX_PORT_PPP1_L 0x5d8
-#define MPS_PORT_STAT_RX_PORT_PPP1_H 0x5dc
-#define MPS_PORT_STAT_RX_PORT_PPP2_L 0x5e0
-#define MPS_PORT_STAT_RX_PORT_PPP2_H 0x5e4
-#define MPS_PORT_STAT_RX_PORT_PPP3_L 0x5e8
-#define MPS_PORT_STAT_RX_PORT_PPP3_H 0x5ec
-#define MPS_PORT_STAT_RX_PORT_PPP4_L 0x5f0
-#define MPS_PORT_STAT_RX_PORT_PPP4_H 0x5f4
-#define MPS_PORT_STAT_RX_PORT_PPP5_L 0x5f8
-#define MPS_PORT_STAT_RX_PORT_PPP5_H 0x5fc
-#define MPS_PORT_STAT_RX_PORT_PPP6_L 0x600
-#define MPS_PORT_STAT_RX_PORT_PPP6_H 0x604
-#define MPS_PORT_STAT_RX_PORT_PPP7_L 0x608
-#define MPS_PORT_STAT_RX_PORT_PPP7_H 0x60c
-#define MPS_PORT_STAT_RX_PORT_LESS_64B_L 0x610
-#define MPS_PORT_STAT_RX_PORT_LESS_64B_H 0x614
-#define MPS_CMN_CTL 0x9000
-#define  NUMPORTS_MASK   0x00000003U
-#define  NUMPORTS_SHIFT  0
-#define  NUMPORTS_GET(x) (((x) & NUMPORTS_MASK) >> NUMPORTS_SHIFT)
-
-#define MPS_INT_CAUSE 0x9008
-#define  STATINT 0x00000020U
-#define  TXINT   0x00000010U
-#define  RXINT   0x00000008U
-#define  TRCINT  0x00000004U
-#define  CLSINT  0x00000002U
-#define  PLINT   0x00000001U
-
-#define MPS_TX_INT_CAUSE 0x9408
-#define  PORTERR    0x00010000U
-#define  FRMERR     0x00008000U
-#define  SECNTERR   0x00004000U
-#define  BUBBLE     0x00002000U
-#define  TXDESCFIFO 0x00001e00U
-#define  TXDATAFIFO 0x000001e0U
-#define  NCSIFIFO   0x00000010U
-#define  TPFIFO     0x0000000fU
-
-#define MPS_STAT_PERR_INT_CAUSE_SRAM 0x9614
-#define MPS_STAT_PERR_INT_CAUSE_TX_FIFO 0x9620
-#define MPS_STAT_PERR_INT_CAUSE_RX_FIFO 0x962c
-
-#define MPS_STAT_RX_BG_0_MAC_DROP_FRAME_L 0x9640
-#define MPS_STAT_RX_BG_0_MAC_DROP_FRAME_H 0x9644
-#define MPS_STAT_RX_BG_1_MAC_DROP_FRAME_L 0x9648
-#define MPS_STAT_RX_BG_1_MAC_DROP_FRAME_H 0x964c
-#define MPS_STAT_RX_BG_2_MAC_DROP_FRAME_L 0x9650
-#define MPS_STAT_RX_BG_2_MAC_DROP_FRAME_H 0x9654
-#define MPS_STAT_RX_BG_3_MAC_DROP_FRAME_L 0x9658
-#define MPS_STAT_RX_BG_3_MAC_DROP_FRAME_H 0x965c
-#define MPS_STAT_RX_BG_0_LB_DROP_FRAME_L 0x9660
-#define MPS_STAT_RX_BG_0_LB_DROP_FRAME_H 0x9664
-#define MPS_STAT_RX_BG_1_LB_DROP_FRAME_L 0x9668
-#define MPS_STAT_RX_BG_1_LB_DROP_FRAME_H 0x966c
-#define MPS_STAT_RX_BG_2_LB_DROP_FRAME_L 0x9670
-#define MPS_STAT_RX_BG_2_LB_DROP_FRAME_H 0x9674
-#define MPS_STAT_RX_BG_3_LB_DROP_FRAME_L 0x9678
-#define MPS_STAT_RX_BG_3_LB_DROP_FRAME_H 0x967c
-#define MPS_STAT_RX_BG_0_MAC_TRUNC_FRAME_L 0x9680
-#define MPS_STAT_RX_BG_0_MAC_TRUNC_FRAME_H 0x9684
-#define MPS_STAT_RX_BG_1_MAC_TRUNC_FRAME_L 0x9688
-#define MPS_STAT_RX_BG_1_MAC_TRUNC_FRAME_H 0x968c
-#define MPS_STAT_RX_BG_2_MAC_TRUNC_FRAME_L 0x9690
-#define MPS_STAT_RX_BG_2_MAC_TRUNC_FRAME_H 0x9694
-#define MPS_STAT_RX_BG_3_MAC_TRUNC_FRAME_L 0x9698
-#define MPS_STAT_RX_BG_3_MAC_TRUNC_FRAME_H 0x969c
-#define MPS_STAT_RX_BG_0_LB_TRUNC_FRAME_L 0x96a0
-#define MPS_STAT_RX_BG_0_LB_TRUNC_FRAME_H 0x96a4
-#define MPS_STAT_RX_BG_1_LB_TRUNC_FRAME_L 0x96a8
-#define MPS_STAT_RX_BG_1_LB_TRUNC_FRAME_H 0x96ac
-#define MPS_STAT_RX_BG_2_LB_TRUNC_FRAME_L 0x96b0
-#define MPS_STAT_RX_BG_2_LB_TRUNC_FRAME_H 0x96b4
-#define MPS_STAT_RX_BG_3_LB_TRUNC_FRAME_L 0x96b8
-#define MPS_STAT_RX_BG_3_LB_TRUNC_FRAME_H 0x96bc
-#define MPS_TRC_CFG 0x9800
-#define  TRCFIFOEMPTY       0x00000010U
-#define  TRCIGNOREDROPINPUT 0x00000008U
-#define  TRCKEEPDUPLICATES  0x00000004U
-#define  TRCEN              0x00000002U
-#define  TRCMULTIFILTER     0x00000001U
-
-#define MPS_TRC_RSS_CONTROL 0x9808
-#define  RSSCONTROL_MASK    0x00ff0000U
-#define  RSSCONTROL_SHIFT   16
-#define  RSSCONTROL(x)      ((x) << RSSCONTROL_SHIFT)
-#define  QUEUENUMBER_MASK   0x0000ffffU
-#define  QUEUENUMBER_SHIFT  0
-#define  QUEUENUMBER(x)     ((x) << QUEUENUMBER_SHIFT)
-
-#define MPS_TRC_FILTER_MATCH_CTL_A 0x9810
-#define  TFINVERTMATCH   0x01000000U
-#define  TFPKTTOOLARGE   0x00800000U
-#define  TFEN            0x00400000U
-#define  TFPORT_MASK     0x003c0000U
-#define  TFPORT_SHIFT    18
-#define  TFPORT(x)       ((x) << TFPORT_SHIFT)
-#define  TFPORT_GET(x)   (((x) & TFPORT_MASK) >> TFPORT_SHIFT)
-#define  TFDROP          0x00020000U
-#define  TFSOPEOPERR     0x00010000U
-#define  TFLENGTH_MASK   0x00001f00U
-#define  TFLENGTH_SHIFT  8
-#define  TFLENGTH(x)     ((x) << TFLENGTH_SHIFT)
-#define  TFLENGTH_GET(x) (((x) & TFLENGTH_MASK) >> TFLENGTH_SHIFT)
-#define  TFOFFSET_MASK   0x0000001fU
-#define  TFOFFSET_SHIFT  0
-#define  TFOFFSET(x)     ((x) << TFOFFSET_SHIFT)
-#define  TFOFFSET_GET(x) (((x) & TFOFFSET_MASK) >> TFOFFSET_SHIFT)
-
-#define MPS_TRC_FILTER_MATCH_CTL_B 0x9820
-#define  TFMINPKTSIZE_MASK   0x01ff0000U
-#define  TFMINPKTSIZE_SHIFT  16
-#define  TFMINPKTSIZE(x)     ((x) << TFMINPKTSIZE_SHIFT)
-#define  TFMINPKTSIZE_GET(x) (((x) & TFMINPKTSIZE_MASK) >> TFMINPKTSIZE_SHIFT)
-#define  TFCAPTUREMAX_MASK   0x00003fffU
-#define  TFCAPTUREMAX_SHIFT  0
-#define  TFCAPTUREMAX(x)     ((x) << TFCAPTUREMAX_SHIFT)
-#define  TFCAPTUREMAX_GET(x) (((x) & TFCAPTUREMAX_MASK) >> TFCAPTUREMAX_SHIFT)
-
-#define MPS_TRC_INT_CAUSE 0x985c
-#define  MISCPERR 0x00000100U
-#define  PKTFIFO  0x000000f0U
-#define  FILTMEM  0x0000000fU
-
-#define MPS_TRC_FILTER0_MATCH 0x9c00
-#define MPS_TRC_FILTER0_DONT_CARE 0x9c80
-#define MPS_TRC_FILTER1_MATCH 0x9d00
-#define MPS_CLS_INT_CAUSE 0xd028
-#define  PLERRENB  0x00000008U
-#define  HASHSRAM  0x00000004U
-#define  MATCHTCAM 0x00000002U
-#define  MATCHSRAM 0x00000001U
-
-#define MPS_RX_PERR_INT_CAUSE 0x11074
-
-#define CPL_INTR_CAUSE 0x19054
-#define  CIM_OP_MAP_PERR   0x00000020U
-#define  CIM_OVFL_ERROR    0x00000010U
-#define  TP_FRAMING_ERROR  0x00000008U
-#define  SGE_FRAMING_ERROR 0x00000004U
-#define  CIM_FRAMING_ERROR 0x00000002U
-#define  ZERO_SWITCH_ERROR 0x00000001U
-
-#define SMB_INT_CAUSE 0x19090
-#define  MSTTXFIFOPARINT 0x00200000U
-#define  MSTRXFIFOPARINT 0x00100000U
-#define  SLVFIFOPARINT   0x00080000U
-
-#define ULP_RX_INT_CAUSE 0x19158
-#define ULP_RX_ISCSI_TAGMASK 0x19164
-#define ULP_RX_ISCSI_PSZ 0x19168
-#define  HPZ3_MASK   0x0f000000U
-#define  HPZ3_SHIFT  24
-#define  HPZ3(x)     ((x) << HPZ3_SHIFT)
-#define  HPZ2_MASK   0x000f0000U
-#define  HPZ2_SHIFT  16
-#define  HPZ2(x)     ((x) << HPZ2_SHIFT)
-#define  HPZ1_MASK   0x00000f00U
-#define  HPZ1_SHIFT  8
-#define  HPZ1(x)     ((x) << HPZ1_SHIFT)
-#define  HPZ0_MASK   0x0000000fU
-#define  HPZ0_SHIFT  0
-#define  HPZ0(x)     ((x) << HPZ0_SHIFT)
-
-#define ULP_RX_TDDP_PSZ 0x19178
-
-#define SF_DATA 0x193f8
-#define SF_OP 0x193fc
-#define  BUSY          0x80000000U
-#define  SF_LOCK       0x00000010U
-#define  SF_CONT       0x00000008U
-#define  BYTECNT_MASK  0x00000006U
-#define  BYTECNT_SHIFT 1
-#define  BYTECNT(x)    ((x) << BYTECNT_SHIFT)
-#define  OP_WR         0x00000001U
-
-#define PL_PF_INT_CAUSE 0x3c0
-#define  PFSW  0x00000008U
-#define  PFSGE 0x00000004U
-#define  PFCIM 0x00000002U
-#define  PFMPS 0x00000001U
-
-#define PL_PF_INT_ENABLE 0x3c4
-#define PL_PF_CTL 0x3c8
-#define  SWINT 0x00000001U
-
-#define PL_WHOAMI 0x19400
-#define  SOURCEPF_MASK   0x00000700U
-#define  SOURCEPF_SHIFT  8
-#define  SOURCEPF(x)     ((x) << SOURCEPF_SHIFT)
-#define  SOURCEPF_GET(x) (((x) & SOURCEPF_MASK) >> SOURCEPF_SHIFT)
-#define  ISVF            0x00000080U
-#define  VFID_MASK       0x0000007fU
-#define  VFID_SHIFT      0
-#define  VFID(x)         ((x) << VFID_SHIFT)
-#define  VFID_GET(x)     (((x) & VFID_MASK) >> VFID_SHIFT)
-
-#define PL_INT_CAUSE 0x1940c
-#define  ULP_TX     0x08000000U
-#define  SGE        0x04000000U
-#define  HMA        0x02000000U
-#define  CPL_SWITCH 0x01000000U
-#define  ULP_RX     0x00800000U
-#define  PM_RX      0x00400000U
-#define  PM_TX      0x00200000U
-#define  MA         0x00100000U
-#define  TP         0x00080000U
-#define  LE         0x00040000U
-#define  EDC1       0x00020000U
-#define  EDC0       0x00010000U
-#define  MC         0x00008000U
-#define  PCIE       0x00004000U
-#define  PMU        0x00002000U
-#define  XGMAC_KR1  0x00001000U
-#define  XGMAC_KR0  0x00000800U
-#define  XGMAC1     0x00000400U
-#define  XGMAC0     0x00000200U
-#define  SMB        0x00000100U
-#define  SF         0x00000080U
-#define  PL         0x00000040U
-#define  NCSI       0x00000020U
-#define  MPS        0x00000010U
-#define  MI         0x00000008U
-#define  DBG        0x00000004U
-#define  I2CM       0x00000002U
-#define  CIM        0x00000001U
-
-#define PL_INT_MAP0 0x19414
-#define PL_RST 0x19428
-#define  PIORST     0x00000002U
-#define  PIORSTMODE 0x00000001U
-
-#define PL_PL_INT_CAUSE 0x19430
-#define  FATALPERR 0x00000010U
-#define  PERRVFID  0x00000001U
-
-#define PL_REV 0x1943c
-
-#define LE_DB_CONFIG 0x19c04
-#define  HASHEN 0x00100000U
-
-#define LE_DB_SERVER_INDEX 0x19c18
-#define LE_DB_ACT_CNT_IPV4 0x19c20
-#define LE_DB_ACT_CNT_IPV6 0x19c24
-
-#define LE_DB_INT_CAUSE 0x19c3c
-#define  REQQPARERR 0x00010000U
-#define  UNKNOWNCMD 0x00008000U
-#define  PARITYERR  0x00000040U
-#define  LIPMISS    0x00000020U
-#define  LIP0       0x00000010U
-
-#define LE_DB_TID_HASHBASE 0x19df8
-
-#define NCSI_INT_CAUSE 0x1a0d8
-#define  CIM_DM_PRTY_ERR 0x00000100U
-#define  MPS_DM_PRTY_ERR 0x00000080U
-#define  TXFIFO_PRTY_ERR 0x00000002U
-#define  RXFIFO_PRTY_ERR 0x00000001U
-
-#define XGMAC_PORT_CFG2 0x1018
-#define  PATEN   0x00040000U
-#define  MAGICEN 0x00020000U
-
-#define XGMAC_PORT_MAGIC_MACID_LO 0x1024
-#define XGMAC_PORT_MAGIC_MACID_HI 0x1028
-
-#define XGMAC_PORT_EPIO_DATA0 0x10c0
-#define XGMAC_PORT_EPIO_DATA1 0x10c4
-#define XGMAC_PORT_EPIO_DATA2 0x10c8
-#define XGMAC_PORT_EPIO_DATA3 0x10cc
-#define XGMAC_PORT_EPIO_OP 0x10d0
-#define  EPIOWR         0x00000100U
-#define  ADDRESS_MASK   0x000000ffU
-#define  ADDRESS_SHIFT  0
-#define  ADDRESS(x)     ((x) << ADDRESS_SHIFT)
-
-#define XGMAC_PORT_INT_CAUSE 0x10dc
-#endif /* __T4_REGS_H */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4vf/adapter.h linux-libre-3.2-gnu/drivers/net/cxgb4vf/adapter.h
--- linux-libre-3.1-gnu/drivers/net/cxgb4vf/adapter.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4vf/adapter.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,534 +0,0 @@
-/*
- * This file is part of the Chelsio T4 PCI-E SR-IOV Virtual Function Ethernet
- * driver for Linux.
- *
- * Copyright (c) 2009-2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
- * This file should not be included directly.  Include t4vf_common.h instead.
- */
-
-#ifndef __CXGB4VF_ADAPTER_H__
-#define __CXGB4VF_ADAPTER_H__
-
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/skbuff.h>
-#include <linux/if_ether.h>
-#include <linux/netdevice.h>
-
-#include "../cxgb4/t4_hw.h"
-
-/*
- * Constants of the implementation.
- */
-enum {
-	MAX_NPORTS	= 1,		/* max # of "ports" */
-	MAX_PORT_QSETS	= 8,		/* max # of Queue Sets / "port" */
-	MAX_ETH_QSETS	= MAX_NPORTS*MAX_PORT_QSETS,
-
-	/*
-	 * MSI-X interrupt index usage.
-	 */
-	MSIX_FW		= 0,		/* MSI-X index for firmware Q */
-	MSIX_IQFLINT	= 1,		/* MSI-X index base for Ingress Qs */
-	MSIX_EXTRAS	= 1,
-	MSIX_ENTRIES	= MAX_ETH_QSETS + MSIX_EXTRAS,
-
-	/*
-	 * The maximum number of Ingress and Egress Queues is determined by
-	 * the maximum number of "Queue Sets" which we support plus any
-	 * ancillary queues.  Each "Queue Set" requires one Ingress Queue
-	 * for RX Packet Ingress Event notifications and two Egress Queues for
-	 * a Free List and an Ethernet TX list.
-	 */
-	INGQ_EXTRAS	= 2,		/* firmware event queue and */
-					/*   forwarded interrupts */
-	MAX_INGQ	= MAX_ETH_QSETS+INGQ_EXTRAS,
-	MAX_EGRQ	= MAX_ETH_QSETS*2,
-};
-
-/*
- * Forward structure definition references.
- */
-struct adapter;
-struct sge_eth_rxq;
-struct sge_rspq;
-
-/*
- * Per-"port" information.  This is really per-Virtual Interface information
- * but the use of the "port" nomanclature makes it easier to go back and forth
- * between the PF and VF drivers ...
- */
-struct port_info {
-	struct adapter *adapter;	/* our adapter */
-	u16 viid;			/* virtual interface ID */
-	s16 xact_addr_filt;		/* index of our MAC address filter */
-	u16 rss_size;			/* size of VI's RSS table slice */
-	u8 pidx;			/* index into adapter port[] */
-	u8 port_id;			/* physical port ID */
-	u8 nqsets;			/* # of "Queue Sets" */
-	u8 first_qset;			/* index of first "Queue Set" */
-	struct link_config link_cfg;	/* physical port configuration */
-};
-
-/*
- * Scatter Gather Engine resources for the "adapter".  Our ingress and egress
- * queues are organized into "Queue Sets" with one ingress and one egress
- * queue per Queue Set.  These Queue Sets are aportionable between the "ports"
- * (Virtual Interfaces).  One extra ingress queue is used to receive
- * asynchronous messages from the firmware.  Note that the "Queue IDs" that we
- * use here are really "Relative Queue IDs" which are returned as part of the
- * firmware command to allocate queues.  These queue IDs are relative to the
- * absolute Queue ID base of the section of the Queue ID space allocated to
- * the PF/VF.
- */
-
-/*
- * SGE free-list queue state.
- */
-struct rx_sw_desc;
-struct sge_fl {
-	unsigned int avail;		/* # of available RX buffers */
-	unsigned int pend_cred;		/* new buffers since last FL DB ring */
-	unsigned int cidx;		/* consumer index */
-	unsigned int pidx;		/* producer index */
-	unsigned long alloc_failed;	/* # of buffer allocation failures */
-	unsigned long large_alloc_failed;
-	unsigned long starving;		/* # of times FL was found starving */
-
-	/*
-	 * Write-once/infrequently fields.
-	 * -------------------------------
-	 */
-
-	unsigned int cntxt_id;		/* SGE relative QID for the free list */
-	unsigned int abs_id;		/* SGE absolute QID for the free list */
-	unsigned int size;		/* capacity of free list */
-	struct rx_sw_desc *sdesc;	/* address of SW RX descriptor ring */
-	__be64 *desc;			/* address of HW RX descriptor ring */
-	dma_addr_t addr;		/* PCI bus address of hardware ring */
-};
-
-/*
- * An ingress packet gather list.
- */
-struct pkt_gl {
-	skb_frag_t frags[MAX_SKB_FRAGS];
-	void *va;			/* virtual address of first byte */
-	unsigned int nfrags;		/* # of fragments */
-	unsigned int tot_len;		/* total length of fragments */
-};
-
-typedef int (*rspq_handler_t)(struct sge_rspq *, const __be64 *,
-			      const struct pkt_gl *);
-
-/*
- * State for an SGE Response Queue.
- */
-struct sge_rspq {
-	struct napi_struct napi;	/* NAPI scheduling control */
-	const __be64 *cur_desc;		/* current descriptor in queue */
-	unsigned int cidx;		/* consumer index */
-	u8 gen;				/* current generation bit */
-	u8 next_intr_params;		/* holdoff params for next interrupt */
-	int offset;			/* offset into current FL buffer */
-
-	unsigned int unhandled_irqs;	/* bogus interrupts */
-
-	/*
-	 * Write-once/infrequently fields.
-	 * -------------------------------
-	 */
-
-	u8 intr_params;			/* interrupt holdoff parameters */
-	u8 pktcnt_idx;			/* interrupt packet threshold */
-	u8 idx;				/* queue index within its group */
-	u16 cntxt_id;			/* SGE rel QID for the response Q */
-	u16 abs_id;			/* SGE abs QID for the response Q */
-	__be64 *desc;			/* address of hardware response ring */
-	dma_addr_t phys_addr;		/* PCI bus address of ring */
-	unsigned int iqe_len;		/* entry size */
-	unsigned int size;		/* capcity of response Q */
-	struct adapter *adapter;	/* our adapter */
-	struct net_device *netdev;	/* associated net device */
-	rspq_handler_t handler;		/* the handler for this response Q */
-};
-
-/*
- * Ethernet queue statistics
- */
-struct sge_eth_stats {
-	unsigned long pkts;		/* # of ethernet packets */
-	unsigned long lro_pkts;		/* # of LRO super packets */
-	unsigned long lro_merged;	/* # of wire packets merged by LRO */
-	unsigned long rx_cso;		/* # of Rx checksum offloads */
-	unsigned long vlan_ex;		/* # of Rx VLAN extractions */
-	unsigned long rx_drops;		/* # of packets dropped due to no mem */
-};
-
-/*
- * State for an Ethernet Receive Queue.
- */
-struct sge_eth_rxq {
-	struct sge_rspq rspq;		/* Response Queue */
-	struct sge_fl fl;		/* Free List */
-	struct sge_eth_stats stats;	/* receive statistics */
-};
-
-/*
- * SGE Transmit Queue state.  This contains all of the resources associated
- * with the hardware status of a TX Queue which is a circular ring of hardware
- * TX Descriptors.  For convenience, it also contains a pointer to a parallel
- * "Software Descriptor" array but we don't know anything about it here other
- * than its type name.
- */
-struct tx_desc {
-	/*
-	 * Egress Queues are measured in units of SGE_EQ_IDXSIZE by the
-	 * hardware: Sizes, Producer and Consumer indices, etc.
-	 */
-	__be64 flit[SGE_EQ_IDXSIZE/sizeof(__be64)];
-};
-struct tx_sw_desc;
-struct sge_txq {
-	unsigned int in_use;		/* # of in-use TX descriptors */
-	unsigned int size;		/* # of descriptors */
-	unsigned int cidx;		/* SW consumer index */
-	unsigned int pidx;		/* producer index */
-	unsigned long stops;		/* # of times queue has been stopped */
-	unsigned long restarts;		/* # of queue restarts */
-
-	/*
-	 * Write-once/infrequently fields.
-	 * -------------------------------
-	 */
-
-	unsigned int cntxt_id;		/* SGE relative QID for the TX Q */
-	unsigned int abs_id;		/* SGE absolute QID for the TX Q */
-	struct tx_desc *desc;		/* address of HW TX descriptor ring */
-	struct tx_sw_desc *sdesc;	/* address of SW TX descriptor ring */
-	struct sge_qstat *stat;		/* queue status entry */
-	dma_addr_t phys_addr;		/* PCI bus address of hardware ring */
-};
-
-/*
- * State for an Ethernet Transmit Queue.
- */
-struct sge_eth_txq {
-	struct sge_txq q;		/* SGE TX Queue */
-	struct netdev_queue *txq;	/* associated netdev TX queue */
-	unsigned long tso;		/* # of TSO requests */
-	unsigned long tx_cso;		/* # of TX checksum offloads */
-	unsigned long vlan_ins;		/* # of TX VLAN insertions */
-	unsigned long mapping_err;	/* # of I/O MMU packet mapping errors */
-};
-
-/*
- * The complete set of Scatter/Gather Engine resources.
- */
-struct sge {
-	/*
-	 * Our "Queue Sets" ...
-	 */
-	struct sge_eth_txq ethtxq[MAX_ETH_QSETS];
-	struct sge_eth_rxq ethrxq[MAX_ETH_QSETS];
-
-	/*
-	 * Extra ingress queues for asynchronous firmware events and
-	 * forwarded interrupts (when in MSI mode).
-	 */
-	struct sge_rspq fw_evtq ____cacheline_aligned_in_smp;
-
-	struct sge_rspq intrq ____cacheline_aligned_in_smp;
-	spinlock_t intrq_lock;
-
-	/*
-	 * State for managing "starving Free Lists" -- Free Lists which have
-	 * fallen below a certain threshold of buffers available to the
-	 * hardware and attempts to refill them up to that threshold have
-	 * failed.  We have a regular "slow tick" timer process which will
-	 * make periodic attempts to refill these starving Free Lists ...
-	 */
-	DECLARE_BITMAP(starving_fl, MAX_EGRQ);
-	struct timer_list rx_timer;
-
-	/*
-	 * State for cleaning up completed TX descriptors.
-	 */
-	struct timer_list tx_timer;
-
-	/*
-	 * Write-once/infrequently fields.
-	 * -------------------------------
-	 */
-
-	u16 max_ethqsets;		/* # of available Ethernet queue sets */
-	u16 ethqsets;			/* # of active Ethernet queue sets */
-	u16 ethtxq_rover;		/* Tx queue to clean up next */
-	u16 timer_val[SGE_NTIMERS];	/* interrupt holdoff timer array */
-	u8 counter_val[SGE_NCOUNTERS];	/* interrupt RX threshold array */
-
-	/*
-	 * Reverse maps from Absolute Queue IDs to associated queue pointers.
-	 * The absolute Queue IDs are in a compact range which start at a
-	 * [potentially large] Base Queue ID.  We perform the reverse map by
-	 * first converting the Absolute Queue ID into a Relative Queue ID by
-	 * subtracting off the Base Queue ID and then use a Relative Queue ID
-	 * indexed table to get the pointer to the corresponding software
-	 * queue structure.
-	 */
-	unsigned int egr_base;
-	unsigned int ingr_base;
-	void *egr_map[MAX_EGRQ];
-	struct sge_rspq *ingr_map[MAX_INGQ];
-};
-
-/*
- * Utility macros to convert Absolute- to Relative-Queue indices and Egress-
- * and Ingress-Queues.  The EQ_MAP() and IQ_MAP() macros which provide
- * pointers to Ingress- and Egress-Queues can be used as both L- and R-values
- */
-#define EQ_IDX(s, abs_id) ((unsigned int)((abs_id) - (s)->egr_base))
-#define IQ_IDX(s, abs_id) ((unsigned int)((abs_id) - (s)->ingr_base))
-
-#define EQ_MAP(s, abs_id) ((s)->egr_map[EQ_IDX(s, abs_id)])
-#define IQ_MAP(s, abs_id) ((s)->ingr_map[IQ_IDX(s, abs_id)])
-
-/*
- * Macro to iterate across Queue Sets ("rxq" is a historic misnomer).
- */
-#define for_each_ethrxq(sge, iter) \
-	for (iter = 0; iter < (sge)->ethqsets; iter++)
-
-/*
- * Per-"adapter" (Virtual Function) information.
- */
-struct adapter {
-	/* PCI resources */
-	void __iomem *regs;
-	struct pci_dev *pdev;
-	struct device *pdev_dev;
-
-	/* "adapter" resources */
-	unsigned long registered_device_map;
-	unsigned long open_device_map;
-	unsigned long flags;
-	struct adapter_params params;
-
-	/* queue and interrupt resources */
-	struct {
-		unsigned short vec;
-		char desc[22];
-	} msix_info[MSIX_ENTRIES];
-	struct sge sge;
-
-	/* Linux network device resources */
-	struct net_device *port[MAX_NPORTS];
-	const char *name;
-	unsigned int msg_enable;
-
-	/* debugfs resources */
-	struct dentry *debugfs_root;
-
-	/* various locks */
-	spinlock_t stats_lock;
-};
-
-enum { /* adapter flags */
-	FULL_INIT_DONE     = (1UL << 0),
-	USING_MSI          = (1UL << 1),
-	USING_MSIX         = (1UL << 2),
-	QUEUES_BOUND       = (1UL << 3),
-};
-
-/*
- * The following register read/write routine definitions are required by
- * the common code.
- */
-
-/**
- * t4_read_reg - read a HW register
- * @adapter: the adapter
- * @reg_addr: the register address
- *
- * Returns the 32-bit value of the given HW register.
- */
-static inline u32 t4_read_reg(struct adapter *adapter, u32 reg_addr)
-{
-	return readl(adapter->regs + reg_addr);
-}
-
-/**
- * t4_write_reg - write a HW register
- * @adapter: the adapter
- * @reg_addr: the register address
- * @val: the value to write
- *
- * Write a 32-bit value into the given HW register.
- */
-static inline void t4_write_reg(struct adapter *adapter, u32 reg_addr, u32 val)
-{
-	writel(val, adapter->regs + reg_addr);
-}
-
-#ifndef readq
-static inline u64 readq(const volatile void __iomem *addr)
-{
-	return readl(addr) + ((u64)readl(addr + 4) << 32);
-}
-
-static inline void writeq(u64 val, volatile void __iomem *addr)
-{
-	writel(val, addr);
-	writel(val >> 32, addr + 4);
-}
-#endif
-
-/**
- * t4_read_reg64 - read a 64-bit HW register
- * @adapter: the adapter
- * @reg_addr: the register address
- *
- * Returns the 64-bit value of the given HW register.
- */
-static inline u64 t4_read_reg64(struct adapter *adapter, u32 reg_addr)
-{
-	return readq(adapter->regs + reg_addr);
-}
-
-/**
- * t4_write_reg64 - write a 64-bit HW register
- * @adapter: the adapter
- * @reg_addr: the register address
- * @val: the value to write
- *
- * Write a 64-bit value into the given HW register.
- */
-static inline void t4_write_reg64(struct adapter *adapter, u32 reg_addr,
-				  u64 val)
-{
-	writeq(val, adapter->regs + reg_addr);
-}
-
-/**
- * port_name - return the string name of a port
- * @adapter: the adapter
- * @pidx: the port index
- *
- * Return the string name of the selected port.
- */
-static inline const char *port_name(struct adapter *adapter, int pidx)
-{
-	return adapter->port[pidx]->name;
-}
-
-/**
- * t4_os_set_hw_addr - store a port's MAC address in SW
- * @adapter: the adapter
- * @pidx: the port index
- * @hw_addr: the Ethernet address
- *
- * Store the Ethernet address of the given port in SW.  Called by the common
- * code when it retrieves a port's Ethernet address from EEPROM.
- */
-static inline void t4_os_set_hw_addr(struct adapter *adapter, int pidx,
-				     u8 hw_addr[])
-{
-	memcpy(adapter->port[pidx]->dev_addr, hw_addr, ETH_ALEN);
-	memcpy(adapter->port[pidx]->perm_addr, hw_addr, ETH_ALEN);
-}
-
-/**
- * netdev2pinfo - return the port_info structure associated with a net_device
- * @dev: the netdev
- *
- * Return the struct port_info associated with a net_device
- */
-static inline struct port_info *netdev2pinfo(const struct net_device *dev)
-{
-	return netdev_priv(dev);
-}
-
-/**
- * adap2pinfo - return the port_info of a port
- * @adap: the adapter
- * @pidx: the port index
- *
- * Return the port_info structure for the adapter.
- */
-static inline struct port_info *adap2pinfo(struct adapter *adapter, int pidx)
-{
-	return netdev_priv(adapter->port[pidx]);
-}
-
-/**
- * netdev2adap - return the adapter structure associated with a net_device
- * @dev: the netdev
- *
- * Return the struct adapter associated with a net_device
- */
-static inline struct adapter *netdev2adap(const struct net_device *dev)
-{
-	return netdev2pinfo(dev)->adapter;
-}
-
-/*
- * OS "Callback" function declarations.  These are functions that the OS code
- * is "contracted" to provide for the common code.
- */
-void t4vf_os_link_changed(struct adapter *, int, int);
-
-/*
- * SGE function prototype declarations.
- */
-int t4vf_sge_alloc_rxq(struct adapter *, struct sge_rspq *, bool,
-		       struct net_device *, int,
-		       struct sge_fl *, rspq_handler_t);
-int t4vf_sge_alloc_eth_txq(struct adapter *, struct sge_eth_txq *,
-			   struct net_device *, struct netdev_queue *,
-			   unsigned int);
-void t4vf_free_sge_resources(struct adapter *);
-
-int t4vf_eth_xmit(struct sk_buff *, struct net_device *);
-int t4vf_ethrx_handler(struct sge_rspq *, const __be64 *,
-		       const struct pkt_gl *);
-
-irq_handler_t t4vf_intr_handler(struct adapter *);
-irqreturn_t t4vf_sge_intr_msix(int, void *);
-
-int t4vf_sge_init(struct adapter *);
-void t4vf_sge_start(struct adapter *);
-void t4vf_sge_stop(struct adapter *);
-
-#endif /* __CXGB4VF_ADAPTER_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4vf/cxgb4vf_main.c linux-libre-3.2-gnu/drivers/net/cxgb4vf/cxgb4vf_main.c
--- linux-libre-3.1-gnu/drivers/net/cxgb4vf/cxgb4vf_main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4vf/cxgb4vf_main.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2947 +0,0 @@
-/*
- * This file is part of the Chelsio T4 PCI-E SR-IOV Virtual Function Ethernet
- * driver for Linux.
- *
- * Copyright (c) 2009-2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/debugfs.h>
-#include <linux/ethtool.h>
-
-#include "t4vf_common.h"
-#include "t4vf_defs.h"
-
-#include "../cxgb4/t4_regs.h"
-#include "../cxgb4/t4_msg.h"
-
-/*
- * Generic information about the driver.
- */
-#define DRV_VERSION "1.0.0"
-#define DRV_DESC "Chelsio T4 Virtual Function (VF) Network Driver"
-
-/*
- * Module Parameters.
- * ==================
- */
-
-/*
- * Default ethtool "message level" for adapters.
- */
-#define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \
-			 NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\
-			 NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
-
-static int dflt_msg_enable = DFLT_MSG_ENABLE;
-
-module_param(dflt_msg_enable, int, 0644);
-MODULE_PARM_DESC(dflt_msg_enable,
-		 "default adapter ethtool message level bitmap");
-
-/*
- * The driver uses the best interrupt scheme available on a platform in the
- * order MSI-X then MSI.  This parameter determines which of these schemes the
- * driver may consider as follows:
- *
- *     msi = 2: choose from among MSI-X and MSI
- *     msi = 1: only consider MSI interrupts
- *
- * Note that unlike the Physical Function driver, this Virtual Function driver
- * does _not_ support legacy INTx interrupts (this limitation is mandated by
- * the PCI-E SR-IOV standard).
- */
-#define MSI_MSIX	2
-#define MSI_MSI		1
-#define MSI_DEFAULT	MSI_MSIX
-
-static int msi = MSI_DEFAULT;
-
-module_param(msi, int, 0644);
-MODULE_PARM_DESC(msi, "whether to use MSI-X or MSI");
-
-/*
- * Fundamental constants.
- * ======================
- */
-
-enum {
-	MAX_TXQ_ENTRIES		= 16384,
-	MAX_RSPQ_ENTRIES	= 16384,
-	MAX_RX_BUFFERS		= 16384,
-
-	MIN_TXQ_ENTRIES		= 32,
-	MIN_RSPQ_ENTRIES	= 128,
-	MIN_FL_ENTRIES		= 16,
-
-	/*
-	 * For purposes of manipulating the Free List size we need to
-	 * recognize that Free Lists are actually Egress Queues (the host
-	 * produces free buffers which the hardware consumes), Egress Queues
-	 * indices are all in units of Egress Context Units bytes, and free
-	 * list entries are 64-bit PCI DMA addresses.  And since the state of
-	 * the Producer Index == the Consumer Index implies an EMPTY list, we
-	 * always have at least one Egress Unit's worth of Free List entries
-	 * unused.  See sge.c for more details ...
-	 */
-	EQ_UNIT = SGE_EQ_IDXSIZE,
-	FL_PER_EQ_UNIT = EQ_UNIT / sizeof(__be64),
-	MIN_FL_RESID = FL_PER_EQ_UNIT,
-};
-
-/*
- * Global driver state.
- * ====================
- */
-
-static struct dentry *cxgb4vf_debugfs_root;
-
-/*
- * OS "Callback" functions.
- * ========================
- */
-
-/*
- * The link status has changed on the indicated "port" (Virtual Interface).
- */
-void t4vf_os_link_changed(struct adapter *adapter, int pidx, int link_ok)
-{
-	struct net_device *dev = adapter->port[pidx];
-
-	/*
-	 * If the port is disabled or the current recorded "link up"
-	 * status matches the new status, just return.
-	 */
-	if (!netif_running(dev) || link_ok == netif_carrier_ok(dev))
-		return;
-
-	/*
-	 * Tell the OS that the link status has changed and print a short
-	 * informative message on the console about the event.
-	 */
-	if (link_ok) {
-		const char *s;
-		const char *fc;
-		const struct port_info *pi = netdev_priv(dev);
-
-		netif_carrier_on(dev);
-
-		switch (pi->link_cfg.speed) {
-		case SPEED_10000:
-			s = "10Gbps";
-			break;
-
-		case SPEED_1000:
-			s = "1000Mbps";
-			break;
-
-		case SPEED_100:
-			s = "100Mbps";
-			break;
-
-		default:
-			s = "unknown";
-			break;
-		}
-
-		switch (pi->link_cfg.fc) {
-		case PAUSE_RX:
-			fc = "RX";
-			break;
-
-		case PAUSE_TX:
-			fc = "TX";
-			break;
-
-		case PAUSE_RX|PAUSE_TX:
-			fc = "RX/TX";
-			break;
-
-		default:
-			fc = "no";
-			break;
-		}
-
-		printk(KERN_INFO "%s: link up, %s, full-duplex, %s PAUSE\n",
-		       dev->name, s, fc);
-	} else {
-		netif_carrier_off(dev);
-		printk(KERN_INFO "%s: link down\n", dev->name);
-	}
-}
-
-/*
- * Net device operations.
- * ======================
- */
-
-
-
-
-/*
- * Perform the MAC and PHY actions needed to enable a "port" (Virtual
- * Interface).
- */
-static int link_start(struct net_device *dev)
-{
-	int ret;
-	struct port_info *pi = netdev_priv(dev);
-
-	/*
-	 * We do not set address filters and promiscuity here, the stack does
-	 * that step explicitly. Enable vlan accel.
-	 */
-	ret = t4vf_set_rxmode(pi->adapter, pi->viid, dev->mtu, -1, -1, -1, 1,
-			      true);
-	if (ret == 0) {
-		ret = t4vf_change_mac(pi->adapter, pi->viid,
-				      pi->xact_addr_filt, dev->dev_addr, true);
-		if (ret >= 0) {
-			pi->xact_addr_filt = ret;
-			ret = 0;
-		}
-	}
-
-	/*
-	 * We don't need to actually "start the link" itself since the
-	 * firmware will do that for us when the first Virtual Interface
-	 * is enabled on a port.
-	 */
-	if (ret == 0)
-		ret = t4vf_enable_vi(pi->adapter, pi->viid, true, true);
-	return ret;
-}
-
-/*
- * Name the MSI-X interrupts.
- */
-static void name_msix_vecs(struct adapter *adapter)
-{
-	int namelen = sizeof(adapter->msix_info[0].desc) - 1;
-	int pidx;
-
-	/*
-	 * Firmware events.
-	 */
-	snprintf(adapter->msix_info[MSIX_FW].desc, namelen,
-		 "%s-FWeventq", adapter->name);
-	adapter->msix_info[MSIX_FW].desc[namelen] = 0;
-
-	/*
-	 * Ethernet queues.
-	 */
-	for_each_port(adapter, pidx) {
-		struct net_device *dev = adapter->port[pidx];
-		const struct port_info *pi = netdev_priv(dev);
-		int qs, msi;
-
-		for (qs = 0, msi = MSIX_IQFLINT; qs < pi->nqsets; qs++, msi++) {
-			snprintf(adapter->msix_info[msi].desc, namelen,
-				 "%s-%d", dev->name, qs);
-			adapter->msix_info[msi].desc[namelen] = 0;
-		}
-	}
-}
-
-/*
- * Request all of our MSI-X resources.
- */
-static int request_msix_queue_irqs(struct adapter *adapter)
-{
-	struct sge *s = &adapter->sge;
-	int rxq, msi, err;
-
-	/*
-	 * Firmware events.
-	 */
-	err = request_irq(adapter->msix_info[MSIX_FW].vec, t4vf_sge_intr_msix,
-			  0, adapter->msix_info[MSIX_FW].desc, &s->fw_evtq);
-	if (err)
-		return err;
-
-	/*
-	 * Ethernet queues.
-	 */
-	msi = MSIX_IQFLINT;
-	for_each_ethrxq(s, rxq) {
-		err = request_irq(adapter->msix_info[msi].vec,
-				  t4vf_sge_intr_msix, 0,
-				  adapter->msix_info[msi].desc,
-				  &s->ethrxq[rxq].rspq);
-		if (err)
-			goto err_free_irqs;
-		msi++;
-	}
-	return 0;
-
-err_free_irqs:
-	while (--rxq >= 0)
-		free_irq(adapter->msix_info[--msi].vec, &s->ethrxq[rxq].rspq);
-	free_irq(adapter->msix_info[MSIX_FW].vec, &s->fw_evtq);
-	return err;
-}
-
-/*
- * Free our MSI-X resources.
- */
-static void free_msix_queue_irqs(struct adapter *adapter)
-{
-	struct sge *s = &adapter->sge;
-	int rxq, msi;
-
-	free_irq(adapter->msix_info[MSIX_FW].vec, &s->fw_evtq);
-	msi = MSIX_IQFLINT;
-	for_each_ethrxq(s, rxq)
-		free_irq(adapter->msix_info[msi++].vec,
-			 &s->ethrxq[rxq].rspq);
-}
-
-/*
- * Turn on NAPI and start up interrupts on a response queue.
- */
-static void qenable(struct sge_rspq *rspq)
-{
-	napi_enable(&rspq->napi);
-
-	/*
-	 * 0-increment the Going To Sleep register to start the timer and
-	 * enable interrupts.
-	 */
-	t4_write_reg(rspq->adapter, T4VF_SGE_BASE_ADDR + SGE_VF_GTS,
-		     CIDXINC(0) |
-		     SEINTARM(rspq->intr_params) |
-		     INGRESSQID(rspq->cntxt_id));
-}
-
-/*
- * Enable NAPI scheduling and interrupt generation for all Receive Queues.
- */
-static void enable_rx(struct adapter *adapter)
-{
-	int rxq;
-	struct sge *s = &adapter->sge;
-
-	for_each_ethrxq(s, rxq)
-		qenable(&s->ethrxq[rxq].rspq);
-	qenable(&s->fw_evtq);
-
-	/*
-	 * The interrupt queue doesn't use NAPI so we do the 0-increment of
-	 * its Going To Sleep register here to get it started.
-	 */
-	if (adapter->flags & USING_MSI)
-		t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_GTS,
-			     CIDXINC(0) |
-			     SEINTARM(s->intrq.intr_params) |
-			     INGRESSQID(s->intrq.cntxt_id));
-
-}
-
-/*
- * Wait until all NAPI handlers are descheduled.
- */
-static void quiesce_rx(struct adapter *adapter)
-{
-	struct sge *s = &adapter->sge;
-	int rxq;
-
-	for_each_ethrxq(s, rxq)
-		napi_disable(&s->ethrxq[rxq].rspq.napi);
-	napi_disable(&s->fw_evtq.napi);
-}
-
-/*
- * Response queue handler for the firmware event queue.
- */
-static int fwevtq_handler(struct sge_rspq *rspq, const __be64 *rsp,
-			  const struct pkt_gl *gl)
-{
-	/*
-	 * Extract response opcode and get pointer to CPL message body.
-	 */
-	struct adapter *adapter = rspq->adapter;
-	u8 opcode = ((const struct rss_header *)rsp)->opcode;
-	void *cpl = (void *)(rsp + 1);
-
-	switch (opcode) {
-	case CPL_FW6_MSG: {
-		/*
-		 * We've received an asynchronous message from the firmware.
-		 */
-		const struct cpl_fw6_msg *fw_msg = cpl;
-		if (fw_msg->type == FW6_TYPE_CMD_RPL)
-			t4vf_handle_fw_rpl(adapter, fw_msg->data);
-		break;
-	}
-
-	case CPL_SGE_EGR_UPDATE: {
-		/*
-		 * We've received an Egress Queue Status Update message.  We
-		 * get these, if the SGE is configured to send these when the
-		 * firmware passes certain points in processing our TX
-		 * Ethernet Queue or if we make an explicit request for one.
-		 * We use these updates to determine when we may need to
-		 * restart a TX Ethernet Queue which was stopped for lack of
-		 * free TX Queue Descriptors ...
-		 */
-		const struct cpl_sge_egr_update *p = (void *)cpl;
-		unsigned int qid = EGR_QID(be32_to_cpu(p->opcode_qid));
-		struct sge *s = &adapter->sge;
-		struct sge_txq *tq;
-		struct sge_eth_txq *txq;
-		unsigned int eq_idx;
-
-		/*
-		 * Perform sanity checking on the Queue ID to make sure it
-		 * really refers to one of our TX Ethernet Egress Queues which
-		 * is active and matches the queue's ID.  None of these error
-		 * conditions should ever happen so we may want to either make
-		 * them fatal and/or conditionalized under DEBUG.
-		 */
-		eq_idx = EQ_IDX(s, qid);
-		if (unlikely(eq_idx >= MAX_EGRQ)) {
-			dev_err(adapter->pdev_dev,
-				"Egress Update QID %d out of range\n", qid);
-			break;
-		}
-		tq = s->egr_map[eq_idx];
-		if (unlikely(tq == NULL)) {
-			dev_err(adapter->pdev_dev,
-				"Egress Update QID %d TXQ=NULL\n", qid);
-			break;
-		}
-		txq = container_of(tq, struct sge_eth_txq, q);
-		if (unlikely(tq->abs_id != qid)) {
-			dev_err(adapter->pdev_dev,
-				"Egress Update QID %d refers to TXQ %d\n",
-				qid, tq->abs_id);
-			break;
-		}
-
-		/*
-		 * Restart a stopped TX Queue which has less than half of its
-		 * TX ring in use ...
-		 */
-		txq->q.restarts++;
-		netif_tx_wake_queue(txq->txq);
-		break;
-	}
-
-	default:
-		dev_err(adapter->pdev_dev,
-			"unexpected CPL %#x on FW event queue\n", opcode);
-	}
-
-	return 0;
-}
-
-/*
- * Allocate SGE TX/RX response queues.  Determine how many sets of SGE queues
- * to use and initializes them.  We support multiple "Queue Sets" per port if
- * we have MSI-X, otherwise just one queue set per port.
- */
-static int setup_sge_queues(struct adapter *adapter)
-{
-	struct sge *s = &adapter->sge;
-	int err, pidx, msix;
-
-	/*
-	 * Clear "Queue Set" Free List Starving and TX Queue Mapping Error
-	 * state.
-	 */
-	bitmap_zero(s->starving_fl, MAX_EGRQ);
-
-	/*
-	 * If we're using MSI interrupt mode we need to set up a "forwarded
-	 * interrupt" queue which we'll set up with our MSI vector.  The rest
-	 * of the ingress queues will be set up to forward their interrupts to
-	 * this queue ...  This must be first since t4vf_sge_alloc_rxq() uses
-	 * the intrq's queue ID as the interrupt forwarding queue for the
-	 * subsequent calls ...
-	 */
-	if (adapter->flags & USING_MSI) {
-		err = t4vf_sge_alloc_rxq(adapter, &s->intrq, false,
-					 adapter->port[0], 0, NULL, NULL);
-		if (err)
-			goto err_free_queues;
-	}
-
-	/*
-	 * Allocate our ingress queue for asynchronous firmware messages.
-	 */
-	err = t4vf_sge_alloc_rxq(adapter, &s->fw_evtq, true, adapter->port[0],
-				 MSIX_FW, NULL, fwevtq_handler);
-	if (err)
-		goto err_free_queues;
-
-	/*
-	 * Allocate each "port"'s initial Queue Sets.  These can be changed
-	 * later on ... up to the point where any interface on the adapter is
-	 * brought up at which point lots of things get nailed down
-	 * permanently ...
-	 */
-	msix = MSIX_IQFLINT;
-	for_each_port(adapter, pidx) {
-		struct net_device *dev = adapter->port[pidx];
-		struct port_info *pi = netdev_priv(dev);
-		struct sge_eth_rxq *rxq = &s->ethrxq[pi->first_qset];
-		struct sge_eth_txq *txq = &s->ethtxq[pi->first_qset];
-		int qs;
-
-		for (qs = 0; qs < pi->nqsets; qs++, rxq++, txq++) {
-			err = t4vf_sge_alloc_rxq(adapter, &rxq->rspq, false,
-						 dev, msix++,
-						 &rxq->fl, t4vf_ethrx_handler);
-			if (err)
-				goto err_free_queues;
-
-			err = t4vf_sge_alloc_eth_txq(adapter, txq, dev,
-					     netdev_get_tx_queue(dev, qs),
-					     s->fw_evtq.cntxt_id);
-			if (err)
-				goto err_free_queues;
-
-			rxq->rspq.idx = qs;
-			memset(&rxq->stats, 0, sizeof(rxq->stats));
-		}
-	}
-
-	/*
-	 * Create the reverse mappings for the queues.
-	 */
-	s->egr_base = s->ethtxq[0].q.abs_id - s->ethtxq[0].q.cntxt_id;
-	s->ingr_base = s->ethrxq[0].rspq.abs_id - s->ethrxq[0].rspq.cntxt_id;
-	IQ_MAP(s, s->fw_evtq.abs_id) = &s->fw_evtq;
-	for_each_port(adapter, pidx) {
-		struct net_device *dev = adapter->port[pidx];
-		struct port_info *pi = netdev_priv(dev);
-		struct sge_eth_rxq *rxq = &s->ethrxq[pi->first_qset];
-		struct sge_eth_txq *txq = &s->ethtxq[pi->first_qset];
-		int qs;
-
-		for (qs = 0; qs < pi->nqsets; qs++, rxq++, txq++) {
-			IQ_MAP(s, rxq->rspq.abs_id) = &rxq->rspq;
-			EQ_MAP(s, txq->q.abs_id) = &txq->q;
-
-			/*
-			 * The FW_IQ_CMD doesn't return the Absolute Queue IDs
-			 * for Free Lists but since all of the Egress Queues
-			 * (including Free Lists) have Relative Queue IDs
-			 * which are computed as Absolute - Base Queue ID, we
-			 * can synthesize the Absolute Queue IDs for the Free
-			 * Lists.  This is useful for debugging purposes when
-			 * we want to dump Queue Contexts via the PF Driver.
-			 */
-			rxq->fl.abs_id = rxq->fl.cntxt_id + s->egr_base;
-			EQ_MAP(s, rxq->fl.abs_id) = &rxq->fl;
-		}
-	}
-	return 0;
-
-err_free_queues:
-	t4vf_free_sge_resources(adapter);
-	return err;
-}
-
-/*
- * Set up Receive Side Scaling (RSS) to distribute packets to multiple receive
- * queues.  We configure the RSS CPU lookup table to distribute to the number
- * of HW receive queues, and the response queue lookup table to narrow that
- * down to the response queues actually configured for each "port" (Virtual
- * Interface).  We always configure the RSS mapping for all ports since the
- * mapping table has plenty of entries.
- */
-static int setup_rss(struct adapter *adapter)
-{
-	int pidx;
-
-	for_each_port(adapter, pidx) {
-		struct port_info *pi = adap2pinfo(adapter, pidx);
-		struct sge_eth_rxq *rxq = &adapter->sge.ethrxq[pi->first_qset];
-		u16 rss[MAX_PORT_QSETS];
-		int qs, err;
-
-		for (qs = 0; qs < pi->nqsets; qs++)
-			rss[qs] = rxq[qs].rspq.abs_id;
-
-		err = t4vf_config_rss_range(adapter, pi->viid,
-					    0, pi->rss_size, rss, pi->nqsets);
-		if (err)
-			return err;
-
-		/*
-		 * Perform Global RSS Mode-specific initialization.
-		 */
-		switch (adapter->params.rss.mode) {
-		case FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL:
-			/*
-			 * If Tunnel All Lookup isn't specified in the global
-			 * RSS Configuration, then we need to specify a
-			 * default Ingress Queue for any ingress packets which
-			 * aren't hashed.  We'll use our first ingress queue
-			 * ...
-			 */
-			if (!adapter->params.rss.u.basicvirtual.tnlalllookup) {
-				union rss_vi_config config;
-				err = t4vf_read_rss_vi_config(adapter,
-							      pi->viid,
-							      &config);
-				if (err)
-					return err;
-				config.basicvirtual.defaultq =
-					rxq[0].rspq.abs_id;
-				err = t4vf_write_rss_vi_config(adapter,
-							       pi->viid,
-							       &config);
-				if (err)
-					return err;
-			}
-			break;
-		}
-	}
-
-	return 0;
-}
-
-/*
- * Bring the adapter up.  Called whenever we go from no "ports" open to having
- * one open.  This function performs the actions necessary to make an adapter
- * operational, such as completing the initialization of HW modules, and
- * enabling interrupts.  Must be called with the rtnl lock held.  (Note that
- * this is called "cxgb_up" in the PF Driver.)
- */
-static int adapter_up(struct adapter *adapter)
-{
-	int err;
-
-	/*
-	 * If this is the first time we've been called, perform basic
-	 * adapter setup.  Once we've done this, many of our adapter
-	 * parameters can no longer be changed ...
-	 */
-	if ((adapter->flags & FULL_INIT_DONE) == 0) {
-		err = setup_sge_queues(adapter);
-		if (err)
-			return err;
-		err = setup_rss(adapter);
-		if (err) {
-			t4vf_free_sge_resources(adapter);
-			return err;
-		}
-
-		if (adapter->flags & USING_MSIX)
-			name_msix_vecs(adapter);
-		adapter->flags |= FULL_INIT_DONE;
-	}
-
-	/*
-	 * Acquire our interrupt resources.  We only support MSI-X and MSI.
-	 */
-	BUG_ON((adapter->flags & (USING_MSIX|USING_MSI)) == 0);
-	if (adapter->flags & USING_MSIX)
-		err = request_msix_queue_irqs(adapter);
-	else
-		err = request_irq(adapter->pdev->irq,
-				  t4vf_intr_handler(adapter), 0,
-				  adapter->name, adapter);
-	if (err) {
-		dev_err(adapter->pdev_dev, "request_irq failed, err %d\n",
-			err);
-		return err;
-	}
-
-	/*
-	 * Enable NAPI ingress processing and return success.
-	 */
-	enable_rx(adapter);
-	t4vf_sge_start(adapter);
-	return 0;
-}
-
-/*
- * Bring the adapter down.  Called whenever the last "port" (Virtual
- * Interface) closed.  (Note that this routine is called "cxgb_down" in the PF
- * Driver.)
- */
-static void adapter_down(struct adapter *adapter)
-{
-	/*
-	 * Free interrupt resources.
-	 */
-	if (adapter->flags & USING_MSIX)
-		free_msix_queue_irqs(adapter);
-	else
-		free_irq(adapter->pdev->irq, adapter);
-
-	/*
-	 * Wait for NAPI handlers to finish.
-	 */
-	quiesce_rx(adapter);
-}
-
-/*
- * Start up a net device.
- */
-static int cxgb4vf_open(struct net_device *dev)
-{
-	int err;
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-
-	/*
-	 * If this is the first interface that we're opening on the "adapter",
-	 * bring the "adapter" up now.
-	 */
-	if (adapter->open_device_map == 0) {
-		err = adapter_up(adapter);
-		if (err)
-			return err;
-	}
-
-	/*
-	 * Note that this interface is up and start everything up ...
-	 */
-	netif_set_real_num_tx_queues(dev, pi->nqsets);
-	err = netif_set_real_num_rx_queues(dev, pi->nqsets);
-	if (err)
-		goto err_unwind;
-	err = link_start(dev);
-	if (err)
-		goto err_unwind;
-
-	netif_tx_start_all_queues(dev);
-	set_bit(pi->port_id, &adapter->open_device_map);
-	return 0;
-
-err_unwind:
-	if (adapter->open_device_map == 0)
-		adapter_down(adapter);
-	return err;
-}
-
-/*
- * Shut down a net device.  This routine is called "cxgb_close" in the PF
- * Driver ...
- */
-static int cxgb4vf_stop(struct net_device *dev)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-
-	netif_tx_stop_all_queues(dev);
-	netif_carrier_off(dev);
-	t4vf_enable_vi(adapter, pi->viid, false, false);
-	pi->link_cfg.link_ok = 0;
-
-	clear_bit(pi->port_id, &adapter->open_device_map);
-	if (adapter->open_device_map == 0)
-		adapter_down(adapter);
-	return 0;
-}
-
-/*
- * Translate our basic statistics into the standard "ifconfig" statistics.
- */
-static struct net_device_stats *cxgb4vf_get_stats(struct net_device *dev)
-{
-	struct t4vf_port_stats stats;
-	struct port_info *pi = netdev2pinfo(dev);
-	struct adapter *adapter = pi->adapter;
-	struct net_device_stats *ns = &dev->stats;
-	int err;
-
-	spin_lock(&adapter->stats_lock);
-	err = t4vf_get_port_stats(adapter, pi->pidx, &stats);
-	spin_unlock(&adapter->stats_lock);
-
-	memset(ns, 0, sizeof(*ns));
-	if (err)
-		return ns;
-
-	ns->tx_bytes = (stats.tx_bcast_bytes + stats.tx_mcast_bytes +
-			stats.tx_ucast_bytes + stats.tx_offload_bytes);
-	ns->tx_packets = (stats.tx_bcast_frames + stats.tx_mcast_frames +
-			  stats.tx_ucast_frames + stats.tx_offload_frames);
-	ns->rx_bytes = (stats.rx_bcast_bytes + stats.rx_mcast_bytes +
-			stats.rx_ucast_bytes);
-	ns->rx_packets = (stats.rx_bcast_frames + stats.rx_mcast_frames +
-			  stats.rx_ucast_frames);
-	ns->multicast = stats.rx_mcast_frames;
-	ns->tx_errors = stats.tx_drop_frames;
-	ns->rx_errors = stats.rx_err_frames;
-
-	return ns;
-}
-
-/*
- * Collect up to maxaddrs worth of a netdevice's unicast addresses, starting
- * at a specified offset within the list, into an array of addrss pointers and
- * return the number collected.
- */
-static inline unsigned int collect_netdev_uc_list_addrs(const struct net_device *dev,
-							const u8 **addr,
-							unsigned int offset,
-							unsigned int maxaddrs)
-{
-	unsigned int index = 0;
-	unsigned int naddr = 0;
-	const struct netdev_hw_addr *ha;
-
-	for_each_dev_addr(dev, ha)
-		if (index++ >= offset) {
-			addr[naddr++] = ha->addr;
-			if (naddr >= maxaddrs)
-				break;
-		}
-	return naddr;
-}
-
-/*
- * Collect up to maxaddrs worth of a netdevice's multicast addresses, starting
- * at a specified offset within the list, into an array of addrss pointers and
- * return the number collected.
- */
-static inline unsigned int collect_netdev_mc_list_addrs(const struct net_device *dev,
-							const u8 **addr,
-							unsigned int offset,
-							unsigned int maxaddrs)
-{
-	unsigned int index = 0;
-	unsigned int naddr = 0;
-	const struct netdev_hw_addr *ha;
-
-	netdev_for_each_mc_addr(ha, dev)
-		if (index++ >= offset) {
-			addr[naddr++] = ha->addr;
-			if (naddr >= maxaddrs)
-				break;
-		}
-	return naddr;
-}
-
-/*
- * Configure the exact and hash address filters to handle a port's multicast
- * and secondary unicast MAC addresses.
- */
-static int set_addr_filters(const struct net_device *dev, bool sleep)
-{
-	u64 mhash = 0;
-	u64 uhash = 0;
-	bool free = true;
-	unsigned int offset, naddr;
-	const u8 *addr[7];
-	int ret;
-	const struct port_info *pi = netdev_priv(dev);
-
-	/* first do the secondary unicast addresses */
-	for (offset = 0; ; offset += naddr) {
-		naddr = collect_netdev_uc_list_addrs(dev, addr, offset,
-						     ARRAY_SIZE(addr));
-		if (naddr == 0)
-			break;
-
-		ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free,
-					  naddr, addr, NULL, &uhash, sleep);
-		if (ret < 0)
-			return ret;
-
-		free = false;
-	}
-
-	/* next set up the multicast addresses */
-	for (offset = 0; ; offset += naddr) {
-		naddr = collect_netdev_mc_list_addrs(dev, addr, offset,
-						     ARRAY_SIZE(addr));
-		if (naddr == 0)
-			break;
-
-		ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free,
-					  naddr, addr, NULL, &mhash, sleep);
-		if (ret < 0)
-			return ret;
-		free = false;
-	}
-
-	return t4vf_set_addr_hash(pi->adapter, pi->viid, uhash != 0,
-				  uhash | mhash, sleep);
-}
-
-/*
- * Set RX properties of a port, such as promiscruity, address filters, and MTU.
- * If @mtu is -1 it is left unchanged.
- */
-static int set_rxmode(struct net_device *dev, int mtu, bool sleep_ok)
-{
-	int ret;
-	struct port_info *pi = netdev_priv(dev);
-
-	ret = set_addr_filters(dev, sleep_ok);
-	if (ret == 0)
-		ret = t4vf_set_rxmode(pi->adapter, pi->viid, -1,
-				      (dev->flags & IFF_PROMISC) != 0,
-				      (dev->flags & IFF_ALLMULTI) != 0,
-				      1, -1, sleep_ok);
-	return ret;
-}
-
-/*
- * Set the current receive modes on the device.
- */
-static void cxgb4vf_set_rxmode(struct net_device *dev)
-{
-	/* unfortunately we can't return errors to the stack */
-	set_rxmode(dev, -1, false);
-}
-
-/*
- * Find the entry in the interrupt holdoff timer value array which comes
- * closest to the specified interrupt holdoff value.
- */
-static int closest_timer(const struct sge *s, int us)
-{
-	int i, timer_idx = 0, min_delta = INT_MAX;
-
-	for (i = 0; i < ARRAY_SIZE(s->timer_val); i++) {
-		int delta = us - s->timer_val[i];
-		if (delta < 0)
-			delta = -delta;
-		if (delta < min_delta) {
-			min_delta = delta;
-			timer_idx = i;
-		}
-	}
-	return timer_idx;
-}
-
-static int closest_thres(const struct sge *s, int thres)
-{
-	int i, delta, pktcnt_idx = 0, min_delta = INT_MAX;
-
-	for (i = 0; i < ARRAY_SIZE(s->counter_val); i++) {
-		delta = thres - s->counter_val[i];
-		if (delta < 0)
-			delta = -delta;
-		if (delta < min_delta) {
-			min_delta = delta;
-			pktcnt_idx = i;
-		}
-	}
-	return pktcnt_idx;
-}
-
-/*
- * Return a queue's interrupt hold-off time in us.  0 means no timer.
- */
-static unsigned int qtimer_val(const struct adapter *adapter,
-			       const struct sge_rspq *rspq)
-{
-	unsigned int timer_idx = QINTR_TIMER_IDX_GET(rspq->intr_params);
-
-	return timer_idx < SGE_NTIMERS
-		? adapter->sge.timer_val[timer_idx]
-		: 0;
-}
-
-/**
- *	set_rxq_intr_params - set a queue's interrupt holdoff parameters
- *	@adapter: the adapter
- *	@rspq: the RX response queue
- *	@us: the hold-off time in us, or 0 to disable timer
- *	@cnt: the hold-off packet count, or 0 to disable counter
- *
- *	Sets an RX response queue's interrupt hold-off time and packet count.
- *	At least one of the two needs to be enabled for the queue to generate
- *	interrupts.
- */
-static int set_rxq_intr_params(struct adapter *adapter, struct sge_rspq *rspq,
-			       unsigned int us, unsigned int cnt)
-{
-	unsigned int timer_idx;
-
-	/*
-	 * If both the interrupt holdoff timer and count are specified as
-	 * zero, default to a holdoff count of 1 ...
-	 */
-	if ((us | cnt) == 0)
-		cnt = 1;
-
-	/*
-	 * If an interrupt holdoff count has been specified, then find the
-	 * closest configured holdoff count and use that.  If the response
-	 * queue has already been created, then update its queue context
-	 * parameters ...
-	 */
-	if (cnt) {
-		int err;
-		u32 v, pktcnt_idx;
-
-		pktcnt_idx = closest_thres(&adapter->sge, cnt);
-		if (rspq->desc && rspq->pktcnt_idx != pktcnt_idx) {
-			v = FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) |
-			    FW_PARAMS_PARAM_X(
-					FW_PARAMS_PARAM_DMAQ_IQ_INTCNTTHRESH) |
-			    FW_PARAMS_PARAM_YZ(rspq->cntxt_id);
-			err = t4vf_set_params(adapter, 1, &v, &pktcnt_idx);
-			if (err)
-				return err;
-		}
-		rspq->pktcnt_idx = pktcnt_idx;
-	}
-
-	/*
-	 * Compute the closest holdoff timer index from the supplied holdoff
-	 * timer value.
-	 */
-	timer_idx = (us == 0
-		     ? SGE_TIMER_RSTRT_CNTR
-		     : closest_timer(&adapter->sge, us));
-
-	/*
-	 * Update the response queue's interrupt coalescing parameters and
-	 * return success.
-	 */
-	rspq->intr_params = (QINTR_TIMER_IDX(timer_idx) |
-			     (cnt > 0 ? QINTR_CNT_EN : 0));
-	return 0;
-}
-
-/*
- * Return a version number to identify the type of adapter.  The scheme is:
- * - bits 0..9: chip version
- * - bits 10..15: chip revision
- */
-static inline unsigned int mk_adap_vers(const struct adapter *adapter)
-{
-	/*
-	 * Chip version 4, revision 0x3f (cxgb4vf).
-	 */
-	return 4 | (0x3f << 10);
-}
-
-/*
- * Execute the specified ioctl command.
- */
-static int cxgb4vf_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	int ret = 0;
-
-	switch (cmd) {
-	    /*
-	     * The VF Driver doesn't have access to any of the other
-	     * common Ethernet device ioctl()'s (like reading/writing
-	     * PHY registers, etc.
-	     */
-
-	default:
-		ret = -EOPNOTSUPP;
-		break;
-	}
-	return ret;
-}
-
-/*
- * Change the device's MTU.
- */
-static int cxgb4vf_change_mtu(struct net_device *dev, int new_mtu)
-{
-	int ret;
-	struct port_info *pi = netdev_priv(dev);
-
-	/* accommodate SACK */
-	if (new_mtu < 81)
-		return -EINVAL;
-
-	ret = t4vf_set_rxmode(pi->adapter, pi->viid, new_mtu,
-			      -1, -1, -1, -1, true);
-	if (!ret)
-		dev->mtu = new_mtu;
-	return ret;
-}
-
-static u32 cxgb4vf_fix_features(struct net_device *dev, u32 features)
-{
-	/*
-	 * Since there is no support for separate rx/tx vlan accel
-	 * enable/disable make sure tx flag is always in same state as rx.
-	 */
-	if (features & NETIF_F_HW_VLAN_RX)
-		features |= NETIF_F_HW_VLAN_TX;
-	else
-		features &= ~NETIF_F_HW_VLAN_TX;
-
-	return features;
-}
-
-static int cxgb4vf_set_features(struct net_device *dev, u32 features)
-{
-	struct port_info *pi = netdev_priv(dev);
-	u32 changed = dev->features ^ features;
-
-	if (changed & NETIF_F_HW_VLAN_RX)
-		t4vf_set_rxmode(pi->adapter, pi->viid, -1, -1, -1, -1,
-				features & NETIF_F_HW_VLAN_TX, 0);
-
-	return 0;
-}
-
-/*
- * Change the devices MAC address.
- */
-static int cxgb4vf_set_mac_addr(struct net_device *dev, void *_addr)
-{
-	int ret;
-	struct sockaddr *addr = _addr;
-	struct port_info *pi = netdev_priv(dev);
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EINVAL;
-
-	ret = t4vf_change_mac(pi->adapter, pi->viid, pi->xact_addr_filt,
-			      addr->sa_data, true);
-	if (ret < 0)
-		return ret;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-	pi->xact_addr_filt = ret;
-	return 0;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Poll all of our receive queues.  This is called outside of normal interrupt
- * context.
- */
-static void cxgb4vf_poll_controller(struct net_device *dev)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-
-	if (adapter->flags & USING_MSIX) {
-		struct sge_eth_rxq *rxq;
-		int nqsets;
-
-		rxq = &adapter->sge.ethrxq[pi->first_qset];
-		for (nqsets = pi->nqsets; nqsets; nqsets--) {
-			t4vf_sge_intr_msix(0, &rxq->rspq);
-			rxq++;
-		}
-	} else
-		t4vf_intr_handler(adapter)(0, adapter);
-}
-#endif
-
-/*
- * Ethtool operations.
- * ===================
- *
- * Note that we don't support any ethtool operations which change the physical
- * state of the port to which we're linked.
- */
-
-/*
- * Return current port link settings.
- */
-static int cxgb4vf_get_settings(struct net_device *dev,
-				struct ethtool_cmd *cmd)
-{
-	const struct port_info *pi = netdev_priv(dev);
-
-	cmd->supported = pi->link_cfg.supported;
-	cmd->advertising = pi->link_cfg.advertising;
-	ethtool_cmd_speed_set(cmd,
-			      netif_carrier_ok(dev) ? pi->link_cfg.speed : -1);
-	cmd->duplex = DUPLEX_FULL;
-
-	cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
-	cmd->phy_address = pi->port_id;
-	cmd->transceiver = XCVR_EXTERNAL;
-	cmd->autoneg = pi->link_cfg.autoneg;
-	cmd->maxtxpkt = 0;
-	cmd->maxrxpkt = 0;
-	return 0;
-}
-
-/*
- * Return our driver information.
- */
-static void cxgb4vf_get_drvinfo(struct net_device *dev,
-				struct ethtool_drvinfo *drvinfo)
-{
-	struct adapter *adapter = netdev2adap(dev);
-
-	strcpy(drvinfo->driver, KBUILD_MODNAME);
-	strcpy(drvinfo->version, DRV_VERSION);
-	strcpy(drvinfo->bus_info, pci_name(to_pci_dev(dev->dev.parent)));
-	snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
-		 "%u.%u.%u.%u, TP %u.%u.%u.%u",
-		 FW_HDR_FW_VER_MAJOR_GET(adapter->params.dev.fwrev),
-		 FW_HDR_FW_VER_MINOR_GET(adapter->params.dev.fwrev),
-		 FW_HDR_FW_VER_MICRO_GET(adapter->params.dev.fwrev),
-		 FW_HDR_FW_VER_BUILD_GET(adapter->params.dev.fwrev),
-		 FW_HDR_FW_VER_MAJOR_GET(adapter->params.dev.tprev),
-		 FW_HDR_FW_VER_MINOR_GET(adapter->params.dev.tprev),
-		 FW_HDR_FW_VER_MICRO_GET(adapter->params.dev.tprev),
-		 FW_HDR_FW_VER_BUILD_GET(adapter->params.dev.tprev));
-}
-
-/*
- * Return current adapter message level.
- */
-static u32 cxgb4vf_get_msglevel(struct net_device *dev)
-{
-	return netdev2adap(dev)->msg_enable;
-}
-
-/*
- * Set current adapter message level.
- */
-static void cxgb4vf_set_msglevel(struct net_device *dev, u32 msglevel)
-{
-	netdev2adap(dev)->msg_enable = msglevel;
-}
-
-/*
- * Return the device's current Queue Set ring size parameters along with the
- * allowed maximum values.  Since ethtool doesn't understand the concept of
- * multi-queue devices, we just return the current values associated with the
- * first Queue Set.
- */
-static void cxgb4vf_get_ringparam(struct net_device *dev,
-				  struct ethtool_ringparam *rp)
-{
-	const struct port_info *pi = netdev_priv(dev);
-	const struct sge *s = &pi->adapter->sge;
-
-	rp->rx_max_pending = MAX_RX_BUFFERS;
-	rp->rx_mini_max_pending = MAX_RSPQ_ENTRIES;
-	rp->rx_jumbo_max_pending = 0;
-	rp->tx_max_pending = MAX_TXQ_ENTRIES;
-
-	rp->rx_pending = s->ethrxq[pi->first_qset].fl.size - MIN_FL_RESID;
-	rp->rx_mini_pending = s->ethrxq[pi->first_qset].rspq.size;
-	rp->rx_jumbo_pending = 0;
-	rp->tx_pending = s->ethtxq[pi->first_qset].q.size;
-}
-
-/*
- * Set the Queue Set ring size parameters for the device.  Again, since
- * ethtool doesn't allow for the concept of multiple queues per device, we'll
- * apply these new values across all of the Queue Sets associated with the
- * device -- after vetting them of course!
- */
-static int cxgb4vf_set_ringparam(struct net_device *dev,
-				 struct ethtool_ringparam *rp)
-{
-	const struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-	struct sge *s = &adapter->sge;
-	int qs;
-
-	if (rp->rx_pending > MAX_RX_BUFFERS ||
-	    rp->rx_jumbo_pending ||
-	    rp->tx_pending > MAX_TXQ_ENTRIES ||
-	    rp->rx_mini_pending > MAX_RSPQ_ENTRIES ||
-	    rp->rx_mini_pending < MIN_RSPQ_ENTRIES ||
-	    rp->rx_pending < MIN_FL_ENTRIES ||
-	    rp->tx_pending < MIN_TXQ_ENTRIES)
-		return -EINVAL;
-
-	if (adapter->flags & FULL_INIT_DONE)
-		return -EBUSY;
-
-	for (qs = pi->first_qset; qs < pi->first_qset + pi->nqsets; qs++) {
-		s->ethrxq[qs].fl.size = rp->rx_pending + MIN_FL_RESID;
-		s->ethrxq[qs].rspq.size = rp->rx_mini_pending;
-		s->ethtxq[qs].q.size = rp->tx_pending;
-	}
-	return 0;
-}
-
-/*
- * Return the interrupt holdoff timer and count for the first Queue Set on the
- * device.  Our extension ioctl() (the cxgbtool interface) allows the
- * interrupt holdoff timer to be read on all of the device's Queue Sets.
- */
-static int cxgb4vf_get_coalesce(struct net_device *dev,
-				struct ethtool_coalesce *coalesce)
-{
-	const struct port_info *pi = netdev_priv(dev);
-	const struct adapter *adapter = pi->adapter;
-	const struct sge_rspq *rspq = &adapter->sge.ethrxq[pi->first_qset].rspq;
-
-	coalesce->rx_coalesce_usecs = qtimer_val(adapter, rspq);
-	coalesce->rx_max_coalesced_frames =
-		((rspq->intr_params & QINTR_CNT_EN)
-		 ? adapter->sge.counter_val[rspq->pktcnt_idx]
-		 : 0);
-	return 0;
-}
-
-/*
- * Set the RX interrupt holdoff timer and count for the first Queue Set on the
- * interface.  Our extension ioctl() (the cxgbtool interface) allows us to set
- * the interrupt holdoff timer on any of the device's Queue Sets.
- */
-static int cxgb4vf_set_coalesce(struct net_device *dev,
-				struct ethtool_coalesce *coalesce)
-{
-	const struct port_info *pi = netdev_priv(dev);
-	struct adapter *adapter = pi->adapter;
-
-	return set_rxq_intr_params(adapter,
-				   &adapter->sge.ethrxq[pi->first_qset].rspq,
-				   coalesce->rx_coalesce_usecs,
-				   coalesce->rx_max_coalesced_frames);
-}
-
-/*
- * Report current port link pause parameter settings.
- */
-static void cxgb4vf_get_pauseparam(struct net_device *dev,
-				   struct ethtool_pauseparam *pauseparam)
-{
-	struct port_info *pi = netdev_priv(dev);
-
-	pauseparam->autoneg = (pi->link_cfg.requested_fc & PAUSE_AUTONEG) != 0;
-	pauseparam->rx_pause = (pi->link_cfg.fc & PAUSE_RX) != 0;
-	pauseparam->tx_pause = (pi->link_cfg.fc & PAUSE_TX) != 0;
-}
-
-/*
- * Identify the port by blinking the port's LED.
- */
-static int cxgb4vf_phys_id(struct net_device *dev,
-			   enum ethtool_phys_id_state state)
-{
-	unsigned int val;
-	struct port_info *pi = netdev_priv(dev);
-
-	if (state == ETHTOOL_ID_ACTIVE)
-		val = 0xffff;
-	else if (state == ETHTOOL_ID_INACTIVE)
-		val = 0;
-	else
-		return -EINVAL;
-
-	return t4vf_identify_port(pi->adapter, pi->viid, val);
-}
-
-/*
- * Port stats maintained per queue of the port.
- */
-struct queue_port_stats {
-	u64 tso;
-	u64 tx_csum;
-	u64 rx_csum;
-	u64 vlan_ex;
-	u64 vlan_ins;
-	u64 lro_pkts;
-	u64 lro_merged;
-};
-
-/*
- * Strings for the ETH_SS_STATS statistics set ("ethtool -S").  Note that
- * these need to match the order of statistics returned by
- * t4vf_get_port_stats().
- */
-static const char stats_strings[][ETH_GSTRING_LEN] = {
-	/*
-	 * These must match the layout of the t4vf_port_stats structure.
-	 */
-	"TxBroadcastBytes  ",
-	"TxBroadcastFrames ",
-	"TxMulticastBytes  ",
-	"TxMulticastFrames ",
-	"TxUnicastBytes    ",
-	"TxUnicastFrames   ",
-	"TxDroppedFrames   ",
-	"TxOffloadBytes    ",
-	"TxOffloadFrames   ",
-	"RxBroadcastBytes  ",
-	"RxBroadcastFrames ",
-	"RxMulticastBytes  ",
-	"RxMulticastFrames ",
-	"RxUnicastBytes    ",
-	"RxUnicastFrames   ",
-	"RxErrorFrames     ",
-
-	/*
-	 * These are accumulated per-queue statistics and must match the
-	 * order of the fields in the queue_port_stats structure.
-	 */
-	"TSO               ",
-	"TxCsumOffload     ",
-	"RxCsumGood        ",
-	"VLANextractions   ",
-	"VLANinsertions    ",
-	"GROPackets        ",
-	"GROMerged         ",
-};
-
-/*
- * Return the number of statistics in the specified statistics set.
- */
-static int cxgb4vf_get_sset_count(struct net_device *dev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		return ARRAY_SIZE(stats_strings);
-	default:
-		return -EOPNOTSUPP;
-	}
-	/*NOTREACHED*/
-}
-
-/*
- * Return the strings for the specified statistics set.
- */
-static void cxgb4vf_get_strings(struct net_device *dev,
-				u32 sset,
-				u8 *data)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		memcpy(data, stats_strings, sizeof(stats_strings));
-		break;
-	}
-}
-
-/*
- * Small utility routine to accumulate queue statistics across the queues of
- * a "port".
- */
-static void collect_sge_port_stats(const struct adapter *adapter,
-				   const struct port_info *pi,
-				   struct queue_port_stats *stats)
-{
-	const struct sge_eth_txq *txq = &adapter->sge.ethtxq[pi->first_qset];
-	const struct sge_eth_rxq *rxq = &adapter->sge.ethrxq[pi->first_qset];
-	int qs;
-
-	memset(stats, 0, sizeof(*stats));
-	for (qs = 0; qs < pi->nqsets; qs++, rxq++, txq++) {
-		stats->tso += txq->tso;
-		stats->tx_csum += txq->tx_cso;
-		stats->rx_csum += rxq->stats.rx_cso;
-		stats->vlan_ex += rxq->stats.vlan_ex;
-		stats->vlan_ins += txq->vlan_ins;
-		stats->lro_pkts += rxq->stats.lro_pkts;
-		stats->lro_merged += rxq->stats.lro_merged;
-	}
-}
-
-/*
- * Return the ETH_SS_STATS statistics set.
- */
-static void cxgb4vf_get_ethtool_stats(struct net_device *dev,
-				      struct ethtool_stats *stats,
-				      u64 *data)
-{
-	struct port_info *pi = netdev2pinfo(dev);
-	struct adapter *adapter = pi->adapter;
-	int err = t4vf_get_port_stats(adapter, pi->pidx,
-				      (struct t4vf_port_stats *)data);
-	if (err)
-		memset(data, 0, sizeof(struct t4vf_port_stats));
-
-	data += sizeof(struct t4vf_port_stats) / sizeof(u64);
-	collect_sge_port_stats(adapter, pi, (struct queue_port_stats *)data);
-}
-
-/*
- * Return the size of our register map.
- */
-static int cxgb4vf_get_regs_len(struct net_device *dev)
-{
-	return T4VF_REGMAP_SIZE;
-}
-
-/*
- * Dump a block of registers, start to end inclusive, into a buffer.
- */
-static void reg_block_dump(struct adapter *adapter, void *regbuf,
-			   unsigned int start, unsigned int end)
-{
-	u32 *bp = regbuf + start - T4VF_REGMAP_START;
-
-	for ( ; start <= end; start += sizeof(u32)) {
-		/*
-		 * Avoid reading the Mailbox Control register since that
-		 * can trigger a Mailbox Ownership Arbitration cycle and
-		 * interfere with communication with the firmware.
-		 */
-		if (start == T4VF_CIM_BASE_ADDR + CIM_VF_EXT_MAILBOX_CTRL)
-			*bp++ = 0xffff;
-		else
-			*bp++ = t4_read_reg(adapter, start);
-	}
-}
-
-/*
- * Copy our entire register map into the provided buffer.
- */
-static void cxgb4vf_get_regs(struct net_device *dev,
-			     struct ethtool_regs *regs,
-			     void *regbuf)
-{
-	struct adapter *adapter = netdev2adap(dev);
-
-	regs->version = mk_adap_vers(adapter);
-
-	/*
-	 * Fill in register buffer with our register map.
-	 */
-	memset(regbuf, 0, T4VF_REGMAP_SIZE);
-
-	reg_block_dump(adapter, regbuf,
-		       T4VF_SGE_BASE_ADDR + T4VF_MOD_MAP_SGE_FIRST,
-		       T4VF_SGE_BASE_ADDR + T4VF_MOD_MAP_SGE_LAST);
-	reg_block_dump(adapter, regbuf,
-		       T4VF_MPS_BASE_ADDR + T4VF_MOD_MAP_MPS_FIRST,
-		       T4VF_MPS_BASE_ADDR + T4VF_MOD_MAP_MPS_LAST);
-	reg_block_dump(adapter, regbuf,
-		       T4VF_PL_BASE_ADDR + T4VF_MOD_MAP_PL_FIRST,
-		       T4VF_PL_BASE_ADDR + T4VF_MOD_MAP_PL_LAST);
-	reg_block_dump(adapter, regbuf,
-		       T4VF_CIM_BASE_ADDR + T4VF_MOD_MAP_CIM_FIRST,
-		       T4VF_CIM_BASE_ADDR + T4VF_MOD_MAP_CIM_LAST);
-
-	reg_block_dump(adapter, regbuf,
-		       T4VF_MBDATA_BASE_ADDR + T4VF_MBDATA_FIRST,
-		       T4VF_MBDATA_BASE_ADDR + T4VF_MBDATA_LAST);
-}
-
-/*
- * Report current Wake On LAN settings.
- */
-static void cxgb4vf_get_wol(struct net_device *dev,
-			    struct ethtool_wolinfo *wol)
-{
-	wol->supported = 0;
-	wol->wolopts = 0;
-	memset(&wol->sopass, 0, sizeof(wol->sopass));
-}
-
-/*
- * TCP Segmentation Offload flags which we support.
- */
-#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
-
-static struct ethtool_ops cxgb4vf_ethtool_ops = {
-	.get_settings		= cxgb4vf_get_settings,
-	.get_drvinfo		= cxgb4vf_get_drvinfo,
-	.get_msglevel		= cxgb4vf_get_msglevel,
-	.set_msglevel		= cxgb4vf_set_msglevel,
-	.get_ringparam		= cxgb4vf_get_ringparam,
-	.set_ringparam		= cxgb4vf_set_ringparam,
-	.get_coalesce		= cxgb4vf_get_coalesce,
-	.set_coalesce		= cxgb4vf_set_coalesce,
-	.get_pauseparam		= cxgb4vf_get_pauseparam,
-	.get_link		= ethtool_op_get_link,
-	.get_strings		= cxgb4vf_get_strings,
-	.set_phys_id		= cxgb4vf_phys_id,
-	.get_sset_count		= cxgb4vf_get_sset_count,
-	.get_ethtool_stats	= cxgb4vf_get_ethtool_stats,
-	.get_regs_len		= cxgb4vf_get_regs_len,
-	.get_regs		= cxgb4vf_get_regs,
-	.get_wol		= cxgb4vf_get_wol,
-};
-
-/*
- * /sys/kernel/debug/cxgb4vf support code and data.
- * ================================================
- */
-
-/*
- * Show SGE Queue Set information.  We display QPL Queues Sets per line.
- */
-#define QPL	4
-
-static int sge_qinfo_show(struct seq_file *seq, void *v)
-{
-	struct adapter *adapter = seq->private;
-	int eth_entries = DIV_ROUND_UP(adapter->sge.ethqsets, QPL);
-	int qs, r = (uintptr_t)v - 1;
-
-	if (r)
-		seq_putc(seq, '\n');
-
-	#define S3(fmt_spec, s, v) \
-		do {\
-			seq_printf(seq, "%-12s", s); \
-			for (qs = 0; qs < n; ++qs) \
-				seq_printf(seq, " %16" fmt_spec, v); \
-			seq_putc(seq, '\n'); \
-		} while (0)
-	#define S(s, v)		S3("s", s, v)
-	#define T(s, v)		S3("u", s, txq[qs].v)
-	#define R(s, v)		S3("u", s, rxq[qs].v)
-
-	if (r < eth_entries) {
-		const struct sge_eth_rxq *rxq = &adapter->sge.ethrxq[r * QPL];
-		const struct sge_eth_txq *txq = &adapter->sge.ethtxq[r * QPL];
-		int n = min(QPL, adapter->sge.ethqsets - QPL * r);
-
-		S("QType:", "Ethernet");
-		S("Interface:",
-		  (rxq[qs].rspq.netdev
-		   ? rxq[qs].rspq.netdev->name
-		   : "N/A"));
-		S3("d", "Port:",
-		   (rxq[qs].rspq.netdev
-		    ? ((struct port_info *)
-		       netdev_priv(rxq[qs].rspq.netdev))->port_id
-		    : -1));
-		T("TxQ ID:", q.abs_id);
-		T("TxQ size:", q.size);
-		T("TxQ inuse:", q.in_use);
-		T("TxQ PIdx:", q.pidx);
-		T("TxQ CIdx:", q.cidx);
-		R("RspQ ID:", rspq.abs_id);
-		R("RspQ size:", rspq.size);
-		R("RspQE size:", rspq.iqe_len);
-		S3("u", "Intr delay:", qtimer_val(adapter, &rxq[qs].rspq));
-		S3("u", "Intr pktcnt:",
-		   adapter->sge.counter_val[rxq[qs].rspq.pktcnt_idx]);
-		R("RspQ CIdx:", rspq.cidx);
-		R("RspQ Gen:", rspq.gen);
-		R("FL ID:", fl.abs_id);
-		R("FL size:", fl.size - MIN_FL_RESID);
-		R("FL avail:", fl.avail);
-		R("FL PIdx:", fl.pidx);
-		R("FL CIdx:", fl.cidx);
-		return 0;
-	}
-
-	r -= eth_entries;
-	if (r == 0) {
-		const struct sge_rspq *evtq = &adapter->sge.fw_evtq;
-
-		seq_printf(seq, "%-12s %16s\n", "QType:", "FW event queue");
-		seq_printf(seq, "%-12s %16u\n", "RspQ ID:", evtq->abs_id);
-		seq_printf(seq, "%-12s %16u\n", "Intr delay:",
-			   qtimer_val(adapter, evtq));
-		seq_printf(seq, "%-12s %16u\n", "Intr pktcnt:",
-			   adapter->sge.counter_val[evtq->pktcnt_idx]);
-		seq_printf(seq, "%-12s %16u\n", "RspQ Cidx:", evtq->cidx);
-		seq_printf(seq, "%-12s %16u\n", "RspQ Gen:", evtq->gen);
-	} else if (r == 1) {
-		const struct sge_rspq *intrq = &adapter->sge.intrq;
-
-		seq_printf(seq, "%-12s %16s\n", "QType:", "Interrupt Queue");
-		seq_printf(seq, "%-12s %16u\n", "RspQ ID:", intrq->abs_id);
-		seq_printf(seq, "%-12s %16u\n", "Intr delay:",
-			   qtimer_val(adapter, intrq));
-		seq_printf(seq, "%-12s %16u\n", "Intr pktcnt:",
-			   adapter->sge.counter_val[intrq->pktcnt_idx]);
-		seq_printf(seq, "%-12s %16u\n", "RspQ Cidx:", intrq->cidx);
-		seq_printf(seq, "%-12s %16u\n", "RspQ Gen:", intrq->gen);
-	}
-
-	#undef R
-	#undef T
-	#undef S
-	#undef S3
-
-	return 0;
-}
-
-/*
- * Return the number of "entries" in our "file".  We group the multi-Queue
- * sections with QPL Queue Sets per "entry".  The sections of the output are:
- *
- *     Ethernet RX/TX Queue Sets
- *     Firmware Event Queue
- *     Forwarded Interrupt Queue (if in MSI mode)
- */
-static int sge_queue_entries(const struct adapter *adapter)
-{
-	return DIV_ROUND_UP(adapter->sge.ethqsets, QPL) + 1 +
-		((adapter->flags & USING_MSI) != 0);
-}
-
-static void *sge_queue_start(struct seq_file *seq, loff_t *pos)
-{
-	int entries = sge_queue_entries(seq->private);
-
-	return *pos < entries ? (void *)((uintptr_t)*pos + 1) : NULL;
-}
-
-static void sge_queue_stop(struct seq_file *seq, void *v)
-{
-}
-
-static void *sge_queue_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-	int entries = sge_queue_entries(seq->private);
-
-	++*pos;
-	return *pos < entries ? (void *)((uintptr_t)*pos + 1) : NULL;
-}
-
-static const struct seq_operations sge_qinfo_seq_ops = {
-	.start = sge_queue_start,
-	.next  = sge_queue_next,
-	.stop  = sge_queue_stop,
-	.show  = sge_qinfo_show
-};
-
-static int sge_qinfo_open(struct inode *inode, struct file *file)
-{
-	int res = seq_open(file, &sge_qinfo_seq_ops);
-
-	if (!res) {
-		struct seq_file *seq = file->private_data;
-		seq->private = inode->i_private;
-	}
-	return res;
-}
-
-static const struct file_operations sge_qinfo_debugfs_fops = {
-	.owner   = THIS_MODULE,
-	.open    = sge_qinfo_open,
-	.read    = seq_read,
-	.llseek  = seq_lseek,
-	.release = seq_release,
-};
-
-/*
- * Show SGE Queue Set statistics.  We display QPL Queues Sets per line.
- */
-#define QPL	4
-
-static int sge_qstats_show(struct seq_file *seq, void *v)
-{
-	struct adapter *adapter = seq->private;
-	int eth_entries = DIV_ROUND_UP(adapter->sge.ethqsets, QPL);
-	int qs, r = (uintptr_t)v - 1;
-
-	if (r)
-		seq_putc(seq, '\n');
-
-	#define S3(fmt, s, v) \
-		do { \
-			seq_printf(seq, "%-16s", s); \
-			for (qs = 0; qs < n; ++qs) \
-				seq_printf(seq, " %8" fmt, v); \
-			seq_putc(seq, '\n'); \
-		} while (0)
-	#define S(s, v)		S3("s", s, v)
-
-	#define T3(fmt, s, v)	S3(fmt, s, txq[qs].v)
-	#define T(s, v)		T3("lu", s, v)
-
-	#define R3(fmt, s, v)	S3(fmt, s, rxq[qs].v)
-	#define R(s, v)		R3("lu", s, v)
-
-	if (r < eth_entries) {
-		const struct sge_eth_rxq *rxq = &adapter->sge.ethrxq[r * QPL];
-		const struct sge_eth_txq *txq = &adapter->sge.ethtxq[r * QPL];
-		int n = min(QPL, adapter->sge.ethqsets - QPL * r);
-
-		S("QType:", "Ethernet");
-		S("Interface:",
-		  (rxq[qs].rspq.netdev
-		   ? rxq[qs].rspq.netdev->name
-		   : "N/A"));
-		R3("u", "RspQNullInts:", rspq.unhandled_irqs);
-		R("RxPackets:", stats.pkts);
-		R("RxCSO:", stats.rx_cso);
-		R("VLANxtract:", stats.vlan_ex);
-		R("LROmerged:", stats.lro_merged);
-		R("LROpackets:", stats.lro_pkts);
-		R("RxDrops:", stats.rx_drops);
-		T("TSO:", tso);
-		T("TxCSO:", tx_cso);
-		T("VLANins:", vlan_ins);
-		T("TxQFull:", q.stops);
-		T("TxQRestarts:", q.restarts);
-		T("TxMapErr:", mapping_err);
-		R("FLAllocErr:", fl.alloc_failed);
-		R("FLLrgAlcErr:", fl.large_alloc_failed);
-		R("FLStarving:", fl.starving);
-		return 0;
-	}
-
-	r -= eth_entries;
-	if (r == 0) {
-		const struct sge_rspq *evtq = &adapter->sge.fw_evtq;
-
-		seq_printf(seq, "%-8s %16s\n", "QType:", "FW event queue");
-		seq_printf(seq, "%-16s %8u\n", "RspQNullInts:",
-			   evtq->unhandled_irqs);
-		seq_printf(seq, "%-16s %8u\n", "RspQ CIdx:", evtq->cidx);
-		seq_printf(seq, "%-16s %8u\n", "RspQ Gen:", evtq->gen);
-	} else if (r == 1) {
-		const struct sge_rspq *intrq = &adapter->sge.intrq;
-
-		seq_printf(seq, "%-8s %16s\n", "QType:", "Interrupt Queue");
-		seq_printf(seq, "%-16s %8u\n", "RspQNullInts:",
-			   intrq->unhandled_irqs);
-		seq_printf(seq, "%-16s %8u\n", "RspQ CIdx:", intrq->cidx);
-		seq_printf(seq, "%-16s %8u\n", "RspQ Gen:", intrq->gen);
-	}
-
-	#undef R
-	#undef T
-	#undef S
-	#undef R3
-	#undef T3
-	#undef S3
-
-	return 0;
-}
-
-/*
- * Return the number of "entries" in our "file".  We group the multi-Queue
- * sections with QPL Queue Sets per "entry".  The sections of the output are:
- *
- *     Ethernet RX/TX Queue Sets
- *     Firmware Event Queue
- *     Forwarded Interrupt Queue (if in MSI mode)
- */
-static int sge_qstats_entries(const struct adapter *adapter)
-{
-	return DIV_ROUND_UP(adapter->sge.ethqsets, QPL) + 1 +
-		((adapter->flags & USING_MSI) != 0);
-}
-
-static void *sge_qstats_start(struct seq_file *seq, loff_t *pos)
-{
-	int entries = sge_qstats_entries(seq->private);
-
-	return *pos < entries ? (void *)((uintptr_t)*pos + 1) : NULL;
-}
-
-static void sge_qstats_stop(struct seq_file *seq, void *v)
-{
-}
-
-static void *sge_qstats_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-	int entries = sge_qstats_entries(seq->private);
-
-	(*pos)++;
-	return *pos < entries ? (void *)((uintptr_t)*pos + 1) : NULL;
-}
-
-static const struct seq_operations sge_qstats_seq_ops = {
-	.start = sge_qstats_start,
-	.next  = sge_qstats_next,
-	.stop  = sge_qstats_stop,
-	.show  = sge_qstats_show
-};
-
-static int sge_qstats_open(struct inode *inode, struct file *file)
-{
-	int res = seq_open(file, &sge_qstats_seq_ops);
-
-	if (res == 0) {
-		struct seq_file *seq = file->private_data;
-		seq->private = inode->i_private;
-	}
-	return res;
-}
-
-static const struct file_operations sge_qstats_proc_fops = {
-	.owner   = THIS_MODULE,
-	.open    = sge_qstats_open,
-	.read    = seq_read,
-	.llseek  = seq_lseek,
-	.release = seq_release,
-};
-
-/*
- * Show PCI-E SR-IOV Virtual Function Resource Limits.
- */
-static int resources_show(struct seq_file *seq, void *v)
-{
-	struct adapter *adapter = seq->private;
-	struct vf_resources *vfres = &adapter->params.vfres;
-
-	#define S(desc, fmt, var) \
-		seq_printf(seq, "%-60s " fmt "\n", \
-			   desc " (" #var "):", vfres->var)
-
-	S("Virtual Interfaces", "%d", nvi);
-	S("Egress Queues", "%d", neq);
-	S("Ethernet Control", "%d", nethctrl);
-	S("Ingress Queues/w Free Lists/Interrupts", "%d", niqflint);
-	S("Ingress Queues", "%d", niq);
-	S("Traffic Class", "%d", tc);
-	S("Port Access Rights Mask", "%#x", pmask);
-	S("MAC Address Filters", "%d", nexactf);
-	S("Firmware Command Read Capabilities", "%#x", r_caps);
-	S("Firmware Command Write/Execute Capabilities", "%#x", wx_caps);
-
-	#undef S
-
-	return 0;
-}
-
-static int resources_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, resources_show, inode->i_private);
-}
-
-static const struct file_operations resources_proc_fops = {
-	.owner   = THIS_MODULE,
-	.open    = resources_open,
-	.read    = seq_read,
-	.llseek  = seq_lseek,
-	.release = single_release,
-};
-
-/*
- * Show Virtual Interfaces.
- */
-static int interfaces_show(struct seq_file *seq, void *v)
-{
-	if (v == SEQ_START_TOKEN) {
-		seq_puts(seq, "Interface  Port   VIID\n");
-	} else {
-		struct adapter *adapter = seq->private;
-		int pidx = (uintptr_t)v - 2;
-		struct net_device *dev = adapter->port[pidx];
-		struct port_info *pi = netdev_priv(dev);
-
-		seq_printf(seq, "%9s  %4d  %#5x\n",
-			   dev->name, pi->port_id, pi->viid);
-	}
-	return 0;
-}
-
-static inline void *interfaces_get_idx(struct adapter *adapter, loff_t pos)
-{
-	return pos <= adapter->params.nports
-		? (void *)(uintptr_t)(pos + 1)
-		: NULL;
-}
-
-static void *interfaces_start(struct seq_file *seq, loff_t *pos)
-{
-	return *pos
-		? interfaces_get_idx(seq->private, *pos)
-		: SEQ_START_TOKEN;
-}
-
-static void *interfaces_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-	(*pos)++;
-	return interfaces_get_idx(seq->private, *pos);
-}
-
-static void interfaces_stop(struct seq_file *seq, void *v)
-{
-}
-
-static const struct seq_operations interfaces_seq_ops = {
-	.start = interfaces_start,
-	.next  = interfaces_next,
-	.stop  = interfaces_stop,
-	.show  = interfaces_show
-};
-
-static int interfaces_open(struct inode *inode, struct file *file)
-{
-	int res = seq_open(file, &interfaces_seq_ops);
-
-	if (res == 0) {
-		struct seq_file *seq = file->private_data;
-		seq->private = inode->i_private;
-	}
-	return res;
-}
-
-static const struct file_operations interfaces_proc_fops = {
-	.owner   = THIS_MODULE,
-	.open    = interfaces_open,
-	.read    = seq_read,
-	.llseek  = seq_lseek,
-	.release = seq_release,
-};
-
-/*
- * /sys/kernel/debugfs/cxgb4vf/ files list.
- */
-struct cxgb4vf_debugfs_entry {
-	const char *name;		/* name of debugfs node */
-	mode_t mode;			/* file system mode */
-	const struct file_operations *fops;
-};
-
-static struct cxgb4vf_debugfs_entry debugfs_files[] = {
-	{ "sge_qinfo",  S_IRUGO, &sge_qinfo_debugfs_fops },
-	{ "sge_qstats", S_IRUGO, &sge_qstats_proc_fops },
-	{ "resources",  S_IRUGO, &resources_proc_fops },
-	{ "interfaces", S_IRUGO, &interfaces_proc_fops },
-};
-
-/*
- * Module and device initialization and cleanup code.
- * ==================================================
- */
-
-/*
- * Set up out /sys/kernel/debug/cxgb4vf sub-nodes.  We assume that the
- * directory (debugfs_root) has already been set up.
- */
-static int __devinit setup_debugfs(struct adapter *adapter)
-{
-	int i;
-
-	BUG_ON(IS_ERR_OR_NULL(adapter->debugfs_root));
-
-	/*
-	 * Debugfs support is best effort.
-	 */
-	for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
-		(void)debugfs_create_file(debugfs_files[i].name,
-				  debugfs_files[i].mode,
-				  adapter->debugfs_root,
-				  (void *)adapter,
-				  debugfs_files[i].fops);
-
-	return 0;
-}
-
-/*
- * Tear down the /sys/kernel/debug/cxgb4vf sub-nodes created above.  We leave
- * it to our caller to tear down the directory (debugfs_root).
- */
-static void cleanup_debugfs(struct adapter *adapter)
-{
-	BUG_ON(IS_ERR_OR_NULL(adapter->debugfs_root));
-
-	/*
-	 * Unlike our sister routine cleanup_proc(), we don't need to remove
-	 * individual entries because a call will be made to
-	 * debugfs_remove_recursive().  We just need to clean up any ancillary
-	 * persistent state.
-	 */
-	/* nothing to do */
-}
-
-/*
- * Perform early "adapter" initialization.  This is where we discover what
- * adapter parameters we're going to be using and initialize basic adapter
- * hardware support.
- */
-static int __devinit adap_init0(struct adapter *adapter)
-{
-	struct vf_resources *vfres = &adapter->params.vfres;
-	struct sge_params *sge_params = &adapter->params.sge;
-	struct sge *s = &adapter->sge;
-	unsigned int ethqsets;
-	int err;
-
-	/*
-	 * Wait for the device to become ready before proceeding ...
-	 */
-	err = t4vf_wait_dev_ready(adapter);
-	if (err) {
-		dev_err(adapter->pdev_dev, "device didn't become ready:"
-			" err=%d\n", err);
-		return err;
-	}
-
-	/*
-	 * Some environments do not properly handle PCIE FLRs -- e.g. in Linux
-	 * 2.6.31 and later we can't call pci_reset_function() in order to
-	 * issue an FLR because of a self- deadlock on the device semaphore.
-	 * Meanwhile, the OS infrastructure doesn't issue FLRs in all the
-	 * cases where they're needed -- for instance, some versions of KVM
-	 * fail to reset "Assigned Devices" when the VM reboots.  Therefore we
-	 * use the firmware based reset in order to reset any per function
-	 * state.
-	 */
-	err = t4vf_fw_reset(adapter);
-	if (err < 0) {
-		dev_err(adapter->pdev_dev, "FW reset failed: err=%d\n", err);
-		return err;
-	}
-
-	/*
-	 * Grab basic operational parameters.  These will predominantly have
-	 * been set up by the Physical Function Driver or will be hard coded
-	 * into the adapter.  We just have to live with them ...  Note that
-	 * we _must_ get our VPD parameters before our SGE parameters because
-	 * we need to know the adapter's core clock from the VPD in order to
-	 * properly decode the SGE Timer Values.
-	 */
-	err = t4vf_get_dev_params(adapter);
-	if (err) {
-		dev_err(adapter->pdev_dev, "unable to retrieve adapter"
-			" device parameters: err=%d\n", err);
-		return err;
-	}
-	err = t4vf_get_vpd_params(adapter);
-	if (err) {
-		dev_err(adapter->pdev_dev, "unable to retrieve adapter"
-			" VPD parameters: err=%d\n", err);
-		return err;
-	}
-	err = t4vf_get_sge_params(adapter);
-	if (err) {
-		dev_err(adapter->pdev_dev, "unable to retrieve adapter"
-			" SGE parameters: err=%d\n", err);
-		return err;
-	}
-	err = t4vf_get_rss_glb_config(adapter);
-	if (err) {
-		dev_err(adapter->pdev_dev, "unable to retrieve adapter"
-			" RSS parameters: err=%d\n", err);
-		return err;
-	}
-	if (adapter->params.rss.mode !=
-	    FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL) {
-		dev_err(adapter->pdev_dev, "unable to operate with global RSS"
-			" mode %d\n", adapter->params.rss.mode);
-		return -EINVAL;
-	}
-	err = t4vf_sge_init(adapter);
-	if (err) {
-		dev_err(adapter->pdev_dev, "unable to use adapter parameters:"
-			" err=%d\n", err);
-		return err;
-	}
-
-	/*
-	 * Retrieve our RX interrupt holdoff timer values and counter
-	 * threshold values from the SGE parameters.
-	 */
-	s->timer_val[0] = core_ticks_to_us(adapter,
-		TIMERVALUE0_GET(sge_params->sge_timer_value_0_and_1));
-	s->timer_val[1] = core_ticks_to_us(adapter,
-		TIMERVALUE1_GET(sge_params->sge_timer_value_0_and_1));
-	s->timer_val[2] = core_ticks_to_us(adapter,
-		TIMERVALUE0_GET(sge_params->sge_timer_value_2_and_3));
-	s->timer_val[3] = core_ticks_to_us(adapter,
-		TIMERVALUE1_GET(sge_params->sge_timer_value_2_and_3));
-	s->timer_val[4] = core_ticks_to_us(adapter,
-		TIMERVALUE0_GET(sge_params->sge_timer_value_4_and_5));
-	s->timer_val[5] = core_ticks_to_us(adapter,
-		TIMERVALUE1_GET(sge_params->sge_timer_value_4_and_5));
-
-	s->counter_val[0] =
-		THRESHOLD_0_GET(sge_params->sge_ingress_rx_threshold);
-	s->counter_val[1] =
-		THRESHOLD_1_GET(sge_params->sge_ingress_rx_threshold);
-	s->counter_val[2] =
-		THRESHOLD_2_GET(sge_params->sge_ingress_rx_threshold);
-	s->counter_val[3] =
-		THRESHOLD_3_GET(sge_params->sge_ingress_rx_threshold);
-
-	/*
-	 * Grab our Virtual Interface resource allocation, extract the
-	 * features that we're interested in and do a bit of sanity testing on
-	 * what we discover.
-	 */
-	err = t4vf_get_vfres(adapter);
-	if (err) {
-		dev_err(adapter->pdev_dev, "unable to get virtual interface"
-			" resources: err=%d\n", err);
-		return err;
-	}
-
-	/*
-	 * The number of "ports" which we support is equal to the number of
-	 * Virtual Interfaces with which we've been provisioned.
-	 */
-	adapter->params.nports = vfres->nvi;
-	if (adapter->params.nports > MAX_NPORTS) {
-		dev_warn(adapter->pdev_dev, "only using %d of %d allowed"
-			 " virtual interfaces\n", MAX_NPORTS,
-			 adapter->params.nports);
-		adapter->params.nports = MAX_NPORTS;
-	}
-
-	/*
-	 * We need to reserve a number of the ingress queues with Free List
-	 * and Interrupt capabilities for special interrupt purposes (like
-	 * asynchronous firmware messages, or forwarded interrupts if we're
-	 * using MSI).  The rest of the FL/Intr-capable ingress queues will be
-	 * matched up one-for-one with Ethernet/Control egress queues in order
-	 * to form "Queue Sets" which will be aportioned between the "ports".
-	 * For each Queue Set, we'll need the ability to allocate two Egress
-	 * Contexts -- one for the Ingress Queue Free List and one for the TX
-	 * Ethernet Queue.
-	 */
-	ethqsets = vfres->niqflint - INGQ_EXTRAS;
-	if (vfres->nethctrl != ethqsets) {
-		dev_warn(adapter->pdev_dev, "unequal number of [available]"
-			 " ingress/egress queues (%d/%d); using minimum for"
-			 " number of Queue Sets\n", ethqsets, vfres->nethctrl);
-		ethqsets = min(vfres->nethctrl, ethqsets);
-	}
-	if (vfres->neq < ethqsets*2) {
-		dev_warn(adapter->pdev_dev, "Not enough Egress Contexts (%d)"
-			 " to support Queue Sets (%d); reducing allowed Queue"
-			 " Sets\n", vfres->neq, ethqsets);
-		ethqsets = vfres->neq/2;
-	}
-	if (ethqsets > MAX_ETH_QSETS) {
-		dev_warn(adapter->pdev_dev, "only using %d of %d allowed Queue"
-			 " Sets\n", MAX_ETH_QSETS, adapter->sge.max_ethqsets);
-		ethqsets = MAX_ETH_QSETS;
-	}
-	if (vfres->niq != 0 || vfres->neq > ethqsets*2) {
-		dev_warn(adapter->pdev_dev, "unused resources niq/neq (%d/%d)"
-			 " ignored\n", vfres->niq, vfres->neq - ethqsets*2);
-	}
-	adapter->sge.max_ethqsets = ethqsets;
-
-	/*
-	 * Check for various parameter sanity issues.  Most checks simply
-	 * result in us using fewer resources than our provissioning but we
-	 * do need at least  one "port" with which to work ...
-	 */
-	if (adapter->sge.max_ethqsets < adapter->params.nports) {
-		dev_warn(adapter->pdev_dev, "only using %d of %d available"
-			 " virtual interfaces (too few Queue Sets)\n",
-			 adapter->sge.max_ethqsets, adapter->params.nports);
-		adapter->params.nports = adapter->sge.max_ethqsets;
-	}
-	if (adapter->params.nports == 0) {
-		dev_err(adapter->pdev_dev, "no virtual interfaces configured/"
-			"usable!\n");
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static inline void init_rspq(struct sge_rspq *rspq, u8 timer_idx,
-			     u8 pkt_cnt_idx, unsigned int size,
-			     unsigned int iqe_size)
-{
-	rspq->intr_params = (QINTR_TIMER_IDX(timer_idx) |
-			     (pkt_cnt_idx < SGE_NCOUNTERS ? QINTR_CNT_EN : 0));
-	rspq->pktcnt_idx = (pkt_cnt_idx < SGE_NCOUNTERS
-			    ? pkt_cnt_idx
-			    : 0);
-	rspq->iqe_len = iqe_size;
-	rspq->size = size;
-}
-
-/*
- * Perform default configuration of DMA queues depending on the number and
- * type of ports we found and the number of available CPUs.  Most settings can
- * be modified by the admin via ethtool and cxgbtool prior to the adapter
- * being brought up for the first time.
- */
-static void __devinit cfg_queues(struct adapter *adapter)
-{
-	struct sge *s = &adapter->sge;
-	int q10g, n10g, qidx, pidx, qs;
-	size_t iqe_size;
-
-	/*
-	 * We should not be called till we know how many Queue Sets we can
-	 * support.  In particular, this means that we need to know what kind
-	 * of interrupts we'll be using ...
-	 */
-	BUG_ON((adapter->flags & (USING_MSIX|USING_MSI)) == 0);
-
-	/*
-	 * Count the number of 10GbE Virtual Interfaces that we have.
-	 */
-	n10g = 0;
-	for_each_port(adapter, pidx)
-		n10g += is_10g_port(&adap2pinfo(adapter, pidx)->link_cfg);
-
-	/*
-	 * We default to 1 queue per non-10G port and up to # of cores queues
-	 * per 10G port.
-	 */
-	if (n10g == 0)
-		q10g = 0;
-	else {
-		int n1g = (adapter->params.nports - n10g);
-		q10g = (adapter->sge.max_ethqsets - n1g) / n10g;
-		if (q10g > num_online_cpus())
-			q10g = num_online_cpus();
-	}
-
-	/*
-	 * Allocate the "Queue Sets" to the various Virtual Interfaces.
-	 * The layout will be established in setup_sge_queues() when the
-	 * adapter is brough up for the first time.
-	 */
-	qidx = 0;
-	for_each_port(adapter, pidx) {
-		struct port_info *pi = adap2pinfo(adapter, pidx);
-
-		pi->first_qset = qidx;
-		pi->nqsets = is_10g_port(&pi->link_cfg) ? q10g : 1;
-		qidx += pi->nqsets;
-	}
-	s->ethqsets = qidx;
-
-	/*
-	 * The Ingress Queue Entry Size for our various Response Queues needs
-	 * to be big enough to accommodate the largest message we can receive
-	 * from the chip/firmware; which is 64 bytes ...
-	 */
-	iqe_size = 64;
-
-	/*
-	 * Set up default Queue Set parameters ...  Start off with the
-	 * shortest interrupt holdoff timer.
-	 */
-	for (qs = 0; qs < s->max_ethqsets; qs++) {
-		struct sge_eth_rxq *rxq = &s->ethrxq[qs];
-		struct sge_eth_txq *txq = &s->ethtxq[qs];
-
-		init_rspq(&rxq->rspq, 0, 0, 1024, iqe_size);
-		rxq->fl.size = 72;
-		txq->q.size = 1024;
-	}
-
-	/*
-	 * The firmware event queue is used for link state changes and
-	 * notifications of TX DMA completions.
-	 */
-	init_rspq(&s->fw_evtq, SGE_TIMER_RSTRT_CNTR, 0, 512, iqe_size);
-
-	/*
-	 * The forwarded interrupt queue is used when we're in MSI interrupt
-	 * mode.  In this mode all interrupts associated with RX queues will
-	 * be forwarded to a single queue which we'll associate with our MSI
-	 * interrupt vector.  The messages dropped in the forwarded interrupt
-	 * queue will indicate which ingress queue needs servicing ...  This
-	 * queue needs to be large enough to accommodate all of the ingress
-	 * queues which are forwarding their interrupt (+1 to prevent the PIDX
-	 * from equalling the CIDX if every ingress queue has an outstanding
-	 * interrupt).  The queue doesn't need to be any larger because no
-	 * ingress queue will ever have more than one outstanding interrupt at
-	 * any time ...
-	 */
-	init_rspq(&s->intrq, SGE_TIMER_RSTRT_CNTR, 0, MSIX_ENTRIES + 1,
-		  iqe_size);
-}
-
-/*
- * Reduce the number of Ethernet queues across all ports to at most n.
- * n provides at least one queue per port.
- */
-static void __devinit reduce_ethqs(struct adapter *adapter, int n)
-{
-	int i;
-	struct port_info *pi;
-
-	/*
-	 * While we have too many active Ether Queue Sets, interate across the
-	 * "ports" and reduce their individual Queue Set allocations.
-	 */
-	BUG_ON(n < adapter->params.nports);
-	while (n < adapter->sge.ethqsets)
-		for_each_port(adapter, i) {
-			pi = adap2pinfo(adapter, i);
-			if (pi->nqsets > 1) {
-				pi->nqsets--;
-				adapter->sge.ethqsets--;
-				if (adapter->sge.ethqsets <= n)
-					break;
-			}
-		}
-
-	/*
-	 * Reassign the starting Queue Sets for each of the "ports" ...
-	 */
-	n = 0;
-	for_each_port(adapter, i) {
-		pi = adap2pinfo(adapter, i);
-		pi->first_qset = n;
-		n += pi->nqsets;
-	}
-}
-
-/*
- * We need to grab enough MSI-X vectors to cover our interrupt needs.  Ideally
- * we get a separate MSI-X vector for every "Queue Set" plus any extras we
- * need.  Minimally we need one for every Virtual Interface plus those needed
- * for our "extras".  Note that this process may lower the maximum number of
- * allowed Queue Sets ...
- */
-static int __devinit enable_msix(struct adapter *adapter)
-{
-	int i, err, want, need;
-	struct msix_entry entries[MSIX_ENTRIES];
-	struct sge *s = &adapter->sge;
-
-	for (i = 0; i < MSIX_ENTRIES; ++i)
-		entries[i].entry = i;
-
-	/*
-	 * We _want_ enough MSI-X interrupts to cover all of our "Queue Sets"
-	 * plus those needed for our "extras" (for example, the firmware
-	 * message queue).  We _need_ at least one "Queue Set" per Virtual
-	 * Interface plus those needed for our "extras".  So now we get to see
-	 * if the song is right ...
-	 */
-	want = s->max_ethqsets + MSIX_EXTRAS;
-	need = adapter->params.nports + MSIX_EXTRAS;
-	while ((err = pci_enable_msix(adapter->pdev, entries, want)) >= need)
-		want = err;
-
-	if (err == 0) {
-		int nqsets = want - MSIX_EXTRAS;
-		if (nqsets < s->max_ethqsets) {
-			dev_warn(adapter->pdev_dev, "only enough MSI-X vectors"
-				 " for %d Queue Sets\n", nqsets);
-			s->max_ethqsets = nqsets;
-			if (nqsets < s->ethqsets)
-				reduce_ethqs(adapter, nqsets);
-		}
-		for (i = 0; i < want; ++i)
-			adapter->msix_info[i].vec = entries[i].vector;
-	} else if (err > 0) {
-		pci_disable_msix(adapter->pdev);
-		dev_info(adapter->pdev_dev, "only %d MSI-X vectors left,"
-			 " not using MSI-X\n", err);
-	}
-	return err;
-}
-
-static const struct net_device_ops cxgb4vf_netdev_ops	= {
-	.ndo_open		= cxgb4vf_open,
-	.ndo_stop		= cxgb4vf_stop,
-	.ndo_start_xmit		= t4vf_eth_xmit,
-	.ndo_get_stats		= cxgb4vf_get_stats,
-	.ndo_set_rx_mode	= cxgb4vf_set_rxmode,
-	.ndo_set_mac_address	= cxgb4vf_set_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_do_ioctl		= cxgb4vf_do_ioctl,
-	.ndo_change_mtu		= cxgb4vf_change_mtu,
-	.ndo_fix_features	= cxgb4vf_fix_features,
-	.ndo_set_features	= cxgb4vf_set_features,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= cxgb4vf_poll_controller,
-#endif
-};
-
-/*
- * "Probe" a device: initialize a device and construct all kernel and driver
- * state needed to manage the device.  This routine is called "init_one" in
- * the PF Driver ...
- */
-static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
-				       const struct pci_device_id *ent)
-{
-	static int version_printed;
-
-	int pci_using_dac;
-	int err, pidx;
-	unsigned int pmask;
-	struct adapter *adapter;
-	struct port_info *pi;
-	struct net_device *netdev;
-
-	/*
-	 * Print our driver banner the first time we're called to initialize a
-	 * device.
-	 */
-	if (version_printed == 0) {
-		printk(KERN_INFO "%s - version %s\n", DRV_DESC, DRV_VERSION);
-		version_printed = 1;
-	}
-
-	/*
-	 * Initialize generic PCI device state.
-	 */
-	err = pci_enable_device(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "cannot enable PCI device\n");
-		return err;
-	}
-
-	/*
-	 * Reserve PCI resources for the device.  If we can't get them some
-	 * other driver may have already claimed the device ...
-	 */
-	err = pci_request_regions(pdev, KBUILD_MODNAME);
-	if (err) {
-		dev_err(&pdev->dev, "cannot obtain PCI resources\n");
-		goto err_disable_device;
-	}
-
-	/*
-	 * Set up our DMA mask: try for 64-bit address masking first and
-	 * fall back to 32-bit if we can't get 64 bits ...
-	 */
-	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
-	if (err == 0) {
-		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
-		if (err) {
-			dev_err(&pdev->dev, "unable to obtain 64-bit DMA for"
-				" coherent allocations\n");
-			goto err_release_regions;
-		}
-		pci_using_dac = 1;
-	} else {
-		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-		if (err != 0) {
-			dev_err(&pdev->dev, "no usable DMA configuration\n");
-			goto err_release_regions;
-		}
-		pci_using_dac = 0;
-	}
-
-	/*
-	 * Enable bus mastering for the device ...
-	 */
-	pci_set_master(pdev);
-
-	/*
-	 * Allocate our adapter data structure and attach it to the device.
-	 */
-	adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
-	if (!adapter) {
-		err = -ENOMEM;
-		goto err_release_regions;
-	}
-	pci_set_drvdata(pdev, adapter);
-	adapter->pdev = pdev;
-	adapter->pdev_dev = &pdev->dev;
-
-	/*
-	 * Initialize SMP data synchronization resources.
-	 */
-	spin_lock_init(&adapter->stats_lock);
-
-	/*
-	 * Map our I/O registers in BAR0.
-	 */
-	adapter->regs = pci_ioremap_bar(pdev, 0);
-	if (!adapter->regs) {
-		dev_err(&pdev->dev, "cannot map device registers\n");
-		err = -ENOMEM;
-		goto err_free_adapter;
-	}
-
-	/*
-	 * Initialize adapter level features.
-	 */
-	adapter->name = pci_name(pdev);
-	adapter->msg_enable = dflt_msg_enable;
-	err = adap_init0(adapter);
-	if (err)
-		goto err_unmap_bar;
-
-	/*
-	 * Allocate our "adapter ports" and stitch everything together.
-	 */
-	pmask = adapter->params.vfres.pmask;
-	for_each_port(adapter, pidx) {
-		int port_id, viid;
-
-		/*
-		 * We simplistically allocate our virtual interfaces
-		 * sequentially across the port numbers to which we have
-		 * access rights.  This should be configurable in some manner
-		 * ...
-		 */
-		if (pmask == 0)
-			break;
-		port_id = ffs(pmask) - 1;
-		pmask &= ~(1 << port_id);
-		viid = t4vf_alloc_vi(adapter, port_id);
-		if (viid < 0) {
-			dev_err(&pdev->dev, "cannot allocate VI for port %d:"
-				" err=%d\n", port_id, viid);
-			err = viid;
-			goto err_free_dev;
-		}
-
-		/*
-		 * Allocate our network device and stitch things together.
-		 */
-		netdev = alloc_etherdev_mq(sizeof(struct port_info),
-					   MAX_PORT_QSETS);
-		if (netdev == NULL) {
-			dev_err(&pdev->dev, "cannot allocate netdev for"
-				" port %d\n", port_id);
-			t4vf_free_vi(adapter, viid);
-			err = -ENOMEM;
-			goto err_free_dev;
-		}
-		adapter->port[pidx] = netdev;
-		SET_NETDEV_DEV(netdev, &pdev->dev);
-		pi = netdev_priv(netdev);
-		pi->adapter = adapter;
-		pi->pidx = pidx;
-		pi->port_id = port_id;
-		pi->viid = viid;
-
-		/*
-		 * Initialize the starting state of our "port" and register
-		 * it.
-		 */
-		pi->xact_addr_filt = -1;
-		netif_carrier_off(netdev);
-		netdev->irq = pdev->irq;
-
-		netdev->hw_features = NETIF_F_SG | TSO_FLAGS |
-			NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-			NETIF_F_HW_VLAN_RX | NETIF_F_RXCSUM;
-		netdev->vlan_features = NETIF_F_SG | TSO_FLAGS |
-			NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-			NETIF_F_HIGHDMA;
-		netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_TX;
-		if (pci_using_dac)
-			netdev->features |= NETIF_F_HIGHDMA;
-
-		netdev->netdev_ops = &cxgb4vf_netdev_ops;
-		SET_ETHTOOL_OPS(netdev, &cxgb4vf_ethtool_ops);
-
-		/*
-		 * Initialize the hardware/software state for the port.
-		 */
-		err = t4vf_port_init(adapter, pidx);
-		if (err) {
-			dev_err(&pdev->dev, "cannot initialize port %d\n",
-				pidx);
-			goto err_free_dev;
-		}
-	}
-
-	/*
-	 * The "card" is now ready to go.  If any errors occur during device
-	 * registration we do not fail the whole "card" but rather proceed
-	 * only with the ports we manage to register successfully.  However we
-	 * must register at least one net device.
-	 */
-	for_each_port(adapter, pidx) {
-		netdev = adapter->port[pidx];
-		if (netdev == NULL)
-			continue;
-
-		err = register_netdev(netdev);
-		if (err) {
-			dev_warn(&pdev->dev, "cannot register net device %s,"
-				 " skipping\n", netdev->name);
-			continue;
-		}
-
-		set_bit(pidx, &adapter->registered_device_map);
-	}
-	if (adapter->registered_device_map == 0) {
-		dev_err(&pdev->dev, "could not register any net devices\n");
-		goto err_free_dev;
-	}
-
-	/*
-	 * Set up our debugfs entries.
-	 */
-	if (!IS_ERR_OR_NULL(cxgb4vf_debugfs_root)) {
-		adapter->debugfs_root =
-			debugfs_create_dir(pci_name(pdev),
-					   cxgb4vf_debugfs_root);
-		if (IS_ERR_OR_NULL(adapter->debugfs_root))
-			dev_warn(&pdev->dev, "could not create debugfs"
-				 " directory");
-		else
-			setup_debugfs(adapter);
-	}
-
-	/*
-	 * See what interrupts we'll be using.  If we've been configured to
-	 * use MSI-X interrupts, try to enable them but fall back to using
-	 * MSI interrupts if we can't enable MSI-X interrupts.  If we can't
-	 * get MSI interrupts we bail with the error.
-	 */
-	if (msi == MSI_MSIX && enable_msix(adapter) == 0)
-		adapter->flags |= USING_MSIX;
-	else {
-		err = pci_enable_msi(pdev);
-		if (err) {
-			dev_err(&pdev->dev, "Unable to allocate %s interrupts;"
-				" err=%d\n",
-				msi == MSI_MSIX ? "MSI-X or MSI" : "MSI", err);
-			goto err_free_debugfs;
-		}
-		adapter->flags |= USING_MSI;
-	}
-
-	/*
-	 * Now that we know how many "ports" we have and what their types are,
-	 * and how many Queue Sets we can support, we can configure our queue
-	 * resources.
-	 */
-	cfg_queues(adapter);
-
-	/*
-	 * Print a short notice on the existence and configuration of the new
-	 * VF network device ...
-	 */
-	for_each_port(adapter, pidx) {
-		dev_info(adapter->pdev_dev, "%s: Chelsio VF NIC PCIe %s\n",
-			 adapter->port[pidx]->name,
-			 (adapter->flags & USING_MSIX) ? "MSI-X" :
-			 (adapter->flags & USING_MSI)  ? "MSI" : "");
-	}
-
-	/*
-	 * Return success!
-	 */
-	return 0;
-
-	/*
-	 * Error recovery and exit code.  Unwind state that's been created
-	 * so far and return the error.
-	 */
-
-err_free_debugfs:
-	if (!IS_ERR_OR_NULL(adapter->debugfs_root)) {
-		cleanup_debugfs(adapter);
-		debugfs_remove_recursive(adapter->debugfs_root);
-	}
-
-err_free_dev:
-	for_each_port(adapter, pidx) {
-		netdev = adapter->port[pidx];
-		if (netdev == NULL)
-			continue;
-		pi = netdev_priv(netdev);
-		t4vf_free_vi(adapter, pi->viid);
-		if (test_bit(pidx, &adapter->registered_device_map))
-			unregister_netdev(netdev);
-		free_netdev(netdev);
-	}
-
-err_unmap_bar:
-	iounmap(adapter->regs);
-
-err_free_adapter:
-	kfree(adapter);
-	pci_set_drvdata(pdev, NULL);
-
-err_release_regions:
-	pci_release_regions(pdev);
-	pci_set_drvdata(pdev, NULL);
-	pci_clear_master(pdev);
-
-err_disable_device:
-	pci_disable_device(pdev);
-
-	return err;
-}
-
-/*
- * "Remove" a device: tear down all kernel and driver state created in the
- * "probe" routine and quiesce the device (disable interrupts, etc.).  (Note
- * that this is called "remove_one" in the PF Driver.)
- */
-static void __devexit cxgb4vf_pci_remove(struct pci_dev *pdev)
-{
-	struct adapter *adapter = pci_get_drvdata(pdev);
-
-	/*
-	 * Tear down driver state associated with device.
-	 */
-	if (adapter) {
-		int pidx;
-
-		/*
-		 * Stop all of our activity.  Unregister network port,
-		 * disable interrupts, etc.
-		 */
-		for_each_port(adapter, pidx)
-			if (test_bit(pidx, &adapter->registered_device_map))
-				unregister_netdev(adapter->port[pidx]);
-		t4vf_sge_stop(adapter);
-		if (adapter->flags & USING_MSIX) {
-			pci_disable_msix(adapter->pdev);
-			adapter->flags &= ~USING_MSIX;
-		} else if (adapter->flags & USING_MSI) {
-			pci_disable_msi(adapter->pdev);
-			adapter->flags &= ~USING_MSI;
-		}
-
-		/*
-		 * Tear down our debugfs entries.
-		 */
-		if (!IS_ERR_OR_NULL(adapter->debugfs_root)) {
-			cleanup_debugfs(adapter);
-			debugfs_remove_recursive(adapter->debugfs_root);
-		}
-
-		/*
-		 * Free all of the various resources which we've acquired ...
-		 */
-		t4vf_free_sge_resources(adapter);
-		for_each_port(adapter, pidx) {
-			struct net_device *netdev = adapter->port[pidx];
-			struct port_info *pi;
-
-			if (netdev == NULL)
-				continue;
-
-			pi = netdev_priv(netdev);
-			t4vf_free_vi(adapter, pi->viid);
-			free_netdev(netdev);
-		}
-		iounmap(adapter->regs);
-		kfree(adapter);
-		pci_set_drvdata(pdev, NULL);
-	}
-
-	/*
-	 * Disable the device and release its PCI resources.
-	 */
-	pci_disable_device(pdev);
-	pci_clear_master(pdev);
-	pci_release_regions(pdev);
-}
-
-/*
- * "Shutdown" quiesce the device, stopping Ingress Packet and Interrupt
- * delivery.
- */
-static void __devexit cxgb4vf_pci_shutdown(struct pci_dev *pdev)
-{
-	struct adapter *adapter;
-	int pidx;
-
-	adapter = pci_get_drvdata(pdev);
-	if (!adapter)
-		return;
-
-	/*
-	 * Disable all Virtual Interfaces.  This will shut down the
-	 * delivery of all ingress packets into the chip for these
-	 * Virtual Interfaces.
-	 */
-	for_each_port(adapter, pidx) {
-		struct net_device *netdev;
-		struct port_info *pi;
-
-		if (!test_bit(pidx, &adapter->registered_device_map))
-			continue;
-
-		netdev = adapter->port[pidx];
-		if (!netdev)
-			continue;
-
-		pi = netdev_priv(netdev);
-		t4vf_enable_vi(adapter, pi->viid, false, false);
-	}
-
-	/*
-	 * Free up all Queues which will prevent further DMA and
-	 * Interrupts allowing various internal pathways to drain.
-	 */
-	t4vf_free_sge_resources(adapter);
-}
-
-/*
- * PCI Device registration data structures.
- */
-#define CH_DEVICE(devid, idx) \
-	{ PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, PCI_ANY_ID, 0, 0, idx }
-
-static struct pci_device_id cxgb4vf_pci_tbl[] = {
-	CH_DEVICE(0xb000, 0),	/* PE10K FPGA */
-	CH_DEVICE(0x4800, 0),	/* T440-dbg */
-	CH_DEVICE(0x4801, 0),	/* T420-cr */
-	CH_DEVICE(0x4802, 0),	/* T422-cr */
-	CH_DEVICE(0x4803, 0),	/* T440-cr */
-	CH_DEVICE(0x4804, 0),	/* T420-bch */
-	CH_DEVICE(0x4805, 0),   /* T440-bch */
-	CH_DEVICE(0x4806, 0),	/* T460-ch */
-	CH_DEVICE(0x4807, 0),	/* T420-so */
-	CH_DEVICE(0x4808, 0),	/* T420-cx */
-	CH_DEVICE(0x4809, 0),	/* T420-bt */
-	CH_DEVICE(0x480a, 0),   /* T404-bt */
-	{ 0, }
-};
-
-MODULE_DESCRIPTION(DRV_DESC);
-MODULE_AUTHOR("Chelsio Communications");
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_VERSION(DRV_VERSION);
-MODULE_DEVICE_TABLE(pci, cxgb4vf_pci_tbl);
-
-static struct pci_driver cxgb4vf_driver = {
-	.name		= KBUILD_MODNAME,
-	.id_table	= cxgb4vf_pci_tbl,
-	.probe		= cxgb4vf_pci_probe,
-	.remove		= __devexit_p(cxgb4vf_pci_remove),
-	.shutdown	= __devexit_p(cxgb4vf_pci_shutdown),
-};
-
-/*
- * Initialize global driver state.
- */
-static int __init cxgb4vf_module_init(void)
-{
-	int ret;
-
-	/*
-	 * Vet our module parameters.
-	 */
-	if (msi != MSI_MSIX && msi != MSI_MSI) {
-		printk(KERN_WARNING KBUILD_MODNAME
-		       ": bad module parameter msi=%d; must be %d"
-		       " (MSI-X or MSI) or %d (MSI)\n",
-		       msi, MSI_MSIX, MSI_MSI);
-		return -EINVAL;
-	}
-
-	/* Debugfs support is optional, just warn if this fails */
-	cxgb4vf_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
-	if (IS_ERR_OR_NULL(cxgb4vf_debugfs_root))
-		printk(KERN_WARNING KBUILD_MODNAME ": could not create"
-		       " debugfs entry, continuing\n");
-
-	ret = pci_register_driver(&cxgb4vf_driver);
-	if (ret < 0 && !IS_ERR_OR_NULL(cxgb4vf_debugfs_root))
-		debugfs_remove(cxgb4vf_debugfs_root);
-	return ret;
-}
-
-/*
- * Tear down global driver state.
- */
-static void __exit cxgb4vf_module_exit(void)
-{
-	pci_unregister_driver(&cxgb4vf_driver);
-	debugfs_remove(cxgb4vf_debugfs_root);
-}
-
-module_init(cxgb4vf_module_init);
-module_exit(cxgb4vf_module_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4vf/Makefile linux-libre-3.2-gnu/drivers/net/cxgb4vf/Makefile
--- linux-libre-3.1-gnu/drivers/net/cxgb4vf/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4vf/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#
-# Chelsio T4 SR-IOV Virtual Function Driver
-#
-
-obj-$(CONFIG_CHELSIO_T4VF) += cxgb4vf.o
-
-cxgb4vf-objs := cxgb4vf_main.o t4vf_hw.o sge.o
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4vf/sge.c linux-libre-3.2-gnu/drivers/net/cxgb4vf/sge.c
--- linux-libre-3.1-gnu/drivers/net/cxgb4vf/sge.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4vf/sge.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2465 +0,0 @@
-/*
- * This file is part of the Chelsio T4 PCI-E SR-IOV Virtual Function Ethernet
- * driver for Linux.
- *
- * Copyright (c) 2009-2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_vlan.h>
-#include <linux/ip.h>
-#include <net/ipv6.h>
-#include <net/tcp.h>
-#include <linux/dma-mapping.h>
-#include <linux/prefetch.h>
-
-#include "t4vf_common.h"
-#include "t4vf_defs.h"
-
-#include "../cxgb4/t4_regs.h"
-#include "../cxgb4/t4fw_api.h"
-#include "../cxgb4/t4_msg.h"
-
-/*
- * Decoded Adapter Parameters.
- */
-static u32 FL_PG_ORDER;		/* large page allocation size */
-static u32 STAT_LEN;		/* length of status page at ring end */
-static u32 PKTSHIFT;		/* padding between CPL and packet data */
-static u32 FL_ALIGN;		/* response queue message alignment */
-
-/*
- * Constants ...
- */
-enum {
-	/*
-	 * Egress Queue sizes, producer and consumer indices are all in units
-	 * of Egress Context Units bytes.  Note that as far as the hardware is
-	 * concerned, the free list is an Egress Queue (the host produces free
-	 * buffers which the hardware consumes) and free list entries are
-	 * 64-bit PCI DMA addresses.
-	 */
-	EQ_UNIT = SGE_EQ_IDXSIZE,
-	FL_PER_EQ_UNIT = EQ_UNIT / sizeof(__be64),
-	TXD_PER_EQ_UNIT = EQ_UNIT / sizeof(__be64),
-
-	/*
-	 * Max number of TX descriptors we clean up at a time.  Should be
-	 * modest as freeing skbs isn't cheap and it happens while holding
-	 * locks.  We just need to free packets faster than they arrive, we
-	 * eventually catch up and keep the amortized cost reasonable.
-	 */
-	MAX_TX_RECLAIM = 16,
-
-	/*
-	 * Max number of Rx buffers we replenish at a time.  Again keep this
-	 * modest, allocating buffers isn't cheap either.
-	 */
-	MAX_RX_REFILL = 16,
-
-	/*
-	 * Period of the Rx queue check timer.  This timer is infrequent as it
-	 * has something to do only when the system experiences severe memory
-	 * shortage.
-	 */
-	RX_QCHECK_PERIOD = (HZ / 2),
-
-	/*
-	 * Period of the TX queue check timer and the maximum number of TX
-	 * descriptors to be reclaimed by the TX timer.
-	 */
-	TX_QCHECK_PERIOD = (HZ / 2),
-	MAX_TIMER_TX_RECLAIM = 100,
-
-	/*
-	 * An FL with <= FL_STARVE_THRES buffers is starving and a periodic
-	 * timer will attempt to refill it.
-	 */
-	FL_STARVE_THRES = 4,
-
-	/*
-	 * Suspend an Ethernet TX queue with fewer available descriptors than
-	 * this.  We always want to have room for a maximum sized packet:
-	 * inline immediate data + MAX_SKB_FRAGS. This is the same as
-	 * calc_tx_flits() for a TSO packet with nr_frags == MAX_SKB_FRAGS
-	 * (see that function and its helpers for a description of the
-	 * calculation).
-	 */
-	ETHTXQ_MAX_FRAGS = MAX_SKB_FRAGS + 1,
-	ETHTXQ_MAX_SGL_LEN = ((3 * (ETHTXQ_MAX_FRAGS-1))/2 +
-				   ((ETHTXQ_MAX_FRAGS-1) & 1) +
-				   2),
-	ETHTXQ_MAX_HDR = (sizeof(struct fw_eth_tx_pkt_vm_wr) +
-			  sizeof(struct cpl_tx_pkt_lso_core) +
-			  sizeof(struct cpl_tx_pkt_core)) / sizeof(__be64),
-	ETHTXQ_MAX_FLITS = ETHTXQ_MAX_SGL_LEN + ETHTXQ_MAX_HDR,
-
-	ETHTXQ_STOP_THRES = 1 + DIV_ROUND_UP(ETHTXQ_MAX_FLITS, TXD_PER_EQ_UNIT),
-
-	/*
-	 * Max TX descriptor space we allow for an Ethernet packet to be
-	 * inlined into a WR.  This is limited by the maximum value which
-	 * we can specify for immediate data in the firmware Ethernet TX
-	 * Work Request.
-	 */
-	MAX_IMM_TX_PKT_LEN = FW_WR_IMMDLEN_MASK,
-
-	/*
-	 * Max size of a WR sent through a control TX queue.
-	 */
-	MAX_CTRL_WR_LEN = 256,
-
-	/*
-	 * Maximum amount of data which we'll ever need to inline into a
-	 * TX ring: max(MAX_IMM_TX_PKT_LEN, MAX_CTRL_WR_LEN).
-	 */
-	MAX_IMM_TX_LEN = (MAX_IMM_TX_PKT_LEN > MAX_CTRL_WR_LEN
-			  ? MAX_IMM_TX_PKT_LEN
-			  : MAX_CTRL_WR_LEN),
-
-	/*
-	 * For incoming packets less than RX_COPY_THRES, we copy the data into
-	 * an skb rather than referencing the data.  We allocate enough
-	 * in-line room in skb's to accommodate pulling in RX_PULL_LEN bytes
-	 * of the data (header).
-	 */
-	RX_COPY_THRES = 256,
-	RX_PULL_LEN = 128,
-
-	/*
-	 * Main body length for sk_buffs used for RX Ethernet packets with
-	 * fragments.  Should be >= RX_PULL_LEN but possibly bigger to give
-	 * pskb_may_pull() some room.
-	 */
-	RX_SKB_LEN = 512,
-};
-
-/*
- * Software state per TX descriptor.
- */
-struct tx_sw_desc {
-	struct sk_buff *skb;		/* socket buffer of TX data source */
-	struct ulptx_sgl *sgl;		/* scatter/gather list in TX Queue */
-};
-
-/*
- * Software state per RX Free List descriptor.  We keep track of the allocated
- * FL page, its size, and its PCI DMA address (if the page is mapped).  The FL
- * page size and its PCI DMA mapped state are stored in the low bits of the
- * PCI DMA address as per below.
- */
-struct rx_sw_desc {
-	struct page *page;		/* Free List page buffer */
-	dma_addr_t dma_addr;		/* PCI DMA address (if mapped) */
-					/*   and flags (see below) */
-};
-
-/*
- * The low bits of rx_sw_desc.dma_addr have special meaning.  Note that the
- * SGE also uses the low 4 bits to determine the size of the buffer.  It uses
- * those bits to index into the SGE_FL_BUFFER_SIZE[index] register array.
- * Since we only use SGE_FL_BUFFER_SIZE0 and SGE_FL_BUFFER_SIZE1, these low 4
- * bits can only contain a 0 or a 1 to indicate which size buffer we're giving
- * to the SGE.  Thus, our software state of "is the buffer mapped for DMA" is
- * maintained in an inverse sense so the hardware never sees that bit high.
- */
-enum {
-	RX_LARGE_BUF    = 1 << 0,	/* buffer is SGE_FL_BUFFER_SIZE[1] */
-	RX_UNMAPPED_BUF = 1 << 1,	/* buffer is not mapped */
-};
-
-/**
- *	get_buf_addr - return DMA buffer address of software descriptor
- *	@sdesc: pointer to the software buffer descriptor
- *
- *	Return the DMA buffer address of a software descriptor (stripping out
- *	our low-order flag bits).
- */
-static inline dma_addr_t get_buf_addr(const struct rx_sw_desc *sdesc)
-{
-	return sdesc->dma_addr & ~(dma_addr_t)(RX_LARGE_BUF | RX_UNMAPPED_BUF);
-}
-
-/**
- *	is_buf_mapped - is buffer mapped for DMA?
- *	@sdesc: pointer to the software buffer descriptor
- *
- *	Determine whether the buffer associated with a software descriptor in
- *	mapped for DMA or not.
- */
-static inline bool is_buf_mapped(const struct rx_sw_desc *sdesc)
-{
-	return !(sdesc->dma_addr & RX_UNMAPPED_BUF);
-}
-
-/**
- *	need_skb_unmap - does the platform need unmapping of sk_buffs?
- *
- *	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)
-{
-#ifdef CONFIG_NEED_DMA_MAP_STATE
-	return 1;
-#else
-	return 0;
-#endif
-}
-
-/**
- *	txq_avail - return the number of available slots in a TX queue
- *	@tq: the TX queue
- *
- *	Returns the number of available descriptors in a TX queue.
- */
-static inline unsigned int txq_avail(const struct sge_txq *tq)
-{
-	return tq->size - 1 - tq->in_use;
-}
-
-/**
- *	fl_cap - return the capacity of a Free List
- *	@fl: the Free List
- *
- *	Returns the capacity of a Free List.  The capacity is less than the
- *	size because an Egress Queue Index Unit worth of descriptors needs to
- *	be left unpopulated, otherwise the Producer and Consumer indices PIDX
- *	and CIDX will match and the hardware will think the FL is empty.
- */
-static inline unsigned int fl_cap(const struct sge_fl *fl)
-{
-	return fl->size - FL_PER_EQ_UNIT;
-}
-
-/**
- *	fl_starving - return whether a Free List is starving.
- *	@fl: the Free List
- *
- *	Tests specified Free List to see whether the number of buffers
- *	available to the hardware has falled below our "starvation"
- *	threshold.
- */
-static inline bool fl_starving(const struct sge_fl *fl)
-{
-	return fl->avail - fl->pend_cred <= FL_STARVE_THRES;
-}
-
-/**
- *	map_skb -  map an skb for DMA to the device
- *	@dev: the egress net device
- *	@skb: the packet to map
- *	@addr: a pointer to the base of the DMA mapping array
- *
- *	Map an skb for DMA to the device and return an array of DMA addresses.
- */
-static int map_skb(struct device *dev, const struct sk_buff *skb,
-		   dma_addr_t *addr)
-{
-	const skb_frag_t *fp, *end;
-	const struct skb_shared_info *si;
-
-	*addr = dma_map_single(dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
-	if (dma_mapping_error(dev, *addr))
-		goto out_err;
-
-	si = skb_shinfo(skb);
-	end = &si->frags[si->nr_frags];
-	for (fp = si->frags; fp < end; fp++) {
-		*++addr = dma_map_page(dev, fp->page, fp->page_offset, fp->size,
-				       DMA_TO_DEVICE);
-		if (dma_mapping_error(dev, *addr))
-			goto unwind;
-	}
-	return 0;
-
-unwind:
-	while (fp-- > si->frags)
-		dma_unmap_page(dev, *--addr, fp->size, DMA_TO_DEVICE);
-	dma_unmap_single(dev, addr[-1], skb_headlen(skb), DMA_TO_DEVICE);
-
-out_err:
-	return -ENOMEM;
-}
-
-static void unmap_sgl(struct device *dev, const struct sk_buff *skb,
-		      const struct ulptx_sgl *sgl, const struct sge_txq *tq)
-{
-	const struct ulptx_sge_pair *p;
-	unsigned int nfrags = skb_shinfo(skb)->nr_frags;
-
-	if (likely(skb_headlen(skb)))
-		dma_unmap_single(dev, be64_to_cpu(sgl->addr0),
-				 be32_to_cpu(sgl->len0), DMA_TO_DEVICE);
-	else {
-		dma_unmap_page(dev, be64_to_cpu(sgl->addr0),
-			       be32_to_cpu(sgl->len0), DMA_TO_DEVICE);
-		nfrags--;
-	}
-
-	/*
-	 * the complexity below is because of the possibility of a wrap-around
-	 * in the middle of an SGL
-	 */
-	for (p = sgl->sge; nfrags >= 2; nfrags -= 2) {
-		if (likely((u8 *)(p + 1) <= (u8 *)tq->stat)) {
-unmap:
-			dma_unmap_page(dev, be64_to_cpu(p->addr[0]),
-				       be32_to_cpu(p->len[0]), DMA_TO_DEVICE);
-			dma_unmap_page(dev, be64_to_cpu(p->addr[1]),
-				       be32_to_cpu(p->len[1]), DMA_TO_DEVICE);
-			p++;
-		} else if ((u8 *)p == (u8 *)tq->stat) {
-			p = (const struct ulptx_sge_pair *)tq->desc;
-			goto unmap;
-		} else if ((u8 *)p + 8 == (u8 *)tq->stat) {
-			const __be64 *addr = (const __be64 *)tq->desc;
-
-			dma_unmap_page(dev, be64_to_cpu(addr[0]),
-				       be32_to_cpu(p->len[0]), DMA_TO_DEVICE);
-			dma_unmap_page(dev, be64_to_cpu(addr[1]),
-				       be32_to_cpu(p->len[1]), DMA_TO_DEVICE);
-			p = (const struct ulptx_sge_pair *)&addr[2];
-		} else {
-			const __be64 *addr = (const __be64 *)tq->desc;
-
-			dma_unmap_page(dev, be64_to_cpu(p->addr[0]),
-				       be32_to_cpu(p->len[0]), DMA_TO_DEVICE);
-			dma_unmap_page(dev, be64_to_cpu(addr[0]),
-				       be32_to_cpu(p->len[1]), DMA_TO_DEVICE);
-			p = (const struct ulptx_sge_pair *)&addr[1];
-		}
-	}
-	if (nfrags) {
-		__be64 addr;
-
-		if ((u8 *)p == (u8 *)tq->stat)
-			p = (const struct ulptx_sge_pair *)tq->desc;
-		addr = ((u8 *)p + 16 <= (u8 *)tq->stat
-			? p->addr[0]
-			: *(const __be64 *)tq->desc);
-		dma_unmap_page(dev, be64_to_cpu(addr), be32_to_cpu(p->len[0]),
-			       DMA_TO_DEVICE);
-	}
-}
-
-/**
- *	free_tx_desc - reclaims TX descriptors and their buffers
- *	@adapter: the adapter
- *	@tq: the TX queue to reclaim descriptors from
- *	@n: the number of descriptors to reclaim
- *	@unmap: whether the buffers should be unmapped for DMA
- *
- *	Reclaims TX descriptors from an SGE TX queue and frees the associated
- *	TX buffers.  Called with the TX queue lock held.
- */
-static void free_tx_desc(struct adapter *adapter, struct sge_txq *tq,
-			 unsigned int n, bool unmap)
-{
-	struct tx_sw_desc *sdesc;
-	unsigned int cidx = tq->cidx;
-	struct device *dev = adapter->pdev_dev;
-
-	const int need_unmap = need_skb_unmap() && unmap;
-
-	sdesc = &tq->sdesc[cidx];
-	while (n--) {
-		/*
-		 * If we kept a reference to the original TX skb, we need to
-		 * unmap it from PCI DMA space (if required) and free it.
-		 */
-		if (sdesc->skb) {
-			if (need_unmap)
-				unmap_sgl(dev, sdesc->skb, sdesc->sgl, tq);
-			kfree_skb(sdesc->skb);
-			sdesc->skb = NULL;
-		}
-
-		sdesc++;
-		if (++cidx == tq->size) {
-			cidx = 0;
-			sdesc = tq->sdesc;
-		}
-	}
-	tq->cidx = cidx;
-}
-
-/*
- * Return the number of reclaimable descriptors in a TX queue.
- */
-static inline int reclaimable(const struct sge_txq *tq)
-{
-	int hw_cidx = be16_to_cpu(tq->stat->cidx);
-	int reclaimable = hw_cidx - tq->cidx;
-	if (reclaimable < 0)
-		reclaimable += tq->size;
-	return reclaimable;
-}
-
-/**
- *	reclaim_completed_tx - reclaims completed TX descriptors
- *	@adapter: the adapter
- *	@tq: the TX queue to reclaim completed descriptors from
- *	@unmap: whether the buffers should be unmapped for DMA
- *
- *	Reclaims TX descriptors that the SGE has indicated it has processed,
- *	and frees the associated buffers if possible.  Called with the TX
- *	queue locked.
- */
-static inline void reclaim_completed_tx(struct adapter *adapter,
-					struct sge_txq *tq,
-					bool unmap)
-{
-	int avail = reclaimable(tq);
-
-	if (avail) {
-		/*
-		 * Limit the amount of clean up work we do at a time to keep
-		 * the TX lock hold time O(1).
-		 */
-		if (avail > MAX_TX_RECLAIM)
-			avail = MAX_TX_RECLAIM;
-
-		free_tx_desc(adapter, tq, avail, unmap);
-		tq->in_use -= avail;
-	}
-}
-
-/**
- *	get_buf_size - return the size of an RX Free List buffer.
- *	@sdesc: pointer to the software buffer descriptor
- */
-static inline int get_buf_size(const struct rx_sw_desc *sdesc)
-{
-	return FL_PG_ORDER > 0 && (sdesc->dma_addr & RX_LARGE_BUF)
-		? (PAGE_SIZE << FL_PG_ORDER)
-		: PAGE_SIZE;
-}
-
-/**
- *	free_rx_bufs - free RX buffers on an SGE Free List
- *	@adapter: the adapter
- *	@fl: the SGE Free List to free buffers from
- *	@n: how many buffers to free
- *
- *	Release the next @n buffers on an SGE Free List RX queue.   The
- *	buffers must be made inaccessible to hardware before calling this
- *	function.
- */
-static void free_rx_bufs(struct adapter *adapter, struct sge_fl *fl, int n)
-{
-	while (n--) {
-		struct rx_sw_desc *sdesc = &fl->sdesc[fl->cidx];
-
-		if (is_buf_mapped(sdesc))
-			dma_unmap_page(adapter->pdev_dev, get_buf_addr(sdesc),
-				       get_buf_size(sdesc), PCI_DMA_FROMDEVICE);
-		put_page(sdesc->page);
-		sdesc->page = NULL;
-		if (++fl->cidx == fl->size)
-			fl->cidx = 0;
-		fl->avail--;
-	}
-}
-
-/**
- *	unmap_rx_buf - unmap the current RX buffer on an SGE Free List
- *	@adapter: the adapter
- *	@fl: the SGE Free List
- *
- *	Unmap the current buffer on an SGE Free List RX queue.   The
- *	buffer must be made inaccessible to HW before calling this function.
- *
- *	This is similar to @free_rx_bufs above but does not free the buffer.
- *	Do note that the FL still loses any further access to the buffer.
- *	This is used predominantly to "transfer ownership" of an FL buffer
- *	to another entity (typically an skb's fragment list).
- */
-static void unmap_rx_buf(struct adapter *adapter, struct sge_fl *fl)
-{
-	struct rx_sw_desc *sdesc = &fl->sdesc[fl->cidx];
-
-	if (is_buf_mapped(sdesc))
-		dma_unmap_page(adapter->pdev_dev, get_buf_addr(sdesc),
-			       get_buf_size(sdesc), PCI_DMA_FROMDEVICE);
-	sdesc->page = NULL;
-	if (++fl->cidx == fl->size)
-		fl->cidx = 0;
-	fl->avail--;
-}
-
-/**
- *	ring_fl_db - righ doorbell on free list
- *	@adapter: the adapter
- *	@fl: the Free List whose doorbell should be rung ...
- *
- *	Tell the Scatter Gather Engine that there are new free list entries
- *	available.
- */
-static inline void ring_fl_db(struct adapter *adapter, struct sge_fl *fl)
-{
-	/*
-	 * The SGE keeps track of its Producer and Consumer Indices in terms
-	 * of Egress Queue Units so we can only tell it about integral numbers
-	 * of multiples of Free List Entries per Egress Queue Units ...
-	 */
-	if (fl->pend_cred >= FL_PER_EQ_UNIT) {
-		wmb();
-		t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL,
-			     DBPRIO |
-			     QID(fl->cntxt_id) |
-			     PIDX(fl->pend_cred / FL_PER_EQ_UNIT));
-		fl->pend_cred %= FL_PER_EQ_UNIT;
-	}
-}
-
-/**
- *	set_rx_sw_desc - initialize software RX buffer descriptor
- *	@sdesc: pointer to the softwore RX buffer descriptor
- *	@page: pointer to the page data structure backing the RX buffer
- *	@dma_addr: PCI DMA address (possibly with low-bit flags)
- */
-static inline void set_rx_sw_desc(struct rx_sw_desc *sdesc, struct page *page,
-				  dma_addr_t dma_addr)
-{
-	sdesc->page = page;
-	sdesc->dma_addr = dma_addr;
-}
-
-/*
- * Support for poisoning RX buffers ...
- */
-#define POISON_BUF_VAL -1
-
-static inline void poison_buf(struct page *page, size_t sz)
-{
-#if POISON_BUF_VAL >= 0
-	memset(page_address(page), POISON_BUF_VAL, sz);
-#endif
-}
-
-/**
- *	refill_fl - refill an SGE RX buffer ring
- *	@adapter: the adapter
- *	@fl: the Free List ring to refill
- *	@n: the number of new buffers to allocate
- *	@gfp: the gfp flags for the allocations
- *
- *	(Re)populate an SGE free-buffer queue with up to @n new packet buffers,
- *	allocated with the supplied gfp flags.  The caller must assure that
- *	@n does not exceed the queue's capacity -- i.e. (cidx == pidx) _IN
- *	EGRESS QUEUE UNITS_ indicates an empty Free List!  Returns the number
- *	of buffers allocated.  If afterwards the queue is found critically low,
- *	mark it as starving in the bitmap of starving FLs.
- */
-static unsigned int refill_fl(struct adapter *adapter, struct sge_fl *fl,
-			      int n, gfp_t gfp)
-{
-	struct page *page;
-	dma_addr_t dma_addr;
-	unsigned int cred = fl->avail;
-	__be64 *d = &fl->desc[fl->pidx];
-	struct rx_sw_desc *sdesc = &fl->sdesc[fl->pidx];
-
-	/*
-	 * Sanity: ensure that the result of adding n Free List buffers
-	 * won't result in wrapping the SGE's Producer Index around to
-	 * it's Consumer Index thereby indicating an empty Free List ...
-	 */
-	BUG_ON(fl->avail + n > fl->size - FL_PER_EQ_UNIT);
-
-	/*
-	 * If we support large pages, prefer large buffers and fail over to
-	 * small pages if we can't allocate large pages to satisfy the refill.
-	 * If we don't support large pages, drop directly into the small page
-	 * allocation code.
-	 */
-	if (FL_PG_ORDER == 0)
-		goto alloc_small_pages;
-
-	while (n) {
-		page = alloc_pages(gfp | __GFP_COMP | __GFP_NOWARN,
-				   FL_PG_ORDER);
-		if (unlikely(!page)) {
-			/*
-			 * We've failed inour attempt to allocate a "large
-			 * page".  Fail over to the "small page" allocation
-			 * below.
-			 */
-			fl->large_alloc_failed++;
-			break;
-		}
-		poison_buf(page, PAGE_SIZE << FL_PG_ORDER);
-
-		dma_addr = dma_map_page(adapter->pdev_dev, page, 0,
-					PAGE_SIZE << FL_PG_ORDER,
-					PCI_DMA_FROMDEVICE);
-		if (unlikely(dma_mapping_error(adapter->pdev_dev, dma_addr))) {
-			/*
-			 * We've run out of DMA mapping space.  Free up the
-			 * buffer and return with what we've managed to put
-			 * into the free list.  We don't want to fail over to
-			 * the small page allocation below in this case
-			 * because DMA mapping resources are typically
-			 * critical resources once they become scarse.
-			 */
-			__free_pages(page, FL_PG_ORDER);
-			goto out;
-		}
-		dma_addr |= RX_LARGE_BUF;
-		*d++ = cpu_to_be64(dma_addr);
-
-		set_rx_sw_desc(sdesc, page, dma_addr);
-		sdesc++;
-
-		fl->avail++;
-		if (++fl->pidx == fl->size) {
-			fl->pidx = 0;
-			sdesc = fl->sdesc;
-			d = fl->desc;
-		}
-		n--;
-	}
-
-alloc_small_pages:
-	while (n--) {
-		page = __netdev_alloc_page(adapter->port[0],
-					   gfp | __GFP_NOWARN);
-		if (unlikely(!page)) {
-			fl->alloc_failed++;
-			break;
-		}
-		poison_buf(page, PAGE_SIZE);
-
-		dma_addr = dma_map_page(adapter->pdev_dev, page, 0, PAGE_SIZE,
-				       PCI_DMA_FROMDEVICE);
-		if (unlikely(dma_mapping_error(adapter->pdev_dev, dma_addr))) {
-			netdev_free_page(adapter->port[0], page);
-			break;
-		}
-		*d++ = cpu_to_be64(dma_addr);
-
-		set_rx_sw_desc(sdesc, page, dma_addr);
-		sdesc++;
-
-		fl->avail++;
-		if (++fl->pidx == fl->size) {
-			fl->pidx = 0;
-			sdesc = fl->sdesc;
-			d = fl->desc;
-		}
-	}
-
-out:
-	/*
-	 * Update our accounting state to incorporate the new Free List
-	 * buffers, tell the hardware about them and return the number of
-	 * bufers which we were able to allocate.
-	 */
-	cred = fl->avail - cred;
-	fl->pend_cred += cred;
-	ring_fl_db(adapter, fl);
-
-	if (unlikely(fl_starving(fl))) {
-		smp_wmb();
-		set_bit(fl->cntxt_id, adapter->sge.starving_fl);
-	}
-
-	return cred;
-}
-
-/*
- * Refill a Free List to its capacity or the Maximum Refill Increment,
- * whichever is smaller ...
- */
-static inline void __refill_fl(struct adapter *adapter, struct sge_fl *fl)
-{
-	refill_fl(adapter, fl,
-		  min((unsigned int)MAX_RX_REFILL, fl_cap(fl) - fl->avail),
-		  GFP_ATOMIC);
-}
-
-/**
- *	alloc_ring - allocate resources for an SGE descriptor ring
- *	@dev: the PCI device's core device
- *	@nelem: the number of descriptors
- *	@hwsize: the size of each hardware descriptor
- *	@swsize: the size of each software descriptor
- *	@busaddrp: the physical PCI bus address of the allocated ring
- *	@swringp: return address pointer for software ring
- *	@stat_size: extra space in hardware ring for status information
- *
- *	Allocates resources for an SGE descriptor ring, such as TX queues,
- *	free buffer lists, response queues, etc.  Each SGE ring requires
- *	space for its hardware descriptors plus, optionally, space for software
- *	state associated with each hardware entry (the metadata).  The function
- *	returns three values: the virtual address for the hardware ring (the
- *	return value of the function), the PCI bus address of the hardware
- *	ring (in *busaddrp), and the address of the software ring (in swringp).
- *	Both the hardware and software rings are returned zeroed out.
- */
-static void *alloc_ring(struct device *dev, size_t nelem, size_t hwsize,
-			size_t swsize, dma_addr_t *busaddrp, void *swringp,
-			size_t stat_size)
-{
-	/*
-	 * Allocate the hardware ring and PCI DMA bus address space for said.
-	 */
-	size_t hwlen = nelem * hwsize + stat_size;
-	void *hwring = dma_alloc_coherent(dev, hwlen, busaddrp, GFP_KERNEL);
-
-	if (!hwring)
-		return NULL;
-
-	/*
-	 * If the caller wants a software ring, allocate it and return a
-	 * pointer to it in *swringp.
-	 */
-	BUG_ON((swsize != 0) != (swringp != NULL));
-	if (swsize) {
-		void *swring = kcalloc(nelem, swsize, GFP_KERNEL);
-
-		if (!swring) {
-			dma_free_coherent(dev, hwlen, hwring, *busaddrp);
-			return NULL;
-		}
-		*(void **)swringp = swring;
-	}
-
-	/*
-	 * Zero out the hardware ring and return its address as our function
-	 * value.
-	 */
-	memset(hwring, 0, hwlen);
-	return hwring;
-}
-
-/**
- *	sgl_len - calculates the size of an SGL of the given capacity
- *	@n: the number of SGL entries
- *
- *	Calculates the number of flits (8-byte units) needed for a Direct
- *	Scatter/Gather List that can hold the given number of entries.
- */
-static inline unsigned int sgl_len(unsigned int n)
-{
-	/*
-	 * A Direct Scatter Gather List uses 32-bit lengths and 64-bit PCI DMA
-	 * addresses.  The DSGL Work Request starts off with a 32-bit DSGL
-	 * ULPTX header, then Length0, then Address0, then, for 1 <= i <= N,
-	 * repeated sequences of { Length[i], Length[i+1], Address[i],
-	 * Address[i+1] } (this ensures that all addresses are on 64-bit
-	 * boundaries).  If N is even, then Length[N+1] should be set to 0 and
-	 * Address[N+1] is omitted.
-	 *
-	 * The following calculation incorporates all of the above.  It's
-	 * somewhat hard to follow but, briefly: the "+2" accounts for the
-	 * first two flits which include the DSGL header, Length0 and
-	 * Address0; the "(3*(n-1))/2" covers the main body of list entries (3
-	 * flits for every pair of the remaining N) +1 if (n-1) is odd; and
-	 * finally the "+((n-1)&1)" adds the one remaining flit needed if
-	 * (n-1) is odd ...
-	 */
-	n--;
-	return (3 * n) / 2 + (n & 1) + 2;
-}
-
-/**
- *	flits_to_desc - returns the num of TX descriptors for the given flits
- *	@flits: the number of flits
- *
- *	Returns the number of TX descriptors needed for the supplied number
- *	of flits.
- */
-static inline unsigned int flits_to_desc(unsigned int flits)
-{
-	BUG_ON(flits > SGE_MAX_WR_LEN / sizeof(__be64));
-	return DIV_ROUND_UP(flits, TXD_PER_EQ_UNIT);
-}
-
-/**
- *	is_eth_imm - can an Ethernet packet be sent as immediate data?
- *	@skb: the packet
- *
- *	Returns whether an Ethernet packet is small enough to fit completely as
- *	immediate data.
- */
-static inline int is_eth_imm(const struct sk_buff *skb)
-{
-	/*
-	 * The VF Driver uses the FW_ETH_TX_PKT_VM_WR firmware Work Request
-	 * which does not accommodate immediate data.  We could dike out all
-	 * of the support code for immediate data but that would tie our hands
-	 * too much if we ever want to enhace the firmware.  It would also
-	 * create more differences between the PF and VF Drivers.
-	 */
-	return false;
-}
-
-/**
- *	calc_tx_flits - calculate the number of flits for a packet TX WR
- *	@skb: the packet
- *
- *	Returns the number of flits needed for a TX Work Request for the
- *	given Ethernet packet, including the needed WR and CPL headers.
- */
-static inline unsigned int calc_tx_flits(const struct sk_buff *skb)
-{
-	unsigned int flits;
-
-	/*
-	 * If the skb is small enough, we can pump it out as a work request
-	 * with only immediate data.  In that case we just have to have the
-	 * TX Packet header plus the skb data in the Work Request.
-	 */
-	if (is_eth_imm(skb))
-		return DIV_ROUND_UP(skb->len + sizeof(struct cpl_tx_pkt),
-				    sizeof(__be64));
-
-	/*
-	 * Otherwise, we're going to have to construct a Scatter gather list
-	 * of the skb body and fragments.  We also include the flits necessary
-	 * for the TX Packet Work Request and CPL.  We always have a firmware
-	 * Write Header (incorporated as part of the cpl_tx_pkt_lso and
-	 * cpl_tx_pkt structures), followed by either a TX Packet Write CPL
-	 * message or, if we're doing a Large Send Offload, an LSO CPL message
-	 * with an embeded TX Packet Write CPL message.
-	 */
-	flits = sgl_len(skb_shinfo(skb)->nr_frags + 1);
-	if (skb_shinfo(skb)->gso_size)
-		flits += (sizeof(struct fw_eth_tx_pkt_vm_wr) +
-			  sizeof(struct cpl_tx_pkt_lso_core) +
-			  sizeof(struct cpl_tx_pkt_core)) / sizeof(__be64);
-	else
-		flits += (sizeof(struct fw_eth_tx_pkt_vm_wr) +
-			  sizeof(struct cpl_tx_pkt_core)) / sizeof(__be64);
-	return flits;
-}
-
-/**
- *	write_sgl - populate a Scatter/Gather List for a packet
- *	@skb: the packet
- *	@tq: the TX queue we are writing into
- *	@sgl: starting location for writing the SGL
- *	@end: points right after the end of the SGL
- *	@start: start offset into skb main-body data to include in the SGL
- *	@addr: the list of DMA bus addresses for the SGL elements
- *
- *	Generates a Scatter/Gather List for the buffers that make up a packet.
- *	The caller must provide adequate space for the SGL that will be written.
- *	The SGL includes all of the packet's page fragments and the data in its
- *	main body except for the first @start bytes.  @pos must be 16-byte
- *	aligned and within a TX descriptor with available space.  @end points
- *	write after the end of the SGL but does not account for any potential
- *	wrap around, i.e., @end > @tq->stat.
- */
-static void write_sgl(const struct sk_buff *skb, struct sge_txq *tq,
-		      struct ulptx_sgl *sgl, u64 *end, unsigned int start,
-		      const dma_addr_t *addr)
-{
-	unsigned int i, len;
-	struct ulptx_sge_pair *to;
-	const struct skb_shared_info *si = skb_shinfo(skb);
-	unsigned int nfrags = si->nr_frags;
-	struct ulptx_sge_pair buf[MAX_SKB_FRAGS / 2 + 1];
-
-	len = skb_headlen(skb) - start;
-	if (likely(len)) {
-		sgl->len0 = htonl(len);
-		sgl->addr0 = cpu_to_be64(addr[0] + start);
-		nfrags++;
-	} else {
-		sgl->len0 = htonl(si->frags[0].size);
-		sgl->addr0 = cpu_to_be64(addr[1]);
-	}
-
-	sgl->cmd_nsge = htonl(ULPTX_CMD(ULP_TX_SC_DSGL) |
-			      ULPTX_NSGE(nfrags));
-	if (likely(--nfrags == 0))
-		return;
-	/*
-	 * Most of the complexity below deals with the possibility we hit the
-	 * end of the queue in the middle of writing the SGL.  For this case
-	 * only we create the SGL in a temporary buffer and then copy it.
-	 */
-	to = (u8 *)end > (u8 *)tq->stat ? buf : sgl->sge;
-
-	for (i = (nfrags != si->nr_frags); nfrags >= 2; nfrags -= 2, to++) {
-		to->len[0] = cpu_to_be32(si->frags[i].size);
-		to->len[1] = cpu_to_be32(si->frags[++i].size);
-		to->addr[0] = cpu_to_be64(addr[i]);
-		to->addr[1] = cpu_to_be64(addr[++i]);
-	}
-	if (nfrags) {
-		to->len[0] = cpu_to_be32(si->frags[i].size);
-		to->len[1] = cpu_to_be32(0);
-		to->addr[0] = cpu_to_be64(addr[i + 1]);
-	}
-	if (unlikely((u8 *)end > (u8 *)tq->stat)) {
-		unsigned int part0 = (u8 *)tq->stat - (u8 *)sgl->sge, part1;
-
-		if (likely(part0))
-			memcpy(sgl->sge, buf, part0);
-		part1 = (u8 *)end - (u8 *)tq->stat;
-		memcpy(tq->desc, (u8 *)buf + part0, part1);
-		end = (void *)tq->desc + part1;
-	}
-	if ((uintptr_t)end & 8)           /* 0-pad to multiple of 16 */
-		*(u64 *)end = 0;
-}
-
-/**
- *	check_ring_tx_db - check and potentially ring a TX queue's doorbell
- *	@adapter: the adapter
- *	@tq: the TX queue
- *	@n: number of new descriptors to give to HW
- *
- *	Ring the doorbel for a TX queue.
- */
-static inline void ring_tx_db(struct adapter *adapter, struct sge_txq *tq,
-			      int n)
-{
-	/*
-	 * Warn if we write doorbells with the wrong priority and write
-	 * descriptors before telling HW.
-	 */
-	WARN_ON((QID(tq->cntxt_id) | PIDX(n)) & DBPRIO);
-	wmb();
-	t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL,
-		     QID(tq->cntxt_id) | PIDX(n));
-}
-
-/**
- *	inline_tx_skb - inline a packet's data into TX descriptors
- *	@skb: the packet
- *	@tq: the TX queue where the packet will be inlined
- *	@pos: starting position in the TX queue to inline the packet
- *
- *	Inline a packet's contents directly into TX descriptors, starting at
- *	the given position within the TX DMA ring.
- *	Most of the complexity of this operation is dealing with wrap arounds
- *	in the middle of the packet we want to inline.
- */
-static void inline_tx_skb(const struct sk_buff *skb, const struct sge_txq *tq,
-			  void *pos)
-{
-	u64 *p;
-	int left = (void *)tq->stat - pos;
-
-	if (likely(skb->len <= left)) {
-		if (likely(!skb->data_len))
-			skb_copy_from_linear_data(skb, pos, skb->len);
-		else
-			skb_copy_bits(skb, 0, pos, skb->len);
-		pos += skb->len;
-	} else {
-		skb_copy_bits(skb, 0, pos, left);
-		skb_copy_bits(skb, left, tq->desc, skb->len - left);
-		pos = (void *)tq->desc + (skb->len - left);
-	}
-
-	/* 0-pad to multiple of 16 */
-	p = PTR_ALIGN(pos, 8);
-	if ((uintptr_t)p & 8)
-		*p = 0;
-}
-
-/*
- * Figure out what HW csum a packet wants and return the appropriate control
- * bits.
- */
-static u64 hwcsum(const struct sk_buff *skb)
-{
-	int csum_type;
-	const struct iphdr *iph = ip_hdr(skb);
-
-	if (iph->version == 4) {
-		if (iph->protocol == IPPROTO_TCP)
-			csum_type = TX_CSUM_TCPIP;
-		else if (iph->protocol == IPPROTO_UDP)
-			csum_type = TX_CSUM_UDPIP;
-		else {
-nocsum:
-			/*
-			 * unknown protocol, disable HW csum
-			 * and hope a bad packet is detected
-			 */
-			return TXPKT_L4CSUM_DIS;
-		}
-	} else {
-		/*
-		 * this doesn't work with extension headers
-		 */
-		const struct ipv6hdr *ip6h = (const struct ipv6hdr *)iph;
-
-		if (ip6h->nexthdr == IPPROTO_TCP)
-			csum_type = TX_CSUM_TCPIP6;
-		else if (ip6h->nexthdr == IPPROTO_UDP)
-			csum_type = TX_CSUM_UDPIP6;
-		else
-			goto nocsum;
-	}
-
-	if (likely(csum_type >= TX_CSUM_TCPIP))
-		return TXPKT_CSUM_TYPE(csum_type) |
-			TXPKT_IPHDR_LEN(skb_network_header_len(skb)) |
-			TXPKT_ETHHDR_LEN(skb_network_offset(skb) - ETH_HLEN);
-	else {
-		int start = skb_transport_offset(skb);
-
-		return TXPKT_CSUM_TYPE(csum_type) |
-			TXPKT_CSUM_START(start) |
-			TXPKT_CSUM_LOC(start + skb->csum_offset);
-	}
-}
-
-/*
- * Stop an Ethernet TX queue and record that state change.
- */
-static void txq_stop(struct sge_eth_txq *txq)
-{
-	netif_tx_stop_queue(txq->txq);
-	txq->q.stops++;
-}
-
-/*
- * Advance our software state for a TX queue by adding n in use descriptors.
- */
-static inline void txq_advance(struct sge_txq *tq, unsigned int n)
-{
-	tq->in_use += n;
-	tq->pidx += n;
-	if (tq->pidx >= tq->size)
-		tq->pidx -= tq->size;
-}
-
-/**
- *	t4vf_eth_xmit - add a packet to an Ethernet TX queue
- *	@skb: the packet
- *	@dev: the egress net device
- *
- *	Add a packet to an SGE Ethernet TX queue.  Runs with softirqs disabled.
- */
-int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	u32 wr_mid;
-	u64 cntrl, *end;
-	int qidx, credits;
-	unsigned int flits, ndesc;
-	struct adapter *adapter;
-	struct sge_eth_txq *txq;
-	const struct port_info *pi;
-	struct fw_eth_tx_pkt_vm_wr *wr;
-	struct cpl_tx_pkt_core *cpl;
-	const struct skb_shared_info *ssi;
-	dma_addr_t addr[MAX_SKB_FRAGS + 1];
-	const size_t fw_hdr_copy_len = (sizeof(wr->ethmacdst) +
-					sizeof(wr->ethmacsrc) +
-					sizeof(wr->ethtype) +
-					sizeof(wr->vlantci));
-
-	/*
-	 * The chip minimum packet length is 10 octets but the firmware
-	 * command that we are using requires that we copy the Ethernet header
-	 * (including the VLAN tag) into the header so we reject anything
-	 * smaller than that ...
-	 */
-	if (unlikely(skb->len < fw_hdr_copy_len))
-		goto out_free;
-
-	/*
-	 * Figure out which TX Queue we're going to use.
-	 */
-	pi = netdev_priv(dev);
-	adapter = pi->adapter;
-	qidx = skb_get_queue_mapping(skb);
-	BUG_ON(qidx >= pi->nqsets);
-	txq = &adapter->sge.ethtxq[pi->first_qset + qidx];
-
-	/*
-	 * Take this opportunity to reclaim any TX Descriptors whose DMA
-	 * transfers have completed.
-	 */
-	reclaim_completed_tx(adapter, &txq->q, true);
-
-	/*
-	 * Calculate the number of flits and TX Descriptors we're going to
-	 * need along with how many TX Descriptors will be left over after
-	 * we inject our Work Request.
-	 */
-	flits = calc_tx_flits(skb);
-	ndesc = flits_to_desc(flits);
-	credits = txq_avail(&txq->q) - ndesc;
-
-	if (unlikely(credits < 0)) {
-		/*
-		 * Not enough room for this packet's Work Request.  Stop the
-		 * TX Queue and return a "busy" condition.  The queue will get
-		 * started later on when the firmware informs us that space
-		 * has opened up.
-		 */
-		txq_stop(txq);
-		dev_err(adapter->pdev_dev,
-			"%s: TX ring %u full while queue awake!\n",
-			dev->name, qidx);
-		return NETDEV_TX_BUSY;
-	}
-
-	if (!is_eth_imm(skb) &&
-	    unlikely(map_skb(adapter->pdev_dev, skb, addr) < 0)) {
-		/*
-		 * We need to map the skb into PCI DMA space (because it can't
-		 * be in-lined directly into the Work Request) and the mapping
-		 * operation failed.  Record the error and drop the packet.
-		 */
-		txq->mapping_err++;
-		goto out_free;
-	}
-
-	wr_mid = FW_WR_LEN16(DIV_ROUND_UP(flits, 2));
-	if (unlikely(credits < ETHTXQ_STOP_THRES)) {
-		/*
-		 * After we're done injecting the Work Request for this
-		 * 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
-		 * Egress Queue Status Update message indicating that space
-		 * has opened up.
-		 */
-		txq_stop(txq);
-		wr_mid |= FW_WR_EQUEQ | FW_WR_EQUIQ;
-	}
-
-	/*
-	 * Start filling in our Work Request.  Note that we do _not_ handle
-	 * the WR Header wrapping around the TX Descriptor Ring.  If our
-	 * maximum header size ever exceeds one TX Descriptor, we'll need to
-	 * do something else here.
-	 */
-	BUG_ON(DIV_ROUND_UP(ETHTXQ_MAX_HDR, TXD_PER_EQ_UNIT) > 1);
-	wr = (void *)&txq->q.desc[txq->q.pidx];
-	wr->equiq_to_len16 = cpu_to_be32(wr_mid);
-	wr->r3[0] = cpu_to_be64(0);
-	wr->r3[1] = cpu_to_be64(0);
-	skb_copy_from_linear_data(skb, (void *)wr->ethmacdst, fw_hdr_copy_len);
-	end = (u64 *)wr + flits;
-
-	/*
-	 * If this is a Large Send Offload packet we'll put in an LSO CPL
-	 * message with an encapsulated TX Packet CPL message.  Otherwise we
-	 * just use a TX Packet CPL message.
-	 */
-	ssi = skb_shinfo(skb);
-	if (ssi->gso_size) {
-		struct cpl_tx_pkt_lso_core *lso = (void *)(wr + 1);
-		bool v6 = (ssi->gso_type & SKB_GSO_TCPV6) != 0;
-		int l3hdr_len = skb_network_header_len(skb);
-		int eth_xtra_len = skb_network_offset(skb) - ETH_HLEN;
-
-		wr->op_immdlen =
-			cpu_to_be32(FW_WR_OP(FW_ETH_TX_PKT_VM_WR) |
-				    FW_WR_IMMDLEN(sizeof(*lso) +
-						  sizeof(*cpl)));
-		/*
-		 * Fill in the LSO CPL message.
-		 */
-		lso->lso_ctrl =
-			cpu_to_be32(LSO_OPCODE(CPL_TX_PKT_LSO) |
-				    LSO_FIRST_SLICE |
-				    LSO_LAST_SLICE |
-				    LSO_IPV6(v6) |
-				    LSO_ETHHDR_LEN(eth_xtra_len/4) |
-				    LSO_IPHDR_LEN(l3hdr_len/4) |
-				    LSO_TCPHDR_LEN(tcp_hdr(skb)->doff));
-		lso->ipid_ofst = cpu_to_be16(0);
-		lso->mss = cpu_to_be16(ssi->gso_size);
-		lso->seqno_offset = cpu_to_be32(0);
-		lso->len = cpu_to_be32(skb->len);
-
-		/*
-		 * Set up TX Packet CPL pointer, control word and perform
-		 * accounting.
-		 */
-		cpl = (void *)(lso + 1);
-		cntrl = (TXPKT_CSUM_TYPE(v6 ? TX_CSUM_TCPIP6 : TX_CSUM_TCPIP) |
-			 TXPKT_IPHDR_LEN(l3hdr_len) |
-			 TXPKT_ETHHDR_LEN(eth_xtra_len));
-		txq->tso++;
-		txq->tx_cso += ssi->gso_segs;
-	} else {
-		int len;
-
-		len = is_eth_imm(skb) ? skb->len + sizeof(*cpl) : sizeof(*cpl);
-		wr->op_immdlen =
-			cpu_to_be32(FW_WR_OP(FW_ETH_TX_PKT_VM_WR) |
-				    FW_WR_IMMDLEN(len));
-
-		/*
-		 * Set up TX Packet CPL pointer, control word and perform
-		 * accounting.
-		 */
-		cpl = (void *)(wr + 1);
-		if (skb->ip_summed == CHECKSUM_PARTIAL) {
-			cntrl = hwcsum(skb) | TXPKT_IPCSUM_DIS;
-			txq->tx_cso++;
-		} else
-			cntrl = TXPKT_L4CSUM_DIS | TXPKT_IPCSUM_DIS;
-	}
-
-	/*
-	 * If there's a VLAN tag present, add that to the list of things to
-	 * do in this Work Request.
-	 */
-	if (vlan_tx_tag_present(skb)) {
-		txq->vlan_ins++;
-		cntrl |= TXPKT_VLAN_VLD | TXPKT_VLAN(vlan_tx_tag_get(skb));
-	}
-
-	/*
-	 * Fill in the TX Packet CPL message header.
-	 */
-	cpl->ctrl0 = cpu_to_be32(TXPKT_OPCODE(CPL_TX_PKT_XT) |
-				 TXPKT_INTF(pi->port_id) |
-				 TXPKT_PF(0));
-	cpl->pack = cpu_to_be16(0);
-	cpl->len = cpu_to_be16(skb->len);
-	cpl->ctrl1 = cpu_to_be64(cntrl);
-
-#ifdef T4_TRACE
-	T4_TRACE5(adapter->tb[txq->q.cntxt_id & 7],
-		  "eth_xmit: ndesc %u, credits %u, pidx %u, len %u, frags %u",
-		  ndesc, credits, txq->q.pidx, skb->len, ssi->nr_frags);
-#endif
-
-	/*
-	 * Fill in the body of the TX Packet CPL message with either in-lined
-	 * data or a Scatter/Gather List.
-	 */
-	if (is_eth_imm(skb)) {
-		/*
-		 * In-line the packet's data and free the skb since we don't
-		 * need it any longer.
-		 */
-		inline_tx_skb(skb, &txq->q, cpl + 1);
-		dev_kfree_skb(skb);
-	} else {
-		/*
-		 * Write the skb's Scatter/Gather list into the TX Packet CPL
-		 * message and retain a pointer to the skb so we can free it
-		 * later when its DMA completes.  (We store the skb pointer
-		 * in the Software Descriptor corresponding to the last TX
-		 * Descriptor used by the Work Request.)
-		 *
-		 * The retained skb will be freed when the corresponding TX
-		 * Descriptors are reclaimed after their DMAs complete.
-		 * However, this could take quite a while since, in general,
-		 * the hardware is set up to be lazy about sending DMA
-		 * completion notifications to us and we mostly perform TX
-		 * reclaims in the transmit routine.
-		 *
-		 * This is good for performamce but means that we rely on new
-		 * TX packets arriving to run the destructors of completed
-		 * packets, which open up space in their sockets' send queues.
-		 * Sometimes we do not get such new packets causing TX to
-		 * stall.  A single UDP transmitter is a good example of this
-		 * situation.  We have a clean up timer that periodically
-		 * reclaims completed packets but it doesn't run often enough
-		 * (nor do we want it to) to prevent lengthy stalls.  A
-		 * solution to this problem is to run the destructor early,
-		 * after the packet is queued but before it's DMAd.  A con is
-		 * that we lie to socket memory accounting, but the amount of
-		 * extra memory is reasonable (limited by the number of TX
-		 * descriptors), the packets do actually get freed quickly by
-		 * new packets almost always, and for protocols like TCP that
-		 * wait for acks to really free up the data the extra memory
-		 * is even less.  On the positive side we run the destructors
-		 * on the sending CPU rather than on a potentially different
-		 * completing CPU, usually a good thing.
-		 *
-		 * Run the destructor before telling the DMA engine about the
-		 * packet to make sure it doesn't complete and get freed
-		 * prematurely.
-		 */
-		struct ulptx_sgl *sgl = (struct ulptx_sgl *)(cpl + 1);
-		struct sge_txq *tq = &txq->q;
-		int last_desc;
-
-		/*
-		 * If the Work Request header was an exact multiple of our TX
-		 * Descriptor length, then it's possible that the starting SGL
-		 * pointer lines up exactly with the end of our TX Descriptor
-		 * ring.  If that's the case, wrap around to the beginning
-		 * here ...
-		 */
-		if (unlikely((void *)sgl == (void *)tq->stat)) {
-			sgl = (void *)tq->desc;
-			end = (void *)((void *)tq->desc +
-				       ((void *)end - (void *)tq->stat));
-		}
-
-		write_sgl(skb, tq, sgl, end, 0, addr);
-		skb_orphan(skb);
-
-		last_desc = tq->pidx + ndesc - 1;
-		if (last_desc >= tq->size)
-			last_desc -= tq->size;
-		tq->sdesc[last_desc].skb = skb;
-		tq->sdesc[last_desc].sgl = sgl;
-	}
-
-	/*
-	 * Advance our internal TX Queue state, tell the hardware about
-	 * the new TX descriptors and return success.
-	 */
-	txq_advance(&txq->q, ndesc);
-	dev->trans_start = jiffies;
-	ring_tx_db(adapter, &txq->q, ndesc);
-	return NETDEV_TX_OK;
-
-out_free:
-	/*
-	 * An error of some sort happened.  Free the TX skb and tell the
-	 * OS that we've "dealt" with the packet ...
-	 */
-	dev_kfree_skb(skb);
-	return NETDEV_TX_OK;
-}
-
-/**
- *	t4vf_pktgl_to_skb - build an sk_buff from a packet gather list
- *	@gl: the gather list
- *	@skb_len: size of sk_buff main body if it carries fragments
- *	@pull_len: amount of data to move to the sk_buff's main body
- *
- *	Builds an sk_buff from the given packet gather list.  Returns the
- *	sk_buff or %NULL if sk_buff allocation failed.
- */
-struct sk_buff *t4vf_pktgl_to_skb(const struct pkt_gl *gl,
-				  unsigned int skb_len, unsigned int pull_len)
-{
-	struct sk_buff *skb;
-	struct skb_shared_info *ssi;
-
-	/*
-	 * If the ingress packet is small enough, allocate an skb large enough
-	 * for all of the data and copy it inline.  Otherwise, allocate an skb
-	 * with enough room to pull in the header and reference the rest of
-	 * the data via the skb fragment list.
-	 *
-	 * Below we rely on RX_COPY_THRES being less than the smallest Rx
-	 * buff!  size, which is expected since buffers are at least
-	 * PAGE_SIZEd.  In this case packets up to RX_COPY_THRES have only one
-	 * fragment.
-	 */
-	if (gl->tot_len <= RX_COPY_THRES) {
-		/* small packets have only one fragment */
-		skb = alloc_skb(gl->tot_len, GFP_ATOMIC);
-		if (unlikely(!skb))
-			goto out;
-		__skb_put(skb, gl->tot_len);
-		skb_copy_to_linear_data(skb, gl->va, gl->tot_len);
-	} else {
-		skb = alloc_skb(skb_len, GFP_ATOMIC);
-		if (unlikely(!skb))
-			goto out;
-		__skb_put(skb, pull_len);
-		skb_copy_to_linear_data(skb, gl->va, pull_len);
-
-		ssi = skb_shinfo(skb);
-		ssi->frags[0].page = gl->frags[0].page;
-		ssi->frags[0].page_offset = gl->frags[0].page_offset + pull_len;
-		ssi->frags[0].size = gl->frags[0].size - pull_len;
-		if (gl->nfrags > 1)
-			memcpy(&ssi->frags[1], &gl->frags[1],
-			       (gl->nfrags-1) * sizeof(skb_frag_t));
-		ssi->nr_frags = gl->nfrags;
-
-		skb->len = gl->tot_len;
-		skb->data_len = skb->len - pull_len;
-		skb->truesize += skb->data_len;
-
-		/* Get a reference for the last page, we don't own it */
-		get_page(gl->frags[gl->nfrags - 1].page);
-	}
-
-out:
-	return skb;
-}
-
-/**
- *	t4vf_pktgl_free - free a packet gather list
- *	@gl: the gather list
- *
- *	Releases the pages of a packet gather list.  We do not own the last
- *	page on the list and do not free it.
- */
-void t4vf_pktgl_free(const struct pkt_gl *gl)
-{
-	int frag;
-
-	frag = gl->nfrags - 1;
-	while (frag--)
-		put_page(gl->frags[frag].page);
-}
-
-/**
- *	copy_frags - copy fragments from gather list into skb_shared_info
- *	@si: destination skb shared info structure
- *	@gl: source internal packet gather list
- *	@offset: packet start offset in first page
- *
- *	Copy an internal packet gather list into a Linux skb_shared_info
- *	structure.
- */
-static inline void copy_frags(struct skb_shared_info *si,
-			      const struct pkt_gl *gl,
-			      unsigned int offset)
-{
-	unsigned int n;
-
-	/* usually there's just one frag */
-	si->frags[0].page = gl->frags[0].page;
-	si->frags[0].page_offset = gl->frags[0].page_offset + offset;
-	si->frags[0].size = gl->frags[0].size - offset;
-	si->nr_frags = gl->nfrags;
-
-	n = gl->nfrags - 1;
-	if (n)
-		memcpy(&si->frags[1], &gl->frags[1], n * sizeof(skb_frag_t));
-
-	/* get a reference to the last page, we don't own it */
-	get_page(gl->frags[n].page);
-}
-
-/**
- *	do_gro - perform Generic Receive Offload ingress packet processing
- *	@rxq: ingress RX Ethernet Queue
- *	@gl: gather list for ingress packet
- *	@pkt: CPL header for last packet fragment
- *
- *	Perform Generic Receive Offload (GRO) ingress packet processing.
- *	We use the standard Linux GRO interfaces for this.
- */
-static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
-		   const struct cpl_rx_pkt *pkt)
-{
-	int ret;
-	struct sk_buff *skb;
-
-	skb = napi_get_frags(&rxq->rspq.napi);
-	if (unlikely(!skb)) {
-		t4vf_pktgl_free(gl);
-		rxq->stats.rx_drops++;
-		return;
-	}
-
-	copy_frags(skb_shinfo(skb), gl, PKTSHIFT);
-	skb->len = gl->tot_len - PKTSHIFT;
-	skb->data_len = skb->len;
-	skb->truesize += skb->data_len;
-	skb->ip_summed = CHECKSUM_UNNECESSARY;
-	skb_record_rx_queue(skb, rxq->rspq.idx);
-
-	if (pkt->vlan_ex)
-		__vlan_hwaccel_put_tag(skb, be16_to_cpu(pkt->vlan));
-	ret = napi_gro_frags(&rxq->rspq.napi);
-
-	if (ret == GRO_HELD)
-		rxq->stats.lro_pkts++;
-	else if (ret == GRO_MERGED || ret == GRO_MERGED_FREE)
-		rxq->stats.lro_merged++;
-	rxq->stats.pkts++;
-	rxq->stats.rx_cso++;
-}
-
-/**
- *	t4vf_ethrx_handler - process an ingress ethernet packet
- *	@rspq: the response queue that received the packet
- *	@rsp: the response queue descriptor holding the RX_PKT message
- *	@gl: the gather list of packet fragments
- *
- *	Process an ingress ethernet packet and deliver it to the stack.
- */
-int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
-		       const struct pkt_gl *gl)
-{
-	struct sk_buff *skb;
-	const struct cpl_rx_pkt *pkt = (void *)&rsp[1];
-	bool csum_ok = pkt->csum_calc && !pkt->err_vec;
-	struct sge_eth_rxq *rxq = container_of(rspq, struct sge_eth_rxq, rspq);
-
-	/*
-	 * If this is a good TCP packet and we have Generic Receive Offload
-	 * enabled, handle the packet in the GRO path.
-	 */
-	if ((pkt->l2info & cpu_to_be32(RXF_TCP)) &&
-	    (rspq->netdev->features & NETIF_F_GRO) && csum_ok &&
-	    !pkt->ip_frag) {
-		do_gro(rxq, gl, pkt);
-		return 0;
-	}
-
-	/*
-	 * Convert the Packet Gather List into an skb.
-	 */
-	skb = t4vf_pktgl_to_skb(gl, RX_SKB_LEN, RX_PULL_LEN);
-	if (unlikely(!skb)) {
-		t4vf_pktgl_free(gl);
-		rxq->stats.rx_drops++;
-		return 0;
-	}
-	__skb_pull(skb, PKTSHIFT);
-	skb->protocol = eth_type_trans(skb, rspq->netdev);
-	skb_record_rx_queue(skb, rspq->idx);
-	rxq->stats.pkts++;
-
-	if (csum_ok && (rspq->netdev->features & NETIF_F_RXCSUM) &&
-	    !pkt->err_vec && (be32_to_cpu(pkt->l2info) & (RXF_UDP|RXF_TCP))) {
-		if (!pkt->ip_frag)
-			skb->ip_summed = CHECKSUM_UNNECESSARY;
-		else {
-			__sum16 c = (__force __sum16)pkt->csum;
-			skb->csum = csum_unfold(c);
-			skb->ip_summed = CHECKSUM_COMPLETE;
-		}
-		rxq->stats.rx_cso++;
-	} else
-		skb_checksum_none_assert(skb);
-
-	if (pkt->vlan_ex) {
-		rxq->stats.vlan_ex++;
-		__vlan_hwaccel_put_tag(skb, be16_to_cpu(pkt->vlan));
-	}
-
-	netif_receive_skb(skb);
-
-	return 0;
-}
-
-/**
- *	is_new_response - check if a response is newly written
- *	@rc: the response control descriptor
- *	@rspq: the response queue
- *
- *	Returns true if a response descriptor contains a yet unprocessed
- *	response.
- */
-static inline bool is_new_response(const struct rsp_ctrl *rc,
-				   const struct sge_rspq *rspq)
-{
-	return RSPD_GEN(rc->type_gen) == rspq->gen;
-}
-
-/**
- *	restore_rx_bufs - put back a packet's RX buffers
- *	@gl: the packet gather list
- *	@fl: the SGE Free List
- *	@nfrags: how many fragments in @si
- *
- *	Called when we find out that the current packet, @si, can't be
- *	processed right away for some reason.  This is a very rare event and
- *	there's no effort to make this suspension/resumption process
- *	particularly efficient.
- *
- *	We implement the suspension by putting all of the RX buffers associated
- *	with the current packet back on the original Free List.  The buffers
- *	have already been unmapped and are left unmapped, we mark them as
- *	unmapped in order to prevent further unmapping attempts.  (Effectively
- *	this function undoes the series of @unmap_rx_buf calls which were done
- *	to create the current packet's gather list.)  This leaves us ready to
- *	restart processing of the packet the next time we start processing the
- *	RX Queue ...
- */
-static void restore_rx_bufs(const struct pkt_gl *gl, struct sge_fl *fl,
-			    int frags)
-{
-	struct rx_sw_desc *sdesc;
-
-	while (frags--) {
-		if (fl->cidx == 0)
-			fl->cidx = fl->size - 1;
-		else
-			fl->cidx--;
-		sdesc = &fl->sdesc[fl->cidx];
-		sdesc->page = gl->frags[frags].page;
-		sdesc->dma_addr |= RX_UNMAPPED_BUF;
-		fl->avail++;
-	}
-}
-
-/**
- *	rspq_next - advance to the next entry in a response queue
- *	@rspq: the queue
- *
- *	Updates the state of a response queue to advance it to the next entry.
- */
-static inline void rspq_next(struct sge_rspq *rspq)
-{
-	rspq->cur_desc = (void *)rspq->cur_desc + rspq->iqe_len;
-	if (unlikely(++rspq->cidx == rspq->size)) {
-		rspq->cidx = 0;
-		rspq->gen ^= 1;
-		rspq->cur_desc = rspq->desc;
-	}
-}
-
-/**
- *	process_responses - process responses from an SGE response queue
- *	@rspq: the ingress response queue to process
- *	@budget: how many responses can be processed in this round
- *
- *	Process responses from a Scatter Gather Engine response queue up to
- *	the supplied budget.  Responses include received packets as well as
- *	control messages from firmware or hardware.
- *
- *	Additionally choose the interrupt holdoff time for the next interrupt
- *	on this queue.  If the system is under memory shortage use a fairly
- *	long delay to help recovery.
- */
-int process_responses(struct sge_rspq *rspq, int budget)
-{
-	struct sge_eth_rxq *rxq = container_of(rspq, struct sge_eth_rxq, rspq);
-	int budget_left = budget;
-
-	while (likely(budget_left)) {
-		int ret, rsp_type;
-		const struct rsp_ctrl *rc;
-
-		rc = (void *)rspq->cur_desc + (rspq->iqe_len - sizeof(*rc));
-		if (!is_new_response(rc, rspq))
-			break;
-
-		/*
-		 * Figure out what kind of response we've received from the
-		 * SGE.
-		 */
-		rmb();
-		rsp_type = RSPD_TYPE(rc->type_gen);
-		if (likely(rsp_type == RSP_TYPE_FLBUF)) {
-			skb_frag_t *fp;
-			struct pkt_gl gl;
-			const struct rx_sw_desc *sdesc;
-			u32 bufsz, frag;
-			u32 len = be32_to_cpu(rc->pldbuflen_qid);
-
-			/*
-			 * If we get a "new buffer" message from the SGE we
-			 * need to move on to the next Free List buffer.
-			 */
-			if (len & RSPD_NEWBUF) {
-				/*
-				 * We get one "new buffer" message when we
-				 * first start up a queue so we need to ignore
-				 * it when our offset into the buffer is 0.
-				 */
-				if (likely(rspq->offset > 0)) {
-					free_rx_bufs(rspq->adapter, &rxq->fl,
-						     1);
-					rspq->offset = 0;
-				}
-				len = RSPD_LEN(len);
-			}
-			gl.tot_len = len;
-
-			/*
-			 * Gather packet fragments.
-			 */
-			for (frag = 0, fp = gl.frags; /**/; frag++, fp++) {
-				BUG_ON(frag >= MAX_SKB_FRAGS);
-				BUG_ON(rxq->fl.avail == 0);
-				sdesc = &rxq->fl.sdesc[rxq->fl.cidx];
-				bufsz = get_buf_size(sdesc);
-				fp->page = sdesc->page;
-				fp->page_offset = rspq->offset;
-				fp->size = min(bufsz, len);
-				len -= fp->size;
-				if (!len)
-					break;
-				unmap_rx_buf(rspq->adapter, &rxq->fl);
-			}
-			gl.nfrags = frag+1;
-
-			/*
-			 * Last buffer remains mapped so explicitly make it
-			 * coherent for CPU access and start preloading first
-			 * cache line ...
-			 */
-			dma_sync_single_for_cpu(rspq->adapter->pdev_dev,
-						get_buf_addr(sdesc),
-						fp->size, DMA_FROM_DEVICE);
-			gl.va = (page_address(gl.frags[0].page) +
-				 gl.frags[0].page_offset);
-			prefetch(gl.va);
-
-			/*
-			 * Hand the new ingress packet to the handler for
-			 * this Response Queue.
-			 */
-			ret = rspq->handler(rspq, rspq->cur_desc, &gl);
-			if (likely(ret == 0))
-				rspq->offset += ALIGN(fp->size, FL_ALIGN);
-			else
-				restore_rx_bufs(&gl, &rxq->fl, frag);
-		} else if (likely(rsp_type == RSP_TYPE_CPL)) {
-			ret = rspq->handler(rspq, rspq->cur_desc, NULL);
-		} else {
-			WARN_ON(rsp_type > RSP_TYPE_CPL);
-			ret = 0;
-		}
-
-		if (unlikely(ret)) {
-			/*
-			 * Couldn't process descriptor, back off for recovery.
-			 * We use the SGE's last timer which has the longest
-			 * interrupt coalescing value ...
-			 */
-			const int NOMEM_TIMER_IDX = SGE_NTIMERS-1;
-			rspq->next_intr_params =
-				QINTR_TIMER_IDX(NOMEM_TIMER_IDX);
-			break;
-		}
-
-		rspq_next(rspq);
-		budget_left--;
-	}
-
-	/*
-	 * If this is a Response Queue with an associated Free List and
-	 * at least two Egress Queue units available in the Free List
-	 * for new buffer pointers, refill the Free List.
-	 */
-	if (rspq->offset >= 0 &&
-	    rxq->fl.size - rxq->fl.avail >= 2*FL_PER_EQ_UNIT)
-		__refill_fl(rspq->adapter, &rxq->fl);
-	return budget - budget_left;
-}
-
-/**
- *	napi_rx_handler - the NAPI handler for RX processing
- *	@napi: the napi instance
- *	@budget: how many packets we can process in this round
- *
- *	Handler for new data events when using NAPI.  This does not need any
- *	locking or protection from interrupts as data interrupts are off at
- *	this point and other adapter interrupts do not interfere (the latter
- *	in not a concern at all with MSI-X as non-data interrupts then have
- *	a separate handler).
- */
-static int napi_rx_handler(struct napi_struct *napi, int budget)
-{
-	unsigned int intr_params;
-	struct sge_rspq *rspq = container_of(napi, struct sge_rspq, napi);
-	int work_done = process_responses(rspq, budget);
-
-	if (likely(work_done < budget)) {
-		napi_complete(napi);
-		intr_params = rspq->next_intr_params;
-		rspq->next_intr_params = rspq->intr_params;
-	} else
-		intr_params = QINTR_TIMER_IDX(SGE_TIMER_UPD_CIDX);
-
-	if (unlikely(work_done == 0))
-		rspq->unhandled_irqs++;
-
-	t4_write_reg(rspq->adapter,
-		     T4VF_SGE_BASE_ADDR + SGE_VF_GTS,
-		     CIDXINC(work_done) |
-		     INGRESSQID((u32)rspq->cntxt_id) |
-		     SEINTARM(intr_params));
-	return work_done;
-}
-
-/*
- * The MSI-X interrupt handler for an SGE response queue for the NAPI case
- * (i.e., response queue serviced by NAPI polling).
- */
-irqreturn_t t4vf_sge_intr_msix(int irq, void *cookie)
-{
-	struct sge_rspq *rspq = cookie;
-
-	napi_schedule(&rspq->napi);
-	return IRQ_HANDLED;
-}
-
-/*
- * Process the indirect interrupt entries in the interrupt queue and kick off
- * NAPI for each queue that has generated an entry.
- */
-static unsigned int process_intrq(struct adapter *adapter)
-{
-	struct sge *s = &adapter->sge;
-	struct sge_rspq *intrq = &s->intrq;
-	unsigned int work_done;
-
-	spin_lock(&adapter->sge.intrq_lock);
-	for (work_done = 0; ; work_done++) {
-		const struct rsp_ctrl *rc;
-		unsigned int qid, iq_idx;
-		struct sge_rspq *rspq;
-
-		/*
-		 * Grab the next response from the interrupt queue and bail
-		 * out if it's not a new response.
-		 */
-		rc = (void *)intrq->cur_desc + (intrq->iqe_len - sizeof(*rc));
-		if (!is_new_response(rc, intrq))
-			break;
-
-		/*
-		 * If the response isn't a forwarded interrupt message issue a
-		 * error and go on to the next response message.  This should
-		 * never happen ...
-		 */
-		rmb();
-		if (unlikely(RSPD_TYPE(rc->type_gen) != RSP_TYPE_INTR)) {
-			dev_err(adapter->pdev_dev,
-				"Unexpected INTRQ response type %d\n",
-				RSPD_TYPE(rc->type_gen));
-			continue;
-		}
-
-		/*
-		 * Extract the Queue ID from the interrupt message and perform
-		 * sanity checking to make sure it really refers to one of our
-		 * Ingress Queues which is active and matches the queue's ID.
-		 * None of these error conditions should ever happen so we may
-		 * want to either make them fatal and/or conditionalized under
-		 * DEBUG.
-		 */
-		qid = RSPD_QID(be32_to_cpu(rc->pldbuflen_qid));
-		iq_idx = IQ_IDX(s, qid);
-		if (unlikely(iq_idx >= MAX_INGQ)) {
-			dev_err(adapter->pdev_dev,
-				"Ingress QID %d out of range\n", qid);
-			continue;
-		}
-		rspq = s->ingr_map[iq_idx];
-		if (unlikely(rspq == NULL)) {
-			dev_err(adapter->pdev_dev,
-				"Ingress QID %d RSPQ=NULL\n", qid);
-			continue;
-		}
-		if (unlikely(rspq->abs_id != qid)) {
-			dev_err(adapter->pdev_dev,
-				"Ingress QID %d refers to RSPQ %d\n",
-				qid, rspq->abs_id);
-			continue;
-		}
-
-		/*
-		 * Schedule NAPI processing on the indicated Response Queue
-		 * and move on to the next entry in the Forwarded Interrupt
-		 * Queue.
-		 */
-		napi_schedule(&rspq->napi);
-		rspq_next(intrq);
-	}
-
-	t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_GTS,
-		     CIDXINC(work_done) |
-		     INGRESSQID(intrq->cntxt_id) |
-		     SEINTARM(intrq->intr_params));
-
-	spin_unlock(&adapter->sge.intrq_lock);
-
-	return work_done;
-}
-
-/*
- * The MSI interrupt handler handles data events from SGE response queues as
- * well as error and other async events as they all use the same MSI vector.
- */
-irqreturn_t t4vf_intr_msi(int irq, void *cookie)
-{
-	struct adapter *adapter = cookie;
-
-	process_intrq(adapter);
-	return IRQ_HANDLED;
-}
-
-/**
- *	t4vf_intr_handler - select the top-level interrupt handler
- *	@adapter: the adapter
- *
- *	Selects the top-level interrupt handler based on the type of interrupts
- *	(MSI-X or MSI).
- */
-irq_handler_t t4vf_intr_handler(struct adapter *adapter)
-{
-	BUG_ON((adapter->flags & (USING_MSIX|USING_MSI)) == 0);
-	if (adapter->flags & USING_MSIX)
-		return t4vf_sge_intr_msix;
-	else
-		return t4vf_intr_msi;
-}
-
-/**
- *	sge_rx_timer_cb - perform periodic maintenance of SGE RX queues
- *	@data: the adapter
- *
- *	Runs periodically from a timer to perform maintenance of SGE RX queues.
- *
- *	a) Replenishes RX queues that have run out due to memory shortage.
- *	Normally new RX buffers are added when existing ones are consumed but
- *	when out of memory a queue can become empty.  We schedule NAPI to do
- *	the actual refill.
- */
-static void sge_rx_timer_cb(unsigned long data)
-{
-	struct adapter *adapter = (struct adapter *)data;
-	struct sge *s = &adapter->sge;
-	unsigned int i;
-
-	/*
-	 * Scan the "Starving Free Lists" flag array looking for any Free
-	 * Lists in need of more free buffers.  If we find one and it's not
-	 * being actively polled, then bump its "starving" counter and attempt
-	 * to refill it.  If we're successful in adding enough buffers to push
-	 * the Free List over the starving threshold, then we can clear its
-	 * "starving" status.
-	 */
-	for (i = 0; i < ARRAY_SIZE(s->starving_fl); i++) {
-		unsigned long m;
-
-		for (m = s->starving_fl[i]; m; m &= m - 1) {
-			unsigned int id = __ffs(m) + i * BITS_PER_LONG;
-			struct sge_fl *fl = s->egr_map[id];
-
-			clear_bit(id, s->starving_fl);
-			smp_mb__after_clear_bit();
-
-			/*
-			 * Since we are accessing fl without a lock there's a
-			 * small probability of a false positive where we
-			 * schedule napi but the FL is no longer starving.
-			 * No biggie.
-			 */
-			if (fl_starving(fl)) {
-				struct sge_eth_rxq *rxq;
-
-				rxq = container_of(fl, struct sge_eth_rxq, fl);
-				if (napi_reschedule(&rxq->rspq.napi))
-					fl->starving++;
-				else
-					set_bit(id, s->starving_fl);
-			}
-		}
-	}
-
-	/*
-	 * Reschedule the next scan for starving Free Lists ...
-	 */
-	mod_timer(&s->rx_timer, jiffies + RX_QCHECK_PERIOD);
-}
-
-/**
- *	sge_tx_timer_cb - perform periodic maintenance of SGE Tx queues
- *	@data: the adapter
- *
- *	Runs periodically from a timer to perform maintenance of SGE TX queues.
- *
- *	b) Reclaims completed Tx packets for the Ethernet queues.  Normally
- *	packets are cleaned up by new Tx packets, this timer cleans up packets
- *	when no new packets are being submitted.  This is essential for pktgen,
- *	at least.
- */
-static void sge_tx_timer_cb(unsigned long data)
-{
-	struct adapter *adapter = (struct adapter *)data;
-	struct sge *s = &adapter->sge;
-	unsigned int i, budget;
-
-	budget = MAX_TIMER_TX_RECLAIM;
-	i = s->ethtxq_rover;
-	do {
-		struct sge_eth_txq *txq = &s->ethtxq[i];
-
-		if (reclaimable(&txq->q) && __netif_tx_trylock(txq->txq)) {
-			int avail = reclaimable(&txq->q);
-
-			if (avail > budget)
-				avail = budget;
-
-			free_tx_desc(adapter, &txq->q, avail, true);
-			txq->q.in_use -= avail;
-			__netif_tx_unlock(txq->txq);
-
-			budget -= avail;
-			if (!budget)
-				break;
-		}
-
-		i++;
-		if (i >= s->ethqsets)
-			i = 0;
-	} while (i != s->ethtxq_rover);
-	s->ethtxq_rover = i;
-
-	/*
-	 * If we found too many reclaimable packets schedule a timer in the
-	 * near future to continue where we left off.  Otherwise the next timer
-	 * will be at its normal interval.
-	 */
-	mod_timer(&s->tx_timer, jiffies + (budget ? TX_QCHECK_PERIOD : 2));
-}
-
-/**
- *	t4vf_sge_alloc_rxq - allocate an SGE RX Queue
- *	@adapter: the adapter
- *	@rspq: pointer to to the new rxq's Response Queue to be filled in
- *	@iqasynch: if 0, a normal rspq; if 1, an asynchronous event queue
- *	@dev: the network device associated with the new rspq
- *	@intr_dest: MSI-X vector index (overriden in MSI mode)
- *	@fl: pointer to the new rxq's Free List to be filled in
- *	@hnd: the interrupt handler to invoke for the rspq
- */
-int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq,
-		       bool iqasynch, struct net_device *dev,
-		       int intr_dest,
-		       struct sge_fl *fl, rspq_handler_t hnd)
-{
-	struct port_info *pi = netdev_priv(dev);
-	struct fw_iq_cmd cmd, rpl;
-	int ret, iqandst, flsz = 0;
-
-	/*
-	 * If we're using MSI interrupts and we're not initializing the
-	 * Forwarded Interrupt Queue itself, then set up this queue for
-	 * indirect interrupts to the Forwarded Interrupt Queue.  Obviously
-	 * the Forwarded Interrupt Queue must be set up before any other
-	 * ingress queue ...
-	 */
-	if ((adapter->flags & USING_MSI) && rspq != &adapter->sge.intrq) {
-		iqandst = SGE_INTRDST_IQ;
-		intr_dest = adapter->sge.intrq.abs_id;
-	} else
-		iqandst = SGE_INTRDST_PCI;
-
-	/*
-	 * Allocate the hardware ring for the Response Queue.  The size needs
-	 * to be a multiple of 16 which includes the mandatory status entry
-	 * (regardless of whether the Status Page capabilities are enabled or
-	 * not).
-	 */
-	rspq->size = roundup(rspq->size, 16);
-	rspq->desc = alloc_ring(adapter->pdev_dev, rspq->size, rspq->iqe_len,
-				0, &rspq->phys_addr, NULL, 0);
-	if (!rspq->desc)
-		return -ENOMEM;
-
-	/*
-	 * Fill in the Ingress Queue Command.  Note: Ideally this code would
-	 * be in t4vf_hw.c but there are so many parameters and dependencies
-	 * on our Linux SGE state that we would end up having to pass tons of
-	 * parameters.  We'll have to think about how this might be migrated
-	 * into OS-independent common code ...
-	 */
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_IQ_CMD) |
-				    FW_CMD_REQUEST |
-				    FW_CMD_WRITE |
-				    FW_CMD_EXEC);
-	cmd.alloc_to_len16 = cpu_to_be32(FW_IQ_CMD_ALLOC |
-					 FW_IQ_CMD_IQSTART(1) |
-					 FW_LEN16(cmd));
-	cmd.type_to_iqandstindex =
-		cpu_to_be32(FW_IQ_CMD_TYPE(FW_IQ_TYPE_FL_INT_CAP) |
-			    FW_IQ_CMD_IQASYNCH(iqasynch) |
-			    FW_IQ_CMD_VIID(pi->viid) |
-			    FW_IQ_CMD_IQANDST(iqandst) |
-			    FW_IQ_CMD_IQANUS(1) |
-			    FW_IQ_CMD_IQANUD(SGE_UPDATEDEL_INTR) |
-			    FW_IQ_CMD_IQANDSTINDEX(intr_dest));
-	cmd.iqdroprss_to_iqesize =
-		cpu_to_be16(FW_IQ_CMD_IQPCIECH(pi->port_id) |
-			    FW_IQ_CMD_IQGTSMODE |
-			    FW_IQ_CMD_IQINTCNTTHRESH(rspq->pktcnt_idx) |
-			    FW_IQ_CMD_IQESIZE(ilog2(rspq->iqe_len) - 4));
-	cmd.iqsize = cpu_to_be16(rspq->size);
-	cmd.iqaddr = cpu_to_be64(rspq->phys_addr);
-
-	if (fl) {
-		/*
-		 * Allocate the ring for the hardware free list (with space
-		 * for its status page) along with the associated software
-		 * descriptor ring.  The free list size needs to be a multiple
-		 * of the Egress Queue Unit.
-		 */
-		fl->size = roundup(fl->size, FL_PER_EQ_UNIT);
-		fl->desc = alloc_ring(adapter->pdev_dev, fl->size,
-				      sizeof(__be64), sizeof(struct rx_sw_desc),
-				      &fl->addr, &fl->sdesc, STAT_LEN);
-		if (!fl->desc) {
-			ret = -ENOMEM;
-			goto err;
-		}
-
-		/*
-		 * Calculate the size of the hardware free list ring plus
-		 * Status Page (which the SGE will place after the end of the
-		 * free list ring) in Egress Queue Units.
-		 */
-		flsz = (fl->size / FL_PER_EQ_UNIT +
-			STAT_LEN / EQ_UNIT);
-
-		/*
-		 * Fill in all the relevant firmware Ingress Queue Command
-		 * fields for the free list.
-		 */
-		cmd.iqns_to_fl0congen =
-			cpu_to_be32(
-				FW_IQ_CMD_FL0HOSTFCMODE(SGE_HOSTFCMODE_NONE) |
-				FW_IQ_CMD_FL0PACKEN |
-				FW_IQ_CMD_FL0PADEN);
-		cmd.fl0dcaen_to_fl0cidxfthresh =
-			cpu_to_be16(
-				FW_IQ_CMD_FL0FBMIN(SGE_FETCHBURSTMIN_64B) |
-				FW_IQ_CMD_FL0FBMAX(SGE_FETCHBURSTMAX_512B));
-		cmd.fl0size = cpu_to_be16(flsz);
-		cmd.fl0addr = cpu_to_be64(fl->addr);
-	}
-
-	/*
-	 * Issue the firmware Ingress Queue Command and extract the results if
-	 * it completes successfully.
-	 */
-	ret = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl);
-	if (ret)
-		goto err;
-
-	netif_napi_add(dev, &rspq->napi, napi_rx_handler, 64);
-	rspq->cur_desc = rspq->desc;
-	rspq->cidx = 0;
-	rspq->gen = 1;
-	rspq->next_intr_params = rspq->intr_params;
-	rspq->cntxt_id = be16_to_cpu(rpl.iqid);
-	rspq->abs_id = be16_to_cpu(rpl.physiqid);
-	rspq->size--;			/* subtract status entry */
-	rspq->adapter = adapter;
-	rspq->netdev = dev;
-	rspq->handler = hnd;
-
-	/* set offset to -1 to distinguish ingress queues without FL */
-	rspq->offset = fl ? 0 : -1;
-
-	if (fl) {
-		fl->cntxt_id = be16_to_cpu(rpl.fl0id);
-		fl->avail = 0;
-		fl->pend_cred = 0;
-		fl->pidx = 0;
-		fl->cidx = 0;
-		fl->alloc_failed = 0;
-		fl->large_alloc_failed = 0;
-		fl->starving = 0;
-		refill_fl(adapter, fl, fl_cap(fl), GFP_KERNEL);
-	}
-
-	return 0;
-
-err:
-	/*
-	 * An error occurred.  Clean up our partial allocation state and
-	 * return the error.
-	 */
-	if (rspq->desc) {
-		dma_free_coherent(adapter->pdev_dev, rspq->size * rspq->iqe_len,
-				  rspq->desc, rspq->phys_addr);
-		rspq->desc = NULL;
-	}
-	if (fl && fl->desc) {
-		kfree(fl->sdesc);
-		fl->sdesc = NULL;
-		dma_free_coherent(adapter->pdev_dev, flsz * EQ_UNIT,
-				  fl->desc, fl->addr);
-		fl->desc = NULL;
-	}
-	return ret;
-}
-
-/**
- *	t4vf_sge_alloc_eth_txq - allocate an SGE Ethernet TX Queue
- *	@adapter: the adapter
- *	@txq: pointer to the new txq to be filled in
- *	@devq: the network TX queue associated with the new txq
- *	@iqid: the relative ingress queue ID to which events relating to
- *		the new txq should be directed
- */
-int t4vf_sge_alloc_eth_txq(struct adapter *adapter, struct sge_eth_txq *txq,
-			   struct net_device *dev, struct netdev_queue *devq,
-			   unsigned int iqid)
-{
-	int ret, nentries;
-	struct fw_eq_eth_cmd cmd, rpl;
-	struct port_info *pi = netdev_priv(dev);
-
-	/*
-	 * Calculate the size of the hardware TX Queue (including the Status
-	 * Page on the end of the TX Queue) in units of TX Descriptors.
-	 */
-	nentries = txq->q.size + STAT_LEN / sizeof(struct tx_desc);
-
-	/*
-	 * Allocate the hardware ring for the TX ring (with space for its
-	 * status page) along with the associated software descriptor ring.
-	 */
-	txq->q.desc = alloc_ring(adapter->pdev_dev, txq->q.size,
-				 sizeof(struct tx_desc),
-				 sizeof(struct tx_sw_desc),
-				 &txq->q.phys_addr, &txq->q.sdesc, STAT_LEN);
-	if (!txq->q.desc)
-		return -ENOMEM;
-
-	/*
-	 * Fill in the Egress Queue Command.  Note: As with the direct use of
-	 * the firmware Ingress Queue COmmand above in our RXQ allocation
-	 * routine, ideally, this code would be in t4vf_hw.c.  Again, we'll
-	 * have to see if there's some reasonable way to parameterize it
-	 * into the common code ...
-	 */
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_EQ_ETH_CMD) |
-				    FW_CMD_REQUEST |
-				    FW_CMD_WRITE |
-				    FW_CMD_EXEC);
-	cmd.alloc_to_len16 = cpu_to_be32(FW_EQ_ETH_CMD_ALLOC |
-					 FW_EQ_ETH_CMD_EQSTART |
-					 FW_LEN16(cmd));
-	cmd.viid_pkd = cpu_to_be32(FW_EQ_ETH_CMD_VIID(pi->viid));
-	cmd.fetchszm_to_iqid =
-		cpu_to_be32(FW_EQ_ETH_CMD_HOSTFCMODE(SGE_HOSTFCMODE_STPG) |
-			    FW_EQ_ETH_CMD_PCIECHN(pi->port_id) |
-			    FW_EQ_ETH_CMD_IQID(iqid));
-	cmd.dcaen_to_eqsize =
-		cpu_to_be32(FW_EQ_ETH_CMD_FBMIN(SGE_FETCHBURSTMIN_64B) |
-			    FW_EQ_ETH_CMD_FBMAX(SGE_FETCHBURSTMAX_512B) |
-			    FW_EQ_ETH_CMD_CIDXFTHRESH(SGE_CIDXFLUSHTHRESH_32) |
-			    FW_EQ_ETH_CMD_EQSIZE(nentries));
-	cmd.eqaddr = cpu_to_be64(txq->q.phys_addr);
-
-	/*
-	 * Issue the firmware Egress Queue Command and extract the results if
-	 * it completes successfully.
-	 */
-	ret = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl);
-	if (ret) {
-		/*
-		 * The girmware Ingress Queue Command failed for some reason.
-		 * Free up our partial allocation state and return the error.
-		 */
-		kfree(txq->q.sdesc);
-		txq->q.sdesc = NULL;
-		dma_free_coherent(adapter->pdev_dev,
-				  nentries * sizeof(struct tx_desc),
-				  txq->q.desc, txq->q.phys_addr);
-		txq->q.desc = NULL;
-		return ret;
-	}
-
-	txq->q.in_use = 0;
-	txq->q.cidx = 0;
-	txq->q.pidx = 0;
-	txq->q.stat = (void *)&txq->q.desc[txq->q.size];
-	txq->q.cntxt_id = FW_EQ_ETH_CMD_EQID_GET(be32_to_cpu(rpl.eqid_pkd));
-	txq->q.abs_id =
-		FW_EQ_ETH_CMD_PHYSEQID_GET(be32_to_cpu(rpl.physeqid_pkd));
-	txq->txq = devq;
-	txq->tso = 0;
-	txq->tx_cso = 0;
-	txq->vlan_ins = 0;
-	txq->q.stops = 0;
-	txq->q.restarts = 0;
-	txq->mapping_err = 0;
-	return 0;
-}
-
-/*
- * Free the DMA map resources associated with a TX queue.
- */
-static void free_txq(struct adapter *adapter, struct sge_txq *tq)
-{
-	dma_free_coherent(adapter->pdev_dev,
-			  tq->size * sizeof(*tq->desc) + STAT_LEN,
-			  tq->desc, tq->phys_addr);
-	tq->cntxt_id = 0;
-	tq->sdesc = NULL;
-	tq->desc = NULL;
-}
-
-/*
- * Free the resources associated with a response queue (possibly including a
- * free list).
- */
-static void free_rspq_fl(struct adapter *adapter, struct sge_rspq *rspq,
-			 struct sge_fl *fl)
-{
-	unsigned int flid = fl ? fl->cntxt_id : 0xffff;
-
-	t4vf_iq_free(adapter, FW_IQ_TYPE_FL_INT_CAP,
-		     rspq->cntxt_id, flid, 0xffff);
-	dma_free_coherent(adapter->pdev_dev, (rspq->size + 1) * rspq->iqe_len,
-			  rspq->desc, rspq->phys_addr);
-	netif_napi_del(&rspq->napi);
-	rspq->netdev = NULL;
-	rspq->cntxt_id = 0;
-	rspq->abs_id = 0;
-	rspq->desc = NULL;
-
-	if (fl) {
-		free_rx_bufs(adapter, fl, fl->avail);
-		dma_free_coherent(adapter->pdev_dev,
-				  fl->size * sizeof(*fl->desc) + STAT_LEN,
-				  fl->desc, fl->addr);
-		kfree(fl->sdesc);
-		fl->sdesc = NULL;
-		fl->cntxt_id = 0;
-		fl->desc = NULL;
-	}
-}
-
-/**
- *	t4vf_free_sge_resources - free SGE resources
- *	@adapter: the adapter
- *
- *	Frees resources used by the SGE queue sets.
- */
-void t4vf_free_sge_resources(struct adapter *adapter)
-{
-	struct sge *s = &adapter->sge;
-	struct sge_eth_rxq *rxq = s->ethrxq;
-	struct sge_eth_txq *txq = s->ethtxq;
-	struct sge_rspq *evtq = &s->fw_evtq;
-	struct sge_rspq *intrq = &s->intrq;
-	int qs;
-
-	for (qs = 0; qs < adapter->sge.ethqsets; qs++, rxq++, txq++) {
-		if (rxq->rspq.desc)
-			free_rspq_fl(adapter, &rxq->rspq, &rxq->fl);
-		if (txq->q.desc) {
-			t4vf_eth_eq_free(adapter, txq->q.cntxt_id);
-			free_tx_desc(adapter, &txq->q, txq->q.in_use, true);
-			kfree(txq->q.sdesc);
-			free_txq(adapter, &txq->q);
-		}
-	}
-	if (evtq->desc)
-		free_rspq_fl(adapter, evtq, NULL);
-	if (intrq->desc)
-		free_rspq_fl(adapter, intrq, NULL);
-}
-
-/**
- *	t4vf_sge_start - enable SGE operation
- *	@adapter: the adapter
- *
- *	Start tasklets and timers associated with the DMA engine.
- */
-void t4vf_sge_start(struct adapter *adapter)
-{
-	adapter->sge.ethtxq_rover = 0;
-	mod_timer(&adapter->sge.rx_timer, jiffies + RX_QCHECK_PERIOD);
-	mod_timer(&adapter->sge.tx_timer, jiffies + TX_QCHECK_PERIOD);
-}
-
-/**
- *	t4vf_sge_stop - disable SGE operation
- *	@adapter: the adapter
- *
- *	Stop tasklets and timers associated with the DMA engine.  Note that
- *	this is effective only if measures have been taken to disable any HW
- *	events that may restart them.
- */
-void t4vf_sge_stop(struct adapter *adapter)
-{
-	struct sge *s = &adapter->sge;
-
-	if (s->rx_timer.function)
-		del_timer_sync(&s->rx_timer);
-	if (s->tx_timer.function)
-		del_timer_sync(&s->tx_timer);
-}
-
-/**
- *	t4vf_sge_init - initialize SGE
- *	@adapter: the adapter
- *
- *	Performs SGE initialization needed every time after a chip reset.
- *	We do not initialize any of the queue sets here, instead the driver
- *	top-level must request those individually.  We also do not enable DMA
- *	here, that should be done after the queues have been set up.
- */
-int t4vf_sge_init(struct adapter *adapter)
-{
-	struct sge_params *sge_params = &adapter->params.sge;
-	u32 fl0 = sge_params->sge_fl_buffer_size[0];
-	u32 fl1 = sge_params->sge_fl_buffer_size[1];
-	struct sge *s = &adapter->sge;
-
-	/*
-	 * Start by vetting the basic SGE parameters which have been set up by
-	 * the Physical Function Driver.  Ideally we should be able to deal
-	 * with _any_ configuration.  Practice is different ...
-	 */
-	if (fl0 != PAGE_SIZE || (fl1 != 0 && fl1 <= fl0)) {
-		dev_err(adapter->pdev_dev, "bad SGE FL buffer sizes [%d, %d]\n",
-			fl0, fl1);
-		return -EINVAL;
-	}
-	if ((sge_params->sge_control & RXPKTCPLMODE) == 0) {
-		dev_err(adapter->pdev_dev, "bad SGE CPL MODE\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * Now translate the adapter parameters into our internal forms.
-	 */
-	if (fl1)
-		FL_PG_ORDER = ilog2(fl1) - PAGE_SHIFT;
-	STAT_LEN = ((sge_params->sge_control & EGRSTATUSPAGESIZE) ? 128 : 64);
-	PKTSHIFT = PKTSHIFT_GET(sge_params->sge_control);
-	FL_ALIGN = 1 << (INGPADBOUNDARY_GET(sge_params->sge_control) +
-			 SGE_INGPADBOUNDARY_SHIFT);
-
-	/*
-	 * Set up tasklet timers.
-	 */
-	setup_timer(&s->rx_timer, sge_rx_timer_cb, (unsigned long)adapter);
-	setup_timer(&s->tx_timer, sge_tx_timer_cb, (unsigned long)adapter);
-
-	/*
-	 * Initialize Forwarded Interrupt Queue lock.
-	 */
-	spin_lock_init(&s->intrq_lock);
-
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4vf/t4vf_common.h linux-libre-3.2-gnu/drivers/net/cxgb4vf/t4vf_common.h
--- linux-libre-3.1-gnu/drivers/net/cxgb4vf/t4vf_common.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4vf/t4vf_common.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,274 +0,0 @@
-/*
- * This file is part of the Chelsio T4 PCI-E SR-IOV Virtual Function Ethernet
- * driver for Linux.
- *
- * Copyright (c) 2009-2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __T4VF_COMMON_H__
-#define __T4VF_COMMON_H__
-
-#include "../cxgb4/t4fw_api.h"
-
-/*
- * The "len16" field of a Firmware Command Structure ...
- */
-#define FW_LEN16(fw_struct) FW_CMD_LEN16(sizeof(fw_struct) / 16)
-
-/*
- * Per-VF statistics.
- */
-struct t4vf_port_stats {
-	/*
-	 * TX statistics.
-	 */
-	u64 tx_bcast_bytes;		/* broadcast */
-	u64 tx_bcast_frames;
-	u64 tx_mcast_bytes;		/* multicast */
-	u64 tx_mcast_frames;
-	u64 tx_ucast_bytes;		/* unicast */
-	u64 tx_ucast_frames;
-	u64 tx_drop_frames;		/* TX dropped frames */
-	u64 tx_offload_bytes;		/* offload */
-	u64 tx_offload_frames;
-
-	/*
-	 * RX statistics.
-	 */
-	u64 rx_bcast_bytes;		/* broadcast */
-	u64 rx_bcast_frames;
-	u64 rx_mcast_bytes;		/* multicast */
-	u64 rx_mcast_frames;
-	u64 rx_ucast_bytes;
-	u64 rx_ucast_frames;		/* unicast */
-
-	u64 rx_err_frames;		/* RX error frames */
-};
-
-/*
- * Per-"port" (Virtual Interface) link configuration ...
- */
-struct link_config {
-	unsigned int   supported;        /* link capabilities */
-	unsigned int   advertising;      /* advertised capabilities */
-	unsigned short requested_speed;  /* speed user has requested */
-	unsigned short speed;            /* actual link speed */
-	unsigned char  requested_fc;     /* flow control user has requested */
-	unsigned char  fc;               /* actual link flow control */
-	unsigned char  autoneg;          /* autonegotiating? */
-	unsigned char  link_ok;          /* link up? */
-};
-
-enum {
-	PAUSE_RX      = 1 << 0,
-	PAUSE_TX      = 1 << 1,
-	PAUSE_AUTONEG = 1 << 2
-};
-
-/*
- * General device parameters ...
- */
-struct dev_params {
-	u32 fwrev;			/* firmware version */
-	u32 tprev;			/* TP Microcode Version */
-};
-
-/*
- * Scatter Gather Engine parameters.  These are almost all determined by the
- * Physical Function Driver.  We just need to grab them to see within which
- * environment we're playing ...
- */
-struct sge_params {
-	u32 sge_control;		/* padding, boundaries, lengths, etc. */
-	u32 sge_host_page_size;		/* RDMA page sizes */
-	u32 sge_queues_per_page;	/* RDMA queues/page */
-	u32 sge_user_mode_limits;	/* limits for BAR2 user mode accesses */
-	u32 sge_fl_buffer_size[16];	/* free list buffer sizes */
-	u32 sge_ingress_rx_threshold;	/* RX counter interrupt threshold[4] */
-	u32 sge_timer_value_0_and_1;	/* interrupt coalescing timer values */
-	u32 sge_timer_value_2_and_3;
-	u32 sge_timer_value_4_and_5;
-};
-
-/*
- * Vital Product Data parameters.
- */
-struct vpd_params {
-	u32 cclk;			/* Core Clock (KHz) */
-};
-
-/*
- * Global Receive Side Scaling (RSS) parameters in host-native format.
- */
-struct rss_params {
-	unsigned int mode;		/* RSS mode */
-	union {
-	    struct {
-		unsigned int synmapen:1;	/* SYN Map Enable */
-		unsigned int syn4tupenipv6:1;	/* enable hashing 4-tuple IPv6 SYNs */
-		unsigned int syn2tupenipv6:1;	/* enable hashing 2-tuple IPv6 SYNs */
-		unsigned int syn4tupenipv4:1;	/* enable hashing 4-tuple IPv4 SYNs */
-		unsigned int syn2tupenipv4:1;	/* enable hashing 2-tuple IPv4 SYNs */
-		unsigned int ofdmapen:1;	/* Offload Map Enable */
-		unsigned int tnlmapen:1;	/* Tunnel Map Enable */
-		unsigned int tnlalllookup:1;	/* Tunnel All Lookup */
-		unsigned int hashtoeplitz:1;	/* use Toeplitz hash */
-	    } basicvirtual;
-	} u;
-};
-
-/*
- * Virtual Interface RSS Configuration in host-native format.
- */
-union rss_vi_config {
-    struct {
-	u16 defaultq;			/* Ingress Queue ID for !tnlalllookup */
-	unsigned int ip6fourtupen:1;	/* hash 4-tuple IPv6 ingress packets */
-	unsigned int ip6twotupen:1;	/* hash 2-tuple IPv6 ingress packets */
-	unsigned int ip4fourtupen:1;	/* hash 4-tuple IPv4 ingress packets */
-	unsigned int ip4twotupen:1;	/* hash 2-tuple IPv4 ingress packets */
-	int udpen;			/* hash 4-tuple UDP ingress packets */
-    } basicvirtual;
-};
-
-/*
- * Maximum resources provisioned for a PCI VF.
- */
-struct vf_resources {
-	unsigned int nvi;		/* N virtual interfaces */
-	unsigned int neq;		/* N egress Qs */
-	unsigned int nethctrl;		/* N egress ETH or CTRL Qs */
-	unsigned int niqflint;		/* N ingress Qs/w free list(s) & intr */
-	unsigned int niq;		/* N ingress Qs */
-	unsigned int tc;		/* PCI-E traffic class */
-	unsigned int pmask;		/* port access rights mask */
-	unsigned int nexactf;		/* N exact MPS filters */
-	unsigned int r_caps;		/* read capabilities */
-	unsigned int wx_caps;		/* write/execute capabilities */
-};
-
-/*
- * Per-"adapter" (Virtual Function) parameters.
- */
-struct adapter_params {
-	struct dev_params dev;		/* general device parameters */
-	struct sge_params sge;		/* Scatter Gather Engine */
-	struct vpd_params vpd;		/* Vital Product Data */
-	struct rss_params rss;		/* Receive Side Scaling */
-	struct vf_resources vfres;	/* Virtual Function Resource limits */
-	u8 nports;			/* # of Ethernet "ports" */
-};
-
-#include "adapter.h"
-
-#ifndef PCI_VENDOR_ID_CHELSIO
-# define PCI_VENDOR_ID_CHELSIO 0x1425
-#endif
-
-#define for_each_port(adapter, iter) \
-	for (iter = 0; iter < (adapter)->params.nports; iter++)
-
-static inline bool is_10g_port(const struct link_config *lc)
-{
-	return (lc->supported & SUPPORTED_10000baseT_Full) != 0;
-}
-
-static inline unsigned int core_ticks_per_usec(const struct adapter *adapter)
-{
-	return adapter->params.vpd.cclk / 1000;
-}
-
-static inline unsigned int us_to_core_ticks(const struct adapter *adapter,
-					    unsigned int us)
-{
-	return (us * adapter->params.vpd.cclk) / 1000;
-}
-
-static inline unsigned int core_ticks_to_us(const struct adapter *adapter,
-					    unsigned int ticks)
-{
-	return (ticks * 1000) / adapter->params.vpd.cclk;
-}
-
-int t4vf_wr_mbox_core(struct adapter *, const void *, int, void *, bool);
-
-static inline int t4vf_wr_mbox(struct adapter *adapter, const void *cmd,
-			       int size, void *rpl)
-{
-	return t4vf_wr_mbox_core(adapter, cmd, size, rpl, true);
-}
-
-static inline int t4vf_wr_mbox_ns(struct adapter *adapter, const void *cmd,
-				  int size, void *rpl)
-{
-	return t4vf_wr_mbox_core(adapter, cmd, size, rpl, false);
-}
-
-int __devinit t4vf_wait_dev_ready(struct adapter *);
-int __devinit t4vf_port_init(struct adapter *, int);
-
-int t4vf_fw_reset(struct adapter *);
-int t4vf_query_params(struct adapter *, unsigned int, const u32 *, u32 *);
-int t4vf_set_params(struct adapter *, unsigned int, const u32 *, const u32 *);
-
-int t4vf_get_sge_params(struct adapter *);
-int t4vf_get_vpd_params(struct adapter *);
-int t4vf_get_dev_params(struct adapter *);
-int t4vf_get_rss_glb_config(struct adapter *);
-int t4vf_get_vfres(struct adapter *);
-
-int t4vf_read_rss_vi_config(struct adapter *, unsigned int,
-			    union rss_vi_config *);
-int t4vf_write_rss_vi_config(struct adapter *, unsigned int,
-			     union rss_vi_config *);
-int t4vf_config_rss_range(struct adapter *, unsigned int, int, int,
-			  const u16 *, int);
-
-int t4vf_alloc_vi(struct adapter *, int);
-int t4vf_free_vi(struct adapter *, int);
-int t4vf_enable_vi(struct adapter *, unsigned int, bool, bool);
-int t4vf_identify_port(struct adapter *, unsigned int, unsigned int);
-
-int t4vf_set_rxmode(struct adapter *, unsigned int, int, int, int, int, int,
-		    bool);
-int t4vf_alloc_mac_filt(struct adapter *, unsigned int, bool, unsigned int,
-			const u8 **, u16 *, u64 *, bool);
-int t4vf_change_mac(struct adapter *, unsigned int, int, const u8 *, bool);
-int t4vf_set_addr_hash(struct adapter *, unsigned int, bool, u64, bool);
-int t4vf_get_port_stats(struct adapter *, int, struct t4vf_port_stats *);
-
-int t4vf_iq_free(struct adapter *, unsigned int, unsigned int, unsigned int,
-		 unsigned int);
-int t4vf_eth_eq_free(struct adapter *, unsigned int);
-
-int t4vf_handle_fw_rpl(struct adapter *, const __be64 *);
-
-#endif /* __T4VF_COMMON_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4vf/t4vf_defs.h linux-libre-3.2-gnu/drivers/net/cxgb4vf/t4vf_defs.h
--- linux-libre-3.1-gnu/drivers/net/cxgb4vf/t4vf_defs.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4vf/t4vf_defs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,121 +0,0 @@
-/*
- * This file is part of the Chelsio T4 PCI-E SR-IOV Virtual Function Ethernet
- * driver for Linux.
- *
- * Copyright (c) 2009-2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __T4VF_DEFS_H__
-#define __T4VF_DEFS_H__
-
-#include "../cxgb4/t4_regs.h"
-
-/*
- * The VF Register Map.
- *
- * The Scatter Gather Engine (SGE), Multiport Support module (MPS), PIO Local
- * bus module (PL) and CPU Interface Module (CIM) components are mapped via
- * the Slice to Module Map Table (see below) in the Physical Function Register
- * Map.  The Mail Box Data (MBDATA) range is mapped via the PCI-E Mailbox Base
- * and Offset registers in the PF Register Map.  The MBDATA base address is
- * quite constrained as it determines the Mailbox Data addresses for both PFs
- * and VFs, and therefore must fit in both the VF and PF Register Maps without
- * overlapping other registers.
- */
-#define T4VF_SGE_BASE_ADDR	0x0000
-#define T4VF_MPS_BASE_ADDR	0x0100
-#define T4VF_PL_BASE_ADDR	0x0200
-#define T4VF_MBDATA_BASE_ADDR	0x0240
-#define T4VF_CIM_BASE_ADDR	0x0300
-
-#define T4VF_REGMAP_START	0x0000
-#define T4VF_REGMAP_SIZE	0x0400
-
-/*
- * There's no hardware limitation which requires that the addresses of the
- * Mailbox Data in the fixed CIM PF map and the programmable VF map must
- * match.  However, it's a useful convention ...
- */
-#if T4VF_MBDATA_BASE_ADDR != CIM_PF_MAILBOX_DATA
-#error T4VF_MBDATA_BASE_ADDR must match CIM_PF_MAILBOX_DATA!
-#endif
-
-/*
- * Virtual Function "Slice to Module Map Table" definitions.
- *
- * This table allows us to map subsets of the various module register sets
- * into the T4VF Register Map.  Each table entry identifies the index of the
- * module whose registers are being mapped, the offset within the module's
- * register set that the mapping should start at, the limit of the mapping,
- * and the offset within the T4VF Register Map to which the module's registers
- * are being mapped.  All addresses and qualtities are in terms of 32-bit
- * words.  The "limit" value is also in terms of 32-bit words and is equal to
- * the last address mapped in the T4VF Register Map 1 (i.e. it's a "<="
- * relation rather than a "<").
- */
-#define T4VF_MOD_MAP(module, index, first, last) \
-	T4VF_MOD_MAP_##module##_INDEX  = (index), \
-	T4VF_MOD_MAP_##module##_FIRST  = (first), \
-	T4VF_MOD_MAP_##module##_LAST   = (last), \
-	T4VF_MOD_MAP_##module##_OFFSET = ((first)/4), \
-	T4VF_MOD_MAP_##module##_BASE = \
-		(T4VF_##module##_BASE_ADDR/4 + (first)/4), \
-	T4VF_MOD_MAP_##module##_LIMIT = \
-		(T4VF_##module##_BASE_ADDR/4 + (last)/4),
-
-#define SGE_VF_KDOORBELL 0x0
-#define SGE_VF_GTS 0x4
-#define MPS_VF_CTL 0x0
-#define MPS_VF_STAT_RX_VF_ERR_FRAMES_H 0xfc
-#define PL_VF_WHOAMI 0x0
-#define CIM_VF_EXT_MAILBOX_CTRL 0x0
-#define CIM_VF_EXT_MAILBOX_STATUS 0x4
-
-enum {
-    T4VF_MOD_MAP(SGE, 2, SGE_VF_KDOORBELL, SGE_VF_GTS)
-    T4VF_MOD_MAP(MPS, 0, MPS_VF_CTL, MPS_VF_STAT_RX_VF_ERR_FRAMES_H)
-    T4VF_MOD_MAP(PL,  3, PL_VF_WHOAMI, PL_VF_WHOAMI)
-    T4VF_MOD_MAP(CIM, 1, CIM_VF_EXT_MAILBOX_CTRL, CIM_VF_EXT_MAILBOX_STATUS)
-};
-
-/*
- * There isn't a Slice to Module Map Table entry for the Mailbox Data
- * registers, but it's convenient to use similar names as above.  There are 8
- * little-endian 64-bit Mailbox Data registers.  Note that the "instances"
- * value below is in terms of 32-bit words which matches the "word" addressing
- * space we use above for the Slice to Module Map Space.
- */
-#define NUM_CIM_VF_MAILBOX_DATA_INSTANCES 16
-
-#define T4VF_MBDATA_FIRST	0
-#define T4VF_MBDATA_LAST	((NUM_CIM_VF_MAILBOX_DATA_INSTANCES-1)*4)
-
-#endif /* __T4T4VF_DEFS_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/cxgb4vf/t4vf_hw.c linux-libre-3.2-gnu/drivers/net/cxgb4vf/t4vf_hw.c
--- linux-libre-3.1-gnu/drivers/net/cxgb4vf/t4vf_hw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/cxgb4vf/t4vf_hw.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1387 +0,0 @@
-/*
- * This file is part of the Chelsio T4 PCI-E SR-IOV Virtual Function Ethernet
- * driver for Linux.
- *
- * Copyright (c) 2009-2010 Chelsio Communications, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <linux/pci.h>
-
-#include "t4vf_common.h"
-#include "t4vf_defs.h"
-
-#include "../cxgb4/t4_regs.h"
-#include "../cxgb4/t4fw_api.h"
-
-/*
- * Wait for the device to become ready (signified by our "who am I" register
- * returning a value other than all 1's).  Return an error if it doesn't
- * become ready ...
- */
-int __devinit t4vf_wait_dev_ready(struct adapter *adapter)
-{
-	const u32 whoami = T4VF_PL_BASE_ADDR + PL_VF_WHOAMI;
-	const u32 notready1 = 0xffffffff;
-	const u32 notready2 = 0xeeeeeeee;
-	u32 val;
-
-	val = t4_read_reg(adapter, whoami);
-	if (val != notready1 && val != notready2)
-		return 0;
-	msleep(500);
-	val = t4_read_reg(adapter, whoami);
-	if (val != notready1 && val != notready2)
-		return 0;
-	else
-		return -EIO;
-}
-
-/*
- * Get the reply to a mailbox command and store it in @rpl in big-endian order
- * (since the firmware data structures are specified in a big-endian layout).
- */
-static void get_mbox_rpl(struct adapter *adapter, __be64 *rpl, int size,
-			 u32 mbox_data)
-{
-	for ( ; size; size -= 8, mbox_data += 8)
-		*rpl++ = cpu_to_be64(t4_read_reg64(adapter, mbox_data));
-}
-
-/*
- * Dump contents of mailbox with a leading tag.
- */
-static void dump_mbox(struct adapter *adapter, const char *tag, u32 mbox_data)
-{
-	dev_err(adapter->pdev_dev,
-		"mbox %s: %llx %llx %llx %llx %llx %llx %llx %llx\n", tag,
-		(unsigned long long)t4_read_reg64(adapter, mbox_data +  0),
-		(unsigned long long)t4_read_reg64(adapter, mbox_data +  8),
-		(unsigned long long)t4_read_reg64(adapter, mbox_data + 16),
-		(unsigned long long)t4_read_reg64(adapter, mbox_data + 24),
-		(unsigned long long)t4_read_reg64(adapter, mbox_data + 32),
-		(unsigned long long)t4_read_reg64(adapter, mbox_data + 40),
-		(unsigned long long)t4_read_reg64(adapter, mbox_data + 48),
-		(unsigned long long)t4_read_reg64(adapter, mbox_data + 56));
-}
-
-/**
- *	t4vf_wr_mbox_core - send a command to FW through the mailbox
- *	@adapter: the adapter
- *	@cmd: the command to write
- *	@size: command length in bytes
- *	@rpl: where to optionally store the reply
- *	@sleep_ok: if true we may sleep while awaiting command completion
- *
- *	Sends the given command to FW through the mailbox and waits for the
- *	FW to execute the command.  If @rpl is not %NULL it is used to store
- *	the FW's reply to the command.  The command and its optional reply
- *	are of the same length.  FW can take up to 500 ms to respond.
- *	@sleep_ok determines whether we may sleep while awaiting the response.
- *	If sleeping is allowed we use progressive backoff otherwise we spin.
- *
- *	The return value is 0 on success or a negative errno on failure.  A
- *	failure can happen either because we are not able to execute the
- *	command or FW executes it but signals an error.  In the latter case
- *	the return value is the error code indicated by FW (negated).
- */
-int t4vf_wr_mbox_core(struct adapter *adapter, const void *cmd, int size,
-		      void *rpl, bool sleep_ok)
-{
-	static const int delay[] = {
-		1, 1, 3, 5, 10, 10, 20, 50, 100
-	};
-
-	u32 v;
-	int i, ms, delay_idx;
-	const __be64 *p;
-	u32 mbox_data = T4VF_MBDATA_BASE_ADDR;
-	u32 mbox_ctl = T4VF_CIM_BASE_ADDR + CIM_VF_EXT_MAILBOX_CTRL;
-
-	/*
-	 * Commands must be multiples of 16 bytes in length and may not be
-	 * larger than the size of the Mailbox Data register array.
-	 */
-	if ((size % 16) != 0 ||
-	    size > NUM_CIM_VF_MAILBOX_DATA_INSTANCES * 4)
-		return -EINVAL;
-
-	/*
-	 * Loop trying to get ownership of the mailbox.  Return an error
-	 * if we can't gain ownership.
-	 */
-	v = MBOWNER_GET(t4_read_reg(adapter, mbox_ctl));
-	for (i = 0; v == MBOX_OWNER_NONE && i < 3; i++)
-		v = MBOWNER_GET(t4_read_reg(adapter, mbox_ctl));
-	if (v != MBOX_OWNER_DRV)
-		return v == MBOX_OWNER_FW ? -EBUSY : -ETIMEDOUT;
-
-	/*
-	 * Write the command array into the Mailbox Data register array and
-	 * transfer ownership of the mailbox to the firmware.
-	 *
-	 * For the VFs, the Mailbox Data "registers" are actually backed by
-	 * T4's "MA" interface rather than PL Registers (as is the case for
-	 * the PFs).  Because these are in different coherency domains, the
-	 * write to the VF's PL-register-backed Mailbox Control can race in
-	 * front of the writes to the MA-backed VF Mailbox Data "registers".
-	 * So we need to do a read-back on at least one byte of the VF Mailbox
-	 * Data registers before doing the write to the VF Mailbox Control
-	 * register.
-	 */
-	for (i = 0, p = cmd; i < size; i += 8)
-		t4_write_reg64(adapter, mbox_data + i, be64_to_cpu(*p++));
-	t4_read_reg(adapter, mbox_data);         /* flush write */
-
-	t4_write_reg(adapter, mbox_ctl,
-		     MBMSGVALID | MBOWNER(MBOX_OWNER_FW));
-	t4_read_reg(adapter, mbox_ctl);          /* flush write */
-
-	/*
-	 * Spin waiting for firmware to acknowledge processing our command.
-	 */
-	delay_idx = 0;
-	ms = delay[0];
-
-	for (i = 0; i < FW_CMD_MAX_TIMEOUT; i += ms) {
-		if (sleep_ok) {
-			ms = delay[delay_idx];
-			if (delay_idx < ARRAY_SIZE(delay) - 1)
-				delay_idx++;
-			msleep(ms);
-		} else
-			mdelay(ms);
-
-		/*
-		 * If we're the owner, see if this is the reply we wanted.
-		 */
-		v = t4_read_reg(adapter, mbox_ctl);
-		if (MBOWNER_GET(v) == MBOX_OWNER_DRV) {
-			/*
-			 * If the Message Valid bit isn't on, revoke ownership
-			 * of the mailbox and continue waiting for our reply.
-			 */
-			if ((v & MBMSGVALID) == 0) {
-				t4_write_reg(adapter, mbox_ctl,
-					     MBOWNER(MBOX_OWNER_NONE));
-				continue;
-			}
-
-			/*
-			 * We now have our reply.  Extract the command return
-			 * value, copy the reply back to our caller's buffer
-			 * (if specified) and revoke ownership of the mailbox.
-			 * We return the (negated) firmware command return
-			 * code (this depends on FW_SUCCESS == 0).
-			 */
-
-			/* return value in low-order little-endian word */
-			v = t4_read_reg(adapter, mbox_data);
-			if (FW_CMD_RETVAL_GET(v))
-				dump_mbox(adapter, "FW Error", mbox_data);
-
-			if (rpl) {
-				/* request bit in high-order BE word */
-				WARN_ON((be32_to_cpu(*(const u32 *)cmd)
-					 & FW_CMD_REQUEST) == 0);
-				get_mbox_rpl(adapter, rpl, size, mbox_data);
-				WARN_ON((be32_to_cpu(*(u32 *)rpl)
-					 & FW_CMD_REQUEST) != 0);
-			}
-			t4_write_reg(adapter, mbox_ctl,
-				     MBOWNER(MBOX_OWNER_NONE));
-			return -FW_CMD_RETVAL_GET(v);
-		}
-	}
-
-	/*
-	 * We timed out.  Return the error ...
-	 */
-	dump_mbox(adapter, "FW Timeout", mbox_data);
-	return -ETIMEDOUT;
-}
-
-/**
- *	hash_mac_addr - return the hash value of a MAC address
- *	@addr: the 48-bit Ethernet MAC address
- *
- *	Hashes a MAC address according to the hash function used by hardware
- *	inexact (hash) address matching.
- */
-static int hash_mac_addr(const u8 *addr)
-{
-	u32 a = ((u32)addr[0] << 16) | ((u32)addr[1] << 8) | addr[2];
-	u32 b = ((u32)addr[3] << 16) | ((u32)addr[4] << 8) | addr[5];
-	a ^= b;
-	a ^= (a >> 12);
-	a ^= (a >> 6);
-	return a & 0x3f;
-}
-
-/**
- *	init_link_config - initialize a link's SW state
- *	@lc: structure holding the link state
- *	@caps: link capabilities
- *
- *	Initializes the SW state maintained for each link, including the link's
- *	capabilities and default speed/flow-control/autonegotiation settings.
- */
-static void __devinit init_link_config(struct link_config *lc,
-				       unsigned int caps)
-{
-	lc->supported = caps;
-	lc->requested_speed = 0;
-	lc->speed = 0;
-	lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX;
-	if (lc->supported & SUPPORTED_Autoneg) {
-		lc->advertising = lc->supported;
-		lc->autoneg = AUTONEG_ENABLE;
-		lc->requested_fc |= PAUSE_AUTONEG;
-	} else {
-		lc->advertising = 0;
-		lc->autoneg = AUTONEG_DISABLE;
-	}
-}
-
-/**
- *	t4vf_port_init - initialize port hardware/software state
- *	@adapter: the adapter
- *	@pidx: the adapter port index
- */
-int __devinit t4vf_port_init(struct adapter *adapter, int pidx)
-{
-	struct port_info *pi = adap2pinfo(adapter, pidx);
-	struct fw_vi_cmd vi_cmd, vi_rpl;
-	struct fw_port_cmd port_cmd, port_rpl;
-	int v;
-	u32 word;
-
-	/*
-	 * Execute a VI Read command to get our Virtual Interface information
-	 * like MAC address, etc.
-	 */
-	memset(&vi_cmd, 0, sizeof(vi_cmd));
-	vi_cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_VI_CMD) |
-				       FW_CMD_REQUEST |
-				       FW_CMD_READ);
-	vi_cmd.alloc_to_len16 = cpu_to_be32(FW_LEN16(vi_cmd));
-	vi_cmd.type_viid = cpu_to_be16(FW_VI_CMD_VIID(pi->viid));
-	v = t4vf_wr_mbox(adapter, &vi_cmd, sizeof(vi_cmd), &vi_rpl);
-	if (v)
-		return v;
-
-	BUG_ON(pi->port_id != FW_VI_CMD_PORTID_GET(vi_rpl.portid_pkd));
-	pi->rss_size = FW_VI_CMD_RSSSIZE_GET(be16_to_cpu(vi_rpl.rsssize_pkd));
-	t4_os_set_hw_addr(adapter, pidx, vi_rpl.mac);
-
-	/*
-	 * If we don't have read access to our port information, we're done
-	 * now.  Otherwise, execute a PORT Read command to get it ...
-	 */
-	if (!(adapter->params.vfres.r_caps & FW_CMD_CAP_PORT))
-		return 0;
-
-	memset(&port_cmd, 0, sizeof(port_cmd));
-	port_cmd.op_to_portid = cpu_to_be32(FW_CMD_OP(FW_PORT_CMD) |
-					    FW_CMD_REQUEST |
-					    FW_CMD_READ |
-					    FW_PORT_CMD_PORTID(pi->port_id));
-	port_cmd.action_to_len16 =
-		cpu_to_be32(FW_PORT_CMD_ACTION(FW_PORT_ACTION_GET_PORT_INFO) |
-			    FW_LEN16(port_cmd));
-	v = t4vf_wr_mbox(adapter, &port_cmd, sizeof(port_cmd), &port_rpl);
-	if (v)
-		return v;
-
-	v = 0;
-	word = be16_to_cpu(port_rpl.u.info.pcap);
-	if (word & FW_PORT_CAP_SPEED_100M)
-		v |= SUPPORTED_100baseT_Full;
-	if (word & FW_PORT_CAP_SPEED_1G)
-		v |= SUPPORTED_1000baseT_Full;
-	if (word & FW_PORT_CAP_SPEED_10G)
-		v |= SUPPORTED_10000baseT_Full;
-	if (word & FW_PORT_CAP_ANEG)
-		v |= SUPPORTED_Autoneg;
-	init_link_config(&pi->link_cfg, v);
-
-	return 0;
-}
-
-/**
- *      t4vf_fw_reset - issue a reset to FW
- *      @adapter: the adapter
- *
- *	Issues a reset command to FW.  For a Physical Function this would
- *	result in the Firmware reseting all of its state.  For a Virtual
- *	Function this just resets the state associated with the VF.
- */
-int t4vf_fw_reset(struct adapter *adapter)
-{
-	struct fw_reset_cmd cmd;
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_write = cpu_to_be32(FW_CMD_OP(FW_RESET_CMD) |
-				      FW_CMD_WRITE);
-	cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
-	return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL);
-}
-
-/**
- *	t4vf_query_params - query FW or device parameters
- *	@adapter: the adapter
- *	@nparams: the number of parameters
- *	@params: the parameter names
- *	@vals: the parameter values
- *
- *	Reads the values of firmware or device parameters.  Up to 7 parameters
- *	can be queried at once.
- */
-int t4vf_query_params(struct adapter *adapter, unsigned int nparams,
-		      const u32 *params, u32 *vals)
-{
-	int i, ret;
-	struct fw_params_cmd cmd, rpl;
-	struct fw_params_param *p;
-	size_t len16;
-
-	if (nparams > 7)
-		return -EINVAL;
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_PARAMS_CMD) |
-				    FW_CMD_REQUEST |
-				    FW_CMD_READ);
-	len16 = DIV_ROUND_UP(offsetof(struct fw_params_cmd,
-				      param[nparams].mnem), 16);
-	cmd.retval_len16 = cpu_to_be32(FW_CMD_LEN16(len16));
-	for (i = 0, p = &cmd.param[0]; i < nparams; i++, p++)
-		p->mnem = htonl(*params++);
-
-	ret = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl);
-	if (ret == 0)
-		for (i = 0, p = &rpl.param[0]; i < nparams; i++, p++)
-			*vals++ = be32_to_cpu(p->val);
-	return ret;
-}
-
-/**
- *	t4vf_set_params - sets FW or device parameters
- *	@adapter: the adapter
- *	@nparams: the number of parameters
- *	@params: the parameter names
- *	@vals: the parameter values
- *
- *	Sets the values of firmware or device parameters.  Up to 7 parameters
- *	can be specified at once.
- */
-int t4vf_set_params(struct adapter *adapter, unsigned int nparams,
-		    const u32 *params, const u32 *vals)
-{
-	int i;
-	struct fw_params_cmd cmd;
-	struct fw_params_param *p;
-	size_t len16;
-
-	if (nparams > 7)
-		return -EINVAL;
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_PARAMS_CMD) |
-				    FW_CMD_REQUEST |
-				    FW_CMD_WRITE);
-	len16 = DIV_ROUND_UP(offsetof(struct fw_params_cmd,
-				      param[nparams]), 16);
-	cmd.retval_len16 = cpu_to_be32(FW_CMD_LEN16(len16));
-	for (i = 0, p = &cmd.param[0]; i < nparams; i++, p++) {
-		p->mnem = cpu_to_be32(*params++);
-		p->val = cpu_to_be32(*vals++);
-	}
-
-	return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL);
-}
-
-/**
- *	t4vf_get_sge_params - retrieve adapter Scatter gather Engine parameters
- *	@adapter: the adapter
- *
- *	Retrieves various core SGE parameters in the form of hardware SGE
- *	register values.  The caller is responsible for decoding these as
- *	needed.  The SGE parameters are stored in @adapter->params.sge.
- */
-int t4vf_get_sge_params(struct adapter *adapter)
-{
-	struct sge_params *sge_params = &adapter->params.sge;
-	u32 params[7], vals[7];
-	int v;
-
-	params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
-		     FW_PARAMS_PARAM_XYZ(SGE_CONTROL));
-	params[1] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
-		     FW_PARAMS_PARAM_XYZ(SGE_HOST_PAGE_SIZE));
-	params[2] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
-		     FW_PARAMS_PARAM_XYZ(SGE_FL_BUFFER_SIZE0));
-	params[3] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
-		     FW_PARAMS_PARAM_XYZ(SGE_FL_BUFFER_SIZE1));
-	params[4] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
-		     FW_PARAMS_PARAM_XYZ(SGE_TIMER_VALUE_0_AND_1));
-	params[5] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
-		     FW_PARAMS_PARAM_XYZ(SGE_TIMER_VALUE_2_AND_3));
-	params[6] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
-		     FW_PARAMS_PARAM_XYZ(SGE_TIMER_VALUE_4_AND_5));
-	v = t4vf_query_params(adapter, 7, params, vals);
-	if (v)
-		return v;
-	sge_params->sge_control = vals[0];
-	sge_params->sge_host_page_size = vals[1];
-	sge_params->sge_fl_buffer_size[0] = vals[2];
-	sge_params->sge_fl_buffer_size[1] = vals[3];
-	sge_params->sge_timer_value_0_and_1 = vals[4];
-	sge_params->sge_timer_value_2_and_3 = vals[5];
-	sge_params->sge_timer_value_4_and_5 = vals[6];
-
-	params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
-		     FW_PARAMS_PARAM_XYZ(SGE_INGRESS_RX_THRESHOLD));
-	v = t4vf_query_params(adapter, 1, params, vals);
-	if (v)
-		return v;
-	sge_params->sge_ingress_rx_threshold = vals[0];
-
-	return 0;
-}
-
-/**
- *	t4vf_get_vpd_params - retrieve device VPD paremeters
- *	@adapter: the adapter
- *
- *	Retrives various device Vital Product Data parameters.  The parameters
- *	are stored in @adapter->params.vpd.
- */
-int t4vf_get_vpd_params(struct adapter *adapter)
-{
-	struct vpd_params *vpd_params = &adapter->params.vpd;
-	u32 params[7], vals[7];
-	int v;
-
-	params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
-		     FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CCLK));
-	v = t4vf_query_params(adapter, 1, params, vals);
-	if (v)
-		return v;
-	vpd_params->cclk = vals[0];
-
-	return 0;
-}
-
-/**
- *	t4vf_get_dev_params - retrieve device paremeters
- *	@adapter: the adapter
- *
- *	Retrives various device parameters.  The parameters are stored in
- *	@adapter->params.dev.
- */
-int t4vf_get_dev_params(struct adapter *adapter)
-{
-	struct dev_params *dev_params = &adapter->params.dev;
-	u32 params[7], vals[7];
-	int v;
-
-	params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
-		     FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_FWREV));
-	params[1] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
-		     FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_TPREV));
-	v = t4vf_query_params(adapter, 2, params, vals);
-	if (v)
-		return v;
-	dev_params->fwrev = vals[0];
-	dev_params->tprev = vals[1];
-
-	return 0;
-}
-
-/**
- *	t4vf_get_rss_glb_config - retrieve adapter RSS Global Configuration
- *	@adapter: the adapter
- *
- *	Retrieves global RSS mode and parameters with which we have to live
- *	and stores them in the @adapter's RSS parameters.
- */
-int t4vf_get_rss_glb_config(struct adapter *adapter)
-{
-	struct rss_params *rss = &adapter->params.rss;
-	struct fw_rss_glb_config_cmd cmd, rpl;
-	int v;
-
-	/*
-	 * Execute an RSS Global Configuration read command to retrieve
-	 * our RSS configuration.
-	 */
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_write = cpu_to_be32(FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) |
-				      FW_CMD_REQUEST |
-				      FW_CMD_READ);
-	cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
-	v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl);
-	if (v)
-		return v;
-
-	/*
-	 * Transate the big-endian RSS Global Configuration into our
-	 * cpu-endian format based on the RSS mode.  We also do first level
-	 * filtering at this point to weed out modes which don't support
-	 * VF Drivers ...
-	 */
-	rss->mode = FW_RSS_GLB_CONFIG_CMD_MODE_GET(
-			be32_to_cpu(rpl.u.manual.mode_pkd));
-	switch (rss->mode) {
-	case FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL: {
-		u32 word = be32_to_cpu(
-				rpl.u.basicvirtual.synmapen_to_hashtoeplitz);
-
-		rss->u.basicvirtual.synmapen =
-			((word & FW_RSS_GLB_CONFIG_CMD_SYNMAPEN) != 0);
-		rss->u.basicvirtual.syn4tupenipv6 =
-			((word & FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV6) != 0);
-		rss->u.basicvirtual.syn2tupenipv6 =
-			((word & FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV6) != 0);
-		rss->u.basicvirtual.syn4tupenipv4 =
-			((word & FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV4) != 0);
-		rss->u.basicvirtual.syn2tupenipv4 =
-			((word & FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV4) != 0);
-
-		rss->u.basicvirtual.ofdmapen =
-			((word & FW_RSS_GLB_CONFIG_CMD_OFDMAPEN) != 0);
-
-		rss->u.basicvirtual.tnlmapen =
-			((word & FW_RSS_GLB_CONFIG_CMD_TNLMAPEN) != 0);
-		rss->u.basicvirtual.tnlalllookup =
-			((word  & FW_RSS_GLB_CONFIG_CMD_TNLALLLKP) != 0);
-
-		rss->u.basicvirtual.hashtoeplitz =
-			((word & FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ) != 0);
-
-		/* we need at least Tunnel Map Enable to be set */
-		if (!rss->u.basicvirtual.tnlmapen)
-			return -EINVAL;
-		break;
-	}
-
-	default:
-		/* all unknown/unsupported RSS modes result in an error */
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/**
- *	t4vf_get_vfres - retrieve VF resource limits
- *	@adapter: the adapter
- *
- *	Retrieves configured resource limits and capabilities for a virtual
- *	function.  The results are stored in @adapter->vfres.
- */
-int t4vf_get_vfres(struct adapter *adapter)
-{
-	struct vf_resources *vfres = &adapter->params.vfres;
-	struct fw_pfvf_cmd cmd, rpl;
-	int v;
-	u32 word;
-
-	/*
-	 * Execute PFVF Read command to get VF resource limits; bail out early
-	 * with error on command failure.
-	 */
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_PFVF_CMD) |
-				    FW_CMD_REQUEST |
-				    FW_CMD_READ);
-	cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
-	v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl);
-	if (v)
-		return v;
-
-	/*
-	 * Extract VF resource limits and return success.
-	 */
-	word = be32_to_cpu(rpl.niqflint_niq);
-	vfres->niqflint = FW_PFVF_CMD_NIQFLINT_GET(word);
-	vfres->niq = FW_PFVF_CMD_NIQ_GET(word);
-
-	word = be32_to_cpu(rpl.type_to_neq);
-	vfres->neq = FW_PFVF_CMD_NEQ_GET(word);
-	vfres->pmask = FW_PFVF_CMD_PMASK_GET(word);
-
-	word = be32_to_cpu(rpl.tc_to_nexactf);
-	vfres->tc = FW_PFVF_CMD_TC_GET(word);
-	vfres->nvi = FW_PFVF_CMD_NVI_GET(word);
-	vfres->nexactf = FW_PFVF_CMD_NEXACTF_GET(word);
-
-	word = be32_to_cpu(rpl.r_caps_to_nethctrl);
-	vfres->r_caps = FW_PFVF_CMD_R_CAPS_GET(word);
-	vfres->wx_caps = FW_PFVF_CMD_WX_CAPS_GET(word);
-	vfres->nethctrl = FW_PFVF_CMD_NETHCTRL_GET(word);
-
-	return 0;
-}
-
-/**
- *	t4vf_read_rss_vi_config - read a VI's RSS configuration
- *	@adapter: the adapter
- *	@viid: Virtual Interface ID
- *	@config: pointer to host-native VI RSS Configuration buffer
- *
- *	Reads the Virtual Interface's RSS configuration information and
- *	translates it into CPU-native format.
- */
-int t4vf_read_rss_vi_config(struct adapter *adapter, unsigned int viid,
-			    union rss_vi_config *config)
-{
-	struct fw_rss_vi_config_cmd cmd, rpl;
-	int v;
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_RSS_VI_CONFIG_CMD) |
-				     FW_CMD_REQUEST |
-				     FW_CMD_READ |
-				     FW_RSS_VI_CONFIG_CMD_VIID(viid));
-	cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
-	v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl);
-	if (v)
-		return v;
-
-	switch (adapter->params.rss.mode) {
-	case FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL: {
-		u32 word = be32_to_cpu(rpl.u.basicvirtual.defaultq_to_udpen);
-
-		config->basicvirtual.ip6fourtupen =
-			((word & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN) != 0);
-		config->basicvirtual.ip6twotupen =
-			((word & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN) != 0);
-		config->basicvirtual.ip4fourtupen =
-			((word & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN) != 0);
-		config->basicvirtual.ip4twotupen =
-			((word & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN) != 0);
-		config->basicvirtual.udpen =
-			((word & FW_RSS_VI_CONFIG_CMD_UDPEN) != 0);
-		config->basicvirtual.defaultq =
-			FW_RSS_VI_CONFIG_CMD_DEFAULTQ_GET(word);
-		break;
-	}
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/**
- *	t4vf_write_rss_vi_config - write a VI's RSS configuration
- *	@adapter: the adapter
- *	@viid: Virtual Interface ID
- *	@config: pointer to host-native VI RSS Configuration buffer
- *
- *	Write the Virtual Interface's RSS configuration information
- *	(translating it into firmware-native format before writing).
- */
-int t4vf_write_rss_vi_config(struct adapter *adapter, unsigned int viid,
-			     union rss_vi_config *config)
-{
-	struct fw_rss_vi_config_cmd cmd, rpl;
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_RSS_VI_CONFIG_CMD) |
-				     FW_CMD_REQUEST |
-				     FW_CMD_WRITE |
-				     FW_RSS_VI_CONFIG_CMD_VIID(viid));
-	cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
-	switch (adapter->params.rss.mode) {
-	case FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL: {
-		u32 word = 0;
-
-		if (config->basicvirtual.ip6fourtupen)
-			word |= FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN;
-		if (config->basicvirtual.ip6twotupen)
-			word |= FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN;
-		if (config->basicvirtual.ip4fourtupen)
-			word |= FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN;
-		if (config->basicvirtual.ip4twotupen)
-			word |= FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN;
-		if (config->basicvirtual.udpen)
-			word |= FW_RSS_VI_CONFIG_CMD_UDPEN;
-		word |= FW_RSS_VI_CONFIG_CMD_DEFAULTQ(
-				config->basicvirtual.defaultq);
-		cmd.u.basicvirtual.defaultq_to_udpen = cpu_to_be32(word);
-		break;
-	}
-
-	default:
-		return -EINVAL;
-	}
-
-	return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl);
-}
-
-/**
- *	t4vf_config_rss_range - configure a portion of the RSS mapping table
- *	@adapter: the adapter
- *	@viid: Virtual Interface of RSS Table Slice
- *	@start: starting entry in the table to write
- *	@n: how many table entries to write
- *	@rspq: values for the "Response Queue" (Ingress Queue) lookup table
- *	@nrspq: number of values in @rspq
- *
- *	Programs the selected part of the VI's RSS mapping table with the
- *	provided values.  If @nrspq < @n the supplied values are used repeatedly
- *	until the full table range is populated.
- *
- *	The caller must ensure the values in @rspq are in the range 0..1023.
- */
-int t4vf_config_rss_range(struct adapter *adapter, unsigned int viid,
-			  int start, int n, const u16 *rspq, int nrspq)
-{
-	const u16 *rsp = rspq;
-	const u16 *rsp_end = rspq+nrspq;
-	struct fw_rss_ind_tbl_cmd cmd;
-
-	/*
-	 * Initialize firmware command template to write the RSS table.
-	 */
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_RSS_IND_TBL_CMD) |
-				     FW_CMD_REQUEST |
-				     FW_CMD_WRITE |
-				     FW_RSS_IND_TBL_CMD_VIID(viid));
-	cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
-
-	/*
-	 * Each firmware RSS command can accommodate up to 32 RSS Ingress
-	 * Queue Identifiers.  These Ingress Queue IDs are packed three to
-	 * a 32-bit word as 10-bit values with the upper remaining 2 bits
-	 * reserved.
-	 */
-	while (n > 0) {
-		__be32 *qp = &cmd.iq0_to_iq2;
-		int nq = min(n, 32);
-		int ret;
-
-		/*
-		 * Set up the firmware RSS command header to send the next
-		 * "nq" Ingress Queue IDs to the firmware.
-		 */
-		cmd.niqid = cpu_to_be16(nq);
-		cmd.startidx = cpu_to_be16(start);
-
-		/*
-		 * "nq" more done for the start of the next loop.
-		 */
-		start += nq;
-		n -= nq;
-
-		/*
-		 * While there are still Ingress Queue IDs to stuff into the
-		 * current firmware RSS command, retrieve them from the
-		 * Ingress Queue ID array and insert them into the command.
-		 */
-		while (nq > 0) {
-			/*
-			 * Grab up to the next 3 Ingress Queue IDs (wrapping
-			 * around the Ingress Queue ID array if necessary) and
-			 * insert them into the firmware RSS command at the
-			 * current 3-tuple position within the commad.
-			 */
-			u16 qbuf[3];
-			u16 *qbp = qbuf;
-			int nqbuf = min(3, nq);
-
-			nq -= nqbuf;
-			qbuf[0] = qbuf[1] = qbuf[2] = 0;
-			while (nqbuf) {
-				nqbuf--;
-				*qbp++ = *rsp++;
-				if (rsp >= rsp_end)
-					rsp = rspq;
-			}
-			*qp++ = cpu_to_be32(FW_RSS_IND_TBL_CMD_IQ0(qbuf[0]) |
-					    FW_RSS_IND_TBL_CMD_IQ1(qbuf[1]) |
-					    FW_RSS_IND_TBL_CMD_IQ2(qbuf[2]));
-		}
-
-		/*
-		 * Send this portion of the RRS table update to the firmware;
-		 * bail out on any errors.
-		 */
-		ret = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL);
-		if (ret)
-			return ret;
-	}
-	return 0;
-}
-
-/**
- *	t4vf_alloc_vi - allocate a virtual interface on a port
- *	@adapter: the adapter
- *	@port_id: physical port associated with the VI
- *
- *	Allocate a new Virtual Interface and bind it to the indicated
- *	physical port.  Return the new Virtual Interface Identifier on
- *	success, or a [negative] error number on failure.
- */
-int t4vf_alloc_vi(struct adapter *adapter, int port_id)
-{
-	struct fw_vi_cmd cmd, rpl;
-	int v;
-
-	/*
-	 * Execute a VI command to allocate Virtual Interface and return its
-	 * VIID.
-	 */
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_VI_CMD) |
-				    FW_CMD_REQUEST |
-				    FW_CMD_WRITE |
-				    FW_CMD_EXEC);
-	cmd.alloc_to_len16 = cpu_to_be32(FW_LEN16(cmd) |
-					 FW_VI_CMD_ALLOC);
-	cmd.portid_pkd = FW_VI_CMD_PORTID(port_id);
-	v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl);
-	if (v)
-		return v;
-
-	return FW_VI_CMD_VIID_GET(be16_to_cpu(rpl.type_viid));
-}
-
-/**
- *	t4vf_free_vi -- free a virtual interface
- *	@adapter: the adapter
- *	@viid: the virtual interface identifier
- *
- *	Free a previously allocated Virtual Interface.  Return an error on
- *	failure.
- */
-int t4vf_free_vi(struct adapter *adapter, int viid)
-{
-	struct fw_vi_cmd cmd;
-
-	/*
-	 * Execute a VI command to free the Virtual Interface.
-	 */
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_VI_CMD) |
-				    FW_CMD_REQUEST |
-				    FW_CMD_EXEC);
-	cmd.alloc_to_len16 = cpu_to_be32(FW_LEN16(cmd) |
-					 FW_VI_CMD_FREE);
-	cmd.type_viid = cpu_to_be16(FW_VI_CMD_VIID(viid));
-	return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL);
-}
-
-/**
- *	t4vf_enable_vi - enable/disable a virtual interface
- *	@adapter: the adapter
- *	@viid: the Virtual Interface ID
- *	@rx_en: 1=enable Rx, 0=disable Rx
- *	@tx_en: 1=enable Tx, 0=disable Tx
- *
- *	Enables/disables a virtual interface.
- */
-int t4vf_enable_vi(struct adapter *adapter, unsigned int viid,
-		   bool rx_en, bool tx_en)
-{
-	struct fw_vi_enable_cmd cmd;
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_ENABLE_CMD) |
-				     FW_CMD_REQUEST |
-				     FW_CMD_EXEC |
-				     FW_VI_ENABLE_CMD_VIID(viid));
-	cmd.ien_to_len16 = cpu_to_be32(FW_VI_ENABLE_CMD_IEN(rx_en) |
-				       FW_VI_ENABLE_CMD_EEN(tx_en) |
-				       FW_LEN16(cmd));
-	return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL);
-}
-
-/**
- *	t4vf_identify_port - identify a VI's port by blinking its LED
- *	@adapter: the adapter
- *	@viid: the Virtual Interface ID
- *	@nblinks: how many times to blink LED at 2.5 Hz
- *
- *	Identifies a VI's port by blinking its LED.
- */
-int t4vf_identify_port(struct adapter *adapter, unsigned int viid,
-		       unsigned int nblinks)
-{
-	struct fw_vi_enable_cmd cmd;
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_ENABLE_CMD) |
-				     FW_CMD_REQUEST |
-				     FW_CMD_EXEC |
-				     FW_VI_ENABLE_CMD_VIID(viid));
-	cmd.ien_to_len16 = cpu_to_be32(FW_VI_ENABLE_CMD_LED |
-				       FW_LEN16(cmd));
-	cmd.blinkdur = cpu_to_be16(nblinks);
-	return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL);
-}
-
-/**
- *	t4vf_set_rxmode - set Rx properties of a virtual interface
- *	@adapter: the adapter
- *	@viid: the VI id
- *	@mtu: the new MTU or -1 for no change
- *	@promisc: 1 to enable promiscuous mode, 0 to disable it, -1 no change
- *	@all_multi: 1 to enable all-multi mode, 0 to disable it, -1 no change
- *	@bcast: 1 to enable broadcast Rx, 0 to disable it, -1 no change
- *	@vlanex: 1 to enable hardware VLAN Tag extraction, 0 to disable it,
- *		-1 no change
- *
- *	Sets Rx properties of a virtual interface.
- */
-int t4vf_set_rxmode(struct adapter *adapter, unsigned int viid,
-		    int mtu, int promisc, int all_multi, int bcast, int vlanex,
-		    bool sleep_ok)
-{
-	struct fw_vi_rxmode_cmd cmd;
-
-	/* convert to FW values */
-	if (mtu < 0)
-		mtu = FW_VI_RXMODE_CMD_MTU_MASK;
-	if (promisc < 0)
-		promisc = FW_VI_RXMODE_CMD_PROMISCEN_MASK;
-	if (all_multi < 0)
-		all_multi = FW_VI_RXMODE_CMD_ALLMULTIEN_MASK;
-	if (bcast < 0)
-		bcast = FW_VI_RXMODE_CMD_BROADCASTEN_MASK;
-	if (vlanex < 0)
-		vlanex = FW_VI_RXMODE_CMD_VLANEXEN_MASK;
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_RXMODE_CMD) |
-				     FW_CMD_REQUEST |
-				     FW_CMD_WRITE |
-				     FW_VI_RXMODE_CMD_VIID(viid));
-	cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
-	cmd.mtu_to_vlanexen =
-		cpu_to_be32(FW_VI_RXMODE_CMD_MTU(mtu) |
-			    FW_VI_RXMODE_CMD_PROMISCEN(promisc) |
-			    FW_VI_RXMODE_CMD_ALLMULTIEN(all_multi) |
-			    FW_VI_RXMODE_CMD_BROADCASTEN(bcast) |
-			    FW_VI_RXMODE_CMD_VLANEXEN(vlanex));
-	return t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), NULL, sleep_ok);
-}
-
-/**
- *	t4vf_alloc_mac_filt - allocates exact-match filters for MAC addresses
- *	@adapter: the adapter
- *	@viid: the Virtual Interface Identifier
- *	@free: if true any existing filters for this VI id are first removed
- *	@naddr: the number of MAC addresses to allocate filters for (up to 7)
- *	@addr: the MAC address(es)
- *	@idx: where to store the index of each allocated filter
- *	@hash: pointer to hash address filter bitmap
- *	@sleep_ok: call is allowed to sleep
- *
- *	Allocates an exact-match filter for each of the supplied addresses and
- *	sets it to the corresponding address.  If @idx is not %NULL it should
- *	have at least @naddr entries, each of which will be set to the index of
- *	the filter allocated for the corresponding MAC address.  If a filter
- *	could not be allocated for an address its index is set to 0xffff.
- *	If @hash is not %NULL addresses that fail to allocate an exact filter
- *	are hashed and update the hash filter bitmap pointed at by @hash.
- *
- *	Returns a negative error number or the number of filters allocated.
- */
-int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free,
-			unsigned int naddr, const u8 **addr, u16 *idx,
-			u64 *hash, bool sleep_ok)
-{
-	int offset, ret = 0;
-	unsigned nfilters = 0;
-	unsigned int rem = naddr;
-	struct fw_vi_mac_cmd cmd, rpl;
-
-	if (naddr > FW_CLS_TCAM_NUM_ENTRIES)
-		return -EINVAL;
-
-	for (offset = 0; offset < naddr; /**/) {
-		unsigned int fw_naddr = (rem < ARRAY_SIZE(cmd.u.exact)
-					 ? rem
-					 : ARRAY_SIZE(cmd.u.exact));
-		size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
-						     u.exact[fw_naddr]), 16);
-		struct fw_vi_mac_exact *p;
-		int i;
-
-		memset(&cmd, 0, sizeof(cmd));
-		cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) |
-					     FW_CMD_REQUEST |
-					     FW_CMD_WRITE |
-					     (free ? FW_CMD_EXEC : 0) |
-					     FW_VI_MAC_CMD_VIID(viid));
-		cmd.freemacs_to_len16 =
-			cpu_to_be32(FW_VI_MAC_CMD_FREEMACS(free) |
-				    FW_CMD_LEN16(len16));
-
-		for (i = 0, p = cmd.u.exact; i < fw_naddr; i++, p++) {
-			p->valid_to_idx = cpu_to_be16(
-				FW_VI_MAC_CMD_VALID |
-				FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
-			memcpy(p->macaddr, addr[offset+i], sizeof(p->macaddr));
-		}
-
-
-		ret = t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), &rpl,
-					sleep_ok);
-		if (ret && ret != -ENOMEM)
-			break;
-
-		for (i = 0, p = rpl.u.exact; i < fw_naddr; i++, p++) {
-			u16 index = FW_VI_MAC_CMD_IDX_GET(
-				be16_to_cpu(p->valid_to_idx));
-
-			if (idx)
-				idx[offset+i] =
-					(index >= FW_CLS_TCAM_NUM_ENTRIES
-					 ? 0xffff
-					 : index);
-			if (index < FW_CLS_TCAM_NUM_ENTRIES)
-				nfilters++;
-			else if (hash)
-				*hash |= (1ULL << hash_mac_addr(addr[offset+i]));
-		}
-
-		free = false;
-		offset += fw_naddr;
-		rem -= fw_naddr;
-	}
-
-	/*
-	 * If there were no errors or we merely ran out of room in our MAC
-	 * address arena, return the number of filters actually written.
-	 */
-	if (ret == 0 || ret == -ENOMEM)
-		ret = nfilters;
-	return ret;
-}
-
-/**
- *	t4vf_change_mac - modifies the exact-match filter for a MAC address
- *	@adapter: the adapter
- *	@viid: the Virtual Interface ID
- *	@idx: index of existing filter for old value of MAC address, or -1
- *	@addr: the new MAC address value
- *	@persist: if idx < 0, the new MAC allocation should be persistent
- *
- *	Modifies an exact-match filter and sets it to the new MAC address.
- *	Note that in general it is not possible to modify the value of a given
- *	filter so the generic way to modify an address filter is to free the
- *	one being used by the old address value and allocate a new filter for
- *	the new address value.  @idx can be -1 if the address is a new
- *	addition.
- *
- *	Returns a negative error number or the index of the filter with the new
- *	MAC value.
- */
-int t4vf_change_mac(struct adapter *adapter, unsigned int viid,
-		    int idx, const u8 *addr, bool persist)
-{
-	int ret;
-	struct fw_vi_mac_cmd cmd, rpl;
-	struct fw_vi_mac_exact *p = &cmd.u.exact[0];
-	size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
-					     u.exact[1]), 16);
-
-	/*
-	 * If this is a new allocation, determine whether it should be
-	 * persistent (across a "freemacs" operation) or not.
-	 */
-	if (idx < 0)
-		idx = persist ? FW_VI_MAC_ADD_PERSIST_MAC : FW_VI_MAC_ADD_MAC;
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) |
-				     FW_CMD_REQUEST |
-				     FW_CMD_WRITE |
-				     FW_VI_MAC_CMD_VIID(viid));
-	cmd.freemacs_to_len16 = cpu_to_be32(FW_CMD_LEN16(len16));
-	p->valid_to_idx = cpu_to_be16(FW_VI_MAC_CMD_VALID |
-				      FW_VI_MAC_CMD_IDX(idx));
-	memcpy(p->macaddr, addr, sizeof(p->macaddr));
-
-	ret = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl);
-	if (ret == 0) {
-		p = &rpl.u.exact[0];
-		ret = FW_VI_MAC_CMD_IDX_GET(be16_to_cpu(p->valid_to_idx));
-		if (ret >= FW_CLS_TCAM_NUM_ENTRIES)
-			ret = -ENOMEM;
-	}
-	return ret;
-}
-
-/**
- *	t4vf_set_addr_hash - program the MAC inexact-match hash filter
- *	@adapter: the adapter
- *	@viid: the Virtual Interface Identifier
- *	@ucast: whether the hash filter should also match unicast addresses
- *	@vec: the value to be written to the hash filter
- *	@sleep_ok: call is allowed to sleep
- *
- *	Sets the 64-bit inexact-match hash filter for a virtual interface.
- */
-int t4vf_set_addr_hash(struct adapter *adapter, unsigned int viid,
-		       bool ucast, u64 vec, bool sleep_ok)
-{
-	struct fw_vi_mac_cmd cmd;
-	size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
-					     u.exact[0]), 16);
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) |
-				     FW_CMD_REQUEST |
-				     FW_CMD_WRITE |
-				     FW_VI_ENABLE_CMD_VIID(viid));
-	cmd.freemacs_to_len16 = cpu_to_be32(FW_VI_MAC_CMD_HASHVECEN |
-					    FW_VI_MAC_CMD_HASHUNIEN(ucast) |
-					    FW_CMD_LEN16(len16));
-	cmd.u.hash.hashvec = cpu_to_be64(vec);
-	return t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), NULL, sleep_ok);
-}
-
-/**
- *	t4vf_get_port_stats - collect "port" statistics
- *	@adapter: the adapter
- *	@pidx: the port index
- *	@s: the stats structure to fill
- *
- *	Collect statistics for the "port"'s Virtual Interface.
- */
-int t4vf_get_port_stats(struct adapter *adapter, int pidx,
-			struct t4vf_port_stats *s)
-{
-	struct port_info *pi = adap2pinfo(adapter, pidx);
-	struct fw_vi_stats_vf fwstats;
-	unsigned int rem = VI_VF_NUM_STATS;
-	__be64 *fwsp = (__be64 *)&fwstats;
-
-	/*
-	 * Grab the Virtual Interface statistics a chunk at a time via mailbox
-	 * commands.  We could use a Work Request and get all of them at once
-	 * but that's an asynchronous interface which is awkward to use.
-	 */
-	while (rem) {
-		unsigned int ix = VI_VF_NUM_STATS - rem;
-		unsigned int nstats = min(6U, rem);
-		struct fw_vi_stats_cmd cmd, rpl;
-		size_t len = (offsetof(struct fw_vi_stats_cmd, u) +
-			      sizeof(struct fw_vi_stats_ctl));
-		size_t len16 = DIV_ROUND_UP(len, 16);
-		int ret;
-
-		memset(&cmd, 0, sizeof(cmd));
-		cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_STATS_CMD) |
-					     FW_VI_STATS_CMD_VIID(pi->viid) |
-					     FW_CMD_REQUEST |
-					     FW_CMD_READ);
-		cmd.retval_len16 = cpu_to_be32(FW_CMD_LEN16(len16));
-		cmd.u.ctl.nstats_ix =
-			cpu_to_be16(FW_VI_STATS_CMD_IX(ix) |
-				    FW_VI_STATS_CMD_NSTATS(nstats));
-		ret = t4vf_wr_mbox_ns(adapter, &cmd, len, &rpl);
-		if (ret)
-			return ret;
-
-		memcpy(fwsp, &rpl.u.ctl.stat0, sizeof(__be64) * nstats);
-
-		rem -= nstats;
-		fwsp += nstats;
-	}
-
-	/*
-	 * Translate firmware statistics into host native statistics.
-	 */
-	s->tx_bcast_bytes = be64_to_cpu(fwstats.tx_bcast_bytes);
-	s->tx_bcast_frames = be64_to_cpu(fwstats.tx_bcast_frames);
-	s->tx_mcast_bytes = be64_to_cpu(fwstats.tx_mcast_bytes);
-	s->tx_mcast_frames = be64_to_cpu(fwstats.tx_mcast_frames);
-	s->tx_ucast_bytes = be64_to_cpu(fwstats.tx_ucast_bytes);
-	s->tx_ucast_frames = be64_to_cpu(fwstats.tx_ucast_frames);
-	s->tx_drop_frames = be64_to_cpu(fwstats.tx_drop_frames);
-	s->tx_offload_bytes = be64_to_cpu(fwstats.tx_offload_bytes);
-	s->tx_offload_frames = be64_to_cpu(fwstats.tx_offload_frames);
-
-	s->rx_bcast_bytes = be64_to_cpu(fwstats.rx_bcast_bytes);
-	s->rx_bcast_frames = be64_to_cpu(fwstats.rx_bcast_frames);
-	s->rx_mcast_bytes = be64_to_cpu(fwstats.rx_mcast_bytes);
-	s->rx_mcast_frames = be64_to_cpu(fwstats.rx_mcast_frames);
-	s->rx_ucast_bytes = be64_to_cpu(fwstats.rx_ucast_bytes);
-	s->rx_ucast_frames = be64_to_cpu(fwstats.rx_ucast_frames);
-
-	s->rx_err_frames = be64_to_cpu(fwstats.rx_err_frames);
-
-	return 0;
-}
-
-/**
- *	t4vf_iq_free - free an ingress queue and its free lists
- *	@adapter: the adapter
- *	@iqtype: the ingress queue type (FW_IQ_TYPE_FL_INT_CAP, etc.)
- *	@iqid: ingress queue ID
- *	@fl0id: FL0 queue ID or 0xffff if no attached FL0
- *	@fl1id: FL1 queue ID or 0xffff if no attached FL1
- *
- *	Frees an ingress queue and its associated free lists, if any.
- */
-int t4vf_iq_free(struct adapter *adapter, unsigned int iqtype,
-		 unsigned int iqid, unsigned int fl0id, unsigned int fl1id)
-{
-	struct fw_iq_cmd cmd;
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_IQ_CMD) |
-				    FW_CMD_REQUEST |
-				    FW_CMD_EXEC);
-	cmd.alloc_to_len16 = cpu_to_be32(FW_IQ_CMD_FREE |
-					 FW_LEN16(cmd));
-	cmd.type_to_iqandstindex =
-		cpu_to_be32(FW_IQ_CMD_TYPE(iqtype));
-
-	cmd.iqid = cpu_to_be16(iqid);
-	cmd.fl0id = cpu_to_be16(fl0id);
-	cmd.fl1id = cpu_to_be16(fl1id);
-	return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL);
-}
-
-/**
- *	t4vf_eth_eq_free - free an Ethernet egress queue
- *	@adapter: the adapter
- *	@eqid: egress queue ID
- *
- *	Frees an Ethernet egress queue.
- */
-int t4vf_eth_eq_free(struct adapter *adapter, unsigned int eqid)
-{
-	struct fw_eq_eth_cmd cmd;
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_EQ_ETH_CMD) |
-				    FW_CMD_REQUEST |
-				    FW_CMD_EXEC);
-	cmd.alloc_to_len16 = cpu_to_be32(FW_EQ_ETH_CMD_FREE |
-					 FW_LEN16(cmd));
-	cmd.eqid_pkd = cpu_to_be32(FW_EQ_ETH_CMD_EQID(eqid));
-	return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL);
-}
-
-/**
- *	t4vf_handle_fw_rpl - process a firmware reply message
- *	@adapter: the adapter
- *	@rpl: start of the firmware message
- *
- *	Processes a firmware message, such as link state change messages.
- */
-int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl)
-{
-	const struct fw_cmd_hdr *cmd_hdr = (const struct fw_cmd_hdr *)rpl;
-	u8 opcode = FW_CMD_OP_GET(be32_to_cpu(cmd_hdr->hi));
-
-	switch (opcode) {
-	case FW_PORT_CMD: {
-		/*
-		 * Link/module state change message.
-		 */
-		const struct fw_port_cmd *port_cmd =
-			(const struct fw_port_cmd *)rpl;
-		u32 word;
-		int action, port_id, link_ok, speed, fc, pidx;
-
-		/*
-		 * Extract various fields from port status change message.
-		 */
-		action = FW_PORT_CMD_ACTION_GET(
-			be32_to_cpu(port_cmd->action_to_len16));
-		if (action != FW_PORT_ACTION_GET_PORT_INFO) {
-			dev_err(adapter->pdev_dev,
-				"Unknown firmware PORT reply action %x\n",
-				action);
-			break;
-		}
-
-		port_id = FW_PORT_CMD_PORTID_GET(
-			be32_to_cpu(port_cmd->op_to_portid));
-
-		word = be32_to_cpu(port_cmd->u.info.lstatus_to_modtype);
-		link_ok = (word & FW_PORT_CMD_LSTATUS) != 0;
-		speed = 0;
-		fc = 0;
-		if (word & FW_PORT_CMD_RXPAUSE)
-			fc |= PAUSE_RX;
-		if (word & FW_PORT_CMD_TXPAUSE)
-			fc |= PAUSE_TX;
-		if (word & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100M))
-			speed = SPEED_100;
-		else if (word & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_1G))
-			speed = SPEED_1000;
-		else if (word & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G))
-			speed = SPEED_10000;
-
-		/*
-		 * Scan all of our "ports" (Virtual Interfaces) looking for
-		 * those bound to the physical port which has changed.  If
-		 * our recorded state doesn't match the current state,
-		 * signal that change to the OS code.
-		 */
-		for_each_port(adapter, pidx) {
-			struct port_info *pi = adap2pinfo(adapter, pidx);
-			struct link_config *lc;
-
-			if (pi->port_id != port_id)
-				continue;
-
-			lc = &pi->link_cfg;
-			if (link_ok != lc->link_ok || speed != lc->speed ||
-			    fc != lc->fc) {
-				/* something changed */
-				lc->link_ok = link_ok;
-				lc->speed = speed;
-				lc->fc = fc;
-				t4vf_os_link_changed(adapter, pidx, link_ok);
-			}
-		}
-		break;
-	}
-
-	default:
-		dev_err(adapter->pdev_dev, "Unknown firmware reply %X\n",
-			opcode);
-	}
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/davinci_cpdma.c linux-libre-3.2-gnu/drivers/net/davinci_cpdma.c
--- linux-libre-3.1-gnu/drivers/net/davinci_cpdma.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/davinci_cpdma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,970 +0,0 @@
-/*
- * Texas Instruments CPDMA Driver
- *
- * Copyright (C) 2010 Texas Instruments
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation 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/spinlock.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/dma-mapping.h>
-#include <linux/io.h>
-
-#include "davinci_cpdma.h"
-
-/* DMA Registers */
-#define CPDMA_TXIDVER		0x00
-#define CPDMA_TXCONTROL		0x04
-#define CPDMA_TXTEARDOWN	0x08
-#define CPDMA_RXIDVER		0x10
-#define CPDMA_RXCONTROL		0x14
-#define CPDMA_SOFTRESET		0x1c
-#define CPDMA_RXTEARDOWN	0x18
-#define CPDMA_TXINTSTATRAW	0x80
-#define CPDMA_TXINTSTATMASKED	0x84
-#define CPDMA_TXINTMASKSET	0x88
-#define CPDMA_TXINTMASKCLEAR	0x8c
-#define CPDMA_MACINVECTOR	0x90
-#define CPDMA_MACEOIVECTOR	0x94
-#define CPDMA_RXINTSTATRAW	0xa0
-#define CPDMA_RXINTSTATMASKED	0xa4
-#define CPDMA_RXINTMASKSET	0xa8
-#define CPDMA_RXINTMASKCLEAR	0xac
-#define CPDMA_DMAINTSTATRAW	0xb0
-#define CPDMA_DMAINTSTATMASKED	0xb4
-#define CPDMA_DMAINTMASKSET	0xb8
-#define CPDMA_DMAINTMASKCLEAR	0xbc
-#define CPDMA_DMAINT_HOSTERR	BIT(1)
-
-/* the following exist only if has_ext_regs is set */
-#define CPDMA_DMACONTROL	0x20
-#define CPDMA_DMASTATUS		0x24
-#define CPDMA_RXBUFFOFS		0x28
-#define CPDMA_EM_CONTROL	0x2c
-
-/* Descriptor mode bits */
-#define CPDMA_DESC_SOP		BIT(31)
-#define CPDMA_DESC_EOP		BIT(30)
-#define CPDMA_DESC_OWNER	BIT(29)
-#define CPDMA_DESC_EOQ		BIT(28)
-#define CPDMA_DESC_TD_COMPLETE	BIT(27)
-#define CPDMA_DESC_PASS_CRC	BIT(26)
-
-#define CPDMA_TEARDOWN_VALUE	0xfffffffc
-
-struct cpdma_desc {
-	/* hardware fields */
-	u32			hw_next;
-	u32			hw_buffer;
-	u32			hw_len;
-	u32			hw_mode;
-	/* software fields */
-	void			*sw_token;
-	u32			sw_buffer;
-	u32			sw_len;
-};
-
-struct cpdma_desc_pool {
-	u32			phys;
-	u32			hw_addr;
-	void __iomem		*iomap;		/* ioremap map */
-	void			*cpumap;	/* dma_alloc map */
-	int			desc_size, mem_size;
-	int			num_desc, used_desc;
-	unsigned long		*bitmap;
-	struct device		*dev;
-	spinlock_t		lock;
-};
-
-enum cpdma_state {
-	CPDMA_STATE_IDLE,
-	CPDMA_STATE_ACTIVE,
-	CPDMA_STATE_TEARDOWN,
-};
-
-const char *cpdma_state_str[] = { "idle", "active", "teardown" };
-
-struct cpdma_ctlr {
-	enum cpdma_state	state;
-	struct cpdma_params	params;
-	struct device		*dev;
-	struct cpdma_desc_pool	*pool;
-	spinlock_t		lock;
-	struct cpdma_chan	*channels[2 * CPDMA_MAX_CHANNELS];
-};
-
-struct cpdma_chan {
-	enum cpdma_state		state;
-	struct cpdma_ctlr		*ctlr;
-	int				chan_num;
-	spinlock_t			lock;
-	struct cpdma_desc __iomem	*head, *tail;
-	int				count;
-	void __iomem			*hdp, *cp, *rxfree;
-	u32				mask;
-	cpdma_handler_fn		handler;
-	enum dma_data_direction		dir;
-	struct cpdma_chan_stats		stats;
-	/* offsets into dmaregs */
-	int	int_set, int_clear, td;
-};
-
-/* The following make access to common cpdma_ctlr params more readable */
-#define dmaregs		params.dmaregs
-#define num_chan	params.num_chan
-
-/* various accessors */
-#define dma_reg_read(ctlr, ofs)		__raw_readl((ctlr)->dmaregs + (ofs))
-#define chan_read(chan, fld)		__raw_readl((chan)->fld)
-#define desc_read(desc, fld)		__raw_readl(&(desc)->fld)
-#define dma_reg_write(ctlr, ofs, v)	__raw_writel(v, (ctlr)->dmaregs + (ofs))
-#define chan_write(chan, fld, v)	__raw_writel(v, (chan)->fld)
-#define desc_write(desc, fld, v)	__raw_writel((u32)(v), &(desc)->fld)
-
-/*
- * Utility constructs for a cpdma descriptor pool.  Some devices (e.g. davinci
- * emac) have dedicated on-chip memory for these descriptors.  Some other
- * devices (e.g. cpsw switches) use plain old memory.  Descriptor pools
- * abstract out these details
- */
-static struct cpdma_desc_pool *
-cpdma_desc_pool_create(struct device *dev, u32 phys, u32 hw_addr,
-				int size, int align)
-{
-	int bitmap_size;
-	struct cpdma_desc_pool *pool;
-
-	pool = kzalloc(sizeof(*pool), GFP_KERNEL);
-	if (!pool)
-		return NULL;
-
-	spin_lock_init(&pool->lock);
-
-	pool->dev	= dev;
-	pool->mem_size	= size;
-	pool->desc_size	= ALIGN(sizeof(struct cpdma_desc), align);
-	pool->num_desc	= size / pool->desc_size;
-
-	bitmap_size  = (pool->num_desc / BITS_PER_LONG) * sizeof(long);
-	pool->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-	if (!pool->bitmap)
-		goto fail;
-
-	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 = pool->cpumap;
-		pool->hw_addr = pool->phys;
-	}
-
-	if (pool->iomap)
-		return pool;
-
-fail:
-	kfree(pool->bitmap);
-	kfree(pool);
-	return NULL;
-}
-
-static void cpdma_desc_pool_destroy(struct cpdma_desc_pool *pool)
-{
-	unsigned long flags;
-
-	if (!pool)
-		return;
-
-	spin_lock_irqsave(&pool->lock, flags);
-	WARN_ON(pool->used_desc);
-	kfree(pool->bitmap);
-	if (pool->cpumap) {
-		dma_free_coherent(pool->dev, pool->mem_size, pool->cpumap,
-				  pool->phys);
-	} else {
-		iounmap(pool->iomap);
-	}
-	spin_unlock_irqrestore(&pool->lock, flags);
-	kfree(pool);
-}
-
-static inline dma_addr_t desc_phys(struct cpdma_desc_pool *pool,
-		  struct cpdma_desc __iomem *desc)
-{
-	if (!desc)
-		return 0;
-	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->hw_addr : NULL;
-}
-
-static struct cpdma_desc __iomem *
-cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc)
-{
-	unsigned long flags;
-	int index;
-	struct cpdma_desc __iomem *desc = NULL;
-
-	spin_lock_irqsave(&pool->lock, flags);
-
-	index = bitmap_find_next_zero_area(pool->bitmap, pool->num_desc, 0,
-					   num_desc, 0);
-	if (index < pool->num_desc) {
-		bitmap_set(pool->bitmap, index, num_desc);
-		desc = pool->iomap + pool->desc_size * index;
-		pool->used_desc++;
-	}
-
-	spin_unlock_irqrestore(&pool->lock, flags);
-	return desc;
-}
-
-static void cpdma_desc_free(struct cpdma_desc_pool *pool,
-			    struct cpdma_desc __iomem *desc, int num_desc)
-{
-	unsigned long flags, index;
-
-	index = ((unsigned long)desc - (unsigned long)pool->iomap) /
-		pool->desc_size;
-	spin_lock_irqsave(&pool->lock, flags);
-	bitmap_clear(pool->bitmap, index, num_desc);
-	pool->used_desc--;
-	spin_unlock_irqrestore(&pool->lock, flags);
-}
-
-struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params)
-{
-	struct cpdma_ctlr *ctlr;
-
-	ctlr = kzalloc(sizeof(*ctlr), GFP_KERNEL);
-	if (!ctlr)
-		return NULL;
-
-	ctlr->state = CPDMA_STATE_IDLE;
-	ctlr->params = *params;
-	ctlr->dev = params->dev;
-	spin_lock_init(&ctlr->lock);
-
-	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) {
-		kfree(ctlr);
-		return NULL;
-	}
-
-	if (WARN_ON(ctlr->num_chan > CPDMA_MAX_CHANNELS))
-		ctlr->num_chan = CPDMA_MAX_CHANNELS;
-	return ctlr;
-}
-
-int cpdma_ctlr_start(struct cpdma_ctlr *ctlr)
-{
-	unsigned long flags;
-	int i;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-	if (ctlr->state != CPDMA_STATE_IDLE) {
-		spin_unlock_irqrestore(&ctlr->lock, flags);
-		return -EBUSY;
-	}
-
-	if (ctlr->params.has_soft_reset) {
-		unsigned long timeout = jiffies + HZ/10;
-
-		dma_reg_write(ctlr, CPDMA_SOFTRESET, 1);
-		while (time_before(jiffies, timeout)) {
-			if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0)
-				break;
-		}
-		WARN_ON(!time_before(jiffies, timeout));
-	}
-
-	for (i = 0; i < ctlr->num_chan; i++) {
-		__raw_writel(0, ctlr->params.txhdp + 4 * i);
-		__raw_writel(0, ctlr->params.rxhdp + 4 * i);
-		__raw_writel(0, ctlr->params.txcp + 4 * i);
-		__raw_writel(0, ctlr->params.rxcp + 4 * i);
-	}
-
-	dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff);
-	dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff);
-
-	dma_reg_write(ctlr, CPDMA_TXCONTROL, 1);
-	dma_reg_write(ctlr, CPDMA_RXCONTROL, 1);
-
-	ctlr->state = CPDMA_STATE_ACTIVE;
-
-	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
-		if (ctlr->channels[i])
-			cpdma_chan_start(ctlr->channels[i]);
-	}
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-	return 0;
-}
-
-int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)
-{
-	unsigned long flags;
-	int i;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-	if (ctlr->state != CPDMA_STATE_ACTIVE) {
-		spin_unlock_irqrestore(&ctlr->lock, flags);
-		return -EINVAL;
-	}
-
-	ctlr->state = CPDMA_STATE_TEARDOWN;
-
-	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
-		if (ctlr->channels[i])
-			cpdma_chan_stop(ctlr->channels[i]);
-	}
-
-	dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff);
-	dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff);
-
-	dma_reg_write(ctlr, CPDMA_TXCONTROL, 0);
-	dma_reg_write(ctlr, CPDMA_RXCONTROL, 0);
-
-	ctlr->state = CPDMA_STATE_IDLE;
-
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-	return 0;
-}
-
-int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr)
-{
-	struct device *dev = ctlr->dev;
-	unsigned long flags;
-	int i;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-
-	dev_info(dev, "CPDMA: state: %s", cpdma_state_str[ctlr->state]);
-
-	dev_info(dev, "CPDMA: txidver: %x",
-		 dma_reg_read(ctlr, CPDMA_TXIDVER));
-	dev_info(dev, "CPDMA: txcontrol: %x",
-		 dma_reg_read(ctlr, CPDMA_TXCONTROL));
-	dev_info(dev, "CPDMA: txteardown: %x",
-		 dma_reg_read(ctlr, CPDMA_TXTEARDOWN));
-	dev_info(dev, "CPDMA: rxidver: %x",
-		 dma_reg_read(ctlr, CPDMA_RXIDVER));
-	dev_info(dev, "CPDMA: rxcontrol: %x",
-		 dma_reg_read(ctlr, CPDMA_RXCONTROL));
-	dev_info(dev, "CPDMA: softreset: %x",
-		 dma_reg_read(ctlr, CPDMA_SOFTRESET));
-	dev_info(dev, "CPDMA: rxteardown: %x",
-		 dma_reg_read(ctlr, CPDMA_RXTEARDOWN));
-	dev_info(dev, "CPDMA: txintstatraw: %x",
-		 dma_reg_read(ctlr, CPDMA_TXINTSTATRAW));
-	dev_info(dev, "CPDMA: txintstatmasked: %x",
-		 dma_reg_read(ctlr, CPDMA_TXINTSTATMASKED));
-	dev_info(dev, "CPDMA: txintmaskset: %x",
-		 dma_reg_read(ctlr, CPDMA_TXINTMASKSET));
-	dev_info(dev, "CPDMA: txintmaskclear: %x",
-		 dma_reg_read(ctlr, CPDMA_TXINTMASKCLEAR));
-	dev_info(dev, "CPDMA: macinvector: %x",
-		 dma_reg_read(ctlr, CPDMA_MACINVECTOR));
-	dev_info(dev, "CPDMA: maceoivector: %x",
-		 dma_reg_read(ctlr, CPDMA_MACEOIVECTOR));
-	dev_info(dev, "CPDMA: rxintstatraw: %x",
-		 dma_reg_read(ctlr, CPDMA_RXINTSTATRAW));
-	dev_info(dev, "CPDMA: rxintstatmasked: %x",
-		 dma_reg_read(ctlr, CPDMA_RXINTSTATMASKED));
-	dev_info(dev, "CPDMA: rxintmaskset: %x",
-		 dma_reg_read(ctlr, CPDMA_RXINTMASKSET));
-	dev_info(dev, "CPDMA: rxintmaskclear: %x",
-		 dma_reg_read(ctlr, CPDMA_RXINTMASKCLEAR));
-	dev_info(dev, "CPDMA: dmaintstatraw: %x",
-		 dma_reg_read(ctlr, CPDMA_DMAINTSTATRAW));
-	dev_info(dev, "CPDMA: dmaintstatmasked: %x",
-		 dma_reg_read(ctlr, CPDMA_DMAINTSTATMASKED));
-	dev_info(dev, "CPDMA: dmaintmaskset: %x",
-		 dma_reg_read(ctlr, CPDMA_DMAINTMASKSET));
-	dev_info(dev, "CPDMA: dmaintmaskclear: %x",
-		 dma_reg_read(ctlr, CPDMA_DMAINTMASKCLEAR));
-
-	if (!ctlr->params.has_ext_regs) {
-		dev_info(dev, "CPDMA: dmacontrol: %x",
-			 dma_reg_read(ctlr, CPDMA_DMACONTROL));
-		dev_info(dev, "CPDMA: dmastatus: %x",
-			 dma_reg_read(ctlr, CPDMA_DMASTATUS));
-		dev_info(dev, "CPDMA: rxbuffofs: %x",
-			 dma_reg_read(ctlr, CPDMA_RXBUFFOFS));
-	}
-
-	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++)
-		if (ctlr->channels[i])
-			cpdma_chan_dump(ctlr->channels[i]);
-
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-	return 0;
-}
-
-int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)
-{
-	unsigned long flags;
-	int ret = 0, i;
-
-	if (!ctlr)
-		return -EINVAL;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-	if (ctlr->state != CPDMA_STATE_IDLE)
-		cpdma_ctlr_stop(ctlr);
-
-	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
-		if (ctlr->channels[i])
-			cpdma_chan_destroy(ctlr->channels[i]);
-	}
-
-	cpdma_desc_pool_destroy(ctlr->pool);
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-	kfree(ctlr);
-	return ret;
-}
-
-int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
-{
-	unsigned long flags;
-	int i, reg;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-	if (ctlr->state != CPDMA_STATE_ACTIVE) {
-		spin_unlock_irqrestore(&ctlr->lock, flags);
-		return -EINVAL;
-	}
-
-	reg = enable ? CPDMA_DMAINTMASKSET : CPDMA_DMAINTMASKCLEAR;
-	dma_reg_write(ctlr, reg, CPDMA_DMAINT_HOSTERR);
-
-	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
-		if (ctlr->channels[i])
-			cpdma_chan_int_ctrl(ctlr->channels[i], enable);
-	}
-
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-	return 0;
-}
-
-void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr)
-{
-	dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0);
-}
-
-struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
-				     cpdma_handler_fn handler)
-{
-	struct cpdma_chan *chan;
-	int ret, offset = (chan_num % CPDMA_MAX_CHANNELS) * 4;
-	unsigned long flags;
-
-	if (__chan_linear(chan_num) >= ctlr->num_chan)
-		return NULL;
-
-	ret = -ENOMEM;
-	chan = kzalloc(sizeof(*chan), GFP_KERNEL);
-	if (!chan)
-		goto err_chan_alloc;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-	ret = -EBUSY;
-	if (ctlr->channels[chan_num])
-		goto err_chan_busy;
-
-	chan->ctlr	= ctlr;
-	chan->state	= CPDMA_STATE_IDLE;
-	chan->chan_num	= chan_num;
-	chan->handler	= handler;
-
-	if (is_rx_chan(chan)) {
-		chan->hdp	= ctlr->params.rxhdp + offset;
-		chan->cp	= ctlr->params.rxcp + offset;
-		chan->rxfree	= ctlr->params.rxfree + offset;
-		chan->int_set	= CPDMA_RXINTMASKSET;
-		chan->int_clear	= CPDMA_RXINTMASKCLEAR;
-		chan->td	= CPDMA_RXTEARDOWN;
-		chan->dir	= DMA_FROM_DEVICE;
-	} else {
-		chan->hdp	= ctlr->params.txhdp + offset;
-		chan->cp	= ctlr->params.txcp + offset;
-		chan->int_set	= CPDMA_TXINTMASKSET;
-		chan->int_clear	= CPDMA_TXINTMASKCLEAR;
-		chan->td	= CPDMA_TXTEARDOWN;
-		chan->dir	= DMA_TO_DEVICE;
-	}
-	chan->mask = BIT(chan_linear(chan));
-
-	spin_lock_init(&chan->lock);
-
-	ctlr->channels[chan_num] = chan;
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-	return chan;
-
-err_chan_busy:
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-	kfree(chan);
-err_chan_alloc:
-	return ERR_PTR(ret);
-}
-
-int cpdma_chan_destroy(struct cpdma_chan *chan)
-{
-	struct cpdma_ctlr *ctlr = chan->ctlr;
-	unsigned long flags;
-
-	if (!chan)
-		return -EINVAL;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-	if (chan->state != CPDMA_STATE_IDLE)
-		cpdma_chan_stop(chan);
-	ctlr->channels[chan->chan_num] = NULL;
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-	kfree(chan);
-	return 0;
-}
-
-int cpdma_chan_get_stats(struct cpdma_chan *chan,
-			 struct cpdma_chan_stats *stats)
-{
-	unsigned long flags;
-	if (!chan)
-		return -EINVAL;
-	spin_lock_irqsave(&chan->lock, flags);
-	memcpy(stats, &chan->stats, sizeof(*stats));
-	spin_unlock_irqrestore(&chan->lock, flags);
-	return 0;
-}
-
-int cpdma_chan_dump(struct cpdma_chan *chan)
-{
-	unsigned long flags;
-	struct device *dev = chan->ctlr->dev;
-
-	spin_lock_irqsave(&chan->lock, flags);
-
-	dev_info(dev, "channel %d (%s %d) state %s",
-		 chan->chan_num, is_rx_chan(chan) ? "rx" : "tx",
-		 chan_linear(chan), cpdma_state_str[chan->state]);
-	dev_info(dev, "\thdp: %x\n", chan_read(chan, hdp));
-	dev_info(dev, "\tcp: %x\n", chan_read(chan, cp));
-	if (chan->rxfree) {
-		dev_info(dev, "\trxfree: %x\n",
-			 chan_read(chan, rxfree));
-	}
-
-	dev_info(dev, "\tstats head_enqueue: %d\n",
-		 chan->stats.head_enqueue);
-	dev_info(dev, "\tstats tail_enqueue: %d\n",
-		 chan->stats.tail_enqueue);
-	dev_info(dev, "\tstats pad_enqueue: %d\n",
-		 chan->stats.pad_enqueue);
-	dev_info(dev, "\tstats misqueued: %d\n",
-		 chan->stats.misqueued);
-	dev_info(dev, "\tstats desc_alloc_fail: %d\n",
-		 chan->stats.desc_alloc_fail);
-	dev_info(dev, "\tstats pad_alloc_fail: %d\n",
-		 chan->stats.pad_alloc_fail);
-	dev_info(dev, "\tstats runt_receive_buff: %d\n",
-		 chan->stats.runt_receive_buff);
-	dev_info(dev, "\tstats runt_transmit_buff: %d\n",
-		 chan->stats.runt_transmit_buff);
-	dev_info(dev, "\tstats empty_dequeue: %d\n",
-		 chan->stats.empty_dequeue);
-	dev_info(dev, "\tstats busy_dequeue: %d\n",
-		 chan->stats.busy_dequeue);
-	dev_info(dev, "\tstats good_dequeue: %d\n",
-		 chan->stats.good_dequeue);
-	dev_info(dev, "\tstats requeue: %d\n",
-		 chan->stats.requeue);
-	dev_info(dev, "\tstats teardown_dequeue: %d\n",
-		 chan->stats.teardown_dequeue);
-
-	spin_unlock_irqrestore(&chan->lock, flags);
-	return 0;
-}
-
-static void __cpdma_chan_submit(struct cpdma_chan *chan,
-				struct cpdma_desc __iomem *desc)
-{
-	struct cpdma_ctlr		*ctlr = chan->ctlr;
-	struct cpdma_desc __iomem	*prev = chan->tail;
-	struct cpdma_desc_pool		*pool = ctlr->pool;
-	dma_addr_t			desc_dma;
-	u32				mode;
-
-	desc_dma = desc_phys(pool, desc);
-
-	/* simple case - idle channel */
-	if (!chan->head) {
-		chan->stats.head_enqueue++;
-		chan->head = desc;
-		chan->tail = desc;
-		if (chan->state == CPDMA_STATE_ACTIVE)
-			chan_write(chan, hdp, desc_dma);
-		return;
-	}
-
-	/* first chain the descriptor at the tail of the list */
-	desc_write(prev, hw_next, desc_dma);
-	chan->tail = desc;
-	chan->stats.tail_enqueue++;
-
-	/* next check if EOQ has been triggered already */
-	mode = desc_read(prev, hw_mode);
-	if (((mode & (CPDMA_DESC_EOQ | CPDMA_DESC_OWNER)) == CPDMA_DESC_EOQ) &&
-	    (chan->state == CPDMA_STATE_ACTIVE)) {
-		desc_write(prev, hw_mode, mode & ~CPDMA_DESC_EOQ);
-		chan_write(chan, hdp, desc_dma);
-		chan->stats.misqueued++;
-	}
-}
-
-int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
-		      int len, gfp_t gfp_mask)
-{
-	struct cpdma_ctlr		*ctlr = chan->ctlr;
-	struct cpdma_desc __iomem	*desc;
-	dma_addr_t			buffer;
-	unsigned long			flags;
-	u32				mode;
-	int				ret = 0;
-
-	spin_lock_irqsave(&chan->lock, flags);
-
-	if (chan->state == CPDMA_STATE_TEARDOWN) {
-		ret = -EINVAL;
-		goto unlock_ret;
-	}
-
-	desc = cpdma_desc_alloc(ctlr->pool, 1);
-	if (!desc) {
-		chan->stats.desc_alloc_fail++;
-		ret = -ENOMEM;
-		goto unlock_ret;
-	}
-
-	if (len < ctlr->params.min_packet_size) {
-		len = ctlr->params.min_packet_size;
-		chan->stats.runt_transmit_buff++;
-	}
-
-	buffer = dma_map_single(ctlr->dev, data, len, chan->dir);
-	mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
-
-	desc_write(desc, hw_next,   0);
-	desc_write(desc, hw_buffer, buffer);
-	desc_write(desc, hw_len,    len);
-	desc_write(desc, hw_mode,   mode | len);
-	desc_write(desc, sw_token,  token);
-	desc_write(desc, sw_buffer, buffer);
-	desc_write(desc, sw_len,    len);
-
-	__cpdma_chan_submit(chan, desc);
-
-	if (chan->state == CPDMA_STATE_ACTIVE && chan->rxfree)
-		chan_write(chan, rxfree, 1);
-
-	chan->count++;
-
-unlock_ret:
-	spin_unlock_irqrestore(&chan->lock, flags);
-	return ret;
-}
-
-static void __cpdma_chan_free(struct cpdma_chan *chan,
-			      struct cpdma_desc __iomem *desc,
-			      int outlen, int status)
-{
-	struct cpdma_ctlr		*ctlr = chan->ctlr;
-	struct cpdma_desc_pool		*pool = ctlr->pool;
-	dma_addr_t			buff_dma;
-	int				origlen;
-	void				*token;
-
-	token      = (void *)desc_read(desc, sw_token);
-	buff_dma   = desc_read(desc, sw_buffer);
-	origlen    = desc_read(desc, sw_len);
-
-	dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir);
-	cpdma_desc_free(pool, desc, 1);
-	(*chan->handler)(token, outlen, status);
-}
-
-static int __cpdma_chan_process(struct cpdma_chan *chan)
-{
-	struct cpdma_ctlr		*ctlr = chan->ctlr;
-	struct cpdma_desc __iomem	*desc;
-	int				status, outlen;
-	struct cpdma_desc_pool		*pool = ctlr->pool;
-	dma_addr_t			desc_dma;
-	unsigned long			flags;
-
-	spin_lock_irqsave(&chan->lock, flags);
-
-	desc = chan->head;
-	if (!desc) {
-		chan->stats.empty_dequeue++;
-		status = -ENOENT;
-		goto unlock_ret;
-	}
-	desc_dma = desc_phys(pool, desc);
-
-	status	= __raw_readl(&desc->hw_mode);
-	outlen	= status & 0x7ff;
-	if (status & CPDMA_DESC_OWNER) {
-		chan->stats.busy_dequeue++;
-		status = -EBUSY;
-		goto unlock_ret;
-	}
-	status	= status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE);
-
-	chan->head = desc_from_phys(pool, desc_read(desc, hw_next));
-	chan_write(chan, cp, desc_dma);
-	chan->count--;
-	chan->stats.good_dequeue++;
-
-	if (status & CPDMA_DESC_EOQ) {
-		chan->stats.requeue++;
-		chan_write(chan, hdp, desc_phys(pool, chan->head));
-	}
-
-	spin_unlock_irqrestore(&chan->lock, flags);
-
-	__cpdma_chan_free(chan, desc, outlen, status);
-	return status;
-
-unlock_ret:
-	spin_unlock_irqrestore(&chan->lock, flags);
-	return status;
-}
-
-int cpdma_chan_process(struct cpdma_chan *chan, int quota)
-{
-	int used = 0, ret = 0;
-
-	if (chan->state != CPDMA_STATE_ACTIVE)
-		return -EINVAL;
-
-	while (used < quota) {
-		ret = __cpdma_chan_process(chan);
-		if (ret < 0)
-			break;
-		used++;
-	}
-	return used;
-}
-
-int cpdma_chan_start(struct cpdma_chan *chan)
-{
-	struct cpdma_ctlr	*ctlr = chan->ctlr;
-	struct cpdma_desc_pool	*pool = ctlr->pool;
-	unsigned long		flags;
-
-	spin_lock_irqsave(&chan->lock, flags);
-	if (chan->state != CPDMA_STATE_IDLE) {
-		spin_unlock_irqrestore(&chan->lock, flags);
-		return -EBUSY;
-	}
-	if (ctlr->state != CPDMA_STATE_ACTIVE) {
-		spin_unlock_irqrestore(&chan->lock, flags);
-		return -EINVAL;
-	}
-	dma_reg_write(ctlr, chan->int_set, chan->mask);
-	chan->state = CPDMA_STATE_ACTIVE;
-	if (chan->head) {
-		chan_write(chan, hdp, desc_phys(pool, chan->head));
-		if (chan->rxfree)
-			chan_write(chan, rxfree, chan->count);
-	}
-
-	spin_unlock_irqrestore(&chan->lock, flags);
-	return 0;
-}
-
-int cpdma_chan_stop(struct cpdma_chan *chan)
-{
-	struct cpdma_ctlr	*ctlr = chan->ctlr;
-	struct cpdma_desc_pool	*pool = ctlr->pool;
-	unsigned long		flags;
-	int			ret;
-	unsigned long		timeout;
-
-	spin_lock_irqsave(&chan->lock, flags);
-	if (chan->state != CPDMA_STATE_ACTIVE) {
-		spin_unlock_irqrestore(&chan->lock, flags);
-		return -EINVAL;
-	}
-
-	chan->state = CPDMA_STATE_TEARDOWN;
-	dma_reg_write(ctlr, chan->int_clear, chan->mask);
-
-	/* trigger teardown */
-	dma_reg_write(ctlr, chan->td, chan->chan_num);
-
-	/* wait for teardown complete */
-	timeout = jiffies + HZ/10;	/* 100 msec */
-	while (time_before(jiffies, timeout)) {
-		u32 cp = chan_read(chan, cp);
-		if ((cp & CPDMA_TEARDOWN_VALUE) == CPDMA_TEARDOWN_VALUE)
-			break;
-		cpu_relax();
-	}
-	WARN_ON(!time_before(jiffies, timeout));
-	chan_write(chan, cp, CPDMA_TEARDOWN_VALUE);
-
-	/* handle completed packets */
-	do {
-		ret = __cpdma_chan_process(chan);
-		if (ret < 0)
-			break;
-	} while ((ret & CPDMA_DESC_TD_COMPLETE) == 0);
-
-	/* remaining packets haven't been tx/rx'ed, clean them up */
-	while (chan->head) {
-		struct cpdma_desc __iomem *desc = chan->head;
-		dma_addr_t next_dma;
-
-		next_dma = desc_read(desc, hw_next);
-		chan->head = desc_from_phys(pool, next_dma);
-		chan->stats.teardown_dequeue++;
-
-		/* issue callback without locks held */
-		spin_unlock_irqrestore(&chan->lock, flags);
-		__cpdma_chan_free(chan, desc, 0, -ENOSYS);
-		spin_lock_irqsave(&chan->lock, flags);
-	}
-
-	chan->state = CPDMA_STATE_IDLE;
-	spin_unlock_irqrestore(&chan->lock, flags);
-	return 0;
-}
-
-int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&chan->lock, flags);
-	if (chan->state != CPDMA_STATE_ACTIVE) {
-		spin_unlock_irqrestore(&chan->lock, flags);
-		return -EINVAL;
-	}
-
-	dma_reg_write(chan->ctlr, enable ? chan->int_set : chan->int_clear,
-		      chan->mask);
-	spin_unlock_irqrestore(&chan->lock, flags);
-
-	return 0;
-}
-
-struct cpdma_control_info {
-	u32		reg;
-	u32		shift, mask;
-	int		access;
-#define ACCESS_RO	BIT(0)
-#define ACCESS_WO	BIT(1)
-#define ACCESS_RW	(ACCESS_RO | ACCESS_WO)
-};
-
-struct cpdma_control_info controls[] = {
-	[CPDMA_CMD_IDLE]	  = {CPDMA_DMACONTROL,	3,  1,      ACCESS_WO},
-	[CPDMA_COPY_ERROR_FRAMES] = {CPDMA_DMACONTROL,	4,  1,      ACCESS_RW},
-	[CPDMA_RX_OFF_LEN_UPDATE] = {CPDMA_DMACONTROL,	2,  1,      ACCESS_RW},
-	[CPDMA_RX_OWNERSHIP_FLIP] = {CPDMA_DMACONTROL,	1,  1,      ACCESS_RW},
-	[CPDMA_TX_PRIO_FIXED]	  = {CPDMA_DMACONTROL,	0,  1,      ACCESS_RW},
-	[CPDMA_STAT_IDLE]	  = {CPDMA_DMASTATUS,	31, 1,      ACCESS_RO},
-	[CPDMA_STAT_TX_ERR_CODE]  = {CPDMA_DMASTATUS,	20, 0xf,    ACCESS_RW},
-	[CPDMA_STAT_TX_ERR_CHAN]  = {CPDMA_DMASTATUS,	16, 0x7,    ACCESS_RW},
-	[CPDMA_STAT_RX_ERR_CODE]  = {CPDMA_DMASTATUS,	12, 0xf,    ACCESS_RW},
-	[CPDMA_STAT_RX_ERR_CHAN]  = {CPDMA_DMASTATUS,	8,  0x7,    ACCESS_RW},
-	[CPDMA_RX_BUFFER_OFFSET]  = {CPDMA_RXBUFFOFS,	0,  0xffff, ACCESS_RW},
-};
-
-int cpdma_control_get(struct cpdma_ctlr *ctlr, int control)
-{
-	unsigned long flags;
-	struct cpdma_control_info *info = &controls[control];
-	int ret;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-
-	ret = -ENOTSUPP;
-	if (!ctlr->params.has_ext_regs)
-		goto unlock_ret;
-
-	ret = -EINVAL;
-	if (ctlr->state != CPDMA_STATE_ACTIVE)
-		goto unlock_ret;
-
-	ret = -ENOENT;
-	if (control < 0 || control >= ARRAY_SIZE(controls))
-		goto unlock_ret;
-
-	ret = -EPERM;
-	if ((info->access & ACCESS_RO) != ACCESS_RO)
-		goto unlock_ret;
-
-	ret = (dma_reg_read(ctlr, info->reg) >> info->shift) & info->mask;
-
-unlock_ret:
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-	return ret;
-}
-
-int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value)
-{
-	unsigned long flags;
-	struct cpdma_control_info *info = &controls[control];
-	int ret;
-	u32 val;
-
-	spin_lock_irqsave(&ctlr->lock, flags);
-
-	ret = -ENOTSUPP;
-	if (!ctlr->params.has_ext_regs)
-		goto unlock_ret;
-
-	ret = -EINVAL;
-	if (ctlr->state != CPDMA_STATE_ACTIVE)
-		goto unlock_ret;
-
-	ret = -ENOENT;
-	if (control < 0 || control >= ARRAY_SIZE(controls))
-		goto unlock_ret;
-
-	ret = -EPERM;
-	if ((info->access & ACCESS_WO) != ACCESS_WO)
-		goto unlock_ret;
-
-	val  = dma_reg_read(ctlr, info->reg);
-	val &= ~(info->mask << info->shift);
-	val |= (value & info->mask) << info->shift;
-	dma_reg_write(ctlr, info->reg, val);
-	ret = 0;
-
-unlock_ret:
-	spin_unlock_irqrestore(&ctlr->lock, flags);
-	return ret;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/davinci_cpdma.h linux-libre-3.2-gnu/drivers/net/davinci_cpdma.h
--- linux-libre-3.1-gnu/drivers/net/davinci_cpdma.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/davinci_cpdma.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,109 +0,0 @@
-/*
- * Texas Instruments CPDMA Driver
- *
- * Copyright (C) 2010 Texas Instruments
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation 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 __DAVINCI_CPDMA_H__
-#define __DAVINCI_CPDMA_H__
-
-#define CPDMA_MAX_CHANNELS	BITS_PER_LONG
-
-#define tx_chan_num(chan)	(chan)
-#define rx_chan_num(chan)	((chan) + CPDMA_MAX_CHANNELS)
-#define is_rx_chan(chan)	((chan)->chan_num >= CPDMA_MAX_CHANNELS)
-#define is_tx_chan(chan)	(!is_rx_chan(chan))
-#define __chan_linear(chan_num)	((chan_num) & (CPDMA_MAX_CHANNELS - 1))
-#define chan_linear(chan)	__chan_linear((chan)->chan_num)
-
-struct cpdma_params {
-	struct device		*dev;
-	void __iomem		*dmaregs;
-	void __iomem		*txhdp, *rxhdp, *txcp, *rxcp;
-	void __iomem		*rxthresh, *rxfree;
-	int			num_chan;
-	bool			has_soft_reset;
-	int			min_packet_size;
-	u32			desc_mem_phys;
-	u32			desc_hw_addr;
-	int			desc_mem_size;
-	int			desc_align;
-
-	/*
-	 * Some instances of embedded cpdma controllers have extra control and
-	 * status registers.  The following flag enables access to these
-	 * "extended" registers.
-	 */
-	bool			has_ext_regs;
-};
-
-struct cpdma_chan_stats {
-	u32			head_enqueue;
-	u32			tail_enqueue;
-	u32			pad_enqueue;
-	u32			misqueued;
-	u32			desc_alloc_fail;
-	u32			pad_alloc_fail;
-	u32			runt_receive_buff;
-	u32			runt_transmit_buff;
-	u32			empty_dequeue;
-	u32			busy_dequeue;
-	u32			good_dequeue;
-	u32			requeue;
-	u32			teardown_dequeue;
-};
-
-struct cpdma_ctlr;
-struct cpdma_chan;
-
-typedef void (*cpdma_handler_fn)(void *token, int len, int status);
-
-struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params);
-int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr);
-int cpdma_ctlr_start(struct cpdma_ctlr *ctlr);
-int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr);
-int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr);
-
-struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
-				     cpdma_handler_fn handler);
-int cpdma_chan_destroy(struct cpdma_chan *chan);
-int cpdma_chan_start(struct cpdma_chan *chan);
-int cpdma_chan_stop(struct cpdma_chan *chan);
-int cpdma_chan_dump(struct cpdma_chan *chan);
-
-int cpdma_chan_get_stats(struct cpdma_chan *chan,
-			 struct cpdma_chan_stats *stats);
-int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
-		      int len, gfp_t gfp_mask);
-int cpdma_chan_process(struct cpdma_chan *chan, int quota);
-
-int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable);
-void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr);
-int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable);
-
-enum cpdma_control {
-	CPDMA_CMD_IDLE,			/* write-only */
-	CPDMA_COPY_ERROR_FRAMES,	/* read-write */
-	CPDMA_RX_OFF_LEN_UPDATE,	/* read-write */
-	CPDMA_RX_OWNERSHIP_FLIP,	/* read-write */
-	CPDMA_TX_PRIO_FIXED,		/* read-write */
-	CPDMA_STAT_IDLE,		/* read-only */
-	CPDMA_STAT_TX_ERR_CHAN,		/* read-only */
-	CPDMA_STAT_TX_ERR_CODE,		/* read-only */
-	CPDMA_STAT_RX_ERR_CHAN,		/* read-only */
-	CPDMA_STAT_RX_ERR_CODE,		/* read-only */
-	CPDMA_RX_BUFFER_OFFSET,		/* read-write */
-};
-
-int cpdma_control_get(struct cpdma_ctlr *ctlr, int control);
-int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value);
-
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/davinci_emac.c linux-libre-3.2-gnu/drivers/net/davinci_emac.c
--- linux-libre-3.1-gnu/drivers/net/davinci_emac.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/davinci_emac.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2047 +0,0 @@
-/*
- * DaVinci Ethernet Medium Access Controller
- *
- * DaVinci EMAC is based upon CPPI 3.0 TI DMA engine
- *
- * Copyright (C) 2009 Texas Instruments.
- *
- * ---------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- * ---------------------------------------------------------------------------
- * History:
- * 0-5 A number of folks worked on this driver in bits and pieces but the major
- *     contribution came from Suraj Iyer and Anant Gole
- * 6.0 Anant Gole - rewrote the driver as per Linux conventions
- * 6.1 Chaithrika U S - added support for Gigabit and RMII features,
- *     PHY layer usage
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/errno.h>
-#include <linux/in.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/ethtool.h>
-#include <linux/highmem.h>
-#include <linux/proc_fs.h>
-#include <linux/ctype.h>
-#include <linux/spinlock.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/semaphore.h>
-#include <linux/phy.h>
-#include <linux/bitops.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-#include <linux/davinci_emac.h>
-
-#include <asm/irq.h>
-#include <asm/page.h>
-
-#include "davinci_cpdma.h"
-
-static int debug_level;
-module_param(debug_level, int, 0);
-MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)");
-
-/* Netif debug messages possible */
-#define DAVINCI_EMAC_DEBUG	(NETIF_MSG_DRV | \
-				NETIF_MSG_PROBE | \
-				NETIF_MSG_LINK | \
-				NETIF_MSG_TIMER | \
-				NETIF_MSG_IFDOWN | \
-				NETIF_MSG_IFUP | \
-				NETIF_MSG_RX_ERR | \
-				NETIF_MSG_TX_ERR | \
-				NETIF_MSG_TX_QUEUED | \
-				NETIF_MSG_INTR | \
-				NETIF_MSG_TX_DONE | \
-				NETIF_MSG_RX_STATUS | \
-				NETIF_MSG_PKTDATA | \
-				NETIF_MSG_HW | \
-				NETIF_MSG_WOL)
-
-/* version info */
-#define EMAC_MAJOR_VERSION	6
-#define EMAC_MINOR_VERSION	1
-#define EMAC_MODULE_VERSION	"6.1"
-MODULE_VERSION(EMAC_MODULE_VERSION);
-static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
-
-/* Configuration items */
-#define EMAC_DEF_PASS_CRC		(0) /* Do not pass CRC 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) /* 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 */
-#define EMAC_DEF_MCAST_CH		(0) /* Multicast channel is 0 */
-
-#define EMAC_DEF_TXPRIO_FIXED		(1) /* TX Priority is fixed */
-#define EMAC_DEF_TXPACING_EN		(0) /* TX pacing NOT supported*/
-
-#define EMAC_DEF_BUFFER_OFFSET		(0) /* Buffer offset to DMA (future) */
-#define EMAC_DEF_MIN_ETHPKTSIZE		(60) /* Minimum ethernet pkt size */
-#define EMAC_DEF_MAX_FRAME_SIZE		(1500 + 14 + 4 + 4)
-#define EMAC_DEF_TX_CH			(0) /* Default 0th channel */
-#define EMAC_DEF_RX_CH			(0) /* Default 0th channel */
-#define EMAC_DEF_RX_NUM_DESC		(128)
-#define EMAC_DEF_MAX_TX_CH		(1) /* Max TX channels configured */
-#define EMAC_DEF_MAX_RX_CH		(1) /* Max RX channels configured */
-#define EMAC_POLL_WEIGHT		(64) /* Default NAPI poll weight */
-
-/* Buffer descriptor parameters */
-#define EMAC_DEF_TX_MAX_SERVICE		(32) /* TX max service BD's */
-#define EMAC_DEF_RX_MAX_SERVICE		(64) /* should = netdev->weight */
-
-/* EMAC register related defines */
-#define EMAC_ALL_MULTI_REG_VALUE	(0xFFFFFFFF)
-#define EMAC_NUM_MULTICAST_BITS		(64)
-#define EMAC_TX_CONTROL_TX_ENABLE_VAL	(0x1)
-#define EMAC_RX_CONTROL_RX_ENABLE_VAL	(0x1)
-#define EMAC_MAC_HOST_ERR_INTMASK_VAL	(0x2)
-#define EMAC_RX_UNICAST_CLEAR_ALL	(0xFF)
-#define EMAC_INT_MASK_CLEAR		(0xFF)
-
-/* RX MBP register bit positions */
-#define EMAC_RXMBP_PASSCRC_MASK		BIT(30)
-#define EMAC_RXMBP_QOSEN_MASK		BIT(29)
-#define EMAC_RXMBP_NOCHAIN_MASK		BIT(28)
-#define EMAC_RXMBP_CMFEN_MASK		BIT(24)
-#define EMAC_RXMBP_CSFEN_MASK		BIT(23)
-#define EMAC_RXMBP_CEFEN_MASK		BIT(22)
-#define EMAC_RXMBP_CAFEN_MASK		BIT(21)
-#define EMAC_RXMBP_PROMCH_SHIFT		(16)
-#define EMAC_RXMBP_PROMCH_MASK		(0x7 << 16)
-#define EMAC_RXMBP_BROADEN_MASK		BIT(13)
-#define EMAC_RXMBP_BROADCH_SHIFT	(8)
-#define EMAC_RXMBP_BROADCH_MASK		(0x7 << 8)
-#define EMAC_RXMBP_MULTIEN_MASK		BIT(5)
-#define EMAC_RXMBP_MULTICH_SHIFT	(0)
-#define EMAC_RXMBP_MULTICH_MASK		(0x7)
-#define EMAC_RXMBP_CHMASK		(0x7)
-
-/* EMAC register definitions/bit maps used */
-# define EMAC_MBP_RXPROMISC		(0x00200000)
-# define EMAC_MBP_PROMISCCH(ch)		(((ch) & 0x7) << 16)
-# define EMAC_MBP_RXBCAST		(0x00002000)
-# define EMAC_MBP_BCASTCHAN(ch)		(((ch) & 0x7) << 8)
-# define EMAC_MBP_RXMCAST		(0x00000020)
-# define EMAC_MBP_MCASTCHAN(ch)		((ch) & 0x7)
-
-/* EMAC mac_control register */
-#define EMAC_MACCONTROL_TXPTYPE		BIT(9)
-#define EMAC_MACCONTROL_TXPACEEN	BIT(6)
-#define EMAC_MACCONTROL_GMIIEN		BIT(5)
-#define EMAC_MACCONTROL_GIGABITEN	BIT(7)
-#define EMAC_MACCONTROL_FULLDUPLEXEN	BIT(0)
-#define EMAC_MACCONTROL_RMIISPEED_MASK	BIT(15)
-
-/* GIGABIT MODE related bits */
-#define EMAC_DM646X_MACCONTORL_GIG	BIT(7)
-#define EMAC_DM646X_MACCONTORL_GIGFORCE	BIT(17)
-
-/* EMAC mac_status register */
-#define EMAC_MACSTATUS_TXERRCODE_MASK	(0xF00000)
-#define EMAC_MACSTATUS_TXERRCODE_SHIFT	(20)
-#define EMAC_MACSTATUS_TXERRCH_MASK	(0x7)
-#define EMAC_MACSTATUS_TXERRCH_SHIFT	(16)
-#define EMAC_MACSTATUS_RXERRCODE_MASK	(0xF000)
-#define EMAC_MACSTATUS_RXERRCODE_SHIFT	(12)
-#define EMAC_MACSTATUS_RXERRCH_MASK	(0x7)
-#define EMAC_MACSTATUS_RXERRCH_SHIFT	(8)
-
-/* EMAC RX register masks */
-#define EMAC_RX_MAX_LEN_MASK		(0xFFFF)
-#define EMAC_RX_BUFFER_OFFSET_MASK	(0xFFFF)
-
-/* MAC_IN_VECTOR (0x180) register bit fields */
-#define EMAC_DM644X_MAC_IN_VECTOR_HOST_INT	BIT(17)
-#define EMAC_DM644X_MAC_IN_VECTOR_STATPEND_INT	BIT(16)
-#define EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC	BIT(8)
-#define EMAC_DM644X_MAC_IN_VECTOR_TX_INT_VEC	BIT(0)
-
-/** NOTE:: For DM646x the IN_VECTOR has changed */
-#define EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC	BIT(EMAC_DEF_RX_CH)
-#define EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC	BIT(16 + EMAC_DEF_TX_CH)
-#define EMAC_DM646X_MAC_IN_VECTOR_HOST_INT	BIT(26)
-#define EMAC_DM646X_MAC_IN_VECTOR_STATPEND_INT	BIT(27)
-
-/* CPPI bit positions */
-#define EMAC_CPPI_SOP_BIT		BIT(31)
-#define EMAC_CPPI_EOP_BIT		BIT(30)
-#define EMAC_CPPI_OWNERSHIP_BIT		BIT(29)
-#define EMAC_CPPI_EOQ_BIT		BIT(28)
-#define EMAC_CPPI_TEARDOWN_COMPLETE_BIT BIT(27)
-#define EMAC_CPPI_PASS_CRC_BIT		BIT(26)
-#define EMAC_RX_BD_BUF_SIZE		(0xFFFF)
-#define EMAC_BD_LENGTH_FOR_CACHE	(16) /* only CPPI bytes */
-#define EMAC_RX_BD_PKT_LENGTH_MASK	(0xFFFF)
-
-/* Max hardware defines */
-#define EMAC_MAX_TXRX_CHANNELS		 (8)  /* Max hardware channels */
-#define EMAC_DEF_MAX_MULTICAST_ADDRESSES (64) /* Max mcast addr's */
-
-/* EMAC Peripheral Device Register Memory Layout structure */
-#define EMAC_MACINVECTOR	0x90
-
-#define EMAC_DM646X_MACEOIVECTOR	0x94
-
-#define EMAC_MACINTSTATRAW	0xB0
-#define EMAC_MACINTSTATMASKED	0xB4
-#define EMAC_MACINTMASKSET	0xB8
-#define EMAC_MACINTMASKCLEAR	0xBC
-
-#define EMAC_RXMBPENABLE	0x100
-#define EMAC_RXUNICASTSET	0x104
-#define EMAC_RXUNICASTCLEAR	0x108
-#define EMAC_RXMAXLEN		0x10C
-#define EMAC_RXBUFFEROFFSET	0x110
-#define EMAC_RXFILTERLOWTHRESH	0x114
-
-#define EMAC_MACCONTROL		0x160
-#define EMAC_MACSTATUS		0x164
-#define EMAC_EMCONTROL		0x168
-#define EMAC_FIFOCONTROL	0x16C
-#define EMAC_MACCONFIG		0x170
-#define EMAC_SOFTRESET		0x174
-#define EMAC_MACSRCADDRLO	0x1D0
-#define EMAC_MACSRCADDRHI	0x1D4
-#define EMAC_MACHASH1		0x1D8
-#define EMAC_MACHASH2		0x1DC
-#define EMAC_MACADDRLO		0x500
-#define EMAC_MACADDRHI		0x504
-#define EMAC_MACINDEX		0x508
-
-/* EMAC statistics registers */
-#define EMAC_RXGOODFRAMES	0x200
-#define EMAC_RXBCASTFRAMES	0x204
-#define EMAC_RXMCASTFRAMES	0x208
-#define EMAC_RXPAUSEFRAMES	0x20C
-#define EMAC_RXCRCERRORS	0x210
-#define EMAC_RXALIGNCODEERRORS	0x214
-#define EMAC_RXOVERSIZED	0x218
-#define EMAC_RXJABBER		0x21C
-#define EMAC_RXUNDERSIZED	0x220
-#define EMAC_RXFRAGMENTS	0x224
-#define EMAC_RXFILTERED		0x228
-#define EMAC_RXQOSFILTERED	0x22C
-#define EMAC_RXOCTETS		0x230
-#define EMAC_TXGOODFRAMES	0x234
-#define EMAC_TXBCASTFRAMES	0x238
-#define EMAC_TXMCASTFRAMES	0x23C
-#define EMAC_TXPAUSEFRAMES	0x240
-#define EMAC_TXDEFERRED		0x244
-#define EMAC_TXCOLLISION	0x248
-#define EMAC_TXSINGLECOLL	0x24C
-#define EMAC_TXMULTICOLL	0x250
-#define EMAC_TXEXCESSIVECOLL	0x254
-#define EMAC_TXLATECOLL		0x258
-#define EMAC_TXUNDERRUN		0x25C
-#define EMAC_TXCARRIERSENSE	0x260
-#define EMAC_TXOCTETS		0x264
-#define EMAC_NETOCTETS		0x280
-#define EMAC_RXSOFOVERRUNS	0x284
-#define EMAC_RXMOFOVERRUNS	0x288
-#define EMAC_RXDMAOVERRUNS	0x28C
-
-/* EMAC DM644x control registers */
-#define EMAC_CTRL_EWCTL		(0x4)
-#define EMAC_CTRL_EWINTTCNT	(0x8)
-
-/* EMAC DM644x control module masks */
-#define EMAC_DM644X_EWINTCNT_MASK	0x1FFFF
-#define EMAC_DM644X_INTMIN_INTVL	0x1
-#define EMAC_DM644X_INTMAX_INTVL	(EMAC_DM644X_EWINTCNT_MASK)
-
-/* EMAC DM646X control module registers */
-#define EMAC_DM646X_CMINTCTRL	0x0C
-#define EMAC_DM646X_CMRXINTEN	0x14
-#define EMAC_DM646X_CMTXINTEN	0x18
-#define EMAC_DM646X_CMRXINTMAX	0x70
-#define EMAC_DM646X_CMTXINTMAX	0x74
-
-/* EMAC DM646X control module masks */
-#define EMAC_DM646X_INTPACEEN		(0x3 << 16)
-#define EMAC_DM646X_INTPRESCALE_MASK	(0x7FF << 0)
-#define EMAC_DM646X_CMINTMAX_CNT	63
-#define EMAC_DM646X_CMINTMIN_CNT	2
-#define EMAC_DM646X_CMINTMAX_INTVL	(1000 / EMAC_DM646X_CMINTMIN_CNT)
-#define EMAC_DM646X_CMINTMIN_INTVL	((1000 / EMAC_DM646X_CMINTMAX_CNT) + 1)
-
-
-/* EMAC EOI codes for C0 */
-#define EMAC_DM646X_MAC_EOI_C0_RXEN	(0x01)
-#define EMAC_DM646X_MAC_EOI_C0_TXEN	(0x02)
-
-/* EMAC Stats Clear Mask */
-#define EMAC_STATS_CLR_MASK    (0xFFFFFFFF)
-
-/* emac_priv: EMAC private data structure
- *
- * EMAC adapter private data structure
- */
-struct emac_priv {
-	u32 msg_enable;
-	struct net_device *ndev;
-	struct platform_device *pdev;
-	struct napi_struct napi;
-	char mac_addr[6];
-	void __iomem *remap_addr;
-	u32 emac_base_phys;
-	void __iomem *emac_base;
-	void __iomem *ctrl_base;
-	struct cpdma_ctlr *dma;
-	struct cpdma_chan *txchan;
-	struct cpdma_chan *rxchan;
-	u32 link; /* 1=link on, 0=link off */
-	u32 speed; /* 0=Auto Neg, 1=No PHY, 10,100, 1000 - mbps */
-	u32 duplex; /* Link duplex: 0=Half, 1=Full */
-	u32 rx_buf_size;
-	u32 isr_count;
-	u32 coal_intvl;
-	u32 bus_freq_mhz;
-	u8 rmii_en;
-	u8 version;
-	u32 mac_hash1;
-	u32 mac_hash2;
-	u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS];
-	u32 rx_addr_type;
-	const char *phy_id;
-	struct phy_device *phydev;
-	spinlock_t lock;
-	/*platform specific members*/
-	void (*int_enable) (void);
-	void (*int_disable) (void);
-};
-
-/* clock frequency for EMAC */
-static struct clk *emac_clk;
-static unsigned long emac_bus_frequency;
-
-/* EMAC TX Host Error description strings */
-static char *emac_txhost_errcodes[16] = {
-	"No error", "SOP error", "Ownership bit not set in SOP buffer",
-	"Zero Next Buffer Descriptor Pointer Without EOP",
-	"Zero Buffer Pointer", "Zero Buffer Length", "Packet Length Error",
-	"Reserved", "Reserved", "Reserved", "Reserved", "Reserved",
-	"Reserved", "Reserved", "Reserved", "Reserved"
-};
-
-/* EMAC RX Host Error description strings */
-static char *emac_rxhost_errcodes[16] = {
-	"No error", "Reserved", "Ownership bit not set in input buffer",
-	"Reserved", "Zero Buffer Pointer", "Reserved", "Reserved",
-	"Reserved", "Reserved", "Reserved", "Reserved", "Reserved",
-	"Reserved", "Reserved", "Reserved", "Reserved"
-};
-
-/* Helper macros */
-#define emac_read(reg)		  ioread32(priv->emac_base + (reg))
-#define emac_write(reg, val)      iowrite32(val, priv->emac_base + (reg))
-
-#define emac_ctrl_read(reg)	  ioread32((priv->ctrl_base + (reg)))
-#define emac_ctrl_write(reg, val) iowrite32(val, (priv->ctrl_base + (reg)))
-
-/**
- * emac_dump_regs: Dump important EMAC registers to debug terminal
- * @priv: The DaVinci EMAC private adapter structure
- *
- * Executes ethtool set cmd & sets phy mode
- *
- */
-static void emac_dump_regs(struct emac_priv *priv)
-{
-	struct device *emac_dev = &priv->ndev->dev;
-
-	/* Print important registers in EMAC */
-	dev_info(emac_dev, "EMAC Basic registers\n");
-	if (priv->version == EMAC_VERSION_1) {
-		dev_info(emac_dev, "EMAC: EWCTL: %08X, EWINTTCNT: %08X\n",
-			emac_ctrl_read(EMAC_CTRL_EWCTL),
-			emac_ctrl_read(EMAC_CTRL_EWINTTCNT));
-	}
-	dev_info(emac_dev, "EMAC: EmuControl:%08X, FifoControl: %08X\n",
-		emac_read(EMAC_EMCONTROL), emac_read(EMAC_FIFOCONTROL));
-	dev_info(emac_dev, "EMAC: MBPEnable:%08X, RXUnicastSet: %08X, "\
-		"RXMaxLen=%08X\n", emac_read(EMAC_RXMBPENABLE),
-		emac_read(EMAC_RXUNICASTSET), emac_read(EMAC_RXMAXLEN));
-	dev_info(emac_dev, "EMAC: MacControl:%08X, MacStatus: %08X, "\
-		"MacConfig=%08X\n", emac_read(EMAC_MACCONTROL),
-		emac_read(EMAC_MACSTATUS), emac_read(EMAC_MACCONFIG));
-	dev_info(emac_dev, "EMAC Statistics\n");
-	dev_info(emac_dev, "EMAC: rx_good_frames:%d\n",
-		emac_read(EMAC_RXGOODFRAMES));
-	dev_info(emac_dev, "EMAC: rx_broadcast_frames:%d\n",
-		emac_read(EMAC_RXBCASTFRAMES));
-	dev_info(emac_dev, "EMAC: rx_multicast_frames:%d\n",
-		emac_read(EMAC_RXMCASTFRAMES));
-	dev_info(emac_dev, "EMAC: rx_pause_frames:%d\n",
-		emac_read(EMAC_RXPAUSEFRAMES));
-	dev_info(emac_dev, "EMAC: rx_crcerrors:%d\n",
-		emac_read(EMAC_RXCRCERRORS));
-	dev_info(emac_dev, "EMAC: rx_align_code_errors:%d\n",
-		emac_read(EMAC_RXALIGNCODEERRORS));
-	dev_info(emac_dev, "EMAC: rx_oversized_frames:%d\n",
-		emac_read(EMAC_RXOVERSIZED));
-	dev_info(emac_dev, "EMAC: rx_jabber_frames:%d\n",
-		emac_read(EMAC_RXJABBER));
-	dev_info(emac_dev, "EMAC: rx_undersized_frames:%d\n",
-		emac_read(EMAC_RXUNDERSIZED));
-	dev_info(emac_dev, "EMAC: rx_fragments:%d\n",
-		emac_read(EMAC_RXFRAGMENTS));
-	dev_info(emac_dev, "EMAC: rx_filtered_frames:%d\n",
-		emac_read(EMAC_RXFILTERED));
-	dev_info(emac_dev, "EMAC: rx_qos_filtered_frames:%d\n",
-		emac_read(EMAC_RXQOSFILTERED));
-	dev_info(emac_dev, "EMAC: rx_octets:%d\n",
-		emac_read(EMAC_RXOCTETS));
-	dev_info(emac_dev, "EMAC: tx_goodframes:%d\n",
-		emac_read(EMAC_TXGOODFRAMES));
-	dev_info(emac_dev, "EMAC: tx_bcastframes:%d\n",
-		emac_read(EMAC_TXBCASTFRAMES));
-	dev_info(emac_dev, "EMAC: tx_mcastframes:%d\n",
-		emac_read(EMAC_TXMCASTFRAMES));
-	dev_info(emac_dev, "EMAC: tx_pause_frames:%d\n",
-		emac_read(EMAC_TXPAUSEFRAMES));
-	dev_info(emac_dev, "EMAC: tx_deferred_frames:%d\n",
-		emac_read(EMAC_TXDEFERRED));
-	dev_info(emac_dev, "EMAC: tx_collision_frames:%d\n",
-		emac_read(EMAC_TXCOLLISION));
-	dev_info(emac_dev, "EMAC: tx_single_coll_frames:%d\n",
-		emac_read(EMAC_TXSINGLECOLL));
-	dev_info(emac_dev, "EMAC: tx_mult_coll_frames:%d\n",
-		emac_read(EMAC_TXMULTICOLL));
-	dev_info(emac_dev, "EMAC: tx_excessive_collisions:%d\n",
-		emac_read(EMAC_TXEXCESSIVECOLL));
-	dev_info(emac_dev, "EMAC: tx_late_collisions:%d\n",
-		emac_read(EMAC_TXLATECOLL));
-	dev_info(emac_dev, "EMAC: tx_underrun:%d\n",
-		emac_read(EMAC_TXUNDERRUN));
-	dev_info(emac_dev, "EMAC: tx_carrier_sense_errors:%d\n",
-		emac_read(EMAC_TXCARRIERSENSE));
-	dev_info(emac_dev, "EMAC: tx_octets:%d\n",
-		emac_read(EMAC_TXOCTETS));
-	dev_info(emac_dev, "EMAC: net_octets:%d\n",
-		emac_read(EMAC_NETOCTETS));
-	dev_info(emac_dev, "EMAC: rx_sof_overruns:%d\n",
-		emac_read(EMAC_RXSOFOVERRUNS));
-	dev_info(emac_dev, "EMAC: rx_mof_overruns:%d\n",
-		emac_read(EMAC_RXMOFOVERRUNS));
-	dev_info(emac_dev, "EMAC: rx_dma_overruns:%d\n",
-		emac_read(EMAC_RXDMAOVERRUNS));
-
-	cpdma_ctlr_dump(priv->dma);
-}
-
-/**
- * emac_get_drvinfo: Get EMAC driver information
- * @ndev: The DaVinci EMAC network adapter
- * @info: ethtool info structure containing name and version
- *
- * Returns EMAC driver information (name and version)
- *
- */
-static void emac_get_drvinfo(struct net_device *ndev,
-			     struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, emac_version_string);
-	strcpy(info->version, EMAC_MODULE_VERSION);
-}
-
-/**
- * emac_get_settings: Get EMAC settings
- * @ndev: The DaVinci EMAC network adapter
- * @ecmd: ethtool command
- *
- * Executes ethool get command
- *
- */
-static int emac_get_settings(struct net_device *ndev,
-			     struct ethtool_cmd *ecmd)
-{
-	struct emac_priv *priv = netdev_priv(ndev);
-	if (priv->phydev)
-		return phy_ethtool_gset(priv->phydev, ecmd);
-	else
-		return -EOPNOTSUPP;
-
-}
-
-/**
- * emac_set_settings: Set EMAC settings
- * @ndev: The DaVinci EMAC network adapter
- * @ecmd: ethtool command
- *
- * Executes ethool set command
- *
- */
-static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
-{
-	struct emac_priv *priv = netdev_priv(ndev);
-	if (priv->phydev)
-		return phy_ethtool_sset(priv->phydev, ecmd);
-	else
-		return -EOPNOTSUPP;
-
-}
-
-/**
- * emac_get_coalesce : Get interrupt coalesce settings for this device
- * @ndev : The DaVinci EMAC network adapter
- * @coal : ethtool coalesce settings structure
- *
- * Fetch the current interrupt coalesce settings
- *
- */
-static int emac_get_coalesce(struct net_device *ndev,
-				struct ethtool_coalesce *coal)
-{
-	struct emac_priv *priv = netdev_priv(ndev);
-
-	coal->rx_coalesce_usecs = priv->coal_intvl;
-	return 0;
-
-}
-
-/**
- * emac_set_coalesce : Set interrupt coalesce settings for this device
- * @ndev : The DaVinci EMAC network adapter
- * @coal : ethtool coalesce settings structure
- *
- * Set interrupt coalesce parameters
- *
- */
-static int emac_set_coalesce(struct net_device *ndev,
-				struct ethtool_coalesce *coal)
-{
-	struct emac_priv *priv = netdev_priv(ndev);
-	u32 int_ctrl, num_interrupts = 0;
-	u32 prescale = 0, addnl_dvdr = 1, coal_intvl = 0;
-
-	if (!coal->rx_coalesce_usecs)
-		return -EINVAL;
-
-	coal_intvl = coal->rx_coalesce_usecs;
-
-	switch (priv->version) {
-	case EMAC_VERSION_2:
-		int_ctrl =  emac_ctrl_read(EMAC_DM646X_CMINTCTRL);
-		prescale = priv->bus_freq_mhz * 4;
-
-		if (coal_intvl < EMAC_DM646X_CMINTMIN_INTVL)
-			coal_intvl = EMAC_DM646X_CMINTMIN_INTVL;
-
-		if (coal_intvl > EMAC_DM646X_CMINTMAX_INTVL) {
-			/*
-			 * Interrupt pacer works with 4us Pulse, we can
-			 * throttle further by dilating the 4us pulse.
-			 */
-			addnl_dvdr = EMAC_DM646X_INTPRESCALE_MASK / prescale;
-
-			if (addnl_dvdr > 1) {
-				prescale *= addnl_dvdr;
-				if (coal_intvl > (EMAC_DM646X_CMINTMAX_INTVL
-							* addnl_dvdr))
-					coal_intvl = (EMAC_DM646X_CMINTMAX_INTVL
-							* addnl_dvdr);
-			} else {
-				addnl_dvdr = 1;
-				coal_intvl = EMAC_DM646X_CMINTMAX_INTVL;
-			}
-		}
-
-		num_interrupts = (1000 * addnl_dvdr) / coal_intvl;
-
-		int_ctrl |= EMAC_DM646X_INTPACEEN;
-		int_ctrl &= (~EMAC_DM646X_INTPRESCALE_MASK);
-		int_ctrl |= (prescale & EMAC_DM646X_INTPRESCALE_MASK);
-		emac_ctrl_write(EMAC_DM646X_CMINTCTRL, int_ctrl);
-
-		emac_ctrl_write(EMAC_DM646X_CMRXINTMAX, num_interrupts);
-		emac_ctrl_write(EMAC_DM646X_CMTXINTMAX, num_interrupts);
-
-		break;
-	default:
-		int_ctrl = emac_ctrl_read(EMAC_CTRL_EWINTTCNT);
-		int_ctrl &= (~EMAC_DM644X_EWINTCNT_MASK);
-		prescale = coal_intvl * priv->bus_freq_mhz;
-		if (prescale > EMAC_DM644X_EWINTCNT_MASK) {
-			prescale = EMAC_DM644X_EWINTCNT_MASK;
-			coal_intvl = prescale / priv->bus_freq_mhz;
-		}
-		emac_ctrl_write(EMAC_CTRL_EWINTTCNT, (int_ctrl | prescale));
-
-		break;
-	}
-
-	printk(KERN_INFO"Set coalesce to %d usecs.\n", coal_intvl);
-	priv->coal_intvl = coal_intvl;
-
-	return 0;
-
-}
-
-
-/**
- * ethtool_ops: DaVinci EMAC Ethtool structure
- *
- * Ethtool support for EMAC adapter
- *
- */
-static const struct ethtool_ops ethtool_ops = {
-	.get_drvinfo = emac_get_drvinfo,
-	.get_settings = emac_get_settings,
-	.set_settings = emac_set_settings,
-	.get_link = ethtool_op_get_link,
-	.get_coalesce = emac_get_coalesce,
-	.set_coalesce =  emac_set_coalesce,
-};
-
-/**
- * emac_update_phystatus: Update Phy status
- * @priv: The DaVinci EMAC private adapter structure
- *
- * Updates phy status and takes action for network queue if required
- * based upon link status
- *
- */
-static void emac_update_phystatus(struct emac_priv *priv)
-{
-	u32 mac_control;
-	u32 new_duplex;
-	u32 cur_duplex;
-	struct net_device *ndev = priv->ndev;
-
-	mac_control = emac_read(EMAC_MACCONTROL);
-	cur_duplex = (mac_control & EMAC_MACCONTROL_FULLDUPLEXEN) ?
-			DUPLEX_FULL : DUPLEX_HALF;
-	if (priv->phydev)
-		new_duplex = priv->phydev->duplex;
-	else
-		new_duplex = DUPLEX_FULL;
-
-	/* We get called only if link has changed (speed/duplex/status) */
-	if ((priv->link) && (new_duplex != cur_duplex)) {
-		priv->duplex = new_duplex;
-		if (DUPLEX_FULL == priv->duplex)
-			mac_control |= (EMAC_MACCONTROL_FULLDUPLEXEN);
-		else
-			mac_control &= ~(EMAC_MACCONTROL_FULLDUPLEXEN);
-	}
-
-	if (priv->speed == SPEED_1000 && (priv->version == EMAC_VERSION_2)) {
-		mac_control = emac_read(EMAC_MACCONTROL);
-		mac_control |= (EMAC_DM646X_MACCONTORL_GIG |
-				EMAC_DM646X_MACCONTORL_GIGFORCE);
-	} else {
-		/* Clear the GIG bit and GIGFORCE bit */
-		mac_control &= ~(EMAC_DM646X_MACCONTORL_GIGFORCE |
-					EMAC_DM646X_MACCONTORL_GIG);
-
-		if (priv->rmii_en && (priv->speed == SPEED_100))
-			mac_control |= EMAC_MACCONTROL_RMIISPEED_MASK;
-		else
-			mac_control &= ~EMAC_MACCONTROL_RMIISPEED_MASK;
-	}
-
-	/* Update mac_control if changed */
-	emac_write(EMAC_MACCONTROL, mac_control);
-
-	if (priv->link) {
-		/* link ON */
-		if (!netif_carrier_ok(ndev))
-			netif_carrier_on(ndev);
-	/* reactivate the transmit queue if it is stopped */
-		if (netif_running(ndev) && netif_queue_stopped(ndev))
-			netif_wake_queue(ndev);
-	} else {
-		/* link OFF */
-		if (netif_carrier_ok(ndev))
-			netif_carrier_off(ndev);
-		if (!netif_queue_stopped(ndev))
-			netif_stop_queue(ndev);
-	}
-}
-
-/**
- * hash_get: Calculate hash value from mac address
- * @addr: mac address to delete from hash table
- *
- * Calculates hash value from mac address
- *
- */
-static u32 hash_get(u8 *addr)
-{
-	u32 hash;
-	u8 tmpval;
-	int cnt;
-	hash = 0;
-
-	for (cnt = 0; cnt < 2; cnt++) {
-		tmpval = *addr++;
-		hash ^= (tmpval >> 2) ^ (tmpval << 4);
-		tmpval = *addr++;
-		hash ^= (tmpval >> 4) ^ (tmpval << 2);
-		tmpval = *addr++;
-		hash ^= (tmpval >> 6) ^ (tmpval);
-	}
-
-	return hash & 0x3F;
-}
-
-/**
- * hash_add: Hash function to add mac addr from hash table
- * @priv: The DaVinci EMAC private adapter structure
- * mac_addr: mac address to delete from hash table
- *
- * Adds mac address to the internal hash table
- *
- */
-static int hash_add(struct emac_priv *priv, u8 *mac_addr)
-{
-	struct device *emac_dev = &priv->ndev->dev;
-	u32 rc = 0;
-	u32 hash_bit;
-	u32 hash_value = hash_get(mac_addr);
-
-	if (hash_value >= EMAC_NUM_MULTICAST_BITS) {
-		if (netif_msg_drv(priv)) {
-			dev_err(emac_dev, "DaVinci EMAC: hash_add(): Invalid "\
-				"Hash %08x, should not be greater than %08x",
-				hash_value, (EMAC_NUM_MULTICAST_BITS - 1));
-		}
-		return -1;
-	}
-
-	/* set the hash bit only if not previously set */
-	if (priv->multicast_hash_cnt[hash_value] == 0) {
-		rc = 1; /* hash value changed */
-		if (hash_value < 32) {
-			hash_bit = BIT(hash_value);
-			priv->mac_hash1 |= hash_bit;
-		} else {
-			hash_bit = BIT((hash_value - 32));
-			priv->mac_hash2 |= hash_bit;
-		}
-	}
-
-	/* incr counter for num of mcast addr's mapped to "this" hash bit */
-	++priv->multicast_hash_cnt[hash_value];
-
-	return rc;
-}
-
-/**
- * hash_del: Hash function to delete mac addr from hash table
- * @priv: The DaVinci EMAC private adapter structure
- * mac_addr: mac address to delete from hash table
- *
- * Removes mac address from the internal hash table
- *
- */
-static int hash_del(struct emac_priv *priv, u8 *mac_addr)
-{
-	u32 hash_value;
-	u32 hash_bit;
-
-	hash_value = hash_get(mac_addr);
-	if (priv->multicast_hash_cnt[hash_value] > 0) {
-		/* dec cntr for num of mcast addr's mapped to this hash bit */
-		--priv->multicast_hash_cnt[hash_value];
-	}
-
-	/* if counter still > 0, at least one multicast address refers
-	 * to this hash bit. so return 0 */
-	if (priv->multicast_hash_cnt[hash_value] > 0)
-		return 0;
-
-	if (hash_value < 32) {
-		hash_bit = BIT(hash_value);
-		priv->mac_hash1 &= ~hash_bit;
-	} else {
-		hash_bit = BIT((hash_value - 32));
-		priv->mac_hash2 &= ~hash_bit;
-	}
-
-	/* return 1 to indicate change in mac_hash registers reqd */
-	return 1;
-}
-
-/* EMAC multicast operation */
-#define EMAC_MULTICAST_ADD	0
-#define EMAC_MULTICAST_DEL	1
-#define EMAC_ALL_MULTI_SET	2
-#define EMAC_ALL_MULTI_CLR	3
-
-/**
- * emac_add_mcast: Set multicast address in the EMAC adapter (Internal)
- * @priv: The DaVinci EMAC private adapter structure
- * @action: multicast operation to perform
- * mac_addr: mac address to set
- *
- * Set multicast addresses in EMAC adapter - internal function
- *
- */
-static void emac_add_mcast(struct emac_priv *priv, u32 action, u8 *mac_addr)
-{
-	struct device *emac_dev = &priv->ndev->dev;
-	int update = -1;
-
-	switch (action) {
-	case EMAC_MULTICAST_ADD:
-		update = hash_add(priv, mac_addr);
-		break;
-	case EMAC_MULTICAST_DEL:
-		update = hash_del(priv, mac_addr);
-		break;
-	case EMAC_ALL_MULTI_SET:
-		update = 1;
-		priv->mac_hash1 = EMAC_ALL_MULTI_REG_VALUE;
-		priv->mac_hash2 = EMAC_ALL_MULTI_REG_VALUE;
-		break;
-	case EMAC_ALL_MULTI_CLR:
-		update = 1;
-		priv->mac_hash1 = 0;
-		priv->mac_hash2 = 0;
-		memset(&(priv->multicast_hash_cnt[0]), 0,
-		sizeof(priv->multicast_hash_cnt[0]) *
-		       EMAC_NUM_MULTICAST_BITS);
-		break;
-	default:
-		if (netif_msg_drv(priv))
-			dev_err(emac_dev, "DaVinci EMAC: add_mcast"\
-				": bad operation %d", action);
-		break;
-	}
-
-	/* write to the hardware only if the register status chances */
-	if (update > 0) {
-		emac_write(EMAC_MACHASH1, priv->mac_hash1);
-		emac_write(EMAC_MACHASH2, priv->mac_hash2);
-	}
-}
-
-/**
- * emac_dev_mcast_set: Set multicast address in the EMAC adapter
- * @ndev: The DaVinci EMAC network adapter
- *
- * Set multicast addresses in EMAC adapter
- *
- */
-static void emac_dev_mcast_set(struct net_device *ndev)
-{
-	u32 mbp_enable;
-	struct emac_priv *priv = netdev_priv(ndev);
-
-	mbp_enable = emac_read(EMAC_RXMBPENABLE);
-	if (ndev->flags & IFF_PROMISC) {
-		mbp_enable &= (~EMAC_MBP_PROMISCCH(EMAC_DEF_PROM_CH));
-		mbp_enable |= (EMAC_MBP_RXPROMISC);
-	} else {
-		mbp_enable = (mbp_enable & ~EMAC_MBP_RXPROMISC);
-		if ((ndev->flags & IFF_ALLMULTI) ||
-		    netdev_mc_count(ndev) > EMAC_DEF_MAX_MULTICAST_ADDRESSES) {
-			mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST);
-			emac_add_mcast(priv, EMAC_ALL_MULTI_SET, NULL);
-		}
-		if (!netdev_mc_empty(ndev)) {
-			struct netdev_hw_addr *ha;
-
-			mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST);
-			emac_add_mcast(priv, EMAC_ALL_MULTI_CLR, NULL);
-			/* program multicast address list into EMAC hardware */
-			netdev_for_each_mc_addr(ha, ndev) {
-				emac_add_mcast(priv, EMAC_MULTICAST_ADD,
-					       (u8 *) ha->addr);
-			}
-		} else {
-			mbp_enable = (mbp_enable & ~EMAC_MBP_RXMCAST);
-			emac_add_mcast(priv, EMAC_ALL_MULTI_CLR, NULL);
-		}
-	}
-	/* Set mbp config register */
-	emac_write(EMAC_RXMBPENABLE, mbp_enable);
-}
-
-/*************************************************************************
- *  EMAC Hardware manipulation
- *************************************************************************/
-
-/**
- * emac_int_disable: Disable EMAC module interrupt (from adapter)
- * @priv: The DaVinci EMAC private adapter structure
- *
- * Disable EMAC interrupt on the adapter
- *
- */
-static void emac_int_disable(struct emac_priv *priv)
-{
-	if (priv->version == EMAC_VERSION_2) {
-		unsigned long flags;
-
-		local_irq_save(flags);
-
-		/* Program C0_Int_En to zero to turn off
-		* interrupts to the CPU */
-		emac_ctrl_write(EMAC_DM646X_CMRXINTEN, 0x0);
-		emac_ctrl_write(EMAC_DM646X_CMTXINTEN, 0x0);
-		/* NOTE: Rx Threshold and Misc interrupts are not disabled */
-		if (priv->int_disable)
-			priv->int_disable();
-
-		local_irq_restore(flags);
-
-	} else {
-		/* Set DM644x control registers for interrupt control */
-		emac_ctrl_write(EMAC_CTRL_EWCTL, 0x0);
-	}
-}
-
-/**
- * emac_int_enable: Enable EMAC module interrupt (from adapter)
- * @priv: The DaVinci EMAC private adapter structure
- *
- * Enable EMAC interrupt on the adapter
- *
- */
-static void emac_int_enable(struct emac_priv *priv)
-{
-	if (priv->version == EMAC_VERSION_2) {
-		if (priv->int_enable)
-			priv->int_enable();
-
-		emac_ctrl_write(EMAC_DM646X_CMRXINTEN, 0xff);
-		emac_ctrl_write(EMAC_DM646X_CMTXINTEN, 0xff);
-
-		/* In addition to turning on interrupt Enable, we need
-		 * ack by writing appropriate values to the EOI
-		 * register */
-
-		/* NOTE: Rx Threshold and Misc interrupts are not enabled */
-
-		/* ack rxen only then a new pulse will be generated */
-		emac_write(EMAC_DM646X_MACEOIVECTOR,
-			EMAC_DM646X_MAC_EOI_C0_RXEN);
-
-		/* ack txen- only then a new pulse will be generated */
-		emac_write(EMAC_DM646X_MACEOIVECTOR,
-			EMAC_DM646X_MAC_EOI_C0_TXEN);
-
-	} else {
-		/* Set DM644x control registers for interrupt control */
-		emac_ctrl_write(EMAC_CTRL_EWCTL, 0x1);
-	}
-}
-
-/**
- * emac_irq: EMAC interrupt handler
- * @irq: interrupt number
- * @dev_id: EMAC network adapter data structure ptr
- *
- * EMAC Interrupt handler - we only schedule NAPI and not process any packets
- * here. EVen the interrupt status is checked (TX/RX/Err) in NAPI poll function
- *
- * Returns interrupt handled condition
- */
-static irqreturn_t emac_irq(int irq, void *dev_id)
-{
-	struct net_device *ndev = (struct net_device *)dev_id;
-	struct emac_priv *priv = netdev_priv(ndev);
-
-	++priv->isr_count;
-	if (likely(netif_running(priv->ndev))) {
-		emac_int_disable(priv);
-		napi_schedule(&priv->napi);
-	} else {
-		/* we are closing down, so dont process anything */
-	}
-	return IRQ_HANDLED;
-}
-
-static struct sk_buff *emac_rx_alloc(struct emac_priv *priv)
-{
-	struct sk_buff *skb = dev_alloc_skb(priv->rx_buf_size);
-	if (WARN_ON(!skb))
-		return NULL;
-	skb->dev = priv->ndev;
-	skb_reserve(skb, NET_IP_ALIGN);
-	return skb;
-}
-
-static void emac_rx_handler(void *token, int len, int status)
-{
-	struct sk_buff		*skb = token;
-	struct net_device	*ndev = skb->dev;
-	struct emac_priv	*priv = netdev_priv(ndev);
-	struct device		*emac_dev = &ndev->dev;
-	int			ret;
-
-	/* free and bail if we are shutting down */
-	if (unlikely(!netif_running(ndev) || !netif_carrier_ok(ndev))) {
-		dev_kfree_skb_any(skb);
-		return;
-	}
-
-	/* recycle on receive error */
-	if (status < 0) {
-		ndev->stats.rx_errors++;
-		goto recycle;
-	}
-
-	/* feed received packet up the stack */
-	skb_put(skb, len);
-	skb->protocol = eth_type_trans(skb, ndev);
-	netif_receive_skb(skb);
-	ndev->stats.rx_bytes += len;
-	ndev->stats.rx_packets++;
-
-	/* alloc a new packet for receive */
-	skb = emac_rx_alloc(priv);
-	if (!skb) {
-		if (netif_msg_rx_err(priv) && net_ratelimit())
-			dev_err(emac_dev, "failed rx buffer alloc\n");
-		return;
-	}
-
-recycle:
-	ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
-			skb_tailroom(skb), GFP_KERNEL);
-	if (WARN_ON(ret < 0))
-		dev_kfree_skb_any(skb);
-}
-
-static void emac_tx_handler(void *token, int len, int status)
-{
-	struct sk_buff		*skb = token;
-	struct net_device	*ndev = skb->dev;
-
-	if (unlikely(netif_queue_stopped(ndev)))
-		netif_start_queue(ndev);
-	ndev->stats.tx_packets++;
-	ndev->stats.tx_bytes += len;
-	dev_kfree_skb_any(skb);
-}
-
-/**
- * emac_dev_xmit: EMAC Transmit function
- * @skb: SKB pointer
- * @ndev: The DaVinci EMAC network adapter
- *
- * Called by the system to transmit a packet  - we queue the packet in
- * EMAC hardware transmit queue
- *
- * Returns success(NETDEV_TX_OK) or error code (typically out of desc's)
- */
-static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
-	struct device *emac_dev = &ndev->dev;
-	int ret_code;
-	struct emac_priv *priv = netdev_priv(ndev);
-
-	/* If no link, return */
-	if (unlikely(!priv->link)) {
-		if (netif_msg_tx_err(priv) && net_ratelimit())
-			dev_err(emac_dev, "DaVinci EMAC: No link to transmit");
-		goto fail_tx;
-	}
-
-	ret_code = skb_padto(skb, EMAC_DEF_MIN_ETHPKTSIZE);
-	if (unlikely(ret_code < 0)) {
-		if (netif_msg_tx_err(priv) && net_ratelimit())
-			dev_err(emac_dev, "DaVinci EMAC: packet pad failed");
-		goto fail_tx;
-	}
-
-	skb_tx_timestamp(skb);
-
-	ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len,
-				     GFP_KERNEL);
-	if (unlikely(ret_code != 0)) {
-		if (netif_msg_tx_err(priv) && net_ratelimit())
-			dev_err(emac_dev, "DaVinci EMAC: desc submit failed");
-		goto fail_tx;
-	}
-
-	return NETDEV_TX_OK;
-
-fail_tx:
-	ndev->stats.tx_dropped++;
-	netif_stop_queue(ndev);
-	return NETDEV_TX_BUSY;
-}
-
-/**
- * emac_dev_tx_timeout: EMAC Transmit timeout function
- * @ndev: The DaVinci EMAC network adapter
- *
- * Called when system detects that a skb timeout period has expired
- * potentially due to a fault in the adapter in not being able to send
- * it out on the wire. We teardown the TX channel assuming a hardware
- * error and re-initialize the TX channel for hardware operation
- *
- */
-static void emac_dev_tx_timeout(struct net_device *ndev)
-{
-	struct emac_priv *priv = netdev_priv(ndev);
-	struct device *emac_dev = &ndev->dev;
-
-	if (netif_msg_tx_err(priv))
-		dev_err(emac_dev, "DaVinci EMAC: xmit timeout, restarting TX");
-
-	emac_dump_regs(priv);
-
-	ndev->stats.tx_errors++;
-	emac_int_disable(priv);
-	cpdma_chan_stop(priv->txchan);
-	cpdma_chan_start(priv->txchan);
-	emac_int_enable(priv);
-}
-
-/**
- * emac_set_type0addr: Set EMAC Type0 mac address
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- * @mac_addr: MAC address to set in device
- *
- * Called internally to set Type0 mac address of the adapter (Device)
- *
- * Returns success (0) or appropriate error code (none as of now)
- */
-static void emac_set_type0addr(struct emac_priv *priv, u32 ch, char *mac_addr)
-{
-	u32 val;
-	val = ((mac_addr[5] << 8) | (mac_addr[4]));
-	emac_write(EMAC_MACSRCADDRLO, val);
-
-	val = ((mac_addr[3] << 24) | (mac_addr[2] << 16) | \
-	       (mac_addr[1] << 8) | (mac_addr[0]));
-	emac_write(EMAC_MACSRCADDRHI, val);
-	val = emac_read(EMAC_RXUNICASTSET);
-	val |= BIT(ch);
-	emac_write(EMAC_RXUNICASTSET, val);
-	val = emac_read(EMAC_RXUNICASTCLEAR);
-	val &= ~BIT(ch);
-	emac_write(EMAC_RXUNICASTCLEAR, val);
-}
-
-/**
- * emac_set_type1addr: Set EMAC Type1 mac address
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- * @mac_addr: MAC address to set in device
- *
- * Called internally to set Type1 mac address of the adapter (Device)
- *
- * Returns success (0) or appropriate error code (none as of now)
- */
-static void emac_set_type1addr(struct emac_priv *priv, u32 ch, char *mac_addr)
-{
-	u32 val;
-	emac_write(EMAC_MACINDEX, ch);
-	val = ((mac_addr[5] << 8) | mac_addr[4]);
-	emac_write(EMAC_MACADDRLO, val);
-	val = ((mac_addr[3] << 24) | (mac_addr[2] << 16) | \
-	       (mac_addr[1] << 8) | (mac_addr[0]));
-	emac_write(EMAC_MACADDRHI, val);
-	emac_set_type0addr(priv, ch, mac_addr);
-}
-
-/**
- * emac_set_type2addr: Set EMAC Type2 mac address
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- * @mac_addr: MAC address to set in device
- * @index: index into RX address entries
- * @match: match parameter for RX address matching logic
- *
- * Called internally to set Type2 mac address of the adapter (Device)
- *
- * Returns success (0) or appropriate error code (none as of now)
- */
-static void emac_set_type2addr(struct emac_priv *priv, u32 ch,
-			       char *mac_addr, int index, int match)
-{
-	u32 val;
-	emac_write(EMAC_MACINDEX, index);
-	val = ((mac_addr[3] << 24) | (mac_addr[2] << 16) | \
-	       (mac_addr[1] << 8) | (mac_addr[0]));
-	emac_write(EMAC_MACADDRHI, val);
-	val = ((mac_addr[5] << 8) | mac_addr[4] | ((ch & 0x7) << 16) | \
-	       (match << 19) | BIT(20));
-	emac_write(EMAC_MACADDRLO, val);
-	emac_set_type0addr(priv, ch, mac_addr);
-}
-
-/**
- * emac_setmac: Set mac address in the adapter (internal function)
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- * @mac_addr: MAC address to set in device
- *
- * Called internally to set the mac address of the adapter (Device)
- *
- * Returns success (0) or appropriate error code (none as of now)
- */
-static void emac_setmac(struct emac_priv *priv, u32 ch, char *mac_addr)
-{
-	struct device *emac_dev = &priv->ndev->dev;
-
-	if (priv->rx_addr_type == 0) {
-		emac_set_type0addr(priv, ch, mac_addr);
-	} else if (priv->rx_addr_type == 1) {
-		u32 cnt;
-		for (cnt = 0; cnt < EMAC_MAX_TXRX_CHANNELS; cnt++)
-			emac_set_type1addr(priv, ch, mac_addr);
-	} else if (priv->rx_addr_type == 2) {
-		emac_set_type2addr(priv, ch, mac_addr, ch, 1);
-		emac_set_type0addr(priv, ch, mac_addr);
-	} else {
-		if (netif_msg_drv(priv))
-			dev_err(emac_dev, "DaVinci EMAC: Wrong addressing\n");
-	}
-}
-
-/**
- * emac_dev_setmac_addr: Set mac address in the adapter
- * @ndev: The DaVinci EMAC network adapter
- * @addr: MAC address to set in device
- *
- * Called by the system to set the mac address of the adapter (Device)
- *
- * Returns success (0) or appropriate error code (none as of now)
- */
-static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
-{
-	struct emac_priv *priv = netdev_priv(ndev);
-	struct device *emac_dev = &priv->ndev->dev;
-	struct sockaddr *sa = addr;
-
-	if (!is_valid_ether_addr(sa->sa_data))
-		return -EINVAL;
-
-	/* Store mac addr in priv and rx channel and set it in EMAC hw */
-	memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len);
-	memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len);
-
-	/* MAC address is configured only after the interface is enabled. */
-	if (netif_running(ndev)) {
-		memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len);
-		emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr);
-	}
-
-	if (netif_msg_drv(priv))
-		dev_notice(emac_dev, "DaVinci EMAC: emac_dev_setmac_addr %pM\n",
-					priv->mac_addr);
-
-	return 0;
-}
-
-/**
- * emac_hw_enable: Enable EMAC hardware for packet transmission/reception
- * @priv: The DaVinci EMAC private adapter structure
- *
- * Enables EMAC hardware for packet processing - enables PHY, enables RX
- * for packet reception and enables device interrupts and then NAPI
- *
- * Returns success (0) or appropriate error code (none right now)
- */
-static int emac_hw_enable(struct emac_priv *priv)
-{
-	u32 val, mbp_enable, mac_control;
-
-	/* Soft reset */
-	emac_write(EMAC_SOFTRESET, 1);
-	while (emac_read(EMAC_SOFTRESET))
-		cpu_relax();
-
-	/* Disable interrupt & Set pacing for more interrupts initially */
-	emac_int_disable(priv);
-
-	/* Full duplex enable bit set when auto negotiation happens */
-	mac_control =
-		(((EMAC_DEF_TXPRIO_FIXED) ? (EMAC_MACCONTROL_TXPTYPE) : 0x0) |
-		((priv->speed == 1000) ? EMAC_MACCONTROL_GIGABITEN : 0x0) |
-		((EMAC_DEF_TXPACING_EN) ? (EMAC_MACCONTROL_TXPACEEN) : 0x0) |
-		((priv->duplex == DUPLEX_FULL) ? 0x1 : 0));
-	emac_write(EMAC_MACCONTROL, mac_control);
-
-	mbp_enable =
-		(((EMAC_DEF_PASS_CRC) ? (EMAC_RXMBP_PASSCRC_MASK) : 0x0) |
-		((EMAC_DEF_QOS_EN) ? (EMAC_RXMBP_QOSEN_MASK) : 0x0) |
-		 ((EMAC_DEF_NO_BUFF_CHAIN) ? (EMAC_RXMBP_NOCHAIN_MASK) : 0x0) |
-		 ((EMAC_DEF_MACCTRL_FRAME_EN) ? (EMAC_RXMBP_CMFEN_MASK) : 0x0) |
-		 ((EMAC_DEF_SHORT_FRAME_EN) ? (EMAC_RXMBP_CSFEN_MASK) : 0x0) |
-		 ((EMAC_DEF_ERROR_FRAME_EN) ? (EMAC_RXMBP_CEFEN_MASK) : 0x0) |
-		 ((EMAC_DEF_PROM_EN) ? (EMAC_RXMBP_CAFEN_MASK) : 0x0) |
-		 ((EMAC_DEF_PROM_CH & EMAC_RXMBP_CHMASK) << \
-			EMAC_RXMBP_PROMCH_SHIFT) |
-		 ((EMAC_DEF_BCAST_EN) ? (EMAC_RXMBP_BROADEN_MASK) : 0x0) |
-		 ((EMAC_DEF_BCAST_CH & EMAC_RXMBP_CHMASK) << \
-			EMAC_RXMBP_BROADCH_SHIFT) |
-		 ((EMAC_DEF_MCAST_EN) ? (EMAC_RXMBP_MULTIEN_MASK) : 0x0) |
-		 ((EMAC_DEF_MCAST_CH & EMAC_RXMBP_CHMASK) << \
-			EMAC_RXMBP_MULTICH_SHIFT));
-	emac_write(EMAC_RXMBPENABLE, mbp_enable);
-	emac_write(EMAC_RXMAXLEN, (EMAC_DEF_MAX_FRAME_SIZE &
-				   EMAC_RX_MAX_LEN_MASK));
-	emac_write(EMAC_RXBUFFEROFFSET, (EMAC_DEF_BUFFER_OFFSET &
-					 EMAC_RX_BUFFER_OFFSET_MASK));
-	emac_write(EMAC_RXFILTERLOWTHRESH, 0);
-	emac_write(EMAC_RXUNICASTCLEAR, EMAC_RX_UNICAST_CLEAR_ALL);
-	priv->rx_addr_type = (emac_read(EMAC_MACCONFIG) >> 8) & 0xFF;
-
-	emac_write(EMAC_MACINTMASKSET, EMAC_MAC_HOST_ERR_INTMASK_VAL);
-
-	emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr);
-
-	/* Enable MII */
-	val = emac_read(EMAC_MACCONTROL);
-	val |= (EMAC_MACCONTROL_GMIIEN);
-	emac_write(EMAC_MACCONTROL, val);
-
-	/* Enable NAPI and interrupts */
-	napi_enable(&priv->napi);
-	emac_int_enable(priv);
-	return 0;
-
-}
-
-/**
- * emac_poll: EMAC NAPI Poll function
- * @ndev: The DaVinci EMAC network adapter
- * @budget: Number of receive packets to process (as told by NAPI layer)
- *
- * NAPI Poll function implemented to process packets as per budget. We check
- * the type of interrupt on the device and accordingly call the TX or RX
- * packet processing functions. We follow the budget for RX processing and
- * also put a cap on number of TX pkts processed through config param. The
- * NAPI schedule function is called if more packets pending.
- *
- * Returns number of packets received (in most cases; else TX pkts - rarely)
- */
-static int emac_poll(struct napi_struct *napi, int budget)
-{
-	unsigned int mask;
-	struct emac_priv *priv = container_of(napi, struct emac_priv, napi);
-	struct net_device *ndev = priv->ndev;
-	struct device *emac_dev = &ndev->dev;
-	u32 status = 0;
-	u32 num_tx_pkts = 0, num_rx_pkts = 0;
-
-	/* Check interrupt vectors and call packet processing */
-	status = emac_read(EMAC_MACINVECTOR);
-
-	mask = EMAC_DM644X_MAC_IN_VECTOR_TX_INT_VEC;
-
-	if (priv->version == EMAC_VERSION_2)
-		mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC;
-
-	if (status & mask) {
-		num_tx_pkts = cpdma_chan_process(priv->txchan,
-					      EMAC_DEF_TX_MAX_SERVICE);
-	} /* TX processing */
-
-	mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC;
-
-	if (priv->version == EMAC_VERSION_2)
-		mask = EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC;
-
-	if (status & mask) {
-		num_rx_pkts = cpdma_chan_process(priv->rxchan, budget);
-	} /* RX processing */
-
-	mask = EMAC_DM644X_MAC_IN_VECTOR_HOST_INT;
-	if (priv->version == EMAC_VERSION_2)
-		mask = EMAC_DM646X_MAC_IN_VECTOR_HOST_INT;
-
-	if (unlikely(status & mask)) {
-		u32 ch, cause;
-		dev_err(emac_dev, "DaVinci EMAC: Fatal Hardware Error\n");
-		netif_stop_queue(ndev);
-		napi_disable(&priv->napi);
-
-		status = emac_read(EMAC_MACSTATUS);
-		cause = ((status & EMAC_MACSTATUS_TXERRCODE_MASK) >>
-			 EMAC_MACSTATUS_TXERRCODE_SHIFT);
-		if (cause) {
-			ch = ((status & EMAC_MACSTATUS_TXERRCH_MASK) >>
-			      EMAC_MACSTATUS_TXERRCH_SHIFT);
-			if (net_ratelimit()) {
-				dev_err(emac_dev, "TX Host error %s on ch=%d\n",
-					&emac_txhost_errcodes[cause][0], ch);
-			}
-		}
-		cause = ((status & EMAC_MACSTATUS_RXERRCODE_MASK) >>
-			 EMAC_MACSTATUS_RXERRCODE_SHIFT);
-		if (cause) {
-			ch = ((status & EMAC_MACSTATUS_RXERRCH_MASK) >>
-			      EMAC_MACSTATUS_RXERRCH_SHIFT);
-			if (netif_msg_hw(priv) && net_ratelimit())
-				dev_err(emac_dev, "RX Host error %s on ch=%d\n",
-					&emac_rxhost_errcodes[cause][0], ch);
-		}
-	} else if (num_rx_pkts < budget) {
-		napi_complete(napi);
-		emac_int_enable(priv);
-	}
-
-	return num_rx_pkts;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/**
- * emac_poll_controller: EMAC Poll controller function
- * @ndev: The DaVinci EMAC network adapter
- *
- * Polled functionality used by netconsole and others in non interrupt mode
- *
- */
-void emac_poll_controller(struct net_device *ndev)
-{
-	struct emac_priv *priv = netdev_priv(ndev);
-
-	emac_int_disable(priv);
-	emac_irq(ndev->irq, ndev);
-	emac_int_enable(priv);
-}
-#endif
-
-static void emac_adjust_link(struct net_device *ndev)
-{
-	struct emac_priv *priv = netdev_priv(ndev);
-	struct phy_device *phydev = priv->phydev;
-	unsigned long flags;
-	int new_state = 0;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	if (phydev->link) {
-		/* check the mode of operation - full/half duplex */
-		if (phydev->duplex != priv->duplex) {
-			new_state = 1;
-			priv->duplex = phydev->duplex;
-		}
-		if (phydev->speed != priv->speed) {
-			new_state = 1;
-			priv->speed = phydev->speed;
-		}
-		if (!priv->link) {
-			new_state = 1;
-			priv->link = 1;
-		}
-
-	} else if (priv->link) {
-		new_state = 1;
-		priv->link = 0;
-		priv->speed = 0;
-		priv->duplex = ~0;
-	}
-	if (new_state) {
-		emac_update_phystatus(priv);
-		phy_print_status(priv->phydev);
-	}
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-/*************************************************************************
- *  Linux Driver Model
- *************************************************************************/
-
-/**
- * emac_devioctl: EMAC adapter ioctl
- * @ndev: The DaVinci EMAC network adapter
- * @ifrq: request parameter
- * @cmd: command parameter
- *
- * EMAC driver ioctl function
- *
- * Returns success(0) or appropriate error code
- */
-static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
-{
-	struct emac_priv *priv = netdev_priv(ndev);
-
-	if (!(netif_running(ndev)))
-		return -EINVAL;
-
-	/* TODO: Add phy read and write and private statistics get feature */
-
-	return phy_mii_ioctl(priv->phydev, ifrq, cmd);
-}
-
-static int match_first_device(struct device *dev, void *data)
-{
-	return 1;
-}
-
-/**
- * emac_dev_open: EMAC device open
- * @ndev: The DaVinci EMAC network adapter
- *
- * Called when system wants to start the interface. We init TX/RX channels
- * and enable the hardware for packet reception/transmission and start the
- * network queue.
- *
- * Returns 0 for a successful open, or appropriate error code
- */
-static int emac_dev_open(struct net_device *ndev)
-{
-	struct device *emac_dev = &ndev->dev;
-	u32 cnt;
-	struct resource *res;
-	int q, m, ret;
-	int i = 0;
-	int k = 0;
-	struct emac_priv *priv = netdev_priv(ndev);
-
-	netif_carrier_off(ndev);
-	for (cnt = 0; cnt < ETH_ALEN; cnt++)
-		ndev->dev_addr[cnt] = priv->mac_addr[cnt];
-
-	/* Configuration items */
-	priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN;
-
-	priv->mac_hash1 = 0;
-	priv->mac_hash2 = 0;
-	emac_write(EMAC_MACHASH1, 0);
-	emac_write(EMAC_MACHASH2, 0);
-
-	for (i = 0; i < EMAC_DEF_RX_NUM_DESC; i++) {
-		struct sk_buff *skb = emac_rx_alloc(priv);
-
-		if (!skb)
-			break;
-
-		ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
-					skb_tailroom(skb), GFP_KERNEL);
-		if (WARN_ON(ret < 0))
-			break;
-	}
-
-	/* Request IRQ */
-
-	while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) {
-		for (i = res->start; i <= res->end; i++) {
-			if (request_irq(i, emac_irq, IRQF_DISABLED,
-					ndev->name, ndev))
-				goto rollback;
-		}
-		k++;
-	}
-
-	/* Start/Enable EMAC hardware */
-	emac_hw_enable(priv);
-
-	/* Enable Interrupt pacing if configured */
-	if (priv->coal_intvl != 0) {
-		struct ethtool_coalesce coal;
-
-		coal.rx_coalesce_usecs = (priv->coal_intvl << 4);
-		emac_set_coalesce(ndev, &coal);
-	}
-
-	cpdma_ctlr_start(priv->dma);
-
-	priv->phydev = NULL;
-	/* use the first phy on the bus if pdata did not give us a phy id */
-	if (!priv->phy_id) {
-		struct device *phy;
-
-		phy = bus_find_device(&mdio_bus_type, NULL, NULL,
-				      match_first_device);
-		if (phy)
-			priv->phy_id = dev_name(phy);
-	}
-
-	if (priv->phy_id && *priv->phy_id) {
-		priv->phydev = phy_connect(ndev, priv->phy_id,
-					   &emac_adjust_link, 0,
-					   PHY_INTERFACE_MODE_MII);
-
-		if (IS_ERR(priv->phydev)) {
-			dev_err(emac_dev, "could not connect to phy %s\n",
-				priv->phy_id);
-			priv->phydev = NULL;
-			return PTR_ERR(priv->phydev);
-		}
-
-		priv->link = 0;
-		priv->speed = 0;
-		priv->duplex = ~0;
-
-		dev_info(emac_dev, "attached PHY driver [%s] "
-			"(mii_bus:phy_addr=%s, id=%x)\n",
-			priv->phydev->drv->name, dev_name(&priv->phydev->dev),
-			priv->phydev->phy_id);
-	} else {
-		/* No PHY , fix the link, speed and duplex settings */
-		dev_notice(emac_dev, "no phy, defaulting to 100/full\n");
-		priv->link = 1;
-		priv->speed = SPEED_100;
-		priv->duplex = DUPLEX_FULL;
-		emac_update_phystatus(priv);
-	}
-
-	if (!netif_running(ndev)) /* debug only - to avoid compiler warning */
-		emac_dump_regs(priv);
-
-	if (netif_msg_drv(priv))
-		dev_notice(emac_dev, "DaVinci EMAC: Opened %s\n", ndev->name);
-
-	if (priv->phydev)
-		phy_start(priv->phydev);
-
-	return 0;
-
-rollback:
-
-	dev_err(emac_dev, "DaVinci EMAC: request_irq() failed");
-
-	for (q = k; k >= 0; k--) {
-		for (m = i; m >= res->start; m--)
-			free_irq(m, ndev);
-		res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k-1);
-		m = res->end;
-	}
-	return -EBUSY;
-}
-
-/**
- * emac_dev_stop: EMAC device stop
- * @ndev: The DaVinci EMAC network adapter
- *
- * Called when system wants to stop or down the interface. We stop the network
- * queue, disable interrupts and cleanup TX/RX channels.
- *
- * We return the statistics in net_device_stats structure pulled from emac
- */
-static int emac_dev_stop(struct net_device *ndev)
-{
-	struct resource *res;
-	int i = 0;
-	int irq_num;
-	struct emac_priv *priv = netdev_priv(ndev);
-	struct device *emac_dev = &ndev->dev;
-
-	/* inform the upper layers. */
-	netif_stop_queue(ndev);
-	napi_disable(&priv->napi);
-
-	netif_carrier_off(ndev);
-	emac_int_disable(priv);
-	cpdma_ctlr_stop(priv->dma);
-	emac_write(EMAC_SOFTRESET, 1);
-
-	if (priv->phydev)
-		phy_disconnect(priv->phydev);
-
-	/* Free IRQ */
-	while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, i))) {
-		for (irq_num = res->start; irq_num <= res->end; irq_num++)
-			free_irq(irq_num, priv->ndev);
-		i++;
-	}
-
-	if (netif_msg_drv(priv))
-		dev_notice(emac_dev, "DaVinci EMAC: %s stopped\n", ndev->name);
-
-	return 0;
-}
-
-/**
- * emac_dev_getnetstats: EMAC get statistics function
- * @ndev: The DaVinci EMAC network adapter
- *
- * Called when system wants to get statistics from the device.
- *
- * We return the statistics in net_device_stats structure pulled from emac
- */
-static struct net_device_stats *emac_dev_getnetstats(struct net_device *ndev)
-{
-	struct emac_priv *priv = netdev_priv(ndev);
-	u32 mac_control;
-	u32 stats_clear_mask;
-
-	/* update emac hardware stats and reset the registers*/
-
-	mac_control = emac_read(EMAC_MACCONTROL);
-
-	if (mac_control & EMAC_MACCONTROL_GMIIEN)
-		stats_clear_mask = EMAC_STATS_CLR_MASK;
-	else
-		stats_clear_mask = 0;
-
-	ndev->stats.multicast += emac_read(EMAC_RXMCASTFRAMES);
-	emac_write(EMAC_RXMCASTFRAMES, stats_clear_mask);
-
-	ndev->stats.collisions += (emac_read(EMAC_TXCOLLISION) +
-					   emac_read(EMAC_TXSINGLECOLL) +
-					   emac_read(EMAC_TXMULTICOLL));
-	emac_write(EMAC_TXCOLLISION, stats_clear_mask);
-	emac_write(EMAC_TXSINGLECOLL, stats_clear_mask);
-	emac_write(EMAC_TXMULTICOLL, stats_clear_mask);
-
-	ndev->stats.rx_length_errors += (emac_read(EMAC_RXOVERSIZED) +
-						emac_read(EMAC_RXJABBER) +
-						emac_read(EMAC_RXUNDERSIZED));
-	emac_write(EMAC_RXOVERSIZED, stats_clear_mask);
-	emac_write(EMAC_RXJABBER, stats_clear_mask);
-	emac_write(EMAC_RXUNDERSIZED, stats_clear_mask);
-
-	ndev->stats.rx_over_errors += (emac_read(EMAC_RXSOFOVERRUNS) +
-					       emac_read(EMAC_RXMOFOVERRUNS));
-	emac_write(EMAC_RXSOFOVERRUNS, stats_clear_mask);
-	emac_write(EMAC_RXMOFOVERRUNS, stats_clear_mask);
-
-	ndev->stats.rx_fifo_errors += emac_read(EMAC_RXDMAOVERRUNS);
-	emac_write(EMAC_RXDMAOVERRUNS, stats_clear_mask);
-
-	ndev->stats.tx_carrier_errors +=
-		emac_read(EMAC_TXCARRIERSENSE);
-	emac_write(EMAC_TXCARRIERSENSE, stats_clear_mask);
-
-	ndev->stats.tx_fifo_errors += emac_read(EMAC_TXUNDERRUN);
-	emac_write(EMAC_TXUNDERRUN, stats_clear_mask);
-
-	return &ndev->stats;
-}
-
-static const struct net_device_ops emac_netdev_ops = {
-	.ndo_open		= emac_dev_open,
-	.ndo_stop		= emac_dev_stop,
-	.ndo_start_xmit		= emac_dev_xmit,
-	.ndo_set_multicast_list	= emac_dev_mcast_set,
-	.ndo_set_mac_address	= emac_dev_setmac_addr,
-	.ndo_do_ioctl		= emac_devioctl,
-	.ndo_tx_timeout		= emac_dev_tx_timeout,
-	.ndo_get_stats		= emac_dev_getnetstats,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= emac_poll_controller,
-#endif
-};
-
-/**
- * davinci_emac_probe: EMAC device probe
- * @pdev: The DaVinci EMAC device that we are removing
- *
- * Called when probing for emac devicesr. We get details of instances and
- * resource information from platform init and register a network device
- * and allocate resources necessary for driver to perform
- */
-static int __devinit davinci_emac_probe(struct platform_device *pdev)
-{
-	int rc = 0;
-	struct resource *res;
-	struct net_device *ndev;
-	struct emac_priv *priv;
-	unsigned long size, hw_ram_addr;
-	struct emac_platform_data *pdata;
-	struct device *emac_dev;
-	struct cpdma_params dma_params;
-
-	/* obtain emac clock from kernel */
-	emac_clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(emac_clk)) {
-		dev_err(&pdev->dev, "failed to get EMAC clock\n");
-		return -EBUSY;
-	}
-	emac_bus_frequency = clk_get_rate(emac_clk);
-	/* TODO: Probe PHY here if possible */
-
-	ndev = alloc_etherdev(sizeof(struct emac_priv));
-	if (!ndev) {
-		dev_err(&pdev->dev, "error allocating net_device\n");
-		rc = -ENOMEM;
-		goto free_clk;
-	}
-
-	platform_set_drvdata(pdev, ndev);
-	priv = netdev_priv(ndev);
-	priv->pdev = pdev;
-	priv->ndev = ndev;
-	priv->msg_enable = netif_msg_init(debug_level, DAVINCI_EMAC_DEBUG);
-
-	spin_lock_init(&priv->lock);
-
-	pdata = pdev->dev.platform_data;
-	if (!pdata) {
-		dev_err(&pdev->dev, "no platform data\n");
-		rc = -ENODEV;
-		goto probe_quit;
-	}
-
-	/* MAC addr and PHY mask , RMII enable info from platform_data */
-	memcpy(priv->mac_addr, pdata->mac_addr, 6);
-	priv->phy_id = pdata->phy_id;
-	priv->rmii_en = pdata->rmii_en;
-	priv->version = pdata->version;
-	priv->int_enable = pdata->interrupt_enable;
-	priv->int_disable = pdata->interrupt_disable;
-
-	priv->coal_intvl = 0;
-	priv->bus_freq_mhz = (u32)(emac_bus_frequency / 1000000);
-
-	emac_dev = &ndev->dev;
-	/* Get EMAC platform data */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev,"error getting res\n");
-		rc = -ENOENT;
-		goto probe_quit;
-	}
-
-	priv->emac_base_phys = res->start + pdata->ctrl_reg_offset;
-	size = resource_size(res);
-	if (!request_mem_region(res->start, size, ndev->name)) {
-		dev_err(&pdev->dev, "failed request_mem_region() for regs\n");
-		rc = -ENXIO;
-		goto probe_quit;
-	}
-
-	priv->remap_addr = ioremap(res->start, size);
-	if (!priv->remap_addr) {
-		dev_err(&pdev->dev, "unable to map IO\n");
-		rc = -ENOMEM;
-		release_mem_region(res->start, size);
-		goto probe_quit;
-	}
-	priv->emac_base = priv->remap_addr + pdata->ctrl_reg_offset;
-	ndev->base_addr = (unsigned long)priv->remap_addr;
-
-	priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset;
-
-	hw_ram_addr = pdata->hw_ram_addr;
-	if (!hw_ram_addr)
-		hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset;
-
-	memset(&dma_params, 0, sizeof(dma_params));
-	dma_params.dev			= emac_dev;
-	dma_params.dmaregs		= priv->emac_base;
-	dma_params.rxthresh		= priv->emac_base + 0x120;
-	dma_params.rxfree		= priv->emac_base + 0x140;
-	dma_params.txhdp		= priv->emac_base + 0x600;
-	dma_params.rxhdp		= priv->emac_base + 0x620;
-	dma_params.txcp			= priv->emac_base + 0x640;
-	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_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(&pdev->dev, "error initializing DMA\n");
-		rc = -ENOMEM;
-		goto no_dma;
-	}
-
-	priv->txchan = cpdma_chan_create(priv->dma, tx_chan_num(EMAC_DEF_TX_CH),
-				       emac_tx_handler);
-	priv->rxchan = cpdma_chan_create(priv->dma, rx_chan_num(EMAC_DEF_RX_CH),
-				       emac_rx_handler);
-	if (WARN_ON(!priv->txchan || !priv->rxchan)) {
-		rc = -ENOMEM;
-		goto no_irq_res;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "error getting irq res\n");
-		rc = -ENOENT;
-		goto no_irq_res;
-	}
-	ndev->irq = res->start;
-
-	if (!is_valid_ether_addr(priv->mac_addr)) {
-		/* Use random MAC if none passed */
-		random_ether_addr(priv->mac_addr);
-		dev_warn(&pdev->dev, "using random MAC addr: %pM\n",
-							priv->mac_addr);
-	}
-
-	ndev->netdev_ops = &emac_netdev_ops;
-	SET_ETHTOOL_OPS(ndev, &ethtool_ops);
-	netif_napi_add(ndev, &priv->napi, emac_poll, EMAC_POLL_WEIGHT);
-
-	clk_enable(emac_clk);
-
-	/* register the network device */
-	SET_NETDEV_DEV(ndev, &pdev->dev);
-	rc = register_netdev(ndev);
-	if (rc) {
-		dev_err(&pdev->dev, "error in register_netdev\n");
-		rc = -ENODEV;
-		goto netdev_reg_err;
-	}
-
-
-	if (netif_msg_probe(priv)) {
-		dev_notice(emac_dev, "DaVinci EMAC Probe found device "\
-			   "(regs: %p, irq: %d)\n",
-			   (void *)priv->emac_base_phys, ndev->irq);
-	}
-	return 0;
-
-netdev_reg_err:
-	clk_disable(emac_clk);
-no_irq_res:
-	if (priv->txchan)
-		cpdma_chan_destroy(priv->txchan);
-	if (priv->rxchan)
-		cpdma_chan_destroy(priv->rxchan);
-	cpdma_ctlr_destroy(priv->dma);
-no_dma:
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-	iounmap(priv->remap_addr);
-
-probe_quit:
-	free_netdev(ndev);
-free_clk:
-	clk_put(emac_clk);
-	return rc;
-}
-
-/**
- * davinci_emac_remove: EMAC device remove
- * @pdev: The DaVinci EMAC device that we are removing
- *
- * Called when removing the device driver. We disable clock usage and release
- * the resources taken up by the driver and unregister network device
- */
-static int __devexit davinci_emac_remove(struct platform_device *pdev)
-{
-	struct resource *res;
-	struct net_device *ndev = platform_get_drvdata(pdev);
-	struct emac_priv *priv = netdev_priv(ndev);
-
-	dev_notice(&ndev->dev, "DaVinci EMAC: davinci_emac_remove()\n");
-
-	platform_set_drvdata(pdev, NULL);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	if (priv->txchan)
-		cpdma_chan_destroy(priv->txchan);
-	if (priv->rxchan)
-		cpdma_chan_destroy(priv->rxchan);
-	cpdma_ctlr_destroy(priv->dma);
-
-	release_mem_region(res->start, resource_size(res));
-
-	unregister_netdev(ndev);
-	iounmap(priv->remap_addr);
-	free_netdev(ndev);
-
-	clk_disable(emac_clk);
-	clk_put(emac_clk);
-
-	return 0;
-}
-
-static int davinci_emac_suspend(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct net_device *ndev = platform_get_drvdata(pdev);
-
-	if (netif_running(ndev))
-		emac_dev_stop(ndev);
-
-	clk_disable(emac_clk);
-
-	return 0;
-}
-
-static int davinci_emac_resume(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct net_device *ndev = platform_get_drvdata(pdev);
-
-	clk_enable(emac_clk);
-
-	if (netif_running(ndev))
-		emac_dev_open(ndev);
-
-	return 0;
-}
-
-static const struct dev_pm_ops davinci_emac_pm_ops = {
-	.suspend	= davinci_emac_suspend,
-	.resume		= davinci_emac_resume,
-};
-
-/**
- * davinci_emac_driver: EMAC platform driver structure
- */
-static struct platform_driver davinci_emac_driver = {
-	.driver = {
-		.name	 = "davinci_emac",
-		.owner	 = THIS_MODULE,
-		.pm	 = &davinci_emac_pm_ops,
-	},
-	.probe = davinci_emac_probe,
-	.remove = __devexit_p(davinci_emac_remove),
-};
-
-/**
- * davinci_emac_init: EMAC driver module init
- *
- * Called when initializing the driver. We register the driver with
- * the platform.
- */
-static int __init davinci_emac_init(void)
-{
-	return platform_driver_register(&davinci_emac_driver);
-}
-late_initcall(davinci_emac_init);
-
-/**
- * davinci_emac_exit: EMAC driver module exit
- *
- * Called when exiting the driver completely. We unregister the driver with
- * the platform and exit
- */
-static void __exit davinci_emac_exit(void)
-{
-	platform_driver_unregister(&davinci_emac_driver);
-}
-module_exit(davinci_emac_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("DaVinci EMAC Maintainer: Anant Gole <anantgole@ti.com>");
-MODULE_AUTHOR("DaVinci EMAC Maintainer: Chaithrika U S <chaithrika@ti.com>");
-MODULE_DESCRIPTION("DaVinci EMAC Ethernet driver");
diff -druN linux-libre-3.1-gnu/drivers/net/davinci_mdio.c linux-libre-3.2-gnu/drivers/net/davinci_mdio.c
--- linux-libre-3.1-gnu/drivers/net/davinci_mdio.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/davinci_mdio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,475 +0,0 @@
-/*
- * DaVinci MDIO Module driver
- *
- * Copyright (C) 2010 Texas Instruments.
- *
- * Shamelessly ripped out of davinci_emac.c, original copyrights follow:
- *
- * Copyright (C) 2009 Texas Instruments.
- *
- * ---------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- * ---------------------------------------------------------------------------
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/phy.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/davinci_emac.h>
-
-/*
- * This timeout definition is a worst-case ultra defensive measure against
- * unexpected controller lock ups.  Ideally, we should never ever hit this
- * scenario in practice.
- */
-#define MDIO_TIMEOUT		100 /* msecs */
-
-#define PHY_REG_MASK		0x1f
-#define PHY_ID_MASK		0x1f
-
-#define DEF_OUT_FREQ		2200000		/* 2.2 MHz */
-
-struct davinci_mdio_regs {
-	u32	version;
-	u32	control;
-#define CONTROL_IDLE		BIT(31)
-#define CONTROL_ENABLE		BIT(30)
-#define CONTROL_MAX_DIV		(0xff)
-
-	u32	alive;
-	u32	link;
-	u32	linkintraw;
-	u32	linkintmasked;
-	u32	__reserved_0[2];
-	u32	userintraw;
-	u32	userintmasked;
-	u32	userintmaskset;
-	u32	userintmaskclr;
-	u32	__reserved_1[20];
-
-	struct {
-		u32	access;
-#define USERACCESS_GO		BIT(31)
-#define USERACCESS_WRITE	BIT(30)
-#define USERACCESS_ACK		BIT(29)
-#define USERACCESS_READ		(0)
-#define USERACCESS_DATA		(0xffff)
-
-		u32	physel;
-	}	user[0];
-};
-
-struct mdio_platform_data default_pdata = {
-	.bus_freq = DEF_OUT_FREQ,
-};
-
-struct davinci_mdio_data {
-	struct mdio_platform_data pdata;
-	struct davinci_mdio_regs __iomem *regs;
-	spinlock_t	lock;
-	struct clk	*clk;
-	struct device	*dev;
-	struct mii_bus	*bus;
-	bool		suspended;
-	unsigned long	access_time; /* jiffies */
-};
-
-static void __davinci_mdio_reset(struct davinci_mdio_data *data)
-{
-	u32 mdio_in, div, mdio_out_khz, access_time;
-
-	mdio_in = clk_get_rate(data->clk);
-	div = (mdio_in / data->pdata.bus_freq) - 1;
-	if (div > CONTROL_MAX_DIV)
-		div = CONTROL_MAX_DIV;
-
-	/* set enable and clock divider */
-	__raw_writel(div | CONTROL_ENABLE, &data->regs->control);
-
-	/*
-	 * One mdio transaction consists of:
-	 *	32 bits of preamble
-	 *	32 bits of transferred data
-	 *	24 bits of bus yield (not needed unless shared?)
-	 */
-	mdio_out_khz = mdio_in / (1000 * (div + 1));
-	access_time  = (88 * 1000) / mdio_out_khz;
-
-	/*
-	 * In the worst case, we could be kicking off a user-access immediately
-	 * after the mdio bus scan state-machine triggered its own read.  If
-	 * so, our request could get deferred by one access cycle.  We
-	 * defensively allow for 4 access cycles.
-	 */
-	data->access_time = usecs_to_jiffies(access_time * 4);
-	if (!data->access_time)
-		data->access_time = 1;
-}
-
-static int davinci_mdio_reset(struct mii_bus *bus)
-{
-	struct davinci_mdio_data *data = bus->priv;
-	u32 phy_mask, ver;
-
-	__davinci_mdio_reset(data);
-
-	/* wait for scan logic to settle */
-	msleep(PHY_MAX_ADDR * data->access_time);
-
-	/* dump hardware version info */
-	ver = __raw_readl(&data->regs->version);
-	dev_info(data->dev, "davinci mdio revision %d.%d\n",
-		 (ver >> 8) & 0xff, ver & 0xff);
-
-	/* get phy mask from the alive register */
-	phy_mask = __raw_readl(&data->regs->alive);
-	if (phy_mask) {
-		/* restrict mdio bus to live phys only */
-		dev_info(data->dev, "detected phy mask %x\n", ~phy_mask);
-		phy_mask = ~phy_mask;
-	} else {
-		/* desperately scan all phys */
-		dev_warn(data->dev, "no live phy, scanning all\n");
-		phy_mask = 0;
-	}
-	data->bus->phy_mask = phy_mask;
-
-	return 0;
-}
-
-/* wait until hardware is ready for another user access */
-static inline int wait_for_user_access(struct davinci_mdio_data *data)
-{
-	struct davinci_mdio_regs __iomem *regs = data->regs;
-	unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT);
-	u32 reg;
-
-	while (time_after(timeout, jiffies)) {
-		reg = __raw_readl(&regs->user[0].access);
-		if ((reg & USERACCESS_GO) == 0)
-			return 0;
-
-		reg = __raw_readl(&regs->control);
-		if ((reg & CONTROL_IDLE) == 0)
-			continue;
-
-		/*
-		 * An emac soft_reset may have clobbered the mdio controller's
-		 * state machine.  We need to reset and retry the current
-		 * operation
-		 */
-		dev_warn(data->dev, "resetting idled controller\n");
-		__davinci_mdio_reset(data);
-		return -EAGAIN;
-	}
-	dev_err(data->dev, "timed out waiting for user access\n");
-	return -ETIMEDOUT;
-}
-
-/* wait until hardware state machine is idle */
-static inline int wait_for_idle(struct davinci_mdio_data *data)
-{
-	struct davinci_mdio_regs __iomem *regs = data->regs;
-	unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT);
-
-	while (time_after(timeout, jiffies)) {
-		if (__raw_readl(&regs->control) & CONTROL_IDLE)
-			return 0;
-	}
-	dev_err(data->dev, "timed out waiting for idle\n");
-	return -ETIMEDOUT;
-}
-
-static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg)
-{
-	struct davinci_mdio_data *data = bus->priv;
-	u32 reg;
-	int ret;
-
-	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
-		return -EINVAL;
-
-	spin_lock(&data->lock);
-
-	if (data->suspended) {
-		spin_unlock(&data->lock);
-		return -ENODEV;
-	}
-
-	reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) |
-	       (phy_id << 16));
-
-	while (1) {
-		ret = wait_for_user_access(data);
-		if (ret == -EAGAIN)
-			continue;
-		if (ret < 0)
-			break;
-
-		__raw_writel(reg, &data->regs->user[0].access);
-
-		ret = wait_for_user_access(data);
-		if (ret == -EAGAIN)
-			continue;
-		if (ret < 0)
-			break;
-
-		reg = __raw_readl(&data->regs->user[0].access);
-		ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO;
-		break;
-	}
-
-	spin_unlock(&data->lock);
-
-	return ret;
-}
-
-static int davinci_mdio_write(struct mii_bus *bus, int phy_id,
-			      int phy_reg, u16 phy_data)
-{
-	struct davinci_mdio_data *data = bus->priv;
-	u32 reg;
-	int ret;
-
-	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
-		return -EINVAL;
-
-	spin_lock(&data->lock);
-
-	if (data->suspended) {
-		spin_unlock(&data->lock);
-		return -ENODEV;
-	}
-
-	reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) |
-		   (phy_id << 16) | (phy_data & USERACCESS_DATA));
-
-	while (1) {
-		ret = wait_for_user_access(data);
-		if (ret == -EAGAIN)
-			continue;
-		if (ret < 0)
-			break;
-
-		__raw_writel(reg, &data->regs->user[0].access);
-
-		ret = wait_for_user_access(data);
-		if (ret == -EAGAIN)
-			continue;
-		break;
-	}
-
-	spin_unlock(&data->lock);
-
-	return 0;
-}
-
-static int __devinit davinci_mdio_probe(struct platform_device *pdev)
-{
-	struct mdio_platform_data *pdata = pdev->dev.platform_data;
-	struct device *dev = &pdev->dev;
-	struct davinci_mdio_data *data;
-	struct resource *res;
-	struct phy_device *phy;
-	int ret, addr;
-
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data) {
-		dev_err(dev, "failed to alloc device data\n");
-		return -ENOMEM;
-	}
-
-	data->pdata = pdata ? (*pdata) : default_pdata;
-
-	data->bus = mdiobus_alloc();
-	if (!data->bus) {
-		dev_err(dev, "failed to alloc mii bus\n");
-		ret = -ENOMEM;
-		goto bail_out;
-	}
-
-	data->bus->name		= dev_name(dev);
-	data->bus->read		= davinci_mdio_read,
-	data->bus->write	= davinci_mdio_write,
-	data->bus->reset	= davinci_mdio_reset,
-	data->bus->parent	= dev;
-	data->bus->priv		= data;
-	snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
-
-	data->clk = clk_get(dev, NULL);
-	if (IS_ERR(data->clk)) {
-		data->clk = NULL;
-		dev_err(dev, "failed to get device clock\n");
-		ret = PTR_ERR(data->clk);
-		goto bail_out;
-	}
-
-	clk_enable(data->clk);
-
-	dev_set_drvdata(dev, data);
-	data->dev = dev;
-	spin_lock_init(&data->lock);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "could not find register map resource\n");
-		ret = -ENOENT;
-		goto bail_out;
-	}
-
-	res = devm_request_mem_region(dev, res->start, resource_size(res),
-					    dev_name(dev));
-	if (!res) {
-		dev_err(dev, "could not allocate register map resource\n");
-		ret = -ENXIO;
-		goto bail_out;
-	}
-
-	data->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
-	if (!data->regs) {
-		dev_err(dev, "could not map mdio registers\n");
-		ret = -ENOMEM;
-		goto bail_out;
-	}
-
-	/* register the mii bus */
-	ret = mdiobus_register(data->bus);
-	if (ret)
-		goto bail_out;
-
-	/* scan and dump the bus */
-	for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
-		phy = data->bus->phy_map[addr];
-		if (phy) {
-			dev_info(dev, "phy[%d]: device %s, driver %s\n",
-				 phy->addr, dev_name(&phy->dev),
-				 phy->drv ? phy->drv->name : "unknown");
-		}
-	}
-
-	return 0;
-
-bail_out:
-	if (data->bus)
-		mdiobus_free(data->bus);
-
-	if (data->clk) {
-		clk_disable(data->clk);
-		clk_put(data->clk);
-	}
-
-	kfree(data);
-
-	return ret;
-}
-
-static int __devexit davinci_mdio_remove(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct davinci_mdio_data *data = dev_get_drvdata(dev);
-
-	if (data->bus)
-		mdiobus_free(data->bus);
-
-	if (data->clk) {
-		clk_disable(data->clk);
-		clk_put(data->clk);
-	}
-
-	dev_set_drvdata(dev, NULL);
-
-	kfree(data);
-
-	return 0;
-}
-
-static int davinci_mdio_suspend(struct device *dev)
-{
-	struct davinci_mdio_data *data = dev_get_drvdata(dev);
-	u32 ctrl;
-
-	spin_lock(&data->lock);
-
-	/* shutdown the scan state machine */
-	ctrl = __raw_readl(&data->regs->control);
-	ctrl &= ~CONTROL_ENABLE;
-	__raw_writel(ctrl, &data->regs->control);
-	wait_for_idle(data);
-
-	if (data->clk)
-		clk_disable(data->clk);
-
-	data->suspended = true;
-	spin_unlock(&data->lock);
-
-	return 0;
-}
-
-static int davinci_mdio_resume(struct device *dev)
-{
-	struct davinci_mdio_data *data = dev_get_drvdata(dev);
-	u32 ctrl;
-
-	spin_lock(&data->lock);
-	if (data->clk)
-		clk_enable(data->clk);
-
-	/* restart the scan state machine */
-	ctrl = __raw_readl(&data->regs->control);
-	ctrl |= CONTROL_ENABLE;
-	__raw_writel(ctrl, &data->regs->control);
-
-	data->suspended = false;
-	spin_unlock(&data->lock);
-
-	return 0;
-}
-
-static const struct dev_pm_ops davinci_mdio_pm_ops = {
-	.suspend	= davinci_mdio_suspend,
-	.resume		= davinci_mdio_resume,
-};
-
-static struct platform_driver davinci_mdio_driver = {
-	.driver = {
-		.name	 = "davinci_mdio",
-		.owner	 = THIS_MODULE,
-		.pm	 = &davinci_mdio_pm_ops,
-	},
-	.probe = davinci_mdio_probe,
-	.remove = __devexit_p(davinci_mdio_remove),
-};
-
-static int __init davinci_mdio_init(void)
-{
-	return platform_driver_register(&davinci_mdio_driver);
-}
-device_initcall(davinci_mdio_init);
-
-static void __exit davinci_mdio_exit(void)
-{
-	platform_driver_unregister(&davinci_mdio_driver);
-}
-module_exit(davinci_mdio_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("DaVinci MDIO driver");
diff -druN linux-libre-3.1-gnu/drivers/net/de600.c linux-libre-3.2-gnu/drivers/net/de600.c
--- linux-libre-3.1-gnu/drivers/net/de600.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/de600.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,530 +0,0 @@
-static const char version[] = "de600.c: $Revision: 1.41-2.5 $,  Bjorn Ekwall (bj0rn@blox.se)\n";
-/*
- *	de600.c
- *
- *	Linux driver for the D-Link DE-600 Ethernet pocket adapter.
- *
- *	Portions (C) Copyright 1993, 1994 by Bjorn Ekwall
- *	The Author may be reached as bj0rn@blox.se
- *
- *	Based on adapter information gathered from DE600.ASM by D-Link Inc.,
- *	as included on disk C in the v.2.11 of PC/TCP from FTP Software.
- *	For DE600.asm:
- *		Portions (C) Copyright 1990 D-Link, Inc.
- *		Copyright, 1988-1992, Russell Nelson, Crynwr Software
- *
- *	Adapted to the sample network driver core for linux,
- *	written by: Donald Becker <becker@super.org>
- *		(Now at <becker@scyld.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; if not, write to the Free Software
- *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- **************************************************************/
-
-/* Add more time here if your adapter won't work OK: */
-#define DE600_SLOW_DOWN	udelay(delay_time)
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <asm/system.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#include <asm/io.h>
-
-#include "de600.h"
-
-static unsigned int check_lost = 1;
-module_param(check_lost, bool, 0);
-MODULE_PARM_DESC(check_lost, "If set then check for unplugged de600");
-
-static unsigned int delay_time = 10;
-module_param(delay_time, int, 0);
-MODULE_PARM_DESC(delay_time, "DE-600 deley on I/O in microseconds");
-
-
-/*
- * D-Link driver variables:
- */
-
-static volatile int		rx_page;
-
-#define TX_PAGES 2
-static volatile int		tx_fifo[TX_PAGES];
-static volatile int		tx_fifo_in;
-static volatile int		tx_fifo_out;
-static volatile int		free_tx_pages = TX_PAGES;
-static int			was_down;
-static DEFINE_SPINLOCK(de600_lock);
-
-static inline u8 de600_read_status(struct net_device *dev)
-{
-	u8 status;
-
-	outb_p(STATUS, DATA_PORT);
-	status = inb(STATUS_PORT);
-	outb_p(NULL_COMMAND | HI_NIBBLE, DATA_PORT);
-
-	return status;
-}
-
-static inline u8 de600_read_byte(unsigned char type, struct net_device *dev)
-{
-	/* dev used by macros */
-	u8 lo;
-	outb_p((type), DATA_PORT);
-	lo = ((unsigned char)inb(STATUS_PORT)) >> 4;
-	outb_p((type) | HI_NIBBLE, DATA_PORT);
-	return ((unsigned char)inb(STATUS_PORT) & (unsigned char)0xf0) | lo;
-}
-
-/*
- * Open/initialize the board.  This is called (in the current kernel)
- * after booting when 'ifconfig <dev->name> $IP_ADDR' is run (in rc.inet1).
- *
- * This routine should set everything up anew at each open, even
- * registers that "should" only need to be set once at boot, so that
- * there is a non-reboot way to recover if something goes wrong.
- */
-
-static int de600_open(struct net_device *dev)
-{
-	unsigned long flags;
-	int ret = request_irq(DE600_IRQ, de600_interrupt, 0, dev->name, dev);
-	if (ret) {
-		printk(KERN_ERR "%s: unable to get IRQ %d\n", dev->name, DE600_IRQ);
-		return ret;
-	}
-	spin_lock_irqsave(&de600_lock, flags);
-	ret = adapter_init(dev);
-	spin_unlock_irqrestore(&de600_lock, flags);
-	return ret;
-}
-
-/*
- * The inverse routine to de600_open().
- */
-
-static int de600_close(struct net_device *dev)
-{
-	select_nic();
-	rx_page = 0;
-	de600_put_command(RESET);
-	de600_put_command(STOP_RESET);
-	de600_put_command(0);
-	select_prn();
-	free_irq(DE600_IRQ, dev);
-	return 0;
-}
-
-static inline void trigger_interrupt(struct net_device *dev)
-{
-	de600_put_command(FLIP_IRQ);
-	select_prn();
-	DE600_SLOW_DOWN;
-	select_nic();
-	de600_put_command(0);
-}
-
-/*
- * Copy a buffer to the adapter transmit page memory.
- * Start sending.
- */
-
-static int de600_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	unsigned long flags;
-	int	transmit_from;
-	int	len;
-	int	tickssofar;
-	u8	*buffer = skb->data;
-	int	i;
-
-	if (free_tx_pages <= 0) {	/* Do timeouts, to avoid hangs. */
-		tickssofar = jiffies - dev_trans_start(dev);
-		if (tickssofar < HZ/20)
-			return NETDEV_TX_BUSY;
-		/* else */
-		printk(KERN_WARNING "%s: transmit timed out (%d), %s?\n", dev->name, tickssofar, "network cable problem");
-		/* Restart the adapter. */
-		spin_lock_irqsave(&de600_lock, flags);
-		if (adapter_init(dev)) {
-			spin_unlock_irqrestore(&de600_lock, flags);
-			return NETDEV_TX_BUSY;
-		}
-		spin_unlock_irqrestore(&de600_lock, flags);
-	}
-
-	/* Start real output */
-	pr_debug("de600_start_xmit:len=%d, page %d/%d\n", skb->len, tx_fifo_in, free_tx_pages);
-
-	if ((len = skb->len) < RUNT)
-		len = RUNT;
-
-	spin_lock_irqsave(&de600_lock, flags);
-	select_nic();
-	tx_fifo[tx_fifo_in] = transmit_from = tx_page_adr(tx_fifo_in) - len;
-	tx_fifo_in = (tx_fifo_in + 1) % TX_PAGES; /* Next free tx page */
-
-	if(check_lost)
-	{
-		/* This costs about 40 instructions per packet... */
-		de600_setup_address(NODE_ADDRESS, RW_ADDR);
-		de600_read_byte(READ_DATA, dev);
-		if (was_down || (de600_read_byte(READ_DATA, dev) != 0xde)) {
-			if (adapter_init(dev)) {
-				spin_unlock_irqrestore(&de600_lock, flags);
-				return NETDEV_TX_BUSY;
-			}
-		}
-	}
-
-	de600_setup_address(transmit_from, RW_ADDR);
-	for (i = 0;  i < skb->len ; ++i, ++buffer)
-		de600_put_byte(*buffer);
-	for (; i < len; ++i)
-		de600_put_byte(0);
-
-	if (free_tx_pages-- == TX_PAGES) { /* No transmission going on */
-		dev->trans_start = jiffies;
-		netif_start_queue(dev); /* allow more packets into adapter */
-		/* Send page and generate a faked interrupt */
-		de600_setup_address(transmit_from, TX_ADDR);
-		de600_put_command(TX_ENABLE);
-	}
-	else {
-		if (free_tx_pages)
-			netif_start_queue(dev);
-		else
-			netif_stop_queue(dev);
-		select_prn();
-	}
-	spin_unlock_irqrestore(&de600_lock, flags);
-	dev_kfree_skb(skb);
-	return NETDEV_TX_OK;
-}
-
-/*
- * The typical workload of the driver:
- * Handle the network interface interrupts.
- */
-
-static irqreturn_t de600_interrupt(int irq, void *dev_id)
-{
-	struct net_device	*dev = dev_id;
-	u8		irq_status;
-	int		retrig = 0;
-	int		boguscount = 0;
-
-	spin_lock(&de600_lock);
-
-	select_nic();
-	irq_status = de600_read_status(dev);
-
-	do {
-		pr_debug("de600_interrupt (%02X)\n", irq_status);
-
-		if (irq_status & RX_GOOD)
-			de600_rx_intr(dev);
-		else if (!(irq_status & RX_BUSY))
-			de600_put_command(RX_ENABLE);
-
-		/* Any transmission in progress? */
-		if (free_tx_pages < TX_PAGES)
-			retrig = de600_tx_intr(dev, irq_status);
-		else
-			retrig = 0;
-
-		irq_status = de600_read_status(dev);
-	} while ( (irq_status & RX_GOOD) || ((++boguscount < 100) && retrig) );
-	/*
-	 * Yeah, it _looks_ like busy waiting, smells like busy waiting
-	 * and I know it's not PC, but please, it will only occur once
-	 * in a while and then only for a loop or so (< 1ms for sure!)
-	 */
-
-	/* Enable adapter interrupts */
-	select_prn();
-	if (retrig)
-		trigger_interrupt(dev);
-	spin_unlock(&de600_lock);
-	return IRQ_HANDLED;
-}
-
-static int de600_tx_intr(struct net_device *dev, int irq_status)
-{
-	/*
-	 * Returns 1 if tx still not done
-	 */
-
-	/* Check if current transmission is done yet */
-	if (irq_status & TX_BUSY)
-		return 1; /* tx not done, try again */
-
-	/* else */
-	/* If last transmission OK then bump fifo index */
-	if (!(irq_status & TX_FAILED16)) {
-		tx_fifo_out = (tx_fifo_out + 1) % TX_PAGES;
-		++free_tx_pages;
-		dev->stats.tx_packets++;
-		netif_wake_queue(dev);
-	}
-
-	/* More to send, or resend last packet? */
-	if ((free_tx_pages < TX_PAGES) || (irq_status & TX_FAILED16)) {
-		dev->trans_start = jiffies;
-		de600_setup_address(tx_fifo[tx_fifo_out], TX_ADDR);
-		de600_put_command(TX_ENABLE);
-		return 1;
-	}
-	/* else */
-
-	return 0;
-}
-
-/*
- * We have a good packet, get it out of the adapter.
- */
-static void de600_rx_intr(struct net_device *dev)
-{
-	struct sk_buff	*skb;
-	int		i;
-	int		read_from;
-	int		size;
-	unsigned char	*buffer;
-
-	/* Get size of received packet */
-	size = de600_read_byte(RX_LEN, dev);	/* low byte */
-	size += (de600_read_byte(RX_LEN, dev) << 8);	/* high byte */
-	size -= 4;	/* Ignore trailing 4 CRC-bytes */
-
-	/* Tell adapter where to store next incoming packet, enable receiver */
-	read_from = rx_page_adr();
-	next_rx_page();
-	de600_put_command(RX_ENABLE);
-
-	if ((size < 32)  ||  (size > 1535)) {
-		printk(KERN_WARNING "%s: Bogus packet size %d.\n", dev->name, size);
-		if (size > 10000)
-			adapter_init(dev);
-		return;
-	}
-
-	skb = dev_alloc_skb(size+2);
-	if (skb == NULL) {
-		printk("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, size);
-		return;
-	}
-	/* else */
-
-	skb_reserve(skb,2);	/* Align */
-
-	/* 'skb->data' points to the start of sk_buff data area. */
-	buffer = skb_put(skb,size);
-
-	/* copy the packet into the buffer */
-	de600_setup_address(read_from, RW_ADDR);
-	for (i = size; i > 0; --i, ++buffer)
-		*buffer = de600_read_byte(READ_DATA, dev);
-
-	skb->protocol=eth_type_trans(skb,dev);
-
-	netif_rx(skb);
-
-	/* update stats */
-	dev->stats.rx_packets++; /* count all receives */
-	dev->stats.rx_bytes += size; /* count all received bytes */
-
-	/*
-	 * If any worth-while packets have been received, netif_rx()
-	 * will work on them when we get to the tasklets.
-	 */
-}
-
-static const struct net_device_ops de600_netdev_ops = {
-	.ndo_open		= de600_open,
-	.ndo_stop		= de600_close,
-	.ndo_start_xmit		= de600_start_xmit,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-
-static struct net_device * __init de600_probe(void)
-{
-	int	i;
-	struct net_device *dev;
-	int err;
-
-	dev = alloc_etherdev(0);
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-
-	if (!request_region(DE600_IO, 3, "de600")) {
-		printk(KERN_WARNING "DE600: port 0x%x busy\n", DE600_IO);
-		err = -EBUSY;
-		goto out;
-	}
-
-	printk(KERN_INFO "%s: D-Link DE-600 pocket adapter", dev->name);
-	/* Alpha testers must have the version number to report bugs. */
-	pr_debug("%s", version);
-
-	/* probe for adapter */
-	err = -ENODEV;
-	rx_page = 0;
-	select_nic();
-	(void)de600_read_status(dev);
-	de600_put_command(RESET);
-	de600_put_command(STOP_RESET);
-	if (de600_read_status(dev) & 0xf0) {
-		printk(": not at I/O %#3x.\n", DATA_PORT);
-		goto out1;
-	}
-
-	/*
-	 * Maybe we found one,
-	 * have to check if it is a D-Link DE-600 adapter...
-	 */
-
-	/* Get the adapter ethernet address from the ROM */
-	de600_setup_address(NODE_ADDRESS, RW_ADDR);
-	for (i = 0; i < ETH_ALEN; i++) {
-		dev->dev_addr[i] = de600_read_byte(READ_DATA, dev);
-		dev->broadcast[i] = 0xff;
-	}
-
-	/* Check magic code */
-	if ((dev->dev_addr[1] == 0xde) && (dev->dev_addr[2] == 0x15)) {
-		/* OK, install real address */
-		dev->dev_addr[0] = 0x00;
-		dev->dev_addr[1] = 0x80;
-		dev->dev_addr[2] = 0xc8;
-		dev->dev_addr[3] &= 0x0f;
-		dev->dev_addr[3] |= 0x70;
-	} else {
-		printk(" not identified in the printer port\n");
-		goto out1;
-	}
-
-	printk(", Ethernet Address: %pM\n", dev->dev_addr);
-
-	dev->netdev_ops = &de600_netdev_ops;
-
-	dev->flags&=~IFF_MULTICAST;
-
-	select_prn();
-
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
-
-	return dev;
-
-out1:
-	release_region(DE600_IO, 3);
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-
-static int adapter_init(struct net_device *dev)
-{
-	int	i;
-
-	select_nic();
-	rx_page = 0; /* used by RESET */
-	de600_put_command(RESET);
-	de600_put_command(STOP_RESET);
-
-	/* Check if it is still there... */
-	/* Get the some bytes of the adapter ethernet address from the ROM */
-	de600_setup_address(NODE_ADDRESS, RW_ADDR);
-	de600_read_byte(READ_DATA, dev);
-	if ((de600_read_byte(READ_DATA, dev) != 0xde) ||
-	    (de600_read_byte(READ_DATA, dev) != 0x15)) {
-	/* was: if (de600_read_status(dev) & 0xf0) { */
-		printk("Something has happened to the DE-600!  Please check it and do a new ifconfig!\n");
-		/* Goodbye, cruel world... */
-		dev->flags &= ~IFF_UP;
-		de600_close(dev);
-		was_down = 1;
-		netif_stop_queue(dev); /* Transmit busy...  */
-		return 1; /* failed */
-	}
-
-	if (was_down) {
-		printk(KERN_INFO "%s: Thanks, I feel much better now!\n", dev->name);
-		was_down = 0;
-	}
-
-	tx_fifo_in = 0;
-	tx_fifo_out = 0;
-	free_tx_pages = TX_PAGES;
-
-
-	/* set the ether address. */
-	de600_setup_address(NODE_ADDRESS, RW_ADDR);
-	for (i = 0; i < ETH_ALEN; i++)
-		de600_put_byte(dev->dev_addr[i]);
-
-	/* where to start saving incoming packets */
-	rx_page = RX_BP | RX_BASE_PAGE;
-	de600_setup_address(MEM_4K, RW_ADDR);
-	/* Enable receiver */
-	de600_put_command(RX_ENABLE);
-	select_prn();
-
-	netif_start_queue(dev);
-
-	return 0; /* OK */
-}
-
-static struct net_device *de600_dev;
-
-static int __init de600_init(void)
-{
-	de600_dev = de600_probe();
-	if (IS_ERR(de600_dev))
-		return PTR_ERR(de600_dev);
-	return 0;
-}
-
-static void __exit de600_exit(void)
-{
-	unregister_netdev(de600_dev);
-	release_region(DE600_IO, 3);
-	free_netdev(de600_dev);
-}
-
-module_init(de600_init);
-module_exit(de600_exit);
-
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/de600.h linux-libre-3.2-gnu/drivers/net/de600.h
--- linux-libre-3.1-gnu/drivers/net/de600.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/de600.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,168 +0,0 @@
-/**************************************************
- *                                                *
- * Definition of D-Link Ethernet Pocket adapter   *
- *                                                *
- **************************************************/
-/*
- * D-Link Ethernet pocket adapter ports
- */
-/*
- * OK, so I'm cheating, but there are an awful lot of
- * reads and writes in order to get anything in and out
- * of the DE-600 with 4 bits at a time in the parallel port,
- * so every saved instruction really helps :-)
- */
-
-#ifndef DE600_IO
-#define DE600_IO	0x378
-#endif
-
-#define DATA_PORT	(DE600_IO)
-#define STATUS_PORT	(DE600_IO + 1)
-#define COMMAND_PORT	(DE600_IO + 2)
-
-#ifndef DE600_IRQ
-#define DE600_IRQ	7
-#endif
-/*
- * It really should look like this, and autoprobing as well...
- *
-#define DATA_PORT	(dev->base_addr + 0)
-#define STATUS_PORT	(dev->base_addr + 1)
-#define COMMAND_PORT	(dev->base_addr + 2)
-#define DE600_IRQ	dev->irq
- */
-
-/*
- * D-Link COMMAND_PORT commands
- */
-#define SELECT_NIC	0x04 /* select Network Interface Card */
-#define SELECT_PRN	0x1c /* select Printer */
-#define NML_PRN		0xec /* normal Printer situation */
-#define IRQEN		0x10 /* enable IRQ line */
-
-/*
- * D-Link STATUS_PORT
- */
-#define RX_BUSY		0x80
-#define RX_GOOD		0x40
-#define TX_FAILED16	0x10
-#define TX_BUSY		0x08
-
-/*
- * D-Link DATA_PORT commands
- * command in low 4 bits
- * data in high 4 bits
- * select current data nibble with HI_NIBBLE bit
- */
-#define WRITE_DATA	0x00 /* write memory */
-#define READ_DATA	0x01 /* read memory */
-#define STATUS		0x02 /* read  status register */
-#define COMMAND		0x03 /* write command register (see COMMAND below) */
-#define NULL_COMMAND	0x04 /* null command */
-#define RX_LEN		0x05 /* read  received packet length */
-#define TX_ADDR		0x06 /* set adapter transmit memory address */
-#define RW_ADDR		0x07 /* set adapter read/write memory address */
-#define HI_NIBBLE	0x08 /* read/write the high nibble of data,
-				or-ed with rest of command */
-
-/*
- * command register, accessed through DATA_PORT with low bits = COMMAND
- */
-#define RX_ALL		0x01 /* PROMISCUOUS */
-#define RX_BP		0x02 /* default: BROADCAST & PHYSICAL ADDRESS */
-#define RX_MBP		0x03 /* MULTICAST, BROADCAST & PHYSICAL ADDRESS */
-
-#define TX_ENABLE	0x04 /* bit 2 */
-#define RX_ENABLE	0x08 /* bit 3 */
-
-#define RESET		0x80 /* set bit 7 high */
-#define STOP_RESET	0x00 /* set bit 7 low */
-
-/*
- * data to command register
- * (high 4 bits in write to DATA_PORT)
- */
-#define RX_PAGE2_SELECT	0x10 /* bit 4, only 2 pages to select */
-#define RX_BASE_PAGE	0x20 /* bit 5, always set when specifying RX_ADDR */
-#define FLIP_IRQ	0x40 /* bit 6 */
-
-/*
- * D-Link adapter internal memory:
- *
- * 0-2K 1:st transmit page (send from pointer up to 2K)
- * 2-4K	2:nd transmit page (send from pointer up to 4K)
- *
- * 4-6K 1:st receive page (data from 4K upwards)
- * 6-8K 2:nd receive page (data from 6K upwards)
- *
- * 8K+	Adapter ROM (contains magic code and last 3 bytes of Ethernet address)
- */
-#define MEM_2K		0x0800 /* 2048 */
-#define MEM_4K		0x1000 /* 4096 */
-#define MEM_6K		0x1800 /* 6144 */
-#define NODE_ADDRESS	0x2000 /* 8192 */
-
-#define RUNT 60		/* Too small Ethernet packet */
-
-/**************************************************
- *                                                *
- *             End of definition                  *
- *                                                *
- **************************************************/
-
-/*
- * Index to functions, as function prototypes.
- */
-/* Routines used internally. (See "convenience macros") */
-static u8	de600_read_status(struct net_device *dev);
-static u8	de600_read_byte(unsigned char type, struct net_device *dev);
-
-/* Put in the device structure. */
-static int	de600_open(struct net_device *dev);
-static int	de600_close(struct net_device *dev);
-static int	de600_start_xmit(struct sk_buff *skb, struct net_device *dev);
-
-/* Dispatch from interrupts. */
-static irqreturn_t de600_interrupt(int irq, void *dev_id);
-static int	de600_tx_intr(struct net_device *dev, int irq_status);
-static void	de600_rx_intr(struct net_device *dev);
-
-/* Initialization */
-static void	trigger_interrupt(struct net_device *dev);
-static int	adapter_init(struct net_device *dev);
-
-/*
- * Convenience macros/functions for D-Link adapter
- */
-
-#define select_prn() outb_p(SELECT_PRN, COMMAND_PORT); DE600_SLOW_DOWN
-#define select_nic() outb_p(SELECT_NIC, COMMAND_PORT); DE600_SLOW_DOWN
-
-/* Thanks for hints from Mark Burton <markb@ordern.demon.co.uk> */
-#define de600_put_byte(data) ( \
-	outb_p(((data) << 4)   | WRITE_DATA            , DATA_PORT), \
-	outb_p(((data) & 0xf0) | WRITE_DATA | HI_NIBBLE, DATA_PORT))
-
-/*
- * The first two outb_p()'s below could perhaps be deleted if there
- * would be more delay in the last two. Not certain about it yet...
- */
-#define de600_put_command(cmd) ( \
-	outb_p(( rx_page        << 4)   | COMMAND            , DATA_PORT), \
-	outb_p(( rx_page        & 0xf0) | COMMAND | HI_NIBBLE, DATA_PORT), \
-	outb_p(((rx_page | cmd) << 4)   | COMMAND            , DATA_PORT), \
-	outb_p(((rx_page | cmd) & 0xf0) | COMMAND | HI_NIBBLE, DATA_PORT))
-
-#define de600_setup_address(addr,type) ( \
-	outb_p((((addr) << 4) & 0xf0) | type            , DATA_PORT), \
-	outb_p(( (addr)       & 0xf0) | type | HI_NIBBLE, DATA_PORT), \
-	outb_p((((addr) >> 4) & 0xf0) | type            , DATA_PORT), \
-	outb_p((((addr) >> 8) & 0xf0) | type | HI_NIBBLE, DATA_PORT))
-
-#define rx_page_adr() ((rx_page & RX_PAGE2_SELECT)?(MEM_6K):(MEM_4K))
-
-/* Flip bit, only 2 pages */
-#define next_rx_page() (rx_page ^= RX_PAGE2_SELECT)
-
-#define tx_page_adr(a) (((a) + 1) * MEM_2K)
diff -druN linux-libre-3.1-gnu/drivers/net/de620.c linux-libre-3.2-gnu/drivers/net/de620.c
--- linux-libre-3.1-gnu/drivers/net/de620.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/de620.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,988 +0,0 @@
-/*
- *	de620.c $Revision: 1.40 $ BETA
- *
- *
- *	Linux driver for the D-Link DE-620 Ethernet pocket adapter.
- *
- *	Portions (C) Copyright 1993, 1994 by Bjorn Ekwall <bj0rn@blox.se>
- *
- *	Based on adapter information gathered from DOS packetdriver
- *	sources from D-Link Inc:  (Special thanks to Henry Ngai of D-Link.)
- *		Portions (C) Copyright D-Link SYSTEM Inc. 1991, 1992
- *		Copyright, 1988, Russell Nelson, Crynwr Software
- *
- *	Adapted to the sample network driver core for linux,
- *	written by: Donald Becker <becker@super.org>
- *		(Now at <becker@scyld.com>)
- *
- *	Valuable assistance from:
- *		J. Joshua Kopper <kopper@rtsg.mot.com>
- *		Olav Kvittem <Olav.Kvittem@uninett.no>
- *		Germano Caronni <caronni@nessie.cs.id.ethz.ch>
- *		Jeremy Fitzhardinge <jeremy@suite.sw.oz.au>
- *
- *****************************************************************************/
-/*
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2, or (at your option)
- *	any later version.
- *
- *	This program is distributed in the hope that it will be useful,
- *	but WITHOUT ANY WARRANTY; without even the implied warranty of
- *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *	GNU General Public License for more details.
- *
- *	You should have received a copy of the GNU General Public License
- *	along with this program; if not, write to the Free Software
- *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *****************************************************************************/
-static const char version[] =
-	"de620.c: $Revision: 1.40 $,  Bjorn Ekwall <bj0rn@blox.se>\n";
-
-/***********************************************************************
- *
- * "Tuning" section.
- *
- * Compile-time options: (see below for descriptions)
- * -DDE620_IO=0x378	(lpt1)
- * -DDE620_IRQ=7	(lpt1)
- * -DSHUTDOWN_WHEN_LOST
- * -DCOUNT_LOOPS
- * -DLOWSPEED
- * -DREAD_DELAY
- * -DWRITE_DELAY
- */
-
-/*
- * This driver assumes that the printer port is a "normal",
- * dumb, uni-directional port!
- * If your port is "fancy" in any way, please try to set it to "normal"
- * with your BIOS setup.  I have no access to machines with bi-directional
- * ports, so I can't test such a driver :-(
- * (Yes, I _know_ it is possible to use DE620 with bidirectional ports...)
- *
- * There are some clones of DE620 out there, with different names.
- * If the current driver does not recognize a clone, try to change
- * the following #define to:
- *
- * #define DE620_CLONE 1
- */
-#define DE620_CLONE 0
-
-/*
- * If the adapter has problems with high speeds, enable this #define
- * otherwise full printerport speed will be attempted.
- *
- * You can tune the READ_DELAY/WRITE_DELAY below if you enable LOWSPEED
- *
-#define LOWSPEED
- */
-
-#ifndef READ_DELAY
-#define READ_DELAY 100	/* adapter internal read delay in 100ns units */
-#endif
-
-#ifndef WRITE_DELAY
-#define WRITE_DELAY 100	/* adapter internal write delay in 100ns units */
-#endif
-
-/*
- * Enable this #define if you want the adapter to do a "ifconfig down" on
- * itself when we have detected that something is possibly wrong with it.
- * The default behaviour is to retry with "adapter_init()" until success.
- * This should be used for debugging purposes only.
- *
-#define SHUTDOWN_WHEN_LOST
- */
-
-#ifdef LOWSPEED
-/*
- * Enable this #define if you want to see debugging output that show how long
- * we have to wait before the DE-620 is ready for the next read/write/command.
- *
-#define COUNT_LOOPS
- */
-#endif
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-
-/* Constant definitions for the DE-620 registers, commands and bits */
-#include "de620.h"
-
-typedef unsigned char byte;
-
-/*******************************************************
- *                                                     *
- * Definition of D-Link DE-620 Ethernet Pocket adapter *
- * See also "de620.h"                                  *
- *                                                     *
- *******************************************************/
-#ifndef DE620_IO /* Compile-time configurable */
-#define DE620_IO 0x378
-#endif
-
-#ifndef DE620_IRQ /* Compile-time configurable */
-#define DE620_IRQ	7
-#endif
-
-#define DATA_PORT	(dev->base_addr)
-#define STATUS_PORT	(dev->base_addr + 1)
-#define COMMAND_PORT	(dev->base_addr + 2)
-
-#define RUNT 60		/* Too small Ethernet packet */
-#define GIANT 1514	/* largest legal size packet, no fcs */
-
-/*
- * Force media with insmod:
- *	insmod de620.o bnc=1
- * or
- *	insmod de620.o utp=1
- *
- * Force io and/or irq with insmod:
- *	insmod de620.o io=0x378 irq=7
- *
- * Make a clone skip the Ethernet-address range check:
- *	insmod de620.o clone=1
- */
-static int bnc;
-static int utp;
-static int io  = DE620_IO;
-static int irq = DE620_IRQ;
-static int clone = DE620_CLONE;
-
-static spinlock_t de620_lock;
-
-module_param(bnc, int, 0);
-module_param(utp, int, 0);
-module_param(io, int, 0);
-module_param(irq, int, 0);
-module_param(clone, int, 0);
-MODULE_PARM_DESC(bnc, "DE-620 set BNC medium (0-1)");
-MODULE_PARM_DESC(utp, "DE-620 set UTP medium (0-1)");
-MODULE_PARM_DESC(io, "DE-620 I/O base address,required");
-MODULE_PARM_DESC(irq, "DE-620 IRQ number,required");
-MODULE_PARM_DESC(clone, "Check also for non-D-Link DE-620 clones (0-1)");
-
-/***********************************************
- *                                             *
- * Index to functions, as function prototypes. *
- *                                             *
- ***********************************************/
-
-/*
- * Routines used internally. (See also "convenience macros.. below")
- */
-
-/* Put in the device structure. */
-static int	de620_open(struct net_device *);
-static int	de620_close(struct net_device *);
-static void	de620_set_multicast_list(struct net_device *);
-static int	de620_start_xmit(struct sk_buff *, struct net_device *);
-
-/* Dispatch from interrupts. */
-static irqreturn_t de620_interrupt(int, void *);
-static int	de620_rx_intr(struct net_device *);
-
-/* Initialization */
-static int	adapter_init(struct net_device *);
-static int	read_eeprom(struct net_device *);
-
-
-/*
- * D-Link driver variables:
- */
-#define SCR_DEF NIBBLEMODE |INTON | SLEEP | AUTOTX
-#define	TCR_DEF RXPB			/* not used: | TXSUCINT | T16INT */
-#define DE620_RX_START_PAGE 12		/* 12 pages (=3k) reserved for tx */
-#define DEF_NIC_CMD IRQEN | ICEN | DS1
-
-static volatile byte	NIC_Cmd;
-static volatile byte	next_rx_page;
-static byte		first_rx_page;
-static byte		last_rx_page;
-static byte		EIPRegister;
-
-static struct nic {
-	byte	NodeID[6];
-	byte	RAM_Size;
-	byte	Model;
-	byte	Media;
-	byte	SCR;
-} nic_data;
-
-/**********************************************************
- *                                                        *
- * Convenience macros/functions for D-Link DE-620 adapter *
- *                                                        *
- **********************************************************/
-#define de620_tx_buffs(dd) (inb(STATUS_PORT) & (TXBF0 | TXBF1))
-#define de620_flip_ds(dd) NIC_Cmd ^= DS0 | DS1; outb(NIC_Cmd, COMMAND_PORT);
-
-/* Check for ready-status, and return a nibble (high 4 bits) for data input */
-#ifdef COUNT_LOOPS
-static int tot_cnt;
-#endif
-static inline byte
-de620_ready(struct net_device *dev)
-{
-	byte value;
-	register short int cnt = 0;
-
-	while ((((value = inb(STATUS_PORT)) & READY) == 0) && (cnt <= 1000))
-		++cnt;
-
-#ifdef COUNT_LOOPS
-	tot_cnt += cnt;
-#endif
-	return value & 0xf0; /* nibble */
-}
-
-static inline void
-de620_send_command(struct net_device *dev, byte cmd)
-{
-	de620_ready(dev);
-	if (cmd == W_DUMMY)
-		outb(NIC_Cmd, COMMAND_PORT);
-
-	outb(cmd, DATA_PORT);
-
-	outb(NIC_Cmd ^ CS0, COMMAND_PORT);
-	de620_ready(dev);
-	outb(NIC_Cmd, COMMAND_PORT);
-}
-
-static inline void
-de620_put_byte(struct net_device *dev, byte value)
-{
-	/* The de620_ready() makes 7 loops, on the average, on a DX2/66 */
-	de620_ready(dev);
-	outb(value, DATA_PORT);
-	de620_flip_ds(dev);
-}
-
-static inline byte
-de620_read_byte(struct net_device *dev)
-{
-	byte value;
-
-	/* The de620_ready() makes 7 loops, on the average, on a DX2/66 */
-	value = de620_ready(dev); /* High nibble */
-	de620_flip_ds(dev);
-	value |= de620_ready(dev) >> 4; /* Low nibble */
-	return value;
-}
-
-static inline void
-de620_write_block(struct net_device *dev, byte *buffer, int count, int pad)
-{
-#ifndef LOWSPEED
-	byte uflip = NIC_Cmd ^ (DS0 | DS1);
-	byte dflip = NIC_Cmd;
-#else /* LOWSPEED */
-#ifdef COUNT_LOOPS
-	int bytes = count;
-#endif /* COUNT_LOOPS */
-#endif /* LOWSPEED */
-
-#ifdef LOWSPEED
-#ifdef COUNT_LOOPS
-	tot_cnt = 0;
-#endif /* COUNT_LOOPS */
-	/* No further optimization useful, the limit is in the adapter. */
-	for ( ; count > 0; --count, ++buffer) {
-		de620_put_byte(dev,*buffer);
-	}
-	for ( count = pad ; count > 0; --count, ++buffer) {
-		de620_put_byte(dev, 0);
-	}
-	de620_send_command(dev,W_DUMMY);
-#ifdef COUNT_LOOPS
-	/* trial debug output: loops per byte in de620_ready() */
-	printk("WRITE(%d)\n", tot_cnt/((bytes?bytes:1)));
-#endif /* COUNT_LOOPS */
-#else /* not LOWSPEED */
-	for ( ; count > 0; count -=2) {
-		outb(*buffer++, DATA_PORT);
-		outb(uflip, COMMAND_PORT);
-		outb(*buffer++, DATA_PORT);
-		outb(dflip, COMMAND_PORT);
-	}
-	de620_send_command(dev,W_DUMMY);
-#endif /* LOWSPEED */
-}
-
-static inline void
-de620_read_block(struct net_device *dev, byte *data, int count)
-{
-#ifndef LOWSPEED
-	byte value;
-	byte uflip = NIC_Cmd ^ (DS0 | DS1);
-	byte dflip = NIC_Cmd;
-#else /* LOWSPEED */
-#ifdef COUNT_LOOPS
-	int bytes = count;
-
-	tot_cnt = 0;
-#endif /* COUNT_LOOPS */
-#endif /* LOWSPEED */
-
-#ifdef LOWSPEED
-	/* No further optimization useful, the limit is in the adapter. */
-	while (count-- > 0) {
-		*data++ = de620_read_byte(dev);
-		de620_flip_ds(dev);
-	}
-#ifdef COUNT_LOOPS
-	/* trial debug output: loops per byte in de620_ready() */
-	printk("READ(%d)\n", tot_cnt/(2*(bytes?bytes:1)));
-#endif /* COUNT_LOOPS */
-#else /* not LOWSPEED */
-	while (count-- > 0) {
-		value = inb(STATUS_PORT) & 0xf0; /* High nibble */
-		outb(uflip, COMMAND_PORT);
-		*data++ = value | inb(STATUS_PORT) >> 4; /* Low nibble */
-		outb(dflip , COMMAND_PORT);
-	}
-#endif /* LOWSPEED */
-}
-
-static inline void
-de620_set_delay(struct net_device *dev)
-{
-	de620_ready(dev);
-	outb(W_DFR, DATA_PORT);
-	outb(NIC_Cmd ^ CS0, COMMAND_PORT);
-
-	de620_ready(dev);
-#ifdef LOWSPEED
-	outb(WRITE_DELAY, DATA_PORT);
-#else
-	outb(0, DATA_PORT);
-#endif
-	de620_flip_ds(dev);
-
-	de620_ready(dev);
-#ifdef LOWSPEED
-	outb(READ_DELAY, DATA_PORT);
-#else
-	outb(0, DATA_PORT);
-#endif
-	de620_flip_ds(dev);
-}
-
-static inline void
-de620_set_register(struct net_device *dev, byte reg, byte value)
-{
-	de620_ready(dev);
-	outb(reg, DATA_PORT);
-	outb(NIC_Cmd ^ CS0, COMMAND_PORT);
-
-	de620_put_byte(dev, value);
-}
-
-static inline byte
-de620_get_register(struct net_device *dev, byte reg)
-{
-	byte value;
-
-	de620_send_command(dev,reg);
-	value = de620_read_byte(dev);
-	de620_send_command(dev,W_DUMMY);
-
-	return value;
-}
-
-/*********************************************************************
- *
- * Open/initialize the board.
- *
- * This routine should set everything up anew at each open, even
- * registers that "should" only need to be set once at boot, so that
- * there is a non-reboot way to recover if something goes wrong.
- *
- */
-static int de620_open(struct net_device *dev)
-{
-	int ret = request_irq(dev->irq, de620_interrupt, 0, dev->name, dev);
-	if (ret) {
-		printk (KERN_ERR "%s: unable to get IRQ %d\n", dev->name, dev->irq);
-		return ret;
-	}
-
-	if (adapter_init(dev)) {
-		ret = -EIO;
-		goto out_free_irq;
-	}
-
-	netif_start_queue(dev);
-	return 0;
-
-out_free_irq:
-	free_irq(dev->irq, dev);
-	return ret;
-}
-
-/************************************************
- *
- * The inverse routine to de620_open().
- *
- */
-
-static int de620_close(struct net_device *dev)
-{
-	netif_stop_queue(dev);
-	/* disable recv */
-	de620_set_register(dev, W_TCR, RXOFF);
-	free_irq(dev->irq, dev);
-	return 0;
-}
-
-/*********************************************
- *
- * Set or clear the multicast filter for this adaptor.
- * (no real multicast implemented for the DE-620, but she can be promiscuous...)
- *
- */
-
-static void de620_set_multicast_list(struct net_device *dev)
-{
-	if (!netdev_mc_empty(dev) || dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
-	{ /* Enable promiscuous mode */
-		de620_set_register(dev, W_TCR, (TCR_DEF & ~RXPBM) | RXALL);
-	}
-	else
-	{ /* Disable promiscuous mode, use normal mode */
-		de620_set_register(dev, W_TCR, TCR_DEF);
-	}
-}
-
-/*******************************************************
- *
- * Handle timeouts on transmit
- */
-
-static void de620_timeout(struct net_device *dev)
-{
-	printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name, "network cable problem");
-	/* Restart the adapter. */
-	if (!adapter_init(dev)) /* maybe close it */
-		netif_wake_queue(dev);
-}
-
-/*******************************************************
- *
- * Copy a buffer to the adapter transmit page memory.
- * Start sending.
- */
-static int de620_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	unsigned long flags;
-	int len;
-	byte *buffer = skb->data;
-	byte using_txbuf;
-
-	using_txbuf = de620_tx_buffs(dev); /* Peek at the adapter */
-
-	netif_stop_queue(dev);
-
-
-	if ((len = skb->len) < RUNT)
-		len = RUNT;
-	if (len & 1) /* send an even number of bytes */
-		++len;
-
-	/* Start real output */
-
-	spin_lock_irqsave(&de620_lock, flags);
-	pr_debug("de620_start_xmit: len=%d, bufs 0x%02x\n",
-		(int)skb->len, using_txbuf);
-
-	/* select a free tx buffer. if there is one... */
-	switch (using_txbuf) {
-	default: /* both are free: use TXBF0 */
-	case TXBF1: /* use TXBF0 */
-		de620_send_command(dev,W_CR | RW0);
-		using_txbuf |= TXBF0;
-		break;
-
-	case TXBF0: /* use TXBF1 */
-		de620_send_command(dev,W_CR | RW1);
-		using_txbuf |= TXBF1;
-		break;
-
-	case (TXBF0 | TXBF1): /* NONE!!! */
-		printk(KERN_WARNING "%s: No tx-buffer available!\n", dev->name);
-		spin_unlock_irqrestore(&de620_lock, flags);
-		return NETDEV_TX_BUSY;
-	}
-	de620_write_block(dev, buffer, skb->len, len-skb->len);
-
-	if(!(using_txbuf == (TXBF0 | TXBF1)))
-		netif_wake_queue(dev);
-
-	dev->stats.tx_packets++;
-	spin_unlock_irqrestore(&de620_lock, flags);
-	dev_kfree_skb (skb);
-	return NETDEV_TX_OK;
-}
-
-/*****************************************************
- *
- * Handle the network interface interrupts.
- *
- */
-static irqreturn_t
-de620_interrupt(int irq_in, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	byte irq_status;
-	int bogus_count = 0;
-	int again = 0;
-
-	spin_lock(&de620_lock);
-
-	/* Read the status register (_not_ the status port) */
-	irq_status = de620_get_register(dev, R_STS);
-
-	pr_debug("de620_interrupt (%2.2X)\n", irq_status);
-
-	if (irq_status & RXGOOD) {
-		do {
-			again = de620_rx_intr(dev);
-			pr_debug("again=%d\n", again);
-		}
-		while (again && (++bogus_count < 100));
-	}
-
-	if(de620_tx_buffs(dev) != (TXBF0 | TXBF1))
-		netif_wake_queue(dev);
-
-	spin_unlock(&de620_lock);
-	return IRQ_HANDLED;
-}
-
-/**************************************
- *
- * Get a packet from the adapter
- *
- * Send it "upstairs"
- *
- */
-static int de620_rx_intr(struct net_device *dev)
-{
-	struct header_buf {
-		byte		status;
-		byte		Rx_NextPage;
-		unsigned short	Rx_ByteCount;
-	} header_buf;
-	struct sk_buff *skb;
-	int size;
-	byte *buffer;
-	byte pagelink;
-	byte curr_page;
-
-	pr_debug("de620_rx_intr: next_rx_page = %d\n", next_rx_page);
-
-	/* Tell the adapter that we are going to read data, and from where */
-	de620_send_command(dev, W_CR | RRN);
-	de620_set_register(dev, W_RSA1, next_rx_page);
-	de620_set_register(dev, W_RSA0, 0);
-
-	/* Deep breath, and away we goooooo */
-	de620_read_block(dev, (byte *)&header_buf, sizeof(struct header_buf));
-	pr_debug("page status=0x%02x, nextpage=%d, packetsize=%d\n",
-		header_buf.status, header_buf.Rx_NextPage,
-		header_buf.Rx_ByteCount);
-
-	/* Plausible page header? */
-	pagelink = header_buf.Rx_NextPage;
-	if ((pagelink < first_rx_page) || (last_rx_page < pagelink)) {
-		/* Ouch... Forget it! Skip all and start afresh... */
-		printk(KERN_WARNING "%s: Ring overrun? Restoring...\n", dev->name);
-		/* You win some, you lose some. And sometimes plenty... */
-		adapter_init(dev);
-		netif_wake_queue(dev);
-		dev->stats.rx_over_errors++;
-		return 0;
-	}
-
-	/* OK, this look good, so far. Let's see if it's consistent... */
-	/* Let's compute the start of the next packet, based on where we are */
-	pagelink = next_rx_page +
-		((header_buf.Rx_ByteCount + (4 - 1 + 0x100)) >> 8);
-
-	/* Are we going to wrap around the page counter? */
-	if (pagelink > last_rx_page)
-		pagelink -= (last_rx_page - first_rx_page + 1);
-
-	/* Is the _computed_ next page number equal to what the adapter says? */
-	if (pagelink != header_buf.Rx_NextPage) {
-		/* Naah, we'll skip this packet. Probably bogus data as well */
-		printk(KERN_WARNING "%s: Page link out of sync! Restoring...\n", dev->name);
-		next_rx_page = header_buf.Rx_NextPage; /* at least a try... */
-		de620_send_command(dev, W_DUMMY);
-		de620_set_register(dev, W_NPRF, next_rx_page);
-		dev->stats.rx_over_errors++;
-		return 0;
-	}
-	next_rx_page = pagelink;
-
-	size = header_buf.Rx_ByteCount - 4;
-	if ((size < RUNT) || (GIANT < size)) {
-		printk(KERN_WARNING "%s: Illegal packet size: %d!\n", dev->name, size);
-	}
-	else { /* Good packet? */
-		skb = dev_alloc_skb(size+2);
-		if (skb == NULL) { /* Yeah, but no place to put it... */
-			printk(KERN_WARNING "%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, size);
-			dev->stats.rx_dropped++;
-		}
-		else { /* Yep! Go get it! */
-			skb_reserve(skb,2);	/* Align */
-			/* skb->data points to the start of sk_buff data area */
-			buffer = skb_put(skb,size);
-			/* copy the packet into the buffer */
-			de620_read_block(dev, buffer, size);
-			pr_debug("Read %d bytes\n", size);
-			skb->protocol=eth_type_trans(skb,dev);
-			netif_rx(skb); /* deliver it "upstairs" */
-			/* count all receives */
-			dev->stats.rx_packets++;
-			dev->stats.rx_bytes += size;
-		}
-	}
-
-	/* Let's peek ahead to see if we have read the last current packet */
-	/* NOTE! We're _not_ checking the 'EMPTY'-flag! This seems better... */
-	curr_page = de620_get_register(dev, R_CPR);
-	de620_set_register(dev, W_NPRF, next_rx_page);
-	pr_debug("next_rx_page=%d CPR=%d\n", next_rx_page, curr_page);
-
-	return next_rx_page != curr_page; /* That was slightly tricky... */
-}
-
-/*********************************************
- *
- * Reset the adapter to a known state
- *
- */
-static int adapter_init(struct net_device *dev)
-{
-	int i;
-	static int was_down;
-
-	if ((nic_data.Model == 3) || (nic_data.Model == 0)) { /* CT */
-		EIPRegister = NCTL0;
-		if (nic_data.Media != 1)
-			EIPRegister |= NIS0;	/* not BNC */
-	}
-	else if (nic_data.Model == 2) { /* UTP */
-		EIPRegister = NCTL0 | NIS0;
-	}
-
-	if (utp)
-		EIPRegister = NCTL0 | NIS0;
-	if (bnc)
-		EIPRegister = NCTL0;
-
-	de620_send_command(dev, W_CR | RNOP | CLEAR);
-	de620_send_command(dev, W_CR | RNOP);
-
-	de620_set_register(dev, W_SCR, SCR_DEF);
-	/* disable recv to wait init */
-	de620_set_register(dev, W_TCR, RXOFF);
-
-	/* Set the node ID in the adapter */
-	for (i = 0; i < 6; ++i) { /* W_PARn = 0xaa + n */
-		de620_set_register(dev, W_PAR0 + i, dev->dev_addr[i]);
-	}
-
-	de620_set_register(dev, W_EIP, EIPRegister);
-
-	next_rx_page = first_rx_page = DE620_RX_START_PAGE;
-	if (nic_data.RAM_Size)
-		last_rx_page = nic_data.RAM_Size - 1;
-	else /* 64k RAM */
-		last_rx_page = 255;
-
-	de620_set_register(dev, W_SPR, first_rx_page); /* Start Page Register*/
-	de620_set_register(dev, W_EPR, last_rx_page);  /* End Page Register */
-	de620_set_register(dev, W_CPR, first_rx_page);/*Current Page Register*/
-	de620_send_command(dev, W_NPR | first_rx_page); /* Next Page Register*/
-	de620_send_command(dev, W_DUMMY);
-	de620_set_delay(dev);
-
-	/* Final sanity check: Anybody out there? */
-	/* Let's hope some bits from the statusregister make a good check */
-#define CHECK_MASK (  0 | TXSUC |  T16  |  0  | RXCRC | RXSHORT |  0  |  0  )
-#define CHECK_OK   (  0 |   0   |  0    |  0  |   0   |   0     |  0  |  0  )
-        /* success:   X     0      0       X      0       0        X     X  */
-        /* ignore:   EEDI                RXGOOD                   COLS  LNKS*/
-
-	if (((i = de620_get_register(dev, R_STS)) & CHECK_MASK) != CHECK_OK) {
-		printk(KERN_ERR "%s: Something has happened to the DE-620!  Please check it"
-#ifdef SHUTDOWN_WHEN_LOST
-			" and do a new ifconfig"
-#endif
-			"! (%02x)\n", dev->name, i);
-#ifdef SHUTDOWN_WHEN_LOST
-		/* Goodbye, cruel world... */
-		dev->flags &= ~IFF_UP;
-		de620_close(dev);
-#endif
-		was_down = 1;
-		return 1; /* failed */
-	}
-	if (was_down) {
-		printk(KERN_WARNING "%s: Thanks, I feel much better now!\n", dev->name);
-		was_down = 0;
-	}
-
-	/* All OK, go ahead... */
-	de620_set_register(dev, W_TCR, TCR_DEF);
-
-	return 0; /* all ok */
-}
-
-static const struct net_device_ops de620_netdev_ops = {
-	.ndo_open 		= de620_open,
-	.ndo_stop 		= de620_close,
-	.ndo_start_xmit 	= de620_start_xmit,
-	.ndo_tx_timeout 	= de620_timeout,
-	.ndo_set_multicast_list = de620_set_multicast_list,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-/******************************************************************************
- *
- * Only start-up code below
- *
- */
-/****************************************
- *
- * Check if there is a DE-620 connected
- */
-struct net_device * __init de620_probe(int unit)
-{
-	byte checkbyte = 0xa5;
-	struct net_device *dev;
-	int err = -ENOMEM;
-	int i;
-
-	dev = alloc_etherdev(0);
-	if (!dev)
-		goto out;
-
-	spin_lock_init(&de620_lock);
-
-	/*
-	 * This is where the base_addr and irq gets set.
-	 * Tunable at compile-time and insmod-time
-	 */
-	dev->base_addr = io;
-	dev->irq       = irq;
-
-	/* allow overriding parameters on command line */
-	if (unit >= 0) {
-		sprintf(dev->name, "eth%d", unit);
-		netdev_boot_setup_check(dev);
-	}
-
-	pr_debug("%s", version);
-
-	printk(KERN_INFO "D-Link DE-620 pocket adapter");
-
-	if (!request_region(dev->base_addr, 3, "de620")) {
-		printk(" io 0x%3lX, which is busy.\n", dev->base_addr);
-		err = -EBUSY;
-		goto out1;
-	}
-
-	/* Initially, configure basic nibble mode, so we can read the EEPROM */
-	NIC_Cmd = DEF_NIC_CMD;
-	de620_set_register(dev, W_EIP, EIPRegister);
-
-	/* Anybody out there? */
-	de620_set_register(dev, W_CPR, checkbyte);
-	checkbyte = de620_get_register(dev, R_CPR);
-
-	if ((checkbyte != 0xa5) || (read_eeprom(dev) != 0)) {
-		printk(" not identified in the printer port\n");
-		err = -ENODEV;
-		goto out2;
-	}
-
-	/* else, got it! */
-	dev->dev_addr[0] = nic_data.NodeID[0];
-	for (i = 1; i < ETH_ALEN; i++) {
-		dev->dev_addr[i] = nic_data.NodeID[i];
-		dev->broadcast[i] = 0xff;
-	}
-
-	printk(", Ethernet Address: %pM", dev->dev_addr);
-
-	printk(" (%dk RAM,",
-		(nic_data.RAM_Size) ? (nic_data.RAM_Size >> 2) : 64);
-
-	if (nic_data.Media == 1)
-		printk(" BNC)\n");
-	else
-		printk(" UTP)\n");
-
-	dev->netdev_ops = &de620_netdev_ops;
-	dev->watchdog_timeo	= HZ*2;
-
-	/* base_addr and irq are already set, see above! */
-
-	/* dump eeprom */
-	pr_debug("\nEEPROM contents:\n"
-		"RAM_Size = 0x%02X\n"
-		"NodeID = %pM\n"
-		"Model = %d\n"
-		"Media = %d\n"
-		"SCR = 0x%02x\n", nic_data.RAM_Size, nic_data.NodeID,
-		nic_data.Model, nic_data.Media, nic_data.SCR);
-
-	err = register_netdev(dev);
-	if (err)
-		goto out2;
-	return dev;
-
-out2:
-	release_region(dev->base_addr, 3);
-out1:
-	free_netdev(dev);
-out:
-	return ERR_PTR(err);
-}
-
-/**********************************
- *
- * Read info from on-board EEPROM
- *
- * Note: Bitwise serial I/O to/from the EEPROM vi the status _register_!
- */
-#define sendit(dev,data) de620_set_register(dev, W_EIP, data | EIPRegister);
-
-static unsigned short __init ReadAWord(struct net_device *dev, int from)
-{
-	unsigned short data;
-	int nbits;
-
-	/* cs   [__~~] SET SEND STATE */
-	/* di   [____]                */
-	/* sck  [_~~_]                */
-	sendit(dev, 0); sendit(dev, 1); sendit(dev, 5); sendit(dev, 4);
-
-	/* Send the 9-bit address from where we want to read the 16-bit word */
-	for (nbits = 9; nbits > 0; --nbits, from <<= 1) {
-		if (from & 0x0100) { /* bit set? */
-			/* cs    [~~~~] SEND 1 */
-			/* di    [~~~~]        */
-			/* sck   [_~~_]        */
-			sendit(dev, 6); sendit(dev, 7); sendit(dev, 7); sendit(dev, 6);
-		}
-		else {
-			/* cs    [~~~~] SEND 0 */
-			/* di    [____]        */
-			/* sck   [_~~_]        */
-			sendit(dev, 4); sendit(dev, 5); sendit(dev, 5); sendit(dev, 4);
-		}
-	}
-
-	/* Shift in the 16-bit word. The bits appear serially in EEDI (=0x80) */
-	for (data = 0, nbits = 16; nbits > 0; --nbits) {
-		/* cs    [~~~~] SEND 0 */
-		/* di    [____]        */
-		/* sck   [_~~_]        */
-		sendit(dev, 4); sendit(dev, 5); sendit(dev, 5); sendit(dev, 4);
-		data = (data << 1) | ((de620_get_register(dev, R_STS) & EEDI) >> 7);
-	}
-	/* cs    [____] RESET SEND STATE */
-	/* di    [____]                  */
-	/* sck   [_~~_]                  */
-	sendit(dev, 0); sendit(dev, 1); sendit(dev, 1); sendit(dev, 0);
-
-	return data;
-}
-
-static int __init read_eeprom(struct net_device *dev)
-{
-	unsigned short wrd;
-
-	/* D-Link Ethernet addresses are in the series  00:80:c8:7X:XX:XX:XX */
-	wrd = ReadAWord(dev, 0x1aa);	/* bytes 0 + 1 of NodeID */
-	if (!clone && (wrd != htons(0x0080))) /* Valid D-Link ether sequence? */
-		return -1; /* Nope, not a DE-620 */
-	nic_data.NodeID[0] = wrd & 0xff;
-	nic_data.NodeID[1] = wrd >> 8;
-
-	wrd = ReadAWord(dev, 0x1ab);	/* bytes 2 + 3 of NodeID */
-	if (!clone && ((wrd & 0xff) != 0xc8)) /* Valid D-Link ether sequence? */
-		return -1; /* Nope, not a DE-620 */
-	nic_data.NodeID[2] = wrd & 0xff;
-	nic_data.NodeID[3] = wrd >> 8;
-
-	wrd = ReadAWord(dev, 0x1ac);	/* bytes 4 + 5 of NodeID */
-	nic_data.NodeID[4] = wrd & 0xff;
-	nic_data.NodeID[5] = wrd >> 8;
-
-	wrd = ReadAWord(dev, 0x1ad);	/* RAM size in pages (256 bytes). 0 = 64k */
-	nic_data.RAM_Size = (wrd >> 8);
-
-	wrd = ReadAWord(dev, 0x1ae);	/* hardware model (CT = 3) */
-	nic_data.Model = (wrd & 0xff);
-
-	wrd = ReadAWord(dev, 0x1af); /* media (indicates BNC/UTP) */
-	nic_data.Media = (wrd & 0xff);
-
-	wrd = ReadAWord(dev, 0x1a8); /* System Configuration Register */
-	nic_data.SCR = (wrd >> 8);
-
-	return 0; /* no errors */
-}
-
-/******************************************************************************
- *
- * Loadable module skeleton
- *
- */
-#ifdef MODULE
-static struct net_device *de620_dev;
-
-int __init init_module(void)
-{
-	de620_dev = de620_probe(-1);
-	if (IS_ERR(de620_dev))
-		return PTR_ERR(de620_dev);
-	return 0;
-}
-
-void cleanup_module(void)
-{
-	unregister_netdev(de620_dev);
-	release_region(de620_dev->base_addr, 3);
-	free_netdev(de620_dev);
-}
-#endif /* MODULE */
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/de620.h linux-libre-3.2-gnu/drivers/net/de620.h
--- linux-libre-3.1-gnu/drivers/net/de620.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/de620.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,117 +0,0 @@
-/*********************************************************
- *                                                       *
- * Definition of D-Link DE-620 Ethernet Pocket adapter   *
- *                                                       *
- *********************************************************/
-
-/* DE-620's CMD port Command */
-#define CS0		0x08	/* 1->0 command strobe */
-#define ICEN		0x04	/* 0=enable DL3520 host interface */
-#define DS0		0x02	/* 1->0 data strobe 0 */
-#define DS1		0x01	/* 1->0 data strobe 1 */
-
-#define WDIR		0x20	/* general 0=read  1=write */
-#define RDIR		0x00	/*  (not 100% confirm ) */
-#define PS2WDIR		0x00	/* ps/2 mode 1=read, 0=write */
-#define PS2RDIR		0x20
-
-#define IRQEN		0x10	/* 1 = enable printer IRQ line */
-#define SELECTIN	0x08	/* 1 = select printer */
-#define INITP		0x04	/* 0 = initial printer */
-#define AUTOFEED	0x02	/* 1 = printer auto form feed */
-#define STROBE		0x01	/* 0->1 data strobe */
-
-#define RESET		0x08
-#define NIS0		0x20	/* 0 = BNC, 1 = UTP */
-#define NCTL0		0x10
-
-/* DE-620 DIC Command */
-#define W_DUMMY		0x00	/* DIC reserved command */
-#define W_CR		0x20	/* DIC write command register */
-#define W_NPR		0x40	/* DIC write Next Page Register */
-#define W_TBR		0x60	/* DIC write Tx Byte Count 1 reg */
-#define W_RSA		0x80	/* DIC write Remote Start Addr 1 */
-
-/* DE-620's STAT port bits 7-4 */
-#define EMPTY		0x80	/* 1 = receive buffer empty */
-#define INTLEVEL	0x40	/* 1 = interrupt level is high */
-#define TXBF1		0x20	/* 1 = transmit buffer 1 is in use */
-#define TXBF0		0x10	/* 1 = transmit buffer 0 is in use */
-#define READY		0x08	/* 1 = h/w ready to accept cmd/data */
-
-/* IDC 1 Command */
-#define	W_RSA1		0xa0	/* write remote start address 1 */
-#define	W_RSA0		0xa1	/* write remote start address 0 */
-#define	W_NPRF		0xa2	/* write next page register NPR15-NPR8 */
-#define	W_DFR		0xa3	/* write delay factor register */
-#define	W_CPR		0xa4	/* write current page register */
-#define	W_SPR		0xa5	/* write start page register */
-#define	W_EPR		0xa6	/* write end page register */
-#define	W_SCR		0xa7	/* write system configuration register */
-#define	W_TCR		0xa8	/* write Transceiver Configuration reg */
-#define	W_EIP		0xa9	/* write EEPM Interface port */
-#define	W_PAR0		0xaa	/* write physical address register 0 */
-#define	W_PAR1		0xab	/* write physical address register 1 */
-#define	W_PAR2		0xac	/* write physical address register 2 */
-#define	W_PAR3		0xad	/* write physical address register 3 */
-#define	W_PAR4		0xae	/* write physical address register 4 */
-#define	W_PAR5		0xaf	/* write physical address register 5 */
-
-/* IDC 2 Command */
-#define	R_STS		0xc0	/* read status register */
-#define	R_CPR		0xc1	/* read current page register */
-#define	R_BPR		0xc2	/* read boundary page register */
-#define	R_TDR		0xc3	/* read time domain reflectometry reg */
-
-/* STATUS Register */
-#define EEDI		0x80	/* EEPM DO pin */
-#define TXSUC		0x40	/* tx success */
-#define T16		0x20	/* tx fail 16 times */
-#define TS1		0x40	/* 0=Tx success, 1=T16 */
-#define TS0		0x20	/* 0=Tx success, 1=T16 */
-#define RXGOOD		0x10	/* rx a good packet */
-#define RXCRC		0x08	/* rx a CRC error packet */
-#define RXSHORT		0x04	/* rx a short packet */
-#define COLS		0x02	/* coaxial collision status */
-#define LNKS		0x01	/* UTP link status */
-
-/* Command Register */
-#define CLEAR		0x10	/* reset part of hardware */
-#define NOPER		0x08	/* No Operation */
-#define RNOP		0x08
-#define RRA		0x06	/* After RR then auto-advance NPR & BPR(=NPR-1) */
-#define RRN		0x04	/* Normal Remote Read mode */
-#define RW1		0x02	/* Remote Write tx buffer 1  ( page 6 - 11 ) */
-#define RW0		0x00	/* Remote Write tx buffer 0  ( page 0 - 5 ) */
-#define TXEN		0x01	/* 0->1 tx enable */
-
-/* System Configuration Register */
-#define TESTON		0x80	/* test host data transfer reliability */
-#define SLEEP		0x40	/* sleep mode */
-#if 0
-#define FASTMODE	0x04	/* fast mode for intel 82360SL fast mode */
-#define BYTEMODE	0x02	/* byte mode */
-#else
-#define FASTMODE	0x20	/* fast mode for intel 82360SL fast mode */
-#define BYTEMODE	0x10	/* byte mode */
-#endif
-#define NIBBLEMODE	0x00	/* nibble mode */
-#define IRQINV		0x08	/* turn off IRQ line inverter */
-#define IRQNML		0x00	/* turn on IRQ line inverter */
-#define INTON		0x04
-#define AUTOFFSET	0x02	/* auto shift address to TPR+12 */
-#define AUTOTX		0x01	/* auto tx when leave RW mode */
-
-/* Transceiver Configuration Register */
-#define JABBER		0x80	/* generate jabber condition */
-#define TXSUCINT	0x40	/* enable tx success interrupt */
-#define T16INT		0x20	/* enable T16 interrupt */
-#define RXERRPKT	0x10	/* accept CRC error or short packet */
-#define EXTERNALB2	0x0C	/* external loopback 2 */
-#define EXTERNALB1	0x08	/* external loopback 1 */
-#define INTERNALB	0x04	/* internal loopback */
-#define NMLOPERATE	0x00	/* normal operation */
-#define RXPBM		0x03	/* rx physical, broadcast, multicast */
-#define RXPB		0x02	/* rx physical, broadcast */
-#define RXALL		0x01	/* rx all packet */
-#define RXOFF		0x00	/* rx disable */
diff -druN linux-libre-3.1-gnu/drivers/net/declance.c linux-libre-3.2-gnu/drivers/net/declance.c
--- linux-libre-3.1-gnu/drivers/net/declance.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/declance.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1381 +0,0 @@
-/*
- *    Lance ethernet driver for the MIPS processor based
- *      DECstation family
- *
- *
- *      adopted from sunlance.c by Richard van den Berg
- *
- *      Copyright (C) 2002, 2003, 2005, 2006  Maciej W. Rozycki
- *
- *      additional sources:
- *      - PMAD-AA TURBOchannel Ethernet Module Functional Specification,
- *        Revision 1.2
- *
- *      History:
- *
- *      v0.001: The kernel accepts the code and it shows the hardware address.
- *
- *      v0.002: Removed most sparc stuff, left only some module and dma stuff.
- *
- *      v0.003: Enhanced base address calculation from proposals by
- *              Harald Koerfgen and Thomas Riemer.
- *
- *      v0.004: lance-regs is pointing at the right addresses, added prom
- *              check. First start of address mapping and DMA.
- *
- *      v0.005: started to play around with LANCE-DMA. This driver will not
- *              work for non IOASIC lances. HK
- *
- *      v0.006: added pointer arrays to lance_private and setup routine for
- *              them in dec_lance_init. HK
- *
- *      v0.007: Big shit. The LANCE seems to use a different DMA mechanism to
- *              access the init block. This looks like one (short) word at a
- *              time, but the smallest amount the IOASIC can transfer is a
- *              (long) word. So we have a 2-2 padding here. Changed
- *              lance_init_block accordingly. The 16-16 padding for the buffers
- *              seems to be correct. HK
- *
- *      v0.008: mods to make PMAX_LANCE work. 01/09/1999 triemer
- *
- *      v0.009: Module support fixes, multiple interfaces support, various
- *              bits. macro
- *
- *      v0.010: Fixes for the PMAD mapping of the LANCE buffer and for the
- *              PMAX requirement to only use halfword accesses to the
- *              buffer. macro
- *
- *      v0.011: Converted the PMAD to the driver model. macro
- */
-
-#include <linux/crc32.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/if_ether.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/spinlock.h>
-#include <linux/stddef.h>
-#include <linux/string.h>
-#include <linux/tc.h>
-#include <linux/types.h>
-
-#include <asm/addrspace.h>
-#include <asm/system.h>
-
-#include <asm/dec/interrupts.h>
-#include <asm/dec/ioasic.h>
-#include <asm/dec/ioasic_addrs.h>
-#include <asm/dec/kn01.h>
-#include <asm/dec/machtype.h>
-#include <asm/dec/system.h>
-
-static char version[] __devinitdata =
-"declance.c: v0.011 by Linux MIPS DECstation task force\n";
-
-MODULE_AUTHOR("Linux MIPS DECstation task force");
-MODULE_DESCRIPTION("DEC LANCE (DECstation onboard, PMAD-xx) driver");
-MODULE_LICENSE("GPL");
-
-#define __unused __attribute__ ((unused))
-
-/*
- * card types
- */
-#define ASIC_LANCE 1
-#define PMAD_LANCE 2
-#define PMAX_LANCE 3
-
-
-#define LE_CSR0 0
-#define LE_CSR1 1
-#define LE_CSR2 2
-#define LE_CSR3 3
-
-#define LE_MO_PROM      0x8000	/* Enable promiscuous mode */
-
-#define	LE_C0_ERR	0x8000	/* Error: set if BAB, SQE, MISS or ME is set */
-#define	LE_C0_BABL	0x4000	/* BAB:  Babble: tx timeout. */
-#define	LE_C0_CERR	0x2000	/* SQE:  Signal quality error */
-#define	LE_C0_MISS	0x1000	/* MISS: Missed a packet */
-#define	LE_C0_MERR	0x0800	/* ME:   Memory error */
-#define	LE_C0_RINT	0x0400	/* Received interrupt */
-#define	LE_C0_TINT	0x0200	/* Transmitter Interrupt */
-#define	LE_C0_IDON	0x0100	/* IFIN: Init finished. */
-#define	LE_C0_INTR	0x0080	/* Interrupt or error */
-#define	LE_C0_INEA	0x0040	/* Interrupt enable */
-#define	LE_C0_RXON	0x0020	/* Receiver on */
-#define	LE_C0_TXON	0x0010	/* Transmitter on */
-#define	LE_C0_TDMD	0x0008	/* Transmitter demand */
-#define	LE_C0_STOP	0x0004	/* Stop the card */
-#define	LE_C0_STRT	0x0002	/* Start the card */
-#define	LE_C0_INIT	0x0001	/* Init the card */
-
-#define	LE_C3_BSWP	0x4	/* SWAP */
-#define	LE_C3_ACON	0x2	/* ALE Control */
-#define	LE_C3_BCON	0x1	/* Byte control */
-
-/* Receive message descriptor 1 */
-#define LE_R1_OWN	0x8000	/* Who owns the entry */
-#define LE_R1_ERR	0x4000	/* Error: if FRA, OFL, CRC or BUF is set */
-#define LE_R1_FRA	0x2000	/* FRA: Frame error */
-#define LE_R1_OFL	0x1000	/* OFL: Frame overflow */
-#define LE_R1_CRC	0x0800	/* CRC error */
-#define LE_R1_BUF	0x0400	/* BUF: Buffer error */
-#define LE_R1_SOP	0x0200	/* Start of packet */
-#define LE_R1_EOP	0x0100	/* End of packet */
-#define LE_R1_POK	0x0300	/* Packet is complete: SOP + EOP */
-
-/* Transmit message descriptor 1 */
-#define LE_T1_OWN	0x8000	/* Lance owns the packet */
-#define LE_T1_ERR	0x4000	/* Error summary */
-#define LE_T1_EMORE	0x1000	/* Error: more than one retry needed */
-#define LE_T1_EONE	0x0800	/* Error: one retry needed */
-#define LE_T1_EDEF	0x0400	/* Error: deferred */
-#define LE_T1_SOP	0x0200	/* Start of packet */
-#define LE_T1_EOP	0x0100	/* End of packet */
-#define LE_T1_POK	0x0300	/* Packet is complete: SOP + EOP */
-
-#define LE_T3_BUF       0x8000	/* Buffer error */
-#define LE_T3_UFL       0x4000	/* Error underflow */
-#define LE_T3_LCOL      0x1000	/* Error late collision */
-#define LE_T3_CLOS      0x0800	/* Error carrier loss */
-#define LE_T3_RTY       0x0400	/* Error retry */
-#define LE_T3_TDR       0x03ff	/* Time Domain Reflectometry counter */
-
-/* Define: 2^4 Tx buffers and 2^4 Rx buffers */
-
-#ifndef LANCE_LOG_TX_BUFFERS
-#define LANCE_LOG_TX_BUFFERS 4
-#define LANCE_LOG_RX_BUFFERS 4
-#endif
-
-#define TX_RING_SIZE			(1 << (LANCE_LOG_TX_BUFFERS))
-#define TX_RING_MOD_MASK		(TX_RING_SIZE - 1)
-
-#define RX_RING_SIZE			(1 << (LANCE_LOG_RX_BUFFERS))
-#define RX_RING_MOD_MASK		(RX_RING_SIZE - 1)
-
-#define PKT_BUF_SZ		1536
-#define RX_BUFF_SIZE            PKT_BUF_SZ
-#define TX_BUFF_SIZE            PKT_BUF_SZ
-
-#undef TEST_HITS
-#define ZERO 0
-
-/*
- * The DS2100/3100 have a linear 64 kB buffer which supports halfword
- * accesses only.  Each halfword of the buffer is word-aligned in the
- * CPU address space.
- *
- * The PMAD-AA has a 128 kB buffer on-board.
- *
- * The IOASIC LANCE devices use a shared memory region.  This region
- * as seen from the CPU is (max) 128 kB long and has to be on an 128 kB
- * boundary.  The LANCE sees this as a 64 kB long continuous memory
- * region.
- *
- * The LANCE's DMA address is used as an index in this buffer and DMA
- * takes place in bursts of eight 16-bit words which are packed into
- * four 32-bit words by the IOASIC.  This leads to a strange padding:
- * 16 bytes of valid data followed by a 16 byte gap :-(.
- */
-
-struct lance_rx_desc {
-	unsigned short rmd0;		/* low address of packet */
-	unsigned short rmd1;		/* high address of packet
-					   and descriptor bits */
-	short length;			/* 2s complement (negative!)
-					   of buffer length */
-	unsigned short mblength;	/* actual number of bytes received */
-};
-
-struct lance_tx_desc {
-	unsigned short tmd0;		/* low address of packet */
-	unsigned short tmd1;		/* high address of packet
-					   and descriptor bits */
-	short length;			/* 2s complement (negative!)
-					   of buffer length */
-	unsigned short misc;
-};
-
-
-/* First part of the LANCE initialization block, described in databook. */
-struct lance_init_block {
-	unsigned short mode;		/* pre-set mode (reg. 15) */
-
-	unsigned short phys_addr[3];	/* physical ethernet address */
-	unsigned short filter[4];	/* multicast filter */
-
-	/* Receive and transmit ring base, along with extra bits. */
-	unsigned short rx_ptr;		/* receive descriptor addr */
-	unsigned short rx_len;		/* receive len and high addr */
-	unsigned short tx_ptr;		/* transmit descriptor addr */
-	unsigned short tx_len;		/* transmit len and high addr */
-
-	short gap[4];
-
-	/* The buffer descriptors */
-	struct lance_rx_desc brx_ring[RX_RING_SIZE];
-	struct lance_tx_desc btx_ring[TX_RING_SIZE];
-};
-
-#define BUF_OFFSET_CPU sizeof(struct lance_init_block)
-#define BUF_OFFSET_LNC sizeof(struct lance_init_block)
-
-#define shift_off(off, type)						\
-	(type == ASIC_LANCE || type == PMAX_LANCE ? off << 1 : off)
-
-#define lib_off(rt, type)						\
-	shift_off(offsetof(struct lance_init_block, rt), type)
-
-#define lib_ptr(ib, rt, type) 						\
-	((volatile u16 *)((u8 *)(ib) + lib_off(rt, type)))
-
-#define rds_off(rt, type)						\
-	shift_off(offsetof(struct lance_rx_desc, rt), type)
-
-#define rds_ptr(rd, rt, type) 						\
-	((volatile u16 *)((u8 *)(rd) + rds_off(rt, type)))
-
-#define tds_off(rt, type)						\
-	shift_off(offsetof(struct lance_tx_desc, rt), type)
-
-#define tds_ptr(td, rt, type) 						\
-	((volatile u16 *)((u8 *)(td) + tds_off(rt, type)))
-
-struct lance_private {
-	struct net_device *next;
-	int type;
-	int dma_irq;
-	volatile struct lance_regs *ll;
-
-	spinlock_t	lock;
-
-	int rx_new, tx_new;
-	int rx_old, tx_old;
-
-	unsigned short busmaster_regval;
-
-	struct timer_list       multicast_timer;
-
-	/* Pointers to the ring buffers as seen from the CPU */
-	char *rx_buf_ptr_cpu[RX_RING_SIZE];
-	char *tx_buf_ptr_cpu[TX_RING_SIZE];
-
-	/* Pointers to the ring buffers as seen from the LANCE */
-	uint rx_buf_ptr_lnc[RX_RING_SIZE];
-	uint tx_buf_ptr_lnc[TX_RING_SIZE];
-};
-
-#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
-			lp->tx_old+TX_RING_MOD_MASK-lp->tx_new:\
-			lp->tx_old - lp->tx_new-1)
-
-/* The lance control ports are at an absolute address, machine and tc-slot
- * dependent.
- * DECstations do only 32-bit access and the LANCE uses 16 bit addresses,
- * so we have to give the structure an extra member making rap pointing
- * at the right address
- */
-struct lance_regs {
-	volatile unsigned short rdp;	/* register data port */
-	unsigned short pad;
-	volatile unsigned short rap;	/* register address port */
-};
-
-int dec_lance_debug = 2;
-
-static struct tc_driver dec_lance_tc_driver;
-static struct net_device *root_lance_dev;
-
-static inline void writereg(volatile unsigned short *regptr, short value)
-{
-	*regptr = value;
-	iob();
-}
-
-/* Load the CSR registers */
-static void load_csrs(struct lance_private *lp)
-{
-	volatile struct lance_regs *ll = lp->ll;
-	uint leptr;
-
-	/* The address space as seen from the LANCE
-	 * begins at address 0. HK
-	 */
-	leptr = 0;
-
-	writereg(&ll->rap, LE_CSR1);
-	writereg(&ll->rdp, (leptr & 0xFFFF));
-	writereg(&ll->rap, LE_CSR2);
-	writereg(&ll->rdp, leptr >> 16);
-	writereg(&ll->rap, LE_CSR3);
-	writereg(&ll->rdp, lp->busmaster_regval);
-
-	/* Point back to csr0 */
-	writereg(&ll->rap, LE_CSR0);
-}
-
-/*
- * Our specialized copy routines
- *
- */
-static void cp_to_buf(const int type, void *to, const void *from, int len)
-{
-	unsigned short *tp;
-	const unsigned short *fp;
-	unsigned short clen;
-	unsigned char *rtp;
-	const unsigned char *rfp;
-
-	if (type == PMAD_LANCE) {
-		memcpy(to, from, len);
-	} else if (type == PMAX_LANCE) {
-		clen = len >> 1;
-		tp = to;
-		fp = from;
-
-		while (clen--) {
-			*tp++ = *fp++;
-			tp++;
-		}
-
-		clen = len & 1;
-		rtp = tp;
-		rfp = fp;
-		while (clen--) {
-			*rtp++ = *rfp++;
-		}
-	} else {
-		/*
-		 * copy 16 Byte chunks
-		 */
-		clen = len >> 4;
-		tp = to;
-		fp = from;
-		while (clen--) {
-			*tp++ = *fp++;
-			*tp++ = *fp++;
-			*tp++ = *fp++;
-			*tp++ = *fp++;
-			*tp++ = *fp++;
-			*tp++ = *fp++;
-			*tp++ = *fp++;
-			*tp++ = *fp++;
-			tp += 8;
-		}
-
-		/*
-		 * do the rest, if any.
-		 */
-		clen = len & 15;
-		rtp = (unsigned char *) tp;
-		rfp = (unsigned char *) fp;
-		while (clen--) {
-			*rtp++ = *rfp++;
-		}
-	}
-
-	iob();
-}
-
-static void cp_from_buf(const int type, void *to, const void *from, int len)
-{
-	unsigned short *tp;
-	const unsigned short *fp;
-	unsigned short clen;
-	unsigned char *rtp;
-	const unsigned char *rfp;
-
-	if (type == PMAD_LANCE) {
-		memcpy(to, from, len);
-	} else if (type == PMAX_LANCE) {
-		clen = len >> 1;
-		tp = to;
-		fp = from;
-		while (clen--) {
-			*tp++ = *fp++;
-			fp++;
-		}
-
-		clen = len & 1;
-
-		rtp = tp;
-		rfp = fp;
-
-		while (clen--) {
-			*rtp++ = *rfp++;
-		}
-	} else {
-
-		/*
-		 * copy 16 Byte chunks
-		 */
-		clen = len >> 4;
-		tp = to;
-		fp = from;
-		while (clen--) {
-			*tp++ = *fp++;
-			*tp++ = *fp++;
-			*tp++ = *fp++;
-			*tp++ = *fp++;
-			*tp++ = *fp++;
-			*tp++ = *fp++;
-			*tp++ = *fp++;
-			*tp++ = *fp++;
-			fp += 8;
-		}
-
-		/*
-		 * do the rest, if any.
-		 */
-		clen = len & 15;
-		rtp = (unsigned char *) tp;
-		rfp = (unsigned char *) fp;
-		while (clen--) {
-			*rtp++ = *rfp++;
-		}
-
-
-	}
-
-}
-
-/* Setup the Lance Rx and Tx rings */
-static void lance_init_ring(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile u16 *ib = (volatile u16 *)dev->mem_start;
-	uint leptr;
-	int i;
-
-	/* Lock out other processes while setting up hardware */
-	netif_stop_queue(dev);
-	lp->rx_new = lp->tx_new = 0;
-	lp->rx_old = lp->tx_old = 0;
-
-	/* Copy the ethernet address to the lance init block.
-	 * XXX bit 0 of the physical address registers has to be zero
-	 */
-	*lib_ptr(ib, phys_addr[0], lp->type) = (dev->dev_addr[1] << 8) |
-				     dev->dev_addr[0];
-	*lib_ptr(ib, phys_addr[1], lp->type) = (dev->dev_addr[3] << 8) |
-				     dev->dev_addr[2];
-	*lib_ptr(ib, phys_addr[2], lp->type) = (dev->dev_addr[5] << 8) |
-				     dev->dev_addr[4];
-	/* Setup the initialization block */
-
-	/* Setup rx descriptor pointer */
-	leptr = offsetof(struct lance_init_block, brx_ring);
-	*lib_ptr(ib, rx_len, lp->type) = (LANCE_LOG_RX_BUFFERS << 13) |
-					 (leptr >> 16);
-	*lib_ptr(ib, rx_ptr, lp->type) = leptr;
-	if (ZERO)
-		printk("RX ptr: %8.8x(%8.8x)\n",
-		       leptr, lib_off(brx_ring, lp->type));
-
-	/* Setup tx descriptor pointer */
-	leptr = offsetof(struct lance_init_block, btx_ring);
-	*lib_ptr(ib, tx_len, lp->type) = (LANCE_LOG_TX_BUFFERS << 13) |
-					 (leptr >> 16);
-	*lib_ptr(ib, tx_ptr, lp->type) = leptr;
-	if (ZERO)
-		printk("TX ptr: %8.8x(%8.8x)\n",
-		       leptr, lib_off(btx_ring, lp->type));
-
-	if (ZERO)
-		printk("TX rings:\n");
-
-	/* Setup the Tx ring entries */
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		leptr = lp->tx_buf_ptr_lnc[i];
-		*lib_ptr(ib, btx_ring[i].tmd0, lp->type) = leptr;
-		*lib_ptr(ib, btx_ring[i].tmd1, lp->type) = (leptr >> 16) &
-							   0xff;
-		*lib_ptr(ib, btx_ring[i].length, lp->type) = 0xf000;
-						/* The ones required by tmd2 */
-		*lib_ptr(ib, btx_ring[i].misc, lp->type) = 0;
-		if (i < 3 && ZERO)
-			printk("%d: 0x%8.8x(0x%8.8x)\n",
-			       i, leptr, (uint)lp->tx_buf_ptr_cpu[i]);
-	}
-
-	/* Setup the Rx ring entries */
-	if (ZERO)
-		printk("RX rings:\n");
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		leptr = lp->rx_buf_ptr_lnc[i];
-		*lib_ptr(ib, brx_ring[i].rmd0, lp->type) = leptr;
-		*lib_ptr(ib, brx_ring[i].rmd1, lp->type) = ((leptr >> 16) &
-							    0xff) |
-							   LE_R1_OWN;
-		*lib_ptr(ib, brx_ring[i].length, lp->type) = -RX_BUFF_SIZE |
-							     0xf000;
-		*lib_ptr(ib, brx_ring[i].mblength, lp->type) = 0;
-		if (i < 3 && ZERO)
-			printk("%d: 0x%8.8x(0x%8.8x)\n",
-			       i, leptr, (uint)lp->rx_buf_ptr_cpu[i]);
-	}
-	iob();
-}
-
-static int init_restart_lance(struct lance_private *lp)
-{
-	volatile struct lance_regs *ll = lp->ll;
-	int i;
-
-	writereg(&ll->rap, LE_CSR0);
-	writereg(&ll->rdp, LE_C0_INIT);
-
-	/* Wait for the lance to complete initialization */
-	for (i = 0; (i < 100) && !(ll->rdp & LE_C0_IDON); i++) {
-		udelay(10);
-	}
-	if ((i == 100) || (ll->rdp & LE_C0_ERR)) {
-		printk("LANCE unopened after %d ticks, csr0=%4.4x.\n",
-		       i, ll->rdp);
-		return -1;
-	}
-	if ((ll->rdp & LE_C0_ERR)) {
-		printk("LANCE unopened after %d ticks, csr0=%4.4x.\n",
-		       i, ll->rdp);
-		return -1;
-	}
-	writereg(&ll->rdp, LE_C0_IDON);
-	writereg(&ll->rdp, LE_C0_STRT);
-	writereg(&ll->rdp, LE_C0_INEA);
-
-	return 0;
-}
-
-static int lance_rx(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile u16 *ib = (volatile u16 *)dev->mem_start;
-	volatile u16 *rd;
-	unsigned short bits;
-	int entry, len;
-	struct sk_buff *skb;
-
-#ifdef TEST_HITS
-	{
-		int i;
-
-		printk("[");
-		for (i = 0; i < RX_RING_SIZE; i++) {
-			if (i == lp->rx_new)
-				printk("%s", *lib_ptr(ib, brx_ring[i].rmd1,
-						      lp->type) &
-					     LE_R1_OWN ? "_" : "X");
-			else
-				printk("%s", *lib_ptr(ib, brx_ring[i].rmd1,
-						      lp->type) &
-					     LE_R1_OWN ? "." : "1");
-		}
-		printk("]");
-	}
-#endif
-
-	for (rd = lib_ptr(ib, brx_ring[lp->rx_new], lp->type);
-	     !((bits = *rds_ptr(rd, rmd1, lp->type)) & LE_R1_OWN);
-	     rd = lib_ptr(ib, brx_ring[lp->rx_new], lp->type)) {
-		entry = lp->rx_new;
-
-		/* We got an incomplete frame? */
-		if ((bits & LE_R1_POK) != LE_R1_POK) {
-			dev->stats.rx_over_errors++;
-			dev->stats.rx_errors++;
-		} else if (bits & LE_R1_ERR) {
-			/* Count only the end frame as a rx error,
-			 * not the beginning
-			 */
-			if (bits & LE_R1_BUF)
-				dev->stats.rx_fifo_errors++;
-			if (bits & LE_R1_CRC)
-				dev->stats.rx_crc_errors++;
-			if (bits & LE_R1_OFL)
-				dev->stats.rx_over_errors++;
-			if (bits & LE_R1_FRA)
-				dev->stats.rx_frame_errors++;
-			if (bits & LE_R1_EOP)
-				dev->stats.rx_errors++;
-		} else {
-			len = (*rds_ptr(rd, mblength, lp->type) & 0xfff) - 4;
-			skb = dev_alloc_skb(len + 2);
-
-			if (skb == 0) {
-				printk("%s: Memory squeeze, deferring packet.\n",
-				       dev->name);
-				dev->stats.rx_dropped++;
-				*rds_ptr(rd, mblength, lp->type) = 0;
-				*rds_ptr(rd, rmd1, lp->type) =
-					((lp->rx_buf_ptr_lnc[entry] >> 16) &
-					 0xff) | LE_R1_OWN;
-				lp->rx_new = (entry + 1) & RX_RING_MOD_MASK;
-				return 0;
-			}
-			dev->stats.rx_bytes += len;
-
-			skb_reserve(skb, 2);	/* 16 byte align */
-			skb_put(skb, len);	/* make room */
-
-			cp_from_buf(lp->type, skb->data,
-				    (char *)lp->rx_buf_ptr_cpu[entry], len);
-
-			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
-			dev->stats.rx_packets++;
-		}
-
-		/* Return the packet to the pool */
-		*rds_ptr(rd, mblength, lp->type) = 0;
-		*rds_ptr(rd, length, lp->type) = -RX_BUFF_SIZE | 0xf000;
-		*rds_ptr(rd, rmd1, lp->type) =
-			((lp->rx_buf_ptr_lnc[entry] >> 16) & 0xff) | LE_R1_OWN;
-		lp->rx_new = (entry + 1) & RX_RING_MOD_MASK;
-	}
-	return 0;
-}
-
-static void lance_tx(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile u16 *ib = (volatile u16 *)dev->mem_start;
-	volatile struct lance_regs *ll = lp->ll;
-	volatile u16 *td;
-	int i, j;
-	int status;
-
-	j = lp->tx_old;
-
-	spin_lock(&lp->lock);
-
-	for (i = j; i != lp->tx_new; i = j) {
-		td = lib_ptr(ib, btx_ring[i], lp->type);
-		/* If we hit a packet not owned by us, stop */
-		if (*tds_ptr(td, tmd1, lp->type) & LE_T1_OWN)
-			break;
-
-		if (*tds_ptr(td, tmd1, lp->type) & LE_T1_ERR) {
-			status = *tds_ptr(td, misc, lp->type);
-
-			dev->stats.tx_errors++;
-			if (status & LE_T3_RTY)
-				dev->stats.tx_aborted_errors++;
-			if (status & LE_T3_LCOL)
-				dev->stats.tx_window_errors++;
-
-			if (status & LE_T3_CLOS) {
-				dev->stats.tx_carrier_errors++;
-				printk("%s: Carrier Lost\n", dev->name);
-				/* Stop the lance */
-				writereg(&ll->rap, LE_CSR0);
-				writereg(&ll->rdp, LE_C0_STOP);
-				lance_init_ring(dev);
-				load_csrs(lp);
-				init_restart_lance(lp);
-				goto out;
-			}
-			/* Buffer errors and underflows turn off the
-			 * transmitter, restart the adapter.
-			 */
-			if (status & (LE_T3_BUF | LE_T3_UFL)) {
-				dev->stats.tx_fifo_errors++;
-
-				printk("%s: Tx: ERR_BUF|ERR_UFL, restarting\n",
-				       dev->name);
-				/* Stop the lance */
-				writereg(&ll->rap, LE_CSR0);
-				writereg(&ll->rdp, LE_C0_STOP);
-				lance_init_ring(dev);
-				load_csrs(lp);
-				init_restart_lance(lp);
-				goto out;
-			}
-		} else if ((*tds_ptr(td, tmd1, lp->type) & LE_T1_POK) ==
-			   LE_T1_POK) {
-			/*
-			 * So we don't count the packet more than once.
-			 */
-			*tds_ptr(td, tmd1, lp->type) &= ~(LE_T1_POK);
-
-			/* One collision before packet was sent. */
-			if (*tds_ptr(td, tmd1, lp->type) & LE_T1_EONE)
-				dev->stats.collisions++;
-
-			/* More than one collision, be optimistic. */
-			if (*tds_ptr(td, tmd1, lp->type) & LE_T1_EMORE)
-				dev->stats.collisions += 2;
-
-			dev->stats.tx_packets++;
-		}
-		j = (j + 1) & TX_RING_MOD_MASK;
-	}
-	lp->tx_old = j;
-out:
-	if (netif_queue_stopped(dev) &&
-	    TX_BUFFS_AVAIL > 0)
-		netif_wake_queue(dev);
-
-	spin_unlock(&lp->lock);
-}
-
-static irqreturn_t lance_dma_merr_int(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-
-	printk(KERN_ERR "%s: DMA error\n", dev->name);
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t lance_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_regs *ll = lp->ll;
-	int csr0;
-
-	writereg(&ll->rap, LE_CSR0);
-	csr0 = ll->rdp;
-
-	/* Acknowledge all the interrupt sources ASAP */
-	writereg(&ll->rdp, csr0 & (LE_C0_INTR | LE_C0_TINT | LE_C0_RINT));
-
-	if ((csr0 & LE_C0_ERR)) {
-		/* Clear the error condition */
-		writereg(&ll->rdp, LE_C0_BABL | LE_C0_ERR | LE_C0_MISS |
-			 LE_C0_CERR | LE_C0_MERR);
-	}
-	if (csr0 & LE_C0_RINT)
-		lance_rx(dev);
-
-	if (csr0 & LE_C0_TINT)
-		lance_tx(dev);
-
-	if (csr0 & LE_C0_BABL)
-		dev->stats.tx_errors++;
-
-	if (csr0 & LE_C0_MISS)
-		dev->stats.rx_errors++;
-
-	if (csr0 & LE_C0_MERR) {
-		printk("%s: Memory error, status %04x\n", dev->name, csr0);
-
-		writereg(&ll->rdp, LE_C0_STOP);
-
-		lance_init_ring(dev);
-		load_csrs(lp);
-		init_restart_lance(lp);
-		netif_wake_queue(dev);
-	}
-
-	writereg(&ll->rdp, LE_C0_INEA);
-	writereg(&ll->rdp, LE_C0_INEA);
-	return IRQ_HANDLED;
-}
-
-static int lance_open(struct net_device *dev)
-{
-	volatile u16 *ib = (volatile u16 *)dev->mem_start;
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_regs *ll = lp->ll;
-	int status = 0;
-
-	/* Stop the Lance */
-	writereg(&ll->rap, LE_CSR0);
-	writereg(&ll->rdp, LE_C0_STOP);
-
-	/* Set mode and clear multicast filter only at device open,
-	 * so that lance_init_ring() called at any error will not
-	 * forget multicast filters.
-	 *
-	 * BTW it is common bug in all lance drivers! --ANK
-	 */
-	*lib_ptr(ib, mode, lp->type) = 0;
-	*lib_ptr(ib, filter[0], lp->type) = 0;
-	*lib_ptr(ib, filter[1], lp->type) = 0;
-	*lib_ptr(ib, filter[2], lp->type) = 0;
-	*lib_ptr(ib, filter[3], lp->type) = 0;
-
-	lance_init_ring(dev);
-	load_csrs(lp);
-
-	netif_start_queue(dev);
-
-	/* Associate IRQ with lance_interrupt */
-	if (request_irq(dev->irq, lance_interrupt, 0, "lance", dev)) {
-		printk("%s: Can't get IRQ %d\n", dev->name, dev->irq);
-		return -EAGAIN;
-	}
-	if (lp->dma_irq >= 0) {
-		unsigned long flags;
-
-		if (request_irq(lp->dma_irq, lance_dma_merr_int, 0,
-				"lance error", dev)) {
-			free_irq(dev->irq, dev);
-			printk("%s: Can't get DMA IRQ %d\n", dev->name,
-				lp->dma_irq);
-			return -EAGAIN;
-		}
-
-		spin_lock_irqsave(&ioasic_ssr_lock, flags);
-
-		fast_mb();
-		/* Enable I/O ASIC LANCE DMA.  */
-		ioasic_write(IO_REG_SSR,
-			     ioasic_read(IO_REG_SSR) | IO_SSR_LANCE_DMA_EN);
-
-		fast_mb();
-		spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
-	}
-
-	status = init_restart_lance(lp);
-	return status;
-}
-
-static int lance_close(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_regs *ll = lp->ll;
-
-	netif_stop_queue(dev);
-	del_timer_sync(&lp->multicast_timer);
-
-	/* Stop the card */
-	writereg(&ll->rap, LE_CSR0);
-	writereg(&ll->rdp, LE_C0_STOP);
-
-	if (lp->dma_irq >= 0) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&ioasic_ssr_lock, flags);
-
-		fast_mb();
-		/* Disable I/O ASIC LANCE DMA.  */
-		ioasic_write(IO_REG_SSR,
-			     ioasic_read(IO_REG_SSR) & ~IO_SSR_LANCE_DMA_EN);
-
-		fast_iob();
-		spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
-
-		free_irq(lp->dma_irq, dev);
-	}
-	free_irq(dev->irq, dev);
-	return 0;
-}
-
-static inline int lance_reset(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_regs *ll = lp->ll;
-	int status;
-
-	/* Stop the lance */
-	writereg(&ll->rap, LE_CSR0);
-	writereg(&ll->rdp, LE_C0_STOP);
-
-	lance_init_ring(dev);
-	load_csrs(lp);
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	status = init_restart_lance(lp);
-	return status;
-}
-
-static void lance_tx_timeout(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_regs *ll = lp->ll;
-
-	printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n",
-		dev->name, ll->rdp);
-	lance_reset(dev);
-	netif_wake_queue(dev);
-}
-
-static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_regs *ll = lp->ll;
-	volatile u16 *ib = (volatile u16 *)dev->mem_start;
-	unsigned long flags;
-	int entry, len;
-
-	len = skb->len;
-
-	if (len < ETH_ZLEN) {
-		if (skb_padto(skb, ETH_ZLEN))
-			return NETDEV_TX_OK;
-		len = ETH_ZLEN;
-	}
-
-	dev->stats.tx_bytes += len;
-
-	spin_lock_irqsave(&lp->lock, flags);
-
-	entry = lp->tx_new;
-	*lib_ptr(ib, btx_ring[entry].length, lp->type) = (-len);
-	*lib_ptr(ib, btx_ring[entry].misc, lp->type) = 0;
-
-	cp_to_buf(lp->type, (char *)lp->tx_buf_ptr_cpu[entry], skb->data, len);
-
-	/* Now, give the packet to the lance */
-	*lib_ptr(ib, btx_ring[entry].tmd1, lp->type) =
-		((lp->tx_buf_ptr_lnc[entry] >> 16) & 0xff) |
-		(LE_T1_POK | LE_T1_OWN);
-	lp->tx_new = (entry + 1) & TX_RING_MOD_MASK;
-
-	if (TX_BUFFS_AVAIL <= 0)
-		netif_stop_queue(dev);
-
-	/* Kick the lance: transmit now */
-	writereg(&ll->rdp, LE_C0_INEA | LE_C0_TDMD);
-
-	spin_unlock_irqrestore(&lp->lock, flags);
-
-	dev_kfree_skb(skb);
-
- 	return NETDEV_TX_OK;
-}
-
-static void lance_load_multicast(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile u16 *ib = (volatile u16 *)dev->mem_start;
-	struct netdev_hw_addr *ha;
-	u32 crc;
-
-	/* set all multicast bits */
-	if (dev->flags & IFF_ALLMULTI) {
-		*lib_ptr(ib, filter[0], lp->type) = 0xffff;
-		*lib_ptr(ib, filter[1], lp->type) = 0xffff;
-		*lib_ptr(ib, filter[2], lp->type) = 0xffff;
-		*lib_ptr(ib, filter[3], lp->type) = 0xffff;
-		return;
-	}
-	/* clear the multicast filter */
-	*lib_ptr(ib, filter[0], lp->type) = 0;
-	*lib_ptr(ib, filter[1], lp->type) = 0;
-	*lib_ptr(ib, filter[2], lp->type) = 0;
-	*lib_ptr(ib, filter[3], lp->type) = 0;
-
-	/* Add addresses */
-	netdev_for_each_mc_addr(ha, dev) {
-		crc = ether_crc_le(ETH_ALEN, ha->addr);
-		crc = crc >> 26;
-		*lib_ptr(ib, filter[crc >> 4], lp->type) |= 1 << (crc & 0xf);
-	}
-}
-
-static void lance_set_multicast(struct net_device *dev)
-{
-	struct lance_private *lp = netdev_priv(dev);
-	volatile u16 *ib = (volatile u16 *)dev->mem_start;
-	volatile struct lance_regs *ll = lp->ll;
-
-	if (!netif_running(dev))
-		return;
-
-	if (lp->tx_old != lp->tx_new) {
-		mod_timer(&lp->multicast_timer, jiffies + 4 * HZ/100);
-		netif_wake_queue(dev);
-		return;
-	}
-
-	netif_stop_queue(dev);
-
-	writereg(&ll->rap, LE_CSR0);
-	writereg(&ll->rdp, LE_C0_STOP);
-
-	lance_init_ring(dev);
-
-	if (dev->flags & IFF_PROMISC) {
-		*lib_ptr(ib, mode, lp->type) |= LE_MO_PROM;
-	} else {
-		*lib_ptr(ib, mode, lp->type) &= ~LE_MO_PROM;
-		lance_load_multicast(dev);
-	}
-	load_csrs(lp);
-	init_restart_lance(lp);
-	netif_wake_queue(dev);
-}
-
-static void lance_set_multicast_retry(unsigned long _opaque)
-{
-	struct net_device *dev = (struct net_device *) _opaque;
-
-	lance_set_multicast(dev);
-}
-
-static const struct net_device_ops lance_netdev_ops = {
-	.ndo_open		= lance_open,
-	.ndo_stop		= lance_close,
-	.ndo_start_xmit		= lance_start_xmit,
-	.ndo_tx_timeout		= lance_tx_timeout,
-	.ndo_set_multicast_list	= lance_set_multicast,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address	= eth_mac_addr,
-};
-
-static int __devinit dec_lance_probe(struct device *bdev, const int type)
-{
-	static unsigned version_printed;
-	static const char fmt[] = "declance%d";
-	char name[10];
-	struct net_device *dev;
-	struct lance_private *lp;
-	volatile struct lance_regs *ll;
-	resource_size_t start = 0, len = 0;
-	int i, ret;
-	unsigned long esar_base;
-	unsigned char *esar;
-
-	if (dec_lance_debug && version_printed++ == 0)
-		printk(version);
-
-	if (bdev)
-		snprintf(name, sizeof(name), "%s", dev_name(bdev));
-	else {
-		i = 0;
-		dev = root_lance_dev;
-		while (dev) {
-			i++;
-			lp = netdev_priv(dev);
-			dev = lp->next;
-		}
-		snprintf(name, sizeof(name), fmt, i);
-	}
-
-	dev = alloc_etherdev(sizeof(struct lance_private));
-	if (!dev) {
-		printk(KERN_ERR "%s: Unable to allocate etherdev, aborting.\n",
-			name);
-		ret = -ENOMEM;
-		goto err_out;
-	}
-
-	/*
-	 * alloc_etherdev ensures the data structures used by the LANCE
-	 * are aligned.
-	 */
-	lp = netdev_priv(dev);
-	spin_lock_init(&lp->lock);
-
-	lp->type = type;
-	switch (type) {
-	case ASIC_LANCE:
-		dev->base_addr = CKSEG1ADDR(dec_kn_slot_base + IOASIC_LANCE);
-
-		/* buffer space for the on-board LANCE shared memory */
-		/*
-		 * FIXME: ugly hack!
-		 */
-		dev->mem_start = CKSEG1ADDR(0x00020000);
-		dev->mem_end = dev->mem_start + 0x00020000;
-		dev->irq = dec_interrupt[DEC_IRQ_LANCE];
-		esar_base = CKSEG1ADDR(dec_kn_slot_base + IOASIC_ESAR);
-
-		/* Workaround crash with booting KN04 2.1k from Disk */
-		memset((void *)dev->mem_start, 0,
-		       dev->mem_end - dev->mem_start);
-
-		/*
-		 * setup the pointer arrays, this sucks [tm] :-(
-		 */
-		for (i = 0; i < RX_RING_SIZE; i++) {
-			lp->rx_buf_ptr_cpu[i] =
-				(char *)(dev->mem_start + 2 * BUF_OFFSET_CPU +
-					 2 * i * RX_BUFF_SIZE);
-			lp->rx_buf_ptr_lnc[i] =
-				(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
-		}
-		for (i = 0; i < TX_RING_SIZE; i++) {
-			lp->tx_buf_ptr_cpu[i] =
-				(char *)(dev->mem_start + 2 * BUF_OFFSET_CPU +
-					 2 * RX_RING_SIZE * RX_BUFF_SIZE +
-					 2 * i * TX_BUFF_SIZE);
-			lp->tx_buf_ptr_lnc[i] =
-				(BUF_OFFSET_LNC +
-				 RX_RING_SIZE * RX_BUFF_SIZE +
-				 i * TX_BUFF_SIZE);
-		}
-
-		/* Setup I/O ASIC LANCE DMA.  */
-		lp->dma_irq = dec_interrupt[DEC_IRQ_LANCE_MERR];
-		ioasic_write(IO_REG_LANCE_DMA_P,
-			     CPHYSADDR(dev->mem_start) << 3);
-
-		break;
-#ifdef CONFIG_TC
-	case PMAD_LANCE:
-		dev_set_drvdata(bdev, dev);
-
-		start = to_tc_dev(bdev)->resource.start;
-		len = to_tc_dev(bdev)->resource.end - start + 1;
-		if (!request_mem_region(start, len, dev_name(bdev))) {
-			printk(KERN_ERR
-			       "%s: Unable to reserve MMIO resource\n",
-			       dev_name(bdev));
-			ret = -EBUSY;
-			goto err_out_dev;
-		}
-
-		dev->mem_start = CKSEG1ADDR(start);
-		dev->mem_end = dev->mem_start + 0x100000;
-		dev->base_addr = dev->mem_start + 0x100000;
-		dev->irq = to_tc_dev(bdev)->interrupt;
-		esar_base = dev->mem_start + 0x1c0002;
-		lp->dma_irq = -1;
-
-		for (i = 0; i < RX_RING_SIZE; i++) {
-			lp->rx_buf_ptr_cpu[i] =
-				(char *)(dev->mem_start + BUF_OFFSET_CPU +
-					 i * RX_BUFF_SIZE);
-			lp->rx_buf_ptr_lnc[i] =
-				(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
-		}
-		for (i = 0; i < TX_RING_SIZE; i++) {
-			lp->tx_buf_ptr_cpu[i] =
-				(char *)(dev->mem_start + BUF_OFFSET_CPU +
-					 RX_RING_SIZE * RX_BUFF_SIZE +
-					 i * TX_BUFF_SIZE);
-			lp->tx_buf_ptr_lnc[i] =
-				(BUF_OFFSET_LNC +
-				 RX_RING_SIZE * RX_BUFF_SIZE +
-				 i * TX_BUFF_SIZE);
-		}
-
-		break;
-#endif
-	case PMAX_LANCE:
-		dev->irq = dec_interrupt[DEC_IRQ_LANCE];
-		dev->base_addr = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE);
-		dev->mem_start = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE_MEM);
-		dev->mem_end = dev->mem_start + KN01_SLOT_SIZE;
-		esar_base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_ESAR + 1);
-		lp->dma_irq = -1;
-
-		/*
-		 * setup the pointer arrays, this sucks [tm] :-(
-		 */
-		for (i = 0; i < RX_RING_SIZE; i++) {
-			lp->rx_buf_ptr_cpu[i] =
-				(char *)(dev->mem_start + 2 * BUF_OFFSET_CPU +
-					 2 * i * RX_BUFF_SIZE);
-			lp->rx_buf_ptr_lnc[i] =
-				(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
-		}
-		for (i = 0; i < TX_RING_SIZE; i++) {
-			lp->tx_buf_ptr_cpu[i] =
-				(char *)(dev->mem_start + 2 * BUF_OFFSET_CPU +
-					 2 * RX_RING_SIZE * RX_BUFF_SIZE +
-					 2 * i * TX_BUFF_SIZE);
-			lp->tx_buf_ptr_lnc[i] =
-				(BUF_OFFSET_LNC +
-				 RX_RING_SIZE * RX_BUFF_SIZE +
-				 i * TX_BUFF_SIZE);
-		}
-
-		break;
-
-	default:
-		printk(KERN_ERR "%s: declance_init called with unknown type\n",
-			name);
-		ret = -ENODEV;
-		goto err_out_dev;
-	}
-
-	ll = (struct lance_regs *) dev->base_addr;
-	esar = (unsigned char *) esar_base;
-
-	/* prom checks */
-	/* First, check for test pattern */
-	if (esar[0x60] != 0xff && esar[0x64] != 0x00 &&
-	    esar[0x68] != 0x55 && esar[0x6c] != 0xaa) {
-		printk(KERN_ERR
-			"%s: Ethernet station address prom not found!\n",
-			name);
-		ret = -ENODEV;
-		goto err_out_resource;
-	}
-	/* Check the prom contents */
-	for (i = 0; i < 8; i++) {
-		if (esar[i * 4] != esar[0x3c - i * 4] &&
-		    esar[i * 4] != esar[0x40 + i * 4] &&
-		    esar[0x3c - i * 4] != esar[0x40 + i * 4]) {
-			printk(KERN_ERR "%s: Something is wrong with the "
-				"ethernet station address prom!\n", name);
-			ret = -ENODEV;
-			goto err_out_resource;
-		}
-	}
-
-	/* Copy the ethernet address to the device structure, later to the
-	 * lance initialization block so the lance gets it every time it's
-	 * (re)initialized.
-	 */
-	switch (type) {
-	case ASIC_LANCE:
-		printk("%s: IOASIC onboard LANCE", name);
-		break;
-	case PMAD_LANCE:
-		printk("%s: PMAD-AA", name);
-		break;
-	case PMAX_LANCE:
-		printk("%s: PMAX onboard LANCE", name);
-		break;
-	}
-	for (i = 0; i < 6; i++)
-		dev->dev_addr[i] = esar[i * 4];
-
-	printk(", addr = %pM, irq = %d\n", dev->dev_addr, dev->irq);
-
-	dev->netdev_ops = &lance_netdev_ops;
-	dev->watchdog_timeo = 5*HZ;
-
-	/* lp->ll is the location of the registers for lance card */
-	lp->ll = ll;
-
-	/* busmaster_regval (CSR3) should be zero according to the PMAD-AA
-	 * specification.
-	 */
-	lp->busmaster_regval = 0;
-
-	dev->dma = 0;
-
-	/* We cannot sleep if the chip is busy during a
-	 * multicast list update event, because such events
-	 * can occur from interrupts (ex. IPv6).  So we
-	 * use a timer to try again later when necessary. -DaveM
-	 */
-	init_timer(&lp->multicast_timer);
-	lp->multicast_timer.data = (unsigned long) dev;
-	lp->multicast_timer.function = lance_set_multicast_retry;
-
-	ret = register_netdev(dev);
-	if (ret) {
-		printk(KERN_ERR
-			"%s: Unable to register netdev, aborting.\n", name);
-		goto err_out_resource;
-	}
-
-	if (!bdev) {
-		lp->next = root_lance_dev;
-		root_lance_dev = dev;
-	}
-
-	printk("%s: registered as %s.\n", name, dev->name);
-	return 0;
-
-err_out_resource:
-	if (bdev)
-		release_mem_region(start, len);
-
-err_out_dev:
-	free_netdev(dev);
-
-err_out:
-	return ret;
-}
-
-static void __exit dec_lance_remove(struct device *bdev)
-{
-	struct net_device *dev = dev_get_drvdata(bdev);
-	resource_size_t start, len;
-
-	unregister_netdev(dev);
-	start = to_tc_dev(bdev)->resource.start;
-	len = to_tc_dev(bdev)->resource.end - start + 1;
-	release_mem_region(start, len);
-	free_netdev(dev);
-}
-
-/* Find all the lance cards on the system and initialize them */
-static int __init dec_lance_platform_probe(void)
-{
-	int count = 0;
-
-	if (dec_interrupt[DEC_IRQ_LANCE] >= 0) {
-		if (dec_interrupt[DEC_IRQ_LANCE_MERR] >= 0) {
-			if (dec_lance_probe(NULL, ASIC_LANCE) >= 0)
-				count++;
-		} else if (!TURBOCHANNEL) {
-			if (dec_lance_probe(NULL, PMAX_LANCE) >= 0)
-				count++;
-		}
-	}
-
-	return (count > 0) ? 0 : -ENODEV;
-}
-
-static void __exit dec_lance_platform_remove(void)
-{
-	while (root_lance_dev) {
-		struct net_device *dev = root_lance_dev;
-		struct lance_private *lp = netdev_priv(dev);
-
-		unregister_netdev(dev);
-		root_lance_dev = lp->next;
-		free_netdev(dev);
-	}
-}
-
-#ifdef CONFIG_TC
-static int __devinit dec_lance_tc_probe(struct device *dev);
-static int __exit dec_lance_tc_remove(struct device *dev);
-
-static const struct tc_device_id dec_lance_tc_table[] = {
-	{ "DEC     ", "PMAD-AA " },
-	{ }
-};
-MODULE_DEVICE_TABLE(tc, dec_lance_tc_table);
-
-static struct tc_driver dec_lance_tc_driver = {
-	.id_table	= dec_lance_tc_table,
-	.driver		= {
-		.name	= "declance",
-		.bus	= &tc_bus_type,
-		.probe	= dec_lance_tc_probe,
-		.remove	= __exit_p(dec_lance_tc_remove),
-	},
-};
-
-static int __devinit dec_lance_tc_probe(struct device *dev)
-{
-        int status = dec_lance_probe(dev, PMAD_LANCE);
-        if (!status)
-                get_device(dev);
-        return status;
-}
-
-static int __exit dec_lance_tc_remove(struct device *dev)
-{
-        put_device(dev);
-        dec_lance_remove(dev);
-        return 0;
-}
-#endif
-
-static int __init dec_lance_init(void)
-{
-	int status;
-
-	status = tc_register_driver(&dec_lance_tc_driver);
-	if (!status)
-		dec_lance_platform_probe();
-	return status;
-}
-
-static void __exit dec_lance_exit(void)
-{
-	dec_lance_platform_remove();
-	tc_unregister_driver(&dec_lance_tc_driver);
-}
-
-
-module_init(dec_lance_init);
-module_exit(dec_lance_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/defxx.c linux-libre-3.2-gnu/drivers/net/defxx.c
--- linux-libre-3.1-gnu/drivers/net/defxx.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/defxx.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3739 +0,0 @@
-/*
- * File Name:
- *   defxx.c
- *
- * Copyright Information:
- *   Copyright Digital Equipment Corporation 1996.
- *
- *   This software may be used and distributed according to the terms of
- *   the GNU General Public License, incorporated herein by reference.
- *
- * Abstract:
- *   A Linux device driver supporting the Digital Equipment Corporation
- *   FDDI TURBOchannel, EISA and PCI controller families.  Supported
- *   adapters include:
- *
- *		DEC FDDIcontroller/TURBOchannel (DEFTA)
- *		DEC FDDIcontroller/EISA         (DEFEA)
- *		DEC FDDIcontroller/PCI          (DEFPA)
- *
- * The original author:
- *   LVS	Lawrence V. Stefani <lstefani@yahoo.com>
- *
- * Maintainers:
- *   macro	Maciej W. Rozycki <macro@linux-mips.org>
- *
- * Credits:
- *   I'd like to thank Patricia Cross for helping me get started with
- *   Linux, David Davies for a lot of help upgrading and configuring
- *   my development system and for answering many OS and driver
- *   development questions, and Alan Cox for recommendations and
- *   integration help on getting FDDI support into Linux.  LVS
- *
- * Driver Architecture:
- *   The driver architecture is largely based on previous driver work
- *   for other operating systems.  The upper edge interface and
- *   functions were largely taken from existing Linux device drivers
- *   such as David Davies' DE4X5.C driver and Donald Becker's TULIP.C
- *   driver.
- *
- *   Adapter Probe -
- *		The driver scans for supported EISA adapters by reading the
- *		SLOT ID register for each EISA slot and making a match
- *		against the expected value.
- *
- *   Bus-Specific Initialization -
- *		This driver currently supports both EISA and PCI controller
- *		families.  While the custom DMA chip and FDDI logic is similar
- *		or identical, the bus logic is very different.  After
- *		initialization, the	only bus-specific differences is in how the
- *		driver enables and disables interrupts.  Other than that, the
- *		run-time critical code behaves the same on both families.
- *		It's important to note that both adapter families are configured
- *		to I/O map, rather than memory map, the adapter registers.
- *
- *   Driver Open/Close -
- *		In the driver open routine, the driver ISR (interrupt service
- *		routine) is registered and the adapter is brought to an
- *		operational state.  In the driver close routine, the opposite
- *		occurs; the driver ISR is deregistered and the adapter is
- *		brought to a safe, but closed state.  Users may use consecutive
- *		commands to bring the adapter up and down as in the following
- *		example:
- *					ifconfig fddi0 up
- *					ifconfig fddi0 down
- *					ifconfig fddi0 up
- *
- *   Driver Shutdown -
- *		Apparently, there is no shutdown or halt routine support under
- *		Linux.  This routine would be called during "reboot" or
- *		"shutdown" to allow the driver to place the adapter in a safe
- *		state before a warm reboot occurs.  To be really safe, the user
- *		should close the adapter before shutdown (eg. ifconfig fddi0 down)
- *		to ensure that the adapter DMA engine is taken off-line.  However,
- *		the current driver code anticipates this problem and always issues
- *		a soft reset of the adapter	at the beginning of driver initialization.
- *		A future driver enhancement in this area may occur in 2.1.X where
- *		Alan indicated that a shutdown handler may be implemented.
- *
- *   Interrupt Service Routine -
- *		The driver supports shared interrupts, so the ISR is registered for
- *		each board with the appropriate flag and the pointer to that board's
- *		device structure.  This provides the context during interrupt
- *		processing to support shared interrupts and multiple boards.
- *
- *		Interrupt enabling/disabling can occur at many levels.  At the host
- *		end, you can disable system interrupts, or disable interrupts at the
- *		PIC (on Intel systems).  Across the bus, both EISA and PCI adapters
- *		have a bus-logic chip interrupt enable/disable as well as a DMA
- *		controller interrupt enable/disable.
- *
- *		The driver currently enables and disables adapter interrupts at the
- *		bus-logic chip and assumes that Linux will take care of clearing or
- *		acknowledging any host-based interrupt chips.
- *
- *   Control Functions -
- *		Control functions are those used to support functions such as adding
- *		or deleting multicast addresses, enabling or disabling packet
- *		reception filters, or other custom/proprietary commands.  Presently,
- *		the driver supports the "get statistics", "set multicast list", and
- *		"set mac address" functions defined by Linux.  A list of possible
- *		enhancements include:
- *
- *				- Custom ioctl interface for executing port interface commands
- *				- Custom ioctl interface for adding unicast addresses to
- *				  adapter CAM (to support bridge functions).
- *				- Custom ioctl interface for supporting firmware upgrades.
- *
- *   Hardware (port interface) Support Routines -
- *		The driver function names that start with "dfx_hw_" represent
- *		low-level port interface routines that are called frequently.  They
- *		include issuing a DMA or port control command to the adapter,
- *		resetting the adapter, or reading the adapter state.  Since the
- *		driver initialization and run-time code must make calls into the
- *		port interface, these routines were written to be as generic and
- *		usable as possible.
- *
- *   Receive Path -
- *		The adapter DMA engine supports a 256 entry receive descriptor block
- *		of which up to 255 entries can be used at any given time.  The
- *		architecture is a standard producer, consumer, completion model in
- *		which the driver "produces" receive buffers to the adapter, the
- *		adapter "consumes" the receive buffers by DMAing incoming packet data,
- *		and the driver "completes" the receive buffers by servicing the
- *		incoming packet, then "produces" a new buffer and starts the cycle
- *		again.  Receive buffers can be fragmented in up to 16 fragments
- *		(descriptor	entries).  For simplicity, this driver posts
- *		single-fragment receive buffers of 4608 bytes, then allocates a
- *		sk_buff, copies the data, then reposts the buffer.  To reduce CPU
- *		utilization, a better approach would be to pass up the receive
- *		buffer (no extra copy) then allocate and post a replacement buffer.
- *		This is a performance enhancement that should be looked into at
- *		some point.
- *
- *   Transmit Path -
- *		Like the receive path, the adapter DMA engine supports a 256 entry
- *		transmit descriptor block of which up to 255 entries can be used at
- *		any	given time.  Transmit buffers can be fragmented	in up to 255
- *		fragments (descriptor entries).  This driver always posts one
- *		fragment per transmit packet request.
- *
- *		The fragment contains the entire packet from FC to end of data.
- *		Before posting the buffer to the adapter, the driver sets a three-byte
- *		packet request header (PRH) which is required by the Motorola MAC chip
- *		used on the adapters.  The PRH tells the MAC the type of token to
- *		receive/send, whether or not to generate and append the CRC, whether
- *		synchronous or asynchronous framing is used, etc.  Since the PRH
- *		definition is not necessarily consistent across all FDDI chipsets,
- *		the driver, rather than the common FDDI packet handler routines,
- *		sets these bytes.
- *
- *		To reduce the amount of descriptor fetches needed per transmit request,
- *		the driver takes advantage of the fact that there are at least three
- *		bytes available before the skb->data field on the outgoing transmit
- *		request.  This is guaranteed by having fddi_setup() in net_init.c set
- *		dev->hard_header_len to 24 bytes.  21 bytes accounts for the largest
- *		header in an 802.2 SNAP frame.  The other 3 bytes are the extra "pad"
- *		bytes which we'll use to store the PRH.
- *
- *		There's a subtle advantage to adding these pad bytes to the
- *		hard_header_len, it ensures that the data portion of the packet for
- *		an 802.2 SNAP frame is longword aligned.  Other FDDI driver
- *		implementations may not need the extra padding and can start copying
- *		or DMAing directly from the FC byte which starts at skb->data.  Should
- *		another driver implementation need ADDITIONAL padding, the net_init.c
- *		module should be updated and dev->hard_header_len should be increased.
- *		NOTE: To maintain the alignment on the data portion of the packet,
- *		dev->hard_header_len should always be evenly divisible by 4 and at
- *		least 24 bytes in size.
- *
- * Modification History:
- *		Date		Name	Description
- *		16-Aug-96	LVS		Created.
- *		20-Aug-96	LVS		Updated dfx_probe so that version information
- *							string is only displayed if 1 or more cards are
- *							found.  Changed dfx_rcv_queue_process to copy
- *							3 NULL bytes before FC to ensure that data is
- *							longword aligned in receive buffer.
- *		09-Sep-96	LVS		Updated dfx_ctl_set_multicast_list to enable
- *							LLC group promiscuous mode if multicast list
- *							is too large.  LLC individual/group promiscuous
- *							mode is now disabled if IFF_PROMISC flag not set.
- *							dfx_xmt_queue_pkt no longer checks for NULL skb
- *							on Alan Cox recommendation.  Added node address
- *							override support.
- *		12-Sep-96	LVS		Reset current address to factory address during
- *							device open.  Updated transmit path to post a
- *							single fragment which includes PRH->end of data.
- *		Mar 2000	AC		Did various cleanups for 2.3.x
- *		Jun 2000	jgarzik		PCI and resource alloc cleanups
- *		Jul 2000	tjeerd		Much cleanup and some bug fixes
- *		Sep 2000	tjeerd		Fix leak on unload, cosmetic code cleanup
- *		Feb 2001			Skb allocation fixes
- *		Feb 2001	davej		PCI enable cleanups.
- *		04 Aug 2003	macro		Converted to the DMA API.
- *		14 Aug 2004	macro		Fix device names reported.
- *		14 Jun 2005	macro		Use irqreturn_t.
- *		23 Oct 2006	macro		Big-endian host support.
- *		14 Dec 2006	macro		TURBOchannel support.
- */
-
-/* Include files */
-#include <linux/bitops.h>
-#include <linux/compiler.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/eisa.h>
-#include <linux/errno.h>
-#include <linux/fddidevice.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/tc.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-
-#include "defxx.h"
-
-/* Version information string should be updated prior to each new release!  */
-#define DRV_NAME "defxx"
-#define DRV_VERSION "v1.10"
-#define DRV_RELDATE "2006/12/14"
-
-static char version[] __devinitdata =
-	DRV_NAME ": " DRV_VERSION " " DRV_RELDATE
-	"  Lawrence V. Stefani and others\n";
-
-#define DYNAMIC_BUFFERS 1
-
-#define SKBUFF_RX_COPYBREAK 200
-/*
- * NEW_SKB_SIZE = PI_RCV_DATA_K_SIZE_MAX+128 to allow 128 byte
- * alignment for compatibility with old EISA boards.
- */
-#define NEW_SKB_SIZE (PI_RCV_DATA_K_SIZE_MAX+128)
-
-#ifdef CONFIG_PCI
-#define DFX_BUS_PCI(dev) (dev->bus == &pci_bus_type)
-#else
-#define DFX_BUS_PCI(dev) 0
-#endif
-
-#ifdef CONFIG_EISA
-#define DFX_BUS_EISA(dev) (dev->bus == &eisa_bus_type)
-#else
-#define DFX_BUS_EISA(dev) 0
-#endif
-
-#ifdef CONFIG_TC
-#define DFX_BUS_TC(dev) (dev->bus == &tc_bus_type)
-#else
-#define DFX_BUS_TC(dev) 0
-#endif
-
-#ifdef CONFIG_DEFXX_MMIO
-#define DFX_MMIO 1
-#else
-#define DFX_MMIO 0
-#endif
-
-/* Define module-wide (static) routines */
-
-static void		dfx_bus_init(struct net_device *dev);
-static void		dfx_bus_uninit(struct net_device *dev);
-static void		dfx_bus_config_check(DFX_board_t *bp);
-
-static int		dfx_driver_init(struct net_device *dev,
-					const char *print_name,
-					resource_size_t bar_start);
-static int		dfx_adap_init(DFX_board_t *bp, int get_buffers);
-
-static int		dfx_open(struct net_device *dev);
-static int		dfx_close(struct net_device *dev);
-
-static void		dfx_int_pr_halt_id(DFX_board_t *bp);
-static void		dfx_int_type_0_process(DFX_board_t *bp);
-static void		dfx_int_common(struct net_device *dev);
-static irqreturn_t	dfx_interrupt(int irq, void *dev_id);
-
-static struct		net_device_stats *dfx_ctl_get_stats(struct net_device *dev);
-static void		dfx_ctl_set_multicast_list(struct net_device *dev);
-static int		dfx_ctl_set_mac_address(struct net_device *dev, void *addr);
-static int		dfx_ctl_update_cam(DFX_board_t *bp);
-static int		dfx_ctl_update_filters(DFX_board_t *bp);
-
-static int		dfx_hw_dma_cmd_req(DFX_board_t *bp);
-static int		dfx_hw_port_ctrl_req(DFX_board_t *bp, PI_UINT32	command, PI_UINT32 data_a, PI_UINT32 data_b, PI_UINT32 *host_data);
-static void		dfx_hw_adap_reset(DFX_board_t *bp, PI_UINT32 type);
-static int		dfx_hw_adap_state_rd(DFX_board_t *bp);
-static int		dfx_hw_dma_uninit(DFX_board_t *bp, PI_UINT32 type);
-
-static int		dfx_rcv_init(DFX_board_t *bp, int get_buffers);
-static void		dfx_rcv_queue_process(DFX_board_t *bp);
-static void		dfx_rcv_flush(DFX_board_t *bp);
-
-static netdev_tx_t dfx_xmt_queue_pkt(struct sk_buff *skb,
-				     struct net_device *dev);
-static int		dfx_xmt_done(DFX_board_t *bp);
-static void		dfx_xmt_flush(DFX_board_t *bp);
-
-/* Define module-wide (static) variables */
-
-static struct pci_driver dfx_pci_driver;
-static struct eisa_driver dfx_eisa_driver;
-static struct tc_driver dfx_tc_driver;
-
-
-/*
- * =======================
- * = dfx_port_write_long =
- * = dfx_port_read_long  =
- * =======================
- *
- * Overview:
- *   Routines for reading and writing values from/to adapter
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp		- pointer to board information
- *   offset	- register offset from base I/O address
- *   data	- for dfx_port_write_long, this is a value to write;
- *		  for dfx_port_read_long, this is a pointer to store
- *		  the read value
- *
- * Functional Description:
- *   These routines perform the correct operation to read or write
- *   the adapter register.
- *
- *   EISA port block base addresses are based on the slot number in which the
- *   controller is installed.  For example, if the EISA controller is installed
- *   in slot 4, the port block base address is 0x4000.  If the controller is
- *   installed in slot 2, the port block base address is 0x2000, and so on.
- *   This port block can be used to access PDQ, ESIC, and DEFEA on-board
- *   registers using the register offsets defined in DEFXX.H.
- *
- *   PCI port block base addresses are assigned by the PCI BIOS or system
- *   firmware.  There is one 128 byte port block which can be accessed.  It
- *   allows for I/O mapping of both PDQ and PFI registers using the register
- *   offsets defined in DEFXX.H.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   bp->base is a valid base I/O address for this adapter.
- *   offset is a valid register offset for this adapter.
- *
- * Side Effects:
- *   Rather than produce macros for these functions, these routines
- *   are defined using "inline" to ensure that the compiler will
- *   generate inline code and not waste a procedure call and return.
- *   This provides all the benefits of macros, but with the
- *   advantage of strict data type checking.
- */
-
-static inline void dfx_writel(DFX_board_t *bp, int offset, u32 data)
-{
-	writel(data, bp->base.mem + offset);
-	mb();
-}
-
-static inline void dfx_outl(DFX_board_t *bp, int offset, u32 data)
-{
-	outl(data, bp->base.port + offset);
-}
-
-static void dfx_port_write_long(DFX_board_t *bp, int offset, u32 data)
-{
-	struct device __maybe_unused *bdev = bp->bus_dev;
-	int dfx_bus_tc = DFX_BUS_TC(bdev);
-	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
-
-	if (dfx_use_mmio)
-		dfx_writel(bp, offset, data);
-	else
-		dfx_outl(bp, offset, data);
-}
-
-
-static inline void dfx_readl(DFX_board_t *bp, int offset, u32 *data)
-{
-	mb();
-	*data = readl(bp->base.mem + offset);
-}
-
-static inline void dfx_inl(DFX_board_t *bp, int offset, u32 *data)
-{
-	*data = inl(bp->base.port + offset);
-}
-
-static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data)
-{
-	struct device __maybe_unused *bdev = bp->bus_dev;
-	int dfx_bus_tc = DFX_BUS_TC(bdev);
-	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
-
-	if (dfx_use_mmio)
-		dfx_readl(bp, offset, data);
-	else
-		dfx_inl(bp, offset, data);
-}
-
-
-/*
- * ================
- * = dfx_get_bars =
- * ================
- *
- * Overview:
- *   Retrieves the address range used to access control and status
- *   registers.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bdev	- pointer to device information
- *   bar_start	- pointer to store the start address
- *   bar_len	- pointer to store the length of the area
- *
- * Assumptions:
- *   I am sure there are some.
- *
- * Side Effects:
- *   None
- */
-static void dfx_get_bars(struct device *bdev,
-			 resource_size_t *bar_start, resource_size_t *bar_len)
-{
-	int dfx_bus_pci = DFX_BUS_PCI(bdev);
-	int dfx_bus_eisa = DFX_BUS_EISA(bdev);
-	int dfx_bus_tc = DFX_BUS_TC(bdev);
-	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
-
-	if (dfx_bus_pci) {
-		int num = dfx_use_mmio ? 0 : 1;
-
-		*bar_start = pci_resource_start(to_pci_dev(bdev), num);
-		*bar_len = pci_resource_len(to_pci_dev(bdev), num);
-	}
-	if (dfx_bus_eisa) {
-		unsigned long base_addr = to_eisa_device(bdev)->base_addr;
-		resource_size_t bar;
-
-		if (dfx_use_mmio) {
-			bar = inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_2);
-			bar <<= 8;
-			bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_1);
-			bar <<= 8;
-			bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_0);
-			bar <<= 16;
-			*bar_start = bar;
-			bar = inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_2);
-			bar <<= 8;
-			bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_1);
-			bar <<= 8;
-			bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_0);
-			bar <<= 16;
-			*bar_len = (bar | PI_MEM_ADD_MASK_M) + 1;
-		} else {
-			*bar_start = base_addr;
-			*bar_len = PI_ESIC_K_CSR_IO_LEN;
-		}
-	}
-	if (dfx_bus_tc) {
-		*bar_start = to_tc_dev(bdev)->resource.start +
-			     PI_TC_K_CSR_OFFSET;
-		*bar_len = PI_TC_K_CSR_LEN;
-	}
-}
-
-static const struct net_device_ops dfx_netdev_ops = {
-	.ndo_open		= dfx_open,
-	.ndo_stop		= dfx_close,
-	.ndo_start_xmit		= dfx_xmt_queue_pkt,
-	.ndo_get_stats		= dfx_ctl_get_stats,
-	.ndo_set_multicast_list	= dfx_ctl_set_multicast_list,
-	.ndo_set_mac_address	= dfx_ctl_set_mac_address,
-};
-
-/*
- * ================
- * = dfx_register =
- * ================
- *
- * Overview:
- *   Initializes a supported FDDI controller
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   bdev - pointer to device information
- *
- * Functional Description:
- *
- * Return Codes:
- *   0		 - This device (fddi0, fddi1, etc) configured successfully
- *   -EBUSY      - Failed to get resources, or dfx_driver_init failed.
- *
- * Assumptions:
- *   It compiles so it should work :-( (PCI cards do :-)
- *
- * Side Effects:
- *   Device structures for FDDI adapters (fddi0, fddi1, etc) are
- *   initialized and the board resources are read and stored in
- *   the device structure.
- */
-static int __devinit dfx_register(struct device *bdev)
-{
-	static int version_disp;
-	int dfx_bus_pci = DFX_BUS_PCI(bdev);
-	int dfx_bus_tc = DFX_BUS_TC(bdev);
-	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
-	const char *print_name = dev_name(bdev);
-	struct net_device *dev;
-	DFX_board_t	  *bp;			/* board pointer */
-	resource_size_t bar_start = 0;		/* pointer to port */
-	resource_size_t bar_len = 0;		/* resource length */
-	int alloc_size;				/* total buffer size used */
-	struct resource *region;
-	int err = 0;
-
-	if (!version_disp) {	/* display version info if adapter is found */
-		version_disp = 1;	/* set display flag to TRUE so that */
-		printk(version);	/* we only display this string ONCE */
-	}
-
-	dev = alloc_fddidev(sizeof(*bp));
-	if (!dev) {
-		printk(KERN_ERR "%s: Unable to allocate fddidev, aborting\n",
-		       print_name);
-		return -ENOMEM;
-	}
-
-	/* Enable PCI device. */
-	if (dfx_bus_pci && pci_enable_device(to_pci_dev(bdev))) {
-		printk(KERN_ERR "%s: Cannot enable PCI device, aborting\n",
-		       print_name);
-		goto err_out;
-	}
-
-	SET_NETDEV_DEV(dev, bdev);
-
-	bp = netdev_priv(dev);
-	bp->bus_dev = bdev;
-	dev_set_drvdata(bdev, dev);
-
-	dfx_get_bars(bdev, &bar_start, &bar_len);
-
-	if (dfx_use_mmio)
-		region = request_mem_region(bar_start, bar_len, print_name);
-	else
-		region = request_region(bar_start, bar_len, print_name);
-	if (!region) {
-		printk(KERN_ERR "%s: Cannot reserve I/O resource "
-		       "0x%lx @ 0x%lx, aborting\n",
-		       print_name, (long)bar_len, (long)bar_start);
-		err = -EBUSY;
-		goto err_out_disable;
-	}
-
-	/* Set up I/O base address. */
-	if (dfx_use_mmio) {
-		bp->base.mem = ioremap_nocache(bar_start, bar_len);
-		if (!bp->base.mem) {
-			printk(KERN_ERR "%s: Cannot map MMIO\n", print_name);
-			err = -ENOMEM;
-			goto err_out_region;
-		}
-	} else {
-		bp->base.port = bar_start;
-		dev->base_addr = bar_start;
-	}
-
-	/* Initialize new device structure */
-	dev->netdev_ops			= &dfx_netdev_ops;
-
-	if (dfx_bus_pci)
-		pci_set_master(to_pci_dev(bdev));
-
-	if (dfx_driver_init(dev, print_name, bar_start) != DFX_K_SUCCESS) {
-		err = -ENODEV;
-		goto err_out_unmap;
-	}
-
-	err = register_netdev(dev);
-	if (err)
-		goto err_out_kfree;
-
-	printk("%s: registered as %s\n", print_name, dev->name);
-	return 0;
-
-err_out_kfree:
-	alloc_size = sizeof(PI_DESCR_BLOCK) +
-		     PI_CMD_REQ_K_SIZE_MAX + PI_CMD_RSP_K_SIZE_MAX +
-#ifndef DYNAMIC_BUFFERS
-		     (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX) +
-#endif
-		     sizeof(PI_CONSUMER_BLOCK) +
-		     (PI_ALIGN_K_DESC_BLK - 1);
-	if (bp->kmalloced)
-		dma_free_coherent(bdev, alloc_size,
-				  bp->kmalloced, bp->kmalloced_dma);
-
-err_out_unmap:
-	if (dfx_use_mmio)
-		iounmap(bp->base.mem);
-
-err_out_region:
-	if (dfx_use_mmio)
-		release_mem_region(bar_start, bar_len);
-	else
-		release_region(bar_start, bar_len);
-
-err_out_disable:
-	if (dfx_bus_pci)
-		pci_disable_device(to_pci_dev(bdev));
-
-err_out:
-	free_netdev(dev);
-	return err;
-}
-
-
-/*
- * ================
- * = dfx_bus_init =
- * ================
- *
- * Overview:
- *   Initializes the bus-specific controller logic.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   Determine and save adapter IRQ in device table,
- *   then perform bus-specific logic initialization.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   bp->base has already been set with the proper
- *	 base I/O address for this device.
- *
- * Side Effects:
- *   Interrupts are enabled at the adapter bus-specific logic.
- *   Note:  Interrupts at the DMA engine (PDQ chip) are not
- *   enabled yet.
- */
-
-static void __devinit dfx_bus_init(struct net_device *dev)
-{
-	DFX_board_t *bp = netdev_priv(dev);
-	struct device *bdev = bp->bus_dev;
-	int dfx_bus_pci = DFX_BUS_PCI(bdev);
-	int dfx_bus_eisa = DFX_BUS_EISA(bdev);
-	int dfx_bus_tc = DFX_BUS_TC(bdev);
-	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
-	u8 val;
-
-	DBG_printk("In dfx_bus_init...\n");
-
-	/* Initialize a pointer back to the net_device struct */
-	bp->dev = dev;
-
-	/* Initialize adapter based on bus type */
-
-	if (dfx_bus_tc)
-		dev->irq = to_tc_dev(bdev)->interrupt;
-	if (dfx_bus_eisa) {
-		unsigned long base_addr = to_eisa_device(bdev)->base_addr;
-
-		/* Get the interrupt level from the ESIC chip.  */
-		val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
-		val &= PI_CONFIG_STAT_0_M_IRQ;
-		val >>= PI_CONFIG_STAT_0_V_IRQ;
-
-		switch (val) {
-		case PI_CONFIG_STAT_0_IRQ_K_9:
-			dev->irq = 9;
-			break;
-
-		case PI_CONFIG_STAT_0_IRQ_K_10:
-			dev->irq = 10;
-			break;
-
-		case PI_CONFIG_STAT_0_IRQ_K_11:
-			dev->irq = 11;
-			break;
-
-		case PI_CONFIG_STAT_0_IRQ_K_15:
-			dev->irq = 15;
-			break;
-		}
-
-		/*
-		 * Enable memory decoding (MEMCS0) and/or port decoding
-		 * (IOCS1/IOCS0) as appropriate in Function Control
-		 * Register.  One of the port chip selects seems to be
-		 * used for the Burst Holdoff register, but this bit of
-		 * documentation is missing and as yet it has not been
-		 * determined which of the two.  This is also the reason
-		 * the size of the decoded port range is twice as large
-		 * as one required by the PDQ.
-		 */
-
-		/* Set the decode range of the board.  */
-		val = ((bp->base.port >> 12) << PI_IO_CMP_V_SLOT);
-		outb(base_addr + PI_ESIC_K_IO_ADD_CMP_0_1, val);
-		outb(base_addr + PI_ESIC_K_IO_ADD_CMP_0_0, 0);
-		outb(base_addr + PI_ESIC_K_IO_ADD_CMP_1_1, val);
-		outb(base_addr + PI_ESIC_K_IO_ADD_CMP_1_0, 0);
-		val = PI_ESIC_K_CSR_IO_LEN - 1;
-		outb(base_addr + PI_ESIC_K_IO_ADD_MASK_0_1, (val >> 8) & 0xff);
-		outb(base_addr + PI_ESIC_K_IO_ADD_MASK_0_0, val & 0xff);
-		outb(base_addr + PI_ESIC_K_IO_ADD_MASK_1_1, (val >> 8) & 0xff);
-		outb(base_addr + PI_ESIC_K_IO_ADD_MASK_1_0, val & 0xff);
-
-		/* Enable the decoders.  */
-		val = PI_FUNCTION_CNTRL_M_IOCS1 | PI_FUNCTION_CNTRL_M_IOCS0;
-		if (dfx_use_mmio)
-			val |= PI_FUNCTION_CNTRL_M_MEMCS0;
-		outb(base_addr + PI_ESIC_K_FUNCTION_CNTRL, val);
-
-		/*
-		 * Enable access to the rest of the module
-		 * (including PDQ and packet memory).
-		 */
-		val = PI_SLOT_CNTRL_M_ENB;
-		outb(base_addr + PI_ESIC_K_SLOT_CNTRL, val);
-
-		/*
-		 * Map PDQ registers into memory or port space.  This is
-		 * done with a bit in the Burst Holdoff register.
-		 */
-		val = inb(base_addr + PI_DEFEA_K_BURST_HOLDOFF);
-		if (dfx_use_mmio)
-			val |= PI_BURST_HOLDOFF_V_MEM_MAP;
-		else
-			val &= ~PI_BURST_HOLDOFF_V_MEM_MAP;
-		outb(base_addr + PI_DEFEA_K_BURST_HOLDOFF, val);
-
-		/* Enable interrupts at EISA bus interface chip (ESIC) */
-		val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
-		val |= PI_CONFIG_STAT_0_M_INT_ENB;
-		outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, val);
-	}
-	if (dfx_bus_pci) {
-		struct pci_dev *pdev = to_pci_dev(bdev);
-
-		/* Get the interrupt level from the PCI Configuration Table */
-
-		dev->irq = pdev->irq;
-
-		/* Check Latency Timer and set if less than minimal */
-
-		pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &val);
-		if (val < PFI_K_LAT_TIMER_MIN) {
-			val = PFI_K_LAT_TIMER_DEF;
-			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, val);
-		}
-
-		/* Enable interrupts at PCI bus interface chip (PFI) */
-		val = PFI_MODE_M_PDQ_INT_ENB | PFI_MODE_M_DMA_ENB;
-		dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, val);
-	}
-}
-
-/*
- * ==================
- * = dfx_bus_uninit =
- * ==================
- *
- * Overview:
- *   Uninitializes the bus-specific controller logic.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   Perform bus-specific logic uninitialization.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   bp->base has already been set with the proper
- *	 base I/O address for this device.
- *
- * Side Effects:
- *   Interrupts are disabled at the adapter bus-specific logic.
- */
-
-static void __devexit dfx_bus_uninit(struct net_device *dev)
-{
-	DFX_board_t *bp = netdev_priv(dev);
-	struct device *bdev = bp->bus_dev;
-	int dfx_bus_pci = DFX_BUS_PCI(bdev);
-	int dfx_bus_eisa = DFX_BUS_EISA(bdev);
-	u8 val;
-
-	DBG_printk("In dfx_bus_uninit...\n");
-
-	/* Uninitialize adapter based on bus type */
-
-	if (dfx_bus_eisa) {
-		unsigned long base_addr = to_eisa_device(bdev)->base_addr;
-
-		/* Disable interrupts at EISA bus interface chip (ESIC) */
-		val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
-		val &= ~PI_CONFIG_STAT_0_M_INT_ENB;
-		outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, val);
-	}
-	if (dfx_bus_pci) {
-		/* Disable interrupts at PCI bus interface chip (PFI) */
-		dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, 0);
-	}
-}
-
-
-/*
- * ========================
- * = dfx_bus_config_check =
- * ========================
- *
- * Overview:
- *   Checks the configuration (burst size, full-duplex, etc.)  If any parameters
- *   are illegal, then this routine will set new defaults.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   For Revision 1 FDDI EISA, Revision 2 or later FDDI EISA with rev E or later
- *   PDQ, and all FDDI PCI controllers, all values are legal.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   dfx_adap_init has NOT been called yet so burst size and other items have
- *   not been set.
- *
- * Side Effects:
- *   None
- */
-
-static void __devinit dfx_bus_config_check(DFX_board_t *bp)
-{
-	struct device __maybe_unused *bdev = bp->bus_dev;
-	int dfx_bus_eisa = DFX_BUS_EISA(bdev);
-	int	status;				/* return code from adapter port control call */
-	u32	host_data;			/* LW data returned from port control call */
-
-	DBG_printk("In dfx_bus_config_check...\n");
-
-	/* Configuration check only valid for EISA adapter */
-
-	if (dfx_bus_eisa) {
-		/*
-		 * First check if revision 2 EISA controller.  Rev. 1 cards used
-		 * PDQ revision B, so no workaround needed in this case.  Rev. 3
-		 * cards used PDQ revision E, so no workaround needed in this
-		 * case, either.  Only Rev. 2 cards used either Rev. D or E
-		 * chips, so we must verify the chip revision on Rev. 2 cards.
-		 */
-		if (to_eisa_device(bdev)->id.driver_data == DEFEA_PROD_ID_2) {
-			/*
-			 * Revision 2 FDDI EISA controller found,
-			 * so let's check PDQ revision of adapter.
-			 */
-			status = dfx_hw_port_ctrl_req(bp,
-											PI_PCTRL_M_SUB_CMD,
-											PI_SUB_CMD_K_PDQ_REV_GET,
-											0,
-											&host_data);
-			if ((status != DFX_K_SUCCESS) || (host_data == 2))
-				{
-				/*
-				 * Either we couldn't determine the PDQ revision, or
-				 * we determined that it is at revision D.  In either case,
-				 * we need to implement the workaround.
-				 */
-
-				/* Ensure that the burst size is set to 8 longwords or less */
-
-				switch (bp->burst_size)
-					{
-					case PI_PDATA_B_DMA_BURST_SIZE_32:
-					case PI_PDATA_B_DMA_BURST_SIZE_16:
-						bp->burst_size = PI_PDATA_B_DMA_BURST_SIZE_8;
-						break;
-
-					default:
-						break;
-					}
-
-				/* Ensure that full-duplex mode is not enabled */
-
-				bp->full_duplex_enb = PI_SNMP_K_FALSE;
-				}
-			}
-		}
-	}
-
-
-/*
- * ===================
- * = dfx_driver_init =
- * ===================
- *
- * Overview:
- *   Initializes remaining adapter board structure information
- *   and makes sure adapter is in a safe state prior to dfx_open().
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   dev - pointer to device information
- *   print_name - printable device name
- *
- * Functional Description:
- *   This function allocates additional resources such as the host memory
- *   blocks needed by the adapter (eg. descriptor and consumer blocks).
- *	 Remaining bus initialization steps are also completed.  The adapter
- *   is also reset so that it is in the DMA_UNAVAILABLE state.  The OS
- *   must call dfx_open() to open the adapter and bring it on-line.
- *
- * Return Codes:
- *   DFX_K_SUCCESS	- initialization succeeded
- *   DFX_K_FAILURE	- initialization failed - could not allocate memory
- *						or read adapter MAC address
- *
- * Assumptions:
- *   Memory allocated from pci_alloc_consistent() call is physically
- *   contiguous, locked memory.
- *
- * Side Effects:
- *   Adapter is reset and should be in DMA_UNAVAILABLE state before
- *   returning from this routine.
- */
-
-static int __devinit dfx_driver_init(struct net_device *dev,
-				     const char *print_name,
-				     resource_size_t bar_start)
-{
-	DFX_board_t *bp = netdev_priv(dev);
-	struct device *bdev = bp->bus_dev;
-	int dfx_bus_pci = DFX_BUS_PCI(bdev);
-	int dfx_bus_eisa = DFX_BUS_EISA(bdev);
-	int dfx_bus_tc = DFX_BUS_TC(bdev);
-	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
-	int alloc_size;			/* total buffer size needed */
-	char *top_v, *curr_v;		/* virtual addrs into memory block */
-	dma_addr_t top_p, curr_p;	/* physical addrs into memory block */
-	u32 data;			/* host data register value */
-	__le32 le32;
-	char *board_name = NULL;
-
-	DBG_printk("In dfx_driver_init...\n");
-
-	/* Initialize bus-specific hardware registers */
-
-	dfx_bus_init(dev);
-
-	/*
-	 * Initialize default values for configurable parameters
-	 *
-	 * Note: All of these parameters are ones that a user may
-	 *       want to customize.  It'd be nice to break these
-	 *		 out into Space.c or someplace else that's more
-	 *		 accessible/understandable than this file.
-	 */
-
-	bp->full_duplex_enb		= PI_SNMP_K_FALSE;
-	bp->req_ttrt			= 8 * 12500;		/* 8ms in 80 nanosec units */
-	bp->burst_size			= PI_PDATA_B_DMA_BURST_SIZE_DEF;
-	bp->rcv_bufs_to_post	= RCV_BUFS_DEF;
-
-	/*
-	 * Ensure that HW configuration is OK
-	 *
-	 * Note: Depending on the hardware revision, we may need to modify
-	 *       some of the configurable parameters to workaround hardware
-	 *       limitations.  We'll perform this configuration check AFTER
-	 *       setting the parameters to their default values.
-	 */
-
-	dfx_bus_config_check(bp);
-
-	/* Disable PDQ interrupts first */
-
-	dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
-
-	/* Place adapter in DMA_UNAVAILABLE state by resetting adapter */
-
-	(void) dfx_hw_dma_uninit(bp, PI_PDATA_A_RESET_M_SKIP_ST);
-
-	/*  Read the factory MAC address from the adapter then save it */
-
-	if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_LO, 0,
-				 &data) != DFX_K_SUCCESS) {
-		printk("%s: Could not read adapter factory MAC address!\n",
-		       print_name);
-		return DFX_K_FAILURE;
-	}
-	le32 = cpu_to_le32(data);
-	memcpy(&bp->factory_mac_addr[0], &le32, sizeof(u32));
-
-	if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_HI, 0,
-				 &data) != DFX_K_SUCCESS) {
-		printk("%s: Could not read adapter factory MAC address!\n",
-		       print_name);
-		return DFX_K_FAILURE;
-	}
-	le32 = cpu_to_le32(data);
-	memcpy(&bp->factory_mac_addr[4], &le32, sizeof(u16));
-
-	/*
-	 * Set current address to factory address
-	 *
-	 * Note: Node address override support is handled through
-	 *       dfx_ctl_set_mac_address.
-	 */
-
-	memcpy(dev->dev_addr, bp->factory_mac_addr, FDDI_K_ALEN);
-	if (dfx_bus_tc)
-		board_name = "DEFTA";
-	if (dfx_bus_eisa)
-		board_name = "DEFEA";
-	if (dfx_bus_pci)
-		board_name = "DEFPA";
-	pr_info("%s: %s at %saddr = 0x%llx, IRQ = %d, Hardware addr = %pMF\n",
-		print_name, board_name, dfx_use_mmio ? "" : "I/O ",
-		(long long)bar_start, dev->irq, dev->dev_addr);
-
-	/*
-	 * Get memory for descriptor block, consumer block, and other buffers
-	 * that need to be DMA read or written to by the adapter.
-	 */
-
-	alloc_size = sizeof(PI_DESCR_BLOCK) +
-					PI_CMD_REQ_K_SIZE_MAX +
-					PI_CMD_RSP_K_SIZE_MAX +
-#ifndef DYNAMIC_BUFFERS
-					(bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX) +
-#endif
-					sizeof(PI_CONSUMER_BLOCK) +
-					(PI_ALIGN_K_DESC_BLK - 1);
-	bp->kmalloced = top_v = dma_alloc_coherent(bp->bus_dev, alloc_size,
-						   &bp->kmalloced_dma,
-						   GFP_ATOMIC);
-	if (top_v == NULL) {
-		printk("%s: Could not allocate memory for host buffers "
-		       "and structures!\n", print_name);
-		return DFX_K_FAILURE;
-	}
-	memset(top_v, 0, alloc_size);	/* zero out memory before continuing */
-	top_p = bp->kmalloced_dma;	/* get physical address of buffer */
-
-	/*
-	 *  To guarantee the 8K alignment required for the descriptor block, 8K - 1
-	 *  plus the amount of memory needed was allocated.  The physical address
-	 *	is now 8K aligned.  By carving up the memory in a specific order,
-	 *  we'll guarantee the alignment requirements for all other structures.
-	 *
-	 *  Note: If the assumptions change regarding the non-paged, non-cached,
-	 *		  physically contiguous nature of the memory block or the address
-	 *		  alignments, then we'll need to implement a different algorithm
-	 *		  for allocating the needed memory.
-	 */
-
-	curr_p = ALIGN(top_p, PI_ALIGN_K_DESC_BLK);
-	curr_v = top_v + (curr_p - top_p);
-
-	/* Reserve space for descriptor block */
-
-	bp->descr_block_virt = (PI_DESCR_BLOCK *) curr_v;
-	bp->descr_block_phys = curr_p;
-	curr_v += sizeof(PI_DESCR_BLOCK);
-	curr_p += sizeof(PI_DESCR_BLOCK);
-
-	/* Reserve space for command request buffer */
-
-	bp->cmd_req_virt = (PI_DMA_CMD_REQ *) curr_v;
-	bp->cmd_req_phys = curr_p;
-	curr_v += PI_CMD_REQ_K_SIZE_MAX;
-	curr_p += PI_CMD_REQ_K_SIZE_MAX;
-
-	/* Reserve space for command response buffer */
-
-	bp->cmd_rsp_virt = (PI_DMA_CMD_RSP *) curr_v;
-	bp->cmd_rsp_phys = curr_p;
-	curr_v += PI_CMD_RSP_K_SIZE_MAX;
-	curr_p += PI_CMD_RSP_K_SIZE_MAX;
-
-	/* Reserve space for the LLC host receive queue buffers */
-
-	bp->rcv_block_virt = curr_v;
-	bp->rcv_block_phys = curr_p;
-
-#ifndef DYNAMIC_BUFFERS
-	curr_v += (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX);
-	curr_p += (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX);
-#endif
-
-	/* Reserve space for the consumer block */
-
-	bp->cons_block_virt = (PI_CONSUMER_BLOCK *) curr_v;
-	bp->cons_block_phys = curr_p;
-
-	/* Display virtual and physical addresses if debug driver */
-
-	DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n",
-		   print_name,
-		   (long)bp->descr_block_virt, bp->descr_block_phys);
-	DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n",
-		   print_name, (long)bp->cmd_req_virt, bp->cmd_req_phys);
-	DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n",
-		   print_name, (long)bp->cmd_rsp_virt, bp->cmd_rsp_phys);
-	DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n",
-		   print_name, (long)bp->rcv_block_virt, bp->rcv_block_phys);
-	DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n",
-		   print_name, (long)bp->cons_block_virt, bp->cons_block_phys);
-
-	return DFX_K_SUCCESS;
-}
-
-
-/*
- * =================
- * = dfx_adap_init =
- * =================
- *
- * Overview:
- *   Brings the adapter to the link avail/link unavailable state.
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   bp - pointer to board information
- *   get_buffers - non-zero if buffers to be allocated
- *
- * Functional Description:
- *   Issues the low-level firmware/hardware calls necessary to bring
- *   the adapter up, or to properly reset and restore adapter during
- *   run-time.
- *
- * Return Codes:
- *   DFX_K_SUCCESS - Adapter brought up successfully
- *   DFX_K_FAILURE - Adapter initialization failed
- *
- * Assumptions:
- *   bp->reset_type should be set to a valid reset type value before
- *   calling this routine.
- *
- * Side Effects:
- *   Adapter should be in LINK_AVAILABLE or LINK_UNAVAILABLE state
- *   upon a successful return of this routine.
- */
-
-static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
-	{
-	DBG_printk("In dfx_adap_init...\n");
-
-	/* Disable PDQ interrupts first */
-
-	dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
-
-	/* Place adapter in DMA_UNAVAILABLE state by resetting adapter */
-
-	if (dfx_hw_dma_uninit(bp, bp->reset_type) != DFX_K_SUCCESS)
-		{
-		printk("%s: Could not uninitialize/reset adapter!\n", bp->dev->name);
-		return DFX_K_FAILURE;
-		}
-
-	/*
-	 * When the PDQ is reset, some false Type 0 interrupts may be pending,
-	 * so we'll acknowledge all Type 0 interrupts now before continuing.
-	 */
-
-	dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_0_STATUS, PI_HOST_INT_K_ACK_ALL_TYPE_0);
-
-	/*
-	 * Clear Type 1 and Type 2 registers before going to DMA_AVAILABLE state
-	 *
-	 * Note: We only need to clear host copies of these registers.  The PDQ reset
-	 *       takes care of the on-board register values.
-	 */
-
-	bp->cmd_req_reg.lword	= 0;
-	bp->cmd_rsp_reg.lword	= 0;
-	bp->rcv_xmt_reg.lword	= 0;
-
-	/* Clear consumer block before going to DMA_AVAILABLE state */
-
-	memset(bp->cons_block_virt, 0, sizeof(PI_CONSUMER_BLOCK));
-
-	/* Initialize the DMA Burst Size */
-
-	if (dfx_hw_port_ctrl_req(bp,
-							PI_PCTRL_M_SUB_CMD,
-							PI_SUB_CMD_K_BURST_SIZE_SET,
-							bp->burst_size,
-							NULL) != DFX_K_SUCCESS)
-		{
-		printk("%s: Could not set adapter burst size!\n", bp->dev->name);
-		return DFX_K_FAILURE;
-		}
-
-	/*
-	 * Set base address of Consumer Block
-	 *
-	 * Assumption: 32-bit physical address of consumer block is 64 byte
-	 *			   aligned.  That is, bits 0-5 of the address must be zero.
-	 */
-
-	if (dfx_hw_port_ctrl_req(bp,
-							PI_PCTRL_M_CONS_BLOCK,
-							bp->cons_block_phys,
-							0,
-							NULL) != DFX_K_SUCCESS)
-		{
-		printk("%s: Could not set consumer block address!\n", bp->dev->name);
-		return DFX_K_FAILURE;
-		}
-
-	/*
-	 * Set the base address of Descriptor Block and bring adapter
-	 * to DMA_AVAILABLE state.
-	 *
-	 * Note: We also set the literal and data swapping requirements
-	 *       in this command.
-	 *
-	 * Assumption: 32-bit physical address of descriptor block
-	 *       is 8Kbyte aligned.
-	 */
-	if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_INIT,
-				 (u32)(bp->descr_block_phys |
-				       PI_PDATA_A_INIT_M_BSWAP_INIT),
-				 0, NULL) != DFX_K_SUCCESS) {
-		printk("%s: Could not set descriptor block address!\n",
-		       bp->dev->name);
-		return DFX_K_FAILURE;
-	}
-
-	/* Set transmit flush timeout value */
-
-	bp->cmd_req_virt->cmd_type = PI_CMD_K_CHARS_SET;
-	bp->cmd_req_virt->char_set.item[0].item_code	= PI_ITEM_K_FLUSH_TIME;
-	bp->cmd_req_virt->char_set.item[0].value		= 3;	/* 3 seconds */
-	bp->cmd_req_virt->char_set.item[0].item_index	= 0;
-	bp->cmd_req_virt->char_set.item[1].item_code	= PI_ITEM_K_EOL;
-	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-		{
-		printk("%s: DMA command request failed!\n", bp->dev->name);
-		return DFX_K_FAILURE;
-		}
-
-	/* Set the initial values for eFDXEnable and MACTReq MIB objects */
-
-	bp->cmd_req_virt->cmd_type = PI_CMD_K_SNMP_SET;
-	bp->cmd_req_virt->snmp_set.item[0].item_code	= PI_ITEM_K_FDX_ENB_DIS;
-	bp->cmd_req_virt->snmp_set.item[0].value		= bp->full_duplex_enb;
-	bp->cmd_req_virt->snmp_set.item[0].item_index	= 0;
-	bp->cmd_req_virt->snmp_set.item[1].item_code	= PI_ITEM_K_MAC_T_REQ;
-	bp->cmd_req_virt->snmp_set.item[1].value		= bp->req_ttrt;
-	bp->cmd_req_virt->snmp_set.item[1].item_index	= 0;
-	bp->cmd_req_virt->snmp_set.item[2].item_code	= PI_ITEM_K_EOL;
-	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-		{
-		printk("%s: DMA command request failed!\n", bp->dev->name);
-		return DFX_K_FAILURE;
-		}
-
-	/* Initialize adapter CAM */
-
-	if (dfx_ctl_update_cam(bp) != DFX_K_SUCCESS)
-		{
-		printk("%s: Adapter CAM update failed!\n", bp->dev->name);
-		return DFX_K_FAILURE;
-		}
-
-	/* Initialize adapter filters */
-
-	if (dfx_ctl_update_filters(bp) != DFX_K_SUCCESS)
-		{
-		printk("%s: Adapter filters update failed!\n", bp->dev->name);
-		return DFX_K_FAILURE;
-		}
-
-	/*
-	 * Remove any existing dynamic buffers (i.e. if the adapter is being
-	 * reinitialized)
-	 */
-
-	if (get_buffers)
-		dfx_rcv_flush(bp);
-
-	/* Initialize receive descriptor block and produce buffers */
-
-	if (dfx_rcv_init(bp, get_buffers))
-	        {
-		printk("%s: Receive buffer allocation failed\n", bp->dev->name);
-		if (get_buffers)
-			dfx_rcv_flush(bp);
-		return DFX_K_FAILURE;
-		}
-
-	/* Issue START command and bring adapter to LINK_(UN)AVAILABLE state */
-
-	bp->cmd_req_virt->cmd_type = PI_CMD_K_START;
-	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-		{
-		printk("%s: Start command failed\n", bp->dev->name);
-		if (get_buffers)
-			dfx_rcv_flush(bp);
-		return DFX_K_FAILURE;
-		}
-
-	/* Initialization succeeded, reenable PDQ interrupts */
-
-	dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_ENABLE_DEF_INTS);
-	return DFX_K_SUCCESS;
-	}
-
-
-/*
- * ============
- * = dfx_open =
- * ============
- *
- * Overview:
- *   Opens the adapter
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   This function brings the adapter to an operational state.
- *
- * Return Codes:
- *   0		 - Adapter was successfully opened
- *   -EAGAIN - Could not register IRQ or adapter initialization failed
- *
- * Assumptions:
- *   This routine should only be called for a device that was
- *   initialized successfully.
- *
- * Side Effects:
- *   Adapter should be in LINK_AVAILABLE or LINK_UNAVAILABLE state
- *   if the open is successful.
- */
-
-static int dfx_open(struct net_device *dev)
-{
-	DFX_board_t *bp = netdev_priv(dev);
-	int ret;
-
-	DBG_printk("In dfx_open...\n");
-
-	/* Register IRQ - support shared interrupts by passing device ptr */
-
-	ret = request_irq(dev->irq, dfx_interrupt, IRQF_SHARED, dev->name,
-			  dev);
-	if (ret) {
-		printk(KERN_ERR "%s: Requested IRQ %d is busy\n", dev->name, dev->irq);
-		return ret;
-	}
-
-	/*
-	 * Set current address to factory MAC address
-	 *
-	 * Note: We've already done this step in dfx_driver_init.
-	 *       However, it's possible that a user has set a node
-	 *		 address override, then closed and reopened the
-	 *		 adapter.  Unless we reset the device address field
-	 *		 now, we'll continue to use the existing modified
-	 *		 address.
-	 */
-
-	memcpy(dev->dev_addr, bp->factory_mac_addr, FDDI_K_ALEN);
-
-	/* Clear local unicast/multicast address tables and counts */
-
-	memset(bp->uc_table, 0, sizeof(bp->uc_table));
-	memset(bp->mc_table, 0, sizeof(bp->mc_table));
-	bp->uc_count = 0;
-	bp->mc_count = 0;
-
-	/* Disable promiscuous filter settings */
-
-	bp->ind_group_prom	= PI_FSTATE_K_BLOCK;
-	bp->group_prom		= PI_FSTATE_K_BLOCK;
-
-	spin_lock_init(&bp->lock);
-
-	/* Reset and initialize adapter */
-
-	bp->reset_type = PI_PDATA_A_RESET_M_SKIP_ST;	/* skip self-test */
-	if (dfx_adap_init(bp, 1) != DFX_K_SUCCESS)
-	{
-		printk(KERN_ERR "%s: Adapter open failed!\n", dev->name);
-		free_irq(dev->irq, dev);
-		return -EAGAIN;
-	}
-
-	/* Set device structure info */
-	netif_start_queue(dev);
-	return 0;
-}
-
-
-/*
- * =============
- * = dfx_close =
- * =============
- *
- * Overview:
- *   Closes the device/module.
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   This routine closes the adapter and brings it to a safe state.
- *   The interrupt service routine is deregistered with the OS.
- *   The adapter can be opened again with another call to dfx_open().
- *
- * Return Codes:
- *   Always return 0.
- *
- * Assumptions:
- *   No further requests for this adapter are made after this routine is
- *   called.  dfx_open() can be called to reset and reinitialize the
- *   adapter.
- *
- * Side Effects:
- *   Adapter should be in DMA_UNAVAILABLE state upon completion of this
- *   routine.
- */
-
-static int dfx_close(struct net_device *dev)
-{
-	DFX_board_t *bp = netdev_priv(dev);
-
-	DBG_printk("In dfx_close...\n");
-
-	/* Disable PDQ interrupts first */
-
-	dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
-
-	/* Place adapter in DMA_UNAVAILABLE state by resetting adapter */
-
-	(void) dfx_hw_dma_uninit(bp, PI_PDATA_A_RESET_M_SKIP_ST);
-
-	/*
-	 * Flush any pending transmit buffers
-	 *
-	 * Note: It's important that we flush the transmit buffers
-	 *		 BEFORE we clear our copy of the Type 2 register.
-	 *		 Otherwise, we'll have no idea how many buffers
-	 *		 we need to free.
-	 */
-
-	dfx_xmt_flush(bp);
-
-	/*
-	 * Clear Type 1 and Type 2 registers after adapter reset
-	 *
-	 * Note: Even though we're closing the adapter, it's
-	 *       possible that an interrupt will occur after
-	 *		 dfx_close is called.  Without some assurance to
-	 *		 the contrary we want to make sure that we don't
-	 *		 process receive and transmit LLC frames and update
-	 *		 the Type 2 register with bad information.
-	 */
-
-	bp->cmd_req_reg.lword	= 0;
-	bp->cmd_rsp_reg.lword	= 0;
-	bp->rcv_xmt_reg.lword	= 0;
-
-	/* Clear consumer block for the same reason given above */
-
-	memset(bp->cons_block_virt, 0, sizeof(PI_CONSUMER_BLOCK));
-
-	/* Release all dynamically allocate skb in the receive ring. */
-
-	dfx_rcv_flush(bp);
-
-	/* Clear device structure flags */
-
-	netif_stop_queue(dev);
-
-	/* Deregister (free) IRQ */
-
-	free_irq(dev->irq, dev);
-
-	return 0;
-}
-
-
-/*
- * ======================
- * = dfx_int_pr_halt_id =
- * ======================
- *
- * Overview:
- *   Displays halt id's in string form.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   Determine current halt id and display appropriate string.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   None
- *
- * Side Effects:
- *   None
- */
-
-static void dfx_int_pr_halt_id(DFX_board_t	*bp)
-	{
-	PI_UINT32	port_status;			/* PDQ port status register value */
-	PI_UINT32	halt_id;				/* PDQ port status halt ID */
-
-	/* Read the latest port status */
-
-	dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &port_status);
-
-	/* Display halt state transition information */
-
-	halt_id = (port_status & PI_PSTATUS_M_HALT_ID) >> PI_PSTATUS_V_HALT_ID;
-	switch (halt_id)
-		{
-		case PI_HALT_ID_K_SELFTEST_TIMEOUT:
-			printk("%s: Halt ID: Selftest Timeout\n", bp->dev->name);
-			break;
-
-		case PI_HALT_ID_K_PARITY_ERROR:
-			printk("%s: Halt ID: Host Bus Parity Error\n", bp->dev->name);
-			break;
-
-		case PI_HALT_ID_K_HOST_DIR_HALT:
-			printk("%s: Halt ID: Host-Directed Halt\n", bp->dev->name);
-			break;
-
-		case PI_HALT_ID_K_SW_FAULT:
-			printk("%s: Halt ID: Adapter Software Fault\n", bp->dev->name);
-			break;
-
-		case PI_HALT_ID_K_HW_FAULT:
-			printk("%s: Halt ID: Adapter Hardware Fault\n", bp->dev->name);
-			break;
-
-		case PI_HALT_ID_K_PC_TRACE:
-			printk("%s: Halt ID: FDDI Network PC Trace Path Test\n", bp->dev->name);
-			break;
-
-		case PI_HALT_ID_K_DMA_ERROR:
-			printk("%s: Halt ID: Adapter DMA Error\n", bp->dev->name);
-			break;
-
-		case PI_HALT_ID_K_IMAGE_CRC_ERROR:
-			printk("%s: Halt ID: Firmware Image CRC Error\n", bp->dev->name);
-			break;
-
-		case PI_HALT_ID_K_BUS_EXCEPTION:
-			printk("%s: Halt ID: 68000 Bus Exception\n", bp->dev->name);
-			break;
-
-		default:
-			printk("%s: Halt ID: Unknown (code = %X)\n", bp->dev->name, halt_id);
-			break;
-		}
-	}
-
-
-/*
- * ==========================
- * = dfx_int_type_0_process =
- * ==========================
- *
- * Overview:
- *   Processes Type 0 interrupts.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   Processes all enabled Type 0 interrupts.  If the reason for the interrupt
- *   is a serious fault on the adapter, then an error message is displayed
- *   and the adapter is reset.
- *
- *   One tricky potential timing window is the rapid succession of "link avail"
- *   "link unavail" state change interrupts.  The acknowledgement of the Type 0
- *   interrupt must be done before reading the state from the Port Status
- *   register.  This is true because a state change could occur after reading
- *   the data, but before acknowledging the interrupt.  If this state change
- *   does happen, it would be lost because the driver is using the old state,
- *   and it will never know about the new state because it subsequently
- *   acknowledges the state change interrupt.
- *
- *          INCORRECT                                      CORRECT
- *      read type 0 int reasons                   read type 0 int reasons
- *      read adapter state                        ack type 0 interrupts
- *      ack type 0 interrupts                     read adapter state
- *      ... process interrupt ...                 ... process interrupt ...
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   None
- *
- * Side Effects:
- *   An adapter reset may occur if the adapter has any Type 0 error interrupts
- *   or if the port status indicates that the adapter is halted.  The driver
- *   is responsible for reinitializing the adapter with the current CAM
- *   contents and adapter filter settings.
- */
-
-static void dfx_int_type_0_process(DFX_board_t	*bp)
-
-	{
-	PI_UINT32	type_0_status;		/* Host Interrupt Type 0 register */
-	PI_UINT32	state;				/* current adap state (from port status) */
-
-	/*
-	 * Read host interrupt Type 0 register to determine which Type 0
-	 * interrupts are pending.  Immediately write it back out to clear
-	 * those interrupts.
-	 */
-
-	dfx_port_read_long(bp, PI_PDQ_K_REG_TYPE_0_STATUS, &type_0_status);
-	dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_0_STATUS, type_0_status);
-
-	/* Check for Type 0 error interrupts */
-
-	if (type_0_status & (PI_TYPE_0_STAT_M_NXM |
-							PI_TYPE_0_STAT_M_PM_PAR_ERR |
-							PI_TYPE_0_STAT_M_BUS_PAR_ERR))
-		{
-		/* Check for Non-Existent Memory error */
-
-		if (type_0_status & PI_TYPE_0_STAT_M_NXM)
-			printk("%s: Non-Existent Memory Access Error\n", bp->dev->name);
-
-		/* Check for Packet Memory Parity error */
-
-		if (type_0_status & PI_TYPE_0_STAT_M_PM_PAR_ERR)
-			printk("%s: Packet Memory Parity Error\n", bp->dev->name);
-
-		/* Check for Host Bus Parity error */
-
-		if (type_0_status & PI_TYPE_0_STAT_M_BUS_PAR_ERR)
-			printk("%s: Host Bus Parity Error\n", bp->dev->name);
-
-		/* Reset adapter and bring it back on-line */
-
-		bp->link_available = PI_K_FALSE;	/* link is no longer available */
-		bp->reset_type = 0;					/* rerun on-board diagnostics */
-		printk("%s: Resetting adapter...\n", bp->dev->name);
-		if (dfx_adap_init(bp, 0) != DFX_K_SUCCESS)
-			{
-			printk("%s: Adapter reset failed!  Disabling adapter interrupts.\n", bp->dev->name);
-			dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
-			return;
-			}
-		printk("%s: Adapter reset successful!\n", bp->dev->name);
-		return;
-		}
-
-	/* Check for transmit flush interrupt */
-
-	if (type_0_status & PI_TYPE_0_STAT_M_XMT_FLUSH)
-		{
-		/* Flush any pending xmt's and acknowledge the flush interrupt */
-
-		bp->link_available = PI_K_FALSE;		/* link is no longer available */
-		dfx_xmt_flush(bp);						/* flush any outstanding packets */
-		(void) dfx_hw_port_ctrl_req(bp,
-									PI_PCTRL_M_XMT_DATA_FLUSH_DONE,
-									0,
-									0,
-									NULL);
-		}
-
-	/* Check for adapter state change */
-
-	if (type_0_status & PI_TYPE_0_STAT_M_STATE_CHANGE)
-		{
-		/* Get latest adapter state */
-
-		state = dfx_hw_adap_state_rd(bp);	/* get adapter state */
-		if (state == PI_STATE_K_HALTED)
-			{
-			/*
-			 * Adapter has transitioned to HALTED state, try to reset
-			 * adapter to bring it back on-line.  If reset fails,
-			 * leave the adapter in the broken state.
-			 */
-
-			printk("%s: Controller has transitioned to HALTED state!\n", bp->dev->name);
-			dfx_int_pr_halt_id(bp);			/* display halt id as string */
-
-			/* Reset adapter and bring it back on-line */
-
-			bp->link_available = PI_K_FALSE;	/* link is no longer available */
-			bp->reset_type = 0;					/* rerun on-board diagnostics */
-			printk("%s: Resetting adapter...\n", bp->dev->name);
-			if (dfx_adap_init(bp, 0) != DFX_K_SUCCESS)
-				{
-				printk("%s: Adapter reset failed!  Disabling adapter interrupts.\n", bp->dev->name);
-				dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
-				return;
-				}
-			printk("%s: Adapter reset successful!\n", bp->dev->name);
-			}
-		else if (state == PI_STATE_K_LINK_AVAIL)
-			{
-			bp->link_available = PI_K_TRUE;		/* set link available flag */
-			}
-		}
-	}
-
-
-/*
- * ==================
- * = dfx_int_common =
- * ==================
- *
- * Overview:
- *   Interrupt service routine (ISR)
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   This is the ISR which processes incoming adapter interrupts.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   This routine assumes PDQ interrupts have not been disabled.
- *   When interrupts are disabled at the PDQ, the Port Status register
- *   is automatically cleared.  This routine uses the Port Status
- *   register value to determine whether a Type 0 interrupt occurred,
- *   so it's important that adapter interrupts are not normally
- *   enabled/disabled at the PDQ.
- *
- *   It's vital that this routine is NOT reentered for the
- *   same board and that the OS is not in another section of
- *   code (eg. dfx_xmt_queue_pkt) for the same board on a
- *   different thread.
- *
- * Side Effects:
- *   Pending interrupts are serviced.  Depending on the type of
- *   interrupt, acknowledging and clearing the interrupt at the
- *   PDQ involves writing a register to clear the interrupt bit
- *   or updating completion indices.
- */
-
-static void dfx_int_common(struct net_device *dev)
-{
-	DFX_board_t *bp = netdev_priv(dev);
-	PI_UINT32	port_status;		/* Port Status register */
-
-	/* Process xmt interrupts - frequent case, so always call this routine */
-
-	if(dfx_xmt_done(bp))				/* free consumed xmt packets */
-		netif_wake_queue(dev);
-
-	/* Process rcv interrupts - frequent case, so always call this routine */
-
-	dfx_rcv_queue_process(bp);		/* service received LLC frames */
-
-	/*
-	 * Transmit and receive producer and completion indices are updated on the
-	 * adapter by writing to the Type 2 Producer register.  Since the frequent
-	 * case is that we'll be processing either LLC transmit or receive buffers,
-	 * we'll optimize I/O writes by doing a single register write here.
-	 */
-
-	dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
-
-	/* Read PDQ Port Status register to find out which interrupts need processing */
-
-	dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &port_status);
-
-	/* Process Type 0 interrupts (if any) - infrequent, so only call when needed */
-
-	if (port_status & PI_PSTATUS_M_TYPE_0_PENDING)
-		dfx_int_type_0_process(bp);	/* process Type 0 interrupts */
-	}
-
-
-/*
- * =================
- * = dfx_interrupt =
- * =================
- *
- * Overview:
- *   Interrupt processing routine
- *
- * Returns:
- *   Whether a valid interrupt was seen.
- *
- * Arguments:
- *   irq	- interrupt vector
- *   dev_id	- pointer to device information
- *
- * Functional Description:
- *   This routine calls the interrupt processing routine for this adapter.  It
- *   disables and reenables adapter interrupts, as appropriate.  We can support
- *   shared interrupts since the incoming dev_id pointer provides our device
- *   structure context.
- *
- * Return Codes:
- *   IRQ_HANDLED - an IRQ was handled.
- *   IRQ_NONE    - no IRQ was handled.
- *
- * Assumptions:
- *   The interrupt acknowledgement at the hardware level (eg. ACKing the PIC
- *   on Intel-based systems) is done by the operating system outside this
- *   routine.
- *
- *	 System interrupts are enabled through this call.
- *
- * Side Effects:
- *   Interrupts are disabled, then reenabled at the adapter.
- */
-
-static irqreturn_t dfx_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	DFX_board_t *bp = netdev_priv(dev);
-	struct device *bdev = bp->bus_dev;
-	int dfx_bus_pci = DFX_BUS_PCI(bdev);
-	int dfx_bus_eisa = DFX_BUS_EISA(bdev);
-	int dfx_bus_tc = DFX_BUS_TC(bdev);
-
-	/* Service adapter interrupts */
-
-	if (dfx_bus_pci) {
-		u32 status;
-
-		dfx_port_read_long(bp, PFI_K_REG_STATUS, &status);
-		if (!(status & PFI_STATUS_M_PDQ_INT))
-			return IRQ_NONE;
-
-		spin_lock(&bp->lock);
-
-		/* Disable PDQ-PFI interrupts at PFI */
-		dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL,
-				    PFI_MODE_M_DMA_ENB);
-
-		/* Call interrupt service routine for this adapter */
-		dfx_int_common(dev);
-
-		/* Clear PDQ interrupt status bit and reenable interrupts */
-		dfx_port_write_long(bp, PFI_K_REG_STATUS,
-				    PFI_STATUS_M_PDQ_INT);
-		dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL,
-				    (PFI_MODE_M_PDQ_INT_ENB |
-				     PFI_MODE_M_DMA_ENB));
-
-		spin_unlock(&bp->lock);
-	}
-	if (dfx_bus_eisa) {
-		unsigned long base_addr = to_eisa_device(bdev)->base_addr;
-		u8 status;
-
-		status = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
-		if (!(status & PI_CONFIG_STAT_0_M_PEND))
-			return IRQ_NONE;
-
-		spin_lock(&bp->lock);
-
-		/* Disable interrupts at the ESIC */
-		status &= ~PI_CONFIG_STAT_0_M_INT_ENB;
-		outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, status);
-
-		/* Call interrupt service routine for this adapter */
-		dfx_int_common(dev);
-
-		/* Reenable interrupts at the ESIC */
-		status = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
-		status |= PI_CONFIG_STAT_0_M_INT_ENB;
-		outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, status);
-
-		spin_unlock(&bp->lock);
-	}
-	if (dfx_bus_tc) {
-		u32 status;
-
-		dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &status);
-		if (!(status & (PI_PSTATUS_M_RCV_DATA_PENDING |
-				PI_PSTATUS_M_XMT_DATA_PENDING |
-				PI_PSTATUS_M_SMT_HOST_PENDING |
-				PI_PSTATUS_M_UNSOL_PENDING |
-				PI_PSTATUS_M_CMD_RSP_PENDING |
-				PI_PSTATUS_M_CMD_REQ_PENDING |
-				PI_PSTATUS_M_TYPE_0_PENDING)))
-			return IRQ_NONE;
-
-		spin_lock(&bp->lock);
-
-		/* Call interrupt service routine for this adapter */
-		dfx_int_common(dev);
-
-		spin_unlock(&bp->lock);
-	}
-
-	return IRQ_HANDLED;
-}
-
-
-/*
- * =====================
- * = dfx_ctl_get_stats =
- * =====================
- *
- * Overview:
- *   Get statistics for FDDI adapter
- *
- * Returns:
- *   Pointer to FDDI statistics structure
- *
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   Gets current MIB objects from adapter, then
- *   returns FDDI statistics structure as defined
- *   in if_fddi.h.
- *
- *   Note: Since the FDDI statistics structure is
- *   still new and the device structure doesn't
- *   have an FDDI-specific get statistics handler,
- *   we'll return the FDDI statistics structure as
- *   a pointer to an Ethernet statistics structure.
- *   That way, at least the first part of the statistics
- *   structure can be decoded properly, and it allows
- *   "smart" applications to perform a second cast to
- *   decode the FDDI-specific statistics.
- *
- *   We'll have to pay attention to this routine as the
- *   device structure becomes more mature and LAN media
- *   independent.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   None
- *
- * Side Effects:
- *   None
- */
-
-static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev)
-	{
-	DFX_board_t *bp = netdev_priv(dev);
-
-	/* Fill the bp->stats structure with driver-maintained counters */
-
-	bp->stats.gen.rx_packets = bp->rcv_total_frames;
-	bp->stats.gen.tx_packets = bp->xmt_total_frames;
-	bp->stats.gen.rx_bytes   = bp->rcv_total_bytes;
-	bp->stats.gen.tx_bytes   = bp->xmt_total_bytes;
-	bp->stats.gen.rx_errors  = bp->rcv_crc_errors +
-				   bp->rcv_frame_status_errors +
-				   bp->rcv_length_errors;
-	bp->stats.gen.tx_errors  = bp->xmt_length_errors;
-	bp->stats.gen.rx_dropped = bp->rcv_discards;
-	bp->stats.gen.tx_dropped = bp->xmt_discards;
-	bp->stats.gen.multicast  = bp->rcv_multicast_frames;
-	bp->stats.gen.collisions = 0;		/* always zero (0) for FDDI */
-
-	/* Get FDDI SMT MIB objects */
-
-	bp->cmd_req_virt->cmd_type = PI_CMD_K_SMT_MIB_GET;
-	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-		return (struct net_device_stats *)&bp->stats;
-
-	/* Fill the bp->stats structure with the SMT MIB object values */
-
-	memcpy(bp->stats.smt_station_id, &bp->cmd_rsp_virt->smt_mib_get.smt_station_id, sizeof(bp->cmd_rsp_virt->smt_mib_get.smt_station_id));
-	bp->stats.smt_op_version_id					= bp->cmd_rsp_virt->smt_mib_get.smt_op_version_id;
-	bp->stats.smt_hi_version_id					= bp->cmd_rsp_virt->smt_mib_get.smt_hi_version_id;
-	bp->stats.smt_lo_version_id					= bp->cmd_rsp_virt->smt_mib_get.smt_lo_version_id;
-	memcpy(bp->stats.smt_user_data, &bp->cmd_rsp_virt->smt_mib_get.smt_user_data, sizeof(bp->cmd_rsp_virt->smt_mib_get.smt_user_data));
-	bp->stats.smt_mib_version_id				= bp->cmd_rsp_virt->smt_mib_get.smt_mib_version_id;
-	bp->stats.smt_mac_cts						= bp->cmd_rsp_virt->smt_mib_get.smt_mac_ct;
-	bp->stats.smt_non_master_cts				= bp->cmd_rsp_virt->smt_mib_get.smt_non_master_ct;
-	bp->stats.smt_master_cts					= bp->cmd_rsp_virt->smt_mib_get.smt_master_ct;
-	bp->stats.smt_available_paths				= bp->cmd_rsp_virt->smt_mib_get.smt_available_paths;
-	bp->stats.smt_config_capabilities			= bp->cmd_rsp_virt->smt_mib_get.smt_config_capabilities;
-	bp->stats.smt_config_policy					= bp->cmd_rsp_virt->smt_mib_get.smt_config_policy;
-	bp->stats.smt_connection_policy				= bp->cmd_rsp_virt->smt_mib_get.smt_connection_policy;
-	bp->stats.smt_t_notify						= bp->cmd_rsp_virt->smt_mib_get.smt_t_notify;
-	bp->stats.smt_stat_rpt_policy				= bp->cmd_rsp_virt->smt_mib_get.smt_stat_rpt_policy;
-	bp->stats.smt_trace_max_expiration			= bp->cmd_rsp_virt->smt_mib_get.smt_trace_max_expiration;
-	bp->stats.smt_bypass_present				= bp->cmd_rsp_virt->smt_mib_get.smt_bypass_present;
-	bp->stats.smt_ecm_state						= bp->cmd_rsp_virt->smt_mib_get.smt_ecm_state;
-	bp->stats.smt_cf_state						= bp->cmd_rsp_virt->smt_mib_get.smt_cf_state;
-	bp->stats.smt_remote_disconnect_flag		= bp->cmd_rsp_virt->smt_mib_get.smt_remote_disconnect_flag;
-	bp->stats.smt_station_status				= bp->cmd_rsp_virt->smt_mib_get.smt_station_status;
-	bp->stats.smt_peer_wrap_flag				= bp->cmd_rsp_virt->smt_mib_get.smt_peer_wrap_flag;
-	bp->stats.smt_time_stamp					= bp->cmd_rsp_virt->smt_mib_get.smt_msg_time_stamp.ls;
-	bp->stats.smt_transition_time_stamp			= bp->cmd_rsp_virt->smt_mib_get.smt_transition_time_stamp.ls;
-	bp->stats.mac_frame_status_functions		= bp->cmd_rsp_virt->smt_mib_get.mac_frame_status_functions;
-	bp->stats.mac_t_max_capability				= bp->cmd_rsp_virt->smt_mib_get.mac_t_max_capability;
-	bp->stats.mac_tvx_capability				= bp->cmd_rsp_virt->smt_mib_get.mac_tvx_capability;
-	bp->stats.mac_available_paths				= bp->cmd_rsp_virt->smt_mib_get.mac_available_paths;
-	bp->stats.mac_current_path					= bp->cmd_rsp_virt->smt_mib_get.mac_current_path;
-	memcpy(bp->stats.mac_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_upstream_nbr, FDDI_K_ALEN);
-	memcpy(bp->stats.mac_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_downstream_nbr, FDDI_K_ALEN);
-	memcpy(bp->stats.mac_old_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_upstream_nbr, FDDI_K_ALEN);
-	memcpy(bp->stats.mac_old_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_downstream_nbr, FDDI_K_ALEN);
-	bp->stats.mac_dup_address_test				= bp->cmd_rsp_virt->smt_mib_get.mac_dup_address_test;
-	bp->stats.mac_requested_paths				= bp->cmd_rsp_virt->smt_mib_get.mac_requested_paths;
-	bp->stats.mac_downstream_port_type			= bp->cmd_rsp_virt->smt_mib_get.mac_downstream_port_type;
-	memcpy(bp->stats.mac_smt_address, &bp->cmd_rsp_virt->smt_mib_get.mac_smt_address, FDDI_K_ALEN);
-	bp->stats.mac_t_req							= bp->cmd_rsp_virt->smt_mib_get.mac_t_req;
-	bp->stats.mac_t_neg							= bp->cmd_rsp_virt->smt_mib_get.mac_t_neg;
-	bp->stats.mac_t_max							= bp->cmd_rsp_virt->smt_mib_get.mac_t_max;
-	bp->stats.mac_tvx_value						= bp->cmd_rsp_virt->smt_mib_get.mac_tvx_value;
-	bp->stats.mac_frame_error_threshold			= bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_threshold;
-	bp->stats.mac_frame_error_ratio				= bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_ratio;
-	bp->stats.mac_rmt_state						= bp->cmd_rsp_virt->smt_mib_get.mac_rmt_state;
-	bp->stats.mac_da_flag						= bp->cmd_rsp_virt->smt_mib_get.mac_da_flag;
-	bp->stats.mac_una_da_flag					= bp->cmd_rsp_virt->smt_mib_get.mac_unda_flag;
-	bp->stats.mac_frame_error_flag				= bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_flag;
-	bp->stats.mac_ma_unitdata_available			= bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_available;
-	bp->stats.mac_hardware_present				= bp->cmd_rsp_virt->smt_mib_get.mac_hardware_present;
-	bp->stats.mac_ma_unitdata_enable			= bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_enable;
-	bp->stats.path_tvx_lower_bound				= bp->cmd_rsp_virt->smt_mib_get.path_tvx_lower_bound;
-	bp->stats.path_t_max_lower_bound			= bp->cmd_rsp_virt->smt_mib_get.path_t_max_lower_bound;
-	bp->stats.path_max_t_req					= bp->cmd_rsp_virt->smt_mib_get.path_max_t_req;
-	memcpy(bp->stats.path_configuration, &bp->cmd_rsp_virt->smt_mib_get.path_configuration, sizeof(bp->cmd_rsp_virt->smt_mib_get.path_configuration));
-	bp->stats.port_my_type[0]					= bp->cmd_rsp_virt->smt_mib_get.port_my_type[0];
-	bp->stats.port_my_type[1]					= bp->cmd_rsp_virt->smt_mib_get.port_my_type[1];
-	bp->stats.port_neighbor_type[0]				= bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[0];
-	bp->stats.port_neighbor_type[1]				= bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[1];
-	bp->stats.port_connection_policies[0]		= bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[0];
-	bp->stats.port_connection_policies[1]		= bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[1];
-	bp->stats.port_mac_indicated[0]				= bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[0];
-	bp->stats.port_mac_indicated[1]				= bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[1];
-	bp->stats.port_current_path[0]				= bp->cmd_rsp_virt->smt_mib_get.port_current_path[0];
-	bp->stats.port_current_path[1]				= bp->cmd_rsp_virt->smt_mib_get.port_current_path[1];
-	memcpy(&bp->stats.port_requested_paths[0*3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[0], 3);
-	memcpy(&bp->stats.port_requested_paths[1*3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[1], 3);
-	bp->stats.port_mac_placement[0]				= bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[0];
-	bp->stats.port_mac_placement[1]				= bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[1];
-	bp->stats.port_available_paths[0]			= bp->cmd_rsp_virt->smt_mib_get.port_available_paths[0];
-	bp->stats.port_available_paths[1]			= bp->cmd_rsp_virt->smt_mib_get.port_available_paths[1];
-	bp->stats.port_pmd_class[0]					= bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[0];
-	bp->stats.port_pmd_class[1]					= bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[1];
-	bp->stats.port_connection_capabilities[0]	= bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[0];
-	bp->stats.port_connection_capabilities[1]	= bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[1];
-	bp->stats.port_bs_flag[0]					= bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[0];
-	bp->stats.port_bs_flag[1]					= bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[1];
-	bp->stats.port_ler_estimate[0]				= bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[0];
-	bp->stats.port_ler_estimate[1]				= bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[1];
-	bp->stats.port_ler_cutoff[0]				= bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[0];
-	bp->stats.port_ler_cutoff[1]				= bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[1];
-	bp->stats.port_ler_alarm[0]					= bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[0];
-	bp->stats.port_ler_alarm[1]					= bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[1];
-	bp->stats.port_connect_state[0]				= bp->cmd_rsp_virt->smt_mib_get.port_connect_state[0];
-	bp->stats.port_connect_state[1]				= bp->cmd_rsp_virt->smt_mib_get.port_connect_state[1];
-	bp->stats.port_pcm_state[0]					= bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[0];
-	bp->stats.port_pcm_state[1]					= bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[1];
-	bp->stats.port_pc_withhold[0]				= bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[0];
-	bp->stats.port_pc_withhold[1]				= bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[1];
-	bp->stats.port_ler_flag[0]					= bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[0];
-	bp->stats.port_ler_flag[1]					= bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[1];
-	bp->stats.port_hardware_present[0]			= bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[0];
-	bp->stats.port_hardware_present[1]			= bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[1];
-
-	/* Get FDDI counters */
-
-	bp->cmd_req_virt->cmd_type = PI_CMD_K_CNTRS_GET;
-	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-		return (struct net_device_stats *)&bp->stats;
-
-	/* Fill the bp->stats structure with the FDDI counter values */
-
-	bp->stats.mac_frame_cts				= bp->cmd_rsp_virt->cntrs_get.cntrs.frame_cnt.ls;
-	bp->stats.mac_copied_cts			= bp->cmd_rsp_virt->cntrs_get.cntrs.copied_cnt.ls;
-	bp->stats.mac_transmit_cts			= bp->cmd_rsp_virt->cntrs_get.cntrs.transmit_cnt.ls;
-	bp->stats.mac_error_cts				= bp->cmd_rsp_virt->cntrs_get.cntrs.error_cnt.ls;
-	bp->stats.mac_lost_cts				= bp->cmd_rsp_virt->cntrs_get.cntrs.lost_cnt.ls;
-	bp->stats.port_lct_fail_cts[0]		= bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[0].ls;
-	bp->stats.port_lct_fail_cts[1]		= bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[1].ls;
-	bp->stats.port_lem_reject_cts[0]	= bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[0].ls;
-	bp->stats.port_lem_reject_cts[1]	= bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[1].ls;
-	bp->stats.port_lem_cts[0]			= bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[0].ls;
-	bp->stats.port_lem_cts[1]			= bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[1].ls;
-
-	return (struct net_device_stats *)&bp->stats;
-	}
-
-
-/*
- * ==============================
- * = dfx_ctl_set_multicast_list =
- * ==============================
- *
- * Overview:
- *   Enable/Disable LLC frame promiscuous mode reception
- *   on the adapter and/or update multicast address table.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   This routine follows a fairly simple algorithm for setting the
- *   adapter filters and CAM:
- *
- *		if IFF_PROMISC flag is set
- *			enable LLC individual/group promiscuous mode
- *		else
- *			disable LLC individual/group promiscuous mode
- *			if number of incoming multicast addresses >
- *					(CAM max size - number of unicast addresses in CAM)
- *				enable LLC group promiscuous mode
- *				set driver-maintained multicast address count to zero
- *			else
- *				disable LLC group promiscuous mode
- *				set driver-maintained multicast address count to incoming count
- *			update adapter CAM
- *		update adapter filters
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   Multicast addresses are presented in canonical (LSB) format.
- *
- * Side Effects:
- *   On-board adapter CAM and filters are updated.
- */
-
-static void dfx_ctl_set_multicast_list(struct net_device *dev)
-{
-	DFX_board_t *bp = netdev_priv(dev);
-	int					i;			/* used as index in for loop */
-	struct netdev_hw_addr *ha;
-
-	/* Enable LLC frame promiscuous mode, if necessary */
-
-	if (dev->flags & IFF_PROMISC)
-		bp->ind_group_prom = PI_FSTATE_K_PASS;		/* Enable LLC ind/group prom mode */
-
-	/* Else, update multicast address table */
-
-	else
-		{
-		bp->ind_group_prom = PI_FSTATE_K_BLOCK;		/* Disable LLC ind/group prom mode */
-		/*
-		 * Check whether incoming multicast address count exceeds table size
-		 *
-		 * Note: The adapters utilize an on-board 64 entry CAM for
-		 *       supporting perfect filtering of multicast packets
-		 *		 and bridge functions when adding unicast addresses.
-		 *		 There is no hash function available.  To support
-		 *		 additional multicast addresses, the all multicast
-		 *		 filter (LLC group promiscuous mode) must be enabled.
-		 *
-		 *		 The firmware reserves two CAM entries for SMT-related
-		 *		 multicast addresses, which leaves 62 entries available.
-		 *		 The following code ensures that we're not being asked
-		 *		 to add more than 62 addresses to the CAM.  If we are,
-		 *		 the driver will enable the all multicast filter.
-		 *		 Should the number of multicast addresses drop below
-		 *		 the high water mark, the filter will be disabled and
-		 *		 perfect filtering will be used.
-		 */
-
-		if (netdev_mc_count(dev) > (PI_CMD_ADDR_FILTER_K_SIZE - bp->uc_count))
-			{
-			bp->group_prom	= PI_FSTATE_K_PASS;		/* Enable LLC group prom mode */
-			bp->mc_count	= 0;					/* Don't add mc addrs to CAM */
-			}
-		else
-			{
-			bp->group_prom	= PI_FSTATE_K_BLOCK;	/* Disable LLC group prom mode */
-			bp->mc_count	= netdev_mc_count(dev);		/* Add mc addrs to CAM */
-			}
-
-		/* Copy addresses to multicast address table, then update adapter CAM */
-
-		i = 0;
-		netdev_for_each_mc_addr(ha, dev)
-			memcpy(&bp->mc_table[i++ * FDDI_K_ALEN],
-			       ha->addr, FDDI_K_ALEN);
-
-		if (dfx_ctl_update_cam(bp) != DFX_K_SUCCESS)
-			{
-			DBG_printk("%s: Could not update multicast address table!\n", dev->name);
-			}
-		else
-			{
-			DBG_printk("%s: Multicast address table updated!  Added %d addresses.\n", dev->name, bp->mc_count);
-			}
-		}
-
-	/* Update adapter filters */
-
-	if (dfx_ctl_update_filters(bp) != DFX_K_SUCCESS)
-		{
-		DBG_printk("%s: Could not update adapter filters!\n", dev->name);
-		}
-	else
-		{
-		DBG_printk("%s: Adapter filters updated!\n", dev->name);
-		}
-	}
-
-
-/*
- * ===========================
- * = dfx_ctl_set_mac_address =
- * ===========================
- *
- * Overview:
- *   Add node address override (unicast address) to adapter
- *   CAM and update dev_addr field in device table.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   dev  - pointer to device information
- *   addr - pointer to sockaddr structure containing unicast address to add
- *
- * Functional Description:
- *   The adapter supports node address overrides by adding one or more
- *   unicast addresses to the adapter CAM.  This is similar to adding
- *   multicast addresses.  In this routine we'll update the driver and
- *   device structures with the new address, then update the adapter CAM
- *   to ensure that the adapter will copy and strip frames destined and
- *   sourced by that address.
- *
- * Return Codes:
- *   Always returns zero.
- *
- * Assumptions:
- *   The address pointed to by addr->sa_data is a valid unicast
- *   address and is presented in canonical (LSB) format.
- *
- * Side Effects:
- *   On-board adapter CAM is updated.  On-board adapter filters
- *   may be updated.
- */
-
-static int dfx_ctl_set_mac_address(struct net_device *dev, void *addr)
-	{
-	struct sockaddr	*p_sockaddr = (struct sockaddr *)addr;
-	DFX_board_t *bp = netdev_priv(dev);
-
-	/* Copy unicast address to driver-maintained structs and update count */
-
-	memcpy(dev->dev_addr, p_sockaddr->sa_data, FDDI_K_ALEN);	/* update device struct */
-	memcpy(&bp->uc_table[0], p_sockaddr->sa_data, FDDI_K_ALEN);	/* update driver struct */
-	bp->uc_count = 1;
-
-	/*
-	 * Verify we're not exceeding the CAM size by adding unicast address
-	 *
-	 * Note: It's possible that before entering this routine we've
-	 *       already filled the CAM with 62 multicast addresses.
-	 *		 Since we need to place the node address override into
-	 *		 the CAM, we have to check to see that we're not
-	 *		 exceeding the CAM size.  If we are, we have to enable
-	 *		 the LLC group (multicast) promiscuous mode filter as
-	 *		 in dfx_ctl_set_multicast_list.
-	 */
-
-	if ((bp->uc_count + bp->mc_count) > PI_CMD_ADDR_FILTER_K_SIZE)
-		{
-		bp->group_prom	= PI_FSTATE_K_PASS;		/* Enable LLC group prom mode */
-		bp->mc_count	= 0;					/* Don't add mc addrs to CAM */
-
-		/* Update adapter filters */
-
-		if (dfx_ctl_update_filters(bp) != DFX_K_SUCCESS)
-			{
-			DBG_printk("%s: Could not update adapter filters!\n", dev->name);
-			}
-		else
-			{
-			DBG_printk("%s: Adapter filters updated!\n", dev->name);
-			}
-		}
-
-	/* Update adapter CAM with new unicast address */
-
-	if (dfx_ctl_update_cam(bp) != DFX_K_SUCCESS)
-		{
-		DBG_printk("%s: Could not set new MAC address!\n", dev->name);
-		}
-	else
-		{
-		DBG_printk("%s: Adapter CAM updated with new MAC address\n", dev->name);
-		}
-	return 0;			/* always return zero */
-	}
-
-
-/*
- * ======================
- * = dfx_ctl_update_cam =
- * ======================
- *
- * Overview:
- *   Procedure to update adapter CAM (Content Addressable Memory)
- *   with desired unicast and multicast address entries.
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   Updates adapter CAM with current contents of board structure
- *   unicast and multicast address tables.  Since there are only 62
- *   free entries in CAM, this routine ensures that the command
- *   request buffer is not overrun.
- *
- * Return Codes:
- *   DFX_K_SUCCESS - Request succeeded
- *   DFX_K_FAILURE - Request failed
- *
- * Assumptions:
- *   All addresses being added (unicast and multicast) are in canonical
- *   order.
- *
- * Side Effects:
- *   On-board adapter CAM is updated.
- */
-
-static int dfx_ctl_update_cam(DFX_board_t *bp)
-	{
-	int			i;				/* used as index */
-	PI_LAN_ADDR	*p_addr;		/* pointer to CAM entry */
-
-	/*
-	 * Fill in command request information
-	 *
-	 * Note: Even though both the unicast and multicast address
-	 *       table entries are stored as contiguous 6 byte entries,
-	 *		 the firmware address filter set command expects each
-	 *		 entry to be two longwords (8 bytes total).  We must be
-	 *		 careful to only copy the six bytes of each unicast and
-	 *		 multicast table entry into each command entry.  This
-	 *		 is also why we must first clear the entire command
-	 *		 request buffer.
-	 */
-
-	memset(bp->cmd_req_virt, 0, PI_CMD_REQ_K_SIZE_MAX);	/* first clear buffer */
-	bp->cmd_req_virt->cmd_type = PI_CMD_K_ADDR_FILTER_SET;
-	p_addr = &bp->cmd_req_virt->addr_filter_set.entry[0];
-
-	/* Now add unicast addresses to command request buffer, if any */
-
-	for (i=0; i < (int)bp->uc_count; i++)
-		{
-		if (i < PI_CMD_ADDR_FILTER_K_SIZE)
-			{
-			memcpy(p_addr, &bp->uc_table[i*FDDI_K_ALEN], FDDI_K_ALEN);
-			p_addr++;			/* point to next command entry */
-			}
-		}
-
-	/* Now add multicast addresses to command request buffer, if any */
-
-	for (i=0; i < (int)bp->mc_count; i++)
-		{
-		if ((i + bp->uc_count) < PI_CMD_ADDR_FILTER_K_SIZE)
-			{
-			memcpy(p_addr, &bp->mc_table[i*FDDI_K_ALEN], FDDI_K_ALEN);
-			p_addr++;			/* point to next command entry */
-			}
-		}
-
-	/* Issue command to update adapter CAM, then return */
-
-	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-		return DFX_K_FAILURE;
-	return DFX_K_SUCCESS;
-	}
-
-
-/*
- * ==========================
- * = dfx_ctl_update_filters =
- * ==========================
- *
- * Overview:
- *   Procedure to update adapter filters with desired
- *   filter settings.
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   Enables or disables filter using current filter settings.
- *
- * Return Codes:
- *   DFX_K_SUCCESS - Request succeeded.
- *   DFX_K_FAILURE - Request failed.
- *
- * Assumptions:
- *   We must always pass up packets destined to the broadcast
- *   address (FF-FF-FF-FF-FF-FF), so we'll always keep the
- *   broadcast filter enabled.
- *
- * Side Effects:
- *   On-board adapter filters are updated.
- */
-
-static int dfx_ctl_update_filters(DFX_board_t *bp)
-	{
-	int	i = 0;					/* used as index */
-
-	/* Fill in command request information */
-
-	bp->cmd_req_virt->cmd_type = PI_CMD_K_FILTERS_SET;
-
-	/* Initialize Broadcast filter - * ALWAYS ENABLED * */
-
-	bp->cmd_req_virt->filter_set.item[i].item_code	= PI_ITEM_K_BROADCAST;
-	bp->cmd_req_virt->filter_set.item[i++].value	= PI_FSTATE_K_PASS;
-
-	/* Initialize LLC Individual/Group Promiscuous filter */
-
-	bp->cmd_req_virt->filter_set.item[i].item_code	= PI_ITEM_K_IND_GROUP_PROM;
-	bp->cmd_req_virt->filter_set.item[i++].value	= bp->ind_group_prom;
-
-	/* Initialize LLC Group Promiscuous filter */
-
-	bp->cmd_req_virt->filter_set.item[i].item_code	= PI_ITEM_K_GROUP_PROM;
-	bp->cmd_req_virt->filter_set.item[i++].value	= bp->group_prom;
-
-	/* Terminate the item code list */
-
-	bp->cmd_req_virt->filter_set.item[i].item_code	= PI_ITEM_K_EOL;
-
-	/* Issue command to update adapter filters, then return */
-
-	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-		return DFX_K_FAILURE;
-	return DFX_K_SUCCESS;
-	}
-
-
-/*
- * ======================
- * = dfx_hw_dma_cmd_req =
- * ======================
- *
- * Overview:
- *   Sends PDQ DMA command to adapter firmware
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   The command request and response buffers are posted to the adapter in the manner
- *   described in the PDQ Port Specification:
- *
- *		1. Command Response Buffer is posted to adapter.
- *		2. Command Request Buffer is posted to adapter.
- *		3. Command Request consumer index is polled until it indicates that request
- *         buffer has been DMA'd to adapter.
- *		4. Command Response consumer index is polled until it indicates that response
- *         buffer has been DMA'd from adapter.
- *
- *   This ordering ensures that a response buffer is already available for the firmware
- *   to use once it's done processing the request buffer.
- *
- * Return Codes:
- *   DFX_K_SUCCESS	  - DMA command succeeded
- * 	 DFX_K_OUTSTATE   - Adapter is NOT in proper state
- *   DFX_K_HW_TIMEOUT - DMA command timed out
- *
- * Assumptions:
- *   Command request buffer has already been filled with desired DMA command.
- *
- * Side Effects:
- *   None
- */
-
-static int dfx_hw_dma_cmd_req(DFX_board_t *bp)
-	{
-	int status;			/* adapter status */
-	int timeout_cnt;	/* used in for loops */
-
-	/* Make sure the adapter is in a state that we can issue the DMA command in */
-
-	status = dfx_hw_adap_state_rd(bp);
-	if ((status == PI_STATE_K_RESET)		||
-		(status == PI_STATE_K_HALTED)		||
-		(status == PI_STATE_K_DMA_UNAVAIL)	||
-		(status == PI_STATE_K_UPGRADE))
-		return DFX_K_OUTSTATE;
-
-	/* Put response buffer on the command response queue */
-
-	bp->descr_block_virt->cmd_rsp[bp->cmd_rsp_reg.index.prod].long_0 = (u32) (PI_RCV_DESCR_M_SOP |
-			((PI_CMD_RSP_K_SIZE_MAX / PI_ALIGN_K_CMD_RSP_BUFF) << PI_RCV_DESCR_V_SEG_LEN));
-	bp->descr_block_virt->cmd_rsp[bp->cmd_rsp_reg.index.prod].long_1 = bp->cmd_rsp_phys;
-
-	/* Bump (and wrap) the producer index and write out to register */
-
-	bp->cmd_rsp_reg.index.prod += 1;
-	bp->cmd_rsp_reg.index.prod &= PI_CMD_RSP_K_NUM_ENTRIES-1;
-	dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_RSP_PROD, bp->cmd_rsp_reg.lword);
-
-	/* Put request buffer on the command request queue */
-
-	bp->descr_block_virt->cmd_req[bp->cmd_req_reg.index.prod].long_0 = (u32) (PI_XMT_DESCR_M_SOP |
-			PI_XMT_DESCR_M_EOP | (PI_CMD_REQ_K_SIZE_MAX << PI_XMT_DESCR_V_SEG_LEN));
-	bp->descr_block_virt->cmd_req[bp->cmd_req_reg.index.prod].long_1 = bp->cmd_req_phys;
-
-	/* Bump (and wrap) the producer index and write out to register */
-
-	bp->cmd_req_reg.index.prod += 1;
-	bp->cmd_req_reg.index.prod &= PI_CMD_REQ_K_NUM_ENTRIES-1;
-	dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_REQ_PROD, bp->cmd_req_reg.lword);
-
-	/*
-	 * Here we wait for the command request consumer index to be equal
-	 * to the producer, indicating that the adapter has DMAed the request.
-	 */
-
-	for (timeout_cnt = 20000; timeout_cnt > 0; timeout_cnt--)
-		{
-		if (bp->cmd_req_reg.index.prod == (u8)(bp->cons_block_virt->cmd_req))
-			break;
-		udelay(100);			/* wait for 100 microseconds */
-		}
-	if (timeout_cnt == 0)
-		return DFX_K_HW_TIMEOUT;
-
-	/* Bump (and wrap) the completion index and write out to register */
-
-	bp->cmd_req_reg.index.comp += 1;
-	bp->cmd_req_reg.index.comp &= PI_CMD_REQ_K_NUM_ENTRIES-1;
-	dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_REQ_PROD, bp->cmd_req_reg.lword);
-
-	/*
-	 * Here we wait for the command response consumer index to be equal
-	 * to the producer, indicating that the adapter has DMAed the response.
-	 */
-
-	for (timeout_cnt = 20000; timeout_cnt > 0; timeout_cnt--)
-		{
-		if (bp->cmd_rsp_reg.index.prod == (u8)(bp->cons_block_virt->cmd_rsp))
-			break;
-		udelay(100);			/* wait for 100 microseconds */
-		}
-	if (timeout_cnt == 0)
-		return DFX_K_HW_TIMEOUT;
-
-	/* Bump (and wrap) the completion index and write out to register */
-
-	bp->cmd_rsp_reg.index.comp += 1;
-	bp->cmd_rsp_reg.index.comp &= PI_CMD_RSP_K_NUM_ENTRIES-1;
-	dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_RSP_PROD, bp->cmd_rsp_reg.lword);
-	return DFX_K_SUCCESS;
-	}
-
-
-/*
- * ========================
- * = dfx_hw_port_ctrl_req =
- * ========================
- *
- * Overview:
- *   Sends PDQ port control command to adapter firmware
- *
- * Returns:
- *   Host data register value in host_data if ptr is not NULL
- *
- * Arguments:
- *   bp			- pointer to board information
- *	 command	- port control command
- *	 data_a		- port data A register value
- *	 data_b		- port data B register value
- *	 host_data	- ptr to host data register value
- *
- * Functional Description:
- *   Send generic port control command to adapter by writing
- *   to various PDQ port registers, then polling for completion.
- *
- * Return Codes:
- *   DFX_K_SUCCESS	  - port control command succeeded
- *   DFX_K_HW_TIMEOUT - port control command timed out
- *
- * Assumptions:
- *   None
- *
- * Side Effects:
- *   None
- */
-
-static int dfx_hw_port_ctrl_req(
-	DFX_board_t	*bp,
-	PI_UINT32	command,
-	PI_UINT32	data_a,
-	PI_UINT32	data_b,
-	PI_UINT32	*host_data
-	)
-
-	{
-	PI_UINT32	port_cmd;		/* Port Control command register value */
-	int			timeout_cnt;	/* used in for loops */
-
-	/* Set Command Error bit in command longword */
-
-	port_cmd = (PI_UINT32) (command | PI_PCTRL_M_CMD_ERROR);
-
-	/* Issue port command to the adapter */
-
-	dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_DATA_A, data_a);
-	dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_DATA_B, data_b);
-	dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_CTRL, port_cmd);
-
-	/* Now wait for command to complete */
-
-	if (command == PI_PCTRL_M_BLAST_FLASH)
-		timeout_cnt = 600000;	/* set command timeout count to 60 seconds */
-	else
-		timeout_cnt = 20000;	/* set command timeout count to 2 seconds */
-
-	for (; timeout_cnt > 0; timeout_cnt--)
-		{
-		dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_CTRL, &port_cmd);
-		if (!(port_cmd & PI_PCTRL_M_CMD_ERROR))
-			break;
-		udelay(100);			/* wait for 100 microseconds */
-		}
-	if (timeout_cnt == 0)
-		return DFX_K_HW_TIMEOUT;
-
-	/*
-	 * If the address of host_data is non-zero, assume caller has supplied a
-	 * non NULL pointer, and return the contents of the HOST_DATA register in
-	 * it.
-	 */
-
-	if (host_data != NULL)
-		dfx_port_read_long(bp, PI_PDQ_K_REG_HOST_DATA, host_data);
-	return DFX_K_SUCCESS;
-	}
-
-
-/*
- * =====================
- * = dfx_hw_adap_reset =
- * =====================
- *
- * Overview:
- *   Resets adapter
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp   - pointer to board information
- *   type - type of reset to perform
- *
- * Functional Description:
- *   Issue soft reset to adapter by writing to PDQ Port Reset
- *   register.  Use incoming reset type to tell adapter what
- *   kind of reset operation to perform.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   This routine merely issues a soft reset to the adapter.
- *   It is expected that after this routine returns, the caller
- *   will appropriately poll the Port Status register for the
- *   adapter to enter the proper state.
- *
- * Side Effects:
- *   Internal adapter registers are cleared.
- */
-
-static void dfx_hw_adap_reset(
-	DFX_board_t	*bp,
-	PI_UINT32	type
-	)
-
-	{
-	/* Set Reset type and assert reset */
-
-	dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_DATA_A, type);	/* tell adapter type of reset */
-	dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_RESET, PI_RESET_M_ASSERT_RESET);
-
-	/* Wait for at least 1 Microsecond according to the spec. We wait 20 just to be safe */
-
-	udelay(20);
-
-	/* Deassert reset */
-
-	dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_RESET, 0);
-	}
-
-
-/*
- * ========================
- * = dfx_hw_adap_state_rd =
- * ========================
- *
- * Overview:
- *   Returns current adapter state
- *
- * Returns:
- *   Adapter state per PDQ Port Specification
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   Reads PDQ Port Status register and returns adapter state.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   None
- *
- * Side Effects:
- *   None
- */
-
-static int dfx_hw_adap_state_rd(DFX_board_t *bp)
-	{
-	PI_UINT32 port_status;		/* Port Status register value */
-
-	dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &port_status);
-	return (port_status & PI_PSTATUS_M_STATE) >> PI_PSTATUS_V_STATE;
-	}
-
-
-/*
- * =====================
- * = dfx_hw_dma_uninit =
- * =====================
- *
- * Overview:
- *   Brings adapter to DMA_UNAVAILABLE state
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   bp   - pointer to board information
- *   type - type of reset to perform
- *
- * Functional Description:
- *   Bring adapter to DMA_UNAVAILABLE state by performing the following:
- *		1. Set reset type bit in Port Data A Register then reset adapter.
- *		2. Check that adapter is in DMA_UNAVAILABLE state.
- *
- * Return Codes:
- *   DFX_K_SUCCESS	  - adapter is in DMA_UNAVAILABLE state
- *   DFX_K_HW_TIMEOUT - adapter did not reset properly
- *
- * Assumptions:
- *   None
- *
- * Side Effects:
- *   Internal adapter registers are cleared.
- */
-
-static int dfx_hw_dma_uninit(DFX_board_t *bp, PI_UINT32 type)
-	{
-	int timeout_cnt;	/* used in for loops */
-
-	/* Set reset type bit and reset adapter */
-
-	dfx_hw_adap_reset(bp, type);
-
-	/* Now wait for adapter to enter DMA_UNAVAILABLE state */
-
-	for (timeout_cnt = 100000; timeout_cnt > 0; timeout_cnt--)
-		{
-		if (dfx_hw_adap_state_rd(bp) == PI_STATE_K_DMA_UNAVAIL)
-			break;
-		udelay(100);					/* wait for 100 microseconds */
-		}
-	if (timeout_cnt == 0)
-		return DFX_K_HW_TIMEOUT;
-	return DFX_K_SUCCESS;
-	}
-
-/*
- *	Align an sk_buff to a boundary power of 2
- *
- */
-
-static void my_skb_align(struct sk_buff *skb, int n)
-{
-	unsigned long x = (unsigned long)skb->data;
-	unsigned long v;
-
-	v = ALIGN(x, n);	/* Where we want to be */
-
-	skb_reserve(skb, v - x);
-}
-
-
-/*
- * ================
- * = dfx_rcv_init =
- * ================
- *
- * Overview:
- *   Produces buffers to adapter LLC Host receive descriptor block
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *   get_buffers - non-zero if buffers to be allocated
- *
- * Functional Description:
- *   This routine can be called during dfx_adap_init() or during an adapter
- *	 reset.  It initializes the descriptor block and produces all allocated
- *   LLC Host queue receive buffers.
- *
- * Return Codes:
- *   Return 0 on success or -ENOMEM if buffer allocation failed (when using
- *   dynamic buffer allocation). If the buffer allocation failed, the
- *   already allocated buffers will not be released and the caller should do
- *   this.
- *
- * Assumptions:
- *   The PDQ has been reset and the adapter and driver maintained Type 2
- *   register indices are cleared.
- *
- * Side Effects:
- *   Receive buffers are posted to the adapter LLC queue and the adapter
- *   is notified.
- */
-
-static int dfx_rcv_init(DFX_board_t *bp, int get_buffers)
-	{
-	int	i, j;					/* used in for loop */
-
-	/*
-	 *  Since each receive buffer is a single fragment of same length, initialize
-	 *  first longword in each receive descriptor for entire LLC Host descriptor
-	 *  block.  Also initialize second longword in each receive descriptor with
-	 *  physical address of receive buffer.  We'll always allocate receive
-	 *  buffers in powers of 2 so that we can easily fill the 256 entry descriptor
-	 *  block and produce new receive buffers by simply updating the receive
-	 *  producer index.
-	 *
-	 * 	Assumptions:
-	 *		To support all shipping versions of PDQ, the receive buffer size
-	 *		must be mod 128 in length and the physical address must be 128 byte
-	 *		aligned.  In other words, bits 0-6 of the length and address must
-	 *		be zero for the following descriptor field entries to be correct on
-	 *		all PDQ-based boards.  We guaranteed both requirements during
-	 *		driver initialization when we allocated memory for the receive buffers.
-	 */
-
-	if (get_buffers) {
-#ifdef DYNAMIC_BUFFERS
-	for (i = 0; i < (int)(bp->rcv_bufs_to_post); i++)
-		for (j = 0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post)
-		{
-			struct sk_buff *newskb = __netdev_alloc_skb(bp->dev, NEW_SKB_SIZE, GFP_NOIO);
-			if (!newskb)
-				return -ENOMEM;
-			bp->descr_block_virt->rcv_data[i+j].long_0 = (u32) (PI_RCV_DESCR_M_SOP |
-				((PI_RCV_DATA_K_SIZE_MAX / PI_ALIGN_K_RCV_DATA_BUFF) << PI_RCV_DESCR_V_SEG_LEN));
-			/*
-			 * align to 128 bytes for compatibility with
-			 * the old EISA boards.
-			 */
-
-			my_skb_align(newskb, 128);
-			bp->descr_block_virt->rcv_data[i + j].long_1 =
-				(u32)dma_map_single(bp->bus_dev, newskb->data,
-						    NEW_SKB_SIZE,
-						    DMA_FROM_DEVICE);
-			/*
-			 * p_rcv_buff_va is only used inside the
-			 * kernel so we put the skb pointer here.
-			 */
-			bp->p_rcv_buff_va[i+j] = (char *) newskb;
-		}
-#else
-	for (i=0; i < (int)(bp->rcv_bufs_to_post); i++)
-		for (j=0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post)
-			{
-			bp->descr_block_virt->rcv_data[i+j].long_0 = (u32) (PI_RCV_DESCR_M_SOP |
-				((PI_RCV_DATA_K_SIZE_MAX / PI_ALIGN_K_RCV_DATA_BUFF) << PI_RCV_DESCR_V_SEG_LEN));
-			bp->descr_block_virt->rcv_data[i+j].long_1 = (u32) (bp->rcv_block_phys + (i * PI_RCV_DATA_K_SIZE_MAX));
-			bp->p_rcv_buff_va[i+j] = (char *) (bp->rcv_block_virt + (i * PI_RCV_DATA_K_SIZE_MAX));
-			}
-#endif
-	}
-
-	/* Update receive producer and Type 2 register */
-
-	bp->rcv_xmt_reg.index.rcv_prod = bp->rcv_bufs_to_post;
-	dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
-	return 0;
-	}
-
-
-/*
- * =========================
- * = dfx_rcv_queue_process =
- * =========================
- *
- * Overview:
- *   Process received LLC frames.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   Received LLC frames are processed until there are no more consumed frames.
- *   Once all frames are processed, the receive buffers are returned to the
- *   adapter.  Note that this algorithm fixes the length of time that can be spent
- *   in this routine, because there are a fixed number of receive buffers to
- *   process and buffers are not produced until this routine exits and returns
- *   to the ISR.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   None
- *
- * Side Effects:
- *   None
- */
-
-static void dfx_rcv_queue_process(
-	DFX_board_t *bp
-	)
-
-	{
-	PI_TYPE_2_CONSUMER	*p_type_2_cons;		/* ptr to rcv/xmt consumer block register */
-	char				*p_buff;			/* ptr to start of packet receive buffer (FMC descriptor) */
-	u32					descr, pkt_len;		/* FMC descriptor field and packet length */
-	struct sk_buff		*skb;				/* pointer to a sk_buff to hold incoming packet data */
-
-	/* Service all consumed LLC receive frames */
-
-	p_type_2_cons = (PI_TYPE_2_CONSUMER *)(&bp->cons_block_virt->xmt_rcv_data);
-	while (bp->rcv_xmt_reg.index.rcv_comp != p_type_2_cons->index.rcv_cons)
-		{
-		/* Process any errors */
-
-		int entry;
-
-		entry = bp->rcv_xmt_reg.index.rcv_comp;
-#ifdef DYNAMIC_BUFFERS
-		p_buff = (char *) (((struct sk_buff *)bp->p_rcv_buff_va[entry])->data);
-#else
-		p_buff = (char *) bp->p_rcv_buff_va[entry];
-#endif
-		memcpy(&descr, p_buff + RCV_BUFF_K_DESCR, sizeof(u32));
-
-		if (descr & PI_FMC_DESCR_M_RCC_FLUSH)
-			{
-			if (descr & PI_FMC_DESCR_M_RCC_CRC)
-				bp->rcv_crc_errors++;
-			else
-				bp->rcv_frame_status_errors++;
-			}
-		else
-		{
-			int rx_in_place = 0;
-
-			/* The frame was received without errors - verify packet length */
-
-			pkt_len = (u32)((descr & PI_FMC_DESCR_M_LEN) >> PI_FMC_DESCR_V_LEN);
-			pkt_len -= 4;				/* subtract 4 byte CRC */
-			if (!IN_RANGE(pkt_len, FDDI_K_LLC_ZLEN, FDDI_K_LLC_LEN))
-				bp->rcv_length_errors++;
-			else{
-#ifdef DYNAMIC_BUFFERS
-				if (pkt_len > SKBUFF_RX_COPYBREAK) {
-					struct sk_buff *newskb;
-
-					newskb = dev_alloc_skb(NEW_SKB_SIZE);
-					if (newskb){
-						rx_in_place = 1;
-
-						my_skb_align(newskb, 128);
-						skb = (struct sk_buff *)bp->p_rcv_buff_va[entry];
-						dma_unmap_single(bp->bus_dev,
-							bp->descr_block_virt->rcv_data[entry].long_1,
-							NEW_SKB_SIZE,
-							DMA_FROM_DEVICE);
-						skb_reserve(skb, RCV_BUFF_K_PADDING);
-						bp->p_rcv_buff_va[entry] = (char *)newskb;
-						bp->descr_block_virt->rcv_data[entry].long_1 =
-							(u32)dma_map_single(bp->bus_dev,
-								newskb->data,
-								NEW_SKB_SIZE,
-								DMA_FROM_DEVICE);
-					} else
-						skb = NULL;
-				} else
-#endif
-					skb = dev_alloc_skb(pkt_len+3);	/* alloc new buffer to pass up, add room for PRH */
-				if (skb == NULL)
-					{
-					printk("%s: Could not allocate receive buffer.  Dropping packet.\n", bp->dev->name);
-					bp->rcv_discards++;
-					break;
-					}
-				else {
-#ifndef DYNAMIC_BUFFERS
-					if (! rx_in_place)
-#endif
-					{
-						/* Receive buffer allocated, pass receive packet up */
-
-						skb_copy_to_linear_data(skb,
-							       p_buff + RCV_BUFF_K_PADDING,
-							       pkt_len + 3);
-					}
-
-					skb_reserve(skb,3);		/* adjust data field so that it points to FC byte */
-					skb_put(skb, pkt_len);		/* pass up packet length, NOT including CRC */
-					skb->protocol = fddi_type_trans(skb, bp->dev);
-					bp->rcv_total_bytes += skb->len;
-					netif_rx(skb);
-
-					/* Update the rcv counters */
-					bp->rcv_total_frames++;
-					if (*(p_buff + RCV_BUFF_K_DA) & 0x01)
-						bp->rcv_multicast_frames++;
-				}
-			}
-			}
-
-		/*
-		 * Advance the producer (for recycling) and advance the completion
-		 * (for servicing received frames).  Note that it is okay to
-		 * advance the producer without checking that it passes the
-		 * completion index because they are both advanced at the same
-		 * rate.
-		 */
-
-		bp->rcv_xmt_reg.index.rcv_prod += 1;
-		bp->rcv_xmt_reg.index.rcv_comp += 1;
-		}
-	}
-
-
-/*
- * =====================
- * = dfx_xmt_queue_pkt =
- * =====================
- *
- * Overview:
- *   Queues packets for transmission
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   skb - pointer to sk_buff to queue for transmission
- *   dev - pointer to device information
- *
- * Functional Description:
- *   Here we assume that an incoming skb transmit request
- *   is contained in a single physically contiguous buffer
- *   in which the virtual address of the start of packet
- *   (skb->data) can be converted to a physical address
- *   by using pci_map_single().
- *
- *   Since the adapter architecture requires a three byte
- *   packet request header to prepend the start of packet,
- *   we'll write the three byte field immediately prior to
- *   the FC byte.  This assumption is valid because we've
- *   ensured that dev->hard_header_len includes three pad
- *   bytes.  By posting a single fragment to the adapter,
- *   we'll reduce the number of descriptor fetches and
- *   bus traffic needed to send the request.
- *
- *   Also, we can't free the skb until after it's been DMA'd
- *   out by the adapter, so we'll queue it in the driver and
- *   return it in dfx_xmt_done.
- *
- * Return Codes:
- *   0 - driver queued packet, link is unavailable, or skbuff was bad
- *	 1 - caller should requeue the sk_buff for later transmission
- *
- * Assumptions:
- *	 First and foremost, we assume the incoming skb pointer
- *   is NOT NULL and is pointing to a valid sk_buff structure.
- *
- *   The outgoing packet is complete, starting with the
- *   frame control byte including the last byte of data,
- *   but NOT including the 4 byte CRC.  We'll let the
- *   adapter hardware generate and append the CRC.
- *
- *   The entire packet is stored in one physically
- *   contiguous buffer which is not cached and whose
- *   32-bit physical address can be determined.
- *
- *   It's vital that this routine is NOT reentered for the
- *   same board and that the OS is not in another section of
- *   code (eg. dfx_int_common) for the same board on a
- *   different thread.
- *
- * Side Effects:
- *   None
- */
-
-static netdev_tx_t dfx_xmt_queue_pkt(struct sk_buff *skb,
-				     struct net_device *dev)
-	{
-	DFX_board_t		*bp = netdev_priv(dev);
-	u8			prod;				/* local transmit producer index */
-	PI_XMT_DESCR		*p_xmt_descr;		/* ptr to transmit descriptor block entry */
-	XMT_DRIVER_DESCR	*p_xmt_drv_descr;	/* ptr to transmit driver descriptor */
-	unsigned long		flags;
-
-	netif_stop_queue(dev);
-
-	/*
-	 * Verify that incoming transmit request is OK
-	 *
-	 * Note: The packet size check is consistent with other
-	 *		 Linux device drivers, although the correct packet
-	 *		 size should be verified before calling the
-	 *		 transmit routine.
-	 */
-
-	if (!IN_RANGE(skb->len, FDDI_K_LLC_ZLEN, FDDI_K_LLC_LEN))
-	{
-		printk("%s: Invalid packet length - %u bytes\n",
-			dev->name, skb->len);
-		bp->xmt_length_errors++;		/* bump error counter */
-		netif_wake_queue(dev);
-		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;			/* return "success" */
-	}
-	/*
-	 * See if adapter link is available, if not, free buffer
-	 *
-	 * Note: If the link isn't available, free buffer and return 0
-	 *		 rather than tell the upper layer to requeue the packet.
-	 *		 The methodology here is that by the time the link
-	 *		 becomes available, the packet to be sent will be
-	 *		 fairly stale.  By simply dropping the packet, the
-	 *		 higher layer protocols will eventually time out
-	 *		 waiting for response packets which it won't receive.
-	 */
-
-	if (bp->link_available == PI_K_FALSE)
-		{
-		if (dfx_hw_adap_state_rd(bp) == PI_STATE_K_LINK_AVAIL)	/* is link really available? */
-			bp->link_available = PI_K_TRUE;		/* if so, set flag and continue */
-		else
-			{
-			bp->xmt_discards++;					/* bump error counter */
-			dev_kfree_skb(skb);		/* free sk_buff now */
-			netif_wake_queue(dev);
-			return NETDEV_TX_OK;		/* return "success" */
-			}
-		}
-
-	spin_lock_irqsave(&bp->lock, flags);
-
-	/* Get the current producer and the next free xmt data descriptor */
-
-	prod		= bp->rcv_xmt_reg.index.xmt_prod;
-	p_xmt_descr = &(bp->descr_block_virt->xmt_data[prod]);
-
-	/*
-	 * Get pointer to auxiliary queue entry to contain information
-	 * for this packet.
-	 *
-	 * Note: The current xmt producer index will become the
-	 *	 current xmt completion index when we complete this
-	 *	 packet later on.  So, we'll get the pointer to the
-	 *	 next auxiliary queue entry now before we bump the
-	 *	 producer index.
-	 */
-
-	p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[prod++]);	/* also bump producer index */
-
-	/* Write the three PRH bytes immediately before the FC byte */
-
-	skb_push(skb,3);
-	skb->data[0] = DFX_PRH0_BYTE;	/* these byte values are defined */
-	skb->data[1] = DFX_PRH1_BYTE;	/* in the Motorola FDDI MAC chip */
-	skb->data[2] = DFX_PRH2_BYTE;	/* specification */
-
-	/*
-	 * Write the descriptor with buffer info and bump producer
-	 *
-	 * Note: Since we need to start DMA from the packet request
-	 *		 header, we'll add 3 bytes to the DMA buffer length,
-	 *		 and we'll determine the physical address of the
-	 *		 buffer from the PRH, not skb->data.
-	 *
-	 * Assumptions:
-	 *		 1. Packet starts with the frame control (FC) byte
-	 *		    at skb->data.
-	 *		 2. The 4-byte CRC is not appended to the buffer or
-	 *			included in the length.
-	 *		 3. Packet length (skb->len) is from FC to end of
-	 *			data, inclusive.
-	 *		 4. The packet length does not exceed the maximum
-	 *			FDDI LLC frame length of 4491 bytes.
-	 *		 5. The entire packet is contained in a physically
-	 *			contiguous, non-cached, locked memory space
-	 *			comprised of a single buffer pointed to by
-	 *			skb->data.
-	 *		 6. The physical address of the start of packet
-	 *			can be determined from the virtual address
-	 *			by using pci_map_single() and is only 32-bits
-	 *			wide.
-	 */
-
-	p_xmt_descr->long_0	= (u32) (PI_XMT_DESCR_M_SOP | PI_XMT_DESCR_M_EOP | ((skb->len) << PI_XMT_DESCR_V_SEG_LEN));
-	p_xmt_descr->long_1 = (u32)dma_map_single(bp->bus_dev, skb->data,
-						  skb->len, DMA_TO_DEVICE);
-
-	/*
-	 * Verify that descriptor is actually available
-	 *
-	 * Note: If descriptor isn't available, return 1 which tells
-	 *	 the upper layer to requeue the packet for later
-	 *	 transmission.
-	 *
-	 *       We need to ensure that the producer never reaches the
-	 *	 completion, except to indicate that the queue is empty.
-	 */
-
-	if (prod == bp->rcv_xmt_reg.index.xmt_comp)
-	{
-		skb_pull(skb,3);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		return NETDEV_TX_BUSY;	/* requeue packet for later */
-	}
-
-	/*
-	 * Save info for this packet for xmt done indication routine
-	 *
-	 * Normally, we'd save the producer index in the p_xmt_drv_descr
-	 * structure so that we'd have it handy when we complete this
-	 * packet later (in dfx_xmt_done).  However, since the current
-	 * transmit architecture guarantees a single fragment for the
-	 * entire packet, we can simply bump the completion index by
-	 * one (1) for each completed packet.
-	 *
-	 * Note: If this assumption changes and we're presented with
-	 *	 an inconsistent number of transmit fragments for packet
-	 *	 data, we'll need to modify this code to save the current
-	 *	 transmit producer index.
-	 */
-
-	p_xmt_drv_descr->p_skb = skb;
-
-	/* Update Type 2 register */
-
-	bp->rcv_xmt_reg.index.xmt_prod = prod;
-	dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	netif_wake_queue(dev);
-	return NETDEV_TX_OK;	/* packet queued to adapter */
-	}
-
-
-/*
- * ================
- * = dfx_xmt_done =
- * ================
- *
- * Overview:
- *   Processes all frames that have been transmitted.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   For all consumed transmit descriptors that have not
- *   yet been completed, we'll free the skb we were holding
- *   onto using dev_kfree_skb and bump the appropriate
- *   counters.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   The Type 2 register is not updated in this routine.  It is
- *   assumed that it will be updated in the ISR when dfx_xmt_done
- *   returns.
- *
- * Side Effects:
- *   None
- */
-
-static int dfx_xmt_done(DFX_board_t *bp)
-	{
-	XMT_DRIVER_DESCR	*p_xmt_drv_descr;	/* ptr to transmit driver descriptor */
-	PI_TYPE_2_CONSUMER	*p_type_2_cons;		/* ptr to rcv/xmt consumer block register */
-	u8			comp;			/* local transmit completion index */
-	int 			freed = 0;		/* buffers freed */
-
-	/* Service all consumed transmit frames */
-
-	p_type_2_cons = (PI_TYPE_2_CONSUMER *)(&bp->cons_block_virt->xmt_rcv_data);
-	while (bp->rcv_xmt_reg.index.xmt_comp != p_type_2_cons->index.xmt_cons)
-		{
-		/* Get pointer to the transmit driver descriptor block information */
-
-		p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[bp->rcv_xmt_reg.index.xmt_comp]);
-
-		/* Increment transmit counters */
-
-		bp->xmt_total_frames++;
-		bp->xmt_total_bytes += p_xmt_drv_descr->p_skb->len;
-
-		/* Return skb to operating system */
-		comp = bp->rcv_xmt_reg.index.xmt_comp;
-		dma_unmap_single(bp->bus_dev,
-				 bp->descr_block_virt->xmt_data[comp].long_1,
-				 p_xmt_drv_descr->p_skb->len,
-				 DMA_TO_DEVICE);
-		dev_kfree_skb_irq(p_xmt_drv_descr->p_skb);
-
-		/*
-		 * Move to start of next packet by updating completion index
-		 *
-		 * Here we assume that a transmit packet request is always
-		 * serviced by posting one fragment.  We can therefore
-		 * simplify the completion code by incrementing the
-		 * completion index by one.  This code will need to be
-		 * modified if this assumption changes.  See comments
-		 * in dfx_xmt_queue_pkt for more details.
-		 */
-
-		bp->rcv_xmt_reg.index.xmt_comp += 1;
-		freed++;
-		}
-	return freed;
-	}
-
-
-/*
- * =================
- * = dfx_rcv_flush =
- * =================
- *
- * Overview:
- *   Remove all skb's in the receive ring.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   Free's all the dynamically allocated skb's that are
- *   currently attached to the device receive ring. This
- *   function is typically only used when the device is
- *   initialized or reinitialized.
- *
- * Return Codes:
- *   None
- *
- * Side Effects:
- *   None
- */
-#ifdef DYNAMIC_BUFFERS
-static void dfx_rcv_flush( DFX_board_t *bp )
-	{
-	int i, j;
-
-	for (i = 0; i < (int)(bp->rcv_bufs_to_post); i++)
-		for (j = 0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post)
-		{
-			struct sk_buff *skb;
-			skb = (struct sk_buff *)bp->p_rcv_buff_va[i+j];
-			if (skb)
-				dev_kfree_skb(skb);
-			bp->p_rcv_buff_va[i+j] = NULL;
-		}
-
-	}
-#else
-static inline void dfx_rcv_flush( DFX_board_t *bp )
-{
-}
-#endif /* DYNAMIC_BUFFERS */
-
-/*
- * =================
- * = dfx_xmt_flush =
- * =================
- *
- * Overview:
- *   Processes all frames whether they've been transmitted
- *   or not.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   For all produced transmit descriptors that have not
- *   yet been completed, we'll free the skb we were holding
- *   onto using dev_kfree_skb and bump the appropriate
- *   counters.  Of course, it's possible that some of
- *   these transmit requests actually did go out, but we
- *   won't make that distinction here.  Finally, we'll
- *   update the consumer index to match the producer.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   This routine does NOT update the Type 2 register.  It
- *   is assumed that this routine is being called during a
- *   transmit flush interrupt, or a shutdown or close routine.
- *
- * Side Effects:
- *   None
- */
-
-static void dfx_xmt_flush( DFX_board_t *bp )
-	{
-	u32			prod_cons;		/* rcv/xmt consumer block longword */
-	XMT_DRIVER_DESCR	*p_xmt_drv_descr;	/* ptr to transmit driver descriptor */
-	u8			comp;			/* local transmit completion index */
-
-	/* Flush all outstanding transmit frames */
-
-	while (bp->rcv_xmt_reg.index.xmt_comp != bp->rcv_xmt_reg.index.xmt_prod)
-		{
-		/* Get pointer to the transmit driver descriptor block information */
-
-		p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[bp->rcv_xmt_reg.index.xmt_comp]);
-
-		/* Return skb to operating system */
-		comp = bp->rcv_xmt_reg.index.xmt_comp;
-		dma_unmap_single(bp->bus_dev,
-				 bp->descr_block_virt->xmt_data[comp].long_1,
-				 p_xmt_drv_descr->p_skb->len,
-				 DMA_TO_DEVICE);
-		dev_kfree_skb(p_xmt_drv_descr->p_skb);
-
-		/* Increment transmit error counter */
-
-		bp->xmt_discards++;
-
-		/*
-		 * Move to start of next packet by updating completion index
-		 *
-		 * Here we assume that a transmit packet request is always
-		 * serviced by posting one fragment.  We can therefore
-		 * simplify the completion code by incrementing the
-		 * completion index by one.  This code will need to be
-		 * modified if this assumption changes.  See comments
-		 * in dfx_xmt_queue_pkt for more details.
-		 */
-
-		bp->rcv_xmt_reg.index.xmt_comp += 1;
-		}
-
-	/* Update the transmit consumer index in the consumer block */
-
-	prod_cons = (u32)(bp->cons_block_virt->xmt_rcv_data & ~PI_CONS_M_XMT_INDEX);
-	prod_cons |= (u32)(bp->rcv_xmt_reg.index.xmt_prod << PI_CONS_V_XMT_INDEX);
-	bp->cons_block_virt->xmt_rcv_data = prod_cons;
-	}
-
-/*
- * ==================
- * = dfx_unregister =
- * ==================
- *
- * Overview:
- *   Shuts down an FDDI controller
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   bdev - pointer to device information
- *
- * Functional Description:
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   It compiles so it should work :-( (PCI cards do :-)
- *
- * Side Effects:
- *   Device structures for FDDI adapters (fddi0, fddi1, etc) are
- *   freed.
- */
-static void __devexit dfx_unregister(struct device *bdev)
-{
-	struct net_device *dev = dev_get_drvdata(bdev);
-	DFX_board_t *bp = netdev_priv(dev);
-	int dfx_bus_pci = DFX_BUS_PCI(bdev);
-	int dfx_bus_tc = DFX_BUS_TC(bdev);
-	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
-	resource_size_t bar_start = 0;		/* pointer to port */
-	resource_size_t bar_len = 0;		/* resource length */
-	int		alloc_size;		/* total buffer size used */
-
-	unregister_netdev(dev);
-
-	alloc_size = sizeof(PI_DESCR_BLOCK) +
-		     PI_CMD_REQ_K_SIZE_MAX + PI_CMD_RSP_K_SIZE_MAX +
-#ifndef DYNAMIC_BUFFERS
-		     (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX) +
-#endif
-		     sizeof(PI_CONSUMER_BLOCK) +
-		     (PI_ALIGN_K_DESC_BLK - 1);
-	if (bp->kmalloced)
-		dma_free_coherent(bdev, alloc_size,
-				  bp->kmalloced, bp->kmalloced_dma);
-
-	dfx_bus_uninit(dev);
-
-	dfx_get_bars(bdev, &bar_start, &bar_len);
-	if (dfx_use_mmio) {
-		iounmap(bp->base.mem);
-		release_mem_region(bar_start, bar_len);
-	} else
-		release_region(bar_start, bar_len);
-
-	if (dfx_bus_pci)
-		pci_disable_device(to_pci_dev(bdev));
-
-	free_netdev(dev);
-}
-
-
-static int __devinit __maybe_unused dfx_dev_register(struct device *);
-static int __devexit __maybe_unused dfx_dev_unregister(struct device *);
-
-#ifdef CONFIG_PCI
-static int __devinit dfx_pci_register(struct pci_dev *,
-				      const struct pci_device_id *);
-static void __devexit dfx_pci_unregister(struct pci_dev *);
-
-static DEFINE_PCI_DEVICE_TABLE(dfx_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI) },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, dfx_pci_table);
-
-static struct pci_driver dfx_pci_driver = {
-	.name		= "defxx",
-	.id_table	= dfx_pci_table,
-	.probe		= dfx_pci_register,
-	.remove		= __devexit_p(dfx_pci_unregister),
-};
-
-static __devinit int dfx_pci_register(struct pci_dev *pdev,
-				      const struct pci_device_id *ent)
-{
-	return dfx_register(&pdev->dev);
-}
-
-static void __devexit dfx_pci_unregister(struct pci_dev *pdev)
-{
-	dfx_unregister(&pdev->dev);
-}
-#endif /* CONFIG_PCI */
-
-#ifdef CONFIG_EISA
-static struct eisa_device_id dfx_eisa_table[] = {
-        { "DEC3001", DEFEA_PROD_ID_1 },
-        { "DEC3002", DEFEA_PROD_ID_2 },
-        { "DEC3003", DEFEA_PROD_ID_3 },
-        { "DEC3004", DEFEA_PROD_ID_4 },
-        { }
-};
-MODULE_DEVICE_TABLE(eisa, dfx_eisa_table);
-
-static struct eisa_driver dfx_eisa_driver = {
-	.id_table	= dfx_eisa_table,
-	.driver		= {
-		.name	= "defxx",
-		.bus	= &eisa_bus_type,
-		.probe	= dfx_dev_register,
-		.remove	= __devexit_p(dfx_dev_unregister),
-	},
-};
-#endif /* CONFIG_EISA */
-
-#ifdef CONFIG_TC
-static struct tc_device_id const dfx_tc_table[] = {
-	{ "DEC     ", "PMAF-FA " },
-	{ "DEC     ", "PMAF-FD " },
-	{ "DEC     ", "PMAF-FS " },
-	{ "DEC     ", "PMAF-FU " },
-	{ }
-};
-MODULE_DEVICE_TABLE(tc, dfx_tc_table);
-
-static struct tc_driver dfx_tc_driver = {
-	.id_table	= dfx_tc_table,
-	.driver		= {
-		.name	= "defxx",
-		.bus	= &tc_bus_type,
-		.probe	= dfx_dev_register,
-		.remove	= __devexit_p(dfx_dev_unregister),
-	},
-};
-#endif /* CONFIG_TC */
-
-static int __devinit __maybe_unused dfx_dev_register(struct device *dev)
-{
-	int status;
-
-	status = dfx_register(dev);
-	if (!status)
-		get_device(dev);
-	return status;
-}
-
-static int __devexit __maybe_unused dfx_dev_unregister(struct device *dev)
-{
-	put_device(dev);
-	dfx_unregister(dev);
-	return 0;
-}
-
-
-static int __devinit dfx_init(void)
-{
-	int status;
-
-	status = pci_register_driver(&dfx_pci_driver);
-	if (!status)
-		status = eisa_driver_register(&dfx_eisa_driver);
-	if (!status)
-		status = tc_register_driver(&dfx_tc_driver);
-	return status;
-}
-
-static void __devexit dfx_cleanup(void)
-{
-	tc_unregister_driver(&dfx_tc_driver);
-	eisa_driver_unregister(&dfx_eisa_driver);
-	pci_unregister_driver(&dfx_pci_driver);
-}
-
-module_init(dfx_init);
-module_exit(dfx_cleanup);
-MODULE_AUTHOR("Lawrence V. Stefani");
-MODULE_DESCRIPTION("DEC FDDIcontroller TC/EISA/PCI (DEFTA/DEFEA/DEFPA) driver "
-		   DRV_VERSION " " DRV_RELDATE);
-MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/defxx.h linux-libre-3.2-gnu/drivers/net/defxx.h
--- linux-libre-3.1-gnu/drivers/net/defxx.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/defxx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1801 +0,0 @@
-/*
- * File Name:
- *   defxx.h
- *
- * Copyright Information:
- *   Copyright Digital Equipment Corporation 1996.
- *
- *   This software may be used and distributed according to the terms of
- *   the GNU General Public License, incorporated herein by reference.
- *
- * Abstract:
- *   Contains all definitions specified by port specification and required
- *   by the defxx.c driver.
- *
- * The original author:
- *   LVS	Lawrence V. Stefani <lstefani@yahoo.com>
- *
- * Maintainers:
- *   macro	Maciej W. Rozycki <macro@linux-mips.org>
- *
- * Modification History:
- *		Date		Name	Description
- *		16-Aug-96	LVS		Created.
- *		09-Sep-96	LVS		Added group_prom field.  Moved read/write I/O
- *							macros to DEFXX.C.
- *		12-Sep-96	LVS		Removed packet request header pointers.
- *		04 Aug 2003	macro		Converted to the DMA API.
- *		23 Oct 2006	macro		Big-endian host support.
- *		14 Dec 2006	macro		TURBOchannel support.
- */
-
-#ifndef _DEFXX_H_
-#define _DEFXX_H_
-
-/* Define basic types for unsigned chars, shorts, longs */
-
-typedef u8	PI_UINT8;
-typedef u16	PI_UINT16;
-typedef u32	PI_UINT32;
-
-/* Define general structures */
-
-typedef struct							/* 64-bit counter */
-	{
-	PI_UINT32  ms;
-	PI_UINT32  ls;
-	} PI_CNTR;
-
-typedef struct							/* LAN address */
-	{
-	PI_UINT32  lwrd_0;
-	PI_UINT32  lwrd_1;
-	} PI_LAN_ADDR;
-
-typedef struct							/* Station ID address */
-	{
-	PI_UINT32  octet_7_4;
-	PI_UINT32  octet_3_0;
-	} PI_STATION_ID;
-
-
-/* Define general constants */
-
-#define PI_ALIGN_K_DESC_BLK	  			8192	/* Descriptor block boundary		*/
-#define PI_ALIGN_K_CONS_BLK	  	 		64		/* Consumer block boundary		  	*/
-#define PI_ALIGN_K_CMD_REQ_BUFF  		128	 	/* Xmt Command que buffer alignment */
-#define PI_ALIGN_K_CMD_RSP_BUFF	 		128	 	/* Rcv Command que buffer alignment */
-#define PI_ALIGN_K_UNSOL_BUFF	 		128	 	/* Unsol que buffer alignment	   	*/
-#define PI_ALIGN_K_XMT_DATA_BUFF 		0	   	/* Xmt data que buffer alignment	*/
-#define PI_ALIGN_K_RCV_DATA_BUFF 		128	 	/* Rcv que buffer alignment			*/
-
-/* Define PHY index values */
-
-#define PI_PHY_K_S						0		/* Index to S phy */
-#define PI_PHY_K_A						0		/* Index to A phy */
-#define PI_PHY_K_B						1		/* Index to B phy */
-#define PI_PHY_K_MAX					2		/* Max number of phys */
-
-/* Define FMC descriptor fields */
-
-#define PI_FMC_DESCR_V_SOP				31
-#define PI_FMC_DESCR_V_EOP				30
-#define PI_FMC_DESCR_V_FSC				27
-#define PI_FMC_DESCR_V_FSB_ERROR		26
-#define PI_FMC_DESCR_V_FSB_ADDR_RECOG	25
-#define PI_FMC_DESCR_V_FSB_ADDR_COPIED	24
-#define PI_FMC_DESCR_V_FSB				22
-#define PI_FMC_DESCR_V_RCC_FLUSH		21
-#define PI_FMC_DESCR_V_RCC_CRC			20
-#define PI_FMC_DESCR_V_RCC_RRR			17
-#define PI_FMC_DESCR_V_RCC_DD			15
-#define PI_FMC_DESCR_V_RCC_SS			13
-#define PI_FMC_DESCR_V_RCC				13
-#define PI_FMC_DESCR_V_LEN				0
-
-#define PI_FMC_DESCR_M_SOP				0x80000000
-#define PI_FMC_DESCR_M_EOP				0x40000000
-#define PI_FMC_DESCR_M_FSC				0x38000000
-#define PI_FMC_DESCR_M_FSB_ERROR		0x04000000
-#define PI_FMC_DESCR_M_FSB_ADDR_RECOG	0x02000000
-#define PI_FMC_DESCR_M_FSB_ADDR_COPIED	0x01000000
-#define PI_FMC_DESCR_M_FSB				0x07C00000
-#define PI_FMC_DESCR_M_RCC_FLUSH		0x00200000
-#define PI_FMC_DESCR_M_RCC_CRC			0x00100000
-#define PI_FMC_DESCR_M_RCC_RRR			0x000E0000
-#define PI_FMC_DESCR_M_RCC_DD			0x00018000
-#define PI_FMC_DESCR_M_RCC_SS			0x00006000
-#define PI_FMC_DESCR_M_RCC				0x003FE000
-#define PI_FMC_DESCR_M_LEN				0x00001FFF
-
-#define PI_FMC_DESCR_K_RCC_FMC_INT_ERR	0x01AA
-
-#define PI_FMC_DESCR_K_RRR_SUCCESS		0x00
-#define PI_FMC_DESCR_K_RRR_SA_MATCH		0x01
-#define PI_FMC_DESCR_K_RRR_DA_MATCH		0x02
-#define PI_FMC_DESCR_K_RRR_FMC_ABORT	0x03
-#define PI_FMC_DESCR_K_RRR_LENGTH_BAD	0x04
-#define PI_FMC_DESCR_K_RRR_FRAGMENT		0x05
-#define PI_FMC_DESCR_K_RRR_FORMAT_ERR	0x06
-#define PI_FMC_DESCR_K_RRR_MAC_RESET	0x07
-
-#define PI_FMC_DESCR_K_DD_NO_MATCH		0x0
-#define PI_FMC_DESCR_K_DD_PROMISCUOUS	0x1
-#define PI_FMC_DESCR_K_DD_CAM_MATCH		0x2
-#define PI_FMC_DESCR_K_DD_LOCAL_MATCH	0x3
-
-#define PI_FMC_DESCR_K_SS_NO_MATCH		0x0
-#define PI_FMC_DESCR_K_SS_BRIDGE_MATCH	0x1
-#define PI_FMC_DESCR_K_SS_NOT_POSSIBLE	0x2
-#define PI_FMC_DESCR_K_SS_LOCAL_MATCH	0x3
-
-/* Define some max buffer sizes */
-
-#define PI_CMD_REQ_K_SIZE_MAX			512
-#define PI_CMD_RSP_K_SIZE_MAX			512
-#define PI_UNSOL_K_SIZE_MAX				512
-#define PI_SMT_HOST_K_SIZE_MAX			4608		/* 4 1/2 K */
-#define PI_RCV_DATA_K_SIZE_MAX			4608		/* 4 1/2 K */
-#define PI_XMT_DATA_K_SIZE_MAX			4608		/* 4 1/2 K */
-
-/* Define adapter states */
-
-#define PI_STATE_K_RESET				0
-#define PI_STATE_K_UPGRADE		  		1
-#define PI_STATE_K_DMA_UNAVAIL			2
-#define PI_STATE_K_DMA_AVAIL			3
-#define PI_STATE_K_LINK_AVAIL			4
-#define PI_STATE_K_LINK_UNAVAIL	 		5
-#define PI_STATE_K_HALTED		   		6
-#define PI_STATE_K_RING_MEMBER			7
-#define PI_STATE_K_NUMBER				8
-
-/* Define codes for command type */
-
-#define PI_CMD_K_START					0x00
-#define PI_CMD_K_FILTERS_SET			0x01
-#define PI_CMD_K_FILTERS_GET			0x02
-#define PI_CMD_K_CHARS_SET				0x03
-#define PI_CMD_K_STATUS_CHARS_GET		0x04
-#define PI_CMD_K_CNTRS_GET				0x05
-#define PI_CMD_K_CNTRS_SET				0x06
-#define PI_CMD_K_ADDR_FILTER_SET		0x07
-#define PI_CMD_K_ADDR_FILTER_GET		0x08
-#define PI_CMD_K_ERROR_LOG_CLEAR		0x09
-#define PI_CMD_K_ERROR_LOG_GET			0x0A
-#define PI_CMD_K_FDDI_MIB_GET			0x0B
-#define PI_CMD_K_DEC_EXT_MIB_GET		0x0C
-#define PI_CMD_K_DEVICE_SPECIFIC_GET	0x0D
-#define PI_CMD_K_SNMP_SET				0x0E
-#define PI_CMD_K_UNSOL_TEST				0x0F
-#define PI_CMD_K_SMT_MIB_GET			0x10
-#define PI_CMD_K_SMT_MIB_SET			0x11
-#define PI_CMD_K_MAX					0x11	/* Must match last */
-
-/* Define item codes for Chars_Set and Filters_Set commands */
-
-#define PI_ITEM_K_EOL					0x00 	/* End-of-Item list 		  */
-#define PI_ITEM_K_T_REQ					0x01 	/* DECnet T_REQ 			  */
-#define PI_ITEM_K_TVX					0x02 	/* DECnet TVX 				  */
-#define PI_ITEM_K_RESTRICTED_TOKEN		0x03 	/* DECnet Restricted Token 	  */
-#define PI_ITEM_K_LEM_THRESHOLD			0x04 	/* DECnet LEM Threshold 	  */
-#define PI_ITEM_K_RING_PURGER			0x05 	/* DECnet Ring Purger Enable  */
-#define PI_ITEM_K_CNTR_INTERVAL			0x06 	/* Chars_Set 				  */
-#define PI_ITEM_K_IND_GROUP_PROM		0x07 	/* Filters_Set 				  */
-#define PI_ITEM_K_GROUP_PROM			0x08 	/* Filters_Set 				  */
-#define PI_ITEM_K_BROADCAST				0x09 	/* Filters_Set 				  */
-#define PI_ITEM_K_SMT_PROM				0x0A 	/* Filters_Set				  */
-#define PI_ITEM_K_SMT_USER				0x0B 	/* Filters_Set 				  */
-#define PI_ITEM_K_RESERVED				0x0C 	/* Filters_Set 				  */
-#define PI_ITEM_K_IMPLEMENTOR			0x0D 	/* Filters_Set 				  */
-#define PI_ITEM_K_LOOPBACK_MODE			0x0E 	/* Chars_Set 				  */
-#define PI_ITEM_K_CONFIG_POLICY			0x10 	/* SMTConfigPolicy 			  */
-#define PI_ITEM_K_CON_POLICY			0x11 	/* SMTConnectionPolicy 		  */
-#define PI_ITEM_K_T_NOTIFY				0x12 	/* SMTTNotify 				  */
-#define PI_ITEM_K_STATION_ACTION		0x13 	/* SMTStationAction			  */
-#define PI_ITEM_K_MAC_PATHS_REQ	   		0x15 	/* MACPathsRequested 		  */
-#define PI_ITEM_K_MAC_ACTION			0x17 	/* MACAction 				  */
-#define PI_ITEM_K_CON_POLICIES			0x18 	/* PORTConnectionPolicies	  */
-#define PI_ITEM_K_PORT_PATHS_REQ		0x19 	/* PORTPathsRequested 		  */
-#define PI_ITEM_K_MAC_LOOP_TIME			0x1A 	/* PORTMACLoopTime 			  */
-#define PI_ITEM_K_TB_MAX				0x1B 	/* PORTTBMax 				  */
-#define PI_ITEM_K_LER_CUTOFF			0x1C 	/* PORTLerCutoff 			  */
-#define PI_ITEM_K_LER_ALARM				0x1D 	/* PORTLerAlarm 			  */
-#define PI_ITEM_K_PORT_ACTION			0x1E 	/* PORTAction 				  */
-#define PI_ITEM_K_FLUSH_TIME			0x20 	/* Chars_Set 				  */
-#define PI_ITEM_K_MAC_T_REQ				0x29 	/* MACTReq 					  */
-#define PI_ITEM_K_EMAC_RING_PURGER		0x2A 	/* eMACRingPurgerEnable		  */
-#define PI_ITEM_K_EMAC_RTOKEN_TIMEOUT	0x2B 	/* eMACRestrictedTokenTimeout */
-#define PI_ITEM_K_FDX_ENB_DIS			0x2C 	/* eFDXEnable				  */
-#define PI_ITEM_K_MAX					0x2C 	/* Must equal high item		  */
-
-/* Values for some of the items */
-
-#define PI_K_FALSE						0	   /* Generic false */
-#define PI_K_TRUE						1	   /* Generic true  */
-
-#define PI_SNMP_K_TRUE					1	   /* SNMP true/false values */
-#define PI_SNMP_K_FALSE					2
-
-#define PI_FSTATE_K_BLOCK				0	   /* Filter State */
-#define PI_FSTATE_K_PASS				1
-
-/* Define command return codes */
-
-#define PI_RSP_K_SUCCESS				0x00
-#define PI_RSP_K_FAILURE				0x01
-#define PI_RSP_K_WARNING				0x02
-#define PI_RSP_K_LOOP_MODE_BAD			0x03
-#define PI_RSP_K_ITEM_CODE_BAD			0x04
-#define PI_RSP_K_TVX_BAD				0x05
-#define PI_RSP_K_TREQ_BAD				0x06
-#define PI_RSP_K_TOKEN_BAD				0x07
-#define PI_RSP_K_NO_EOL					0x0C
-#define PI_RSP_K_FILTER_STATE_BAD		0x0D
-#define PI_RSP_K_CMD_TYPE_BAD			0x0E
-#define PI_RSP_K_ADAPTER_STATE_BAD		0x0F
-#define PI_RSP_K_RING_PURGER_BAD		0x10
-#define PI_RSP_K_LEM_THRESHOLD_BAD		0x11
-#define PI_RSP_K_LOOP_NOT_SUPPORTED		0x12
-#define PI_RSP_K_FLUSH_TIME_BAD			0x13
-#define PI_RSP_K_NOT_IMPLEMENTED		0x14
-#define PI_RSP_K_CONFIG_POLICY_BAD		0x15
-#define PI_RSP_K_STATION_ACTION_BAD		0x16
-#define PI_RSP_K_MAC_ACTION_BAD			0x17
-#define PI_RSP_K_CON_POLICIES_BAD		0x18
-#define PI_RSP_K_MAC_LOOP_TIME_BAD		0x19
-#define PI_RSP_K_TB_MAX_BAD				0x1A
-#define PI_RSP_K_LER_CUTOFF_BAD			0x1B
-#define PI_RSP_K_LER_ALARM_BAD			0x1C
-#define PI_RSP_K_MAC_PATHS_REQ_BAD		0x1D
-#define PI_RSP_K_MAC_T_REQ_BAD			0x1E
-#define PI_RSP_K_EMAC_RING_PURGER_BAD	0x1F
-#define PI_RSP_K_EMAC_RTOKEN_TIME_BAD	0x20
-#define PI_RSP_K_NO_SUCH_ENTRY			0x21
-#define PI_RSP_K_T_NOTIFY_BAD			0x22
-#define PI_RSP_K_TR_MAX_EXP_BAD			0x23
-#define PI_RSP_K_MAC_FRM_ERR_THR_BAD	0x24
-#define PI_RSP_K_MAX_T_REQ_BAD			0x25
-#define PI_RSP_K_FDX_ENB_DIS_BAD		0x26
-#define PI_RSP_K_ITEM_INDEX_BAD			0x27
-#define PI_RSP_K_PORT_ACTION_BAD		0x28
-
-/* Commonly used structures */
-
-typedef struct									/* Item list */
-	{
-	PI_UINT32  item_code;
-	PI_UINT32  value;
-	} PI_ITEM_LIST;
-
-typedef struct									/* Response header */
-	{
-	PI_UINT32  reserved;
-	PI_UINT32  cmd_type;
-	PI_UINT32  status;
-	} PI_RSP_HEADER;
-
-
-/* Start Command */
-
-typedef struct
-	{
-	PI_UINT32  cmd_type;
-	} PI_CMD_START_REQ;
-
-/* Start Response */
-
-typedef struct
-	{
-	PI_RSP_HEADER   header;
-	} PI_CMD_START_RSP;
-
-/* Filters_Set Request */
-
-#define PI_CMD_FILTERS_SET_K_ITEMS_MAX  63		/* Fits in a 512 byte buffer */
-
-typedef struct
-	{
-	PI_UINT32		cmd_type;
-	PI_ITEM_LIST	item[PI_CMD_FILTERS_SET_K_ITEMS_MAX];
-	} PI_CMD_FILTERS_SET_REQ;
-
-/* Filters_Set Response */
-
-typedef struct
-	{
-	PI_RSP_HEADER   header;
-	} PI_CMD_FILTERS_SET_RSP;
-
-/* Filters_Get Request */
-
-typedef struct
-	{
-	PI_UINT32		cmd_type;
-	} PI_CMD_FILTERS_GET_REQ;
-
-/* Filters_Get Response */
-
-typedef struct
-	{
-	PI_RSP_HEADER   header;
-	PI_UINT32		ind_group_prom;
-	PI_UINT32		group_prom;
-	PI_UINT32		broadcast_all;
-	PI_UINT32		smt_all;
-	PI_UINT32		smt_user;
-	PI_UINT32		reserved_all;
-	PI_UINT32		implementor_all;
-	} PI_CMD_FILTERS_GET_RSP;
-
-
-/* Chars_Set Request */
-
-#define PI_CMD_CHARS_SET_K_ITEMS_MAX 42		/* Fits in a 512 byte buffer */
-
-typedef struct
-	{
-	PI_UINT32		cmd_type;
-	struct							  		/* Item list */
-		{
-		PI_UINT32	item_code;
-		PI_UINT32	value;
-		PI_UINT32	item_index;
-		} item[PI_CMD_CHARS_SET_K_ITEMS_MAX];
-	} PI_CMD_CHARS_SET_REQ;
-
-/* Chars_Set Response */
-
-typedef struct
-	{
-	PI_RSP_HEADER   header;
-	} PI_CMD_CHARS_SET_RSP;
-
-
-/* SNMP_Set Request */
-
-#define PI_CMD_SNMP_SET_K_ITEMS_MAX 42	   	/* Fits in a 512 byte buffer */
-
-typedef struct
-	{
-	PI_UINT32		cmd_type;
-	struct							   		/* Item list */
-		{
-		PI_UINT32	item_code;
-		PI_UINT32	value;
-		PI_UINT32	item_index;
-		} item[PI_CMD_SNMP_SET_K_ITEMS_MAX];
-	} PI_CMD_SNMP_SET_REQ;
-
-/* SNMP_Set Response */
-
-typedef struct
-	{
-	PI_RSP_HEADER   header;
-	} PI_CMD_SNMP_SET_RSP;
-
-
-/* SMT_MIB_Set Request */
-
-#define PI_CMD_SMT_MIB_SET_K_ITEMS_MAX 42	/* Max number of items */
-
-typedef struct
-	{
-	PI_UINT32	cmd_type;
-	struct
-		{
-		PI_UINT32	item_code;
-		PI_UINT32	value;
-		PI_UINT32	item_index;
-		} item[PI_CMD_SMT_MIB_SET_K_ITEMS_MAX];
-	} PI_CMD_SMT_MIB_SET_REQ;
-
-/* SMT_MIB_Set Response */
-
-typedef struct
-	{
-	PI_RSP_HEADER   header;
-	} PI_CMD_SMT_MIB_SET_RSP;
-
-/* SMT_MIB_Get Request */
-
-typedef struct
-	{
-	PI_UINT32  cmd_type;
-	} PI_CMD_SMT_MIB_GET_REQ;
-
-/* SMT_MIB_Get Response */
-
-typedef struct						  /* Refer to ANSI FDDI SMT Rev. 7.3 */
-	{
-	PI_RSP_HEADER  header;
-
-	/* SMT GROUP */
-
-	PI_STATION_ID  	smt_station_id;
-	PI_UINT32 		smt_op_version_id;
-	PI_UINT32	   	smt_hi_version_id;
-	PI_UINT32	   	smt_lo_version_id;
-	PI_UINT32	   	smt_user_data[8];
-	PI_UINT32	   	smt_mib_version_id;
-	PI_UINT32	   	smt_mac_ct;
-	PI_UINT32	   	smt_non_master_ct;
-	PI_UINT32	   	smt_master_ct;
-	PI_UINT32	   	smt_available_paths;
-	PI_UINT32	   	smt_config_capabilities;
-	PI_UINT32	   	smt_config_policy;
-	PI_UINT32	   	smt_connection_policy;
-	PI_UINT32	   	smt_t_notify;
-	PI_UINT32	   	smt_stat_rpt_policy;
-	PI_UINT32	   	smt_trace_max_expiration;
-	PI_UINT32	   	smt_bypass_present;
-	PI_UINT32	  	smt_ecm_state;
-	PI_UINT32	   	smt_cf_state;
-	PI_UINT32	   	smt_remote_disconnect_flag;
-	PI_UINT32	   	smt_station_status;
-	PI_UINT32	   	smt_peer_wrap_flag;
-	PI_CNTR	   		smt_msg_time_stamp;
-	PI_CNTR	  		smt_transition_time_stamp;
-
-	/* MAC GROUP */
-
-	PI_UINT32		mac_frame_status_functions;
-	PI_UINT32		mac_t_max_capability;
-	PI_UINT32		mac_tvx_capability;
-	PI_UINT32		mac_available_paths;
-	PI_UINT32		mac_current_path;
-	PI_LAN_ADDR		mac_upstream_nbr;
-	PI_LAN_ADDR		mac_downstream_nbr;
-	PI_LAN_ADDR		mac_old_upstream_nbr;
-	PI_LAN_ADDR		mac_old_downstream_nbr;
-	PI_UINT32	   	mac_dup_address_test;
-	PI_UINT32	   	mac_requested_paths;
-	PI_UINT32	   	mac_downstream_port_type;
-	PI_LAN_ADDR		mac_smt_address;
-	PI_UINT32		mac_t_req;
-	PI_UINT32		mac_t_neg;
-	PI_UINT32		mac_t_max;
-	PI_UINT32		mac_tvx_value;
-	PI_UINT32		mac_frame_error_threshold;
-	PI_UINT32		mac_frame_error_ratio;
-	PI_UINT32		mac_rmt_state;
-	PI_UINT32		mac_da_flag;
-	PI_UINT32		mac_unda_flag;
-	PI_UINT32		mac_frame_error_flag;
-	PI_UINT32		mac_ma_unitdata_available;
-	PI_UINT32		mac_hardware_present;
-	PI_UINT32		mac_ma_unitdata_enable;
-
-	/* PATH GROUP */
-
-	PI_UINT32		path_configuration[8];
-	PI_UINT32		path_tvx_lower_bound;
-	PI_UINT32		path_t_max_lower_bound;
-	PI_UINT32		path_max_t_req;
-
-	/* PORT GROUP */
-
-	PI_UINT32		port_my_type[PI_PHY_K_MAX];
-	PI_UINT32		port_neighbor_type[PI_PHY_K_MAX];
-	PI_UINT32		port_connection_policies[PI_PHY_K_MAX];
-	PI_UINT32		port_mac_indicated[PI_PHY_K_MAX];
-	PI_UINT32		port_current_path[PI_PHY_K_MAX];
-	PI_UINT32		port_requested_paths[PI_PHY_K_MAX];
-	PI_UINT32		port_mac_placement[PI_PHY_K_MAX];
-	PI_UINT32		port_available_paths[PI_PHY_K_MAX];
-	PI_UINT32		port_pmd_class[PI_PHY_K_MAX];
-	PI_UINT32		port_connection_capabilities[PI_PHY_K_MAX];
-	PI_UINT32		port_bs_flag[PI_PHY_K_MAX];
-	PI_UINT32		port_ler_estimate[PI_PHY_K_MAX];
-	PI_UINT32		port_ler_cutoff[PI_PHY_K_MAX];
-	PI_UINT32		port_ler_alarm[PI_PHY_K_MAX];
-	PI_UINT32		port_connect_state[PI_PHY_K_MAX];
-	PI_UINT32		port_pcm_state[PI_PHY_K_MAX];
-	PI_UINT32		port_pc_withhold[PI_PHY_K_MAX];
-	PI_UINT32		port_ler_flag[PI_PHY_K_MAX];
-	PI_UINT32		port_hardware_present[PI_PHY_K_MAX];
-
-	/* GROUP for things that were added later, so must be at the end. */
-
-	PI_CNTR	   		path_ring_latency;
-
-	} PI_CMD_SMT_MIB_GET_RSP;
-
-
-/*
- *  Item and group code definitions for SMT 7.3 mandatory objects.  These
- *  definitions are to be used as appropriate in SMT_MIB_SET commands and
- *  certain host-sent SMT frames such as PMF Get and Set requests.  The
- *  codes have been taken from the MIB summary section of ANSI SMT 7.3.
- */
-
-#define PI_GRP_K_SMT_STATION_ID			0x100A
-#define PI_ITEM_K_SMT_STATION_ID		0x100B
-#define PI_ITEM_K_SMT_OP_VERS_ID		0x100D
-#define PI_ITEM_K_SMT_HI_VERS_ID		0x100E
-#define PI_ITEM_K_SMT_LO_VERS_ID		0x100F
-#define PI_ITEM_K_SMT_USER_DATA			0x1011
-#define PI_ITEM_K_SMT_MIB_VERS_ID	  	0x1012
-
-#define PI_GRP_K_SMT_STATION_CONFIG		0x1014
-#define PI_ITEM_K_SMT_MAC_CT			0x1015
-#define PI_ITEM_K_SMT_NON_MASTER_CT		0x1016
-#define PI_ITEM_K_SMT_MASTER_CT			0x1017
-#define PI_ITEM_K_SMT_AVAIL_PATHS		0x1018
-#define PI_ITEM_K_SMT_CONFIG_CAPS		0x1019
-#define PI_ITEM_K_SMT_CONFIG_POL		0x101A
-#define PI_ITEM_K_SMT_CONN_POL			0x101B
-#define PI_ITEM_K_SMT_T_NOTIFY			0x101D
-#define PI_ITEM_K_SMT_STAT_POL			0x101E
-#define PI_ITEM_K_SMT_TR_MAX_EXP		0x101F
-#define PI_ITEM_K_SMT_PORT_INDEXES		0x1020
-#define PI_ITEM_K_SMT_MAC_INDEXES		0x1021
-#define PI_ITEM_K_SMT_BYPASS_PRESENT	0x1022
-
-#define PI_GRP_K_SMT_STATUS				0x1028
-#define PI_ITEM_K_SMT_ECM_STATE			0x1029
-#define PI_ITEM_K_SMT_CF_STATE		 	0x102A
-#define PI_ITEM_K_SMT_REM_DISC_FLAG		0x102C
-#define PI_ITEM_K_SMT_STATION_STATUS	0x102D
-#define PI_ITEM_K_SMT_PEER_WRAP_FLAG	0x102E
-
-#define PI_GRP_K_SMT_MIB_OPERATION	 	0x1032
-#define PI_ITEM_K_SMT_MSG_TIME_STAMP 	0x1033
-#define PI_ITEM_K_SMT_TRN_TIME_STAMP 	0x1034
-
-#define PI_ITEM_K_SMT_STATION_ACT		0x103C
-
-#define PI_GRP_K_MAC_CAPABILITIES	  	0x200A
-#define PI_ITEM_K_MAC_FRM_STAT_FUNC		0x200B
-#define PI_ITEM_K_MAC_T_MAX_CAP			0x200D
-#define PI_ITEM_K_MAC_TVX_CAP		  	0x200E
-
-#define PI_GRP_K_MAC_CONFIG				0x2014
-#define PI_ITEM_K_MAC_AVAIL_PATHS	  	0x2016
-#define PI_ITEM_K_MAC_CURRENT_PATH	 	0x2017
-#define PI_ITEM_K_MAC_UP_NBR			0x2018
-#define PI_ITEM_K_MAC_DOWN_NBR			0x2019
-#define PI_ITEM_K_MAC_OLD_UP_NBR	 	0x201A
-#define PI_ITEM_K_MAC_OLD_DOWN_NBR	 	0x201B
-#define PI_ITEM_K_MAC_DUP_ADDR_TEST		0x201D
-#define PI_ITEM_K_MAC_REQ_PATHS			0x2020
-#define PI_ITEM_K_MAC_DOWN_PORT_TYPE   	0x2021
-#define PI_ITEM_K_MAC_INDEX				0x2022
-
-#define PI_GRP_K_MAC_ADDRESS			0x2028
-#define PI_ITEM_K_MAC_SMT_ADDRESS		0x2029
-
-#define PI_GRP_K_MAC_OPERATION			0x2032
-#define PI_ITEM_K_MAC_TREQ				0x2033
-#define PI_ITEM_K_MAC_TNEG				0x2034
-#define PI_ITEM_K_MAC_TMAX				0x2035
-#define PI_ITEM_K_MAC_TVX_VALUE			0x2036
-
-#define PI_GRP_K_MAC_COUNTERS			0x2046
-#define PI_ITEM_K_MAC_FRAME_CT			0x2047
-#define PI_ITEM_K_MAC_COPIED_CT			0x2048
-#define PI_ITEM_K_MAC_TRANSMIT_CT		0x2049
-#define PI_ITEM_K_MAC_ERROR_CT			0x2051
-#define PI_ITEM_K_MAC_LOST_CT			0x2052
-
-#define PI_GRP_K_MAC_FRM_ERR_COND		0x205A
-#define PI_ITEM_K_MAC_FRM_ERR_THR		0x205F
-#define PI_ITEM_K_MAC_FRM_ERR_RAT		0x2060
-
-#define PI_GRP_K_MAC_STATUS				0x206E
-#define PI_ITEM_K_MAC_RMT_STATE			0x206F
-#define PI_ITEM_K_MAC_DA_FLAG			0x2070
-#define PI_ITEM_K_MAC_UNDA_FLAG			0x2071
-#define PI_ITEM_K_MAC_FRM_ERR_FLAG		0x2072
-#define PI_ITEM_K_MAC_MA_UNIT_AVAIL		0x2074
-#define PI_ITEM_K_MAC_HW_PRESENT		0x2075
-#define PI_ITEM_K_MAC_MA_UNIT_ENAB		0x2076
-
-#define PI_GRP_K_PATH_CONFIG			0x320A
-#define PI_ITEM_K_PATH_INDEX			0x320B
-#define PI_ITEM_K_PATH_CONFIGURATION 	0x3212
-#define PI_ITEM_K_PATH_TVX_LB			0x3215
-#define PI_ITEM_K_PATH_T_MAX_LB			0x3216
-#define PI_ITEM_K_PATH_MAX_T_REQ		0x3217
-
-#define PI_GRP_K_PORT_CONFIG			0x400A
-#define PI_ITEM_K_PORT_MY_TYPE			0x400C
-#define PI_ITEM_K_PORT_NBR_TYPE			0x400D
-#define PI_ITEM_K_PORT_CONN_POLS		0x400E
-#define PI_ITEM_K_PORT_MAC_INDICATED  	0x400F
-#define PI_ITEM_K_PORT_CURRENT_PATH		0x4010
-#define PI_ITEM_K_PORT_REQ_PATHS		0x4011
-#define PI_ITEM_K_PORT_MAC_PLACEMENT 	0x4012
-#define PI_ITEM_K_PORT_AVAIL_PATHS		0x4013
-#define PI_ITEM_K_PORT_PMD_CLASS		0x4016
-#define PI_ITEM_K_PORT_CONN_CAPS		0x4017
-#define PI_ITEM_K_PORT_INDEX			0x401D
-
-#define PI_GRP_K_PORT_OPERATION			0x401E
-#define PI_ITEM_K_PORT_BS_FLAG		 	0x4021
-
-#define PI_GRP_K_PORT_ERR_CNTRS			0x4028
-#define PI_ITEM_K_PORT_LCT_FAIL_CT	 	0x402A
-
-#define PI_GRP_K_PORT_LER			  	0x4032
-#define PI_ITEM_K_PORT_LER_ESTIMATE		0x4033
-#define PI_ITEM_K_PORT_LEM_REJ_CT		0x4034
-#define PI_ITEM_K_PORT_LEM_CT			0x4035
-#define PI_ITEM_K_PORT_LER_CUTOFF		0x403A
-#define PI_ITEM_K_PORT_LER_ALARM		0x403B
-
-#define PI_GRP_K_PORT_STATUS			0x403C
-#define PI_ITEM_K_PORT_CONNECT_STATE	0x403D
-#define PI_ITEM_K_PORT_PCM_STATE		0x403E
-#define PI_ITEM_K_PORT_PC_WITHHOLD		0x403F
-#define PI_ITEM_K_PORT_LER_FLAG			0x4040
-#define PI_ITEM_K_PORT_HW_PRESENT		0x4041
-
-#define PI_ITEM_K_PORT_ACT				0x4046
-
-/* Addr_Filter_Set Request */
-
-#define PI_CMD_ADDR_FILTER_K_SIZE   62
-
-typedef struct
-	{
-	PI_UINT32	cmd_type;
-	PI_LAN_ADDR	entry[PI_CMD_ADDR_FILTER_K_SIZE];
-	} PI_CMD_ADDR_FILTER_SET_REQ;
-
-/* Addr_Filter_Set Response */
-
-typedef struct
-	{
-	PI_RSP_HEADER   header;
-	} PI_CMD_ADDR_FILTER_SET_RSP;
-
-/* Addr_Filter_Get Request */
-
-typedef struct
-	{
-	PI_UINT32	cmd_type;
-	} PI_CMD_ADDR_FILTER_GET_REQ;
-
-/* Addr_Filter_Get Response */
-
-typedef struct
-	{
-	PI_RSP_HEADER   header;
-	PI_LAN_ADDR		entry[PI_CMD_ADDR_FILTER_K_SIZE];
-	} PI_CMD_ADDR_FILTER_GET_RSP;
-
-/* Status_Chars_Get Request */
-
-typedef struct
-	{
-	PI_UINT32  cmd_type;
-	} PI_CMD_STATUS_CHARS_GET_REQ;
-
-/* Status_Chars_Get Response */
-
-typedef struct
-	{
-	PI_RSP_HEADER   header;
-	PI_STATION_ID   station_id;						/* Station */
-	PI_UINT32		station_type;
-	PI_UINT32		smt_ver_id;
-	PI_UINT32		smt_ver_id_max;
-	PI_UINT32		smt_ver_id_min;
-	PI_UINT32		station_state;
-	PI_LAN_ADDR		link_addr;						/* Link */
-	PI_UINT32		t_req;
-	PI_UINT32		tvx;
-	PI_UINT32		token_timeout;
-	PI_UINT32		purger_enb;
-	PI_UINT32		link_state;
-	PI_UINT32		tneg;
-	PI_UINT32		dup_addr_flag;
-	PI_LAN_ADDR		una;
-	PI_LAN_ADDR		una_old;
-	PI_UINT32		un_dup_addr_flag;
-	PI_LAN_ADDR		dna;
-	PI_LAN_ADDR		dna_old;
-	PI_UINT32		purger_state;
-	PI_UINT32		fci_mode;
-	PI_UINT32		error_reason;
-	PI_UINT32		loopback;
-	PI_UINT32		ring_latency;
-	PI_LAN_ADDR		last_dir_beacon_sa;
-	PI_LAN_ADDR		last_dir_beacon_una;
-	PI_UINT32		phy_type[PI_PHY_K_MAX];			/* Phy */
-	PI_UINT32		pmd_type[PI_PHY_K_MAX];
-	PI_UINT32		lem_threshold[PI_PHY_K_MAX];
-	PI_UINT32		phy_state[PI_PHY_K_MAX];
-	PI_UINT32		nbor_phy_type[PI_PHY_K_MAX];
-	PI_UINT32		link_error_est[PI_PHY_K_MAX];
-	PI_UINT32		broken_reason[PI_PHY_K_MAX];
-	PI_UINT32		reject_reason[PI_PHY_K_MAX];
-	PI_UINT32		cntr_interval;					/* Miscellaneous */
-	PI_UINT32		module_rev;
-	PI_UINT32		firmware_rev;
-	PI_UINT32		mop_device_type;
-	PI_UINT32		phy_led[PI_PHY_K_MAX];
-	PI_UINT32		flush_time;
-	} PI_CMD_STATUS_CHARS_GET_RSP;
-
-/* FDDI_MIB_Get Request */
-
-typedef struct
-	{
-	PI_UINT32  cmd_type;
-	} PI_CMD_FDDI_MIB_GET_REQ;
-
-/* FDDI_MIB_Get Response */
-
-typedef struct
-	{
-	PI_RSP_HEADER   header;
-
-	/* SMT GROUP */
-
-	PI_STATION_ID   smt_station_id;
-	PI_UINT32		smt_op_version_id;
-	PI_UINT32		smt_hi_version_id;
-	PI_UINT32		smt_lo_version_id;
-	PI_UINT32		smt_mac_ct;
-	PI_UINT32		smt_non_master_ct;
-	PI_UINT32		smt_master_ct;
-	PI_UINT32		smt_paths_available;
-	PI_UINT32		smt_config_capabilities;
-	PI_UINT32		smt_config_policy;
-	PI_UINT32		smt_connection_policy;
-	PI_UINT32		smt_t_notify;
-	PI_UINT32		smt_status_reporting;
-	PI_UINT32		smt_ecm_state;
-	PI_UINT32		smt_cf_state;
-	PI_UINT32		smt_hold_state;
-	PI_UINT32		smt_remote_disconnect_flag;
-	PI_UINT32		smt_station_action;
-
-	/* MAC GROUP */
-
-	PI_UINT32		mac_frame_status_capabilities;
-	PI_UINT32		mac_t_max_greatest_lower_bound;
-	PI_UINT32		mac_tvx_greatest_lower_bound;
-	PI_UINT32		mac_paths_available;
-	PI_UINT32		mac_current_path;
-	PI_LAN_ADDR		mac_upstream_nbr;
-	PI_LAN_ADDR		mac_old_upstream_nbr;
-	PI_UINT32		mac_dup_addr_test;
-	PI_UINT32		mac_paths_requested;
-	PI_UINT32		mac_downstream_port_type;
-	PI_LAN_ADDR		mac_smt_address;
-	PI_UINT32		mac_t_req;
-	PI_UINT32		mac_t_neg;
-	PI_UINT32		mac_t_max;
-	PI_UINT32		mac_tvx_value;
-	PI_UINT32		mac_t_min;
-	PI_UINT32		mac_current_frame_status;
-	/*			  	mac_frame_cts 			*/
-	/* 				mac_error_cts 			*/
-	/* 		   		mac_lost_cts 			*/
-	PI_UINT32		mac_frame_error_threshold;
-	PI_UINT32		mac_frame_error_ratio;
-	PI_UINT32		mac_rmt_state;
-	PI_UINT32		mac_da_flag;
-	PI_UINT32		mac_una_da_flag;
-	PI_UINT32		mac_frame_condition;
-	PI_UINT32		mac_chip_set;
-	PI_UINT32		mac_action;
-
-	/* PATH GROUP => Does not need to be implemented */
-
-	/* PORT GROUP */
-
-	PI_UINT32		port_pc_type[PI_PHY_K_MAX];
-	PI_UINT32		port_pc_neighbor[PI_PHY_K_MAX];
-	PI_UINT32		port_connection_policies[PI_PHY_K_MAX];
-	PI_UINT32		port_remote_mac_indicated[PI_PHY_K_MAX];
-	PI_UINT32		port_ce_state[PI_PHY_K_MAX];
-	PI_UINT32		port_paths_requested[PI_PHY_K_MAX];
-	PI_UINT32		port_mac_placement[PI_PHY_K_MAX];
-	PI_UINT32		port_available_paths[PI_PHY_K_MAX];
-	PI_UINT32		port_mac_loop_time[PI_PHY_K_MAX];
-	PI_UINT32		port_tb_max[PI_PHY_K_MAX];
-	PI_UINT32		port_bs_flag[PI_PHY_K_MAX];
-	/*				port_lct_fail_cts[PI_PHY_K_MAX];	*/
-	PI_UINT32		port_ler_estimate[PI_PHY_K_MAX];
-	/*				port_lem_reject_cts[PI_PHY_K_MAX];	*/
-	/*				port_lem_cts[PI_PHY_K_MAX];		*/
-	PI_UINT32		port_ler_cutoff[PI_PHY_K_MAX];
-	PI_UINT32		port_ler_alarm[PI_PHY_K_MAX];
-	PI_UINT32		port_connect_state[PI_PHY_K_MAX];
-	PI_UINT32		port_pcm_state[PI_PHY_K_MAX];
-	PI_UINT32		port_pc_withhold[PI_PHY_K_MAX];
-	PI_UINT32		port_ler_condition[PI_PHY_K_MAX];
-	PI_UINT32		port_chip_set[PI_PHY_K_MAX];
-	PI_UINT32		port_action[PI_PHY_K_MAX];
-
-	/* ATTACHMENT GROUP */
-
-	PI_UINT32		attachment_class;
-	PI_UINT32		attachment_ob_present;
-	PI_UINT32		attachment_imax_expiration;
-	PI_UINT32		attachment_inserted_status;
-	PI_UINT32		attachment_insert_policy;
-
-	/* CHIP SET GROUP => Does not need to be implemented */
-
-	} PI_CMD_FDDI_MIB_GET_RSP;
-
-/* DEC_Ext_MIB_Get Request */
-
-typedef struct
-	{
-	PI_UINT32  cmd_type;
-	} PI_CMD_DEC_EXT_MIB_GET_REQ;
-
-/* DEC_Ext_MIB_Get (efddi and efdx groups only) Response */
-
-typedef struct
-	{
-	PI_RSP_HEADER   header;
-
-	/* SMT GROUP */
-
-	PI_UINT32		esmt_station_type;
-
-	/* MAC GROUP */
-
-	PI_UINT32		emac_link_state;
-	PI_UINT32		emac_ring_purger_state;
-	PI_UINT32		emac_ring_purger_enable;
-	PI_UINT32		emac_frame_strip_mode;
-	PI_UINT32		emac_ring_error_reason;
-	PI_UINT32		emac_up_nbr_dup_addr_flag;
-	PI_UINT32		emac_restricted_token_timeout;
-
-	/* PORT GROUP */
-
-	PI_UINT32		eport_pmd_type[PI_PHY_K_MAX];
-	PI_UINT32		eport_phy_state[PI_PHY_K_MAX];
-	PI_UINT32		eport_reject_reason[PI_PHY_K_MAX];
-
-	/* FDX (Full-Duplex) GROUP */
-
-	PI_UINT32		efdx_enable;				/* Valid only in SMT 7.3 */
-	PI_UINT32		efdx_op;					/* Valid only in SMT 7.3 */
-	PI_UINT32		efdx_state;					/* Valid only in SMT 7.3 */
-
-	} PI_CMD_DEC_EXT_MIB_GET_RSP;
-
-typedef struct
-	{
-	PI_CNTR		traces_rcvd;					/* Station */
-	PI_CNTR		frame_cnt;						/* Link */
-	PI_CNTR		error_cnt;
-	PI_CNTR		lost_cnt;
-	PI_CNTR		octets_rcvd;
-	PI_CNTR		octets_sent;
-	PI_CNTR		pdus_rcvd;
-	PI_CNTR		pdus_sent;
-	PI_CNTR		mcast_octets_rcvd;
-	PI_CNTR		mcast_octets_sent;
-	PI_CNTR		mcast_pdus_rcvd;
-	PI_CNTR		mcast_pdus_sent;
-	PI_CNTR		xmt_underruns;
-	PI_CNTR		xmt_failures;
-	PI_CNTR		block_check_errors;
-	PI_CNTR		frame_status_errors;
-	PI_CNTR		pdu_length_errors;
-	PI_CNTR		rcv_overruns;
-	PI_CNTR		user_buff_unavailable;
-	PI_CNTR		inits_initiated;
-	PI_CNTR		inits_rcvd;
-	PI_CNTR		beacons_initiated;
-	PI_CNTR		dup_addrs;
-	PI_CNTR		dup_tokens;
-	PI_CNTR		purge_errors;
-	PI_CNTR		fci_strip_errors;
-	PI_CNTR		traces_initiated;
-	PI_CNTR		directed_beacons_rcvd;
-	PI_CNTR		emac_frame_alignment_errors;
-	PI_CNTR		ebuff_errors[PI_PHY_K_MAX];		/* Phy */
-	PI_CNTR		lct_rejects[PI_PHY_K_MAX];
-	PI_CNTR		lem_rejects[PI_PHY_K_MAX];
-	PI_CNTR		link_errors[PI_PHY_K_MAX];
-	PI_CNTR		connections[PI_PHY_K_MAX];
-	PI_CNTR		copied_cnt;			 			/* Valid only if using SMT 7.3 */
-	PI_CNTR		transmit_cnt;					/* Valid only if using SMT 7.3 */
-	PI_CNTR		tokens;
-	} PI_CNTR_BLK;
-
-/* Counters_Get Request */
-
-typedef struct
-	{
-	PI_UINT32  cmd_type;
-	} PI_CMD_CNTRS_GET_REQ;
-
-/* Counters_Get Response */
-
-typedef struct
-	{
-	PI_RSP_HEADER   header;
-	PI_CNTR		time_since_reset;
-	PI_CNTR_BLK		cntrs;
-	} PI_CMD_CNTRS_GET_RSP;
-
-/* Counters_Set Request */
-
-typedef struct
-	{
-	PI_UINT32	cmd_type;
-	PI_CNTR_BLK	cntrs;
-	} PI_CMD_CNTRS_SET_REQ;
-
-/* Counters_Set Response */
-
-typedef struct
-	{
-	PI_RSP_HEADER   header;
-	} PI_CMD_CNTRS_SET_RSP;
-
-/* Error_Log_Clear Request */
-
-typedef struct
-	{
-	PI_UINT32  cmd_type;
-	} PI_CMD_ERROR_LOG_CLEAR_REQ;
-
-/* Error_Log_Clear Response */
-
-typedef struct
-	{
-	PI_RSP_HEADER   header;
-	} PI_CMD_ERROR_LOG_CLEAR_RSP;
-
-/* Error_Log_Get Request */
-
-#define PI_LOG_ENTRY_K_INDEX_MIN	0		/* Minimum index for entry */
-
-typedef struct
-	{
-	PI_UINT32  cmd_type;
-	PI_UINT32  entry_index;
-	} PI_CMD_ERROR_LOG_GET_REQ;
-
-/* Error_Log_Get Response */
-
-#define PI_K_LOG_FW_SIZE			111		/* Max number of fw longwords */
-#define PI_K_LOG_DIAG_SIZE	 		6		/* Max number of diag longwords */
-
-typedef struct
-	{
-	struct
-		{
-		PI_UINT32	fru_imp_mask;
-		PI_UINT32	test_id;
-		PI_UINT32	reserved[PI_K_LOG_DIAG_SIZE];
-		} diag;
-	PI_UINT32		fw[PI_K_LOG_FW_SIZE];
-	} PI_LOG_ENTRY;
-
-typedef struct
-	{
-	PI_RSP_HEADER   header;
-	PI_UINT32		event_status;
-	PI_UINT32		caller_id;
-	PI_UINT32		timestamp_l;
-	PI_UINT32		timestamp_h;
-	PI_UINT32		write_count;
-	PI_LOG_ENTRY	entry_info;
-	} PI_CMD_ERROR_LOG_GET_RSP;
-
-/* Define error log related constants and types.					*/
-/*   Not all of the caller id's can occur.  The only ones currently */
-/*   implemented are: none, selftest, mfg, fw, console				*/
-
-#define PI_LOG_EVENT_STATUS_K_VALID		0	/* Valid Event Status 		*/
-#define PI_LOG_EVENT_STATUS_K_INVALID	1	/* Invalid Event Status 	*/
-#define PI_LOG_CALLER_ID_K_NONE		 	0	/* No caller 				*/
-#define PI_LOG_CALLER_ID_K_SELFTEST	 	1	/* Normal power-up selftest */
-#define PI_LOG_CALLER_ID_K_MFG		 	2	/* Mfg power-up selftest 	*/
-#define PI_LOG_CALLER_ID_K_ONLINE		3	/* On-line diagnostics 		*/
-#define PI_LOG_CALLER_ID_K_HW			4	/* Hardware 				*/
-#define PI_LOG_CALLER_ID_K_FW			5	/* Firmware 				*/
-#define PI_LOG_CALLER_ID_K_CNS_HW		6	/* CNS firmware 			*/
-#define PI_LOG_CALLER_ID_K_CNS_FW		7	/* CNS hardware 			*/
-#define PI_LOG_CALLER_ID_K_CONSOLE	 	8   /* Console Caller Id 		*/
-
-/*
- *  Place all DMA commands in the following request and response structures
- *  to simplify code.
- */
-
-typedef union
-	{
-	PI_UINT32					cmd_type;
-	PI_CMD_START_REQ			start;
-	PI_CMD_FILTERS_SET_REQ		filter_set;
-	PI_CMD_FILTERS_GET_REQ		filter_get;
-	PI_CMD_CHARS_SET_REQ		char_set;
-	PI_CMD_ADDR_FILTER_SET_REQ	addr_filter_set;
-	PI_CMD_ADDR_FILTER_GET_REQ	addr_filter_get;
-	PI_CMD_STATUS_CHARS_GET_REQ	stat_char_get;
-	PI_CMD_CNTRS_GET_REQ		cntrs_get;
-	PI_CMD_CNTRS_SET_REQ		cntrs_set;
-	PI_CMD_ERROR_LOG_CLEAR_REQ	error_log_clear;
-	PI_CMD_ERROR_LOG_GET_REQ	error_log_read;
-	PI_CMD_SNMP_SET_REQ			snmp_set;
-	PI_CMD_FDDI_MIB_GET_REQ		fddi_mib_get;
-	PI_CMD_DEC_EXT_MIB_GET_REQ	dec_mib_get;
-	PI_CMD_SMT_MIB_SET_REQ		smt_mib_set;
-	PI_CMD_SMT_MIB_GET_REQ		smt_mib_get;
-	char						pad[PI_CMD_REQ_K_SIZE_MAX];
-	} PI_DMA_CMD_REQ;
-
-typedef union
-	{
-	PI_RSP_HEADER				header;
-	PI_CMD_START_RSP			start;
-	PI_CMD_FILTERS_SET_RSP		filter_set;
-	PI_CMD_FILTERS_GET_RSP		filter_get;
-	PI_CMD_CHARS_SET_RSP		char_set;
-	PI_CMD_ADDR_FILTER_SET_RSP	addr_filter_set;
-	PI_CMD_ADDR_FILTER_GET_RSP	addr_filter_get;
-	PI_CMD_STATUS_CHARS_GET_RSP	stat_char_get;
-	PI_CMD_CNTRS_GET_RSP		cntrs_get;
-	PI_CMD_CNTRS_SET_RSP		cntrs_set;
-	PI_CMD_ERROR_LOG_CLEAR_RSP	error_log_clear;
-	PI_CMD_ERROR_LOG_GET_RSP	error_log_get;
-	PI_CMD_SNMP_SET_RSP			snmp_set;
-	PI_CMD_FDDI_MIB_GET_RSP		fddi_mib_get;
-	PI_CMD_DEC_EXT_MIB_GET_RSP	dec_mib_get;
-	PI_CMD_SMT_MIB_SET_RSP		smt_mib_set;
-	PI_CMD_SMT_MIB_GET_RSP		smt_mib_get;
-	char						pad[PI_CMD_RSP_K_SIZE_MAX];
-	} PI_DMA_CMD_RSP;
-
-typedef union
-	{
-	PI_DMA_CMD_REQ	request;
-	PI_DMA_CMD_RSP	response;
-	} PI_DMA_CMD_BUFFER;
-
-
-/* Define format of Consumer Block (resident in host memory) */
-
-typedef struct
-	{
-	volatile PI_UINT32	xmt_rcv_data;
-	volatile PI_UINT32	reserved_1;
-	volatile PI_UINT32	smt_host;
-	volatile PI_UINT32	reserved_2;
-	volatile PI_UINT32	unsol;
-	volatile PI_UINT32	reserved_3;
-	volatile PI_UINT32	cmd_rsp;
-	volatile PI_UINT32	reserved_4;
-	volatile PI_UINT32	cmd_req;
-	volatile PI_UINT32	reserved_5;
-	} PI_CONSUMER_BLOCK;
-
-#define PI_CONS_M_RCV_INDEX			0x000000FF
-#define PI_CONS_M_XMT_INDEX			0x00FF0000
-#define PI_CONS_V_RCV_INDEX			0
-#define PI_CONS_V_XMT_INDEX			16
-
-/* Offsets into consumer block */
-
-#define PI_CONS_BLK_K_XMT_RCV		0x00
-#define PI_CONS_BLK_K_SMT_HOST		0x08
-#define PI_CONS_BLK_K_UNSOL			0x10
-#define PI_CONS_BLK_K_CMD_RSP		0x18
-#define PI_CONS_BLK_K_CMD_REQ		0x20
-
-/* Offsets into descriptor block */
-
-#define PI_DESCR_BLK_K_RCV_DATA		0x0000
-#define PI_DESCR_BLK_K_XMT_DATA		0x0800
-#define PI_DESCR_BLK_K_SMT_HOST 	0x1000
-#define PI_DESCR_BLK_K_UNSOL		0x1200
-#define PI_DESCR_BLK_K_CMD_RSP		0x1280
-#define PI_DESCR_BLK_K_CMD_REQ		0x1300
-
-/* Define format of a rcv descr (Rcv Data, Cmd Rsp, Unsolicited, SMT Host)   */
-/*   Note a field has been added for later versions of the PDQ to allow for  */
-/*   finer granularity of the rcv buffer alignment.  For backwards		 	 */
-/*   compatibility, the two bits (which allow the rcv buffer to be longword  */
-/*   aligned) have been added at the MBZ bits.  To support previous drivers, */
-/*   the MBZ definition is left intact.									  	 */
-
-typedef struct
-	{
-	PI_UINT32	long_0;
-	PI_UINT32	long_1;
-	} PI_RCV_DESCR;
-
-#define	PI_RCV_DESCR_M_SOP	  		0x80000000
-#define PI_RCV_DESCR_M_SEG_LEN_LO 	0x60000000
-#define PI_RCV_DESCR_M_MBZ	  		0x60000000
-#define PI_RCV_DESCR_M_SEG_LEN		0x1F800000
-#define PI_RCV_DESCR_M_SEG_LEN_HI	0x1FF00000
-#define PI_RCV_DESCR_M_SEG_CNT	  	0x000F0000
-#define PI_RCV_DESCR_M_BUFF_HI	  	0x0000FFFF
-
-#define	PI_RCV_DESCR_V_SOP	  		31
-#define PI_RCV_DESCR_V_SEG_LEN_LO 	29
-#define PI_RCV_DESCR_V_MBZ	  		29
-#define PI_RCV_DESCR_V_SEG_LEN	  	23
-#define PI_RCV_DESCR_V_SEG_LEN_HI 	20
-#define PI_RCV_DESCR_V_SEG_CNT	  	16
-#define PI_RCV_DESCR_V_BUFF_HI	 	0
-
-/* Define the format of a transmit descriptor (Xmt Data, Cmd Req) */
-
-typedef struct
-	{
-	PI_UINT32	long_0;
-	PI_UINT32	long_1;
-	} PI_XMT_DESCR;
-
-#define	PI_XMT_DESCR_M_SOP			0x80000000
-#define PI_XMT_DESCR_M_EOP			0x40000000
-#define PI_XMT_DESCR_M_MBZ			0x20000000
-#define PI_XMT_DESCR_M_SEG_LEN		0x1FFF0000
-#define PI_XMT_DESCR_M_BUFF_HI		0x0000FFFF
-
-#define	PI_XMT_DESCR_V_SOP			31
-#define	PI_XMT_DESCR_V_EOP			30
-#define PI_XMT_DESCR_V_MBZ			29
-#define PI_XMT_DESCR_V_SEG_LEN		16
-#define PI_XMT_DESCR_V_BUFF_HI		0
-
-/* Define format of the Descriptor Block (resident in host memory) */
-
-#define PI_RCV_DATA_K_NUM_ENTRIES			256
-#define PI_XMT_DATA_K_NUM_ENTRIES			256
-#define PI_SMT_HOST_K_NUM_ENTRIES			64
-#define PI_UNSOL_K_NUM_ENTRIES				16
-#define PI_CMD_RSP_K_NUM_ENTRIES			16
-#define PI_CMD_REQ_K_NUM_ENTRIES			16
-
-typedef struct
-	{
-	PI_RCV_DESCR  rcv_data[PI_RCV_DATA_K_NUM_ENTRIES];
-	PI_XMT_DESCR  xmt_data[PI_XMT_DATA_K_NUM_ENTRIES];
-	PI_RCV_DESCR  smt_host[PI_SMT_HOST_K_NUM_ENTRIES];
-	PI_RCV_DESCR  unsol[PI_UNSOL_K_NUM_ENTRIES];
-	PI_RCV_DESCR  cmd_rsp[PI_CMD_RSP_K_NUM_ENTRIES];
-	PI_XMT_DESCR  cmd_req[PI_CMD_REQ_K_NUM_ENTRIES];
-	} PI_DESCR_BLOCK;
-
-/* Define Port Registers - offsets from PDQ Base address */
-
-#define PI_PDQ_K_REG_PORT_RESET			0x00000000
-#define PI_PDQ_K_REG_HOST_DATA			0x00000004
-#define PI_PDQ_K_REG_PORT_CTRL			0x00000008
-#define PI_PDQ_K_REG_PORT_DATA_A		0x0000000C
-#define PI_PDQ_K_REG_PORT_DATA_B		0x00000010
-#define PI_PDQ_K_REG_PORT_STATUS		0x00000014
-#define PI_PDQ_K_REG_TYPE_0_STATUS 		0x00000018
-#define PI_PDQ_K_REG_HOST_INT_ENB	  	0x0000001C
-#define PI_PDQ_K_REG_TYPE_2_PROD_NOINT 	0x00000020
-#define PI_PDQ_K_REG_TYPE_2_PROD		0x00000024
-#define PI_PDQ_K_REG_CMD_RSP_PROD		0x00000028
-#define PI_PDQ_K_REG_CMD_REQ_PROD		0x0000002C
-#define PI_PDQ_K_REG_SMT_HOST_PROD   	0x00000030
-#define PI_PDQ_K_REG_UNSOL_PROD			0x00000034
-
-/* Port Control Register - Command codes for primary commands */
-
-#define PI_PCTRL_M_CMD_ERROR			0x8000
-#define PI_PCTRL_M_BLAST_FLASH			0x4000
-#define PI_PCTRL_M_HALT					0x2000
-#define PI_PCTRL_M_COPY_DATA			0x1000
-#define PI_PCTRL_M_ERROR_LOG_START		0x0800
-#define PI_PCTRL_M_ERROR_LOG_READ		0x0400
-#define PI_PCTRL_M_XMT_DATA_FLUSH_DONE	0x0200
-#define PI_PCTRL_M_INIT					0x0100
-#define PI_PCTRL_M_INIT_START		    0x0080
-#define PI_PCTRL_M_CONS_BLOCK			0x0040
-#define PI_PCTRL_M_UNINIT				0x0020
-#define PI_PCTRL_M_RING_MEMBER			0x0010
-#define PI_PCTRL_M_MLA					0x0008
-#define PI_PCTRL_M_FW_REV_READ			0x0004
-#define PI_PCTRL_M_DEV_SPECIFIC			0x0002
-#define PI_PCTRL_M_SUB_CMD				0x0001
-
-/* Define sub-commands accessed via the PI_PCTRL_M_SUB_CMD command */
-
-#define PI_SUB_CMD_K_LINK_UNINIT		0x0001
-#define PI_SUB_CMD_K_BURST_SIZE_SET		0x0002
-#define PI_SUB_CMD_K_PDQ_REV_GET		0x0004
-#define PI_SUB_CMD_K_HW_REV_GET			0x0008
-
-/* Define some Port Data B values */
-
-#define PI_PDATA_B_DMA_BURST_SIZE_4	 	0		/* valid values for command */
-#define PI_PDATA_B_DMA_BURST_SIZE_8	 	1
-#define PI_PDATA_B_DMA_BURST_SIZE_16	2
-#define PI_PDATA_B_DMA_BURST_SIZE_32	3		/* not supported on PCI */
-#define PI_PDATA_B_DMA_BURST_SIZE_DEF	PI_PDATA_B_DMA_BURST_SIZE_16
-
-/* Port Data A Reset state */
-
-#define PI_PDATA_A_RESET_M_UPGRADE		0x00000001
-#define PI_PDATA_A_RESET_M_SOFT_RESET	0x00000002
-#define PI_PDATA_A_RESET_M_SKIP_ST		0x00000004
-
-/* Read adapter MLA address port control command constants */
-
-#define PI_PDATA_A_MLA_K_LO				0
-#define PI_PDATA_A_MLA_K_HI				1
-
-/* Byte Swap values for init command */
-
-#define PI_PDATA_A_INIT_M_DESC_BLK_ADDR			0x0FFFFE000
-#define PI_PDATA_A_INIT_M_RESERVED				0x000001FFC
-#define PI_PDATA_A_INIT_M_BSWAP_DATA			0x000000002
-#define PI_PDATA_A_INIT_M_BSWAP_LITERAL			0x000000001
-
-#define PI_PDATA_A_INIT_V_DESC_BLK_ADDR			13
-#define PI_PDATA_A_INIT_V_RESERVED				3
-#define PI_PDATA_A_INIT_V_BSWAP_DATA			1
-#define PI_PDATA_A_INIT_V_BSWAP_LITERAL			0
-
-/* Port Reset Register */
-
-#define PI_RESET_M_ASSERT_RESET			1
-
-/* Port Status register */
-
-#define PI_PSTATUS_V_RCV_DATA_PENDING	31
-#define PI_PSTATUS_V_XMT_DATA_PENDING	30
-#define PI_PSTATUS_V_SMT_HOST_PENDING	29
-#define PI_PSTATUS_V_UNSOL_PENDING		28
-#define PI_PSTATUS_V_CMD_RSP_PENDING	27
-#define PI_PSTATUS_V_CMD_REQ_PENDING	26
-#define PI_PSTATUS_V_TYPE_0_PENDING		25
-#define PI_PSTATUS_V_RESERVED_1			16
-#define PI_PSTATUS_V_RESERVED_2			11
-#define PI_PSTATUS_V_STATE				8
-#define PI_PSTATUS_V_HALT_ID			0
-
-#define PI_PSTATUS_M_RCV_DATA_PENDING	0x80000000
-#define PI_PSTATUS_M_XMT_DATA_PENDING	0x40000000
-#define PI_PSTATUS_M_SMT_HOST_PENDING	0x20000000
-#define PI_PSTATUS_M_UNSOL_PENDING		0x10000000
-#define PI_PSTATUS_M_CMD_RSP_PENDING	0x08000000
-#define PI_PSTATUS_M_CMD_REQ_PENDING	0x04000000
-#define PI_PSTATUS_M_TYPE_0_PENDING		0x02000000
-#define PI_PSTATUS_M_RESERVED_1			0x01FF0000
-#define PI_PSTATUS_M_RESERVED_2			0x0000F800
-#define PI_PSTATUS_M_STATE				0x00000700
-#define PI_PSTATUS_M_HALT_ID			0x000000FF
-
-/* Define Halt Id's			 					*/
-/*   Do not insert into this list, only append. */
-
-#define PI_HALT_ID_K_SELFTEST_TIMEOUT	0
-#define PI_HALT_ID_K_PARITY_ERROR		1
-#define PI_HALT_ID_K_HOST_DIR_HALT		2
-#define PI_HALT_ID_K_SW_FAULT			3
-#define PI_HALT_ID_K_HW_FAULT			4
-#define PI_HALT_ID_K_PC_TRACE			5
-#define PI_HALT_ID_K_DMA_ERROR			6			/* Host Data has error reg */
-#define PI_HALT_ID_K_IMAGE_CRC_ERROR	7   		/* Image is bad, update it */
-#define PI_HALT_ID_K_BUS_EXCEPTION	 	8   		/* 68K bus exception	   */
-
-/* Host Interrupt Enable Register as seen by host */
-
-#define PI_HOST_INT_M_XMT_DATA_ENB		0x80000000	/* Type 2 Enables */
-#define PI_HOST_INT_M_RCV_DATA_ENB		0x40000000
-#define PI_HOST_INT_M_SMT_HOST_ENB		0x10000000	/* Type 1 Enables */
-#define PI_HOST_INT_M_UNSOL_ENB			0x20000000
-#define PI_HOST_INT_M_CMD_RSP_ENB		0x08000000
-#define PI_HOST_INT_M_CMD_REQ_ENB		0x04000000
-#define	PI_HOST_INT_M_TYPE_1_RESERVED	0x00FF0000
-#define	PI_HOST_INT_M_TYPE_0_RESERVED	0x0000FF00	/* Type 0 Enables */
-#define PI_HOST_INT_M_1MS				0x00000080
-#define PI_HOST_INT_M_20MS				0x00000040
-#define PI_HOST_INT_M_CSR_CMD_DONE		0x00000020
-#define PI_HOST_INT_M_STATE_CHANGE		0x00000010
-#define PI_HOST_INT_M_XMT_FLUSH			0x00000008
-#define PI_HOST_INT_M_NXM				0x00000004
-#define PI_HOST_INT_M_PM_PAR_ERR		0x00000002
-#define PI_HOST_INT_M_BUS_PAR_ERR		0x00000001
-
-#define PI_HOST_INT_V_XMT_DATA_ENB		31			/* Type 2 Enables */
-#define PI_HOST_INT_V_RCV_DATA_ENB		30
-#define PI_HOST_INT_V_SMT_HOST_ENB		29			/* Type 1 Enables */
-#define PI_HOST_INT_V_UNSOL_ENB			28
-#define PI_HOST_INT_V_CMD_RSP_ENB		27
-#define PI_HOST_INT_V_CMD_REQ_ENB		26
-#define	PI_HOST_INT_V_TYPE_1_RESERVED	16
-#define	PI_HOST_INT_V_TYPE_0_RESERVED   8			/* Type 0 Enables */
-#define PI_HOST_INT_V_1MS_ENB			7
-#define PI_HOST_INT_V_20MS_ENB			6
-#define PI_HOST_INT_V_CSR_CMD_DONE_ENB	5
-#define PI_HOST_INT_V_STATE_CHANGE_ENB	4
-#define PI_HOST_INT_V_XMT_FLUSH_ENB 	3
-#define PI_HOST_INT_V_NXM_ENB			2
-#define PI_HOST_INT_V_PM_PAR_ERR_ENB	1
-#define PI_HOST_INT_V_BUS_PAR_ERR_ENB	0
-
-#define PI_HOST_INT_K_ACK_ALL_TYPE_0	0x000000FF
-#define PI_HOST_INT_K_DISABLE_ALL_INTS	0x00000000
-#define PI_HOST_INT_K_ENABLE_ALL_INTS	0xFFFFFFFF
-#define PI_HOST_INT_K_ENABLE_DEF_INTS	0xC000001F
-
-/* Type 0 Interrupt Status Register */
-
-#define PI_TYPE_0_STAT_M_1MS			0x00000080
-#define PI_TYPE_0_STAT_M_20MS			0x00000040
-#define PI_TYPE_0_STAT_M_CSR_CMD_DONE	0x00000020
-#define PI_TYPE_0_STAT_M_STATE_CHANGE	0x00000010
-#define PI_TYPE_0_STAT_M_XMT_FLUSH		0x00000008
-#define PI_TYPE_0_STAT_M_NXM			0x00000004
-#define PI_TYPE_0_STAT_M_PM_PAR_ERR		0x00000002
-#define PI_TYPE_0_STAT_M_BUS_PAR_ERR	0x00000001
-
-#define PI_TYPE_0_STAT_V_1MS			7
-#define PI_TYPE_0_STAT_V_20MS			6
-#define PI_TYPE_0_STAT_V_CSR_CMD_DONE	5
-#define PI_TYPE_0_STAT_V_STATE_CHANGE	4
-#define PI_TYPE_0_STAT_V_XMT_FLUSH		3
-#define PI_TYPE_0_STAT_V_NXM			2
-#define PI_TYPE_0_STAT_V_PM_PAR_ERR		1
-#define PI_TYPE_0_STAT_V_BUS_PAR_ERR	0
-
-/* Register definition structures are defined for both big and little endian systems */
-
-#ifndef __BIG_ENDIAN
-
-/* Little endian format of Type 1 Producer register */
-
-typedef union
-	{
-	PI_UINT32	lword;
-	struct
-		{
-		PI_UINT8	prod;
-		PI_UINT8	comp;
-		PI_UINT8	mbz_1;
-		PI_UINT8	mbz_2;
-		} index;
-	} PI_TYPE_1_PROD_REG;
-
-/* Little endian format of Type 2 Producer register */
-
-typedef union
-	{
-	PI_UINT32	lword;
-	struct
-		{
-		PI_UINT8	rcv_prod;
-		PI_UINT8	xmt_prod;
-		PI_UINT8	rcv_comp;
-		PI_UINT8	xmt_comp;
-		} index;
-	} PI_TYPE_2_PROD_REG;
-
-/* Little endian format of Type 1 Consumer Block longword */
-
-typedef union
-	{
-	PI_UINT32	lword;
-	struct
-		{
-		PI_UINT8	cons;
-		PI_UINT8	res0;
-		PI_UINT8	res1;
-		PI_UINT8	res2;
-		} index;
-	} PI_TYPE_1_CONSUMER;
-
-/* Little endian format of Type 2 Consumer Block longword */
-
-typedef union
-	{
-	PI_UINT32	lword;
-	struct
-		{
-		PI_UINT8	rcv_cons;
-		PI_UINT8	res0;
-		PI_UINT8	xmt_cons;
-		PI_UINT8	res1;
-		} index;
-	} PI_TYPE_2_CONSUMER;
-
-/* Define swapping required by DMA transfers.  */
-#define PI_PDATA_A_INIT_M_BSWAP_INIT	\
-	(PI_PDATA_A_INIT_M_BSWAP_DATA)
-
-#else /* __BIG_ENDIAN */
-
-/* Big endian format of Type 1 Producer register */
-
-typedef union
-	{
-	PI_UINT32	lword;
-	struct
-		{
-		PI_UINT8	mbz_2;
-		PI_UINT8	mbz_1;
-		PI_UINT8	comp;
-		PI_UINT8	prod;
-		} index;
-	} PI_TYPE_1_PROD_REG;
-
-/* Big endian format of Type 2 Producer register */
-
-typedef union
-	{
-	PI_UINT32	lword;
-	struct
-		{
-		PI_UINT8	xmt_comp;
-		PI_UINT8	rcv_comp;
-		PI_UINT8	xmt_prod;
-		PI_UINT8	rcv_prod;
-		} index;
-	} PI_TYPE_2_PROD_REG;
-
-/* Big endian format of Type 1 Consumer Block longword */
-
-typedef union
-	{
-	PI_UINT32	lword;
-	struct
-		{
-		PI_UINT8	res2;
-		PI_UINT8	res1;
-		PI_UINT8	res0;
-		PI_UINT8	cons;
-		} index;
-	} PI_TYPE_1_CONSUMER;
-
-/* Big endian format of Type 2 Consumer Block longword */
-
-typedef union
-	{
-	PI_UINT32	lword;
-	struct
-		{
-		PI_UINT8	res1;
-		PI_UINT8	xmt_cons;
-		PI_UINT8	res0;
-		PI_UINT8	rcv_cons;
-		} index;
-	} PI_TYPE_2_CONSUMER;
-
-/* Define swapping required by DMA transfers.  */
-#define PI_PDATA_A_INIT_M_BSWAP_INIT	\
-	(PI_PDATA_A_INIT_M_BSWAP_DATA | PI_PDATA_A_INIT_M_BSWAP_LITERAL)
-
-#endif /* __BIG_ENDIAN */
-
-/* Define TC PDQ CSR offset and length */
-
-#define PI_TC_K_CSR_OFFSET		0x100000
-#define PI_TC_K_CSR_LEN			0x40		/* 64 bytes */
-
-/* Define EISA controller register offsets */
-
-#define PI_ESIC_K_CSR_IO_LEN		0x80		/* 128 bytes */
-
-#define PI_DEFEA_K_BURST_HOLDOFF	0x040
-
-#define PI_ESIC_K_SLOT_ID            	0xC80
-#define PI_ESIC_K_SLOT_CNTRL		0xC84
-#define PI_ESIC_K_MEM_ADD_CMP_0     	0xC85
-#define PI_ESIC_K_MEM_ADD_CMP_1     	0xC86
-#define PI_ESIC_K_MEM_ADD_CMP_2     	0xC87
-#define PI_ESIC_K_MEM_ADD_HI_CMP_0  	0xC88
-#define PI_ESIC_K_MEM_ADD_HI_CMP_1  	0xC89
-#define PI_ESIC_K_MEM_ADD_HI_CMP_2  	0xC8A
-#define PI_ESIC_K_MEM_ADD_MASK_0     	0xC8B
-#define PI_ESIC_K_MEM_ADD_MASK_1     	0xC8C
-#define PI_ESIC_K_MEM_ADD_MASK_2     	0xC8D
-#define PI_ESIC_K_MEM_ADD_LO_CMP_0  	0xC8E
-#define PI_ESIC_K_MEM_ADD_LO_CMP_1  	0xC8F
-#define PI_ESIC_K_MEM_ADD_LO_CMP_2  	0xC90
-#define PI_ESIC_K_IO_ADD_CMP_0_0	0xC91
-#define PI_ESIC_K_IO_ADD_CMP_0_1	0xC92
-#define PI_ESIC_K_IO_ADD_CMP_1_0	0xC93
-#define PI_ESIC_K_IO_ADD_CMP_1_1	0xC94
-#define PI_ESIC_K_IO_ADD_CMP_2_0	0xC95
-#define PI_ESIC_K_IO_ADD_CMP_2_1	0xC96
-#define PI_ESIC_K_IO_ADD_CMP_3_0	0xC97
-#define PI_ESIC_K_IO_ADD_CMP_3_1	0xC98
-#define PI_ESIC_K_IO_ADD_MASK_0_0    	0xC99
-#define PI_ESIC_K_IO_ADD_MASK_0_1    	0xC9A
-#define PI_ESIC_K_IO_ADD_MASK_1_0    	0xC9B
-#define PI_ESIC_K_IO_ADD_MASK_1_1    	0xC9C
-#define PI_ESIC_K_IO_ADD_MASK_2_0    	0xC9D
-#define PI_ESIC_K_IO_ADD_MASK_2_1    	0xC9E
-#define PI_ESIC_K_IO_ADD_MASK_3_0    	0xC9F
-#define PI_ESIC_K_IO_ADD_MASK_3_1    	0xCA0
-#define PI_ESIC_K_MOD_CONFIG_1		0xCA1
-#define PI_ESIC_K_MOD_CONFIG_2		0xCA2
-#define PI_ESIC_K_MOD_CONFIG_3		0xCA3
-#define PI_ESIC_K_MOD_CONFIG_4		0xCA4
-#define PI_ESIC_K_MOD_CONFIG_5    	0xCA5
-#define PI_ESIC_K_MOD_CONFIG_6		0xCA6
-#define PI_ESIC_K_MOD_CONFIG_7		0xCA7
-#define PI_ESIC_K_DIP_SWITCH         	0xCA8
-#define PI_ESIC_K_IO_CONFIG_STAT_0   	0xCA9
-#define PI_ESIC_K_IO_CONFIG_STAT_1   	0xCAA
-#define PI_ESIC_K_DMA_CONFIG         	0xCAB
-#define PI_ESIC_K_INPUT_PORT         	0xCAC
-#define PI_ESIC_K_OUTPUT_PORT        	0xCAD
-#define PI_ESIC_K_FUNCTION_CNTRL	0xCAE
-
-/* Define the bits in the function control register. */
-
-#define PI_FUNCTION_CNTRL_M_IOCS0	0x01
-#define PI_FUNCTION_CNTRL_M_IOCS1	0x02
-#define PI_FUNCTION_CNTRL_M_IOCS2	0x04
-#define PI_FUNCTION_CNTRL_M_IOCS3	0x08
-#define PI_FUNCTION_CNTRL_M_MEMCS0	0x10
-#define PI_FUNCTION_CNTRL_M_MEMCS1	0x20
-#define PI_FUNCTION_CNTRL_M_DMA		0x80
-
-/* Define the bits in the slot control register. */
-
-#define PI_SLOT_CNTRL_M_RESET		0x04	/* Don't use.       */
-#define PI_SLOT_CNTRL_M_ERROR		0x02	/* Not implemented. */
-#define PI_SLOT_CNTRL_M_ENB		0x01	/* Must be set.     */
-
-/* Define the bits in the burst holdoff register. */
-
-#define PI_BURST_HOLDOFF_M_HOLDOFF	0xFC
-#define PI_BURST_HOLDOFF_M_RESERVED	0x02
-#define PI_BURST_HOLDOFF_M_MEM_MAP	0x01
-
-#define PI_BURST_HOLDOFF_V_HOLDOFF	2
-#define PI_BURST_HOLDOFF_V_RESERVED	1
-#define PI_BURST_HOLDOFF_V_MEM_MAP	0
-
-/* Define the implicit mask of the Memory Address Mask Register.  */
-
-#define PI_MEM_ADD_MASK_M		0x3ff
-
-/*
- * Define the fields in the IO Compare registers.
- * The driver must initialize the slot field with the slot ID shifted by the
- * amount shown below.
- */
-
-#define PI_IO_CMP_V_SLOT		4
-
-/* Define the fields in the Interrupt Channel Configuration and Status reg */
-
-#define PI_CONFIG_STAT_0_M_PEND			0x80
-#define PI_CONFIG_STAT_0_M_RES_1		0x40
-#define PI_CONFIG_STAT_0_M_IREQ_OUT		0x20
-#define PI_CONFIG_STAT_0_M_IREQ_IN		0x10
-#define PI_CONFIG_STAT_0_M_INT_ENB		0x08
-#define PI_CONFIG_STAT_0_M_RES_0		0x04
-#define PI_CONFIG_STAT_0_M_IRQ			0x03
-
-#define PI_CONFIG_STAT_0_V_PEND			7
-#define PI_CONFIG_STAT_0_V_RES_1		6
-#define PI_CONFIG_STAT_0_V_IREQ_OUT		5
-#define PI_CONFIG_STAT_0_V_IREQ_IN		4
-#define PI_CONFIG_STAT_0_V_INT_ENB		3
-#define PI_CONFIG_STAT_0_V_RES_0		2
-#define PI_CONFIG_STAT_0_V_IRQ			0
-
-#define PI_CONFIG_STAT_0_IRQ_K_9		0
-#define PI_CONFIG_STAT_0_IRQ_K_10		1
-#define PI_CONFIG_STAT_0_IRQ_K_11		2
-#define PI_CONFIG_STAT_0_IRQ_K_15		3
-
-/* Define DEC FDDIcontroller/EISA (DEFEA) EISA hardware ID's */
-
-#define DEFEA_PRODUCT_ID	0x0030A310		/* DEC product 300 (no rev)	*/
-#define DEFEA_PROD_ID_1		0x0130A310		/* DEC product 300, rev 1	*/
-#define DEFEA_PROD_ID_2		0x0230A310		/* DEC product 300, rev 2	*/
-#define DEFEA_PROD_ID_3		0x0330A310		/* DEC product 300, rev 3	*/
-#define DEFEA_PROD_ID_4		0x0430A310		/* DEC product 300, rev 4	*/
-
-/**********************************************/
-/* Digital PFI Specification v1.0 Definitions */
-/**********************************************/
-
-/* PCI Configuration Space Constants */
-
-#define PFI_K_LAT_TIMER_DEF			0x88	/* def max master latency timer */
-#define PFI_K_LAT_TIMER_MIN			0x20	/* min max master latency timer */
-#define PFI_K_CSR_MEM_LEN			0x80	/* 128 bytes */
-#define PFI_K_CSR_IO_LEN			0x80	/* 128 bytes */
-#define PFI_K_PKT_MEM_LEN			0x10000	/* 64K bytes */
-
-/* PFI Register Offsets (starting at PDQ Register Base Address) */
-
-#define PFI_K_REG_RESERVED_0		 0X00000038
-#define PFI_K_REG_RESERVED_1		 0X0000003C
-#define PFI_K_REG_MODE_CTRL		 0X00000040
-#define PFI_K_REG_STATUS		 0X00000044
-#define PFI_K_REG_FIFO_WRITE		 0X00000048
-#define PFI_K_REG_FIFO_READ		 0X0000004C
-
-/* PFI Mode Control Register Constants */
-
-#define PFI_MODE_M_RESERVED		 0XFFFFFFF0
-#define PFI_MODE_M_TGT_ABORT_ENB	 0X00000008
-#define PFI_MODE_M_PDQ_INT_ENB		 0X00000004
-#define PFI_MODE_M_PFI_INT_ENB		 0X00000002
-#define PFI_MODE_M_DMA_ENB		 0X00000001
-
-#define PFI_MODE_V_RESERVED		 4
-#define PFI_MODE_V_TGT_ABORT_ENB	 3
-#define PFI_MODE_V_PDQ_INT_ENB		 2
-#define PFI_MODE_V_PFI_INT_ENB		 1
-#define PFI_MODE_V_DMA_ENB		 0
-
-#define PFI_MODE_K_ALL_DISABLE		 0X00000000
-
-/* PFI Status Register Constants */
-
-#define PFI_STATUS_M_RESERVED		 0XFFFFFFC0
-#define PFI_STATUS_M_PFI_ERROR		 0X00000020		/* only valid in rev 1 or later PFI */
-#define PFI_STATUS_M_PDQ_INT		 0X00000010
-#define PFI_STATUS_M_PDQ_DMA_ABORT	 0X00000008
-#define PFI_STATUS_M_FIFO_FULL		 0X00000004
-#define PFI_STATUS_M_FIFO_EMPTY		 0X00000002
-#define PFI_STATUS_M_DMA_IN_PROGRESS	 0X00000001
-
-#define PFI_STATUS_V_RESERVED		 6
-#define PFI_STATUS_V_PFI_ERROR		 5			/* only valid in rev 1 or later PFI */
-#define PFI_STATUS_V_PDQ_INT		 4
-#define PFI_STATUS_V_PDQ_DMA_ABORT	 3
-#define PFI_STATUS_V_FIFO_FULL		 2
-#define PFI_STATUS_V_FIFO_EMPTY		 1
-#define PFI_STATUS_V_DMA_IN_PROGRESS 0
-
-#define DFX_FC_PRH2_PRH1_PRH0		0x54003820	/* Packet Request Header bytes + FC */
-#define DFX_PRH0_BYTE			0x20		/* Packet Request Header byte 0 */
-#define DFX_PRH1_BYTE			0x38		/* Packet Request Header byte 1 */
-#define DFX_PRH2_BYTE			0x00		/* Packet Request Header byte 2 */
-
-/* Driver routine status (return) codes */
-
-#define DFX_K_SUCCESS			0			/* routine succeeded */
-#define DFX_K_FAILURE			1			/* routine failed */
-#define DFX_K_OUTSTATE			2			/* bad state for command */
-#define DFX_K_HW_TIMEOUT		3			/* command timed out */
-
-/* Define LLC host receive buffer min/max/default values */
-
-#define RCV_BUFS_MIN	2					/* minimum pre-allocated receive buffers */
-#define RCV_BUFS_MAX	32					/* maximum pre-allocated receive buffers */
-#define RCV_BUFS_DEF	8					/* default pre-allocated receive buffers */
-
-/* Define offsets into FDDI LLC or SMT receive frame buffers - used when indicating frames */
-
-#define RCV_BUFF_K_DESCR	0				/* four byte FMC descriptor */
-#define RCV_BUFF_K_PADDING	4				/* three null bytes */
-#define RCV_BUFF_K_FC		7				/* one byte frame control */
-#define RCV_BUFF_K_DA		8				/* six byte destination address */
-#define RCV_BUFF_K_SA		14				/* six byte source address */
-#define RCV_BUFF_K_DATA		20				/* offset to start of packet data */
-
-/* Define offsets into FDDI LLC transmit frame buffers - used when sending frames */
-
-#define XMT_BUFF_K_FC		0				/* one byte frame control */
-#define XMT_BUFF_K_DA		1				/* six byte destination address */
-#define XMT_BUFF_K_SA		7				/* six byte source address */
-#define XMT_BUFF_K_DATA		13				/* offset to start of packet data */
-
-/* Macro for checking a "value" is within a specific range */
-
-#define IN_RANGE(value,low,high) ((value >= low) && (value <= high))
-
-/* Only execute special print call when debug driver was built */
-
-#ifdef DEFXX_DEBUG
-#define DBG_printk(args...) printk(## args)
-#else
-#define DBG_printk(args...)
-#endif
-
-/* Define constants for masking/unmasking interrupts */
-
-#define DFX_MASK_INTERRUPTS		1
-#define DFX_UNMASK_INTERRUPTS		0
-
-/* Define structure for driver transmit descriptor block */
-
-typedef struct
-	{
-	struct sk_buff	*p_skb;					/* ptr to skb */
-	} XMT_DRIVER_DESCR;
-
-typedef struct DFX_board_tag
-	{
-	/* Keep virtual and physical pointers to locked, physically contiguous memory */
-
-	char				*kmalloced;					/* pci_free_consistent this on unload */
-	dma_addr_t			kmalloced_dma;
-	/* DMA handle for the above */
-	PI_DESCR_BLOCK			*descr_block_virt;				/* PDQ descriptor block virt address */
-	dma_addr_t			descr_block_phys;				/* PDQ descriptor block phys address */
-	PI_DMA_CMD_REQ			*cmd_req_virt;					/* Command request buffer virt address */
-	dma_addr_t			cmd_req_phys;					/* Command request buffer phys address */
-	PI_DMA_CMD_RSP			*cmd_rsp_virt;					/* Command response buffer virt address */
-	dma_addr_t			cmd_rsp_phys;					/* Command response buffer phys address */
-	char				*rcv_block_virt;				/* LLC host receive queue buf blk virt */
-	dma_addr_t			rcv_block_phys;					/* LLC host receive queue buf blk phys */
-	PI_CONSUMER_BLOCK		*cons_block_virt;				/* PDQ consumer block virt address */
-	dma_addr_t			cons_block_phys;				/* PDQ consumer block phys address */
-
-	/* Keep local copies of Type 1 and Type 2 register data */
-
-	PI_TYPE_1_PROD_REG		cmd_req_reg;					/* Command Request register */
-	PI_TYPE_1_PROD_REG		cmd_rsp_reg;					/* Command Response register */
-	PI_TYPE_2_PROD_REG		rcv_xmt_reg;					/* Type 2 (RCV/XMT) register */
-
-	/* Storage for unicast and multicast address entries in adapter CAM */
-
-	u8				uc_table[1*FDDI_K_ALEN];
-	u32				uc_count;						/* number of unicast addresses */
-	u8				mc_table[PI_CMD_ADDR_FILTER_K_SIZE*FDDI_K_ALEN];
-	u32				mc_count;						/* number of multicast addresses */
-
-	/* Current packet filter settings */
-
-	u32				ind_group_prom;					/* LLC individual & group frame prom mode */
-	u32				group_prom;					/* LLC group (multicast) frame prom mode */
-
-	/* Link available flag needed to determine whether to drop outgoing packet requests */
-
-	u32				link_available;					/* is link available? */
-
-	/* Resources to indicate reset type when resetting adapter */
-
-	u32				reset_type;					/* skip or rerun diagnostics */
-
-	/* Store pointers to receive buffers for queue processing code */
-
-	char				*p_rcv_buff_va[PI_RCV_DATA_K_NUM_ENTRIES];
-
-	/* Store pointers to transmit buffers for transmit completion code */
-
-	XMT_DRIVER_DESCR		xmt_drv_descr_blk[PI_XMT_DATA_K_NUM_ENTRIES];
-
-	/* Transmit spinlocks */
-
-	spinlock_t			lock;
-
-	/* Store device, bus-specific, and parameter information for this adapter */
-
-	struct net_device		*dev;						/* pointer to device structure */
-	union {
-		void __iomem *mem;
-		int port;
-	} base;										/* base address */
-	struct device			*bus_dev;
-	u32				full_duplex_enb;				/* FDDI Full Duplex enable (1 == on, 2 == off) */
-	u32				req_ttrt;					/* requested TTRT value (in 80ns units) */
-	u32				burst_size;					/* adapter burst size (enumerated) */
-	u32				rcv_bufs_to_post;				/* receive buffers to post for LLC host queue */
-	u8				factory_mac_addr[FDDI_K_ALEN];			/* factory (on-board) MAC address */
-
-	/* Common FDDI statistics structure and private counters */
-
-	struct fddi_statistics	stats;
-
-	u32				rcv_discards;
-	u32				rcv_crc_errors;
-	u32				rcv_frame_status_errors;
-	u32				rcv_length_errors;
-	u32				rcv_total_frames;
-	u32				rcv_multicast_frames;
-	u32				rcv_total_bytes;
-
-	u32				xmt_discards;
-	u32				xmt_length_errors;
-	u32				xmt_total_frames;
-	u32				xmt_total_bytes;
-	} DFX_board_t;
-
-#endif	/* #ifndef _DEFXX_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/depca.c linux-libre-3.2-gnu/drivers/net/depca.c
--- linux-libre-3.1-gnu/drivers/net/depca.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/depca.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2111 +0,0 @@
-/*  depca.c: A DIGITAL DEPCA & EtherWORKS ethernet driver for linux.
-
-    Written 1994, 1995 by David C. Davies.
-
-
-                      Copyright 1994 David C. Davies
-		                   and
-			 United States Government
-	 (as represented by the Director, National Security Agency).
-
-               Copyright 1995  Digital Equipment Corporation.
-
-
-    This software may be used and distributed according to the terms of
-    the GNU General Public License, incorporated herein by reference.
-
-    This driver is written for the Digital Equipment Corporation series
-    of DEPCA and EtherWORKS ethernet cards:
-
-        DEPCA       (the original)
-    	DE100
-    	DE101
-	DE200 Turbo
-	DE201 Turbo
-	DE202 Turbo (TP BNC)
-	DE210
-	DE422       (EISA)
-
-    The  driver has been tested on DE100, DE200 and DE202 cards  in  a
-    relatively busy network. The DE422 has been tested a little.
-
-    This  driver will NOT work   for the DE203,  DE204  and DE205 series  of
-    cards,  since they have  a  new custom ASIC in   place of the AMD  LANCE
-    chip.  See the 'ewrk3.c'   driver in the  Linux  source tree for running
-    those cards.
-
-    I have benchmarked the driver with a  DE100 at 595kB/s to (542kB/s from)
-    a DECstation 5000/200.
-
-    The author may be reached at davies@maniac.ultranet.com
-
-    =========================================================================
-
-    The  driver was originally based  on   the 'lance.c' driver from  Donald
-    Becker   which  is included with  the  standard  driver distribution for
-    linux.  V0.4  is  a complete  re-write  with only  the kernel  interface
-    remaining from the original code.
-
-    1) Lance.c code in /linux/drivers/net/
-    2) "Ethernet/IEEE 802.3 Family. 1992 World Network Data Book/Handbook",
-       AMD, 1992 [(800) 222-9323].
-    3) "Am79C90 CMOS Local Area Network Controller for Ethernet (C-LANCE)",
-       AMD, Pub. #17881, May 1993.
-    4) "Am79C960 PCnet-ISA(tm), Single-Chip Ethernet Controller for ISA",
-       AMD, Pub. #16907, May 1992
-    5) "DEC EtherWORKS LC Ethernet Controller Owners Manual",
-       Digital Equipment corporation, 1990, Pub. #EK-DE100-OM.003
-    6) "DEC EtherWORKS Turbo Ethernet Controller Owners Manual",
-       Digital Equipment corporation, 1990, Pub. #EK-DE200-OM.003
-    7) "DEPCA Hardware Reference Manual", Pub. #EK-DEPCA-PR
-       Digital Equipment Corporation, 1989
-    8) "DEC EtherWORKS Turbo_(TP BNC) Ethernet Controller Owners Manual",
-       Digital Equipment corporation, 1991, Pub. #EK-DE202-OM.001
-
-
-    Peter Bauer's depca.c (V0.5) was referred to when debugging V0.1 of this
-    driver.
-
-    The original DEPCA  card requires that the  ethernet ROM address counter
-    be enabled to count and has an 8 bit NICSR.  The ROM counter enabling is
-    only  done when a  0x08 is read as the  first address octet (to minimise
-    the chances  of writing over some  other hardware's  I/O register).  The
-    NICSR accesses   have been changed  to  byte accesses  for all the cards
-    supported by this driver, since there is only one  useful bit in the MSB
-    (remote boot timeout) and it  is not used.  Also, there  is a maximum of
-    only 48kB network  RAM for this  card.  My thanks  to Torbjorn Lindh for
-    help debugging all this (and holding my feet to  the fire until I got it
-    right).
-
-    The DE200  series  boards have  on-board 64kB  RAM for  use  as a shared
-    memory network  buffer. Only the DE100  cards make use  of a  2kB buffer
-    mode which has not  been implemented in  this driver (only the 32kB  and
-    64kB modes are supported [16kB/48kB for the original DEPCA]).
-
-    At the most only 2 DEPCA cards can  be supported on  the ISA bus because
-    there is only provision  for two I/O base addresses  on each card (0x300
-    and 0x200). The I/O address is detected by searching for a byte sequence
-    in the Ethernet station address PROM at the expected I/O address for the
-    Ethernet  PROM.   The shared memory  base   address  is 'autoprobed'  by
-    looking  for the self  test PROM  and detecting the  card name.   When a
-    second  DEPCA is  detected,  information  is   placed in the   base_addr
-    variable of the  next device structure (which  is created if necessary),
-    thus  enabling ethif_probe  initialization  for the device.  More than 2
-    EISA cards can  be  supported, but  care will  be  needed assigning  the
-    shared memory to ensure that each slot has the  correct IRQ, I/O address
-    and shared memory address assigned.
-
-    ************************************************************************
-
-    NOTE: If you are using two  ISA DEPCAs, it is  important that you assign
-    the base memory addresses correctly.   The  driver autoprobes I/O  0x300
-    then 0x200.  The  base memory address for  the first device must be less
-    than that of the second so that the auto probe will correctly assign the
-    I/O and memory addresses on the same card.  I can't think of a way to do
-    this unambiguously at the moment, since there is nothing on the cards to
-    tie I/O and memory information together.
-
-    I am unable  to  test  2 cards   together for now,    so this  code   is
-    unchecked. All reports, good or bad, are welcome.
-
-    ************************************************************************
-
-    The board IRQ   setting must be  at an  unused IRQ which  is auto-probed
-    using Donald Becker's autoprobe routines. DEPCA and DE100 board IRQs are
-    {2,3,4,5,7}, whereas the  DE200 is at {5,9,10,11,15}.  Note that IRQ2 is
-    really IRQ9 in machines with 16 IRQ lines.
-
-    No 16MB memory  limitation should exist with this  driver as DMA is  not
-    used and the common memory area is in low memory on the network card (my
-    current system has 20MB and I've not had problems yet).
-
-    The ability to load this driver as a loadable module has been added. To
-    utilise this ability, you have to do <8 things:
-
-    0) have a copy of the loadable modules code installed on your system.
-    1) copy depca.c from the  /linux/drivers/net directory to your favourite
-    temporary directory.
-    2) if you wish, edit the  source code near  line 1530 to reflect the I/O
-    address and IRQ you're using (see also 5).
-    3) compile  depca.c, but include -DMODULE in  the command line to ensure
-    that the correct bits are compiled (see end of source code).
-    4) if you are wanting to add a new  card, goto 5. Otherwise, recompile a
-    kernel with the depca configuration turned off and reboot.
-    5) insmod depca.o [irq=7] [io=0x200] [mem=0xd0000] [adapter_name=DE100]
-       [Alan Cox: Changed the code to allow command line irq/io assignments]
-       [Dave Davies: Changed the code to allow command line mem/name
-                                                                assignments]
-    6) run the net startup bits for your eth?? interface manually
-    (usually /etc/rc.inet[12] at boot time).
-    7) enjoy!
-
-    Note that autoprobing is not allowed in loadable modules - the system is
-    already up and running and you're messing with interrupts.
-
-    To unload a module, turn off the associated interface
-    'ifconfig eth?? down' then 'rmmod depca'.
-
-    To assign a base memory address for the shared memory  when running as a
-    loadable module, see 5 above.  To include the adapter  name (if you have
-    no PROM  but know the card name)  also see 5  above. Note that this last
-    option  will not work  with kernel  built-in  depca's.
-
-    The shared memory assignment for a loadable module  makes sense to avoid
-    the 'memory autoprobe' picking the wrong shared memory  (for the case of
-    2 depca's in a PC).
-
-    ************************************************************************
-    Support for MCA EtherWORKS cards added 11-3-98.
-    Verified to work with up to 2 DE212 cards in a system (although not
-      fully stress-tested).
-
-    Currently known bugs/limitations:
-
-    Note:  with the MCA stuff as a module, it trusts the MCA configuration,
-           not the command line for IRQ and memory address.  You can
-           specify them if you want, but it will throw your values out.
-           You still have to pass the IO address it was configured as
-           though.
-
-    ************************************************************************
-    TO DO:
-    ------
-
-
-    Revision History
-    ----------------
-
-    Version   Date        Description
-
-      0.1     25-jan-94   Initial writing.
-      0.2     27-jan-94   Added LANCE TX hardware buffer chaining.
-      0.3      1-feb-94   Added multiple DEPCA support.
-      0.31     4-feb-94   Added DE202 recognition.
-      0.32    19-feb-94   Tidy up. Improve multi-DEPCA support.
-      0.33    25-feb-94   Fix DEPCA ethernet ROM counter enable.
-                          Add jabber packet fix from murf@perftech.com
-			  and becker@super.org
-      0.34     7-mar-94   Fix DEPCA max network memory RAM & NICSR access.
-      0.35     8-mar-94   Added DE201 recognition. Tidied up.
-      0.351   30-apr-94   Added EISA support. Added DE422 recognition.
-      0.36    16-may-94   DE422 fix released.
-      0.37    22-jul-94   Added MODULE support
-      0.38    15-aug-94   Added DBR ROM switch in depca_close().
-                          Multi DEPCA bug fix.
-      0.38axp 15-sep-94   Special version for Alpha AXP Linux V1.0.
-      0.381   12-dec-94   Added DE101 recognition, fix multicast bug.
-      0.382    9-feb-95   Fix recognition bug reported by <bkm@star.rl.ac.uk>.
-      0.383   22-feb-95   Fix for conflict with VESA SCSI reported by
-                          <stromain@alf.dec.com>
-      0.384   17-mar-95   Fix a ring full bug reported by <bkm@star.rl.ac.uk>
-      0.385    3-apr-95   Fix a recognition bug reported by
-                                                <ryan.niemi@lastfrontier.com>
-      0.386   21-apr-95   Fix the last fix...sorry, must be galloping senility
-      0.40    25-May-95   Rewrite for portability & updated.
-                          ALPHA support from <jestabro@amt.tay1.dec.com>
-      0.41    26-Jun-95   Added verify_area() calls in depca_ioctl() from
-                          suggestion by <heiko@colossus.escape.de>
-      0.42    27-Dec-95   Add 'mem' shared memory assignment for loadable
-                          modules.
-                          Add 'adapter_name' for loadable modules when no PROM.
-			  Both above from a suggestion by
-			  <pchen@woodruffs121.residence.gatech.edu>.
-			  Add new multicasting code.
-      0.421   22-Apr-96	  Fix alloc_device() bug <jari@markkus2.fimr.fi>
-      0.422   29-Apr-96	  Fix depca_hw_init() bug <jari@markkus2.fimr.fi>
-      0.423    7-Jun-96   Fix module load bug <kmg@barco.be>
-      0.43    16-Aug-96   Update alloc_device() to conform to de4x5.c
-      0.44     1-Sep-97   Fix *_probe() to test check_region() first - bug
-                           reported by <mmogilvi@elbert.uccs.edu>
-      0.45     3-Nov-98   Added support for MCA EtherWORKS (DE210/DE212) cards
-                           by <tymm@computer.org>
-      0.451    5-Nov-98   Fixed mca stuff cuz I'm a dummy. <tymm@computer.org>
-      0.5     14-Nov-98   Re-spin for 2.1.x kernels.
-      0.51    27-Jun-99   Correct received packet length for CRC from
-                           report by <worm@dkik.dk>
-      0.52    16-Oct-00   Fixes for 2.3 io memory accesses
-                          Fix show-stopper (ints left masked) in depca_interrupt
-			   by <peterd@pnd-pc.demon.co.uk>
-      0.53    12-Jan-01	  Release resources on failure, bss tidbits
-      			   by acme@conectiva.com.br
-      0.54    08-Nov-01	  use library crc32 functions
-      			   by Matt_Domsch@dell.com
-      0.55    01-Mar-03   Use EISA/sysfs framework <maz@wild-wind.fr.eu.org>
-
-    =========================================================================
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/crc32.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/time.h>
-#include <linux/types.h>
-#include <linux/unistd.h>
-#include <linux/ctype.h>
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-#include <linux/bitops.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#ifdef CONFIG_MCA
-#include <linux/mca.h>
-#endif
-
-#ifdef CONFIG_EISA
-#include <linux/eisa.h>
-#endif
-
-#include "depca.h"
-
-static char version[] __initdata = "depca.c:v0.53 2001/1/12 davies@maniac.ultranet.com\n";
-
-#ifdef DEPCA_DEBUG
-static int depca_debug = DEPCA_DEBUG;
-#else
-static int depca_debug = 1;
-#endif
-
-#define DEPCA_NDA 0xffe0	/* No Device Address */
-
-#define TX_TIMEOUT (1*HZ)
-
-/*
-** Ethernet PROM defines
-*/
-#define PROBE_LENGTH    32
-#define ETH_PROM_SIG    0xAA5500FFUL
-
-/*
-** Set the number of Tx and Rx buffers. Ensure that the memory requested
-** here is <= to the amount of shared memory set up by the board switches.
-** The number of descriptors MUST BE A POWER OF 2.
-**
-** total_memory = NUM_RX_DESC*(8+RX_BUFF_SZ) + NUM_TX_DESC*(8+TX_BUFF_SZ)
-*/
-#define NUM_RX_DESC     8	/* Number of RX descriptors */
-#define NUM_TX_DESC     8	/* Number of TX descriptors */
-#define RX_BUFF_SZ	1536	/* Buffer size for each Rx buffer */
-#define TX_BUFF_SZ	1536	/* Buffer size for each Tx buffer */
-
-/*
-** EISA bus defines
-*/
-#define DEPCA_EISA_IO_PORTS 0x0c00	/* I/O port base address, slot 0 */
-
-/*
-** ISA Bus defines
-*/
-#define DEPCA_RAM_BASE_ADDRESSES {0xc0000,0xd0000,0xe0000,0x00000}
-#define DEPCA_TOTAL_SIZE 0x10
-
-static struct {
-	u_long iobase;
-	struct platform_device *device;
-} depca_io_ports[] = {
-	{ 0x300, NULL },
-	{ 0x200, NULL },
-	{ 0    , NULL },
-};
-
-/*
-** Name <-> Adapter mapping
-*/
-#define DEPCA_SIGNATURE {"DEPCA",\
-			 "DE100","DE101",\
-                         "DE200","DE201","DE202",\
-			 "DE210","DE212",\
-                         "DE422",\
-                         ""}
-
-static char* __initdata depca_signature[] = DEPCA_SIGNATURE;
-
-enum depca_type {
-	DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown
-};
-
-static char depca_string[] = "depca";
-
-static int depca_device_remove (struct device *device);
-
-#ifdef CONFIG_EISA
-static struct eisa_device_id depca_eisa_ids[] = {
-	{ "DEC4220", de422 },
-	{ "" }
-};
-MODULE_DEVICE_TABLE(eisa, depca_eisa_ids);
-
-static int depca_eisa_probe  (struct device *device);
-
-static struct eisa_driver depca_eisa_driver = {
-	.id_table = depca_eisa_ids,
-	.driver   = {
-		.name    = depca_string,
-		.probe   = depca_eisa_probe,
-		.remove  = __devexit_p (depca_device_remove)
-	}
-};
-#endif
-
-#ifdef CONFIG_MCA
-/*
-** Adapter ID for the MCA EtherWORKS DE210/212 adapter
-*/
-#define DE210_ID 0x628d
-#define DE212_ID 0x6def
-
-static short depca_mca_adapter_ids[] = {
-	DE210_ID,
-	DE212_ID,
-	0x0000
-};
-
-static char *depca_mca_adapter_name[] = {
-	"DEC EtherWORKS MC Adapter (DE210)",
-	"DEC EtherWORKS MC Adapter (DE212)",
-	NULL
-};
-
-static enum depca_type depca_mca_adapter_type[] = {
-	de210,
-	de212,
-	0
-};
-
-static int depca_mca_probe (struct device *);
-
-static struct mca_driver depca_mca_driver = {
-	.id_table = depca_mca_adapter_ids,
-	.driver   = {
-		.name   = depca_string,
-		.bus    = &mca_bus_type,
-		.probe  = depca_mca_probe,
-		.remove = __devexit_p(depca_device_remove),
-	},
-};
-#endif
-
-static int depca_isa_probe (struct platform_device *);
-
-static int __devexit depca_isa_remove(struct platform_device *pdev)
-{
-	return depca_device_remove(&pdev->dev);
-}
-
-static struct platform_driver depca_isa_driver = {
-	.probe  = depca_isa_probe,
-	.remove = __devexit_p(depca_isa_remove),
-	.driver	= {
-		.name   = depca_string,
-	},
-};
-
-/*
-** Miscellaneous info...
-*/
-#define DEPCA_STRLEN 16
-
-/*
-** Memory Alignment. Each descriptor is 4 longwords long. To force a
-** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and
-** DESC_ALIGN. DEPCA_ALIGN aligns the start address of the private memory area
-** and hence the RX descriptor ring's first entry.
-*/
-#define DEPCA_ALIGN4      ((u_long)4 - 1)	/* 1 longword align */
-#define DEPCA_ALIGN8      ((u_long)8 - 1)	/* 2 longword (quadword) align */
-#define DEPCA_ALIGN         DEPCA_ALIGN8	/* Keep the LANCE happy... */
-
-/*
-** The DEPCA Rx and Tx ring descriptors.
-*/
-struct depca_rx_desc {
-	volatile s32 base;
-	s16 buf_length;		/* This length is negative 2's complement! */
-	s16 msg_length;		/* This length is "normal". */
-};
-
-struct depca_tx_desc {
-	volatile s32 base;
-	s16 length;		/* This length is negative 2's complement! */
-	s16 misc;		/* Errors and TDR info */
-};
-
-#define LA_MASK 0x0000ffff	/* LANCE address mask for mapping network RAM
-				   to LANCE memory address space */
-
-/*
-** The Lance initialization block, described in databook, in common memory.
-*/
-struct depca_init {
-	u16 mode;		/* Mode register */
-	u8 phys_addr[ETH_ALEN];	/* Physical ethernet address */
-	u8 mcast_table[8];	/* Multicast Hash Table. */
-	u32 rx_ring;		/* Rx ring base pointer & ring length */
-	u32 tx_ring;		/* Tx ring base pointer & ring length */
-};
-
-#define DEPCA_PKT_STAT_SZ 16
-#define DEPCA_PKT_BIN_SZ  128	/* Should be >=100 unless you
-				   increase DEPCA_PKT_STAT_SZ */
-struct depca_private {
-	char adapter_name[DEPCA_STRLEN];	/* /proc/ioports string                  */
-	enum depca_type adapter;		/* Adapter type */
-	enum {
-                DEPCA_BUS_MCA = 1,
-                DEPCA_BUS_ISA,
-                DEPCA_BUS_EISA,
-        } depca_bus;	        /* type of bus */
-	struct depca_init init_block;	/* Shadow Initialization block            */
-/* CPU address space fields */
-	struct depca_rx_desc __iomem *rx_ring;	/* Pointer to start of RX descriptor ring */
-	struct depca_tx_desc __iomem *tx_ring;	/* Pointer to start of TX descriptor ring */
-	void __iomem *rx_buff[NUM_RX_DESC];	/* CPU virt address of sh'd memory buffs  */
-	void __iomem *tx_buff[NUM_TX_DESC];	/* CPU virt address of sh'd memory buffs  */
-	void __iomem *sh_mem;	/* CPU mapped virt address of device RAM  */
-	u_long mem_start;	/* Bus address of device RAM (before remap) */
-	u_long mem_len;		/* device memory size */
-/* Device address space fields */
-	u_long device_ram_start;	/* Start of RAM in device addr space      */
-/* Offsets used in both address spaces */
-	u_long rx_ring_offset;	/* Offset from start of RAM to rx_ring    */
-	u_long tx_ring_offset;	/* Offset from start of RAM to tx_ring    */
-	u_long buffs_offset;	/* LANCE Rx and Tx buffers start address. */
-/* Kernel-only (not device) fields */
-	int rx_new, tx_new;	/* The next free ring entry               */
-	int rx_old, tx_old;	/* The ring entries to be free()ed.       */
-	spinlock_t lock;
-	struct {		/* Private stats counters                 */
-		u32 bins[DEPCA_PKT_STAT_SZ];
-		u32 unicast;
-		u32 multicast;
-		u32 broadcast;
-		u32 excessive_collisions;
-		u32 tx_underruns;
-		u32 excessive_underruns;
-	} pktStats;
-	int txRingMask;		/* TX ring mask                           */
-	int rxRingMask;		/* RX ring mask                           */
-	s32 rx_rlen;		/* log2(rxRingMask+1) for the descriptors */
-	s32 tx_rlen;		/* log2(txRingMask+1) for the descriptors */
-};
-
-/*
-** The transmit ring full condition is described by the tx_old and tx_new
-** pointers by:
-**    tx_old            = tx_new    Empty ring
-**    tx_old            = tx_new+1  Full ring
-**    tx_old+txRingMask = tx_new    Full ring  (wrapped condition)
-*/
-#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
-			 lp->tx_old+lp->txRingMask-lp->tx_new:\
-                         lp->tx_old               -lp->tx_new-1)
-
-/*
-** Public Functions
-*/
-static int depca_open(struct net_device *dev);
-static netdev_tx_t depca_start_xmit(struct sk_buff *skb,
-				    struct net_device *dev);
-static irqreturn_t depca_interrupt(int irq, void *dev_id);
-static int depca_close(struct net_device *dev);
-static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static void depca_tx_timeout(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
-
-/*
-** Private functions
-*/
-static void depca_init_ring(struct net_device *dev);
-static int depca_rx(struct net_device *dev);
-static int depca_tx(struct net_device *dev);
-
-static void LoadCSRs(struct net_device *dev);
-static int InitRestartDepca(struct net_device *dev);
-static int DepcaSignature(char *name, u_long paddr);
-static int DevicePresent(u_long ioaddr);
-static int get_hw_addr(struct net_device *dev);
-static void SetMulticastFilter(struct net_device *dev);
-static int load_packet(struct net_device *dev, struct sk_buff *skb);
-static void depca_dbg_open(struct net_device *dev);
-
-static u_char de1xx_irq[] __initdata = { 2, 3, 4, 5, 7, 9, 0 };
-static u_char de2xx_irq[] __initdata = { 5, 9, 10, 11, 15, 0 };
-static u_char de422_irq[] __initdata = { 5, 9, 10, 11, 0 };
-static u_char *depca_irq;
-
-static int irq;
-static int io;
-static char *adapter_name;
-static int mem;			/* For loadable module assignment
-				   use insmod mem=0x????? .... */
-module_param (irq, int, 0);
-module_param (io, int, 0);
-module_param (adapter_name, charp, 0);
-module_param (mem, int, 0);
-MODULE_PARM_DESC(irq, "DEPCA IRQ number");
-MODULE_PARM_DESC(io, "DEPCA I/O base address");
-MODULE_PARM_DESC(adapter_name, "DEPCA adapter name");
-MODULE_PARM_DESC(mem, "DEPCA shared memory address");
-MODULE_LICENSE("GPL");
-
-/*
-** Miscellaneous defines...
-*/
-#define STOP_DEPCA \
-    outw(CSR0, DEPCA_ADDR);\
-    outw(STOP, DEPCA_DATA)
-
-static const struct net_device_ops depca_netdev_ops = {
-	.ndo_open 		= depca_open,
-	.ndo_start_xmit 	= depca_start_xmit,
-	.ndo_stop 		= depca_close,
-	.ndo_set_multicast_list = set_multicast_list,
-	.ndo_do_ioctl 		= depca_ioctl,
-	.ndo_tx_timeout 	= depca_tx_timeout,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-static int __init depca_hw_init (struct net_device *dev, struct device *device)
-{
-	struct depca_private *lp;
-	int i, j, offset, netRAM, mem_len, status = 0;
-	s16 nicsr;
-	u_long ioaddr;
-	u_long mem_start;
-
-	/*
-	 * We are now supposed to enter this function with the
-	 * following fields filled with proper values :
-	 *
-	 * dev->base_addr
-	 * lp->mem_start
-	 * lp->depca_bus
-	 * lp->adapter
-	 *
-	 * dev->irq can be set if known from device configuration (on
-	 * MCA or EISA) or module option. Otherwise, it will be auto
-	 * detected.
-	 */
-
-	ioaddr = dev->base_addr;
-
-	STOP_DEPCA;
-
-	nicsr = inb(DEPCA_NICSR);
-	nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM);
-	outb(nicsr, DEPCA_NICSR);
-
-	if (inw(DEPCA_DATA) != STOP) {
-		return -ENXIO;
-	}
-
-	lp = netdev_priv(dev);
-	mem_start = lp->mem_start;
-
-	if (!mem_start || lp->adapter < DEPCA || lp->adapter >=unknown)
-		return -ENXIO;
-
-	printk("%s: %s at 0x%04lx",
-	       dev_name(device), depca_signature[lp->adapter], ioaddr);
-
-	switch (lp->depca_bus) {
-#ifdef CONFIG_MCA
-	case DEPCA_BUS_MCA:
-		printk(" (MCA slot %d)", to_mca_device(device)->slot + 1);
-		break;
-#endif
-
-#ifdef CONFIG_EISA
-	case DEPCA_BUS_EISA:
-		printk(" (EISA slot %d)", to_eisa_device(device)->slot);
-		break;
-#endif
-
-	case DEPCA_BUS_ISA:
-		break;
-
-	default:
-		printk("Unknown DEPCA bus %d\n", lp->depca_bus);
-		return -ENXIO;
-	}
-
-	printk(", h/w address ");
-	status = get_hw_addr(dev);
-	printk("%pM", dev->dev_addr);
-	if (status != 0) {
-		printk("      which has an Ethernet PROM CRC error.\n");
-		return -ENXIO;
-	}
-
-	/* Set up the maximum amount of network RAM(kB) */
-	netRAM = ((lp->adapter != DEPCA) ? 64 : 48);
-	if ((nicsr & _128KB) && (lp->adapter == de422))
-		netRAM = 128;
-
-	/* Shared Memory Base Address */
-	if (nicsr & BUF) {
-		nicsr &= ~BS;	/* DEPCA RAM in top 32k */
-		netRAM -= 32;
-
-		/* Only EISA/ISA needs start address to be re-computed */
-		if (lp->depca_bus != DEPCA_BUS_MCA)
-			mem_start += 0x8000;
-	}
-
-	if ((mem_len = (NUM_RX_DESC * (sizeof(struct depca_rx_desc) + RX_BUFF_SZ) + NUM_TX_DESC * (sizeof(struct depca_tx_desc) + TX_BUFF_SZ) + sizeof(struct depca_init)))
-	    > (netRAM << 10)) {
-		printk(",\n       requests %dkB RAM: only %dkB is available!\n", (mem_len >> 10), netRAM);
-		return -ENXIO;
-	}
-
-	printk(",\n      has %dkB RAM at 0x%.5lx", netRAM, mem_start);
-
-	/* Enable the shadow RAM. */
-	if (lp->adapter != DEPCA) {
-		nicsr |= SHE;
-		outb(nicsr, DEPCA_NICSR);
-	}
-
-	spin_lock_init(&lp->lock);
-	sprintf(lp->adapter_name, "%s (%s)",
-		depca_signature[lp->adapter], dev_name(device));
-	status = -EBUSY;
-
-	/* Initialisation Block */
-	if (!request_mem_region (mem_start, mem_len, lp->adapter_name)) {
-		printk(KERN_ERR "depca: cannot request ISA memory, aborting\n");
-		goto out_priv;
-	}
-
-	status = -EIO;
-	lp->sh_mem = ioremap(mem_start, mem_len);
-	if (lp->sh_mem == NULL) {
-		printk(KERN_ERR "depca: cannot remap ISA memory, aborting\n");
-		goto out1;
-	}
-
-	lp->mem_start = mem_start;
-	lp->mem_len   = mem_len;
-	lp->device_ram_start = mem_start & LA_MASK;
-
-	offset = 0;
-	offset += sizeof(struct depca_init);
-
-	/* Tx & Rx descriptors (aligned to a quadword boundary) */
-	offset = (offset + DEPCA_ALIGN) & ~DEPCA_ALIGN;
-	lp->rx_ring = lp->sh_mem + offset;
-	lp->rx_ring_offset = offset;
-
-	offset += (sizeof(struct depca_rx_desc) * NUM_RX_DESC);
-	lp->tx_ring = lp->sh_mem + offset;
-	lp->tx_ring_offset = offset;
-
-	offset += (sizeof(struct depca_tx_desc) * NUM_TX_DESC);
-
-	lp->buffs_offset = offset;
-
-	/* Finish initialising the ring information. */
-	lp->rxRingMask = NUM_RX_DESC - 1;
-	lp->txRingMask = NUM_TX_DESC - 1;
-
-	/* Calculate Tx/Rx RLEN size for the descriptors. */
-	for (i = 0, j = lp->rxRingMask; j > 0; i++) {
-		j >>= 1;
-	}
-	lp->rx_rlen = (s32) (i << 29);
-	for (i = 0, j = lp->txRingMask; j > 0; i++) {
-		j >>= 1;
-	}
-	lp->tx_rlen = (s32) (i << 29);
-
-	/* Load the initialisation block */
-	depca_init_ring(dev);
-
-	/* Initialise the control and status registers */
-	LoadCSRs(dev);
-
-	/* Enable DEPCA board interrupts for autoprobing */
-	nicsr = ((nicsr & ~IM) | IEN);
-	outb(nicsr, DEPCA_NICSR);
-
-	/* To auto-IRQ we enable the initialization-done and DMA err,
-	   interrupts. For now we will always get a DMA error. */
-	if (dev->irq < 2) {
-		unsigned char irqnum;
-		unsigned long irq_mask, delay;
-
-		irq_mask = probe_irq_on();
-
-		/* Assign the correct irq list */
-		switch (lp->adapter) {
-		case DEPCA:
-		case de100:
-		case de101:
-			depca_irq = de1xx_irq;
-			break;
-		case de200:
-		case de201:
-		case de202:
-		case de210:
-		case de212:
-			depca_irq = de2xx_irq;
-			break;
-		case de422:
-			depca_irq = de422_irq;
-			break;
-
-		default:
-			break;	/* Not reached */
-		}
-
-		/* Trigger an initialization just for the interrupt. */
-		outw(INEA | INIT, DEPCA_DATA);
-
-		delay = jiffies + HZ/50;
-		while (time_before(jiffies, delay))
-			yield();
-
-		irqnum = probe_irq_off(irq_mask);
-
-		status = -ENXIO;
-		if (!irqnum) {
-			printk(" and failed to detect IRQ line.\n");
-			goto out2;
-		} else {
-			for (dev->irq = 0, i = 0; (depca_irq[i]) && (!dev->irq); i++)
-				if (irqnum == depca_irq[i]) {
-					dev->irq = irqnum;
-					printk(" and uses IRQ%d.\n", dev->irq);
-				}
-
-			if (!dev->irq) {
-				printk(" but incorrect IRQ line detected.\n");
-				goto out2;
-			}
-		}
-	} else {
-		printk(" and assigned IRQ%d.\n", dev->irq);
-	}
-
-	if (depca_debug > 1) {
-		printk(version);
-	}
-
-	/* The DEPCA-specific entries in the device structure. */
-	dev->netdev_ops = &depca_netdev_ops;
-	dev->watchdog_timeo = TX_TIMEOUT;
-
-	dev->mem_start = 0;
-
-	dev_set_drvdata(device, dev);
-	SET_NETDEV_DEV (dev, device);
-
-	status = register_netdev(dev);
-	if (status == 0)
-		return 0;
-out2:
-	iounmap(lp->sh_mem);
-out1:
-	release_mem_region (mem_start, mem_len);
-out_priv:
-	return status;
-}
-
-
-static int depca_open(struct net_device *dev)
-{
-	struct depca_private *lp = netdev_priv(dev);
-	u_long ioaddr = dev->base_addr;
-	s16 nicsr;
-	int status = 0;
-
-	STOP_DEPCA;
-	nicsr = inb(DEPCA_NICSR);
-
-	/* Make sure the shadow RAM is enabled */
-	if (lp->adapter != DEPCA) {
-		nicsr |= SHE;
-		outb(nicsr, DEPCA_NICSR);
-	}
-
-	/* Re-initialize the DEPCA... */
-	depca_init_ring(dev);
-	LoadCSRs(dev);
-
-	depca_dbg_open(dev);
-
-	if (request_irq(dev->irq, depca_interrupt, 0, lp->adapter_name, dev)) {
-		printk("depca_open(): Requested IRQ%d is busy\n", dev->irq);
-		status = -EAGAIN;
-	} else {
-
-		/* Enable DEPCA board interrupts and turn off LED */
-		nicsr = ((nicsr & ~IM & ~LED) | IEN);
-		outb(nicsr, DEPCA_NICSR);
-		outw(CSR0, DEPCA_ADDR);
-
-		netif_start_queue(dev);
-
-		status = InitRestartDepca(dev);
-
-		if (depca_debug > 1) {
-			printk("CSR0: 0x%4.4x\n", inw(DEPCA_DATA));
-			printk("nicsr: 0x%02x\n", inb(DEPCA_NICSR));
-		}
-	}
-	return status;
-}
-
-/* Initialize the lance Rx and Tx descriptor rings. */
-static void depca_init_ring(struct net_device *dev)
-{
-	struct depca_private *lp = netdev_priv(dev);
-	u_int i;
-	u_long offset;
-
-	/* Lock out other processes whilst setting up the hardware */
-	netif_stop_queue(dev);
-
-	lp->rx_new = lp->tx_new = 0;
-	lp->rx_old = lp->tx_old = 0;
-
-	/* Initialize the base address and length of each buffer in the ring */
-	for (i = 0; i <= lp->rxRingMask; i++) {
-		offset = lp->buffs_offset + i * RX_BUFF_SZ;
-		writel((lp->device_ram_start + offset) | R_OWN, &lp->rx_ring[i].base);
-		writew(-RX_BUFF_SZ, &lp->rx_ring[i].buf_length);
-		lp->rx_buff[i] = lp->sh_mem + offset;
-	}
-
-	for (i = 0; i <= lp->txRingMask; i++) {
-		offset = lp->buffs_offset + (i + lp->rxRingMask + 1) * TX_BUFF_SZ;
-		writel((lp->device_ram_start + offset) & 0x00ffffff, &lp->tx_ring[i].base);
-		lp->tx_buff[i] = lp->sh_mem + offset;
-	}
-
-	/* Set up the initialization block */
-	lp->init_block.rx_ring = (lp->device_ram_start + lp->rx_ring_offset) | lp->rx_rlen;
-	lp->init_block.tx_ring = (lp->device_ram_start + lp->tx_ring_offset) | lp->tx_rlen;
-
-	SetMulticastFilter(dev);
-
-	for (i = 0; i < ETH_ALEN; i++) {
-		lp->init_block.phys_addr[i] = dev->dev_addr[i];
-	}
-
-	lp->init_block.mode = 0x0000;	/* Enable the Tx and Rx */
-}
-
-
-static void depca_tx_timeout(struct net_device *dev)
-{
-	u_long ioaddr = dev->base_addr;
-
-	printk("%s: transmit timed out, status %04x, resetting.\n", dev->name, inw(DEPCA_DATA));
-
-	STOP_DEPCA;
-	depca_init_ring(dev);
-	LoadCSRs(dev);
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	netif_wake_queue(dev);
-	InitRestartDepca(dev);
-}
-
-
-/*
-** Writes a socket buffer to TX descriptor ring and starts transmission
-*/
-static netdev_tx_t depca_start_xmit(struct sk_buff *skb,
-				    struct net_device *dev)
-{
-	struct depca_private *lp = netdev_priv(dev);
-	u_long ioaddr = dev->base_addr;
-	int status = 0;
-
-	/* Transmitter timeout, serious problems. */
-	if (skb->len < 1)
-		goto out;
-
-	if (skb_padto(skb, ETH_ZLEN))
-		goto out;
-
-	netif_stop_queue(dev);
-
-	if (TX_BUFFS_AVAIL) {	/* Fill in a Tx ring entry */
-		status = load_packet(dev, skb);
-
-		if (!status) {
-			/* Trigger an immediate send demand. */
-			outw(CSR0, DEPCA_ADDR);
-			outw(INEA | TDMD, DEPCA_DATA);
-
-			dev_kfree_skb(skb);
-		}
-		if (TX_BUFFS_AVAIL)
-			netif_start_queue(dev);
-	} else
-		status = NETDEV_TX_LOCKED;
-
-      out:
-	return status;
-}
-
-/*
-** The DEPCA interrupt handler.
-*/
-static irqreturn_t depca_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct depca_private *lp;
-	s16 csr0, nicsr;
-	u_long ioaddr;
-
-	if (dev == NULL) {
-		printk("depca_interrupt(): irq %d for unknown device.\n", irq);
-		return IRQ_NONE;
-	}
-
-	lp = netdev_priv(dev);
-	ioaddr = dev->base_addr;
-
-	spin_lock(&lp->lock);
-
-	/* mask the DEPCA board interrupts and turn on the LED */
-	nicsr = inb(DEPCA_NICSR);
-	nicsr |= (IM | LED);
-	outb(nicsr, DEPCA_NICSR);
-
-	outw(CSR0, DEPCA_ADDR);
-	csr0 = inw(DEPCA_DATA);
-
-	/* Acknowledge all of the current interrupt sources ASAP. */
-	outw(csr0 & INTE, DEPCA_DATA);
-
-	if (csr0 & RINT)	/* Rx interrupt (packet arrived) */
-		depca_rx(dev);
-
-	if (csr0 & TINT)	/* Tx interrupt (packet sent) */
-		depca_tx(dev);
-
-	/* Any resources available? */
-	if ((TX_BUFFS_AVAIL >= 0) && netif_queue_stopped(dev)) {
-		netif_wake_queue(dev);
-	}
-
-	/* Unmask the DEPCA board interrupts and turn off the LED */
-	nicsr = (nicsr & ~IM & ~LED);
-	outb(nicsr, DEPCA_NICSR);
-
-	spin_unlock(&lp->lock);
-	return IRQ_HANDLED;
-}
-
-/* Called with lp->lock held */
-static int depca_rx(struct net_device *dev)
-{
-	struct depca_private *lp = netdev_priv(dev);
-	int i, entry;
-	s32 status;
-
-	for (entry = lp->rx_new; !(readl(&lp->rx_ring[entry].base) & R_OWN); entry = lp->rx_new) {
-		status = readl(&lp->rx_ring[entry].base) >> 16;
-		if (status & R_STP) {	/* Remember start of frame */
-			lp->rx_old = entry;
-		}
-		if (status & R_ENP) {	/* Valid frame status */
-			if (status & R_ERR) {	/* There was an error. */
-				dev->stats.rx_errors++;	/* Update the error stats. */
-				if (status & R_FRAM)
-					dev->stats.rx_frame_errors++;
-				if (status & R_OFLO)
-					dev->stats.rx_over_errors++;
-				if (status & R_CRC)
-					dev->stats.rx_crc_errors++;
-				if (status & R_BUFF)
-					dev->stats.rx_fifo_errors++;
-			} else {
-				short len, pkt_len = readw(&lp->rx_ring[entry].msg_length) - 4;
-				struct sk_buff *skb;
-
-				skb = dev_alloc_skb(pkt_len + 2);
-				if (skb != NULL) {
-					unsigned char *buf;
-					skb_reserve(skb, 2);	/* 16 byte align the IP header */
-					buf = skb_put(skb, pkt_len);
-					if (entry < lp->rx_old) {	/* Wrapped buffer */
-						len = (lp->rxRingMask - lp->rx_old + 1) * RX_BUFF_SZ;
-						memcpy_fromio(buf, lp->rx_buff[lp->rx_old], len);
-						memcpy_fromio(buf + len, lp->rx_buff[0], pkt_len - len);
-					} else {	/* Linear buffer */
-						memcpy_fromio(buf, lp->rx_buff[lp->rx_old], pkt_len);
-					}
-
-					/*
-					   ** Notify the upper protocol layers that there is another
-					   ** packet to handle
-					 */
-					skb->protocol = eth_type_trans(skb, dev);
-					netif_rx(skb);
-
-					/*
-					   ** Update stats
-					 */
-					dev->stats.rx_packets++;
-					dev->stats.rx_bytes += pkt_len;
-					for (i = 1; i < DEPCA_PKT_STAT_SZ - 1; i++) {
-						if (pkt_len < (i * DEPCA_PKT_BIN_SZ)) {
-							lp->pktStats.bins[i]++;
-							i = DEPCA_PKT_STAT_SZ;
-						}
-					}
-					if (is_multicast_ether_addr(buf)) {
-						if (is_broadcast_ether_addr(buf)) {
-							lp->pktStats.broadcast++;
-						} else {
-							lp->pktStats.multicast++;
-						}
-					} else if (compare_ether_addr(buf, dev->dev_addr) == 0) {
-						lp->pktStats.unicast++;
-					}
-
-					lp->pktStats.bins[0]++;	/* Duplicates stats.rx_packets */
-					if (lp->pktStats.bins[0] == 0) {	/* Reset counters */
-						memset((char *) &lp->pktStats, 0, sizeof(lp->pktStats));
-					}
-				} else {
-					printk("%s: Memory squeeze, deferring packet.\n", dev->name);
-					dev->stats.rx_dropped++;	/* Really, deferred. */
-					break;
-				}
-			}
-			/* Change buffer ownership for this last frame, back to the adapter */
-			for (; lp->rx_old != entry; lp->rx_old = (lp->rx_old + 1) & lp->rxRingMask) {
-				writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN, &lp->rx_ring[lp->rx_old].base);
-			}
-			writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base);
-		}
-
-		/*
-		   ** Update entry information
-		 */
-		lp->rx_new = (lp->rx_new + 1) & lp->rxRingMask;
-	}
-
-	return 0;
-}
-
-/*
-** Buffer sent - check for buffer errors.
-** Called with lp->lock held
-*/
-static int depca_tx(struct net_device *dev)
-{
-	struct depca_private *lp = netdev_priv(dev);
-	int entry;
-	s32 status;
-	u_long ioaddr = dev->base_addr;
-
-	for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) {
-		status = readl(&lp->tx_ring[entry].base) >> 16;
-
-		if (status < 0) {	/* Packet not yet sent! */
-			break;
-		} else if (status & T_ERR) {	/* An error occurred. */
-			status = readl(&lp->tx_ring[entry].misc);
-			dev->stats.tx_errors++;
-			if (status & TMD3_RTRY)
-				dev->stats.tx_aborted_errors++;
-			if (status & TMD3_LCAR)
-				dev->stats.tx_carrier_errors++;
-			if (status & TMD3_LCOL)
-				dev->stats.tx_window_errors++;
-			if (status & TMD3_UFLO)
-				dev->stats.tx_fifo_errors++;
-			if (status & (TMD3_BUFF | TMD3_UFLO)) {
-				/* Trigger an immediate send demand. */
-				outw(CSR0, DEPCA_ADDR);
-				outw(INEA | TDMD, DEPCA_DATA);
-			}
-		} else if (status & (T_MORE | T_ONE)) {
-			dev->stats.collisions++;
-		} else {
-			dev->stats.tx_packets++;
-		}
-
-		/* Update all the pointers */
-		lp->tx_old = (lp->tx_old + 1) & lp->txRingMask;
-	}
-
-	return 0;
-}
-
-static int depca_close(struct net_device *dev)
-{
-	struct depca_private *lp = netdev_priv(dev);
-	s16 nicsr;
-	u_long ioaddr = dev->base_addr;
-
-	netif_stop_queue(dev);
-
-	outw(CSR0, DEPCA_ADDR);
-
-	if (depca_debug > 1) {
-		printk("%s: Shutting down ethercard, status was %2.2x.\n", dev->name, inw(DEPCA_DATA));
-	}
-
-	/*
-	   ** We stop the DEPCA here -- it occasionally polls
-	   ** memory if we don't.
-	 */
-	outw(STOP, DEPCA_DATA);
-
-	/*
-	   ** Give back the ROM in case the user wants to go to DOS
-	 */
-	if (lp->adapter != DEPCA) {
-		nicsr = inb(DEPCA_NICSR);
-		nicsr &= ~SHE;
-		outb(nicsr, DEPCA_NICSR);
-	}
-
-	/*
-	   ** Free the associated irq
-	 */
-	free_irq(dev->irq, dev);
-	return 0;
-}
-
-static void LoadCSRs(struct net_device *dev)
-{
-	struct depca_private *lp = netdev_priv(dev);
-	u_long ioaddr = dev->base_addr;
-
-	outw(CSR1, DEPCA_ADDR);	/* initialisation block address LSW */
-	outw((u16) lp->device_ram_start, DEPCA_DATA);
-	outw(CSR2, DEPCA_ADDR);	/* initialisation block address MSW */
-	outw((u16) (lp->device_ram_start >> 16), DEPCA_DATA);
-	outw(CSR3, DEPCA_ADDR);	/* ALE control */
-	outw(ACON, DEPCA_DATA);
-
-	outw(CSR0, DEPCA_ADDR);	/* Point back to CSR0 */
-}
-
-static int InitRestartDepca(struct net_device *dev)
-{
-	struct depca_private *lp = netdev_priv(dev);
-	u_long ioaddr = dev->base_addr;
-	int i, status = 0;
-
-	/* Copy the shadow init_block to shared memory */
-	memcpy_toio(lp->sh_mem, &lp->init_block, sizeof(struct depca_init));
-
-	outw(CSR0, DEPCA_ADDR);	/* point back to CSR0 */
-	outw(INIT, DEPCA_DATA);	/* initialize DEPCA */
-
-	/* wait for lance to complete initialisation */
-	for (i = 0; (i < 100) && !(inw(DEPCA_DATA) & IDON); i++);
-
-	if (i != 100) {
-		/* clear IDON by writing a "1", enable interrupts and start lance */
-		outw(IDON | INEA | STRT, DEPCA_DATA);
-		if (depca_debug > 2) {
-			printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, lp->mem_start, inw(DEPCA_DATA));
-		}
-	} else {
-		printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, lp->mem_start, inw(DEPCA_DATA));
-		status = -1;
-	}
-
-	return status;
-}
-
-/*
-** Set or clear the multicast filter for this adaptor.
-*/
-static void set_multicast_list(struct net_device *dev)
-{
-	struct depca_private *lp = netdev_priv(dev);
-	u_long ioaddr = dev->base_addr;
-
-	netif_stop_queue(dev);
-	while (lp->tx_old != lp->tx_new);	/* Wait for the ring to empty */
-
-	STOP_DEPCA;	/* Temporarily stop the depca.  */
-	depca_init_ring(dev);	/* Initialize the descriptor rings */
-
-	if (dev->flags & IFF_PROMISC) {	/* Set promiscuous mode */
-		lp->init_block.mode |= PROM;
-	} else {
-		SetMulticastFilter(dev);
-		lp->init_block.mode &= ~PROM;	/* Unset promiscuous mode */
-	}
-
-	LoadCSRs(dev);	/* Reload CSR3 */
-	InitRestartDepca(dev);	/* Resume normal operation. */
-	netif_start_queue(dev);	/* Unlock the TX ring */
-}
-
-/*
-** Calculate the hash code and update the logical address filter
-** from a list of ethernet multicast addresses.
-** Big endian crc one liner is mine, all mine, ha ha ha ha!
-** LANCE calculates its hash codes big endian.
-*/
-static void SetMulticastFilter(struct net_device *dev)
-{
-	struct depca_private *lp = netdev_priv(dev);
-	struct netdev_hw_addr *ha;
-	int i, j, bit, byte;
-	u16 hashcode;
-	u32 crc;
-
-	if (dev->flags & IFF_ALLMULTI) {	/* Set all multicast bits */
-		for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) {
-			lp->init_block.mcast_table[i] = (char) 0xff;
-		}
-	} else {
-		for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) {	/* Clear the multicast table */
-			lp->init_block.mcast_table[i] = 0;
-		}
-		/* Add multicast addresses */
-		netdev_for_each_mc_addr(ha, dev) {
-			crc = ether_crc(ETH_ALEN, ha->addr);
-			hashcode = (crc & 1);	/* hashcode is 6 LSb of CRC ... */
-			for (j = 0; j < 5; j++) {	/* ... in reverse order. */
-				hashcode = (hashcode << 1) | ((crc >>= 1) & 1);
-			}
-
-			byte = hashcode >> 3;	/* bit[3-5] -> byte in filter */
-			bit = 1 << (hashcode & 0x07);	/* bit[0-2] -> bit in byte */
-			lp->init_block.mcast_table[byte] |= bit;
-		}
-	}
-}
-
-static int __init depca_common_init (u_long ioaddr, struct net_device **devp)
-{
-	int status = 0;
-
-	if (!request_region (ioaddr, DEPCA_TOTAL_SIZE, depca_string)) {
-		status = -EBUSY;
-		goto out;
-	}
-
-	if (DevicePresent(ioaddr)) {
-		status = -ENODEV;
-		goto out_release;
-	}
-
-	if (!(*devp = alloc_etherdev (sizeof (struct depca_private)))) {
-		status = -ENOMEM;
-		goto out_release;
-	}
-
-	return 0;
-
- out_release:
-	release_region (ioaddr, DEPCA_TOTAL_SIZE);
- out:
-	return status;
-}
-
-#ifdef CONFIG_MCA
-/*
-** Microchannel bus I/O device probe
-*/
-static int __init depca_mca_probe(struct device *device)
-{
-	unsigned char pos[2];
-	unsigned char where;
-	unsigned long iobase, mem_start;
-	int irq, err;
-	struct mca_device *mdev = to_mca_device (device);
-	struct net_device *dev;
-	struct depca_private *lp;
-
-	/*
-	** Search for the adapter.  If an address has been given, search
-	** specifically for the card at that address.  Otherwise find the
-	** first card in the system.
-	*/
-
-	pos[0] = mca_device_read_stored_pos(mdev, 2);
-	pos[1] = mca_device_read_stored_pos(mdev, 3);
-
-	/*
-	** IO of card is handled by bits 1 and 2 of pos0.
-	**
-	**    bit2 bit1    IO
-	**       0    0    0x2c00
-	**       0    1    0x2c10
-	**       1    0    0x2c20
-	**       1    1    0x2c30
-	*/
-	where = (pos[0] & 6) >> 1;
-	iobase = 0x2c00 + (0x10 * where);
-
-	/*
-	** Found the adapter we were looking for. Now start setting it up.
-	**
-	** First work on decoding the IRQ.  It's stored in the lower 4 bits
-	** of pos1.  Bits are as follows (from the ADF file):
-	**
-	**      Bits
-	**   3   2   1   0    IRQ
-	**   --------------------
-	**   0   0   1   0     5
-	**   0   0   0   1     9
-	**   0   1   0   0    10
-	**   1   0   0   0    11
-	*/
-	where = pos[1] & 0x0f;
-	switch (where) {
-	case 1:
-		irq = 9;
-		break;
-	case 2:
-		irq = 5;
-		break;
-	case 4:
-		irq = 10;
-		break;
-	case 8:
-		irq = 11;
-		break;
-	default:
-		printk("%s: mca_probe IRQ error.  You should never get here (%d).\n", mdev->name, where);
-		return -EINVAL;
-	}
-
-	/*
-	** Shared memory address of adapter is stored in bits 3-5 of pos0.
-	** They are mapped as follows:
-	**
-	**    Bit
-	**   5  4  3       Memory Addresses
-	**   0  0  0       C0000-CFFFF (64K)
-	**   1  0  0       C8000-CFFFF (32K)
-	**   0  0  1       D0000-DFFFF (64K)
-	**   1  0  1       D8000-DFFFF (32K)
-	**   0  1  0       E0000-EFFFF (64K)
-	**   1  1  0       E8000-EFFFF (32K)
-	*/
-	where = (pos[0] & 0x18) >> 3;
-	mem_start = 0xc0000 + (where * 0x10000);
-	if (pos[0] & 0x20) {
-		mem_start += 0x8000;
-	}
-
-	/* claim the slot */
-	strncpy(mdev->name, depca_mca_adapter_name[mdev->index],
-		sizeof(mdev->name));
-	mca_device_set_claim(mdev, 1);
-
-        /*
-	** Get everything allocated and initialized...  (almost just
-	** like the ISA and EISA probes)
-	*/
-	irq = mca_device_transform_irq(mdev, irq);
-	iobase = mca_device_transform_ioport(mdev, iobase);
-
-	if ((err = depca_common_init (iobase, &dev)))
-		goto out_unclaim;
-
-	dev->irq = irq;
-	dev->base_addr = iobase;
-	lp = netdev_priv(dev);
-	lp->depca_bus = DEPCA_BUS_MCA;
-	lp->adapter = depca_mca_adapter_type[mdev->index];
-	lp->mem_start = mem_start;
-
-	if ((err = depca_hw_init(dev, device)))
-		goto out_free;
-
-	return 0;
-
- out_free:
-	free_netdev (dev);
-	release_region (iobase, DEPCA_TOTAL_SIZE);
- out_unclaim:
-	mca_device_set_claim(mdev, 0);
-
-	return err;
-}
-#endif
-
-/*
-** ISA bus I/O device probe
-*/
-
-static void __init depca_platform_probe (void)
-{
-	int i;
-	struct platform_device *pldev;
-
-	for (i = 0; depca_io_ports[i].iobase; i++) {
-		depca_io_ports[i].device = NULL;
-
-		/* if an address has been specified on the command
-		 * line, use it (if valid) */
-		if (io && io != depca_io_ports[i].iobase)
-			continue;
-
-		pldev = platform_device_alloc(depca_string, i);
-		if (!pldev)
-			continue;
-
-		pldev->dev.platform_data = (void *) depca_io_ports[i].iobase;
-		depca_io_ports[i].device = pldev;
-
-		if (platform_device_add(pldev)) {
-			depca_io_ports[i].device = NULL;
-			pldev->dev.platform_data = NULL;
-			platform_device_put(pldev);
-			continue;
-		}
-
-		if (!pldev->dev.driver) {
-		/* The driver was not bound to this device, there was
-		 * no hardware at this address. Unregister it, as the
-		 * release function will take care of freeing the
-		 * allocated structure */
-
-			depca_io_ports[i].device = NULL;
-			pldev->dev.platform_data = NULL;
-			platform_device_unregister (pldev);
-		}
-	}
-}
-
-static enum depca_type __init depca_shmem_probe (ulong *mem_start)
-{
-	u_long mem_base[] = DEPCA_RAM_BASE_ADDRESSES;
-	enum depca_type adapter = unknown;
-	int i;
-
-	for (i = 0; mem_base[i]; i++) {
-		*mem_start = mem ? mem : mem_base[i];
-		adapter = DepcaSignature (adapter_name, *mem_start);
-		if (adapter != unknown)
-			break;
-	}
-
-	return adapter;
-}
-
-static int __devinit depca_isa_probe (struct platform_device *device)
-{
-	struct net_device *dev;
-	struct depca_private *lp;
-	u_long ioaddr, mem_start = 0;
-	enum depca_type adapter = unknown;
-	int status = 0;
-
-	ioaddr = (u_long) device->dev.platform_data;
-
-	if ((status = depca_common_init (ioaddr, &dev)))
-		goto out;
-
-	adapter = depca_shmem_probe (&mem_start);
-
-	if (adapter == unknown) {
-		status = -ENODEV;
-		goto out_free;
-	}
-
-	dev->base_addr = ioaddr;
-	dev->irq = irq;		/* Use whatever value the user gave
-				 * us, and 0 if he didn't. */
-	lp = netdev_priv(dev);
-	lp->depca_bus = DEPCA_BUS_ISA;
-	lp->adapter = adapter;
-	lp->mem_start = mem_start;
-
-	if ((status = depca_hw_init(dev, &device->dev)))
-		goto out_free;
-
-	return 0;
-
- out_free:
-	free_netdev (dev);
-	release_region (ioaddr, DEPCA_TOTAL_SIZE);
- out:
-	return status;
-}
-
-/*
-** EISA callbacks from sysfs.
-*/
-
-#ifdef CONFIG_EISA
-static int __init depca_eisa_probe (struct device *device)
-{
-	enum depca_type adapter = unknown;
-	struct eisa_device *edev;
-	struct net_device *dev;
-	struct depca_private *lp;
-	u_long ioaddr, mem_start;
-	int status = 0;
-
-	edev = to_eisa_device (device);
-	ioaddr = edev->base_addr + DEPCA_EISA_IO_PORTS;
-
-	if ((status = depca_common_init (ioaddr, &dev)))
-		goto out;
-
-	/* It would have been nice to get card configuration from the
-	 * card. Unfortunately, this register is write-only (shares
-	 * it's address with the ethernet prom)... As we don't parse
-	 * the EISA configuration structures (yet... :-), just rely on
-	 * the ISA probing to sort it out... */
-
-	adapter = depca_shmem_probe (&mem_start);
-	if (adapter == unknown) {
-		status = -ENODEV;
-		goto out_free;
-	}
-
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-	lp = netdev_priv(dev);
-	lp->depca_bus = DEPCA_BUS_EISA;
-	lp->adapter = edev->id.driver_data;
-	lp->mem_start = mem_start;
-
-	if ((status = depca_hw_init(dev, device)))
-		goto out_free;
-
-	return 0;
-
- out_free:
-	free_netdev (dev);
-	release_region (ioaddr, DEPCA_TOTAL_SIZE);
- out:
-	return status;
-}
-#endif
-
-static int __devexit depca_device_remove (struct device *device)
-{
-	struct net_device *dev;
-	struct depca_private *lp;
-	int bus;
-
-	dev  = dev_get_drvdata(device);
-	lp   = netdev_priv(dev);
-
-	unregister_netdev (dev);
-	iounmap (lp->sh_mem);
-	release_mem_region (lp->mem_start, lp->mem_len);
-	release_region (dev->base_addr, DEPCA_TOTAL_SIZE);
-	bus = lp->depca_bus;
-	free_netdev (dev);
-
-	return 0;
-}
-
-/*
-** Look for a particular board name in the on-board Remote Diagnostics
-** and Boot (readb) ROM. This will also give us a clue to the network RAM
-** base address.
-*/
-static int __init DepcaSignature(char *name, u_long base_addr)
-{
-	u_int i, j, k;
-	void __iomem *ptr;
-	char tmpstr[16];
-	u_long prom_addr = base_addr + 0xc000;
-	u_long mem_addr = base_addr + 0x8000; /* 32KB */
-
-	/* Can't reserve the prom region, it is already marked as
-	 * used, at least on x86. Instead, reserve a memory region a
-	 * board would certainly use. If it works, go ahead. If not,
-	 * run like hell... */
-
-	if (!request_mem_region (mem_addr, 16, depca_string))
-		return unknown;
-
-	/* Copy the first 16 bytes of ROM */
-
-	ptr = ioremap(prom_addr, 16);
-	if (ptr == NULL) {
-		printk(KERN_ERR "depca: I/O remap failed at %lx\n", prom_addr);
-		return unknown;
-	}
-	for (i = 0; i < 16; i++) {
-		tmpstr[i] = readb(ptr + i);
-	}
-	iounmap(ptr);
-
-	release_mem_region (mem_addr, 16);
-
-	/* Check if PROM contains a valid string */
-	for (i = 0; *depca_signature[i] != '\0'; i++) {
-		for (j = 0, k = 0; j < 16 && k < strlen(depca_signature[i]); j++) {
-			if (depca_signature[i][k] == tmpstr[j]) {	/* track signature */
-				k++;
-			} else {	/* lost signature; begin search again */
-				k = 0;
-			}
-		}
-		if (k == strlen(depca_signature[i]))
-			break;
-	}
-
-	/* Check if name string is valid, provided there's no PROM */
-	if (name && *name && (i == unknown)) {
-		for (i = 0; *depca_signature[i] != '\0'; i++) {
-			if (strcmp(name, depca_signature[i]) == 0)
-				break;
-		}
-	}
-
-	return i;
-}
-
-/*
-** Look for a special sequence in the Ethernet station address PROM that
-** is common across all DEPCA products. Note that the original DEPCA needs
-** its ROM address counter to be initialized and enabled. Only enable
-** if the first address octet is a 0x08 - this minimises the chances of
-** messing around with some other hardware, but it assumes that this DEPCA
-** card initialized itself correctly.
-**
-** Search the Ethernet address ROM for the signature. Since the ROM address
-** counter can start at an arbitrary point, the search must include the entire
-** probe sequence length plus the (length_of_the_signature - 1).
-** Stop the search IMMEDIATELY after the signature is found so that the
-** PROM address counter is correctly positioned at the start of the
-** ethernet address for later read out.
-*/
-static int __init DevicePresent(u_long ioaddr)
-{
-	union {
-		struct {
-			u32 a;
-			u32 b;
-		} llsig;
-		char Sig[sizeof(u32) << 1];
-	}
-	dev;
-	short sigLength = 0;
-	s8 data;
-	s16 nicsr;
-	int i, j, status = 0;
-
-	data = inb(DEPCA_PROM);	/* clear counter on DEPCA */
-	data = inb(DEPCA_PROM);	/* read data */
-
-	if (data == 0x08) {	/* Enable counter on DEPCA */
-		nicsr = inb(DEPCA_NICSR);
-		nicsr |= AAC;
-		outb(nicsr, DEPCA_NICSR);
-	}
-
-	dev.llsig.a = ETH_PROM_SIG;
-	dev.llsig.b = ETH_PROM_SIG;
-	sigLength = sizeof(u32) << 1;
-
-	for (i = 0, j = 0; j < sigLength && i < PROBE_LENGTH + sigLength - 1; i++) {
-		data = inb(DEPCA_PROM);
-		if (dev.Sig[j] == data) {	/* track signature */
-			j++;
-		} else {	/* lost signature; begin search again */
-			if (data == dev.Sig[0]) {	/* rare case.... */
-				j = 1;
-			} else {
-				j = 0;
-			}
-		}
-	}
-
-	if (j != sigLength) {
-		status = -ENODEV;	/* search failed */
-	}
-
-	return status;
-}
-
-/*
-** The DE100 and DE101 PROM accesses were made non-standard for some bizarre
-** reason: access the upper half of the PROM with x=0; access the lower half
-** with x=1.
-*/
-static int __init get_hw_addr(struct net_device *dev)
-{
-	u_long ioaddr = dev->base_addr;
-	struct depca_private *lp = netdev_priv(dev);
-	int i, k, tmp, status = 0;
-	u_short j, x, chksum;
-
-	x = (((lp->adapter == de100) || (lp->adapter == de101)) ? 1 : 0);
-
-	for (i = 0, k = 0, j = 0; j < 3; j++) {
-		k <<= 1;
-		if (k > 0xffff)
-			k -= 0xffff;
-
-		k += (u_char) (tmp = inb(DEPCA_PROM + x));
-		dev->dev_addr[i++] = (u_char) tmp;
-		k += (u_short) ((tmp = inb(DEPCA_PROM + x)) << 8);
-		dev->dev_addr[i++] = (u_char) tmp;
-
-		if (k > 0xffff)
-			k -= 0xffff;
-	}
-	if (k == 0xffff)
-		k = 0;
-
-	chksum = (u_char) inb(DEPCA_PROM + x);
-	chksum |= (u_short) (inb(DEPCA_PROM + x) << 8);
-	if (k != chksum)
-		status = -1;
-
-	return status;
-}
-
-/*
-** Load a packet into the shared memory
-*/
-static int load_packet(struct net_device *dev, struct sk_buff *skb)
-{
-	struct depca_private *lp = netdev_priv(dev);
-	int i, entry, end, len, status = NETDEV_TX_OK;
-
-	entry = lp->tx_new;	/* Ring around buffer number. */
-	end = (entry + (skb->len - 1) / TX_BUFF_SZ) & lp->txRingMask;
-	if (!(readl(&lp->tx_ring[end].base) & T_OWN)) {	/* Enough room? */
-		/*
-		   ** Caution: the write order is important here... don't set up the
-		   ** ownership rights until all the other information is in place.
-		 */
-		if (end < entry) {	/* wrapped buffer */
-			len = (lp->txRingMask - entry + 1) * TX_BUFF_SZ;
-			memcpy_toio(lp->tx_buff[entry], skb->data, len);
-			memcpy_toio(lp->tx_buff[0], skb->data + len, skb->len - len);
-		} else {	/* linear buffer */
-			memcpy_toio(lp->tx_buff[entry], skb->data, skb->len);
-		}
-
-		/* set up the buffer descriptors */
-		len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
-		for (i = entry; i != end; i = (i+1) & lp->txRingMask) {
-			/* clean out flags */
-			writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base);
-			writew(0x0000, &lp->tx_ring[i].misc);	/* clears other error flags */
-			writew(-TX_BUFF_SZ, &lp->tx_ring[i].length);	/* packet length in buffer */
-			len -= TX_BUFF_SZ;
-		}
-		/* clean out flags */
-		writel(readl(&lp->tx_ring[end].base) & ~T_FLAGS, &lp->tx_ring[end].base);
-		writew(0x0000, &lp->tx_ring[end].misc);	/* clears other error flags */
-		writew(-len, &lp->tx_ring[end].length);	/* packet length in last buff */
-
-		/* start of packet */
-		writel(readl(&lp->tx_ring[entry].base) | T_STP, &lp->tx_ring[entry].base);
-		/* end of packet */
-		writel(readl(&lp->tx_ring[end].base) | T_ENP, &lp->tx_ring[end].base);
-
-		for (i = end; i != entry; --i) {
-			/* ownership of packet */
-			writel(readl(&lp->tx_ring[i].base) | T_OWN, &lp->tx_ring[i].base);
-			if (i == 0)
-				i = lp->txRingMask + 1;
-		}
-		writel(readl(&lp->tx_ring[entry].base) | T_OWN, &lp->tx_ring[entry].base);
-
-		lp->tx_new = (++end) & lp->txRingMask;	/* update current pointers */
-	} else {
-		status = NETDEV_TX_LOCKED;
-	}
-
-	return status;
-}
-
-static void depca_dbg_open(struct net_device *dev)
-{
-	struct depca_private *lp = netdev_priv(dev);
-	u_long ioaddr = dev->base_addr;
-	struct depca_init *p = &lp->init_block;
-	int i;
-
-	if (depca_debug > 1) {
-		/* Do not copy the shadow init block into shared memory */
-		/* Debugging should not affect normal operation! */
-		/* The shadow init block will get copied across during InitRestartDepca */
-		printk("%s: depca open with irq %d\n", dev->name, dev->irq);
-		printk("Descriptor head addresses (CPU):\n");
-		printk("        0x%lx  0x%lx\n", (u_long) lp->rx_ring, (u_long) lp->tx_ring);
-		printk("Descriptor addresses (CPU):\nRX: ");
-		for (i = 0; i < lp->rxRingMask; i++) {
-			if (i < 3) {
-				printk("%p ", &lp->rx_ring[i].base);
-			}
-		}
-		printk("...%p\n", &lp->rx_ring[i].base);
-		printk("TX: ");
-		for (i = 0; i < lp->txRingMask; i++) {
-			if (i < 3) {
-				printk("%p ", &lp->tx_ring[i].base);
-			}
-		}
-		printk("...%p\n", &lp->tx_ring[i].base);
-		printk("\nDescriptor buffers (Device):\nRX: ");
-		for (i = 0; i < lp->rxRingMask; i++) {
-			if (i < 3) {
-				printk("0x%8.8x  ", readl(&lp->rx_ring[i].base));
-			}
-		}
-		printk("...0x%8.8x\n", readl(&lp->rx_ring[i].base));
-		printk("TX: ");
-		for (i = 0; i < lp->txRingMask; i++) {
-			if (i < 3) {
-				printk("0x%8.8x  ", readl(&lp->tx_ring[i].base));
-			}
-		}
-		printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base));
-		printk("Initialisation block at 0x%8.8lx(Phys)\n", lp->mem_start);
-		printk("        mode: 0x%4.4x\n", p->mode);
-		printk("        physical address: %pM\n", p->phys_addr);
-		printk("        multicast hash table: ");
-		for (i = 0; i < (HASH_TABLE_LEN >> 3) - 1; i++) {
-			printk("%2.2x:", p->mcast_table[i]);
-		}
-		printk("%2.2x\n", p->mcast_table[i]);
-		printk("        rx_ring at: 0x%8.8x\n", p->rx_ring);
-		printk("        tx_ring at: 0x%8.8x\n", p->tx_ring);
-		printk("buffers (Phys): 0x%8.8lx\n", lp->mem_start + lp->buffs_offset);
-		printk("Ring size:\nRX: %d  Log2(rxRingMask): 0x%8.8x\n", (int) lp->rxRingMask + 1, lp->rx_rlen);
-		printk("TX: %d  Log2(txRingMask): 0x%8.8x\n", (int) lp->txRingMask + 1, lp->tx_rlen);
-		outw(CSR2, DEPCA_ADDR);
-		printk("CSR2&1: 0x%4.4x", inw(DEPCA_DATA));
-		outw(CSR1, DEPCA_ADDR);
-		printk("%4.4x\n", inw(DEPCA_DATA));
-		outw(CSR3, DEPCA_ADDR);
-		printk("CSR3: 0x%4.4x\n", inw(DEPCA_DATA));
-	}
-}
-
-/*
-** Perform IOCTL call functions here. Some are privileged operations and the
-** effective uid is checked in those cases.
-** All multicast IOCTLs will not work here and are for testing purposes only.
-*/
-static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct depca_private *lp = netdev_priv(dev);
-	struct depca_ioctl *ioc = (struct depca_ioctl *) &rq->ifr_ifru;
-	int i, status = 0;
-	u_long ioaddr = dev->base_addr;
-	union {
-		u8 addr[(HASH_TABLE_LEN * ETH_ALEN)];
-		u16 sval[(HASH_TABLE_LEN * ETH_ALEN) >> 1];
-		u32 lval[(HASH_TABLE_LEN * ETH_ALEN) >> 2];
-	} tmp;
-	unsigned long flags;
-	void *buf;
-
-	switch (ioc->cmd) {
-	case DEPCA_GET_HWADDR:	/* Get the hardware address */
-		for (i = 0; i < ETH_ALEN; i++) {
-			tmp.addr[i] = dev->dev_addr[i];
-		}
-		ioc->len = ETH_ALEN;
-		if (copy_to_user(ioc->data, tmp.addr, ioc->len))
-			return -EFAULT;
-		break;
-
-	case DEPCA_SET_HWADDR:	/* Set the hardware address */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN))
-			return -EFAULT;
-		for (i = 0; i < ETH_ALEN; i++) {
-			dev->dev_addr[i] = tmp.addr[i];
-		}
-		netif_stop_queue(dev);
-		while (lp->tx_old != lp->tx_new)
-			cpu_relax();	/* Wait for the ring to empty */
-
-		STOP_DEPCA;	/* Temporarily stop the depca.  */
-		depca_init_ring(dev);	/* Initialize the descriptor rings */
-		LoadCSRs(dev);	/* Reload CSR3 */
-		InitRestartDepca(dev);	/* Resume normal operation. */
-		netif_start_queue(dev);	/* Unlock the TX ring */
-		break;
-
-	case DEPCA_SET_PROM:	/* Set Promiscuous Mode */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		netif_stop_queue(dev);
-		while (lp->tx_old != lp->tx_new)
-			cpu_relax();	/* Wait for the ring to empty */
-
-		STOP_DEPCA;	/* Temporarily stop the depca.  */
-		depca_init_ring(dev);	/* Initialize the descriptor rings */
-		lp->init_block.mode |= PROM;	/* Set promiscuous mode */
-
-		LoadCSRs(dev);	/* Reload CSR3 */
-		InitRestartDepca(dev);	/* Resume normal operation. */
-		netif_start_queue(dev);	/* Unlock the TX ring */
-		break;
-
-	case DEPCA_CLR_PROM:	/* Clear Promiscuous Mode */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		netif_stop_queue(dev);
-		while (lp->tx_old != lp->tx_new)
-			cpu_relax();	/* Wait for the ring to empty */
-
-		STOP_DEPCA;	/* Temporarily stop the depca.  */
-		depca_init_ring(dev);	/* Initialize the descriptor rings */
-		lp->init_block.mode &= ~PROM;	/* Clear promiscuous mode */
-
-		LoadCSRs(dev);	/* Reload CSR3 */
-		InitRestartDepca(dev);	/* Resume normal operation. */
-		netif_start_queue(dev);	/* Unlock the TX ring */
-		break;
-
-	case DEPCA_SAY_BOO:	/* Say "Boo!" to the kernel log file */
-		if(!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		printk("%s: Boo!\n", dev->name);
-		break;
-
-	case DEPCA_GET_MCA:	/* Get the multicast address table */
-		ioc->len = (HASH_TABLE_LEN >> 3);
-		if (copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len))
-			return -EFAULT;
-		break;
-
-	case DEPCA_SET_MCA:	/* Set a multicast address */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		if (ioc->len >= HASH_TABLE_LEN)
-			return -EINVAL;
-		if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len))
-			return -EFAULT;
-		set_multicast_list(dev);
-		break;
-
-	case DEPCA_CLR_MCA:	/* Clear all multicast addresses */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		set_multicast_list(dev);
-		break;
-
-	case DEPCA_MCA_EN:	/* Enable pass all multicast addressing */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		set_multicast_list(dev);
-		break;
-
-	case DEPCA_GET_STATS:	/* Get the driver statistics */
-		ioc->len = sizeof(lp->pktStats);
-		buf = kmalloc(ioc->len, GFP_KERNEL);
-		if(!buf)
-			return -ENOMEM;
-		spin_lock_irqsave(&lp->lock, flags);
-		memcpy(buf, &lp->pktStats, ioc->len);
-		spin_unlock_irqrestore(&lp->lock, flags);
-		if (copy_to_user(ioc->data, buf, ioc->len))
-			status = -EFAULT;
-		kfree(buf);
-		break;
-
-	case DEPCA_CLR_STATS:	/* Zero out the driver statistics */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		spin_lock_irqsave(&lp->lock, flags);
-		memset(&lp->pktStats, 0, sizeof(lp->pktStats));
-		spin_unlock_irqrestore(&lp->lock, flags);
-		break;
-
-	case DEPCA_GET_REG:	/* Get the DEPCA Registers */
-		i = 0;
-		tmp.sval[i++] = inw(DEPCA_NICSR);
-		outw(CSR0, DEPCA_ADDR);	/* status register */
-		tmp.sval[i++] = inw(DEPCA_DATA);
-		memcpy(&tmp.sval[i], &lp->init_block, sizeof(struct depca_init));
-		ioc->len = i + sizeof(struct depca_init);
-		if (copy_to_user(ioc->data, tmp.addr, ioc->len))
-			return -EFAULT;
-		break;
-
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	return status;
-}
-
-static int __init depca_module_init (void)
-{
-	int err = 0;
-
-#ifdef CONFIG_MCA
-	err = mca_register_driver(&depca_mca_driver);
-	if (err)
-		goto err;
-#endif
-#ifdef CONFIG_EISA
-	err = eisa_driver_register(&depca_eisa_driver);
-	if (err)
-		goto err_mca;
-#endif
-	err = platform_driver_register(&depca_isa_driver);
-	if (err)
-		goto err_eisa;
-
-	depca_platform_probe();
-	return 0;
-
-err_eisa:
-#ifdef CONFIG_EISA
-	eisa_driver_unregister(&depca_eisa_driver);
-err_mca:
-#endif
-#ifdef CONFIG_MCA
-	mca_unregister_driver(&depca_mca_driver);
-err:
-#endif
-	return err;
-}
-
-static void __exit depca_module_exit (void)
-{
-	int i;
-#ifdef CONFIG_MCA
-        mca_unregister_driver (&depca_mca_driver);
-#endif
-#ifdef CONFIG_EISA
-        eisa_driver_unregister (&depca_eisa_driver);
-#endif
-	platform_driver_unregister (&depca_isa_driver);
-
-	for (i = 0; depca_io_ports[i].iobase; i++) {
-		if (depca_io_ports[i].device) {
-			depca_io_ports[i].device->dev.platform_data = NULL;
-			platform_device_unregister (depca_io_ports[i].device);
-			depca_io_ports[i].device = NULL;
-		}
-	}
-}
-
-module_init (depca_module_init);
-module_exit (depca_module_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/depca.h linux-libre-3.2-gnu/drivers/net/depca.h
--- linux-libre-3.1-gnu/drivers/net/depca.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/depca.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,185 +0,0 @@
-/*
-    Written 1994 by David C. Davies.
-
-    Copyright 1994 David C. Davies. This software may be used and distributed
-    according to the terms of the GNU General Public License, incorporated herein by
-    reference.
-*/
-
-/*
-** I/O addresses. Note that the 2k buffer option is not supported in
-** this driver.
-*/
-#define DEPCA_NICSR ioaddr+0x00   /* Network interface CSR */
-#define DEPCA_RBI   ioaddr+0x02   /* RAM buffer index (2k buffer mode) */
-#define DEPCA_DATA  ioaddr+0x04   /* LANCE registers' data port */
-#define DEPCA_ADDR  ioaddr+0x06   /* LANCE registers' address port */
-#define DEPCA_HBASE ioaddr+0x08   /* EISA high memory base address reg. */
-#define DEPCA_PROM  ioaddr+0x0c   /* Ethernet address ROM data port */
-#define DEPCA_CNFG  ioaddr+0x0c   /* EISA Configuration port */
-#define DEPCA_RBSA  ioaddr+0x0e   /* RAM buffer starting address (2k buff.) */
-
-/*
-** These are LANCE registers addressable through DEPCA_ADDR
-*/
-#define CSR0       0
-#define CSR1       1
-#define CSR2       2
-#define CSR3       3
-
-/*
-** NETWORK INTERFACE CSR (NI_CSR) bit definitions
-*/
-
-#define TO       	0x0100	/* Time Out for remote boot */
-#define SHE      	0x0080  /* SHadow memory Enable */
-#define BS       	0x0040  /* Bank Select */
-#define BUF      	0x0020	/* BUFfer size (1->32k, 0->64k) */
-#define RBE      	0x0010	/* Remote Boot Enable (1->net boot) */
-#define AAC      	0x0008  /* Address ROM Address Counter (1->enable) */
-#define _128KB      	0x0008  /* 128kB Network RAM (1->enable) */
-#define IM       	0x0004	/* Interrupt Mask (1->mask) */
-#define IEN      	0x0002	/* Interrupt tristate ENable (1->enable) */
-#define LED      	0x0001	/* LED control */
-
-/*
-** Control and Status Register 0 (CSR0) bit definitions
-*/
-
-#define ERR     	0x8000 	/* Error summary */
-#define BABL    	0x4000 	/* Babble transmitter timeout error  */
-#define CERR    	0x2000 	/* Collision Error */
-#define MISS    	0x1000 	/* Missed packet */
-#define MERR    	0x0800 	/* Memory Error */
-#define RINT    	0x0400 	/* Receiver Interrupt */
-#define TINT    	0x0200 	/* Transmit Interrupt */
-#define IDON    	0x0100 	/* Initialization Done */
-#define INTR    	0x0080 	/* Interrupt Flag */
-#define INEA    	0x0040 	/* Interrupt Enable */
-#define RXON    	0x0020 	/* Receiver on */
-#define TXON    	0x0010 	/* Transmitter on */
-#define TDMD    	0x0008 	/* Transmit Demand */
-#define STOP    	0x0004 	/* Stop */
-#define STRT    	0x0002 	/* Start */
-#define INIT    	0x0001 	/* Initialize */
-#define INTM            0xff00  /* Interrupt Mask */
-#define INTE            0xfff0  /* Interrupt Enable */
-
-/*
-** CONTROL AND STATUS REGISTER 3 (CSR3)
-*/
-
-#define BSWP    	0x0004	/* Byte SWaP */
-#define ACON    	0x0002	/* ALE control */
-#define BCON    	0x0001	/* Byte CONtrol */
-
-/*
-** Initialization Block Mode Register
-*/
-
-#define PROM       	0x8000 	/* Promiscuous Mode */
-#define EMBA       	0x0080	/* Enable Modified Back-off Algorithm */
-#define INTL       	0x0040 	/* Internal Loopback */
-#define DRTY       	0x0020 	/* Disable Retry */
-#define COLL       	0x0010 	/* Force Collision */
-#define DTCR       	0x0008 	/* Disable Transmit CRC */
-#define LOOP       	0x0004 	/* Loopback */
-#define DTX        	0x0002 	/* Disable the Transmitter */
-#define DRX        	0x0001 	/* Disable the Receiver */
-
-/*
-** Receive Message Descriptor 1 (RMD1) bit definitions.
-*/
-
-#define R_OWN       0x80000000 	/* Owner bit 0 = host, 1 = lance */
-#define R_ERR     	0x4000 	/* Error Summary */
-#define R_FRAM    	0x2000 	/* Framing Error */
-#define R_OFLO    	0x1000 	/* Overflow Error */
-#define R_CRC     	0x0800 	/* CRC Error */
-#define R_BUFF    	0x0400 	/* Buffer Error */
-#define R_STP     	0x0200 	/* Start of Packet */
-#define R_ENP     	0x0100 	/* End of Packet */
-
-/*
-** Transmit Message Descriptor 1 (TMD1) bit definitions.
-*/
-
-#define T_OWN       0x80000000 	/* Owner bit 0 = host, 1 = lance */
-#define T_ERR     	0x4000 	/* Error Summary */
-#define T_ADD_FCS 	0x2000 	/* More the 1 retry needed to Xmit */
-#define T_MORE    	0x1000	/* >1 retry to transmit packet */
-#define T_ONE     	0x0800 	/* 1 try needed to transmit the packet */
-#define T_DEF     	0x0400 	/* Deferred */
-#define T_STP       0x02000000 	/* Start of Packet */
-#define T_ENP       0x01000000	/* End of Packet */
-#define T_FLAGS     0xff000000  /* TX Flags Field */
-
-/*
-** Transmit Message Descriptor 3 (TMD3) bit definitions.
-*/
-
-#define TMD3_BUFF    0x8000	/* BUFFer error */
-#define TMD3_UFLO    0x4000	/* UnderFLOw error */
-#define TMD3_RES     0x2000	/* REServed */
-#define TMD3_LCOL    0x1000	/* Late COLlision */
-#define TMD3_LCAR    0x0800	/* Loss of CARrier */
-#define TMD3_RTRY    0x0400	/* ReTRY error */
-
-/*
-** EISA configuration Register (CNFG) bit definitions
-*/
-
-#define TIMEOUT       	0x0100	/* 0:2.5 mins, 1: 30 secs */
-#define REMOTE      	0x0080  /* Remote Boot Enable -> 1 */
-#define IRQ11       	0x0040  /* Enable -> 1 */
-#define IRQ10    	0x0020	/* Enable -> 1 */
-#define IRQ9    	0x0010	/* Enable -> 1 */
-#define IRQ5      	0x0008  /* Enable -> 1 */
-#define BUFF     	0x0004	/* 0: 64kB or 128kB, 1: 32kB */
-#define PADR16   	0x0002	/* RAM on 64kB boundary */
-#define PADR17    	0x0001	/* RAM on 128kB boundary */
-
-/*
-** Miscellaneous
-*/
-#define HASH_TABLE_LEN   64           /* Bits */
-#define HASH_BITS        0x003f       /* 6 LS bits */
-
-#define MASK_INTERRUPTS   1
-#define UNMASK_INTERRUPTS 0
-
-#define EISA_EN         0x0001        /* Enable EISA bus buffers */
-#define EISA_ID         iobase+0x0080 /* ID long word for EISA card */
-#define EISA_CTRL       iobase+0x0084 /* Control word for EISA card */
-
-/*
-** Include the IOCTL stuff
-*/
-#include <linux/sockios.h>
-
-#define	DEPCAIOCTL	SIOCDEVPRIVATE
-
-struct depca_ioctl {
-	unsigned short cmd;                /* Command to run */
-	unsigned short len;                /* Length of the data buffer */
-	unsigned char  __user *data;       /* Pointer to the data buffer */
-};
-
-/*
-** Recognised commands for the driver
-*/
-#define DEPCA_GET_HWADDR	0x01 /* Get the hardware address */
-#define DEPCA_SET_HWADDR	0x02 /* Get the hardware address */
-#define DEPCA_SET_PROM  	0x03 /* Set Promiscuous Mode */
-#define DEPCA_CLR_PROM  	0x04 /* Clear Promiscuous Mode */
-#define DEPCA_SAY_BOO	        0x05 /* Say "Boo!" to the kernel log file */
-#define DEPCA_GET_MCA   	0x06 /* Get a multicast address */
-#define DEPCA_SET_MCA   	0x07 /* Set a multicast address */
-#define DEPCA_CLR_MCA    	0x08 /* Clear a multicast address */
-#define DEPCA_MCA_EN    	0x09 /* Enable a multicast address group */
-#define DEPCA_GET_STATS  	0x0a /* Get the driver statistics */
-#define DEPCA_CLR_STATS 	0x0b /* Zero out the driver statistics */
-#define DEPCA_GET_REG   	0x0c /* Get the Register contents */
-#define DEPCA_SET_REG   	0x0d /* Set the Register contents */
-#define DEPCA_DUMP              0x0f /* Dump the DEPCA Status */
-
diff -druN linux-libre-3.1-gnu/drivers/net/dl2k.c linux-libre-3.2-gnu/drivers/net/dl2k.c
--- linux-libre-3.1-gnu/drivers/net/dl2k.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/dl2k.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1824 +0,0 @@
-/*  D-Link DL2000-based Gigabit Ethernet Adapter Linux driver */
-/*
-    Copyright (c) 2001, 2002 by D-Link Corporation
-    Written by Edward Peng.<edward_peng@dlink.com.tw>
-    Created 03-May-2001, base on Linux' sundance.c.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-*/
-
-#define DRV_NAME	"DL2000/TC902x-based linux driver"
-#define DRV_VERSION	"v1.19"
-#define DRV_RELDATE	"2007/08/12"
-#include "dl2k.h"
-#include <linux/dma-mapping.h>
-
-static char version[] __devinitdata =
-      KERN_INFO DRV_NAME " " DRV_VERSION " " DRV_RELDATE "\n";
-#define MAX_UNITS 8
-static int mtu[MAX_UNITS];
-static int vlan[MAX_UNITS];
-static int jumbo[MAX_UNITS];
-static char *media[MAX_UNITS];
-static int tx_flow=-1;
-static int rx_flow=-1;
-static int copy_thresh;
-static int rx_coalesce=10;	/* Rx frame count each interrupt */
-static int rx_timeout=200;	/* Rx DMA wait time in 640ns increments */
-static int tx_coalesce=16;	/* HW xmit count each TxDMAComplete */
-
-
-MODULE_AUTHOR ("Edward Peng");
-MODULE_DESCRIPTION ("D-Link DL2000-based Gigabit Ethernet Adapter");
-MODULE_LICENSE("GPL");
-module_param_array(mtu, int, NULL, 0);
-module_param_array(media, charp, NULL, 0);
-module_param_array(vlan, int, NULL, 0);
-module_param_array(jumbo, int, NULL, 0);
-module_param(tx_flow, int, 0);
-module_param(rx_flow, int, 0);
-module_param(copy_thresh, int, 0);
-module_param(rx_coalesce, int, 0);	/* Rx frame count each interrupt */
-module_param(rx_timeout, int, 0);	/* Rx DMA wait time in 64ns increments */
-module_param(tx_coalesce, int, 0); /* HW xmit count each TxDMAComplete */
-
-
-/* Enable the default interrupts */
-#define DEFAULT_INTR (RxDMAComplete | HostError | IntRequested | TxDMAComplete| \
-       UpdateStats | LinkEvent)
-#define EnableInt() \
-writew(DEFAULT_INTR, ioaddr + IntEnable)
-
-static const int max_intrloop = 50;
-static const int multicast_filter_limit = 0x40;
-
-static int rio_open (struct net_device *dev);
-static void rio_timer (unsigned long data);
-static void rio_tx_timeout (struct net_device *dev);
-static void alloc_list (struct net_device *dev);
-static netdev_tx_t start_xmit (struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t rio_interrupt (int irq, void *dev_instance);
-static void rio_free_tx (struct net_device *dev, int irq);
-static void tx_error (struct net_device *dev, int tx_status);
-static int receive_packet (struct net_device *dev);
-static void rio_error (struct net_device *dev, int int_status);
-static int change_mtu (struct net_device *dev, int new_mtu);
-static void set_multicast (struct net_device *dev);
-static struct net_device_stats *get_stats (struct net_device *dev);
-static int clear_stats (struct net_device *dev);
-static int rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
-static int rio_close (struct net_device *dev);
-static int find_miiphy (struct net_device *dev);
-static int parse_eeprom (struct net_device *dev);
-static int read_eeprom (long ioaddr, int eep_addr);
-static int mii_wait_link (struct net_device *dev, int wait);
-static int mii_set_media (struct net_device *dev);
-static int mii_get_media (struct net_device *dev);
-static int mii_set_media_pcs (struct net_device *dev);
-static int mii_get_media_pcs (struct net_device *dev);
-static int mii_read (struct net_device *dev, int phy_addr, int reg_num);
-static int mii_write (struct net_device *dev, int phy_addr, int reg_num,
-		      u16 data);
-
-static const struct ethtool_ops ethtool_ops;
-
-static const struct net_device_ops netdev_ops = {
-	.ndo_open		= rio_open,
-	.ndo_start_xmit	= start_xmit,
-	.ndo_stop		= rio_close,
-	.ndo_get_stats		= get_stats,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_set_multicast_list = set_multicast,
-	.ndo_do_ioctl		= rio_ioctl,
-	.ndo_tx_timeout		= rio_tx_timeout,
-	.ndo_change_mtu		= change_mtu,
-};
-
-static int __devinit
-rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	struct net_device *dev;
-	struct netdev_private *np;
-	static int card_idx;
-	int chip_idx = ent->driver_data;
-	int err, irq;
-	long ioaddr;
-	static int version_printed;
-	void *ring_space;
-	dma_addr_t ring_dma;
-
-	if (!version_printed++)
-		printk ("%s", version);
-
-	err = pci_enable_device (pdev);
-	if (err)
-		return err;
-
-	irq = pdev->irq;
-	err = pci_request_regions (pdev, "dl2k");
-	if (err)
-		goto err_out_disable;
-
-	pci_set_master (pdev);
-	dev = alloc_etherdev (sizeof (*np));
-	if (!dev) {
-		err = -ENOMEM;
-		goto err_out_res;
-	}
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-#ifdef MEM_MAPPING
-	ioaddr = pci_resource_start (pdev, 1);
-	ioaddr = (long) ioremap (ioaddr, RIO_IO_SIZE);
-	if (!ioaddr) {
-		err = -ENOMEM;
-		goto err_out_dev;
-	}
-#else
-	ioaddr = pci_resource_start (pdev, 0);
-#endif
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-	np = netdev_priv(dev);
-	np->chip_id = chip_idx;
-	np->pdev = pdev;
-	spin_lock_init (&np->tx_lock);
-	spin_lock_init (&np->rx_lock);
-
-	/* Parse manual configuration */
-	np->an_enable = 1;
-	np->tx_coalesce = 1;
-	if (card_idx < MAX_UNITS) {
-		if (media[card_idx] != NULL) {
-			np->an_enable = 0;
-			if (strcmp (media[card_idx], "auto") == 0 ||
-			    strcmp (media[card_idx], "autosense") == 0 ||
-			    strcmp (media[card_idx], "0") == 0 ) {
-				np->an_enable = 2;
-			} else if (strcmp (media[card_idx], "100mbps_fd") == 0 ||
-			    strcmp (media[card_idx], "4") == 0) {
-				np->speed = 100;
-				np->full_duplex = 1;
-			} else if (strcmp (media[card_idx], "100mbps_hd") == 0 ||
-				   strcmp (media[card_idx], "3") == 0) {
-				np->speed = 100;
-				np->full_duplex = 0;
-			} else if (strcmp (media[card_idx], "10mbps_fd") == 0 ||
-				   strcmp (media[card_idx], "2") == 0) {
-				np->speed = 10;
-				np->full_duplex = 1;
-			} else if (strcmp (media[card_idx], "10mbps_hd") == 0 ||
-				   strcmp (media[card_idx], "1") == 0) {
-				np->speed = 10;
-				np->full_duplex = 0;
-			} else if (strcmp (media[card_idx], "1000mbps_fd") == 0 ||
-				 strcmp (media[card_idx], "6") == 0) {
-				np->speed=1000;
-				np->full_duplex=1;
-			} else if (strcmp (media[card_idx], "1000mbps_hd") == 0 ||
-				 strcmp (media[card_idx], "5") == 0) {
-				np->speed = 1000;
-				np->full_duplex = 0;
-			} else {
-				np->an_enable = 1;
-			}
-		}
-		if (jumbo[card_idx] != 0) {
-			np->jumbo = 1;
-			dev->mtu = MAX_JUMBO;
-		} else {
-			np->jumbo = 0;
-			if (mtu[card_idx] > 0 && mtu[card_idx] < PACKET_SIZE)
-				dev->mtu = mtu[card_idx];
-		}
-		np->vlan = (vlan[card_idx] > 0 && vlan[card_idx] < 4096) ?
-		    vlan[card_idx] : 0;
-		if (rx_coalesce > 0 && rx_timeout > 0) {
-			np->rx_coalesce = rx_coalesce;
-			np->rx_timeout = rx_timeout;
-			np->coalesce = 1;
-		}
-		np->tx_flow = (tx_flow == 0) ? 0 : 1;
-		np->rx_flow = (rx_flow == 0) ? 0 : 1;
-
-		if (tx_coalesce < 1)
-			tx_coalesce = 1;
-		else if (tx_coalesce > TX_RING_SIZE-1)
-			tx_coalesce = TX_RING_SIZE - 1;
-	}
-	dev->netdev_ops = &netdev_ops;
-	dev->watchdog_timeo = TX_TIMEOUT;
-	SET_ETHTOOL_OPS(dev, &ethtool_ops);
-#if 0
-	dev->features = NETIF_F_IP_CSUM;
-#endif
-	pci_set_drvdata (pdev, dev);
-
-	ring_space = pci_alloc_consistent (pdev, TX_TOTAL_SIZE, &ring_dma);
-	if (!ring_space)
-		goto err_out_iounmap;
-	np->tx_ring = ring_space;
-	np->tx_ring_dma = ring_dma;
-
-	ring_space = pci_alloc_consistent (pdev, RX_TOTAL_SIZE, &ring_dma);
-	if (!ring_space)
-		goto err_out_unmap_tx;
-	np->rx_ring = ring_space;
-	np->rx_ring_dma = ring_dma;
-
-	/* Parse eeprom data */
-	parse_eeprom (dev);
-
-	/* Find PHY address */
-	err = find_miiphy (dev);
-	if (err)
-		goto err_out_unmap_rx;
-
-	/* Fiber device? */
-	np->phy_media = (readw(ioaddr + ASICCtrl) & PhyMedia) ? 1 : 0;
-	np->link_status = 0;
-	/* Set media and reset PHY */
-	if (np->phy_media) {
-		/* default Auto-Negotiation for fiber deivices */
-	 	if (np->an_enable == 2) {
-			np->an_enable = 1;
-		}
-		mii_set_media_pcs (dev);
-	} else {
-		/* Auto-Negotiation is mandatory for 1000BASE-T,
-		   IEEE 802.3ab Annex 28D page 14 */
-		if (np->speed == 1000)
-			np->an_enable = 1;
-		mii_set_media (dev);
-	}
-
-	err = register_netdev (dev);
-	if (err)
-		goto err_out_unmap_rx;
-
-	card_idx++;
-
-	printk (KERN_INFO "%s: %s, %pM, IRQ %d\n",
-		dev->name, np->name, dev->dev_addr, irq);
-	if (tx_coalesce > 1)
-		printk(KERN_INFO "tx_coalesce:\t%d packets\n",
-				tx_coalesce);
-	if (np->coalesce)
-		printk(KERN_INFO
-		       "rx_coalesce:\t%d packets\n"
-		       "rx_timeout: \t%d ns\n",
-				np->rx_coalesce, np->rx_timeout*640);
-	if (np->vlan)
-		printk(KERN_INFO "vlan(id):\t%d\n", np->vlan);
-	return 0;
-
-      err_out_unmap_rx:
-	pci_free_consistent (pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma);
-      err_out_unmap_tx:
-	pci_free_consistent (pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma);
-      err_out_iounmap:
-#ifdef MEM_MAPPING
-	iounmap ((void *) ioaddr);
-
-      err_out_dev:
-#endif
-	free_netdev (dev);
-
-      err_out_res:
-	pci_release_regions (pdev);
-
-      err_out_disable:
-	pci_disable_device (pdev);
-	return err;
-}
-
-static int
-find_miiphy (struct net_device *dev)
-{
-	int i, phy_found = 0;
-	struct netdev_private *np;
-	long ioaddr;
-	np = netdev_priv(dev);
-	ioaddr = dev->base_addr;
-	np->phy_addr = 1;
-
-	for (i = 31; i >= 0; i--) {
-		int mii_status = mii_read (dev, i, 1);
-		if (mii_status != 0xffff && mii_status != 0x0000) {
-			np->phy_addr = i;
-			phy_found++;
-		}
-	}
-	if (!phy_found) {
-		printk (KERN_ERR "%s: No MII PHY found!\n", dev->name);
-		return -ENODEV;
-	}
-	return 0;
-}
-
-static int
-parse_eeprom (struct net_device *dev)
-{
-	int i, j;
-	long ioaddr = dev->base_addr;
-	u8 sromdata[256];
-	u8 *psib;
-	u32 crc;
-	PSROM_t psrom = (PSROM_t) sromdata;
-	struct netdev_private *np = netdev_priv(dev);
-
-	int cid, next;
-
-#ifdef	MEM_MAPPING
-	ioaddr = pci_resource_start (np->pdev, 0);
-#endif
-	/* Read eeprom */
-	for (i = 0; i < 128; i++) {
-		((__le16 *) sromdata)[i] = cpu_to_le16(read_eeprom (ioaddr, i));
-	}
-#ifdef	MEM_MAPPING
-	ioaddr = dev->base_addr;
-#endif
-	if (np->pdev->vendor == PCI_VENDOR_ID_DLINK) {	/* D-Link Only */
-		/* Check CRC */
-		crc = ~ether_crc_le (256 - 4, sromdata);
-		if (psrom->crc != cpu_to_le32(crc)) {
-			printk (KERN_ERR "%s: EEPROM data CRC error.\n",
-					dev->name);
-			return -1;
-		}
-	}
-
-	/* Set MAC address */
-	for (i = 0; i < 6; i++)
-		dev->dev_addr[i] = psrom->mac_addr[i];
-
-	if (np->pdev->vendor != PCI_VENDOR_ID_DLINK) {
-		return 0;
-	}
-
-	/* Parse Software Information Block */
-	i = 0x30;
-	psib = (u8 *) sromdata;
-	do {
-		cid = psib[i++];
-		next = psib[i++];
-		if ((cid == 0 && next == 0) || (cid == 0xff && next == 0xff)) {
-			printk (KERN_ERR "Cell data error\n");
-			return -1;
-		}
-		switch (cid) {
-		case 0:	/* Format version */
-			break;
-		case 1:	/* End of cell */
-			return 0;
-		case 2:	/* Duplex Polarity */
-			np->duplex_polarity = psib[i];
-			writeb (readb (ioaddr + PhyCtrl) | psib[i],
-				ioaddr + PhyCtrl);
-			break;
-		case 3:	/* Wake Polarity */
-			np->wake_polarity = psib[i];
-			break;
-		case 9:	/* Adapter description */
-			j = (next - i > 255) ? 255 : next - i;
-			memcpy (np->name, &(psib[i]), j);
-			break;
-		case 4:
-		case 5:
-		case 6:
-		case 7:
-		case 8:	/* Reversed */
-			break;
-		default:	/* Unknown cell */
-			return -1;
-		}
-		i = next;
-	} while (1);
-
-	return 0;
-}
-
-static int
-rio_open (struct net_device *dev)
-{
-	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	int i;
-	u16 macctrl;
-
-	i = request_irq (dev->irq, rio_interrupt, IRQF_SHARED, dev->name, dev);
-	if (i)
-		return i;
-
-	/* Reset all logic functions */
-	writew (GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset,
-		ioaddr + ASICCtrl + 2);
-	mdelay(10);
-
-	/* DebugCtrl bit 4, 5, 9 must set */
-	writel (readl (ioaddr + DebugCtrl) | 0x0230, ioaddr + DebugCtrl);
-
-	/* Jumbo frame */
-	if (np->jumbo != 0)
-		writew (MAX_JUMBO+14, ioaddr + MaxFrameSize);
-
-	alloc_list (dev);
-
-	/* Get station address */
-	for (i = 0; i < 6; i++)
-		writeb (dev->dev_addr[i], ioaddr + StationAddr0 + i);
-
-	set_multicast (dev);
-	if (np->coalesce) {
-		writel (np->rx_coalesce | np->rx_timeout << 16,
-			ioaddr + RxDMAIntCtrl);
-	}
-	/* Set RIO to poll every N*320nsec. */
-	writeb (0x20, ioaddr + RxDMAPollPeriod);
-	writeb (0xff, ioaddr + TxDMAPollPeriod);
-	writeb (0x30, ioaddr + RxDMABurstThresh);
-	writeb (0x30, ioaddr + RxDMAUrgentThresh);
-	writel (0x0007ffff, ioaddr + RmonStatMask);
-	/* clear statistics */
-	clear_stats (dev);
-
-	/* VLAN supported */
-	if (np->vlan) {
-		/* priority field in RxDMAIntCtrl  */
-		writel (readl(ioaddr + RxDMAIntCtrl) | 0x7 << 10,
-			ioaddr + RxDMAIntCtrl);
-		/* VLANId */
-		writew (np->vlan, ioaddr + VLANId);
-		/* Length/Type should be 0x8100 */
-		writel (0x8100 << 16 | np->vlan, ioaddr + VLANTag);
-		/* Enable AutoVLANuntagging, but disable AutoVLANtagging.
-		   VLAN information tagged by TFC' VID, CFI fields. */
-		writel (readl (ioaddr + MACCtrl) | AutoVLANuntagging,
-			ioaddr + MACCtrl);
-	}
-
-	init_timer (&np->timer);
-	np->timer.expires = jiffies + 1*HZ;
-	np->timer.data = (unsigned long) dev;
-	np->timer.function = rio_timer;
-	add_timer (&np->timer);
-
-	/* Start Tx/Rx */
-	writel (readl (ioaddr + MACCtrl) | StatsEnable | RxEnable | TxEnable,
-			ioaddr + MACCtrl);
-
-	macctrl = 0;
-	macctrl |= (np->vlan) ? AutoVLANuntagging : 0;
-	macctrl |= (np->full_duplex) ? DuplexSelect : 0;
-	macctrl |= (np->tx_flow) ? TxFlowControlEnable : 0;
-	macctrl |= (np->rx_flow) ? RxFlowControlEnable : 0;
-	writew(macctrl,	ioaddr + MACCtrl);
-
-	netif_start_queue (dev);
-
-	/* Enable default interrupts */
-	EnableInt ();
-	return 0;
-}
-
-static void
-rio_timer (unsigned long data)
-{
-	struct net_device *dev = (struct net_device *)data;
-	struct netdev_private *np = netdev_priv(dev);
-	unsigned int entry;
-	int next_tick = 1*HZ;
-	unsigned long flags;
-
-	spin_lock_irqsave(&np->rx_lock, flags);
-	/* Recover rx ring exhausted error */
-	if (np->cur_rx - np->old_rx >= RX_RING_SIZE) {
-		printk(KERN_INFO "Try to recover rx ring exhausted...\n");
-		/* Re-allocate skbuffs to fill the descriptor ring */
-		for (; np->cur_rx - np->old_rx > 0; np->old_rx++) {
-			struct sk_buff *skb;
-			entry = np->old_rx % RX_RING_SIZE;
-			/* Dropped packets don't need to re-allocate */
-			if (np->rx_skbuff[entry] == NULL) {
-				skb = netdev_alloc_skb_ip_align(dev,
-								np->rx_buf_sz);
-				if (skb == NULL) {
-					np->rx_ring[entry].fraginfo = 0;
-					printk (KERN_INFO
-						"%s: Still unable to re-allocate Rx skbuff.#%d\n",
-						dev->name, entry);
-					break;
-				}
-				np->rx_skbuff[entry] = skb;
-				np->rx_ring[entry].fraginfo =
-				    cpu_to_le64 (pci_map_single
-					 (np->pdev, skb->data, np->rx_buf_sz,
-					  PCI_DMA_FROMDEVICE));
-			}
-			np->rx_ring[entry].fraginfo |=
-			    cpu_to_le64((u64)np->rx_buf_sz << 48);
-			np->rx_ring[entry].status = 0;
-		} /* end for */
-	} /* end if */
-	spin_unlock_irqrestore (&np->rx_lock, flags);
-	np->timer.expires = jiffies + next_tick;
-	add_timer(&np->timer);
-}
-
-static void
-rio_tx_timeout (struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-
-	printk (KERN_INFO "%s: Tx timed out (%4.4x), is buffer full?\n",
-		dev->name, readl (ioaddr + TxStatus));
-	rio_free_tx(dev, 0);
-	dev->if_port = 0;
-	dev->trans_start = jiffies; /* prevent tx timeout */
-}
-
- /* allocate and initialize Tx and Rx descriptors */
-static void
-alloc_list (struct net_device *dev)
-{
-	struct netdev_private *np = netdev_priv(dev);
-	int i;
-
-	np->cur_rx = np->cur_tx = 0;
-	np->old_rx = np->old_tx = 0;
-	np->rx_buf_sz = (dev->mtu <= 1500 ? PACKET_SIZE : dev->mtu + 32);
-
-	/* Initialize Tx descriptors, TFDListPtr leaves in start_xmit(). */
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		np->tx_skbuff[i] = NULL;
-		np->tx_ring[i].status = cpu_to_le64 (TFDDone);
-		np->tx_ring[i].next_desc = cpu_to_le64 (np->tx_ring_dma +
-					      ((i+1)%TX_RING_SIZE) *
-					      sizeof (struct netdev_desc));
-	}
-
-	/* Initialize Rx descriptors */
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		np->rx_ring[i].next_desc = cpu_to_le64 (np->rx_ring_dma +
-						((i + 1) % RX_RING_SIZE) *
-						sizeof (struct netdev_desc));
-		np->rx_ring[i].status = 0;
-		np->rx_ring[i].fraginfo = 0;
-		np->rx_skbuff[i] = NULL;
-	}
-
-	/* Allocate the rx buffers */
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		/* Allocated fixed size of skbuff */
-		struct sk_buff *skb;
-
-		skb = netdev_alloc_skb_ip_align(dev, np->rx_buf_sz);
-		np->rx_skbuff[i] = skb;
-		if (skb == NULL) {
-			printk (KERN_ERR
-				"%s: alloc_list: allocate Rx buffer error! ",
-				dev->name);
-			break;
-		}
-		/* Rubicon now supports 40 bits of addressing space. */
-		np->rx_ring[i].fraginfo =
-		    cpu_to_le64 ( pci_map_single (
-			 	  np->pdev, skb->data, np->rx_buf_sz,
-				  PCI_DMA_FROMDEVICE));
-		np->rx_ring[i].fraginfo |= cpu_to_le64((u64)np->rx_buf_sz << 48);
-	}
-
-	/* Set RFDListPtr */
-	writel (np->rx_ring_dma, dev->base_addr + RFDListPtr0);
-	writel (0, dev->base_addr + RFDListPtr1);
-}
-
-static netdev_tx_t
-start_xmit (struct sk_buff *skb, struct net_device *dev)
-{
-	struct netdev_private *np = netdev_priv(dev);
-	struct netdev_desc *txdesc;
-	unsigned entry;
-	u32 ioaddr;
-	u64 tfc_vlan_tag = 0;
-
-	if (np->link_status == 0) {	/* Link Down */
-		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-	ioaddr = dev->base_addr;
-	entry = np->cur_tx % TX_RING_SIZE;
-	np->tx_skbuff[entry] = skb;
-	txdesc = &np->tx_ring[entry];
-
-#if 0
-	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		txdesc->status |=
-		    cpu_to_le64 (TCPChecksumEnable | UDPChecksumEnable |
-				 IPChecksumEnable);
-	}
-#endif
-	if (np->vlan) {
-		tfc_vlan_tag = VLANTagInsert |
-		    ((u64)np->vlan << 32) |
-		    ((u64)skb->priority << 45);
-	}
-	txdesc->fraginfo = cpu_to_le64 (pci_map_single (np->pdev, skb->data,
-							skb->len,
-							PCI_DMA_TODEVICE));
-	txdesc->fraginfo |= cpu_to_le64((u64)skb->len << 48);
-
-	/* DL2K bug: DMA fails to get next descriptor ptr in 10Mbps mode
-	 * Work around: Always use 1 descriptor in 10Mbps mode */
-	if (entry % np->tx_coalesce == 0 || np->speed == 10)
-		txdesc->status = cpu_to_le64 (entry | tfc_vlan_tag |
-					      WordAlignDisable |
-					      TxDMAIndicate |
-					      (1 << FragCountShift));
-	else
-		txdesc->status = cpu_to_le64 (entry | tfc_vlan_tag |
-					      WordAlignDisable |
-					      (1 << FragCountShift));
-
-	/* TxDMAPollNow */
-	writel (readl (ioaddr + DMACtrl) | 0x00001000, ioaddr + DMACtrl);
-	/* Schedule ISR */
-	writel(10000, ioaddr + CountDown);
-	np->cur_tx = (np->cur_tx + 1) % TX_RING_SIZE;
-	if ((np->cur_tx - np->old_tx + TX_RING_SIZE) % TX_RING_SIZE
-			< TX_QUEUE_LEN - 1 && np->speed != 10) {
-		/* do nothing */
-	} else if (!netif_queue_stopped(dev)) {
-		netif_stop_queue (dev);
-	}
-
-	/* The first TFDListPtr */
-	if (readl (dev->base_addr + TFDListPtr0) == 0) {
-		writel (np->tx_ring_dma + entry * sizeof (struct netdev_desc),
-			dev->base_addr + TFDListPtr0);
-		writel (0, dev->base_addr + TFDListPtr1);
-	}
-
-	return NETDEV_TX_OK;
-}
-
-static irqreturn_t
-rio_interrupt (int irq, void *dev_instance)
-{
-	struct net_device *dev = dev_instance;
-	struct netdev_private *np;
-	unsigned int_status;
-	long ioaddr;
-	int cnt = max_intrloop;
-	int handled = 0;
-
-	ioaddr = dev->base_addr;
-	np = netdev_priv(dev);
-	while (1) {
-		int_status = readw (ioaddr + IntStatus);
-		writew (int_status, ioaddr + IntStatus);
-		int_status &= DEFAULT_INTR;
-		if (int_status == 0 || --cnt < 0)
-			break;
-		handled = 1;
-		/* Processing received packets */
-		if (int_status & RxDMAComplete)
-			receive_packet (dev);
-		/* TxDMAComplete interrupt */
-		if ((int_status & (TxDMAComplete|IntRequested))) {
-			int tx_status;
-			tx_status = readl (ioaddr + TxStatus);
-			if (tx_status & 0x01)
-				tx_error (dev, tx_status);
-			/* Free used tx skbuffs */
-			rio_free_tx (dev, 1);
-		}
-
-		/* Handle uncommon events */
-		if (int_status &
-		    (HostError | LinkEvent | UpdateStats))
-			rio_error (dev, int_status);
-	}
-	if (np->cur_tx != np->old_tx)
-		writel (100, ioaddr + CountDown);
-	return IRQ_RETVAL(handled);
-}
-
-static inline dma_addr_t desc_to_dma(struct netdev_desc *desc)
-{
-	return le64_to_cpu(desc->fraginfo) & DMA_BIT_MASK(48);
-}
-
-static void
-rio_free_tx (struct net_device *dev, int irq)
-{
-	struct netdev_private *np = netdev_priv(dev);
-	int entry = np->old_tx % TX_RING_SIZE;
-	int tx_use = 0;
-	unsigned long flag = 0;
-
-	if (irq)
-		spin_lock(&np->tx_lock);
-	else
-		spin_lock_irqsave(&np->tx_lock, flag);
-
-	/* Free used tx skbuffs */
-	while (entry != np->cur_tx) {
-		struct sk_buff *skb;
-
-		if (!(np->tx_ring[entry].status & cpu_to_le64(TFDDone)))
-			break;
-		skb = np->tx_skbuff[entry];
-		pci_unmap_single (np->pdev,
-				  desc_to_dma(&np->tx_ring[entry]),
-				  skb->len, PCI_DMA_TODEVICE);
-		if (irq)
-			dev_kfree_skb_irq (skb);
-		else
-			dev_kfree_skb (skb);
-
-		np->tx_skbuff[entry] = NULL;
-		entry = (entry + 1) % TX_RING_SIZE;
-		tx_use++;
-	}
-	if (irq)
-		spin_unlock(&np->tx_lock);
-	else
-		spin_unlock_irqrestore(&np->tx_lock, flag);
-	np->old_tx = entry;
-
-	/* If the ring is no longer full, clear tx_full and
-	   call netif_wake_queue() */
-
-	if (netif_queue_stopped(dev) &&
-	    ((np->cur_tx - np->old_tx + TX_RING_SIZE) % TX_RING_SIZE
-	    < TX_QUEUE_LEN - 1 || np->speed == 10)) {
-		netif_wake_queue (dev);
-	}
-}
-
-static void
-tx_error (struct net_device *dev, int tx_status)
-{
-	struct netdev_private *np;
-	long ioaddr = dev->base_addr;
-	int frame_id;
-	int i;
-
-	np = netdev_priv(dev);
-
-	frame_id = (tx_status & 0xffff0000);
-	printk (KERN_ERR "%s: Transmit error, TxStatus %4.4x, FrameId %d.\n",
-		dev->name, tx_status, frame_id);
-	np->stats.tx_errors++;
-	/* Ttransmit Underrun */
-	if (tx_status & 0x10) {
-		np->stats.tx_fifo_errors++;
-		writew (readw (ioaddr + TxStartThresh) + 0x10,
-			ioaddr + TxStartThresh);
-		/* Transmit Underrun need to set TxReset, DMARest, FIFOReset */
-		writew (TxReset | DMAReset | FIFOReset | NetworkReset,
-			ioaddr + ASICCtrl + 2);
-		/* Wait for ResetBusy bit clear */
-		for (i = 50; i > 0; i--) {
-			if ((readw (ioaddr + ASICCtrl + 2) & ResetBusy) == 0)
-				break;
-			mdelay (1);
-		}
-		rio_free_tx (dev, 1);
-		/* Reset TFDListPtr */
-		writel (np->tx_ring_dma +
-			np->old_tx * sizeof (struct netdev_desc),
-			dev->base_addr + TFDListPtr0);
-		writel (0, dev->base_addr + TFDListPtr1);
-
-		/* Let TxStartThresh stay default value */
-	}
-	/* Late Collision */
-	if (tx_status & 0x04) {
-		np->stats.tx_fifo_errors++;
-		/* TxReset and clear FIFO */
-		writew (TxReset | FIFOReset, ioaddr + ASICCtrl + 2);
-		/* Wait reset done */
-		for (i = 50; i > 0; i--) {
-			if ((readw (ioaddr + ASICCtrl + 2) & ResetBusy) == 0)
-				break;
-			mdelay (1);
-		}
-		/* Let TxStartThresh stay default value */
-	}
-	/* Maximum Collisions */
-#ifdef ETHER_STATS
-	if (tx_status & 0x08)
-		np->stats.collisions16++;
-#else
-	if (tx_status & 0x08)
-		np->stats.collisions++;
-#endif
-	/* Restart the Tx */
-	writel (readw (dev->base_addr + MACCtrl) | TxEnable, ioaddr + MACCtrl);
-}
-
-static int
-receive_packet (struct net_device *dev)
-{
-	struct netdev_private *np = netdev_priv(dev);
-	int entry = np->cur_rx % RX_RING_SIZE;
-	int cnt = 30;
-
-	/* If RFDDone, FrameStart and FrameEnd set, there is a new packet in. */
-	while (1) {
-		struct netdev_desc *desc = &np->rx_ring[entry];
-		int pkt_len;
-		u64 frame_status;
-
-		if (!(desc->status & cpu_to_le64(RFDDone)) ||
-		    !(desc->status & cpu_to_le64(FrameStart)) ||
-		    !(desc->status & cpu_to_le64(FrameEnd)))
-			break;
-
-		/* Chip omits the CRC. */
-		frame_status = le64_to_cpu(desc->status);
-		pkt_len = frame_status & 0xffff;
-		if (--cnt < 0)
-			break;
-		/* Update rx error statistics, drop packet. */
-		if (frame_status & RFS_Errors) {
-			np->stats.rx_errors++;
-			if (frame_status & (RxRuntFrame | RxLengthError))
-				np->stats.rx_length_errors++;
-			if (frame_status & RxFCSError)
-				np->stats.rx_crc_errors++;
-			if (frame_status & RxAlignmentError && np->speed != 1000)
-				np->stats.rx_frame_errors++;
-			if (frame_status & RxFIFOOverrun)
-	 			np->stats.rx_fifo_errors++;
-		} else {
-			struct sk_buff *skb;
-
-			/* Small skbuffs for short packets */
-			if (pkt_len > copy_thresh) {
-				pci_unmap_single (np->pdev,
-						  desc_to_dma(desc),
-						  np->rx_buf_sz,
-						  PCI_DMA_FROMDEVICE);
-				skb_put (skb = np->rx_skbuff[entry], pkt_len);
-				np->rx_skbuff[entry] = NULL;
-			} else if ((skb = netdev_alloc_skb_ip_align(dev, pkt_len))) {
-				pci_dma_sync_single_for_cpu(np->pdev,
-							    desc_to_dma(desc),
-							    np->rx_buf_sz,
-							    PCI_DMA_FROMDEVICE);
-				skb_copy_to_linear_data (skb,
-						  np->rx_skbuff[entry]->data,
-						  pkt_len);
-				skb_put (skb, pkt_len);
-				pci_dma_sync_single_for_device(np->pdev,
-							       desc_to_dma(desc),
-							       np->rx_buf_sz,
-							       PCI_DMA_FROMDEVICE);
-			}
-			skb->protocol = eth_type_trans (skb, dev);
-#if 0
-			/* Checksum done by hw, but csum value unavailable. */
-			if (np->pdev->pci_rev_id >= 0x0c &&
-				!(frame_status & (TCPError | UDPError | IPError))) {
-				skb->ip_summed = CHECKSUM_UNNECESSARY;
-			}
-#endif
-			netif_rx (skb);
-		}
-		entry = (entry + 1) % RX_RING_SIZE;
-	}
-	spin_lock(&np->rx_lock);
-	np->cur_rx = entry;
-	/* Re-allocate skbuffs to fill the descriptor ring */
-	entry = np->old_rx;
-	while (entry != np->cur_rx) {
-		struct sk_buff *skb;
-		/* Dropped packets don't need to re-allocate */
-		if (np->rx_skbuff[entry] == NULL) {
-			skb = netdev_alloc_skb_ip_align(dev, np->rx_buf_sz);
-			if (skb == NULL) {
-				np->rx_ring[entry].fraginfo = 0;
-				printk (KERN_INFO
-					"%s: receive_packet: "
-					"Unable to re-allocate Rx skbuff.#%d\n",
-					dev->name, entry);
-				break;
-			}
-			np->rx_skbuff[entry] = skb;
-			np->rx_ring[entry].fraginfo =
-			    cpu_to_le64 (pci_map_single
-					 (np->pdev, skb->data, np->rx_buf_sz,
-					  PCI_DMA_FROMDEVICE));
-		}
-		np->rx_ring[entry].fraginfo |=
-		    cpu_to_le64((u64)np->rx_buf_sz << 48);
-		np->rx_ring[entry].status = 0;
-		entry = (entry + 1) % RX_RING_SIZE;
-	}
-	np->old_rx = entry;
-	spin_unlock(&np->rx_lock);
-	return 0;
-}
-
-static void
-rio_error (struct net_device *dev, int int_status)
-{
-	long ioaddr = dev->base_addr;
-	struct netdev_private *np = netdev_priv(dev);
-	u16 macctrl;
-
-	/* Link change event */
-	if (int_status & LinkEvent) {
-		if (mii_wait_link (dev, 10) == 0) {
-			printk (KERN_INFO "%s: Link up\n", dev->name);
-			if (np->phy_media)
-				mii_get_media_pcs (dev);
-			else
-				mii_get_media (dev);
-			if (np->speed == 1000)
-				np->tx_coalesce = tx_coalesce;
-			else
-				np->tx_coalesce = 1;
-			macctrl = 0;
-			macctrl |= (np->vlan) ? AutoVLANuntagging : 0;
-			macctrl |= (np->full_duplex) ? DuplexSelect : 0;
-			macctrl |= (np->tx_flow) ?
-				TxFlowControlEnable : 0;
-			macctrl |= (np->rx_flow) ?
-				RxFlowControlEnable : 0;
-			writew(macctrl,	ioaddr + MACCtrl);
-			np->link_status = 1;
-			netif_carrier_on(dev);
-		} else {
-			printk (KERN_INFO "%s: Link off\n", dev->name);
-			np->link_status = 0;
-			netif_carrier_off(dev);
-		}
-	}
-
-	/* UpdateStats statistics registers */
-	if (int_status & UpdateStats) {
-		get_stats (dev);
-	}
-
-	/* PCI Error, a catastronphic error related to the bus interface
-	   occurs, set GlobalReset and HostReset to reset. */
-	if (int_status & HostError) {
-		printk (KERN_ERR "%s: HostError! IntStatus %4.4x.\n",
-			dev->name, int_status);
-		writew (GlobalReset | HostReset, ioaddr + ASICCtrl + 2);
-		mdelay (500);
-	}
-}
-
-static struct net_device_stats *
-get_stats (struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-	struct netdev_private *np = netdev_priv(dev);
-#ifdef MEM_MAPPING
-	int i;
-#endif
-	unsigned int stat_reg;
-
-	/* All statistics registers need to be acknowledged,
-	   else statistic overflow could cause problems */
-
-	np->stats.rx_packets += readl (ioaddr + FramesRcvOk);
-	np->stats.tx_packets += readl (ioaddr + FramesXmtOk);
-	np->stats.rx_bytes += readl (ioaddr + OctetRcvOk);
-	np->stats.tx_bytes += readl (ioaddr + OctetXmtOk);
-
-	np->stats.multicast = readl (ioaddr + McstFramesRcvdOk);
-	np->stats.collisions += readl (ioaddr + SingleColFrames)
-			     +  readl (ioaddr + MultiColFrames);
-
-	/* detailed tx errors */
-	stat_reg = readw (ioaddr + FramesAbortXSColls);
-	np->stats.tx_aborted_errors += stat_reg;
-	np->stats.tx_errors += stat_reg;
-
-	stat_reg = readw (ioaddr + CarrierSenseErrors);
-	np->stats.tx_carrier_errors += stat_reg;
-	np->stats.tx_errors += stat_reg;
-
-	/* Clear all other statistic register. */
-	readl (ioaddr + McstOctetXmtOk);
-	readw (ioaddr + BcstFramesXmtdOk);
-	readl (ioaddr + McstFramesXmtdOk);
-	readw (ioaddr + BcstFramesRcvdOk);
-	readw (ioaddr + MacControlFramesRcvd);
-	readw (ioaddr + FrameTooLongErrors);
-	readw (ioaddr + InRangeLengthErrors);
-	readw (ioaddr + FramesCheckSeqErrors);
-	readw (ioaddr + FramesLostRxErrors);
-	readl (ioaddr + McstOctetXmtOk);
-	readl (ioaddr + BcstOctetXmtOk);
-	readl (ioaddr + McstFramesXmtdOk);
-	readl (ioaddr + FramesWDeferredXmt);
-	readl (ioaddr + LateCollisions);
-	readw (ioaddr + BcstFramesXmtdOk);
-	readw (ioaddr + MacControlFramesXmtd);
-	readw (ioaddr + FramesWEXDeferal);
-
-#ifdef MEM_MAPPING
-	for (i = 0x100; i <= 0x150; i += 4)
-		readl (ioaddr + i);
-#endif
-	readw (ioaddr + TxJumboFrames);
-	readw (ioaddr + RxJumboFrames);
-	readw (ioaddr + TCPCheckSumErrors);
-	readw (ioaddr + UDPCheckSumErrors);
-	readw (ioaddr + IPCheckSumErrors);
-	return &np->stats;
-}
-
-static int
-clear_stats (struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-#ifdef MEM_MAPPING
-	int i;
-#endif
-
-	/* All statistics registers need to be acknowledged,
-	   else statistic overflow could cause problems */
-	readl (ioaddr + FramesRcvOk);
-	readl (ioaddr + FramesXmtOk);
-	readl (ioaddr + OctetRcvOk);
-	readl (ioaddr + OctetXmtOk);
-
-	readl (ioaddr + McstFramesRcvdOk);
-	readl (ioaddr + SingleColFrames);
-	readl (ioaddr + MultiColFrames);
-	readl (ioaddr + LateCollisions);
-	/* detailed rx errors */
-	readw (ioaddr + FrameTooLongErrors);
-	readw (ioaddr + InRangeLengthErrors);
-	readw (ioaddr + FramesCheckSeqErrors);
-	readw (ioaddr + FramesLostRxErrors);
-
-	/* detailed tx errors */
-	readw (ioaddr + FramesAbortXSColls);
-	readw (ioaddr + CarrierSenseErrors);
-
-	/* Clear all other statistic register. */
-	readl (ioaddr + McstOctetXmtOk);
-	readw (ioaddr + BcstFramesXmtdOk);
-	readl (ioaddr + McstFramesXmtdOk);
-	readw (ioaddr + BcstFramesRcvdOk);
-	readw (ioaddr + MacControlFramesRcvd);
-	readl (ioaddr + McstOctetXmtOk);
-	readl (ioaddr + BcstOctetXmtOk);
-	readl (ioaddr + McstFramesXmtdOk);
-	readl (ioaddr + FramesWDeferredXmt);
-	readw (ioaddr + BcstFramesXmtdOk);
-	readw (ioaddr + MacControlFramesXmtd);
-	readw (ioaddr + FramesWEXDeferal);
-#ifdef MEM_MAPPING
-	for (i = 0x100; i <= 0x150; i += 4)
-		readl (ioaddr + i);
-#endif
-	readw (ioaddr + TxJumboFrames);
-	readw (ioaddr + RxJumboFrames);
-	readw (ioaddr + TCPCheckSumErrors);
-	readw (ioaddr + UDPCheckSumErrors);
-	readw (ioaddr + IPCheckSumErrors);
-	return 0;
-}
-
-
-static int
-change_mtu (struct net_device *dev, int new_mtu)
-{
-	struct netdev_private *np = netdev_priv(dev);
-	int max = (np->jumbo) ? MAX_JUMBO : 1536;
-
-	if ((new_mtu < 68) || (new_mtu > max)) {
-		return -EINVAL;
-	}
-
-	dev->mtu = new_mtu;
-
-	return 0;
-}
-
-static void
-set_multicast (struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-	u32 hash_table[2];
-	u16 rx_mode = 0;
-	struct netdev_private *np = netdev_priv(dev);
-
-	hash_table[0] = hash_table[1] = 0;
-	/* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */
-	hash_table[1] |= 0x02000000;
-	if (dev->flags & IFF_PROMISC) {
-		/* Receive all frames promiscuously. */
-		rx_mode = ReceiveAllFrames;
-	} else if ((dev->flags & IFF_ALLMULTI) ||
-			(netdev_mc_count(dev) > multicast_filter_limit)) {
-		/* Receive broadcast and multicast frames */
-		rx_mode = ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast;
-	} else if (!netdev_mc_empty(dev)) {
-		struct netdev_hw_addr *ha;
-		/* Receive broadcast frames and multicast frames filtering
-		   by Hashtable */
-		rx_mode =
-		    ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast;
-		netdev_for_each_mc_addr(ha, dev) {
-			int bit, index = 0;
-			int crc = ether_crc_le(ETH_ALEN, ha->addr);
-			/* The inverted high significant 6 bits of CRC are
-			   used as an index to hashtable */
-			for (bit = 0; bit < 6; bit++)
-				if (crc & (1 << (31 - bit)))
-					index |= (1 << bit);
-			hash_table[index / 32] |= (1 << (index % 32));
-		}
-	} else {
-		rx_mode = ReceiveBroadcast | ReceiveUnicast;
-	}
-	if (np->vlan) {
-		/* ReceiveVLANMatch field in ReceiveMode */
-		rx_mode |= ReceiveVLANMatch;
-	}
-
-	writel (hash_table[0], ioaddr + HashTable0);
-	writel (hash_table[1], ioaddr + HashTable1);
-	writew (rx_mode, ioaddr + ReceiveMode);
-}
-
-static void rio_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct netdev_private *np = netdev_priv(dev);
-	strcpy(info->driver, "dl2k");
-	strcpy(info->version, DRV_VERSION);
-	strcpy(info->bus_info, pci_name(np->pdev));
-}
-
-static int rio_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct netdev_private *np = netdev_priv(dev);
-	if (np->phy_media) {
-		/* fiber device */
-		cmd->supported = SUPPORTED_Autoneg | SUPPORTED_FIBRE;
-		cmd->advertising= ADVERTISED_Autoneg | ADVERTISED_FIBRE;
-		cmd->port = PORT_FIBRE;
-		cmd->transceiver = XCVR_INTERNAL;
-	} else {
-		/* copper device */
-		cmd->supported = SUPPORTED_10baseT_Half |
-			SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half
-			| SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full |
-			SUPPORTED_Autoneg | SUPPORTED_MII;
-		cmd->advertising = ADVERTISED_10baseT_Half |
-			ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half |
-			ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Full|
-			ADVERTISED_Autoneg | ADVERTISED_MII;
-		cmd->port = PORT_MII;
-		cmd->transceiver = XCVR_INTERNAL;
-	}
-	if ( np->link_status ) {
-		ethtool_cmd_speed_set(cmd, np->speed);
-		cmd->duplex = np->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
-	} else {
-		ethtool_cmd_speed_set(cmd, -1);
-		cmd->duplex = -1;
-	}
-	if ( np->an_enable)
-		cmd->autoneg = AUTONEG_ENABLE;
-	else
-		cmd->autoneg = AUTONEG_DISABLE;
-
-	cmd->phy_address = np->phy_addr;
-	return 0;
-}
-
-static int rio_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct netdev_private *np = netdev_priv(dev);
-	netif_carrier_off(dev);
-	if (cmd->autoneg == AUTONEG_ENABLE) {
-		if (np->an_enable)
-			return 0;
-		else {
-			np->an_enable = 1;
-			mii_set_media(dev);
-			return 0;
-		}
-	} else {
-		np->an_enable = 0;
-		if (np->speed == 1000) {
-			ethtool_cmd_speed_set(cmd, SPEED_100);
-			cmd->duplex = DUPLEX_FULL;
-			printk("Warning!! Can't disable Auto negotiation in 1000Mbps, change to Manual 100Mbps, Full duplex.\n");
-		}
-		switch (ethtool_cmd_speed(cmd)) {
-		case SPEED_10:
-			np->speed = 10;
-			np->full_duplex = (cmd->duplex == DUPLEX_FULL);
-			break;
-		case SPEED_100:
-			np->speed = 100;
-			np->full_duplex = (cmd->duplex == DUPLEX_FULL);
-			break;
-		case SPEED_1000: /* not supported */
-		default:
-			return -EINVAL;
-		}
-		mii_set_media(dev);
-	}
-	return 0;
-}
-
-static u32 rio_get_link(struct net_device *dev)
-{
-	struct netdev_private *np = netdev_priv(dev);
-	return np->link_status;
-}
-
-static const struct ethtool_ops ethtool_ops = {
-	.get_drvinfo = rio_get_drvinfo,
-	.get_settings = rio_get_settings,
-	.set_settings = rio_set_settings,
-	.get_link = rio_get_link,
-};
-
-static int
-rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	int phy_addr;
-	struct netdev_private *np = netdev_priv(dev);
-	struct mii_data *miidata = (struct mii_data *) &rq->ifr_ifru;
-
-	struct netdev_desc *desc;
-	int i;
-
-	phy_addr = np->phy_addr;
-	switch (cmd) {
-	case SIOCDEVPRIVATE:
-		break;
-
-	case SIOCDEVPRIVATE + 1:
-		miidata->out_value = mii_read (dev, phy_addr, miidata->reg_num);
-		break;
-	case SIOCDEVPRIVATE + 2:
-		mii_write (dev, phy_addr, miidata->reg_num, miidata->in_value);
-		break;
-	case SIOCDEVPRIVATE + 3:
-		break;
-	case SIOCDEVPRIVATE + 4:
-		break;
-	case SIOCDEVPRIVATE + 5:
-		netif_stop_queue (dev);
-		break;
-	case SIOCDEVPRIVATE + 6:
-		netif_wake_queue (dev);
-		break;
-	case SIOCDEVPRIVATE + 7:
-		printk
-		    ("tx_full=%x cur_tx=%lx old_tx=%lx cur_rx=%lx old_rx=%lx\n",
-		     netif_queue_stopped(dev), np->cur_tx, np->old_tx, np->cur_rx,
-		     np->old_rx);
-		break;
-	case SIOCDEVPRIVATE + 8:
-		printk("TX ring:\n");
-		for (i = 0; i < TX_RING_SIZE; i++) {
-			desc = &np->tx_ring[i];
-			printk
-			    ("%02x:cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",
-			     i,
-			     (u32) (np->tx_ring_dma + i * sizeof (*desc)),
-			     (u32)le64_to_cpu(desc->next_desc),
-			     (u32)le64_to_cpu(desc->status),
-			     (u32)(le64_to_cpu(desc->fraginfo) >> 32),
-			     (u32)le64_to_cpu(desc->fraginfo));
-			printk ("\n");
-		}
-		printk ("\n");
-		break;
-
-	default:
-		return -EOPNOTSUPP;
-	}
-	return 0;
-}
-
-#define EEP_READ 0x0200
-#define EEP_BUSY 0x8000
-/* Read the EEPROM word */
-/* We use I/O instruction to read/write eeprom to avoid fail on some machines */
-static int
-read_eeprom (long ioaddr, int eep_addr)
-{
-	int i = 1000;
-	outw (EEP_READ | (eep_addr & 0xff), ioaddr + EepromCtrl);
-	while (i-- > 0) {
-		if (!(inw (ioaddr + EepromCtrl) & EEP_BUSY)) {
-			return inw (ioaddr + EepromData);
-		}
-	}
-	return 0;
-}
-
-enum phy_ctrl_bits {
-	MII_READ = 0x00, MII_CLK = 0x01, MII_DATA1 = 0x02, MII_WRITE = 0x04,
-	MII_DUPLEX = 0x08,
-};
-
-#define mii_delay() readb(ioaddr)
-static void
-mii_sendbit (struct net_device *dev, u32 data)
-{
-	long ioaddr = dev->base_addr + PhyCtrl;
-	data = (data) ? MII_DATA1 : 0;
-	data |= MII_WRITE;
-	data |= (readb (ioaddr) & 0xf8) | MII_WRITE;
-	writeb (data, ioaddr);
-	mii_delay ();
-	writeb (data | MII_CLK, ioaddr);
-	mii_delay ();
-}
-
-static int
-mii_getbit (struct net_device *dev)
-{
-	long ioaddr = dev->base_addr + PhyCtrl;
-	u8 data;
-
-	data = (readb (ioaddr) & 0xf8) | MII_READ;
-	writeb (data, ioaddr);
-	mii_delay ();
-	writeb (data | MII_CLK, ioaddr);
-	mii_delay ();
-	return ((readb (ioaddr) >> 1) & 1);
-}
-
-static void
-mii_send_bits (struct net_device *dev, u32 data, int len)
-{
-	int i;
-	for (i = len - 1; i >= 0; i--) {
-		mii_sendbit (dev, data & (1 << i));
-	}
-}
-
-static int
-mii_read (struct net_device *dev, int phy_addr, int reg_num)
-{
-	u32 cmd;
-	int i;
-	u32 retval = 0;
-
-	/* Preamble */
-	mii_send_bits (dev, 0xffffffff, 32);
-	/* ST(2), OP(2), ADDR(5), REG#(5), TA(2), Data(16) total 32 bits */
-	/* ST,OP = 0110'b for read operation */
-	cmd = (0x06 << 10 | phy_addr << 5 | reg_num);
-	mii_send_bits (dev, cmd, 14);
-	/* Turnaround */
-	if (mii_getbit (dev))
-		goto err_out;
-	/* Read data */
-	for (i = 0; i < 16; i++) {
-		retval |= mii_getbit (dev);
-		retval <<= 1;
-	}
-	/* End cycle */
-	mii_getbit (dev);
-	return (retval >> 1) & 0xffff;
-
-      err_out:
-	return 0;
-}
-static int
-mii_write (struct net_device *dev, int phy_addr, int reg_num, u16 data)
-{
-	u32 cmd;
-
-	/* Preamble */
-	mii_send_bits (dev, 0xffffffff, 32);
-	/* ST(2), OP(2), ADDR(5), REG#(5), TA(2), Data(16) total 32 bits */
-	/* ST,OP,AAAAA,RRRRR,TA = 0101xxxxxxxxxx10'b = 0x5002 for write */
-	cmd = (0x5002 << 16) | (phy_addr << 23) | (reg_num << 18) | data;
-	mii_send_bits (dev, cmd, 32);
-	/* End cycle */
-	mii_getbit (dev);
-	return 0;
-}
-static int
-mii_wait_link (struct net_device *dev, int wait)
-{
-	__u16 bmsr;
-	int phy_addr;
-	struct netdev_private *np;
-
-	np = netdev_priv(dev);
-	phy_addr = np->phy_addr;
-
-	do {
-		bmsr = mii_read (dev, phy_addr, MII_BMSR);
-		if (bmsr & MII_BMSR_LINK_STATUS)
-			return 0;
-		mdelay (1);
-	} while (--wait > 0);
-	return -1;
-}
-static int
-mii_get_media (struct net_device *dev)
-{
-	__u16 negotiate;
-	__u16 bmsr;
-	__u16 mscr;
-	__u16 mssr;
-	int phy_addr;
-	struct netdev_private *np;
-
-	np = netdev_priv(dev);
-	phy_addr = np->phy_addr;
-
-	bmsr = mii_read (dev, phy_addr, MII_BMSR);
-	if (np->an_enable) {
-		if (!(bmsr & MII_BMSR_AN_COMPLETE)) {
-			/* Auto-Negotiation not completed */
-			return -1;
-		}
-		negotiate = mii_read (dev, phy_addr, MII_ANAR) &
-			mii_read (dev, phy_addr, MII_ANLPAR);
-		mscr = mii_read (dev, phy_addr, MII_MSCR);
-		mssr = mii_read (dev, phy_addr, MII_MSSR);
-		if (mscr & MII_MSCR_1000BT_FD && mssr & MII_MSSR_LP_1000BT_FD) {
-			np->speed = 1000;
-			np->full_duplex = 1;
-			printk (KERN_INFO "Auto 1000 Mbps, Full duplex\n");
-		} else if (mscr & MII_MSCR_1000BT_HD && mssr & MII_MSSR_LP_1000BT_HD) {
-			np->speed = 1000;
-			np->full_duplex = 0;
-			printk (KERN_INFO "Auto 1000 Mbps, Half duplex\n");
-		} else if (negotiate & MII_ANAR_100BX_FD) {
-			np->speed = 100;
-			np->full_duplex = 1;
-			printk (KERN_INFO "Auto 100 Mbps, Full duplex\n");
-		} else if (negotiate & MII_ANAR_100BX_HD) {
-			np->speed = 100;
-			np->full_duplex = 0;
-			printk (KERN_INFO "Auto 100 Mbps, Half duplex\n");
-		} else if (negotiate & MII_ANAR_10BT_FD) {
-			np->speed = 10;
-			np->full_duplex = 1;
-			printk (KERN_INFO "Auto 10 Mbps, Full duplex\n");
-		} else if (negotiate & MII_ANAR_10BT_HD) {
-			np->speed = 10;
-			np->full_duplex = 0;
-			printk (KERN_INFO "Auto 10 Mbps, Half duplex\n");
-		}
-		if (negotiate & MII_ANAR_PAUSE) {
-			np->tx_flow &= 1;
-			np->rx_flow &= 1;
-		} else if (negotiate & MII_ANAR_ASYMMETRIC) {
-			np->tx_flow = 0;
-			np->rx_flow &= 1;
-		}
-		/* else tx_flow, rx_flow = user select  */
-	} else {
-		__u16 bmcr = mii_read (dev, phy_addr, MII_BMCR);
-		switch (bmcr & (MII_BMCR_SPEED_100 | MII_BMCR_SPEED_1000)) {
-		case MII_BMCR_SPEED_1000:
-			printk (KERN_INFO "Operating at 1000 Mbps, ");
-			break;
-		case MII_BMCR_SPEED_100:
-			printk (KERN_INFO "Operating at 100 Mbps, ");
-			break;
-		case 0:
-			printk (KERN_INFO "Operating at 10 Mbps, ");
-		}
-		if (bmcr & MII_BMCR_DUPLEX_MODE) {
-			printk (KERN_CONT "Full duplex\n");
-		} else {
-			printk (KERN_CONT "Half duplex\n");
-		}
-	}
-	if (np->tx_flow)
-		printk(KERN_INFO "Enable Tx Flow Control\n");
-	else
-		printk(KERN_INFO "Disable Tx Flow Control\n");
-	if (np->rx_flow)
-		printk(KERN_INFO "Enable Rx Flow Control\n");
-	else
-		printk(KERN_INFO "Disable Rx Flow Control\n");
-
-	return 0;
-}
-
-static int
-mii_set_media (struct net_device *dev)
-{
-	__u16 pscr;
-	__u16 bmcr;
-	__u16 bmsr;
-	__u16 anar;
-	int phy_addr;
-	struct netdev_private *np;
-	np = netdev_priv(dev);
-	phy_addr = np->phy_addr;
-
-	/* Does user set speed? */
-	if (np->an_enable) {
-		/* Advertise capabilities */
-		bmsr = mii_read (dev, phy_addr, MII_BMSR);
-		anar = mii_read (dev, phy_addr, MII_ANAR) &
-			     ~MII_ANAR_100BX_FD &
-			     ~MII_ANAR_100BX_HD &
-			     ~MII_ANAR_100BT4 &
-			     ~MII_ANAR_10BT_FD &
-			     ~MII_ANAR_10BT_HD;
-		if (bmsr & MII_BMSR_100BX_FD)
-			anar |= MII_ANAR_100BX_FD;
-		if (bmsr & MII_BMSR_100BX_HD)
-			anar |= MII_ANAR_100BX_HD;
-		if (bmsr & MII_BMSR_100BT4)
-			anar |= MII_ANAR_100BT4;
-		if (bmsr & MII_BMSR_10BT_FD)
-			anar |= MII_ANAR_10BT_FD;
-		if (bmsr & MII_BMSR_10BT_HD)
-			anar |= MII_ANAR_10BT_HD;
-		anar |= MII_ANAR_PAUSE | MII_ANAR_ASYMMETRIC;
-		mii_write (dev, phy_addr, MII_ANAR, anar);
-
-		/* Enable Auto crossover */
-		pscr = mii_read (dev, phy_addr, MII_PHY_SCR);
-		pscr |= 3 << 5;	/* 11'b */
-		mii_write (dev, phy_addr, MII_PHY_SCR, pscr);
-
-		/* Soft reset PHY */
-		mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET);
-		bmcr = MII_BMCR_AN_ENABLE | MII_BMCR_RESTART_AN | MII_BMCR_RESET;
-		mii_write (dev, phy_addr, MII_BMCR, bmcr);
-		mdelay(1);
-	} else {
-		/* Force speed setting */
-		/* 1) Disable Auto crossover */
-		pscr = mii_read (dev, phy_addr, MII_PHY_SCR);
-		pscr &= ~(3 << 5);
-		mii_write (dev, phy_addr, MII_PHY_SCR, pscr);
-
-		/* 2) PHY Reset */
-		bmcr = mii_read (dev, phy_addr, MII_BMCR);
-		bmcr |= MII_BMCR_RESET;
-		mii_write (dev, phy_addr, MII_BMCR, bmcr);
-
-		/* 3) Power Down */
-		bmcr = 0x1940;	/* must be 0x1940 */
-		mii_write (dev, phy_addr, MII_BMCR, bmcr);
-		mdelay (100);	/* wait a certain time */
-
-		/* 4) Advertise nothing */
-		mii_write (dev, phy_addr, MII_ANAR, 0);
-
-		/* 5) Set media and Power Up */
-		bmcr = MII_BMCR_POWER_DOWN;
-		if (np->speed == 100) {
-			bmcr |= MII_BMCR_SPEED_100;
-			printk (KERN_INFO "Manual 100 Mbps, ");
-		} else if (np->speed == 10) {
-			printk (KERN_INFO "Manual 10 Mbps, ");
-		}
-		if (np->full_duplex) {
-			bmcr |= MII_BMCR_DUPLEX_MODE;
-			printk (KERN_CONT "Full duplex\n");
-		} else {
-			printk (KERN_CONT "Half duplex\n");
-		}
-#if 0
-		/* Set 1000BaseT Master/Slave setting */
-		mscr = mii_read (dev, phy_addr, MII_MSCR);
-		mscr |= MII_MSCR_CFG_ENABLE;
-		mscr &= ~MII_MSCR_CFG_VALUE = 0;
-#endif
-		mii_write (dev, phy_addr, MII_BMCR, bmcr);
-		mdelay(10);
-	}
-	return 0;
-}
-
-static int
-mii_get_media_pcs (struct net_device *dev)
-{
-	__u16 negotiate;
-	__u16 bmsr;
-	int phy_addr;
-	struct netdev_private *np;
-
-	np = netdev_priv(dev);
-	phy_addr = np->phy_addr;
-
-	bmsr = mii_read (dev, phy_addr, PCS_BMSR);
-	if (np->an_enable) {
-		if (!(bmsr & MII_BMSR_AN_COMPLETE)) {
-			/* Auto-Negotiation not completed */
-			return -1;
-		}
-		negotiate = mii_read (dev, phy_addr, PCS_ANAR) &
-			mii_read (dev, phy_addr, PCS_ANLPAR);
-		np->speed = 1000;
-		if (negotiate & PCS_ANAR_FULL_DUPLEX) {
-			printk (KERN_INFO "Auto 1000 Mbps, Full duplex\n");
-			np->full_duplex = 1;
-		} else {
-			printk (KERN_INFO "Auto 1000 Mbps, half duplex\n");
-			np->full_duplex = 0;
-		}
-		if (negotiate & PCS_ANAR_PAUSE) {
-			np->tx_flow &= 1;
-			np->rx_flow &= 1;
-		} else if (negotiate & PCS_ANAR_ASYMMETRIC) {
-			np->tx_flow = 0;
-			np->rx_flow &= 1;
-		}
-		/* else tx_flow, rx_flow = user select  */
-	} else {
-		__u16 bmcr = mii_read (dev, phy_addr, PCS_BMCR);
-		printk (KERN_INFO "Operating at 1000 Mbps, ");
-		if (bmcr & MII_BMCR_DUPLEX_MODE) {
-			printk (KERN_CONT "Full duplex\n");
-		} else {
-			printk (KERN_CONT "Half duplex\n");
-		}
-	}
-	if (np->tx_flow)
-		printk(KERN_INFO "Enable Tx Flow Control\n");
-	else
-		printk(KERN_INFO "Disable Tx Flow Control\n");
-	if (np->rx_flow)
-		printk(KERN_INFO "Enable Rx Flow Control\n");
-	else
-		printk(KERN_INFO "Disable Rx Flow Control\n");
-
-	return 0;
-}
-
-static int
-mii_set_media_pcs (struct net_device *dev)
-{
-	__u16 bmcr;
-	__u16 esr;
-	__u16 anar;
-	int phy_addr;
-	struct netdev_private *np;
-	np = netdev_priv(dev);
-	phy_addr = np->phy_addr;
-
-	/* Auto-Negotiation? */
-	if (np->an_enable) {
-		/* Advertise capabilities */
-		esr = mii_read (dev, phy_addr, PCS_ESR);
-		anar = mii_read (dev, phy_addr, MII_ANAR) &
-			~PCS_ANAR_HALF_DUPLEX &
-			~PCS_ANAR_FULL_DUPLEX;
-		if (esr & (MII_ESR_1000BT_HD | MII_ESR_1000BX_HD))
-			anar |= PCS_ANAR_HALF_DUPLEX;
-		if (esr & (MII_ESR_1000BT_FD | MII_ESR_1000BX_FD))
-			anar |= PCS_ANAR_FULL_DUPLEX;
-		anar |= PCS_ANAR_PAUSE | PCS_ANAR_ASYMMETRIC;
-		mii_write (dev, phy_addr, MII_ANAR, anar);
-
-		/* Soft reset PHY */
-		mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET);
-		bmcr = MII_BMCR_AN_ENABLE | MII_BMCR_RESTART_AN |
-		       MII_BMCR_RESET;
-		mii_write (dev, phy_addr, MII_BMCR, bmcr);
-		mdelay(1);
-	} else {
-		/* Force speed setting */
-		/* PHY Reset */
-		bmcr = MII_BMCR_RESET;
-		mii_write (dev, phy_addr, MII_BMCR, bmcr);
-		mdelay(10);
-		if (np->full_duplex) {
-			bmcr = MII_BMCR_DUPLEX_MODE;
-			printk (KERN_INFO "Manual full duplex\n");
-		} else {
-			bmcr = 0;
-			printk (KERN_INFO "Manual half duplex\n");
-		}
-		mii_write (dev, phy_addr, MII_BMCR, bmcr);
-		mdelay(10);
-
-		/*  Advertise nothing */
-		mii_write (dev, phy_addr, MII_ANAR, 0);
-	}
-	return 0;
-}
-
-
-static int
-rio_close (struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-	struct netdev_private *np = netdev_priv(dev);
-	struct sk_buff *skb;
-	int i;
-
-	netif_stop_queue (dev);
-
-	/* Disable interrupts */
-	writew (0, ioaddr + IntEnable);
-
-	/* Stop Tx and Rx logics */
-	writel (TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl);
-
-	free_irq (dev->irq, dev);
-	del_timer_sync (&np->timer);
-
-	/* Free all the skbuffs in the queue. */
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		skb = np->rx_skbuff[i];
-		if (skb) {
-			pci_unmap_single(np->pdev,
-					 desc_to_dma(&np->rx_ring[i]),
-					 skb->len, PCI_DMA_FROMDEVICE);
-			dev_kfree_skb (skb);
-			np->rx_skbuff[i] = NULL;
-		}
-		np->rx_ring[i].status = 0;
-		np->rx_ring[i].fraginfo = 0;
-	}
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		skb = np->tx_skbuff[i];
-		if (skb) {
-			pci_unmap_single(np->pdev,
-					 desc_to_dma(&np->tx_ring[i]),
-					 skb->len, PCI_DMA_TODEVICE);
-			dev_kfree_skb (skb);
-			np->tx_skbuff[i] = NULL;
-		}
-	}
-
-	return 0;
-}
-
-static void __devexit
-rio_remove1 (struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata (pdev);
-
-	if (dev) {
-		struct netdev_private *np = netdev_priv(dev);
-
-		unregister_netdev (dev);
-		pci_free_consistent (pdev, RX_TOTAL_SIZE, np->rx_ring,
-				     np->rx_ring_dma);
-		pci_free_consistent (pdev, TX_TOTAL_SIZE, np->tx_ring,
-				     np->tx_ring_dma);
-#ifdef MEM_MAPPING
-		iounmap ((char *) (dev->base_addr));
-#endif
-		free_netdev (dev);
-		pci_release_regions (pdev);
-		pci_disable_device (pdev);
-	}
-	pci_set_drvdata (pdev, NULL);
-}
-
-static struct pci_driver rio_driver = {
-	.name		= "dl2k",
-	.id_table	= rio_pci_tbl,
-	.probe		= rio_probe1,
-	.remove		= __devexit_p(rio_remove1),
-};
-
-static int __init
-rio_init (void)
-{
-	return pci_register_driver(&rio_driver);
-}
-
-static void __exit
-rio_exit (void)
-{
-	pci_unregister_driver (&rio_driver);
-}
-
-module_init (rio_init);
-module_exit (rio_exit);
-
-/*
-
-Compile command:
-
-gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -c dl2k.c
-
-Read Documentation/networking/dl2k.txt for details.
-
-*/
-
diff -druN linux-libre-3.1-gnu/drivers/net/dl2k.h linux-libre-3.2-gnu/drivers/net/dl2k.h
--- linux-libre-3.1-gnu/drivers/net/dl2k.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/dl2k.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,554 +0,0 @@
-/*  D-Link DL2000-based Gigabit Ethernet Adapter Linux driver */
-/*
-    Copyright (c) 2001, 2002 by D-Link Corporation
-    Written by Edward Peng.<edward_peng@dlink.com.tw>
-    Created 03-May-2001, base on Linux' sundance.c.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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 __DL2K_H__
-#define __DL2K_H__
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-#include <linux/crc32.h>
-#include <linux/ethtool.h>
-#include <linux/bitops.h>
-#include <asm/processor.h>	/* Processor type for cache alignment. */
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/time.h>
-#define TX_RING_SIZE	256
-#define TX_QUEUE_LEN	(TX_RING_SIZE - 1) /* Limit ring entries actually used.*/
-#define RX_RING_SIZE 	256
-#define TX_TOTAL_SIZE	TX_RING_SIZE*sizeof(struct netdev_desc)
-#define RX_TOTAL_SIZE	RX_RING_SIZE*sizeof(struct netdev_desc)
-
-/* This driver was written to use PCI memory space, however x86-oriented
-   hardware often uses I/O space accesses. */
-#ifndef MEM_MAPPING
-#undef readb
-#undef readw
-#undef readl
-#undef writeb
-#undef writew
-#undef writel
-#define readb inb
-#define readw inw
-#define readl inl
-#define writeb outb
-#define writew outw
-#define writel outl
-#endif
-
-/* Offsets to the device registers.
-   Unlike software-only systems, device drivers interact with complex hardware.
-   It's not useful to define symbolic names for every register bit in the
-   device.  The name can only partially document the semantics and make
-   the driver longer and more difficult to read.
-   In general, only the important configuration values or bits changed
-   multiple times should be defined symbolically.
-*/
-enum dl2x_offsets {
-	/* I/O register offsets */
-	DMACtrl = 0x00,
-	RxDMAStatus = 0x08,
-	TFDListPtr0 = 0x10,
-	TFDListPtr1 = 0x14,
-	TxDMABurstThresh = 0x18,
-	TxDMAUrgentThresh = 0x19,
-	TxDMAPollPeriod = 0x1a,
-	RFDListPtr0 = 0x1c,
-	RFDListPtr1 = 0x20,
-	RxDMABurstThresh = 0x24,
-	RxDMAUrgentThresh = 0x25,
-	RxDMAPollPeriod = 0x26,
-	RxDMAIntCtrl = 0x28,
-	DebugCtrl = 0x2c,
-	ASICCtrl = 0x30,
-	FifoCtrl = 0x38,
-	RxEarlyThresh = 0x3a,
-	FlowOffThresh = 0x3c,
-	FlowOnThresh = 0x3e,
-	TxStartThresh = 0x44,
-	EepromData = 0x48,
-	EepromCtrl = 0x4a,
-	ExpromAddr = 0x4c,
-	Exprodata = 0x50,
-	WakeEvent = 0x51,
-	CountDown = 0x54,
-	IntStatusAck = 0x5a,
-	IntEnable = 0x5c,
-	IntStatus = 0x5e,
-	TxStatus = 0x60,
-	MACCtrl = 0x6c,
-	VLANTag = 0x70,
-	PhyCtrl = 0x76,
-	StationAddr0 = 0x78,
-	StationAddr1 = 0x7a,
-	StationAddr2 = 0x7c,
-	VLANId = 0x80,
-	MaxFrameSize = 0x86,
-	ReceiveMode = 0x88,
-	HashTable0 = 0x8c,
-	HashTable1 = 0x90,
-	RmonStatMask = 0x98,
-	StatMask = 0x9c,
-	RxJumboFrames = 0xbc,
-	TCPCheckSumErrors = 0xc0,
-	IPCheckSumErrors = 0xc2,
-	UDPCheckSumErrors = 0xc4,
-	TxJumboFrames = 0xf4,
-	/* Ethernet MIB statistic register offsets */
-	OctetRcvOk = 0xa8,
-	McstOctetRcvOk = 0xac,
-	BcstOctetRcvOk = 0xb0,
-	FramesRcvOk = 0xb4,
-	McstFramesRcvdOk = 0xb8,
-	BcstFramesRcvdOk = 0xbe,
-	MacControlFramesRcvd = 0xc6,
-	FrameTooLongErrors = 0xc8,
-	InRangeLengthErrors = 0xca,
-	FramesCheckSeqErrors = 0xcc,
-	FramesLostRxErrors = 0xce,
-	OctetXmtOk = 0xd0,
-	McstOctetXmtOk = 0xd4,
-	BcstOctetXmtOk = 0xd8,
-	FramesXmtOk = 0xdc,
-	McstFramesXmtdOk = 0xe0,
-	FramesWDeferredXmt = 0xe4,
-	LateCollisions = 0xe8,
-	MultiColFrames = 0xec,
-	SingleColFrames = 0xf0,
-	BcstFramesXmtdOk = 0xf6,
-	CarrierSenseErrors = 0xf8,
-	MacControlFramesXmtd = 0xfa,
-	FramesAbortXSColls = 0xfc,
-	FramesWEXDeferal = 0xfe,
-	/* RMON statistic register offsets */
-	EtherStatsCollisions = 0x100,
-	EtherStatsOctetsTransmit = 0x104,
-	EtherStatsPktsTransmit = 0x108,
-	EtherStatsPkts64OctetTransmit = 0x10c,
-	EtherStats65to127OctetsTransmit = 0x110,
-	EtherStatsPkts128to255OctetsTransmit = 0x114,
-	EtherStatsPkts256to511OctetsTransmit = 0x118,
-	EtherStatsPkts512to1023OctetsTransmit = 0x11c,
-	EtherStatsPkts1024to1518OctetsTransmit = 0x120,
-	EtherStatsCRCAlignErrors = 0x124,
-	EtherStatsUndersizePkts = 0x128,
-	EtherStatsFragments = 0x12c,
-	EtherStatsJabbers = 0x130,
-	EtherStatsOctets = 0x134,
-	EtherStatsPkts = 0x138,
-	EtherStats64Octets = 0x13c,
-	EtherStatsPkts65to127Octets = 0x140,
-	EtherStatsPkts128to255Octets = 0x144,
-	EtherStatsPkts256to511Octets = 0x148,
-	EtherStatsPkts512to1023Octets = 0x14c,
-	EtherStatsPkts1024to1518Octets = 0x150,
-};
-
-/* Bits in the interrupt status/mask registers. */
-enum IntStatus_bits {
-	InterruptStatus = 0x0001,
-	HostError = 0x0002,
-	MACCtrlFrame = 0x0008,
-	TxComplete = 0x0004,
-	RxComplete = 0x0010,
-	RxEarly = 0x0020,
-	IntRequested = 0x0040,
-	UpdateStats = 0x0080,
-	LinkEvent = 0x0100,
-	TxDMAComplete = 0x0200,
-	RxDMAComplete = 0x0400,
-	RFDListEnd = 0x0800,
-	RxDMAPriority = 0x1000,
-};
-
-/* Bits in the ReceiveMode register. */
-enum ReceiveMode_bits {
-	ReceiveUnicast = 0x0001,
-	ReceiveMulticast = 0x0002,
-	ReceiveBroadcast = 0x0004,
-	ReceiveAllFrames = 0x0008,
-	ReceiveMulticastHash = 0x0010,
-	ReceiveIPMulticast = 0x0020,
-	ReceiveVLANMatch = 0x0100,
-	ReceiveVLANHash = 0x0200,
-};
-/* Bits in MACCtrl. */
-enum MACCtrl_bits {
-	DuplexSelect = 0x20,
-	TxFlowControlEnable = 0x80,
-	RxFlowControlEnable = 0x0100,
-	RcvFCS = 0x200,
-	AutoVLANtagging = 0x1000,
-	AutoVLANuntagging = 0x2000,
-	StatsEnable = 0x00200000,
-	StatsDisable = 0x00400000,
-	StatsEnabled = 0x00800000,
-	TxEnable = 0x01000000,
-	TxDisable = 0x02000000,
-	TxEnabled = 0x04000000,
-	RxEnable = 0x08000000,
-	RxDisable = 0x10000000,
-	RxEnabled = 0x20000000,
-};
-
-enum ASICCtrl_LoWord_bits {
-	PhyMedia = 0x0080,
-};
-
-enum ASICCtrl_HiWord_bits {
-	GlobalReset = 0x0001,
-	RxReset = 0x0002,
-	TxReset = 0x0004,
-	DMAReset = 0x0008,
-	FIFOReset = 0x0010,
-	NetworkReset = 0x0020,
-	HostReset = 0x0040,
-	ResetBusy = 0x0400,
-};
-
-/* Transmit Frame Control bits */
-enum TFC_bits {
-	DwordAlign = 0x00000000,
-	WordAlignDisable = 0x00030000,
-	WordAlign = 0x00020000,
-	TCPChecksumEnable = 0x00040000,
-	UDPChecksumEnable = 0x00080000,
-	IPChecksumEnable = 0x00100000,
-	FCSAppendDisable = 0x00200000,
-	TxIndicate = 0x00400000,
-	TxDMAIndicate = 0x00800000,
-	FragCountShift = 24,
-	VLANTagInsert = 0x0000000010000000,
-	TFDDone = 0x80000000,
-	VIDShift = 32,
-	UsePriorityShift = 48,
-};
-
-/* Receive Frames Status bits */
-enum RFS_bits {
-	RxFIFOOverrun = 0x00010000,
-	RxRuntFrame = 0x00020000,
-	RxAlignmentError = 0x00040000,
-	RxFCSError = 0x00080000,
-	RxOverSizedFrame = 0x00100000,
-	RxLengthError = 0x00200000,
-	VLANDetected = 0x00400000,
-	TCPDetected = 0x00800000,
-	TCPError = 0x01000000,
-	UDPDetected = 0x02000000,
-	UDPError = 0x04000000,
-	IPDetected = 0x08000000,
-	IPError = 0x10000000,
-	FrameStart = 0x20000000,
-	FrameEnd = 0x40000000,
-	RFDDone = 0x80000000,
-	TCIShift = 32,
-	RFS_Errors = 0x003f0000,
-};
-
-#define MII_RESET_TIME_OUT		10000
-/* MII register */
-enum _mii_reg {
-	MII_BMCR = 0,
-	MII_BMSR = 1,
-	MII_PHY_ID1 = 2,
-	MII_PHY_ID2 = 3,
-	MII_ANAR = 4,
-	MII_ANLPAR = 5,
-	MII_ANER = 6,
-	MII_ANNPT = 7,
-	MII_ANLPRNP = 8,
-	MII_MSCR = 9,
-	MII_MSSR = 10,
-	MII_ESR = 15,
-	MII_PHY_SCR = 16,
-};
-/* PCS register */
-enum _pcs_reg {
-	PCS_BMCR = 0,
-	PCS_BMSR = 1,
-	PCS_ANAR = 4,
-	PCS_ANLPAR = 5,
-	PCS_ANER = 6,
-	PCS_ANNPT = 7,
-	PCS_ANLPRNP = 8,
-	PCS_ESR = 15,
-};
-
-/* Basic Mode Control Register */
-enum _mii_bmcr {
-	MII_BMCR_RESET = 0x8000,
-	MII_BMCR_LOOP_BACK = 0x4000,
-	MII_BMCR_SPEED_LSB = 0x2000,
-	MII_BMCR_AN_ENABLE = 0x1000,
-	MII_BMCR_POWER_DOWN = 0x0800,
-	MII_BMCR_ISOLATE = 0x0400,
-	MII_BMCR_RESTART_AN = 0x0200,
-	MII_BMCR_DUPLEX_MODE = 0x0100,
-	MII_BMCR_COL_TEST = 0x0080,
-	MII_BMCR_SPEED_MSB = 0x0040,
-	MII_BMCR_SPEED_RESERVED = 0x003f,
-	MII_BMCR_SPEED_10 = 0,
-	MII_BMCR_SPEED_100 = MII_BMCR_SPEED_LSB,
-	MII_BMCR_SPEED_1000 = MII_BMCR_SPEED_MSB,
-};
-
-/* Basic Mode Status Register */
-enum _mii_bmsr {
-	MII_BMSR_100BT4 = 0x8000,
-	MII_BMSR_100BX_FD = 0x4000,
-	MII_BMSR_100BX_HD = 0x2000,
-	MII_BMSR_10BT_FD = 0x1000,
-	MII_BMSR_10BT_HD = 0x0800,
-	MII_BMSR_100BT2_FD = 0x0400,
-	MII_BMSR_100BT2_HD = 0x0200,
-	MII_BMSR_EXT_STATUS = 0x0100,
-	MII_BMSR_PREAMBLE_SUPP = 0x0040,
-	MII_BMSR_AN_COMPLETE = 0x0020,
-	MII_BMSR_REMOTE_FAULT = 0x0010,
-	MII_BMSR_AN_ABILITY = 0x0008,
-	MII_BMSR_LINK_STATUS = 0x0004,
-	MII_BMSR_JABBER_DETECT = 0x0002,
-	MII_BMSR_EXT_CAP = 0x0001,
-};
-
-/* ANAR */
-enum _mii_anar {
-	MII_ANAR_NEXT_PAGE = 0x8000,
-	MII_ANAR_REMOTE_FAULT = 0x4000,
-	MII_ANAR_ASYMMETRIC = 0x0800,
-	MII_ANAR_PAUSE = 0x0400,
-	MII_ANAR_100BT4 = 0x0200,
-	MII_ANAR_100BX_FD = 0x0100,
-	MII_ANAR_100BX_HD = 0x0080,
-	MII_ANAR_10BT_FD = 0x0020,
-	MII_ANAR_10BT_HD = 0x0010,
-	MII_ANAR_SELECTOR = 0x001f,
-	MII_IEEE8023_CSMACD = 0x0001,
-};
-
-/* ANLPAR */
-enum _mii_anlpar {
-	MII_ANLPAR_NEXT_PAGE = MII_ANAR_NEXT_PAGE,
-	MII_ANLPAR_REMOTE_FAULT = MII_ANAR_REMOTE_FAULT,
-	MII_ANLPAR_ASYMMETRIC = MII_ANAR_ASYMMETRIC,
-	MII_ANLPAR_PAUSE = MII_ANAR_PAUSE,
-	MII_ANLPAR_100BT4 = MII_ANAR_100BT4,
-	MII_ANLPAR_100BX_FD = MII_ANAR_100BX_FD,
-	MII_ANLPAR_100BX_HD = MII_ANAR_100BX_HD,
-	MII_ANLPAR_10BT_FD = MII_ANAR_10BT_FD,
-	MII_ANLPAR_10BT_HD = MII_ANAR_10BT_HD,
-	MII_ANLPAR_SELECTOR = MII_ANAR_SELECTOR,
-};
-
-/* Auto-Negotiation Expansion Register */
-enum _mii_aner {
-	MII_ANER_PAR_DETECT_FAULT = 0x0010,
-	MII_ANER_LP_NEXTPAGABLE = 0x0008,
-	MII_ANER_NETXTPAGABLE = 0x0004,
-	MII_ANER_PAGE_RECEIVED = 0x0002,
-	MII_ANER_LP_NEGOTIABLE = 0x0001,
-};
-
-/* MASTER-SLAVE Control Register */
-enum _mii_mscr {
-	MII_MSCR_TEST_MODE = 0xe000,
-	MII_MSCR_CFG_ENABLE = 0x1000,
-	MII_MSCR_CFG_VALUE = 0x0800,
-	MII_MSCR_PORT_VALUE = 0x0400,
-	MII_MSCR_1000BT_FD = 0x0200,
-	MII_MSCR_1000BT_HD = 0X0100,
-};
-
-/* MASTER-SLAVE Status Register */
-enum _mii_mssr {
-	MII_MSSR_CFG_FAULT = 0x8000,
-	MII_MSSR_CFG_RES = 0x4000,
-	MII_MSSR_LOCAL_RCV_STATUS = 0x2000,
-	MII_MSSR_REMOTE_RCVR = 0x1000,
-	MII_MSSR_LP_1000BT_FD = 0x0800,
-	MII_MSSR_LP_1000BT_HD = 0x0400,
-	MII_MSSR_IDLE_ERR_COUNT = 0x00ff,
-};
-
-/* IEEE Extened Status Register */
-enum _mii_esr {
-	MII_ESR_1000BX_FD = 0x8000,
-	MII_ESR_1000BX_HD = 0x4000,
-	MII_ESR_1000BT_FD = 0x2000,
-	MII_ESR_1000BT_HD = 0x1000,
-};
-/* PHY Specific Control Register */
-#if 0
-typedef union t_MII_PHY_SCR {
-	u16 image;
-	struct {
-		u16 disable_jabber:1;	// bit 0
-		u16 polarity_reversal:1;	// bit 1
-		u16 SEQ_test:1;	// bit 2
-		u16 _bit_3:1;	// bit 3
-		u16 disable_CLK125:1;	// bit 4
-		u16 mdi_crossover_mode:2;	// bit 6:5
-		u16 enable_ext_dist:1;	// bit 7
-		u16 _bit_8_9:2;	// bit 9:8
-		u16 force_link:1;	// bit 10
-		u16 assert_CRS:1;	// bit 11
-		u16 rcv_fifo_depth:2;	// bit 13:12
-		u16 xmit_fifo_depth:2;	// bit 15:14
-	} bits;
-} PHY_SCR_t, *PPHY_SCR_t;
-#endif
-
-typedef enum t_MII_ADMIN_STATUS {
-	adm_reset,
-	adm_operational,
-	adm_loopback,
-	adm_power_down,
-	adm_isolate
-} MII_ADMIN_t, *PMII_ADMIN_t;
-
-/* Physical Coding Sublayer Management (PCS) */
-/* PCS control and status registers bitmap as the same as MII */
-/* PCS Extended Status register bitmap as the same as MII */
-/* PCS ANAR */
-enum _pcs_anar {
-	PCS_ANAR_NEXT_PAGE = 0x8000,
-	PCS_ANAR_REMOTE_FAULT = 0x3000,
-	PCS_ANAR_ASYMMETRIC = 0x0100,
-	PCS_ANAR_PAUSE = 0x0080,
-	PCS_ANAR_HALF_DUPLEX = 0x0040,
-	PCS_ANAR_FULL_DUPLEX = 0x0020,
-};
-/* PCS ANLPAR */
-enum _pcs_anlpar {
-	PCS_ANLPAR_NEXT_PAGE = PCS_ANAR_NEXT_PAGE,
-	PCS_ANLPAR_REMOTE_FAULT = PCS_ANAR_REMOTE_FAULT,
-	PCS_ANLPAR_ASYMMETRIC = PCS_ANAR_ASYMMETRIC,
-	PCS_ANLPAR_PAUSE = PCS_ANAR_PAUSE,
-	PCS_ANLPAR_HALF_DUPLEX = PCS_ANAR_HALF_DUPLEX,
-	PCS_ANLPAR_FULL_DUPLEX = PCS_ANAR_FULL_DUPLEX,
-};
-
-typedef struct t_SROM {
-	u16 config_param;	/* 0x00 */
-	u16 asic_ctrl;		/* 0x02 */
-	u16 sub_vendor_id;	/* 0x04 */
-	u16 sub_system_id;	/* 0x06 */
-	u16 reserved1[12];	/* 0x08-0x1f */
-	u8 mac_addr[6];		/* 0x20-0x25 */
-	u8 reserved2[10];	/* 0x26-0x2f */
-	u8 sib[204];		/* 0x30-0xfb */
-	u32 crc;		/* 0xfc-0xff */
-} SROM_t, *PSROM_t;
-
-/* Ioctl custom data */
-struct ioctl_data {
-	char signature[10];
-	int cmd;
-	int len;
-	char *data;
-};
-
-struct mii_data {
-	__u16 reserved;
-	__u16 reg_num;
-	__u16 in_value;
-	__u16 out_value;
-};
-
-/* The Rx and Tx buffer descriptors. */
-struct netdev_desc {
-	__le64 next_desc;
-	__le64 status;
-	__le64 fraginfo;
-};
-
-#define PRIV_ALIGN	15	/* Required alignment mask */
-/* Use  __attribute__((aligned (L1_CACHE_BYTES)))  to maintain alignment
-   within the structure. */
-struct netdev_private {
-	/* Descriptor rings first for alignment. */
-	struct netdev_desc *rx_ring;
-	struct netdev_desc *tx_ring;
-	struct sk_buff *rx_skbuff[RX_RING_SIZE];
-	struct sk_buff *tx_skbuff[TX_RING_SIZE];
-	dma_addr_t tx_ring_dma;
-	dma_addr_t rx_ring_dma;
-	struct pci_dev *pdev;
-	spinlock_t tx_lock;
-	spinlock_t rx_lock;
-	struct net_device_stats stats;
-	unsigned int rx_buf_sz;		/* Based on MTU+slack. */
-	unsigned int speed;		/* Operating speed */
-	unsigned int vlan;		/* VLAN Id */
-	unsigned int chip_id;		/* PCI table chip id */
-	unsigned int rx_coalesce; 	/* Maximum frames each RxDMAComplete intr */
-	unsigned int rx_timeout; 	/* Wait time between RxDMAComplete intr */
-	unsigned int tx_coalesce;	/* Maximum frames each tx interrupt */
-	unsigned int full_duplex:1;	/* Full-duplex operation requested. */
-	unsigned int an_enable:2;	/* Auto-Negotiated Enable */
-	unsigned int jumbo:1;		/* Jumbo frame enable */
-	unsigned int coalesce:1;	/* Rx coalescing enable */
-	unsigned int tx_flow:1;		/* Tx flow control enable */
-	unsigned int rx_flow:1;		/* Rx flow control enable */
-	unsigned int phy_media:1;	/* 1: fiber, 0: copper */
-	unsigned int link_status:1;	/* Current link status */
-	struct netdev_desc *last_tx;	/* Last Tx descriptor used. */
-	unsigned long cur_rx, old_rx;	/* Producer/consumer ring indices */
-	unsigned long cur_tx, old_tx;
-	struct timer_list timer;
-	int wake_polarity;
-	char name[256];		/* net device description */
-	u8 duplex_polarity;
-	u16 mcast_filter[4];
-	u16 advertising;	/* NWay media advertisement */
-	u16 negotiate;		/* Negotiated media */
-	int phy_addr;		/* PHY addresses. */
-};
-
-/* The station address location in the EEPROM. */
-/* The struct pci_device_id consist of:
-        vendor, device          Vendor and device ID to match (or PCI_ANY_ID)
-        subvendor, subdevice    Subsystem vendor and device ID to match (or PCI_ANY_ID)
-        class                   Device class to match. The class_mask tells which bits
-        class_mask              of the class are honored during the comparison.
-        driver_data             Data private to the driver.
-*/
-
-static DEFINE_PCI_DEVICE_TABLE(rio_pci_tbl) = {
-	{0x1186, 0x4000, PCI_ANY_ID, PCI_ANY_ID, },
-	{0x13f0, 0x1021, PCI_ANY_ID, PCI_ANY_ID, },
-	{ }
-};
-MODULE_DEVICE_TABLE (pci, rio_pci_tbl);
-#define TX_TIMEOUT  (4*HZ)
-#define PACKET_SIZE		1536
-#define MAX_JUMBO		8000
-#define RIO_IO_SIZE             340
-#define DEFAULT_RXC		5
-#define DEFAULT_RXT		750
-#define DEFAULT_TXC		1
-#define MAX_TXC			8
-#endif				/* __DL2K_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/dm9000.c linux-libre-3.2-gnu/drivers/net/dm9000.c
--- linux-libre-3.1-gnu/drivers/net/dm9000.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/dm9000.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1705 +0,0 @@
-/*
- *      Davicom DM9000 Fast Ethernet driver for Linux.
- * 	Copyright (C) 1997  Sten Wang
- *
- * 	This program is free software; you can redistribute it and/or
- * 	modify it under the terms of the GNU General Public License
- * 	as published by the Free Software Foundation; either version 2
- * 	of the License, or (at your option) any later version.
- *
- * 	This program is distributed in the hope that it will be useful,
- * 	but WITHOUT ANY WARRANTY; without even the implied warranty of
- * 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * 	GNU General Public License for more details.
- *
- * (C) Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
- *
- * Additional updates, Copyright:
- *	Ben Dooks <ben@simtec.co.uk>
- *	Sascha Hauer <s.hauer@pengutronix.de>
- */
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/crc32.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/dm9000.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-#include <linux/slab.h>
-
-#include <asm/delay.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include "dm9000.h"
-
-/* Board/System/Debug information/definition ---------------- */
-
-#define DM9000_PHY		0x40	/* PHY address 0x01 */
-
-#define CARDNAME	"dm9000"
-#define DRV_VERSION	"1.31"
-
-/*
- * Transmit timeout, default 5 seconds.
- */
-static int watchdog = 5000;
-module_param(watchdog, int, 0400);
-MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
-
-/* DM9000 register address locking.
- *
- * The DM9000 uses an address register to control where data written
- * to the data register goes. This means that the address register
- * must be preserved over interrupts or similar calls.
- *
- * During interrupt and other critical calls, a spinlock is used to
- * protect the system, but the calls themselves save the address
- * in the address register in case they are interrupting another
- * access to the device.
- *
- * For general accesses a lock is provided so that calls which are
- * allowed to sleep are serialised so that the address register does
- * not need to be saved. This lock also serves to serialise access
- * to the EEPROM and PHY access registers which are shared between
- * these two devices.
- */
-
-/* The driver supports the original DM9000E, and now the two newer
- * devices, DM9000A and DM9000B.
- */
-
-enum dm9000_type {
-	TYPE_DM9000E,	/* original DM9000 */
-	TYPE_DM9000A,
-	TYPE_DM9000B
-};
-
-/* Structure/enum declaration ------------------------------- */
-typedef struct board_info {
-
-	void __iomem	*io_addr;	/* Register I/O base address */
-	void __iomem	*io_data;	/* Data I/O address */
-	u16		 irq;		/* IRQ */
-
-	u16		tx_pkt_cnt;
-	u16		queue_pkt_len;
-	u16		queue_start_addr;
-	u16		queue_ip_summed;
-	u16		dbug_cnt;
-	u8		io_mode;		/* 0:word, 2:byte */
-	u8		phy_addr;
-	u8		imr_all;
-
-	unsigned int	flags;
-	unsigned int	in_suspend :1;
-	unsigned int	wake_supported :1;
-	int		debug_level;
-
-	enum dm9000_type type;
-
-	void (*inblk)(void __iomem *port, void *data, int length);
-	void (*outblk)(void __iomem *port, void *data, int length);
-	void (*dumpblk)(void __iomem *port, int length);
-
-	struct device	*dev;	     /* parent device */
-
-	struct resource	*addr_res;   /* resources found */
-	struct resource *data_res;
-	struct resource	*addr_req;   /* resources requested */
-	struct resource *data_req;
-	struct resource *irq_res;
-
-	int		 irq_wake;
-
-	struct mutex	 addr_lock;	/* phy and eeprom access lock */
-
-	struct delayed_work phy_poll;
-	struct net_device  *ndev;
-
-	spinlock_t	lock;
-
-	struct mii_if_info mii;
-	u32		msg_enable;
-	u32		wake_state;
-
-	int		ip_summed;
-} board_info_t;
-
-/* debug code */
-
-#define dm9000_dbg(db, lev, msg...) do {		\
-	if ((lev) < CONFIG_DM9000_DEBUGLEVEL &&		\
-	    (lev) < db->debug_level) {			\
-		dev_dbg(db->dev, msg);			\
-	}						\
-} while (0)
-
-static inline board_info_t *to_dm9000_board(struct net_device *dev)
-{
-	return netdev_priv(dev);
-}
-
-/* DM9000 network board routine ---------------------------- */
-
-static void
-dm9000_reset(board_info_t * db)
-{
-	dev_dbg(db->dev, "resetting device\n");
-
-	/* RESET device */
-	writeb(DM9000_NCR, db->io_addr);
-	udelay(200);
-	writeb(NCR_RST, db->io_data);
-	udelay(200);
-}
-
-/*
- *   Read a byte from I/O port
- */
-static u8
-ior(board_info_t * db, int reg)
-{
-	writeb(reg, db->io_addr);
-	return readb(db->io_data);
-}
-
-/*
- *   Write a byte to I/O port
- */
-
-static void
-iow(board_info_t * db, int reg, int value)
-{
-	writeb(reg, db->io_addr);
-	writeb(value, db->io_data);
-}
-
-/* routines for sending block to chip */
-
-static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count)
-{
-	writesb(reg, data, count);
-}
-
-static void dm9000_outblk_16bit(void __iomem *reg, void *data, int count)
-{
-	writesw(reg, data, (count+1) >> 1);
-}
-
-static void dm9000_outblk_32bit(void __iomem *reg, void *data, int count)
-{
-	writesl(reg, data, (count+3) >> 2);
-}
-
-/* input block from chip to memory */
-
-static void dm9000_inblk_8bit(void __iomem *reg, void *data, int count)
-{
-	readsb(reg, data, count);
-}
-
-
-static void dm9000_inblk_16bit(void __iomem *reg, void *data, int count)
-{
-	readsw(reg, data, (count+1) >> 1);
-}
-
-static void dm9000_inblk_32bit(void __iomem *reg, void *data, int count)
-{
-	readsl(reg, data, (count+3) >> 2);
-}
-
-/* dump block from chip to null */
-
-static void dm9000_dumpblk_8bit(void __iomem *reg, int count)
-{
-	int i;
-	int tmp;
-
-	for (i = 0; i < count; i++)
-		tmp = readb(reg);
-}
-
-static void dm9000_dumpblk_16bit(void __iomem *reg, int count)
-{
-	int i;
-	int tmp;
-
-	count = (count + 1) >> 1;
-
-	for (i = 0; i < count; i++)
-		tmp = readw(reg);
-}
-
-static void dm9000_dumpblk_32bit(void __iomem *reg, int count)
-{
-	int i;
-	int tmp;
-
-	count = (count + 3) >> 2;
-
-	for (i = 0; i < count; i++)
-		tmp = readl(reg);
-}
-
-/* dm9000_set_io
- *
- * select the specified set of io routines to use with the
- * device
- */
-
-static void dm9000_set_io(struct board_info *db, int byte_width)
-{
-	/* use the size of the data resource to work out what IO
-	 * routines we want to use
-	 */
-
-	switch (byte_width) {
-	case 1:
-		db->dumpblk = dm9000_dumpblk_8bit;
-		db->outblk  = dm9000_outblk_8bit;
-		db->inblk   = dm9000_inblk_8bit;
-		break;
-
-
-	case 3:
-		dev_dbg(db->dev, ": 3 byte IO, falling back to 16bit\n");
-	case 2:
-		db->dumpblk = dm9000_dumpblk_16bit;
-		db->outblk  = dm9000_outblk_16bit;
-		db->inblk   = dm9000_inblk_16bit;
-		break;
-
-	case 4:
-	default:
-		db->dumpblk = dm9000_dumpblk_32bit;
-		db->outblk  = dm9000_outblk_32bit;
-		db->inblk   = dm9000_inblk_32bit;
-		break;
-	}
-}
-
-static void dm9000_schedule_poll(board_info_t *db)
-{
-	if (db->type == TYPE_DM9000E)
-		schedule_delayed_work(&db->phy_poll, HZ * 2);
-}
-
-static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
-{
-	board_info_t *dm = to_dm9000_board(dev);
-
-	if (!netif_running(dev))
-		return -EINVAL;
-
-	return generic_mii_ioctl(&dm->mii, if_mii(req), cmd, NULL);
-}
-
-static unsigned int
-dm9000_read_locked(board_info_t *db, int reg)
-{
-	unsigned long flags;
-	unsigned int ret;
-
-	spin_lock_irqsave(&db->lock, flags);
-	ret = ior(db, reg);
-	spin_unlock_irqrestore(&db->lock, flags);
-
-	return ret;
-}
-
-static int dm9000_wait_eeprom(board_info_t *db)
-{
-	unsigned int status;
-	int timeout = 8;	/* wait max 8msec */
-
-	/* The DM9000 data sheets say we should be able to
-	 * poll the ERRE bit in EPCR to wait for the EEPROM
-	 * operation. From testing several chips, this bit
-	 * does not seem to work.
-	 *
-	 * We attempt to use the bit, but fall back to the
-	 * timeout (which is why we do not return an error
-	 * on expiry) to say that the EEPROM operation has
-	 * completed.
-	 */
-
-	while (1) {
-		status = dm9000_read_locked(db, DM9000_EPCR);
-
-		if ((status & EPCR_ERRE) == 0)
-			break;
-
-		msleep(1);
-
-		if (timeout-- < 0) {
-			dev_dbg(db->dev, "timeout waiting EEPROM\n");
-			break;
-		}
-	}
-
-	return 0;
-}
-
-/*
- *  Read a word data from EEPROM
- */
-static void
-dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)
-{
-	unsigned long flags;
-
-	if (db->flags & DM9000_PLATF_NO_EEPROM) {
-		to[0] = 0xff;
-		to[1] = 0xff;
-		return;
-	}
-
-	mutex_lock(&db->addr_lock);
-
-	spin_lock_irqsave(&db->lock, flags);
-
-	iow(db, DM9000_EPAR, offset);
-	iow(db, DM9000_EPCR, EPCR_ERPRR);
-
-	spin_unlock_irqrestore(&db->lock, flags);
-
-	dm9000_wait_eeprom(db);
-
-	/* delay for at-least 150uS */
-	msleep(1);
-
-	spin_lock_irqsave(&db->lock, flags);
-
-	iow(db, DM9000_EPCR, 0x0);
-
-	to[0] = ior(db, DM9000_EPDRL);
-	to[1] = ior(db, DM9000_EPDRH);
-
-	spin_unlock_irqrestore(&db->lock, flags);
-
-	mutex_unlock(&db->addr_lock);
-}
-
-/*
- * Write a word data to SROM
- */
-static void
-dm9000_write_eeprom(board_info_t *db, int offset, u8 *data)
-{
-	unsigned long flags;
-
-	if (db->flags & DM9000_PLATF_NO_EEPROM)
-		return;
-
-	mutex_lock(&db->addr_lock);
-
-	spin_lock_irqsave(&db->lock, flags);
-	iow(db, DM9000_EPAR, offset);
-	iow(db, DM9000_EPDRH, data[1]);
-	iow(db, DM9000_EPDRL, data[0]);
-	iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);
-	spin_unlock_irqrestore(&db->lock, flags);
-
-	dm9000_wait_eeprom(db);
-
-	mdelay(1);	/* wait at least 150uS to clear */
-
-	spin_lock_irqsave(&db->lock, flags);
-	iow(db, DM9000_EPCR, 0);
-	spin_unlock_irqrestore(&db->lock, flags);
-
-	mutex_unlock(&db->addr_lock);
-}
-
-/* ethtool ops */
-
-static void dm9000_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	board_info_t *dm = to_dm9000_board(dev);
-
-	strcpy(info->driver, CARDNAME);
-	strcpy(info->version, DRV_VERSION);
-	strcpy(info->bus_info, to_platform_device(dm->dev)->name);
-}
-
-static u32 dm9000_get_msglevel(struct net_device *dev)
-{
-	board_info_t *dm = to_dm9000_board(dev);
-
-	return dm->msg_enable;
-}
-
-static void dm9000_set_msglevel(struct net_device *dev, u32 value)
-{
-	board_info_t *dm = to_dm9000_board(dev);
-
-	dm->msg_enable = value;
-}
-
-static int dm9000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	board_info_t *dm = to_dm9000_board(dev);
-
-	mii_ethtool_gset(&dm->mii, cmd);
-	return 0;
-}
-
-static int dm9000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	board_info_t *dm = to_dm9000_board(dev);
-
-	return mii_ethtool_sset(&dm->mii, cmd);
-}
-
-static int dm9000_nway_reset(struct net_device *dev)
-{
-	board_info_t *dm = to_dm9000_board(dev);
-	return mii_nway_restart(&dm->mii);
-}
-
-static int dm9000_set_features(struct net_device *dev, u32 features)
-{
-	board_info_t *dm = to_dm9000_board(dev);
-	u32 changed = dev->features ^ features;
-	unsigned long flags;
-
-	if (!(changed & NETIF_F_RXCSUM))
-		return 0;
-
-	spin_lock_irqsave(&dm->lock, flags);
-	iow(dm, DM9000_RCSR, (features & NETIF_F_RXCSUM) ? RCSR_CSUM : 0);
-	spin_unlock_irqrestore(&dm->lock, flags);
-
-	return 0;
-}
-
-static u32 dm9000_get_link(struct net_device *dev)
-{
-	board_info_t *dm = to_dm9000_board(dev);
-	u32 ret;
-
-	if (dm->flags & DM9000_PLATF_EXT_PHY)
-		ret = mii_link_ok(&dm->mii);
-	else
-		ret = dm9000_read_locked(dm, DM9000_NSR) & NSR_LINKST ? 1 : 0;
-
-	return ret;
-}
-
-#define DM_EEPROM_MAGIC		(0x444D394B)
-
-static int dm9000_get_eeprom_len(struct net_device *dev)
-{
-	return 128;
-}
-
-static int dm9000_get_eeprom(struct net_device *dev,
-			     struct ethtool_eeprom *ee, u8 *data)
-{
-	board_info_t *dm = to_dm9000_board(dev);
-	int offset = ee->offset;
-	int len = ee->len;
-	int i;
-
-	/* EEPROM access is aligned to two bytes */
-
-	if ((len & 1) != 0 || (offset & 1) != 0)
-		return -EINVAL;
-
-	if (dm->flags & DM9000_PLATF_NO_EEPROM)
-		return -ENOENT;
-
-	ee->magic = DM_EEPROM_MAGIC;
-
-	for (i = 0; i < len; i += 2)
-		dm9000_read_eeprom(dm, (offset + i) / 2, data + i);
-
-	return 0;
-}
-
-static int dm9000_set_eeprom(struct net_device *dev,
-			     struct ethtool_eeprom *ee, u8 *data)
-{
-	board_info_t *dm = to_dm9000_board(dev);
-	int offset = ee->offset;
-	int len = ee->len;
-	int done;
-
-	/* EEPROM access is aligned to two bytes */
-
-	if (dm->flags & DM9000_PLATF_NO_EEPROM)
-		return -ENOENT;
-
-	if (ee->magic != DM_EEPROM_MAGIC)
-		return -EINVAL;
-
-	while (len > 0) {
-		if (len & 1 || offset & 1) {
-			int which = offset & 1;
-			u8 tmp[2];
-
-			dm9000_read_eeprom(dm, offset / 2, tmp);
-			tmp[which] = *data;
-			dm9000_write_eeprom(dm, offset / 2, tmp);
-
-			done = 1;
-		} else {
-			dm9000_write_eeprom(dm, offset / 2, data);
-			done = 2;
-		}
-
-		data += done;
-		offset += done;
-		len -= done;
-	}
-
-	return 0;
-}
-
-static void dm9000_get_wol(struct net_device *dev, struct ethtool_wolinfo *w)
-{
-	board_info_t *dm = to_dm9000_board(dev);
-
-	memset(w, 0, sizeof(struct ethtool_wolinfo));
-
-	/* note, we could probably support wake-phy too */
-	w->supported = dm->wake_supported ? WAKE_MAGIC : 0;
-	w->wolopts = dm->wake_state;
-}
-
-static int dm9000_set_wol(struct net_device *dev, struct ethtool_wolinfo *w)
-{
-	board_info_t *dm = to_dm9000_board(dev);
-	unsigned long flags;
-	u32 opts = w->wolopts;
-	u32 wcr = 0;
-
-	if (!dm->wake_supported)
-		return -EOPNOTSUPP;
-
-	if (opts & ~WAKE_MAGIC)
-		return -EINVAL;
-
-	if (opts & WAKE_MAGIC)
-		wcr |= WCR_MAGICEN;
-
-	mutex_lock(&dm->addr_lock);
-
-	spin_lock_irqsave(&dm->lock, flags);
-	iow(dm, DM9000_WCR, wcr);
-	spin_unlock_irqrestore(&dm->lock, flags);
-
-	mutex_unlock(&dm->addr_lock);
-
-	if (dm->wake_state != opts) {
-		/* change in wol state, update IRQ state */
-
-		if (!dm->wake_state)
-			irq_set_irq_wake(dm->irq_wake, 1);
-		else if (dm->wake_state & !opts)
-			irq_set_irq_wake(dm->irq_wake, 0);
-	}
-
-	dm->wake_state = opts;
-	return 0;
-}
-
-static const struct ethtool_ops dm9000_ethtool_ops = {
-	.get_drvinfo		= dm9000_get_drvinfo,
-	.get_settings		= dm9000_get_settings,
-	.set_settings		= dm9000_set_settings,
-	.get_msglevel		= dm9000_get_msglevel,
-	.set_msglevel		= dm9000_set_msglevel,
-	.nway_reset		= dm9000_nway_reset,
-	.get_link		= dm9000_get_link,
-	.get_wol		= dm9000_get_wol,
-	.set_wol		= dm9000_set_wol,
- 	.get_eeprom_len		= dm9000_get_eeprom_len,
- 	.get_eeprom		= dm9000_get_eeprom,
- 	.set_eeprom		= dm9000_set_eeprom,
-};
-
-static void dm9000_show_carrier(board_info_t *db,
-				unsigned carrier, unsigned nsr)
-{
-	struct net_device *ndev = db->ndev;
-	unsigned ncr = dm9000_read_locked(db, DM9000_NCR);
-
-	if (carrier)
-		dev_info(db->dev, "%s: link up, %dMbps, %s-duplex, no LPA\n",
-			 ndev->name, (nsr & NSR_SPEED) ? 10 : 100,
-			 (ncr & NCR_FDX) ? "full" : "half");
-	else
-		dev_info(db->dev, "%s: link down\n", ndev->name);
-}
-
-static void
-dm9000_poll_work(struct work_struct *w)
-{
-	struct delayed_work *dw = to_delayed_work(w);
-	board_info_t *db = container_of(dw, board_info_t, phy_poll);
-	struct net_device *ndev = db->ndev;
-
-	if (db->flags & DM9000_PLATF_SIMPLE_PHY &&
-	    !(db->flags & DM9000_PLATF_EXT_PHY)) {
-		unsigned nsr = dm9000_read_locked(db, DM9000_NSR);
-		unsigned old_carrier = netif_carrier_ok(ndev) ? 1 : 0;
-		unsigned new_carrier;
-
-		new_carrier = (nsr & NSR_LINKST) ? 1 : 0;
-
-		if (old_carrier != new_carrier) {
-			if (netif_msg_link(db))
-				dm9000_show_carrier(db, new_carrier, nsr);
-
-			if (!new_carrier)
-				netif_carrier_off(ndev);
-			else
-				netif_carrier_on(ndev);
-		}
-	} else
-		mii_check_media(&db->mii, netif_msg_link(db), 0);
-	
-	if (netif_running(ndev))
-		dm9000_schedule_poll(db);
-}
-
-/* dm9000_release_board
- *
- * release a board, and any mapped resources
- */
-
-static void
-dm9000_release_board(struct platform_device *pdev, struct board_info *db)
-{
-	/* unmap our resources */
-
-	iounmap(db->io_addr);
-	iounmap(db->io_data);
-
-	/* release the resources */
-
-	release_resource(db->data_req);
-	kfree(db->data_req);
-
-	release_resource(db->addr_req);
-	kfree(db->addr_req);
-}
-
-static unsigned char dm9000_type_to_char(enum dm9000_type type)
-{
-	switch (type) {
-	case TYPE_DM9000E: return 'e';
-	case TYPE_DM9000A: return 'a';
-	case TYPE_DM9000B: return 'b';
-	}
-
-	return '?';
-}
-
-/*
- *  Set DM9000 multicast address
- */
-static void
-dm9000_hash_table_unlocked(struct net_device *dev)
-{
-	board_info_t *db = netdev_priv(dev);
-	struct netdev_hw_addr *ha;
-	int i, oft;
-	u32 hash_val;
-	u16 hash_table[4];
-	u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN;
-
-	dm9000_dbg(db, 1, "entering %s\n", __func__);
-
-	for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
-		iow(db, oft, dev->dev_addr[i]);
-
-	/* Clear Hash Table */
-	for (i = 0; i < 4; i++)
-		hash_table[i] = 0x0;
-
-	/* broadcast address */
-	hash_table[3] = 0x8000;
-
-	if (dev->flags & IFF_PROMISC)
-		rcr |= RCR_PRMSC;
-
-	if (dev->flags & IFF_ALLMULTI)
-		rcr |= RCR_ALL;
-
-	/* the multicast address in Hash Table : 64 bits */
-	netdev_for_each_mc_addr(ha, dev) {
-		hash_val = ether_crc_le(6, ha->addr) & 0x3f;
-		hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
-	}
-
-	/* Write the hash table to MAC MD table */
-	for (i = 0, oft = DM9000_MAR; i < 4; i++) {
-		iow(db, oft++, hash_table[i]);
-		iow(db, oft++, hash_table[i] >> 8);
-	}
-
-	iow(db, DM9000_RCR, rcr);
-}
-
-static void
-dm9000_hash_table(struct net_device *dev)
-{
-	board_info_t *db = netdev_priv(dev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&db->lock, flags);
-	dm9000_hash_table_unlocked(dev);
-	spin_unlock_irqrestore(&db->lock, flags);
-}
-
-/*
- * Initialize dm9000 board
- */
-static void
-dm9000_init_dm9000(struct net_device *dev)
-{
-	board_info_t *db = netdev_priv(dev);
-	unsigned int imr;
-	unsigned int ncr;
-
-	dm9000_dbg(db, 1, "entering %s\n", __func__);
-
-	/* I/O mode */
-	db->io_mode = ior(db, DM9000_ISR) >> 6;	/* ISR bit7:6 keeps I/O mode */
-
-	/* Checksum mode */
-	if (dev->hw_features & NETIF_F_RXCSUM)
-		iow(db, DM9000_RCSR,
-			(dev->features & NETIF_F_RXCSUM) ? RCSR_CSUM : 0);
-
-	iow(db, DM9000_GPCR, GPCR_GEP_CNTL);	/* Let GPIO0 output */
-
-	ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0;
-
-	/* if wol is needed, then always set NCR_WAKEEN otherwise we end
-	 * up dumping the wake events if we disable this. There is already
-	 * a wake-mask in DM9000_WCR */
-	if (db->wake_supported)
-		ncr |= NCR_WAKEEN;
-
-	iow(db, DM9000_NCR, ncr);
-
-	/* Program operating register */
-	iow(db, DM9000_TCR, 0);	        /* TX Polling clear */
-	iow(db, DM9000_BPTR, 0x3f);	/* Less 3Kb, 200us */
-	iow(db, DM9000_FCR, 0xff);	/* Flow Control */
-	iow(db, DM9000_SMCR, 0);        /* Special Mode */
-	/* clear TX status */
-	iow(db, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
-	iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */
-
-	/* Set address filter table */
-	dm9000_hash_table_unlocked(dev);
-
-	imr = IMR_PAR | IMR_PTM | IMR_PRM;
-	if (db->type != TYPE_DM9000E)
-		imr |= IMR_LNKCHNG;
-
-	db->imr_all = imr;
-
-	/* Enable TX/RX interrupt mask */
-	iow(db, DM9000_IMR, imr);
-
-	/* Init Driver variable */
-	db->tx_pkt_cnt = 0;
-	db->queue_pkt_len = 0;
-	dev->trans_start = jiffies;
-}
-
-/* Our watchdog timed out. Called by the networking layer */
-static void dm9000_timeout(struct net_device *dev)
-{
-	board_info_t *db = netdev_priv(dev);
-	u8 reg_save;
-	unsigned long flags;
-
-	/* Save previous register address */
-	spin_lock_irqsave(&db->lock, flags);
-	reg_save = readb(db->io_addr);
-
-	netif_stop_queue(dev);
-	dm9000_reset(db);
-	dm9000_init_dm9000(dev);
-	/* We can accept TX packets again */
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	netif_wake_queue(dev);
-
-	/* Restore previous register address */
-	writeb(reg_save, db->io_addr);
-	spin_unlock_irqrestore(&db->lock, flags);
-}
-
-static void dm9000_send_packet(struct net_device *dev,
-			       int ip_summed,
-			       u16 pkt_len)
-{
-	board_info_t *dm = to_dm9000_board(dev);
-
-	/* The DM9000 is not smart enough to leave fragmented packets alone. */
-	if (dm->ip_summed != ip_summed) {
-		if (ip_summed == CHECKSUM_NONE)
-			iow(dm, DM9000_TCCR, 0);
-		else
-			iow(dm, DM9000_TCCR, TCCR_IP | TCCR_UDP | TCCR_TCP);
-		dm->ip_summed = ip_summed;
-	}
-
-	/* Set TX length to DM9000 */
-	iow(dm, DM9000_TXPLL, pkt_len);
-	iow(dm, DM9000_TXPLH, pkt_len >> 8);
-
-	/* Issue TX polling command */
-	iow(dm, DM9000_TCR, TCR_TXREQ);	/* Cleared after TX complete */
-}
-
-/*
- *  Hardware start transmission.
- *  Send a packet to media from the upper layer.
- */
-static int
-dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	unsigned long flags;
-	board_info_t *db = netdev_priv(dev);
-
-	dm9000_dbg(db, 3, "%s:\n", __func__);
-
-	if (db->tx_pkt_cnt > 1)
-		return NETDEV_TX_BUSY;
-
-	spin_lock_irqsave(&db->lock, flags);
-
-	/* Move data to DM9000 TX RAM */
-	writeb(DM9000_MWCMD, db->io_addr);
-
-	(db->outblk)(db->io_data, skb->data, skb->len);
-	dev->stats.tx_bytes += skb->len;
-
-	db->tx_pkt_cnt++;
-	/* TX control: First packet immediately send, second packet queue */
-	if (db->tx_pkt_cnt == 1) {
-		dm9000_send_packet(dev, skb->ip_summed, skb->len);
-	} else {
-		/* Second packet */
-		db->queue_pkt_len = skb->len;
-		db->queue_ip_summed = skb->ip_summed;
-		netif_stop_queue(dev);
-	}
-
-	spin_unlock_irqrestore(&db->lock, flags);
-
-	/* free this SKB */
-	dev_kfree_skb(skb);
-
-	return NETDEV_TX_OK;
-}
-
-/*
- * DM9000 interrupt handler
- * receive the packet to upper layer, free the transmitted packet
- */
-
-static void dm9000_tx_done(struct net_device *dev, board_info_t *db)
-{
-	int tx_status = ior(db, DM9000_NSR);	/* Got TX status */
-
-	if (tx_status & (NSR_TX2END | NSR_TX1END)) {
-		/* One packet sent complete */
-		db->tx_pkt_cnt--;
-		dev->stats.tx_packets++;
-
-		if (netif_msg_tx_done(db))
-			dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status);
-
-		/* Queue packet check & send */
-		if (db->tx_pkt_cnt > 0)
-			dm9000_send_packet(dev, db->queue_ip_summed,
-					   db->queue_pkt_len);
-		netif_wake_queue(dev);
-	}
-}
-
-struct dm9000_rxhdr {
-	u8	RxPktReady;
-	u8	RxStatus;
-	__le16	RxLen;
-} __packed;
-
-/*
- *  Received a packet and pass to upper layer
- */
-static void
-dm9000_rx(struct net_device *dev)
-{
-	board_info_t *db = netdev_priv(dev);
-	struct dm9000_rxhdr rxhdr;
-	struct sk_buff *skb;
-	u8 rxbyte, *rdptr;
-	bool GoodPacket;
-	int RxLen;
-
-	/* Check packet ready or not */
-	do {
-		ior(db, DM9000_MRCMDX);	/* Dummy read */
-
-		/* Get most updated data */
-		rxbyte = readb(db->io_data);
-
-		/* Status check: this byte must be 0 or 1 */
-		if (rxbyte & DM9000_PKT_ERR) {
-			dev_warn(db->dev, "status check fail: %d\n", rxbyte);
-			iow(db, DM9000_RCR, 0x00);	/* Stop Device */
-			iow(db, DM9000_ISR, IMR_PAR);	/* Stop INT request */
-			return;
-		}
-
-		if (!(rxbyte & DM9000_PKT_RDY))
-			return;
-
-		/* A packet ready now  & Get status/length */
-		GoodPacket = true;
-		writeb(DM9000_MRCMD, db->io_addr);
-
-		(db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));
-
-		RxLen = le16_to_cpu(rxhdr.RxLen);
-
-		if (netif_msg_rx_status(db))
-			dev_dbg(db->dev, "RX: status %02x, length %04x\n",
-				rxhdr.RxStatus, RxLen);
-
-		/* Packet Status check */
-		if (RxLen < 0x40) {
-			GoodPacket = false;
-			if (netif_msg_rx_err(db))
-				dev_dbg(db->dev, "RX: Bad Packet (runt)\n");
-		}
-
-		if (RxLen > DM9000_PKT_MAX) {
-			dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);
-		}
-
-		/* rxhdr.RxStatus is identical to RSR register. */
-		if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE |
-				      RSR_PLE | RSR_RWTO |
-				      RSR_LCS | RSR_RF)) {
-			GoodPacket = false;
-			if (rxhdr.RxStatus & RSR_FOE) {
-				if (netif_msg_rx_err(db))
-					dev_dbg(db->dev, "fifo error\n");
-				dev->stats.rx_fifo_errors++;
-			}
-			if (rxhdr.RxStatus & RSR_CE) {
-				if (netif_msg_rx_err(db))
-					dev_dbg(db->dev, "crc error\n");
-				dev->stats.rx_crc_errors++;
-			}
-			if (rxhdr.RxStatus & RSR_RF) {
-				if (netif_msg_rx_err(db))
-					dev_dbg(db->dev, "length error\n");
-				dev->stats.rx_length_errors++;
-			}
-		}
-
-		/* Move data from DM9000 */
-		if (GoodPacket &&
-		    ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {
-			skb_reserve(skb, 2);
-			rdptr = (u8 *) skb_put(skb, RxLen - 4);
-
-			/* Read received packet from RX SRAM */
-
-			(db->inblk)(db->io_data, rdptr, RxLen);
-			dev->stats.rx_bytes += RxLen;
-
-			/* Pass to upper layer */
-			skb->protocol = eth_type_trans(skb, dev);
-			if (dev->features & NETIF_F_RXCSUM) {
-				if ((((rxbyte & 0x1c) << 3) & rxbyte) == 0)
-					skb->ip_summed = CHECKSUM_UNNECESSARY;
-				else
-					skb_checksum_none_assert(skb);
-			}
-			netif_rx(skb);
-			dev->stats.rx_packets++;
-
-		} else {
-			/* need to dump the packet's data */
-
-			(db->dumpblk)(db->io_data, RxLen);
-		}
-	} while (rxbyte & DM9000_PKT_RDY);
-}
-
-static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	board_info_t *db = netdev_priv(dev);
-	int int_status;
-	unsigned long flags;
-	u8 reg_save;
-
-	dm9000_dbg(db, 3, "entering %s\n", __func__);
-
-	/* A real interrupt coming */
-
-	/* holders of db->lock must always block IRQs */
-	spin_lock_irqsave(&db->lock, flags);
-
-	/* Save previous register address */
-	reg_save = readb(db->io_addr);
-
-	/* Disable all interrupts */
-	iow(db, DM9000_IMR, IMR_PAR);
-
-	/* Got DM9000 interrupt status */
-	int_status = ior(db, DM9000_ISR);	/* Got ISR */
-	iow(db, DM9000_ISR, int_status);	/* Clear ISR status */
-
-	if (netif_msg_intr(db))
-		dev_dbg(db->dev, "interrupt status %02x\n", int_status);
-
-	/* Received the coming packet */
-	if (int_status & ISR_PRS)
-		dm9000_rx(dev);
-
-	/* Trnasmit Interrupt check */
-	if (int_status & ISR_PTS)
-		dm9000_tx_done(dev, db);
-
-	if (db->type != TYPE_DM9000E) {
-		if (int_status & ISR_LNKCHNG) {
-			/* fire a link-change request */
-			schedule_delayed_work(&db->phy_poll, 1);
-		}
-	}
-
-	/* Re-enable interrupt mask */
-	iow(db, DM9000_IMR, db->imr_all);
-
-	/* Restore previous register address */
-	writeb(reg_save, db->io_addr);
-
-	spin_unlock_irqrestore(&db->lock, flags);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t dm9000_wol_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	board_info_t *db = netdev_priv(dev);
-	unsigned long flags;
-	unsigned nsr, wcr;
-
-	spin_lock_irqsave(&db->lock, flags);
-
-	nsr = ior(db, DM9000_NSR);
-	wcr = ior(db, DM9000_WCR);
-
-	dev_dbg(db->dev, "%s: NSR=0x%02x, WCR=0x%02x\n", __func__, nsr, wcr);
-
-	if (nsr & NSR_WAKEST) {
-		/* clear, so we can avoid */
-		iow(db, DM9000_NSR, NSR_WAKEST);
-
-		if (wcr & WCR_LINKST)
-			dev_info(db->dev, "wake by link status change\n");
-		if (wcr & WCR_SAMPLEST)
-			dev_info(db->dev, "wake by sample packet\n");
-		if (wcr & WCR_MAGICST )
-			dev_info(db->dev, "wake by magic packet\n");
-		if (!(wcr & (WCR_LINKST | WCR_SAMPLEST | WCR_MAGICST)))
-			dev_err(db->dev, "wake signalled with no reason? "
-				"NSR=0x%02x, WSR=0x%02x\n", nsr, wcr);
-
-	}
-
-	spin_unlock_irqrestore(&db->lock, flags);
-
-	return (nsr & NSR_WAKEST) ? IRQ_HANDLED : IRQ_NONE;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- *Used by netconsole
- */
-static void dm9000_poll_controller(struct net_device *dev)
-{
-	disable_irq(dev->irq);
-	dm9000_interrupt(dev->irq, dev);
-	enable_irq(dev->irq);
-}
-#endif
-
-/*
- *  Open the interface.
- *  The interface is opened whenever "ifconfig" actives it.
- */
-static int
-dm9000_open(struct net_device *dev)
-{
-	board_info_t *db = netdev_priv(dev);
-	unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
-
-	if (netif_msg_ifup(db))
-		dev_dbg(db->dev, "enabling %s\n", dev->name);
-
-	/* If there is no IRQ type specified, default to something that
-	 * may work, and tell the user that this is a problem */
-
-	if (irqflags == IRQF_TRIGGER_NONE)
-		dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");
-
-	irqflags |= IRQF_SHARED;
-
-	/* GPIO0 on pre-activate PHY, Reg 1F is not set by reset */
-	iow(db, DM9000_GPR, 0);	/* REG_1F bit0 activate phyxcer */
-	mdelay(1); /* delay needs by DM9000B */
-
-	/* Initialize DM9000 board */
-	dm9000_reset(db);
-	dm9000_init_dm9000(dev);
-
-	if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev))
-		return -EAGAIN;
-
-	/* Init driver variable */
-	db->dbug_cnt = 0;
-
-	mii_check_media(&db->mii, netif_msg_link(db), 1);
-	netif_start_queue(dev);
-	
-	dm9000_schedule_poll(db);
-
-	return 0;
-}
-
-/*
- * Sleep, either by using msleep() or if we are suspending, then
- * use mdelay() to sleep.
- */
-static void dm9000_msleep(board_info_t *db, unsigned int ms)
-{
-	if (db->in_suspend)
-		mdelay(ms);
-	else
-		msleep(ms);
-}
-
-/*
- *   Read a word from phyxcer
- */
-static int
-dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
-{
-	board_info_t *db = netdev_priv(dev);
-	unsigned long flags;
-	unsigned int reg_save;
-	int ret;
-
-	mutex_lock(&db->addr_lock);
-
-	spin_lock_irqsave(&db->lock,flags);
-
-	/* Save previous register address */
-	reg_save = readb(db->io_addr);
-
-	/* Fill the phyxcer register into REG_0C */
-	iow(db, DM9000_EPAR, DM9000_PHY | reg);
-
-	iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS);	/* Issue phyxcer read command */
-
-	writeb(reg_save, db->io_addr);
-	spin_unlock_irqrestore(&db->lock,flags);
-
-	dm9000_msleep(db, 1);		/* Wait read complete */
-
-	spin_lock_irqsave(&db->lock,flags);
-	reg_save = readb(db->io_addr);
-
-	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer read command */
-
-	/* The read data keeps on REG_0D & REG_0E */
-	ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
-
-	/* restore the previous address */
-	writeb(reg_save, db->io_addr);
-	spin_unlock_irqrestore(&db->lock,flags);
-
-	mutex_unlock(&db->addr_lock);
-
-	dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret);
-	return ret;
-}
-
-/*
- *   Write a word to phyxcer
- */
-static void
-dm9000_phy_write(struct net_device *dev,
-		 int phyaddr_unused, int reg, int value)
-{
-	board_info_t *db = netdev_priv(dev);
-	unsigned long flags;
-	unsigned long reg_save;
-
-	dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
-	mutex_lock(&db->addr_lock);
-
-	spin_lock_irqsave(&db->lock,flags);
-
-	/* Save previous register address */
-	reg_save = readb(db->io_addr);
-
-	/* Fill the phyxcer register into REG_0C */
-	iow(db, DM9000_EPAR, DM9000_PHY | reg);
-
-	/* Fill the written data into REG_0D & REG_0E */
-	iow(db, DM9000_EPDRL, value);
-	iow(db, DM9000_EPDRH, value >> 8);
-
-	iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW);	/* Issue phyxcer write command */
-
-	writeb(reg_save, db->io_addr);
-	spin_unlock_irqrestore(&db->lock, flags);
-
-	dm9000_msleep(db, 1);		/* Wait write complete */
-
-	spin_lock_irqsave(&db->lock,flags);
-	reg_save = readb(db->io_addr);
-
-	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer write command */
-
-	/* restore the previous address */
-	writeb(reg_save, db->io_addr);
-
-	spin_unlock_irqrestore(&db->lock, flags);
-	mutex_unlock(&db->addr_lock);
-}
-
-static void
-dm9000_shutdown(struct net_device *dev)
-{
-	board_info_t *db = netdev_priv(dev);
-
-	/* RESET device */
-	dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET);	/* PHY RESET */
-	iow(db, DM9000_GPR, 0x01);	/* Power-Down PHY */
-	iow(db, DM9000_IMR, IMR_PAR);	/* Disable all interrupt */
-	iow(db, DM9000_RCR, 0x00);	/* Disable RX */
-}
-
-/*
- * Stop the interface.
- * The interface is stopped when it is brought.
- */
-static int
-dm9000_stop(struct net_device *ndev)
-{
-	board_info_t *db = netdev_priv(ndev);
-
-	if (netif_msg_ifdown(db))
-		dev_dbg(db->dev, "shutting down %s\n", ndev->name);
-
-	cancel_delayed_work_sync(&db->phy_poll);
-
-	netif_stop_queue(ndev);
-	netif_carrier_off(ndev);
-
-	/* free interrupt */
-	free_irq(ndev->irq, ndev);
-
-	dm9000_shutdown(ndev);
-
-	return 0;
-}
-
-static const struct net_device_ops dm9000_netdev_ops = {
-	.ndo_open		= dm9000_open,
-	.ndo_stop		= dm9000_stop,
-	.ndo_start_xmit		= dm9000_start_xmit,
-	.ndo_tx_timeout		= dm9000_timeout,
-	.ndo_set_multicast_list	= dm9000_hash_table,
-	.ndo_do_ioctl		= dm9000_ioctl,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_features	= dm9000_set_features,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address	= eth_mac_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= dm9000_poll_controller,
-#endif
-};
-
-/*
- * Search DM9000 board, allocate space and register it
- */
-static int __devinit
-dm9000_probe(struct platform_device *pdev)
-{
-	struct dm9000_plat_data *pdata = pdev->dev.platform_data;
-	struct board_info *db;	/* Point a board information structure */
-	struct net_device *ndev;
-	const unsigned char *mac_src;
-	int ret = 0;
-	int iosize;
-	int i;
-	u32 id_val;
-
-	/* Init network device */
-	ndev = alloc_etherdev(sizeof(struct board_info));
-	if (!ndev) {
-		dev_err(&pdev->dev, "could not allocate device.\n");
-		return -ENOMEM;
-	}
-
-	SET_NETDEV_DEV(ndev, &pdev->dev);
-
-	dev_dbg(&pdev->dev, "dm9000_probe()\n");
-
-	/* setup board info structure */
-	db = netdev_priv(ndev);
-
-	db->dev = &pdev->dev;
-	db->ndev = ndev;
-
-	spin_lock_init(&db->lock);
-	mutex_init(&db->addr_lock);
-
-	INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work);
-
-	db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	db->irq_res  = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-
-	if (db->addr_res == NULL || db->data_res == NULL ||
-	    db->irq_res == NULL) {
-		dev_err(db->dev, "insufficient resources\n");
-		ret = -ENOENT;
-		goto out;
-	}
-
-	db->irq_wake = platform_get_irq(pdev, 1);
-	if (db->irq_wake >= 0) {
-		dev_dbg(db->dev, "wakeup irq %d\n", db->irq_wake);
-
-		ret = request_irq(db->irq_wake, dm9000_wol_interrupt,
-				  IRQF_SHARED, dev_name(db->dev), ndev);
-		if (ret) {
-			dev_err(db->dev, "cannot get wakeup irq (%d)\n", ret);
-		} else {
-
-			/* test to see if irq is really wakeup capable */
-			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 {
-				irq_set_irq_wake(db->irq_wake, 0);
-				db->wake_supported = 1;
-			}
-		}
-	}
-
-	iosize = resource_size(db->addr_res);
-	db->addr_req = request_mem_region(db->addr_res->start, iosize,
-					  pdev->name);
-
-	if (db->addr_req == NULL) {
-		dev_err(db->dev, "cannot claim address reg area\n");
-		ret = -EIO;
-		goto out;
-	}
-
-	db->io_addr = ioremap(db->addr_res->start, iosize);
-
-	if (db->io_addr == NULL) {
-		dev_err(db->dev, "failed to ioremap address reg\n");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	iosize = resource_size(db->data_res);
-	db->data_req = request_mem_region(db->data_res->start, iosize,
-					  pdev->name);
-
-	if (db->data_req == NULL) {
-		dev_err(db->dev, "cannot claim data reg area\n");
-		ret = -EIO;
-		goto out;
-	}
-
-	db->io_data = ioremap(db->data_res->start, iosize);
-
-	if (db->io_data == NULL) {
-		dev_err(db->dev, "failed to ioremap data reg\n");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/* fill in parameters for net-dev structure */
-	ndev->base_addr = (unsigned long)db->io_addr;
-	ndev->irq	= db->irq_res->start;
-
-	/* ensure at least we have a default set of IO routines */
-	dm9000_set_io(db, iosize);
-
-	/* check to see if anything is being over-ridden */
-	if (pdata != NULL) {
-		/* check to see if the driver wants to over-ride the
-		 * default IO width */
-
-		if (pdata->flags & DM9000_PLATF_8BITONLY)
-			dm9000_set_io(db, 1);
-
-		if (pdata->flags & DM9000_PLATF_16BITONLY)
-			dm9000_set_io(db, 2);
-
-		if (pdata->flags & DM9000_PLATF_32BITONLY)
-			dm9000_set_io(db, 4);
-
-		/* check to see if there are any IO routine
-		 * over-rides */
-
-		if (pdata->inblk != NULL)
-			db->inblk = pdata->inblk;
-
-		if (pdata->outblk != NULL)
-			db->outblk = pdata->outblk;
-
-		if (pdata->dumpblk != NULL)
-			db->dumpblk = pdata->dumpblk;
-
-		db->flags = pdata->flags;
-	}
-
-#ifdef CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL
-	db->flags |= DM9000_PLATF_SIMPLE_PHY;
-#endif
-
-	dm9000_reset(db);
-
-	/* try multiple times, DM9000 sometimes gets the read wrong */
-	for (i = 0; i < 8; i++) {
-		id_val  = ior(db, DM9000_VIDL);
-		id_val |= (u32)ior(db, DM9000_VIDH) << 8;
-		id_val |= (u32)ior(db, DM9000_PIDL) << 16;
-		id_val |= (u32)ior(db, DM9000_PIDH) << 24;
-
-		if (id_val == DM9000_ID)
-			break;
-		dev_err(db->dev, "read wrong id 0x%08x\n", id_val);
-	}
-
-	if (id_val != DM9000_ID) {
-		dev_err(db->dev, "wrong id: 0x%08x\n", id_val);
-		ret = -ENODEV;
-		goto out;
-	}
-
-	/* Identify what type of DM9000 we are working on */
-
-	id_val = ior(db, DM9000_CHIPR);
-	dev_dbg(db->dev, "dm9000 revision 0x%02x\n", id_val);
-
-	switch (id_val) {
-	case CHIPR_DM9000A:
-		db->type = TYPE_DM9000A;
-		break;
-	case CHIPR_DM9000B:
-		db->type = TYPE_DM9000B;
-		break;
-	default:
-		dev_dbg(db->dev, "ID %02x => defaulting to DM9000E\n", id_val);
-		db->type = TYPE_DM9000E;
-	}
-
-	/* dm9000a/b are capable of hardware checksum offload */
-	if (db->type == TYPE_DM9000A || db->type == TYPE_DM9000B) {
-		ndev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
-		ndev->features |= ndev->hw_features;
-	}
-
-	/* from this point we assume that we have found a DM9000 */
-
-	/* driver system function */
-	ether_setup(ndev);
-
-	ndev->netdev_ops	= &dm9000_netdev_ops;
-	ndev->watchdog_timeo	= msecs_to_jiffies(watchdog);
-	ndev->ethtool_ops	= &dm9000_ethtool_ops;
-
-	db->msg_enable       = NETIF_MSG_LINK;
-	db->mii.phy_id_mask  = 0x1f;
-	db->mii.reg_num_mask = 0x1f;
-	db->mii.force_media  = 0;
-	db->mii.full_duplex  = 0;
-	db->mii.dev	     = ndev;
-	db->mii.mdio_read    = dm9000_phy_read;
-	db->mii.mdio_write   = dm9000_phy_write;
-
-	mac_src = "eeprom";
-
-	/* try reading the node address from the attached EEPROM */
-	for (i = 0; i < 6; i += 2)
-		dm9000_read_eeprom(db, i / 2, ndev->dev_addr+i);
-
-	if (!is_valid_ether_addr(ndev->dev_addr) && pdata != NULL) {
-		mac_src = "platform data";
-		memcpy(ndev->dev_addr, pdata->dev_addr, 6);
-	}
-
-	if (!is_valid_ether_addr(ndev->dev_addr)) {
-		/* try reading from mac */
-		
-		mac_src = "chip";
-		for (i = 0; i < 6; i++)
-			ndev->dev_addr[i] = ior(db, i+DM9000_PAR);
-	}
-
-	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);
-
-	if (ret == 0)
-		printk(KERN_INFO "%s: dm9000%c at %p,%p IRQ %d MAC: %pM (%s)\n",
-		       ndev->name, dm9000_type_to_char(db->type),
-		       db->io_addr, db->io_data, ndev->irq,
-		       ndev->dev_addr, mac_src);
-	return 0;
-
-out:
-	dev_err(db->dev, "not found (%d).\n", ret);
-
-	dm9000_release_board(pdev, db);
-	free_netdev(ndev);
-
-	return ret;
-}
-
-static int
-dm9000_drv_suspend(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct net_device *ndev = platform_get_drvdata(pdev);
-	board_info_t *db;
-
-	if (ndev) {
-		db = netdev_priv(ndev);
-		db->in_suspend = 1;
-
-		if (!netif_running(ndev))
-			return 0;
-
-		netif_device_detach(ndev);
-
-		/* only shutdown if not using WoL */
-		if (!db->wake_state)
-			dm9000_shutdown(ndev);
-	}
-	return 0;
-}
-
-static int
-dm9000_drv_resume(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct net_device *ndev = platform_get_drvdata(pdev);
-	board_info_t *db = netdev_priv(ndev);
-
-	if (ndev) {
-		if (netif_running(ndev)) {
-			/* reset if we were not in wake mode to ensure if
-			 * the device was powered off it is in a known state */
-			if (!db->wake_state) {
-				dm9000_reset(db);
-				dm9000_init_dm9000(ndev);
-			}
-
-			netif_device_attach(ndev);
-		}
-
-		db->in_suspend = 0;
-	}
-	return 0;
-}
-
-static const struct dev_pm_ops dm9000_drv_pm_ops = {
-	.suspend	= dm9000_drv_suspend,
-	.resume		= dm9000_drv_resume,
-};
-
-static int __devexit
-dm9000_drv_remove(struct platform_device *pdev)
-{
-	struct net_device *ndev = platform_get_drvdata(pdev);
-
-	platform_set_drvdata(pdev, NULL);
-
-	unregister_netdev(ndev);
-	dm9000_release_board(pdev, netdev_priv(ndev));
-	free_netdev(ndev);		/* free device structure */
-
-	dev_dbg(&pdev->dev, "released and freed device\n");
-	return 0;
-}
-
-static struct platform_driver dm9000_driver = {
-	.driver	= {
-		.name    = "dm9000",
-		.owner	 = THIS_MODULE,
-		.pm	 = &dm9000_drv_pm_ops,
-	},
-	.probe   = dm9000_probe,
-	.remove  = __devexit_p(dm9000_drv_remove),
-};
-
-static int __init
-dm9000_init(void)
-{
-	printk(KERN_INFO "%s Ethernet Driver, V%s\n", CARDNAME, DRV_VERSION);
-
-	return platform_driver_register(&dm9000_driver);
-}
-
-static void __exit
-dm9000_cleanup(void)
-{
-	platform_driver_unregister(&dm9000_driver);
-}
-
-module_init(dm9000_init);
-module_exit(dm9000_cleanup);
-
-MODULE_AUTHOR("Sascha Hauer, Ben Dooks");
-MODULE_DESCRIPTION("Davicom DM9000 network driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:dm9000");
diff -druN linux-libre-3.1-gnu/drivers/net/dm9000.h linux-libre-3.2-gnu/drivers/net/dm9000.h
--- linux-libre-3.1-gnu/drivers/net/dm9000.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/dm9000.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,171 +0,0 @@
-/*
- * dm9000 Ethernet
- */
-
-#ifndef _DM9000X_H_
-#define _DM9000X_H_
-
-#define DM9000_ID		0x90000A46
-
-/* although the registers are 16 bit, they are 32-bit aligned.
- */
-
-#define DM9000_NCR             0x00
-#define DM9000_NSR             0x01
-#define DM9000_TCR             0x02
-#define DM9000_TSR1            0x03
-#define DM9000_TSR2            0x04
-#define DM9000_RCR             0x05
-#define DM9000_RSR             0x06
-#define DM9000_ROCR            0x07
-#define DM9000_BPTR            0x08
-#define DM9000_FCTR            0x09
-#define DM9000_FCR             0x0A
-#define DM9000_EPCR            0x0B
-#define DM9000_EPAR            0x0C
-#define DM9000_EPDRL           0x0D
-#define DM9000_EPDRH           0x0E
-#define DM9000_WCR             0x0F
-
-#define DM9000_PAR             0x10
-#define DM9000_MAR             0x16
-
-#define DM9000_GPCR	       0x1e
-#define DM9000_GPR             0x1f
-#define DM9000_TRPAL           0x22
-#define DM9000_TRPAH           0x23
-#define DM9000_RWPAL           0x24
-#define DM9000_RWPAH           0x25
-
-#define DM9000_VIDL            0x28
-#define DM9000_VIDH            0x29
-#define DM9000_PIDL            0x2A
-#define DM9000_PIDH            0x2B
-
-#define DM9000_CHIPR           0x2C
-#define DM9000_SMCR            0x2F
-
-#define DM9000_ETXCSR          0x30
-#define DM9000_TCCR	       0x31
-#define DM9000_RCSR	       0x32
-
-#define CHIPR_DM9000A	       0x19
-#define CHIPR_DM9000B	       0x1A
-
-#define DM9000_MRCMDX          0xF0
-#define DM9000_MRCMD           0xF2
-#define DM9000_MRRL            0xF4
-#define DM9000_MRRH            0xF5
-#define DM9000_MWCMDX          0xF6
-#define DM9000_MWCMD           0xF8
-#define DM9000_MWRL            0xFA
-#define DM9000_MWRH            0xFB
-#define DM9000_TXPLL           0xFC
-#define DM9000_TXPLH           0xFD
-#define DM9000_ISR             0xFE
-#define DM9000_IMR             0xFF
-
-#define NCR_EXT_PHY         (1<<7)
-#define NCR_WAKEEN          (1<<6)
-#define NCR_FCOL            (1<<4)
-#define NCR_FDX             (1<<3)
-#define NCR_LBK             (3<<1)
-#define NCR_RST	            (1<<0)
-
-#define NSR_SPEED           (1<<7)
-#define NSR_LINKST          (1<<6)
-#define NSR_WAKEST          (1<<5)
-#define NSR_TX2END          (1<<3)
-#define NSR_TX1END          (1<<2)
-#define NSR_RXOV            (1<<1)
-
-#define TCR_TJDIS           (1<<6)
-#define TCR_EXCECM          (1<<5)
-#define TCR_PAD_DIS2        (1<<4)
-#define TCR_CRC_DIS2        (1<<3)
-#define TCR_PAD_DIS1        (1<<2)
-#define TCR_CRC_DIS1        (1<<1)
-#define TCR_TXREQ           (1<<0)
-
-#define TSR_TJTO            (1<<7)
-#define TSR_LC              (1<<6)
-#define TSR_NC              (1<<5)
-#define TSR_LCOL            (1<<4)
-#define TSR_COL             (1<<3)
-#define TSR_EC              (1<<2)
-
-#define RCR_WTDIS           (1<<6)
-#define RCR_DIS_LONG        (1<<5)
-#define RCR_DIS_CRC         (1<<4)
-#define RCR_ALL	            (1<<3)
-#define RCR_RUNT            (1<<2)
-#define RCR_PRMSC           (1<<1)
-#define RCR_RXEN            (1<<0)
-
-#define RSR_RF              (1<<7)
-#define RSR_MF              (1<<6)
-#define RSR_LCS             (1<<5)
-#define RSR_RWTO            (1<<4)
-#define RSR_PLE             (1<<3)
-#define RSR_AE              (1<<2)
-#define RSR_CE              (1<<1)
-#define RSR_FOE             (1<<0)
-
-#define WCR_LINKEN		(1 << 5)
-#define WCR_SAMPLEEN		(1 << 4)
-#define WCR_MAGICEN		(1 << 3)
-#define WCR_LINKST		(1 << 2)
-#define WCR_SAMPLEST		(1 << 1)
-#define WCR_MAGICST		(1 << 0)
-
-#define FCTR_HWOT(ot)	(( ot & 0xf ) << 4 )
-#define FCTR_LWOT(ot)	( ot & 0xf )
-
-#define IMR_PAR             (1<<7)
-#define IMR_ROOM            (1<<3)
-#define IMR_ROM             (1<<2)
-#define IMR_PTM             (1<<1)
-#define IMR_PRM             (1<<0)
-
-#define ISR_ROOS            (1<<3)
-#define ISR_ROS             (1<<2)
-#define ISR_PTS             (1<<1)
-#define ISR_PRS             (1<<0)
-#define ISR_CLR_STATUS      (ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS)
-
-#define EPCR_REEP           (1<<5)
-#define EPCR_WEP            (1<<4)
-#define EPCR_EPOS           (1<<3)
-#define EPCR_ERPRR          (1<<2)
-#define EPCR_ERPRW          (1<<1)
-#define EPCR_ERRE           (1<<0)
-
-#define GPCR_GEP_CNTL       (1<<0)
-
-#define TCCR_IP		    (1<<0)
-#define TCCR_TCP	    (1<<1)
-#define TCCR_UDP	    (1<<2)
-
-#define RCSR_UDP_BAD	    (1<<7)
-#define RCSR_TCP_BAD	    (1<<6)
-#define RCSR_IP_BAD	    (1<<5)
-#define RCSR_UDP	    (1<<4)
-#define RCSR_TCP	    (1<<3)
-#define RCSR_IP		    (1<<2)
-#define RCSR_CSUM	    (1<<1)
-#define RCSR_DISCARD	    (1<<0)
-
-#define DM9000_PKT_RDY		0x01	/* Packet ready to receive */
-#define DM9000_PKT_ERR		0x02
-#define DM9000_PKT_MAX		1536	/* Received packet max size */
-
-/* DM9000A / DM9000B definitions */
-
-#define IMR_LNKCHNG		(1<<5)
-#define IMR_UNDERRUN		(1<<4)
-
-#define ISR_LNKCHNG		(1<<5)
-#define ISR_UNDERRUN		(1<<4)
-
-#endif /* _DM9000X_H_ */
-
diff -druN linux-libre-3.1-gnu/drivers/net/dnet.c linux-libre-3.2-gnu/drivers/net/dnet.c
--- linux-libre-3.1-gnu/drivers/net/dnet.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/dnet.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,996 +0,0 @@
-/*
- * Dave DNET Ethernet Controller driver
- *
- * Copyright (C) 2008 Dave S.r.l. <www.dave.eu>
- * Copyright (C) 2009 Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.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/io.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/phy.h>
-
-#include "dnet.h"
-
-#undef DEBUG
-
-/* function for reading internal MAC register */
-static u16 dnet_readw_mac(struct dnet *bp, u16 reg)
-{
-	u16 data_read;
-
-	/* issue a read */
-	dnet_writel(bp, reg, MACREG_ADDR);
-
-	/* since a read/write op to the MAC is very slow,
-	 * we must wait before reading the data */
-	ndelay(500);
-
-	/* read data read from the MAC register */
-	data_read = dnet_readl(bp, MACREG_DATA);
-
-	/* all done */
-	return data_read;
-}
-
-/* function for writing internal MAC register */
-static void dnet_writew_mac(struct dnet *bp, u16 reg, u16 val)
-{
-	/* load data to write */
-	dnet_writel(bp, val, MACREG_DATA);
-
-	/* issue a write */
-	dnet_writel(bp, reg | DNET_INTERNAL_WRITE, MACREG_ADDR);
-
-	/* since a read/write op to the MAC is very slow,
-	 * we must wait before exiting */
-	ndelay(500);
-}
-
-static void __dnet_set_hwaddr(struct dnet *bp)
-{
-	u16 tmp;
-
-	tmp = be16_to_cpup((__be16 *)bp->dev->dev_addr);
-	dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG, tmp);
-	tmp = be16_to_cpup((__be16 *)(bp->dev->dev_addr + 2));
-	dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG, tmp);
-	tmp = be16_to_cpup((__be16 *)(bp->dev->dev_addr + 4));
-	dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG, tmp);
-}
-
-static void __devinit dnet_get_hwaddr(struct dnet *bp)
-{
-	u16 tmp;
-	u8 addr[6];
-
-	/*
-	 * from MAC docs:
-	 * "Note that the MAC address is stored in the registers in Hexadecimal
-	 * form. For example, to set the MAC Address to: AC-DE-48-00-00-80
-	 * would require writing 0xAC (octet 0) to address 0x0B (high byte of
-	 * Mac_addr[15:0]), 0xDE (octet 1) to address 0x0A (Low byte of
-	 * Mac_addr[15:0]), 0x48 (octet 2) to address 0x0D (high byte of
-	 * Mac_addr[15:0]), 0x00 (octet 3) to address 0x0C (Low byte of
-	 * Mac_addr[15:0]), 0x00 (octet 4) to address 0x0F (high byte of
-	 * Mac_addr[15:0]), and 0x80 (octet 5) to address * 0x0E (Low byte of
-	 * Mac_addr[15:0]).
-	 */
-	tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG);
-	*((__be16 *)addr) = cpu_to_be16(tmp);
-	tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG);
-	*((__be16 *)(addr + 2)) = cpu_to_be16(tmp);
-	tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG);
-	*((__be16 *)(addr + 4)) = cpu_to_be16(tmp);
-
-	if (is_valid_ether_addr(addr))
-		memcpy(bp->dev->dev_addr, addr, sizeof(addr));
-}
-
-static int dnet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
-{
-	struct dnet *bp = bus->priv;
-	u16 value;
-
-	while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG)
-				& DNET_INTERNAL_GMII_MNG_CMD_FIN))
-		cpu_relax();
-
-	/* only 5 bits allowed for phy-addr and reg_offset */
-	mii_id &= 0x1f;
-	regnum &= 0x1f;
-
-	/* prepare reg_value for a read */
-	value = (mii_id << 8);
-	value |= regnum;
-
-	/* write control word */
-	dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG, value);
-
-	/* wait for end of transfer */
-	while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG)
-				& DNET_INTERNAL_GMII_MNG_CMD_FIN))
-		cpu_relax();
-
-	value = dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_DAT_REG);
-
-	pr_debug("mdio_read %02x:%02x <- %04x\n", mii_id, regnum, value);
-
-	return value;
-}
-
-static int dnet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
-			   u16 value)
-{
-	struct dnet *bp = bus->priv;
-	u16 tmp;
-
-	pr_debug("mdio_write %02x:%02x <- %04x\n", mii_id, regnum, value);
-
-	while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG)
-				& DNET_INTERNAL_GMII_MNG_CMD_FIN))
-		cpu_relax();
-
-	/* prepare for a write operation */
-	tmp = (1 << 13);
-
-	/* only 5 bits allowed for phy-addr and reg_offset */
-	mii_id &= 0x1f;
-	regnum &= 0x1f;
-
-	/* only 16 bits on data */
-	value &= 0xffff;
-
-	/* prepare reg_value for a write */
-	tmp |= (mii_id << 8);
-	tmp |= regnum;
-
-	/* write data to write first */
-	dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_DAT_REG, value);
-
-	/* write control word */
-	dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG, tmp);
-
-	while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG)
-				& DNET_INTERNAL_GMII_MNG_CMD_FIN))
-		cpu_relax();
-
-	return 0;
-}
-
-static int dnet_mdio_reset(struct mii_bus *bus)
-{
-	return 0;
-}
-
-static void dnet_handle_link_change(struct net_device *dev)
-{
-	struct dnet *bp = netdev_priv(dev);
-	struct phy_device *phydev = bp->phy_dev;
-	unsigned long flags;
-	u32 mode_reg, ctl_reg;
-
-	int status_change = 0;
-
-	spin_lock_irqsave(&bp->lock, flags);
-
-	mode_reg = dnet_readw_mac(bp, DNET_INTERNAL_MODE_REG);
-	ctl_reg = dnet_readw_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG);
-
-	if (phydev->link) {
-		if (bp->duplex != phydev->duplex) {
-			if (phydev->duplex)
-				ctl_reg &=
-				    ~(DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP);
-			else
-				ctl_reg |=
-				    DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP;
-
-			bp->duplex = phydev->duplex;
-			status_change = 1;
-		}
-
-		if (bp->speed != phydev->speed) {
-			status_change = 1;
-			switch (phydev->speed) {
-			case 1000:
-				mode_reg |= DNET_INTERNAL_MODE_GBITEN;
-				break;
-			case 100:
-			case 10:
-				mode_reg &= ~DNET_INTERNAL_MODE_GBITEN;
-				break;
-			default:
-				printk(KERN_WARNING
-				       "%s: Ack!  Speed (%d) is not "
-				       "10/100/1000!\n", dev->name,
-				       phydev->speed);
-				break;
-			}
-			bp->speed = phydev->speed;
-		}
-	}
-
-	if (phydev->link != bp->link) {
-		if (phydev->link) {
-			mode_reg |=
-			    (DNET_INTERNAL_MODE_RXEN | DNET_INTERNAL_MODE_TXEN);
-		} else {
-			mode_reg &=
-			    ~(DNET_INTERNAL_MODE_RXEN |
-			      DNET_INTERNAL_MODE_TXEN);
-			bp->speed = 0;
-			bp->duplex = -1;
-		}
-		bp->link = phydev->link;
-
-		status_change = 1;
-	}
-
-	if (status_change) {
-		dnet_writew_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG, ctl_reg);
-		dnet_writew_mac(bp, DNET_INTERNAL_MODE_REG, mode_reg);
-	}
-
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	if (status_change) {
-		if (phydev->link)
-			printk(KERN_INFO "%s: link up (%d/%s)\n",
-			       dev->name, phydev->speed,
-			       DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
-		else
-			printk(KERN_INFO "%s: link down\n", dev->name);
-	}
-}
-
-static int dnet_mii_probe(struct net_device *dev)
-{
-	struct dnet *bp = netdev_priv(dev);
-	struct phy_device *phydev = NULL;
-	int phy_addr;
-
-	/* find the first phy */
-	for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
-		if (bp->mii_bus->phy_map[phy_addr]) {
-			phydev = bp->mii_bus->phy_map[phy_addr];
-			break;
-		}
-	}
-
-	if (!phydev) {
-		printk(KERN_ERR "%s: no PHY found\n", dev->name);
-		return -ENODEV;
-	}
-
-	/* TODO : add pin_irq */
-
-	/* attach the mac to the phy */
-	if (bp->capabilities & DNET_HAS_RMII) {
-		phydev = phy_connect(dev, dev_name(&phydev->dev),
-				     &dnet_handle_link_change, 0,
-				     PHY_INTERFACE_MODE_RMII);
-	} else {
-		phydev = phy_connect(dev, dev_name(&phydev->dev),
-				     &dnet_handle_link_change, 0,
-				     PHY_INTERFACE_MODE_MII);
-	}
-
-	if (IS_ERR(phydev)) {
-		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
-		return PTR_ERR(phydev);
-	}
-
-	/* mask with MAC supported features */
-	if (bp->capabilities & DNET_HAS_GIGABIT)
-		phydev->supported &= PHY_GBIT_FEATURES;
-	else
-		phydev->supported &= PHY_BASIC_FEATURES;
-
-	phydev->supported |= SUPPORTED_Asym_Pause | SUPPORTED_Pause;
-
-	phydev->advertising = phydev->supported;
-
-	bp->link = 0;
-	bp->speed = 0;
-	bp->duplex = -1;
-	bp->phy_dev = phydev;
-
-	return 0;
-}
-
-static int dnet_mii_init(struct dnet *bp)
-{
-	int err, i;
-
-	bp->mii_bus = mdiobus_alloc();
-	if (bp->mii_bus == NULL)
-		return -ENOMEM;
-
-	bp->mii_bus->name = "dnet_mii_bus";
-	bp->mii_bus->read = &dnet_mdio_read;
-	bp->mii_bus->write = &dnet_mdio_write;
-	bp->mii_bus->reset = &dnet_mdio_reset;
-
-	snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
-
-	bp->mii_bus->priv = bp;
-
-	bp->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
-	if (!bp->mii_bus->irq) {
-		err = -ENOMEM;
-		goto err_out;
-	}
-
-	for (i = 0; i < PHY_MAX_ADDR; i++)
-		bp->mii_bus->irq[i] = PHY_POLL;
-
-	if (mdiobus_register(bp->mii_bus)) {
-		err = -ENXIO;
-		goto err_out_free_mdio_irq;
-	}
-
-	if (dnet_mii_probe(bp->dev) != 0) {
-		err = -ENXIO;
-		goto err_out_unregister_bus;
-	}
-
-	return 0;
-
-err_out_unregister_bus:
-	mdiobus_unregister(bp->mii_bus);
-err_out_free_mdio_irq:
-	kfree(bp->mii_bus->irq);
-err_out:
-	mdiobus_free(bp->mii_bus);
-	return err;
-}
-
-/* For Neptune board: LINK1000 as Link LED and TX as activity LED */
-static int dnet_phy_marvell_fixup(struct phy_device *phydev)
-{
-	return phy_write(phydev, 0x18, 0x4148);
-}
-
-static void dnet_update_stats(struct dnet *bp)
-{
-	u32 __iomem *reg = bp->regs + DNET_RX_PKT_IGNR_CNT;
-	u32 *p = &bp->hw_stats.rx_pkt_ignr;
-	u32 *end = &bp->hw_stats.rx_byte + 1;
-
-	WARN_ON((unsigned long)(end - p - 1) !=
-		(DNET_RX_BYTE_CNT - DNET_RX_PKT_IGNR_CNT) / 4);
-
-	for (; p < end; p++, reg++)
-		*p += readl(reg);
-
-	reg = bp->regs + DNET_TX_UNICAST_CNT;
-	p = &bp->hw_stats.tx_unicast;
-	end = &bp->hw_stats.tx_byte + 1;
-
-	WARN_ON((unsigned long)(end - p - 1) !=
-		(DNET_TX_BYTE_CNT - DNET_TX_UNICAST_CNT) / 4);
-
-	for (; p < end; p++, reg++)
-		*p += readl(reg);
-}
-
-static int dnet_poll(struct napi_struct *napi, int budget)
-{
-	struct dnet *bp = container_of(napi, struct dnet, napi);
-	struct net_device *dev = bp->dev;
-	int npackets = 0;
-	unsigned int pkt_len;
-	struct sk_buff *skb;
-	unsigned int *data_ptr;
-	u32 int_enable;
-	u32 cmd_word;
-	int i;
-
-	while (npackets < budget) {
-		/*
-		 * break out of while loop if there are no more
-		 * packets waiting
-		 */
-		if (!(dnet_readl(bp, RX_FIFO_WCNT) >> 16)) {
-			napi_complete(napi);
-			int_enable = dnet_readl(bp, INTR_ENB);
-			int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF;
-			dnet_writel(bp, int_enable, INTR_ENB);
-			return 0;
-		}
-
-		cmd_word = dnet_readl(bp, RX_LEN_FIFO);
-		pkt_len = cmd_word & 0xFFFF;
-
-		if (cmd_word & 0xDF180000)
-			printk(KERN_ERR "%s packet receive error %x\n",
-			       __func__, cmd_word);
-
-		skb = dev_alloc_skb(pkt_len + 5);
-		if (skb != NULL) {
-			/* Align IP on 16 byte boundaries */
-			skb_reserve(skb, 2);
-			/*
-			 * 'skb_put()' points to the start of sk_buff
-			 * data area.
-			 */
-			data_ptr = (unsigned int *)skb_put(skb, pkt_len);
-			for (i = 0; i < (pkt_len + 3) >> 2; i++)
-				*data_ptr++ = dnet_readl(bp, RX_DATA_FIFO);
-			skb->protocol = eth_type_trans(skb, dev);
-			netif_receive_skb(skb);
-			npackets++;
-		} else
-			printk(KERN_NOTICE
-			       "%s: No memory to allocate a sk_buff of "
-			       "size %u.\n", dev->name, pkt_len);
-	}
-
-	budget -= npackets;
-
-	if (npackets < budget) {
-		/* We processed all packets available.  Tell NAPI it can
-		 * stop polling then re-enable rx interrupts */
-		napi_complete(napi);
-		int_enable = dnet_readl(bp, INTR_ENB);
-		int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF;
-		dnet_writel(bp, int_enable, INTR_ENB);
-		return 0;
-	}
-
-	/* There are still packets waiting */
-	return 1;
-}
-
-static irqreturn_t dnet_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct dnet *bp = netdev_priv(dev);
-	u32 int_src, int_enable, int_current;
-	unsigned long flags;
-	unsigned int handled = 0;
-
-	spin_lock_irqsave(&bp->lock, flags);
-
-	/* read and clear the DNET irq (clear on read) */
-	int_src = dnet_readl(bp, INTR_SRC);
-	int_enable = dnet_readl(bp, INTR_ENB);
-	int_current = int_src & int_enable;
-
-	/* restart the queue if we had stopped it for TX fifo almost full */
-	if (int_current & DNET_INTR_SRC_TX_FIFOAE) {
-		int_enable = dnet_readl(bp, INTR_ENB);
-		int_enable &= ~DNET_INTR_ENB_TX_FIFOAE;
-		dnet_writel(bp, int_enable, INTR_ENB);
-		netif_wake_queue(dev);
-		handled = 1;
-	}
-
-	/* RX FIFO error checking */
-	if (int_current &
-	    (DNET_INTR_SRC_RX_CMDFIFOFF | DNET_INTR_SRC_RX_DATAFIFOFF)) {
-		printk(KERN_ERR "%s: RX fifo error %x, irq %x\n", __func__,
-		       dnet_readl(bp, RX_STATUS), int_current);
-		/* we can only flush the RX FIFOs */
-		dnet_writel(bp, DNET_SYS_CTL_RXFIFOFLUSH, SYS_CTL);
-		ndelay(500);
-		dnet_writel(bp, 0, SYS_CTL);
-		handled = 1;
-	}
-
-	/* TX FIFO error checking */
-	if (int_current &
-	    (DNET_INTR_SRC_TX_FIFOFULL | DNET_INTR_SRC_TX_DISCFRM)) {
-		printk(KERN_ERR "%s: TX fifo error %x, irq %x\n", __func__,
-		       dnet_readl(bp, TX_STATUS), int_current);
-		/* we can only flush the TX FIFOs */
-		dnet_writel(bp, DNET_SYS_CTL_TXFIFOFLUSH, SYS_CTL);
-		ndelay(500);
-		dnet_writel(bp, 0, SYS_CTL);
-		handled = 1;
-	}
-
-	if (int_current & DNET_INTR_SRC_RX_CMDFIFOAF) {
-		if (napi_schedule_prep(&bp->napi)) {
-			/*
-			 * There's no point taking any more interrupts
-			 * until we have processed the buffers
-			 */
-			/* Disable Rx interrupts and schedule NAPI poll */
-			int_enable = dnet_readl(bp, INTR_ENB);
-			int_enable &= ~DNET_INTR_SRC_RX_CMDFIFOAF;
-			dnet_writel(bp, int_enable, INTR_ENB);
-			__napi_schedule(&bp->napi);
-		}
-		handled = 1;
-	}
-
-	if (!handled)
-		pr_debug("%s: irq %x remains\n", __func__, int_current);
-
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	return IRQ_RETVAL(handled);
-}
-
-#ifdef DEBUG
-static inline void dnet_print_skb(struct sk_buff *skb)
-{
-	int k;
-	printk(KERN_DEBUG PFX "data:");
-	for (k = 0; k < skb->len; k++)
-		printk(" %02x", (unsigned int)skb->data[k]);
-	printk("\n");
-}
-#else
-#define dnet_print_skb(skb)	do {} while (0)
-#endif
-
-static netdev_tx_t dnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-
-	struct dnet *bp = netdev_priv(dev);
-	u32 tx_status, irq_enable;
-	unsigned int len, i, tx_cmd, wrsz;
-	unsigned long flags;
-	unsigned int *bufp;
-
-	tx_status = dnet_readl(bp, TX_STATUS);
-
-	pr_debug("start_xmit: len %u head %p data %p\n",
-	       skb->len, skb->head, skb->data);
-	dnet_print_skb(skb);
-
-	/* frame size (words) */
-	len = (skb->len + 3) >> 2;
-
-	spin_lock_irqsave(&bp->lock, flags);
-
-	tx_status = dnet_readl(bp, TX_STATUS);
-
-	bufp = (unsigned int *)(((unsigned long) skb->data) & ~0x3UL);
-	wrsz = (u32) skb->len + 3;
-	wrsz += ((unsigned long) skb->data) & 0x3;
-	wrsz >>= 2;
-	tx_cmd = ((((unsigned long)(skb->data)) & 0x03) << 16) | (u32) skb->len;
-
-	/* check if there is enough room for the current frame */
-	if (wrsz < (DNET_FIFO_SIZE - dnet_readl(bp, TX_FIFO_WCNT))) {
-		for (i = 0; i < wrsz; i++)
-			dnet_writel(bp, *bufp++, TX_DATA_FIFO);
-
-		/*
-		 * inform MAC that a packet's written and ready to be
-		 * shipped out
-		 */
-		dnet_writel(bp, tx_cmd, TX_LEN_FIFO);
-	}
-
-	if (dnet_readl(bp, TX_FIFO_WCNT) > DNET_FIFO_TX_DATA_AF_TH) {
-		netif_stop_queue(dev);
-		tx_status = dnet_readl(bp, INTR_SRC);
-		irq_enable = dnet_readl(bp, INTR_ENB);
-		irq_enable |= DNET_INTR_ENB_TX_FIFOAE;
-		dnet_writel(bp, irq_enable, INTR_ENB);
-	}
-
-	skb_tx_timestamp(skb);
-
-	/* free the buffer */
-	dev_kfree_skb(skb);
-
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	return NETDEV_TX_OK;
-}
-
-static void dnet_reset_hw(struct dnet *bp)
-{
-	/* put ts_mac in IDLE state i.e. disable rx/tx */
-	dnet_writew_mac(bp, DNET_INTERNAL_MODE_REG, DNET_INTERNAL_MODE_FCEN);
-
-	/*
-	 * RX FIFO almost full threshold: only cmd FIFO almost full is
-	 * implemented for RX side
-	 */
-	dnet_writel(bp, DNET_FIFO_RX_CMD_AF_TH, RX_FIFO_TH);
-	/*
-	 * TX FIFO almost empty threshold: only data FIFO almost empty
-	 * is implemented for TX side
-	 */
-	dnet_writel(bp, DNET_FIFO_TX_DATA_AE_TH, TX_FIFO_TH);
-
-	/* flush rx/tx fifos */
-	dnet_writel(bp, DNET_SYS_CTL_RXFIFOFLUSH | DNET_SYS_CTL_TXFIFOFLUSH,
-			SYS_CTL);
-	msleep(1);
-	dnet_writel(bp, 0, SYS_CTL);
-}
-
-static void dnet_init_hw(struct dnet *bp)
-{
-	u32 config;
-
-	dnet_reset_hw(bp);
-	__dnet_set_hwaddr(bp);
-
-	config = dnet_readw_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG);
-
-	if (bp->dev->flags & IFF_PROMISC)
-		/* Copy All Frames */
-		config |= DNET_INTERNAL_RXTX_CONTROL_ENPROMISC;
-	if (!(bp->dev->flags & IFF_BROADCAST))
-		/* No BroadCast */
-		config |= DNET_INTERNAL_RXTX_CONTROL_RXMULTICAST;
-
-	config |= DNET_INTERNAL_RXTX_CONTROL_RXPAUSE |
-	    DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST |
-	    DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL |
-	    DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS;
-
-	dnet_writew_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG, config);
-
-	/* clear irq before enabling them */
-	config = dnet_readl(bp, INTR_SRC);
-
-	/* enable RX/TX interrupt, recv packet ready interrupt */
-	dnet_writel(bp, DNET_INTR_ENB_GLOBAL_ENABLE | DNET_INTR_ENB_RX_SUMMARY |
-			DNET_INTR_ENB_TX_SUMMARY | DNET_INTR_ENB_RX_FIFOERR |
-			DNET_INTR_ENB_RX_ERROR | DNET_INTR_ENB_RX_FIFOFULL |
-			DNET_INTR_ENB_TX_FIFOFULL | DNET_INTR_ENB_TX_DISCFRM |
-			DNET_INTR_ENB_RX_PKTRDY, INTR_ENB);
-}
-
-static int dnet_open(struct net_device *dev)
-{
-	struct dnet *bp = netdev_priv(dev);
-
-	/* if the phy is not yet register, retry later */
-	if (!bp->phy_dev)
-		return -EAGAIN;
-
-	if (!is_valid_ether_addr(dev->dev_addr))
-		return -EADDRNOTAVAIL;
-
-	napi_enable(&bp->napi);
-	dnet_init_hw(bp);
-
-	phy_start_aneg(bp->phy_dev);
-
-	/* schedule a link state check */
-	phy_start(bp->phy_dev);
-
-	netif_start_queue(dev);
-
-	return 0;
-}
-
-static int dnet_close(struct net_device *dev)
-{
-	struct dnet *bp = netdev_priv(dev);
-
-	netif_stop_queue(dev);
-	napi_disable(&bp->napi);
-
-	if (bp->phy_dev)
-		phy_stop(bp->phy_dev);
-
-	dnet_reset_hw(bp);
-	netif_carrier_off(dev);
-
-	return 0;
-}
-
-static inline void dnet_print_pretty_hwstats(struct dnet_stats *hwstat)
-{
-	pr_debug("%s\n", __func__);
-	pr_debug("----------------------------- RX statistics "
-		 "-------------------------------\n");
-	pr_debug("RX_PKT_IGNR_CNT %-8x\n", hwstat->rx_pkt_ignr);
-	pr_debug("RX_LEN_CHK_ERR_CNT %-8x\n", hwstat->rx_len_chk_err);
-	pr_debug("RX_LNG_FRM_CNT %-8x\n", hwstat->rx_lng_frm);
-	pr_debug("RX_SHRT_FRM_CNT %-8x\n", hwstat->rx_shrt_frm);
-	pr_debug("RX_IPG_VIOL_CNT %-8x\n", hwstat->rx_ipg_viol);
-	pr_debug("RX_CRC_ERR_CNT %-8x\n", hwstat->rx_crc_err);
-	pr_debug("RX_OK_PKT_CNT %-8x\n", hwstat->rx_ok_pkt);
-	pr_debug("RX_CTL_FRM_CNT %-8x\n", hwstat->rx_ctl_frm);
-	pr_debug("RX_PAUSE_FRM_CNT %-8x\n", hwstat->rx_pause_frm);
-	pr_debug("RX_MULTICAST_CNT %-8x\n", hwstat->rx_multicast);
-	pr_debug("RX_BROADCAST_CNT %-8x\n", hwstat->rx_broadcast);
-	pr_debug("RX_VLAN_TAG_CNT %-8x\n", hwstat->rx_vlan_tag);
-	pr_debug("RX_PRE_SHRINK_CNT %-8x\n", hwstat->rx_pre_shrink);
-	pr_debug("RX_DRIB_NIB_CNT %-8x\n", hwstat->rx_drib_nib);
-	pr_debug("RX_UNSUP_OPCD_CNT %-8x\n", hwstat->rx_unsup_opcd);
-	pr_debug("RX_BYTE_CNT %-8x\n", hwstat->rx_byte);
-	pr_debug("----------------------------- TX statistics "
-		 "-------------------------------\n");
-	pr_debug("TX_UNICAST_CNT %-8x\n", hwstat->tx_unicast);
-	pr_debug("TX_PAUSE_FRM_CNT %-8x\n", hwstat->tx_pause_frm);
-	pr_debug("TX_MULTICAST_CNT %-8x\n", hwstat->tx_multicast);
-	pr_debug("TX_BRDCAST_CNT %-8x\n", hwstat->tx_brdcast);
-	pr_debug("TX_VLAN_TAG_CNT %-8x\n", hwstat->tx_vlan_tag);
-	pr_debug("TX_BAD_FCS_CNT %-8x\n", hwstat->tx_bad_fcs);
-	pr_debug("TX_JUMBO_CNT %-8x\n", hwstat->tx_jumbo);
-	pr_debug("TX_BYTE_CNT %-8x\n", hwstat->tx_byte);
-}
-
-static struct net_device_stats *dnet_get_stats(struct net_device *dev)
-{
-
-	struct dnet *bp = netdev_priv(dev);
-	struct net_device_stats *nstat = &dev->stats;
-	struct dnet_stats *hwstat = &bp->hw_stats;
-
-	/* read stats from hardware */
-	dnet_update_stats(bp);
-
-	/* Convert HW stats into netdevice stats */
-	nstat->rx_errors = (hwstat->rx_len_chk_err +
-			    hwstat->rx_lng_frm + hwstat->rx_shrt_frm +
-			    /* ignore IGP violation error
-			    hwstat->rx_ipg_viol + */
-			    hwstat->rx_crc_err +
-			    hwstat->rx_pre_shrink +
-			    hwstat->rx_drib_nib + hwstat->rx_unsup_opcd);
-	nstat->tx_errors = hwstat->tx_bad_fcs;
-	nstat->rx_length_errors = (hwstat->rx_len_chk_err +
-				   hwstat->rx_lng_frm +
-				   hwstat->rx_shrt_frm + hwstat->rx_pre_shrink);
-	nstat->rx_crc_errors = hwstat->rx_crc_err;
-	nstat->rx_frame_errors = hwstat->rx_pre_shrink + hwstat->rx_drib_nib;
-	nstat->rx_packets = hwstat->rx_ok_pkt;
-	nstat->tx_packets = (hwstat->tx_unicast +
-			     hwstat->tx_multicast + hwstat->tx_brdcast);
-	nstat->rx_bytes = hwstat->rx_byte;
-	nstat->tx_bytes = hwstat->tx_byte;
-	nstat->multicast = hwstat->rx_multicast;
-	nstat->rx_missed_errors = hwstat->rx_pkt_ignr;
-
-	dnet_print_pretty_hwstats(hwstat);
-
-	return nstat;
-}
-
-static int dnet_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct dnet *bp = netdev_priv(dev);
-	struct phy_device *phydev = bp->phy_dev;
-
-	if (!phydev)
-		return -ENODEV;
-
-	return phy_ethtool_gset(phydev, cmd);
-}
-
-static int dnet_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct dnet *bp = netdev_priv(dev);
-	struct phy_device *phydev = bp->phy_dev;
-
-	if (!phydev)
-		return -ENODEV;
-
-	return phy_ethtool_sset(phydev, cmd);
-}
-
-static int dnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct dnet *bp = netdev_priv(dev);
-	struct phy_device *phydev = bp->phy_dev;
-
-	if (!netif_running(dev))
-		return -EINVAL;
-
-	if (!phydev)
-		return -ENODEV;
-
-	return phy_mii_ioctl(phydev, rq, cmd);
-}
-
-static void dnet_get_drvinfo(struct net_device *dev,
-			     struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-	strcpy(info->bus_info, "0");
-}
-
-static const struct ethtool_ops dnet_ethtool_ops = {
-	.get_settings		= dnet_get_settings,
-	.set_settings		= dnet_set_settings,
-	.get_drvinfo		= dnet_get_drvinfo,
-	.get_link		= ethtool_op_get_link,
-};
-
-static const struct net_device_ops dnet_netdev_ops = {
-	.ndo_open		= dnet_open,
-	.ndo_stop		= dnet_close,
-	.ndo_get_stats		= dnet_get_stats,
-	.ndo_start_xmit		= dnet_start_xmit,
-	.ndo_do_ioctl		= dnet_ioctl,
-	.ndo_set_mac_address	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
-};
-
-static int __devinit dnet_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	struct net_device *dev;
-	struct dnet *bp;
-	struct phy_device *phydev;
-	int err = -ENXIO;
-	unsigned int mem_base, mem_size, irq;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "no mmio resource defined\n");
-		goto err_out;
-	}
-	mem_base = res->start;
-	mem_size = resource_size(res);
-	irq = platform_get_irq(pdev, 0);
-
-	if (!request_mem_region(mem_base, mem_size, DRV_NAME)) {
-		dev_err(&pdev->dev, "no memory region available\n");
-		err = -EBUSY;
-		goto err_out;
-	}
-
-	err = -ENOMEM;
-	dev = alloc_etherdev(sizeof(*bp));
-	if (!dev) {
-		dev_err(&pdev->dev, "etherdev alloc failed, aborting.\n");
-		goto err_out_release_mem;
-	}
-
-	/* TODO: Actually, we have some interesting features... */
-	dev->features |= 0;
-
-	bp = netdev_priv(dev);
-	bp->dev = dev;
-
-	platform_set_drvdata(pdev, dev);
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-	spin_lock_init(&bp->lock);
-
-	bp->regs = ioremap(mem_base, mem_size);
-	if (!bp->regs) {
-		dev_err(&pdev->dev, "failed to map registers, aborting.\n");
-		err = -ENOMEM;
-		goto err_out_free_dev;
-	}
-
-	dev->irq = irq;
-	err = request_irq(dev->irq, dnet_interrupt, 0, DRV_NAME, dev);
-	if (err) {
-		dev_err(&pdev->dev, "Unable to request IRQ %d (error %d)\n",
-		       irq, err);
-		goto err_out_iounmap;
-	}
-
-	dev->netdev_ops = &dnet_netdev_ops;
-	netif_napi_add(dev, &bp->napi, dnet_poll, 64);
-	dev->ethtool_ops = &dnet_ethtool_ops;
-
-	dev->base_addr = (unsigned long)bp->regs;
-
-	bp->capabilities = dnet_readl(bp, VERCAPS) & DNET_CAPS_MASK;
-
-	dnet_get_hwaddr(bp);
-
-	if (!is_valid_ether_addr(dev->dev_addr)) {
-		/* choose a random ethernet address */
-		random_ether_addr(dev->dev_addr);
-		__dnet_set_hwaddr(bp);
-	}
-
-	err = register_netdev(dev);
-	if (err) {
-		dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
-		goto err_out_free_irq;
-	}
-
-	/* register the PHY board fixup (for Marvell 88E1111) */
-	err = phy_register_fixup_for_uid(0x01410cc0, 0xfffffff0,
-					 dnet_phy_marvell_fixup);
-	/* we can live without it, so just issue a warning */
-	if (err)
-		dev_warn(&pdev->dev, "Cannot register PHY board fixup.\n");
-
-	err = dnet_mii_init(bp);
-	if (err)
-		goto err_out_unregister_netdev;
-
-	dev_info(&pdev->dev, "Dave DNET at 0x%p (0x%08x) irq %d %pM\n",
-	       bp->regs, mem_base, dev->irq, dev->dev_addr);
-	dev_info(&pdev->dev, "has %smdio, %sirq, %sgigabit, %sdma\n",
-	       (bp->capabilities & DNET_HAS_MDIO) ? "" : "no ",
-	       (bp->capabilities & DNET_HAS_IRQ) ? "" : "no ",
-	       (bp->capabilities & DNET_HAS_GIGABIT) ? "" : "no ",
-	       (bp->capabilities & DNET_HAS_DMA) ? "" : "no ");
-	phydev = bp->phy_dev;
-	dev_info(&pdev->dev, "attached PHY driver [%s] "
-	       "(mii_bus:phy_addr=%s, irq=%d)\n",
-	       phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
-
-	return 0;
-
-err_out_unregister_netdev:
-	unregister_netdev(dev);
-err_out_free_irq:
-	free_irq(dev->irq, dev);
-err_out_iounmap:
-	iounmap(bp->regs);
-err_out_free_dev:
-	free_netdev(dev);
-err_out_release_mem:
-	release_mem_region(mem_base, mem_size);
-err_out:
-	return err;
-}
-
-static int __devexit dnet_remove(struct platform_device *pdev)
-{
-
-	struct net_device *dev;
-	struct dnet *bp;
-
-	dev = platform_get_drvdata(pdev);
-
-	if (dev) {
-		bp = netdev_priv(dev);
-		if (bp->phy_dev)
-			phy_disconnect(bp->phy_dev);
-		mdiobus_unregister(bp->mii_bus);
-		kfree(bp->mii_bus->irq);
-		mdiobus_free(bp->mii_bus);
-		unregister_netdev(dev);
-		free_irq(dev->irq, dev);
-		iounmap(bp->regs);
-		free_netdev(dev);
-	}
-
-	return 0;
-}
-
-static struct platform_driver dnet_driver = {
-	.probe		= dnet_probe,
-	.remove		= __devexit_p(dnet_remove),
-	.driver		= {
-		.name		= "dnet",
-	},
-};
-
-static int __init dnet_init(void)
-{
-	return platform_driver_register(&dnet_driver);
-}
-
-static void __exit dnet_exit(void)
-{
-	platform_driver_unregister(&dnet_driver);
-}
-
-module_init(dnet_init);
-module_exit(dnet_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Dave DNET Ethernet driver");
-MODULE_AUTHOR("Ilya Yanok <yanok@emcraft.com>, "
-	      "Matteo Vit <matteo.vit@dave.eu>");
diff -druN linux-libre-3.1-gnu/drivers/net/dnet.h linux-libre-3.2-gnu/drivers/net/dnet.h
--- linux-libre-3.1-gnu/drivers/net/dnet.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/dnet.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,225 +0,0 @@
-/*
- * Dave DNET Ethernet Controller driver
- *
- * Copyright (C) 2008 Dave S.r.l. <www.dave.eu>
- *
- * This program is free software; you can 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 _DNET_H
-#define _DNET_H
-
-#define DRV_NAME		"dnet"
-#define DRV_VERSION		"0.9.1"
-#define PFX				DRV_NAME ": "
-
-/* Register access macros */
-#define dnet_writel(port, value, reg)	\
-	writel((value), (port)->regs + DNET_##reg)
-#define dnet_readl(port, reg)	readl((port)->regs + DNET_##reg)
-
-/* ALL DNET FIFO REGISTERS */
-#define DNET_RX_LEN_FIFO		0x000	/* RX_LEN_FIFO */
-#define DNET_RX_DATA_FIFO		0x004	/* RX_DATA_FIFO */
-#define DNET_TX_LEN_FIFO		0x008	/* TX_LEN_FIFO */
-#define DNET_TX_DATA_FIFO		0x00C	/* TX_DATA_FIFO */
-
-/* ALL DNET CONTROL/STATUS REGISTERS OFFSETS */
-#define DNET_VERCAPS			0x100	/* VERCAPS */
-#define DNET_INTR_SRC			0x104	/* INTR_SRC */
-#define DNET_INTR_ENB			0x108	/* INTR_ENB */
-#define DNET_RX_STATUS			0x10C	/* RX_STATUS */
-#define DNET_TX_STATUS			0x110	/* TX_STATUS */
-#define DNET_RX_FRAMES_CNT		0x114	/* RX_FRAMES_CNT */
-#define DNET_TX_FRAMES_CNT		0x118	/* TX_FRAMES_CNT */
-#define DNET_RX_FIFO_TH			0x11C	/* RX_FIFO_TH */
-#define DNET_TX_FIFO_TH			0x120	/* TX_FIFO_TH */
-#define DNET_SYS_CTL			0x124	/* SYS_CTL */
-#define DNET_PAUSE_TMR			0x128	/* PAUSE_TMR */
-#define DNET_RX_FIFO_WCNT		0x12C	/* RX_FIFO_WCNT */
-#define DNET_TX_FIFO_WCNT		0x130	/* TX_FIFO_WCNT */
-
-/* ALL DNET MAC REGISTERS */
-#define DNET_MACREG_DATA		0x200	/* Mac-Reg Data */
-#define DNET_MACREG_ADDR		0x204	/* Mac-Reg Addr  */
-
-/* ALL DNET RX STATISTICS COUNTERS  */
-#define DNET_RX_PKT_IGNR_CNT		0x300
-#define DNET_RX_LEN_CHK_ERR_CNT		0x304
-#define DNET_RX_LNG_FRM_CNT		0x308
-#define DNET_RX_SHRT_FRM_CNT		0x30C
-#define DNET_RX_IPG_VIOL_CNT		0x310
-#define DNET_RX_CRC_ERR_CNT		0x314
-#define DNET_RX_OK_PKT_CNT		0x318
-#define DNET_RX_CTL_FRM_CNT		0x31C
-#define DNET_RX_PAUSE_FRM_CNT		0x320
-#define DNET_RX_MULTICAST_CNT		0x324
-#define DNET_RX_BROADCAST_CNT		0x328
-#define DNET_RX_VLAN_TAG_CNT		0x32C
-#define DNET_RX_PRE_SHRINK_CNT		0x330
-#define DNET_RX_DRIB_NIB_CNT		0x334
-#define DNET_RX_UNSUP_OPCD_CNT		0x338
-#define DNET_RX_BYTE_CNT		0x33C
-
-/* DNET TX STATISTICS COUNTERS */
-#define DNET_TX_UNICAST_CNT		0x400
-#define DNET_TX_PAUSE_FRM_CNT		0x404
-#define DNET_TX_MULTICAST_CNT		0x408
-#define DNET_TX_BRDCAST_CNT		0x40C
-#define DNET_TX_VLAN_TAG_CNT		0x410
-#define DNET_TX_BAD_FCS_CNT		0x414
-#define DNET_TX_JUMBO_CNT		0x418
-#define DNET_TX_BYTE_CNT		0x41C
-
-/* SOME INTERNAL MAC-CORE REGISTER */
-#define DNET_INTERNAL_MODE_REG		0x0
-#define DNET_INTERNAL_RXTX_CONTROL_REG	0x2
-#define DNET_INTERNAL_MAX_PKT_SIZE_REG	0x4
-#define DNET_INTERNAL_IGP_REG		0x8
-#define DNET_INTERNAL_MAC_ADDR_0_REG	0xa
-#define DNET_INTERNAL_MAC_ADDR_1_REG	0xc
-#define DNET_INTERNAL_MAC_ADDR_2_REG	0xe
-#define DNET_INTERNAL_TX_RX_STS_REG	0x12
-#define DNET_INTERNAL_GMII_MNG_CTL_REG	0x14
-#define DNET_INTERNAL_GMII_MNG_DAT_REG	0x16
-
-#define DNET_INTERNAL_GMII_MNG_CMD_FIN	(1 << 14)
-
-#define DNET_INTERNAL_WRITE		(1 << 31)
-
-/* MAC-CORE REGISTER FIELDS */
-
-/* MAC-CORE MODE REGISTER FIELDS */
-#define DNET_INTERNAL_MODE_GBITEN			(1 << 0)
-#define DNET_INTERNAL_MODE_FCEN				(1 << 1)
-#define DNET_INTERNAL_MODE_RXEN				(1 << 2)
-#define DNET_INTERNAL_MODE_TXEN				(1 << 3)
-
-/* MAC-CORE RXTX CONTROL REGISTER FIELDS */
-#define DNET_INTERNAL_RXTX_CONTROL_RXSHORTFRAME		(1 << 8)
-#define DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST		(1 << 7)
-#define DNET_INTERNAL_RXTX_CONTROL_RXMULTICAST		(1 << 4)
-#define DNET_INTERNAL_RXTX_CONTROL_RXPAUSE		(1 << 3)
-#define DNET_INTERNAL_RXTX_CONTROL_DISTXFCS		(1 << 2)
-#define DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS		(1 << 1)
-#define DNET_INTERNAL_RXTX_CONTROL_ENPROMISC		(1 << 0)
-#define DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL		(1 << 6)
-#define DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP	(1 << 5)
-
-/* SYSTEM CONTROL REGISTER FIELDS */
-#define DNET_SYS_CTL_IGNORENEXTPKT			(1 << 0)
-#define DNET_SYS_CTL_SENDPAUSE				(1 << 2)
-#define DNET_SYS_CTL_RXFIFOFLUSH			(1 << 3)
-#define DNET_SYS_CTL_TXFIFOFLUSH			(1 << 4)
-
-/* TX STATUS REGISTER FIELDS */
-#define DNET_TX_STATUS_FIFO_ALMOST_EMPTY		(1 << 2)
-#define DNET_TX_STATUS_FIFO_ALMOST_FULL			(1 << 1)
-
-/* INTERRUPT SOURCE REGISTER FIELDS */
-#define DNET_INTR_SRC_TX_PKTSENT			(1 << 0)
-#define DNET_INTR_SRC_TX_FIFOAF				(1 << 1)
-#define DNET_INTR_SRC_TX_FIFOAE				(1 << 2)
-#define DNET_INTR_SRC_TX_DISCFRM			(1 << 3)
-#define DNET_INTR_SRC_TX_FIFOFULL			(1 << 4)
-#define DNET_INTR_SRC_RX_CMDFIFOAF			(1 << 8)
-#define DNET_INTR_SRC_RX_CMDFIFOFF			(1 << 9)
-#define DNET_INTR_SRC_RX_DATAFIFOFF			(1 << 10)
-#define DNET_INTR_SRC_TX_SUMMARY			(1 << 16)
-#define DNET_INTR_SRC_RX_SUMMARY			(1 << 17)
-#define DNET_INTR_SRC_PHY				(1 << 19)
-
-/* INTERRUPT ENABLE REGISTER FIELDS */
-#define DNET_INTR_ENB_TX_PKTSENT			(1 << 0)
-#define DNET_INTR_ENB_TX_FIFOAF				(1 << 1)
-#define DNET_INTR_ENB_TX_FIFOAE				(1 << 2)
-#define DNET_INTR_ENB_TX_DISCFRM			(1 << 3)
-#define DNET_INTR_ENB_TX_FIFOFULL			(1 << 4)
-#define DNET_INTR_ENB_RX_PKTRDY				(1 << 8)
-#define DNET_INTR_ENB_RX_FIFOAF				(1 << 9)
-#define DNET_INTR_ENB_RX_FIFOERR			(1 << 10)
-#define DNET_INTR_ENB_RX_ERROR				(1 << 11)
-#define DNET_INTR_ENB_RX_FIFOFULL			(1 << 12)
-#define DNET_INTR_ENB_RX_FIFOAE				(1 << 13)
-#define DNET_INTR_ENB_TX_SUMMARY			(1 << 16)
-#define DNET_INTR_ENB_RX_SUMMARY			(1 << 17)
-#define DNET_INTR_ENB_GLOBAL_ENABLE			(1 << 18)
-
-/* default values:
- * almost empty = less than one full sized ethernet frame (no jumbo) inside
- * the fifo almost full = can write less than one full sized ethernet frame
- * (no jumbo) inside the fifo
- */
-#define DNET_CFG_TX_FIFO_FULL_THRES	25
-#define DNET_CFG_RX_FIFO_FULL_THRES	20
-
-/*
- * Capabilities. Used by the driver to know the capabilities that the ethernet
- * controller inside the FPGA have.
- */
-
-#define DNET_HAS_MDIO		(1 << 0)
-#define DNET_HAS_IRQ		(1 << 1)
-#define DNET_HAS_GIGABIT	(1 << 2)
-#define DNET_HAS_DMA		(1 << 3)
-
-#define DNET_HAS_MII		(1 << 4) /* or GMII */
-#define DNET_HAS_RMII		(1 << 5) /* or RGMII */
-
-#define DNET_CAPS_MASK		0xFFFF
-
-#define DNET_FIFO_SIZE		1024 /* 1K x 32 bit */
-#define DNET_FIFO_TX_DATA_AF_TH	(DNET_FIFO_SIZE - 384) /* 384 = 1536 / 4 */
-#define DNET_FIFO_TX_DATA_AE_TH	384
-
-#define DNET_FIFO_RX_CMD_AF_TH	(1 << 16) /* just one frame inside the FIFO */
-
-/*
- * Hardware-collected statistics.
- */
-struct dnet_stats {
-	u32 rx_pkt_ignr;
-	u32 rx_len_chk_err;
-	u32 rx_lng_frm;
-	u32 rx_shrt_frm;
-	u32 rx_ipg_viol;
-	u32 rx_crc_err;
-	u32 rx_ok_pkt;
-	u32 rx_ctl_frm;
-	u32 rx_pause_frm;
-	u32 rx_multicast;
-	u32 rx_broadcast;
-	u32 rx_vlan_tag;
-	u32 rx_pre_shrink;
-	u32 rx_drib_nib;
-	u32 rx_unsup_opcd;
-	u32 rx_byte;
-	u32 tx_unicast;
-	u32 tx_pause_frm;
-	u32 tx_multicast;
-	u32 tx_brdcast;
-	u32 tx_vlan_tag;
-	u32 tx_bad_fcs;
-	u32 tx_jumbo;
-	u32 tx_byte;
-};
-
-struct dnet {
-	void __iomem			*regs;
-	spinlock_t			lock;
-	struct platform_device		*pdev;
-	struct net_device		*dev;
-	struct dnet_stats		hw_stats;
-	unsigned int			capabilities; /* read from FPGA */
-	struct napi_struct		napi;
-
-	/* PHY stuff */
-	struct mii_bus			*mii_bus;
-	struct phy_device		*phy_dev;
-	unsigned int			link;
-	unsigned int			speed;
-	unsigned int			duplex;
-};
-
-#endif /* _DNET_H */
diff -druN linux-libre-3.1-gnu/drivers/net/dummy.c linux-libre-3.2-gnu/drivers/net/dummy.c
--- linux-libre-3.1-gnu/drivers/net/dummy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/dummy.c	2012-01-04 18:55:44.000000000 -0500
@@ -116,7 +116,7 @@
 	.ndo_init		= dummy_dev_init,
 	.ndo_start_xmit		= dummy_xmit,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_multicast_list = set_multicast_list,
+	.ndo_set_rx_mode	= set_multicast_list,
 	.ndo_set_mac_address	= dummy_set_address,
 	.ndo_get_stats64	= dummy_get_stats64,
 };
diff -druN linux-libre-3.1-gnu/drivers/net/e1000/e1000_ethtool.c linux-libre-3.2-gnu/drivers/net/e1000/e1000_ethtool.c
--- linux-libre-3.1-gnu/drivers/net/e1000/e1000_ethtool.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000/e1000_ethtool.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1863 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2006 Intel Corporation.
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms and conditions of the GNU General Public License,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-/* ethtool support for e1000 */
-
-#include "e1000.h"
-#include <asm/uaccess.h>
-
-enum {NETDEV_STATS, E1000_STATS};
-
-struct e1000_stats {
-	char stat_string[ETH_GSTRING_LEN];
-	int type;
-	int sizeof_stat;
-	int stat_offset;
-};
-
-#define E1000_STAT(m)		E1000_STATS, \
-				sizeof(((struct e1000_adapter *)0)->m), \
-		      		offsetof(struct e1000_adapter, m)
-#define E1000_NETDEV_STAT(m)	NETDEV_STATS, \
-				sizeof(((struct net_device *)0)->m), \
-				offsetof(struct net_device, m)
-
-static const struct e1000_stats e1000_gstrings_stats[] = {
-	{ "rx_packets", E1000_STAT(stats.gprc) },
-	{ "tx_packets", E1000_STAT(stats.gptc) },
-	{ "rx_bytes", E1000_STAT(stats.gorcl) },
-	{ "tx_bytes", E1000_STAT(stats.gotcl) },
-	{ "rx_broadcast", E1000_STAT(stats.bprc) },
-	{ "tx_broadcast", E1000_STAT(stats.bptc) },
-	{ "rx_multicast", E1000_STAT(stats.mprc) },
-	{ "tx_multicast", E1000_STAT(stats.mptc) },
-	{ "rx_errors", E1000_STAT(stats.rxerrc) },
-	{ "tx_errors", E1000_STAT(stats.txerrc) },
-	{ "tx_dropped", E1000_NETDEV_STAT(stats.tx_dropped) },
-	{ "multicast", E1000_STAT(stats.mprc) },
-	{ "collisions", E1000_STAT(stats.colc) },
-	{ "rx_length_errors", E1000_STAT(stats.rlerrc) },
-	{ "rx_over_errors", E1000_NETDEV_STAT(stats.rx_over_errors) },
-	{ "rx_crc_errors", E1000_STAT(stats.crcerrs) },
-	{ "rx_frame_errors", E1000_NETDEV_STAT(stats.rx_frame_errors) },
-	{ "rx_no_buffer_count", E1000_STAT(stats.rnbc) },
-	{ "rx_missed_errors", E1000_STAT(stats.mpc) },
-	{ "tx_aborted_errors", E1000_STAT(stats.ecol) },
-	{ "tx_carrier_errors", E1000_STAT(stats.tncrs) },
-	{ "tx_fifo_errors", E1000_NETDEV_STAT(stats.tx_fifo_errors) },
-	{ "tx_heartbeat_errors", E1000_NETDEV_STAT(stats.tx_heartbeat_errors) },
-	{ "tx_window_errors", E1000_STAT(stats.latecol) },
-	{ "tx_abort_late_coll", E1000_STAT(stats.latecol) },
-	{ "tx_deferred_ok", E1000_STAT(stats.dc) },
-	{ "tx_single_coll_ok", E1000_STAT(stats.scc) },
-	{ "tx_multi_coll_ok", E1000_STAT(stats.mcc) },
-	{ "tx_timeout_count", E1000_STAT(tx_timeout_count) },
-	{ "tx_restart_queue", E1000_STAT(restart_queue) },
-	{ "rx_long_length_errors", E1000_STAT(stats.roc) },
-	{ "rx_short_length_errors", E1000_STAT(stats.ruc) },
-	{ "rx_align_errors", E1000_STAT(stats.algnerrc) },
-	{ "tx_tcp_seg_good", E1000_STAT(stats.tsctc) },
-	{ "tx_tcp_seg_failed", E1000_STAT(stats.tsctfc) },
-	{ "rx_flow_control_xon", E1000_STAT(stats.xonrxc) },
-	{ "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) },
-	{ "tx_flow_control_xon", E1000_STAT(stats.xontxc) },
-	{ "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
-	{ "rx_long_byte_count", E1000_STAT(stats.gorcl) },
-	{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
-	{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
-	{ "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) },
-	{ "tx_smbus", E1000_STAT(stats.mgptc) },
-	{ "rx_smbus", E1000_STAT(stats.mgprc) },
-	{ "dropped_smbus", E1000_STAT(stats.mgpdc) },
-};
-
-#define E1000_QUEUE_STATS_LEN 0
-#define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats)
-#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN + E1000_QUEUE_STATS_LEN)
-static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
-	"Register test  (offline)", "Eeprom test    (offline)",
-	"Interrupt test (offline)", "Loopback test  (offline)",
-	"Link test   (on/offline)"
-};
-#define E1000_TEST_LEN	ARRAY_SIZE(e1000_gstrings_test)
-
-static int e1000_get_settings(struct net_device *netdev,
-			      struct ethtool_cmd *ecmd)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	if (hw->media_type == e1000_media_type_copper) {
-
-		ecmd->supported = (SUPPORTED_10baseT_Half |
-		                   SUPPORTED_10baseT_Full |
-		                   SUPPORTED_100baseT_Half |
-		                   SUPPORTED_100baseT_Full |
-		                   SUPPORTED_1000baseT_Full|
-		                   SUPPORTED_Autoneg |
-		                   SUPPORTED_TP);
-		ecmd->advertising = ADVERTISED_TP;
-
-		if (hw->autoneg == 1) {
-			ecmd->advertising |= ADVERTISED_Autoneg;
-			/* the e1000 autoneg seems to match ethtool nicely */
-			ecmd->advertising |= hw->autoneg_advertised;
-		}
-
-		ecmd->port = PORT_TP;
-		ecmd->phy_address = hw->phy_addr;
-
-		if (hw->mac_type == e1000_82543)
-			ecmd->transceiver = XCVR_EXTERNAL;
-		else
-			ecmd->transceiver = XCVR_INTERNAL;
-
-	} else {
-		ecmd->supported   = (SUPPORTED_1000baseT_Full |
-				     SUPPORTED_FIBRE |
-				     SUPPORTED_Autoneg);
-
-		ecmd->advertising = (ADVERTISED_1000baseT_Full |
-				     ADVERTISED_FIBRE |
-				     ADVERTISED_Autoneg);
-
-		ecmd->port = PORT_FIBRE;
-
-		if (hw->mac_type >= e1000_82545)
-			ecmd->transceiver = XCVR_INTERNAL;
-		else
-			ecmd->transceiver = XCVR_EXTERNAL;
-	}
-
-	if (er32(STATUS) & E1000_STATUS_LU) {
-
-		e1000_get_speed_and_duplex(hw, &adapter->link_speed,
-		                                   &adapter->link_duplex);
-		ethtool_cmd_speed_set(ecmd, adapter->link_speed);
-
-		/* unfortunately FULL_DUPLEX != DUPLEX_FULL
-		 *          and HALF_DUPLEX != DUPLEX_HALF */
-
-		if (adapter->link_duplex == FULL_DUPLEX)
-			ecmd->duplex = DUPLEX_FULL;
-		else
-			ecmd->duplex = DUPLEX_HALF;
-	} else {
-		ethtool_cmd_speed_set(ecmd, -1);
-		ecmd->duplex = -1;
-	}
-
-	ecmd->autoneg = ((hw->media_type == e1000_media_type_fiber) ||
-			 hw->autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
-	return 0;
-}
-
-static int e1000_set_settings(struct net_device *netdev,
-			      struct ethtool_cmd *ecmd)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
-		msleep(1);
-
-	if (ecmd->autoneg == AUTONEG_ENABLE) {
-		hw->autoneg = 1;
-		if (hw->media_type == e1000_media_type_fiber)
-			hw->autoneg_advertised = ADVERTISED_1000baseT_Full |
-				     ADVERTISED_FIBRE |
-				     ADVERTISED_Autoneg;
-		else
-			hw->autoneg_advertised = ecmd->advertising |
-			                         ADVERTISED_TP |
-			                         ADVERTISED_Autoneg;
-		ecmd->advertising = hw->autoneg_advertised;
-	} else {
-		u32 speed = ethtool_cmd_speed(ecmd);
-		if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) {
-			clear_bit(__E1000_RESETTING, &adapter->flags);
-			return -EINVAL;
-		}
-	}
-
-	/* reset the link */
-
-	if (netif_running(adapter->netdev)) {
-		e1000_down(adapter);
-		e1000_up(adapter);
-	} else
-		e1000_reset(adapter);
-
-	clear_bit(__E1000_RESETTING, &adapter->flags);
-	return 0;
-}
-
-static u32 e1000_get_link(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	/*
-	 * If the link is not reported up to netdev, interrupts are disabled,
-	 * and so the physical link state may have changed since we last
-	 * looked. Set get_link_status to make sure that the true link
-	 * state is interrogated, rather than pulling a cached and possibly
-	 * stale link state from the driver.
-	 */
-	if (!netif_carrier_ok(netdev))
-		adapter->hw.get_link_status = 1;
-
-	return e1000_has_link(adapter);
-}
-
-static void e1000_get_pauseparam(struct net_device *netdev,
-				 struct ethtool_pauseparam *pause)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	pause->autoneg =
-		(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
-
-	if (hw->fc == E1000_FC_RX_PAUSE)
-		pause->rx_pause = 1;
-	else if (hw->fc == E1000_FC_TX_PAUSE)
-		pause->tx_pause = 1;
-	else if (hw->fc == E1000_FC_FULL) {
-		pause->rx_pause = 1;
-		pause->tx_pause = 1;
-	}
-}
-
-static int e1000_set_pauseparam(struct net_device *netdev,
-				struct ethtool_pauseparam *pause)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	int retval = 0;
-
-	adapter->fc_autoneg = pause->autoneg;
-
-	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
-		msleep(1);
-
-	if (pause->rx_pause && pause->tx_pause)
-		hw->fc = E1000_FC_FULL;
-	else if (pause->rx_pause && !pause->tx_pause)
-		hw->fc = E1000_FC_RX_PAUSE;
-	else if (!pause->rx_pause && pause->tx_pause)
-		hw->fc = E1000_FC_TX_PAUSE;
-	else if (!pause->rx_pause && !pause->tx_pause)
-		hw->fc = E1000_FC_NONE;
-
-	hw->original_fc = hw->fc;
-
-	if (adapter->fc_autoneg == AUTONEG_ENABLE) {
-		if (netif_running(adapter->netdev)) {
-			e1000_down(adapter);
-			e1000_up(adapter);
-		} else
-			e1000_reset(adapter);
-	} else
-		retval = ((hw->media_type == e1000_media_type_fiber) ?
-			  e1000_setup_link(hw) : e1000_force_mac_fc(hw));
-
-	clear_bit(__E1000_RESETTING, &adapter->flags);
-	return retval;
-}
-
-static u32 e1000_get_msglevel(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	return adapter->msg_enable;
-}
-
-static void e1000_set_msglevel(struct net_device *netdev, u32 data)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	adapter->msg_enable = data;
-}
-
-static int e1000_get_regs_len(struct net_device *netdev)
-{
-#define E1000_REGS_LEN 32
-	return E1000_REGS_LEN * sizeof(u32);
-}
-
-static void e1000_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
-			   void *p)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u32 *regs_buff = p;
-	u16 phy_data;
-
-	memset(p, 0, E1000_REGS_LEN * sizeof(u32));
-
-	regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
-
-	regs_buff[0]  = er32(CTRL);
-	regs_buff[1]  = er32(STATUS);
-
-	regs_buff[2]  = er32(RCTL);
-	regs_buff[3]  = er32(RDLEN);
-	regs_buff[4]  = er32(RDH);
-	regs_buff[5]  = er32(RDT);
-	regs_buff[6]  = er32(RDTR);
-
-	regs_buff[7]  = er32(TCTL);
-	regs_buff[8]  = er32(TDLEN);
-	regs_buff[9]  = er32(TDH);
-	regs_buff[10] = er32(TDT);
-	regs_buff[11] = er32(TIDV);
-
-	regs_buff[12] = hw->phy_type;  /* PHY type (IGP=1, M88=0) */
-	if (hw->phy_type == e1000_phy_igp) {
-		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
-				    IGP01E1000_PHY_AGC_A);
-		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A &
-				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
-		regs_buff[13] = (u32)phy_data; /* cable length */
-		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
-				    IGP01E1000_PHY_AGC_B);
-		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_B &
-				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
-		regs_buff[14] = (u32)phy_data; /* cable length */
-		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
-				    IGP01E1000_PHY_AGC_C);
-		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_C &
-				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
-		regs_buff[15] = (u32)phy_data; /* cable length */
-		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
-				    IGP01E1000_PHY_AGC_D);
-		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_D &
-				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
-		regs_buff[16] = (u32)phy_data; /* cable length */
-		regs_buff[17] = 0; /* extended 10bt distance (not needed) */
-		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
-		e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS &
-				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
-		regs_buff[18] = (u32)phy_data; /* cable polarity */
-		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
-				    IGP01E1000_PHY_PCS_INIT_REG);
-		e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG &
-				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
-		regs_buff[19] = (u32)phy_data; /* cable polarity */
-		regs_buff[20] = 0; /* polarity correction enabled (always) */
-		regs_buff[22] = 0; /* phy receive errors (unavailable) */
-		regs_buff[23] = regs_buff[18]; /* mdix mode */
-		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
-	} else {
-		e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
-		regs_buff[13] = (u32)phy_data; /* cable length */
-		regs_buff[14] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
-		regs_buff[15] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
-		regs_buff[16] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
-		e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-		regs_buff[17] = (u32)phy_data; /* extended 10bt distance */
-		regs_buff[18] = regs_buff[13]; /* cable polarity */
-		regs_buff[19] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
-		regs_buff[20] = regs_buff[17]; /* polarity correction */
-		/* phy receive errors */
-		regs_buff[22] = adapter->phy_stats.receive_errors;
-		regs_buff[23] = regs_buff[13]; /* mdix mode */
-	}
-	regs_buff[21] = adapter->phy_stats.idle_errors;  /* phy idle errors */
-	e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
-	regs_buff[24] = (u32)phy_data;  /* phy local receiver status */
-	regs_buff[25] = regs_buff[24];  /* phy remote receiver status */
-	if (hw->mac_type >= e1000_82540 &&
-	    hw->media_type == e1000_media_type_copper) {
-		regs_buff[26] = er32(MANC);
-	}
-}
-
-static int e1000_get_eeprom_len(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	return hw->eeprom.word_size * 2;
-}
-
-static int e1000_get_eeprom(struct net_device *netdev,
-			    struct ethtool_eeprom *eeprom, u8 *bytes)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u16 *eeprom_buff;
-	int first_word, last_word;
-	int ret_val = 0;
-	u16 i;
-
-	if (eeprom->len == 0)
-		return -EINVAL;
-
-	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
-
-	first_word = eeprom->offset >> 1;
-	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
-
-	eeprom_buff = kmalloc(sizeof(u16) *
-			(last_word - first_word + 1), GFP_KERNEL);
-	if (!eeprom_buff)
-		return -ENOMEM;
-
-	if (hw->eeprom.type == e1000_eeprom_spi)
-		ret_val = e1000_read_eeprom(hw, first_word,
-					    last_word - first_word + 1,
-					    eeprom_buff);
-	else {
-		for (i = 0; i < last_word - first_word + 1; i++) {
-			ret_val = e1000_read_eeprom(hw, first_word + i, 1,
-						    &eeprom_buff[i]);
-			if (ret_val)
-				break;
-		}
-	}
-
-	/* Device's eeprom is always little-endian, word addressable */
-	for (i = 0; i < last_word - first_word + 1; i++)
-		le16_to_cpus(&eeprom_buff[i]);
-
-	memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1),
-			eeprom->len);
-	kfree(eeprom_buff);
-
-	return ret_val;
-}
-
-static int e1000_set_eeprom(struct net_device *netdev,
-			    struct ethtool_eeprom *eeprom, u8 *bytes)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u16 *eeprom_buff;
-	void *ptr;
-	int max_len, first_word, last_word, ret_val = 0;
-	u16 i;
-
-	if (eeprom->len == 0)
-		return -EOPNOTSUPP;
-
-	if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
-		return -EFAULT;
-
-	max_len = hw->eeprom.word_size * 2;
-
-	first_word = eeprom->offset >> 1;
-	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
-	eeprom_buff = kmalloc(max_len, GFP_KERNEL);
-	if (!eeprom_buff)
-		return -ENOMEM;
-
-	ptr = (void *)eeprom_buff;
-
-	if (eeprom->offset & 1) {
-		/* need read/modify/write of first changed EEPROM word */
-		/* only the second byte of the word is being modified */
-		ret_val = e1000_read_eeprom(hw, first_word, 1,
-					    &eeprom_buff[0]);
-		ptr++;
-	}
-	if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {
-		/* need read/modify/write of last changed EEPROM word */
-		/* only the first byte of the word is being modified */
-		ret_val = e1000_read_eeprom(hw, last_word, 1,
-		                  &eeprom_buff[last_word - first_word]);
-	}
-
-	/* Device's eeprom is always little-endian, word addressable */
-	for (i = 0; i < last_word - first_word + 1; i++)
-		le16_to_cpus(&eeprom_buff[i]);
-
-	memcpy(ptr, bytes, eeprom->len);
-
-	for (i = 0; i < last_word - first_word + 1; i++)
-		eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]);
-
-	ret_val = e1000_write_eeprom(hw, first_word,
-				     last_word - first_word + 1, eeprom_buff);
-
-	/* Update the checksum over the first part of the EEPROM if needed */
-	if ((ret_val == 0) && (first_word <= EEPROM_CHECKSUM_REG))
-		e1000_update_eeprom_checksum(hw);
-
-	kfree(eeprom_buff);
-	return ret_val;
-}
-
-static void e1000_get_drvinfo(struct net_device *netdev,
-			      struct ethtool_drvinfo *drvinfo)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	char firmware_version[32];
-
-	strncpy(drvinfo->driver,  e1000_driver_name, 32);
-	strncpy(drvinfo->version, e1000_driver_version, 32);
-
-	sprintf(firmware_version, "N/A");
-	strncpy(drvinfo->fw_version, firmware_version, 32);
-	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
-	drvinfo->regdump_len = e1000_get_regs_len(netdev);
-	drvinfo->eedump_len = e1000_get_eeprom_len(netdev);
-}
-
-static void e1000_get_ringparam(struct net_device *netdev,
-				struct ethtool_ringparam *ring)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	e1000_mac_type mac_type = hw->mac_type;
-	struct e1000_tx_ring *txdr = adapter->tx_ring;
-	struct e1000_rx_ring *rxdr = adapter->rx_ring;
-
-	ring->rx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_RXD :
-		E1000_MAX_82544_RXD;
-	ring->tx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_TXD :
-		E1000_MAX_82544_TXD;
-	ring->rx_mini_max_pending = 0;
-	ring->rx_jumbo_max_pending = 0;
-	ring->rx_pending = rxdr->count;
-	ring->tx_pending = txdr->count;
-	ring->rx_mini_pending = 0;
-	ring->rx_jumbo_pending = 0;
-}
-
-static int e1000_set_ringparam(struct net_device *netdev,
-			       struct ethtool_ringparam *ring)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	e1000_mac_type mac_type = hw->mac_type;
-	struct e1000_tx_ring *txdr, *tx_old;
-	struct e1000_rx_ring *rxdr, *rx_old;
-	int i, err;
-
-	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
-		return -EINVAL;
-
-	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
-		msleep(1);
-
-	if (netif_running(adapter->netdev))
-		e1000_down(adapter);
-
-	tx_old = adapter->tx_ring;
-	rx_old = adapter->rx_ring;
-
-	err = -ENOMEM;
-	txdr = kcalloc(adapter->num_tx_queues, sizeof(struct e1000_tx_ring), GFP_KERNEL);
-	if (!txdr)
-		goto err_alloc_tx;
-
-	rxdr = kcalloc(adapter->num_rx_queues, sizeof(struct e1000_rx_ring), GFP_KERNEL);
-	if (!rxdr)
-		goto err_alloc_rx;
-
-	adapter->tx_ring = txdr;
-	adapter->rx_ring = rxdr;
-
-	rxdr->count = max(ring->rx_pending,(u32)E1000_MIN_RXD);
-	rxdr->count = min(rxdr->count,(u32)(mac_type < e1000_82544 ?
-		E1000_MAX_RXD : E1000_MAX_82544_RXD));
-	rxdr->count = ALIGN(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE);
-
-	txdr->count = max(ring->tx_pending,(u32)E1000_MIN_TXD);
-	txdr->count = min(txdr->count,(u32)(mac_type < e1000_82544 ?
-		E1000_MAX_TXD : E1000_MAX_82544_TXD));
-	txdr->count = ALIGN(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);
-
-	for (i = 0; i < adapter->num_tx_queues; i++)
-		txdr[i].count = txdr->count;
-	for (i = 0; i < adapter->num_rx_queues; i++)
-		rxdr[i].count = rxdr->count;
-
-	if (netif_running(adapter->netdev)) {
-		/* Try to get new resources before deleting old */
-		err = e1000_setup_all_rx_resources(adapter);
-		if (err)
-			goto err_setup_rx;
-		err = e1000_setup_all_tx_resources(adapter);
-		if (err)
-			goto err_setup_tx;
-
-		/* save the new, restore the old in order to free it,
-		 * then restore the new back again */
-
-		adapter->rx_ring = rx_old;
-		adapter->tx_ring = tx_old;
-		e1000_free_all_rx_resources(adapter);
-		e1000_free_all_tx_resources(adapter);
-		kfree(tx_old);
-		kfree(rx_old);
-		adapter->rx_ring = rxdr;
-		adapter->tx_ring = txdr;
-		err = e1000_up(adapter);
-		if (err)
-			goto err_setup;
-	}
-
-	clear_bit(__E1000_RESETTING, &adapter->flags);
-	return 0;
-err_setup_tx:
-	e1000_free_all_rx_resources(adapter);
-err_setup_rx:
-	adapter->rx_ring = rx_old;
-	adapter->tx_ring = tx_old;
-	kfree(rxdr);
-err_alloc_rx:
-	kfree(txdr);
-err_alloc_tx:
-	e1000_up(adapter);
-err_setup:
-	clear_bit(__E1000_RESETTING, &adapter->flags);
-	return err;
-}
-
-static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data, int reg,
-			     u32 mask, u32 write)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	static const u32 test[] =
-		{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
-	u8 __iomem *address = hw->hw_addr + reg;
-	u32 read;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(test); i++) {
-		writel(write & test[i], address);
-		read = readl(address);
-		if (read != (write & test[i] & mask)) {
-			e_err(drv, "pattern test reg %04X failed: "
-			      "got 0x%08X expected 0x%08X\n",
-			      reg, read, (write & test[i] & mask));
-			*data = reg;
-			return true;
-		}
-	}
-	return false;
-}
-
-static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data, int reg,
-			      u32 mask, u32 write)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u8 __iomem *address = hw->hw_addr + reg;
-	u32 read;
-
-	writel(write & mask, address);
-	read = readl(address);
-	if ((read & mask) != (write & mask)) {
-		e_err(drv, "set/check reg %04X test failed: "
-		      "got 0x%08X expected 0x%08X\n",
-		      reg, (read & mask), (write & mask));
-		*data = reg;
-		return true;
-	}
-	return false;
-}
-
-#define REG_PATTERN_TEST(reg, mask, write)			     \
-	do {							     \
-		if (reg_pattern_test(adapter, data,		     \
-			     (hw->mac_type >= e1000_82543)   \
-			     ? E1000_##reg : E1000_82542_##reg,	     \
-			     mask, write))			     \
-			return 1;				     \
-	} while (0)
-
-#define REG_SET_AND_CHECK(reg, mask, write)			     \
-	do {							     \
-		if (reg_set_and_check(adapter, data,		     \
-			      (hw->mac_type >= e1000_82543)  \
-			      ? E1000_##reg : E1000_82542_##reg,     \
-			      mask, write))			     \
-			return 1;				     \
-	} while (0)
-
-static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
-{
-	u32 value, before, after;
-	u32 i, toggle;
-	struct e1000_hw *hw = &adapter->hw;
-
-	/* The status register is Read Only, so a write should fail.
-	 * Some bits that get toggled are ignored.
-	 */
-
-	/* there are several bits on newer hardware that are r/w */
-	toggle = 0xFFFFF833;
-
-	before = er32(STATUS);
-	value = (er32(STATUS) & toggle);
-	ew32(STATUS, toggle);
-	after = er32(STATUS) & toggle;
-	if (value != after) {
-		e_err(drv, "failed STATUS register test got: "
-		      "0x%08X expected: 0x%08X\n", after, value);
-		*data = 1;
-		return 1;
-	}
-	/* restore previous status */
-	ew32(STATUS, before);
-
-	REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
-	REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
-	REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);
-	REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF);
-
-	REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF);
-	REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
-	REG_PATTERN_TEST(RDLEN, 0x000FFF80, 0x000FFFFF);
-	REG_PATTERN_TEST(RDH, 0x0000FFFF, 0x0000FFFF);
-	REG_PATTERN_TEST(RDT, 0x0000FFFF, 0x0000FFFF);
-	REG_PATTERN_TEST(FCRTH, 0x0000FFF8, 0x0000FFF8);
-	REG_PATTERN_TEST(FCTTV, 0x0000FFFF, 0x0000FFFF);
-	REG_PATTERN_TEST(TIPG, 0x3FFFFFFF, 0x3FFFFFFF);
-	REG_PATTERN_TEST(TDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
-	REG_PATTERN_TEST(TDLEN, 0x000FFF80, 0x000FFFFF);
-
-	REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000);
-
-	before = 0x06DFB3FE;
-	REG_SET_AND_CHECK(RCTL, before, 0x003FFFFB);
-	REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
-
-	if (hw->mac_type >= e1000_82543) {
-
-		REG_SET_AND_CHECK(RCTL, before, 0xFFFFFFFF);
-		REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
-		REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);
-		REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
-		REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
-		value = E1000_RAR_ENTRIES;
-		for (i = 0; i < value; i++) {
-			REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
-			                 0xFFFFFFFF);
-		}
-
-	} else {
-
-		REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x01FFFFFF);
-		REG_PATTERN_TEST(RDBAL, 0xFFFFF000, 0xFFFFFFFF);
-		REG_PATTERN_TEST(TXCW, 0x0000FFFF, 0x0000FFFF);
-		REG_PATTERN_TEST(TDBAL, 0xFFFFF000, 0xFFFFFFFF);
-
-	}
-
-	value = E1000_MC_TBL_SIZE;
-	for (i = 0; i < value; i++)
-		REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
-
-	*data = 0;
-	return 0;
-}
-
-static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u16 temp;
-	u16 checksum = 0;
-	u16 i;
-
-	*data = 0;
-	/* Read and add up the contents of the EEPROM */
-	for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
-		if ((e1000_read_eeprom(hw, i, 1, &temp)) < 0) {
-			*data = 1;
-			break;
-		}
-		checksum += temp;
-	}
-
-	/* If Checksum is not Correct return error else test passed */
-	if ((checksum != (u16)EEPROM_SUM) && !(*data))
-		*data = 2;
-
-	return *data;
-}
-
-static irqreturn_t e1000_test_intr(int irq, void *data)
-{
-	struct net_device *netdev = (struct net_device *)data;
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	adapter->test_icr |= er32(ICR);
-
-	return IRQ_HANDLED;
-}
-
-static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
-{
-	struct net_device *netdev = adapter->netdev;
-	u32 mask, i = 0;
-	bool shared_int = true;
-	u32 irq = adapter->pdev->irq;
-	struct e1000_hw *hw = &adapter->hw;
-
-	*data = 0;
-
-	/* NOTE: we don't test MSI interrupts here, yet */
-	/* Hook up test interrupt handler just for this test */
-	if (!request_irq(irq, e1000_test_intr, IRQF_PROBE_SHARED, netdev->name,
-	                 netdev))
-		shared_int = false;
-	else if (request_irq(irq, e1000_test_intr, IRQF_SHARED,
-	         netdev->name, netdev)) {
-		*data = 1;
-		return -1;
-	}
-	e_info(hw, "testing %s interrupt\n", (shared_int ?
-	       "shared" : "unshared"));
-
-	/* Disable all the interrupts */
-	ew32(IMC, 0xFFFFFFFF);
-	E1000_WRITE_FLUSH();
-	msleep(10);
-
-	/* Test each interrupt */
-	for (; i < 10; i++) {
-
-		/* Interrupt to test */
-		mask = 1 << i;
-
-		if (!shared_int) {
-			/* Disable the interrupt to be reported in
-			 * the cause register and then force the same
-			 * interrupt and see if one gets posted.  If
-			 * an interrupt was posted to the bus, the
-			 * test failed.
-			 */
-			adapter->test_icr = 0;
-			ew32(IMC, mask);
-			ew32(ICS, mask);
-			E1000_WRITE_FLUSH();
-			msleep(10);
-
-			if (adapter->test_icr & mask) {
-				*data = 3;
-				break;
-			}
-		}
-
-		/* Enable the interrupt to be reported in
-		 * the cause register and then force the same
-		 * interrupt and see if one gets posted.  If
-		 * an interrupt was not posted to the bus, the
-		 * test failed.
-		 */
-		adapter->test_icr = 0;
-		ew32(IMS, mask);
-		ew32(ICS, mask);
-		E1000_WRITE_FLUSH();
-		msleep(10);
-
-		if (!(adapter->test_icr & mask)) {
-			*data = 4;
-			break;
-		}
-
-		if (!shared_int) {
-			/* Disable the other interrupts to be reported in
-			 * the cause register and then force the other
-			 * interrupts and see if any get posted.  If
-			 * an interrupt was posted to the bus, the
-			 * test failed.
-			 */
-			adapter->test_icr = 0;
-			ew32(IMC, ~mask & 0x00007FFF);
-			ew32(ICS, ~mask & 0x00007FFF);
-			E1000_WRITE_FLUSH();
-			msleep(10);
-
-			if (adapter->test_icr) {
-				*data = 5;
-				break;
-			}
-		}
-	}
-
-	/* Disable all the interrupts */
-	ew32(IMC, 0xFFFFFFFF);
-	E1000_WRITE_FLUSH();
-	msleep(10);
-
-	/* Unhook test interrupt handler */
-	free_irq(irq, netdev);
-
-	return *data;
-}
-
-static void e1000_free_desc_rings(struct e1000_adapter *adapter)
-{
-	struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
-	struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
-	struct pci_dev *pdev = adapter->pdev;
-	int i;
-
-	if (txdr->desc && txdr->buffer_info) {
-		for (i = 0; i < txdr->count; i++) {
-			if (txdr->buffer_info[i].dma)
-				dma_unmap_single(&pdev->dev,
-						 txdr->buffer_info[i].dma,
-						 txdr->buffer_info[i].length,
-						 DMA_TO_DEVICE);
-			if (txdr->buffer_info[i].skb)
-				dev_kfree_skb(txdr->buffer_info[i].skb);
-		}
-	}
-
-	if (rxdr->desc && rxdr->buffer_info) {
-		for (i = 0; i < rxdr->count; i++) {
-			if (rxdr->buffer_info[i].dma)
-				dma_unmap_single(&pdev->dev,
-						 rxdr->buffer_info[i].dma,
-						 rxdr->buffer_info[i].length,
-						 DMA_FROM_DEVICE);
-			if (rxdr->buffer_info[i].skb)
-				dev_kfree_skb(rxdr->buffer_info[i].skb);
-		}
-	}
-
-	if (txdr->desc) {
-		dma_free_coherent(&pdev->dev, txdr->size, txdr->desc,
-				  txdr->dma);
-		txdr->desc = NULL;
-	}
-	if (rxdr->desc) {
-		dma_free_coherent(&pdev->dev, rxdr->size, rxdr->desc,
-				  rxdr->dma);
-		rxdr->desc = NULL;
-	}
-
-	kfree(txdr->buffer_info);
-	txdr->buffer_info = NULL;
-	kfree(rxdr->buffer_info);
-	rxdr->buffer_info = NULL;
-}
-
-static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
-	struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
-	struct pci_dev *pdev = adapter->pdev;
-	u32 rctl;
-	int i, ret_val;
-
-	/* Setup Tx descriptor ring and Tx buffers */
-
-	if (!txdr->count)
-		txdr->count = E1000_DEFAULT_TXD;
-
-	txdr->buffer_info = kcalloc(txdr->count, sizeof(struct e1000_buffer),
-				    GFP_KERNEL);
-	if (!txdr->buffer_info) {
-		ret_val = 1;
-		goto err_nomem;
-	}
-
-	txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
-	txdr->size = ALIGN(txdr->size, 4096);
-	txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
-					GFP_KERNEL);
-	if (!txdr->desc) {
-		ret_val = 2;
-		goto err_nomem;
-	}
-	memset(txdr->desc, 0, txdr->size);
-	txdr->next_to_use = txdr->next_to_clean = 0;
-
-	ew32(TDBAL, ((u64)txdr->dma & 0x00000000FFFFFFFF));
-	ew32(TDBAH, ((u64)txdr->dma >> 32));
-	ew32(TDLEN, txdr->count * sizeof(struct e1000_tx_desc));
-	ew32(TDH, 0);
-	ew32(TDT, 0);
-	ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN |
-	     E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
-	     E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT);
-
-	for (i = 0; i < txdr->count; i++) {
-		struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*txdr, i);
-		struct sk_buff *skb;
-		unsigned int size = 1024;
-
-		skb = alloc_skb(size, GFP_KERNEL);
-		if (!skb) {
-			ret_val = 3;
-			goto err_nomem;
-		}
-		skb_put(skb, size);
-		txdr->buffer_info[i].skb = skb;
-		txdr->buffer_info[i].length = skb->len;
-		txdr->buffer_info[i].dma =
-			dma_map_single(&pdev->dev, skb->data, skb->len,
-				       DMA_TO_DEVICE);
-		tx_desc->buffer_addr = cpu_to_le64(txdr->buffer_info[i].dma);
-		tx_desc->lower.data = cpu_to_le32(skb->len);
-		tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP |
-						   E1000_TXD_CMD_IFCS |
-						   E1000_TXD_CMD_RPS);
-		tx_desc->upper.data = 0;
-	}
-
-	/* Setup Rx descriptor ring and Rx buffers */
-
-	if (!rxdr->count)
-		rxdr->count = E1000_DEFAULT_RXD;
-
-	rxdr->buffer_info = kcalloc(rxdr->count, sizeof(struct e1000_buffer),
-				    GFP_KERNEL);
-	if (!rxdr->buffer_info) {
-		ret_val = 4;
-		goto err_nomem;
-	}
-
-	rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
-	rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
-					GFP_KERNEL);
-	if (!rxdr->desc) {
-		ret_val = 5;
-		goto err_nomem;
-	}
-	memset(rxdr->desc, 0, rxdr->size);
-	rxdr->next_to_use = rxdr->next_to_clean = 0;
-
-	rctl = er32(RCTL);
-	ew32(RCTL, rctl & ~E1000_RCTL_EN);
-	ew32(RDBAL, ((u64)rxdr->dma & 0xFFFFFFFF));
-	ew32(RDBAH, ((u64)rxdr->dma >> 32));
-	ew32(RDLEN, rxdr->size);
-	ew32(RDH, 0);
-	ew32(RDT, 0);
-	rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |
-		E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
-		(hw->mc_filter_type << E1000_RCTL_MO_SHIFT);
-	ew32(RCTL, rctl);
-
-	for (i = 0; i < rxdr->count; i++) {
-		struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i);
-		struct sk_buff *skb;
-
-		skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL);
-		if (!skb) {
-			ret_val = 6;
-			goto err_nomem;
-		}
-		skb_reserve(skb, NET_IP_ALIGN);
-		rxdr->buffer_info[i].skb = skb;
-		rxdr->buffer_info[i].length = E1000_RXBUFFER_2048;
-		rxdr->buffer_info[i].dma =
-			dma_map_single(&pdev->dev, skb->data,
-				       E1000_RXBUFFER_2048, DMA_FROM_DEVICE);
-		rx_desc->buffer_addr = cpu_to_le64(rxdr->buffer_info[i].dma);
-		memset(skb->data, 0x00, skb->len);
-	}
-
-	return 0;
-
-err_nomem:
-	e1000_free_desc_rings(adapter);
-	return ret_val;
-}
-
-static void e1000_phy_disable_receiver(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-
-	/* Write out to PHY registers 29 and 30 to disable the Receiver. */
-	e1000_write_phy_reg(hw, 29, 0x001F);
-	e1000_write_phy_reg(hw, 30, 0x8FFC);
-	e1000_write_phy_reg(hw, 29, 0x001A);
-	e1000_write_phy_reg(hw, 30, 0x8FF0);
-}
-
-static void e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u16 phy_reg;
-
-	/* Because we reset the PHY above, we need to re-force TX_CLK in the
-	 * Extended PHY Specific Control Register to 25MHz clock.  This
-	 * value defaults back to a 2.5MHz clock when the PHY is reset.
-	 */
-	e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
-	phy_reg |= M88E1000_EPSCR_TX_CLK_25;
-	e1000_write_phy_reg(hw,
-		M88E1000_EXT_PHY_SPEC_CTRL, phy_reg);
-
-	/* In addition, because of the s/w reset above, we need to enable
-	 * CRS on TX.  This must be set for both full and half duplex
-	 * operation.
-	 */
-	e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
-	phy_reg |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
-	e1000_write_phy_reg(hw,
-		M88E1000_PHY_SPEC_CTRL, phy_reg);
-}
-
-static int e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 ctrl_reg;
-	u16 phy_reg;
-
-	/* Setup the Device Control Register for PHY loopback test. */
-
-	ctrl_reg = er32(CTRL);
-	ctrl_reg |= (E1000_CTRL_ILOS |		/* Invert Loss-Of-Signal */
-		     E1000_CTRL_FRCSPD |	/* Set the Force Speed Bit */
-		     E1000_CTRL_FRCDPX |	/* Set the Force Duplex Bit */
-		     E1000_CTRL_SPD_1000 |	/* Force Speed to 1000 */
-		     E1000_CTRL_FD);		/* Force Duplex to FULL */
-
-	ew32(CTRL, ctrl_reg);
-
-	/* Read the PHY Specific Control Register (0x10) */
-	e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
-
-	/* Clear Auto-Crossover bits in PHY Specific Control Register
-	 * (bits 6:5).
-	 */
-	phy_reg &= ~M88E1000_PSCR_AUTO_X_MODE;
-	e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_reg);
-
-	/* Perform software reset on the PHY */
-	e1000_phy_reset(hw);
-
-	/* Have to setup TX_CLK and TX_CRS after software reset */
-	e1000_phy_reset_clk_and_crs(adapter);
-
-	e1000_write_phy_reg(hw, PHY_CTRL, 0x8100);
-
-	/* Wait for reset to complete. */
-	udelay(500);
-
-	/* Have to setup TX_CLK and TX_CRS after software reset */
-	e1000_phy_reset_clk_and_crs(adapter);
-
-	/* Write out to PHY registers 29 and 30 to disable the Receiver. */
-	e1000_phy_disable_receiver(adapter);
-
-	/* Set the loopback bit in the PHY control register. */
-	e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
-	phy_reg |= MII_CR_LOOPBACK;
-	e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
-
-	/* Setup TX_CLK and TX_CRS one more time. */
-	e1000_phy_reset_clk_and_crs(adapter);
-
-	/* Check Phy Configuration */
-	e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
-	if (phy_reg != 0x4100)
-		 return 9;
-
-	e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
-	if (phy_reg != 0x0070)
-		return 10;
-
-	e1000_read_phy_reg(hw, 29, &phy_reg);
-	if (phy_reg != 0x001A)
-		return 11;
-
-	return 0;
-}
-
-static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 ctrl_reg = 0;
-	u32 stat_reg = 0;
-
-	hw->autoneg = false;
-
-	if (hw->phy_type == e1000_phy_m88) {
-		/* Auto-MDI/MDIX Off */
-		e1000_write_phy_reg(hw,
-				    M88E1000_PHY_SPEC_CTRL, 0x0808);
-		/* reset to update Auto-MDI/MDIX */
-		e1000_write_phy_reg(hw, PHY_CTRL, 0x9140);
-		/* autoneg off */
-		e1000_write_phy_reg(hw, PHY_CTRL, 0x8140);
-	}
-
-	ctrl_reg = er32(CTRL);
-
-	/* force 1000, set loopback */
-	e1000_write_phy_reg(hw, PHY_CTRL, 0x4140);
-
-	/* Now set up the MAC to the same speed/duplex as the PHY. */
-	ctrl_reg = er32(CTRL);
-	ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
-	ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
-			E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
-			E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
-			E1000_CTRL_FD);	 /* Force Duplex to FULL */
-
-	if (hw->media_type == e1000_media_type_copper &&
-	   hw->phy_type == e1000_phy_m88)
-		ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
-	else {
-		/* Set the ILOS bit on the fiber Nic is half
-		 * duplex link is detected. */
-		stat_reg = er32(STATUS);
-		if ((stat_reg & E1000_STATUS_FD) == 0)
-			ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
-	}
-
-	ew32(CTRL, ctrl_reg);
-
-	/* Disable the receiver on the PHY so when a cable is plugged in, the
-	 * PHY does not begin to autoneg when a cable is reconnected to the NIC.
-	 */
-	if (hw->phy_type == e1000_phy_m88)
-		e1000_phy_disable_receiver(adapter);
-
-	udelay(500);
-
-	return 0;
-}
-
-static int e1000_set_phy_loopback(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u16 phy_reg = 0;
-	u16 count = 0;
-
-	switch (hw->mac_type) {
-	case e1000_82543:
-		if (hw->media_type == e1000_media_type_copper) {
-			/* Attempt to setup Loopback mode on Non-integrated PHY.
-			 * Some PHY registers get corrupted at random, so
-			 * attempt this 10 times.
-			 */
-			while (e1000_nonintegrated_phy_loopback(adapter) &&
-			      count++ < 10);
-			if (count < 11)
-				return 0;
-		}
-		break;
-
-	case e1000_82544:
-	case e1000_82540:
-	case e1000_82545:
-	case e1000_82545_rev_3:
-	case e1000_82546:
-	case e1000_82546_rev_3:
-	case e1000_82541:
-	case e1000_82541_rev_2:
-	case e1000_82547:
-	case e1000_82547_rev_2:
-		return e1000_integrated_phy_loopback(adapter);
-		break;
-	default:
-		/* Default PHY loopback work is to read the MII
-		 * control register and assert bit 14 (loopback mode).
-		 */
-		e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
-		phy_reg |= MII_CR_LOOPBACK;
-		e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
-		return 0;
-		break;
-	}
-
-	return 8;
-}
-
-static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 rctl;
-
-	if (hw->media_type == e1000_media_type_fiber ||
-	    hw->media_type == e1000_media_type_internal_serdes) {
-		switch (hw->mac_type) {
-		case e1000_82545:
-		case e1000_82546:
-		case e1000_82545_rev_3:
-		case e1000_82546_rev_3:
-			return e1000_set_phy_loopback(adapter);
-			break;
-		default:
-			rctl = er32(RCTL);
-			rctl |= E1000_RCTL_LBM_TCVR;
-			ew32(RCTL, rctl);
-			return 0;
-		}
-	} else if (hw->media_type == e1000_media_type_copper)
-		return e1000_set_phy_loopback(adapter);
-
-	return 7;
-}
-
-static void e1000_loopback_cleanup(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 rctl;
-	u16 phy_reg;
-
-	rctl = er32(RCTL);
-	rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
-	ew32(RCTL, rctl);
-
-	switch (hw->mac_type) {
-	case e1000_82545:
-	case e1000_82546:
-	case e1000_82545_rev_3:
-	case e1000_82546_rev_3:
-	default:
-		hw->autoneg = true;
-		e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
-		if (phy_reg & MII_CR_LOOPBACK) {
-			phy_reg &= ~MII_CR_LOOPBACK;
-			e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
-			e1000_phy_reset(hw);
-		}
-		break;
-	}
-}
-
-static void e1000_create_lbtest_frame(struct sk_buff *skb,
-				      unsigned int frame_size)
-{
-	memset(skb->data, 0xFF, frame_size);
-	frame_size &= ~1;
-	memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
-	memset(&skb->data[frame_size / 2 + 10], 0xBE, 1);
-	memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);
-}
-
-static int e1000_check_lbtest_frame(struct sk_buff *skb,
-				    unsigned int frame_size)
-{
-	frame_size &= ~1;
-	if (*(skb->data + 3) == 0xFF) {
-		if ((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
-		   (*(skb->data + frame_size / 2 + 12) == 0xAF)) {
-			return 0;
-		}
-	}
-	return 13;
-}
-
-static int e1000_run_loopback_test(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
-	struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
-	struct pci_dev *pdev = adapter->pdev;
-	int i, j, k, l, lc, good_cnt, ret_val=0;
-	unsigned long time;
-
-	ew32(RDT, rxdr->count - 1);
-
-	/* Calculate the loop count based on the largest descriptor ring
-	 * The idea is to wrap the largest ring a number of times using 64
-	 * send/receive pairs during each loop
-	 */
-
-	if (rxdr->count <= txdr->count)
-		lc = ((txdr->count / 64) * 2) + 1;
-	else
-		lc = ((rxdr->count / 64) * 2) + 1;
-
-	k = l = 0;
-	for (j = 0; j <= lc; j++) { /* loop count loop */
-		for (i = 0; i < 64; i++) { /* send the packets */
-			e1000_create_lbtest_frame(txdr->buffer_info[i].skb,
-					1024);
-			dma_sync_single_for_device(&pdev->dev,
-						   txdr->buffer_info[k].dma,
-						   txdr->buffer_info[k].length,
-						   DMA_TO_DEVICE);
-			if (unlikely(++k == txdr->count)) k = 0;
-		}
-		ew32(TDT, k);
-		E1000_WRITE_FLUSH();
-		msleep(200);
-		time = jiffies; /* set the start time for the receive */
-		good_cnt = 0;
-		do { /* receive the sent packets */
-			dma_sync_single_for_cpu(&pdev->dev,
-						rxdr->buffer_info[l].dma,
-						rxdr->buffer_info[l].length,
-						DMA_FROM_DEVICE);
-
-			ret_val = e1000_check_lbtest_frame(
-					rxdr->buffer_info[l].skb,
-				   	1024);
-			if (!ret_val)
-				good_cnt++;
-			if (unlikely(++l == rxdr->count)) l = 0;
-			/* time + 20 msecs (200 msecs on 2.4) is more than
-			 * enough time to complete the receives, if it's
-			 * exceeded, break and error off
-			 */
-		} while (good_cnt < 64 && jiffies < (time + 20));
-		if (good_cnt != 64) {
-			ret_val = 13; /* ret_val is the same as mis-compare */
-			break;
-		}
-		if (jiffies >= (time + 2)) {
-			ret_val = 14; /* error code for time out error */
-			break;
-		}
-	} /* end loop count loop */
-	return ret_val;
-}
-
-static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
-{
-	*data = e1000_setup_desc_rings(adapter);
-	if (*data)
-		goto out;
-	*data = e1000_setup_loopback_test(adapter);
-	if (*data)
-		goto err_loopback;
-	*data = e1000_run_loopback_test(adapter);
-	e1000_loopback_cleanup(adapter);
-
-err_loopback:
-	e1000_free_desc_rings(adapter);
-out:
-	return *data;
-}
-
-static int e1000_link_test(struct e1000_adapter *adapter, u64 *data)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	*data = 0;
-	if (hw->media_type == e1000_media_type_internal_serdes) {
-		int i = 0;
-		hw->serdes_has_link = false;
-
-		/* On some blade server designs, link establishment
-		 * could take as long as 2-3 minutes */
-		do {
-			e1000_check_for_link(hw);
-			if (hw->serdes_has_link)
-				return *data;
-			msleep(20);
-		} while (i++ < 3750);
-
-		*data = 1;
-	} else {
-		e1000_check_for_link(hw);
-		if (hw->autoneg)  /* if auto_neg is set wait for it */
-			msleep(4000);
-
-		if (!(er32(STATUS) & E1000_STATUS_LU)) {
-			*data = 1;
-		}
-	}
-	return *data;
-}
-
-static int e1000_get_sset_count(struct net_device *netdev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_TEST:
-		return E1000_TEST_LEN;
-	case ETH_SS_STATS:
-		return E1000_STATS_LEN;
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void e1000_diag_test(struct net_device *netdev,
-			    struct ethtool_test *eth_test, u64 *data)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	bool if_running = netif_running(netdev);
-
-	set_bit(__E1000_TESTING, &adapter->flags);
-	if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
-		/* Offline tests */
-
-		/* save speed, duplex, autoneg settings */
-		u16 autoneg_advertised = hw->autoneg_advertised;
-		u8 forced_speed_duplex = hw->forced_speed_duplex;
-		u8 autoneg = hw->autoneg;
-
-		e_info(hw, "offline testing starting\n");
-
-		/* Link test performed before hardware reset so autoneg doesn't
-		 * interfere with test result */
-		if (e1000_link_test(adapter, &data[4]))
-			eth_test->flags |= ETH_TEST_FL_FAILED;
-
-		if (if_running)
-			/* indicate we're in test mode */
-			dev_close(netdev);
-		else
-			e1000_reset(adapter);
-
-		if (e1000_reg_test(adapter, &data[0]))
-			eth_test->flags |= ETH_TEST_FL_FAILED;
-
-		e1000_reset(adapter);
-		if (e1000_eeprom_test(adapter, &data[1]))
-			eth_test->flags |= ETH_TEST_FL_FAILED;
-
-		e1000_reset(adapter);
-		if (e1000_intr_test(adapter, &data[2]))
-			eth_test->flags |= ETH_TEST_FL_FAILED;
-
-		e1000_reset(adapter);
-		/* make sure the phy is powered up */
-		e1000_power_up_phy(adapter);
-		if (e1000_loopback_test(adapter, &data[3]))
-			eth_test->flags |= ETH_TEST_FL_FAILED;
-
-		/* restore speed, duplex, autoneg settings */
-		hw->autoneg_advertised = autoneg_advertised;
-		hw->forced_speed_duplex = forced_speed_duplex;
-		hw->autoneg = autoneg;
-
-		e1000_reset(adapter);
-		clear_bit(__E1000_TESTING, &adapter->flags);
-		if (if_running)
-			dev_open(netdev);
-	} else {
-		e_info(hw, "online testing starting\n");
-		/* Online tests */
-		if (e1000_link_test(adapter, &data[4]))
-			eth_test->flags |= ETH_TEST_FL_FAILED;
-
-		/* Online tests aren't run; pass by default */
-		data[0] = 0;
-		data[1] = 0;
-		data[2] = 0;
-		data[3] = 0;
-
-		clear_bit(__E1000_TESTING, &adapter->flags);
-	}
-	msleep_interruptible(4 * 1000);
-}
-
-static int e1000_wol_exclusion(struct e1000_adapter *adapter,
-			       struct ethtool_wolinfo *wol)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	int retval = 1; /* fail by default */
-
-	switch (hw->device_id) {
-	case E1000_DEV_ID_82542:
-	case E1000_DEV_ID_82543GC_FIBER:
-	case E1000_DEV_ID_82543GC_COPPER:
-	case E1000_DEV_ID_82544EI_FIBER:
-	case E1000_DEV_ID_82546EB_QUAD_COPPER:
-	case E1000_DEV_ID_82545EM_FIBER:
-	case E1000_DEV_ID_82545EM_COPPER:
-	case E1000_DEV_ID_82546GB_QUAD_COPPER:
-	case E1000_DEV_ID_82546GB_PCIE:
-		/* these don't support WoL at all */
-		wol->supported = 0;
-		break;
-	case E1000_DEV_ID_82546EB_FIBER:
-	case E1000_DEV_ID_82546GB_FIBER:
-		/* Wake events not supported on port B */
-		if (er32(STATUS) & E1000_STATUS_FUNC_1) {
-			wol->supported = 0;
-			break;
-		}
-		/* return success for non excluded adapter ports */
-		retval = 0;
-		break;
-	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
-		/* quad port adapters only support WoL on port A */
-		if (!adapter->quad_port_a) {
-			wol->supported = 0;
-			break;
-		}
-		/* return success for non excluded adapter ports */
-		retval = 0;
-		break;
-	default:
-		/* dual port cards only support WoL on port A from now on
-		 * unless it was enabled in the eeprom for port B
-		 * so exclude FUNC_1 ports from having WoL enabled */
-		if (er32(STATUS) & E1000_STATUS_FUNC_1 &&
-		    !adapter->eeprom_wol) {
-			wol->supported = 0;
-			break;
-		}
-
-		retval = 0;
-	}
-
-	return retval;
-}
-
-static void e1000_get_wol(struct net_device *netdev,
-			  struct ethtool_wolinfo *wol)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	wol->supported = WAKE_UCAST | WAKE_MCAST |
-	                 WAKE_BCAST | WAKE_MAGIC;
-	wol->wolopts = 0;
-
-	/* this function will set ->supported = 0 and return 1 if wol is not
-	 * supported by this hardware */
-	if (e1000_wol_exclusion(adapter, wol) ||
-	    !device_can_wakeup(&adapter->pdev->dev))
-		return;
-
-	/* apply any specific unsupported masks here */
-	switch (hw->device_id) {
-	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
-		/* KSP3 does not suppport UCAST wake-ups */
-		wol->supported &= ~WAKE_UCAST;
-
-		if (adapter->wol & E1000_WUFC_EX)
-			e_err(drv, "Interface does not support directed "
-			      "(unicast) frame wake-up packets\n");
-		break;
-	default:
-		break;
-	}
-
-	if (adapter->wol & E1000_WUFC_EX)
-		wol->wolopts |= WAKE_UCAST;
-	if (adapter->wol & E1000_WUFC_MC)
-		wol->wolopts |= WAKE_MCAST;
-	if (adapter->wol & E1000_WUFC_BC)
-		wol->wolopts |= WAKE_BCAST;
-	if (adapter->wol & E1000_WUFC_MAG)
-		wol->wolopts |= WAKE_MAGIC;
-}
-
-static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
-		return -EOPNOTSUPP;
-
-	if (e1000_wol_exclusion(adapter, wol) ||
-	    !device_can_wakeup(&adapter->pdev->dev))
-		return wol->wolopts ? -EOPNOTSUPP : 0;
-
-	switch (hw->device_id) {
-	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
-		if (wol->wolopts & WAKE_UCAST) {
-			e_err(drv, "Interface does not support directed "
-			      "(unicast) frame wake-up packets\n");
-			return -EOPNOTSUPP;
-		}
-		break;
-	default:
-		break;
-	}
-
-	/* these settings will always override what we currently have */
-	adapter->wol = 0;
-
-	if (wol->wolopts & WAKE_UCAST)
-		adapter->wol |= E1000_WUFC_EX;
-	if (wol->wolopts & WAKE_MCAST)
-		adapter->wol |= E1000_WUFC_MC;
-	if (wol->wolopts & WAKE_BCAST)
-		adapter->wol |= E1000_WUFC_BC;
-	if (wol->wolopts & WAKE_MAGIC)
-		adapter->wol |= E1000_WUFC_MAG;
-
-	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
-
-	return 0;
-}
-
-static int e1000_set_phys_id(struct net_device *netdev,
-			     enum ethtool_phys_id_state state)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	switch (state) {
-	case ETHTOOL_ID_ACTIVE:
-		e1000_setup_led(hw);
-		return 2;
-
-	case ETHTOOL_ID_ON:
-		e1000_led_on(hw);
-		break;
-
-	case ETHTOOL_ID_OFF:
-		e1000_led_off(hw);
-		break;
-
-	case ETHTOOL_ID_INACTIVE:
-		e1000_cleanup_led(hw);
-	}
-
-	return 0;
-}
-
-static int e1000_get_coalesce(struct net_device *netdev,
-			      struct ethtool_coalesce *ec)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	if (adapter->hw.mac_type < e1000_82545)
-		return -EOPNOTSUPP;
-
-	if (adapter->itr_setting <= 4)
-		ec->rx_coalesce_usecs = adapter->itr_setting;
-	else
-		ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting;
-
-	return 0;
-}
-
-static int e1000_set_coalesce(struct net_device *netdev,
-			      struct ethtool_coalesce *ec)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	if (hw->mac_type < e1000_82545)
-		return -EOPNOTSUPP;
-
-	if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) ||
-	    ((ec->rx_coalesce_usecs > 4) &&
-	     (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) ||
-	    (ec->rx_coalesce_usecs == 2))
-		return -EINVAL;
-
-	if (ec->rx_coalesce_usecs == 4) {
-		adapter->itr = adapter->itr_setting = 4;
-	} else if (ec->rx_coalesce_usecs <= 3) {
-		adapter->itr = 20000;
-		adapter->itr_setting = ec->rx_coalesce_usecs;
-	} else {
-		adapter->itr = (1000000 / ec->rx_coalesce_usecs);
-		adapter->itr_setting = adapter->itr & ~3;
-	}
-
-	if (adapter->itr_setting != 0)
-		ew32(ITR, 1000000000 / (adapter->itr * 256));
-	else
-		ew32(ITR, 0);
-
-	return 0;
-}
-
-static int e1000_nway_reset(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	if (netif_running(netdev))
-		e1000_reinit_locked(adapter);
-	return 0;
-}
-
-static void e1000_get_ethtool_stats(struct net_device *netdev,
-				    struct ethtool_stats *stats, u64 *data)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	int i;
-	char *p = NULL;
-
-	e1000_update_stats(adapter);
-	for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
-		switch (e1000_gstrings_stats[i].type) {
-		case NETDEV_STATS:
-			p = (char *) netdev +
-					e1000_gstrings_stats[i].stat_offset;
-			break;
-		case E1000_STATS:
-			p = (char *) adapter +
-					e1000_gstrings_stats[i].stat_offset;
-			break;
-		}
-
-		data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
-			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
-	}
-/*	BUG_ON(i != E1000_STATS_LEN); */
-}
-
-static void e1000_get_strings(struct net_device *netdev, u32 stringset,
-			      u8 *data)
-{
-	u8 *p = data;
-	int i;
-
-	switch (stringset) {
-	case ETH_SS_TEST:
-		memcpy(data, *e1000_gstrings_test,
-			sizeof(e1000_gstrings_test));
-		break;
-	case ETH_SS_STATS:
-		for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
-			memcpy(p, e1000_gstrings_stats[i].stat_string,
-			       ETH_GSTRING_LEN);
-			p += ETH_GSTRING_LEN;
-		}
-/*		BUG_ON(p - data != E1000_STATS_LEN * ETH_GSTRING_LEN); */
-		break;
-	}
-}
-
-static const struct ethtool_ops e1000_ethtool_ops = {
-	.get_settings           = e1000_get_settings,
-	.set_settings           = e1000_set_settings,
-	.get_drvinfo            = e1000_get_drvinfo,
-	.get_regs_len           = e1000_get_regs_len,
-	.get_regs               = e1000_get_regs,
-	.get_wol                = e1000_get_wol,
-	.set_wol                = e1000_set_wol,
-	.get_msglevel           = e1000_get_msglevel,
-	.set_msglevel           = e1000_set_msglevel,
-	.nway_reset             = e1000_nway_reset,
-	.get_link               = e1000_get_link,
-	.get_eeprom_len         = e1000_get_eeprom_len,
-	.get_eeprom             = e1000_get_eeprom,
-	.set_eeprom             = e1000_set_eeprom,
-	.get_ringparam          = e1000_get_ringparam,
-	.set_ringparam          = e1000_set_ringparam,
-	.get_pauseparam         = e1000_get_pauseparam,
-	.set_pauseparam         = e1000_set_pauseparam,
-	.self_test              = e1000_diag_test,
-	.get_strings            = e1000_get_strings,
-	.set_phys_id            = e1000_set_phys_id,
-	.get_ethtool_stats      = e1000_get_ethtool_stats,
-	.get_sset_count         = e1000_get_sset_count,
-	.get_coalesce           = e1000_get_coalesce,
-	.set_coalesce           = e1000_set_coalesce,
-};
-
-void e1000_set_ethtool_ops(struct net_device *netdev)
-{
-	SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/e1000/e1000.h linux-libre-3.2-gnu/drivers/net/e1000/e1000.h
--- linux-libre-3.1-gnu/drivers/net/e1000/e1000.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000/e1000.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,361 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2006 Intel Corporation.
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms and conditions of the GNU General Public License,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-
-/* Linux PRO/1000 Ethernet Driver main header file */
-
-#ifndef _E1000_H_
-#define _E1000_H_
-
-#include <linux/stddef.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <asm/byteorder.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/interrupt.h>
-#include <linux/string.h>
-#include <linux/pagemap.h>
-#include <linux/dma-mapping.h>
-#include <linux/bitops.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <linux/capability.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
-#include <net/pkt_sched.h>
-#include <linux/list.h>
-#include <linux/reboot.h>
-#include <net/checksum.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/if_vlan.h>
-
-#define BAR_0		0
-#define BAR_1		1
-#define BAR_5		5
-
-#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
-	PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
-
-struct e1000_adapter;
-
-#include "e1000_hw.h"
-
-#define E1000_MAX_INTR 10
-
-/* TX/RX descriptor defines */
-#define E1000_DEFAULT_TXD                  256
-#define E1000_MAX_TXD                      256
-#define E1000_MIN_TXD                       48
-#define E1000_MAX_82544_TXD               4096
-
-#define E1000_DEFAULT_RXD                  256
-#define E1000_MAX_RXD                      256
-#define E1000_MIN_RXD                       48
-#define E1000_MAX_82544_RXD               4096
-
-#define E1000_MIN_ITR_USECS		10 /* 100000 irq/sec */
-#define E1000_MAX_ITR_USECS		10000 /* 100    irq/sec */
-
-/* this is the size past which hardware will drop packets when setting LPE=0 */
-#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
-
-/* Supported Rx Buffer Sizes */
-#define E1000_RXBUFFER_128   128    /* Used for packet split */
-#define E1000_RXBUFFER_256   256    /* Used for packet split */
-#define E1000_RXBUFFER_512   512
-#define E1000_RXBUFFER_1024  1024
-#define E1000_RXBUFFER_2048  2048
-#define E1000_RXBUFFER_4096  4096
-#define E1000_RXBUFFER_8192  8192
-#define E1000_RXBUFFER_16384 16384
-
-/* SmartSpeed delimiters */
-#define E1000_SMARTSPEED_DOWNSHIFT 3
-#define E1000_SMARTSPEED_MAX       15
-
-/* Packet Buffer allocations */
-#define E1000_PBA_BYTES_SHIFT 0xA
-#define E1000_TX_HEAD_ADDR_SHIFT 7
-#define E1000_PBA_TX_MASK 0xFFFF0000
-
-/* Flow Control Watermarks */
-#define E1000_FC_HIGH_DIFF 0x1638  /* High: 5688 bytes below Rx FIFO size */
-#define E1000_FC_LOW_DIFF 0x1640   /* Low:  5696 bytes below Rx FIFO size */
-
-#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
-
-/* How many Tx Descriptors do we need to call netif_wake_queue ? */
-#define E1000_TX_QUEUE_WAKE	16
-/* How many Rx Buffers do we bundle into one write to the hardware ? */
-#define E1000_RX_BUFFER_WRITE	16	/* Must be power of 2 */
-
-#define AUTO_ALL_MODES            0
-#define E1000_EEPROM_82544_APM    0x0004
-#define E1000_EEPROM_APME         0x0400
-
-#ifndef E1000_MASTER_SLAVE
-/* Switch to override PHY master/slave setting */
-#define E1000_MASTER_SLAVE	e1000_ms_hw_default
-#endif
-
-#define E1000_MNG_VLAN_NONE (-1)
-
-/* wrapper around a pointer to a socket buffer,
- * so a DMA handle can be stored along with the buffer */
-struct e1000_buffer {
-	struct sk_buff *skb;
-	dma_addr_t dma;
-	struct page *page;
-	unsigned long time_stamp;
-	u16 length;
-	u16 next_to_watch;
-	u16 mapped_as_page;
-};
-
-struct e1000_tx_ring {
-	/* pointer to the descriptor ring memory */
-	void *desc;
-	/* physical address of the descriptor ring */
-	dma_addr_t dma;
-	/* length of descriptor ring in bytes */
-	unsigned int size;
-	/* number of descriptors in the ring */
-	unsigned int count;
-	/* next descriptor to associate a buffer with */
-	unsigned int next_to_use;
-	/* next descriptor to check for DD status bit */
-	unsigned int next_to_clean;
-	/* array of buffer information structs */
-	struct e1000_buffer *buffer_info;
-
-	u16 tdh;
-	u16 tdt;
-	bool last_tx_tso;
-};
-
-struct e1000_rx_ring {
-	/* pointer to the descriptor ring memory */
-	void *desc;
-	/* physical address of the descriptor ring */
-	dma_addr_t dma;
-	/* length of descriptor ring in bytes */
-	unsigned int size;
-	/* number of descriptors in the ring */
-	unsigned int count;
-	/* next descriptor to associate a buffer with */
-	unsigned int next_to_use;
-	/* next descriptor to check for DD status bit */
-	unsigned int next_to_clean;
-	/* array of buffer information structs */
-	struct e1000_buffer *buffer_info;
-	struct sk_buff *rx_skb_top;
-
-	/* cpu for rx queue */
-	int cpu;
-
-	u16 rdh;
-	u16 rdt;
-};
-
-#define E1000_DESC_UNUSED(R)						\
-	((((R)->next_to_clean > (R)->next_to_use)			\
-	  ? 0 : (R)->count) + (R)->next_to_clean - (R)->next_to_use - 1)
-
-#define E1000_RX_DESC_EXT(R, i)						\
-	(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
-#define E1000_GET_DESC(R, i, type)	(&(((struct type *)((R).desc))[i]))
-#define E1000_RX_DESC(R, i)		E1000_GET_DESC(R, i, e1000_rx_desc)
-#define E1000_TX_DESC(R, i)		E1000_GET_DESC(R, i, e1000_tx_desc)
-#define E1000_CONTEXT_DESC(R, i)	E1000_GET_DESC(R, i, e1000_context_desc)
-
-/* board specific private data structure */
-
-struct e1000_adapter {
-	struct timer_list tx_fifo_stall_timer;
-	struct timer_list watchdog_timer;
-	struct timer_list phy_info_timer;
-	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
-	u16 mng_vlan_id;
-	u32 bd_number;
-	u32 rx_buffer_len;
-	u32 wol;
-	u32 smartspeed;
-	u32 en_mng_pt;
-	u16 link_speed;
-	u16 link_duplex;
-	spinlock_t stats_lock;
-	unsigned int total_tx_bytes;
-	unsigned int total_tx_packets;
-	unsigned int total_rx_bytes;
-	unsigned int total_rx_packets;
-	/* Interrupt Throttle Rate */
-	u32 itr;
-	u32 itr_setting;
-	u16 tx_itr;
-	u16 rx_itr;
-
-	struct work_struct reset_task;
-	u8 fc_autoneg;
-
-	/* TX */
-	struct e1000_tx_ring *tx_ring;      /* One per active queue */
-	unsigned int restart_queue;
-	u32 txd_cmd;
-	u32 tx_int_delay;
-	u32 tx_abs_int_delay;
-	u32 gotcl;
-	u64 gotcl_old;
-	u64 tpt_old;
-	u64 colc_old;
-	u32 tx_timeout_count;
-	u32 tx_fifo_head;
-	u32 tx_head_addr;
-	u32 tx_fifo_size;
-	u8  tx_timeout_factor;
-	atomic_t tx_fifo_stall;
-	bool pcix_82544;
-	bool detect_tx_hung;
-
-	/* RX */
-	bool (*clean_rx)(struct e1000_adapter *adapter,
-			 struct e1000_rx_ring *rx_ring,
-			 int *work_done, int work_to_do);
-	void (*alloc_rx_buf)(struct e1000_adapter *adapter,
-			     struct e1000_rx_ring *rx_ring,
-			     int cleaned_count);
-	struct e1000_rx_ring *rx_ring;      /* One per active queue */
-	struct napi_struct napi;
-
-	int num_tx_queues;
-	int num_rx_queues;
-
-	u64 hw_csum_err;
-	u64 hw_csum_good;
-	u32 alloc_rx_buff_failed;
-	u32 rx_int_delay;
-	u32 rx_abs_int_delay;
-	bool rx_csum;
-	u32 gorcl;
-	u64 gorcl_old;
-
-	/* OS defined structs */
-	struct net_device *netdev;
-	struct pci_dev *pdev;
-
-	/* structs defined in e1000_hw.h */
-	struct e1000_hw hw;
-	struct e1000_hw_stats stats;
-	struct e1000_phy_info phy_info;
-	struct e1000_phy_stats phy_stats;
-
-	u32 test_icr;
-	struct e1000_tx_ring test_tx_ring;
-	struct e1000_rx_ring test_rx_ring;
-
-	int msg_enable;
-
-	/* to not mess up cache alignment, always add to the bottom */
-	bool tso_force;
-	bool smart_power_down;	/* phy smart power down */
-	bool quad_port_a;
-	unsigned long flags;
-	u32 eeprom_wol;
-
-	/* for ioport free */
-	int bars;
-	int need_ioport;
-
-	bool discarding;
-
-	struct work_struct fifo_stall_task;
-	struct work_struct phy_info_task;
-};
-
-enum e1000_state_t {
-	__E1000_TESTING,
-	__E1000_RESETTING,
-	__E1000_DOWN
-};
-
-#undef pr_fmt
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-extern struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
-#define e_dbg(format, arg...) \
-	netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
-#define e_err(msglvl, format, arg...) \
-	netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
-#define e_info(msglvl, format, arg...) \
-	netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
-#define e_warn(msglvl, format, arg...) \
-	netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
-#define e_notice(msglvl, format, arg...) \
-	netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
-#define e_dev_info(format, arg...) \
-	dev_info(&adapter->pdev->dev, format, ## arg)
-#define e_dev_warn(format, arg...) \
-	dev_warn(&adapter->pdev->dev, format, ## arg)
-#define e_dev_err(format, arg...) \
-	dev_err(&adapter->pdev->dev, format, ## arg)
-
-extern char e1000_driver_name[];
-extern const char e1000_driver_version[];
-
-extern int e1000_up(struct e1000_adapter *adapter);
-extern void e1000_down(struct e1000_adapter *adapter);
-extern void e1000_reinit_locked(struct e1000_adapter *adapter);
-extern void e1000_reset(struct e1000_adapter *adapter);
-extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
-extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
-extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_update_stats(struct e1000_adapter *adapter);
-extern bool e1000_has_link(struct e1000_adapter *adapter);
-extern void e1000_power_up_phy(struct e1000_adapter *);
-extern void e1000_set_ethtool_ops(struct net_device *netdev);
-extern void e1000_check_options(struct e1000_adapter *adapter);
-extern char *e1000_get_hw_dev_name(struct e1000_hw *hw);
-
-#endif /* _E1000_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/e1000/e1000_hw.c linux-libre-3.2-gnu/drivers/net/e1000/e1000_hw.c
--- linux-libre-3.1-gnu/drivers/net/e1000/e1000_hw.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000/e1000_hw.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,5830 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2006 Intel Corporation.
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms and conditions of the GNU General Public License,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
- */
-
-/* e1000_hw.c
- * Shared functions for accessing and configuring the MAC
- */
-
-#include "e1000.h"
-
-static s32 e1000_check_downshift(struct e1000_hw *hw);
-static s32 e1000_check_polarity(struct e1000_hw *hw,
-				e1000_rev_polarity *polarity);
-static void e1000_clear_hw_cntrs(struct e1000_hw *hw);
-static void e1000_clear_vfta(struct e1000_hw *hw);
-static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw,
-					      bool link_up);
-static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw);
-static s32 e1000_detect_gig_phy(struct e1000_hw *hw);
-static s32 e1000_get_auto_rd_done(struct e1000_hw *hw);
-static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
-				  u16 *max_length);
-static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw);
-static s32 e1000_id_led_init(struct e1000_hw *hw);
-static void e1000_init_rx_addrs(struct e1000_hw *hw);
-static s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
-				  struct e1000_phy_info *phy_info);
-static s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
-				  struct e1000_phy_info *phy_info);
-static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
-static s32 e1000_wait_autoneg(struct e1000_hw *hw);
-static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value);
-static s32 e1000_set_phy_type(struct e1000_hw *hw);
-static void e1000_phy_init_script(struct e1000_hw *hw);
-static s32 e1000_setup_copper_link(struct e1000_hw *hw);
-static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw);
-static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw);
-static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw);
-static s32 e1000_config_mac_to_phy(struct e1000_hw *hw);
-static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
-static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
-static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count);
-static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw);
-static s32 e1000_phy_reset_dsp(struct e1000_hw *hw);
-static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset,
-				  u16 words, u16 *data);
-static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
-					u16 words, u16 *data);
-static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw);
-static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd);
-static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd);
-static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count);
-static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
-				  u16 phy_data);
-static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
-				 u16 *phy_data);
-static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count);
-static s32 e1000_acquire_eeprom(struct e1000_hw *hw);
-static void e1000_release_eeprom(struct e1000_hw *hw);
-static void e1000_standby_eeprom(struct e1000_hw *hw);
-static s32 e1000_set_vco_speed(struct e1000_hw *hw);
-static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw);
-static s32 e1000_set_phy_mode(struct e1000_hw *hw);
-static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
-				u16 *data);
-static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
-				 u16 *data);
-
-/* IGP cable length table */
-static const
-u16 e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = {
-	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-	5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25,
-	25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40,
-	40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60,
-	60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90,
-	90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100,
-	    100,
-	100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
-	    110, 110,
-	110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120,
-	    120, 120
-};
-
-static DEFINE_SPINLOCK(e1000_eeprom_lock);
-
-/**
- * e1000_set_phy_type - Set the phy type member in the hw struct.
- * @hw: Struct containing variables accessed by shared code
- */
-static s32 e1000_set_phy_type(struct e1000_hw *hw)
-{
-	e_dbg("e1000_set_phy_type");
-
-	if (hw->mac_type == e1000_undefined)
-		return -E1000_ERR_PHY_TYPE;
-
-	switch (hw->phy_id) {
-	case M88E1000_E_PHY_ID:
-	case M88E1000_I_PHY_ID:
-	case M88E1011_I_PHY_ID:
-	case M88E1111_I_PHY_ID:
-	case M88E1118_E_PHY_ID:
-		hw->phy_type = e1000_phy_m88;
-		break;
-	case IGP01E1000_I_PHY_ID:
-		if (hw->mac_type == e1000_82541 ||
-		    hw->mac_type == e1000_82541_rev_2 ||
-		    hw->mac_type == e1000_82547 ||
-		    hw->mac_type == e1000_82547_rev_2)
-			hw->phy_type = e1000_phy_igp;
-		break;
-	case RTL8211B_PHY_ID:
-		hw->phy_type = e1000_phy_8211;
-		break;
-	case RTL8201N_PHY_ID:
-		hw->phy_type = e1000_phy_8201;
-		break;
-	default:
-		/* Should never have loaded on this device */
-		hw->phy_type = e1000_phy_undefined;
-		return -E1000_ERR_PHY_TYPE;
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_phy_init_script - IGP phy init script - initializes the GbE PHY
- * @hw: Struct containing variables accessed by shared code
- */
-static void e1000_phy_init_script(struct e1000_hw *hw)
-{
-	u32 ret_val;
-	u16 phy_saved_data;
-
-	e_dbg("e1000_phy_init_script");
-
-	if (hw->phy_init_script) {
-		msleep(20);
-
-		/* Save off the current value of register 0x2F5B to be restored at
-		 * the end of this routine. */
-		ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
-
-		/* Disabled the PHY transmitter */
-		e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
-		msleep(20);
-
-		e1000_write_phy_reg(hw, 0x0000, 0x0140);
-		msleep(5);
-
-		switch (hw->mac_type) {
-		case e1000_82541:
-		case e1000_82547:
-			e1000_write_phy_reg(hw, 0x1F95, 0x0001);
-			e1000_write_phy_reg(hw, 0x1F71, 0xBD21);
-			e1000_write_phy_reg(hw, 0x1F79, 0x0018);
-			e1000_write_phy_reg(hw, 0x1F30, 0x1600);
-			e1000_write_phy_reg(hw, 0x1F31, 0x0014);
-			e1000_write_phy_reg(hw, 0x1F32, 0x161C);
-			e1000_write_phy_reg(hw, 0x1F94, 0x0003);
-			e1000_write_phy_reg(hw, 0x1F96, 0x003F);
-			e1000_write_phy_reg(hw, 0x2010, 0x0008);
-			break;
-
-		case e1000_82541_rev_2:
-		case e1000_82547_rev_2:
-			e1000_write_phy_reg(hw, 0x1F73, 0x0099);
-			break;
-		default:
-			break;
-		}
-
-		e1000_write_phy_reg(hw, 0x0000, 0x3300);
-		msleep(20);
-
-		/* Now enable the transmitter */
-		e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
-
-		if (hw->mac_type == e1000_82547) {
-			u16 fused, fine, coarse;
-
-			/* Move to analog registers page */
-			e1000_read_phy_reg(hw,
-					   IGP01E1000_ANALOG_SPARE_FUSE_STATUS,
-					   &fused);
-
-			if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
-				e1000_read_phy_reg(hw,
-						   IGP01E1000_ANALOG_FUSE_STATUS,
-						   &fused);
-
-				fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
-				coarse =
-				    fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
-
-				if (coarse >
-				    IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
-					coarse -=
-					    IGP01E1000_ANALOG_FUSE_COARSE_10;
-					fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
-				} else if (coarse ==
-					   IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
-					fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
-
-				fused =
-				    (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |
-				    (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
-				    (coarse &
-				     IGP01E1000_ANALOG_FUSE_COARSE_MASK);
-
-				e1000_write_phy_reg(hw,
-						    IGP01E1000_ANALOG_FUSE_CONTROL,
-						    fused);
-				e1000_write_phy_reg(hw,
-						    IGP01E1000_ANALOG_FUSE_BYPASS,
-						    IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
-			}
-		}
-	}
-}
-
-/**
- * e1000_set_mac_type - Set the mac type member in the hw struct.
- * @hw: Struct containing variables accessed by shared code
- */
-s32 e1000_set_mac_type(struct e1000_hw *hw)
-{
-	e_dbg("e1000_set_mac_type");
-
-	switch (hw->device_id) {
-	case E1000_DEV_ID_82542:
-		switch (hw->revision_id) {
-		case E1000_82542_2_0_REV_ID:
-			hw->mac_type = e1000_82542_rev2_0;
-			break;
-		case E1000_82542_2_1_REV_ID:
-			hw->mac_type = e1000_82542_rev2_1;
-			break;
-		default:
-			/* Invalid 82542 revision ID */
-			return -E1000_ERR_MAC_TYPE;
-		}
-		break;
-	case E1000_DEV_ID_82543GC_FIBER:
-	case E1000_DEV_ID_82543GC_COPPER:
-		hw->mac_type = e1000_82543;
-		break;
-	case E1000_DEV_ID_82544EI_COPPER:
-	case E1000_DEV_ID_82544EI_FIBER:
-	case E1000_DEV_ID_82544GC_COPPER:
-	case E1000_DEV_ID_82544GC_LOM:
-		hw->mac_type = e1000_82544;
-		break;
-	case E1000_DEV_ID_82540EM:
-	case E1000_DEV_ID_82540EM_LOM:
-	case E1000_DEV_ID_82540EP:
-	case E1000_DEV_ID_82540EP_LOM:
-	case E1000_DEV_ID_82540EP_LP:
-		hw->mac_type = e1000_82540;
-		break;
-	case E1000_DEV_ID_82545EM_COPPER:
-	case E1000_DEV_ID_82545EM_FIBER:
-		hw->mac_type = e1000_82545;
-		break;
-	case E1000_DEV_ID_82545GM_COPPER:
-	case E1000_DEV_ID_82545GM_FIBER:
-	case E1000_DEV_ID_82545GM_SERDES:
-		hw->mac_type = e1000_82545_rev_3;
-		break;
-	case E1000_DEV_ID_82546EB_COPPER:
-	case E1000_DEV_ID_82546EB_FIBER:
-	case E1000_DEV_ID_82546EB_QUAD_COPPER:
-		hw->mac_type = e1000_82546;
-		break;
-	case E1000_DEV_ID_82546GB_COPPER:
-	case E1000_DEV_ID_82546GB_FIBER:
-	case E1000_DEV_ID_82546GB_SERDES:
-	case E1000_DEV_ID_82546GB_PCIE:
-	case E1000_DEV_ID_82546GB_QUAD_COPPER:
-	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
-		hw->mac_type = e1000_82546_rev_3;
-		break;
-	case E1000_DEV_ID_82541EI:
-	case E1000_DEV_ID_82541EI_MOBILE:
-	case E1000_DEV_ID_82541ER_LOM:
-		hw->mac_type = e1000_82541;
-		break;
-	case E1000_DEV_ID_82541ER:
-	case E1000_DEV_ID_82541GI:
-	case E1000_DEV_ID_82541GI_LF:
-	case E1000_DEV_ID_82541GI_MOBILE:
-		hw->mac_type = e1000_82541_rev_2;
-		break;
-	case E1000_DEV_ID_82547EI:
-	case E1000_DEV_ID_82547EI_MOBILE:
-		hw->mac_type = e1000_82547;
-		break;
-	case E1000_DEV_ID_82547GI:
-		hw->mac_type = e1000_82547_rev_2;
-		break;
-	case E1000_DEV_ID_INTEL_CE4100_GBE:
-		hw->mac_type = e1000_ce4100;
-		break;
-	default:
-		/* Should never have loaded on this device */
-		return -E1000_ERR_MAC_TYPE;
-	}
-
-	switch (hw->mac_type) {
-	case e1000_82541:
-	case e1000_82547:
-	case e1000_82541_rev_2:
-	case e1000_82547_rev_2:
-		hw->asf_firmware_present = true;
-		break;
-	default:
-		break;
-	}
-
-	/* The 82543 chip does not count tx_carrier_errors properly in
-	 * FD mode
-	 */
-	if (hw->mac_type == e1000_82543)
-		hw->bad_tx_carr_stats_fd = true;
-
-	if (hw->mac_type > e1000_82544)
-		hw->has_smbus = true;
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_set_media_type - Set media type and TBI compatibility.
- * @hw: Struct containing variables accessed by shared code
- */
-void e1000_set_media_type(struct e1000_hw *hw)
-{
-	u32 status;
-
-	e_dbg("e1000_set_media_type");
-
-	if (hw->mac_type != e1000_82543) {
-		/* tbi_compatibility is only valid on 82543 */
-		hw->tbi_compatibility_en = false;
-	}
-
-	switch (hw->device_id) {
-	case E1000_DEV_ID_82545GM_SERDES:
-	case E1000_DEV_ID_82546GB_SERDES:
-		hw->media_type = e1000_media_type_internal_serdes;
-		break;
-	default:
-		switch (hw->mac_type) {
-		case e1000_82542_rev2_0:
-		case e1000_82542_rev2_1:
-			hw->media_type = e1000_media_type_fiber;
-			break;
-		case e1000_ce4100:
-			hw->media_type = e1000_media_type_copper;
-			break;
-		default:
-			status = er32(STATUS);
-			if (status & E1000_STATUS_TBIMODE) {
-				hw->media_type = e1000_media_type_fiber;
-				/* tbi_compatibility not valid on fiber */
-				hw->tbi_compatibility_en = false;
-			} else {
-				hw->media_type = e1000_media_type_copper;
-			}
-			break;
-		}
-	}
-}
-
-/**
- * e1000_reset_hw: reset the hardware completely
- * @hw: Struct containing variables accessed by shared code
- *
- * Reset the transmit and receive units; mask and clear all interrupts.
- */
-s32 e1000_reset_hw(struct e1000_hw *hw)
-{
-	u32 ctrl;
-	u32 ctrl_ext;
-	u32 icr;
-	u32 manc;
-	u32 led_ctrl;
-	s32 ret_val;
-
-	e_dbg("e1000_reset_hw");
-
-	/* For 82542 (rev 2.0), disable MWI before issuing a device reset */
-	if (hw->mac_type == e1000_82542_rev2_0) {
-		e_dbg("Disabling MWI on 82542 rev 2.0\n");
-		e1000_pci_clear_mwi(hw);
-	}
-
-	/* Clear interrupt mask to stop board from generating interrupts */
-	e_dbg("Masking off all interrupts\n");
-	ew32(IMC, 0xffffffff);
-
-	/* Disable the Transmit and Receive units.  Then delay to allow
-	 * any pending transactions to complete before we hit the MAC with
-	 * the global reset.
-	 */
-	ew32(RCTL, 0);
-	ew32(TCTL, E1000_TCTL_PSP);
-	E1000_WRITE_FLUSH();
-
-	/* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
-	hw->tbi_compatibility_on = false;
-
-	/* Delay to allow any outstanding PCI transactions to complete before
-	 * resetting the device
-	 */
-	msleep(10);
-
-	ctrl = er32(CTRL);
-
-	/* Must reset the PHY before resetting the MAC */
-	if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
-		ew32(CTRL, (ctrl | E1000_CTRL_PHY_RST));
-		E1000_WRITE_FLUSH();
-		msleep(5);
-	}
-
-	/* Issue a global reset to the MAC.  This will reset the chip's
-	 * transmit, receive, DMA, and link units.  It will not effect
-	 * the current PCI configuration.  The global reset bit is self-
-	 * clearing, and should clear within a microsecond.
-	 */
-	e_dbg("Issuing a global reset to MAC\n");
-
-	switch (hw->mac_type) {
-	case e1000_82544:
-	case e1000_82540:
-	case e1000_82545:
-	case e1000_82546:
-	case e1000_82541:
-	case e1000_82541_rev_2:
-		/* These controllers can't ack the 64-bit write when issuing the
-		 * reset, so use IO-mapping as a workaround to issue the reset */
-		E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST));
-		break;
-	case e1000_82545_rev_3:
-	case e1000_82546_rev_3:
-		/* Reset is performed on a shadow of the control register */
-		ew32(CTRL_DUP, (ctrl | E1000_CTRL_RST));
-		break;
-	case e1000_ce4100:
-	default:
-		ew32(CTRL, (ctrl | E1000_CTRL_RST));
-		break;
-	}
-
-	/* After MAC reset, force reload of EEPROM to restore power-on settings to
-	 * device.  Later controllers reload the EEPROM automatically, so just wait
-	 * for reload to complete.
-	 */
-	switch (hw->mac_type) {
-	case e1000_82542_rev2_0:
-	case e1000_82542_rev2_1:
-	case e1000_82543:
-	case e1000_82544:
-		/* Wait for reset to complete */
-		udelay(10);
-		ctrl_ext = er32(CTRL_EXT);
-		ctrl_ext |= E1000_CTRL_EXT_EE_RST;
-		ew32(CTRL_EXT, ctrl_ext);
-		E1000_WRITE_FLUSH();
-		/* Wait for EEPROM reload */
-		msleep(2);
-		break;
-	case e1000_82541:
-	case e1000_82541_rev_2:
-	case e1000_82547:
-	case e1000_82547_rev_2:
-		/* Wait for EEPROM reload */
-		msleep(20);
-		break;
-	default:
-		/* Auto read done will delay 5ms or poll based on mac type */
-		ret_val = e1000_get_auto_rd_done(hw);
-		if (ret_val)
-			return ret_val;
-		break;
-	}
-
-	/* Disable HW ARPs on ASF enabled adapters */
-	if (hw->mac_type >= e1000_82540) {
-		manc = er32(MANC);
-		manc &= ~(E1000_MANC_ARP_EN);
-		ew32(MANC, manc);
-	}
-
-	if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
-		e1000_phy_init_script(hw);
-
-		/* Configure activity LED after PHY reset */
-		led_ctrl = er32(LEDCTL);
-		led_ctrl &= IGP_ACTIVITY_LED_MASK;
-		led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
-		ew32(LEDCTL, led_ctrl);
-	}
-
-	/* Clear interrupt mask to stop board from generating interrupts */
-	e_dbg("Masking off all interrupts\n");
-	ew32(IMC, 0xffffffff);
-
-	/* Clear any pending interrupt events. */
-	icr = er32(ICR);
-
-	/* If MWI was previously enabled, reenable it. */
-	if (hw->mac_type == e1000_82542_rev2_0) {
-		if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
-			e1000_pci_set_mwi(hw);
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_init_hw: Performs basic configuration of the adapter.
- * @hw: Struct containing variables accessed by shared code
- *
- * Assumes that the controller has previously been reset and is in a
- * post-reset uninitialized state. Initializes the receive address registers,
- * multicast table, and VLAN filter table. Calls routines to setup link
- * configuration and flow control settings. Clears all on-chip counters. Leaves
- * the transmit and receive units disabled and uninitialized.
- */
-s32 e1000_init_hw(struct e1000_hw *hw)
-{
-	u32 ctrl;
-	u32 i;
-	s32 ret_val;
-	u32 mta_size;
-	u32 ctrl_ext;
-
-	e_dbg("e1000_init_hw");
-
-	/* Initialize Identification LED */
-	ret_val = e1000_id_led_init(hw);
-	if (ret_val) {
-		e_dbg("Error Initializing Identification LED\n");
-		return ret_val;
-	}
-
-	/* Set the media type and TBI compatibility */
-	e1000_set_media_type(hw);
-
-	/* Disabling VLAN filtering. */
-	e_dbg("Initializing the IEEE VLAN\n");
-	if (hw->mac_type < e1000_82545_rev_3)
-		ew32(VET, 0);
-	e1000_clear_vfta(hw);
-
-	/* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
-	if (hw->mac_type == e1000_82542_rev2_0) {
-		e_dbg("Disabling MWI on 82542 rev 2.0\n");
-		e1000_pci_clear_mwi(hw);
-		ew32(RCTL, E1000_RCTL_RST);
-		E1000_WRITE_FLUSH();
-		msleep(5);
-	}
-
-	/* Setup the receive address. This involves initializing all of the Receive
-	 * Address Registers (RARs 0 - 15).
-	 */
-	e1000_init_rx_addrs(hw);
-
-	/* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
-	if (hw->mac_type == e1000_82542_rev2_0) {
-		ew32(RCTL, 0);
-		E1000_WRITE_FLUSH();
-		msleep(1);
-		if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
-			e1000_pci_set_mwi(hw);
-	}
-
-	/* Zero out the Multicast HASH table */
-	e_dbg("Zeroing the MTA\n");
-	mta_size = E1000_MC_TBL_SIZE;
-	for (i = 0; i < mta_size; i++) {
-		E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
-		/* use write flush to prevent Memory Write Block (MWB) from
-		 * occurring when accessing our register space */
-		E1000_WRITE_FLUSH();
-	}
-
-	/* Set the PCI priority bit correctly in the CTRL register.  This
-	 * determines if the adapter gives priority to receives, or if it
-	 * gives equal priority to transmits and receives.  Valid only on
-	 * 82542 and 82543 silicon.
-	 */
-	if (hw->dma_fairness && hw->mac_type <= e1000_82543) {
-		ctrl = er32(CTRL);
-		ew32(CTRL, ctrl | E1000_CTRL_PRIOR);
-	}
-
-	switch (hw->mac_type) {
-	case e1000_82545_rev_3:
-	case e1000_82546_rev_3:
-		break;
-	default:
-		/* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */
-		if (hw->bus_type == e1000_bus_type_pcix
-		    && e1000_pcix_get_mmrbc(hw) > 2048)
-			e1000_pcix_set_mmrbc(hw, 2048);
-		break;
-	}
-
-	/* Call a subroutine to configure the link and setup flow control. */
-	ret_val = e1000_setup_link(hw);
-
-	/* Set the transmit descriptor write-back policy */
-	if (hw->mac_type > e1000_82544) {
-		ctrl = er32(TXDCTL);
-		ctrl =
-		    (ctrl & ~E1000_TXDCTL_WTHRESH) |
-		    E1000_TXDCTL_FULL_TX_DESC_WB;
-		ew32(TXDCTL, ctrl);
-	}
-
-	/* Clear all of the statistics registers (clear on read).  It is
-	 * important that we do this after we have tried to establish link
-	 * because the symbol error count will increment wildly if there
-	 * is no link.
-	 */
-	e1000_clear_hw_cntrs(hw);
-
-	if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
-	    hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) {
-		ctrl_ext = er32(CTRL_EXT);
-		/* Relaxed ordering must be disabled to avoid a parity
-		 * error crash in a PCI slot. */
-		ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
-		ew32(CTRL_EXT, ctrl_ext);
-	}
-
-	return ret_val;
-}
-
-/**
- * e1000_adjust_serdes_amplitude - Adjust SERDES output amplitude based on EEPROM setting.
- * @hw: Struct containing variables accessed by shared code.
- */
-static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
-{
-	u16 eeprom_data;
-	s32 ret_val;
-
-	e_dbg("e1000_adjust_serdes_amplitude");
-
-	if (hw->media_type != e1000_media_type_internal_serdes)
-		return E1000_SUCCESS;
-
-	switch (hw->mac_type) {
-	case e1000_82545_rev_3:
-	case e1000_82546_rev_3:
-		break;
-	default:
-		return E1000_SUCCESS;
-	}
-
-	ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1,
-	                            &eeprom_data);
-	if (ret_val) {
-		return ret_val;
-	}
-
-	if (eeprom_data != EEPROM_RESERVED_WORD) {
-		/* Adjust SERDES output amplitude only. */
-		eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK;
-		ret_val =
-		    e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, eeprom_data);
-		if (ret_val)
-			return ret_val;
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_setup_link - Configures flow control and link settings.
- * @hw: Struct containing variables accessed by shared code
- *
- * Determines which flow control settings to use. Calls the appropriate media-
- * specific link configuration function. Configures the flow control settings.
- * Assuming the adapter has a valid link partner, a valid link should be
- * established. Assumes the hardware has previously been reset and the
- * transmitter and receiver are not enabled.
- */
-s32 e1000_setup_link(struct e1000_hw *hw)
-{
-	u32 ctrl_ext;
-	s32 ret_val;
-	u16 eeprom_data;
-
-	e_dbg("e1000_setup_link");
-
-	/* Read and store word 0x0F of the EEPROM. This word contains bits
-	 * that determine the hardware's default PAUSE (flow control) mode,
-	 * a bit that determines whether the HW defaults to enabling or
-	 * disabling auto-negotiation, and the direction of the
-	 * SW defined pins. If there is no SW over-ride of the flow
-	 * control setting, then the variable hw->fc will
-	 * be initialized based on a value in the EEPROM.
-	 */
-	if (hw->fc == E1000_FC_DEFAULT) {
-		ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
-					    1, &eeprom_data);
-		if (ret_val) {
-			e_dbg("EEPROM Read Error\n");
-			return -E1000_ERR_EEPROM;
-		}
-		if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
-			hw->fc = E1000_FC_NONE;
-		else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
-			 EEPROM_WORD0F_ASM_DIR)
-			hw->fc = E1000_FC_TX_PAUSE;
-		else
-			hw->fc = E1000_FC_FULL;
-	}
-
-	/* We want to save off the original Flow Control configuration just
-	 * in case we get disconnected and then reconnected into a different
-	 * hub or switch with different Flow Control capabilities.
-	 */
-	if (hw->mac_type == e1000_82542_rev2_0)
-		hw->fc &= (~E1000_FC_TX_PAUSE);
-
-	if ((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1))
-		hw->fc &= (~E1000_FC_RX_PAUSE);
-
-	hw->original_fc = hw->fc;
-
-	e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc);
-
-	/* Take the 4 bits from EEPROM word 0x0F that determine the initial
-	 * polarity value for the SW controlled pins, and setup the
-	 * Extended Device Control reg with that info.
-	 * This is needed because one of the SW controlled pins is used for
-	 * signal detection.  So this should be done before e1000_setup_pcs_link()
-	 * or e1000_phy_setup() is called.
-	 */
-	if (hw->mac_type == e1000_82543) {
-		ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
-					    1, &eeprom_data);
-		if (ret_val) {
-			e_dbg("EEPROM Read Error\n");
-			return -E1000_ERR_EEPROM;
-		}
-		ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) <<
-			    SWDPIO__EXT_SHIFT);
-		ew32(CTRL_EXT, ctrl_ext);
-	}
-
-	/* Call the necessary subroutine to configure the link. */
-	ret_val = (hw->media_type == e1000_media_type_copper) ?
-	    e1000_setup_copper_link(hw) : e1000_setup_fiber_serdes_link(hw);
-
-	/* Initialize the flow control address, type, and PAUSE timer
-	 * registers to their default values.  This is done even if flow
-	 * control is disabled, because it does not hurt anything to
-	 * initialize these registers.
-	 */
-	e_dbg("Initializing the Flow Control address, type and timer regs\n");
-
-	ew32(FCT, FLOW_CONTROL_TYPE);
-	ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH);
-	ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW);
-
-	ew32(FCTTV, hw->fc_pause_time);
-
-	/* Set the flow control receive threshold registers.  Normally,
-	 * these registers will be set to a default threshold that may be
-	 * adjusted later by the driver's runtime code.  However, if the
-	 * ability to transmit pause frames in not enabled, then these
-	 * registers will be set to 0.
-	 */
-	if (!(hw->fc & E1000_FC_TX_PAUSE)) {
-		ew32(FCRTL, 0);
-		ew32(FCRTH, 0);
-	} else {
-		/* We need to set up the Receive Threshold high and low water marks
-		 * as well as (optionally) enabling the transmission of XON frames.
-		 */
-		if (hw->fc_send_xon) {
-			ew32(FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE));
-			ew32(FCRTH, hw->fc_high_water);
-		} else {
-			ew32(FCRTL, hw->fc_low_water);
-			ew32(FCRTH, hw->fc_high_water);
-		}
-	}
-	return ret_val;
-}
-
-/**
- * e1000_setup_fiber_serdes_link - prepare fiber or serdes link
- * @hw: Struct containing variables accessed by shared code
- *
- * Manipulates Physical Coding Sublayer functions in order to configure
- * link. Assumes the hardware has been previously reset and the transmitter
- * and receiver are not enabled.
- */
-static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
-{
-	u32 ctrl;
-	u32 status;
-	u32 txcw = 0;
-	u32 i;
-	u32 signal = 0;
-	s32 ret_val;
-
-	e_dbg("e1000_setup_fiber_serdes_link");
-
-	/* On adapters with a MAC newer than 82544, SWDP 1 will be
-	 * set when the optics detect a signal. On older adapters, it will be
-	 * cleared when there is a signal.  This applies to fiber media only.
-	 * If we're on serdes media, adjust the output amplitude to value
-	 * set in the EEPROM.
-	 */
-	ctrl = er32(CTRL);
-	if (hw->media_type == e1000_media_type_fiber)
-		signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
-
-	ret_val = e1000_adjust_serdes_amplitude(hw);
-	if (ret_val)
-		return ret_val;
-
-	/* Take the link out of reset */
-	ctrl &= ~(E1000_CTRL_LRST);
-
-	/* Adjust VCO speed to improve BER performance */
-	ret_val = e1000_set_vco_speed(hw);
-	if (ret_val)
-		return ret_val;
-
-	e1000_config_collision_dist(hw);
-
-	/* Check for a software override of the flow control settings, and setup
-	 * the device accordingly.  If auto-negotiation is enabled, then software
-	 * will have to set the "PAUSE" bits to the correct value in the Tranmsit
-	 * Config Word Register (TXCW) and re-start auto-negotiation.  However, if
-	 * auto-negotiation is disabled, then software will have to manually
-	 * configure the two flow control enable bits in the CTRL register.
-	 *
-	 * The possible values of the "fc" parameter 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.
-	 */
-	switch (hw->fc) {
-	case E1000_FC_NONE:
-		/* Flow control is completely disabled by a software over-ride. */
-		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
-		break;
-	case E1000_FC_RX_PAUSE:
-		/* RX Flow control is enabled and TX Flow control is disabled by a
-		 * software over-ride. 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.
-		 */
-		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
-		break;
-	case E1000_FC_TX_PAUSE:
-		/* TX Flow control is enabled, and RX Flow control is disabled, by a
-		 * software over-ride.
-		 */
-		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
-		break;
-	case E1000_FC_FULL:
-		/* Flow control (both RX and TX) is enabled by a software over-ride. */
-		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
-		break;
-	default:
-		e_dbg("Flow control param set incorrectly\n");
-		return -E1000_ERR_CONFIG;
-		break;
-	}
-
-	/* Since auto-negotiation is enabled, take the link out of reset (the link
-	 * will be in reset, because we previously reset the chip). This will
-	 * restart auto-negotiation.  If auto-negotiation is successful then the
-	 * link-up status bit will be set and the flow control enable bits (RFCE
-	 * and TFCE) will be set according to their negotiated value.
-	 */
-	e_dbg("Auto-negotiation enabled\n");
-
-	ew32(TXCW, txcw);
-	ew32(CTRL, ctrl);
-	E1000_WRITE_FLUSH();
-
-	hw->txcw = txcw;
-	msleep(1);
-
-	/* If we have a signal (the cable is plugged in) then poll for a "Link-Up"
-	 * indication in the Device Status Register.  Time-out if a link isn't
-	 * seen in 500 milliseconds seconds (Auto-negotiation should complete in
-	 * less than 500 milliseconds even if the other end is doing it in SW).
-	 * For internal serdes, we just assume a signal is present, then poll.
-	 */
-	if (hw->media_type == e1000_media_type_internal_serdes ||
-	    (er32(CTRL) & E1000_CTRL_SWDPIN1) == signal) {
-		e_dbg("Looking for Link\n");
-		for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
-			msleep(10);
-			status = er32(STATUS);
-			if (status & E1000_STATUS_LU)
-				break;
-		}
-		if (i == (LINK_UP_TIMEOUT / 10)) {
-			e_dbg("Never got a valid link from auto-neg!!!\n");
-			hw->autoneg_failed = 1;
-			/* AutoNeg failed to achieve a link, so we'll call
-			 * e1000_check_for_link. This routine will force the link up if
-			 * we detect a signal. This will allow us to communicate with
-			 * non-autonegotiating link partners.
-			 */
-			ret_val = e1000_check_for_link(hw);
-			if (ret_val) {
-				e_dbg("Error while checking for link\n");
-				return ret_val;
-			}
-			hw->autoneg_failed = 0;
-		} else {
-			hw->autoneg_failed = 0;
-			e_dbg("Valid Link Found\n");
-		}
-	} else {
-		e_dbg("No Signal Detected\n");
-	}
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_copper_link_rtl_setup - Copper link setup for e1000_phy_rtl series.
- * @hw: Struct containing variables accessed by shared code
- *
- * Commits changes to PHY configuration by calling e1000_phy_reset().
- */
-static s32 e1000_copper_link_rtl_setup(struct e1000_hw *hw)
-{
-	s32 ret_val;
-
-	/* SW reset the PHY so all changes take effect */
-	ret_val = e1000_phy_reset(hw);
-	if (ret_val) {
-		e_dbg("Error Resetting the PHY\n");
-		return ret_val;
-	}
-
-	return E1000_SUCCESS;
-}
-
-static s32 gbe_dhg_phy_setup(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u32 ctrl_aux;
-
-	switch (hw->phy_type) {
-	case e1000_phy_8211:
-		ret_val = e1000_copper_link_rtl_setup(hw);
-		if (ret_val) {
-			e_dbg("e1000_copper_link_rtl_setup failed!\n");
-			return ret_val;
-		}
-		break;
-	case e1000_phy_8201:
-		/* Set RMII mode */
-		ctrl_aux = er32(CTL_AUX);
-		ctrl_aux |= E1000_CTL_AUX_RMII;
-		ew32(CTL_AUX, ctrl_aux);
-		E1000_WRITE_FLUSH();
-
-		/* Disable the J/K bits required for receive */
-		ctrl_aux = er32(CTL_AUX);
-		ctrl_aux |= 0x4;
-		ctrl_aux &= ~0x2;
-		ew32(CTL_AUX, ctrl_aux);
-		E1000_WRITE_FLUSH();
-		ret_val = e1000_copper_link_rtl_setup(hw);
-
-		if (ret_val) {
-			e_dbg("e1000_copper_link_rtl_setup failed!\n");
-			return ret_val;
-		}
-		break;
-	default:
-		e_dbg("Error Resetting the PHY\n");
-		return E1000_ERR_PHY_TYPE;
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_copper_link_preconfig - early configuration for copper
- * @hw: Struct containing variables accessed by shared code
- *
- * Make sure we have a valid PHY and change PHY mode before link setup.
- */
-static s32 e1000_copper_link_preconfig(struct e1000_hw *hw)
-{
-	u32 ctrl;
-	s32 ret_val;
-	u16 phy_data;
-
-	e_dbg("e1000_copper_link_preconfig");
-
-	ctrl = er32(CTRL);
-	/* With 82543, we need to force speed and duplex on the MAC equal to what
-	 * the PHY speed and duplex configuration is. In addition, we need to
-	 * perform a hardware reset on the PHY to take it out of reset.
-	 */
-	if (hw->mac_type > e1000_82543) {
-		ctrl |= E1000_CTRL_SLU;
-		ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
-		ew32(CTRL, ctrl);
-	} else {
-		ctrl |=
-		    (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
-		ew32(CTRL, ctrl);
-		ret_val = e1000_phy_hw_reset(hw);
-		if (ret_val)
-			return ret_val;
-	}
-
-	/* Make sure we have a valid PHY */
-	ret_val = e1000_detect_gig_phy(hw);
-	if (ret_val) {
-		e_dbg("Error, did not detect valid phy.\n");
-		return ret_val;
-	}
-	e_dbg("Phy ID = %x\n", hw->phy_id);
-
-	/* Set PHY to class A mode (if necessary) */
-	ret_val = e1000_set_phy_mode(hw);
-	if (ret_val)
-		return ret_val;
-
-	if ((hw->mac_type == e1000_82545_rev_3) ||
-	    (hw->mac_type == e1000_82546_rev_3)) {
-		ret_val =
-		    e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-		phy_data |= 0x00000008;
-		ret_val =
-		    e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
-	}
-
-	if (hw->mac_type <= e1000_82543 ||
-	    hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||
-	    hw->mac_type == e1000_82541_rev_2
-	    || hw->mac_type == e1000_82547_rev_2)
-		hw->phy_reset_disable = false;
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_copper_link_igp_setup - Copper link setup for e1000_phy_igp series.
- * @hw: Struct containing variables accessed by shared code
- */
-static s32 e1000_copper_link_igp_setup(struct e1000_hw *hw)
-{
-	u32 led_ctrl;
-	s32 ret_val;
-	u16 phy_data;
-
-	e_dbg("e1000_copper_link_igp_setup");
-
-	if (hw->phy_reset_disable)
-		return E1000_SUCCESS;
-
-	ret_val = e1000_phy_reset(hw);
-	if (ret_val) {
-		e_dbg("Error Resetting the PHY\n");
-		return ret_val;
-	}
-
-	/* Wait 15ms for MAC to configure PHY from eeprom settings */
-	msleep(15);
-	/* Configure activity LED after PHY reset */
-	led_ctrl = er32(LEDCTL);
-	led_ctrl &= IGP_ACTIVITY_LED_MASK;
-	led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
-	ew32(LEDCTL, led_ctrl);
-
-	/* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */
-	if (hw->phy_type == e1000_phy_igp) {
-		/* disable lplu d3 during driver init */
-		ret_val = e1000_set_d3_lplu_state(hw, false);
-		if (ret_val) {
-			e_dbg("Error Disabling LPLU D3\n");
-			return ret_val;
-		}
-	}
-
-	/* Configure mdi-mdix settings */
-	ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
-		hw->dsp_config_state = e1000_dsp_config_disabled;
-		/* Force MDI for earlier revs of the IGP PHY */
-		phy_data &=
-		    ~(IGP01E1000_PSCR_AUTO_MDIX |
-		      IGP01E1000_PSCR_FORCE_MDI_MDIX);
-		hw->mdix = 1;
-
-	} else {
-		hw->dsp_config_state = e1000_dsp_config_enabled;
-		phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
-
-		switch (hw->mdix) {
-		case 1:
-			phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
-			break;
-		case 2:
-			phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;
-			break;
-		case 0:
-		default:
-			phy_data |= IGP01E1000_PSCR_AUTO_MDIX;
-			break;
-		}
-	}
-	ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
-	if (ret_val)
-		return ret_val;
-
-	/* set auto-master slave resolution settings */
-	if (hw->autoneg) {
-		e1000_ms_type phy_ms_setting = hw->master_slave;
-
-		if (hw->ffe_config_state == e1000_ffe_config_active)
-			hw->ffe_config_state = e1000_ffe_config_enabled;
-
-		if (hw->dsp_config_state == e1000_dsp_config_activated)
-			hw->dsp_config_state = e1000_dsp_config_enabled;
-
-		/* when autonegotiation advertisement is only 1000Mbps then we
-		 * should disable SmartSpeed and enable Auto MasterSlave
-		 * resolution as hardware default. */
-		if (hw->autoneg_advertised == ADVERTISE_1000_FULL) {
-			/* Disable SmartSpeed */
-			ret_val =
-			    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
-					       &phy_data);
-			if (ret_val)
-				return ret_val;
-			phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-			ret_val =
-			    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
-						phy_data);
-			if (ret_val)
-				return ret_val;
-			/* Set auto Master/Slave resolution process */
-			ret_val =
-			    e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
-			if (ret_val)
-				return ret_val;
-			phy_data &= ~CR_1000T_MS_ENABLE;
-			ret_val =
-			    e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
-			if (ret_val)
-				return ret_val;
-		}
-
-		ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		/* load defaults for future use */
-		hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ?
-		    ((phy_data & CR_1000T_MS_VALUE) ?
-		     e1000_ms_force_master :
-		     e1000_ms_force_slave) : e1000_ms_auto;
-
-		switch (phy_ms_setting) {
-		case e1000_ms_force_master:
-			phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
-			break;
-		case e1000_ms_force_slave:
-			phy_data |= CR_1000T_MS_ENABLE;
-			phy_data &= ~(CR_1000T_MS_VALUE);
-			break;
-		case e1000_ms_auto:
-			phy_data &= ~CR_1000T_MS_ENABLE;
-		default:
-			break;
-		}
-		ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
-		if (ret_val)
-			return ret_val;
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_copper_link_mgp_setup - Copper link setup for e1000_phy_m88 series.
- * @hw: Struct containing variables accessed by shared code
- */
-static s32 e1000_copper_link_mgp_setup(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 phy_data;
-
-	e_dbg("e1000_copper_link_mgp_setup");
-
-	if (hw->phy_reset_disable)
-		return E1000_SUCCESS;
-
-	/* Enable CRS on TX. This must be set for half-duplex operation. */
-	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
-
-	/* Options:
-	 *   MDI/MDI-X = 0 (default)
-	 *   0 - Auto for all speeds
-	 *   1 - MDI mode
-	 *   2 - MDI-X mode
-	 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
-	 */
-	phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
-
-	switch (hw->mdix) {
-	case 1:
-		phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
-		break;
-	case 2:
-		phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
-		break;
-	case 3:
-		phy_data |= M88E1000_PSCR_AUTO_X_1000T;
-		break;
-	case 0:
-	default:
-		phy_data |= M88E1000_PSCR_AUTO_X_MODE;
-		break;
-	}
-
-	/* Options:
-	 *   disable_polarity_correction = 0 (default)
-	 *       Automatic Correction for Reversed Cable Polarity
-	 *   0 - Disabled
-	 *   1 - Enabled
-	 */
-	phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
-	if (hw->disable_polarity_correction == 1)
-		phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
-	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
-	if (ret_val)
-		return ret_val;
-
-	if (hw->phy_revision < M88E1011_I_REV_4) {
-		/* Force TX_CLK in the Extended PHY Specific Control Register
-		 * to 25MHz clock.
-		 */
-		ret_val =
-		    e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
-				       &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		phy_data |= M88E1000_EPSCR_TX_CLK_25;
-
-		if ((hw->phy_revision == E1000_REVISION_2) &&
-		    (hw->phy_id == M88E1111_I_PHY_ID)) {
-			/* Vidalia Phy, set the downshift counter to 5x */
-			phy_data &= ~(M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK);
-			phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X;
-			ret_val = e1000_write_phy_reg(hw,
-						      M88E1000_EXT_PHY_SPEC_CTRL,
-						      phy_data);
-			if (ret_val)
-				return ret_val;
-		} else {
-			/* Configure Master and Slave downshift values */
-			phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
-				      M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
-			phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
-				     M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
-			ret_val = e1000_write_phy_reg(hw,
-						      M88E1000_EXT_PHY_SPEC_CTRL,
-						      phy_data);
-			if (ret_val)
-				return ret_val;
-		}
-	}
-
-	/* SW Reset the PHY so all changes take effect */
-	ret_val = e1000_phy_reset(hw);
-	if (ret_val) {
-		e_dbg("Error Resetting the PHY\n");
-		return ret_val;
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_copper_link_autoneg - setup auto-neg
- * @hw: Struct containing variables accessed by shared code
- *
- * Setup auto-negotiation and flow control advertisements,
- * and then perform auto-negotiation.
- */
-static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 phy_data;
-
-	e_dbg("e1000_copper_link_autoneg");
-
-	/* Perform some bounds checking on the hw->autoneg_advertised
-	 * parameter.  If this variable is zero, then set it to the default.
-	 */
-	hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;
-
-	/* If autoneg_advertised is zero, we assume it was not defaulted
-	 * by the calling code so we set to advertise full capability.
-	 */
-	if (hw->autoneg_advertised == 0)
-		hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
-
-	/* IFE/RTL8201N PHY only supports 10/100 */
-	if (hw->phy_type == e1000_phy_8201)
-		hw->autoneg_advertised &= AUTONEG_ADVERTISE_10_100_ALL;
-
-	e_dbg("Reconfiguring auto-neg advertisement params\n");
-	ret_val = e1000_phy_setup_autoneg(hw);
-	if (ret_val) {
-		e_dbg("Error Setting up Auto-Negotiation\n");
-		return ret_val;
-	}
-	e_dbg("Restarting Auto-Neg\n");
-
-	/* Restart auto-negotiation by setting the Auto Neg Enable bit and
-	 * the Auto Neg Restart bit in the PHY control register.
-	 */
-	ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
-	ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
-	if (ret_val)
-		return ret_val;
-
-	/* Does the user want to wait for Auto-Neg to complete here, or
-	 * check at a later time (for example, callback routine).
-	 */
-	if (hw->wait_autoneg_complete) {
-		ret_val = e1000_wait_autoneg(hw);
-		if (ret_val) {
-			e_dbg
-			    ("Error while waiting for autoneg to complete\n");
-			return ret_val;
-		}
-	}
-
-	hw->get_link_status = true;
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_copper_link_postconfig - post link setup
- * @hw: Struct containing variables accessed by shared code
- *
- * Config the MAC and the PHY after link is up.
- *   1) Set up the MAC to the current PHY speed/duplex
- *      if we are on 82543.  If we
- *      are on newer silicon, we only need to configure
- *      collision distance in the Transmit Control Register.
- *   2) Set up flow control on the MAC to that established with
- *      the link partner.
- *   3) Config DSP to improve Gigabit link quality for some PHY revisions.
- */
-static s32 e1000_copper_link_postconfig(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	e_dbg("e1000_copper_link_postconfig");
-
-	if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100)) {
-		e1000_config_collision_dist(hw);
-	} else {
-		ret_val = e1000_config_mac_to_phy(hw);
-		if (ret_val) {
-			e_dbg("Error configuring MAC to PHY settings\n");
-			return ret_val;
-		}
-	}
-	ret_val = e1000_config_fc_after_link_up(hw);
-	if (ret_val) {
-		e_dbg("Error Configuring Flow Control\n");
-		return ret_val;
-	}
-
-	/* Config DSP to improve Giga link quality */
-	if (hw->phy_type == e1000_phy_igp) {
-		ret_val = e1000_config_dsp_after_link_change(hw, true);
-		if (ret_val) {
-			e_dbg("Error Configuring DSP after link up\n");
-			return ret_val;
-		}
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_setup_copper_link - phy/speed/duplex setting
- * @hw: Struct containing variables accessed by shared code
- *
- * Detects which PHY is present and sets up the speed and duplex
- */
-static s32 e1000_setup_copper_link(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 i;
-	u16 phy_data;
-
-	e_dbg("e1000_setup_copper_link");
-
-	/* Check if it is a valid PHY and set PHY mode if necessary. */
-	ret_val = e1000_copper_link_preconfig(hw);
-	if (ret_val)
-		return ret_val;
-
-	if (hw->phy_type == e1000_phy_igp) {
-		ret_val = e1000_copper_link_igp_setup(hw);
-		if (ret_val)
-			return ret_val;
-	} else if (hw->phy_type == e1000_phy_m88) {
-		ret_val = e1000_copper_link_mgp_setup(hw);
-		if (ret_val)
-			return ret_val;
-	} else {
-		ret_val = gbe_dhg_phy_setup(hw);
-		if (ret_val) {
-			e_dbg("gbe_dhg_phy_setup failed!\n");
-			return ret_val;
-		}
-	}
-
-	if (hw->autoneg) {
-		/* Setup autoneg and flow control advertisement
-		 * and perform autonegotiation */
-		ret_val = e1000_copper_link_autoneg(hw);
-		if (ret_val)
-			return ret_val;
-	} else {
-		/* PHY will be set to 10H, 10F, 100H,or 100F
-		 * depending on value from forced_speed_duplex. */
-		e_dbg("Forcing speed and duplex\n");
-		ret_val = e1000_phy_force_speed_duplex(hw);
-		if (ret_val) {
-			e_dbg("Error Forcing Speed and Duplex\n");
-			return ret_val;
-		}
-	}
-
-	/* Check link status. Wait up to 100 microseconds for link to become
-	 * valid.
-	 */
-	for (i = 0; i < 10; i++) {
-		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-		if (ret_val)
-			return ret_val;
-		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		if (phy_data & MII_SR_LINK_STATUS) {
-			/* Config the MAC and PHY after link is up */
-			ret_val = e1000_copper_link_postconfig(hw);
-			if (ret_val)
-				return ret_val;
-
-			e_dbg("Valid link established!!!\n");
-			return E1000_SUCCESS;
-		}
-		udelay(10);
-	}
-
-	e_dbg("Unable to establish link!!!\n");
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_phy_setup_autoneg - phy settings
- * @hw: Struct containing variables accessed by shared code
- *
- * Configures PHY autoneg and flow control advertisement settings
- */
-s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 mii_autoneg_adv_reg;
-	u16 mii_1000t_ctrl_reg;
-
-	e_dbg("e1000_phy_setup_autoneg");
-
-	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
-	ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
-	if (ret_val)
-		return ret_val;
-
-	/* Read the MII 1000Base-T Control Register (Address 9). */
-	ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
-	if (ret_val)
-		return ret_val;
-	else if (hw->phy_type == e1000_phy_8201)
-		mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;
-
-	/* Need to parse both autoneg_advertised and fc and set up
-	 * the appropriate PHY registers.  First we will parse for
-	 * autoneg_advertised software override.  Since we can advertise
-	 * a plethora of combinations, we need to check each bit
-	 * individually.
-	 */
-
-	/* First we clear all the 10/100 mb speed bits in the Auto-Neg
-	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
-	 * the  1000Base-T Control Register (Address 9).
-	 */
-	mii_autoneg_adv_reg &= ~REG4_SPEED_MASK;
-	mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;
-
-	e_dbg("autoneg_advertised %x\n", hw->autoneg_advertised);
-
-	/* Do we want to advertise 10 Mb Half Duplex? */
-	if (hw->autoneg_advertised & ADVERTISE_10_HALF) {
-		e_dbg("Advertise 10mb Half duplex\n");
-		mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
-	}
-
-	/* Do we want to advertise 10 Mb Full Duplex? */
-	if (hw->autoneg_advertised & ADVERTISE_10_FULL) {
-		e_dbg("Advertise 10mb Full duplex\n");
-		mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
-	}
-
-	/* Do we want to advertise 100 Mb Half Duplex? */
-	if (hw->autoneg_advertised & ADVERTISE_100_HALF) {
-		e_dbg("Advertise 100mb Half duplex\n");
-		mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
-	}
-
-	/* Do we want to advertise 100 Mb Full Duplex? */
-	if (hw->autoneg_advertised & ADVERTISE_100_FULL) {
-		e_dbg("Advertise 100mb Full duplex\n");
-		mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
-	}
-
-	/* We do not allow the Phy to advertise 1000 Mb Half Duplex */
-	if (hw->autoneg_advertised & ADVERTISE_1000_HALF) {
-		e_dbg
-		    ("Advertise 1000mb Half duplex requested, request denied!\n");
-	}
-
-	/* Do we want to advertise 1000 Mb Full Duplex? */
-	if (hw->autoneg_advertised & ADVERTISE_1000_FULL) {
-		e_dbg("Advertise 1000mb Full duplex\n");
-		mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
-	}
-
-	/* Check for a software override of the flow control settings, and
-	 * setup the PHY advertisement registers accordingly.  If
-	 * auto-negotiation is enabled, then software will have to set the
-	 * "PAUSE" bits to the correct value in the Auto-Negotiation
-	 * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-negotiation.
-	 *
-	 * The possible values of the "fc" parameter 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:  No software override.  The flow control configuration
-	 *          in the EEPROM is used.
-	 */
-	switch (hw->fc) {
-	case E1000_FC_NONE:	/* 0 */
-		/* Flow control (RX & TX) is completely disabled by a
-		 * software over-ride.
-		 */
-		mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
-		break;
-	case E1000_FC_RX_PAUSE:	/* 1 */
-		/* RX Flow control is enabled, and TX Flow control is
-		 * disabled, by a software over-ride.
-		 */
-		/* 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
-		 * (in e1000_config_fc_after_link_up) we will disable the
-		 *hw's ability to send PAUSE frames.
-		 */
-		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
-		break;
-	case E1000_FC_TX_PAUSE:	/* 2 */
-		/* TX Flow control is enabled, and RX Flow control is
-		 * disabled, by a software over-ride.
-		 */
-		mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
-		mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
-		break;
-	case E1000_FC_FULL:	/* 3 */
-		/* Flow control (both RX and TX) is enabled by a software
-		 * over-ride.
-		 */
-		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
-		break;
-	default:
-		e_dbg("Flow control param set incorrectly\n");
-		return -E1000_ERR_CONFIG;
-	}
-
-	ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
-	if (ret_val)
-		return ret_val;
-
-	e_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
-
-	if (hw->phy_type == e1000_phy_8201) {
-		mii_1000t_ctrl_reg = 0;
-	} else {
-		ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL,
-		                              mii_1000t_ctrl_reg);
-		if (ret_val)
-			return ret_val;
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_phy_force_speed_duplex - force link settings
- * @hw: Struct containing variables accessed by shared code
- *
- * Force PHY speed and duplex settings to hw->forced_speed_duplex
- */
-static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
-{
-	u32 ctrl;
-	s32 ret_val;
-	u16 mii_ctrl_reg;
-	u16 mii_status_reg;
-	u16 phy_data;
-	u16 i;
-
-	e_dbg("e1000_phy_force_speed_duplex");
-
-	/* Turn off Flow control if we are forcing speed and duplex. */
-	hw->fc = E1000_FC_NONE;
-
-	e_dbg("hw->fc = %d\n", hw->fc);
-
-	/* Read the Device Control Register. */
-	ctrl = er32(CTRL);
-
-	/* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */
-	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
-	ctrl &= ~(DEVICE_SPEED_MASK);
-
-	/* Clear the Auto Speed Detect Enable bit. */
-	ctrl &= ~E1000_CTRL_ASDE;
-
-	/* Read the MII Control Register. */
-	ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg);
-	if (ret_val)
-		return ret_val;
-
-	/* We need to disable autoneg in order to force link and duplex. */
-
-	mii_ctrl_reg &= ~MII_CR_AUTO_NEG_EN;
-
-	/* Are we forcing Full or Half Duplex? */
-	if (hw->forced_speed_duplex == e1000_100_full ||
-	    hw->forced_speed_duplex == e1000_10_full) {
-		/* We want to force full duplex so we SET the full duplex bits in the
-		 * Device and MII Control Registers.
-		 */
-		ctrl |= E1000_CTRL_FD;
-		mii_ctrl_reg |= MII_CR_FULL_DUPLEX;
-		e_dbg("Full Duplex\n");
-	} else {
-		/* We want to force half duplex so we CLEAR the full duplex bits in
-		 * the Device and MII Control Registers.
-		 */
-		ctrl &= ~E1000_CTRL_FD;
-		mii_ctrl_reg &= ~MII_CR_FULL_DUPLEX;
-		e_dbg("Half Duplex\n");
-	}
-
-	/* Are we forcing 100Mbps??? */
-	if (hw->forced_speed_duplex == e1000_100_full ||
-	    hw->forced_speed_duplex == e1000_100_half) {
-		/* Set the 100Mb bit and turn off the 1000Mb and 10Mb bits. */
-		ctrl |= E1000_CTRL_SPD_100;
-		mii_ctrl_reg |= MII_CR_SPEED_100;
-		mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10);
-		e_dbg("Forcing 100mb ");
-	} else {
-		/* Set the 10Mb bit and turn off the 1000Mb and 100Mb bits. */
-		ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
-		mii_ctrl_reg |= MII_CR_SPEED_10;
-		mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
-		e_dbg("Forcing 10mb ");
-	}
-
-	e1000_config_collision_dist(hw);
-
-	/* Write the configured values back to the Device Control Reg. */
-	ew32(CTRL, ctrl);
-
-	if (hw->phy_type == e1000_phy_m88) {
-		ret_val =
-		    e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		/* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
-		 * forced whenever speed are duplex are forced.
-		 */
-		phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
-		ret_val =
-		    e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
-		if (ret_val)
-			return ret_val;
-
-		e_dbg("M88E1000 PSCR: %x\n", phy_data);
-
-		/* Need to reset the PHY or these changes will be ignored */
-		mii_ctrl_reg |= MII_CR_RESET;
-
-		/* Disable MDI-X support for 10/100 */
-	} else {
-		/* Clear Auto-Crossover to force MDI manually.  IGP requires MDI
-		 * forced whenever speed or duplex are forced.
-		 */
-		ret_val =
-		    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
-		phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
-
-		ret_val =
-		    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
-		if (ret_val)
-			return ret_val;
-	}
-
-	/* Write back the modified PHY MII control register. */
-	ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg);
-	if (ret_val)
-		return ret_val;
-
-	udelay(1);
-
-	/* The wait_autoneg_complete flag may be a little misleading here.
-	 * Since we are forcing speed and duplex, Auto-Neg is not enabled.
-	 * But we do want to delay for a period while forcing only so we
-	 * don't generate false No Link messages.  So we will wait here
-	 * only if the user has set wait_autoneg_complete to 1, which is
-	 * the default.
-	 */
-	if (hw->wait_autoneg_complete) {
-		/* We will wait for autoneg to complete. */
-		e_dbg("Waiting for forced speed/duplex link.\n");
-		mii_status_reg = 0;
-
-		/* We will wait for autoneg to complete or 4.5 seconds to expire. */
-		for (i = PHY_FORCE_TIME; i > 0; i--) {
-			/* Read the MII Status Register and wait for Auto-Neg Complete bit
-			 * to be set.
-			 */
-			ret_val =
-			    e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-			if (ret_val)
-				return ret_val;
-
-			ret_val =
-			    e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-			if (ret_val)
-				return ret_val;
-
-			if (mii_status_reg & MII_SR_LINK_STATUS)
-				break;
-			msleep(100);
-		}
-		if ((i == 0) && (hw->phy_type == e1000_phy_m88)) {
-			/* We didn't get link.  Reset the DSP and wait again for link. */
-			ret_val = e1000_phy_reset_dsp(hw);
-			if (ret_val) {
-				e_dbg("Error Resetting PHY DSP\n");
-				return ret_val;
-			}
-		}
-		/* This loop will early-out if the link condition has been met.  */
-		for (i = PHY_FORCE_TIME; i > 0; i--) {
-			if (mii_status_reg & MII_SR_LINK_STATUS)
-				break;
-			msleep(100);
-			/* Read the MII Status Register and wait for Auto-Neg Complete bit
-			 * to be set.
-			 */
-			ret_val =
-			    e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-			if (ret_val)
-				return ret_val;
-
-			ret_val =
-			    e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-			if (ret_val)
-				return ret_val;
-		}
-	}
-
-	if (hw->phy_type == e1000_phy_m88) {
-		/* Because we reset the PHY above, we need to re-force TX_CLK in the
-		 * Extended PHY Specific Control Register to 25MHz clock.  This value
-		 * defaults back to a 2.5MHz clock when the PHY is reset.
-		 */
-		ret_val =
-		    e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
-				       &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		phy_data |= M88E1000_EPSCR_TX_CLK_25;
-		ret_val =
-		    e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
-					phy_data);
-		if (ret_val)
-			return ret_val;
-
-		/* In addition, because of the s/w reset above, we need to enable CRS on
-		 * TX.  This must be set for both full and half duplex operation.
-		 */
-		ret_val =
-		    e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
-		ret_val =
-		    e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
-		if (ret_val)
-			return ret_val;
-
-		if ((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543)
-		    && (!hw->autoneg)
-		    && (hw->forced_speed_duplex == e1000_10_full
-			|| hw->forced_speed_duplex == e1000_10_half)) {
-			ret_val = e1000_polarity_reversal_workaround(hw);
-			if (ret_val)
-				return ret_val;
-		}
-	}
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_config_collision_dist - set collision distance register
- * @hw: Struct containing variables accessed by shared code
- *
- * Sets the collision distance in the Transmit Control register.
- * Link should have been established previously. Reads the speed and duplex
- * information from the Device Status register.
- */
-void e1000_config_collision_dist(struct e1000_hw *hw)
-{
-	u32 tctl, coll_dist;
-
-	e_dbg("e1000_config_collision_dist");
-
-	if (hw->mac_type < e1000_82543)
-		coll_dist = E1000_COLLISION_DISTANCE_82542;
-	else
-		coll_dist = E1000_COLLISION_DISTANCE;
-
-	tctl = er32(TCTL);
-
-	tctl &= ~E1000_TCTL_COLD;
-	tctl |= coll_dist << E1000_COLD_SHIFT;
-
-	ew32(TCTL, tctl);
-	E1000_WRITE_FLUSH();
-}
-
-/**
- * e1000_config_mac_to_phy - sync phy and mac settings
- * @hw: Struct containing variables accessed by shared code
- * @mii_reg: data to write to the MII control register
- *
- * Sets MAC speed and duplex settings to reflect the those in the PHY
- * The contents of the PHY register containing the needed information need to
- * be passed in.
- */
-static s32 e1000_config_mac_to_phy(struct e1000_hw *hw)
-{
-	u32 ctrl;
-	s32 ret_val;
-	u16 phy_data;
-
-	e_dbg("e1000_config_mac_to_phy");
-
-	/* 82544 or newer MAC, Auto Speed Detection takes care of
-	 * MAC speed/duplex configuration.*/
-	if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100))
-		return E1000_SUCCESS;
-
-	/* Read the Device Control Register and set the bits to Force Speed
-	 * and Duplex.
-	 */
-	ctrl = er32(CTRL);
-	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
-	ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
-
-	switch (hw->phy_type) {
-	case e1000_phy_8201:
-		ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		if (phy_data & RTL_PHY_CTRL_FD)
-			ctrl |= E1000_CTRL_FD;
-		else
-			ctrl &= ~E1000_CTRL_FD;
-
-		if (phy_data & RTL_PHY_CTRL_SPD_100)
-			ctrl |= E1000_CTRL_SPD_100;
-		else
-			ctrl |= E1000_CTRL_SPD_10;
-
-		e1000_config_collision_dist(hw);
-		break;
-	default:
-		/* Set up duplex in the Device Control and Transmit Control
-		 * registers depending on negotiated values.
-		 */
-		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
-		                             &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		if (phy_data & M88E1000_PSSR_DPLX)
-			ctrl |= E1000_CTRL_FD;
-		else
-			ctrl &= ~E1000_CTRL_FD;
-
-		e1000_config_collision_dist(hw);
-
-		/* Set up speed in the Device Control register depending on
-		 * negotiated values.
-		 */
-		if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
-			ctrl |= E1000_CTRL_SPD_1000;
-		else if ((phy_data & M88E1000_PSSR_SPEED) ==
-		         M88E1000_PSSR_100MBS)
-			ctrl |= E1000_CTRL_SPD_100;
-	}
-
-	/* Write the configured values back to the Device Control Reg. */
-	ew32(CTRL, ctrl);
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_force_mac_fc - force flow control settings
- * @hw: Struct containing variables accessed by shared code
- *
- * Forces the MAC's flow control settings.
- * Sets the TFCE and RFCE bits in the device control register to reflect
- * the adapter settings. TFCE and RFCE need to be explicitly set by
- * software when a Copper PHY is used because autonegotiation is managed
- * by the PHY rather than the MAC. Software must also configure these
- * bits when link is forced on a fiber connection.
- */
-s32 e1000_force_mac_fc(struct e1000_hw *hw)
-{
-	u32 ctrl;
-
-	e_dbg("e1000_force_mac_fc");
-
-	/* Get the current configuration of the Device Control Register */
-	ctrl = er32(CTRL);
-
-	/* Because we didn't get link via the internal auto-negotiation
-	 * mechanism (we either forced link or we got link via PHY
-	 * auto-neg), we have to manually enable/disable transmit an
-	 * receive flow control.
-	 *
-	 * The "Case" statement below enables/disable flow control
-	 * according to the "hw->fc" parameter.
-	 *
-	 * The possible values of the "fc" parameter 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
-	 *          frames but we do not receive pause frames).
-	 *      3:  Both Rx and TX flow control (symmetric) is enabled.
-	 *  other:  No other values should be possible at this point.
-	 */
-
-	switch (hw->fc) {
-	case E1000_FC_NONE:
-		ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
-		break;
-	case E1000_FC_RX_PAUSE:
-		ctrl &= (~E1000_CTRL_TFCE);
-		ctrl |= E1000_CTRL_RFCE;
-		break;
-	case E1000_FC_TX_PAUSE:
-		ctrl &= (~E1000_CTRL_RFCE);
-		ctrl |= E1000_CTRL_TFCE;
-		break;
-	case E1000_FC_FULL:
-		ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
-		break;
-	default:
-		e_dbg("Flow control param set incorrectly\n");
-		return -E1000_ERR_CONFIG;
-	}
-
-	/* Disable TX Flow Control for 82542 (rev 2.0) */
-	if (hw->mac_type == e1000_82542_rev2_0)
-		ctrl &= (~E1000_CTRL_TFCE);
-
-	ew32(CTRL, ctrl);
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_config_fc_after_link_up - configure flow control after autoneg
- * @hw: Struct containing variables accessed by shared code
- *
- * Configures flow control settings after link is established
- * Should be called immediately after a valid link has been established.
- * Forces MAC flow control settings if link was forced. When in MII/GMII mode
- * and autonegotiation is enabled, the MAC flow control settings will be set
- * based on the flow control negotiated by the PHY. In TBI mode, the TFCE
- * and RFCE bits will be automatically set to the negotiated flow control mode.
- */
-static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 mii_status_reg;
-	u16 mii_nway_adv_reg;
-	u16 mii_nway_lp_ability_reg;
-	u16 speed;
-	u16 duplex;
-
-	e_dbg("e1000_config_fc_after_link_up");
-
-	/* Check for the case where we have fiber media and auto-neg failed
-	 * so we had to force link.  In this case, we need to force the
-	 * configuration of the MAC to match the "fc" parameter.
-	 */
-	if (((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed))
-	    || ((hw->media_type == e1000_media_type_internal_serdes)
-		&& (hw->autoneg_failed))
-	    || ((hw->media_type == e1000_media_type_copper)
-		&& (!hw->autoneg))) {
-		ret_val = e1000_force_mac_fc(hw);
-		if (ret_val) {
-			e_dbg("Error forcing flow control settings\n");
-			return ret_val;
-		}
-	}
-
-	/* Check for the case where we have copper media and auto-neg is
-	 * enabled.  In this case, we need to check and see if Auto-Neg
-	 * has completed, and if so, how the PHY and link partner has
-	 * flow control configured.
-	 */
-	if ((hw->media_type == e1000_media_type_copper) && hw->autoneg) {
-		/* Read the MII Status Register and check to see if AutoNeg
-		 * has completed.  We read this twice because this reg has
-		 * some "sticky" (latched) bits.
-		 */
-		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-		if (ret_val)
-			return ret_val;
-		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-		if (ret_val)
-			return ret_val;
-
-		if (mii_status_reg & MII_SR_AUTONEG_COMPLETE) {
-			/* The AutoNeg process has completed, so we now need to
-			 * read both the Auto Negotiation Advertisement Register
-			 * (Address 4) and the Auto_Negotiation Base Page Ability
-			 * Register (Address 5) to determine how flow control was
-			 * negotiated.
-			 */
-			ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,
-						     &mii_nway_adv_reg);
-			if (ret_val)
-				return ret_val;
-			ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY,
-						     &mii_nway_lp_ability_reg);
-			if (ret_val)
-				return ret_val;
-
-			/* Two bits in the Auto Negotiation Advertisement Register
-			 * (Address 4) and two bits in the Auto Negotiation Base
-			 * Page Ability Register (Address 5) determine flow control
-			 * for both the PHY and the link partner.  The following
-			 * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
-			 * 1999, describes these PAUSE resolution bits and how flow
-			 * control is determined based upon these settings.
-			 * NOTE:  DC = Don't Care
-			 *
-			 *   LOCAL DEVICE  |   LINK PARTNER
-			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
-			 *-------|---------|-------|---------|--------------------
-			 *   0   |    0    |  DC   |   DC    | E1000_FC_NONE
-			 *   0   |    1    |   0   |   DC    | E1000_FC_NONE
-			 *   0   |    1    |   1   |    0    | E1000_FC_NONE
-			 *   0   |    1    |   1   |    1    | E1000_FC_TX_PAUSE
-			 *   1   |    0    |   0   |   DC    | E1000_FC_NONE
-			 *   1   |   DC    |   1   |   DC    | E1000_FC_FULL
-			 *   1   |    1    |   0   |    0    | E1000_FC_NONE
-			 *   1   |    1    |   0   |    1    | E1000_FC_RX_PAUSE
-			 *
-			 */
-			/* Are both PAUSE bits set to 1?  If so, this implies
-			 * Symmetric Flow Control is enabled at both ends.  The
-			 * ASM_DIR bits are irrelevant per the spec.
-			 *
-			 * For Symmetric Flow Control:
-			 *
-			 *   LOCAL DEVICE  |   LINK PARTNER
-			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
-			 *-------|---------|-------|---------|--------------------
-			 *   1   |   DC    |   1   |   DC    | E1000_FC_FULL
-			 *
-			 */
-			if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
-			    (mii_nway_lp_ability_reg & NWAY_LPAR_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->original_fc == E1000_FC_FULL) {
-					hw->fc = E1000_FC_FULL;
-					e_dbg("Flow Control = FULL.\n");
-				} else {
-					hw->fc = E1000_FC_RX_PAUSE;
-					e_dbg
-					    ("Flow Control = RX PAUSE frames only.\n");
-				}
-			}
-			/* For receiving PAUSE frames ONLY.
-			 *
-			 *   LOCAL DEVICE  |   LINK PARTNER
-			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
-			 *-------|---------|-------|---------|--------------------
-			 *   0   |    1    |   1   |    1    | E1000_FC_TX_PAUSE
-			 *
-			 */
-			else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
-				 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
-				 (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
-				 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR))
-			{
-				hw->fc = E1000_FC_TX_PAUSE;
-				e_dbg
-				    ("Flow Control = TX PAUSE frames only.\n");
-			}
-			/* For transmitting PAUSE frames ONLY.
-			 *
-			 *   LOCAL DEVICE  |   LINK PARTNER
-			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
-			 *-------|---------|-------|---------|--------------------
-			 *   1   |    1    |   0   |    1    | E1000_FC_RX_PAUSE
-			 *
-			 */
-			else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
-				 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
-				 !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
-				 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR))
-			{
-				hw->fc = E1000_FC_RX_PAUSE;
-				e_dbg
-				    ("Flow Control = RX PAUSE frames only.\n");
-			}
-			/* Per the IEEE spec, at this point flow control should be
-			 * disabled.  However, we want to consider that we could
-			 * be connected to a legacy switch that doesn't advertise
-			 * desired flow control, but can be forced on the link
-			 * partner.  So if we advertised no flow control, that is
-			 * what we will resolve to.  If we advertised some kind of
-			 * receive capability (Rx Pause Only or Full Flow Control)
-			 * and the link partner advertised none, we will configure
-			 * ourselves to enable Rx Flow Control only.  We can do
-			 * this safely for two reasons:  If the link partner really
-			 * didn't want flow control enabled, and we enable Rx, no
-			 * harm done since we won't be receiving any PAUSE frames
-			 * anyway.  If the intent on the link partner was to have
-			 * flow control enabled, then by us enabling RX only, we
-			 * can at least receive pause frames and process them.
-			 * This is a good idea because in most cases, since we are
-			 * predominantly a server NIC, more times than not we will
-			 * be asked to delay transmission of packets than asking
-			 * our link partner to pause transmission of frames.
-			 */
-			else if ((hw->original_fc == E1000_FC_NONE ||
-				  hw->original_fc == E1000_FC_TX_PAUSE) ||
-				 hw->fc_strict_ieee) {
-				hw->fc = E1000_FC_NONE;
-				e_dbg("Flow Control = NONE.\n");
-			} else {
-				hw->fc = E1000_FC_RX_PAUSE;
-				e_dbg
-				    ("Flow Control = RX PAUSE frames only.\n");
-			}
-
-			/* Now we need to do one last check...  If we auto-
-			 * negotiated to HALF DUPLEX, flow control should not be
-			 * enabled per IEEE 802.3 spec.
-			 */
-			ret_val =
-			    e1000_get_speed_and_duplex(hw, &speed, &duplex);
-			if (ret_val) {
-				e_dbg
-				    ("Error getting link speed and duplex\n");
-				return ret_val;
-			}
-
-			if (duplex == HALF_DUPLEX)
-				hw->fc = E1000_FC_NONE;
-
-			/* Now we call a subroutine to actually force the MAC
-			 * controller to use the correct flow control settings.
-			 */
-			ret_val = e1000_force_mac_fc(hw);
-			if (ret_val) {
-				e_dbg
-				    ("Error forcing flow control settings\n");
-				return ret_val;
-			}
-		} else {
-			e_dbg
-			    ("Copper PHY and Auto Neg has not completed.\n");
-		}
-	}
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_check_for_serdes_link_generic - Check for link (Serdes)
- * @hw: pointer to the HW structure
- *
- * Checks for link up on the hardware.  If link is not up and we have
- * a signal, then we need to force link up.
- */
-static s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
-{
-	u32 rxcw;
-	u32 ctrl;
-	u32 status;
-	s32 ret_val = E1000_SUCCESS;
-
-	e_dbg("e1000_check_for_serdes_link_generic");
-
-	ctrl = er32(CTRL);
-	status = er32(STATUS);
-	rxcw = er32(RXCW);
-
-	/*
-	 * If we don't have link (auto-negotiation failed or link partner
-	 * cannot auto-negotiate), and our link partner is not trying to
-	 * auto-negotiate with us (we are receiving idles or data),
-	 * we need to force link up. We also need to give auto-negotiation
-	 * time to complete.
-	 */
-	/* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
-	if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {
-		if (hw->autoneg_failed == 0) {
-			hw->autoneg_failed = 1;
-			goto out;
-		}
-		e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n");
-
-		/* Disable auto-negotiation in the TXCW register */
-		ew32(TXCW, (hw->txcw & ~E1000_TXCW_ANE));
-
-		/* Force link-up and also force full-duplex. */
-		ctrl = er32(CTRL);
-		ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
-		ew32(CTRL, ctrl);
-
-		/* Configure Flow Control after forcing link up. */
-		ret_val = e1000_config_fc_after_link_up(hw);
-		if (ret_val) {
-			e_dbg("Error configuring flow control\n");
-			goto out;
-		}
-	} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
-		/*
-		 * If we are forcing link and we are receiving /C/ ordered
-		 * sets, re-enable auto-negotiation in the TXCW register
-		 * and disable forced link in the Device Control register
-		 * in an attempt to auto-negotiate with our link partner.
-		 */
-		e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n");
-		ew32(TXCW, hw->txcw);
-		ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
-
-		hw->serdes_has_link = true;
-	} else if (!(E1000_TXCW_ANE & er32(TXCW))) {
-		/*
-		 * If we force link for non-auto-negotiation switch, check
-		 * link status based on MAC synchronization for internal
-		 * serdes media type.
-		 */
-		/* SYNCH bit and IV bit are sticky. */
-		udelay(10);
-		rxcw = er32(RXCW);
-		if (rxcw & E1000_RXCW_SYNCH) {
-			if (!(rxcw & E1000_RXCW_IV)) {
-				hw->serdes_has_link = true;
-				e_dbg("SERDES: Link up - forced.\n");
-			}
-		} else {
-			hw->serdes_has_link = false;
-			e_dbg("SERDES: Link down - force failed.\n");
-		}
-	}
-
-	if (E1000_TXCW_ANE & er32(TXCW)) {
-		status = er32(STATUS);
-		if (status & E1000_STATUS_LU) {
-			/* SYNCH bit and IV bit are sticky, so reread rxcw. */
-			udelay(10);
-			rxcw = er32(RXCW);
-			if (rxcw & E1000_RXCW_SYNCH) {
-				if (!(rxcw & E1000_RXCW_IV)) {
-					hw->serdes_has_link = true;
-					e_dbg("SERDES: Link up - autoneg "
-						 "completed successfully.\n");
-				} else {
-					hw->serdes_has_link = false;
-					e_dbg("SERDES: Link down - invalid"
-						 "codewords detected in autoneg.\n");
-				}
-			} else {
-				hw->serdes_has_link = false;
-				e_dbg("SERDES: Link down - no sync.\n");
-			}
-		} else {
-			hw->serdes_has_link = false;
-			e_dbg("SERDES: Link down - autoneg failed\n");
-		}
-	}
-
-      out:
-	return ret_val;
-}
-
-/**
- * e1000_check_for_link
- * @hw: Struct containing variables accessed by shared code
- *
- * Checks to see if the link status of the hardware has changed.
- * Called by any function that needs to check the link status of the adapter.
- */
-s32 e1000_check_for_link(struct e1000_hw *hw)
-{
-	u32 rxcw = 0;
-	u32 ctrl;
-	u32 status;
-	u32 rctl;
-	u32 icr;
-	u32 signal = 0;
-	s32 ret_val;
-	u16 phy_data;
-
-	e_dbg("e1000_check_for_link");
-
-	ctrl = er32(CTRL);
-	status = er32(STATUS);
-
-	/* On adapters with a MAC newer than 82544, SW Definable pin 1 will be
-	 * set when the optics detect a signal. On older adapters, it will be
-	 * cleared when there is a signal.  This applies to fiber media only.
-	 */
-	if ((hw->media_type == e1000_media_type_fiber) ||
-	    (hw->media_type == e1000_media_type_internal_serdes)) {
-		rxcw = er32(RXCW);
-
-		if (hw->media_type == e1000_media_type_fiber) {
-			signal =
-			    (hw->mac_type >
-			     e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
-			if (status & E1000_STATUS_LU)
-				hw->get_link_status = false;
-		}
-	}
-
-	/* If we have a copper PHY then we only want to go out to the PHY
-	 * registers to see if Auto-Neg has completed and/or if our link
-	 * status has changed.  The get_link_status flag will be set if we
-	 * receive a Link Status Change interrupt or we have Rx Sequence
-	 * Errors.
-	 */
-	if ((hw->media_type == e1000_media_type_copper) && hw->get_link_status) {
-		/* First we want to see if the MII Status Register reports
-		 * link.  If so, then we want to get the current speed/duplex
-		 * of the PHY.
-		 * Read the register twice since the link bit is sticky.
-		 */
-		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-		if (ret_val)
-			return ret_val;
-		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		if (phy_data & MII_SR_LINK_STATUS) {
-			hw->get_link_status = false;
-			/* Check if there was DownShift, must be checked immediately after
-			 * link-up */
-			e1000_check_downshift(hw);
-
-			/* If we are on 82544 or 82543 silicon and speed/duplex
-			 * are forced to 10H or 10F, then we will implement the polarity
-			 * reversal workaround.  We disable interrupts first, and upon
-			 * returning, place the devices interrupt state to its previous
-			 * value except for the link status change interrupt which will
-			 * happen due to the execution of this workaround.
-			 */
-
-			if ((hw->mac_type == e1000_82544
-			     || hw->mac_type == e1000_82543) && (!hw->autoneg)
-			    && (hw->forced_speed_duplex == e1000_10_full
-				|| hw->forced_speed_duplex == e1000_10_half)) {
-				ew32(IMC, 0xffffffff);
-				ret_val =
-				    e1000_polarity_reversal_workaround(hw);
-				icr = er32(ICR);
-				ew32(ICS, (icr & ~E1000_ICS_LSC));
-				ew32(IMS, IMS_ENABLE_MASK);
-			}
-
-		} else {
-			/* No link detected */
-			e1000_config_dsp_after_link_change(hw, false);
-			return 0;
-		}
-
-		/* If we are forcing speed/duplex, then we simply return since
-		 * we have already determined whether we have link or not.
-		 */
-		if (!hw->autoneg)
-			return -E1000_ERR_CONFIG;
-
-		/* optimize the dsp settings for the igp phy */
-		e1000_config_dsp_after_link_change(hw, true);
-
-		/* We have a M88E1000 PHY and Auto-Neg is enabled.  If we
-		 * have Si on board that is 82544 or newer, Auto
-		 * Speed Detection takes care of MAC speed/duplex
-		 * configuration.  So we only need to configure Collision
-		 * Distance in the MAC.  Otherwise, we need to force
-		 * speed/duplex on the MAC to the current PHY speed/duplex
-		 * settings.
-		 */
-		if ((hw->mac_type >= e1000_82544) &&
-		    (hw->mac_type != e1000_ce4100))
-			e1000_config_collision_dist(hw);
-		else {
-			ret_val = e1000_config_mac_to_phy(hw);
-			if (ret_val) {
-				e_dbg
-				    ("Error configuring MAC to PHY settings\n");
-				return ret_val;
-			}
-		}
-
-		/* Configure Flow Control now that Auto-Neg has completed. First, we
-		 * need to restore the desired flow control settings because we may
-		 * have had to re-autoneg with a different link partner.
-		 */
-		ret_val = e1000_config_fc_after_link_up(hw);
-		if (ret_val) {
-			e_dbg("Error configuring flow control\n");
-			return ret_val;
-		}
-
-		/* At this point we know that we are on copper and we have
-		 * auto-negotiated link.  These are conditions for checking the link
-		 * partner capability register.  We use the link speed to determine if
-		 * TBI compatibility needs to be turned on or off.  If the link is not
-		 * at gigabit speed, then TBI compatibility is not needed.  If we are
-		 * at gigabit speed, we turn on TBI compatibility.
-		 */
-		if (hw->tbi_compatibility_en) {
-			u16 speed, duplex;
-			ret_val =
-			    e1000_get_speed_and_duplex(hw, &speed, &duplex);
-			if (ret_val) {
-				e_dbg
-				    ("Error getting link speed and duplex\n");
-				return ret_val;
-			}
-			if (speed != SPEED_1000) {
-				/* If link speed is not set to gigabit speed, we do not need
-				 * to enable TBI compatibility.
-				 */
-				if (hw->tbi_compatibility_on) {
-					/* If we previously were in the mode, turn it off. */
-					rctl = er32(RCTL);
-					rctl &= ~E1000_RCTL_SBP;
-					ew32(RCTL, rctl);
-					hw->tbi_compatibility_on = false;
-				}
-			} else {
-				/* If TBI compatibility is was previously off, turn it on. For
-				 * compatibility with a TBI link partner, we will store bad
-				 * packets. Some frames have an additional byte on the end and
-				 * will look like CRC errors to to the hardware.
-				 */
-				if (!hw->tbi_compatibility_on) {
-					hw->tbi_compatibility_on = true;
-					rctl = er32(RCTL);
-					rctl |= E1000_RCTL_SBP;
-					ew32(RCTL, rctl);
-				}
-			}
-		}
-	}
-
-	if ((hw->media_type == e1000_media_type_fiber) ||
-	    (hw->media_type == e1000_media_type_internal_serdes))
-		e1000_check_for_serdes_link_generic(hw);
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_get_speed_and_duplex
- * @hw: Struct containing variables accessed by shared code
- * @speed: Speed of the connection
- * @duplex: Duplex setting of the connection
-
- * Detects the current speed and duplex settings of the hardware.
- */
-s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex)
-{
-	u32 status;
-	s32 ret_val;
-	u16 phy_data;
-
-	e_dbg("e1000_get_speed_and_duplex");
-
-	if (hw->mac_type >= e1000_82543) {
-		status = er32(STATUS);
-		if (status & E1000_STATUS_SPEED_1000) {
-			*speed = SPEED_1000;
-			e_dbg("1000 Mbs, ");
-		} else if (status & E1000_STATUS_SPEED_100) {
-			*speed = SPEED_100;
-			e_dbg("100 Mbs, ");
-		} else {
-			*speed = SPEED_10;
-			e_dbg("10 Mbs, ");
-		}
-
-		if (status & E1000_STATUS_FD) {
-			*duplex = FULL_DUPLEX;
-			e_dbg("Full Duplex\n");
-		} else {
-			*duplex = HALF_DUPLEX;
-			e_dbg(" Half Duplex\n");
-		}
-	} else {
-		e_dbg("1000 Mbs, Full Duplex\n");
-		*speed = SPEED_1000;
-		*duplex = FULL_DUPLEX;
-	}
-
-	/* IGP01 PHY may advertise full duplex operation after speed downgrade even
-	 * if it is operating at half duplex.  Here we set the duplex settings to
-	 * match the duplex in the link partner's capabilities.
-	 */
-	if (hw->phy_type == e1000_phy_igp && hw->speed_downgraded) {
-		ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		if (!(phy_data & NWAY_ER_LP_NWAY_CAPS))
-			*duplex = HALF_DUPLEX;
-		else {
-			ret_val =
-			    e1000_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data);
-			if (ret_val)
-				return ret_val;
-			if ((*speed == SPEED_100
-			     && !(phy_data & NWAY_LPAR_100TX_FD_CAPS))
-			    || (*speed == SPEED_10
-				&& !(phy_data & NWAY_LPAR_10T_FD_CAPS)))
-				*duplex = HALF_DUPLEX;
-		}
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_wait_autoneg
- * @hw: Struct containing variables accessed by shared code
- *
- * Blocks until autoneg completes or times out (~4.5 seconds)
- */
-static s32 e1000_wait_autoneg(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 i;
-	u16 phy_data;
-
-	e_dbg("e1000_wait_autoneg");
-	e_dbg("Waiting for Auto-Neg to complete.\n");
-
-	/* We will wait for autoneg to complete or 4.5 seconds to expire. */
-	for (i = PHY_AUTO_NEG_TIME; i > 0; i--) {
-		/* Read the MII Status Register and wait for Auto-Neg
-		 * Complete bit to be set.
-		 */
-		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-		if (ret_val)
-			return ret_val;
-		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-		if (ret_val)
-			return ret_val;
-		if (phy_data & MII_SR_AUTONEG_COMPLETE) {
-			return E1000_SUCCESS;
-		}
-		msleep(100);
-	}
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_raise_mdi_clk - Raises the Management Data Clock
- * @hw: Struct containing variables accessed by shared code
- * @ctrl: Device control register's current value
- */
-static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
-{
-	/* Raise the clock input to the Management Data Clock (by setting the MDC
-	 * bit), and then delay 10 microseconds.
-	 */
-	ew32(CTRL, (*ctrl | E1000_CTRL_MDC));
-	E1000_WRITE_FLUSH();
-	udelay(10);
-}
-
-/**
- * e1000_lower_mdi_clk - Lowers the Management Data Clock
- * @hw: Struct containing variables accessed by shared code
- * @ctrl: Device control register's current value
- */
-static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
-{
-	/* Lower the clock input to the Management Data Clock (by clearing the MDC
-	 * bit), and then delay 10 microseconds.
-	 */
-	ew32(CTRL, (*ctrl & ~E1000_CTRL_MDC));
-	E1000_WRITE_FLUSH();
-	udelay(10);
-}
-
-/**
- * e1000_shift_out_mdi_bits - Shifts data bits out to the PHY
- * @hw: Struct containing variables accessed by shared code
- * @data: Data to send out to the PHY
- * @count: Number of bits to shift out
- *
- * Bits are shifted out in MSB to LSB order.
- */
-static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count)
-{
-	u32 ctrl;
-	u32 mask;
-
-	/* We need to shift "count" number of bits out to the PHY. So, the value
-	 * in the "data" parameter will be shifted out to the PHY one bit at a
-	 * time. In order to do this, "data" must be broken down into bits.
-	 */
-	mask = 0x01;
-	mask <<= (count - 1);
-
-	ctrl = er32(CTRL);
-
-	/* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
-	ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
-
-	while (mask) {
-		/* A "1" is shifted out to the PHY by setting the MDIO bit to "1" and
-		 * then raising and lowering the Management Data Clock. A "0" is
-		 * shifted out to the PHY by setting the MDIO bit to "0" and then
-		 * raising and lowering the clock.
-		 */
-		if (data & mask)
-			ctrl |= E1000_CTRL_MDIO;
-		else
-			ctrl &= ~E1000_CTRL_MDIO;
-
-		ew32(CTRL, ctrl);
-		E1000_WRITE_FLUSH();
-
-		udelay(10);
-
-		e1000_raise_mdi_clk(hw, &ctrl);
-		e1000_lower_mdi_clk(hw, &ctrl);
-
-		mask = mask >> 1;
-	}
-}
-
-/**
- * e1000_shift_in_mdi_bits - Shifts data bits in from the PHY
- * @hw: Struct containing variables accessed by shared code
- *
- * Bits are shifted in in MSB to LSB order.
- */
-static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw)
-{
-	u32 ctrl;
-	u16 data = 0;
-	u8 i;
-
-	/* In order to read a register from the PHY, we need to shift in a total
-	 * of 18 bits from the PHY. The first two bit (turnaround) times are used
-	 * to avoid contention on the MDIO pin when a read operation is performed.
-	 * These two bits are ignored by us and thrown away. Bits are "shifted in"
-	 * by raising the input to the Management Data Clock (setting the MDC bit),
-	 * and then reading the value of the MDIO bit.
-	 */
-	ctrl = er32(CTRL);
-
-	/* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as input. */
-	ctrl &= ~E1000_CTRL_MDIO_DIR;
-	ctrl &= ~E1000_CTRL_MDIO;
-
-	ew32(CTRL, ctrl);
-	E1000_WRITE_FLUSH();
-
-	/* Raise and Lower the clock before reading in the data. This accounts for
-	 * the turnaround bits. The first clock occurred when we clocked out the
-	 * last bit of the Register Address.
-	 */
-	e1000_raise_mdi_clk(hw, &ctrl);
-	e1000_lower_mdi_clk(hw, &ctrl);
-
-	for (data = 0, i = 0; i < 16; i++) {
-		data = data << 1;
-		e1000_raise_mdi_clk(hw, &ctrl);
-		ctrl = er32(CTRL);
-		/* Check to see if we shifted in a "1". */
-		if (ctrl & E1000_CTRL_MDIO)
-			data |= 1;
-		e1000_lower_mdi_clk(hw, &ctrl);
-	}
-
-	e1000_raise_mdi_clk(hw, &ctrl);
-	e1000_lower_mdi_clk(hw, &ctrl);
-
-	return data;
-}
-
-
-/**
- * e1000_read_phy_reg - read a phy register
- * @hw: Struct containing variables accessed by shared code
- * @reg_addr: address of the PHY register to read
- *
- * Reads the value from a PHY register, if the value is on a specific non zero
- * page, sets the page first.
- */
-s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data)
-{
-	u32 ret_val;
-
-	e_dbg("e1000_read_phy_reg");
-
-	if ((hw->phy_type == e1000_phy_igp) &&
-	    (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
-		ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
-						 (u16) reg_addr);
-		if (ret_val)
-			return ret_val;
-	}
-
-	ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
-					phy_data);
-
-	return ret_val;
-}
-
-static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
-				 u16 *phy_data)
-{
-	u32 i;
-	u32 mdic = 0;
-	const u32 phy_addr = (hw->mac_type == e1000_ce4100) ? hw->phy_addr : 1;
-
-	e_dbg("e1000_read_phy_reg_ex");
-
-	if (reg_addr > MAX_PHY_REG_ADDRESS) {
-		e_dbg("PHY Address %d is out of range\n", reg_addr);
-		return -E1000_ERR_PARAM;
-	}
-
-	if (hw->mac_type > e1000_82543) {
-		/* Set up Op-code, Phy Address, and register address in the MDI
-		 * Control register.  The MAC will take care of interfacing with the
-		 * PHY to retrieve the desired data.
-		 */
-		if (hw->mac_type == e1000_ce4100) {
-			mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
-				(phy_addr << E1000_MDIC_PHY_SHIFT) |
-				(INTEL_CE_GBE_MDIC_OP_READ) |
-				(INTEL_CE_GBE_MDIC_GO));
-
-			writel(mdic, E1000_MDIO_CMD);
-
-			/* Poll the ready bit to see if the MDI read
-			 * completed
-			 */
-			for (i = 0; i < 64; i++) {
-				udelay(50);
-				mdic = readl(E1000_MDIO_CMD);
-				if (!(mdic & INTEL_CE_GBE_MDIC_GO))
-					break;
-			}
-
-			if (mdic & INTEL_CE_GBE_MDIC_GO) {
-				e_dbg("MDI Read did not complete\n");
-				return -E1000_ERR_PHY;
-			}
-
-			mdic = readl(E1000_MDIO_STS);
-			if (mdic & INTEL_CE_GBE_MDIC_READ_ERROR) {
-				e_dbg("MDI Read Error\n");
-				return -E1000_ERR_PHY;
-			}
-			*phy_data = (u16) mdic;
-		} else {
-			mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
-				(phy_addr << E1000_MDIC_PHY_SHIFT) |
-				(E1000_MDIC_OP_READ));
-
-			ew32(MDIC, mdic);
-
-			/* Poll the ready bit to see if the MDI read
-			 * completed
-			 */
-			for (i = 0; i < 64; i++) {
-				udelay(50);
-				mdic = er32(MDIC);
-				if (mdic & E1000_MDIC_READY)
-					break;
-			}
-			if (!(mdic & E1000_MDIC_READY)) {
-				e_dbg("MDI Read did not complete\n");
-				return -E1000_ERR_PHY;
-			}
-			if (mdic & E1000_MDIC_ERROR) {
-				e_dbg("MDI Error\n");
-				return -E1000_ERR_PHY;
-			}
-			*phy_data = (u16) mdic;
-		}
-	} else {
-		/* We must first send a preamble through the MDIO pin to signal the
-		 * beginning of an MII instruction.  This is done by sending 32
-		 * consecutive "1" bits.
-		 */
-		e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
-
-		/* Now combine the next few fields that are required for a read
-		 * operation.  We use this method instead of calling the
-		 * e1000_shift_out_mdi_bits routine five different times. The format of
-		 * a MII read instruction consists of a shift out of 14 bits and is
-		 * defined as follows:
-		 *    <Preamble><SOF><Op Code><Phy Addr><Reg Addr>
-		 * followed by a shift in of 18 bits.  This first two bits shifted in
-		 * are TurnAround bits used to avoid contention on the MDIO pin when a
-		 * READ operation is performed.  These two bits are thrown away
-		 * followed by a shift in of 16 bits which contains the desired data.
-		 */
-		mdic = ((reg_addr) | (phy_addr << 5) |
-			(PHY_OP_READ << 10) | (PHY_SOF << 12));
-
-		e1000_shift_out_mdi_bits(hw, mdic, 14);
-
-		/* Now that we've shifted out the read command to the MII, we need to
-		 * "shift in" the 16-bit value (18 total bits) of the requested PHY
-		 * register address.
-		 */
-		*phy_data = e1000_shift_in_mdi_bits(hw);
-	}
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_write_phy_reg - write a phy register
- *
- * @hw: Struct containing variables accessed by shared code
- * @reg_addr: address of the PHY register to write
- * @data: data to write to the PHY
-
- * Writes a value to a PHY register
- */
-s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data)
-{
-	u32 ret_val;
-
-	e_dbg("e1000_write_phy_reg");
-
-	if ((hw->phy_type == e1000_phy_igp) &&
-	    (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
-		ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
-						 (u16) reg_addr);
-		if (ret_val)
-			return ret_val;
-	}
-
-	ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
-					 phy_data);
-
-	return ret_val;
-}
-
-static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
-				  u16 phy_data)
-{
-	u32 i;
-	u32 mdic = 0;
-	const u32 phy_addr = (hw->mac_type == e1000_ce4100) ? hw->phy_addr : 1;
-
-	e_dbg("e1000_write_phy_reg_ex");
-
-	if (reg_addr > MAX_PHY_REG_ADDRESS) {
-		e_dbg("PHY Address %d is out of range\n", reg_addr);
-		return -E1000_ERR_PARAM;
-	}
-
-	if (hw->mac_type > e1000_82543) {
-		/* Set up Op-code, Phy Address, register address, and data
-		 * intended for the PHY register in the MDI Control register.
-		 * The MAC will take care of interfacing with the PHY to send
-		 * the desired data.
-		 */
-		if (hw->mac_type == e1000_ce4100) {
-			mdic = (((u32) phy_data) |
-				(reg_addr << E1000_MDIC_REG_SHIFT) |
-				(phy_addr << E1000_MDIC_PHY_SHIFT) |
-				(INTEL_CE_GBE_MDIC_OP_WRITE) |
-				(INTEL_CE_GBE_MDIC_GO));
-
-			writel(mdic, E1000_MDIO_CMD);
-
-			/* Poll the ready bit to see if the MDI read
-			 * completed
-			 */
-			for (i = 0; i < 640; i++) {
-				udelay(5);
-				mdic = readl(E1000_MDIO_CMD);
-				if (!(mdic & INTEL_CE_GBE_MDIC_GO))
-					break;
-			}
-			if (mdic & INTEL_CE_GBE_MDIC_GO) {
-				e_dbg("MDI Write did not complete\n");
-				return -E1000_ERR_PHY;
-			}
-		} else {
-			mdic = (((u32) phy_data) |
-				(reg_addr << E1000_MDIC_REG_SHIFT) |
-				(phy_addr << E1000_MDIC_PHY_SHIFT) |
-				(E1000_MDIC_OP_WRITE));
-
-			ew32(MDIC, mdic);
-
-			/* Poll the ready bit to see if the MDI read
-			 * completed
-			 */
-			for (i = 0; i < 641; i++) {
-				udelay(5);
-				mdic = er32(MDIC);
-				if (mdic & E1000_MDIC_READY)
-					break;
-			}
-			if (!(mdic & E1000_MDIC_READY)) {
-				e_dbg("MDI Write did not complete\n");
-				return -E1000_ERR_PHY;
-			}
-		}
-	} else {
-		/* We'll need to use the SW defined pins to shift the write command
-		 * out to the PHY. We first send a preamble to the PHY to signal the
-		 * beginning of the MII instruction.  This is done by sending 32
-		 * consecutive "1" bits.
-		 */
-		e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
-
-		/* Now combine the remaining required fields that will indicate a
-		 * write operation. We use this method instead of calling the
-		 * e1000_shift_out_mdi_bits routine for each field in the command. The
-		 * format of a MII write instruction is as follows:
-		 * <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>.
-		 */
-		mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) |
-			(PHY_OP_WRITE << 12) | (PHY_SOF << 14));
-		mdic <<= 16;
-		mdic |= (u32) phy_data;
-
-		e1000_shift_out_mdi_bits(hw, mdic, 32);
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_phy_hw_reset - reset the phy, hardware style
- * @hw: Struct containing variables accessed by shared code
- *
- * Returns the PHY to the power-on reset state
- */
-s32 e1000_phy_hw_reset(struct e1000_hw *hw)
-{
-	u32 ctrl, ctrl_ext;
-	u32 led_ctrl;
-
-	e_dbg("e1000_phy_hw_reset");
-
-	e_dbg("Resetting Phy...\n");
-
-	if (hw->mac_type > e1000_82543) {
-		/* Read the device control register and assert the E1000_CTRL_PHY_RST
-		 * bit. Then, take it out of reset.
-		 * For e1000 hardware, we delay for 10ms between the assert
-		 * and deassert.
-		 */
-		ctrl = er32(CTRL);
-		ew32(CTRL, ctrl | E1000_CTRL_PHY_RST);
-		E1000_WRITE_FLUSH();
-
-		msleep(10);
-
-		ew32(CTRL, ctrl);
-		E1000_WRITE_FLUSH();
-
-	} else {
-		/* Read the Extended Device Control Register, assert the PHY_RESET_DIR
-		 * bit to put the PHY into reset. Then, take it out of reset.
-		 */
-		ctrl_ext = er32(CTRL_EXT);
-		ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR;
-		ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA;
-		ew32(CTRL_EXT, ctrl_ext);
-		E1000_WRITE_FLUSH();
-		msleep(10);
-		ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA;
-		ew32(CTRL_EXT, ctrl_ext);
-		E1000_WRITE_FLUSH();
-	}
-	udelay(150);
-
-	if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
-		/* Configure activity LED after PHY reset */
-		led_ctrl = er32(LEDCTL);
-		led_ctrl &= IGP_ACTIVITY_LED_MASK;
-		led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
-		ew32(LEDCTL, led_ctrl);
-	}
-
-	/* Wait for FW to finish PHY configuration. */
-	return e1000_get_phy_cfg_done(hw);
-}
-
-/**
- * e1000_phy_reset - reset the phy to commit settings
- * @hw: Struct containing variables accessed by shared code
- *
- * Resets the PHY
- * Sets bit 15 of the MII Control register
- */
-s32 e1000_phy_reset(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 phy_data;
-
-	e_dbg("e1000_phy_reset");
-
-	switch (hw->phy_type) {
-	case e1000_phy_igp:
-		ret_val = e1000_phy_hw_reset(hw);
-		if (ret_val)
-			return ret_val;
-		break;
-	default:
-		ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		phy_data |= MII_CR_RESET;
-		ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
-		if (ret_val)
-			return ret_val;
-
-		udelay(1);
-		break;
-	}
-
-	if (hw->phy_type == e1000_phy_igp)
-		e1000_phy_init_script(hw);
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_detect_gig_phy - check the phy type
- * @hw: Struct containing variables accessed by shared code
- *
- * Probes the expected PHY address for known PHY IDs
- */
-static s32 e1000_detect_gig_phy(struct e1000_hw *hw)
-{
-	s32 phy_init_status, ret_val;
-	u16 phy_id_high, phy_id_low;
-	bool match = false;
-
-	e_dbg("e1000_detect_gig_phy");
-
-	if (hw->phy_id != 0)
-		return E1000_SUCCESS;
-
-	/* Read the PHY ID Registers to identify which PHY is onboard. */
-	ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high);
-	if (ret_val)
-		return ret_val;
-
-	hw->phy_id = (u32) (phy_id_high << 16);
-	udelay(20);
-	ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low);
-	if (ret_val)
-		return ret_val;
-
-	hw->phy_id |= (u32) (phy_id_low & PHY_REVISION_MASK);
-	hw->phy_revision = (u32) phy_id_low & ~PHY_REVISION_MASK;
-
-	switch (hw->mac_type) {
-	case e1000_82543:
-		if (hw->phy_id == M88E1000_E_PHY_ID)
-			match = true;
-		break;
-	case e1000_82544:
-		if (hw->phy_id == M88E1000_I_PHY_ID)
-			match = true;
-		break;
-	case e1000_82540:
-	case e1000_82545:
-	case e1000_82545_rev_3:
-	case e1000_82546:
-	case e1000_82546_rev_3:
-		if (hw->phy_id == M88E1011_I_PHY_ID)
-			match = true;
-		break;
-	case e1000_ce4100:
-		if ((hw->phy_id == RTL8211B_PHY_ID) ||
-		    (hw->phy_id == RTL8201N_PHY_ID) ||
-		    (hw->phy_id == M88E1118_E_PHY_ID))
-			match = true;
-		break;
-	case e1000_82541:
-	case e1000_82541_rev_2:
-	case e1000_82547:
-	case e1000_82547_rev_2:
-		if (hw->phy_id == IGP01E1000_I_PHY_ID)
-			match = true;
-		break;
-	default:
-		e_dbg("Invalid MAC type %d\n", hw->mac_type);
-		return -E1000_ERR_CONFIG;
-	}
-	phy_init_status = e1000_set_phy_type(hw);
-
-	if ((match) && (phy_init_status == E1000_SUCCESS)) {
-		e_dbg("PHY ID 0x%X detected\n", hw->phy_id);
-		return E1000_SUCCESS;
-	}
-	e_dbg("Invalid PHY ID 0x%X\n", hw->phy_id);
-	return -E1000_ERR_PHY;
-}
-
-/**
- * e1000_phy_reset_dsp - reset DSP
- * @hw: Struct containing variables accessed by shared code
- *
- * Resets the PHY's DSP
- */
-static s32 e1000_phy_reset_dsp(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	e_dbg("e1000_phy_reset_dsp");
-
-	do {
-		ret_val = e1000_write_phy_reg(hw, 29, 0x001d);
-		if (ret_val)
-			break;
-		ret_val = e1000_write_phy_reg(hw, 30, 0x00c1);
-		if (ret_val)
-			break;
-		ret_val = e1000_write_phy_reg(hw, 30, 0x0000);
-		if (ret_val)
-			break;
-		ret_val = E1000_SUCCESS;
-	} while (0);
-
-	return ret_val;
-}
-
-/**
- * e1000_phy_igp_get_info - get igp specific registers
- * @hw: Struct containing variables accessed by shared code
- * @phy_info: PHY information structure
- *
- * Get PHY information from various PHY registers for igp PHY only.
- */
-static s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
-				  struct e1000_phy_info *phy_info)
-{
-	s32 ret_val;
-	u16 phy_data, min_length, max_length, average;
-	e1000_rev_polarity polarity;
-
-	e_dbg("e1000_phy_igp_get_info");
-
-	/* The downshift status is checked only once, after link is established,
-	 * and it stored in the hw->speed_downgraded parameter. */
-	phy_info->downshift = (e1000_downshift) hw->speed_downgraded;
-
-	/* IGP01E1000 does not need to support it. */
-	phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal;
-
-	/* IGP01E1000 always correct polarity reversal */
-	phy_info->polarity_correction = e1000_polarity_reversal_enabled;
-
-	/* Check polarity status */
-	ret_val = e1000_check_polarity(hw, &polarity);
-	if (ret_val)
-		return ret_val;
-
-	phy_info->cable_polarity = polarity;
-
-	ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	phy_info->mdix_mode =
-	    (e1000_auto_x_mode) ((phy_data & IGP01E1000_PSSR_MDIX) >>
-				 IGP01E1000_PSSR_MDIX_SHIFT);
-
-	if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
-	    IGP01E1000_PSSR_SPEED_1000MBPS) {
-		/* Local/Remote Receiver Information are only valid at 1000 Mbps */
-		ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >>
-				      SR_1000T_LOCAL_RX_STATUS_SHIFT) ?
-		    e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
-		phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >>
-				       SR_1000T_REMOTE_RX_STATUS_SHIFT) ?
-		    e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
-
-		/* Get cable length */
-		ret_val = e1000_get_cable_length(hw, &min_length, &max_length);
-		if (ret_val)
-			return ret_val;
-
-		/* Translate to old method */
-		average = (max_length + min_length) / 2;
-
-		if (average <= e1000_igp_cable_length_50)
-			phy_info->cable_length = e1000_cable_length_50;
-		else if (average <= e1000_igp_cable_length_80)
-			phy_info->cable_length = e1000_cable_length_50_80;
-		else if (average <= e1000_igp_cable_length_110)
-			phy_info->cable_length = e1000_cable_length_80_110;
-		else if (average <= e1000_igp_cable_length_140)
-			phy_info->cable_length = e1000_cable_length_110_140;
-		else
-			phy_info->cable_length = e1000_cable_length_140;
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_phy_m88_get_info - get m88 specific registers
- * @hw: Struct containing variables accessed by shared code
- * @phy_info: PHY information structure
- *
- * Get PHY information from various PHY registers for m88 PHY only.
- */
-static s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
-				  struct e1000_phy_info *phy_info)
-{
-	s32 ret_val;
-	u16 phy_data;
-	e1000_rev_polarity polarity;
-
-	e_dbg("e1000_phy_m88_get_info");
-
-	/* The downshift status is checked only once, after link is established,
-	 * and it stored in the hw->speed_downgraded parameter. */
-	phy_info->downshift = (e1000_downshift) hw->speed_downgraded;
-
-	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	phy_info->extended_10bt_distance =
-	    ((phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >>
-	     M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT) ?
-	    e1000_10bt_ext_dist_enable_lower :
-	    e1000_10bt_ext_dist_enable_normal;
-
-	phy_info->polarity_correction =
-	    ((phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >>
-	     M88E1000_PSCR_POLARITY_REVERSAL_SHIFT) ?
-	    e1000_polarity_reversal_disabled : e1000_polarity_reversal_enabled;
-
-	/* Check polarity status */
-	ret_val = e1000_check_polarity(hw, &polarity);
-	if (ret_val)
-		return ret_val;
-	phy_info->cable_polarity = polarity;
-
-	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	phy_info->mdix_mode =
-	    (e1000_auto_x_mode) ((phy_data & M88E1000_PSSR_MDIX) >>
-				 M88E1000_PSSR_MDIX_SHIFT);
-
-	if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
-		/* Cable Length Estimation and Local/Remote Receiver Information
-		 * are only valid at 1000 Mbps.
-		 */
-		phy_info->cable_length =
-		    (e1000_cable_length) ((phy_data &
-					   M88E1000_PSSR_CABLE_LENGTH) >>
-					  M88E1000_PSSR_CABLE_LENGTH_SHIFT);
-
-		ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >>
-				      SR_1000T_LOCAL_RX_STATUS_SHIFT) ?
-		    e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
-		phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >>
-				       SR_1000T_REMOTE_RX_STATUS_SHIFT) ?
-		    e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
-
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_phy_get_info - request phy info
- * @hw: Struct containing variables accessed by shared code
- * @phy_info: PHY information structure
- *
- * Get PHY information from various PHY registers
- */
-s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info)
-{
-	s32 ret_val;
-	u16 phy_data;
-
-	e_dbg("e1000_phy_get_info");
-
-	phy_info->cable_length = e1000_cable_length_undefined;
-	phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_undefined;
-	phy_info->cable_polarity = e1000_rev_polarity_undefined;
-	phy_info->downshift = e1000_downshift_undefined;
-	phy_info->polarity_correction = e1000_polarity_reversal_undefined;
-	phy_info->mdix_mode = e1000_auto_x_mode_undefined;
-	phy_info->local_rx = e1000_1000t_rx_status_undefined;
-	phy_info->remote_rx = e1000_1000t_rx_status_undefined;
-
-	if (hw->media_type != e1000_media_type_copper) {
-		e_dbg("PHY info is only valid for copper media\n");
-		return -E1000_ERR_CONFIG;
-	}
-
-	ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	if ((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) {
-		e_dbg("PHY info is only valid if link is up\n");
-		return -E1000_ERR_CONFIG;
-	}
-
-	if (hw->phy_type == e1000_phy_igp)
-		return e1000_phy_igp_get_info(hw, phy_info);
-	else if ((hw->phy_type == e1000_phy_8211) ||
-	         (hw->phy_type == e1000_phy_8201))
-		return E1000_SUCCESS;
-	else
-		return e1000_phy_m88_get_info(hw, phy_info);
-}
-
-s32 e1000_validate_mdi_setting(struct e1000_hw *hw)
-{
-	e_dbg("e1000_validate_mdi_settings");
-
-	if (!hw->autoneg && (hw->mdix == 0 || hw->mdix == 3)) {
-		e_dbg("Invalid MDI setting detected\n");
-		hw->mdix = 1;
-		return -E1000_ERR_CONFIG;
-	}
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_init_eeprom_params - initialize sw eeprom vars
- * @hw: Struct containing variables accessed by shared code
- *
- * Sets up eeprom variables in the hw struct.  Must be called after mac_type
- * is configured.
- */
-s32 e1000_init_eeprom_params(struct e1000_hw *hw)
-{
-	struct e1000_eeprom_info *eeprom = &hw->eeprom;
-	u32 eecd = er32(EECD);
-	s32 ret_val = E1000_SUCCESS;
-	u16 eeprom_size;
-
-	e_dbg("e1000_init_eeprom_params");
-
-	switch (hw->mac_type) {
-	case e1000_82542_rev2_0:
-	case e1000_82542_rev2_1:
-	case e1000_82543:
-	case e1000_82544:
-		eeprom->type = e1000_eeprom_microwire;
-		eeprom->word_size = 64;
-		eeprom->opcode_bits = 3;
-		eeprom->address_bits = 6;
-		eeprom->delay_usec = 50;
-		break;
-	case e1000_82540:
-	case e1000_82545:
-	case e1000_82545_rev_3:
-	case e1000_82546:
-	case e1000_82546_rev_3:
-		eeprom->type = e1000_eeprom_microwire;
-		eeprom->opcode_bits = 3;
-		eeprom->delay_usec = 50;
-		if (eecd & E1000_EECD_SIZE) {
-			eeprom->word_size = 256;
-			eeprom->address_bits = 8;
-		} else {
-			eeprom->word_size = 64;
-			eeprom->address_bits = 6;
-		}
-		break;
-	case e1000_82541:
-	case e1000_82541_rev_2:
-	case e1000_82547:
-	case e1000_82547_rev_2:
-		if (eecd & E1000_EECD_TYPE) {
-			eeprom->type = e1000_eeprom_spi;
-			eeprom->opcode_bits = 8;
-			eeprom->delay_usec = 1;
-			if (eecd & E1000_EECD_ADDR_BITS) {
-				eeprom->page_size = 32;
-				eeprom->address_bits = 16;
-			} else {
-				eeprom->page_size = 8;
-				eeprom->address_bits = 8;
-			}
-		} else {
-			eeprom->type = e1000_eeprom_microwire;
-			eeprom->opcode_bits = 3;
-			eeprom->delay_usec = 50;
-			if (eecd & E1000_EECD_ADDR_BITS) {
-				eeprom->word_size = 256;
-				eeprom->address_bits = 8;
-			} else {
-				eeprom->word_size = 64;
-				eeprom->address_bits = 6;
-			}
-		}
-		break;
-	default:
-		break;
-	}
-
-	if (eeprom->type == e1000_eeprom_spi) {
-		/* eeprom_size will be an enum [0..8] that maps to eeprom sizes 128B to
-		 * 32KB (incremented by powers of 2).
-		 */
-		/* Set to default value for initial eeprom read. */
-		eeprom->word_size = 64;
-		ret_val = e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size);
-		if (ret_val)
-			return ret_val;
-		eeprom_size =
-		    (eeprom_size & EEPROM_SIZE_MASK) >> EEPROM_SIZE_SHIFT;
-		/* 256B eeprom size was not supported in earlier hardware, so we
-		 * bump eeprom_size up one to ensure that "1" (which maps to 256B)
-		 * is never the result used in the shifting logic below. */
-		if (eeprom_size)
-			eeprom_size++;
-
-		eeprom->word_size = 1 << (eeprom_size + EEPROM_WORD_SIZE_SHIFT);
-	}
-	return ret_val;
-}
-
-/**
- * e1000_raise_ee_clk - Raises the EEPROM's clock input.
- * @hw: Struct containing variables accessed by shared code
- * @eecd: EECD's current value
- */
-static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd)
-{
-	/* Raise the clock input to the EEPROM (by setting the SK bit), and then
-	 * wait <delay> microseconds.
-	 */
-	*eecd = *eecd | E1000_EECD_SK;
-	ew32(EECD, *eecd);
-	E1000_WRITE_FLUSH();
-	udelay(hw->eeprom.delay_usec);
-}
-
-/**
- * e1000_lower_ee_clk - Lowers the EEPROM's clock input.
- * @hw: Struct containing variables accessed by shared code
- * @eecd: EECD's current value
- */
-static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd)
-{
-	/* Lower the clock input to the EEPROM (by clearing the SK bit), and then
-	 * wait 50 microseconds.
-	 */
-	*eecd = *eecd & ~E1000_EECD_SK;
-	ew32(EECD, *eecd);
-	E1000_WRITE_FLUSH();
-	udelay(hw->eeprom.delay_usec);
-}
-
-/**
- * e1000_shift_out_ee_bits - Shift data bits out to the EEPROM.
- * @hw: Struct containing variables accessed by shared code
- * @data: data to send to the EEPROM
- * @count: number of bits to shift out
- */
-static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count)
-{
-	struct e1000_eeprom_info *eeprom = &hw->eeprom;
-	u32 eecd;
-	u32 mask;
-
-	/* We need to shift "count" bits out to the EEPROM. So, value in the
-	 * "data" parameter will be shifted out to the EEPROM one bit at a time.
-	 * In order to do this, "data" must be broken down into bits.
-	 */
-	mask = 0x01 << (count - 1);
-	eecd = er32(EECD);
-	if (eeprom->type == e1000_eeprom_microwire) {
-		eecd &= ~E1000_EECD_DO;
-	} else if (eeprom->type == e1000_eeprom_spi) {
-		eecd |= E1000_EECD_DO;
-	}
-	do {
-		/* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1",
-		 * and then raising and then lowering the clock (the SK bit controls
-		 * the clock input to the EEPROM).  A "0" is shifted out to the EEPROM
-		 * by setting "DI" to "0" and then raising and then lowering the clock.
-		 */
-		eecd &= ~E1000_EECD_DI;
-
-		if (data & mask)
-			eecd |= E1000_EECD_DI;
-
-		ew32(EECD, eecd);
-		E1000_WRITE_FLUSH();
-
-		udelay(eeprom->delay_usec);
-
-		e1000_raise_ee_clk(hw, &eecd);
-		e1000_lower_ee_clk(hw, &eecd);
-
-		mask = mask >> 1;
-
-	} while (mask);
-
-	/* We leave the "DI" bit set to "0" when we leave this routine. */
-	eecd &= ~E1000_EECD_DI;
-	ew32(EECD, eecd);
-}
-
-/**
- * e1000_shift_in_ee_bits - Shift data bits in from the EEPROM
- * @hw: Struct containing variables accessed by shared code
- * @count: number of bits to shift in
- */
-static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count)
-{
-	u32 eecd;
-	u32 i;
-	u16 data;
-
-	/* In order to read a register from the EEPROM, we need to shift 'count'
-	 * bits in from the EEPROM. Bits are "shifted in" by raising the clock
-	 * input to the EEPROM (setting the SK bit), and then reading the value of
-	 * the "DO" bit.  During this "shifting in" process the "DI" bit should
-	 * always be clear.
-	 */
-
-	eecd = er32(EECD);
-
-	eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
-	data = 0;
-
-	for (i = 0; i < count; i++) {
-		data = data << 1;
-		e1000_raise_ee_clk(hw, &eecd);
-
-		eecd = er32(EECD);
-
-		eecd &= ~(E1000_EECD_DI);
-		if (eecd & E1000_EECD_DO)
-			data |= 1;
-
-		e1000_lower_ee_clk(hw, &eecd);
-	}
-
-	return data;
-}
-
-/**
- * e1000_acquire_eeprom - Prepares EEPROM for access
- * @hw: Struct containing variables accessed by shared code
- *
- * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
- * function should be called before issuing a command to the EEPROM.
- */
-static s32 e1000_acquire_eeprom(struct e1000_hw *hw)
-{
-	struct e1000_eeprom_info *eeprom = &hw->eeprom;
-	u32 eecd, i = 0;
-
-	e_dbg("e1000_acquire_eeprom");
-
-	eecd = er32(EECD);
-
-	/* Request EEPROM Access */
-	if (hw->mac_type > e1000_82544) {
-		eecd |= E1000_EECD_REQ;
-		ew32(EECD, eecd);
-		eecd = er32(EECD);
-		while ((!(eecd & E1000_EECD_GNT)) &&
-		       (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
-			i++;
-			udelay(5);
-			eecd = er32(EECD);
-		}
-		if (!(eecd & E1000_EECD_GNT)) {
-			eecd &= ~E1000_EECD_REQ;
-			ew32(EECD, eecd);
-			e_dbg("Could not acquire EEPROM grant\n");
-			return -E1000_ERR_EEPROM;
-		}
-	}
-
-	/* Setup EEPROM for Read/Write */
-
-	if (eeprom->type == e1000_eeprom_microwire) {
-		/* Clear SK and DI */
-		eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
-		ew32(EECD, eecd);
-
-		/* Set CS */
-		eecd |= E1000_EECD_CS;
-		ew32(EECD, eecd);
-	} else if (eeprom->type == e1000_eeprom_spi) {
-		/* Clear SK and CS */
-		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
-		ew32(EECD, eecd);
-		E1000_WRITE_FLUSH();
-		udelay(1);
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_standby_eeprom - Returns EEPROM to a "standby" state
- * @hw: Struct containing variables accessed by shared code
- */
-static void e1000_standby_eeprom(struct e1000_hw *hw)
-{
-	struct e1000_eeprom_info *eeprom = &hw->eeprom;
-	u32 eecd;
-
-	eecd = er32(EECD);
-
-	if (eeprom->type == e1000_eeprom_microwire) {
-		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
-		ew32(EECD, eecd);
-		E1000_WRITE_FLUSH();
-		udelay(eeprom->delay_usec);
-
-		/* Clock high */
-		eecd |= E1000_EECD_SK;
-		ew32(EECD, eecd);
-		E1000_WRITE_FLUSH();
-		udelay(eeprom->delay_usec);
-
-		/* Select EEPROM */
-		eecd |= E1000_EECD_CS;
-		ew32(EECD, eecd);
-		E1000_WRITE_FLUSH();
-		udelay(eeprom->delay_usec);
-
-		/* Clock low */
-		eecd &= ~E1000_EECD_SK;
-		ew32(EECD, eecd);
-		E1000_WRITE_FLUSH();
-		udelay(eeprom->delay_usec);
-	} else if (eeprom->type == e1000_eeprom_spi) {
-		/* Toggle CS to flush commands */
-		eecd |= E1000_EECD_CS;
-		ew32(EECD, eecd);
-		E1000_WRITE_FLUSH();
-		udelay(eeprom->delay_usec);
-		eecd &= ~E1000_EECD_CS;
-		ew32(EECD, eecd);
-		E1000_WRITE_FLUSH();
-		udelay(eeprom->delay_usec);
-	}
-}
-
-/**
- * e1000_release_eeprom - drop chip select
- * @hw: Struct containing variables accessed by shared code
- *
- * Terminates a command by inverting the EEPROM's chip select pin
- */
-static void e1000_release_eeprom(struct e1000_hw *hw)
-{
-	u32 eecd;
-
-	e_dbg("e1000_release_eeprom");
-
-	eecd = er32(EECD);
-
-	if (hw->eeprom.type == e1000_eeprom_spi) {
-		eecd |= E1000_EECD_CS;	/* Pull CS high */
-		eecd &= ~E1000_EECD_SK;	/* Lower SCK */
-
-		ew32(EECD, eecd);
-		E1000_WRITE_FLUSH();
-
-		udelay(hw->eeprom.delay_usec);
-	} else if (hw->eeprom.type == e1000_eeprom_microwire) {
-		/* cleanup eeprom */
-
-		/* CS on Microwire is active-high */
-		eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
-
-		ew32(EECD, eecd);
-
-		/* Rising edge of clock */
-		eecd |= E1000_EECD_SK;
-		ew32(EECD, eecd);
-		E1000_WRITE_FLUSH();
-		udelay(hw->eeprom.delay_usec);
-
-		/* Falling edge of clock */
-		eecd &= ~E1000_EECD_SK;
-		ew32(EECD, eecd);
-		E1000_WRITE_FLUSH();
-		udelay(hw->eeprom.delay_usec);
-	}
-
-	/* Stop requesting EEPROM access */
-	if (hw->mac_type > e1000_82544) {
-		eecd &= ~E1000_EECD_REQ;
-		ew32(EECD, eecd);
-	}
-}
-
-/**
- * e1000_spi_eeprom_ready - Reads a 16 bit word from the EEPROM.
- * @hw: Struct containing variables accessed by shared code
- */
-static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw)
-{
-	u16 retry_count = 0;
-	u8 spi_stat_reg;
-
-	e_dbg("e1000_spi_eeprom_ready");
-
-	/* Read "Status Register" repeatedly until the LSB is cleared.  The
-	 * EEPROM will signal that the command has been completed by clearing
-	 * bit 0 of the internal status register.  If it's not cleared within
-	 * 5 milliseconds, then error out.
-	 */
-	retry_count = 0;
-	do {
-		e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI,
-					hw->eeprom.opcode_bits);
-		spi_stat_reg = (u8) e1000_shift_in_ee_bits(hw, 8);
-		if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI))
-			break;
-
-		udelay(5);
-		retry_count += 5;
-
-		e1000_standby_eeprom(hw);
-	} while (retry_count < EEPROM_MAX_RETRY_SPI);
-
-	/* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and
-	 * only 0-5mSec on 5V devices)
-	 */
-	if (retry_count >= EEPROM_MAX_RETRY_SPI) {
-		e_dbg("SPI EEPROM Status error\n");
-		return -E1000_ERR_EEPROM;
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_read_eeprom - Reads a 16 bit word from the EEPROM.
- * @hw: Struct containing variables accessed by shared code
- * @offset: offset of  word in the EEPROM to read
- * @data: word read from the EEPROM
- * @words: number of words to read
- */
-s32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
-{
-	s32 ret;
-	spin_lock(&e1000_eeprom_lock);
-	ret = e1000_do_read_eeprom(hw, offset, words, data);
-	spin_unlock(&e1000_eeprom_lock);
-	return ret;
-}
-
-static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
-				u16 *data)
-{
-	struct e1000_eeprom_info *eeprom = &hw->eeprom;
-	u32 i = 0;
-
-	e_dbg("e1000_read_eeprom");
-
-	if (hw->mac_type == e1000_ce4100) {
-		GBE_CONFIG_FLASH_READ(GBE_CONFIG_BASE_VIRT, offset, words,
-		                      data);
-		return E1000_SUCCESS;
-	}
-
-	/* If eeprom is not yet detected, do so now */
-	if (eeprom->word_size == 0)
-		e1000_init_eeprom_params(hw);
-
-	/* A check for invalid values:  offset too large, too many words, and not
-	 * enough words.
-	 */
-	if ((offset >= eeprom->word_size)
-	    || (words > eeprom->word_size - offset) || (words == 0)) {
-		e_dbg("\"words\" parameter out of bounds. Words = %d,"
-		      "size = %d\n", offset, eeprom->word_size);
-		return -E1000_ERR_EEPROM;
-	}
-
-	/* EEPROM's that don't use EERD to read require us to bit-bang the SPI
-	 * directly. In this case, we need to acquire the EEPROM so that
-	 * FW or other port software does not interrupt.
-	 */
-	/* Prepare the EEPROM for bit-bang reading */
-	if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
-		return -E1000_ERR_EEPROM;
-
-	/* Set up the SPI or Microwire EEPROM for bit-bang reading.  We have
-	 * acquired the EEPROM at this point, so any returns should release it */
-	if (eeprom->type == e1000_eeprom_spi) {
-		u16 word_in;
-		u8 read_opcode = EEPROM_READ_OPCODE_SPI;
-
-		if (e1000_spi_eeprom_ready(hw)) {
-			e1000_release_eeprom(hw);
-			return -E1000_ERR_EEPROM;
-		}
-
-		e1000_standby_eeprom(hw);
-
-		/* Some SPI eeproms use the 8th address bit embedded in the opcode */
-		if ((eeprom->address_bits == 8) && (offset >= 128))
-			read_opcode |= EEPROM_A8_OPCODE_SPI;
-
-		/* Send the READ command (opcode + addr)  */
-		e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits);
-		e1000_shift_out_ee_bits(hw, (u16) (offset * 2),
-					eeprom->address_bits);
-
-		/* Read the data.  The address of the eeprom internally increments with
-		 * each byte (spi) being read, saving on the overhead of eeprom setup
-		 * and tear-down.  The address counter will roll over if reading beyond
-		 * the size of the eeprom, thus allowing the entire memory to be read
-		 * starting from any offset. */
-		for (i = 0; i < words; i++) {
-			word_in = e1000_shift_in_ee_bits(hw, 16);
-			data[i] = (word_in >> 8) | (word_in << 8);
-		}
-	} else if (eeprom->type == e1000_eeprom_microwire) {
-		for (i = 0; i < words; i++) {
-			/* Send the READ command (opcode + addr)  */
-			e1000_shift_out_ee_bits(hw,
-						EEPROM_READ_OPCODE_MICROWIRE,
-						eeprom->opcode_bits);
-			e1000_shift_out_ee_bits(hw, (u16) (offset + i),
-						eeprom->address_bits);
-
-			/* Read the data.  For microwire, each word requires the overhead
-			 * of eeprom setup and tear-down. */
-			data[i] = e1000_shift_in_ee_bits(hw, 16);
-			e1000_standby_eeprom(hw);
-		}
-	}
-
-	/* End this read operation */
-	e1000_release_eeprom(hw);
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_validate_eeprom_checksum - Verifies that the EEPROM has a valid checksum
- * @hw: Struct containing variables accessed by shared code
- *
- * Reads the first 64 16 bit words of the EEPROM and sums the values read.
- * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
- * valid.
- */
-s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw)
-{
-	u16 checksum = 0;
-	u16 i, eeprom_data;
-
-	e_dbg("e1000_validate_eeprom_checksum");
-
-	for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
-		if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
-			e_dbg("EEPROM Read Error\n");
-			return -E1000_ERR_EEPROM;
-		}
-		checksum += eeprom_data;
-	}
-
-#ifdef CONFIG_PARISC
-	/* This is a signature and not a checksum on HP c8000 */
-	if ((hw->subsystem_vendor_id == 0x103C) && (eeprom_data == 0x16d6))
-		return E1000_SUCCESS;
-
-#endif
-	if (checksum == (u16) EEPROM_SUM)
-		return E1000_SUCCESS;
-	else {
-		e_dbg("EEPROM Checksum Invalid\n");
-		return -E1000_ERR_EEPROM;
-	}
-}
-
-/**
- * e1000_update_eeprom_checksum - Calculates/writes the EEPROM checksum
- * @hw: Struct containing variables accessed by shared code
- *
- * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
- * Writes the difference to word offset 63 of the EEPROM.
- */
-s32 e1000_update_eeprom_checksum(struct e1000_hw *hw)
-{
-	u16 checksum = 0;
-	u16 i, eeprom_data;
-
-	e_dbg("e1000_update_eeprom_checksum");
-
-	for (i = 0; i < EEPROM_CHECKSUM_REG; i++) {
-		if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
-			e_dbg("EEPROM Read Error\n");
-			return -E1000_ERR_EEPROM;
-		}
-		checksum += eeprom_data;
-	}
-	checksum = (u16) EEPROM_SUM - checksum;
-	if (e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
-		e_dbg("EEPROM Write Error\n");
-		return -E1000_ERR_EEPROM;
-	}
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_write_eeprom - write words to the different EEPROM types.
- * @hw: Struct containing variables accessed by shared code
- * @offset: offset within the EEPROM to be written to
- * @words: number of words to write
- * @data: 16 bit word to be written to the EEPROM
- *
- * If e1000_update_eeprom_checksum is not called after this function, the
- * EEPROM will most likely contain an invalid checksum.
- */
-s32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
-{
-	s32 ret;
-	spin_lock(&e1000_eeprom_lock);
-	ret = e1000_do_write_eeprom(hw, offset, words, data);
-	spin_unlock(&e1000_eeprom_lock);
-	return ret;
-}
-
-static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
-				 u16 *data)
-{
-	struct e1000_eeprom_info *eeprom = &hw->eeprom;
-	s32 status = 0;
-
-	e_dbg("e1000_write_eeprom");
-
-	if (hw->mac_type == e1000_ce4100) {
-		GBE_CONFIG_FLASH_WRITE(GBE_CONFIG_BASE_VIRT, offset, words,
-		                       data);
-		return E1000_SUCCESS;
-	}
-
-	/* If eeprom is not yet detected, do so now */
-	if (eeprom->word_size == 0)
-		e1000_init_eeprom_params(hw);
-
-	/* A check for invalid values:  offset too large, too many words, and not
-	 * enough words.
-	 */
-	if ((offset >= eeprom->word_size)
-	    || (words > eeprom->word_size - offset) || (words == 0)) {
-		e_dbg("\"words\" parameter out of bounds\n");
-		return -E1000_ERR_EEPROM;
-	}
-
-	/* Prepare the EEPROM for writing  */
-	if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
-		return -E1000_ERR_EEPROM;
-
-	if (eeprom->type == e1000_eeprom_microwire) {
-		status = e1000_write_eeprom_microwire(hw, offset, words, data);
-	} else {
-		status = e1000_write_eeprom_spi(hw, offset, words, data);
-		msleep(10);
-	}
-
-	/* Done with writing */
-	e1000_release_eeprom(hw);
-
-	return status;
-}
-
-/**
- * e1000_write_eeprom_spi - Writes a 16 bit word to a given offset in an SPI EEPROM.
- * @hw: Struct containing variables accessed by shared code
- * @offset: offset within the EEPROM to be written to
- * @words: number of words to write
- * @data: pointer to array of 8 bit words to be written to the EEPROM
- */
-static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset, u16 words,
-				  u16 *data)
-{
-	struct e1000_eeprom_info *eeprom = &hw->eeprom;
-	u16 widx = 0;
-
-	e_dbg("e1000_write_eeprom_spi");
-
-	while (widx < words) {
-		u8 write_opcode = EEPROM_WRITE_OPCODE_SPI;
-
-		if (e1000_spi_eeprom_ready(hw))
-			return -E1000_ERR_EEPROM;
-
-		e1000_standby_eeprom(hw);
-
-		/*  Send the WRITE ENABLE command (8 bit opcode )  */
-		e1000_shift_out_ee_bits(hw, EEPROM_WREN_OPCODE_SPI,
-					eeprom->opcode_bits);
-
-		e1000_standby_eeprom(hw);
-
-		/* Some SPI eeproms use the 8th address bit embedded in the opcode */
-		if ((eeprom->address_bits == 8) && (offset >= 128))
-			write_opcode |= EEPROM_A8_OPCODE_SPI;
-
-		/* Send the Write command (8-bit opcode + addr) */
-		e1000_shift_out_ee_bits(hw, write_opcode, eeprom->opcode_bits);
-
-		e1000_shift_out_ee_bits(hw, (u16) ((offset + widx) * 2),
-					eeprom->address_bits);
-
-		/* Send the data */
-
-		/* Loop to allow for up to whole page write (32 bytes) of eeprom */
-		while (widx < words) {
-			u16 word_out = data[widx];
-			word_out = (word_out >> 8) | (word_out << 8);
-			e1000_shift_out_ee_bits(hw, word_out, 16);
-			widx++;
-
-			/* Some larger eeprom sizes are capable of a 32-byte PAGE WRITE
-			 * operation, while the smaller eeproms are capable of an 8-byte
-			 * PAGE WRITE operation.  Break the inner loop to pass new address
-			 */
-			if ((((offset + widx) * 2) % eeprom->page_size) == 0) {
-				e1000_standby_eeprom(hw);
-				break;
-			}
-		}
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_write_eeprom_microwire - Writes a 16 bit word to a given offset in a Microwire EEPROM.
- * @hw: Struct containing variables accessed by shared code
- * @offset: offset within the EEPROM to be written to
- * @words: number of words to write
- * @data: pointer to array of 8 bit words to be written to the EEPROM
- */
-static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
-					u16 words, u16 *data)
-{
-	struct e1000_eeprom_info *eeprom = &hw->eeprom;
-	u32 eecd;
-	u16 words_written = 0;
-	u16 i = 0;
-
-	e_dbg("e1000_write_eeprom_microwire");
-
-	/* Send the write enable command to the EEPROM (3-bit opcode plus
-	 * 6/8-bit dummy address beginning with 11).  It's less work to include
-	 * the 11 of the dummy address as part of the opcode than it is to shift
-	 * it over the correct number of bits for the address.  This puts the
-	 * EEPROM into write/erase mode.
-	 */
-	e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE_MICROWIRE,
-				(u16) (eeprom->opcode_bits + 2));
-
-	e1000_shift_out_ee_bits(hw, 0, (u16) (eeprom->address_bits - 2));
-
-	/* Prepare the EEPROM */
-	e1000_standby_eeprom(hw);
-
-	while (words_written < words) {
-		/* Send the Write command (3-bit opcode + addr) */
-		e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE_MICROWIRE,
-					eeprom->opcode_bits);
-
-		e1000_shift_out_ee_bits(hw, (u16) (offset + words_written),
-					eeprom->address_bits);
-
-		/* Send the data */
-		e1000_shift_out_ee_bits(hw, data[words_written], 16);
-
-		/* Toggle the CS line.  This in effect tells the EEPROM to execute
-		 * the previous command.
-		 */
-		e1000_standby_eeprom(hw);
-
-		/* Read DO repeatedly until it is high (equal to '1').  The EEPROM will
-		 * signal that the command has been completed by raising the DO signal.
-		 * If DO does not go high in 10 milliseconds, then error out.
-		 */
-		for (i = 0; i < 200; i++) {
-			eecd = er32(EECD);
-			if (eecd & E1000_EECD_DO)
-				break;
-			udelay(50);
-		}
-		if (i == 200) {
-			e_dbg("EEPROM Write did not complete\n");
-			return -E1000_ERR_EEPROM;
-		}
-
-		/* Recover from write */
-		e1000_standby_eeprom(hw);
-
-		words_written++;
-	}
-
-	/* Send the write disable command to the EEPROM (3-bit opcode plus
-	 * 6/8-bit dummy address beginning with 10).  It's less work to include
-	 * the 10 of the dummy address as part of the opcode than it is to shift
-	 * it over the correct number of bits for the address.  This takes the
-	 * EEPROM out of write/erase mode.
-	 */
-	e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE_MICROWIRE,
-				(u16) (eeprom->opcode_bits + 2));
-
-	e1000_shift_out_ee_bits(hw, 0, (u16) (eeprom->address_bits - 2));
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_read_mac_addr - read the adapters MAC from eeprom
- * @hw: Struct containing variables accessed by shared code
- *
- * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
- * second function of dual function devices
- */
-s32 e1000_read_mac_addr(struct e1000_hw *hw)
-{
-	u16 offset;
-	u16 eeprom_data, i;
-
-	e_dbg("e1000_read_mac_addr");
-
-	for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
-		offset = i >> 1;
-		if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
-			e_dbg("EEPROM Read Error\n");
-			return -E1000_ERR_EEPROM;
-		}
-		hw->perm_mac_addr[i] = (u8) (eeprom_data & 0x00FF);
-		hw->perm_mac_addr[i + 1] = (u8) (eeprom_data >> 8);
-	}
-
-	switch (hw->mac_type) {
-	default:
-		break;
-	case e1000_82546:
-	case e1000_82546_rev_3:
-		if (er32(STATUS) & E1000_STATUS_FUNC_1)
-			hw->perm_mac_addr[5] ^= 0x01;
-		break;
-	}
-
-	for (i = 0; i < NODE_ADDRESS_SIZE; i++)
-		hw->mac_addr[i] = hw->perm_mac_addr[i];
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_init_rx_addrs - Initializes receive address filters.
- * @hw: Struct containing variables accessed by shared code
- *
- * Places the MAC address in receive address register 0 and clears the rest
- * of the receive address registers. Clears the multicast table. Assumes
- * the receiver is in reset when the routine is called.
- */
-static void e1000_init_rx_addrs(struct e1000_hw *hw)
-{
-	u32 i;
-	u32 rar_num;
-
-	e_dbg("e1000_init_rx_addrs");
-
-	/* Setup the receive address. */
-	e_dbg("Programming MAC Address into RAR[0]\n");
-
-	e1000_rar_set(hw, hw->mac_addr, 0);
-
-	rar_num = E1000_RAR_ENTRIES;
-
-	/* Zero out the other 15 receive addresses. */
-	e_dbg("Clearing RAR[1-15]\n");
-	for (i = 1; i < rar_num; i++) {
-		E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
-		E1000_WRITE_FLUSH();
-		E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
-		E1000_WRITE_FLUSH();
-	}
-}
-
-/**
- * e1000_hash_mc_addr - Hashes an address to determine its location in the multicast table
- * @hw: Struct containing variables accessed by shared code
- * @mc_addr: the multicast address to hash
- */
-u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
-{
-	u32 hash_value = 0;
-
-	/* The portion of the address that is used for the hash table is
-	 * determined by the mc_filter_type setting.
-	 */
-	switch (hw->mc_filter_type) {
-		/* [0] [1] [2] [3] [4] [5]
-		 * 01  AA  00  12  34  56
-		 * LSB                 MSB
-		 */
-	case 0:
-		/* [47:36] i.e. 0x563 for above example address */
-		hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
-		break;
-	case 1:
-		/* [46:35] i.e. 0xAC6 for above example address */
-		hash_value = ((mc_addr[4] >> 3) | (((u16) mc_addr[5]) << 5));
-		break;
-	case 2:
-		/* [45:34] i.e. 0x5D8 for above example address */
-		hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
-		break;
-	case 3:
-		/* [43:32] i.e. 0x634 for above example address */
-		hash_value = ((mc_addr[4]) | (((u16) mc_addr[5]) << 8));
-		break;
-	}
-
-	hash_value &= 0xFFF;
-	return hash_value;
-}
-
-/**
- * e1000_rar_set - Puts an ethernet address into a receive address register.
- * @hw: Struct containing variables accessed by shared code
- * @addr: Address to put into receive address register
- * @index: Receive address register to write
- */
-void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
-{
-	u32 rar_low, rar_high;
-
-	/* 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));
-	rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
-
-	/* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx
-	 * unit hang.
-	 *
-	 * Description:
-	 * If there are any Rx frames queued up or otherwise present in the HW
-	 * before RSS is enabled, and then we enable RSS, the HW Rx unit will
-	 * hang.  To work around this issue, we have to disable receives and
-	 * flush out all Rx frames before we enable RSS. To do so, we modify we
-	 * redirect all Rx traffic to manageability and then reset the HW.
-	 * This flushes away Rx frames, and (since the redirections to
-	 * manageability persists across resets) keeps new ones from coming in
-	 * while we work.  Then, we clear the Address Valid AV bit for all MAC
-	 * addresses and undo the re-direction to manageability.
-	 * Now, frames are coming in again, but the MAC won't accept them, so
-	 * far so good.  We now proceed to initialize RSS (if necessary) and
-	 * configure the Rx unit.  Last, we re-enable the AV bits and continue
-	 * on our merry way.
-	 */
-	switch (hw->mac_type) {
-	default:
-		/* Indicate to hardware the Address is Valid. */
-		rar_high |= E1000_RAH_AV;
-		break;
-	}
-
-	E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
-	E1000_WRITE_FLUSH();
-	E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
-	E1000_WRITE_FLUSH();
-}
-
-/**
- * e1000_write_vfta - Writes a value to the specified offset in the VLAN filter table.
- * @hw: Struct containing variables accessed by shared code
- * @offset: Offset in VLAN filer table to write
- * @value: Value to write into VLAN filter table
- */
-void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
-{
-	u32 temp;
-
-	if ((hw->mac_type == e1000_82544) && ((offset & 0x1) == 1)) {
-		temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1));
-		E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
-		E1000_WRITE_FLUSH();
-		E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp);
-		E1000_WRITE_FLUSH();
-	} else {
-		E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
-		E1000_WRITE_FLUSH();
-	}
-}
-
-/**
- * e1000_clear_vfta - Clears the VLAN filer table
- * @hw: Struct containing variables accessed by shared code
- */
-static void e1000_clear_vfta(struct e1000_hw *hw)
-{
-	u32 offset;
-	u32 vfta_value = 0;
-	u32 vfta_offset = 0;
-	u32 vfta_bit_in_reg = 0;
-
-	for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
-		/* If the offset we want to clear is the same offset of the
-		 * manageability VLAN ID, then clear all bits except that of the
-		 * manageability unit */
-		vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
-		E1000_WRITE_REG_ARRAY(hw, VFTA, offset, vfta_value);
-		E1000_WRITE_FLUSH();
-	}
-}
-
-static s32 e1000_id_led_init(struct e1000_hw *hw)
-{
-	u32 ledctl;
-	const u32 ledctl_mask = 0x000000FF;
-	const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON;
-	const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF;
-	u16 eeprom_data, i, temp;
-	const u16 led_mask = 0x0F;
-
-	e_dbg("e1000_id_led_init");
-
-	if (hw->mac_type < e1000_82540) {
-		/* Nothing to do */
-		return E1000_SUCCESS;
-	}
-
-	ledctl = er32(LEDCTL);
-	hw->ledctl_default = ledctl;
-	hw->ledctl_mode1 = hw->ledctl_default;
-	hw->ledctl_mode2 = hw->ledctl_default;
-
-	if (e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, 1, &eeprom_data) < 0) {
-		e_dbg("EEPROM Read Error\n");
-		return -E1000_ERR_EEPROM;
-	}
-
-	if ((eeprom_data == ID_LED_RESERVED_0000) ||
-	    (eeprom_data == ID_LED_RESERVED_FFFF)) {
-		eeprom_data = ID_LED_DEFAULT;
-	}
-
-	for (i = 0; i < 4; i++) {
-		temp = (eeprom_data >> (i << 2)) & led_mask;
-		switch (temp) {
-		case ID_LED_ON1_DEF2:
-		case ID_LED_ON1_ON2:
-		case ID_LED_ON1_OFF2:
-			hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
-			hw->ledctl_mode1 |= ledctl_on << (i << 3);
-			break;
-		case ID_LED_OFF1_DEF2:
-		case ID_LED_OFF1_ON2:
-		case ID_LED_OFF1_OFF2:
-			hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
-			hw->ledctl_mode1 |= ledctl_off << (i << 3);
-			break;
-		default:
-			/* Do nothing */
-			break;
-		}
-		switch (temp) {
-		case ID_LED_DEF1_ON2:
-		case ID_LED_ON1_ON2:
-		case ID_LED_OFF1_ON2:
-			hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
-			hw->ledctl_mode2 |= ledctl_on << (i << 3);
-			break;
-		case ID_LED_DEF1_OFF2:
-		case ID_LED_ON1_OFF2:
-		case ID_LED_OFF1_OFF2:
-			hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
-			hw->ledctl_mode2 |= ledctl_off << (i << 3);
-			break;
-		default:
-			/* Do nothing */
-			break;
-		}
-	}
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_setup_led
- * @hw: Struct containing variables accessed by shared code
- *
- * Prepares SW controlable LED for use and saves the current state of the LED.
- */
-s32 e1000_setup_led(struct e1000_hw *hw)
-{
-	u32 ledctl;
-	s32 ret_val = E1000_SUCCESS;
-
-	e_dbg("e1000_setup_led");
-
-	switch (hw->mac_type) {
-	case e1000_82542_rev2_0:
-	case e1000_82542_rev2_1:
-	case e1000_82543:
-	case e1000_82544:
-		/* No setup necessary */
-		break;
-	case e1000_82541:
-	case e1000_82547:
-	case e1000_82541_rev_2:
-	case e1000_82547_rev_2:
-		/* Turn off PHY Smart Power Down (if enabled) */
-		ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO,
-					     &hw->phy_spd_default);
-		if (ret_val)
-			return ret_val;
-		ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
-					      (u16) (hw->phy_spd_default &
-						     ~IGP01E1000_GMII_SPD));
-		if (ret_val)
-			return ret_val;
-		/* Fall Through */
-	default:
-		if (hw->media_type == e1000_media_type_fiber) {
-			ledctl = er32(LEDCTL);
-			/* Save current LEDCTL settings */
-			hw->ledctl_default = ledctl;
-			/* Turn off LED0 */
-			ledctl &= ~(E1000_LEDCTL_LED0_IVRT |
-				    E1000_LEDCTL_LED0_BLINK |
-				    E1000_LEDCTL_LED0_MODE_MASK);
-			ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
-				   E1000_LEDCTL_LED0_MODE_SHIFT);
-			ew32(LEDCTL, ledctl);
-		} else if (hw->media_type == e1000_media_type_copper)
-			ew32(LEDCTL, hw->ledctl_mode1);
-		break;
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_cleanup_led - Restores the saved state of the SW controlable LED.
- * @hw: Struct containing variables accessed by shared code
- */
-s32 e1000_cleanup_led(struct e1000_hw *hw)
-{
-	s32 ret_val = E1000_SUCCESS;
-
-	e_dbg("e1000_cleanup_led");
-
-	switch (hw->mac_type) {
-	case e1000_82542_rev2_0:
-	case e1000_82542_rev2_1:
-	case e1000_82543:
-	case e1000_82544:
-		/* No cleanup necessary */
-		break;
-	case e1000_82541:
-	case e1000_82547:
-	case e1000_82541_rev_2:
-	case e1000_82547_rev_2:
-		/* Turn on PHY Smart Power Down (if previously enabled) */
-		ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
-					      hw->phy_spd_default);
-		if (ret_val)
-			return ret_val;
-		/* Fall Through */
-	default:
-		/* Restore LEDCTL settings */
-		ew32(LEDCTL, hw->ledctl_default);
-		break;
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_led_on - Turns on the software controllable LED
- * @hw: Struct containing variables accessed by shared code
- */
-s32 e1000_led_on(struct e1000_hw *hw)
-{
-	u32 ctrl = er32(CTRL);
-
-	e_dbg("e1000_led_on");
-
-	switch (hw->mac_type) {
-	case e1000_82542_rev2_0:
-	case e1000_82542_rev2_1:
-	case e1000_82543:
-		/* Set SW Defineable Pin 0 to turn on the LED */
-		ctrl |= E1000_CTRL_SWDPIN0;
-		ctrl |= E1000_CTRL_SWDPIO0;
-		break;
-	case e1000_82544:
-		if (hw->media_type == e1000_media_type_fiber) {
-			/* Set SW Defineable Pin 0 to turn on the LED */
-			ctrl |= E1000_CTRL_SWDPIN0;
-			ctrl |= E1000_CTRL_SWDPIO0;
-		} else {
-			/* Clear SW Defineable Pin 0 to turn on the LED */
-			ctrl &= ~E1000_CTRL_SWDPIN0;
-			ctrl |= E1000_CTRL_SWDPIO0;
-		}
-		break;
-	default:
-		if (hw->media_type == e1000_media_type_fiber) {
-			/* Clear SW Defineable Pin 0 to turn on the LED */
-			ctrl &= ~E1000_CTRL_SWDPIN0;
-			ctrl |= E1000_CTRL_SWDPIO0;
-		} else if (hw->media_type == e1000_media_type_copper) {
-			ew32(LEDCTL, hw->ledctl_mode2);
-			return E1000_SUCCESS;
-		}
-		break;
-	}
-
-	ew32(CTRL, ctrl);
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_led_off - Turns off the software controllable LED
- * @hw: Struct containing variables accessed by shared code
- */
-s32 e1000_led_off(struct e1000_hw *hw)
-{
-	u32 ctrl = er32(CTRL);
-
-	e_dbg("e1000_led_off");
-
-	switch (hw->mac_type) {
-	case e1000_82542_rev2_0:
-	case e1000_82542_rev2_1:
-	case e1000_82543:
-		/* Clear SW Defineable Pin 0 to turn off the LED */
-		ctrl &= ~E1000_CTRL_SWDPIN0;
-		ctrl |= E1000_CTRL_SWDPIO0;
-		break;
-	case e1000_82544:
-		if (hw->media_type == e1000_media_type_fiber) {
-			/* Clear SW Defineable Pin 0 to turn off the LED */
-			ctrl &= ~E1000_CTRL_SWDPIN0;
-			ctrl |= E1000_CTRL_SWDPIO0;
-		} else {
-			/* Set SW Defineable Pin 0 to turn off the LED */
-			ctrl |= E1000_CTRL_SWDPIN0;
-			ctrl |= E1000_CTRL_SWDPIO0;
-		}
-		break;
-	default:
-		if (hw->media_type == e1000_media_type_fiber) {
-			/* Set SW Defineable Pin 0 to turn off the LED */
-			ctrl |= E1000_CTRL_SWDPIN0;
-			ctrl |= E1000_CTRL_SWDPIO0;
-		} else if (hw->media_type == e1000_media_type_copper) {
-			ew32(LEDCTL, hw->ledctl_mode1);
-			return E1000_SUCCESS;
-		}
-		break;
-	}
-
-	ew32(CTRL, ctrl);
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_clear_hw_cntrs - Clears all hardware statistics counters.
- * @hw: Struct containing variables accessed by shared code
- */
-static void e1000_clear_hw_cntrs(struct e1000_hw *hw)
-{
-	volatile u32 temp;
-
-	temp = er32(CRCERRS);
-	temp = er32(SYMERRS);
-	temp = er32(MPC);
-	temp = er32(SCC);
-	temp = er32(ECOL);
-	temp = er32(MCC);
-	temp = er32(LATECOL);
-	temp = er32(COLC);
-	temp = er32(DC);
-	temp = er32(SEC);
-	temp = er32(RLEC);
-	temp = er32(XONRXC);
-	temp = er32(XONTXC);
-	temp = er32(XOFFRXC);
-	temp = er32(XOFFTXC);
-	temp = er32(FCRUC);
-
-	temp = er32(PRC64);
-	temp = er32(PRC127);
-	temp = er32(PRC255);
-	temp = er32(PRC511);
-	temp = er32(PRC1023);
-	temp = er32(PRC1522);
-
-	temp = er32(GPRC);
-	temp = er32(BPRC);
-	temp = er32(MPRC);
-	temp = er32(GPTC);
-	temp = er32(GORCL);
-	temp = er32(GORCH);
-	temp = er32(GOTCL);
-	temp = er32(GOTCH);
-	temp = er32(RNBC);
-	temp = er32(RUC);
-	temp = er32(RFC);
-	temp = er32(ROC);
-	temp = er32(RJC);
-	temp = er32(TORL);
-	temp = er32(TORH);
-	temp = er32(TOTL);
-	temp = er32(TOTH);
-	temp = er32(TPR);
-	temp = er32(TPT);
-
-	temp = er32(PTC64);
-	temp = er32(PTC127);
-	temp = er32(PTC255);
-	temp = er32(PTC511);
-	temp = er32(PTC1023);
-	temp = er32(PTC1522);
-
-	temp = er32(MPTC);
-	temp = er32(BPTC);
-
-	if (hw->mac_type < e1000_82543)
-		return;
-
-	temp = er32(ALGNERRC);
-	temp = er32(RXERRC);
-	temp = er32(TNCRS);
-	temp = er32(CEXTERR);
-	temp = er32(TSCTC);
-	temp = er32(TSCTFC);
-
-	if (hw->mac_type <= e1000_82544)
-		return;
-
-	temp = er32(MGTPRC);
-	temp = er32(MGTPDC);
-	temp = er32(MGTPTC);
-}
-
-/**
- * e1000_reset_adaptive - Resets Adaptive IFS to its default state.
- * @hw: Struct containing variables accessed by shared code
- *
- * Call this after e1000_init_hw. You may override the IFS defaults by setting
- * hw->ifs_params_forced to true. However, you must initialize hw->
- * current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio
- * before calling this function.
- */
-void e1000_reset_adaptive(struct e1000_hw *hw)
-{
-	e_dbg("e1000_reset_adaptive");
-
-	if (hw->adaptive_ifs) {
-		if (!hw->ifs_params_forced) {
-			hw->current_ifs_val = 0;
-			hw->ifs_min_val = IFS_MIN;
-			hw->ifs_max_val = IFS_MAX;
-			hw->ifs_step_size = IFS_STEP;
-			hw->ifs_ratio = IFS_RATIO;
-		}
-		hw->in_ifs_mode = false;
-		ew32(AIT, 0);
-	} else {
-		e_dbg("Not in Adaptive IFS mode!\n");
-	}
-}
-
-/**
- * e1000_update_adaptive - update adaptive IFS
- * @hw: Struct containing variables accessed by shared code
- * @tx_packets: Number of transmits since last callback
- * @total_collisions: Number of collisions since last callback
- *
- * Called during the callback/watchdog routine to update IFS value based on
- * the ratio of transmits to collisions.
- */
-void e1000_update_adaptive(struct e1000_hw *hw)
-{
-	e_dbg("e1000_update_adaptive");
-
-	if (hw->adaptive_ifs) {
-		if ((hw->collision_delta *hw->ifs_ratio) > hw->tx_packet_delta) {
-			if (hw->tx_packet_delta > MIN_NUM_XMITS) {
-				hw->in_ifs_mode = true;
-				if (hw->current_ifs_val < hw->ifs_max_val) {
-					if (hw->current_ifs_val == 0)
-						hw->current_ifs_val =
-						    hw->ifs_min_val;
-					else
-						hw->current_ifs_val +=
-						    hw->ifs_step_size;
-					ew32(AIT, hw->current_ifs_val);
-				}
-			}
-		} else {
-			if (hw->in_ifs_mode
-			    && (hw->tx_packet_delta <= MIN_NUM_XMITS)) {
-				hw->current_ifs_val = 0;
-				hw->in_ifs_mode = false;
-				ew32(AIT, 0);
-			}
-		}
-	} else {
-		e_dbg("Not in Adaptive IFS mode!\n");
-	}
-}
-
-/**
- * e1000_tbi_adjust_stats
- * @hw: Struct containing variables accessed by shared code
- * @frame_len: The length of the frame in question
- * @mac_addr: The Ethernet destination address of the frame in question
- *
- * Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT
- */
-void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats,
-			    u32 frame_len, u8 *mac_addr)
-{
-	u64 carry_bit;
-
-	/* First adjust the frame length. */
-	frame_len--;
-	/* We need to adjust the statistics counters, since the hardware
-	 * counters overcount this packet as a CRC error and undercount
-	 * the packet as a good packet
-	 */
-	/* This packet should not be counted as a CRC error.    */
-	stats->crcerrs--;
-	/* This packet does count as a Good Packet Received.    */
-	stats->gprc++;
-
-	/* Adjust the Good Octets received counters             */
-	carry_bit = 0x80000000 & stats->gorcl;
-	stats->gorcl += frame_len;
-	/* If the high bit of Gorcl (the low 32 bits of the Good Octets
-	 * Received Count) was one before the addition,
-	 * AND it is zero after, then we lost the carry out,
-	 * need to add one to Gorch (Good Octets Received Count High).
-	 * This could be simplified if all environments supported
-	 * 64-bit integers.
-	 */
-	if (carry_bit && ((stats->gorcl & 0x80000000) == 0))
-		stats->gorch++;
-	/* Is this a broadcast or multicast?  Check broadcast first,
-	 * since the test for a multicast frame will test positive on
-	 * a broadcast frame.
-	 */
-	if ((mac_addr[0] == (u8) 0xff) && (mac_addr[1] == (u8) 0xff))
-		/* Broadcast packet */
-		stats->bprc++;
-	else if (*mac_addr & 0x01)
-		/* Multicast packet */
-		stats->mprc++;
-
-	if (frame_len == hw->max_frame_size) {
-		/* In this case, the hardware has overcounted the number of
-		 * oversize frames.
-		 */
-		if (stats->roc > 0)
-			stats->roc--;
-	}
-
-	/* Adjust the bin counters when the extra byte put the frame in the
-	 * wrong bin. Remember that the frame_len was adjusted above.
-	 */
-	if (frame_len == 64) {
-		stats->prc64++;
-		stats->prc127--;
-	} else if (frame_len == 127) {
-		stats->prc127++;
-		stats->prc255--;
-	} else if (frame_len == 255) {
-		stats->prc255++;
-		stats->prc511--;
-	} else if (frame_len == 511) {
-		stats->prc511++;
-		stats->prc1023--;
-	} else if (frame_len == 1023) {
-		stats->prc1023++;
-		stats->prc1522--;
-	} else if (frame_len == 1522) {
-		stats->prc1522++;
-	}
-}
-
-/**
- * e1000_get_bus_info
- * @hw: Struct containing variables accessed by shared code
- *
- * Gets the current PCI bus type, speed, and width of the hardware
- */
-void e1000_get_bus_info(struct e1000_hw *hw)
-{
-	u32 status;
-
-	switch (hw->mac_type) {
-	case e1000_82542_rev2_0:
-	case e1000_82542_rev2_1:
-		hw->bus_type = e1000_bus_type_pci;
-		hw->bus_speed = e1000_bus_speed_unknown;
-		hw->bus_width = e1000_bus_width_unknown;
-		break;
-	default:
-		status = er32(STATUS);
-		hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
-		    e1000_bus_type_pcix : e1000_bus_type_pci;
-
-		if (hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
-			hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ?
-			    e1000_bus_speed_66 : e1000_bus_speed_120;
-		} else if (hw->bus_type == e1000_bus_type_pci) {
-			hw->bus_speed = (status & E1000_STATUS_PCI66) ?
-			    e1000_bus_speed_66 : e1000_bus_speed_33;
-		} else {
-			switch (status & E1000_STATUS_PCIX_SPEED) {
-			case E1000_STATUS_PCIX_SPEED_66:
-				hw->bus_speed = e1000_bus_speed_66;
-				break;
-			case E1000_STATUS_PCIX_SPEED_100:
-				hw->bus_speed = e1000_bus_speed_100;
-				break;
-			case E1000_STATUS_PCIX_SPEED_133:
-				hw->bus_speed = e1000_bus_speed_133;
-				break;
-			default:
-				hw->bus_speed = e1000_bus_speed_reserved;
-				break;
-			}
-		}
-		hw->bus_width = (status & E1000_STATUS_BUS64) ?
-		    e1000_bus_width_64 : e1000_bus_width_32;
-		break;
-	}
-}
-
-/**
- * e1000_write_reg_io
- * @hw: Struct containing variables accessed by shared code
- * @offset: offset to write to
- * @value: value to write
- *
- * Writes a value to one of the devices registers using port I/O (as opposed to
- * memory mapped I/O). Only 82544 and newer devices support port I/O.
- */
-static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value)
-{
-	unsigned long io_addr = hw->io_base;
-	unsigned long io_data = hw->io_base + 4;
-
-	e1000_io_write(hw, io_addr, offset);
-	e1000_io_write(hw, io_data, value);
-}
-
-/**
- * e1000_get_cable_length - Estimates the cable length.
- * @hw: Struct containing variables accessed by shared code
- * @min_length: The estimated minimum length
- * @max_length: The estimated maximum length
- *
- * returns: - E1000_ERR_XXX
- *            E1000_SUCCESS
- *
- * This function always returns a ranged length (minimum & maximum).
- * So for M88 phy's, this function interprets the one value returned from the
- * register to the minimum and maximum range.
- * For IGP phy's, the function calculates the range by the AGC registers.
- */
-static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
-				  u16 *max_length)
-{
-	s32 ret_val;
-	u16 agc_value = 0;
-	u16 i, phy_data;
-	u16 cable_length;
-
-	e_dbg("e1000_get_cable_length");
-
-	*min_length = *max_length = 0;
-
-	/* Use old method for Phy older than IGP */
-	if (hw->phy_type == e1000_phy_m88) {
-
-		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
-					     &phy_data);
-		if (ret_val)
-			return ret_val;
-		cable_length = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
-		    M88E1000_PSSR_CABLE_LENGTH_SHIFT;
-
-		/* Convert the enum value to ranged values */
-		switch (cable_length) {
-		case e1000_cable_length_50:
-			*min_length = 0;
-			*max_length = e1000_igp_cable_length_50;
-			break;
-		case e1000_cable_length_50_80:
-			*min_length = e1000_igp_cable_length_50;
-			*max_length = e1000_igp_cable_length_80;
-			break;
-		case e1000_cable_length_80_110:
-			*min_length = e1000_igp_cable_length_80;
-			*max_length = e1000_igp_cable_length_110;
-			break;
-		case e1000_cable_length_110_140:
-			*min_length = e1000_igp_cable_length_110;
-			*max_length = e1000_igp_cable_length_140;
-			break;
-		case e1000_cable_length_140:
-			*min_length = e1000_igp_cable_length_140;
-			*max_length = e1000_igp_cable_length_170;
-			break;
-		default:
-			return -E1000_ERR_PHY;
-			break;
-		}
-	} else if (hw->phy_type == e1000_phy_igp) {	/* For IGP PHY */
-		u16 cur_agc_value;
-		u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
-		static const u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
-		       IGP01E1000_PHY_AGC_A,
-		       IGP01E1000_PHY_AGC_B,
-		       IGP01E1000_PHY_AGC_C,
-		       IGP01E1000_PHY_AGC_D
-		};
-		/* Read the AGC registers for all channels */
-		for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
-
-			ret_val =
-			    e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data);
-			if (ret_val)
-				return ret_val;
-
-			cur_agc_value = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT;
-
-			/* Value bound check. */
-			if ((cur_agc_value >=
-			     IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1)
-			    || (cur_agc_value == 0))
-				return -E1000_ERR_PHY;
-
-			agc_value += cur_agc_value;
-
-			/* Update minimal AGC value. */
-			if (min_agc_value > cur_agc_value)
-				min_agc_value = cur_agc_value;
-		}
-
-		/* Remove the minimal AGC result for length < 50m */
-		if (agc_value <
-		    IGP01E1000_PHY_CHANNEL_NUM * e1000_igp_cable_length_50) {
-			agc_value -= min_agc_value;
-
-			/* Get the average length of the remaining 3 channels */
-			agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1);
-		} else {
-			/* Get the average length of all the 4 channels. */
-			agc_value /= IGP01E1000_PHY_CHANNEL_NUM;
-		}
-
-		/* Set the range of the calculated length. */
-		*min_length = ((e1000_igp_cable_length_table[agc_value] -
-				IGP01E1000_AGC_RANGE) > 0) ?
-		    (e1000_igp_cable_length_table[agc_value] -
-		     IGP01E1000_AGC_RANGE) : 0;
-		*max_length = e1000_igp_cable_length_table[agc_value] +
-		    IGP01E1000_AGC_RANGE;
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_check_polarity - Check the cable polarity
- * @hw: Struct containing variables accessed by shared code
- * @polarity: output parameter : 0 - Polarity is not reversed
- *                               1 - Polarity is reversed.
- *
- * returns: - E1000_ERR_XXX
- *            E1000_SUCCESS
- *
- * For phy's older than IGP, this function simply reads the polarity bit in the
- * Phy Status register.  For IGP phy's, this bit is valid only if link speed is
- * 10 Mbps.  If the link speed is 100 Mbps there is no polarity so this bit will
- * return 0.  If the link speed is 1000 Mbps the polarity status is in the
- * IGP01E1000_PHY_PCS_INIT_REG.
- */
-static s32 e1000_check_polarity(struct e1000_hw *hw,
-				e1000_rev_polarity *polarity)
-{
-	s32 ret_val;
-	u16 phy_data;
-
-	e_dbg("e1000_check_polarity");
-
-	if (hw->phy_type == e1000_phy_m88) {
-		/* return the Polarity bit in the Status register. */
-		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
-					     &phy_data);
-		if (ret_val)
-			return ret_val;
-		*polarity = ((phy_data & M88E1000_PSSR_REV_POLARITY) >>
-			     M88E1000_PSSR_REV_POLARITY_SHIFT) ?
-		    e1000_rev_polarity_reversed : e1000_rev_polarity_normal;
-
-	} else if (hw->phy_type == e1000_phy_igp) {
-		/* Read the Status register to check the speed */
-		ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
-					     &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		/* If speed is 1000 Mbps, must read the IGP01E1000_PHY_PCS_INIT_REG to
-		 * find the polarity status */
-		if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
-		    IGP01E1000_PSSR_SPEED_1000MBPS) {
-
-			/* Read the GIG initialization PCS register (0x00B4) */
-			ret_val =
-			    e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG,
-					       &phy_data);
-			if (ret_val)
-				return ret_val;
-
-			/* Check the polarity bits */
-			*polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ?
-			    e1000_rev_polarity_reversed :
-			    e1000_rev_polarity_normal;
-		} else {
-			/* For 10 Mbps, read the polarity bit in the status register. (for
-			 * 100 Mbps this bit is always 0) */
-			*polarity =
-			    (phy_data & IGP01E1000_PSSR_POLARITY_REVERSED) ?
-			    e1000_rev_polarity_reversed :
-			    e1000_rev_polarity_normal;
-		}
-	}
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_check_downshift - Check if Downshift occurred
- * @hw: Struct containing variables accessed by shared code
- * @downshift: output parameter : 0 - No Downshift occurred.
- *                                1 - Downshift occurred.
- *
- * returns: - E1000_ERR_XXX
- *            E1000_SUCCESS
- *
- * For phy's older than IGP, this function reads the Downshift bit in the Phy
- * Specific Status register.  For IGP phy's, it reads the Downgrade bit in the
- * Link Health register.  In IGP this bit is latched high, so the driver must
- * read it immediately after link is established.
- */
-static s32 e1000_check_downshift(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 phy_data;
-
-	e_dbg("e1000_check_downshift");
-
-	if (hw->phy_type == e1000_phy_igp) {
-		ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH,
-					     &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		hw->speed_downgraded =
-		    (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0;
-	} else if (hw->phy_type == e1000_phy_m88) {
-		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
-					     &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >>
-		    M88E1000_PSSR_DOWNSHIFT_SHIFT;
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_config_dsp_after_link_change
- * @hw: Struct containing variables accessed by shared code
- * @link_up: was link up at the time this was called
- *
- * returns: - E1000_ERR_PHY if fail to read/write the PHY
- *            E1000_SUCCESS at any other case.
- *
- * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a
- * gigabit link is achieved to improve link quality.
- */
-
-static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
-{
-	s32 ret_val;
-	u16 phy_data, phy_saved_data, speed, duplex, i;
-	static const u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
-	       IGP01E1000_PHY_AGC_PARAM_A,
-	       IGP01E1000_PHY_AGC_PARAM_B,
-	       IGP01E1000_PHY_AGC_PARAM_C,
-	       IGP01E1000_PHY_AGC_PARAM_D
-	};
-	u16 min_length, max_length;
-
-	e_dbg("e1000_config_dsp_after_link_change");
-
-	if (hw->phy_type != e1000_phy_igp)
-		return E1000_SUCCESS;
-
-	if (link_up) {
-		ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
-		if (ret_val) {
-			e_dbg("Error getting link speed and duplex\n");
-			return ret_val;
-		}
-
-		if (speed == SPEED_1000) {
-
-			ret_val =
-			    e1000_get_cable_length(hw, &min_length,
-						   &max_length);
-			if (ret_val)
-				return ret_val;
-
-			if ((hw->dsp_config_state == e1000_dsp_config_enabled)
-			    && min_length >= e1000_igp_cable_length_50) {
-
-				for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
-					ret_val =
-					    e1000_read_phy_reg(hw,
-							       dsp_reg_array[i],
-							       &phy_data);
-					if (ret_val)
-						return ret_val;
-
-					phy_data &=
-					    ~IGP01E1000_PHY_EDAC_MU_INDEX;
-
-					ret_val =
-					    e1000_write_phy_reg(hw,
-								dsp_reg_array
-								[i], phy_data);
-					if (ret_val)
-						return ret_val;
-				}
-				hw->dsp_config_state =
-				    e1000_dsp_config_activated;
-			}
-
-			if ((hw->ffe_config_state == e1000_ffe_config_enabled)
-			    && (min_length < e1000_igp_cable_length_50)) {
-
-				u16 ffe_idle_err_timeout =
-				    FFE_IDLE_ERR_COUNT_TIMEOUT_20;
-				u32 idle_errs = 0;
-
-				/* clear previous idle error counts */
-				ret_val =
-				    e1000_read_phy_reg(hw, PHY_1000T_STATUS,
-						       &phy_data);
-				if (ret_val)
-					return ret_val;
-
-				for (i = 0; i < ffe_idle_err_timeout; i++) {
-					udelay(1000);
-					ret_val =
-					    e1000_read_phy_reg(hw,
-							       PHY_1000T_STATUS,
-							       &phy_data);
-					if (ret_val)
-						return ret_val;
-
-					idle_errs +=
-					    (phy_data &
-					     SR_1000T_IDLE_ERROR_CNT);
-					if (idle_errs >
-					    SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT)
-					{
-						hw->ffe_config_state =
-						    e1000_ffe_config_active;
-
-						ret_val =
-						    e1000_write_phy_reg(hw,
-									IGP01E1000_PHY_DSP_FFE,
-									IGP01E1000_PHY_DSP_FFE_CM_CP);
-						if (ret_val)
-							return ret_val;
-						break;
-					}
-
-					if (idle_errs)
-						ffe_idle_err_timeout =
-						    FFE_IDLE_ERR_COUNT_TIMEOUT_100;
-				}
-			}
-		}
-	} else {
-		if (hw->dsp_config_state == e1000_dsp_config_activated) {
-			/* Save off the current value of register 0x2F5B to be restored at
-			 * the end of the routines. */
-			ret_val =
-			    e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
-
-			if (ret_val)
-				return ret_val;
-
-			/* Disable the PHY transmitter */
-			ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
-
-			if (ret_val)
-				return ret_val;
-
-			mdelay(20);
-
-			ret_val = e1000_write_phy_reg(hw, 0x0000,
-						      IGP01E1000_IEEE_FORCE_GIGA);
-			if (ret_val)
-				return ret_val;
-			for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
-				ret_val =
-				    e1000_read_phy_reg(hw, dsp_reg_array[i],
-						       &phy_data);
-				if (ret_val)
-					return ret_val;
-
-				phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
-				phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS;
-
-				ret_val =
-				    e1000_write_phy_reg(hw, dsp_reg_array[i],
-							phy_data);
-				if (ret_val)
-					return ret_val;
-			}
-
-			ret_val = e1000_write_phy_reg(hw, 0x0000,
-						      IGP01E1000_IEEE_RESTART_AUTONEG);
-			if (ret_val)
-				return ret_val;
-
-			mdelay(20);
-
-			/* Now enable the transmitter */
-			ret_val =
-			    e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
-
-			if (ret_val)
-				return ret_val;
-
-			hw->dsp_config_state = e1000_dsp_config_enabled;
-		}
-
-		if (hw->ffe_config_state == e1000_ffe_config_active) {
-			/* Save off the current value of register 0x2F5B to be restored at
-			 * the end of the routines. */
-			ret_val =
-			    e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
-
-			if (ret_val)
-				return ret_val;
-
-			/* Disable the PHY transmitter */
-			ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
-
-			if (ret_val)
-				return ret_val;
-
-			mdelay(20);
-
-			ret_val = e1000_write_phy_reg(hw, 0x0000,
-						      IGP01E1000_IEEE_FORCE_GIGA);
-			if (ret_val)
-				return ret_val;
-			ret_val =
-			    e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE,
-						IGP01E1000_PHY_DSP_FFE_DEFAULT);
-			if (ret_val)
-				return ret_val;
-
-			ret_val = e1000_write_phy_reg(hw, 0x0000,
-						      IGP01E1000_IEEE_RESTART_AUTONEG);
-			if (ret_val)
-				return ret_val;
-
-			mdelay(20);
-
-			/* Now enable the transmitter */
-			ret_val =
-			    e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
-
-			if (ret_val)
-				return ret_val;
-
-			hw->ffe_config_state = e1000_ffe_config_enabled;
-		}
-	}
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_set_phy_mode - Set PHY to class A mode
- * @hw: Struct containing variables accessed by shared code
- *
- * Assumes the following operations will follow to enable the new class mode.
- *  1. Do a PHY soft reset
- *  2. Restart auto-negotiation or force link.
- */
-static s32 e1000_set_phy_mode(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 eeprom_data;
-
-	e_dbg("e1000_set_phy_mode");
-
-	if ((hw->mac_type == e1000_82545_rev_3) &&
-	    (hw->media_type == e1000_media_type_copper)) {
-		ret_val =
-		    e1000_read_eeprom(hw, EEPROM_PHY_CLASS_WORD, 1,
-				      &eeprom_data);
-		if (ret_val) {
-			return ret_val;
-		}
-
-		if ((eeprom_data != EEPROM_RESERVED_WORD) &&
-		    (eeprom_data & EEPROM_PHY_CLASS_A)) {
-			ret_val =
-			    e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT,
-						0x000B);
-			if (ret_val)
-				return ret_val;
-			ret_val =
-			    e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL,
-						0x8104);
-			if (ret_val)
-				return ret_val;
-
-			hw->phy_reset_disable = false;
-		}
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_set_d3_lplu_state - set d3 link power state
- * @hw: Struct containing variables accessed by shared code
- * @active: true to enable lplu false to disable lplu.
- *
- * This function sets the lplu state according to the active flag.  When
- * activating lplu this function also disables smart speed and vise versa.
- * lplu will not be activated unless the device autonegotiation advertisement
- * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes.
- *
- * returns: - E1000_ERR_PHY if fail to read/write the PHY
- *            E1000_SUCCESS at any other case.
- */
-static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active)
-{
-	s32 ret_val;
-	u16 phy_data;
-	e_dbg("e1000_set_d3_lplu_state");
-
-	if (hw->phy_type != e1000_phy_igp)
-		return E1000_SUCCESS;
-
-	/* During driver activity LPLU should not be used or it will attain link
-	 * from the lowest speeds starting from 10Mbps. The capability is used for
-	 * Dx transitions and states */
-	if (hw->mac_type == e1000_82541_rev_2
-	    || hw->mac_type == e1000_82547_rev_2) {
-		ret_val =
-		    e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data);
-		if (ret_val)
-			return ret_val;
-	}
-
-	if (!active) {
-		if (hw->mac_type == e1000_82541_rev_2 ||
-		    hw->mac_type == e1000_82547_rev_2) {
-			phy_data &= ~IGP01E1000_GMII_FLEX_SPD;
-			ret_val =
-			    e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
-						phy_data);
-			if (ret_val)
-				return ret_val;
-		}
-
-		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used during
-		 * Dx states where the power conservation is most important.  During
-		 * driver activity we should enable SmartSpeed, so performance is
-		 * maintained. */
-		if (hw->smart_speed == e1000_smart_speed_on) {
-			ret_val =
-			    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
-					       &phy_data);
-			if (ret_val)
-				return ret_val;
-
-			phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
-			ret_val =
-			    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
-						phy_data);
-			if (ret_val)
-				return ret_val;
-		} else if (hw->smart_speed == e1000_smart_speed_off) {
-			ret_val =
-			    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
-					       &phy_data);
-			if (ret_val)
-				return ret_val;
-
-			phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-			ret_val =
-			    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
-						phy_data);
-			if (ret_val)
-				return ret_val;
-		}
-	} else if ((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT)
-		   || (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL)
-		   || (hw->autoneg_advertised ==
-		       AUTONEG_ADVERTISE_10_100_ALL)) {
-
-		if (hw->mac_type == e1000_82541_rev_2 ||
-		    hw->mac_type == e1000_82547_rev_2) {
-			phy_data |= IGP01E1000_GMII_FLEX_SPD;
-			ret_val =
-			    e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
-						phy_data);
-			if (ret_val)
-				return ret_val;
-		}
-
-		/* When LPLU is enabled we should disable SmartSpeed */
-		ret_val =
-		    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
-				       &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-		ret_val =
-		    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
-					phy_data);
-		if (ret_val)
-			return ret_val;
-
-	}
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_set_vco_speed
- * @hw: Struct containing variables accessed by shared code
- *
- * Change VCO speed register to improve Bit Error Rate performance of SERDES.
- */
-static s32 e1000_set_vco_speed(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 default_page = 0;
-	u16 phy_data;
-
-	e_dbg("e1000_set_vco_speed");
-
-	switch (hw->mac_type) {
-	case e1000_82545_rev_3:
-	case e1000_82546_rev_3:
-		break;
-	default:
-		return E1000_SUCCESS;
-	}
-
-	/* Set PHY register 30, page 5, bit 8 to 0 */
-
-	ret_val =
-	    e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, &default_page);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	phy_data &= ~M88E1000_PHY_VCO_REG_BIT8;
-	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
-	if (ret_val)
-		return ret_val;
-
-	/* Set PHY register 30, page 4, bit 11 to 1 */
-
-	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	phy_data |= M88E1000_PHY_VCO_REG_BIT11;
-	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
-	if (ret_val)
-		return ret_val;
-
-	ret_val =
-	    e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, default_page);
-	if (ret_val)
-		return ret_val;
-
-	return E1000_SUCCESS;
-}
-
-
-/**
- * e1000_enable_mng_pass_thru - check for bmc pass through
- * @hw: Struct containing variables accessed by shared code
- *
- * Verifies the hardware needs to allow ARPs to be processed by the host
- * returns: - true/false
- */
-u32 e1000_enable_mng_pass_thru(struct e1000_hw *hw)
-{
-	u32 manc;
-
-	if (hw->asf_firmware_present) {
-		manc = er32(MANC);
-
-		if (!(manc & E1000_MANC_RCV_TCO_EN) ||
-		    !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
-			return false;
-		if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN))
-			return true;
-	}
-	return false;
-}
-
-static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 mii_status_reg;
-	u16 i;
-
-	/* Polarity reversal workaround for forced 10F/10H links. */
-
-	/* Disable the transmitter on the PHY */
-
-	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
-	if (ret_val)
-		return ret_val;
-	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
-	if (ret_val)
-		return ret_val;
-
-	/* This loop will early-out if the NO link condition has been met. */
-	for (i = PHY_FORCE_TIME; i > 0; i--) {
-		/* Read the MII Status Register and wait for Link Status bit
-		 * to be clear.
-		 */
-
-		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-		if (ret_val)
-			return ret_val;
-
-		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-		if (ret_val)
-			return ret_val;
-
-		if ((mii_status_reg & ~MII_SR_LINK_STATUS) == 0)
-			break;
-		mdelay(100);
-	}
-
-	/* Recommended delay time after link has been lost */
-	mdelay(1000);
-
-	/* Now we will re-enable th transmitter on the PHY */
-
-	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
-	if (ret_val)
-		return ret_val;
-	mdelay(50);
-	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
-	if (ret_val)
-		return ret_val;
-	mdelay(50);
-	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
-	if (ret_val)
-		return ret_val;
-	mdelay(50);
-	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
-	if (ret_val)
-		return ret_val;
-
-	/* This loop will early-out if the link condition has been met. */
-	for (i = PHY_FORCE_TIME; i > 0; i--) {
-		/* Read the MII Status Register and wait for Link Status bit
-		 * to be set.
-		 */
-
-		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-		if (ret_val)
-			return ret_val;
-
-		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-		if (ret_val)
-			return ret_val;
-
-		if (mii_status_reg & MII_SR_LINK_STATUS)
-			break;
-		mdelay(100);
-	}
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_get_auto_rd_done
- * @hw: Struct containing variables accessed by shared code
- *
- * Check for EEPROM Auto Read bit done.
- * returns: - E1000_ERR_RESET if fail to reset MAC
- *            E1000_SUCCESS at any other case.
- */
-static s32 e1000_get_auto_rd_done(struct e1000_hw *hw)
-{
-	e_dbg("e1000_get_auto_rd_done");
-	msleep(5);
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_get_phy_cfg_done
- * @hw: Struct containing variables accessed by shared code
- *
- * Checks if the PHY configuration is done
- * returns: - E1000_ERR_RESET if fail to reset MAC
- *            E1000_SUCCESS at any other case.
- */
-static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw)
-{
-	e_dbg("e1000_get_phy_cfg_done");
-	mdelay(10);
-	return E1000_SUCCESS;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/e1000/e1000_hw.h linux-libre-3.2-gnu/drivers/net/e1000/e1000_hw.h
--- linux-libre-3.1-gnu/drivers/net/e1000/e1000_hw.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000/e1000_hw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,3103 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2006 Intel Corporation.
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms and conditions of the GNU General Public License,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-/* e1000_hw.h
- * Structures, enums, and macros for the MAC
- */
-
-#ifndef _E1000_HW_H_
-#define _E1000_HW_H_
-
-#include "e1000_osdep.h"
-
-
-/* Forward declarations of structures used by the shared code */
-struct e1000_hw;
-struct e1000_hw_stats;
-
-/* Enumerated types specific to the e1000 hardware */
-/* Media Access Controllers */
-typedef enum {
-	e1000_undefined = 0,
-	e1000_82542_rev2_0,
-	e1000_82542_rev2_1,
-	e1000_82543,
-	e1000_82544,
-	e1000_82540,
-	e1000_82545,
-	e1000_82545_rev_3,
-	e1000_82546,
-	e1000_ce4100,
-	e1000_82546_rev_3,
-	e1000_82541,
-	e1000_82541_rev_2,
-	e1000_82547,
-	e1000_82547_rev_2,
-	e1000_num_macs
-} e1000_mac_type;
-
-typedef enum {
-	e1000_eeprom_uninitialized = 0,
-	e1000_eeprom_spi,
-	e1000_eeprom_microwire,
-	e1000_eeprom_flash,
-	e1000_eeprom_none,	/* No NVM support */
-	e1000_num_eeprom_types
-} e1000_eeprom_type;
-
-/* Media Types */
-typedef enum {
-	e1000_media_type_copper = 0,
-	e1000_media_type_fiber = 1,
-	e1000_media_type_internal_serdes = 2,
-	e1000_num_media_types
-} e1000_media_type;
-
-typedef enum {
-	e1000_10_half = 0,
-	e1000_10_full = 1,
-	e1000_100_half = 2,
-	e1000_100_full = 3
-} e1000_speed_duplex_type;
-
-/* Flow Control Settings */
-typedef enum {
-	E1000_FC_NONE = 0,
-	E1000_FC_RX_PAUSE = 1,
-	E1000_FC_TX_PAUSE = 2,
-	E1000_FC_FULL = 3,
-	E1000_FC_DEFAULT = 0xFF
-} e1000_fc_type;
-
-struct e1000_shadow_ram {
-	u16 eeprom_word;
-	bool modified;
-};
-
-/* PCI bus types */
-typedef enum {
-	e1000_bus_type_unknown = 0,
-	e1000_bus_type_pci,
-	e1000_bus_type_pcix,
-	e1000_bus_type_reserved
-} e1000_bus_type;
-
-/* PCI bus speeds */
-typedef enum {
-	e1000_bus_speed_unknown = 0,
-	e1000_bus_speed_33,
-	e1000_bus_speed_66,
-	e1000_bus_speed_100,
-	e1000_bus_speed_120,
-	e1000_bus_speed_133,
-	e1000_bus_speed_reserved
-} e1000_bus_speed;
-
-/* PCI bus widths */
-typedef enum {
-	e1000_bus_width_unknown = 0,
-	e1000_bus_width_32,
-	e1000_bus_width_64,
-	e1000_bus_width_reserved
-} e1000_bus_width;
-
-/* PHY status info structure and supporting enums */
-typedef enum {
-	e1000_cable_length_50 = 0,
-	e1000_cable_length_50_80,
-	e1000_cable_length_80_110,
-	e1000_cable_length_110_140,
-	e1000_cable_length_140,
-	e1000_cable_length_undefined = 0xFF
-} e1000_cable_length;
-
-typedef enum {
-	e1000_gg_cable_length_60 = 0,
-	e1000_gg_cable_length_60_115 = 1,
-	e1000_gg_cable_length_115_150 = 2,
-	e1000_gg_cable_length_150 = 4
-} e1000_gg_cable_length;
-
-typedef enum {
-	e1000_igp_cable_length_10 = 10,
-	e1000_igp_cable_length_20 = 20,
-	e1000_igp_cable_length_30 = 30,
-	e1000_igp_cable_length_40 = 40,
-	e1000_igp_cable_length_50 = 50,
-	e1000_igp_cable_length_60 = 60,
-	e1000_igp_cable_length_70 = 70,
-	e1000_igp_cable_length_80 = 80,
-	e1000_igp_cable_length_90 = 90,
-	e1000_igp_cable_length_100 = 100,
-	e1000_igp_cable_length_110 = 110,
-	e1000_igp_cable_length_115 = 115,
-	e1000_igp_cable_length_120 = 120,
-	e1000_igp_cable_length_130 = 130,
-	e1000_igp_cable_length_140 = 140,
-	e1000_igp_cable_length_150 = 150,
-	e1000_igp_cable_length_160 = 160,
-	e1000_igp_cable_length_170 = 170,
-	e1000_igp_cable_length_180 = 180
-} e1000_igp_cable_length;
-
-typedef enum {
-	e1000_10bt_ext_dist_enable_normal = 0,
-	e1000_10bt_ext_dist_enable_lower,
-	e1000_10bt_ext_dist_enable_undefined = 0xFF
-} e1000_10bt_ext_dist_enable;
-
-typedef enum {
-	e1000_rev_polarity_normal = 0,
-	e1000_rev_polarity_reversed,
-	e1000_rev_polarity_undefined = 0xFF
-} e1000_rev_polarity;
-
-typedef enum {
-	e1000_downshift_normal = 0,
-	e1000_downshift_activated,
-	e1000_downshift_undefined = 0xFF
-} e1000_downshift;
-
-typedef enum {
-	e1000_smart_speed_default = 0,
-	e1000_smart_speed_on,
-	e1000_smart_speed_off
-} e1000_smart_speed;
-
-typedef enum {
-	e1000_polarity_reversal_enabled = 0,
-	e1000_polarity_reversal_disabled,
-	e1000_polarity_reversal_undefined = 0xFF
-} e1000_polarity_reversal;
-
-typedef enum {
-	e1000_auto_x_mode_manual_mdi = 0,
-	e1000_auto_x_mode_manual_mdix,
-	e1000_auto_x_mode_auto1,
-	e1000_auto_x_mode_auto2,
-	e1000_auto_x_mode_undefined = 0xFF
-} e1000_auto_x_mode;
-
-typedef enum {
-	e1000_1000t_rx_status_not_ok = 0,
-	e1000_1000t_rx_status_ok,
-	e1000_1000t_rx_status_undefined = 0xFF
-} e1000_1000t_rx_status;
-
-typedef enum {
-	e1000_phy_m88 = 0,
-	e1000_phy_igp,
-	e1000_phy_8211,
-	e1000_phy_8201,
-	e1000_phy_undefined = 0xFF
-} e1000_phy_type;
-
-typedef enum {
-	e1000_ms_hw_default = 0,
-	e1000_ms_force_master,
-	e1000_ms_force_slave,
-	e1000_ms_auto
-} e1000_ms_type;
-
-typedef enum {
-	e1000_ffe_config_enabled = 0,
-	e1000_ffe_config_active,
-	e1000_ffe_config_blocked
-} e1000_ffe_config;
-
-typedef enum {
-	e1000_dsp_config_disabled = 0,
-	e1000_dsp_config_enabled,
-	e1000_dsp_config_activated,
-	e1000_dsp_config_undefined = 0xFF
-} e1000_dsp_config;
-
-struct e1000_phy_info {
-	e1000_cable_length cable_length;
-	e1000_10bt_ext_dist_enable extended_10bt_distance;
-	e1000_rev_polarity cable_polarity;
-	e1000_downshift downshift;
-	e1000_polarity_reversal polarity_correction;
-	e1000_auto_x_mode mdix_mode;
-	e1000_1000t_rx_status local_rx;
-	e1000_1000t_rx_status remote_rx;
-};
-
-struct e1000_phy_stats {
-	u32 idle_errors;
-	u32 receive_errors;
-};
-
-struct e1000_eeprom_info {
-	e1000_eeprom_type type;
-	u16 word_size;
-	u16 opcode_bits;
-	u16 address_bits;
-	u16 delay_usec;
-	u16 page_size;
-};
-
-/* Flex ASF Information */
-#define E1000_HOST_IF_MAX_SIZE  2048
-
-typedef enum {
-	e1000_byte_align = 0,
-	e1000_word_align = 1,
-	e1000_dword_align = 2
-} e1000_align_type;
-
-/* Error Codes */
-#define E1000_SUCCESS      0
-#define E1000_ERR_EEPROM   1
-#define E1000_ERR_PHY      2
-#define E1000_ERR_CONFIG   3
-#define E1000_ERR_PARAM    4
-#define E1000_ERR_MAC_TYPE 5
-#define E1000_ERR_PHY_TYPE 6
-#define E1000_ERR_RESET   9
-#define E1000_ERR_MASTER_REQUESTS_PENDING 10
-#define E1000_ERR_HOST_INTERFACE_COMMAND 11
-#define E1000_BLK_PHY_RESET   12
-
-#define E1000_BYTE_SWAP_WORD(_value) ((((_value) & 0x00ff) << 8) | \
-                                     (((_value) & 0xff00) >> 8))
-
-/* Function prototypes */
-/* Initialization */
-s32 e1000_reset_hw(struct e1000_hw *hw);
-s32 e1000_init_hw(struct e1000_hw *hw);
-s32 e1000_set_mac_type(struct e1000_hw *hw);
-void e1000_set_media_type(struct e1000_hw *hw);
-
-/* Link Configuration */
-s32 e1000_setup_link(struct e1000_hw *hw);
-s32 e1000_phy_setup_autoneg(struct e1000_hw *hw);
-void e1000_config_collision_dist(struct e1000_hw *hw);
-s32 e1000_check_for_link(struct e1000_hw *hw);
-s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 * speed, u16 * duplex);
-s32 e1000_force_mac_fc(struct e1000_hw *hw);
-
-/* PHY */
-s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 * phy_data);
-s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 data);
-s32 e1000_phy_hw_reset(struct e1000_hw *hw);
-s32 e1000_phy_reset(struct e1000_hw *hw);
-s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
-s32 e1000_validate_mdi_setting(struct e1000_hw *hw);
-
-/* EEPROM Functions */
-s32 e1000_init_eeprom_params(struct e1000_hw *hw);
-
-/* MNG HOST IF functions */
-u32 e1000_enable_mng_pass_thru(struct e1000_hw *hw);
-
-#define E1000_MNG_DHCP_TX_PAYLOAD_CMD   64
-#define E1000_HI_MAX_MNG_DATA_LENGTH    0x6F8	/* Host Interface data length */
-
-#define E1000_MNG_DHCP_COMMAND_TIMEOUT  10	/* Time in ms to process MNG command */
-#define E1000_MNG_DHCP_COOKIE_OFFSET    0x6F0	/* Cookie offset */
-#define E1000_MNG_DHCP_COOKIE_LENGTH    0x10	/* Cookie length */
-#define E1000_MNG_IAMT_MODE             0x3
-#define E1000_MNG_ICH_IAMT_MODE         0x2
-#define E1000_IAMT_SIGNATURE            0x544D4149	/* Intel(R) Active Management Technology signature */
-
-#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT 0x1	/* DHCP parsing enabled */
-#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT    0x2	/* DHCP parsing enabled */
-#define E1000_VFTA_ENTRY_SHIFT                       0x5
-#define E1000_VFTA_ENTRY_MASK                        0x7F
-#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK              0x1F
-
-struct e1000_host_mng_command_header {
-	u8 command_id;
-	u8 checksum;
-	u16 reserved1;
-	u16 reserved2;
-	u16 command_length;
-};
-
-struct e1000_host_mng_command_info {
-	struct e1000_host_mng_command_header command_header;	/* Command Head/Command Result Head has 4 bytes */
-	u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH];	/* Command data can length 0..0x658 */
-};
-#ifdef __BIG_ENDIAN
-struct e1000_host_mng_dhcp_cookie {
-	u32 signature;
-	u16 vlan_id;
-	u8 reserved0;
-	u8 status;
-	u32 reserved1;
-	u8 checksum;
-	u8 reserved3;
-	u16 reserved2;
-};
-#else
-struct e1000_host_mng_dhcp_cookie {
-	u32 signature;
-	u8 status;
-	u8 reserved0;
-	u16 vlan_id;
-	u32 reserved1;
-	u16 reserved2;
-	u8 reserved3;
-	u8 checksum;
-};
-#endif
-
-bool e1000_check_mng_mode(struct e1000_hw *hw);
-s32 e1000_read_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 * data);
-s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw);
-s32 e1000_update_eeprom_checksum(struct e1000_hw *hw);
-s32 e1000_write_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 * data);
-s32 e1000_read_mac_addr(struct e1000_hw *hw);
-
-/* Filters (multicast, vlan, receive) */
-u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 * mc_addr);
-void e1000_mta_set(struct e1000_hw *hw, u32 hash_value);
-void e1000_rar_set(struct e1000_hw *hw, u8 * mc_addr, u32 rar_index);
-void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value);
-
-/* LED functions */
-s32 e1000_setup_led(struct e1000_hw *hw);
-s32 e1000_cleanup_led(struct e1000_hw *hw);
-s32 e1000_led_on(struct e1000_hw *hw);
-s32 e1000_led_off(struct e1000_hw *hw);
-s32 e1000_blink_led_start(struct e1000_hw *hw);
-
-/* Adaptive IFS Functions */
-
-/* Everything else */
-void e1000_reset_adaptive(struct e1000_hw *hw);
-void e1000_update_adaptive(struct e1000_hw *hw);
-void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats,
-			    u32 frame_len, u8 * mac_addr);
-void e1000_get_bus_info(struct e1000_hw *hw);
-void e1000_pci_set_mwi(struct e1000_hw *hw);
-void e1000_pci_clear_mwi(struct e1000_hw *hw);
-void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc);
-int e1000_pcix_get_mmrbc(struct e1000_hw *hw);
-/* Port I/O is only supported on 82544 and newer */
-void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value);
-
-#define E1000_READ_REG_IO(a, reg) \
-    e1000_read_reg_io((a), E1000_##reg)
-#define E1000_WRITE_REG_IO(a, reg, val) \
-    e1000_write_reg_io((a), E1000_##reg, val)
-
-/* PCI Device IDs */
-#define E1000_DEV_ID_82542               0x1000
-#define E1000_DEV_ID_82543GC_FIBER       0x1001
-#define E1000_DEV_ID_82543GC_COPPER      0x1004
-#define E1000_DEV_ID_82544EI_COPPER      0x1008
-#define E1000_DEV_ID_82544EI_FIBER       0x1009
-#define E1000_DEV_ID_82544GC_COPPER      0x100C
-#define E1000_DEV_ID_82544GC_LOM         0x100D
-#define E1000_DEV_ID_82540EM             0x100E
-#define E1000_DEV_ID_82540EM_LOM         0x1015
-#define E1000_DEV_ID_82540EP_LOM         0x1016
-#define E1000_DEV_ID_82540EP             0x1017
-#define E1000_DEV_ID_82540EP_LP          0x101E
-#define E1000_DEV_ID_82545EM_COPPER      0x100F
-#define E1000_DEV_ID_82545EM_FIBER       0x1011
-#define E1000_DEV_ID_82545GM_COPPER      0x1026
-#define E1000_DEV_ID_82545GM_FIBER       0x1027
-#define E1000_DEV_ID_82545GM_SERDES      0x1028
-#define E1000_DEV_ID_82546EB_COPPER      0x1010
-#define E1000_DEV_ID_82546EB_FIBER       0x1012
-#define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D
-#define E1000_DEV_ID_82541EI             0x1013
-#define E1000_DEV_ID_82541EI_MOBILE      0x1018
-#define E1000_DEV_ID_82541ER_LOM         0x1014
-#define E1000_DEV_ID_82541ER             0x1078
-#define E1000_DEV_ID_82547GI             0x1075
-#define E1000_DEV_ID_82541GI             0x1076
-#define E1000_DEV_ID_82541GI_MOBILE      0x1077
-#define E1000_DEV_ID_82541GI_LF          0x107C
-#define E1000_DEV_ID_82546GB_COPPER      0x1079
-#define E1000_DEV_ID_82546GB_FIBER       0x107A
-#define E1000_DEV_ID_82546GB_SERDES      0x107B
-#define E1000_DEV_ID_82546GB_PCIE        0x108A
-#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
-#define E1000_DEV_ID_82547EI             0x1019
-#define E1000_DEV_ID_82547EI_MOBILE      0x101A
-#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
-#define E1000_DEV_ID_INTEL_CE4100_GBE    0x2E6E
-
-#define NODE_ADDRESS_SIZE 6
-#define ETH_LENGTH_OF_ADDRESS 6
-
-/* MAC decode size is 128K - This is the size of BAR0 */
-#define MAC_DECODE_SIZE (128 * 1024)
-
-#define E1000_82542_2_0_REV_ID 2
-#define E1000_82542_2_1_REV_ID 3
-#define E1000_REVISION_0       0
-#define E1000_REVISION_1       1
-#define E1000_REVISION_2       2
-#define E1000_REVISION_3       3
-
-#define SPEED_10    10
-#define SPEED_100   100
-#define SPEED_1000  1000
-#define HALF_DUPLEX 1
-#define FULL_DUPLEX 2
-
-/* The sizes (in bytes) of a ethernet packet */
-#define ENET_HEADER_SIZE             14
-#define MINIMUM_ETHERNET_FRAME_SIZE  64	/* With FCS */
-#define ETHERNET_FCS_SIZE            4
-#define MINIMUM_ETHERNET_PACKET_SIZE \
-    (MINIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE)
-#define CRC_LENGTH                   ETHERNET_FCS_SIZE
-#define MAX_JUMBO_FRAME_SIZE         0x3F00
-
-/* 802.1q VLAN Packet Sizes */
-#define VLAN_TAG_SIZE  4	/* 802.3ac tag (not DMAed) */
-
-/* Ethertype field values */
-#define ETHERNET_IEEE_VLAN_TYPE 0x8100	/* 802.3ac packet */
-#define ETHERNET_IP_TYPE        0x0800	/* IP packets */
-#define ETHERNET_ARP_TYPE       0x0806	/* Address Resolution Protocol (ARP) */
-
-/* Packet Header defines */
-#define IP_PROTOCOL_TCP    6
-#define IP_PROTOCOL_UDP    0x11
-
-/* This defines the bits that are set in the Interrupt Mask
- * Set/Read Register.  Each bit is documented below:
- *   o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
- *   o RXSEQ  = Receive Sequence Error
- */
-#define POLL_IMS_ENABLE_MASK ( \
-    E1000_IMS_RXDMT0 |         \
-    E1000_IMS_RXSEQ)
-
-/* This defines the bits that are set in the Interrupt Mask
- * Set/Read Register.  Each bit is documented below:
- *   o RXT0   = Receiver Timer Interrupt (ring 0)
- *   o TXDW   = Transmit Descriptor Written Back
- *   o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
- *   o RXSEQ  = Receive Sequence Error
- *   o LSC    = Link Status Change
- */
-#define IMS_ENABLE_MASK ( \
-    E1000_IMS_RXT0   |    \
-    E1000_IMS_TXDW   |    \
-    E1000_IMS_RXDMT0 |    \
-    E1000_IMS_RXSEQ  |    \
-    E1000_IMS_LSC)
-
-/* Number of high/low register pairs in the RAR. The RAR (Receive Address
- * Registers) holds the directed and multicast addresses that we monitor. We
- * reserve one of these spots for our directed address, allowing us room for
- * E1000_RAR_ENTRIES - 1 multicast addresses.
- */
-#define E1000_RAR_ENTRIES 15
-
-#define MIN_NUMBER_OF_DESCRIPTORS  8
-#define MAX_NUMBER_OF_DESCRIPTORS  0xFFF8
-
-/* Receive Descriptor */
-struct e1000_rx_desc {
-	__le64 buffer_addr;	/* Address of the descriptor's data buffer */
-	__le16 length;		/* Length of data DMAed into data buffer */
-	__le16 csum;		/* Packet checksum */
-	u8 status;		/* Descriptor status */
-	u8 errors;		/* Descriptor Errors */
-	__le16 special;
-};
-
-/* Receive Descriptor - Extended */
-union e1000_rx_desc_extended {
-	struct {
-		__le64 buffer_addr;
-		__le64 reserved;
-	} read;
-	struct {
-		struct {
-			__le32 mrq;	/* Multiple Rx Queues */
-			union {
-				__le32 rss;	/* RSS Hash */
-				struct {
-					__le16 ip_id;	/* IP id */
-					__le16 csum;	/* Packet Checksum */
-				} csum_ip;
-			} hi_dword;
-		} lower;
-		struct {
-			__le32 status_error;	/* ext status/error */
-			__le16 length;
-			__le16 vlan;	/* VLAN tag */
-		} upper;
-	} wb;			/* writeback */
-};
-
-#define MAX_PS_BUFFERS 4
-/* Receive Descriptor - Packet Split */
-union e1000_rx_desc_packet_split {
-	struct {
-		/* one buffer for protocol header(s), three data buffers */
-		__le64 buffer_addr[MAX_PS_BUFFERS];
-	} read;
-	struct {
-		struct {
-			__le32 mrq;	/* Multiple Rx Queues */
-			union {
-				__le32 rss;	/* RSS Hash */
-				struct {
-					__le16 ip_id;	/* IP id */
-					__le16 csum;	/* Packet Checksum */
-				} csum_ip;
-			} hi_dword;
-		} lower;
-		struct {
-			__le32 status_error;	/* ext status/error */
-			__le16 length0;	/* length of buffer 0 */
-			__le16 vlan;	/* VLAN tag */
-		} middle;
-		struct {
-			__le16 header_status;
-			__le16 length[3];	/* length of buffers 1-3 */
-		} upper;
-		__le64 reserved;
-	} wb;			/* writeback */
-};
-
-/* Receive Descriptor bit definitions */
-#define E1000_RXD_STAT_DD       0x01	/* Descriptor Done */
-#define E1000_RXD_STAT_EOP      0x02	/* End of Packet */
-#define E1000_RXD_STAT_IXSM     0x04	/* Ignore checksum */
-#define E1000_RXD_STAT_VP       0x08	/* IEEE VLAN Packet */
-#define E1000_RXD_STAT_UDPCS    0x10	/* UDP xsum calculated */
-#define E1000_RXD_STAT_TCPCS    0x20	/* TCP xsum calculated */
-#define E1000_RXD_STAT_IPCS     0x40	/* IP xsum calculated */
-#define E1000_RXD_STAT_PIF      0x80	/* passed in-exact filter */
-#define E1000_RXD_STAT_IPIDV    0x200	/* IP identification valid */
-#define E1000_RXD_STAT_UDPV     0x400	/* Valid UDP checksum */
-#define E1000_RXD_STAT_ACK      0x8000	/* ACK Packet indication */
-#define E1000_RXD_ERR_CE        0x01	/* CRC Error */
-#define E1000_RXD_ERR_SE        0x02	/* Symbol Error */
-#define E1000_RXD_ERR_SEQ       0x04	/* Sequence Error */
-#define E1000_RXD_ERR_CXE       0x10	/* Carrier Extension Error */
-#define E1000_RXD_ERR_TCPE      0x20	/* TCP/UDP Checksum Error */
-#define E1000_RXD_ERR_IPE       0x40	/* IP Checksum Error */
-#define E1000_RXD_ERR_RXE       0x80	/* Rx Data Error */
-#define E1000_RXD_SPC_VLAN_MASK 0x0FFF	/* VLAN ID is in lower 12 bits */
-#define E1000_RXD_SPC_PRI_MASK  0xE000	/* Priority is in upper 3 bits */
-#define E1000_RXD_SPC_PRI_SHIFT 13
-#define E1000_RXD_SPC_CFI_MASK  0x1000	/* CFI is bit 12 */
-#define E1000_RXD_SPC_CFI_SHIFT 12
-
-#define E1000_RXDEXT_STATERR_CE    0x01000000
-#define E1000_RXDEXT_STATERR_SE    0x02000000
-#define E1000_RXDEXT_STATERR_SEQ   0x04000000
-#define E1000_RXDEXT_STATERR_CXE   0x10000000
-#define E1000_RXDEXT_STATERR_TCPE  0x20000000
-#define E1000_RXDEXT_STATERR_IPE   0x40000000
-#define E1000_RXDEXT_STATERR_RXE   0x80000000
-
-#define E1000_RXDPS_HDRSTAT_HDRSP        0x00008000
-#define E1000_RXDPS_HDRSTAT_HDRLEN_MASK  0x000003FF
-
-/* mask to determine if packets should be dropped due to frame errors */
-#define E1000_RXD_ERR_FRAME_ERR_MASK ( \
-    E1000_RXD_ERR_CE  |                \
-    E1000_RXD_ERR_SE  |                \
-    E1000_RXD_ERR_SEQ |                \
-    E1000_RXD_ERR_CXE |                \
-    E1000_RXD_ERR_RXE)
-
-/* Same mask, but for extended and packet split descriptors */
-#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \
-    E1000_RXDEXT_STATERR_CE  |            \
-    E1000_RXDEXT_STATERR_SE  |            \
-    E1000_RXDEXT_STATERR_SEQ |            \
-    E1000_RXDEXT_STATERR_CXE |            \
-    E1000_RXDEXT_STATERR_RXE)
-
-/* Transmit Descriptor */
-struct e1000_tx_desc {
-	__le64 buffer_addr;	/* Address of the descriptor's data buffer */
-	union {
-		__le32 data;
-		struct {
-			__le16 length;	/* Data buffer length */
-			u8 cso;	/* Checksum offset */
-			u8 cmd;	/* Descriptor control */
-		} flags;
-	} lower;
-	union {
-		__le32 data;
-		struct {
-			u8 status;	/* Descriptor status */
-			u8 css;	/* Checksum start */
-			__le16 special;
-		} fields;
-	} upper;
-};
-
-/* Transmit Descriptor bit definitions */
-#define E1000_TXD_DTYP_D     0x00100000	/* Data Descriptor */
-#define E1000_TXD_DTYP_C     0x00000000	/* Context Descriptor */
-#define E1000_TXD_POPTS_IXSM 0x01	/* Insert IP checksum */
-#define E1000_TXD_POPTS_TXSM 0x02	/* Insert TCP/UDP checksum */
-#define E1000_TXD_CMD_EOP    0x01000000	/* End of Packet */
-#define E1000_TXD_CMD_IFCS   0x02000000	/* Insert FCS (Ethernet CRC) */
-#define E1000_TXD_CMD_IC     0x04000000	/* Insert Checksum */
-#define E1000_TXD_CMD_RS     0x08000000	/* Report Status */
-#define E1000_TXD_CMD_RPS    0x10000000	/* Report Packet Sent */
-#define E1000_TXD_CMD_DEXT   0x20000000	/* Descriptor extension (0 = legacy) */
-#define E1000_TXD_CMD_VLE    0x40000000	/* Add VLAN tag */
-#define E1000_TXD_CMD_IDE    0x80000000	/* Enable Tidv register */
-#define E1000_TXD_STAT_DD    0x00000001	/* Descriptor Done */
-#define E1000_TXD_STAT_EC    0x00000002	/* Excess Collisions */
-#define E1000_TXD_STAT_LC    0x00000004	/* Late Collisions */
-#define E1000_TXD_STAT_TU    0x00000008	/* Transmit underrun */
-#define E1000_TXD_CMD_TCP    0x01000000	/* TCP packet */
-#define E1000_TXD_CMD_IP     0x02000000	/* IP packet */
-#define E1000_TXD_CMD_TSE    0x04000000	/* TCP Seg enable */
-#define E1000_TXD_STAT_TC    0x00000004	/* Tx Underrun */
-
-/* Offload Context Descriptor */
-struct e1000_context_desc {
-	union {
-		__le32 ip_config;
-		struct {
-			u8 ipcss;	/* IP checksum start */
-			u8 ipcso;	/* IP checksum offset */
-			__le16 ipcse;	/* IP checksum end */
-		} ip_fields;
-	} lower_setup;
-	union {
-		__le32 tcp_config;
-		struct {
-			u8 tucss;	/* TCP checksum start */
-			u8 tucso;	/* TCP checksum offset */
-			__le16 tucse;	/* TCP checksum end */
-		} tcp_fields;
-	} upper_setup;
-	__le32 cmd_and_length;	/* */
-	union {
-		__le32 data;
-		struct {
-			u8 status;	/* Descriptor status */
-			u8 hdr_len;	/* Header length */
-			__le16 mss;	/* Maximum segment size */
-		} fields;
-	} tcp_seg_setup;
-};
-
-/* Offload data descriptor */
-struct e1000_data_desc {
-	__le64 buffer_addr;	/* Address of the descriptor's buffer address */
-	union {
-		__le32 data;
-		struct {
-			__le16 length;	/* Data buffer length */
-			u8 typ_len_ext;	/* */
-			u8 cmd;	/* */
-		} flags;
-	} lower;
-	union {
-		__le32 data;
-		struct {
-			u8 status;	/* Descriptor status */
-			u8 popts;	/* Packet Options */
-			__le16 special;	/* */
-		} fields;
-	} upper;
-};
-
-/* Filters */
-#define E1000_NUM_UNICAST          16	/* Unicast filter entries */
-#define E1000_MC_TBL_SIZE          128	/* Multicast Filter Table (4096 bits) */
-#define E1000_VLAN_FILTER_TBL_SIZE 128	/* VLAN Filter Table (4096 bits) */
-
-/* Receive Address Register */
-struct e1000_rar {
-	volatile __le32 low;	/* receive address low */
-	volatile __le32 high;	/* receive address high */
-};
-
-/* Number of entries in the Multicast Table Array (MTA). */
-#define E1000_NUM_MTA_REGISTERS 128
-
-/* IPv4 Address Table Entry */
-struct e1000_ipv4_at_entry {
-	volatile u32 ipv4_addr;	/* IP Address (RW) */
-	volatile u32 reserved;
-};
-
-/* Four wakeup IP addresses are supported */
-#define E1000_WAKEUP_IP_ADDRESS_COUNT_MAX 4
-#define E1000_IP4AT_SIZE                  E1000_WAKEUP_IP_ADDRESS_COUNT_MAX
-#define E1000_IP6AT_SIZE                  1
-
-/* IPv6 Address Table Entry */
-struct e1000_ipv6_at_entry {
-	volatile u8 ipv6_addr[16];
-};
-
-/* Flexible Filter Length Table Entry */
-struct e1000_fflt_entry {
-	volatile u32 length;	/* Flexible Filter Length (RW) */
-	volatile u32 reserved;
-};
-
-/* Flexible Filter Mask Table Entry */
-struct e1000_ffmt_entry {
-	volatile u32 mask;	/* Flexible Filter Mask (RW) */
-	volatile u32 reserved;
-};
-
-/* Flexible Filter Value Table Entry */
-struct e1000_ffvt_entry {
-	volatile u32 value;	/* Flexible Filter Value (RW) */
-	volatile u32 reserved;
-};
-
-/* Four Flexible Filters are supported */
-#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4
-
-/* Each Flexible Filter is at most 128 (0x80) bytes in length */
-#define E1000_FLEXIBLE_FILTER_SIZE_MAX  128
-
-#define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX
-#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
-#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
-
-#define E1000_DISABLE_SERDES_LOOPBACK   0x0400
-
-/* Register Set. (82543, 82544)
- *
- * Registers are defined to be 32 bits and  should be accessed as 32 bit values.
- * These registers are physically located on the NIC, but are mapped into the
- * host memory address space.
- *
- * RW - register is both readable and writable
- * RO - register is read only
- * WO - register is write only
- * R/clr - register is read only and is cleared when read
- * A - register array
- */
-#define E1000_CTRL     0x00000	/* Device Control - RW */
-#define E1000_CTRL_DUP 0x00004	/* Device Control Duplicate (Shadow) - RW */
-#define E1000_STATUS   0x00008	/* Device Status - RO */
-#define E1000_EECD     0x00010	/* EEPROM/Flash Control - RW */
-#define E1000_EERD     0x00014	/* EEPROM Read - RW */
-#define E1000_CTRL_EXT 0x00018	/* Extended Device Control - RW */
-#define E1000_FLA      0x0001C	/* Flash Access - RW */
-#define E1000_MDIC     0x00020	/* MDI Control - RW */
-
-extern void __iomem *ce4100_gbe_mdio_base_virt;
-#define INTEL_CE_GBE_MDIO_RCOMP_BASE    (ce4100_gbe_mdio_base_virt)
-#define E1000_MDIO_STS  (INTEL_CE_GBE_MDIO_RCOMP_BASE + 0)
-#define E1000_MDIO_CMD  (INTEL_CE_GBE_MDIO_RCOMP_BASE + 4)
-#define E1000_MDIO_DRV  (INTEL_CE_GBE_MDIO_RCOMP_BASE + 8)
-#define E1000_MDC_CMD   (INTEL_CE_GBE_MDIO_RCOMP_BASE + 0xC)
-#define E1000_RCOMP_CTL (INTEL_CE_GBE_MDIO_RCOMP_BASE + 0x20)
-#define E1000_RCOMP_STS (INTEL_CE_GBE_MDIO_RCOMP_BASE + 0x24)
-
-#define E1000_SCTL     0x00024	/* SerDes Control - RW */
-#define E1000_FEXTNVM  0x00028	/* Future Extended NVM register */
-#define E1000_FCAL     0x00028	/* Flow Control Address Low - RW */
-#define E1000_FCAH     0x0002C	/* Flow Control Address High -RW */
-#define E1000_FCT      0x00030	/* Flow Control Type - RW */
-#define E1000_VET      0x00038	/* VLAN Ether Type - RW */
-#define E1000_ICR      0x000C0	/* Interrupt Cause Read - R/clr */
-#define E1000_ITR      0x000C4	/* Interrupt Throttling Rate - RW */
-#define E1000_ICS      0x000C8	/* Interrupt Cause Set - WO */
-#define E1000_IMS      0x000D0	/* Interrupt Mask Set - RW */
-#define E1000_IMC      0x000D8	/* Interrupt Mask Clear - WO */
-#define E1000_IAM      0x000E0	/* Interrupt Acknowledge Auto Mask */
-
-/* Auxiliary Control Register. This register is CE4100 specific,
- * RMII/RGMII function is switched by this register - RW
- * Following are bits definitions of the Auxiliary Control Register
- */
-#define E1000_CTL_AUX  0x000E0
-#define E1000_CTL_AUX_END_SEL_SHIFT     10
-#define E1000_CTL_AUX_ENDIANESS_SHIFT   8
-#define E1000_CTL_AUX_RGMII_RMII_SHIFT  0
-
-/* descriptor and packet transfer use CTL_AUX.ENDIANESS */
-#define E1000_CTL_AUX_DES_PKT   (0x0 << E1000_CTL_AUX_END_SEL_SHIFT)
-/* descriptor use CTL_AUX.ENDIANESS, packet use default */
-#define E1000_CTL_AUX_DES       (0x1 << E1000_CTL_AUX_END_SEL_SHIFT)
-/* descriptor use default, packet use CTL_AUX.ENDIANESS */
-#define E1000_CTL_AUX_PKT       (0x2 << E1000_CTL_AUX_END_SEL_SHIFT)
-/* all use CTL_AUX.ENDIANESS */
-#define E1000_CTL_AUX_ALL       (0x3 << E1000_CTL_AUX_END_SEL_SHIFT)
-
-#define E1000_CTL_AUX_RGMII     (0x0 << E1000_CTL_AUX_RGMII_RMII_SHIFT)
-#define E1000_CTL_AUX_RMII      (0x1 << E1000_CTL_AUX_RGMII_RMII_SHIFT)
-
-/* LW little endian, Byte big endian */
-#define E1000_CTL_AUX_LWLE_BBE  (0x0 << E1000_CTL_AUX_ENDIANESS_SHIFT)
-#define E1000_CTL_AUX_LWLE_BLE  (0x1 << E1000_CTL_AUX_ENDIANESS_SHIFT)
-#define E1000_CTL_AUX_LWBE_BBE  (0x2 << E1000_CTL_AUX_ENDIANESS_SHIFT)
-#define E1000_CTL_AUX_LWBE_BLE  (0x3 << E1000_CTL_AUX_ENDIANESS_SHIFT)
-
-#define E1000_RCTL     0x00100	/* RX Control - RW */
-#define E1000_RDTR1    0x02820	/* RX Delay Timer (1) - RW */
-#define E1000_RDBAL1   0x02900	/* RX Descriptor Base Address Low (1) - RW */
-#define E1000_RDBAH1   0x02904	/* RX Descriptor Base Address High (1) - RW */
-#define E1000_RDLEN1   0x02908	/* RX Descriptor Length (1) - RW */
-#define E1000_RDH1     0x02910	/* RX Descriptor Head (1) - RW */
-#define E1000_RDT1     0x02918	/* RX Descriptor Tail (1) - RW */
-#define E1000_FCTTV    0x00170	/* Flow Control Transmit Timer Value - RW */
-#define E1000_TXCW     0x00178	/* TX Configuration Word - RW */
-#define E1000_RXCW     0x00180	/* RX Configuration Word - RO */
-#define E1000_TCTL     0x00400	/* TX Control - RW */
-#define E1000_TCTL_EXT 0x00404	/* Extended TX Control - RW */
-#define E1000_TIPG     0x00410	/* TX Inter-packet gap -RW */
-#define E1000_TBT      0x00448	/* TX Burst Timer - RW */
-#define E1000_AIT      0x00458	/* Adaptive Interframe Spacing Throttle - RW */
-#define E1000_LEDCTL   0x00E00	/* LED Control - RW */
-#define E1000_EXTCNF_CTRL  0x00F00	/* Extended Configuration Control */
-#define E1000_EXTCNF_SIZE  0x00F08	/* Extended Configuration Size */
-#define E1000_PHY_CTRL     0x00F10	/* PHY Control Register in CSR */
-#define FEXTNVM_SW_CONFIG  0x0001
-#define E1000_PBA      0x01000	/* Packet Buffer Allocation - RW */
-#define E1000_PBS      0x01008	/* Packet Buffer Size */
-#define E1000_EEMNGCTL 0x01010	/* MNG EEprom Control */
-#define E1000_FLASH_UPDATES 1000
-#define E1000_EEARBC   0x01024	/* EEPROM Auto Read Bus Control */
-#define E1000_FLASHT   0x01028	/* FLASH Timer Register */
-#define E1000_EEWR     0x0102C	/* EEPROM Write Register - RW */
-#define E1000_FLSWCTL  0x01030	/* FLASH control register */
-#define E1000_FLSWDATA 0x01034	/* FLASH data register */
-#define E1000_FLSWCNT  0x01038	/* FLASH Access Counter */
-#define E1000_FLOP     0x0103C	/* FLASH Opcode Register */
-#define E1000_ERT      0x02008	/* Early Rx Threshold - RW */
-#define E1000_FCRTL    0x02160	/* Flow Control Receive Threshold Low - RW */
-#define E1000_FCRTH    0x02168	/* Flow Control Receive Threshold High - RW */
-#define E1000_PSRCTL   0x02170	/* Packet Split Receive Control - RW */
-#define E1000_RDBAL    0x02800	/* RX Descriptor Base Address Low - RW */
-#define E1000_RDBAH    0x02804	/* RX Descriptor Base Address High - RW */
-#define E1000_RDLEN    0x02808	/* RX Descriptor Length - RW */
-#define E1000_RDH      0x02810	/* RX Descriptor Head - RW */
-#define E1000_RDT      0x02818	/* RX Descriptor Tail - RW */
-#define E1000_RDTR     0x02820	/* RX Delay Timer - RW */
-#define E1000_RDBAL0   E1000_RDBAL	/* RX Desc Base Address Low (0) - RW */
-#define E1000_RDBAH0   E1000_RDBAH	/* RX Desc Base Address High (0) - RW */
-#define E1000_RDLEN0   E1000_RDLEN	/* RX Desc Length (0) - RW */
-#define E1000_RDH0     E1000_RDH	/* RX Desc Head (0) - RW */
-#define E1000_RDT0     E1000_RDT	/* RX Desc Tail (0) - RW */
-#define E1000_RDTR0    E1000_RDTR	/* RX Delay Timer (0) - RW */
-#define E1000_RXDCTL   0x02828	/* RX Descriptor Control queue 0 - RW */
-#define E1000_RXDCTL1  0x02928	/* RX Descriptor Control queue 1 - RW */
-#define E1000_RADV     0x0282C	/* RX Interrupt Absolute Delay Timer - RW */
-#define E1000_RSRPD    0x02C00	/* RX Small Packet Detect - RW */
-#define E1000_RAID     0x02C08	/* Receive Ack Interrupt Delay - RW */
-#define E1000_TXDMAC   0x03000	/* TX DMA Control - RW */
-#define E1000_KABGTXD  0x03004	/* AFE Band Gap Transmit Ref Data */
-#define E1000_TDFH     0x03410	/* TX Data FIFO Head - RW */
-#define E1000_TDFT     0x03418	/* TX Data FIFO Tail - RW */
-#define E1000_TDFHS    0x03420	/* TX Data FIFO Head Saved - RW */
-#define E1000_TDFTS    0x03428	/* TX Data FIFO Tail Saved - RW */
-#define E1000_TDFPC    0x03430	/* TX Data FIFO Packet Count - RW */
-#define E1000_TDBAL    0x03800	/* TX Descriptor Base Address Low - RW */
-#define E1000_TDBAH    0x03804	/* TX Descriptor Base Address High - RW */
-#define E1000_TDLEN    0x03808	/* TX Descriptor Length - RW */
-#define E1000_TDH      0x03810	/* TX Descriptor Head - RW */
-#define E1000_TDT      0x03818	/* TX Descripotr Tail - RW */
-#define E1000_TIDV     0x03820	/* TX Interrupt Delay Value - RW */
-#define E1000_TXDCTL   0x03828	/* TX Descriptor Control - RW */
-#define E1000_TADV     0x0382C	/* TX Interrupt Absolute Delay Val - RW */
-#define E1000_TSPMT    0x03830	/* TCP Segmentation PAD & Min Threshold - RW */
-#define E1000_TARC0    0x03840	/* TX Arbitration Count (0) */
-#define E1000_TDBAL1   0x03900	/* TX Desc Base Address Low (1) - RW */
-#define E1000_TDBAH1   0x03904	/* TX Desc Base Address High (1) - RW */
-#define E1000_TDLEN1   0x03908	/* TX Desc Length (1) - RW */
-#define E1000_TDH1     0x03910	/* TX Desc Head (1) - RW */
-#define E1000_TDT1     0x03918	/* TX Desc Tail (1) - RW */
-#define E1000_TXDCTL1  0x03928	/* TX Descriptor Control (1) - RW */
-#define E1000_TARC1    0x03940	/* TX Arbitration Count (1) */
-#define E1000_CRCERRS  0x04000	/* CRC Error Count - R/clr */
-#define E1000_ALGNERRC 0x04004	/* Alignment Error Count - R/clr */
-#define E1000_SYMERRS  0x04008	/* Symbol Error Count - R/clr */
-#define E1000_RXERRC   0x0400C	/* Receive Error Count - R/clr */
-#define E1000_MPC      0x04010	/* Missed Packet Count - R/clr */
-#define E1000_SCC      0x04014	/* Single Collision Count - R/clr */
-#define E1000_ECOL     0x04018	/* Excessive Collision Count - R/clr */
-#define E1000_MCC      0x0401C	/* Multiple Collision Count - R/clr */
-#define E1000_LATECOL  0x04020	/* Late Collision Count - R/clr */
-#define E1000_COLC     0x04028	/* Collision Count - R/clr */
-#define E1000_DC       0x04030	/* Defer Count - R/clr */
-#define E1000_TNCRS    0x04034	/* TX-No CRS - R/clr */
-#define E1000_SEC      0x04038	/* Sequence Error Count - R/clr */
-#define E1000_CEXTERR  0x0403C	/* Carrier Extension Error Count - R/clr */
-#define E1000_RLEC     0x04040	/* Receive Length Error Count - R/clr */
-#define E1000_XONRXC   0x04048	/* XON RX Count - R/clr */
-#define E1000_XONTXC   0x0404C	/* XON TX Count - R/clr */
-#define E1000_XOFFRXC  0x04050	/* XOFF RX Count - R/clr */
-#define E1000_XOFFTXC  0x04054	/* XOFF TX Count - R/clr */
-#define E1000_FCRUC    0x04058	/* Flow Control RX Unsupported Count- R/clr */
-#define E1000_PRC64    0x0405C	/* Packets RX (64 bytes) - R/clr */
-#define E1000_PRC127   0x04060	/* Packets RX (65-127 bytes) - R/clr */
-#define E1000_PRC255   0x04064	/* Packets RX (128-255 bytes) - R/clr */
-#define E1000_PRC511   0x04068	/* Packets RX (255-511 bytes) - R/clr */
-#define E1000_PRC1023  0x0406C	/* Packets RX (512-1023 bytes) - R/clr */
-#define E1000_PRC1522  0x04070	/* Packets RX (1024-1522 bytes) - R/clr */
-#define E1000_GPRC     0x04074	/* Good Packets RX Count - R/clr */
-#define E1000_BPRC     0x04078	/* Broadcast Packets RX Count - R/clr */
-#define E1000_MPRC     0x0407C	/* Multicast Packets RX Count - R/clr */
-#define E1000_GPTC     0x04080	/* Good Packets TX Count - R/clr */
-#define E1000_GORCL    0x04088	/* Good Octets RX Count Low - R/clr */
-#define E1000_GORCH    0x0408C	/* Good Octets RX Count High - R/clr */
-#define E1000_GOTCL    0x04090	/* Good Octets TX Count Low - R/clr */
-#define E1000_GOTCH    0x04094	/* Good Octets TX Count High - R/clr */
-#define E1000_RNBC     0x040A0	/* RX No Buffers Count - R/clr */
-#define E1000_RUC      0x040A4	/* RX Undersize Count - R/clr */
-#define E1000_RFC      0x040A8	/* RX Fragment Count - R/clr */
-#define E1000_ROC      0x040AC	/* RX Oversize Count - R/clr */
-#define E1000_RJC      0x040B0	/* RX Jabber Count - R/clr */
-#define E1000_MGTPRC   0x040B4	/* Management Packets RX Count - R/clr */
-#define E1000_MGTPDC   0x040B8	/* Management Packets Dropped Count - R/clr */
-#define E1000_MGTPTC   0x040BC	/* Management Packets TX Count - R/clr */
-#define E1000_TORL     0x040C0	/* Total Octets RX Low - R/clr */
-#define E1000_TORH     0x040C4	/* Total Octets RX High - R/clr */
-#define E1000_TOTL     0x040C8	/* Total Octets TX Low - R/clr */
-#define E1000_TOTH     0x040CC	/* Total Octets TX High - R/clr */
-#define E1000_TPR      0x040D0	/* Total Packets RX - R/clr */
-#define E1000_TPT      0x040D4	/* Total Packets TX - R/clr */
-#define E1000_PTC64    0x040D8	/* Packets TX (64 bytes) - R/clr */
-#define E1000_PTC127   0x040DC	/* Packets TX (65-127 bytes) - R/clr */
-#define E1000_PTC255   0x040E0	/* Packets TX (128-255 bytes) - R/clr */
-#define E1000_PTC511   0x040E4	/* Packets TX (256-511 bytes) - R/clr */
-#define E1000_PTC1023  0x040E8	/* Packets TX (512-1023 bytes) - R/clr */
-#define E1000_PTC1522  0x040EC	/* Packets TX (1024-1522 Bytes) - R/clr */
-#define E1000_MPTC     0x040F0	/* Multicast Packets TX Count - R/clr */
-#define E1000_BPTC     0x040F4	/* Broadcast Packets TX Count - R/clr */
-#define E1000_TSCTC    0x040F8	/* TCP Segmentation Context TX - R/clr */
-#define E1000_TSCTFC   0x040FC	/* TCP Segmentation Context TX Fail - R/clr */
-#define E1000_IAC      0x04100	/* Interrupt Assertion Count */
-#define E1000_ICRXPTC  0x04104	/* Interrupt Cause Rx Packet Timer Expire Count */
-#define E1000_ICRXATC  0x04108	/* Interrupt Cause Rx Absolute Timer Expire Count */
-#define E1000_ICTXPTC  0x0410C	/* Interrupt Cause Tx Packet Timer Expire Count */
-#define E1000_ICTXATC  0x04110	/* Interrupt Cause Tx Absolute Timer Expire Count */
-#define E1000_ICTXQEC  0x04118	/* Interrupt Cause Tx Queue Empty Count */
-#define E1000_ICTXQMTC 0x0411C	/* Interrupt Cause Tx Queue Minimum Threshold Count */
-#define E1000_ICRXDMTC 0x04120	/* Interrupt Cause Rx Descriptor Minimum Threshold Count */
-#define E1000_ICRXOC   0x04124	/* Interrupt Cause Receiver Overrun Count */
-#define E1000_RXCSUM   0x05000	/* RX Checksum Control - RW */
-#define E1000_RFCTL    0x05008	/* Receive Filter Control */
-#define E1000_MTA      0x05200	/* Multicast Table Array - RW Array */
-#define E1000_RA       0x05400	/* Receive Address - RW Array */
-#define E1000_VFTA     0x05600	/* VLAN Filter Table Array - RW Array */
-#define E1000_WUC      0x05800	/* Wakeup Control - RW */
-#define E1000_WUFC     0x05808	/* Wakeup Filter Control - RW */
-#define E1000_WUS      0x05810	/* Wakeup Status - RO */
-#define E1000_MANC     0x05820	/* Management Control - RW */
-#define E1000_IPAV     0x05838	/* IP Address Valid - RW */
-#define E1000_IP4AT    0x05840	/* IPv4 Address Table - RW Array */
-#define E1000_IP6AT    0x05880	/* IPv6 Address Table - RW Array */
-#define E1000_WUPL     0x05900	/* Wakeup Packet Length - RW */
-#define E1000_WUPM     0x05A00	/* Wakeup Packet Memory - RO A */
-#define E1000_FFLT     0x05F00	/* Flexible Filter Length Table - RW Array */
-#define E1000_HOST_IF  0x08800	/* Host Interface */
-#define E1000_FFMT     0x09000	/* Flexible Filter Mask Table - RW Array */
-#define E1000_FFVT     0x09800	/* Flexible Filter Value Table - RW Array */
-
-#define E1000_KUMCTRLSTA 0x00034	/* MAC-PHY interface - RW */
-#define E1000_MDPHYA     0x0003C	/* PHY address - 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 */
-#define E1000_GSCL_1    0x05B10	/* PCI-Ex Statistic Control #1 */
-#define E1000_GSCL_2    0x05B14	/* PCI-Ex Statistic Control #2 */
-#define E1000_GSCL_3    0x05B18	/* PCI-Ex Statistic Control #3 */
-#define E1000_GSCL_4    0x05B1C	/* PCI-Ex Statistic Control #4 */
-#define E1000_FACTPS    0x05B30	/* Function Active and Power State to MNG */
-#define E1000_SWSM      0x05B50	/* SW Semaphore */
-#define E1000_FWSM      0x05B54	/* FW Semaphore */
-#define E1000_FFLT_DBG  0x05F04	/* Debug Register */
-#define E1000_HICR      0x08F00	/* Host Interface Control */
-
-/* RSS registers */
-#define E1000_CPUVEC    0x02C10	/* CPU Vector Register - RW */
-#define E1000_MRQC      0x05818	/* Multiple Receive Control - RW */
-#define E1000_RETA      0x05C00	/* Redirection Table - RW Array */
-#define E1000_RSSRK     0x05C80	/* RSS Random Key - RW Array */
-#define E1000_RSSIM     0x05864	/* RSS Interrupt Mask */
-#define E1000_RSSIR     0x05868	/* RSS Interrupt Request */
-/* Register Set (82542)
- *
- * Some of the 82542 registers are located at different offsets than they are
- * in more current versions of the 8254x. Despite the difference in location,
- * the registers function in the same manner.
- */
-#define E1000_82542_CTL_AUX  E1000_CTL_AUX
-#define E1000_82542_CTRL     E1000_CTRL
-#define E1000_82542_CTRL_DUP E1000_CTRL_DUP
-#define E1000_82542_STATUS   E1000_STATUS
-#define E1000_82542_EECD     E1000_EECD
-#define E1000_82542_EERD     E1000_EERD
-#define E1000_82542_CTRL_EXT E1000_CTRL_EXT
-#define E1000_82542_FLA      E1000_FLA
-#define E1000_82542_MDIC     E1000_MDIC
-#define E1000_82542_SCTL     E1000_SCTL
-#define E1000_82542_FEXTNVM  E1000_FEXTNVM
-#define E1000_82542_FCAL     E1000_FCAL
-#define E1000_82542_FCAH     E1000_FCAH
-#define E1000_82542_FCT      E1000_FCT
-#define E1000_82542_VET      E1000_VET
-#define E1000_82542_RA       0x00040
-#define E1000_82542_ICR      E1000_ICR
-#define E1000_82542_ITR      E1000_ITR
-#define E1000_82542_ICS      E1000_ICS
-#define E1000_82542_IMS      E1000_IMS
-#define E1000_82542_IMC      E1000_IMC
-#define E1000_82542_RCTL     E1000_RCTL
-#define E1000_82542_RDTR     0x00108
-#define E1000_82542_RDBAL    0x00110
-#define E1000_82542_RDBAH    0x00114
-#define E1000_82542_RDLEN    0x00118
-#define E1000_82542_RDH      0x00120
-#define E1000_82542_RDT      0x00128
-#define E1000_82542_RDTR0    E1000_82542_RDTR
-#define E1000_82542_RDBAL0   E1000_82542_RDBAL
-#define E1000_82542_RDBAH0   E1000_82542_RDBAH
-#define E1000_82542_RDLEN0   E1000_82542_RDLEN
-#define E1000_82542_RDH0     E1000_82542_RDH
-#define E1000_82542_RDT0     E1000_82542_RDT
-#define E1000_82542_SRRCTL(_n) (0x280C + ((_n) << 8))	/* Split and Replication
-							 * RX Control - RW */
-#define E1000_82542_DCA_RXCTRL(_n) (0x02814 + ((_n) << 8))
-#define E1000_82542_RDBAH3   0x02B04	/* RX Desc Base High Queue 3 - RW */
-#define E1000_82542_RDBAL3   0x02B00	/* RX Desc Low Queue 3 - RW */
-#define E1000_82542_RDLEN3   0x02B08	/* RX Desc Length Queue 3 - RW */
-#define E1000_82542_RDH3     0x02B10	/* RX Desc Head Queue 3 - RW */
-#define E1000_82542_RDT3     0x02B18	/* RX Desc Tail Queue 3 - RW */
-#define E1000_82542_RDBAL2   0x02A00	/* RX Desc Base Low Queue 2 - RW */
-#define E1000_82542_RDBAH2   0x02A04	/* RX Desc Base High Queue 2 - RW */
-#define E1000_82542_RDLEN2   0x02A08	/* RX Desc Length Queue 2 - RW */
-#define E1000_82542_RDH2     0x02A10	/* RX Desc Head Queue 2 - RW */
-#define E1000_82542_RDT2     0x02A18	/* RX Desc Tail Queue 2 - RW */
-#define E1000_82542_RDTR1    0x00130
-#define E1000_82542_RDBAL1   0x00138
-#define E1000_82542_RDBAH1   0x0013C
-#define E1000_82542_RDLEN1   0x00140
-#define E1000_82542_RDH1     0x00148
-#define E1000_82542_RDT1     0x00150
-#define E1000_82542_FCRTH    0x00160
-#define E1000_82542_FCRTL    0x00168
-#define E1000_82542_FCTTV    E1000_FCTTV
-#define E1000_82542_TXCW     E1000_TXCW
-#define E1000_82542_RXCW     E1000_RXCW
-#define E1000_82542_MTA      0x00200
-#define E1000_82542_TCTL     E1000_TCTL
-#define E1000_82542_TCTL_EXT E1000_TCTL_EXT
-#define E1000_82542_TIPG     E1000_TIPG
-#define E1000_82542_TDBAL    0x00420
-#define E1000_82542_TDBAH    0x00424
-#define E1000_82542_TDLEN    0x00428
-#define E1000_82542_TDH      0x00430
-#define E1000_82542_TDT      0x00438
-#define E1000_82542_TIDV     0x00440
-#define E1000_82542_TBT      E1000_TBT
-#define E1000_82542_AIT      E1000_AIT
-#define E1000_82542_VFTA     0x00600
-#define E1000_82542_LEDCTL   E1000_LEDCTL
-#define E1000_82542_PBA      E1000_PBA
-#define E1000_82542_PBS      E1000_PBS
-#define E1000_82542_EEMNGCTL E1000_EEMNGCTL
-#define E1000_82542_EEARBC   E1000_EEARBC
-#define E1000_82542_FLASHT   E1000_FLASHT
-#define E1000_82542_EEWR     E1000_EEWR
-#define E1000_82542_FLSWCTL  E1000_FLSWCTL
-#define E1000_82542_FLSWDATA E1000_FLSWDATA
-#define E1000_82542_FLSWCNT  E1000_FLSWCNT
-#define E1000_82542_FLOP     E1000_FLOP
-#define E1000_82542_EXTCNF_CTRL  E1000_EXTCNF_CTRL
-#define E1000_82542_EXTCNF_SIZE  E1000_EXTCNF_SIZE
-#define E1000_82542_PHY_CTRL E1000_PHY_CTRL
-#define E1000_82542_ERT      E1000_ERT
-#define E1000_82542_RXDCTL   E1000_RXDCTL
-#define E1000_82542_RXDCTL1  E1000_RXDCTL1
-#define E1000_82542_RADV     E1000_RADV
-#define E1000_82542_RSRPD    E1000_RSRPD
-#define E1000_82542_TXDMAC   E1000_TXDMAC
-#define E1000_82542_KABGTXD  E1000_KABGTXD
-#define E1000_82542_TDFHS    E1000_TDFHS
-#define E1000_82542_TDFTS    E1000_TDFTS
-#define E1000_82542_TDFPC    E1000_TDFPC
-#define E1000_82542_TXDCTL   E1000_TXDCTL
-#define E1000_82542_TADV     E1000_TADV
-#define E1000_82542_TSPMT    E1000_TSPMT
-#define E1000_82542_CRCERRS  E1000_CRCERRS
-#define E1000_82542_ALGNERRC E1000_ALGNERRC
-#define E1000_82542_SYMERRS  E1000_SYMERRS
-#define E1000_82542_RXERRC   E1000_RXERRC
-#define E1000_82542_MPC      E1000_MPC
-#define E1000_82542_SCC      E1000_SCC
-#define E1000_82542_ECOL     E1000_ECOL
-#define E1000_82542_MCC      E1000_MCC
-#define E1000_82542_LATECOL  E1000_LATECOL
-#define E1000_82542_COLC     E1000_COLC
-#define E1000_82542_DC       E1000_DC
-#define E1000_82542_TNCRS    E1000_TNCRS
-#define E1000_82542_SEC      E1000_SEC
-#define E1000_82542_CEXTERR  E1000_CEXTERR
-#define E1000_82542_RLEC     E1000_RLEC
-#define E1000_82542_XONRXC   E1000_XONRXC
-#define E1000_82542_XONTXC   E1000_XONTXC
-#define E1000_82542_XOFFRXC  E1000_XOFFRXC
-#define E1000_82542_XOFFTXC  E1000_XOFFTXC
-#define E1000_82542_FCRUC    E1000_FCRUC
-#define E1000_82542_PRC64    E1000_PRC64
-#define E1000_82542_PRC127   E1000_PRC127
-#define E1000_82542_PRC255   E1000_PRC255
-#define E1000_82542_PRC511   E1000_PRC511
-#define E1000_82542_PRC1023  E1000_PRC1023
-#define E1000_82542_PRC1522  E1000_PRC1522
-#define E1000_82542_GPRC     E1000_GPRC
-#define E1000_82542_BPRC     E1000_BPRC
-#define E1000_82542_MPRC     E1000_MPRC
-#define E1000_82542_GPTC     E1000_GPTC
-#define E1000_82542_GORCL    E1000_GORCL
-#define E1000_82542_GORCH    E1000_GORCH
-#define E1000_82542_GOTCL    E1000_GOTCL
-#define E1000_82542_GOTCH    E1000_GOTCH
-#define E1000_82542_RNBC     E1000_RNBC
-#define E1000_82542_RUC      E1000_RUC
-#define E1000_82542_RFC      E1000_RFC
-#define E1000_82542_ROC      E1000_ROC
-#define E1000_82542_RJC      E1000_RJC
-#define E1000_82542_MGTPRC   E1000_MGTPRC
-#define E1000_82542_MGTPDC   E1000_MGTPDC
-#define E1000_82542_MGTPTC   E1000_MGTPTC
-#define E1000_82542_TORL     E1000_TORL
-#define E1000_82542_TORH     E1000_TORH
-#define E1000_82542_TOTL     E1000_TOTL
-#define E1000_82542_TOTH     E1000_TOTH
-#define E1000_82542_TPR      E1000_TPR
-#define E1000_82542_TPT      E1000_TPT
-#define E1000_82542_PTC64    E1000_PTC64
-#define E1000_82542_PTC127   E1000_PTC127
-#define E1000_82542_PTC255   E1000_PTC255
-#define E1000_82542_PTC511   E1000_PTC511
-#define E1000_82542_PTC1023  E1000_PTC1023
-#define E1000_82542_PTC1522  E1000_PTC1522
-#define E1000_82542_MPTC     E1000_MPTC
-#define E1000_82542_BPTC     E1000_BPTC
-#define E1000_82542_TSCTC    E1000_TSCTC
-#define E1000_82542_TSCTFC   E1000_TSCTFC
-#define E1000_82542_RXCSUM   E1000_RXCSUM
-#define E1000_82542_WUC      E1000_WUC
-#define E1000_82542_WUFC     E1000_WUFC
-#define E1000_82542_WUS      E1000_WUS
-#define E1000_82542_MANC     E1000_MANC
-#define E1000_82542_IPAV     E1000_IPAV
-#define E1000_82542_IP4AT    E1000_IP4AT
-#define E1000_82542_IP6AT    E1000_IP6AT
-#define E1000_82542_WUPL     E1000_WUPL
-#define E1000_82542_WUPM     E1000_WUPM
-#define E1000_82542_FFLT     E1000_FFLT
-#define E1000_82542_TDFH     0x08010
-#define E1000_82542_TDFT     0x08018
-#define E1000_82542_FFMT     E1000_FFMT
-#define E1000_82542_FFVT     E1000_FFVT
-#define E1000_82542_HOST_IF  E1000_HOST_IF
-#define E1000_82542_IAM         E1000_IAM
-#define E1000_82542_EEMNGCTL    E1000_EEMNGCTL
-#define E1000_82542_PSRCTL      E1000_PSRCTL
-#define E1000_82542_RAID        E1000_RAID
-#define E1000_82542_TARC0       E1000_TARC0
-#define E1000_82542_TDBAL1      E1000_TDBAL1
-#define E1000_82542_TDBAH1      E1000_TDBAH1
-#define E1000_82542_TDLEN1      E1000_TDLEN1
-#define E1000_82542_TDH1        E1000_TDH1
-#define E1000_82542_TDT1        E1000_TDT1
-#define E1000_82542_TXDCTL1     E1000_TXDCTL1
-#define E1000_82542_TARC1       E1000_TARC1
-#define E1000_82542_RFCTL       E1000_RFCTL
-#define E1000_82542_GCR         E1000_GCR
-#define E1000_82542_GSCL_1      E1000_GSCL_1
-#define E1000_82542_GSCL_2      E1000_GSCL_2
-#define E1000_82542_GSCL_3      E1000_GSCL_3
-#define E1000_82542_GSCL_4      E1000_GSCL_4
-#define E1000_82542_FACTPS      E1000_FACTPS
-#define E1000_82542_SWSM        E1000_SWSM
-#define E1000_82542_FWSM        E1000_FWSM
-#define E1000_82542_FFLT_DBG    E1000_FFLT_DBG
-#define E1000_82542_IAC         E1000_IAC
-#define E1000_82542_ICRXPTC     E1000_ICRXPTC
-#define E1000_82542_ICRXATC     E1000_ICRXATC
-#define E1000_82542_ICTXPTC     E1000_ICTXPTC
-#define E1000_82542_ICTXATC     E1000_ICTXATC
-#define E1000_82542_ICTXQEC     E1000_ICTXQEC
-#define E1000_82542_ICTXQMTC    E1000_ICTXQMTC
-#define E1000_82542_ICRXDMTC    E1000_ICRXDMTC
-#define E1000_82542_ICRXOC      E1000_ICRXOC
-#define E1000_82542_HICR        E1000_HICR
-
-#define E1000_82542_CPUVEC      E1000_CPUVEC
-#define E1000_82542_MRQC        E1000_MRQC
-#define E1000_82542_RETA        E1000_RETA
-#define E1000_82542_RSSRK       E1000_RSSRK
-#define E1000_82542_RSSIM       E1000_RSSIM
-#define E1000_82542_RSSIR       E1000_RSSIR
-#define E1000_82542_KUMCTRLSTA E1000_KUMCTRLSTA
-#define E1000_82542_SW_FW_SYNC E1000_SW_FW_SYNC
-
-/* Statistics counters collected by the MAC */
-struct e1000_hw_stats {
-	u64 crcerrs;
-	u64 algnerrc;
-	u64 symerrs;
-	u64 rxerrc;
-	u64 txerrc;
-	u64 mpc;
-	u64 scc;
-	u64 ecol;
-	u64 mcc;
-	u64 latecol;
-	u64 colc;
-	u64 dc;
-	u64 tncrs;
-	u64 sec;
-	u64 cexterr;
-	u64 rlec;
-	u64 xonrxc;
-	u64 xontxc;
-	u64 xoffrxc;
-	u64 xofftxc;
-	u64 fcruc;
-	u64 prc64;
-	u64 prc127;
-	u64 prc255;
-	u64 prc511;
-	u64 prc1023;
-	u64 prc1522;
-	u64 gprc;
-	u64 bprc;
-	u64 mprc;
-	u64 gptc;
-	u64 gorcl;
-	u64 gorch;
-	u64 gotcl;
-	u64 gotch;
-	u64 rnbc;
-	u64 ruc;
-	u64 rfc;
-	u64 roc;
-	u64 rlerrc;
-	u64 rjc;
-	u64 mgprc;
-	u64 mgpdc;
-	u64 mgptc;
-	u64 torl;
-	u64 torh;
-	u64 totl;
-	u64 toth;
-	u64 tpr;
-	u64 tpt;
-	u64 ptc64;
-	u64 ptc127;
-	u64 ptc255;
-	u64 ptc511;
-	u64 ptc1023;
-	u64 ptc1522;
-	u64 mptc;
-	u64 bptc;
-	u64 tsctc;
-	u64 tsctfc;
-	u64 iac;
-	u64 icrxptc;
-	u64 icrxatc;
-	u64 ictxptc;
-	u64 ictxatc;
-	u64 ictxqec;
-	u64 ictxqmtc;
-	u64 icrxdmtc;
-	u64 icrxoc;
-};
-
-/* Structure containing variables used by the shared code (e1000_hw.c) */
-struct e1000_hw {
-	u8 __iomem *hw_addr;
-	u8 __iomem *flash_address;
-	e1000_mac_type mac_type;
-	e1000_phy_type phy_type;
-	u32 phy_init_script;
-	e1000_media_type media_type;
-	void *back;
-	struct e1000_shadow_ram *eeprom_shadow_ram;
-	u32 flash_bank_size;
-	u32 flash_base_addr;
-	e1000_fc_type fc;
-	e1000_bus_speed bus_speed;
-	e1000_bus_width bus_width;
-	e1000_bus_type bus_type;
-	struct e1000_eeprom_info eeprom;
-	e1000_ms_type master_slave;
-	e1000_ms_type original_master_slave;
-	e1000_ffe_config ffe_config_state;
-	u32 asf_firmware_present;
-	u32 eeprom_semaphore_present;
-	unsigned long io_base;
-	u32 phy_id;
-	u32 phy_revision;
-	u32 phy_addr;
-	u32 original_fc;
-	u32 txcw;
-	u32 autoneg_failed;
-	u32 max_frame_size;
-	u32 min_frame_size;
-	u32 mc_filter_type;
-	u32 num_mc_addrs;
-	u32 collision_delta;
-	u32 tx_packet_delta;
-	u32 ledctl_default;
-	u32 ledctl_mode1;
-	u32 ledctl_mode2;
-	bool tx_pkt_filtering;
-	struct e1000_host_mng_dhcp_cookie mng_cookie;
-	u16 phy_spd_default;
-	u16 autoneg_advertised;
-	u16 pci_cmd_word;
-	u16 fc_high_water;
-	u16 fc_low_water;
-	u16 fc_pause_time;
-	u16 current_ifs_val;
-	u16 ifs_min_val;
-	u16 ifs_max_val;
-	u16 ifs_step_size;
-	u16 ifs_ratio;
-	u16 device_id;
-	u16 vendor_id;
-	u16 subsystem_id;
-	u16 subsystem_vendor_id;
-	u8 revision_id;
-	u8 autoneg;
-	u8 mdix;
-	u8 forced_speed_duplex;
-	u8 wait_autoneg_complete;
-	u8 dma_fairness;
-	u8 mac_addr[NODE_ADDRESS_SIZE];
-	u8 perm_mac_addr[NODE_ADDRESS_SIZE];
-	bool disable_polarity_correction;
-	bool speed_downgraded;
-	e1000_smart_speed smart_speed;
-	e1000_dsp_config dsp_config_state;
-	bool get_link_status;
-	bool serdes_has_link;
-	bool tbi_compatibility_en;
-	bool tbi_compatibility_on;
-	bool laa_is_present;
-	bool phy_reset_disable;
-	bool initialize_hw_bits_disable;
-	bool fc_send_xon;
-	bool fc_strict_ieee;
-	bool report_tx_early;
-	bool adaptive_ifs;
-	bool ifs_params_forced;
-	bool in_ifs_mode;
-	bool mng_reg_access_disabled;
-	bool leave_av_bit_off;
-	bool bad_tx_carr_stats_fd;
-	bool has_smbus;
-};
-
-#define E1000_EEPROM_SWDPIN0   0x0001	/* SWDPIN 0 EEPROM Value */
-#define E1000_EEPROM_LED_LOGIC 0x0020	/* Led Logic Word */
-#define E1000_EEPROM_RW_REG_DATA   16	/* Offset to data in EEPROM read/write registers */
-#define E1000_EEPROM_RW_REG_DONE   2	/* Offset to READ/WRITE done bit */
-#define E1000_EEPROM_RW_REG_START  1	/* First bit for telling part to start operation */
-#define E1000_EEPROM_RW_ADDR_SHIFT 2	/* Shift to the address bits */
-#define E1000_EEPROM_POLL_WRITE    1	/* Flag for polling for write complete */
-#define E1000_EEPROM_POLL_READ     0	/* Flag for polling for read complete */
-/* Register Bit Masks */
-/* Device Control */
-#define E1000_CTRL_FD       0x00000001	/* Full duplex.0=half; 1=full */
-#define E1000_CTRL_BEM      0x00000002	/* Endian Mode.0=little,1=big */
-#define E1000_CTRL_PRIOR    0x00000004	/* Priority on PCI. 0=rx,1=fair */
-#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004	/*Blocks new Master requests */
-#define E1000_CTRL_LRST     0x00000008	/* Link reset. 0=normal,1=reset */
-#define E1000_CTRL_TME      0x00000010	/* Test mode. 0=normal,1=test */
-#define E1000_CTRL_SLE      0x00000020	/* Serial Link on 0=dis,1=en */
-#define E1000_CTRL_ASDE     0x00000020	/* Auto-speed detect enable */
-#define E1000_CTRL_SLU      0x00000040	/* Set link up (Force Link) */
-#define E1000_CTRL_ILOS     0x00000080	/* Invert Loss-Of Signal */
-#define E1000_CTRL_SPD_SEL  0x00000300	/* Speed Select Mask */
-#define E1000_CTRL_SPD_10   0x00000000	/* Force 10Mb */
-#define E1000_CTRL_SPD_100  0x00000100	/* Force 100Mb */
-#define E1000_CTRL_SPD_1000 0x00000200	/* Force 1Gb */
-#define E1000_CTRL_BEM32    0x00000400	/* Big Endian 32 mode */
-#define E1000_CTRL_FRCSPD   0x00000800	/* Force Speed */
-#define E1000_CTRL_FRCDPX   0x00001000	/* Force Duplex */
-#define E1000_CTRL_D_UD_EN  0x00002000	/* Dock/Undock enable */
-#define E1000_CTRL_D_UD_POLARITY 0x00004000	/* Defined polarity of Dock/Undock indication in SDP[0] */
-#define E1000_CTRL_FORCE_PHY_RESET 0x00008000	/* Reset both PHY ports, through PHYRST_N pin */
-#define E1000_CTRL_EXT_LINK_EN 0x00010000	/* enable link status from external LINK_0 and LINK_1 pins */
-#define E1000_CTRL_SWDPIN0  0x00040000	/* SWDPIN 0 value */
-#define E1000_CTRL_SWDPIN1  0x00080000	/* SWDPIN 1 value */
-#define E1000_CTRL_SWDPIN2  0x00100000	/* SWDPIN 2 value */
-#define E1000_CTRL_SWDPIN3  0x00200000	/* SWDPIN 3 value */
-#define E1000_CTRL_SWDPIO0  0x00400000	/* SWDPIN 0 Input or output */
-#define E1000_CTRL_SWDPIO1  0x00800000	/* SWDPIN 1 input or output */
-#define E1000_CTRL_SWDPIO2  0x01000000	/* SWDPIN 2 input or output */
-#define E1000_CTRL_SWDPIO3  0x02000000	/* SWDPIN 3 input or output */
-#define E1000_CTRL_RST      0x04000000	/* Global reset */
-#define E1000_CTRL_RFCE     0x08000000	/* Receive Flow Control enable */
-#define E1000_CTRL_TFCE     0x10000000	/* Transmit flow control enable */
-#define E1000_CTRL_RTE      0x20000000	/* Routing tag enable */
-#define E1000_CTRL_VME      0x40000000	/* IEEE VLAN mode enable */
-#define E1000_CTRL_PHY_RST  0x80000000	/* PHY Reset */
-#define E1000_CTRL_SW2FW_INT 0x02000000	/* Initiate an interrupt to manageability engine */
-
-/* Device Status */
-#define E1000_STATUS_FD         0x00000001	/* Full duplex.0=half,1=full */
-#define E1000_STATUS_LU         0x00000002	/* Link up.0=no,1=link */
-#define E1000_STATUS_FUNC_MASK  0x0000000C	/* PCI Function Mask */
-#define E1000_STATUS_FUNC_SHIFT 2
-#define E1000_STATUS_FUNC_0     0x00000000	/* Function 0 */
-#define E1000_STATUS_FUNC_1     0x00000004	/* Function 1 */
-#define E1000_STATUS_TXOFF      0x00000010	/* transmission paused */
-#define E1000_STATUS_TBIMODE    0x00000020	/* TBI mode */
-#define E1000_STATUS_SPEED_MASK 0x000000C0
-#define E1000_STATUS_SPEED_10   0x00000000	/* Speed 10Mb/s */
-#define E1000_STATUS_SPEED_100  0x00000040	/* Speed 100Mb/s */
-#define E1000_STATUS_SPEED_1000 0x00000080	/* Speed 1000Mb/s */
-#define E1000_STATUS_LAN_INIT_DONE 0x00000200	/* Lan Init Completion
-						   by EEPROM/Flash */
-#define E1000_STATUS_ASDV       0x00000300	/* Auto speed detect value */
-#define E1000_STATUS_DOCK_CI    0x00000800	/* Change in Dock/Undock state. Clear on write '0'. */
-#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000	/* Status of Master requests. */
-#define E1000_STATUS_MTXCKOK    0x00000400	/* MTX clock running OK */
-#define E1000_STATUS_PCI66      0x00000800	/* In 66Mhz slot */
-#define E1000_STATUS_BUS64      0x00001000	/* In 64 bit slot */
-#define E1000_STATUS_PCIX_MODE  0x00002000	/* PCI-X mode */
-#define E1000_STATUS_PCIX_SPEED 0x0000C000	/* PCI-X bus speed */
-#define E1000_STATUS_BMC_SKU_0  0x00100000	/* BMC USB redirect disabled */
-#define E1000_STATUS_BMC_SKU_1  0x00200000	/* BMC SRAM disabled */
-#define E1000_STATUS_BMC_SKU_2  0x00400000	/* BMC SDRAM disabled */
-#define E1000_STATUS_BMC_CRYPTO 0x00800000	/* BMC crypto disabled */
-#define E1000_STATUS_BMC_LITE   0x01000000	/* BMC external code execution disabled */
-#define E1000_STATUS_RGMII_ENABLE 0x02000000	/* RGMII disabled */
-#define E1000_STATUS_FUSE_8       0x04000000
-#define E1000_STATUS_FUSE_9       0x08000000
-#define E1000_STATUS_SERDES0_DIS  0x10000000	/* SERDES disabled on port 0 */
-#define E1000_STATUS_SERDES1_DIS  0x20000000	/* SERDES disabled on port 1 */
-
-/* Constants used to interpret the masked PCI-X bus speed. */
-#define E1000_STATUS_PCIX_SPEED_66  0x00000000	/* PCI-X bus speed  50-66 MHz */
-#define E1000_STATUS_PCIX_SPEED_100 0x00004000	/* PCI-X bus speed  66-100 MHz */
-#define E1000_STATUS_PCIX_SPEED_133 0x00008000	/* PCI-X bus speed 100-133 MHz */
-
-/* EEPROM/Flash Control */
-#define E1000_EECD_SK        0x00000001	/* EEPROM Clock */
-#define E1000_EECD_CS        0x00000002	/* EEPROM Chip Select */
-#define E1000_EECD_DI        0x00000004	/* EEPROM Data In */
-#define E1000_EECD_DO        0x00000008	/* EEPROM Data Out */
-#define E1000_EECD_FWE_MASK  0x00000030
-#define E1000_EECD_FWE_DIS   0x00000010	/* Disable FLASH writes */
-#define E1000_EECD_FWE_EN    0x00000020	/* Enable FLASH writes */
-#define E1000_EECD_FWE_SHIFT 4
-#define E1000_EECD_REQ       0x00000040	/* EEPROM Access Request */
-#define E1000_EECD_GNT       0x00000080	/* EEPROM Access Grant */
-#define E1000_EECD_PRES      0x00000100	/* EEPROM Present */
-#define E1000_EECD_SIZE      0x00000200	/* EEPROM Size (0=64 word 1=256 word) */
-#define E1000_EECD_ADDR_BITS 0x00000400	/* EEPROM Addressing bits based on type
-					 * (0-small, 1-large) */
-#define E1000_EECD_TYPE      0x00002000	/* EEPROM Type (1-SPI, 0-Microwire) */
-#ifndef E1000_EEPROM_GRANT_ATTEMPTS
-#define E1000_EEPROM_GRANT_ATTEMPTS 1000	/* EEPROM # attempts to gain grant */
-#endif
-#define E1000_EECD_AUTO_RD          0x00000200	/* EEPROM Auto Read done */
-#define E1000_EECD_SIZE_EX_MASK     0x00007800	/* EEprom Size */
-#define E1000_EECD_SIZE_EX_SHIFT    11
-#define E1000_EECD_NVADDS    0x00018000	/* NVM Address Size */
-#define E1000_EECD_SELSHAD   0x00020000	/* Select Shadow RAM */
-#define E1000_EECD_INITSRAM  0x00040000	/* Initialize Shadow RAM */
-#define E1000_EECD_FLUPD     0x00080000	/* Update FLASH */
-#define E1000_EECD_AUPDEN    0x00100000	/* Enable Autonomous FLASH update */
-#define E1000_EECD_SHADV     0x00200000	/* Shadow RAM Data Valid */
-#define E1000_EECD_SEC1VAL   0x00400000	/* Sector One Valid */
-#define E1000_EECD_SECVAL_SHIFT      22
-#define E1000_STM_OPCODE     0xDB00
-#define E1000_HICR_FW_RESET  0xC0
-
-#define E1000_SHADOW_RAM_WORDS     2048
-#define E1000_ICH_NVM_SIG_WORD     0x13
-#define E1000_ICH_NVM_SIG_MASK     0xC0
-
-/* EEPROM Read */
-#define E1000_EERD_START      0x00000001	/* Start Read */
-#define E1000_EERD_DONE       0x00000010	/* Read Done */
-#define E1000_EERD_ADDR_SHIFT 8
-#define E1000_EERD_ADDR_MASK  0x0000FF00	/* Read Address */
-#define E1000_EERD_DATA_SHIFT 16
-#define E1000_EERD_DATA_MASK  0xFFFF0000	/* Read Data */
-
-/* SPI EEPROM Status Register */
-#define EEPROM_STATUS_RDY_SPI  0x01
-#define EEPROM_STATUS_WEN_SPI  0x02
-#define EEPROM_STATUS_BP0_SPI  0x04
-#define EEPROM_STATUS_BP1_SPI  0x08
-#define EEPROM_STATUS_WPEN_SPI 0x80
-
-/* Extended Device Control */
-#define E1000_CTRL_EXT_GPI0_EN   0x00000001	/* Maps SDP4 to GPI0 */
-#define E1000_CTRL_EXT_GPI1_EN   0x00000002	/* Maps SDP5 to GPI1 */
-#define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN
-#define E1000_CTRL_EXT_GPI2_EN   0x00000004	/* Maps SDP6 to GPI2 */
-#define E1000_CTRL_EXT_GPI3_EN   0x00000008	/* Maps SDP7 to GPI3 */
-#define E1000_CTRL_EXT_SDP4_DATA 0x00000010	/* Value of SW Defineable Pin 4 */
-#define E1000_CTRL_EXT_SDP5_DATA 0x00000020	/* Value of SW Defineable Pin 5 */
-#define E1000_CTRL_EXT_PHY_INT   E1000_CTRL_EXT_SDP5_DATA
-#define E1000_CTRL_EXT_SDP6_DATA 0x00000040	/* Value of SW Defineable Pin 6 */
-#define E1000_CTRL_EXT_SDP7_DATA 0x00000080	/* Value of SW Defineable Pin 7 */
-#define E1000_CTRL_EXT_SDP4_DIR  0x00000100	/* Direction of SDP4 0=in 1=out */
-#define E1000_CTRL_EXT_SDP5_DIR  0x00000200	/* Direction of SDP5 0=in 1=out */
-#define E1000_CTRL_EXT_SDP6_DIR  0x00000400	/* Direction of SDP6 0=in 1=out */
-#define E1000_CTRL_EXT_SDP7_DIR  0x00000800	/* Direction of SDP7 0=in 1=out */
-#define E1000_CTRL_EXT_ASDCHK    0x00001000	/* Initiate an ASD sequence */
-#define E1000_CTRL_EXT_EE_RST    0x00002000	/* Reinitialize from EEPROM */
-#define E1000_CTRL_EXT_IPS       0x00004000	/* Invert Power State */
-#define E1000_CTRL_EXT_SPD_BYPS  0x00008000	/* Speed Select Bypass */
-#define E1000_CTRL_EXT_RO_DIS    0x00020000	/* Relaxed Ordering disable */
-#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
-#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
-#define E1000_CTRL_EXT_LINK_MODE_TBI  0x00C00000
-#define E1000_CTRL_EXT_LINK_MODE_KMRN 0x00000000
-#define E1000_CTRL_EXT_LINK_MODE_SERDES  0x00C00000
-#define E1000_CTRL_EXT_LINK_MODE_SGMII   0x00800000
-#define E1000_CTRL_EXT_WR_WMARK_MASK  0x03000000
-#define E1000_CTRL_EXT_WR_WMARK_256   0x00000000
-#define E1000_CTRL_EXT_WR_WMARK_320   0x01000000
-#define E1000_CTRL_EXT_WR_WMARK_384   0x02000000
-#define E1000_CTRL_EXT_WR_WMARK_448   0x03000000
-#define E1000_CTRL_EXT_DRV_LOAD       0x10000000	/* Driver loaded bit for FW */
-#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_CRTL_EXT_PB_PAREN       0x01000000	/* packet buffer parity error detection enabled */
-#define E1000_CTRL_EXT_DF_PAREN       0x02000000	/* descriptor FIFO parity error detection enable */
-#define E1000_CTRL_EXT_GHOST_PAREN    0x40000000
-
-/* MDI Control */
-#define E1000_MDIC_DATA_MASK 0x0000FFFF
-#define E1000_MDIC_REG_MASK  0x001F0000
-#define E1000_MDIC_REG_SHIFT 16
-#define E1000_MDIC_PHY_MASK  0x03E00000
-#define E1000_MDIC_PHY_SHIFT 21
-#define E1000_MDIC_OP_WRITE  0x04000000
-#define E1000_MDIC_OP_READ   0x08000000
-#define E1000_MDIC_READY     0x10000000
-#define E1000_MDIC_INT_EN    0x20000000
-#define E1000_MDIC_ERROR     0x40000000
-
-#define INTEL_CE_GBE_MDIC_OP_WRITE      0x04000000
-#define INTEL_CE_GBE_MDIC_OP_READ       0x00000000
-#define INTEL_CE_GBE_MDIC_GO            0x80000000
-#define INTEL_CE_GBE_MDIC_READ_ERROR    0x80000000
-
-#define E1000_KUMCTRLSTA_MASK           0x0000FFFF
-#define E1000_KUMCTRLSTA_OFFSET         0x001F0000
-#define E1000_KUMCTRLSTA_OFFSET_SHIFT   16
-#define E1000_KUMCTRLSTA_REN            0x00200000
-
-#define E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL      0x00000000
-#define E1000_KUMCTRLSTA_OFFSET_CTRL           0x00000001
-#define E1000_KUMCTRLSTA_OFFSET_INB_CTRL       0x00000002
-#define E1000_KUMCTRLSTA_OFFSET_DIAG           0x00000003
-#define E1000_KUMCTRLSTA_OFFSET_TIMEOUTS       0x00000004
-#define E1000_KUMCTRLSTA_OFFSET_INB_PARAM      0x00000009
-#define E1000_KUMCTRLSTA_OFFSET_HD_CTRL        0x00000010
-#define E1000_KUMCTRLSTA_OFFSET_M2P_SERDES     0x0000001E
-#define E1000_KUMCTRLSTA_OFFSET_M2P_MODES      0x0000001F
-
-/* FIFO Control */
-#define E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS   0x00000008
-#define E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS   0x00000800
-
-/* In-Band Control */
-#define E1000_KUMCTRLSTA_INB_CTRL_LINK_STATUS_TX_TIMEOUT_DEFAULT    0x00000500
-#define E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING  0x00000010
-
-/* Half-Duplex Control */
-#define E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT 0x00000004
-#define E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT  0x00000000
-
-#define E1000_KUMCTRLSTA_OFFSET_K0S_CTRL       0x0000001E
-
-#define E1000_KUMCTRLSTA_DIAG_FELPBK           0x2000
-#define E1000_KUMCTRLSTA_DIAG_NELPBK           0x1000
-
-#define E1000_KUMCTRLSTA_K0S_100_EN            0x2000
-#define E1000_KUMCTRLSTA_K0S_GBE_EN            0x1000
-#define E1000_KUMCTRLSTA_K0S_ENTRY_LATENCY_MASK   0x0003
-
-#define E1000_KABGTXD_BGSQLBIAS                0x00050000
-
-#define E1000_PHY_CTRL_SPD_EN                  0x00000001
-#define E1000_PHY_CTRL_D0A_LPLU                0x00000002
-#define E1000_PHY_CTRL_NOND0A_LPLU             0x00000004
-#define E1000_PHY_CTRL_NOND0A_GBE_DISABLE      0x00000008
-#define E1000_PHY_CTRL_GBE_DISABLE             0x00000040
-#define E1000_PHY_CTRL_B2B_EN                  0x00000080
-
-/* LED Control */
-#define E1000_LEDCTL_LED0_MODE_MASK       0x0000000F
-#define E1000_LEDCTL_LED0_MODE_SHIFT      0
-#define E1000_LEDCTL_LED0_BLINK_RATE      0x0000020
-#define E1000_LEDCTL_LED0_IVRT            0x00000040
-#define E1000_LEDCTL_LED0_BLINK           0x00000080
-#define E1000_LEDCTL_LED1_MODE_MASK       0x00000F00
-#define E1000_LEDCTL_LED1_MODE_SHIFT      8
-#define E1000_LEDCTL_LED1_BLINK_RATE      0x0002000
-#define E1000_LEDCTL_LED1_IVRT            0x00004000
-#define E1000_LEDCTL_LED1_BLINK           0x00008000
-#define E1000_LEDCTL_LED2_MODE_MASK       0x000F0000
-#define E1000_LEDCTL_LED2_MODE_SHIFT      16
-#define E1000_LEDCTL_LED2_BLINK_RATE      0x00200000
-#define E1000_LEDCTL_LED2_IVRT            0x00400000
-#define E1000_LEDCTL_LED2_BLINK           0x00800000
-#define E1000_LEDCTL_LED3_MODE_MASK       0x0F000000
-#define E1000_LEDCTL_LED3_MODE_SHIFT      24
-#define E1000_LEDCTL_LED3_BLINK_RATE      0x20000000
-#define E1000_LEDCTL_LED3_IVRT            0x40000000
-#define E1000_LEDCTL_LED3_BLINK           0x80000000
-
-#define E1000_LEDCTL_MODE_LINK_10_1000  0x0
-#define E1000_LEDCTL_MODE_LINK_100_1000 0x1
-#define E1000_LEDCTL_MODE_LINK_UP       0x2
-#define E1000_LEDCTL_MODE_ACTIVITY      0x3
-#define E1000_LEDCTL_MODE_LINK_ACTIVITY 0x4
-#define E1000_LEDCTL_MODE_LINK_10       0x5
-#define E1000_LEDCTL_MODE_LINK_100      0x6
-#define E1000_LEDCTL_MODE_LINK_1000     0x7
-#define E1000_LEDCTL_MODE_PCIX_MODE     0x8
-#define E1000_LEDCTL_MODE_FULL_DUPLEX   0x9
-#define E1000_LEDCTL_MODE_COLLISION     0xA
-#define E1000_LEDCTL_MODE_BUS_SPEED     0xB
-#define E1000_LEDCTL_MODE_BUS_SIZE      0xC
-#define E1000_LEDCTL_MODE_PAUSED        0xD
-#define E1000_LEDCTL_MODE_LED_ON        0xE
-#define E1000_LEDCTL_MODE_LED_OFF       0xF
-
-/* Receive Address */
-#define E1000_RAH_AV  0x80000000	/* Receive descriptor valid */
-
-/* Interrupt Cause Read */
-#define E1000_ICR_TXDW          0x00000001	/* Transmit desc written back */
-#define E1000_ICR_TXQE          0x00000002	/* Transmit Queue empty */
-#define E1000_ICR_LSC           0x00000004	/* Link Status Change */
-#define E1000_ICR_RXSEQ         0x00000008	/* rx sequence error */
-#define E1000_ICR_RXDMT0        0x00000010	/* rx desc min. threshold (0) */
-#define E1000_ICR_RXO           0x00000040	/* rx overrun */
-#define E1000_ICR_RXT0          0x00000080	/* rx timer intr (ring 0) */
-#define E1000_ICR_MDAC          0x00000200	/* MDIO access complete */
-#define E1000_ICR_RXCFG         0x00000400	/* RX /c/ ordered set */
-#define E1000_ICR_GPI_EN0       0x00000800	/* GP Int 0 */
-#define E1000_ICR_GPI_EN1       0x00001000	/* GP Int 1 */
-#define E1000_ICR_GPI_EN2       0x00002000	/* GP Int 2 */
-#define E1000_ICR_GPI_EN3       0x00004000	/* GP Int 3 */
-#define E1000_ICR_TXD_LOW       0x00008000
-#define E1000_ICR_SRPD          0x00010000
-#define E1000_ICR_ACK           0x00020000	/* Receive Ack frame */
-#define E1000_ICR_MNG           0x00040000	/* Manageability event */
-#define E1000_ICR_DOCK          0x00080000	/* Dock/Undock */
-#define E1000_ICR_INT_ASSERTED  0x80000000	/* If this bit asserted, the driver should claim the interrupt */
-#define E1000_ICR_RXD_FIFO_PAR0 0x00100000	/* queue 0 Rx descriptor FIFO parity error */
-#define E1000_ICR_TXD_FIFO_PAR0 0x00200000	/* queue 0 Tx descriptor FIFO parity error */
-#define E1000_ICR_HOST_ARB_PAR  0x00400000	/* host arb read buffer parity error */
-#define E1000_ICR_PB_PAR        0x00800000	/* packet buffer parity error */
-#define E1000_ICR_RXD_FIFO_PAR1 0x01000000	/* queue 1 Rx descriptor FIFO parity error */
-#define E1000_ICR_TXD_FIFO_PAR1 0x02000000	/* queue 1 Tx descriptor FIFO parity error */
-#define E1000_ICR_ALL_PARITY    0x03F00000	/* all parity error bits */
-#define E1000_ICR_DSW           0x00000020	/* FW changed the status of DISSW bit in the FWSM */
-#define E1000_ICR_PHYINT        0x00001000	/* LAN connected device generates an interrupt */
-#define E1000_ICR_EPRST         0x00100000	/* ME hardware reset occurs */
-
-/* Interrupt Cause Set */
-#define E1000_ICS_TXDW      E1000_ICR_TXDW	/* Transmit desc written back */
-#define E1000_ICS_TXQE      E1000_ICR_TXQE	/* Transmit Queue empty */
-#define E1000_ICS_LSC       E1000_ICR_LSC	/* Link Status Change */
-#define E1000_ICS_RXSEQ     E1000_ICR_RXSEQ	/* rx sequence error */
-#define E1000_ICS_RXDMT0    E1000_ICR_RXDMT0	/* rx desc min. threshold */
-#define E1000_ICS_RXO       E1000_ICR_RXO	/* rx overrun */
-#define E1000_ICS_RXT0      E1000_ICR_RXT0	/* rx timer intr */
-#define E1000_ICS_MDAC      E1000_ICR_MDAC	/* MDIO access complete */
-#define E1000_ICS_RXCFG     E1000_ICR_RXCFG	/* RX /c/ ordered set */
-#define E1000_ICS_GPI_EN0   E1000_ICR_GPI_EN0	/* GP Int 0 */
-#define E1000_ICS_GPI_EN1   E1000_ICR_GPI_EN1	/* GP Int 1 */
-#define E1000_ICS_GPI_EN2   E1000_ICR_GPI_EN2	/* GP Int 2 */
-#define E1000_ICS_GPI_EN3   E1000_ICR_GPI_EN3	/* GP Int 3 */
-#define E1000_ICS_TXD_LOW   E1000_ICR_TXD_LOW
-#define E1000_ICS_SRPD      E1000_ICR_SRPD
-#define E1000_ICS_ACK       E1000_ICR_ACK	/* Receive Ack frame */
-#define E1000_ICS_MNG       E1000_ICR_MNG	/* Manageability event */
-#define E1000_ICS_DOCK      E1000_ICR_DOCK	/* Dock/Undock */
-#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0	/* queue 0 Rx descriptor FIFO parity error */
-#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0	/* queue 0 Tx descriptor FIFO parity error */
-#define E1000_ICS_HOST_ARB_PAR  E1000_ICR_HOST_ARB_PAR	/* host arb read buffer parity error */
-#define E1000_ICS_PB_PAR        E1000_ICR_PB_PAR	/* packet buffer parity error */
-#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1	/* queue 1 Rx descriptor FIFO parity error */
-#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1	/* queue 1 Tx descriptor FIFO parity error */
-#define E1000_ICS_DSW       E1000_ICR_DSW
-#define E1000_ICS_PHYINT    E1000_ICR_PHYINT
-#define E1000_ICS_EPRST     E1000_ICR_EPRST
-
-/* Interrupt Mask Set */
-#define E1000_IMS_TXDW      E1000_ICR_TXDW	/* Transmit desc written back */
-#define E1000_IMS_TXQE      E1000_ICR_TXQE	/* Transmit Queue empty */
-#define E1000_IMS_LSC       E1000_ICR_LSC	/* Link Status Change */
-#define E1000_IMS_RXSEQ     E1000_ICR_RXSEQ	/* rx sequence error */
-#define E1000_IMS_RXDMT0    E1000_ICR_RXDMT0	/* rx desc min. threshold */
-#define E1000_IMS_RXO       E1000_ICR_RXO	/* rx overrun */
-#define E1000_IMS_RXT0      E1000_ICR_RXT0	/* rx timer intr */
-#define E1000_IMS_MDAC      E1000_ICR_MDAC	/* MDIO access complete */
-#define E1000_IMS_RXCFG     E1000_ICR_RXCFG	/* RX /c/ ordered set */
-#define E1000_IMS_GPI_EN0   E1000_ICR_GPI_EN0	/* GP Int 0 */
-#define E1000_IMS_GPI_EN1   E1000_ICR_GPI_EN1	/* GP Int 1 */
-#define E1000_IMS_GPI_EN2   E1000_ICR_GPI_EN2	/* GP Int 2 */
-#define E1000_IMS_GPI_EN3   E1000_ICR_GPI_EN3	/* GP Int 3 */
-#define E1000_IMS_TXD_LOW   E1000_ICR_TXD_LOW
-#define E1000_IMS_SRPD      E1000_ICR_SRPD
-#define E1000_IMS_ACK       E1000_ICR_ACK	/* Receive Ack frame */
-#define E1000_IMS_MNG       E1000_ICR_MNG	/* Manageability event */
-#define E1000_IMS_DOCK      E1000_ICR_DOCK	/* Dock/Undock */
-#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0	/* queue 0 Rx descriptor FIFO parity error */
-#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0	/* queue 0 Tx descriptor FIFO parity error */
-#define E1000_IMS_HOST_ARB_PAR  E1000_ICR_HOST_ARB_PAR	/* host arb read buffer parity error */
-#define E1000_IMS_PB_PAR        E1000_ICR_PB_PAR	/* packet buffer parity error */
-#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1	/* queue 1 Rx descriptor FIFO parity error */
-#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1	/* queue 1 Tx descriptor FIFO parity error */
-#define E1000_IMS_DSW       E1000_ICR_DSW
-#define E1000_IMS_PHYINT    E1000_ICR_PHYINT
-#define E1000_IMS_EPRST     E1000_ICR_EPRST
-
-/* Interrupt Mask Clear */
-#define E1000_IMC_TXDW      E1000_ICR_TXDW	/* Transmit desc written back */
-#define E1000_IMC_TXQE      E1000_ICR_TXQE	/* Transmit Queue empty */
-#define E1000_IMC_LSC       E1000_ICR_LSC	/* Link Status Change */
-#define E1000_IMC_RXSEQ     E1000_ICR_RXSEQ	/* rx sequence error */
-#define E1000_IMC_RXDMT0    E1000_ICR_RXDMT0	/* rx desc min. threshold */
-#define E1000_IMC_RXO       E1000_ICR_RXO	/* rx overrun */
-#define E1000_IMC_RXT0      E1000_ICR_RXT0	/* rx timer intr */
-#define E1000_IMC_MDAC      E1000_ICR_MDAC	/* MDIO access complete */
-#define E1000_IMC_RXCFG     E1000_ICR_RXCFG	/* RX /c/ ordered set */
-#define E1000_IMC_GPI_EN0   E1000_ICR_GPI_EN0	/* GP Int 0 */
-#define E1000_IMC_GPI_EN1   E1000_ICR_GPI_EN1	/* GP Int 1 */
-#define E1000_IMC_GPI_EN2   E1000_ICR_GPI_EN2	/* GP Int 2 */
-#define E1000_IMC_GPI_EN3   E1000_ICR_GPI_EN3	/* GP Int 3 */
-#define E1000_IMC_TXD_LOW   E1000_ICR_TXD_LOW
-#define E1000_IMC_SRPD      E1000_ICR_SRPD
-#define E1000_IMC_ACK       E1000_ICR_ACK	/* Receive Ack frame */
-#define E1000_IMC_MNG       E1000_ICR_MNG	/* Manageability event */
-#define E1000_IMC_DOCK      E1000_ICR_DOCK	/* Dock/Undock */
-#define E1000_IMC_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0	/* queue 0 Rx descriptor FIFO parity error */
-#define E1000_IMC_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0	/* queue 0 Tx descriptor FIFO parity error */
-#define E1000_IMC_HOST_ARB_PAR  E1000_ICR_HOST_ARB_PAR	/* host arb read buffer parity error */
-#define E1000_IMC_PB_PAR        E1000_ICR_PB_PAR	/* packet buffer parity error */
-#define E1000_IMC_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1	/* queue 1 Rx descriptor FIFO parity error */
-#define E1000_IMC_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1	/* queue 1 Tx descriptor FIFO parity error */
-#define E1000_IMC_DSW       E1000_ICR_DSW
-#define E1000_IMC_PHYINT    E1000_ICR_PHYINT
-#define E1000_IMC_EPRST     E1000_ICR_EPRST
-
-/* Receive Control */
-#define E1000_RCTL_RST            0x00000001	/* Software reset */
-#define E1000_RCTL_EN             0x00000002	/* enable */
-#define E1000_RCTL_SBP            0x00000004	/* store bad packet */
-#define E1000_RCTL_UPE            0x00000008	/* unicast promiscuous enable */
-#define E1000_RCTL_MPE            0x00000010	/* multicast promiscuous enab */
-#define E1000_RCTL_LPE            0x00000020	/* long packet enable */
-#define E1000_RCTL_LBM_NO         0x00000000	/* no loopback mode */
-#define E1000_RCTL_LBM_MAC        0x00000040	/* MAC loopback mode */
-#define E1000_RCTL_LBM_SLP        0x00000080	/* serial link loopback mode */
-#define E1000_RCTL_LBM_TCVR       0x000000C0	/* tcvr loopback mode */
-#define E1000_RCTL_DTYP_MASK      0x00000C00	/* Descriptor type mask */
-#define E1000_RCTL_DTYP_PS        0x00000400	/* Packet Split descriptor */
-#define E1000_RCTL_RDMTS_HALF     0x00000000	/* rx desc min threshold size */
-#define E1000_RCTL_RDMTS_QUAT     0x00000100	/* rx desc min threshold size */
-#define E1000_RCTL_RDMTS_EIGTH    0x00000200	/* rx desc min threshold size */
-#define E1000_RCTL_MO_SHIFT       12	/* multicast offset shift */
-#define E1000_RCTL_MO_0           0x00000000	/* multicast offset 11:0 */
-#define E1000_RCTL_MO_1           0x00001000	/* multicast offset 12:1 */
-#define E1000_RCTL_MO_2           0x00002000	/* multicast offset 13:2 */
-#define E1000_RCTL_MO_3           0x00003000	/* multicast offset 15:4 */
-#define E1000_RCTL_MDR            0x00004000	/* multicast desc ring 0 */
-#define E1000_RCTL_BAM            0x00008000	/* broadcast enable */
-/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
-#define E1000_RCTL_SZ_2048        0x00000000	/* rx buffer size 2048 */
-#define E1000_RCTL_SZ_1024        0x00010000	/* rx buffer size 1024 */
-#define E1000_RCTL_SZ_512         0x00020000	/* rx buffer size 512 */
-#define E1000_RCTL_SZ_256         0x00030000	/* rx buffer size 256 */
-/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
-#define E1000_RCTL_SZ_16384       0x00010000	/* rx buffer size 16384 */
-#define E1000_RCTL_SZ_8192        0x00020000	/* rx buffer size 8192 */
-#define E1000_RCTL_SZ_4096        0x00030000	/* rx buffer size 4096 */
-#define E1000_RCTL_VFE            0x00040000	/* vlan filter enable */
-#define E1000_RCTL_CFIEN          0x00080000	/* canonical form enable */
-#define E1000_RCTL_CFI            0x00100000	/* canonical form indicator */
-#define E1000_RCTL_DPF            0x00400000	/* discard pause frames */
-#define E1000_RCTL_PMCF           0x00800000	/* pass MAC control frames */
-#define E1000_RCTL_BSEX           0x02000000	/* Buffer size extension */
-#define E1000_RCTL_SECRC          0x04000000	/* Strip Ethernet CRC */
-#define E1000_RCTL_FLXBUF_MASK    0x78000000	/* Flexible buffer size */
-#define E1000_RCTL_FLXBUF_SHIFT   27	/* Flexible buffer shift */
-
-/* Use byte values for the following shift parameters
- * Usage:
- *     psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) &
- *                  E1000_PSRCTL_BSIZE0_MASK) |
- *                ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) &
- *                  E1000_PSRCTL_BSIZE1_MASK) |
- *                ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) &
- *                  E1000_PSRCTL_BSIZE2_MASK) |
- *                ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |;
- *                  E1000_PSRCTL_BSIZE3_MASK))
- * where value0 = [128..16256],  default=256
- *       value1 = [1024..64512], default=4096
- *       value2 = [0..64512],    default=4096
- *       value3 = [0..64512],    default=0
- */
-
-#define E1000_PSRCTL_BSIZE0_MASK   0x0000007F
-#define E1000_PSRCTL_BSIZE1_MASK   0x00003F00
-#define E1000_PSRCTL_BSIZE2_MASK   0x003F0000
-#define E1000_PSRCTL_BSIZE3_MASK   0x3F000000
-
-#define E1000_PSRCTL_BSIZE0_SHIFT  7	/* Shift _right_ 7 */
-#define E1000_PSRCTL_BSIZE1_SHIFT  2	/* Shift _right_ 2 */
-#define E1000_PSRCTL_BSIZE2_SHIFT  6	/* Shift _left_ 6 */
-#define E1000_PSRCTL_BSIZE3_SHIFT 14	/* Shift _left_ 14 */
-
-/* SW_W_SYNC definitions */
-#define E1000_SWFW_EEP_SM     0x0001
-#define E1000_SWFW_PHY0_SM    0x0002
-#define E1000_SWFW_PHY1_SM    0x0004
-#define E1000_SWFW_MAC_CSR_SM 0x0008
-
-/* Receive Descriptor */
-#define E1000_RDT_DELAY 0x0000ffff	/* Delay timer (1=1024us) */
-#define E1000_RDT_FPDB  0x80000000	/* Flush descriptor block */
-#define E1000_RDLEN_LEN 0x0007ff80	/* descriptor length */
-#define E1000_RDH_RDH   0x0000ffff	/* receive descriptor head */
-#define E1000_RDT_RDT   0x0000ffff	/* receive descriptor tail */
-
-/* Flow Control */
-#define E1000_FCRTH_RTH  0x0000FFF8	/* Mask Bits[15:3] for RTH */
-#define E1000_FCRTH_XFCE 0x80000000	/* External Flow Control Enable */
-#define E1000_FCRTL_RTL  0x0000FFF8	/* Mask Bits[15:3] for RTL */
-#define E1000_FCRTL_XONE 0x80000000	/* Enable XON frame transmission */
-
-/* Header split receive */
-#define E1000_RFCTL_ISCSI_DIS           0x00000001
-#define E1000_RFCTL_ISCSI_DWC_MASK      0x0000003E
-#define E1000_RFCTL_ISCSI_DWC_SHIFT     1
-#define E1000_RFCTL_NFSW_DIS            0x00000040
-#define E1000_RFCTL_NFSR_DIS            0x00000080
-#define E1000_RFCTL_NFS_VER_MASK        0x00000300
-#define E1000_RFCTL_NFS_VER_SHIFT       8
-#define E1000_RFCTL_IPV6_DIS            0x00000400
-#define E1000_RFCTL_IPV6_XSUM_DIS       0x00000800
-#define E1000_RFCTL_ACK_DIS             0x00001000
-#define E1000_RFCTL_ACKD_DIS            0x00002000
-#define E1000_RFCTL_IPFRSP_DIS          0x00004000
-#define E1000_RFCTL_EXTEN               0x00008000
-#define E1000_RFCTL_IPV6_EX_DIS         0x00010000
-#define E1000_RFCTL_NEW_IPV6_EXT_DIS    0x00020000
-
-/* Receive Descriptor Control */
-#define E1000_RXDCTL_PTHRESH 0x0000003F	/* RXDCTL Prefetch Threshold */
-#define E1000_RXDCTL_HTHRESH 0x00003F00	/* RXDCTL Host Threshold */
-#define E1000_RXDCTL_WTHRESH 0x003F0000	/* RXDCTL Writeback Threshold */
-#define E1000_RXDCTL_GRAN    0x01000000	/* RXDCTL Granularity */
-
-/* Transmit Descriptor Control */
-#define E1000_TXDCTL_PTHRESH 0x0000003F	/* TXDCTL Prefetch Threshold */
-#define E1000_TXDCTL_HTHRESH 0x00003F00	/* TXDCTL Host Threshold */
-#define E1000_TXDCTL_WTHRESH 0x003F0000	/* TXDCTL Writeback Threshold */
-#define E1000_TXDCTL_GRAN    0x01000000	/* TXDCTL Granularity */
-#define E1000_TXDCTL_LWTHRESH 0xFE000000	/* TXDCTL Low Threshold */
-#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000	/* GRAN=1, WTHRESH=1 */
-#define E1000_TXDCTL_COUNT_DESC 0x00400000	/* Enable the counting of desc.
-						   still to be processed. */
-/* Transmit Configuration Word */
-#define E1000_TXCW_FD         0x00000020	/* TXCW full duplex */
-#define E1000_TXCW_HD         0x00000040	/* TXCW half duplex */
-#define E1000_TXCW_PAUSE      0x00000080	/* TXCW sym pause request */
-#define E1000_TXCW_ASM_DIR    0x00000100	/* TXCW astm pause direction */
-#define E1000_TXCW_PAUSE_MASK 0x00000180	/* TXCW pause request mask */
-#define E1000_TXCW_RF         0x00003000	/* TXCW remote fault */
-#define E1000_TXCW_NP         0x00008000	/* TXCW next page */
-#define E1000_TXCW_CW         0x0000ffff	/* TxConfigWord mask */
-#define E1000_TXCW_TXC        0x40000000	/* Transmit Config control */
-#define E1000_TXCW_ANE        0x80000000	/* Auto-neg enable */
-
-/* Receive Configuration Word */
-#define E1000_RXCW_CW    0x0000ffff	/* RxConfigWord mask */
-#define E1000_RXCW_NC    0x04000000	/* Receive config no carrier */
-#define E1000_RXCW_IV    0x08000000	/* Receive config invalid */
-#define E1000_RXCW_CC    0x10000000	/* Receive config change */
-#define E1000_RXCW_C     0x20000000	/* Receive config */
-#define E1000_RXCW_SYNCH 0x40000000	/* Receive config synch */
-#define E1000_RXCW_ANC   0x80000000	/* Auto-neg complete */
-
-/* Transmit Control */
-#define E1000_TCTL_RST    0x00000001	/* software reset */
-#define E1000_TCTL_EN     0x00000002	/* enable tx */
-#define E1000_TCTL_BCE    0x00000004	/* busy check enable */
-#define E1000_TCTL_PSP    0x00000008	/* pad short packets */
-#define E1000_TCTL_CT     0x00000ff0	/* collision threshold */
-#define E1000_TCTL_COLD   0x003ff000	/* collision distance */
-#define E1000_TCTL_SWXOFF 0x00400000	/* SW Xoff transmission */
-#define E1000_TCTL_PBE    0x00800000	/* Packet Burst Enable */
-#define E1000_TCTL_RTLC   0x01000000	/* Re-transmit on late collision */
-#define E1000_TCTL_NRTU   0x02000000	/* No Re-transmit on underrun */
-#define E1000_TCTL_MULR   0x10000000	/* Multiple request support */
-/* Extended Transmit Control */
-#define E1000_TCTL_EXT_BST_MASK  0x000003FF	/* Backoff Slot Time */
-#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00	/* Gigabit Carry Extend Padding */
-
-/* Receive Checksum Control */
-#define E1000_RXCSUM_PCSS_MASK 0x000000FF	/* Packet Checksum Start */
-#define E1000_RXCSUM_IPOFL     0x00000100	/* IPv4 checksum offload */
-#define E1000_RXCSUM_TUOFL     0x00000200	/* TCP / UDP checksum offload */
-#define E1000_RXCSUM_IPV6OFL   0x00000400	/* IPv6 checksum offload */
-#define E1000_RXCSUM_IPPCSE    0x00001000	/* IP payload checksum enable */
-#define E1000_RXCSUM_PCSD      0x00002000	/* packet checksum disabled */
-
-/* Multiple Receive Queue Control */
-#define E1000_MRQC_ENABLE_MASK              0x00000003
-#define E1000_MRQC_ENABLE_RSS_2Q            0x00000001
-#define E1000_MRQC_ENABLE_RSS_INT           0x00000004
-#define E1000_MRQC_RSS_FIELD_MASK           0xFFFF0000
-#define E1000_MRQC_RSS_FIELD_IPV4_TCP       0x00010000
-#define E1000_MRQC_RSS_FIELD_IPV4           0x00020000
-#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX    0x00040000
-#define E1000_MRQC_RSS_FIELD_IPV6_EX        0x00080000
-#define E1000_MRQC_RSS_FIELD_IPV6           0x00100000
-#define E1000_MRQC_RSS_FIELD_IPV6_TCP       0x00200000
-
-/* Definitions for power management and wakeup registers */
-/* Wake Up Control */
-#define E1000_WUC_APME       0x00000001	/* APM Enable */
-#define E1000_WUC_PME_EN     0x00000002	/* PME Enable */
-#define E1000_WUC_PME_STATUS 0x00000004	/* PME Status */
-#define E1000_WUC_APMPME     0x00000008	/* Assert PME on APM Wakeup */
-#define E1000_WUC_SPM        0x80000000	/* Enable SPM */
-
-/* Wake Up Filter Control */
-#define E1000_WUFC_LNKC 0x00000001	/* Link Status Change Wakeup Enable */
-#define E1000_WUFC_MAG  0x00000002	/* Magic Packet Wakeup Enable */
-#define E1000_WUFC_EX   0x00000004	/* Directed Exact Wakeup Enable */
-#define E1000_WUFC_MC   0x00000008	/* Directed Multicast Wakeup Enable */
-#define E1000_WUFC_BC   0x00000010	/* Broadcast Wakeup Enable */
-#define E1000_WUFC_ARP  0x00000020	/* ARP Request Packet Wakeup Enable */
-#define E1000_WUFC_IPV4 0x00000040	/* Directed IPv4 Packet Wakeup Enable */
-#define E1000_WUFC_IPV6 0x00000080	/* Directed IPv6 Packet Wakeup Enable */
-#define E1000_WUFC_IGNORE_TCO      0x00008000	/* Ignore WakeOn TCO packets */
-#define E1000_WUFC_FLX0 0x00010000	/* Flexible Filter 0 Enable */
-#define E1000_WUFC_FLX1 0x00020000	/* Flexible Filter 1 Enable */
-#define E1000_WUFC_FLX2 0x00040000	/* Flexible Filter 2 Enable */
-#define E1000_WUFC_FLX3 0x00080000	/* Flexible Filter 3 Enable */
-#define E1000_WUFC_ALL_FILTERS 0x000F00FF	/* Mask for all wakeup filters */
-#define E1000_WUFC_FLX_OFFSET 16	/* Offset to the Flexible Filters bits */
-#define E1000_WUFC_FLX_FILTERS 0x000F0000	/* Mask for the 4 flexible filters */
-
-/* Wake Up Status */
-#define E1000_WUS_LNKC 0x00000001	/* Link Status Changed */
-#define E1000_WUS_MAG  0x00000002	/* Magic Packet Received */
-#define E1000_WUS_EX   0x00000004	/* Directed Exact Received */
-#define E1000_WUS_MC   0x00000008	/* Directed Multicast Received */
-#define E1000_WUS_BC   0x00000010	/* Broadcast Received */
-#define E1000_WUS_ARP  0x00000020	/* ARP Request Packet Received */
-#define E1000_WUS_IPV4 0x00000040	/* Directed IPv4 Packet Wakeup Received */
-#define E1000_WUS_IPV6 0x00000080	/* Directed IPv6 Packet Wakeup Received */
-#define E1000_WUS_FLX0 0x00010000	/* Flexible Filter 0 Match */
-#define E1000_WUS_FLX1 0x00020000	/* Flexible Filter 1 Match */
-#define E1000_WUS_FLX2 0x00040000	/* Flexible Filter 2 Match */
-#define E1000_WUS_FLX3 0x00080000	/* Flexible Filter 3 Match */
-#define E1000_WUS_FLX_FILTERS 0x000F0000	/* Mask for the 4 flexible filters */
-
-/* Management Control */
-#define E1000_MANC_SMBUS_EN      0x00000001	/* SMBus Enabled - RO */
-#define E1000_MANC_ASF_EN        0x00000002	/* ASF Enabled - RO */
-#define E1000_MANC_R_ON_FORCE    0x00000004	/* Reset on Force TCO - RO */
-#define E1000_MANC_RMCP_EN       0x00000100	/* Enable RCMP 026Fh Filtering */
-#define E1000_MANC_0298_EN       0x00000200	/* Enable RCMP 0298h Filtering */
-#define E1000_MANC_IPV4_EN       0x00000400	/* Enable IPv4 */
-#define E1000_MANC_IPV6_EN       0x00000800	/* Enable IPv6 */
-#define E1000_MANC_SNAP_EN       0x00001000	/* Accept LLC/SNAP */
-#define E1000_MANC_ARP_EN        0x00002000	/* Enable ARP Request Filtering */
-#define E1000_MANC_NEIGHBOR_EN   0x00004000	/* Enable Neighbor Discovery
-						 * Filtering */
-#define E1000_MANC_ARP_RES_EN    0x00008000	/* Enable ARP response Filtering */
-#define E1000_MANC_TCO_RESET     0x00010000	/* TCO Reset Occurred */
-#define E1000_MANC_RCV_TCO_EN    0x00020000	/* Receive TCO Packets Enabled */
-#define E1000_MANC_REPORT_STATUS 0x00040000	/* Status Reporting Enabled */
-#define E1000_MANC_RCV_ALL       0x00080000	/* Receive All Enabled */
-#define E1000_MANC_BLK_PHY_RST_ON_IDE   0x00040000	/* Block phy resets */
-#define E1000_MANC_EN_MAC_ADDR_FILTER   0x00100000	/* Enable MAC address
-							 * filtering */
-#define E1000_MANC_EN_MNG2HOST   0x00200000	/* Enable MNG packets to host
-						 * memory */
-#define E1000_MANC_EN_IP_ADDR_FILTER    0x00400000	/* Enable IP address
-							 * filtering */
-#define E1000_MANC_EN_XSUM_FILTER   0x00800000	/* Enable checksum filtering */
-#define E1000_MANC_BR_EN         0x01000000	/* Enable broadcast filtering */
-#define E1000_MANC_SMB_REQ       0x01000000	/* SMBus Request */
-#define E1000_MANC_SMB_GNT       0x02000000	/* SMBus Grant */
-#define E1000_MANC_SMB_CLK_IN    0x04000000	/* SMBus Clock In */
-#define E1000_MANC_SMB_DATA_IN   0x08000000	/* SMBus Data In */
-#define E1000_MANC_SMB_DATA_OUT  0x10000000	/* SMBus Data Out */
-#define E1000_MANC_SMB_CLK_OUT   0x20000000	/* SMBus Clock Out */
-
-#define E1000_MANC_SMB_DATA_OUT_SHIFT  28	/* SMBus Data Out Shift */
-#define E1000_MANC_SMB_CLK_OUT_SHIFT   29	/* SMBus Clock Out Shift */
-
-/* SW Semaphore Register */
-#define E1000_SWSM_SMBI         0x00000001	/* Driver Semaphore bit */
-#define E1000_SWSM_SWESMBI      0x00000002	/* FW Semaphore bit */
-#define E1000_SWSM_WMNG         0x00000004	/* Wake MNG Clock */
-#define E1000_SWSM_DRV_LOAD     0x00000008	/* Driver Loaded Bit */
-
-/* FW Semaphore Register */
-#define E1000_FWSM_MODE_MASK    0x0000000E	/* FW mode */
-#define E1000_FWSM_MODE_SHIFT            1
-#define E1000_FWSM_FW_VALID     0x00008000	/* FW established a valid mode */
-
-#define E1000_FWSM_RSPCIPHY        0x00000040	/* Reset PHY on PCI reset */
-#define E1000_FWSM_DISSW           0x10000000	/* FW disable SW Write Access */
-#define E1000_FWSM_SKUSEL_MASK     0x60000000	/* LAN SKU select */
-#define E1000_FWSM_SKUEL_SHIFT     29
-#define E1000_FWSM_SKUSEL_EMB      0x0	/* Embedded SKU */
-#define E1000_FWSM_SKUSEL_CONS     0x1	/* Consumer SKU */
-#define E1000_FWSM_SKUSEL_PERF_100 0x2	/* Perf & Corp 10/100 SKU */
-#define E1000_FWSM_SKUSEL_PERF_GBE 0x3	/* Perf & Copr GbE SKU */
-
-/* FFLT Debug Register */
-#define E1000_FFLT_DBG_INVC     0x00100000	/* Invalid /C/ code handling */
-
-typedef enum {
-	e1000_mng_mode_none = 0,
-	e1000_mng_mode_asf,
-	e1000_mng_mode_pt,
-	e1000_mng_mode_ipmi,
-	e1000_mng_mode_host_interface_only
-} e1000_mng_mode;
-
-/* Host Interface Control Register */
-#define E1000_HICR_EN           0x00000001	/* Enable Bit - RO */
-#define E1000_HICR_C            0x00000002	/* Driver sets this bit when done
-						 * to put command in RAM */
-#define E1000_HICR_SV           0x00000004	/* Status Validity */
-#define E1000_HICR_FWR          0x00000080	/* FW reset. Set by the Host */
-
-/* Host Interface Command Interface - Address range 0x8800-0x8EFF */
-#define E1000_HI_MAX_DATA_LENGTH         252	/* Host Interface data length */
-#define E1000_HI_MAX_BLOCK_BYTE_LENGTH  1792	/* Number of bytes in range */
-#define E1000_HI_MAX_BLOCK_DWORD_LENGTH  448	/* Number of dwords in range */
-#define E1000_HI_COMMAND_TIMEOUT         500	/* Time in ms to process HI command */
-
-struct e1000_host_command_header {
-	u8 command_id;
-	u8 command_length;
-	u8 command_options;	/* I/F bits for command, status for return */
-	u8 checksum;
-};
-struct e1000_host_command_info {
-	struct e1000_host_command_header command_header;	/* Command Head/Command Result Head has 4 bytes */
-	u8 command_data[E1000_HI_MAX_DATA_LENGTH];	/* Command data can length 0..252 */
-};
-
-/* Host SMB register #0 */
-#define E1000_HSMC0R_CLKIN      0x00000001	/* SMB Clock in */
-#define E1000_HSMC0R_DATAIN     0x00000002	/* SMB Data in */
-#define E1000_HSMC0R_DATAOUT    0x00000004	/* SMB Data out */
-#define E1000_HSMC0R_CLKOUT     0x00000008	/* SMB Clock out */
-
-/* Host SMB register #1 */
-#define E1000_HSMC1R_CLKIN      E1000_HSMC0R_CLKIN
-#define E1000_HSMC1R_DATAIN     E1000_HSMC0R_DATAIN
-#define E1000_HSMC1R_DATAOUT    E1000_HSMC0R_DATAOUT
-#define E1000_HSMC1R_CLKOUT     E1000_HSMC0R_CLKOUT
-
-/* FW Status Register */
-#define E1000_FWSTS_FWS_MASK    0x000000FF	/* FW Status */
-
-/* Wake Up Packet Length */
-#define E1000_WUPL_LENGTH_MASK 0x0FFF	/* Only the lower 12 bits are valid */
-
-#define E1000_MDALIGN          4096
-
-/* PCI-Ex registers*/
-
-/* PCI-Ex Control Register */
-#define E1000_GCR_RXD_NO_SNOOP          0x00000001
-#define E1000_GCR_RXDSCW_NO_SNOOP       0x00000002
-#define E1000_GCR_RXDSCR_NO_SNOOP       0x00000004
-#define E1000_GCR_TXD_NO_SNOOP          0x00000008
-#define E1000_GCR_TXDSCW_NO_SNOOP       0x00000010
-#define E1000_GCR_TXDSCR_NO_SNOOP       0x00000020
-
-#define PCI_EX_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP         | \
-                             E1000_GCR_RXDSCW_NO_SNOOP      | \
-                             E1000_GCR_RXDSCR_NO_SNOOP      | \
-                             E1000_GCR_TXD_NO_SNOOP         | \
-                             E1000_GCR_TXDSCW_NO_SNOOP      | \
-                             E1000_GCR_TXDSCR_NO_SNOOP)
-
-#define PCI_EX_82566_SNOOP_ALL PCI_EX_NO_SNOOP_ALL
-
-#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
-/* Function Active and Power State to MNG */
-#define E1000_FACTPS_FUNC0_POWER_STATE_MASK         0x00000003
-#define E1000_FACTPS_LAN0_VALID                     0x00000004
-#define E1000_FACTPS_FUNC0_AUX_EN                   0x00000008
-#define E1000_FACTPS_FUNC1_POWER_STATE_MASK         0x000000C0
-#define E1000_FACTPS_FUNC1_POWER_STATE_SHIFT        6
-#define E1000_FACTPS_LAN1_VALID                     0x00000100
-#define E1000_FACTPS_FUNC1_AUX_EN                   0x00000200
-#define E1000_FACTPS_FUNC2_POWER_STATE_MASK         0x00003000
-#define E1000_FACTPS_FUNC2_POWER_STATE_SHIFT        12
-#define E1000_FACTPS_IDE_ENABLE                     0x00004000
-#define E1000_FACTPS_FUNC2_AUX_EN                   0x00008000
-#define E1000_FACTPS_FUNC3_POWER_STATE_MASK         0x000C0000
-#define E1000_FACTPS_FUNC3_POWER_STATE_SHIFT        18
-#define E1000_FACTPS_SP_ENABLE                      0x00100000
-#define E1000_FACTPS_FUNC3_AUX_EN                   0x00200000
-#define E1000_FACTPS_FUNC4_POWER_STATE_MASK         0x03000000
-#define E1000_FACTPS_FUNC4_POWER_STATE_SHIFT        24
-#define E1000_FACTPS_IPMI_ENABLE                    0x04000000
-#define E1000_FACTPS_FUNC4_AUX_EN                   0x08000000
-#define E1000_FACTPS_MNGCG                          0x20000000
-#define E1000_FACTPS_LAN_FUNC_SEL                   0x40000000
-#define E1000_FACTPS_PM_STATE_CHANGED               0x80000000
-
-/* PCI-Ex Config Space */
-#define PCI_EX_LINK_STATUS           0x12
-#define PCI_EX_LINK_WIDTH_MASK       0x3F0
-#define PCI_EX_LINK_WIDTH_SHIFT      4
-
-/* EEPROM Commands - Microwire */
-#define EEPROM_READ_OPCODE_MICROWIRE  0x6	/* EEPROM read opcode */
-#define EEPROM_WRITE_OPCODE_MICROWIRE 0x5	/* EEPROM write opcode */
-#define EEPROM_ERASE_OPCODE_MICROWIRE 0x7	/* EEPROM erase opcode */
-#define EEPROM_EWEN_OPCODE_MICROWIRE  0x13	/* EEPROM erase/write enable */
-#define EEPROM_EWDS_OPCODE_MICROWIRE  0x10	/* EEPROM erase/write disable */
-
-/* EEPROM Commands - SPI */
-#define EEPROM_MAX_RETRY_SPI        5000	/* Max wait of 5ms, for RDY signal */
-#define EEPROM_READ_OPCODE_SPI      0x03	/* EEPROM read opcode */
-#define EEPROM_WRITE_OPCODE_SPI     0x02	/* EEPROM write opcode */
-#define EEPROM_A8_OPCODE_SPI        0x08	/* opcode bit-3 = address bit-8 */
-#define EEPROM_WREN_OPCODE_SPI      0x06	/* EEPROM set Write Enable latch */
-#define EEPROM_WRDI_OPCODE_SPI      0x04	/* EEPROM reset Write Enable latch */
-#define EEPROM_RDSR_OPCODE_SPI      0x05	/* EEPROM read Status register */
-#define EEPROM_WRSR_OPCODE_SPI      0x01	/* EEPROM write Status register */
-#define EEPROM_ERASE4K_OPCODE_SPI   0x20	/* EEPROM ERASE 4KB */
-#define EEPROM_ERASE64K_OPCODE_SPI  0xD8	/* EEPROM ERASE 64KB */
-#define EEPROM_ERASE256_OPCODE_SPI  0xDB	/* EEPROM ERASE 256B */
-
-/* EEPROM Size definitions */
-#define EEPROM_WORD_SIZE_SHIFT  6
-#define EEPROM_SIZE_SHIFT       10
-#define EEPROM_SIZE_MASK        0x1C00
-
-/* EEPROM Word Offsets */
-#define EEPROM_COMPAT                 0x0003
-#define EEPROM_ID_LED_SETTINGS        0x0004
-#define EEPROM_VERSION                0x0005
-#define EEPROM_SERDES_AMPLITUDE       0x0006	/* For SERDES output amplitude adjustment. */
-#define EEPROM_PHY_CLASS_WORD         0x0007
-#define EEPROM_INIT_CONTROL1_REG      0x000A
-#define EEPROM_INIT_CONTROL2_REG      0x000F
-#define EEPROM_SWDEF_PINS_CTRL_PORT_1 0x0010
-#define EEPROM_INIT_CONTROL3_PORT_B   0x0014
-#define EEPROM_INIT_3GIO_3            0x001A
-#define EEPROM_SWDEF_PINS_CTRL_PORT_0 0x0020
-#define EEPROM_INIT_CONTROL3_PORT_A   0x0024
-#define EEPROM_CFG                    0x0012
-#define EEPROM_FLASH_VERSION          0x0032
-#define EEPROM_CHECKSUM_REG           0x003F
-
-#define E1000_EEPROM_CFG_DONE         0x00040000	/* MNG config cycle done */
-#define E1000_EEPROM_CFG_DONE_PORT_1  0x00080000	/* ...for second port */
-
-/* Word definitions for ID LED Settings */
-#define ID_LED_RESERVED_0000 0x0000
-#define ID_LED_RESERVED_FFFF 0xFFFF
-#define ID_LED_DEFAULT       ((ID_LED_OFF1_ON2 << 12) | \
-                              (ID_LED_OFF1_OFF2 << 8) | \
-                              (ID_LED_DEF1_DEF2 << 4) | \
-                              (ID_LED_DEF1_DEF2))
-#define ID_LED_DEF1_DEF2     0x1
-#define ID_LED_DEF1_ON2      0x2
-#define ID_LED_DEF1_OFF2     0x3
-#define ID_LED_ON1_DEF2      0x4
-#define ID_LED_ON1_ON2       0x5
-#define ID_LED_ON1_OFF2      0x6
-#define ID_LED_OFF1_DEF2     0x7
-#define ID_LED_OFF1_ON2      0x8
-#define ID_LED_OFF1_OFF2     0x9
-
-#define IGP_ACTIVITY_LED_MASK   0xFFFFF0FF
-#define IGP_ACTIVITY_LED_ENABLE 0x0300
-#define IGP_LED3_MODE           0x07000000
-
-/* Mask bits for SERDES amplitude adjustment in Word 6 of the EEPROM */
-#define EEPROM_SERDES_AMPLITUDE_MASK  0x000F
-
-/* Mask bit for PHY class in Word 7 of the EEPROM */
-#define EEPROM_PHY_CLASS_A   0x8000
-
-/* Mask bits for fields in Word 0x0a of the EEPROM */
-#define EEPROM_WORD0A_ILOS   0x0010
-#define EEPROM_WORD0A_SWDPIO 0x01E0
-#define EEPROM_WORD0A_LRST   0x0200
-#define EEPROM_WORD0A_FD     0x0400
-#define EEPROM_WORD0A_66MHZ  0x0800
-
-/* Mask bits for fields in Word 0x0f of the EEPROM */
-#define EEPROM_WORD0F_PAUSE_MASK 0x3000
-#define EEPROM_WORD0F_PAUSE      0x1000
-#define EEPROM_WORD0F_ASM_DIR    0x2000
-#define EEPROM_WORD0F_ANE        0x0800
-#define EEPROM_WORD0F_SWPDIO_EXT 0x00F0
-#define EEPROM_WORD0F_LPLU       0x0001
-
-/* Mask bits for fields in Word 0x10/0x20 of the EEPROM */
-#define EEPROM_WORD1020_GIGA_DISABLE         0x0010
-#define EEPROM_WORD1020_GIGA_DISABLE_NON_D0A 0x0008
-
-/* Mask bits for fields in Word 0x1a of the EEPROM */
-#define EEPROM_WORD1A_ASPM_MASK  0x000C
-
-/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */
-#define EEPROM_SUM 0xBABA
-
-/* EEPROM Map defines (WORD OFFSETS)*/
-#define EEPROM_NODE_ADDRESS_BYTE_0 0
-#define EEPROM_PBA_BYTE_1          8
-
-#define EEPROM_RESERVED_WORD          0xFFFF
-
-/* EEPROM Map Sizes (Byte Counts) */
-#define PBA_SIZE 4
-
-/* Collision related configuration parameters */
-#define E1000_COLLISION_THRESHOLD       15
-#define E1000_CT_SHIFT                  4
-/* Collision distance is a 0-based value that applies to
- * half-duplex-capable hardware only. */
-#define E1000_COLLISION_DISTANCE        63
-#define E1000_COLLISION_DISTANCE_82542  64
-#define E1000_FDX_COLLISION_DISTANCE    E1000_COLLISION_DISTANCE
-#define E1000_HDX_COLLISION_DISTANCE    E1000_COLLISION_DISTANCE
-#define E1000_COLD_SHIFT                12
-
-/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
-#define REQ_TX_DESCRIPTOR_MULTIPLE  8
-#define REQ_RX_DESCRIPTOR_MULTIPLE  8
-
-/* Default values for the transmit IPG register */
-#define DEFAULT_82542_TIPG_IPGT        10
-#define DEFAULT_82543_TIPG_IPGT_FIBER  9
-#define DEFAULT_82543_TIPG_IPGT_COPPER 8
-
-#define E1000_TIPG_IPGT_MASK  0x000003FF
-#define E1000_TIPG_IPGR1_MASK 0x000FFC00
-#define E1000_TIPG_IPGR2_MASK 0x3FF00000
-
-#define DEFAULT_82542_TIPG_IPGR1 2
-#define DEFAULT_82543_TIPG_IPGR1 8
-#define E1000_TIPG_IPGR1_SHIFT  10
-
-#define DEFAULT_82542_TIPG_IPGR2 10
-#define DEFAULT_82543_TIPG_IPGR2 6
-#define E1000_TIPG_IPGR2_SHIFT  20
-
-#define E1000_TXDMAC_DPP 0x00000001
-
-/* Adaptive IFS defines */
-#define TX_THRESHOLD_START     8
-#define TX_THRESHOLD_INCREMENT 10
-#define TX_THRESHOLD_DECREMENT 1
-#define TX_THRESHOLD_STOP      190
-#define TX_THRESHOLD_DISABLE   0
-#define TX_THRESHOLD_TIMER_MS  10000
-#define MIN_NUM_XMITS          1000
-#define IFS_MAX                80
-#define IFS_STEP               10
-#define IFS_MIN                40
-#define IFS_RATIO              4
-
-/* Extended Configuration Control and Size */
-#define E1000_EXTCNF_CTRL_PCIE_WRITE_ENABLE 0x00000001
-#define E1000_EXTCNF_CTRL_PHY_WRITE_ENABLE  0x00000002
-#define E1000_EXTCNF_CTRL_D_UD_ENABLE       0x00000004
-#define E1000_EXTCNF_CTRL_D_UD_LATENCY      0x00000008
-#define E1000_EXTCNF_CTRL_D_UD_OWNER        0x00000010
-#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020
-#define E1000_EXTCNF_CTRL_MDIO_HW_OWNERSHIP 0x00000040
-#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER   0x0FFF0000
-
-#define E1000_EXTCNF_SIZE_EXT_PHY_LENGTH    0x000000FF
-#define E1000_EXTCNF_SIZE_EXT_DOCK_LENGTH   0x0000FF00
-#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH   0x00FF0000
-#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE  0x00000001
-#define E1000_EXTCNF_CTRL_SWFLAG            0x00000020
-
-/* PBA constants */
-#define E1000_PBA_8K 0x0008	/* 8KB, default Rx allocation */
-#define E1000_PBA_12K 0x000C	/* 12KB, default Rx allocation */
-#define E1000_PBA_16K 0x0010	/* 16KB, default TX allocation */
-#define E1000_PBA_20K 0x0014
-#define E1000_PBA_22K 0x0016
-#define E1000_PBA_24K 0x0018
-#define E1000_PBA_30K 0x001E
-#define E1000_PBA_32K 0x0020
-#define E1000_PBA_34K 0x0022
-#define E1000_PBA_38K 0x0026
-#define E1000_PBA_40K 0x0028
-#define E1000_PBA_48K 0x0030	/* 48KB, default RX allocation */
-
-#define E1000_PBS_16K E1000_PBA_16K
-
-/* Flow Control Constants */
-#define FLOW_CONTROL_ADDRESS_LOW  0x00C28001
-#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
-#define FLOW_CONTROL_TYPE         0x8808
-
-/* The historical defaults for the flow control values are given below. */
-#define FC_DEFAULT_HI_THRESH        (0x8000)	/* 32KB */
-#define FC_DEFAULT_LO_THRESH        (0x4000)	/* 16KB */
-#define FC_DEFAULT_TX_TIMER         (0x100)	/* ~130 us */
-
-/* PCIX Config space */
-#define PCIX_COMMAND_REGISTER    0xE6
-#define PCIX_STATUS_REGISTER_LO  0xE8
-#define PCIX_STATUS_REGISTER_HI  0xEA
-
-#define PCIX_COMMAND_MMRBC_MASK      0x000C
-#define PCIX_COMMAND_MMRBC_SHIFT     0x2
-#define PCIX_STATUS_HI_MMRBC_MASK    0x0060
-#define PCIX_STATUS_HI_MMRBC_SHIFT   0x5
-#define PCIX_STATUS_HI_MMRBC_4K      0x3
-#define PCIX_STATUS_HI_MMRBC_2K      0x2
-
-/* Number of bits required to shift right the "pause" bits from the
- * EEPROM (bits 13:12) to the "pause" (bits 8:7) field in the TXCW register.
- */
-#define PAUSE_SHIFT 5
-
-/* Number of bits required to shift left the "SWDPIO" bits from the
- * EEPROM (bits 8:5) to the "SWDPIO" (bits 25:22) field in the CTRL register.
- */
-#define SWDPIO_SHIFT 17
-
-/* Number of bits required to shift left the "SWDPIO_EXT" bits from the
- * EEPROM word F (bits 7:4) to the bits 11:8 of The Extended CTRL register.
- */
-#define SWDPIO__EXT_SHIFT 4
-
-/* Number of bits required to shift left the "ILOS" bit from the EEPROM
- * (bit 4) to the "ILOS" (bit 7) field in the CTRL register.
- */
-#define ILOS_SHIFT  3
-
-#define RECEIVE_BUFFER_ALIGN_SIZE  (256)
-
-/* Number of milliseconds we wait for auto-negotiation to complete */
-#define LINK_UP_TIMEOUT             500
-
-/* Number of milliseconds we wait for Eeprom auto read bit done after MAC reset */
-#define AUTO_READ_DONE_TIMEOUT      10
-/* Number of milliseconds we wait for PHY configuration done after MAC reset */
-#define PHY_CFG_TIMEOUT             100
-
-#define E1000_TX_BUFFER_SIZE ((u32)1514)
-
-/* The carrier extension symbol, as received by the NIC. */
-#define CARRIER_EXTENSION   0x0F
-
-/* TBI_ACCEPT macro definition:
- *
- * This macro requires:
- *      adapter = a pointer to struct e1000_hw
- *      status = the 8 bit status field of the RX descriptor with EOP set
- *      error = the 8 bit error field of the RX descriptor with EOP set
- *      length = the sum of all the length fields of the RX descriptors that
- *               make up the current frame
- *      last_byte = the last byte of the frame DMAed by the hardware
- *      max_frame_length = the maximum frame length we want to accept.
- *      min_frame_length = the minimum frame length we want to accept.
- *
- * This macro is a conditional that should be used in the interrupt
- * handler's Rx processing routine when RxErrors have been detected.
- *
- * Typical use:
- *  ...
- *  if (TBI_ACCEPT) {
- *      accept_frame = true;
- *      e1000_tbi_adjust_stats(adapter, MacAddress);
- *      frame_length--;
- *  } else {
- *      accept_frame = false;
- *  }
- *  ...
- */
-
-#define TBI_ACCEPT(adapter, status, errors, length, last_byte) \
-    ((adapter)->tbi_compatibility_on && \
-     (((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \
-     ((last_byte) == CARRIER_EXTENSION) && \
-     (((status) & E1000_RXD_STAT_VP) ? \
-          (((length) > ((adapter)->min_frame_size - VLAN_TAG_SIZE)) && \
-           ((length) <= ((adapter)->max_frame_size + 1))) : \
-          (((length) > (adapter)->min_frame_size) && \
-           ((length) <= ((adapter)->max_frame_size + VLAN_TAG_SIZE + 1)))))
-
-/* Structures, enums, and macros for the PHY */
-
-/* Bit definitions for the Management Data IO (MDIO) and Management Data
- * Clock (MDC) pins in the Device Control Register.
- */
-#define E1000_CTRL_PHY_RESET_DIR  E1000_CTRL_SWDPIO0
-#define E1000_CTRL_PHY_RESET      E1000_CTRL_SWDPIN0
-#define E1000_CTRL_MDIO_DIR       E1000_CTRL_SWDPIO2
-#define E1000_CTRL_MDIO           E1000_CTRL_SWDPIN2
-#define E1000_CTRL_MDC_DIR        E1000_CTRL_SWDPIO3
-#define E1000_CTRL_MDC            E1000_CTRL_SWDPIN3
-#define E1000_CTRL_PHY_RESET_DIR4 E1000_CTRL_EXT_SDP4_DIR
-#define E1000_CTRL_PHY_RESET4     E1000_CTRL_EXT_SDP4_DATA
-
-/* PHY 1000 MII Register/Bit Definitions */
-/* PHY Registers defined by IEEE */
-#define PHY_CTRL         0x00	/* Control Register */
-#define PHY_STATUS       0x01	/* Status Register */
-#define PHY_ID1          0x02	/* Phy Id Reg (word 1) */
-#define PHY_ID2          0x03	/* Phy Id Reg (word 2) */
-#define PHY_AUTONEG_ADV  0x04	/* Autoneg Advertisement */
-#define PHY_LP_ABILITY   0x05	/* Link Partner Ability (Base Page) */
-#define PHY_AUTONEG_EXP  0x06	/* Autoneg Expansion Reg */
-#define PHY_NEXT_PAGE_TX 0x07	/* Next Page TX */
-#define PHY_LP_NEXT_PAGE 0x08	/* Link Partner Next Page */
-#define PHY_1000T_CTRL   0x09	/* 1000Base-T Control Reg */
-#define PHY_1000T_STATUS 0x0A	/* 1000Base-T Status Reg */
-#define PHY_EXT_STATUS   0x0F	/* Extended Status Reg */
-
-#define MAX_PHY_REG_ADDRESS        0x1F	/* 5 bit address bus (0-0x1F) */
-#define MAX_PHY_MULTI_PAGE_REG     0xF	/* Registers equal on all pages */
-
-/* M88E1000 Specific Registers */
-#define M88E1000_PHY_SPEC_CTRL     0x10	/* PHY Specific Control Register */
-#define M88E1000_PHY_SPEC_STATUS   0x11	/* PHY Specific Status Register */
-#define M88E1000_INT_ENABLE        0x12	/* Interrupt Enable Register */
-#define M88E1000_INT_STATUS        0x13	/* Interrupt Status Register */
-#define M88E1000_EXT_PHY_SPEC_CTRL 0x14	/* Extended PHY Specific Control */
-#define M88E1000_RX_ERR_CNTR       0x15	/* Receive Error Counter */
-
-#define M88E1000_PHY_EXT_CTRL      0x1A	/* PHY extend control register */
-#define M88E1000_PHY_PAGE_SELECT   0x1D	/* Reg 29 for page number setting */
-#define M88E1000_PHY_GEN_CONTROL   0x1E	/* Its meaning depends on reg 29 */
-#define M88E1000_PHY_VCO_REG_BIT8  0x100	/* Bits 8 & 11 are adjusted for */
-#define M88E1000_PHY_VCO_REG_BIT11 0x800	/* improved BER performance */
-
-#define IGP01E1000_IEEE_REGS_PAGE  0x0000
-#define IGP01E1000_IEEE_RESTART_AUTONEG 0x3300
-#define IGP01E1000_IEEE_FORCE_GIGA      0x0140
-
-/* IGP01E1000 Specific Registers */
-#define IGP01E1000_PHY_PORT_CONFIG 0x10	/* PHY Specific Port Config Register */
-#define IGP01E1000_PHY_PORT_STATUS 0x11	/* PHY Specific Status Register */
-#define IGP01E1000_PHY_PORT_CTRL   0x12	/* PHY Specific Control Register */
-#define IGP01E1000_PHY_LINK_HEALTH 0x13	/* PHY Link Health Register */
-#define IGP01E1000_GMII_FIFO       0x14	/* GMII FIFO Register */
-#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15	/* PHY Channel Quality Register */
-#define IGP02E1000_PHY_POWER_MGMT      0x19
-#define IGP01E1000_PHY_PAGE_SELECT     0x1F	/* PHY Page Select Core Register */
-
-/* IGP01E1000 AGC Registers - stores the cable length values*/
-#define IGP01E1000_PHY_AGC_A        0x1172
-#define IGP01E1000_PHY_AGC_B        0x1272
-#define IGP01E1000_PHY_AGC_C        0x1472
-#define IGP01E1000_PHY_AGC_D        0x1872
-
-/* IGP02E1000 AGC Registers for cable length values */
-#define IGP02E1000_PHY_AGC_A        0x11B1
-#define IGP02E1000_PHY_AGC_B        0x12B1
-#define IGP02E1000_PHY_AGC_C        0x14B1
-#define IGP02E1000_PHY_AGC_D        0x18B1
-
-/* IGP01E1000 DSP Reset Register */
-#define IGP01E1000_PHY_DSP_RESET   0x1F33
-#define IGP01E1000_PHY_DSP_SET     0x1F71
-#define IGP01E1000_PHY_DSP_FFE     0x1F35
-
-#define IGP01E1000_PHY_CHANNEL_NUM    4
-#define IGP02E1000_PHY_CHANNEL_NUM    4
-
-#define IGP01E1000_PHY_AGC_PARAM_A    0x1171
-#define IGP01E1000_PHY_AGC_PARAM_B    0x1271
-#define IGP01E1000_PHY_AGC_PARAM_C    0x1471
-#define IGP01E1000_PHY_AGC_PARAM_D    0x1871
-
-#define IGP01E1000_PHY_EDAC_MU_INDEX        0xC000
-#define IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS 0x8000
-
-#define IGP01E1000_PHY_ANALOG_TX_STATE      0x2890
-#define IGP01E1000_PHY_ANALOG_CLASS_A       0x2000
-#define IGP01E1000_PHY_FORCE_ANALOG_ENABLE  0x0004
-#define IGP01E1000_PHY_DSP_FFE_CM_CP        0x0069
-
-#define IGP01E1000_PHY_DSP_FFE_DEFAULT      0x002A
-/* IGP01E1000 PCS Initialization register - stores the polarity status when
- * speed = 1000 Mbps. */
-#define IGP01E1000_PHY_PCS_INIT_REG  0x00B4
-#define IGP01E1000_PHY_PCS_CTRL_REG  0x00B5
-
-#define IGP01E1000_ANALOG_REGS_PAGE  0x20C0
-
-/* 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 */
-
-/* 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 */
-
-/* Autoneg Advertisement Register */
-#define NWAY_AR_SELECTOR_FIELD 0x0001	/* indicates IEEE 802.3 CSMA/CD */
-#define NWAY_AR_10T_HD_CAPS    0x0020	/* 10T   Half Duplex Capable */
-#define NWAY_AR_10T_FD_CAPS    0x0040	/* 10T   Full Duplex Capable */
-#define NWAY_AR_100TX_HD_CAPS  0x0080	/* 100TX Half Duplex Capable */
-#define NWAY_AR_100TX_FD_CAPS  0x0100	/* 100TX Full Duplex Capable */
-#define NWAY_AR_100T4_CAPS     0x0200	/* 100T4 Capable */
-#define NWAY_AR_PAUSE          0x0400	/* Pause operation desired */
-#define NWAY_AR_ASM_DIR        0x0800	/* Asymmetric Pause Direction bit */
-#define NWAY_AR_REMOTE_FAULT   0x2000	/* Remote Fault detected */
-#define NWAY_AR_NEXT_PAGE      0x8000	/* Next Page ability supported */
-
-/* Link Partner Ability Register (Base Page) */
-#define NWAY_LPAR_SELECTOR_FIELD 0x0000	/* LP protocol selector field */
-#define NWAY_LPAR_10T_HD_CAPS    0x0020	/* LP is 10T   Half Duplex Capable */
-#define NWAY_LPAR_10T_FD_CAPS    0x0040	/* LP is 10T   Full Duplex Capable */
-#define NWAY_LPAR_100TX_HD_CAPS  0x0080	/* LP is 100TX Half Duplex Capable */
-#define NWAY_LPAR_100TX_FD_CAPS  0x0100	/* LP is 100TX Full Duplex Capable */
-#define NWAY_LPAR_100T4_CAPS     0x0200	/* LP is 100T4 Capable */
-#define NWAY_LPAR_PAUSE          0x0400	/* LP Pause operation desired */
-#define NWAY_LPAR_ASM_DIR        0x0800	/* LP Asymmetric Pause Direction bit */
-#define NWAY_LPAR_REMOTE_FAULT   0x2000	/* LP has detected Remote Fault */
-#define NWAY_LPAR_ACKNOWLEDGE    0x4000	/* LP has rx'd link code word */
-#define NWAY_LPAR_NEXT_PAGE      0x8000	/* Next Page ability supported */
-
-/* Autoneg Expansion Register */
-#define NWAY_ER_LP_NWAY_CAPS      0x0001	/* LP has Auto Neg Capability */
-#define NWAY_ER_PAGE_RXD          0x0002	/* LP is 10T   Half Duplex Capable */
-#define NWAY_ER_NEXT_PAGE_CAPS    0x0004	/* LP is 10T   Full Duplex Capable */
-#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008	/* LP is 100TX Half Duplex Capable */
-#define NWAY_ER_PAR_DETECT_FAULT  0x0010	/* LP is 100TX Full Duplex Capable */
-
-/* Next Page TX Register */
-#define NPTX_MSG_CODE_FIELD 0x0001	/* NP msg code or unformatted data */
-#define NPTX_TOGGLE         0x0800	/* Toggles between exchanges
-					 * of different NP
-					 */
-#define NPTX_ACKNOWLDGE2    0x1000	/* 1 = will comply with msg
-					 * 0 = cannot comply with msg
-					 */
-#define NPTX_MSG_PAGE       0x2000	/* formatted(1)/unformatted(0) pg */
-#define NPTX_NEXT_PAGE      0x8000	/* 1 = addition NP will follow
-					 * 0 = sending last NP
-					 */
-
-/* Link Partner Next Page Register */
-#define LP_RNPR_MSG_CODE_FIELD 0x0001	/* NP msg code or unformatted data */
-#define LP_RNPR_TOGGLE         0x0800	/* Toggles between exchanges
-					 * of different NP
-					 */
-#define LP_RNPR_ACKNOWLDGE2    0x1000	/* 1 = will comply with msg
-					 * 0 = cannot comply with msg
-					 */
-#define LP_RNPR_MSG_PAGE       0x2000	/* formatted(1)/unformatted(0) pg */
-#define LP_RNPR_ACKNOWLDGE     0x4000	/* 1 = ACK / 0 = NO ACK */
-#define LP_RNPR_NEXT_PAGE      0x8000	/* 1 = addition NP will follow
-					 * 0 = sending last NP
-					 */
-
-/* 1000BASE-T Control Register */
-#define CR_1000T_ASYM_PAUSE      0x0080	/* Advertise asymmetric pause bit */
-#define CR_1000T_HD_CAPS         0x0100	/* Advertise 1000T HD capability */
-#define CR_1000T_FD_CAPS         0x0200	/* Advertise 1000T FD capability  */
-#define CR_1000T_REPEATER_DTE    0x0400	/* 1=Repeater/switch device port */
-					/* 0=DTE device */
-#define CR_1000T_MS_VALUE        0x0800	/* 1=Configure PHY as Master */
-					/* 0=Configure PHY as Slave */
-#define CR_1000T_MS_ENABLE       0x1000	/* 1=Master/Slave manual config value */
-					/* 0=Automatic Master/Slave config */
-#define CR_1000T_TEST_MODE_NORMAL 0x0000	/* Normal Operation */
-#define CR_1000T_TEST_MODE_1     0x2000	/* Transmit Waveform test */
-#define CR_1000T_TEST_MODE_2     0x4000	/* Master Transmit Jitter test */
-#define CR_1000T_TEST_MODE_3     0x6000	/* Slave Transmit Jitter test */
-#define CR_1000T_TEST_MODE_4     0x8000	/* Transmitter Distortion test */
-
-/* 1000BASE-T Status Register */
-#define SR_1000T_IDLE_ERROR_CNT   0x00FF	/* Num idle errors since last read */
-#define SR_1000T_ASYM_PAUSE_DIR   0x0100	/* LP asymmetric pause direction bit */
-#define SR_1000T_LP_HD_CAPS       0x0400	/* LP is 1000T HD capable */
-#define SR_1000T_LP_FD_CAPS       0x0800	/* LP is 1000T FD capable */
-#define SR_1000T_REMOTE_RX_STATUS 0x1000	/* Remote receiver OK */
-#define SR_1000T_LOCAL_RX_STATUS  0x2000	/* Local receiver OK */
-#define SR_1000T_MS_CONFIG_RES    0x4000	/* 1=Local TX is Master, 0=Slave */
-#define SR_1000T_MS_CONFIG_FAULT  0x8000	/* Master/Slave config fault */
-#define SR_1000T_REMOTE_RX_STATUS_SHIFT          12
-#define SR_1000T_LOCAL_RX_STATUS_SHIFT           13
-#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT    5
-#define FFE_IDLE_ERR_COUNT_TIMEOUT_20            20
-#define FFE_IDLE_ERR_COUNT_TIMEOUT_100           100
-
-/* Extended Status Register */
-#define IEEE_ESR_1000T_HD_CAPS 0x1000	/* 1000T HD capable */
-#define IEEE_ESR_1000T_FD_CAPS 0x2000	/* 1000T FD capable */
-#define IEEE_ESR_1000X_HD_CAPS 0x4000	/* 1000X HD capable */
-#define IEEE_ESR_1000X_FD_CAPS 0x8000	/* 1000X FD capable */
-
-#define PHY_TX_POLARITY_MASK   0x0100	/* register 10h bit 8 (polarity bit) */
-#define PHY_TX_NORMAL_POLARITY 0	/* register 10h bit 8 (normal polarity) */
-
-#define AUTO_POLARITY_DISABLE  0x0010	/* register 11h bit 4 */
-				      /* (0=enable, 1=disable) */
-
-/* M88E1000 PHY Specific Control Register */
-#define M88E1000_PSCR_JABBER_DISABLE    0x0001	/* 1=Jabber Function disabled */
-#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002	/* 1=Polarity Reversal enabled */
-#define M88E1000_PSCR_SQE_TEST          0x0004	/* 1=SQE Test enabled */
-#define M88E1000_PSCR_CLK125_DISABLE    0x0010	/* 1=CLK125 low,
-						 * 0=CLK125 toggling
-						 */
-#define M88E1000_PSCR_MDI_MANUAL_MODE  0x0000	/* MDI Crossover Mode bits 6:5 */
-					       /* Manual MDI configuration */
-#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020	/* Manual MDIX configuration */
-#define M88E1000_PSCR_AUTO_X_1000T     0x0040	/* 1000BASE-T: Auto crossover,
-						 *  100BASE-TX/10BASE-T:
-						 *  MDI Mode
-						 */
-#define M88E1000_PSCR_AUTO_X_MODE      0x0060	/* Auto crossover enabled
-						 * all speeds.
-						 */
-#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE 0x0080
-					/* 1=Enable Extended 10BASE-T distance
-					 * (Lower 10BASE-T RX Threshold)
-					 * 0=Normal 10BASE-T RX Threshold */
-#define M88E1000_PSCR_MII_5BIT_ENABLE      0x0100
-					/* 1=5-Bit interface in 100BASE-TX
-					 * 0=MII interface in 100BASE-TX */
-#define M88E1000_PSCR_SCRAMBLER_DISABLE    0x0200	/* 1=Scrambler disable */
-#define M88E1000_PSCR_FORCE_LINK_GOOD      0x0400	/* 1=Force link good */
-#define M88E1000_PSCR_ASSERT_CRS_ON_TX     0x0800	/* 1=Assert CRS on Transmit */
-
-#define M88E1000_PSCR_POLARITY_REVERSAL_SHIFT    1
-#define M88E1000_PSCR_AUTO_X_MODE_SHIFT          5
-#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
-
-/* M88E1000 PHY Specific Status Register */
-#define M88E1000_PSSR_JABBER             0x0001	/* 1=Jabber */
-#define M88E1000_PSSR_REV_POLARITY       0x0002	/* 1=Polarity reversed */
-#define M88E1000_PSSR_DOWNSHIFT          0x0020	/* 1=Downshifted */
-#define M88E1000_PSSR_MDIX               0x0040	/* 1=MDIX; 0=MDI */
-#define M88E1000_PSSR_CABLE_LENGTH       0x0380	/* 0=<50M;1=50-80M;2=80-110M;
-						 * 3=110-140M;4=>140M */
-#define M88E1000_PSSR_LINK               0x0400	/* 1=Link up, 0=Link down */
-#define M88E1000_PSSR_SPD_DPLX_RESOLVED  0x0800	/* 1=Speed & Duplex resolved */
-#define M88E1000_PSSR_PAGE_RCVD          0x1000	/* 1=Page received */
-#define M88E1000_PSSR_DPLX               0x2000	/* 1=Duplex 0=Half Duplex */
-#define M88E1000_PSSR_SPEED              0xC000	/* Speed, bits 14:15 */
-#define M88E1000_PSSR_10MBS              0x0000	/* 00=10Mbs */
-#define M88E1000_PSSR_100MBS             0x4000	/* 01=100Mbs */
-#define M88E1000_PSSR_1000MBS            0x8000	/* 10=1000Mbs */
-
-#define M88E1000_PSSR_REV_POLARITY_SHIFT 1
-#define M88E1000_PSSR_DOWNSHIFT_SHIFT    5
-#define M88E1000_PSSR_MDIX_SHIFT         6
-#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
-
-/* M88E1000 Extended PHY Specific Control Register */
-#define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000	/* 1=Fiber loopback */
-#define M88E1000_EPSCR_DOWN_NO_IDLE   0x8000	/* 1=Lost lock detect enabled.
-						 * Will assert lost lock and bring
-						 * link down if idle not seen
-						 * within 1ms in 1000BASE-T
-						 */
-/* Number of times we will attempt to autonegotiate before downshifting if we
- * are the master */
-#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00
-#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X   0x0000
-#define M88E1000_EPSCR_MASTER_DOWNSHIFT_2X   0x0400
-#define M88E1000_EPSCR_MASTER_DOWNSHIFT_3X   0x0800
-#define M88E1000_EPSCR_MASTER_DOWNSHIFT_4X   0x0C00
-/* Number of times we will attempt to autonegotiate before downshifting if we
- * are the slave */
-#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK  0x0300
-#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_DIS   0x0000
-#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X    0x0100
-#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_2X    0x0200
-#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_3X    0x0300
-#define M88E1000_EPSCR_TX_CLK_2_5     0x0060	/* 2.5 MHz TX_CLK */
-#define M88E1000_EPSCR_TX_CLK_25      0x0070	/* 25  MHz TX_CLK */
-#define M88E1000_EPSCR_TX_CLK_0       0x0000	/* NO  TX_CLK */
-
-/* M88EC018 Rev 2 specific DownShift settings */
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK  0x0E00
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_1X    0x0000
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_2X    0x0200
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_3X    0x0400
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_4X    0x0600
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X    0x0800
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_6X    0x0A00
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_7X    0x0C00
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_8X    0x0E00
-
-/* IGP01E1000 Specific Port Config Register - R/W */
-#define IGP01E1000_PSCFR_AUTO_MDIX_PAR_DETECT  0x0010
-#define IGP01E1000_PSCFR_PRE_EN                0x0020
-#define IGP01E1000_PSCFR_SMART_SPEED           0x0080
-#define IGP01E1000_PSCFR_DISABLE_TPLOOPBACK    0x0100
-#define IGP01E1000_PSCFR_DISABLE_JABBER        0x0400
-#define IGP01E1000_PSCFR_DISABLE_TRANSMIT      0x2000
-
-/* IGP01E1000 Specific Port Status Register - R/O */
-#define IGP01E1000_PSSR_AUTONEG_FAILED         0x0001	/* RO LH SC */
-#define IGP01E1000_PSSR_POLARITY_REVERSED      0x0002
-#define IGP01E1000_PSSR_CABLE_LENGTH           0x007C
-#define IGP01E1000_PSSR_FULL_DUPLEX            0x0200
-#define IGP01E1000_PSSR_LINK_UP                0x0400
-#define IGP01E1000_PSSR_MDIX                   0x0800
-#define IGP01E1000_PSSR_SPEED_MASK             0xC000	/* speed bits mask */
-#define IGP01E1000_PSSR_SPEED_10MBPS           0x4000
-#define IGP01E1000_PSSR_SPEED_100MBPS          0x8000
-#define IGP01E1000_PSSR_SPEED_1000MBPS         0xC000
-#define IGP01E1000_PSSR_CABLE_LENGTH_SHIFT     0x0002	/* shift right 2 */
-#define IGP01E1000_PSSR_MDIX_SHIFT             0x000B	/* shift right 11 */
-
-/* IGP01E1000 Specific Port Control Register - R/W */
-#define IGP01E1000_PSCR_TP_LOOPBACK            0x0010
-#define IGP01E1000_PSCR_CORRECT_NC_SCMBLR      0x0200
-#define IGP01E1000_PSCR_TEN_CRS_SELECT         0x0400
-#define IGP01E1000_PSCR_FLIP_CHIP              0x0800
-#define IGP01E1000_PSCR_AUTO_MDIX              0x1000
-#define IGP01E1000_PSCR_FORCE_MDI_MDIX         0x2000	/* 0-MDI, 1-MDIX */
-
-/* IGP01E1000 Specific Port Link Health Register */
-#define IGP01E1000_PLHR_SS_DOWNGRADE           0x8000
-#define IGP01E1000_PLHR_GIG_SCRAMBLER_ERROR    0x4000
-#define IGP01E1000_PLHR_MASTER_FAULT           0x2000
-#define IGP01E1000_PLHR_MASTER_RESOLUTION      0x1000
-#define IGP01E1000_PLHR_GIG_REM_RCVR_NOK       0x0800	/* LH */
-#define IGP01E1000_PLHR_IDLE_ERROR_CNT_OFLOW   0x0400	/* LH */
-#define IGP01E1000_PLHR_DATA_ERR_1             0x0200	/* LH */
-#define IGP01E1000_PLHR_DATA_ERR_0             0x0100
-#define IGP01E1000_PLHR_AUTONEG_FAULT          0x0040
-#define IGP01E1000_PLHR_AUTONEG_ACTIVE         0x0010
-#define IGP01E1000_PLHR_VALID_CHANNEL_D        0x0008
-#define IGP01E1000_PLHR_VALID_CHANNEL_C        0x0004
-#define IGP01E1000_PLHR_VALID_CHANNEL_B        0x0002
-#define IGP01E1000_PLHR_VALID_CHANNEL_A        0x0001
-
-/* IGP01E1000 Channel Quality Register */
-#define IGP01E1000_MSE_CHANNEL_D        0x000F
-#define IGP01E1000_MSE_CHANNEL_C        0x00F0
-#define IGP01E1000_MSE_CHANNEL_B        0x0F00
-#define IGP01E1000_MSE_CHANNEL_A        0xF000
-
-#define IGP02E1000_PM_SPD                         0x0001	/* Smart Power Down */
-#define IGP02E1000_PM_D3_LPLU                     0x0004	/* Enable LPLU in non-D0a modes */
-#define IGP02E1000_PM_D0_LPLU                     0x0002	/* Enable LPLU in D0a mode */
-
-/* IGP01E1000 DSP reset macros */
-#define DSP_RESET_ENABLE     0x0
-#define DSP_RESET_DISABLE    0x2
-#define E1000_MAX_DSP_RESETS 10
-
-/* IGP01E1000 & IGP02E1000 AGC Registers */
-
-#define IGP01E1000_AGC_LENGTH_SHIFT 7	/* Coarse - 13:11, Fine - 10:7 */
-#define IGP02E1000_AGC_LENGTH_SHIFT 9	/* Coarse - 15:13, Fine - 12:9 */
-
-/* IGP02E1000 AGC Register Length 9-bit mask */
-#define IGP02E1000_AGC_LENGTH_MASK  0x7F
-
-/* 7 bits (3 Coarse + 4 Fine) --> 128 optional values */
-#define IGP01E1000_AGC_LENGTH_TABLE_SIZE 128
-#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 113
-
-/* The precision error of the cable length is +/- 10 meters */
-#define IGP01E1000_AGC_RANGE    10
-#define IGP02E1000_AGC_RANGE    15
-
-/* IGP01E1000 PCS Initialization register */
-/* bits 3:6 in the PCS registers stores the channels polarity */
-#define IGP01E1000_PHY_POLARITY_MASK    0x0078
-
-/* IGP01E1000 GMII FIFO Register */
-#define IGP01E1000_GMII_FLEX_SPD               0x10	/* Enable flexible speed
-							 * on Link-Up */
-#define IGP01E1000_GMII_SPD                    0x20	/* Enable SPD */
-
-/* IGP01E1000 Analog Register */
-#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS       0x20D1
-#define IGP01E1000_ANALOG_FUSE_STATUS             0x20D0
-#define IGP01E1000_ANALOG_FUSE_CONTROL            0x20DC
-#define IGP01E1000_ANALOG_FUSE_BYPASS             0x20DE
-
-#define IGP01E1000_ANALOG_FUSE_POLY_MASK            0xF000
-#define IGP01E1000_ANALOG_FUSE_FINE_MASK            0x0F80
-#define IGP01E1000_ANALOG_FUSE_COARSE_MASK          0x0070
-#define IGP01E1000_ANALOG_SPARE_FUSE_ENABLED        0x0100
-#define IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL    0x0002
-
-#define IGP01E1000_ANALOG_FUSE_COARSE_THRESH        0x0040
-#define IGP01E1000_ANALOG_FUSE_COARSE_10            0x0010
-#define IGP01E1000_ANALOG_FUSE_FINE_1               0x0080
-#define IGP01E1000_ANALOG_FUSE_FINE_10              0x0500
-
-/* Bit definitions for valid PHY IDs. */
-/* I = Integrated
- * E = External
- */
-#define M88_VENDOR         0x0141
-#define M88E1000_E_PHY_ID  0x01410C50
-#define M88E1000_I_PHY_ID  0x01410C30
-#define M88E1011_I_PHY_ID  0x01410C20
-#define IGP01E1000_I_PHY_ID  0x02A80380
-#define M88E1000_12_PHY_ID M88E1000_E_PHY_ID
-#define M88E1000_14_PHY_ID M88E1000_E_PHY_ID
-#define M88E1011_I_REV_4   0x04
-#define M88E1111_I_PHY_ID  0x01410CC0
-#define M88E1118_E_PHY_ID  0x01410E40
-#define L1LXT971A_PHY_ID   0x001378E0
-
-#define RTL8211B_PHY_ID    0x001CC910
-#define RTL8201N_PHY_ID    0x8200
-#define RTL_PHY_CTRL_FD    0x0100 /* Full duplex.0=half; 1=full */
-#define RTL_PHY_CTRL_SPD_100    0x200000 /* Force 100Mb */
-
-/* Bits...
- * 15-5: page
- * 4-0: register offset
- */
-#define PHY_PAGE_SHIFT        5
-#define PHY_REG(page, reg)    \
-        (((page) << PHY_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS))
-
-#define IGP3_PHY_PORT_CTRL           \
-        PHY_REG(769, 17)	/* Port General Configuration */
-#define IGP3_PHY_RATE_ADAPT_CTRL \
-        PHY_REG(769, 25)	/* Rate Adapter Control Register */
-
-#define IGP3_KMRN_FIFO_CTRL_STATS \
-        PHY_REG(770, 16)	/* KMRN FIFO's control/status register */
-#define IGP3_KMRN_POWER_MNG_CTRL \
-        PHY_REG(770, 17)	/* KMRN Power Management Control Register */
-#define IGP3_KMRN_INBAND_CTRL \
-        PHY_REG(770, 18)	/* KMRN Inband Control Register */
-#define IGP3_KMRN_DIAG \
-        PHY_REG(770, 19)	/* KMRN Diagnostic register */
-#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002	/* RX PCS is not synced */
-#define IGP3_KMRN_ACK_TIMEOUT \
-        PHY_REG(770, 20)	/* KMRN Acknowledge Timeouts register */
-
-#define IGP3_VR_CTRL \
-        PHY_REG(776, 18)	/* Voltage regulator control register */
-#define IGP3_VR_CTRL_MODE_SHUT       0x0200	/* Enter powerdown, shutdown VRs */
-#define IGP3_VR_CTRL_MODE_MASK       0x0300	/* Shutdown VR Mask */
-
-#define IGP3_CAPABILITY \
-        PHY_REG(776, 19)	/* IGP3 Capability Register */
-
-/* Capabilities for SKU Control  */
-#define IGP3_CAP_INITIATE_TEAM       0x0001	/* Able to initiate a team */
-#define IGP3_CAP_WFM                 0x0002	/* Support WoL and PXE */
-#define IGP3_CAP_ASF                 0x0004	/* Support ASF */
-#define IGP3_CAP_LPLU                0x0008	/* Support Low Power Link Up */
-#define IGP3_CAP_DC_AUTO_SPEED       0x0010	/* Support AC/DC Auto Link Speed */
-#define IGP3_CAP_SPD                 0x0020	/* Support Smart Power Down */
-#define IGP3_CAP_MULT_QUEUE          0x0040	/* Support 2 tx & 2 rx queues */
-#define IGP3_CAP_RSS                 0x0080	/* Support RSS */
-#define IGP3_CAP_8021PQ              0x0100	/* Support 802.1Q & 802.1p */
-#define IGP3_CAP_AMT_CB              0x0200	/* Support active manageability and circuit breaker */
-
-#define IGP3_PPC_JORDAN_EN           0x0001
-#define IGP3_PPC_JORDAN_GIGA_SPEED   0x0002
-
-#define IGP3_KMRN_PMC_EE_IDLE_LINK_DIS         0x0001
-#define IGP3_KMRN_PMC_K0S_ENTRY_LATENCY_MASK   0x001E
-#define IGP3_KMRN_PMC_K0S_MODE1_EN_GIGA        0x0020
-#define IGP3_KMRN_PMC_K0S_MODE1_EN_100         0x0040
-
-#define IGP3E1000_PHY_MISC_CTRL                0x1B	/* Misc. Ctrl register */
-#define IGP3_PHY_MISC_DUPLEX_MANUAL_SET        0x1000	/* Duplex Manual Set */
-
-#define IGP3_KMRN_EXT_CTRL  PHY_REG(770, 18)
-#define IGP3_KMRN_EC_DIS_INBAND    0x0080
-
-#define IGP03E1000_E_PHY_ID  0x02A80390
-#define IFE_E_PHY_ID         0x02A80330	/* 10/100 PHY */
-#define IFE_PLUS_E_PHY_ID    0x02A80320
-#define IFE_C_E_PHY_ID       0x02A80310
-
-#define IFE_PHY_EXTENDED_STATUS_CONTROL   0x10	/* 100BaseTx Extended Status, Control and Address */
-#define IFE_PHY_SPECIAL_CONTROL           0x11	/* 100BaseTx PHY special control register */
-#define IFE_PHY_RCV_FALSE_CARRIER         0x13	/* 100BaseTx Receive False Carrier Counter */
-#define IFE_PHY_RCV_DISCONNECT            0x14	/* 100BaseTx Receive Disconnect Counter */
-#define IFE_PHY_RCV_ERROT_FRAME           0x15	/* 100BaseTx Receive Error Frame Counter */
-#define IFE_PHY_RCV_SYMBOL_ERR            0x16	/* Receive Symbol Error Counter */
-#define IFE_PHY_PREM_EOF_ERR              0x17	/* 100BaseTx Receive Premature End Of Frame Error Counter */
-#define IFE_PHY_RCV_EOF_ERR               0x18	/* 10BaseT Receive End Of Frame Error Counter */
-#define IFE_PHY_TX_JABBER_DETECT          0x19	/* 10BaseT Transmit Jabber Detect Counter */
-#define IFE_PHY_EQUALIZER                 0x1A	/* PHY Equalizer Control and Status */
-#define IFE_PHY_SPECIAL_CONTROL_LED       0x1B	/* PHY special control and LED configuration */
-#define IFE_PHY_MDIX_CONTROL              0x1C	/* MDI/MDI-X Control register */
-#define IFE_PHY_HWI_CONTROL               0x1D	/* Hardware Integrity Control (HWI) */
-
-#define IFE_PESC_REDUCED_POWER_DOWN_DISABLE  0x2000	/* Default 1 = Disable auto reduced power down */
-#define IFE_PESC_100BTX_POWER_DOWN           0x0400	/* Indicates the power state of 100BASE-TX */
-#define IFE_PESC_10BTX_POWER_DOWN            0x0200	/* Indicates the power state of 10BASE-T */
-#define IFE_PESC_POLARITY_REVERSED           0x0100	/* Indicates 10BASE-T polarity */
-#define IFE_PESC_PHY_ADDR_MASK               0x007C	/* Bit 6:2 for sampled PHY address */
-#define IFE_PESC_SPEED                       0x0002	/* Auto-negotiation speed result 1=100Mbs, 0=10Mbs */
-#define IFE_PESC_DUPLEX                      0x0001	/* Auto-negotiation duplex result 1=Full, 0=Half */
-#define IFE_PESC_POLARITY_REVERSED_SHIFT     8
-
-#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN   0x0100	/* 1 = Dynamic Power Down disabled */
-#define IFE_PSC_FORCE_POLARITY               0x0020	/* 1=Reversed Polarity, 0=Normal */
-#define IFE_PSC_AUTO_POLARITY_DISABLE        0x0010	/* 1=Auto Polarity Disabled, 0=Enabled */
-#define IFE_PSC_JABBER_FUNC_DISABLE          0x0001	/* 1=Jabber Disabled, 0=Normal Jabber Operation */
-#define IFE_PSC_FORCE_POLARITY_SHIFT         5
-#define IFE_PSC_AUTO_POLARITY_DISABLE_SHIFT  4
-
-#define IFE_PMC_AUTO_MDIX                    0x0080	/* 1=enable MDI/MDI-X feature, default 0=disabled */
-#define IFE_PMC_FORCE_MDIX                   0x0040	/* 1=force MDIX-X, 0=force MDI */
-#define IFE_PMC_MDIX_STATUS                  0x0020	/* 1=MDI-X, 0=MDI */
-#define IFE_PMC_AUTO_MDIX_COMPLETE           0x0010	/* Resolution algorithm is completed */
-#define IFE_PMC_MDIX_MODE_SHIFT              6
-#define IFE_PHC_MDIX_RESET_ALL_MASK          0x0000	/* Disable auto MDI-X */
-
-#define IFE_PHC_HWI_ENABLE                   0x8000	/* Enable the HWI feature */
-#define IFE_PHC_ABILITY_CHECK                0x4000	/* 1= Test Passed, 0=failed */
-#define IFE_PHC_TEST_EXEC                    0x2000	/* PHY launch test pulses on the wire */
-#define IFE_PHC_HIGHZ                        0x0200	/* 1 = Open Circuit */
-#define IFE_PHC_LOWZ                         0x0400	/* 1 = Short Circuit */
-#define IFE_PHC_LOW_HIGH_Z_MASK              0x0600	/* Mask for indication type of problem on the line */
-#define IFE_PHC_DISTANCE_MASK                0x01FF	/* Mask for distance to the cable problem, in 80cm granularity */
-#define IFE_PHC_RESET_ALL_MASK               0x0000	/* Disable HWI */
-#define IFE_PSCL_PROBE_MODE                  0x0020	/* LED Probe mode */
-#define IFE_PSCL_PROBE_LEDS_OFF              0x0006	/* Force LEDs 0 and 2 off */
-#define IFE_PSCL_PROBE_LEDS_ON               0x0007	/* Force LEDs 0 and 2 on */
-
-#define ICH_FLASH_COMMAND_TIMEOUT            5000	/* 5000 uSecs - adjusted */
-#define ICH_FLASH_ERASE_TIMEOUT              3000000	/* Up to 3 seconds - worst case */
-#define ICH_FLASH_CYCLE_REPEAT_COUNT         10	/* 10 cycles */
-#define ICH_FLASH_SEG_SIZE_256               256
-#define ICH_FLASH_SEG_SIZE_4K                4096
-#define ICH_FLASH_SEG_SIZE_64K               65536
-
-#define ICH_CYCLE_READ                       0x0
-#define ICH_CYCLE_RESERVED                   0x1
-#define ICH_CYCLE_WRITE                      0x2
-#define ICH_CYCLE_ERASE                      0x3
-
-#define ICH_FLASH_GFPREG   0x0000
-#define ICH_FLASH_HSFSTS   0x0004
-#define ICH_FLASH_HSFCTL   0x0006
-#define ICH_FLASH_FADDR    0x0008
-#define ICH_FLASH_FDATA0   0x0010
-#define ICH_FLASH_FRACC    0x0050
-#define ICH_FLASH_FREG0    0x0054
-#define ICH_FLASH_FREG1    0x0058
-#define ICH_FLASH_FREG2    0x005C
-#define ICH_FLASH_FREG3    0x0060
-#define ICH_FLASH_FPR0     0x0074
-#define ICH_FLASH_FPR1     0x0078
-#define ICH_FLASH_SSFSTS   0x0090
-#define ICH_FLASH_SSFCTL   0x0092
-#define ICH_FLASH_PREOP    0x0094
-#define ICH_FLASH_OPTYPE   0x0096
-#define ICH_FLASH_OPMENU   0x0098
-
-#define ICH_FLASH_REG_MAPSIZE      0x00A0
-#define ICH_FLASH_SECTOR_SIZE      4096
-#define ICH_GFPREG_BASE_MASK       0x1FFF
-#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF
-
-/* Miscellaneous PHY bit definitions. */
-#define PHY_PREAMBLE        0xFFFFFFFF
-#define PHY_SOF             0x01
-#define PHY_OP_READ         0x02
-#define PHY_OP_WRITE        0x01
-#define PHY_TURNAROUND      0x02
-#define PHY_PREAMBLE_SIZE   32
-#define MII_CR_SPEED_1000   0x0040
-#define MII_CR_SPEED_100    0x2000
-#define MII_CR_SPEED_10     0x0000
-#define E1000_PHY_ADDRESS   0x01
-#define PHY_AUTO_NEG_TIME   45	/* 4.5 Seconds */
-#define PHY_FORCE_TIME      20	/* 2.0 Seconds */
-#define PHY_REVISION_MASK   0xFFFFFFF0
-#define DEVICE_SPEED_MASK   0x00000300	/* Device Ctrl Reg Speed Mask */
-#define REG4_SPEED_MASK     0x01E0
-#define REG9_SPEED_MASK     0x0300
-#define ADVERTISE_10_HALF   0x0001
-#define ADVERTISE_10_FULL   0x0002
-#define ADVERTISE_100_HALF  0x0004
-#define ADVERTISE_100_FULL  0x0008
-#define ADVERTISE_1000_HALF 0x0010
-#define ADVERTISE_1000_FULL 0x0020
-#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F	/* Everything but 1000-Half */
-#define AUTONEG_ADVERTISE_10_100_ALL    0x000F	/* All 10/100 speeds */
-#define AUTONEG_ADVERTISE_10_ALL        0x0003	/* 10Mbps Full & Half speeds */
-
-#endif /* _E1000_HW_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/e1000/e1000_main.c linux-libre-3.2-gnu/drivers/net/e1000/e1000_main.c
--- linux-libre-3.1-gnu/drivers/net/e1000/e1000_main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000/e1000_main.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,4974 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2006 Intel Corporation.
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms and conditions of the GNU General Public License,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-#include "e1000.h"
-#include <net/ip6_checksum.h>
-#include <linux/io.h>
-#include <linux/prefetch.h>
-#include <linux/bitops.h>
-#include <linux/if_vlan.h>
-
-/* Intel Media SOC GbE MDIO physical base address */
-static unsigned long ce4100_gbe_mdio_base_phy;
-/* Intel Media SOC GbE MDIO virtual base address */
-void __iomem *ce4100_gbe_mdio_base_virt;
-
-char e1000_driver_name[] = "e1000";
-static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
-#define DRV_VERSION "7.3.21-k8-NAPI"
-const char e1000_driver_version[] = DRV_VERSION;
-static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
-
-/* e1000_pci_tbl - PCI Device ID Table
- *
- * Last entry must be all 0s
- *
- * Macro expands to...
- *   {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
- */
-static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
-	INTEL_E1000_ETHERNET_DEVICE(0x1000),
-	INTEL_E1000_ETHERNET_DEVICE(0x1001),
-	INTEL_E1000_ETHERNET_DEVICE(0x1004),
-	INTEL_E1000_ETHERNET_DEVICE(0x1008),
-	INTEL_E1000_ETHERNET_DEVICE(0x1009),
-	INTEL_E1000_ETHERNET_DEVICE(0x100C),
-	INTEL_E1000_ETHERNET_DEVICE(0x100D),
-	INTEL_E1000_ETHERNET_DEVICE(0x100E),
-	INTEL_E1000_ETHERNET_DEVICE(0x100F),
-	INTEL_E1000_ETHERNET_DEVICE(0x1010),
-	INTEL_E1000_ETHERNET_DEVICE(0x1011),
-	INTEL_E1000_ETHERNET_DEVICE(0x1012),
-	INTEL_E1000_ETHERNET_DEVICE(0x1013),
-	INTEL_E1000_ETHERNET_DEVICE(0x1014),
-	INTEL_E1000_ETHERNET_DEVICE(0x1015),
-	INTEL_E1000_ETHERNET_DEVICE(0x1016),
-	INTEL_E1000_ETHERNET_DEVICE(0x1017),
-	INTEL_E1000_ETHERNET_DEVICE(0x1018),
-	INTEL_E1000_ETHERNET_DEVICE(0x1019),
-	INTEL_E1000_ETHERNET_DEVICE(0x101A),
-	INTEL_E1000_ETHERNET_DEVICE(0x101D),
-	INTEL_E1000_ETHERNET_DEVICE(0x101E),
-	INTEL_E1000_ETHERNET_DEVICE(0x1026),
-	INTEL_E1000_ETHERNET_DEVICE(0x1027),
-	INTEL_E1000_ETHERNET_DEVICE(0x1028),
-	INTEL_E1000_ETHERNET_DEVICE(0x1075),
-	INTEL_E1000_ETHERNET_DEVICE(0x1076),
-	INTEL_E1000_ETHERNET_DEVICE(0x1077),
-	INTEL_E1000_ETHERNET_DEVICE(0x1078),
-	INTEL_E1000_ETHERNET_DEVICE(0x1079),
-	INTEL_E1000_ETHERNET_DEVICE(0x107A),
-	INTEL_E1000_ETHERNET_DEVICE(0x107B),
-	INTEL_E1000_ETHERNET_DEVICE(0x107C),
-	INTEL_E1000_ETHERNET_DEVICE(0x108A),
-	INTEL_E1000_ETHERNET_DEVICE(0x1099),
-	INTEL_E1000_ETHERNET_DEVICE(0x10B5),
-	INTEL_E1000_ETHERNET_DEVICE(0x2E6E),
-	/* required last entry */
-	{0,}
-};
-
-MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
-
-int e1000_up(struct e1000_adapter *adapter);
-void e1000_down(struct e1000_adapter *adapter);
-void e1000_reinit_locked(struct e1000_adapter *adapter);
-void e1000_reset(struct e1000_adapter *adapter);
-int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
-int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
-void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
-void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
-static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
-                             struct e1000_tx_ring *txdr);
-static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
-                             struct e1000_rx_ring *rxdr);
-static void e1000_free_tx_resources(struct e1000_adapter *adapter,
-                             struct e1000_tx_ring *tx_ring);
-static void e1000_free_rx_resources(struct e1000_adapter *adapter,
-                             struct e1000_rx_ring *rx_ring);
-void e1000_update_stats(struct e1000_adapter *adapter);
-
-static int e1000_init_module(void);
-static void e1000_exit_module(void);
-static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-static void __devexit e1000_remove(struct pci_dev *pdev);
-static int e1000_alloc_queues(struct e1000_adapter *adapter);
-static int e1000_sw_init(struct e1000_adapter *adapter);
-static int e1000_open(struct net_device *netdev);
-static int e1000_close(struct net_device *netdev);
-static void e1000_configure_tx(struct e1000_adapter *adapter);
-static void e1000_configure_rx(struct e1000_adapter *adapter);
-static void e1000_setup_rctl(struct e1000_adapter *adapter);
-static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter);
-static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter);
-static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
-                                struct e1000_tx_ring *tx_ring);
-static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
-                                struct e1000_rx_ring *rx_ring);
-static void e1000_set_rx_mode(struct net_device *netdev);
-static void e1000_update_phy_info(unsigned long data);
-static void e1000_update_phy_info_task(struct work_struct *work);
-static void e1000_watchdog(unsigned long data);
-static void e1000_82547_tx_fifo_stall(unsigned long data);
-static void e1000_82547_tx_fifo_stall_task(struct work_struct *work);
-static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
-				    struct net_device *netdev);
-static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
-static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
-static int e1000_set_mac(struct net_device *netdev, void *p);
-static irqreturn_t e1000_intr(int irq, void *data);
-static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
-			       struct e1000_tx_ring *tx_ring);
-static int e1000_clean(struct napi_struct *napi, int budget);
-static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
-			       struct e1000_rx_ring *rx_ring,
-			       int *work_done, int work_to_do);
-static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
-				     struct e1000_rx_ring *rx_ring,
-				     int *work_done, int work_to_do);
-static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
-				   struct e1000_rx_ring *rx_ring,
-				   int cleaned_count);
-static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
-					 struct e1000_rx_ring *rx_ring,
-					 int cleaned_count);
-static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
-static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
-			   int cmd);
-static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
-static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
-static void e1000_tx_timeout(struct net_device *dev);
-static void e1000_reset_task(struct work_struct *work);
-static void e1000_smartspeed(struct e1000_adapter *adapter);
-static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
-                                       struct sk_buff *skb);
-
-static bool e1000_vlan_used(struct e1000_adapter *adapter);
-static void e1000_vlan_mode(struct net_device *netdev, u32 features);
-static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
-static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
-static void e1000_restore_vlan(struct e1000_adapter *adapter);
-
-#ifdef CONFIG_PM
-static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
-static int e1000_resume(struct pci_dev *pdev);
-#endif
-static void e1000_shutdown(struct pci_dev *pdev);
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/* for netdump / net console */
-static void e1000_netpoll (struct net_device *netdev);
-#endif
-
-#define COPYBREAK_DEFAULT 256
-static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT;
-module_param(copybreak, uint, 0644);
-MODULE_PARM_DESC(copybreak,
-	"Maximum size of packet that is copied to a new buffer on receive");
-
-static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
-                     pci_channel_state_t state);
-static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev);
-static void e1000_io_resume(struct pci_dev *pdev);
-
-static struct pci_error_handlers e1000_err_handler = {
-	.error_detected = e1000_io_error_detected,
-	.slot_reset = e1000_io_slot_reset,
-	.resume = e1000_io_resume,
-};
-
-static struct pci_driver e1000_driver = {
-	.name     = e1000_driver_name,
-	.id_table = e1000_pci_tbl,
-	.probe    = e1000_probe,
-	.remove   = __devexit_p(e1000_remove),
-#ifdef CONFIG_PM
-	/* Power Management Hooks */
-	.suspend  = e1000_suspend,
-	.resume   = e1000_resume,
-#endif
-	.shutdown = e1000_shutdown,
-	.err_handler = &e1000_err_handler
-};
-
-MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
-MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-
-static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
-
-/**
- * e1000_get_hw_dev - return device
- * used by hardware layer to print debugging information
- *
- **/
-struct net_device *e1000_get_hw_dev(struct e1000_hw *hw)
-{
-	struct e1000_adapter *adapter = hw->back;
-	return adapter->netdev;
-}
-
-/**
- * e1000_init_module - Driver Registration Routine
- *
- * e1000_init_module is the first routine called when the driver is
- * loaded. All it does is register with the PCI subsystem.
- **/
-
-static int __init e1000_init_module(void)
-{
-	int ret;
-	pr_info("%s - version %s\n", e1000_driver_string, e1000_driver_version);
-
-	pr_info("%s\n", e1000_copyright);
-
-	ret = pci_register_driver(&e1000_driver);
-	if (copybreak != COPYBREAK_DEFAULT) {
-		if (copybreak == 0)
-			pr_info("copybreak disabled\n");
-		else
-			pr_info("copybreak enabled for "
-				   "packets <= %u bytes\n", copybreak);
-	}
-	return ret;
-}
-
-module_init(e1000_init_module);
-
-/**
- * e1000_exit_module - Driver Exit Cleanup Routine
- *
- * e1000_exit_module is called just before the driver is removed
- * from memory.
- **/
-
-static void __exit e1000_exit_module(void)
-{
-	pci_unregister_driver(&e1000_driver);
-}
-
-module_exit(e1000_exit_module);
-
-static int e1000_request_irq(struct e1000_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	irq_handler_t handler = e1000_intr;
-	int irq_flags = IRQF_SHARED;
-	int err;
-
-	err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name,
-	                  netdev);
-	if (err) {
-		e_err(probe, "Unable to allocate interrupt Error: %d\n", err);
-	}
-
-	return err;
-}
-
-static void e1000_free_irq(struct e1000_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-
-	free_irq(adapter->pdev->irq, netdev);
-}
-
-/**
- * e1000_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- **/
-
-static void e1000_irq_disable(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-
-	ew32(IMC, ~0);
-	E1000_WRITE_FLUSH();
-	synchronize_irq(adapter->pdev->irq);
-}
-
-/**
- * e1000_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- **/
-
-static void e1000_irq_enable(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-
-	ew32(IMS, IMS_ENABLE_MASK);
-	E1000_WRITE_FLUSH();
-}
-
-static void e1000_update_mng_vlan(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	u16 vid = hw->mng_cookie.vlan_id;
-	u16 old_vid = adapter->mng_vlan_id;
-
-	if (!e1000_vlan_used(adapter))
-		return;
-
-	if (!test_bit(vid, adapter->active_vlans)) {
-		if (hw->mng_cookie.status &
-		    E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
-			e1000_vlan_rx_add_vid(netdev, vid);
-			adapter->mng_vlan_id = vid;
-		} else {
-			adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
-		}
-		if ((old_vid != (u16)E1000_MNG_VLAN_NONE) &&
-		    (vid != old_vid) &&
-		    !test_bit(old_vid, adapter->active_vlans))
-			e1000_vlan_rx_kill_vid(netdev, old_vid);
-	} else {
-		adapter->mng_vlan_id = vid;
-	}
-}
-
-static void e1000_init_manageability(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-
-	if (adapter->en_mng_pt) {
-		u32 manc = er32(MANC);
-
-		/* disable hardware interception of ARP */
-		manc &= ~(E1000_MANC_ARP_EN);
-
-		ew32(MANC, manc);
-	}
-}
-
-static void e1000_release_manageability(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-
-	if (adapter->en_mng_pt) {
-		u32 manc = er32(MANC);
-
-		/* re-enable hardware interception of ARP */
-		manc |= E1000_MANC_ARP_EN;
-
-		ew32(MANC, manc);
-	}
-}
-
-/**
- * e1000_configure - configure the hardware for RX and TX
- * @adapter = private board structure
- **/
-static void e1000_configure(struct e1000_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	int i;
-
-	e1000_set_rx_mode(netdev);
-
-	e1000_restore_vlan(adapter);
-	e1000_init_manageability(adapter);
-
-	e1000_configure_tx(adapter);
-	e1000_setup_rctl(adapter);
-	e1000_configure_rx(adapter);
-	/* call E1000_DESC_UNUSED which always leaves
-	 * at least 1 descriptor unused to make sure
-	 * next_to_use != next_to_clean */
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		struct e1000_rx_ring *ring = &adapter->rx_ring[i];
-		adapter->alloc_rx_buf(adapter, ring,
-		                      E1000_DESC_UNUSED(ring));
-	}
-}
-
-int e1000_up(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-
-	/* hardware has been reset, we need to reload some things */
-	e1000_configure(adapter);
-
-	clear_bit(__E1000_DOWN, &adapter->flags);
-
-	napi_enable(&adapter->napi);
-
-	e1000_irq_enable(adapter);
-
-	netif_wake_queue(adapter->netdev);
-
-	/* fire a link change interrupt to start the watchdog */
-	ew32(ICS, E1000_ICS_LSC);
-	return 0;
-}
-
-/**
- * e1000_power_up_phy - restore link in case the phy was powered down
- * @adapter: address of board private structure
- *
- * The phy may be powered down to save power and turn off link when the
- * driver is unloaded and wake on lan is not enabled (among others)
- * *** this routine MUST be followed by a call to e1000_reset ***
- *
- **/
-
-void e1000_power_up_phy(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u16 mii_reg = 0;
-
-	/* Just clear the power down bit to wake the phy back up */
-	if (hw->media_type == e1000_media_type_copper) {
-		/* according to the manual, the phy will retain its
-		 * settings across a power-down/up cycle */
-		e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
-		mii_reg &= ~MII_CR_POWER_DOWN;
-		e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
-	}
-}
-
-static void e1000_power_down_phy(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-
-	/* Power down the PHY so no link is implied when interface is down *
-	 * The PHY cannot be powered down if any of the following is true *
-	 * (a) WoL is enabled
-	 * (b) AMT is active
-	 * (c) SoL/IDER session is active */
-	if (!adapter->wol && hw->mac_type >= e1000_82540 &&
-	   hw->media_type == e1000_media_type_copper) {
-		u16 mii_reg = 0;
-
-		switch (hw->mac_type) {
-		case e1000_82540:
-		case e1000_82545:
-		case e1000_82545_rev_3:
-		case e1000_82546:
-		case e1000_ce4100:
-		case e1000_82546_rev_3:
-		case e1000_82541:
-		case e1000_82541_rev_2:
-		case e1000_82547:
-		case e1000_82547_rev_2:
-			if (er32(MANC) & E1000_MANC_SMBUS_EN)
-				goto out;
-			break;
-		default:
-			goto out;
-		}
-		e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
-		mii_reg |= MII_CR_POWER_DOWN;
-		e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
-		mdelay(1);
-	}
-out:
-	return;
-}
-
-void e1000_down(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	u32 rctl, tctl;
-
-
-	/* disable receives in the hardware */
-	rctl = er32(RCTL);
-	ew32(RCTL, rctl & ~E1000_RCTL_EN);
-	/* flush and sleep below */
-
-	netif_tx_disable(netdev);
-
-	/* disable transmits in the hardware */
-	tctl = er32(TCTL);
-	tctl &= ~E1000_TCTL_EN;
-	ew32(TCTL, tctl);
-	/* flush both disables and wait for them to finish */
-	E1000_WRITE_FLUSH();
-	msleep(10);
-
-	napi_disable(&adapter->napi);
-
-	e1000_irq_disable(adapter);
-
-	/*
-	 * Setting DOWN must be after irq_disable to prevent
-	 * a screaming interrupt.  Setting DOWN also prevents
-	 * timers and tasks from rescheduling.
-	 */
-	set_bit(__E1000_DOWN, &adapter->flags);
-
-	del_timer_sync(&adapter->tx_fifo_stall_timer);
-	del_timer_sync(&adapter->watchdog_timer);
-	del_timer_sync(&adapter->phy_info_timer);
-
-	adapter->link_speed = 0;
-	adapter->link_duplex = 0;
-	netif_carrier_off(netdev);
-
-	e1000_reset(adapter);
-	e1000_clean_all_tx_rings(adapter);
-	e1000_clean_all_rx_rings(adapter);
-}
-
-static void e1000_reinit_safe(struct e1000_adapter *adapter)
-{
-	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
-		msleep(1);
-	rtnl_lock();
-	e1000_down(adapter);
-	e1000_up(adapter);
-	rtnl_unlock();
-	clear_bit(__E1000_RESETTING, &adapter->flags);
-}
-
-void e1000_reinit_locked(struct e1000_adapter *adapter)
-{
-	/* if rtnl_lock is not held the call path is bogus */
-	ASSERT_RTNL();
-	WARN_ON(in_interrupt());
-	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
-		msleep(1);
-	e1000_down(adapter);
-	e1000_up(adapter);
-	clear_bit(__E1000_RESETTING, &adapter->flags);
-}
-
-void e1000_reset(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 pba = 0, tx_space, min_tx_space, min_rx_space;
-	bool legacy_pba_adjust = false;
-	u16 hwm;
-
-	/* Repartition Pba for greater than 9k mtu
-	 * To take effect CTRL.RST is required.
-	 */
-
-	switch (hw->mac_type) {
-	case e1000_82542_rev2_0:
-	case e1000_82542_rev2_1:
-	case e1000_82543:
-	case e1000_82544:
-	case e1000_82540:
-	case e1000_82541:
-	case e1000_82541_rev_2:
-		legacy_pba_adjust = true;
-		pba = E1000_PBA_48K;
-		break;
-	case e1000_82545:
-	case e1000_82545_rev_3:
-	case e1000_82546:
-	case e1000_ce4100:
-	case e1000_82546_rev_3:
-		pba = E1000_PBA_48K;
-		break;
-	case e1000_82547:
-	case e1000_82547_rev_2:
-		legacy_pba_adjust = true;
-		pba = E1000_PBA_30K;
-		break;
-	case e1000_undefined:
-	case e1000_num_macs:
-		break;
-	}
-
-	if (legacy_pba_adjust) {
-		if (hw->max_frame_size > E1000_RXBUFFER_8192)
-			pba -= 8; /* allocate more FIFO for Tx */
-
-		if (hw->mac_type == e1000_82547) {
-			adapter->tx_fifo_head = 0;
-			adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
-			adapter->tx_fifo_size =
-				(E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
-			atomic_set(&adapter->tx_fifo_stall, 0);
-		}
-	} else if (hw->max_frame_size >  ETH_FRAME_LEN + ETH_FCS_LEN) {
-		/* adjust PBA for jumbo frames */
-		ew32(PBA, pba);
-
-		/* To maintain wire speed transmits, the Tx FIFO should be
-		 * large enough to accommodate two full transmit packets,
-		 * rounded up to the next 1KB and expressed in KB.  Likewise,
-		 * the Rx FIFO should be large enough to accommodate at least
-		 * one full receive packet and is similarly rounded up and
-		 * expressed in KB. */
-		pba = er32(PBA);
-		/* upper 16 bits has Tx packet buffer allocation size in KB */
-		tx_space = pba >> 16;
-		/* lower 16 bits has Rx packet buffer allocation size in KB */
-		pba &= 0xffff;
-		/*
-		 * the tx fifo also stores 16 bytes of information about the tx
-		 * but don't include ethernet FCS because hardware appends it
-		 */
-		min_tx_space = (hw->max_frame_size +
-		                sizeof(struct e1000_tx_desc) -
-		                ETH_FCS_LEN) * 2;
-		min_tx_space = ALIGN(min_tx_space, 1024);
-		min_tx_space >>= 10;
-		/* software strips receive CRC, so leave room for it */
-		min_rx_space = hw->max_frame_size;
-		min_rx_space = ALIGN(min_rx_space, 1024);
-		min_rx_space >>= 10;
-
-		/* If current Tx allocation is less than the min Tx FIFO size,
-		 * and the min Tx FIFO size is less than the current Rx FIFO
-		 * allocation, take space away from current Rx allocation */
-		if (tx_space < min_tx_space &&
-		    ((min_tx_space - tx_space) < pba)) {
-			pba = pba - (min_tx_space - tx_space);
-
-			/* PCI/PCIx hardware has PBA alignment constraints */
-			switch (hw->mac_type) {
-			case e1000_82545 ... e1000_82546_rev_3:
-				pba &= ~(E1000_PBA_8K - 1);
-				break;
-			default:
-				break;
-			}
-
-			/* if short on rx space, rx wins and must trump tx
-			 * adjustment or use Early Receive if available */
-			if (pba < min_rx_space)
-				pba = min_rx_space;
-		}
-	}
-
-	ew32(PBA, pba);
-
-	/*
-	 * flow control settings:
-	 * The high water mark must be low enough to fit one full frame
-	 * (or the size used for early receive) above it in the Rx FIFO.
-	 * Set it to the lower of:
-	 * - 90% of the Rx FIFO size, and
-	 * - the full Rx FIFO size minus the early receive size (for parts
-	 *   with ERT support assuming ERT set to E1000_ERT_2048), or
-	 * - the full Rx FIFO size minus one full frame
-	 */
-	hwm = min(((pba << 10) * 9 / 10),
-		  ((pba << 10) - hw->max_frame_size));
-
-	hw->fc_high_water = hwm & 0xFFF8;	/* 8-byte granularity */
-	hw->fc_low_water = hw->fc_high_water - 8;
-	hw->fc_pause_time = E1000_FC_PAUSE_TIME;
-	hw->fc_send_xon = 1;
-	hw->fc = hw->original_fc;
-
-	/* Allow time for pending master requests to run */
-	e1000_reset_hw(hw);
-	if (hw->mac_type >= e1000_82544)
-		ew32(WUC, 0);
-
-	if (e1000_init_hw(hw))
-		e_dev_err("Hardware Error\n");
-	e1000_update_mng_vlan(adapter);
-
-	/* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */
-	if (hw->mac_type >= e1000_82544 &&
-	    hw->autoneg == 1 &&
-	    hw->autoneg_advertised == ADVERTISE_1000_FULL) {
-		u32 ctrl = er32(CTRL);
-		/* clear phy power management bit if we are in gig only mode,
-		 * which if enabled will attempt negotiation to 100Mb, which
-		 * can cause a loss of link at power off or driver unload */
-		ctrl &= ~E1000_CTRL_SWDPIN3;
-		ew32(CTRL, ctrl);
-	}
-
-	/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
-	ew32(VET, ETHERNET_IEEE_VLAN_TYPE);
-
-	e1000_reset_adaptive(hw);
-	e1000_phy_get_info(hw, &adapter->phy_info);
-
-	e1000_release_manageability(adapter);
-}
-
-/**
- *  Dump the eeprom for users having checksum issues
- **/
-static void e1000_dump_eeprom(struct e1000_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct ethtool_eeprom eeprom;
-	const struct ethtool_ops *ops = netdev->ethtool_ops;
-	u8 *data;
-	int i;
-	u16 csum_old, csum_new = 0;
-
-	eeprom.len = ops->get_eeprom_len(netdev);
-	eeprom.offset = 0;
-
-	data = kmalloc(eeprom.len, GFP_KERNEL);
-	if (!data) {
-		pr_err("Unable to allocate memory to dump EEPROM data\n");
-		return;
-	}
-
-	ops->get_eeprom(netdev, &eeprom, data);
-
-	csum_old = (data[EEPROM_CHECKSUM_REG * 2]) +
-		   (data[EEPROM_CHECKSUM_REG * 2 + 1] << 8);
-	for (i = 0; i < EEPROM_CHECKSUM_REG * 2; i += 2)
-		csum_new += data[i] + (data[i + 1] << 8);
-	csum_new = EEPROM_SUM - csum_new;
-
-	pr_err("/*********************/\n");
-	pr_err("Current EEPROM Checksum : 0x%04x\n", csum_old);
-	pr_err("Calculated              : 0x%04x\n", csum_new);
-
-	pr_err("Offset    Values\n");
-	pr_err("========  ======\n");
-	print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, data, 128, 0);
-
-	pr_err("Include this output when contacting your support provider.\n");
-	pr_err("This is not a software error! Something bad happened to\n");
-	pr_err("your hardware or EEPROM image. Ignoring this problem could\n");
-	pr_err("result in further problems, possibly loss of data,\n");
-	pr_err("corruption or system hangs!\n");
-	pr_err("The MAC Address will be reset to 00:00:00:00:00:00,\n");
-	pr_err("which is invalid and requires you to set the proper MAC\n");
-	pr_err("address manually before continuing to enable this network\n");
-	pr_err("device. Please inspect the EEPROM dump and report the\n");
-	pr_err("issue to your hardware vendor or Intel Customer Support.\n");
-	pr_err("/*********************/\n");
-
-	kfree(data);
-}
-
-/**
- * e1000_is_need_ioport - determine if an adapter needs ioport resources or not
- * @pdev: PCI device information struct
- *
- * Return true if an adapter needs ioport resources
- **/
-static int e1000_is_need_ioport(struct pci_dev *pdev)
-{
-	switch (pdev->device) {
-	case E1000_DEV_ID_82540EM:
-	case E1000_DEV_ID_82540EM_LOM:
-	case E1000_DEV_ID_82540EP:
-	case E1000_DEV_ID_82540EP_LOM:
-	case E1000_DEV_ID_82540EP_LP:
-	case E1000_DEV_ID_82541EI:
-	case E1000_DEV_ID_82541EI_MOBILE:
-	case E1000_DEV_ID_82541ER:
-	case E1000_DEV_ID_82541ER_LOM:
-	case E1000_DEV_ID_82541GI:
-	case E1000_DEV_ID_82541GI_LF:
-	case E1000_DEV_ID_82541GI_MOBILE:
-	case E1000_DEV_ID_82544EI_COPPER:
-	case E1000_DEV_ID_82544EI_FIBER:
-	case E1000_DEV_ID_82544GC_COPPER:
-	case E1000_DEV_ID_82544GC_LOM:
-	case E1000_DEV_ID_82545EM_COPPER:
-	case E1000_DEV_ID_82545EM_FIBER:
-	case E1000_DEV_ID_82546EB_COPPER:
-	case E1000_DEV_ID_82546EB_FIBER:
-	case E1000_DEV_ID_82546EB_QUAD_COPPER:
-		return true;
-	default:
-		return false;
-	}
-}
-
-static u32 e1000_fix_features(struct net_device *netdev, u32 features)
-{
-	/*
-	 * Since there is no support for separate rx/tx vlan accel
-	 * enable/disable make sure tx flag is always in same state as rx.
-	 */
-	if (features & NETIF_F_HW_VLAN_RX)
-		features |= NETIF_F_HW_VLAN_TX;
-	else
-		features &= ~NETIF_F_HW_VLAN_TX;
-
-	return features;
-}
-
-static int e1000_set_features(struct net_device *netdev, u32 features)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	u32 changed = features ^ netdev->features;
-
-	if (changed & NETIF_F_HW_VLAN_RX)
-		e1000_vlan_mode(netdev, features);
-
-	if (!(changed & NETIF_F_RXCSUM))
-		return 0;
-
-	adapter->rx_csum = !!(features & NETIF_F_RXCSUM);
-
-	if (netif_running(netdev))
-		e1000_reinit_locked(adapter);
-	else
-		e1000_reset(adapter);
-
-	return 0;
-}
-
-static const struct net_device_ops e1000_netdev_ops = {
-	.ndo_open		= e1000_open,
-	.ndo_stop		= e1000_close,
-	.ndo_start_xmit		= e1000_xmit_frame,
-	.ndo_get_stats		= e1000_get_stats,
-	.ndo_set_rx_mode	= e1000_set_rx_mode,
-	.ndo_set_mac_address	= e1000_set_mac,
-	.ndo_tx_timeout		= e1000_tx_timeout,
-	.ndo_change_mtu		= e1000_change_mtu,
-	.ndo_do_ioctl		= e1000_ioctl,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_vlan_rx_add_vid	= e1000_vlan_rx_add_vid,
-	.ndo_vlan_rx_kill_vid	= e1000_vlan_rx_kill_vid,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= e1000_netpoll,
-#endif
-	.ndo_fix_features	= e1000_fix_features,
-	.ndo_set_features	= e1000_set_features,
-};
-
-/**
- * e1000_init_hw_struct - initialize members of hw struct
- * @adapter: board private struct
- * @hw: structure used by e1000_hw.c
- *
- * Factors out initialization of the e1000_hw struct to its own function
- * that can be called very early at init (just after struct allocation).
- * Fields are initialized based on PCI device information and
- * OS network device settings (MTU size).
- * Returns negative error codes if MAC type setup fails.
- */
-static int e1000_init_hw_struct(struct e1000_adapter *adapter,
-				struct e1000_hw *hw)
-{
-	struct pci_dev *pdev = adapter->pdev;
-
-	/* PCI config space info */
-	hw->vendor_id = pdev->vendor;
-	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_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
-
-	hw->max_frame_size = adapter->netdev->mtu +
-			     ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
-	hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
-
-	/* identify the MAC */
-	if (e1000_set_mac_type(hw)) {
-		e_err(probe, "Unknown MAC Type\n");
-		return -EIO;
-	}
-
-	switch (hw->mac_type) {
-	default:
-		break;
-	case e1000_82541:
-	case e1000_82547:
-	case e1000_82541_rev_2:
-	case e1000_82547_rev_2:
-		hw->phy_init_script = 1;
-		break;
-	}
-
-	e1000_set_media_type(hw);
-	e1000_get_bus_info(hw);
-
-	hw->wait_autoneg_complete = false;
-	hw->tbi_compatibility_en = true;
-	hw->adaptive_ifs = true;
-
-	/* Copper options */
-
-	if (hw->media_type == e1000_media_type_copper) {
-		hw->mdix = AUTO_ALL_MODES;
-		hw->disable_polarity_correction = false;
-		hw->master_slave = E1000_MASTER_SLAVE;
-	}
-
-	return 0;
-}
-
-/**
- * e1000_probe - Device Initialization Routine
- * @pdev: PCI device information struct
- * @ent: entry in e1000_pci_tbl
- *
- * Returns 0 on success, negative on failure
- *
- * e1000_probe initializes an adapter identified by a pci_dev structure.
- * The OS initialization, configuring of the adapter private structure,
- * and a hardware reset occur.
- **/
-static int __devinit e1000_probe(struct pci_dev *pdev,
-				 const struct pci_device_id *ent)
-{
-	struct net_device *netdev;
-	struct e1000_adapter *adapter;
-	struct e1000_hw *hw;
-
-	static int cards_found = 0;
-	static int global_quad_port_a = 0; /* global ksp3 port a indication */
-	int i, err, pci_using_dac;
-	u16 eeprom_data = 0;
-	u16 tmp = 0;
-	u16 eeprom_apme_mask = E1000_EEPROM_APME;
-	int bars, need_ioport;
-
-	/* do not allocate ioport bars when not needed */
-	need_ioport = e1000_is_need_ioport(pdev);
-	if (need_ioport) {
-		bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
-		err = pci_enable_device(pdev);
-	} else {
-		bars = pci_select_bars(pdev, IORESOURCE_MEM);
-		err = pci_enable_device_mem(pdev);
-	}
-	if (err)
-		return err;
-
-	err = pci_request_selected_regions(pdev, bars, e1000_driver_name);
-	if (err)
-		goto err_pci_reg;
-
-	pci_set_master(pdev);
-	err = pci_save_state(pdev);
-	if (err)
-		goto err_alloc_etherdev;
-
-	err = -ENOMEM;
-	netdev = alloc_etherdev(sizeof(struct e1000_adapter));
-	if (!netdev)
-		goto err_alloc_etherdev;
-
-	SET_NETDEV_DEV(netdev, &pdev->dev);
-
-	pci_set_drvdata(pdev, netdev);
-	adapter = netdev_priv(netdev);
-	adapter->netdev = netdev;
-	adapter->pdev = pdev;
-	adapter->msg_enable = (1 << debug) - 1;
-	adapter->bars = bars;
-	adapter->need_ioport = need_ioport;
-
-	hw = &adapter->hw;
-	hw->back = adapter;
-
-	err = -EIO;
-	hw->hw_addr = pci_ioremap_bar(pdev, BAR_0);
-	if (!hw->hw_addr)
-		goto err_ioremap;
-
-	if (adapter->need_ioport) {
-		for (i = BAR_1; i <= BAR_5; i++) {
-			if (pci_resource_len(pdev, i) == 0)
-				continue;
-			if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
-				hw->io_base = pci_resource_start(pdev, i);
-				break;
-			}
-		}
-	}
-
-	/* make ready for any if (hw->...) below */
-	err = e1000_init_hw_struct(adapter, hw);
-	if (err)
-		goto err_sw_init;
-
-	/*
-	 * there is a workaround being applied below that limits
-	 * 64-bit DMA addresses to 64-bit hardware.  There are some
-	 * 32-bit adapters that Tx hang when given 64-bit DMA addresses
-	 */
-	pci_using_dac = 0;
-	if ((hw->bus_type == e1000_bus_type_pcix) &&
-	    !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
-		/*
-		 * according to DMA-API-HOWTO, coherent calls will always
-		 * succeed if the set call did
-		 */
-		dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
-		pci_using_dac = 1;
-	} else {
-		err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
-		if (err) {
-			pr_err("No usable DMA config, aborting\n");
-			goto err_dma;
-		}
-		dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
-	}
-
-	netdev->netdev_ops = &e1000_netdev_ops;
-	e1000_set_ethtool_ops(netdev);
-	netdev->watchdog_timeo = 5 * HZ;
-	netif_napi_add(netdev, &adapter->napi, e1000_clean, 64);
-
-	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
-
-	adapter->bd_number = cards_found;
-
-	/* setup the private structure */
-
-	err = e1000_sw_init(adapter);
-	if (err)
-		goto err_sw_init;
-
-	err = -EIO;
-	if (hw->mac_type == e1000_ce4100) {
-		ce4100_gbe_mdio_base_phy = pci_resource_start(pdev, BAR_1);
-		ce4100_gbe_mdio_base_virt = ioremap(ce4100_gbe_mdio_base_phy,
-		                                pci_resource_len(pdev, BAR_1));
-
-		if (!ce4100_gbe_mdio_base_virt)
-			goto err_mdio_ioremap;
-	}
-
-	if (hw->mac_type >= e1000_82543) {
-		netdev->hw_features = NETIF_F_SG |
-				   NETIF_F_HW_CSUM |
-				   NETIF_F_HW_VLAN_RX;
-		netdev->features = NETIF_F_HW_VLAN_TX |
-				   NETIF_F_HW_VLAN_FILTER;
-	}
-
-	if ((hw->mac_type >= e1000_82544) &&
-	   (hw->mac_type != e1000_82547))
-		netdev->hw_features |= NETIF_F_TSO;
-
-	netdev->features |= netdev->hw_features;
-	netdev->hw_features |= NETIF_F_RXCSUM;
-
-	if (pci_using_dac) {
-		netdev->features |= NETIF_F_HIGHDMA;
-		netdev->vlan_features |= NETIF_F_HIGHDMA;
-	}
-
-	netdev->vlan_features |= NETIF_F_TSO;
-	netdev->vlan_features |= NETIF_F_HW_CSUM;
-	netdev->vlan_features |= NETIF_F_SG;
-
-	adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw);
-
-	/* initialize eeprom parameters */
-	if (e1000_init_eeprom_params(hw)) {
-		e_err(probe, "EEPROM initialization failed\n");
-		goto err_eeprom;
-	}
-
-	/* before reading the EEPROM, reset the controller to
-	 * put the device in a known good starting state */
-
-	e1000_reset_hw(hw);
-
-	/* make sure the EEPROM is good */
-	if (e1000_validate_eeprom_checksum(hw) < 0) {
-		e_err(probe, "The EEPROM Checksum Is Not Valid\n");
-		e1000_dump_eeprom(adapter);
-		/*
-		 * set MAC address to all zeroes to invalidate and temporary
-		 * disable this device for the user. This blocks regular
-		 * traffic while still permitting ethtool ioctls from reaching
-		 * the hardware as well as allowing the user to run the
-		 * interface after manually setting a hw addr using
-		 * `ip set address`
-		 */
-		memset(hw->mac_addr, 0, netdev->addr_len);
-	} else {
-		/* copy the MAC address out of the EEPROM */
-		if (e1000_read_mac_addr(hw))
-			e_err(probe, "EEPROM Read Error\n");
-	}
-	/* don't block initalization here due to bad MAC address */
-	memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len);
-	memcpy(netdev->perm_addr, hw->mac_addr, netdev->addr_len);
-
-	if (!is_valid_ether_addr(netdev->perm_addr))
-		e_err(probe, "Invalid MAC Address\n");
-
-	init_timer(&adapter->tx_fifo_stall_timer);
-	adapter->tx_fifo_stall_timer.function = e1000_82547_tx_fifo_stall;
-	adapter->tx_fifo_stall_timer.data = (unsigned long)adapter;
-
-	init_timer(&adapter->watchdog_timer);
-	adapter->watchdog_timer.function = e1000_watchdog;
-	adapter->watchdog_timer.data = (unsigned long) adapter;
-
-	init_timer(&adapter->phy_info_timer);
-	adapter->phy_info_timer.function = e1000_update_phy_info;
-	adapter->phy_info_timer.data = (unsigned long)adapter;
-
-	INIT_WORK(&adapter->fifo_stall_task, e1000_82547_tx_fifo_stall_task);
-	INIT_WORK(&adapter->reset_task, e1000_reset_task);
-	INIT_WORK(&adapter->phy_info_task, e1000_update_phy_info_task);
-
-	e1000_check_options(adapter);
-
-	/* Initial Wake on LAN setting
-	 * If APM wake is enabled in the EEPROM,
-	 * enable the ACPI Magic Packet filter
-	 */
-
-	switch (hw->mac_type) {
-	case e1000_82542_rev2_0:
-	case e1000_82542_rev2_1:
-	case e1000_82543:
-		break;
-	case e1000_82544:
-		e1000_read_eeprom(hw,
-			EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
-		eeprom_apme_mask = E1000_EEPROM_82544_APM;
-		break;
-	case e1000_82546:
-	case e1000_82546_rev_3:
-		if (er32(STATUS) & E1000_STATUS_FUNC_1){
-			e1000_read_eeprom(hw,
-				EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
-			break;
-		}
-		/* Fall Through */
-	default:
-		e1000_read_eeprom(hw,
-			EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
-		break;
-	}
-	if (eeprom_data & eeprom_apme_mask)
-		adapter->eeprom_wol |= E1000_WUFC_MAG;
-
-	/* now that we have the eeprom settings, apply the special cases
-	 * where the eeprom may be wrong or the board simply won't support
-	 * wake on lan on a particular port */
-	switch (pdev->device) {
-	case E1000_DEV_ID_82546GB_PCIE:
-		adapter->eeprom_wol = 0;
-		break;
-	case E1000_DEV_ID_82546EB_FIBER:
-	case E1000_DEV_ID_82546GB_FIBER:
-		/* Wake events only supported on port A for dual fiber
-		 * regardless of eeprom setting */
-		if (er32(STATUS) & E1000_STATUS_FUNC_1)
-			adapter->eeprom_wol = 0;
-		break;
-	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
-		/* if quad port adapter, disable WoL on all but port A */
-		if (global_quad_port_a != 0)
-			adapter->eeprom_wol = 0;
-		else
-			adapter->quad_port_a = 1;
-		/* Reset for multiple quad port adapters */
-		if (++global_quad_port_a == 4)
-			global_quad_port_a = 0;
-		break;
-	}
-
-	/* initialize the wol settings based on the eeprom settings */
-	adapter->wol = adapter->eeprom_wol;
-	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
-
-	/* Auto detect PHY address */
-	if (hw->mac_type == e1000_ce4100) {
-		for (i = 0; i < 32; i++) {
-			hw->phy_addr = i;
-			e1000_read_phy_reg(hw, PHY_ID2, &tmp);
-			if (tmp == 0 || tmp == 0xFF) {
-				if (i == 31)
-					goto err_eeprom;
-				continue;
-			} else
-				break;
-		}
-	}
-
-	/* reset the hardware with the new settings */
-	e1000_reset(adapter);
-
-	strcpy(netdev->name, "eth%d");
-	err = register_netdev(netdev);
-	if (err)
-		goto err_register;
-
-	e1000_vlan_mode(netdev, netdev->features);
-
-	/* print bus type/speed/width info */
-	e_info(probe, "(PCI%s:%dMHz:%d-bit) %pM\n",
-	       ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
-	       ((hw->bus_speed == e1000_bus_speed_133) ? 133 :
-		(hw->bus_speed == e1000_bus_speed_120) ? 120 :
-		(hw->bus_speed == e1000_bus_speed_100) ? 100 :
-		(hw->bus_speed == e1000_bus_speed_66) ? 66 : 33),
-	       ((hw->bus_width == e1000_bus_width_64) ? 64 : 32),
-	       netdev->dev_addr);
-
-	/* carrier off reporting is important to ethtool even BEFORE open */
-	netif_carrier_off(netdev);
-
-	e_info(probe, "Intel(R) PRO/1000 Network Connection\n");
-
-	cards_found++;
-	return 0;
-
-err_register:
-err_eeprom:
-	e1000_phy_hw_reset(hw);
-
-	if (hw->flash_address)
-		iounmap(hw->flash_address);
-	kfree(adapter->tx_ring);
-	kfree(adapter->rx_ring);
-err_dma:
-err_sw_init:
-err_mdio_ioremap:
-	iounmap(ce4100_gbe_mdio_base_virt);
-	iounmap(hw->hw_addr);
-err_ioremap:
-	free_netdev(netdev);
-err_alloc_etherdev:
-	pci_release_selected_regions(pdev, bars);
-err_pci_reg:
-	pci_disable_device(pdev);
-	return err;
-}
-
-/**
- * e1000_remove - Device Removal Routine
- * @pdev: PCI device information struct
- *
- * e1000_remove is called by the PCI subsystem to alert the driver
- * that it should release a PCI device.  The could be caused by a
- * Hot-Plug event, or because the driver is going to be removed from
- * memory.
- **/
-
-static void __devexit e1000_remove(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	set_bit(__E1000_DOWN, &adapter->flags);
-	del_timer_sync(&adapter->tx_fifo_stall_timer);
-	del_timer_sync(&adapter->watchdog_timer);
-	del_timer_sync(&adapter->phy_info_timer);
-
-	cancel_work_sync(&adapter->reset_task);
-
-	e1000_release_manageability(adapter);
-
-	unregister_netdev(netdev);
-
-	e1000_phy_hw_reset(hw);
-
-	kfree(adapter->tx_ring);
-	kfree(adapter->rx_ring);
-
-	iounmap(hw->hw_addr);
-	if (hw->flash_address)
-		iounmap(hw->flash_address);
-	pci_release_selected_regions(pdev, adapter->bars);
-
-	free_netdev(netdev);
-
-	pci_disable_device(pdev);
-}
-
-/**
- * e1000_sw_init - Initialize general software structures (struct e1000_adapter)
- * @adapter: board private structure to initialize
- *
- * e1000_sw_init initializes the Adapter private data structure.
- * e1000_init_hw_struct MUST be called before this function
- **/
-
-static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
-{
-	adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
-
-	adapter->num_tx_queues = 1;
-	adapter->num_rx_queues = 1;
-
-	if (e1000_alloc_queues(adapter)) {
-		e_err(probe, "Unable to allocate memory for queues\n");
-		return -ENOMEM;
-	}
-
-	/* Explicitly disable IRQ since the NIC can be in any state. */
-	e1000_irq_disable(adapter);
-
-	spin_lock_init(&adapter->stats_lock);
-
-	set_bit(__E1000_DOWN, &adapter->flags);
-
-	return 0;
-}
-
-/**
- * e1000_alloc_queues - Allocate memory for all rings
- * @adapter: board private structure to initialize
- *
- * We allocate one ring per queue at run-time since we don't know the
- * number of queues at compile-time.
- **/
-
-static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
-{
-	adapter->tx_ring = kcalloc(adapter->num_tx_queues,
-	                           sizeof(struct e1000_tx_ring), GFP_KERNEL);
-	if (!adapter->tx_ring)
-		return -ENOMEM;
-
-	adapter->rx_ring = kcalloc(adapter->num_rx_queues,
-	                           sizeof(struct e1000_rx_ring), GFP_KERNEL);
-	if (!adapter->rx_ring) {
-		kfree(adapter->tx_ring);
-		return -ENOMEM;
-	}
-
-	return E1000_SUCCESS;
-}
-
-/**
- * e1000_open - Called when a network interface is made active
- * @netdev: network interface device structure
- *
- * Returns 0 on success, negative value on failure
- *
- * 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.
- **/
-
-static int e1000_open(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	int err;
-
-	/* disallow open during test */
-	if (test_bit(__E1000_TESTING, &adapter->flags))
-		return -EBUSY;
-
-	netif_carrier_off(netdev);
-
-	/* allocate transmit descriptors */
-	err = e1000_setup_all_tx_resources(adapter);
-	if (err)
-		goto err_setup_tx;
-
-	/* allocate receive descriptors */
-	err = e1000_setup_all_rx_resources(adapter);
-	if (err)
-		goto err_setup_rx;
-
-	e1000_power_up_phy(adapter);
-
-	adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
-	if ((hw->mng_cookie.status &
-			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
-		e1000_update_mng_vlan(adapter);
-	}
-
-	/* before we allocate an interrupt, we must be ready to handle it.
-	 * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
-	 * as soon as we call pci_request_irq, so we have to setup our
-	 * clean_rx handler before we do so.  */
-	e1000_configure(adapter);
-
-	err = e1000_request_irq(adapter);
-	if (err)
-		goto err_req_irq;
-
-	/* From here on the code is the same as e1000_up() */
-	clear_bit(__E1000_DOWN, &adapter->flags);
-
-	napi_enable(&adapter->napi);
-
-	e1000_irq_enable(adapter);
-
-	netif_start_queue(netdev);
-
-	/* fire a link status change interrupt to start the watchdog */
-	ew32(ICS, E1000_ICS_LSC);
-
-	return E1000_SUCCESS;
-
-err_req_irq:
-	e1000_power_down_phy(adapter);
-	e1000_free_all_rx_resources(adapter);
-err_setup_rx:
-	e1000_free_all_tx_resources(adapter);
-err_setup_tx:
-	e1000_reset(adapter);
-
-	return err;
-}
-
-/**
- * e1000_close - Disables a network interface
- * @netdev: network interface device structure
- *
- * 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.
- **/
-
-static int e1000_close(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
-	e1000_down(adapter);
-	e1000_power_down_phy(adapter);
-	e1000_free_irq(adapter);
-
-	e1000_free_all_tx_resources(adapter);
-	e1000_free_all_rx_resources(adapter);
-
-	/* kill manageability vlan ID if supported, but not if a vlan with
-	 * the same ID is registered on the host OS (let 8021q kill it) */
-	if ((hw->mng_cookie.status &
-			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
-	     !test_bit(adapter->mng_vlan_id, adapter->active_vlans)) {
-		e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
-	}
-
-	return 0;
-}
-
-/**
- * e1000_check_64k_bound - check that memory doesn't cross 64kB boundary
- * @adapter: address of board private structure
- * @start: address of beginning of memory
- * @len: length of memory
- **/
-static bool e1000_check_64k_bound(struct e1000_adapter *adapter, void *start,
-				  unsigned long len)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	unsigned long begin = (unsigned long)start;
-	unsigned long end = begin + len;
-
-	/* First rev 82545 and 82546 need to not allow any memory
-	 * write location to cross 64k boundary due to errata 23 */
-	if (hw->mac_type == e1000_82545 ||
-	    hw->mac_type == e1000_ce4100 ||
-	    hw->mac_type == e1000_82546) {
-		return ((begin ^ (end - 1)) >> 16) != 0 ? false : true;
-	}
-
-	return true;
-}
-
-/**
- * e1000_setup_tx_resources - allocate Tx resources (Descriptors)
- * @adapter: board private structure
- * @txdr:    tx descriptor ring (for a specific queue) to setup
- *
- * Return 0 on success, negative on failure
- **/
-
-static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
-				    struct e1000_tx_ring *txdr)
-{
-	struct pci_dev *pdev = adapter->pdev;
-	int size;
-
-	size = sizeof(struct e1000_buffer) * txdr->count;
-	txdr->buffer_info = vzalloc(size);
-	if (!txdr->buffer_info) {
-		e_err(probe, "Unable to allocate memory for the Tx descriptor "
-		      "ring\n");
-		return -ENOMEM;
-	}
-
-	/* round up to nearest 4K */
-
-	txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
-	txdr->size = ALIGN(txdr->size, 4096);
-
-	txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
-					GFP_KERNEL);
-	if (!txdr->desc) {
-setup_tx_desc_die:
-		vfree(txdr->buffer_info);
-		e_err(probe, "Unable to allocate memory for the Tx descriptor "
-		      "ring\n");
-		return -ENOMEM;
-	}
-
-	/* Fix for errata 23, can't cross 64kB boundary */
-	if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) {
-		void *olddesc = txdr->desc;
-		dma_addr_t olddma = txdr->dma;
-		e_err(tx_err, "txdr align check failed: %u bytes at %p\n",
-		      txdr->size, txdr->desc);
-		/* Try again, without freeing the previous */
-		txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size,
-						&txdr->dma, GFP_KERNEL);
-		/* Failed allocation, critical failure */
-		if (!txdr->desc) {
-			dma_free_coherent(&pdev->dev, txdr->size, olddesc,
-					  olddma);
-			goto setup_tx_desc_die;
-		}
-
-		if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) {
-			/* give up */
-			dma_free_coherent(&pdev->dev, txdr->size, txdr->desc,
-					  txdr->dma);
-			dma_free_coherent(&pdev->dev, txdr->size, olddesc,
-					  olddma);
-			e_err(probe, "Unable to allocate aligned memory "
-			      "for the transmit descriptor ring\n");
-			vfree(txdr->buffer_info);
-			return -ENOMEM;
-		} else {
-			/* Free old allocation, new allocation was successful */
-			dma_free_coherent(&pdev->dev, txdr->size, olddesc,
-					  olddma);
-		}
-	}
-	memset(txdr->desc, 0, txdr->size);
-
-	txdr->next_to_use = 0;
-	txdr->next_to_clean = 0;
-
-	return 0;
-}
-
-/**
- * e1000_setup_all_tx_resources - wrapper to allocate Tx resources
- * 				  (Descriptors) for all queues
- * @adapter: board private structure
- *
- * Return 0 on success, negative on failure
- **/
-
-int e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
-{
-	int i, err = 0;
-
-	for (i = 0; i < adapter->num_tx_queues; i++) {
-		err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]);
-		if (err) {
-			e_err(probe, "Allocation for Tx Queue %u failed\n", i);
-			for (i-- ; i >= 0; i--)
-				e1000_free_tx_resources(adapter,
-							&adapter->tx_ring[i]);
-			break;
-		}
-	}
-
-	return err;
-}
-
-/**
- * e1000_configure_tx - Configure 8254x Transmit Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Tx unit of the MAC after a reset.
- **/
-
-static void e1000_configure_tx(struct e1000_adapter *adapter)
-{
-	u64 tdba;
-	struct e1000_hw *hw = &adapter->hw;
-	u32 tdlen, tctl, tipg;
-	u32 ipgr1, ipgr2;
-
-	/* Setup the HW Tx Head and Tail descriptor pointers */
-
-	switch (adapter->num_tx_queues) {
-	case 1:
-	default:
-		tdba = adapter->tx_ring[0].dma;
-		tdlen = adapter->tx_ring[0].count *
-			sizeof(struct e1000_tx_desc);
-		ew32(TDLEN, tdlen);
-		ew32(TDBAH, (tdba >> 32));
-		ew32(TDBAL, (tdba & 0x00000000ffffffffULL));
-		ew32(TDT, 0);
-		ew32(TDH, 0);
-		adapter->tx_ring[0].tdh = ((hw->mac_type >= e1000_82543) ? E1000_TDH : E1000_82542_TDH);
-		adapter->tx_ring[0].tdt = ((hw->mac_type >= e1000_82543) ? E1000_TDT : E1000_82542_TDT);
-		break;
-	}
-
-	/* Set the default values for the Tx Inter Packet Gap timer */
-	if ((hw->media_type == e1000_media_type_fiber ||
-	     hw->media_type == e1000_media_type_internal_serdes))
-		tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
-	else
-		tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
-
-	switch (hw->mac_type) {
-	case e1000_82542_rev2_0:
-	case e1000_82542_rev2_1:
-		tipg = DEFAULT_82542_TIPG_IPGT;
-		ipgr1 = DEFAULT_82542_TIPG_IPGR1;
-		ipgr2 = DEFAULT_82542_TIPG_IPGR2;
-		break;
-	default:
-		ipgr1 = DEFAULT_82543_TIPG_IPGR1;
-		ipgr2 = DEFAULT_82543_TIPG_IPGR2;
-		break;
-	}
-	tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT;
-	tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT;
-	ew32(TIPG, tipg);
-
-	/* Set the Tx Interrupt Delay register */
-
-	ew32(TIDV, adapter->tx_int_delay);
-	if (hw->mac_type >= e1000_82540)
-		ew32(TADV, adapter->tx_abs_int_delay);
-
-	/* Program the Transmit Control Register */
-
-	tctl = er32(TCTL);
-	tctl &= ~E1000_TCTL_CT;
-	tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
-		(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
-
-	e1000_config_collision_dist(hw);
-
-	/* Setup Transmit Descriptor Settings for eop descriptor */
-	adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS;
-
-	/* only set IDE if we are delaying interrupts using the timers */
-	if (adapter->tx_int_delay)
-		adapter->txd_cmd |= E1000_TXD_CMD_IDE;
-
-	if (hw->mac_type < e1000_82543)
-		adapter->txd_cmd |= E1000_TXD_CMD_RPS;
-	else
-		adapter->txd_cmd |= E1000_TXD_CMD_RS;
-
-	/* Cache if we're 82544 running in PCI-X because we'll
-	 * need this to apply a workaround later in the send path. */
-	if (hw->mac_type == e1000_82544 &&
-	    hw->bus_type == e1000_bus_type_pcix)
-		adapter->pcix_82544 = 1;
-
-	ew32(TCTL, tctl);
-
-}
-
-/**
- * e1000_setup_rx_resources - allocate Rx resources (Descriptors)
- * @adapter: board private structure
- * @rxdr:    rx descriptor ring (for a specific queue) to setup
- *
- * Returns 0 on success, negative on failure
- **/
-
-static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
-				    struct e1000_rx_ring *rxdr)
-{
-	struct pci_dev *pdev = adapter->pdev;
-	int size, desc_len;
-
-	size = sizeof(struct e1000_buffer) * rxdr->count;
-	rxdr->buffer_info = vzalloc(size);
-	if (!rxdr->buffer_info) {
-		e_err(probe, "Unable to allocate memory for the Rx descriptor "
-		      "ring\n");
-		return -ENOMEM;
-	}
-
-	desc_len = sizeof(struct e1000_rx_desc);
-
-	/* Round up to nearest 4K */
-
-	rxdr->size = rxdr->count * desc_len;
-	rxdr->size = ALIGN(rxdr->size, 4096);
-
-	rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
-					GFP_KERNEL);
-
-	if (!rxdr->desc) {
-		e_err(probe, "Unable to allocate memory for the Rx descriptor "
-		      "ring\n");
-setup_rx_desc_die:
-		vfree(rxdr->buffer_info);
-		return -ENOMEM;
-	}
-
-	/* Fix for errata 23, can't cross 64kB boundary */
-	if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
-		void *olddesc = rxdr->desc;
-		dma_addr_t olddma = rxdr->dma;
-		e_err(rx_err, "rxdr align check failed: %u bytes at %p\n",
-		      rxdr->size, rxdr->desc);
-		/* Try again, without freeing the previous */
-		rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size,
-						&rxdr->dma, GFP_KERNEL);
-		/* Failed allocation, critical failure */
-		if (!rxdr->desc) {
-			dma_free_coherent(&pdev->dev, rxdr->size, olddesc,
-					  olddma);
-			e_err(probe, "Unable to allocate memory for the Rx "
-			      "descriptor ring\n");
-			goto setup_rx_desc_die;
-		}
-
-		if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
-			/* give up */
-			dma_free_coherent(&pdev->dev, rxdr->size, rxdr->desc,
-					  rxdr->dma);
-			dma_free_coherent(&pdev->dev, rxdr->size, olddesc,
-					  olddma);
-			e_err(probe, "Unable to allocate aligned memory for "
-			      "the Rx descriptor ring\n");
-			goto setup_rx_desc_die;
-		} else {
-			/* Free old allocation, new allocation was successful */
-			dma_free_coherent(&pdev->dev, rxdr->size, olddesc,
-					  olddma);
-		}
-	}
-	memset(rxdr->desc, 0, rxdr->size);
-
-	rxdr->next_to_clean = 0;
-	rxdr->next_to_use = 0;
-	rxdr->rx_skb_top = NULL;
-
-	return 0;
-}
-
-/**
- * e1000_setup_all_rx_resources - wrapper to allocate Rx resources
- * 				  (Descriptors) for all queues
- * @adapter: board private structure
- *
- * Return 0 on success, negative on failure
- **/
-
-int e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
-{
-	int i, err = 0;
-
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]);
-		if (err) {
-			e_err(probe, "Allocation for Rx Queue %u failed\n", i);
-			for (i-- ; i >= 0; i--)
-				e1000_free_rx_resources(adapter,
-							&adapter->rx_ring[i]);
-			break;
-		}
-	}
-
-	return err;
-}
-
-/**
- * e1000_setup_rctl - configure the receive control registers
- * @adapter: Board private structure
- **/
-static void e1000_setup_rctl(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 rctl;
-
-	rctl = er32(RCTL);
-
-	rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
-
-	rctl |= E1000_RCTL_EN | E1000_RCTL_BAM |
-		E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
-		(hw->mc_filter_type << E1000_RCTL_MO_SHIFT);
-
-	if (hw->tbi_compatibility_on == 1)
-		rctl |= E1000_RCTL_SBP;
-	else
-		rctl &= ~E1000_RCTL_SBP;
-
-	if (adapter->netdev->mtu <= ETH_DATA_LEN)
-		rctl &= ~E1000_RCTL_LPE;
-	else
-		rctl |= E1000_RCTL_LPE;
-
-	/* Setup buffer sizes */
-	rctl &= ~E1000_RCTL_SZ_4096;
-	rctl |= E1000_RCTL_BSEX;
-	switch (adapter->rx_buffer_len) {
-		case E1000_RXBUFFER_2048:
-		default:
-			rctl |= E1000_RCTL_SZ_2048;
-			rctl &= ~E1000_RCTL_BSEX;
-			break;
-		case E1000_RXBUFFER_4096:
-			rctl |= E1000_RCTL_SZ_4096;
-			break;
-		case E1000_RXBUFFER_8192:
-			rctl |= E1000_RCTL_SZ_8192;
-			break;
-		case E1000_RXBUFFER_16384:
-			rctl |= E1000_RCTL_SZ_16384;
-			break;
-	}
-
-	ew32(RCTL, rctl);
-}
-
-/**
- * e1000_configure_rx - Configure 8254x Receive Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Rx unit of the MAC after a reset.
- **/
-
-static void e1000_configure_rx(struct e1000_adapter *adapter)
-{
-	u64 rdba;
-	struct e1000_hw *hw = &adapter->hw;
-	u32 rdlen, rctl, rxcsum;
-
-	if (adapter->netdev->mtu > ETH_DATA_LEN) {
-		rdlen = adapter->rx_ring[0].count *
-		        sizeof(struct e1000_rx_desc);
-		adapter->clean_rx = e1000_clean_jumbo_rx_irq;
-		adapter->alloc_rx_buf = e1000_alloc_jumbo_rx_buffers;
-	} else {
-		rdlen = adapter->rx_ring[0].count *
-		        sizeof(struct e1000_rx_desc);
-		adapter->clean_rx = e1000_clean_rx_irq;
-		adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
-	}
-
-	/* disable receives while setting up the descriptors */
-	rctl = er32(RCTL);
-	ew32(RCTL, rctl & ~E1000_RCTL_EN);
-
-	/* set the Receive Delay Timer Register */
-	ew32(RDTR, adapter->rx_int_delay);
-
-	if (hw->mac_type >= e1000_82540) {
-		ew32(RADV, adapter->rx_abs_int_delay);
-		if (adapter->itr_setting != 0)
-			ew32(ITR, 1000000000 / (adapter->itr * 256));
-	}
-
-	/* Setup the HW Rx Head and Tail Descriptor Pointers and
-	 * the Base and Length of the Rx Descriptor Ring */
-	switch (adapter->num_rx_queues) {
-	case 1:
-	default:
-		rdba = adapter->rx_ring[0].dma;
-		ew32(RDLEN, rdlen);
-		ew32(RDBAH, (rdba >> 32));
-		ew32(RDBAL, (rdba & 0x00000000ffffffffULL));
-		ew32(RDT, 0);
-		ew32(RDH, 0);
-		adapter->rx_ring[0].rdh = ((hw->mac_type >= e1000_82543) ? E1000_RDH : E1000_82542_RDH);
-		adapter->rx_ring[0].rdt = ((hw->mac_type >= e1000_82543) ? E1000_RDT : E1000_82542_RDT);
-		break;
-	}
-
-	/* Enable 82543 Receive Checksum Offload for TCP and UDP */
-	if (hw->mac_type >= e1000_82543) {
-		rxcsum = er32(RXCSUM);
-		if (adapter->rx_csum)
-			rxcsum |= E1000_RXCSUM_TUOFL;
-		else
-			/* don't need to clear IPPCSE as it defaults to 0 */
-			rxcsum &= ~E1000_RXCSUM_TUOFL;
-		ew32(RXCSUM, rxcsum);
-	}
-
-	/* Enable Receives */
-	ew32(RCTL, rctl);
-}
-
-/**
- * e1000_free_tx_resources - Free Tx Resources per Queue
- * @adapter: board private structure
- * @tx_ring: Tx descriptor ring for a specific queue
- *
- * Free all transmit software resources
- **/
-
-static void e1000_free_tx_resources(struct e1000_adapter *adapter,
-				    struct e1000_tx_ring *tx_ring)
-{
-	struct pci_dev *pdev = adapter->pdev;
-
-	e1000_clean_tx_ring(adapter, tx_ring);
-
-	vfree(tx_ring->buffer_info);
-	tx_ring->buffer_info = NULL;
-
-	dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc,
-			  tx_ring->dma);
-
-	tx_ring->desc = NULL;
-}
-
-/**
- * e1000_free_all_tx_resources - Free Tx Resources for All Queues
- * @adapter: board private structure
- *
- * Free all transmit software resources
- **/
-
-void e1000_free_all_tx_resources(struct e1000_adapter *adapter)
-{
-	int i;
-
-	for (i = 0; i < adapter->num_tx_queues; i++)
-		e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
-}
-
-static void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
-					     struct e1000_buffer *buffer_info)
-{
-	if (buffer_info->dma) {
-		if (buffer_info->mapped_as_page)
-			dma_unmap_page(&adapter->pdev->dev, buffer_info->dma,
-				       buffer_info->length, DMA_TO_DEVICE);
-		else
-			dma_unmap_single(&adapter->pdev->dev, buffer_info->dma,
-					 buffer_info->length,
-					 DMA_TO_DEVICE);
-		buffer_info->dma = 0;
-	}
-	if (buffer_info->skb) {
-		dev_kfree_skb_any(buffer_info->skb);
-		buffer_info->skb = NULL;
-	}
-	buffer_info->time_stamp = 0;
-	/* buffer_info must be completely set up in the transmit path */
-}
-
-/**
- * e1000_clean_tx_ring - Free Tx Buffers
- * @adapter: board private structure
- * @tx_ring: ring to be cleaned
- **/
-
-static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
-				struct e1000_tx_ring *tx_ring)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_buffer *buffer_info;
-	unsigned long size;
-	unsigned int i;
-
-	/* Free all the Tx ring sk_buffs */
-
-	for (i = 0; i < tx_ring->count; i++) {
-		buffer_info = &tx_ring->buffer_info[i];
-		e1000_unmap_and_free_tx_resource(adapter, buffer_info);
-	}
-
-	size = sizeof(struct e1000_buffer) * tx_ring->count;
-	memset(tx_ring->buffer_info, 0, size);
-
-	/* Zero out the descriptor ring */
-
-	memset(tx_ring->desc, 0, tx_ring->size);
-
-	tx_ring->next_to_use = 0;
-	tx_ring->next_to_clean = 0;
-	tx_ring->last_tx_tso = 0;
-
-	writel(0, hw->hw_addr + tx_ring->tdh);
-	writel(0, hw->hw_addr + tx_ring->tdt);
-}
-
-/**
- * e1000_clean_all_tx_rings - Free Tx Buffers for all queues
- * @adapter: board private structure
- **/
-
-static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
-{
-	int i;
-
-	for (i = 0; i < adapter->num_tx_queues; i++)
-		e1000_clean_tx_ring(adapter, &adapter->tx_ring[i]);
-}
-
-/**
- * e1000_free_rx_resources - Free Rx Resources
- * @adapter: board private structure
- * @rx_ring: ring to clean the resources from
- *
- * Free all receive software resources
- **/
-
-static void e1000_free_rx_resources(struct e1000_adapter *adapter,
-				    struct e1000_rx_ring *rx_ring)
-{
-	struct pci_dev *pdev = adapter->pdev;
-
-	e1000_clean_rx_ring(adapter, rx_ring);
-
-	vfree(rx_ring->buffer_info);
-	rx_ring->buffer_info = NULL;
-
-	dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc,
-			  rx_ring->dma);
-
-	rx_ring->desc = NULL;
-}
-
-/**
- * e1000_free_all_rx_resources - Free Rx Resources for All Queues
- * @adapter: board private structure
- *
- * Free all receive software resources
- **/
-
-void e1000_free_all_rx_resources(struct e1000_adapter *adapter)
-{
-	int i;
-
-	for (i = 0; i < adapter->num_rx_queues; i++)
-		e1000_free_rx_resources(adapter, &adapter->rx_ring[i]);
-}
-
-/**
- * e1000_clean_rx_ring - Free Rx Buffers per Queue
- * @adapter: board private structure
- * @rx_ring: ring to free buffers from
- **/
-
-static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
-				struct e1000_rx_ring *rx_ring)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_buffer *buffer_info;
-	struct pci_dev *pdev = adapter->pdev;
-	unsigned long size;
-	unsigned int i;
-
-	/* Free all the Rx ring sk_buffs */
-	for (i = 0; i < rx_ring->count; i++) {
-		buffer_info = &rx_ring->buffer_info[i];
-		if (buffer_info->dma &&
-		    adapter->clean_rx == e1000_clean_rx_irq) {
-			dma_unmap_single(&pdev->dev, buffer_info->dma,
-			                 buffer_info->length,
-					 DMA_FROM_DEVICE);
-		} else if (buffer_info->dma &&
-		           adapter->clean_rx == e1000_clean_jumbo_rx_irq) {
-			dma_unmap_page(&pdev->dev, buffer_info->dma,
-				       buffer_info->length,
-				       DMA_FROM_DEVICE);
-		}
-
-		buffer_info->dma = 0;
-		if (buffer_info->page) {
-			put_page(buffer_info->page);
-			buffer_info->page = NULL;
-		}
-		if (buffer_info->skb) {
-			dev_kfree_skb(buffer_info->skb);
-			buffer_info->skb = NULL;
-		}
-	}
-
-	/* there also may be some cached data from a chained receive */
-	if (rx_ring->rx_skb_top) {
-		dev_kfree_skb(rx_ring->rx_skb_top);
-		rx_ring->rx_skb_top = NULL;
-	}
-
-	size = sizeof(struct e1000_buffer) * rx_ring->count;
-	memset(rx_ring->buffer_info, 0, size);
-
-	/* Zero out the descriptor ring */
-	memset(rx_ring->desc, 0, rx_ring->size);
-
-	rx_ring->next_to_clean = 0;
-	rx_ring->next_to_use = 0;
-
-	writel(0, hw->hw_addr + rx_ring->rdh);
-	writel(0, hw->hw_addr + rx_ring->rdt);
-}
-
-/**
- * e1000_clean_all_rx_rings - Free Rx Buffers for all queues
- * @adapter: board private structure
- **/
-
-static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
-{
-	int i;
-
-	for (i = 0; i < adapter->num_rx_queues; i++)
-		e1000_clean_rx_ring(adapter, &adapter->rx_ring[i]);
-}
-
-/* The 82542 2.0 (revision 2) needs to have the receive unit in reset
- * and memory write and invalidate disabled for certain operations
- */
-static void e1000_enter_82542_rst(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	u32 rctl;
-
-	e1000_pci_clear_mwi(hw);
-
-	rctl = er32(RCTL);
-	rctl |= E1000_RCTL_RST;
-	ew32(RCTL, rctl);
-	E1000_WRITE_FLUSH();
-	mdelay(5);
-
-	if (netif_running(netdev))
-		e1000_clean_all_rx_rings(adapter);
-}
-
-static void e1000_leave_82542_rst(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	u32 rctl;
-
-	rctl = er32(RCTL);
-	rctl &= ~E1000_RCTL_RST;
-	ew32(RCTL, rctl);
-	E1000_WRITE_FLUSH();
-	mdelay(5);
-
-	if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
-		e1000_pci_set_mwi(hw);
-
-	if (netif_running(netdev)) {
-		/* No need to loop, because 82542 supports only 1 queue */
-		struct e1000_rx_ring *ring = &adapter->rx_ring[0];
-		e1000_configure_rx(adapter);
-		adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring));
-	}
-}
-
-/**
- * e1000_set_mac - Change the Ethernet Address of the NIC
- * @netdev: network interface device structure
- * @p: pointer to an address structure
- *
- * Returns 0 on success, negative on failure
- **/
-
-static int e1000_set_mac(struct net_device *netdev, void *p)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	struct sockaddr *addr = p;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	/* 82542 2.0 needs to be in reset to write receive address registers */
-
-	if (hw->mac_type == e1000_82542_rev2_0)
-		e1000_enter_82542_rst(adapter);
-
-	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-	memcpy(hw->mac_addr, addr->sa_data, netdev->addr_len);
-
-	e1000_rar_set(hw, hw->mac_addr, 0);
-
-	if (hw->mac_type == e1000_82542_rev2_0)
-		e1000_leave_82542_rst(adapter);
-
-	return 0;
-}
-
-/**
- * e1000_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set
- * @netdev: network interface device structure
- *
- * The set_rx_mode entry point is called whenever the unicast or multicast
- * address lists or the network interface flags are updated. This routine is
- * responsible for configuring the hardware for proper unicast, multicast,
- * promiscuous mode, and all-multi behavior.
- **/
-
-static void e1000_set_rx_mode(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	struct netdev_hw_addr *ha;
-	bool use_uc = false;
-	u32 rctl;
-	u32 hash_value;
-	int i, rar_entries = E1000_RAR_ENTRIES;
-	int mta_reg_count = E1000_NUM_MTA_REGISTERS;
-	u32 *mcarray = kcalloc(mta_reg_count, sizeof(u32), GFP_ATOMIC);
-
-	if (!mcarray) {
-		e_err(probe, "memory allocation failed\n");
-		return;
-	}
-
-	/* Check for Promiscuous and All Multicast modes */
-
-	rctl = er32(RCTL);
-
-	if (netdev->flags & IFF_PROMISC) {
-		rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
-		rctl &= ~E1000_RCTL_VFE;
-	} else {
-		if (netdev->flags & IFF_ALLMULTI)
-			rctl |= E1000_RCTL_MPE;
-		else
-			rctl &= ~E1000_RCTL_MPE;
-		/* Enable VLAN filter if there is a VLAN */
-		if (e1000_vlan_used(adapter))
-			rctl |= E1000_RCTL_VFE;
-	}
-
-	if (netdev_uc_count(netdev) > rar_entries - 1) {
-		rctl |= E1000_RCTL_UPE;
-	} else if (!(netdev->flags & IFF_PROMISC)) {
-		rctl &= ~E1000_RCTL_UPE;
-		use_uc = true;
-	}
-
-	ew32(RCTL, rctl);
-
-	/* 82542 2.0 needs to be in reset to write receive address registers */
-
-	if (hw->mac_type == e1000_82542_rev2_0)
-		e1000_enter_82542_rst(adapter);
-
-	/* load the first 14 addresses into the exact filters 1-14. Unicast
-	 * addresses take precedence to avoid disabling unicast filtering
-	 * when possible.
-	 *
-	 * RAR 0 is used for the station MAC address
-	 * if there are not 14 addresses, go ahead and clear the filters
-	 */
-	i = 1;
-	if (use_uc)
-		netdev_for_each_uc_addr(ha, netdev) {
-			if (i == rar_entries)
-				break;
-			e1000_rar_set(hw, ha->addr, i++);
-		}
-
-	netdev_for_each_mc_addr(ha, netdev) {
-		if (i == rar_entries) {
-			/* load any remaining addresses into the hash table */
-			u32 hash_reg, hash_bit, mta;
-			hash_value = e1000_hash_mc_addr(hw, ha->addr);
-			hash_reg = (hash_value >> 5) & 0x7F;
-			hash_bit = hash_value & 0x1F;
-			mta = (1 << hash_bit);
-			mcarray[hash_reg] |= mta;
-		} else {
-			e1000_rar_set(hw, ha->addr, i++);
-		}
-	}
-
-	for (; i < rar_entries; i++) {
-		E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0);
-		E1000_WRITE_FLUSH();
-		E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0);
-		E1000_WRITE_FLUSH();
-	}
-
-	/* write the hash table completely, write from bottom to avoid
-	 * both stupid write combining chipsets, and flushing each write */
-	for (i = mta_reg_count - 1; i >= 0 ; i--) {
-		/*
-		 * If we are on an 82544 has an errata where writing odd
-		 * offsets overwrites the previous even offset, but writing
-		 * backwards over the range solves the issue by always
-		 * writing the odd offset first
-		 */
-		E1000_WRITE_REG_ARRAY(hw, MTA, i, mcarray[i]);
-	}
-	E1000_WRITE_FLUSH();
-
-	if (hw->mac_type == e1000_82542_rev2_0)
-		e1000_leave_82542_rst(adapter);
-
-	kfree(mcarray);
-}
-
-/* Need to wait a few seconds after link up to get diagnostic information from
- * the phy */
-
-static void e1000_update_phy_info(unsigned long data)
-{
-	struct e1000_adapter *adapter = (struct e1000_adapter *)data;
-	schedule_work(&adapter->phy_info_task);
-}
-
-static void e1000_update_phy_info_task(struct work_struct *work)
-{
-	struct e1000_adapter *adapter = container_of(work,
-	                                             struct e1000_adapter,
-	                                             phy_info_task);
-	struct e1000_hw *hw = &adapter->hw;
-
-	rtnl_lock();
-	e1000_phy_get_info(hw, &adapter->phy_info);
-	rtnl_unlock();
-}
-
-/**
- * e1000_82547_tx_fifo_stall - Timer Call-back
- * @data: pointer to adapter cast into an unsigned long
- **/
-static void e1000_82547_tx_fifo_stall(unsigned long data)
-{
-	struct e1000_adapter *adapter = (struct e1000_adapter *)data;
-	schedule_work(&adapter->fifo_stall_task);
-}
-
-/**
- * e1000_82547_tx_fifo_stall_task - task to complete work
- * @work: work struct contained inside adapter struct
- **/
-static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)
-{
-	struct e1000_adapter *adapter = container_of(work,
-	                                             struct e1000_adapter,
-	                                             fifo_stall_task);
-	struct e1000_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	u32 tctl;
-
-	rtnl_lock();
-	if (atomic_read(&adapter->tx_fifo_stall)) {
-		if ((er32(TDT) == er32(TDH)) &&
-		   (er32(TDFT) == er32(TDFH)) &&
-		   (er32(TDFTS) == er32(TDFHS))) {
-			tctl = er32(TCTL);
-			ew32(TCTL, tctl & ~E1000_TCTL_EN);
-			ew32(TDFT, adapter->tx_head_addr);
-			ew32(TDFH, adapter->tx_head_addr);
-			ew32(TDFTS, adapter->tx_head_addr);
-			ew32(TDFHS, adapter->tx_head_addr);
-			ew32(TCTL, tctl);
-			E1000_WRITE_FLUSH();
-
-			adapter->tx_fifo_head = 0;
-			atomic_set(&adapter->tx_fifo_stall, 0);
-			netif_wake_queue(netdev);
-		} else if (!test_bit(__E1000_DOWN, &adapter->flags)) {
-			mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1);
-		}
-	}
-	rtnl_unlock();
-}
-
-bool e1000_has_link(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	bool link_active = false;
-
-	/* get_link_status is set on LSC (link status) interrupt or rx
-	 * sequence error interrupt (except on intel ce4100).
-	 * get_link_status will stay false until the
-	 * e1000_check_for_link establishes link for copper adapters
-	 * ONLY
-	 */
-	switch (hw->media_type) {
-	case e1000_media_type_copper:
-		if (hw->mac_type == e1000_ce4100)
-			hw->get_link_status = 1;
-		if (hw->get_link_status) {
-			e1000_check_for_link(hw);
-			link_active = !hw->get_link_status;
-		} else {
-			link_active = true;
-		}
-		break;
-	case e1000_media_type_fiber:
-		e1000_check_for_link(hw);
-		link_active = !!(er32(STATUS) & E1000_STATUS_LU);
-		break;
-	case e1000_media_type_internal_serdes:
-		e1000_check_for_link(hw);
-		link_active = hw->serdes_has_link;
-		break;
-	default:
-		break;
-	}
-
-	return link_active;
-}
-
-/**
- * e1000_watchdog - Timer Call-back
- * @data: pointer to adapter cast into an unsigned long
- **/
-static void e1000_watchdog(unsigned long data)
-{
-	struct e1000_adapter *adapter = (struct e1000_adapter *)data;
-	struct e1000_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	struct e1000_tx_ring *txdr = adapter->tx_ring;
-	u32 link, tctl;
-
-	link = e1000_has_link(adapter);
-	if ((netif_carrier_ok(netdev)) && link)
-		goto link_up;
-
-	if (link) {
-		if (!netif_carrier_ok(netdev)) {
-			u32 ctrl;
-			bool txb2b = true;
-			/* update snapshot of PHY registers on LSC */
-			e1000_get_speed_and_duplex(hw,
-			                           &adapter->link_speed,
-			                           &adapter->link_duplex);
-
-			ctrl = er32(CTRL);
-			pr_info("%s NIC Link is Up %d Mbps %s, "
-				"Flow Control: %s\n",
-				netdev->name,
-				adapter->link_speed,
-				adapter->link_duplex == FULL_DUPLEX ?
-				"Full Duplex" : "Half Duplex",
-				((ctrl & E1000_CTRL_TFCE) && (ctrl &
-				E1000_CTRL_RFCE)) ? "RX/TX" : ((ctrl &
-				E1000_CTRL_RFCE) ? "RX" : ((ctrl &
-				E1000_CTRL_TFCE) ? "TX" : "None")));
-
-			/* adjust timeout factor according to speed/duplex */
-			adapter->tx_timeout_factor = 1;
-			switch (adapter->link_speed) {
-			case SPEED_10:
-				txb2b = false;
-				adapter->tx_timeout_factor = 16;
-				break;
-			case SPEED_100:
-				txb2b = false;
-				/* maybe add some timeout factor ? */
-				break;
-			}
-
-			/* enable transmits in the hardware */
-			tctl = er32(TCTL);
-			tctl |= E1000_TCTL_EN;
-			ew32(TCTL, tctl);
-
-			netif_carrier_on(netdev);
-			if (!test_bit(__E1000_DOWN, &adapter->flags))
-				mod_timer(&adapter->phy_info_timer,
-				          round_jiffies(jiffies + 2 * HZ));
-			adapter->smartspeed = 0;
-		}
-	} else {
-		if (netif_carrier_ok(netdev)) {
-			adapter->link_speed = 0;
-			adapter->link_duplex = 0;
-			pr_info("%s NIC Link is Down\n",
-				netdev->name);
-			netif_carrier_off(netdev);
-
-			if (!test_bit(__E1000_DOWN, &adapter->flags))
-				mod_timer(&adapter->phy_info_timer,
-				          round_jiffies(jiffies + 2 * HZ));
-		}
-
-		e1000_smartspeed(adapter);
-	}
-
-link_up:
-	e1000_update_stats(adapter);
-
-	hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
-	adapter->tpt_old = adapter->stats.tpt;
-	hw->collision_delta = adapter->stats.colc - adapter->colc_old;
-	adapter->colc_old = adapter->stats.colc;
-
-	adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
-	adapter->gorcl_old = adapter->stats.gorcl;
-	adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
-	adapter->gotcl_old = adapter->stats.gotcl;
-
-	e1000_update_adaptive(hw);
-
-	if (!netif_carrier_ok(netdev)) {
-		if (E1000_DESC_UNUSED(txdr) + 1 < txdr->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). */
-			adapter->tx_timeout_count++;
-			schedule_work(&adapter->reset_task);
-			/* return immediately since reset is imminent */
-			return;
-		}
-	}
-
-	/* Simple mode for Interrupt Throttle Rate (ITR) */
-	if (hw->mac_type >= e1000_82540 && adapter->itr_setting == 4) {
-		/*
-		 * Symmetric Tx/Rx gets a reduced ITR=2000;
-		 * Total asymmetrical Tx or Rx gets ITR=8000;
-		 * everyone else is between 2000-8000.
-		 */
-		u32 goc = (adapter->gotcl + adapter->gorcl) / 10000;
-		u32 dif = (adapter->gotcl > adapter->gorcl ?
-			    adapter->gotcl - adapter->gorcl :
-			    adapter->gorcl - adapter->gotcl) / 10000;
-		u32 itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
-
-		ew32(ITR, 1000000000 / (itr * 256));
-	}
-
-	/* Cause software interrupt to ensure rx ring is cleaned */
-	ew32(ICS, E1000_ICS_RXDMT0);
-
-	/* Force detection of hung controller every watchdog period */
-	adapter->detect_tx_hung = true;
-
-	/* Reset the timer */
-	if (!test_bit(__E1000_DOWN, &adapter->flags))
-		mod_timer(&adapter->watchdog_timer,
-		          round_jiffies(jiffies + 2 * HZ));
-}
-
-enum latency_range {
-	lowest_latency = 0,
-	low_latency = 1,
-	bulk_latency = 2,
-	latency_invalid = 255
-};
-
-/**
- * e1000_update_itr - update the dynamic ITR value based on statistics
- * @adapter: pointer to adapter
- * @itr_setting: current adapter->itr
- * @packets: the number of packets during this measurement interval
- * @bytes: the number of bytes during this measurement interval
- *
- *      Stores a new ITR value based on packets and byte
- *      counts during the last interrupt.  The advantage of per interrupt
- *      computation is faster updates and more accurate ITR for the current
- *      traffic pattern.  Constants in this function were computed
- *      based on theoretical maximum wire speed and thresholds were set based
- *      on testing data as well as attempting to minimize response time
- *      while increasing bulk throughput.
- *      this functionality is controlled by the InterruptThrottleRate module
- *      parameter (see e1000_param.c)
- **/
-static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
-				     u16 itr_setting, int packets, int bytes)
-{
-	unsigned int retval = itr_setting;
-	struct e1000_hw *hw = &adapter->hw;
-
-	if (unlikely(hw->mac_type < e1000_82540))
-		goto update_itr_done;
-
-	if (packets == 0)
-		goto update_itr_done;
-
-	switch (itr_setting) {
-	case lowest_latency:
-		/* jumbo frames get bulk treatment*/
-		if (bytes/packets > 8000)
-			retval = bulk_latency;
-		else if ((packets < 5) && (bytes > 512))
-			retval = low_latency;
-		break;
-	case low_latency:  /* 50 usec aka 20000 ints/s */
-		if (bytes > 10000) {
-			/* jumbo frames need bulk latency setting */
-			if (bytes/packets > 8000)
-				retval = bulk_latency;
-			else if ((packets < 10) || ((bytes/packets) > 1200))
-				retval = bulk_latency;
-			else if ((packets > 35))
-				retval = lowest_latency;
-		} else if (bytes/packets > 2000)
-			retval = bulk_latency;
-		else if (packets <= 2 && bytes < 512)
-			retval = lowest_latency;
-		break;
-	case bulk_latency: /* 250 usec aka 4000 ints/s */
-		if (bytes > 25000) {
-			if (packets > 35)
-				retval = low_latency;
-		} else if (bytes < 6000) {
-			retval = low_latency;
-		}
-		break;
-	}
-
-update_itr_done:
-	return retval;
-}
-
-static void e1000_set_itr(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u16 current_itr;
-	u32 new_itr = adapter->itr;
-
-	if (unlikely(hw->mac_type < e1000_82540))
-		return;
-
-	/* for non-gigabit speeds, just fix the interrupt rate at 4000 */
-	if (unlikely(adapter->link_speed != SPEED_1000)) {
-		current_itr = 0;
-		new_itr = 4000;
-		goto set_itr_now;
-	}
-
-	adapter->tx_itr = e1000_update_itr(adapter,
-	                            adapter->tx_itr,
-	                            adapter->total_tx_packets,
-	                            adapter->total_tx_bytes);
-	/* conservative mode (itr 3) eliminates the lowest_latency setting */
-	if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency)
-		adapter->tx_itr = low_latency;
-
-	adapter->rx_itr = e1000_update_itr(adapter,
-	                            adapter->rx_itr,
-	                            adapter->total_rx_packets,
-	                            adapter->total_rx_bytes);
-	/* conservative mode (itr 3) eliminates the lowest_latency setting */
-	if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency)
-		adapter->rx_itr = low_latency;
-
-	current_itr = max(adapter->rx_itr, adapter->tx_itr);
-
-	switch (current_itr) {
-	/* counts and packets in update_itr are dependent on these numbers */
-	case lowest_latency:
-		new_itr = 70000;
-		break;
-	case low_latency:
-		new_itr = 20000; /* aka hwitr = ~200 */
-		break;
-	case bulk_latency:
-		new_itr = 4000;
-		break;
-	default:
-		break;
-	}
-
-set_itr_now:
-	if (new_itr != adapter->itr) {
-		/* this attempts to bias the interrupt rate towards Bulk
-		 * by adding intermediate steps when interrupt rate is
-		 * increasing */
-		new_itr = new_itr > adapter->itr ?
-		             min(adapter->itr + (new_itr >> 2), new_itr) :
-		             new_itr;
-		adapter->itr = new_itr;
-		ew32(ITR, 1000000000 / (new_itr * 256));
-	}
-}
-
-#define E1000_TX_FLAGS_CSUM		0x00000001
-#define E1000_TX_FLAGS_VLAN		0x00000002
-#define E1000_TX_FLAGS_TSO		0x00000004
-#define E1000_TX_FLAGS_IPV4		0x00000008
-#define E1000_TX_FLAGS_VLAN_MASK	0xffff0000
-#define E1000_TX_FLAGS_VLAN_SHIFT	16
-
-static int e1000_tso(struct e1000_adapter *adapter,
-		     struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
-{
-	struct e1000_context_desc *context_desc;
-	struct e1000_buffer *buffer_info;
-	unsigned int i;
-	u32 cmd_length = 0;
-	u16 ipcse = 0, tucse, mss;
-	u8 ipcss, ipcso, tucss, tucso, hdr_len;
-	int err;
-
-	if (skb_is_gso(skb)) {
-		if (skb_header_cloned(skb)) {
-			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
-			if (err)
-				return err;
-		}
-
-		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-		mss = skb_shinfo(skb)->gso_size;
-		if (skb->protocol == htons(ETH_P_IP)) {
-			struct iphdr *iph = ip_hdr(skb);
-			iph->tot_len = 0;
-			iph->check = 0;
-			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
-								 iph->daddr, 0,
-								 IPPROTO_TCP,
-								 0);
-			cmd_length = E1000_TXD_CMD_IP;
-			ipcse = skb_transport_offset(skb) - 1;
-		} else if (skb->protocol == htons(ETH_P_IPV6)) {
-			ipv6_hdr(skb)->payload_len = 0;
-			tcp_hdr(skb)->check =
-				~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
-						 &ipv6_hdr(skb)->daddr,
-						 0, IPPROTO_TCP, 0);
-			ipcse = 0;
-		}
-		ipcss = skb_network_offset(skb);
-		ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data;
-		tucss = skb_transport_offset(skb);
-		tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data;
-		tucse = 0;
-
-		cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
-			       E1000_TXD_CMD_TCP | (skb->len - (hdr_len)));
-
-		i = tx_ring->next_to_use;
-		context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
-		buffer_info = &tx_ring->buffer_info[i];
-
-		context_desc->lower_setup.ip_fields.ipcss  = ipcss;
-		context_desc->lower_setup.ip_fields.ipcso  = ipcso;
-		context_desc->lower_setup.ip_fields.ipcse  = cpu_to_le16(ipcse);
-		context_desc->upper_setup.tcp_fields.tucss = tucss;
-		context_desc->upper_setup.tcp_fields.tucso = tucso;
-		context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse);
-		context_desc->tcp_seg_setup.fields.mss     = cpu_to_le16(mss);
-		context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
-		context_desc->cmd_and_length = cpu_to_le32(cmd_length);
-
-		buffer_info->time_stamp = jiffies;
-		buffer_info->next_to_watch = i;
-
-		if (++i == tx_ring->count) i = 0;
-		tx_ring->next_to_use = i;
-
-		return true;
-	}
-	return false;
-}
-
-static bool e1000_tx_csum(struct e1000_adapter *adapter,
-			  struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
-{
-	struct e1000_context_desc *context_desc;
-	struct e1000_buffer *buffer_info;
-	unsigned int i;
-	u8 css;
-	u32 cmd_len = E1000_TXD_CMD_DEXT;
-
-	if (skb->ip_summed != CHECKSUM_PARTIAL)
-		return false;
-
-	switch (skb->protocol) {
-	case cpu_to_be16(ETH_P_IP):
-		if (ip_hdr(skb)->protocol == IPPROTO_TCP)
-			cmd_len |= E1000_TXD_CMD_TCP;
-		break;
-	case cpu_to_be16(ETH_P_IPV6):
-		/* XXX not handling all IPV6 headers */
-		if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
-			cmd_len |= E1000_TXD_CMD_TCP;
-		break;
-	default:
-		if (unlikely(net_ratelimit()))
-			e_warn(drv, "checksum_partial proto=%x!\n",
-			       skb->protocol);
-		break;
-	}
-
-	css = skb_checksum_start_offset(skb);
-
-	i = tx_ring->next_to_use;
-	buffer_info = &tx_ring->buffer_info[i];
-	context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
-
-	context_desc->lower_setup.ip_config = 0;
-	context_desc->upper_setup.tcp_fields.tucss = css;
-	context_desc->upper_setup.tcp_fields.tucso =
-		css + skb->csum_offset;
-	context_desc->upper_setup.tcp_fields.tucse = 0;
-	context_desc->tcp_seg_setup.data = 0;
-	context_desc->cmd_and_length = cpu_to_le32(cmd_len);
-
-	buffer_info->time_stamp = jiffies;
-	buffer_info->next_to_watch = i;
-
-	if (unlikely(++i == tx_ring->count)) i = 0;
-	tx_ring->next_to_use = i;
-
-	return true;
-}
-
-#define E1000_MAX_TXD_PWR	12
-#define E1000_MAX_DATA_PER_TXD	(1<<E1000_MAX_TXD_PWR)
-
-static int e1000_tx_map(struct e1000_adapter *adapter,
-			struct e1000_tx_ring *tx_ring,
-			struct sk_buff *skb, unsigned int first,
-			unsigned int max_per_txd, unsigned int nr_frags,
-			unsigned int mss)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_buffer *buffer_info;
-	unsigned int len = skb_headlen(skb);
-	unsigned int offset = 0, size, count = 0, i;
-	unsigned int f;
-
-	i = tx_ring->next_to_use;
-
-	while (len) {
-		buffer_info = &tx_ring->buffer_info[i];
-		size = min(len, max_per_txd);
-		/* Workaround for Controller erratum --
-		 * descriptor for non-tso packet in a linear SKB that follows a
-		 * tso gets written back prematurely before the data is fully
-		 * DMA'd to the controller */
-		if (!skb->data_len && tx_ring->last_tx_tso &&
-		    !skb_is_gso(skb)) {
-			tx_ring->last_tx_tso = 0;
-			size -= 4;
-		}
-
-		/* Workaround for premature desc write-backs
-		 * in TSO mode.  Append 4-byte sentinel desc */
-		if (unlikely(mss && !nr_frags && size == len && size > 8))
-			size -= 4;
-		/* work-around for errata 10 and it applies
-		 * to all controllers in PCI-X mode
-		 * The fix is to make sure that the first descriptor of a
-		 * packet is smaller than 2048 - 16 - 16 (or 2016) bytes
-		 */
-		if (unlikely((hw->bus_type == e1000_bus_type_pcix) &&
-		                (size > 2015) && count == 0))
-		        size = 2015;
-
-		/* Workaround for potential 82544 hang in PCI-X.  Avoid
-		 * terminating buffers within evenly-aligned dwords. */
-		if (unlikely(adapter->pcix_82544 &&
-		   !((unsigned long)(skb->data + offset + size - 1) & 4) &&
-		   size > 4))
-			size -= 4;
-
-		buffer_info->length = size;
-		/* set time_stamp *before* dma to help avoid a possible race */
-		buffer_info->time_stamp = jiffies;
-		buffer_info->mapped_as_page = false;
-		buffer_info->dma = dma_map_single(&pdev->dev,
-						  skb->data + offset,
-						  size,	DMA_TO_DEVICE);
-		if (dma_mapping_error(&pdev->dev, buffer_info->dma))
-			goto dma_error;
-		buffer_info->next_to_watch = i;
-
-		len -= size;
-		offset += size;
-		count++;
-		if (len) {
-			i++;
-			if (unlikely(i == tx_ring->count))
-				i = 0;
-		}
-	}
-
-	for (f = 0; f < nr_frags; f++) {
-		struct skb_frag_struct *frag;
-
-		frag = &skb_shinfo(skb)->frags[f];
-		len = frag->size;
-		offset = frag->page_offset;
-
-		while (len) {
-			i++;
-			if (unlikely(i == tx_ring->count))
-				i = 0;
-
-			buffer_info = &tx_ring->buffer_info[i];
-			size = min(len, max_per_txd);
-			/* Workaround for premature desc write-backs
-			 * in TSO mode.  Append 4-byte sentinel desc */
-			if (unlikely(mss && f == (nr_frags-1) && size == len && size > 8))
-				size -= 4;
-			/* Workaround for potential 82544 hang in PCI-X.
-			 * Avoid terminating buffers within evenly-aligned
-			 * dwords. */
-			if (unlikely(adapter->pcix_82544 &&
-			    !((unsigned long)(page_to_phys(frag->page) + offset
-			                      + size - 1) & 4) &&
-			    size > 4))
-				size -= 4;
-
-			buffer_info->length = size;
-			buffer_info->time_stamp = jiffies;
-			buffer_info->mapped_as_page = true;
-			buffer_info->dma = dma_map_page(&pdev->dev, frag->page,
-							offset,	size,
-							DMA_TO_DEVICE);
-			if (dma_mapping_error(&pdev->dev, buffer_info->dma))
-				goto dma_error;
-			buffer_info->next_to_watch = i;
-
-			len -= size;
-			offset += size;
-			count++;
-		}
-	}
-
-	tx_ring->buffer_info[i].skb = skb;
-	tx_ring->buffer_info[first].next_to_watch = i;
-
-	return count;
-
-dma_error:
-	dev_err(&pdev->dev, "TX DMA map failed\n");
-	buffer_info->dma = 0;
-	if (count)
-		count--;
-
-	while (count--) {
-		if (i==0)
-			i += tx_ring->count;
-		i--;
-		buffer_info = &tx_ring->buffer_info[i];
-		e1000_unmap_and_free_tx_resource(adapter, buffer_info);
-	}
-
-	return 0;
-}
-
-static void e1000_tx_queue(struct e1000_adapter *adapter,
-			   struct e1000_tx_ring *tx_ring, int tx_flags,
-			   int count)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_tx_desc *tx_desc = NULL;
-	struct e1000_buffer *buffer_info;
-	u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
-	unsigned int i;
-
-	if (likely(tx_flags & E1000_TX_FLAGS_TSO)) {
-		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
-		             E1000_TXD_CMD_TSE;
-		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
-
-		if (likely(tx_flags & E1000_TX_FLAGS_IPV4))
-			txd_upper |= E1000_TXD_POPTS_IXSM << 8;
-	}
-
-	if (likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
-		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
-		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
-	}
-
-	if (unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
-		txd_lower |= E1000_TXD_CMD_VLE;
-		txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
-	}
-
-	i = tx_ring->next_to_use;
-
-	while (count--) {
-		buffer_info = &tx_ring->buffer_info[i];
-		tx_desc = E1000_TX_DESC(*tx_ring, i);
-		tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
-		tx_desc->lower.data =
-			cpu_to_le32(txd_lower | buffer_info->length);
-		tx_desc->upper.data = cpu_to_le32(txd_upper);
-		if (unlikely(++i == tx_ring->count)) i = 0;
-	}
-
-	tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
-
-	/* Force memory writes to complete before letting h/w
-	 * know there are new descriptors to fetch.  (Only
-	 * applicable for weak-ordered memory model archs,
-	 * such as IA-64). */
-	wmb();
-
-	tx_ring->next_to_use = i;
-	writel(i, hw->hw_addr + tx_ring->tdt);
-	/* we need this if more than one processor can write to our tail
-	 * at a time, it syncronizes IO on IA64/Altix systems */
-	mmiowb();
-}
-
-/**
- * 82547 workaround to avoid controller hang in half-duplex environment.
- * The workaround is to avoid queuing a large packet that would span
- * the internal Tx FIFO ring boundary by notifying the stack to resend
- * the packet at a later time.  This gives the Tx FIFO an opportunity to
- * flush all packets.  When that occurs, we reset the Tx FIFO pointers
- * to the beginning of the Tx FIFO.
- **/
-
-#define E1000_FIFO_HDR			0x10
-#define E1000_82547_PAD_LEN		0x3E0
-
-static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
-				       struct sk_buff *skb)
-{
-	u32 fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
-	u32 skb_fifo_len = skb->len + E1000_FIFO_HDR;
-
-	skb_fifo_len = ALIGN(skb_fifo_len, E1000_FIFO_HDR);
-
-	if (adapter->link_duplex != HALF_DUPLEX)
-		goto no_fifo_stall_required;
-
-	if (atomic_read(&adapter->tx_fifo_stall))
-		return 1;
-
-	if (skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) {
-		atomic_set(&adapter->tx_fifo_stall, 1);
-		return 1;
-	}
-
-no_fifo_stall_required:
-	adapter->tx_fifo_head += skb_fifo_len;
-	if (adapter->tx_fifo_head >= adapter->tx_fifo_size)
-		adapter->tx_fifo_head -= adapter->tx_fifo_size;
-	return 0;
-}
-
-static int __e1000_maybe_stop_tx(struct net_device *netdev, int size)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_tx_ring *tx_ring = adapter->tx_ring;
-
-	netif_stop_queue(netdev);
-	/* Herbert's original patch had:
-	 *  smp_mb__after_netif_stop_queue();
-	 * but since that doesn't exist yet, just open code it. */
-	smp_mb();
-
-	/* We need to check again in a case another CPU has just
-	 * made room available. */
-	if (likely(E1000_DESC_UNUSED(tx_ring) < size))
-		return -EBUSY;
-
-	/* A reprieve! */
-	netif_start_queue(netdev);
-	++adapter->restart_queue;
-	return 0;
-}
-
-static int e1000_maybe_stop_tx(struct net_device *netdev,
-                               struct e1000_tx_ring *tx_ring, int size)
-{
-	if (likely(E1000_DESC_UNUSED(tx_ring) >= size))
-		return 0;
-	return __e1000_maybe_stop_tx(netdev, size);
-}
-
-#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 )
-static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
-				    struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_tx_ring *tx_ring;
-	unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
-	unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
-	unsigned int tx_flags = 0;
-	unsigned int len = skb_headlen(skb);
-	unsigned int nr_frags;
-	unsigned int mss;
-	int count = 0;
-	int tso;
-	unsigned int f;
-
-	/* This goes back to the question of how to logically map a tx queue
-	 * to a flow.  Right now, performance is impacted slightly negatively
-	 * if using multiple tx queues.  If the stack breaks away from a
-	 * single qdisc implementation, we can look at this again. */
-	tx_ring = adapter->tx_ring;
-
-	if (unlikely(skb->len <= 0)) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	mss = skb_shinfo(skb)->gso_size;
-	/* The controller does a simple calculation to
-	 * make sure there is enough room in the FIFO before
-	 * initiating the DMA for each buffer.  The calc is:
-	 * 4 = ceil(buffer len/mss).  To make sure we don't
-	 * overrun the FIFO, adjust the max buffer len if mss
-	 * drops. */
-	if (mss) {
-		u8 hdr_len;
-		max_per_txd = min(mss << 2, max_per_txd);
-		max_txd_pwr = fls(max_per_txd) - 1;
-
-		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-		if (skb->data_len && hdr_len == len) {
-			switch (hw->mac_type) {
-				unsigned int pull_size;
-			case e1000_82544:
-				/* Make sure we have room to chop off 4 bytes,
-				 * and that the end alignment will work out to
-				 * this hardware's requirements
-				 * NOTE: this is a TSO only workaround
-				 * if end byte alignment not correct move us
-				 * into the next dword */
-				if ((unsigned long)(skb_tail_pointer(skb) - 1) & 4)
-					break;
-				/* fall through */
-				pull_size = min((unsigned int)4, skb->data_len);
-				if (!__pskb_pull_tail(skb, pull_size)) {
-					e_err(drv, "__pskb_pull_tail "
-					      "failed.\n");
-					dev_kfree_skb_any(skb);
-					return NETDEV_TX_OK;
-				}
-				len = skb_headlen(skb);
-				break;
-			default:
-				/* do nothing */
-				break;
-			}
-		}
-	}
-
-	/* reserve a descriptor for the offload context */
-	if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL))
-		count++;
-	count++;
-
-	/* Controller Erratum workaround */
-	if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb))
-		count++;
-
-	count += TXD_USE_COUNT(len, max_txd_pwr);
-
-	if (adapter->pcix_82544)
-		count++;
-
-	/* work-around for errata 10 and it applies to all controllers
-	 * in PCI-X mode, so add one more descriptor to the count
-	 */
-	if (unlikely((hw->bus_type == e1000_bus_type_pcix) &&
-			(len > 2015)))
-		count++;
-
-	nr_frags = skb_shinfo(skb)->nr_frags;
-	for (f = 0; f < nr_frags; f++)
-		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
-				       max_txd_pwr);
-	if (adapter->pcix_82544)
-		count += nr_frags;
-
-	/* need: count + 2 desc gap to keep tail from touching
-	 * head, otherwise try next time */
-	if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2)))
-		return NETDEV_TX_BUSY;
-
-	if (unlikely(hw->mac_type == e1000_82547)) {
-		if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
-			netif_stop_queue(netdev);
-			if (!test_bit(__E1000_DOWN, &adapter->flags))
-				mod_timer(&adapter->tx_fifo_stall_timer,
-				          jiffies + 1);
-			return NETDEV_TX_BUSY;
-		}
-	}
-
-	if (vlan_tx_tag_present(skb)) {
-		tx_flags |= E1000_TX_FLAGS_VLAN;
-		tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
-	}
-
-	first = tx_ring->next_to_use;
-
-	tso = e1000_tso(adapter, tx_ring, skb);
-	if (tso < 0) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	if (likely(tso)) {
-		if (likely(hw->mac_type != e1000_82544))
-			tx_ring->last_tx_tso = 1;
-		tx_flags |= E1000_TX_FLAGS_TSO;
-	} else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
-		tx_flags |= E1000_TX_FLAGS_CSUM;
-
-	if (likely(skb->protocol == htons(ETH_P_IP)))
-		tx_flags |= E1000_TX_FLAGS_IPV4;
-
-	count = e1000_tx_map(adapter, tx_ring, skb, first, max_per_txd,
-	                     nr_frags, mss);
-
-	if (count) {
-		e1000_tx_queue(adapter, tx_ring, tx_flags, count);
-		/* Make sure there is space in the ring for the next send. */
-		e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2);
-
-	} else {
-		dev_kfree_skb_any(skb);
-		tx_ring->buffer_info[first].time_stamp = 0;
-		tx_ring->next_to_use = first;
-	}
-
-	return NETDEV_TX_OK;
-}
-
-/**
- * e1000_tx_timeout - Respond to a Tx Hang
- * @netdev: network interface device structure
- **/
-
-static void e1000_tx_timeout(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	/* Do the reset outside of interrupt context */
-	adapter->tx_timeout_count++;
-	schedule_work(&adapter->reset_task);
-}
-
-static void e1000_reset_task(struct work_struct *work)
-{
-	struct e1000_adapter *adapter =
-		container_of(work, struct e1000_adapter, reset_task);
-
-	e1000_reinit_safe(adapter);
-}
-
-/**
- * e1000_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- *
- * 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)
-{
-	/* only return the current stats */
-	return &netdev->stats;
-}
-
-/**
- * e1000_change_mtu - Change the Maximum Transfer Unit
- * @netdev: network interface device structure
- * @new_mtu: new value for maximum frame size
- *
- * Returns 0 on success, negative on failure
- **/
-
-static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
-
-	if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
-	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
-		e_err(probe, "Invalid MTU setting\n");
-		return -EINVAL;
-	}
-
-	/* Adapter-specific max frame size limits. */
-	switch (hw->mac_type) {
-	case e1000_undefined ... e1000_82542_rev2_1:
-		if (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
-			e_err(probe, "Jumbo Frames not supported.\n");
-			return -EINVAL;
-		}
-		break;
-	default:
-		/* Capable of supporting up to MAX_JUMBO_FRAME_SIZE limit. */
-		break;
-	}
-
-	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
-		msleep(1);
-	/* e1000_down has a dependency on max_frame_size */
-	hw->max_frame_size = max_frame;
-	if (netif_running(netdev))
-		e1000_down(adapter);
-
-	/* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
-	 * means we reserve 2 more, this pushes us to allocate from the next
-	 * larger slab size.
-	 * i.e. RXBUFFER_2048 --> size-4096 slab
-	 *  however with the new *_jumbo_rx* routines, jumbo receives will use
-	 *  fragmented skbs */
-
-	if (max_frame <= E1000_RXBUFFER_2048)
-		adapter->rx_buffer_len = E1000_RXBUFFER_2048;
-	else
-#if (PAGE_SIZE >= E1000_RXBUFFER_16384)
-		adapter->rx_buffer_len = E1000_RXBUFFER_16384;
-#elif (PAGE_SIZE >= E1000_RXBUFFER_4096)
-		adapter->rx_buffer_len = PAGE_SIZE;
-#endif
-
-	/* adjust allocation if LPE protects us, and we aren't using SBP */
-	if (!hw->tbi_compatibility_on &&
-	    ((max_frame == (ETH_FRAME_LEN + ETH_FCS_LEN)) ||
-	     (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
-		adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
-
-	pr_info("%s changing MTU from %d to %d\n",
-		netdev->name, netdev->mtu, new_mtu);
-	netdev->mtu = new_mtu;
-
-	if (netif_running(netdev))
-		e1000_up(adapter);
-	else
-		e1000_reset(adapter);
-
-	clear_bit(__E1000_RESETTING, &adapter->flags);
-
-	return 0;
-}
-
-/**
- * e1000_update_stats - Update the board statistics counters
- * @adapter: board private structure
- **/
-
-void e1000_update_stats(struct e1000_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct e1000_hw *hw = &adapter->hw;
-	struct pci_dev *pdev = adapter->pdev;
-	unsigned long flags;
-	u16 phy_tmp;
-
-#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
-
-	/*
-	 * Prevent stats update while adapter is being reset, or if the pci
-	 * connection is down.
-	 */
-	if (adapter->link_speed == 0)
-		return;
-	if (pci_channel_offline(pdev))
-		return;
-
-	spin_lock_irqsave(&adapter->stats_lock, flags);
-
-	/* these counters are modified from e1000_tbi_adjust_stats,
-	 * called from the interrupt context, so they must only
-	 * be written while holding adapter->stats_lock
-	 */
-
-	adapter->stats.crcerrs += er32(CRCERRS);
-	adapter->stats.gprc += er32(GPRC);
-	adapter->stats.gorcl += er32(GORCL);
-	adapter->stats.gorch += er32(GORCH);
-	adapter->stats.bprc += er32(BPRC);
-	adapter->stats.mprc += er32(MPRC);
-	adapter->stats.roc += er32(ROC);
-
-	adapter->stats.prc64 += er32(PRC64);
-	adapter->stats.prc127 += er32(PRC127);
-	adapter->stats.prc255 += er32(PRC255);
-	adapter->stats.prc511 += er32(PRC511);
-	adapter->stats.prc1023 += er32(PRC1023);
-	adapter->stats.prc1522 += er32(PRC1522);
-
-	adapter->stats.symerrs += er32(SYMERRS);
-	adapter->stats.mpc += er32(MPC);
-	adapter->stats.scc += er32(SCC);
-	adapter->stats.ecol += er32(ECOL);
-	adapter->stats.mcc += er32(MCC);
-	adapter->stats.latecol += er32(LATECOL);
-	adapter->stats.dc += er32(DC);
-	adapter->stats.sec += er32(SEC);
-	adapter->stats.rlec += er32(RLEC);
-	adapter->stats.xonrxc += er32(XONRXC);
-	adapter->stats.xontxc += er32(XONTXC);
-	adapter->stats.xoffrxc += er32(XOFFRXC);
-	adapter->stats.xofftxc += er32(XOFFTXC);
-	adapter->stats.fcruc += er32(FCRUC);
-	adapter->stats.gptc += er32(GPTC);
-	adapter->stats.gotcl += er32(GOTCL);
-	adapter->stats.gotch += er32(GOTCH);
-	adapter->stats.rnbc += er32(RNBC);
-	adapter->stats.ruc += er32(RUC);
-	adapter->stats.rfc += er32(RFC);
-	adapter->stats.rjc += er32(RJC);
-	adapter->stats.torl += er32(TORL);
-	adapter->stats.torh += er32(TORH);
-	adapter->stats.totl += er32(TOTL);
-	adapter->stats.toth += er32(TOTH);
-	adapter->stats.tpr += er32(TPR);
-
-	adapter->stats.ptc64 += er32(PTC64);
-	adapter->stats.ptc127 += er32(PTC127);
-	adapter->stats.ptc255 += er32(PTC255);
-	adapter->stats.ptc511 += er32(PTC511);
-	adapter->stats.ptc1023 += er32(PTC1023);
-	adapter->stats.ptc1522 += er32(PTC1522);
-
-	adapter->stats.mptc += er32(MPTC);
-	adapter->stats.bptc += er32(BPTC);
-
-	/* used for adaptive IFS */
-
-	hw->tx_packet_delta = er32(TPT);
-	adapter->stats.tpt += hw->tx_packet_delta;
-	hw->collision_delta = er32(COLC);
-	adapter->stats.colc += hw->collision_delta;
-
-	if (hw->mac_type >= e1000_82543) {
-		adapter->stats.algnerrc += er32(ALGNERRC);
-		adapter->stats.rxerrc += er32(RXERRC);
-		adapter->stats.tncrs += er32(TNCRS);
-		adapter->stats.cexterr += er32(CEXTERR);
-		adapter->stats.tsctc += er32(TSCTC);
-		adapter->stats.tsctfc += er32(TSCTFC);
-	}
-
-	/* Fill out the OS statistics structure */
-	netdev->stats.multicast = adapter->stats.mprc;
-	netdev->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 */
-	netdev->stats.rx_errors = adapter->stats.rxerrc +
-		adapter->stats.crcerrs + adapter->stats.algnerrc +
-		adapter->stats.ruc + adapter->stats.roc +
-		adapter->stats.cexterr;
-	adapter->stats.rlerrc = adapter->stats.ruc + adapter->stats.roc;
-	netdev->stats.rx_length_errors = adapter->stats.rlerrc;
-	netdev->stats.rx_crc_errors = adapter->stats.crcerrs;
-	netdev->stats.rx_frame_errors = adapter->stats.algnerrc;
-	netdev->stats.rx_missed_errors = adapter->stats.mpc;
-
-	/* Tx Errors */
-	adapter->stats.txerrc = adapter->stats.ecol + adapter->stats.latecol;
-	netdev->stats.tx_errors = adapter->stats.txerrc;
-	netdev->stats.tx_aborted_errors = adapter->stats.ecol;
-	netdev->stats.tx_window_errors = adapter->stats.latecol;
-	netdev->stats.tx_carrier_errors = adapter->stats.tncrs;
-	if (hw->bad_tx_carr_stats_fd &&
-	    adapter->link_duplex == FULL_DUPLEX) {
-		netdev->stats.tx_carrier_errors = 0;
-		adapter->stats.tncrs = 0;
-	}
-
-	/* Tx Dropped needs to be maintained elsewhere */
-
-	/* Phy Stats */
-	if (hw->media_type == e1000_media_type_copper) {
-		if ((adapter->link_speed == SPEED_1000) &&
-		   (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) {
-			phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
-			adapter->phy_stats.idle_errors += phy_tmp;
-		}
-
-		if ((hw->mac_type <= e1000_82546) &&
-		   (hw->phy_type == e1000_phy_m88) &&
-		   !e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
-			adapter->phy_stats.receive_errors += phy_tmp;
-	}
-
-	/* Management Stats */
-	if (hw->has_smbus) {
-		adapter->stats.mgptc += er32(MGTPTC);
-		adapter->stats.mgprc += er32(MGTPRC);
-		adapter->stats.mgpdc += er32(MGTPDC);
-	}
-
-	spin_unlock_irqrestore(&adapter->stats_lock, flags);
-}
-
-/**
- * e1000_intr - Interrupt Handler
- * @irq: interrupt number
- * @data: pointer to a network interface device structure
- **/
-
-static irqreturn_t e1000_intr(int irq, void *data)
-{
-	struct net_device *netdev = data;
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u32 icr = er32(ICR);
-
-	if (unlikely((!icr)))
-		return IRQ_NONE;  /* Not our interrupt */
-
-	/*
-	 * we might have caused the interrupt, but the above
-	 * read cleared it, and just in case the driver is
-	 * down there is nothing to do so return handled
-	 */
-	if (unlikely(test_bit(__E1000_DOWN, &adapter->flags)))
-		return IRQ_HANDLED;
-
-	if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
-		hw->get_link_status = 1;
-		/* guard against interrupt when we're going down */
-		if (!test_bit(__E1000_DOWN, &adapter->flags))
-			mod_timer(&adapter->watchdog_timer, jiffies + 1);
-	}
-
-	/* disable interrupts, without the synchronize_irq bit */
-	ew32(IMC, ~0);
-	E1000_WRITE_FLUSH();
-
-	if (likely(napi_schedule_prep(&adapter->napi))) {
-		adapter->total_tx_bytes = 0;
-		adapter->total_tx_packets = 0;
-		adapter->total_rx_bytes = 0;
-		adapter->total_rx_packets = 0;
-		__napi_schedule(&adapter->napi);
-	} else {
-		/* this really should not happen! if it does it is basically a
-		 * bug, but not a hard error, so enable ints and continue */
-		if (!test_bit(__E1000_DOWN, &adapter->flags))
-			e1000_irq_enable(adapter);
-	}
-
-	return IRQ_HANDLED;
-}
-
-/**
- * e1000_clean - NAPI Rx polling callback
- * @adapter: board private structure
- **/
-static int e1000_clean(struct napi_struct *napi, int budget)
-{
-	struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi);
-	int tx_clean_complete = 0, work_done = 0;
-
-	tx_clean_complete = e1000_clean_tx_irq(adapter, &adapter->tx_ring[0]);
-
-	adapter->clean_rx(adapter, &adapter->rx_ring[0], &work_done, budget);
-
-	if (!tx_clean_complete)
-		work_done = budget;
-
-	/* If budget not fully consumed, exit the polling mode */
-	if (work_done < budget) {
-		if (likely(adapter->itr_setting & 3))
-			e1000_set_itr(adapter);
-		napi_complete(napi);
-		if (!test_bit(__E1000_DOWN, &adapter->flags))
-			e1000_irq_enable(adapter);
-	}
-
-	return work_done;
-}
-
-/**
- * e1000_clean_tx_irq - Reclaim resources after transmit completes
- * @adapter: board private structure
- **/
-static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
-			       struct e1000_tx_ring *tx_ring)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	struct e1000_tx_desc *tx_desc, *eop_desc;
-	struct e1000_buffer *buffer_info;
-	unsigned int i, eop;
-	unsigned int count = 0;
-	unsigned int total_tx_bytes=0, total_tx_packets=0;
-
-	i = tx_ring->next_to_clean;
-	eop = tx_ring->buffer_info[i].next_to_watch;
-	eop_desc = E1000_TX_DESC(*tx_ring, eop);
-
-	while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
-	       (count < tx_ring->count)) {
-		bool cleaned = false;
-		rmb();	/* read buffer_info after eop_desc */
-		for ( ; !cleaned; count++) {
-			tx_desc = E1000_TX_DESC(*tx_ring, i);
-			buffer_info = &tx_ring->buffer_info[i];
-			cleaned = (i == eop);
-
-			if (cleaned) {
-				struct sk_buff *skb = buffer_info->skb;
-				unsigned int segs, bytecount;
-				segs = skb_shinfo(skb)->gso_segs ?: 1;
-				/* multiply data chunks by size of headers */
-				bytecount = ((segs - 1) * skb_headlen(skb)) +
-				            skb->len;
-				total_tx_packets += segs;
-				total_tx_bytes += bytecount;
-			}
-			e1000_unmap_and_free_tx_resource(adapter, buffer_info);
-			tx_desc->upper.data = 0;
-
-			if (unlikely(++i == tx_ring->count)) i = 0;
-		}
-
-		eop = tx_ring->buffer_info[i].next_to_watch;
-		eop_desc = E1000_TX_DESC(*tx_ring, eop);
-	}
-
-	tx_ring->next_to_clean = i;
-
-#define TX_WAKE_THRESHOLD 32
-	if (unlikely(count && netif_carrier_ok(netdev) &&
-		     E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) {
-		/* Make sure that anybody stopping the queue after this
-		 * sees the new next_to_clean.
-		 */
-		smp_mb();
-
-		if (netif_queue_stopped(netdev) &&
-		    !(test_bit(__E1000_DOWN, &adapter->flags))) {
-			netif_wake_queue(netdev);
-			++adapter->restart_queue;
-		}
-	}
-
-	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[eop].time_stamp &&
-		    time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
-		               (adapter->tx_timeout_factor * HZ)) &&
-		    !(er32(STATUS) & E1000_STATUS_TXOFF)) {
-
-			/* detected Tx unit hang */
-			e_err(drv, "Detected Tx Unit Hang\n"
-			      "  Tx Queue             <%lu>\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",
-				(unsigned long)((tx_ring - adapter->tx_ring) /
-					sizeof(struct e1000_tx_ring)),
-				readl(hw->hw_addr + tx_ring->tdh),
-				readl(hw->hw_addr + tx_ring->tdt),
-				tx_ring->next_to_use,
-				tx_ring->next_to_clean,
-				tx_ring->buffer_info[eop].time_stamp,
-				eop,
-				jiffies,
-				eop_desc->upper.fields.status);
-			netif_stop_queue(netdev);
-		}
-	}
-	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;
-}
-
-/**
- * e1000_rx_checksum - Receive Checksum Offload for 82543
- * @adapter:     board private structure
- * @status_err:  receive descriptor status and error fields
- * @csum:        receive descriptor csum field
- * @sk_buff:     socket buffer with received data
- **/
-
-static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
-			      u32 csum, struct sk_buff *skb)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u16 status = (u16)status_err;
-	u8 errors = (u8)(status_err >> 24);
-
-	skb_checksum_none_assert(skb);
-
-	/* 82543 or newer only */
-	if (unlikely(hw->mac_type < e1000_82543)) return;
-	/* Ignore Checksum bit is set */
-	if (unlikely(status & E1000_RXD_STAT_IXSM)) return;
-	/* TCP/UDP checksum error bit is set */
-	if (unlikely(errors & E1000_RXD_ERR_TCPE)) {
-		/* let the stack verify checksum errors */
-		adapter->hw_csum_err++;
-		return;
-	}
-	/* TCP/UDP Checksum has not been calculated */
-	if (!(status & E1000_RXD_STAT_TCPCS))
-		return;
-
-	/* It must be a TCP or UDP packet with a valid checksum */
-	if (likely(status & E1000_RXD_STAT_TCPCS)) {
-		/* TCP checksum is good */
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	}
-	adapter->hw_csum_good++;
-}
-
-/**
- * e1000_consume_page - helper function
- **/
-static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb,
-                               u16 length)
-{
-	bi->page = NULL;
-	skb->len += length;
-	skb->data_len += length;
-	skb->truesize += length;
-}
-
-/**
- * e1000_receive_skb - helper function to handle rx indications
- * @adapter: board private structure
- * @status: descriptor status field as written by hardware
- * @vlan: descriptor vlan field as written by hardware (no le/be conversion)
- * @skb: pointer to sk_buff to be indicated to stack
- */
-static void e1000_receive_skb(struct e1000_adapter *adapter, u8 status,
-			      __le16 vlan, struct sk_buff *skb)
-{
-	skb->protocol = eth_type_trans(skb, adapter->netdev);
-
-	if (status & E1000_RXD_STAT_VP) {
-		u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
-
-		__vlan_hwaccel_put_tag(skb, vid);
-	}
-	napi_gro_receive(&adapter->napi, skb);
-}
-
-/**
- * e1000_clean_jumbo_rx_irq - Send received data up the network stack; legacy
- * @adapter: board private structure
- * @rx_ring: ring to clean
- * @work_done: amount of napi work completed this call
- * @work_to_do: max amount of work allowed for this call to do
- *
- * the return value indicates whether actual cleaning was done, there
- * is no guarantee that everything was cleaned
- */
-static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
-				     struct e1000_rx_ring *rx_ring,
-				     int *work_done, int work_to_do)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_rx_desc *rx_desc, *next_rxd;
-	struct e1000_buffer *buffer_info, *next_buffer;
-	unsigned long irq_flags;
-	u32 length;
-	unsigned int i;
-	int cleaned_count = 0;
-	bool cleaned = false;
-	unsigned int total_rx_bytes=0, total_rx_packets=0;
-
-	i = rx_ring->next_to_clean;
-	rx_desc = E1000_RX_DESC(*rx_ring, i);
-	buffer_info = &rx_ring->buffer_info[i];
-
-	while (rx_desc->status & E1000_RXD_STAT_DD) {
-		struct sk_buff *skb;
-		u8 status;
-
-		if (*work_done >= work_to_do)
-			break;
-		(*work_done)++;
-		rmb(); /* read descriptor and rx_buffer_info after status DD */
-
-		status = rx_desc->status;
-		skb = buffer_info->skb;
-		buffer_info->skb = NULL;
-
-		if (++i == rx_ring->count) i = 0;
-		next_rxd = E1000_RX_DESC(*rx_ring, i);
-		prefetch(next_rxd);
-
-		next_buffer = &rx_ring->buffer_info[i];
-
-		cleaned = true;
-		cleaned_count++;
-		dma_unmap_page(&pdev->dev, buffer_info->dma,
-			       buffer_info->length, DMA_FROM_DEVICE);
-		buffer_info->dma = 0;
-
-		length = le16_to_cpu(rx_desc->length);
-
-		/* errors is only valid for DD + EOP descriptors */
-		if (unlikely((status & E1000_RXD_STAT_EOP) &&
-		    (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK))) {
-			u8 last_byte = *(skb->data + length - 1);
-			if (TBI_ACCEPT(hw, status, rx_desc->errors, length,
-				       last_byte)) {
-				spin_lock_irqsave(&adapter->stats_lock,
-				                  irq_flags);
-				e1000_tbi_adjust_stats(hw, &adapter->stats,
-				                       length, skb->data);
-				spin_unlock_irqrestore(&adapter->stats_lock,
-				                       irq_flags);
-				length--;
-			} else {
-				/* recycle both page and skb */
-				buffer_info->skb = skb;
-				/* an error means any chain goes out the window
-				 * too */
-				if (rx_ring->rx_skb_top)
-					dev_kfree_skb(rx_ring->rx_skb_top);
-				rx_ring->rx_skb_top = NULL;
-				goto next_desc;
-			}
-		}
-
-#define rxtop rx_ring->rx_skb_top
-		if (!(status & E1000_RXD_STAT_EOP)) {
-			/* this descriptor is only the beginning (or middle) */
-			if (!rxtop) {
-				/* this is the beginning of a chain */
-				rxtop = skb;
-				skb_fill_page_desc(rxtop, 0, buffer_info->page,
-				                   0, length);
-			} else {
-				/* this is the middle of a chain */
-				skb_fill_page_desc(rxtop,
-				    skb_shinfo(rxtop)->nr_frags,
-				    buffer_info->page, 0, length);
-				/* re-use the skb, only consumed the page */
-				buffer_info->skb = skb;
-			}
-			e1000_consume_page(buffer_info, rxtop, length);
-			goto next_desc;
-		} else {
-			if (rxtop) {
-				/* end of the chain */
-				skb_fill_page_desc(rxtop,
-				    skb_shinfo(rxtop)->nr_frags,
-				    buffer_info->page, 0, length);
-				/* re-use the current skb, we only consumed the
-				 * page */
-				buffer_info->skb = skb;
-				skb = rxtop;
-				rxtop = NULL;
-				e1000_consume_page(buffer_info, skb, length);
-			} else {
-				/* no chain, got EOP, this buf is the packet
-				 * copybreak to save the put_page/alloc_page */
-				if (length <= copybreak &&
-				    skb_tailroom(skb) >= length) {
-					u8 *vaddr;
-					vaddr = kmap_atomic(buffer_info->page,
-					                    KM_SKB_DATA_SOFTIRQ);
-					memcpy(skb_tail_pointer(skb), vaddr, length);
-					kunmap_atomic(vaddr,
-					              KM_SKB_DATA_SOFTIRQ);
-					/* re-use the page, so don't erase
-					 * buffer_info->page */
-					skb_put(skb, length);
-				} else {
-					skb_fill_page_desc(skb, 0,
-					                   buffer_info->page, 0,
-				                           length);
-					e1000_consume_page(buffer_info, skb,
-					                   length);
-				}
-			}
-		}
-
-		/* Receive Checksum Offload XXX recompute due to CRC strip? */
-		e1000_rx_checksum(adapter,
-		                  (u32)(status) |
-		                  ((u32)(rx_desc->errors) << 24),
-		                  le16_to_cpu(rx_desc->csum), skb);
-
-		pskb_trim(skb, skb->len - 4);
-
-		/* probably a little skewed due to removing CRC */
-		total_rx_bytes += skb->len;
-		total_rx_packets++;
-
-		/* eth type trans needs skb->data to point to something */
-		if (!pskb_may_pull(skb, ETH_HLEN)) {
-			e_err(drv, "pskb_may_pull failed.\n");
-			dev_kfree_skb(skb);
-			goto next_desc;
-		}
-
-		e1000_receive_skb(adapter, status, rx_desc->special, skb);
-
-next_desc:
-		rx_desc->status = 0;
-
-		/* return some buffers to hardware, one at a time is too slow */
-		if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
-			adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
-			cleaned_count = 0;
-		}
-
-		/* use prefetched values */
-		rx_desc = next_rxd;
-		buffer_info = next_buffer;
-	}
-	rx_ring->next_to_clean = i;
-
-	cleaned_count = E1000_DESC_UNUSED(rx_ring);
-	if (cleaned_count)
-		adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
-
-	adapter->total_rx_packets += total_rx_packets;
-	adapter->total_rx_bytes += total_rx_bytes;
-	netdev->stats.rx_bytes += total_rx_bytes;
-	netdev->stats.rx_packets += total_rx_packets;
-	return cleaned;
-}
-
-/*
- * this should improve performance for small packets with large amounts
- * of reassembly being done in the stack
- */
-static void e1000_check_copybreak(struct net_device *netdev,
-				 struct e1000_buffer *buffer_info,
-				 u32 length, struct sk_buff **skb)
-{
-	struct sk_buff *new_skb;
-
-	if (length > copybreak)
-		return;
-
-	new_skb = netdev_alloc_skb_ip_align(netdev, length);
-	if (!new_skb)
-		return;
-
-	skb_copy_to_linear_data_offset(new_skb, -NET_IP_ALIGN,
-				       (*skb)->data - NET_IP_ALIGN,
-				       length + NET_IP_ALIGN);
-	/* save the skb in buffer_info as good */
-	buffer_info->skb = *skb;
-	*skb = new_skb;
-}
-
-/**
- * e1000_clean_rx_irq - Send received data up the network stack; legacy
- * @adapter: board private structure
- * @rx_ring: ring to clean
- * @work_done: amount of napi work completed this call
- * @work_to_do: max amount of work allowed for this call to do
- */
-static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
-			       struct e1000_rx_ring *rx_ring,
-			       int *work_done, int work_to_do)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_rx_desc *rx_desc, *next_rxd;
-	struct e1000_buffer *buffer_info, *next_buffer;
-	unsigned long flags;
-	u32 length;
-	unsigned int i;
-	int cleaned_count = 0;
-	bool cleaned = false;
-	unsigned int total_rx_bytes=0, total_rx_packets=0;
-
-	i = rx_ring->next_to_clean;
-	rx_desc = E1000_RX_DESC(*rx_ring, i);
-	buffer_info = &rx_ring->buffer_info[i];
-
-	while (rx_desc->status & E1000_RXD_STAT_DD) {
-		struct sk_buff *skb;
-		u8 status;
-
-		if (*work_done >= work_to_do)
-			break;
-		(*work_done)++;
-		rmb(); /* read descriptor and rx_buffer_info after status DD */
-
-		status = rx_desc->status;
-		skb = buffer_info->skb;
-		buffer_info->skb = NULL;
-
-		prefetch(skb->data - NET_IP_ALIGN);
-
-		if (++i == rx_ring->count) i = 0;
-		next_rxd = E1000_RX_DESC(*rx_ring, i);
-		prefetch(next_rxd);
-
-		next_buffer = &rx_ring->buffer_info[i];
-
-		cleaned = true;
-		cleaned_count++;
-		dma_unmap_single(&pdev->dev, buffer_info->dma,
-				 buffer_info->length, DMA_FROM_DEVICE);
-		buffer_info->dma = 0;
-
-		length = le16_to_cpu(rx_desc->length);
-		/* !EOP means multiple descriptors were used to store a single
-		 * packet, if thats the case we need to toss it.  In fact, we
-		 * to toss every packet with the EOP bit clear and the next
-		 * frame that _does_ have the EOP bit set, as it is by
-		 * definition only a frame fragment
-		 */
-		if (unlikely(!(status & E1000_RXD_STAT_EOP)))
-			adapter->discarding = true;
-
-		if (adapter->discarding) {
-			/* All receives must fit into a single buffer */
-			e_dbg("Receive packet consumed multiple buffers\n");
-			/* recycle */
-			buffer_info->skb = skb;
-			if (status & E1000_RXD_STAT_EOP)
-				adapter->discarding = false;
-			goto next_desc;
-		}
-
-		if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
-			u8 last_byte = *(skb->data + length - 1);
-			if (TBI_ACCEPT(hw, status, rx_desc->errors, length,
-				       last_byte)) {
-				spin_lock_irqsave(&adapter->stats_lock, flags);
-				e1000_tbi_adjust_stats(hw, &adapter->stats,
-				                       length, skb->data);
-				spin_unlock_irqrestore(&adapter->stats_lock,
-				                       flags);
-				length--;
-			} else {
-				/* recycle */
-				buffer_info->skb = skb;
-				goto next_desc;
-			}
-		}
-
-		/* adjust length to remove Ethernet CRC, this must be
-		 * done after the TBI_ACCEPT workaround above */
-		length -= 4;
-
-		/* probably a little skewed due to removing CRC */
-		total_rx_bytes += length;
-		total_rx_packets++;
-
-		e1000_check_copybreak(netdev, buffer_info, length, &skb);
-
-		skb_put(skb, length);
-
-		/* Receive Checksum Offload */
-		e1000_rx_checksum(adapter,
-				  (u32)(status) |
-				  ((u32)(rx_desc->errors) << 24),
-				  le16_to_cpu(rx_desc->csum), skb);
-
-		e1000_receive_skb(adapter, status, rx_desc->special, skb);
-
-next_desc:
-		rx_desc->status = 0;
-
-		/* return some buffers to hardware, one at a time is too slow */
-		if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
-			adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
-			cleaned_count = 0;
-		}
-
-		/* use prefetched values */
-		rx_desc = next_rxd;
-		buffer_info = next_buffer;
-	}
-	rx_ring->next_to_clean = i;
-
-	cleaned_count = E1000_DESC_UNUSED(rx_ring);
-	if (cleaned_count)
-		adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
-
-	adapter->total_rx_packets += total_rx_packets;
-	adapter->total_rx_bytes += total_rx_bytes;
-	netdev->stats.rx_bytes += total_rx_bytes;
-	netdev->stats.rx_packets += total_rx_packets;
-	return cleaned;
-}
-
-/**
- * e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers
- * @adapter: address of board private structure
- * @rx_ring: pointer to receive ring structure
- * @cleaned_count: number of buffers to allocate this pass
- **/
-
-static void
-e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
-                             struct e1000_rx_ring *rx_ring, int cleaned_count)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_rx_desc *rx_desc;
-	struct e1000_buffer *buffer_info;
-	struct sk_buff *skb;
-	unsigned int i;
-	unsigned int bufsz = 256 - 16 /*for skb_reserve */ ;
-
-	i = rx_ring->next_to_use;
-	buffer_info = &rx_ring->buffer_info[i];
-
-	while (cleaned_count--) {
-		skb = buffer_info->skb;
-		if (skb) {
-			skb_trim(skb, 0);
-			goto check_page;
-		}
-
-		skb = netdev_alloc_skb_ip_align(netdev, bufsz);
-		if (unlikely(!skb)) {
-			/* Better luck next round */
-			adapter->alloc_rx_buff_failed++;
-			break;
-		}
-
-		/* Fix for errata 23, can't cross 64kB boundary */
-		if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
-			struct sk_buff *oldskb = skb;
-			e_err(rx_err, "skb align check failed: %u bytes at "
-			      "%p\n", bufsz, skb->data);
-			/* Try again, without freeing the previous */
-			skb = netdev_alloc_skb_ip_align(netdev, bufsz);
-			/* Failed allocation, critical failure */
-			if (!skb) {
-				dev_kfree_skb(oldskb);
-				adapter->alloc_rx_buff_failed++;
-				break;
-			}
-
-			if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
-				/* give up */
-				dev_kfree_skb(skb);
-				dev_kfree_skb(oldskb);
-				break; /* while (cleaned_count--) */
-			}
-
-			/* Use new allocation */
-			dev_kfree_skb(oldskb);
-		}
-		buffer_info->skb = skb;
-		buffer_info->length = adapter->rx_buffer_len;
-check_page:
-		/* allocate a new page if necessary */
-		if (!buffer_info->page) {
-			buffer_info->page = alloc_page(GFP_ATOMIC);
-			if (unlikely(!buffer_info->page)) {
-				adapter->alloc_rx_buff_failed++;
-				break;
-			}
-		}
-
-		if (!buffer_info->dma) {
-			buffer_info->dma = dma_map_page(&pdev->dev,
-			                                buffer_info->page, 0,
-							buffer_info->length,
-							DMA_FROM_DEVICE);
-			if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
-				put_page(buffer_info->page);
-				dev_kfree_skb(skb);
-				buffer_info->page = NULL;
-				buffer_info->skb = NULL;
-				buffer_info->dma = 0;
-				adapter->alloc_rx_buff_failed++;
-				break; /* while !buffer_info->skb */
-			}
-		}
-
-		rx_desc = E1000_RX_DESC(*rx_ring, i);
-		rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
-
-		if (unlikely(++i == rx_ring->count))
-			i = 0;
-		buffer_info = &rx_ring->buffer_info[i];
-	}
-
-	if (likely(rx_ring->next_to_use != i)) {
-		rx_ring->next_to_use = i;
-		if (unlikely(i-- == 0))
-			i = (rx_ring->count - 1);
-
-		/* Force memory writes to complete before letting h/w
-		 * know there are new descriptors to fetch.  (Only
-		 * applicable for weak-ordered memory model archs,
-		 * such as IA-64). */
-		wmb();
-		writel(i, adapter->hw.hw_addr + rx_ring->rdt);
-	}
-}
-
-/**
- * e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended
- * @adapter: address of board private structure
- **/
-
-static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
-				   struct e1000_rx_ring *rx_ring,
-				   int cleaned_count)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_rx_desc *rx_desc;
-	struct e1000_buffer *buffer_info;
-	struct sk_buff *skb;
-	unsigned int i;
-	unsigned int bufsz = adapter->rx_buffer_len;
-
-	i = rx_ring->next_to_use;
-	buffer_info = &rx_ring->buffer_info[i];
-
-	while (cleaned_count--) {
-		skb = buffer_info->skb;
-		if (skb) {
-			skb_trim(skb, 0);
-			goto map_skb;
-		}
-
-		skb = netdev_alloc_skb_ip_align(netdev, bufsz);
-		if (unlikely(!skb)) {
-			/* Better luck next round */
-			adapter->alloc_rx_buff_failed++;
-			break;
-		}
-
-		/* Fix for errata 23, can't cross 64kB boundary */
-		if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
-			struct sk_buff *oldskb = skb;
-			e_err(rx_err, "skb align check failed: %u bytes at "
-			      "%p\n", bufsz, skb->data);
-			/* Try again, without freeing the previous */
-			skb = netdev_alloc_skb_ip_align(netdev, bufsz);
-			/* Failed allocation, critical failure */
-			if (!skb) {
-				dev_kfree_skb(oldskb);
-				adapter->alloc_rx_buff_failed++;
-				break;
-			}
-
-			if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
-				/* give up */
-				dev_kfree_skb(skb);
-				dev_kfree_skb(oldskb);
-				adapter->alloc_rx_buff_failed++;
-				break; /* while !buffer_info->skb */
-			}
-
-			/* Use new allocation */
-			dev_kfree_skb(oldskb);
-		}
-		buffer_info->skb = skb;
-		buffer_info->length = adapter->rx_buffer_len;
-map_skb:
-		buffer_info->dma = dma_map_single(&pdev->dev,
-						  skb->data,
-						  buffer_info->length,
-						  DMA_FROM_DEVICE);
-		if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
-			dev_kfree_skb(skb);
-			buffer_info->skb = NULL;
-			buffer_info->dma = 0;
-			adapter->alloc_rx_buff_failed++;
-			break; /* while !buffer_info->skb */
-		}
-
-		/*
-		 * XXX if it was allocated cleanly it will never map to a
-		 * boundary crossing
-		 */
-
-		/* Fix for errata 23, can't cross 64kB boundary */
-		if (!e1000_check_64k_bound(adapter,
-					(void *)(unsigned long)buffer_info->dma,
-					adapter->rx_buffer_len)) {
-			e_err(rx_err, "dma align check failed: %u bytes at "
-			      "%p\n", adapter->rx_buffer_len,
-			      (void *)(unsigned long)buffer_info->dma);
-			dev_kfree_skb(skb);
-			buffer_info->skb = NULL;
-
-			dma_unmap_single(&pdev->dev, buffer_info->dma,
-					 adapter->rx_buffer_len,
-					 DMA_FROM_DEVICE);
-			buffer_info->dma = 0;
-
-			adapter->alloc_rx_buff_failed++;
-			break; /* while !buffer_info->skb */
-		}
-		rx_desc = E1000_RX_DESC(*rx_ring, i);
-		rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
-
-		if (unlikely(++i == rx_ring->count))
-			i = 0;
-		buffer_info = &rx_ring->buffer_info[i];
-	}
-
-	if (likely(rx_ring->next_to_use != i)) {
-		rx_ring->next_to_use = i;
-		if (unlikely(i-- == 0))
-			i = (rx_ring->count - 1);
-
-		/* Force memory writes to complete before letting h/w
-		 * know there are new descriptors to fetch.  (Only
-		 * applicable for weak-ordered memory model archs,
-		 * such as IA-64). */
-		wmb();
-		writel(i, hw->hw_addr + rx_ring->rdt);
-	}
-}
-
-/**
- * e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers.
- * @adapter:
- **/
-
-static void e1000_smartspeed(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u16 phy_status;
-	u16 phy_ctrl;
-
-	if ((hw->phy_type != e1000_phy_igp) || !hw->autoneg ||
-	   !(hw->autoneg_advertised & ADVERTISE_1000_FULL))
-		return;
-
-	if (adapter->smartspeed == 0) {
-		/* If Master/Slave config fault is asserted twice,
-		 * we assume back-to-back */
-		e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status);
-		if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
-		e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status);
-		if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
-		e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl);
-		if (phy_ctrl & CR_1000T_MS_ENABLE) {
-			phy_ctrl &= ~CR_1000T_MS_ENABLE;
-			e1000_write_phy_reg(hw, PHY_1000T_CTRL,
-					    phy_ctrl);
-			adapter->smartspeed++;
-			if (!e1000_phy_setup_autoneg(hw) &&
-			   !e1000_read_phy_reg(hw, PHY_CTRL,
-				   	       &phy_ctrl)) {
-				phy_ctrl |= (MII_CR_AUTO_NEG_EN |
-					     MII_CR_RESTART_AUTO_NEG);
-				e1000_write_phy_reg(hw, PHY_CTRL,
-						    phy_ctrl);
-			}
-		}
-		return;
-	} else if (adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
-		/* If still no link, perhaps using 2/3 pair cable */
-		e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl);
-		phy_ctrl |= CR_1000T_MS_ENABLE;
-		e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_ctrl);
-		if (!e1000_phy_setup_autoneg(hw) &&
-		   !e1000_read_phy_reg(hw, PHY_CTRL, &phy_ctrl)) {
-			phy_ctrl |= (MII_CR_AUTO_NEG_EN |
-				     MII_CR_RESTART_AUTO_NEG);
-			e1000_write_phy_reg(hw, PHY_CTRL, phy_ctrl);
-		}
-	}
-	/* Restart process after E1000_SMARTSPEED_MAX iterations */
-	if (adapter->smartspeed++ == E1000_SMARTSPEED_MAX)
-		adapter->smartspeed = 0;
-}
-
-/**
- * e1000_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- **/
-
-static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	switch (cmd) {
-	case SIOCGMIIPHY:
-	case SIOCGMIIREG:
-	case SIOCSMIIREG:
-		return e1000_mii_ioctl(netdev, ifr, cmd);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-/**
- * e1000_mii_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- **/
-
-static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
-			   int cmd)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	struct mii_ioctl_data *data = if_mii(ifr);
-	int retval;
-	u16 mii_reg;
-	unsigned long flags;
-
-	if (hw->media_type != e1000_media_type_copper)
-		return -EOPNOTSUPP;
-
-	switch (cmd) {
-	case SIOCGMIIPHY:
-		data->phy_id = hw->phy_addr;
-		break;
-	case SIOCGMIIREG:
-		spin_lock_irqsave(&adapter->stats_lock, flags);
-		if (e1000_read_phy_reg(hw, data->reg_num & 0x1F,
-				   &data->val_out)) {
-			spin_unlock_irqrestore(&adapter->stats_lock, flags);
-			return -EIO;
-		}
-		spin_unlock_irqrestore(&adapter->stats_lock, flags);
-		break;
-	case SIOCSMIIREG:
-		if (data->reg_num & ~(0x1F))
-			return -EFAULT;
-		mii_reg = data->val_in;
-		spin_lock_irqsave(&adapter->stats_lock, flags);
-		if (e1000_write_phy_reg(hw, data->reg_num,
-					mii_reg)) {
-			spin_unlock_irqrestore(&adapter->stats_lock, flags);
-			return -EIO;
-		}
-		spin_unlock_irqrestore(&adapter->stats_lock, flags);
-		if (hw->media_type == e1000_media_type_copper) {
-			switch (data->reg_num) {
-			case PHY_CTRL:
-				if (mii_reg & MII_CR_POWER_DOWN)
-					break;
-				if (mii_reg & MII_CR_AUTO_NEG_EN) {
-					hw->autoneg = 1;
-					hw->autoneg_advertised = 0x2F;
-				} else {
-					u32 speed;
-					if (mii_reg & 0x40)
-						speed = SPEED_1000;
-					else if (mii_reg & 0x2000)
-						speed = SPEED_100;
-					else
-						speed = SPEED_10;
-					retval = e1000_set_spd_dplx(
-						adapter, speed,
-						((mii_reg & 0x100)
-						 ? DUPLEX_FULL :
-						 DUPLEX_HALF));
-					if (retval)
-						return retval;
-				}
-				if (netif_running(adapter->netdev))
-					e1000_reinit_locked(adapter);
-				else
-					e1000_reset(adapter);
-				break;
-			case M88E1000_PHY_SPEC_CTRL:
-			case M88E1000_EXT_PHY_SPEC_CTRL:
-				if (e1000_phy_reset(hw))
-					return -EIO;
-				break;
-			}
-		} else {
-			switch (data->reg_num) {
-			case PHY_CTRL:
-				if (mii_reg & MII_CR_POWER_DOWN)
-					break;
-				if (netif_running(adapter->netdev))
-					e1000_reinit_locked(adapter);
-				else
-					e1000_reset(adapter);
-				break;
-			}
-		}
-		break;
-	default:
-		return -EOPNOTSUPP;
-	}
-	return E1000_SUCCESS;
-}
-
-void e1000_pci_set_mwi(struct e1000_hw *hw)
-{
-	struct e1000_adapter *adapter = hw->back;
-	int ret_val = pci_set_mwi(adapter->pdev);
-
-	if (ret_val)
-		e_err(probe, "Error in setting MWI\n");
-}
-
-void e1000_pci_clear_mwi(struct e1000_hw *hw)
-{
-	struct e1000_adapter *adapter = hw->back;
-
-	pci_clear_mwi(adapter->pdev);
-}
-
-int e1000_pcix_get_mmrbc(struct e1000_hw *hw)
-{
-	struct e1000_adapter *adapter = hw->back;
-	return pcix_get_mmrbc(adapter->pdev);
-}
-
-void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc)
-{
-	struct e1000_adapter *adapter = hw->back;
-	pcix_set_mmrbc(adapter->pdev, mmrbc);
-}
-
-void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value)
-{
-	outl(value, port);
-}
-
-static bool e1000_vlan_used(struct e1000_adapter *adapter)
-{
-	u16 vid;
-
-	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
-		return true;
-	return false;
-}
-
-static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter,
-				     bool filter_on)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 rctl;
-
-	if (!test_bit(__E1000_DOWN, &adapter->flags))
-		e1000_irq_disable(adapter);
-
-	if (filter_on) {
-		/* enable VLAN receive filtering */
-		rctl = er32(RCTL);
-		rctl &= ~E1000_RCTL_CFIEN;
-		if (!(adapter->netdev->flags & IFF_PROMISC))
-			rctl |= E1000_RCTL_VFE;
-		ew32(RCTL, rctl);
-		e1000_update_mng_vlan(adapter);
-	} else {
-		/* disable VLAN receive filtering */
-		rctl = er32(RCTL);
-		rctl &= ~E1000_RCTL_VFE;
-		ew32(RCTL, rctl);
-	}
-
-	if (!test_bit(__E1000_DOWN, &adapter->flags))
-		e1000_irq_enable(adapter);
-}
-
-static void e1000_vlan_mode(struct net_device *netdev, u32 features)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u32 ctrl;
-
-	if (!test_bit(__E1000_DOWN, &adapter->flags))
-		e1000_irq_disable(adapter);
-
-	ctrl = er32(CTRL);
-	if (features & NETIF_F_HW_VLAN_RX) {
-		/* enable VLAN tag insert/strip */
-		ctrl |= E1000_CTRL_VME;
-	} else {
-		/* disable VLAN tag insert/strip */
-		ctrl &= ~E1000_CTRL_VME;
-	}
-	ew32(CTRL, ctrl);
-
-	if (!test_bit(__E1000_DOWN, &adapter->flags))
-		e1000_irq_enable(adapter);
-}
-
-static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u32 vfta, index;
-
-	if ((hw->mng_cookie.status &
-	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
-	    (vid == adapter->mng_vlan_id))
-		return;
-
-	if (!e1000_vlan_used(adapter))
-		e1000_vlan_filter_on_off(adapter, true);
-
-	/* add VID to filter table */
-	index = (vid >> 5) & 0x7F;
-	vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
-	vfta |= (1 << (vid & 0x1F));
-	e1000_write_vfta(hw, index, vfta);
-
-	set_bit(vid, adapter->active_vlans);
-}
-
-static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u32 vfta, index;
-
-	if (!test_bit(__E1000_DOWN, &adapter->flags))
-		e1000_irq_disable(adapter);
-	if (!test_bit(__E1000_DOWN, &adapter->flags))
-		e1000_irq_enable(adapter);
-
-	/* remove VID from filter table */
-	index = (vid >> 5) & 0x7F;
-	vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
-	vfta &= ~(1 << (vid & 0x1F));
-	e1000_write_vfta(hw, index, vfta);
-
-	clear_bit(vid, adapter->active_vlans);
-
-	if (!e1000_vlan_used(adapter))
-		e1000_vlan_filter_on_off(adapter, false);
-}
-
-static void e1000_restore_vlan(struct e1000_adapter *adapter)
-{
-	u16 vid;
-
-	if (!e1000_vlan_used(adapter))
-		return;
-
-	e1000_vlan_filter_on_off(adapter, true);
-	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
-		e1000_vlan_rx_add_vid(adapter->netdev, vid);
-}
-
-int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx)
-{
-	struct e1000_hw *hw = &adapter->hw;
-
-	hw->autoneg = 0;
-
-	/* Make sure dplx is at most 1 bit and lsb of speed is not set
-	 * for the switch() below to work */
-	if ((spd & 1) || (dplx & ~1))
-		goto err_inval;
-
-	/* Fiber NICs only allow 1000 gbps Full duplex */
-	if ((hw->media_type == e1000_media_type_fiber) &&
-	    spd != SPEED_1000 &&
-	    dplx != DUPLEX_FULL)
-		goto err_inval;
-
-	switch (spd + dplx) {
-	case SPEED_10 + DUPLEX_HALF:
-		hw->forced_speed_duplex = e1000_10_half;
-		break;
-	case SPEED_10 + DUPLEX_FULL:
-		hw->forced_speed_duplex = e1000_10_full;
-		break;
-	case SPEED_100 + DUPLEX_HALF:
-		hw->forced_speed_duplex = e1000_100_half;
-		break;
-	case SPEED_100 + DUPLEX_FULL:
-		hw->forced_speed_duplex = e1000_100_full;
-		break;
-	case SPEED_1000 + DUPLEX_FULL:
-		hw->autoneg = 1;
-		hw->autoneg_advertised = ADVERTISE_1000_FULL;
-		break;
-	case SPEED_1000 + DUPLEX_HALF: /* not supported */
-	default:
-		goto err_inval;
-	}
-	return 0;
-
-err_inval:
-	e_err(probe, "Unsupported Speed/Duplex configuration\n");
-	return -EINVAL;
-}
-
-static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u32 ctrl, ctrl_ext, rctl, status;
-	u32 wufc = adapter->wol;
-#ifdef CONFIG_PM
-	int retval = 0;
-#endif
-
-	netif_device_detach(netdev);
-
-	if (netif_running(netdev)) {
-		WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
-		e1000_down(adapter);
-	}
-
-#ifdef CONFIG_PM
-	retval = pci_save_state(pdev);
-	if (retval)
-		return retval;
-#endif
-
-	status = er32(STATUS);
-	if (status & E1000_STATUS_LU)
-		wufc &= ~E1000_WUFC_LNKC;
-
-	if (wufc) {
-		e1000_setup_rctl(adapter);
-		e1000_set_rx_mode(netdev);
-
-		/* turn on all-multi mode if wake on multicast is enabled */
-		if (wufc & E1000_WUFC_MC) {
-			rctl = er32(RCTL);
-			rctl |= E1000_RCTL_MPE;
-			ew32(RCTL, rctl);
-		}
-
-		if (hw->mac_type >= e1000_82540) {
-			ctrl = er32(CTRL);
-			/* advertise wake from D3Cold */
-			#define E1000_CTRL_ADVD3WUC 0x00100000
-			/* phy power management enable */
-			#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000
-			ctrl |= E1000_CTRL_ADVD3WUC |
-				E1000_CTRL_EN_PHY_PWR_MGMT;
-			ew32(CTRL, ctrl);
-		}
-
-		if (hw->media_type == e1000_media_type_fiber ||
-		    hw->media_type == e1000_media_type_internal_serdes) {
-			/* keep the laser running in D3 */
-			ctrl_ext = er32(CTRL_EXT);
-			ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
-			ew32(CTRL_EXT, ctrl_ext);
-		}
-
-		ew32(WUC, E1000_WUC_PME_EN);
-		ew32(WUFC, wufc);
-	} else {
-		ew32(WUC, 0);
-		ew32(WUFC, 0);
-	}
-
-	e1000_release_manageability(adapter);
-
-	*enable_wake = !!wufc;
-
-	/* make sure adapter isn't asleep if manageability is enabled */
-	if (adapter->en_mng_pt)
-		*enable_wake = true;
-
-	if (netif_running(netdev))
-		e1000_free_irq(adapter);
-
-	pci_disable_device(pdev);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	int retval;
-	bool wake;
-
-	retval = __e1000_shutdown(pdev, &wake);
-	if (retval)
-		return retval;
-
-	if (wake) {
-		pci_prepare_to_sleep(pdev);
-	} else {
-		pci_wake_from_d3(pdev, false);
-		pci_set_power_state(pdev, PCI_D3hot);
-	}
-
-	return 0;
-}
-
-static int e1000_resume(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u32 err;
-
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	pci_save_state(pdev);
-
-	if (adapter->need_ioport)
-		err = pci_enable_device(pdev);
-	else
-		err = pci_enable_device_mem(pdev);
-	if (err) {
-		pr_err("Cannot enable PCI device from suspend\n");
-		return err;
-	}
-	pci_set_master(pdev);
-
-	pci_enable_wake(pdev, PCI_D3hot, 0);
-	pci_enable_wake(pdev, PCI_D3cold, 0);
-
-	if (netif_running(netdev)) {
-		err = e1000_request_irq(adapter);
-		if (err)
-			return err;
-	}
-
-	e1000_power_up_phy(adapter);
-	e1000_reset(adapter);
-	ew32(WUS, ~0);
-
-	e1000_init_manageability(adapter);
-
-	if (netif_running(netdev))
-		e1000_up(adapter);
-
-	netif_device_attach(netdev);
-
-	return 0;
-}
-#endif
-
-static void e1000_shutdown(struct pci_dev *pdev)
-{
-	bool wake;
-
-	__e1000_shutdown(pdev, &wake);
-
-	if (system_state == SYSTEM_POWER_OFF) {
-		pci_wake_from_d3(pdev, wake);
-		pci_set_power_state(pdev, PCI_D3hot);
-	}
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Polling 'interrupt' - used by things like netconsole to send skbs
- * without having to re-enable interrupts. It's not called while
- * the interrupt routine is executing.
- */
-static void e1000_netpoll(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	disable_irq(adapter->pdev->irq);
-	e1000_intr(adapter->pdev->irq, netdev);
-	enable_irq(adapter->pdev->irq);
-}
-#endif
-
-/**
- * e1000_io_error_detected - called when PCI error is detected
- * @pdev: Pointer to PCI device
- * @state: The current pci connection state
- *
- * This function is called after a PCI bus error affecting
- * this device has been detected.
- */
-static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
-						pci_channel_state_t state)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	netif_device_detach(netdev);
-
-	if (state == pci_channel_io_perm_failure)
-		return PCI_ERS_RESULT_DISCONNECT;
-
-	if (netif_running(netdev))
-		e1000_down(adapter);
-	pci_disable_device(pdev);
-
-	/* Request a slot slot reset. */
-	return PCI_ERS_RESULT_NEED_RESET;
-}
-
-/**
- * e1000_io_slot_reset - called after the pci bus has been reset.
- * @pdev: Pointer to PCI device
- *
- * Restart the card from scratch, as if from a cold-boot. Implementation
- * resembles the first-half of the e1000_resume routine.
- */
-static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	int err;
-
-	if (adapter->need_ioport)
-		err = pci_enable_device(pdev);
-	else
-		err = pci_enable_device_mem(pdev);
-	if (err) {
-		pr_err("Cannot re-enable PCI device after reset.\n");
-		return PCI_ERS_RESULT_DISCONNECT;
-	}
-	pci_set_master(pdev);
-
-	pci_enable_wake(pdev, PCI_D3hot, 0);
-	pci_enable_wake(pdev, PCI_D3cold, 0);
-
-	e1000_reset(adapter);
-	ew32(WUS, ~0);
-
-	return PCI_ERS_RESULT_RECOVERED;
-}
-
-/**
- * e1000_io_resume - called when traffic can start flowing again.
- * @pdev: Pointer to PCI device
- *
- * This callback is called when the error recovery driver tells us that
- * its OK to resume normal operation. Implementation resembles the
- * second-half of the e1000_resume routine.
- */
-static void e1000_io_resume(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	e1000_init_manageability(adapter);
-
-	if (netif_running(netdev)) {
-		if (e1000_up(adapter)) {
-			pr_info("can't bring device back up after reset\n");
-			return;
-		}
-	}
-
-	netif_device_attach(netdev);
-}
-
-/* e1000_main.c */
diff -druN linux-libre-3.1-gnu/drivers/net/e1000/e1000_osdep.h linux-libre-3.2-gnu/drivers/net/e1000/e1000_osdep.h
--- linux-libre-3.1-gnu/drivers/net/e1000/e1000_osdep.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000/e1000_osdep.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,109 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2006 Intel Corporation.
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms and conditions of the GNU General Public License,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-
-/* glue for the OS independent part of e1000
- * includes register access macros
- */
-
-#ifndef _E1000_OSDEP_H_
-#define _E1000_OSDEP_H_
-
-#include <asm/io.h>
-
-#define CONFIG_RAM_BASE         0x60000
-#define GBE_CONFIG_OFFSET       0x0
-
-#define GBE_CONFIG_RAM_BASE \
-	((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
-
-#define GBE_CONFIG_BASE_VIRT \
-	((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
-
-#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
-	(iowrite16_rep(base + offset, data, count))
-
-#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
-	(ioread16_rep(base + (offset << 1), data, count))
-
-#define er32(reg)							\
-	(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543)		\
-			       ? E1000_##reg : E1000_82542_##reg)))
-
-#define ew32(reg, value)						\
-	(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543)	\
-					 ? E1000_##reg : E1000_82542_##reg))))
-
-#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
-    writel((value), ((a)->hw_addr + \
-        (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
-        ((offset) << 2))))
-
-#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
-    readl((a)->hw_addr + \
-        (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
-        ((offset) << 2)))
-
-#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
-#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
-
-#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
-    writew((value), ((a)->hw_addr + \
-        (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
-        ((offset) << 1))))
-
-#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
-    readw((a)->hw_addr + \
-        (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
-        ((offset) << 1)))
-
-#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
-    writeb((value), ((a)->hw_addr + \
-        (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
-        (offset))))
-
-#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
-    readb((a)->hw_addr + \
-        (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
-        (offset)))
-
-#define E1000_WRITE_FLUSH() er32(STATUS)
-
-#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
-    writel((value), ((a)->flash_address + reg)))
-
-#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
-    readl((a)->flash_address + reg))
-
-#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
-    writew((value), ((a)->flash_address + reg)))
-
-#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
-    readw((a)->flash_address + reg))
-
-#endif /* _E1000_OSDEP_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/e1000/e1000_param.c linux-libre-3.2-gnu/drivers/net/e1000/e1000_param.c
--- linux-libre-3.1-gnu/drivers/net/e1000/e1000_param.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000/e1000_param.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,755 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2006 Intel Corporation.
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms and conditions of the GNU General Public License,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-#include "e1000.h"
-
-/* This is the only thing that needs to be changed to adjust the
- * maximum number of ports that the driver can manage.
- */
-
-#define E1000_MAX_NIC 32
-
-#define OPTION_UNSET   -1
-#define OPTION_DISABLED 0
-#define OPTION_ENABLED  1
-
-/* All parameters are treated the same, as an integer array of values.
- * This macro just reduces the need to repeat the same declaration code
- * over and over (plus this helps to avoid typo bugs).
- */
-
-#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
-#define E1000_PARAM(X, desc) \
-	static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
-	static unsigned int num_##X; \
-	module_param_array_named(X, X, int, &num_##X, 0); \
-	MODULE_PARM_DESC(X, desc);
-
-/* Transmit Descriptor Count
- *
- * Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
- * Valid Range: 80-4096 for 82544 and newer
- *
- * Default Value: 256
- */
-E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
-
-/* Receive Descriptor Count
- *
- * Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
- * Valid Range: 80-4096 for 82544 and newer
- *
- * Default Value: 256
- */
-E1000_PARAM(RxDescriptors, "Number of receive descriptors");
-
-/* User Specified Speed Override
- *
- * Valid Range: 0, 10, 100, 1000
- *  - 0    - auto-negotiate at all supported speeds
- *  - 10   - only link at 10 Mbps
- *  - 100  - only link at 100 Mbps
- *  - 1000 - only link at 1000 Mbps
- *
- * Default Value: 0
- */
-E1000_PARAM(Speed, "Speed setting");
-
-/* User Specified Duplex Override
- *
- * Valid Range: 0-2
- *  - 0 - auto-negotiate for duplex
- *  - 1 - only link at half duplex
- *  - 2 - only link at full duplex
- *
- * Default Value: 0
- */
-E1000_PARAM(Duplex, "Duplex setting");
-
-/* Auto-negotiation Advertisement Override
- *
- * Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
- *
- * The AutoNeg value is a bit mask describing which speed and duplex
- * combinations should be advertised during auto-negotiation.
- * The supported speed and duplex modes are listed below
- *
- * Bit           7     6     5      4      3     2     1      0
- * Speed (Mbps)  N/A   N/A   1000   N/A    100   100   10     10
- * Duplex                    Full          Full  Half  Full   Half
- *
- * Default Value: 0x2F (copper); 0x20 (fiber)
- */
-E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
-#define AUTONEG_ADV_DEFAULT  0x2F
-#define AUTONEG_ADV_MASK     0x2F
-
-/* User Specified Flow Control Override
- *
- * Valid Range: 0-3
- *  - 0 - No Flow Control
- *  - 1 - Rx only, respond to PAUSE frames but do not generate them
- *  - 2 - Tx only, generate PAUSE frames but ignore them on receive
- *  - 3 - Full Flow Control Support
- *
- * Default Value: Read flow control settings from the EEPROM
- */
-E1000_PARAM(FlowControl, "Flow Control setting");
-#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
-
-/* XsumRX - Receive Checksum Offload Enable/Disable
- *
- * Valid Range: 0, 1
- *  - 0 - disables all checksum offload
- *  - 1 - enables receive IP/TCP/UDP checksum offload
- *        on 82543 and newer -based NICs
- *
- * Default Value: 1
- */
-E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
-
-/* Transmit Interrupt Delay in units of 1.024 microseconds
- *  Tx interrupt delay needs to typically be set to something non zero
- *
- * Valid Range: 0-65535
- */
-E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
-#define DEFAULT_TIDV                   8
-#define MAX_TXDELAY               0xFFFF
-#define MIN_TXDELAY                    0
-
-/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
- *
- * Valid Range: 0-65535
- */
-E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
-#define DEFAULT_TADV                  32
-#define MAX_TXABSDELAY            0xFFFF
-#define MIN_TXABSDELAY                 0
-
-/* Receive Interrupt Delay in units of 1.024 microseconds
- *   hardware will likely hang if you set this to anything but zero.
- *
- * Valid Range: 0-65535
- */
-E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
-#define DEFAULT_RDTR                   0
-#define MAX_RXDELAY               0xFFFF
-#define MIN_RXDELAY                    0
-
-/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
- *
- * Valid Range: 0-65535
- */
-E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
-#define DEFAULT_RADV                   8
-#define MAX_RXABSDELAY            0xFFFF
-#define MIN_RXABSDELAY                 0
-
-/* Interrupt Throttle Rate (interrupts/sec)
- *
- * Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
- */
-E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
-#define DEFAULT_ITR                    3
-#define MAX_ITR                   100000
-#define MIN_ITR                      100
-
-/* Enable Smart Power Down of the PHY
- *
- * Valid Range: 0, 1
- *
- * Default Value: 0 (disabled)
- */
-E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
-
-struct e1000_option {
-	enum { enable_option, range_option, list_option } type;
-	const char *name;
-	const char *err;
-	int def;
-	union {
-		struct { /* range_option info */
-			int min;
-			int max;
-		} r;
-		struct { /* list_option info */
-			int nr;
-			const struct e1000_opt_list { int i; char *str; } *p;
-		} l;
-	} arg;
-};
-
-static int __devinit e1000_validate_option(unsigned int *value,
-					   const struct e1000_option *opt,
-					   struct e1000_adapter *adapter)
-{
-	if (*value == OPTION_UNSET) {
-		*value = opt->def;
-		return 0;
-	}
-
-	switch (opt->type) {
-	case enable_option:
-		switch (*value) {
-		case OPTION_ENABLED:
-			e_dev_info("%s Enabled\n", opt->name);
-			return 0;
-		case OPTION_DISABLED:
-			e_dev_info("%s Disabled\n", opt->name);
-			return 0;
-		}
-		break;
-	case range_option:
-		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
-			e_dev_info("%s set to %i\n", opt->name, *value);
-			return 0;
-		}
-		break;
-	case list_option: {
-		int i;
-		const struct e1000_opt_list *ent;
-
-		for (i = 0; i < opt->arg.l.nr; i++) {
-			ent = &opt->arg.l.p[i];
-			if (*value == ent->i) {
-				if (ent->str[0] != '\0')
-					e_dev_info("%s\n", ent->str);
-				return 0;
-			}
-		}
-	}
-		break;
-	default:
-		BUG();
-	}
-
-	e_dev_info("Invalid %s value specified (%i) %s\n",
-	       opt->name, *value, opt->err);
-	*value = opt->def;
-	return -1;
-}
-
-static void e1000_check_fiber_options(struct e1000_adapter *adapter);
-static void e1000_check_copper_options(struct e1000_adapter *adapter);
-
-/**
- * e1000_check_options - Range Checking for Command Line Parameters
- * @adapter: board private structure
- *
- * This routine checks all command line parameters for valid user
- * input.  If an invalid value is given, or if no user specified
- * value exists, a default value is used.  The final value is stored
- * in a variable in the adapter structure.
- **/
-
-void __devinit e1000_check_options(struct e1000_adapter *adapter)
-{
-	struct e1000_option opt;
-	int bd = adapter->bd_number;
-
-	if (bd >= E1000_MAX_NIC) {
-		e_dev_warn("Warning: no configuration for board #%i "
-			   "using defaults for all values\n", bd);
-	}
-
-	{ /* Transmit Descriptor Count */
-		struct e1000_tx_ring *tx_ring = adapter->tx_ring;
-		int i;
-		e1000_mac_type mac_type = adapter->hw.mac_type;
-
-		opt = (struct e1000_option) {
-			.type = range_option,
-			.name = "Transmit Descriptors",
-			.err  = "using default of "
-				__MODULE_STRING(E1000_DEFAULT_TXD),
-			.def  = E1000_DEFAULT_TXD,
-			.arg  = { .r = {
-				.min = E1000_MIN_TXD,
-				.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
-				}}
-		};
-
-		if (num_TxDescriptors > bd) {
-			tx_ring->count = TxDescriptors[bd];
-			e1000_validate_option(&tx_ring->count, &opt, adapter);
-			tx_ring->count = ALIGN(tx_ring->count,
-						REQ_TX_DESCRIPTOR_MULTIPLE);
-		} else {
-			tx_ring->count = opt.def;
-		}
-		for (i = 0; i < adapter->num_tx_queues; i++)
-			tx_ring[i].count = tx_ring->count;
-	}
-	{ /* Receive Descriptor Count */
-		struct e1000_rx_ring *rx_ring = adapter->rx_ring;
-		int i;
-		e1000_mac_type mac_type = adapter->hw.mac_type;
-
-		opt = (struct e1000_option) {
-			.type = range_option,
-			.name = "Receive Descriptors",
-			.err  = "using default of "
-				__MODULE_STRING(E1000_DEFAULT_RXD),
-			.def  = E1000_DEFAULT_RXD,
-			.arg  = { .r = {
-				.min = E1000_MIN_RXD,
-				.max = mac_type < e1000_82544 ? E1000_MAX_RXD : E1000_MAX_82544_RXD
-			}}
-		};
-
-		if (num_RxDescriptors > bd) {
-			rx_ring->count = RxDescriptors[bd];
-			e1000_validate_option(&rx_ring->count, &opt, adapter);
-			rx_ring->count = ALIGN(rx_ring->count,
-						REQ_RX_DESCRIPTOR_MULTIPLE);
-		} else {
-			rx_ring->count = opt.def;
-		}
-		for (i = 0; i < adapter->num_rx_queues; i++)
-			rx_ring[i].count = rx_ring->count;
-	}
-	{ /* Checksum Offload Enable/Disable */
-		opt = (struct e1000_option) {
-			.type = enable_option,
-			.name = "Checksum Offload",
-			.err  = "defaulting to Enabled",
-			.def  = OPTION_ENABLED
-		};
-
-		if (num_XsumRX > bd) {
-			unsigned int rx_csum = XsumRX[bd];
-			e1000_validate_option(&rx_csum, &opt, adapter);
-			adapter->rx_csum = rx_csum;
-		} else {
-			adapter->rx_csum = opt.def;
-		}
-	}
-	{ /* Flow Control */
-
-		static const struct e1000_opt_list fc_list[] = {
-		       { E1000_FC_NONE, "Flow Control Disabled" },
-		       { E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
-		       { E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
-		       { E1000_FC_FULL, "Flow Control Enabled" },
-		       { E1000_FC_DEFAULT, "Flow Control Hardware Default" }
-		};
-
-		opt = (struct e1000_option) {
-			.type = list_option,
-			.name = "Flow Control",
-			.err  = "reading default settings from EEPROM",
-			.def  = E1000_FC_DEFAULT,
-			.arg  = { .l = { .nr = ARRAY_SIZE(fc_list),
-					 .p = fc_list }}
-		};
-
-		if (num_FlowControl > bd) {
-			unsigned int fc = FlowControl[bd];
-			e1000_validate_option(&fc, &opt, adapter);
-			adapter->hw.fc = adapter->hw.original_fc = fc;
-		} else {
-			adapter->hw.fc = adapter->hw.original_fc = opt.def;
-		}
-	}
-	{ /* Transmit Interrupt Delay */
-		opt = (struct e1000_option) {
-			.type = range_option,
-			.name = "Transmit Interrupt Delay",
-			.err  = "using default of " __MODULE_STRING(DEFAULT_TIDV),
-			.def  = DEFAULT_TIDV,
-			.arg  = { .r = { .min = MIN_TXDELAY,
-					 .max = MAX_TXDELAY }}
-		};
-
-		if (num_TxIntDelay > bd) {
-			adapter->tx_int_delay = TxIntDelay[bd];
-			e1000_validate_option(&adapter->tx_int_delay, &opt,
-			                      adapter);
-		} else {
-			adapter->tx_int_delay = opt.def;
-		}
-	}
-	{ /* Transmit Absolute Interrupt Delay */
-		opt = (struct e1000_option) {
-			.type = range_option,
-			.name = "Transmit Absolute Interrupt Delay",
-			.err  = "using default of " __MODULE_STRING(DEFAULT_TADV),
-			.def  = DEFAULT_TADV,
-			.arg  = { .r = { .min = MIN_TXABSDELAY,
-					 .max = MAX_TXABSDELAY }}
-		};
-
-		if (num_TxAbsIntDelay > bd) {
-			adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
-			e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
-			                      adapter);
-		} else {
-			adapter->tx_abs_int_delay = opt.def;
-		}
-	}
-	{ /* Receive Interrupt Delay */
-		opt = (struct e1000_option) {
-			.type = range_option,
-			.name = "Receive Interrupt Delay",
-			.err  = "using default of " __MODULE_STRING(DEFAULT_RDTR),
-			.def  = DEFAULT_RDTR,
-			.arg  = { .r = { .min = MIN_RXDELAY,
-					 .max = MAX_RXDELAY }}
-		};
-
-		if (num_RxIntDelay > bd) {
-			adapter->rx_int_delay = RxIntDelay[bd];
-			e1000_validate_option(&adapter->rx_int_delay, &opt,
-			                      adapter);
-		} else {
-			adapter->rx_int_delay = opt.def;
-		}
-	}
-	{ /* Receive Absolute Interrupt Delay */
-		opt = (struct e1000_option) {
-			.type = range_option,
-			.name = "Receive Absolute Interrupt Delay",
-			.err  = "using default of " __MODULE_STRING(DEFAULT_RADV),
-			.def  = DEFAULT_RADV,
-			.arg  = { .r = { .min = MIN_RXABSDELAY,
-					 .max = MAX_RXABSDELAY }}
-		};
-
-		if (num_RxAbsIntDelay > bd) {
-			adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
-			e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
-			                      adapter);
-		} else {
-			adapter->rx_abs_int_delay = opt.def;
-		}
-	}
-	{ /* Interrupt Throttling Rate */
-		opt = (struct e1000_option) {
-			.type = range_option,
-			.name = "Interrupt Throttling Rate (ints/sec)",
-			.err  = "using default of " __MODULE_STRING(DEFAULT_ITR),
-			.def  = DEFAULT_ITR,
-			.arg  = { .r = { .min = MIN_ITR,
-					 .max = MAX_ITR }}
-		};
-
-		if (num_InterruptThrottleRate > bd) {
-			adapter->itr = InterruptThrottleRate[bd];
-			switch (adapter->itr) {
-			case 0:
-				e_dev_info("%s turned off\n", opt.name);
-				break;
-			case 1:
-				e_dev_info("%s set to dynamic mode\n",
-					   opt.name);
-				adapter->itr_setting = adapter->itr;
-				adapter->itr = 20000;
-				break;
-			case 3:
-				e_dev_info("%s set to dynamic conservative "
-					   "mode\n", opt.name);
-				adapter->itr_setting = adapter->itr;
-				adapter->itr = 20000;
-				break;
-			case 4:
-				e_dev_info("%s set to simplified "
-				           "(2000-8000) ints mode\n", opt.name);
-				adapter->itr_setting = adapter->itr;
-				break;
-			default:
-				e1000_validate_option(&adapter->itr, &opt,
-				        adapter);
-				/* save the setting, because the dynamic bits
-				 * change itr.
-				 * clear the lower two bits because they are
-				 * used as control */
-				adapter->itr_setting = adapter->itr & ~3;
-				break;
-			}
-		} else {
-			adapter->itr_setting = opt.def;
-			adapter->itr = 20000;
-		}
-	}
-	{ /* Smart Power Down */
-		opt = (struct e1000_option) {
-			.type = enable_option,
-			.name = "PHY Smart Power Down",
-			.err  = "defaulting to Disabled",
-			.def  = OPTION_DISABLED
-		};
-
-		if (num_SmartPowerDownEnable > bd) {
-			unsigned int spd = SmartPowerDownEnable[bd];
-			e1000_validate_option(&spd, &opt, adapter);
-			adapter->smart_power_down = spd;
-		} else {
-			adapter->smart_power_down = opt.def;
-		}
-	}
-
-	switch (adapter->hw.media_type) {
-	case e1000_media_type_fiber:
-	case e1000_media_type_internal_serdes:
-		e1000_check_fiber_options(adapter);
-		break;
-	case e1000_media_type_copper:
-		e1000_check_copper_options(adapter);
-		break;
-	default:
-		BUG();
-	}
-}
-
-/**
- * e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
- * @adapter: board private structure
- *
- * Handles speed and duplex options on fiber adapters
- **/
-
-static void __devinit e1000_check_fiber_options(struct e1000_adapter *adapter)
-{
-	int bd = adapter->bd_number;
-	if (num_Speed > bd) {
-		e_dev_info("Speed not valid for fiber adapters, parameter "
-			   "ignored\n");
-	}
-
-	if (num_Duplex > bd) {
-		e_dev_info("Duplex not valid for fiber adapters, parameter "
-			   "ignored\n");
-	}
-
-	if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
-		e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
-			   "adapters, parameter ignored\n");
-	}
-}
-
-/**
- * e1000_check_copper_options - Range Checking for Link Options, Copper Version
- * @adapter: board private structure
- *
- * Handles speed and duplex options on copper adapters
- **/
-
-static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter)
-{
-	struct e1000_option opt;
-	unsigned int speed, dplx, an;
-	int bd = adapter->bd_number;
-
-	{ /* Speed */
-		static const struct e1000_opt_list speed_list[] = {
-			{          0, "" },
-			{   SPEED_10, "" },
-			{  SPEED_100, "" },
-			{ SPEED_1000, "" }};
-
-		opt = (struct e1000_option) {
-			.type = list_option,
-			.name = "Speed",
-			.err  = "parameter ignored",
-			.def  = 0,
-			.arg  = { .l = { .nr = ARRAY_SIZE(speed_list),
-					 .p = speed_list }}
-		};
-
-		if (num_Speed > bd) {
-			speed = Speed[bd];
-			e1000_validate_option(&speed, &opt, adapter);
-		} else {
-			speed = opt.def;
-		}
-	}
-	{ /* Duplex */
-		static const struct e1000_opt_list dplx_list[] = {
-			{           0, "" },
-			{ HALF_DUPLEX, "" },
-			{ FULL_DUPLEX, "" }};
-
-		opt = (struct e1000_option) {
-			.type = list_option,
-			.name = "Duplex",
-			.err  = "parameter ignored",
-			.def  = 0,
-			.arg  = { .l = { .nr = ARRAY_SIZE(dplx_list),
-					 .p = dplx_list }}
-		};
-
-		if (num_Duplex > bd) {
-			dplx = Duplex[bd];
-			e1000_validate_option(&dplx, &opt, adapter);
-		} else {
-			dplx = opt.def;
-		}
-	}
-
-	if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
-		e_dev_info("AutoNeg specified along with Speed or Duplex, "
-			   "parameter ignored\n");
-		adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
-	} else { /* Autoneg */
-		static const struct e1000_opt_list an_list[] =
-			#define AA "AutoNeg advertising "
-			{{ 0x01, AA "10/HD" },
-			 { 0x02, AA "10/FD" },
-			 { 0x03, AA "10/FD, 10/HD" },
-			 { 0x04, AA "100/HD" },
-			 { 0x05, AA "100/HD, 10/HD" },
-			 { 0x06, AA "100/HD, 10/FD" },
-			 { 0x07, AA "100/HD, 10/FD, 10/HD" },
-			 { 0x08, AA "100/FD" },
-			 { 0x09, AA "100/FD, 10/HD" },
-			 { 0x0a, AA "100/FD, 10/FD" },
-			 { 0x0b, AA "100/FD, 10/FD, 10/HD" },
-			 { 0x0c, AA "100/FD, 100/HD" },
-			 { 0x0d, AA "100/FD, 100/HD, 10/HD" },
-			 { 0x0e, AA "100/FD, 100/HD, 10/FD" },
-			 { 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
-			 { 0x20, AA "1000/FD" },
-			 { 0x21, AA "1000/FD, 10/HD" },
-			 { 0x22, AA "1000/FD, 10/FD" },
-			 { 0x23, AA "1000/FD, 10/FD, 10/HD" },
-			 { 0x24, AA "1000/FD, 100/HD" },
-			 { 0x25, AA "1000/FD, 100/HD, 10/HD" },
-			 { 0x26, AA "1000/FD, 100/HD, 10/FD" },
-			 { 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
-			 { 0x28, AA "1000/FD, 100/FD" },
-			 { 0x29, AA "1000/FD, 100/FD, 10/HD" },
-			 { 0x2a, AA "1000/FD, 100/FD, 10/FD" },
-			 { 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
-			 { 0x2c, AA "1000/FD, 100/FD, 100/HD" },
-			 { 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
-			 { 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
-			 { 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
-
-		opt = (struct e1000_option) {
-			.type = list_option,
-			.name = "AutoNeg",
-			.err  = "parameter ignored",
-			.def  = AUTONEG_ADV_DEFAULT,
-			.arg  = { .l = { .nr = ARRAY_SIZE(an_list),
-					 .p = an_list }}
-		};
-
-		if (num_AutoNeg > bd) {
-			an = AutoNeg[bd];
-			e1000_validate_option(&an, &opt, adapter);
-		} else {
-			an = opt.def;
-		}
-		adapter->hw.autoneg_advertised = an;
-	}
-
-	switch (speed + dplx) {
-	case 0:
-		adapter->hw.autoneg = adapter->fc_autoneg = 1;
-		if ((num_Speed > bd) && (speed != 0 || dplx != 0))
-			e_dev_info("Speed and duplex autonegotiation "
-				   "enabled\n");
-		break;
-	case HALF_DUPLEX:
-		e_dev_info("Half Duplex specified without Speed\n");
-		e_dev_info("Using Autonegotiation at Half Duplex only\n");
-		adapter->hw.autoneg = adapter->fc_autoneg = 1;
-		adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
-		                                 ADVERTISE_100_HALF;
-		break;
-	case FULL_DUPLEX:
-		e_dev_info("Full Duplex specified without Speed\n");
-		e_dev_info("Using Autonegotiation at Full Duplex only\n");
-		adapter->hw.autoneg = adapter->fc_autoneg = 1;
-		adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
-		                                 ADVERTISE_100_FULL |
-		                                 ADVERTISE_1000_FULL;
-		break;
-	case SPEED_10:
-		e_dev_info("10 Mbps Speed specified without Duplex\n");
-		e_dev_info("Using Autonegotiation at 10 Mbps only\n");
-		adapter->hw.autoneg = adapter->fc_autoneg = 1;
-		adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
-		                                 ADVERTISE_10_FULL;
-		break;
-	case SPEED_10 + HALF_DUPLEX:
-		e_dev_info("Forcing to 10 Mbps Half Duplex\n");
-		adapter->hw.autoneg = adapter->fc_autoneg = 0;
-		adapter->hw.forced_speed_duplex = e1000_10_half;
-		adapter->hw.autoneg_advertised = 0;
-		break;
-	case SPEED_10 + FULL_DUPLEX:
-		e_dev_info("Forcing to 10 Mbps Full Duplex\n");
-		adapter->hw.autoneg = adapter->fc_autoneg = 0;
-		adapter->hw.forced_speed_duplex = e1000_10_full;
-		adapter->hw.autoneg_advertised = 0;
-		break;
-	case SPEED_100:
-		e_dev_info("100 Mbps Speed specified without Duplex\n");
-		e_dev_info("Using Autonegotiation at 100 Mbps only\n");
-		adapter->hw.autoneg = adapter->fc_autoneg = 1;
-		adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
-		                                 ADVERTISE_100_FULL;
-		break;
-	case SPEED_100 + HALF_DUPLEX:
-		e_dev_info("Forcing to 100 Mbps Half Duplex\n");
-		adapter->hw.autoneg = adapter->fc_autoneg = 0;
-		adapter->hw.forced_speed_duplex = e1000_100_half;
-		adapter->hw.autoneg_advertised = 0;
-		break;
-	case SPEED_100 + FULL_DUPLEX:
-		e_dev_info("Forcing to 100 Mbps Full Duplex\n");
-		adapter->hw.autoneg = adapter->fc_autoneg = 0;
-		adapter->hw.forced_speed_duplex = e1000_100_full;
-		adapter->hw.autoneg_advertised = 0;
-		break;
-	case SPEED_1000:
-		e_dev_info("1000 Mbps Speed specified without Duplex\n");
-		goto full_duplex_only;
-	case SPEED_1000 + HALF_DUPLEX:
-		e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
-		/* fall through */
-	case SPEED_1000 + FULL_DUPLEX:
-full_duplex_only:
-		e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
-			   "only\n");
-		adapter->hw.autoneg = adapter->fc_autoneg = 1;
-		adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
-		break;
-	default:
-		BUG();
-	}
-
-	/* Speed, AutoNeg and MDI/MDI-X must all play nice */
-	if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
-		e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
-			   "Setting MDI-X to a compatible value.\n");
-	}
-}
-
diff -druN linux-libre-3.1-gnu/drivers/net/e1000/Makefile linux-libre-3.2-gnu/drivers/net/e1000/Makefile
--- linux-libre-3.1-gnu/drivers/net/e1000/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-################################################################################
-#
-# Intel PRO/1000 Linux driver
-# Copyright(c) 1999 - 2006 Intel Corporation.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-# more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Linux NICS <linux.nics@intel.com>
-# e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-#
-################################################################################
-
-#
-# Makefile for the Intel(R) PRO/1000 ethernet driver
-#
-
-obj-$(CONFIG_E1000) += e1000.o
-
-e1000-objs := e1000_main.o e1000_hw.o e1000_ethtool.o e1000_param.o
diff -druN linux-libre-3.1-gnu/drivers/net/e1000e/82571.c linux-libre-3.2-gnu/drivers/net/e1000e/82571.c
--- linux-libre-3.1-gnu/drivers/net/e1000e/82571.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000e/82571.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2117 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  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,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-/*
- * 82571EB Gigabit Ethernet Controller
- * 82571EB Gigabit Ethernet Controller (Copper)
- * 82571EB Gigabit Ethernet Controller (Fiber)
- * 82571EB Dual Port Gigabit Mezzanine Adapter
- * 82571EB Quad Port Gigabit Mezzanine Adapter
- * 82571PT Gigabit PT Quad Port Server ExpressModule
- * 82572EI Gigabit Ethernet Controller (Copper)
- * 82572EI Gigabit Ethernet Controller (Fiber)
- * 82572EI Gigabit Ethernet Controller
- * 82573V Gigabit Ethernet Controller (Copper)
- * 82573E Gigabit Ethernet Controller (Copper)
- * 82573L Gigabit Ethernet Controller
- * 82574L Gigabit Network Connection
- * 82583V Gigabit Network Connection
- */
-
-#include "e1000.h"
-
-#define ID_LED_RESERVED_F746 0xF746
-#define ID_LED_DEFAULT_82573 ((ID_LED_DEF1_DEF2 << 12) | \
-			      (ID_LED_OFF1_ON2  <<  8) | \
-			      (ID_LED_DEF1_DEF2 <<  4) | \
-			      (ID_LED_DEF1_DEF2))
-
-#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
-#define AN_RETRY_COUNT          5 /* Autoneg Retry Count value */
-#define E1000_BASE1000T_STATUS          10
-#define E1000_IDLE_ERROR_COUNT_MASK     0xFF
-#define E1000_RECEIVE_ERROR_COUNTER     21
-#define E1000_RECEIVE_ERROR_MAX         0xFFFF
-
-#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask */
-
-static s32 e1000_get_phy_id_82571(struct e1000_hw *hw);
-static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw);
-static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw);
-static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw);
-static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
-				      u16 words, u16 *data);
-static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw);
-static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw);
-static s32 e1000_setup_link_82571(struct e1000_hw *hw);
-static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw);
-static void e1000_clear_vfta_82571(struct e1000_hw *hw);
-static bool e1000_check_mng_mode_82574(struct e1000_hw *hw);
-static s32 e1000_led_on_82574(struct e1000_hw *hw);
-static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw);
-static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw);
-static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw);
-static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw);
-static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw);
-static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active);
-static s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active);
-
-/**
- *  e1000_init_phy_params_82571 - Init PHY func ptrs.
- *  @hw: pointer to the HW structure
- **/
-static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-
-	if (hw->phy.media_type != e1000_media_type_copper) {
-		phy->type = e1000_phy_none;
-		return 0;
-	}
-
-	phy->addr			 = 1;
-	phy->autoneg_mask		 = AUTONEG_ADVERTISE_SPEED_DEFAULT;
-	phy->reset_delay_us		 = 100;
-
-	phy->ops.power_up		 = e1000_power_up_phy_copper;
-	phy->ops.power_down		 = e1000_power_down_phy_copper_82571;
-
-	switch (hw->mac.type) {
-	case e1000_82571:
-	case e1000_82572:
-		phy->type		 = e1000_phy_igp_2;
-		break;
-	case e1000_82573:
-		phy->type		 = e1000_phy_m88;
-		break;
-	case e1000_82574:
-	case e1000_82583:
-		phy->type		 = e1000_phy_bm;
-		phy->ops.acquire = e1000_get_hw_semaphore_82574;
-		phy->ops.release = e1000_put_hw_semaphore_82574;
-		phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82574;
-		phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82574;
-		break;
-	default:
-		return -E1000_ERR_PHY;
-		break;
-	}
-
-	/* This can only be done after all function pointers are setup. */
-	ret_val = e1000_get_phy_id_82571(hw);
-	if (ret_val) {
-		e_dbg("Error getting PHY ID\n");
-		return ret_val;
-	}
-
-	/* Verify phy id */
-	switch (hw->mac.type) {
-	case e1000_82571:
-	case e1000_82572:
-		if (phy->id != IGP01E1000_I_PHY_ID)
-			ret_val = -E1000_ERR_PHY;
-		break;
-	case e1000_82573:
-		if (phy->id != M88E1111_I_PHY_ID)
-			ret_val = -E1000_ERR_PHY;
-		break;
-	case e1000_82574:
-	case e1000_82583:
-		if (phy->id != BME1000_E_PHY_ID_R2)
-			ret_val = -E1000_ERR_PHY;
-		break;
-	default:
-		ret_val = -E1000_ERR_PHY;
-		break;
-	}
-
-	if (ret_val)
-		e_dbg("PHY ID unknown: type = 0x%08x\n", phy->id);
-
-	return ret_val;
-}
-
-/**
- *  e1000_init_nvm_params_82571 - Init NVM func ptrs.
- *  @hw: pointer to the HW structure
- **/
-static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
-{
-	struct e1000_nvm_info *nvm = &hw->nvm;
-	u32 eecd = er32(EECD);
-	u16 size;
-
-	nvm->opcode_bits = 8;
-	nvm->delay_usec = 1;
-	switch (nvm->override) {
-	case e1000_nvm_override_spi_large:
-		nvm->page_size = 32;
-		nvm->address_bits = 16;
-		break;
-	case e1000_nvm_override_spi_small:
-		nvm->page_size = 8;
-		nvm->address_bits = 8;
-		break;
-	default:
-		nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
-		nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8;
-		break;
-	}
-
-	switch (hw->mac.type) {
-	case e1000_82573:
-	case e1000_82574:
-	case e1000_82583:
-		if (((eecd >> 15) & 0x3) == 0x3) {
-			nvm->type = e1000_nvm_flash_hw;
-			nvm->word_size = 2048;
-			/*
-			 * Autonomous Flash update bit must be cleared due
-			 * to Flash update issue.
-			 */
-			eecd &= ~E1000_EECD_AUPDEN;
-			ew32(EECD, eecd);
-			break;
-		}
-		/* Fall Through */
-	default:
-		nvm->type = e1000_nvm_eeprom_spi;
-		size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
-				  E1000_EECD_SIZE_EX_SHIFT);
-		/*
-		 * Added to a constant, "size" becomes the left-shift value
-		 * for setting word_size.
-		 */
-		size += NVM_WORD_SIZE_BASE_SHIFT;
-
-		/* EEPROM access above 16k is unsupported */
-		if (size > 14)
-			size = 14;
-		nvm->word_size	= 1 << size;
-		break;
-	}
-
-	/* Function Pointers */
-	switch (hw->mac.type) {
-	case e1000_82574:
-	case e1000_82583:
-		nvm->ops.acquire = e1000_get_hw_semaphore_82574;
-		nvm->ops.release = e1000_put_hw_semaphore_82574;
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_init_mac_params_82571 - Init MAC func ptrs.
- *  @hw: pointer to the HW structure
- **/
-static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_mac_info *mac = &hw->mac;
-	struct e1000_mac_operations *func = &mac->ops;
-	u32 swsm = 0;
-	u32 swsm2 = 0;
-	bool force_clear_smbi = false;
-
-	/* Set media type */
-	switch (adapter->pdev->device) {
-	case E1000_DEV_ID_82571EB_FIBER:
-	case E1000_DEV_ID_82572EI_FIBER:
-	case E1000_DEV_ID_82571EB_QUAD_FIBER:
-		hw->phy.media_type = e1000_media_type_fiber;
-		break;
-	case E1000_DEV_ID_82571EB_SERDES:
-	case E1000_DEV_ID_82572EI_SERDES:
-	case E1000_DEV_ID_82571EB_SERDES_DUAL:
-	case E1000_DEV_ID_82571EB_SERDES_QUAD:
-		hw->phy.media_type = e1000_media_type_internal_serdes;
-		break;
-	default:
-		hw->phy.media_type = e1000_media_type_copper;
-		break;
-	}
-
-	/* Set mta register count */
-	mac->mta_reg_count = 128;
-	/* Set rar entry count */
-	mac->rar_entry_count = E1000_RAR_ENTRIES;
-	/* Adaptive IFS supported */
-	mac->adaptive_ifs = true;
-
-	/* check for link */
-	switch (hw->phy.media_type) {
-	case e1000_media_type_copper:
-		func->setup_physical_interface = e1000_setup_copper_link_82571;
-		func->check_for_link = e1000e_check_for_copper_link;
-		func->get_link_up_info = e1000e_get_speed_and_duplex_copper;
-		break;
-	case e1000_media_type_fiber:
-		func->setup_physical_interface =
-			e1000_setup_fiber_serdes_link_82571;
-		func->check_for_link = e1000e_check_for_fiber_link;
-		func->get_link_up_info =
-			e1000e_get_speed_and_duplex_fiber_serdes;
-		break;
-	case e1000_media_type_internal_serdes:
-		func->setup_physical_interface =
-			e1000_setup_fiber_serdes_link_82571;
-		func->check_for_link = e1000_check_for_serdes_link_82571;
-		func->get_link_up_info =
-			e1000e_get_speed_and_duplex_fiber_serdes;
-		break;
-	default:
-		return -E1000_ERR_CONFIG;
-		break;
-	}
-
-	switch (hw->mac.type) {
-	case e1000_82573:
-		func->set_lan_id = e1000_set_lan_id_single_port;
-		func->check_mng_mode = e1000e_check_mng_mode_generic;
-		func->led_on = e1000e_led_on_generic;
-		func->blink_led = e1000e_blink_led_generic;
-
-		/* FWSM register */
-		mac->has_fwsm = true;
-		/*
-		 * ARC supported; valid only if manageability features are
-		 * enabled.
-		 */
-		mac->arc_subsystem_valid =
-			(er32(FWSM) & E1000_FWSM_MODE_MASK)
-			? true : false;
-		break;
-	case e1000_82574:
-	case e1000_82583:
-		func->set_lan_id = e1000_set_lan_id_single_port;
-		func->check_mng_mode = e1000_check_mng_mode_82574;
-		func->led_on = e1000_led_on_82574;
-		break;
-	default:
-		func->check_mng_mode = e1000e_check_mng_mode_generic;
-		func->led_on = e1000e_led_on_generic;
-		func->blink_led = e1000e_blink_led_generic;
-
-		/* FWSM register */
-		mac->has_fwsm = true;
-		break;
-	}
-
-	/*
-	 * Ensure that the inter-port SWSM.SMBI lock bit is clear before
-	 * first NVM or PHY access. This should be done for single-port
-	 * devices, and for one port only on dual-port devices so that
-	 * for those devices we can still use the SMBI lock to synchronize
-	 * inter-port accesses to the PHY & NVM.
-	 */
-	switch (hw->mac.type) {
-	case e1000_82571:
-	case e1000_82572:
-		swsm2 = er32(SWSM2);
-
-		if (!(swsm2 & E1000_SWSM2_LOCK)) {
-			/* Only do this for the first interface on this card */
-			ew32(SWSM2,
-			    swsm2 | E1000_SWSM2_LOCK);
-			force_clear_smbi = true;
-		} else
-			force_clear_smbi = false;
-		break;
-	default:
-		force_clear_smbi = true;
-		break;
-	}
-
-	if (force_clear_smbi) {
-		/* Make sure SWSM.SMBI is clear */
-		swsm = er32(SWSM);
-		if (swsm & E1000_SWSM_SMBI) {
-			/* This bit should not be set on a first interface, and
-			 * indicates that the bootagent or EFI code has
-			 * improperly left this bit enabled
-			 */
-			e_dbg("Please update your 82571 Bootagent\n");
-		}
-		ew32(SWSM, swsm & ~E1000_SWSM_SMBI);
-	}
-
-	/*
-	 * Initialize device specific counter of SMBI acquisition
-	 * timeouts.
-	 */
-	 hw->dev_spec.e82571.smb_counter = 0;
-
-	return 0;
-}
-
-static s32 e1000_get_variants_82571(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	static int global_quad_port_a; /* global port a indication */
-	struct pci_dev *pdev = adapter->pdev;
-	int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1;
-	s32 rc;
-
-	rc = e1000_init_mac_params_82571(adapter);
-	if (rc)
-		return rc;
-
-	rc = e1000_init_nvm_params_82571(hw);
-	if (rc)
-		return rc;
-
-	rc = e1000_init_phy_params_82571(hw);
-	if (rc)
-		return rc;
-
-	/* tag quad port adapters first, it's used below */
-	switch (pdev->device) {
-	case E1000_DEV_ID_82571EB_QUAD_COPPER:
-	case E1000_DEV_ID_82571EB_QUAD_FIBER:
-	case E1000_DEV_ID_82571EB_QUAD_COPPER_LP:
-	case E1000_DEV_ID_82571PT_QUAD_COPPER:
-		adapter->flags |= FLAG_IS_QUAD_PORT;
-		/* mark the first port */
-		if (global_quad_port_a == 0)
-			adapter->flags |= FLAG_IS_QUAD_PORT_A;
-		/* Reset for multiple quad port adapters */
-		global_quad_port_a++;
-		if (global_quad_port_a == 4)
-			global_quad_port_a = 0;
-		break;
-	default:
-		break;
-	}
-
-	switch (adapter->hw.mac.type) {
-	case e1000_82571:
-		/* these dual ports don't have WoL on port B at all */
-		if (((pdev->device == E1000_DEV_ID_82571EB_FIBER) ||
-		     (pdev->device == E1000_DEV_ID_82571EB_SERDES) ||
-		     (pdev->device == E1000_DEV_ID_82571EB_COPPER)) &&
-		    (is_port_b))
-			adapter->flags &= ~FLAG_HAS_WOL;
-		/* quad ports only support WoL on port A */
-		if (adapter->flags & FLAG_IS_QUAD_PORT &&
-		    (!(adapter->flags & FLAG_IS_QUAD_PORT_A)))
-			adapter->flags &= ~FLAG_HAS_WOL;
-		/* Does not support WoL on any port */
-		if (pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD)
-			adapter->flags &= ~FLAG_HAS_WOL;
-		break;
-	case e1000_82573:
-		if (pdev->device == E1000_DEV_ID_82573L) {
-			adapter->flags |= FLAG_HAS_JUMBO_FRAMES;
-			adapter->max_hw_frame_size = DEFAULT_JUMBO;
-		}
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_get_phy_id_82571 - Retrieve the PHY ID and revision
- *  @hw: pointer to the HW structure
- *
- *  Reads the PHY registers and stores the PHY ID and possibly the PHY
- *  revision in the hardware structure.
- **/
-static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 phy_id = 0;
-
-	switch (hw->mac.type) {
-	case e1000_82571:
-	case e1000_82572:
-		/*
-		 * The 82571 firmware may still be configuring the PHY.
-		 * In this case, we cannot access the PHY until the
-		 * configuration is done.  So we explicitly set the
-		 * PHY ID.
-		 */
-		phy->id = IGP01E1000_I_PHY_ID;
-		break;
-	case e1000_82573:
-		return e1000e_get_phy_id(hw);
-		break;
-	case e1000_82574:
-	case e1000_82583:
-		ret_val = e1e_rphy(hw, PHY_ID1, &phy_id);
-		if (ret_val)
-			return ret_val;
-
-		phy->id = (u32)(phy_id << 16);
-		udelay(20);
-		ret_val = e1e_rphy(hw, PHY_ID2, &phy_id);
-		if (ret_val)
-			return ret_val;
-
-		phy->id |= (u32)(phy_id);
-		phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
-		break;
-	default:
-		return -E1000_ERR_PHY;
-		break;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_get_hw_semaphore_82571 - Acquire hardware semaphore
- *  @hw: pointer to the HW structure
- *
- *  Acquire the HW semaphore to access the PHY or NVM
- **/
-static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
-{
-	u32 swsm;
-	s32 sw_timeout = hw->nvm.word_size + 1;
-	s32 fw_timeout = hw->nvm.word_size + 1;
-	s32 i = 0;
-
-	/*
-	 * If we have timedout 3 times on trying to acquire
-	 * the inter-port SMBI semaphore, there is old code
-	 * operating on the other port, and it is not
-	 * releasing SMBI. Modify the number of times that
-	 * we try for the semaphore to interwork with this
-	 * older code.
-	 */
-	if (hw->dev_spec.e82571.smb_counter > 2)
-		sw_timeout = 1;
-
-	/* Get the SW semaphore */
-	while (i < sw_timeout) {
-		swsm = er32(SWSM);
-		if (!(swsm & E1000_SWSM_SMBI))
-			break;
-
-		udelay(50);
-		i++;
-	}
-
-	if (i == sw_timeout) {
-		e_dbg("Driver can't access device - SMBI bit is set.\n");
-		hw->dev_spec.e82571.smb_counter++;
-	}
-	/* Get the FW semaphore. */
-	for (i = 0; i < fw_timeout; i++) {
-		swsm = er32(SWSM);
-		ew32(SWSM, swsm | E1000_SWSM_SWESMBI);
-
-		/* Semaphore acquired if bit latched */
-		if (er32(SWSM) & E1000_SWSM_SWESMBI)
-			break;
-
-		udelay(50);
-	}
-
-	if (i == fw_timeout) {
-		/* Release semaphores */
-		e1000_put_hw_semaphore_82571(hw);
-		e_dbg("Driver can't access the NVM\n");
-		return -E1000_ERR_NVM;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_put_hw_semaphore_82571 - Release hardware semaphore
- *  @hw: pointer to the HW structure
- *
- *  Release hardware semaphore used to access the PHY or NVM
- **/
-static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw)
-{
-	u32 swsm;
-
-	swsm = er32(SWSM);
-	swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
-	ew32(SWSM, swsm);
-}
-/**
- *  e1000_get_hw_semaphore_82573 - Acquire hardware semaphore
- *  @hw: pointer to the HW structure
- *
- *  Acquire the HW semaphore during reset.
- *
- **/
-static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw)
-{
-	u32 extcnf_ctrl;
-	s32 ret_val = 0;
-	s32 i = 0;
-
-	extcnf_ctrl = er32(EXTCNF_CTRL);
-	extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
-	do {
-		ew32(EXTCNF_CTRL, extcnf_ctrl);
-		extcnf_ctrl = er32(EXTCNF_CTRL);
-
-		if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
-			break;
-
-		extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
-
-		usleep_range(2000, 4000);
-		i++;
-	} while (i < MDIO_OWNERSHIP_TIMEOUT);
-
-	if (i == MDIO_OWNERSHIP_TIMEOUT) {
-		/* Release semaphores */
-		e1000_put_hw_semaphore_82573(hw);
-		e_dbg("Driver can't access the PHY\n");
-		ret_val = -E1000_ERR_PHY;
-		goto out;
-	}
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_put_hw_semaphore_82573 - Release hardware semaphore
- *  @hw: pointer to the HW structure
- *
- *  Release hardware semaphore used during reset.
- *
- **/
-static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw)
-{
-	u32 extcnf_ctrl;
-
-	extcnf_ctrl = er32(EXTCNF_CTRL);
-	extcnf_ctrl &= ~E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
-	ew32(EXTCNF_CTRL, extcnf_ctrl);
-}
-
-static DEFINE_MUTEX(swflag_mutex);
-
-/**
- *  e1000_get_hw_semaphore_82574 - Acquire hardware semaphore
- *  @hw: pointer to the HW structure
- *
- *  Acquire the HW semaphore to access the PHY or NVM.
- *
- **/
-static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw)
-{
-	s32 ret_val;
-
-	mutex_lock(&swflag_mutex);
-	ret_val = e1000_get_hw_semaphore_82573(hw);
-	if (ret_val)
-		mutex_unlock(&swflag_mutex);
-	return ret_val;
-}
-
-/**
- *  e1000_put_hw_semaphore_82574 - Release hardware semaphore
- *  @hw: pointer to the HW structure
- *
- *  Release hardware semaphore used to access the PHY or NVM
- *
- **/
-static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw)
-{
-	e1000_put_hw_semaphore_82573(hw);
-	mutex_unlock(&swflag_mutex);
-}
-
-/**
- *  e1000_set_d0_lplu_state_82574 - Set Low Power Linkup D0 state
- *  @hw: pointer to the HW structure
- *  @active: true to enable LPLU, false to disable
- *
- *  Sets the LPLU D0 state according to the active flag.
- *  LPLU will not be activated unless the
- *  device autonegotiation advertisement meets standards of
- *  either 10 or 10/100 or 10/100/1000 at all duplexes.
- *  This is a function pointer entry point only called by
- *  PHY setup routines.
- **/
-static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active)
-{
-	u16 data = er32(POEMB);
-
-	if (active)
-		data |= E1000_PHY_CTRL_D0A_LPLU;
-	else
-		data &= ~E1000_PHY_CTRL_D0A_LPLU;
-
-	ew32(POEMB, data);
-	return 0;
-}
-
-/**
- *  e1000_set_d3_lplu_state_82574 - Sets low power link up state for D3
- *  @hw: pointer to the HW structure
- *  @active: boolean used to enable/disable lplu
- *
- *  The low power link up (lplu) state is set to the power management level D3
- *  when active is true, else clear lplu for D3. LPLU
- *  is used during Dx states where the power conservation is most important.
- *  During driver activity, SmartSpeed should be enabled so performance is
- *  maintained.
- **/
-static s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active)
-{
-	u16 data = er32(POEMB);
-
-	if (!active) {
-		data &= ~E1000_PHY_CTRL_NOND0A_LPLU;
-	} else if ((hw->phy.autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
-		   (hw->phy.autoneg_advertised == E1000_ALL_NOT_GIG) ||
-		   (hw->phy.autoneg_advertised == E1000_ALL_10_SPEED)) {
-		data |= E1000_PHY_CTRL_NOND0A_LPLU;
-	}
-
-	ew32(POEMB, data);
-	return 0;
-}
-
-/**
- *  e1000_acquire_nvm_82571 - Request for access to the EEPROM
- *  @hw: pointer to the HW structure
- *
- *  To gain access to the EEPROM, first we must obtain a hardware semaphore.
- *  Then for non-82573 hardware, set the EEPROM access request bit and wait
- *  for EEPROM access grant bit.  If the access grant bit is not set, release
- *  hardware semaphore.
- **/
-static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw)
-{
-	s32 ret_val;
-
-	ret_val = e1000_get_hw_semaphore_82571(hw);
-	if (ret_val)
-		return ret_val;
-
-	switch (hw->mac.type) {
-	case e1000_82573:
-		break;
-	default:
-		ret_val = e1000e_acquire_nvm(hw);
-		break;
-	}
-
-	if (ret_val)
-		e1000_put_hw_semaphore_82571(hw);
-
-	return ret_val;
-}
-
-/**
- *  e1000_release_nvm_82571 - Release exclusive access to EEPROM
- *  @hw: pointer to the HW structure
- *
- *  Stop any current commands to the EEPROM and clear the EEPROM request bit.
- **/
-static void e1000_release_nvm_82571(struct e1000_hw *hw)
-{
-	e1000e_release_nvm(hw);
-	e1000_put_hw_semaphore_82571(hw);
-}
-
-/**
- *  e1000_write_nvm_82571 - Write to EEPROM using appropriate interface
- *  @hw: pointer to the HW structure
- *  @offset: offset within the EEPROM to be written to
- *  @words: number of words to write
- *  @data: 16 bit word(s) to be written to the EEPROM
- *
- *  For non-82573 silicon, write data to EEPROM at offset using SPI interface.
- *
- *  If e1000e_update_nvm_checksum is not called after this function, the
- *  EEPROM will most likely contain an invalid checksum.
- **/
-static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words,
-				 u16 *data)
-{
-	s32 ret_val;
-
-	switch (hw->mac.type) {
-	case e1000_82573:
-	case e1000_82574:
-	case e1000_82583:
-		ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data);
-		break;
-	case e1000_82571:
-	case e1000_82572:
-		ret_val = e1000e_write_nvm_spi(hw, offset, words, data);
-		break;
-	default:
-		ret_val = -E1000_ERR_NVM;
-		break;
-	}
-
-	return ret_val;
-}
-
-/**
- *  e1000_update_nvm_checksum_82571 - Update EEPROM checksum
- *  @hw: pointer to the HW structure
- *
- *  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.
- **/
-static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
-{
-	u32 eecd;
-	s32 ret_val;
-	u16 i;
-
-	ret_val = e1000e_update_nvm_checksum_generic(hw);
-	if (ret_val)
-		return ret_val;
-
-	/*
-	 * If our nvm is an EEPROM, then we're done
-	 * otherwise, commit the checksum to the flash NVM.
-	 */
-	if (hw->nvm.type != e1000_nvm_flash_hw)
-		return ret_val;
-
-	/* Check for pending operations. */
-	for (i = 0; i < E1000_FLASH_UPDATES; i++) {
-		usleep_range(1000, 2000);
-		if ((er32(EECD) & E1000_EECD_FLUPD) == 0)
-			break;
-	}
-
-	if (i == E1000_FLASH_UPDATES)
-		return -E1000_ERR_NVM;
-
-	/* Reset the firmware if using STM opcode. */
-	if ((er32(FLOP) & 0xFF00) == E1000_STM_OPCODE) {
-		/*
-		 * The enabling of and the actual reset must be done
-		 * in two write cycles.
-		 */
-		ew32(HICR, E1000_HICR_FW_RESET_ENABLE);
-		e1e_flush();
-		ew32(HICR, E1000_HICR_FW_RESET);
-	}
-
-	/* Commit the write to flash */
-	eecd = er32(EECD) | E1000_EECD_FLUPD;
-	ew32(EECD, eecd);
-
-	for (i = 0; i < E1000_FLASH_UPDATES; i++) {
-		usleep_range(1000, 2000);
-		if ((er32(EECD) & E1000_EECD_FLUPD) == 0)
-			break;
-	}
-
-	if (i == E1000_FLASH_UPDATES)
-		return -E1000_ERR_NVM;
-
-	return 0;
-}
-
-/**
- *  e1000_validate_nvm_checksum_82571 - Validate EEPROM checksum
- *  @hw: pointer to the HW structure
- *
- *  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.
- **/
-static s32 e1000_validate_nvm_checksum_82571(struct e1000_hw *hw)
-{
-	if (hw->nvm.type == e1000_nvm_flash_hw)
-		e1000_fix_nvm_checksum_82571(hw);
-
-	return e1000e_validate_nvm_checksum_generic(hw);
-}
-
-/**
- *  e1000_write_nvm_eewr_82571 - Write to EEPROM for 82573 silicon
- *  @hw: pointer to the HW structure
- *  @offset: offset within the EEPROM to be written to
- *  @words: number of words to write
- *  @data: 16 bit word(s) to be written to the EEPROM
- *
- *  After checking for invalid values, poll the EEPROM to ensure the previous
- *  command has completed before trying to write the next word.  After write
- *  poll for completion.
- *
- *  If e1000e_update_nvm_checksum is not called after this function, the
- *  EEPROM will most likely contain an invalid checksum.
- **/
-static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
-				      u16 words, u16 *data)
-{
-	struct e1000_nvm_info *nvm = &hw->nvm;
-	u32 i, eewr = 0;
-	s32 ret_val = 0;
-
-	/*
-	 * 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)) {
-		e_dbg("nvm parameter(s) out of bounds\n");
-		return -E1000_ERR_NVM;
-	}
-
-	for (i = 0; i < words; i++) {
-		eewr = (data[i] << E1000_NVM_RW_REG_DATA) |
-		       ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
-		       E1000_NVM_RW_REG_START;
-
-		ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE);
-		if (ret_val)
-			break;
-
-		ew32(EEWR, eewr);
-
-		ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE);
-		if (ret_val)
-			break;
-	}
-
-	return ret_val;
-}
-
-/**
- *  e1000_get_cfg_done_82571 - Poll for configuration done
- *  @hw: pointer to the HW structure
- *
- *  Reads the management control register for the config done bit to be set.
- **/
-static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw)
-{
-	s32 timeout = PHY_CFG_TIMEOUT;
-
-	while (timeout) {
-		if (er32(EEMNGCTL) &
-		    E1000_NVM_CFG_DONE_PORT_0)
-			break;
-		usleep_range(1000, 2000);
-		timeout--;
-	}
-	if (!timeout) {
-		e_dbg("MNG configuration cycle has not completed.\n");
-		return -E1000_ERR_RESET;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_set_d0_lplu_state_82571 - Set Low Power Linkup D0 state
- *  @hw: pointer to the HW structure
- *  @active: true to enable LPLU, false to disable
- *
- *  Sets the LPLU D0 state according to the active flag.  When activating LPLU
- *  this function also disables smart speed and vice versa.  LPLU will not be
- *  activated unless the device autonegotiation advertisement meets standards
- *  of either 10 or 10/100 or 10/100/1000 at all duplexes.  This is a function
- *  pointer entry point only called by PHY setup routines.
- **/
-static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 data;
-
-	ret_val = e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &data);
-	if (ret_val)
-		return ret_val;
-
-	if (active) {
-		data |= IGP02E1000_PM_D0_LPLU;
-		ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
-		if (ret_val)
-			return ret_val;
-
-		/* When LPLU is enabled, we should disable SmartSpeed */
-		ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data);
-		data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-		ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data);
-		if (ret_val)
-			return ret_val;
-	} else {
-		data &= ~IGP02E1000_PM_D0_LPLU;
-		ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
-		/*
-		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
-		 * during Dx states where the power conservation is most
-		 * important.  During driver activity we should enable
-		 * SmartSpeed, so performance is maintained.
-		 */
-		if (phy->smart_speed == e1000_smart_speed_on) {
-			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   &data);
-			if (ret_val)
-				return ret_val;
-
-			data |= IGP01E1000_PSCFR_SMART_SPEED;
-			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   data);
-			if (ret_val)
-				return ret_val;
-		} else if (phy->smart_speed == e1000_smart_speed_off) {
-			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   &data);
-			if (ret_val)
-				return ret_val;
-
-			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   data);
-			if (ret_val)
-				return ret_val;
-		}
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_reset_hw_82571 - Reset hardware
- *  @hw: pointer to the HW structure
- *
- *  This resets the hardware into a known state.
- **/
-static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
-{
-	u32 ctrl, ctrl_ext;
-	s32 ret_val;
-
-	/*
-	 * Prevent the PCI-E bus from sticking if there is no TLP connection
-	 * on the last TLP read/write transaction when MAC is reset.
-	 */
-	ret_val = e1000e_disable_pcie_master(hw);
-	if (ret_val)
-		e_dbg("PCI-E Master disable polling has failed.\n");
-
-	e_dbg("Masking off all interrupts\n");
-	ew32(IMC, 0xffffffff);
-
-	ew32(RCTL, 0);
-	ew32(TCTL, E1000_TCTL_PSP);
-	e1e_flush();
-
-	usleep_range(10000, 20000);
-
-	/*
-	 * Must acquire the MDIO ownership before MAC reset.
-	 * Ownership defaults to firmware after a reset.
-	 */
-	switch (hw->mac.type) {
-	case e1000_82573:
-		ret_val = e1000_get_hw_semaphore_82573(hw);
-		break;
-	case e1000_82574:
-	case e1000_82583:
-		ret_val = e1000_get_hw_semaphore_82574(hw);
-		break;
-	default:
-		break;
-	}
-	if (ret_val)
-		e_dbg("Cannot acquire MDIO ownership\n");
-
-	ctrl = er32(CTRL);
-
-	e_dbg("Issuing a global reset to MAC\n");
-	ew32(CTRL, ctrl | E1000_CTRL_RST);
-
-	/* Must release MDIO ownership and mutex after MAC reset. */
-	switch (hw->mac.type) {
-	case e1000_82574:
-	case e1000_82583:
-		e1000_put_hw_semaphore_82574(hw);
-		break;
-	default:
-		break;
-	}
-
-	if (hw->nvm.type == e1000_nvm_flash_hw) {
-		udelay(10);
-		ctrl_ext = er32(CTRL_EXT);
-		ctrl_ext |= E1000_CTRL_EXT_EE_RST;
-		ew32(CTRL_EXT, ctrl_ext);
-		e1e_flush();
-	}
-
-	ret_val = e1000e_get_auto_rd_done(hw);
-	if (ret_val)
-		/* We don't want to continue accessing MAC registers. */
-		return ret_val;
-
-	/*
-	 * Phy configuration from NVM just starts after EECD_AUTO_RD is set.
-	 * Need to wait for Phy configuration completion before accessing
-	 * NVM and Phy.
-	 */
-
-	switch (hw->mac.type) {
-	case e1000_82573:
-	case e1000_82574:
-	case e1000_82583:
-		msleep(25);
-		break;
-	default:
-		break;
-	}
-
-	/* Clear any pending interrupt events. */
-	ew32(IMC, 0xffffffff);
-	er32(ICR);
-
-	if (hw->mac.type == e1000_82571) {
-		/* Install any alternate MAC address into RAR0 */
-		ret_val = e1000_check_alt_mac_addr_generic(hw);
-		if (ret_val)
-			return ret_val;
-
-		e1000e_set_laa_state_82571(hw, true);
-	}
-
-	/* Reinitialize the 82571 serdes link state machine */
-	if (hw->phy.media_type == e1000_media_type_internal_serdes)
-		hw->mac.serdes_link_state = e1000_serdes_link_down;
-
-	return 0;
-}
-
-/**
- *  e1000_init_hw_82571 - Initialize hardware
- *  @hw: pointer to the HW structure
- *
- *  This inits the hardware readying it for operation.
- **/
-static s32 e1000_init_hw_82571(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-	u32 reg_data;
-	s32 ret_val;
-	u16 i, rar_count = mac->rar_entry_count;
-
-	e1000_initialize_hw_bits_82571(hw);
-
-	/* Initialize identification LED */
-	ret_val = e1000e_id_led_init(hw);
-	if (ret_val)
-		e_dbg("Error initializing identification LED\n");
-		/* This is not fatal and we should not stop init due to this */
-
-	/* Disabling VLAN filtering */
-	e_dbg("Initializing the IEEE VLAN\n");
-	mac->ops.clear_vfta(hw);
-
-	/* Setup the receive address. */
-	/*
-	 * If, however, a locally administered address was assigned to the
-	 * 82571, we must reserve a RAR for it to work around an issue where
-	 * resetting one port will reload the MAC on the other port.
-	 */
-	if (e1000e_get_laa_state_82571(hw))
-		rar_count--;
-	e1000e_init_rx_addrs(hw, rar_count);
-
-	/* Zero out the Multicast HASH table */
-	e_dbg("Zeroing the MTA\n");
-	for (i = 0; i < mac->mta_reg_count; i++)
-		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
-
-	/* Setup link and flow control */
-	ret_val = e1000_setup_link_82571(hw);
-
-	/* Set the transmit descriptor write-back policy */
-	reg_data = er32(TXDCTL(0));
-	reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
-		   E1000_TXDCTL_FULL_TX_DESC_WB |
-		   E1000_TXDCTL_COUNT_DESC;
-	ew32(TXDCTL(0), reg_data);
-
-	/* ...for both queues. */
-	switch (mac->type) {
-	case e1000_82573:
-		e1000e_enable_tx_pkt_filtering(hw);
-		/* fall through */
-	case e1000_82574:
-	case e1000_82583:
-		reg_data = er32(GCR);
-		reg_data |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
-		ew32(GCR, reg_data);
-		break;
-	default:
-		reg_data = er32(TXDCTL(1));
-		reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
-			   E1000_TXDCTL_FULL_TX_DESC_WB |
-			   E1000_TXDCTL_COUNT_DESC;
-		ew32(TXDCTL(1), reg_data);
-		break;
-	}
-
-	/*
-	 * Clear all of the statistics registers (clear on read).  It is
-	 * important that we do this after we have tried to establish link
-	 * because the symbol error count will increment wildly if there
-	 * is no link.
-	 */
-	e1000_clear_hw_cntrs_82571(hw);
-
-	return ret_val;
-}
-
-/**
- *  e1000_initialize_hw_bits_82571 - Initialize hardware-dependent bits
- *  @hw: pointer to the HW structure
- *
- *  Initializes required hardware-dependent bits needed for normal operation.
- **/
-static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
-{
-	u32 reg;
-
-	/* Transmit Descriptor Control 0 */
-	reg = er32(TXDCTL(0));
-	reg |= (1 << 22);
-	ew32(TXDCTL(0), reg);
-
-	/* Transmit Descriptor Control 1 */
-	reg = er32(TXDCTL(1));
-	reg |= (1 << 22);
-	ew32(TXDCTL(1), reg);
-
-	/* Transmit Arbitration Control 0 */
-	reg = er32(TARC(0));
-	reg &= ~(0xF << 27); /* 30:27 */
-	switch (hw->mac.type) {
-	case e1000_82571:
-	case e1000_82572:
-		reg |= (1 << 23) | (1 << 24) | (1 << 25) | (1 << 26);
-		break;
-	default:
-		break;
-	}
-	ew32(TARC(0), reg);
-
-	/* Transmit Arbitration Control 1 */
-	reg = er32(TARC(1));
-	switch (hw->mac.type) {
-	case e1000_82571:
-	case e1000_82572:
-		reg &= ~((1 << 29) | (1 << 30));
-		reg |= (1 << 22) | (1 << 24) | (1 << 25) | (1 << 26);
-		if (er32(TCTL) & E1000_TCTL_MULR)
-			reg &= ~(1 << 28);
-		else
-			reg |= (1 << 28);
-		ew32(TARC(1), reg);
-		break;
-	default:
-		break;
-	}
-
-	/* Device Control */
-	switch (hw->mac.type) {
-	case e1000_82573:
-	case e1000_82574:
-	case e1000_82583:
-		reg = er32(CTRL);
-		reg &= ~(1 << 29);
-		ew32(CTRL, reg);
-		break;
-	default:
-		break;
-	}
-
-	/* Extended Device Control */
-	switch (hw->mac.type) {
-	case e1000_82573:
-	case e1000_82574:
-	case e1000_82583:
-		reg = er32(CTRL_EXT);
-		reg &= ~(1 << 23);
-		reg |= (1 << 22);
-		ew32(CTRL_EXT, reg);
-		break;
-	default:
-		break;
-	}
-
-	if (hw->mac.type == e1000_82571) {
-		reg = er32(PBA_ECC);
-		reg |= E1000_PBA_ECC_CORR_EN;
-		ew32(PBA_ECC, reg);
-	}
-	/*
-	 * Workaround for hardware errata.
-	 * Ensure that DMA Dynamic Clock gating is disabled on 82571 and 82572
-	 */
-
-        if ((hw->mac.type == e1000_82571) ||
-           (hw->mac.type == e1000_82572)) {
-                reg = er32(CTRL_EXT);
-                reg &= ~E1000_CTRL_EXT_DMA_DYN_CLK_EN;
-                ew32(CTRL_EXT, reg);
-        }
-
-
-	/* PCI-Ex Control Registers */
-	switch (hw->mac.type) {
-	case e1000_82574:
-	case e1000_82583:
-		reg = er32(GCR);
-		reg |= (1 << 22);
-		ew32(GCR, reg);
-
-		/*
-		 * Workaround for hardware errata.
-		 * apply workaround for hardware errata documented in errata
-		 * docs Fixes issue where some error prone or unreliable PCIe
-		 * completions are occurring, particularly with ASPM enabled.
-		 * Without fix, issue can cause Tx timeouts.
-		 */
-		reg = er32(GCR2);
-		reg |= 1;
-		ew32(GCR2, reg);
-		break;
-	default:
-		break;
-	}
-}
-
-/**
- *  e1000_clear_vfta_82571 - Clear VLAN filter table
- *  @hw: pointer to the HW structure
- *
- *  Clears the register array which contains the VLAN filter table by
- *  setting all the values to 0.
- **/
-static void e1000_clear_vfta_82571(struct e1000_hw *hw)
-{
-	u32 offset;
-	u32 vfta_value = 0;
-	u32 vfta_offset = 0;
-	u32 vfta_bit_in_reg = 0;
-
-	switch (hw->mac.type) {
-	case e1000_82573:
-	case e1000_82574:
-	case e1000_82583:
-		if (hw->mng_cookie.vlan_id != 0) {
-			/*
-			 * The VFTA is a 4096b bit-field, each identifying
-			 * a single VLAN ID.  The following operations
-			 * determine which 32b entry (i.e. offset) into the
-			 * array we want to set the VLAN ID (i.e. bit) of
-			 * the manageability unit.
-			 */
-			vfta_offset = (hw->mng_cookie.vlan_id >>
-				       E1000_VFTA_ENTRY_SHIFT) &
-				      E1000_VFTA_ENTRY_MASK;
-			vfta_bit_in_reg = 1 << (hw->mng_cookie.vlan_id &
-					       E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
-		}
-		break;
-	default:
-		break;
-	}
-	for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
-		/*
-		 * If the offset we want to clear is the same offset of the
-		 * manageability VLAN ID, then clear all bits except that of
-		 * the manageability unit.
-		 */
-		vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
-		E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, vfta_value);
-		e1e_flush();
-	}
-}
-
-/**
- *  e1000_check_mng_mode_82574 - Check manageability is enabled
- *  @hw: pointer to the HW structure
- *
- *  Reads the NVM Initialization Control Word 2 and returns true
- *  (>0) if any manageability is enabled, else false (0).
- **/
-static bool e1000_check_mng_mode_82574(struct e1000_hw *hw)
-{
-	u16 data;
-
-	e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
-	return (data & E1000_NVM_INIT_CTRL2_MNGM) != 0;
-}
-
-/**
- *  e1000_led_on_82574 - Turn LED on
- *  @hw: pointer to the HW structure
- *
- *  Turn LED on.
- **/
-static s32 e1000_led_on_82574(struct e1000_hw *hw)
-{
-	u32 ctrl;
-	u32 i;
-
-	ctrl = hw->mac.ledctl_mode2;
-	if (!(E1000_STATUS_LU & er32(STATUS))) {
-		/*
-		 * If no link, then turn LED on by setting the invert bit
-		 * for each LED that's "on" (0x0E) in ledctl_mode2.
-		 */
-		for (i = 0; i < 4; i++)
-			if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
-			    E1000_LEDCTL_MODE_LED_ON)
-				ctrl |= (E1000_LEDCTL_LED0_IVRT << (i * 8));
-	}
-	ew32(LEDCTL, ctrl);
-
-	return 0;
-}
-
-/**
- *  e1000_check_phy_82574 - check 82574 phy hung state
- *  @hw: pointer to the HW structure
- *
- *  Returns whether phy is hung or not
- **/
-bool e1000_check_phy_82574(struct e1000_hw *hw)
-{
-	u16 status_1kbt = 0;
-	u16 receive_errors = 0;
-	bool phy_hung = false;
-	s32 ret_val = 0;
-
-	/*
-	 * Read PHY Receive Error counter first, if its is max - all F's then
-	 * read the Base1000T status register If both are max then PHY is hung.
-	 */
-	ret_val = e1e_rphy(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors);
-
-	if (ret_val)
-		goto out;
-	if (receive_errors == E1000_RECEIVE_ERROR_MAX)  {
-		ret_val = e1e_rphy(hw, E1000_BASE1000T_STATUS, &status_1kbt);
-		if (ret_val)
-			goto out;
-		if ((status_1kbt & E1000_IDLE_ERROR_COUNT_MASK) ==
-		    E1000_IDLE_ERROR_COUNT_MASK)
-			phy_hung = true;
-	}
-out:
-	return phy_hung;
-}
-
-/**
- *  e1000_setup_link_82571 - Setup flow control and link settings
- *  @hw: pointer to the HW structure
- *
- *  Determines which flow control settings to use, then configures flow
- *  control.  Calls the appropriate media-specific link configuration
- *  function.  Assuming the adapter has a valid link partner, a valid link
- *  should be established.  Assumes the hardware has previously been reset
- *  and the transmitter and receiver are not enabled.
- **/
-static s32 e1000_setup_link_82571(struct e1000_hw *hw)
-{
-	/*
-	 * 82573 does not have a word in the NVM to determine
-	 * the default flow control setting, so we explicitly
-	 * set it to full.
-	 */
-	switch (hw->mac.type) {
-	case e1000_82573:
-	case e1000_82574:
-	case e1000_82583:
-		if (hw->fc.requested_mode == e1000_fc_default)
-			hw->fc.requested_mode = e1000_fc_full;
-		break;
-	default:
-		break;
-	}
-
-	return e1000e_setup_link(hw);
-}
-
-/**
- *  e1000_setup_copper_link_82571 - Configure copper link settings
- *  @hw: pointer to the HW structure
- *
- *  Configures the link for auto-neg or forced speed and duplex.  Then we check
- *  for link, once link is established calls to configure collision distance
- *  and flow control are called.
- **/
-static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw)
-{
-	u32 ctrl;
-	s32 ret_val;
-
-	ctrl = er32(CTRL);
-	ctrl |= E1000_CTRL_SLU;
-	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
-	ew32(CTRL, ctrl);
-
-	switch (hw->phy.type) {
-	case e1000_phy_m88:
-	case e1000_phy_bm:
-		ret_val = e1000e_copper_link_setup_m88(hw);
-		break;
-	case e1000_phy_igp_2:
-		ret_val = e1000e_copper_link_setup_igp(hw);
-		break;
-	default:
-		return -E1000_ERR_PHY;
-		break;
-	}
-
-	if (ret_val)
-		return ret_val;
-
-	ret_val = e1000e_setup_copper_link(hw);
-
-	return ret_val;
-}
-
-/**
- *  e1000_setup_fiber_serdes_link_82571 - Setup link for fiber/serdes
- *  @hw: pointer to the HW structure
- *
- *  Configures collision distance and flow control for fiber and serdes links.
- *  Upon successful setup, poll for link.
- **/
-static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw)
-{
-	switch (hw->mac.type) {
-	case e1000_82571:
-	case e1000_82572:
-		/*
-		 * If SerDes loopback mode is entered, there is no form
-		 * of reset to take the adapter out of that mode.  So we
-		 * have to explicitly take the adapter out of loopback
-		 * mode.  This prevents drivers from twiddling their thumbs
-		 * if another tool failed to take it out of loopback mode.
-		 */
-		ew32(SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK);
-		break;
-	default:
-		break;
-	}
-
-	return e1000e_setup_fiber_serdes_link(hw);
-}
-
-/**
- *  e1000_check_for_serdes_link_82571 - Check for link (Serdes)
- *  @hw: pointer to the HW structure
- *
- *  Reports the link state as up or down.
- *
- *  If autonegotiation is supported by the link partner, the link state is
- *  determined by the result of autonegotiation. This is the most likely case.
- *  If autonegotiation is not supported by the link partner, and the link
- *  has a valid signal, force the link up.
- *
- *  The link state is represented internally here by 4 states:
- *
- *  1) down
- *  2) autoneg_progress
- *  3) autoneg_complete (the link successfully autonegotiated)
- *  4) forced_up (the link has been forced up, it did not autonegotiate)
- *
- **/
-static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-	u32 rxcw;
-	u32 ctrl;
-	u32 status;
-	u32 txcw;
-	u32 i;
-	s32 ret_val = 0;
-
-	ctrl = er32(CTRL);
-	status = er32(STATUS);
-	rxcw = er32(RXCW);
-
-	if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) {
-
-		/* Receiver is synchronized with no invalid bits.  */
-		switch (mac->serdes_link_state) {
-		case e1000_serdes_link_autoneg_complete:
-			if (!(status & E1000_STATUS_LU)) {
-				/*
-				 * We have lost link, retry autoneg before
-				 * reporting link failure
-				 */
-				mac->serdes_link_state =
-				    e1000_serdes_link_autoneg_progress;
-				mac->serdes_has_link = false;
-				e_dbg("AN_UP     -> AN_PROG\n");
-			} else {
-				mac->serdes_has_link = true;
-			}
-			break;
-
-		case e1000_serdes_link_forced_up:
-			/*
-			 * If we are receiving /C/ ordered sets, re-enable
-			 * auto-negotiation in the TXCW register and disable
-			 * forced link in the Device Control register in an
-			 * attempt to auto-negotiate with our link partner.
-			 * If the partner code word is null, stop forcing
-			 * and restart auto negotiation.
-			 */
-			if ((rxcw & E1000_RXCW_C) || !(rxcw & E1000_RXCW_CW))  {
-				/* Enable autoneg, and unforce link up */
-				ew32(TXCW, mac->txcw);
-				ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
-				mac->serdes_link_state =
-				    e1000_serdes_link_autoneg_progress;
-				mac->serdes_has_link = false;
-				e_dbg("FORCED_UP -> AN_PROG\n");
-			} else {
-				mac->serdes_has_link = true;
-			}
-			break;
-
-		case e1000_serdes_link_autoneg_progress:
-			if (rxcw & E1000_RXCW_C) {
-				/*
-				 * We received /C/ ordered sets, meaning the
-				 * link partner has autonegotiated, and we can
-				 * trust the Link Up (LU) status bit.
-				 */
-				if (status & E1000_STATUS_LU) {
-					mac->serdes_link_state =
-					    e1000_serdes_link_autoneg_complete;
-					e_dbg("AN_PROG   -> AN_UP\n");
-					mac->serdes_has_link = true;
-				} else {
-					/* Autoneg completed, but failed. */
-					mac->serdes_link_state =
-					    e1000_serdes_link_down;
-					e_dbg("AN_PROG   -> DOWN\n");
-				}
-			} else {
-				/*
-				 * The link partner did not autoneg.
-				 * Force link up and full duplex, and change
-				 * state to forced.
-				 */
-				ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE));
-				ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
-				ew32(CTRL, ctrl);
-
-				/* Configure Flow Control after link up. */
-				ret_val = e1000e_config_fc_after_link_up(hw);
-				if (ret_val) {
-					e_dbg("Error config flow control\n");
-					break;
-				}
-				mac->serdes_link_state =
-				    e1000_serdes_link_forced_up;
-				mac->serdes_has_link = true;
-				e_dbg("AN_PROG   -> FORCED_UP\n");
-			}
-			break;
-
-		case e1000_serdes_link_down:
-		default:
-			/*
-			 * The link was down but the receiver has now gained
-			 * valid sync, so lets see if we can bring the link
-			 * up.
-			 */
-			ew32(TXCW, mac->txcw);
-			ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
-			mac->serdes_link_state =
-			    e1000_serdes_link_autoneg_progress;
-			mac->serdes_has_link = false;
-			e_dbg("DOWN      -> AN_PROG\n");
-			break;
-		}
-	} else {
-		if (!(rxcw & E1000_RXCW_SYNCH)) {
-			mac->serdes_has_link = false;
-			mac->serdes_link_state = e1000_serdes_link_down;
-			e_dbg("ANYSTATE  -> DOWN\n");
-		} else {
-			/*
-			 * Check several times, if Sync and Config
-			 * both are consistently 1 then simply ignore
-			 * the Invalid bit and restart Autoneg
-			 */
-			for (i = 0; i < AN_RETRY_COUNT; i++) {
-				udelay(10);
-				rxcw = er32(RXCW);
-				if ((rxcw & E1000_RXCW_IV) &&
-				    !((rxcw & E1000_RXCW_SYNCH) &&
-				      (rxcw & E1000_RXCW_C))) {
-					mac->serdes_has_link = false;
-					mac->serdes_link_state =
-					    e1000_serdes_link_down;
-					e_dbg("ANYSTATE  -> DOWN\n");
-					break;
-				}
-			}
-
-			if (i == AN_RETRY_COUNT) {
-				txcw = er32(TXCW);
-				txcw |= E1000_TXCW_ANE;
-				ew32(TXCW, txcw);
-				mac->serdes_link_state =
-				    e1000_serdes_link_autoneg_progress;
-				mac->serdes_has_link = false;
-				e_dbg("ANYSTATE  -> AN_PROG\n");
-			}
-		}
-	}
-
-	return ret_val;
-}
-
-/**
- *  e1000_valid_led_default_82571 - Verify a valid default LED config
- *  @hw: pointer to the HW structure
- *  @data: pointer to the NVM (EEPROM)
- *
- *  Read the EEPROM for the current default LED configuration.  If the
- *  LED configuration is not valid, set to a valid LED configuration.
- **/
-static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data)
-{
-	s32 ret_val;
-
-	ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data);
-	if (ret_val) {
-		e_dbg("NVM Read Error\n");
-		return ret_val;
-	}
-
-	switch (hw->mac.type) {
-	case e1000_82573:
-	case e1000_82574:
-	case e1000_82583:
-		if (*data == ID_LED_RESERVED_F746)
-			*data = ID_LED_DEFAULT_82573;
-		break;
-	default:
-		if (*data == ID_LED_RESERVED_0000 ||
-		    *data == ID_LED_RESERVED_FFFF)
-			*data = ID_LED_DEFAULT;
-		break;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_get_laa_state_82571 - Get locally administered address state
- *  @hw: pointer to the HW structure
- *
- *  Retrieve and return the current locally administered address state.
- **/
-bool e1000e_get_laa_state_82571(struct e1000_hw *hw)
-{
-	if (hw->mac.type != e1000_82571)
-		return false;
-
-	return hw->dev_spec.e82571.laa_is_present;
-}
-
-/**
- *  e1000e_set_laa_state_82571 - Set locally administered address state
- *  @hw: pointer to the HW structure
- *  @state: enable/disable locally administered address
- *
- *  Enable/Disable the current locally administered address state.
- **/
-void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state)
-{
-	if (hw->mac.type != e1000_82571)
-		return;
-
-	hw->dev_spec.e82571.laa_is_present = state;
-
-	/* If workaround is activated... */
-	if (state)
-		/*
-		 * Hold a copy of the LAA in RAR[14] This is done so that
-		 * between the time RAR[0] gets clobbered and the time it
-		 * gets fixed, the actual LAA is in one of the RARs and no
-		 * incoming packets directed to this port are dropped.
-		 * Eventually the LAA will be in RAR[0] and RAR[14].
-		 */
-		e1000e_rar_set(hw, hw->mac.addr, hw->mac.rar_entry_count - 1);
-}
-
-/**
- *  e1000_fix_nvm_checksum_82571 - Fix EEPROM checksum
- *  @hw: pointer to the HW structure
- *
- *  Verifies that the EEPROM has completed the update.  After updating the
- *  EEPROM, we need to check bit 15 in work 0x23 for the checksum fix.  If
- *  the checksum fix is not implemented, we need to set the bit and update
- *  the checksum.  Otherwise, if bit 15 is set and the checksum is incorrect,
- *  we need to return bad checksum.
- **/
-static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw)
-{
-	struct e1000_nvm_info *nvm = &hw->nvm;
-	s32 ret_val;
-	u16 data;
-
-	if (nvm->type != e1000_nvm_flash_hw)
-		return 0;
-
-	/*
-	 * Check bit 4 of word 10h.  If it is 0, firmware is done updating
-	 * 10h-12h.  Checksum may need to be fixed.
-	 */
-	ret_val = e1000_read_nvm(hw, 0x10, 1, &data);
-	if (ret_val)
-		return ret_val;
-
-	if (!(data & 0x10)) {
-		/*
-		 * Read 0x23 and check bit 15.  This bit is a 1
-		 * when the checksum has already been fixed.  If
-		 * the checksum is still wrong and this bit is a
-		 * 1, we need to return bad checksum.  Otherwise,
-		 * we need to set this bit to a 1 and update the
-		 * checksum.
-		 */
-		ret_val = e1000_read_nvm(hw, 0x23, 1, &data);
-		if (ret_val)
-			return ret_val;
-
-		if (!(data & 0x8000)) {
-			data |= 0x8000;
-			ret_val = e1000_write_nvm(hw, 0x23, 1, &data);
-			if (ret_val)
-				return ret_val;
-			ret_val = e1000e_update_nvm_checksum(hw);
-		}
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_read_mac_addr_82571 - Read device MAC address
- *  @hw: pointer to the HW structure
- **/
-static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw)
-{
-	s32 ret_val = 0;
-
-	if (hw->mac.type == e1000_82571) {
-		/*
-		 * If there's an alternate MAC address place it in RAR0
-		 * so that it will override the Si installed default perm
-		 * address.
-		 */
-		ret_val = e1000_check_alt_mac_addr_generic(hw);
-		if (ret_val)
-			goto out;
-	}
-
-	ret_val = e1000_read_mac_addr_generic(hw);
-
-out:
-	return ret_val;
-}
-
-/**
- * e1000_power_down_phy_copper_82571 - Remove link during PHY power down
- * @hw: pointer to the HW structure
- *
- * In the case of a PHY power down to save power, or to turn off link during a
- * driver unload, or wake on lan is not enabled, remove the link.
- **/
-static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	struct e1000_mac_info *mac = &hw->mac;
-
-	if (!(phy->ops.check_reset_block))
-		return;
-
-	/* If the management interface is not enabled, then power down */
-	if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw)))
-		e1000_power_down_phy_copper(hw);
-}
-
-/**
- *  e1000_clear_hw_cntrs_82571 - Clear device specific hardware counters
- *  @hw: pointer to the HW structure
- *
- *  Clears the hardware counters by reading the counter registers.
- **/
-static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw)
-{
-	e1000e_clear_hw_cntrs_base(hw);
-
-	er32(PRC64);
-	er32(PRC127);
-	er32(PRC255);
-	er32(PRC511);
-	er32(PRC1023);
-	er32(PRC1522);
-	er32(PTC64);
-	er32(PTC127);
-	er32(PTC255);
-	er32(PTC511);
-	er32(PTC1023);
-	er32(PTC1522);
-
-	er32(ALGNERRC);
-	er32(RXERRC);
-	er32(TNCRS);
-	er32(CEXTERR);
-	er32(TSCTC);
-	er32(TSCTFC);
-
-	er32(MGTPRC);
-	er32(MGTPDC);
-	er32(MGTPTC);
-
-	er32(IAC);
-	er32(ICRXOC);
-
-	er32(ICRXPTC);
-	er32(ICRXATC);
-	er32(ICTXPTC);
-	er32(ICTXATC);
-	er32(ICTXQEC);
-	er32(ICTXQMTC);
-	er32(ICRXDMTC);
-}
-
-static struct e1000_mac_operations e82571_mac_ops = {
-	/* .check_mng_mode: mac type dependent */
-	/* .check_for_link: media type dependent */
-	.id_led_init		= e1000e_id_led_init,
-	.cleanup_led		= e1000e_cleanup_led_generic,
-	.clear_hw_cntrs		= e1000_clear_hw_cntrs_82571,
-	.get_bus_info		= e1000e_get_bus_info_pcie,
-	.set_lan_id		= e1000_set_lan_id_multi_port_pcie,
-	/* .get_link_up_info: media type dependent */
-	/* .led_on: mac type dependent */
-	.led_off		= e1000e_led_off_generic,
-	.update_mc_addr_list	= e1000e_update_mc_addr_list_generic,
-	.write_vfta		= e1000_write_vfta_generic,
-	.clear_vfta		= e1000_clear_vfta_82571,
-	.reset_hw		= e1000_reset_hw_82571,
-	.init_hw		= e1000_init_hw_82571,
-	.setup_link		= e1000_setup_link_82571,
-	/* .setup_physical_interface: media type dependent */
-	.setup_led		= e1000e_setup_led_generic,
-	.read_mac_addr		= e1000_read_mac_addr_82571,
-};
-
-static struct e1000_phy_operations e82_phy_ops_igp = {
-	.acquire		= e1000_get_hw_semaphore_82571,
-	.check_polarity		= e1000_check_polarity_igp,
-	.check_reset_block	= e1000e_check_reset_block_generic,
-	.commit			= NULL,
-	.force_speed_duplex	= e1000e_phy_force_speed_duplex_igp,
-	.get_cfg_done		= e1000_get_cfg_done_82571,
-	.get_cable_length	= e1000e_get_cable_length_igp_2,
-	.get_info		= e1000e_get_phy_info_igp,
-	.read_reg		= e1000e_read_phy_reg_igp,
-	.release		= e1000_put_hw_semaphore_82571,
-	.reset			= e1000e_phy_hw_reset_generic,
-	.set_d0_lplu_state	= e1000_set_d0_lplu_state_82571,
-	.set_d3_lplu_state	= e1000e_set_d3_lplu_state,
-	.write_reg		= e1000e_write_phy_reg_igp,
-	.cfg_on_link_up      	= NULL,
-};
-
-static struct e1000_phy_operations e82_phy_ops_m88 = {
-	.acquire		= e1000_get_hw_semaphore_82571,
-	.check_polarity		= e1000_check_polarity_m88,
-	.check_reset_block	= e1000e_check_reset_block_generic,
-	.commit			= e1000e_phy_sw_reset,
-	.force_speed_duplex	= e1000e_phy_force_speed_duplex_m88,
-	.get_cfg_done		= e1000e_get_cfg_done,
-	.get_cable_length	= e1000e_get_cable_length_m88,
-	.get_info		= e1000e_get_phy_info_m88,
-	.read_reg		= e1000e_read_phy_reg_m88,
-	.release		= e1000_put_hw_semaphore_82571,
-	.reset			= e1000e_phy_hw_reset_generic,
-	.set_d0_lplu_state	= e1000_set_d0_lplu_state_82571,
-	.set_d3_lplu_state	= e1000e_set_d3_lplu_state,
-	.write_reg		= e1000e_write_phy_reg_m88,
-	.cfg_on_link_up      	= NULL,
-};
-
-static struct e1000_phy_operations e82_phy_ops_bm = {
-	.acquire		= e1000_get_hw_semaphore_82571,
-	.check_polarity		= e1000_check_polarity_m88,
-	.check_reset_block	= e1000e_check_reset_block_generic,
-	.commit			= e1000e_phy_sw_reset,
-	.force_speed_duplex	= e1000e_phy_force_speed_duplex_m88,
-	.get_cfg_done		= e1000e_get_cfg_done,
-	.get_cable_length	= e1000e_get_cable_length_m88,
-	.get_info		= e1000e_get_phy_info_m88,
-	.read_reg		= e1000e_read_phy_reg_bm2,
-	.release		= e1000_put_hw_semaphore_82571,
-	.reset			= e1000e_phy_hw_reset_generic,
-	.set_d0_lplu_state	= e1000_set_d0_lplu_state_82571,
-	.set_d3_lplu_state	= e1000e_set_d3_lplu_state,
-	.write_reg		= e1000e_write_phy_reg_bm2,
-	.cfg_on_link_up      	= NULL,
-};
-
-static struct e1000_nvm_operations e82571_nvm_ops = {
-	.acquire		= e1000_acquire_nvm_82571,
-	.read			= e1000e_read_nvm_eerd,
-	.release		= e1000_release_nvm_82571,
-	.update			= e1000_update_nvm_checksum_82571,
-	.valid_led_default	= e1000_valid_led_default_82571,
-	.validate		= e1000_validate_nvm_checksum_82571,
-	.write			= e1000_write_nvm_82571,
-};
-
-struct e1000_info e1000_82571_info = {
-	.mac			= e1000_82571,
-	.flags			= FLAG_HAS_HW_VLAN_FILTER
-				  | FLAG_HAS_JUMBO_FRAMES
-				  | FLAG_HAS_WOL
-				  | FLAG_APME_IN_CTRL3
-				  | FLAG_RX_CSUM_ENABLED
-				  | FLAG_HAS_CTRLEXT_ON_LOAD
-				  | FLAG_HAS_SMART_POWER_DOWN
-				  | FLAG_RESET_OVERWRITES_LAA /* errata */
-				  | FLAG_TARC_SPEED_MODE_BIT /* errata */
-				  | FLAG_APME_CHECK_PORT_B,
-	.flags2			= FLAG2_DISABLE_ASPM_L1 /* errata 13 */
-				  | FLAG2_DMA_BURST,
-	.pba			= 38,
-	.max_hw_frame_size	= DEFAULT_JUMBO,
-	.get_variants		= e1000_get_variants_82571,
-	.mac_ops		= &e82571_mac_ops,
-	.phy_ops		= &e82_phy_ops_igp,
-	.nvm_ops		= &e82571_nvm_ops,
-};
-
-struct e1000_info e1000_82572_info = {
-	.mac			= e1000_82572,
-	.flags			= FLAG_HAS_HW_VLAN_FILTER
-				  | FLAG_HAS_JUMBO_FRAMES
-				  | FLAG_HAS_WOL
-				  | FLAG_APME_IN_CTRL3
-				  | FLAG_RX_CSUM_ENABLED
-				  | FLAG_HAS_CTRLEXT_ON_LOAD
-				  | FLAG_TARC_SPEED_MODE_BIT, /* errata */
-	.flags2			= FLAG2_DISABLE_ASPM_L1 /* errata 13 */
-				  | FLAG2_DMA_BURST,
-	.pba			= 38,
-	.max_hw_frame_size	= DEFAULT_JUMBO,
-	.get_variants		= e1000_get_variants_82571,
-	.mac_ops		= &e82571_mac_ops,
-	.phy_ops		= &e82_phy_ops_igp,
-	.nvm_ops		= &e82571_nvm_ops,
-};
-
-struct e1000_info e1000_82573_info = {
-	.mac			= e1000_82573,
-	.flags			= FLAG_HAS_HW_VLAN_FILTER
-				  | FLAG_HAS_WOL
-				  | FLAG_APME_IN_CTRL3
-				  | FLAG_RX_CSUM_ENABLED
-				  | FLAG_HAS_SMART_POWER_DOWN
-				  | FLAG_HAS_AMT
-				  | FLAG_HAS_SWSM_ON_LOAD,
-	.flags2			= FLAG2_DISABLE_ASPM_L1
-				  | FLAG2_DISABLE_ASPM_L0S,
-	.pba			= 20,
-	.max_hw_frame_size	= ETH_FRAME_LEN + ETH_FCS_LEN,
-	.get_variants		= e1000_get_variants_82571,
-	.mac_ops		= &e82571_mac_ops,
-	.phy_ops		= &e82_phy_ops_m88,
-	.nvm_ops		= &e82571_nvm_ops,
-};
-
-struct e1000_info e1000_82574_info = {
-	.mac			= e1000_82574,
-	.flags			= FLAG_HAS_HW_VLAN_FILTER
-				  | FLAG_HAS_MSIX
-				  | FLAG_HAS_JUMBO_FRAMES
-				  | FLAG_HAS_WOL
-				  | FLAG_APME_IN_CTRL3
-				  | FLAG_RX_CSUM_ENABLED
-				  | FLAG_HAS_SMART_POWER_DOWN
-				  | FLAG_HAS_AMT
-				  | FLAG_HAS_CTRLEXT_ON_LOAD,
-	.flags2			  = FLAG2_CHECK_PHY_HANG
-				  | FLAG2_DISABLE_ASPM_L0S
-				  | FLAG2_NO_DISABLE_RX,
-	.pba			= 32,
-	.max_hw_frame_size	= DEFAULT_JUMBO,
-	.get_variants		= e1000_get_variants_82571,
-	.mac_ops		= &e82571_mac_ops,
-	.phy_ops		= &e82_phy_ops_bm,
-	.nvm_ops		= &e82571_nvm_ops,
-};
-
-struct e1000_info e1000_82583_info = {
-	.mac			= e1000_82583,
-	.flags			= FLAG_HAS_HW_VLAN_FILTER
-				  | FLAG_HAS_WOL
-				  | FLAG_APME_IN_CTRL3
-				  | FLAG_RX_CSUM_ENABLED
-				  | FLAG_HAS_SMART_POWER_DOWN
-				  | FLAG_HAS_AMT
-				  | FLAG_HAS_JUMBO_FRAMES
-				  | FLAG_HAS_CTRLEXT_ON_LOAD,
-	.flags2			= FLAG2_DISABLE_ASPM_L0S
-				  | FLAG2_NO_DISABLE_RX,
-	.pba			= 32,
-	.max_hw_frame_size	= DEFAULT_JUMBO,
-	.get_variants		= e1000_get_variants_82571,
-	.mac_ops		= &e82571_mac_ops,
-	.phy_ops		= &e82_phy_ops_bm,
-	.nvm_ops		= &e82571_nvm_ops,
-};
-
diff -druN linux-libre-3.1-gnu/drivers/net/e1000e/defines.h linux-libre-3.2-gnu/drivers/net/e1000e/defines.h
--- linux-libre-3.1-gnu/drivers/net/e1000e/defines.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000e/defines.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,844 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  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,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-#ifndef _E1000_DEFINES_H_
-#define _E1000_DEFINES_H_
-
-#define E1000_TXD_POPTS_IXSM 0x01       /* Insert IP checksum */
-#define E1000_TXD_POPTS_TXSM 0x02       /* Insert TCP/UDP checksum */
-#define E1000_TXD_CMD_EOP    0x01000000 /* End of Packet */
-#define E1000_TXD_CMD_IFCS   0x02000000 /* Insert FCS (Ethernet CRC) */
-#define E1000_TXD_CMD_IC     0x04000000 /* Insert Checksum */
-#define E1000_TXD_CMD_RS     0x08000000 /* Report Status */
-#define E1000_TXD_CMD_RPS    0x10000000 /* Report Packet Sent */
-#define E1000_TXD_CMD_DEXT   0x20000000 /* Descriptor extension (0 = legacy) */
-#define E1000_TXD_CMD_VLE    0x40000000 /* Add VLAN tag */
-#define E1000_TXD_CMD_IDE    0x80000000 /* Enable Tidv register */
-#define E1000_TXD_STAT_DD    0x00000001 /* Descriptor Done */
-#define E1000_TXD_STAT_EC    0x00000002 /* Excess Collisions */
-#define E1000_TXD_STAT_LC    0x00000004 /* Late Collisions */
-#define E1000_TXD_STAT_TU    0x00000008 /* Transmit underrun */
-#define E1000_TXD_CMD_TCP    0x01000000 /* TCP packet */
-#define E1000_TXD_CMD_IP     0x02000000 /* IP packet */
-#define E1000_TXD_CMD_TSE    0x04000000 /* TCP Seg enable */
-#define E1000_TXD_STAT_TC    0x00000004 /* Tx Underrun */
-
-/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
-#define REQ_TX_DESCRIPTOR_MULTIPLE  8
-#define REQ_RX_DESCRIPTOR_MULTIPLE  8
-
-/* Definitions for power management and wakeup registers */
-/* Wake Up Control */
-#define E1000_WUC_APME       0x00000001 /* APM Enable */
-#define E1000_WUC_PME_EN     0x00000002 /* PME Enable */
-#define E1000_WUC_PHY_WAKE   0x00000100 /* if PHY supports wakeup */
-
-/* Wake Up Filter Control */
-#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
-#define E1000_WUFC_MAG  0x00000002 /* Magic Packet Wakeup Enable */
-#define E1000_WUFC_EX   0x00000004 /* Directed Exact Wakeup Enable */
-#define E1000_WUFC_MC   0x00000008 /* Directed Multicast Wakeup Enable */
-#define E1000_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */
-#define E1000_WUFC_ARP  0x00000020 /* ARP Request Packet Wakeup Enable */
-
-/* Wake Up Status */
-#define E1000_WUS_LNKC         E1000_WUFC_LNKC
-#define E1000_WUS_MAG          E1000_WUFC_MAG
-#define E1000_WUS_EX           E1000_WUFC_EX
-#define E1000_WUS_MC           E1000_WUFC_MC
-#define E1000_WUS_BC           E1000_WUFC_BC
-
-/* Extended Device Control */
-#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Definable Pin 3 */
-#define E1000_CTRL_EXT_EE_RST    0x00002000 /* Reinitialize from EEPROM */
-#define E1000_CTRL_EXT_SPD_BYPS  0x00008000 /* Speed Select Bypass */
-#define E1000_CTRL_EXT_RO_DIS    0x00020000 /* Relaxed Ordering disable */
-#define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */
-#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
-#define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES  0x00C00000
-#define E1000_CTRL_EXT_EIAME          0x01000000
-#define E1000_CTRL_EXT_DRV_LOAD       0x10000000 /* Driver loaded bit for FW */
-#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 */
-#define E1000_RXD_STAT_DD       0x01    /* Descriptor Done */
-#define E1000_RXD_STAT_EOP      0x02    /* End of Packet */
-#define E1000_RXD_STAT_IXSM     0x04    /* Ignore checksum */
-#define E1000_RXD_STAT_VP       0x08    /* IEEE VLAN Packet */
-#define E1000_RXD_STAT_UDPCS    0x10    /* UDP xsum calculated */
-#define E1000_RXD_STAT_TCPCS    0x20    /* TCP xsum calculated */
-#define E1000_RXD_ERR_CE        0x01    /* CRC Error */
-#define E1000_RXD_ERR_SE        0x02    /* Symbol Error */
-#define E1000_RXD_ERR_SEQ       0x04    /* Sequence Error */
-#define E1000_RXD_ERR_CXE       0x10    /* Carrier Extension Error */
-#define E1000_RXD_ERR_TCPE      0x20    /* TCP/UDP Checksum Error */
-#define E1000_RXD_ERR_RXE       0x80    /* Rx Data Error */
-#define E1000_RXD_SPC_VLAN_MASK 0x0FFF  /* VLAN ID is in lower 12 bits */
-
-#define E1000_RXDEXT_STATERR_CE    0x01000000
-#define E1000_RXDEXT_STATERR_SE    0x02000000
-#define E1000_RXDEXT_STATERR_SEQ   0x04000000
-#define E1000_RXDEXT_STATERR_CXE   0x10000000
-#define E1000_RXDEXT_STATERR_RXE   0x80000000
-
-/* mask to determine if packets should be dropped due to frame errors */
-#define E1000_RXD_ERR_FRAME_ERR_MASK ( \
-    E1000_RXD_ERR_CE  |                \
-    E1000_RXD_ERR_SE  |                \
-    E1000_RXD_ERR_SEQ |                \
-    E1000_RXD_ERR_CXE |                \
-    E1000_RXD_ERR_RXE)
-
-/* Same mask, but for extended and packet split descriptors */
-#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \
-    E1000_RXDEXT_STATERR_CE  |            \
-    E1000_RXDEXT_STATERR_SE  |            \
-    E1000_RXDEXT_STATERR_SEQ |            \
-    E1000_RXDEXT_STATERR_CXE |            \
-    E1000_RXDEXT_STATERR_RXE)
-
-#define E1000_RXDPS_HDRSTAT_HDRSP              0x00008000
-
-/* Management Control */
-#define E1000_MANC_SMBUS_EN      0x00000001 /* SMBus Enabled - RO */
-#define E1000_MANC_ASF_EN        0x00000002 /* ASF Enabled - RO */
-#define E1000_MANC_ARP_EN        0x00002000 /* Enable ARP Request Filtering */
-#define E1000_MANC_RCV_TCO_EN    0x00020000 /* Receive TCO Packets Enabled */
-#define E1000_MANC_BLK_PHY_RST_ON_IDE   0x00040000 /* Block phy resets */
-/* Enable MAC address filtering */
-#define E1000_MANC_EN_MAC_ADDR_FILTER   0x00100000
-/* Enable MNG packets to host memory */
-#define E1000_MANC_EN_MNG2HOST   0x00200000
-
-#define E1000_MANC2H_PORT_623    0x00000020 /* Port 0x26f */
-#define E1000_MANC2H_PORT_664    0x00000040 /* Port 0x298 */
-#define E1000_MDEF_PORT_623      0x00000800 /* Port 0x26f */
-#define E1000_MDEF_PORT_664      0x00000400 /* Port 0x298 */
-
-/* Receive Control */
-#define E1000_RCTL_EN             0x00000002    /* enable */
-#define E1000_RCTL_SBP            0x00000004    /* store bad packet */
-#define E1000_RCTL_UPE            0x00000008    /* unicast promiscuous enable */
-#define E1000_RCTL_MPE            0x00000010    /* multicast promiscuous enab */
-#define E1000_RCTL_LPE            0x00000020    /* long packet enable */
-#define E1000_RCTL_LBM_NO         0x00000000    /* no loopback mode */
-#define E1000_RCTL_LBM_MAC        0x00000040    /* MAC loopback mode */
-#define E1000_RCTL_LBM_TCVR       0x000000C0    /* tcvr loopback mode */
-#define E1000_RCTL_DTYP_PS        0x00000400    /* Packet Split descriptor */
-#define E1000_RCTL_RDMTS_HALF     0x00000000    /* Rx desc min threshold size */
-#define E1000_RCTL_MO_SHIFT       12            /* multicast offset shift */
-#define E1000_RCTL_MO_3           0x00003000    /* multicast offset 15:4 */
-#define E1000_RCTL_BAM            0x00008000    /* broadcast enable */
-/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
-#define E1000_RCTL_SZ_2048        0x00000000    /* Rx buffer size 2048 */
-#define E1000_RCTL_SZ_1024        0x00010000    /* Rx buffer size 1024 */
-#define E1000_RCTL_SZ_512         0x00020000    /* Rx buffer size 512 */
-#define E1000_RCTL_SZ_256         0x00030000    /* Rx buffer size 256 */
-/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
-#define E1000_RCTL_SZ_16384       0x00010000    /* Rx buffer size 16384 */
-#define E1000_RCTL_SZ_8192        0x00020000    /* Rx buffer size 8192 */
-#define E1000_RCTL_SZ_4096        0x00030000    /* Rx buffer size 4096 */
-#define E1000_RCTL_VFE            0x00040000    /* vlan filter enable */
-#define E1000_RCTL_CFIEN          0x00080000    /* canonical form enable */
-#define E1000_RCTL_CFI            0x00100000    /* canonical form indicator */
-#define E1000_RCTL_PMCF           0x00800000    /* pass MAC control frames */
-#define E1000_RCTL_BSEX           0x02000000    /* Buffer size extension */
-#define E1000_RCTL_SECRC          0x04000000    /* Strip Ethernet CRC */
-
-/*
- * Use byte values for the following shift parameters
- * Usage:
- *     psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) &
- *                  E1000_PSRCTL_BSIZE0_MASK) |
- *                ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) &
- *                  E1000_PSRCTL_BSIZE1_MASK) |
- *                ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) &
- *                  E1000_PSRCTL_BSIZE2_MASK) |
- *                ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |;
- *                  E1000_PSRCTL_BSIZE3_MASK))
- * where value0 = [128..16256],  default=256
- *       value1 = [1024..64512], default=4096
- *       value2 = [0..64512],    default=4096
- *       value3 = [0..64512],    default=0
- */
-
-#define E1000_PSRCTL_BSIZE0_MASK   0x0000007F
-#define E1000_PSRCTL_BSIZE1_MASK   0x00003F00
-#define E1000_PSRCTL_BSIZE2_MASK   0x003F0000
-#define E1000_PSRCTL_BSIZE3_MASK   0x3F000000
-
-#define E1000_PSRCTL_BSIZE0_SHIFT  7            /* Shift _right_ 7 */
-#define E1000_PSRCTL_BSIZE1_SHIFT  2            /* Shift _right_ 2 */
-#define E1000_PSRCTL_BSIZE2_SHIFT  6            /* Shift _left_ 6 */
-#define E1000_PSRCTL_BSIZE3_SHIFT 14            /* Shift _left_ 14 */
-
-/* SWFW_SYNC Definitions */
-#define E1000_SWFW_EEP_SM   0x1
-#define E1000_SWFW_PHY0_SM  0x2
-#define E1000_SWFW_PHY1_SM  0x4
-#define E1000_SWFW_CSR_SM   0x8
-
-/* Device Control */
-#define E1000_CTRL_FD       0x00000001  /* Full duplex.0=half; 1=full */
-#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master requests */
-#define E1000_CTRL_LRST     0x00000008  /* Link reset. 0=normal,1=reset */
-#define E1000_CTRL_ASDE     0x00000020  /* Auto-speed detect enable */
-#define E1000_CTRL_SLU      0x00000040  /* Set link up (Force Link) */
-#define E1000_CTRL_ILOS     0x00000080  /* Invert Loss-Of Signal */
-#define E1000_CTRL_SPD_SEL  0x00000300  /* Speed Select Mask */
-#define E1000_CTRL_SPD_10   0x00000000  /* Force 10Mb */
-#define E1000_CTRL_SPD_100  0x00000100  /* Force 100Mb */
-#define E1000_CTRL_SPD_1000 0x00000200  /* Force 1Gb */
-#define E1000_CTRL_FRCSPD   0x00000800  /* Force Speed */
-#define E1000_CTRL_FRCDPX   0x00001000  /* Force Duplex */
-#define E1000_CTRL_LANPHYPC_OVERRIDE 0x00010000 /* SW control of LANPHYPC */
-#define E1000_CTRL_LANPHYPC_VALUE    0x00020000 /* SW value of LANPHYPC */
-#define E1000_CTRL_SWDPIN0  0x00040000  /* SWDPIN 0 value */
-#define E1000_CTRL_SWDPIN1  0x00080000  /* SWDPIN 1 value */
-#define E1000_CTRL_SWDPIO0  0x00400000  /* SWDPIN 0 Input or output */
-#define E1000_CTRL_RST      0x04000000  /* Global reset */
-#define E1000_CTRL_RFCE     0x08000000  /* Receive Flow Control enable */
-#define E1000_CTRL_TFCE     0x10000000  /* Transmit flow control enable */
-#define E1000_CTRL_VME      0x40000000  /* IEEE VLAN mode enable */
-#define E1000_CTRL_PHY_RST  0x80000000  /* PHY Reset */
-
-/*
- * Bit definitions for the Management Data IO (MDIO) and Management Data
- * Clock (MDC) pins in the Device Control Register.
- */
-
-/* Device Status */
-#define E1000_STATUS_FD         0x00000001      /* Full duplex.0=half,1=full */
-#define E1000_STATUS_LU         0x00000002      /* Link up.0=no,1=link */
-#define E1000_STATUS_FUNC_MASK  0x0000000C      /* PCI Function Mask */
-#define E1000_STATUS_FUNC_SHIFT 2
-#define E1000_STATUS_FUNC_1     0x00000004      /* Function 1 */
-#define E1000_STATUS_TXOFF      0x00000010      /* transmission paused */
-#define E1000_STATUS_SPEED_10   0x00000000      /* Speed 10Mb/s */
-#define E1000_STATUS_SPEED_100  0x00000040      /* Speed 100Mb/s */
-#define E1000_STATUS_SPEED_1000 0x00000080      /* Speed 1000Mb/s */
-#define E1000_STATUS_LAN_INIT_DONE 0x00000200   /* Lan Init Completion by NVM */
-#define E1000_STATUS_PHYRA      0x00000400      /* PHY Reset Asserted */
-#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */
-
-/* Constants used to interpret the masked PCI-X bus speed. */
-
-#define HALF_DUPLEX 1
-#define FULL_DUPLEX 2
-
-
-#define ADVERTISE_10_HALF                 0x0001
-#define ADVERTISE_10_FULL                 0x0002
-#define ADVERTISE_100_HALF                0x0004
-#define ADVERTISE_100_FULL                0x0008
-#define ADVERTISE_1000_HALF               0x0010 /* Not used, just FYI */
-#define ADVERTISE_1000_FULL               0x0020
-
-/* 1000/H is not supported, nor spec-compliant. */
-#define E1000_ALL_SPEED_DUPLEX ( ADVERTISE_10_HALF |   ADVERTISE_10_FULL | \
-				ADVERTISE_100_HALF |  ADVERTISE_100_FULL | \
-						     ADVERTISE_1000_FULL)
-#define E1000_ALL_NOT_GIG      ( ADVERTISE_10_HALF |   ADVERTISE_10_FULL | \
-				ADVERTISE_100_HALF |  ADVERTISE_100_FULL)
-#define E1000_ALL_100_SPEED    (ADVERTISE_100_HALF |  ADVERTISE_100_FULL)
-#define E1000_ALL_10_SPEED      (ADVERTISE_10_HALF |   ADVERTISE_10_FULL)
-#define E1000_ALL_HALF_DUPLEX   (ADVERTISE_10_HALF |  ADVERTISE_100_HALF)
-
-#define AUTONEG_ADVERTISE_SPEED_DEFAULT   E1000_ALL_SPEED_DUPLEX
-
-/* LED Control */
-#define E1000_PHY_LED0_MODE_MASK          0x00000007
-#define E1000_PHY_LED0_IVRT               0x00000008
-#define E1000_PHY_LED0_MASK               0x0000001F
-
-#define E1000_LEDCTL_LED0_MODE_MASK       0x0000000F
-#define E1000_LEDCTL_LED0_MODE_SHIFT      0
-#define E1000_LEDCTL_LED0_IVRT            0x00000040
-#define E1000_LEDCTL_LED0_BLINK           0x00000080
-
-#define E1000_LEDCTL_MODE_LINK_UP       0x2
-#define E1000_LEDCTL_MODE_LED_ON        0xE
-#define E1000_LEDCTL_MODE_LED_OFF       0xF
-
-/* Transmit Descriptor bit definitions */
-#define E1000_TXD_DTYP_D     0x00100000 /* Data Descriptor */
-#define E1000_TXD_POPTS_IXSM 0x01       /* Insert IP checksum */
-#define E1000_TXD_POPTS_TXSM 0x02       /* Insert TCP/UDP checksum */
-#define E1000_TXD_CMD_EOP    0x01000000 /* End of Packet */
-#define E1000_TXD_CMD_IFCS   0x02000000 /* Insert FCS (Ethernet CRC) */
-#define E1000_TXD_CMD_IC     0x04000000 /* Insert Checksum */
-#define E1000_TXD_CMD_RS     0x08000000 /* Report Status */
-#define E1000_TXD_CMD_RPS    0x10000000 /* Report Packet Sent */
-#define E1000_TXD_CMD_DEXT   0x20000000 /* Descriptor extension (0 = legacy) */
-#define E1000_TXD_CMD_VLE    0x40000000 /* Add VLAN tag */
-#define E1000_TXD_CMD_IDE    0x80000000 /* Enable Tidv register */
-#define E1000_TXD_STAT_DD    0x00000001 /* Descriptor Done */
-#define E1000_TXD_STAT_EC    0x00000002 /* Excess Collisions */
-#define E1000_TXD_STAT_LC    0x00000004 /* Late Collisions */
-#define E1000_TXD_STAT_TU    0x00000008 /* Transmit underrun */
-#define E1000_TXD_CMD_TCP    0x01000000 /* TCP packet */
-#define E1000_TXD_CMD_IP     0x02000000 /* IP packet */
-#define E1000_TXD_CMD_TSE    0x04000000 /* TCP Seg enable */
-#define E1000_TXD_STAT_TC    0x00000004 /* Tx Underrun */
-
-/* Transmit Control */
-#define E1000_TCTL_EN     0x00000002    /* enable Tx */
-#define E1000_TCTL_PSP    0x00000008    /* pad short packets */
-#define E1000_TCTL_CT     0x00000ff0    /* collision threshold */
-#define E1000_TCTL_COLD   0x003ff000    /* collision distance */
-#define E1000_TCTL_RTLC   0x01000000    /* Re-transmit on late collision */
-#define E1000_TCTL_MULR   0x10000000    /* Multiple request support */
-
-/* Transmit Arbitration Count */
-
-/* SerDes Control */
-#define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400
-
-/* Receive Checksum Control */
-#define E1000_RXCSUM_TUOFL     0x00000200   /* TCP / UDP checksum offload */
-#define E1000_RXCSUM_IPPCSE    0x00001000   /* IP payload checksum enable */
-
-/* Header split receive */
-#define E1000_RFCTL_NFSW_DIS            0x00000040
-#define E1000_RFCTL_NFSR_DIS            0x00000080
-#define E1000_RFCTL_ACK_DIS             0x00001000
-#define E1000_RFCTL_EXTEN               0x00008000
-#define E1000_RFCTL_IPV6_EX_DIS         0x00010000
-#define E1000_RFCTL_NEW_IPV6_EXT_DIS    0x00020000
-
-/* Collision related configuration parameters */
-#define E1000_COLLISION_THRESHOLD       15
-#define E1000_CT_SHIFT                  4
-#define E1000_COLLISION_DISTANCE        63
-#define E1000_COLD_SHIFT                12
-
-/* Default values for the transmit IPG register */
-#define DEFAULT_82543_TIPG_IPGT_COPPER 8
-
-#define E1000_TIPG_IPGT_MASK  0x000003FF
-
-#define DEFAULT_82543_TIPG_IPGR1 8
-#define E1000_TIPG_IPGR1_SHIFT  10
-
-#define DEFAULT_82543_TIPG_IPGR2 6
-#define DEFAULT_80003ES2LAN_TIPG_IPGR2 7
-#define E1000_TIPG_IPGR2_SHIFT  20
-
-#define MAX_JUMBO_FRAME_SIZE    0x3F00
-
-/* Extended Configuration Control and Size */
-#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP      0x00000020
-#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE       0x00000001
-#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE       0x00000008
-#define E1000_EXTCNF_CTRL_SWFLAG                 0x00000020
-#define E1000_EXTCNF_CTRL_GATE_PHY_CFG           0x00000080
-#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK   0x00FF0000
-#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT          16
-#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK   0x0FFF0000
-#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT          16
-
-#define E1000_PHY_CTRL_D0A_LPLU           0x00000002
-#define E1000_PHY_CTRL_NOND0A_LPLU        0x00000004
-#define E1000_PHY_CTRL_NOND0A_GBE_DISABLE 0x00000008
-#define E1000_PHY_CTRL_GBE_DISABLE        0x00000040
-
-#define E1000_KABGTXD_BGSQLBIAS           0x00050000
-
-/* PBA constants */
-#define E1000_PBA_8K  0x0008    /* 8KB */
-#define E1000_PBA_16K 0x0010    /* 16KB */
-
-#define E1000_PBS_16K E1000_PBA_16K
-
-#define IFS_MAX       80
-#define IFS_MIN       40
-#define IFS_RATIO     4
-#define IFS_STEP      10
-#define MIN_NUM_XMITS 1000
-
-/* SW Semaphore Register */
-#define E1000_SWSM_SMBI         0x00000001 /* Driver Semaphore bit */
-#define E1000_SWSM_SWESMBI      0x00000002 /* FW Semaphore bit */
-#define E1000_SWSM_DRV_LOAD     0x00000008 /* Driver Loaded Bit */
-
-#define E1000_SWSM2_LOCK        0x00000002 /* Secondary driver semaphore bit */
-
-/* Interrupt Cause Read */
-#define E1000_ICR_TXDW          0x00000001 /* Transmit desc written back */
-#define E1000_ICR_LSC           0x00000004 /* Link Status Change */
-#define E1000_ICR_RXSEQ         0x00000008 /* Rx sequence error */
-#define E1000_ICR_RXDMT0        0x00000010 /* Rx desc min. threshold (0) */
-#define E1000_ICR_RXT0          0x00000080 /* Rx timer intr (ring 0) */
-#define E1000_ICR_INT_ASSERTED  0x80000000 /* If this bit asserted, the driver should claim the interrupt */
-#define E1000_ICR_RXQ0          0x00100000 /* Rx Queue 0 Interrupt */
-#define E1000_ICR_RXQ1          0x00200000 /* Rx Queue 1 Interrupt */
-#define E1000_ICR_TXQ0          0x00400000 /* Tx Queue 0 Interrupt */
-#define E1000_ICR_TXQ1          0x00800000 /* Tx Queue 1 Interrupt */
-#define E1000_ICR_OTHER         0x01000000 /* Other Interrupts */
-
-/* PBA ECC Register */
-#define E1000_PBA_ECC_COUNTER_MASK  0xFFF00000 /* ECC counter mask */
-#define E1000_PBA_ECC_COUNTER_SHIFT 20         /* ECC counter shift value */
-#define E1000_PBA_ECC_CORR_EN       0x00000001 /* ECC correction enable */
-#define E1000_PBA_ECC_STAT_CLR      0x00000002 /* Clear ECC error counter */
-#define E1000_PBA_ECC_INT_EN        0x00000004 /* Enable ICR bit 5 for ECC */
-
-/*
- * This defines the bits that are set in the Interrupt Mask
- * Set/Read Register.  Each bit is documented below:
- *   o RXT0   = Receiver Timer Interrupt (ring 0)
- *   o TXDW   = Transmit Descriptor Written Back
- *   o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
- *   o RXSEQ  = Receive Sequence Error
- *   o LSC    = Link Status Change
- */
-#define IMS_ENABLE_MASK ( \
-    E1000_IMS_RXT0   |    \
-    E1000_IMS_TXDW   |    \
-    E1000_IMS_RXDMT0 |    \
-    E1000_IMS_RXSEQ  |    \
-    E1000_IMS_LSC)
-
-/* Interrupt Mask Set */
-#define E1000_IMS_TXDW      E1000_ICR_TXDW      /* Transmit desc written back */
-#define E1000_IMS_LSC       E1000_ICR_LSC       /* Link Status Change */
-#define E1000_IMS_RXSEQ     E1000_ICR_RXSEQ     /* Rx sequence error */
-#define E1000_IMS_RXDMT0    E1000_ICR_RXDMT0    /* Rx desc min. threshold */
-#define E1000_IMS_RXT0      E1000_ICR_RXT0      /* Rx timer intr */
-#define E1000_IMS_RXQ0      E1000_ICR_RXQ0      /* Rx Queue 0 Interrupt */
-#define E1000_IMS_RXQ1      E1000_ICR_RXQ1      /* Rx Queue 1 Interrupt */
-#define E1000_IMS_TXQ0      E1000_ICR_TXQ0      /* Tx Queue 0 Interrupt */
-#define E1000_IMS_TXQ1      E1000_ICR_TXQ1      /* Tx Queue 1 Interrupt */
-#define E1000_IMS_OTHER     E1000_ICR_OTHER     /* Other Interrupts */
-
-/* Interrupt Cause Set */
-#define E1000_ICS_LSC       E1000_ICR_LSC       /* Link Status Change */
-#define E1000_ICS_RXSEQ     E1000_ICR_RXSEQ     /* Rx sequence error */
-#define E1000_ICS_RXDMT0    E1000_ICR_RXDMT0    /* Rx desc min. threshold */
-
-/* Transmit Descriptor Control */
-#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */
-#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */
-#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */
-#define E1000_TXDCTL_GRAN    0x01000000 /* TXDCTL Granularity */
-#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
-#define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */
-/* Enable the counting of desc. still to be processed. */
-#define E1000_TXDCTL_COUNT_DESC 0x00400000
-
-/* Flow Control Constants */
-#define FLOW_CONTROL_ADDRESS_LOW  0x00C28001
-#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
-#define FLOW_CONTROL_TYPE         0x8808
-
-/* 802.1q VLAN Packet Size */
-#define E1000_VLAN_FILTER_TBL_SIZE 128  /* VLAN Filter Table (4096 bits) */
-
-/* Receive Address */
-/*
- * Number of high/low register pairs in the RAR. The RAR (Receive Address
- * Registers) holds the directed and multicast addresses that we monitor.
- * Technically, we have 16 spots.  However, we reserve one of these spots
- * (RAR[15]) for our directed address used by controllers with
- * manageability enabled, allowing us room for 15 multicast addresses.
- */
-#define E1000_RAR_ENTRIES     15
-#define E1000_RAH_AV  0x80000000        /* Receive descriptor valid */
-#define E1000_RAL_MAC_ADDR_LEN 4
-#define E1000_RAH_MAC_ADDR_LEN 2
-
-/* Error Codes */
-#define E1000_ERR_NVM      1
-#define E1000_ERR_PHY      2
-#define E1000_ERR_CONFIG   3
-#define E1000_ERR_PARAM    4
-#define E1000_ERR_MAC_INIT 5
-#define E1000_ERR_PHY_TYPE 6
-#define E1000_ERR_RESET   9
-#define E1000_ERR_MASTER_REQUESTS_PENDING 10
-#define E1000_ERR_HOST_INTERFACE_COMMAND 11
-#define E1000_BLK_PHY_RESET   12
-#define E1000_ERR_SWFW_SYNC 13
-#define E1000_NOT_IMPLEMENTED 14
-#define E1000_ERR_INVALID_ARGUMENT  16
-#define E1000_ERR_NO_SPACE          17
-#define E1000_ERR_NVM_PBA_SECTION   18
-
-/* Loop limit on how long we wait for auto-negotiation to complete */
-#define FIBER_LINK_UP_LIMIT               50
-#define COPPER_LINK_UP_LIMIT              10
-#define PHY_AUTO_NEG_LIMIT                45
-#define PHY_FORCE_LIMIT                   20
-/* Number of 100 microseconds we wait for PCI Express master disable */
-#define MASTER_DISABLE_TIMEOUT      800
-/* Number of milliseconds we wait for PHY configuration done after MAC reset */
-#define PHY_CFG_TIMEOUT             100
-/* Number of 2 milliseconds we wait for acquiring MDIO ownership. */
-#define MDIO_OWNERSHIP_TIMEOUT      10
-/* Number of milliseconds for NVM auto read done after MAC reset. */
-#define AUTO_READ_DONE_TIMEOUT      10
-
-/* Flow Control */
-#define E1000_FCRTH_RTH  0x0000FFF8     /* Mask Bits[15:3] for RTH */
-#define E1000_FCRTL_RTL  0x0000FFF8     /* Mask Bits[15:3] for RTL */
-#define E1000_FCRTL_XONE 0x80000000     /* Enable XON frame transmission */
-
-/* Transmit Configuration Word */
-#define E1000_TXCW_FD         0x00000020        /* TXCW full duplex */
-#define E1000_TXCW_PAUSE      0x00000080        /* TXCW sym pause request */
-#define E1000_TXCW_ASM_DIR    0x00000100        /* TXCW astm pause direction */
-#define E1000_TXCW_PAUSE_MASK 0x00000180        /* TXCW pause request mask */
-#define E1000_TXCW_ANE        0x80000000        /* Auto-neg enable */
-
-/* Receive Configuration Word */
-#define E1000_RXCW_CW         0x0000ffff        /* RxConfigWord mask */
-#define E1000_RXCW_IV         0x08000000        /* Receive config invalid */
-#define E1000_RXCW_C          0x20000000        /* Receive config */
-#define E1000_RXCW_SYNCH      0x40000000        /* Receive config synch */
-
-/* PCI Express Control */
-#define E1000_GCR_RXD_NO_SNOOP          0x00000001
-#define E1000_GCR_RXDSCW_NO_SNOOP       0x00000002
-#define E1000_GCR_RXDSCR_NO_SNOOP       0x00000004
-#define E1000_GCR_TXD_NO_SNOOP          0x00000008
-#define E1000_GCR_TXDSCW_NO_SNOOP       0x00000010
-#define E1000_GCR_TXDSCR_NO_SNOOP       0x00000020
-
-#define PCIE_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP         | \
-			   E1000_GCR_RXDSCW_NO_SNOOP      | \
-			   E1000_GCR_RXDSCR_NO_SNOOP      | \
-			   E1000_GCR_TXD_NO_SNOOP         | \
-			   E1000_GCR_TXDSCW_NO_SNOOP      | \
-			   E1000_GCR_TXDSCR_NO_SNOOP)
-
-/* PHY Control Register */
-#define MII_CR_FULL_DUPLEX      0x0100  /* FDX =1, half duplex =0 */
-#define MII_CR_RESTART_AUTO_NEG 0x0200  /* Restart auto negotiation */
-#define MII_CR_POWER_DOWN       0x0800  /* Power down */
-#define MII_CR_AUTO_NEG_EN      0x1000  /* Auto Neg Enable */
-#define MII_CR_LOOPBACK         0x4000  /* 0 = normal, 1 = loopback */
-#define MII_CR_RESET            0x8000  /* 0 = normal, 1 = PHY reset */
-#define MII_CR_SPEED_1000       0x0040
-#define MII_CR_SPEED_100        0x2000
-#define MII_CR_SPEED_10         0x0000
-
-/* PHY Status Register */
-#define MII_SR_LINK_STATUS       0x0004 /* Link Status 1 = link */
-#define MII_SR_AUTONEG_COMPLETE  0x0020 /* Auto Neg Complete */
-
-/* Autoneg Advertisement Register */
-#define NWAY_AR_10T_HD_CAPS      0x0020   /* 10T   Half Duplex Capable */
-#define NWAY_AR_10T_FD_CAPS      0x0040   /* 10T   Full Duplex Capable */
-#define NWAY_AR_100TX_HD_CAPS    0x0080   /* 100TX Half Duplex Capable */
-#define NWAY_AR_100TX_FD_CAPS    0x0100   /* 100TX Full Duplex Capable */
-#define NWAY_AR_PAUSE            0x0400   /* Pause operation desired */
-#define NWAY_AR_ASM_DIR          0x0800   /* Asymmetric Pause Direction bit */
-
-/* Link Partner Ability Register (Base Page) */
-#define NWAY_LPAR_PAUSE          0x0400 /* LP Pause operation desired */
-#define NWAY_LPAR_ASM_DIR        0x0800 /* LP Asymmetric Pause Direction bit */
-
-/* Autoneg Expansion Register */
-#define NWAY_ER_LP_NWAY_CAPS     0x0001 /* LP has Auto Neg Capability */
-
-/* 1000BASE-T Control Register */
-#define CR_1000T_HD_CAPS         0x0100 /* Advertise 1000T HD capability */
-#define CR_1000T_FD_CAPS         0x0200 /* Advertise 1000T FD capability  */
-					/* 0=DTE device */
-#define CR_1000T_MS_VALUE        0x0800 /* 1=Configure PHY as Master */
-					/* 0=Configure PHY as Slave */
-#define CR_1000T_MS_ENABLE       0x1000 /* 1=Master/Slave manual config value */
-					/* 0=Automatic Master/Slave config */
-
-/* 1000BASE-T Status Register */
-#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
-#define SR_1000T_LOCAL_RX_STATUS  0x2000 /* Local receiver OK */
-
-
-/* PHY 1000 MII Register/Bit Definitions */
-/* PHY Registers defined by IEEE */
-#define PHY_CONTROL      0x00 /* Control Register */
-#define PHY_STATUS       0x01 /* Status Register */
-#define PHY_ID1          0x02 /* Phy Id Reg (word 1) */
-#define PHY_ID2          0x03 /* Phy Id Reg (word 2) */
-#define PHY_AUTONEG_ADV  0x04 /* Autoneg Advertisement */
-#define PHY_LP_ABILITY   0x05 /* Link Partner Ability (Base Page) */
-#define PHY_AUTONEG_EXP  0x06 /* Autoneg Expansion Reg */
-#define PHY_1000T_CTRL   0x09 /* 1000Base-T Control Reg */
-#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
-#define PHY_EXT_STATUS   0x0F /* Extended Status Reg */
-
-#define PHY_CONTROL_LB   0x4000 /* PHY Loopback bit */
-
-/* NVM Control */
-#define E1000_EECD_SK        0x00000001 /* NVM Clock */
-#define E1000_EECD_CS        0x00000002 /* NVM Chip Select */
-#define E1000_EECD_DI        0x00000004 /* NVM Data In */
-#define E1000_EECD_DO        0x00000008 /* NVM Data Out */
-#define E1000_EECD_REQ       0x00000040 /* NVM Access Request */
-#define E1000_EECD_GNT       0x00000080 /* NVM Access Grant */
-#define E1000_EECD_PRES      0x00000100 /* NVM Present */
-#define E1000_EECD_SIZE      0x00000200 /* NVM Size (0=64 word 1=256 word) */
-/* NVM Addressing bits based on type (0-small, 1-large) */
-#define E1000_EECD_ADDR_BITS 0x00000400
-#define E1000_NVM_GRANT_ATTEMPTS   1000 /* NVM # attempts to gain grant */
-#define E1000_EECD_AUTO_RD          0x00000200  /* NVM Auto Read done */
-#define E1000_EECD_SIZE_EX_MASK     0x00007800  /* NVM Size */
-#define E1000_EECD_SIZE_EX_SHIFT     11
-#define E1000_EECD_FLUPD     0x00080000 /* Update FLASH */
-#define E1000_EECD_AUPDEN    0x00100000 /* Enable Autonomous FLASH update */
-#define E1000_EECD_SEC1VAL   0x00400000 /* Sector One Valid */
-#define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES)
-
-#define E1000_NVM_RW_REG_DATA   16   /* Offset to data in NVM read/write registers */
-#define E1000_NVM_RW_REG_DONE   2    /* Offset to READ/WRITE done bit */
-#define E1000_NVM_RW_REG_START  1    /* Start operation */
-#define E1000_NVM_RW_ADDR_SHIFT 2    /* Shift to the address bits */
-#define E1000_NVM_POLL_WRITE    1    /* Flag for polling for write complete */
-#define E1000_NVM_POLL_READ     0    /* Flag for polling for read complete */
-#define E1000_FLASH_UPDATES  2000
-
-/* NVM Word Offsets */
-#define NVM_COMPAT                 0x0003
-#define NVM_ID_LED_SETTINGS        0x0004
-#define NVM_INIT_CONTROL2_REG      0x000F
-#define NVM_INIT_CONTROL3_PORT_B   0x0014
-#define NVM_INIT_3GIO_3            0x001A
-#define NVM_INIT_CONTROL3_PORT_A   0x0024
-#define NVM_CFG                    0x0012
-#define NVM_ALT_MAC_ADDR_PTR       0x0037
-#define NVM_CHECKSUM_REG           0x003F
-
-#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask */
-
-#define E1000_NVM_CFG_DONE_PORT_0  0x40000 /* MNG config cycle done */
-#define E1000_NVM_CFG_DONE_PORT_1  0x80000 /* ...for second port */
-
-/* Mask bits for fields in Word 0x0f of the NVM */
-#define NVM_WORD0F_PAUSE_MASK       0x3000
-#define NVM_WORD0F_PAUSE            0x1000
-#define NVM_WORD0F_ASM_DIR          0x2000
-
-/* Mask bits for fields in Word 0x1a of the NVM */
-#define NVM_WORD1A_ASPM_MASK  0x000C
-
-/* Mask bits for fields in Word 0x03 of the EEPROM */
-#define NVM_COMPAT_LOM    0x0800
-
-/* length of string needed to store PBA number */
-#define E1000_PBANUM_LENGTH             11
-
-/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
-#define NVM_SUM                    0xBABA
-
-/* PBA (printed board assembly) number words */
-#define NVM_PBA_OFFSET_0           8
-#define NVM_PBA_OFFSET_1           9
-#define NVM_PBA_PTR_GUARD          0xFAFA
-#define NVM_WORD_SIZE_BASE_SHIFT   6
-
-/* NVM Commands - SPI */
-#define NVM_MAX_RETRY_SPI          5000 /* Max wait of 5ms, for RDY signal */
-#define NVM_READ_OPCODE_SPI        0x03 /* NVM read opcode */
-#define NVM_WRITE_OPCODE_SPI       0x02 /* NVM write 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 */
-
-/* SPI NVM Status Register */
-#define NVM_STATUS_RDY_SPI         0x01
-
-/* Word definitions for ID LED Settings */
-#define ID_LED_RESERVED_0000 0x0000
-#define ID_LED_RESERVED_FFFF 0xFFFF
-#define ID_LED_DEFAULT       ((ID_LED_OFF1_ON2  << 12) | \
-			      (ID_LED_OFF1_OFF2 <<  8) | \
-			      (ID_LED_DEF1_DEF2 <<  4) | \
-			      (ID_LED_DEF1_DEF2))
-#define ID_LED_DEF1_DEF2     0x1
-#define ID_LED_DEF1_ON2      0x2
-#define ID_LED_DEF1_OFF2     0x3
-#define ID_LED_ON1_DEF2      0x4
-#define ID_LED_ON1_ON2       0x5
-#define ID_LED_ON1_OFF2      0x6
-#define ID_LED_OFF1_DEF2     0x7
-#define ID_LED_OFF1_ON2      0x8
-#define ID_LED_OFF1_OFF2     0x9
-
-#define IGP_ACTIVITY_LED_MASK   0xFFFFF0FF
-#define IGP_ACTIVITY_LED_ENABLE 0x0300
-#define IGP_LED3_MODE           0x07000000
-
-/* PCI/PCI-X/PCI-EX Config space */
-#define PCI_HEADER_TYPE_REGISTER     0x0E
-#define PCIE_LINK_STATUS             0x12
-
-#define PCI_HEADER_TYPE_MULTIFUNC    0x80
-#define PCIE_LINK_WIDTH_MASK         0x3F0
-#define PCIE_LINK_WIDTH_SHIFT        4
-
-#define PHY_REVISION_MASK      0xFFFFFFF0
-#define MAX_PHY_REG_ADDRESS    0x1F  /* 5 bit address bus (0-0x1F) */
-#define MAX_PHY_MULTI_PAGE_REG 0xF
-
-/* Bit definitions for valid PHY IDs. */
-/*
- * I = Integrated
- * E = External
- */
-#define M88E1000_E_PHY_ID    0x01410C50
-#define M88E1000_I_PHY_ID    0x01410C30
-#define M88E1011_I_PHY_ID    0x01410C20
-#define IGP01E1000_I_PHY_ID  0x02A80380
-#define M88E1111_I_PHY_ID    0x01410CC0
-#define GG82563_E_PHY_ID     0x01410CA0
-#define IGP03E1000_E_PHY_ID  0x02A80390
-#define IFE_E_PHY_ID         0x02A80330
-#define IFE_PLUS_E_PHY_ID    0x02A80320
-#define IFE_C_E_PHY_ID       0x02A80310
-#define BME1000_E_PHY_ID     0x01410CB0
-#define BME1000_E_PHY_ID_R2  0x01410CB1
-#define I82577_E_PHY_ID      0x01540050
-#define I82578_E_PHY_ID      0x004DD040
-#define I82579_E_PHY_ID      0x01540090
-
-/* M88E1000 Specific Registers */
-#define M88E1000_PHY_SPEC_CTRL     0x10  /* PHY Specific Control Register */
-#define M88E1000_PHY_SPEC_STATUS   0x11  /* PHY Specific Status Register */
-#define M88E1000_EXT_PHY_SPEC_CTRL 0x14  /* Extended PHY Specific Control */
-
-#define M88E1000_PHY_PAGE_SELECT   0x1D  /* Reg 29 for page number setting */
-#define M88E1000_PHY_GEN_CONTROL   0x1E  /* Its meaning depends on reg 29 */
-
-/* M88E1000 PHY Specific Control Register */
-#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */
-#define M88E1000_PSCR_MDI_MANUAL_MODE  0x0000  /* MDI Crossover Mode bits 6:5 */
-					       /* Manual MDI configuration */
-#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020  /* Manual MDIX configuration */
-/* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */
-#define M88E1000_PSCR_AUTO_X_1000T     0x0040
-/* Auto crossover enabled all speeds */
-#define M88E1000_PSCR_AUTO_X_MODE      0x0060
-/*
- * 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold)
- * 0=Normal 10BASE-T Rx Threshold
- */
-#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
-
-/* M88E1000 PHY Specific Status Register */
-#define M88E1000_PSSR_REV_POLARITY       0x0002 /* 1=Polarity reversed */
-#define M88E1000_PSSR_DOWNSHIFT          0x0020 /* 1=Downshifted */
-#define M88E1000_PSSR_MDIX               0x0040 /* 1=MDIX; 0=MDI */
-/* 0=<50M; 1=50-80M; 2=80-110M; 3=110-140M; 4=>140M */
-#define M88E1000_PSSR_CABLE_LENGTH       0x0380
-#define M88E1000_PSSR_SPEED              0xC000 /* Speed, bits 14:15 */
-#define M88E1000_PSSR_1000MBS            0x8000 /* 10=1000Mbs */
-
-#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
-
-/*
- * Number of times we will attempt to autonegotiate before downshifting if we
- * are the master
- */
-#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00
-#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X   0x0000
-/*
- * Number of times we will attempt to autonegotiate before downshifting if we
- * are the slave
- */
-#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK  0x0300
-#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X    0x0100
-#define M88E1000_EPSCR_TX_CLK_25      0x0070 /* 25  MHz TX_CLK */
-
-/* M88EC018 Rev 2 specific DownShift settings */
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK  0x0E00
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X    0x0800
-
-#define I82578_EPSCR_DOWNSHIFT_ENABLE          0x0020
-#define I82578_EPSCR_DOWNSHIFT_COUNTER_MASK    0x001C
-
-/* BME1000 PHY Specific Control Register */
-#define BME1000_PSCR_ENABLE_DOWNSHIFT   0x0800 /* 1 = enable downshift */
-
-
-#define PHY_PAGE_SHIFT 5
-#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \
-                           ((reg) & MAX_PHY_REG_ADDRESS))
-
-/*
- * Bits...
- * 15-5: page
- * 4-0: register offset
- */
-#define GG82563_PAGE_SHIFT        5
-#define GG82563_REG(page, reg)    \
-	(((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS))
-#define GG82563_MIN_ALT_REG       30
-
-/* GG82563 Specific Registers */
-#define GG82563_PHY_SPEC_CTRL           \
-	GG82563_REG(0, 16) /* PHY Specific Control */
-#define GG82563_PHY_PAGE_SELECT         \
-	GG82563_REG(0, 22) /* Page Select */
-#define GG82563_PHY_SPEC_CTRL_2         \
-	GG82563_REG(0, 26) /* PHY Specific Control 2 */
-#define GG82563_PHY_PAGE_SELECT_ALT     \
-	GG82563_REG(0, 29) /* Alternate Page Select */
-
-#define GG82563_PHY_MAC_SPEC_CTRL       \
-	GG82563_REG(2, 21) /* MAC Specific Control Register */
-
-#define GG82563_PHY_DSP_DISTANCE    \
-	GG82563_REG(5, 26) /* DSP Distance */
-
-/* Page 193 - Port Control Registers */
-#define GG82563_PHY_KMRN_MODE_CTRL   \
-	GG82563_REG(193, 16) /* Kumeran Mode Control */
-#define GG82563_PHY_PWR_MGMT_CTRL       \
-	GG82563_REG(193, 20) /* Power Management Control */
-
-/* Page 194 - KMRN Registers */
-#define GG82563_PHY_INBAND_CTRL         \
-	GG82563_REG(194, 18) /* Inband Control */
-
-/* MDI Control */
-#define E1000_MDIC_REG_SHIFT 16
-#define E1000_MDIC_PHY_SHIFT 21
-#define E1000_MDIC_OP_WRITE  0x04000000
-#define E1000_MDIC_OP_READ   0x08000000
-#define E1000_MDIC_READY     0x10000000
-#define E1000_MDIC_ERROR     0x40000000
-
-/* SerDes Control */
-#define E1000_GEN_POLL_TIMEOUT          640
-
-#endif /* _E1000_DEFINES_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/e1000e/e1000.h linux-libre-3.2-gnu/drivers/net/e1000e/e1000.h
--- linux-libre-3.1-gnu/drivers/net/e1000e/e1000.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000e/e1000.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,741 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  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,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-/* Linux PRO/1000 Ethernet Driver main header file */
-
-#ifndef _E1000_H_
-#define _E1000_H_
-
-#include <linux/bitops.h>
-#include <linux/types.h>
-#include <linux/timer.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/pci-aspm.h>
-#include <linux/crc32.h>
-#include <linux/if_vlan.h>
-
-#include "hw.h"
-
-struct e1000_info;
-
-#define e_dbg(format, arg...) \
-	netdev_dbg(hw->adapter->netdev, format, ## arg)
-#define e_err(format, arg...) \
-	netdev_err(adapter->netdev, format, ## arg)
-#define e_info(format, arg...) \
-	netdev_info(adapter->netdev, format, ## arg)
-#define e_warn(format, arg...) \
-	netdev_warn(adapter->netdev, format, ## arg)
-#define e_notice(format, arg...) \
-	netdev_notice(adapter->netdev, format, ## arg)
-
-
-/* Interrupt modes, as used by the IntMode parameter */
-#define E1000E_INT_MODE_LEGACY		0
-#define E1000E_INT_MODE_MSI		1
-#define E1000E_INT_MODE_MSIX		2
-
-/* Tx/Rx descriptor defines */
-#define E1000_DEFAULT_TXD		256
-#define E1000_MAX_TXD			4096
-#define E1000_MIN_TXD			64
-
-#define E1000_DEFAULT_RXD		256
-#define E1000_MAX_RXD			4096
-#define E1000_MIN_RXD			64
-
-#define E1000_MIN_ITR_USECS		10 /* 100000 irq/sec */
-#define E1000_MAX_ITR_USECS		10000 /* 100    irq/sec */
-
-/* Early Receive defines */
-#define E1000_ERT_2048			0x100
-
-#define E1000_FC_PAUSE_TIME		0x0680 /* 858 usec */
-
-/* How many Tx Descriptors do we need to call netif_wake_queue ? */
-/* How many Rx Buffers do we bundle into one write to the hardware ? */
-#define E1000_RX_BUFFER_WRITE		16 /* Must be power of 2 */
-
-#define AUTO_ALL_MODES			0
-#define E1000_EEPROM_APME		0x0400
-
-#define E1000_MNG_VLAN_NONE		(-1)
-
-/* Number of packet split data buffers (not including the header buffer) */
-#define PS_PAGE_BUFFERS			(MAX_PS_BUFFERS - 1)
-
-#define DEFAULT_JUMBO			9234
-
-/* BM/HV Specific Registers */
-#define BM_PORT_CTRL_PAGE                 769
-
-#define PHY_UPPER_SHIFT                   21
-#define BM_PHY_REG(page, reg) \
-	(((reg) & MAX_PHY_REG_ADDRESS) |\
-	 (((page) & 0xFFFF) << PHY_PAGE_SHIFT) |\
-	 (((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)))
-
-/* PHY Wakeup Registers and defines */
-#define BM_PORT_GEN_CFG PHY_REG(BM_PORT_CTRL_PAGE, 17)
-#define BM_RCTL         PHY_REG(BM_WUC_PAGE, 0)
-#define BM_WUC          PHY_REG(BM_WUC_PAGE, 1)
-#define BM_WUFC         PHY_REG(BM_WUC_PAGE, 2)
-#define BM_WUS          PHY_REG(BM_WUC_PAGE, 3)
-#define BM_RAR_L(_i)    (BM_PHY_REG(BM_WUC_PAGE, 16 + ((_i) << 2)))
-#define BM_RAR_M(_i)    (BM_PHY_REG(BM_WUC_PAGE, 17 + ((_i) << 2)))
-#define BM_RAR_H(_i)    (BM_PHY_REG(BM_WUC_PAGE, 18 + ((_i) << 2)))
-#define BM_RAR_CTRL(_i) (BM_PHY_REG(BM_WUC_PAGE, 19 + ((_i) << 2)))
-#define BM_MTA(_i)      (BM_PHY_REG(BM_WUC_PAGE, 128 + ((_i) << 1)))
-
-#define BM_RCTL_UPE           0x0001          /* Unicast Promiscuous Mode */
-#define BM_RCTL_MPE           0x0002          /* Multicast Promiscuous Mode */
-#define BM_RCTL_MO_SHIFT      3               /* Multicast Offset Shift */
-#define BM_RCTL_MO_MASK       (3 << 3)        /* Multicast Offset Mask */
-#define BM_RCTL_BAM           0x0020          /* Broadcast Accept Mode */
-#define BM_RCTL_PMCF          0x0040          /* Pass MAC Control Frames */
-#define BM_RCTL_RFCE          0x0080          /* Rx Flow Control Enable */
-
-#define HV_STATS_PAGE	778
-#define HV_SCC_UPPER	PHY_REG(HV_STATS_PAGE, 16) /* Single Collision Count */
-#define HV_SCC_LOWER	PHY_REG(HV_STATS_PAGE, 17)
-#define HV_ECOL_UPPER	PHY_REG(HV_STATS_PAGE, 18) /* Excessive Coll. Count */
-#define HV_ECOL_LOWER	PHY_REG(HV_STATS_PAGE, 19)
-#define HV_MCC_UPPER	PHY_REG(HV_STATS_PAGE, 20) /* Multiple Coll. Count */
-#define HV_MCC_LOWER	PHY_REG(HV_STATS_PAGE, 21)
-#define HV_LATECOL_UPPER PHY_REG(HV_STATS_PAGE, 23) /* Late Collision Count */
-#define HV_LATECOL_LOWER PHY_REG(HV_STATS_PAGE, 24)
-#define HV_COLC_UPPER	PHY_REG(HV_STATS_PAGE, 25) /* Collision Count */
-#define HV_COLC_LOWER	PHY_REG(HV_STATS_PAGE, 26)
-#define HV_DC_UPPER	PHY_REG(HV_STATS_PAGE, 27) /* Defer Count */
-#define HV_DC_LOWER	PHY_REG(HV_STATS_PAGE, 28)
-#define HV_TNCRS_UPPER	PHY_REG(HV_STATS_PAGE, 29) /* Transmit with no CRS */
-#define HV_TNCRS_LOWER	PHY_REG(HV_STATS_PAGE, 30)
-
-#define E1000_FCRTV_PCH     0x05F40 /* PCH Flow Control Refresh Timer Value */
-
-/* BM PHY Copper Specific Status */
-#define BM_CS_STATUS                      17
-#define BM_CS_STATUS_LINK_UP              0x0400
-#define BM_CS_STATUS_RESOLVED             0x0800
-#define BM_CS_STATUS_SPEED_MASK           0xC000
-#define BM_CS_STATUS_SPEED_1000           0x8000
-
-/* 82577 Mobile Phy Status Register */
-#define HV_M_STATUS                       26
-#define HV_M_STATUS_AUTONEG_COMPLETE      0x1000
-#define HV_M_STATUS_SPEED_MASK            0x0300
-#define HV_M_STATUS_SPEED_1000            0x0200
-#define HV_M_STATUS_LINK_UP               0x0040
-
-#define E1000_ICH_FWSM_PCIM2PCI		0x01000000 /* ME PCIm-to-PCI active */
-#define E1000_ICH_FWSM_PCIM2PCI_COUNT	2000
-
-/* Time to wait before putting the device into D3 if there's no link (in ms). */
-#define LINK_TIMEOUT		100
-
-#define DEFAULT_RDTR			0
-#define DEFAULT_RADV			8
-#define BURST_RDTR			0x20
-#define BURST_RADV			0x20
-
-/*
- * in the case of WTHRESH, it appears at least the 82571/2 hardware
- * writes back 4 descriptors when WTHRESH=5, and 3 descriptors when
- * WTHRESH=4, and since we want 64 bytes at a time written back, set
- * it to 5
- */
-#define E1000_TXDCTL_DMA_BURST_ENABLE                          \
-	(E1000_TXDCTL_GRAN | /* set descriptor granularity */  \
-	 E1000_TXDCTL_COUNT_DESC |                             \
-	 (5 << 16) | /* wthresh must be +1 more than desired */\
-	 (1 << 8)  | /* hthresh */                             \
-	 0x1f)       /* pthresh */
-
-#define E1000_RXDCTL_DMA_BURST_ENABLE                          \
-	(0x01000000 | /* set descriptor granularity */         \
-	 (4 << 16)  | /* set writeback threshold    */         \
-	 (4 << 8)   | /* set prefetch threshold     */         \
-	 0x20)        /* set hthresh                */
-
-#define E1000_TIDV_FPD (1 << 31)
-#define E1000_RDTR_FPD (1 << 31)
-
-enum e1000_boards {
-	board_82571,
-	board_82572,
-	board_82573,
-	board_82574,
-	board_82583,
-	board_80003es2lan,
-	board_ich8lan,
-	board_ich9lan,
-	board_ich10lan,
-	board_pchlan,
-	board_pch2lan,
-};
-
-struct e1000_ps_page {
-	struct page *page;
-	u64 dma; /* must be u64 - written to hw */
-};
-
-/*
- * wrappers around a pointer to a socket buffer,
- * so a DMA handle can be stored along with the buffer
- */
-struct e1000_buffer {
-	dma_addr_t dma;
-	struct sk_buff *skb;
-	union {
-		/* Tx */
-		struct {
-			unsigned long time_stamp;
-			u16 length;
-			u16 next_to_watch;
-			unsigned int segs;
-			unsigned int bytecount;
-			u16 mapped_as_page;
-		};
-		/* Rx */
-		struct {
-			/* arrays of page information for packet split */
-			struct e1000_ps_page *ps_pages;
-			struct page *page;
-		};
-	};
-};
-
-struct e1000_ring {
-	void *desc;			/* pointer to ring memory  */
-	dma_addr_t dma;			/* phys address of ring    */
-	unsigned int size;		/* length of ring in bytes */
-	unsigned int count;		/* number of desc. in ring */
-
-	u16 next_to_use;
-	u16 next_to_clean;
-
-	u16 head;
-	u16 tail;
-
-	/* array of buffer information structs */
-	struct e1000_buffer *buffer_info;
-
-	char name[IFNAMSIZ + 5];
-	u32 ims_val;
-	u32 itr_val;
-	u16 itr_register;
-	int set_itr;
-
-	struct sk_buff *rx_skb_top;
-};
-
-/* PHY register snapshot values */
-struct e1000_phy_regs {
-	u16 bmcr;		/* basic mode control register    */
-	u16 bmsr;		/* basic mode status register     */
-	u16 advertise;		/* auto-negotiation advertisement */
-	u16 lpa;		/* link partner ability register  */
-	u16 expansion;		/* auto-negotiation expansion reg */
-	u16 ctrl1000;		/* 1000BASE-T control register    */
-	u16 stat1000;		/* 1000BASE-T status register     */
-	u16 estatus;		/* extended status register       */
-};
-
-/* board specific private data structure */
-struct e1000_adapter {
-	struct timer_list watchdog_timer;
-	struct timer_list phy_info_timer;
-	struct timer_list blink_timer;
-
-	struct work_struct reset_task;
-	struct work_struct watchdog_task;
-
-	const struct e1000_info *ei;
-
-	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
-	u32 bd_number;
-	u32 rx_buffer_len;
-	u16 mng_vlan_id;
-	u16 link_speed;
-	u16 link_duplex;
-	u16 eeprom_vers;
-
-	/* track device up/down/testing state */
-	unsigned long state;
-
-	/* Interrupt Throttle Rate */
-	u32 itr;
-	u32 itr_setting;
-	u16 tx_itr;
-	u16 rx_itr;
-
-	/*
-	 * Tx
-	 */
-	struct e1000_ring *tx_ring /* One per active queue */
-						____cacheline_aligned_in_smp;
-
-	struct napi_struct napi;
-
-	unsigned int restart_queue;
-	u32 txd_cmd;
-
-	bool detect_tx_hung;
-	u8 tx_timeout_factor;
-
-	u32 tx_int_delay;
-	u32 tx_abs_int_delay;
-
-	unsigned int total_tx_bytes;
-	unsigned int total_tx_packets;
-	unsigned int total_rx_bytes;
-	unsigned int total_rx_packets;
-
-	/* Tx stats */
-	u64 tpt_old;
-	u64 colc_old;
-	u32 gotc;
-	u64 gotc_old;
-	u32 tx_timeout_count;
-	u32 tx_fifo_head;
-	u32 tx_head_addr;
-	u32 tx_fifo_size;
-	u32 tx_dma_failed;
-
-	/*
-	 * Rx
-	 */
-	bool (*clean_rx) (struct e1000_adapter *adapter,
-			  int *work_done, int work_to_do)
-						____cacheline_aligned_in_smp;
-	void (*alloc_rx_buf) (struct e1000_adapter *adapter,
-			      int cleaned_count, gfp_t gfp);
-	struct e1000_ring *rx_ring;
-
-	u32 rx_int_delay;
-	u32 rx_abs_int_delay;
-
-	/* Rx stats */
-	u64 hw_csum_err;
-	u64 hw_csum_good;
-	u64 rx_hdr_split;
-	u32 gorc;
-	u64 gorc_old;
-	u32 alloc_rx_buff_failed;
-	u32 rx_dma_failed;
-
-	unsigned int rx_ps_pages;
-	u16 rx_ps_bsize0;
-	u32 max_frame_size;
-	u32 min_frame_size;
-
-	/* OS defined structs */
-	struct net_device *netdev;
-	struct pci_dev *pdev;
-
-	/* 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;
-
-	/* Snapshot of PHY registers */
-	struct e1000_phy_regs phy_regs;
-
-	struct e1000_ring test_tx_ring;
-	struct e1000_ring test_rx_ring;
-	u32 test_icr;
-
-	u32 msg_enable;
-	unsigned int num_vectors;
-	struct msix_entry *msix_entries;
-	int int_mode;
-	u32 eiac_mask;
-
-	u32 eeprom_wol;
-	u32 wol;
-	u32 pba;
-	u32 max_hw_frame_size;
-
-	bool fc_autoneg;
-
-	unsigned int flags;
-	unsigned int flags2;
-	struct work_struct downshift_task;
-	struct work_struct update_phy_task;
-	struct work_struct print_hang_task;
-
-	bool idle_check;
-	int phy_hang_count;
-};
-
-struct e1000_info {
-	enum e1000_mac_type	mac;
-	unsigned int		flags;
-	unsigned int		flags2;
-	u32			pba;
-	u32			max_hw_frame_size;
-	s32			(*get_variants)(struct e1000_adapter *);
-	struct e1000_mac_operations *mac_ops;
-	struct e1000_phy_operations *phy_ops;
-	struct e1000_nvm_operations *nvm_ops;
-};
-
-/* hardware capability, feature, and workaround flags */
-#define FLAG_HAS_AMT                      (1 << 0)
-#define FLAG_HAS_FLASH                    (1 << 1)
-#define FLAG_HAS_HW_VLAN_FILTER           (1 << 2)
-#define FLAG_HAS_WOL                      (1 << 3)
-#define FLAG_HAS_ERT                      (1 << 4)
-#define FLAG_HAS_CTRLEXT_ON_LOAD          (1 << 5)
-#define FLAG_HAS_SWSM_ON_LOAD             (1 << 6)
-#define FLAG_HAS_JUMBO_FRAMES             (1 << 7)
-#define FLAG_READ_ONLY_NVM                (1 << 8)
-#define FLAG_IS_ICH                       (1 << 9)
-#define FLAG_HAS_MSIX                     (1 << 10)
-#define FLAG_HAS_SMART_POWER_DOWN         (1 << 11)
-#define FLAG_IS_QUAD_PORT_A               (1 << 12)
-#define FLAG_IS_QUAD_PORT                 (1 << 13)
-#define FLAG_TIPG_MEDIUM_FOR_80003ESLAN   (1 << 14)
-#define FLAG_APME_IN_WUC                  (1 << 15)
-#define FLAG_APME_IN_CTRL3                (1 << 16)
-#define FLAG_APME_CHECK_PORT_B            (1 << 17)
-#define FLAG_DISABLE_FC_PAUSE_TIME        (1 << 18)
-#define FLAG_NO_WAKE_UCAST                (1 << 19)
-#define FLAG_MNG_PT_ENABLED               (1 << 20)
-#define FLAG_RESET_OVERWRITES_LAA         (1 << 21)
-#define FLAG_TARC_SPEED_MODE_BIT          (1 << 22)
-#define FLAG_TARC_SET_BIT_ZERO            (1 << 23)
-#define FLAG_RX_NEEDS_RESTART             (1 << 24)
-#define FLAG_LSC_GIG_SPEED_DROP           (1 << 25)
-#define FLAG_SMART_POWER_DOWN             (1 << 26)
-#define FLAG_MSI_ENABLED                  (1 << 27)
-#define FLAG_RX_CSUM_ENABLED              (1 << 28)
-#define FLAG_TSO_FORCE                    (1 << 29)
-#define FLAG_RX_RESTART_NOW               (1 << 30)
-#define FLAG_MSI_TEST_FAILED              (1 << 31)
-
-/* CRC Stripping defines */
-#define FLAG2_CRC_STRIPPING               (1 << 0)
-#define FLAG2_HAS_PHY_WAKEUP              (1 << 1)
-#define FLAG2_IS_DISCARDING               (1 << 2)
-#define FLAG2_DISABLE_ASPM_L1             (1 << 3)
-#define FLAG2_HAS_PHY_STATS               (1 << 4)
-#define FLAG2_HAS_EEE                     (1 << 5)
-#define FLAG2_DMA_BURST                   (1 << 6)
-#define FLAG2_DISABLE_ASPM_L0S            (1 << 7)
-#define FLAG2_DISABLE_AIM                 (1 << 8)
-#define FLAG2_CHECK_PHY_HANG              (1 << 9)
-#define FLAG2_NO_DISABLE_RX               (1 << 10)
-#define FLAG2_PCIM2PCI_ARBITER_WA         (1 << 11)
-
-#define E1000_RX_DESC_PS(R, i)	    \
-	(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
-#define E1000_GET_DESC(R, i, type)	(&(((struct type *)((R).desc))[i]))
-#define E1000_RX_DESC(R, i)		E1000_GET_DESC(R, i, e1000_rx_desc)
-#define E1000_TX_DESC(R, i)		E1000_GET_DESC(R, i, e1000_tx_desc)
-#define E1000_CONTEXT_DESC(R, i)	E1000_GET_DESC(R, i, e1000_context_desc)
-
-enum e1000_state_t {
-	__E1000_TESTING,
-	__E1000_RESETTING,
-	__E1000_DOWN
-};
-
-enum latency_range {
-	lowest_latency = 0,
-	low_latency = 1,
-	bulk_latency = 2,
-	latency_invalid = 255
-};
-
-extern char e1000e_driver_name[];
-extern const char e1000e_driver_version[];
-
-extern void e1000e_check_options(struct e1000_adapter *adapter);
-extern void e1000e_set_ethtool_ops(struct net_device *netdev);
-
-extern int e1000e_up(struct e1000_adapter *adapter);
-extern void e1000e_down(struct e1000_adapter *adapter);
-extern void e1000e_reinit_locked(struct e1000_adapter *adapter);
-extern void e1000e_reset(struct e1000_adapter *adapter);
-extern void e1000e_power_up_phy(struct e1000_adapter *adapter);
-extern int e1000e_setup_rx_resources(struct e1000_adapter *adapter);
-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 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);
-extern void e1000e_release_hw_control(struct e1000_adapter *adapter);
-
-extern unsigned int copybreak;
-
-extern char *e1000e_get_hw_dev_name(struct e1000_hw *hw);
-
-extern struct e1000_info e1000_82571_info;
-extern struct e1000_info e1000_82572_info;
-extern struct e1000_info e1000_82573_info;
-extern struct e1000_info e1000_82574_info;
-extern struct e1000_info e1000_82583_info;
-extern struct e1000_info e1000_ich8_info;
-extern struct e1000_info e1000_ich9_info;
-extern struct e1000_info e1000_ich10_info;
-extern struct e1000_info e1000_pch_info;
-extern struct e1000_info e1000_pch2_info;
-extern struct e1000_info e1000_es2_info;
-
-extern s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
-					 u32 pba_num_size);
-
-extern s32  e1000e_commit_phy(struct e1000_hw *hw);
-
-extern bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw);
-
-extern bool e1000e_get_laa_state_82571(struct e1000_hw *hw);
-extern void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state);
-
-extern void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw);
-extern void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
-						 bool state);
-extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
-extern void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
-extern void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw);
-extern void e1000_resume_workarounds_pchlan(struct e1000_hw *hw);
-extern s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
-extern s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable);
-extern void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw);
-
-extern s32 e1000e_check_for_copper_link(struct e1000_hw *hw);
-extern s32 e1000e_check_for_fiber_link(struct e1000_hw *hw);
-extern s32 e1000e_check_for_serdes_link(struct e1000_hw *hw);
-extern s32 e1000e_setup_led_generic(struct e1000_hw *hw);
-extern s32 e1000e_cleanup_led_generic(struct e1000_hw *hw);
-extern s32 e1000e_led_on_generic(struct e1000_hw *hw);
-extern s32 e1000e_led_off_generic(struct e1000_hw *hw);
-extern s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw);
-extern void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw);
-extern void e1000_set_lan_id_single_port(struct e1000_hw *hw);
-extern s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *duplex);
-extern s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, u16 *speed, u16 *duplex);
-extern s32 e1000e_disable_pcie_master(struct e1000_hw *hw);
-extern s32 e1000e_get_auto_rd_done(struct e1000_hw *hw);
-extern s32 e1000e_id_led_init(struct e1000_hw *hw);
-extern void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw);
-extern s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw);
-extern s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw);
-extern s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw);
-extern s32 e1000e_setup_link(struct e1000_hw *hw);
-extern void e1000_clear_vfta_generic(struct e1000_hw *hw);
-extern void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count);
-extern void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,
-					       u8 *mc_addr_list,
-					       u32 mc_addr_count);
-extern void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
-extern s32 e1000e_set_fc_watermarks(struct e1000_hw *hw);
-extern void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop);
-extern s32 e1000e_get_hw_semaphore(struct e1000_hw *hw);
-extern s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data);
-extern void e1000e_config_collision_dist(struct e1000_hw *hw);
-extern s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw);
-extern s32 e1000e_force_mac_fc(struct e1000_hw *hw);
-extern s32 e1000e_blink_led_generic(struct e1000_hw *hw);
-extern void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value);
-extern s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw);
-extern void e1000e_reset_adaptive(struct e1000_hw *hw);
-extern void e1000e_update_adaptive(struct e1000_hw *hw);
-
-extern s32 e1000e_setup_copper_link(struct e1000_hw *hw);
-extern s32 e1000e_get_phy_id(struct e1000_hw *hw);
-extern void e1000e_put_hw_semaphore(struct e1000_hw *hw);
-extern s32 e1000e_check_reset_block_generic(struct e1000_hw *hw);
-extern s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw);
-extern s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw);
-extern s32 e1000e_get_phy_info_igp(struct e1000_hw *hw);
-extern s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page);
-extern s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
-extern s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset,
-                                          u16 *data);
-extern s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw);
-extern s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active);
-extern s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data);
-extern s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset,
-                                           u16 data);
-extern s32 e1000e_phy_sw_reset(struct e1000_hw *hw);
-extern s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw);
-extern s32 e1000e_get_cfg_done(struct e1000_hw *hw);
-extern s32 e1000e_get_cable_length_m88(struct e1000_hw *hw);
-extern s32 e1000e_get_phy_info_m88(struct e1000_hw *hw);
-extern s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data);
-extern s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data);
-extern s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw);
-extern enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id);
-extern s32 e1000e_determine_phy_address(struct e1000_hw *hw);
-extern s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data);
-extern s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data);
-extern s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw,
-						 u16 *phy_reg);
-extern s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw,
-						  u16 *phy_reg);
-extern s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data);
-extern s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data);
-extern void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl);
-extern s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data);
-extern s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset,
-                                        u16 data);
-extern s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data);
-extern s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset,
-                                       u16 *data);
-extern s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
-			       u32 usec_interval, bool *success);
-extern s32 e1000e_phy_reset_dsp(struct e1000_hw *hw);
-extern void e1000_power_up_phy_copper(struct e1000_hw *hw);
-extern void e1000_power_down_phy_copper(struct e1000_hw *hw);
-extern s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
-extern s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
-extern s32 e1000e_check_downshift(struct e1000_hw *hw);
-extern s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data);
-extern s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset,
-                                        u16 *data);
-extern s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset,
-				      u16 *data);
-extern s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data);
-extern s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset,
-                                         u16 data);
-extern s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset,
-				       u16 data);
-extern s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw);
-extern s32 e1000_copper_link_setup_82577(struct e1000_hw *hw);
-extern s32 e1000_check_polarity_82577(struct e1000_hw *hw);
-extern s32 e1000_get_phy_info_82577(struct e1000_hw *hw);
-extern s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw);
-extern s32 e1000_get_cable_length_82577(struct e1000_hw *hw);
-
-extern s32 e1000_check_polarity_m88(struct e1000_hw *hw);
-extern s32 e1000_get_phy_info_ife(struct e1000_hw *hw);
-extern s32 e1000_check_polarity_ife(struct e1000_hw *hw);
-extern s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw);
-extern s32 e1000_check_polarity_igp(struct e1000_hw *hw);
-extern bool e1000_check_phy_82574(struct e1000_hw *hw);
-
-static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw)
-{
-	return hw->phy.ops.reset(hw);
-}
-
-static inline s32 e1000_check_reset_block(struct e1000_hw *hw)
-{
-	return hw->phy.ops.check_reset_block(hw);
-}
-
-static inline s32 e1e_rphy(struct e1000_hw *hw, u32 offset, u16 *data)
-{
-	return hw->phy.ops.read_reg(hw, offset, data);
-}
-
-static inline s32 e1e_wphy(struct e1000_hw *hw, u32 offset, u16 data)
-{
-	return hw->phy.ops.write_reg(hw, offset, data);
-}
-
-static inline s32 e1000_get_cable_length(struct e1000_hw *hw)
-{
-	return hw->phy.ops.get_cable_length(hw);
-}
-
-extern s32 e1000e_acquire_nvm(struct e1000_hw *hw);
-extern s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
-extern s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw);
-extern s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg);
-extern s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
-extern s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw);
-extern void e1000e_release_nvm(struct e1000_hw *hw);
-extern void e1000e_reload_nvm(struct e1000_hw *hw);
-extern s32 e1000_read_mac_addr_generic(struct e1000_hw *hw);
-
-static inline s32 e1000e_read_mac_addr(struct e1000_hw *hw)
-{
-	if (hw->mac.ops.read_mac_addr)
-		return hw->mac.ops.read_mac_addr(hw);
-
-	return e1000_read_mac_addr_generic(hw);
-}
-
-static inline s32 e1000_validate_nvm_checksum(struct e1000_hw *hw)
-{
-	return hw->nvm.ops.validate(hw);
-}
-
-static inline s32 e1000e_update_nvm_checksum(struct e1000_hw *hw)
-{
-	return hw->nvm.ops.update(hw);
-}
-
-static inline s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
-{
-	return hw->nvm.ops.read(hw, offset, words, data);
-}
-
-static inline s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
-{
-	return hw->nvm.ops.write(hw, offset, words, data);
-}
-
-static inline s32 e1000_get_phy_info(struct e1000_hw *hw)
-{
-	return hw->phy.ops.get_info(hw);
-}
-
-static inline s32 e1000e_check_mng_mode(struct e1000_hw *hw)
-{
-	return hw->mac.ops.check_mng_mode(hw);
-}
-
-extern bool e1000e_check_mng_mode_generic(struct e1000_hw *hw);
-extern bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw);
-extern s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length);
-
-static inline u32 __er32(struct e1000_hw *hw, unsigned long reg)
-{
-	return readl(hw->hw_addr + reg);
-}
-
-static inline void __ew32(struct e1000_hw *hw, unsigned long reg, u32 val)
-{
-	writel(val, hw->hw_addr + reg);
-}
-
-#endif /* _E1000_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/e1000e/es2lan.c linux-libre-3.2-gnu/drivers/net/e1000e/es2lan.c
--- linux-libre-3.1-gnu/drivers/net/e1000e/es2lan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000e/es2lan.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1516 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  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,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-/*
- * 80003ES2LAN Gigabit Ethernet Controller (Copper)
- * 80003ES2LAN Gigabit Ethernet Controller (Serdes)
- */
-
-#include "e1000.h"
-
-#define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL	 0x00
-#define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL	 0x02
-#define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL	 0x10
-#define E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE	 0x1F
-
-#define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS	 0x0008
-#define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS	 0x0800
-#define E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING	 0x0010
-
-#define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004
-#define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT	 0x0000
-#define E1000_KMRNCTRLSTA_OPMODE_E_IDLE		 0x2000
-
-#define E1000_KMRNCTRLSTA_OPMODE_MASK		 0x000C
-#define E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO	 0x0004
-
-#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */
-#define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN	 0x00010000
-
-#define DEFAULT_TIPG_IPGT_1000_80003ES2LAN	 0x8
-#define DEFAULT_TIPG_IPGT_10_100_80003ES2LAN	 0x9
-
-/* GG82563 PHY Specific Status Register (Page 0, Register 16 */
-#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE	 0x0002 /* 1=Reversal Disab. */
-#define GG82563_PSCR_CROSSOVER_MODE_MASK	 0x0060
-#define GG82563_PSCR_CROSSOVER_MODE_MDI		 0x0000 /* 00=Manual MDI */
-#define GG82563_PSCR_CROSSOVER_MODE_MDIX	 0x0020 /* 01=Manual MDIX */
-#define GG82563_PSCR_CROSSOVER_MODE_AUTO	 0x0060 /* 11=Auto crossover */
-
-/* PHY Specific Control Register 2 (Page 0, Register 26) */
-#define GG82563_PSCR2_REVERSE_AUTO_NEG		 0x2000
-						/* 1=Reverse Auto-Negotiation */
-
-/* MAC Specific Control Register (Page 2, Register 21) */
-/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */
-#define GG82563_MSCR_TX_CLK_MASK		 0x0007
-#define GG82563_MSCR_TX_CLK_10MBPS_2_5		 0x0004
-#define GG82563_MSCR_TX_CLK_100MBPS_25		 0x0005
-#define GG82563_MSCR_TX_CLK_1000MBPS_25		 0x0007
-
-#define GG82563_MSCR_ASSERT_CRS_ON_TX		 0x0010 /* 1=Assert */
-
-/* DSP Distance Register (Page 5, Register 26) */
-#define GG82563_DSPD_CABLE_LENGTH		 0x0007 /* 0 = <50M
-							   1 = 50-80M
-							   2 = 80-110M
-							   3 = 110-140M
-							   4 = >140M */
-
-/* Kumeran Mode Control Register (Page 193, Register 16) */
-#define GG82563_KMCR_PASS_FALSE_CARRIER		 0x0800
-
-/* Max number of times Kumeran read/write should be validated */
-#define GG82563_MAX_KMRN_RETRY  0x5
-
-/* Power Management Control Register (Page 193, Register 20) */
-#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE	 0x0001
-					   /* 1=Enable SERDES Electrical Idle */
-
-/* In-Band Control Register (Page 194, Register 18) */
-#define GG82563_ICR_DIS_PADDING			 0x0010 /* Disable Padding */
-
-/*
- * A table for the GG82563 cable length where the range is defined
- * with a lower bound at "index" and the upper bound at
- * "index + 5".
- */
-static const u16 e1000_gg82563_cable_length_table[] = {
-	 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF };
-#define GG82563_CABLE_LENGTH_TABLE_SIZE \
-		ARRAY_SIZE(e1000_gg82563_cable_length_table)
-
-static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw);
-static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask);
-static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask);
-static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw);
-static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw);
-static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw);
-static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex);
-static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw);
-static s32  e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
-                                            u16 *data);
-static s32  e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
-                                             u16 data);
-static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw);
-
-/**
- *  e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs.
- *  @hw: pointer to the HW structure
- **/
-static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-
-	if (hw->phy.media_type != e1000_media_type_copper) {
-		phy->type	= e1000_phy_none;
-		return 0;
-	} else {
-		phy->ops.power_up = e1000_power_up_phy_copper;
-		phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan;
-	}
-
-	phy->addr		= 1;
-	phy->autoneg_mask	= AUTONEG_ADVERTISE_SPEED_DEFAULT;
-	phy->reset_delay_us      = 100;
-	phy->type		= e1000_phy_gg82563;
-
-	/* This can only be done after all function pointers are setup. */
-	ret_val = e1000e_get_phy_id(hw);
-
-	/* Verify phy id */
-	if (phy->id != GG82563_E_PHY_ID)
-		return -E1000_ERR_PHY;
-
-	return ret_val;
-}
-
-/**
- *  e1000_init_nvm_params_80003es2lan - Init ESB2 NVM func ptrs.
- *  @hw: pointer to the HW structure
- **/
-static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
-{
-	struct e1000_nvm_info *nvm = &hw->nvm;
-	u32 eecd = er32(EECD);
-	u16 size;
-
-	nvm->opcode_bits	= 8;
-	nvm->delay_usec	 = 1;
-	switch (nvm->override) {
-	case e1000_nvm_override_spi_large:
-		nvm->page_size    = 32;
-		nvm->address_bits = 16;
-		break;
-	case e1000_nvm_override_spi_small:
-		nvm->page_size    = 8;
-		nvm->address_bits = 8;
-		break;
-	default:
-		nvm->page_size    = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
-		nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8;
-		break;
-	}
-
-	nvm->type = e1000_nvm_eeprom_spi;
-
-	size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
-			  E1000_EECD_SIZE_EX_SHIFT);
-
-	/*
-	 * Added to a constant, "size" becomes the left-shift value
-	 * for setting word_size.
-	 */
-	size += NVM_WORD_SIZE_BASE_SHIFT;
-
-	/* EEPROM access above 16k is unsupported */
-	if (size > 14)
-		size = 14;
-	nvm->word_size	= 1 << size;
-
-	return 0;
-}
-
-/**
- *  e1000_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs.
- *  @hw: pointer to the HW structure
- **/
-static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_mac_info *mac = &hw->mac;
-	struct e1000_mac_operations *func = &mac->ops;
-
-	/* Set media type */
-	switch (adapter->pdev->device) {
-	case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
-		hw->phy.media_type = e1000_media_type_internal_serdes;
-		break;
-	default:
-		hw->phy.media_type = e1000_media_type_copper;
-		break;
-	}
-
-	/* Set mta register count */
-	mac->mta_reg_count = 128;
-	/* Set rar entry count */
-	mac->rar_entry_count = E1000_RAR_ENTRIES;
-	/* FWSM register */
-	mac->has_fwsm = true;
-	/* ARC supported; valid only if manageability features are enabled. */
-	mac->arc_subsystem_valid =
-	        (er32(FWSM) & E1000_FWSM_MODE_MASK)
-	                ? true : false;
-	/* Adaptive IFS not supported */
-	mac->adaptive_ifs = false;
-
-	/* check for link */
-	switch (hw->phy.media_type) {
-	case e1000_media_type_copper:
-		func->setup_physical_interface = e1000_setup_copper_link_80003es2lan;
-		func->check_for_link = e1000e_check_for_copper_link;
-		break;
-	case e1000_media_type_fiber:
-		func->setup_physical_interface = e1000e_setup_fiber_serdes_link;
-		func->check_for_link = e1000e_check_for_fiber_link;
-		break;
-	case e1000_media_type_internal_serdes:
-		func->setup_physical_interface = e1000e_setup_fiber_serdes_link;
-		func->check_for_link = e1000e_check_for_serdes_link;
-		break;
-	default:
-		return -E1000_ERR_CONFIG;
-		break;
-	}
-
-	/* set lan id for port to determine which phy lock to use */
-	hw->mac.ops.set_lan_id(hw);
-
-	return 0;
-}
-
-static s32 e1000_get_variants_80003es2lan(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	s32 rc;
-
-	rc = e1000_init_mac_params_80003es2lan(adapter);
-	if (rc)
-		return rc;
-
-	rc = e1000_init_nvm_params_80003es2lan(hw);
-	if (rc)
-		return rc;
-
-	rc = e1000_init_phy_params_80003es2lan(hw);
-	if (rc)
-		return rc;
-
-	return 0;
-}
-
-/**
- *  e1000_acquire_phy_80003es2lan - Acquire rights to access PHY
- *  @hw: pointer to the HW structure
- *
- *  A wrapper to acquire access rights to the correct PHY.
- **/
-static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw)
-{
-	u16 mask;
-
-	mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
-	return e1000_acquire_swfw_sync_80003es2lan(hw, mask);
-}
-
-/**
- *  e1000_release_phy_80003es2lan - Release rights to access PHY
- *  @hw: pointer to the HW structure
- *
- *  A wrapper to release access rights to the correct PHY.
- **/
-static void e1000_release_phy_80003es2lan(struct e1000_hw *hw)
-{
-	u16 mask;
-
-	mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
-	e1000_release_swfw_sync_80003es2lan(hw, mask);
-}
-
-/**
- *  e1000_acquire_mac_csr_80003es2lan - Acquire rights to access Kumeran register
- *  @hw: pointer to the HW structure
- *
- *  Acquire the semaphore to access the Kumeran interface.
- *
- **/
-static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw)
-{
-	u16 mask;
-
-	mask = E1000_SWFW_CSR_SM;
-
-	return e1000_acquire_swfw_sync_80003es2lan(hw, mask);
-}
-
-/**
- *  e1000_release_mac_csr_80003es2lan - Release rights to access Kumeran Register
- *  @hw: pointer to the HW structure
- *
- *  Release the semaphore used to access the Kumeran interface
- **/
-static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw)
-{
-	u16 mask;
-
-	mask = E1000_SWFW_CSR_SM;
-
-	e1000_release_swfw_sync_80003es2lan(hw, mask);
-}
-
-/**
- *  e1000_acquire_nvm_80003es2lan - Acquire rights to access NVM
- *  @hw: pointer to the HW structure
- *
- *  Acquire the semaphore to access the EEPROM.
- **/
-static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw)
-{
-	s32 ret_val;
-
-	ret_val = e1000_acquire_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = e1000e_acquire_nvm(hw);
-
-	if (ret_val)
-		e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM);
-
-	return ret_val;
-}
-
-/**
- *  e1000_release_nvm_80003es2lan - Relinquish rights to access NVM
- *  @hw: pointer to the HW structure
- *
- *  Release the semaphore used to access the EEPROM.
- **/
-static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw)
-{
-	e1000e_release_nvm(hw);
-	e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM);
-}
-
-/**
- *  e1000_acquire_swfw_sync_80003es2lan - Acquire SW/FW semaphore
- *  @hw: pointer to the HW structure
- *  @mask: specifies which semaphore to acquire
- *
- *  Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
- *  will also specify which port we're acquiring the lock for.
- **/
-static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
-{
-	u32 swfw_sync;
-	u32 swmask = mask;
-	u32 fwmask = mask << 16;
-	s32 i = 0;
-	s32 timeout = 50;
-
-	while (i < timeout) {
-		if (e1000e_get_hw_semaphore(hw))
-			return -E1000_ERR_SWFW_SYNC;
-
-		swfw_sync = er32(SW_FW_SYNC);
-		if (!(swfw_sync & (fwmask | swmask)))
-			break;
-
-		/*
-		 * Firmware currently using resource (fwmask)
-		 * or other software thread using resource (swmask)
-		 */
-		e1000e_put_hw_semaphore(hw);
-		mdelay(5);
-		i++;
-	}
-
-	if (i == timeout) {
-		e_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n");
-		return -E1000_ERR_SWFW_SYNC;
-	}
-
-	swfw_sync |= swmask;
-	ew32(SW_FW_SYNC, swfw_sync);
-
-	e1000e_put_hw_semaphore(hw);
-
-	return 0;
-}
-
-/**
- *  e1000_release_swfw_sync_80003es2lan - Release SW/FW semaphore
- *  @hw: pointer to the HW structure
- *  @mask: specifies which semaphore to acquire
- *
- *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask
- *  will also specify which port we're releasing the lock for.
- **/
-static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
-{
-	u32 swfw_sync;
-
-	while (e1000e_get_hw_semaphore(hw) != 0)
-		; /* Empty */
-
-	swfw_sync = er32(SW_FW_SYNC);
-	swfw_sync &= ~mask;
-	ew32(SW_FW_SYNC, swfw_sync);
-
-	e1000e_put_hw_semaphore(hw);
-}
-
-/**
- *  e1000_read_phy_reg_gg82563_80003es2lan - Read GG82563 PHY register
- *  @hw: pointer to the HW structure
- *  @offset: offset of the register to read
- *  @data: pointer to the data returned from the operation
- *
- *  Read the GG82563 PHY register.
- **/
-static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
-						  u32 offset, u16 *data)
-{
-	s32 ret_val;
-	u32 page_select;
-	u16 temp;
-
-	ret_val = e1000_acquire_phy_80003es2lan(hw);
-	if (ret_val)
-		return ret_val;
-
-	/* Select Configuration Page */
-	if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
-		page_select = GG82563_PHY_PAGE_SELECT;
-	} else {
-		/*
-		 * Use Alternative Page Select register to access
-		 * registers 30 and 31
-		 */
-		page_select = GG82563_PHY_PAGE_SELECT_ALT;
-	}
-
-	temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
-	ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp);
-	if (ret_val) {
-		e1000_release_phy_80003es2lan(hw);
-		return ret_val;
-	}
-
-	if (hw->dev_spec.e80003es2lan.mdic_wa_enable == true) {
-		/*
-		 * The "ready" bit in the MDIC register may be incorrectly set
-		 * before the device has completed the "Page Select" MDI
-		 * transaction.  So we wait 200us after each MDI command...
-		 */
-		udelay(200);
-
-		/* ...and verify the command was successful. */
-		ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
-
-		if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
-			ret_val = -E1000_ERR_PHY;
-			e1000_release_phy_80003es2lan(hw);
-			return ret_val;
-		}
-
-		udelay(200);
-
-		ret_val = e1000e_read_phy_reg_mdic(hw,
-		                                  MAX_PHY_REG_ADDRESS & offset,
-		                                  data);
-
-		udelay(200);
-	} else {
-		ret_val = e1000e_read_phy_reg_mdic(hw,
-		                                  MAX_PHY_REG_ADDRESS & offset,
-		                                  data);
-	}
-
-	e1000_release_phy_80003es2lan(hw);
-
-	return ret_val;
-}
-
-/**
- *  e1000_write_phy_reg_gg82563_80003es2lan - Write GG82563 PHY register
- *  @hw: pointer to the HW structure
- *  @offset: offset of the register to read
- *  @data: value to write to the register
- *
- *  Write to the GG82563 PHY register.
- **/
-static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
-						   u32 offset, u16 data)
-{
-	s32 ret_val;
-	u32 page_select;
-	u16 temp;
-
-	ret_val = e1000_acquire_phy_80003es2lan(hw);
-	if (ret_val)
-		return ret_val;
-
-	/* Select Configuration Page */
-	if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
-		page_select = GG82563_PHY_PAGE_SELECT;
-	} else {
-		/*
-		 * Use Alternative Page Select register to access
-		 * registers 30 and 31
-		 */
-		page_select = GG82563_PHY_PAGE_SELECT_ALT;
-	}
-
-	temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
-	ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp);
-	if (ret_val) {
-		e1000_release_phy_80003es2lan(hw);
-		return ret_val;
-	}
-
-	if (hw->dev_spec.e80003es2lan.mdic_wa_enable == true) {
-		/*
-		 * The "ready" bit in the MDIC register may be incorrectly set
-		 * before the device has completed the "Page Select" MDI
-		 * transaction.  So we wait 200us after each MDI command...
-		 */
-		udelay(200);
-
-		/* ...and verify the command was successful. */
-		ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
-
-		if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
-			e1000_release_phy_80003es2lan(hw);
-			return -E1000_ERR_PHY;
-		}
-
-		udelay(200);
-
-		ret_val = e1000e_write_phy_reg_mdic(hw,
-		                                  MAX_PHY_REG_ADDRESS & offset,
-		                                  data);
-
-		udelay(200);
-	} else {
-		ret_val = e1000e_write_phy_reg_mdic(hw,
-		                                  MAX_PHY_REG_ADDRESS & offset,
-		                                  data);
-	}
-
-	e1000_release_phy_80003es2lan(hw);
-
-	return ret_val;
-}
-
-/**
- *  e1000_write_nvm_80003es2lan - Write to ESB2 NVM
- *  @hw: pointer to the HW structure
- *  @offset: offset of the register to read
- *  @words: number of words to write
- *  @data: buffer of data to write to the NVM
- *
- *  Write "words" of data to the ESB2 NVM.
- **/
-static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
-				       u16 words, u16 *data)
-{
-	return e1000e_write_nvm_spi(hw, offset, words, data);
-}
-
-/**
- *  e1000_get_cfg_done_80003es2lan - Wait for configuration to complete
- *  @hw: pointer to the HW structure
- *
- *  Wait a specific amount of time for manageability processes to complete.
- *  This is a function pointer entry point called by the phy module.
- **/
-static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw)
-{
-	s32 timeout = PHY_CFG_TIMEOUT;
-	u32 mask = E1000_NVM_CFG_DONE_PORT_0;
-
-	if (hw->bus.func == 1)
-		mask = E1000_NVM_CFG_DONE_PORT_1;
-
-	while (timeout) {
-		if (er32(EEMNGCTL) & mask)
-			break;
-		usleep_range(1000, 2000);
-		timeout--;
-	}
-	if (!timeout) {
-		e_dbg("MNG configuration cycle has not completed.\n");
-		return -E1000_ERR_RESET;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_phy_force_speed_duplex_80003es2lan - Force PHY speed and duplex
- *  @hw: pointer to the HW structure
- *
- *  Force the speed and duplex settings onto the PHY.  This is a
- *  function pointer entry point called by the phy module.
- **/
-static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 phy_data;
-	bool link;
-
-	/*
-	 * Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
-	 * forced whenever speed and duplex are forced.
-	 */
-	ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_AUTO;
-	ret_val = e1e_wphy(hw, GG82563_PHY_SPEC_CTRL, phy_data);
-	if (ret_val)
-		return ret_val;
-
-	e_dbg("GG82563 PSCR: %X\n", phy_data);
-
-	ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	e1000e_phy_force_speed_duplex_setup(hw, &phy_data);
-
-	/* Reset the phy to commit changes. */
-	phy_data |= MII_CR_RESET;
-
-	ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data);
-	if (ret_val)
-		return ret_val;
-
-	udelay(1);
-
-	if (hw->phy.autoneg_wait_to_complete) {
-		e_dbg("Waiting for forced speed/duplex link "
-			 "on GG82563 phy.\n");
-
-		ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
-						     100000, &link);
-		if (ret_val)
-			return ret_val;
-
-		if (!link) {
-			/*
-			 * We didn't get link.
-			 * Reset the DSP and cross our fingers.
-			 */
-			ret_val = e1000e_phy_reset_dsp(hw);
-			if (ret_val)
-				return ret_val;
-		}
-
-		/* Try once more */
-		ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
-						     100000, &link);
-		if (ret_val)
-			return ret_val;
-	}
-
-	ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	/*
-	 * Resetting the phy means we need to verify the TX_CLK corresponds
-	 * to the link speed.  10Mbps -> 2.5MHz, else 25MHz.
-	 */
-	phy_data &= ~GG82563_MSCR_TX_CLK_MASK;
-	if (hw->mac.forced_speed_duplex & E1000_ALL_10_SPEED)
-		phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5;
-	else
-		phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25;
-
-	/*
-	 * In addition, we must re-enable CRS on Tx for both half and full
-	 * duplex.
-	 */
-	phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
-	ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data);
-
-	return ret_val;
-}
-
-/**
- *  e1000_get_cable_length_80003es2lan - Set approximate cable length
- *  @hw: pointer to the HW structure
- *
- *  Find the approximate cable length as measured by the GG82563 PHY.
- *  This is a function pointer entry point called by the phy module.
- **/
-static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val = 0;
-	u16 phy_data, index;
-
-	ret_val = e1e_rphy(hw, GG82563_PHY_DSP_DISTANCE, &phy_data);
-	if (ret_val)
-		goto out;
-
-	index = phy_data & GG82563_DSPD_CABLE_LENGTH;
-
-	if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5) {
-		ret_val = -E1000_ERR_PHY;
-		goto out;
-	}
-
-	phy->min_cable_length = e1000_gg82563_cable_length_table[index];
-	phy->max_cable_length = e1000_gg82563_cable_length_table[index + 5];
-
-	phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_get_link_up_info_80003es2lan - Report speed and duplex
- *  @hw: pointer to the HW structure
- *  @speed: pointer to speed buffer
- *  @duplex: pointer to duplex buffer
- *
- *  Retrieve the current speed and duplex configuration.
- **/
-static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
-					      u16 *duplex)
-{
-	s32 ret_val;
-
-	if (hw->phy.media_type == e1000_media_type_copper) {
-		ret_val = e1000e_get_speed_and_duplex_copper(hw,
-								    speed,
-								    duplex);
-		hw->phy.ops.cfg_on_link_up(hw);
-	} else {
-		ret_val = e1000e_get_speed_and_duplex_fiber_serdes(hw,
-								  speed,
-								  duplex);
-	}
-
-	return ret_val;
-}
-
-/**
- *  e1000_reset_hw_80003es2lan - Reset the ESB2 controller
- *  @hw: pointer to the HW structure
- *
- *  Perform a global reset to the ESB2 controller.
- **/
-static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
-{
-	u32 ctrl;
-	s32 ret_val;
-
-	/*
-	 * Prevent the PCI-E bus from sticking if there is no TLP connection
-	 * on the last TLP read/write transaction when MAC is reset.
-	 */
-	ret_val = e1000e_disable_pcie_master(hw);
-	if (ret_val)
-		e_dbg("PCI-E Master disable polling has failed.\n");
-
-	e_dbg("Masking off all interrupts\n");
-	ew32(IMC, 0xffffffff);
-
-	ew32(RCTL, 0);
-	ew32(TCTL, E1000_TCTL_PSP);
-	e1e_flush();
-
-	usleep_range(10000, 20000);
-
-	ctrl = er32(CTRL);
-
-	ret_val = e1000_acquire_phy_80003es2lan(hw);
-	e_dbg("Issuing a global reset to MAC\n");
-	ew32(CTRL, ctrl | E1000_CTRL_RST);
-	e1000_release_phy_80003es2lan(hw);
-
-	ret_val = e1000e_get_auto_rd_done(hw);
-	if (ret_val)
-		/* We don't want to continue accessing MAC registers. */
-		return ret_val;
-
-	/* Clear any pending interrupt events. */
-	ew32(IMC, 0xffffffff);
-	er32(ICR);
-
-	ret_val = e1000_check_alt_mac_addr_generic(hw);
-
-	return ret_val;
-}
-
-/**
- *  e1000_init_hw_80003es2lan - Initialize the ESB2 controller
- *  @hw: pointer to the HW structure
- *
- *  Initialize the hw bits, LED, VFTA, MTA, link and hw counters.
- **/
-static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-	u32 reg_data;
-	s32 ret_val;
-	u16 kum_reg_data;
-	u16 i;
-
-	e1000_initialize_hw_bits_80003es2lan(hw);
-
-	/* Initialize identification LED */
-	ret_val = e1000e_id_led_init(hw);
-	if (ret_val)
-		e_dbg("Error initializing identification LED\n");
-		/* This is not fatal and we should not stop init due to this */
-
-	/* Disabling VLAN filtering */
-	e_dbg("Initializing the IEEE VLAN\n");
-	mac->ops.clear_vfta(hw);
-
-	/* Setup the receive address. */
-	e1000e_init_rx_addrs(hw, mac->rar_entry_count);
-
-	/* Zero out the Multicast HASH table */
-	e_dbg("Zeroing the MTA\n");
-	for (i = 0; i < mac->mta_reg_count; i++)
-		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
-
-	/* Setup link and flow control */
-	ret_val = e1000e_setup_link(hw);
-
-	/* Disable IBIST slave mode (far-end loopback) */
-	e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
-					&kum_reg_data);
-	kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
-	e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
-					 kum_reg_data);
-
-	/* Set the transmit descriptor write-back policy */
-	reg_data = er32(TXDCTL(0));
-	reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
-		   E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
-	ew32(TXDCTL(0), reg_data);
-
-	/* ...for both queues. */
-	reg_data = er32(TXDCTL(1));
-	reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
-		   E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
-	ew32(TXDCTL(1), reg_data);
-
-	/* Enable retransmit on late collisions */
-	reg_data = er32(TCTL);
-	reg_data |= E1000_TCTL_RTLC;
-	ew32(TCTL, reg_data);
-
-	/* Configure Gigabit Carry Extend Padding */
-	reg_data = er32(TCTL_EXT);
-	reg_data &= ~E1000_TCTL_EXT_GCEX_MASK;
-	reg_data |= DEFAULT_TCTL_EXT_GCEX_80003ES2LAN;
-	ew32(TCTL_EXT, reg_data);
-
-	/* Configure Transmit Inter-Packet Gap */
-	reg_data = er32(TIPG);
-	reg_data &= ~E1000_TIPG_IPGT_MASK;
-	reg_data |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
-	ew32(TIPG, reg_data);
-
-	reg_data = E1000_READ_REG_ARRAY(hw, E1000_FFLT, 0x0001);
-	reg_data &= ~0x00100000;
-	E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data);
-
-	/* default to true to enable the MDIC W/A */
-	hw->dev_spec.e80003es2lan.mdic_wa_enable = true;
-
-	ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
-	                              E1000_KMRNCTRLSTA_OFFSET >>
-	                              E1000_KMRNCTRLSTA_OFFSET_SHIFT,
-	                              &i);
-	if (!ret_val) {
-		if ((i & E1000_KMRNCTRLSTA_OPMODE_MASK) ==
-		     E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO)
-			hw->dev_spec.e80003es2lan.mdic_wa_enable = false;
-	}
-
-	/*
-	 * Clear all of the statistics registers (clear on read).  It is
-	 * important that we do this after we have tried to establish link
-	 * because the symbol error count will increment wildly if there
-	 * is no link.
-	 */
-	e1000_clear_hw_cntrs_80003es2lan(hw);
-
-	return ret_val;
-}
-
-/**
- *  e1000_initialize_hw_bits_80003es2lan - Init hw bits of ESB2
- *  @hw: pointer to the HW structure
- *
- *  Initializes required hardware-dependent bits needed for normal operation.
- **/
-static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw)
-{
-	u32 reg;
-
-	/* Transmit Descriptor Control 0 */
-	reg = er32(TXDCTL(0));
-	reg |= (1 << 22);
-	ew32(TXDCTL(0), reg);
-
-	/* Transmit Descriptor Control 1 */
-	reg = er32(TXDCTL(1));
-	reg |= (1 << 22);
-	ew32(TXDCTL(1), reg);
-
-	/* Transmit Arbitration Control 0 */
-	reg = er32(TARC(0));
-	reg &= ~(0xF << 27); /* 30:27 */
-	if (hw->phy.media_type != e1000_media_type_copper)
-		reg &= ~(1 << 20);
-	ew32(TARC(0), reg);
-
-	/* Transmit Arbitration Control 1 */
-	reg = er32(TARC(1));
-	if (er32(TCTL) & E1000_TCTL_MULR)
-		reg &= ~(1 << 28);
-	else
-		reg |= (1 << 28);
-	ew32(TARC(1), reg);
-}
-
-/**
- *  e1000_copper_link_setup_gg82563_80003es2lan - Configure GG82563 Link
- *  @hw: pointer to the HW structure
- *
- *  Setup some GG82563 PHY registers for obtaining link
- **/
-static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u32 ctrl_ext;
-	u16 data;
-
-	ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &data);
-	if (ret_val)
-		return ret_val;
-
-	data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
-	/* Use 25MHz for both link down and 1000Base-T for Tx clock. */
-	data |= GG82563_MSCR_TX_CLK_1000MBPS_25;
-
-	ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, data);
-	if (ret_val)
-		return ret_val;
-
-	/*
-	 * Options:
-	 *   MDI/MDI-X = 0 (default)
-	 *   0 - Auto for all speeds
-	 *   1 - MDI mode
-	 *   2 - MDI-X mode
-	 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
-	 */
-	ret_val = e1e_rphy(hw, GG82563_PHY_SPEC_CTRL, &data);
-	if (ret_val)
-		return ret_val;
-
-	data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK;
-
-	switch (phy->mdix) {
-	case 1:
-		data |= GG82563_PSCR_CROSSOVER_MODE_MDI;
-		break;
-	case 2:
-		data |= GG82563_PSCR_CROSSOVER_MODE_MDIX;
-		break;
-	case 0:
-	default:
-		data |= GG82563_PSCR_CROSSOVER_MODE_AUTO;
-		break;
-	}
-
-	/*
-	 * Options:
-	 *   disable_polarity_correction = 0 (default)
-	 *       Automatic Correction for Reversed Cable Polarity
-	 *   0 - Disabled
-	 *   1 - Enabled
-	 */
-	data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
-	if (phy->disable_polarity_correction)
-		data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
-
-	ret_val = e1e_wphy(hw, GG82563_PHY_SPEC_CTRL, data);
-	if (ret_val)
-		return ret_val;
-
-	/* SW Reset the PHY so all changes take effect */
-	ret_val = e1000e_commit_phy(hw);
-	if (ret_val) {
-		e_dbg("Error Resetting the PHY\n");
-		return ret_val;
-	}
-
-	/* Bypass Rx and Tx FIFO's */
-	ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
-					E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL,
-					E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
-					E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
-				       E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
-				       &data);
-	if (ret_val)
-		return ret_val;
-	data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE;
-	ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
-					E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
-					data);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = e1e_rphy(hw, GG82563_PHY_SPEC_CTRL_2, &data);
-	if (ret_val)
-		return ret_val;
-
-	data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG;
-	ret_val = e1e_wphy(hw, GG82563_PHY_SPEC_CTRL_2, data);
-	if (ret_val)
-		return ret_val;
-
-	ctrl_ext = er32(CTRL_EXT);
-	ctrl_ext &= ~(E1000_CTRL_EXT_LINK_MODE_MASK);
-	ew32(CTRL_EXT, ctrl_ext);
-
-	ret_val = e1e_rphy(hw, GG82563_PHY_PWR_MGMT_CTRL, &data);
-	if (ret_val)
-		return ret_val;
-
-	/*
-	 * Do not init these registers when the HW is in IAMT mode, since the
-	 * firmware will have already initialized them.  We only initialize
-	 * them if the HW is not in IAMT mode.
-	 */
-	if (!e1000e_check_mng_mode(hw)) {
-		/* Enable Electrical Idle on the PHY */
-		data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
-		ret_val = e1e_wphy(hw, GG82563_PHY_PWR_MGMT_CTRL, data);
-		if (ret_val)
-			return ret_val;
-
-		ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &data);
-		if (ret_val)
-			return ret_val;
-
-		data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
-		ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, data);
-		if (ret_val)
-			return ret_val;
-	}
-
-	/*
-	 * Workaround: Disable padding in Kumeran interface in the MAC
-	 * and in the PHY to avoid CRC errors.
-	 */
-	ret_val = e1e_rphy(hw, GG82563_PHY_INBAND_CTRL, &data);
-	if (ret_val)
-		return ret_val;
-
-	data |= GG82563_ICR_DIS_PADDING;
-	ret_val = e1e_wphy(hw, GG82563_PHY_INBAND_CTRL, data);
-	if (ret_val)
-		return ret_val;
-
-	return 0;
-}
-
-/**
- *  e1000_setup_copper_link_80003es2lan - Setup Copper Link for ESB2
- *  @hw: pointer to the HW structure
- *
- *  Essentially a wrapper for setting up all things "copper" related.
- *  This is a function pointer entry point called by the mac module.
- **/
-static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
-{
-	u32 ctrl;
-	s32 ret_val;
-	u16 reg_data;
-
-	ctrl = er32(CTRL);
-	ctrl |= E1000_CTRL_SLU;
-	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
-	ew32(CTRL, ctrl);
-
-	/*
-	 * Set the mac to wait the maximum time between each
-	 * iteration and increase the max iterations when
-	 * polling the phy; this fixes erroneous timeouts at 10Mbps.
-	 */
-	ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4),
-	                                           0xFFFF);
-	if (ret_val)
-		return ret_val;
-	ret_val = e1000_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
-	                                          &reg_data);
-	if (ret_val)
-		return ret_val;
-	reg_data |= 0x3F;
-	ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
-	                                           reg_data);
-	if (ret_val)
-		return ret_val;
-	ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
-				      E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
-				      &reg_data);
-	if (ret_val)
-		return ret_val;
-	reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING;
-	ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
-					E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
-					reg_data);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = e1000_copper_link_setup_gg82563_80003es2lan(hw);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = e1000e_setup_copper_link(hw);
-
-	return 0;
-}
-
-/**
- *  e1000_cfg_on_link_up_80003es2lan - es2 link configuration after link-up
- *  @hw: pointer to the HW structure
- *  @duplex: current duplex setting
- *
- *  Configure the KMRN interface by applying last minute quirks for
- *  10/100 operation.
- **/
-static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw)
-{
-	s32 ret_val = 0;
-	u16 speed;
-	u16 duplex;
-
-	if (hw->phy.media_type == e1000_media_type_copper) {
-		ret_val = e1000e_get_speed_and_duplex_copper(hw, &speed,
-		                                             &duplex);
-		if (ret_val)
-			return ret_val;
-
-		if (speed == SPEED_1000)
-			ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw);
-		else
-			ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw, duplex);
-	}
-
-	return ret_val;
-}
-
-/**
- *  e1000_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation
- *  @hw: pointer to the HW structure
- *  @duplex: current duplex setting
- *
- *  Configure the KMRN interface by applying last minute quirks for
- *  10/100 operation.
- **/
-static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
-{
-	s32 ret_val;
-	u32 tipg;
-	u32 i = 0;
-	u16 reg_data, reg_data2;
-
-	reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT;
-	ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
-	                               E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
-	                               reg_data);
-	if (ret_val)
-		return ret_val;
-
-	/* Configure Transmit Inter-Packet Gap */
-	tipg = er32(TIPG);
-	tipg &= ~E1000_TIPG_IPGT_MASK;
-	tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN;
-	ew32(TIPG, tipg);
-
-	do {
-		ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
-		if (ret_val)
-			return ret_val;
-
-		ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data2);
-		if (ret_val)
-			return ret_val;
-		i++;
-	} while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
-
-	if (duplex == HALF_DUPLEX)
-		reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER;
-	else
-		reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
-
-	ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
-
-	return 0;
-}
-
-/**
- *  e1000_cfg_kmrn_1000_80003es2lan - Apply "quirks" for gigabit operation
- *  @hw: pointer to the HW structure
- *
- *  Configure the KMRN interface by applying last minute quirks for
- *  gigabit operation.
- **/
-static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 reg_data, reg_data2;
-	u32 tipg;
-	u32 i = 0;
-
-	reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT;
-	ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
-	                               E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
-	                               reg_data);
-	if (ret_val)
-		return ret_val;
-
-	/* Configure Transmit Inter-Packet Gap */
-	tipg = er32(TIPG);
-	tipg &= ~E1000_TIPG_IPGT_MASK;
-	tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
-	ew32(TIPG, tipg);
-
-	do {
-		ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
-		if (ret_val)
-			return ret_val;
-
-		ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data2);
-		if (ret_val)
-			return ret_val;
-		i++;
-	} while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
-
-	reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
-	ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
-
-	return ret_val;
-}
-
-/**
- *  e1000_read_kmrn_reg_80003es2lan - Read kumeran register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to be read
- *  @data: pointer to the read data
- *
- *  Acquire semaphore, then read the PHY register at offset
- *  using the kumeran interface.  The information retrieved is stored in data.
- *  Release the semaphore before exiting.
- **/
-static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
-					   u16 *data)
-{
-	u32 kmrnctrlsta;
-	s32 ret_val = 0;
-
-	ret_val = e1000_acquire_mac_csr_80003es2lan(hw);
-	if (ret_val)
-		return ret_val;
-
-	kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
-	               E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
-	ew32(KMRNCTRLSTA, kmrnctrlsta);
-	e1e_flush();
-
-	udelay(2);
-
-	kmrnctrlsta = er32(KMRNCTRLSTA);
-	*data = (u16)kmrnctrlsta;
-
-	e1000_release_mac_csr_80003es2lan(hw);
-
-	return ret_val;
-}
-
-/**
- *  e1000_write_kmrn_reg_80003es2lan - Write kumeran register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to write to
- *  @data: data to write at register offset
- *
- *  Acquire semaphore, then write the data to PHY register
- *  at the offset using the kumeran interface.  Release semaphore
- *  before exiting.
- **/
-static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
-					    u16 data)
-{
-	u32 kmrnctrlsta;
-	s32 ret_val = 0;
-
-	ret_val = e1000_acquire_mac_csr_80003es2lan(hw);
-	if (ret_val)
-		return ret_val;
-
-	kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
-	               E1000_KMRNCTRLSTA_OFFSET) | data;
-	ew32(KMRNCTRLSTA, kmrnctrlsta);
-	e1e_flush();
-
-	udelay(2);
-
-	e1000_release_mac_csr_80003es2lan(hw);
-
-	return ret_val;
-}
-
-/**
- *  e1000_read_mac_addr_80003es2lan - Read device MAC address
- *  @hw: pointer to the HW structure
- **/
-static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw)
-{
-	s32 ret_val = 0;
-
-	/*
-	 * If there's an alternate MAC address place it in RAR0
-	 * so that it will override the Si installed default perm
-	 * address.
-	 */
-	ret_val = e1000_check_alt_mac_addr_generic(hw);
-	if (ret_val)
-		goto out;
-
-	ret_val = e1000_read_mac_addr_generic(hw);
-
-out:
-	return ret_val;
-}
-
-/**
- * e1000_power_down_phy_copper_80003es2lan - Remove link during PHY power down
- * @hw: pointer to the HW structure
- *
- * In the case of a PHY power down to save power, or to turn off link during a
- * driver unload, or wake on lan is not enabled, remove the link.
- **/
-static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw)
-{
-	/* If the management interface is not enabled, then power down */
-	if (!(hw->mac.ops.check_mng_mode(hw) ||
-	      hw->phy.ops.check_reset_block(hw)))
-		e1000_power_down_phy_copper(hw);
-}
-
-/**
- *  e1000_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters
- *  @hw: pointer to the HW structure
- *
- *  Clears the hardware counters by reading the counter registers.
- **/
-static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw)
-{
-	e1000e_clear_hw_cntrs_base(hw);
-
-	er32(PRC64);
-	er32(PRC127);
-	er32(PRC255);
-	er32(PRC511);
-	er32(PRC1023);
-	er32(PRC1522);
-	er32(PTC64);
-	er32(PTC127);
-	er32(PTC255);
-	er32(PTC511);
-	er32(PTC1023);
-	er32(PTC1522);
-
-	er32(ALGNERRC);
-	er32(RXERRC);
-	er32(TNCRS);
-	er32(CEXTERR);
-	er32(TSCTC);
-	er32(TSCTFC);
-
-	er32(MGTPRC);
-	er32(MGTPDC);
-	er32(MGTPTC);
-
-	er32(IAC);
-	er32(ICRXOC);
-
-	er32(ICRXPTC);
-	er32(ICRXATC);
-	er32(ICTXPTC);
-	er32(ICTXATC);
-	er32(ICTXQEC);
-	er32(ICTXQMTC);
-	er32(ICRXDMTC);
-}
-
-static struct e1000_mac_operations es2_mac_ops = {
-	.read_mac_addr		= e1000_read_mac_addr_80003es2lan,
-	.id_led_init		= e1000e_id_led_init,
-	.blink_led		= e1000e_blink_led_generic,
-	.check_mng_mode		= e1000e_check_mng_mode_generic,
-	/* check_for_link dependent on media type */
-	.cleanup_led		= e1000e_cleanup_led_generic,
-	.clear_hw_cntrs		= e1000_clear_hw_cntrs_80003es2lan,
-	.get_bus_info		= e1000e_get_bus_info_pcie,
-	.set_lan_id		= e1000_set_lan_id_multi_port_pcie,
-	.get_link_up_info	= e1000_get_link_up_info_80003es2lan,
-	.led_on			= e1000e_led_on_generic,
-	.led_off		= e1000e_led_off_generic,
-	.update_mc_addr_list	= e1000e_update_mc_addr_list_generic,
-	.write_vfta		= e1000_write_vfta_generic,
-	.clear_vfta		= e1000_clear_vfta_generic,
-	.reset_hw		= e1000_reset_hw_80003es2lan,
-	.init_hw		= e1000_init_hw_80003es2lan,
-	.setup_link		= e1000e_setup_link,
-	/* setup_physical_interface dependent on media type */
-	.setup_led		= e1000e_setup_led_generic,
-};
-
-static struct e1000_phy_operations es2_phy_ops = {
-	.acquire		= e1000_acquire_phy_80003es2lan,
-	.check_polarity		= e1000_check_polarity_m88,
-	.check_reset_block	= e1000e_check_reset_block_generic,
-	.commit		 	= e1000e_phy_sw_reset,
-	.force_speed_duplex 	= e1000_phy_force_speed_duplex_80003es2lan,
-	.get_cfg_done       	= e1000_get_cfg_done_80003es2lan,
-	.get_cable_length   	= e1000_get_cable_length_80003es2lan,
-	.get_info       	= e1000e_get_phy_info_m88,
-	.read_reg       	= e1000_read_phy_reg_gg82563_80003es2lan,
-	.release		= e1000_release_phy_80003es2lan,
-	.reset		  	= e1000e_phy_hw_reset_generic,
-	.set_d0_lplu_state  	= NULL,
-	.set_d3_lplu_state  	= e1000e_set_d3_lplu_state,
-	.write_reg      	= e1000_write_phy_reg_gg82563_80003es2lan,
-	.cfg_on_link_up      	= e1000_cfg_on_link_up_80003es2lan,
-};
-
-static struct e1000_nvm_operations es2_nvm_ops = {
-	.acquire		= e1000_acquire_nvm_80003es2lan,
-	.read			= e1000e_read_nvm_eerd,
-	.release		= e1000_release_nvm_80003es2lan,
-	.update			= e1000e_update_nvm_checksum_generic,
-	.valid_led_default	= e1000e_valid_led_default,
-	.validate		= e1000e_validate_nvm_checksum_generic,
-	.write			= e1000_write_nvm_80003es2lan,
-};
-
-struct e1000_info e1000_es2_info = {
-	.mac			= e1000_80003es2lan,
-	.flags			= FLAG_HAS_HW_VLAN_FILTER
-				  | FLAG_HAS_JUMBO_FRAMES
-				  | FLAG_HAS_WOL
-				  | FLAG_APME_IN_CTRL3
-				  | FLAG_RX_CSUM_ENABLED
-				  | FLAG_HAS_CTRLEXT_ON_LOAD
-				  | FLAG_RX_NEEDS_RESTART /* errata */
-				  | FLAG_TARC_SET_BIT_ZERO /* errata */
-				  | FLAG_APME_CHECK_PORT_B
-				  | FLAG_DISABLE_FC_PAUSE_TIME /* errata */
-				  | FLAG_TIPG_MEDIUM_FOR_80003ESLAN,
-	.flags2			= FLAG2_DMA_BURST,
-	.pba			= 38,
-	.max_hw_frame_size	= DEFAULT_JUMBO,
-	.get_variants		= e1000_get_variants_80003es2lan,
-	.mac_ops		= &es2_mac_ops,
-	.phy_ops		= &es2_phy_ops,
-	.nvm_ops		= &es2_nvm_ops,
-};
-
diff -druN linux-libre-3.1-gnu/drivers/net/e1000e/ethtool.c linux-libre-3.2-gnu/drivers/net/e1000e/ethtool.c
--- linux-libre-3.1-gnu/drivers/net/e1000e/ethtool.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000e/ethtool.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2082 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  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,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-/* ethtool support for e1000 */
-
-#include <linux/netdevice.h>
-#include <linux/interrupt.h>
-#include <linux/ethtool.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-#include "e1000.h"
-
-enum {NETDEV_STATS, E1000_STATS};
-
-struct e1000_stats {
-	char stat_string[ETH_GSTRING_LEN];
-	int type;
-	int sizeof_stat;
-	int stat_offset;
-};
-
-#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) }
-#define E1000_NETDEV_STAT(str, 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),
-	E1000_STAT("tx_packets", stats.gptc),
-	E1000_STAT("rx_bytes", stats.gorc),
-	E1000_STAT("tx_bytes", stats.gotc),
-	E1000_STAT("rx_broadcast", stats.bprc),
-	E1000_STAT("tx_broadcast", stats.bptc),
-	E1000_STAT("rx_multicast", stats.mprc),
-	E1000_STAT("tx_multicast", stats.mptc),
-	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", 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", 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", 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),
-	E1000_STAT("tx_single_coll_ok", stats.scc),
-	E1000_STAT("tx_multi_coll_ok", stats.mcc),
-	E1000_STAT("tx_timeout_count", tx_timeout_count),
-	E1000_STAT("tx_restart_queue", restart_queue),
-	E1000_STAT("rx_long_length_errors", stats.roc),
-	E1000_STAT("rx_short_length_errors", stats.ruc),
-	E1000_STAT("rx_align_errors", stats.algnerrc),
-	E1000_STAT("tx_tcp_seg_good", stats.tsctc),
-	E1000_STAT("tx_tcp_seg_failed", stats.tsctfc),
-	E1000_STAT("rx_flow_control_xon", stats.xonrxc),
-	E1000_STAT("rx_flow_control_xoff", stats.xoffrxc),
-	E1000_STAT("tx_flow_control_xon", stats.xontxc),
-	E1000_STAT("tx_flow_control_xoff", stats.xofftxc),
-	E1000_STAT("rx_long_byte_count", stats.gorc),
-	E1000_STAT("rx_csum_offload_good", hw_csum_good),
-	E1000_STAT("rx_csum_offload_errors", hw_csum_err),
-	E1000_STAT("rx_header_split", rx_hdr_split),
-	E1000_STAT("alloc_rx_buff_failed", alloc_rx_buff_failed),
-	E1000_STAT("tx_smbus", stats.mgptc),
-	E1000_STAT("rx_smbus", stats.mgprc),
-	E1000_STAT("dropped_smbus", stats.mgpdc),
-	E1000_STAT("rx_dma_failed", rx_dma_failed),
-	E1000_STAT("tx_dma_failed", tx_dma_failed),
-};
-
-#define E1000_GLOBAL_STATS_LEN	ARRAY_SIZE(e1000_gstrings_stats)
-#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN)
-static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
-	"Register test  (offline)", "Eeprom test    (offline)",
-	"Interrupt test (offline)", "Loopback test  (offline)",
-	"Link test   (on/offline)"
-};
-#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test)
-
-static int e1000_get_settings(struct net_device *netdev,
-			      struct ethtool_cmd *ecmd)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u32 speed;
-
-	if (hw->phy.media_type == e1000_media_type_copper) {
-
-		ecmd->supported = (SUPPORTED_10baseT_Half |
-				   SUPPORTED_10baseT_Full |
-				   SUPPORTED_100baseT_Half |
-				   SUPPORTED_100baseT_Full |
-				   SUPPORTED_1000baseT_Full |
-				   SUPPORTED_Autoneg |
-				   SUPPORTED_TP);
-		if (hw->phy.type == e1000_phy_ife)
-			ecmd->supported &= ~SUPPORTED_1000baseT_Full;
-		ecmd->advertising = ADVERTISED_TP;
-
-		if (hw->mac.autoneg == 1) {
-			ecmd->advertising |= ADVERTISED_Autoneg;
-			/* the e1000 autoneg seems to match ethtool nicely */
-			ecmd->advertising |= hw->phy.autoneg_advertised;
-		}
-
-		ecmd->port = PORT_TP;
-		ecmd->phy_address = hw->phy.addr;
-		ecmd->transceiver = XCVR_INTERNAL;
-
-	} else {
-		ecmd->supported   = (SUPPORTED_1000baseT_Full |
-				     SUPPORTED_FIBRE |
-				     SUPPORTED_Autoneg);
-
-		ecmd->advertising = (ADVERTISED_1000baseT_Full |
-				     ADVERTISED_FIBRE |
-				     ADVERTISED_Autoneg);
-
-		ecmd->port = PORT_FIBRE;
-		ecmd->transceiver = XCVR_EXTERNAL;
-	}
-
-	speed = -1;
-	ecmd->duplex = -1;
-
-	if (netif_running(netdev)) {
-		if (netif_carrier_ok(netdev)) {
-			speed = adapter->link_speed;
-			ecmd->duplex = adapter->link_duplex - 1;
-		}
-	} else {
-		u32 status = er32(STATUS);
-		if (status & E1000_STATUS_LU) {
-			if (status & E1000_STATUS_SPEED_1000)
-				speed = SPEED_1000;
-			else if (status & E1000_STATUS_SPEED_100)
-				speed = SPEED_100;
-			else
-				speed = SPEED_10;
-
-			if (status & E1000_STATUS_FD)
-				ecmd->duplex = DUPLEX_FULL;
-			else
-				ecmd->duplex = DUPLEX_HALF;
-		}
-	}
-
-	ethtool_cmd_speed_set(ecmd, speed);
-	ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) ||
-			 hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
-
-	/* MDI-X => 2; MDI =>1; Invalid =>0 */
-	if ((hw->phy.media_type == e1000_media_type_copper) &&
-	    netif_carrier_ok(netdev))
-		ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X :
-		                                      ETH_TP_MDI;
-	else
-		ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
-
-	return 0;
-}
-
-static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx)
-{
-	struct e1000_mac_info *mac = &adapter->hw.mac;
-
-	mac->autoneg = 0;
-
-	/* Make sure dplx is at most 1 bit and lsb of speed is not set
-	 * for the switch() below to work */
-	if ((spd & 1) || (dplx & ~1))
-		goto err_inval;
-
-	/* Fiber NICs only allow 1000 gbps Full duplex */
-	if ((adapter->hw.phy.media_type == e1000_media_type_fiber) &&
-	    spd != SPEED_1000 &&
-	    dplx != DUPLEX_FULL) {
-		goto err_inval;
-	}
-
-	switch (spd + dplx) {
-	case SPEED_10 + DUPLEX_HALF:
-		mac->forced_speed_duplex = ADVERTISE_10_HALF;
-		break;
-	case SPEED_10 + DUPLEX_FULL:
-		mac->forced_speed_duplex = ADVERTISE_10_FULL;
-		break;
-	case SPEED_100 + DUPLEX_HALF:
-		mac->forced_speed_duplex = ADVERTISE_100_HALF;
-		break;
-	case SPEED_100 + DUPLEX_FULL:
-		mac->forced_speed_duplex = ADVERTISE_100_FULL;
-		break;
-	case SPEED_1000 + DUPLEX_FULL:
-		mac->autoneg = 1;
-		adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL;
-		break;
-	case SPEED_1000 + DUPLEX_HALF: /* not supported */
-	default:
-		goto err_inval;
-	}
-	return 0;
-
-err_inval:
-	e_err("Unsupported Speed/Duplex configuration\n");
-	return -EINVAL;
-}
-
-static int e1000_set_settings(struct net_device *netdev,
-			      struct ethtool_cmd *ecmd)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	/*
-	 * When SoL/IDER sessions are active, autoneg/speed/duplex
-	 * cannot be changed
-	 */
-	if (e1000_check_reset_block(hw)) {
-		e_err("Cannot change link characteristics when SoL/IDER is "
-		      "active.\n");
-		return -EINVAL;
-	}
-
-	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
-		usleep_range(1000, 2000);
-
-	if (ecmd->autoneg == AUTONEG_ENABLE) {
-		hw->mac.autoneg = 1;
-		if (hw->phy.media_type == e1000_media_type_fiber)
-			hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full |
-						     ADVERTISED_FIBRE |
-						     ADVERTISED_Autoneg;
-		else
-			hw->phy.autoneg_advertised = ecmd->advertising |
-						     ADVERTISED_TP |
-						     ADVERTISED_Autoneg;
-		ecmd->advertising = hw->phy.autoneg_advertised;
-		if (adapter->fc_autoneg)
-			hw->fc.requested_mode = e1000_fc_default;
-	} else {
-		u32 speed = ethtool_cmd_speed(ecmd);
-		if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) {
-			clear_bit(__E1000_RESETTING, &adapter->state);
-			return -EINVAL;
-		}
-	}
-
-	/* reset the link */
-
-	if (netif_running(adapter->netdev)) {
-		e1000e_down(adapter);
-		e1000e_up(adapter);
-	} else {
-		e1000e_reset(adapter);
-	}
-
-	clear_bit(__E1000_RESETTING, &adapter->state);
-	return 0;
-}
-
-static void e1000_get_pauseparam(struct net_device *netdev,
-				 struct ethtool_pauseparam *pause)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	pause->autoneg =
-		(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
-
-	if (hw->fc.current_mode == e1000_fc_rx_pause) {
-		pause->rx_pause = 1;
-	} else if (hw->fc.current_mode == e1000_fc_tx_pause) {
-		pause->tx_pause = 1;
-	} else if (hw->fc.current_mode == e1000_fc_full) {
-		pause->rx_pause = 1;
-		pause->tx_pause = 1;
-	}
-}
-
-static int e1000_set_pauseparam(struct net_device *netdev,
-				struct ethtool_pauseparam *pause)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	int retval = 0;
-
-	adapter->fc_autoneg = pause->autoneg;
-
-	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
-		usleep_range(1000, 2000);
-
-	if (adapter->fc_autoneg == AUTONEG_ENABLE) {
-		hw->fc.requested_mode = e1000_fc_default;
-		if (netif_running(adapter->netdev)) {
-			e1000e_down(adapter);
-			e1000e_up(adapter);
-		} else {
-			e1000e_reset(adapter);
-		}
-	} else {
-		if (pause->rx_pause && pause->tx_pause)
-			hw->fc.requested_mode = e1000_fc_full;
-		else if (pause->rx_pause && !pause->tx_pause)
-			hw->fc.requested_mode = e1000_fc_rx_pause;
-		else if (!pause->rx_pause && pause->tx_pause)
-			hw->fc.requested_mode = e1000_fc_tx_pause;
-		else if (!pause->rx_pause && !pause->tx_pause)
-			hw->fc.requested_mode = e1000_fc_none;
-
-		hw->fc.current_mode = hw->fc.requested_mode;
-
-		if (hw->phy.media_type == e1000_media_type_fiber) {
-			retval = hw->mac.ops.setup_link(hw);
-			/* implicit goto out */
-		} else {
-			retval = e1000e_force_mac_fc(hw);
-			if (retval)
-				goto out;
-			e1000e_set_fc_watermarks(hw);
-		}
-	}
-
-out:
-	clear_bit(__E1000_RESETTING, &adapter->state);
-	return retval;
-}
-
-static u32 e1000_get_rx_csum(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	return adapter->flags & FLAG_RX_CSUM_ENABLED;
-}
-
-static int e1000_set_rx_csum(struct net_device *netdev, u32 data)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	if (data)
-		adapter->flags |= FLAG_RX_CSUM_ENABLED;
-	else
-		adapter->flags &= ~FLAG_RX_CSUM_ENABLED;
-
-	if (netif_running(netdev))
-		e1000e_reinit_locked(adapter);
-	else
-		e1000e_reset(adapter);
-	return 0;
-}
-
-static u32 e1000_get_tx_csum(struct net_device *netdev)
-{
-	return (netdev->features & NETIF_F_HW_CSUM) != 0;
-}
-
-static int e1000_set_tx_csum(struct net_device *netdev, u32 data)
-{
-	if (data)
-		netdev->features |= NETIF_F_HW_CSUM;
-	else
-		netdev->features &= ~NETIF_F_HW_CSUM;
-
-	return 0;
-}
-
-static int e1000_set_tso(struct net_device *netdev, u32 data)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	if (data) {
-		netdev->features |= NETIF_F_TSO;
-		netdev->features |= NETIF_F_TSO6;
-	} else {
-		netdev->features &= ~NETIF_F_TSO;
-		netdev->features &= ~NETIF_F_TSO6;
-	}
-
-	adapter->flags |= FLAG_TSO_FORCE;
-	return 0;
-}
-
-static u32 e1000_get_msglevel(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	return adapter->msg_enable;
-}
-
-static void e1000_set_msglevel(struct net_device *netdev, u32 data)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	adapter->msg_enable = data;
-}
-
-static int e1000_get_regs_len(struct net_device *netdev)
-{
-#define E1000_REGS_LEN 32 /* overestimate */
-	return E1000_REGS_LEN * sizeof(u32);
-}
-
-static void e1000_get_regs(struct net_device *netdev,
-			   struct ethtool_regs *regs, void *p)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u32 *regs_buff = p;
-	u16 phy_data;
-
-	memset(p, 0, E1000_REGS_LEN * sizeof(u32));
-
-	regs->version = (1 << 24) | (adapter->pdev->revision << 16) |
-			adapter->pdev->device;
-
-	regs_buff[0]  = er32(CTRL);
-	regs_buff[1]  = er32(STATUS);
-
-	regs_buff[2]  = er32(RCTL);
-	regs_buff[3]  = er32(RDLEN);
-	regs_buff[4]  = er32(RDH);
-	regs_buff[5]  = er32(RDT);
-	regs_buff[6]  = er32(RDTR);
-
-	regs_buff[7]  = er32(TCTL);
-	regs_buff[8]  = er32(TDLEN);
-	regs_buff[9]  = er32(TDH);
-	regs_buff[10] = er32(TDT);
-	regs_buff[11] = er32(TIDV);
-
-	regs_buff[12] = adapter->hw.phy.type;  /* PHY type (IGP=1, M88=0) */
-
-	/* ethtool doesn't use anything past this point, so all this
-	 * code is likely legacy junk for apps that may or may not
-	 * exist */
-	if (hw->phy.type == e1000_phy_m88) {
-		e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
-		regs_buff[13] = (u32)phy_data; /* cable length */
-		regs_buff[14] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
-		regs_buff[15] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
-		regs_buff[16] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
-		e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-		regs_buff[17] = (u32)phy_data; /* extended 10bt distance */
-		regs_buff[18] = regs_buff[13]; /* cable polarity */
-		regs_buff[19] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
-		regs_buff[20] = regs_buff[17]; /* polarity correction */
-		/* phy receive errors */
-		regs_buff[22] = adapter->phy_stats.receive_errors;
-		regs_buff[23] = regs_buff[13]; /* mdix mode */
-	}
-	regs_buff[21] = 0; /* was idle_errors */
-	e1e_rphy(hw, PHY_1000T_STATUS, &phy_data);
-	regs_buff[24] = (u32)phy_data;  /* phy local receiver status */
-	regs_buff[25] = regs_buff[24];  /* phy remote receiver status */
-}
-
-static int e1000_get_eeprom_len(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	return adapter->hw.nvm.word_size * 2;
-}
-
-static int e1000_get_eeprom(struct net_device *netdev,
-			    struct ethtool_eeprom *eeprom, u8 *bytes)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u16 *eeprom_buff;
-	int first_word;
-	int last_word;
-	int ret_val = 0;
-	u16 i;
-
-	if (eeprom->len == 0)
-		return -EINVAL;
-
-	eeprom->magic = adapter->pdev->vendor | (adapter->pdev->device << 16);
-
-	first_word = eeprom->offset >> 1;
-	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
-
-	eeprom_buff = kmalloc(sizeof(u16) *
-			(last_word - first_word + 1), GFP_KERNEL);
-	if (!eeprom_buff)
-		return -ENOMEM;
-
-	if (hw->nvm.type == e1000_nvm_eeprom_spi) {
-		ret_val = e1000_read_nvm(hw, first_word,
-					 last_word - first_word + 1,
-					 eeprom_buff);
-	} else {
-		for (i = 0; i < last_word - first_word + 1; i++) {
-			ret_val = e1000_read_nvm(hw, first_word + i, 1,
-						      &eeprom_buff[i]);
-			if (ret_val)
-				break;
-		}
-	}
-
-	if (ret_val) {
-		/* a read error occurred, throw away the result */
-		memset(eeprom_buff, 0xff, sizeof(u16) *
-		       (last_word - first_word + 1));
-	} else {
-		/* Device's eeprom is always little-endian, word addressable */
-		for (i = 0; i < last_word - first_word + 1; i++)
-			le16_to_cpus(&eeprom_buff[i]);
-	}
-
-	memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len);
-	kfree(eeprom_buff);
-
-	return ret_val;
-}
-
-static int e1000_set_eeprom(struct net_device *netdev,
-			    struct ethtool_eeprom *eeprom, u8 *bytes)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u16 *eeprom_buff;
-	void *ptr;
-	int max_len;
-	int first_word;
-	int last_word;
-	int ret_val = 0;
-	u16 i;
-
-	if (eeprom->len == 0)
-		return -EOPNOTSUPP;
-
-	if (eeprom->magic != (adapter->pdev->vendor | (adapter->pdev->device << 16)))
-		return -EFAULT;
-
-	if (adapter->flags & FLAG_READ_ONLY_NVM)
-		return -EINVAL;
-
-	max_len = hw->nvm.word_size * 2;
-
-	first_word = eeprom->offset >> 1;
-	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
-	eeprom_buff = kmalloc(max_len, GFP_KERNEL);
-	if (!eeprom_buff)
-		return -ENOMEM;
-
-	ptr = (void *)eeprom_buff;
-
-	if (eeprom->offset & 1) {
-		/* need read/modify/write of first changed EEPROM word */
-		/* only the second byte of the word is being modified */
-		ret_val = e1000_read_nvm(hw, first_word, 1, &eeprom_buff[0]);
-		ptr++;
-	}
-	if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0))
-		/* need read/modify/write of last changed EEPROM word */
-		/* only the first byte of the word is being modified */
-		ret_val = e1000_read_nvm(hw, last_word, 1,
-				  &eeprom_buff[last_word - first_word]);
-
-	if (ret_val)
-		goto out;
-
-	/* Device's eeprom is always little-endian, word addressable */
-	for (i = 0; i < last_word - first_word + 1; i++)
-		le16_to_cpus(&eeprom_buff[i]);
-
-	memcpy(ptr, bytes, eeprom->len);
-
-	for (i = 0; i < last_word - first_word + 1; i++)
-		eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]);
-
-	ret_val = e1000_write_nvm(hw, first_word,
-				  last_word - first_word + 1, eeprom_buff);
-
-	if (ret_val)
-		goto out;
-
-	/*
-	 * Update the checksum over the first part of the EEPROM if needed
-	 * and flush shadow RAM for applicable controllers
-	 */
-	if ((first_word <= NVM_CHECKSUM_REG) ||
-	    (hw->mac.type == e1000_82583) ||
-	    (hw->mac.type == e1000_82574) ||
-	    (hw->mac.type == e1000_82573))
-		ret_val = e1000e_update_nvm_checksum(hw);
-
-out:
-	kfree(eeprom_buff);
-	return ret_val;
-}
-
-static void e1000_get_drvinfo(struct net_device *netdev,
-			      struct ethtool_drvinfo *drvinfo)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	char firmware_version[32];
-
-	strncpy(drvinfo->driver,  e1000e_driver_name,
-		sizeof(drvinfo->driver) - 1);
-	strncpy(drvinfo->version, e1000e_driver_version,
-		sizeof(drvinfo->version) - 1);
-
-	/*
-	 * EEPROM image version # is reported as firmware version # for
-	 * PCI-E controllers
-	 */
-	snprintf(firmware_version, sizeof(firmware_version), "%d.%d-%d",
-		(adapter->eeprom_vers & 0xF000) >> 12,
-		(adapter->eeprom_vers & 0x0FF0) >> 4,
-		(adapter->eeprom_vers & 0x000F));
-
-	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->regdump_len = e1000_get_regs_len(netdev);
-	drvinfo->eedump_len = e1000_get_eeprom_len(netdev);
-}
-
-static void e1000_get_ringparam(struct net_device *netdev,
-				struct ethtool_ringparam *ring)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_ring *tx_ring = adapter->tx_ring;
-	struct e1000_ring *rx_ring = adapter->rx_ring;
-
-	ring->rx_max_pending = E1000_MAX_RXD;
-	ring->tx_max_pending = E1000_MAX_TXD;
-	ring->rx_mini_max_pending = 0;
-	ring->rx_jumbo_max_pending = 0;
-	ring->rx_pending = rx_ring->count;
-	ring->tx_pending = tx_ring->count;
-	ring->rx_mini_pending = 0;
-	ring->rx_jumbo_pending = 0;
-}
-
-static int e1000_set_ringparam(struct net_device *netdev,
-			       struct ethtool_ringparam *ring)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_ring *tx_ring, *tx_old;
-	struct e1000_ring *rx_ring, *rx_old;
-	int err;
-
-	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
-		return -EINVAL;
-
-	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
-		usleep_range(1000, 2000);
-
-	if (netif_running(adapter->netdev))
-		e1000e_down(adapter);
-
-	tx_old = adapter->tx_ring;
-	rx_old = adapter->rx_ring;
-
-	err = -ENOMEM;
-	tx_ring = kmemdup(tx_old, sizeof(struct e1000_ring), GFP_KERNEL);
-	if (!tx_ring)
-		goto err_alloc_tx;
-
-	rx_ring = kmemdup(rx_old, sizeof(struct e1000_ring), GFP_KERNEL);
-	if (!rx_ring)
-		goto err_alloc_rx;
-
-	adapter->tx_ring = tx_ring;
-	adapter->rx_ring = rx_ring;
-
-	rx_ring->count = max(ring->rx_pending, (u32)E1000_MIN_RXD);
-	rx_ring->count = min(rx_ring->count, (u32)(E1000_MAX_RXD));
-	rx_ring->count = ALIGN(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE);
-
-	tx_ring->count = max(ring->tx_pending, (u32)E1000_MIN_TXD);
-	tx_ring->count = min(tx_ring->count, (u32)(E1000_MAX_TXD));
-	tx_ring->count = ALIGN(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE);
-
-	if (netif_running(adapter->netdev)) {
-		/* Try to get new resources before deleting old */
-		err = e1000e_setup_rx_resources(adapter);
-		if (err)
-			goto err_setup_rx;
-		err = e1000e_setup_tx_resources(adapter);
-		if (err)
-			goto err_setup_tx;
-
-		/*
-		 * restore the old in order to free it,
-		 * then add in the new
-		 */
-		adapter->rx_ring = rx_old;
-		adapter->tx_ring = tx_old;
-		e1000e_free_rx_resources(adapter);
-		e1000e_free_tx_resources(adapter);
-		kfree(tx_old);
-		kfree(rx_old);
-		adapter->rx_ring = rx_ring;
-		adapter->tx_ring = tx_ring;
-		err = e1000e_up(adapter);
-		if (err)
-			goto err_setup;
-	}
-
-	clear_bit(__E1000_RESETTING, &adapter->state);
-	return 0;
-err_setup_tx:
-	e1000e_free_rx_resources(adapter);
-err_setup_rx:
-	adapter->rx_ring = rx_old;
-	adapter->tx_ring = tx_old;
-	kfree(rx_ring);
-err_alloc_rx:
-	kfree(tx_ring);
-err_alloc_tx:
-	e1000e_up(adapter);
-err_setup:
-	clear_bit(__E1000_RESETTING, &adapter->state);
-	return err;
-}
-
-static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data,
-			     int reg, int offset, u32 mask, u32 write)
-{
-	u32 pat, val;
-	static const u32 test[] = {
-		0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
-	for (pat = 0; pat < ARRAY_SIZE(test); pat++) {
-		E1000_WRITE_REG_ARRAY(&adapter->hw, reg, offset,
-				      (test[pat] & write));
-		val = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset);
-		if (val != (test[pat] & write & mask)) {
-			e_err("pattern test reg %04X failed: got 0x%08X "
-			      "expected 0x%08X\n", reg + offset, val,
-			      (test[pat] & write & mask));
-			*data = reg;
-			return 1;
-		}
-	}
-	return 0;
-}
-
-static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
-			      int reg, u32 mask, u32 write)
-{
-	u32 val;
-	__ew32(&adapter->hw, reg, write & mask);
-	val = __er32(&adapter->hw, reg);
-	if ((write & mask) != (val & mask)) {
-		e_err("set/check reg %04X test failed: got 0x%08X "
-		      "expected 0x%08X\n", reg, (val & mask), (write & mask));
-		*data = reg;
-		return 1;
-	}
-	return 0;
-}
-#define REG_PATTERN_TEST_ARRAY(reg, offset, mask, write)                       \
-	do {                                                                   \
-		if (reg_pattern_test(adapter, data, reg, offset, mask, write)) \
-			return 1;                                              \
-	} while (0)
-#define REG_PATTERN_TEST(reg, mask, write)                                     \
-	REG_PATTERN_TEST_ARRAY(reg, 0, mask, write)
-
-#define REG_SET_AND_CHECK(reg, mask, write)                                    \
-	do {                                                                   \
-		if (reg_set_and_check(adapter, data, reg, mask, write))        \
-			return 1;                                              \
-	} while (0)
-
-static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_mac_info *mac = &adapter->hw.mac;
-	u32 value;
-	u32 before;
-	u32 after;
-	u32 i;
-	u32 toggle;
-	u32 mask;
-
-	/*
-	 * The status register is Read Only, so a write should fail.
-	 * Some bits that get toggled are ignored.
-	 */
-	switch (mac->type) {
-	/* there are several bits on newer hardware that are r/w */
-	case e1000_82571:
-	case e1000_82572:
-	case e1000_80003es2lan:
-		toggle = 0x7FFFF3FF;
-		break;
-        default:
-		toggle = 0x7FFFF033;
-		break;
-	}
-
-	before = er32(STATUS);
-	value = (er32(STATUS) & toggle);
-	ew32(STATUS, toggle);
-	after = er32(STATUS) & toggle;
-	if (value != after) {
-		e_err("failed STATUS register test got: 0x%08X expected: "
-		      "0x%08X\n", after, value);
-		*data = 1;
-		return 1;
-	}
-	/* restore previous status */
-	ew32(STATUS, before);
-
-	if (!(adapter->flags & FLAG_IS_ICH)) {
-		REG_PATTERN_TEST(E1000_FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
-		REG_PATTERN_TEST(E1000_FCAH, 0x0000FFFF, 0xFFFFFFFF);
-		REG_PATTERN_TEST(E1000_FCT, 0x0000FFFF, 0xFFFFFFFF);
-		REG_PATTERN_TEST(E1000_VET, 0x0000FFFF, 0xFFFFFFFF);
-	}
-
-	REG_PATTERN_TEST(E1000_RDTR, 0x0000FFFF, 0xFFFFFFFF);
-	REG_PATTERN_TEST(E1000_RDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
-	REG_PATTERN_TEST(E1000_RDLEN, 0x000FFF80, 0x000FFFFF);
-	REG_PATTERN_TEST(E1000_RDH, 0x0000FFFF, 0x0000FFFF);
-	REG_PATTERN_TEST(E1000_RDT, 0x0000FFFF, 0x0000FFFF);
-	REG_PATTERN_TEST(E1000_FCRTH, 0x0000FFF8, 0x0000FFF8);
-	REG_PATTERN_TEST(E1000_FCTTV, 0x0000FFFF, 0x0000FFFF);
-	REG_PATTERN_TEST(E1000_TIPG, 0x3FFFFFFF, 0x3FFFFFFF);
-	REG_PATTERN_TEST(E1000_TDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
-	REG_PATTERN_TEST(E1000_TDLEN, 0x000FFF80, 0x000FFFFF);
-
-	REG_SET_AND_CHECK(E1000_RCTL, 0xFFFFFFFF, 0x00000000);
-
-	before = ((adapter->flags & FLAG_IS_ICH) ? 0x06C3B33E : 0x06DFB3FE);
-	REG_SET_AND_CHECK(E1000_RCTL, before, 0x003FFFFB);
-	REG_SET_AND_CHECK(E1000_TCTL, 0xFFFFFFFF, 0x00000000);
-
-	REG_SET_AND_CHECK(E1000_RCTL, before, 0xFFFFFFFF);
-	REG_PATTERN_TEST(E1000_RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
-	if (!(adapter->flags & FLAG_IS_ICH))
-		REG_PATTERN_TEST(E1000_TXCW, 0xC000FFFF, 0x0000FFFF);
-	REG_PATTERN_TEST(E1000_TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
-	REG_PATTERN_TEST(E1000_TIDV, 0x0000FFFF, 0x0000FFFF);
-	mask = 0x8003FFFF;
-	switch (mac->type) {
-	case e1000_ich10lan:
-	case e1000_pchlan:
-	case e1000_pch2lan:
-		mask |= (1 << 18);
-		break;
-	default:
-		break;
-	}
-	for (i = 0; i < mac->rar_entry_count; i++)
-		REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1),
-		                       mask, 0xFFFFFFFF);
-
-	for (i = 0; i < mac->mta_reg_count; i++)
-		REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF);
-
-	*data = 0;
-	return 0;
-}
-
-static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
-{
-	u16 temp;
-	u16 checksum = 0;
-	u16 i;
-
-	*data = 0;
-	/* Read and add up the contents of the EEPROM */
-	for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
-		if ((e1000_read_nvm(&adapter->hw, i, 1, &temp)) < 0) {
-			*data = 1;
-			return *data;
-		}
-		checksum += temp;
-	}
-
-	/* If Checksum is not Correct return error else test passed */
-	if ((checksum != (u16) NVM_SUM) && !(*data))
-		*data = 2;
-
-	return *data;
-}
-
-static irqreturn_t e1000_test_intr(int irq, void *data)
-{
-	struct net_device *netdev = (struct net_device *) data;
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	adapter->test_icr |= er32(ICR);
-
-	return IRQ_HANDLED;
-}
-
-static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct e1000_hw *hw = &adapter->hw;
-	u32 mask;
-	u32 shared_int = 1;
-	u32 irq = adapter->pdev->irq;
-	int i;
-	int ret_val = 0;
-	int int_mode = E1000E_INT_MODE_LEGACY;
-
-	*data = 0;
-
-	/* NOTE: we don't test MSI/MSI-X interrupts here, yet */
-	if (adapter->int_mode == E1000E_INT_MODE_MSIX) {
-		int_mode = adapter->int_mode;
-		e1000e_reset_interrupt_capability(adapter);
-		adapter->int_mode = E1000E_INT_MODE_LEGACY;
-		e1000e_set_interrupt_capability(adapter);
-	}
-	/* Hook up test interrupt handler just for this test */
-	if (!request_irq(irq, e1000_test_intr, IRQF_PROBE_SHARED, netdev->name,
-			 netdev)) {
-		shared_int = 0;
-	} else if (request_irq(irq, e1000_test_intr, IRQF_SHARED,
-		 netdev->name, netdev)) {
-		*data = 1;
-		ret_val = -1;
-		goto out;
-	}
-	e_info("testing %s interrupt\n", (shared_int ? "shared" : "unshared"));
-
-	/* Disable all the interrupts */
-	ew32(IMC, 0xFFFFFFFF);
-	e1e_flush();
-	usleep_range(10000, 20000);
-
-	/* Test each interrupt */
-	for (i = 0; i < 10; i++) {
-		/* Interrupt to test */
-		mask = 1 << i;
-
-		if (adapter->flags & FLAG_IS_ICH) {
-			switch (mask) {
-			case E1000_ICR_RXSEQ:
-				continue;
-			case 0x00000100:
-				if (adapter->hw.mac.type == e1000_ich8lan ||
-				    adapter->hw.mac.type == e1000_ich9lan)
-					continue;
-				break;
-			default:
-				break;
-			}
-		}
-
-		if (!shared_int) {
-			/*
-			 * Disable the interrupt to be reported in
-			 * the cause register and then force the same
-			 * interrupt and see if one gets posted.  If
-			 * an interrupt was posted to the bus, the
-			 * test failed.
-			 */
-			adapter->test_icr = 0;
-			ew32(IMC, mask);
-			ew32(ICS, mask);
-			e1e_flush();
-			usleep_range(10000, 20000);
-
-			if (adapter->test_icr & mask) {
-				*data = 3;
-				break;
-			}
-		}
-
-		/*
-		 * Enable the interrupt to be reported in
-		 * the cause register and then force the same
-		 * interrupt and see if one gets posted.  If
-		 * an interrupt was not posted to the bus, the
-		 * test failed.
-		 */
-		adapter->test_icr = 0;
-		ew32(IMS, mask);
-		ew32(ICS, mask);
-		e1e_flush();
-		usleep_range(10000, 20000);
-
-		if (!(adapter->test_icr & mask)) {
-			*data = 4;
-			break;
-		}
-
-		if (!shared_int) {
-			/*
-			 * Disable the other interrupts to be reported in
-			 * the cause register and then force the other
-			 * interrupts and see if any get posted.  If
-			 * an interrupt was posted to the bus, the
-			 * test failed.
-			 */
-			adapter->test_icr = 0;
-			ew32(IMC, ~mask & 0x00007FFF);
-			ew32(ICS, ~mask & 0x00007FFF);
-			e1e_flush();
-			usleep_range(10000, 20000);
-
-			if (adapter->test_icr) {
-				*data = 5;
-				break;
-			}
-		}
-	}
-
-	/* Disable all the interrupts */
-	ew32(IMC, 0xFFFFFFFF);
-	e1e_flush();
-	usleep_range(10000, 20000);
-
-	/* Unhook test interrupt handler */
-	free_irq(irq, netdev);
-
-out:
-	if (int_mode == E1000E_INT_MODE_MSIX) {
-		e1000e_reset_interrupt_capability(adapter);
-		adapter->int_mode = int_mode;
-		e1000e_set_interrupt_capability(adapter);
-	}
-
-	return ret_val;
-}
-
-static void e1000_free_desc_rings(struct e1000_adapter *adapter)
-{
-	struct e1000_ring *tx_ring = &adapter->test_tx_ring;
-	struct e1000_ring *rx_ring = &adapter->test_rx_ring;
-	struct pci_dev *pdev = adapter->pdev;
-	int i;
-
-	if (tx_ring->desc && tx_ring->buffer_info) {
-		for (i = 0; i < tx_ring->count; i++) {
-			if (tx_ring->buffer_info[i].dma)
-				dma_unmap_single(&pdev->dev,
-					tx_ring->buffer_info[i].dma,
-					tx_ring->buffer_info[i].length,
-					DMA_TO_DEVICE);
-			if (tx_ring->buffer_info[i].skb)
-				dev_kfree_skb(tx_ring->buffer_info[i].skb);
-		}
-	}
-
-	if (rx_ring->desc && rx_ring->buffer_info) {
-		for (i = 0; i < rx_ring->count; i++) {
-			if (rx_ring->buffer_info[i].dma)
-				dma_unmap_single(&pdev->dev,
-					rx_ring->buffer_info[i].dma,
-					2048, DMA_FROM_DEVICE);
-			if (rx_ring->buffer_info[i].skb)
-				dev_kfree_skb(rx_ring->buffer_info[i].skb);
-		}
-	}
-
-	if (tx_ring->desc) {
-		dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc,
-				  tx_ring->dma);
-		tx_ring->desc = NULL;
-	}
-	if (rx_ring->desc) {
-		dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc,
-				  rx_ring->dma);
-		rx_ring->desc = NULL;
-	}
-
-	kfree(tx_ring->buffer_info);
-	tx_ring->buffer_info = NULL;
-	kfree(rx_ring->buffer_info);
-	rx_ring->buffer_info = NULL;
-}
-
-static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
-{
-	struct e1000_ring *tx_ring = &adapter->test_tx_ring;
-	struct e1000_ring *rx_ring = &adapter->test_rx_ring;
-	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_hw *hw = &adapter->hw;
-	u32 rctl;
-	int i;
-	int ret_val;
-
-	/* Setup Tx descriptor ring and Tx buffers */
-
-	if (!tx_ring->count)
-		tx_ring->count = E1000_DEFAULT_TXD;
-
-	tx_ring->buffer_info = kcalloc(tx_ring->count,
-				       sizeof(struct e1000_buffer),
-				       GFP_KERNEL);
-	if (!(tx_ring->buffer_info)) {
-		ret_val = 1;
-		goto err_nomem;
-	}
-
-	tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc);
-	tx_ring->size = ALIGN(tx_ring->size, 4096);
-	tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
-					   &tx_ring->dma, GFP_KERNEL);
-	if (!tx_ring->desc) {
-		ret_val = 2;
-		goto err_nomem;
-	}
-	tx_ring->next_to_use = 0;
-	tx_ring->next_to_clean = 0;
-
-	ew32(TDBAL, ((u64) tx_ring->dma & 0x00000000FFFFFFFF));
-	ew32(TDBAH, ((u64) tx_ring->dma >> 32));
-	ew32(TDLEN, tx_ring->count * sizeof(struct e1000_tx_desc));
-	ew32(TDH, 0);
-	ew32(TDT, 0);
-	ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN | E1000_TCTL_MULR |
-	     E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
-	     E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT);
-
-	for (i = 0; i < tx_ring->count; i++) {
-		struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i);
-		struct sk_buff *skb;
-		unsigned int skb_size = 1024;
-
-		skb = alloc_skb(skb_size, GFP_KERNEL);
-		if (!skb) {
-			ret_val = 3;
-			goto err_nomem;
-		}
-		skb_put(skb, skb_size);
-		tx_ring->buffer_info[i].skb = skb;
-		tx_ring->buffer_info[i].length = skb->len;
-		tx_ring->buffer_info[i].dma =
-			dma_map_single(&pdev->dev, skb->data, skb->len,
-				       DMA_TO_DEVICE);
-		if (dma_mapping_error(&pdev->dev,
-				      tx_ring->buffer_info[i].dma)) {
-			ret_val = 4;
-			goto err_nomem;
-		}
-		tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma);
-		tx_desc->lower.data = cpu_to_le32(skb->len);
-		tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP |
-						   E1000_TXD_CMD_IFCS |
-						   E1000_TXD_CMD_RS);
-		tx_desc->upper.data = 0;
-	}
-
-	/* Setup Rx descriptor ring and Rx buffers */
-
-	if (!rx_ring->count)
-		rx_ring->count = E1000_DEFAULT_RXD;
-
-	rx_ring->buffer_info = kcalloc(rx_ring->count,
-				       sizeof(struct e1000_buffer),
-				       GFP_KERNEL);
-	if (!(rx_ring->buffer_info)) {
-		ret_val = 5;
-		goto err_nomem;
-	}
-
-	rx_ring->size = rx_ring->count * sizeof(struct e1000_rx_desc);
-	rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
-					   &rx_ring->dma, GFP_KERNEL);
-	if (!rx_ring->desc) {
-		ret_val = 6;
-		goto err_nomem;
-	}
-	rx_ring->next_to_use = 0;
-	rx_ring->next_to_clean = 0;
-
-	rctl = er32(RCTL);
-	if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX))
-		ew32(RCTL, rctl & ~E1000_RCTL_EN);
-	ew32(RDBAL, ((u64) rx_ring->dma & 0xFFFFFFFF));
-	ew32(RDBAH, ((u64) rx_ring->dma >> 32));
-	ew32(RDLEN, rx_ring->size);
-	ew32(RDH, 0);
-	ew32(RDT, 0);
-	rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |
-		E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_LPE |
-		E1000_RCTL_SBP | E1000_RCTL_SECRC |
-		E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
-		(adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
-	ew32(RCTL, rctl);
-
-	for (i = 0; i < rx_ring->count; i++) {
-		struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i);
-		struct sk_buff *skb;
-
-		skb = alloc_skb(2048 + NET_IP_ALIGN, GFP_KERNEL);
-		if (!skb) {
-			ret_val = 7;
-			goto err_nomem;
-		}
-		skb_reserve(skb, NET_IP_ALIGN);
-		rx_ring->buffer_info[i].skb = skb;
-		rx_ring->buffer_info[i].dma =
-			dma_map_single(&pdev->dev, skb->data, 2048,
-				       DMA_FROM_DEVICE);
-		if (dma_mapping_error(&pdev->dev,
-				      rx_ring->buffer_info[i].dma)) {
-			ret_val = 8;
-			goto err_nomem;
-		}
-		rx_desc->buffer_addr =
-			cpu_to_le64(rx_ring->buffer_info[i].dma);
-		memset(skb->data, 0x00, skb->len);
-	}
-
-	return 0;
-
-err_nomem:
-	e1000_free_desc_rings(adapter);
-	return ret_val;
-}
-
-static void e1000_phy_disable_receiver(struct e1000_adapter *adapter)
-{
-	/* Write out to PHY registers 29 and 30 to disable the Receiver. */
-	e1e_wphy(&adapter->hw, 29, 0x001F);
-	e1e_wphy(&adapter->hw, 30, 0x8FFC);
-	e1e_wphy(&adapter->hw, 29, 0x001A);
-	e1e_wphy(&adapter->hw, 30, 0x8FF0);
-}
-
-static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 ctrl_reg = 0;
-	u16 phy_reg = 0;
-	s32 ret_val = 0;
-
-	hw->mac.autoneg = 0;
-
-	if (hw->phy.type == e1000_phy_ife) {
-		/* force 100, set loopback */
-		e1e_wphy(hw, PHY_CONTROL, 0x6100);
-
-		/* Now set up the MAC to the same speed/duplex as the PHY. */
-		ctrl_reg = er32(CTRL);
-		ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
-		ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
-			     E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
-			     E1000_CTRL_SPD_100 |/* Force Speed to 100 */
-			     E1000_CTRL_FD);	 /* Force Duplex to FULL */
-
-		ew32(CTRL, ctrl_reg);
-		e1e_flush();
-		udelay(500);
-
-		return 0;
-	}
-
-	/* Specific PHY configuration for loopback */
-	switch (hw->phy.type) {
-	case e1000_phy_m88:
-		/* Auto-MDI/MDIX Off */
-		e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808);
-		/* reset to update Auto-MDI/MDIX */
-		e1e_wphy(hw, PHY_CONTROL, 0x9140);
-		/* autoneg off */
-		e1e_wphy(hw, PHY_CONTROL, 0x8140);
-		break;
-	case e1000_phy_gg82563:
-		e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC);
-		break;
-	case e1000_phy_bm:
-		/* Set Default MAC Interface speed to 1GB */
-		e1e_rphy(hw, PHY_REG(2, 21), &phy_reg);
-		phy_reg &= ~0x0007;
-		phy_reg |= 0x006;
-		e1e_wphy(hw, PHY_REG(2, 21), phy_reg);
-		/* Assert SW reset for above settings to take effect */
-		e1000e_commit_phy(hw);
-		mdelay(1);
-		/* Force Full Duplex */
-		e1e_rphy(hw, PHY_REG(769, 16), &phy_reg);
-		e1e_wphy(hw, PHY_REG(769, 16), phy_reg | 0x000C);
-		/* Set Link Up (in force link) */
-		e1e_rphy(hw, PHY_REG(776, 16), &phy_reg);
-		e1e_wphy(hw, PHY_REG(776, 16), phy_reg | 0x0040);
-		/* Force Link */
-		e1e_rphy(hw, PHY_REG(769, 16), &phy_reg);
-		e1e_wphy(hw, PHY_REG(769, 16), phy_reg | 0x0040);
-		/* Set Early Link Enable */
-		e1e_rphy(hw, PHY_REG(769, 20), &phy_reg);
-		e1e_wphy(hw, PHY_REG(769, 20), phy_reg | 0x0400);
-		break;
-	case e1000_phy_82577:
-	case e1000_phy_82578:
-		/* Workaround: K1 must be disabled for stable 1Gbps operation */
-		ret_val = hw->phy.ops.acquire(hw);
-		if (ret_val) {
-			e_err("Cannot setup 1Gbps loopback.\n");
-			return ret_val;
-		}
-		e1000_configure_k1_ich8lan(hw, false);
-		hw->phy.ops.release(hw);
-		break;
-	case e1000_phy_82579:
-		/* Disable PHY energy detect power down */
-		e1e_rphy(hw, PHY_REG(0, 21), &phy_reg);
-		e1e_wphy(hw, PHY_REG(0, 21), phy_reg & ~(1 << 3));
-		/* Disable full chip energy detect */
-		e1e_rphy(hw, PHY_REG(776, 18), &phy_reg);
-		e1e_wphy(hw, PHY_REG(776, 18), phy_reg | 1);
-		/* Enable loopback on the PHY */
-#define I82577_PHY_LBK_CTRL          19
-		e1e_wphy(hw, I82577_PHY_LBK_CTRL, 0x8001);
-		break;
-	default:
-		break;
-	}
-
-	/* force 1000, set loopback */
-	e1e_wphy(hw, PHY_CONTROL, 0x4140);
-	mdelay(250);
-
-	/* Now set up the MAC to the same speed/duplex as the PHY. */
-	ctrl_reg = er32(CTRL);
-	ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
-	ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
-		     E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
-		     E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
-		     E1000_CTRL_FD);	 /* Force Duplex to FULL */
-
-	if (adapter->flags & FLAG_IS_ICH)
-		ctrl_reg |= E1000_CTRL_SLU;	/* Set Link Up */
-
-	if (hw->phy.media_type == e1000_media_type_copper &&
-	    hw->phy.type == e1000_phy_m88) {
-		ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
-	} else {
-		/*
-		 * Set the ILOS bit on the fiber Nic if half duplex link is
-		 * detected.
-		 */
-		if ((er32(STATUS) & E1000_STATUS_FD) == 0)
-			ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
-	}
-
-	ew32(CTRL, ctrl_reg);
-
-	/*
-	 * Disable the receiver on the PHY so when a cable is plugged in, the
-	 * PHY does not begin to autoneg when a cable is reconnected to the NIC.
-	 */
-	if (hw->phy.type == e1000_phy_m88)
-		e1000_phy_disable_receiver(adapter);
-
-	udelay(500);
-
-	return 0;
-}
-
-static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 ctrl = er32(CTRL);
-	int link = 0;
-
-	/* special requirements for 82571/82572 fiber adapters */
-
-	/*
-	 * jump through hoops to make sure link is up because serdes
-	 * link is hardwired up
-	 */
-	ctrl |= E1000_CTRL_SLU;
-	ew32(CTRL, ctrl);
-
-	/* disable autoneg */
-	ctrl = er32(TXCW);
-	ctrl &= ~(1 << 31);
-	ew32(TXCW, ctrl);
-
-	link = (er32(STATUS) & E1000_STATUS_LU);
-
-	if (!link) {
-		/* set invert loss of signal */
-		ctrl = er32(CTRL);
-		ctrl |= E1000_CTRL_ILOS;
-		ew32(CTRL, ctrl);
-	}
-
-	/*
-	 * special write to serdes control register to enable SerDes analog
-	 * loopback
-	 */
-#define E1000_SERDES_LB_ON 0x410
-	ew32(SCTL, E1000_SERDES_LB_ON);
-	e1e_flush();
-	usleep_range(10000, 20000);
-
-	return 0;
-}
-
-/* only call this for fiber/serdes connections to es2lan */
-static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 ctrlext = er32(CTRL_EXT);
-	u32 ctrl = er32(CTRL);
-
-	/*
-	 * save CTRL_EXT to restore later, reuse an empty variable (unused
-	 * on mac_type 80003es2lan)
-	 */
-	adapter->tx_fifo_head = ctrlext;
-
-	/* clear the serdes mode bits, putting the device into mac loopback */
-	ctrlext &= ~E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES;
-	ew32(CTRL_EXT, ctrlext);
-
-	/* force speed to 1000/FD, link up */
-	ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
-	ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX |
-		 E1000_CTRL_SPD_1000 | E1000_CTRL_FD);
-	ew32(CTRL, ctrl);
-
-	/* set mac loopback */
-	ctrl = er32(RCTL);
-	ctrl |= E1000_RCTL_LBM_MAC;
-	ew32(RCTL, ctrl);
-
-	/* set testing mode parameters (no need to reset later) */
-#define KMRNCTRLSTA_OPMODE (0x1F << 16)
-#define KMRNCTRLSTA_OPMODE_1GB_FD_GMII 0x0582
-	ew32(KMRNCTRLSTA,
-	     (KMRNCTRLSTA_OPMODE | KMRNCTRLSTA_OPMODE_1GB_FD_GMII));
-
-	return 0;
-}
-
-static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 rctl;
-
-	if (hw->phy.media_type == e1000_media_type_fiber ||
-	    hw->phy.media_type == e1000_media_type_internal_serdes) {
-		switch (hw->mac.type) {
-		case e1000_80003es2lan:
-			return e1000_set_es2lan_mac_loopback(adapter);
-			break;
-		case e1000_82571:
-		case e1000_82572:
-			return e1000_set_82571_fiber_loopback(adapter);
-			break;
-		default:
-			rctl = er32(RCTL);
-			rctl |= E1000_RCTL_LBM_TCVR;
-			ew32(RCTL, rctl);
-			return 0;
-		}
-	} else if (hw->phy.media_type == e1000_media_type_copper) {
-		return e1000_integrated_phy_loopback(adapter);
-	}
-
-	return 7;
-}
-
-static void e1000_loopback_cleanup(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 rctl;
-	u16 phy_reg;
-
-	rctl = er32(RCTL);
-	rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
-	ew32(RCTL, rctl);
-
-	switch (hw->mac.type) {
-	case e1000_80003es2lan:
-		if (hw->phy.media_type == e1000_media_type_fiber ||
-		    hw->phy.media_type == e1000_media_type_internal_serdes) {
-			/* restore CTRL_EXT, stealing space from tx_fifo_head */
-			ew32(CTRL_EXT, adapter->tx_fifo_head);
-			adapter->tx_fifo_head = 0;
-		}
-		/* fall through */
-	case e1000_82571:
-	case e1000_82572:
-		if (hw->phy.media_type == e1000_media_type_fiber ||
-		    hw->phy.media_type == e1000_media_type_internal_serdes) {
-#define E1000_SERDES_LB_OFF 0x400
-			ew32(SCTL, E1000_SERDES_LB_OFF);
-			e1e_flush();
-			usleep_range(10000, 20000);
-			break;
-		}
-		/* Fall Through */
-	default:
-		hw->mac.autoneg = 1;
-		if (hw->phy.type == e1000_phy_gg82563)
-			e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x180);
-		e1e_rphy(hw, PHY_CONTROL, &phy_reg);
-		if (phy_reg & MII_CR_LOOPBACK) {
-			phy_reg &= ~MII_CR_LOOPBACK;
-			e1e_wphy(hw, PHY_CONTROL, phy_reg);
-			e1000e_commit_phy(hw);
-		}
-		break;
-	}
-}
-
-static void e1000_create_lbtest_frame(struct sk_buff *skb,
-				      unsigned int frame_size)
-{
-	memset(skb->data, 0xFF, frame_size);
-	frame_size &= ~1;
-	memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
-	memset(&skb->data[frame_size / 2 + 10], 0xBE, 1);
-	memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);
-}
-
-static int e1000_check_lbtest_frame(struct sk_buff *skb,
-				    unsigned int frame_size)
-{
-	frame_size &= ~1;
-	if (*(skb->data + 3) == 0xFF)
-		if ((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
-		   (*(skb->data + frame_size / 2 + 12) == 0xAF))
-			return 0;
-	return 13;
-}
-
-static int e1000_run_loopback_test(struct e1000_adapter *adapter)
-{
-	struct e1000_ring *tx_ring = &adapter->test_tx_ring;
-	struct e1000_ring *rx_ring = &adapter->test_rx_ring;
-	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_hw *hw = &adapter->hw;
-	int i, j, k, l;
-	int lc;
-	int good_cnt;
-	int ret_val = 0;
-	unsigned long time;
-
-	ew32(RDT, rx_ring->count - 1);
-
-	/*
-	 * Calculate the loop count based on the largest descriptor ring
-	 * The idea is to wrap the largest ring a number of times using 64
-	 * send/receive pairs during each loop
-	 */
-
-	if (rx_ring->count <= tx_ring->count)
-		lc = ((tx_ring->count / 64) * 2) + 1;
-	else
-		lc = ((rx_ring->count / 64) * 2) + 1;
-
-	k = 0;
-	l = 0;
-	for (j = 0; j <= lc; j++) { /* loop count loop */
-		for (i = 0; i < 64; i++) { /* send the packets */
-			e1000_create_lbtest_frame(tx_ring->buffer_info[k].skb,
-						  1024);
-			dma_sync_single_for_device(&pdev->dev,
-					tx_ring->buffer_info[k].dma,
-					tx_ring->buffer_info[k].length,
-					DMA_TO_DEVICE);
-			k++;
-			if (k == tx_ring->count)
-				k = 0;
-		}
-		ew32(TDT, k);
-		e1e_flush();
-		msleep(200);
-		time = jiffies; /* set the start time for the receive */
-		good_cnt = 0;
-		do { /* receive the sent packets */
-			dma_sync_single_for_cpu(&pdev->dev,
-					rx_ring->buffer_info[l].dma, 2048,
-					DMA_FROM_DEVICE);
-
-			ret_val = e1000_check_lbtest_frame(
-					rx_ring->buffer_info[l].skb, 1024);
-			if (!ret_val)
-				good_cnt++;
-			l++;
-			if (l == rx_ring->count)
-				l = 0;
-			/*
-			 * time + 20 msecs (200 msecs on 2.4) is more than
-			 * enough time to complete the receives, if it's
-			 * exceeded, break and error off
-			 */
-		} while ((good_cnt < 64) && !time_after(jiffies, time + 20));
-		if (good_cnt != 64) {
-			ret_val = 13; /* ret_val is the same as mis-compare */
-			break;
-		}
-		if (jiffies >= (time + 20)) {
-			ret_val = 14; /* error code for time out error */
-			break;
-		}
-	} /* end loop count loop */
-	return ret_val;
-}
-
-static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
-{
-	/*
-	 * PHY loopback cannot be performed if SoL/IDER
-	 * sessions are active
-	 */
-	if (e1000_check_reset_block(&adapter->hw)) {
-		e_err("Cannot do PHY loopback test when SoL/IDER is active.\n");
-		*data = 0;
-		goto out;
-	}
-
-	*data = e1000_setup_desc_rings(adapter);
-	if (*data)
-		goto out;
-
-	*data = e1000_setup_loopback_test(adapter);
-	if (*data)
-		goto err_loopback;
-
-	*data = e1000_run_loopback_test(adapter);
-	e1000_loopback_cleanup(adapter);
-
-err_loopback:
-	e1000_free_desc_rings(adapter);
-out:
-	return *data;
-}
-
-static int e1000_link_test(struct e1000_adapter *adapter, u64 *data)
-{
-	struct e1000_hw *hw = &adapter->hw;
-
-	*data = 0;
-	if (hw->phy.media_type == e1000_media_type_internal_serdes) {
-		int i = 0;
-		hw->mac.serdes_has_link = false;
-
-		/*
-		 * On some blade server designs, link establishment
-		 * could take as long as 2-3 minutes
-		 */
-		do {
-			hw->mac.ops.check_for_link(hw);
-			if (hw->mac.serdes_has_link)
-				return *data;
-			msleep(20);
-		} while (i++ < 3750);
-
-		*data = 1;
-	} else {
-		hw->mac.ops.check_for_link(hw);
-		if (hw->mac.autoneg)
-			/*
-			 * On some Phy/switch combinations, link establishment
-			 * can take a few seconds more than expected.
-			 */
-			msleep(5000);
-
-		if (!(er32(STATUS) & E1000_STATUS_LU))
-			*data = 1;
-	}
-	return *data;
-}
-
-static int e1000e_get_sset_count(struct net_device *netdev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_TEST:
-		return E1000_TEST_LEN;
-	case ETH_SS_STATS:
-		return E1000_STATS_LEN;
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void e1000_diag_test(struct net_device *netdev,
-			    struct ethtool_test *eth_test, u64 *data)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	u16 autoneg_advertised;
-	u8 forced_speed_duplex;
-	u8 autoneg;
-	bool if_running = netif_running(netdev);
-
-	set_bit(__E1000_TESTING, &adapter->state);
-
-	if (!if_running) {
-		/* Get control of and reset hardware */
-		if (adapter->flags & FLAG_HAS_AMT)
-			e1000e_get_hw_control(adapter);
-
-		e1000e_power_up_phy(adapter);
-
-		adapter->hw.phy.autoneg_wait_to_complete = 1;
-		e1000e_reset(adapter);
-		adapter->hw.phy.autoneg_wait_to_complete = 0;
-	}
-
-	if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
-		/* Offline tests */
-
-		/* save speed, duplex, autoneg settings */
-		autoneg_advertised = adapter->hw.phy.autoneg_advertised;
-		forced_speed_duplex = adapter->hw.mac.forced_speed_duplex;
-		autoneg = adapter->hw.mac.autoneg;
-
-		e_info("offline testing starting\n");
-
-		if (if_running)
-			/* indicate we're in test mode */
-			dev_close(netdev);
-
-		if (e1000_reg_test(adapter, &data[0]))
-			eth_test->flags |= ETH_TEST_FL_FAILED;
-
-		e1000e_reset(adapter);
-		if (e1000_eeprom_test(adapter, &data[1]))
-			eth_test->flags |= ETH_TEST_FL_FAILED;
-
-		e1000e_reset(adapter);
-		if (e1000_intr_test(adapter, &data[2]))
-			eth_test->flags |= ETH_TEST_FL_FAILED;
-
-		e1000e_reset(adapter);
-		if (e1000_loopback_test(adapter, &data[3]))
-			eth_test->flags |= ETH_TEST_FL_FAILED;
-
-		/* force this routine to wait until autoneg complete/timeout */
-		adapter->hw.phy.autoneg_wait_to_complete = 1;
-		e1000e_reset(adapter);
-		adapter->hw.phy.autoneg_wait_to_complete = 0;
-
-		if (e1000_link_test(adapter, &data[4]))
-			eth_test->flags |= ETH_TEST_FL_FAILED;
-
-		/* restore speed, duplex, autoneg settings */
-		adapter->hw.phy.autoneg_advertised = autoneg_advertised;
-		adapter->hw.mac.forced_speed_duplex = forced_speed_duplex;
-		adapter->hw.mac.autoneg = autoneg;
-		e1000e_reset(adapter);
-
-		clear_bit(__E1000_TESTING, &adapter->state);
-		if (if_running)
-			dev_open(netdev);
-	} else {
-		/* Online tests */
-
-		e_info("online testing starting\n");
-
-		/* register, eeprom, intr and loopback tests not run online */
-		data[0] = 0;
-		data[1] = 0;
-		data[2] = 0;
-		data[3] = 0;
-
-		if (e1000_link_test(adapter, &data[4]))
-			eth_test->flags |= ETH_TEST_FL_FAILED;
-
-		clear_bit(__E1000_TESTING, &adapter->state);
-	}
-
-	if (!if_running) {
-		e1000e_reset(adapter);
-
-		if (adapter->flags & FLAG_HAS_AMT)
-			e1000e_release_hw_control(adapter);
-	}
-
-	msleep_interruptible(4 * 1000);
-}
-
-static void e1000_get_wol(struct net_device *netdev,
-			  struct ethtool_wolinfo *wol)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	wol->supported = 0;
-	wol->wolopts = 0;
-
-	if (!(adapter->flags & FLAG_HAS_WOL) ||
-	    !device_can_wakeup(&adapter->pdev->dev))
-		return;
-
-	wol->supported = WAKE_UCAST | WAKE_MCAST |
-	    WAKE_BCAST | WAKE_MAGIC | WAKE_PHY;
-
-	/* apply any specific unsupported masks here */
-	if (adapter->flags & FLAG_NO_WAKE_UCAST) {
-		wol->supported &= ~WAKE_UCAST;
-
-		if (adapter->wol & E1000_WUFC_EX)
-			e_err("Interface does not support directed (unicast) "
-			      "frame wake-up packets\n");
-	}
-
-	if (adapter->wol & E1000_WUFC_EX)
-		wol->wolopts |= WAKE_UCAST;
-	if (adapter->wol & E1000_WUFC_MC)
-		wol->wolopts |= WAKE_MCAST;
-	if (adapter->wol & E1000_WUFC_BC)
-		wol->wolopts |= WAKE_BCAST;
-	if (adapter->wol & E1000_WUFC_MAG)
-		wol->wolopts |= WAKE_MAGIC;
-	if (adapter->wol & E1000_WUFC_LNKC)
-		wol->wolopts |= WAKE_PHY;
-}
-
-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)))
-		return -EOPNOTSUPP;
-
-	/* these settings will always override what we currently have */
-	adapter->wol = 0;
-
-	if (wol->wolopts & WAKE_UCAST)
-		adapter->wol |= E1000_WUFC_EX;
-	if (wol->wolopts & WAKE_MCAST)
-		adapter->wol |= E1000_WUFC_MC;
-	if (wol->wolopts & WAKE_BCAST)
-		adapter->wol |= E1000_WUFC_BC;
-	if (wol->wolopts & WAKE_MAGIC)
-		adapter->wol |= E1000_WUFC_MAG;
-	if (wol->wolopts & WAKE_PHY)
-		adapter->wol |= E1000_WUFC_LNKC;
-
-	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
-
-	return 0;
-}
-
-static int e1000_set_phys_id(struct net_device *netdev,
-			     enum ethtool_phys_id_state state)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	switch (state) {
-	case ETHTOOL_ID_ACTIVE:
-		if (!hw->mac.ops.blink_led)
-			return 2;	/* cycle on/off twice per second */
-
-		hw->mac.ops.blink_led(hw);
-		break;
-
-	case ETHTOOL_ID_INACTIVE:
-		if (hw->phy.type == e1000_phy_ife)
-			e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0);
-		hw->mac.ops.led_off(hw);
-		hw->mac.ops.cleanup_led(hw);
-		break;
-
-	case ETHTOOL_ID_ON:
-		adapter->hw.mac.ops.led_on(&adapter->hw);
-		break;
-
-	case ETHTOOL_ID_OFF:
-		adapter->hw.mac.ops.led_off(&adapter->hw);
-		break;
-	}
-	return 0;
-}
-
-static int e1000_get_coalesce(struct net_device *netdev,
-			      struct ethtool_coalesce *ec)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	if (adapter->itr_setting <= 4)
-		ec->rx_coalesce_usecs = adapter->itr_setting;
-	else
-		ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting;
-
-	return 0;
-}
-
-static int e1000_set_coalesce(struct net_device *netdev,
-			      struct ethtool_coalesce *ec)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) ||
-	    ((ec->rx_coalesce_usecs > 4) &&
-	     (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) ||
-	    (ec->rx_coalesce_usecs == 2))
-		return -EINVAL;
-
-	if (ec->rx_coalesce_usecs == 4) {
-		adapter->itr = adapter->itr_setting = 4;
-	} else if (ec->rx_coalesce_usecs <= 3) {
-		adapter->itr = 20000;
-		adapter->itr_setting = ec->rx_coalesce_usecs;
-	} else {
-		adapter->itr = (1000000 / ec->rx_coalesce_usecs);
-		adapter->itr_setting = adapter->itr & ~3;
-	}
-
-	if (adapter->itr_setting != 0)
-		ew32(ITR, 1000000000 / (adapter->itr * 256));
-	else
-		ew32(ITR, 0);
-
-	return 0;
-}
-
-static int e1000_nway_reset(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	if (!netif_running(netdev))
-		return -EAGAIN;
-
-	if (!adapter->hw.mac.autoneg)
-		return -EINVAL;
-
-	e1000e_reinit_locked(adapter);
-
-	return 0;
-}
-
-static void e1000_get_ethtool_stats(struct net_device *netdev,
-				    struct ethtool_stats *stats,
-				    u64 *data)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct rtnl_link_stats64 net_stats;
-	int i;
-	char *p = NULL;
-
-	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 *) &net_stats +
-					e1000_gstrings_stats[i].stat_offset;
-			break;
-		case E1000_STATS:
-			p = (char *) adapter +
-					e1000_gstrings_stats[i].stat_offset;
-			break;
-		default:
-			data[i] = 0;
-			continue;
-		}
-
-		data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
-			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
-	}
-}
-
-static void e1000_get_strings(struct net_device *netdev, u32 stringset,
-			      u8 *data)
-{
-	u8 *p = data;
-	int i;
-
-	switch (stringset) {
-	case ETH_SS_TEST:
-		memcpy(data, e1000_gstrings_test, sizeof(e1000_gstrings_test));
-		break;
-	case ETH_SS_STATS:
-		for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
-			memcpy(p, e1000_gstrings_stats[i].stat_string,
-			       ETH_GSTRING_LEN);
-			p += ETH_GSTRING_LEN;
-		}
-		break;
-	}
-}
-
-static int e1000e_set_flags(struct net_device *netdev, u32 data)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	bool need_reset = false;
-	int rc;
-
-	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))
-			e1000e_reinit_locked(adapter);
-		else
-			e1000e_reset(adapter);
-	}
-
-	return 0;
-}
-
-static const struct ethtool_ops e1000_ethtool_ops = {
-	.get_settings		= e1000_get_settings,
-	.set_settings		= e1000_set_settings,
-	.get_drvinfo		= e1000_get_drvinfo,
-	.get_regs_len		= e1000_get_regs_len,
-	.get_regs		= e1000_get_regs,
-	.get_wol		= e1000_get_wol,
-	.set_wol		= e1000_set_wol,
-	.get_msglevel		= e1000_get_msglevel,
-	.set_msglevel		= e1000_set_msglevel,
-	.nway_reset		= e1000_nway_reset,
-	.get_link		= ethtool_op_get_link,
-	.get_eeprom_len		= e1000_get_eeprom_len,
-	.get_eeprom		= e1000_get_eeprom,
-	.set_eeprom		= e1000_set_eeprom,
-	.get_ringparam		= e1000_get_ringparam,
-	.set_ringparam		= e1000_set_ringparam,
-	.get_pauseparam		= e1000_get_pauseparam,
-	.set_pauseparam		= e1000_set_pauseparam,
-	.get_rx_csum		= e1000_get_rx_csum,
-	.set_rx_csum		= e1000_set_rx_csum,
-	.get_tx_csum		= e1000_get_tx_csum,
-	.set_tx_csum		= e1000_set_tx_csum,
-	.get_sg			= ethtool_op_get_sg,
-	.set_sg			= ethtool_op_set_sg,
-	.get_tso		= ethtool_op_get_tso,
-	.set_tso		= e1000_set_tso,
-	.self_test		= e1000_diag_test,
-	.get_strings		= e1000_get_strings,
-	.set_phys_id		= e1000_set_phys_id,
-	.get_ethtool_stats	= e1000_get_ethtool_stats,
-	.get_sset_count		= e1000e_get_sset_count,
-	.get_coalesce		= e1000_get_coalesce,
-	.set_coalesce		= e1000_set_coalesce,
-	.get_flags		= ethtool_op_get_flags,
-	.set_flags		= e1000e_set_flags,
-};
-
-void e1000e_set_ethtool_ops(struct net_device *netdev)
-{
-	SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/e1000e/hw.h linux-libre-3.2-gnu/drivers/net/e1000e/hw.h
--- linux-libre-3.1-gnu/drivers/net/e1000e/hw.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000e/hw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,984 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  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,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-#ifndef _E1000_HW_H_
-#define _E1000_HW_H_
-
-#include <linux/types.h>
-
-struct e1000_hw;
-struct e1000_adapter;
-
-#include "defines.h"
-
-#define er32(reg)	__er32(hw, E1000_##reg)
-#define ew32(reg,val)	__ew32(hw, E1000_##reg, (val))
-#define e1e_flush()	er32(STATUS)
-
-#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) \
-	(writel((value), ((a)->hw_addr + reg + ((offset) << 2))))
-
-#define E1000_READ_REG_ARRAY(a, reg, offset) \
-	(readl((a)->hw_addr + reg + ((offset) << 2)))
-
-enum e1e_registers {
-	E1000_CTRL     = 0x00000, /* Device Control - RW */
-	E1000_STATUS   = 0x00008, /* Device Status - RO */
-	E1000_EECD     = 0x00010, /* EEPROM/Flash Control - RW */
-	E1000_EERD     = 0x00014, /* EEPROM Read - RW */
-	E1000_CTRL_EXT = 0x00018, /* Extended Device Control - RW */
-	E1000_FLA      = 0x0001C, /* Flash Access - RW */
-	E1000_MDIC     = 0x00020, /* MDI Control - RW */
-	E1000_SCTL     = 0x00024, /* SerDes Control - RW */
-	E1000_FCAL     = 0x00028, /* Flow Control Address Low - RW */
-	E1000_FCAH     = 0x0002C, /* Flow Control Address High -RW */
-	E1000_FEXTNVM4 = 0x00024, /* Future Extended NVM 4 - RW */
-	E1000_FEXTNVM  = 0x00028, /* Future Extended NVM - RW */
-	E1000_FCT      = 0x00030, /* Flow Control Type - RW */
-	E1000_VET      = 0x00038, /* VLAN Ether Type - RW */
-	E1000_ICR      = 0x000C0, /* Interrupt Cause Read - R/clr */
-	E1000_ITR      = 0x000C4, /* Interrupt Throttling Rate - RW */
-	E1000_ICS      = 0x000C8, /* Interrupt Cause Set - WO */
-	E1000_IMS      = 0x000D0, /* Interrupt Mask Set - RW */
-	E1000_IMC      = 0x000D8, /* Interrupt Mask Clear - WO */
-	E1000_EIAC_82574 = 0x000DC, /* Ext. Interrupt Auto Clear - RW */
-	E1000_IAM      = 0x000E0, /* Interrupt Acknowledge Auto Mask */
-	E1000_IVAR     = 0x000E4, /* Interrupt Vector Allocation - RW */
-	E1000_EITR_82574_BASE = 0x000E8, /* Interrupt Throttling - RW */
-#define E1000_EITR_82574(_n) (E1000_EITR_82574_BASE + (_n << 2))
-	E1000_RCTL     = 0x00100, /* Rx Control - RW */
-	E1000_FCTTV    = 0x00170, /* Flow Control Transmit Timer Value - RW */
-	E1000_TXCW     = 0x00178, /* Tx Configuration Word - RW */
-	E1000_RXCW     = 0x00180, /* Rx Configuration Word - RO */
-	E1000_TCTL     = 0x00400, /* Tx Control - RW */
-	E1000_TCTL_EXT = 0x00404, /* Extended Tx Control - RW */
-	E1000_TIPG     = 0x00410, /* Tx Inter-packet gap -RW */
-	E1000_AIT      = 0x00458, /* Adaptive Interframe Spacing Throttle -RW */
-	E1000_LEDCTL   = 0x00E00, /* LED Control - RW */
-	E1000_EXTCNF_CTRL  = 0x00F00, /* Extended Configuration Control */
-	E1000_EXTCNF_SIZE  = 0x00F08, /* Extended Configuration Size */
-	E1000_PHY_CTRL     = 0x00F10, /* PHY Control Register in CSR */
-#define E1000_POEMB	E1000_PHY_CTRL	/* PHY OEM Bits */
-	E1000_PBA      = 0x01000, /* Packet Buffer Allocation - RW */
-	E1000_PBS      = 0x01008, /* Packet Buffer Size */
-	E1000_EEMNGCTL = 0x01010, /* MNG EEprom Control */
-	E1000_EEWR     = 0x0102C, /* EEPROM Write Register - RW */
-	E1000_FLOP     = 0x0103C, /* FLASH Opcode Register */
-	E1000_PBA_ECC  = 0x01100, /* PBA ECC Register */
-	E1000_ERT      = 0x02008, /* Early Rx Threshold - RW */
-	E1000_FCRTL    = 0x02160, /* Flow Control Receive Threshold Low - RW */
-	E1000_FCRTH    = 0x02168, /* Flow Control Receive Threshold High - RW */
-	E1000_PSRCTL   = 0x02170, /* Packet Split Receive Control - RW */
-	E1000_RDBAL    = 0x02800, /* Rx Descriptor Base Address Low - RW */
-	E1000_RDBAH    = 0x02804, /* Rx Descriptor Base Address High - RW */
-	E1000_RDLEN    = 0x02808, /* Rx Descriptor Length - RW */
-	E1000_RDH      = 0x02810, /* Rx Descriptor Head - RW */
-	E1000_RDT      = 0x02818, /* Rx Descriptor Tail - RW */
-	E1000_RDTR     = 0x02820, /* Rx Delay Timer - RW */
-	E1000_RXDCTL_BASE = 0x02828, /* Rx Descriptor Control - RW */
-#define E1000_RXDCTL(_n)   (E1000_RXDCTL_BASE + (_n << 8))
-	E1000_RADV     = 0x0282C, /* Rx Interrupt Absolute Delay Timer - RW */
-
-/* Convenience macros
- *
- * Note: "_n" is the queue number of the register to be written to.
- *
- * Example usage:
- * E1000_RDBAL_REG(current_rx_queue)
- *
- */
-#define E1000_RDBAL_REG(_n)   (E1000_RDBAL + (_n << 8))
-	E1000_KABGTXD  = 0x03004, /* AFE Band Gap Transmit Ref Data */
-	E1000_TDBAL    = 0x03800, /* Tx Descriptor Base Address Low - RW */
-	E1000_TDBAH    = 0x03804, /* Tx Descriptor Base Address High - RW */
-	E1000_TDLEN    = 0x03808, /* Tx Descriptor Length - RW */
-	E1000_TDH      = 0x03810, /* Tx Descriptor Head - RW */
-	E1000_TDT      = 0x03818, /* Tx Descriptor Tail - RW */
-	E1000_TIDV     = 0x03820, /* Tx Interrupt Delay Value - RW */
-	E1000_TXDCTL_BASE = 0x03828, /* Tx Descriptor Control - RW */
-#define E1000_TXDCTL(_n)   (E1000_TXDCTL_BASE + (_n << 8))
-	E1000_TADV     = 0x0382C, /* Tx Interrupt Absolute Delay Val - RW */
-	E1000_TARC_BASE = 0x03840, /* Tx Arbitration Count (0) */
-#define E1000_TARC(_n)   (E1000_TARC_BASE + (_n << 8))
-	E1000_CRCERRS  = 0x04000, /* CRC Error Count - R/clr */
-	E1000_ALGNERRC = 0x04004, /* Alignment Error Count - R/clr */
-	E1000_SYMERRS  = 0x04008, /* Symbol Error Count - R/clr */
-	E1000_RXERRC   = 0x0400C, /* Receive Error Count - R/clr */
-	E1000_MPC      = 0x04010, /* Missed Packet Count - R/clr */
-	E1000_SCC      = 0x04014, /* Single Collision Count - R/clr */
-	E1000_ECOL     = 0x04018, /* Excessive Collision Count - R/clr */
-	E1000_MCC      = 0x0401C, /* Multiple Collision Count - R/clr */
-	E1000_LATECOL  = 0x04020, /* Late Collision Count - R/clr */
-	E1000_COLC     = 0x04028, /* Collision Count - R/clr */
-	E1000_DC       = 0x04030, /* Defer Count - R/clr */
-	E1000_TNCRS    = 0x04034, /* Tx-No CRS - R/clr */
-	E1000_SEC      = 0x04038, /* Sequence Error Count - R/clr */
-	E1000_CEXTERR  = 0x0403C, /* Carrier Extension Error Count - R/clr */
-	E1000_RLEC     = 0x04040, /* Receive Length Error Count - R/clr */
-	E1000_XONRXC   = 0x04048, /* XON Rx Count - R/clr */
-	E1000_XONTXC   = 0x0404C, /* XON Tx Count - R/clr */
-	E1000_XOFFRXC  = 0x04050, /* XOFF Rx Count - R/clr */
-	E1000_XOFFTXC  = 0x04054, /* XOFF Tx Count - R/clr */
-	E1000_FCRUC    = 0x04058, /* Flow Control Rx Unsupported Count- R/clr */
-	E1000_PRC64    = 0x0405C, /* Packets Rx (64 bytes) - R/clr */
-	E1000_PRC127   = 0x04060, /* Packets Rx (65-127 bytes) - R/clr */
-	E1000_PRC255   = 0x04064, /* Packets Rx (128-255 bytes) - R/clr */
-	E1000_PRC511   = 0x04068, /* Packets Rx (255-511 bytes) - R/clr */
-	E1000_PRC1023  = 0x0406C, /* Packets Rx (512-1023 bytes) - R/clr */
-	E1000_PRC1522  = 0x04070, /* Packets Rx (1024-1522 bytes) - R/clr */
-	E1000_GPRC     = 0x04074, /* Good Packets Rx Count - R/clr */
-	E1000_BPRC     = 0x04078, /* Broadcast Packets Rx Count - R/clr */
-	E1000_MPRC     = 0x0407C, /* Multicast Packets Rx Count - R/clr */
-	E1000_GPTC     = 0x04080, /* Good Packets Tx Count - R/clr */
-	E1000_GORCL    = 0x04088, /* Good Octets Rx Count Low - R/clr */
-	E1000_GORCH    = 0x0408C, /* Good Octets Rx Count High - R/clr */
-	E1000_GOTCL    = 0x04090, /* Good Octets Tx Count Low - R/clr */
-	E1000_GOTCH    = 0x04094, /* Good Octets Tx Count High - R/clr */
-	E1000_RNBC     = 0x040A0, /* Rx No Buffers Count - R/clr */
-	E1000_RUC      = 0x040A4, /* Rx Undersize Count - R/clr */
-	E1000_RFC      = 0x040A8, /* Rx Fragment Count - R/clr */
-	E1000_ROC      = 0x040AC, /* Rx Oversize Count - R/clr */
-	E1000_RJC      = 0x040B0, /* Rx Jabber Count - R/clr */
-	E1000_MGTPRC   = 0x040B4, /* Management Packets Rx Count - R/clr */
-	E1000_MGTPDC   = 0x040B8, /* Management Packets Dropped Count - R/clr */
-	E1000_MGTPTC   = 0x040BC, /* Management Packets Tx Count - R/clr */
-	E1000_TORL     = 0x040C0, /* Total Octets Rx Low - R/clr */
-	E1000_TORH     = 0x040C4, /* Total Octets Rx High - R/clr */
-	E1000_TOTL     = 0x040C8, /* Total Octets Tx Low - R/clr */
-	E1000_TOTH     = 0x040CC, /* Total Octets Tx High - R/clr */
-	E1000_TPR      = 0x040D0, /* Total Packets Rx - R/clr */
-	E1000_TPT      = 0x040D4, /* Total Packets Tx - R/clr */
-	E1000_PTC64    = 0x040D8, /* Packets Tx (64 bytes) - R/clr */
-	E1000_PTC127   = 0x040DC, /* Packets Tx (65-127 bytes) - R/clr */
-	E1000_PTC255   = 0x040E0, /* Packets Tx (128-255 bytes) - R/clr */
-	E1000_PTC511   = 0x040E4, /* Packets Tx (256-511 bytes) - R/clr */
-	E1000_PTC1023  = 0x040E8, /* Packets Tx (512-1023 bytes) - R/clr */
-	E1000_PTC1522  = 0x040EC, /* Packets Tx (1024-1522 Bytes) - R/clr */
-	E1000_MPTC     = 0x040F0, /* Multicast Packets Tx Count - R/clr */
-	E1000_BPTC     = 0x040F4, /* Broadcast Packets Tx Count - R/clr */
-	E1000_TSCTC    = 0x040F8, /* TCP Segmentation Context Tx - R/clr */
-	E1000_TSCTFC   = 0x040FC, /* TCP Segmentation Context Tx Fail - R/clr */
-	E1000_IAC      = 0x04100, /* Interrupt Assertion Count */
-	E1000_ICRXPTC  = 0x04104, /* Irq Cause Rx Packet Timer Expire Count */
-	E1000_ICRXATC  = 0x04108, /* Irq Cause Rx Abs Timer Expire Count */
-	E1000_ICTXPTC  = 0x0410C, /* Irq Cause Tx Packet Timer Expire Count */
-	E1000_ICTXATC  = 0x04110, /* Irq Cause Tx Abs Timer Expire Count */
-	E1000_ICTXQEC  = 0x04118, /* Irq Cause Tx Queue Empty Count */
-	E1000_ICTXQMTC = 0x0411C, /* Irq Cause Tx Queue MinThreshold Count */
-	E1000_ICRXDMTC = 0x04120, /* Irq Cause Rx Desc MinThreshold Count */
-	E1000_ICRXOC   = 0x04124, /* Irq Cause Receiver Overrun Count */
-	E1000_RXCSUM   = 0x05000, /* Rx Checksum Control - RW */
-	E1000_RFCTL    = 0x05008, /* Receive Filter Control */
-	E1000_MTA      = 0x05200, /* Multicast Table Array - RW Array */
-	E1000_RAL_BASE = 0x05400, /* Receive Address Low - RW */
-#define E1000_RAL(_n)   (E1000_RAL_BASE + ((_n) * 8))
-#define E1000_RA        (E1000_RAL(0))
-	E1000_RAH_BASE = 0x05404, /* Receive Address High - RW */
-#define E1000_RAH(_n)   (E1000_RAH_BASE + ((_n) * 8))
-	E1000_VFTA     = 0x05600, /* VLAN Filter Table Array - RW Array */
-	E1000_WUC      = 0x05800, /* Wakeup Control - RW */
-	E1000_WUFC     = 0x05808, /* Wakeup Filter Control - RW */
-	E1000_WUS      = 0x05810, /* Wakeup Status - RO */
-	E1000_MANC     = 0x05820, /* Management Control - RW */
-	E1000_FFLT     = 0x05F00, /* Flexible Filter Length Table - RW Array */
-	E1000_HOST_IF  = 0x08800, /* Host Interface */
-
-	E1000_KMRNCTRLSTA = 0x00034, /* MAC-PHY interface - RW */
-	E1000_MANC2H    = 0x05860, /* Management Control To Host - RW */
-	E1000_MDEF_BASE = 0x05890, /* Management Decision Filters */
-#define E1000_MDEF(_n)   (E1000_MDEF_BASE + ((_n) * 4))
-	E1000_SW_FW_SYNC = 0x05B5C, /* Software-Firmware Synchronization - RW */
-	E1000_GCR	= 0x05B00, /* PCI-Ex Control */
-	E1000_GCR2      = 0x05B64, /* PCI-Ex Control #2 */
-	E1000_FACTPS    = 0x05B30, /* Function Active and Power State to MNG */
-	E1000_SWSM      = 0x05B50, /* SW Semaphore */
-	E1000_FWSM      = 0x05B54, /* FW Semaphore */
-	E1000_SWSM2     = 0x05B58, /* Driver-only SW semaphore */
-	E1000_FFLT_DBG  = 0x05F04, /* Debug Register */
-	E1000_PCH_RAICC_BASE = 0x05F50, /* Receive Address Initial CRC */
-#define E1000_PCH_RAICC(_n)	(E1000_PCH_RAICC_BASE + ((_n) * 4))
-#define E1000_CRC_OFFSET	E1000_PCH_RAICC_BASE
-	E1000_HICR      = 0x08F00, /* Host Interface Control */
-};
-
-#define E1000_MAX_PHY_ADDR		4
-
-/* IGP01E1000 Specific Registers */
-#define IGP01E1000_PHY_PORT_CONFIG	0x10 /* Port Config */
-#define IGP01E1000_PHY_PORT_STATUS	0x11 /* Status */
-#define IGP01E1000_PHY_PORT_CTRL	0x12 /* Control */
-#define IGP01E1000_PHY_LINK_HEALTH	0x13 /* PHY Link Health */
-#define IGP02E1000_PHY_POWER_MGMT	0x19 /* Power Management */
-#define IGP01E1000_PHY_PAGE_SELECT	0x1F /* Page Select */
-#define BM_PHY_PAGE_SELECT		22   /* Page Select for BM */
-#define IGP_PAGE_SHIFT			5
-#define PHY_REG_MASK			0x1F
-
-#define BM_WUC_PAGE			800
-#define BM_WUC_ADDRESS_OPCODE		0x11
-#define BM_WUC_DATA_OPCODE		0x12
-#define BM_WUC_ENABLE_PAGE		769
-#define BM_WUC_ENABLE_REG		17
-#define BM_WUC_ENABLE_BIT		(1 << 2)
-#define BM_WUC_HOST_WU_BIT		(1 << 4)
-#define BM_WUC_ME_WU_BIT		(1 << 5)
-
-#define BM_WUC	PHY_REG(BM_WUC_PAGE, 1)
-#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2)
-#define BM_WUS	PHY_REG(BM_WUC_PAGE, 3)
-
-#define IGP01E1000_PHY_PCS_INIT_REG	0x00B4
-#define IGP01E1000_PHY_POLARITY_MASK	0x0078
-
-#define IGP01E1000_PSCR_AUTO_MDIX	0x1000
-#define IGP01E1000_PSCR_FORCE_MDI_MDIX	0x2000 /* 0=MDI, 1=MDIX */
-
-#define IGP01E1000_PSCFR_SMART_SPEED	0x0080
-
-#define IGP02E1000_PM_SPD		0x0001 /* Smart Power Down */
-#define IGP02E1000_PM_D0_LPLU		0x0002 /* For D0a states */
-#define IGP02E1000_PM_D3_LPLU		0x0004 /* For all other states */
-
-#define IGP01E1000_PLHR_SS_DOWNGRADE	0x8000
-
-#define IGP01E1000_PSSR_POLARITY_REVERSED	0x0002
-#define IGP01E1000_PSSR_MDIX			0x0800
-#define IGP01E1000_PSSR_SPEED_MASK		0xC000
-#define IGP01E1000_PSSR_SPEED_1000MBPS		0xC000
-
-#define IGP02E1000_PHY_CHANNEL_NUM		4
-#define IGP02E1000_PHY_AGC_A			0x11B1
-#define IGP02E1000_PHY_AGC_B			0x12B1
-#define IGP02E1000_PHY_AGC_C			0x14B1
-#define IGP02E1000_PHY_AGC_D			0x18B1
-
-#define IGP02E1000_AGC_LENGTH_SHIFT	9 /* Course - 15:13, Fine - 12:9 */
-#define IGP02E1000_AGC_LENGTH_MASK	0x7F
-#define IGP02E1000_AGC_RANGE		15
-
-/* manage.c */
-#define E1000_VFTA_ENTRY_SHIFT		5
-#define E1000_VFTA_ENTRY_MASK		0x7F
-#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK	0x1F
-
-#define E1000_HICR_EN			0x01  /* Enable bit - RO */
-/* Driver sets this bit when done to put command in RAM */
-#define E1000_HICR_C			0x02
-#define E1000_HICR_FW_RESET_ENABLE	0x40
-#define E1000_HICR_FW_RESET		0x80
-
-#define E1000_FWSM_MODE_MASK		0xE
-#define E1000_FWSM_MODE_SHIFT		1
-
-#define E1000_MNG_IAMT_MODE		0x3
-#define E1000_MNG_DHCP_COOKIE_LENGTH	0x10
-#define E1000_MNG_DHCP_COOKIE_OFFSET	0x6F0
-#define E1000_MNG_DHCP_COMMAND_TIMEOUT	10
-#define E1000_MNG_DHCP_TX_PAYLOAD_CMD	64
-#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING	0x1
-#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN	0x2
-
-/* nvm.c */
-#define E1000_STM_OPCODE  0xDB00
-
-#define E1000_KMRNCTRLSTA_OFFSET	0x001F0000
-#define E1000_KMRNCTRLSTA_OFFSET_SHIFT	16
-#define E1000_KMRNCTRLSTA_REN		0x00200000
-#define E1000_KMRNCTRLSTA_CTRL_OFFSET	0x1    /* Kumeran Control */
-#define E1000_KMRNCTRLSTA_DIAG_OFFSET	0x3    /* Kumeran Diagnostic */
-#define E1000_KMRNCTRLSTA_TIMEOUTS	0x4    /* Kumeran Timeouts */
-#define E1000_KMRNCTRLSTA_INBAND_PARAM	0x9    /* Kumeran InBand Parameters */
-#define E1000_KMRNCTRLSTA_IBIST_DISABLE	0x0200 /* Kumeran IBIST Disable */
-#define E1000_KMRNCTRLSTA_DIAG_NELPBK	0x1000 /* Nearend Loopback mode */
-#define E1000_KMRNCTRLSTA_K1_CONFIG	0x7
-#define E1000_KMRNCTRLSTA_K1_ENABLE	0x0002
-#define E1000_KMRNCTRLSTA_HD_CTRL	0x10   /* Kumeran HD Control */
-
-#define IFE_PHY_EXTENDED_STATUS_CONTROL	0x10
-#define IFE_PHY_SPECIAL_CONTROL		0x11 /* 100BaseTx PHY Special Control */
-#define IFE_PHY_SPECIAL_CONTROL_LED	0x1B /* PHY Special and LED Control */
-#define IFE_PHY_MDIX_CONTROL		0x1C /* MDI/MDI-X Control */
-
-/* IFE PHY Extended Status Control */
-#define IFE_PESC_POLARITY_REVERSED	0x0100
-
-/* IFE PHY Special Control */
-#define IFE_PSC_AUTO_POLARITY_DISABLE		0x0010
-#define IFE_PSC_FORCE_POLARITY			0x0020
-
-/* IFE PHY Special Control and LED Control */
-#define IFE_PSCL_PROBE_MODE		0x0020
-#define IFE_PSCL_PROBE_LEDS_OFF		0x0006 /* Force LEDs 0 and 2 off */
-#define IFE_PSCL_PROBE_LEDS_ON		0x0007 /* Force LEDs 0 and 2 on */
-
-/* IFE PHY MDIX Control */
-#define IFE_PMC_MDIX_STATUS	0x0020 /* 1=MDI-X, 0=MDI */
-#define IFE_PMC_FORCE_MDIX	0x0040 /* 1=force MDI-X, 0=force MDI */
-#define IFE_PMC_AUTO_MDIX	0x0080 /* 1=enable auto MDI/MDI-X, 0=disable */
-
-#define E1000_CABLE_LENGTH_UNDEFINED	0xFF
-
-#define E1000_DEV_ID_82571EB_COPPER		0x105E
-#define E1000_DEV_ID_82571EB_FIBER		0x105F
-#define E1000_DEV_ID_82571EB_SERDES		0x1060
-#define E1000_DEV_ID_82571EB_QUAD_COPPER	0x10A4
-#define E1000_DEV_ID_82571PT_QUAD_COPPER	0x10D5
-#define E1000_DEV_ID_82571EB_QUAD_FIBER		0x10A5
-#define E1000_DEV_ID_82571EB_QUAD_COPPER_LP	0x10BC
-#define E1000_DEV_ID_82571EB_SERDES_DUAL	0x10D9
-#define E1000_DEV_ID_82571EB_SERDES_QUAD	0x10DA
-#define E1000_DEV_ID_82572EI_COPPER		0x107D
-#define E1000_DEV_ID_82572EI_FIBER		0x107E
-#define E1000_DEV_ID_82572EI_SERDES		0x107F
-#define E1000_DEV_ID_82572EI			0x10B9
-#define E1000_DEV_ID_82573E			0x108B
-#define E1000_DEV_ID_82573E_IAMT		0x108C
-#define E1000_DEV_ID_82573L			0x109A
-#define E1000_DEV_ID_82574L			0x10D3
-#define E1000_DEV_ID_82574LA			0x10F6
-#define E1000_DEV_ID_82583V                     0x150C
-
-#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT	0x1096
-#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT	0x1098
-#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT	0x10BA
-#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT	0x10BB
-
-#define E1000_DEV_ID_ICH8_82567V_3		0x1501
-#define E1000_DEV_ID_ICH8_IGP_M_AMT		0x1049
-#define E1000_DEV_ID_ICH8_IGP_AMT		0x104A
-#define E1000_DEV_ID_ICH8_IGP_C			0x104B
-#define E1000_DEV_ID_ICH8_IFE			0x104C
-#define E1000_DEV_ID_ICH8_IFE_GT		0x10C4
-#define E1000_DEV_ID_ICH8_IFE_G			0x10C5
-#define E1000_DEV_ID_ICH8_IGP_M			0x104D
-#define E1000_DEV_ID_ICH9_IGP_AMT		0x10BD
-#define E1000_DEV_ID_ICH9_BM			0x10E5
-#define E1000_DEV_ID_ICH9_IGP_M_AMT		0x10F5
-#define E1000_DEV_ID_ICH9_IGP_M			0x10BF
-#define E1000_DEV_ID_ICH9_IGP_M_V		0x10CB
-#define E1000_DEV_ID_ICH9_IGP_C			0x294C
-#define E1000_DEV_ID_ICH9_IFE			0x10C0
-#define E1000_DEV_ID_ICH9_IFE_GT		0x10C3
-#define E1000_DEV_ID_ICH9_IFE_G			0x10C2
-#define E1000_DEV_ID_ICH10_R_BM_LM		0x10CC
-#define E1000_DEV_ID_ICH10_R_BM_LF		0x10CD
-#define E1000_DEV_ID_ICH10_R_BM_V		0x10CE
-#define E1000_DEV_ID_ICH10_D_BM_LM		0x10DE
-#define E1000_DEV_ID_ICH10_D_BM_LF		0x10DF
-#define E1000_DEV_ID_ICH10_D_BM_V		0x1525
-#define E1000_DEV_ID_PCH_M_HV_LM		0x10EA
-#define E1000_DEV_ID_PCH_M_HV_LC		0x10EB
-#define E1000_DEV_ID_PCH_D_HV_DM		0x10EF
-#define E1000_DEV_ID_PCH_D_HV_DC		0x10F0
-#define E1000_DEV_ID_PCH2_LV_LM			0x1502
-#define E1000_DEV_ID_PCH2_LV_V			0x1503
-
-#define E1000_REVISION_4 4
-
-#define E1000_FUNC_1 1
-
-#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0   0
-#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1   3
-
-enum e1000_mac_type {
-	e1000_82571,
-	e1000_82572,
-	e1000_82573,
-	e1000_82574,
-	e1000_82583,
-	e1000_80003es2lan,
-	e1000_ich8lan,
-	e1000_ich9lan,
-	e1000_ich10lan,
-	e1000_pchlan,
-	e1000_pch2lan,
-};
-
-enum e1000_media_type {
-	e1000_media_type_unknown = 0,
-	e1000_media_type_copper = 1,
-	e1000_media_type_fiber = 2,
-	e1000_media_type_internal_serdes = 3,
-	e1000_num_media_types
-};
-
-enum e1000_nvm_type {
-	e1000_nvm_unknown = 0,
-	e1000_nvm_none,
-	e1000_nvm_eeprom_spi,
-	e1000_nvm_flash_hw,
-	e1000_nvm_flash_sw
-};
-
-enum e1000_nvm_override {
-	e1000_nvm_override_none = 0,
-	e1000_nvm_override_spi_small,
-	e1000_nvm_override_spi_large
-};
-
-enum e1000_phy_type {
-	e1000_phy_unknown = 0,
-	e1000_phy_none,
-	e1000_phy_m88,
-	e1000_phy_igp,
-	e1000_phy_igp_2,
-	e1000_phy_gg82563,
-	e1000_phy_igp_3,
-	e1000_phy_ife,
-	e1000_phy_bm,
-	e1000_phy_82578,
-	e1000_phy_82577,
-	e1000_phy_82579,
-};
-
-enum e1000_bus_width {
-	e1000_bus_width_unknown = 0,
-	e1000_bus_width_pcie_x1,
-	e1000_bus_width_pcie_x2,
-	e1000_bus_width_pcie_x4 = 4,
-	e1000_bus_width_32,
-	e1000_bus_width_64,
-	e1000_bus_width_reserved
-};
-
-enum e1000_1000t_rx_status {
-	e1000_1000t_rx_status_not_ok = 0,
-	e1000_1000t_rx_status_ok,
-	e1000_1000t_rx_status_undefined = 0xFF
-};
-
-enum e1000_rev_polarity{
-	e1000_rev_polarity_normal = 0,
-	e1000_rev_polarity_reversed,
-	e1000_rev_polarity_undefined = 0xFF
-};
-
-enum e1000_fc_mode {
-	e1000_fc_none = 0,
-	e1000_fc_rx_pause,
-	e1000_fc_tx_pause,
-	e1000_fc_full,
-	e1000_fc_default = 0xFF
-};
-
-enum e1000_ms_type {
-	e1000_ms_hw_default = 0,
-	e1000_ms_force_master,
-	e1000_ms_force_slave,
-	e1000_ms_auto
-};
-
-enum e1000_smart_speed {
-	e1000_smart_speed_default = 0,
-	e1000_smart_speed_on,
-	e1000_smart_speed_off
-};
-
-enum e1000_serdes_link_state {
-	e1000_serdes_link_down = 0,
-	e1000_serdes_link_autoneg_progress,
-	e1000_serdes_link_autoneg_complete,
-	e1000_serdes_link_forced_up
-};
-
-/* Receive Descriptor */
-struct e1000_rx_desc {
-	__le64 buffer_addr; /* Address of the descriptor's data buffer */
-	__le16 length;      /* Length of data DMAed into data buffer */
-	__le16 csum;	/* Packet checksum */
-	u8  status;      /* Descriptor status */
-	u8  errors;      /* Descriptor Errors */
-	__le16 special;
-};
-
-/* Receive Descriptor - Extended */
-union e1000_rx_desc_extended {
-	struct {
-		__le64 buffer_addr;
-		__le64 reserved;
-	} read;
-	struct {
-		struct {
-			__le32 mrq;	      /* Multiple Rx Queues */
-			union {
-				__le32 rss;	    /* RSS Hash */
-				struct {
-					__le16 ip_id;  /* IP id */
-					__le16 csum;   /* Packet Checksum */
-				} csum_ip;
-			} hi_dword;
-		} lower;
-		struct {
-			__le32 status_error;     /* ext status/error */
-			__le16 length;
-			__le16 vlan;	     /* VLAN tag */
-		} upper;
-	} wb;  /* writeback */
-};
-
-#define MAX_PS_BUFFERS 4
-/* Receive Descriptor - Packet Split */
-union e1000_rx_desc_packet_split {
-	struct {
-		/* one buffer for protocol header(s), three data buffers */
-		__le64 buffer_addr[MAX_PS_BUFFERS];
-	} read;
-	struct {
-		struct {
-			__le32 mrq;	      /* Multiple Rx Queues */
-			union {
-				__le32 rss;	      /* RSS Hash */
-				struct {
-					__le16 ip_id;    /* IP id */
-					__le16 csum;     /* Packet Checksum */
-				} csum_ip;
-			} hi_dword;
-		} lower;
-		struct {
-			__le32 status_error;     /* ext status/error */
-			__le16 length0;	  /* length of buffer 0 */
-			__le16 vlan;	     /* VLAN tag */
-		} middle;
-		struct {
-			__le16 header_status;
-			__le16 length[3];	/* length of buffers 1-3 */
-		} upper;
-		__le64 reserved;
-	} wb; /* writeback */
-};
-
-/* Transmit Descriptor */
-struct e1000_tx_desc {
-	__le64 buffer_addr;      /* Address of the descriptor's data buffer */
-	union {
-		__le32 data;
-		struct {
-			__le16 length;    /* Data buffer length */
-			u8 cso;	/* Checksum offset */
-			u8 cmd;	/* Descriptor control */
-		} flags;
-	} lower;
-	union {
-		__le32 data;
-		struct {
-			u8 status;     /* Descriptor status */
-			u8 css;	/* Checksum start */
-			__le16 special;
-		} fields;
-	} upper;
-};
-
-/* Offload Context Descriptor */
-struct e1000_context_desc {
-	union {
-		__le32 ip_config;
-		struct {
-			u8 ipcss;      /* IP checksum start */
-			u8 ipcso;      /* IP checksum offset */
-			__le16 ipcse;     /* IP checksum end */
-		} ip_fields;
-	} lower_setup;
-	union {
-		__le32 tcp_config;
-		struct {
-			u8 tucss;      /* TCP checksum start */
-			u8 tucso;      /* TCP checksum offset */
-			__le16 tucse;     /* TCP checksum end */
-		} tcp_fields;
-	} upper_setup;
-	__le32 cmd_and_length;
-	union {
-		__le32 data;
-		struct {
-			u8 status;     /* Descriptor status */
-			u8 hdr_len;    /* Header length */
-			__le16 mss;       /* Maximum segment size */
-		} fields;
-	} tcp_seg_setup;
-};
-
-/* Offload data descriptor */
-struct e1000_data_desc {
-	__le64 buffer_addr;   /* Address of the descriptor's buffer address */
-	union {
-		__le32 data;
-		struct {
-			__le16 length;    /* Data buffer length */
-			u8 typ_len_ext;
-			u8 cmd;
-		} flags;
-	} lower;
-	union {
-		__le32 data;
-		struct {
-			u8 status;     /* Descriptor status */
-			u8 popts;      /* Packet Options */
-			__le16 special;   /* */
-		} fields;
-	} upper;
-};
-
-/* Statistics counters collected by the MAC */
-struct e1000_hw_stats {
-	u64 crcerrs;
-	u64 algnerrc;
-	u64 symerrs;
-	u64 rxerrc;
-	u64 mpc;
-	u64 scc;
-	u64 ecol;
-	u64 mcc;
-	u64 latecol;
-	u64 colc;
-	u64 dc;
-	u64 tncrs;
-	u64 sec;
-	u64 cexterr;
-	u64 rlec;
-	u64 xonrxc;
-	u64 xontxc;
-	u64 xoffrxc;
-	u64 xofftxc;
-	u64 fcruc;
-	u64 prc64;
-	u64 prc127;
-	u64 prc255;
-	u64 prc511;
-	u64 prc1023;
-	u64 prc1522;
-	u64 gprc;
-	u64 bprc;
-	u64 mprc;
-	u64 gptc;
-	u64 gorc;
-	u64 gotc;
-	u64 rnbc;
-	u64 ruc;
-	u64 rfc;
-	u64 roc;
-	u64 rjc;
-	u64 mgprc;
-	u64 mgpdc;
-	u64 mgptc;
-	u64 tor;
-	u64 tot;
-	u64 tpr;
-	u64 tpt;
-	u64 ptc64;
-	u64 ptc127;
-	u64 ptc255;
-	u64 ptc511;
-	u64 ptc1023;
-	u64 ptc1522;
-	u64 mptc;
-	u64 bptc;
-	u64 tsctc;
-	u64 tsctfc;
-	u64 iac;
-	u64 icrxptc;
-	u64 icrxatc;
-	u64 ictxptc;
-	u64 ictxatc;
-	u64 ictxqec;
-	u64 ictxqmtc;
-	u64 icrxdmtc;
-	u64 icrxoc;
-};
-
-struct e1000_phy_stats {
-	u32 idle_errors;
-	u32 receive_errors;
-};
-
-struct e1000_host_mng_dhcp_cookie {
-	u32 signature;
-	u8  status;
-	u8  reserved0;
-	u16 vlan_id;
-	u32 reserved1;
-	u16 reserved2;
-	u8  reserved3;
-	u8  checksum;
-};
-
-/* Host Interface "Rev 1" */
-struct e1000_host_command_header {
-	u8 command_id;
-	u8 command_length;
-	u8 command_options;
-	u8 checksum;
-};
-
-#define E1000_HI_MAX_DATA_LENGTH     252
-struct e1000_host_command_info {
-	struct e1000_host_command_header command_header;
-	u8 command_data[E1000_HI_MAX_DATA_LENGTH];
-};
-
-/* Host Interface "Rev 2" */
-struct e1000_host_mng_command_header {
-	u8  command_id;
-	u8  checksum;
-	u16 reserved1;
-	u16 reserved2;
-	u16 command_length;
-};
-
-#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8
-struct e1000_host_mng_command_info {
-	struct e1000_host_mng_command_header command_header;
-	u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH];
-};
-
-/* Function pointers and static data for the MAC. */
-struct e1000_mac_operations {
-	s32  (*id_led_init)(struct e1000_hw *);
-	s32  (*blink_led)(struct e1000_hw *);
-	bool (*check_mng_mode)(struct e1000_hw *);
-	s32  (*check_for_link)(struct e1000_hw *);
-	s32  (*cleanup_led)(struct e1000_hw *);
-	void (*clear_hw_cntrs)(struct e1000_hw *);
-	void (*clear_vfta)(struct e1000_hw *);
-	s32  (*get_bus_info)(struct e1000_hw *);
-	void (*set_lan_id)(struct e1000_hw *);
-	s32  (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
-	s32  (*led_on)(struct e1000_hw *);
-	s32  (*led_off)(struct e1000_hw *);
-	void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32);
-	s32  (*reset_hw)(struct e1000_hw *);
-	s32  (*init_hw)(struct e1000_hw *);
-	s32  (*setup_link)(struct e1000_hw *);
-	s32  (*setup_physical_interface)(struct e1000_hw *);
-	s32  (*setup_led)(struct e1000_hw *);
-	void (*write_vfta)(struct e1000_hw *, u32, u32);
-	s32  (*read_mac_addr)(struct e1000_hw *);
-};
-
-/*
- * When to use various PHY register access functions:
- *
- *                 Func   Caller
- *   Function      Does   Does    When to use
- *   ~~~~~~~~~~~~  ~~~~~  ~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *   X_reg         L,P,A  n/a     for simple PHY reg accesses
- *   X_reg_locked  P,A    L       for multiple accesses of different regs
- *                                on different pages
- *   X_reg_page    A      L,P     for multiple accesses of different regs
- *                                on the same page
- *
- * Where X=[read|write], L=locking, P=sets page, A=register access
- *
- */
-struct e1000_phy_operations {
-	s32  (*acquire)(struct e1000_hw *);
-	s32  (*cfg_on_link_up)(struct e1000_hw *);
-	s32  (*check_polarity)(struct e1000_hw *);
-	s32  (*check_reset_block)(struct e1000_hw *);
-	s32  (*commit)(struct e1000_hw *);
-	s32  (*force_speed_duplex)(struct e1000_hw *);
-	s32  (*get_cfg_done)(struct e1000_hw *hw);
-	s32  (*get_cable_length)(struct e1000_hw *);
-	s32  (*get_info)(struct e1000_hw *);
-	s32  (*set_page)(struct e1000_hw *, u16);
-	s32  (*read_reg)(struct e1000_hw *, u32, u16 *);
-	s32  (*read_reg_locked)(struct e1000_hw *, u32, u16 *);
-	s32  (*read_reg_page)(struct e1000_hw *, u32, u16 *);
-	void (*release)(struct e1000_hw *);
-	s32  (*reset)(struct e1000_hw *);
-	s32  (*set_d0_lplu_state)(struct e1000_hw *, bool);
-	s32  (*set_d3_lplu_state)(struct e1000_hw *, bool);
-	s32  (*write_reg)(struct e1000_hw *, u32, u16);
-	s32  (*write_reg_locked)(struct e1000_hw *, u32, u16);
-	s32  (*write_reg_page)(struct e1000_hw *, u32, u16);
-	void (*power_up)(struct e1000_hw *);
-	void (*power_down)(struct e1000_hw *);
-};
-
-/* Function pointers for the NVM. */
-struct e1000_nvm_operations {
-	s32  (*acquire)(struct e1000_hw *);
-	s32  (*read)(struct e1000_hw *, u16, u16, u16 *);
-	void (*release)(struct e1000_hw *);
-	s32  (*update)(struct e1000_hw *);
-	s32  (*valid_led_default)(struct e1000_hw *, u16 *);
-	s32  (*validate)(struct e1000_hw *);
-	s32  (*write)(struct e1000_hw *, u16, u16, u16 *);
-};
-
-struct e1000_mac_info {
-	struct e1000_mac_operations ops;
-	u8 addr[ETH_ALEN];
-	u8 perm_addr[ETH_ALEN];
-
-	enum e1000_mac_type type;
-
-	u32 collision_delta;
-	u32 ledctl_default;
-	u32 ledctl_mode1;
-	u32 ledctl_mode2;
-	u32 mc_filter_type;
-	u32 tx_packet_delta;
-	u32 txcw;
-
-	u16 current_ifs_val;
-	u16 ifs_max_val;
-	u16 ifs_min_val;
-	u16 ifs_ratio;
-	u16 ifs_step_size;
-	u16 mta_reg_count;
-
-	/* Maximum size of the MTA register table in all supported adapters */
-	#define MAX_MTA_REG 128
-	u32 mta_shadow[MAX_MTA_REG];
-	u16 rar_entry_count;
-
-	u8  forced_speed_duplex;
-
-	bool adaptive_ifs;
-	bool has_fwsm;
-	bool arc_subsystem_valid;
-	bool autoneg;
-	bool autoneg_failed;
-	bool get_link_status;
-	bool in_ifs_mode;
-	bool serdes_has_link;
-	bool tx_pkt_filtering;
-	enum e1000_serdes_link_state serdes_link_state;
-};
-
-struct e1000_phy_info {
-	struct e1000_phy_operations ops;
-
-	enum e1000_phy_type type;
-
-	enum e1000_1000t_rx_status local_rx;
-	enum e1000_1000t_rx_status remote_rx;
-	enum e1000_ms_type ms_type;
-	enum e1000_ms_type original_ms_type;
-	enum e1000_rev_polarity cable_polarity;
-	enum e1000_smart_speed smart_speed;
-
-	u32 addr;
-	u32 id;
-	u32 reset_delay_us; /* in usec */
-	u32 revision;
-
-	enum e1000_media_type media_type;
-
-	u16 autoneg_advertised;
-	u16 autoneg_mask;
-	u16 cable_length;
-	u16 max_cable_length;
-	u16 min_cable_length;
-
-	u8 mdix;
-
-	bool disable_polarity_correction;
-	bool is_mdix;
-	bool polarity_correction;
-	bool speed_downgraded;
-	bool autoneg_wait_to_complete;
-};
-
-struct e1000_nvm_info {
-	struct e1000_nvm_operations ops;
-
-	enum e1000_nvm_type type;
-	enum e1000_nvm_override override;
-
-	u32 flash_bank_size;
-	u32 flash_base_addr;
-
-	u16 word_size;
-	u16 delay_usec;
-	u16 address_bits;
-	u16 opcode_bits;
-	u16 page_size;
-};
-
-struct e1000_bus_info {
-	enum e1000_bus_width width;
-
-	u16 func;
-};
-
-struct e1000_fc_info {
-	u32 high_water;          /* Flow control high-water mark */
-	u32 low_water;           /* Flow control low-water mark */
-	u16 pause_time;          /* Flow control pause timer */
-	u16 refresh_time;        /* Flow control refresh timer */
-	bool send_xon;           /* Flow control send XON */
-	bool strict_ieee;        /* Strict IEEE mode */
-	enum e1000_fc_mode current_mode; /* FC mode in effect */
-	enum e1000_fc_mode requested_mode; /* FC mode requested by caller */
-};
-
-struct e1000_dev_spec_82571 {
-	bool laa_is_present;
-	u32 smb_counter;
-};
-
-struct e1000_dev_spec_80003es2lan {
-	bool  mdic_wa_enable;
-};
-
-struct e1000_shadow_ram {
-	u16  value;
-	bool modified;
-};
-
-#define E1000_ICH8_SHADOW_RAM_WORDS		2048
-
-struct e1000_dev_spec_ich8lan {
-	bool kmrn_lock_loss_workaround_enabled;
-	struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS];
-	bool nvm_k1_enabled;
-	bool eee_disable;
-};
-
-struct e1000_hw {
-	struct e1000_adapter *adapter;
-
-	u8 __iomem *hw_addr;
-	u8 __iomem *flash_address;
-
-	struct e1000_mac_info  mac;
-	struct e1000_fc_info   fc;
-	struct e1000_phy_info  phy;
-	struct e1000_nvm_info  nvm;
-	struct e1000_bus_info  bus;
-	struct e1000_host_mng_dhcp_cookie mng_cookie;
-
-	union {
-		struct e1000_dev_spec_82571	e82571;
-		struct e1000_dev_spec_80003es2lan e80003es2lan;
-		struct e1000_dev_spec_ich8lan	ich8lan;
-	} dev_spec;
-};
-
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/e1000e/ich8lan.c linux-libre-3.2-gnu/drivers/net/e1000e/ich8lan.c
--- linux-libre-3.1-gnu/drivers/net/e1000e/ich8lan.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000e/ich8lan.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,4150 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  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,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-/*
- * 82562G 10/100 Network Connection
- * 82562G-2 10/100 Network Connection
- * 82562GT 10/100 Network Connection
- * 82562GT-2 10/100 Network Connection
- * 82562V 10/100 Network Connection
- * 82562V-2 10/100 Network Connection
- * 82566DC-2 Gigabit Network Connection
- * 82566DC Gigabit Network Connection
- * 82566DM-2 Gigabit Network Connection
- * 82566DM Gigabit Network Connection
- * 82566MC Gigabit Network Connection
- * 82566MM Gigabit Network Connection
- * 82567LM Gigabit Network Connection
- * 82567LF Gigabit Network Connection
- * 82567V Gigabit Network Connection
- * 82567LM-2 Gigabit Network Connection
- * 82567LF-2 Gigabit Network Connection
- * 82567V-2 Gigabit Network Connection
- * 82567LF-3 Gigabit Network Connection
- * 82567LM-3 Gigabit Network Connection
- * 82567LM-4 Gigabit Network Connection
- * 82577LM Gigabit Network Connection
- * 82577LC Gigabit Network Connection
- * 82578DM Gigabit Network Connection
- * 82578DC Gigabit Network Connection
- * 82579LM Gigabit Network Connection
- * 82579V Gigabit Network Connection
- */
-
-#include "e1000.h"
-
-#define ICH_FLASH_GFPREG		0x0000
-#define ICH_FLASH_HSFSTS		0x0004
-#define ICH_FLASH_HSFCTL		0x0006
-#define ICH_FLASH_FADDR			0x0008
-#define ICH_FLASH_FDATA0		0x0010
-#define ICH_FLASH_PR0			0x0074
-
-#define ICH_FLASH_READ_COMMAND_TIMEOUT	500
-#define ICH_FLASH_WRITE_COMMAND_TIMEOUT	500
-#define ICH_FLASH_ERASE_COMMAND_TIMEOUT	3000000
-#define ICH_FLASH_LINEAR_ADDR_MASK	0x00FFFFFF
-#define ICH_FLASH_CYCLE_REPEAT_COUNT	10
-
-#define ICH_CYCLE_READ			0
-#define ICH_CYCLE_WRITE			2
-#define ICH_CYCLE_ERASE			3
-
-#define FLASH_GFPREG_BASE_MASK		0x1FFF
-#define FLASH_SECTOR_ADDR_SHIFT		12
-
-#define ICH_FLASH_SEG_SIZE_256		256
-#define ICH_FLASH_SEG_SIZE_4K		4096
-#define ICH_FLASH_SEG_SIZE_8K		8192
-#define ICH_FLASH_SEG_SIZE_64K		65536
-
-
-#define E1000_ICH_FWSM_RSPCIPHY	0x00000040 /* Reset PHY on PCI Reset */
-/* FW established a valid mode */
-#define E1000_ICH_FWSM_FW_VALID		0x00008000
-
-#define E1000_ICH_MNG_IAMT_MODE		0x2
-
-#define ID_LED_DEFAULT_ICH8LAN  ((ID_LED_DEF1_DEF2 << 12) | \
-				 (ID_LED_DEF1_OFF2 <<  8) | \
-				 (ID_LED_DEF1_ON2  <<  4) | \
-				 (ID_LED_DEF1_DEF2))
-
-#define E1000_ICH_NVM_SIG_WORD		0x13
-#define E1000_ICH_NVM_SIG_MASK		0xC000
-#define E1000_ICH_NVM_VALID_SIG_MASK    0xC0
-#define E1000_ICH_NVM_SIG_VALUE         0x80
-
-#define E1000_ICH8_LAN_INIT_TIMEOUT	1500
-
-#define E1000_FEXTNVM_SW_CONFIG		1
-#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M :/ */
-
-#define E1000_FEXTNVM4_BEACON_DURATION_MASK    0x7
-#define E1000_FEXTNVM4_BEACON_DURATION_8USEC   0x7
-#define E1000_FEXTNVM4_BEACON_DURATION_16USEC  0x3
-
-#define PCIE_ICH8_SNOOP_ALL		PCIE_NO_SNOOP_ALL
-
-#define E1000_ICH_RAR_ENTRIES		7
-
-#define PHY_PAGE_SHIFT 5
-#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \
-			   ((reg) & MAX_PHY_REG_ADDRESS))
-#define IGP3_KMRN_DIAG  PHY_REG(770, 19) /* KMRN Diagnostic */
-#define IGP3_VR_CTRL    PHY_REG(776, 18) /* Voltage Regulator Control */
-
-#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS	0x0002
-#define IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK 0x0300
-#define IGP3_VR_CTRL_MODE_SHUTDOWN	0x0200
-
-#define HV_LED_CONFIG		PHY_REG(768, 30) /* LED Configuration */
-
-#define SW_FLAG_TIMEOUT    1000 /* SW Semaphore flag timeout in milliseconds */
-
-/* SMBus Address Phy Register */
-#define HV_SMB_ADDR            PHY_REG(768, 26)
-#define HV_SMB_ADDR_MASK       0x007F
-#define HV_SMB_ADDR_PEC_EN     0x0200
-#define HV_SMB_ADDR_VALID      0x0080
-
-/* PHY Power Management Control */
-#define HV_PM_CTRL		PHY_REG(770, 17)
-
-/* PHY Low Power Idle Control */
-#define I82579_LPI_CTRL				PHY_REG(772, 20)
-#define I82579_LPI_CTRL_ENABLE_MASK		0x6000
-#define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT	0x80
-
-/* 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
-#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17
-
-/* OEM Bits Phy Register */
-#define HV_OEM_BITS            PHY_REG(768, 25)
-#define HV_OEM_BITS_LPLU       0x0004 /* Low Power Link Up */
-#define HV_OEM_BITS_GBE_DIS    0x0040 /* Gigabit Disable */
-#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */
-
-#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */
-#define E1000_NVM_K1_ENABLE 0x1  /* NVM Enable K1 bit */
-
-/* KMRN Mode Control */
-#define HV_KMRN_MODE_CTRL      PHY_REG(769, 16)
-#define HV_KMRN_MDIO_SLOW      0x0400
-
-/* KMRN FIFO Control and Status */
-#define HV_KMRN_FIFO_CTRLSTA                  PHY_REG(770, 16)
-#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK    0x7000
-#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT   12
-
-/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
-/* Offset 04h HSFSTS */
-union ich8_hws_flash_status {
-	struct ich8_hsfsts {
-		u16 flcdone    :1; /* bit 0 Flash Cycle Done */
-		u16 flcerr     :1; /* bit 1 Flash Cycle Error */
-		u16 dael       :1; /* bit 2 Direct Access error Log */
-		u16 berasesz   :2; /* bit 4:3 Sector Erase Size */
-		u16 flcinprog  :1; /* bit 5 flash cycle in Progress */
-		u16 reserved1  :2; /* bit 13:6 Reserved */
-		u16 reserved2  :6; /* bit 13:6 Reserved */
-		u16 fldesvalid :1; /* bit 14 Flash Descriptor Valid */
-		u16 flockdn    :1; /* bit 15 Flash Config Lock-Down */
-	} hsf_status;
-	u16 regval;
-};
-
-/* ICH GbE Flash Hardware Sequencing Flash control Register bit breakdown */
-/* Offset 06h FLCTL */
-union ich8_hws_flash_ctrl {
-	struct ich8_hsflctl {
-		u16 flcgo      :1;   /* 0 Flash Cycle Go */
-		u16 flcycle    :2;   /* 2:1 Flash Cycle */
-		u16 reserved   :5;   /* 7:3 Reserved  */
-		u16 fldbcount  :2;   /* 9:8 Flash Data Byte Count */
-		u16 flockdn    :6;   /* 15:10 Reserved */
-	} hsf_ctrl;
-	u16 regval;
-};
-
-/* ICH Flash Region Access Permissions */
-union ich8_hws_flash_regacc {
-	struct ich8_flracc {
-		u32 grra      :8; /* 0:7 GbE region Read Access */
-		u32 grwa      :8; /* 8:15 GbE region Write Access */
-		u32 gmrag     :8; /* 23:16 GbE Master Read Access Grant */
-		u32 gmwag     :8; /* 31:24 GbE Master Write Access Grant */
-	} hsf_flregacc;
-	u16 regval;
-};
-
-/* ICH Flash Protected Region */
-union ich8_flash_protected_range {
-	struct ich8_pr {
-		u32 base:13;     /* 0:12 Protected Range Base */
-		u32 reserved1:2; /* 13:14 Reserved */
-		u32 rpe:1;       /* 15 Read Protection Enable */
-		u32 limit:13;    /* 16:28 Protected Range Limit */
-		u32 reserved2:2; /* 29:30 Reserved */
-		u32 wpe:1;       /* 31 Write Protection Enable */
-	} range;
-	u32 regval;
-};
-
-static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw);
-static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw);
-static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw);
-static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank);
-static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
-						u32 offset, u8 byte);
-static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
-					 u8 *data);
-static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset,
-					 u16 *data);
-static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
-					 u8 size, u16 *data);
-static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw);
-static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw);
-static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw);
-static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw);
-static s32 e1000_led_on_ich8lan(struct e1000_hw *hw);
-static s32 e1000_led_off_ich8lan(struct e1000_hw *hw);
-static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw);
-static s32 e1000_setup_led_pchlan(struct e1000_hw *hw);
-static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw);
-static s32 e1000_led_on_pchlan(struct e1000_hw *hw);
-static s32 e1000_led_off_pchlan(struct e1000_hw *hw);
-static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active);
-static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw);
-static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw);
-static s32  e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link);
-static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw);
-static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);
-static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw);
-static s32 e1000_k1_workaround_lv(struct e1000_hw *hw);
-static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate);
-
-static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg)
-{
-	return readw(hw->flash_address + reg);
-}
-
-static inline u32 __er32flash(struct e1000_hw *hw, unsigned long reg)
-{
-	return readl(hw->flash_address + reg);
-}
-
-static inline void __ew16flash(struct e1000_hw *hw, unsigned long reg, u16 val)
-{
-	writew(val, hw->flash_address + reg);
-}
-
-static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val)
-{
-	writel(val, hw->flash_address + reg);
-}
-
-#define er16flash(reg)		__er16flash(hw, (reg))
-#define er32flash(reg)		__er32flash(hw, (reg))
-#define ew16flash(reg,val)	__ew16flash(hw, (reg), (val))
-#define ew32flash(reg,val)	__ew32flash(hw, (reg), (val))
-
-static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw)
-{
-	u32 ctrl;
-
-	ctrl = er32(CTRL);
-	ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
-	ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
-	ew32(CTRL, ctrl);
-	e1e_flush();
-	udelay(10);
-	ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
-	ew32(CTRL, ctrl);
-}
-
-/**
- *  e1000_init_phy_params_pchlan - Initialize PHY function pointers
- *  @hw: pointer to the HW structure
- *
- *  Initialize family-specific PHY parameters and function pointers.
- **/
-static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	u32 fwsm;
-	s32 ret_val = 0;
-
-	phy->addr                     = 1;
-	phy->reset_delay_us           = 100;
-
-	phy->ops.set_page             = e1000_set_page_igp;
-	phy->ops.read_reg             = e1000_read_phy_reg_hv;
-	phy->ops.read_reg_locked      = e1000_read_phy_reg_hv_locked;
-	phy->ops.read_reg_page        = e1000_read_phy_reg_page_hv;
-	phy->ops.set_d0_lplu_state    = e1000_set_lplu_state_pchlan;
-	phy->ops.set_d3_lplu_state    = e1000_set_lplu_state_pchlan;
-	phy->ops.write_reg            = e1000_write_phy_reg_hv;
-	phy->ops.write_reg_locked     = e1000_write_phy_reg_hv_locked;
-	phy->ops.write_reg_page       = e1000_write_phy_reg_page_hv;
-	phy->ops.power_up             = e1000_power_up_phy_copper;
-	phy->ops.power_down           = e1000_power_down_phy_copper_ich8lan;
-	phy->autoneg_mask             = AUTONEG_ADVERTISE_SPEED_DEFAULT;
-
-	/*
-	 * The MAC-PHY interconnect may still be in SMBus mode
-	 * after Sx->S0.  If the manageability engine (ME) is
-	 * disabled, then toggle the LANPHYPC Value bit to force
-	 * the interconnect to PCIe mode.
-	 */
-	fwsm = er32(FWSM);
-	if (!(fwsm & E1000_ICH_FWSM_FW_VALID) && !e1000_check_reset_block(hw)) {
-		e1000_toggle_lanphypc_value_ich8lan(hw);
-		msleep(50);
-
-		/*
-		 * Gate automatic PHY configuration by hardware on
-		 * non-managed 82579
-		 */
-		if (hw->mac.type == e1000_pch2lan)
-			e1000_gate_hw_phy_config_ich8lan(hw, true);
-	}
-
-	/*
-	 * Reset the PHY before any access to it.  Doing so, ensures that
-	 * the PHY is in a known good state before we read/write PHY registers.
-	 * The generic reset is sufficient here, because we haven't determined
-	 * the PHY type yet.
-	 */
-	ret_val = e1000e_phy_hw_reset_generic(hw);
-	if (ret_val)
-		goto out;
-
-	/* Ungate automatic PHY configuration on non-managed 82579 */
-	if ((hw->mac.type == e1000_pch2lan) &&
-	    !(fwsm & E1000_ICH_FWSM_FW_VALID)) {
-		usleep_range(10000, 20000);
-		e1000_gate_hw_phy_config_ich8lan(hw, false);
-	}
-
-	phy->id = e1000_phy_unknown;
-	switch (hw->mac.type) {
-	default:
-		ret_val = e1000e_get_phy_id(hw);
-		if (ret_val)
-			goto out;
-		if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK))
-			break;
-		/* fall-through */
-	case e1000_pch2lan:
-		/*
-		 * In case the PHY needs to be in mdio slow mode,
-		 * set slow mode and try to get the PHY id again.
-		 */
-		ret_val = e1000_set_mdio_slow_mode_hv(hw);
-		if (ret_val)
-			goto out;
-		ret_val = e1000e_get_phy_id(hw);
-		if (ret_val)
-			goto out;
-		break;
-	}
-	phy->type = e1000e_get_phy_type_from_id(phy->id);
-
-	switch (phy->type) {
-	case e1000_phy_82577:
-	case e1000_phy_82579:
-		phy->ops.check_polarity = e1000_check_polarity_82577;
-		phy->ops.force_speed_duplex =
-		    e1000_phy_force_speed_duplex_82577;
-		phy->ops.get_cable_length = e1000_get_cable_length_82577;
-		phy->ops.get_info = e1000_get_phy_info_82577;
-		phy->ops.commit = e1000e_phy_sw_reset;
-		break;
-	case e1000_phy_82578:
-		phy->ops.check_polarity = e1000_check_polarity_m88;
-		phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_m88;
-		phy->ops.get_cable_length = e1000e_get_cable_length_m88;
-		phy->ops.get_info = e1000e_get_phy_info_m88;
-		break;
-	default:
-		ret_val = -E1000_ERR_PHY;
-		break;
-	}
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_init_phy_params_ich8lan - Initialize PHY function pointers
- *  @hw: pointer to the HW structure
- *
- *  Initialize family-specific PHY parameters and function pointers.
- **/
-static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 i = 0;
-
-	phy->addr			= 1;
-	phy->reset_delay_us		= 100;
-
-	phy->ops.power_up               = e1000_power_up_phy_copper;
-	phy->ops.power_down             = e1000_power_down_phy_copper_ich8lan;
-
-	/*
-	 * We may need to do this twice - once for IGP and if that fails,
-	 * we'll set BM func pointers and try again
-	 */
-	ret_val = e1000e_determine_phy_address(hw);
-	if (ret_val) {
-		phy->ops.write_reg = e1000e_write_phy_reg_bm;
-		phy->ops.read_reg  = e1000e_read_phy_reg_bm;
-		ret_val = e1000e_determine_phy_address(hw);
-		if (ret_val) {
-			e_dbg("Cannot determine PHY addr. Erroring out\n");
-			return ret_val;
-		}
-	}
-
-	phy->id = 0;
-	while ((e1000_phy_unknown == e1000e_get_phy_type_from_id(phy->id)) &&
-	       (i++ < 100)) {
-		usleep_range(1000, 2000);
-		ret_val = e1000e_get_phy_id(hw);
-		if (ret_val)
-			return ret_val;
-	}
-
-	/* Verify phy id */
-	switch (phy->id) {
-	case IGP03E1000_E_PHY_ID:
-		phy->type = e1000_phy_igp_3;
-		phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
-		phy->ops.read_reg_locked = e1000e_read_phy_reg_igp_locked;
-		phy->ops.write_reg_locked = e1000e_write_phy_reg_igp_locked;
-		phy->ops.get_info = e1000e_get_phy_info_igp;
-		phy->ops.check_polarity = e1000_check_polarity_igp;
-		phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_igp;
-		break;
-	case IFE_E_PHY_ID:
-	case IFE_PLUS_E_PHY_ID:
-	case IFE_C_E_PHY_ID:
-		phy->type = e1000_phy_ife;
-		phy->autoneg_mask = E1000_ALL_NOT_GIG;
-		phy->ops.get_info = e1000_get_phy_info_ife;
-		phy->ops.check_polarity = e1000_check_polarity_ife;
-		phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_ife;
-		break;
-	case BME1000_E_PHY_ID:
-		phy->type = e1000_phy_bm;
-		phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
-		phy->ops.read_reg = e1000e_read_phy_reg_bm;
-		phy->ops.write_reg = e1000e_write_phy_reg_bm;
-		phy->ops.commit = e1000e_phy_sw_reset;
-		phy->ops.get_info = e1000e_get_phy_info_m88;
-		phy->ops.check_polarity = e1000_check_polarity_m88;
-		phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_m88;
-		break;
-	default:
-		return -E1000_ERR_PHY;
-		break;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_init_nvm_params_ich8lan - Initialize NVM function pointers
- *  @hw: pointer to the HW structure
- *
- *  Initialize family-specific NVM parameters and function
- *  pointers.
- **/
-static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
-{
-	struct e1000_nvm_info *nvm = &hw->nvm;
-	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
-	u32 gfpreg, sector_base_addr, sector_end_addr;
-	u16 i;
-
-	/* Can't read flash registers if the register set isn't mapped. */
-	if (!hw->flash_address) {
-		e_dbg("ERROR: Flash registers not mapped\n");
-		return -E1000_ERR_CONFIG;
-	}
-
-	nvm->type = e1000_nvm_flash_sw;
-
-	gfpreg = er32flash(ICH_FLASH_GFPREG);
-
-	/*
-	 * sector_X_addr is a "sector"-aligned address (4096 bytes)
-	 * Add 1 to sector_end_addr since this sector is included in
-	 * the overall size.
-	 */
-	sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK;
-	sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1;
-
-	/* flash_base_addr is byte-aligned */
-	nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT;
-
-	/*
-	 * find total size of the NVM, then cut in half since the total
-	 * size represents two separate NVM banks.
-	 */
-	nvm->flash_bank_size = (sector_end_addr - sector_base_addr)
-				<< FLASH_SECTOR_ADDR_SHIFT;
-	nvm->flash_bank_size /= 2;
-	/* Adjust to word count */
-	nvm->flash_bank_size /= sizeof(u16);
-
-	nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS;
-
-	/* Clear shadow ram */
-	for (i = 0; i < nvm->word_size; i++) {
-		dev_spec->shadow_ram[i].modified = false;
-		dev_spec->shadow_ram[i].value    = 0xFFFF;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_init_mac_params_ich8lan - Initialize MAC function pointers
- *  @hw: pointer to the HW structure
- *
- *  Initialize family-specific MAC parameters and function
- *  pointers.
- **/
-static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_mac_info *mac = &hw->mac;
-
-	/* Set media type function pointer */
-	hw->phy.media_type = e1000_media_type_copper;
-
-	/* Set mta register count */
-	mac->mta_reg_count = 32;
-	/* Set rar entry count */
-	mac->rar_entry_count = E1000_ICH_RAR_ENTRIES;
-	if (mac->type == e1000_ich8lan)
-		mac->rar_entry_count--;
-	/* FWSM register */
-	mac->has_fwsm = true;
-	/* ARC subsystem not supported */
-	mac->arc_subsystem_valid = false;
-	/* Adaptive IFS supported */
-	mac->adaptive_ifs = true;
-
-	/* LED operations */
-	switch (mac->type) {
-	case e1000_ich8lan:
-	case e1000_ich9lan:
-	case e1000_ich10lan:
-		/* check management mode */
-		mac->ops.check_mng_mode = e1000_check_mng_mode_ich8lan;
-		/* ID LED init */
-		mac->ops.id_led_init = e1000e_id_led_init;
-		/* blink LED */
-		mac->ops.blink_led = e1000e_blink_led_generic;
-		/* setup LED */
-		mac->ops.setup_led = e1000e_setup_led_generic;
-		/* cleanup LED */
-		mac->ops.cleanup_led = e1000_cleanup_led_ich8lan;
-		/* turn on/off LED */
-		mac->ops.led_on = e1000_led_on_ich8lan;
-		mac->ops.led_off = e1000_led_off_ich8lan;
-		break;
-	case e1000_pchlan:
-	case e1000_pch2lan:
-		/* check management mode */
-		mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
-		/* ID LED init */
-		mac->ops.id_led_init = e1000_id_led_init_pchlan;
-		/* setup LED */
-		mac->ops.setup_led = e1000_setup_led_pchlan;
-		/* cleanup LED */
-		mac->ops.cleanup_led = e1000_cleanup_led_pchlan;
-		/* turn on/off LED */
-		mac->ops.led_on = e1000_led_on_pchlan;
-		mac->ops.led_off = e1000_led_off_pchlan;
-		break;
-	default:
-		break;
-	}
-
-	/* Enable PCS Lock-loss workaround for ICH8 */
-	if (mac->type == e1000_ich8lan)
-		e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true);
-
-	/* Gate automatic PHY configuration by hardware on managed 82579 */
-	if ((mac->type == e1000_pch2lan) &&
-	    (er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
-		e1000_gate_hw_phy_config_ich8lan(hw, true);
-
-	return 0;
-}
-
-/**
- *  e1000_set_eee_pchlan - Enable/disable EEE support
- *  @hw: pointer to the HW structure
- *
- *  Enable/disable EEE based on setting in dev_spec structure.  The bits in
- *  the LPI Control register will remain set only if/when link is up.
- **/
-static s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
-{
-	s32 ret_val = 0;
-	u16 phy_reg;
-
-	if (hw->phy.type != e1000_phy_82579)
-		goto out;
-
-	ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg);
-	if (ret_val)
-		goto out;
-
-	if (hw->dev_spec.ich8lan.eee_disable)
-		phy_reg &= ~I82579_LPI_CTRL_ENABLE_MASK;
-	else
-		phy_reg |= I82579_LPI_CTRL_ENABLE_MASK;
-
-	ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_check_for_copper_link_ich8lan - Check for link (Copper)
- *  @hw: pointer to the HW structure
- *
- *  Checks to see of the link status of the hardware has changed.  If a
- *  change in link status has been detected, then we read the PHY registers
- *  to get the current speed/duplex if link exists.
- **/
-static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-	s32 ret_val;
-	bool link;
-	u16 phy_reg;
-
-	/*
-	 * We only want to go out to the PHY registers to see if Auto-Neg
-	 * has completed and/or if our link status has changed.  The
-	 * get_link_status flag is set upon receiving a Link Status
-	 * Change or Rx Sequence Error interrupt.
-	 */
-	if (!mac->get_link_status) {
-		ret_val = 0;
-		goto out;
-	}
-
-	/*
-	 * First we want to see if the MII Status Register reports
-	 * link.  If so, then we want to get the current speed/duplex
-	 * of the PHY.
-	 */
-	ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
-	if (ret_val)
-		goto out;
-
-	if (hw->mac.type == e1000_pchlan) {
-		ret_val = e1000_k1_gig_workaround_hv(hw, link);
-		if (ret_val)
-			goto out;
-	}
-
-	if (!link)
-		goto out; /* No link detected */
-
-	mac->get_link_status = false;
-
-	switch (hw->mac.type) {
-	case e1000_pch2lan:
-		ret_val = e1000_k1_workaround_lv(hw);
-		if (ret_val)
-			goto out;
-		/* fall-thru */
-	case e1000_pchlan:
-		if (hw->phy.type == e1000_phy_82578) {
-			ret_val = e1000_link_stall_workaround_hv(hw);
-			if (ret_val)
-				goto out;
-		}
-
-		/*
-		 * Workaround for PCHx parts in half-duplex:
-		 * Set the number of preambles removed from the packet
-		 * when it is passed from the PHY to the MAC to prevent
-		 * the MAC from misinterpreting the packet type.
-		 */
-		e1e_rphy(hw, HV_KMRN_FIFO_CTRLSTA, &phy_reg);
-		phy_reg &= ~HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK;
-
-		if ((er32(STATUS) & E1000_STATUS_FD) != E1000_STATUS_FD)
-			phy_reg |= (1 << HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT);
-
-		e1e_wphy(hw, HV_KMRN_FIFO_CTRLSTA, phy_reg);
-		break;
-	default:
-		break;
-	}
-
-	/*
-	 * Check if there was DownShift, must be checked
-	 * immediately after link-up
-	 */
-	e1000e_check_downshift(hw);
-
-	/* Enable/Disable EEE after link up */
-	ret_val = e1000_set_eee_pchlan(hw);
-	if (ret_val)
-		goto out;
-
-	/*
-	 * If we are forcing speed/duplex, then we simply return since
-	 * we have already determined whether we have link or not.
-	 */
-	if (!mac->autoneg) {
-		ret_val = -E1000_ERR_CONFIG;
-		goto out;
-	}
-
-	/*
-	 * Auto-Neg is enabled.  Auto Speed Detection takes care
-	 * of MAC speed/duplex configuration.  So we only need to
-	 * configure Collision Distance in the MAC.
-	 */
-	e1000e_config_collision_dist(hw);
-
-	/*
-	 * Configure Flow Control now that Auto-Neg has completed.
-	 * First, we need to restore the desired flow control
-	 * settings because we may have had to re-autoneg with a
-	 * different link partner.
-	 */
-	ret_val = e1000e_config_fc_after_link_up(hw);
-	if (ret_val)
-		e_dbg("Error configuring flow control\n");
-
-out:
-	return ret_val;
-}
-
-static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	s32 rc;
-
-	rc = e1000_init_mac_params_ich8lan(adapter);
-	if (rc)
-		return rc;
-
-	rc = e1000_init_nvm_params_ich8lan(hw);
-	if (rc)
-		return rc;
-
-	switch (hw->mac.type) {
-	case e1000_ich8lan:
-	case e1000_ich9lan:
-	case e1000_ich10lan:
-		rc = e1000_init_phy_params_ich8lan(hw);
-		break;
-	case e1000_pchlan:
-	case e1000_pch2lan:
-		rc = e1000_init_phy_params_pchlan(hw);
-		break;
-	default:
-		break;
-	}
-	if (rc)
-		return rc;
-
-	/*
-	 * 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;
-
-		hw->mac.ops.blink_led = NULL;
-	}
-
-	if ((adapter->hw.mac.type == e1000_ich8lan) &&
-	    (adapter->hw.phy.type == e1000_phy_igp_3))
-		adapter->flags |= FLAG_LSC_GIG_SPEED_DROP;
-
-	/* Enable workaround for 82579 w/ ME enabled */
-	if ((adapter->hw.mac.type == e1000_pch2lan) &&
-	    (er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
-		adapter->flags2 |= FLAG2_PCIM2PCI_ARBITER_WA;
-
-	/* Disable EEE by default until IEEE802.3az spec is finalized */
-	if (adapter->flags2 & FLAG2_HAS_EEE)
-		adapter->hw.dev_spec.ich8lan.eee_disable = true;
-
-	return 0;
-}
-
-static DEFINE_MUTEX(nvm_mutex);
-
-/**
- *  e1000_acquire_nvm_ich8lan - Acquire NVM mutex
- *  @hw: pointer to the HW structure
- *
- *  Acquires the mutex for performing NVM operations.
- **/
-static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw)
-{
-	mutex_lock(&nvm_mutex);
-
-	return 0;
-}
-
-/**
- *  e1000_release_nvm_ich8lan - Release NVM mutex
- *  @hw: pointer to the HW structure
- *
- *  Releases the mutex used while performing NVM operations.
- **/
-static void e1000_release_nvm_ich8lan(struct e1000_hw *hw)
-{
-	mutex_unlock(&nvm_mutex);
-}
-
-static DEFINE_MUTEX(swflag_mutex);
-
-/**
- *  e1000_acquire_swflag_ich8lan - Acquire software control flag
- *  @hw: pointer to the HW structure
- *
- *  Acquires the software control flag for performing PHY and select
- *  MAC CSR accesses.
- **/
-static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
-{
-	u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT;
-	s32 ret_val = 0;
-
-	mutex_lock(&swflag_mutex);
-
-	while (timeout) {
-		extcnf_ctrl = er32(EXTCNF_CTRL);
-		if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG))
-			break;
-
-		mdelay(1);
-		timeout--;
-	}
-
-	if (!timeout) {
-		e_dbg("SW/FW/HW has locked the resource for too long.\n");
-		ret_val = -E1000_ERR_CONFIG;
-		goto out;
-	}
-
-	timeout = SW_FLAG_TIMEOUT;
-
-	extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
-	ew32(EXTCNF_CTRL, extcnf_ctrl);
-
-	while (timeout) {
-		extcnf_ctrl = er32(EXTCNF_CTRL);
-		if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)
-			break;
-
-		mdelay(1);
-		timeout--;
-	}
-
-	if (!timeout) {
-		e_dbg("Failed to acquire the semaphore.\n");
-		extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
-		ew32(EXTCNF_CTRL, extcnf_ctrl);
-		ret_val = -E1000_ERR_CONFIG;
-		goto out;
-	}
-
-out:
-	if (ret_val)
-		mutex_unlock(&swflag_mutex);
-
-	return ret_val;
-}
-
-/**
- *  e1000_release_swflag_ich8lan - Release software control flag
- *  @hw: pointer to the HW structure
- *
- *  Releases the software control flag for performing PHY and select
- *  MAC CSR accesses.
- **/
-static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
-{
-	u32 extcnf_ctrl;
-
-	extcnf_ctrl = er32(EXTCNF_CTRL);
-
-	if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) {
-		extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
-		ew32(EXTCNF_CTRL, extcnf_ctrl);
-	} else {
-		e_dbg("Semaphore unexpectedly released by sw/fw/hw\n");
-	}
-
-	mutex_unlock(&swflag_mutex);
-}
-
-/**
- *  e1000_check_mng_mode_ich8lan - Checks management mode
- *  @hw: pointer to the HW structure
- *
- *  This checks if the adapter has any manageability enabled.
- *  This is a function pointer entry point only called by read/write
- *  routines for the PHY and NVM parts.
- **/
-static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw)
-{
-	u32 fwsm;
-
-	fwsm = er32(FWSM);
-	return (fwsm & E1000_ICH_FWSM_FW_VALID) &&
-	       ((fwsm & E1000_FWSM_MODE_MASK) ==
-		(E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT));
-}
-
-/**
- *  e1000_check_mng_mode_pchlan - Checks management mode
- *  @hw: pointer to the HW structure
- *
- *  This checks if the adapter has iAMT enabled.
- *  This is a function pointer entry point only called by read/write
- *  routines for the PHY and NVM parts.
- **/
-static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw)
-{
-	u32 fwsm;
-
-	fwsm = er32(FWSM);
-	return (fwsm & E1000_ICH_FWSM_FW_VALID) &&
-	       (fwsm & (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT));
-}
-
-/**
- *  e1000_check_reset_block_ich8lan - Check if PHY reset is blocked
- *  @hw: pointer to the HW structure
- *
- *  Checks if firmware is blocking the reset of the PHY.
- *  This is a function pointer entry point only called by
- *  reset routines.
- **/
-static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
-{
-	u32 fwsm;
-
-	fwsm = er32(FWSM);
-
-	return (fwsm & E1000_ICH_FWSM_RSPCIPHY) ? 0 : E1000_BLK_PHY_RESET;
-}
-
-/**
- *  e1000_write_smbus_addr - Write SMBus address to PHY needed during Sx states
- *  @hw: pointer to the HW structure
- *
- *  Assumes semaphore already acquired.
- *
- **/
-static s32 e1000_write_smbus_addr(struct e1000_hw *hw)
-{
-	u16 phy_data;
-	u32 strap = er32(STRAP);
-	s32 ret_val = 0;
-
-	strap &= E1000_STRAP_SMBUS_ADDRESS_MASK;
-
-	ret_val = e1000_read_phy_reg_hv_locked(hw, HV_SMB_ADDR, &phy_data);
-	if (ret_val)
-		goto out;
-
-	phy_data &= ~HV_SMB_ADDR_MASK;
-	phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT);
-	phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
-	ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data);
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration
- *  @hw:   pointer to the HW structure
- *
- *  SW should configure the LCD from the NVM extended configuration region
- *  as a workaround for certain parts.
- **/
-static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask;
-	s32 ret_val = 0;
-	u16 word_addr, reg_data, reg_addr, phy_page = 0;
-
-	/*
-	 * Initialize the PHY from the NVM on ICH platforms.  This
-	 * is needed due to an issue where the NVM configuration is
-	 * not properly autoloaded after power transitions.
-	 * Therefore, after each PHY reset, we will load the
-	 * configuration data out of the NVM manually.
-	 */
-	switch (hw->mac.type) {
-	case e1000_ich8lan:
-		if (phy->type != e1000_phy_igp_3)
-			return ret_val;
-
-		if ((hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) ||
-		    (hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_C)) {
-			sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
-			break;
-		}
-		/* Fall-thru */
-	case e1000_pchlan:
-	case e1000_pch2lan:
-		sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
-		break;
-	default:
-		return ret_val;
-	}
-
-	ret_val = hw->phy.ops.acquire(hw);
-	if (ret_val)
-		return ret_val;
-
-	data = er32(FEXTNVM);
-	if (!(data & sw_cfg_mask))
-		goto out;
-
-	/*
-	 * Make sure HW does not configure LCD from PHY
-	 * extended configuration before SW configuration
-	 */
-	data = er32(EXTCNF_CTRL);
-	if (!(hw->mac.type == e1000_pch2lan)) {
-		if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
-			goto out;
-	}
-
-	cnf_size = er32(EXTCNF_SIZE);
-	cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
-	cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;
-	if (!cnf_size)
-		goto out;
-
-	cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
-	cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
-
-	if ((!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
-	    (hw->mac.type == e1000_pchlan)) ||
-	     (hw->mac.type == e1000_pch2lan)) {
-		/*
-		 * HW configures the SMBus address and LEDs when the
-		 * OEM and LCD Write Enable bits are set in the NVM.
-		 * When both NVM bits are cleared, SW will configure
-		 * them instead.
-		 */
-		ret_val = e1000_write_smbus_addr(hw);
-		if (ret_val)
-			goto out;
-
-		data = er32(LEDCTL);
-		ret_val = e1000_write_phy_reg_hv_locked(hw, HV_LED_CONFIG,
-							(u16)data);
-		if (ret_val)
-			goto out;
-	}
-
-	/* Configure LCD from extended configuration region. */
-
-	/* cnf_base_addr is in DWORD */
-	word_addr = (u16)(cnf_base_addr << 1);
-
-	for (i = 0; i < cnf_size; i++) {
-		ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1,
-					 &reg_data);
-		if (ret_val)
-			goto out;
-
-		ret_val = e1000_read_nvm(hw, (word_addr + i * 2 + 1),
-					 1, &reg_addr);
-		if (ret_val)
-			goto out;
-
-		/* Save off the PHY page for future writes. */
-		if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {
-			phy_page = reg_data;
-			continue;
-		}
-
-		reg_addr &= PHY_REG_MASK;
-		reg_addr |= phy_page;
-
-		ret_val = phy->ops.write_reg_locked(hw, (u32)reg_addr,
-						    reg_data);
-		if (ret_val)
-			goto out;
-	}
-
-out:
-	hw->phy.ops.release(hw);
-	return ret_val;
-}
-
-/**
- *  e1000_k1_gig_workaround_hv - K1 Si workaround
- *  @hw:   pointer to the HW structure
- *  @link: link up bool flag
- *
- *  If K1 is enabled for 1Gbps, the MAC might stall when transitioning
- *  from a lower speed.  This workaround disables K1 whenever link is at 1Gig
- *  If link is down, the function will restore the default K1 setting located
- *  in the NVM.
- **/
-static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
-{
-	s32 ret_val = 0;
-	u16 status_reg = 0;
-	bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled;
-
-	if (hw->mac.type != e1000_pchlan)
-		goto out;
-
-	/* Wrap the whole flow with the sw flag */
-	ret_val = hw->phy.ops.acquire(hw);
-	if (ret_val)
-		goto out;
-
-	/* Disable K1 when link is 1Gbps, otherwise use the NVM setting */
-	if (link) {
-		if (hw->phy.type == e1000_phy_82578) {
-			ret_val = hw->phy.ops.read_reg_locked(hw, BM_CS_STATUS,
-			                                          &status_reg);
-			if (ret_val)
-				goto release;
-
-			status_reg &= BM_CS_STATUS_LINK_UP |
-			              BM_CS_STATUS_RESOLVED |
-			              BM_CS_STATUS_SPEED_MASK;
-
-			if (status_reg == (BM_CS_STATUS_LINK_UP |
-			                   BM_CS_STATUS_RESOLVED |
-			                   BM_CS_STATUS_SPEED_1000))
-				k1_enable = false;
-		}
-
-		if (hw->phy.type == e1000_phy_82577) {
-			ret_val = hw->phy.ops.read_reg_locked(hw, HV_M_STATUS,
-			                                          &status_reg);
-			if (ret_val)
-				goto release;
-
-			status_reg &= HV_M_STATUS_LINK_UP |
-			              HV_M_STATUS_AUTONEG_COMPLETE |
-			              HV_M_STATUS_SPEED_MASK;
-
-			if (status_reg == (HV_M_STATUS_LINK_UP |
-			                   HV_M_STATUS_AUTONEG_COMPLETE |
-			                   HV_M_STATUS_SPEED_1000))
-				k1_enable = false;
-		}
-
-		/* Link stall fix for link up */
-		ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19),
-		                                           0x0100);
-		if (ret_val)
-			goto release;
-
-	} else {
-		/* Link stall fix for link down */
-		ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19),
-		                                           0x4100);
-		if (ret_val)
-			goto release;
-	}
-
-	ret_val = e1000_configure_k1_ich8lan(hw, k1_enable);
-
-release:
-	hw->phy.ops.release(hw);
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_configure_k1_ich8lan - Configure K1 power state
- *  @hw: pointer to the HW structure
- *  @enable: K1 state to configure
- *
- *  Configure the K1 power state based on the provided parameter.
- *  Assumes semaphore already acquired.
- *
- *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
- **/
-s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable)
-{
-	s32 ret_val = 0;
-	u32 ctrl_reg = 0;
-	u32 ctrl_ext = 0;
-	u32 reg = 0;
-	u16 kmrn_reg = 0;
-
-	ret_val = e1000e_read_kmrn_reg_locked(hw,
-	                                     E1000_KMRNCTRLSTA_K1_CONFIG,
-	                                     &kmrn_reg);
-	if (ret_val)
-		goto out;
-
-	if (k1_enable)
-		kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE;
-	else
-		kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE;
-
-	ret_val = e1000e_write_kmrn_reg_locked(hw,
-	                                      E1000_KMRNCTRLSTA_K1_CONFIG,
-	                                      kmrn_reg);
-	if (ret_val)
-		goto out;
-
-	udelay(20);
-	ctrl_ext = er32(CTRL_EXT);
-	ctrl_reg = er32(CTRL);
-
-	reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
-	reg |= E1000_CTRL_FRCSPD;
-	ew32(CTRL, reg);
-
-	ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS);
-	e1e_flush();
-	udelay(20);
-	ew32(CTRL, ctrl_reg);
-	ew32(CTRL_EXT, ctrl_ext);
-	e1e_flush();
-	udelay(20);
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_oem_bits_config_ich8lan - SW-based LCD Configuration
- *  @hw:       pointer to the HW structure
- *  @d0_state: boolean if entering d0 or d3 device state
- *
- *  SW will configure Gbe Disable and LPLU based on the NVM. The four bits are
- *  collectively called OEM bits.  The OEM Write Enable bit and SW Config bit
- *  in NVM determines whether HW should configure LPLU and Gbe Disable.
- **/
-static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
-{
-	s32 ret_val = 0;
-	u32 mac_reg;
-	u16 oem_reg;
-
-	if ((hw->mac.type != e1000_pch2lan) && (hw->mac.type != e1000_pchlan))
-		return ret_val;
-
-	ret_val = hw->phy.ops.acquire(hw);
-	if (ret_val)
-		return ret_val;
-
-	if (!(hw->mac.type == e1000_pch2lan)) {
-		mac_reg = er32(EXTCNF_CTRL);
-		if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
-			goto out;
-	}
-
-	mac_reg = er32(FEXTNVM);
-	if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M))
-		goto out;
-
-	mac_reg = er32(PHY_CTRL);
-
-	ret_val = hw->phy.ops.read_reg_locked(hw, HV_OEM_BITS, &oem_reg);
-	if (ret_val)
-		goto out;
-
-	oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU);
-
-	if (d0_state) {
-		if (mac_reg & E1000_PHY_CTRL_GBE_DISABLE)
-			oem_reg |= HV_OEM_BITS_GBE_DIS;
-
-		if (mac_reg & E1000_PHY_CTRL_D0A_LPLU)
-			oem_reg |= HV_OEM_BITS_LPLU;
-	} else {
-		if (mac_reg & E1000_PHY_CTRL_NOND0A_GBE_DISABLE)
-			oem_reg |= HV_OEM_BITS_GBE_DIS;
-
-		if (mac_reg & E1000_PHY_CTRL_NOND0A_LPLU)
-			oem_reg |= HV_OEM_BITS_LPLU;
-	}
-	/* Restart auto-neg to activate the bits */
-	if (!e1000_check_reset_block(hw))
-		oem_reg |= HV_OEM_BITS_RESTART_AN;
-	ret_val = hw->phy.ops.write_reg_locked(hw, HV_OEM_BITS, oem_reg);
-
-out:
-	hw->phy.ops.release(hw);
-
-	return ret_val;
-}
-
-
-/**
- *  e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode
- *  @hw:   pointer to the HW structure
- **/
-static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 data;
-
-	ret_val = e1e_rphy(hw, HV_KMRN_MODE_CTRL, &data);
-	if (ret_val)
-		return ret_val;
-
-	data |= HV_KMRN_MDIO_SLOW;
-
-	ret_val = e1e_wphy(hw, HV_KMRN_MODE_CTRL, data);
-
-	return ret_val;
-}
-
-/**
- *  e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be
- *  done after every PHY reset.
- **/
-static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
-{
-	s32 ret_val = 0;
-	u16 phy_data;
-
-	if (hw->mac.type != e1000_pchlan)
-		return ret_val;
-
-	/* Set MDIO slow mode before any other MDIO access */
-	if (hw->phy.type == e1000_phy_82577) {
-		ret_val = e1000_set_mdio_slow_mode_hv(hw);
-		if (ret_val)
-			goto out;
-	}
-
-	if (((hw->phy.type == e1000_phy_82577) &&
-	     ((hw->phy.revision == 1) || (hw->phy.revision == 2))) ||
-	    ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision == 1))) {
-		/* Disable generation of early preamble */
-		ret_val = e1e_wphy(hw, PHY_REG(769, 25), 0x4431);
-		if (ret_val)
-			return ret_val;
-
-		/* Preamble tuning for SSC */
-		ret_val = e1e_wphy(hw, HV_KMRN_FIFO_CTRLSTA, 0xA204);
-		if (ret_val)
-			return ret_val;
-	}
-
-	if (hw->phy.type == e1000_phy_82578) {
-		/*
-		 * Return registers to default by doing a soft reset then
-		 * writing 0x3140 to the control register.
-		 */
-		if (hw->phy.revision < 2) {
-			e1000e_phy_sw_reset(hw);
-			ret_val = e1e_wphy(hw, PHY_CONTROL, 0x3140);
-		}
-	}
-
-	/* Select page 0 */
-	ret_val = hw->phy.ops.acquire(hw);
-	if (ret_val)
-		return ret_val;
-
-	hw->phy.addr = 1;
-	ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
-	hw->phy.ops.release(hw);
-	if (ret_val)
-		goto out;
-
-	/*
-	 * Configure the K1 Si workaround during phy reset assuming there is
-	 * link so that it disables K1 if link is in 1Gbps.
-	 */
-	ret_val = e1000_k1_gig_workaround_hv(hw, true);
-	if (ret_val)
-		goto out;
-
-	/* Workaround for link disconnects on a busy hub in half duplex */
-	ret_val = hw->phy.ops.acquire(hw);
-	if (ret_val)
-		goto out;
-	ret_val = hw->phy.ops.read_reg_locked(hw, BM_PORT_GEN_CFG, &phy_data);
-	if (ret_val)
-		goto release;
-	ret_val = hw->phy.ops.write_reg_locked(hw, BM_PORT_GEN_CFG,
-					       phy_data & 0x00FF);
-release:
-	hw->phy.ops.release(hw);
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_copy_rx_addrs_to_phy_ich8lan - Copy Rx addresses from MAC to PHY
- *  @hw:   pointer to the HW structure
- **/
-void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw)
-{
-	u32 mac_reg;
-	u16 i, phy_reg = 0;
-	s32 ret_val;
-
-	ret_val = hw->phy.ops.acquire(hw);
-	if (ret_val)
-		return;
-	ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
-	if (ret_val)
-		goto release;
-
-	/* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */
-	for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
-		mac_reg = er32(RAL(i));
-		hw->phy.ops.write_reg_page(hw, BM_RAR_L(i),
-					   (u16)(mac_reg & 0xFFFF));
-		hw->phy.ops.write_reg_page(hw, BM_RAR_M(i),
-					   (u16)((mac_reg >> 16) & 0xFFFF));
-
-		mac_reg = er32(RAH(i));
-		hw->phy.ops.write_reg_page(hw, BM_RAR_H(i),
-					   (u16)(mac_reg & 0xFFFF));
-		hw->phy.ops.write_reg_page(hw, BM_RAR_CTRL(i),
-					   (u16)((mac_reg & E1000_RAH_AV)
-						 >> 16));
-	}
-
-	e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
-
-release:
-	hw->phy.ops.release(hw);
-}
-
-/**
- *  e1000_lv_jumbo_workaround_ich8lan - required for jumbo frame operation
- *  with 82579 PHY
- *  @hw: pointer to the HW structure
- *  @enable: flag to enable/disable workaround when enabling/disabling jumbos
- **/
-s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
-{
-	s32 ret_val = 0;
-	u16 phy_reg, data;
-	u32 mac_reg;
-	u16 i;
-
-	if (hw->mac.type != e1000_pch2lan)
-		goto out;
-
-	/* disable Rx path while enabling/disabling workaround */
-	e1e_rphy(hw, PHY_REG(769, 20), &phy_reg);
-	ret_val = e1e_wphy(hw, PHY_REG(769, 20), phy_reg | (1 << 14));
-	if (ret_val)
-		goto out;
-
-	if (enable) {
-		/*
-		 * Write Rx addresses (rar_entry_count for RAL/H, +4 for
-		 * SHRAL/H) and initial CRC values to the MAC
-		 */
-		for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
-			u8 mac_addr[ETH_ALEN] = {0};
-			u32 addr_high, addr_low;
-
-			addr_high = er32(RAH(i));
-			if (!(addr_high & E1000_RAH_AV))
-				continue;
-			addr_low = er32(RAL(i));
-			mac_addr[0] = (addr_low & 0xFF);
-			mac_addr[1] = ((addr_low >> 8) & 0xFF);
-			mac_addr[2] = ((addr_low >> 16) & 0xFF);
-			mac_addr[3] = ((addr_low >> 24) & 0xFF);
-			mac_addr[4] = (addr_high & 0xFF);
-			mac_addr[5] = ((addr_high >> 8) & 0xFF);
-
-			ew32(PCH_RAICC(i), ~ether_crc_le(ETH_ALEN, mac_addr));
-		}
-
-		/* Write Rx addresses to the PHY */
-		e1000_copy_rx_addrs_to_phy_ich8lan(hw);
-
-		/* Enable jumbo frame workaround in the MAC */
-		mac_reg = er32(FFLT_DBG);
-		mac_reg &= ~(1 << 14);
-		mac_reg |= (7 << 15);
-		ew32(FFLT_DBG, mac_reg);
-
-		mac_reg = er32(RCTL);
-		mac_reg |= E1000_RCTL_SECRC;
-		ew32(RCTL, mac_reg);
-
-		ret_val = e1000e_read_kmrn_reg(hw,
-						E1000_KMRNCTRLSTA_CTRL_OFFSET,
-						&data);
-		if (ret_val)
-			goto out;
-		ret_val = e1000e_write_kmrn_reg(hw,
-						E1000_KMRNCTRLSTA_CTRL_OFFSET,
-						data | (1 << 0));
-		if (ret_val)
-			goto out;
-		ret_val = e1000e_read_kmrn_reg(hw,
-						E1000_KMRNCTRLSTA_HD_CTRL,
-						&data);
-		if (ret_val)
-			goto out;
-		data &= ~(0xF << 8);
-		data |= (0xB << 8);
-		ret_val = e1000e_write_kmrn_reg(hw,
-						E1000_KMRNCTRLSTA_HD_CTRL,
-						data);
-		if (ret_val)
-			goto out;
-
-		/* Enable jumbo frame workaround in the PHY */
-		e1e_rphy(hw, PHY_REG(769, 23), &data);
-		data &= ~(0x7F << 5);
-		data |= (0x37 << 5);
-		ret_val = e1e_wphy(hw, PHY_REG(769, 23), data);
-		if (ret_val)
-			goto out;
-		e1e_rphy(hw, PHY_REG(769, 16), &data);
-		data &= ~(1 << 13);
-		ret_val = e1e_wphy(hw, PHY_REG(769, 16), data);
-		if (ret_val)
-			goto out;
-		e1e_rphy(hw, PHY_REG(776, 20), &data);
-		data &= ~(0x3FF << 2);
-		data |= (0x1A << 2);
-		ret_val = e1e_wphy(hw, PHY_REG(776, 20), data);
-		if (ret_val)
-			goto out;
-		ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0xFE00);
-		if (ret_val)
-			goto out;
-		e1e_rphy(hw, HV_PM_CTRL, &data);
-		ret_val = e1e_wphy(hw, HV_PM_CTRL, data | (1 << 10));
-		if (ret_val)
-			goto out;
-	} else {
-		/* Write MAC register values back to h/w defaults */
-		mac_reg = er32(FFLT_DBG);
-		mac_reg &= ~(0xF << 14);
-		ew32(FFLT_DBG, mac_reg);
-
-		mac_reg = er32(RCTL);
-		mac_reg &= ~E1000_RCTL_SECRC;
-		ew32(RCTL, mac_reg);
-
-		ret_val = e1000e_read_kmrn_reg(hw,
-						E1000_KMRNCTRLSTA_CTRL_OFFSET,
-						&data);
-		if (ret_val)
-			goto out;
-		ret_val = e1000e_write_kmrn_reg(hw,
-						E1000_KMRNCTRLSTA_CTRL_OFFSET,
-						data & ~(1 << 0));
-		if (ret_val)
-			goto out;
-		ret_val = e1000e_read_kmrn_reg(hw,
-						E1000_KMRNCTRLSTA_HD_CTRL,
-						&data);
-		if (ret_val)
-			goto out;
-		data &= ~(0xF << 8);
-		data |= (0xB << 8);
-		ret_val = e1000e_write_kmrn_reg(hw,
-						E1000_KMRNCTRLSTA_HD_CTRL,
-						data);
-		if (ret_val)
-			goto out;
-
-		/* Write PHY register values back to h/w defaults */
-		e1e_rphy(hw, PHY_REG(769, 23), &data);
-		data &= ~(0x7F << 5);
-		ret_val = e1e_wphy(hw, PHY_REG(769, 23), data);
-		if (ret_val)
-			goto out;
-		e1e_rphy(hw, PHY_REG(769, 16), &data);
-		data |= (1 << 13);
-		ret_val = e1e_wphy(hw, PHY_REG(769, 16), data);
-		if (ret_val)
-			goto out;
-		e1e_rphy(hw, PHY_REG(776, 20), &data);
-		data &= ~(0x3FF << 2);
-		data |= (0x8 << 2);
-		ret_val = e1e_wphy(hw, PHY_REG(776, 20), data);
-		if (ret_val)
-			goto out;
-		ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0x7E00);
-		if (ret_val)
-			goto out;
-		e1e_rphy(hw, HV_PM_CTRL, &data);
-		ret_val = e1e_wphy(hw, HV_PM_CTRL, data & ~(1 << 10));
-		if (ret_val)
-			goto out;
-	}
-
-	/* re-enable Rx path after enabling/disabling workaround */
-	ret_val = e1e_wphy(hw, PHY_REG(769, 20), phy_reg & ~(1 << 14));
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_lv_phy_workarounds_ich8lan - A series of Phy workarounds to be
- *  done after every PHY reset.
- **/
-static s32 e1000_lv_phy_workarounds_ich8lan(struct e1000_hw *hw)
-{
-	s32 ret_val = 0;
-
-	if (hw->mac.type != e1000_pch2lan)
-		goto out;
-
-	/* Set MDIO slow mode before any other MDIO access */
-	ret_val = e1000_set_mdio_slow_mode_hv(hw);
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_k1_gig_workaround_lv - K1 Si workaround
- *  @hw:   pointer to the HW structure
- *
- *  Workaround to set the K1 beacon duration for 82579 parts
- **/
-static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)
-{
-	s32 ret_val = 0;
-	u16 status_reg = 0;
-	u32 mac_reg;
-	u16 phy_reg;
-
-	if (hw->mac.type != e1000_pch2lan)
-		goto out;
-
-	/* Set K1 beacon duration based on 1Gbps speed or otherwise */
-	ret_val = e1e_rphy(hw, HV_M_STATUS, &status_reg);
-	if (ret_val)
-		goto out;
-
-	if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE))
-	    == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) {
-		mac_reg = er32(FEXTNVM4);
-		mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK;
-
-		ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg);
-		if (ret_val)
-			goto out;
-
-		if (status_reg & HV_M_STATUS_SPEED_1000) {
-			mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC;
-			phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT;
-		} else {
-			mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC;
-			phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT;
-		}
-		ew32(FEXTNVM4, mac_reg);
-		ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);
-	}
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_gate_hw_phy_config_ich8lan - disable PHY config via hardware
- *  @hw:   pointer to the HW structure
- *  @gate: boolean set to true to gate, false to ungate
- *
- *  Gate/ungate the automatic PHY configuration via hardware; perform
- *  the configuration via software instead.
- **/
-static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate)
-{
-	u32 extcnf_ctrl;
-
-	if (hw->mac.type != e1000_pch2lan)
-		return;
-
-	extcnf_ctrl = er32(EXTCNF_CTRL);
-
-	if (gate)
-		extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG;
-	else
-		extcnf_ctrl &= ~E1000_EXTCNF_CTRL_GATE_PHY_CFG;
-
-	ew32(EXTCNF_CTRL, extcnf_ctrl);
-	return;
-}
-
-/**
- *  e1000_lan_init_done_ich8lan - Check for PHY config completion
- *  @hw: pointer to the HW structure
- *
- *  Check the appropriate indication the MAC has finished configuring the
- *  PHY after a software reset.
- **/
-static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw)
-{
-	u32 data, loop = E1000_ICH8_LAN_INIT_TIMEOUT;
-
-	/* Wait for basic configuration completes before proceeding */
-	do {
-		data = er32(STATUS);
-		data &= E1000_STATUS_LAN_INIT_DONE;
-		udelay(100);
-	} while ((!data) && --loop);
-
-	/*
-	 * If basic configuration is incomplete before the above loop
-	 * count reaches 0, loading the configuration from NVM will
-	 * leave the PHY in a bad state possibly resulting in no link.
-	 */
-	if (loop == 0)
-		e_dbg("LAN_INIT_DONE not set, increase timeout\n");
-
-	/* Clear the Init Done bit for the next init event */
-	data = er32(STATUS);
-	data &= ~E1000_STATUS_LAN_INIT_DONE;
-	ew32(STATUS, data);
-}
-
-/**
- *  e1000_post_phy_reset_ich8lan - Perform steps required after a PHY reset
- *  @hw: pointer to the HW structure
- **/
-static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
-{
-	s32 ret_val = 0;
-	u16 reg;
-
-	if (e1000_check_reset_block(hw))
-		goto out;
-
-	/* Allow time for h/w to get to quiescent state after reset */
-	usleep_range(10000, 20000);
-
-	/* Perform any necessary post-reset workarounds */
-	switch (hw->mac.type) {
-	case e1000_pchlan:
-		ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
-		if (ret_val)
-			goto out;
-		break;
-	case e1000_pch2lan:
-		ret_val = e1000_lv_phy_workarounds_ich8lan(hw);
-		if (ret_val)
-			goto out;
-		break;
-	default:
-		break;
-	}
-
-	/* Clear the host wakeup bit after lcd reset */
-	if (hw->mac.type >= e1000_pchlan) {
-		e1e_rphy(hw, BM_PORT_GEN_CFG, &reg);
-		reg &= ~BM_WUC_HOST_WU_BIT;
-		e1e_wphy(hw, BM_PORT_GEN_CFG, reg);
-	}
-
-	/* Configure the LCD with the extended configuration region in NVM */
-	ret_val = e1000_sw_lcd_config_ich8lan(hw);
-	if (ret_val)
-		goto out;
-
-	/* Configure the LCD with the OEM bits in NVM */
-	ret_val = e1000_oem_bits_config_ich8lan(hw, true);
-
-	if (hw->mac.type == e1000_pch2lan) {
-		/* Ungate automatic PHY configuration on non-managed 82579 */
-		if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
-			usleep_range(10000, 20000);
-			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:
-	return ret_val;
-}
-
-/**
- *  e1000_phy_hw_reset_ich8lan - Performs a PHY reset
- *  @hw: pointer to the HW structure
- *
- *  Resets the PHY
- *  This is a function pointer entry point called by drivers
- *  or other shared routines.
- **/
-static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
-{
-	s32 ret_val = 0;
-
-	/* Gate automatic PHY configuration by hardware on non-managed 82579 */
-	if ((hw->mac.type == e1000_pch2lan) &&
-	    !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
-		e1000_gate_hw_phy_config_ich8lan(hw, true);
-
-	ret_val = e1000e_phy_hw_reset_generic(hw);
-	if (ret_val)
-		goto out;
-
-	ret_val = e1000_post_phy_reset_ich8lan(hw);
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_set_lplu_state_pchlan - Set Low Power Link Up state
- *  @hw: pointer to the HW structure
- *  @active: true to enable LPLU, false to disable
- *
- *  Sets the LPLU state according to the active flag.  For PCH, if OEM write
- *  bit are disabled in the NVM, writing the LPLU bits in the MAC will not set
- *  the phy speed. This function will manually set the LPLU bit and restart
- *  auto-neg as hw would do. D3 and D0 LPLU will call the same function
- *  since it configures the same bit.
- **/
-static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active)
-{
-	s32 ret_val = 0;
-	u16 oem_reg;
-
-	ret_val = e1e_rphy(hw, HV_OEM_BITS, &oem_reg);
-	if (ret_val)
-		goto out;
-
-	if (active)
-		oem_reg |= HV_OEM_BITS_LPLU;
-	else
-		oem_reg &= ~HV_OEM_BITS_LPLU;
-
-	oem_reg |= HV_OEM_BITS_RESTART_AN;
-	ret_val = e1e_wphy(hw, HV_OEM_BITS, oem_reg);
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_set_d0_lplu_state_ich8lan - Set Low Power Linkup D0 state
- *  @hw: pointer to the HW structure
- *  @active: true to enable LPLU, false to disable
- *
- *  Sets the LPLU D0 state according to the active flag.  When
- *  activating LPLU this function also disables smart speed
- *  and vice versa.  LPLU will not be activated unless the
- *  device autonegotiation advertisement meets standards of
- *  either 10 or 10/100 or 10/100/1000 at all duplexes.
- *  This is a function pointer entry point only called by
- *  PHY setup routines.
- **/
-static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	u32 phy_ctrl;
-	s32 ret_val = 0;
-	u16 data;
-
-	if (phy->type == e1000_phy_ife)
-		return ret_val;
-
-	phy_ctrl = er32(PHY_CTRL);
-
-	if (active) {
-		phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;
-		ew32(PHY_CTRL, phy_ctrl);
-
-		if (phy->type != e1000_phy_igp_3)
-			return 0;
-
-		/*
-		 * Call gig speed drop workaround on LPLU before accessing
-		 * any PHY registers
-		 */
-		if (hw->mac.type == e1000_ich8lan)
-			e1000e_gig_downshift_workaround_ich8lan(hw);
-
-		/* When LPLU is enabled, we should disable SmartSpeed */
-		ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data);
-		data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-		ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data);
-		if (ret_val)
-			return ret_val;
-	} else {
-		phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
-		ew32(PHY_CTRL, phy_ctrl);
-
-		if (phy->type != e1000_phy_igp_3)
-			return 0;
-
-		/*
-		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
-		 * during Dx states where the power conservation is most
-		 * important.  During driver activity we should enable
-		 * SmartSpeed, so performance is maintained.
-		 */
-		if (phy->smart_speed == e1000_smart_speed_on) {
-			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   &data);
-			if (ret_val)
-				return ret_val;
-
-			data |= IGP01E1000_PSCFR_SMART_SPEED;
-			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   data);
-			if (ret_val)
-				return ret_val;
-		} else if (phy->smart_speed == e1000_smart_speed_off) {
-			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   &data);
-			if (ret_val)
-				return ret_val;
-
-			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   data);
-			if (ret_val)
-				return ret_val;
-		}
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_set_d3_lplu_state_ich8lan - Set Low Power Linkup D3 state
- *  @hw: pointer to the HW structure
- *  @active: true to enable LPLU, false to disable
- *
- *  Sets the LPLU D3 state according to the active flag.  When
- *  activating LPLU this function also disables smart speed
- *  and vice versa.  LPLU will not be activated unless the
- *  device autonegotiation advertisement meets standards of
- *  either 10 or 10/100 or 10/100/1000 at all duplexes.
- *  This is a function pointer entry point only called by
- *  PHY setup routines.
- **/
-static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	u32 phy_ctrl;
-	s32 ret_val;
-	u16 data;
-
-	phy_ctrl = er32(PHY_CTRL);
-
-	if (!active) {
-		phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU;
-		ew32(PHY_CTRL, phy_ctrl);
-
-		if (phy->type != e1000_phy_igp_3)
-			return 0;
-
-		/*
-		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
-		 * during Dx states where the power conservation is most
-		 * important.  During driver activity we should enable
-		 * SmartSpeed, so performance is maintained.
-		 */
-		if (phy->smart_speed == e1000_smart_speed_on) {
-			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   &data);
-			if (ret_val)
-				return ret_val;
-
-			data |= IGP01E1000_PSCFR_SMART_SPEED;
-			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   data);
-			if (ret_val)
-				return ret_val;
-		} else if (phy->smart_speed == e1000_smart_speed_off) {
-			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   &data);
-			if (ret_val)
-				return ret_val;
-
-			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   data);
-			if (ret_val)
-				return ret_val;
-		}
-	} else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
-		   (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
-		   (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
-		phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU;
-		ew32(PHY_CTRL, phy_ctrl);
-
-		if (phy->type != e1000_phy_igp_3)
-			return 0;
-
-		/*
-		 * Call gig speed drop workaround on LPLU before accessing
-		 * any PHY registers
-		 */
-		if (hw->mac.type == e1000_ich8lan)
-			e1000e_gig_downshift_workaround_ich8lan(hw);
-
-		/* When LPLU is enabled, we should disable SmartSpeed */
-		ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data);
-		if (ret_val)
-			return ret_val;
-
-		data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-		ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data);
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_valid_nvm_bank_detect_ich8lan - finds out the valid bank 0 or 1
- *  @hw: pointer to the HW structure
- *  @bank:  pointer to the variable that returns the active bank
- *
- *  Reads signature byte from the NVM using the flash access registers.
- *  Word 0x13 bits 15:14 = 10b indicate a valid signature for that bank.
- **/
-static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
-{
-	u32 eecd;
-	struct e1000_nvm_info *nvm = &hw->nvm;
-	u32 bank1_offset = nvm->flash_bank_size * sizeof(u16);
-	u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1;
-	u8 sig_byte = 0;
-	s32 ret_val = 0;
-
-	switch (hw->mac.type) {
-	case e1000_ich8lan:
-	case e1000_ich9lan:
-		eecd = er32(EECD);
-		if ((eecd & E1000_EECD_SEC1VAL_VALID_MASK) ==
-		    E1000_EECD_SEC1VAL_VALID_MASK) {
-			if (eecd & E1000_EECD_SEC1VAL)
-				*bank = 1;
-			else
-				*bank = 0;
-
-			return 0;
-		}
-		e_dbg("Unable to determine valid NVM bank via EEC - "
-		       "reading flash signature\n");
-		/* fall-thru */
-	default:
-		/* set bank to 0 in case flash read fails */
-		*bank = 0;
-
-		/* Check bank 0 */
-		ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset,
-		                                        &sig_byte);
-		if (ret_val)
-			return ret_val;
-		if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
-		    E1000_ICH_NVM_SIG_VALUE) {
-			*bank = 0;
-			return 0;
-		}
-
-		/* Check bank 1 */
-		ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset +
-		                                        bank1_offset,
-		                                        &sig_byte);
-		if (ret_val)
-			return ret_val;
-		if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
-		    E1000_ICH_NVM_SIG_VALUE) {
-			*bank = 1;
-			return 0;
-		}
-
-		e_dbg("ERROR: No valid NVM bank present\n");
-		return -E1000_ERR_NVM;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_read_nvm_ich8lan - Read word(s) from the NVM
- *  @hw: pointer to the HW structure
- *  @offset: The offset (in bytes) of the word(s) to read.
- *  @words: Size of data to read in words
- *  @data: Pointer to the word(s) to read at offset.
- *
- *  Reads a word(s) from the NVM using the flash access registers.
- **/
-static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
-				  u16 *data)
-{
-	struct e1000_nvm_info *nvm = &hw->nvm;
-	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
-	u32 act_offset;
-	s32 ret_val = 0;
-	u32 bank = 0;
-	u16 i, word;
-
-	if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
-	    (words == 0)) {
-		e_dbg("nvm parameter(s) out of bounds\n");
-		ret_val = -E1000_ERR_NVM;
-		goto out;
-	}
-
-	nvm->ops.acquire(hw);
-
-	ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
-	if (ret_val) {
-		e_dbg("Could not detect valid bank, assuming bank 0\n");
-		bank = 0;
-	}
-
-	act_offset = (bank) ? nvm->flash_bank_size : 0;
-	act_offset += offset;
-
-	ret_val = 0;
-	for (i = 0; i < words; i++) {
-		if (dev_spec->shadow_ram[offset+i].modified) {
-			data[i] = dev_spec->shadow_ram[offset+i].value;
-		} else {
-			ret_val = e1000_read_flash_word_ich8lan(hw,
-								act_offset + i,
-								&word);
-			if (ret_val)
-				break;
-			data[i] = word;
-		}
-	}
-
-	nvm->ops.release(hw);
-
-out:
-	if (ret_val)
-		e_dbg("NVM read error: %d\n", ret_val);
-
-	return ret_val;
-}
-
-/**
- *  e1000_flash_cycle_init_ich8lan - Initialize flash
- *  @hw: pointer to the HW structure
- *
- *  This function does initial flash setup so that a new read/write/erase cycle
- *  can be started.
- **/
-static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
-{
-	union ich8_hws_flash_status hsfsts;
-	s32 ret_val = -E1000_ERR_NVM;
-
-	hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
-
-	/* Check if the flash descriptor is valid */
-	if (hsfsts.hsf_status.fldesvalid == 0) {
-		e_dbg("Flash descriptor invalid.  "
-			 "SW Sequencing must be used.\n");
-		return -E1000_ERR_NVM;
-	}
-
-	/* Clear FCERR and DAEL in hw status by writing 1 */
-	hsfsts.hsf_status.flcerr = 1;
-	hsfsts.hsf_status.dael = 1;
-
-	ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
-
-	/*
-	 * Either we should have a hardware SPI cycle in progress
-	 * bit to check against, in order to start a new cycle or
-	 * FDONE bit should be changed in the hardware so that it
-	 * is 1 after hardware reset, which can then be used as an
-	 * indication whether a cycle is in progress or has been
-	 * completed.
-	 */
-
-	if (hsfsts.hsf_status.flcinprog == 0) {
-		/*
-		 * There is no cycle running at present,
-		 * so we can start a cycle.
-		 * Begin by setting Flash Cycle Done.
-		 */
-		hsfsts.hsf_status.flcdone = 1;
-		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.
-		 */
-		for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) {
-			hsfsts.regval = __er16flash(hw, ICH_FLASH_HSFSTS);
-			if (hsfsts.hsf_status.flcinprog == 0) {
-				ret_val = 0;
-				break;
-			}
-			udelay(1);
-		}
-		if (ret_val == 0) {
-			/*
-			 * Successful in waiting for previous cycle to timeout,
-			 * now set the Flash Cycle Done.
-			 */
-			hsfsts.hsf_status.flcdone = 1;
-			ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
-		} else {
-			e_dbg("Flash controller busy, cannot get access\n");
-		}
-	}
-
-	return ret_val;
-}
-
-/**
- *  e1000_flash_cycle_ich8lan - Starts flash cycle (read/write/erase)
- *  @hw: pointer to the HW structure
- *  @timeout: maximum time to wait for completion
- *
- *  This function starts a flash cycle and waits for its completion.
- **/
-static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
-{
-	union ich8_hws_flash_ctrl hsflctl;
-	union ich8_hws_flash_status hsfsts;
-	s32 ret_val = -E1000_ERR_NVM;
-	u32 i = 0;
-
-	/* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
-	hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
-	hsflctl.hsf_ctrl.flcgo = 1;
-	ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
-
-	/* wait till FDONE bit is set to 1 */
-	do {
-		hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
-		if (hsfsts.hsf_status.flcdone == 1)
-			break;
-		udelay(1);
-	} while (i++ < timeout);
-
-	if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0)
-		return 0;
-
-	return ret_val;
-}
-
-/**
- *  e1000_read_flash_word_ich8lan - Read word from flash
- *  @hw: pointer to the HW structure
- *  @offset: offset to data location
- *  @data: pointer to the location for storing the data
- *
- *  Reads the flash word at offset into data.  Offset is converted
- *  to bytes before read.
- **/
-static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset,
-					 u16 *data)
-{
-	/* Must convert offset into bytes. */
-	offset <<= 1;
-
-	return e1000_read_flash_data_ich8lan(hw, offset, 2, data);
-}
-
-/**
- *  e1000_read_flash_byte_ich8lan - Read byte from flash
- *  @hw: pointer to the HW structure
- *  @offset: The offset of the byte to read.
- *  @data: Pointer to a byte to store the value read.
- *
- *  Reads a single byte from the NVM using the flash access registers.
- **/
-static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
-					 u8 *data)
-{
-	s32 ret_val;
-	u16 word = 0;
-
-	ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
-	if (ret_val)
-		return ret_val;
-
-	*data = (u8)word;
-
-	return 0;
-}
-
-/**
- *  e1000_read_flash_data_ich8lan - Read byte or word from NVM
- *  @hw: pointer to the HW structure
- *  @offset: The offset (in bytes) of the byte or word to read.
- *  @size: Size of data to read, 1=byte 2=word
- *  @data: Pointer to the word to store the value read.
- *
- *  Reads a byte or word from the NVM using the flash access registers.
- **/
-static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
-					 u8 size, u16 *data)
-{
-	union ich8_hws_flash_status hsfsts;
-	union ich8_hws_flash_ctrl hsflctl;
-	u32 flash_linear_addr;
-	u32 flash_data = 0;
-	s32 ret_val = -E1000_ERR_NVM;
-	u8 count = 0;
-
-	if (size < 1  || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
-		return -E1000_ERR_NVM;
-
-	flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) +
-			    hw->nvm.flash_base_addr;
-
-	do {
-		udelay(1);
-		/* Steps */
-		ret_val = e1000_flash_cycle_init_ich8lan(hw);
-		if (ret_val != 0)
-			break;
-
-		hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
-		/* 0b/1b corresponds to 1 or 2 byte size, respectively. */
-		hsflctl.hsf_ctrl.fldbcount = size - 1;
-		hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ;
-		ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
-
-		ew32flash(ICH_FLASH_FADDR, flash_linear_addr);
-
-		ret_val = e1000_flash_cycle_ich8lan(hw,
-						ICH_FLASH_READ_COMMAND_TIMEOUT);
-
-		/*
-		 * Check if FCERR is set to 1, if set to 1, clear it
-		 * and try the whole sequence a few more times, else
-		 * read in (shift in) the Flash Data0, the order is
-		 * least significant byte first msb to lsb
-		 */
-		if (ret_val == 0) {
-			flash_data = er32flash(ICH_FLASH_FDATA0);
-			if (size == 1)
-				*data = (u8)(flash_data & 0x000000FF);
-			else if (size == 2)
-				*data = (u16)(flash_data & 0x0000FFFF);
-			break;
-		} else {
-			/*
-			 * If we've gotten here, then things are probably
-			 * completely hosed, but if the error condition is
-			 * detected, it won't hurt to give it another try...
-			 * ICH_FLASH_CYCLE_REPEAT_COUNT times.
-			 */
-			hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
-			if (hsfsts.hsf_status.flcerr == 1) {
-				/* Repeat for some time before giving up. */
-				continue;
-			} else if (hsfsts.hsf_status.flcdone == 0) {
-				e_dbg("Timeout error - flash cycle "
-					 "did not complete.\n");
-				break;
-			}
-		}
-	} while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
-
-	return ret_val;
-}
-
-/**
- *  e1000_write_nvm_ich8lan - Write word(s) to the NVM
- *  @hw: pointer to the HW structure
- *  @offset: The offset (in bytes) of the word(s) to write.
- *  @words: Size of data to write in words
- *  @data: Pointer to the word(s) to write at offset.
- *
- *  Writes a byte or word to the NVM using the flash access registers.
- **/
-static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
-				   u16 *data)
-{
-	struct e1000_nvm_info *nvm = &hw->nvm;
-	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
-	u16 i;
-
-	if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
-	    (words == 0)) {
-		e_dbg("nvm parameter(s) out of bounds\n");
-		return -E1000_ERR_NVM;
-	}
-
-	nvm->ops.acquire(hw);
-
-	for (i = 0; i < words; i++) {
-		dev_spec->shadow_ram[offset+i].modified = true;
-		dev_spec->shadow_ram[offset+i].value = data[i];
-	}
-
-	nvm->ops.release(hw);
-
-	return 0;
-}
-
-/**
- *  e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM
- *  @hw: pointer to the HW structure
- *
- *  The NVM checksum is updated by calling the generic update_nvm_checksum,
- *  which writes the checksum to the shadow ram.  The changes in the shadow
- *  ram are then committed to the EEPROM by processing each bank at a time
- *  checking for the modified bit and writing only the pending changes.
- *  After a successful commit, the shadow ram is cleared and is ready for
- *  future writes.
- **/
-static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
-{
-	struct e1000_nvm_info *nvm = &hw->nvm;
-	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
-	u32 i, act_offset, new_bank_offset, old_bank_offset, bank;
-	s32 ret_val;
-	u16 data;
-
-	ret_val = e1000e_update_nvm_checksum_generic(hw);
-	if (ret_val)
-		goto out;
-
-	if (nvm->type != e1000_nvm_flash_sw)
-		goto out;
-
-	nvm->ops.acquire(hw);
-
-	/*
-	 * We're writing to the opposite bank so if we're on bank 1,
-	 * write to bank 0 etc.  We also need to erase the segment that
-	 * is going to be written
-	 */
-	ret_val =  e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
-	if (ret_val) {
-		e_dbg("Could not detect valid bank, assuming bank 0\n");
-		bank = 0;
-	}
-
-	if (bank == 0) {
-		new_bank_offset = nvm->flash_bank_size;
-		old_bank_offset = 0;
-		ret_val = e1000_erase_flash_bank_ich8lan(hw, 1);
-		if (ret_val)
-			goto release;
-	} else {
-		old_bank_offset = nvm->flash_bank_size;
-		new_bank_offset = 0;
-		ret_val = e1000_erase_flash_bank_ich8lan(hw, 0);
-		if (ret_val)
-			goto release;
-	}
-
-	for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
-		/*
-		 * Determine whether to write the value stored
-		 * in the other NVM bank or a modified value stored
-		 * in the shadow RAM
-		 */
-		if (dev_spec->shadow_ram[i].modified) {
-			data = dev_spec->shadow_ram[i].value;
-		} else {
-			ret_val = e1000_read_flash_word_ich8lan(hw, i +
-			                                        old_bank_offset,
-			                                        &data);
-			if (ret_val)
-				break;
-		}
-
-		/*
-		 * If the word is 0x13, then make sure the signature bits
-		 * (15:14) are 11b until the commit has completed.
-		 * This will allow us to write 10b which indicates the
-		 * signature is valid.  We want to do this after the write
-		 * has completed so that we don't mark the segment valid
-		 * while the write is still in progress
-		 */
-		if (i == E1000_ICH_NVM_SIG_WORD)
-			data |= E1000_ICH_NVM_SIG_MASK;
-
-		/* Convert offset to bytes. */
-		act_offset = (i + new_bank_offset) << 1;
-
-		udelay(100);
-		/* Write the bytes to the new bank. */
-		ret_val = e1000_retry_write_flash_byte_ich8lan(hw,
-							       act_offset,
-							       (u8)data);
-		if (ret_val)
-			break;
-
-		udelay(100);
-		ret_val = e1000_retry_write_flash_byte_ich8lan(hw,
-							  act_offset + 1,
-							  (u8)(data >> 8));
-		if (ret_val)
-			break;
-	}
-
-	/*
-	 * Don't bother writing the segment valid bits if sector
-	 * programming failed.
-	 */
-	if (ret_val) {
-		/* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */
-		e_dbg("Flash commit failed.\n");
-		goto release;
-	}
-
-	/*
-	 * Finally validate the new segment by setting bit 15:14
-	 * to 10b in word 0x13 , this can be done without an
-	 * erase as well since these bits are 11 to start with
-	 * and we need to change bit 14 to 0b
-	 */
-	act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
-	ret_val = e1000_read_flash_word_ich8lan(hw, act_offset, &data);
-	if (ret_val)
-		goto release;
-
-	data &= 0xBFFF;
-	ret_val = e1000_retry_write_flash_byte_ich8lan(hw,
-						       act_offset * 2 + 1,
-						       (u8)(data >> 8));
-	if (ret_val)
-		goto release;
-
-	/*
-	 * And invalidate the previously valid segment by setting
-	 * its signature word (0x13) high_byte to 0b. This can be
-	 * done without an erase because flash erase sets all bits
-	 * to 1's. We can write 1's to 0's without an erase
-	 */
-	act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1;
-	ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0);
-	if (ret_val)
-		goto release;
-
-	/* Great!  Everything worked, we can now clear the cached entries. */
-	for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
-		dev_spec->shadow_ram[i].modified = false;
-		dev_spec->shadow_ram[i].value = 0xFFFF;
-	}
-
-release:
-	nvm->ops.release(hw);
-
-	/*
-	 * Reload the EEPROM, or else modifications will not appear
-	 * until after the next adapter reset.
-	 */
-	if (!ret_val) {
-		e1000e_reload_nvm(hw);
-		usleep_range(10000, 20000);
-	}
-
-out:
-	if (ret_val)
-		e_dbg("NVM update error: %d\n", ret_val);
-
-	return ret_val;
-}
-
-/**
- *  e1000_validate_nvm_checksum_ich8lan - Validate EEPROM checksum
- *  @hw: pointer to the HW structure
- *
- *  Check to see if checksum needs to be fixed by reading bit 6 in word 0x19.
- *  If the bit is 0, that the EEPROM had been modified, but the checksum was not
- *  calculated, in which case we need to calculate the checksum and set bit 6.
- **/
-static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 data;
-
-	/*
-	 * Read 0x19 and check bit 6.  If this bit is 0, the checksum
-	 * needs to be fixed.  This bit is an indication that the NVM
-	 * was prepared by OEM software and did not calculate the
-	 * checksum...a likely scenario.
-	 */
-	ret_val = e1000_read_nvm(hw, 0x19, 1, &data);
-	if (ret_val)
-		return ret_val;
-
-	if ((data & 0x40) == 0) {
-		data |= 0x40;
-		ret_val = e1000_write_nvm(hw, 0x19, 1, &data);
-		if (ret_val)
-			return ret_val;
-		ret_val = e1000e_update_nvm_checksum(hw);
-		if (ret_val)
-			return ret_val;
-	}
-
-	return e1000e_validate_nvm_checksum_generic(hw);
-}
-
-/**
- *  e1000e_write_protect_nvm_ich8lan - Make the NVM read-only
- *  @hw: pointer to the HW structure
- *
- *  To prevent malicious write/erase of the NVM, set it to be read-only
- *  so that the hardware ignores all write/erase cycles of the NVM via
- *  the flash control registers.  The shadow-ram copy of the NVM will
- *  still be updated, however any updates to this copy will not stick
- *  across driver reloads.
- **/
-void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw)
-{
-	struct e1000_nvm_info *nvm = &hw->nvm;
-	union ich8_flash_protected_range pr0;
-	union ich8_hws_flash_status hsfsts;
-	u32 gfpreg;
-
-	nvm->ops.acquire(hw);
-
-	gfpreg = er32flash(ICH_FLASH_GFPREG);
-
-	/* Write-protect GbE Sector of NVM */
-	pr0.regval = er32flash(ICH_FLASH_PR0);
-	pr0.range.base = gfpreg & FLASH_GFPREG_BASE_MASK;
-	pr0.range.limit = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK);
-	pr0.range.wpe = true;
-	ew32flash(ICH_FLASH_PR0, pr0.regval);
-
-	/*
-	 * Lock down a subset of GbE Flash Control Registers, e.g.
-	 * PR0 to prevent the write-protection from being lifted.
-	 * Once FLOCKDN is set, the registers protected by it cannot
-	 * be written until FLOCKDN is cleared by a hardware reset.
-	 */
-	hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
-	hsfsts.hsf_status.flockdn = true;
-	ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval);
-
-	nvm->ops.release(hw);
-}
-
-/**
- *  e1000_write_flash_data_ich8lan - Writes bytes to the NVM
- *  @hw: pointer to the HW structure
- *  @offset: The offset (in bytes) of the byte/word to read.
- *  @size: Size of data to read, 1=byte 2=word
- *  @data: The byte(s) to write to the NVM.
- *
- *  Writes one/two bytes to the NVM using the flash access registers.
- **/
-static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
-					  u8 size, u16 data)
-{
-	union ich8_hws_flash_status hsfsts;
-	union ich8_hws_flash_ctrl hsflctl;
-	u32 flash_linear_addr;
-	u32 flash_data = 0;
-	s32 ret_val;
-	u8 count = 0;
-
-	if (size < 1 || size > 2 || data > size * 0xff ||
-	    offset > ICH_FLASH_LINEAR_ADDR_MASK)
-		return -E1000_ERR_NVM;
-
-	flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) +
-			    hw->nvm.flash_base_addr;
-
-	do {
-		udelay(1);
-		/* Steps */
-		ret_val = e1000_flash_cycle_init_ich8lan(hw);
-		if (ret_val)
-			break;
-
-		hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
-		/* 0b/1b corresponds to 1 or 2 byte size, respectively. */
-		hsflctl.hsf_ctrl.fldbcount = size -1;
-		hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;
-		ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
-
-		ew32flash(ICH_FLASH_FADDR, flash_linear_addr);
-
-		if (size == 1)
-			flash_data = (u32)data & 0x00FF;
-		else
-			flash_data = (u32)data;
-
-		ew32flash(ICH_FLASH_FDATA0, flash_data);
-
-		/*
-		 * check if FCERR is set to 1 , if set to 1, clear it
-		 * and try the whole sequence a few more times else done
-		 */
-		ret_val = e1000_flash_cycle_ich8lan(hw,
-					       ICH_FLASH_WRITE_COMMAND_TIMEOUT);
-		if (!ret_val)
-			break;
-
-		/*
-		 * If we're here, then things are most likely
-		 * completely hosed, but if the error condition
-		 * is detected, it won't hurt to give it another
-		 * try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
-		 */
-		hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
-		if (hsfsts.hsf_status.flcerr == 1)
-			/* Repeat for some time before giving up. */
-			continue;
-		if (hsfsts.hsf_status.flcdone == 0) {
-			e_dbg("Timeout error - flash cycle "
-				 "did not complete.");
-			break;
-		}
-	} while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
-
-	return ret_val;
-}
-
-/**
- *  e1000_write_flash_byte_ich8lan - Write a single byte to NVM
- *  @hw: pointer to the HW structure
- *  @offset: The index of the byte to read.
- *  @data: The byte to write to the NVM.
- *
- *  Writes a single byte to the NVM using the flash access registers.
- **/
-static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
-					  u8 data)
-{
-	u16 word = (u16)data;
-
-	return e1000_write_flash_data_ich8lan(hw, offset, 1, word);
-}
-
-/**
- *  e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM
- *  @hw: pointer to the HW structure
- *  @offset: The offset of the byte to write.
- *  @byte: The byte to write to the NVM.
- *
- *  Writes a single byte to the NVM using the flash access registers.
- *  Goes through a retry algorithm before giving up.
- **/
-static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
-						u32 offset, u8 byte)
-{
-	s32 ret_val;
-	u16 program_retries;
-
-	ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte);
-	if (!ret_val)
-		return ret_val;
-
-	for (program_retries = 0; program_retries < 100; program_retries++) {
-		e_dbg("Retrying Byte %2.2X at offset %u\n", byte, offset);
-		udelay(100);
-		ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte);
-		if (!ret_val)
-			break;
-	}
-	if (program_retries == 100)
-		return -E1000_ERR_NVM;
-
-	return 0;
-}
-
-/**
- *  e1000_erase_flash_bank_ich8lan - Erase a bank (4k) from NVM
- *  @hw: pointer to the HW structure
- *  @bank: 0 for first bank, 1 for second bank, etc.
- *
- *  Erases the bank specified. Each bank is a 4k block. Banks are 0 based.
- *  bank N is 4096 * N + flash_reg_addr.
- **/
-static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
-{
-	struct e1000_nvm_info *nvm = &hw->nvm;
-	union ich8_hws_flash_status hsfsts;
-	union ich8_hws_flash_ctrl hsflctl;
-	u32 flash_linear_addr;
-	/* bank size is in 16bit words - adjust to bytes */
-	u32 flash_bank_size = nvm->flash_bank_size * 2;
-	s32 ret_val;
-	s32 count = 0;
-	s32 j, iteration, sector_size;
-
-	hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
-
-	/*
-	 * Determine HW Sector size: Read BERASE bits of hw flash status
-	 * register
-	 * 00: The Hw sector is 256 bytes, hence we need to erase 16
-	 *     consecutive sectors.  The start index for the nth Hw sector
-	 *     can be calculated as = bank * 4096 + n * 256
-	 * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector.
-	 *     The start index for the nth Hw sector can be calculated
-	 *     as = bank * 4096
-	 * 10: The Hw sector is 8K bytes, nth sector = bank * 8192
-	 *     (ich9 only, otherwise error condition)
-	 * 11: The Hw sector is 64K bytes, nth sector = bank * 65536
-	 */
-	switch (hsfsts.hsf_status.berasesz) {
-	case 0:
-		/* Hw sector size 256 */
-		sector_size = ICH_FLASH_SEG_SIZE_256;
-		iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_256;
-		break;
-	case 1:
-		sector_size = ICH_FLASH_SEG_SIZE_4K;
-		iteration = 1;
-		break;
-	case 2:
-		sector_size = ICH_FLASH_SEG_SIZE_8K;
-		iteration = 1;
-		break;
-	case 3:
-		sector_size = ICH_FLASH_SEG_SIZE_64K;
-		iteration = 1;
-		break;
-	default:
-		return -E1000_ERR_NVM;
-	}
-
-	/* Start with the base address, then add the sector offset. */
-	flash_linear_addr = hw->nvm.flash_base_addr;
-	flash_linear_addr += (bank) ? flash_bank_size : 0;
-
-	for (j = 0; j < iteration ; j++) {
-		do {
-			/* Steps */
-			ret_val = e1000_flash_cycle_init_ich8lan(hw);
-			if (ret_val)
-				return ret_val;
-
-			/*
-			 * Write a value 11 (block Erase) in Flash
-			 * Cycle field in hw flash control
-			 */
-			hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
-			hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
-			ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
-
-			/*
-			 * Write the last 24 bits of an index within the
-			 * block into Flash Linear address field in Flash
-			 * Address.
-			 */
-			flash_linear_addr += (j * sector_size);
-			ew32flash(ICH_FLASH_FADDR, flash_linear_addr);
-
-			ret_val = e1000_flash_cycle_ich8lan(hw,
-					       ICH_FLASH_ERASE_COMMAND_TIMEOUT);
-			if (ret_val == 0)
-				break;
-
-			/*
-			 * Check if FCERR is set to 1.  If 1,
-			 * clear it and try the whole sequence
-			 * a few more times else Done
-			 */
-			hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
-			if (hsfsts.hsf_status.flcerr == 1)
-				/* repeat for some time before giving up */
-				continue;
-			else if (hsfsts.hsf_status.flcdone == 0)
-				return ret_val;
-		} while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT);
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_valid_led_default_ich8lan - Set the default LED settings
- *  @hw: pointer to the HW structure
- *  @data: Pointer to the LED settings
- *
- *  Reads the LED default settings from the NVM to data.  If the NVM LED
- *  settings is all 0's or F's, set the LED default to a valid LED default
- *  setting.
- **/
-static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data)
-{
-	s32 ret_val;
-
-	ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data);
-	if (ret_val) {
-		e_dbg("NVM Read Error\n");
-		return ret_val;
-	}
-
-	if (*data == ID_LED_RESERVED_0000 ||
-	    *data == ID_LED_RESERVED_FFFF)
-		*data = ID_LED_DEFAULT_ICH8LAN;
-
-	return 0;
-}
-
-/**
- *  e1000_id_led_init_pchlan - store LED configurations
- *  @hw: pointer to the HW structure
- *
- *  PCH does not control LEDs via the LEDCTL register, rather it uses
- *  the PHY LED configuration register.
- *
- *  PCH also does not have an "always on" or "always off" mode which
- *  complicates the ID feature.  Instead of using the "on" mode to indicate
- *  in ledctl_mode2 the LEDs to use for ID (see e1000e_id_led_init()),
- *  use "link_up" mode.  The LEDs will still ID on request if there is no
- *  link based on logic in e1000_led_[on|off]_pchlan().
- **/
-static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-	s32 ret_val;
-	const u32 ledctl_on = E1000_LEDCTL_MODE_LINK_UP;
-	const u32 ledctl_off = E1000_LEDCTL_MODE_LINK_UP | E1000_PHY_LED0_IVRT;
-	u16 data, i, temp, shift;
-
-	/* Get default ID LED modes */
-	ret_val = hw->nvm.ops.valid_led_default(hw, &data);
-	if (ret_val)
-		goto out;
-
-	mac->ledctl_default = er32(LEDCTL);
-	mac->ledctl_mode1 = mac->ledctl_default;
-	mac->ledctl_mode2 = mac->ledctl_default;
-
-	for (i = 0; i < 4; i++) {
-		temp = (data >> (i << 2)) & E1000_LEDCTL_LED0_MODE_MASK;
-		shift = (i * 5);
-		switch (temp) {
-		case ID_LED_ON1_DEF2:
-		case ID_LED_ON1_ON2:
-		case ID_LED_ON1_OFF2:
-			mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift);
-			mac->ledctl_mode1 |= (ledctl_on << shift);
-			break;
-		case ID_LED_OFF1_DEF2:
-		case ID_LED_OFF1_ON2:
-		case ID_LED_OFF1_OFF2:
-			mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift);
-			mac->ledctl_mode1 |= (ledctl_off << shift);
-			break;
-		default:
-			/* Do nothing */
-			break;
-		}
-		switch (temp) {
-		case ID_LED_DEF1_ON2:
-		case ID_LED_ON1_ON2:
-		case ID_LED_OFF1_ON2:
-			mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift);
-			mac->ledctl_mode2 |= (ledctl_on << shift);
-			break;
-		case ID_LED_DEF1_OFF2:
-		case ID_LED_ON1_OFF2:
-		case ID_LED_OFF1_OFF2:
-			mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift);
-			mac->ledctl_mode2 |= (ledctl_off << shift);
-			break;
-		default:
-			/* Do nothing */
-			break;
-		}
-	}
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_get_bus_info_ich8lan - Get/Set the bus type and width
- *  @hw: pointer to the HW structure
- *
- *  ICH8 use the PCI Express bus, but does not contain a PCI Express Capability
- *  register, so the the bus width is hard coded.
- **/
-static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
-{
-	struct e1000_bus_info *bus = &hw->bus;
-	s32 ret_val;
-
-	ret_val = e1000e_get_bus_info_pcie(hw);
-
-	/*
-	 * ICH devices are "PCI Express"-ish.  They have
-	 * a configuration space, but do not contain
-	 * PCI Express Capability registers, so bus width
-	 * must be hardcoded.
-	 */
-	if (bus->width == e1000_bus_width_unknown)
-		bus->width = e1000_bus_width_pcie_x1;
-
-	return ret_val;
-}
-
-/**
- *  e1000_reset_hw_ich8lan - Reset the hardware
- *  @hw: pointer to the HW structure
- *
- *  Does a full reset of the hardware which includes a reset of the PHY and
- *  MAC.
- **/
-static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
-{
-	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
-	u16 reg;
-	u32 ctrl, kab;
-	s32 ret_val;
-
-	/*
-	 * Prevent the PCI-E bus from sticking if there is no TLP connection
-	 * on the last TLP read/write transaction when MAC is reset.
-	 */
-	ret_val = e1000e_disable_pcie_master(hw);
-	if (ret_val)
-		e_dbg("PCI-E Master disable polling has failed.\n");
-
-	e_dbg("Masking off all interrupts\n");
-	ew32(IMC, 0xffffffff);
-
-	/*
-	 * Disable the Transmit and Receive units.  Then delay to allow
-	 * any pending transactions to complete before we hit the MAC
-	 * with the global reset.
-	 */
-	ew32(RCTL, 0);
-	ew32(TCTL, E1000_TCTL_PSP);
-	e1e_flush();
-
-	usleep_range(10000, 20000);
-
-	/* Workaround for ICH8 bit corruption issue in FIFO memory */
-	if (hw->mac.type == e1000_ich8lan) {
-		/* Set Tx and Rx buffer allocation to 8k apiece. */
-		ew32(PBA, E1000_PBA_8K);
-		/* Set Packet Buffer Size to 16k. */
-		ew32(PBS, E1000_PBS_16K);
-	}
-
-	if (hw->mac.type == e1000_pchlan) {
-		/* Save the NVM K1 bit setting*/
-		ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &reg);
-		if (ret_val)
-			return ret_val;
-
-		if (reg & E1000_NVM_K1_ENABLE)
-			dev_spec->nvm_k1_enabled = true;
-		else
-			dev_spec->nvm_k1_enabled = false;
-	}
-
-	ctrl = er32(CTRL);
-
-	if (!e1000_check_reset_block(hw)) {
-		/*
-		 * Full-chip reset requires MAC and PHY reset at the same
-		 * time to make sure the interface between MAC and the
-		 * external PHY is reset.
-		 */
-		ctrl |= E1000_CTRL_PHY_RST;
-
-		/*
-		 * Gate automatic PHY configuration by hardware on
-		 * non-managed 82579
-		 */
-		if ((hw->mac.type == e1000_pch2lan) &&
-		    !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
-			e1000_gate_hw_phy_config_ich8lan(hw, true);
-	}
-	ret_val = e1000_acquire_swflag_ich8lan(hw);
-	e_dbg("Issuing a global reset to ich8lan\n");
-	ew32(CTRL, (ctrl | E1000_CTRL_RST));
-	/* cannot issue a flush here because it hangs the hardware */
-	msleep(20);
-
-	if (!ret_val)
-		mutex_unlock(&swflag_mutex);
-
-	if (ctrl & E1000_CTRL_PHY_RST) {
-		ret_val = hw->phy.ops.get_cfg_done(hw);
-		if (ret_val)
-			goto out;
-
-		ret_val = e1000_post_phy_reset_ich8lan(hw);
-		if (ret_val)
-			goto out;
-	}
-
-	/*
-	 * For PCH, this write will make sure that any noise
-	 * will be detected as a CRC error and be dropped rather than show up
-	 * as a bad packet to the DMA engine.
-	 */
-	if (hw->mac.type == e1000_pchlan)
-		ew32(CRC_OFFSET, 0x65656565);
-
-	ew32(IMC, 0xffffffff);
-	er32(ICR);
-
-	kab = er32(KABGTXD);
-	kab |= E1000_KABGTXD_BGSQLBIAS;
-	ew32(KABGTXD, kab);
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_init_hw_ich8lan - Initialize the hardware
- *  @hw: pointer to the HW structure
- *
- *  Prepares the hardware for transmit and receive by doing the following:
- *   - initialize hardware bits
- *   - initialize LED identification
- *   - setup receive address registers
- *   - setup flow control
- *   - setup transmit descriptors
- *   - clear statistics
- **/
-static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-	u32 ctrl_ext, txdctl, snoop;
-	s32 ret_val;
-	u16 i;
-
-	e1000_initialize_hw_bits_ich8lan(hw);
-
-	/* Initialize identification LED */
-	ret_val = mac->ops.id_led_init(hw);
-	if (ret_val)
-		e_dbg("Error initializing identification LED\n");
-		/* This is not fatal and we should not stop init due to this */
-
-	/* Setup the receive address. */
-	e1000e_init_rx_addrs(hw, mac->rar_entry_count);
-
-	/* Zero out the Multicast HASH table */
-	e_dbg("Zeroing the MTA\n");
-	for (i = 0; i < mac->mta_reg_count; i++)
-		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
-
-	/*
-	 * The 82578 Rx buffer will stall if wakeup is enabled in host and
-	 * the ME.  Disable wakeup by clearing the host wakeup bit.
-	 * Reset the phy after disabling host wakeup to reset the Rx buffer.
-	 */
-	if (hw->phy.type == e1000_phy_82578) {
-		e1e_rphy(hw, BM_PORT_GEN_CFG, &i);
-		i &= ~BM_WUC_HOST_WU_BIT;
-		e1e_wphy(hw, BM_PORT_GEN_CFG, i);
-		ret_val = e1000_phy_hw_reset_ich8lan(hw);
-		if (ret_val)
-			return ret_val;
-	}
-
-	/* Setup link and flow control */
-	ret_val = e1000_setup_link_ich8lan(hw);
-
-	/* Set the transmit descriptor write-back policy for both queues */
-	txdctl = er32(TXDCTL(0));
-	txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
-		 E1000_TXDCTL_FULL_TX_DESC_WB;
-	txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |
-		 E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
-	ew32(TXDCTL(0), txdctl);
-	txdctl = er32(TXDCTL(1));
-	txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
-		 E1000_TXDCTL_FULL_TX_DESC_WB;
-	txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |
-		 E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
-	ew32(TXDCTL(1), txdctl);
-
-	/*
-	 * ICH8 has opposite polarity of no_snoop bits.
-	 * By default, we should use snoop behavior.
-	 */
-	if (mac->type == e1000_ich8lan)
-		snoop = PCIE_ICH8_SNOOP_ALL;
-	else
-		snoop = (u32) ~(PCIE_NO_SNOOP_ALL);
-	e1000e_set_pcie_no_snoop(hw, snoop);
-
-	ctrl_ext = er32(CTRL_EXT);
-	ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
-	ew32(CTRL_EXT, ctrl_ext);
-
-	/*
-	 * Clear all of the statistics registers (clear on read).  It is
-	 * important that we do this after we have tried to establish link
-	 * because the symbol error count will increment wildly if there
-	 * is no link.
-	 */
-	e1000_clear_hw_cntrs_ich8lan(hw);
-
-	return 0;
-}
-/**
- *  e1000_initialize_hw_bits_ich8lan - Initialize required hardware bits
- *  @hw: pointer to the HW structure
- *
- *  Sets/Clears required hardware bits necessary for correctly setting up the
- *  hardware for transmit and receive.
- **/
-static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
-{
-	u32 reg;
-
-	/* Extended Device Control */
-	reg = er32(CTRL_EXT);
-	reg |= (1 << 22);
-	/* Enable PHY low-power state when MAC is at D3 w/o WoL */
-	if (hw->mac.type >= e1000_pchlan)
-		reg |= E1000_CTRL_EXT_PHYPDEN;
-	ew32(CTRL_EXT, reg);
-
-	/* Transmit Descriptor Control 0 */
-	reg = er32(TXDCTL(0));
-	reg |= (1 << 22);
-	ew32(TXDCTL(0), reg);
-
-	/* Transmit Descriptor Control 1 */
-	reg = er32(TXDCTL(1));
-	reg |= (1 << 22);
-	ew32(TXDCTL(1), reg);
-
-	/* Transmit Arbitration Control 0 */
-	reg = er32(TARC(0));
-	if (hw->mac.type == e1000_ich8lan)
-		reg |= (1 << 28) | (1 << 29);
-	reg |= (1 << 23) | (1 << 24) | (1 << 26) | (1 << 27);
-	ew32(TARC(0), reg);
-
-	/* Transmit Arbitration Control 1 */
-	reg = er32(TARC(1));
-	if (er32(TCTL) & E1000_TCTL_MULR)
-		reg &= ~(1 << 28);
-	else
-		reg |= (1 << 28);
-	reg |= (1 << 24) | (1 << 26) | (1 << 30);
-	ew32(TARC(1), reg);
-
-	/* Device Status */
-	if (hw->mac.type == e1000_ich8lan) {
-		reg = er32(STATUS);
-		reg &= ~(1 << 31);
-		ew32(STATUS, reg);
-	}
-
-	/*
-	 * work-around descriptor data corruption issue during nfs v2 udp
-	 * traffic, just disable the nfs filtering capability
-	 */
-	reg = er32(RFCTL);
-	reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS);
-	ew32(RFCTL, reg);
-}
-
-/**
- *  e1000_setup_link_ich8lan - Setup flow control and link settings
- *  @hw: pointer to the HW structure
- *
- *  Determines which flow control settings to use, then configures flow
- *  control.  Calls the appropriate media-specific link configuration
- *  function.  Assuming the adapter has a valid link partner, a valid link
- *  should be established.  Assumes the hardware has previously been reset
- *  and the transmitter and receiver are not enabled.
- **/
-static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
-{
-	s32 ret_val;
-
-	if (e1000_check_reset_block(hw))
-		return 0;
-
-	/*
-	 * ICH parts do not have a word in the NVM to determine
-	 * the default flow control setting, so we explicitly
-	 * set it to full.
-	 */
-	if (hw->fc.requested_mode == e1000_fc_default) {
-		/* Workaround h/w hang when Tx flow control enabled */
-		if (hw->mac.type == e1000_pchlan)
-			hw->fc.requested_mode = e1000_fc_rx_pause;
-		else
-			hw->fc.requested_mode = e1000_fc_full;
-	}
-
-	/*
-	 * Save off the requested flow control mode for use later.  Depending
-	 * on the link partner's capabilities, we may or may not use this mode.
-	 */
-	hw->fc.current_mode = hw->fc.requested_mode;
-
-	e_dbg("After fix-ups FlowControl is now = %x\n",
-		hw->fc.current_mode);
-
-	/* Continue to configure the copper link. */
-	ret_val = e1000_setup_copper_link_ich8lan(hw);
-	if (ret_val)
-		return ret_val;
-
-	ew32(FCTTV, hw->fc.pause_time);
-	if ((hw->phy.type == e1000_phy_82578) ||
-	    (hw->phy.type == e1000_phy_82579) ||
-	    (hw->phy.type == e1000_phy_82577)) {
-		ew32(FCRTV_PCH, hw->fc.refresh_time);
-
-		ret_val = e1e_wphy(hw, PHY_REG(BM_PORT_CTRL_PAGE, 27),
-				   hw->fc.pause_time);
-		if (ret_val)
-			return ret_val;
-	}
-
-	return e1000e_set_fc_watermarks(hw);
-}
-
-/**
- *  e1000_setup_copper_link_ich8lan - Configure MAC/PHY interface
- *  @hw: pointer to the HW structure
- *
- *  Configures the kumeran interface to the PHY to wait the appropriate time
- *  when polling the PHY, then call the generic setup_copper_link to finish
- *  configuring the copper link.
- **/
-static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
-{
-	u32 ctrl;
-	s32 ret_val;
-	u16 reg_data;
-
-	ctrl = er32(CTRL);
-	ctrl |= E1000_CTRL_SLU;
-	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
-	ew32(CTRL, ctrl);
-
-	/*
-	 * Set the mac to wait the maximum time between each iteration
-	 * and increase the max iterations when polling the phy;
-	 * this fixes erroneous timeouts at 10Mbps.
-	 */
-	ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_TIMEOUTS, 0xFFFF);
-	if (ret_val)
-		return ret_val;
-	ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
-	                               &reg_data);
-	if (ret_val)
-		return ret_val;
-	reg_data |= 0x3F;
-	ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
-	                                reg_data);
-	if (ret_val)
-		return ret_val;
-
-	switch (hw->phy.type) {
-	case e1000_phy_igp_3:
-		ret_val = e1000e_copper_link_setup_igp(hw);
-		if (ret_val)
-			return ret_val;
-		break;
-	case e1000_phy_bm:
-	case e1000_phy_82578:
-		ret_val = e1000e_copper_link_setup_m88(hw);
-		if (ret_val)
-			return ret_val;
-		break;
-	case e1000_phy_82577:
-	case e1000_phy_82579:
-		ret_val = e1000_copper_link_setup_82577(hw);
-		if (ret_val)
-			return ret_val;
-		break;
-	case e1000_phy_ife:
-		ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &reg_data);
-		if (ret_val)
-			return ret_val;
-
-		reg_data &= ~IFE_PMC_AUTO_MDIX;
-
-		switch (hw->phy.mdix) {
-		case 1:
-			reg_data &= ~IFE_PMC_FORCE_MDIX;
-			break;
-		case 2:
-			reg_data |= IFE_PMC_FORCE_MDIX;
-			break;
-		case 0:
-		default:
-			reg_data |= IFE_PMC_AUTO_MDIX;
-			break;
-		}
-		ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, reg_data);
-		if (ret_val)
-			return ret_val;
-		break;
-	default:
-		break;
-	}
-	return e1000e_setup_copper_link(hw);
-}
-
-/**
- *  e1000_get_link_up_info_ich8lan - Get current link speed and duplex
- *  @hw: pointer to the HW structure
- *  @speed: pointer to store current link speed
- *  @duplex: pointer to store the current link duplex
- *
- *  Calls the generic get_speed_and_duplex to retrieve the current link
- *  information and then calls the Kumeran lock loss workaround for links at
- *  gigabit speeds.
- **/
-static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed,
-					  u16 *duplex)
-{
-	s32 ret_val;
-
-	ret_val = e1000e_get_speed_and_duplex_copper(hw, speed, duplex);
-	if (ret_val)
-		return ret_val;
-
-	if ((hw->mac.type == e1000_ich8lan) &&
-	    (hw->phy.type == e1000_phy_igp_3) &&
-	    (*speed == SPEED_1000)) {
-		ret_val = e1000_kmrn_lock_loss_workaround_ich8lan(hw);
-	}
-
-	return ret_val;
-}
-
-/**
- *  e1000_kmrn_lock_loss_workaround_ich8lan - Kumeran workaround
- *  @hw: pointer to the HW structure
- *
- *  Work-around for 82566 Kumeran PCS lock loss:
- *  On link status change (i.e. PCI reset, speed change) and link is up and
- *  speed is gigabit-
- *    0) if workaround is optionally disabled do nothing
- *    1) wait 1ms for Kumeran link to come up
- *    2) check Kumeran Diagnostic register PCS lock loss bit
- *    3) if not set the link is locked (all is good), otherwise...
- *    4) reset the PHY
- *    5) repeat up to 10 times
- *  Note: this is only called for IGP3 copper when speed is 1gb.
- **/
-static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
-{
-	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
-	u32 phy_ctrl;
-	s32 ret_val;
-	u16 i, data;
-	bool link;
-
-	if (!dev_spec->kmrn_lock_loss_workaround_enabled)
-		return 0;
-
-	/*
-	 * Make sure link is up before proceeding.  If not just return.
-	 * Attempting this while link is negotiating fouled up link
-	 * stability
-	 */
-	ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
-	if (!link)
-		return 0;
-
-	for (i = 0; i < 10; i++) {
-		/* read once to clear */
-		ret_val = e1e_rphy(hw, IGP3_KMRN_DIAG, &data);
-		if (ret_val)
-			return ret_val;
-		/* and again to get new status */
-		ret_val = e1e_rphy(hw, IGP3_KMRN_DIAG, &data);
-		if (ret_val)
-			return ret_val;
-
-		/* check for PCS lock */
-		if (!(data & IGP3_KMRN_DIAG_PCS_LOCK_LOSS))
-			return 0;
-
-		/* Issue PHY reset */
-		e1000_phy_hw_reset(hw);
-		mdelay(5);
-	}
-	/* Disable GigE link negotiation */
-	phy_ctrl = er32(PHY_CTRL);
-	phy_ctrl |= (E1000_PHY_CTRL_GBE_DISABLE |
-		     E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
-	ew32(PHY_CTRL, phy_ctrl);
-
-	/*
-	 * Call gig speed drop workaround on Gig disable before accessing
-	 * any PHY registers
-	 */
-	e1000e_gig_downshift_workaround_ich8lan(hw);
-
-	/* unable to acquire PCS lock */
-	return -E1000_ERR_PHY;
-}
-
-/**
- *  e1000_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state
- *  @hw: pointer to the HW structure
- *  @state: boolean value used to set the current Kumeran workaround state
- *
- *  If ICH8, set the current Kumeran workaround state (enabled - true
- *  /disabled - false).
- **/
-void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
-						 bool state)
-{
-	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
-
-	if (hw->mac.type != e1000_ich8lan) {
-		e_dbg("Workaround applies to ICH8 only.\n");
-		return;
-	}
-
-	dev_spec->kmrn_lock_loss_workaround_enabled = state;
-}
-
-/**
- *  e1000_ipg3_phy_powerdown_workaround_ich8lan - Power down workaround on D3
- *  @hw: pointer to the HW structure
- *
- *  Workaround for 82566 power-down on D3 entry:
- *    1) disable gigabit link
- *    2) write VR power-down enable
- *    3) read it back
- *  Continue if successful, else issue LCD reset and repeat
- **/
-void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw)
-{
-	u32 reg;
-	u16 data;
-	u8  retry = 0;
-
-	if (hw->phy.type != e1000_phy_igp_3)
-		return;
-
-	/* Try the workaround twice (if needed) */
-	do {
-		/* Disable link */
-		reg = er32(PHY_CTRL);
-		reg |= (E1000_PHY_CTRL_GBE_DISABLE |
-			E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
-		ew32(PHY_CTRL, reg);
-
-		/*
-		 * Call gig speed drop workaround on Gig disable before
-		 * accessing any PHY registers
-		 */
-		if (hw->mac.type == e1000_ich8lan)
-			e1000e_gig_downshift_workaround_ich8lan(hw);
-
-		/* Write VR power-down enable */
-		e1e_rphy(hw, IGP3_VR_CTRL, &data);
-		data &= ~IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK;
-		e1e_wphy(hw, IGP3_VR_CTRL, data | IGP3_VR_CTRL_MODE_SHUTDOWN);
-
-		/* Read it back and test */
-		e1e_rphy(hw, IGP3_VR_CTRL, &data);
-		data &= IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK;
-		if ((data == IGP3_VR_CTRL_MODE_SHUTDOWN) || retry)
-			break;
-
-		/* Issue PHY reset and repeat at most one more time */
-		reg = er32(CTRL);
-		ew32(CTRL, reg | E1000_CTRL_PHY_RST);
-		retry++;
-	} while (retry);
-}
-
-/**
- *  e1000e_gig_downshift_workaround_ich8lan - WoL from S5 stops working
- *  @hw: pointer to the HW structure
- *
- *  Steps to take when dropping from 1Gb/s (eg. link cable removal (LSC),
- *  LPLU, Gig disable, MDIC PHY reset):
- *    1) Set Kumeran Near-end loopback
- *    2) Clear Kumeran Near-end loopback
- *  Should only be called for ICH8[m] devices with IGP_3 Phy.
- **/
-void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 reg_data;
-
-	if ((hw->mac.type != e1000_ich8lan) ||
-	    (hw->phy.type != e1000_phy_igp_3))
-		return;
-
-	ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET,
-				      &reg_data);
-	if (ret_val)
-		return;
-	reg_data |= E1000_KMRNCTRLSTA_DIAG_NELPBK;
-	ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET,
-				       reg_data);
-	if (ret_val)
-		return;
-	reg_data &= ~E1000_KMRNCTRLSTA_DIAG_NELPBK;
-	ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET,
-				       reg_data);
-}
-
-/**
- *  e1000_suspend_workarounds_ich8lan - workarounds needed during S0->Sx
- *  @hw: pointer to the HW structure
- *
- *  During S0 to Sx transition, it is possible the link remains at gig
- *  instead of negotiating to a lower speed.  Before going to Sx, set
- *  'LPLU Enabled' and 'Gig Disable' to force link speed negotiation
- *  to a lower speed.  For PCH and newer parts, the OEM bits PHY register
- *  (LED, GbE disable and LPLU configurations) also needs to be written.
- **/
-void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
-{
-	u32 phy_ctrl;
-	s32 ret_val;
-
-	phy_ctrl = er32(PHY_CTRL);
-	phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_GBE_DISABLE;
-	ew32(PHY_CTRL, phy_ctrl);
-
-	if (hw->mac.type >= e1000_pchlan) {
-		e1000_oem_bits_config_ich8lan(hw, false);
-		ret_val = hw->phy.ops.acquire(hw);
-		if (ret_val)
-			return;
-		e1000_write_smbus_addr(hw);
-		hw->phy.ops.release(hw);
-	}
-}
-
-/**
- *  e1000_resume_workarounds_pchlan - workarounds needed during Sx->S0
- *  @hw: pointer to the HW structure
- *
- *  During Sx to S0 transitions on non-managed devices or managed devices
- *  on which PHY resets are not blocked, if the PHY registers cannot be
- *  accessed properly by the s/w toggle the LANPHYPC value to power cycle
- *  the PHY.
- **/
-void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
-{
-	u32 fwsm;
-
-	if (hw->mac.type != e1000_pch2lan)
-		return;
-
-	fwsm = er32(FWSM);
-	if (!(fwsm & E1000_ICH_FWSM_FW_VALID) || !e1000_check_reset_block(hw)) {
-		u16 phy_id1, phy_id2;
-		s32 ret_val;
-
-		ret_val = hw->phy.ops.acquire(hw);
-		if (ret_val) {
-			e_dbg("Failed to acquire PHY semaphore in resume\n");
-			return;
-		}
-
-		/* Test access to the PHY registers by reading the ID regs */
-		ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_id1);
-		if (ret_val)
-			goto release;
-		ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_id2);
-		if (ret_val)
-			goto release;
-
-		if (hw->phy.id == ((u32)(phy_id1 << 16) |
-				   (u32)(phy_id2 & PHY_REVISION_MASK)))
-			goto release;
-
-		e1000_toggle_lanphypc_value_ich8lan(hw);
-
-		hw->phy.ops.release(hw);
-		msleep(50);
-		e1000_phy_hw_reset(hw);
-		msleep(50);
-		return;
-	}
-
-release:
-	hw->phy.ops.release(hw);
-
-	return;
-}
-
-/**
- *  e1000_cleanup_led_ich8lan - Restore the default LED operation
- *  @hw: pointer to the HW structure
- *
- *  Return the LED back to the default configuration.
- **/
-static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw)
-{
-	if (hw->phy.type == e1000_phy_ife)
-		return e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0);
-
-	ew32(LEDCTL, hw->mac.ledctl_default);
-	return 0;
-}
-
-/**
- *  e1000_led_on_ich8lan - Turn LEDs on
- *  @hw: pointer to the HW structure
- *
- *  Turn on the LEDs.
- **/
-static s32 e1000_led_on_ich8lan(struct e1000_hw *hw)
-{
-	if (hw->phy.type == e1000_phy_ife)
-		return e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED,
-				(IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON));
-
-	ew32(LEDCTL, hw->mac.ledctl_mode2);
-	return 0;
-}
-
-/**
- *  e1000_led_off_ich8lan - Turn LEDs off
- *  @hw: pointer to the HW structure
- *
- *  Turn off the LEDs.
- **/
-static s32 e1000_led_off_ich8lan(struct e1000_hw *hw)
-{
-	if (hw->phy.type == e1000_phy_ife)
-		return e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED,
-				(IFE_PSCL_PROBE_MODE |
-				 IFE_PSCL_PROBE_LEDS_OFF));
-
-	ew32(LEDCTL, hw->mac.ledctl_mode1);
-	return 0;
-}
-
-/**
- *  e1000_setup_led_pchlan - Configures SW controllable LED
- *  @hw: pointer to the HW structure
- *
- *  This prepares the SW controllable LED for use.
- **/
-static s32 e1000_setup_led_pchlan(struct e1000_hw *hw)
-{
-	return e1e_wphy(hw, HV_LED_CONFIG, (u16)hw->mac.ledctl_mode1);
-}
-
-/**
- *  e1000_cleanup_led_pchlan - Restore the default LED operation
- *  @hw: pointer to the HW structure
- *
- *  Return the LED back to the default configuration.
- **/
-static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw)
-{
-	return e1e_wphy(hw, HV_LED_CONFIG, (u16)hw->mac.ledctl_default);
-}
-
-/**
- *  e1000_led_on_pchlan - Turn LEDs on
- *  @hw: pointer to the HW structure
- *
- *  Turn on the LEDs.
- **/
-static s32 e1000_led_on_pchlan(struct e1000_hw *hw)
-{
-	u16 data = (u16)hw->mac.ledctl_mode2;
-	u32 i, led;
-
-	/*
-	 * If no link, then turn LED on by setting the invert bit
-	 * for each LED that's mode is "link_up" in ledctl_mode2.
-	 */
-	if (!(er32(STATUS) & E1000_STATUS_LU)) {
-		for (i = 0; i < 3; i++) {
-			led = (data >> (i * 5)) & E1000_PHY_LED0_MASK;
-			if ((led & E1000_PHY_LED0_MODE_MASK) !=
-			    E1000_LEDCTL_MODE_LINK_UP)
-				continue;
-			if (led & E1000_PHY_LED0_IVRT)
-				data &= ~(E1000_PHY_LED0_IVRT << (i * 5));
-			else
-				data |= (E1000_PHY_LED0_IVRT << (i * 5));
-		}
-	}
-
-	return e1e_wphy(hw, HV_LED_CONFIG, data);
-}
-
-/**
- *  e1000_led_off_pchlan - Turn LEDs off
- *  @hw: pointer to the HW structure
- *
- *  Turn off the LEDs.
- **/
-static s32 e1000_led_off_pchlan(struct e1000_hw *hw)
-{
-	u16 data = (u16)hw->mac.ledctl_mode1;
-	u32 i, led;
-
-	/*
-	 * If no link, then turn LED off by clearing the invert bit
-	 * for each LED that's mode is "link_up" in ledctl_mode1.
-	 */
-	if (!(er32(STATUS) & E1000_STATUS_LU)) {
-		for (i = 0; i < 3; i++) {
-			led = (data >> (i * 5)) & E1000_PHY_LED0_MASK;
-			if ((led & E1000_PHY_LED0_MODE_MASK) !=
-			    E1000_LEDCTL_MODE_LINK_UP)
-				continue;
-			if (led & E1000_PHY_LED0_IVRT)
-				data &= ~(E1000_PHY_LED0_IVRT << (i * 5));
-			else
-				data |= (E1000_PHY_LED0_IVRT << (i * 5));
-		}
-	}
-
-	return e1e_wphy(hw, HV_LED_CONFIG, data);
-}
-
-/**
- *  e1000_get_cfg_done_ich8lan - Read config done bit after Full or PHY reset
- *  @hw: pointer to the HW structure
- *
- *  Read appropriate register for the config done bit for completion status
- *  and configure the PHY through s/w for EEPROM-less parts.
- *
- *  NOTE: some silicon which is EEPROM-less will fail trying to read the
- *  config done bit, so only an error is logged and continues.  If we were
- *  to return with error, EEPROM-less silicon would not be able to be reset
- *  or change link.
- **/
-static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
-{
-	s32 ret_val = 0;
-	u32 bank = 0;
-	u32 status;
-
-	e1000e_get_cfg_done(hw);
-
-	/* Wait for indication from h/w that it has completed basic config */
-	if (hw->mac.type >= e1000_ich10lan) {
-		e1000_lan_init_done_ich8lan(hw);
-	} else {
-		ret_val = e1000e_get_auto_rd_done(hw);
-		if (ret_val) {
-			/*
-			 * When auto config read does not complete, do not
-			 * return with an error. This can happen in situations
-			 * where there is no eeprom and prevents getting link.
-			 */
-			e_dbg("Auto Read Done did not complete\n");
-			ret_val = 0;
-		}
-	}
-
-	/* Clear PHY Reset Asserted bit */
-	status = er32(STATUS);
-	if (status & E1000_STATUS_PHYRA)
-		ew32(STATUS, status & ~E1000_STATUS_PHYRA);
-	else
-		e_dbg("PHY Reset Asserted not set - needs delay\n");
-
-	/* If EEPROM is not marked present, init the IGP 3 PHY manually */
-	if (hw->mac.type <= e1000_ich9lan) {
-		if (((er32(EECD) & E1000_EECD_PRES) == 0) &&
-		    (hw->phy.type == e1000_phy_igp_3)) {
-			e1000e_phy_init_script_igp3(hw);
-		}
-	} else {
-		if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) {
-			/* Maybe we should do a basic PHY config */
-			e_dbg("EEPROM not present\n");
-			ret_val = -E1000_ERR_CONFIG;
-		}
-	}
-
-	return ret_val;
-}
-
-/**
- * e1000_power_down_phy_copper_ich8lan - Remove link during PHY power down
- * @hw: pointer to the HW structure
- *
- * In the case of a PHY power down to save power, or to turn off link during a
- * driver unload, or wake on lan is not enabled, remove the link.
- **/
-static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw)
-{
-	/* If the management interface is not enabled, then power down */
-	if (!(hw->mac.ops.check_mng_mode(hw) ||
-	      hw->phy.ops.check_reset_block(hw)))
-		e1000_power_down_phy_copper(hw);
-}
-
-/**
- *  e1000_clear_hw_cntrs_ich8lan - Clear statistical counters
- *  @hw: pointer to the HW structure
- *
- *  Clears hardware counters specific to the silicon family and calls
- *  clear_hw_cntrs_generic to clear all general purpose counters.
- **/
-static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
-{
-	u16 phy_data;
-	s32 ret_val;
-
-	e1000e_clear_hw_cntrs_base(hw);
-
-	er32(ALGNERRC);
-	er32(RXERRC);
-	er32(TNCRS);
-	er32(CEXTERR);
-	er32(TSCTC);
-	er32(TSCTFC);
-
-	er32(MGTPRC);
-	er32(MGTPDC);
-	er32(MGTPTC);
-
-	er32(IAC);
-	er32(ICRXOC);
-
-	/* Clear PHY statistics registers */
-	if ((hw->phy.type == e1000_phy_82578) ||
-	    (hw->phy.type == e1000_phy_82579) ||
-	    (hw->phy.type == e1000_phy_82577)) {
-		ret_val = hw->phy.ops.acquire(hw);
-		if (ret_val)
-			return;
-		ret_val = hw->phy.ops.set_page(hw,
-					       HV_STATS_PAGE << IGP_PAGE_SHIFT);
-		if (ret_val)
-			goto release;
-		hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data);
-		hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data);
-		hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data);
-		hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data);
-		hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data);
-		hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data);
-		hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data);
-		hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data);
-		hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data);
-		hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data);
-		hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data);
-		hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data);
-		hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data);
-		hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data);
-release:
-		hw->phy.ops.release(hw);
-	}
-}
-
-static struct e1000_mac_operations ich8_mac_ops = {
-	.id_led_init		= e1000e_id_led_init,
-	/* check_mng_mode dependent on mac type */
-	.check_for_link		= e1000_check_for_copper_link_ich8lan,
-	/* cleanup_led dependent on mac type */
-	.clear_hw_cntrs		= e1000_clear_hw_cntrs_ich8lan,
-	.get_bus_info		= e1000_get_bus_info_ich8lan,
-	.set_lan_id		= e1000_set_lan_id_single_port,
-	.get_link_up_info	= e1000_get_link_up_info_ich8lan,
-	/* led_on dependent on mac type */
-	/* led_off dependent on mac type */
-	.update_mc_addr_list	= e1000e_update_mc_addr_list_generic,
-	.reset_hw		= e1000_reset_hw_ich8lan,
-	.init_hw		= e1000_init_hw_ich8lan,
-	.setup_link		= e1000_setup_link_ich8lan,
-	.setup_physical_interface= e1000_setup_copper_link_ich8lan,
-	/* id_led_init dependent on mac type */
-};
-
-static struct e1000_phy_operations ich8_phy_ops = {
-	.acquire		= e1000_acquire_swflag_ich8lan,
-	.check_reset_block	= e1000_check_reset_block_ich8lan,
-	.commit			= NULL,
-	.get_cfg_done		= e1000_get_cfg_done_ich8lan,
-	.get_cable_length	= e1000e_get_cable_length_igp_2,
-	.read_reg		= e1000e_read_phy_reg_igp,
-	.release		= e1000_release_swflag_ich8lan,
-	.reset			= e1000_phy_hw_reset_ich8lan,
-	.set_d0_lplu_state	= e1000_set_d0_lplu_state_ich8lan,
-	.set_d3_lplu_state	= e1000_set_d3_lplu_state_ich8lan,
-	.write_reg		= e1000e_write_phy_reg_igp,
-};
-
-static struct e1000_nvm_operations ich8_nvm_ops = {
-	.acquire		= e1000_acquire_nvm_ich8lan,
-	.read		 	= e1000_read_nvm_ich8lan,
-	.release		= e1000_release_nvm_ich8lan,
-	.update			= e1000_update_nvm_checksum_ich8lan,
-	.valid_led_default	= e1000_valid_led_default_ich8lan,
-	.validate		= e1000_validate_nvm_checksum_ich8lan,
-	.write			= e1000_write_nvm_ich8lan,
-};
-
-struct e1000_info e1000_ich8_info = {
-	.mac			= e1000_ich8lan,
-	.flags			= FLAG_HAS_WOL
-				  | FLAG_IS_ICH
-				  | FLAG_RX_CSUM_ENABLED
-				  | FLAG_HAS_CTRLEXT_ON_LOAD
-				  | FLAG_HAS_AMT
-				  | FLAG_HAS_FLASH
-				  | FLAG_APME_IN_WUC,
-	.pba			= 8,
-	.max_hw_frame_size	= ETH_FRAME_LEN + ETH_FCS_LEN,
-	.get_variants		= e1000_get_variants_ich8lan,
-	.mac_ops		= &ich8_mac_ops,
-	.phy_ops		= &ich8_phy_ops,
-	.nvm_ops		= &ich8_nvm_ops,
-};
-
-struct e1000_info e1000_ich9_info = {
-	.mac			= e1000_ich9lan,
-	.flags			= FLAG_HAS_JUMBO_FRAMES
-				  | FLAG_IS_ICH
-				  | FLAG_HAS_WOL
-				  | FLAG_RX_CSUM_ENABLED
-				  | FLAG_HAS_CTRLEXT_ON_LOAD
-				  | FLAG_HAS_AMT
-				  | FLAG_HAS_ERT
-				  | FLAG_HAS_FLASH
-				  | FLAG_APME_IN_WUC,
-	.pba			= 10,
-	.max_hw_frame_size	= DEFAULT_JUMBO,
-	.get_variants		= e1000_get_variants_ich8lan,
-	.mac_ops		= &ich8_mac_ops,
-	.phy_ops		= &ich8_phy_ops,
-	.nvm_ops		= &ich8_nvm_ops,
-};
-
-struct e1000_info e1000_ich10_info = {
-	.mac			= e1000_ich10lan,
-	.flags			= FLAG_HAS_JUMBO_FRAMES
-				  | FLAG_IS_ICH
-				  | FLAG_HAS_WOL
-				  | FLAG_RX_CSUM_ENABLED
-				  | FLAG_HAS_CTRLEXT_ON_LOAD
-				  | FLAG_HAS_AMT
-				  | FLAG_HAS_ERT
-				  | FLAG_HAS_FLASH
-				  | FLAG_APME_IN_WUC,
-	.pba			= 10,
-	.max_hw_frame_size	= DEFAULT_JUMBO,
-	.get_variants		= e1000_get_variants_ich8lan,
-	.mac_ops		= &ich8_mac_ops,
-	.phy_ops		= &ich8_phy_ops,
-	.nvm_ops		= &ich8_nvm_ops,
-};
-
-struct e1000_info e1000_pch_info = {
-	.mac			= e1000_pchlan,
-	.flags			= FLAG_IS_ICH
-				  | FLAG_HAS_WOL
-				  | FLAG_RX_CSUM_ENABLED
-				  | FLAG_HAS_CTRLEXT_ON_LOAD
-				  | FLAG_HAS_AMT
-				  | FLAG_HAS_FLASH
-				  | FLAG_HAS_JUMBO_FRAMES
-				  | FLAG_DISABLE_FC_PAUSE_TIME /* errata */
-				  | FLAG_APME_IN_WUC,
-	.flags2			= FLAG2_HAS_PHY_STATS,
-	.pba			= 26,
-	.max_hw_frame_size	= 4096,
-	.get_variants		= e1000_get_variants_ich8lan,
-	.mac_ops		= &ich8_mac_ops,
-	.phy_ops		= &ich8_phy_ops,
-	.nvm_ops		= &ich8_nvm_ops,
-};
-
-struct e1000_info e1000_pch2_info = {
-	.mac			= e1000_pch2lan,
-	.flags			= FLAG_IS_ICH
-				  | FLAG_HAS_WOL
-				  | FLAG_RX_CSUM_ENABLED
-				  | FLAG_HAS_CTRLEXT_ON_LOAD
-				  | FLAG_HAS_AMT
-				  | FLAG_HAS_FLASH
-				  | FLAG_HAS_JUMBO_FRAMES
-				  | FLAG_APME_IN_WUC,
-	.flags2			= FLAG2_HAS_PHY_STATS
-				  | FLAG2_HAS_EEE,
-	.pba			= 26,
-	.max_hw_frame_size	= DEFAULT_JUMBO,
-	.get_variants		= e1000_get_variants_ich8lan,
-	.mac_ops		= &ich8_mac_ops,
-	.phy_ops		= &ich8_phy_ops,
-	.nvm_ops		= &ich8_nvm_ops,
-};
diff -druN linux-libre-3.1-gnu/drivers/net/e1000e/lib.c linux-libre-3.2-gnu/drivers/net/e1000e/lib.c
--- linux-libre-3.1-gnu/drivers/net/e1000e/lib.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000e/lib.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2693 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  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,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-#include "e1000.h"
-
-enum e1000_mng_mode {
-	e1000_mng_mode_none = 0,
-	e1000_mng_mode_asf,
-	e1000_mng_mode_pt,
-	e1000_mng_mode_ipmi,
-	e1000_mng_mode_host_if_only
-};
-
-#define E1000_FACTPS_MNGCG		0x20000000
-
-/* Intel(R) Active Management Technology signature */
-#define E1000_IAMT_SIGNATURE		0x544D4149
-
-/**
- *  e1000e_get_bus_info_pcie - Get PCIe bus information
- *  @hw: pointer to the HW structure
- *
- *  Determines and stores the system bus information for a particular
- *  network interface.  The following bus information is determined and stored:
- *  bus speed, bus width, type (PCIe), and PCIe function.
- **/
-s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-	struct e1000_bus_info *bus = &hw->bus;
-	struct e1000_adapter *adapter = hw->adapter;
-	u16 pcie_link_status, cap_offset;
-
-	cap_offset = adapter->pdev->pcie_cap;
-	if (!cap_offset) {
-		bus->width = e1000_bus_width_unknown;
-	} else {
-		pci_read_config_word(adapter->pdev,
-				     cap_offset + PCIE_LINK_STATUS,
-				     &pcie_link_status);
-		bus->width = (enum e1000_bus_width)((pcie_link_status &
-						     PCIE_LINK_WIDTH_MASK) >>
-						    PCIE_LINK_WIDTH_SHIFT);
-	}
-
-	mac->ops.set_lan_id(hw);
-
-	return 0;
-}
-
-/**
- *  e1000_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
- *
- *  @hw: pointer to the HW structure
- *
- *  Determines the LAN function id by reading memory-mapped registers
- *  and swaps the port value if requested.
- **/
-void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw)
-{
-	struct e1000_bus_info *bus = &hw->bus;
-	u32 reg;
-
-	/*
-	 * The status register reports the correct function number
-	 * for the device regardless of function swap state.
-	 */
-	reg = er32(STATUS);
-	bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT;
-}
-
-/**
- *  e1000_set_lan_id_single_port - Set LAN id for a single port device
- *  @hw: pointer to the HW structure
- *
- *  Sets the LAN function id to zero for a single port device.
- **/
-void e1000_set_lan_id_single_port(struct e1000_hw *hw)
-{
-	struct e1000_bus_info *bus = &hw->bus;
-
-	bus->func = 0;
-}
-
-/**
- *  e1000_clear_vfta_generic - Clear VLAN filter table
- *  @hw: pointer to the HW structure
- *
- *  Clears the register array which contains the VLAN filter table by
- *  setting all the values to 0.
- **/
-void e1000_clear_vfta_generic(struct e1000_hw *hw)
-{
-	u32 offset;
-
-	for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
-		E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0);
-		e1e_flush();
-	}
-}
-
-/**
- *  e1000_write_vfta_generic - Write value to VLAN filter table
- *  @hw: pointer to the HW structure
- *  @offset: register offset in VLAN filter table
- *  @value: register value written to VLAN filter table
- *
- *  Writes value at the given offset in the register array which stores
- *  the VLAN filter table.
- **/
-void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value)
-{
-	E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);
-	e1e_flush();
-}
-
-/**
- *  e1000e_init_rx_addrs - Initialize receive address's
- *  @hw: pointer to the HW structure
- *  @rar_count: receive address registers
- *
- *  Setup the receive address registers by setting the base receive address
- *  register to the devices MAC address and clearing all the other receive
- *  address registers to 0.
- **/
-void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count)
-{
-	u32 i;
-	u8 mac_addr[ETH_ALEN] = {0};
-
-	/* Setup the receive address */
-	e_dbg("Programming MAC Address into RAR[0]\n");
-
-	e1000e_rar_set(hw, hw->mac.addr, 0);
-
-	/* Zero out the other (rar_entry_count - 1) receive addresses */
-	e_dbg("Clearing RAR[1-%u]\n", rar_count-1);
-	for (i = 1; i < rar_count; i++)
-		e1000e_rar_set(hw, mac_addr, i);
-}
-
-/**
- *  e1000_check_alt_mac_addr_generic - Check for alternate MAC addr
- *  @hw: pointer to the HW structure
- *
- *  Checks the nvm for an alternate MAC address.  An alternate MAC address
- *  can be setup by pre-boot software and must be treated like a permanent
- *  address and must override the actual permanent MAC address. If an
- *  alternate MAC address is found it is programmed into RAR0, replacing
- *  the permanent address that was installed into RAR0 by the Si on reset.
- *  This function will return SUCCESS unless it encounters an error while
- *  reading the EEPROM.
- **/
-s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
-{
-	u32 i;
-	s32 ret_val = 0;
-	u16 offset, nvm_alt_mac_addr_offset, nvm_data;
-	u8 alt_mac_addr[ETH_ALEN];
-
-	ret_val = e1000_read_nvm(hw, NVM_COMPAT, 1, &nvm_data);
-	if (ret_val)
-		goto out;
-
-	/* Check for LOM (vs. NIC) or one of two valid mezzanine cards */
-	if (!((nvm_data & NVM_COMPAT_LOM) ||
-	      (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_DUAL) ||
-	      (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD) ||
-	      (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES)))
-		goto out;
-
-	ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1,
-	                         &nvm_alt_mac_addr_offset);
-	if (ret_val) {
-		e_dbg("NVM Read Error\n");
-		goto out;
-	}
-
-	if ((nvm_alt_mac_addr_offset == 0xFFFF) ||
-	    (nvm_alt_mac_addr_offset == 0x0000))
-		/* There is no Alternate MAC Address */
-		goto out;
-
-	if (hw->bus.func == E1000_FUNC_1)
-		nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1;
-	for (i = 0; i < ETH_ALEN; i += 2) {
-		offset = nvm_alt_mac_addr_offset + (i >> 1);
-		ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data);
-		if (ret_val) {
-			e_dbg("NVM Read Error\n");
-			goto out;
-		}
-
-		alt_mac_addr[i] = (u8)(nvm_data & 0xFF);
-		alt_mac_addr[i + 1] = (u8)(nvm_data >> 8);
-	}
-
-	/* if multicast bit is set, the alternate address will not be used */
-	if (is_multicast_ether_addr(alt_mac_addr)) {
-		e_dbg("Ignoring Alternate Mac Address with MC bit set\n");
-		goto out;
-	}
-
-	/*
-	 * We have a valid alternate MAC address, and we want to treat it the
-	 * same as the normal permanent MAC address stored by the HW into the
-	 * RAR. Do this by mapping this address into RAR0.
-	 */
-	e1000e_rar_set(hw, alt_mac_addr, 0);
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000e_rar_set - Set receive address register
- *  @hw: pointer to the HW structure
- *  @addr: pointer to the receive address
- *  @index: receive address array register
- *
- *  Sets the receive address array register at index to the address passed
- *  in by addr.
- **/
-void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
-{
-	u32 rar_low, rar_high;
-
-	/*
-	 * 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));
-
-	rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
-
-	/* If MAC address zero, no need to set the AV bit */
-	if (rar_low || rar_high)
-		rar_high |= E1000_RAH_AV;
-
-	/*
-	 * Some bridges will combine consecutive 32-bit writes into
-	 * a single burst write, which will malfunction on some parts.
-	 * The flushes avoid this.
-	 */
-	ew32(RAL(index), rar_low);
-	e1e_flush();
-	ew32(RAH(index), rar_high);
-	e1e_flush();
-}
-
-/**
- *  e1000_hash_mc_addr - Generate a multicast hash value
- *  @hw: pointer to the HW structure
- *  @mc_addr: pointer to a multicast address
- *
- *  Generates a multicast address hash value which is used to determine
- *  the multicast filter table array address and new table value.  See
- *  e1000_mta_set_generic()
- **/
-static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
-{
-	u32 hash_value, hash_mask;
-	u8 bit_shift = 0;
-
-	/* Register count multiplied by bits per register */
-	hash_mask = (hw->mac.mta_reg_count * 32) - 1;
-
-	/*
-	 * For a mc_filter_type of 0, bit_shift is the number of left-shifts
-	 * where 0xFF would still fall within the hash mask.
-	 */
-	while (hash_mask >> bit_shift != 0xFF)
-		bit_shift++;
-
-	/*
-	 * The portion of the address that is used for the hash table
-	 * is determined by the mc_filter_type setting.
-	 * The algorithm is such that there is a total of 8 bits of shifting.
-	 * The bit_shift for a mc_filter_type of 0 represents the number of
-	 * left-shifts where the MSB of mc_addr[5] would still fall within
-	 * the hash_mask.  Case 0 does this exactly.  Since there are a total
-	 * of 8 bits of shifting, then mc_addr[4] will shift right the
-	 * remaining number of bits. Thus 8 - bit_shift.  The rest of the
-	 * cases are a variation of this algorithm...essentially raising the
-	 * number of bits to shift mc_addr[5] left, while still keeping the
-	 * 8-bit shifting total.
-	 *
-	 * For example, given the following Destination MAC Address and an
-	 * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask),
-	 * we can see that the bit_shift for case 0 is 4.  These are the hash
-	 * values resulting from each mc_filter_type...
-	 * [0] [1] [2] [3] [4] [5]
-	 * 01  AA  00  12  34  56
-	 * LSB		 MSB
-	 *
-	 * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563
-	 * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6
-	 * case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163
-	 * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634
-	 */
-	switch (hw->mac.mc_filter_type) {
-	default:
-	case 0:
-		break;
-	case 1:
-		bit_shift += 1;
-		break;
-	case 2:
-		bit_shift += 2;
-		break;
-	case 3:
-		bit_shift += 4;
-		break;
-	}
-
-	hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
-				  (((u16) mc_addr[5]) << bit_shift)));
-
-	return hash_value;
-}
-
-/**
- *  e1000e_update_mc_addr_list_generic - Update Multicast addresses
- *  @hw: pointer to the HW structure
- *  @mc_addr_list: array of multicast addresses to program
- *  @mc_addr_count: number of multicast addresses to program
- *
- *  Updates entire Multicast Table Array.
- *  The caller must have a packed mc_addr_list of multicast addresses.
- **/
-void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,
-					u8 *mc_addr_list, u32 mc_addr_count)
-{
-	u32 hash_value, hash_bit, hash_reg;
-	int i;
-
-	/* clear mta_shadow */
-	memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
-
-	/* update mta_shadow from mc_addr_list */
-	for (i = 0; (u32) i < mc_addr_count; i++) {
-		hash_value = e1000_hash_mc_addr(hw, mc_addr_list);
-
-		hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
-		hash_bit = hash_value & 0x1F;
-
-		hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
-		mc_addr_list += (ETH_ALEN);
-	}
-
-	/* replace the entire MTA table */
-	for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
-		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]);
-	e1e_flush();
-}
-
-/**
- *  e1000e_clear_hw_cntrs_base - Clear base hardware counters
- *  @hw: pointer to the HW structure
- *
- *  Clears the base hardware counters by reading the counter registers.
- **/
-void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw)
-{
-	er32(CRCERRS);
-	er32(SYMERRS);
-	er32(MPC);
-	er32(SCC);
-	er32(ECOL);
-	er32(MCC);
-	er32(LATECOL);
-	er32(COLC);
-	er32(DC);
-	er32(SEC);
-	er32(RLEC);
-	er32(XONRXC);
-	er32(XONTXC);
-	er32(XOFFRXC);
-	er32(XOFFTXC);
-	er32(FCRUC);
-	er32(GPRC);
-	er32(BPRC);
-	er32(MPRC);
-	er32(GPTC);
-	er32(GORCL);
-	er32(GORCH);
-	er32(GOTCL);
-	er32(GOTCH);
-	er32(RNBC);
-	er32(RUC);
-	er32(RFC);
-	er32(ROC);
-	er32(RJC);
-	er32(TORL);
-	er32(TORH);
-	er32(TOTL);
-	er32(TOTH);
-	er32(TPR);
-	er32(TPT);
-	er32(MPTC);
-	er32(BPTC);
-}
-
-/**
- *  e1000e_check_for_copper_link - Check for link (Copper)
- *  @hw: pointer to the HW structure
- *
- *  Checks to see of the link status of the hardware has changed.  If a
- *  change in link status has been detected, then we read the PHY registers
- *  to get the current speed/duplex if link exists.
- **/
-s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-	s32 ret_val;
-	bool link;
-
-	/*
-	 * We only want to go out to the PHY registers to see if Auto-Neg
-	 * has completed and/or if our link status has changed.  The
-	 * get_link_status flag is set upon receiving a Link Status
-	 * Change or Rx Sequence Error interrupt.
-	 */
-	if (!mac->get_link_status)
-		return 0;
-
-	/*
-	 * First we want to see if the MII Status Register reports
-	 * link.  If so, then we want to get the current speed/duplex
-	 * of the PHY.
-	 */
-	ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
-	if (ret_val)
-		return ret_val;
-
-	if (!link)
-		return ret_val; /* No link detected */
-
-	mac->get_link_status = false;
-
-	/*
-	 * Check if there was DownShift, must be checked
-	 * immediately after link-up
-	 */
-	e1000e_check_downshift(hw);
-
-	/*
-	 * If we are forcing speed/duplex, then we simply return since
-	 * we have already determined whether we have link or not.
-	 */
-	if (!mac->autoneg) {
-		ret_val = -E1000_ERR_CONFIG;
-		return ret_val;
-	}
-
-	/*
-	 * Auto-Neg is enabled.  Auto Speed Detection takes care
-	 * of MAC speed/duplex configuration.  So we only need to
-	 * configure Collision Distance in the MAC.
-	 */
-	e1000e_config_collision_dist(hw);
-
-	/*
-	 * Configure Flow Control now that Auto-Neg has completed.
-	 * First, we need to restore the desired flow control
-	 * settings because we may have had to re-autoneg with a
-	 * different link partner.
-	 */
-	ret_val = e1000e_config_fc_after_link_up(hw);
-	if (ret_val)
-		e_dbg("Error configuring flow control\n");
-
-	return ret_val;
-}
-
-/**
- *  e1000e_check_for_fiber_link - Check for link (Fiber)
- *  @hw: pointer to the HW structure
- *
- *  Checks for link up on the hardware.  If link is not up and we have
- *  a signal, then we need to force link up.
- **/
-s32 e1000e_check_for_fiber_link(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-	u32 rxcw;
-	u32 ctrl;
-	u32 status;
-	s32 ret_val;
-
-	ctrl = er32(CTRL);
-	status = er32(STATUS);
-	rxcw = er32(RXCW);
-
-	/*
-	 * If we don't have link (auto-negotiation failed or link partner
-	 * cannot auto-negotiate), the cable is plugged in (we have signal),
-	 * and our link partner is not trying to auto-negotiate with us (we
-	 * are receiving idles or data), we need to force link up. We also
-	 * need to give auto-negotiation time to complete, in case the cable
-	 * was just plugged in. The autoneg_failed flag does this.
-	 */
-	/* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
-	if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) &&
-	    (!(rxcw & E1000_RXCW_C))) {
-		if (mac->autoneg_failed == 0) {
-			mac->autoneg_failed = 1;
-			return 0;
-		}
-		e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
-
-		/* Disable auto-negotiation in the TXCW register */
-		ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE));
-
-		/* Force link-up and also force full-duplex. */
-		ctrl = er32(CTRL);
-		ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
-		ew32(CTRL, ctrl);
-
-		/* Configure Flow Control after forcing link up. */
-		ret_val = e1000e_config_fc_after_link_up(hw);
-		if (ret_val) {
-			e_dbg("Error configuring flow control\n");
-			return ret_val;
-		}
-	} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
-		/*
-		 * If we are forcing link and we are receiving /C/ ordered
-		 * sets, re-enable auto-negotiation in the TXCW register
-		 * and disable forced link in the Device Control register
-		 * in an attempt to auto-negotiate with our link partner.
-		 */
-		e_dbg("Rx'ing /C/, enable AutoNeg and stop forcing link.\n");
-		ew32(TXCW, mac->txcw);
-		ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
-
-		mac->serdes_has_link = true;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_check_for_serdes_link - Check for link (Serdes)
- *  @hw: pointer to the HW structure
- *
- *  Checks for link up on the hardware.  If link is not up and we have
- *  a signal, then we need to force link up.
- **/
-s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-	u32 rxcw;
-	u32 ctrl;
-	u32 status;
-	s32 ret_val;
-
-	ctrl = er32(CTRL);
-	status = er32(STATUS);
-	rxcw = er32(RXCW);
-
-	/*
-	 * If we don't have link (auto-negotiation failed or link partner
-	 * cannot auto-negotiate), and our link partner is not trying to
-	 * auto-negotiate with us (we are receiving idles or data),
-	 * we need to force link up. We also need to give auto-negotiation
-	 * time to complete.
-	 */
-	/* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
-	if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {
-		if (mac->autoneg_failed == 0) {
-			mac->autoneg_failed = 1;
-			return 0;
-		}
-		e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
-
-		/* Disable auto-negotiation in the TXCW register */
-		ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE));
-
-		/* Force link-up and also force full-duplex. */
-		ctrl = er32(CTRL);
-		ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
-		ew32(CTRL, ctrl);
-
-		/* Configure Flow Control after forcing link up. */
-		ret_val = e1000e_config_fc_after_link_up(hw);
-		if (ret_val) {
-			e_dbg("Error configuring flow control\n");
-			return ret_val;
-		}
-	} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
-		/*
-		 * If we are forcing link and we are receiving /C/ ordered
-		 * sets, re-enable auto-negotiation in the TXCW register
-		 * and disable forced link in the Device Control register
-		 * in an attempt to auto-negotiate with our link partner.
-		 */
-		e_dbg("Rx'ing /C/, enable AutoNeg and stop forcing link.\n");
-		ew32(TXCW, mac->txcw);
-		ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
-
-		mac->serdes_has_link = true;
-	} else if (!(E1000_TXCW_ANE & er32(TXCW))) {
-		/*
-		 * If we force link for non-auto-negotiation switch, check
-		 * link status based on MAC synchronization for internal
-		 * serdes media type.
-		 */
-		/* SYNCH bit and IV bit are sticky. */
-		udelay(10);
-		rxcw = er32(RXCW);
-		if (rxcw & E1000_RXCW_SYNCH) {
-			if (!(rxcw & E1000_RXCW_IV)) {
-				mac->serdes_has_link = true;
-				e_dbg("SERDES: Link up - forced.\n");
-			}
-		} else {
-			mac->serdes_has_link = false;
-			e_dbg("SERDES: Link down - force failed.\n");
-		}
-	}
-
-	if (E1000_TXCW_ANE & er32(TXCW)) {
-		status = er32(STATUS);
-		if (status & E1000_STATUS_LU) {
-			/* SYNCH bit and IV bit are sticky, so reread rxcw.  */
-			udelay(10);
-			rxcw = er32(RXCW);
-			if (rxcw & E1000_RXCW_SYNCH) {
-				if (!(rxcw & E1000_RXCW_IV)) {
-					mac->serdes_has_link = true;
-					e_dbg("SERDES: Link up - autoneg "
-					   "completed successfully.\n");
-				} else {
-					mac->serdes_has_link = false;
-					e_dbg("SERDES: Link down - invalid"
-					   "codewords detected in autoneg.\n");
-				}
-			} else {
-				mac->serdes_has_link = false;
-				e_dbg("SERDES: Link down - no sync.\n");
-			}
-		} else {
-			mac->serdes_has_link = false;
-			e_dbg("SERDES: Link down - autoneg failed\n");
-		}
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_set_default_fc_generic - Set flow control default values
- *  @hw: pointer to the HW structure
- *
- *  Read the EEPROM for the default values for flow control and store the
- *  values.
- **/
-static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 nvm_data;
-
-	/*
-	 * Read and store word 0x0F of the EEPROM. This word contains bits
-	 * that determine the hardware's default PAUSE (flow control) mode,
-	 * a bit that determines whether the HW defaults to enabling or
-	 * disabling auto-negotiation, and the direction of the
-	 * SW defined pins. If there is no SW over-ride of the flow
-	 * control setting, then the variable hw->fc will
-	 * be initialized based on a value in the EEPROM.
-	 */
-	ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data);
-
-	if (ret_val) {
-		e_dbg("NVM Read Error\n");
-		return ret_val;
-	}
-
-	if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0)
-		hw->fc.requested_mode = e1000_fc_none;
-	else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==
-		 NVM_WORD0F_ASM_DIR)
-		hw->fc.requested_mode = e1000_fc_tx_pause;
-	else
-		hw->fc.requested_mode = e1000_fc_full;
-
-	return 0;
-}
-
-/**
- *  e1000e_setup_link - Setup flow control and link settings
- *  @hw: pointer to the HW structure
- *
- *  Determines which flow control settings to use, then configures flow
- *  control.  Calls the appropriate media-specific link configuration
- *  function.  Assuming the adapter has a valid link partner, a valid link
- *  should be established.  Assumes the hardware has previously been reset
- *  and the transmitter and receiver are not enabled.
- **/
-s32 e1000e_setup_link(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-	s32 ret_val;
-
-	/*
-	 * In the case of the phy reset being blocked, we already have a link.
-	 * We do not need to set it up again.
-	 */
-	if (e1000_check_reset_block(hw))
-		return 0;
-
-	/*
-	 * If requested flow control is set to default, set flow control
-	 * based on the EEPROM flow control settings.
-	 */
-	if (hw->fc.requested_mode == e1000_fc_default) {
-		ret_val = e1000_set_default_fc_generic(hw);
-		if (ret_val)
-			return ret_val;
-	}
-
-	/*
-	 * Save off the requested flow control mode for use later.  Depending
-	 * on the link partner's capabilities, we may or may not use this mode.
-	 */
-	hw->fc.current_mode = hw->fc.requested_mode;
-
-	e_dbg("After fix-ups FlowControl is now = %x\n",
-		hw->fc.current_mode);
-
-	/* Call the necessary media_type subroutine to configure the link. */
-	ret_val = mac->ops.setup_physical_interface(hw);
-	if (ret_val)
-		return ret_val;
-
-	/*
-	 * Initialize the flow control address, type, and PAUSE timer
-	 * registers to their default values.  This is done even if flow
-	 * control is disabled, because it does not hurt anything to
-	 * initialize these registers.
-	 */
-	e_dbg("Initializing the Flow Control address, type and timer regs\n");
-	ew32(FCT, FLOW_CONTROL_TYPE);
-	ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH);
-	ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW);
-
-	ew32(FCTTV, hw->fc.pause_time);
-
-	return e1000e_set_fc_watermarks(hw);
-}
-
-/**
- *  e1000_commit_fc_settings_generic - Configure flow control
- *  @hw: pointer to the HW structure
- *
- *  Write the flow control settings to the Transmit Config Word Register (TXCW)
- *  base on the flow control settings in e1000_mac_info.
- **/
-static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-	u32 txcw;
-
-	/*
-	 * Check for a software override of the flow control settings, and
-	 * setup the device accordingly.  If auto-negotiation is enabled, then
-	 * software will have to set the "PAUSE" bits to the correct value in
-	 * the Transmit Config Word Register (TXCW) and re-start auto-
-	 * negotiation.  However, if auto-negotiation is disabled, then
-	 * software will have to manually configure the two flow control enable
-	 * bits in the CTRL register.
-	 *
-	 * The possible values of the "fc" parameter 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.
-	 */
-	switch (hw->fc.current_mode) {
-	case e1000_fc_none:
-		/* Flow control completely disabled by a software over-ride. */
-		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
-		break;
-	case e1000_fc_rx_pause:
-		/*
-		 * Rx Flow control is enabled and Tx Flow control is disabled
-		 * by a software over-ride. 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.
-		 */
-		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
-		break;
-	case e1000_fc_tx_pause:
-		/*
-		 * Tx Flow control is enabled, and Rx Flow control is disabled,
-		 * by a software over-ride.
-		 */
-		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
-		break;
-	case e1000_fc_full:
-		/*
-		 * Flow control (both Rx and Tx) is enabled by a software
-		 * over-ride.
-		 */
-		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
-		break;
-	default:
-		e_dbg("Flow control param set incorrectly\n");
-		return -E1000_ERR_CONFIG;
-		break;
-	}
-
-	ew32(TXCW, txcw);
-	mac->txcw = txcw;
-
-	return 0;
-}
-
-/**
- *  e1000_poll_fiber_serdes_link_generic - Poll for link up
- *  @hw: pointer to the HW structure
- *
- *  Polls for link up by reading the status register, if link fails to come
- *  up with auto-negotiation, then the link is forced if a signal is detected.
- **/
-static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-	u32 i, status;
-	s32 ret_val;
-
-	/*
-	 * If we have a signal (the cable is plugged in, or assumed true for
-	 * serdes media) then poll for a "Link-Up" indication in the Device
-	 * Status Register.  Time-out if a link isn't seen in 500 milliseconds
-	 * seconds (Auto-negotiation should complete in less than 500
-	 * milliseconds even if the other end is doing it in SW).
-	 */
-	for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) {
-		usleep_range(10000, 20000);
-		status = er32(STATUS);
-		if (status & E1000_STATUS_LU)
-			break;
-	}
-	if (i == FIBER_LINK_UP_LIMIT) {
-		e_dbg("Never got a valid link from auto-neg!!!\n");
-		mac->autoneg_failed = 1;
-		/*
-		 * AutoNeg failed to achieve a link, so we'll call
-		 * mac->check_for_link. This routine will force the
-		 * link up if we detect a signal. This will allow us to
-		 * communicate with non-autonegotiating link partners.
-		 */
-		ret_val = mac->ops.check_for_link(hw);
-		if (ret_val) {
-			e_dbg("Error while checking for link\n");
-			return ret_val;
-		}
-		mac->autoneg_failed = 0;
-	} else {
-		mac->autoneg_failed = 0;
-		e_dbg("Valid Link Found\n");
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_setup_fiber_serdes_link - Setup link for fiber/serdes
- *  @hw: pointer to the HW structure
- *
- *  Configures collision distance and flow control for fiber and serdes
- *  links.  Upon successful setup, poll for link.
- **/
-s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw)
-{
-	u32 ctrl;
-	s32 ret_val;
-
-	ctrl = er32(CTRL);
-
-	/* Take the link out of reset */
-	ctrl &= ~E1000_CTRL_LRST;
-
-	e1000e_config_collision_dist(hw);
-
-	ret_val = e1000_commit_fc_settings_generic(hw);
-	if (ret_val)
-		return ret_val;
-
-	/*
-	 * Since auto-negotiation is enabled, take the link out of reset (the
-	 * link will be in reset, because we previously reset the chip). This
-	 * will restart auto-negotiation.  If auto-negotiation is successful
-	 * then the link-up status bit will be set and the flow control enable
-	 * bits (RFCE and TFCE) will be set according to their negotiated value.
-	 */
-	e_dbg("Auto-negotiation enabled\n");
-
-	ew32(CTRL, ctrl);
-	e1e_flush();
-	usleep_range(1000, 2000);
-
-	/*
-	 * For these adapters, the SW definable pin 1 is set when the optics
-	 * detect a signal.  If we have a signal, then poll for a "Link-Up"
-	 * indication.
-	 */
-	if (hw->phy.media_type == e1000_media_type_internal_serdes ||
-	    (er32(CTRL) & E1000_CTRL_SWDPIN1)) {
-		ret_val = e1000_poll_fiber_serdes_link_generic(hw);
-	} else {
-		e_dbg("No signal detected\n");
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_config_collision_dist - Configure collision distance
- *  @hw: pointer to the HW structure
- *
- *  Configures the collision distance to the default value and is used
- *  during link setup. Currently no func pointer exists and all
- *  implementations are handled in the generic version of this function.
- **/
-void e1000e_config_collision_dist(struct e1000_hw *hw)
-{
-	u32 tctl;
-
-	tctl = er32(TCTL);
-
-	tctl &= ~E1000_TCTL_COLD;
-	tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
-
-	ew32(TCTL, tctl);
-	e1e_flush();
-}
-
-/**
- *  e1000e_set_fc_watermarks - Set flow control high/low watermarks
- *  @hw: pointer to the HW structure
- *
- *  Sets the flow control high/low threshold (watermark) registers.  If
- *  flow control XON frame transmission is enabled, then set XON frame
- *  transmission as well.
- **/
-s32 e1000e_set_fc_watermarks(struct e1000_hw *hw)
-{
-	u32 fcrtl = 0, fcrth = 0;
-
-	/*
-	 * Set the flow control receive threshold registers.  Normally,
-	 * these registers will be set to a default threshold that may be
-	 * adjusted later by the driver's runtime code.  However, if the
-	 * ability to transmit pause frames is not enabled, then these
-	 * registers will be set to 0.
-	 */
-	if (hw->fc.current_mode & e1000_fc_tx_pause) {
-		/*
-		 * We need to set up the Receive Threshold high and low water
-		 * marks as well as (optionally) enabling the transmission of
-		 * XON frames.
-		 */
-		fcrtl = hw->fc.low_water;
-		fcrtl |= E1000_FCRTL_XONE;
-		fcrth = hw->fc.high_water;
-	}
-	ew32(FCRTL, fcrtl);
-	ew32(FCRTH, fcrth);
-
-	return 0;
-}
-
-/**
- *  e1000e_force_mac_fc - Force the MAC's flow control settings
- *  @hw: pointer to the HW structure
- *
- *  Force the MAC's flow control settings.  Sets the TFCE and RFCE bits in the
- *  device control register to reflect the adapter settings.  TFCE and RFCE
- *  need to be explicitly set by software when a copper PHY is used because
- *  autonegotiation is managed by the PHY rather than the MAC.  Software must
- *  also configure these bits when link is forced on a fiber connection.
- **/
-s32 e1000e_force_mac_fc(struct e1000_hw *hw)
-{
-	u32 ctrl;
-
-	ctrl = er32(CTRL);
-
-	/*
-	 * Because we didn't get link via the internal auto-negotiation
-	 * mechanism (we either forced link or we got link via PHY
-	 * auto-neg), we have to manually enable/disable transmit an
-	 * receive flow control.
-	 *
-	 * The "Case" statement below enables/disable flow control
-	 * according to the "hw->fc.current_mode" parameter.
-	 *
-	 * The possible values of the "fc" parameter 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
-	 *          frames but we do not receive pause frames).
-	 *      3:  Both Rx and Tx flow control (symmetric) is enabled.
-	 *  other:  No other values should be possible at this point.
-	 */
-	e_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode);
-
-	switch (hw->fc.current_mode) {
-	case e1000_fc_none:
-		ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
-		break;
-	case e1000_fc_rx_pause:
-		ctrl &= (~E1000_CTRL_TFCE);
-		ctrl |= E1000_CTRL_RFCE;
-		break;
-	case e1000_fc_tx_pause:
-		ctrl &= (~E1000_CTRL_RFCE);
-		ctrl |= E1000_CTRL_TFCE;
-		break;
-	case e1000_fc_full:
-		ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
-		break;
-	default:
-		e_dbg("Flow control param set incorrectly\n");
-		return -E1000_ERR_CONFIG;
-	}
-
-	ew32(CTRL, ctrl);
-
-	return 0;
-}
-
-/**
- *  e1000e_config_fc_after_link_up - Configures flow control after link
- *  @hw: pointer to the HW structure
- *
- *  Checks the status of auto-negotiation after link up to ensure that the
- *  speed and duplex were not forced.  If the link needed to be forced, then
- *  flow control needs to be forced also.  If auto-negotiation is enabled
- *  and did not fail, then we configure flow control based on our link
- *  partner.
- **/
-s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-	s32 ret_val = 0;
-	u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
-	u16 speed, duplex;
-
-	/*
-	 * Check for the case where we have fiber media and auto-neg failed
-	 * so we had to force link.  In this case, we need to force the
-	 * configuration of the MAC to match the "fc" parameter.
-	 */
-	if (mac->autoneg_failed) {
-		if (hw->phy.media_type == e1000_media_type_fiber ||
-		    hw->phy.media_type == e1000_media_type_internal_serdes)
-			ret_val = e1000e_force_mac_fc(hw);
-	} else {
-		if (hw->phy.media_type == e1000_media_type_copper)
-			ret_val = e1000e_force_mac_fc(hw);
-	}
-
-	if (ret_val) {
-		e_dbg("Error forcing flow control settings\n");
-		return ret_val;
-	}
-
-	/*
-	 * Check for the case where we have copper media and auto-neg is
-	 * enabled.  In this case, we need to check and see if Auto-Neg
-	 * has completed, and if so, how the PHY and link partner has
-	 * flow control configured.
-	 */
-	if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) {
-		/*
-		 * Read the MII Status Register and check to see if AutoNeg
-		 * has completed.  We read this twice because this reg has
-		 * some "sticky" (latched) bits.
-		 */
-		ret_val = e1e_rphy(hw, PHY_STATUS, &mii_status_reg);
-		if (ret_val)
-			return ret_val;
-		ret_val = e1e_rphy(hw, PHY_STATUS, &mii_status_reg);
-		if (ret_val)
-			return ret_val;
-
-		if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {
-			e_dbg("Copper PHY and Auto Neg "
-				 "has not completed.\n");
-			return ret_val;
-		}
-
-		/*
-		 * The AutoNeg process has completed, so we now need to
-		 * read both the Auto Negotiation Advertisement
-		 * Register (Address 4) and the Auto_Negotiation Base
-		 * Page Ability Register (Address 5) to determine how
-		 * flow control was negotiated.
-		 */
-		ret_val = e1e_rphy(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg);
-		if (ret_val)
-			return ret_val;
-		ret_val =
-		    e1e_rphy(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg);
-		if (ret_val)
-			return ret_val;
-
-		/*
-		 * Two bits in the Auto Negotiation Advertisement Register
-		 * (Address 4) and two bits in the Auto Negotiation Base
-		 * Page Ability Register (Address 5) determine flow control
-		 * for both the PHY and the link partner.  The following
-		 * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
-		 * 1999, describes these PAUSE resolution bits and how flow
-		 * control is determined based upon these settings.
-		 * NOTE:  DC = Don't Care
-		 *
-		 *   LOCAL DEVICE  |   LINK PARTNER
-		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
-		 *-------|---------|-------|---------|--------------------
-		 *   0   |    0    |  DC   |   DC    | e1000_fc_none
-		 *   0   |    1    |   0   |   DC    | e1000_fc_none
-		 *   0   |    1    |   1   |    0    | e1000_fc_none
-		 *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
-		 *   1   |    0    |   0   |   DC    | e1000_fc_none
-		 *   1   |   DC    |   1   |   DC    | e1000_fc_full
-		 *   1   |    1    |   0   |    0    | e1000_fc_none
-		 *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
-		 *
-		 * Are both PAUSE bits set to 1?  If so, this implies
-		 * Symmetric Flow Control is enabled at both ends.  The
-		 * ASM_DIR bits are irrelevant per the spec.
-		 *
-		 * For Symmetric Flow Control:
-		 *
-		 *   LOCAL DEVICE  |   LINK PARTNER
-		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
-		 *-------|---------|-------|---------|--------------------
-		 *   1   |   DC    |   1   |   DC    | E1000_fc_full
-		 *
-		 */
-		if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
-		    (mii_nway_lp_ability_reg & NWAY_LPAR_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 == e1000_fc_full) {
-				hw->fc.current_mode = e1000_fc_full;
-				e_dbg("Flow Control = FULL.\r\n");
-			} else {
-				hw->fc.current_mode = e1000_fc_rx_pause;
-				e_dbg("Flow Control = "
-				      "Rx PAUSE frames only.\r\n");
-			}
-		}
-		/*
-		 * For receiving PAUSE frames ONLY.
-		 *
-		 *   LOCAL DEVICE  |   LINK PARTNER
-		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
-		 *-------|---------|-------|---------|--------------------
-		 *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
-		 */
-		else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
-			  (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
-			  (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
-			  (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
-			hw->fc.current_mode = e1000_fc_tx_pause;
-			e_dbg("Flow Control = Tx PAUSE frames only.\r\n");
-		}
-		/*
-		 * For transmitting PAUSE frames ONLY.
-		 *
-		 *   LOCAL DEVICE  |   LINK PARTNER
-		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
-		 *-------|---------|-------|---------|--------------------
-		 *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
-		 */
-		else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
-			 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
-			 !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
-			 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
-			hw->fc.current_mode = e1000_fc_rx_pause;
-			e_dbg("Flow Control = Rx PAUSE frames only.\r\n");
-		} else {
-			/*
-			 * Per the IEEE spec, at this point flow control
-			 * should be disabled.
-			 */
-			hw->fc.current_mode = e1000_fc_none;
-			e_dbg("Flow Control = NONE.\r\n");
-		}
-
-		/*
-		 * Now we need to do one last check...  If we auto-
-		 * negotiated to HALF DUPLEX, flow control should not be
-		 * enabled per IEEE 802.3 spec.
-		 */
-		ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex);
-		if (ret_val) {
-			e_dbg("Error getting link speed and duplex\n");
-			return ret_val;
-		}
-
-		if (duplex == HALF_DUPLEX)
-			hw->fc.current_mode = e1000_fc_none;
-
-		/*
-		 * Now we call a subroutine to actually force the MAC
-		 * controller to use the correct flow control settings.
-		 */
-		ret_val = e1000e_force_mac_fc(hw);
-		if (ret_val) {
-			e_dbg("Error forcing flow control settings\n");
-			return ret_val;
-		}
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_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
- *
- *  Read the status register for the current speed/duplex and store the current
- *  speed and duplex for copper connections.
- **/
-s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *duplex)
-{
-	u32 status;
-
-	status = er32(STATUS);
-	if (status & E1000_STATUS_SPEED_1000)
-		*speed = SPEED_1000;
-	else if (status & E1000_STATUS_SPEED_100)
-		*speed = SPEED_100;
-	else
-		*speed = SPEED_10;
-
-	if (status & E1000_STATUS_FD)
-		*duplex = FULL_DUPLEX;
-	else
-		*duplex = HALF_DUPLEX;
-
-	e_dbg("%u Mbps, %s Duplex\n",
-	      *speed == SPEED_1000 ? 1000 : *speed == SPEED_100 ? 100 : 10,
-	      *duplex == FULL_DUPLEX ? "Full" : "Half");
-
-	return 0;
-}
-
-/**
- *  e1000e_get_speed_and_duplex_fiber_serdes - Retrieve current speed/duplex
- *  @hw: pointer to the HW structure
- *  @speed: stores the current speed
- *  @duplex: stores the current duplex
- *
- *  Sets the speed and duplex to gigabit full duplex (the only possible option)
- *  for fiber/serdes links.
- **/
-s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, u16 *speed, u16 *duplex)
-{
-	*speed = SPEED_1000;
-	*duplex = FULL_DUPLEX;
-
-	return 0;
-}
-
-/**
- *  e1000e_get_hw_semaphore - Acquire hardware semaphore
- *  @hw: pointer to the HW structure
- *
- *  Acquire the HW semaphore to access the PHY or NVM
- **/
-s32 e1000e_get_hw_semaphore(struct e1000_hw *hw)
-{
-	u32 swsm;
-	s32 timeout = hw->nvm.word_size + 1;
-	s32 i = 0;
-
-	/* Get the SW semaphore */
-	while (i < timeout) {
-		swsm = er32(SWSM);
-		if (!(swsm & E1000_SWSM_SMBI))
-			break;
-
-		udelay(50);
-		i++;
-	}
-
-	if (i == timeout) {
-		e_dbg("Driver can't access device - SMBI bit is set.\n");
-		return -E1000_ERR_NVM;
-	}
-
-	/* Get the FW semaphore. */
-	for (i = 0; i < timeout; i++) {
-		swsm = er32(SWSM);
-		ew32(SWSM, swsm | E1000_SWSM_SWESMBI);
-
-		/* Semaphore acquired if bit latched */
-		if (er32(SWSM) & E1000_SWSM_SWESMBI)
-			break;
-
-		udelay(50);
-	}
-
-	if (i == timeout) {
-		/* Release semaphores */
-		e1000e_put_hw_semaphore(hw);
-		e_dbg("Driver can't access the NVM\n");
-		return -E1000_ERR_NVM;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_put_hw_semaphore - Release hardware semaphore
- *  @hw: pointer to the HW structure
- *
- *  Release hardware semaphore used to access the PHY or NVM
- **/
-void e1000e_put_hw_semaphore(struct e1000_hw *hw)
-{
-	u32 swsm;
-
-	swsm = er32(SWSM);
-	swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
-	ew32(SWSM, swsm);
-}
-
-/**
- *  e1000e_get_auto_rd_done - Check for auto read completion
- *  @hw: pointer to the HW structure
- *
- *  Check EEPROM for Auto Read done bit.
- **/
-s32 e1000e_get_auto_rd_done(struct e1000_hw *hw)
-{
-	s32 i = 0;
-
-	while (i < AUTO_READ_DONE_TIMEOUT) {
-		if (er32(EECD) & E1000_EECD_AUTO_RD)
-			break;
-		usleep_range(1000, 2000);
-		i++;
-	}
-
-	if (i == AUTO_READ_DONE_TIMEOUT) {
-		e_dbg("Auto read by HW from NVM has not completed.\n");
-		return -E1000_ERR_RESET;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_valid_led_default - Verify a valid default LED config
- *  @hw: pointer to the HW structure
- *  @data: pointer to the NVM (EEPROM)
- *
- *  Read the EEPROM for the current default LED configuration.  If the
- *  LED configuration is not valid, set to a valid LED configuration.
- **/
-s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data)
-{
-	s32 ret_val;
-
-	ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data);
-	if (ret_val) {
-		e_dbg("NVM Read Error\n");
-		return ret_val;
-	}
-
-	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)
-		*data = ID_LED_DEFAULT;
-
-	return 0;
-}
-
-/**
- *  e1000e_id_led_init -
- *  @hw: pointer to the HW structure
- *
- **/
-s32 e1000e_id_led_init(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-	s32 ret_val;
-	const u32 ledctl_mask = 0x000000FF;
-	const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON;
-	const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF;
-	u16 data, i, temp;
-	const u16 led_mask = 0x0F;
-
-	ret_val = hw->nvm.ops.valid_led_default(hw, &data);
-	if (ret_val)
-		return ret_val;
-
-	mac->ledctl_default = er32(LEDCTL);
-	mac->ledctl_mode1 = mac->ledctl_default;
-	mac->ledctl_mode2 = mac->ledctl_default;
-
-	for (i = 0; i < 4; i++) {
-		temp = (data >> (i << 2)) & led_mask;
-		switch (temp) {
-		case ID_LED_ON1_DEF2:
-		case ID_LED_ON1_ON2:
-		case ID_LED_ON1_OFF2:
-			mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
-			mac->ledctl_mode1 |= ledctl_on << (i << 3);
-			break;
-		case ID_LED_OFF1_DEF2:
-		case ID_LED_OFF1_ON2:
-		case ID_LED_OFF1_OFF2:
-			mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
-			mac->ledctl_mode1 |= ledctl_off << (i << 3);
-			break;
-		default:
-			/* Do nothing */
-			break;
-		}
-		switch (temp) {
-		case ID_LED_DEF1_ON2:
-		case ID_LED_ON1_ON2:
-		case ID_LED_OFF1_ON2:
-			mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
-			mac->ledctl_mode2 |= ledctl_on << (i << 3);
-			break;
-		case ID_LED_DEF1_OFF2:
-		case ID_LED_ON1_OFF2:
-		case ID_LED_OFF1_OFF2:
-			mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
-			mac->ledctl_mode2 |= ledctl_off << (i << 3);
-			break;
-		default:
-			/* Do nothing */
-			break;
-		}
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_setup_led_generic - Configures SW controllable LED
- *  @hw: pointer to the HW structure
- *
- *  This prepares the SW controllable LED for use and saves the current state
- *  of the LED so it can be later restored.
- **/
-s32 e1000e_setup_led_generic(struct e1000_hw *hw)
-{
-	u32 ledctl;
-
-	if (hw->mac.ops.setup_led != e1000e_setup_led_generic)
-		return -E1000_ERR_CONFIG;
-
-	if (hw->phy.media_type == e1000_media_type_fiber) {
-		ledctl = er32(LEDCTL);
-		hw->mac.ledctl_default = ledctl;
-		/* Turn off LED0 */
-		ledctl &= ~(E1000_LEDCTL_LED0_IVRT |
-		            E1000_LEDCTL_LED0_BLINK |
-		            E1000_LEDCTL_LED0_MODE_MASK);
-		ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
-		           E1000_LEDCTL_LED0_MODE_SHIFT);
-		ew32(LEDCTL, ledctl);
-	} else if (hw->phy.media_type == e1000_media_type_copper) {
-		ew32(LEDCTL, hw->mac.ledctl_mode1);
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_cleanup_led_generic - Set LED config to default operation
- *  @hw: pointer to the HW structure
- *
- *  Remove the current LED configuration and set the LED configuration
- *  to the default value, saved from the EEPROM.
- **/
-s32 e1000e_cleanup_led_generic(struct e1000_hw *hw)
-{
-	ew32(LEDCTL, hw->mac.ledctl_default);
-	return 0;
-}
-
-/**
- *  e1000e_blink_led_generic - Blink LED
- *  @hw: pointer to the HW structure
- *
- *  Blink the LEDs which are set to be on.
- **/
-s32 e1000e_blink_led_generic(struct e1000_hw *hw)
-{
-	u32 ledctl_blink = 0;
-	u32 i;
-
-	if (hw->phy.media_type == e1000_media_type_fiber) {
-		/* always blink LED0 for PCI-E fiber */
-		ledctl_blink = E1000_LEDCTL_LED0_BLINK |
-		     (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);
-	} else {
-		/*
-		 * set the blink bit for each LED that's "on" (0x0E)
-		 * in ledctl_mode2
-		 */
-		ledctl_blink = hw->mac.ledctl_mode2;
-		for (i = 0; i < 4; i++)
-			if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
-			    E1000_LEDCTL_MODE_LED_ON)
-				ledctl_blink |= (E1000_LEDCTL_LED0_BLINK <<
-						 (i * 8));
-	}
-
-	ew32(LEDCTL, ledctl_blink);
-
-	return 0;
-}
-
-/**
- *  e1000e_led_on_generic - Turn LED on
- *  @hw: pointer to the HW structure
- *
- *  Turn LED on.
- **/
-s32 e1000e_led_on_generic(struct e1000_hw *hw)
-{
-	u32 ctrl;
-
-	switch (hw->phy.media_type) {
-	case e1000_media_type_fiber:
-		ctrl = er32(CTRL);
-		ctrl &= ~E1000_CTRL_SWDPIN0;
-		ctrl |= E1000_CTRL_SWDPIO0;
-		ew32(CTRL, ctrl);
-		break;
-	case e1000_media_type_copper:
-		ew32(LEDCTL, hw->mac.ledctl_mode2);
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_led_off_generic - Turn LED off
- *  @hw: pointer to the HW structure
- *
- *  Turn LED off.
- **/
-s32 e1000e_led_off_generic(struct e1000_hw *hw)
-{
-	u32 ctrl;
-
-	switch (hw->phy.media_type) {
-	case e1000_media_type_fiber:
-		ctrl = er32(CTRL);
-		ctrl |= E1000_CTRL_SWDPIN0;
-		ctrl |= E1000_CTRL_SWDPIO0;
-		ew32(CTRL, ctrl);
-		break;
-	case e1000_media_type_copper:
-		ew32(LEDCTL, hw->mac.ledctl_mode1);
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_set_pcie_no_snoop - Set PCI-express capabilities
- *  @hw: pointer to the HW structure
- *  @no_snoop: bitmap of snoop events
- *
- *  Set the PCI-express register to snoop for events enabled in 'no_snoop'.
- **/
-void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop)
-{
-	u32 gcr;
-
-	if (no_snoop) {
-		gcr = er32(GCR);
-		gcr &= ~(PCIE_NO_SNOOP_ALL);
-		gcr |= no_snoop;
-		ew32(GCR, gcr);
-	}
-}
-
-/**
- *  e1000e_disable_pcie_master - Disables PCI-express master access
- *  @hw: pointer to the HW structure
- *
- *  Returns 0 if successful, else returns -10
- *  (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused
- *  the master requests to be disabled.
- *
- *  Disables PCI-Express master access and verifies there are no pending
- *  requests.
- **/
-s32 e1000e_disable_pcie_master(struct e1000_hw *hw)
-{
-	u32 ctrl;
-	s32 timeout = MASTER_DISABLE_TIMEOUT;
-
-	ctrl = er32(CTRL);
-	ctrl |= E1000_CTRL_GIO_MASTER_DISABLE;
-	ew32(CTRL, ctrl);
-
-	while (timeout) {
-		if (!(er32(STATUS) &
-		      E1000_STATUS_GIO_MASTER_ENABLE))
-			break;
-		udelay(100);
-		timeout--;
-	}
-
-	if (!timeout) {
-		e_dbg("Master requests are pending.\n");
-		return -E1000_ERR_MASTER_REQUESTS_PENDING;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_reset_adaptive - Reset Adaptive Interframe Spacing
- *  @hw: pointer to the HW structure
- *
- *  Reset the Adaptive Interframe Spacing throttle to default values.
- **/
-void e1000e_reset_adaptive(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-
-	if (!mac->adaptive_ifs) {
-		e_dbg("Not in Adaptive IFS mode!\n");
-		goto out;
-	}
-
-	mac->current_ifs_val = 0;
-	mac->ifs_min_val = IFS_MIN;
-	mac->ifs_max_val = IFS_MAX;
-	mac->ifs_step_size = IFS_STEP;
-	mac->ifs_ratio = IFS_RATIO;
-
-	mac->in_ifs_mode = false;
-	ew32(AIT, 0);
-out:
-	return;
-}
-
-/**
- *  e1000e_update_adaptive - Update Adaptive Interframe Spacing
- *  @hw: pointer to the HW structure
- *
- *  Update the Adaptive Interframe Spacing Throttle value based on the
- *  time between transmitted packets and time between collisions.
- **/
-void e1000e_update_adaptive(struct e1000_hw *hw)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-
-	if (!mac->adaptive_ifs) {
-		e_dbg("Not in Adaptive IFS mode!\n");
-		goto out;
-	}
-
-	if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) {
-		if (mac->tx_packet_delta > MIN_NUM_XMITS) {
-			mac->in_ifs_mode = true;
-			if (mac->current_ifs_val < mac->ifs_max_val) {
-				if (!mac->current_ifs_val)
-					mac->current_ifs_val = mac->ifs_min_val;
-				else
-					mac->current_ifs_val +=
-						mac->ifs_step_size;
-				ew32(AIT, mac->current_ifs_val);
-			}
-		}
-	} else {
-		if (mac->in_ifs_mode &&
-		    (mac->tx_packet_delta <= MIN_NUM_XMITS)) {
-			mac->current_ifs_val = 0;
-			mac->in_ifs_mode = false;
-			ew32(AIT, 0);
-		}
-	}
-out:
-	return;
-}
-
-/**
- *  e1000_raise_eec_clk - Raise EEPROM clock
- *  @hw: pointer to the HW structure
- *  @eecd: pointer to the EEPROM
- *
- *  Enable/Raise the EEPROM clock bit.
- **/
-static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd)
-{
-	*eecd = *eecd | E1000_EECD_SK;
-	ew32(EECD, *eecd);
-	e1e_flush();
-	udelay(hw->nvm.delay_usec);
-}
-
-/**
- *  e1000_lower_eec_clk - Lower EEPROM clock
- *  @hw: pointer to the HW structure
- *  @eecd: pointer to the EEPROM
- *
- *  Clear/Lower the EEPROM clock bit.
- **/
-static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd)
-{
-	*eecd = *eecd & ~E1000_EECD_SK;
-	ew32(EECD, *eecd);
-	e1e_flush();
-	udelay(hw->nvm.delay_usec);
-}
-
-/**
- *  e1000_shift_out_eec_bits - Shift data bits our to the EEPROM
- *  @hw: pointer to the HW structure
- *  @data: data to send to the EEPROM
- *  @count: number of bits to shift out
- *
- *  We need to shift 'count' bits out to the EEPROM.  So, the value in the
- *  "data" parameter will be shifted out to the EEPROM one bit at a time.
- *  In order to do this, "data" must be broken down into bits.
- **/
-static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count)
-{
-	struct e1000_nvm_info *nvm = &hw->nvm;
-	u32 eecd = er32(EECD);
-	u32 mask;
-
-	mask = 0x01 << (count - 1);
-	if (nvm->type == e1000_nvm_eeprom_spi)
-		eecd |= E1000_EECD_DO;
-
-	do {
-		eecd &= ~E1000_EECD_DI;
-
-		if (data & mask)
-			eecd |= E1000_EECD_DI;
-
-		ew32(EECD, eecd);
-		e1e_flush();
-
-		udelay(nvm->delay_usec);
-
-		e1000_raise_eec_clk(hw, &eecd);
-		e1000_lower_eec_clk(hw, &eecd);
-
-		mask >>= 1;
-	} while (mask);
-
-	eecd &= ~E1000_EECD_DI;
-	ew32(EECD, eecd);
-}
-
-/**
- *  e1000_shift_in_eec_bits - Shift data bits in from the EEPROM
- *  @hw: pointer to the HW structure
- *  @count: number of bits to shift in
- *
- *  In order to read a register from the EEPROM, we need to shift 'count' bits
- *  in from the EEPROM.  Bits are "shifted in" by raising the clock input to
- *  the EEPROM (setting the SK bit), and then reading the value of the data out
- *  "DO" bit.  During this "shifting in" process the data in "DI" bit should
- *  always be clear.
- **/
-static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count)
-{
-	u32 eecd;
-	u32 i;
-	u16 data;
-
-	eecd = er32(EECD);
-
-	eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
-	data = 0;
-
-	for (i = 0; i < count; i++) {
-		data <<= 1;
-		e1000_raise_eec_clk(hw, &eecd);
-
-		eecd = er32(EECD);
-
-		eecd &= ~E1000_EECD_DI;
-		if (eecd & E1000_EECD_DO)
-			data |= 1;
-
-		e1000_lower_eec_clk(hw, &eecd);
-	}
-
-	return data;
-}
-
-/**
- *  e1000e_poll_eerd_eewr_done - Poll for EEPROM read/write completion
- *  @hw: pointer to the HW structure
- *  @ee_reg: EEPROM flag for polling
- *
- *  Polls the EEPROM status bit for either read or write completion based
- *  upon the value of 'ee_reg'.
- **/
-s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
-{
-	u32 attempts = 100000;
-	u32 i, reg = 0;
-
-	for (i = 0; i < attempts; i++) {
-		if (ee_reg == E1000_NVM_POLL_READ)
-			reg = er32(EERD);
-		else
-			reg = er32(EEWR);
-
-		if (reg & E1000_NVM_RW_REG_DONE)
-			return 0;
-
-		udelay(5);
-	}
-
-	return -E1000_ERR_NVM;
-}
-
-/**
- *  e1000e_acquire_nvm - Generic request for access to EEPROM
- *  @hw: pointer to the HW structure
- *
- *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
- *  Return successful if access grant bit set, else clear the request for
- *  EEPROM access and return -E1000_ERR_NVM (-1).
- **/
-s32 e1000e_acquire_nvm(struct e1000_hw *hw)
-{
-	u32 eecd = er32(EECD);
-	s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
-
-	ew32(EECD, eecd | E1000_EECD_REQ);
-	eecd = er32(EECD);
-
-	while (timeout) {
-		if (eecd & E1000_EECD_GNT)
-			break;
-		udelay(5);
-		eecd = er32(EECD);
-		timeout--;
-	}
-
-	if (!timeout) {
-		eecd &= ~E1000_EECD_REQ;
-		ew32(EECD, eecd);
-		e_dbg("Could not acquire NVM grant\n");
-		return -E1000_ERR_NVM;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_standby_nvm - Return EEPROM to standby state
- *  @hw: pointer to the HW structure
- *
- *  Return the EEPROM to a standby state.
- **/
-static void e1000_standby_nvm(struct e1000_hw *hw)
-{
-	struct e1000_nvm_info *nvm = &hw->nvm;
-	u32 eecd = er32(EECD);
-
-	if (nvm->type == e1000_nvm_eeprom_spi) {
-		/* Toggle CS to flush commands */
-		eecd |= E1000_EECD_CS;
-		ew32(EECD, eecd);
-		e1e_flush();
-		udelay(nvm->delay_usec);
-		eecd &= ~E1000_EECD_CS;
-		ew32(EECD, eecd);
-		e1e_flush();
-		udelay(nvm->delay_usec);
-	}
-}
-
-/**
- *  e1000_stop_nvm - Terminate EEPROM command
- *  @hw: pointer to the HW structure
- *
- *  Terminates the current command by inverting the EEPROM's chip select pin.
- **/
-static void e1000_stop_nvm(struct e1000_hw *hw)
-{
-	u32 eecd;
-
-	eecd = er32(EECD);
-	if (hw->nvm.type == e1000_nvm_eeprom_spi) {
-		/* Pull CS high */
-		eecd |= E1000_EECD_CS;
-		e1000_lower_eec_clk(hw, &eecd);
-	}
-}
-
-/**
- *  e1000e_release_nvm - Release exclusive access to EEPROM
- *  @hw: pointer to the HW structure
- *
- *  Stop any current commands to the EEPROM and clear the EEPROM request bit.
- **/
-void e1000e_release_nvm(struct e1000_hw *hw)
-{
-	u32 eecd;
-
-	e1000_stop_nvm(hw);
-
-	eecd = er32(EECD);
-	eecd &= ~E1000_EECD_REQ;
-	ew32(EECD, eecd);
-}
-
-/**
- *  e1000_ready_nvm_eeprom - Prepares EEPROM for read/write
- *  @hw: pointer to the HW structure
- *
- *  Setups the EEPROM for reading and writing.
- **/
-static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
-{
-	struct e1000_nvm_info *nvm = &hw->nvm;
-	u32 eecd = er32(EECD);
-	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);
-		e1e_flush();
-		udelay(1);
-
-		/*
-		 * Read "Status Register" repeatedly until the LSB is cleared.
-		 * The EEPROM will signal that the command has been completed
-		 * by clearing bit 0 of the internal status register.  If it's
-		 * not cleared within 'timeout', then error out.
-		 */
-		while (timeout) {
-			e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
-						 hw->nvm.opcode_bits);
-			spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8);
-			if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
-				break;
-
-			udelay(5);
-			e1000_standby_nvm(hw);
-			timeout--;
-		}
-
-		if (!timeout) {
-			e_dbg("SPI NVM Status error\n");
-			return -E1000_ERR_NVM;
-		}
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_read_nvm_eerd - Reads EEPROM using EERD register
- *  @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 using the EERD register.
- **/
-s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
-{
-	struct e1000_nvm_info *nvm = &hw->nvm;
-	u32 i, eerd = 0;
-	s32 ret_val = 0;
-
-	/*
-	 * A check for invalid values:  offset too large, too many words,
-	 * too many words for the offset, and not enough words.
-	 */
-	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
-	    (words == 0)) {
-		e_dbg("nvm parameter(s) out of bounds\n");
-		return -E1000_ERR_NVM;
-	}
-
-	for (i = 0; i < words; i++) {
-		eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) +
-		       E1000_NVM_RW_REG_START;
-
-		ew32(EERD, eerd);
-		ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ);
-		if (ret_val)
-			break;
-
-		data[i] = (er32(EERD) >> E1000_NVM_RW_REG_DATA);
-	}
-
-	return ret_val;
-}
-
-/**
- *  e1000e_write_nvm_spi - Write to EEPROM using SPI
- *  @hw: pointer to the HW structure
- *  @offset: offset within the EEPROM to be written to
- *  @words: number of words to write
- *  @data: 16 bit word(s) to be written to the EEPROM
- *
- *  Writes data to EEPROM at offset using SPI interface.
- *
- *  If e1000e_update_nvm_checksum is not called after this function , the
- *  EEPROM will most likely contain an invalid checksum.
- **/
-s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
-{
-	struct e1000_nvm_info *nvm = &hw->nvm;
-	s32 ret_val;
-	u16 widx = 0;
-
-	/*
-	 * 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)) {
-		e_dbg("nvm parameter(s) out of bounds\n");
-		return -E1000_ERR_NVM;
-	}
-
-	ret_val = nvm->ops.acquire(hw);
-	if (ret_val)
-		return ret_val;
-
-	while (widx < words) {
-		u8 write_opcode = NVM_WRITE_OPCODE_SPI;
-
-		ret_val = e1000_ready_nvm_eeprom(hw);
-		if (ret_val) {
-			nvm->ops.release(hw);
-			return ret_val;
-		}
-
-		e1000_standby_nvm(hw);
-
-		/* Send the WRITE ENABLE command (8 bit opcode) */
-		e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,
-					 nvm->opcode_bits);
-
-		e1000_standby_nvm(hw);
-
-		/*
-		 * Some SPI eeproms use the 8th address bit embedded in the
-		 * opcode
-		 */
-		if ((nvm->address_bits == 8) && (offset >= 128))
-			write_opcode |= NVM_A8_OPCODE_SPI;
-
-		/* Send the Write command (8-bit opcode + addr) */
-		e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);
-		e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),
-					 nvm->address_bits);
-
-		/* Loop to allow for up to whole page write of eeprom */
-		while (widx < words) {
-			u16 word_out = data[widx];
-			word_out = (word_out >> 8) | (word_out << 8);
-			e1000_shift_out_eec_bits(hw, word_out, 16);
-			widx++;
-
-			if ((((offset + widx) * 2) % nvm->page_size) == 0) {
-				e1000_standby_nvm(hw);
-				break;
-			}
-		}
-	}
-
-	usleep_range(10000, 20000);
-	nvm->ops.release(hw);
-	return 0;
-}
-
-/**
- *  e1000_read_pba_string_generic - Read device part number
- *  @hw: pointer to the HW structure
- *  @pba_num: pointer to device part number
- *  @pba_num_size: size of part number buffer
- *
- *  Reads the product board assembly (PBA) number from the EEPROM and stores
- *  the value in pba_num.
- **/
-s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
-				  u32 pba_num_size)
-{
-	s32 ret_val;
-	u16 nvm_data;
-	u16 pba_ptr;
-	u16 offset;
-	u16 length;
-
-	if (pba_num == NULL) {
-		e_dbg("PBA string buffer was null\n");
-		ret_val = E1000_ERR_INVALID_ARGUMENT;
-		goto out;
-	}
-
-	ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
-	if (ret_val) {
-		e_dbg("NVM Read Error\n");
-		goto out;
-	}
-
-	ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
-	if (ret_val) {
-		e_dbg("NVM Read Error\n");
-		goto out;
-	}
-
-	/*
-	 * if nvm_data is not ptr guard the PBA must be in legacy format which
-	 * means pba_ptr is actually our second data word for the PBA number
-	 * and we can decode it into an ascii string
-	 */
-	if (nvm_data != NVM_PBA_PTR_GUARD) {
-		e_dbg("NVM PBA number is not stored as string\n");
-
-		/* we will need 11 characters to store the PBA */
-		if (pba_num_size < 11) {
-			e_dbg("PBA string buffer too small\n");
-			return E1000_ERR_NO_SPACE;
-		}
-
-		/* extract hex string from data and pba_ptr */
-		pba_num[0] = (nvm_data >> 12) & 0xF;
-		pba_num[1] = (nvm_data >> 8) & 0xF;
-		pba_num[2] = (nvm_data >> 4) & 0xF;
-		pba_num[3] = nvm_data & 0xF;
-		pba_num[4] = (pba_ptr >> 12) & 0xF;
-		pba_num[5] = (pba_ptr >> 8) & 0xF;
-		pba_num[6] = '-';
-		pba_num[7] = 0;
-		pba_num[8] = (pba_ptr >> 4) & 0xF;
-		pba_num[9] = pba_ptr & 0xF;
-
-		/* put a null character on the end of our string */
-		pba_num[10] = '\0';
-
-		/* switch all the data but the '-' to hex char */
-		for (offset = 0; offset < 10; offset++) {
-			if (pba_num[offset] < 0xA)
-				pba_num[offset] += '0';
-			else if (pba_num[offset] < 0x10)
-				pba_num[offset] += 'A' - 0xA;
-		}
-
-		goto out;
-	}
-
-	ret_val = e1000_read_nvm(hw, pba_ptr, 1, &length);
-	if (ret_val) {
-		e_dbg("NVM Read Error\n");
-		goto out;
-	}
-
-	if (length == 0xFFFF || length == 0) {
-		e_dbg("NVM PBA number section invalid length\n");
-		ret_val = E1000_ERR_NVM_PBA_SECTION;
-		goto out;
-	}
-	/* check if pba_num buffer is big enough */
-	if (pba_num_size < (((u32)length * 2) - 1)) {
-		e_dbg("PBA string buffer too small\n");
-		ret_val = E1000_ERR_NO_SPACE;
-		goto out;
-	}
-
-	/* trim pba length from start of string */
-	pba_ptr++;
-	length--;
-
-	for (offset = 0; offset < length; offset++) {
-		ret_val = e1000_read_nvm(hw, pba_ptr + offset, 1, &nvm_data);
-		if (ret_val) {
-			e_dbg("NVM Read Error\n");
-			goto out;
-		}
-		pba_num[offset * 2] = (u8)(nvm_data >> 8);
-		pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
-	}
-	pba_num[offset * 2] = '\0';
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_read_mac_addr_generic - Read device MAC address
- *  @hw: pointer to the HW structure
- *
- *  Reads the device MAC address from the EEPROM and stores the value.
- *  Since devices with two ports use the same EEPROM, we increment the
- *  last bit in the MAC address for the second port.
- **/
-s32 e1000_read_mac_addr_generic(struct e1000_hw *hw)
-{
-	u32 rar_high;
-	u32 rar_low;
-	u16 i;
-
-	rar_high = er32(RAH(0));
-	rar_low = er32(RAL(0));
-
-	for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
-		hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8));
-
-	for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
-		hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8));
-
-	for (i = 0; i < ETH_ALEN; i++)
-		hw->mac.addr[i] = hw->mac.perm_addr[i];
-
-	return 0;
-}
-
-/**
- *  e1000e_validate_nvm_checksum_generic - Validate EEPROM checksum
- *  @hw: pointer to the HW structure
- *
- *  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 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 checksum = 0;
-	u16 i, nvm_data;
-
-	for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
-		ret_val = e1000_read_nvm(hw, i, 1, &nvm_data);
-		if (ret_val) {
-			e_dbg("NVM Read Error\n");
-			return ret_val;
-		}
-		checksum += nvm_data;
-	}
-
-	if (checksum != (u16) NVM_SUM) {
-		e_dbg("NVM Checksum Invalid\n");
-		return -E1000_ERR_NVM;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_update_nvm_checksum_generic - Update EEPROM checksum
- *  @hw: pointer to the HW structure
- *
- *  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 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 checksum = 0;
-	u16 i, nvm_data;
-
-	for (i = 0; i < NVM_CHECKSUM_REG; i++) {
-		ret_val = e1000_read_nvm(hw, i, 1, &nvm_data);
-		if (ret_val) {
-			e_dbg("NVM Read Error while updating checksum.\n");
-			return ret_val;
-		}
-		checksum += nvm_data;
-	}
-	checksum = (u16) NVM_SUM - checksum;
-	ret_val = e1000_write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum);
-	if (ret_val)
-		e_dbg("NVM Write Error while updating checksum.\n");
-
-	return ret_val;
-}
-
-/**
- *  e1000e_reload_nvm - Reloads EEPROM
- *  @hw: pointer to the HW structure
- *
- *  Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
- *  extended control register.
- **/
-void e1000e_reload_nvm(struct e1000_hw *hw)
-{
-	u32 ctrl_ext;
-
-	udelay(10);
-	ctrl_ext = er32(CTRL_EXT);
-	ctrl_ext |= E1000_CTRL_EXT_EE_RST;
-	ew32(CTRL_EXT, ctrl_ext);
-	e1e_flush();
-}
-
-/**
- *  e1000_calculate_checksum - Calculate checksum for buffer
- *  @buffer: pointer to EEPROM
- *  @length: size of EEPROM to calculate a checksum for
- *
- *  Calculates the checksum for some buffer on a specified length.  The
- *  checksum calculated is returned.
- **/
-static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
-{
-	u32 i;
-	u8  sum = 0;
-
-	if (!buffer)
-		return 0;
-
-	for (i = 0; i < length; i++)
-		sum += buffer[i];
-
-	return (u8) (0 - sum);
-}
-
-/**
- *  e1000_mng_enable_host_if - Checks host interface is enabled
- *  @hw: pointer to the HW structure
- *
- *  Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
- *
- *  This function checks whether the HOST IF is enabled for command operation
- *  and also checks whether the previous command is completed.  It busy waits
- *  in case of previous command is not completed.
- **/
-static s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
-{
-	u32 hicr;
-	u8 i;
-
-	if (!(hw->mac.arc_subsystem_valid)) {
-		e_dbg("ARC subsystem not valid.\n");
-		return -E1000_ERR_HOST_INTERFACE_COMMAND;
-	}
-
-	/* Check that the host interface is enabled. */
-	hicr = er32(HICR);
-	if ((hicr & E1000_HICR_EN) == 0) {
-		e_dbg("E1000_HOST_EN bit disabled.\n");
-		return -E1000_ERR_HOST_INTERFACE_COMMAND;
-	}
-	/* check the previous command is completed */
-	for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
-		hicr = er32(HICR);
-		if (!(hicr & E1000_HICR_C))
-			break;
-		mdelay(1);
-	}
-
-	if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
-		e_dbg("Previous command timeout failed .\n");
-		return -E1000_ERR_HOST_INTERFACE_COMMAND;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_check_mng_mode_generic - check management mode
- *  @hw: pointer to the HW structure
- *
- *  Reads the firmware semaphore register and returns true (>0) if
- *  manageability is enabled, else false (0).
- **/
-bool e1000e_check_mng_mode_generic(struct e1000_hw *hw)
-{
-	u32 fwsm = er32(FWSM);
-
-	return (fwsm & E1000_FWSM_MODE_MASK) ==
-		(E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
-}
-
-/**
- *  e1000e_enable_tx_pkt_filtering - Enable packet filtering on Tx
- *  @hw: pointer to the HW structure
- *
- *  Enables packet filtering on transmit packets if manageability is enabled
- *  and host interface is enabled.
- **/
-bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
-{
-	struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
-	u32 *buffer = (u32 *)&hw->mng_cookie;
-	u32 offset;
-	s32 ret_val, hdr_csum, csum;
-	u8 i, len;
-
-	hw->mac.tx_pkt_filtering = true;
-
-	/* No manageability, no filtering */
-	if (!e1000e_check_mng_mode(hw)) {
-		hw->mac.tx_pkt_filtering = false;
-		goto out;
-	}
-
-	/*
-	 * If we can't read from the host interface for whatever
-	 * reason, disable filtering.
-	 */
-	ret_val = e1000_mng_enable_host_if(hw);
-	if (ret_val) {
-		hw->mac.tx_pkt_filtering = false;
-		goto out;
-	}
-
-	/* Read in the header.  Length and offset are in dwords. */
-	len    = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
-	offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
-	for (i = 0; i < len; i++)
-		*(buffer + i) = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset + i);
-	hdr_csum = hdr->checksum;
-	hdr->checksum = 0;
-	csum = e1000_calculate_checksum((u8 *)hdr,
-					E1000_MNG_DHCP_COOKIE_LENGTH);
-	/*
-	 * If either the checksums or signature don't match, then
-	 * the cookie area isn't considered valid, in which case we
-	 * take the safe route of assuming Tx filtering is enabled.
-	 */
-	if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
-		hw->mac.tx_pkt_filtering = true;
-		goto out;
-	}
-
-	/* Cookie area is valid, make the final check for filtering. */
-	if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) {
-		hw->mac.tx_pkt_filtering = false;
-		goto out;
-	}
-
-out:
-	return hw->mac.tx_pkt_filtering;
-}
-
-/**
- *  e1000_mng_write_cmd_header - Writes manageability command header
- *  @hw: pointer to the HW structure
- *  @hdr: pointer to the host interface command header
- *
- *  Writes the command header after does the checksum calculation.
- **/
-static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
-				  struct e1000_host_mng_command_header *hdr)
-{
-	u16 i, length = sizeof(struct e1000_host_mng_command_header);
-
-	/* Write the whole command header structure with new checksum. */
-
-	hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
-
-	length >>= 2;
-	/* Write the relevant command block into the ram area. */
-	for (i = 0; i < length; i++) {
-		E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, i,
-					    *((u32 *) hdr + i));
-		e1e_flush();
-	}
-
-	return 0;
-}
-
-/**
- *  e1000_mng_host_if_write - Write to the manageability host interface
- *  @hw: pointer to the HW structure
- *  @buffer: pointer to the host interface buffer
- *  @length: size of the buffer
- *  @offset: location in the buffer to write to
- *  @sum: sum of the data (not checksum)
- *
- *  This function writes the buffer content at the offset given on the host if.
- *  It also does alignment considerations to do the writes in most efficient
- *  way.  Also fills up the sum of the buffer in *buffer parameter.
- **/
-static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer,
-				   u16 length, u16 offset, u8 *sum)
-{
-	u8 *tmp;
-	u8 *bufptr = buffer;
-	u32 data = 0;
-	u16 remaining, i, j, prev_bytes;
-
-	/* sum = only sum of the data and it is not checksum */
-
-	if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH)
-		return -E1000_ERR_PARAM;
-
-	tmp = (u8 *)&data;
-	prev_bytes = offset & 0x3;
-	offset >>= 2;
-
-	if (prev_bytes) {
-		data = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset);
-		for (j = prev_bytes; j < sizeof(u32); j++) {
-			*(tmp + j) = *bufptr++;
-			*sum += *(tmp + j);
-		}
-		E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset, data);
-		length -= j - prev_bytes;
-		offset++;
-	}
-
-	remaining = length & 0x3;
-	length -= remaining;
-
-	/* Calculate length in DWORDs */
-	length >>= 2;
-
-	/*
-	 * The device driver writes the relevant command block into the
-	 * ram area.
-	 */
-	for (i = 0; i < length; i++) {
-		for (j = 0; j < sizeof(u32); j++) {
-			*(tmp + j) = *bufptr++;
-			*sum += *(tmp + j);
-		}
-
-		E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data);
-	}
-	if (remaining) {
-		for (j = 0; j < sizeof(u32); j++) {
-			if (j < remaining)
-				*(tmp + j) = *bufptr++;
-			else
-				*(tmp + j) = 0;
-
-			*sum += *(tmp + j);
-		}
-		E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data);
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_mng_write_dhcp_info - Writes DHCP info to host interface
- *  @hw: pointer to the HW structure
- *  @buffer: pointer to the host interface
- *  @length: size of the buffer
- *
- *  Writes the DHCP information to the host interface.
- **/
-s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length)
-{
-	struct e1000_host_mng_command_header hdr;
-	s32 ret_val;
-	u32 hicr;
-
-	hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
-	hdr.command_length = length;
-	hdr.reserved1 = 0;
-	hdr.reserved2 = 0;
-	hdr.checksum = 0;
-
-	/* Enable the host interface */
-	ret_val = e1000_mng_enable_host_if(hw);
-	if (ret_val)
-		return ret_val;
-
-	/* Populate the host interface with the contents of "buffer". */
-	ret_val = e1000_mng_host_if_write(hw, buffer, length,
-					  sizeof(hdr), &(hdr.checksum));
-	if (ret_val)
-		return ret_val;
-
-	/* Write the manageability command header */
-	ret_val = e1000_mng_write_cmd_header(hw, &hdr);
-	if (ret_val)
-		return ret_val;
-
-	/* Tell the ARC a new command is pending. */
-	hicr = er32(HICR);
-	ew32(HICR, hicr | E1000_HICR_C);
-
-	return 0;
-}
-
-/**
- *  e1000e_enable_mng_pass_thru - Check if management passthrough is needed
- *  @hw: pointer to the HW structure
- *
- *  Verifies the hardware needs to leave interface enabled so that frames can
- *  be directed to and from the management interface.
- **/
-bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
-{
-	u32 manc;
-	u32 fwsm, factps;
-	bool ret_val = false;
-
-	manc = er32(MANC);
-
-	if (!(manc & E1000_MANC_RCV_TCO_EN))
-		goto out;
-
-	if (hw->mac.has_fwsm) {
-		fwsm = er32(FWSM);
-		factps = er32(FACTPS);
-
-		if (!(factps & E1000_FACTPS_MNGCG) &&
-		    ((fwsm & E1000_FWSM_MODE_MASK) ==
-		     (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
-			ret_val = true;
-			goto out;
-		}
-	} else if ((hw->mac.type == e1000_82574) ||
-		   (hw->mac.type == e1000_82583)) {
-		u16 data;
-
-		factps = er32(FACTPS);
-		e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
-
-		if (!(factps & E1000_FACTPS_MNGCG) &&
-		    ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
-		     (e1000_mng_mode_pt << 13))) {
-			ret_val = true;
-			goto out;
-		}
-	} else if ((manc & E1000_MANC_SMBUS_EN) &&
-		    !(manc & E1000_MANC_ASF_EN)) {
-			ret_val = true;
-			goto out;
-	}
-
-out:
-	return ret_val;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/e1000e/Makefile linux-libre-3.2-gnu/drivers/net/e1000e/Makefile
--- linux-libre-3.1-gnu/drivers/net/e1000e/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000e/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,37 +0,0 @@
-################################################################################
-#
-# Intel PRO/1000 Linux driver
-# 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,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-# more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# The full GNU General Public License is included in this distribution in
-# the file called "COPYING".
-#
-# Contact Information:
-# Linux NICS <linux.nics@intel.com>
-# e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-#
-################################################################################
-
-#
-# Makefile for the Intel(R) PRO/1000 ethernet driver
-#
-
-obj-$(CONFIG_E1000E) += e1000e.o
-
-e1000e-objs := 82571.o ich8lan.o es2lan.o \
-	       lib.o phy.o param.o ethtool.o netdev.o
-
diff -druN linux-libre-3.1-gnu/drivers/net/e1000e/netdev.c linux-libre-3.2-gnu/drivers/net/e1000e/netdev.c
--- linux-libre-3.1-gnu/drivers/net/e1000e/netdev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000e/netdev.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,6387 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  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,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-#include <linux/pagemap.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/interrupt.h>
-#include <linux/tcp.h>
-#include <linux/ipv6.h>
-#include <linux/slab.h>
-#include <net/checksum.h>
-#include <net/ip6_checksum.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/if_vlan.h>
-#include <linux/cpu.h>
-#include <linux/smp.h>
-#include <linux/pm_qos_params.h>
-#include <linux/pm_runtime.h>
-#include <linux/aer.h>
-#include <linux/prefetch.h>
-
-#include "e1000.h"
-
-#define DRV_EXTRAVERSION "-k"
-
-#define DRV_VERSION "1.4.4" DRV_EXTRAVERSION
-char e1000e_driver_name[] = "e1000e";
-const char e1000e_driver_version[] = DRV_VERSION;
-
-static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state);
-
-static const struct e1000_info *e1000_info_tbl[] = {
-	[board_82571]		= &e1000_82571_info,
-	[board_82572]		= &e1000_82572_info,
-	[board_82573]		= &e1000_82573_info,
-	[board_82574]		= &e1000_82574_info,
-	[board_82583]		= &e1000_82583_info,
-	[board_80003es2lan]	= &e1000_es2_info,
-	[board_ich8lan]		= &e1000_ich8_info,
-	[board_ich9lan]		= &e1000_ich9_info,
-	[board_ich10lan]	= &e1000_ich10_info,
-	[board_pchlan]		= &e1000_pch_info,
-	[board_pch2lan]		= &e1000_pch2_info,
-};
-
-struct e1000_reg_info {
-	u32 ofs;
-	char *name;
-};
-
-#define E1000_RDFH	0x02410	/* Rx Data FIFO Head - RW */
-#define E1000_RDFT	0x02418	/* Rx Data FIFO Tail - RW */
-#define E1000_RDFHS	0x02420	/* Rx Data FIFO Head Saved - RW */
-#define E1000_RDFTS	0x02428	/* Rx Data FIFO Tail Saved - RW */
-#define E1000_RDFPC	0x02430	/* Rx Data FIFO Packet Count - RW */
-
-#define E1000_TDFH	0x03410	/* Tx Data FIFO Head - RW */
-#define E1000_TDFT	0x03418	/* Tx Data FIFO Tail - RW */
-#define E1000_TDFHS	0x03420	/* Tx Data FIFO Head Saved - RW */
-#define E1000_TDFTS	0x03428	/* Tx Data FIFO Tail Saved - RW */
-#define E1000_TDFPC	0x03430	/* Tx Data FIFO Packet Count - RW */
-
-static const struct e1000_reg_info e1000_reg_info_tbl[] = {
-
-	/* General Registers */
-	{E1000_CTRL, "CTRL"},
-	{E1000_STATUS, "STATUS"},
-	{E1000_CTRL_EXT, "CTRL_EXT"},
-
-	/* Interrupt Registers */
-	{E1000_ICR, "ICR"},
-
-	/* Rx Registers */
-	{E1000_RCTL, "RCTL"},
-	{E1000_RDLEN, "RDLEN"},
-	{E1000_RDH, "RDH"},
-	{E1000_RDT, "RDT"},
-	{E1000_RDTR, "RDTR"},
-	{E1000_RXDCTL(0), "RXDCTL"},
-	{E1000_ERT, "ERT"},
-	{E1000_RDBAL, "RDBAL"},
-	{E1000_RDBAH, "RDBAH"},
-	{E1000_RDFH, "RDFH"},
-	{E1000_RDFT, "RDFT"},
-	{E1000_RDFHS, "RDFHS"},
-	{E1000_RDFTS, "RDFTS"},
-	{E1000_RDFPC, "RDFPC"},
-
-	/* Tx Registers */
-	{E1000_TCTL, "TCTL"},
-	{E1000_TDBAL, "TDBAL"},
-	{E1000_TDBAH, "TDBAH"},
-	{E1000_TDLEN, "TDLEN"},
-	{E1000_TDH, "TDH"},
-	{E1000_TDT, "TDT"},
-	{E1000_TIDV, "TIDV"},
-	{E1000_TXDCTL(0), "TXDCTL"},
-	{E1000_TADV, "TADV"},
-	{E1000_TARC(0), "TARC"},
-	{E1000_TDFH, "TDFH"},
-	{E1000_TDFT, "TDFT"},
-	{E1000_TDFHS, "TDFHS"},
-	{E1000_TDFTS, "TDFTS"},
-	{E1000_TDFPC, "TDFPC"},
-
-	/* List Terminator */
-	{}
-};
-
-/*
- * e1000_regdump - register printout routine
- */
-static void e1000_regdump(struct e1000_hw *hw, struct e1000_reg_info *reginfo)
-{
-	int n = 0;
-	char rname[16];
-	u32 regs[8];
-
-	switch (reginfo->ofs) {
-	case E1000_RXDCTL(0):
-		for (n = 0; n < 2; n++)
-			regs[n] = __er32(hw, E1000_RXDCTL(n));
-		break;
-	case E1000_TXDCTL(0):
-		for (n = 0; n < 2; n++)
-			regs[n] = __er32(hw, E1000_TXDCTL(n));
-		break;
-	case E1000_TARC(0):
-		for (n = 0; n < 2; n++)
-			regs[n] = __er32(hw, E1000_TARC(n));
-		break;
-	default:
-		printk(KERN_INFO "%-15s %08x\n",
-		       reginfo->name, __er32(hw, reginfo->ofs));
-		return;
-	}
-
-	snprintf(rname, 16, "%s%s", reginfo->name, "[0-1]");
-	printk(KERN_INFO "%-15s ", rname);
-	for (n = 0; n < 2; n++)
-		printk(KERN_CONT "%08x ", regs[n]);
-	printk(KERN_CONT "\n");
-}
-
-/*
- * e1000e_dump - Print registers, Tx-ring and Rx-ring
- */
-static void e1000e_dump(struct e1000_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_reg_info *reginfo;
-	struct e1000_ring *tx_ring = adapter->tx_ring;
-	struct e1000_tx_desc *tx_desc;
-	struct my_u0 {
-		u64 a;
-		u64 b;
-	} *u0;
-	struct e1000_buffer *buffer_info;
-	struct e1000_ring *rx_ring = adapter->rx_ring;
-	union e1000_rx_desc_packet_split *rx_desc_ps;
-	struct e1000_rx_desc *rx_desc;
-	struct my_u1 {
-		u64 a;
-		u64 b;
-		u64 c;
-		u64 d;
-	} *u1;
-	u32 staterr;
-	int i = 0;
-
-	if (!netif_msg_hw(adapter))
-		return;
-
-	/* Print netdevice Info */
-	if (netdev) {
-		dev_info(&adapter->pdev->dev, "Net device Info\n");
-		printk(KERN_INFO "Device Name     state            "
-		       "trans_start      last_rx\n");
-		printk(KERN_INFO "%-15s %016lX %016lX %016lX\n",
-		       netdev->name, netdev->state, netdev->trans_start,
-		       netdev->last_rx);
-	}
-
-	/* Print Registers */
-	dev_info(&adapter->pdev->dev, "Register Dump\n");
-	printk(KERN_INFO " Register Name   Value\n");
-	for (reginfo = (struct e1000_reg_info *)e1000_reg_info_tbl;
-	     reginfo->name; reginfo++) {
-		e1000_regdump(hw, reginfo);
-	}
-
-	/* Print Tx Ring Summary */
-	if (!netdev || !netif_running(netdev))
-		goto exit;
-
-	dev_info(&adapter->pdev->dev, "Tx Ring Summary\n");
-	printk(KERN_INFO "Queue [NTU] [NTC] [bi(ntc)->dma  ]"
-	       " leng ntw timestamp\n");
-	buffer_info = &tx_ring->buffer_info[tx_ring->next_to_clean];
-	printk(KERN_INFO " %5d %5X %5X %016llX %04X %3X %016llX\n",
-	       0, tx_ring->next_to_use, tx_ring->next_to_clean,
-	       (unsigned long long)buffer_info->dma,
-	       buffer_info->length,
-	       buffer_info->next_to_watch,
-	       (unsigned long long)buffer_info->time_stamp);
-
-	/* Print Tx Ring */
-	if (!netif_msg_tx_done(adapter))
-		goto rx_ring_summary;
-
-	dev_info(&adapter->pdev->dev, "Tx Ring Dump\n");
-
-	/* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended)
-	 *
-	 * Legacy Transmit Descriptor
-	 *   +--------------------------------------------------------------+
-	 * 0 |         Buffer Address [63:0] (Reserved on Write Back)       |
-	 *   +--------------------------------------------------------------+
-	 * 8 | Special  |    CSS     | Status |  CMD    |  CSO   |  Length  |
-	 *   +--------------------------------------------------------------+
-	 *   63       48 47        36 35    32 31     24 23    16 15        0
-	 *
-	 * Extended Context Descriptor (DTYP=0x0) for TSO or checksum offload
-	 *   63      48 47    40 39       32 31             16 15    8 7      0
-	 *   +----------------------------------------------------------------+
-	 * 0 |  TUCSE  | TUCS0  |   TUCSS   |     IPCSE       | IPCS0 | IPCSS |
-	 *   +----------------------------------------------------------------+
-	 * 8 |   MSS   | HDRLEN | RSV | STA | TUCMD | DTYP |      PAYLEN      |
-	 *   +----------------------------------------------------------------+
-	 *   63      48 47    40 39 36 35 32 31   24 23  20 19                0
-	 *
-	 * Extended Data Descriptor (DTYP=0x1)
-	 *   +----------------------------------------------------------------+
-	 * 0 |                     Buffer Address [63:0]                      |
-	 *   +----------------------------------------------------------------+
-	 * 8 | VLAN tag |  POPTS  | Rsvd | Status | Command | DTYP |  DTALEN  |
-	 *   +----------------------------------------------------------------+
-	 *   63       48 47     40 39  36 35    32 31     24 23  20 19        0
-	 */
-	printk(KERN_INFO "Tl[desc]     [address 63:0  ] [SpeCssSCmCsLen]"
-	       " [bi->dma       ] leng  ntw timestamp        bi->skb "
-	       "<-- Legacy format\n");
-	printk(KERN_INFO "Tc[desc]     [Ce CoCsIpceCoS] [MssHlRSCm0Plen]"
-	       " [bi->dma       ] leng  ntw timestamp        bi->skb "
-	       "<-- Ext Context format\n");
-	printk(KERN_INFO "Td[desc]     [address 63:0  ] [VlaPoRSCm1Dlen]"
-	       " [bi->dma       ] leng  ntw timestamp        bi->skb "
-	       "<-- Ext Data format\n");
-	for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
-		tx_desc = E1000_TX_DESC(*tx_ring, i);
-		buffer_info = &tx_ring->buffer_info[i];
-		u0 = (struct my_u0 *)tx_desc;
-		printk(KERN_INFO "T%c[0x%03X]    %016llX %016llX %016llX "
-		       "%04X  %3X %016llX %p",
-		       (!(le64_to_cpu(u0->b) & (1 << 29)) ? 'l' :
-			((le64_to_cpu(u0->b) & (1 << 20)) ? 'd' : 'c')), i,
-		       (unsigned long long)le64_to_cpu(u0->a),
-		       (unsigned long long)le64_to_cpu(u0->b),
-		       (unsigned long long)buffer_info->dma,
-		       buffer_info->length, buffer_info->next_to_watch,
-		       (unsigned long long)buffer_info->time_stamp,
-		       buffer_info->skb);
-		if (i == tx_ring->next_to_use && i == tx_ring->next_to_clean)
-			printk(KERN_CONT " NTC/U\n");
-		else if (i == tx_ring->next_to_use)
-			printk(KERN_CONT " NTU\n");
-		else if (i == tx_ring->next_to_clean)
-			printk(KERN_CONT " NTC\n");
-		else
-			printk(KERN_CONT "\n");
-
-		if (netif_msg_pktdata(adapter) && buffer_info->dma != 0)
-			print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS,
-				       16, 1, phys_to_virt(buffer_info->dma),
-				       buffer_info->length, true);
-	}
-
-	/* Print Rx Ring Summary */
-rx_ring_summary:
-	dev_info(&adapter->pdev->dev, "Rx Ring Summary\n");
-	printk(KERN_INFO "Queue [NTU] [NTC]\n");
-	printk(KERN_INFO " %5d %5X %5X\n", 0,
-	       rx_ring->next_to_use, rx_ring->next_to_clean);
-
-	/* Print Rx Ring */
-	if (!netif_msg_rx_status(adapter))
-		goto exit;
-
-	dev_info(&adapter->pdev->dev, "Rx Ring Dump\n");
-	switch (adapter->rx_ps_pages) {
-	case 1:
-	case 2:
-	case 3:
-		/* [Extended] Packet Split Receive Descriptor Format
-		 *
-		 *    +-----------------------------------------------------+
-		 *  0 |                Buffer Address 0 [63:0]              |
-		 *    +-----------------------------------------------------+
-		 *  8 |                Buffer Address 1 [63:0]              |
-		 *    +-----------------------------------------------------+
-		 * 16 |                Buffer Address 2 [63:0]              |
-		 *    +-----------------------------------------------------+
-		 * 24 |                Buffer Address 3 [63:0]              |
-		 *    +-----------------------------------------------------+
-		 */
-		printk(KERN_INFO "R  [desc]      [buffer 0 63:0 ] "
-		       "[buffer 1 63:0 ] "
-		       "[buffer 2 63:0 ] [buffer 3 63:0 ] [bi->dma       ] "
-		       "[bi->skb] <-- Ext Pkt Split format\n");
-		/* [Extended] Receive Descriptor (Write-Back) Format
-		 *
-		 *   63       48 47    32 31     13 12    8 7    4 3        0
-		 *   +------------------------------------------------------+
-		 * 0 | Packet   | IP     |  Rsvd   | MRQ   | Rsvd | MRQ RSS |
-		 *   | Checksum | Ident  |         | Queue |      |  Type   |
-		 *   +------------------------------------------------------+
-		 * 8 | VLAN Tag | Length | Extended Error | Extended Status |
-		 *   +------------------------------------------------------+
-		 *   63       48 47    32 31            20 19               0
-		 */
-		printk(KERN_INFO "RWB[desc]      [ck ipid mrqhsh] "
-		       "[vl   l0 ee  es] "
-		       "[ l3  l2  l1 hs] [reserved      ] ---------------- "
-		       "[bi->skb] <-- Ext Rx Write-Back format\n");
-		for (i = 0; i < rx_ring->count; i++) {
-			buffer_info = &rx_ring->buffer_info[i];
-			rx_desc_ps = E1000_RX_DESC_PS(*rx_ring, i);
-			u1 = (struct my_u1 *)rx_desc_ps;
-			staterr =
-			    le32_to_cpu(rx_desc_ps->wb.middle.status_error);
-			if (staterr & E1000_RXD_STAT_DD) {
-				/* Descriptor Done */
-				printk(KERN_INFO "RWB[0x%03X]     %016llX "
-				       "%016llX %016llX %016llX "
-				       "---------------- %p", i,
-				       (unsigned long long)le64_to_cpu(u1->a),
-				       (unsigned long long)le64_to_cpu(u1->b),
-				       (unsigned long long)le64_to_cpu(u1->c),
-				       (unsigned long long)le64_to_cpu(u1->d),
-				       buffer_info->skb);
-			} else {
-				printk(KERN_INFO "R  [0x%03X]     %016llX "
-				       "%016llX %016llX %016llX %016llX %p", i,
-				       (unsigned long long)le64_to_cpu(u1->a),
-				       (unsigned long long)le64_to_cpu(u1->b),
-				       (unsigned long long)le64_to_cpu(u1->c),
-				       (unsigned long long)le64_to_cpu(u1->d),
-				       (unsigned long long)buffer_info->dma,
-				       buffer_info->skb);
-
-				if (netif_msg_pktdata(adapter))
-					print_hex_dump(KERN_INFO, "",
-						DUMP_PREFIX_ADDRESS, 16, 1,
-						phys_to_virt(buffer_info->dma),
-						adapter->rx_ps_bsize0, true);
-			}
-
-			if (i == rx_ring->next_to_use)
-				printk(KERN_CONT " NTU\n");
-			else if (i == rx_ring->next_to_clean)
-				printk(KERN_CONT " NTC\n");
-			else
-				printk(KERN_CONT "\n");
-		}
-		break;
-	default:
-	case 0:
-		/* Legacy Receive Descriptor Format
-		 *
-		 * +-----------------------------------------------------+
-		 * |                Buffer Address [63:0]                |
-		 * +-----------------------------------------------------+
-		 * | VLAN Tag | Errors | Status 0 | Packet csum | Length |
-		 * +-----------------------------------------------------+
-		 * 63       48 47    40 39      32 31         16 15      0
-		 */
-		printk(KERN_INFO "Rl[desc]     [address 63:0  ] "
-		       "[vl er S cks ln] [bi->dma       ] [bi->skb] "
-		       "<-- Legacy format\n");
-		for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) {
-			rx_desc = E1000_RX_DESC(*rx_ring, i);
-			buffer_info = &rx_ring->buffer_info[i];
-			u0 = (struct my_u0 *)rx_desc;
-			printk(KERN_INFO "Rl[0x%03X]    %016llX %016llX "
-			       "%016llX %p", i,
-			       (unsigned long long)le64_to_cpu(u0->a),
-			       (unsigned long long)le64_to_cpu(u0->b),
-			       (unsigned long long)buffer_info->dma,
-			       buffer_info->skb);
-			if (i == rx_ring->next_to_use)
-				printk(KERN_CONT " NTU\n");
-			else if (i == rx_ring->next_to_clean)
-				printk(KERN_CONT " NTC\n");
-			else
-				printk(KERN_CONT "\n");
-
-			if (netif_msg_pktdata(adapter))
-				print_hex_dump(KERN_INFO, "",
-					       DUMP_PREFIX_ADDRESS,
-					       16, 1,
-					       phys_to_virt(buffer_info->dma),
-					       adapter->rx_buffer_len, true);
-		}
-	}
-
-exit:
-	return;
-}
-
-/**
- * e1000_desc_unused - calculate if we have unused descriptors
- **/
-static int e1000_desc_unused(struct e1000_ring *ring)
-{
-	if (ring->next_to_clean > ring->next_to_use)
-		return ring->next_to_clean - ring->next_to_use - 1;
-
-	return ring->count + ring->next_to_clean - ring->next_to_use - 1;
-}
-
-/**
- * e1000_receive_skb - helper function to handle Rx indications
- * @adapter: board private structure
- * @status: descriptor status field as written by hardware
- * @vlan: descriptor vlan field as written by hardware (no le/be conversion)
- * @skb: pointer to sk_buff to be indicated to stack
- **/
-static void e1000_receive_skb(struct e1000_adapter *adapter,
-			      struct net_device *netdev, struct sk_buff *skb,
-			      u8 status, __le16 vlan)
-{
-	u16 tag = le16_to_cpu(vlan);
-	skb->protocol = eth_type_trans(skb, netdev);
-
-	if (status & E1000_RXD_STAT_VP)
-		__vlan_hwaccel_put_tag(skb, tag);
-
-	napi_gro_receive(&adapter->napi, skb);
-}
-
-/**
- * e1000_rx_checksum - Receive Checksum Offload
- * @adapter:     board private structure
- * @status_err:  receive descriptor status and error fields
- * @csum:	receive descriptor csum field
- * @sk_buff:     socket buffer with received data
- **/
-static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
-			      u32 csum, struct sk_buff *skb)
-{
-	u16 status = (u16)status_err;
-	u8 errors = (u8)(status_err >> 24);
-
-	skb_checksum_none_assert(skb);
-
-	/* Ignore Checksum bit is set */
-	if (status & E1000_RXD_STAT_IXSM)
-		return;
-	/* TCP/UDP checksum error bit is set */
-	if (errors & E1000_RXD_ERR_TCPE) {
-		/* let the stack verify checksum errors */
-		adapter->hw_csum_err++;
-		return;
-	}
-
-	/* TCP/UDP Checksum has not been calculated */
-	if (!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)))
-		return;
-
-	/* It must be a TCP or UDP packet with a valid checksum */
-	if (status & E1000_RXD_STAT_TCPCS) {
-		/* TCP checksum is good */
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	} else {
-		/*
-		 * IP fragment with UDP payload
-		 * Hardware complements the payload checksum, so we undo it
-		 * and then put the value in host order for further stack use.
-		 */
-		__sum16 sum = (__force __sum16)htons(csum);
-		skb->csum = csum_unfold(~sum);
-		skb->ip_summed = CHECKSUM_COMPLETE;
-	}
-	adapter->hw_csum_good++;
-}
-
-/**
- * e1000e_update_tail_wa - helper function for e1000e_update_[rt]dt_wa()
- * @hw: pointer to the HW structure
- * @tail: address of tail descriptor register
- * @i: value to write to tail descriptor register
- *
- * When updating the tail register, the ME could be accessing Host CSR
- * registers at the same time.  Normally, this is handled in h/w by an
- * arbiter but on some parts there is a bug that acknowledges Host accesses
- * later than it should which could result in the descriptor register to
- * have an incorrect value.  Workaround this by checking the FWSM register
- * which has bit 24 set while ME is accessing Host CSR registers, wait
- * if it is set and try again a number of times.
- **/
-static inline s32 e1000e_update_tail_wa(struct e1000_hw *hw, u8 __iomem * tail,
-					unsigned int i)
-{
-	unsigned int j = 0;
-
-	while ((j++ < E1000_ICH_FWSM_PCIM2PCI_COUNT) &&
-	       (er32(FWSM) & E1000_ICH_FWSM_PCIM2PCI))
-		udelay(50);
-
-	writel(i, tail);
-
-	if ((j == E1000_ICH_FWSM_PCIM2PCI_COUNT) && (i != readl(tail)))
-		return E1000_ERR_SWFW_SYNC;
-
-	return 0;
-}
-
-static void e1000e_update_rdt_wa(struct e1000_adapter *adapter, unsigned int i)
-{
-	u8 __iomem *tail = (adapter->hw.hw_addr + adapter->rx_ring->tail);
-	struct e1000_hw *hw = &adapter->hw;
-
-	if (e1000e_update_tail_wa(hw, tail, i)) {
-		u32 rctl = er32(RCTL);
-		ew32(RCTL, rctl & ~E1000_RCTL_EN);
-		e_err("ME firmware caused invalid RDT - resetting\n");
-		schedule_work(&adapter->reset_task);
-	}
-}
-
-static void e1000e_update_tdt_wa(struct e1000_adapter *adapter, unsigned int i)
-{
-	u8 __iomem *tail = (adapter->hw.hw_addr + adapter->tx_ring->tail);
-	struct e1000_hw *hw = &adapter->hw;
-
-	if (e1000e_update_tail_wa(hw, tail, i)) {
-		u32 tctl = er32(TCTL);
-		ew32(TCTL, tctl & ~E1000_TCTL_EN);
-		e_err("ME firmware caused invalid TDT - resetting\n");
-		schedule_work(&adapter->reset_task);
-	}
-}
-
-/**
- * e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended
- * @adapter: address of board private structure
- **/
-static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
-				   int cleaned_count, gfp_t gfp)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_ring *rx_ring = adapter->rx_ring;
-	struct e1000_rx_desc *rx_desc;
-	struct e1000_buffer *buffer_info;
-	struct sk_buff *skb;
-	unsigned int i;
-	unsigned int bufsz = adapter->rx_buffer_len;
-
-	i = rx_ring->next_to_use;
-	buffer_info = &rx_ring->buffer_info[i];
-
-	while (cleaned_count--) {
-		skb = buffer_info->skb;
-		if (skb) {
-			skb_trim(skb, 0);
-			goto map_skb;
-		}
-
-		skb = __netdev_alloc_skb_ip_align(netdev, bufsz, gfp);
-		if (!skb) {
-			/* Better luck next round */
-			adapter->alloc_rx_buff_failed++;
-			break;
-		}
-
-		buffer_info->skb = skb;
-map_skb:
-		buffer_info->dma = dma_map_single(&pdev->dev, skb->data,
-						  adapter->rx_buffer_len,
-						  DMA_FROM_DEVICE);
-		if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
-			dev_err(&pdev->dev, "Rx DMA map failed\n");
-			adapter->rx_dma_failed++;
-			break;
-		}
-
-		rx_desc = E1000_RX_DESC(*rx_ring, i);
-		rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
-
-		if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) {
-			/*
-			 * Force memory writes to complete before letting h/w
-			 * know there are new descriptors to fetch.  (Only
-			 * applicable for weak-ordered memory model archs,
-			 * such as IA-64).
-			 */
-			wmb();
-			if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
-				e1000e_update_rdt_wa(adapter, i);
-			else
-				writel(i, adapter->hw.hw_addr + rx_ring->tail);
-		}
-		i++;
-		if (i == rx_ring->count)
-			i = 0;
-		buffer_info = &rx_ring->buffer_info[i];
-	}
-
-	rx_ring->next_to_use = i;
-}
-
-/**
- * e1000_alloc_rx_buffers_ps - Replace used receive buffers; packet split
- * @adapter: address of board private structure
- **/
-static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
-				      int cleaned_count, gfp_t gfp)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct pci_dev *pdev = adapter->pdev;
-	union e1000_rx_desc_packet_split *rx_desc;
-	struct e1000_ring *rx_ring = adapter->rx_ring;
-	struct e1000_buffer *buffer_info;
-	struct e1000_ps_page *ps_page;
-	struct sk_buff *skb;
-	unsigned int i, j;
-
-	i = rx_ring->next_to_use;
-	buffer_info = &rx_ring->buffer_info[i];
-
-	while (cleaned_count--) {
-		rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
-
-		for (j = 0; j < PS_PAGE_BUFFERS; j++) {
-			ps_page = &buffer_info->ps_pages[j];
-			if (j >= adapter->rx_ps_pages) {
-				/* all unused desc entries get hw null ptr */
-				rx_desc->read.buffer_addr[j + 1] =
-				    ~cpu_to_le64(0);
-				continue;
-			}
-			if (!ps_page->page) {
-				ps_page->page = alloc_page(gfp);
-				if (!ps_page->page) {
-					adapter->alloc_rx_buff_failed++;
-					goto no_buffers;
-				}
-				ps_page->dma = dma_map_page(&pdev->dev,
-							    ps_page->page,
-							    0, PAGE_SIZE,
-							    DMA_FROM_DEVICE);
-				if (dma_mapping_error(&pdev->dev,
-						      ps_page->dma)) {
-					dev_err(&adapter->pdev->dev,
-						"Rx DMA page map failed\n");
-					adapter->rx_dma_failed++;
-					goto no_buffers;
-				}
-			}
-			/*
-			 * Refresh the desc even if buffer_addrs
-			 * didn't change because each write-back
-			 * erases this info.
-			 */
-			rx_desc->read.buffer_addr[j + 1] =
-			    cpu_to_le64(ps_page->dma);
-		}
-
-		skb = __netdev_alloc_skb_ip_align(netdev,
-						  adapter->rx_ps_bsize0,
-						  gfp);
-
-		if (!skb) {
-			adapter->alloc_rx_buff_failed++;
-			break;
-		}
-
-		buffer_info->skb = skb;
-		buffer_info->dma = dma_map_single(&pdev->dev, skb->data,
-						  adapter->rx_ps_bsize0,
-						  DMA_FROM_DEVICE);
-		if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
-			dev_err(&pdev->dev, "Rx DMA map failed\n");
-			adapter->rx_dma_failed++;
-			/* cleanup skb */
-			dev_kfree_skb_any(skb);
-			buffer_info->skb = NULL;
-			break;
-		}
-
-		rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma);
-
-		if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) {
-			/*
-			 * Force memory writes to complete before letting h/w
-			 * know there are new descriptors to fetch.  (Only
-			 * applicable for weak-ordered memory model archs,
-			 * such as IA-64).
-			 */
-			wmb();
-			if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
-				e1000e_update_rdt_wa(adapter, i << 1);
-			else
-				writel(i << 1,
-				       adapter->hw.hw_addr + rx_ring->tail);
-		}
-
-		i++;
-		if (i == rx_ring->count)
-			i = 0;
-		buffer_info = &rx_ring->buffer_info[i];
-	}
-
-no_buffers:
-	rx_ring->next_to_use = i;
-}
-
-/**
- * e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers
- * @adapter: address of board private structure
- * @cleaned_count: number of buffers to allocate this pass
- **/
-
-static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
-					 int cleaned_count, gfp_t gfp)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_rx_desc *rx_desc;
-	struct e1000_ring *rx_ring = adapter->rx_ring;
-	struct e1000_buffer *buffer_info;
-	struct sk_buff *skb;
-	unsigned int i;
-	unsigned int bufsz = 256 - 16 /* for skb_reserve */;
-
-	i = rx_ring->next_to_use;
-	buffer_info = &rx_ring->buffer_info[i];
-
-	while (cleaned_count--) {
-		skb = buffer_info->skb;
-		if (skb) {
-			skb_trim(skb, 0);
-			goto check_page;
-		}
-
-		skb = __netdev_alloc_skb_ip_align(netdev, bufsz, gfp);
-		if (unlikely(!skb)) {
-			/* Better luck next round */
-			adapter->alloc_rx_buff_failed++;
-			break;
-		}
-
-		buffer_info->skb = skb;
-check_page:
-		/* allocate a new page if necessary */
-		if (!buffer_info->page) {
-			buffer_info->page = alloc_page(gfp);
-			if (unlikely(!buffer_info->page)) {
-				adapter->alloc_rx_buff_failed++;
-				break;
-			}
-		}
-
-		if (!buffer_info->dma)
-			buffer_info->dma = dma_map_page(&pdev->dev,
-			                                buffer_info->page, 0,
-			                                PAGE_SIZE,
-							DMA_FROM_DEVICE);
-
-		rx_desc = E1000_RX_DESC(*rx_ring, i);
-		rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
-
-		if (unlikely(++i == rx_ring->count))
-			i = 0;
-		buffer_info = &rx_ring->buffer_info[i];
-	}
-
-	if (likely(rx_ring->next_to_use != i)) {
-		rx_ring->next_to_use = i;
-		if (unlikely(i-- == 0))
-			i = (rx_ring->count - 1);
-
-		/* Force memory writes to complete before letting h/w
-		 * know there are new descriptors to fetch.  (Only
-		 * applicable for weak-ordered memory model archs,
-		 * such as IA-64). */
-		wmb();
-		if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
-			e1000e_update_rdt_wa(adapter, i);
-		else
-			writel(i, adapter->hw.hw_addr + rx_ring->tail);
-	}
-}
-
-/**
- * e1000_clean_rx_irq - Send received data up the network stack; legacy
- * @adapter: board private structure
- *
- * the return value indicates whether actual cleaning was done, there
- * is no guarantee that everything was cleaned
- **/
-static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
-			       int *work_done, int work_to_do)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_ring *rx_ring = adapter->rx_ring;
-	struct e1000_rx_desc *rx_desc, *next_rxd;
-	struct e1000_buffer *buffer_info, *next_buffer;
-	u32 length;
-	unsigned int i;
-	int cleaned_count = 0;
-	bool cleaned = 0;
-	unsigned int total_rx_bytes = 0, total_rx_packets = 0;
-
-	i = rx_ring->next_to_clean;
-	rx_desc = E1000_RX_DESC(*rx_ring, i);
-	buffer_info = &rx_ring->buffer_info[i];
-
-	while (rx_desc->status & E1000_RXD_STAT_DD) {
-		struct sk_buff *skb;
-		u8 status;
-
-		if (*work_done >= work_to_do)
-			break;
-		(*work_done)++;
-		rmb();	/* read descriptor and rx_buffer_info after status DD */
-
-		status = rx_desc->status;
-		skb = buffer_info->skb;
-		buffer_info->skb = NULL;
-
-		prefetch(skb->data - NET_IP_ALIGN);
-
-		i++;
-		if (i == rx_ring->count)
-			i = 0;
-		next_rxd = E1000_RX_DESC(*rx_ring, i);
-		prefetch(next_rxd);
-
-		next_buffer = &rx_ring->buffer_info[i];
-
-		cleaned = 1;
-		cleaned_count++;
-		dma_unmap_single(&pdev->dev,
-				 buffer_info->dma,
-				 adapter->rx_buffer_len,
-				 DMA_FROM_DEVICE);
-		buffer_info->dma = 0;
-
-		length = le16_to_cpu(rx_desc->length);
-
-		/*
-		 * !EOP means multiple descriptors were used to store a single
-		 * packet, if that's the case we need to toss it.  In fact, we
-		 * need to toss every packet with the EOP bit clear and the
-		 * next frame that _does_ have the EOP bit set, as it is by
-		 * definition only a frame fragment
-		 */
-		if (unlikely(!(status & E1000_RXD_STAT_EOP)))
-			adapter->flags2 |= FLAG2_IS_DISCARDING;
-
-		if (adapter->flags2 & FLAG2_IS_DISCARDING) {
-			/* All receives must fit into a single buffer */
-			e_dbg("Receive packet consumed multiple buffers\n");
-			/* recycle */
-			buffer_info->skb = skb;
-			if (status & E1000_RXD_STAT_EOP)
-				adapter->flags2 &= ~FLAG2_IS_DISCARDING;
-			goto next_desc;
-		}
-
-		if (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) {
-			/* recycle */
-			buffer_info->skb = skb;
-			goto next_desc;
-		}
-
-		/* adjust length to remove Ethernet CRC */
-		if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
-			length -= 4;
-
-		total_rx_bytes += length;
-		total_rx_packets++;
-
-		/*
-		 * code added for copybreak, this should improve
-		 * performance for small packets with large amounts
-		 * of reassembly being done in the stack
-		 */
-		if (length < copybreak) {
-			struct sk_buff *new_skb =
-			    netdev_alloc_skb_ip_align(netdev, length);
-			if (new_skb) {
-				skb_copy_to_linear_data_offset(new_skb,
-							       -NET_IP_ALIGN,
-							       (skb->data -
-								NET_IP_ALIGN),
-							       (length +
-								NET_IP_ALIGN));
-				/* save the skb in buffer_info as good */
-				buffer_info->skb = skb;
-				skb = new_skb;
-			}
-			/* else just continue with the old one */
-		}
-		/* end copybreak code */
-		skb_put(skb, length);
-
-		/* Receive Checksum Offload */
-		e1000_rx_checksum(adapter,
-				  (u32)(status) |
-				  ((u32)(rx_desc->errors) << 24),
-				  le16_to_cpu(rx_desc->csum), skb);
-
-		e1000_receive_skb(adapter, netdev, skb,status,rx_desc->special);
-
-next_desc:
-		rx_desc->status = 0;
-
-		/* return some buffers to hardware, one at a time is too slow */
-		if (cleaned_count >= E1000_RX_BUFFER_WRITE) {
-			adapter->alloc_rx_buf(adapter, cleaned_count,
-					      GFP_ATOMIC);
-			cleaned_count = 0;
-		}
-
-		/* use prefetched values */
-		rx_desc = next_rxd;
-		buffer_info = next_buffer;
-	}
-	rx_ring->next_to_clean = i;
-
-	cleaned_count = e1000_desc_unused(rx_ring);
-	if (cleaned_count)
-		adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC);
-
-	adapter->total_rx_bytes += total_rx_bytes;
-	adapter->total_rx_packets += total_rx_packets;
-	return cleaned;
-}
-
-static void e1000_put_txbuf(struct e1000_adapter *adapter,
-			     struct e1000_buffer *buffer_info)
-{
-	if (buffer_info->dma) {
-		if (buffer_info->mapped_as_page)
-			dma_unmap_page(&adapter->pdev->dev, buffer_info->dma,
-				       buffer_info->length, DMA_TO_DEVICE);
-		else
-			dma_unmap_single(&adapter->pdev->dev, buffer_info->dma,
-					 buffer_info->length, DMA_TO_DEVICE);
-		buffer_info->dma = 0;
-	}
-	if (buffer_info->skb) {
-		dev_kfree_skb_any(buffer_info->skb);
-		buffer_info->skb = NULL;
-	}
-	buffer_info->time_stamp = 0;
-}
-
-static void e1000_print_hw_hang(struct work_struct *work)
-{
-	struct e1000_adapter *adapter = container_of(work,
-	                                             struct e1000_adapter,
-	                                             print_hang_task);
-	struct e1000_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;
-	struct e1000_tx_desc *eop_desc = E1000_TX_DESC(*tx_ring, eop);
-	struct e1000_hw *hw = &adapter->hw;
-	u16 phy_status, phy_1000t_status, phy_ext_status;
-	u16 pci_status;
-
-	if (test_bit(__E1000_DOWN, &adapter->state))
-		return;
-
-	e1e_rphy(hw, PHY_STATUS, &phy_status);
-	e1e_rphy(hw, PHY_1000T_STATUS, &phy_1000t_status);
-	e1e_rphy(hw, PHY_EXT_STATUS, &phy_ext_status);
-
-	pci_read_config_word(adapter->pdev, PCI_STATUS, &pci_status);
-
-	/* detected Hardware unit hang */
-	e_err("Detected Hardware 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"
-	      "MAC Status             <%x>\n"
-	      "PHY Status             <%x>\n"
-	      "PHY 1000BASE-T Status  <%x>\n"
-	      "PHY Extended Status    <%x>\n"
-	      "PCI 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->upper.fields.status,
-	      er32(STATUS),
-	      phy_status,
-	      phy_1000t_status,
-	      phy_ext_status,
-	      pci_status);
-}
-
-/**
- * e1000_clean_tx_irq - Reclaim resources after transmit completes
- * @adapter: board private structure
- *
- * the return value indicates whether actual cleaning was done, there
- * is no guarantee that everything was cleaned
- **/
-static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_ring *tx_ring = adapter->tx_ring;
-	struct e1000_tx_desc *tx_desc, *eop_desc;
-	struct e1000_buffer *buffer_info;
-	unsigned int i, eop;
-	unsigned int count = 0;
-	unsigned int total_tx_bytes = 0, total_tx_packets = 0;
-
-	i = tx_ring->next_to_clean;
-	eop = tx_ring->buffer_info[i].next_to_watch;
-	eop_desc = E1000_TX_DESC(*tx_ring, eop);
-
-	while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
-	       (count < tx_ring->count)) {
-		bool cleaned = false;
-		rmb(); /* read buffer_info after eop_desc */
-		for (; !cleaned; count++) {
-			tx_desc = E1000_TX_DESC(*tx_ring, i);
-			buffer_info = &tx_ring->buffer_info[i];
-			cleaned = (i == eop);
-
-			if (cleaned) {
-				total_tx_packets += buffer_info->segs;
-				total_tx_bytes += buffer_info->bytecount;
-			}
-
-			e1000_put_txbuf(adapter, buffer_info);
-			tx_desc->upper.data = 0;
-
-			i++;
-			if (i == tx_ring->count)
-				i = 0;
-		}
-
-		if (i == tx_ring->next_to_use)
-			break;
-		eop = tx_ring->buffer_info[i].next_to_watch;
-		eop_desc = E1000_TX_DESC(*tx_ring, eop);
-	}
-
-	tx_ring->next_to_clean = i;
-
-#define TX_WAKE_THRESHOLD 32
-	if (count && netif_carrier_ok(netdev) &&
-	    e1000_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD) {
-		/* Make sure that anybody stopping the queue after this
-		 * sees the new next_to_clean.
-		 */
-		smp_mb();
-
-		if (netif_queue_stopped(netdev) &&
-		    !(test_bit(__E1000_DOWN, &adapter->state))) {
-			netif_wake_queue(netdev);
-			++adapter->restart_queue;
-		}
-	}
-
-	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 = 0;
-		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)) {
-			schedule_work(&adapter->print_hang_task);
-			netif_stop_queue(netdev);
-		}
-	}
-	adapter->total_tx_bytes += total_tx_bytes;
-	adapter->total_tx_packets += total_tx_packets;
-	return count < tx_ring->count;
-}
-
-/**
- * e1000_clean_rx_irq_ps - Send received data up the network stack; packet split
- * @adapter: board private structure
- *
- * the return value indicates whether actual cleaning was done, there
- * is no guarantee that everything was cleaned
- **/
-static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
-				  int *work_done, int work_to_do)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	union e1000_rx_desc_packet_split *rx_desc, *next_rxd;
-	struct net_device *netdev = adapter->netdev;
-	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_ring *rx_ring = adapter->rx_ring;
-	struct e1000_buffer *buffer_info, *next_buffer;
-	struct e1000_ps_page *ps_page;
-	struct sk_buff *skb;
-	unsigned int i, j;
-	u32 length, staterr;
-	int cleaned_count = 0;
-	bool cleaned = 0;
-	unsigned int total_rx_bytes = 0, total_rx_packets = 0;
-
-	i = rx_ring->next_to_clean;
-	rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
-	staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
-	buffer_info = &rx_ring->buffer_info[i];
-
-	while (staterr & E1000_RXD_STAT_DD) {
-		if (*work_done >= work_to_do)
-			break;
-		(*work_done)++;
-		skb = buffer_info->skb;
-		rmb();	/* read descriptor and rx_buffer_info after status DD */
-
-		/* in the packet split case this is header only */
-		prefetch(skb->data - NET_IP_ALIGN);
-
-		i++;
-		if (i == rx_ring->count)
-			i = 0;
-		next_rxd = E1000_RX_DESC_PS(*rx_ring, i);
-		prefetch(next_rxd);
-
-		next_buffer = &rx_ring->buffer_info[i];
-
-		cleaned = 1;
-		cleaned_count++;
-		dma_unmap_single(&pdev->dev, buffer_info->dma,
-				 adapter->rx_ps_bsize0, DMA_FROM_DEVICE);
-		buffer_info->dma = 0;
-
-		/* see !EOP comment in other Rx routine */
-		if (!(staterr & E1000_RXD_STAT_EOP))
-			adapter->flags2 |= FLAG2_IS_DISCARDING;
-
-		if (adapter->flags2 & FLAG2_IS_DISCARDING) {
-			e_dbg("Packet Split buffers didn't pick up the full "
-			      "packet\n");
-			dev_kfree_skb_irq(skb);
-			if (staterr & E1000_RXD_STAT_EOP)
-				adapter->flags2 &= ~FLAG2_IS_DISCARDING;
-			goto next_desc;
-		}
-
-		if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) {
-			dev_kfree_skb_irq(skb);
-			goto next_desc;
-		}
-
-		length = le16_to_cpu(rx_desc->wb.middle.length0);
-
-		if (!length) {
-			e_dbg("Last part of the packet spanning multiple "
-			      "descriptors\n");
-			dev_kfree_skb_irq(skb);
-			goto next_desc;
-		}
-
-		/* Good Receive */
-		skb_put(skb, length);
-
-		{
-		/*
-		 * this looks ugly, but it seems compiler issues make it
-		 * more efficient than reusing j
-		 */
-		int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]);
-
-		/*
-		 * page alloc/put takes too long and effects small packet
-		 * throughput, so unsplit small packets and save the alloc/put
-		 * only valid in softirq (napi) context to call kmap_*
-		 */
-		if (l1 && (l1 <= copybreak) &&
-		    ((length + l1) <= adapter->rx_ps_bsize0)) {
-			u8 *vaddr;
-
-			ps_page = &buffer_info->ps_pages[0];
-
-			/*
-			 * there is no documentation about how to call
-			 * kmap_atomic, so we can't hold the mapping
-			 * very long
-			 */
-			dma_sync_single_for_cpu(&pdev->dev, ps_page->dma,
-						PAGE_SIZE, DMA_FROM_DEVICE);
-			vaddr = kmap_atomic(ps_page->page, KM_SKB_DATA_SOFTIRQ);
-			memcpy(skb_tail_pointer(skb), vaddr, l1);
-			kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ);
-			dma_sync_single_for_device(&pdev->dev, ps_page->dma,
-						   PAGE_SIZE, DMA_FROM_DEVICE);
-
-			/* remove the CRC */
-			if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
-				l1 -= 4;
-
-			skb_put(skb, l1);
-			goto copydone;
-		} /* if */
-		}
-
-		for (j = 0; j < PS_PAGE_BUFFERS; j++) {
-			length = le16_to_cpu(rx_desc->wb.upper.length[j]);
-			if (!length)
-				break;
-
-			ps_page = &buffer_info->ps_pages[j];
-			dma_unmap_page(&pdev->dev, ps_page->dma, PAGE_SIZE,
-				       DMA_FROM_DEVICE);
-			ps_page->dma = 0;
-			skb_fill_page_desc(skb, j, ps_page->page, 0, length);
-			ps_page->page = NULL;
-			skb->len += length;
-			skb->data_len += length;
-			skb->truesize += length;
-		}
-
-		/* strip the ethernet crc, problem is we're using pages now so
-		 * this whole operation can get a little cpu intensive
-		 */
-		if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
-			pskb_trim(skb, skb->len - 4);
-
-copydone:
-		total_rx_bytes += skb->len;
-		total_rx_packets++;
-
-		e1000_rx_checksum(adapter, staterr, le16_to_cpu(
-			rx_desc->wb.lower.hi_dword.csum_ip.csum), skb);
-
-		if (rx_desc->wb.upper.header_status &
-			   cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP))
-			adapter->rx_hdr_split++;
-
-		e1000_receive_skb(adapter, netdev, skb,
-				  staterr, rx_desc->wb.middle.vlan);
-
-next_desc:
-		rx_desc->wb.middle.status_error &= cpu_to_le32(~0xFF);
-		buffer_info->skb = NULL;
-
-		/* return some buffers to hardware, one at a time is too slow */
-		if (cleaned_count >= E1000_RX_BUFFER_WRITE) {
-			adapter->alloc_rx_buf(adapter, cleaned_count,
-					      GFP_ATOMIC);
-			cleaned_count = 0;
-		}
-
-		/* use prefetched values */
-		rx_desc = next_rxd;
-		buffer_info = next_buffer;
-
-		staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
-	}
-	rx_ring->next_to_clean = i;
-
-	cleaned_count = e1000_desc_unused(rx_ring);
-	if (cleaned_count)
-		adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC);
-
-	adapter->total_rx_bytes += total_rx_bytes;
-	adapter->total_rx_packets += total_rx_packets;
-	return cleaned;
-}
-
-/**
- * e1000_consume_page - helper function
- **/
-static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb,
-                               u16 length)
-{
-	bi->page = NULL;
-	skb->len += length;
-	skb->data_len += length;
-	skb->truesize += length;
-}
-
-/**
- * e1000_clean_jumbo_rx_irq - Send received data up the network stack; legacy
- * @adapter: board private structure
- *
- * the return value indicates whether actual cleaning was done, there
- * is no guarantee that everything was cleaned
- **/
-
-static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
-                                     int *work_done, int work_to_do)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_ring *rx_ring = adapter->rx_ring;
-	struct e1000_rx_desc *rx_desc, *next_rxd;
-	struct e1000_buffer *buffer_info, *next_buffer;
-	u32 length;
-	unsigned int i;
-	int cleaned_count = 0;
-	bool cleaned = false;
-	unsigned int total_rx_bytes=0, total_rx_packets=0;
-
-	i = rx_ring->next_to_clean;
-	rx_desc = E1000_RX_DESC(*rx_ring, i);
-	buffer_info = &rx_ring->buffer_info[i];
-
-	while (rx_desc->status & E1000_RXD_STAT_DD) {
-		struct sk_buff *skb;
-		u8 status;
-
-		if (*work_done >= work_to_do)
-			break;
-		(*work_done)++;
-		rmb();	/* read descriptor and rx_buffer_info after status DD */
-
-		status = rx_desc->status;
-		skb = buffer_info->skb;
-		buffer_info->skb = NULL;
-
-		++i;
-		if (i == rx_ring->count)
-			i = 0;
-		next_rxd = E1000_RX_DESC(*rx_ring, i);
-		prefetch(next_rxd);
-
-		next_buffer = &rx_ring->buffer_info[i];
-
-		cleaned = true;
-		cleaned_count++;
-		dma_unmap_page(&pdev->dev, buffer_info->dma, PAGE_SIZE,
-			       DMA_FROM_DEVICE);
-		buffer_info->dma = 0;
-
-		length = le16_to_cpu(rx_desc->length);
-
-		/* errors is only valid for DD + EOP descriptors */
-		if (unlikely((status & E1000_RXD_STAT_EOP) &&
-		    (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK))) {
-				/* recycle both page and skb */
-				buffer_info->skb = skb;
-				/* an error means any chain goes out the window
-				 * too */
-				if (rx_ring->rx_skb_top)
-					dev_kfree_skb_irq(rx_ring->rx_skb_top);
-				rx_ring->rx_skb_top = NULL;
-				goto next_desc;
-		}
-
-#define rxtop (rx_ring->rx_skb_top)
-		if (!(status & E1000_RXD_STAT_EOP)) {
-			/* this descriptor is only the beginning (or middle) */
-			if (!rxtop) {
-				/* this is the beginning of a chain */
-				rxtop = skb;
-				skb_fill_page_desc(rxtop, 0, buffer_info->page,
-				                   0, length);
-			} else {
-				/* this is the middle of a chain */
-				skb_fill_page_desc(rxtop,
-				    skb_shinfo(rxtop)->nr_frags,
-				    buffer_info->page, 0, length);
-				/* re-use the skb, only consumed the page */
-				buffer_info->skb = skb;
-			}
-			e1000_consume_page(buffer_info, rxtop, length);
-			goto next_desc;
-		} else {
-			if (rxtop) {
-				/* end of the chain */
-				skb_fill_page_desc(rxtop,
-				    skb_shinfo(rxtop)->nr_frags,
-				    buffer_info->page, 0, length);
-				/* re-use the current skb, we only consumed the
-				 * page */
-				buffer_info->skb = skb;
-				skb = rxtop;
-				rxtop = NULL;
-				e1000_consume_page(buffer_info, skb, length);
-			} else {
-				/* no chain, got EOP, this buf is the packet
-				 * copybreak to save the put_page/alloc_page */
-				if (length <= copybreak &&
-				    skb_tailroom(skb) >= length) {
-					u8 *vaddr;
-					vaddr = kmap_atomic(buffer_info->page,
-					                   KM_SKB_DATA_SOFTIRQ);
-					memcpy(skb_tail_pointer(skb), vaddr,
-					       length);
-					kunmap_atomic(vaddr,
-					              KM_SKB_DATA_SOFTIRQ);
-					/* re-use the page, so don't erase
-					 * buffer_info->page */
-					skb_put(skb, length);
-				} else {
-					skb_fill_page_desc(skb, 0,
-					                   buffer_info->page, 0,
-				                           length);
-					e1000_consume_page(buffer_info, skb,
-					                   length);
-				}
-			}
-		}
-
-		/* Receive Checksum Offload XXX recompute due to CRC strip? */
-		e1000_rx_checksum(adapter,
-		                  (u32)(status) |
-		                  ((u32)(rx_desc->errors) << 24),
-		                  le16_to_cpu(rx_desc->csum), skb);
-
-		/* probably a little skewed due to removing CRC */
-		total_rx_bytes += skb->len;
-		total_rx_packets++;
-
-		/* 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_irq(skb);
-			goto next_desc;
-		}
-
-		e1000_receive_skb(adapter, netdev, skb, status,
-		                  rx_desc->special);
-
-next_desc:
-		rx_desc->status = 0;
-
-		/* return some buffers to hardware, one at a time is too slow */
-		if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
-			adapter->alloc_rx_buf(adapter, cleaned_count,
-					      GFP_ATOMIC);
-			cleaned_count = 0;
-		}
-
-		/* use prefetched values */
-		rx_desc = next_rxd;
-		buffer_info = next_buffer;
-	}
-	rx_ring->next_to_clean = i;
-
-	cleaned_count = e1000_desc_unused(rx_ring);
-	if (cleaned_count)
-		adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC);
-
-	adapter->total_rx_bytes += total_rx_bytes;
-	adapter->total_rx_packets += total_rx_packets;
-	return cleaned;
-}
-
-/**
- * e1000_clean_rx_ring - Free Rx Buffers per Queue
- * @adapter: board private structure
- **/
-static void e1000_clean_rx_ring(struct e1000_adapter *adapter)
-{
-	struct e1000_ring *rx_ring = adapter->rx_ring;
-	struct e1000_buffer *buffer_info;
-	struct e1000_ps_page *ps_page;
-	struct pci_dev *pdev = adapter->pdev;
-	unsigned int i, j;
-
-	/* Free all the Rx ring sk_buffs */
-	for (i = 0; i < rx_ring->count; i++) {
-		buffer_info = &rx_ring->buffer_info[i];
-		if (buffer_info->dma) {
-			if (adapter->clean_rx == e1000_clean_rx_irq)
-				dma_unmap_single(&pdev->dev, buffer_info->dma,
-						 adapter->rx_buffer_len,
-						 DMA_FROM_DEVICE);
-			else if (adapter->clean_rx == e1000_clean_jumbo_rx_irq)
-				dma_unmap_page(&pdev->dev, buffer_info->dma,
-				               PAGE_SIZE,
-					       DMA_FROM_DEVICE);
-			else if (adapter->clean_rx == e1000_clean_rx_irq_ps)
-				dma_unmap_single(&pdev->dev, buffer_info->dma,
-						 adapter->rx_ps_bsize0,
-						 DMA_FROM_DEVICE);
-			buffer_info->dma = 0;
-		}
-
-		if (buffer_info->page) {
-			put_page(buffer_info->page);
-			buffer_info->page = NULL;
-		}
-
-		if (buffer_info->skb) {
-			dev_kfree_skb(buffer_info->skb);
-			buffer_info->skb = NULL;
-		}
-
-		for (j = 0; j < PS_PAGE_BUFFERS; j++) {
-			ps_page = &buffer_info->ps_pages[j];
-			if (!ps_page->page)
-				break;
-			dma_unmap_page(&pdev->dev, ps_page->dma, PAGE_SIZE,
-				       DMA_FROM_DEVICE);
-			ps_page->dma = 0;
-			put_page(ps_page->page);
-			ps_page->page = NULL;
-		}
-	}
-
-	/* there also may be some cached data from a chained receive */
-	if (rx_ring->rx_skb_top) {
-		dev_kfree_skb(rx_ring->rx_skb_top);
-		rx_ring->rx_skb_top = NULL;
-	}
-
-	/* Zero out the descriptor ring */
-	memset(rx_ring->desc, 0, rx_ring->size);
-
-	rx_ring->next_to_clean = 0;
-	rx_ring->next_to_use = 0;
-	adapter->flags2 &= ~FLAG2_IS_DISCARDING;
-
-	writel(0, adapter->hw.hw_addr + rx_ring->head);
-	writel(0, adapter->hw.hw_addr + rx_ring->tail);
-}
-
-static void e1000e_downshift_workaround(struct work_struct *work)
-{
-	struct e1000_adapter *adapter = container_of(work,
-					struct e1000_adapter, downshift_task);
-
-	if (test_bit(__E1000_DOWN, &adapter->state))
-		return;
-
-	e1000e_gig_downshift_workaround_ich8lan(&adapter->hw);
-}
-
-/**
- * e1000_intr_msi - Interrupt Handler
- * @irq: interrupt number
- * @data: pointer to a network interface device structure
- **/
-static irqreturn_t e1000_intr_msi(int irq, void *data)
-{
-	struct net_device *netdev = data;
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u32 icr = er32(ICR);
-
-	/*
-	 * read ICR disables interrupts using IAM
-	 */
-
-	if (icr & E1000_ICR_LSC) {
-		hw->mac.get_link_status = 1;
-		/*
-		 * ICH8 workaround-- Call gig speed drop workaround on cable
-		 * disconnect (LSC) before accessing any PHY registers
-		 */
-		if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
-		    (!(er32(STATUS) & E1000_STATUS_LU)))
-			schedule_work(&adapter->downshift_task);
-
-		/*
-		 * 80003ES2LAN workaround-- For packet buffer work-around on
-		 * link down event; disable receives here in the ISR and reset
-		 * adapter in watchdog
-		 */
-		if (netif_carrier_ok(netdev) &&
-		    adapter->flags & FLAG_RX_NEEDS_RESTART) {
-			/* disable receives */
-			u32 rctl = er32(RCTL);
-			ew32(RCTL, rctl & ~E1000_RCTL_EN);
-			adapter->flags |= FLAG_RX_RESTART_NOW;
-		}
-		/* guard against interrupt when we're going down */
-		if (!test_bit(__E1000_DOWN, &adapter->state))
-			mod_timer(&adapter->watchdog_timer, jiffies + 1);
-	}
-
-	if (napi_schedule_prep(&adapter->napi)) {
-		adapter->total_tx_bytes = 0;
-		adapter->total_tx_packets = 0;
-		adapter->total_rx_bytes = 0;
-		adapter->total_rx_packets = 0;
-		__napi_schedule(&adapter->napi);
-	}
-
-	return IRQ_HANDLED;
-}
-
-/**
- * e1000_intr - Interrupt Handler
- * @irq: interrupt number
- * @data: pointer to a network interface device structure
- **/
-static irqreturn_t e1000_intr(int irq, void *data)
-{
-	struct net_device *netdev = data;
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u32 rctl, icr = er32(ICR);
-
-	if (!icr || test_bit(__E1000_DOWN, &adapter->state))
-		return IRQ_NONE;  /* Not our interrupt */
-
-	/*
-	 * IMS will not auto-mask if INT_ASSERTED is not set, and if it is
-	 * not set, then the adapter didn't send an interrupt
-	 */
-	if (!(icr & E1000_ICR_INT_ASSERTED))
-		return IRQ_NONE;
-
-	/*
-	 * Interrupt Auto-Mask...upon reading ICR,
-	 * interrupts are masked.  No need for the
-	 * IMC write
-	 */
-
-	if (icr & E1000_ICR_LSC) {
-		hw->mac.get_link_status = 1;
-		/*
-		 * ICH8 workaround-- Call gig speed drop workaround on cable
-		 * disconnect (LSC) before accessing any PHY registers
-		 */
-		if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
-		    (!(er32(STATUS) & E1000_STATUS_LU)))
-			schedule_work(&adapter->downshift_task);
-
-		/*
-		 * 80003ES2LAN workaround--
-		 * For packet buffer work-around on link down event;
-		 * disable receives here in the ISR and
-		 * reset adapter in watchdog
-		 */
-		if (netif_carrier_ok(netdev) &&
-		    (adapter->flags & FLAG_RX_NEEDS_RESTART)) {
-			/* disable receives */
-			rctl = er32(RCTL);
-			ew32(RCTL, rctl & ~E1000_RCTL_EN);
-			adapter->flags |= FLAG_RX_RESTART_NOW;
-		}
-		/* guard against interrupt when we're going down */
-		if (!test_bit(__E1000_DOWN, &adapter->state))
-			mod_timer(&adapter->watchdog_timer, jiffies + 1);
-	}
-
-	if (napi_schedule_prep(&adapter->napi)) {
-		adapter->total_tx_bytes = 0;
-		adapter->total_tx_packets = 0;
-		adapter->total_rx_bytes = 0;
-		adapter->total_rx_packets = 0;
-		__napi_schedule(&adapter->napi);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t e1000_msix_other(int irq, void *data)
-{
-	struct net_device *netdev = data;
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u32 icr = er32(ICR);
-
-	if (!(icr & E1000_ICR_INT_ASSERTED)) {
-		if (!test_bit(__E1000_DOWN, &adapter->state))
-			ew32(IMS, E1000_IMS_OTHER);
-		return IRQ_NONE;
-	}
-
-	if (icr & adapter->eiac_mask)
-		ew32(ICS, (icr & adapter->eiac_mask));
-
-	if (icr & E1000_ICR_OTHER) {
-		if (!(icr & E1000_ICR_LSC))
-			goto no_link_interrupt;
-		hw->mac.get_link_status = 1;
-		/* guard against interrupt when we're going down */
-		if (!test_bit(__E1000_DOWN, &adapter->state))
-			mod_timer(&adapter->watchdog_timer, jiffies + 1);
-	}
-
-no_link_interrupt:
-	if (!test_bit(__E1000_DOWN, &adapter->state))
-		ew32(IMS, E1000_IMS_LSC | E1000_IMS_OTHER);
-
-	return IRQ_HANDLED;
-}
-
-
-static irqreturn_t e1000_intr_msix_tx(int irq, void *data)
-{
-	struct net_device *netdev = data;
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_ring *tx_ring = adapter->tx_ring;
-
-
-	adapter->total_tx_bytes = 0;
-	adapter->total_tx_packets = 0;
-
-	if (!e1000_clean_tx_irq(adapter))
-		/* Ring was not completely cleaned, so fire another interrupt */
-		ew32(ICS, tx_ring->ims_val);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t e1000_intr_msix_rx(int irq, void *data)
-{
-	struct net_device *netdev = data;
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	/* Write the ITR value calculated at the end of the
-	 * previous interrupt.
-	 */
-	if (adapter->rx_ring->set_itr) {
-		writel(1000000000 / (adapter->rx_ring->itr_val * 256),
-		       adapter->hw.hw_addr + adapter->rx_ring->itr_register);
-		adapter->rx_ring->set_itr = 0;
-	}
-
-	if (napi_schedule_prep(&adapter->napi)) {
-		adapter->total_rx_bytes = 0;
-		adapter->total_rx_packets = 0;
-		__napi_schedule(&adapter->napi);
-	}
-	return IRQ_HANDLED;
-}
-
-/**
- * e1000_configure_msix - Configure MSI-X hardware
- *
- * e1000_configure_msix sets up the hardware to properly
- * generate MSI-X interrupts.
- **/
-static void e1000_configure_msix(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_ring *rx_ring = adapter->rx_ring;
-	struct e1000_ring *tx_ring = adapter->tx_ring;
-	int vector = 0;
-	u32 ctrl_ext, ivar = 0;
-
-	adapter->eiac_mask = 0;
-
-	/* Workaround issue with spurious interrupts on 82574 in MSI-X mode */
-	if (hw->mac.type == e1000_82574) {
-		u32 rfctl = er32(RFCTL);
-		rfctl |= E1000_RFCTL_ACK_DIS;
-		ew32(RFCTL, rfctl);
-	}
-
-#define E1000_IVAR_INT_ALLOC_VALID	0x8
-	/* Configure Rx vector */
-	rx_ring->ims_val = E1000_IMS_RXQ0;
-	adapter->eiac_mask |= rx_ring->ims_val;
-	if (rx_ring->itr_val)
-		writel(1000000000 / (rx_ring->itr_val * 256),
-		       hw->hw_addr + rx_ring->itr_register);
-	else
-		writel(1, hw->hw_addr + rx_ring->itr_register);
-	ivar = E1000_IVAR_INT_ALLOC_VALID | vector;
-
-	/* Configure Tx vector */
-	tx_ring->ims_val = E1000_IMS_TXQ0;
-	vector++;
-	if (tx_ring->itr_val)
-		writel(1000000000 / (tx_ring->itr_val * 256),
-		       hw->hw_addr + tx_ring->itr_register);
-	else
-		writel(1, hw->hw_addr + tx_ring->itr_register);
-	adapter->eiac_mask |= tx_ring->ims_val;
-	ivar |= ((E1000_IVAR_INT_ALLOC_VALID | vector) << 8);
-
-	/* set vector for Other Causes, e.g. link changes */
-	vector++;
-	ivar |= ((E1000_IVAR_INT_ALLOC_VALID | vector) << 16);
-	if (rx_ring->itr_val)
-		writel(1000000000 / (rx_ring->itr_val * 256),
-		       hw->hw_addr + E1000_EITR_82574(vector));
-	else
-		writel(1, hw->hw_addr + E1000_EITR_82574(vector));
-
-	/* Cause Tx interrupts on every write back */
-	ivar |= (1 << 31);
-
-	ew32(IVAR, ivar);
-
-	/* enable MSI-X PBA support */
-	ctrl_ext = er32(CTRL_EXT);
-	ctrl_ext |= E1000_CTRL_EXT_PBA_CLR;
-
-	/* Auto-Mask Other interrupts upon ICR read */
-#define E1000_EIAC_MASK_82574   0x01F00000
-	ew32(IAM, ~E1000_EIAC_MASK_82574 | E1000_IMS_OTHER);
-	ctrl_ext |= E1000_CTRL_EXT_EIAME;
-	ew32(CTRL_EXT, ctrl_ext);
-	e1e_flush();
-}
-
-void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter)
-{
-	if (adapter->msix_entries) {
-		pci_disable_msix(adapter->pdev);
-		kfree(adapter->msix_entries);
-		adapter->msix_entries = NULL;
-	} else if (adapter->flags & FLAG_MSI_ENABLED) {
-		pci_disable_msi(adapter->pdev);
-		adapter->flags &= ~FLAG_MSI_ENABLED;
-	}
-}
-
-/**
- * e1000e_set_interrupt_capability - set MSI or MSI-X if supported
- *
- * Attempt to configure interrupts using the best available
- * capabilities of the hardware and kernel.
- **/
-void e1000e_set_interrupt_capability(struct e1000_adapter *adapter)
-{
-	int err;
-	int i;
-
-	switch (adapter->int_mode) {
-	case E1000E_INT_MODE_MSIX:
-		if (adapter->flags & FLAG_HAS_MSIX) {
-			adapter->num_vectors = 3; /* RxQ0, TxQ0 and other */
-			adapter->msix_entries = kcalloc(adapter->num_vectors,
-						      sizeof(struct msix_entry),
-						      GFP_KERNEL);
-			if (adapter->msix_entries) {
-				for (i = 0; i < adapter->num_vectors; i++)
-					adapter->msix_entries[i].entry = i;
-
-				err = pci_enable_msix(adapter->pdev,
-						      adapter->msix_entries,
-						      adapter->num_vectors);
-				if (err == 0)
-					return;
-			}
-			/* MSI-X failed, so fall through and try MSI */
-			e_err("Failed to initialize MSI-X interrupts.  "
-			      "Falling back to MSI interrupts.\n");
-			e1000e_reset_interrupt_capability(adapter);
-		}
-		adapter->int_mode = E1000E_INT_MODE_MSI;
-		/* Fall through */
-	case E1000E_INT_MODE_MSI:
-		if (!pci_enable_msi(adapter->pdev)) {
-			adapter->flags |= FLAG_MSI_ENABLED;
-		} else {
-			adapter->int_mode = E1000E_INT_MODE_LEGACY;
-			e_err("Failed to initialize MSI interrupts.  Falling "
-			      "back to legacy interrupts.\n");
-		}
-		/* Fall through */
-	case E1000E_INT_MODE_LEGACY:
-		/* Don't do anything; this is the system default */
-		break;
-	}
-
-	/* store the number of vectors being used */
-	adapter->num_vectors = 1;
-}
-
-/**
- * e1000_request_msix - Initialize MSI-X interrupts
- *
- * e1000_request_msix allocates MSI-X vectors and requests interrupts from the
- * kernel.
- **/
-static int e1000_request_msix(struct e1000_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	int err = 0, vector = 0;
-
-	if (strlen(netdev->name) < (IFNAMSIZ - 5))
-		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,
-			  e1000_intr_msix_rx, 0, adapter->rx_ring->name,
-			  netdev);
-	if (err)
-		goto out;
-	adapter->rx_ring->itr_register = E1000_EITR_82574(vector);
-	adapter->rx_ring->itr_val = adapter->itr;
-	vector++;
-
-	if (strlen(netdev->name) < (IFNAMSIZ - 5))
-		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,
-			  e1000_intr_msix_tx, 0, adapter->tx_ring->name,
-			  netdev);
-	if (err)
-		goto out;
-	adapter->tx_ring->itr_register = E1000_EITR_82574(vector);
-	adapter->tx_ring->itr_val = adapter->itr;
-	vector++;
-
-	err = request_irq(adapter->msix_entries[vector].vector,
-			  e1000_msix_other, 0, netdev->name, netdev);
-	if (err)
-		goto out;
-
-	e1000_configure_msix(adapter);
-	return 0;
-out:
-	return err;
-}
-
-/**
- * e1000_request_irq - initialize interrupts
- *
- * Attempts to configure interrupts using the best available
- * capabilities of the hardware and kernel.
- **/
-static int e1000_request_irq(struct e1000_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	int err;
-
-	if (adapter->msix_entries) {
-		err = e1000_request_msix(adapter);
-		if (!err)
-			return err;
-		/* fall back to MSI */
-		e1000e_reset_interrupt_capability(adapter);
-		adapter->int_mode = E1000E_INT_MODE_MSI;
-		e1000e_set_interrupt_capability(adapter);
-	}
-	if (adapter->flags & FLAG_MSI_ENABLED) {
-		err = request_irq(adapter->pdev->irq, e1000_intr_msi, 0,
-				  netdev->name, netdev);
-		if (!err)
-			return err;
-
-		/* fall back to legacy interrupt */
-		e1000e_reset_interrupt_capability(adapter);
-		adapter->int_mode = E1000E_INT_MODE_LEGACY;
-	}
-
-	err = request_irq(adapter->pdev->irq, e1000_intr, IRQF_SHARED,
-			  netdev->name, netdev);
-	if (err)
-		e_err("Unable to allocate interrupt, Error: %d\n", err);
-
-	return err;
-}
-
-static void e1000_free_irq(struct e1000_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-
-	if (adapter->msix_entries) {
-		int vector = 0;
-
-		free_irq(adapter->msix_entries[vector].vector, netdev);
-		vector++;
-
-		free_irq(adapter->msix_entries[vector].vector, netdev);
-		vector++;
-
-		/* Other Causes interrupt vector */
-		free_irq(adapter->msix_entries[vector].vector, netdev);
-		return;
-	}
-
-	free_irq(adapter->pdev->irq, netdev);
-}
-
-/**
- * e1000_irq_disable - Mask off interrupt generation on the NIC
- **/
-static void e1000_irq_disable(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-
-	ew32(IMC, ~0);
-	if (adapter->msix_entries)
-		ew32(EIAC_82574, 0);
-	e1e_flush();
-
-	if (adapter->msix_entries) {
-		int i;
-		for (i = 0; i < adapter->num_vectors; i++)
-			synchronize_irq(adapter->msix_entries[i].vector);
-	} else {
-		synchronize_irq(adapter->pdev->irq);
-	}
-}
-
-/**
- * e1000_irq_enable - Enable default interrupt generation settings
- **/
-static void e1000_irq_enable(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-
-	if (adapter->msix_entries) {
-		ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574);
-		ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC);
-	} else {
-		ew32(IMS, IMS_ENABLE_MASK);
-	}
-	e1e_flush();
-}
-
-/**
- * e1000e_get_hw_control - get control of the h/w from f/w
- * @adapter: address of board private structure
- *
- * e1000e_get_hw_control sets {CTRL_EXT|SWSM}:DRV_LOAD bit.
- * For ASF and Pass Through versions of f/w this means that
- * the driver is loaded. For AMT version (only with 82573)
- * of the f/w this means that the network i/f is open.
- **/
-void e1000e_get_hw_control(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 ctrl_ext;
-	u32 swsm;
-
-	/* Let firmware know the driver has taken over */
-	if (adapter->flags & FLAG_HAS_SWSM_ON_LOAD) {
-		swsm = er32(SWSM);
-		ew32(SWSM, swsm | E1000_SWSM_DRV_LOAD);
-	} else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) {
-		ctrl_ext = er32(CTRL_EXT);
-		ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
-	}
-}
-
-/**
- * e1000e_release_hw_control - release control of the h/w to f/w
- * @adapter: address of board private structure
- *
- * e1000e_release_hw_control resets {CTRL_EXT|SWSM}:DRV_LOAD bit.
- * For ASF and Pass Through versions of f/w this means that the
- * driver is no longer loaded. For AMT version (only with 82573) i
- * of the f/w this means that the network i/f is closed.
- *
- **/
-void e1000e_release_hw_control(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 ctrl_ext;
-	u32 swsm;
-
-	/* Let firmware taken over control of h/w */
-	if (adapter->flags & FLAG_HAS_SWSM_ON_LOAD) {
-		swsm = er32(SWSM);
-		ew32(SWSM, swsm & ~E1000_SWSM_DRV_LOAD);
-	} else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) {
-		ctrl_ext = er32(CTRL_EXT);
-		ew32(CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
-	}
-}
-
-/**
- * @e1000_alloc_ring - allocate memory for a ring structure
- **/
-static int e1000_alloc_ring_dma(struct e1000_adapter *adapter,
-				struct e1000_ring *ring)
-{
-	struct pci_dev *pdev = adapter->pdev;
-
-	ring->desc = dma_alloc_coherent(&pdev->dev, ring->size, &ring->dma,
-					GFP_KERNEL);
-	if (!ring->desc)
-		return -ENOMEM;
-
-	return 0;
-}
-
-/**
- * e1000e_setup_tx_resources - allocate Tx resources (Descriptors)
- * @adapter: board private structure
- *
- * Return 0 on success, negative on failure
- **/
-int e1000e_setup_tx_resources(struct e1000_adapter *adapter)
-{
-	struct e1000_ring *tx_ring = adapter->tx_ring;
-	int err = -ENOMEM, size;
-
-	size = sizeof(struct e1000_buffer) * tx_ring->count;
-	tx_ring->buffer_info = vzalloc(size);
-	if (!tx_ring->buffer_info)
-		goto err;
-
-	/* round up to nearest 4K */
-	tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc);
-	tx_ring->size = ALIGN(tx_ring->size, 4096);
-
-	err = e1000_alloc_ring_dma(adapter, tx_ring);
-	if (err)
-		goto err;
-
-	tx_ring->next_to_use = 0;
-	tx_ring->next_to_clean = 0;
-
-	return 0;
-err:
-	vfree(tx_ring->buffer_info);
-	e_err("Unable to allocate memory for the transmit descriptor ring\n");
-	return err;
-}
-
-/**
- * e1000e_setup_rx_resources - allocate Rx resources (Descriptors)
- * @adapter: board private structure
- *
- * Returns 0 on success, negative on failure
- **/
-int e1000e_setup_rx_resources(struct e1000_adapter *adapter)
-{
-	struct e1000_ring *rx_ring = adapter->rx_ring;
-	struct e1000_buffer *buffer_info;
-	int i, size, desc_len, err = -ENOMEM;
-
-	size = sizeof(struct e1000_buffer) * rx_ring->count;
-	rx_ring->buffer_info = vzalloc(size);
-	if (!rx_ring->buffer_info)
-		goto err;
-
-	for (i = 0; i < rx_ring->count; i++) {
-		buffer_info = &rx_ring->buffer_info[i];
-		buffer_info->ps_pages = kcalloc(PS_PAGE_BUFFERS,
-						sizeof(struct e1000_ps_page),
-						GFP_KERNEL);
-		if (!buffer_info->ps_pages)
-			goto err_pages;
-	}
-
-	desc_len = sizeof(union e1000_rx_desc_packet_split);
-
-	/* Round up to nearest 4K */
-	rx_ring->size = rx_ring->count * desc_len;
-	rx_ring->size = ALIGN(rx_ring->size, 4096);
-
-	err = e1000_alloc_ring_dma(adapter, rx_ring);
-	if (err)
-		goto err_pages;
-
-	rx_ring->next_to_clean = 0;
-	rx_ring->next_to_use = 0;
-	rx_ring->rx_skb_top = NULL;
-
-	return 0;
-
-err_pages:
-	for (i = 0; i < rx_ring->count; i++) {
-		buffer_info = &rx_ring->buffer_info[i];
-		kfree(buffer_info->ps_pages);
-	}
-err:
-	vfree(rx_ring->buffer_info);
-	e_err("Unable to allocate memory for the receive descriptor ring\n");
-	return err;
-}
-
-/**
- * e1000_clean_tx_ring - Free Tx Buffers
- * @adapter: board private structure
- **/
-static void e1000_clean_tx_ring(struct e1000_adapter *adapter)
-{
-	struct e1000_ring *tx_ring = adapter->tx_ring;
-	struct e1000_buffer *buffer_info;
-	unsigned long size;
-	unsigned int i;
-
-	for (i = 0; i < tx_ring->count; i++) {
-		buffer_info = &tx_ring->buffer_info[i];
-		e1000_put_txbuf(adapter, buffer_info);
-	}
-
-	size = sizeof(struct e1000_buffer) * tx_ring->count;
-	memset(tx_ring->buffer_info, 0, size);
-
-	memset(tx_ring->desc, 0, tx_ring->size);
-
-	tx_ring->next_to_use = 0;
-	tx_ring->next_to_clean = 0;
-
-	writel(0, adapter->hw.hw_addr + tx_ring->head);
-	writel(0, adapter->hw.hw_addr + tx_ring->tail);
-}
-
-/**
- * e1000e_free_tx_resources - Free Tx Resources per Queue
- * @adapter: board private structure
- *
- * Free all transmit software resources
- **/
-void e1000e_free_tx_resources(struct e1000_adapter *adapter)
-{
-	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_ring *tx_ring = adapter->tx_ring;
-
-	e1000_clean_tx_ring(adapter);
-
-	vfree(tx_ring->buffer_info);
-	tx_ring->buffer_info = NULL;
-
-	dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc,
-			  tx_ring->dma);
-	tx_ring->desc = NULL;
-}
-
-/**
- * e1000e_free_rx_resources - Free Rx Resources
- * @adapter: board private structure
- *
- * Free all receive software resources
- **/
-
-void e1000e_free_rx_resources(struct e1000_adapter *adapter)
-{
-	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_ring *rx_ring = adapter->rx_ring;
-	int i;
-
-	e1000_clean_rx_ring(adapter);
-
-	for (i = 0; i < rx_ring->count; i++)
-		kfree(rx_ring->buffer_info[i].ps_pages);
-
-	vfree(rx_ring->buffer_info);
-	rx_ring->buffer_info = NULL;
-
-	dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc,
-			  rx_ring->dma);
-	rx_ring->desc = NULL;
-}
-
-/**
- * e1000_update_itr - update the dynamic ITR value based on statistics
- * @adapter: pointer to adapter
- * @itr_setting: current adapter->itr
- * @packets: the number of packets during this measurement interval
- * @bytes: the number of bytes during this measurement interval
- *
- *      Stores a new ITR value based on packets and byte
- *      counts during the last interrupt.  The advantage of per interrupt
- *      computation is faster updates and more accurate ITR for the current
- *      traffic pattern.  Constants in this function were computed
- *      based on theoretical maximum wire speed and thresholds were set based
- *      on testing data as well as attempting to minimize response time
- *      while increasing bulk throughput.  This functionality is controlled
- *      by the InterruptThrottleRate module parameter.
- **/
-static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
-				     u16 itr_setting, int packets,
-				     int bytes)
-{
-	unsigned int retval = itr_setting;
-
-	if (packets == 0)
-		goto update_itr_done;
-
-	switch (itr_setting) {
-	case lowest_latency:
-		/* handle TSO and jumbo frames */
-		if (bytes/packets > 8000)
-			retval = bulk_latency;
-		else if ((packets < 5) && (bytes > 512))
-			retval = low_latency;
-		break;
-	case low_latency:  /* 50 usec aka 20000 ints/s */
-		if (bytes > 10000) {
-			/* this if handles the TSO accounting */
-			if (bytes/packets > 8000)
-				retval = bulk_latency;
-			else if ((packets < 10) || ((bytes/packets) > 1200))
-				retval = bulk_latency;
-			else if ((packets > 35))
-				retval = lowest_latency;
-		} else if (bytes/packets > 2000) {
-			retval = bulk_latency;
-		} else if (packets <= 2 && bytes < 512) {
-			retval = lowest_latency;
-		}
-		break;
-	case bulk_latency: /* 250 usec aka 4000 ints/s */
-		if (bytes > 25000) {
-			if (packets > 35)
-				retval = low_latency;
-		} else if (bytes < 6000) {
-			retval = low_latency;
-		}
-		break;
-	}
-
-update_itr_done:
-	return retval;
-}
-
-static void e1000_set_itr(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u16 current_itr;
-	u32 new_itr = adapter->itr;
-
-	/* for non-gigabit speeds, just fix the interrupt rate at 4000 */
-	if (adapter->link_speed != SPEED_1000) {
-		current_itr = 0;
-		new_itr = 4000;
-		goto set_itr_now;
-	}
-
-	if (adapter->flags2 & FLAG2_DISABLE_AIM) {
-		new_itr = 0;
-		goto set_itr_now;
-	}
-
-	adapter->tx_itr = e1000_update_itr(adapter,
-				    adapter->tx_itr,
-				    adapter->total_tx_packets,
-				    adapter->total_tx_bytes);
-	/* conservative mode (itr 3) eliminates the lowest_latency setting */
-	if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency)
-		adapter->tx_itr = low_latency;
-
-	adapter->rx_itr = e1000_update_itr(adapter,
-				    adapter->rx_itr,
-				    adapter->total_rx_packets,
-				    adapter->total_rx_bytes);
-	/* conservative mode (itr 3) eliminates the lowest_latency setting */
-	if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency)
-		adapter->rx_itr = low_latency;
-
-	current_itr = max(adapter->rx_itr, adapter->tx_itr);
-
-	switch (current_itr) {
-	/* counts and packets in update_itr are dependent on these numbers */
-	case lowest_latency:
-		new_itr = 70000;
-		break;
-	case low_latency:
-		new_itr = 20000; /* aka hwitr = ~200 */
-		break;
-	case bulk_latency:
-		new_itr = 4000;
-		break;
-	default:
-		break;
-	}
-
-set_itr_now:
-	if (new_itr != adapter->itr) {
-		/*
-		 * this attempts to bias the interrupt rate towards Bulk
-		 * by adding intermediate steps when interrupt rate is
-		 * increasing
-		 */
-		new_itr = new_itr > adapter->itr ?
-			     min(adapter->itr + (new_itr >> 2), new_itr) :
-			     new_itr;
-		adapter->itr = new_itr;
-		adapter->rx_ring->itr_val = new_itr;
-		if (adapter->msix_entries)
-			adapter->rx_ring->set_itr = 1;
-		else
-			if (new_itr)
-				ew32(ITR, 1000000000 / (new_itr * 256));
-			else
-				ew32(ITR, 0);
-	}
-}
-
-/**
- * e1000_alloc_queues - Allocate memory for all rings
- * @adapter: board private structure to initialize
- **/
-static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
-{
-	adapter->tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
-	if (!adapter->tx_ring)
-		goto err;
-
-	adapter->rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
-	if (!adapter->rx_ring)
-		goto err;
-
-	return 0;
-err:
-	e_err("Unable to allocate memory for queues\n");
-	kfree(adapter->rx_ring);
-	kfree(adapter->tx_ring);
-	return -ENOMEM;
-}
-
-/**
- * e1000_clean - NAPI Rx polling callback
- * @napi: struct associated with this polling callback
- * @budget: amount of packets driver is allowed to process this poll
- **/
-static int e1000_clean(struct napi_struct *napi, int budget)
-{
-	struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi);
-	struct e1000_hw *hw = &adapter->hw;
-	struct net_device *poll_dev = adapter->netdev;
-	int tx_cleaned = 1, work_done = 0;
-
-	adapter = netdev_priv(poll_dev);
-
-	if (adapter->msix_entries &&
-	    !(adapter->rx_ring->ims_val & adapter->tx_ring->ims_val))
-		goto clean_rx;
-
-	tx_cleaned = e1000_clean_tx_irq(adapter);
-
-clean_rx:
-	adapter->clean_rx(adapter, &work_done, budget);
-
-	if (!tx_cleaned)
-		work_done = budget;
-
-	/* If budget not fully consumed, exit the polling mode */
-	if (work_done < budget) {
-		if (adapter->itr_setting & 3)
-			e1000_set_itr(adapter);
-		napi_complete(napi);
-		if (!test_bit(__E1000_DOWN, &adapter->state)) {
-			if (adapter->msix_entries)
-				ew32(IMS, adapter->rx_ring->ims_val);
-			else
-				e1000_irq_enable(adapter);
-		}
-	}
-
-	return work_done;
-}
-
-static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u32 vfta, index;
-
-	/* don't update vlan cookie if already programmed */
-	if ((adapter->hw.mng_cookie.status &
-	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&
-	    (vid == adapter->mng_vlan_id))
-		return;
-
-	/* add VID to filter table */
-	if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) {
-		index = (vid >> 5) & 0x7F;
-		vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index);
-		vfta |= (1 << (vid & 0x1F));
-		hw->mac.ops.write_vfta(hw, index, vfta);
-	}
-
-	set_bit(vid, adapter->active_vlans);
-}
-
-static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u32 vfta, index;
-
-	if ((adapter->hw.mng_cookie.status &
-	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&
-	    (vid == adapter->mng_vlan_id)) {
-		/* release control to f/w */
-		e1000e_release_hw_control(adapter);
-		return;
-	}
-
-	/* remove VID from filter table */
-	if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) {
-		index = (vid >> 5) & 0x7F;
-		vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index);
-		vfta &= ~(1 << (vid & 0x1F));
-		hw->mac.ops.write_vfta(hw, index, vfta);
-	}
-
-	clear_bit(vid, adapter->active_vlans);
-}
-
-/**
- * e1000e_vlan_filter_disable - helper to disable hw VLAN filtering
- * @adapter: board private structure to initialize
- **/
-static void e1000e_vlan_filter_disable(struct e1000_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct e1000_hw *hw = &adapter->hw;
-	u32 rctl;
-
-	if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) {
-		/* disable VLAN receive filtering */
-		rctl = er32(RCTL);
-		rctl &= ~(E1000_RCTL_VFE | E1000_RCTL_CFIEN);
-		ew32(RCTL, rctl);
-
-		if (adapter->mng_vlan_id != (u16)E1000_MNG_VLAN_NONE) {
-			e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
-			adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
-		}
-	}
-}
-
-/**
- * e1000e_vlan_filter_enable - helper to enable HW VLAN filtering
- * @adapter: board private structure to initialize
- **/
-static void e1000e_vlan_filter_enable(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 rctl;
-
-	if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) {
-		/* enable VLAN receive filtering */
-		rctl = er32(RCTL);
-		rctl |= E1000_RCTL_VFE;
-		rctl &= ~E1000_RCTL_CFIEN;
-		ew32(RCTL, rctl);
-	}
-}
-
-/**
- * e1000e_vlan_strip_enable - helper to disable HW VLAN stripping
- * @adapter: board private structure to initialize
- **/
-static void e1000e_vlan_strip_disable(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 ctrl;
-
-	/* disable VLAN tag insert/strip */
-	ctrl = er32(CTRL);
-	ctrl &= ~E1000_CTRL_VME;
-	ew32(CTRL, ctrl);
-}
-
-/**
- * e1000e_vlan_strip_enable - helper to enable HW VLAN stripping
- * @adapter: board private structure to initialize
- **/
-static void e1000e_vlan_strip_enable(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 ctrl;
-
-	/* enable VLAN tag insert/strip */
-	ctrl = er32(CTRL);
-	ctrl |= E1000_CTRL_VME;
-	ew32(CTRL, ctrl);
-}
-
-static void e1000_update_mng_vlan(struct e1000_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	u16 vid = adapter->hw.mng_cookie.vlan_id;
-	u16 old_vid = adapter->mng_vlan_id;
-
-	if (adapter->hw.mng_cookie.status &
-	    E1000_MNG_DHCP_COOKIE_STATUS_VLAN) {
-		e1000_vlan_rx_add_vid(netdev, vid);
-		adapter->mng_vlan_id = vid;
-	}
-
-	if ((old_vid != (u16)E1000_MNG_VLAN_NONE) && (vid != old_vid))
-		e1000_vlan_rx_kill_vid(netdev, old_vid);
-}
-
-static void e1000_restore_vlan(struct e1000_adapter *adapter)
-{
-	u16 vid;
-
-	e1000_vlan_rx_add_vid(adapter->netdev, 0);
-
-	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
-		e1000_vlan_rx_add_vid(adapter->netdev, vid);
-}
-
-static void e1000_init_manageability_pt(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 manc, manc2h, mdef, i, j;
-
-	if (!(adapter->flags & FLAG_MNG_PT_ENABLED))
-		return;
-
-	manc = er32(MANC);
-
-	/*
-	 * enable receiving management packets to the host. this will probably
-	 * generate destination unreachable messages from the host OS, but
-	 * the packets will be handled on SMBUS
-	 */
-	manc |= E1000_MANC_EN_MNG2HOST;
-	manc2h = er32(MANC2H);
-
-	switch (hw->mac.type) {
-	default:
-		manc2h |= (E1000_MANC2H_PORT_623 | E1000_MANC2H_PORT_664);
-		break;
-	case e1000_82574:
-	case e1000_82583:
-		/*
-		 * Check if IPMI pass-through decision filter already exists;
-		 * if so, enable it.
-		 */
-		for (i = 0, j = 0; i < 8; i++) {
-			mdef = er32(MDEF(i));
-
-			/* Ignore filters with anything other than IPMI ports */
-			if (mdef & ~(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
-				continue;
-
-			/* Enable this decision filter in MANC2H */
-			if (mdef)
-				manc2h |= (1 << i);
-
-			j |= mdef;
-		}
-
-		if (j == (E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
-			break;
-
-		/* Create new decision filter in an empty filter */
-		for (i = 0, j = 0; i < 8; i++)
-			if (er32(MDEF(i)) == 0) {
-				ew32(MDEF(i), (E1000_MDEF_PORT_623 |
-					       E1000_MDEF_PORT_664));
-				manc2h |= (1 << 1);
-				j++;
-				break;
-			}
-
-		if (!j)
-			e_warn("Unable to create IPMI pass-through filter\n");
-		break;
-	}
-
-	ew32(MANC2H, manc2h);
-	ew32(MANC, manc);
-}
-
-/**
- * e1000_configure_tx - Configure Transmit Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Tx unit of the MAC after a reset.
- **/
-static void e1000_configure_tx(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_ring *tx_ring = adapter->tx_ring;
-	u64 tdba;
-	u32 tdlen, tctl, tipg, tarc;
-	u32 ipgr1, ipgr2;
-
-	/* Setup the HW Tx Head and Tail descriptor pointers */
-	tdba = tx_ring->dma;
-	tdlen = tx_ring->count * sizeof(struct e1000_tx_desc);
-	ew32(TDBAL, (tdba & DMA_BIT_MASK(32)));
-	ew32(TDBAH, (tdba >> 32));
-	ew32(TDLEN, tdlen);
-	ew32(TDH, 0);
-	ew32(TDT, 0);
-	tx_ring->head = E1000_TDH;
-	tx_ring->tail = E1000_TDT;
-
-	/* Set the default values for the Tx Inter Packet Gap timer */
-	tipg = DEFAULT_82543_TIPG_IPGT_COPPER;          /*  8  */
-	ipgr1 = DEFAULT_82543_TIPG_IPGR1;               /*  8  */
-	ipgr2 = DEFAULT_82543_TIPG_IPGR2;               /*  6  */
-
-	if (adapter->flags & FLAG_TIPG_MEDIUM_FOR_80003ESLAN)
-		ipgr2 = DEFAULT_80003ES2LAN_TIPG_IPGR2; /*  7  */
-
-	tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT;
-	tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT;
-	ew32(TIPG, tipg);
-
-	/* Set the Tx Interrupt Delay register */
-	ew32(TIDV, adapter->tx_int_delay);
-	/* Tx irq moderation */
-	ew32(TADV, adapter->tx_abs_int_delay);
-
-	if (adapter->flags2 & FLAG2_DMA_BURST) {
-		u32 txdctl = er32(TXDCTL(0));
-		txdctl &= ~(E1000_TXDCTL_PTHRESH | E1000_TXDCTL_HTHRESH |
-			    E1000_TXDCTL_WTHRESH);
-		/*
-		 * set up some performance related parameters to encourage the
-		 * hardware to use the bus more efficiently in bursts, depends
-		 * on the tx_int_delay to be enabled,
-		 * wthresh = 5 ==> burst write a cacheline (64 bytes) at a time
-		 * hthresh = 1 ==> prefetch when one or more available
-		 * pthresh = 0x1f ==> prefetch if internal cache 31 or less
-		 * BEWARE: this seems to work but should be considered first if
-		 * there are Tx hangs or other Tx related bugs
-		 */
-		txdctl |= E1000_TXDCTL_DMA_BURST_ENABLE;
-		ew32(TXDCTL(0), txdctl);
-		/* erratum work around: set txdctl the same for both queues */
-		ew32(TXDCTL(1), txdctl);
-	}
-
-	/* Program the Transmit Control Register */
-	tctl = er32(TCTL);
-	tctl &= ~E1000_TCTL_CT;
-	tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
-		(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
-
-	if (adapter->flags & FLAG_TARC_SPEED_MODE_BIT) {
-		tarc = er32(TARC(0));
-		/*
-		 * set the speed mode bit, we'll clear it if we're not at
-		 * gigabit link later
-		 */
-#define SPEED_MODE_BIT (1 << 21)
-		tarc |= SPEED_MODE_BIT;
-		ew32(TARC(0), tarc);
-	}
-
-	/* errata: program both queues to unweighted RR */
-	if (adapter->flags & FLAG_TARC_SET_BIT_ZERO) {
-		tarc = er32(TARC(0));
-		tarc |= 1;
-		ew32(TARC(0), tarc);
-		tarc = er32(TARC(1));
-		tarc |= 1;
-		ew32(TARC(1), tarc);
-	}
-
-	/* Setup Transmit Descriptor Settings for eop descriptor */
-	adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS;
-
-	/* only set IDE if we are delaying interrupts using the timers */
-	if (adapter->tx_int_delay)
-		adapter->txd_cmd |= E1000_TXD_CMD_IDE;
-
-	/* enable Report Status bit */
-	adapter->txd_cmd |= E1000_TXD_CMD_RS;
-
-	ew32(TCTL, tctl);
-
-	e1000e_config_collision_dist(hw);
-}
-
-/**
- * e1000_setup_rctl - configure the receive control registers
- * @adapter: Board private structure
- **/
-#define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \
-			   (((S) & (PAGE_SIZE - 1)) ? 1 : 0))
-static void e1000_setup_rctl(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 rctl, rfctl;
-	u32 pages = 0;
-
-	/* Workaround Si errata on 82579 - configure jumbo frame flow */
-	if (hw->mac.type == e1000_pch2lan) {
-		s32 ret_val;
-
-		if (adapter->netdev->mtu > ETH_DATA_LEN)
-			ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true);
-		else
-			ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false);
-
-		if (ret_val)
-			e_dbg("failed to enable jumbo frame workaround mode\n");
-	}
-
-	/* Program MC offset vector base */
-	rctl = er32(RCTL);
-	rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
-	rctl |= E1000_RCTL_EN | E1000_RCTL_BAM |
-		E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
-		(adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
-
-	/* Do not Store bad packets */
-	rctl &= ~E1000_RCTL_SBP;
-
-	/* Enable Long Packet receive */
-	if (adapter->netdev->mtu <= ETH_DATA_LEN)
-		rctl &= ~E1000_RCTL_LPE;
-	else
-		rctl |= E1000_RCTL_LPE;
-
-	/* Some systems expect that the CRC is included in SMBUS traffic. The
-	 * hardware strips the CRC before sending to both SMBUS (BMC) and to
-	 * host memory when this is enabled
-	 */
-	if (adapter->flags2 & FLAG2_CRC_STRIPPING)
-		rctl |= E1000_RCTL_SECRC;
-
-	/* Workaround Si errata on 82577 PHY - configure IPG for jumbos */
-	if ((hw->phy.type == e1000_phy_82577) && (rctl & E1000_RCTL_LPE)) {
-		u16 phy_data;
-
-		e1e_rphy(hw, PHY_REG(770, 26), &phy_data);
-		phy_data &= 0xfff8;
-		phy_data |= (1 << 2);
-		e1e_wphy(hw, PHY_REG(770, 26), phy_data);
-
-		e1e_rphy(hw, 22, &phy_data);
-		phy_data &= 0x0fff;
-		phy_data |= (1 << 14);
-		e1e_wphy(hw, 0x10, 0x2823);
-		e1e_wphy(hw, 0x11, 0x0003);
-		e1e_wphy(hw, 22, phy_data);
-	}
-
-	/* Setup buffer sizes */
-	rctl &= ~E1000_RCTL_SZ_4096;
-	rctl |= E1000_RCTL_BSEX;
-	switch (adapter->rx_buffer_len) {
-	case 2048:
-	default:
-		rctl |= E1000_RCTL_SZ_2048;
-		rctl &= ~E1000_RCTL_BSEX;
-		break;
-	case 4096:
-		rctl |= E1000_RCTL_SZ_4096;
-		break;
-	case 8192:
-		rctl |= E1000_RCTL_SZ_8192;
-		break;
-	case 16384:
-		rctl |= E1000_RCTL_SZ_16384;
-		break;
-	}
-
-	/*
-	 * 82571 and greater support packet-split where the protocol
-	 * header is placed in skb->data and the packet data is
-	 * placed in pages hanging off of skb_shinfo(skb)->nr_frags.
-	 * In the case of a non-split, skb->data is linearly filled,
-	 * followed by the page buffers.  Therefore, skb->data is
-	 * sized to hold the largest protocol header.
-	 *
-	 * allocations using alloc_page take too long for regular MTU
-	 * so only enable packet split for jumbo frames
-	 *
-	 * Using pages when the page size is greater than 16k wastes
-	 * a lot of memory, since we allocate 3 pages at all times
-	 * per packet.
-	 */
-	pages = PAGE_USE_COUNT(adapter->netdev->mtu);
-	if (!(adapter->flags & FLAG_HAS_ERT) && (pages <= 3) &&
-	    (PAGE_SIZE <= 16384) && (rctl & E1000_RCTL_LPE))
-		adapter->rx_ps_pages = pages;
-	else
-		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;
-		/*
-		 * disable packet split support for IPv6 extension headers,
-		 * because some malformed IPv6 headers can hang the Rx
-		 */
-		rfctl |= (E1000_RFCTL_IPV6_EX_DIS |
-			  E1000_RFCTL_NEW_IPV6_EXT_DIS);
-
-		ew32(RFCTL, rfctl);
-
-		/* Enable Packet split descriptors */
-		rctl |= E1000_RCTL_DTYP_PS;
-
-		psrctl |= adapter->rx_ps_bsize0 >>
-			E1000_PSRCTL_BSIZE0_SHIFT;
-
-		switch (adapter->rx_ps_pages) {
-		case 3:
-			psrctl |= PAGE_SIZE <<
-				E1000_PSRCTL_BSIZE3_SHIFT;
-		case 2:
-			psrctl |= PAGE_SIZE <<
-				E1000_PSRCTL_BSIZE2_SHIFT;
-		case 1:
-			psrctl |= PAGE_SIZE >>
-				E1000_PSRCTL_BSIZE1_SHIFT;
-			break;
-		}
-
-		ew32(PSRCTL, psrctl);
-	}
-
-	ew32(RCTL, rctl);
-	/* just started the receive unit, no need to restart */
-	adapter->flags &= ~FLAG_RX_RESTART_NOW;
-}
-
-/**
- * e1000_configure_rx - Configure Receive Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Rx unit of the MAC after a reset.
- **/
-static void e1000_configure_rx(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_ring *rx_ring = adapter->rx_ring;
-	u64 rdba;
-	u32 rdlen, rctl, rxcsum, ctrl_ext;
-
-	if (adapter->rx_ps_pages) {
-		/* this is a 32 byte descriptor */
-		rdlen = rx_ring->count *
-		    sizeof(union e1000_rx_desc_packet_split);
-		adapter->clean_rx = e1000_clean_rx_irq_ps;
-		adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps;
-	} else if (adapter->netdev->mtu > ETH_FRAME_LEN + ETH_FCS_LEN) {
-		rdlen = rx_ring->count * sizeof(struct e1000_rx_desc);
-		adapter->clean_rx = e1000_clean_jumbo_rx_irq;
-		adapter->alloc_rx_buf = e1000_alloc_jumbo_rx_buffers;
-	} else {
-		rdlen = rx_ring->count * sizeof(struct e1000_rx_desc);
-		adapter->clean_rx = e1000_clean_rx_irq;
-		adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
-	}
-
-	/* disable receives while setting up the descriptors */
-	rctl = er32(RCTL);
-	if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX))
-		ew32(RCTL, rctl & ~E1000_RCTL_EN);
-	e1e_flush();
-	usleep_range(10000, 20000);
-
-	if (adapter->flags2 & FLAG2_DMA_BURST) {
-		/*
-		 * set the writeback threshold (only takes effect if the RDTR
-		 * is set). set GRAN=1 and write back up to 0x4 worth, and
-		 * enable prefetching of 0x20 Rx descriptors
-		 * granularity = 01
-		 * wthresh = 04,
-		 * hthresh = 04,
-		 * pthresh = 0x20
-		 */
-		ew32(RXDCTL(0), E1000_RXDCTL_DMA_BURST_ENABLE);
-		ew32(RXDCTL(1), E1000_RXDCTL_DMA_BURST_ENABLE);
-
-		/*
-		 * override the delay timers for enabling bursting, only if
-		 * the value was not set by the user via module options
-		 */
-		if (adapter->rx_int_delay == DEFAULT_RDTR)
-			adapter->rx_int_delay = BURST_RDTR;
-		if (adapter->rx_abs_int_delay == DEFAULT_RADV)
-			adapter->rx_abs_int_delay = BURST_RADV;
-	}
-
-	/* set the Receive Delay Timer Register */
-	ew32(RDTR, adapter->rx_int_delay);
-
-	/* irq moderation */
-	ew32(RADV, adapter->rx_abs_int_delay);
-	if ((adapter->itr_setting != 0) && (adapter->itr != 0))
-		ew32(ITR, 1000000000 / (adapter->itr * 256));
-
-	ctrl_ext = er32(CTRL_EXT);
-	/* Auto-Mask interrupts upon ICR access */
-	ctrl_ext |= E1000_CTRL_EXT_IAME;
-	ew32(IAM, 0xffffffff);
-	ew32(CTRL_EXT, ctrl_ext);
-	e1e_flush();
-
-	/*
-	 * Setup the HW Rx Head and Tail Descriptor Pointers and
-	 * the Base and Length of the Rx Descriptor Ring
-	 */
-	rdba = rx_ring->dma;
-	ew32(RDBAL, (rdba & DMA_BIT_MASK(32)));
-	ew32(RDBAH, (rdba >> 32));
-	ew32(RDLEN, rdlen);
-	ew32(RDH, 0);
-	ew32(RDT, 0);
-	rx_ring->head = E1000_RDH;
-	rx_ring->tail = E1000_RDT;
-
-	/* Enable Receive Checksum Offload for TCP and UDP */
-	rxcsum = er32(RXCSUM);
-	if (adapter->flags & FLAG_RX_CSUM_ENABLED) {
-		rxcsum |= E1000_RXCSUM_TUOFL;
-
-		/*
-		 * IPv4 payload checksum for UDP fragments must be
-		 * used in conjunction with packet-split.
-		 */
-		if (adapter->rx_ps_pages)
-			rxcsum |= E1000_RXCSUM_IPPCSE;
-	} else {
-		rxcsum &= ~E1000_RXCSUM_TUOFL;
-		/* no need to clear IPPCSE as it defaults to 0 */
-	}
-	ew32(RXCSUM, rxcsum);
-
-	/*
-	 * Enable early receives on supported devices, only takes effect when
-	 * packet size is equal or larger than the specified value (in 8 byte
-	 * units), e.g. using jumbo frames when setting to E1000_ERT_2048
-	 */
-	if ((adapter->flags & FLAG_HAS_ERT) ||
-	    (adapter->hw.mac.type == e1000_pch2lan)) {
-		if (adapter->netdev->mtu > ETH_DATA_LEN) {
-			u32 rxdctl = er32(RXDCTL(0));
-			ew32(RXDCTL(0), rxdctl | 0x3);
-			if (adapter->flags & FLAG_HAS_ERT)
-				ew32(ERT, E1000_ERT_2048 | (1 << 13));
-			/*
-			 * With jumbo frames and early-receive enabled,
-			 * excessive C-state transition latencies result in
-			 * dropped transactions.
-			 */
-			pm_qos_update_request(&adapter->netdev->pm_qos_req, 55);
-		} else {
-			pm_qos_update_request(&adapter->netdev->pm_qos_req,
-					      PM_QOS_DEFAULT_VALUE);
-		}
-	}
-
-	/* Enable Receives */
-	ew32(RCTL, rctl);
-}
-
-/**
- *  e1000_update_mc_addr_list - Update Multicast addresses
- *  @hw: pointer to the HW structure
- *  @mc_addr_list: array of multicast addresses to program
- *  @mc_addr_count: number of multicast addresses to program
- *
- *  Updates the Multicast Table Array.
- *  The caller must have a packed mc_addr_list of multicast addresses.
- **/
-static void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list,
-				      u32 mc_addr_count)
-{
-	hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, mc_addr_count);
-}
-
-/**
- * e1000_set_multi - Multicast and Promiscuous mode set
- * @netdev: network interface device structure
- *
- * The set_multi entry point is called whenever the multicast address
- * list or the network interface flags are updated.  This routine is
- * responsible for configuring the hardware for proper multicast,
- * promiscuous mode, and all-multi behavior.
- **/
-static void e1000_set_multi(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	struct netdev_hw_addr *ha;
-	u8  *mta_list;
-	u32 rctl;
-
-	/* Check for Promiscuous and All Multicast modes */
-
-	rctl = er32(RCTL);
-
-	if (netdev->flags & IFF_PROMISC) {
-		rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
-		rctl &= ~E1000_RCTL_VFE;
-		/* Do not hardware filter VLANs in promisc mode */
-		e1000e_vlan_filter_disable(adapter);
-	} else {
-		if (netdev->flags & IFF_ALLMULTI) {
-			rctl |= E1000_RCTL_MPE;
-			rctl &= ~E1000_RCTL_UPE;
-		} else {
-			rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE);
-		}
-		e1000e_vlan_filter_enable(adapter);
-	}
-
-	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. */
-		netdev_for_each_mc_addr(ha, netdev)
-			memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN);
-
-		e1000_update_mc_addr_list(hw, mta_list, i);
-		kfree(mta_list);
-	} else {
-		/*
-		 * if we're called from probe, we might not have
-		 * anything to do here, so clear out the list
-		 */
-		e1000_update_mc_addr_list(hw, NULL, 0);
-	}
-
-	if (netdev->features & NETIF_F_HW_VLAN_RX)
-		e1000e_vlan_strip_enable(adapter);
-	else
-		e1000e_vlan_strip_disable(adapter);
-}
-
-/**
- * e1000_configure - configure the hardware for Rx and Tx
- * @adapter: private board structure
- **/
-static void e1000_configure(struct e1000_adapter *adapter)
-{
-	e1000_set_multi(adapter->netdev);
-
-	e1000_restore_vlan(adapter);
-	e1000_init_manageability_pt(adapter);
-
-	e1000_configure_tx(adapter);
-	e1000_setup_rctl(adapter);
-	e1000_configure_rx(adapter);
-	adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring),
-			      GFP_KERNEL);
-}
-
-/**
- * e1000e_power_up_phy - restore link in case the phy was powered down
- * @adapter: address of board private structure
- *
- * The phy may be powered down to save power and turn off link when the
- * driver is unloaded and wake on lan is not enabled (among others)
- * *** this routine MUST be followed by a call to e1000e_reset ***
- **/
-void e1000e_power_up_phy(struct e1000_adapter *adapter)
-{
-	if (adapter->hw.phy.ops.power_up)
-		adapter->hw.phy.ops.power_up(&adapter->hw);
-
-	adapter->hw.mac.ops.setup_link(&adapter->hw);
-}
-
-/**
- * e1000_power_down_phy - Power down the PHY
- *
- * Power down the PHY so no link is implied when interface is down.
- * The PHY cannot be powered down if management or WoL is active.
- */
-static void e1000_power_down_phy(struct e1000_adapter *adapter)
-{
-	/* WoL is enabled */
-	if (adapter->wol)
-		return;
-
-	if (adapter->hw.phy.ops.power_down)
-		adapter->hw.phy.ops.power_down(&adapter->hw);
-}
-
-/**
- * e1000e_reset - bring the hardware into a known good state
- *
- * This function boots the hardware and enables some settings that
- * require a configuration cycle of the hardware - those cannot be
- * set/changed during runtime. After reset the device needs to be
- * properly configured for Rx, Tx etc.
- */
-void e1000e_reset(struct e1000_adapter *adapter)
-{
-	struct e1000_mac_info *mac = &adapter->hw.mac;
-	struct e1000_fc_info *fc = &adapter->hw.fc;
-	struct e1000_hw *hw = &adapter->hw;
-	u32 tx_space, min_tx_space, min_rx_space;
-	u32 pba = adapter->pba;
-	u16 hwm;
-
-	/* reset Packet Buffer Allocation to default */
-	ew32(PBA, pba);
-
-	if (adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) {
-		/*
-		 * To maintain wire speed transmits, the Tx FIFO should be
-		 * large enough to accommodate two full transmit packets,
-		 * rounded up to the next 1KB and expressed in KB.  Likewise,
-		 * the Rx FIFO should be large enough to accommodate at least
-		 * one full receive packet and is similarly rounded up and
-		 * expressed in KB.
-		 */
-		pba = er32(PBA);
-		/* upper 16 bits has Tx packet buffer allocation size in KB */
-		tx_space = pba >> 16;
-		/* lower 16 bits has Rx packet buffer allocation size in KB */
-		pba &= 0xffff;
-		/*
-		 * the Tx fifo also stores 16 bytes of information about the Tx
-		 * but don't include ethernet FCS because hardware appends it
-		 */
-		min_tx_space = (adapter->max_frame_size +
-				sizeof(struct e1000_tx_desc) -
-				ETH_FCS_LEN) * 2;
-		min_tx_space = ALIGN(min_tx_space, 1024);
-		min_tx_space >>= 10;
-		/* software strips receive CRC, so leave room for it */
-		min_rx_space = adapter->max_frame_size;
-		min_rx_space = ALIGN(min_rx_space, 1024);
-		min_rx_space >>= 10;
-
-		/*
-		 * If current Tx allocation is less than the min Tx FIFO size,
-		 * and the min Tx FIFO size is less than the current Rx FIFO
-		 * allocation, take space away from current Rx allocation
-		 */
-		if ((tx_space < min_tx_space) &&
-		    ((min_tx_space - tx_space) < pba)) {
-			pba -= min_tx_space - tx_space;
-
-			/*
-			 * if short on Rx space, Rx wins and must trump Tx
-			 * adjustment or use Early Receive if available
-			 */
-			if ((pba < min_rx_space) &&
-			    (!(adapter->flags & FLAG_HAS_ERT)))
-				/* ERT enabled in e1000_configure_rx */
-				pba = min_rx_space;
-		}
-
-		ew32(PBA, pba);
-	}
-
-	/*
-	 * flow control settings
-	 *
-	 * The high water mark must be low enough to fit one full frame
-	 * (or the size used for early receive) above it in the Rx FIFO.
-	 * Set it to the lower of:
-	 * - 90% of the Rx FIFO size, and
-	 * - the full Rx FIFO size minus the early receive size (for parts
-	 *   with ERT support assuming ERT set to E1000_ERT_2048), or
-	 * - the full Rx FIFO size minus one full frame
-	 */
-	if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME)
-		fc->pause_time = 0xFFFF;
-	else
-		fc->pause_time = E1000_FC_PAUSE_TIME;
-	fc->send_xon = 1;
-	fc->current_mode = fc->requested_mode;
-
-	switch (hw->mac.type) {
-	default:
-		if ((adapter->flags & FLAG_HAS_ERT) &&
-		    (adapter->netdev->mtu > ETH_DATA_LEN))
-			hwm = min(((pba << 10) * 9 / 10),
-				  ((pba << 10) - (E1000_ERT_2048 << 3)));
-		else
-			hwm = min(((pba << 10) * 9 / 10),
-				  ((pba << 10) - adapter->max_frame_size));
-
-		fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */
-		fc->low_water = fc->high_water - 8;
-		break;
-	case e1000_pchlan:
-		/*
-		 * Workaround PCH LOM adapter hangs with certain network
-		 * loads.  If hangs persist, try disabling Tx flow control.
-		 */
-		if (adapter->netdev->mtu > ETH_DATA_LEN) {
-			fc->high_water = 0x3500;
-			fc->low_water  = 0x1500;
-		} else {
-			fc->high_water = 0x5000;
-			fc->low_water  = 0x3000;
-		}
-		fc->refresh_time = 0x1000;
-		break;
-	case e1000_pch2lan:
-		fc->high_water = 0x05C20;
-		fc->low_water = 0x05048;
-		fc->pause_time = 0x0650;
-		fc->refresh_time = 0x0400;
-		if (adapter->netdev->mtu > ETH_DATA_LEN) {
-			pba = 14;
-			ew32(PBA, pba);
-		}
-		break;
-	}
-
-	/*
-	 * Disable Adaptive Interrupt Moderation if 2 full packets cannot
-	 * fit in receive buffer and early-receive not supported.
-	 */
-	if (adapter->itr_setting & 0x3) {
-		if (((adapter->max_frame_size * 2) > (pba << 10)) &&
-		    !(adapter->flags & FLAG_HAS_ERT)) {
-			if (!(adapter->flags2 & FLAG2_DISABLE_AIM)) {
-				dev_info(&adapter->pdev->dev,
-					"Interrupt Throttle Rate turned off\n");
-				adapter->flags2 |= FLAG2_DISABLE_AIM;
-				ew32(ITR, 0);
-			}
-		} else if (adapter->flags2 & FLAG2_DISABLE_AIM) {
-			dev_info(&adapter->pdev->dev,
-				 "Interrupt Throttle Rate turned on\n");
-			adapter->flags2 &= ~FLAG2_DISABLE_AIM;
-			adapter->itr = 20000;
-			ew32(ITR, 1000000000 / (adapter->itr * 256));
-		}
-	}
-
-	/* Allow time for pending master requests to run */
-	mac->ops.reset_hw(hw);
-
-	/*
-	 * For parts with AMT enabled, let the firmware know
-	 * that the network interface is in control
-	 */
-	if (adapter->flags & FLAG_HAS_AMT)
-		e1000e_get_hw_control(adapter);
-
-	ew32(WUC, 0);
-
-	if (mac->ops.init_hw(hw))
-		e_err("Hardware Error\n");
-
-	e1000_update_mng_vlan(adapter);
-
-	/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
-	ew32(VET, ETH_P_8021Q);
-
-	e1000e_reset_adaptive(hw);
-
-	if (!netif_running(adapter->netdev) &&
-	    !test_bit(__E1000_TESTING, &adapter->state)) {
-		e1000_power_down_phy(adapter);
-		return;
-	}
-
-	e1000_get_phy_info(hw);
-
-	if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) &&
-	    !(adapter->flags & FLAG_SMART_POWER_DOWN)) {
-		u16 phy_data = 0;
-		/*
-		 * speed up time to link by disabling smart power down, ignore
-		 * the return value of this function because there is nothing
-		 * different we would do if it failed
-		 */
-		e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
-		phy_data &= ~IGP02E1000_PM_SPD;
-		e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
-	}
-}
-
-int e1000e_up(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-
-	/* hardware has been reset, we need to reload some things */
-	e1000_configure(adapter);
-
-	clear_bit(__E1000_DOWN, &adapter->state);
-
-	napi_enable(&adapter->napi);
-	if (adapter->msix_entries)
-		e1000_configure_msix(adapter);
-	e1000_irq_enable(adapter);
-
-	netif_start_queue(adapter->netdev);
-
-	/* fire a link change interrupt to start the watchdog */
-	if (adapter->msix_entries)
-		ew32(ICS, E1000_ICS_LSC | E1000_ICR_OTHER);
-	else
-		ew32(ICS, E1000_ICS_LSC);
-
-	return 0;
-}
-
-static void e1000e_flush_descriptors(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-
-	if (!(adapter->flags2 & FLAG2_DMA_BURST))
-		return;
-
-	/* flush pending descriptor writebacks to memory */
-	ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
-	ew32(RDTR, adapter->rx_int_delay | E1000_RDTR_FPD);
-
-	/* execute the writes immediately */
-	e1e_flush();
-}
-
-static void e1000e_update_stats(struct e1000_adapter *adapter);
-
-void e1000e_down(struct e1000_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct e1000_hw *hw = &adapter->hw;
-	u32 tctl, rctl;
-
-	/*
-	 * signal that we're down so the interrupt handler does not
-	 * reschedule our watchdog timer
-	 */
-	set_bit(__E1000_DOWN, &adapter->state);
-
-	/* disable receives in the hardware */
-	rctl = er32(RCTL);
-	if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX))
-		ew32(RCTL, rctl & ~E1000_RCTL_EN);
-	/* flush and sleep below */
-
-	netif_stop_queue(netdev);
-
-	/* disable transmits in the hardware */
-	tctl = er32(TCTL);
-	tctl &= ~E1000_TCTL_EN;
-	ew32(TCTL, tctl);
-
-	/* flush both disables and wait for them to finish */
-	e1e_flush();
-	usleep_range(10000, 20000);
-
-	napi_disable(&adapter->napi);
-	e1000_irq_disable(adapter);
-
-	del_timer_sync(&adapter->watchdog_timer);
-	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);
-
-	e1000e_flush_descriptors(adapter);
-	e1000_clean_tx_ring(adapter);
-	e1000_clean_rx_ring(adapter);
-
-	adapter->link_speed = 0;
-	adapter->link_duplex = 0;
-
-	if (!pci_channel_offline(adapter->pdev))
-		e1000e_reset(adapter);
-
-	/*
-	 * TODO: for power management, we could drop the link and
-	 * pci_disable_device here.
-	 */
-}
-
-void e1000e_reinit_locked(struct e1000_adapter *adapter)
-{
-	might_sleep();
-	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
-		usleep_range(1000, 2000);
-	e1000e_down(adapter);
-	e1000e_up(adapter);
-	clear_bit(__E1000_RESETTING, &adapter->state);
-}
-
-/**
- * e1000_sw_init - Initialize general software structures (struct e1000_adapter)
- * @adapter: board private structure to initialize
- *
- * e1000_sw_init initializes the Adapter private data structure.
- * Fields are initialized based on PCI device information and
- * OS network device settings (MTU size).
- **/
-static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-
-	adapter->rx_buffer_len = ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN;
-	adapter->rx_ps_bsize0 = 128;
-	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))
-		return -ENOMEM;
-
-	/* Explicitly disable IRQ since the NIC can be in any state. */
-	e1000_irq_disable(adapter);
-
-	set_bit(__E1000_DOWN, &adapter->state);
-	return 0;
-}
-
-/**
- * e1000_intr_msi_test - Interrupt Handler
- * @irq: interrupt number
- * @data: pointer to a network interface device structure
- **/
-static irqreturn_t e1000_intr_msi_test(int irq, void *data)
-{
-	struct net_device *netdev = data;
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u32 icr = er32(ICR);
-
-	e_dbg("icr is %08X\n", icr);
-	if (icr & E1000_ICR_RXSEQ) {
-		adapter->flags &= ~FLAG_MSI_TEST_FAILED;
-		wmb();
-	}
-
-	return IRQ_HANDLED;
-}
-
-/**
- * e1000_test_msi_interrupt - Returns 0 for successful test
- * @adapter: board private struct
- *
- * code flow taken from tg3.c
- **/
-static int e1000_test_msi_interrupt(struct e1000_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct e1000_hw *hw = &adapter->hw;
-	int err;
-
-	/* poll_enable hasn't been called yet, so don't need disable */
-	/* clear any pending events */
-	er32(ICR);
-
-	/* free the real vector and request a test handler */
-	e1000_free_irq(adapter);
-	e1000e_reset_interrupt_capability(adapter);
-
-	/* Assume that the test fails, if it succeeds then the test
-	 * MSI irq handler will unset this flag */
-	adapter->flags |= FLAG_MSI_TEST_FAILED;
-
-	err = pci_enable_msi(adapter->pdev);
-	if (err)
-		goto msi_test_failed;
-
-	err = request_irq(adapter->pdev->irq, e1000_intr_msi_test, 0,
-			  netdev->name, netdev);
-	if (err) {
-		pci_disable_msi(adapter->pdev);
-		goto msi_test_failed;
-	}
-
-	wmb();
-
-	e1000_irq_enable(adapter);
-
-	/* fire an unusual interrupt on the test handler */
-	ew32(ICS, E1000_ICS_RXSEQ);
-	e1e_flush();
-	msleep(50);
-
-	e1000_irq_disable(adapter);
-
-	rmb();
-
-	if (adapter->flags & FLAG_MSI_TEST_FAILED) {
-		adapter->int_mode = E1000E_INT_MODE_LEGACY;
-		e_info("MSI interrupt test failed, using legacy interrupt.\n");
-	} else
-		e_dbg("MSI interrupt test succeeded!\n");
-
-	free_irq(adapter->pdev->irq, netdev);
-	pci_disable_msi(adapter->pdev);
-
-msi_test_failed:
-	e1000e_set_interrupt_capability(adapter);
-	return e1000_request_irq(adapter);
-}
-
-/**
- * e1000_test_msi - Returns 0 if MSI test succeeds or INTx mode is restored
- * @adapter: board private struct
- *
- * code flow taken from tg3.c, called with e1000 interrupts disabled.
- **/
-static int e1000_test_msi(struct e1000_adapter *adapter)
-{
-	int err;
-	u16 pci_cmd;
-
-	if (!(adapter->flags & FLAG_MSI_ENABLED))
-		return 0;
-
-	/* disable SERR in case the MSI write causes a master abort */
-	pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd);
-	if (pci_cmd & PCI_COMMAND_SERR)
-		pci_write_config_word(adapter->pdev, PCI_COMMAND,
-				      pci_cmd & ~PCI_COMMAND_SERR);
-
-	err = e1000_test_msi_interrupt(adapter);
-
-	/* re-enable SERR */
-	if (pci_cmd & PCI_COMMAND_SERR) {
-		pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd);
-		pci_cmd |= PCI_COMMAND_SERR;
-		pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd);
-	}
-
-	return err;
-}
-
-/**
- * e1000_open - Called when a network interface is made active
- * @netdev: network interface device structure
- *
- * Returns 0 on success, negative value on failure
- *
- * 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.
- **/
-static int e1000_open(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	struct pci_dev *pdev = adapter->pdev;
-	int err;
-
-	/* disallow open during test */
-	if (test_bit(__E1000_TESTING, &adapter->state))
-		return -EBUSY;
-
-	pm_runtime_get_sync(&pdev->dev);
-
-	netif_carrier_off(netdev);
-
-	/* allocate transmit descriptors */
-	err = e1000e_setup_tx_resources(adapter);
-	if (err)
-		goto err_setup_tx;
-
-	/* allocate receive descriptors */
-	err = e1000e_setup_rx_resources(adapter);
-	if (err)
-		goto err_setup_rx;
-
-	/*
-	 * If AMT is enabled, let the firmware know that the network
-	 * interface is now open and reset the part to a known state.
-	 */
-	if (adapter->flags & FLAG_HAS_AMT) {
-		e1000e_get_hw_control(adapter);
-		e1000e_reset(adapter);
-	}
-
-	e1000e_power_up_phy(adapter);
-
-	adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
-	if ((adapter->hw.mng_cookie.status &
-	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN))
-		e1000_update_mng_vlan(adapter);
-
-	/* DMA latency requirement to workaround early-receive/jumbo issue */
-	if ((adapter->flags & FLAG_HAS_ERT) ||
-	    (adapter->hw.mac.type == e1000_pch2lan))
-		pm_qos_add_request(&adapter->netdev->pm_qos_req,
-				   PM_QOS_CPU_DMA_LATENCY,
-				   PM_QOS_DEFAULT_VALUE);
-
-	/*
-	 * before we allocate an interrupt, we must be ready to handle it.
-	 * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
-	 * as soon as we call pci_request_irq, so we have to setup our
-	 * clean_rx handler before we do so.
-	 */
-	e1000_configure(adapter);
-
-	err = e1000_request_irq(adapter);
-	if (err)
-		goto err_req_irq;
-
-	/*
-	 * Work around PCIe errata with MSI interrupts causing some chipsets to
-	 * ignore e1000e MSI messages, which means we need to test our MSI
-	 * interrupt now
-	 */
-	if (adapter->int_mode != E1000E_INT_MODE_LEGACY) {
-		err = e1000_test_msi(adapter);
-		if (err) {
-			e_err("Interrupt allocation failed\n");
-			goto err_req_irq;
-		}
-	}
-
-	/* From here on the code is the same as e1000e_up() */
-	clear_bit(__E1000_DOWN, &adapter->state);
-
-	napi_enable(&adapter->napi);
-
-	e1000_irq_enable(adapter);
-
-	netif_start_queue(netdev);
-
-	adapter->idle_check = true;
-	pm_runtime_put(&pdev->dev);
-
-	/* fire a link status change interrupt to start the watchdog */
-	if (adapter->msix_entries)
-		ew32(ICS, E1000_ICS_LSC | E1000_ICR_OTHER);
-	else
-		ew32(ICS, E1000_ICS_LSC);
-
-	return 0;
-
-err_req_irq:
-	e1000e_release_hw_control(adapter);
-	e1000_power_down_phy(adapter);
-	e1000e_free_rx_resources(adapter);
-err_setup_rx:
-	e1000e_free_tx_resources(adapter);
-err_setup_tx:
-	e1000e_reset(adapter);
-	pm_runtime_put_sync(&pdev->dev);
-
-	return err;
-}
-
-/**
- * e1000_close - Disables a network interface
- * @netdev: network interface device structure
- *
- * 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.
- **/
-static int e1000_close(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct pci_dev *pdev = adapter->pdev;
-
-	WARN_ON(test_bit(__E1000_RESETTING, &adapter->state));
-
-	pm_runtime_get_sync(&pdev->dev);
-
-	if (!test_bit(__E1000_DOWN, &adapter->state)) {
-		e1000e_down(adapter);
-		e1000_free_irq(adapter);
-	}
-	e1000_power_down_phy(adapter);
-
-	e1000e_free_tx_resources(adapter);
-	e1000e_free_rx_resources(adapter);
-
-	/*
-	 * kill manageability vlan ID if supported, but not if a vlan with
-	 * the same ID is registered on the host OS (let 8021q kill it)
-	 */
-	if (adapter->hw.mng_cookie.status &
-	    E1000_MNG_DHCP_COOKIE_STATUS_VLAN)
-		e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
-
-	/*
-	 * If AMT is enabled, let the firmware know that the network
-	 * interface is now closed
-	 */
-	if ((adapter->flags & FLAG_HAS_AMT) &&
-	    !test_bit(__E1000_TESTING, &adapter->state))
-		e1000e_release_hw_control(adapter);
-
-	if ((adapter->flags & FLAG_HAS_ERT) ||
-	    (adapter->hw.mac.type == e1000_pch2lan))
-		pm_qos_remove_request(&adapter->netdev->pm_qos_req);
-
-	pm_runtime_put_sync(&pdev->dev);
-
-	return 0;
-}
-/**
- * e1000_set_mac - Change the Ethernet Address of the NIC
- * @netdev: network interface device structure
- * @p: pointer to an address structure
- *
- * Returns 0 on success, negative on failure
- **/
-static int e1000_set_mac(struct net_device *netdev, void *p)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct sockaddr *addr = p;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-	memcpy(adapter->hw.mac.addr, addr->sa_data, netdev->addr_len);
-
-	e1000e_rar_set(&adapter->hw, adapter->hw.mac.addr, 0);
-
-	if (adapter->flags & FLAG_RESET_OVERWRITES_LAA) {
-		/* activate the work around */
-		e1000e_set_laa_state_82571(&adapter->hw, 1);
-
-		/*
-		 * Hold a copy of the LAA in RAR[14] This is done so that
-		 * between the time RAR[0] gets clobbered  and the time it
-		 * gets fixed (in e1000_watchdog), the actual LAA is in one
-		 * of the RARs and no incoming packets directed to this port
-		 * are dropped. Eventually the LAA will be in RAR[0] and
-		 * RAR[14]
-		 */
-		e1000e_rar_set(&adapter->hw,
-			      adapter->hw.mac.addr,
-			      adapter->hw.mac.rar_entry_count - 1);
-	}
-
-	return 0;
-}
-
-/**
- * e1000e_update_phy_task - work thread to update phy
- * @work: pointer to our work struct
- *
- * this worker thread exists because we must acquire a
- * semaphore to read the phy, which we could msleep while
- * waiting for it, and we can't msleep in a timer.
- **/
-static void e1000e_update_phy_task(struct work_struct *work)
-{
-	struct e1000_adapter *adapter = container_of(work,
-					struct e1000_adapter, update_phy_task);
-
-	if (test_bit(__E1000_DOWN, &adapter->state))
-		return;
-
-	e1000_get_phy_info(&adapter->hw);
-}
-
-/*
- * Need to wait a few seconds after link up to get diagnostic information from
- * the phy
- */
-static void e1000_update_phy_info(unsigned long data)
-{
-	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
-
-	if (test_bit(__E1000_DOWN, &adapter->state))
-		return;
-
-	schedule_work(&adapter->update_phy_task);
-}
-
-/**
- * e1000e_update_phy_stats - Update the PHY statistics counters
- * @adapter: board private structure
- *
- * Read/clear the upper 16-bit PHY registers and read/accumulate lower
- **/
-static void e1000e_update_phy_stats(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	s32 ret_val;
-	u16 phy_data;
-
-	ret_val = hw->phy.ops.acquire(hw);
-	if (ret_val)
-		return;
-
-	/*
-	 * A page set is expensive so check if already on desired page.
-	 * If not, set to the page with the PHY status registers.
-	 */
-	hw->phy.addr = 1;
-	ret_val = e1000e_read_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
-					   &phy_data);
-	if (ret_val)
-		goto release;
-	if (phy_data != (HV_STATS_PAGE << IGP_PAGE_SHIFT)) {
-		ret_val = hw->phy.ops.set_page(hw,
-					       HV_STATS_PAGE << IGP_PAGE_SHIFT);
-		if (ret_val)
-			goto release;
-	}
-
-	/* Single Collision Count */
-	hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data);
-	ret_val = hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data);
-	if (!ret_val)
-		adapter->stats.scc += phy_data;
-
-	/* Excessive Collision Count */
-	hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data);
-	ret_val = hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data);
-	if (!ret_val)
-		adapter->stats.ecol += phy_data;
-
-	/* Multiple Collision Count */
-	hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data);
-	ret_val = hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data);
-	if (!ret_val)
-		adapter->stats.mcc += phy_data;
-
-	/* Late Collision Count */
-	hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data);
-	ret_val = hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data);
-	if (!ret_val)
-		adapter->stats.latecol += phy_data;
-
-	/* Collision Count - also used for adaptive IFS */
-	hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data);
-	ret_val = hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data);
-	if (!ret_val)
-		hw->mac.collision_delta = phy_data;
-
-	/* Defer Count */
-	hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data);
-	ret_val = hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data);
-	if (!ret_val)
-		adapter->stats.dc += phy_data;
-
-	/* Transmit with no CRS */
-	hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data);
-	ret_val = hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data);
-	if (!ret_val)
-		adapter->stats.tncrs += phy_data;
-
-release:
-	hw->phy.ops.release(hw);
-}
-
-/**
- * e1000e_update_stats - Update the board statistics counters
- * @adapter: board private structure
- **/
-static void e1000e_update_stats(struct e1000_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct e1000_hw *hw = &adapter->hw;
-	struct pci_dev *pdev = adapter->pdev;
-
-	/*
-	 * Prevent stats update while adapter is being reset, or if the pci
-	 * connection is down.
-	 */
-	if (adapter->link_speed == 0)
-		return;
-	if (pci_channel_offline(pdev))
-		return;
-
-	adapter->stats.crcerrs += er32(CRCERRS);
-	adapter->stats.gprc += er32(GPRC);
-	adapter->stats.gorc += er32(GORCL);
-	er32(GORCH); /* Clear gorc */
-	adapter->stats.bprc += er32(BPRC);
-	adapter->stats.mprc += er32(MPRC);
-	adapter->stats.roc += er32(ROC);
-
-	adapter->stats.mpc += er32(MPC);
-
-	/* Half-duplex statistics */
-	if (adapter->link_duplex == HALF_DUPLEX) {
-		if (adapter->flags2 & FLAG2_HAS_PHY_STATS) {
-			e1000e_update_phy_stats(adapter);
-		} else {
-			adapter->stats.scc += er32(SCC);
-			adapter->stats.ecol += er32(ECOL);
-			adapter->stats.mcc += er32(MCC);
-			adapter->stats.latecol += er32(LATECOL);
-			adapter->stats.dc += er32(DC);
-
-			hw->mac.collision_delta = er32(COLC);
-
-			if ((hw->mac.type != e1000_82574) &&
-			    (hw->mac.type != e1000_82583))
-				adapter->stats.tncrs += er32(TNCRS);
-		}
-		adapter->stats.colc += hw->mac.collision_delta;
-	}
-
-	adapter->stats.xonrxc += er32(XONRXC);
-	adapter->stats.xontxc += er32(XONTXC);
-	adapter->stats.xoffrxc += er32(XOFFRXC);
-	adapter->stats.xofftxc += er32(XOFFTXC);
-	adapter->stats.gptc += er32(GPTC);
-	adapter->stats.gotc += er32(GOTCL);
-	er32(GOTCH); /* Clear gotc */
-	adapter->stats.rnbc += er32(RNBC);
-	adapter->stats.ruc += er32(RUC);
-
-	adapter->stats.mptc += er32(MPTC);
-	adapter->stats.bptc += er32(BPTC);
-
-	/* used for adaptive IFS */
-
-	hw->mac.tx_packet_delta = er32(TPT);
-	adapter->stats.tpt += hw->mac.tx_packet_delta;
-
-	adapter->stats.algnerrc += er32(ALGNERRC);
-	adapter->stats.rxerrc += er32(RXERRC);
-	adapter->stats.cexterr += er32(CEXTERR);
-	adapter->stats.tsctc += er32(TSCTC);
-	adapter->stats.tsctfc += er32(TSCTFC);
-
-	/* Fill out the OS statistics structure */
-	netdev->stats.multicast = adapter->stats.mprc;
-	netdev->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
-	 */
-	netdev->stats.rx_errors = adapter->stats.rxerrc +
-		adapter->stats.crcerrs + adapter->stats.algnerrc +
-		adapter->stats.ruc + adapter->stats.roc +
-		adapter->stats.cexterr;
-	netdev->stats.rx_length_errors = adapter->stats.ruc +
-					      adapter->stats.roc;
-	netdev->stats.rx_crc_errors = adapter->stats.crcerrs;
-	netdev->stats.rx_frame_errors = adapter->stats.algnerrc;
-	netdev->stats.rx_missed_errors = adapter->stats.mpc;
-
-	/* Tx Errors */
-	netdev->stats.tx_errors = adapter->stats.ecol +
-				       adapter->stats.latecol;
-	netdev->stats.tx_aborted_errors = adapter->stats.ecol;
-	netdev->stats.tx_window_errors = adapter->stats.latecol;
-	netdev->stats.tx_carrier_errors = adapter->stats.tncrs;
-
-	/* Tx Dropped needs to be maintained elsewhere */
-
-	/* Management Stats */
-	adapter->stats.mgptc += er32(MGTPTC);
-	adapter->stats.mgprc += er32(MGTPRC);
-	adapter->stats.mgpdc += er32(MGTPDC);
-}
-
-/**
- * e1000_phy_read_status - Update the PHY register status snapshot
- * @adapter: board private structure
- **/
-static void e1000_phy_read_status(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct e1000_phy_regs *phy = &adapter->phy_regs;
-
-	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);
-		ret_val |= e1e_rphy(hw, PHY_LP_ABILITY, &phy->lpa);
-		ret_val |= e1e_rphy(hw, PHY_AUTONEG_EXP, &phy->expansion);
-		ret_val |= e1e_rphy(hw, PHY_1000T_CTRL, &phy->ctrl1000);
-		ret_val |= e1e_rphy(hw, PHY_1000T_STATUS, &phy->stat1000);
-		ret_val |= e1e_rphy(hw, PHY_EXT_STATUS, &phy->estatus);
-		if (ret_val)
-			e_warn("Error reading PHY register\n");
-	} else {
-		/*
-		 * Do not read PHY registers if link is not up
-		 * Set values to typical power-on defaults
-		 */
-		phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX);
-		phy->bmsr = (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL |
-			     BMSR_10HALF | BMSR_ESTATEN | BMSR_ANEGCAPABLE |
-			     BMSR_ERCAP);
-		phy->advertise = (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP |
-				  ADVERTISE_ALL | ADVERTISE_CSMA);
-		phy->lpa = 0;
-		phy->expansion = EXPANSION_ENABLENPAGE;
-		phy->ctrl1000 = ADVERTISE_1000FULL;
-		phy->stat1000 = 0;
-		phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF);
-	}
-}
-
-static void e1000_print_link_info(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 ctrl = er32(CTRL);
-
-	/* Link status message must follow this format for user tools */
-	printk(KERN_INFO "e1000e: %s NIC Link is Up %d Mbps %s, "
-	       "Flow Control: %s\n",
-	       adapter->netdev->name,
-	       adapter->link_speed,
-	       (adapter->link_duplex == FULL_DUPLEX) ?
-	       "Full Duplex" : "Half Duplex",
-	       ((ctrl & E1000_CTRL_TFCE) && (ctrl & E1000_CTRL_RFCE)) ?
-	       "Rx/Tx" :
-	       ((ctrl & E1000_CTRL_RFCE) ? "Rx" :
-		((ctrl & E1000_CTRL_TFCE) ? "Tx" : "None")));
-}
-
-static bool e1000e_has_link(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	bool link_active = 0;
-	s32 ret_val = 0;
-
-	/*
-	 * get_link_status is set on LSC (link status) interrupt or
-	 * Rx sequence error interrupt.  get_link_status will stay
-	 * false until the check_for_link establishes link
-	 * for copper adapters ONLY
-	 */
-	switch (hw->phy.media_type) {
-	case e1000_media_type_copper:
-		if (hw->mac.get_link_status) {
-			ret_val = hw->mac.ops.check_for_link(hw);
-			link_active = !hw->mac.get_link_status;
-		} else {
-			link_active = 1;
-		}
-		break;
-	case e1000_media_type_fiber:
-		ret_val = hw->mac.ops.check_for_link(hw);
-		link_active = !!(er32(STATUS) & E1000_STATUS_LU);
-		break;
-	case e1000_media_type_internal_serdes:
-		ret_val = hw->mac.ops.check_for_link(hw);
-		link_active = adapter->hw.mac.serdes_has_link;
-		break;
-	default:
-	case e1000_media_type_unknown:
-		break;
-	}
-
-	if ((ret_val == E1000_ERR_PHY) && (hw->phy.type == e1000_phy_igp_3) &&
-	    (er32(CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) {
-		/* See e1000_kmrn_lock_loss_workaround_ich8lan() */
-		e_info("Gigabit has been disabled, downgrading speed\n");
-	}
-
-	return link_active;
-}
-
-static void e1000e_enable_receives(struct e1000_adapter *adapter)
-{
-	/* make sure the receive unit is started */
-	if ((adapter->flags & FLAG_RX_NEEDS_RESTART) &&
-	    (adapter->flags & FLAG_RX_RESTART_NOW)) {
-		struct e1000_hw *hw = &adapter->hw;
-		u32 rctl = er32(RCTL);
-		ew32(RCTL, rctl | E1000_RCTL_EN);
-		adapter->flags &= ~FLAG_RX_RESTART_NOW;
-	}
-}
-
-static void e1000e_check_82574_phy_workaround(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-
-	/*
-	 * With 82574 controllers, PHY needs to be checked periodically
-	 * for hung state and reset, if two calls return true
-	 */
-	if (e1000_check_phy_82574(hw))
-		adapter->phy_hang_count++;
-	else
-		adapter->phy_hang_count = 0;
-
-	if (adapter->phy_hang_count > 1) {
-		adapter->phy_hang_count = 0;
-		schedule_work(&adapter->reset_task);
-	}
-}
-
-/**
- * e1000_watchdog - Timer Call-back
- * @data: pointer to adapter cast into an unsigned long
- **/
-static void e1000_watchdog(unsigned long data)
-{
-	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
-
-	/* Do the rest outside of interrupt context */
-	schedule_work(&adapter->watchdog_task);
-
-	/* TODO: make this use queue_delayed_work() */
-}
-
-static void e1000_watchdog_task(struct work_struct *work)
-{
-	struct e1000_adapter *adapter = container_of(work,
-					struct e1000_adapter, watchdog_task);
-	struct net_device *netdev = adapter->netdev;
-	struct e1000_mac_info *mac = &adapter->hw.mac;
-	struct e1000_phy_info *phy = &adapter->hw.phy;
-	struct e1000_ring *tx_ring = adapter->tx_ring;
-	struct e1000_hw *hw = &adapter->hw;
-	u32 link, tctl;
-
-	if (test_bit(__E1000_DOWN, &adapter->state))
-		return;
-
-	link = e1000e_has_link(adapter);
-	if ((netif_carrier_ok(netdev)) && link) {
-		/* Cancel scheduled suspend requests. */
-		pm_runtime_resume(netdev->dev.parent);
-
-		e1000e_enable_receives(adapter);
-		goto link_up;
-	}
-
-	if ((e1000e_enable_tx_pkt_filtering(hw)) &&
-	    (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id))
-		e1000_update_mng_vlan(adapter);
-
-	if (link) {
-		if (!netif_carrier_ok(netdev)) {
-			bool txb2b = 1;
-
-			/* Cancel scheduled suspend requests. */
-			pm_runtime_resume(netdev->dev.parent);
-
-			/* update snapshot of PHY registers on LSC */
-			e1000_phy_read_status(adapter);
-			mac->ops.get_link_up_info(&adapter->hw,
-						   &adapter->link_speed,
-						   &adapter->link_duplex);
-			e1000_print_link_info(adapter);
-			/*
-			 * On supported PHYs, check for duplex mismatch only
-			 * if link has autonegotiated at 10/100 half
-			 */
-			if ((hw->phy.type == e1000_phy_igp_3 ||
-			     hw->phy.type == e1000_phy_bm) &&
-			    (hw->mac.autoneg == true) &&
-			    (adapter->link_speed == SPEED_10 ||
-			     adapter->link_speed == SPEED_100) &&
-			    (adapter->link_duplex == HALF_DUPLEX)) {
-				u16 autoneg_exp;
-
-				e1e_rphy(hw, PHY_AUTONEG_EXP, &autoneg_exp);
-
-				if (!(autoneg_exp & NWAY_ER_LP_NWAY_CAPS))
-					e_info("Autonegotiated half duplex but"
-					       " link partner cannot autoneg. "
-					       " Try forcing full duplex if "
-					       "link gets many collisions.\n");
-			}
-
-			/* adjust timeout factor according to speed/duplex */
-			adapter->tx_timeout_factor = 1;
-			switch (adapter->link_speed) {
-			case SPEED_10:
-				txb2b = 0;
-				adapter->tx_timeout_factor = 16;
-				break;
-			case SPEED_100:
-				txb2b = 0;
-				adapter->tx_timeout_factor = 10;
-				break;
-			}
-
-			/*
-			 * workaround: re-program speed mode bit after
-			 * link-up event
-			 */
-			if ((adapter->flags & FLAG_TARC_SPEED_MODE_BIT) &&
-			    !txb2b) {
-				u32 tarc0;
-				tarc0 = er32(TARC(0));
-				tarc0 &= ~SPEED_MODE_BIT;
-				ew32(TARC(0), tarc0);
-			}
-
-			/*
-			 * disable TSO for pcie and 10/100 speeds, to avoid
-			 * some hardware issues
-			 */
-			if (!(adapter->flags & FLAG_TSO_FORCE)) {
-				switch (adapter->link_speed) {
-				case SPEED_10:
-				case SPEED_100:
-					e_info("10/100 speed: disabling TSO\n");
-					netdev->features &= ~NETIF_F_TSO;
-					netdev->features &= ~NETIF_F_TSO6;
-					break;
-				case SPEED_1000:
-					netdev->features |= NETIF_F_TSO;
-					netdev->features |= NETIF_F_TSO6;
-					break;
-				default:
-					/* oops */
-					break;
-				}
-			}
-
-			/*
-			 * enable transmits in the hardware, need to do this
-			 * after setting TARC(0)
-			 */
-			tctl = er32(TCTL);
-			tctl |= E1000_TCTL_EN;
-			ew32(TCTL, tctl);
-
-                        /*
-			 * Perform any post-link-up configuration before
-			 * reporting link up.
-			 */
-			if (phy->ops.cfg_on_link_up)
-				phy->ops.cfg_on_link_up(hw);
-
-			netif_carrier_on(netdev);
-
-			if (!test_bit(__E1000_DOWN, &adapter->state))
-				mod_timer(&adapter->phy_info_timer,
-					  round_jiffies(jiffies + 2 * HZ));
-		}
-	} else {
-		if (netif_carrier_ok(netdev)) {
-			adapter->link_speed = 0;
-			adapter->link_duplex = 0;
-			/* Link status message must follow this format */
-			printk(KERN_INFO "e1000e: %s NIC Link is Down\n",
-			       adapter->netdev->name);
-			netif_carrier_off(netdev);
-			if (!test_bit(__E1000_DOWN, &adapter->state))
-				mod_timer(&adapter->phy_info_timer,
-					  round_jiffies(jiffies + 2 * HZ));
-
-			if (adapter->flags & FLAG_RX_NEEDS_RESTART)
-				schedule_work(&adapter->reset_task);
-			else
-				pm_schedule_suspend(netdev->dev.parent,
-							LINK_TIMEOUT);
-		}
-	}
-
-link_up:
-	spin_lock(&adapter->stats64_lock);
-	e1000e_update_stats(adapter);
-
-	mac->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
-	adapter->tpt_old = adapter->stats.tpt;
-	mac->collision_delta = adapter->stats.colc - adapter->colc_old;
-	adapter->colc_old = adapter->stats.colc;
-
-	adapter->gorc = adapter->stats.gorc - adapter->gorc_old;
-	adapter->gorc_old = adapter->stats.gorc;
-	adapter->gotc = adapter->stats.gotc - adapter->gotc_old;
-	adapter->gotc_old = adapter->stats.gotc;
-	spin_unlock(&adapter->stats64_lock);
-
-	e1000e_update_adaptive(&adapter->hw);
-
-	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) */
-	if (adapter->itr_setting == 4) {
-		/*
-		 * Symmetric Tx/Rx gets a reduced ITR=2000;
-		 * Total asymmetrical Tx or Rx gets ITR=8000;
-		 * everyone else is between 2000-8000.
-		 */
-		u32 goc = (adapter->gotc + adapter->gorc) / 10000;
-		u32 dif = (adapter->gotc > adapter->gorc ?
-			    adapter->gotc - adapter->gorc :
-			    adapter->gorc - adapter->gotc) / 10000;
-		u32 itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
-
-		ew32(ITR, 1000000000 / (itr * 256));
-	}
-
-	/* Cause software interrupt to ensure Rx ring is cleaned */
-	if (adapter->msix_entries)
-		ew32(ICS, adapter->rx_ring->ims_val);
-	else
-		ew32(ICS, E1000_ICS_RXDMT0);
-
-	/* flush pending descriptors to memory before detecting Tx hang */
-	e1000e_flush_descriptors(adapter);
-
-	/* Force detection of hung controller every watchdog period */
-	adapter->detect_tx_hung = 1;
-
-	/*
-	 * With 82571 controllers, LAA may be overwritten due to controller
-	 * reset from the other port. Set the appropriate LAA in RAR[0]
-	 */
-	if (e1000e_get_laa_state_82571(hw))
-		e1000e_rar_set(hw, adapter->hw.mac.addr, 0);
-
-	if (adapter->flags2 & FLAG2_CHECK_PHY_HANG)
-		e1000e_check_82574_phy_workaround(adapter);
-
-	/* Reset the timer */
-	if (!test_bit(__E1000_DOWN, &adapter->state))
-		mod_timer(&adapter->watchdog_timer,
-			  round_jiffies(jiffies + 2 * HZ));
-}
-
-#define E1000_TX_FLAGS_CSUM		0x00000001
-#define E1000_TX_FLAGS_VLAN		0x00000002
-#define E1000_TX_FLAGS_TSO		0x00000004
-#define E1000_TX_FLAGS_IPV4		0x00000008
-#define E1000_TX_FLAGS_VLAN_MASK	0xffff0000
-#define E1000_TX_FLAGS_VLAN_SHIFT	16
-
-static int e1000_tso(struct e1000_adapter *adapter,
-		     struct sk_buff *skb)
-{
-	struct e1000_ring *tx_ring = adapter->tx_ring;
-	struct e1000_context_desc *context_desc;
-	struct e1000_buffer *buffer_info;
-	unsigned int i;
-	u32 cmd_length = 0;
-	u16 ipcse = 0, tucse, mss;
-	u8 ipcss, ipcso, tucss, tucso, hdr_len;
-
-	if (!skb_is_gso(skb))
-		return 0;
-
-	if (skb_header_cloned(skb)) {
-		int err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
-
-		if (err)
-			return err;
-	}
-
-	hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-	mss = skb_shinfo(skb)->gso_size;
-	if (skb->protocol == htons(ETH_P_IP)) {
-		struct iphdr *iph = ip_hdr(skb);
-		iph->tot_len = 0;
-		iph->check = 0;
-		tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
-		                                         0, IPPROTO_TCP, 0);
-		cmd_length = E1000_TXD_CMD_IP;
-		ipcse = skb_transport_offset(skb) - 1;
-	} else if (skb_is_gso_v6(skb)) {
-		ipv6_hdr(skb)->payload_len = 0;
-		tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
-		                                       &ipv6_hdr(skb)->daddr,
-		                                       0, IPPROTO_TCP, 0);
-		ipcse = 0;
-	}
-	ipcss = skb_network_offset(skb);
-	ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data;
-	tucss = skb_transport_offset(skb);
-	tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data;
-	tucse = 0;
-
-	cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
-	               E1000_TXD_CMD_TCP | (skb->len - (hdr_len)));
-
-	i = tx_ring->next_to_use;
-	context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
-	buffer_info = &tx_ring->buffer_info[i];
-
-	context_desc->lower_setup.ip_fields.ipcss  = ipcss;
-	context_desc->lower_setup.ip_fields.ipcso  = ipcso;
-	context_desc->lower_setup.ip_fields.ipcse  = cpu_to_le16(ipcse);
-	context_desc->upper_setup.tcp_fields.tucss = tucss;
-	context_desc->upper_setup.tcp_fields.tucso = tucso;
-	context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse);
-	context_desc->tcp_seg_setup.fields.mss     = cpu_to_le16(mss);
-	context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
-	context_desc->cmd_and_length = cpu_to_le32(cmd_length);
-
-	buffer_info->time_stamp = jiffies;
-	buffer_info->next_to_watch = i;
-
-	i++;
-	if (i == tx_ring->count)
-		i = 0;
-	tx_ring->next_to_use = i;
-
-	return 1;
-}
-
-static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
-{
-	struct e1000_ring *tx_ring = adapter->tx_ring;
-	struct e1000_context_desc *context_desc;
-	struct e1000_buffer *buffer_info;
-	unsigned int i;
-	u8 css;
-	u32 cmd_len = E1000_TXD_CMD_DEXT;
-	__be16 protocol;
-
-	if (skb->ip_summed != CHECKSUM_PARTIAL)
-		return 0;
-
-	if (skb->protocol == cpu_to_be16(ETH_P_8021Q))
-		protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
-	else
-		protocol = skb->protocol;
-
-	switch (protocol) {
-	case cpu_to_be16(ETH_P_IP):
-		if (ip_hdr(skb)->protocol == IPPROTO_TCP)
-			cmd_len |= E1000_TXD_CMD_TCP;
-		break;
-	case cpu_to_be16(ETH_P_IPV6):
-		/* XXX not handling all IPV6 headers */
-		if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
-			cmd_len |= E1000_TXD_CMD_TCP;
-		break;
-	default:
-		if (unlikely(net_ratelimit()))
-			e_warn("checksum_partial proto=%x!\n",
-			       be16_to_cpu(protocol));
-		break;
-	}
-
-	css = skb_checksum_start_offset(skb);
-
-	i = tx_ring->next_to_use;
-	buffer_info = &tx_ring->buffer_info[i];
-	context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
-
-	context_desc->lower_setup.ip_config = 0;
-	context_desc->upper_setup.tcp_fields.tucss = css;
-	context_desc->upper_setup.tcp_fields.tucso =
-				css + skb->csum_offset;
-	context_desc->upper_setup.tcp_fields.tucse = 0;
-	context_desc->tcp_seg_setup.data = 0;
-	context_desc->cmd_and_length = cpu_to_le32(cmd_len);
-
-	buffer_info->time_stamp = jiffies;
-	buffer_info->next_to_watch = i;
-
-	i++;
-	if (i == tx_ring->count)
-		i = 0;
-	tx_ring->next_to_use = i;
-
-	return 1;
-}
-
-#define E1000_MAX_PER_TXD	8192
-#define E1000_MAX_TXD_PWR	12
-
-static int e1000_tx_map(struct e1000_adapter *adapter,
-			struct sk_buff *skb, unsigned int first,
-			unsigned int max_per_txd, unsigned int nr_frags,
-			unsigned int mss)
-{
-	struct e1000_ring *tx_ring = adapter->tx_ring;
-	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_buffer *buffer_info;
-	unsigned int len = skb_headlen(skb);
-	unsigned int offset = 0, size, count = 0, i;
-	unsigned int f, bytecount, segs;
-
-	i = tx_ring->next_to_use;
-
-	while (len) {
-		buffer_info = &tx_ring->buffer_info[i];
-		size = min(len, max_per_txd);
-
-		buffer_info->length = size;
-		buffer_info->time_stamp = jiffies;
-		buffer_info->next_to_watch = i;
-		buffer_info->dma = dma_map_single(&pdev->dev,
-						  skb->data + offset,
-						  size, DMA_TO_DEVICE);
-		buffer_info->mapped_as_page = false;
-		if (dma_mapping_error(&pdev->dev, buffer_info->dma))
-			goto dma_error;
-
-		len -= size;
-		offset += size;
-		count++;
-
-		if (len) {
-			i++;
-			if (i == tx_ring->count)
-				i = 0;
-		}
-	}
-
-	for (f = 0; f < nr_frags; f++) {
-		struct skb_frag_struct *frag;
-
-		frag = &skb_shinfo(skb)->frags[f];
-		len = frag->size;
-		offset = frag->page_offset;
-
-		while (len) {
-			i++;
-			if (i == tx_ring->count)
-				i = 0;
-
-			buffer_info = &tx_ring->buffer_info[i];
-			size = min(len, max_per_txd);
-
-			buffer_info->length = size;
-			buffer_info->time_stamp = jiffies;
-			buffer_info->next_to_watch = i;
-			buffer_info->dma = dma_map_page(&pdev->dev, frag->page,
-							offset, size,
-							DMA_TO_DEVICE);
-			buffer_info->mapped_as_page = true;
-			if (dma_mapping_error(&pdev->dev, buffer_info->dma))
-				goto dma_error;
-
-			len -= size;
-			offset += size;
-			count++;
-		}
-	}
-
-	segs = skb_shinfo(skb)->gso_segs ? : 1;
-	/* multiply data chunks by size of headers */
-	bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len;
-
-	tx_ring->buffer_info[i].skb = skb;
-	tx_ring->buffer_info[i].segs = segs;
-	tx_ring->buffer_info[i].bytecount = bytecount;
-	tx_ring->buffer_info[first].next_to_watch = i;
-
-	return count;
-
-dma_error:
-	dev_err(&pdev->dev, "Tx DMA map failed\n");
-	buffer_info->dma = 0;
-	if (count)
-		count--;
-
-	while (count--) {
-		if (i == 0)
-			i += tx_ring->count;
-		i--;
-		buffer_info = &tx_ring->buffer_info[i];
-		e1000_put_txbuf(adapter, buffer_info);
-	}
-
-	return 0;
-}
-
-static void e1000_tx_queue(struct e1000_adapter *adapter,
-			   int tx_flags, int count)
-{
-	struct e1000_ring *tx_ring = adapter->tx_ring;
-	struct e1000_tx_desc *tx_desc = NULL;
-	struct e1000_buffer *buffer_info;
-	u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
-	unsigned int i;
-
-	if (tx_flags & E1000_TX_FLAGS_TSO) {
-		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
-			     E1000_TXD_CMD_TSE;
-		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
-
-		if (tx_flags & E1000_TX_FLAGS_IPV4)
-			txd_upper |= E1000_TXD_POPTS_IXSM << 8;
-	}
-
-	if (tx_flags & E1000_TX_FLAGS_CSUM) {
-		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
-		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
-	}
-
-	if (tx_flags & E1000_TX_FLAGS_VLAN) {
-		txd_lower |= E1000_TXD_CMD_VLE;
-		txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
-	}
-
-	i = tx_ring->next_to_use;
-
-	do {
-		buffer_info = &tx_ring->buffer_info[i];
-		tx_desc = E1000_TX_DESC(*tx_ring, i);
-		tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
-		tx_desc->lower.data =
-			cpu_to_le32(txd_lower | buffer_info->length);
-		tx_desc->upper.data = cpu_to_le32(txd_upper);
-
-		i++;
-		if (i == tx_ring->count)
-			i = 0;
-	} while (--count > 0);
-
-	tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
-
-	/*
-	 * Force memory writes to complete before letting h/w
-	 * know there are new descriptors to fetch.  (Only
-	 * applicable for weak-ordered memory model archs,
-	 * such as IA-64).
-	 */
-	wmb();
-
-	tx_ring->next_to_use = i;
-
-	if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
-		e1000e_update_tdt_wa(adapter, i);
-	else
-		writel(i, adapter->hw.hw_addr + tx_ring->tail);
-
-	/*
-	 * we need this if more than one processor can write to our tail
-	 * at a time, it synchronizes IO on IA64/Altix systems
-	 */
-	mmiowb();
-}
-
-#define MINIMUM_DHCP_PACKET_SIZE 282
-static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter,
-				    struct sk_buff *skb)
-{
-	struct e1000_hw *hw =  &adapter->hw;
-	u16 length, offset;
-
-	if (vlan_tx_tag_present(skb)) {
-		if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
-		    (adapter->hw.mng_cookie.status &
-			E1000_MNG_DHCP_COOKIE_STATUS_VLAN)))
-			return 0;
-	}
-
-	if (skb->len <= MINIMUM_DHCP_PACKET_SIZE)
-		return 0;
-
-	if (((struct ethhdr *) skb->data)->h_proto != htons(ETH_P_IP))
-		return 0;
-
-	{
-		const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data+14);
-		struct udphdr *udp;
-
-		if (ip->protocol != IPPROTO_UDP)
-			return 0;
-
-		udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2));
-		if (ntohs(udp->dest) != 67)
-			return 0;
-
-		offset = (u8 *)udp + 8 - skb->data;
-		length = skb->len - offset;
-		return e1000e_mng_write_dhcp_info(hw, (u8 *)udp + 8, length);
-	}
-
-	return 0;
-}
-
-static int __e1000_maybe_stop_tx(struct net_device *netdev, int size)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	netif_stop_queue(netdev);
-	/*
-	 * Herbert's original patch had:
-	 *  smp_mb__after_netif_stop_queue();
-	 * but since that doesn't exist yet, just open code it.
-	 */
-	smp_mb();
-
-	/*
-	 * We need to check again in a case another CPU has just
-	 * made room available.
-	 */
-	if (e1000_desc_unused(adapter->tx_ring) < size)
-		return -EBUSY;
-
-	/* A reprieve! */
-	netif_start_queue(netdev);
-	++adapter->restart_queue;
-	return 0;
-}
-
-static int e1000_maybe_stop_tx(struct net_device *netdev, int size)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	if (e1000_desc_unused(adapter->tx_ring) >= size)
-		return 0;
-	return __e1000_maybe_stop_tx(netdev, size);
-}
-
-#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 )
-static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
-				    struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_ring *tx_ring = adapter->tx_ring;
-	unsigned int first;
-	unsigned int max_per_txd = E1000_MAX_PER_TXD;
-	unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
-	unsigned int tx_flags = 0;
-	unsigned int len = skb_headlen(skb);
-	unsigned int nr_frags;
-	unsigned int mss;
-	int count = 0;
-	int tso;
-	unsigned int f;
-
-	if (test_bit(__E1000_DOWN, &adapter->state)) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	if (skb->len <= 0) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	mss = skb_shinfo(skb)->gso_size;
-	/*
-	 * The controller does a simple calculation to
-	 * make sure there is enough room in the FIFO before
-	 * initiating the DMA for each buffer.  The calc is:
-	 * 4 = ceil(buffer len/mss).  To make sure we don't
-	 * overrun the FIFO, adjust the max buffer len if mss
-	 * drops.
-	 */
-	if (mss) {
-		u8 hdr_len;
-		max_per_txd = min(mss << 2, max_per_txd);
-		max_txd_pwr = fls(max_per_txd) - 1;
-
-		/*
-		 * TSO Workaround for 82571/2/3 Controllers -- if skb->data
-		 * points to just header, pull a few bytes of payload from
-		 * frags into skb->data
-		 */
-		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-		/*
-		 * we do this workaround for ES2LAN, but it is un-necessary,
-		 * avoiding it could save a lot of cycles
-		 */
-		if (skb->data_len && (hdr_len == len)) {
-			unsigned int pull_size;
-
-			pull_size = min((unsigned int)4, skb->data_len);
-			if (!__pskb_pull_tail(skb, pull_size)) {
-				e_err("__pskb_pull_tail failed.\n");
-				dev_kfree_skb_any(skb);
-				return NETDEV_TX_OK;
-			}
-			len = skb_headlen(skb);
-		}
-	}
-
-	/* reserve a descriptor for the offload context */
-	if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL))
-		count++;
-	count++;
-
-	count += TXD_USE_COUNT(len, max_txd_pwr);
-
-	nr_frags = skb_shinfo(skb)->nr_frags;
-	for (f = 0; f < nr_frags; f++)
-		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
-				       max_txd_pwr);
-
-	if (adapter->hw.mac.tx_pkt_filtering)
-		e1000_transfer_dhcp_info(adapter, skb);
-
-	/*
-	 * need: count + 2 desc gap to keep tail from touching
-	 * head, otherwise try next time
-	 */
-	if (e1000_maybe_stop_tx(netdev, count + 2))
-		return NETDEV_TX_BUSY;
-
-	if (vlan_tx_tag_present(skb)) {
-		tx_flags |= E1000_TX_FLAGS_VLAN;
-		tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
-	}
-
-	first = tx_ring->next_to_use;
-
-	tso = e1000_tso(adapter, skb);
-	if (tso < 0) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	if (tso)
-		tx_flags |= E1000_TX_FLAGS_TSO;
-	else if (e1000_tx_csum(adapter, skb))
-		tx_flags |= E1000_TX_FLAGS_CSUM;
-
-	/*
-	 * Old method was to assume IPv4 packet by default if TSO was enabled.
-	 * 82571 hardware supports TSO capabilities for IPv6 as well...
-	 * no longer assume, we must.
-	 */
-	if (skb->protocol == htons(ETH_P_IP))
-		tx_flags |= E1000_TX_FLAGS_IPV4;
-
-	/* 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);
-		/* Make sure there is space in the ring for the next send. */
-		e1000_maybe_stop_tx(netdev, MAX_SKB_FRAGS + 2);
-
-	} else {
-		dev_kfree_skb_any(skb);
-		tx_ring->buffer_info[first].time_stamp = 0;
-		tx_ring->next_to_use = first;
-	}
-
-	return NETDEV_TX_OK;
-}
-
-/**
- * e1000_tx_timeout - Respond to a Tx Hang
- * @netdev: network interface device structure
- **/
-static void e1000_tx_timeout(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	/* Do the reset outside of interrupt context */
-	adapter->tx_timeout_count++;
-	schedule_work(&adapter->reset_task);
-}
-
-static void e1000_reset_task(struct work_struct *work)
-{
-	struct e1000_adapter *adapter;
-	adapter = container_of(work, struct e1000_adapter, reset_task);
-
-	/* don't run the task if already down */
-	if (test_bit(__E1000_DOWN, &adapter->state))
-		return;
-
-	if (!((adapter->flags & FLAG_RX_NEEDS_RESTART) &&
-	      (adapter->flags & FLAG_RX_RESTART_NOW))) {
-		e1000e_dump(adapter);
-		e_err("Reset adapter\n");
-	}
-	e1000e_reinit_locked(adapter);
-}
-
-/**
- * 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.
- **/
-struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
-                                             struct rtnl_link_stats64 *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;
-}
-
-/**
- * e1000_change_mtu - Change the Maximum Transfer Unit
- * @netdev: network interface device structure
- * @new_mtu: new value for maximum frame size
- *
- * Returns 0 on success, negative on failure
- **/
-static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
-
-	/* Jumbo frame support */
-	if ((max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) &&
-	    !(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) {
-		e_err("Jumbo Frames not supported.\n");
-		return -EINVAL;
-	}
-
-	/* Supported frame sizes */
-	if ((new_mtu < ETH_ZLEN + ETH_FCS_LEN + VLAN_HLEN) ||
-	    (max_frame > adapter->max_hw_frame_size)) {
-		e_err("Unsupported MTU setting\n");
-		return -EINVAL;
-	}
-
-	/* Jumbo frame workaround on 82579 requires CRC be stripped */
-	if ((adapter->hw.mac.type == e1000_pch2lan) &&
-	    !(adapter->flags2 & FLAG2_CRC_STRIPPING) &&
-	    (new_mtu > ETH_DATA_LEN)) {
-		e_err("Jumbo Frames not supported on 82579 when CRC "
-		      "stripping is disabled.\n");
-		return -EINVAL;
-	}
-
-	/* 82573 Errata 17 */
-	if (((adapter->hw.mac.type == e1000_82573) ||
-	     (adapter->hw.mac.type == e1000_82574)) &&
-	    (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN)) {
-		adapter->flags2 |= FLAG2_DISABLE_ASPM_L1;
-		e1000e_disable_aspm(adapter->pdev, PCIE_LINK_STATE_L1);
-	}
-
-	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
-		usleep_range(1000, 2000);
-	/* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */
-	adapter->max_frame_size = max_frame;
-	e_info("changing MTU from %d to %d\n", netdev->mtu, new_mtu);
-	netdev->mtu = new_mtu;
-	if (netif_running(netdev))
-		e1000e_down(adapter);
-
-	/*
-	 * NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
-	 * means we reserve 2 more, this pushes us to allocate from the next
-	 * larger slab size.
-	 * i.e. RXBUFFER_2048 --> size-4096 slab
-	 * However with the new *_jumbo_rx* routines, jumbo receives will use
-	 * fragmented skbs
-	 */
-
-	if (max_frame <= 2048)
-		adapter->rx_buffer_len = 2048;
-	else
-		adapter->rx_buffer_len = 4096;
-
-	/* adjust allocation if LPE protects us, and we aren't using SBP */
-	if ((max_frame == ETH_FRAME_LEN + ETH_FCS_LEN) ||
-	     (max_frame == ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN))
-		adapter->rx_buffer_len = ETH_FRAME_LEN + VLAN_HLEN
-					 + ETH_FCS_LEN;
-
-	if (netif_running(netdev))
-		e1000e_up(adapter);
-	else
-		e1000e_reset(adapter);
-
-	clear_bit(__E1000_RESETTING, &adapter->state);
-
-	return 0;
-}
-
-static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
-			   int cmd)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct mii_ioctl_data *data = if_mii(ifr);
-
-	if (adapter->hw.phy.media_type != e1000_media_type_copper)
-		return -EOPNOTSUPP;
-
-	switch (cmd) {
-	case SIOCGMIIPHY:
-		data->phy_id = adapter->hw.phy.addr;
-		break;
-	case SIOCGMIIREG:
-		e1000_phy_read_status(adapter);
-
-		switch (data->reg_num & 0x1F) {
-		case MII_BMCR:
-			data->val_out = adapter->phy_regs.bmcr;
-			break;
-		case MII_BMSR:
-			data->val_out = adapter->phy_regs.bmsr;
-			break;
-		case MII_PHYSID1:
-			data->val_out = (adapter->hw.phy.id >> 16);
-			break;
-		case MII_PHYSID2:
-			data->val_out = (adapter->hw.phy.id & 0xFFFF);
-			break;
-		case MII_ADVERTISE:
-			data->val_out = adapter->phy_regs.advertise;
-			break;
-		case MII_LPA:
-			data->val_out = adapter->phy_regs.lpa;
-			break;
-		case MII_EXPANSION:
-			data->val_out = adapter->phy_regs.expansion;
-			break;
-		case MII_CTRL1000:
-			data->val_out = adapter->phy_regs.ctrl1000;
-			break;
-		case MII_STAT1000:
-			data->val_out = adapter->phy_regs.stat1000;
-			break;
-		case MII_ESTATUS:
-			data->val_out = adapter->phy_regs.estatus;
-			break;
-		default:
-			return -EIO;
-		}
-		break;
-	case SIOCSMIIREG:
-	default:
-		return -EOPNOTSUPP;
-	}
-	return 0;
-}
-
-static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	switch (cmd) {
-	case SIOCGMIIPHY:
-	case SIOCGMIIREG:
-	case SIOCSMIIREG:
-		return e1000_mii_ioctl(netdev, ifr, cmd);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 i, mac_reg;
-	u16 phy_reg, wuc_enable;
-	int retval = 0;
-
-	/* copy MAC RARs to PHY RARs */
-	e1000_copy_rx_addrs_to_phy_ich8lan(hw);
-
-	retval = hw->phy.ops.acquire(hw);
-	if (retval) {
-		e_err("Could not acquire PHY\n");
-		return retval;
-	}
-
-	/* Enable access to wakeup registers on and set page to BM_WUC_PAGE */
-	retval = e1000_enable_phy_wakeup_reg_access_bm(hw, &wuc_enable);
-	if (retval)
-		goto out;
-
-	/* copy MAC MTA to PHY MTA - only needed for pchlan */
-	for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) {
-		mac_reg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i);
-		hw->phy.ops.write_reg_page(hw, BM_MTA(i),
-					   (u16)(mac_reg & 0xFFFF));
-		hw->phy.ops.write_reg_page(hw, BM_MTA(i) + 1,
-					   (u16)((mac_reg >> 16) & 0xFFFF));
-	}
-
-	/* configure PHY Rx Control register */
-	hw->phy.ops.read_reg_page(&adapter->hw, BM_RCTL, &phy_reg);
-	mac_reg = er32(RCTL);
-	if (mac_reg & E1000_RCTL_UPE)
-		phy_reg |= BM_RCTL_UPE;
-	if (mac_reg & E1000_RCTL_MPE)
-		phy_reg |= BM_RCTL_MPE;
-	phy_reg &= ~(BM_RCTL_MO_MASK);
-	if (mac_reg & E1000_RCTL_MO_3)
-		phy_reg |= (((mac_reg & E1000_RCTL_MO_3) >> E1000_RCTL_MO_SHIFT)
-				<< BM_RCTL_MO_SHIFT);
-	if (mac_reg & E1000_RCTL_BAM)
-		phy_reg |= BM_RCTL_BAM;
-	if (mac_reg & E1000_RCTL_PMCF)
-		phy_reg |= BM_RCTL_PMCF;
-	mac_reg = er32(CTRL);
-	if (mac_reg & E1000_CTRL_RFCE)
-		phy_reg |= BM_RCTL_RFCE;
-	hw->phy.ops.write_reg_page(&adapter->hw, BM_RCTL, phy_reg);
-
-	/* enable PHY wakeup in MAC register */
-	ew32(WUFC, wufc);
-	ew32(WUC, E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN);
-
-	/* configure and enable PHY wakeup in PHY registers */
-	hw->phy.ops.write_reg_page(&adapter->hw, BM_WUFC, wufc);
-	hw->phy.ops.write_reg_page(&adapter->hw, BM_WUC, E1000_WUC_PME_EN);
-
-	/* activate PHY wakeup */
-	wuc_enable |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT;
-	retval = e1000_disable_phy_wakeup_reg_access_bm(hw, &wuc_enable);
-	if (retval)
-		e_err("Could not set PHY Host Wakeup bit\n");
-out:
-	hw->phy.ops.release(hw);
-
-	return retval;
-}
-
-static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
-			    bool runtime)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u32 ctrl, ctrl_ext, rctl, status;
-	/* Runtime suspend should only enable wakeup for link changes */
-	u32 wufc = runtime ? E1000_WUFC_LNKC : adapter->wol;
-	int retval = 0;
-
-	netif_device_detach(netdev);
-
-	if (netif_running(netdev)) {
-		WARN_ON(test_bit(__E1000_RESETTING, &adapter->state));
-		e1000e_down(adapter);
-		e1000_free_irq(adapter);
-	}
-	e1000e_reset_interrupt_capability(adapter);
-
-	retval = pci_save_state(pdev);
-	if (retval)
-		return retval;
-
-	status = er32(STATUS);
-	if (status & E1000_STATUS_LU)
-		wufc &= ~E1000_WUFC_LNKC;
-
-	if (wufc) {
-		e1000_setup_rctl(adapter);
-		e1000_set_multi(netdev);
-
-		/* turn on all-multi mode if wake on multicast is enabled */
-		if (wufc & E1000_WUFC_MC) {
-			rctl = er32(RCTL);
-			rctl |= E1000_RCTL_MPE;
-			ew32(RCTL, rctl);
-		}
-
-		ctrl = er32(CTRL);
-		/* advertise wake from D3Cold */
-		#define E1000_CTRL_ADVD3WUC 0x00100000
-		/* phy power management enable */
-		#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000
-		ctrl |= E1000_CTRL_ADVD3WUC;
-		if (!(adapter->flags2 & FLAG2_HAS_PHY_WAKEUP))
-			ctrl |= E1000_CTRL_EN_PHY_PWR_MGMT;
-		ew32(CTRL, ctrl);
-
-		if (adapter->hw.phy.media_type == e1000_media_type_fiber ||
-		    adapter->hw.phy.media_type ==
-		    e1000_media_type_internal_serdes) {
-			/* keep the laser running in D3 */
-			ctrl_ext = er32(CTRL_EXT);
-			ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA;
-			ew32(CTRL_EXT, ctrl_ext);
-		}
-
-		if (adapter->flags & FLAG_IS_ICH)
-			e1000_suspend_workarounds_ich8lan(&adapter->hw);
-
-		/* Allow time for pending master requests to run */
-		e1000e_disable_pcie_master(&adapter->hw);
-
-		if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) {
-			/* enable wakeup by the PHY */
-			retval = e1000_init_phy_wakeup(adapter, wufc);
-			if (retval)
-				return retval;
-		} else {
-			/* enable wakeup by the MAC */
-			ew32(WUFC, wufc);
-			ew32(WUC, E1000_WUC_PME_EN);
-		}
-	} else {
-		ew32(WUC, 0);
-		ew32(WUFC, 0);
-	}
-
-	*enable_wake = !!wufc;
-
-	/* make sure adapter isn't asleep if manageability is enabled */
-	if ((adapter->flags & FLAG_MNG_PT_ENABLED) ||
-	    (hw->mac.ops.check_mng_mode(hw)))
-		*enable_wake = true;
-
-	if (adapter->hw.phy.type == e1000_phy_igp_3)
-		e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
-
-	/*
-	 * Release control of h/w to f/w.  If f/w is AMT enabled, this
-	 * would have already happened in close and is redundant.
-	 */
-	e1000e_release_hw_control(adapter);
-
-	pci_disable_device(pdev);
-
-	return 0;
-}
-
-static void e1000_power_off(struct pci_dev *pdev, bool sleep, bool wake)
-{
-	if (sleep && wake) {
-		pci_prepare_to_sleep(pdev);
-		return;
-	}
-
-	pci_wake_from_d3(pdev, wake);
-	pci_set_power_state(pdev, PCI_D3hot);
-}
-
-static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,
-                                    bool wake)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	/*
-	 * The pci-e switch on some quad port adapters will report a
-	 * correctable error when the MAC transitions from D0 to D3.  To
-	 * prevent this we need to mask off the correctable errors on the
-	 * downstream port of the pci-e switch.
-	 */
-	if (adapter->flags & FLAG_IS_QUAD_PORT) {
-		struct pci_dev *us_dev = pdev->bus->self;
-		int pos = pci_pcie_cap(us_dev);
-		u16 devctl;
-
-		pci_read_config_word(us_dev, pos + PCI_EXP_DEVCTL, &devctl);
-		pci_write_config_word(us_dev, pos + PCI_EXP_DEVCTL,
-		                      (devctl & ~PCI_EXP_DEVCTL_CERE));
-
-		e1000_power_off(pdev, sleep, wake);
-
-		pci_write_config_word(us_dev, pos + PCI_EXP_DEVCTL, devctl);
-	} else {
-		e1000_power_off(pdev, sleep, wake);
-	}
-}
-
-#ifdef CONFIG_PCIEASPM
-static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
-{
-	pci_disable_link_state_locked(pdev, state);
-}
-#else
-static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
-{
-	int pos;
-	u16 reg16;
-
-	/*
-	 * Both device and parent should have the same ASPM setting.
-	 * Disable ASPM in downstream component first and then upstream.
-	 */
-	pos = pci_pcie_cap(pdev);
-	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
-	reg16 &= ~state;
-	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
-
-	if (!pdev->bus->self)
-		return;
-
-	pos = pci_pcie_cap(pdev->bus->self);
-	pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, &reg16);
-	reg16 &= ~state;
-	pci_write_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, reg16);
-}
-#endif
-static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
-{
-	dev_info(&pdev->dev, "Disabling ASPM %s %s\n",
-		 (state & PCIE_LINK_STATE_L0S) ? "L0s" : "",
-		 (state & PCIE_LINK_STATE_L1) ? "L1" : "");
-
-	__e1000e_disable_aspm(pdev, state);
-}
-
-#ifdef CONFIG_PM
-static bool e1000e_pm_ready(struct e1000_adapter *adapter)
-{
-	return !!adapter->tx_ring->buffer_info;
-}
-
-static int __e1000_resume(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u16 aspm_disable_flag = 0;
-	u32 err;
-
-	if (adapter->flags2 & FLAG2_DISABLE_ASPM_L0S)
-		aspm_disable_flag = PCIE_LINK_STATE_L0S;
-	if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1)
-		aspm_disable_flag |= PCIE_LINK_STATE_L1;
-	if (aspm_disable_flag)
-		e1000e_disable_aspm(pdev, aspm_disable_flag);
-
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	pci_save_state(pdev);
-
-	e1000e_set_interrupt_capability(adapter);
-	if (netif_running(netdev)) {
-		err = e1000_request_irq(adapter);
-		if (err)
-			return err;
-	}
-
-	if (hw->mac.type == e1000_pch2lan)
-		e1000_resume_workarounds_pchlan(&adapter->hw);
-
-	e1000e_power_up_phy(adapter);
-
-	/* report the system wakeup cause from S3/S4 */
-	if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) {
-		u16 phy_data;
-
-		e1e_rphy(&adapter->hw, BM_WUS, &phy_data);
-		if (phy_data) {
-			e_info("PHY Wakeup cause - %s\n",
-				phy_data & E1000_WUS_EX ? "Unicast Packet" :
-				phy_data & E1000_WUS_MC ? "Multicast Packet" :
-				phy_data & E1000_WUS_BC ? "Broadcast Packet" :
-				phy_data & E1000_WUS_MAG ? "Magic Packet" :
-				phy_data & E1000_WUS_LNKC ? "Link Status "
-				" Change" : "other");
-		}
-		e1e_wphy(&adapter->hw, BM_WUS, ~0);
-	} else {
-		u32 wus = er32(WUS);
-		if (wus) {
-			e_info("MAC Wakeup cause - %s\n",
-				wus & E1000_WUS_EX ? "Unicast Packet" :
-				wus & E1000_WUS_MC ? "Multicast Packet" :
-				wus & E1000_WUS_BC ? "Broadcast Packet" :
-				wus & E1000_WUS_MAG ? "Magic Packet" :
-				wus & E1000_WUS_LNKC ? "Link Status Change" :
-				"other");
-		}
-		ew32(WUS, ~0);
-	}
-
-	e1000e_reset(adapter);
-
-	e1000_init_manageability_pt(adapter);
-
-	if (netif_running(netdev))
-		e1000e_up(adapter);
-
-	netif_device_attach(netdev);
-
-	/*
-	 * If the controller has AMT, do not set DRV_LOAD until the interface
-	 * is up.  For all other cases, let the f/w know that the h/w is now
-	 * under the control of the driver.
-	 */
-	if (!(adapter->flags & FLAG_HAS_AMT))
-		e1000e_get_hw_control(adapter);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int e1000_suspend(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	int retval;
-	bool wake;
-
-	retval = __e1000_shutdown(pdev, &wake, false);
-	if (!retval)
-		e1000_complete_shutdown(pdev, true, wake);
-
-	return retval;
-}
-
-static int e1000_resume(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	if (e1000e_pm_ready(adapter))
-		adapter->idle_check = true;
-
-	return __e1000_resume(pdev);
-}
-#endif /* CONFIG_PM_SLEEP */
-
-#ifdef CONFIG_PM_RUNTIME
-static int e1000_runtime_suspend(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	if (e1000e_pm_ready(adapter)) {
-		bool wake;
-
-		__e1000_shutdown(pdev, &wake, true);
-	}
-
-	return 0;
-}
-
-static int e1000_idle(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	if (!e1000e_pm_ready(adapter))
-		return 0;
-
-	if (adapter->idle_check) {
-		adapter->idle_check = false;
-		if (!e1000e_has_link(adapter))
-			pm_schedule_suspend(dev, MSEC_PER_SEC);
-	}
-
-	return -EBUSY;
-}
-
-static int e1000_runtime_resume(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	if (!e1000e_pm_ready(adapter))
-		return 0;
-
-	adapter->idle_check = !dev->power.runtime_auto;
-	return __e1000_resume(pdev);
-}
-#endif /* CONFIG_PM_RUNTIME */
-#endif /* CONFIG_PM */
-
-static void e1000_shutdown(struct pci_dev *pdev)
-{
-	bool wake = false;
-
-	__e1000_shutdown(pdev, &wake, false);
-
-	if (system_state == SYSTEM_POWER_OFF)
-		e1000_complete_shutdown(pdev, false, wake);
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-
-static irqreturn_t e1000_intr_msix(int irq, void *data)
-{
-	struct net_device *netdev = data;
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	if (adapter->msix_entries) {
-		int vector, msix_irq;
-
-		vector = 0;
-		msix_irq = adapter->msix_entries[vector].vector;
-		disable_irq(msix_irq);
-		e1000_intr_msix_rx(msix_irq, netdev);
-		enable_irq(msix_irq);
-
-		vector++;
-		msix_irq = adapter->msix_entries[vector].vector;
-		disable_irq(msix_irq);
-		e1000_intr_msix_tx(msix_irq, netdev);
-		enable_irq(msix_irq);
-
-		vector++;
-		msix_irq = adapter->msix_entries[vector].vector;
-		disable_irq(msix_irq);
-		e1000_msix_other(msix_irq, netdev);
-		enable_irq(msix_irq);
-	}
-
-	return IRQ_HANDLED;
-}
-
-/*
- * Polling 'interrupt' - used by things like netconsole to send skbs
- * without having to re-enable interrupts. It's not called while
- * the interrupt routine is executing.
- */
-static void e1000_netpoll(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	switch (adapter->int_mode) {
-	case E1000E_INT_MODE_MSIX:
-		e1000_intr_msix(adapter->pdev->irq, netdev);
-		break;
-	case E1000E_INT_MODE_MSI:
-		disable_irq(adapter->pdev->irq);
-		e1000_intr_msi(adapter->pdev->irq, netdev);
-		enable_irq(adapter->pdev->irq);
-		break;
-	default: /* E1000E_INT_MODE_LEGACY */
-		disable_irq(adapter->pdev->irq);
-		e1000_intr(adapter->pdev->irq, netdev);
-		enable_irq(adapter->pdev->irq);
-		break;
-	}
-}
-#endif
-
-/**
- * e1000_io_error_detected - called when PCI error is detected
- * @pdev: Pointer to PCI device
- * @state: The current pci connection state
- *
- * This function is called after a PCI bus error affecting
- * this device has been detected.
- */
-static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
-						pci_channel_state_t state)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	netif_device_detach(netdev);
-
-	if (state == pci_channel_io_perm_failure)
-		return PCI_ERS_RESULT_DISCONNECT;
-
-	if (netif_running(netdev))
-		e1000e_down(adapter);
-	pci_disable_device(pdev);
-
-	/* Request a slot slot reset. */
-	return PCI_ERS_RESULT_NEED_RESET;
-}
-
-/**
- * e1000_io_slot_reset - called after the pci bus has been reset.
- * @pdev: Pointer to PCI device
- *
- * Restart the card from scratch, as if from a cold-boot. Implementation
- * resembles the first-half of the e1000_resume routine.
- */
-static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-	u16 aspm_disable_flag = 0;
-	int err;
-	pci_ers_result_t result;
-
-	if (adapter->flags2 & FLAG2_DISABLE_ASPM_L0S)
-		aspm_disable_flag = PCIE_LINK_STATE_L0S;
-	if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1)
-		aspm_disable_flag |= PCIE_LINK_STATE_L1;
-	if (aspm_disable_flag)
-		e1000e_disable_aspm(pdev, aspm_disable_flag);
-
-	err = pci_enable_device_mem(pdev);
-	if (err) {
-		dev_err(&pdev->dev,
-			"Cannot re-enable PCI device after reset.\n");
-		result = PCI_ERS_RESULT_DISCONNECT;
-	} else {
-		pci_set_master(pdev);
-		pdev->state_saved = true;
-		pci_restore_state(pdev);
-
-		pci_enable_wake(pdev, PCI_D3hot, 0);
-		pci_enable_wake(pdev, PCI_D3cold, 0);
-
-		e1000e_reset(adapter);
-		ew32(WUS, ~0);
-		result = PCI_ERS_RESULT_RECOVERED;
-	}
-
-	pci_cleanup_aer_uncorrect_error_status(pdev);
-
-	return result;
-}
-
-/**
- * e1000_io_resume - called when traffic can start flowing again.
- * @pdev: Pointer to PCI device
- *
- * This callback is called when the error recovery driver tells us that
- * its OK to resume normal operation. Implementation resembles the
- * second-half of the e1000_resume routine.
- */
-static void e1000_io_resume(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	e1000_init_manageability_pt(adapter);
-
-	if (netif_running(netdev)) {
-		if (e1000e_up(adapter)) {
-			dev_err(&pdev->dev,
-				"can't bring device back up after reset\n");
-			return;
-		}
-	}
-
-	netif_device_attach(netdev);
-
-	/*
-	 * If the controller has AMT, do not set DRV_LOAD until the interface
-	 * is up.  For all other cases, let the f/w know that the h/w is now
-	 * under the control of the driver.
-	 */
-	if (!(adapter->flags & FLAG_HAS_AMT))
-		e1000e_get_hw_control(adapter);
-
-}
-
-static void e1000_print_device_info(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	u32 ret_val;
-	u8 pba_str[E1000_PBANUM_LENGTH];
-
-	/* print bus type/speed/width info */
-	e_info("(PCI Express:2.5GT/s:%s) %pM\n",
-	       /* bus width */
-	       ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" :
-	        "Width x1"),
-	       /* MAC address */
-	       netdev->dev_addr);
-	e_info("Intel(R) PRO/%s Network Connection\n",
-	       (hw->phy.type == e1000_phy_ife) ? "10/100" : "1000");
-	ret_val = e1000_read_pba_string_generic(hw, pba_str,
-						E1000_PBANUM_LENGTH);
-	if (ret_val)
-		strncpy((char *)pba_str, "Unknown", sizeof(pba_str) - 1);
-	e_info("MAC: %d, PHY: %d, PBA No: %s\n",
-	       hw->mac.type, hw->phy.type, pba_str);
-}
-
-static void e1000_eeprom_checks(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	int ret_val;
-	u16 buf = 0;
-
-	if (hw->mac.type != e1000_82573)
-		return;
-
-	ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &buf);
-	if (!ret_val && (!(le16_to_cpu(buf) & (1 << 0)))) {
-		/* Deep Smart Power Down (DSPD) */
-		dev_warn(&adapter->pdev->dev,
-			 "Warning: detected DSPD enabled in EEPROM\n");
-	}
-}
-
-static const struct net_device_ops e1000e_netdev_ops = {
-	.ndo_open		= e1000_open,
-	.ndo_stop		= e1000_close,
-	.ndo_start_xmit		= e1000_xmit_frame,
-	.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,
-	.ndo_do_ioctl		= e1000_ioctl,
-	.ndo_tx_timeout		= e1000_tx_timeout,
-	.ndo_validate_addr	= eth_validate_addr,
-
-	.ndo_vlan_rx_add_vid	= e1000_vlan_rx_add_vid,
-	.ndo_vlan_rx_kill_vid	= e1000_vlan_rx_kill_vid,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= e1000_netpoll,
-#endif
-};
-
-/**
- * e1000_probe - Device Initialization Routine
- * @pdev: PCI device information struct
- * @ent: entry in e1000_pci_tbl
- *
- * Returns 0 on success, negative on failure
- *
- * e1000_probe initializes an adapter identified by a pci_dev structure.
- * The OS initialization, configuring of the adapter private structure,
- * and a hardware reset occur.
- **/
-static int __devinit e1000_probe(struct pci_dev *pdev,
-				 const struct pci_device_id *ent)
-{
-	struct net_device *netdev;
-	struct e1000_adapter *adapter;
-	struct e1000_hw *hw;
-	const struct e1000_info *ei = e1000_info_tbl[ent->driver_data];
-	resource_size_t mmio_start, mmio_len;
-	resource_size_t flash_start, flash_len;
-
-	static int cards_found;
-	u16 aspm_disable_flag = 0;
-	int i, err, pci_using_dac;
-	u16 eeprom_data = 0;
-	u16 eeprom_apme_mask = E1000_EEPROM_APME;
-
-	if (ei->flags2 & FLAG2_DISABLE_ASPM_L0S)
-		aspm_disable_flag = PCIE_LINK_STATE_L0S;
-	if (ei->flags2 & FLAG2_DISABLE_ASPM_L1)
-		aspm_disable_flag |= PCIE_LINK_STATE_L1;
-	if (aspm_disable_flag)
-		e1000e_disable_aspm(pdev, aspm_disable_flag);
-
-	err = pci_enable_device_mem(pdev);
-	if (err)
-		return err;
-
-	pci_using_dac = 0;
-	err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
-	if (!err) {
-		err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
-		if (!err)
-			pci_using_dac = 1;
-	} else {
-		err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
-		if (err) {
-			err = dma_set_coherent_mask(&pdev->dev,
-						    DMA_BIT_MASK(32));
-			if (err) {
-				dev_err(&pdev->dev, "No usable DMA "
-					"configuration, aborting\n");
-				goto err_dma;
-			}
-		}
-	}
-
-	err = pci_request_selected_regions_exclusive(pdev,
-	                                  pci_select_bars(pdev, IORESOURCE_MEM),
-	                                  e1000e_driver_name);
-	if (err)
-		goto err_pci_reg;
-
-	/* AER (Advanced Error Reporting) hooks */
-	pci_enable_pcie_error_reporting(pdev);
-
-	pci_set_master(pdev);
-	/* PCI config space info */
-	err = pci_save_state(pdev);
-	if (err)
-		goto err_alloc_etherdev;
-
-	err = -ENOMEM;
-	netdev = alloc_etherdev(sizeof(struct e1000_adapter));
-	if (!netdev)
-		goto err_alloc_etherdev;
-
-	SET_NETDEV_DEV(netdev, &pdev->dev);
-
-	netdev->irq = pdev->irq;
-
-	pci_set_drvdata(pdev, netdev);
-	adapter = netdev_priv(netdev);
-	hw = &adapter->hw;
-	adapter->netdev = netdev;
-	adapter->pdev = pdev;
-	adapter->ei = ei;
-	adapter->pba = ei->pba;
-	adapter->flags = ei->flags;
-	adapter->flags2 = ei->flags2;
-	adapter->hw.adapter = adapter;
-	adapter->hw.mac.type = ei->mac;
-	adapter->max_hw_frame_size = ei->max_hw_frame_size;
-	adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1;
-
-	mmio_start = pci_resource_start(pdev, 0);
-	mmio_len = pci_resource_len(pdev, 0);
-
-	err = -EIO;
-	adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
-	if (!adapter->hw.hw_addr)
-		goto err_ioremap;
-
-	if ((adapter->flags & FLAG_HAS_FLASH) &&
-	    (pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
-		flash_start = pci_resource_start(pdev, 1);
-		flash_len = pci_resource_len(pdev, 1);
-		adapter->hw.flash_address = ioremap(flash_start, flash_len);
-		if (!adapter->hw.flash_address)
-			goto err_flashmap;
-	}
-
-	/* construct the net_device struct */
-	netdev->netdev_ops		= &e1000e_netdev_ops;
-	e1000e_set_ethtool_ops(netdev);
-	netdev->watchdog_timeo		= 5 * HZ;
-	netif_napi_add(netdev, &adapter->napi, e1000_clean, 64);
-	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
-
-	netdev->mem_start = mmio_start;
-	netdev->mem_end = mmio_start + mmio_len;
-
-	adapter->bd_number = cards_found++;
-
-	e1000e_check_options(adapter);
-
-	/* setup adapter struct */
-	err = e1000_sw_init(adapter);
-	if (err)
-		goto err_sw_init;
-
-	memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops));
-	memcpy(&hw->nvm.ops, ei->nvm_ops, sizeof(hw->nvm.ops));
-	memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops));
-
-	err = ei->get_variants(adapter);
-	if (err)
-		goto err_hw_init;
-
-	if ((adapter->flags & FLAG_IS_ICH) &&
-	    (adapter->flags & FLAG_READ_ONLY_NVM))
-		e1000e_write_protect_nvm_ich8lan(&adapter->hw);
-
-	hw->mac.ops.get_bus_info(&adapter->hw);
-
-	adapter->hw.phy.autoneg_wait_to_complete = 0;
-
-	/* Copper options */
-	if (adapter->hw.phy.media_type == e1000_media_type_copper) {
-		adapter->hw.phy.mdix = AUTO_ALL_MODES;
-		adapter->hw.phy.disable_polarity_correction = 0;
-		adapter->hw.phy.ms_type = e1000_ms_hw_default;
-	}
-
-	if (e1000_check_reset_block(&adapter->hw))
-		e_info("PHY reset is blocked due to SOL/IDER session.\n");
-
-	netdev->features = NETIF_F_SG |
-			   NETIF_F_HW_CSUM |
-			   NETIF_F_HW_VLAN_TX |
-			   NETIF_F_HW_VLAN_RX;
-
-	if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER)
-		netdev->features |= NETIF_F_HW_VLAN_FILTER;
-
-	netdev->features |= NETIF_F_TSO;
-	netdev->features |= NETIF_F_TSO6;
-
-	netdev->vlan_features |= NETIF_F_TSO;
-	netdev->vlan_features |= NETIF_F_TSO6;
-	netdev->vlan_features |= NETIF_F_HW_CSUM;
-	netdev->vlan_features |= NETIF_F_SG;
-
-	if (pci_using_dac) {
-		netdev->features |= NETIF_F_HIGHDMA;
-		netdev->vlan_features |= NETIF_F_HIGHDMA;
-	}
-
-	if (e1000e_enable_mng_pass_thru(&adapter->hw))
-		adapter->flags |= FLAG_MNG_PT_ENABLED;
-
-	/*
-	 * before reading the NVM, reset the controller to
-	 * put the device in a known good starting state
-	 */
-	adapter->hw.mac.ops.reset_hw(&adapter->hw);
-
-	/*
-	 * systems with ASPM and others may see the checksum fail on the first
-	 * attempt. Let's give it a few tries
-	 */
-	for (i = 0;; i++) {
-		if (e1000_validate_nvm_checksum(&adapter->hw) >= 0)
-			break;
-		if (i == 2) {
-			e_err("The NVM Checksum Is Not Valid\n");
-			err = -EIO;
-			goto err_eeprom;
-		}
-	}
-
-	e1000_eeprom_checks(adapter);
-
-	/* copy the MAC address */
-	if (e1000e_read_mac_addr(&adapter->hw))
-		e_err("NVM Read Error while reading MAC address\n");
-
-	memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
-	memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len);
-
-	if (!is_valid_ether_addr(netdev->perm_addr)) {
-		e_err("Invalid MAC Address: %pM\n", netdev->perm_addr);
-		err = -EIO;
-		goto err_eeprom;
-	}
-
-	init_timer(&adapter->watchdog_timer);
-	adapter->watchdog_timer.function = e1000_watchdog;
-	adapter->watchdog_timer.data = (unsigned long) adapter;
-
-	init_timer(&adapter->phy_info_timer);
-	adapter->phy_info_timer.function = e1000_update_phy_info;
-	adapter->phy_info_timer.data = (unsigned long) adapter;
-
-	INIT_WORK(&adapter->reset_task, e1000_reset_task);
-	INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task);
-	INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround);
-	INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task);
-	INIT_WORK(&adapter->print_hang_task, e1000_print_hw_hang);
-
-	/* Initialize link parameters. User can change them with ethtool */
-	adapter->hw.mac.autoneg = 1;
-	adapter->fc_autoneg = 1;
-	adapter->hw.fc.requested_mode = e1000_fc_default;
-	adapter->hw.fc.current_mode = e1000_fc_default;
-	adapter->hw.phy.autoneg_advertised = 0x2f;
-
-	/* ring size defaults */
-	adapter->rx_ring->count = 256;
-	adapter->tx_ring->count = 256;
-
-	/*
-	 * Initial Wake on LAN setting - If APM wake is enabled in
-	 * the EEPROM, enable the ACPI Magic Packet filter
-	 */
-	if (adapter->flags & FLAG_APME_IN_WUC) {
-		/* APME bit in EEPROM is mapped to WUC.APME */
-		eeprom_data = er32(WUC);
-		eeprom_apme_mask = E1000_WUC_APME;
-		if ((hw->mac.type > e1000_ich10lan) &&
-		    (eeprom_data & E1000_WUC_PHY_WAKE))
-			adapter->flags2 |= FLAG2_HAS_PHY_WAKEUP;
-	} else if (adapter->flags & FLAG_APME_IN_CTRL3) {
-		if (adapter->flags & FLAG_APME_CHECK_PORT_B &&
-		    (adapter->hw.bus.func == 1))
-			e1000_read_nvm(&adapter->hw,
-				NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
-		else
-			e1000_read_nvm(&adapter->hw,
-				NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
-	}
-
-	/* fetch WoL from EEPROM */
-	if (eeprom_data & eeprom_apme_mask)
-		adapter->eeprom_wol |= E1000_WUFC_MAG;
-
-	/*
-	 * now that we have the eeprom settings, apply the special cases
-	 * where the eeprom may be wrong or the board simply won't support
-	 * wake on lan on a particular port
-	 */
-	if (!(adapter->flags & FLAG_HAS_WOL))
-		adapter->eeprom_wol = 0;
-
-	/* initialize the wol settings based on the eeprom settings */
-	adapter->wol = adapter->eeprom_wol;
-	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
-
-	/* save off EEPROM version number */
-	e1000_read_nvm(&adapter->hw, 5, 1, &adapter->eeprom_vers);
-
-	/* reset the hardware with the new settings */
-	e1000e_reset(adapter);
-
-	/*
-	 * If the controller has AMT, do not set DRV_LOAD until the interface
-	 * is up.  For all other cases, let the f/w know that the h/w is now
-	 * under the control of the driver.
-	 */
-	if (!(adapter->flags & FLAG_HAS_AMT))
-		e1000e_get_hw_control(adapter);
-
-	strncpy(netdev->name, "eth%d", sizeof(netdev->name) - 1);
-	err = register_netdev(netdev);
-	if (err)
-		goto err_register;
-
-	/* carrier off reporting is important to ethtool even BEFORE open */
-	netif_carrier_off(netdev);
-
-	e1000_print_device_info(adapter);
-
-	if (pci_dev_run_wake(pdev))
-		pm_runtime_put_noidle(&pdev->dev);
-
-	return 0;
-
-err_register:
-	if (!(adapter->flags & FLAG_HAS_AMT))
-		e1000e_release_hw_control(adapter);
-err_eeprom:
-	if (!e1000_check_reset_block(&adapter->hw))
-		e1000_phy_hw_reset(&adapter->hw);
-err_hw_init:
-	kfree(adapter->tx_ring);
-	kfree(adapter->rx_ring);
-err_sw_init:
-	if (adapter->hw.flash_address)
-		iounmap(adapter->hw.flash_address);
-	e1000e_reset_interrupt_capability(adapter);
-err_flashmap:
-	iounmap(adapter->hw.hw_addr);
-err_ioremap:
-	free_netdev(netdev);
-err_alloc_etherdev:
-	pci_release_selected_regions(pdev,
-	                             pci_select_bars(pdev, IORESOURCE_MEM));
-err_pci_reg:
-err_dma:
-	pci_disable_device(pdev);
-	return err;
-}
-
-/**
- * e1000_remove - Device Removal Routine
- * @pdev: PCI device information struct
- *
- * e1000_remove is called by the PCI subsystem to alert the driver
- * that it should release a PCI device.  The could be caused by a
- * Hot-Plug event, or because the driver is going to be removed from
- * memory.
- **/
-static void __devexit e1000_remove(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	bool down = test_bit(__E1000_DOWN, &adapter->state);
-
-	/*
-	 * The timers may be rescheduled, so explicitly disable them
-	 * from being rescheduled.
-	 */
-	if (!down)
-		set_bit(__E1000_DOWN, &adapter->state);
-	del_timer_sync(&adapter->watchdog_timer);
-	del_timer_sync(&adapter->phy_info_timer);
-
-	cancel_work_sync(&adapter->reset_task);
-	cancel_work_sync(&adapter->watchdog_task);
-	cancel_work_sync(&adapter->downshift_task);
-	cancel_work_sync(&adapter->update_phy_task);
-	cancel_work_sync(&adapter->print_hang_task);
-
-	if (!(netdev->flags & IFF_UP))
-		e1000_power_down_phy(adapter);
-
-	/* Don't lie to e1000_close() down the road. */
-	if (!down)
-		clear_bit(__E1000_DOWN, &adapter->state);
-	unregister_netdev(netdev);
-
-	if (pci_dev_run_wake(pdev))
-		pm_runtime_get_noresume(&pdev->dev);
-
-	/*
-	 * Release control of h/w to f/w.  If f/w is AMT enabled, this
-	 * would have already happened in close and is redundant.
-	 */
-	e1000e_release_hw_control(adapter);
-
-	e1000e_reset_interrupt_capability(adapter);
-	kfree(adapter->tx_ring);
-	kfree(adapter->rx_ring);
-
-	iounmap(adapter->hw.hw_addr);
-	if (adapter->hw.flash_address)
-		iounmap(adapter->hw.flash_address);
-	pci_release_selected_regions(pdev,
-	                             pci_select_bars(pdev, IORESOURCE_MEM));
-
-	free_netdev(netdev);
-
-	/* AER disable */
-	pci_disable_pcie_error_reporting(pdev);
-
-	pci_disable_device(pdev);
-}
-
-/* PCI Error Recovery (ERS) */
-static struct pci_error_handlers e1000_err_handler = {
-	.error_detected = e1000_io_error_detected,
-	.slot_reset = e1000_io_slot_reset,
-	.resume = e1000_io_resume,
-};
-
-static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_COPPER), board_82571 },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_FIBER), board_82571 },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER), board_82571 },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER_LP), board_82571 },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_FIBER), board_82571 },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES), board_82571 },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_DUAL), board_82571 },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_QUAD), board_82571 },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571PT_QUAD_COPPER), board_82571 },
-
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI), board_82572 },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_COPPER), board_82572 },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_FIBER), board_82572 },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_SERDES), board_82572 },
-
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82573E), board_82573 },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82573E_IAMT), board_82573 },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82573L), board_82573 },
-
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82574L), board_82574 },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82574LA), board_82574 },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82583V), board_82583 },
-
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_DPT),
-	  board_80003es2lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_SPT),
-	  board_80003es2lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_SERDES_DPT),
-	  board_80003es2lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_SERDES_SPT),
-	  board_80003es2lan },
-
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE), board_ich8lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE_G), board_ich8lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE_GT), board_ich8lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_AMT), board_ich8lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_C), board_ich8lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M), board_ich8lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M_AMT), board_ich8lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_82567V_3), board_ich8lan },
-
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE), board_ich9lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_G), board_ich9lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_GT), board_ich9lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_AMT), board_ich9lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_C), board_ich9lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_BM), board_ich9lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M), board_ich9lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_AMT), board_ich9lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_V), board_ich9lan },
-
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LM), board_ich9lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LF), board_ich9lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_V), board_ich9lan },
-
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LM), board_ich10lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LF), board_ich10lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_V), board_ich10lan },
-
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LM), board_pchlan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LC), board_pchlan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DM), board_pchlan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DC), board_pchlan },
-
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_LM), board_pch2lan },
-	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_V), board_pch2lan },
-
-	{ }	/* terminate list */
-};
-MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
-
-#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,
-				e1000_runtime_resume, e1000_idle)
-};
-#endif
-
-/* PCI Device API Driver */
-static struct pci_driver e1000_driver = {
-	.name     = e1000e_driver_name,
-	.id_table = e1000_pci_tbl,
-	.probe    = e1000_probe,
-	.remove   = __devexit_p(e1000_remove),
-#ifdef CONFIG_PM
-	.driver.pm = &e1000_pm_ops,
-#endif
-	.shutdown = e1000_shutdown,
-	.err_handler = &e1000_err_handler
-};
-
-/**
- * e1000_init_module - Driver Registration Routine
- *
- * e1000_init_module is the first routine called when the driver is
- * loaded. All it does is register with the PCI subsystem.
- **/
-static int __init e1000_init_module(void)
-{
-	int ret;
-	pr_info("Intel(R) PRO/1000 Network Driver - %s\n",
-		e1000e_driver_version);
-	pr_info("Copyright(c) 1999 - 2011 Intel Corporation.\n");
-	ret = pci_register_driver(&e1000_driver);
-
-	return ret;
-}
-module_init(e1000_init_module);
-
-/**
- * e1000_exit_module - Driver Exit Cleanup Routine
- *
- * e1000_exit_module is called just before the driver is removed
- * from memory.
- **/
-static void __exit e1000_exit_module(void)
-{
-	pci_unregister_driver(&e1000_driver);
-}
-module_exit(e1000_exit_module);
-
-
-MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
-MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-
-/* e1000_main.c */
diff -druN linux-libre-3.1-gnu/drivers/net/e1000e/param.c linux-libre-3.2-gnu/drivers/net/e1000e/param.c
--- linux-libre-3.1-gnu/drivers/net/e1000e/param.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000e/param.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,478 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  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,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-
-#include "e1000.h"
-
-/*
- * This is the only thing that needs to be changed to adjust the
- * maximum number of ports that the driver can manage.
- */
-
-#define E1000_MAX_NIC 32
-
-#define OPTION_UNSET   -1
-#define OPTION_DISABLED 0
-#define OPTION_ENABLED  1
-
-#define COPYBREAK_DEFAULT 256
-unsigned int copybreak = COPYBREAK_DEFAULT;
-module_param(copybreak, uint, 0644);
-MODULE_PARM_DESC(copybreak,
-	"Maximum size of packet that is copied to a new buffer on receive");
-
-/*
- * All parameters are treated the same, as an integer array of values.
- * This macro just reduces the need to repeat the same declaration code
- * over and over (plus this helps to avoid typo bugs).
- */
-
-#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
-#define E1000_PARAM(X, desc)					\
-	static int __devinitdata X[E1000_MAX_NIC+1]		\
-		= E1000_PARAM_INIT;				\
-	static unsigned int num_##X;				\
-	module_param_array_named(X, X, int, &num_##X, 0);	\
-	MODULE_PARM_DESC(X, desc);
-
-/*
- * Transmit Interrupt Delay in units of 1.024 microseconds
- * Tx interrupt delay needs to typically be set to something non-zero
- *
- * Valid Range: 0-65535
- */
-E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
-#define DEFAULT_TIDV 8
-#define MAX_TXDELAY 0xFFFF
-#define MIN_TXDELAY 0
-
-/*
- * Transmit Absolute Interrupt Delay in units of 1.024 microseconds
- *
- * Valid Range: 0-65535
- */
-E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
-#define DEFAULT_TADV 32
-#define MAX_TXABSDELAY 0xFFFF
-#define MIN_TXABSDELAY 0
-
-/*
- * Receive Interrupt Delay in units of 1.024 microseconds
- * hardware will likely hang if you set this to anything but zero.
- *
- * Valid Range: 0-65535
- */
-E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
-#define MAX_RXDELAY 0xFFFF
-#define MIN_RXDELAY 0
-
-/*
- * Receive Absolute Interrupt Delay in units of 1.024 microseconds
- *
- * Valid Range: 0-65535
- */
-E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
-#define MAX_RXABSDELAY 0xFFFF
-#define MIN_RXABSDELAY 0
-
-/*
- * Interrupt Throttle Rate (interrupts/sec)
- *
- * Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
- */
-E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
-#define DEFAULT_ITR 3
-#define MAX_ITR 100000
-#define MIN_ITR 100
-
-/* IntMode (Interrupt Mode)
- *
- * Valid Range: 0 - 2
- *
- * Default Value: 2 (MSI-X)
- */
-E1000_PARAM(IntMode, "Interrupt Mode");
-#define MAX_INTMODE	2
-#define MIN_INTMODE	0
-
-/*
- * Enable Smart Power Down of the PHY
- *
- * Valid Range: 0, 1
- *
- * Default Value: 0 (disabled)
- */
-E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
-
-/*
- * Enable Kumeran Lock Loss workaround
- *
- * Valid Range: 0, 1
- *
- * Default Value: 1 (enabled)
- */
-E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround");
-
-/*
- * Write Protect NVM
- *
- * Valid Range: 0, 1
- *
- * Default Value: 1 (enabled)
- */
-E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]");
-
-/*
- * Enable CRC Stripping
- *
- * Valid Range: 0, 1
- *
- * Default Value: 1 (enabled)
- */
-E1000_PARAM(CrcStripping, "Enable CRC Stripping, disable if your BMC needs " \
-                          "the CRC");
-
-struct e1000_option {
-	enum { enable_option, range_option, list_option } type;
-	const char *name;
-	const char *err;
-	int def;
-	union {
-		struct { /* range_option info */
-			int min;
-			int max;
-		} r;
-		struct { /* list_option info */
-			int nr;
-			struct e1000_opt_list { int i; char *str; } *p;
-		} l;
-	} arg;
-};
-
-static int __devinit e1000_validate_option(unsigned int *value,
-					   const struct e1000_option *opt,
-					   struct e1000_adapter *adapter)
-{
-	if (*value == OPTION_UNSET) {
-		*value = opt->def;
-		return 0;
-	}
-
-	switch (opt->type) {
-	case enable_option:
-		switch (*value) {
-		case OPTION_ENABLED:
-			e_info("%s Enabled\n", opt->name);
-			return 0;
-		case OPTION_DISABLED:
-			e_info("%s Disabled\n", opt->name);
-			return 0;
-		}
-		break;
-	case range_option:
-		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
-			e_info("%s set to %i\n", opt->name, *value);
-			return 0;
-		}
-		break;
-	case list_option: {
-		int i;
-		struct e1000_opt_list *ent;
-
-		for (i = 0; i < opt->arg.l.nr; i++) {
-			ent = &opt->arg.l.p[i];
-			if (*value == ent->i) {
-				if (ent->str[0] != '\0')
-					e_info("%s\n", ent->str);
-				return 0;
-			}
-		}
-	}
-		break;
-	default:
-		BUG();
-	}
-
-	e_info("Invalid %s value specified (%i) %s\n", opt->name, *value,
-	       opt->err);
-	*value = opt->def;
-	return -1;
-}
-
-/**
- * e1000e_check_options - Range Checking for Command Line Parameters
- * @adapter: board private structure
- *
- * This routine checks all command line parameters for valid user
- * input.  If an invalid value is given, or if no user specified
- * value exists, a default value is used.  The final value is stored
- * in a variable in the adapter structure.
- **/
-void __devinit e1000e_check_options(struct e1000_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	int bd = adapter->bd_number;
-
-	if (bd >= E1000_MAX_NIC) {
-		e_notice("Warning: no configuration for board #%i\n", bd);
-		e_notice("Using defaults for all values\n");
-	}
-
-	{ /* Transmit Interrupt Delay */
-		static const struct e1000_option opt = {
-			.type = range_option,
-			.name = "Transmit Interrupt Delay",
-			.err  = "using default of "
-				__MODULE_STRING(DEFAULT_TIDV),
-			.def  = DEFAULT_TIDV,
-			.arg  = { .r = { .min = MIN_TXDELAY,
-					 .max = MAX_TXDELAY } }
-		};
-
-		if (num_TxIntDelay > bd) {
-			adapter->tx_int_delay = TxIntDelay[bd];
-			e1000_validate_option(&adapter->tx_int_delay, &opt,
-					      adapter);
-		} else {
-			adapter->tx_int_delay = opt.def;
-		}
-	}
-	{ /* Transmit Absolute Interrupt Delay */
-		static const struct e1000_option opt = {
-			.type = range_option,
-			.name = "Transmit Absolute Interrupt Delay",
-			.err  = "using default of "
-				__MODULE_STRING(DEFAULT_TADV),
-			.def  = DEFAULT_TADV,
-			.arg  = { .r = { .min = MIN_TXABSDELAY,
-					 .max = MAX_TXABSDELAY } }
-		};
-
-		if (num_TxAbsIntDelay > bd) {
-			adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
-			e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
-					      adapter);
-		} else {
-			adapter->tx_abs_int_delay = opt.def;
-		}
-	}
-	{ /* Receive Interrupt Delay */
-		static struct e1000_option opt = {
-			.type = range_option,
-			.name = "Receive Interrupt Delay",
-			.err  = "using default of "
-				__MODULE_STRING(DEFAULT_RDTR),
-			.def  = DEFAULT_RDTR,
-			.arg  = { .r = { .min = MIN_RXDELAY,
-					 .max = MAX_RXDELAY } }
-		};
-
-		if (num_RxIntDelay > bd) {
-			adapter->rx_int_delay = RxIntDelay[bd];
-			e1000_validate_option(&adapter->rx_int_delay, &opt,
-					      adapter);
-		} else {
-			adapter->rx_int_delay = opt.def;
-		}
-	}
-	{ /* Receive Absolute Interrupt Delay */
-		static const struct e1000_option opt = {
-			.type = range_option,
-			.name = "Receive Absolute Interrupt Delay",
-			.err  = "using default of "
-				__MODULE_STRING(DEFAULT_RADV),
-			.def  = DEFAULT_RADV,
-			.arg  = { .r = { .min = MIN_RXABSDELAY,
-					 .max = MAX_RXABSDELAY } }
-		};
-
-		if (num_RxAbsIntDelay > bd) {
-			adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
-			e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
-					      adapter);
-		} else {
-			adapter->rx_abs_int_delay = opt.def;
-		}
-	}
-	{ /* Interrupt Throttling Rate */
-		static const struct e1000_option opt = {
-			.type = range_option,
-			.name = "Interrupt Throttling Rate (ints/sec)",
-			.err  = "using default of "
-				__MODULE_STRING(DEFAULT_ITR),
-			.def  = DEFAULT_ITR,
-			.arg  = { .r = { .min = MIN_ITR,
-					 .max = MAX_ITR } }
-		};
-
-		if (num_InterruptThrottleRate > bd) {
-			adapter->itr = InterruptThrottleRate[bd];
-			switch (adapter->itr) {
-			case 0:
-				e_info("%s turned off\n", opt.name);
-				break;
-			case 1:
-				e_info("%s set to dynamic mode\n", opt.name);
-				adapter->itr_setting = adapter->itr;
-				adapter->itr = 20000;
-				break;
-			case 3:
-				e_info("%s set to dynamic conservative mode\n",
-					opt.name);
-				adapter->itr_setting = adapter->itr;
-				adapter->itr = 20000;
-				break;
-			case 4:
-				e_info("%s set to simplified (2000-8000 ints) "
-				       "mode\n", opt.name);
-				adapter->itr_setting = 4;
-				break;
-			default:
-				/*
-				 * Save the setting, because the dynamic bits
-				 * change itr.
-				 */
-				if (e1000_validate_option(&adapter->itr, &opt,
-							  adapter) &&
-				    (adapter->itr == 3)) {
-					/*
-					 * In case of invalid user value,
-					 * default to conservative mode.
-					 */
-					adapter->itr_setting = adapter->itr;
-					adapter->itr = 20000;
-				} else {
-					/*
-					 * Clear the lower two bits because
-					 * they are used as control.
-					 */
-					adapter->itr_setting =
-						adapter->itr & ~3;
-				}
-				break;
-			}
-		} else {
-			adapter->itr_setting = opt.def;
-			adapter->itr = 20000;
-		}
-	}
-	{ /* Interrupt Mode */
-		static struct e1000_option opt = {
-			.type = range_option,
-			.name = "Interrupt Mode",
-			.err  = "defaulting to 2 (MSI-X)",
-			.def  = E1000E_INT_MODE_MSIX,
-			.arg  = { .r = { .min = MIN_INTMODE,
-					 .max = MAX_INTMODE } }
-		};
-
-		if (num_IntMode > bd) {
-			unsigned int int_mode = IntMode[bd];
-			e1000_validate_option(&int_mode, &opt, adapter);
-			adapter->int_mode = int_mode;
-		} else {
-			adapter->int_mode = opt.def;
-		}
-	}
-	{ /* Smart Power Down */
-		static const struct e1000_option opt = {
-			.type = enable_option,
-			.name = "PHY Smart Power Down",
-			.err  = "defaulting to Disabled",
-			.def  = OPTION_DISABLED
-		};
-
-		if (num_SmartPowerDownEnable > bd) {
-			unsigned int spd = SmartPowerDownEnable[bd];
-			e1000_validate_option(&spd, &opt, adapter);
-			if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN)
-			    && spd)
-				adapter->flags |= FLAG_SMART_POWER_DOWN;
-		}
-	}
-	{ /* CRC Stripping */
-		static const struct e1000_option opt = {
-			.type = enable_option,
-			.name = "CRC Stripping",
-			.err  = "defaulting to Enabled",
-			.def  = OPTION_ENABLED
-		};
-
-		if (num_CrcStripping > bd) {
-			unsigned int crc_stripping = CrcStripping[bd];
-			e1000_validate_option(&crc_stripping, &opt, adapter);
-			if (crc_stripping == OPTION_ENABLED)
-				adapter->flags2 |= FLAG2_CRC_STRIPPING;
-		} else {
-			adapter->flags2 |= FLAG2_CRC_STRIPPING;
-		}
-	}
-	{ /* Kumeran Lock Loss Workaround */
-		static const struct e1000_option opt = {
-			.type = enable_option,
-			.name = "Kumeran Lock Loss Workaround",
-			.err  = "defaulting to Enabled",
-			.def  = OPTION_ENABLED
-		};
-
-		if (num_KumeranLockLoss > bd) {
-			unsigned int kmrn_lock_loss = KumeranLockLoss[bd];
-			e1000_validate_option(&kmrn_lock_loss, &opt, adapter);
-			if (hw->mac.type == e1000_ich8lan)
-				e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw,
-								kmrn_lock_loss);
-		} else {
-			if (hw->mac.type == e1000_ich8lan)
-				e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw,
-								       opt.def);
-		}
-	}
-	{ /* Write-protect NVM */
-		static const struct e1000_option opt = {
-			.type = enable_option,
-			.name = "Write-protect NVM",
-			.err  = "defaulting to Enabled",
-			.def  = OPTION_ENABLED
-		};
-
-		if (adapter->flags & FLAG_IS_ICH) {
-			if (num_WriteProtectNVM > bd) {
-				unsigned int write_protect_nvm = WriteProtectNVM[bd];
-				e1000_validate_option(&write_protect_nvm, &opt,
-						      adapter);
-				if (write_protect_nvm)
-					adapter->flags |= FLAG_READ_ONLY_NVM;
-			} else {
-				if (opt.def)
-					adapter->flags |= FLAG_READ_ONLY_NVM;
-			}
-		}
-	}
-}
diff -druN linux-libre-3.1-gnu/drivers/net/e1000e/phy.c linux-libre-3.2-gnu/drivers/net/e1000e/phy.c
--- linux-libre-3.1-gnu/drivers/net/e1000e/phy.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e1000e/phy.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3377 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/1000 Linux driver
-  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,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-#include <linux/delay.h>
-
-#include "e1000.h"
-
-static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw);
-static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw);
-static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
-static s32 e1000_wait_autoneg(struct e1000_hw *hw);
-static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg);
-static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
-					  u16 *data, bool read, bool page_set);
-static u32 e1000_get_phy_addr_for_hv_page(u32 page);
-static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
-                                          u16 *data, bool read);
-
-/* Cable length tables */
-static const u16 e1000_m88_cable_length_table[] = {
-	0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
-#define M88E1000_CABLE_LENGTH_TABLE_SIZE \
-		ARRAY_SIZE(e1000_m88_cable_length_table)
-
-static const u16 e1000_igp_2_cable_length_table[] = {
-	0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 0, 0, 0, 3,
-	6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, 6, 10, 14, 18, 22,
-	26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, 21, 26, 31, 35, 40,
-	44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, 40, 45, 51, 56, 61,
-	66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, 60, 66, 72, 77, 82,
-	87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, 83, 89, 95,
-	100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121,
-	124};
-#define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \
-		ARRAY_SIZE(e1000_igp_2_cable_length_table)
-
-#define BM_PHY_REG_PAGE(offset) \
-	((u16)(((offset) >> PHY_PAGE_SHIFT) & 0xFFFF))
-#define BM_PHY_REG_NUM(offset) \
-	((u16)(((offset) & MAX_PHY_REG_ADDRESS) |\
-	 (((offset) >> (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)) &\
-		~MAX_PHY_REG_ADDRESS)))
-
-#define HV_INTC_FC_PAGE_START             768
-#define I82578_ADDR_REG                   29
-#define I82577_ADDR_REG                   16
-#define I82577_CFG_REG                    22
-#define I82577_CFG_ASSERT_CRS_ON_TX       (1 << 15)
-#define I82577_CFG_ENABLE_DOWNSHIFT       (3 << 10) /* auto downshift 100/10 */
-#define I82577_CTRL_REG                   23
-
-/* 82577 specific PHY registers */
-#define I82577_PHY_CTRL_2            18
-#define I82577_PHY_STATUS_2          26
-#define I82577_PHY_DIAG_STATUS       31
-
-/* I82577 PHY Status 2 */
-#define I82577_PHY_STATUS2_REV_POLARITY   0x0400
-#define I82577_PHY_STATUS2_MDIX           0x0800
-#define I82577_PHY_STATUS2_SPEED_MASK     0x0300
-#define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200
-
-/* I82577 PHY Control 2 */
-#define I82577_PHY_CTRL2_AUTO_MDIX        0x0400
-#define I82577_PHY_CTRL2_FORCE_MDI_MDIX   0x0200
-
-/* I82577 PHY Diagnostics Status */
-#define I82577_DSTATUS_CABLE_LENGTH       0x03FC
-#define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2
-
-/* BM PHY Copper Specific Control 1 */
-#define BM_CS_CTRL1                       16
-
-#define HV_MUX_DATA_CTRL               PHY_REG(776, 16)
-#define HV_MUX_DATA_CTRL_GEN_TO_MAC    0x0400
-#define HV_MUX_DATA_CTRL_FORCE_SPEED   0x0004
-
-/**
- *  e1000e_check_reset_block_generic - Check if PHY reset is blocked
- *  @hw: pointer to the HW structure
- *
- *  Read the PHY management control register and check whether a PHY reset
- *  is blocked.  If a reset is not blocked return 0, otherwise
- *  return E1000_BLK_PHY_RESET (12).
- **/
-s32 e1000e_check_reset_block_generic(struct e1000_hw *hw)
-{
-	u32 manc;
-
-	manc = er32(MANC);
-
-	return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ?
-	       E1000_BLK_PHY_RESET : 0;
-}
-
-/**
- *  e1000e_get_phy_id - Retrieve the PHY ID and revision
- *  @hw: pointer to the HW structure
- *
- *  Reads the PHY registers and stores the PHY ID and possibly the PHY
- *  revision in the hardware structure.
- **/
-s32 e1000e_get_phy_id(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val = 0;
-	u16 phy_id;
-	u16 retry_count = 0;
-
-	if (!(phy->ops.read_reg))
-		goto out;
-
-	while (retry_count < 2) {
-		ret_val = e1e_rphy(hw, PHY_ID1, &phy_id);
-		if (ret_val)
-			goto out;
-
-		phy->id = (u32)(phy_id << 16);
-		udelay(20);
-		ret_val = e1e_rphy(hw, PHY_ID2, &phy_id);
-		if (ret_val)
-			goto out;
-
-		phy->id |= (u32)(phy_id & PHY_REVISION_MASK);
-		phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
-
-		if (phy->id != 0 && phy->id != PHY_REVISION_MASK)
-			goto out;
-
-		retry_count++;
-	}
-out:
-	return ret_val;
-}
-
-/**
- *  e1000e_phy_reset_dsp - Reset PHY DSP
- *  @hw: pointer to the HW structure
- *
- *  Reset the digital signal processor.
- **/
-s32 e1000e_phy_reset_dsp(struct e1000_hw *hw)
-{
-	s32 ret_val;
-
-	ret_val = e1e_wphy(hw, M88E1000_PHY_GEN_CONTROL, 0xC1);
-	if (ret_val)
-		return ret_val;
-
-	return e1e_wphy(hw, M88E1000_PHY_GEN_CONTROL, 0);
-}
-
-/**
- *  e1000e_read_phy_reg_mdic - Read MDI control register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to be read
- *  @data: pointer to the read data
- *
- *  Reads the MDI control register in the PHY at offset and stores the
- *  information read to data.
- **/
-s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	u32 i, mdic = 0;
-
-	if (offset > MAX_PHY_REG_ADDRESS) {
-		e_dbg("PHY Address %d is out of range\n", offset);
-		return -E1000_ERR_PARAM;
-	}
-
-	/*
-	 * Set up Op-code, Phy Address, and register offset in the MDI
-	 * Control register.  The MAC will take care of interfacing with the
-	 * PHY to retrieve the desired data.
-	 */
-	mdic = ((offset << E1000_MDIC_REG_SHIFT) |
-		(phy->addr << E1000_MDIC_PHY_SHIFT) |
-		(E1000_MDIC_OP_READ));
-
-	ew32(MDIC, mdic);
-
-	/*
-	 * Poll the ready bit to see if the MDI read completed
-	 * Increasing the time out as testing showed failures with
-	 * the lower time out
-	 */
-	for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
-		udelay(50);
-		mdic = er32(MDIC);
-		if (mdic & E1000_MDIC_READY)
-			break;
-	}
-	if (!(mdic & E1000_MDIC_READY)) {
-		e_dbg("MDI Read did not complete\n");
-		return -E1000_ERR_PHY;
-	}
-	if (mdic & E1000_MDIC_ERROR) {
-		e_dbg("MDI Error\n");
-		return -E1000_ERR_PHY;
-	}
-	*data = (u16) mdic;
-
-	/*
-	 * Allow some time after each MDIC transaction to avoid
-	 * reading duplicate data in the next MDIC transaction.
-	 */
-	if (hw->mac.type == e1000_pch2lan)
-		udelay(100);
-
-	return 0;
-}
-
-/**
- *  e1000e_write_phy_reg_mdic - Write MDI control register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to write to
- *  @data: data to write to register at offset
- *
- *  Writes data to MDI control register in the PHY at offset.
- **/
-s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	u32 i, mdic = 0;
-
-	if (offset > MAX_PHY_REG_ADDRESS) {
-		e_dbg("PHY Address %d is out of range\n", offset);
-		return -E1000_ERR_PARAM;
-	}
-
-	/*
-	 * Set up Op-code, Phy Address, and register offset in the MDI
-	 * Control register.  The MAC will take care of interfacing with the
-	 * PHY to retrieve the desired data.
-	 */
-	mdic = (((u32)data) |
-		(offset << E1000_MDIC_REG_SHIFT) |
-		(phy->addr << E1000_MDIC_PHY_SHIFT) |
-		(E1000_MDIC_OP_WRITE));
-
-	ew32(MDIC, mdic);
-
-	/*
-	 * Poll the ready bit to see if the MDI read completed
-	 * Increasing the time out as testing showed failures with
-	 * the lower time out
-	 */
-	for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
-		udelay(50);
-		mdic = er32(MDIC);
-		if (mdic & E1000_MDIC_READY)
-			break;
-	}
-	if (!(mdic & E1000_MDIC_READY)) {
-		e_dbg("MDI Write did not complete\n");
-		return -E1000_ERR_PHY;
-	}
-	if (mdic & E1000_MDIC_ERROR) {
-		e_dbg("MDI Error\n");
-		return -E1000_ERR_PHY;
-	}
-
-	/*
-	 * Allow some time after each MDIC transaction to avoid
-	 * reading duplicate data in the next MDIC transaction.
-	 */
-	if (hw->mac.type == e1000_pch2lan)
-		udelay(100);
-
-	return 0;
-}
-
-/**
- *  e1000e_read_phy_reg_m88 - Read m88 PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to be read
- *  @data: pointer to the read data
- *
- *  Acquires semaphore, if necessary, then reads the PHY register at offset
- *  and storing the retrieved information in data.  Release any acquired
- *  semaphores before exiting.
- **/
-s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data)
-{
-	s32 ret_val;
-
-	ret_val = hw->phy.ops.acquire(hw);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
-					   data);
-
-	hw->phy.ops.release(hw);
-
-	return ret_val;
-}
-
-/**
- *  e1000e_write_phy_reg_m88 - Write m88 PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to write to
- *  @data: data to write at register offset
- *
- *  Acquires semaphore, if necessary, then writes the data to PHY register
- *  at the offset.  Release any acquired semaphores before exiting.
- **/
-s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
-{
-	s32 ret_val;
-
-	ret_val = hw->phy.ops.acquire(hw);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
-					    data);
-
-	hw->phy.ops.release(hw);
-
-	return ret_val;
-}
-
-/**
- *  e1000_set_page_igp - Set page as on IGP-like PHY(s)
- *  @hw: pointer to the HW structure
- *  @page: page to set (shifted left when necessary)
- *
- *  Sets PHY page required for PHY register access.  Assumes semaphore is
- *  already acquired.  Note, this function sets phy.addr to 1 so the caller
- *  must set it appropriately (if necessary) after this function returns.
- **/
-s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page)
-{
-	e_dbg("Setting page 0x%x\n", page);
-
-	hw->phy.addr = 1;
-
-	return e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page);
-}
-
-/**
- *  __e1000e_read_phy_reg_igp - Read igp PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to be read
- *  @data: pointer to the read data
- *  @locked: semaphore has already been acquired or not
- *
- *  Acquires semaphore, if necessary, then reads the PHY register at offset
- *  and stores the retrieved information in data.  Release any acquired
- *  semaphores before exiting.
- **/
-static s32 __e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data,
-                                    bool locked)
-{
-	s32 ret_val = 0;
-
-	if (!locked) {
-		if (!(hw->phy.ops.acquire))
-			goto out;
-
-		ret_val = hw->phy.ops.acquire(hw);
-		if (ret_val)
-			goto out;
-	}
-
-	if (offset > MAX_PHY_MULTI_PAGE_REG) {
-		ret_val = e1000e_write_phy_reg_mdic(hw,
-						    IGP01E1000_PHY_PAGE_SELECT,
-						    (u16)offset);
-		if (ret_val)
-			goto release;
-	}
-
-	ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
-	                                  data);
-
-release:
-	if (!locked)
-		hw->phy.ops.release(hw);
-out:
-	return ret_val;
-}
-
-/**
- *  e1000e_read_phy_reg_igp - Read igp PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to be read
- *  @data: pointer to the read data
- *
- *  Acquires semaphore then reads the PHY register at offset and stores the
- *  retrieved information in data.
- *  Release the acquired semaphore before exiting.
- **/
-s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
-{
-	return __e1000e_read_phy_reg_igp(hw, offset, data, false);
-}
-
-/**
- *  e1000e_read_phy_reg_igp_locked - Read igp PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to be read
- *  @data: pointer to the read data
- *
- *  Reads the PHY register at offset and stores the retrieved information
- *  in data.  Assumes semaphore already acquired.
- **/
-s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data)
-{
-	return __e1000e_read_phy_reg_igp(hw, offset, data, true);
-}
-
-/**
- *  e1000e_write_phy_reg_igp - Write igp PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to write to
- *  @data: data to write at register offset
- *  @locked: semaphore has already been acquired or not
- *
- *  Acquires semaphore, if necessary, then writes the data to PHY register
- *  at the offset.  Release any acquired semaphores before exiting.
- **/
-static s32 __e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data,
-                                     bool locked)
-{
-	s32 ret_val = 0;
-
-	if (!locked) {
-		if (!(hw->phy.ops.acquire))
-			goto out;
-
-		ret_val = hw->phy.ops.acquire(hw);
-		if (ret_val)
-			goto out;
-	}
-
-	if (offset > MAX_PHY_MULTI_PAGE_REG) {
-		ret_val = e1000e_write_phy_reg_mdic(hw,
-						    IGP01E1000_PHY_PAGE_SELECT,
-						    (u16)offset);
-		if (ret_val)
-			goto release;
-	}
-
-	ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
-					    data);
-
-release:
-	if (!locked)
-		hw->phy.ops.release(hw);
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000e_write_phy_reg_igp - Write igp PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to write to
- *  @data: data to write at register offset
- *
- *  Acquires semaphore then writes the data to PHY register
- *  at the offset.  Release any acquired semaphores before exiting.
- **/
-s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
-{
-	return __e1000e_write_phy_reg_igp(hw, offset, data, false);
-}
-
-/**
- *  e1000e_write_phy_reg_igp_locked - Write igp PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to write to
- *  @data: data to write at register offset
- *
- *  Writes the data to PHY register at the offset.
- *  Assumes semaphore already acquired.
- **/
-s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data)
-{
-	return __e1000e_write_phy_reg_igp(hw, offset, data, true);
-}
-
-/**
- *  __e1000_read_kmrn_reg - Read kumeran register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to be read
- *  @data: pointer to the read data
- *  @locked: semaphore has already been acquired or not
- *
- *  Acquires semaphore, if necessary.  Then reads the PHY register at offset
- *  using the kumeran interface.  The information retrieved is stored in data.
- *  Release any acquired semaphores before exiting.
- **/
-static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
-                                 bool locked)
-{
-	u32 kmrnctrlsta;
-	s32 ret_val = 0;
-
-	if (!locked) {
-		if (!(hw->phy.ops.acquire))
-			goto out;
-
-		ret_val = hw->phy.ops.acquire(hw);
-		if (ret_val)
-			goto out;
-	}
-
-	kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
-		       E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
-	ew32(KMRNCTRLSTA, kmrnctrlsta);
-	e1e_flush();
-
-	udelay(2);
-
-	kmrnctrlsta = er32(KMRNCTRLSTA);
-	*data = (u16)kmrnctrlsta;
-
-	if (!locked)
-		hw->phy.ops.release(hw);
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000e_read_kmrn_reg -  Read kumeran register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to be read
- *  @data: pointer to the read data
- *
- *  Acquires semaphore then reads the PHY register at offset using the
- *  kumeran interface.  The information retrieved is stored in data.
- *  Release the acquired semaphore before exiting.
- **/
-s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data)
-{
-	return __e1000_read_kmrn_reg(hw, offset, data, false);
-}
-
-/**
- *  e1000e_read_kmrn_reg_locked -  Read kumeran register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to be read
- *  @data: pointer to the read data
- *
- *  Reads the PHY register at offset using the kumeran interface.  The
- *  information retrieved is stored in data.
- *  Assumes semaphore already acquired.
- **/
-s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data)
-{
-	return __e1000_read_kmrn_reg(hw, offset, data, true);
-}
-
-/**
- *  __e1000_write_kmrn_reg - Write kumeran register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to write to
- *  @data: data to write at register offset
- *  @locked: semaphore has already been acquired or not
- *
- *  Acquires semaphore, if necessary.  Then write the data to PHY register
- *  at the offset using the kumeran interface.  Release any acquired semaphores
- *  before exiting.
- **/
-static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
-                                  bool locked)
-{
-	u32 kmrnctrlsta;
-	s32 ret_val = 0;
-
-	if (!locked) {
-		if (!(hw->phy.ops.acquire))
-			goto out;
-
-		ret_val = hw->phy.ops.acquire(hw);
-		if (ret_val)
-			goto out;
-	}
-
-	kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
-		       E1000_KMRNCTRLSTA_OFFSET) | data;
-	ew32(KMRNCTRLSTA, kmrnctrlsta);
-	e1e_flush();
-
-	udelay(2);
-
-	if (!locked)
-		hw->phy.ops.release(hw);
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000e_write_kmrn_reg -  Write kumeran register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to write to
- *  @data: data to write at register offset
- *
- *  Acquires semaphore then writes the data to the PHY register at the offset
- *  using the kumeran interface.  Release the acquired semaphore before exiting.
- **/
-s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data)
-{
-	return __e1000_write_kmrn_reg(hw, offset, data, false);
-}
-
-/**
- *  e1000e_write_kmrn_reg_locked -  Write kumeran register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to write to
- *  @data: data to write at register offset
- *
- *  Write the data to PHY register at the offset using the kumeran interface.
- *  Assumes semaphore already acquired.
- **/
-s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data)
-{
-	return __e1000_write_kmrn_reg(hw, offset, data, true);
-}
-
-/**
- *  e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link
- *  @hw: pointer to the HW structure
- *
- *  Sets up Carrier-sense on Transmit and downshift values.
- **/
-s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 phy_data;
-
-	/* Enable CRS on Tx. This must be set for half-duplex operation. */
-	ret_val = e1e_rphy(hw, I82577_CFG_REG, &phy_data);
-	if (ret_val)
-		goto out;
-
-	phy_data |= I82577_CFG_ASSERT_CRS_ON_TX;
-
-	/* Enable downshift */
-	phy_data |= I82577_CFG_ENABLE_DOWNSHIFT;
-
-	ret_val = e1e_wphy(hw, I82577_CFG_REG, phy_data);
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000e_copper_link_setup_m88 - Setup m88 PHY's for copper link
- *  @hw: pointer to the HW structure
- *
- *  Sets up MDI/MDI-X and polarity for m88 PHY's.  If necessary, transmit clock
- *  and downshift values are set also.
- **/
-s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 phy_data;
-
-	/* Enable CRS on Tx. This must be set for half-duplex operation. */
-	ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	/* For BM PHY this bit is downshift enable */
-	if (phy->type != e1000_phy_bm)
-		phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
-
-	/*
-	 * Options:
-	 *   MDI/MDI-X = 0 (default)
-	 *   0 - Auto for all speeds
-	 *   1 - MDI mode
-	 *   2 - MDI-X mode
-	 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
-	 */
-	phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
-
-	switch (phy->mdix) {
-	case 1:
-		phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
-		break;
-	case 2:
-		phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
-		break;
-	case 3:
-		phy_data |= M88E1000_PSCR_AUTO_X_1000T;
-		break;
-	case 0:
-	default:
-		phy_data |= M88E1000_PSCR_AUTO_X_MODE;
-		break;
-	}
-
-	/*
-	 * Options:
-	 *   disable_polarity_correction = 0 (default)
-	 *       Automatic Correction for Reversed Cable Polarity
-	 *   0 - Disabled
-	 *   1 - Enabled
-	 */
-	phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
-	if (phy->disable_polarity_correction == 1)
-		phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
-
-	/* Enable downshift on BM (disabled by default) */
-	if (phy->type == e1000_phy_bm)
-		phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT;
-
-	ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
-	if (ret_val)
-		return ret_val;
-
-	if ((phy->type == e1000_phy_m88) &&
-	    (phy->revision < E1000_REVISION_4) &&
-	    (phy->id != BME1000_E_PHY_ID_R2)) {
-		/*
-		 * Force TX_CLK in the Extended PHY Specific Control Register
-		 * to 25MHz clock.
-		 */
-		ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		phy_data |= M88E1000_EPSCR_TX_CLK_25;
-
-		if ((phy->revision == 2) &&
-		    (phy->id == M88E1111_I_PHY_ID)) {
-			/* 82573L PHY - set the downshift counter to 5x. */
-			phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK;
-			phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X;
-		} else {
-			/* Configure Master and Slave downshift values */
-			phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
-				      M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
-			phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
-				     M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
-		}
-		ret_val = e1e_wphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
-		if (ret_val)
-			return ret_val;
-	}
-
-	if ((phy->type == e1000_phy_bm) && (phy->id == BME1000_E_PHY_ID_R2)) {
-		/* Set PHY page 0, register 29 to 0x0003 */
-		ret_val = e1e_wphy(hw, 29, 0x0003);
-		if (ret_val)
-			return ret_val;
-
-		/* Set PHY page 0, register 30 to 0x0000 */
-		ret_val = e1e_wphy(hw, 30, 0x0000);
-		if (ret_val)
-			return ret_val;
-	}
-
-	/* Commit the changes. */
-	ret_val = e1000e_commit_phy(hw);
-	if (ret_val) {
-		e_dbg("Error committing the PHY changes\n");
-		return ret_val;
-	}
-
-	if (phy->type == e1000_phy_82578) {
-		ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		/* 82578 PHY - set the downshift count to 1x. */
-		phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE;
-		phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK;
-		ret_val = e1e_wphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
-		if (ret_val)
-			return ret_val;
-	}
-
-	return 0;
-}
-
-/**
- *  e1000e_copper_link_setup_igp - Setup igp PHY's for copper link
- *  @hw: pointer to the HW structure
- *
- *  Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for
- *  igp PHY's.
- **/
-s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 data;
-
-	ret_val = e1000_phy_hw_reset(hw);
-	if (ret_val) {
-		e_dbg("Error resetting the PHY.\n");
-		return ret_val;
-	}
-
-	/*
-	 * Wait 100ms for MAC to configure PHY from NVM settings, to avoid
-	 * timeout issues when LFS is enabled.
-	 */
-	msleep(100);
-
-	/* disable lplu d0 during driver init */
-	ret_val = e1000_set_d0_lplu_state(hw, false);
-	if (ret_val) {
-		e_dbg("Error Disabling LPLU D0\n");
-		return ret_val;
-	}
-	/* Configure mdi-mdix settings */
-	ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CTRL, &data);
-	if (ret_val)
-		return ret_val;
-
-	data &= ~IGP01E1000_PSCR_AUTO_MDIX;
-
-	switch (phy->mdix) {
-	case 1:
-		data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
-		break;
-	case 2:
-		data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;
-		break;
-	case 0:
-	default:
-		data |= IGP01E1000_PSCR_AUTO_MDIX;
-		break;
-	}
-	ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CTRL, data);
-	if (ret_val)
-		return ret_val;
-
-	/* set auto-master slave resolution settings */
-	if (hw->mac.autoneg) {
-		/*
-		 * when autonegotiation advertisement is only 1000Mbps then we
-		 * should disable SmartSpeed and enable Auto MasterSlave
-		 * resolution as hardware default.
-		 */
-		if (phy->autoneg_advertised == ADVERTISE_1000_FULL) {
-			/* Disable SmartSpeed */
-			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   &data);
-			if (ret_val)
-				return ret_val;
-
-			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   data);
-			if (ret_val)
-				return ret_val;
-
-			/* Set auto Master/Slave resolution process */
-			ret_val = e1e_rphy(hw, PHY_1000T_CTRL, &data);
-			if (ret_val)
-				return ret_val;
-
-			data &= ~CR_1000T_MS_ENABLE;
-			ret_val = e1e_wphy(hw, PHY_1000T_CTRL, data);
-			if (ret_val)
-				return ret_val;
-		}
-
-		ret_val = e1e_rphy(hw, PHY_1000T_CTRL, &data);
-		if (ret_val)
-			return ret_val;
-
-		/* load defaults for future use */
-		phy->original_ms_type = (data & CR_1000T_MS_ENABLE) ?
-			((data & CR_1000T_MS_VALUE) ?
-			e1000_ms_force_master :
-			e1000_ms_force_slave) :
-			e1000_ms_auto;
-
-		switch (phy->ms_type) {
-		case e1000_ms_force_master:
-			data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
-			break;
-		case e1000_ms_force_slave:
-			data |= CR_1000T_MS_ENABLE;
-			data &= ~(CR_1000T_MS_VALUE);
-			break;
-		case e1000_ms_auto:
-			data &= ~CR_1000T_MS_ENABLE;
-		default:
-			break;
-		}
-		ret_val = e1e_wphy(hw, PHY_1000T_CTRL, data);
-	}
-
-	return ret_val;
-}
-
-/**
- *  e1000_phy_setup_autoneg - Configure PHY for auto-negotiation
- *  @hw: pointer to the HW structure
- *
- *  Reads the MII auto-neg advertisement register and/or the 1000T control
- *  register and if the PHY is already setup for auto-negotiation, then
- *  return successful.  Otherwise, setup advertisement and flow control to
- *  the appropriate values for the wanted auto-negotiation.
- **/
-static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 mii_autoneg_adv_reg;
-	u16 mii_1000t_ctrl_reg = 0;
-
-	phy->autoneg_advertised &= phy->autoneg_mask;
-
-	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
-	ret_val = e1e_rphy(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
-	if (ret_val)
-		return ret_val;
-
-	if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
-		/* Read the MII 1000Base-T Control Register (Address 9). */
-		ret_val = e1e_rphy(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
-		if (ret_val)
-			return ret_val;
-	}
-
-	/*
-	 * Need to parse both autoneg_advertised and fc and set up
-	 * the appropriate PHY registers.  First we will parse for
-	 * autoneg_advertised software override.  Since we can advertise
-	 * a plethora of combinations, we need to check each bit
-	 * individually.
-	 */
-
-	/*
-	 * First we clear all the 10/100 mb speed bits in the Auto-Neg
-	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
-	 * the  1000Base-T Control Register (Address 9).
-	 */
-	mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS |
-				 NWAY_AR_100TX_HD_CAPS |
-				 NWAY_AR_10T_FD_CAPS   |
-				 NWAY_AR_10T_HD_CAPS);
-	mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS);
-
-	e_dbg("autoneg_advertised %x\n", phy->autoneg_advertised);
-
-	/* Do we want to advertise 10 Mb Half Duplex? */
-	if (phy->autoneg_advertised & ADVERTISE_10_HALF) {
-		e_dbg("Advertise 10mb Half duplex\n");
-		mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
-	}
-
-	/* Do we want to advertise 10 Mb Full Duplex? */
-	if (phy->autoneg_advertised & ADVERTISE_10_FULL) {
-		e_dbg("Advertise 10mb Full duplex\n");
-		mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
-	}
-
-	/* Do we want to advertise 100 Mb Half Duplex? */
-	if (phy->autoneg_advertised & ADVERTISE_100_HALF) {
-		e_dbg("Advertise 100mb Half duplex\n");
-		mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
-	}
-
-	/* Do we want to advertise 100 Mb Full Duplex? */
-	if (phy->autoneg_advertised & ADVERTISE_100_FULL) {
-		e_dbg("Advertise 100mb Full duplex\n");
-		mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
-	}
-
-	/* We do not allow the Phy to advertise 1000 Mb Half Duplex */
-	if (phy->autoneg_advertised & ADVERTISE_1000_HALF)
-		e_dbg("Advertise 1000mb Half duplex request denied!\n");
-
-	/* Do we want to advertise 1000 Mb Full Duplex? */
-	if (phy->autoneg_advertised & ADVERTISE_1000_FULL) {
-		e_dbg("Advertise 1000mb Full duplex\n");
-		mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
-	}
-
-	/*
-	 * Check for a software override of the flow control settings, and
-	 * setup the PHY advertisement registers accordingly.  If
-	 * auto-negotiation is enabled, then software will have to set the
-	 * "PAUSE" bits to the correct value in the Auto-Negotiation
-	 * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-
-	 * negotiation.
-	 *
-	 * The possible values of the "fc" parameter 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:  No software override.  The flow control configuration
-	 *	  in the EEPROM is used.
-	 */
-	switch (hw->fc.current_mode) {
-	case e1000_fc_none:
-		/*
-		 * Flow control (Rx & Tx) is completely disabled by a
-		 * software over-ride.
-		 */
-		mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
-		break;
-	case e1000_fc_rx_pause:
-		/*
-		 * Rx Flow control is enabled, and Tx Flow control is
-		 * disabled, by a software over-ride.
-		 *
-		 * 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
-		 * (in e1000e_config_fc_after_link_up) we will disable the
-		 * hw's ability to send PAUSE frames.
-		 */
-		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
-		break;
-	case e1000_fc_tx_pause:
-		/*
-		 * Tx Flow control is enabled, and Rx Flow control is
-		 * disabled, by a software over-ride.
-		 */
-		mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
-		mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
-		break;
-	case e1000_fc_full:
-		/*
-		 * Flow control (both Rx and Tx) is enabled by a software
-		 * over-ride.
-		 */
-		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
-		break;
-	default:
-		e_dbg("Flow control param set incorrectly\n");
-		ret_val = -E1000_ERR_CONFIG;
-		return ret_val;
-	}
-
-	ret_val = e1e_wphy(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
-	if (ret_val)
-		return ret_val;
-
-	e_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
-
-	if (phy->autoneg_mask & ADVERTISE_1000_FULL)
-		ret_val = e1e_wphy(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
-
-	return ret_val;
-}
-
-/**
- *  e1000_copper_link_autoneg - Setup/Enable autoneg for copper link
- *  @hw: pointer to the HW structure
- *
- *  Performs initial bounds checking on autoneg advertisement parameter, then
- *  configure to advertise the full capability.  Setup the PHY to autoneg
- *  and restart the negotiation process between the link partner.  If
- *  autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
- **/
-static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 phy_ctrl;
-
-	/*
-	 * Perform some bounds checking on the autoneg advertisement
-	 * parameter.
-	 */
-	phy->autoneg_advertised &= phy->autoneg_mask;
-
-	/*
-	 * If autoneg_advertised is zero, we assume it was not defaulted
-	 * by the calling code so we set to advertise full capability.
-	 */
-	if (phy->autoneg_advertised == 0)
-		phy->autoneg_advertised = phy->autoneg_mask;
-
-	e_dbg("Reconfiguring auto-neg advertisement params\n");
-	ret_val = e1000_phy_setup_autoneg(hw);
-	if (ret_val) {
-		e_dbg("Error Setting up Auto-Negotiation\n");
-		return ret_val;
-	}
-	e_dbg("Restarting Auto-Neg\n");
-
-	/*
-	 * Restart auto-negotiation by setting the Auto Neg Enable bit and
-	 * the Auto Neg Restart bit in the PHY control register.
-	 */
-	ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_ctrl);
-	if (ret_val)
-		return ret_val;
-
-	phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
-	ret_val = e1e_wphy(hw, PHY_CONTROL, phy_ctrl);
-	if (ret_val)
-		return ret_val;
-
-	/*
-	 * Does the user want to wait for Auto-Neg to complete here, or
-	 * check at a later time (for example, callback routine).
-	 */
-	if (phy->autoneg_wait_to_complete) {
-		ret_val = e1000_wait_autoneg(hw);
-		if (ret_val) {
-			e_dbg("Error while waiting for "
-				 "autoneg to complete\n");
-			return ret_val;
-		}
-	}
-
-	hw->mac.get_link_status = 1;
-
-	return ret_val;
-}
-
-/**
- *  e1000e_setup_copper_link - Configure copper link settings
- *  @hw: pointer to the HW structure
- *
- *  Calls the appropriate function to configure the link for auto-neg or forced
- *  speed and duplex.  Then we check for link, once link is established calls
- *  to configure collision distance and flow control are called.  If link is
- *  not established, we return -E1000_ERR_PHY (-2).
- **/
-s32 e1000e_setup_copper_link(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	bool link;
-
-	if (hw->mac.autoneg) {
-		/*
-		 * Setup autoneg and flow control advertisement and perform
-		 * autonegotiation.
-		 */
-		ret_val = e1000_copper_link_autoneg(hw);
-		if (ret_val)
-			return ret_val;
-	} else {
-		/*
-		 * PHY will be set to 10H, 10F, 100H or 100F
-		 * depending on user settings.
-		 */
-		e_dbg("Forcing Speed and Duplex\n");
-		ret_val = e1000_phy_force_speed_duplex(hw);
-		if (ret_val) {
-			e_dbg("Error Forcing Speed and Duplex\n");
-			return ret_val;
-		}
-	}
-
-	/*
-	 * Check link status. Wait up to 100 microseconds for link to become
-	 * valid.
-	 */
-	ret_val = e1000e_phy_has_link_generic(hw,
-					     COPPER_LINK_UP_LIMIT,
-					     10,
-					     &link);
-	if (ret_val)
-		return ret_val;
-
-	if (link) {
-		e_dbg("Valid link established!!!\n");
-		e1000e_config_collision_dist(hw);
-		ret_val = e1000e_config_fc_after_link_up(hw);
-	} else {
-		e_dbg("Unable to establish link!!!\n");
-	}
-
-	return ret_val;
-}
-
-/**
- *  e1000e_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY
- *  @hw: pointer to the HW structure
- *
- *  Calls the PHY setup function to force speed and duplex.  Clears the
- *  auto-crossover to force MDI manually.  Waits for link and returns
- *  successful if link up is successful, else -E1000_ERR_PHY (-2).
- **/
-s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 phy_data;
-	bool link;
-
-	ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	e1000e_phy_force_speed_duplex_setup(hw, &phy_data);
-
-	ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data);
-	if (ret_val)
-		return ret_val;
-
-	/*
-	 * Clear Auto-Crossover to force MDI manually.  IGP requires MDI
-	 * forced whenever speed and duplex are forced.
-	 */
-	ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
-	phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
-
-	ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
-	if (ret_val)
-		return ret_val;
-
-	e_dbg("IGP PSCR: %X\n", phy_data);
-
-	udelay(1);
-
-	if (phy->autoneg_wait_to_complete) {
-		e_dbg("Waiting for forced speed/duplex link on IGP phy.\n");
-
-		ret_val = e1000e_phy_has_link_generic(hw,
-						     PHY_FORCE_LIMIT,
-						     100000,
-						     &link);
-		if (ret_val)
-			return ret_val;
-
-		if (!link)
-			e_dbg("Link taking longer than expected.\n");
-
-		/* Try once more */
-		ret_val = e1000e_phy_has_link_generic(hw,
-						     PHY_FORCE_LIMIT,
-						     100000,
-						     &link);
-		if (ret_val)
-			return ret_val;
-	}
-
-	return ret_val;
-}
-
-/**
- *  e1000e_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY
- *  @hw: pointer to the HW structure
- *
- *  Calls the PHY setup function to force speed and duplex.  Clears the
- *  auto-crossover to force MDI manually.  Resets the PHY to commit the
- *  changes.  If time expires while waiting for link up, we reset the DSP.
- *  After reset, TX_CLK and CRS on Tx must be set.  Return successful upon
- *  successful completion, else return corresponding error code.
- **/
-s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 phy_data;
-	bool link;
-
-	/*
-	 * Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
-	 * forced whenever speed and duplex are forced.
-	 */
-	ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
-	ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
-	if (ret_val)
-		return ret_val;
-
-	e_dbg("M88E1000 PSCR: %X\n", phy_data);
-
-	ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	e1000e_phy_force_speed_duplex_setup(hw, &phy_data);
-
-	ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data);
-	if (ret_val)
-		return ret_val;
-
-	/* Reset the phy to commit changes. */
-	ret_val = e1000e_commit_phy(hw);
-	if (ret_val)
-		return ret_val;
-
-	if (phy->autoneg_wait_to_complete) {
-		e_dbg("Waiting for forced speed/duplex link on M88 phy.\n");
-
-		ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
-						     100000, &link);
-		if (ret_val)
-			return ret_val;
-
-		if (!link) {
-			if (hw->phy.type != e1000_phy_m88) {
-				e_dbg("Link taking longer than expected.\n");
-			} else {
-				/*
-				 * We didn't get link.
-				 * Reset the DSP and cross our fingers.
-				 */
-				ret_val = e1e_wphy(hw, M88E1000_PHY_PAGE_SELECT,
-						   0x001d);
-				if (ret_val)
-					return ret_val;
-				ret_val = e1000e_phy_reset_dsp(hw);
-				if (ret_val)
-					return ret_val;
-			}
-		}
-
-		/* Try once more */
-		ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
-						     100000, &link);
-		if (ret_val)
-			return ret_val;
-	}
-
-	if (hw->phy.type != e1000_phy_m88)
-		return 0;
-
-	ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	/*
-	 * Resetting the phy means we need to re-force TX_CLK in the
-	 * Extended PHY Specific Control Register to 25MHz clock from
-	 * the reset value of 2.5MHz.
-	 */
-	phy_data |= M88E1000_EPSCR_TX_CLK_25;
-	ret_val = e1e_wphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
-	if (ret_val)
-		return ret_val;
-
-	/*
-	 * In addition, we must re-enable CRS on Tx for both half and full
-	 * duplex.
-	 */
-	ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
-	ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
-
-	return ret_val;
-}
-
-/**
- *  e1000_phy_force_speed_duplex_ife - Force PHY speed & duplex
- *  @hw: pointer to the HW structure
- *
- *  Forces the speed and duplex settings of the PHY.
- *  This is a function pointer entry point only called by
- *  PHY setup routines.
- **/
-s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 data;
-	bool link;
-
-	ret_val = e1e_rphy(hw, PHY_CONTROL, &data);
-	if (ret_val)
-		goto out;
-
-	e1000e_phy_force_speed_duplex_setup(hw, &data);
-
-	ret_val = e1e_wphy(hw, PHY_CONTROL, data);
-	if (ret_val)
-		goto out;
-
-	/* Disable MDI-X support for 10/100 */
-	ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data);
-	if (ret_val)
-		goto out;
-
-	data &= ~IFE_PMC_AUTO_MDIX;
-	data &= ~IFE_PMC_FORCE_MDIX;
-
-	ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, data);
-	if (ret_val)
-		goto out;
-
-	e_dbg("IFE PMC: %X\n", data);
-
-	udelay(1);
-
-	if (phy->autoneg_wait_to_complete) {
-		e_dbg("Waiting for forced speed/duplex link on IFE phy.\n");
-
-		ret_val = e1000e_phy_has_link_generic(hw,
-		                                     PHY_FORCE_LIMIT,
-		                                     100000,
-		                                     &link);
-		if (ret_val)
-			goto out;
-
-		if (!link)
-			e_dbg("Link taking longer than expected.\n");
-
-		/* Try once more */
-		ret_val = e1000e_phy_has_link_generic(hw,
-		                                     PHY_FORCE_LIMIT,
-		                                     100000,
-		                                     &link);
-		if (ret_val)
-			goto out;
-	}
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000e_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex
- *  @hw: pointer to the HW structure
- *  @phy_ctrl: pointer to current value of PHY_CONTROL
- *
- *  Forces speed and duplex on the PHY by doing the following: disable flow
- *  control, force speed/duplex on the MAC, disable auto speed detection,
- *  disable auto-negotiation, configure duplex, configure speed, configure
- *  the collision distance, write configuration to CTRL register.  The
- *  caller must write to the PHY_CONTROL register for these settings to
- *  take affect.
- **/
-void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
-{
-	struct e1000_mac_info *mac = &hw->mac;
-	u32 ctrl;
-
-	/* Turn off flow control when forcing speed/duplex */
-	hw->fc.current_mode = e1000_fc_none;
-
-	/* Force speed/duplex on the mac */
-	ctrl = er32(CTRL);
-	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
-	ctrl &= ~E1000_CTRL_SPD_SEL;
-
-	/* Disable Auto Speed Detection */
-	ctrl &= ~E1000_CTRL_ASDE;
-
-	/* Disable autoneg on the phy */
-	*phy_ctrl &= ~MII_CR_AUTO_NEG_EN;
-
-	/* Forcing Full or Half Duplex? */
-	if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) {
-		ctrl &= ~E1000_CTRL_FD;
-		*phy_ctrl &= ~MII_CR_FULL_DUPLEX;
-		e_dbg("Half Duplex\n");
-	} else {
-		ctrl |= E1000_CTRL_FD;
-		*phy_ctrl |= MII_CR_FULL_DUPLEX;
-		e_dbg("Full Duplex\n");
-	}
-
-	/* Forcing 10mb or 100mb? */
-	if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) {
-		ctrl |= E1000_CTRL_SPD_100;
-		*phy_ctrl |= MII_CR_SPEED_100;
-		*phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10);
-		e_dbg("Forcing 100mb\n");
-	} else {
-		ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
-		*phy_ctrl |= MII_CR_SPEED_10;
-		*phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
-		e_dbg("Forcing 10mb\n");
-	}
-
-	e1000e_config_collision_dist(hw);
-
-	ew32(CTRL, ctrl);
-}
-
-/**
- *  e1000e_set_d3_lplu_state - Sets low power link up state for D3
- *  @hw: pointer to the HW structure
- *  @active: boolean used to enable/disable lplu
- *
- *  Success returns 0, Failure returns 1
- *
- *  The low power link up (lplu) state is set to the power management level D3
- *  and SmartSpeed is disabled when active is true, else clear lplu for D3
- *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU
- *  is used during Dx states where the power conservation is most important.
- *  During driver activity, SmartSpeed should be enabled so performance is
- *  maintained.
- **/
-s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 data;
-
-	ret_val = e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &data);
-	if (ret_val)
-		return ret_val;
-
-	if (!active) {
-		data &= ~IGP02E1000_PM_D3_LPLU;
-		ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
-		if (ret_val)
-			return ret_val;
-		/*
-		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
-		 * during Dx states where the power conservation is most
-		 * important.  During driver activity we should enable
-		 * SmartSpeed, so performance is maintained.
-		 */
-		if (phy->smart_speed == e1000_smart_speed_on) {
-			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   &data);
-			if (ret_val)
-				return ret_val;
-
-			data |= IGP01E1000_PSCFR_SMART_SPEED;
-			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   data);
-			if (ret_val)
-				return ret_val;
-		} else if (phy->smart_speed == e1000_smart_speed_off) {
-			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   &data);
-			if (ret_val)
-				return ret_val;
-
-			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
-					   data);
-			if (ret_val)
-				return ret_val;
-		}
-	} else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
-		   (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
-		   (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
-		data |= IGP02E1000_PM_D3_LPLU;
-		ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
-		if (ret_val)
-			return ret_val;
-
-		/* When LPLU is enabled, we should disable SmartSpeed */
-		ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data);
-		if (ret_val)
-			return ret_val;
-
-		data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-		ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data);
-	}
-
-	return ret_val;
-}
-
-/**
- *  e1000e_check_downshift - Checks whether a downshift in speed occurred
- *  @hw: pointer to the HW structure
- *
- *  Success returns 0, Failure returns 1
- *
- *  A downshift is detected by querying the PHY link health.
- **/
-s32 e1000e_check_downshift(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 phy_data, offset, mask;
-
-	switch (phy->type) {
-	case e1000_phy_m88:
-	case e1000_phy_gg82563:
-	case e1000_phy_bm:
-	case e1000_phy_82578:
-		offset	= M88E1000_PHY_SPEC_STATUS;
-		mask	= M88E1000_PSSR_DOWNSHIFT;
-		break;
-	case e1000_phy_igp_2:
-	case e1000_phy_igp_3:
-		offset	= IGP01E1000_PHY_LINK_HEALTH;
-		mask	= IGP01E1000_PLHR_SS_DOWNGRADE;
-		break;
-	default:
-		/* speed downshift not supported */
-		phy->speed_downgraded = false;
-		return 0;
-	}
-
-	ret_val = e1e_rphy(hw, offset, &phy_data);
-
-	if (!ret_val)
-		phy->speed_downgraded = (phy_data & mask);
-
-	return ret_val;
-}
-
-/**
- *  e1000_check_polarity_m88 - Checks the polarity.
- *  @hw: pointer to the HW structure
- *
- *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
- *
- *  Polarity is determined based on the PHY specific status register.
- **/
-s32 e1000_check_polarity_m88(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 data;
-
-	ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &data);
-
-	if (!ret_val)
-		phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY)
-				      ? e1000_rev_polarity_reversed
-				      : e1000_rev_polarity_normal;
-
-	return ret_val;
-}
-
-/**
- *  e1000_check_polarity_igp - Checks the polarity.
- *  @hw: pointer to the HW structure
- *
- *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
- *
- *  Polarity is determined based on the PHY port status register, and the
- *  current speed (since there is no polarity at 100Mbps).
- **/
-s32 e1000_check_polarity_igp(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 data, offset, mask;
-
-	/*
-	 * Polarity is determined based on the speed of
-	 * our connection.
-	 */
-	ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_STATUS, &data);
-	if (ret_val)
-		return ret_val;
-
-	if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
-	    IGP01E1000_PSSR_SPEED_1000MBPS) {
-		offset	= IGP01E1000_PHY_PCS_INIT_REG;
-		mask	= IGP01E1000_PHY_POLARITY_MASK;
-	} else {
-		/*
-		 * This really only applies to 10Mbps since
-		 * there is no polarity for 100Mbps (always 0).
-		 */
-		offset	= IGP01E1000_PHY_PORT_STATUS;
-		mask	= IGP01E1000_PSSR_POLARITY_REVERSED;
-	}
-
-	ret_val = e1e_rphy(hw, offset, &data);
-
-	if (!ret_val)
-		phy->cable_polarity = (data & mask)
-				      ? e1000_rev_polarity_reversed
-				      : e1000_rev_polarity_normal;
-
-	return ret_val;
-}
-
-/**
- *  e1000_check_polarity_ife - Check cable polarity for IFE PHY
- *  @hw: pointer to the HW structure
- *
- *  Polarity is determined on the polarity reversal feature being enabled.
- **/
-s32 e1000_check_polarity_ife(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 phy_data, offset, mask;
-
-	/*
-	 * Polarity is determined based on the reversal feature being enabled.
-	 */
-	if (phy->polarity_correction) {
-		offset = IFE_PHY_EXTENDED_STATUS_CONTROL;
-		mask = IFE_PESC_POLARITY_REVERSED;
-	} else {
-		offset = IFE_PHY_SPECIAL_CONTROL;
-		mask = IFE_PSC_FORCE_POLARITY;
-	}
-
-	ret_val = e1e_rphy(hw, offset, &phy_data);
-
-	if (!ret_val)
-		phy->cable_polarity = (phy_data & mask)
-		                       ? e1000_rev_polarity_reversed
-		                       : e1000_rev_polarity_normal;
-
-	return ret_val;
-}
-
-/**
- *  e1000_wait_autoneg - Wait for auto-neg completion
- *  @hw: pointer to the HW structure
- *
- *  Waits for auto-negotiation to complete or for the auto-negotiation time
- *  limit to expire, which ever happens first.
- **/
-static s32 e1000_wait_autoneg(struct e1000_hw *hw)
-{
-	s32 ret_val = 0;
-	u16 i, phy_status;
-
-	/* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */
-	for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) {
-		ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status);
-		if (ret_val)
-			break;
-		ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status);
-		if (ret_val)
-			break;
-		if (phy_status & MII_SR_AUTONEG_COMPLETE)
-			break;
-		msleep(100);
-	}
-
-	/*
-	 * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
-	 * has completed.
-	 */
-	return ret_val;
-}
-
-/**
- *  e1000e_phy_has_link_generic - Polls PHY for link
- *  @hw: pointer to the HW structure
- *  @iterations: number of times to poll for link
- *  @usec_interval: delay between polling attempts
- *  @success: pointer to whether polling was successful or not
- *
- *  Polls the PHY status register for link, 'iterations' number of times.
- **/
-s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
-			       u32 usec_interval, bool *success)
-{
-	s32 ret_val = 0;
-	u16 i, phy_status;
-
-	for (i = 0; i < iterations; i++) {
-		/*
-		 * Some PHYs require the PHY_STATUS register to be read
-		 * twice due to the link bit being sticky.  No harm doing
-		 * it across the board.
-		 */
-		ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status);
-		if (ret_val)
-			/*
-			 * If the first read fails, another entity may have
-			 * ownership of the resources, wait and try again to
-			 * see if they have relinquished the resources yet.
-			 */
-			udelay(usec_interval);
-		ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status);
-		if (ret_val)
-			break;
-		if (phy_status & MII_SR_LINK_STATUS)
-			break;
-		if (usec_interval >= 1000)
-			mdelay(usec_interval/1000);
-		else
-			udelay(usec_interval);
-	}
-
-	*success = (i < iterations);
-
-	return ret_val;
-}
-
-/**
- *  e1000e_get_cable_length_m88 - Determine cable length for m88 PHY
- *  @hw: pointer to the HW structure
- *
- *  Reads the PHY specific status register to retrieve the cable length
- *  information.  The cable length is determined by averaging the minimum and
- *  maximum values to get the "average" cable length.  The m88 PHY has four
- *  possible cable length values, which are:
- *	Register Value		Cable Length
- *	0			< 50 meters
- *	1			50 - 80 meters
- *	2			80 - 110 meters
- *	3			110 - 140 meters
- *	4			> 140 meters
- **/
-s32 e1000e_get_cable_length_m88(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 phy_data, index;
-
-	ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
-	if (ret_val)
-		goto out;
-
-	index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
-	        M88E1000_PSSR_CABLE_LENGTH_SHIFT;
-	if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) {
-		ret_val = -E1000_ERR_PHY;
-		goto out;
-	}
-
-	phy->min_cable_length = e1000_m88_cable_length_table[index];
-	phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
-
-	phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000e_get_cable_length_igp_2 - Determine cable length for igp2 PHY
- *  @hw: pointer to the HW structure
- *
- *  The automatic gain control (agc) normalizes the amplitude of the
- *  received signal, adjusting for the attenuation produced by the
- *  cable.  By reading the AGC registers, which represent the
- *  combination of coarse and fine gain value, the value can be put
- *  into a lookup table to obtain the approximate cable length
- *  for each channel.
- **/
-s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 phy_data, i, agc_value = 0;
-	u16 cur_agc_index, max_agc_index = 0;
-	u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1;
-	static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = {
-	       IGP02E1000_PHY_AGC_A,
-	       IGP02E1000_PHY_AGC_B,
-	       IGP02E1000_PHY_AGC_C,
-	       IGP02E1000_PHY_AGC_D
-	};
-
-	/* Read the AGC registers for all channels */
-	for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
-		ret_val = e1e_rphy(hw, agc_reg_array[i], &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		/*
-		 * Getting bits 15:9, which represent the combination of
-		 * coarse and fine gain values.  The result is a number
-		 * that can be put into the lookup table to obtain the
-		 * approximate cable length.
-		 */
-		cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
-				IGP02E1000_AGC_LENGTH_MASK;
-
-		/* Array index bound check. */
-		if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) ||
-		    (cur_agc_index == 0))
-			return -E1000_ERR_PHY;
-
-		/* Remove min & max AGC values from calculation. */
-		if (e1000_igp_2_cable_length_table[min_agc_index] >
-		    e1000_igp_2_cable_length_table[cur_agc_index])
-			min_agc_index = cur_agc_index;
-		if (e1000_igp_2_cable_length_table[max_agc_index] <
-		    e1000_igp_2_cable_length_table[cur_agc_index])
-			max_agc_index = cur_agc_index;
-
-		agc_value += e1000_igp_2_cable_length_table[cur_agc_index];
-	}
-
-	agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] +
-		      e1000_igp_2_cable_length_table[max_agc_index]);
-	agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
-
-	/* Calculate cable length with the error range of +/- 10 meters. */
-	phy->min_cable_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
-				 (agc_value - IGP02E1000_AGC_RANGE) : 0;
-	phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE;
-
-	phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
-
-	return ret_val;
-}
-
-/**
- *  e1000e_get_phy_info_m88 - Retrieve PHY information
- *  @hw: pointer to the HW structure
- *
- *  Valid for only copper links.  Read the PHY status register (sticky read)
- *  to verify that link is up.  Read the PHY special control register to
- *  determine the polarity and 10base-T extended distance.  Read the PHY
- *  special status register to determine MDI/MDIx and current speed.  If
- *  speed is 1000, then determine cable length, local and remote receiver.
- **/
-s32 e1000e_get_phy_info_m88(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32  ret_val;
-	u16 phy_data;
-	bool link;
-
-	if (phy->media_type != e1000_media_type_copper) {
-		e_dbg("Phy info is only valid for copper media\n");
-		return -E1000_ERR_CONFIG;
-	}
-
-	ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
-	if (ret_val)
-		return ret_val;
-
-	if (!link) {
-		e_dbg("Phy info is only valid if link is up\n");
-		return -E1000_ERR_CONFIG;
-	}
-
-	ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	phy->polarity_correction = (phy_data &
-				    M88E1000_PSCR_POLARITY_REVERSAL);
-
-	ret_val = e1000_check_polarity_m88(hw);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
-	if (ret_val)
-		return ret_val;
-
-	phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX);
-
-	if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
-		ret_val = e1000_get_cable_length(hw);
-		if (ret_val)
-			return ret_val;
-
-		ret_val = e1e_rphy(hw, PHY_1000T_STATUS, &phy_data);
-		if (ret_val)
-			return ret_val;
-
-		phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS)
-				? e1000_1000t_rx_status_ok
-				: e1000_1000t_rx_status_not_ok;
-
-		phy->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS)
-				 ? e1000_1000t_rx_status_ok
-				 : e1000_1000t_rx_status_not_ok;
-	} else {
-		/* Set values to "undefined" */
-		phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
-		phy->local_rx = e1000_1000t_rx_status_undefined;
-		phy->remote_rx = e1000_1000t_rx_status_undefined;
-	}
-
-	return ret_val;
-}
-
-/**
- *  e1000e_get_phy_info_igp - Retrieve igp PHY information
- *  @hw: pointer to the HW structure
- *
- *  Read PHY status to determine if link is up.  If link is up, then
- *  set/determine 10base-T extended distance and polarity correction.  Read
- *  PHY port status to determine MDI/MDIx and speed.  Based on the speed,
- *  determine on the cable length, local and remote receiver.
- **/
-s32 e1000e_get_phy_info_igp(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 data;
-	bool link;
-
-	ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
-	if (ret_val)
-		return ret_val;
-
-	if (!link) {
-		e_dbg("Phy info is only valid if link is up\n");
-		return -E1000_ERR_CONFIG;
-	}
-
-	phy->polarity_correction = true;
-
-	ret_val = e1000_check_polarity_igp(hw);
-	if (ret_val)
-		return ret_val;
-
-	ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_STATUS, &data);
-	if (ret_val)
-		return ret_val;
-
-	phy->is_mdix = (data & IGP01E1000_PSSR_MDIX);
-
-	if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
-	    IGP01E1000_PSSR_SPEED_1000MBPS) {
-		ret_val = e1000_get_cable_length(hw);
-		if (ret_val)
-			return ret_val;
-
-		ret_val = e1e_rphy(hw, PHY_1000T_STATUS, &data);
-		if (ret_val)
-			return ret_val;
-
-		phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
-				? e1000_1000t_rx_status_ok
-				: e1000_1000t_rx_status_not_ok;
-
-		phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS)
-				 ? e1000_1000t_rx_status_ok
-				 : e1000_1000t_rx_status_not_ok;
-	} else {
-		phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
-		phy->local_rx = e1000_1000t_rx_status_undefined;
-		phy->remote_rx = e1000_1000t_rx_status_undefined;
-	}
-
-	return ret_val;
-}
-
-/**
- *  e1000_get_phy_info_ife - Retrieves various IFE PHY states
- *  @hw: pointer to the HW structure
- *
- *  Populates "phy" structure with various feature states.
- **/
-s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 data;
-	bool link;
-
-	ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
-	if (ret_val)
-		goto out;
-
-	if (!link) {
-		e_dbg("Phy info is only valid if link is up\n");
-		ret_val = -E1000_ERR_CONFIG;
-		goto out;
-	}
-
-	ret_val = e1e_rphy(hw, IFE_PHY_SPECIAL_CONTROL, &data);
-	if (ret_val)
-		goto out;
-	phy->polarity_correction = (data & IFE_PSC_AUTO_POLARITY_DISABLE)
-	                           ? false : true;
-
-	if (phy->polarity_correction) {
-		ret_val = e1000_check_polarity_ife(hw);
-		if (ret_val)
-			goto out;
-	} else {
-		/* Polarity is forced */
-		phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY)
-		                      ? e1000_rev_polarity_reversed
-		                      : e1000_rev_polarity_normal;
-	}
-
-	ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data);
-	if (ret_val)
-		goto out;
-
-	phy->is_mdix = (data & IFE_PMC_MDIX_STATUS) ? true : false;
-
-	/* The following parameters are undefined for 10/100 operation. */
-	phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
-	phy->local_rx = e1000_1000t_rx_status_undefined;
-	phy->remote_rx = e1000_1000t_rx_status_undefined;
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000e_phy_sw_reset - PHY software reset
- *  @hw: pointer to the HW structure
- *
- *  Does a software reset of the PHY by reading the PHY control register and
- *  setting/write the control register reset bit to the PHY.
- **/
-s32 e1000e_phy_sw_reset(struct e1000_hw *hw)
-{
-	s32 ret_val;
-	u16 phy_ctrl;
-
-	ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_ctrl);
-	if (ret_val)
-		return ret_val;
-
-	phy_ctrl |= MII_CR_RESET;
-	ret_val = e1e_wphy(hw, PHY_CONTROL, phy_ctrl);
-	if (ret_val)
-		return ret_val;
-
-	udelay(1);
-
-	return ret_val;
-}
-
-/**
- *  e1000e_phy_hw_reset_generic - PHY hardware reset
- *  @hw: pointer to the HW structure
- *
- *  Verify the reset block is not blocking us from resetting.  Acquire
- *  semaphore (if necessary) and read/set/write the device control reset
- *  bit in the PHY.  Wait the appropriate delay time for the device to
- *  reset and release the semaphore (if necessary).
- **/
-s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u32 ctrl;
-
-	ret_val = e1000_check_reset_block(hw);
-	if (ret_val)
-		return 0;
-
-	ret_val = phy->ops.acquire(hw);
-	if (ret_val)
-		return ret_val;
-
-	ctrl = er32(CTRL);
-	ew32(CTRL, ctrl | E1000_CTRL_PHY_RST);
-	e1e_flush();
-
-	udelay(phy->reset_delay_us);
-
-	ew32(CTRL, ctrl);
-	e1e_flush();
-
-	udelay(150);
-
-	phy->ops.release(hw);
-
-	return e1000_get_phy_cfg_done(hw);
-}
-
-/**
- *  e1000e_get_cfg_done - Generic configuration done
- *  @hw: pointer to the HW structure
- *
- *  Generic function to wait 10 milli-seconds for configuration to complete
- *  and return success.
- **/
-s32 e1000e_get_cfg_done(struct e1000_hw *hw)
-{
-	mdelay(10);
-	return 0;
-}
-
-/**
- *  e1000e_phy_init_script_igp3 - Inits the IGP3 PHY
- *  @hw: pointer to the HW structure
- *
- *  Initializes a Intel Gigabit PHY3 when an EEPROM is not present.
- **/
-s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw)
-{
-	e_dbg("Running IGP 3 PHY init script\n");
-
-	/* PHY init IGP 3 */
-	/* Enable rise/fall, 10-mode work in class-A */
-	e1e_wphy(hw, 0x2F5B, 0x9018);
-	/* Remove all caps from Replica path filter */
-	e1e_wphy(hw, 0x2F52, 0x0000);
-	/* Bias trimming for ADC, AFE and Driver (Default) */
-	e1e_wphy(hw, 0x2FB1, 0x8B24);
-	/* Increase Hybrid poly bias */
-	e1e_wphy(hw, 0x2FB2, 0xF8F0);
-	/* Add 4% to Tx amplitude in Gig mode */
-	e1e_wphy(hw, 0x2010, 0x10B0);
-	/* Disable trimming (TTT) */
-	e1e_wphy(hw, 0x2011, 0x0000);
-	/* Poly DC correction to 94.6% + 2% for all channels */
-	e1e_wphy(hw, 0x20DD, 0x249A);
-	/* ABS DC correction to 95.9% */
-	e1e_wphy(hw, 0x20DE, 0x00D3);
-	/* BG temp curve trim */
-	e1e_wphy(hw, 0x28B4, 0x04CE);
-	/* Increasing ADC OPAMP stage 1 currents to max */
-	e1e_wphy(hw, 0x2F70, 0x29E4);
-	/* Force 1000 ( required for enabling PHY regs configuration) */
-	e1e_wphy(hw, 0x0000, 0x0140);
-	/* Set upd_freq to 6 */
-	e1e_wphy(hw, 0x1F30, 0x1606);
-	/* Disable NPDFE */
-	e1e_wphy(hw, 0x1F31, 0xB814);
-	/* Disable adaptive fixed FFE (Default) */
-	e1e_wphy(hw, 0x1F35, 0x002A);
-	/* Enable FFE hysteresis */
-	e1e_wphy(hw, 0x1F3E, 0x0067);
-	/* Fixed FFE for short cable lengths */
-	e1e_wphy(hw, 0x1F54, 0x0065);
-	/* Fixed FFE for medium cable lengths */
-	e1e_wphy(hw, 0x1F55, 0x002A);
-	/* Fixed FFE for long cable lengths */
-	e1e_wphy(hw, 0x1F56, 0x002A);
-	/* Enable Adaptive Clip Threshold */
-	e1e_wphy(hw, 0x1F72, 0x3FB0);
-	/* AHT reset limit to 1 */
-	e1e_wphy(hw, 0x1F76, 0xC0FF);
-	/* Set AHT master delay to 127 msec */
-	e1e_wphy(hw, 0x1F77, 0x1DEC);
-	/* Set scan bits for AHT */
-	e1e_wphy(hw, 0x1F78, 0xF9EF);
-	/* Set AHT Preset bits */
-	e1e_wphy(hw, 0x1F79, 0x0210);
-	/* Change integ_factor of channel A to 3 */
-	e1e_wphy(hw, 0x1895, 0x0003);
-	/* Change prop_factor of channels BCD to 8 */
-	e1e_wphy(hw, 0x1796, 0x0008);
-	/* Change cg_icount + enable integbp for channels BCD */
-	e1e_wphy(hw, 0x1798, 0xD008);
-	/*
-	 * Change cg_icount + enable integbp + change prop_factor_master
-	 * to 8 for channel A
-	 */
-	e1e_wphy(hw, 0x1898, 0xD918);
-	/* Disable AHT in Slave mode on channel A */
-	e1e_wphy(hw, 0x187A, 0x0800);
-	/*
-	 * Enable LPLU and disable AN to 1000 in non-D0a states,
-	 * Enable SPD+B2B
-	 */
-	e1e_wphy(hw, 0x0019, 0x008D);
-	/* Enable restart AN on an1000_dis change */
-	e1e_wphy(hw, 0x001B, 0x2080);
-	/* Enable wh_fifo read clock in 10/100 modes */
-	e1e_wphy(hw, 0x0014, 0x0045);
-	/* Restart AN, Speed selection is 1000 */
-	e1e_wphy(hw, 0x0000, 0x1340);
-
-	return 0;
-}
-
-/* Internal function pointers */
-
-/**
- *  e1000_get_phy_cfg_done - Generic PHY configuration done
- *  @hw: pointer to the HW structure
- *
- *  Return success if silicon family did not implement a family specific
- *  get_cfg_done function.
- **/
-static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw)
-{
-	if (hw->phy.ops.get_cfg_done)
-		return hw->phy.ops.get_cfg_done(hw);
-
-	return 0;
-}
-
-/**
- *  e1000_phy_force_speed_duplex - Generic force PHY speed/duplex
- *  @hw: pointer to the HW structure
- *
- *  When the silicon family has not implemented a forced speed/duplex
- *  function for the PHY, simply return 0.
- **/
-static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
-{
-	if (hw->phy.ops.force_speed_duplex)
-		return hw->phy.ops.force_speed_duplex(hw);
-
-	return 0;
-}
-
-/**
- *  e1000e_get_phy_type_from_id - Get PHY type from id
- *  @phy_id: phy_id read from the phy
- *
- *  Returns the phy type from the id.
- **/
-enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id)
-{
-	enum e1000_phy_type phy_type = e1000_phy_unknown;
-
-	switch (phy_id) {
-	case M88E1000_I_PHY_ID:
-	case M88E1000_E_PHY_ID:
-	case M88E1111_I_PHY_ID:
-	case M88E1011_I_PHY_ID:
-		phy_type = e1000_phy_m88;
-		break;
-	case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */
-		phy_type = e1000_phy_igp_2;
-		break;
-	case GG82563_E_PHY_ID:
-		phy_type = e1000_phy_gg82563;
-		break;
-	case IGP03E1000_E_PHY_ID:
-		phy_type = e1000_phy_igp_3;
-		break;
-	case IFE_E_PHY_ID:
-	case IFE_PLUS_E_PHY_ID:
-	case IFE_C_E_PHY_ID:
-		phy_type = e1000_phy_ife;
-		break;
-	case BME1000_E_PHY_ID:
-	case BME1000_E_PHY_ID_R2:
-		phy_type = e1000_phy_bm;
-		break;
-	case I82578_E_PHY_ID:
-		phy_type = e1000_phy_82578;
-		break;
-	case I82577_E_PHY_ID:
-		phy_type = e1000_phy_82577;
-		break;
-	case I82579_E_PHY_ID:
-		phy_type = e1000_phy_82579;
-		break;
-	default:
-		phy_type = e1000_phy_unknown;
-		break;
-	}
-	return phy_type;
-}
-
-/**
- *  e1000e_determine_phy_address - Determines PHY address.
- *  @hw: pointer to the HW structure
- *
- *  This uses a trial and error method to loop through possible PHY
- *  addresses. It tests each by reading the PHY ID registers and
- *  checking for a match.
- **/
-s32 e1000e_determine_phy_address(struct e1000_hw *hw)
-{
-	s32 ret_val = -E1000_ERR_PHY_TYPE;
-	u32 phy_addr = 0;
-	u32 i;
-	enum e1000_phy_type phy_type = e1000_phy_unknown;
-
-	hw->phy.id = phy_type;
-
-	for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) {
-		hw->phy.addr = phy_addr;
-		i = 0;
-
-		do {
-			e1000e_get_phy_id(hw);
-			phy_type = e1000e_get_phy_type_from_id(hw->phy.id);
-
-			/*
-			 * If phy_type is valid, break - we found our
-			 * PHY address
-			 */
-			if (phy_type  != e1000_phy_unknown) {
-				ret_val = 0;
-				goto out;
-			}
-			usleep_range(1000, 2000);
-			i++;
-		} while (i < 10);
-	}
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_get_phy_addr_for_bm_page - Retrieve PHY page address
- *  @page: page to access
- *
- *  Returns the phy address for the page requested.
- **/
-static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg)
-{
-	u32 phy_addr = 2;
-
-	if ((page >= 768) || (page == 0 && reg == 25) || (reg == 31))
-		phy_addr = 1;
-
-	return phy_addr;
-}
-
-/**
- *  e1000e_write_phy_reg_bm - Write BM PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to write to
- *  @data: data to write at register offset
- *
- *  Acquires semaphore, if necessary, then writes the data to PHY register
- *  at the offset.  Release any acquired semaphores before exiting.
- **/
-s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
-{
-	s32 ret_val;
-	u32 page = offset >> IGP_PAGE_SHIFT;
-
-	ret_val = hw->phy.ops.acquire(hw);
-	if (ret_val)
-		return ret_val;
-
-	/* Page 800 works differently than the rest so it has its own func */
-	if (page == BM_WUC_PAGE) {
-		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
-							 false, false);
-		goto out;
-	}
-
-	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
-		 * phy address 1.
-		 */
-		if (hw->phy.addr == 1) {
-			page_shift = IGP_PAGE_SHIFT;
-			page_select = IGP01E1000_PHY_PAGE_SELECT;
-		} else {
-			page_shift = 0;
-			page_select = BM_PHY_PAGE_SELECT;
-		}
-
-		/* Page is shifted left, PHY expects (page x 32) */
-		ret_val = e1000e_write_phy_reg_mdic(hw, page_select,
-		                                    (page << page_shift));
-		if (ret_val)
-			goto out;
-	}
-
-	ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
-	                                    data);
-
-out:
-	hw->phy.ops.release(hw);
-	return ret_val;
-}
-
-/**
- *  e1000e_read_phy_reg_bm - Read BM PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to be read
- *  @data: pointer to the read data
- *
- *  Acquires semaphore, if necessary, then reads the PHY register at offset
- *  and storing the retrieved information in data.  Release any acquired
- *  semaphores before exiting.
- **/
-s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
-{
-	s32 ret_val;
-	u32 page = offset >> IGP_PAGE_SHIFT;
-
-	ret_val = hw->phy.ops.acquire(hw);
-	if (ret_val)
-		return ret_val;
-
-	/* Page 800 works differently than the rest so it has its own func */
-	if (page == BM_WUC_PAGE) {
-		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
-							 true, false);
-		goto out;
-	}
-
-	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
-		 * phy address 1.
-		 */
-		if (hw->phy.addr == 1) {
-			page_shift = IGP_PAGE_SHIFT;
-			page_select = IGP01E1000_PHY_PAGE_SELECT;
-		} else {
-			page_shift = 0;
-			page_select = BM_PHY_PAGE_SELECT;
-		}
-
-		/* Page is shifted left, PHY expects (page x 32) */
-		ret_val = e1000e_write_phy_reg_mdic(hw, page_select,
-		                                    (page << page_shift));
-		if (ret_val)
-			goto out;
-	}
-
-	ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
-	                                   data);
-out:
-	hw->phy.ops.release(hw);
-	return ret_val;
-}
-
-/**
- *  e1000e_read_phy_reg_bm2 - Read BM PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to be read
- *  @data: pointer to the read data
- *
- *  Acquires semaphore, if necessary, then reads the PHY register at offset
- *  and storing the retrieved information in data.  Release any acquired
- *  semaphores before exiting.
- **/
-s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
-{
-	s32 ret_val;
-	u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
-
-	ret_val = hw->phy.ops.acquire(hw);
-	if (ret_val)
-		return ret_val;
-
-	/* Page 800 works differently than the rest so it has its own func */
-	if (page == BM_WUC_PAGE) {
-		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
-							 true, false);
-		goto out;
-	}
-
-	hw->phy.addr = 1;
-
-	if (offset > MAX_PHY_MULTI_PAGE_REG) {
-
-		/* Page is shifted left, PHY expects (page x 32) */
-		ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
-						    page);
-
-		if (ret_val)
-			goto out;
-	}
-
-	ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
-					   data);
-out:
-	hw->phy.ops.release(hw);
-	return ret_val;
-}
-
-/**
- *  e1000e_write_phy_reg_bm2 - Write BM PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to write to
- *  @data: data to write at register offset
- *
- *  Acquires semaphore, if necessary, then writes the data to PHY register
- *  at the offset.  Release any acquired semaphores before exiting.
- **/
-s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
-{
-	s32 ret_val;
-	u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
-
-	ret_val = hw->phy.ops.acquire(hw);
-	if (ret_val)
-		return ret_val;
-
-	/* Page 800 works differently than the rest so it has its own func */
-	if (page == BM_WUC_PAGE) {
-		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
-							 false, false);
-		goto out;
-	}
-
-	hw->phy.addr = 1;
-
-	if (offset > MAX_PHY_MULTI_PAGE_REG) {
-		/* Page is shifted left, PHY expects (page x 32) */
-		ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
-						    page);
-
-		if (ret_val)
-			goto out;
-	}
-
-	ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
-					    data);
-
-out:
-	hw->phy.ops.release(hw);
-	return ret_val;
-}
-
-/**
- *  e1000_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers
- *  @hw: pointer to the HW structure
- *  @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG
- *
- *  Assumes semaphore already acquired and phy_reg points to a valid memory
- *  address to store contents of the BM_WUC_ENABLE_REG register.
- **/
-s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
-{
-	s32 ret_val;
-	u16 temp;
-
-	/* All page select, port ctrl and wakeup registers use phy address 1 */
-	hw->phy.addr = 1;
-
-	/* Select Port Control Registers page */
-	ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
-	if (ret_val) {
-		e_dbg("Could not set Port Control page\n");
-		goto out;
-	}
-
-	ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
-	if (ret_val) {
-		e_dbg("Could not read PHY register %d.%d\n",
-		      BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
-		goto out;
-	}
-
-	/*
-	 * Enable both PHY wakeup mode and Wakeup register page writes.
-	 * Prevent a power state change by disabling ME and Host PHY wakeup.
-	 */
-	temp = *phy_reg;
-	temp |= BM_WUC_ENABLE_BIT;
-	temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT);
-
-	ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, temp);
-	if (ret_val) {
-		e_dbg("Could not write PHY register %d.%d\n",
-		      BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
-		goto out;
-	}
-
-	/* Select Host Wakeup Registers page */
-	ret_val = e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT));
-
-	/* caller now able to write registers on the Wakeup registers page */
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs
- *  @hw: pointer to the HW structure
- *  @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG
- *
- *  Restore BM_WUC_ENABLE_REG to its original value.
- *
- *  Assumes semaphore already acquired and *phy_reg is the contents of the
- *  BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by
- *  caller.
- **/
-s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
-{
-	s32 ret_val = 0;
-
-	/* Select Port Control Registers page */
-	ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
-	if (ret_val) {
-		e_dbg("Could not set Port Control page\n");
-		goto out;
-	}
-
-	/* Restore 769.17 to its original value */
-	ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, *phy_reg);
-	if (ret_val)
-		e_dbg("Could not restore PHY register %d.%d\n",
-		      BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to be read or written
- *  @data: pointer to the data to read or write
- *  @read: determines if operation is read or write
- *  @page_set: BM_WUC_PAGE already set and access enabled
- *
- *  Read the PHY register at offset and store the retrieved information in
- *  data, or write data to PHY register at offset.  Note the procedure to
- *  access the PHY wakeup registers is different than reading the other PHY
- *  registers. It works as such:
- *  1) Set 769.17.2 (page 769, register 17, bit 2) = 1
- *  2) Set page to 800 for host (801 if we were manageability)
- *  3) Write the address using the address opcode (0x11)
- *  4) Read or write the data using the data opcode (0x12)
- *  5) Restore 769.17.2 to its original value
- *
- *  Steps 1 and 2 are done by e1000_enable_phy_wakeup_reg_access_bm() and
- *  step 5 is done by e1000_disable_phy_wakeup_reg_access_bm().
- *
- *  Assumes semaphore is already acquired.  When page_set==true, assumes
- *  the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack
- *  is responsible for calls to e1000_[enable|disable]_phy_wakeup_reg_bm()).
- **/
-static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
-					  u16 *data, bool read, bool page_set)
-{
-	s32 ret_val;
-	u16 reg = BM_PHY_REG_NUM(offset);
-	u16 page = BM_PHY_REG_PAGE(offset);
-	u16 phy_reg = 0;
-
-	/* Gig must be disabled for MDIO accesses to Host Wakeup reg page */
-	if ((hw->mac.type == e1000_pchlan) &&
-	    (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
-		e_dbg("Attempting to access page %d while gig enabled.\n",
-		      page);
-
-	if (!page_set) {
-		/* Enable access to PHY wakeup registers */
-		ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
-		if (ret_val) {
-			e_dbg("Could not enable PHY wakeup reg access\n");
-			goto out;
-		}
-	}
-
-	e_dbg("Accessing PHY page %d reg 0x%x\n", page, reg);
-
-	/* Write the Wakeup register page offset value using opcode 0x11 */
-	ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg);
-	if (ret_val) {
-		e_dbg("Could not write address opcode to page %d\n", page);
-		goto out;
-	}
-
-	if (read) {
-		/* Read the Wakeup register page value using opcode 0x12 */
-		ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
-		                                   data);
-	} else {
-		/* Write the Wakeup register page value using opcode 0x12 */
-		ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
-						    *data);
-	}
-
-	if (ret_val) {
-		e_dbg("Could not access PHY reg %d.%d\n", page, reg);
-		goto out;
-	}
-
-	if (!page_set)
-		ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
-
-out:
-	return ret_val;
-}
-
-/**
- * e1000_power_up_phy_copper - Restore copper link in case of PHY power down
- * @hw: pointer to the HW structure
- *
- * In the case of a PHY power down to save power, or to turn off link during a
- * driver unload, or wake on lan is not enabled, restore the link to previous
- * settings.
- **/
-void e1000_power_up_phy_copper(struct e1000_hw *hw)
-{
-	u16 mii_reg = 0;
-
-	/* The PHY will retain its settings across a power down/up cycle */
-	e1e_rphy(hw, PHY_CONTROL, &mii_reg);
-	mii_reg &= ~MII_CR_POWER_DOWN;
-	e1e_wphy(hw, PHY_CONTROL, mii_reg);
-}
-
-/**
- * e1000_power_down_phy_copper - Restore copper link in case of PHY power down
- * @hw: pointer to the HW structure
- *
- * In the case of a PHY power down to save power, or to turn off link during a
- * driver unload, or wake on lan is not enabled, restore the link to previous
- * settings.
- **/
-void e1000_power_down_phy_copper(struct e1000_hw *hw)
-{
-	u16 mii_reg = 0;
-
-	/* The PHY will retain its settings across a power down/up cycle */
-	e1e_rphy(hw, PHY_CONTROL, &mii_reg);
-	mii_reg |= MII_CR_POWER_DOWN;
-	e1e_wphy(hw, PHY_CONTROL, mii_reg);
-	usleep_range(1000, 2000);
-}
-
-/**
- *  e1000e_commit_phy - Soft PHY reset
- *  @hw: pointer to the HW structure
- *
- *  Performs a soft PHY reset on those that apply. This is a function pointer
- *  entry point called by drivers.
- **/
-s32 e1000e_commit_phy(struct e1000_hw *hw)
-{
-	if (hw->phy.ops.commit)
-		return hw->phy.ops.commit(hw);
-
-	return 0;
-}
-
-/**
- *  e1000_set_d0_lplu_state - Sets low power link up state for D0
- *  @hw: pointer to the HW structure
- *  @active: boolean used to enable/disable lplu
- *
- *  Success returns 0, Failure returns 1
- *
- *  The low power link up (lplu) state is set to the power management level D0
- *  and SmartSpeed is disabled when active is true, else clear lplu for D0
- *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU
- *  is used during Dx states where the power conservation is most important.
- *  During driver activity, SmartSpeed should be enabled so performance is
- *  maintained.  This is a function pointer entry point called by drivers.
- **/
-static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
-{
-	if (hw->phy.ops.set_d0_lplu_state)
-		return hw->phy.ops.set_d0_lplu_state(hw, active);
-
-	return 0;
-}
-
-/**
- *  __e1000_read_phy_reg_hv -  Read HV PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to be read
- *  @data: pointer to the read data
- *  @locked: semaphore has already been acquired or not
- *
- *  Acquires semaphore, if necessary, then reads the PHY register at offset
- *  and stores the retrieved information in data.  Release any acquired
- *  semaphore before exiting.
- **/
-static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
-				   bool locked, bool page_set)
-{
-	s32 ret_val;
-	u16 page = BM_PHY_REG_PAGE(offset);
-	u16 reg = BM_PHY_REG_NUM(offset);
-	u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
-
-	if (!locked) {
-		ret_val = hw->phy.ops.acquire(hw);
-		if (ret_val)
-			return ret_val;
-	}
-
-	/* Page 800 works differently than the rest so it has its own func */
-	if (page == BM_WUC_PAGE) {
-		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
-							 true, page_set);
-		goto out;
-	}
-
-	if (page > 0 && page < HV_INTC_FC_PAGE_START) {
-		ret_val = e1000_access_phy_debug_regs_hv(hw, offset,
-		                                         data, true);
-		goto out;
-	}
-
-	if (!page_set) {
-		if (page == HV_INTC_FC_PAGE_START)
-			page = 0;
-
-		if (reg > MAX_PHY_MULTI_PAGE_REG) {
-			/* Page is shifted left, PHY expects (page x 32) */
-			ret_val = e1000_set_page_igp(hw,
-						     (page << IGP_PAGE_SHIFT));
-
-			hw->phy.addr = phy_addr;
-
-			if (ret_val)
-				goto out;
-		}
-	}
-
-	e_dbg("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
-	      page << IGP_PAGE_SHIFT, reg);
-
-	ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
-	                                  data);
-out:
-	if (!locked)
-		hw->phy.ops.release(hw);
-
-	return ret_val;
-}
-
-/**
- *  e1000_read_phy_reg_hv -  Read HV PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to be read
- *  @data: pointer to the read data
- *
- *  Acquires semaphore then reads the PHY register at offset and stores
- *  the retrieved information in data.  Release the acquired semaphore
- *  before exiting.
- **/
-s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
-{
-	return __e1000_read_phy_reg_hv(hw, offset, data, false, false);
-}
-
-/**
- *  e1000_read_phy_reg_hv_locked -  Read HV PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to be read
- *  @data: pointer to the read data
- *
- *  Reads the PHY register at offset and stores the retrieved information
- *  in data.  Assumes semaphore already acquired.
- **/
-s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
-{
-	return __e1000_read_phy_reg_hv(hw, offset, data, true, false);
-}
-
-/**
- *  e1000_read_phy_reg_page_hv - Read HV PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to write to
- *  @data: data to write at register offset
- *
- *  Reads the PHY register at offset and stores the retrieved information
- *  in data.  Assumes semaphore already acquired and page already set.
- **/
-s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data)
-{
-	return __e1000_read_phy_reg_hv(hw, offset, data, true, true);
-}
-
-/**
- *  __e1000_write_phy_reg_hv - Write HV PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to write to
- *  @data: data to write at register offset
- *  @locked: semaphore has already been acquired or not
- *
- *  Acquires semaphore, if necessary, then writes the data to PHY register
- *  at the offset.  Release any acquired semaphores before exiting.
- **/
-static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
-				    bool locked, bool page_set)
-{
-	s32 ret_val;
-	u16 page = BM_PHY_REG_PAGE(offset);
-	u16 reg = BM_PHY_REG_NUM(offset);
-	u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
-
-	if (!locked) {
-		ret_val = hw->phy.ops.acquire(hw);
-		if (ret_val)
-			return ret_val;
-	}
-
-	/* Page 800 works differently than the rest so it has its own func */
-	if (page == BM_WUC_PAGE) {
-		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
-							 false, page_set);
-		goto out;
-	}
-
-	if (page > 0 && page < HV_INTC_FC_PAGE_START) {
-		ret_val = e1000_access_phy_debug_regs_hv(hw, offset,
-		                                         &data, false);
-		goto out;
-	}
-
-	if (!page_set) {
-		if (page == HV_INTC_FC_PAGE_START)
-			page = 0;
-
-		/*
-		 * Workaround MDIO accesses being disabled after entering IEEE
-		 * Power Down (when bit 11 of the PHY Control register is set)
-		 */
-		if ((hw->phy.type == e1000_phy_82578) &&
-		    (hw->phy.revision >= 1) &&
-		    (hw->phy.addr == 2) &&
-		    ((MAX_PHY_REG_ADDRESS & reg) == 0) && (data & (1 << 11))) {
-			u16 data2 = 0x7EFF;
-			ret_val = e1000_access_phy_debug_regs_hv(hw,
-								 (1 << 6) | 0x3,
-								 &data2, false);
-			if (ret_val)
-				goto out;
-		}
-
-		if (reg > MAX_PHY_MULTI_PAGE_REG) {
-			/* Page is shifted left, PHY expects (page x 32) */
-			ret_val = e1000_set_page_igp(hw,
-						     (page << IGP_PAGE_SHIFT));
-
-			hw->phy.addr = phy_addr;
-
-			if (ret_val)
-				goto out;
-		}
-	}
-
-	e_dbg("writing PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
-	      page << IGP_PAGE_SHIFT, reg);
-
-	ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
-	                                  data);
-
-out:
-	if (!locked)
-		hw->phy.ops.release(hw);
-
-	return ret_val;
-}
-
-/**
- *  e1000_write_phy_reg_hv - Write HV PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to write to
- *  @data: data to write at register offset
- *
- *  Acquires semaphore then writes the data to PHY register at the offset.
- *  Release the acquired semaphores before exiting.
- **/
-s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
-{
-	return __e1000_write_phy_reg_hv(hw, offset, data, false, false);
-}
-
-/**
- *  e1000_write_phy_reg_hv_locked - Write HV PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to write to
- *  @data: data to write at register offset
- *
- *  Writes the data to PHY register at the offset.  Assumes semaphore
- *  already acquired.
- **/
-s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data)
-{
-	return __e1000_write_phy_reg_hv(hw, offset, data, true, false);
-}
-
-/**
- *  e1000_write_phy_reg_page_hv - Write HV PHY register
- *  @hw: pointer to the HW structure
- *  @offset: register offset to write to
- *  @data: data to write at register offset
- *
- *  Writes the data to PHY register at the offset.  Assumes semaphore
- *  already acquired and page already set.
- **/
-s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data)
-{
-	return __e1000_write_phy_reg_hv(hw, offset, data, true, true);
-}
-
-/**
- *  e1000_get_phy_addr_for_hv_page - Get PHY address based on page
- *  @page: page to be accessed
- **/
-static u32 e1000_get_phy_addr_for_hv_page(u32 page)
-{
-	u32 phy_addr = 2;
-
-	if (page >= HV_INTC_FC_PAGE_START)
-		phy_addr = 1;
-
-	return phy_addr;
-}
-
-/**
- *  e1000_access_phy_debug_regs_hv - Read HV PHY vendor specific high registers
- *  @hw: pointer to the HW structure
- *  @offset: register offset to be read or written
- *  @data: pointer to the data to be read or written
- *  @read: determines if operation is read or write
- *
- *  Reads the PHY register at offset and stores the retreived information
- *  in data.  Assumes semaphore already acquired.  Note that the procedure
- *  to access these regs uses the address port and data port to read/write.
- *  These accesses done with PHY address 2 and without using pages.
- **/
-static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
-                                          u16 *data, bool read)
-{
-	s32 ret_val;
-	u32 addr_reg = 0;
-	u32 data_reg = 0;
-
-	/* This takes care of the difference with desktop vs mobile phy */
-	addr_reg = (hw->phy.type == e1000_phy_82578) ?
-	           I82578_ADDR_REG : I82577_ADDR_REG;
-	data_reg = addr_reg + 1;
-
-	/* All operations in this function are phy address 2 */
-	hw->phy.addr = 2;
-
-	/* masking with 0x3F to remove the page from offset */
-	ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F);
-	if (ret_val) {
-		e_dbg("Could not write the Address Offset port register\n");
-		goto out;
-	}
-
-	/* Read or write the data value next */
-	if (read)
-		ret_val = e1000e_read_phy_reg_mdic(hw, data_reg, data);
-	else
-		ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data);
-
-	if (ret_val) {
-		e_dbg("Could not access the Data port register\n");
-		goto out;
-	}
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_link_stall_workaround_hv - Si workaround
- *  @hw: pointer to the HW structure
- *
- *  This function works around a Si bug where the link partner can get
- *  a link up indication before the PHY does.  If small packets are sent
- *  by the link partner they can be placed in the packet buffer without
- *  being properly accounted for by the PHY and will stall preventing
- *  further packets from being received.  The workaround is to clear the
- *  packet buffer after the PHY detects link up.
- **/
-s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
-{
-	s32 ret_val = 0;
-	u16 data;
-
-	if (hw->phy.type != e1000_phy_82578)
-		goto out;
-
-	/* Do not apply workaround if in PHY loopback bit 14 set */
-	e1e_rphy(hw, PHY_CONTROL, &data);
-	if (data & PHY_CONTROL_LB)
-		goto out;
-
-	/* check if link is up and at 1Gbps */
-	ret_val = e1e_rphy(hw, BM_CS_STATUS, &data);
-	if (ret_val)
-		goto out;
-
-	data &= BM_CS_STATUS_LINK_UP |
-	        BM_CS_STATUS_RESOLVED |
-	        BM_CS_STATUS_SPEED_MASK;
-
-	if (data != (BM_CS_STATUS_LINK_UP |
-	             BM_CS_STATUS_RESOLVED |
-	             BM_CS_STATUS_SPEED_1000))
-		goto out;
-
-	mdelay(200);
-
-	/* flush the packets in the fifo buffer */
-	ret_val = e1e_wphy(hw, HV_MUX_DATA_CTRL, HV_MUX_DATA_CTRL_GEN_TO_MAC |
-			   HV_MUX_DATA_CTRL_FORCE_SPEED);
-	if (ret_val)
-		goto out;
-
-	ret_val = e1e_wphy(hw, HV_MUX_DATA_CTRL, HV_MUX_DATA_CTRL_GEN_TO_MAC);
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_check_polarity_82577 - Checks the polarity.
- *  @hw: pointer to the HW structure
- *
- *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
- *
- *  Polarity is determined based on the PHY specific status register.
- **/
-s32 e1000_check_polarity_82577(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 data;
-
-	ret_val = e1e_rphy(hw, I82577_PHY_STATUS_2, &data);
-
-	if (!ret_val)
-		phy->cable_polarity = (data & I82577_PHY_STATUS2_REV_POLARITY)
-		                      ? e1000_rev_polarity_reversed
-		                      : e1000_rev_polarity_normal;
-
-	return ret_val;
-}
-
-/**
- *  e1000_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY
- *  @hw: pointer to the HW structure
- *
- *  Calls the PHY setup function to force speed and duplex.
- **/
-s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 phy_data;
-	bool link;
-
-	ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data);
-	if (ret_val)
-		goto out;
-
-	e1000e_phy_force_speed_duplex_setup(hw, &phy_data);
-
-	ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data);
-	if (ret_val)
-		goto out;
-
-	udelay(1);
-
-	if (phy->autoneg_wait_to_complete) {
-		e_dbg("Waiting for forced speed/duplex link on 82577 phy\n");
-
-		ret_val = e1000e_phy_has_link_generic(hw,
-		                                     PHY_FORCE_LIMIT,
-		                                     100000,
-		                                     &link);
-		if (ret_val)
-			goto out;
-
-		if (!link)
-			e_dbg("Link taking longer than expected.\n");
-
-		/* Try once more */
-		ret_val = e1000e_phy_has_link_generic(hw,
-		                                     PHY_FORCE_LIMIT,
-		                                     100000,
-		                                     &link);
-		if (ret_val)
-			goto out;
-	}
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_get_phy_info_82577 - Retrieve I82577 PHY information
- *  @hw: pointer to the HW structure
- *
- *  Read PHY status to determine if link is up.  If link is up, then
- *  set/determine 10base-T extended distance and polarity correction.  Read
- *  PHY port status to determine MDI/MDIx and speed.  Based on the speed,
- *  determine on the cable length, local and remote receiver.
- **/
-s32 e1000_get_phy_info_82577(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 data;
-	bool link;
-
-	ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
-	if (ret_val)
-		goto out;
-
-	if (!link) {
-		e_dbg("Phy info is only valid if link is up\n");
-		ret_val = -E1000_ERR_CONFIG;
-		goto out;
-	}
-
-	phy->polarity_correction = true;
-
-	ret_val = e1000_check_polarity_82577(hw);
-	if (ret_val)
-		goto out;
-
-	ret_val = e1e_rphy(hw, I82577_PHY_STATUS_2, &data);
-	if (ret_val)
-		goto out;
-
-	phy->is_mdix = (data & I82577_PHY_STATUS2_MDIX) ? true : false;
-
-	if ((data & I82577_PHY_STATUS2_SPEED_MASK) ==
-	    I82577_PHY_STATUS2_SPEED_1000MBPS) {
-		ret_val = hw->phy.ops.get_cable_length(hw);
-		if (ret_val)
-			goto out;
-
-		ret_val = e1e_rphy(hw, PHY_1000T_STATUS, &data);
-		if (ret_val)
-			goto out;
-
-		phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
-		                ? e1000_1000t_rx_status_ok
-		                : e1000_1000t_rx_status_not_ok;
-
-		phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS)
-		                 ? e1000_1000t_rx_status_ok
-		                 : e1000_1000t_rx_status_not_ok;
-	} else {
-		phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
-		phy->local_rx = e1000_1000t_rx_status_undefined;
-		phy->remote_rx = e1000_1000t_rx_status_undefined;
-	}
-
-out:
-	return ret_val;
-}
-
-/**
- *  e1000_get_cable_length_82577 - Determine cable length for 82577 PHY
- *  @hw: pointer to the HW structure
- *
- * Reads the diagnostic status register and verifies result is valid before
- * placing it in the phy_cable_length field.
- **/
-s32 e1000_get_cable_length_82577(struct e1000_hw *hw)
-{
-	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
-	u16 phy_data, length;
-
-	ret_val = e1e_rphy(hw, I82577_PHY_DIAG_STATUS, &phy_data);
-	if (ret_val)
-		goto out;
-
-	length = (phy_data & I82577_DSTATUS_CABLE_LENGTH) >>
-	         I82577_DSTATUS_CABLE_LENGTH_SHIFT;
-
-	if (length == E1000_CABLE_LENGTH_UNDEFINED)
-		ret_val = -E1000_ERR_PHY;
-
-	phy->cable_length = length;
-
-out:
-	return ret_val;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/e100.c linux-libre-3.2-gnu/drivers/net/e100.c
--- linux-libre-3.1-gnu/drivers/net/e100.c	2012-03-19 21:44:18.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e100.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3108 +0,0 @@
-/*******************************************************************************
-
-  Intel PRO/100 Linux driver
-  Copyright(c) 1999 - 2006 Intel Corporation.
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms and conditions of the GNU General Public License,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  Linux NICS <linux.nics@intel.com>
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-/*
- *	e100.c: Intel(R) PRO/100 ethernet driver
- *
- *	(Re)written 2003 by scott.feldman@intel.com.  Based loosely on
- *	original e100 driver, but better described as a munging of
- *	e100, e1000, eepro100, tg3, 8139cp, and other drivers.
- *
- *	References:
- *		Intel 8255x 10/100 Mbps Ethernet Controller Family,
- *		Open Source Software Developers Manual,
- *		http://sourceforge.net/projects/e1000
- *
- *
- *	                      Theory of Operation
- *
- *	I.   General
- *
- *	The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet
- *	controller family, which includes the 82557, 82558, 82559, 82550,
- *	82551, and 82562 devices.  82558 and greater controllers
- *	integrate the Intel 82555 PHY.  The controllers are used in
- *	server and client network interface cards, as well as in
- *	LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx
- *	configurations.  8255x supports a 32-bit linear addressing
- *	mode and operates at 33Mhz PCI clock rate.
- *
- *	II.  Driver Operation
- *
- *	Memory-mapped mode is used exclusively to access the device's
- *	shared-memory structure, the Control/Status Registers (CSR). All
- *	setup, configuration, and control of the device, including queuing
- *	of Tx, Rx, and configuration commands is through the CSR.
- *	cmd_lock serializes accesses to the CSR command register.  cb_lock
- *	protects the shared Command Block List (CBL).
- *
- *	8255x is highly MII-compliant and all access to the PHY go
- *	through the Management Data Interface (MDI).  Consequently, the
- *	driver leverages the mii.c library shared with other MII-compliant
- *	devices.
- *
- *	Big- and Little-Endian byte order as well as 32- and 64-bit
- *	archs are supported.  Weak-ordered memory and non-cache-coherent
- *	archs are supported.
- *
- *	III. Transmit
- *
- *	A Tx skb is mapped and hangs off of a TCB.  TCBs are linked
- *	together in a fixed-size ring (CBL) thus forming the flexible mode
- *	memory structure.  A TCB marked with the suspend-bit indicates
- *	the end of the ring.  The last TCB processed suspends the
- *	controller, and the controller can be restarted by issue a CU
- *	resume command to continue from the suspend point, or a CU start
- *	command to start at a given position in the ring.
- *
- *	Non-Tx commands (config, multicast setup, etc) are linked
- *	into the CBL ring along with Tx commands.  The common structure
- *	used for both Tx and non-Tx commands is the Command Block (CB).
- *
- *	cb_to_use is the next CB to use for queuing a command; cb_to_clean
- *	is the next CB to check for completion; cb_to_send is the first
- *	CB to start on in case of a previous failure to resume.  CB clean
- *	up happens in interrupt context in response to a CU interrupt.
- *	cbs_avail keeps track of number of free CB resources available.
- *
- * 	Hardware padding of short packets to minimum packet size is
- * 	enabled.  82557 pads with 7Eh, while the later controllers pad
- * 	with 00h.
- *
- *	IV.  Receive
- *
- *	The Receive Frame Area (RFA) comprises a ring of Receive Frame
- *	Descriptors (RFD) + data buffer, thus forming the simplified mode
- *	memory structure.  Rx skbs are allocated to contain both the RFD
- *	and the data buffer, but the RFD is pulled off before the skb is
- *	indicated.  The data buffer is aligned such that encapsulated
- *	protocol headers are u32-aligned.  Since the RFD is part of the
- *	mapped shared memory, and completion status is contained within
- *	the RFD, the RFD must be dma_sync'ed to maintain a consistent
- *	view from software and hardware.
- *
- *	In order to keep updates to the RFD link field from colliding with
- *	hardware writes to mark packets complete, we use the feature that
- *	hardware will not write to a size 0 descriptor and mark the previous
- *	packet as end-of-list (EL).   After updating the link, we remove EL
- *	and only then restore the size such that hardware may use the
- *	previous-to-end RFD.
- *
- *	Under typical operation, the  receive unit (RU) is start once,
- *	and the controller happily fills RFDs as frames arrive.  If
- *	replacement RFDs cannot be allocated, or the RU goes non-active,
- *	the RU must be restarted.  Frame arrival generates an interrupt,
- *	and Rx indication and re-allocation happen in the same context,
- *	therefore no locking is required.  A software-generated interrupt
- *	is generated from the watchdog to recover from a failed allocation
- *	scenario where all Rx resources have been indicated and none re-
- *	placed.
- *
- *	V.   Miscellaneous
- *
- * 	VLAN offloading of tagging, stripping and filtering is not
- * 	supported, but driver will accommodate the extra 4-byte VLAN tag
- * 	for processing by upper layers.  Tx/Rx Checksum offloading is not
- * 	supported.  Tx Scatter/Gather is not supported.  Jumbo Frames is
- * 	not supported (hardware limitation).
- *
- * 	MagicPacket(tm) WoL support is enabled/disabled via ethtool.
- *
- * 	Thanks to JC (jchapman@katalix.com) for helping with
- * 	testing/troubleshooting the development driver.
- *
- * 	TODO:
- * 	o several entry points race with dev->close
- * 	o check for tx-no-resources/stop Q races with tx clean/wake Q
- *
- *	FIXES:
- * 2005/12/02 - Michael O'Donnell <Michael.ODonnell at stratus dot com>
- *	- Stratus87247: protect MDI control register manipulations
- * 2009/06/01 - Andreas Mohr <andi at lisas dot de>
- *      - add clean lowlevel I/O emulation for cards with MII-lacking PHYs
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/hardirq.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/mii.h>
-#include <linux/if_vlan.h>
-#include <linux/skbuff.h>
-#include <linux/ethtool.h>
-#include <linux/string.h>
-#include <linux/firmware.h>
-#include <linux/rtnetlink.h>
-#include <asm/unaligned.h>
-
-
-#define DRV_NAME		"e100"
-#define DRV_EXT			"-NAPI"
-#define DRV_VERSION		"3.5.24-k2"DRV_EXT
-#define DRV_DESCRIPTION		"Intel(R) PRO/100 Network Driver"
-#define DRV_COPYRIGHT		"Copyright(c) 1999-2006 Intel Corporation"
-
-#define E100_WATCHDOG_PERIOD	(2 * HZ)
-#define E100_NAPI_WEIGHT	16
-
-#define FIRMWARE_D101M		"/*(DEBLOBBED)*/"
-#define FIRMWARE_D101S		"/*(DEBLOBBED)*/"
-#define FIRMWARE_D102E		"/*(DEBLOBBED)*/"
-
-MODULE_DESCRIPTION(DRV_DESCRIPTION);
-MODULE_AUTHOR(DRV_COPYRIGHT);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-/*(DEBLOBBED)*/
-
-static int debug = 3;
-static int eeprom_bad_csum_allow = 0;
-static int use_io = 0;
-module_param(debug, int, 0);
-module_param(eeprom_bad_csum_allow, int, 0);
-module_param(use_io, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
-MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums");
-MODULE_PARM_DESC(use_io, "Force use of i/o access mode");
-
-#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\
-	PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \
-	PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich }
-static DEFINE_PCI_DEVICE_TABLE(e100_id_table) = {
-	INTEL_8255X_ETHERNET_DEVICE(0x1029, 0),
-	INTEL_8255X_ETHERNET_DEVICE(0x1030, 0),
-	INTEL_8255X_ETHERNET_DEVICE(0x1031, 3),
-	INTEL_8255X_ETHERNET_DEVICE(0x1032, 3),
-	INTEL_8255X_ETHERNET_DEVICE(0x1033, 3),
-	INTEL_8255X_ETHERNET_DEVICE(0x1034, 3),
-	INTEL_8255X_ETHERNET_DEVICE(0x1038, 3),
-	INTEL_8255X_ETHERNET_DEVICE(0x1039, 4),
-	INTEL_8255X_ETHERNET_DEVICE(0x103A, 4),
-	INTEL_8255X_ETHERNET_DEVICE(0x103B, 4),
-	INTEL_8255X_ETHERNET_DEVICE(0x103C, 4),
-	INTEL_8255X_ETHERNET_DEVICE(0x103D, 4),
-	INTEL_8255X_ETHERNET_DEVICE(0x103E, 4),
-	INTEL_8255X_ETHERNET_DEVICE(0x1050, 5),
-	INTEL_8255X_ETHERNET_DEVICE(0x1051, 5),
-	INTEL_8255X_ETHERNET_DEVICE(0x1052, 5),
-	INTEL_8255X_ETHERNET_DEVICE(0x1053, 5),
-	INTEL_8255X_ETHERNET_DEVICE(0x1054, 5),
-	INTEL_8255X_ETHERNET_DEVICE(0x1055, 5),
-	INTEL_8255X_ETHERNET_DEVICE(0x1056, 5),
-	INTEL_8255X_ETHERNET_DEVICE(0x1057, 5),
-	INTEL_8255X_ETHERNET_DEVICE(0x1059, 0),
-	INTEL_8255X_ETHERNET_DEVICE(0x1064, 6),
-	INTEL_8255X_ETHERNET_DEVICE(0x1065, 6),
-	INTEL_8255X_ETHERNET_DEVICE(0x1066, 6),
-	INTEL_8255X_ETHERNET_DEVICE(0x1067, 6),
-	INTEL_8255X_ETHERNET_DEVICE(0x1068, 6),
-	INTEL_8255X_ETHERNET_DEVICE(0x1069, 6),
-	INTEL_8255X_ETHERNET_DEVICE(0x106A, 6),
-	INTEL_8255X_ETHERNET_DEVICE(0x106B, 6),
-	INTEL_8255X_ETHERNET_DEVICE(0x1091, 7),
-	INTEL_8255X_ETHERNET_DEVICE(0x1092, 7),
-	INTEL_8255X_ETHERNET_DEVICE(0x1093, 7),
-	INTEL_8255X_ETHERNET_DEVICE(0x1094, 7),
-	INTEL_8255X_ETHERNET_DEVICE(0x1095, 7),
-	INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7),
-	INTEL_8255X_ETHERNET_DEVICE(0x1209, 0),
-	INTEL_8255X_ETHERNET_DEVICE(0x1229, 0),
-	INTEL_8255X_ETHERNET_DEVICE(0x2449, 2),
-	INTEL_8255X_ETHERNET_DEVICE(0x2459, 2),
-	INTEL_8255X_ETHERNET_DEVICE(0x245D, 2),
-	INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7),
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci, e100_id_table);
-
-enum mac {
-	mac_82557_D100_A  = 0,
-	mac_82557_D100_B  = 1,
-	mac_82557_D100_C  = 2,
-	mac_82558_D101_A4 = 4,
-	mac_82558_D101_B0 = 5,
-	mac_82559_D101M   = 8,
-	mac_82559_D101S   = 9,
-	mac_82550_D102    = 12,
-	mac_82550_D102_C  = 13,
-	mac_82551_E       = 14,
-	mac_82551_F       = 15,
-	mac_82551_10      = 16,
-	mac_unknown       = 0xFF,
-};
-
-enum phy {
-	phy_100a     = 0x000003E0,
-	phy_100c     = 0x035002A8,
-	phy_82555_tx = 0x015002A8,
-	phy_nsc_tx   = 0x5C002000,
-	phy_82562_et = 0x033002A8,
-	phy_82562_em = 0x032002A8,
-	phy_82562_ek = 0x031002A8,
-	phy_82562_eh = 0x017002A8,
-	phy_82552_v  = 0xd061004d,
-	phy_unknown  = 0xFFFFFFFF,
-};
-
-/* CSR (Control/Status Registers) */
-struct csr {
-	struct {
-		u8 status;
-		u8 stat_ack;
-		u8 cmd_lo;
-		u8 cmd_hi;
-		u32 gen_ptr;
-	} scb;
-	u32 port;
-	u16 flash_ctrl;
-	u8 eeprom_ctrl_lo;
-	u8 eeprom_ctrl_hi;
-	u32 mdi_ctrl;
-	u32 rx_dma_count;
-};
-
-enum scb_status {
-	rus_no_res       = 0x08,
-	rus_ready        = 0x10,
-	rus_mask         = 0x3C,
-};
-
-enum ru_state  {
-	RU_SUSPENDED = 0,
-	RU_RUNNING	 = 1,
-	RU_UNINITIALIZED = -1,
-};
-
-enum scb_stat_ack {
-	stat_ack_not_ours    = 0x00,
-	stat_ack_sw_gen      = 0x04,
-	stat_ack_rnr         = 0x10,
-	stat_ack_cu_idle     = 0x20,
-	stat_ack_frame_rx    = 0x40,
-	stat_ack_cu_cmd_done = 0x80,
-	stat_ack_not_present = 0xFF,
-	stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx),
-	stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done),
-};
-
-enum scb_cmd_hi {
-	irq_mask_none = 0x00,
-	irq_mask_all  = 0x01,
-	irq_sw_gen    = 0x02,
-};
-
-enum scb_cmd_lo {
-	cuc_nop        = 0x00,
-	ruc_start      = 0x01,
-	ruc_load_base  = 0x06,
-	cuc_start      = 0x10,
-	cuc_resume     = 0x20,
-	cuc_dump_addr  = 0x40,
-	cuc_dump_stats = 0x50,
-	cuc_load_base  = 0x60,
-	cuc_dump_reset = 0x70,
-};
-
-enum cuc_dump {
-	cuc_dump_complete       = 0x0000A005,
-	cuc_dump_reset_complete = 0x0000A007,
-};
-
-enum port {
-	software_reset  = 0x0000,
-	selftest        = 0x0001,
-	selective_reset = 0x0002,
-};
-
-enum eeprom_ctrl_lo {
-	eesk = 0x01,
-	eecs = 0x02,
-	eedi = 0x04,
-	eedo = 0x08,
-};
-
-enum mdi_ctrl {
-	mdi_write = 0x04000000,
-	mdi_read  = 0x08000000,
-	mdi_ready = 0x10000000,
-};
-
-enum eeprom_op {
-	op_write = 0x05,
-	op_read  = 0x06,
-	op_ewds  = 0x10,
-	op_ewen  = 0x13,
-};
-
-enum eeprom_offsets {
-	eeprom_cnfg_mdix  = 0x03,
-	eeprom_phy_iface  = 0x06,
-	eeprom_id         = 0x0A,
-	eeprom_config_asf = 0x0D,
-	eeprom_smbus_addr = 0x90,
-};
-
-enum eeprom_cnfg_mdix {
-	eeprom_mdix_enabled = 0x0080,
-};
-
-enum eeprom_phy_iface {
-	NoSuchPhy = 0,
-	I82553AB,
-	I82553C,
-	I82503,
-	DP83840,
-	S80C240,
-	S80C24,
-	I82555,
-	DP83840A = 10,
-};
-
-enum eeprom_id {
-	eeprom_id_wol = 0x0020,
-};
-
-enum eeprom_config_asf {
-	eeprom_asf = 0x8000,
-	eeprom_gcl = 0x4000,
-};
-
-enum cb_status {
-	cb_complete = 0x8000,
-	cb_ok       = 0x2000,
-};
-
-enum cb_command {
-	cb_nop    = 0x0000,
-	cb_iaaddr = 0x0001,
-	cb_config = 0x0002,
-	cb_multi  = 0x0003,
-	cb_tx     = 0x0004,
-	cb_ucode  = 0x0005,
-	cb_dump   = 0x0006,
-	cb_tx_sf  = 0x0008,
-	cb_cid    = 0x1f00,
-	cb_i      = 0x2000,
-	cb_s      = 0x4000,
-	cb_el     = 0x8000,
-};
-
-struct rfd {
-	__le16 status;
-	__le16 command;
-	__le32 link;
-	__le32 rbd;
-	__le16 actual_size;
-	__le16 size;
-};
-
-struct rx {
-	struct rx *next, *prev;
-	struct sk_buff *skb;
-	dma_addr_t dma_addr;
-};
-
-#if defined(__BIG_ENDIAN_BITFIELD)
-#define X(a,b)	b,a
-#else
-#define X(a,b)	a,b
-#endif
-struct config {
-/*0*/	u8 X(byte_count:6, pad0:2);
-/*1*/	u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1);
-/*2*/	u8 adaptive_ifs;
-/*3*/	u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1),
-	   term_write_cache_line:1), pad3:4);
-/*4*/	u8 X(rx_dma_max_count:7, pad4:1);
-/*5*/	u8 X(tx_dma_max_count:7, dma_max_count_enable:1);
-/*6*/	u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1),
-	   tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1),
-	   rx_discard_overruns:1), rx_save_bad_frames:1);
-/*7*/	u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2),
-	   pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1),
-	   tx_dynamic_tbd:1);
-/*8*/	u8 X(X(mii_mode:1, pad8:6), csma_disabled:1);
-/*9*/	u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1),
-	   link_status_wake:1), arp_wake:1), mcmatch_wake:1);
-/*10*/	u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2),
-	   loopback:2);
-/*11*/	u8 X(linear_priority:3, pad11:5);
-/*12*/	u8 X(X(linear_priority_mode:1, pad12:3), ifs:4);
-/*13*/	u8 ip_addr_lo;
-/*14*/	u8 ip_addr_hi;
-/*15*/	u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1),
-	   wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1),
-	   pad15_2:1), crs_or_cdt:1);
-/*16*/	u8 fc_delay_lo;
-/*17*/	u8 fc_delay_hi;
-/*18*/	u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1),
-	   rx_long_ok:1), fc_priority_threshold:3), pad18:1);
-/*19*/	u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1),
-	   fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1),
-	   full_duplex_force:1), full_duplex_pin:1);
-/*20*/	u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1);
-/*21*/	u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4);
-/*22*/	u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6);
-	u8 pad_d102[9];
-};
-
-#define E100_MAX_MULTICAST_ADDRS	64
-struct multi {
-	__le16 count;
-	u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/];
-};
-
-/* Important: keep total struct u32-aligned */
-#define UCODE_SIZE			134
-struct cb {
-	__le16 status;
-	__le16 command;
-	__le32 link;
-	union {
-		u8 iaaddr[ETH_ALEN];
-		__le32 ucode[UCODE_SIZE];
-		struct config config;
-		struct multi multi;
-		struct {
-			u32 tbd_array;
-			u16 tcb_byte_count;
-			u8 threshold;
-			u8 tbd_count;
-			struct {
-				__le32 buf_addr;
-				__le16 size;
-				u16 eol;
-			} tbd;
-		} tcb;
-		__le32 dump_buffer_addr;
-	} u;
-	struct cb *next, *prev;
-	dma_addr_t dma_addr;
-	struct sk_buff *skb;
-};
-
-enum loopback {
-	lb_none = 0, lb_mac = 1, lb_phy = 3,
-};
-
-struct stats {
-	__le32 tx_good_frames, tx_max_collisions, tx_late_collisions,
-		tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions,
-		tx_multiple_collisions, tx_total_collisions;
-	__le32 rx_good_frames, rx_crc_errors, rx_alignment_errors,
-		rx_resource_errors, rx_overrun_errors, rx_cdt_errors,
-		rx_short_frame_errors;
-	__le32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported;
-	__le16 xmt_tco_frames, rcv_tco_frames;
-	__le32 complete;
-};
-
-struct mem {
-	struct {
-		u32 signature;
-		u32 result;
-	} selftest;
-	struct stats stats;
-	u8 dump_buf[596];
-};
-
-struct param_range {
-	u32 min;
-	u32 max;
-	u32 count;
-};
-
-struct params {
-	struct param_range rfds;
-	struct param_range cbs;
-};
-
-struct nic {
-	/* Begin: frequently used values: keep adjacent for cache effect */
-	u32 msg_enable				____cacheline_aligned;
-	struct net_device *netdev;
-	struct pci_dev *pdev;
-	u16 (*mdio_ctrl)(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data);
-
-	struct rx *rxs				____cacheline_aligned;
-	struct rx *rx_to_use;
-	struct rx *rx_to_clean;
-	struct rfd blank_rfd;
-	enum ru_state ru_running;
-
-	spinlock_t cb_lock			____cacheline_aligned;
-	spinlock_t cmd_lock;
-	struct csr __iomem *csr;
-	enum scb_cmd_lo cuc_cmd;
-	unsigned int cbs_avail;
-	struct napi_struct napi;
-	struct cb *cbs;
-	struct cb *cb_to_use;
-	struct cb *cb_to_send;
-	struct cb *cb_to_clean;
-	__le16 tx_command;
-	/* End: frequently used values: keep adjacent for cache effect */
-
-	enum {
-		ich                = (1 << 0),
-		promiscuous        = (1 << 1),
-		multicast_all      = (1 << 2),
-		wol_magic          = (1 << 3),
-		ich_10h_workaround = (1 << 4),
-	} flags					____cacheline_aligned;
-
-	enum mac mac;
-	enum phy phy;
-	struct params params;
-	struct timer_list watchdog;
-	struct mii_if_info mii;
-	struct work_struct tx_timeout_task;
-	enum loopback loopback;
-
-	struct mem *mem;
-	dma_addr_t dma_addr;
-
-	struct pci_pool *cbs_pool;
-	dma_addr_t cbs_dma_addr;
-	u8 adaptive_ifs;
-	u8 tx_threshold;
-	u32 tx_frames;
-	u32 tx_collisions;
-	u32 tx_deferred;
-	u32 tx_single_collisions;
-	u32 tx_multiple_collisions;
-	u32 tx_fc_pause;
-	u32 tx_tco_frames;
-
-	u32 rx_fc_pause;
-	u32 rx_fc_unsupported;
-	u32 rx_tco_frames;
-	u32 rx_over_length_errors;
-
-	u16 eeprom_wc;
-	__le16 eeprom[256];
-	spinlock_t mdio_lock;
-	const struct firmware *fw;
-};
-
-static inline void e100_write_flush(struct nic *nic)
-{
-	/* Flush previous PCI writes through intermediate bridges
-	 * by doing a benign read */
-	(void)ioread8(&nic->csr->scb.status);
-}
-
-static void e100_enable_irq(struct nic *nic)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&nic->cmd_lock, flags);
-	iowrite8(irq_mask_none, &nic->csr->scb.cmd_hi);
-	e100_write_flush(nic);
-	spin_unlock_irqrestore(&nic->cmd_lock, flags);
-}
-
-static void e100_disable_irq(struct nic *nic)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&nic->cmd_lock, flags);
-	iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi);
-	e100_write_flush(nic);
-	spin_unlock_irqrestore(&nic->cmd_lock, flags);
-}
-
-static void e100_hw_reset(struct nic *nic)
-{
-	/* Put CU and RU into idle with a selective reset to get
-	 * device off of PCI bus */
-	iowrite32(selective_reset, &nic->csr->port);
-	e100_write_flush(nic); udelay(20);
-
-	/* Now fully reset device */
-	iowrite32(software_reset, &nic->csr->port);
-	e100_write_flush(nic); udelay(20);
-
-	/* Mask off our interrupt line - it's unmasked after reset */
-	e100_disable_irq(nic);
-}
-
-static int e100_self_test(struct nic *nic)
-{
-	u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest);
-
-	/* Passing the self-test is a pretty good indication
-	 * that the device can DMA to/from host memory */
-
-	nic->mem->selftest.signature = 0;
-	nic->mem->selftest.result = 0xFFFFFFFF;
-
-	iowrite32(selftest | dma_addr, &nic->csr->port);
-	e100_write_flush(nic);
-	/* Wait 10 msec for self-test to complete */
-	msleep(10);
-
-	/* Interrupts are enabled after self-test */
-	e100_disable_irq(nic);
-
-	/* Check results of self-test */
-	if (nic->mem->selftest.result != 0) {
-		netif_err(nic, hw, nic->netdev,
-			  "Self-test failed: result=0x%08X\n",
-			  nic->mem->selftest.result);
-		return -ETIMEDOUT;
-	}
-	if (nic->mem->selftest.signature == 0) {
-		netif_err(nic, hw, nic->netdev, "Self-test failed: timed out\n");
-		return -ETIMEDOUT;
-	}
-
-	return 0;
-}
-
-static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 data)
-{
-	u32 cmd_addr_data[3];
-	u8 ctrl;
-	int i, j;
-
-	/* Three cmds: write/erase enable, write data, write/erase disable */
-	cmd_addr_data[0] = op_ewen << (addr_len - 2);
-	cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) |
-		le16_to_cpu(data);
-	cmd_addr_data[2] = op_ewds << (addr_len - 2);
-
-	/* Bit-bang cmds to write word to eeprom */
-	for (j = 0; j < 3; j++) {
-
-		/* Chip select */
-		iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo);
-		e100_write_flush(nic); udelay(4);
-
-		for (i = 31; i >= 0; i--) {
-			ctrl = (cmd_addr_data[j] & (1 << i)) ?
-				eecs | eedi : eecs;
-			iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo);
-			e100_write_flush(nic); udelay(4);
-
-			iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo);
-			e100_write_flush(nic); udelay(4);
-		}
-		/* Wait 10 msec for cmd to complete */
-		msleep(10);
-
-		/* Chip deselect */
-		iowrite8(0, &nic->csr->eeprom_ctrl_lo);
-		e100_write_flush(nic); udelay(4);
-	}
-};
-
-/* General technique stolen from the eepro100 driver - very clever */
-static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
-{
-	u32 cmd_addr_data;
-	u16 data = 0;
-	u8 ctrl;
-	int i;
-
-	cmd_addr_data = ((op_read << *addr_len) | addr) << 16;
-
-	/* Chip select */
-	iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo);
-	e100_write_flush(nic); udelay(4);
-
-	/* Bit-bang to read word from eeprom */
-	for (i = 31; i >= 0; i--) {
-		ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs;
-		iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo);
-		e100_write_flush(nic); udelay(4);
-
-		iowrite8(ctrl | eesk, &nic->csr->eeprom_ctrl_lo);
-		e100_write_flush(nic); udelay(4);
-
-		/* Eeprom drives a dummy zero to EEDO after receiving
-		 * complete address.  Use this to adjust addr_len. */
-		ctrl = ioread8(&nic->csr->eeprom_ctrl_lo);
-		if (!(ctrl & eedo) && i > 16) {
-			*addr_len -= (i - 16);
-			i = 17;
-		}
-
-		data = (data << 1) | (ctrl & eedo ? 1 : 0);
-	}
-
-	/* Chip deselect */
-	iowrite8(0, &nic->csr->eeprom_ctrl_lo);
-	e100_write_flush(nic); udelay(4);
-
-	return cpu_to_le16(data);
-};
-
-/* Load entire EEPROM image into driver cache and validate checksum */
-static int e100_eeprom_load(struct nic *nic)
-{
-	u16 addr, addr_len = 8, checksum = 0;
-
-	/* Try reading with an 8-bit addr len to discover actual addr len */
-	e100_eeprom_read(nic, &addr_len, 0);
-	nic->eeprom_wc = 1 << addr_len;
-
-	for (addr = 0; addr < nic->eeprom_wc; addr++) {
-		nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr);
-		if (addr < nic->eeprom_wc - 1)
-			checksum += le16_to_cpu(nic->eeprom[addr]);
-	}
-
-	/* The checksum, stored in the last word, is calculated such that
-	 * the sum of words should be 0xBABA */
-	if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) {
-		netif_err(nic, probe, nic->netdev, "EEPROM corrupted\n");
-		if (!eeprom_bad_csum_allow)
-			return -EAGAIN;
-	}
-
-	return 0;
-}
-
-/* Save (portion of) driver EEPROM cache to device and update checksum */
-static int e100_eeprom_save(struct nic *nic, u16 start, u16 count)
-{
-	u16 addr, addr_len = 8, checksum = 0;
-
-	/* Try reading with an 8-bit addr len to discover actual addr len */
-	e100_eeprom_read(nic, &addr_len, 0);
-	nic->eeprom_wc = 1 << addr_len;
-
-	if (start + count >= nic->eeprom_wc)
-		return -EINVAL;
-
-	for (addr = start; addr < start + count; addr++)
-		e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]);
-
-	/* The checksum, stored in the last word, is calculated such that
-	 * the sum of words should be 0xBABA */
-	for (addr = 0; addr < nic->eeprom_wc - 1; addr++)
-		checksum += le16_to_cpu(nic->eeprom[addr]);
-	nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum);
-	e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1,
-		nic->eeprom[nic->eeprom_wc - 1]);
-
-	return 0;
-}
-
-#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */
-#define E100_WAIT_SCB_FAST 20       /* delay like the old code */
-static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
-{
-	unsigned long flags;
-	unsigned int i;
-	int err = 0;
-
-	spin_lock_irqsave(&nic->cmd_lock, flags);
-
-	/* Previous command is accepted when SCB clears */
-	for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) {
-		if (likely(!ioread8(&nic->csr->scb.cmd_lo)))
-			break;
-		cpu_relax();
-		if (unlikely(i > E100_WAIT_SCB_FAST))
-			udelay(5);
-	}
-	if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) {
-		err = -EAGAIN;
-		goto err_unlock;
-	}
-
-	if (unlikely(cmd != cuc_resume))
-		iowrite32(dma_addr, &nic->csr->scb.gen_ptr);
-	iowrite8(cmd, &nic->csr->scb.cmd_lo);
-
-err_unlock:
-	spin_unlock_irqrestore(&nic->cmd_lock, flags);
-
-	return err;
-}
-
-static int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
-	void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
-{
-	struct cb *cb;
-	unsigned long flags;
-	int err = 0;
-
-	spin_lock_irqsave(&nic->cb_lock, flags);
-
-	if (unlikely(!nic->cbs_avail)) {
-		err = -ENOMEM;
-		goto err_unlock;
-	}
-
-	cb = nic->cb_to_use;
-	nic->cb_to_use = cb->next;
-	nic->cbs_avail--;
-	cb->skb = skb;
-
-	if (unlikely(!nic->cbs_avail))
-		err = -ENOSPC;
-
-	cb_prepare(nic, cb, skb);
-
-	/* Order is important otherwise we'll be in a race with h/w:
-	 * set S-bit in current first, then clear S-bit in previous. */
-	cb->command |= cpu_to_le16(cb_s);
-	wmb();
-	cb->prev->command &= cpu_to_le16(~cb_s);
-
-	while (nic->cb_to_send != nic->cb_to_use) {
-		if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd,
-			nic->cb_to_send->dma_addr))) {
-			/* Ok, here's where things get sticky.  It's
-			 * possible that we can't schedule the command
-			 * because the controller is too busy, so
-			 * let's just queue the command and try again
-			 * when another command is scheduled. */
-			if (err == -ENOSPC) {
-				//request a reset
-				schedule_work(&nic->tx_timeout_task);
-			}
-			break;
-		} else {
-			nic->cuc_cmd = cuc_resume;
-			nic->cb_to_send = nic->cb_to_send->next;
-		}
-	}
-
-err_unlock:
-	spin_unlock_irqrestore(&nic->cb_lock, flags);
-
-	return err;
-}
-
-static int mdio_read(struct net_device *netdev, int addr, int reg)
-{
-	struct nic *nic = netdev_priv(netdev);
-	return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0);
-}
-
-static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
-{
-	struct nic *nic = netdev_priv(netdev);
-
-	nic->mdio_ctrl(nic, addr, mdi_write, reg, data);
-}
-
-/* the standard mdio_ctrl() function for usual MII-compliant hardware */
-static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data)
-{
-	u32 data_out = 0;
-	unsigned int i;
-	unsigned long flags;
-
-
-	/*
-	 * Stratus87247: we shouldn't be writing the MDI control
-	 * register until the Ready bit shows True.  Also, since
-	 * manipulation of the MDI control registers is a multi-step
-	 * procedure it should be done under lock.
-	 */
-	spin_lock_irqsave(&nic->mdio_lock, flags);
-	for (i = 100; i; --i) {
-		if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready)
-			break;
-		udelay(20);
-	}
-	if (unlikely(!i)) {
-		netdev_err(nic->netdev, "e100.mdio_ctrl won't go Ready\n");
-		spin_unlock_irqrestore(&nic->mdio_lock, flags);
-		return 0;		/* No way to indicate timeout error */
-	}
-	iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl);
-
-	for (i = 0; i < 100; i++) {
-		udelay(20);
-		if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready)
-			break;
-	}
-	spin_unlock_irqrestore(&nic->mdio_lock, flags);
-	netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
-		     "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n",
-		     dir == mdi_read ? "READ" : "WRITE",
-		     addr, reg, data, data_out);
-	return (u16)data_out;
-}
-
-/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */
-static u16 mdio_ctrl_phy_82552_v(struct nic *nic,
-				 u32 addr,
-				 u32 dir,
-				 u32 reg,
-				 u16 data)
-{
-	if ((reg == MII_BMCR) && (dir == mdi_write)) {
-		if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) {
-			u16 advert = mdio_read(nic->netdev, nic->mii.phy_id,
-							MII_ADVERTISE);
-
-			/*
-			 * Workaround Si issue where sometimes the part will not
-			 * autoneg to 100Mbps even when advertised.
-			 */
-			if (advert & ADVERTISE_100FULL)
-				data |= BMCR_SPEED100 | BMCR_FULLDPLX;
-			else if (advert & ADVERTISE_100HALF)
-				data |= BMCR_SPEED100;
-		}
-	}
-	return mdio_ctrl_hw(nic, addr, dir, reg, data);
-}
-
-/* Fully software-emulated mdio_ctrl() function for cards without
- * MII-compliant PHYs.
- * For now, this is mainly geared towards 80c24 support; in case of further
- * requirements for other types (i82503, ...?) either extend this mechanism
- * or split it, whichever is cleaner.
- */
-static u16 mdio_ctrl_phy_mii_emulated(struct nic *nic,
-				      u32 addr,
-				      u32 dir,
-				      u32 reg,
-				      u16 data)
-{
-	/* might need to allocate a netdev_priv'ed register array eventually
-	 * to be able to record state changes, but for now
-	 * some fully hardcoded register handling ought to be ok I guess. */
-
-	if (dir == mdi_read) {
-		switch (reg) {
-		case MII_BMCR:
-			/* Auto-negotiation, right? */
-			return  BMCR_ANENABLE |
-				BMCR_FULLDPLX;
-		case MII_BMSR:
-			return	BMSR_LSTATUS /* for mii_link_ok() */ |
-				BMSR_ANEGCAPABLE |
-				BMSR_10FULL;
-		case MII_ADVERTISE:
-			/* 80c24 is a "combo card" PHY, right? */
-			return	ADVERTISE_10HALF |
-				ADVERTISE_10FULL;
-		default:
-			netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
-				     "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n",
-				     dir == mdi_read ? "READ" : "WRITE",
-				     addr, reg, data);
-			return 0xFFFF;
-		}
-	} else {
-		switch (reg) {
-		default:
-			netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
-				     "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n",
-				     dir == mdi_read ? "READ" : "WRITE",
-				     addr, reg, data);
-			return 0xFFFF;
-		}
-	}
-}
-static inline int e100_phy_supports_mii(struct nic *nic)
-{
-	/* for now, just check it by comparing whether we
-	   are using MII software emulation.
-	*/
-	return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated);
-}
-
-static void e100_get_defaults(struct nic *nic)
-{
-	struct param_range rfds = { .min = 16, .max = 256, .count = 256 };
-	struct param_range cbs  = { .min = 64, .max = 256, .count = 128 };
-
-	/* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */
-	nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision;
-	if (nic->mac == mac_unknown)
-		nic->mac = mac_82557_D100_A;
-
-	nic->params.rfds = rfds;
-	nic->params.cbs = cbs;
-
-	/* Quadwords to DMA into FIFO before starting frame transmit */
-	nic->tx_threshold = 0xE0;
-
-	/* no interrupt for every tx completion, delay = 256us if not 557 */
-	nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf |
-		((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i));
-
-	/* Template for a freshly allocated RFD */
-	nic->blank_rfd.command = 0;
-	nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF);
-	nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN);
-
-	/* MII setup */
-	nic->mii.phy_id_mask = 0x1F;
-	nic->mii.reg_num_mask = 0x1F;
-	nic->mii.dev = nic->netdev;
-	nic->mii.mdio_read = mdio_read;
-	nic->mii.mdio_write = mdio_write;
-}
-
-static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
-{
-	struct config *config = &cb->u.config;
-	u8 *c = (u8 *)config;
-
-	cb->command = cpu_to_le16(cb_config);
-
-	memset(config, 0, sizeof(struct config));
-
-	config->byte_count = 0x16;		/* bytes in this struct */
-	config->rx_fifo_limit = 0x8;		/* bytes in FIFO before DMA */
-	config->direct_rx_dma = 0x1;		/* reserved */
-	config->standard_tcb = 0x1;		/* 1=standard, 0=extended */
-	config->standard_stat_counter = 0x1;	/* 1=standard, 0=extended */
-	config->rx_discard_short_frames = 0x1;	/* 1=discard, 0=pass */
-	config->tx_underrun_retry = 0x3;	/* # of underrun retries */
-	if (e100_phy_supports_mii(nic))
-		config->mii_mode = 1;           /* 1=MII mode, 0=i82503 mode */
-	config->pad10 = 0x6;
-	config->no_source_addr_insertion = 0x1;	/* 1=no, 0=yes */
-	config->preamble_length = 0x2;		/* 0=1, 1=3, 2=7, 3=15 bytes */
-	config->ifs = 0x6;			/* x16 = inter frame spacing */
-	config->ip_addr_hi = 0xF2;		/* ARP IP filter - not used */
-	config->pad15_1 = 0x1;
-	config->pad15_2 = 0x1;
-	config->crs_or_cdt = 0x0;		/* 0=CRS only, 1=CRS or CDT */
-	config->fc_delay_hi = 0x40;		/* time delay for fc frame */
-	config->tx_padding = 0x1;		/* 1=pad short frames */
-	config->fc_priority_threshold = 0x7;	/* 7=priority fc disabled */
-	config->pad18 = 0x1;
-	config->full_duplex_pin = 0x1;		/* 1=examine FDX# pin */
-	config->pad20_1 = 0x1F;
-	config->fc_priority_location = 0x1;	/* 1=byte#31, 0=byte#19 */
-	config->pad21_1 = 0x5;
-
-	config->adaptive_ifs = nic->adaptive_ifs;
-	config->loopback = nic->loopback;
-
-	if (nic->mii.force_media && nic->mii.full_duplex)
-		config->full_duplex_force = 0x1;	/* 1=force, 0=auto */
-
-	if (nic->flags & promiscuous || nic->loopback) {
-		config->rx_save_bad_frames = 0x1;	/* 1=save, 0=discard */
-		config->rx_discard_short_frames = 0x0;	/* 1=discard, 0=save */
-		config->promiscuous_mode = 0x1;		/* 1=on, 0=off */
-	}
-
-	if (nic->flags & multicast_all)
-		config->multicast_all = 0x1;		/* 1=accept, 0=no */
-
-	/* disable WoL when up */
-	if (netif_running(nic->netdev) || !(nic->flags & wol_magic))
-		config->magic_packet_disable = 0x1;	/* 1=off, 0=on */
-
-	if (nic->mac >= mac_82558_D101_A4) {
-		config->fc_disable = 0x1;	/* 1=Tx fc off, 0=Tx fc on */
-		config->mwi_enable = 0x1;	/* 1=enable, 0=disable */
-		config->standard_tcb = 0x0;	/* 1=standard, 0=extended */
-		config->rx_long_ok = 0x1;	/* 1=VLANs ok, 0=standard */
-		if (nic->mac >= mac_82559_D101M) {
-			config->tno_intr = 0x1;		/* TCO stats enable */
-			/* Enable TCO in extended config */
-			if (nic->mac >= mac_82551_10) {
-				config->byte_count = 0x20; /* extended bytes */
-				config->rx_d102_mode = 0x1; /* GMRC for TCO */
-			}
-		} else {
-			config->standard_stat_counter = 0x0;
-		}
-	}
-
-	netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
-		     "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-		     c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]);
-	netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
-		     "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-		     c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]);
-	netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
-		     "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-		     c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
-}
-
-/*************************************************************************
-*  CPUSaver parameters
-*
-*  All CPUSaver parameters are 16-bit literals that are part of a
-*  "move immediate value" instruction.  By changing the value of
-*  the literal in the instruction before the code is loaded, the
-*  driver can change the algorithm.
-*
-*  INTDELAY - This loads the dead-man timer with its initial value.
-*    When this timer expires the interrupt is asserted, and the
-*    timer is reset each time a new packet is received.  (see
-*    BUNDLEMAX below to set the limit on number of chained packets)
-*    The current default is 0x600 or 1536.  Experiments show that
-*    the value should probably stay within the 0x200 - 0x1000.
-*
-*  BUNDLEMAX -
-*    This sets the maximum number of frames that will be bundled.  In
-*    some situations, such as the TCP windowing algorithm, it may be
-*    better to limit the growth of the bundle size than let it go as
-*    high as it can, because that could cause too much added latency.
-*    The default is six, because this is the number of packets in the
-*    default TCP window size.  A value of 1 would make CPUSaver indicate
-*    an interrupt for every frame received.  If you do not want to put
-*    a limit on the bundle size, set this value to xFFFF.
-*
-*  BUNDLESMALL -
-*    This contains a bit-mask describing the minimum size frame that
-*    will be bundled.  The default masks the lower 7 bits, which means
-*    that any frame less than 128 bytes in length will not be bundled,
-*    but will instead immediately generate an interrupt.  This does
-*    not affect the current bundle in any way.  Any frame that is 128
-*    bytes or large will be bundled normally.  This feature is meant
-*    to provide immediate indication of ACK frames in a TCP environment.
-*    Customers were seeing poor performance when a machine with CPUSaver
-*    enabled was sending but not receiving.  The delay introduced when
-*    the ACKs were received was enough to reduce total throughput, because
-*    the sender would sit idle until the ACK was finally seen.
-*
-*    The current default is 0xFF80, which masks out the lower 7 bits.
-*    This means that any frame which is x7F (127) bytes or smaller
-*    will cause an immediate interrupt.  Because this value must be a
-*    bit mask, there are only a few valid values that can be used.  To
-*    turn this feature off, the driver can write the value xFFFF to the
-*    lower word of this instruction (in the same way that the other
-*    parameters are used).  Likewise, a value of 0xF800 (2047) would
-*    cause an interrupt to be generated for every frame, because all
-*    standard Ethernet frames are <= 2047 bytes in length.
-*************************************************************************/
-
-/* if you wish to disable the ucode functionality, while maintaining the
- * workarounds it provides, set the following defines to:
- * BUNDLESMALL 0
- * BUNDLEMAX 1
- * INTDELAY 1
- */
-#define BUNDLESMALL 1
-#define BUNDLEMAX (u16)6
-#define INTDELAY (u16)1536 /* 0x600 */
-
-/* Initialize firmware */
-static const struct firmware *e100_reject_firmware(struct nic *nic)
-{
-	const char *fw_name;
-	const struct firmware *fw = nic->fw;
-	u8 timer, bundle, min_size;
-	int err = 0;
-
-	/* do not load u-code for ICH devices */
-	if (nic->flags & ich)
-		return NULL;
-
-	/* Search for ucode match against h/w revision */
-	if (nic->mac == mac_82559_D101M)
-		fw_name = FIRMWARE_D101M;
-	else if (nic->mac == mac_82559_D101S)
-		fw_name = FIRMWARE_D101S;
-	else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10)
-		fw_name = FIRMWARE_D102E;
-	else /* No ucode on other devices */
-		return NULL;
-
-	/* If the firmware has not previously been loaded, request a pointer
-	 * to it. If it was previously loaded, we are reinitializing the
-	 * adapter, possibly in a resume from hibernate, in which case
-	 * reject_firmware() cannot be used.
-	 */
-	if (!fw)
-		err = reject_firmware(&fw, fw_name, &nic->pdev->dev);
-
-	if (err) {
-		netif_err(nic, probe, nic->netdev,
-			  "Failed to load firmware \"%s\": %d\n",
-			  fw_name, err);
-		netif_err(nic, probe, nic->netdev, "Proceeding without firmware\n");
-		return NULL;
-	}
-
-	/* Firmware should be precisely UCODE_SIZE (words) plus three bytes
-	   indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */
-	if (fw->size != UCODE_SIZE * 4 + 3) {
-		netif_err(nic, probe, nic->netdev,
-			  "Firmware \"%s\" has wrong size %zu\n",
-			  fw_name, fw->size);
-		release_firmware(fw);
-		return ERR_PTR(-EINVAL);
-	}
-
-	/* Read timer, bundle and min_size from end of firmware blob */
-	timer = fw->data[UCODE_SIZE * 4];
-	bundle = fw->data[UCODE_SIZE * 4 + 1];
-	min_size = fw->data[UCODE_SIZE * 4 + 2];
-
-	if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE ||
-	    min_size >= UCODE_SIZE) {
-		netif_err(nic, probe, nic->netdev,
-			  "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n",
-			  fw_name, timer, bundle, min_size);
-		release_firmware(fw);
-		return ERR_PTR(-EINVAL);
-	}
-
-	/* OK, firmware is validated and ready to use. Save a pointer
-	 * to it in the nic */
-	nic->fw = fw;
-	return fw;
-}
-
-static void e100_setup_ucode(struct nic *nic, struct cb *cb,
-			     struct sk_buff *skb)
-{
-	const struct firmware *fw = (void *)skb;
-	u8 timer, bundle, min_size;
-
-	/* It's not a real skb; we just abused the fact that e100_exec_cb
-	   will pass it through to here... */
-	cb->skb = NULL;
-
-	/* firmware is stored as little endian already */
-	memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4);
-
-	/* Read timer, bundle and min_size from end of firmware blob */
-	timer = fw->data[UCODE_SIZE * 4];
-	bundle = fw->data[UCODE_SIZE * 4 + 1];
-	min_size = fw->data[UCODE_SIZE * 4 + 2];
-
-	/* Insert user-tunable settings in cb->u.ucode */
-	cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000);
-	cb->u.ucode[timer] |= cpu_to_le32(INTDELAY);
-	cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000);
-	cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX);
-	cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000);
-	cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80);
-
-	cb->command = cpu_to_le16(cb_ucode | cb_el);
-}
-
-static inline int e100_load_ucode_wait(struct nic *nic)
-{
-	const struct firmware *fw;
-	int err = 0, counter = 50;
-	struct cb *cb = nic->cb_to_clean;
-
-	fw = e100_reject_firmware(nic);
-	/* If it's NULL, then no ucode is required */
-	if (!fw || IS_ERR(fw))
-		return PTR_ERR(fw);
-
-	if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode)))
-		netif_err(nic, probe, nic->netdev,
-			  "ucode cmd failed with error %d\n", err);
-
-	/* must restart cuc */
-	nic->cuc_cmd = cuc_start;
-
-	/* wait for completion */
-	e100_write_flush(nic);
-	udelay(10);
-
-	/* wait for possibly (ouch) 500ms */
-	while (!(cb->status & cpu_to_le16(cb_complete))) {
-		msleep(10);
-		if (!--counter) break;
-	}
-
-	/* ack any interrupts, something could have been set */
-	iowrite8(~0, &nic->csr->scb.stat_ack);
-
-	/* if the command failed, or is not OK, notify and return */
-	if (!counter || !(cb->status & cpu_to_le16(cb_ok))) {
-		netif_err(nic, probe, nic->netdev, "ucode load failed\n");
-		err = -EPERM;
-	}
-
-	return err;
-}
-
-static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
-	struct sk_buff *skb)
-{
-	cb->command = cpu_to_le16(cb_iaaddr);
-	memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN);
-}
-
-static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb)
-{
-	cb->command = cpu_to_le16(cb_dump);
-	cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr +
-		offsetof(struct mem, dump_buf));
-}
-
-static int e100_phy_check_without_mii(struct nic *nic)
-{
-	u8 phy_type;
-	int without_mii;
-
-	phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f;
-
-	switch (phy_type) {
-	case NoSuchPhy: /* Non-MII PHY; UNTESTED! */
-	case I82503: /* Non-MII PHY; UNTESTED! */
-	case S80C24: /* Non-MII PHY; tested and working */
-		/* paragraph from the FreeBSD driver, "FXP_PHY_80C24":
-		 * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter
-		 * doesn't have a programming interface of any sort.  The
-		 * media is sensed automatically based on how the link partner
-		 * is configured.  This is, in essence, manual configuration.
-		 */
-		netif_info(nic, probe, nic->netdev,
-			   "found MII-less i82503 or 80c24 or other PHY\n");
-
-		nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated;
-		nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */
-
-		/* these might be needed for certain MII-less cards...
-		 * nic->flags |= ich;
-		 * nic->flags |= ich_10h_workaround; */
-
-		without_mii = 1;
-		break;
-	default:
-		without_mii = 0;
-		break;
-	}
-	return without_mii;
-}
-
-#define NCONFIG_AUTO_SWITCH	0x0080
-#define MII_NSC_CONG		MII_RESV1
-#define NSC_CONG_ENABLE		0x0100
-#define NSC_CONG_TXREADY	0x0400
-#define ADVERTISE_FC_SUPPORTED	0x0400
-static int e100_phy_init(struct nic *nic)
-{
-	struct net_device *netdev = nic->netdev;
-	u32 addr;
-	u16 bmcr, stat, id_lo, id_hi, cong;
-
-	/* Discover phy addr by searching addrs in order {1,0,2,..., 31} */
-	for (addr = 0; addr < 32; addr++) {
-		nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr;
-		bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR);
-		stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR);
-		stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR);
-		if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
-			break;
-	}
-	if (addr == 32) {
-		/* uhoh, no PHY detected: check whether we seem to be some
-		 * weird, rare variant which is *known* to not have any MII.
-		 * But do this AFTER MII checking only, since this does
-		 * lookup of EEPROM values which may easily be unreliable. */
-		if (e100_phy_check_without_mii(nic))
-			return 0; /* simply return and hope for the best */
-		else {
-			/* for unknown cases log a fatal error */
-			netif_err(nic, hw, nic->netdev,
-				  "Failed to locate any known PHY, aborting\n");
-			return -EAGAIN;
-		}
-	} else
-		netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
-			     "phy_addr = %d\n", nic->mii.phy_id);
-
-	/* Get phy ID */
-	id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1);
-	id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2);
-	nic->phy = (u32)id_hi << 16 | (u32)id_lo;
-	netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
-		     "phy ID = 0x%08X\n", nic->phy);
-
-	/* Select the phy and isolate the rest */
-	for (addr = 0; addr < 32; addr++) {
-		if (addr != nic->mii.phy_id) {
-			mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
-		} else if (nic->phy != phy_82552_v) {
-			bmcr = mdio_read(netdev, addr, MII_BMCR);
-			mdio_write(netdev, addr, MII_BMCR,
-				bmcr & ~BMCR_ISOLATE);
-		}
-	}
-	/*
-	 * Workaround for 82552:
-	 * Clear the ISOLATE bit on selected phy_id last (mirrored on all
-	 * other phy_id's) using bmcr value from addr discovery loop above.
-	 */
-	if (nic->phy == phy_82552_v)
-		mdio_write(netdev, nic->mii.phy_id, MII_BMCR,
-			bmcr & ~BMCR_ISOLATE);
-
-	/* Handle National tx phys */
-#define NCS_PHY_MODEL_MASK	0xFFF0FFFF
-	if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) {
-		/* Disable congestion control */
-		cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG);
-		cong |= NSC_CONG_TXREADY;
-		cong &= ~NSC_CONG_ENABLE;
-		mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
-	}
-
-	if (nic->phy == phy_82552_v) {
-		u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE);
-
-		/* assign special tweaked mdio_ctrl() function */
-		nic->mdio_ctrl = mdio_ctrl_phy_82552_v;
-
-		/* Workaround Si not advertising flow-control during autoneg */
-		advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
-		mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert);
-
-		/* Reset for the above changes to take effect */
-		bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR);
-		bmcr |= BMCR_RESET;
-		mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr);
-	} else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
-	   (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) &&
-		!(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) {
-		/* enable/disable MDI/MDI-X auto-switching. */
-		mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG,
-				nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH);
-	}
-
-	return 0;
-}
-
-static int e100_hw_init(struct nic *nic)
-{
-	int err = 0;
-
-	e100_hw_reset(nic);
-
-	netif_err(nic, hw, nic->netdev, "e100_hw_init\n");
-	if (!in_interrupt() && (err = e100_self_test(nic)))
-		return err;
-
-	if ((err = e100_phy_init(nic)))
-		return err;
-	if ((err = e100_exec_cmd(nic, cuc_load_base, 0)))
-		return err;
-	if ((err = e100_exec_cmd(nic, ruc_load_base, 0)))
-		return err;
-	if ((err = e100_load_ucode_wait(nic)))
-		return err;
-	if ((err = e100_exec_cb(nic, NULL, e100_configure)))
-		return err;
-	if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr)))
-		return err;
-	if ((err = e100_exec_cmd(nic, cuc_dump_addr,
-		nic->dma_addr + offsetof(struct mem, stats))))
-		return err;
-	if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0)))
-		return err;
-
-	e100_disable_irq(nic);
-
-	return 0;
-}
-
-static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb)
-{
-	struct net_device *netdev = nic->netdev;
-	struct netdev_hw_addr *ha;
-	u16 i, count = min(netdev_mc_count(netdev), E100_MAX_MULTICAST_ADDRS);
-
-	cb->command = cpu_to_le16(cb_multi);
-	cb->u.multi.count = cpu_to_le16(count * ETH_ALEN);
-	i = 0;
-	netdev_for_each_mc_addr(ha, netdev) {
-		if (i == count)
-			break;
-		memcpy(&cb->u.multi.addr[i++ * ETH_ALEN], &ha->addr,
-			ETH_ALEN);
-	}
-}
-
-static void e100_set_multicast_list(struct net_device *netdev)
-{
-	struct nic *nic = netdev_priv(netdev);
-
-	netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
-		     "mc_count=%d, flags=0x%04X\n",
-		     netdev_mc_count(netdev), netdev->flags);
-
-	if (netdev->flags & IFF_PROMISC)
-		nic->flags |= promiscuous;
-	else
-		nic->flags &= ~promiscuous;
-
-	if (netdev->flags & IFF_ALLMULTI ||
-		netdev_mc_count(netdev) > E100_MAX_MULTICAST_ADDRS)
-		nic->flags |= multicast_all;
-	else
-		nic->flags &= ~multicast_all;
-
-	e100_exec_cb(nic, NULL, e100_configure);
-	e100_exec_cb(nic, NULL, e100_multi);
-}
-
-static void e100_update_stats(struct nic *nic)
-{
-	struct net_device *dev = nic->netdev;
-	struct net_device_stats *ns = &dev->stats;
-	struct stats *s = &nic->mem->stats;
-	__le32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause :
-		(nic->mac < mac_82559_D101M) ? (__le32 *)&s->xmt_tco_frames :
-		&s->complete;
-
-	/* Device's stats reporting may take several microseconds to
-	 * complete, so we're always waiting for results of the
-	 * previous command. */
-
-	if (*complete == cpu_to_le32(cuc_dump_reset_complete)) {
-		*complete = 0;
-		nic->tx_frames = le32_to_cpu(s->tx_good_frames);
-		nic->tx_collisions = le32_to_cpu(s->tx_total_collisions);
-		ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions);
-		ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions);
-		ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs);
-		ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns);
-		ns->collisions += nic->tx_collisions;
-		ns->tx_errors += le32_to_cpu(s->tx_max_collisions) +
-			le32_to_cpu(s->tx_lost_crs);
-		ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) +
-			nic->rx_over_length_errors;
-		ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors);
-		ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors);
-		ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors);
-		ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors);
-		ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors);
-		ns->rx_errors += le32_to_cpu(s->rx_crc_errors) +
-			le32_to_cpu(s->rx_alignment_errors) +
-			le32_to_cpu(s->rx_short_frame_errors) +
-			le32_to_cpu(s->rx_cdt_errors);
-		nic->tx_deferred += le32_to_cpu(s->tx_deferred);
-		nic->tx_single_collisions +=
-			le32_to_cpu(s->tx_single_collisions);
-		nic->tx_multiple_collisions +=
-			le32_to_cpu(s->tx_multiple_collisions);
-		if (nic->mac >= mac_82558_D101_A4) {
-			nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause);
-			nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause);
-			nic->rx_fc_unsupported +=
-				le32_to_cpu(s->fc_rcv_unsupported);
-			if (nic->mac >= mac_82559_D101M) {
-				nic->tx_tco_frames +=
-					le16_to_cpu(s->xmt_tco_frames);
-				nic->rx_tco_frames +=
-					le16_to_cpu(s->rcv_tco_frames);
-			}
-		}
-	}
-
-
-	if (e100_exec_cmd(nic, cuc_dump_reset, 0))
-		netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev,
-			     "exec cuc_dump_reset failed\n");
-}
-
-static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex)
-{
-	/* Adjust inter-frame-spacing (IFS) between two transmits if
-	 * we're getting collisions on a half-duplex connection. */
-
-	if (duplex == DUPLEX_HALF) {
-		u32 prev = nic->adaptive_ifs;
-		u32 min_frames = (speed == SPEED_100) ? 1000 : 100;
-
-		if ((nic->tx_frames / 32 < nic->tx_collisions) &&
-		   (nic->tx_frames > min_frames)) {
-			if (nic->adaptive_ifs < 60)
-				nic->adaptive_ifs += 5;
-		} else if (nic->tx_frames < min_frames) {
-			if (nic->adaptive_ifs >= 5)
-				nic->adaptive_ifs -= 5;
-		}
-		if (nic->adaptive_ifs != prev)
-			e100_exec_cb(nic, NULL, e100_configure);
-	}
-}
-
-static void e100_watchdog(unsigned long data)
-{
-	struct nic *nic = (struct nic *)data;
-	struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET };
-	u32 speed;
-
-	netif_printk(nic, timer, KERN_DEBUG, nic->netdev,
-		     "right now = %ld\n", jiffies);
-
-	/* mii library handles link maintenance tasks */
-
-	mii_ethtool_gset(&nic->mii, &cmd);
-	speed = ethtool_cmd_speed(&cmd);
-
-	if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) {
-		netdev_info(nic->netdev, "NIC Link is Up %u Mbps %s Duplex\n",
-			    speed == SPEED_100 ? 100 : 10,
-			    cmd.duplex == DUPLEX_FULL ? "Full" : "Half");
-	} else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) {
-		netdev_info(nic->netdev, "NIC Link is Down\n");
-	}
-
-	mii_check_link(&nic->mii);
-
-	/* Software generated interrupt to recover from (rare) Rx
-	 * allocation failure.
-	 * Unfortunately have to use a spinlock to not re-enable interrupts
-	 * accidentally, due to hardware that shares a register between the
-	 * interrupt mask bit and the SW Interrupt generation bit */
-	spin_lock_irq(&nic->cmd_lock);
-	iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi);
-	e100_write_flush(nic);
-	spin_unlock_irq(&nic->cmd_lock);
-
-	e100_update_stats(nic);
-	e100_adjust_adaptive_ifs(nic, speed, cmd.duplex);
-
-	if (nic->mac <= mac_82557_D100_C)
-		/* Issue a multicast command to workaround a 557 lock up */
-		e100_set_multicast_list(nic->netdev);
-
-	if (nic->flags & ich && speed == SPEED_10 && cmd.duplex == DUPLEX_HALF)
-		/* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */
-		nic->flags |= ich_10h_workaround;
-	else
-		nic->flags &= ~ich_10h_workaround;
-
-	mod_timer(&nic->watchdog,
-		  round_jiffies(jiffies + E100_WATCHDOG_PERIOD));
-}
-
-static void e100_xmit_prepare(struct nic *nic, struct cb *cb,
-	struct sk_buff *skb)
-{
-	cb->command = nic->tx_command;
-	/* interrupt every 16 packets regardless of delay */
-	if ((nic->cbs_avail & ~15) == nic->cbs_avail)
-		cb->command |= cpu_to_le16(cb_i);
-	cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd);
-	cb->u.tcb.tcb_byte_count = 0;
-	cb->u.tcb.threshold = nic->tx_threshold;
-	cb->u.tcb.tbd_count = 1;
-	cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev,
-		skb->data, skb->len, PCI_DMA_TODEVICE));
-	/* check for mapping failure? */
-	cb->u.tcb.tbd.size = cpu_to_le16(skb->len);
-}
-
-static netdev_tx_t e100_xmit_frame(struct sk_buff *skb,
-				   struct net_device *netdev)
-{
-	struct nic *nic = netdev_priv(netdev);
-	int err;
-
-	if (nic->flags & ich_10h_workaround) {
-		/* SW workaround for ICH[x] 10Mbps/half duplex Tx hang.
-		   Issue a NOP command followed by a 1us delay before
-		   issuing the Tx command. */
-		if (e100_exec_cmd(nic, cuc_nop, 0))
-			netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev,
-				     "exec cuc_nop failed\n");
-		udelay(1);
-	}
-
-	err = e100_exec_cb(nic, skb, e100_xmit_prepare);
-
-	switch (err) {
-	case -ENOSPC:
-		/* We queued the skb, but now we're out of space. */
-		netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev,
-			     "No space for CB\n");
-		netif_stop_queue(netdev);
-		break;
-	case -ENOMEM:
-		/* This is a hard error - log it. */
-		netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev,
-			     "Out of Tx resources, returning skb\n");
-		netif_stop_queue(netdev);
-		return NETDEV_TX_BUSY;
-	}
-
-	return NETDEV_TX_OK;
-}
-
-static int e100_tx_clean(struct nic *nic)
-{
-	struct net_device *dev = nic->netdev;
-	struct cb *cb;
-	int tx_cleaned = 0;
-
-	spin_lock(&nic->cb_lock);
-
-	/* Clean CBs marked complete */
-	for (cb = nic->cb_to_clean;
-	    cb->status & cpu_to_le16(cb_complete);
-	    cb = nic->cb_to_clean = cb->next) {
-		rmb(); /* read skb after status */
-		netif_printk(nic, tx_done, KERN_DEBUG, nic->netdev,
-			     "cb[%d]->status = 0x%04X\n",
-			     (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)),
-			     cb->status);
-
-		if (likely(cb->skb != NULL)) {
-			dev->stats.tx_packets++;
-			dev->stats.tx_bytes += cb->skb->len;
-
-			pci_unmap_single(nic->pdev,
-				le32_to_cpu(cb->u.tcb.tbd.buf_addr),
-				le16_to_cpu(cb->u.tcb.tbd.size),
-				PCI_DMA_TODEVICE);
-			dev_kfree_skb_any(cb->skb);
-			cb->skb = NULL;
-			tx_cleaned = 1;
-		}
-		cb->status = 0;
-		nic->cbs_avail++;
-	}
-
-	spin_unlock(&nic->cb_lock);
-
-	/* Recover from running out of Tx resources in xmit_frame */
-	if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev)))
-		netif_wake_queue(nic->netdev);
-
-	return tx_cleaned;
-}
-
-static void e100_clean_cbs(struct nic *nic)
-{
-	if (nic->cbs) {
-		while (nic->cbs_avail != nic->params.cbs.count) {
-			struct cb *cb = nic->cb_to_clean;
-			if (cb->skb) {
-				pci_unmap_single(nic->pdev,
-					le32_to_cpu(cb->u.tcb.tbd.buf_addr),
-					le16_to_cpu(cb->u.tcb.tbd.size),
-					PCI_DMA_TODEVICE);
-				dev_kfree_skb(cb->skb);
-			}
-			nic->cb_to_clean = nic->cb_to_clean->next;
-			nic->cbs_avail++;
-		}
-		pci_pool_free(nic->cbs_pool, nic->cbs, nic->cbs_dma_addr);
-		nic->cbs = NULL;
-		nic->cbs_avail = 0;
-	}
-	nic->cuc_cmd = cuc_start;
-	nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean =
-		nic->cbs;
-}
-
-static int e100_alloc_cbs(struct nic *nic)
-{
-	struct cb *cb;
-	unsigned int i, count = nic->params.cbs.count;
-
-	nic->cuc_cmd = cuc_start;
-	nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL;
-	nic->cbs_avail = 0;
-
-	nic->cbs = pci_pool_alloc(nic->cbs_pool, GFP_KERNEL,
-				  &nic->cbs_dma_addr);
-	if (!nic->cbs)
-		return -ENOMEM;
-	memset(nic->cbs, 0, count * sizeof(struct cb));
-
-	for (cb = nic->cbs, i = 0; i < count; cb++, i++) {
-		cb->next = (i + 1 < count) ? cb + 1 : nic->cbs;
-		cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1;
-
-		cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb);
-		cb->link = cpu_to_le32(nic->cbs_dma_addr +
-			((i+1) % count) * sizeof(struct cb));
-	}
-
-	nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs;
-	nic->cbs_avail = count;
-
-	return 0;
-}
-
-static inline void e100_start_receiver(struct nic *nic, struct rx *rx)
-{
-	if (!nic->rxs) return;
-	if (RU_SUSPENDED != nic->ru_running) return;
-
-	/* handle init time starts */
-	if (!rx) rx = nic->rxs;
-
-	/* (Re)start RU if suspended or idle and RFA is non-NULL */
-	if (rx->skb) {
-		e100_exec_cmd(nic, ruc_start, rx->dma_addr);
-		nic->ru_running = RU_RUNNING;
-	}
-}
-
-#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN)
-static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
-{
-	if (!(rx->skb = netdev_alloc_skb_ip_align(nic->netdev, RFD_BUF_LEN)))
-		return -ENOMEM;
-
-	/* Init, and map the RFD. */
-	skb_copy_to_linear_data(rx->skb, &nic->blank_rfd, sizeof(struct rfd));
-	rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data,
-		RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
-
-	if (pci_dma_mapping_error(nic->pdev, rx->dma_addr)) {
-		dev_kfree_skb_any(rx->skb);
-		rx->skb = NULL;
-		rx->dma_addr = 0;
-		return -ENOMEM;
-	}
-
-	/* Link the RFD to end of RFA by linking previous RFD to
-	 * this one.  We are safe to touch the previous RFD because
-	 * it is protected by the before last buffer's el bit being set */
-	if (rx->prev->skb) {
-		struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data;
-		put_unaligned_le32(rx->dma_addr, &prev_rfd->link);
-		pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr,
-			sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL);
-	}
-
-	return 0;
-}
-
-static int e100_rx_indicate(struct nic *nic, struct rx *rx,
-	unsigned int *work_done, unsigned int work_to_do)
-{
-	struct net_device *dev = nic->netdev;
-	struct sk_buff *skb = rx->skb;
-	struct rfd *rfd = (struct rfd *)skb->data;
-	u16 rfd_status, actual_size;
-
-	if (unlikely(work_done && *work_done >= work_to_do))
-		return -EAGAIN;
-
-	/* Need to sync before taking a peek at cb_complete bit */
-	pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr,
-		sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL);
-	rfd_status = le16_to_cpu(rfd->status);
-
-	netif_printk(nic, rx_status, KERN_DEBUG, nic->netdev,
-		     "status=0x%04X\n", rfd_status);
-	rmb(); /* read size after status bit */
-
-	/* If data isn't ready, nothing to indicate */
-	if (unlikely(!(rfd_status & cb_complete))) {
-		/* If the next buffer has the el bit, but we think the receiver
-		 * is still running, check to see if it really stopped while
-		 * we had interrupts off.
-		 * This allows for a fast restart without re-enabling
-		 * interrupts */
-		if ((le16_to_cpu(rfd->command) & cb_el) &&
-		    (RU_RUNNING == nic->ru_running))
-
-			if (ioread8(&nic->csr->scb.status) & rus_no_res)
-				nic->ru_running = RU_SUSPENDED;
-		pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr,
-					       sizeof(struct rfd),
-					       PCI_DMA_FROMDEVICE);
-		return -ENODATA;
-	}
-
-	/* Get actual data size */
-	actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF;
-	if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd)))
-		actual_size = RFD_BUF_LEN - sizeof(struct rfd);
-
-	/* Get data */
-	pci_unmap_single(nic->pdev, rx->dma_addr,
-		RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
-
-	/* If this buffer has the el bit, but we think the receiver
-	 * is still running, check to see if it really stopped while
-	 * we had interrupts off.
-	 * This allows for a fast restart without re-enabling interrupts.
-	 * This can happen when the RU sees the size change but also sees
-	 * the el bit set. */
-	if ((le16_to_cpu(rfd->command) & cb_el) &&
-	    (RU_RUNNING == nic->ru_running)) {
-
-	    if (ioread8(&nic->csr->scb.status) & rus_no_res)
-		nic->ru_running = RU_SUSPENDED;
-	}
-
-	/* Pull off the RFD and put the actual data (minus eth hdr) */
-	skb_reserve(skb, sizeof(struct rfd));
-	skb_put(skb, actual_size);
-	skb->protocol = eth_type_trans(skb, nic->netdev);
-
-	if (unlikely(!(rfd_status & cb_ok))) {
-		/* Don't indicate if hardware indicates errors */
-		dev_kfree_skb_any(skb);
-	} else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) {
-		/* Don't indicate oversized frames */
-		nic->rx_over_length_errors++;
-		dev_kfree_skb_any(skb);
-	} else {
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += actual_size;
-		netif_receive_skb(skb);
-		if (work_done)
-			(*work_done)++;
-	}
-
-	rx->skb = NULL;
-
-	return 0;
-}
-
-static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
-	unsigned int work_to_do)
-{
-	struct rx *rx;
-	int restart_required = 0, err = 0;
-	struct rx *old_before_last_rx, *new_before_last_rx;
-	struct rfd *old_before_last_rfd, *new_before_last_rfd;
-
-	/* Indicate newly arrived packets */
-	for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
-		err = e100_rx_indicate(nic, rx, work_done, work_to_do);
-		/* Hit quota or no more to clean */
-		if (-EAGAIN == err || -ENODATA == err)
-			break;
-	}
-
-
-	/* On EAGAIN, hit quota so have more work to do, restart once
-	 * cleanup is complete.
-	 * Else, are we already rnr? then pay attention!!! this ensures that
-	 * the state machine progression never allows a start with a
-	 * partially cleaned list, avoiding a race between hardware
-	 * and rx_to_clean when in NAPI mode */
-	if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running)
-		restart_required = 1;
-
-	old_before_last_rx = nic->rx_to_use->prev->prev;
-	old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data;
-
-	/* Alloc new skbs to refill list */
-	for (rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
-		if (unlikely(e100_rx_alloc_skb(nic, rx)))
-			break; /* Better luck next time (see watchdog) */
-	}
-
-	new_before_last_rx = nic->rx_to_use->prev->prev;
-	if (new_before_last_rx != old_before_last_rx) {
-		/* Set the el-bit on the buffer that is before the last buffer.
-		 * This lets us update the next pointer on the last buffer
-		 * without worrying about hardware touching it.
-		 * We set the size to 0 to prevent hardware from touching this
-		 * buffer.
-		 * When the hardware hits the before last buffer with el-bit
-		 * and size of 0, it will RNR interrupt, the RUS will go into
-		 * the No Resources state.  It will not complete nor write to
-		 * this buffer. */
-		new_before_last_rfd =
-			(struct rfd *)new_before_last_rx->skb->data;
-		new_before_last_rfd->size = 0;
-		new_before_last_rfd->command |= cpu_to_le16(cb_el);
-		pci_dma_sync_single_for_device(nic->pdev,
-			new_before_last_rx->dma_addr, sizeof(struct rfd),
-			PCI_DMA_BIDIRECTIONAL);
-
-		/* Now that we have a new stopping point, we can clear the old
-		 * stopping point.  We must sync twice to get the proper
-		 * ordering on the hardware side of things. */
-		old_before_last_rfd->command &= ~cpu_to_le16(cb_el);
-		pci_dma_sync_single_for_device(nic->pdev,
-			old_before_last_rx->dma_addr, sizeof(struct rfd),
-			PCI_DMA_BIDIRECTIONAL);
-		old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN);
-		pci_dma_sync_single_for_device(nic->pdev,
-			old_before_last_rx->dma_addr, sizeof(struct rfd),
-			PCI_DMA_BIDIRECTIONAL);
-	}
-
-	if (restart_required) {
-		// ack the rnr?
-		iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack);
-		e100_start_receiver(nic, nic->rx_to_clean);
-		if (work_done)
-			(*work_done)++;
-	}
-}
-
-static void e100_rx_clean_list(struct nic *nic)
-{
-	struct rx *rx;
-	unsigned int i, count = nic->params.rfds.count;
-
-	nic->ru_running = RU_UNINITIALIZED;
-
-	if (nic->rxs) {
-		for (rx = nic->rxs, i = 0; i < count; rx++, i++) {
-			if (rx->skb) {
-				pci_unmap_single(nic->pdev, rx->dma_addr,
-					RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
-				dev_kfree_skb(rx->skb);
-			}
-		}
-		kfree(nic->rxs);
-		nic->rxs = NULL;
-	}
-
-	nic->rx_to_use = nic->rx_to_clean = NULL;
-}
-
-static int e100_rx_alloc_list(struct nic *nic)
-{
-	struct rx *rx;
-	unsigned int i, count = nic->params.rfds.count;
-	struct rfd *before_last;
-
-	nic->rx_to_use = nic->rx_to_clean = NULL;
-	nic->ru_running = RU_UNINITIALIZED;
-
-	if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC)))
-		return -ENOMEM;
-
-	for (rx = nic->rxs, i = 0; i < count; rx++, i++) {
-		rx->next = (i + 1 < count) ? rx + 1 : nic->rxs;
-		rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1;
-		if (e100_rx_alloc_skb(nic, rx)) {
-			e100_rx_clean_list(nic);
-			return -ENOMEM;
-		}
-	}
-	/* Set the el-bit on the buffer that is before the last buffer.
-	 * This lets us update the next pointer on the last buffer without
-	 * worrying about hardware touching it.
-	 * We set the size to 0 to prevent hardware from touching this buffer.
-	 * When the hardware hits the before last buffer with el-bit and size
-	 * of 0, it will RNR interrupt, the RU will go into the No Resources
-	 * state.  It will not complete nor write to this buffer. */
-	rx = nic->rxs->prev->prev;
-	before_last = (struct rfd *)rx->skb->data;
-	before_last->command |= cpu_to_le16(cb_el);
-	before_last->size = 0;
-	pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr,
-		sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL);
-
-	nic->rx_to_use = nic->rx_to_clean = nic->rxs;
-	nic->ru_running = RU_SUSPENDED;
-
-	return 0;
-}
-
-static irqreturn_t e100_intr(int irq, void *dev_id)
-{
-	struct net_device *netdev = dev_id;
-	struct nic *nic = netdev_priv(netdev);
-	u8 stat_ack = ioread8(&nic->csr->scb.stat_ack);
-
-	netif_printk(nic, intr, KERN_DEBUG, nic->netdev,
-		     "stat_ack = 0x%02X\n", stat_ack);
-
-	if (stat_ack == stat_ack_not_ours ||	/* Not our interrupt */
-	   stat_ack == stat_ack_not_present)	/* Hardware is ejected */
-		return IRQ_NONE;
-
-	/* Ack interrupt(s) */
-	iowrite8(stat_ack, &nic->csr->scb.stat_ack);
-
-	/* We hit Receive No Resource (RNR); restart RU after cleaning */
-	if (stat_ack & stat_ack_rnr)
-		nic->ru_running = RU_SUSPENDED;
-
-	if (likely(napi_schedule_prep(&nic->napi))) {
-		e100_disable_irq(nic);
-		__napi_schedule(&nic->napi);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static int e100_poll(struct napi_struct *napi, int budget)
-{
-	struct nic *nic = container_of(napi, struct nic, napi);
-	unsigned int work_done = 0;
-
-	e100_rx_clean(nic, &work_done, budget);
-	e100_tx_clean(nic);
-
-	/* If budget not fully consumed, exit the polling mode */
-	if (work_done < budget) {
-		napi_complete(napi);
-		e100_enable_irq(nic);
-	}
-
-	return work_done;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void e100_netpoll(struct net_device *netdev)
-{
-	struct nic *nic = netdev_priv(netdev);
-
-	e100_disable_irq(nic);
-	e100_intr(nic->pdev->irq, netdev);
-	e100_tx_clean(nic);
-	e100_enable_irq(nic);
-}
-#endif
-
-static int e100_set_mac_address(struct net_device *netdev, void *p)
-{
-	struct nic *nic = netdev_priv(netdev);
-	struct sockaddr *addr = p;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-	e100_exec_cb(nic, NULL, e100_setup_iaaddr);
-
-	return 0;
-}
-
-static int e100_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN)
-		return -EINVAL;
-	netdev->mtu = new_mtu;
-	return 0;
-}
-
-static int e100_asf(struct nic *nic)
-{
-	/* ASF can be enabled from eeprom */
-	return (nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) &&
-	   (nic->eeprom[eeprom_config_asf] & eeprom_asf) &&
-	   !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) &&
-	   ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE);
-}
-
-static int e100_up(struct nic *nic)
-{
-	int err;
-
-	if ((err = e100_rx_alloc_list(nic)))
-		return err;
-	if ((err = e100_alloc_cbs(nic)))
-		goto err_rx_clean_list;
-	if ((err = e100_hw_init(nic)))
-		goto err_clean_cbs;
-	e100_set_multicast_list(nic->netdev);
-	e100_start_receiver(nic, NULL);
-	mod_timer(&nic->watchdog, jiffies);
-	if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
-		nic->netdev->name, nic->netdev)))
-		goto err_no_irq;
-	netif_wake_queue(nic->netdev);
-	napi_enable(&nic->napi);
-	/* enable ints _after_ enabling poll, preventing a race between
-	 * disable ints+schedule */
-	e100_enable_irq(nic);
-	return 0;
-
-err_no_irq:
-	del_timer_sync(&nic->watchdog);
-err_clean_cbs:
-	e100_clean_cbs(nic);
-err_rx_clean_list:
-	e100_rx_clean_list(nic);
-	return err;
-}
-
-static void e100_down(struct nic *nic)
-{
-	/* wait here for poll to complete */
-	napi_disable(&nic->napi);
-	netif_stop_queue(nic->netdev);
-	e100_hw_reset(nic);
-	free_irq(nic->pdev->irq, nic->netdev);
-	del_timer_sync(&nic->watchdog);
-	netif_carrier_off(nic->netdev);
-	e100_clean_cbs(nic);
-	e100_rx_clean_list(nic);
-}
-
-static void e100_tx_timeout(struct net_device *netdev)
-{
-	struct nic *nic = netdev_priv(netdev);
-
-	/* Reset outside of interrupt context, to avoid request_irq
-	 * in interrupt context */
-	schedule_work(&nic->tx_timeout_task);
-}
-
-static void e100_tx_timeout_task(struct work_struct *work)
-{
-	struct nic *nic = container_of(work, struct nic, tx_timeout_task);
-	struct net_device *netdev = nic->netdev;
-
-	netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev,
-		     "scb.status=0x%02X\n", ioread8(&nic->csr->scb.status));
-
-	rtnl_lock();
-	if (netif_running(netdev)) {
-		e100_down(netdev_priv(netdev));
-		e100_up(netdev_priv(netdev));
-	}
-	rtnl_unlock();
-}
-
-static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
-{
-	int err;
-	struct sk_buff *skb;
-
-	/* Use driver resources to perform internal MAC or PHY
-	 * loopback test.  A single packet is prepared and transmitted
-	 * in loopback mode, and the test passes if the received
-	 * packet compares byte-for-byte to the transmitted packet. */
-
-	if ((err = e100_rx_alloc_list(nic)))
-		return err;
-	if ((err = e100_alloc_cbs(nic)))
-		goto err_clean_rx;
-
-	/* ICH PHY loopback is broken so do MAC loopback instead */
-	if (nic->flags & ich && loopback_mode == lb_phy)
-		loopback_mode = lb_mac;
-
-	nic->loopback = loopback_mode;
-	if ((err = e100_hw_init(nic)))
-		goto err_loopback_none;
-
-	if (loopback_mode == lb_phy)
-		mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR,
-			BMCR_LOOPBACK);
-
-	e100_start_receiver(nic, NULL);
-
-	if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) {
-		err = -ENOMEM;
-		goto err_loopback_none;
-	}
-	skb_put(skb, ETH_DATA_LEN);
-	memset(skb->data, 0xFF, ETH_DATA_LEN);
-	e100_xmit_frame(skb, nic->netdev);
-
-	msleep(10);
-
-	pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr,
-			RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
-
-	if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
-	   skb->data, ETH_DATA_LEN))
-		err = -EAGAIN;
-
-err_loopback_none:
-	mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0);
-	nic->loopback = lb_none;
-	e100_clean_cbs(nic);
-	e100_hw_reset(nic);
-err_clean_rx:
-	e100_rx_clean_list(nic);
-	return err;
-}
-
-#define MII_LED_CONTROL	0x1B
-#define E100_82552_LED_OVERRIDE 0x19
-#define E100_82552_LED_ON       0x000F /* LEDTX and LED_RX both on */
-#define E100_82552_LED_OFF      0x000A /* LEDTX and LED_RX both off */
-
-static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
-{
-	struct nic *nic = netdev_priv(netdev);
-	return mii_ethtool_gset(&nic->mii, cmd);
-}
-
-static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
-{
-	struct nic *nic = netdev_priv(netdev);
-	int err;
-
-	mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET);
-	err = mii_ethtool_sset(&nic->mii, cmd);
-	e100_exec_cb(nic, NULL, e100_configure);
-
-	return err;
-}
-
-static void e100_get_drvinfo(struct net_device *netdev,
-	struct ethtool_drvinfo *info)
-{
-	struct nic *nic = netdev_priv(netdev);
-	strcpy(info->driver, DRV_NAME);
-	strcpy(info->version, DRV_VERSION);
-	strcpy(info->fw_version, "N/A");
-	strcpy(info->bus_info, pci_name(nic->pdev));
-}
-
-#define E100_PHY_REGS 0x1C
-static int e100_get_regs_len(struct net_device *netdev)
-{
-	struct nic *nic = netdev_priv(netdev);
-	return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf);
-}
-
-static void e100_get_regs(struct net_device *netdev,
-	struct ethtool_regs *regs, void *p)
-{
-	struct nic *nic = netdev_priv(netdev);
-	u32 *buff = p;
-	int i;
-
-	regs->version = (1 << 24) | nic->pdev->revision;
-	buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 |
-		ioread8(&nic->csr->scb.cmd_lo) << 16 |
-		ioread16(&nic->csr->scb.status);
-	for (i = E100_PHY_REGS; i >= 0; i--)
-		buff[1 + E100_PHY_REGS - i] =
-			mdio_read(netdev, nic->mii.phy_id, i);
-	memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf));
-	e100_exec_cb(nic, NULL, e100_dump);
-	msleep(10);
-	memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf,
-		sizeof(nic->mem->dump_buf));
-}
-
-static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
-{
-	struct nic *nic = netdev_priv(netdev);
-	wol->supported = (nic->mac >= mac_82558_D101_A4) ?  WAKE_MAGIC : 0;
-	wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0;
-}
-
-static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
-{
-	struct nic *nic = netdev_priv(netdev);
-
-	if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) ||
-	    !device_can_wakeup(&nic->pdev->dev))
-		return -EOPNOTSUPP;
-
-	if (wol->wolopts)
-		nic->flags |= wol_magic;
-	else
-		nic->flags &= ~wol_magic;
-
-	device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts);
-
-	e100_exec_cb(nic, NULL, e100_configure);
-
-	return 0;
-}
-
-static u32 e100_get_msglevel(struct net_device *netdev)
-{
-	struct nic *nic = netdev_priv(netdev);
-	return nic->msg_enable;
-}
-
-static void e100_set_msglevel(struct net_device *netdev, u32 value)
-{
-	struct nic *nic = netdev_priv(netdev);
-	nic->msg_enable = value;
-}
-
-static int e100_nway_reset(struct net_device *netdev)
-{
-	struct nic *nic = netdev_priv(netdev);
-	return mii_nway_restart(&nic->mii);
-}
-
-static u32 e100_get_link(struct net_device *netdev)
-{
-	struct nic *nic = netdev_priv(netdev);
-	return mii_link_ok(&nic->mii);
-}
-
-static int e100_get_eeprom_len(struct net_device *netdev)
-{
-	struct nic *nic = netdev_priv(netdev);
-	return nic->eeprom_wc << 1;
-}
-
-#define E100_EEPROM_MAGIC	0x1234
-static int e100_get_eeprom(struct net_device *netdev,
-	struct ethtool_eeprom *eeprom, u8 *bytes)
-{
-	struct nic *nic = netdev_priv(netdev);
-
-	eeprom->magic = E100_EEPROM_MAGIC;
-	memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len);
-
-	return 0;
-}
-
-static int e100_set_eeprom(struct net_device *netdev,
-	struct ethtool_eeprom *eeprom, u8 *bytes)
-{
-	struct nic *nic = netdev_priv(netdev);
-
-	if (eeprom->magic != E100_EEPROM_MAGIC)
-		return -EINVAL;
-
-	memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len);
-
-	return e100_eeprom_save(nic, eeprom->offset >> 1,
-		(eeprom->len >> 1) + 1);
-}
-
-static void e100_get_ringparam(struct net_device *netdev,
-	struct ethtool_ringparam *ring)
-{
-	struct nic *nic = netdev_priv(netdev);
-	struct param_range *rfds = &nic->params.rfds;
-	struct param_range *cbs = &nic->params.cbs;
-
-	ring->rx_max_pending = rfds->max;
-	ring->tx_max_pending = cbs->max;
-	ring->rx_mini_max_pending = 0;
-	ring->rx_jumbo_max_pending = 0;
-	ring->rx_pending = rfds->count;
-	ring->tx_pending = cbs->count;
-	ring->rx_mini_pending = 0;
-	ring->rx_jumbo_pending = 0;
-}
-
-static int e100_set_ringparam(struct net_device *netdev,
-	struct ethtool_ringparam *ring)
-{
-	struct nic *nic = netdev_priv(netdev);
-	struct param_range *rfds = &nic->params.rfds;
-	struct param_range *cbs = &nic->params.cbs;
-
-	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
-		return -EINVAL;
-
-	if (netif_running(netdev))
-		e100_down(nic);
-	rfds->count = max(ring->rx_pending, rfds->min);
-	rfds->count = min(rfds->count, rfds->max);
-	cbs->count = max(ring->tx_pending, cbs->min);
-	cbs->count = min(cbs->count, cbs->max);
-	netif_info(nic, drv, nic->netdev, "Ring Param settings: rx: %d, tx %d\n",
-		   rfds->count, cbs->count);
-	if (netif_running(netdev))
-		e100_up(nic);
-
-	return 0;
-}
-
-static const char e100_gstrings_test[][ETH_GSTRING_LEN] = {
-	"Link test     (on/offline)",
-	"Eeprom test   (on/offline)",
-	"Self test        (offline)",
-	"Mac loopback     (offline)",
-	"Phy loopback     (offline)",
-};
-#define E100_TEST_LEN	ARRAY_SIZE(e100_gstrings_test)
-
-static void e100_diag_test(struct net_device *netdev,
-	struct ethtool_test *test, u64 *data)
-{
-	struct ethtool_cmd cmd;
-	struct nic *nic = netdev_priv(netdev);
-	int i, err;
-
-	memset(data, 0, E100_TEST_LEN * sizeof(u64));
-	data[0] = !mii_link_ok(&nic->mii);
-	data[1] = e100_eeprom_load(nic);
-	if (test->flags & ETH_TEST_FL_OFFLINE) {
-
-		/* save speed, duplex & autoneg settings */
-		err = mii_ethtool_gset(&nic->mii, &cmd);
-
-		if (netif_running(netdev))
-			e100_down(nic);
-		data[2] = e100_self_test(nic);
-		data[3] = e100_loopback_test(nic, lb_mac);
-		data[4] = e100_loopback_test(nic, lb_phy);
-
-		/* restore speed, duplex & autoneg settings */
-		err = mii_ethtool_sset(&nic->mii, &cmd);
-
-		if (netif_running(netdev))
-			e100_up(nic);
-	}
-	for (i = 0; i < E100_TEST_LEN; i++)
-		test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0;
-
-	msleep_interruptible(4 * 1000);
-}
-
-static int e100_set_phys_id(struct net_device *netdev,
-			    enum ethtool_phys_id_state state)
-{
-	struct nic *nic = netdev_priv(netdev);
-	enum led_state {
-		led_on     = 0x01,
-		led_off    = 0x04,
-		led_on_559 = 0x05,
-		led_on_557 = 0x07,
-	};
-	u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE :
-		MII_LED_CONTROL;
-	u16 leds = 0;
-
-	switch (state) {
-	case ETHTOOL_ID_ACTIVE:
-		return 2;
-
-	case ETHTOOL_ID_ON:
-		leds = (nic->phy == phy_82552_v) ? E100_82552_LED_ON :
-		       (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559;
-		break;
-
-	case ETHTOOL_ID_OFF:
-		leds = (nic->phy == phy_82552_v) ? E100_82552_LED_OFF : led_off;
-		break;
-
-	case ETHTOOL_ID_INACTIVE:
-		break;
-	}
-
-	mdio_write(netdev, nic->mii.phy_id, led_reg, leds);
-	return 0;
-}
-
-static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = {
-	"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
-	"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
-	"rx_length_errors", "rx_over_errors", "rx_crc_errors",
-	"rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
-	"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
-	"tx_heartbeat_errors", "tx_window_errors",
-	/* device-specific stats */
-	"tx_deferred", "tx_single_collisions", "tx_multi_collisions",
-	"tx_flow_control_pause", "rx_flow_control_pause",
-	"rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets",
-};
-#define E100_NET_STATS_LEN	21
-#define E100_STATS_LEN	ARRAY_SIZE(e100_gstrings_stats)
-
-static int e100_get_sset_count(struct net_device *netdev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_TEST:
-		return E100_TEST_LEN;
-	case ETH_SS_STATS:
-		return E100_STATS_LEN;
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void e100_get_ethtool_stats(struct net_device *netdev,
-	struct ethtool_stats *stats, u64 *data)
-{
-	struct nic *nic = netdev_priv(netdev);
-	int i;
-
-	for (i = 0; i < E100_NET_STATS_LEN; i++)
-		data[i] = ((unsigned long *)&netdev->stats)[i];
-
-	data[i++] = nic->tx_deferred;
-	data[i++] = nic->tx_single_collisions;
-	data[i++] = nic->tx_multiple_collisions;
-	data[i++] = nic->tx_fc_pause;
-	data[i++] = nic->rx_fc_pause;
-	data[i++] = nic->rx_fc_unsupported;
-	data[i++] = nic->tx_tco_frames;
-	data[i++] = nic->rx_tco_frames;
-}
-
-static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
-{
-	switch (stringset) {
-	case ETH_SS_TEST:
-		memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test));
-		break;
-	case ETH_SS_STATS:
-		memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats));
-		break;
-	}
-}
-
-static const struct ethtool_ops e100_ethtool_ops = {
-	.get_settings		= e100_get_settings,
-	.set_settings		= e100_set_settings,
-	.get_drvinfo		= e100_get_drvinfo,
-	.get_regs_len		= e100_get_regs_len,
-	.get_regs		= e100_get_regs,
-	.get_wol		= e100_get_wol,
-	.set_wol		= e100_set_wol,
-	.get_msglevel		= e100_get_msglevel,
-	.set_msglevel		= e100_set_msglevel,
-	.nway_reset		= e100_nway_reset,
-	.get_link		= e100_get_link,
-	.get_eeprom_len		= e100_get_eeprom_len,
-	.get_eeprom		= e100_get_eeprom,
-	.set_eeprom		= e100_set_eeprom,
-	.get_ringparam		= e100_get_ringparam,
-	.set_ringparam		= e100_set_ringparam,
-	.self_test		= e100_diag_test,
-	.get_strings		= e100_get_strings,
-	.set_phys_id		= e100_set_phys_id,
-	.get_ethtool_stats	= e100_get_ethtool_stats,
-	.get_sset_count		= e100_get_sset_count,
-};
-
-static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	struct nic *nic = netdev_priv(netdev);
-
-	return generic_mii_ioctl(&nic->mii, if_mii(ifr), cmd, NULL);
-}
-
-static int e100_alloc(struct nic *nic)
-{
-	nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem),
-		&nic->dma_addr);
-	return nic->mem ? 0 : -ENOMEM;
-}
-
-static void e100_free(struct nic *nic)
-{
-	if (nic->mem) {
-		pci_free_consistent(nic->pdev, sizeof(struct mem),
-			nic->mem, nic->dma_addr);
-		nic->mem = NULL;
-	}
-}
-
-static int e100_open(struct net_device *netdev)
-{
-	struct nic *nic = netdev_priv(netdev);
-	int err = 0;
-
-	netif_carrier_off(netdev);
-	if ((err = e100_up(nic)))
-		netif_err(nic, ifup, nic->netdev, "Cannot open interface, aborting\n");
-	return err;
-}
-
-static int e100_close(struct net_device *netdev)
-{
-	e100_down(netdev_priv(netdev));
-	return 0;
-}
-
-static const struct net_device_ops e100_netdev_ops = {
-	.ndo_open		= e100_open,
-	.ndo_stop		= e100_close,
-	.ndo_start_xmit		= e100_xmit_frame,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_multicast_list	= e100_set_multicast_list,
-	.ndo_set_mac_address	= e100_set_mac_address,
-	.ndo_change_mtu		= e100_change_mtu,
-	.ndo_do_ioctl		= e100_do_ioctl,
-	.ndo_tx_timeout		= e100_tx_timeout,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= e100_netpoll,
-#endif
-};
-
-static int __devinit e100_probe(struct pci_dev *pdev,
-	const struct pci_device_id *ent)
-{
-	struct net_device *netdev;
-	struct nic *nic;
-	int err;
-
-	if (!(netdev = alloc_etherdev(sizeof(struct nic)))) {
-		if (((1 << debug) - 1) & NETIF_MSG_PROBE)
-			pr_err("Etherdev alloc failed, aborting\n");
-		return -ENOMEM;
-	}
-
-	netdev->netdev_ops = &e100_netdev_ops;
-	SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops);
-	netdev->watchdog_timeo = E100_WATCHDOG_PERIOD;
-	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
-
-	nic = netdev_priv(netdev);
-	netif_napi_add(netdev, &nic->napi, e100_poll, E100_NAPI_WEIGHT);
-	nic->netdev = netdev;
-	nic->pdev = pdev;
-	nic->msg_enable = (1 << debug) - 1;
-	nic->mdio_ctrl = mdio_ctrl_hw;
-	pci_set_drvdata(pdev, netdev);
-
-	if ((err = pci_enable_device(pdev))) {
-		netif_err(nic, probe, nic->netdev, "Cannot enable PCI device, aborting\n");
-		goto err_out_free_dev;
-	}
-
-	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
-		netif_err(nic, probe, nic->netdev, "Cannot find proper PCI device base address, aborting\n");
-		err = -ENODEV;
-		goto err_out_disable_pdev;
-	}
-
-	if ((err = pci_request_regions(pdev, DRV_NAME))) {
-		netif_err(nic, probe, nic->netdev, "Cannot obtain PCI resources, aborting\n");
-		goto err_out_disable_pdev;
-	}
-
-	if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) {
-		netif_err(nic, probe, nic->netdev, "No usable DMA configuration, aborting\n");
-		goto err_out_free_res;
-	}
-
-	SET_NETDEV_DEV(netdev, &pdev->dev);
-
-	if (use_io)
-		netif_info(nic, probe, nic->netdev, "using i/o access mode\n");
-
-	nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr));
-	if (!nic->csr) {
-		netif_err(nic, probe, nic->netdev, "Cannot map device registers, aborting\n");
-		err = -ENOMEM;
-		goto err_out_free_res;
-	}
-
-	if (ent->driver_data)
-		nic->flags |= ich;
-	else
-		nic->flags &= ~ich;
-
-	e100_get_defaults(nic);
-
-	/* locks must be initialized before calling hw_reset */
-	spin_lock_init(&nic->cb_lock);
-	spin_lock_init(&nic->cmd_lock);
-	spin_lock_init(&nic->mdio_lock);
-
-	/* Reset the device before pci_set_master() in case device is in some
-	 * funky state and has an interrupt pending - hint: we don't have the
-	 * interrupt handler registered yet. */
-	e100_hw_reset(nic);
-
-	pci_set_master(pdev);
-
-	init_timer(&nic->watchdog);
-	nic->watchdog.function = e100_watchdog;
-	nic->watchdog.data = (unsigned long)nic;
-
-	INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task);
-
-	if ((err = e100_alloc(nic))) {
-		netif_err(nic, probe, nic->netdev, "Cannot alloc driver memory, aborting\n");
-		goto err_out_iounmap;
-	}
-
-	if ((err = e100_eeprom_load(nic)))
-		goto err_out_free;
-
-	e100_phy_init(nic);
-
-	memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN);
-	memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN);
-	if (!is_valid_ether_addr(netdev->perm_addr)) {
-		if (!eeprom_bad_csum_allow) {
-			netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, aborting\n");
-			err = -EAGAIN;
-			goto err_out_free;
-		} else {
-			netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, you MUST configure one.\n");
-		}
-	}
-
-	/* Wol magic packet can be enabled from eeprom */
-	if ((nic->mac >= mac_82558_D101_A4) &&
-	   (nic->eeprom[eeprom_id] & eeprom_id_wol)) {
-		nic->flags |= wol_magic;
-		device_set_wakeup_enable(&pdev->dev, true);
-	}
-
-	/* ack any pending wake events, disable PME */
-	pci_pme_active(pdev, false);
-
-	strcpy(netdev->name, "eth%d");
-	if ((err = register_netdev(netdev))) {
-		netif_err(nic, probe, nic->netdev, "Cannot register net device, aborting\n");
-		goto err_out_free;
-	}
-	nic->cbs_pool = pci_pool_create(netdev->name,
-			   nic->pdev,
-			   nic->params.cbs.max * sizeof(struct cb),
-			   sizeof(u32),
-			   0);
-	netif_info(nic, probe, nic->netdev,
-		   "addr 0x%llx, irq %d, MAC addr %pM\n",
-		   (unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0),
-		   pdev->irq, netdev->dev_addr);
-
-	return 0;
-
-err_out_free:
-	e100_free(nic);
-err_out_iounmap:
-	pci_iounmap(pdev, nic->csr);
-err_out_free_res:
-	pci_release_regions(pdev);
-err_out_disable_pdev:
-	pci_disable_device(pdev);
-err_out_free_dev:
-	pci_set_drvdata(pdev, NULL);
-	free_netdev(netdev);
-	return err;
-}
-
-static void __devexit e100_remove(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-
-	if (netdev) {
-		struct nic *nic = netdev_priv(netdev);
-		unregister_netdev(netdev);
-		e100_free(nic);
-		pci_iounmap(pdev, nic->csr);
-		pci_pool_destroy(nic->cbs_pool);
-		free_netdev(netdev);
-		pci_release_regions(pdev);
-		pci_disable_device(pdev);
-		pci_set_drvdata(pdev, NULL);
-	}
-}
-
-#define E100_82552_SMARTSPEED   0x14   /* SmartSpeed Ctrl register */
-#define E100_82552_REV_ANEG     0x0200 /* Reverse auto-negotiation */
-#define E100_82552_ANEG_NOW     0x0400 /* Auto-negotiate now */
-static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct nic *nic = netdev_priv(netdev);
-
-	if (netif_running(netdev))
-		e100_down(nic);
-	netif_device_detach(netdev);
-
-	pci_save_state(pdev);
-
-	if ((nic->flags & wol_magic) | e100_asf(nic)) {
-		/* enable reverse auto-negotiation */
-		if (nic->phy == phy_82552_v) {
-			u16 smartspeed = mdio_read(netdev, nic->mii.phy_id,
-			                           E100_82552_SMARTSPEED);
-
-			mdio_write(netdev, nic->mii.phy_id,
-			           E100_82552_SMARTSPEED, smartspeed |
-			           E100_82552_REV_ANEG | E100_82552_ANEG_NOW);
-		}
-		*enable_wake = true;
-	} else {
-		*enable_wake = false;
-	}
-
-	pci_disable_device(pdev);
-}
-
-static int __e100_power_off(struct pci_dev *pdev, bool wake)
-{
-	if (wake)
-		return pci_prepare_to_sleep(pdev);
-
-	pci_wake_from_d3(pdev, false);
-	pci_set_power_state(pdev, PCI_D3hot);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	bool wake;
-	__e100_shutdown(pdev, &wake);
-	return __e100_power_off(pdev, wake);
-}
-
-static int e100_resume(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct nic *nic = netdev_priv(netdev);
-
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	/* ack any pending wake events, disable PME */
-	pci_enable_wake(pdev, 0, 0);
-
-	/* disable reverse auto-negotiation */
-	if (nic->phy == phy_82552_v) {
-		u16 smartspeed = mdio_read(netdev, nic->mii.phy_id,
-		                           E100_82552_SMARTSPEED);
-
-		mdio_write(netdev, nic->mii.phy_id,
-		           E100_82552_SMARTSPEED,
-		           smartspeed & ~(E100_82552_REV_ANEG));
-	}
-
-	netif_device_attach(netdev);
-	if (netif_running(netdev))
-		e100_up(nic);
-
-	return 0;
-}
-#endif /* CONFIG_PM */
-
-static void e100_shutdown(struct pci_dev *pdev)
-{
-	bool wake;
-	__e100_shutdown(pdev, &wake);
-	if (system_state == SYSTEM_POWER_OFF)
-		__e100_power_off(pdev, wake);
-}
-
-/* ------------------ PCI Error Recovery infrastructure  -------------- */
-/**
- * e100_io_error_detected - called when PCI error is detected.
- * @pdev: Pointer to PCI device
- * @state: The current pci connection state
- */
-static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct nic *nic = netdev_priv(netdev);
-
-	netif_device_detach(netdev);
-
-	if (state == pci_channel_io_perm_failure)
-		return PCI_ERS_RESULT_DISCONNECT;
-
-	if (netif_running(netdev))
-		e100_down(nic);
-	pci_disable_device(pdev);
-
-	/* Request a slot reset. */
-	return PCI_ERS_RESULT_NEED_RESET;
-}
-
-/**
- * e100_io_slot_reset - called after the pci bus has been reset.
- * @pdev: Pointer to PCI device
- *
- * Restart the card from scratch.
- */
-static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct nic *nic = netdev_priv(netdev);
-
-	if (pci_enable_device(pdev)) {
-		pr_err("Cannot re-enable PCI device after reset\n");
-		return PCI_ERS_RESULT_DISCONNECT;
-	}
-	pci_set_master(pdev);
-
-	/* Only one device per card can do a reset */
-	if (0 != PCI_FUNC(pdev->devfn))
-		return PCI_ERS_RESULT_RECOVERED;
-	e100_hw_reset(nic);
-	e100_phy_init(nic);
-
-	return PCI_ERS_RESULT_RECOVERED;
-}
-
-/**
- * e100_io_resume - resume normal operations
- * @pdev: Pointer to PCI device
- *
- * Resume normal operations after an error recovery
- * sequence has been completed.
- */
-static void e100_io_resume(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct nic *nic = netdev_priv(netdev);
-
-	/* ack any pending wake events, disable PME */
-	pci_enable_wake(pdev, 0, 0);
-
-	netif_device_attach(netdev);
-	if (netif_running(netdev)) {
-		e100_open(netdev);
-		mod_timer(&nic->watchdog, jiffies);
-	}
-}
-
-static struct pci_error_handlers e100_err_handler = {
-	.error_detected = e100_io_error_detected,
-	.slot_reset = e100_io_slot_reset,
-	.resume = e100_io_resume,
-};
-
-static struct pci_driver e100_driver = {
-	.name =         DRV_NAME,
-	.id_table =     e100_id_table,
-	.probe =        e100_probe,
-	.remove =       __devexit_p(e100_remove),
-#ifdef CONFIG_PM
-	/* Power Management hooks */
-	.suspend =      e100_suspend,
-	.resume =       e100_resume,
-#endif
-	.shutdown =     e100_shutdown,
-	.err_handler = &e100_err_handler,
-};
-
-static int __init e100_init_module(void)
-{
-	if (((1 << debug) - 1) & NETIF_MSG_DRV) {
-		pr_info("%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
-		pr_info("%s\n", DRV_COPYRIGHT);
-	}
-	return pci_register_driver(&e100_driver);
-}
-
-static void __exit e100_cleanup_module(void)
-{
-	pci_unregister_driver(&e100_driver);
-}
-
-module_init(e100_init_module);
-module_exit(e100_cleanup_module);
diff -druN linux-libre-3.1-gnu/drivers/net/e2100.c linux-libre-3.2-gnu/drivers/net/e2100.c
--- linux-libre-3.1-gnu/drivers/net/e2100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/e2100.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,490 +0,0 @@
-/* e2100.c: A Cabletron E2100 series ethernet driver for linux. */
-/*
-	Written 1993-1994 by Donald Becker.
-
-	Copyright 1994 by Donald Becker.
-	Copyright 1993 United States Government as represented by the
-	Director, National Security Agency.  This software may be used and
-	distributed according to the terms of the GNU General Public License,
-	incorporated herein by reference.
-
-	This is a driver for the Cabletron E2100 series ethercards.
-
-	The Author may be reached as becker@scyld.com, or C/O
-	Scyld Computing Corporation
-	410 Severn Ave., Suite 210
-	Annapolis MD 21403
-
-	The E2100 series ethercard is a fairly generic shared memory 8390
-	implementation.  The only unusual aspect is the way the shared memory
-	registers are set: first you do an inb() in what is normally the
-	station address region, and the low three bits of next outb() *address*
-	is used	as the write value for that register.  Either someone wasn't
-	too used to dem bit en bites, or they were trying to obfuscate the
-	programming interface.
-
-	There is an additional complication when setting the window on the packet
-	buffer.  You must first do a read into the packet buffer region with the
-	low 8 address bits the address setting the page for the start of the packet
-	buffer window, and then do the above operation.  See mem_on() for details.
-
-	One bug on the chip is that even a hard reset won't disable the memory
-	window, usually resulting in a hung machine if mem_off() isn't called.
-	If this happens, you must power down the machine for about 30 seconds.
-*/
-
-static const char version[] =
-	"e2100.c:v1.01 7/21/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include "8390.h"
-
-#define DRV_NAME "e2100"
-
-static int e21_probe_list[] = {0x300, 0x280, 0x380, 0x220, 0};
-
-/* Offsets from the base_addr.
-   Read from the ASIC register, and the low three bits of the next outb()
-   address is used to set the corresponding register. */
-#define E21_NIC_OFFSET  0		/* Offset to the 8390 NIC. */
-#define E21_ASIC		0x10
-#define E21_MEM_ENABLE	0x10
-#define  E21_MEM_ON		0x05	/* Enable memory in 16 bit mode. */
-#define  E21_MEM_ON_8	0x07	/* Enable memory in  8 bit mode. */
-#define E21_MEM_BASE	0x11
-#define E21_IRQ_LOW		0x12	/* The low three bits of the IRQ number. */
-#define E21_IRQ_HIGH	0x14	/* The high IRQ bit and media select ...  */
-#define E21_MEDIA		0x14	/* (alias). */
-#define  E21_ALT_IFPORT 0x02	/* Set to use the other (BNC,AUI) port. */
-#define  E21_BIG_MEM	0x04	/* Use a bigger (64K) buffer (we don't) */
-#define E21_SAPROM		0x10	/* Offset to station address data. */
-#define E21_IO_EXTENT	 0x20
-
-static inline void mem_on(short port, volatile char __iomem *mem_base,
-						  unsigned char start_page )
-{
-	/* This is a little weird: set the shared memory window by doing a
-	   read.  The low address bits specify the starting page. */
-	readb(mem_base+start_page);
-	inb(port + E21_MEM_ENABLE);
-	outb(E21_MEM_ON, port + E21_MEM_ENABLE + E21_MEM_ON);
-}
-
-static inline void mem_off(short port)
-{
-	inb(port + E21_MEM_ENABLE);
-	outb(0x00, port + E21_MEM_ENABLE);
-}
-
-/* In other drivers I put the TX pages first, but the E2100 window circuitry
-   is designed to have a 4K Tx region last. The windowing circuitry wraps the
-   window at 0x2fff->0x0000 so that the packets at e.g. 0x2f00 in the RX ring
-   appear contiguously in the window. */
-#define E21_RX_START_PG		0x00	/* First page of RX buffer */
-#define E21_RX_STOP_PG		0x30	/* Last page +1 of RX ring */
-#define E21_BIG_RX_STOP_PG	0xF0	/* Last page +1 of RX ring */
-#define E21_TX_START_PG		E21_RX_STOP_PG	/* First page of TX buffer */
-
-static int e21_probe1(struct net_device *dev, int ioaddr);
-
-static int e21_open(struct net_device *dev);
-static void e21_reset_8390(struct net_device *dev);
-static void e21_block_input(struct net_device *dev, int count,
-						   struct sk_buff *skb, int ring_offset);
-static void e21_block_output(struct net_device *dev, int count,
-							 const unsigned char *buf, int start_page);
-static void e21_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-							int ring_page);
-static int e21_open(struct net_device *dev);
-static int e21_close(struct net_device *dev);
-
-
-/*  Probe for the E2100 series ethercards.  These cards have an 8390 at the
-	base address and the station address at both offset 0x10 and 0x18.  I read
-	the station address from offset 0x18 to avoid the dataport of NE2000
-	ethercards, and look for Ctron's unique ID (first three octets of the
-	station address).
- */
-
-static int  __init do_e2100_probe(struct net_device *dev)
-{
-	int *port;
-	int base_addr = dev->base_addr;
-	int irq = dev->irq;
-
-	if (base_addr > 0x1ff)		/* Check a single specified location. */
-		return e21_probe1(dev, base_addr);
-	else if (base_addr != 0)	/* Don't probe at all. */
-		return -ENXIO;
-
-	for (port = e21_probe_list; *port; port++) {
-		dev->irq = irq;
-		if (e21_probe1(dev, *port) == 0)
-			return 0;
-	}
-
-	return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init e2100_probe(int unit)
-{
-	struct net_device *dev = alloc_ei_netdev();
-	int err;
-
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	sprintf(dev->name, "eth%d", unit);
-	netdev_boot_setup_check(dev);
-
-	err = do_e2100_probe(dev);
-	if (err)
-		goto out;
-	return dev;
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-#endif
-
-static const struct net_device_ops e21_netdev_ops = {
-	.ndo_open		= e21_open,
-	.ndo_stop		= e21_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_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,
-#endif
-};
-
-static int __init e21_probe1(struct net_device *dev, int ioaddr)
-{
-	int i, status, retval;
-	unsigned char *station_addr = dev->dev_addr;
-	static unsigned version_printed;
-
-	if (!request_region(ioaddr, E21_IO_EXTENT, DRV_NAME))
-		return -EBUSY;
-
-	/* First check the station address for the Ctron prefix. */
-	if (inb(ioaddr + E21_SAPROM + 0) != 0x00 ||
-	    inb(ioaddr + E21_SAPROM + 1) != 0x00 ||
-	    inb(ioaddr + E21_SAPROM + 2) != 0x1d) {
-		retval = -ENODEV;
-		goto out;
-	}
-
-	/* Verify by making certain that there is a 8390 at there. */
-	outb(E8390_NODMA + E8390_STOP, ioaddr);
-	udelay(1);	/* we want to delay one I/O cycle - which is 2MHz */
-	status = inb(ioaddr);
-	if (status != 0x21 && status != 0x23) {
-		retval = -ENODEV;
-		goto out;
-	}
-
-	/* Read the station address PROM.  */
-	for (i = 0; i < 6; i++)
-		station_addr[i] = inb(ioaddr + E21_SAPROM + i);
-
-	inb(ioaddr + E21_MEDIA); 		/* Point to media selection. */
-	outb(0, ioaddr + E21_ASIC); 	/* and disable the secondary interface. */
-
-	if (ei_debug  &&  version_printed++ == 0)
-		printk(version);
-
-	for (i = 0; i < 6; i++)
-		printk(" %02X", station_addr[i]);
-
-	if (dev->irq < 2) {
-		static const int irqlist[] = {15, 11, 10, 12, 5, 9, 3, 4};
-		for (i = 0; i < ARRAY_SIZE(irqlist); i++)
-			if (request_irq (irqlist[i], NULL, 0, "bogus", NULL) != -EBUSY) {
-				dev->irq = irqlist[i];
-				break;
-			}
-		if (i >= ARRAY_SIZE(irqlist)) {
-			printk(" unable to get IRQ %d.\n", dev->irq);
-			retval = -EAGAIN;
-			goto out;
-		}
-	} else if (dev->irq == 2)	/* Fixup luser bogosity: IRQ2 is really IRQ9 */
-		dev->irq = 9;
-
-	/* The 8390 is at the base address. */
-	dev->base_addr = ioaddr;
-
-	ei_status.name = "E2100";
-	ei_status.word16 = 1;
-	ei_status.tx_start_page = E21_TX_START_PG;
-	ei_status.rx_start_page = E21_RX_START_PG;
-	ei_status.stop_page = E21_RX_STOP_PG;
-	ei_status.saved_irq = dev->irq;
-
-	/* Check the media port used.  The port can be passed in on the
-	   low mem_end bits. */
-	if (dev->mem_end & 15)
-		dev->if_port = dev->mem_end & 7;
-	else {
-		dev->if_port = 0;
-		inb(ioaddr + E21_MEDIA); 	/* Turn automatic media detection on. */
-		for(i = 0; i < 6; i++)
-			if (station_addr[i] != inb(ioaddr + E21_SAPROM + 8 + i)) {
-				dev->if_port = 1;
-				break;
-			}
-	}
-
-	/* Never map in the E21 shared memory unless you are actively using it.
-	   Also, the shared memory has effective only one setting -- spread all
-	   over the 128K region! */
-	if (dev->mem_start == 0)
-		dev->mem_start = 0xd0000;
-
-	ei_status.mem = ioremap(dev->mem_start, 2*1024);
-	if (!ei_status.mem) {
-		printk("unable to remap memory\n");
-		retval = -EAGAIN;
-		goto out;
-	}
-
-#ifdef notdef
-	/* These values are unused.  The E2100 has a 2K window into the packet
-	   buffer.  The window can be set to start on any page boundary. */
-	ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
-	dev->mem_end = ei_status.rmem_end = dev->mem_start + 2*1024;
-#endif
-
-	printk(", IRQ %d, %s media, memory @ %#lx.\n", dev->irq,
-		   dev->if_port ? "secondary" : "primary", dev->mem_start);
-
-	ei_status.reset_8390 = &e21_reset_8390;
-	ei_status.block_input = &e21_block_input;
-	ei_status.block_output = &e21_block_output;
-	ei_status.get_8390_hdr = &e21_get_8390_hdr;
-
-	dev->netdev_ops = &e21_netdev_ops;
-	NS8390_init(dev, 0);
-
-	retval = register_netdev(dev);
-	if (retval)
-		goto out;
-	return 0;
-out:
-	release_region(ioaddr, E21_IO_EXTENT);
-	return retval;
-}
-
-static int
-e21_open(struct net_device *dev)
-{
-	short ioaddr = dev->base_addr;
-	int retval;
-
-	if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev)))
-		return retval;
-
-	/* Set the interrupt line and memory base on the hardware. */
-	inb(ioaddr + E21_IRQ_LOW);
-	outb(0, ioaddr + E21_ASIC + (dev->irq & 7));
-	inb(ioaddr + E21_IRQ_HIGH); 			/* High IRQ bit, and if_port. */
-	outb(0, ioaddr + E21_ASIC + (dev->irq > 7 ? 1:0)
-		   + (dev->if_port ? E21_ALT_IFPORT : 0));
-	inb(ioaddr + E21_MEM_BASE);
-	outb(0, ioaddr + E21_ASIC + ((dev->mem_start >> 17) & 7));
-
-	ei_open(dev);
-	return 0;
-}
-
-static void
-e21_reset_8390(struct net_device *dev)
-{
-	short ioaddr = dev->base_addr;
-
-	outb(0x01, ioaddr);
-	if (ei_debug > 1) printk("resetting the E2180x3 t=%ld...", jiffies);
-	ei_status.txing = 0;
-
-	/* Set up the ASIC registers, just in case something changed them. */
-
-	if (ei_debug > 1) printk("reset done\n");
-}
-
-/* Grab the 8390 specific header. We put the 2k window so the header page
-   appears at the start of the shared memory. */
-
-static void
-e21_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-
-	short ioaddr = dev->base_addr;
-	char __iomem *shared_mem = ei_status.mem;
-
-	mem_on(ioaddr, shared_mem, ring_page);
-
-#ifdef notdef
-	/* Officially this is what we are doing, but the readl() is faster */
-	memcpy_fromio(hdr, shared_mem, sizeof(struct e8390_pkt_hdr));
-#else
-	((unsigned int*)hdr)[0] = readl(shared_mem);
-#endif
-
-	/* Turn off memory access: we would need to reprogram the window anyway. */
-	mem_off(ioaddr);
-
-}
-
-/*  Block input and output are easy on shared memory ethercards.
-	The E21xx makes block_input() especially easy by wrapping the top
-	ring buffer to the bottom automatically. */
-static void
-e21_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-	short ioaddr = dev->base_addr;
-	char __iomem *shared_mem = ei_status.mem;
-
-	mem_on(ioaddr, shared_mem, (ring_offset>>8));
-
-	memcpy_fromio(skb->data, ei_status.mem + (ring_offset & 0xff), count);
-
-	mem_off(ioaddr);
-}
-
-static void
-e21_block_output(struct net_device *dev, int count, const unsigned char *buf,
-				 int start_page)
-{
-	short ioaddr = dev->base_addr;
-	volatile char __iomem *shared_mem = ei_status.mem;
-
-	/* Set the shared memory window start by doing a read, with the low address
-	   bits specifying the starting page. */
-	readb(shared_mem + start_page);
-	mem_on(ioaddr, shared_mem, start_page);
-
-	memcpy_toio(shared_mem, buf, count);
-	mem_off(ioaddr);
-}
-
-static int
-e21_close(struct net_device *dev)
-{
-	short ioaddr = dev->base_addr;
-
-	if (ei_debug > 1)
-		printk("%s: Shutting down ethercard.\n", dev->name);
-
-	free_irq(dev->irq, dev);
-	dev->irq = ei_status.saved_irq;
-
-	/* Shut off the interrupt line and secondary interface. */
-	inb(ioaddr + E21_IRQ_LOW);
-	outb(0, ioaddr + E21_ASIC);
-	inb(ioaddr + E21_IRQ_HIGH); 			/* High IRQ bit, and if_port. */
-	outb(0, ioaddr + E21_ASIC);
-
-	ei_close(dev);
-
-	/* Double-check that the memory has been turned off, because really
-	   really bad things happen if it isn't. */
-	mem_off(ioaddr);
-
-	return 0;
-}
-
-
-#ifdef MODULE
-#define MAX_E21_CARDS	4	/* Max number of E21 cards per module */
-static struct net_device *dev_e21[MAX_E21_CARDS];
-static int io[MAX_E21_CARDS];
-static int irq[MAX_E21_CARDS];
-static int mem[MAX_E21_CARDS];
-static int xcvr[MAX_E21_CARDS];		/* choose int. or ext. xcvr */
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(mem, int, NULL, 0);
-module_param_array(xcvr, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es)");
-MODULE_PARM_DESC(irq, "IRQ number(s)");
-MODULE_PARM_DESC(mem, " memory base address(es)");
-MODULE_PARM_DESC(xcvr, "transceiver(s) (0=internal, 1=external)");
-MODULE_DESCRIPTION("Cabletron E2100 ISA ethernet driver");
-MODULE_LICENSE("GPL");
-
-/* This is set up so that only a single autoprobe takes place per call.
-ISA device autoprobes on a running machine are not recommended. */
-
-int __init init_module(void)
-{
-	struct net_device *dev;
-	int this_dev, found = 0;
-
-	for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
-		if (io[this_dev] == 0)  {
-			if (this_dev != 0) break; /* only autoprobe 1st one */
-			printk(KERN_NOTICE "e2100.c: Presently autoprobing (not recommended) for a single card.\n");
-		}
-		dev = alloc_ei_netdev();
-		if (!dev)
-			break;
-		dev->irq = irq[this_dev];
-		dev->base_addr = io[this_dev];
-		dev->mem_start = mem[this_dev];
-		dev->mem_end = xcvr[this_dev];	/* low 4bits = xcvr sel. */
-		if (do_e2100_probe(dev) == 0) {
-			dev_e21[found++] = dev;
-			continue;
-		}
-		free_netdev(dev);
-		printk(KERN_WARNING "e2100.c: No E2100 card found (i/o = 0x%x).\n", io[this_dev]);
-		break;
-	}
-	if (found)
-		return 0;
-	return -ENXIO;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-	/* NB: e21_close() handles free_irq */
-	iounmap(ei_status.mem);
-	release_region(dev->base_addr, E21_IO_EXTENT);
-}
-
-void __exit
-cleanup_module(void)
-{
-	int this_dev;
-
-	for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
-		struct net_device *dev = dev_e21[this_dev];
-		if (dev) {
-			unregister_netdev(dev);
-			cleanup_card(dev);
-			free_netdev(dev);
-		}
-	}
-}
-#endif /* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/eepro.c linux-libre-3.2-gnu/drivers/net/eepro.c
--- linux-libre-3.1-gnu/drivers/net/eepro.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/eepro.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1822 +0,0 @@
-/* eepro.c: Intel EtherExpress Pro/10 device driver for Linux. */
-/*
-	Written 1994, 1995,1996 by Bao C. Ha.
-
-	Copyright (C) 1994, 1995,1996 by Bao C. Ha.
-
-	This software may be used and distributed
-	according to the terms of the GNU General Public License,
-	incorporated herein by reference.
-
-	The author may be reached at bao.ha@srs.gov
-	or 418 Hastings Place, Martinez, GA 30907.
-
-	Things remaining to do:
-	Better record keeping of errors.
-	Eliminate transmit interrupt to reduce overhead.
-	Implement "concurrent processing". I won't be doing it!
-
-	Bugs:
-
-	If you have a problem of not detecting the 82595 during a
-	reboot (warm reset), disable the FLASH memory should fix it.
-	This is a compatibility hardware problem.
-
-	Versions:
-	0.13b	basic ethtool support (aris, 09/13/2004)
-	0.13a   in memory shortage, drop packets also in board
-		(Michael Westermann <mw@microdata-pos.de>, 07/30/2002)
-	0.13    irq sharing, rewrote probe function, fixed a nasty bug in
-		hardware_send_packet and a major cleanup (aris, 11/08/2001)
-	0.12d	fixing a problem with single card detected as eight eth devices
-		fixing a problem with sudden drop in card performance
-		(chris (asdn@go2.pl), 10/29/2001)
-	0.12c	fixing some problems with old cards (aris, 01/08/2001)
-	0.12b	misc fixes (aris, 06/26/2000)
-	0.12a   port of version 0.12a of 2.2.x kernels to 2.3.x
-		(aris (aris@conectiva.com.br), 05/19/2000)
-	0.11e   some tweaks about multiple cards support (PdP, jul/aug 1999)
-	0.11d	added __initdata, __init stuff; call spin_lock_init
-	        in eepro_probe1. Replaced "eepro" by dev->name. Augmented
-		the code protected by spin_lock in interrupt routine
-		(PdP, 12/12/1998)
-	0.11c   minor cleanup (PdP, RMC, 09/12/1998)
-	0.11b   Pascal Dupuis (dupuis@lei.ucl.ac.be): works as a module
-	        under 2.1.xx. Debug messages are flagged as KERN_DEBUG to
-		avoid console flooding. Added locking at critical parts. Now
-		the dawn thing is SMP safe.
-	0.11a   Attempt to get 2.1.xx support up (RMC)
-	0.11	Brian Candler added support for multiple cards. Tested as
-		a module, no idea if it works when compiled into kernel.
-
-	0.10e	Rick Bressler notified me that ifconfig up;ifconfig down fails
-		because the irq is lost somewhere. Fixed that by moving
-		request_irq and free_irq to eepro_open and eepro_close respectively.
-	0.10d	Ugh! Now Wakeup works. Was seriously broken in my first attempt.
-		I'll need to find a way to specify an ioport other than
-		the default one in the PnP case. PnP definitively sucks.
-		And, yes, this is not the only reason.
-	0.10c	PnP Wakeup Test for 595FX. uncomment #define PnPWakeup;
-		to use.
-	0.10b	Should work now with (some) Pro/10+. At least for
-		me (and my two cards) it does. _No_ guarantee for
-		function with non-Pro/10+ cards! (don't have any)
-		(RMC, 9/11/96)
-
-	0.10	Added support for the Etherexpress Pro/10+.  The
-		IRQ map was changed significantly from the old
-		pro/10.  The new interrupt map was provided by
-		Rainer M. Canavan (Canavan@Zeus.cs.bonn.edu).
-		(BCH, 9/3/96)
-
-	0.09	Fixed a race condition in the transmit algorithm,
-		which causes crashes under heavy load with fast
-		pentium computers.  The performance should also
-		improve a bit.  The size of RX buffer, and hence
-		TX buffer, can also be changed via lilo or insmod.
-		(BCH, 7/31/96)
-
-	0.08	Implement 32-bit I/O for the 82595TX and 82595FX
-		based lan cards.  Disable full-duplex mode if TPE
-		is not used.  (BCH, 4/8/96)
-
-	0.07a	Fix a stat report which counts every packet as a
-		heart-beat failure. (BCH, 6/3/95)
-
-	0.07	Modified to support all other 82595-based lan cards.
-		The IRQ vector of the EtherExpress Pro will be set
-		according to the value saved in the EEPROM.  For other
-		cards, I will do autoirq_request() to grab the next
-		available interrupt vector. (BCH, 3/17/95)
-
-	0.06a,b	Interim released.  Minor changes in the comments and
-		print out format. (BCH, 3/9/95 and 3/14/95)
-
-	0.06	First stable release that I am comfortable with. (BCH,
-		3/2/95)
-
-	0.05	Complete testing of multicast. (BCH, 2/23/95)
-
-	0.04	Adding multicast support. (BCH, 2/14/95)
-
-	0.03	First widely alpha release for public testing.
-		(BCH, 2/14/95)
-
-*/
-
-static const char version[] =
-	"eepro.c: v0.13b 09/13/2004 aris@cathedrallabs.org\n";
-
-#include <linux/module.h>
-
-/*
-  Sources:
-
-	This driver wouldn't have been written without the availability
-	of the Crynwr's Lan595 driver source code.  It helps me to
-	familiarize with the 82595 chipset while waiting for the Intel
-	documentation.  I also learned how to detect the 82595 using
-	the packet driver's technique.
-
-	This driver is written by cutting and pasting the skeleton.c driver
-	provided by Donald Becker.  I also borrowed the EEPROM routine from
-	Donald Becker's 82586 driver.
-
-	Datasheet for the Intel 82595 (including the TX and FX version). It
-	provides just enough info that the casual reader might think that it
-	documents the i82595.
-
-	The User Manual for the 82595.  It provides a lot of the missing
-	information.
-
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-#include <linux/ethtool.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#define DRV_NAME "eepro"
-#define DRV_VERSION "0.13c"
-
-#define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb) )
-/* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */
-#define SLOW_DOWN inb(0x80)
-/* udelay(2) */
-#define compat_init_data     __initdata
-enum iftype { AUI=0, BNC=1, TPE=2 };
-
-/* First, a few definitions that the brave might change. */
-/* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int eepro_portlist[] compat_init_data =
-   { 0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0};
-/* note: 0x300 is default, the 595FX supports ALL IO Ports
-  from 0x000 to 0x3F0, some of which are reserved in PCs */
-
-/* To try the (not-really PnP Wakeup: */
-/*
-#define PnPWakeup
-*/
-
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifndef NET_DEBUG
-#define NET_DEBUG 0
-#endif
-static unsigned int net_debug = NET_DEBUG;
-
-/* The number of low I/O ports used by the ethercard. */
-#define EEPRO_IO_EXTENT	16
-
-/* Different 82595 chips */
-#define	LAN595		0
-#define	LAN595TX	1
-#define	LAN595FX	2
-#define	LAN595FX_10ISA	3
-
-/* Information that need to be kept for each board. */
-struct eepro_local {
-	unsigned rx_start;
-	unsigned tx_start; /* start of the transmit chain */
-	int tx_last;  /* pointer to last packet in the transmit chain */
-	unsigned tx_end;   /* end of the transmit chain (plus 1) */
-	int eepro;	/* 1 for the EtherExpress Pro/10,
-			   2 for the EtherExpress Pro/10+,
-			   3 for the EtherExpress 10 (blue cards),
-			   0 for other 82595-based lan cards. */
-	int version;	/* a flag to indicate if this is a TX or FX
-				   version of the 82595 chip. */
-	int stepping;
-
-	spinlock_t lock; /* Serializing lock  */
-
-	unsigned rcv_ram;	/* pre-calculated space for rx */
-	unsigned xmt_ram;	/* pre-calculated space for tx */
-	unsigned char xmt_bar;
-	unsigned char xmt_lower_limit_reg;
-	unsigned char xmt_upper_limit_reg;
-	short xmt_lower_limit;
-	short xmt_upper_limit;
-	short rcv_lower_limit;
-	short rcv_upper_limit;
-	unsigned char eeprom_reg;
-	unsigned short word[8];
-};
-
-/* The station (ethernet) address prefix, used for IDing the board. */
-#define SA_ADDR0 0x00	/* Etherexpress Pro/10 */
-#define SA_ADDR1 0xaa
-#define SA_ADDR2 0x00
-
-#define GetBit(x,y) ((x & (1<<y))>>y)
-
-/* EEPROM Word 0: */
-#define ee_PnP       0  /* Plug 'n Play enable bit */
-#define ee_Word1     1  /* Word 1? */
-#define ee_BusWidth  2  /* 8/16 bit */
-#define ee_FlashAddr 3  /* Flash Address */
-#define ee_FlashMask 0x7   /* Mask */
-#define ee_AutoIO    6  /* */
-#define ee_reserved0 7  /* =0! */
-#define ee_Flash     8  /* Flash there? */
-#define ee_AutoNeg   9  /* Auto Negotiation enabled? */
-#define ee_IO0       10 /* IO Address LSB */
-#define ee_IO0Mask   0x /*...*/
-#define ee_IO1       15 /* IO MSB */
-
-/* EEPROM Word 1: */
-#define ee_IntSel    0   /* Interrupt */
-#define ee_IntMask   0x7
-#define ee_LI        3   /* Link Integrity 0= enabled */
-#define ee_PC        4   /* Polarity Correction 0= enabled */
-#define ee_TPE_AUI   5   /* PortSelection 1=TPE */
-#define ee_Jabber    6   /* Jabber prevention 0= enabled */
-#define ee_AutoPort  7   /* Auto Port Selection 1= Disabled */
-#define ee_SMOUT     8   /* SMout Pin Control 0= Input */
-#define ee_PROM      9   /* Flash EPROM / PROM 0=Flash */
-#define ee_reserved1 10  /* .. 12 =0! */
-#define ee_AltReady  13  /* Alternate Ready, 0=normal */
-#define ee_reserved2 14  /* =0! */
-#define ee_Duplex    15
-
-/* Word2,3,4: */
-#define ee_IA5       0 /*bit start for individual Addr Byte 5 */
-#define ee_IA4       8 /*bit start for individual Addr Byte 5 */
-#define ee_IA3       0 /*bit start for individual Addr Byte 5 */
-#define ee_IA2       8 /*bit start for individual Addr Byte 5 */
-#define ee_IA1       0 /*bit start for individual Addr Byte 5 */
-#define ee_IA0       8 /*bit start for individual Addr Byte 5 */
-
-/* Word 5: */
-#define ee_BNC_TPE   0 /* 0=TPE */
-#define ee_BootType  1 /* 00=None, 01=IPX, 10=ODI, 11=NDIS */
-#define ee_BootTypeMask 0x3
-#define ee_NumConn   3  /* Number of Connections 0= One or Two */
-#define ee_FlashSock 4  /* Presence of Flash Socket 0= Present */
-#define ee_PortTPE   5
-#define ee_PortBNC   6
-#define ee_PortAUI   7
-#define ee_PowerMgt  10 /* 0= disabled */
-#define ee_CP        13 /* Concurrent Processing */
-#define ee_CPMask    0x7
-
-/* Word 6: */
-#define ee_Stepping  0 /* Stepping info */
-#define ee_StepMask  0x0F
-#define ee_BoardID   4 /* Manucaturer Board ID, reserved */
-#define ee_BoardMask 0x0FFF
-
-/* Word 7: */
-#define ee_INT_TO_IRQ 0 /* int to IRQ Mapping  = 0x1EB8 for Pro/10+ */
-#define ee_FX_INT2IRQ 0x1EB8 /* the _only_ mapping allowed for FX chips */
-
-/*..*/
-#define ee_SIZE 0x40 /* total EEprom Size */
-#define ee_Checksum 0xBABA /* initial and final value for adding checksum */
-
-
-/* Card identification via EEprom:   */
-#define ee_addr_vendor 0x10  /* Word offset for EISA Vendor ID */
-#define ee_addr_id 0x11      /* Word offset for Card ID */
-#define ee_addr_SN 0x12      /* Serial Number */
-#define ee_addr_CRC_8 0x14   /* CRC over last thee Bytes */
-
-
-#define ee_vendor_intel0 0x25  /* Vendor ID Intel */
-#define ee_vendor_intel1 0xD4
-#define ee_id_eepro10p0 0x10   /* ID for eepro/10+ */
-#define ee_id_eepro10p1 0x31
-
-#define TX_TIMEOUT ((4*HZ)/10)
-
-/* Index to functions, as function prototypes. */
-
-static int	eepro_probe1(struct net_device *dev, int autoprobe);
-static int	eepro_open(struct net_device *dev);
-static netdev_tx_t eepro_send_packet(struct sk_buff *skb,
-				     struct net_device *dev);
-static irqreturn_t eepro_interrupt(int irq, void *dev_id);
-static void 	eepro_rx(struct net_device *dev);
-static void 	eepro_transmit_interrupt(struct net_device *dev);
-static int	eepro_close(struct net_device *dev);
-static void     set_multicast_list(struct net_device *dev);
-static void     eepro_tx_timeout (struct net_device *dev);
-
-static int read_eeprom(int ioaddr, int location, struct net_device *dev);
-static int	hardware_send_packet(struct net_device *dev, void *buf, short length);
-static int	eepro_grab_irq(struct net_device *dev);
-
-/*
-			Details of the i82595.
-
-You will need either the datasheet or the user manual to understand what
-is going on here.  The 82595 is very different from the 82586, 82593.
-
-The receive algorithm in eepro_rx() is just an implementation of the
-RCV ring structure that the Intel 82595 imposes at the hardware level.
-The receive buffer is set at 24K, and the transmit buffer is 8K.  I
-am assuming that the total buffer memory is 32K, which is true for the
-Intel EtherExpress Pro/10.  If it is less than that on a generic card,
-the driver will be broken.
-
-The transmit algorithm in the hardware_send_packet() is similar to the
-one in the eepro_rx().  The transmit buffer is a ring linked list.
-I just queue the next available packet to the end of the list.  In my
-system, the 82595 is so fast that the list seems to always contain a
-single packet.  In other systems with faster computers and more congested
-network traffics, the ring linked list should improve performance by
-allowing up to 8K worth of packets to be queued.
-
-The sizes of the receive and transmit buffers can now be changed via lilo
-or insmod.  Lilo uses the appended line "ether=io,irq,debug,rx-buffer,eth0"
-where rx-buffer is in KB unit.  Modules uses the parameter mem which is
-also in KB unit, for example "insmod io=io-address irq=0 mem=rx-buffer."
-The receive buffer has to be more than 3K or less than 29K.  Otherwise,
-it is reset to the default of 24K, and, hence, 8K for the trasnmit
-buffer (transmit-buffer = 32K - receive-buffer).
-
-*/
-#define RAM_SIZE        0x8000
-
-#define RCV_HEADER      8
-#define RCV_DEFAULT_RAM 0x6000
-
-#define XMT_HEADER      8
-#define XMT_DEFAULT_RAM	(RAM_SIZE - RCV_DEFAULT_RAM)
-
-#define XMT_START_PRO	RCV_DEFAULT_RAM
-#define XMT_START_10	0x0000
-#define RCV_START_PRO	0x0000
-#define RCV_START_10	XMT_DEFAULT_RAM
-
-#define	RCV_DONE	0x0008
-#define	RX_OK		0x2000
-#define	RX_ERROR	0x0d81
-
-#define	TX_DONE_BIT	0x0080
-#define	TX_OK		0x2000
-#define	CHAIN_BIT	0x8000
-#define	XMT_STATUS	0x02
-#define	XMT_CHAIN	0x04
-#define	XMT_COUNT	0x06
-
-#define	BANK0_SELECT	0x00
-#define	BANK1_SELECT	0x40
-#define	BANK2_SELECT	0x80
-
-/* Bank 0 registers */
-#define	COMMAND_REG	0x00	/* Register 0 */
-#define	MC_SETUP	0x03
-#define	XMT_CMD		0x04
-#define	DIAGNOSE_CMD	0x07
-#define	RCV_ENABLE_CMD	0x08
-#define	RCV_DISABLE_CMD	0x0a
-#define	STOP_RCV_CMD	0x0b
-#define	RESET_CMD	0x0e
-#define	POWER_DOWN_CMD	0x18
-#define	RESUME_XMT_CMD	0x1c
-#define	SEL_RESET_CMD	0x1e
-#define	STATUS_REG	0x01	/* Register 1 */
-#define	RX_INT		0x02
-#define	TX_INT		0x04
-#define	EXEC_STATUS	0x30
-#define	ID_REG		0x02	/* Register 2	*/
-#define	R_ROBIN_BITS	0xc0	/* round robin counter */
-#define	ID_REG_MASK	0x2c
-#define	ID_REG_SIG	0x24
-#define	AUTO_ENABLE	0x10
-#define	INT_MASK_REG	0x03	/* Register 3	*/
-#define	RX_STOP_MASK	0x01
-#define	RX_MASK		0x02
-#define	TX_MASK		0x04
-#define	EXEC_MASK	0x08
-#define	ALL_MASK	0x0f
-#define	IO_32_BIT	0x10
-#define	RCV_BAR		0x04	/* The following are word (16-bit) registers */
-#define	RCV_STOP	0x06
-
-#define	XMT_BAR_PRO	0x0a
-#define	XMT_BAR_10	0x0b
-
-#define	HOST_ADDRESS_REG	0x0c
-#define	IO_PORT		0x0e
-#define	IO_PORT_32_BIT	0x0c
-
-/* Bank 1 registers */
-#define	REG1	0x01
-#define	WORD_WIDTH	0x02
-#define	INT_ENABLE	0x80
-#define INT_NO_REG	0x02
-#define	RCV_LOWER_LIMIT_REG	0x08
-#define	RCV_UPPER_LIMIT_REG	0x09
-
-#define	XMT_LOWER_LIMIT_REG_PRO 0x0a
-#define	XMT_UPPER_LIMIT_REG_PRO 0x0b
-#define	XMT_LOWER_LIMIT_REG_10  0x0b
-#define	XMT_UPPER_LIMIT_REG_10  0x0a
-
-/* Bank 2 registers */
-#define	XMT_Chain_Int	0x20	/* Interrupt at the end of the transmit chain */
-#define	XMT_Chain_ErrStop	0x40 /* Interrupt at the end of the chain even if there are errors */
-#define	RCV_Discard_BadFrame	0x80 /* Throw bad frames away, and continue to receive others */
-#define	REG2		0x02
-#define	PRMSC_Mode	0x01
-#define	Multi_IA	0x20
-#define	REG3		0x03
-#define	TPE_BIT		0x04
-#define	BNC_BIT		0x20
-#define	REG13		0x0d
-#define	FDX		0x00
-#define	A_N_ENABLE	0x02
-
-#define	I_ADD_REG0	0x04
-#define	I_ADD_REG1	0x05
-#define	I_ADD_REG2	0x06
-#define	I_ADD_REG3	0x07
-#define	I_ADD_REG4	0x08
-#define	I_ADD_REG5	0x09
-
-#define	EEPROM_REG_PRO 0x0a
-#define	EEPROM_REG_10  0x0b
-
-#define EESK 0x01
-#define EECS 0x02
-#define EEDI 0x04
-#define EEDO 0x08
-
-/* do a full reset */
-#define eepro_reset(ioaddr) outb(RESET_CMD, ioaddr)
-
-/* do a nice reset */
-#define eepro_sel_reset(ioaddr) 	{ \
-					outb(SEL_RESET_CMD, ioaddr); \
-					SLOW_DOWN; \
-					SLOW_DOWN; \
-					}
-
-/* disable all interrupts */
-#define eepro_dis_int(ioaddr) outb(ALL_MASK, ioaddr + INT_MASK_REG)
-
-/* clear all interrupts */
-#define eepro_clear_int(ioaddr) outb(ALL_MASK, ioaddr + STATUS_REG)
-
-/* enable tx/rx */
-#define eepro_en_int(ioaddr) outb(ALL_MASK & ~(RX_MASK | TX_MASK), \
-							ioaddr + INT_MASK_REG)
-
-/* enable exec event interrupt */
-#define eepro_en_intexec(ioaddr) outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG)
-
-/* enable rx */
-#define eepro_en_rx(ioaddr) outb(RCV_ENABLE_CMD, ioaddr)
-
-/* disable rx */
-#define eepro_dis_rx(ioaddr) outb(RCV_DISABLE_CMD, ioaddr)
-
-/* switch bank */
-#define eepro_sw2bank0(ioaddr) outb(BANK0_SELECT, ioaddr)
-#define eepro_sw2bank1(ioaddr) outb(BANK1_SELECT, ioaddr)
-#define eepro_sw2bank2(ioaddr) outb(BANK2_SELECT, ioaddr)
-
-/* enable interrupt line */
-#define eepro_en_intline(ioaddr) outb(inb(ioaddr + REG1) | INT_ENABLE,\
-				ioaddr + REG1)
-
-/* disable interrupt line */
-#define eepro_dis_intline(ioaddr) outb(inb(ioaddr + REG1) & 0x7f, \
-				ioaddr + REG1);
-
-/* set diagnose flag */
-#define eepro_diag(ioaddr) outb(DIAGNOSE_CMD, ioaddr)
-
-/* ack for rx int */
-#define eepro_ack_rx(ioaddr) outb (RX_INT, ioaddr + STATUS_REG)
-
-/* ack for tx int */
-#define eepro_ack_tx(ioaddr) outb (TX_INT, ioaddr + STATUS_REG)
-
-/* a complete sel reset */
-#define eepro_complete_selreset(ioaddr) { \
-						dev->stats.tx_errors++;\
-						eepro_sel_reset(ioaddr);\
-						lp->tx_end = \
-							lp->xmt_lower_limit;\
-						lp->tx_start = lp->tx_end;\
-						lp->tx_last = 0;\
-						dev->trans_start = jiffies;\
-						netif_wake_queue(dev);\
-						eepro_en_rx(ioaddr);\
-					}
-
-/* Check for a network adaptor of this type, and return '0' if one exists.
-   If dev->base_addr == 0, probe all likely locations.
-   If dev->base_addr == 1, always return failure.
-   If dev->base_addr == 2, allocate space for the device and return success
-   (detachable devices only).
-   */
-static int __init do_eepro_probe(struct net_device *dev)
-{
-	int i;
-	int base_addr = dev->base_addr;
-	int irq = dev->irq;
-
-#ifdef PnPWakeup
-	/* XXXX for multiple cards should this only be run once? */
-
-	/* Wakeup: */
-	#define WakeupPort 0x279
-	#define WakeupSeq    {0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE,\
-	                      0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,\
-	                      0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,\
-	                      0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43}
-
-	{
-		unsigned short int WS[32]=WakeupSeq;
-
-		if (request_region(WakeupPort, 2, "eepro wakeup")) {
-			if (net_debug>5)
-				printk(KERN_DEBUG "Waking UP\n");
-
-			outb_p(0,WakeupPort);
-			outb_p(0,WakeupPort);
-			for (i=0; i<32; i++) {
-				outb_p(WS[i],WakeupPort);
-				if (net_debug>5) printk(KERN_DEBUG ": %#x ",WS[i]);
-			}
-
-			release_region(WakeupPort, 2);
-		} else
-			printk(KERN_WARNING "PnP wakeup region busy!\n");
-	}
-#endif
-
-	if (base_addr > 0x1ff)		/* Check a single specified location. */
-		return eepro_probe1(dev, 0);
-
-	else if (base_addr != 0)	/* Don't probe at all. */
-		return -ENXIO;
-
-	for (i = 0; eepro_portlist[i]; i++) {
-		dev->base_addr = eepro_portlist[i];
-		dev->irq = irq;
-		if (eepro_probe1(dev, 1) == 0)
-			return 0;
-	}
-
-	return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init eepro_probe(int unit)
-{
-	struct net_device *dev = alloc_etherdev(sizeof(struct eepro_local));
-	int err;
-
-	if (!dev)
-		return ERR_PTR(-ENODEV);
-
-	sprintf(dev->name, "eth%d", unit);
-	netdev_boot_setup_check(dev);
-
-	err = do_eepro_probe(dev);
-	if (err)
-		goto out;
-	return dev;
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-#endif
-
-static void __init printEEPROMInfo(struct net_device *dev)
-{
-	struct eepro_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-	unsigned short Word;
-	int i,j;
-
-	j = ee_Checksum;
-	for (i = 0; i < 8; i++)
-		j += lp->word[i];
-	for ( ; i < ee_SIZE; i++)
-		j += read_eeprom(ioaddr, i, dev);
-
-	printk(KERN_DEBUG "Checksum: %#x\n",j&0xffff);
-
-	Word = lp->word[0];
-	printk(KERN_DEBUG "Word0:\n");
-	printk(KERN_DEBUG " Plug 'n Pray: %d\n",GetBit(Word,ee_PnP));
-	printk(KERN_DEBUG " Buswidth: %d\n",(GetBit(Word,ee_BusWidth)+1)*8 );
-	printk(KERN_DEBUG " AutoNegotiation: %d\n",GetBit(Word,ee_AutoNeg));
-	printk(KERN_DEBUG " IO Address: %#x\n", (Word>>ee_IO0)<<4);
-
-	if (net_debug>4)  {
-		Word = lp->word[1];
-		printk(KERN_DEBUG "Word1:\n");
-		printk(KERN_DEBUG " INT: %d\n", Word & ee_IntMask);
-		printk(KERN_DEBUG " LI: %d\n", GetBit(Word,ee_LI));
-		printk(KERN_DEBUG " PC: %d\n", GetBit(Word,ee_PC));
-		printk(KERN_DEBUG " TPE/AUI: %d\n", GetBit(Word,ee_TPE_AUI));
-		printk(KERN_DEBUG " Jabber: %d\n", GetBit(Word,ee_Jabber));
-		printk(KERN_DEBUG " AutoPort: %d\n", !GetBit(Word,ee_AutoPort));
-		printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex));
-	}
-
-	Word = lp->word[5];
-	printk(KERN_DEBUG "Word5:\n");
-	printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE));
-	printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn));
-	printk(KERN_DEBUG " Has ");
-	if (GetBit(Word,ee_PortTPE)) printk(KERN_DEBUG "TPE ");
-	if (GetBit(Word,ee_PortBNC)) printk(KERN_DEBUG "BNC ");
-	if (GetBit(Word,ee_PortAUI)) printk(KERN_DEBUG "AUI ");
-	printk(KERN_DEBUG "port(s)\n");
-
-	Word = lp->word[6];
-	printk(KERN_DEBUG "Word6:\n");
-	printk(KERN_DEBUG " Stepping: %d\n",Word & ee_StepMask);
-	printk(KERN_DEBUG " BoardID: %d\n",Word>>ee_BoardID);
-
-	Word = lp->word[7];
-	printk(KERN_DEBUG "Word7:\n");
-	printk(KERN_DEBUG " INT to IRQ:\n");
-
-	for (i=0, j=0; i<15; i++)
-		if (GetBit(Word,i)) printk(KERN_DEBUG " INT%d -> IRQ %d;",j++,i);
-
-	printk(KERN_DEBUG "\n");
-}
-
-/* function to recalculate the limits of buffer based on rcv_ram */
-static void eepro_recalc (struct net_device *dev)
-{
-	struct eepro_local *	lp;
-
-	lp = netdev_priv(dev);
-	lp->xmt_ram = RAM_SIZE - lp->rcv_ram;
-
-	if (lp->eepro == LAN595FX_10ISA) {
-		lp->xmt_lower_limit = XMT_START_10;
-		lp->xmt_upper_limit = (lp->xmt_ram - 2);
-		lp->rcv_lower_limit = lp->xmt_ram;
-		lp->rcv_upper_limit = (RAM_SIZE - 2);
-	}
-	else {
-		lp->rcv_lower_limit = RCV_START_PRO;
-		lp->rcv_upper_limit = (lp->rcv_ram - 2);
-		lp->xmt_lower_limit = lp->rcv_ram;
-		lp->xmt_upper_limit = (RAM_SIZE - 2);
-	}
-}
-
-/* prints boot-time info */
-static void __init eepro_print_info (struct net_device *dev)
-{
-	struct eepro_local *	lp = netdev_priv(dev);
-	int			i;
-	const char *		ifmap[] = {"AUI", "10Base2", "10BaseT"};
-
-	i = inb(dev->base_addr + ID_REG);
-	printk(KERN_DEBUG " id: %#x ",i);
-	printk(" io: %#x ", (unsigned)dev->base_addr);
-
-	switch (lp->eepro) {
-		case LAN595FX_10ISA:
-			printk("%s: Intel EtherExpress 10 ISA\n at %#x,",
-					dev->name, (unsigned)dev->base_addr);
-			break;
-		case LAN595FX:
-			printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,",
-					dev->name, (unsigned)dev->base_addr);
-			break;
-		case LAN595TX:
-			printk("%s: Intel EtherExpress Pro/10 ISA at %#x,",
-					dev->name, (unsigned)dev->base_addr);
-			break;
-		case LAN595:
-			printk("%s: Intel 82595-based lan card at %#x,",
-					dev->name, (unsigned)dev->base_addr);
-			break;
-	}
-
-	printk(" %pM", dev->dev_addr);
-
-	if (net_debug > 3)
-		printk(KERN_DEBUG ", %dK RCV buffer",
-				(int)(lp->rcv_ram)/1024);
-
-	if (dev->irq > 2)
-		printk(", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]);
-	else
-		printk(", %s.\n", ifmap[dev->if_port]);
-
-	if (net_debug > 3) {
-		i = lp->word[5];
-		if (i & 0x2000) /* bit 13 of EEPROM word 5 */
-			printk(KERN_DEBUG "%s: Concurrent Processing is "
-				"enabled but not used!\n", dev->name);
-	}
-
-	/* Check the station address for the manufacturer's code */
-	if (net_debug>3)
-		printEEPROMInfo(dev);
-}
-
-static const struct ethtool_ops eepro_ethtool_ops;
-
-static const struct net_device_ops eepro_netdev_ops = {
- 	.ndo_open               = eepro_open,
- 	.ndo_stop               = eepro_close,
- 	.ndo_start_xmit    	= eepro_send_packet,
- 	.ndo_set_multicast_list = set_multicast_list,
- 	.ndo_tx_timeout		= eepro_tx_timeout,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-/* This is the real probe routine.  Linux has a history of friendly device
-   probes on the ISA bus.  A good device probe avoids doing writes, and
-   verifies that the correct device exists and functions.  */
-
-static int __init eepro_probe1(struct net_device *dev, int autoprobe)
-{
-	unsigned short station_addr[3], id, counter;
-	int i;
-	struct eepro_local *lp;
-	int ioaddr = dev->base_addr;
-	int err;
-
-	/* Grab the region so we can find another board if autoIRQ fails. */
-	if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) {
-		if (!autoprobe)
-			printk(KERN_WARNING "EEPRO: io-port 0x%04x in use\n",
-				ioaddr);
-		return -EBUSY;
-	}
-
-	/* Now, we are going to check for the signature of the
-	   ID_REG (register 2 of bank 0) */
-
-	id = inb(ioaddr + ID_REG);
-
-	if ((id & ID_REG_MASK) != ID_REG_SIG)
-		goto exit;
-
-	/* We seem to have the 82595 signature, let's
-	   play with its counter (last 2 bits of
-	   register 2 of bank 0) to be sure. */
-
-	counter = id & R_ROBIN_BITS;
-
-	if ((inb(ioaddr + ID_REG) & R_ROBIN_BITS) != (counter + 0x40))
-		goto exit;
-
-	lp = netdev_priv(dev);
-	memset(lp, 0, sizeof(struct eepro_local));
-	lp->xmt_bar = XMT_BAR_PRO;
-	lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO;
-	lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO;
-	lp->eeprom_reg = EEPROM_REG_PRO;
-	spin_lock_init(&lp->lock);
-
-	/* Now, get the ethernet hardware address from
-	   the EEPROM */
-	station_addr[0] = read_eeprom(ioaddr, 2, dev);
-
-	/* FIXME - find another way to know that we've found
-	 * an Etherexpress 10
-	 */
-	if (station_addr[0] == 0x0000 || station_addr[0] == 0xffff) {
-		lp->eepro = LAN595FX_10ISA;
-		lp->eeprom_reg = EEPROM_REG_10;
-		lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10;
-		lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10;
-		lp->xmt_bar = XMT_BAR_10;
-		station_addr[0] = read_eeprom(ioaddr, 2, dev);
-	}
-
-	/* get all words at once. will be used here and for ethtool */
-	for (i = 0; i < 8; i++) {
-		lp->word[i] = read_eeprom(ioaddr, i, dev);
-	}
-	station_addr[1] = lp->word[3];
-	station_addr[2] = lp->word[4];
-
-	if (!lp->eepro) {
-		if (lp->word[7] == ee_FX_INT2IRQ)
-			lp->eepro = 2;
-		else if (station_addr[2] == SA_ADDR1)
-			lp->eepro = 1;
-	}
-
-	/* Fill in the 'dev' fields. */
-	for (i=0; i < 6; i++)
-		dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i];
-
-	/* RX buffer must be more than 3K and less than 29K */
-	if (dev->mem_end < 3072 || dev->mem_end > 29696)
-		lp->rcv_ram = RCV_DEFAULT_RAM;
-
-	/* calculate {xmt,rcv}_{lower,upper}_limit */
-	eepro_recalc(dev);
-
-	if (GetBit(lp->word[5], ee_BNC_TPE))
-		dev->if_port = BNC;
-	else
-		dev->if_port = TPE;
-
- 	if (dev->irq < 2 && lp->eepro != 0) {
- 		/* Mask off INT number */
- 		int count = lp->word[1] & 7;
- 		unsigned irqMask = lp->word[7];
-
- 		while (count--)
- 			irqMask &= irqMask - 1;
-
- 		count = ffs(irqMask);
-
- 		if (count)
- 			dev->irq = count - 1;
-
- 		if (dev->irq < 2) {
- 			printk(KERN_ERR " Duh! illegal interrupt vector stored in EEPROM.\n");
- 			goto exit;
- 		} else if (dev->irq == 2) {
- 			dev->irq = 9;
- 		}
- 	}
-
-	dev->netdev_ops		= &eepro_netdev_ops;
- 	dev->watchdog_timeo	= TX_TIMEOUT;
-	dev->ethtool_ops	= &eepro_ethtool_ops;
-
-	/* print boot time info */
-	eepro_print_info(dev);
-
-	/* reset 82595 */
-	eepro_reset(ioaddr);
-
-	err = register_netdev(dev);
-	if (err)
-		goto err;
-	return 0;
-exit:
-	err = -ENODEV;
-err:
- 	release_region(dev->base_addr, EEPRO_IO_EXTENT);
- 	return err;
-}
-
-/* Open/initialize the board.  This is called (in the current kernel)
-   sometime after booting when the 'ifconfig' program is run.
-
-   This routine should set everything up anew at each open, even
-   registers that "should" only need to be set once at boot, so that
-   there is non-reboot way to recover if something goes wrong.
-   */
-
-static const char irqrmap[] = {-1,-1,0,1,-1,2,-1,-1,-1,0,3,4,-1,-1,-1,-1};
-static const char irqrmap2[] = {-1,-1,4,0,1,2,-1,3,-1,4,5,6,7,-1,-1,-1};
-static int	eepro_grab_irq(struct net_device *dev)
-{
-	static const int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12, 0 };
-	const int *irqp = irqlist;
-	int temp_reg, ioaddr = dev->base_addr;
-
-	eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */
-
-	/* Enable the interrupt line. */
-	eepro_en_intline(ioaddr);
-
-	/* be CAREFUL, BANK 0 now */
-	eepro_sw2bank0(ioaddr);
-
-	/* clear all interrupts */
-	eepro_clear_int(ioaddr);
-
-	/* Let EXEC event to interrupt */
-	eepro_en_intexec(ioaddr);
-
-	do {
-		eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */
-
-		temp_reg = inb(ioaddr + INT_NO_REG);
-		outb((temp_reg & 0xf8) | irqrmap[*irqp], ioaddr + INT_NO_REG);
-
-		eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
-
-		if (request_irq (*irqp, NULL, IRQF_SHARED, "bogus", dev) != EBUSY) {
-			unsigned long irq_mask;
-			/* Twinkle the interrupt, and check if it's seen */
-			irq_mask = probe_irq_on();
-
-			eepro_diag(ioaddr); /* RESET the 82595 */
-			mdelay(20);
-
-			if (*irqp == probe_irq_off(irq_mask))  /* It's a good IRQ line */
-				break;
-
-			/* clear all interrupts */
-			eepro_clear_int(ioaddr);
-		}
-	} while (*++irqp);
-
-	eepro_sw2bank1(ioaddr); /* Switch back to Bank 1 */
-
-	/* Disable the physical interrupt line. */
-	eepro_dis_intline(ioaddr);
-
-	eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
-
-	/* Mask all the interrupts. */
-	eepro_dis_int(ioaddr);
-
-	/* clear all interrupts */
-	eepro_clear_int(ioaddr);
-
-	return dev->irq;
-}
-
-static int eepro_open(struct net_device *dev)
-{
-	unsigned short temp_reg, old8, old9;
-	int irqMask;
-	int i, ioaddr = dev->base_addr;
-	struct eepro_local *lp = netdev_priv(dev);
-
-	if (net_debug > 3)
-		printk(KERN_DEBUG "%s: entering eepro_open routine.\n", dev->name);
-
-	irqMask = lp->word[7];
-
-	if (lp->eepro == LAN595FX_10ISA) {
-		if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 3;\n");
-	}
-	else if (irqMask == ee_FX_INT2IRQ) /* INT to IRQ Mask */
-		{
-			lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */
-			if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n");
-		}
-
-	else if ((dev->dev_addr[0] == SA_ADDR0 &&
-			dev->dev_addr[1] == SA_ADDR1 &&
-			dev->dev_addr[2] == SA_ADDR2))
-		{
-			lp->eepro = 1;
-			if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 1;\n");
-		}  /* Yes, an Intel EtherExpress Pro/10 */
-
-	else lp->eepro = 0; /* No, it is a generic 82585 lan card */
-
-	/* Get the interrupt vector for the 82595 */
-	if (dev->irq < 2 && eepro_grab_irq(dev) == 0) {
-		printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
-		return -EAGAIN;
-	}
-
-	if (request_irq(dev->irq , eepro_interrupt, 0, dev->name, dev)) {
-		printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
-		return -EAGAIN;
-	}
-
-	/* Initialize the 82595. */
-
-	eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
-	temp_reg = inb(ioaddr + lp->eeprom_reg);
-
-	lp->stepping = temp_reg >> 5;	/* Get the stepping number of the 595 */
-
-	if (net_debug > 3)
-		printk(KERN_DEBUG "The stepping of the 82595 is %d\n", lp->stepping);
-
-	if (temp_reg & 0x10) /* Check the TurnOff Enable bit */
-		outb(temp_reg & 0xef, ioaddr + lp->eeprom_reg);
-	for (i=0; i < 6; i++)
-		outb(dev->dev_addr[i] , ioaddr + I_ADD_REG0 + i);
-
-	temp_reg = inb(ioaddr + REG1);    /* Setup Transmit Chaining */
-	outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop /* and discard bad RCV frames */
-		| RCV_Discard_BadFrame, ioaddr + REG1);
-
-	temp_reg = inb(ioaddr + REG2); /* Match broadcast */
-	outb(temp_reg | 0x14, ioaddr + REG2);
-
-	temp_reg = inb(ioaddr + REG3);
-	outb(temp_reg & 0x3f, ioaddr + REG3); /* clear test mode */
-
-	/* Set the receiving mode */
-	eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */
-
-	/* Set the interrupt vector */
-	temp_reg = inb(ioaddr + INT_NO_REG);
-	if (lp->eepro == LAN595FX || lp->eepro == LAN595FX_10ISA)
-		outb((temp_reg & 0xf8) | irqrmap2[dev->irq], ioaddr + INT_NO_REG);
-	else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
-
-
-	temp_reg = inb(ioaddr + INT_NO_REG);
-	if (lp->eepro == LAN595FX || lp->eepro == LAN595FX_10ISA)
-		outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG);
-	else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
-
-	if (net_debug > 3)
-		printk(KERN_DEBUG "eepro_open: content of INT Reg is %x\n", temp_reg);
-
-
-	/* Initialize the RCV and XMT upper and lower limits */
-	outb(lp->rcv_lower_limit >> 8, ioaddr + RCV_LOWER_LIMIT_REG);
-	outb(lp->rcv_upper_limit >> 8, ioaddr + RCV_UPPER_LIMIT_REG);
-	outb(lp->xmt_lower_limit >> 8, ioaddr + lp->xmt_lower_limit_reg);
-	outb(lp->xmt_upper_limit >> 8, ioaddr + lp->xmt_upper_limit_reg);
-
-	/* Enable the interrupt line. */
-	eepro_en_intline(ioaddr);
-
-	/* Switch back to Bank 0 */
-	eepro_sw2bank0(ioaddr);
-
-	/* Let RX and TX events to interrupt */
-	eepro_en_int(ioaddr);
-
-	/* clear all interrupts */
-	eepro_clear_int(ioaddr);
-
-	/* Initialize RCV */
-	outw(lp->rcv_lower_limit, ioaddr + RCV_BAR);
-	lp->rx_start = lp->rcv_lower_limit;
-	outw(lp->rcv_upper_limit | 0xfe, ioaddr + RCV_STOP);
-
-	/* Initialize XMT */
-	outw(lp->xmt_lower_limit, ioaddr + lp->xmt_bar);
-	lp->tx_start = lp->tx_end = lp->xmt_lower_limit;
-	lp->tx_last = 0;
-
-	/* Check for the i82595TX and i82595FX */
-	old8 = inb(ioaddr + 8);
-	outb(~old8, ioaddr + 8);
-
-	if ((temp_reg = inb(ioaddr + 8)) == old8) {
-		if (net_debug > 3)
-			printk(KERN_DEBUG "i82595 detected!\n");
-		lp->version = LAN595;
-	}
-	else {
-		lp->version = LAN595TX;
-		outb(old8, ioaddr + 8);
-		old9 = inb(ioaddr + 9);
-
-		if (irqMask==ee_FX_INT2IRQ) {
-			if (net_debug > 3) {
-				printk(KERN_DEBUG "IrqMask: %#x\n",irqMask);
-				printk(KERN_DEBUG "i82595FX detected!\n");
-			}
-			lp->version = LAN595FX;
-			outb(old9, ioaddr + 9);
-			if (dev->if_port != TPE) {	/* Hopefully, this will fix the
-							problem of using Pentiums and
-							pro/10 w/ BNC. */
-				eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
-				temp_reg = inb(ioaddr + REG13);
-				/* disable the full duplex mode since it is not
-				applicable with the 10Base2 cable. */
-				outb(temp_reg & ~(FDX | A_N_ENABLE), REG13);
-				eepro_sw2bank0(ioaddr); /* be CAREFUL, BANK 0 now */
-			}
-		}
-		else if (net_debug > 3) {
-			printk(KERN_DEBUG "temp_reg: %#x  ~old9: %#x\n",temp_reg,((~old9)&0xff));
-			printk(KERN_DEBUG "i82595TX detected!\n");
-		}
-	}
-
-	eepro_sel_reset(ioaddr);
-
-	netif_start_queue(dev);
-
-	if (net_debug > 3)
-		printk(KERN_DEBUG "%s: exiting eepro_open routine.\n", dev->name);
-
-	/* enabling rx */
-	eepro_en_rx(ioaddr);
-
-	return 0;
-}
-
-static void eepro_tx_timeout (struct net_device *dev)
-{
-	struct eepro_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-
-	/* if (net_debug > 1) */
-	printk (KERN_ERR "%s: transmit timed out, %s?\n", dev->name,
-		"network cable problem");
-	/* This is not a duplicate. One message for the console,
-	   one for the log file  */
-	printk (KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name,
-		"network cable problem");
-	eepro_complete_selreset(ioaddr);
-}
-
-
-static netdev_tx_t eepro_send_packet(struct sk_buff *skb,
-				     struct net_device *dev)
-{
-	struct eepro_local *lp = netdev_priv(dev);
-	unsigned long flags;
-	int ioaddr = dev->base_addr;
-	short length = skb->len;
-
-	if (net_debug > 5)
-		printk(KERN_DEBUG  "%s: entering eepro_send_packet routine.\n", dev->name);
-
-	if (length < ETH_ZLEN) {
-		if (skb_padto(skb, ETH_ZLEN))
-			return NETDEV_TX_OK;
-		length = ETH_ZLEN;
-	}
-	netif_stop_queue (dev);
-
-	eepro_dis_int(ioaddr);
-	spin_lock_irqsave(&lp->lock, flags);
-
-	{
-		unsigned char *buf = skb->data;
-
-		if (hardware_send_packet(dev, buf, length))
-			/* we won't wake queue here because we're out of space */
-			dev->stats.tx_dropped++;
-		else {
-			dev->stats.tx_bytes+=skb->len;
-			netif_wake_queue(dev);
-		}
-
-	}
-
-	dev_kfree_skb (skb);
-
-	/* You might need to clean up and record Tx statistics here. */
-	/* dev->stats.tx_aborted_errors++; */
-
-	if (net_debug > 5)
-		printk(KERN_DEBUG "%s: exiting eepro_send_packet routine.\n", dev->name);
-
-	eepro_en_int(ioaddr);
-	spin_unlock_irqrestore(&lp->lock, flags);
-
-	return NETDEV_TX_OK;
-}
-
-
-/*	The typical workload of the driver:
-	Handle the network interface interrupts. */
-
-static irqreturn_t
-eepro_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct eepro_local *lp;
-	int ioaddr, status, boguscount = 20;
-	int handled = 0;
-
-	lp = netdev_priv(dev);
-
-        spin_lock(&lp->lock);
-
-	if (net_debug > 5)
-		printk(KERN_DEBUG "%s: entering eepro_interrupt routine.\n", dev->name);
-
-	ioaddr = dev->base_addr;
-
-	while (((status = inb(ioaddr + STATUS_REG)) & (RX_INT|TX_INT)) && (boguscount--))
-	{
-		handled = 1;
-		if (status & RX_INT) {
-			if (net_debug > 4)
-				printk(KERN_DEBUG "%s: packet received interrupt.\n", dev->name);
-
-			eepro_dis_int(ioaddr);
-
-			/* Get the received packets */
-			eepro_ack_rx(ioaddr);
-			eepro_rx(dev);
-
-			eepro_en_int(ioaddr);
-		}
-		if (status & TX_INT) {
-			if (net_debug > 4)
- 				printk(KERN_DEBUG "%s: packet transmit interrupt.\n", dev->name);
-
-
-			eepro_dis_int(ioaddr);
-
-			/* Process the status of transmitted packets */
-			eepro_ack_tx(ioaddr);
-			eepro_transmit_interrupt(dev);
-
-			eepro_en_int(ioaddr);
-		}
-	}
-
-	if (net_debug > 5)
-		printk(KERN_DEBUG "%s: exiting eepro_interrupt routine.\n", dev->name);
-
-	spin_unlock(&lp->lock);
-	return IRQ_RETVAL(handled);
-}
-
-static int eepro_close(struct net_device *dev)
-{
-	struct eepro_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-	short temp_reg;
-
-	netif_stop_queue(dev);
-
-	eepro_sw2bank1(ioaddr); /* Switch back to Bank 1 */
-
-	/* Disable the physical interrupt line. */
-	temp_reg = inb(ioaddr + REG1);
-	outb(temp_reg & 0x7f, ioaddr + REG1);
-
-	eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
-
-	/* Flush the Tx and disable Rx. */
-	outb(STOP_RCV_CMD, ioaddr);
-	lp->tx_start = lp->tx_end = lp->xmt_lower_limit;
-	lp->tx_last = 0;
-
-	/* Mask all the interrupts. */
-	eepro_dis_int(ioaddr);
-
-	/* clear all interrupts */
-	eepro_clear_int(ioaddr);
-
-	/* Reset the 82595 */
-	eepro_reset(ioaddr);
-
-	/* release the interrupt */
-	free_irq(dev->irq, dev);
-
-	/* Update the statistics here. What statistics? */
-
-	return 0;
-}
-
-/* Set or clear the multicast filter for this adaptor.
- */
-static void
-set_multicast_list(struct net_device *dev)
-{
-	struct eepro_local *lp = netdev_priv(dev);
-	short ioaddr = dev->base_addr;
-	unsigned short mode;
-	struct netdev_hw_addr *ha;
-	int mc_count = netdev_mc_count(dev);
-
-	if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || mc_count > 63)
-	{
-		eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
-		mode = inb(ioaddr + REG2);
-		outb(mode | PRMSC_Mode, ioaddr + REG2);
-		mode = inb(ioaddr + REG3);
-		outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
-		eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */
-	}
-
-	else if (mc_count == 0)
-	{
-		eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
-		mode = inb(ioaddr + REG2);
-		outb(mode & 0xd6, ioaddr + REG2); /* Turn off Multi-IA and PRMSC_Mode bits */
-		mode = inb(ioaddr + REG3);
-		outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
-		eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */
-	}
-
-	else
-	{
-		unsigned short status, *eaddrs;
-		int i, boguscount = 0;
-
-		/* Disable RX and TX interrupts.  Necessary to avoid
-		   corruption of the HOST_ADDRESS_REG by interrupt
-		   service routines. */
-		eepro_dis_int(ioaddr);
-
-		eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
-		mode = inb(ioaddr + REG2);
-		outb(mode | Multi_IA, ioaddr + REG2);
-		mode = inb(ioaddr + REG3);
-		outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
-		eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */
-		outw(lp->tx_end, ioaddr + HOST_ADDRESS_REG);
-		outw(MC_SETUP, ioaddr + IO_PORT);
-		outw(0, ioaddr + IO_PORT);
-		outw(0, ioaddr + IO_PORT);
-		outw(6 * (mc_count + 1), ioaddr + IO_PORT);
-
-		netdev_for_each_mc_addr(ha, dev) {
-			eaddrs = (unsigned short *) ha->addr;
-			outw(*eaddrs++, ioaddr + IO_PORT);
-			outw(*eaddrs++, ioaddr + IO_PORT);
-			outw(*eaddrs++, ioaddr + IO_PORT);
-		}
-
-		eaddrs = (unsigned short *) dev->dev_addr;
-		outw(eaddrs[0], ioaddr + IO_PORT);
-		outw(eaddrs[1], ioaddr + IO_PORT);
-		outw(eaddrs[2], ioaddr + IO_PORT);
-		outw(lp->tx_end, ioaddr + lp->xmt_bar);
-		outb(MC_SETUP, ioaddr);
-
-		/* Update the transmit queue */
-		i = lp->tx_end + XMT_HEADER + 6 * (mc_count + 1);
-
-		if (lp->tx_start != lp->tx_end)
-		{
-			/* update the next address and the chain bit in the
-			   last packet */
-			outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
-			outw(i, ioaddr + IO_PORT);
-			outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
-			status = inw(ioaddr + IO_PORT);
-			outw(status | CHAIN_BIT, ioaddr + IO_PORT);
-			lp->tx_end = i ;
-		}
-		else {
-			lp->tx_start = lp->tx_end = i ;
-		}
-
-		/* Acknowledge that the MC setup is done */
-		do { /* We should be doing this in the eepro_interrupt()! */
-			SLOW_DOWN;
-			SLOW_DOWN;
-			if (inb(ioaddr + STATUS_REG) & 0x08)
-			{
-				i = inb(ioaddr);
-				outb(0x08, ioaddr + STATUS_REG);
-
-				if (i & 0x20) { /* command ABORTed */
-					printk(KERN_NOTICE "%s: multicast setup failed.\n",
-						dev->name);
-					break;
-				} else if ((i & 0x0f) == 0x03)	{ /* MC-Done */
-					printk(KERN_DEBUG "%s: set Rx mode to %d address%s.\n",
-						dev->name, mc_count,
-						mc_count > 1 ? "es":"");
-					break;
-				}
-			}
-		} while (++boguscount < 100);
-
-		/* Re-enable RX and TX interrupts */
-		eepro_en_int(ioaddr);
-	}
-	if (lp->eepro == LAN595FX_10ISA) {
-		eepro_complete_selreset(ioaddr);
-	}
-	else
-		eepro_en_rx(ioaddr);
-}
-
-/* The horrible routine to read a word from the serial EEPROM. */
-/* IMPORTANT - the 82595 will be set to Bank 0 after the eeprom is read */
-
-/* The delay between EEPROM clock transitions. */
-#define eeprom_delay() { udelay(40); }
-#define EE_READ_CMD (6 << 6)
-
-static int
-read_eeprom(int ioaddr, int location, struct net_device *dev)
-{
-	int i;
-	unsigned short retval = 0;
-	struct eepro_local *lp = netdev_priv(dev);
-	short ee_addr = ioaddr + lp->eeprom_reg;
-	int read_cmd = location | EE_READ_CMD;
-	short ctrl_val = EECS ;
-
-	/* XXXX - black magic */
-		eepro_sw2bank1(ioaddr);
-		outb(0x00, ioaddr + STATUS_REG);
-	/* XXXX - black magic */
-
-	eepro_sw2bank2(ioaddr);
-	outb(ctrl_val, ee_addr);
-
-	/* Shift the read command bits out. */
-	for (i = 8; i >= 0; i--) {
-		short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI
-			: ctrl_val;
-		outb(outval, ee_addr);
-		outb(outval | EESK, ee_addr);	/* EEPROM clock tick. */
-		eeprom_delay();
-		outb(outval, ee_addr);	/* Finish EEPROM a clock tick. */
-		eeprom_delay();
-	}
-	outb(ctrl_val, ee_addr);
-
-	for (i = 16; i > 0; i--) {
-		outb(ctrl_val | EESK, ee_addr);	 eeprom_delay();
-		retval = (retval << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0);
-		outb(ctrl_val, ee_addr);  eeprom_delay();
-	}
-
-	/* Terminate the EEPROM access. */
-	ctrl_val &= ~EECS;
-	outb(ctrl_val | EESK, ee_addr);
-	eeprom_delay();
-	outb(ctrl_val, ee_addr);
-	eeprom_delay();
-	eepro_sw2bank0(ioaddr);
-	return retval;
-}
-
-static int
-hardware_send_packet(struct net_device *dev, void *buf, short length)
-{
-	struct eepro_local *lp = netdev_priv(dev);
-	short ioaddr = dev->base_addr;
-	unsigned status, tx_available, last, end;
-
-	if (net_debug > 5)
-		printk(KERN_DEBUG "%s: entering hardware_send_packet routine.\n", dev->name);
-
-	/* determine how much of the transmit buffer space is available */
-	if (lp->tx_end > lp->tx_start)
-		tx_available = lp->xmt_ram - (lp->tx_end - lp->tx_start);
-	else if (lp->tx_end < lp->tx_start)
-		tx_available = lp->tx_start - lp->tx_end;
-	else tx_available = lp->xmt_ram;
-
-	if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) >= tx_available) {
-		/* No space available ??? */
-		return 1;
-		}
-
-		last = lp->tx_end;
-		end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
-
-	if (end >= lp->xmt_upper_limit + 2) { /* the transmit buffer is wrapped around */
-		if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) {
-				/* Arrrr!!!, must keep the xmt header together,
-				several days were lost to chase this one down. */
-			last = lp->xmt_lower_limit;
-				end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
-			}
-		else end = lp->xmt_lower_limit + (end -
-						lp->xmt_upper_limit + 2);
-		}
-
-		outw(last, ioaddr + HOST_ADDRESS_REG);
-		outw(XMT_CMD, ioaddr + IO_PORT);
-		outw(0, ioaddr + IO_PORT);
-		outw(end, ioaddr + IO_PORT);
-		outw(length, ioaddr + IO_PORT);
-
-		if (lp->version == LAN595)
-			outsw(ioaddr + IO_PORT, buf, (length + 3) >> 1);
-		else {	/* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
-			unsigned short temp = inb(ioaddr + INT_MASK_REG);
-			outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);
-			outsl(ioaddr + IO_PORT_32_BIT, buf, (length + 3) >> 2);
-			outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
-		}
-
-		/* A dummy read to flush the DRAM write pipeline */
-		status = inw(ioaddr + IO_PORT);
-
-		if (lp->tx_start == lp->tx_end) {
-		outw(last, ioaddr + lp->xmt_bar);
-			outb(XMT_CMD, ioaddr);
-			lp->tx_start = last;   /* I don't like to change tx_start here */
-		}
-		else {
-			/* update the next address and the chain bit in the
-			last packet */
-
-			if (lp->tx_end != last) {
-				outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
-				outw(last, ioaddr + IO_PORT);
-			}
-
-			outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
-			status = inw(ioaddr + IO_PORT);
-			outw(status | CHAIN_BIT, ioaddr + IO_PORT);
-
-			/* Continue the transmit command */
-			outb(RESUME_XMT_CMD, ioaddr);
-		}
-
-		lp->tx_last = last;
-		lp->tx_end = end;
-
-		if (net_debug > 5)
-			printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
-
-	return 0;
-}
-
-static void
-eepro_rx(struct net_device *dev)
-{
-	struct eepro_local *lp = netdev_priv(dev);
-	short ioaddr = dev->base_addr;
-	short boguscount = 20;
-	short rcv_car = lp->rx_start;
-	unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size;
-
-	if (net_debug > 5)
-		printk(KERN_DEBUG "%s: entering eepro_rx routine.\n", dev->name);
-
-	/* Set the read pointer to the start of the RCV */
-	outw(rcv_car, ioaddr + HOST_ADDRESS_REG);
-
-	rcv_event = inw(ioaddr + IO_PORT);
-
-	while (rcv_event == RCV_DONE) {
-
-		rcv_status = inw(ioaddr + IO_PORT);
-		rcv_next_frame = inw(ioaddr + IO_PORT);
-		rcv_size = inw(ioaddr + IO_PORT);
-
-		if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) {
-
-			/* Malloc up new buffer. */
-			struct sk_buff *skb;
-
-			dev->stats.rx_bytes+=rcv_size;
-			rcv_size &= 0x3fff;
-			skb = dev_alloc_skb(rcv_size+5);
-			if (skb == NULL) {
-				printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
-				dev->stats.rx_dropped++;
-				rcv_car = lp->rx_start + RCV_HEADER + rcv_size;
-				lp->rx_start = rcv_next_frame;
-				outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG);
-
-				break;
-			}
-			skb_reserve(skb,2);
-
-			if (lp->version == LAN595)
-				insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 3) >> 1);
-			else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
-				unsigned short temp = inb(ioaddr + INT_MASK_REG);
-				outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);
-				insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size),
-					(rcv_size + 3) >> 2);
-				outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
-			}
-
-			skb->protocol = eth_type_trans(skb,dev);
-			netif_rx(skb);
-			dev->stats.rx_packets++;
-		}
-
-		else { /* Not sure will ever reach here,
-			I set the 595 to discard bad received frames */
-			dev->stats.rx_errors++;
-
-			if (rcv_status & 0x0100)
-				dev->stats.rx_over_errors++;
-
-			else if (rcv_status & 0x0400)
-				dev->stats.rx_frame_errors++;
-
-			else if (rcv_status & 0x0800)
-				dev->stats.rx_crc_errors++;
-
-			printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n",
-				dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);
-		}
-
-		if (rcv_status & 0x1000)
-			dev->stats.rx_length_errors++;
-
-		rcv_car = lp->rx_start + RCV_HEADER + rcv_size;
-		lp->rx_start = rcv_next_frame;
-
-		if (--boguscount == 0)
-			break;
-
-		outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG);
-		rcv_event = inw(ioaddr + IO_PORT);
-
-	}
-	if (rcv_car == 0)
-		rcv_car = lp->rcv_upper_limit | 0xff;
-
-	outw(rcv_car - 1, ioaddr + RCV_STOP);
-
-	if (net_debug > 5)
-		printk(KERN_DEBUG "%s: exiting eepro_rx routine.\n", dev->name);
-}
-
-static void
-eepro_transmit_interrupt(struct net_device *dev)
-{
-	struct eepro_local *lp = netdev_priv(dev);
-	short ioaddr = dev->base_addr;
-	short boguscount = 25;
-	short xmt_status;
-
-	while ((lp->tx_start != lp->tx_end) && boguscount--) {
-
-		outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
-		xmt_status = inw(ioaddr+IO_PORT);
-
-		if (!(xmt_status & TX_DONE_BIT))
-				break;
-
-		xmt_status = inw(ioaddr+IO_PORT);
-		lp->tx_start = inw(ioaddr+IO_PORT);
-
-		netif_wake_queue (dev);
-
-		if (xmt_status & TX_OK)
-			dev->stats.tx_packets++;
-		else {
-			dev->stats.tx_errors++;
-			if (xmt_status & 0x0400) {
-				dev->stats.tx_carrier_errors++;
-				printk(KERN_DEBUG "%s: carrier error\n",
-					dev->name);
-				printk(KERN_DEBUG "%s: XMT status = %#x\n",
-					dev->name, xmt_status);
-			}
-			else {
-				printk(KERN_DEBUG "%s: XMT status = %#x\n",
-					dev->name, xmt_status);
-				printk(KERN_DEBUG "%s: XMT status = %#x\n",
-					dev->name, xmt_status);
-			}
-		}
-		if (xmt_status & 0x000f) {
-			dev->stats.collisions += (xmt_status & 0x000f);
-		}
-
-		if ((xmt_status & 0x0040) == 0x0) {
-			dev->stats.tx_heartbeat_errors++;
-		}
-	}
-}
-
-static int eepro_ethtool_get_settings(struct net_device *dev,
-					struct ethtool_cmd *cmd)
-{
-	struct eepro_local	*lp = netdev_priv(dev);
-
-	cmd->supported = 	SUPPORTED_10baseT_Half |
-				SUPPORTED_10baseT_Full |
-				SUPPORTED_Autoneg;
-	cmd->advertising =	ADVERTISED_10baseT_Half |
-				ADVERTISED_10baseT_Full |
-				ADVERTISED_Autoneg;
-
-	if (GetBit(lp->word[5], ee_PortTPE)) {
-		cmd->supported |= SUPPORTED_TP;
-		cmd->advertising |= ADVERTISED_TP;
-	}
-	if (GetBit(lp->word[5], ee_PortBNC)) {
-		cmd->supported |= SUPPORTED_BNC;
-		cmd->advertising |= ADVERTISED_BNC;
-	}
-	if (GetBit(lp->word[5], ee_PortAUI)) {
-		cmd->supported |= SUPPORTED_AUI;
-		cmd->advertising |= ADVERTISED_AUI;
-	}
-
-	ethtool_cmd_speed_set(cmd, SPEED_10);
-
-	if (dev->if_port == TPE && lp->word[1] & ee_Duplex) {
-		cmd->duplex = DUPLEX_FULL;
-	}
-	else {
-		cmd->duplex = DUPLEX_HALF;
-	}
-
-	cmd->port = dev->if_port;
-	cmd->phy_address = dev->base_addr;
-	cmd->transceiver = XCVR_INTERNAL;
-
-	if (lp->word[0] & ee_AutoNeg) {
-		cmd->autoneg = 1;
-	}
-
-	return 0;
-}
-
-static void eepro_ethtool_get_drvinfo(struct net_device *dev,
-					struct ethtool_drvinfo *drvinfo)
-{
-	strcpy(drvinfo->driver, DRV_NAME);
-	strcpy(drvinfo->version, DRV_VERSION);
-	sprintf(drvinfo->bus_info, "ISA 0x%lx", dev->base_addr);
-}
-
-static const struct ethtool_ops eepro_ethtool_ops = {
-	.get_settings	= eepro_ethtool_get_settings,
-	.get_drvinfo 	= eepro_ethtool_get_drvinfo,
-};
-
-#ifdef MODULE
-
-#define MAX_EEPRO 8
-static struct net_device *dev_eepro[MAX_EEPRO];
-
-static int io[MAX_EEPRO] = {
-  [0 ... MAX_EEPRO-1] = -1
-};
-static int irq[MAX_EEPRO];
-static int mem[MAX_EEPRO] = {	/* Size of the rx buffer in KB */
-  [0 ... MAX_EEPRO-1] = RCV_DEFAULT_RAM/1024
-};
-static int autodetect;
-
-static int n_eepro;
-/* For linux 2.1.xx */
-
-MODULE_AUTHOR("Pascal Dupuis and others");
-MODULE_DESCRIPTION("Intel i82595 ISA EtherExpressPro10/10+ driver");
-MODULE_LICENSE("GPL");
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(mem, int, NULL, 0);
-module_param(autodetect, int, 0);
-MODULE_PARM_DESC(io, "EtherExpress Pro/10 I/O base address(es)");
-MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)");
-MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)");
-MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)");
-
-int __init init_module(void)
-{
-	struct net_device *dev;
-	int i;
-	if (io[0] == -1 && autodetect == 0) {
-		printk(KERN_WARNING "eepro_init_module: Probe is very dangerous in ISA boards!\n");
-		printk(KERN_WARNING "eepro_init_module: Please add \"autodetect=1\" to force probe\n");
-		return -ENODEV;
-	}
-	else if (autodetect) {
-		/* if autodetect is set then we must force detection */
-		for (i = 0; i < MAX_EEPRO; i++) {
-			io[i] = 0;
-		}
-
-		printk(KERN_INFO "eepro_init_module: Auto-detecting boards (May God protect us...)\n");
-	}
-
-	for (i = 0; i < MAX_EEPRO && io[i] != -1; i++) {
-		dev = alloc_etherdev(sizeof(struct eepro_local));
-		if (!dev)
-			break;
-
-		dev->mem_end = mem[i];
-		dev->base_addr = io[i];
-		dev->irq = irq[i];
-
-		if (do_eepro_probe(dev) == 0) {
-			dev_eepro[n_eepro++] = dev;
-			continue;
-		}
-		free_netdev(dev);
-		break;
-	}
-
-	if (n_eepro)
-		printk(KERN_INFO "%s", version);
-
-	return n_eepro ? 0 : -ENODEV;
-}
-
-void __exit
-cleanup_module(void)
-{
-	int i;
-
-	for (i=0; i<n_eepro; i++) {
-		struct net_device *dev = dev_eepro[i];
-		unregister_netdev(dev);
-		release_region(dev->base_addr, EEPRO_IO_EXTENT);
-		free_netdev(dev);
-	}
-}
-#endif /* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/eexpress.c linux-libre-3.2-gnu/drivers/net/eexpress.c
--- linux-libre-3.1-gnu/drivers/net/eexpress.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/eexpress.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1720 +0,0 @@
-/* Intel EtherExpress 16 device driver for Linux
- *
- * Written by John Sullivan, 1995
- *  based on original code by Donald Becker, with changes by
- *  Alan Cox and Pauline Middelink.
- *
- * Support for 8-bit mode by Zoltan Szilagyi <zoltans@cs.arizona.edu>
- *
- * Many modifications, and currently maintained, by
- *  Philip Blundell <philb@gnu.org>
- * Added the Compaq LTE  Alan Cox <alan@lxorguk.ukuu.org.uk>
- * Added MCA support Adam Fritzler
- *
- * Note - this driver is experimental still - it has problems on faster
- * machines. Someone needs to sit down and go through it line by line with
- * a databook...
- */
-
-/* The EtherExpress 16 is a fairly simple card, based on a shared-memory
- * design using the i82586 Ethernet coprocessor.  It bears no relationship,
- * as far as I know, to the similarly-named "EtherExpress Pro" range.
- *
- * Historically, Linux support for these cards has been very bad.  However,
- * things seem to be getting better slowly.
- */
-
-/* If your card is confused about what sort of interface it has (eg it
- * persistently reports "10baseT" when none is fitted), running 'SOFTSET /BART'
- * or 'SOFTSET /LISA' from DOS seems to help.
- */
-
-/* Here's the scoop on memory mapping.
- *
- * There are three ways to access EtherExpress card memory: either using the
- * shared-memory mapping, or using PIO through the dataport, or using PIO
- * through the "shadow memory" ports.
- *
- * The shadow memory system works by having the card map some of its memory
- * as follows:
- *
- * (the low five bits of the SMPTR are ignored)
- *
- *  base+0x4000..400f      memory at SMPTR+0..15
- *  base+0x8000..800f      memory at SMPTR+16..31
- *  base+0xc000..c007      dubious stuff (memory at SMPTR+16..23 apparently)
- *  base+0xc008..c00f      memory at 0x0008..0x000f
- *
- * This last set (the one at c008) is particularly handy because the SCB
- * lives at 0x0008.  So that set of ports gives us easy random access to data
- * in the SCB without having to mess around setting up pointers and the like.
- * We always use this method to access the SCB (via the scb_xx() functions).
- *
- * Dataport access works by aiming the appropriate (read or write) pointer
- * at the first address you're interested in, and then reading or writing from
- * the dataport.  The pointers auto-increment after each transfer.  We use
- * this for data transfer.
- *
- * We don't use the shared-memory system because it allegedly doesn't work on
- * all cards, and because it's a bit more prone to go wrong (it's one more
- * thing to configure...).
- */
-
-/* Known bugs:
- *
- * - The card seems to want to give us two interrupts every time something
- *   happens, where just one would be better.
- */
-
-/*
- *
- * Note by Zoltan Szilagyi 10-12-96:
- *
- * I've succeeded in eliminating the "CU wedged" messages, and hence the
- * lockups, which were only occurring with cards running in 8-bit mode ("force
- * 8-bit operation" in Intel's SoftSet utility). This version of the driver
- * sets the 82586 and the ASIC to 8-bit mode at startup; it also stops the
- * CU before submitting a packet for transmission, and then restarts it as soon
- * as the process of handing the packet is complete. This is definitely an
- * unnecessary slowdown if the card is running in 16-bit mode; therefore one
- * should detect 16-bit vs 8-bit mode from the EEPROM settings and act
- * accordingly. In 8-bit mode with this bugfix I'm getting about 150 K/s for
- * ftp's, which is significantly better than I get in DOS, so the overhead of
- * stopping and restarting the CU with each transmit is not prohibitive in
- * practice.
- *
- * Update by David Woodhouse 11/5/99:
- *
- * I've seen "CU wedged" messages in 16-bit mode, on the Alpha architecture.
- * I assume that this is because 16-bit accesses are actually handled as two
- * 8-bit accesses.
- */
-
-#ifdef __alpha__
-#define LOCKUP16 1
-#endif
-#ifndef LOCKUP16
-#define LOCKUP16 0
-#endif
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/in.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/mca-legacy.h>
-#include <linux/spinlock.h>
-#include <linux/bitops.h>
-#include <linux/jiffies.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#ifndef NET_DEBUG
-#define NET_DEBUG 4
-#endif
-
-#include "eexpress.h"
-
-#define EEXP_IO_EXTENT  16
-
-/*
- * Private data declarations
- */
-
-struct net_local
-{
-	unsigned long last_tx;       /* jiffies when last transmit started */
-	unsigned long init_time;     /* jiffies when eexp_hw_init586 called */
-	unsigned short rx_first;     /* first rx buf, same as RX_BUF_START */
-	unsigned short rx_last;      /* last rx buf */
-	unsigned short rx_ptr;       /* first rx buf to look at */
-	unsigned short tx_head;      /* next free tx buf */
-	unsigned short tx_reap;      /* first in-use tx buf */
-	unsigned short tx_tail;      /* previous tx buf to tx_head */
-	unsigned short tx_link;      /* last known-executing tx buf */
-	unsigned short last_tx_restart;   /* set to tx_link when we
-					     restart the CU */
-	unsigned char started;
-	unsigned short rx_buf_start;
-	unsigned short rx_buf_end;
-	unsigned short num_tx_bufs;
-	unsigned short num_rx_bufs;
-	unsigned char width;         /* 0 for 16bit, 1 for 8bit */
-	unsigned char was_promisc;
-	unsigned char old_mc_count;
-	spinlock_t lock;
-};
-
-/* This is the code and data that is downloaded to the EtherExpress card's
- * memory at boot time.
- */
-
-static unsigned short start_code[] = {
-/* 0x0000 */
-	0x0001,                 /* ISCP: busy - cleared after reset */
-	0x0008,0x0000,0x0000,   /* offset,address (lo,hi) of SCB */
-
-	0x0000,0x0000,          /* SCB: status, commands */
-	0x0000,0x0000,          /* links to first command block,
-				   first receive descriptor */
-	0x0000,0x0000,          /* CRC error, alignment error counts */
-	0x0000,0x0000,          /* out of resources, overrun error counts */
-
-	0x0000,0x0000,          /* pad */
-	0x0000,0x0000,
-
-/* 0x20 -- start of 82586 CU program */
-#define CONF_LINK 0x20
-	0x0000,Cmd_Config,
-	0x0032,                 /* link to next command */
-	0x080c,                 /* 12 bytes follow : fifo threshold=8 */
-	0x2e40,                 /* don't rx bad frames
-				 * SRDY/ARDY => ext. sync. : preamble len=8
-	                         * take addresses from data buffers
-				 * 6 bytes/address
-				 */
-	0x6000,                 /* default backoff method & priority
-				 * interframe spacing = 0x60 */
-	0xf200,                 /* slot time=0x200
-				 * max collision retry = 0xf */
-#define CONF_PROMISC  0x2e
-	0x0000,                 /* no HDLC : normal CRC : enable broadcast
-				 * disable promiscuous/multicast modes */
-	0x003c,                 /* minimum frame length = 60 octets) */
-
-	0x0000,Cmd_SetAddr,
-	0x003e,                 /* link to next command */
-#define CONF_HWADDR  0x38
-	0x0000,0x0000,0x0000,   /* hardware address placed here */
-
-	0x0000,Cmd_MCast,
-	0x0076,                 /* link to next command */
-#define CONF_NR_MULTICAST 0x44
-	0x0000,                 /* number of bytes in multicast address(es) */
-#define CONF_MULTICAST 0x46
-	0x0000, 0x0000, 0x0000, /* some addresses */
-	0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000,
-
-#define CONF_DIAG_RESULT  0x76
-	0x0000, Cmd_Diag,
-	0x007c,                 /* link to next command */
-
-	0x0000,Cmd_TDR|Cmd_INT,
-	0x0084,
-#define CONF_TDR_RESULT  0x82
-	0x0000,
-
-	0x0000,Cmd_END|Cmd_Nop, /* end of configure sequence */
-	0x0084                  /* dummy link */
-};
-
-/* maps irq number to EtherExpress magic value */
-static char irqrmap[] = { 0,0,1,2,3,4,0,0,0,1,5,6,0,0,0,0 };
-
-#ifdef CONFIG_MCA_LEGACY
-/* mapping of the first four bits of the second POS register */
-static unsigned short mca_iomap[] = {
-	0x270, 0x260, 0x250, 0x240, 0x230, 0x220, 0x210, 0x200,
-	0x370, 0x360, 0x350, 0x340, 0x330, 0x320, 0x310, 0x300
-};
-/* bits 5-7 of the second POS register */
-static char mca_irqmap[] = { 12, 9, 3, 4, 5, 10, 11, 15 };
-#endif
-
-/*
- * Prototypes for Linux interface
- */
-
-static int eexp_open(struct net_device *dev);
-static int eexp_close(struct net_device *dev);
-static void eexp_timeout(struct net_device *dev);
-static netdev_tx_t eexp_xmit(struct sk_buff *buf,
-			     struct net_device *dev);
-
-static irqreturn_t eexp_irq(int irq, void *dev_addr);
-static void eexp_set_multicast(struct net_device *dev);
-
-/*
- * Prototypes for hardware access functions
- */
-
-static void eexp_hw_rx_pio(struct net_device *dev);
-static void eexp_hw_tx_pio(struct net_device *dev, unsigned short *buf,
-		       unsigned short len);
-static int eexp_hw_probe(struct net_device *dev,unsigned short ioaddr);
-static unsigned short eexp_hw_readeeprom(unsigned short ioaddr,
-					 unsigned char location);
-
-static unsigned short eexp_hw_lasttxstat(struct net_device *dev);
-static void eexp_hw_txrestart(struct net_device *dev);
-
-static void eexp_hw_txinit    (struct net_device *dev);
-static void eexp_hw_rxinit    (struct net_device *dev);
-
-static void eexp_hw_init586   (struct net_device *dev);
-static void eexp_setup_filter (struct net_device *dev);
-
-static char *eexp_ifmap[]={"AUI", "BNC", "RJ45"};
-enum eexp_iftype {AUI=0, BNC=1, TPE=2};
-
-#define STARTED_RU      2
-#define STARTED_CU      1
-
-/*
- * Primitive hardware access functions.
- */
-
-static inline unsigned short scb_status(struct net_device *dev)
-{
-	return inw(dev->base_addr + 0xc008);
-}
-
-static inline unsigned short scb_rdcmd(struct net_device *dev)
-{
-	return inw(dev->base_addr + 0xc00a);
-}
-
-static inline void scb_command(struct net_device *dev, unsigned short cmd)
-{
-	outw(cmd, dev->base_addr + 0xc00a);
-}
-
-static inline void scb_wrcbl(struct net_device *dev, unsigned short val)
-{
-	outw(val, dev->base_addr + 0xc00c);
-}
-
-static inline void scb_wrrfa(struct net_device *dev, unsigned short val)
-{
-	outw(val, dev->base_addr + 0xc00e);
-}
-
-static inline void set_loopback(struct net_device *dev)
-{
-	outb(inb(dev->base_addr + Config) | 2, dev->base_addr + Config);
-}
-
-static inline void clear_loopback(struct net_device *dev)
-{
-	outb(inb(dev->base_addr + Config) & ~2, dev->base_addr + Config);
-}
-
-static inline unsigned short int SHADOW(short int addr)
-{
-	addr &= 0x1f;
-	if (addr > 0xf) addr += 0x3ff0;
-	return addr + 0x4000;
-}
-
-/*
- * Linux interface
- */
-
-/*
- * checks for presence of EtherExpress card
- */
-
-static int __init do_express_probe(struct net_device *dev)
-{
-	unsigned short *port;
-	static unsigned short ports[] = { 0x240,0x300,0x310,0x270,0x320,0x340,0 };
-	unsigned short ioaddr = dev->base_addr;
-	int dev_irq = dev->irq;
-	int err;
-
-	dev->if_port = 0xff; /* not set */
-
-#ifdef CONFIG_MCA_LEGACY
-	if (MCA_bus) {
-		int slot = 0;
-
-		/*
-		 * Only find one card at a time.  Subsequent calls
-		 * will find others, however, proper multicard MCA
-		 * probing and setup can't be done with the
-		 * old-style Space.c init routines.  -- ASF
-		 */
-		while (slot != MCA_NOTFOUND) {
-			int pos0, pos1;
-
-			slot = mca_find_unused_adapter(0x628B, slot);
-			if (slot == MCA_NOTFOUND)
-				break;
-
-			pos0 = mca_read_stored_pos(slot, 2);
-			pos1 = mca_read_stored_pos(slot, 3);
-			ioaddr = mca_iomap[pos1&0xf];
-
-			dev->irq = mca_irqmap[(pos1>>4)&0x7];
-
-			/*
-			 * XXX: Transceiver selection is done
-			 * differently on the MCA version.
-			 * How to get it to select something
-			 * other than external/AUI is currently
-			 * unknown.  This code is just for looks. -- ASF
-			 */
-			if ((pos0 & 0x7) == 0x1)
-				dev->if_port = AUI;
-			else if ((pos0 & 0x7) == 0x5) {
-				if (pos1 & 0x80)
-					dev->if_port = BNC;
-				else
-					dev->if_port = TPE;
-			}
-
-			mca_set_adapter_name(slot, "Intel EtherExpress 16 MCA");
-			mca_set_adapter_procfn(slot, NULL, dev);
-			mca_mark_as_used(slot);
-
-			break;
-		}
-	}
-#endif
-	if (ioaddr&0xfe00) {
-		if (!request_region(ioaddr, EEXP_IO_EXTENT, "EtherExpress"))
-			return -EBUSY;
-		err = eexp_hw_probe(dev,ioaddr);
-		release_region(ioaddr, EEXP_IO_EXTENT);
-		return err;
-	} else if (ioaddr)
-		return -ENXIO;
-
-	for (port=&ports[0] ; *port ; port++ )
-	{
-		unsigned short sum = 0;
-		int i;
-		if (!request_region(*port, EEXP_IO_EXTENT, "EtherExpress"))
-			continue;
-		for ( i=0 ; i<4 ; i++ )
-		{
-			unsigned short t;
-			t = inb(*port + ID_PORT);
-			sum |= (t>>4) << ((t & 0x03)<<2);
-		}
-		if (sum==0xbaba && !eexp_hw_probe(dev,*port)) {
-			release_region(*port, EEXP_IO_EXTENT);
-			return 0;
-		}
-		release_region(*port, EEXP_IO_EXTENT);
-		dev->irq = dev_irq;
-	}
-	return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init express_probe(int unit)
-{
-	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
-	int err;
-
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	sprintf(dev->name, "eth%d", unit);
-	netdev_boot_setup_check(dev);
-
-	err = do_express_probe(dev);
-	if (!err)
-		return dev;
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-#endif
-
-/*
- * open and initialize the adapter, ready for use
- */
-
-static int eexp_open(struct net_device *dev)
-{
-	int ret;
-	unsigned short ioaddr = dev->base_addr;
-	struct net_local *lp = netdev_priv(dev);
-
-#if NET_DEBUG > 6
-	printk(KERN_DEBUG "%s: eexp_open()\n", dev->name);
-#endif
-
-	if (!dev->irq || !irqrmap[dev->irq])
-		return -ENXIO;
-
-	ret = request_irq(dev->irq, eexp_irq, 0, dev->name, dev);
-	if (ret)
-		return ret;
-
-	if (!request_region(ioaddr, EEXP_IO_EXTENT, "EtherExpress")) {
-		printk(KERN_WARNING "EtherExpress io port %x, is busy.\n"
-			, ioaddr);
-		goto err_out1;
-	}
-	if (!request_region(ioaddr+0x4000, EEXP_IO_EXTENT, "EtherExpress shadow")) {
-		printk(KERN_WARNING "EtherExpress io port %x, is busy.\n"
-			, ioaddr+0x4000);
-		goto err_out2;
-	}
-	if (!request_region(ioaddr+0x8000, EEXP_IO_EXTENT, "EtherExpress shadow")) {
-		printk(KERN_WARNING "EtherExpress io port %x, is busy.\n"
-			, ioaddr+0x8000);
-		goto err_out3;
-	}
-	if (!request_region(ioaddr+0xc000, EEXP_IO_EXTENT, "EtherExpress shadow")) {
-		printk(KERN_WARNING "EtherExpress io port %x, is busy.\n"
-			, ioaddr+0xc000);
-		goto err_out4;
-	}
-
-	if (lp->width) {
-		printk("%s: forcing ASIC to 8-bit mode\n", dev->name);
-		outb(inb(dev->base_addr+Config)&~4, dev->base_addr+Config);
-	}
-
-	eexp_hw_init586(dev);
-	netif_start_queue(dev);
-#if NET_DEBUG > 6
-	printk(KERN_DEBUG "%s: leaving eexp_open()\n", dev->name);
-#endif
-	return 0;
-
-	err_out4:
-		release_region(ioaddr+0x8000, EEXP_IO_EXTENT);
-	err_out3:
-		release_region(ioaddr+0x4000, EEXP_IO_EXTENT);
-	err_out2:
-		release_region(ioaddr, EEXP_IO_EXTENT);
-	err_out1:
-		free_irq(dev->irq, dev);
-		return -EBUSY;
-}
-
-/*
- * close and disable the interface, leaving the 586 in reset.
- */
-
-static int eexp_close(struct net_device *dev)
-{
-	unsigned short ioaddr = dev->base_addr;
-	struct net_local *lp = netdev_priv(dev);
-
-	int irq = dev->irq;
-
-	netif_stop_queue(dev);
-
-	outb(SIRQ_dis|irqrmap[irq],ioaddr+SET_IRQ);
-	lp->started = 0;
-	scb_command(dev, SCB_CUsuspend|SCB_RUsuspend);
-	outb(0,ioaddr+SIGNAL_CA);
-	free_irq(irq,dev);
-	outb(i586_RST,ioaddr+EEPROM_Ctrl);
-	release_region(ioaddr, EEXP_IO_EXTENT);
-	release_region(ioaddr+0x4000, 16);
-	release_region(ioaddr+0x8000, 16);
-	release_region(ioaddr+0xc000, 16);
-
-	return 0;
-}
-
-/*
- * This gets called when a higher level thinks we are broken.  Check that
- * nothing has become jammed in the CU.
- */
-
-static void unstick_cu(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	unsigned short ioaddr = dev->base_addr;
-
-	if (lp->started)
-	{
-		if (time_after(jiffies, dev_trans_start(dev) + HZ/2))
-		{
-			if (lp->tx_link==lp->last_tx_restart)
-			{
-				unsigned short boguscount=200,rsst;
-				printk(KERN_WARNING "%s: Retransmit timed out, status %04x, resetting...\n",
-				       dev->name, scb_status(dev));
-				eexp_hw_txinit(dev);
-				lp->last_tx_restart = 0;
-				scb_wrcbl(dev, lp->tx_link);
-				scb_command(dev, SCB_CUstart);
-				outb(0,ioaddr+SIGNAL_CA);
-				while (!SCB_complete(rsst=scb_status(dev)))
-				{
-					if (!--boguscount)
-					{
-						boguscount=200;
-						printk(KERN_WARNING "%s: Reset timed out status %04x, retrying...\n",
-						       dev->name,rsst);
-						scb_wrcbl(dev, lp->tx_link);
-						scb_command(dev, SCB_CUstart);
-						outb(0,ioaddr+SIGNAL_CA);
-					}
-				}
-				netif_wake_queue(dev);
-			}
-			else
-			{
-				unsigned short status = scb_status(dev);
-				if (SCB_CUdead(status))
-				{
-					unsigned short txstatus = eexp_hw_lasttxstat(dev);
-					printk(KERN_WARNING "%s: Transmit timed out, CU not active status %04x %04x, restarting...\n",
-					       dev->name, status, txstatus);
-					eexp_hw_txrestart(dev);
-				}
-				else
-				{
-					unsigned short txstatus = eexp_hw_lasttxstat(dev);
-					if (netif_queue_stopped(dev) && !txstatus)
-					{
-						printk(KERN_WARNING "%s: CU wedged, status %04x %04x, resetting...\n",
-						       dev->name,status,txstatus);
-						eexp_hw_init586(dev);
-						netif_wake_queue(dev);
-					}
-					else
-					{
-						printk(KERN_WARNING "%s: transmit timed out\n", dev->name);
-					}
-				}
-			}
-		}
-	}
-	else
-	{
-		if (time_after(jiffies, lp->init_time + 10))
-		{
-			unsigned short status = scb_status(dev);
-			printk(KERN_WARNING "%s: i82586 startup timed out, status %04x, resetting...\n",
-			       dev->name, status);
-			eexp_hw_init586(dev);
-			netif_wake_queue(dev);
-		}
-	}
-}
-
-static void eexp_timeout(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-#ifdef CONFIG_SMP
-	unsigned long flags;
-#endif
-	int status;
-
-	disable_irq(dev->irq);
-
-	/*
-	 *	Best would be to use synchronize_irq(); spin_lock() here
-	 *	lets make it work first..
-	 */
-
-#ifdef CONFIG_SMP
-	spin_lock_irqsave(&lp->lock, flags);
-#endif
-
-	status = scb_status(dev);
-	unstick_cu(dev);
-	printk(KERN_INFO "%s: transmit timed out, %s?\n", dev->name,
-	       (SCB_complete(status)?"lost interrupt":
-		"board on fire"));
-	dev->stats.tx_errors++;
-	lp->last_tx = jiffies;
-	if (!SCB_complete(status)) {
-		scb_command(dev, SCB_CUabort);
-		outb(0,dev->base_addr+SIGNAL_CA);
-	}
-	netif_wake_queue(dev);
-#ifdef CONFIG_SMP
-	spin_unlock_irqrestore(&lp->lock, flags);
-#endif
-}
-
-/*
- * Called to transmit a packet, or to allow us to right ourselves
- * if the kernel thinks we've died.
- */
-static netdev_tx_t eexp_xmit(struct sk_buff *buf, struct net_device *dev)
-{
-	short length = buf->len;
-#ifdef CONFIG_SMP
-	struct net_local *lp = netdev_priv(dev);
-	unsigned long flags;
-#endif
-
-#if NET_DEBUG > 6
-	printk(KERN_DEBUG "%s: eexp_xmit()\n", dev->name);
-#endif
-
-	if (buf->len < ETH_ZLEN) {
-		if (skb_padto(buf, ETH_ZLEN))
-			return NETDEV_TX_OK;
-		length = ETH_ZLEN;
-	}
-
-	disable_irq(dev->irq);
-
-	/*
-	 *	Best would be to use synchronize_irq(); spin_lock() here
-	 *	lets make it work first..
-	 */
-
-#ifdef CONFIG_SMP
-	spin_lock_irqsave(&lp->lock, flags);
-#endif
-
-	{
-		unsigned short *data = (unsigned short *)buf->data;
-
-		dev->stats.tx_bytes += length;
-
-	        eexp_hw_tx_pio(dev,data,length);
-	}
-	dev_kfree_skb(buf);
-#ifdef CONFIG_SMP
-	spin_unlock_irqrestore(&lp->lock, flags);
-#endif
-	enable_irq(dev->irq);
-	return NETDEV_TX_OK;
-}
-
-/*
- * Handle an EtherExpress interrupt
- * If we've finished initializing, start the RU and CU up.
- * If we've already started, reap tx buffers, handle any received packets,
- * check to make sure we've not become wedged.
- */
-
-static unsigned short eexp_start_irq(struct net_device *dev,
-				     unsigned short status)
-{
-	unsigned short ack_cmd = SCB_ack(status);
-	struct net_local *lp = netdev_priv(dev);
-	unsigned short ioaddr = dev->base_addr;
-	if ((dev->flags & IFF_UP) && !(lp->started & STARTED_CU)) {
-		short diag_status, tdr_status;
-		while (SCB_CUstat(status)==2)
-			status = scb_status(dev);
-#if NET_DEBUG > 4
-		printk("%s: CU went non-active (status %04x)\n",
-		       dev->name, status);
-#endif
-
-		outw(CONF_DIAG_RESULT & ~31, ioaddr + SM_PTR);
-		diag_status = inw(ioaddr + SHADOW(CONF_DIAG_RESULT));
-		if (diag_status & 1<<11) {
-			printk(KERN_WARNING "%s: 82586 failed self-test\n",
-			       dev->name);
-		} else if (!(diag_status & 1<<13)) {
-			printk(KERN_WARNING "%s: 82586 self-test failed to complete\n", dev->name);
-		}
-
-		outw(CONF_TDR_RESULT & ~31, ioaddr + SM_PTR);
-		tdr_status = inw(ioaddr + SHADOW(CONF_TDR_RESULT));
-		if (tdr_status & (TDR_SHORT|TDR_OPEN)) {
-			printk(KERN_WARNING "%s: TDR reports cable %s at %d tick%s\n", dev->name, (tdr_status & TDR_SHORT)?"short":"broken", tdr_status & TDR_TIME, ((tdr_status & TDR_TIME) != 1) ? "s" : "");
-		}
-		else if (tdr_status & TDR_XCVRPROBLEM) {
-			printk(KERN_WARNING "%s: TDR reports transceiver problem\n", dev->name);
-		}
-		else if (tdr_status & TDR_LINKOK) {
-#if NET_DEBUG > 4
-			printk(KERN_DEBUG "%s: TDR reports link OK\n", dev->name);
-#endif
-		} else {
-			printk("%s: TDR is ga-ga (status %04x)\n", dev->name,
-			       tdr_status);
-		}
-
-		lp->started |= STARTED_CU;
-		scb_wrcbl(dev, lp->tx_link);
-		/* if the RU isn't running, start it now */
-		if (!(lp->started & STARTED_RU)) {
-			ack_cmd |= SCB_RUstart;
-			scb_wrrfa(dev, lp->rx_buf_start);
-			lp->rx_ptr = lp->rx_buf_start;
-			lp->started |= STARTED_RU;
-		}
-		ack_cmd |= SCB_CUstart | 0x2000;
-	}
-
-	if ((dev->flags & IFF_UP) && !(lp->started & STARTED_RU) && SCB_RUstat(status)==4)
-		lp->started|=STARTED_RU;
-
-	return ack_cmd;
-}
-
-static void eexp_cmd_clear(struct net_device *dev)
-{
-	unsigned long int oldtime = jiffies;
-	while (scb_rdcmd(dev) && (time_before(jiffies, oldtime + 10)));
-	if (scb_rdcmd(dev)) {
-		printk("%s: command didn't clear\n", dev->name);
-	}
-}
-
-static irqreturn_t eexp_irq(int dummy, void *dev_info)
-{
-	struct net_device *dev = dev_info;
-	struct net_local *lp;
-	unsigned short ioaddr,status,ack_cmd;
-	unsigned short old_read_ptr, old_write_ptr;
-
-	lp = netdev_priv(dev);
-	ioaddr = dev->base_addr;
-
-	spin_lock(&lp->lock);
-
-	old_read_ptr = inw(ioaddr+READ_PTR);
-	old_write_ptr = inw(ioaddr+WRITE_PTR);
-
-	outb(SIRQ_dis|irqrmap[dev->irq], ioaddr+SET_IRQ);
-
-	status = scb_status(dev);
-
-#if NET_DEBUG > 4
-	printk(KERN_DEBUG "%s: interrupt (status %x)\n", dev->name, status);
-#endif
-
-	if (lp->started == (STARTED_CU | STARTED_RU)) {
-
-		do {
-			eexp_cmd_clear(dev);
-
-			ack_cmd = SCB_ack(status);
-			scb_command(dev, ack_cmd);
-			outb(0,ioaddr+SIGNAL_CA);
-
-			eexp_cmd_clear(dev);
-
-			if (SCB_complete(status)) {
-				if (!eexp_hw_lasttxstat(dev)) {
-					printk("%s: tx interrupt but no status\n", dev->name);
-				}
-			}
-
-			if (SCB_rxdframe(status))
-				eexp_hw_rx_pio(dev);
-
-			status = scb_status(dev);
-		} while (status & 0xc000);
-
-		if (SCB_RUdead(status))
-		{
-			printk(KERN_WARNING "%s: RU stopped: status %04x\n",
-			       dev->name,status);
-#if 0
-			printk(KERN_WARNING "%s: cur_rfd=%04x, cur_rbd=%04x\n", dev->name, lp->cur_rfd, lp->cur_rbd);
-			outw(lp->cur_rfd, ioaddr+READ_PTR);
-			printk(KERN_WARNING "%s: [%04x]\n", dev->name, inw(ioaddr+DATAPORT));
-			outw(lp->cur_rfd+6, ioaddr+READ_PTR);
-			printk(KERN_WARNING "%s: rbd is %04x\n", dev->name, rbd= inw(ioaddr+DATAPORT));
-			outw(rbd, ioaddr+READ_PTR);
-			printk(KERN_WARNING "%s: [%04x %04x] ", dev->name, inw(ioaddr+DATAPORT), inw(ioaddr+DATAPORT));
-			outw(rbd+8, ioaddr+READ_PTR);
-			printk("[%04x]\n", inw(ioaddr+DATAPORT));
-#endif
-			dev->stats.rx_errors++;
-#if 1
-		        eexp_hw_rxinit(dev);
-#else
-			lp->cur_rfd = lp->first_rfd;
-#endif
-			scb_wrrfa(dev, lp->rx_buf_start);
-			scb_command(dev, SCB_RUstart);
-			outb(0,ioaddr+SIGNAL_CA);
-		}
-	} else {
-		if (status & 0x8000)
-			ack_cmd = eexp_start_irq(dev, status);
-		else
-			ack_cmd = SCB_ack(status);
-		scb_command(dev, ack_cmd);
-		outb(0,ioaddr+SIGNAL_CA);
-	}
-
-	eexp_cmd_clear(dev);
-
-	outb(SIRQ_en|irqrmap[dev->irq], ioaddr+SET_IRQ);
-
-#if NET_DEBUG > 6
-	printk("%s: leaving eexp_irq()\n", dev->name);
-#endif
-	outw(old_read_ptr, ioaddr+READ_PTR);
-	outw(old_write_ptr, ioaddr+WRITE_PTR);
-
-	spin_unlock(&lp->lock);
-	return IRQ_HANDLED;
-}
-
-/*
- * Hardware access functions
- */
-
-/*
- * Set the cable type to use.
- */
-
-static void eexp_hw_set_interface(struct net_device *dev)
-{
-	unsigned char oldval = inb(dev->base_addr + 0x300e);
-	oldval &= ~0x82;
-	switch (dev->if_port) {
-	case TPE:
-		oldval |= 0x2;
-	case BNC:
-		oldval |= 0x80;
-		break;
-	}
-	outb(oldval, dev->base_addr+0x300e);
-	mdelay(20);
-}
-
-/*
- * Check all the receive buffers, and hand any received packets
- * to the upper levels. Basic sanity check on each frame
- * descriptor, though we don't bother trying to fix broken ones.
- */
-
-static void eexp_hw_rx_pio(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	unsigned short rx_block = lp->rx_ptr;
-	unsigned short boguscount = lp->num_rx_bufs;
-	unsigned short ioaddr = dev->base_addr;
-	unsigned short status;
-
-#if NET_DEBUG > 6
-	printk(KERN_DEBUG "%s: eexp_hw_rx()\n", dev->name);
-#endif
-
- 	do {
- 		unsigned short rfd_cmd, rx_next, pbuf, pkt_len;
-
-		outw(rx_block, ioaddr + READ_PTR);
-		status = inw(ioaddr + DATAPORT);
-
-		if (FD_Done(status))
-		{
-			rfd_cmd = inw(ioaddr + DATAPORT);
-			rx_next = inw(ioaddr + DATAPORT);
-			pbuf = inw(ioaddr + DATAPORT);
-
-			outw(pbuf, ioaddr + READ_PTR);
-			pkt_len = inw(ioaddr + DATAPORT);
-
-			if (rfd_cmd!=0x0000)
-  			{
-				printk(KERN_WARNING "%s: rfd_cmd not zero:0x%04x\n",
-				       dev->name, rfd_cmd);
-				continue;
-			}
-			else if (pbuf!=rx_block+0x16)
-			{
-				printk(KERN_WARNING "%s: rfd and rbd out of sync 0x%04x 0x%04x\n",
-				       dev->name, rx_block+0x16, pbuf);
-				continue;
-			}
-			else if ((pkt_len & 0xc000)!=0xc000)
-			{
-				printk(KERN_WARNING "%s: EOF or F not set on received buffer (%04x)\n",
-				       dev->name, pkt_len & 0xc000);
-  				continue;
-  			}
-  			else if (!FD_OK(status))
-			{
-				dev->stats.rx_errors++;
-				if (FD_CRC(status))
-					dev->stats.rx_crc_errors++;
-				if (FD_Align(status))
-					dev->stats.rx_frame_errors++;
-				if (FD_Resrc(status))
-					dev->stats.rx_fifo_errors++;
-				if (FD_DMA(status))
-					dev->stats.rx_over_errors++;
-				if (FD_Short(status))
-					dev->stats.rx_length_errors++;
-			}
-			else
-			{
-				struct sk_buff *skb;
-				pkt_len &= 0x3fff;
-				skb = dev_alloc_skb(pkt_len+16);
-				if (skb == NULL)
-				{
-					printk(KERN_WARNING "%s: Memory squeeze, dropping packet\n",dev->name);
-					dev->stats.rx_dropped++;
-					break;
-				}
-				skb_reserve(skb, 2);
-				outw(pbuf+10, ioaddr+READ_PTR);
-			        insw(ioaddr+DATAPORT, skb_put(skb,pkt_len),(pkt_len+1)>>1);
-				skb->protocol = eth_type_trans(skb,dev);
-				netif_rx(skb);
-				dev->stats.rx_packets++;
-				dev->stats.rx_bytes += pkt_len;
-			}
-			outw(rx_block, ioaddr+WRITE_PTR);
-			outw(0, ioaddr+DATAPORT);
-			outw(0, ioaddr+DATAPORT);
-			rx_block = rx_next;
-		}
-	} while (FD_Done(status) && boguscount--);
-	lp->rx_ptr = rx_block;
-}
-
-/*
- * Hand a packet to the card for transmission
- * If we get here, we MUST have already checked
- * to make sure there is room in the transmit
- * buffer region.
- */
-
-static void eexp_hw_tx_pio(struct net_device *dev, unsigned short *buf,
-		       unsigned short len)
-{
-	struct net_local *lp = netdev_priv(dev);
-	unsigned short ioaddr = dev->base_addr;
-
-	if (LOCKUP16 || lp->width) {
-		/* Stop the CU so that there is no chance that it
-		   jumps off to a bogus address while we are writing the
-		   pointer to the next transmit packet in 8-bit mode --
-		   this eliminates the "CU wedged" errors in 8-bit mode.
-		   (Zoltan Szilagyi 10-12-96) */
-		scb_command(dev, SCB_CUsuspend);
-		outw(0xFFFF, ioaddr+SIGNAL_CA);
-	}
-
- 	outw(lp->tx_head, ioaddr + WRITE_PTR);
-
-	outw(0x0000, ioaddr + DATAPORT);
-        outw(Cmd_INT|Cmd_Xmit, ioaddr + DATAPORT);
-	outw(lp->tx_head+0x08, ioaddr + DATAPORT);
-	outw(lp->tx_head+0x0e, ioaddr + DATAPORT);
-
-	outw(0x0000, ioaddr + DATAPORT);
-	outw(0x0000, ioaddr + DATAPORT);
-	outw(lp->tx_head+0x08, ioaddr + DATAPORT);
-
-	outw(0x8000|len, ioaddr + DATAPORT);
-	outw(-1, ioaddr + DATAPORT);
-	outw(lp->tx_head+0x16, ioaddr + DATAPORT);
-	outw(0, ioaddr + DATAPORT);
-
-	outsw(ioaddr + DATAPORT, buf, (len+1)>>1);
-
-	outw(lp->tx_tail+0xc, ioaddr + WRITE_PTR);
-	outw(lp->tx_head, ioaddr + DATAPORT);
-
-	dev->trans_start = jiffies;
-	lp->tx_tail = lp->tx_head;
-	if (lp->tx_head==TX_BUF_START+((lp->num_tx_bufs-1)*TX_BUF_SIZE))
-		lp->tx_head = TX_BUF_START;
-	else
-		lp->tx_head += TX_BUF_SIZE;
-	if (lp->tx_head != lp->tx_reap)
-		netif_wake_queue(dev);
-
-	if (LOCKUP16 || lp->width) {
-		/* Restart the CU so that the packet can actually
-		   be transmitted. (Zoltan Szilagyi 10-12-96) */
-		scb_command(dev, SCB_CUresume);
-		outw(0xFFFF, ioaddr+SIGNAL_CA);
-	}
-
-	dev->stats.tx_packets++;
-	lp->last_tx = jiffies;
-}
-
-static const struct net_device_ops eexp_netdev_ops = {
-	.ndo_open 		= eexp_open,
-	.ndo_stop 		= eexp_close,
-	.ndo_start_xmit		= eexp_xmit,
-	.ndo_set_multicast_list = eexp_set_multicast,
-	.ndo_tx_timeout		= eexp_timeout,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-/*
- * Sanity check the suspected EtherExpress card
- * Read hardware address, reset card, size memory and initialize buffer
- * memory pointers. These are held in netdev_priv(), in case someone has more
- * than one card in a machine.
- */
-
-static int __init eexp_hw_probe(struct net_device *dev, unsigned short ioaddr)
-{
-	unsigned short hw_addr[3];
-	unsigned char buswidth;
-	unsigned int memory_size;
-	int i;
-	unsigned short xsum = 0;
-	struct net_local *lp = netdev_priv(dev);
-
-	printk("%s: EtherExpress 16 at %#x ",dev->name,ioaddr);
-
-	outb(ASIC_RST, ioaddr+EEPROM_Ctrl);
-	outb(0, ioaddr+EEPROM_Ctrl);
-	udelay(500);
-	outb(i586_RST, ioaddr+EEPROM_Ctrl);
-
-	hw_addr[0] = eexp_hw_readeeprom(ioaddr,2);
-	hw_addr[1] = eexp_hw_readeeprom(ioaddr,3);
-	hw_addr[2] = eexp_hw_readeeprom(ioaddr,4);
-
-	/* Standard Address or Compaq LTE Address */
-	if (!((hw_addr[2]==0x00aa && ((hw_addr[1] & 0xff00)==0x0000)) ||
-	      (hw_addr[2]==0x0080 && ((hw_addr[1] & 0xff00)==0x5F00))))
-	{
-		printk(" rejected: invalid address %04x%04x%04x\n",
-			hw_addr[2],hw_addr[1],hw_addr[0]);
-		return -ENODEV;
-	}
-
-	/* Calculate the EEPROM checksum.  Carry on anyway if it's bad,
-	 * though.
-	 */
-	for (i = 0; i < 64; i++)
-		xsum += eexp_hw_readeeprom(ioaddr, i);
-	if (xsum != 0xbaba)
-		printk(" (bad EEPROM xsum 0x%02x)", xsum);
-
-	dev->base_addr = ioaddr;
-	for ( i=0 ; i<6 ; i++ )
-		dev->dev_addr[i] = ((unsigned char *)hw_addr)[5-i];
-
-	{
-		static const char irqmap[] = { 0, 9, 3, 4, 5, 10, 11, 0 };
-		unsigned short setupval = eexp_hw_readeeprom(ioaddr,0);
-
-		/* Use the IRQ from EEPROM if none was given */
-		if (!dev->irq)
-			dev->irq = irqmap[setupval>>13];
-
-		if (dev->if_port == 0xff) {
-			dev->if_port = !(setupval & 0x1000) ? AUI :
-				eexp_hw_readeeprom(ioaddr,5) & 0x1 ? TPE : BNC;
-		}
-
-		buswidth = !((setupval & 0x400) >> 10);
-	}
-
-	memset(lp, 0, sizeof(struct net_local));
-	spin_lock_init(&lp->lock);
-
- 	printk("(IRQ %d, %s connector, %d-bit bus", dev->irq,
- 	       eexp_ifmap[dev->if_port], buswidth?8:16);
-
-	if (!request_region(dev->base_addr + 0x300e, 1, "EtherExpress"))
-		return -EBUSY;
-
- 	eexp_hw_set_interface(dev);
-
-	release_region(dev->base_addr + 0x300e, 1);
-
-	/* Find out how much RAM we have on the card */
-	outw(0, dev->base_addr + WRITE_PTR);
-	for (i = 0; i < 32768; i++)
-		outw(0, dev->base_addr + DATAPORT);
-
-        for (memory_size = 0; memory_size < 64; memory_size++)
-	{
-		outw(memory_size<<10, dev->base_addr + READ_PTR);
-		if (inw(dev->base_addr+DATAPORT))
-			break;
-		outw(memory_size<<10, dev->base_addr + WRITE_PTR);
-		outw(memory_size | 0x5000, dev->base_addr+DATAPORT);
-		outw(memory_size<<10, dev->base_addr + READ_PTR);
-		if (inw(dev->base_addr+DATAPORT) != (memory_size | 0x5000))
-			break;
-	}
-
-	/* Sort out the number of buffers.  We may have 16, 32, 48 or 64k
-	 * of RAM to play with.
-	 */
-	lp->num_tx_bufs = 4;
-	lp->rx_buf_end = 0x3ff6;
-	switch (memory_size)
-	{
-	case 64:
-		lp->rx_buf_end += 0x4000;
-	case 48:
-		lp->num_tx_bufs += 4;
-		lp->rx_buf_end += 0x4000;
-	case 32:
-		lp->rx_buf_end += 0x4000;
-	case 16:
-		printk(", %dk RAM)\n", memory_size);
-		break;
-	default:
-		printk(") bad memory size (%dk).\n", memory_size);
-		return -ENODEV;
-		break;
-	}
-
-	lp->rx_buf_start = TX_BUF_START + (lp->num_tx_bufs*TX_BUF_SIZE);
-	lp->width = buswidth;
-
-	dev->netdev_ops = &eexp_netdev_ops;
-	dev->watchdog_timeo = 2*HZ;
-
-	return register_netdev(dev);
-}
-
-/*
- * Read a word from the EtherExpress on-board serial EEPROM.
- * The EEPROM contains 64 words of 16 bits.
- */
-static unsigned short __init eexp_hw_readeeprom(unsigned short ioaddr,
-						    unsigned char location)
-{
-	unsigned short cmd = 0x180|(location&0x7f);
-	unsigned short rval = 0,wval = EC_CS|i586_RST;
-	int i;
-
-	outb(EC_CS|i586_RST,ioaddr+EEPROM_Ctrl);
-	for (i=0x100 ; i ; i>>=1 )
-	{
-		if (cmd&i)
-			wval |= EC_Wr;
-		else
-			wval &= ~EC_Wr;
-
-		outb(wval,ioaddr+EEPROM_Ctrl);
-		outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl);
-		eeprom_delay();
-		outb(wval,ioaddr+EEPROM_Ctrl);
-		eeprom_delay();
-	}
-	wval &= ~EC_Wr;
-	outb(wval,ioaddr+EEPROM_Ctrl);
-	for (i=0x8000 ; i ; i>>=1 )
-	{
-		outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl);
-		eeprom_delay();
-		if (inb(ioaddr+EEPROM_Ctrl)&EC_Rd)
-			rval |= i;
-		outb(wval,ioaddr+EEPROM_Ctrl);
-		eeprom_delay();
-	}
-	wval &= ~EC_CS;
-	outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl);
-	eeprom_delay();
-	outb(wval,ioaddr+EEPROM_Ctrl);
-	eeprom_delay();
-	return rval;
-}
-
-/*
- * Reap tx buffers and return last transmit status.
- * if ==0 then either:
- *    a) we're not transmitting anything, so why are we here?
- *    b) we've died.
- * otherwise, Stat_Busy(return) means we've still got some packets
- * to transmit, Stat_Done(return) means our buffers should be empty
- * again
- */
-
-static unsigned short eexp_hw_lasttxstat(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	unsigned short tx_block = lp->tx_reap;
-	unsigned short status;
-
-	if (!netif_queue_stopped(dev) && lp->tx_head==lp->tx_reap)
-		return 0x0000;
-
-	do
-	{
-		outw(tx_block & ~31, dev->base_addr + SM_PTR);
-		status = inw(dev->base_addr + SHADOW(tx_block));
-		if (!Stat_Done(status))
-		{
-			lp->tx_link = tx_block;
-			return status;
-		}
-		else
-		{
-			lp->last_tx_restart = 0;
-			dev->stats.collisions += Stat_NoColl(status);
-			if (!Stat_OK(status))
-			{
-				char *whatsup = NULL;
-				dev->stats.tx_errors++;
-  				if (Stat_Abort(status))
-					dev->stats.tx_aborted_errors++;
-				if (Stat_TNoCar(status)) {
-					whatsup = "aborted, no carrier";
-					dev->stats.tx_carrier_errors++;
-				}
-				if (Stat_TNoCTS(status)) {
-					whatsup = "aborted, lost CTS";
-					dev->stats.tx_carrier_errors++;
-				}
-				if (Stat_TNoDMA(status)) {
-					whatsup = "FIFO underran";
-					dev->stats.tx_fifo_errors++;
-				}
-				if (Stat_TXColl(status)) {
-					whatsup = "aborted, too many collisions";
-					dev->stats.tx_aborted_errors++;
-				}
-				if (whatsup)
-					printk(KERN_INFO "%s: transmit %s\n",
-					       dev->name, whatsup);
-			}
-			else
-				dev->stats.tx_packets++;
-		}
-		if (tx_block == TX_BUF_START+((lp->num_tx_bufs-1)*TX_BUF_SIZE))
-			lp->tx_reap = tx_block = TX_BUF_START;
-		else
-			lp->tx_reap = tx_block += TX_BUF_SIZE;
-		netif_wake_queue(dev);
-	}
-	while (lp->tx_reap != lp->tx_head);
-
-	lp->tx_link = lp->tx_tail + 0x08;
-
-	return status;
-}
-
-/*
- * This should never happen. It is called when some higher routine detects
- * that the CU has stopped, to try to restart it from the last packet we knew
- * we were working on, or the idle loop if we had finished for the time.
- */
-
-static void eexp_hw_txrestart(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	unsigned short ioaddr = dev->base_addr;
-
-	lp->last_tx_restart = lp->tx_link;
-	scb_wrcbl(dev, lp->tx_link);
-	scb_command(dev, SCB_CUstart);
-	outb(0,ioaddr+SIGNAL_CA);
-
-	{
-		unsigned short boguscount=50,failcount=5;
-		while (!scb_status(dev))
-		{
-			if (!--boguscount)
-			{
-				if (--failcount)
-				{
-					printk(KERN_WARNING "%s: CU start timed out, status %04x, cmd %04x\n", dev->name, scb_status(dev), scb_rdcmd(dev));
-				        scb_wrcbl(dev, lp->tx_link);
-					scb_command(dev, SCB_CUstart);
-					outb(0,ioaddr+SIGNAL_CA);
-					boguscount = 100;
-				}
-				else
-				{
-					printk(KERN_WARNING "%s: Failed to restart CU, resetting board...\n",dev->name);
-					eexp_hw_init586(dev);
-					netif_wake_queue(dev);
-					return;
-				}
-			}
-		}
-	}
-}
-
-/*
- * Writes down the list of transmit buffers into card memory.  Each
- * entry consists of an 82586 transmit command, followed by a jump
- * pointing to itself.  When we want to transmit a packet, we write
- * the data into the appropriate transmit buffer and then modify the
- * preceding jump to point at the new transmit command.  This means that
- * the 586 command unit is continuously active.
- */
-
-static void eexp_hw_txinit(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	unsigned short tx_block = TX_BUF_START;
-	unsigned short curtbuf;
-	unsigned short ioaddr = dev->base_addr;
-
-	for ( curtbuf=0 ; curtbuf<lp->num_tx_bufs ; curtbuf++ )
-	{
-		outw(tx_block, ioaddr + WRITE_PTR);
-
-	        outw(0x0000, ioaddr + DATAPORT);
-		outw(Cmd_INT|Cmd_Xmit, ioaddr + DATAPORT);
-		outw(tx_block+0x08, ioaddr + DATAPORT);
-		outw(tx_block+0x0e, ioaddr + DATAPORT);
-
-		outw(0x0000, ioaddr + DATAPORT);
-		outw(0x0000, ioaddr + DATAPORT);
-		outw(tx_block+0x08, ioaddr + DATAPORT);
-
-		outw(0x8000, ioaddr + DATAPORT);
-		outw(-1, ioaddr + DATAPORT);
-		outw(tx_block+0x16, ioaddr + DATAPORT);
-		outw(0x0000, ioaddr + DATAPORT);
-
-		tx_block += TX_BUF_SIZE;
-	}
-	lp->tx_head = TX_BUF_START;
-	lp->tx_reap = TX_BUF_START;
-	lp->tx_tail = tx_block - TX_BUF_SIZE;
-	lp->tx_link = lp->tx_tail + 0x08;
-	lp->rx_buf_start = tx_block;
-
-}
-
-/*
- * Write the circular list of receive buffer descriptors to card memory.
- * The end of the list isn't marked, which means that the 82586 receive
- * unit will loop until buffers become available (this avoids it giving us
- * "out of resources" messages).
- */
-
-static void eexp_hw_rxinit(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	unsigned short rx_block = lp->rx_buf_start;
-	unsigned short ioaddr = dev->base_addr;
-
-	lp->num_rx_bufs = 0;
-	lp->rx_first = lp->rx_ptr = rx_block;
-	do
-	{
-		lp->num_rx_bufs++;
-
-		outw(rx_block, ioaddr + WRITE_PTR);
-
-		outw(0, ioaddr + DATAPORT);  outw(0, ioaddr+DATAPORT);
-		outw(rx_block + RX_BUF_SIZE, ioaddr+DATAPORT);
-		outw(0xffff, ioaddr+DATAPORT);
-
-		outw(0x0000, ioaddr+DATAPORT);
-		outw(0xdead, ioaddr+DATAPORT);
-		outw(0xdead, ioaddr+DATAPORT);
-		outw(0xdead, ioaddr+DATAPORT);
-		outw(0xdead, ioaddr+DATAPORT);
-		outw(0xdead, ioaddr+DATAPORT);
-		outw(0xdead, ioaddr+DATAPORT);
-
-		outw(0x0000, ioaddr+DATAPORT);
-		outw(rx_block + RX_BUF_SIZE + 0x16, ioaddr+DATAPORT);
-		outw(rx_block + 0x20, ioaddr+DATAPORT);
-		outw(0, ioaddr+DATAPORT);
-		outw(RX_BUF_SIZE-0x20, ioaddr+DATAPORT);
-
-		lp->rx_last = rx_block;
-		rx_block += RX_BUF_SIZE;
-	} while (rx_block <= lp->rx_buf_end-RX_BUF_SIZE);
-
-
-	/* Make first Rx frame descriptor point to first Rx buffer
-           descriptor */
-	outw(lp->rx_first + 6, ioaddr+WRITE_PTR);
-	outw(lp->rx_first + 0x16, ioaddr+DATAPORT);
-
-	/* Close Rx frame descriptor ring */
-  	outw(lp->rx_last + 4, ioaddr+WRITE_PTR);
-  	outw(lp->rx_first, ioaddr+DATAPORT);
-
-	/* Close Rx buffer descriptor ring */
-	outw(lp->rx_last + 0x16 + 2, ioaddr+WRITE_PTR);
-	outw(lp->rx_first + 0x16, ioaddr+DATAPORT);
-
-}
-
-/*
- * Un-reset the 586, and start the configuration sequence. We don't wait for
- * this to finish, but allow the interrupt handler to start the CU and RU for
- * us.  We can't start the receive/transmission system up before we know that
- * the hardware is configured correctly.
- */
-
-static void eexp_hw_init586(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	unsigned short ioaddr = dev->base_addr;
-	int i;
-
-#if NET_DEBUG > 6
-	printk("%s: eexp_hw_init586()\n", dev->name);
-#endif
-
-	lp->started = 0;
-
-	set_loopback(dev);
-
-	outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ);
-
-	/* Download the startup code */
-	outw(lp->rx_buf_end & ~31, ioaddr + SM_PTR);
-	outw(lp->width?0x0001:0x0000, ioaddr + 0x8006);
-	outw(0x0000, ioaddr + 0x8008);
-	outw(0x0000, ioaddr + 0x800a);
-	outw(0x0000, ioaddr + 0x800c);
-	outw(0x0000, ioaddr + 0x800e);
-
-	for (i = 0; i < ARRAY_SIZE(start_code) * 2; i+=32) {
-		int j;
-		outw(i, ioaddr + SM_PTR);
-		for (j = 0; j < 16 && (i+j)/2 < ARRAY_SIZE(start_code); j+=2)
-			outw(start_code[(i+j)/2],
-			     ioaddr+0x4000+j);
-		for (j = 0; j < 16 && (i+j+16)/2 < ARRAY_SIZE(start_code); j+=2)
-			outw(start_code[(i+j+16)/2],
-			     ioaddr+0x8000+j);
-	}
-
-	/* Do we want promiscuous mode or multicast? */
-	outw(CONF_PROMISC & ~31, ioaddr+SM_PTR);
-	i = inw(ioaddr+SHADOW(CONF_PROMISC));
-	outw((dev->flags & IFF_PROMISC)?(i|1):(i & ~1),
-	     ioaddr+SHADOW(CONF_PROMISC));
-	lp->was_promisc = dev->flags & IFF_PROMISC;
-#if 0
-	eexp_setup_filter(dev);
-#endif
-
-	/* Write our hardware address */
-	outw(CONF_HWADDR & ~31, ioaddr+SM_PTR);
-	outw(((unsigned short *)dev->dev_addr)[0], ioaddr+SHADOW(CONF_HWADDR));
-	outw(((unsigned short *)dev->dev_addr)[1],
-	     ioaddr+SHADOW(CONF_HWADDR+2));
-	outw(((unsigned short *)dev->dev_addr)[2],
-	     ioaddr+SHADOW(CONF_HWADDR+4));
-
-	eexp_hw_txinit(dev);
-	eexp_hw_rxinit(dev);
-
-	outb(0,ioaddr+EEPROM_Ctrl);
-	mdelay(5);
-
-	scb_command(dev, 0xf000);
-	outb(0,ioaddr+SIGNAL_CA);
-
-	outw(0, ioaddr+SM_PTR);
-
-	{
-		unsigned short rboguscount=50,rfailcount=5;
-		while (inw(ioaddr+0x4000))
-		{
-			if (!--rboguscount)
-			{
-				printk(KERN_WARNING "%s: i82586 reset timed out, kicking...\n",
-					dev->name);
-				scb_command(dev, 0);
-				outb(0,ioaddr+SIGNAL_CA);
-				rboguscount = 100;
-				if (!--rfailcount)
-				{
-					printk(KERN_WARNING "%s: i82586 not responding, giving up.\n",
-						dev->name);
-					return;
-				}
-			}
-		}
-	}
-
-        scb_wrcbl(dev, CONF_LINK);
-	scb_command(dev, 0xf000|SCB_CUstart);
-	outb(0,ioaddr+SIGNAL_CA);
-
-	{
-		unsigned short iboguscount=50,ifailcount=5;
-		while (!scb_status(dev))
-		{
-			if (!--iboguscount)
-			{
-				if (--ifailcount)
-				{
-					printk(KERN_WARNING "%s: i82586 initialization timed out, status %04x, cmd %04x\n",
-						dev->name, scb_status(dev), scb_rdcmd(dev));
-					scb_wrcbl(dev, CONF_LINK);
-				        scb_command(dev, 0xf000|SCB_CUstart);
-					outb(0,ioaddr+SIGNAL_CA);
-					iboguscount = 100;
-				}
-				else
-				{
-					printk(KERN_WARNING "%s: Failed to initialize i82586, giving up.\n",dev->name);
-					return;
-				}
-			}
-		}
-	}
-
-	clear_loopback(dev);
-	outb(SIRQ_en|irqrmap[dev->irq],ioaddr+SET_IRQ);
-
-	lp->init_time = jiffies;
-#if NET_DEBUG > 6
-        printk("%s: leaving eexp_hw_init586()\n", dev->name);
-#endif
-}
-
-static void eexp_setup_filter(struct net_device *dev)
-{
-	struct netdev_hw_addr *ha;
-	unsigned short ioaddr = dev->base_addr;
-	int count = netdev_mc_count(dev);
-	int i;
-	if (count > 8) {
-		printk(KERN_INFO "%s: too many multicast addresses (%d)\n",
-		       dev->name, count);
-		count = 8;
-	}
-
-	outw(CONF_NR_MULTICAST & ~31, ioaddr+SM_PTR);
-	outw(6*count, ioaddr+SHADOW(CONF_NR_MULTICAST));
-	i = 0;
-	netdev_for_each_mc_addr(ha, dev) {
-		unsigned short *data = (unsigned short *) ha->addr;
-
-		if (i == count)
-			break;
-		outw((CONF_MULTICAST+(6*i)) & ~31, ioaddr+SM_PTR);
-		outw(data[0], ioaddr+SHADOW(CONF_MULTICAST+(6*i)));
-		outw((CONF_MULTICAST+(6*i)+2) & ~31, ioaddr+SM_PTR);
-		outw(data[1], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+2));
-		outw((CONF_MULTICAST+(6*i)+4) & ~31, ioaddr+SM_PTR);
-		outw(data[2], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+4));
-		i++;
-	}
-}
-
-/*
- * Set or clear the multicast filter for this adaptor.
- */
-static void
-eexp_set_multicast(struct net_device *dev)
-{
-        unsigned short ioaddr = dev->base_addr;
-        struct net_local *lp = netdev_priv(dev);
-        int kick = 0, i;
-        if ((dev->flags & IFF_PROMISC) != lp->was_promisc) {
-                outw(CONF_PROMISC & ~31, ioaddr+SM_PTR);
-                i = inw(ioaddr+SHADOW(CONF_PROMISC));
-                outw((dev->flags & IFF_PROMISC)?(i|1):(i & ~1),
-                     ioaddr+SHADOW(CONF_PROMISC));
-                lp->was_promisc = dev->flags & IFF_PROMISC;
-                kick = 1;
-        }
-        if (!(dev->flags & IFF_PROMISC)) {
-                eexp_setup_filter(dev);
-                if (lp->old_mc_count != netdev_mc_count(dev)) {
-                        kick = 1;
-                        lp->old_mc_count = netdev_mc_count(dev);
-                }
-        }
-        if (kick) {
-                unsigned long oj;
-                scb_command(dev, SCB_CUsuspend);
-                outb(0, ioaddr+SIGNAL_CA);
-                outb(0, ioaddr+SIGNAL_CA);
-#if 0
-                printk("%s: waiting for CU to go suspended\n", dev->name);
-#endif
-                oj = jiffies;
-                while ((SCB_CUstat(scb_status(dev)) == 2) &&
-                       (time_before(jiffies, oj + 2000)));
-		if (SCB_CUstat(scb_status(dev)) == 2)
-			printk("%s: warning, CU didn't stop\n", dev->name);
-                lp->started &= ~(STARTED_CU);
-                scb_wrcbl(dev, CONF_LINK);
-                scb_command(dev, SCB_CUstart);
-                outb(0, ioaddr+SIGNAL_CA);
-        }
-}
-
-
-/*
- * MODULE stuff
- */
-
-#ifdef MODULE
-
-#define EEXP_MAX_CARDS     4    /* max number of cards to support */
-
-static struct net_device *dev_eexp[EEXP_MAX_CARDS];
-static int irq[EEXP_MAX_CARDS];
-static int io[EEXP_MAX_CARDS];
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-MODULE_PARM_DESC(io, "EtherExpress 16 I/O base address(es)");
-MODULE_PARM_DESC(irq, "EtherExpress 16 IRQ number(s)");
-MODULE_LICENSE("GPL");
-
-
-/* Ideally the user would give us io=, irq= for every card.  If any parameters
- * are specified, we verify and then use them.  If no parameters are given, we
- * autoprobe for one card only.
- */
-int __init init_module(void)
-{
-	struct net_device *dev;
-	int this_dev, found = 0;
-
-	for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) {
-		dev = alloc_etherdev(sizeof(struct net_local));
-		dev->irq = irq[this_dev];
-		dev->base_addr = io[this_dev];
-		if (io[this_dev] == 0) {
-			if (this_dev)
-				break;
-			printk(KERN_NOTICE "eexpress.c: Module autoprobe not recommended, give io=xx.\n");
-		}
-		if (do_express_probe(dev) == 0) {
-			dev_eexp[this_dev] = dev;
-			found++;
-			continue;
-		}
-		printk(KERN_WARNING "eexpress.c: Failed to register card at 0x%x.\n", io[this_dev]);
-		free_netdev(dev);
-		break;
-	}
-	if (found)
-		return 0;
-	return -ENXIO;
-}
-
-void __exit cleanup_module(void)
-{
-	int this_dev;
-
-	for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) {
-		struct net_device *dev = dev_eexp[this_dev];
-		if (dev) {
-			unregister_netdev(dev);
-			free_netdev(dev);
-		}
-	}
-}
-#endif
-
-/*
- * Local Variables:
- *  c-file-style: "linux"
- *  tab-width: 8
- * End:
- */
diff -druN linux-libre-3.1-gnu/drivers/net/eexpress.h linux-libre-3.2-gnu/drivers/net/eexpress.h
--- linux-libre-3.1-gnu/drivers/net/eexpress.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/eexpress.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,179 +0,0 @@
-/*
- * eexpress.h: Intel EtherExpress16 defines
- */
-
-/*
- * EtherExpress card register addresses
- * as offsets from the base IO region (dev->base_addr)
- */
-
-#define DATAPORT      0x0000
-#define WRITE_PTR     0x0002
-#define READ_PTR      0x0004
-#define SIGNAL_CA     0x0006
-#define SET_IRQ       0x0007
-#define SM_PTR        0x0008
-#define	MEM_Dec	      0x000a
-#define MEM_Ctrl      0x000b
-#define MEM_Page_Ctrl 0x000c
-#define Config        0x000d
-#define EEPROM_Ctrl   0x000e
-#define ID_PORT       0x000f
-#define	MEM_ECtrl     0x000f
-
-/*
- * card register defines
- */
-
-/* SET_IRQ */
-#define SIRQ_en       0x08
-#define SIRQ_dis      0x00
-
-/* EEPROM_Ctrl */
-#define EC_Clk        0x01
-#define EC_CS         0x02
-#define EC_Wr         0x04
-#define EC_Rd         0x08
-#define ASIC_RST      0x40
-#define i586_RST      0x80
-
-#define eeprom_delay() { udelay(40); }
-
-/*
- * i82586 Memory Configuration
- */
-
-/* (System Configuration Pointer) System start up block, read after 586_RST */
-#define SCP_START 0xfff6
-
-/* Intermediate System Configuration Pointer */
-#define ISCP_START 0x0000
-
-/* System Command Block */
-#define SCB_START 0x0008
-
-/* Start of buffer region.  Everything before this is used for control
- * structures and the CU configuration program.  The memory layout is
- * determined in eexp_hw_probe(), once we know how much memory is
- * available on the card.
- */
-
-#define TX_BUF_START 0x0100
-
-#define TX_BUF_SIZE ((24+ETH_FRAME_LEN+31)&~0x1f)
-#define RX_BUF_SIZE ((32+ETH_FRAME_LEN+31)&~0x1f)
-
-/*
- * SCB defines
- */
-
-/* these functions take the SCB status word and test the relevant status bit */
-#define SCB_complete(s) (((s) & 0x8000) != 0)
-#define SCB_rxdframe(s) (((s) & 0x4000) != 0)
-#define SCB_CUdead(s)   (((s) & 0x2000) != 0)
-#define SCB_RUdead(s)   (((s) & 0x1000) != 0)
-#define SCB_ack(s)      ((s) & 0xf000)
-
-/* Command unit status: 0=idle, 1=suspended, 2=active */
-#define SCB_CUstat(s)   (((s)&0x0300)>>8)
-
-/* Receive unit status: 0=idle, 1=suspended, 2=out of resources, 4=ready */
-#define SCB_RUstat(s)   (((s)&0x0070)>>4)
-
-/* SCB commands */
-#define SCB_CUnop       0x0000
-#define SCB_CUstart     0x0100
-#define SCB_CUresume    0x0200
-#define SCB_CUsuspend   0x0300
-#define SCB_CUabort     0x0400
-#define SCB_resetchip   0x0080
-
-#define SCB_RUnop       0x0000
-#define SCB_RUstart     0x0010
-#define SCB_RUresume    0x0020
-#define SCB_RUsuspend   0x0030
-#define SCB_RUabort     0x0040
-
-/*
- * Command block defines
- */
-
-#define Stat_Done(s)    (((s) & 0x8000) != 0)
-#define Stat_Busy(s)    (((s) & 0x4000) != 0)
-#define Stat_OK(s)      (((s) & 0x2000) != 0)
-#define Stat_Abort(s)   (((s) & 0x1000) != 0)
-#define Stat_STFail     (((s) & 0x0800) != 0)
-#define Stat_TNoCar(s)  (((s) & 0x0400) != 0)
-#define Stat_TNoCTS(s)  (((s) & 0x0200) != 0)
-#define Stat_TNoDMA(s)  (((s) & 0x0100) != 0)
-#define Stat_TDefer(s)  (((s) & 0x0080) != 0)
-#define Stat_TColl(s)   (((s) & 0x0040) != 0)
-#define Stat_TXColl(s)  (((s) & 0x0020) != 0)
-#define Stat_NoColl(s)  ((s) & 0x000f)
-
-/* Cmd_END will end AFTER the command if this is the first
- * command block after an SCB_CUstart, but BEFORE the command
- * for all subsequent commands. Best strategy is to place
- * Cmd_INT on the last command in the sequence, followed by a
- * dummy Cmd_Nop with Cmd_END after this.
- */
-
-#define Cmd_END     0x8000
-#define Cmd_SUS     0x4000
-#define Cmd_INT     0x2000
-
-#define Cmd_Nop     0x0000
-#define Cmd_SetAddr 0x0001
-#define Cmd_Config  0x0002
-#define Cmd_MCast   0x0003
-#define Cmd_Xmit    0x0004
-#define Cmd_TDR     0x0005
-#define Cmd_Dump    0x0006
-#define Cmd_Diag    0x0007
-
-
-/*
- * Frame Descriptor (Receive block) defines
- */
-
-#define FD_Done(s)  (((s) & 0x8000) != 0)
-#define FD_Busy(s)  (((s) & 0x4000) != 0)
-#define FD_OK(s)    (((s) & 0x2000) != 0)
-
-#define FD_CRC(s)   (((s) & 0x0800) != 0)
-#define FD_Align(s) (((s) & 0x0400) != 0)
-#define FD_Resrc(s) (((s) & 0x0200) != 0)
-#define FD_DMA(s)   (((s) & 0x0100) != 0)
-#define FD_Short(s) (((s) & 0x0080) != 0)
-#define FD_NoEOF(s) (((s) & 0x0040) != 0)
-
-struct rfd_header {
-	volatile unsigned long flags;
-	volatile unsigned short link;
-	volatile unsigned short rbd_offset;
-	volatile unsigned short dstaddr1;
-	volatile unsigned short dstaddr2;
-	volatile unsigned short dstaddr3;
-	volatile unsigned short srcaddr1;
-	volatile unsigned short srcaddr2;
-	volatile unsigned short srcaddr3;
-	volatile unsigned short length;
-
-	/* This is actually a Receive Buffer Descriptor.  The way we
-	 * arrange memory means that an RBD always follows the RFD that
-	 * points to it, so they might as well be in the same structure.
-	 */
-	volatile unsigned short actual_count;
-	volatile unsigned short next_rbd;
-	volatile unsigned short buf_addr1;
-	volatile unsigned short buf_addr2;
-	volatile unsigned short size;
-};
-
-/* Returned data from the Time Domain Reflectometer */
-
-#define TDR_LINKOK       (1<<15)
-#define TDR_XCVRPROBLEM  (1<<14)
-#define TDR_OPEN         (1<<13)
-#define TDR_SHORT        (1<<12)
-#define TDR_TIME         0x7ff
diff -druN linux-libre-3.1-gnu/drivers/net/ehea/ehea_ethtool.c linux-libre-3.2-gnu/drivers/net/ehea/ehea_ethtool.c
--- linux-libre-3.1-gnu/drivers/net/ehea/ehea_ethtool.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/ehea/ehea_ethtool.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,295 +0,0 @@
-/*
- *  linux/drivers/net/ehea/ehea_ethtool.c
- *
- *  eHEA ethernet device driver for IBM eServer System p
- *
- *  (C) Copyright IBM Corp. 2006
- *
- *  Authors:
- *       Christoph Raisch <raisch@de.ibm.com>
- *       Jan-Bernd Themann <themann@de.ibm.com>
- *       Thomas Klein <tklein@de.ibm.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; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "ehea.h"
-#include "ehea_phyp.h"
-
-static int ehea_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	u32 speed;
-	int ret;
-
-	ret = ehea_sense_port_attr(port);
-
-	if (ret)
-		return ret;
-
-	if (netif_carrier_ok(dev)) {
-		switch (port->port_speed) {
-		case EHEA_SPEED_10M:
-			speed = SPEED_10;
-			break;
-		case EHEA_SPEED_100M:
-			speed = SPEED_100;
-			break;
-		case EHEA_SPEED_1G:
-			speed = SPEED_1000;
-			break;
-		case EHEA_SPEED_10G:
-			speed = SPEED_10000;
-			break;
-		default:
-			speed = -1;
-			break; /* BUG */
-		}
-		cmd->duplex = port->full_duplex == 1 ?
-						     DUPLEX_FULL : DUPLEX_HALF;
-	} else {
-		speed = ~0;
-		cmd->duplex = -1;
-	}
-	ethtool_cmd_speed_set(cmd, speed);
-
-	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->autoneg = port->autoneg == 1 ? AUTONEG_ENABLE : AUTONEG_DISABLE;
-
-	return 0;
-}
-
-static int ehea_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	int ret = 0;
-	u32 sp;
-
-	if (cmd->autoneg == AUTONEG_ENABLE) {
-		sp = EHEA_SPEED_AUTONEG;
-		goto doit;
-	}
-
-	switch (cmd->speed) {
-	case SPEED_10:
-		if (cmd->duplex == DUPLEX_FULL)
-			sp = H_SPEED_10M_F;
-		else
-			sp = H_SPEED_10M_H;
-		break;
-
-	case SPEED_100:
-		if (cmd->duplex == DUPLEX_FULL)
-			sp = H_SPEED_100M_F;
-		else
-			sp = H_SPEED_100M_H;
-		break;
-
-	case SPEED_1000:
-		if (cmd->duplex == DUPLEX_FULL)
-			sp = H_SPEED_1G_F;
-		else
-			ret = -EINVAL;
-		break;
-
-	case SPEED_10000:
-		if (cmd->duplex == DUPLEX_FULL)
-			sp = H_SPEED_10G_F;
-		else
-			ret = -EINVAL;
-		break;
-
-	default:
-			ret = -EINVAL;
-		break;
-	}
-
-	if (ret)
-		goto out;
-doit:
-	ret = ehea_set_portspeed(port, sp);
-
-	if (!ret)
-		netdev_info(dev,
-			    "Port speed successfully set: %dMbps %s Duplex\n",
-			    port->port_speed,
-			    port->full_duplex == 1 ? "Full" : "Half");
-out:
-	return ret;
-}
-
-static int ehea_nway_reset(struct net_device *dev)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	int ret;
-
-	ret = ehea_set_portspeed(port, EHEA_SPEED_AUTONEG);
-
-	if (!ret)
-		netdev_info(port->netdev,
-			    "Port speed successfully set: %dMbps %s Duplex\n",
-			    port->port_speed,
-			    port->full_duplex == 1 ? "Full" : "Half");
-	return ret;
-}
-
-static void ehea_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-}
-
-static u32 ehea_get_msglevel(struct net_device *dev)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	return port->msg_enable;
-}
-
-static void ehea_set_msglevel(struct net_device *dev, u32 value)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	port->msg_enable = value;
-}
-
-static char ehea_ethtool_stats_keys[][ETH_GSTRING_LEN] = {
-	{"sig_comp_iv"},
-	{"swqe_refill_th"},
-	{"port resets"},
-	{"Receive errors"},
-	{"TCP cksum errors"},
-	{"IP cksum errors"},
-	{"Frame cksum errors"},
-	{"num SQ stopped"},
-	{"SQ stopped"},
-	{"PR0 free_swqes"},
-	{"PR1 free_swqes"},
-	{"PR2 free_swqes"},
-	{"PR3 free_swqes"},
-	{"PR4 free_swqes"},
-	{"PR5 free_swqes"},
-	{"PR6 free_swqes"},
-	{"PR7 free_swqes"},
-	{"LRO aggregated"},
-	{"LRO flushed"},
-	{"LRO no_desc"},
-};
-
-static void ehea_get_strings(struct net_device *dev, u32 stringset, u8 *data)
-{
-	if (stringset == ETH_SS_STATS) {
-		memcpy(data, &ehea_ethtool_stats_keys,
-		       sizeof(ehea_ethtool_stats_keys));
-	}
-}
-
-static int ehea_get_sset_count(struct net_device *dev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		return ARRAY_SIZE(ehea_ethtool_stats_keys);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void ehea_get_ethtool_stats(struct net_device *dev,
-				     struct ethtool_stats *stats, u64 *data)
-{
-	int i, k, tmp;
-	struct ehea_port *port = netdev_priv(dev);
-
-	for (i = 0; i < ehea_get_sset_count(dev, ETH_SS_STATS); i++)
-		data[i] = 0;
-	i = 0;
-
-	data[i++] = port->sig_comp_iv;
-	data[i++] = port->port_res[0].swqe_refill_th;
-	data[i++] = port->resets;
-
-	for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
-		tmp += port->port_res[k].p_stats.poll_receive_errors;
-	data[i++] = tmp;
-
-	for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
-		tmp += port->port_res[k].p_stats.err_tcp_cksum;
-	data[i++] = tmp;
-
-	for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
-		tmp += port->port_res[k].p_stats.err_ip_cksum;
-	data[i++] = tmp;
-
-	for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
-		tmp += port->port_res[k].p_stats.err_frame_crc;
-	data[i++] = tmp;
-
-	for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
-		tmp += port->port_res[k].p_stats.queue_stopped;
-	data[i++] = tmp;
-
-	for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
-		tmp |= port->port_res[k].queue_stopped;
-	data[i++] = tmp;
-
-	for (k = 0; k < 8; k++)
-		data[i++] = atomic_read(&port->port_res[k].swqe_avail);
-
-	for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
-		tmp |= port->port_res[k].lro_mgr.stats.aggregated;
-	data[i++] = tmp;
-
-	for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
-		tmp |= port->port_res[k].lro_mgr.stats.flushed;
-	data[i++] = tmp;
-
-	for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
-		tmp |= port->port_res[k].lro_mgr.stats.no_desc;
-	data[i++] = tmp;
-
-}
-
-const struct ethtool_ops ehea_ethtool_ops = {
-	.get_settings = ehea_get_settings,
-	.get_drvinfo = ehea_get_drvinfo,
-	.get_msglevel = ehea_get_msglevel,
-	.set_msglevel = ehea_set_msglevel,
-	.get_link = ethtool_op_get_link,
-	.get_strings = ehea_get_strings,
-	.get_sset_count = ehea_get_sset_count,
-	.get_ethtool_stats = ehea_get_ethtool_stats,
-	.set_settings = ehea_set_settings,
-	.nway_reset = ehea_nway_reset,		/* Restart autonegotiation */
-};
-
-void ehea_set_ethtool_ops(struct net_device *netdev)
-{
-	SET_ETHTOOL_OPS(netdev, &ehea_ethtool_ops);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/ehea/ehea.h linux-libre-3.2-gnu/drivers/net/ehea/ehea.h
--- linux-libre-3.1-gnu/drivers/net/ehea/ehea.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/ehea/ehea.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,504 +0,0 @@
-/*
- *  linux/drivers/net/ehea/ehea.h
- *
- *  eHEA ethernet device driver for IBM eServer System p
- *
- *  (C) Copyright IBM Corp. 2006
- *
- *  Authors:
- *       Christoph Raisch <raisch@de.ibm.com>
- *       Jan-Bernd Themann <themann@de.ibm.com>
- *       Thomas Klein <tklein@de.ibm.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; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __EHEA_H__
-#define __EHEA_H__
-
-#include <linux/module.h>
-#include <linux/ethtool.h>
-#include <linux/vmalloc.h>
-#include <linux/if_vlan.h>
-#include <linux/inet_lro.h>
-
-#include <asm/ibmebus.h>
-#include <asm/abs_addr.h>
-#include <asm/io.h>
-
-#define DRV_NAME	"ehea"
-#define DRV_VERSION	"EHEA_0107"
-
-/* eHEA capability flags */
-#define DLPAR_PORT_ADD_REM 1
-#define DLPAR_MEM_ADD      2
-#define DLPAR_MEM_REM      4
-#define EHEA_CAPABILITIES  (DLPAR_PORT_ADD_REM | DLPAR_MEM_ADD | DLPAR_MEM_REM)
-
-#define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
-	| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
-
-#define EHEA_MAX_ENTRIES_RQ1 32767
-#define EHEA_MAX_ENTRIES_RQ2 16383
-#define EHEA_MAX_ENTRIES_RQ3 16383
-#define EHEA_MAX_ENTRIES_SQ  32767
-#define EHEA_MIN_ENTRIES_QP  127
-
-#define EHEA_SMALL_QUEUES
-#define EHEA_NUM_TX_QP 1
-#define EHEA_LRO_MAX_AGGR 64
-
-#ifdef EHEA_SMALL_QUEUES
-#define EHEA_MAX_CQE_COUNT      1023
-#define EHEA_DEF_ENTRIES_SQ     1023
-#define EHEA_DEF_ENTRIES_RQ1    4095
-#define EHEA_DEF_ENTRIES_RQ2    1023
-#define EHEA_DEF_ENTRIES_RQ3    1023
-#else
-#define EHEA_MAX_CQE_COUNT      4080
-#define EHEA_DEF_ENTRIES_SQ     4080
-#define EHEA_DEF_ENTRIES_RQ1    8160
-#define EHEA_DEF_ENTRIES_RQ2    2040
-#define EHEA_DEF_ENTRIES_RQ3    2040
-#endif
-
-#define EHEA_MAX_ENTRIES_EQ 20
-
-#define EHEA_SG_SQ  2
-#define EHEA_SG_RQ1 1
-#define EHEA_SG_RQ2 0
-#define EHEA_SG_RQ3 0
-
-#define EHEA_MAX_PACKET_SIZE    9022	/* for jumbo frames */
-#define EHEA_RQ2_PKT_SIZE       1522
-#define EHEA_L_PKT_SIZE         256	/* low latency */
-
-#define MAX_LRO_DESCRIPTORS 8
-
-/* Send completion signaling */
-
-/* Protection Domain Identifier */
-#define EHEA_PD_ID        0xaabcdeff
-
-#define EHEA_RQ2_THRESHOLD 	   1
-#define EHEA_RQ3_THRESHOLD 	   9	/* use RQ3 threshold of 1522 bytes */
-
-#define EHEA_SPEED_10G         10000
-#define EHEA_SPEED_1G           1000
-#define EHEA_SPEED_100M          100
-#define EHEA_SPEED_10M            10
-#define EHEA_SPEED_AUTONEG         0
-
-/* Broadcast/Multicast registration types */
-#define EHEA_BCMC_SCOPE_ALL	0x08
-#define EHEA_BCMC_SCOPE_SINGLE	0x00
-#define EHEA_BCMC_MULTICAST	0x04
-#define EHEA_BCMC_BROADCAST	0x00
-#define EHEA_BCMC_UNTAGGED	0x02
-#define EHEA_BCMC_TAGGED	0x00
-#define EHEA_BCMC_VLANID_ALL	0x01
-#define EHEA_BCMC_VLANID_SINGLE	0x00
-
-#define EHEA_CACHE_LINE          128
-
-/* Memory Regions */
-#define EHEA_MR_ACC_CTRL       0x00800000
-
-#define EHEA_BUSMAP_START      0x8000000000000000ULL
-#define EHEA_INVAL_ADDR        0xFFFFFFFFFFFFFFFFULL
-#define EHEA_DIR_INDEX_SHIFT 13                   /* 8k Entries in 64k block */
-#define EHEA_TOP_INDEX_SHIFT (EHEA_DIR_INDEX_SHIFT * 2)
-#define EHEA_MAP_ENTRIES (1 << EHEA_DIR_INDEX_SHIFT)
-#define EHEA_MAP_SIZE (0x10000)                   /* currently fixed map size */
-#define EHEA_INDEX_MASK (EHEA_MAP_ENTRIES - 1)
-
-
-#define EHEA_WATCH_DOG_TIMEOUT 10*HZ
-
-/* utility functions */
-
-void ehea_dump(void *adr, int len, char *msg);
-
-#define EHEA_BMASK(pos, length) (((pos) << 16) + (length))
-
-#define EHEA_BMASK_IBM(from, to) (((63 - to) << 16) + ((to) - (from) + 1))
-
-#define EHEA_BMASK_SHIFTPOS(mask) (((mask) >> 16) & 0xffff)
-
-#define EHEA_BMASK_MASK(mask) \
-	(0xffffffffffffffffULL >> ((64 - (mask)) & 0xffff))
-
-#define EHEA_BMASK_SET(mask, value) \
-	((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask))
-
-#define EHEA_BMASK_GET(mask, value) \
-	(EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask)))
-
-/*
- * Generic ehea page
- */
-struct ehea_page {
-	u8 entries[PAGE_SIZE];
-};
-
-/*
- * Generic queue in linux kernel virtual memory
- */
-struct hw_queue {
-	u64 current_q_offset;		/* current queue entry */
-	struct ehea_page **queue_pages;	/* array of pages belonging to queue */
-	u32 qe_size;			/* queue entry size */
-	u32 queue_length;      		/* queue length allocated in bytes */
-	u32 pagesize;
-	u32 toggle_state;		/* toggle flag - per page */
-	u32 reserved;			/* 64 bit alignment */
-};
-
-/*
- * For pSeries this is a 64bit memory address where
- * I/O memory is mapped into CPU address space
- */
-struct h_epa {
-	void __iomem *addr;
-};
-
-struct h_epa_user {
-	u64 addr;
-};
-
-struct h_epas {
-	struct h_epa kernel;	/* kernel space accessible resource,
-				   set to 0 if unused */
-	struct h_epa_user user;	/* user space accessible resource
-				   set to 0 if unused */
-};
-
-/*
- * Memory map data structures
- */
-struct ehea_dir_bmap
-{
-	u64 ent[EHEA_MAP_ENTRIES];
-};
-struct ehea_top_bmap
-{
-	struct ehea_dir_bmap *dir[EHEA_MAP_ENTRIES];
-};
-struct ehea_bmap
-{
-	struct ehea_top_bmap *top[EHEA_MAP_ENTRIES];
-};
-
-struct ehea_qp;
-struct ehea_cq;
-struct ehea_eq;
-struct ehea_port;
-struct ehea_av;
-
-/*
- * Queue attributes passed to ehea_create_qp()
- */
-struct ehea_qp_init_attr {
-	/* input parameter */
-	u32 qp_token;           /* queue token */
-	u8 low_lat_rq1;
-	u8 signalingtype;       /* cqe generation flag */
-	u8 rq_count;            /* num of receive queues */
-	u8 eqe_gen;             /* eqe generation flag */
-	u16 max_nr_send_wqes;   /* max number of send wqes */
-	u16 max_nr_rwqes_rq1;   /* max number of receive wqes */
-	u16 max_nr_rwqes_rq2;
-	u16 max_nr_rwqes_rq3;
-	u8 wqe_size_enc_sq;
-	u8 wqe_size_enc_rq1;
-	u8 wqe_size_enc_rq2;
-	u8 wqe_size_enc_rq3;
-	u8 swqe_imm_data_len;   /* immediate data length for swqes */
-	u16 port_nr;
-	u16 rq2_threshold;
-	u16 rq3_threshold;
-	u64 send_cq_handle;
-	u64 recv_cq_handle;
-	u64 aff_eq_handle;
-
-	/* output parameter */
-	u32 qp_nr;
-	u16 act_nr_send_wqes;
-	u16 act_nr_rwqes_rq1;
-	u16 act_nr_rwqes_rq2;
-	u16 act_nr_rwqes_rq3;
-	u8 act_wqe_size_enc_sq;
-	u8 act_wqe_size_enc_rq1;
-	u8 act_wqe_size_enc_rq2;
-	u8 act_wqe_size_enc_rq3;
-	u32 nr_sq_pages;
-	u32 nr_rq1_pages;
-	u32 nr_rq2_pages;
-	u32 nr_rq3_pages;
-	u32 liobn_sq;
-	u32 liobn_rq1;
-	u32 liobn_rq2;
-	u32 liobn_rq3;
-};
-
-/*
- * Event Queue attributes, passed as parameter
- */
-struct ehea_eq_attr {
-	u32 type;
-	u32 max_nr_of_eqes;
-	u8 eqe_gen;        /* generate eqe flag */
-	u64 eq_handle;
-	u32 act_nr_of_eqes;
-	u32 nr_pages;
-	u32 ist1;          /* Interrupt service token */
-	u32 ist2;
-	u32 ist3;
-	u32 ist4;
-};
-
-
-/*
- * Event Queue
- */
-struct ehea_eq {
-	struct ehea_adapter *adapter;
-	struct hw_queue hw_queue;
-	u64 fw_handle;
-	struct h_epas epas;
-	spinlock_t spinlock;
-	struct ehea_eq_attr attr;
-};
-
-/*
- * HEA Queues
- */
-struct ehea_qp {
-	struct ehea_adapter *adapter;
-	u64 fw_handle;			/* QP handle for firmware calls */
-	struct hw_queue hw_squeue;
-	struct hw_queue hw_rqueue1;
-	struct hw_queue hw_rqueue2;
-	struct hw_queue hw_rqueue3;
-	struct h_epas epas;
-	struct ehea_qp_init_attr init_attr;
-};
-
-/*
- * Completion Queue attributes
- */
-struct ehea_cq_attr {
-	/* input parameter */
-	u32 max_nr_of_cqes;
-	u32 cq_token;
-	u64 eq_handle;
-
-	/* output parameter */
-	u32 act_nr_of_cqes;
-	u32 nr_pages;
-};
-
-/*
- * Completion Queue
- */
-struct ehea_cq {
-	struct ehea_adapter *adapter;
-	u64 fw_handle;
-	struct hw_queue hw_queue;
-	struct h_epas epas;
-	struct ehea_cq_attr attr;
-};
-
-/*
- * Memory Region
- */
-struct ehea_mr {
-	struct ehea_adapter *adapter;
-	u64 handle;
-	u64 vaddr;
-	u32 lkey;
-};
-
-/*
- * Port state information
- */
-struct port_stats {
-	int poll_receive_errors;
-	int queue_stopped;
-	int err_tcp_cksum;
-	int err_ip_cksum;
-	int err_frame_crc;
-};
-
-#define EHEA_IRQ_NAME_SIZE 20
-
-/*
- * Queue SKB Array
- */
-struct ehea_q_skb_arr {
-	struct sk_buff **arr;		/* skb array for queue */
-	int len;                	/* array length */
-	int index;			/* array index */
-	int os_skbs;			/* rq2/rq3 only: outstanding skbs */
-};
-
-/*
- * Port resources
- */
-struct ehea_port_res {
-	struct napi_struct napi;
-	struct port_stats p_stats;
-	struct ehea_mr send_mr;       	/* send memory region */
-	struct ehea_mr recv_mr;       	/* receive memory region */
-	spinlock_t xmit_lock;
-	struct ehea_port *port;
-	char int_recv_name[EHEA_IRQ_NAME_SIZE];
-	char int_send_name[EHEA_IRQ_NAME_SIZE];
-	struct ehea_qp *qp;
-	struct ehea_cq *send_cq;
-	struct ehea_cq *recv_cq;
-	struct ehea_eq *eq;
-	struct ehea_q_skb_arr rq1_skba;
-	struct ehea_q_skb_arr rq2_skba;
-	struct ehea_q_skb_arr rq3_skba;
-	struct ehea_q_skb_arr sq_skba;
-	int sq_skba_size;
-	spinlock_t netif_queue;
-	int queue_stopped;
-	int swqe_refill_th;
-	atomic_t swqe_avail;
-	int swqe_ll_count;
-	u32 swqe_id_counter;
-	u64 tx_packets;
-	u64 tx_bytes;
-	u64 rx_packets;
-	u64 rx_bytes;
-	u32 poll_counter;
-	struct net_lro_mgr lro_mgr;
-	struct net_lro_desc lro_desc[MAX_LRO_DESCRIPTORS];
-	int sq_restart_flag;
-};
-
-
-#define EHEA_MAX_PORTS 16
-
-#define EHEA_NUM_PORTRES_FW_HANDLES    6  /* QP handle, SendCQ handle,
-					     RecvCQ handle, EQ handle,
-					     SendMR handle, RecvMR handle */
-#define EHEA_NUM_PORT_FW_HANDLES       1  /* EQ handle */
-#define EHEA_NUM_ADAPTER_FW_HANDLES    2  /* MR handle, NEQ handle */
-
-struct ehea_adapter {
-	u64 handle;
-	struct platform_device *ofdev;
-	struct ehea_port *port[EHEA_MAX_PORTS];
-	struct ehea_eq *neq;       /* notification event queue */
-	struct tasklet_struct neq_tasklet;
-	struct ehea_mr mr;
-	u32 pd;                    /* protection domain */
-	u64 max_mc_mac;            /* max number of multicast mac addresses */
-	int active_ports;
-	struct list_head list;
-};
-
-
-struct ehea_mc_list {
-	struct list_head list;
-	u64 macaddr;
-};
-
-/* kdump support */
-struct ehea_fw_handle_entry {
-	u64 adh;               /* Adapter Handle */
-	u64 fwh;               /* Firmware Handle */
-};
-
-struct ehea_fw_handle_array {
-	struct ehea_fw_handle_entry *arr;
-	int num_entries;
-	struct mutex lock;
-};
-
-struct ehea_bcmc_reg_entry {
-	u64 adh;               /* Adapter Handle */
-	u32 port_id;           /* Logical Port Id */
-	u8 reg_type;           /* Registration Type */
-	u64 macaddr;
-};
-
-struct ehea_bcmc_reg_array {
-	struct ehea_bcmc_reg_entry *arr;
-	int num_entries;
-	spinlock_t lock;
-};
-
-#define EHEA_PORT_UP 1
-#define EHEA_PORT_DOWN 0
-#define EHEA_PHY_LINK_UP 1
-#define EHEA_PHY_LINK_DOWN 0
-#define EHEA_MAX_PORT_RES 16
-struct ehea_port {
-	struct ehea_adapter *adapter;	 /* adapter that owns this port */
-	struct net_device *netdev;
-	struct net_device_stats stats;
-	struct ehea_port_res port_res[EHEA_MAX_PORT_RES];
-	struct platform_device  ofdev; /* Open Firmware Device */
-	struct ehea_mc_list *mc_list;	 /* Multicast MAC addresses */
-	struct ehea_eq *qp_eq;
-	struct work_struct reset_task;
-	struct mutex port_lock;
-	char int_aff_name[EHEA_IRQ_NAME_SIZE];
-	int allmulti;			 /* Indicates IFF_ALLMULTI state */
-	int promisc;		 	 /* Indicates IFF_PROMISC state */
-	int num_tx_qps;
-	int num_add_tx_qps;
-	int num_mcs;
-	int resets;
-	unsigned long flags;
-	u64 mac_addr;
-	u32 logical_port_id;
-	u32 port_speed;
-	u32 msg_enable;
-	u32 sig_comp_iv;
-	u32 state;
-	u32 lro_max_aggr;
-	u8 phy_link;
-	u8 full_duplex;
-	u8 autoneg;
-	u8 num_def_qps;
-	wait_queue_head_t swqe_avail_wq;
-	wait_queue_head_t restart_wq;
-};
-
-struct port_res_cfg {
-	int max_entries_rcq;
-	int max_entries_scq;
-	int max_entries_sq;
-	int max_entries_rq1;
-	int max_entries_rq2;
-	int max_entries_rq3;
-};
-
-enum ehea_flag_bits {
-	__EHEA_STOP_XFER,
-	__EHEA_DISABLE_PORT_RESET
-};
-
-void ehea_set_ethtool_ops(struct net_device *netdev);
-int ehea_sense_port_attr(struct ehea_port *port);
-int ehea_set_portspeed(struct ehea_port *port, u32 port_speed);
-
-#endif	/* __EHEA_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/ehea/ehea_hw.h linux-libre-3.2-gnu/drivers/net/ehea/ehea_hw.h
--- linux-libre-3.1-gnu/drivers/net/ehea/ehea_hw.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/ehea/ehea_hw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,292 +0,0 @@
-/*
- *  linux/drivers/net/ehea/ehea_hw.h
- *
- *  eHEA ethernet device driver for IBM eServer System p
- *
- *  (C) Copyright IBM Corp. 2006
- *
- *  Authors:
- *       Christoph Raisch <raisch@de.ibm.com>
- *       Jan-Bernd Themann <themann@de.ibm.com>
- *       Thomas Klein <tklein@de.ibm.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; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __EHEA_HW_H__
-#define __EHEA_HW_H__
-
-#define QPX_SQA_VALUE   EHEA_BMASK_IBM(48, 63)
-#define QPX_RQ1A_VALUE  EHEA_BMASK_IBM(48, 63)
-#define QPX_RQ2A_VALUE  EHEA_BMASK_IBM(48, 63)
-#define QPX_RQ3A_VALUE  EHEA_BMASK_IBM(48, 63)
-
-#define QPTEMM_OFFSET(x) offsetof(struct ehea_qptemm, x)
-
-struct ehea_qptemm {
-	u64 qpx_hcr;
-	u64 qpx_c;
-	u64 qpx_herr;
-	u64 qpx_aer;
-	u64 qpx_sqa;
-	u64 qpx_sqc;
-	u64 qpx_rq1a;
-	u64 qpx_rq1c;
-	u64 qpx_st;
-	u64 qpx_aerr;
-	u64 qpx_tenure;
-	u64 qpx_reserved1[(0x098 - 0x058) / 8];
-	u64 qpx_portp;
-	u64 qpx_reserved2[(0x100 - 0x0A0) / 8];
-	u64 qpx_t;
-	u64 qpx_sqhp;
-	u64 qpx_sqptp;
-	u64 qpx_reserved3[(0x140 - 0x118) / 8];
-	u64 qpx_sqwsize;
-	u64 qpx_reserved4[(0x170 - 0x148) / 8];
-	u64 qpx_sqsize;
-	u64 qpx_reserved5[(0x1B0 - 0x178) / 8];
-	u64 qpx_sigt;
-	u64 qpx_wqecnt;
-	u64 qpx_rq1hp;
-	u64 qpx_rq1ptp;
-	u64 qpx_rq1size;
-	u64 qpx_reserved6[(0x220 - 0x1D8) / 8];
-	u64 qpx_rq1wsize;
-	u64 qpx_reserved7[(0x240 - 0x228) / 8];
-	u64 qpx_pd;
-	u64 qpx_scqn;
-	u64 qpx_rcqn;
-	u64 qpx_aeqn;
-	u64 reserved49;
-	u64 qpx_ram;
-	u64 qpx_reserved8[(0x300 - 0x270) / 8];
-	u64 qpx_rq2a;
-	u64 qpx_rq2c;
-	u64 qpx_rq2hp;
-	u64 qpx_rq2ptp;
-	u64 qpx_rq2size;
-	u64 qpx_rq2wsize;
-	u64 qpx_rq2th;
-	u64 qpx_rq3a;
-	u64 qpx_rq3c;
-	u64 qpx_rq3hp;
-	u64 qpx_rq3ptp;
-	u64 qpx_rq3size;
-	u64 qpx_rq3wsize;
-	u64 qpx_rq3th;
-	u64 qpx_lpn;
-	u64 qpx_reserved9[(0x400 - 0x378) / 8];
-	u64 reserved_ext[(0x500 - 0x400) / 8];
-	u64 reserved2[(0x1000 - 0x500) / 8];
-};
-
-#define MRx_HCR_LPARID_VALID EHEA_BMASK_IBM(0, 0)
-
-#define MRMWMM_OFFSET(x) offsetof(struct ehea_mrmwmm, x)
-
-struct ehea_mrmwmm {
-	u64 mrx_hcr;
-	u64 mrx_c;
-	u64 mrx_herr;
-	u64 mrx_aer;
-	u64 mrx_pp;
-	u64 reserved1;
-	u64 reserved2;
-	u64 reserved3;
-	u64 reserved4[(0x200 - 0x40) / 8];
-	u64 mrx_ctl[64];
-};
-
-#define QPEDMM_OFFSET(x) offsetof(struct ehea_qpedmm, x)
-
-struct ehea_qpedmm {
-
-	u64 reserved0[(0x400) / 8];
-	u64 qpedx_phh;
-	u64 qpedx_ppsgp;
-	u64 qpedx_ppsgu;
-	u64 qpedx_ppdgp;
-	u64 qpedx_ppdgu;
-	u64 qpedx_aph;
-	u64 qpedx_apsgp;
-	u64 qpedx_apsgu;
-	u64 qpedx_apdgp;
-	u64 qpedx_apdgu;
-	u64 qpedx_apav;
-	u64 qpedx_apsav;
-	u64 qpedx_hcr;
-	u64 reserved1[4];
-	u64 qpedx_rrl0;
-	u64 qpedx_rrrkey0;
-	u64 qpedx_rrva0;
-	u64 reserved2;
-	u64 qpedx_rrl1;
-	u64 qpedx_rrrkey1;
-	u64 qpedx_rrva1;
-	u64 reserved3;
-	u64 qpedx_rrl2;
-	u64 qpedx_rrrkey2;
-	u64 qpedx_rrva2;
-	u64 reserved4;
-	u64 qpedx_rrl3;
-	u64 qpedx_rrrkey3;
-	u64 qpedx_rrva3;
-};
-
-#define CQX_FECADDER EHEA_BMASK_IBM(32, 63)
-#define CQX_FEC_CQE_CNT EHEA_BMASK_IBM(32, 63)
-#define CQX_N1_GENERATE_COMP_EVENT EHEA_BMASK_IBM(0, 0)
-#define CQX_EP_EVENT_PENDING EHEA_BMASK_IBM(0, 0)
-
-#define CQTEMM_OFFSET(x) offsetof(struct ehea_cqtemm, x)
-
-struct ehea_cqtemm {
-	u64 cqx_hcr;
-	u64 cqx_c;
-	u64 cqx_herr;
-	u64 cqx_aer;
-	u64 cqx_ptp;
-	u64 cqx_tp;
-	u64 cqx_fec;
-	u64 cqx_feca;
-	u64 cqx_ep;
-	u64 cqx_eq;
-	u64 reserved1;
-	u64 cqx_n0;
-	u64 cqx_n1;
-	u64 reserved2[(0x1000 - 0x60) / 8];
-};
-
-#define EQTEMM_OFFSET(x) offsetof(struct ehea_eqtemm, x)
-
-struct ehea_eqtemm {
-	u64 eqx_hcr;
-	u64 eqx_c;
-	u64 eqx_herr;
-	u64 eqx_aer;
-	u64 eqx_ptp;
-	u64 eqx_tp;
-	u64 eqx_ssba;
-	u64 eqx_psba;
-	u64 eqx_cec;
-	u64 eqx_meql;
-	u64 eqx_xisbi;
-	u64 eqx_xisc;
-	u64 eqx_it;
-};
-
-/*
- * These access functions will be changed when the dissuccsion about
- * the new access methods for POWER has settled.
- */
-
-static inline u64 epa_load(struct h_epa epa, u32 offset)
-{
-	return __raw_readq((void __iomem *)(epa.addr + offset));
-}
-
-static inline void epa_store(struct h_epa epa, u32 offset, u64 value)
-{
-	__raw_writeq(value, (void __iomem *)(epa.addr + offset));
-	epa_load(epa, offset);	/* synchronize explicitly to eHEA */
-}
-
-static inline void epa_store_acc(struct h_epa epa, u32 offset, u64 value)
-{
-	__raw_writeq(value, (void __iomem *)(epa.addr + offset));
-}
-
-#define epa_store_eq(epa, offset, value)\
-	epa_store(epa, EQTEMM_OFFSET(offset), value)
-#define epa_load_eq(epa, offset)\
-	epa_load(epa, EQTEMM_OFFSET(offset))
-
-#define epa_store_cq(epa, offset, value)\
-	epa_store(epa, CQTEMM_OFFSET(offset), value)
-#define epa_load_cq(epa, offset)\
-	epa_load(epa, CQTEMM_OFFSET(offset))
-
-#define epa_store_qp(epa, offset, value)\
-	epa_store(epa, QPTEMM_OFFSET(offset), value)
-#define epa_load_qp(epa, offset)\
-	epa_load(epa, QPTEMM_OFFSET(offset))
-
-#define epa_store_qped(epa, offset, value)\
-	epa_store(epa, QPEDMM_OFFSET(offset), value)
-#define epa_load_qped(epa, offset)\
-	epa_load(epa, QPEDMM_OFFSET(offset))
-
-#define epa_store_mrmw(epa, offset, value)\
-	epa_store(epa, MRMWMM_OFFSET(offset), value)
-#define epa_load_mrmw(epa, offset)\
-	epa_load(epa, MRMWMM_OFFSET(offset))
-
-#define epa_store_base(epa, offset, value)\
-	epa_store(epa, HCAGR_OFFSET(offset), value)
-#define epa_load_base(epa, offset)\
-	epa_load(epa, HCAGR_OFFSET(offset))
-
-static inline void ehea_update_sqa(struct ehea_qp *qp, u16 nr_wqes)
-{
-	struct h_epa epa = qp->epas.kernel;
-	epa_store_acc(epa, QPTEMM_OFFSET(qpx_sqa),
-		      EHEA_BMASK_SET(QPX_SQA_VALUE, nr_wqes));
-}
-
-static inline void ehea_update_rq3a(struct ehea_qp *qp, u16 nr_wqes)
-{
-	struct h_epa epa = qp->epas.kernel;
-	epa_store_acc(epa, QPTEMM_OFFSET(qpx_rq3a),
-		      EHEA_BMASK_SET(QPX_RQ1A_VALUE, nr_wqes));
-}
-
-static inline void ehea_update_rq2a(struct ehea_qp *qp, u16 nr_wqes)
-{
-	struct h_epa epa = qp->epas.kernel;
-	epa_store_acc(epa, QPTEMM_OFFSET(qpx_rq2a),
-		      EHEA_BMASK_SET(QPX_RQ2A_VALUE, nr_wqes));
-}
-
-static inline void ehea_update_rq1a(struct ehea_qp *qp, u16 nr_wqes)
-{
-	struct h_epa epa = qp->epas.kernel;
-	epa_store_acc(epa, QPTEMM_OFFSET(qpx_rq1a),
-		      EHEA_BMASK_SET(QPX_RQ3A_VALUE, nr_wqes));
-}
-
-static inline void ehea_update_feca(struct ehea_cq *cq, u32 nr_cqes)
-{
-	struct h_epa epa = cq->epas.kernel;
-	epa_store_acc(epa, CQTEMM_OFFSET(cqx_feca),
-		      EHEA_BMASK_SET(CQX_FECADDER, nr_cqes));
-}
-
-static inline void ehea_reset_cq_n1(struct ehea_cq *cq)
-{
-	struct h_epa epa = cq->epas.kernel;
-	epa_store_cq(epa, cqx_n1,
-		     EHEA_BMASK_SET(CQX_N1_GENERATE_COMP_EVENT, 1));
-}
-
-static inline void ehea_reset_cq_ep(struct ehea_cq *my_cq)
-{
-	struct h_epa epa = my_cq->epas.kernel;
-	epa_store_acc(epa, CQTEMM_OFFSET(cqx_ep),
-		      EHEA_BMASK_SET(CQX_EP_EVENT_PENDING, 0));
-}
-
-#endif	/* __EHEA_HW_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/ehea/ehea_main.c linux-libre-3.2-gnu/drivers/net/ehea/ehea_main.c
--- linux-libre-3.1-gnu/drivers/net/ehea/ehea_main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/ehea/ehea_main.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3768 +0,0 @@
-/*
- *  linux/drivers/net/ehea/ehea_main.c
- *
- *  eHEA ethernet device driver for IBM eServer System p
- *
- *  (C) Copyright IBM Corp. 2006
- *
- *  Authors:
- *	 Christoph Raisch <raisch@de.ibm.com>
- *	 Jan-Bernd Themann <themann@de.ibm.com>
- *	 Thomas Klein <tklein@de.ibm.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; 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/in.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
-#include <linux/if.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/if_ether.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/memory.h>
-#include <asm/kexec.h>
-#include <linux/mutex.h>
-#include <linux/prefetch.h>
-
-#include <net/ip.h>
-
-#include "ehea.h"
-#include "ehea_qmr.h"
-#include "ehea_phyp.h"
-
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
-MODULE_DESCRIPTION("IBM eServer HEA Driver");
-MODULE_VERSION(DRV_VERSION);
-
-
-static int msg_level = -1;
-static int rq1_entries = EHEA_DEF_ENTRIES_RQ1;
-static int rq2_entries = EHEA_DEF_ENTRIES_RQ2;
-static int rq3_entries = EHEA_DEF_ENTRIES_RQ3;
-static int sq_entries = EHEA_DEF_ENTRIES_SQ;
-static int use_mcs;
-static int use_lro;
-static int lro_max_aggr = EHEA_LRO_MAX_AGGR;
-static int num_tx_qps = EHEA_NUM_TX_QP;
-static int prop_carrier_state;
-
-module_param(msg_level, int, 0);
-module_param(rq1_entries, int, 0);
-module_param(rq2_entries, int, 0);
-module_param(rq3_entries, int, 0);
-module_param(sq_entries, int, 0);
-module_param(prop_carrier_state, int, 0);
-module_param(use_mcs, int, 0);
-module_param(use_lro, int, 0);
-module_param(lro_max_aggr, int, 0);
-module_param(num_tx_qps, int, 0);
-
-MODULE_PARM_DESC(num_tx_qps, "Number of TX-QPS");
-MODULE_PARM_DESC(msg_level, "msg_level");
-MODULE_PARM_DESC(prop_carrier_state, "Propagate carrier state of physical "
-		 "port to stack. 1:yes, 0:no.  Default = 0 ");
-MODULE_PARM_DESC(rq3_entries, "Number of entries for Receive Queue 3 "
-		 "[2^x - 1], x = [6..14]. Default = "
-		 __MODULE_STRING(EHEA_DEF_ENTRIES_RQ3) ")");
-MODULE_PARM_DESC(rq2_entries, "Number of entries for Receive Queue 2 "
-		 "[2^x - 1], x = [6..14]. Default = "
-		 __MODULE_STRING(EHEA_DEF_ENTRIES_RQ2) ")");
-MODULE_PARM_DESC(rq1_entries, "Number of entries for Receive Queue 1 "
-		 "[2^x - 1], x = [6..14]. Default = "
-		 __MODULE_STRING(EHEA_DEF_ENTRIES_RQ1) ")");
-MODULE_PARM_DESC(sq_entries, " Number of entries for the Send Queue  "
-		 "[2^x - 1], x = [6..14]. Default = "
-		 __MODULE_STRING(EHEA_DEF_ENTRIES_SQ) ")");
-MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 0 ");
-
-MODULE_PARM_DESC(lro_max_aggr, " LRO: Max packets to be aggregated. Default = "
-		 __MODULE_STRING(EHEA_LRO_MAX_AGGR));
-MODULE_PARM_DESC(use_lro, " Large Receive Offload, 1: enable, 0: disable, "
-		 "Default = 0");
-
-static int port_name_cnt;
-static LIST_HEAD(adapter_list);
-static unsigned long ehea_driver_flags;
-static DEFINE_MUTEX(dlpar_mem_lock);
-struct ehea_fw_handle_array ehea_fw_handles;
-struct ehea_bcmc_reg_array ehea_bcmc_regs;
-
-
-static int __devinit ehea_probe_adapter(struct platform_device *dev,
-					const struct of_device_id *id);
-
-static int __devexit ehea_remove(struct platform_device *dev);
-
-static struct of_device_id ehea_device_table[] = {
-	{
-		.name = "lhea",
-		.compatible = "IBM,lhea",
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, ehea_device_table);
-
-static struct of_platform_driver ehea_driver = {
-	.driver = {
-		.name = "ehea",
-		.owner = THIS_MODULE,
-		.of_match_table = ehea_device_table,
-	},
-	.probe = ehea_probe_adapter,
-	.remove = ehea_remove,
-};
-
-void ehea_dump(void *adr, int len, char *msg)
-{
-	int x;
-	unsigned char *deb = adr;
-	for (x = 0; x < len; x += 16) {
-		pr_info("%s adr=%p ofs=%04x %016llx %016llx\n",
-			msg, deb, x, *((u64 *)&deb[0]), *((u64 *)&deb[8]));
-		deb += 16;
-	}
-}
-
-void ehea_schedule_port_reset(struct ehea_port *port)
-{
-	if (!test_bit(__EHEA_DISABLE_PORT_RESET, &port->flags))
-		schedule_work(&port->reset_task);
-}
-
-static void ehea_update_firmware_handles(void)
-{
-	struct ehea_fw_handle_entry *arr = NULL;
-	struct ehea_adapter *adapter;
-	int num_adapters = 0;
-	int num_ports = 0;
-	int num_portres = 0;
-	int i = 0;
-	int num_fw_handles, k, l;
-
-	/* Determine number of handles */
-	mutex_lock(&ehea_fw_handles.lock);
-
-	list_for_each_entry(adapter, &adapter_list, list) {
-		num_adapters++;
-
-		for (k = 0; k < EHEA_MAX_PORTS; k++) {
-			struct ehea_port *port = adapter->port[k];
-
-			if (!port || (port->state != EHEA_PORT_UP))
-				continue;
-
-			num_ports++;
-			num_portres += port->num_def_qps + port->num_add_tx_qps;
-		}
-	}
-
-	num_fw_handles = num_adapters * EHEA_NUM_ADAPTER_FW_HANDLES +
-			 num_ports * EHEA_NUM_PORT_FW_HANDLES +
-			 num_portres * EHEA_NUM_PORTRES_FW_HANDLES;
-
-	if (num_fw_handles) {
-		arr = kcalloc(num_fw_handles, sizeof(*arr), GFP_KERNEL);
-		if (!arr)
-			goto out;  /* Keep the existing array */
-	} else
-		goto out_update;
-
-	list_for_each_entry(adapter, &adapter_list, list) {
-		if (num_adapters == 0)
-			break;
-
-		for (k = 0; k < EHEA_MAX_PORTS; k++) {
-			struct ehea_port *port = adapter->port[k];
-
-			if (!port || (port->state != EHEA_PORT_UP) ||
-			    (num_ports == 0))
-				continue;
-
-			for (l = 0;
-			     l < port->num_def_qps + port->num_add_tx_qps;
-			     l++) {
-				struct ehea_port_res *pr = &port->port_res[l];
-
-				arr[i].adh = adapter->handle;
-				arr[i++].fwh = pr->qp->fw_handle;
-				arr[i].adh = adapter->handle;
-				arr[i++].fwh = pr->send_cq->fw_handle;
-				arr[i].adh = adapter->handle;
-				arr[i++].fwh = pr->recv_cq->fw_handle;
-				arr[i].adh = adapter->handle;
-				arr[i++].fwh = pr->eq->fw_handle;
-				arr[i].adh = adapter->handle;
-				arr[i++].fwh = pr->send_mr.handle;
-				arr[i].adh = adapter->handle;
-				arr[i++].fwh = pr->recv_mr.handle;
-			}
-			arr[i].adh = adapter->handle;
-			arr[i++].fwh = port->qp_eq->fw_handle;
-			num_ports--;
-		}
-
-		arr[i].adh = adapter->handle;
-		arr[i++].fwh = adapter->neq->fw_handle;
-
-		if (adapter->mr.handle) {
-			arr[i].adh = adapter->handle;
-			arr[i++].fwh = adapter->mr.handle;
-		}
-		num_adapters--;
-	}
-
-out_update:
-	kfree(ehea_fw_handles.arr);
-	ehea_fw_handles.arr = arr;
-	ehea_fw_handles.num_entries = i;
-out:
-	mutex_unlock(&ehea_fw_handles.lock);
-}
-
-static void ehea_update_bcmc_registrations(void)
-{
-	unsigned long flags;
-	struct ehea_bcmc_reg_entry *arr = NULL;
-	struct ehea_adapter *adapter;
-	struct ehea_mc_list *mc_entry;
-	int num_registrations = 0;
-	int i = 0;
-	int k;
-
-	spin_lock_irqsave(&ehea_bcmc_regs.lock, flags);
-
-	/* Determine number of registrations */
-	list_for_each_entry(adapter, &adapter_list, list)
-		for (k = 0; k < EHEA_MAX_PORTS; k++) {
-			struct ehea_port *port = adapter->port[k];
-
-			if (!port || (port->state != EHEA_PORT_UP))
-				continue;
-
-			num_registrations += 2;	/* Broadcast registrations */
-
-			list_for_each_entry(mc_entry, &port->mc_list->list,list)
-				num_registrations += 2;
-		}
-
-	if (num_registrations) {
-		arr = kcalloc(num_registrations, sizeof(*arr), GFP_ATOMIC);
-		if (!arr)
-			goto out;  /* Keep the existing array */
-	} else
-		goto out_update;
-
-	list_for_each_entry(adapter, &adapter_list, list) {
-		for (k = 0; k < EHEA_MAX_PORTS; k++) {
-			struct ehea_port *port = adapter->port[k];
-
-			if (!port || (port->state != EHEA_PORT_UP))
-				continue;
-
-			if (num_registrations == 0)
-				goto out_update;
-
-			arr[i].adh = adapter->handle;
-			arr[i].port_id = port->logical_port_id;
-			arr[i].reg_type = EHEA_BCMC_BROADCAST |
-					  EHEA_BCMC_UNTAGGED;
-			arr[i++].macaddr = port->mac_addr;
-
-			arr[i].adh = adapter->handle;
-			arr[i].port_id = port->logical_port_id;
-			arr[i].reg_type = EHEA_BCMC_BROADCAST |
-					  EHEA_BCMC_VLANID_ALL;
-			arr[i++].macaddr = port->mac_addr;
-			num_registrations -= 2;
-
-			list_for_each_entry(mc_entry,
-					    &port->mc_list->list, list) {
-				if (num_registrations == 0)
-					goto out_update;
-
-				arr[i].adh = adapter->handle;
-				arr[i].port_id = port->logical_port_id;
-				arr[i].reg_type = EHEA_BCMC_SCOPE_ALL |
-						  EHEA_BCMC_MULTICAST |
-						  EHEA_BCMC_UNTAGGED;
-				arr[i++].macaddr = mc_entry->macaddr;
-
-				arr[i].adh = adapter->handle;
-				arr[i].port_id = port->logical_port_id;
-				arr[i].reg_type = EHEA_BCMC_SCOPE_ALL |
-						  EHEA_BCMC_MULTICAST |
-						  EHEA_BCMC_VLANID_ALL;
-				arr[i++].macaddr = mc_entry->macaddr;
-				num_registrations -= 2;
-			}
-		}
-	}
-
-out_update:
-	kfree(ehea_bcmc_regs.arr);
-	ehea_bcmc_regs.arr = arr;
-	ehea_bcmc_regs.num_entries = i;
-out:
-	spin_unlock_irqrestore(&ehea_bcmc_regs.lock, flags);
-}
-
-static struct net_device_stats *ehea_get_stats(struct net_device *dev)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	struct net_device_stats *stats = &port->stats;
-	struct hcp_ehea_port_cb2 *cb2;
-	u64 hret, rx_packets, tx_packets, rx_bytes = 0, tx_bytes = 0;
-	int i;
-
-	memset(stats, 0, sizeof(*stats));
-
-	cb2 = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!cb2) {
-		netdev_err(dev, "no mem for cb2\n");
-		goto out;
-	}
-
-	hret = ehea_h_query_ehea_port(port->adapter->handle,
-				      port->logical_port_id,
-				      H_PORT_CB2, H_PORT_CB2_ALL, cb2);
-	if (hret != H_SUCCESS) {
-		netdev_err(dev, "query_ehea_port failed\n");
-		goto out_herr;
-	}
-
-	if (netif_msg_hw(port))
-		ehea_dump(cb2, sizeof(*cb2), "net_device_stats");
-
-	rx_packets = 0;
-	for (i = 0; i < port->num_def_qps; i++) {
-		rx_packets += port->port_res[i].rx_packets;
-		rx_bytes   += port->port_res[i].rx_bytes;
-	}
-
-	tx_packets = 0;
-	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
-		tx_packets += port->port_res[i].tx_packets;
-		tx_bytes   += port->port_res[i].tx_bytes;
-	}
-
-	stats->tx_packets = tx_packets;
-	stats->multicast = cb2->rxmcp;
-	stats->rx_errors = cb2->rxuerr;
-	stats->rx_bytes = rx_bytes;
-	stats->tx_bytes = tx_bytes;
-	stats->rx_packets = rx_packets;
-
-out_herr:
-	free_page((unsigned long)cb2);
-out:
-	return stats;
-}
-
-static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes)
-{
-	struct sk_buff **skb_arr_rq1 = pr->rq1_skba.arr;
-	struct net_device *dev = pr->port->netdev;
-	int max_index_mask = pr->rq1_skba.len - 1;
-	int fill_wqes = pr->rq1_skba.os_skbs + nr_of_wqes;
-	int adder = 0;
-	int i;
-
-	pr->rq1_skba.os_skbs = 0;
-
-	if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) {
-		if (nr_of_wqes > 0)
-			pr->rq1_skba.index = index;
-		pr->rq1_skba.os_skbs = fill_wqes;
-		return;
-	}
-
-	for (i = 0; i < fill_wqes; i++) {
-		if (!skb_arr_rq1[index]) {
-			skb_arr_rq1[index] = netdev_alloc_skb(dev,
-							      EHEA_L_PKT_SIZE);
-			if (!skb_arr_rq1[index]) {
-				netdev_info(dev, "Unable to allocate enough skb in the array\n");
-				pr->rq1_skba.os_skbs = fill_wqes - i;
-				break;
-			}
-		}
-		index--;
-		index &= max_index_mask;
-		adder++;
-	}
-
-	if (adder == 0)
-		return;
-
-	/* Ring doorbell */
-	ehea_update_rq1a(pr->qp, adder);
-}
-
-static void ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a)
-{
-	struct sk_buff **skb_arr_rq1 = pr->rq1_skba.arr;
-	struct net_device *dev = pr->port->netdev;
-	int i;
-
-	if (nr_rq1a > pr->rq1_skba.len) {
-		netdev_err(dev, "NR_RQ1A bigger than skb array len\n");
-		return;
-	}
-
-	for (i = 0; i < nr_rq1a; i++) {
-		skb_arr_rq1[i] = netdev_alloc_skb(dev, EHEA_L_PKT_SIZE);
-		if (!skb_arr_rq1[i]) {
-			netdev_info(dev, "Not enough memory to allocate skb array\n");
-			break;
-		}
-	}
-	/* Ring doorbell */
-	ehea_update_rq1a(pr->qp, i - 1);
-}
-
-static int ehea_refill_rq_def(struct ehea_port_res *pr,
-			      struct ehea_q_skb_arr *q_skba, int rq_nr,
-			      int num_wqes, int wqe_type, int packet_size)
-{
-	struct net_device *dev = pr->port->netdev;
-	struct ehea_qp *qp = pr->qp;
-	struct sk_buff **skb_arr = q_skba->arr;
-	struct ehea_rwqe *rwqe;
-	int i, index, max_index_mask, fill_wqes;
-	int adder = 0;
-	int ret = 0;
-
-	fill_wqes = q_skba->os_skbs + num_wqes;
-	q_skba->os_skbs = 0;
-
-	if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) {
-		q_skba->os_skbs = fill_wqes;
-		return ret;
-	}
-
-	index = q_skba->index;
-	max_index_mask = q_skba->len - 1;
-	for (i = 0; i < fill_wqes; i++) {
-		u64 tmp_addr;
-		struct sk_buff *skb;
-
-		skb = netdev_alloc_skb_ip_align(dev, packet_size);
-		if (!skb) {
-			q_skba->os_skbs = fill_wqes - i;
-			if (q_skba->os_skbs == q_skba->len - 2) {
-				netdev_info(pr->port->netdev,
-					    "rq%i ran dry - no mem for skb\n",
-					    rq_nr);
-				ret = -ENOMEM;
-			}
-			break;
-		}
-
-		skb_arr[index] = skb;
-		tmp_addr = ehea_map_vaddr(skb->data);
-		if (tmp_addr == -1) {
-			dev_kfree_skb(skb);
-			q_skba->os_skbs = fill_wqes - i;
-			ret = 0;
-			break;
-		}
-
-		rwqe = ehea_get_next_rwqe(qp, rq_nr);
-		rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type)
-			    | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
-		rwqe->sg_list[0].l_key = pr->recv_mr.lkey;
-		rwqe->sg_list[0].vaddr = tmp_addr;
-		rwqe->sg_list[0].len = packet_size;
-		rwqe->data_segments = 1;
-
-		index++;
-		index &= max_index_mask;
-		adder++;
-	}
-
-	q_skba->index = index;
-	if (adder == 0)
-		goto out;
-
-	/* Ring doorbell */
-	iosync();
-	if (rq_nr == 2)
-		ehea_update_rq2a(pr->qp, adder);
-	else
-		ehea_update_rq3a(pr->qp, adder);
-out:
-	return ret;
-}
-
-
-static int ehea_refill_rq2(struct ehea_port_res *pr, int nr_of_wqes)
-{
-	return ehea_refill_rq_def(pr, &pr->rq2_skba, 2,
-				  nr_of_wqes, EHEA_RWQE2_TYPE,
-				  EHEA_RQ2_PKT_SIZE);
-}
-
-
-static int ehea_refill_rq3(struct ehea_port_res *pr, int nr_of_wqes)
-{
-	return ehea_refill_rq_def(pr, &pr->rq3_skba, 3,
-				  nr_of_wqes, EHEA_RWQE3_TYPE,
-				  EHEA_MAX_PACKET_SIZE);
-}
-
-static inline int ehea_check_cqe(struct ehea_cqe *cqe, int *rq_num)
-{
-	*rq_num = (cqe->type & EHEA_CQE_TYPE_RQ) >> 5;
-	if ((cqe->status & EHEA_CQE_STAT_ERR_MASK) == 0)
-		return 0;
-	if (((cqe->status & EHEA_CQE_STAT_ERR_TCP) != 0) &&
-	    (cqe->header_length == 0))
-		return 0;
-	return -EINVAL;
-}
-
-static inline void ehea_fill_skb(struct net_device *dev,
-				 struct sk_buff *skb, struct ehea_cqe *cqe)
-{
-	int length = cqe->num_bytes_transfered - 4;	/*remove CRC */
-
-	skb_put(skb, length);
-	skb->protocol = eth_type_trans(skb, dev);
-
-	/* The packet was not an IPV4 packet so a complemented checksum was
-	   calculated. The value is found in the Internet Checksum field. */
-	if (cqe->status & EHEA_CQE_BLIND_CKSUM) {
-		skb->ip_summed = CHECKSUM_COMPLETE;
-		skb->csum = csum_unfold(~cqe->inet_checksum_value);
-	} else
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-}
-
-static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array,
-					       int arr_len,
-					       struct ehea_cqe *cqe)
-{
-	int skb_index = EHEA_BMASK_GET(EHEA_WR_ID_INDEX, cqe->wr_id);
-	struct sk_buff *skb;
-	void *pref;
-	int x;
-
-	x = skb_index + 1;
-	x &= (arr_len - 1);
-
-	pref = skb_array[x];
-	if (pref) {
-		prefetchw(pref);
-		prefetchw(pref + EHEA_CACHE_LINE);
-
-		pref = (skb_array[x]->data);
-		prefetch(pref);
-		prefetch(pref + EHEA_CACHE_LINE);
-		prefetch(pref + EHEA_CACHE_LINE * 2);
-		prefetch(pref + EHEA_CACHE_LINE * 3);
-	}
-
-	skb = skb_array[skb_index];
-	skb_array[skb_index] = NULL;
-	return skb;
-}
-
-static inline struct sk_buff *get_skb_by_index_ll(struct sk_buff **skb_array,
-						  int arr_len, int wqe_index)
-{
-	struct sk_buff *skb;
-	void *pref;
-	int x;
-
-	x = wqe_index + 1;
-	x &= (arr_len - 1);
-
-	pref = skb_array[x];
-	if (pref) {
-		prefetchw(pref);
-		prefetchw(pref + EHEA_CACHE_LINE);
-
-		pref = (skb_array[x]->data);
-		prefetchw(pref);
-		prefetchw(pref + EHEA_CACHE_LINE);
-	}
-
-	skb = skb_array[wqe_index];
-	skb_array[wqe_index] = NULL;
-	return skb;
-}
-
-static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq,
-				 struct ehea_cqe *cqe, int *processed_rq2,
-				 int *processed_rq3)
-{
-	struct sk_buff *skb;
-
-	if (cqe->status & EHEA_CQE_STAT_ERR_TCP)
-		pr->p_stats.err_tcp_cksum++;
-	if (cqe->status & EHEA_CQE_STAT_ERR_IP)
-		pr->p_stats.err_ip_cksum++;
-	if (cqe->status & EHEA_CQE_STAT_ERR_CRC)
-		pr->p_stats.err_frame_crc++;
-
-	if (rq == 2) {
-		*processed_rq2 += 1;
-		skb = get_skb_by_index(pr->rq2_skba.arr, pr->rq2_skba.len, cqe);
-		dev_kfree_skb(skb);
-	} else if (rq == 3) {
-		*processed_rq3 += 1;
-		skb = get_skb_by_index(pr->rq3_skba.arr, pr->rq3_skba.len, cqe);
-		dev_kfree_skb(skb);
-	}
-
-	if (cqe->status & EHEA_CQE_STAT_FAT_ERR_MASK) {
-		if (netif_msg_rx_err(pr->port)) {
-			pr_err("Critical receive error for QP %d. Resetting port.\n",
-			       pr->qp->init_attr.qp_nr);
-			ehea_dump(cqe, sizeof(*cqe), "CQE");
-		}
-		ehea_schedule_port_reset(pr->port);
-		return 1;
-	}
-
-	return 0;
-}
-
-static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
-		       void **tcph, u64 *hdr_flags, void *priv)
-{
-	struct ehea_cqe *cqe = priv;
-	unsigned int ip_len;
-	struct iphdr *iph;
-
-	/* non tcp/udp packets */
-	if (!cqe->header_length)
-		return -1;
-
-	/* non tcp packet */
-	skb_reset_network_header(skb);
-	iph = ip_hdr(skb);
-	if (iph->protocol != IPPROTO_TCP)
-		return -1;
-
-	ip_len = ip_hdrlen(skb);
-	skb_set_transport_header(skb, ip_len);
-	*tcph = tcp_hdr(skb);
-
-	/* check if ip header and tcp header are complete */
-	if (ntohs(iph->tot_len) < ip_len + tcp_hdrlen(skb))
-		return -1;
-
-	*hdr_flags = LRO_IPV4 | LRO_TCP;
-	*iphdr = iph;
-
-	return 0;
-}
-
-static void ehea_proc_skb(struct ehea_port_res *pr, struct ehea_cqe *cqe,
-			  struct sk_buff *skb)
-{
-	if (cqe->status & EHEA_CQE_VLAN_TAG_XTRACT)
-		__vlan_hwaccel_put_tag(skb, cqe->vlan_tag);
-
-	if (skb->dev->features & NETIF_F_LRO)
-		lro_receive_skb(&pr->lro_mgr, skb, cqe);
-	else
-		netif_receive_skb(skb);
-}
-
-static int ehea_proc_rwqes(struct net_device *dev,
-			   struct ehea_port_res *pr,
-			   int budget)
-{
-	struct ehea_port *port = pr->port;
-	struct ehea_qp *qp = pr->qp;
-	struct ehea_cqe *cqe;
-	struct sk_buff *skb;
-	struct sk_buff **skb_arr_rq1 = pr->rq1_skba.arr;
-	struct sk_buff **skb_arr_rq2 = pr->rq2_skba.arr;
-	struct sk_buff **skb_arr_rq3 = pr->rq3_skba.arr;
-	int skb_arr_rq1_len = pr->rq1_skba.len;
-	int skb_arr_rq2_len = pr->rq2_skba.len;
-	int skb_arr_rq3_len = pr->rq3_skba.len;
-	int processed, processed_rq1, processed_rq2, processed_rq3;
-	u64 processed_bytes = 0;
-	int wqe_index, last_wqe_index, rq, port_reset;
-
-	processed = processed_rq1 = processed_rq2 = processed_rq3 = 0;
-	last_wqe_index = 0;
-
-	cqe = ehea_poll_rq1(qp, &wqe_index);
-	while ((processed < budget) && cqe) {
-		ehea_inc_rq1(qp);
-		processed_rq1++;
-		processed++;
-		if (netif_msg_rx_status(port))
-			ehea_dump(cqe, sizeof(*cqe), "CQE");
-
-		last_wqe_index = wqe_index;
-		rmb();
-		if (!ehea_check_cqe(cqe, &rq)) {
-			if (rq == 1) {
-				/* LL RQ1 */
-				skb = get_skb_by_index_ll(skb_arr_rq1,
-							  skb_arr_rq1_len,
-							  wqe_index);
-				if (unlikely(!skb)) {
-					netif_info(port, rx_err, dev,
-						  "LL rq1: skb=NULL\n");
-
-					skb = netdev_alloc_skb(dev,
-							       EHEA_L_PKT_SIZE);
-					if (!skb) {
-						netdev_err(dev, "Not enough memory to allocate skb\n");
-						break;
-					}
-				}
-				skb_copy_to_linear_data(skb, ((char *)cqe) + 64,
-						 cqe->num_bytes_transfered - 4);
-				ehea_fill_skb(dev, skb, cqe);
-			} else if (rq == 2) {
-				/* RQ2 */
-				skb = get_skb_by_index(skb_arr_rq2,
-						       skb_arr_rq2_len, cqe);
-				if (unlikely(!skb)) {
-					netif_err(port, rx_err, dev,
-						  "rq2: skb=NULL\n");
-					break;
-				}
-				ehea_fill_skb(dev, skb, cqe);
-				processed_rq2++;
-			} else {
-				/* RQ3 */
-				skb = get_skb_by_index(skb_arr_rq3,
-						       skb_arr_rq3_len, cqe);
-				if (unlikely(!skb)) {
-					netif_err(port, rx_err, dev,
-						  "rq3: skb=NULL\n");
-					break;
-				}
-				ehea_fill_skb(dev, skb, cqe);
-				processed_rq3++;
-			}
-
-			processed_bytes += skb->len;
-			ehea_proc_skb(pr, cqe, skb);
-		} else {
-			pr->p_stats.poll_receive_errors++;
-			port_reset = ehea_treat_poll_error(pr, rq, cqe,
-							   &processed_rq2,
-							   &processed_rq3);
-			if (port_reset)
-				break;
-		}
-		cqe = ehea_poll_rq1(qp, &wqe_index);
-	}
-	if (dev->features & NETIF_F_LRO)
-		lro_flush_all(&pr->lro_mgr);
-
-	pr->rx_packets += processed;
-	pr->rx_bytes += processed_bytes;
-
-	ehea_refill_rq1(pr, last_wqe_index, processed_rq1);
-	ehea_refill_rq2(pr, processed_rq2);
-	ehea_refill_rq3(pr, processed_rq3);
-
-	return processed;
-}
-
-#define SWQE_RESTART_CHECK 0xdeadbeaff00d0000ull
-
-static void reset_sq_restart_flag(struct ehea_port *port)
-{
-	int i;
-
-	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
-		struct ehea_port_res *pr = &port->port_res[i];
-		pr->sq_restart_flag = 0;
-	}
-	wake_up(&port->restart_wq);
-}
-
-static void check_sqs(struct ehea_port *port)
-{
-	struct ehea_swqe *swqe;
-	int swqe_index;
-	int i, k;
-
-	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
-		struct ehea_port_res *pr = &port->port_res[i];
-		int ret;
-		k = 0;
-		swqe = ehea_get_swqe(pr->qp, &swqe_index);
-		memset(swqe, 0, SWQE_HEADER_SIZE);
-		atomic_dec(&pr->swqe_avail);
-
-		swqe->tx_control |= EHEA_SWQE_PURGE;
-		swqe->wr_id = SWQE_RESTART_CHECK;
-		swqe->tx_control |= EHEA_SWQE_SIGNALLED_COMPLETION;
-		swqe->tx_control |= EHEA_SWQE_IMM_DATA_PRESENT;
-		swqe->immediate_data_length = 80;
-
-		ehea_post_swqe(pr->qp, swqe);
-
-		ret = wait_event_timeout(port->restart_wq,
-					 pr->sq_restart_flag == 0,
-					 msecs_to_jiffies(100));
-
-		if (!ret) {
-			pr_err("HW/SW queues out of sync\n");
-			ehea_schedule_port_reset(pr->port);
-			return;
-		}
-	}
-}
-
-
-static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
-{
-	struct sk_buff *skb;
-	struct ehea_cq *send_cq = pr->send_cq;
-	struct ehea_cqe *cqe;
-	int quota = my_quota;
-	int cqe_counter = 0;
-	int swqe_av = 0;
-	int index;
-	unsigned long flags;
-
-	cqe = ehea_poll_cq(send_cq);
-	while (cqe && (quota > 0)) {
-		ehea_inc_cq(send_cq);
-
-		cqe_counter++;
-		rmb();
-
-		if (cqe->wr_id == SWQE_RESTART_CHECK) {
-			pr->sq_restart_flag = 1;
-			swqe_av++;
-			break;
-		}
-
-		if (cqe->status & EHEA_CQE_STAT_ERR_MASK) {
-			pr_err("Bad send completion status=0x%04X\n",
-			       cqe->status);
-
-			if (netif_msg_tx_err(pr->port))
-				ehea_dump(cqe, sizeof(*cqe), "Send CQE");
-
-			if (cqe->status & EHEA_CQE_STAT_RESET_MASK) {
-				pr_err("Resetting port\n");
-				ehea_schedule_port_reset(pr->port);
-				break;
-			}
-		}
-
-		if (netif_msg_tx_done(pr->port))
-			ehea_dump(cqe, sizeof(*cqe), "CQE");
-
-		if (likely(EHEA_BMASK_GET(EHEA_WR_ID_TYPE, cqe->wr_id)
-			   == EHEA_SWQE2_TYPE)) {
-
-			index = EHEA_BMASK_GET(EHEA_WR_ID_INDEX, cqe->wr_id);
-			skb = pr->sq_skba.arr[index];
-			dev_kfree_skb(skb);
-			pr->sq_skba.arr[index] = NULL;
-		}
-
-		swqe_av += EHEA_BMASK_GET(EHEA_WR_ID_REFILL, cqe->wr_id);
-		quota--;
-
-		cqe = ehea_poll_cq(send_cq);
-	}
-
-	ehea_update_feca(send_cq, cqe_counter);
-	atomic_add(swqe_av, &pr->swqe_avail);
-
-	spin_lock_irqsave(&pr->netif_queue, flags);
-
-	if (pr->queue_stopped && (atomic_read(&pr->swqe_avail)
-				  >= pr->swqe_refill_th)) {
-		netif_wake_queue(pr->port->netdev);
-		pr->queue_stopped = 0;
-	}
-	spin_unlock_irqrestore(&pr->netif_queue, flags);
-	wake_up(&pr->port->swqe_avail_wq);
-
-	return cqe;
-}
-
-#define EHEA_NAPI_POLL_NUM_BEFORE_IRQ 16
-#define EHEA_POLL_MAX_CQES 65535
-
-static int ehea_poll(struct napi_struct *napi, int budget)
-{
-	struct ehea_port_res *pr = container_of(napi, struct ehea_port_res,
-						napi);
-	struct net_device *dev = pr->port->netdev;
-	struct ehea_cqe *cqe;
-	struct ehea_cqe *cqe_skb = NULL;
-	int force_irq, wqe_index;
-	int rx = 0;
-
-	force_irq = (pr->poll_counter > EHEA_NAPI_POLL_NUM_BEFORE_IRQ);
-	cqe_skb = ehea_proc_cqes(pr, EHEA_POLL_MAX_CQES);
-
-	if (!force_irq)
-		rx += ehea_proc_rwqes(dev, pr, budget - rx);
-
-	while ((rx != budget) || force_irq) {
-		pr->poll_counter = 0;
-		force_irq = 0;
-		napi_complete(napi);
-		ehea_reset_cq_ep(pr->recv_cq);
-		ehea_reset_cq_ep(pr->send_cq);
-		ehea_reset_cq_n1(pr->recv_cq);
-		ehea_reset_cq_n1(pr->send_cq);
-		rmb();
-		cqe = ehea_poll_rq1(pr->qp, &wqe_index);
-		cqe_skb = ehea_poll_cq(pr->send_cq);
-
-		if (!cqe && !cqe_skb)
-			return rx;
-
-		if (!napi_reschedule(napi))
-			return rx;
-
-		cqe_skb = ehea_proc_cqes(pr, EHEA_POLL_MAX_CQES);
-		rx += ehea_proc_rwqes(dev, pr, budget - rx);
-	}
-
-	pr->poll_counter++;
-	return rx;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void ehea_netpoll(struct net_device *dev)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	int i;
-
-	for (i = 0; i < port->num_def_qps; i++)
-		napi_schedule(&port->port_res[i].napi);
-}
-#endif
-
-static irqreturn_t ehea_recv_irq_handler(int irq, void *param)
-{
-	struct ehea_port_res *pr = param;
-
-	napi_schedule(&pr->napi);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
-{
-	struct ehea_port *port = param;
-	struct ehea_eqe *eqe;
-	struct ehea_qp *qp;
-	u32 qp_token;
-	u64 resource_type, aer, aerr;
-	int reset_port = 0;
-
-	eqe = ehea_poll_eq(port->qp_eq);
-
-	while (eqe) {
-		qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry);
-		pr_err("QP aff_err: entry=0x%llx, token=0x%x\n",
-		       eqe->entry, qp_token);
-
-		qp = port->port_res[qp_token].qp;
-
-		resource_type = ehea_error_data(port->adapter, qp->fw_handle,
-						&aer, &aerr);
-
-		if (resource_type == EHEA_AER_RESTYPE_QP) {
-			if ((aer & EHEA_AER_RESET_MASK) ||
-			    (aerr & EHEA_AERR_RESET_MASK))
-				 reset_port = 1;
-		} else
-			reset_port = 1;   /* Reset in case of CQ or EQ error */
-
-		eqe = ehea_poll_eq(port->qp_eq);
-	}
-
-	if (reset_port) {
-		pr_err("Resetting port\n");
-		ehea_schedule_port_reset(port);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static struct ehea_port *ehea_get_port(struct ehea_adapter *adapter,
-				       int logical_port)
-{
-	int i;
-
-	for (i = 0; i < EHEA_MAX_PORTS; i++)
-		if (adapter->port[i])
-			if (adapter->port[i]->logical_port_id == logical_port)
-				return adapter->port[i];
-	return NULL;
-}
-
-int ehea_sense_port_attr(struct ehea_port *port)
-{
-	int ret;
-	u64 hret;
-	struct hcp_ehea_port_cb0 *cb0;
-
-	/* may be called via ehea_neq_tasklet() */
-	cb0 = (void *)get_zeroed_page(GFP_ATOMIC);
-	if (!cb0) {
-		pr_err("no mem for cb0\n");
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	hret = ehea_h_query_ehea_port(port->adapter->handle,
-				      port->logical_port_id, H_PORT_CB0,
-				      EHEA_BMASK_SET(H_PORT_CB0_ALL, 0xFFFF),
-				      cb0);
-	if (hret != H_SUCCESS) {
-		ret = -EIO;
-		goto out_free;
-	}
-
-	/* MAC address */
-	port->mac_addr = cb0->port_mac_addr << 16;
-
-	if (!is_valid_ether_addr((u8 *)&port->mac_addr)) {
-		ret = -EADDRNOTAVAIL;
-		goto out_free;
-	}
-
-	/* Port speed */
-	switch (cb0->port_speed) {
-	case H_SPEED_10M_H:
-		port->port_speed = EHEA_SPEED_10M;
-		port->full_duplex = 0;
-		break;
-	case H_SPEED_10M_F:
-		port->port_speed = EHEA_SPEED_10M;
-		port->full_duplex = 1;
-		break;
-	case H_SPEED_100M_H:
-		port->port_speed = EHEA_SPEED_100M;
-		port->full_duplex = 0;
-		break;
-	case H_SPEED_100M_F:
-		port->port_speed = EHEA_SPEED_100M;
-		port->full_duplex = 1;
-		break;
-	case H_SPEED_1G_F:
-		port->port_speed = EHEA_SPEED_1G;
-		port->full_duplex = 1;
-		break;
-	case H_SPEED_10G_F:
-		port->port_speed = EHEA_SPEED_10G;
-		port->full_duplex = 1;
-		break;
-	default:
-		port->port_speed = 0;
-		port->full_duplex = 0;
-		break;
-	}
-
-	port->autoneg = 1;
-	port->num_mcs = cb0->num_default_qps;
-
-	/* Number of default QPs */
-	if (use_mcs)
-		port->num_def_qps = cb0->num_default_qps;
-	else
-		port->num_def_qps = 1;
-
-	if (!port->num_def_qps) {
-		ret = -EINVAL;
-		goto out_free;
-	}
-
-	port->num_tx_qps = num_tx_qps;
-
-	if (port->num_def_qps >= port->num_tx_qps)
-		port->num_add_tx_qps = 0;
-	else
-		port->num_add_tx_qps = port->num_tx_qps - port->num_def_qps;
-
-	ret = 0;
-out_free:
-	if (ret || netif_msg_probe(port))
-		ehea_dump(cb0, sizeof(*cb0), "ehea_sense_port_attr");
-	free_page((unsigned long)cb0);
-out:
-	return ret;
-}
-
-int ehea_set_portspeed(struct ehea_port *port, u32 port_speed)
-{
-	struct hcp_ehea_port_cb4 *cb4;
-	u64 hret;
-	int ret = 0;
-
-	cb4 = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!cb4) {
-		pr_err("no mem for cb4\n");
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	cb4->port_speed = port_speed;
-
-	netif_carrier_off(port->netdev);
-
-	hret = ehea_h_modify_ehea_port(port->adapter->handle,
-				       port->logical_port_id,
-				       H_PORT_CB4, H_PORT_CB4_SPEED, cb4);
-	if (hret == H_SUCCESS) {
-		port->autoneg = port_speed == EHEA_SPEED_AUTONEG ? 1 : 0;
-
-		hret = ehea_h_query_ehea_port(port->adapter->handle,
-					      port->logical_port_id,
-					      H_PORT_CB4, H_PORT_CB4_SPEED,
-					      cb4);
-		if (hret == H_SUCCESS) {
-			switch (cb4->port_speed) {
-			case H_SPEED_10M_H:
-				port->port_speed = EHEA_SPEED_10M;
-				port->full_duplex = 0;
-				break;
-			case H_SPEED_10M_F:
-				port->port_speed = EHEA_SPEED_10M;
-				port->full_duplex = 1;
-				break;
-			case H_SPEED_100M_H:
-				port->port_speed = EHEA_SPEED_100M;
-				port->full_duplex = 0;
-				break;
-			case H_SPEED_100M_F:
-				port->port_speed = EHEA_SPEED_100M;
-				port->full_duplex = 1;
-				break;
-			case H_SPEED_1G_F:
-				port->port_speed = EHEA_SPEED_1G;
-				port->full_duplex = 1;
-				break;
-			case H_SPEED_10G_F:
-				port->port_speed = EHEA_SPEED_10G;
-				port->full_duplex = 1;
-				break;
-			default:
-				port->port_speed = 0;
-				port->full_duplex = 0;
-				break;
-			}
-		} else {
-			pr_err("Failed sensing port speed\n");
-			ret = -EIO;
-		}
-	} else {
-		if (hret == H_AUTHORITY) {
-			pr_info("Hypervisor denied setting port speed\n");
-			ret = -EPERM;
-		} else {
-			ret = -EIO;
-			pr_err("Failed setting port speed\n");
-		}
-	}
-	if (!prop_carrier_state || (port->phy_link == EHEA_PHY_LINK_UP))
-		netif_carrier_on(port->netdev);
-
-	free_page((unsigned long)cb4);
-out:
-	return ret;
-}
-
-static void ehea_parse_eqe(struct ehea_adapter *adapter, u64 eqe)
-{
-	int ret;
-	u8 ec;
-	u8 portnum;
-	struct ehea_port *port;
-	struct net_device *dev;
-
-	ec = EHEA_BMASK_GET(NEQE_EVENT_CODE, eqe);
-	portnum = EHEA_BMASK_GET(NEQE_PORTNUM, eqe);
-	port = ehea_get_port(adapter, portnum);
-	dev = port->netdev;
-
-	switch (ec) {
-	case EHEA_EC_PORTSTATE_CHG:	/* port state change */
-
-		if (!port) {
-			netdev_err(dev, "unknown portnum %x\n", portnum);
-			break;
-		}
-
-		if (EHEA_BMASK_GET(NEQE_PORT_UP, eqe)) {
-			if (!netif_carrier_ok(dev)) {
-				ret = ehea_sense_port_attr(port);
-				if (ret) {
-					netdev_err(dev, "failed resensing port attributes\n");
-					break;
-				}
-
-				netif_info(port, link, dev,
-					   "Logical port up: %dMbps %s Duplex\n",
-					   port->port_speed,
-					   port->full_duplex == 1 ?
-					   "Full" : "Half");
-
-				netif_carrier_on(dev);
-				netif_wake_queue(dev);
-			}
-		} else
-			if (netif_carrier_ok(dev)) {
-				netif_info(port, link, dev,
-					   "Logical port down\n");
-				netif_carrier_off(dev);
-				netif_stop_queue(dev);
-			}
-
-		if (EHEA_BMASK_GET(NEQE_EXTSWITCH_PORT_UP, eqe)) {
-			port->phy_link = EHEA_PHY_LINK_UP;
-			netif_info(port, link, dev,
-				   "Physical port up\n");
-			if (prop_carrier_state)
-				netif_carrier_on(dev);
-		} else {
-			port->phy_link = EHEA_PHY_LINK_DOWN;
-			netif_info(port, link, dev,
-				   "Physical port down\n");
-			if (prop_carrier_state)
-				netif_carrier_off(dev);
-		}
-
-		if (EHEA_BMASK_GET(NEQE_EXTSWITCH_PRIMARY, eqe))
-			netdev_info(dev,
-				    "External switch port is primary port\n");
-		else
-			netdev_info(dev,
-				    "External switch port is backup port\n");
-
-		break;
-	case EHEA_EC_ADAPTER_MALFUNC:
-		netdev_err(dev, "Adapter malfunction\n");
-		break;
-	case EHEA_EC_PORT_MALFUNC:
-		netdev_info(dev, "Port malfunction\n");
-		netif_carrier_off(dev);
-		netif_stop_queue(dev);
-		break;
-	default:
-		netdev_err(dev, "unknown event code %x, eqe=0x%llX\n", ec, eqe);
-		break;
-	}
-}
-
-static void ehea_neq_tasklet(unsigned long data)
-{
-	struct ehea_adapter *adapter = (struct ehea_adapter *)data;
-	struct ehea_eqe *eqe;
-	u64 event_mask;
-
-	eqe = ehea_poll_eq(adapter->neq);
-	pr_debug("eqe=%p\n", eqe);
-
-	while (eqe) {
-		pr_debug("*eqe=%lx\n", (unsigned long) eqe->entry);
-		ehea_parse_eqe(adapter, eqe->entry);
-		eqe = ehea_poll_eq(adapter->neq);
-		pr_debug("next eqe=%p\n", eqe);
-	}
-
-	event_mask = EHEA_BMASK_SET(NELR_PORTSTATE_CHG, 1)
-		   | EHEA_BMASK_SET(NELR_ADAPTER_MALFUNC, 1)
-		   | EHEA_BMASK_SET(NELR_PORT_MALFUNC, 1);
-
-	ehea_h_reset_events(adapter->handle,
-			    adapter->neq->fw_handle, event_mask);
-}
-
-static irqreturn_t ehea_interrupt_neq(int irq, void *param)
-{
-	struct ehea_adapter *adapter = param;
-	tasklet_hi_schedule(&adapter->neq_tasklet);
-	return IRQ_HANDLED;
-}
-
-
-static int ehea_fill_port_res(struct ehea_port_res *pr)
-{
-	int ret;
-	struct ehea_qp_init_attr *init_attr = &pr->qp->init_attr;
-
-	ehea_init_fill_rq1(pr, pr->rq1_skba.len);
-
-	ret = ehea_refill_rq2(pr, init_attr->act_nr_rwqes_rq2 - 1);
-
-	ret |= ehea_refill_rq3(pr, init_attr->act_nr_rwqes_rq3 - 1);
-
-	return ret;
-}
-
-static int ehea_reg_interrupts(struct net_device *dev)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	struct ehea_port_res *pr;
-	int i, ret;
-
-
-	snprintf(port->int_aff_name, EHEA_IRQ_NAME_SIZE - 1, "%s-aff",
-		 dev->name);
-
-	ret = ibmebus_request_irq(port->qp_eq->attr.ist1,
-				  ehea_qp_aff_irq_handler,
-				  IRQF_DISABLED, port->int_aff_name, port);
-	if (ret) {
-		netdev_err(dev, "failed registering irq for qp_aff_irq_handler:ist=%X\n",
-			   port->qp_eq->attr.ist1);
-		goto out_free_qpeq;
-	}
-
-	netif_info(port, ifup, dev,
-		   "irq_handle 0x%X for function qp_aff_irq_handler registered\n",
-		   port->qp_eq->attr.ist1);
-
-
-	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
-		pr = &port->port_res[i];
-		snprintf(pr->int_send_name, EHEA_IRQ_NAME_SIZE - 1,
-			 "%s-queue%d", dev->name, i);
-		ret = ibmebus_request_irq(pr->eq->attr.ist1,
-					  ehea_recv_irq_handler,
-					  IRQF_DISABLED, pr->int_send_name,
-					  pr);
-		if (ret) {
-			netdev_err(dev, "failed registering irq for ehea_queue port_res_nr:%d, ist=%X\n",
-				   i, pr->eq->attr.ist1);
-			goto out_free_req;
-		}
-		netif_info(port, ifup, dev,
-			   "irq_handle 0x%X for function ehea_queue_int %d registered\n",
-			   pr->eq->attr.ist1, i);
-	}
-out:
-	return ret;
-
-
-out_free_req:
-	while (--i >= 0) {
-		u32 ist = port->port_res[i].eq->attr.ist1;
-		ibmebus_free_irq(ist, &port->port_res[i]);
-	}
-
-out_free_qpeq:
-	ibmebus_free_irq(port->qp_eq->attr.ist1, port);
-	i = port->num_def_qps;
-
-	goto out;
-
-}
-
-static void ehea_free_interrupts(struct net_device *dev)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	struct ehea_port_res *pr;
-	int i;
-
-	/* send */
-
-	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
-		pr = &port->port_res[i];
-		ibmebus_free_irq(pr->eq->attr.ist1, pr);
-		netif_info(port, intr, dev,
-			   "free send irq for res %d with handle 0x%X\n",
-			   i, pr->eq->attr.ist1);
-	}
-
-	/* associated events */
-	ibmebus_free_irq(port->qp_eq->attr.ist1, port);
-	netif_info(port, intr, dev,
-		   "associated event interrupt for handle 0x%X freed\n",
-		   port->qp_eq->attr.ist1);
-}
-
-static int ehea_configure_port(struct ehea_port *port)
-{
-	int ret, i;
-	u64 hret, mask;
-	struct hcp_ehea_port_cb0 *cb0;
-
-	ret = -ENOMEM;
-	cb0 = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!cb0)
-		goto out;
-
-	cb0->port_rc = EHEA_BMASK_SET(PXLY_RC_VALID, 1)
-		     | EHEA_BMASK_SET(PXLY_RC_IP_CHKSUM, 1)
-		     | EHEA_BMASK_SET(PXLY_RC_TCP_UDP_CHKSUM, 1)
-		     | EHEA_BMASK_SET(PXLY_RC_VLAN_XTRACT, 1)
-		     | EHEA_BMASK_SET(PXLY_RC_VLAN_TAG_FILTER,
-				      PXLY_RC_VLAN_FILTER)
-		     | EHEA_BMASK_SET(PXLY_RC_JUMBO_FRAME, 1);
-
-	for (i = 0; i < port->num_mcs; i++)
-		if (use_mcs)
-			cb0->default_qpn_arr[i] =
-				port->port_res[i].qp->init_attr.qp_nr;
-		else
-			cb0->default_qpn_arr[i] =
-				port->port_res[0].qp->init_attr.qp_nr;
-
-	if (netif_msg_ifup(port))
-		ehea_dump(cb0, sizeof(*cb0), "ehea_configure_port");
-
-	mask = EHEA_BMASK_SET(H_PORT_CB0_PRC, 1)
-	     | EHEA_BMASK_SET(H_PORT_CB0_DEFQPNARRAY, 1);
-
-	hret = ehea_h_modify_ehea_port(port->adapter->handle,
-				       port->logical_port_id,
-				       H_PORT_CB0, mask, cb0);
-	ret = -EIO;
-	if (hret != H_SUCCESS)
-		goto out_free;
-
-	ret = 0;
-
-out_free:
-	free_page((unsigned long)cb0);
-out:
-	return ret;
-}
-
-int ehea_gen_smrs(struct ehea_port_res *pr)
-{
-	int ret;
-	struct ehea_adapter *adapter = pr->port->adapter;
-
-	ret = ehea_gen_smr(adapter, &adapter->mr, &pr->send_mr);
-	if (ret)
-		goto out;
-
-	ret = ehea_gen_smr(adapter, &adapter->mr, &pr->recv_mr);
-	if (ret)
-		goto out_free;
-
-	return 0;
-
-out_free:
-	ehea_rem_mr(&pr->send_mr);
-out:
-	pr_err("Generating SMRS failed\n");
-	return -EIO;
-}
-
-int ehea_rem_smrs(struct ehea_port_res *pr)
-{
-	if ((ehea_rem_mr(&pr->send_mr)) ||
-	    (ehea_rem_mr(&pr->recv_mr)))
-		return -EIO;
-	else
-		return 0;
-}
-
-static int ehea_init_q_skba(struct ehea_q_skb_arr *q_skba, int max_q_entries)
-{
-	int arr_size = sizeof(void *) * max_q_entries;
-
-	q_skba->arr = vzalloc(arr_size);
-	if (!q_skba->arr)
-		return -ENOMEM;
-
-	q_skba->len = max_q_entries;
-	q_skba->index = 0;
-	q_skba->os_skbs = 0;
-
-	return 0;
-}
-
-static int ehea_init_port_res(struct ehea_port *port, struct ehea_port_res *pr,
-			      struct port_res_cfg *pr_cfg, int queue_token)
-{
-	struct ehea_adapter *adapter = port->adapter;
-	enum ehea_eq_type eq_type = EHEA_EQ;
-	struct ehea_qp_init_attr *init_attr = NULL;
-	int ret = -EIO;
-	u64 tx_bytes, rx_bytes, tx_packets, rx_packets;
-
-	tx_bytes = pr->tx_bytes;
-	tx_packets = pr->tx_packets;
-	rx_bytes = pr->rx_bytes;
-	rx_packets = pr->rx_packets;
-
-	memset(pr, 0, sizeof(struct ehea_port_res));
-
-	pr->tx_bytes = rx_bytes;
-	pr->tx_packets = tx_packets;
-	pr->rx_bytes = rx_bytes;
-	pr->rx_packets = rx_packets;
-
-	pr->port = port;
-	spin_lock_init(&pr->xmit_lock);
-	spin_lock_init(&pr->netif_queue);
-
-	pr->eq = ehea_create_eq(adapter, eq_type, EHEA_MAX_ENTRIES_EQ, 0);
-	if (!pr->eq) {
-		pr_err("create_eq failed (eq)\n");
-		goto out_free;
-	}
-
-	pr->recv_cq = ehea_create_cq(adapter, pr_cfg->max_entries_rcq,
-				     pr->eq->fw_handle,
-				     port->logical_port_id);
-	if (!pr->recv_cq) {
-		pr_err("create_cq failed (cq_recv)\n");
-		goto out_free;
-	}
-
-	pr->send_cq = ehea_create_cq(adapter, pr_cfg->max_entries_scq,
-				     pr->eq->fw_handle,
-				     port->logical_port_id);
-	if (!pr->send_cq) {
-		pr_err("create_cq failed (cq_send)\n");
-		goto out_free;
-	}
-
-	if (netif_msg_ifup(port))
-		pr_info("Send CQ: act_nr_cqes=%d, Recv CQ: act_nr_cqes=%d\n",
-			pr->send_cq->attr.act_nr_of_cqes,
-			pr->recv_cq->attr.act_nr_of_cqes);
-
-	init_attr = kzalloc(sizeof(*init_attr), GFP_KERNEL);
-	if (!init_attr) {
-		ret = -ENOMEM;
-		pr_err("no mem for ehea_qp_init_attr\n");
-		goto out_free;
-	}
-
-	init_attr->low_lat_rq1 = 1;
-	init_attr->signalingtype = 1;	/* generate CQE if specified in WQE */
-	init_attr->rq_count = 3;
-	init_attr->qp_token = queue_token;
-	init_attr->max_nr_send_wqes = pr_cfg->max_entries_sq;
-	init_attr->max_nr_rwqes_rq1 = pr_cfg->max_entries_rq1;
-	init_attr->max_nr_rwqes_rq2 = pr_cfg->max_entries_rq2;
-	init_attr->max_nr_rwqes_rq3 = pr_cfg->max_entries_rq3;
-	init_attr->wqe_size_enc_sq = EHEA_SG_SQ;
-	init_attr->wqe_size_enc_rq1 = EHEA_SG_RQ1;
-	init_attr->wqe_size_enc_rq2 = EHEA_SG_RQ2;
-	init_attr->wqe_size_enc_rq3 = EHEA_SG_RQ3;
-	init_attr->rq2_threshold = EHEA_RQ2_THRESHOLD;
-	init_attr->rq3_threshold = EHEA_RQ3_THRESHOLD;
-	init_attr->port_nr = port->logical_port_id;
-	init_attr->send_cq_handle = pr->send_cq->fw_handle;
-	init_attr->recv_cq_handle = pr->recv_cq->fw_handle;
-	init_attr->aff_eq_handle = port->qp_eq->fw_handle;
-
-	pr->qp = ehea_create_qp(adapter, adapter->pd, init_attr);
-	if (!pr->qp) {
-		pr_err("create_qp failed\n");
-		ret = -EIO;
-		goto out_free;
-	}
-
-	if (netif_msg_ifup(port))
-		pr_info("QP: qp_nr=%d\n act_nr_snd_wqe=%d\n nr_rwqe_rq1=%d\n nr_rwqe_rq2=%d\n nr_rwqe_rq3=%d\n",
-			init_attr->qp_nr,
-			init_attr->act_nr_send_wqes,
-			init_attr->act_nr_rwqes_rq1,
-			init_attr->act_nr_rwqes_rq2,
-			init_attr->act_nr_rwqes_rq3);
-
-	pr->sq_skba_size = init_attr->act_nr_send_wqes + 1;
-
-	ret = ehea_init_q_skba(&pr->sq_skba, pr->sq_skba_size);
-	ret |= ehea_init_q_skba(&pr->rq1_skba, init_attr->act_nr_rwqes_rq1 + 1);
-	ret |= ehea_init_q_skba(&pr->rq2_skba, init_attr->act_nr_rwqes_rq2 + 1);
-	ret |= ehea_init_q_skba(&pr->rq3_skba, init_attr->act_nr_rwqes_rq3 + 1);
-	if (ret)
-		goto out_free;
-
-	pr->swqe_refill_th = init_attr->act_nr_send_wqes / 10;
-	if (ehea_gen_smrs(pr) != 0) {
-		ret = -EIO;
-		goto out_free;
-	}
-
-	atomic_set(&pr->swqe_avail, init_attr->act_nr_send_wqes - 1);
-
-	kfree(init_attr);
-
-	netif_napi_add(pr->port->netdev, &pr->napi, ehea_poll, 64);
-
-	pr->lro_mgr.max_aggr = pr->port->lro_max_aggr;
-	pr->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS;
-	pr->lro_mgr.lro_arr = pr->lro_desc;
-	pr->lro_mgr.get_skb_header = get_skb_hdr;
-	pr->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
-	pr->lro_mgr.dev = port->netdev;
-	pr->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
-	pr->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
-
-	ret = 0;
-	goto out;
-
-out_free:
-	kfree(init_attr);
-	vfree(pr->sq_skba.arr);
-	vfree(pr->rq1_skba.arr);
-	vfree(pr->rq2_skba.arr);
-	vfree(pr->rq3_skba.arr);
-	ehea_destroy_qp(pr->qp);
-	ehea_destroy_cq(pr->send_cq);
-	ehea_destroy_cq(pr->recv_cq);
-	ehea_destroy_eq(pr->eq);
-out:
-	return ret;
-}
-
-static int ehea_clean_portres(struct ehea_port *port, struct ehea_port_res *pr)
-{
-	int ret, i;
-
-	if (pr->qp)
-		netif_napi_del(&pr->napi);
-
-	ret = ehea_destroy_qp(pr->qp);
-
-	if (!ret) {
-		ehea_destroy_cq(pr->send_cq);
-		ehea_destroy_cq(pr->recv_cq);
-		ehea_destroy_eq(pr->eq);
-
-		for (i = 0; i < pr->rq1_skba.len; i++)
-			if (pr->rq1_skba.arr[i])
-				dev_kfree_skb(pr->rq1_skba.arr[i]);
-
-		for (i = 0; i < pr->rq2_skba.len; i++)
-			if (pr->rq2_skba.arr[i])
-				dev_kfree_skb(pr->rq2_skba.arr[i]);
-
-		for (i = 0; i < pr->rq3_skba.len; i++)
-			if (pr->rq3_skba.arr[i])
-				dev_kfree_skb(pr->rq3_skba.arr[i]);
-
-		for (i = 0; i < pr->sq_skba.len; i++)
-			if (pr->sq_skba.arr[i])
-				dev_kfree_skb(pr->sq_skba.arr[i]);
-
-		vfree(pr->rq1_skba.arr);
-		vfree(pr->rq2_skba.arr);
-		vfree(pr->rq3_skba.arr);
-		vfree(pr->sq_skba.arr);
-		ret = ehea_rem_smrs(pr);
-	}
-	return ret;
-}
-
-/*
- * The write_* functions store information in swqe which is used by
- * the hardware to calculate the ip/tcp/udp checksum
- */
-
-static inline void write_ip_start_end(struct ehea_swqe *swqe,
-				      const struct sk_buff *skb)
-{
-	swqe->ip_start = skb_network_offset(skb);
-	swqe->ip_end = (u8)(swqe->ip_start + ip_hdrlen(skb) - 1);
-}
-
-static inline void write_tcp_offset_end(struct ehea_swqe *swqe,
-					const struct sk_buff *skb)
-{
-	swqe->tcp_offset =
-		(u8)(swqe->ip_end + 1 + offsetof(struct tcphdr, check));
-
-	swqe->tcp_end = (u16)skb->len - 1;
-}
-
-static inline void write_udp_offset_end(struct ehea_swqe *swqe,
-					const struct sk_buff *skb)
-{
-	swqe->tcp_offset =
-		(u8)(swqe->ip_end + 1 + offsetof(struct udphdr, check));
-
-	swqe->tcp_end = (u16)skb->len - 1;
-}
-
-
-static void write_swqe2_TSO(struct sk_buff *skb,
-			    struct ehea_swqe *swqe, u32 lkey)
-{
-	struct ehea_vsgentry *sg1entry = &swqe->u.immdata_desc.sg_entry;
-	u8 *imm_data = &swqe->u.immdata_desc.immediate_data[0];
-	int skb_data_size = skb_headlen(skb);
-	int headersize;
-
-	/* Packet is TCP with TSO enabled */
-	swqe->tx_control |= EHEA_SWQE_TSO;
-	swqe->mss = skb_shinfo(skb)->gso_size;
-	/* copy only eth/ip/tcp headers to immediate data and
-	 * the rest of skb->data to sg1entry
-	 */
-	headersize = ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
-
-	skb_data_size = skb_headlen(skb);
-
-	if (skb_data_size >= headersize) {
-		/* copy immediate data */
-		skb_copy_from_linear_data(skb, imm_data, headersize);
-		swqe->immediate_data_length = headersize;
-
-		if (skb_data_size > headersize) {
-			/* set sg1entry data */
-			sg1entry->l_key = lkey;
-			sg1entry->len = skb_data_size - headersize;
-			sg1entry->vaddr =
-				ehea_map_vaddr(skb->data + headersize);
-			swqe->descriptors++;
-		}
-	} else
-		pr_err("cannot handle fragmented headers\n");
-}
-
-static void write_swqe2_nonTSO(struct sk_buff *skb,
-			       struct ehea_swqe *swqe, u32 lkey)
-{
-	int skb_data_size = skb_headlen(skb);
-	u8 *imm_data = &swqe->u.immdata_desc.immediate_data[0];
-	struct ehea_vsgentry *sg1entry = &swqe->u.immdata_desc.sg_entry;
-
-	/* Packet is any nonTSO type
-	 *
-	 * Copy as much as possible skb->data to immediate data and
-	 * the rest to sg1entry
-	 */
-	if (skb_data_size >= SWQE2_MAX_IMM) {
-		/* copy immediate data */
-		skb_copy_from_linear_data(skb, imm_data, SWQE2_MAX_IMM);
-
-		swqe->immediate_data_length = SWQE2_MAX_IMM;
-
-		if (skb_data_size > SWQE2_MAX_IMM) {
-			/* copy sg1entry data */
-			sg1entry->l_key = lkey;
-			sg1entry->len = skb_data_size - SWQE2_MAX_IMM;
-			sg1entry->vaddr =
-				ehea_map_vaddr(skb->data + SWQE2_MAX_IMM);
-			swqe->descriptors++;
-		}
-	} else {
-		skb_copy_from_linear_data(skb, imm_data, skb_data_size);
-		swqe->immediate_data_length = skb_data_size;
-	}
-}
-
-static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
-				    struct ehea_swqe *swqe, u32 lkey)
-{
-	struct ehea_vsgentry *sg_list, *sg1entry, *sgentry;
-	skb_frag_t *frag;
-	int nfrags, sg1entry_contains_frag_data, i;
-
-	nfrags = skb_shinfo(skb)->nr_frags;
-	sg1entry = &swqe->u.immdata_desc.sg_entry;
-	sg_list = (struct ehea_vsgentry *)&swqe->u.immdata_desc.sg_list;
-	swqe->descriptors = 0;
-	sg1entry_contains_frag_data = 0;
-
-	if ((dev->features & NETIF_F_TSO) && skb_shinfo(skb)->gso_size)
-		write_swqe2_TSO(skb, swqe, lkey);
-	else
-		write_swqe2_nonTSO(skb, swqe, lkey);
-
-	/* write descriptors */
-	if (nfrags > 0) {
-		if (swqe->descriptors == 0) {
-			/* sg1entry not yet used */
-			frag = &skb_shinfo(skb)->frags[0];
-
-			/* copy sg1entry data */
-			sg1entry->l_key = lkey;
-			sg1entry->len = frag->size;
-			sg1entry->vaddr =
-				ehea_map_vaddr(page_address(frag->page)
-					       + frag->page_offset);
-			swqe->descriptors++;
-			sg1entry_contains_frag_data = 1;
-		}
-
-		for (i = sg1entry_contains_frag_data; i < nfrags; i++) {
-
-			frag = &skb_shinfo(skb)->frags[i];
-			sgentry = &sg_list[i - sg1entry_contains_frag_data];
-
-			sgentry->l_key = lkey;
-			sgentry->len = frag->size;
-			sgentry->vaddr =
-				ehea_map_vaddr(page_address(frag->page)
-					       + frag->page_offset);
-			swqe->descriptors++;
-		}
-	}
-}
-
-static int ehea_broadcast_reg_helper(struct ehea_port *port, u32 hcallid)
-{
-	int ret = 0;
-	u64 hret;
-	u8 reg_type;
-
-	/* De/Register untagged packets */
-	reg_type = EHEA_BCMC_BROADCAST | EHEA_BCMC_UNTAGGED;
-	hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
-				     port->logical_port_id,
-				     reg_type, port->mac_addr, 0, hcallid);
-	if (hret != H_SUCCESS) {
-		pr_err("%sregistering bc address failed (tagged)\n",
-		       hcallid == H_REG_BCMC ? "" : "de");
-		ret = -EIO;
-		goto out_herr;
-	}
-
-	/* De/Register VLAN packets */
-	reg_type = EHEA_BCMC_BROADCAST | EHEA_BCMC_VLANID_ALL;
-	hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
-				     port->logical_port_id,
-				     reg_type, port->mac_addr, 0, hcallid);
-	if (hret != H_SUCCESS) {
-		pr_err("%sregistering bc address failed (vlan)\n",
-		       hcallid == H_REG_BCMC ? "" : "de");
-		ret = -EIO;
-	}
-out_herr:
-	return ret;
-}
-
-static int ehea_set_mac_addr(struct net_device *dev, void *sa)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	struct sockaddr *mac_addr = sa;
-	struct hcp_ehea_port_cb0 *cb0;
-	int ret;
-	u64 hret;
-
-	if (!is_valid_ether_addr(mac_addr->sa_data)) {
-		ret = -EADDRNOTAVAIL;
-		goto out;
-	}
-
-	cb0 = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!cb0) {
-		pr_err("no mem for cb0\n");
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	memcpy(&(cb0->port_mac_addr), &(mac_addr->sa_data[0]), ETH_ALEN);
-
-	cb0->port_mac_addr = cb0->port_mac_addr >> 16;
-
-	hret = ehea_h_modify_ehea_port(port->adapter->handle,
-				       port->logical_port_id, H_PORT_CB0,
-				       EHEA_BMASK_SET(H_PORT_CB0_MAC, 1), cb0);
-	if (hret != H_SUCCESS) {
-		ret = -EIO;
-		goto out_free;
-	}
-
-	memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len);
-
-	/* Deregister old MAC in pHYP */
-	if (port->state == EHEA_PORT_UP) {
-		ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
-		if (ret)
-			goto out_upregs;
-	}
-
-	port->mac_addr = cb0->port_mac_addr << 16;
-
-	/* Register new MAC in pHYP */
-	if (port->state == EHEA_PORT_UP) {
-		ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
-		if (ret)
-			goto out_upregs;
-	}
-
-	ret = 0;
-
-out_upregs:
-	ehea_update_bcmc_registrations();
-out_free:
-	free_page((unsigned long)cb0);
-out:
-	return ret;
-}
-
-static void ehea_promiscuous_error(u64 hret, int enable)
-{
-	if (hret == H_AUTHORITY)
-		pr_info("Hypervisor denied %sabling promiscuous mode\n",
-			enable == 1 ? "en" : "dis");
-	else
-		pr_err("failed %sabling promiscuous mode\n",
-		       enable == 1 ? "en" : "dis");
-}
-
-static void ehea_promiscuous(struct net_device *dev, int enable)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	struct hcp_ehea_port_cb7 *cb7;
-	u64 hret;
-
-	if (enable == port->promisc)
-		return;
-
-	cb7 = (void *)get_zeroed_page(GFP_ATOMIC);
-	if (!cb7) {
-		pr_err("no mem for cb7\n");
-		goto out;
-	}
-
-	/* Modify Pxs_DUCQPN in CB7 */
-	cb7->def_uc_qpn = enable == 1 ? port->port_res[0].qp->fw_handle : 0;
-
-	hret = ehea_h_modify_ehea_port(port->adapter->handle,
-				       port->logical_port_id,
-				       H_PORT_CB7, H_PORT_CB7_DUCQPN, cb7);
-	if (hret) {
-		ehea_promiscuous_error(hret, enable);
-		goto out;
-	}
-
-	port->promisc = enable;
-out:
-	free_page((unsigned long)cb7);
-}
-
-static u64 ehea_multicast_reg_helper(struct ehea_port *port, u64 mc_mac_addr,
-				     u32 hcallid)
-{
-	u64 hret;
-	u8 reg_type;
-
-	reg_type = EHEA_BCMC_SCOPE_ALL | EHEA_BCMC_MULTICAST
-		 | EHEA_BCMC_UNTAGGED;
-
-	hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
-				     port->logical_port_id,
-				     reg_type, mc_mac_addr, 0, hcallid);
-	if (hret)
-		goto out;
-
-	reg_type = EHEA_BCMC_SCOPE_ALL | EHEA_BCMC_MULTICAST
-		 | EHEA_BCMC_VLANID_ALL;
-
-	hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
-				     port->logical_port_id,
-				     reg_type, mc_mac_addr, 0, hcallid);
-out:
-	return hret;
-}
-
-static int ehea_drop_multicast_list(struct net_device *dev)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	struct ehea_mc_list *mc_entry = port->mc_list;
-	struct list_head *pos;
-	struct list_head *temp;
-	int ret = 0;
-	u64 hret;
-
-	list_for_each_safe(pos, temp, &(port->mc_list->list)) {
-		mc_entry = list_entry(pos, struct ehea_mc_list, list);
-
-		hret = ehea_multicast_reg_helper(port, mc_entry->macaddr,
-						 H_DEREG_BCMC);
-		if (hret) {
-			pr_err("failed deregistering mcast MAC\n");
-			ret = -EIO;
-		}
-
-		list_del(pos);
-		kfree(mc_entry);
-	}
-	return ret;
-}
-
-static void ehea_allmulti(struct net_device *dev, int enable)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	u64 hret;
-
-	if (!port->allmulti) {
-		if (enable) {
-			/* Enable ALLMULTI */
-			ehea_drop_multicast_list(dev);
-			hret = ehea_multicast_reg_helper(port, 0, H_REG_BCMC);
-			if (!hret)
-				port->allmulti = 1;
-			else
-				netdev_err(dev,
-					   "failed enabling IFF_ALLMULTI\n");
-		}
-	} else
-		if (!enable) {
-			/* Disable ALLMULTI */
-			hret = ehea_multicast_reg_helper(port, 0, H_DEREG_BCMC);
-			if (!hret)
-				port->allmulti = 0;
-			else
-				netdev_err(dev,
-					   "failed disabling IFF_ALLMULTI\n");
-		}
-}
-
-static void ehea_add_multicast_entry(struct ehea_port *port, u8 *mc_mac_addr)
-{
-	struct ehea_mc_list *ehea_mcl_entry;
-	u64 hret;
-
-	ehea_mcl_entry = kzalloc(sizeof(*ehea_mcl_entry), GFP_ATOMIC);
-	if (!ehea_mcl_entry) {
-		pr_err("no mem for mcl_entry\n");
-		return;
-	}
-
-	INIT_LIST_HEAD(&ehea_mcl_entry->list);
-
-	memcpy(&ehea_mcl_entry->macaddr, mc_mac_addr, ETH_ALEN);
-
-	hret = ehea_multicast_reg_helper(port, ehea_mcl_entry->macaddr,
-					 H_REG_BCMC);
-	if (!hret)
-		list_add(&ehea_mcl_entry->list, &port->mc_list->list);
-	else {
-		pr_err("failed registering mcast MAC\n");
-		kfree(ehea_mcl_entry);
-	}
-}
-
-static void ehea_set_multicast_list(struct net_device *dev)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	struct netdev_hw_addr *ha;
-	int ret;
-
-	if (port->promisc) {
-		ehea_promiscuous(dev, 1);
-		return;
-	}
-	ehea_promiscuous(dev, 0);
-
-	if (dev->flags & IFF_ALLMULTI) {
-		ehea_allmulti(dev, 1);
-		goto out;
-	}
-	ehea_allmulti(dev, 0);
-
-	if (!netdev_mc_empty(dev)) {
-		ret = ehea_drop_multicast_list(dev);
-		if (ret) {
-			/* Dropping the current multicast list failed.
-			 * Enabling ALL_MULTI is the best we can do.
-			 */
-			ehea_allmulti(dev, 1);
-		}
-
-		if (netdev_mc_count(dev) > port->adapter->max_mc_mac) {
-			pr_info("Mcast registration limit reached (0x%llx). Use ALLMULTI!\n",
-				port->adapter->max_mc_mac);
-			goto out;
-		}
-
-		netdev_for_each_mc_addr(ha, dev)
-			ehea_add_multicast_entry(port, ha->addr);
-
-	}
-out:
-	ehea_update_bcmc_registrations();
-}
-
-static int ehea_change_mtu(struct net_device *dev, int new_mtu)
-{
-	if ((new_mtu < 68) || (new_mtu > EHEA_MAX_PACKET_SIZE))
-		return -EINVAL;
-	dev->mtu = new_mtu;
-	return 0;
-}
-
-static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
-		       struct ehea_swqe *swqe, u32 lkey)
-{
-	if (skb->protocol == htons(ETH_P_IP)) {
-		const struct iphdr *iph = ip_hdr(skb);
-
-		/* IPv4 */
-		swqe->tx_control |= EHEA_SWQE_CRC
-				 | EHEA_SWQE_IP_CHECKSUM
-				 | EHEA_SWQE_TCP_CHECKSUM
-				 | EHEA_SWQE_IMM_DATA_PRESENT
-				 | EHEA_SWQE_DESCRIPTORS_PRESENT;
-
-		write_ip_start_end(swqe, skb);
-
-		if (iph->protocol == IPPROTO_UDP) {
-			if ((iph->frag_off & IP_MF) ||
-			    (iph->frag_off & IP_OFFSET))
-				/* IP fragment, so don't change cs */
-				swqe->tx_control &= ~EHEA_SWQE_TCP_CHECKSUM;
-			else
-				write_udp_offset_end(swqe, skb);
-		} else if (iph->protocol == IPPROTO_TCP) {
-			write_tcp_offset_end(swqe, skb);
-		}
-
-		/* icmp (big data) and ip segmentation packets (all other ip
-		   packets) do not require any special handling */
-
-	} else {
-		/* Other Ethernet Protocol */
-		swqe->tx_control |= EHEA_SWQE_CRC
-				 | EHEA_SWQE_IMM_DATA_PRESENT
-				 | EHEA_SWQE_DESCRIPTORS_PRESENT;
-	}
-
-	write_swqe2_data(skb, dev, swqe, lkey);
-}
-
-static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev,
-		       struct ehea_swqe *swqe)
-{
-	int nfrags = skb_shinfo(skb)->nr_frags;
-	u8 *imm_data = &swqe->u.immdata_nodesc.immediate_data[0];
-	skb_frag_t *frag;
-	int i;
-
-	if (skb->protocol == htons(ETH_P_IP)) {
-		const struct iphdr *iph = ip_hdr(skb);
-
-		/* IPv4 */
-		write_ip_start_end(swqe, skb);
-
-		if (iph->protocol == IPPROTO_TCP) {
-			swqe->tx_control |= EHEA_SWQE_CRC
-					 | EHEA_SWQE_IP_CHECKSUM
-					 | EHEA_SWQE_TCP_CHECKSUM
-					 | EHEA_SWQE_IMM_DATA_PRESENT;
-
-			write_tcp_offset_end(swqe, skb);
-
-		} else if (iph->protocol == IPPROTO_UDP) {
-			if ((iph->frag_off & IP_MF) ||
-			    (iph->frag_off & IP_OFFSET))
-				/* IP fragment, so don't change cs */
-				swqe->tx_control |= EHEA_SWQE_CRC
-						 | EHEA_SWQE_IMM_DATA_PRESENT;
-			else {
-				swqe->tx_control |= EHEA_SWQE_CRC
-						 | EHEA_SWQE_IP_CHECKSUM
-						 | EHEA_SWQE_TCP_CHECKSUM
-						 | EHEA_SWQE_IMM_DATA_PRESENT;
-
-				write_udp_offset_end(swqe, skb);
-			}
-		} else {
-			/* icmp (big data) and
-			   ip segmentation packets (all other ip packets) */
-			swqe->tx_control |= EHEA_SWQE_CRC
-					 | EHEA_SWQE_IP_CHECKSUM
-					 | EHEA_SWQE_IMM_DATA_PRESENT;
-		}
-	} else {
-		/* Other Ethernet Protocol */
-		swqe->tx_control |= EHEA_SWQE_CRC | EHEA_SWQE_IMM_DATA_PRESENT;
-	}
-	/* copy (immediate) data */
-	if (nfrags == 0) {
-		/* data is in a single piece */
-		skb_copy_from_linear_data(skb, imm_data, skb->len);
-	} else {
-		/* first copy data from the skb->data buffer ... */
-		skb_copy_from_linear_data(skb, imm_data,
-					  skb_headlen(skb));
-		imm_data += skb_headlen(skb);
-
-		/* ... then copy data from the fragments */
-		for (i = 0; i < nfrags; i++) {
-			frag = &skb_shinfo(skb)->frags[i];
-			memcpy(imm_data,
-			       page_address(frag->page) + frag->page_offset,
-			       frag->size);
-			imm_data += frag->size;
-		}
-	}
-	swqe->immediate_data_length = skb->len;
-	dev_kfree_skb(skb);
-}
-
-static inline int ehea_hash_skb(struct sk_buff *skb, int num_qps)
-{
-	struct tcphdr *tcp;
-	u32 tmp;
-
-	if ((skb->protocol == htons(ETH_P_IP)) &&
-	    (ip_hdr(skb)->protocol == IPPROTO_TCP)) {
-		tcp = (struct tcphdr *)(skb_network_header(skb) +
-					(ip_hdr(skb)->ihl * 4));
-		tmp = (tcp->source + (tcp->dest << 16)) % 31;
-		tmp += ip_hdr(skb)->daddr % 31;
-		return tmp % num_qps;
-	} else
-		return 0;
-}
-
-static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	struct ehea_swqe *swqe;
-	unsigned long flags;
-	u32 lkey;
-	int swqe_index;
-	struct ehea_port_res *pr;
-
-	pr = &port->port_res[ehea_hash_skb(skb, port->num_tx_qps)];
-
-	if (!spin_trylock(&pr->xmit_lock))
-		return NETDEV_TX_BUSY;
-
-	if (pr->queue_stopped) {
-		spin_unlock(&pr->xmit_lock);
-		return NETDEV_TX_BUSY;
-	}
-
-	swqe = ehea_get_swqe(pr->qp, &swqe_index);
-	memset(swqe, 0, SWQE_HEADER_SIZE);
-	atomic_dec(&pr->swqe_avail);
-
-	if (vlan_tx_tag_present(skb)) {
-		swqe->tx_control |= EHEA_SWQE_VLAN_INSERT;
-		swqe->vlan_tag = vlan_tx_tag_get(skb);
-	}
-
-	pr->tx_packets++;
-	pr->tx_bytes += skb->len;
-
-	if (skb->len <= SWQE3_MAX_IMM) {
-		u32 sig_iv = port->sig_comp_iv;
-		u32 swqe_num = pr->swqe_id_counter;
-		ehea_xmit3(skb, dev, swqe);
-		swqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, EHEA_SWQE3_TYPE)
-			| EHEA_BMASK_SET(EHEA_WR_ID_COUNT, swqe_num);
-		if (pr->swqe_ll_count >= (sig_iv - 1)) {
-			swqe->wr_id |= EHEA_BMASK_SET(EHEA_WR_ID_REFILL,
-						      sig_iv);
-			swqe->tx_control |= EHEA_SWQE_SIGNALLED_COMPLETION;
-			pr->swqe_ll_count = 0;
-		} else
-			pr->swqe_ll_count += 1;
-	} else {
-		swqe->wr_id =
-			EHEA_BMASK_SET(EHEA_WR_ID_TYPE, EHEA_SWQE2_TYPE)
-		      | EHEA_BMASK_SET(EHEA_WR_ID_COUNT, pr->swqe_id_counter)
-		      | EHEA_BMASK_SET(EHEA_WR_ID_REFILL, 1)
-		      | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, pr->sq_skba.index);
-		pr->sq_skba.arr[pr->sq_skba.index] = skb;
-
-		pr->sq_skba.index++;
-		pr->sq_skba.index &= (pr->sq_skba.len - 1);
-
-		lkey = pr->send_mr.lkey;
-		ehea_xmit2(skb, dev, swqe, lkey);
-		swqe->tx_control |= EHEA_SWQE_SIGNALLED_COMPLETION;
-	}
-	pr->swqe_id_counter += 1;
-
-	netif_info(port, tx_queued, dev,
-		   "post swqe on QP %d\n", pr->qp->init_attr.qp_nr);
-	if (netif_msg_tx_queued(port))
-		ehea_dump(swqe, 512, "swqe");
-
-	if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) {
-		netif_stop_queue(dev);
-		swqe->tx_control |= EHEA_SWQE_PURGE;
-	}
-
-	ehea_post_swqe(pr->qp, swqe);
-
-	if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) {
-		spin_lock_irqsave(&pr->netif_queue, flags);
-		if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) {
-			pr->p_stats.queue_stopped++;
-			netif_stop_queue(dev);
-			pr->queue_stopped = 1;
-		}
-		spin_unlock_irqrestore(&pr->netif_queue, flags);
-	}
-	dev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
-	spin_unlock(&pr->xmit_lock);
-
-	return NETDEV_TX_OK;
-}
-
-static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	struct ehea_adapter *adapter = port->adapter;
-	struct hcp_ehea_port_cb1 *cb1;
-	int index;
-	u64 hret;
-
-	cb1 = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!cb1) {
-		pr_err("no mem for cb1\n");
-		goto out;
-	}
-
-	hret = ehea_h_query_ehea_port(adapter->handle, port->logical_port_id,
-				      H_PORT_CB1, H_PORT_CB1_ALL, cb1);
-	if (hret != H_SUCCESS) {
-		pr_err("query_ehea_port failed\n");
-		goto out;
-	}
-
-	index = (vid / 64);
-	cb1->vlan_filter[index] |= ((u64)(0x8000000000000000 >> (vid & 0x3F)));
-
-	hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
-				       H_PORT_CB1, H_PORT_CB1_ALL, cb1);
-	if (hret != H_SUCCESS)
-		pr_err("modify_ehea_port failed\n");
-out:
-	free_page((unsigned long)cb1);
-	return;
-}
-
-static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	struct ehea_adapter *adapter = port->adapter;
-	struct hcp_ehea_port_cb1 *cb1;
-	int index;
-	u64 hret;
-
-	cb1 = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!cb1) {
-		pr_err("no mem for cb1\n");
-		goto out;
-	}
-
-	hret = ehea_h_query_ehea_port(adapter->handle, port->logical_port_id,
-				      H_PORT_CB1, H_PORT_CB1_ALL, cb1);
-	if (hret != H_SUCCESS) {
-		pr_err("query_ehea_port failed\n");
-		goto out;
-	}
-
-	index = (vid / 64);
-	cb1->vlan_filter[index] &= ~((u64)(0x8000000000000000 >> (vid & 0x3F)));
-
-	hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
-				       H_PORT_CB1, H_PORT_CB1_ALL, cb1);
-	if (hret != H_SUCCESS)
-		pr_err("modify_ehea_port failed\n");
-out:
-	free_page((unsigned long)cb1);
-}
-
-int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp)
-{
-	int ret = -EIO;
-	u64 hret;
-	u16 dummy16 = 0;
-	u64 dummy64 = 0;
-	struct hcp_modify_qp_cb0 *cb0;
-
-	cb0 = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!cb0) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
-				    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
-	if (hret != H_SUCCESS) {
-		pr_err("query_ehea_qp failed (1)\n");
-		goto out;
-	}
-
-	cb0->qp_ctl_reg = H_QP_CR_STATE_INITIALIZED;
-	hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
-				     EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG, 1), cb0,
-				     &dummy64, &dummy64, &dummy16, &dummy16);
-	if (hret != H_SUCCESS) {
-		pr_err("modify_ehea_qp failed (1)\n");
-		goto out;
-	}
-
-	hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
-				    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
-	if (hret != H_SUCCESS) {
-		pr_err("query_ehea_qp failed (2)\n");
-		goto out;
-	}
-
-	cb0->qp_ctl_reg = H_QP_CR_ENABLED | H_QP_CR_STATE_INITIALIZED;
-	hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
-				     EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG, 1), cb0,
-				     &dummy64, &dummy64, &dummy16, &dummy16);
-	if (hret != H_SUCCESS) {
-		pr_err("modify_ehea_qp failed (2)\n");
-		goto out;
-	}
-
-	hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
-				    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
-	if (hret != H_SUCCESS) {
-		pr_err("query_ehea_qp failed (3)\n");
-		goto out;
-	}
-
-	cb0->qp_ctl_reg = H_QP_CR_ENABLED | H_QP_CR_STATE_RDY2SND;
-	hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
-				     EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG, 1), cb0,
-				     &dummy64, &dummy64, &dummy16, &dummy16);
-	if (hret != H_SUCCESS) {
-		pr_err("modify_ehea_qp failed (3)\n");
-		goto out;
-	}
-
-	hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
-				    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
-	if (hret != H_SUCCESS) {
-		pr_err("query_ehea_qp failed (4)\n");
-		goto out;
-	}
-
-	ret = 0;
-out:
-	free_page((unsigned long)cb0);
-	return ret;
-}
-
-static int ehea_port_res_setup(struct ehea_port *port, int def_qps,
-			       int add_tx_qps)
-{
-	int ret, i;
-	struct port_res_cfg pr_cfg, pr_cfg_small_rx;
-	enum ehea_eq_type eq_type = EHEA_EQ;
-
-	port->qp_eq = ehea_create_eq(port->adapter, eq_type,
-				   EHEA_MAX_ENTRIES_EQ, 1);
-	if (!port->qp_eq) {
-		ret = -EINVAL;
-		pr_err("ehea_create_eq failed (qp_eq)\n");
-		goto out_kill_eq;
-	}
-
-	pr_cfg.max_entries_rcq = rq1_entries + rq2_entries + rq3_entries;
-	pr_cfg.max_entries_scq = sq_entries * 2;
-	pr_cfg.max_entries_sq = sq_entries;
-	pr_cfg.max_entries_rq1 = rq1_entries;
-	pr_cfg.max_entries_rq2 = rq2_entries;
-	pr_cfg.max_entries_rq3 = rq3_entries;
-
-	pr_cfg_small_rx.max_entries_rcq = 1;
-	pr_cfg_small_rx.max_entries_scq = sq_entries;
-	pr_cfg_small_rx.max_entries_sq = sq_entries;
-	pr_cfg_small_rx.max_entries_rq1 = 1;
-	pr_cfg_small_rx.max_entries_rq2 = 1;
-	pr_cfg_small_rx.max_entries_rq3 = 1;
-
-	for (i = 0; i < def_qps; i++) {
-		ret = ehea_init_port_res(port, &port->port_res[i], &pr_cfg, i);
-		if (ret)
-			goto out_clean_pr;
-	}
-	for (i = def_qps; i < def_qps + add_tx_qps; i++) {
-		ret = ehea_init_port_res(port, &port->port_res[i],
-					 &pr_cfg_small_rx, i);
-		if (ret)
-			goto out_clean_pr;
-	}
-
-	return 0;
-
-out_clean_pr:
-	while (--i >= 0)
-		ehea_clean_portres(port, &port->port_res[i]);
-
-out_kill_eq:
-	ehea_destroy_eq(port->qp_eq);
-	return ret;
-}
-
-static int ehea_clean_all_portres(struct ehea_port *port)
-{
-	int ret = 0;
-	int i;
-
-	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
-		ret |= ehea_clean_portres(port, &port->port_res[i]);
-
-	ret |= ehea_destroy_eq(port->qp_eq);
-
-	return ret;
-}
-
-static void ehea_remove_adapter_mr(struct ehea_adapter *adapter)
-{
-	if (adapter->active_ports)
-		return;
-
-	ehea_rem_mr(&adapter->mr);
-}
-
-static int ehea_add_adapter_mr(struct ehea_adapter *adapter)
-{
-	if (adapter->active_ports)
-		return 0;
-
-	return ehea_reg_kernel_mr(adapter, &adapter->mr);
-}
-
-static int ehea_up(struct net_device *dev)
-{
-	int ret, i;
-	struct ehea_port *port = netdev_priv(dev);
-
-	if (port->state == EHEA_PORT_UP)
-		return 0;
-
-	ret = ehea_port_res_setup(port, port->num_def_qps,
-				  port->num_add_tx_qps);
-	if (ret) {
-		netdev_err(dev, "port_res_failed\n");
-		goto out;
-	}
-
-	/* Set default QP for this port */
-	ret = ehea_configure_port(port);
-	if (ret) {
-		netdev_err(dev, "ehea_configure_port failed. ret:%d\n", ret);
-		goto out_clean_pr;
-	}
-
-	ret = ehea_reg_interrupts(dev);
-	if (ret) {
-		netdev_err(dev, "reg_interrupts failed. ret:%d\n", ret);
-		goto out_clean_pr;
-	}
-
-	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
-		ret = ehea_activate_qp(port->adapter, port->port_res[i].qp);
-		if (ret) {
-			netdev_err(dev, "activate_qp failed\n");
-			goto out_free_irqs;
-		}
-	}
-
-	for (i = 0; i < port->num_def_qps; i++) {
-		ret = ehea_fill_port_res(&port->port_res[i]);
-		if (ret) {
-			netdev_err(dev, "out_free_irqs\n");
-			goto out_free_irqs;
-		}
-	}
-
-	ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
-	if (ret) {
-		ret = -EIO;
-		goto out_free_irqs;
-	}
-
-	port->state = EHEA_PORT_UP;
-
-	ret = 0;
-	goto out;
-
-out_free_irqs:
-	ehea_free_interrupts(dev);
-
-out_clean_pr:
-	ehea_clean_all_portres(port);
-out:
-	if (ret)
-		netdev_info(dev, "Failed starting. ret=%i\n", ret);
-
-	ehea_update_bcmc_registrations();
-	ehea_update_firmware_handles();
-
-	return ret;
-}
-
-static void port_napi_disable(struct ehea_port *port)
-{
-	int i;
-
-	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
-		napi_disable(&port->port_res[i].napi);
-}
-
-static void port_napi_enable(struct ehea_port *port)
-{
-	int i;
-
-	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
-		napi_enable(&port->port_res[i].napi);
-}
-
-static int ehea_open(struct net_device *dev)
-{
-	int ret;
-	struct ehea_port *port = netdev_priv(dev);
-
-	mutex_lock(&port->port_lock);
-
-	netif_info(port, ifup, dev, "enabling port\n");
-
-	ret = ehea_up(dev);
-	if (!ret) {
-		port_napi_enable(port);
-		netif_start_queue(dev);
-	}
-
-	mutex_unlock(&port->port_lock);
-
-	return ret;
-}
-
-static int ehea_down(struct net_device *dev)
-{
-	int ret;
-	struct ehea_port *port = netdev_priv(dev);
-
-	if (port->state == EHEA_PORT_DOWN)
-		return 0;
-
-	ehea_drop_multicast_list(dev);
-	ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
-
-	ehea_free_interrupts(dev);
-
-	port->state = EHEA_PORT_DOWN;
-
-	ehea_update_bcmc_registrations();
-
-	ret = ehea_clean_all_portres(port);
-	if (ret)
-		netdev_info(dev, "Failed freeing resources. ret=%i\n", ret);
-
-	ehea_update_firmware_handles();
-
-	return ret;
-}
-
-static int ehea_stop(struct net_device *dev)
-{
-	int ret;
-	struct ehea_port *port = netdev_priv(dev);
-
-	netif_info(port, ifdown, dev, "disabling port\n");
-
-	set_bit(__EHEA_DISABLE_PORT_RESET, &port->flags);
-	cancel_work_sync(&port->reset_task);
-	mutex_lock(&port->port_lock);
-	netif_stop_queue(dev);
-	port_napi_disable(port);
-	ret = ehea_down(dev);
-	mutex_unlock(&port->port_lock);
-	clear_bit(__EHEA_DISABLE_PORT_RESET, &port->flags);
-	return ret;
-}
-
-static void ehea_purge_sq(struct ehea_qp *orig_qp)
-{
-	struct ehea_qp qp = *orig_qp;
-	struct ehea_qp_init_attr *init_attr = &qp.init_attr;
-	struct ehea_swqe *swqe;
-	int wqe_index;
-	int i;
-
-	for (i = 0; i < init_attr->act_nr_send_wqes; i++) {
-		swqe = ehea_get_swqe(&qp, &wqe_index);
-		swqe->tx_control |= EHEA_SWQE_PURGE;
-	}
-}
-
-static void ehea_flush_sq(struct ehea_port *port)
-{
-	int i;
-
-	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
-		struct ehea_port_res *pr = &port->port_res[i];
-		int swqe_max = pr->sq_skba_size - 2 - pr->swqe_ll_count;
-		int ret;
-
-		ret = wait_event_timeout(port->swqe_avail_wq,
-			 atomic_read(&pr->swqe_avail) >= swqe_max,
-			 msecs_to_jiffies(100));
-
-		if (!ret) {
-			pr_err("WARNING: sq not flushed completely\n");
-			break;
-		}
-	}
-}
-
-int ehea_stop_qps(struct net_device *dev)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	struct ehea_adapter *adapter = port->adapter;
-	struct hcp_modify_qp_cb0 *cb0;
-	int ret = -EIO;
-	int dret;
-	int i;
-	u64 hret;
-	u64 dummy64 = 0;
-	u16 dummy16 = 0;
-
-	cb0 = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!cb0) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	for (i = 0; i < (port->num_def_qps + port->num_add_tx_qps); i++) {
-		struct ehea_port_res *pr =  &port->port_res[i];
-		struct ehea_qp *qp = pr->qp;
-
-		/* Purge send queue */
-		ehea_purge_sq(qp);
-
-		/* Disable queue pair */
-		hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
-					    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
-					    cb0);
-		if (hret != H_SUCCESS) {
-			pr_err("query_ehea_qp failed (1)\n");
-			goto out;
-		}
-
-		cb0->qp_ctl_reg = (cb0->qp_ctl_reg & H_QP_CR_RES_STATE) << 8;
-		cb0->qp_ctl_reg &= ~H_QP_CR_ENABLED;
-
-		hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
-					     EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG,
-							    1), cb0, &dummy64,
-					     &dummy64, &dummy16, &dummy16);
-		if (hret != H_SUCCESS) {
-			pr_err("modify_ehea_qp failed (1)\n");
-			goto out;
-		}
-
-		hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
-					    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
-					    cb0);
-		if (hret != H_SUCCESS) {
-			pr_err("query_ehea_qp failed (2)\n");
-			goto out;
-		}
-
-		/* deregister shared memory regions */
-		dret = ehea_rem_smrs(pr);
-		if (dret) {
-			pr_err("unreg shared memory region failed\n");
-			goto out;
-		}
-	}
-
-	ret = 0;
-out:
-	free_page((unsigned long)cb0);
-
-	return ret;
-}
-
-void ehea_update_rqs(struct ehea_qp *orig_qp, struct ehea_port_res *pr)
-{
-	struct ehea_qp qp = *orig_qp;
-	struct ehea_qp_init_attr *init_attr = &qp.init_attr;
-	struct ehea_rwqe *rwqe;
-	struct sk_buff **skba_rq2 = pr->rq2_skba.arr;
-	struct sk_buff **skba_rq3 = pr->rq3_skba.arr;
-	struct sk_buff *skb;
-	u32 lkey = pr->recv_mr.lkey;
-
-
-	int i;
-	int index;
-
-	for (i = 0; i < init_attr->act_nr_rwqes_rq2 + 1; i++) {
-		rwqe = ehea_get_next_rwqe(&qp, 2);
-		rwqe->sg_list[0].l_key = lkey;
-		index = EHEA_BMASK_GET(EHEA_WR_ID_INDEX, rwqe->wr_id);
-		skb = skba_rq2[index];
-		if (skb)
-			rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data);
-	}
-
-	for (i = 0; i < init_attr->act_nr_rwqes_rq3 + 1; i++) {
-		rwqe = ehea_get_next_rwqe(&qp, 3);
-		rwqe->sg_list[0].l_key = lkey;
-		index = EHEA_BMASK_GET(EHEA_WR_ID_INDEX, rwqe->wr_id);
-		skb = skba_rq3[index];
-		if (skb)
-			rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data);
-	}
-}
-
-int ehea_restart_qps(struct net_device *dev)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	struct ehea_adapter *adapter = port->adapter;
-	int ret = 0;
-	int i;
-
-	struct hcp_modify_qp_cb0 *cb0;
-	u64 hret;
-	u64 dummy64 = 0;
-	u16 dummy16 = 0;
-
-	cb0 = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!cb0) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	for (i = 0; i < (port->num_def_qps + port->num_add_tx_qps); i++) {
-		struct ehea_port_res *pr =  &port->port_res[i];
-		struct ehea_qp *qp = pr->qp;
-
-		ret = ehea_gen_smrs(pr);
-		if (ret) {
-			netdev_err(dev, "creation of shared memory regions failed\n");
-			goto out;
-		}
-
-		ehea_update_rqs(qp, pr);
-
-		/* Enable queue pair */
-		hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
-					    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
-					    cb0);
-		if (hret != H_SUCCESS) {
-			netdev_err(dev, "query_ehea_qp failed (1)\n");
-			goto out;
-		}
-
-		cb0->qp_ctl_reg = (cb0->qp_ctl_reg & H_QP_CR_RES_STATE) << 8;
-		cb0->qp_ctl_reg |= H_QP_CR_ENABLED;
-
-		hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
-					     EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG,
-							    1), cb0, &dummy64,
-					     &dummy64, &dummy16, &dummy16);
-		if (hret != H_SUCCESS) {
-			netdev_err(dev, "modify_ehea_qp failed (1)\n");
-			goto out;
-		}
-
-		hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
-					    EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
-					    cb0);
-		if (hret != H_SUCCESS) {
-			netdev_err(dev, "query_ehea_qp failed (2)\n");
-			goto out;
-		}
-
-		/* refill entire queue */
-		ehea_refill_rq1(pr, pr->rq1_skba.index, 0);
-		ehea_refill_rq2(pr, 0);
-		ehea_refill_rq3(pr, 0);
-	}
-out:
-	free_page((unsigned long)cb0);
-
-	return ret;
-}
-
-static void ehea_reset_port(struct work_struct *work)
-{
-	int ret;
-	struct ehea_port *port =
-		container_of(work, struct ehea_port, reset_task);
-	struct net_device *dev = port->netdev;
-
-	mutex_lock(&dlpar_mem_lock);
-	port->resets++;
-	mutex_lock(&port->port_lock);
-	netif_stop_queue(dev);
-
-	port_napi_disable(port);
-
-	ehea_down(dev);
-
-	ret = ehea_up(dev);
-	if (ret)
-		goto out;
-
-	ehea_set_multicast_list(dev);
-
-	netif_info(port, timer, dev, "reset successful\n");
-
-	port_napi_enable(port);
-
-	netif_wake_queue(dev);
-out:
-	mutex_unlock(&port->port_lock);
-	mutex_unlock(&dlpar_mem_lock);
-}
-
-static void ehea_rereg_mrs(void)
-{
-	int ret, i;
-	struct ehea_adapter *adapter;
-
-	pr_info("LPAR memory changed - re-initializing driver\n");
-
-	list_for_each_entry(adapter, &adapter_list, list)
-		if (adapter->active_ports) {
-			/* Shutdown all ports */
-			for (i = 0; i < EHEA_MAX_PORTS; i++) {
-				struct ehea_port *port = adapter->port[i];
-				struct net_device *dev;
-
-				if (!port)
-					continue;
-
-				dev = port->netdev;
-
-				if (dev->flags & IFF_UP) {
-					mutex_lock(&port->port_lock);
-					netif_stop_queue(dev);
-					ehea_flush_sq(port);
-					ret = ehea_stop_qps(dev);
-					if (ret) {
-						mutex_unlock(&port->port_lock);
-						goto out;
-					}
-					port_napi_disable(port);
-					mutex_unlock(&port->port_lock);
-				}
-				reset_sq_restart_flag(port);
-			}
-
-			/* Unregister old memory region */
-			ret = ehea_rem_mr(&adapter->mr);
-			if (ret) {
-				pr_err("unregister MR failed - driver inoperable!\n");
-				goto out;
-			}
-		}
-
-	clear_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
-
-	list_for_each_entry(adapter, &adapter_list, list)
-		if (adapter->active_ports) {
-			/* Register new memory region */
-			ret = ehea_reg_kernel_mr(adapter, &adapter->mr);
-			if (ret) {
-				pr_err("register MR failed - driver inoperable!\n");
-				goto out;
-			}
-
-			/* Restart all ports */
-			for (i = 0; i < EHEA_MAX_PORTS; i++) {
-				struct ehea_port *port = adapter->port[i];
-
-				if (port) {
-					struct net_device *dev = port->netdev;
-
-					if (dev->flags & IFF_UP) {
-						mutex_lock(&port->port_lock);
-						ret = ehea_restart_qps(dev);
-						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);
-					}
-				}
-			}
-		}
-	pr_info("re-initializing driver complete\n");
-out:
-	return;
-}
-
-static void ehea_tx_watchdog(struct net_device *dev)
-{
-	struct ehea_port *port = netdev_priv(dev);
-
-	if (netif_carrier_ok(dev) &&
-	    !test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))
-		ehea_schedule_port_reset(port);
-}
-
-int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
-{
-	struct hcp_query_ehea *cb;
-	u64 hret;
-	int ret;
-
-	cb = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!cb) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	hret = ehea_h_query_ehea(adapter->handle, cb);
-
-	if (hret != H_SUCCESS) {
-		ret = -EIO;
-		goto out_herr;
-	}
-
-	adapter->max_mc_mac = cb->max_mc_mac - 1;
-	ret = 0;
-
-out_herr:
-	free_page((unsigned long)cb);
-out:
-	return ret;
-}
-
-int ehea_get_jumboframe_status(struct ehea_port *port, int *jumbo)
-{
-	struct hcp_ehea_port_cb4 *cb4;
-	u64 hret;
-	int ret = 0;
-
-	*jumbo = 0;
-
-	/* (Try to) enable *jumbo frames */
-	cb4 = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!cb4) {
-		pr_err("no mem for cb4\n");
-		ret = -ENOMEM;
-		goto out;
-	} else {
-		hret = ehea_h_query_ehea_port(port->adapter->handle,
-					      port->logical_port_id,
-					      H_PORT_CB4,
-					      H_PORT_CB4_JUMBO, cb4);
-		if (hret == H_SUCCESS) {
-			if (cb4->jumbo_frame)
-				*jumbo = 1;
-			else {
-				cb4->jumbo_frame = 1;
-				hret = ehea_h_modify_ehea_port(port->adapter->
-							       handle,
-							       port->
-							       logical_port_id,
-							       H_PORT_CB4,
-							       H_PORT_CB4_JUMBO,
-							       cb4);
-				if (hret == H_SUCCESS)
-					*jumbo = 1;
-			}
-		} else
-			ret = -EINVAL;
-
-		free_page((unsigned long)cb4);
-	}
-out:
-	return ret;
-}
-
-static ssize_t ehea_show_port_id(struct device *dev,
-				 struct device_attribute *attr, char *buf)
-{
-	struct ehea_port *port = container_of(dev, struct ehea_port, ofdev.dev);
-	return sprintf(buf, "%d", port->logical_port_id);
-}
-
-static DEVICE_ATTR(log_port_id, S_IRUSR | S_IRGRP | S_IROTH, ehea_show_port_id,
-		   NULL);
-
-static void __devinit logical_port_release(struct device *dev)
-{
-	struct ehea_port *port = container_of(dev, struct ehea_port, ofdev.dev);
-	of_node_put(port->ofdev.dev.of_node);
-}
-
-static struct device *ehea_register_port(struct ehea_port *port,
-					 struct device_node *dn)
-{
-	int ret;
-
-	port->ofdev.dev.of_node = of_node_get(dn);
-	port->ofdev.dev.parent = &port->adapter->ofdev->dev;
-	port->ofdev.dev.bus = &ibmebus_bus_type;
-
-	dev_set_name(&port->ofdev.dev, "port%d", port_name_cnt++);
-	port->ofdev.dev.release = logical_port_release;
-
-	ret = of_device_register(&port->ofdev);
-	if (ret) {
-		pr_err("failed to register device. ret=%d\n", ret);
-		goto out;
-	}
-
-	ret = device_create_file(&port->ofdev.dev, &dev_attr_log_port_id);
-	if (ret) {
-		pr_err("failed to register attributes, ret=%d\n", ret);
-		goto out_unreg_of_dev;
-	}
-
-	return &port->ofdev.dev;
-
-out_unreg_of_dev:
-	of_device_unregister(&port->ofdev);
-out:
-	return NULL;
-}
-
-static void ehea_unregister_port(struct ehea_port *port)
-{
-	device_remove_file(&port->ofdev.dev, &dev_attr_log_port_id);
-	of_device_unregister(&port->ofdev);
-}
-
-static const struct net_device_ops ehea_netdev_ops = {
-	.ndo_open		= ehea_open,
-	.ndo_stop		= ehea_stop,
-	.ndo_start_xmit		= ehea_start_xmit,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= ehea_netpoll,
-#endif
-	.ndo_get_stats		= ehea_get_stats,
-	.ndo_set_mac_address	= ehea_set_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_multicast_list	= ehea_set_multicast_list,
-	.ndo_change_mtu		= ehea_change_mtu,
-	.ndo_vlan_rx_add_vid	= ehea_vlan_rx_add_vid,
-	.ndo_vlan_rx_kill_vid	= ehea_vlan_rx_kill_vid,
-	.ndo_tx_timeout		= ehea_tx_watchdog,
-};
-
-struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
-					 u32 logical_port_id,
-					 struct device_node *dn)
-{
-	int ret;
-	struct net_device *dev;
-	struct ehea_port *port;
-	struct device *port_dev;
-	int jumbo;
-
-	/* allocate memory for the port structures */
-	dev = alloc_etherdev(sizeof(struct ehea_port));
-
-	if (!dev) {
-		pr_err("no mem for net_device\n");
-		ret = -ENOMEM;
-		goto out_err;
-	}
-
-	port = netdev_priv(dev);
-
-	mutex_init(&port->port_lock);
-	port->state = EHEA_PORT_DOWN;
-	port->sig_comp_iv = sq_entries / 10;
-
-	port->adapter = adapter;
-	port->netdev = dev;
-	port->logical_port_id = logical_port_id;
-
-	port->msg_enable = netif_msg_init(msg_level, EHEA_MSG_DEFAULT);
-
-	port->mc_list = kzalloc(sizeof(struct ehea_mc_list), GFP_KERNEL);
-	if (!port->mc_list) {
-		ret = -ENOMEM;
-		goto out_free_ethdev;
-	}
-
-	INIT_LIST_HEAD(&port->mc_list->list);
-
-	ret = ehea_sense_port_attr(port);
-	if (ret)
-		goto out_free_mc_list;
-
-	port_dev = ehea_register_port(port, dn);
-	if (!port_dev)
-		goto out_free_mc_list;
-
-	SET_NETDEV_DEV(dev, port_dev);
-
-	/* initialize net_device structure */
-	memcpy(dev->dev_addr, &port->mac_addr, ETH_ALEN);
-
-	dev->netdev_ops = &ehea_netdev_ops;
-	ehea_set_ethtool_ops(dev);
-
-	dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
-		      | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_LRO;
-	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
-		      | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX
-		      | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER
-		      | NETIF_F_LLTX | NETIF_F_RXCSUM;
-	dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
-
-	if (use_lro)
-		dev->features |= NETIF_F_LRO;
-
-	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);
-		goto out_unreg_port;
-	}
-
-	port->lro_max_aggr = lro_max_aggr;
-
-	ret = ehea_get_jumboframe_status(port, &jumbo);
-	if (ret)
-		netdev_err(dev, "failed determining jumbo frame status\n");
-
-	netdev_info(dev, "Jumbo frames are %sabled\n",
-		    jumbo == 1 ? "en" : "dis");
-
-	adapter->active_ports++;
-
-	return port;
-
-out_unreg_port:
-	ehea_unregister_port(port);
-
-out_free_mc_list:
-	kfree(port->mc_list);
-
-out_free_ethdev:
-	free_netdev(dev);
-
-out_err:
-	pr_err("setting up logical port with id=%d failed, ret=%d\n",
-	       logical_port_id, ret);
-	return NULL;
-}
-
-static void ehea_shutdown_single_port(struct ehea_port *port)
-{
-	struct ehea_adapter *adapter = port->adapter;
-
-	cancel_work_sync(&port->reset_task);
-	unregister_netdev(port->netdev);
-	ehea_unregister_port(port);
-	kfree(port->mc_list);
-	free_netdev(port->netdev);
-	adapter->active_ports--;
-}
-
-static int ehea_setup_ports(struct ehea_adapter *adapter)
-{
-	struct device_node *lhea_dn;
-	struct device_node *eth_dn = NULL;
-
-	const u32 *dn_log_port_id;
-	int i = 0;
-
-	lhea_dn = adapter->ofdev->dev.of_node;
-	while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
-
-		dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
-						 NULL);
-		if (!dn_log_port_id) {
-			pr_err("bad device node: eth_dn name=%s\n",
-			       eth_dn->full_name);
-			continue;
-		}
-
-		if (ehea_add_adapter_mr(adapter)) {
-			pr_err("creating MR failed\n");
-			of_node_put(eth_dn);
-			return -EIO;
-		}
-
-		adapter->port[i] = ehea_setup_single_port(adapter,
-							  *dn_log_port_id,
-							  eth_dn);
-		if (adapter->port[i])
-			netdev_info(adapter->port[i]->netdev,
-				    "logical port id #%d\n", *dn_log_port_id);
-		else
-			ehea_remove_adapter_mr(adapter);
-
-		i++;
-	}
-	return 0;
-}
-
-static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter,
-					   u32 logical_port_id)
-{
-	struct device_node *lhea_dn;
-	struct device_node *eth_dn = NULL;
-	const u32 *dn_log_port_id;
-
-	lhea_dn = adapter->ofdev->dev.of_node;
-	while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
-
-		dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
-						 NULL);
-		if (dn_log_port_id)
-			if (*dn_log_port_id == logical_port_id)
-				return eth_dn;
-	}
-
-	return NULL;
-}
-
-static ssize_t ehea_probe_port(struct device *dev,
-			       struct device_attribute *attr,
-			       const char *buf, size_t count)
-{
-	struct ehea_adapter *adapter = dev_get_drvdata(dev);
-	struct ehea_port *port;
-	struct device_node *eth_dn = NULL;
-	int i;
-
-	u32 logical_port_id;
-
-	sscanf(buf, "%d", &logical_port_id);
-
-	port = ehea_get_port(adapter, logical_port_id);
-
-	if (port) {
-		netdev_info(port->netdev, "adding port with logical port id=%d failed: port already configured\n",
-			    logical_port_id);
-		return -EINVAL;
-	}
-
-	eth_dn = ehea_get_eth_dn(adapter, logical_port_id);
-
-	if (!eth_dn) {
-		pr_info("no logical port with id %d found\n", logical_port_id);
-		return -EINVAL;
-	}
-
-	if (ehea_add_adapter_mr(adapter)) {
-		pr_err("creating MR failed\n");
-		return -EIO;
-	}
-
-	port = ehea_setup_single_port(adapter, logical_port_id, eth_dn);
-
-	of_node_put(eth_dn);
-
-	if (port) {
-		for (i = 0; i < EHEA_MAX_PORTS; i++)
-			if (!adapter->port[i]) {
-				adapter->port[i] = port;
-				break;
-			}
-
-		netdev_info(port->netdev, "added: (logical port id=%d)\n",
-			    logical_port_id);
-	} else {
-		ehea_remove_adapter_mr(adapter);
-		return -EIO;
-	}
-
-	return (ssize_t) count;
-}
-
-static ssize_t ehea_remove_port(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t count)
-{
-	struct ehea_adapter *adapter = dev_get_drvdata(dev);
-	struct ehea_port *port;
-	int i;
-	u32 logical_port_id;
-
-	sscanf(buf, "%d", &logical_port_id);
-
-	port = ehea_get_port(adapter, logical_port_id);
-
-	if (port) {
-		netdev_info(port->netdev, "removed: (logical port id=%d)\n",
-			    logical_port_id);
-
-		ehea_shutdown_single_port(port);
-
-		for (i = 0; i < EHEA_MAX_PORTS; i++)
-			if (adapter->port[i] == port) {
-				adapter->port[i] = NULL;
-				break;
-			}
-	} else {
-		pr_err("removing port with logical port id=%d failed. port not configured.\n",
-		       logical_port_id);
-		return -EINVAL;
-	}
-
-	ehea_remove_adapter_mr(adapter);
-
-	return (ssize_t) count;
-}
-
-static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port);
-static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port);
-
-int ehea_create_device_sysfs(struct platform_device *dev)
-{
-	int ret = device_create_file(&dev->dev, &dev_attr_probe_port);
-	if (ret)
-		goto out;
-
-	ret = device_create_file(&dev->dev, &dev_attr_remove_port);
-out:
-	return ret;
-}
-
-void ehea_remove_device_sysfs(struct platform_device *dev)
-{
-	device_remove_file(&dev->dev, &dev_attr_probe_port);
-	device_remove_file(&dev->dev, &dev_attr_remove_port);
-}
-
-static int __devinit ehea_probe_adapter(struct platform_device *dev,
-					const struct of_device_id *id)
-{
-	struct ehea_adapter *adapter;
-	const u64 *adapter_handle;
-	int ret;
-
-	if (!dev || !dev->dev.of_node) {
-		pr_err("Invalid ibmebus device probed\n");
-		return -EINVAL;
-	}
-
-	adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
-	if (!adapter) {
-		ret = -ENOMEM;
-		dev_err(&dev->dev, "no mem for ehea_adapter\n");
-		goto out;
-	}
-
-	list_add(&adapter->list, &adapter_list);
-
-	adapter->ofdev = dev;
-
-	adapter_handle = of_get_property(dev->dev.of_node, "ibm,hea-handle",
-					 NULL);
-	if (adapter_handle)
-		adapter->handle = *adapter_handle;
-
-	if (!adapter->handle) {
-		dev_err(&dev->dev, "failed getting handle for adapter"
-			" '%s'\n", dev->dev.of_node->full_name);
-		ret = -ENODEV;
-		goto out_free_ad;
-	}
-
-	adapter->pd = EHEA_PD_ID;
-
-	dev_set_drvdata(&dev->dev, adapter);
-
-
-	/* initialize adapter and ports */
-	/* get adapter properties */
-	ret = ehea_sense_adapter_attr(adapter);
-	if (ret) {
-		dev_err(&dev->dev, "sense_adapter_attr failed: %d\n", ret);
-		goto out_free_ad;
-	}
-
-	adapter->neq = ehea_create_eq(adapter,
-				      EHEA_NEQ, EHEA_MAX_ENTRIES_EQ, 1);
-	if (!adapter->neq) {
-		ret = -EIO;
-		dev_err(&dev->dev, "NEQ creation failed\n");
-		goto out_free_ad;
-	}
-
-	tasklet_init(&adapter->neq_tasklet, ehea_neq_tasklet,
-		     (unsigned long)adapter);
-
-	ret = ibmebus_request_irq(adapter->neq->attr.ist1,
-				  ehea_interrupt_neq, IRQF_DISABLED,
-				  "ehea_neq", adapter);
-	if (ret) {
-		dev_err(&dev->dev, "requesting NEQ IRQ failed\n");
-		goto out_kill_eq;
-	}
-
-	ret = ehea_create_device_sysfs(dev);
-	if (ret)
-		goto out_free_irq;
-
-	ret = ehea_setup_ports(adapter);
-	if (ret) {
-		dev_err(&dev->dev, "setup_ports failed\n");
-		goto out_rem_dev_sysfs;
-	}
-
-	ret = 0;
-	goto out;
-
-out_rem_dev_sysfs:
-	ehea_remove_device_sysfs(dev);
-
-out_free_irq:
-	ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
-
-out_kill_eq:
-	ehea_destroy_eq(adapter->neq);
-
-out_free_ad:
-	list_del(&adapter->list);
-	kfree(adapter);
-
-out:
-	ehea_update_firmware_handles();
-
-	return ret;
-}
-
-static int __devexit ehea_remove(struct platform_device *dev)
-{
-	struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev);
-	int i;
-
-	for (i = 0; i < EHEA_MAX_PORTS; i++)
-		if (adapter->port[i]) {
-			ehea_shutdown_single_port(adapter->port[i]);
-			adapter->port[i] = NULL;
-		}
-
-	ehea_remove_device_sysfs(dev);
-
-	ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
-	tasklet_kill(&adapter->neq_tasklet);
-
-	ehea_destroy_eq(adapter->neq);
-	ehea_remove_adapter_mr(adapter);
-	list_del(&adapter->list);
-	kfree(adapter);
-
-	ehea_update_firmware_handles();
-
-	return 0;
-}
-
-void ehea_crash_handler(void)
-{
-	int i;
-
-	if (ehea_fw_handles.arr)
-		for (i = 0; i < ehea_fw_handles.num_entries; i++)
-			ehea_h_free_resource(ehea_fw_handles.arr[i].adh,
-					     ehea_fw_handles.arr[i].fwh,
-					     FORCE_FREE);
-
-	if (ehea_bcmc_regs.arr)
-		for (i = 0; i < ehea_bcmc_regs.num_entries; i++)
-			ehea_h_reg_dereg_bcmc(ehea_bcmc_regs.arr[i].adh,
-					      ehea_bcmc_regs.arr[i].port_id,
-					      ehea_bcmc_regs.arr[i].reg_type,
-					      ehea_bcmc_regs.arr[i].macaddr,
-					      0, H_DEREG_BCMC);
-}
-
-static int ehea_mem_notifier(struct notifier_block *nb,
-                             unsigned long action, void *data)
-{
-	int ret = NOTIFY_BAD;
-	struct memory_notify *arg = data;
-
-	mutex_lock(&dlpar_mem_lock);
-
-	switch (action) {
-	case MEM_CANCEL_OFFLINE:
-		pr_info("memory offlining canceled");
-		/* Readd canceled memory block */
-	case MEM_ONLINE:
-		pr_info("memory is going online");
-		set_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
-		if (ehea_add_sect_bmap(arg->start_pfn, arg->nr_pages))
-			goto out_unlock;
-		ehea_rereg_mrs();
-		break;
-	case MEM_GOING_OFFLINE:
-		pr_info("memory is going offline");
-		set_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
-		if (ehea_rem_sect_bmap(arg->start_pfn, arg->nr_pages))
-			goto out_unlock;
-		ehea_rereg_mrs();
-		break;
-	default:
-		break;
-	}
-
-	ehea_update_firmware_handles();
-	ret = NOTIFY_OK;
-
-out_unlock:
-	mutex_unlock(&dlpar_mem_lock);
-	return ret;
-}
-
-static struct notifier_block ehea_mem_nb = {
-	.notifier_call = ehea_mem_notifier,
-};
-
-static int ehea_reboot_notifier(struct notifier_block *nb,
-				unsigned long action, void *unused)
-{
-	if (action == SYS_RESTART) {
-		pr_info("Reboot: freeing all eHEA resources\n");
-		ibmebus_unregister_driver(&ehea_driver);
-	}
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block ehea_reboot_nb = {
-	.notifier_call = ehea_reboot_notifier,
-};
-
-static int check_module_parm(void)
-{
-	int ret = 0;
-
-	if ((rq1_entries < EHEA_MIN_ENTRIES_QP) ||
-	    (rq1_entries > EHEA_MAX_ENTRIES_RQ1)) {
-		pr_info("Bad parameter: rq1_entries\n");
-		ret = -EINVAL;
-	}
-	if ((rq2_entries < EHEA_MIN_ENTRIES_QP) ||
-	    (rq2_entries > EHEA_MAX_ENTRIES_RQ2)) {
-		pr_info("Bad parameter: rq2_entries\n");
-		ret = -EINVAL;
-	}
-	if ((rq3_entries < EHEA_MIN_ENTRIES_QP) ||
-	    (rq3_entries > EHEA_MAX_ENTRIES_RQ3)) {
-		pr_info("Bad parameter: rq3_entries\n");
-		ret = -EINVAL;
-	}
-	if ((sq_entries < EHEA_MIN_ENTRIES_QP) ||
-	    (sq_entries > EHEA_MAX_ENTRIES_SQ)) {
-		pr_info("Bad parameter: sq_entries\n");
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static ssize_t ehea_show_capabilities(struct device_driver *drv,
-				      char *buf)
-{
-	return sprintf(buf, "%d", EHEA_CAPABILITIES);
-}
-
-static DRIVER_ATTR(capabilities, S_IRUSR | S_IRGRP | S_IROTH,
-		   ehea_show_capabilities, NULL);
-
-int __init ehea_module_init(void)
-{
-	int ret;
-
-	pr_info("IBM eHEA ethernet device driver (Release %s)\n", DRV_VERSION);
-
-	memset(&ehea_fw_handles, 0, sizeof(ehea_fw_handles));
-	memset(&ehea_bcmc_regs, 0, sizeof(ehea_bcmc_regs));
-
-	mutex_init(&ehea_fw_handles.lock);
-	spin_lock_init(&ehea_bcmc_regs.lock);
-
-	ret = check_module_parm();
-	if (ret)
-		goto out;
-
-	ret = ehea_create_busmap();
-	if (ret)
-		goto out;
-
-	ret = register_reboot_notifier(&ehea_reboot_nb);
-	if (ret)
-		pr_info("failed registering reboot notifier\n");
-
-	ret = register_memory_notifier(&ehea_mem_nb);
-	if (ret)
-		pr_info("failed registering memory remove notifier\n");
-
-	ret = crash_shutdown_register(ehea_crash_handler);
-	if (ret)
-		pr_info("failed registering crash handler\n");
-
-	ret = ibmebus_register_driver(&ehea_driver);
-	if (ret) {
-		pr_err("failed registering eHEA device driver on ebus\n");
-		goto out2;
-	}
-
-	ret = driver_create_file(&ehea_driver.driver,
-				 &driver_attr_capabilities);
-	if (ret) {
-		pr_err("failed to register capabilities attribute, ret=%d\n",
-		       ret);
-		goto out3;
-	}
-
-	return ret;
-
-out3:
-	ibmebus_unregister_driver(&ehea_driver);
-out2:
-	unregister_memory_notifier(&ehea_mem_nb);
-	unregister_reboot_notifier(&ehea_reboot_nb);
-	crash_shutdown_unregister(ehea_crash_handler);
-out:
-	return ret;
-}
-
-static void __exit ehea_module_exit(void)
-{
-	int ret;
-
-	driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
-	ibmebus_unregister_driver(&ehea_driver);
-	unregister_reboot_notifier(&ehea_reboot_nb);
-	ret = crash_shutdown_unregister(ehea_crash_handler);
-	if (ret)
-		pr_info("failed unregistering crash handler\n");
-	unregister_memory_notifier(&ehea_mem_nb);
-	kfree(ehea_fw_handles.arr);
-	kfree(ehea_bcmc_regs.arr);
-	ehea_destroy_busmap();
-}
-
-module_init(ehea_module_init);
-module_exit(ehea_module_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/ehea/ehea_phyp.c linux-libre-3.2-gnu/drivers/net/ehea/ehea_phyp.c
--- linux-libre-3.1-gnu/drivers/net/ehea/ehea_phyp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/ehea/ehea_phyp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,626 +0,0 @@
-/*
- *  linux/drivers/net/ehea/ehea_phyp.c
- *
- *  eHEA ethernet device driver for IBM eServer System p
- *
- *  (C) Copyright IBM Corp. 2006
- *
- *  Authors:
- *	 Christoph Raisch <raisch@de.ibm.com>
- *	 Jan-Bernd Themann <themann@de.ibm.com>
- *	 Thomas Klein <tklein@de.ibm.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; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "ehea_phyp.h"
-
-
-static inline u16 get_order_of_qentries(u16 queue_entries)
-{
-	u8 ld = 1;		/*  logarithmus dualis */
-	while (((1U << ld) - 1) < queue_entries)
-		ld++;
-	return ld - 1;
-}
-
-/* Defines for H_CALL H_ALLOC_RESOURCE */
-#define H_ALL_RES_TYPE_QP	 1
-#define H_ALL_RES_TYPE_CQ	 2
-#define H_ALL_RES_TYPE_EQ	 3
-#define H_ALL_RES_TYPE_MR	 5
-#define H_ALL_RES_TYPE_MW	 6
-
-static long ehea_plpar_hcall_norets(unsigned long opcode,
-				    unsigned long arg1,
-				    unsigned long arg2,
-				    unsigned long arg3,
-				    unsigned long arg4,
-				    unsigned long arg5,
-				    unsigned long arg6,
-				    unsigned long arg7)
-{
-	long ret;
-	int i, sleep_msecs;
-
-	for (i = 0; i < 5; i++) {
-		ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
-					 arg5, arg6, arg7);
-
-		if (H_IS_LONG_BUSY(ret)) {
-			sleep_msecs = get_longbusy_msecs(ret);
-			msleep_interruptible(sleep_msecs);
-			continue;
-		}
-
-		if (ret < H_SUCCESS)
-			pr_err("opcode=%lx ret=%lx"
-			       " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
-			       " arg5=%lx arg6=%lx arg7=%lx\n",
-			       opcode, ret,
-			       arg1, arg2, arg3, arg4, arg5, arg6, arg7);
-
-		return ret;
-	}
-
-	return H_BUSY;
-}
-
-static long ehea_plpar_hcall9(unsigned long opcode,
-			      unsigned long *outs, /* array of 9 outputs */
-			      unsigned long arg1,
-			      unsigned long arg2,
-			      unsigned long arg3,
-			      unsigned long arg4,
-			      unsigned long arg5,
-			      unsigned long arg6,
-			      unsigned long arg7,
-			      unsigned long arg8,
-			      unsigned long arg9)
-{
-	long ret;
-	int i, sleep_msecs;
-	u8 cb_cat;
-
-	for (i = 0; i < 5; i++) {
-		ret = plpar_hcall9(opcode, outs,
-				   arg1, arg2, arg3, arg4, arg5,
-				   arg6, arg7, arg8, arg9);
-
-		if (H_IS_LONG_BUSY(ret)) {
-			sleep_msecs = get_longbusy_msecs(ret);
-			msleep_interruptible(sleep_msecs);
-			continue;
-		}
-
-		cb_cat = EHEA_BMASK_GET(H_MEHEAPORT_CAT, arg2);
-
-		if ((ret < H_SUCCESS) && !(((ret == H_AUTHORITY)
-		    && (opcode == H_MODIFY_HEA_PORT))
-		    && (((cb_cat == H_PORT_CB4) && ((arg3 == H_PORT_CB4_JUMBO)
-		    || (arg3 == H_PORT_CB4_SPEED))) || ((cb_cat == H_PORT_CB7)
-		    && (arg3 == H_PORT_CB7_DUCQPN)))))
-			pr_err("opcode=%lx ret=%lx"
-			       " arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
-			       " arg5=%lx arg6=%lx arg7=%lx arg8=%lx"
-			       " arg9=%lx"
-			       " out1=%lx out2=%lx out3=%lx out4=%lx"
-			       " out5=%lx out6=%lx out7=%lx out8=%lx"
-			       " out9=%lx\n",
-			       opcode, ret,
-			       arg1, arg2, arg3, arg4, arg5,
-			       arg6, arg7, arg8, arg9,
-			       outs[0], outs[1], outs[2], outs[3], outs[4],
-			       outs[5], outs[6], outs[7], outs[8]);
-		return ret;
-	}
-
-	return H_BUSY;
-}
-
-u64 ehea_h_query_ehea_qp(const u64 adapter_handle, const u8 qp_category,
-			 const u64 qp_handle, const u64 sel_mask, void *cb_addr)
-{
-	return ehea_plpar_hcall_norets(H_QUERY_HEA_QP,
-				       adapter_handle,		/* R4 */
-				       qp_category,		/* R5 */
-				       qp_handle,		/* R6 */
-				       sel_mask,		/* R7 */
-				       virt_to_abs(cb_addr),	/* R8 */
-				       0, 0);
-}
-
-/* input param R5 */
-#define H_ALL_RES_QP_EQPO	  EHEA_BMASK_IBM(9, 11)
-#define H_ALL_RES_QP_QPP	  EHEA_BMASK_IBM(12, 12)
-#define H_ALL_RES_QP_RQR	  EHEA_BMASK_IBM(13, 15)
-#define H_ALL_RES_QP_EQEG	  EHEA_BMASK_IBM(16, 16)
-#define H_ALL_RES_QP_LL_QP	  EHEA_BMASK_IBM(17, 17)
-#define H_ALL_RES_QP_DMA128	  EHEA_BMASK_IBM(19, 19)
-#define H_ALL_RES_QP_HSM	  EHEA_BMASK_IBM(20, 21)
-#define H_ALL_RES_QP_SIGT	  EHEA_BMASK_IBM(22, 23)
-#define H_ALL_RES_QP_TENURE	  EHEA_BMASK_IBM(48, 55)
-#define H_ALL_RES_QP_RES_TYP	  EHEA_BMASK_IBM(56, 63)
-
-/* input param R9  */
-#define H_ALL_RES_QP_TOKEN	  EHEA_BMASK_IBM(0, 31)
-#define H_ALL_RES_QP_PD		  EHEA_BMASK_IBM(32, 63)
-
-/* input param R10 */
-#define H_ALL_RES_QP_MAX_SWQE	  EHEA_BMASK_IBM(4, 7)
-#define H_ALL_RES_QP_MAX_R1WQE	  EHEA_BMASK_IBM(12, 15)
-#define H_ALL_RES_QP_MAX_R2WQE	  EHEA_BMASK_IBM(20, 23)
-#define H_ALL_RES_QP_MAX_R3WQE	  EHEA_BMASK_IBM(28, 31)
-/* Max Send Scatter Gather Elements */
-#define H_ALL_RES_QP_MAX_SSGE	  EHEA_BMASK_IBM(37, 39)
-#define H_ALL_RES_QP_MAX_R1SGE	  EHEA_BMASK_IBM(45, 47)
-/* Max Receive SG Elements RQ1 */
-#define H_ALL_RES_QP_MAX_R2SGE	  EHEA_BMASK_IBM(53, 55)
-#define H_ALL_RES_QP_MAX_R3SGE	  EHEA_BMASK_IBM(61, 63)
-
-/* input param R11 */
-#define H_ALL_RES_QP_SWQE_IDL	  EHEA_BMASK_IBM(0, 7)
-/* max swqe immediate data length */
-#define H_ALL_RES_QP_PORT_NUM	  EHEA_BMASK_IBM(48, 63)
-
-/* input param R12 */
-#define H_ALL_RES_QP_TH_RQ2	  EHEA_BMASK_IBM(0, 15)
-/* Threshold RQ2 */
-#define H_ALL_RES_QP_TH_RQ3	  EHEA_BMASK_IBM(16, 31)
-/* Threshold RQ3 */
-
-/* output param R6 */
-#define H_ALL_RES_QP_ACT_SWQE	  EHEA_BMASK_IBM(0, 15)
-#define H_ALL_RES_QP_ACT_R1WQE	  EHEA_BMASK_IBM(16, 31)
-#define H_ALL_RES_QP_ACT_R2WQE	  EHEA_BMASK_IBM(32, 47)
-#define H_ALL_RES_QP_ACT_R3WQE	  EHEA_BMASK_IBM(48, 63)
-
-/* output param, R7 */
-#define H_ALL_RES_QP_ACT_SSGE	  EHEA_BMASK_IBM(0, 7)
-#define H_ALL_RES_QP_ACT_R1SGE	  EHEA_BMASK_IBM(8, 15)
-#define H_ALL_RES_QP_ACT_R2SGE	  EHEA_BMASK_IBM(16, 23)
-#define H_ALL_RES_QP_ACT_R3SGE	  EHEA_BMASK_IBM(24, 31)
-#define H_ALL_RES_QP_ACT_SWQE_IDL EHEA_BMASK_IBM(32, 39)
-
-/* output param R8,R9 */
-#define H_ALL_RES_QP_SIZE_SQ	  EHEA_BMASK_IBM(0, 31)
-#define H_ALL_RES_QP_SIZE_RQ1	  EHEA_BMASK_IBM(32, 63)
-#define H_ALL_RES_QP_SIZE_RQ2	  EHEA_BMASK_IBM(0, 31)
-#define H_ALL_RES_QP_SIZE_RQ3	  EHEA_BMASK_IBM(32, 63)
-
-/* output param R11,R12 */
-#define H_ALL_RES_QP_LIOBN_SQ	  EHEA_BMASK_IBM(0, 31)
-#define H_ALL_RES_QP_LIOBN_RQ1	  EHEA_BMASK_IBM(32, 63)
-#define H_ALL_RES_QP_LIOBN_RQ2	  EHEA_BMASK_IBM(0, 31)
-#define H_ALL_RES_QP_LIOBN_RQ3	  EHEA_BMASK_IBM(32, 63)
-
-u64 ehea_h_alloc_resource_qp(const u64 adapter_handle,
-			     struct ehea_qp_init_attr *init_attr, const u32 pd,
-			     u64 *qp_handle, struct h_epas *h_epas)
-{
-	u64 hret;
-	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-	u64 allocate_controls =
-	    EHEA_BMASK_SET(H_ALL_RES_QP_EQPO, init_attr->low_lat_rq1 ? 1 : 0)
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_QPP, 0)
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_RQR, 6)	/* rq1 & rq2 & rq3 */
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_EQEG, 0)	/* EQE gen. disabled */
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_LL_QP, init_attr->low_lat_rq1)
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_DMA128, 0)
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_HSM, 0)
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_SIGT, init_attr->signalingtype)
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_RES_TYP, H_ALL_RES_TYPE_QP);
-
-	u64 r9_reg = EHEA_BMASK_SET(H_ALL_RES_QP_PD, pd)
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_TOKEN, init_attr->qp_token);
-
-	u64 max_r10_reg =
-	    EHEA_BMASK_SET(H_ALL_RES_QP_MAX_SWQE,
-			   get_order_of_qentries(init_attr->max_nr_send_wqes))
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_MAX_R1WQE,
-			     get_order_of_qentries(init_attr->max_nr_rwqes_rq1))
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_MAX_R2WQE,
-			     get_order_of_qentries(init_attr->max_nr_rwqes_rq2))
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_MAX_R3WQE,
-			     get_order_of_qentries(init_attr->max_nr_rwqes_rq3))
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_MAX_SSGE, init_attr->wqe_size_enc_sq)
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_MAX_R1SGE,
-			     init_attr->wqe_size_enc_rq1)
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_MAX_R2SGE,
-			     init_attr->wqe_size_enc_rq2)
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_MAX_R3SGE,
-			     init_attr->wqe_size_enc_rq3);
-
-	u64 r11_in =
-	    EHEA_BMASK_SET(H_ALL_RES_QP_SWQE_IDL, init_attr->swqe_imm_data_len)
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_PORT_NUM, init_attr->port_nr);
-	u64 threshold =
-	    EHEA_BMASK_SET(H_ALL_RES_QP_TH_RQ2, init_attr->rq2_threshold)
-	    | EHEA_BMASK_SET(H_ALL_RES_QP_TH_RQ3, init_attr->rq3_threshold);
-
-	hret = ehea_plpar_hcall9(H_ALLOC_HEA_RESOURCE,
-				 outs,
-				 adapter_handle,		/* R4 */
-				 allocate_controls,		/* R5 */
-				 init_attr->send_cq_handle,	/* R6 */
-				 init_attr->recv_cq_handle,	/* R7 */
-				 init_attr->aff_eq_handle,	/* R8 */
-				 r9_reg,			/* R9 */
-				 max_r10_reg,			/* R10 */
-				 r11_in,			/* R11 */
-				 threshold);			/* R12 */
-
-	*qp_handle = outs[0];
-	init_attr->qp_nr = (u32)outs[1];
-
-	init_attr->act_nr_send_wqes =
-	    (u16)EHEA_BMASK_GET(H_ALL_RES_QP_ACT_SWQE, outs[2]);
-	init_attr->act_nr_rwqes_rq1 =
-	    (u16)EHEA_BMASK_GET(H_ALL_RES_QP_ACT_R1WQE, outs[2]);
-	init_attr->act_nr_rwqes_rq2 =
-	    (u16)EHEA_BMASK_GET(H_ALL_RES_QP_ACT_R2WQE, outs[2]);
-	init_attr->act_nr_rwqes_rq3 =
-	    (u16)EHEA_BMASK_GET(H_ALL_RES_QP_ACT_R3WQE, outs[2]);
-
-	init_attr->act_wqe_size_enc_sq = init_attr->wqe_size_enc_sq;
-	init_attr->act_wqe_size_enc_rq1 = init_attr->wqe_size_enc_rq1;
-	init_attr->act_wqe_size_enc_rq2 = init_attr->wqe_size_enc_rq2;
-	init_attr->act_wqe_size_enc_rq3 = init_attr->wqe_size_enc_rq3;
-
-	init_attr->nr_sq_pages =
-	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_SIZE_SQ, outs[4]);
-	init_attr->nr_rq1_pages =
-	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_SIZE_RQ1, outs[4]);
-	init_attr->nr_rq2_pages =
-	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_SIZE_RQ2, outs[5]);
-	init_attr->nr_rq3_pages =
-	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_SIZE_RQ3, outs[5]);
-
-	init_attr->liobn_sq =
-	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_LIOBN_SQ, outs[7]);
-	init_attr->liobn_rq1 =
-	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_LIOBN_RQ1, outs[7]);
-	init_attr->liobn_rq2 =
-	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_LIOBN_RQ2, outs[8]);
-	init_attr->liobn_rq3 =
-	    (u32)EHEA_BMASK_GET(H_ALL_RES_QP_LIOBN_RQ3, outs[8]);
-
-	if (!hret)
-		hcp_epas_ctor(h_epas, outs[6], outs[6]);
-
-	return hret;
-}
-
-u64 ehea_h_alloc_resource_cq(const u64 adapter_handle,
-			     struct ehea_cq_attr *cq_attr,
-			     u64 *cq_handle, struct h_epas *epas)
-{
-	u64 hret;
-	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-	hret = ehea_plpar_hcall9(H_ALLOC_HEA_RESOURCE,
-				 outs,
-				 adapter_handle,		/* R4 */
-				 H_ALL_RES_TYPE_CQ,		/* R5 */
-				 cq_attr->eq_handle,		/* R6 */
-				 cq_attr->cq_token,		/* R7 */
-				 cq_attr->max_nr_of_cqes,	/* R8 */
-				 0, 0, 0, 0);			/* R9-R12 */
-
-	*cq_handle = outs[0];
-	cq_attr->act_nr_of_cqes = outs[3];
-	cq_attr->nr_pages = outs[4];
-
-	if (!hret)
-		hcp_epas_ctor(epas, outs[5], outs[6]);
-
-	return hret;
-}
-
-/* Defines for H_CALL H_ALLOC_RESOURCE */
-#define H_ALL_RES_TYPE_QP	 1
-#define H_ALL_RES_TYPE_CQ	 2
-#define H_ALL_RES_TYPE_EQ	 3
-#define H_ALL_RES_TYPE_MR	 5
-#define H_ALL_RES_TYPE_MW	 6
-
-/*  input param R5 */
-#define H_ALL_RES_EQ_NEQ	     EHEA_BMASK_IBM(0, 0)
-#define H_ALL_RES_EQ_NON_NEQ_ISN     EHEA_BMASK_IBM(6, 7)
-#define H_ALL_RES_EQ_INH_EQE_GEN     EHEA_BMASK_IBM(16, 16)
-#define H_ALL_RES_EQ_RES_TYPE	     EHEA_BMASK_IBM(56, 63)
-/*  input param R6 */
-#define H_ALL_RES_EQ_MAX_EQE	     EHEA_BMASK_IBM(32, 63)
-
-/*  output param R6 */
-#define H_ALL_RES_EQ_LIOBN	     EHEA_BMASK_IBM(32, 63)
-
-/*  output param R7 */
-#define H_ALL_RES_EQ_ACT_EQE	     EHEA_BMASK_IBM(32, 63)
-
-/*  output param R8 */
-#define H_ALL_RES_EQ_ACT_PS	     EHEA_BMASK_IBM(32, 63)
-
-/*  output param R9 */
-#define H_ALL_RES_EQ_ACT_EQ_IST_C    EHEA_BMASK_IBM(30, 31)
-#define H_ALL_RES_EQ_ACT_EQ_IST_1    EHEA_BMASK_IBM(40, 63)
-
-/*  output param R10 */
-#define H_ALL_RES_EQ_ACT_EQ_IST_2    EHEA_BMASK_IBM(40, 63)
-
-/*  output param R11 */
-#define H_ALL_RES_EQ_ACT_EQ_IST_3    EHEA_BMASK_IBM(40, 63)
-
-/*  output param R12 */
-#define H_ALL_RES_EQ_ACT_EQ_IST_4    EHEA_BMASK_IBM(40, 63)
-
-u64 ehea_h_alloc_resource_eq(const u64 adapter_handle,
-			     struct ehea_eq_attr *eq_attr, u64 *eq_handle)
-{
-	u64 hret, allocate_controls;
-	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-	/* resource type */
-	allocate_controls =
-	    EHEA_BMASK_SET(H_ALL_RES_EQ_RES_TYPE, H_ALL_RES_TYPE_EQ)
-	    | EHEA_BMASK_SET(H_ALL_RES_EQ_NEQ, eq_attr->type ? 1 : 0)
-	    | EHEA_BMASK_SET(H_ALL_RES_EQ_INH_EQE_GEN, !eq_attr->eqe_gen)
-	    | EHEA_BMASK_SET(H_ALL_RES_EQ_NON_NEQ_ISN, 1);
-
-	hret = ehea_plpar_hcall9(H_ALLOC_HEA_RESOURCE,
-				 outs,
-				 adapter_handle,		/* R4 */
-				 allocate_controls,		/* R5 */
-				 eq_attr->max_nr_of_eqes,	/* R6 */
-				 0, 0, 0, 0, 0, 0);		/* R7-R10 */
-
-	*eq_handle = outs[0];
-	eq_attr->act_nr_of_eqes = outs[3];
-	eq_attr->nr_pages = outs[4];
-	eq_attr->ist1 = outs[5];
-	eq_attr->ist2 = outs[6];
-	eq_attr->ist3 = outs[7];
-	eq_attr->ist4 = outs[8];
-
-	return hret;
-}
-
-u64 ehea_h_modify_ehea_qp(const u64 adapter_handle, const u8 cat,
-			  const u64 qp_handle, const u64 sel_mask,
-			  void *cb_addr, u64 *inv_attr_id, u64 *proc_mask,
-			  u16 *out_swr, u16 *out_rwr)
-{
-	u64 hret;
-	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-	hret = ehea_plpar_hcall9(H_MODIFY_HEA_QP,
-				 outs,
-				 adapter_handle,		/* R4 */
-				 (u64) cat,			/* R5 */
-				 qp_handle,			/* R6 */
-				 sel_mask,			/* R7 */
-				 virt_to_abs(cb_addr),		/* R8 */
-				 0, 0, 0, 0);			/* R9-R12 */
-
-	*inv_attr_id = outs[0];
-	*out_swr = outs[3];
-	*out_rwr = outs[4];
-	*proc_mask = outs[5];
-
-	return hret;
-}
-
-u64 ehea_h_register_rpage(const u64 adapter_handle, const u8 pagesize,
-			  const u8 queue_type, const u64 resource_handle,
-			  const u64 log_pageaddr, u64 count)
-{
-	u64  reg_control;
-
-	reg_control = EHEA_BMASK_SET(H_REG_RPAGE_PAGE_SIZE, pagesize)
-		    | EHEA_BMASK_SET(H_REG_RPAGE_QT, queue_type);
-
-	return ehea_plpar_hcall_norets(H_REGISTER_HEA_RPAGES,
-				       adapter_handle,		/* R4 */
-				       reg_control,		/* R5 */
-				       resource_handle,		/* R6 */
-				       log_pageaddr,		/* R7 */
-				       count,			/* R8 */
-				       0, 0);			/* R9-R10 */
-}
-
-u64 ehea_h_register_smr(const u64 adapter_handle, const u64 orig_mr_handle,
-			const u64 vaddr_in, const u32 access_ctrl, const u32 pd,
-			struct ehea_mr *mr)
-{
-	u64 hret;
-	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-	hret = ehea_plpar_hcall9(H_REGISTER_SMR,
-				 outs,
-				 adapter_handle	      ,		 /* R4 */
-				 orig_mr_handle,		 /* R5 */
-				 vaddr_in,			 /* R6 */
-				 (((u64)access_ctrl) << 32ULL),	 /* R7 */
-				 pd,				 /* R8 */
-				 0, 0, 0, 0);			 /* R9-R12 */
-
-	mr->handle = outs[0];
-	mr->lkey = (u32)outs[2];
-
-	return hret;
-}
-
-u64 ehea_h_disable_and_get_hea(const u64 adapter_handle, const u64 qp_handle)
-{
-	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-	return ehea_plpar_hcall9(H_DISABLE_AND_GET_HEA,
-				 outs,
-				 adapter_handle,		/* R4 */
-				 H_DISABLE_GET_EHEA_WQE_P,	/* R5 */
-				 qp_handle,			/* R6 */
-				 0, 0, 0, 0, 0, 0);		/* R7-R12 */
-}
-
-u64 ehea_h_free_resource(const u64 adapter_handle, const u64 res_handle,
-			 u64 force_bit)
-{
-	return ehea_plpar_hcall_norets(H_FREE_RESOURCE,
-				       adapter_handle,	   /* R4 */
-				       res_handle,	   /* R5 */
-				       force_bit,
-				       0, 0, 0, 0);	   /* R7-R10 */
-}
-
-u64 ehea_h_alloc_resource_mr(const u64 adapter_handle, const u64 vaddr,
-			     const u64 length, const u32 access_ctrl,
-			     const u32 pd, u64 *mr_handle, u32 *lkey)
-{
-	u64 hret;
-	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-	hret = ehea_plpar_hcall9(H_ALLOC_HEA_RESOURCE,
-				 outs,
-				 adapter_handle,		   /* R4 */
-				 5,				   /* R5 */
-				 vaddr,				   /* R6 */
-				 length,			   /* R7 */
-				 (((u64) access_ctrl) << 32ULL),   /* R8 */
-				 pd,				   /* R9 */
-				 0, 0, 0);			   /* R10-R12 */
-
-	*mr_handle = outs[0];
-	*lkey = (u32)outs[2];
-	return hret;
-}
-
-u64 ehea_h_register_rpage_mr(const u64 adapter_handle, const u64 mr_handle,
-			     const u8 pagesize, const u8 queue_type,
-			     const u64 log_pageaddr, const u64 count)
-{
-	if ((count > 1) && (log_pageaddr & ~PAGE_MASK)) {
-		pr_err("not on pageboundary\n");
-		return H_PARAMETER;
-	}
-
-	return ehea_h_register_rpage(adapter_handle, pagesize,
-				     queue_type, mr_handle,
-				     log_pageaddr, count);
-}
-
-u64 ehea_h_query_ehea(const u64 adapter_handle, void *cb_addr)
-{
-	u64 hret, cb_logaddr;
-
-	cb_logaddr = virt_to_abs(cb_addr);
-
-	hret = ehea_plpar_hcall_norets(H_QUERY_HEA,
-				       adapter_handle,		/* R4 */
-				       cb_logaddr,		/* R5 */
-				       0, 0, 0, 0, 0);		/* R6-R10 */
-#ifdef DEBUG
-	ehea_dump(cb_addr, sizeof(struct hcp_query_ehea), "hcp_query_ehea");
-#endif
-	return hret;
-}
-
-u64 ehea_h_query_ehea_port(const u64 adapter_handle, const u16 port_num,
-			   const u8 cb_cat, const u64 select_mask,
-			   void *cb_addr)
-{
-	u64 port_info;
-	u64 cb_logaddr = virt_to_abs(cb_addr);
-	u64 arr_index = 0;
-
-	port_info = EHEA_BMASK_SET(H_MEHEAPORT_CAT, cb_cat)
-		  | EHEA_BMASK_SET(H_MEHEAPORT_PN, port_num);
-
-	return ehea_plpar_hcall_norets(H_QUERY_HEA_PORT,
-				       adapter_handle,		/* R4 */
-				       port_info,		/* R5 */
-				       select_mask,		/* R6 */
-				       arr_index,		/* R7 */
-				       cb_logaddr,		/* R8 */
-				       0, 0);			/* R9-R10 */
-}
-
-u64 ehea_h_modify_ehea_port(const u64 adapter_handle, const u16 port_num,
-			    const u8 cb_cat, const u64 select_mask,
-			    void *cb_addr)
-{
-	unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-	u64 port_info;
-	u64 arr_index = 0;
-	u64 cb_logaddr = virt_to_abs(cb_addr);
-
-	port_info = EHEA_BMASK_SET(H_MEHEAPORT_CAT, cb_cat)
-		  | EHEA_BMASK_SET(H_MEHEAPORT_PN, port_num);
-#ifdef DEBUG
-	ehea_dump(cb_addr, sizeof(struct hcp_ehea_port_cb0), "Before HCALL");
-#endif
-	return ehea_plpar_hcall9(H_MODIFY_HEA_PORT,
-				 outs,
-				 adapter_handle,		/* R4 */
-				 port_info,			/* R5 */
-				 select_mask,			/* R6 */
-				 arr_index,			/* R7 */
-				 cb_logaddr,			/* R8 */
-				 0, 0, 0, 0);			/* R9-R12 */
-}
-
-u64 ehea_h_reg_dereg_bcmc(const u64 adapter_handle, const u16 port_num,
-			  const u8 reg_type, const u64 mc_mac_addr,
-			  const u16 vlan_id, const u32 hcall_id)
-{
-	u64 r5_port_num, r6_reg_type, r7_mc_mac_addr, r8_vlan_id;
-	u64 mac_addr = mc_mac_addr >> 16;
-
-	r5_port_num = EHEA_BMASK_SET(H_REGBCMC_PN, port_num);
-	r6_reg_type = EHEA_BMASK_SET(H_REGBCMC_REGTYPE, reg_type);
-	r7_mc_mac_addr = EHEA_BMASK_SET(H_REGBCMC_MACADDR, mac_addr);
-	r8_vlan_id = EHEA_BMASK_SET(H_REGBCMC_VLANID, vlan_id);
-
-	return ehea_plpar_hcall_norets(hcall_id,
-				       adapter_handle,		/* R4 */
-				       r5_port_num,		/* R5 */
-				       r6_reg_type,		/* R6 */
-				       r7_mc_mac_addr,		/* R7 */
-				       r8_vlan_id,		/* R8 */
-				       0, 0);			/* R9-R12 */
-}
-
-u64 ehea_h_reset_events(const u64 adapter_handle, const u64 neq_handle,
-			const u64 event_mask)
-{
-	return ehea_plpar_hcall_norets(H_RESET_EVENTS,
-				       adapter_handle,		/* R4 */
-				       neq_handle,		/* R5 */
-				       event_mask,		/* R6 */
-				       0, 0, 0, 0);		/* R7-R12 */
-}
-
-u64 ehea_h_error_data(const u64 adapter_handle, const u64 ressource_handle,
-		      void *rblock)
-{
-	return ehea_plpar_hcall_norets(H_ERROR_DATA,
-				       adapter_handle,		/* R4 */
-				       ressource_handle,	/* R5 */
-				       virt_to_abs(rblock),	/* R6 */
-				       0, 0, 0, 0);		/* R7-R12 */
-}
diff -druN linux-libre-3.1-gnu/drivers/net/ehea/ehea_phyp.h linux-libre-3.2-gnu/drivers/net/ehea/ehea_phyp.h
--- linux-libre-3.1-gnu/drivers/net/ehea/ehea_phyp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/ehea/ehea_phyp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,467 +0,0 @@
-/*
- *  linux/drivers/net/ehea/ehea_phyp.h
- *
- *  eHEA ethernet device driver for IBM eServer System p
- *
- *  (C) Copyright IBM Corp. 2006
- *
- *  Authors:
- *       Christoph Raisch <raisch@de.ibm.com>
- *       Jan-Bernd Themann <themann@de.ibm.com>
- *       Thomas Klein <tklein@de.ibm.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; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __EHEA_PHYP_H__
-#define __EHEA_PHYP_H__
-
-#include <linux/delay.h>
-#include <asm/hvcall.h>
-#include "ehea.h"
-#include "ehea_hw.h"
-
-/* Some abbreviations used here:
- *
- * hcp_*  - structures, variables and functions releated to Hypervisor Calls
- */
-
-static inline u32 get_longbusy_msecs(int long_busy_ret_code)
-{
-	switch (long_busy_ret_code) {
-	case H_LONG_BUSY_ORDER_1_MSEC:
-		return 1;
-	case H_LONG_BUSY_ORDER_10_MSEC:
-		return 10;
-	case H_LONG_BUSY_ORDER_100_MSEC:
-		return 100;
-	case H_LONG_BUSY_ORDER_1_SEC:
-		return 1000;
-	case H_LONG_BUSY_ORDER_10_SEC:
-		return 10000;
-	case H_LONG_BUSY_ORDER_100_SEC:
-		return 100000;
-	default:
-		return 1;
-	}
-}
-
-/* Number of pages which can be registered at once by H_REGISTER_HEA_RPAGES */
-#define EHEA_MAX_RPAGE 512
-
-/* Notification Event Queue (NEQ) Entry bit masks */
-#define NEQE_EVENT_CODE		EHEA_BMASK_IBM(2, 7)
-#define NEQE_PORTNUM  		EHEA_BMASK_IBM(32, 47)
-#define NEQE_PORT_UP		EHEA_BMASK_IBM(16, 16)
-#define NEQE_EXTSWITCH_PORT_UP	EHEA_BMASK_IBM(17, 17)
-#define NEQE_EXTSWITCH_PRIMARY	EHEA_BMASK_IBM(18, 18)
-#define NEQE_PLID		EHEA_BMASK_IBM(16, 47)
-
-/* Notification Event Codes */
-#define EHEA_EC_PORTSTATE_CHG	0x30
-#define EHEA_EC_ADAPTER_MALFUNC	0x32
-#define EHEA_EC_PORT_MALFUNC	0x33
-
-/* Notification Event Log Register (NELR) bit masks */
-#define NELR_PORT_MALFUNC	EHEA_BMASK_IBM(61, 61)
-#define NELR_ADAPTER_MALFUNC	EHEA_BMASK_IBM(62, 62)
-#define NELR_PORTSTATE_CHG	EHEA_BMASK_IBM(63, 63)
-
-static inline void hcp_epas_ctor(struct h_epas *epas, u64 paddr_kernel,
-				 u64 paddr_user)
-{
-	/* To support 64k pages we must round to 64k page boundary */
-	epas->kernel.addr = ioremap((paddr_kernel & PAGE_MASK), PAGE_SIZE) +
-			    (paddr_kernel & ~PAGE_MASK);
-	epas->user.addr = paddr_user;
-}
-
-static inline void hcp_epas_dtor(struct h_epas *epas)
-{
-	if (epas->kernel.addr)
-		iounmap((void __iomem *)((u64)epas->kernel.addr & PAGE_MASK));
-
-	epas->user.addr = 0;
-	epas->kernel.addr = 0;
-}
-
-struct hcp_modify_qp_cb0 {
-	u64 qp_ctl_reg;		/* 00 */
-	u32 max_swqe;		/* 02 */
-	u32 max_rwqe;		/* 03 */
-	u32 port_nb;		/* 04 */
-	u32 reserved0;		/* 05 */
-	u64 qp_aer;		/* 06 */
-	u64 qp_tenure;		/* 08 */
-};
-
-/* Hcall Query/Modify Queue Pair Control Block 0 Selection Mask Bits */
-#define H_QPCB0_ALL             EHEA_BMASK_IBM(0, 5)
-#define H_QPCB0_QP_CTL_REG      EHEA_BMASK_IBM(0, 0)
-#define H_QPCB0_MAX_SWQE        EHEA_BMASK_IBM(1, 1)
-#define H_QPCB0_MAX_RWQE        EHEA_BMASK_IBM(2, 2)
-#define H_QPCB0_PORT_NB         EHEA_BMASK_IBM(3, 3)
-#define H_QPCB0_QP_AER          EHEA_BMASK_IBM(4, 4)
-#define H_QPCB0_QP_TENURE       EHEA_BMASK_IBM(5, 5)
-
-/* Queue Pair Control Register Status Bits */
-#define H_QP_CR_ENABLED		    0x8000000000000000ULL /* QP enabled */
-							  /* QP States: */
-#define H_QP_CR_STATE_RESET	    0x0000010000000000ULL /*  Reset */
-#define H_QP_CR_STATE_INITIALIZED   0x0000020000000000ULL /*  Initialized */
-#define H_QP_CR_STATE_RDY2RCV	    0x0000030000000000ULL /*  Ready to recv */
-#define H_QP_CR_STATE_RDY2SND	    0x0000050000000000ULL /*  Ready to send */
-#define H_QP_CR_STATE_ERROR	    0x0000800000000000ULL /*  Error */
-#define H_QP_CR_RES_STATE 	    0x0000007F00000000ULL /* Resultant state */
-
-struct hcp_modify_qp_cb1 {
-	u32 qpn;		/* 00 */
-	u32 qp_asyn_ev_eq_nb;	/* 01 */
-	u64 sq_cq_handle;	/* 02 */
-	u64 rq_cq_handle;	/* 04 */
-	/* sgel = scatter gather element */
-	u32 sgel_nb_sq;		/* 06 */
-	u32 sgel_nb_rq1;	/* 07 */
-	u32 sgel_nb_rq2;	/* 08 */
-	u32 sgel_nb_rq3;	/* 09 */
-};
-
-/* Hcall Query/Modify Queue Pair Control Block 1 Selection Mask Bits */
-#define H_QPCB1_ALL             EHEA_BMASK_IBM(0, 7)
-#define H_QPCB1_QPN             EHEA_BMASK_IBM(0, 0)
-#define H_QPCB1_ASYN_EV_EQ_NB   EHEA_BMASK_IBM(1, 1)
-#define H_QPCB1_SQ_CQ_HANDLE    EHEA_BMASK_IBM(2, 2)
-#define H_QPCB1_RQ_CQ_HANDLE    EHEA_BMASK_IBM(3, 3)
-#define H_QPCB1_SGEL_NB_SQ      EHEA_BMASK_IBM(4, 4)
-#define H_QPCB1_SGEL_NB_RQ1     EHEA_BMASK_IBM(5, 5)
-#define H_QPCB1_SGEL_NB_RQ2     EHEA_BMASK_IBM(6, 6)
-#define H_QPCB1_SGEL_NB_RQ3     EHEA_BMASK_IBM(7, 7)
-
-struct hcp_query_ehea {
-	u32 cur_num_qps;		/* 00 */
-	u32 cur_num_cqs;		/* 01 */
-	u32 cur_num_eqs;		/* 02 */
-	u32 cur_num_mrs;		/* 03 */
-	u32 auth_level;			/* 04 */
-	u32 max_num_qps;		/* 05 */
-	u32 max_num_cqs;		/* 06 */
-	u32 max_num_eqs;		/* 07 */
-	u32 max_num_mrs;		/* 08 */
-	u32 reserved0;			/* 09 */
-	u32 int_clock_freq;		/* 10 */
-	u32 max_num_pds;		/* 11 */
-	u32 max_num_addr_handles;	/* 12 */
-	u32 max_num_cqes;		/* 13 */
-	u32 max_num_wqes;		/* 14 */
-	u32 max_num_sgel_rq1wqe;	/* 15 */
-	u32 max_num_sgel_rq2wqe;	/* 16 */
-	u32 max_num_sgel_rq3wqe;	/* 17 */
-	u32 mr_page_size;		/* 18 */
-	u32 reserved1;			/* 19 */
-	u64 max_mr_size;		/* 20 */
-	u64 reserved2;			/* 22 */
-	u32 num_ports;			/* 24 */
-	u32 reserved3;			/* 25 */
-	u32 reserved4;			/* 26 */
-	u32 reserved5;			/* 27 */
-	u64 max_mc_mac;			/* 28 */
-	u64 ehea_cap;			/* 30 */
-	u32 max_isn_per_eq;		/* 32 */
-	u32 max_num_neq;		/* 33 */
-	u64 max_num_vlan_ids;		/* 34 */
-	u32 max_num_port_group;		/* 36 */
-	u32 max_num_phys_port;		/* 37 */
-
-};
-
-/* Hcall Query/Modify Port Control Block defines */
-#define H_PORT_CB0	 0
-#define H_PORT_CB1	 1
-#define H_PORT_CB2	 2
-#define H_PORT_CB3	 3
-#define H_PORT_CB4	 4
-#define H_PORT_CB5	 5
-#define H_PORT_CB6	 6
-#define H_PORT_CB7	 7
-
-struct hcp_ehea_port_cb0 {
-	u64 port_mac_addr;
-	u64 port_rc;
-	u64 reserved0;
-	u32 port_op_state;
-	u32 port_speed;
-	u32 ext_swport_op_state;
-	u32 neg_tpf_prpf;
-	u32 num_default_qps;
-	u32 reserved1;
-	u64 default_qpn_arr[16];
-};
-
-/* Hcall Query/Modify Port Control Block 0 Selection Mask Bits */
-#define H_PORT_CB0_ALL		EHEA_BMASK_IBM(0, 7)    /* Set all bits */
-#define H_PORT_CB0_MAC		EHEA_BMASK_IBM(0, 0)    /* MAC address */
-#define H_PORT_CB0_PRC		EHEA_BMASK_IBM(1, 1)    /* Port Recv Control */
-#define H_PORT_CB0_DEFQPNARRAY	EHEA_BMASK_IBM(7, 7)    /* Default QPN Array */
-
-/*  Hcall Query Port: Returned port speed values */
-#define H_SPEED_10M_H	1	/*  10 Mbps, Half Duplex */
-#define H_SPEED_10M_F	2	/*  10 Mbps, Full Duplex */
-#define H_SPEED_100M_H	3	/* 100 Mbps, Half Duplex */
-#define H_SPEED_100M_F	4	/* 100 Mbps, Full Duplex */
-#define H_SPEED_1G_F	6	/*   1 Gbps, Full Duplex */
-#define H_SPEED_10G_F	8	/*  10 Gbps, Full Duplex */
-
-/* Port Receive Control Status Bits */
-#define PXLY_RC_VALID           EHEA_BMASK_IBM(49, 49)
-#define PXLY_RC_VLAN_XTRACT     EHEA_BMASK_IBM(50, 50)
-#define PXLY_RC_TCP_6_TUPLE     EHEA_BMASK_IBM(51, 51)
-#define PXLY_RC_UDP_6_TUPLE     EHEA_BMASK_IBM(52, 52)
-#define PXLY_RC_TCP_3_TUPLE     EHEA_BMASK_IBM(53, 53)
-#define PXLY_RC_TCP_2_TUPLE     EHEA_BMASK_IBM(54, 54)
-#define PXLY_RC_LLC_SNAP        EHEA_BMASK_IBM(55, 55)
-#define PXLY_RC_JUMBO_FRAME     EHEA_BMASK_IBM(56, 56)
-#define PXLY_RC_FRAG_IP_PKT     EHEA_BMASK_IBM(57, 57)
-#define PXLY_RC_TCP_UDP_CHKSUM  EHEA_BMASK_IBM(58, 58)
-#define PXLY_RC_IP_CHKSUM       EHEA_BMASK_IBM(59, 59)
-#define PXLY_RC_MAC_FILTER      EHEA_BMASK_IBM(60, 60)
-#define PXLY_RC_UNTAG_FILTER    EHEA_BMASK_IBM(61, 61)
-#define PXLY_RC_VLAN_TAG_FILTER EHEA_BMASK_IBM(62, 63)
-
-#define PXLY_RC_VLAN_FILTER     2
-#define PXLY_RC_VLAN_PERM       0
-
-
-#define H_PORT_CB1_ALL          0x8000000000000000ULL
-
-struct hcp_ehea_port_cb1 {
-	u64 vlan_filter[64];
-};
-
-#define H_PORT_CB2_ALL          0xFFE0000000000000ULL
-
-struct hcp_ehea_port_cb2 {
-	u64 rxo;
-	u64 rxucp;
-	u64 rxufd;
-	u64 rxuerr;
-	u64 rxftl;
-	u64 rxmcp;
-	u64 rxbcp;
-	u64 txo;
-	u64 txucp;
-	u64 txmcp;
-	u64 txbcp;
-};
-
-struct hcp_ehea_port_cb3 {
-	u64 vlan_bc_filter[64];
-	u64 vlan_mc_filter[64];
-	u64 vlan_un_filter[64];
-	u64 port_mac_hash_array[64];
-};
-
-#define H_PORT_CB4_ALL          0xF000000000000000ULL
-#define H_PORT_CB4_JUMBO        0x1000000000000000ULL
-#define H_PORT_CB4_SPEED        0x8000000000000000ULL
-
-struct hcp_ehea_port_cb4 {
-	u32 port_speed;
-	u32 pause_frame;
-	u32 ens_port_op_state;
-	u32 jumbo_frame;
-	u32 ens_port_wrap;
-};
-
-/* Hcall Query/Modify Port Control Block 5 Selection Mask Bits */
-#define H_PORT_CB5_RCU		0x0001000000000000ULL
-#define PXS_RCU			EHEA_BMASK_IBM(61, 63)
-
-struct hcp_ehea_port_cb5 {
-	u64 prc;	        /* 00 */
-	u64 uaa;		/* 01 */
-	u64 macvc;		/* 02 */
-	u64 xpcsc;		/* 03 */
-	u64 xpcsp;		/* 04 */
-	u64 pcsid;		/* 05 */
-	u64 xpcsst;		/* 06 */
-	u64 pthlb;		/* 07 */
-	u64 pthrb;		/* 08 */
-	u64 pqu;		/* 09 */
-	u64 pqd;		/* 10 */
-	u64 prt;		/* 11 */
-	u64 wsth;		/* 12 */
-	u64 rcb;		/* 13 */
-	u64 rcm;		/* 14 */
-	u64 rcu;		/* 15 */
-	u64 macc;		/* 16 */
-	u64 pc;			/* 17 */
-	u64 pst;		/* 18 */
-	u64 ducqpn;		/* 19 */
-	u64 mcqpn;		/* 20 */
-	u64 mma;		/* 21 */
-	u64 pmc0h;		/* 22 */
-	u64 pmc0l;		/* 23 */
-	u64 lbc;		/* 24 */
-};
-
-#define H_PORT_CB6_ALL  0xFFFFFE7FFFFF8000ULL
-
-struct hcp_ehea_port_cb6 {
-	u64 rxo;		/* 00 */
-	u64 rx64;		/* 01 */
-	u64 rx65;		/* 02 */
-	u64 rx128;		/* 03 */
-	u64 rx256;		/* 04 */
-	u64 rx512;		/* 05 */
-	u64 rx1024;		/* 06 */
-	u64 rxbfcs;		/* 07 */
-	u64 rxime;		/* 08 */
-	u64 rxrle;		/* 09 */
-	u64 rxorle;		/* 10 */
-	u64 rxftl;		/* 11 */
-	u64 rxjab;		/* 12 */
-	u64 rxse;		/* 13 */
-	u64 rxce;		/* 14 */
-	u64 rxrf;		/* 15 */
-	u64 rxfrag;		/* 16 */
-	u64 rxuoc;		/* 17 */
-	u64 rxcpf;		/* 18 */
-	u64 rxsb;		/* 19 */
-	u64 rxfd;		/* 20 */
-	u64 rxoerr;		/* 21 */
-	u64 rxaln;		/* 22 */
-	u64 ducqpn;		/* 23 */
-	u64 reserved0;		/* 24 */
-	u64 rxmcp;		/* 25 */
-	u64 rxbcp;		/* 26 */
-	u64 txmcp;		/* 27 */
-	u64 txbcp;		/* 28 */
-	u64 txo;		/* 29 */
-	u64 tx64;		/* 30 */
-	u64 tx65;		/* 31 */
-	u64 tx128;		/* 32 */
-	u64 tx256;		/* 33 */
-	u64 tx512;		/* 34 */
-	u64 tx1024;		/* 35 */
-	u64 txbfcs;		/* 36 */
-	u64 txcpf;		/* 37 */
-	u64 txlf;		/* 38 */
-	u64 txrf;		/* 39 */
-	u64 txime;		/* 40 */
-	u64 txsc;		/* 41 */
-	u64 txmc;		/* 42 */
-	u64 txsqe;		/* 43 */
-	u64 txdef;		/* 44 */
-	u64 txlcol;		/* 45 */
-	u64 txexcol;		/* 46 */
-	u64 txcse;		/* 47 */
-	u64 txbor;		/* 48 */
-};
-
-#define H_PORT_CB7_DUCQPN 0x8000000000000000ULL
-
-struct hcp_ehea_port_cb7 {
-	u64 def_uc_qpn;
-};
-
-u64 ehea_h_query_ehea_qp(const u64 adapter_handle,
-			 const u8 qp_category,
-			 const u64 qp_handle, const u64 sel_mask,
-			 void *cb_addr);
-
-u64 ehea_h_modify_ehea_qp(const u64 adapter_handle,
-			  const u8 cat,
-			  const u64 qp_handle,
-			  const u64 sel_mask,
-			  void *cb_addr,
-			  u64 *inv_attr_id,
-			  u64 *proc_mask, u16 *out_swr, u16 *out_rwr);
-
-u64 ehea_h_alloc_resource_eq(const u64 adapter_handle,
-			     struct ehea_eq_attr *eq_attr, u64 *eq_handle);
-
-u64 ehea_h_alloc_resource_cq(const u64 adapter_handle,
-			     struct ehea_cq_attr *cq_attr,
-			     u64 *cq_handle, struct h_epas *epas);
-
-u64 ehea_h_alloc_resource_qp(const u64 adapter_handle,
-			     struct ehea_qp_init_attr *init_attr,
-			     const u32 pd,
-			     u64 *qp_handle, struct h_epas *h_epas);
-
-#define H_REG_RPAGE_PAGE_SIZE          EHEA_BMASK_IBM(48, 55)
-#define H_REG_RPAGE_QT                 EHEA_BMASK_IBM(62, 63)
-
-u64 ehea_h_register_rpage(const u64 adapter_handle,
-			  const u8 pagesize,
-			  const u8 queue_type,
-			  const u64 resource_handle,
-			  const u64 log_pageaddr, u64 count);
-
-#define H_DISABLE_GET_EHEA_WQE_P  1
-#define H_DISABLE_GET_SQ_WQE_P    2
-#define H_DISABLE_GET_RQC         3
-
-u64 ehea_h_disable_and_get_hea(const u64 adapter_handle, const u64 qp_handle);
-
-#define FORCE_FREE 1
-#define NORMAL_FREE 0
-
-u64 ehea_h_free_resource(const u64 adapter_handle, const u64 res_handle,
-			 u64 force_bit);
-
-u64 ehea_h_alloc_resource_mr(const u64 adapter_handle, const u64 vaddr,
-			     const u64 length, const u32 access_ctrl,
-			     const u32 pd, u64 *mr_handle, u32 *lkey);
-
-u64 ehea_h_register_rpage_mr(const u64 adapter_handle, const u64 mr_handle,
-			     const u8 pagesize, const u8 queue_type,
-			     const u64 log_pageaddr, const u64 count);
-
-u64 ehea_h_register_smr(const u64 adapter_handle, const u64 orig_mr_handle,
-			const u64 vaddr_in, const u32 access_ctrl, const u32 pd,
-			struct ehea_mr *mr);
-
-u64 ehea_h_query_ehea(const u64 adapter_handle, void *cb_addr);
-
-/* output param R5 */
-#define H_MEHEAPORT_CAT		EHEA_BMASK_IBM(40, 47)
-#define H_MEHEAPORT_PN		EHEA_BMASK_IBM(48, 63)
-
-u64 ehea_h_query_ehea_port(const u64 adapter_handle, const u16 port_num,
-			   const u8 cb_cat, const u64 select_mask,
-			   void *cb_addr);
-
-u64 ehea_h_modify_ehea_port(const u64 adapter_handle, const u16 port_num,
-			    const u8 cb_cat, const u64 select_mask,
-			    void *cb_addr);
-
-#define H_REGBCMC_PN            EHEA_BMASK_IBM(48, 63)
-#define H_REGBCMC_REGTYPE       EHEA_BMASK_IBM(61, 63)
-#define H_REGBCMC_MACADDR       EHEA_BMASK_IBM(16, 63)
-#define H_REGBCMC_VLANID        EHEA_BMASK_IBM(52, 63)
-
-u64 ehea_h_reg_dereg_bcmc(const u64 adapter_handle, const u16 port_num,
-			  const u8 reg_type, const u64 mc_mac_addr,
-			  const u16 vlan_id, const u32 hcall_id);
-
-u64 ehea_h_reset_events(const u64 adapter_handle, const u64 neq_handle,
-			const u64 event_mask);
-
-u64 ehea_h_error_data(const u64 adapter_handle, const u64 ressource_handle,
-		      void *rblock);
-
-#endif	/* __EHEA_PHYP_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/ehea/ehea_qmr.c linux-libre-3.2-gnu/drivers/net/ehea/ehea_qmr.c
--- linux-libre-3.1-gnu/drivers/net/ehea/ehea_qmr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/ehea/ehea_qmr.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1031 +0,0 @@
-/*
- *  linux/drivers/net/ehea/ehea_qmr.c
- *
- *  eHEA ethernet device driver for IBM eServer System p
- *
- *  (C) Copyright IBM Corp. 2006
- *
- *  Authors:
- *       Christoph Raisch <raisch@de.ibm.com>
- *       Jan-Bernd Themann <themann@de.ibm.com>
- *       Thomas Klein <tklein@de.ibm.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; 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/mm.h>
-#include <linux/slab.h>
-#include "ehea.h"
-#include "ehea_phyp.h"
-#include "ehea_qmr.h"
-
-struct ehea_bmap *ehea_bmap = NULL;
-
-
-
-static void *hw_qpageit_get_inc(struct hw_queue *queue)
-{
-	void *retvalue = hw_qeit_get(queue);
-
-	queue->current_q_offset += queue->pagesize;
-	if (queue->current_q_offset > queue->queue_length) {
-		queue->current_q_offset -= queue->pagesize;
-		retvalue = NULL;
-	} else if (((u64) retvalue) & (EHEA_PAGESIZE-1)) {
-		pr_err("not on pageboundary\n");
-		retvalue = NULL;
-	}
-	return retvalue;
-}
-
-static int hw_queue_ctor(struct hw_queue *queue, const u32 nr_of_pages,
-			  const u32 pagesize, const u32 qe_size)
-{
-	int pages_per_kpage = PAGE_SIZE / pagesize;
-	int i, k;
-
-	if ((pagesize > PAGE_SIZE) || (!pages_per_kpage)) {
-		pr_err("pagesize conflict! kernel pagesize=%d, ehea pagesize=%d\n",
-		       (int)PAGE_SIZE, (int)pagesize);
-		return -EINVAL;
-	}
-
-	queue->queue_length = nr_of_pages * pagesize;
-	queue->queue_pages = kmalloc(nr_of_pages * sizeof(void *), GFP_KERNEL);
-	if (!queue->queue_pages) {
-		pr_err("no mem for queue_pages\n");
-		return -ENOMEM;
-	}
-
-	/*
-	 * allocate pages for queue:
-	 * outer loop allocates whole kernel pages (page aligned) and
-	 * inner loop divides a kernel page into smaller hea queue pages
-	 */
-	i = 0;
-	while (i < nr_of_pages) {
-		u8 *kpage = (u8 *)get_zeroed_page(GFP_KERNEL);
-		if (!kpage)
-			goto out_nomem;
-		for (k = 0; k < pages_per_kpage && i < nr_of_pages; k++) {
-			(queue->queue_pages)[i] = (struct ehea_page *)kpage;
-			kpage += pagesize;
-			i++;
-		}
-	}
-
-	queue->current_q_offset = 0;
-	queue->qe_size = qe_size;
-	queue->pagesize = pagesize;
-	queue->toggle_state = 1;
-
-	return 0;
-out_nomem:
-	for (i = 0; i < nr_of_pages; i += pages_per_kpage) {
-		if (!(queue->queue_pages)[i])
-			break;
-		free_page((unsigned long)(queue->queue_pages)[i]);
-	}
-	return -ENOMEM;
-}
-
-static void hw_queue_dtor(struct hw_queue *queue)
-{
-	int pages_per_kpage = PAGE_SIZE / queue->pagesize;
-	int i, nr_pages;
-
-	if (!queue || !queue->queue_pages)
-		return;
-
-	nr_pages = queue->queue_length / queue->pagesize;
-
-	for (i = 0; i < nr_pages; i += pages_per_kpage)
-		free_page((unsigned long)(queue->queue_pages)[i]);
-
-	kfree(queue->queue_pages);
-}
-
-struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter,
-			       int nr_of_cqe, u64 eq_handle, u32 cq_token)
-{
-	struct ehea_cq *cq;
-	struct h_epa epa;
-	u64 *cq_handle_ref, hret, rpage;
-	u32 act_nr_of_entries, act_pages, counter;
-	int ret;
-	void *vpage;
-
-	cq = kzalloc(sizeof(*cq), GFP_KERNEL);
-	if (!cq) {
-		pr_err("no mem for cq\n");
-		goto out_nomem;
-	}
-
-	cq->attr.max_nr_of_cqes = nr_of_cqe;
-	cq->attr.cq_token = cq_token;
-	cq->attr.eq_handle = eq_handle;
-
-	cq->adapter = adapter;
-
-	cq_handle_ref = &cq->fw_handle;
-	act_nr_of_entries = 0;
-	act_pages = 0;
-
-	hret = ehea_h_alloc_resource_cq(adapter->handle, &cq->attr,
-					&cq->fw_handle, &cq->epas);
-	if (hret != H_SUCCESS) {
-		pr_err("alloc_resource_cq failed\n");
-		goto out_freemem;
-	}
-
-	ret = hw_queue_ctor(&cq->hw_queue, cq->attr.nr_pages,
-			    EHEA_PAGESIZE, sizeof(struct ehea_cqe));
-	if (ret)
-		goto out_freeres;
-
-	for (counter = 0; counter < cq->attr.nr_pages; counter++) {
-		vpage = hw_qpageit_get_inc(&cq->hw_queue);
-		if (!vpage) {
-			pr_err("hw_qpageit_get_inc failed\n");
-			goto out_kill_hwq;
-		}
-
-		rpage = virt_to_abs(vpage);
-		hret = ehea_h_register_rpage(adapter->handle,
-					     0, EHEA_CQ_REGISTER_ORIG,
-					     cq->fw_handle, rpage, 1);
-		if (hret < H_SUCCESS) {
-			pr_err("register_rpage_cq failed ehea_cq=%p hret=%llx counter=%i act_pages=%i\n",
-			       cq, hret, counter, cq->attr.nr_pages);
-			goto out_kill_hwq;
-		}
-
-		if (counter == (cq->attr.nr_pages - 1)) {
-			vpage = hw_qpageit_get_inc(&cq->hw_queue);
-
-			if ((hret != H_SUCCESS) || (vpage)) {
-				pr_err("registration of pages not complete hret=%llx\n",
-				       hret);
-				goto out_kill_hwq;
-			}
-		} else {
-			if (hret != H_PAGE_REGISTERED) {
-				pr_err("CQ: registration of page failed hret=%llx\n",
-				       hret);
-				goto out_kill_hwq;
-			}
-		}
-	}
-
-	hw_qeit_reset(&cq->hw_queue);
-	epa = cq->epas.kernel;
-	ehea_reset_cq_ep(cq);
-	ehea_reset_cq_n1(cq);
-
-	return cq;
-
-out_kill_hwq:
-	hw_queue_dtor(&cq->hw_queue);
-
-out_freeres:
-	ehea_h_free_resource(adapter->handle, cq->fw_handle, FORCE_FREE);
-
-out_freemem:
-	kfree(cq);
-
-out_nomem:
-	return NULL;
-}
-
-u64 ehea_destroy_cq_res(struct ehea_cq *cq, u64 force)
-{
-	u64 hret;
-	u64 adapter_handle = cq->adapter->handle;
-
-	/* deregister all previous registered pages */
-	hret = ehea_h_free_resource(adapter_handle, cq->fw_handle, force);
-	if (hret != H_SUCCESS)
-		return hret;
-
-	hw_queue_dtor(&cq->hw_queue);
-	kfree(cq);
-
-	return hret;
-}
-
-int ehea_destroy_cq(struct ehea_cq *cq)
-{
-	u64 hret, aer, aerr;
-	if (!cq)
-		return 0;
-
-	hcp_epas_dtor(&cq->epas);
-	hret = ehea_destroy_cq_res(cq, NORMAL_FREE);
-	if (hret == H_R_STATE) {
-		ehea_error_data(cq->adapter, cq->fw_handle, &aer, &aerr);
-		hret = ehea_destroy_cq_res(cq, FORCE_FREE);
-	}
-
-	if (hret != H_SUCCESS) {
-		pr_err("destroy CQ failed\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-struct ehea_eq *ehea_create_eq(struct ehea_adapter *adapter,
-			       const enum ehea_eq_type type,
-			       const u32 max_nr_of_eqes, const u8 eqe_gen)
-{
-	int ret, i;
-	u64 hret, rpage;
-	void *vpage;
-	struct ehea_eq *eq;
-
-	eq = kzalloc(sizeof(*eq), GFP_KERNEL);
-	if (!eq) {
-		pr_err("no mem for eq\n");
-		return NULL;
-	}
-
-	eq->adapter = adapter;
-	eq->attr.type = type;
-	eq->attr.max_nr_of_eqes = max_nr_of_eqes;
-	eq->attr.eqe_gen = eqe_gen;
-	spin_lock_init(&eq->spinlock);
-
-	hret = ehea_h_alloc_resource_eq(adapter->handle,
-					&eq->attr, &eq->fw_handle);
-	if (hret != H_SUCCESS) {
-		pr_err("alloc_resource_eq failed\n");
-		goto out_freemem;
-	}
-
-	ret = hw_queue_ctor(&eq->hw_queue, eq->attr.nr_pages,
-			    EHEA_PAGESIZE, sizeof(struct ehea_eqe));
-	if (ret) {
-		pr_err("can't allocate eq pages\n");
-		goto out_freeres;
-	}
-
-	for (i = 0; i < eq->attr.nr_pages; i++) {
-		vpage = hw_qpageit_get_inc(&eq->hw_queue);
-		if (!vpage) {
-			pr_err("hw_qpageit_get_inc failed\n");
-			hret = H_RESOURCE;
-			goto out_kill_hwq;
-		}
-
-		rpage = virt_to_abs(vpage);
-
-		hret = ehea_h_register_rpage(adapter->handle, 0,
-					     EHEA_EQ_REGISTER_ORIG,
-					     eq->fw_handle, rpage, 1);
-
-		if (i == (eq->attr.nr_pages - 1)) {
-			/* last page */
-			vpage = hw_qpageit_get_inc(&eq->hw_queue);
-			if ((hret != H_SUCCESS) || (vpage))
-				goto out_kill_hwq;
-
-		} else {
-			if (hret != H_PAGE_REGISTERED)
-				goto out_kill_hwq;
-
-		}
-	}
-
-	hw_qeit_reset(&eq->hw_queue);
-	return eq;
-
-out_kill_hwq:
-	hw_queue_dtor(&eq->hw_queue);
-
-out_freeres:
-	ehea_h_free_resource(adapter->handle, eq->fw_handle, FORCE_FREE);
-
-out_freemem:
-	kfree(eq);
-	return NULL;
-}
-
-struct ehea_eqe *ehea_poll_eq(struct ehea_eq *eq)
-{
-	struct ehea_eqe *eqe;
-	unsigned long flags;
-
-	spin_lock_irqsave(&eq->spinlock, flags);
-	eqe = hw_eqit_eq_get_inc_valid(&eq->hw_queue);
-	spin_unlock_irqrestore(&eq->spinlock, flags);
-
-	return eqe;
-}
-
-u64 ehea_destroy_eq_res(struct ehea_eq *eq, u64 force)
-{
-	u64 hret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&eq->spinlock, flags);
-
-	hret = ehea_h_free_resource(eq->adapter->handle, eq->fw_handle, force);
-	spin_unlock_irqrestore(&eq->spinlock, flags);
-
-	if (hret != H_SUCCESS)
-		return hret;
-
-	hw_queue_dtor(&eq->hw_queue);
-	kfree(eq);
-
-	return hret;
-}
-
-int ehea_destroy_eq(struct ehea_eq *eq)
-{
-	u64 hret, aer, aerr;
-	if (!eq)
-		return 0;
-
-	hcp_epas_dtor(&eq->epas);
-
-	hret = ehea_destroy_eq_res(eq, NORMAL_FREE);
-	if (hret == H_R_STATE) {
-		ehea_error_data(eq->adapter, eq->fw_handle, &aer, &aerr);
-		hret = ehea_destroy_eq_res(eq, FORCE_FREE);
-	}
-
-	if (hret != H_SUCCESS) {
-		pr_err("destroy EQ failed\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-/**
- * allocates memory for a queue and registers pages in phyp
- */
-int ehea_qp_alloc_register(struct ehea_qp *qp, struct hw_queue *hw_queue,
-			   int nr_pages, int wqe_size, int act_nr_sges,
-			   struct ehea_adapter *adapter, int h_call_q_selector)
-{
-	u64 hret, rpage;
-	int ret, cnt;
-	void *vpage;
-
-	ret = hw_queue_ctor(hw_queue, nr_pages, EHEA_PAGESIZE, wqe_size);
-	if (ret)
-		return ret;
-
-	for (cnt = 0; cnt < nr_pages; cnt++) {
-		vpage = hw_qpageit_get_inc(hw_queue);
-		if (!vpage) {
-			pr_err("hw_qpageit_get_inc failed\n");
-			goto out_kill_hwq;
-		}
-		rpage = virt_to_abs(vpage);
-		hret = ehea_h_register_rpage(adapter->handle,
-					     0, h_call_q_selector,
-					     qp->fw_handle, rpage, 1);
-		if (hret < H_SUCCESS) {
-			pr_err("register_rpage_qp failed\n");
-			goto out_kill_hwq;
-		}
-	}
-	hw_qeit_reset(hw_queue);
-	return 0;
-
-out_kill_hwq:
-	hw_queue_dtor(hw_queue);
-	return -EIO;
-}
-
-static inline u32 map_wqe_size(u8 wqe_enc_size)
-{
-	return 128 << wqe_enc_size;
-}
-
-struct ehea_qp *ehea_create_qp(struct ehea_adapter *adapter,
-			       u32 pd, struct ehea_qp_init_attr *init_attr)
-{
-	int ret;
-	u64 hret;
-	struct ehea_qp *qp;
-	u32 wqe_size_in_bytes_sq, wqe_size_in_bytes_rq1;
-	u32 wqe_size_in_bytes_rq2, wqe_size_in_bytes_rq3;
-
-
-	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
-	if (!qp) {
-		pr_err("no mem for qp\n");
-		return NULL;
-	}
-
-	qp->adapter = adapter;
-
-	hret = ehea_h_alloc_resource_qp(adapter->handle, init_attr, pd,
-					&qp->fw_handle, &qp->epas);
-	if (hret != H_SUCCESS) {
-		pr_err("ehea_h_alloc_resource_qp failed\n");
-		goto out_freemem;
-	}
-
-	wqe_size_in_bytes_sq = map_wqe_size(init_attr->act_wqe_size_enc_sq);
-	wqe_size_in_bytes_rq1 = map_wqe_size(init_attr->act_wqe_size_enc_rq1);
-	wqe_size_in_bytes_rq2 = map_wqe_size(init_attr->act_wqe_size_enc_rq2);
-	wqe_size_in_bytes_rq3 = map_wqe_size(init_attr->act_wqe_size_enc_rq3);
-
-	ret = ehea_qp_alloc_register(qp, &qp->hw_squeue, init_attr->nr_sq_pages,
-				     wqe_size_in_bytes_sq,
-				     init_attr->act_wqe_size_enc_sq, adapter,
-				     0);
-	if (ret) {
-		pr_err("can't register for sq ret=%x\n", ret);
-		goto out_freeres;
-	}
-
-	ret = ehea_qp_alloc_register(qp, &qp->hw_rqueue1,
-				     init_attr->nr_rq1_pages,
-				     wqe_size_in_bytes_rq1,
-				     init_attr->act_wqe_size_enc_rq1,
-				     adapter, 1);
-	if (ret) {
-		pr_err("can't register for rq1 ret=%x\n", ret);
-		goto out_kill_hwsq;
-	}
-
-	if (init_attr->rq_count > 1) {
-		ret = ehea_qp_alloc_register(qp, &qp->hw_rqueue2,
-					     init_attr->nr_rq2_pages,
-					     wqe_size_in_bytes_rq2,
-					     init_attr->act_wqe_size_enc_rq2,
-					     adapter, 2);
-		if (ret) {
-			pr_err("can't register for rq2 ret=%x\n", ret);
-			goto out_kill_hwr1q;
-		}
-	}
-
-	if (init_attr->rq_count > 2) {
-		ret = ehea_qp_alloc_register(qp, &qp->hw_rqueue3,
-					     init_attr->nr_rq3_pages,
-					     wqe_size_in_bytes_rq3,
-					     init_attr->act_wqe_size_enc_rq3,
-					     adapter, 3);
-		if (ret) {
-			pr_err("can't register for rq3 ret=%x\n", ret);
-			goto out_kill_hwr2q;
-		}
-	}
-
-	qp->init_attr = *init_attr;
-
-	return qp;
-
-out_kill_hwr2q:
-	hw_queue_dtor(&qp->hw_rqueue2);
-
-out_kill_hwr1q:
-	hw_queue_dtor(&qp->hw_rqueue1);
-
-out_kill_hwsq:
-	hw_queue_dtor(&qp->hw_squeue);
-
-out_freeres:
-	ehea_h_disable_and_get_hea(adapter->handle, qp->fw_handle);
-	ehea_h_free_resource(adapter->handle, qp->fw_handle, FORCE_FREE);
-
-out_freemem:
-	kfree(qp);
-	return NULL;
-}
-
-u64 ehea_destroy_qp_res(struct ehea_qp *qp, u64 force)
-{
-	u64 hret;
-	struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
-
-
-	ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
-	hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force);
-	if (hret != H_SUCCESS)
-		return hret;
-
-	hw_queue_dtor(&qp->hw_squeue);
-	hw_queue_dtor(&qp->hw_rqueue1);
-
-	if (qp_attr->rq_count > 1)
-		hw_queue_dtor(&qp->hw_rqueue2);
-	if (qp_attr->rq_count > 2)
-		hw_queue_dtor(&qp->hw_rqueue3);
-	kfree(qp);
-
-	return hret;
-}
-
-int ehea_destroy_qp(struct ehea_qp *qp)
-{
-	u64 hret, aer, aerr;
-	if (!qp)
-		return 0;
-
-	hcp_epas_dtor(&qp->epas);
-
-	hret = ehea_destroy_qp_res(qp, NORMAL_FREE);
-	if (hret == H_R_STATE) {
-		ehea_error_data(qp->adapter, qp->fw_handle, &aer, &aerr);
-		hret = ehea_destroy_qp_res(qp, FORCE_FREE);
-	}
-
-	if (hret != H_SUCCESS) {
-		pr_err("destroy QP failed\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static inline int ehea_calc_index(unsigned long i, unsigned long s)
-{
-	return (i >> s) & EHEA_INDEX_MASK;
-}
-
-static inline int ehea_init_top_bmap(struct ehea_top_bmap *ehea_top_bmap,
-				     int dir)
-{
-	if (!ehea_top_bmap->dir[dir]) {
-		ehea_top_bmap->dir[dir] =
-			kzalloc(sizeof(struct ehea_dir_bmap), GFP_KERNEL);
-		if (!ehea_top_bmap->dir[dir])
-			return -ENOMEM;
-	}
-	return 0;
-}
-
-static inline int ehea_init_bmap(struct ehea_bmap *ehea_bmap, int top, int dir)
-{
-	if (!ehea_bmap->top[top]) {
-		ehea_bmap->top[top] =
-			kzalloc(sizeof(struct ehea_top_bmap), GFP_KERNEL);
-		if (!ehea_bmap->top[top])
-			return -ENOMEM;
-	}
-	return ehea_init_top_bmap(ehea_bmap->top[top], dir);
-}
-
-static DEFINE_MUTEX(ehea_busmap_mutex);
-static unsigned long ehea_mr_len;
-
-#define EHEA_BUSMAP_ADD_SECT 1
-#define EHEA_BUSMAP_REM_SECT 0
-
-static void ehea_rebuild_busmap(void)
-{
-	u64 vaddr = EHEA_BUSMAP_START;
-	int top, dir, idx;
-
-	for (top = 0; top < EHEA_MAP_ENTRIES; top++) {
-		struct ehea_top_bmap *ehea_top;
-		int valid_dir_entries = 0;
-
-		if (!ehea_bmap->top[top])
-			continue;
-		ehea_top = ehea_bmap->top[top];
-		for (dir = 0; dir < EHEA_MAP_ENTRIES; dir++) {
-			struct ehea_dir_bmap *ehea_dir;
-			int valid_entries = 0;
-
-			if (!ehea_top->dir[dir])
-				continue;
-			valid_dir_entries++;
-			ehea_dir = ehea_top->dir[dir];
-			for (idx = 0; idx < EHEA_MAP_ENTRIES; idx++) {
-				if (!ehea_dir->ent[idx])
-					continue;
-				valid_entries++;
-				ehea_dir->ent[idx] = vaddr;
-				vaddr += EHEA_SECTSIZE;
-			}
-			if (!valid_entries) {
-				ehea_top->dir[dir] = NULL;
-				kfree(ehea_dir);
-			}
-		}
-		if (!valid_dir_entries) {
-			ehea_bmap->top[top] = NULL;
-			kfree(ehea_top);
-		}
-	}
-}
-
-static int ehea_update_busmap(unsigned long pfn, unsigned long nr_pages, int add)
-{
-	unsigned long i, start_section, end_section;
-
-	if (!nr_pages)
-		return 0;
-
-	if (!ehea_bmap) {
-		ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL);
-		if (!ehea_bmap)
-			return -ENOMEM;
-	}
-
-	start_section = (pfn * PAGE_SIZE) / EHEA_SECTSIZE;
-	end_section = start_section + ((nr_pages * PAGE_SIZE) / EHEA_SECTSIZE);
-	/* Mark entries as valid or invalid only; address is assigned later */
-	for (i = start_section; i < end_section; i++) {
-		u64 flag;
-		int top = ehea_calc_index(i, EHEA_TOP_INDEX_SHIFT);
-		int dir = ehea_calc_index(i, EHEA_DIR_INDEX_SHIFT);
-		int idx = i & EHEA_INDEX_MASK;
-
-		if (add) {
-			int ret = ehea_init_bmap(ehea_bmap, top, dir);
-			if (ret)
-				return ret;
-			flag = 1; /* valid */
-			ehea_mr_len += EHEA_SECTSIZE;
-		} else {
-			if (!ehea_bmap->top[top])
-				continue;
-			if (!ehea_bmap->top[top]->dir[dir])
-				continue;
-			flag = 0; /* invalid */
-			ehea_mr_len -= EHEA_SECTSIZE;
-		}
-
-		ehea_bmap->top[top]->dir[dir]->ent[idx] = flag;
-	}
-	ehea_rebuild_busmap(); /* Assign contiguous addresses for mr */
-	return 0;
-}
-
-int ehea_add_sect_bmap(unsigned long pfn, unsigned long nr_pages)
-{
-	int ret;
-
-	mutex_lock(&ehea_busmap_mutex);
-	ret = ehea_update_busmap(pfn, nr_pages, EHEA_BUSMAP_ADD_SECT);
-	mutex_unlock(&ehea_busmap_mutex);
-	return ret;
-}
-
-int ehea_rem_sect_bmap(unsigned long pfn, unsigned long nr_pages)
-{
-	int ret;
-
-	mutex_lock(&ehea_busmap_mutex);
-	ret = ehea_update_busmap(pfn, nr_pages, EHEA_BUSMAP_REM_SECT);
-	mutex_unlock(&ehea_busmap_mutex);
-	return ret;
-}
-
-static int ehea_is_hugepage(unsigned long pfn)
-{
-	int page_order;
-
-	if (pfn & EHEA_HUGEPAGE_PFN_MASK)
-		return 0;
-
-	page_order = compound_order(pfn_to_page(pfn));
-	if (page_order + PAGE_SHIFT != EHEA_HUGEPAGESHIFT)
-		return 0;
-
-	return 1;
-}
-
-static int ehea_create_busmap_callback(unsigned long initial_pfn,
-				       unsigned long total_nr_pages, void *arg)
-{
-	int ret;
-	unsigned long pfn, start_pfn, end_pfn, nr_pages;
-
-	if ((total_nr_pages * PAGE_SIZE) < EHEA_HUGEPAGE_SIZE)
-		return ehea_update_busmap(initial_pfn, total_nr_pages,
-					  EHEA_BUSMAP_ADD_SECT);
-
-	/* Given chunk is >= 16GB -> check for hugepages */
-	start_pfn = initial_pfn;
-	end_pfn = initial_pfn + total_nr_pages;
-	pfn = start_pfn;
-
-	while (pfn < end_pfn) {
-		if (ehea_is_hugepage(pfn)) {
-			/* Add mem found in front of the hugepage */
-			nr_pages = pfn - start_pfn;
-			ret = ehea_update_busmap(start_pfn, nr_pages,
-						 EHEA_BUSMAP_ADD_SECT);
-			if (ret)
-				return ret;
-
-			/* Skip the hugepage */
-			pfn += (EHEA_HUGEPAGE_SIZE / PAGE_SIZE);
-			start_pfn = pfn;
-		} else
-			pfn += (EHEA_SECTSIZE / PAGE_SIZE);
-	}
-
-	/* Add mem found behind the hugepage(s)  */
-	nr_pages = pfn - start_pfn;
-	return ehea_update_busmap(start_pfn, nr_pages, EHEA_BUSMAP_ADD_SECT);
-}
-
-int ehea_create_busmap(void)
-{
-	int ret;
-
-	mutex_lock(&ehea_busmap_mutex);
-	ehea_mr_len = 0;
-	ret = walk_system_ram_range(0, 1ULL << MAX_PHYSMEM_BITS, NULL,
-				   ehea_create_busmap_callback);
-	mutex_unlock(&ehea_busmap_mutex);
-	return ret;
-}
-
-void ehea_destroy_busmap(void)
-{
-	int top, dir;
-	mutex_lock(&ehea_busmap_mutex);
-	if (!ehea_bmap)
-		goto out_destroy;
-
-	for (top = 0; top < EHEA_MAP_ENTRIES; top++) {
-		if (!ehea_bmap->top[top])
-			continue;
-
-		for (dir = 0; dir < EHEA_MAP_ENTRIES; dir++) {
-			if (!ehea_bmap->top[top]->dir[dir])
-				continue;
-
-			kfree(ehea_bmap->top[top]->dir[dir]);
-		}
-
-		kfree(ehea_bmap->top[top]);
-	}
-
-	kfree(ehea_bmap);
-	ehea_bmap = NULL;
-out_destroy:
-	mutex_unlock(&ehea_busmap_mutex);
-}
-
-u64 ehea_map_vaddr(void *caddr)
-{
-	int top, dir, idx;
-	unsigned long index, offset;
-
-	if (!ehea_bmap)
-		return EHEA_INVAL_ADDR;
-
-	index = virt_to_abs(caddr) >> SECTION_SIZE_BITS;
-	top = (index >> EHEA_TOP_INDEX_SHIFT) & EHEA_INDEX_MASK;
-	if (!ehea_bmap->top[top])
-		return EHEA_INVAL_ADDR;
-
-	dir = (index >> EHEA_DIR_INDEX_SHIFT) & EHEA_INDEX_MASK;
-	if (!ehea_bmap->top[top]->dir[dir])
-		return EHEA_INVAL_ADDR;
-
-	idx = index & EHEA_INDEX_MASK;
-	if (!ehea_bmap->top[top]->dir[dir]->ent[idx])
-		return EHEA_INVAL_ADDR;
-
-	offset = (unsigned long)caddr & (EHEA_SECTSIZE - 1);
-	return ehea_bmap->top[top]->dir[dir]->ent[idx] | offset;
-}
-
-static inline void *ehea_calc_sectbase(int top, int dir, int idx)
-{
-	unsigned long ret = idx;
-	ret |= dir << EHEA_DIR_INDEX_SHIFT;
-	ret |= top << EHEA_TOP_INDEX_SHIFT;
-	return abs_to_virt(ret << SECTION_SIZE_BITS);
-}
-
-static u64 ehea_reg_mr_section(int top, int dir, int idx, u64 *pt,
-			       struct ehea_adapter *adapter,
-			       struct ehea_mr *mr)
-{
-	void *pg;
-	u64 j, m, hret;
-	unsigned long k = 0;
-	u64 pt_abs = virt_to_abs(pt);
-
-	void *sectbase = ehea_calc_sectbase(top, dir, idx);
-
-	for (j = 0; j < (EHEA_PAGES_PER_SECTION / EHEA_MAX_RPAGE); j++) {
-
-		for (m = 0; m < EHEA_MAX_RPAGE; m++) {
-			pg = sectbase + ((k++) * EHEA_PAGESIZE);
-			pt[m] = virt_to_abs(pg);
-		}
-		hret = ehea_h_register_rpage_mr(adapter->handle, mr->handle, 0,
-						0, pt_abs, EHEA_MAX_RPAGE);
-
-		if ((hret != H_SUCCESS) &&
-		    (hret != H_PAGE_REGISTERED)) {
-			ehea_h_free_resource(adapter->handle, mr->handle,
-					     FORCE_FREE);
-			pr_err("register_rpage_mr failed\n");
-			return hret;
-		}
-	}
-	return hret;
-}
-
-static u64 ehea_reg_mr_sections(int top, int dir, u64 *pt,
-				struct ehea_adapter *adapter,
-				struct ehea_mr *mr)
-{
-	u64 hret = H_SUCCESS;
-	int idx;
-
-	for (idx = 0; idx < EHEA_MAP_ENTRIES; idx++) {
-		if (!ehea_bmap->top[top]->dir[dir]->ent[idx])
-			continue;
-
-		hret = ehea_reg_mr_section(top, dir, idx, pt, adapter, mr);
-		if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED))
-			return hret;
-	}
-	return hret;
-}
-
-static u64 ehea_reg_mr_dir_sections(int top, u64 *pt,
-				    struct ehea_adapter *adapter,
-				    struct ehea_mr *mr)
-{
-	u64 hret = H_SUCCESS;
-	int dir;
-
-	for (dir = 0; dir < EHEA_MAP_ENTRIES; dir++) {
-		if (!ehea_bmap->top[top]->dir[dir])
-			continue;
-
-		hret = ehea_reg_mr_sections(top, dir, pt, adapter, mr);
-		if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED))
-			return hret;
-	}
-	return hret;
-}
-
-int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
-{
-	int ret;
-	u64 *pt;
-	u64 hret;
-	u32 acc_ctrl = EHEA_MR_ACC_CTRL;
-
-	unsigned long top;
-
-	pt = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!pt) {
-		pr_err("no mem\n");
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	hret = ehea_h_alloc_resource_mr(adapter->handle, EHEA_BUSMAP_START,
-					ehea_mr_len, acc_ctrl, adapter->pd,
-					&mr->handle, &mr->lkey);
-
-	if (hret != H_SUCCESS) {
-		pr_err("alloc_resource_mr failed\n");
-		ret = -EIO;
-		goto out;
-	}
-
-	if (!ehea_bmap) {
-		ehea_h_free_resource(adapter->handle, mr->handle, FORCE_FREE);
-		pr_err("no busmap available\n");
-		ret = -EIO;
-		goto out;
-	}
-
-	for (top = 0; top < EHEA_MAP_ENTRIES; top++) {
-		if (!ehea_bmap->top[top])
-			continue;
-
-		hret = ehea_reg_mr_dir_sections(top, pt, adapter, mr);
-		if((hret != H_PAGE_REGISTERED) && (hret != H_SUCCESS))
-			break;
-	}
-
-	if (hret != H_SUCCESS) {
-		ehea_h_free_resource(adapter->handle, mr->handle, FORCE_FREE);
-		pr_err("registering mr failed\n");
-		ret = -EIO;
-		goto out;
-	}
-
-	mr->vaddr = EHEA_BUSMAP_START;
-	mr->adapter = adapter;
-	ret = 0;
-out:
-	free_page((unsigned long)pt);
-	return ret;
-}
-
-int ehea_rem_mr(struct ehea_mr *mr)
-{
-	u64 hret;
-
-	if (!mr || !mr->adapter)
-		return -EINVAL;
-
-	hret = ehea_h_free_resource(mr->adapter->handle, mr->handle,
-				    FORCE_FREE);
-	if (hret != H_SUCCESS) {
-		pr_err("destroy MR failed\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-int ehea_gen_smr(struct ehea_adapter *adapter, struct ehea_mr *old_mr,
-		 struct ehea_mr *shared_mr)
-{
-	u64 hret;
-
-	hret = ehea_h_register_smr(adapter->handle, old_mr->handle,
-				   old_mr->vaddr, EHEA_MR_ACC_CTRL,
-				   adapter->pd, shared_mr);
-	if (hret != H_SUCCESS)
-		return -EIO;
-
-	shared_mr->adapter = adapter;
-
-	return 0;
-}
-
-void print_error_data(u64 *data)
-{
-	int length;
-	u64 type = EHEA_BMASK_GET(ERROR_DATA_TYPE, data[2]);
-	u64 resource = data[1];
-
-	length = EHEA_BMASK_GET(ERROR_DATA_LENGTH, data[0]);
-
-	if (length > EHEA_PAGESIZE)
-		length = EHEA_PAGESIZE;
-
-	if (type == EHEA_AER_RESTYPE_QP)
-		pr_err("QP (resource=%llX) state: AER=0x%llX, AERR=0x%llX, port=%llX\n",
-		       resource, data[6], data[12], data[22]);
-	else if (type == EHEA_AER_RESTYPE_CQ)
-		pr_err("CQ (resource=%llX) state: AER=0x%llX\n",
-		       resource, data[6]);
-	else if (type == EHEA_AER_RESTYPE_EQ)
-		pr_err("EQ (resource=%llX) state: AER=0x%llX\n",
-		       resource, data[6]);
-
-	ehea_dump(data, length, "error data");
-}
-
-u64 ehea_error_data(struct ehea_adapter *adapter, u64 res_handle,
-		    u64 *aer, u64 *aerr)
-{
-	unsigned long ret;
-	u64 *rblock;
-	u64 type = 0;
-
-	rblock = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!rblock) {
-		pr_err("Cannot allocate rblock memory\n");
-		goto out;
-	}
-
-	ret = ehea_h_error_data(adapter->handle, res_handle, rblock);
-
-	if (ret == H_SUCCESS) {
-		type = EHEA_BMASK_GET(ERROR_DATA_TYPE, rblock[2]);
-		*aer = rblock[6];
-		*aerr = rblock[12];
-		print_error_data(rblock);
-	} else if (ret == H_R_STATE) {
-		pr_err("No error data available: %llX\n", res_handle);
-	} else
-		pr_err("Error data could not be fetched: %llX\n", res_handle);
-
-	free_page((unsigned long)rblock);
-out:
-	return type;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/ehea/ehea_qmr.h linux-libre-3.2-gnu/drivers/net/ehea/ehea_qmr.h
--- linux-libre-3.1-gnu/drivers/net/ehea/ehea_qmr.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/ehea/ehea_qmr.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,404 +0,0 @@
-/*
- *  linux/drivers/net/ehea/ehea_qmr.h
- *
- *  eHEA ethernet device driver for IBM eServer System p
- *
- *  (C) Copyright IBM Corp. 2006
- *
- *  Authors:
- *       Christoph Raisch <raisch@de.ibm.com>
- *       Jan-Bernd Themann <themann@de.ibm.com>
- *       Thomas Klein <tklein@de.ibm.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; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __EHEA_QMR_H__
-#define __EHEA_QMR_H__
-
-#include <linux/prefetch.h>
-#include "ehea.h"
-#include "ehea_hw.h"
-
-/*
- * page size of ehea hardware queues
- */
-
-#define EHEA_PAGESHIFT         12
-#define EHEA_PAGESIZE          (1UL << EHEA_PAGESHIFT)
-#define EHEA_SECTSIZE          (1UL << 24)
-#define EHEA_PAGES_PER_SECTION (EHEA_SECTSIZE >> EHEA_PAGESHIFT)
-#define EHEA_HUGEPAGESHIFT     34
-#define EHEA_HUGEPAGE_SIZE     (1UL << EHEA_HUGEPAGESHIFT)
-#define EHEA_HUGEPAGE_PFN_MASK ((EHEA_HUGEPAGE_SIZE - 1) >> PAGE_SHIFT)
-
-#if ((1UL << SECTION_SIZE_BITS) < EHEA_SECTSIZE)
-#error eHEA module cannot work if kernel sectionsize < ehea sectionsize
-#endif
-
-/* Some abbreviations used here:
- *
- * WQE  - Work Queue Entry
- * SWQE - Send Work Queue Entry
- * RWQE - Receive Work Queue Entry
- * CQE  - Completion Queue Entry
- * EQE  - Event Queue Entry
- * MR   - Memory Region
- */
-
-/* Use of WR_ID field for EHEA */
-#define EHEA_WR_ID_COUNT   EHEA_BMASK_IBM(0, 19)
-#define EHEA_WR_ID_TYPE    EHEA_BMASK_IBM(20, 23)
-#define EHEA_SWQE2_TYPE    0x1
-#define EHEA_SWQE3_TYPE    0x2
-#define EHEA_RWQE2_TYPE    0x3
-#define EHEA_RWQE3_TYPE    0x4
-#define EHEA_WR_ID_INDEX   EHEA_BMASK_IBM(24, 47)
-#define EHEA_WR_ID_REFILL  EHEA_BMASK_IBM(48, 63)
-
-struct ehea_vsgentry {
-	u64 vaddr;
-	u32 l_key;
-	u32 len;
-};
-
-/* maximum number of sg entries allowed in a WQE */
-#define EHEA_MAX_WQE_SG_ENTRIES  	252
-#define SWQE2_MAX_IMM            	(0xD0 - 0x30)
-#define SWQE3_MAX_IMM            	224
-
-/* tx control flags for swqe */
-#define EHEA_SWQE_CRC                   0x8000
-#define EHEA_SWQE_IP_CHECKSUM           0x4000
-#define EHEA_SWQE_TCP_CHECKSUM          0x2000
-#define EHEA_SWQE_TSO                   0x1000
-#define EHEA_SWQE_SIGNALLED_COMPLETION  0x0800
-#define EHEA_SWQE_VLAN_INSERT           0x0400
-#define EHEA_SWQE_IMM_DATA_PRESENT      0x0200
-#define EHEA_SWQE_DESCRIPTORS_PRESENT   0x0100
-#define EHEA_SWQE_WRAP_CTL_REC          0x0080
-#define EHEA_SWQE_WRAP_CTL_FORCE        0x0040
-#define EHEA_SWQE_BIND                  0x0020
-#define EHEA_SWQE_PURGE                 0x0010
-
-/* sizeof(struct ehea_swqe) less the union */
-#define SWQE_HEADER_SIZE		32
-
-struct ehea_swqe {
-	u64 wr_id;
-	u16 tx_control;
-	u16 vlan_tag;
-	u8 reserved1;
-	u8 ip_start;
-	u8 ip_end;
-	u8 immediate_data_length;
-	u8 tcp_offset;
-	u8 reserved2;
-	u16 tcp_end;
-	u8 wrap_tag;
-	u8 descriptors;		/* number of valid descriptors in WQE */
-	u16 reserved3;
-	u16 reserved4;
-	u16 mss;
-	u32 reserved5;
-	union {
-		/*  Send WQE Format 1 */
-		struct {
-			struct ehea_vsgentry sg_list[EHEA_MAX_WQE_SG_ENTRIES];
-		} no_immediate_data;
-
-		/*  Send WQE Format 2 */
-		struct {
-			struct ehea_vsgentry sg_entry;
-			/* 0x30 */
-			u8 immediate_data[SWQE2_MAX_IMM];
-			/* 0xd0 */
-			struct ehea_vsgentry sg_list[EHEA_MAX_WQE_SG_ENTRIES-1];
-		} immdata_desc __packed;
-
-		/*  Send WQE Format 3 */
-		struct {
-			u8 immediate_data[SWQE3_MAX_IMM];
-		} immdata_nodesc;
-	} u;
-};
-
-struct ehea_rwqe {
-	u64 wr_id;		/* work request ID */
-	u8 reserved1[5];
-	u8 data_segments;
-	u16 reserved2;
-	u64 reserved3;
-	u64 reserved4;
-	struct ehea_vsgentry sg_list[EHEA_MAX_WQE_SG_ENTRIES];
-};
-
-#define EHEA_CQE_VLAN_TAG_XTRACT   0x0400
-
-#define EHEA_CQE_TYPE_RQ           0x60
-#define EHEA_CQE_STAT_ERR_MASK     0x700F
-#define EHEA_CQE_STAT_FAT_ERR_MASK 0xF
-#define EHEA_CQE_BLIND_CKSUM       0x8000
-#define EHEA_CQE_STAT_ERR_TCP      0x4000
-#define EHEA_CQE_STAT_ERR_IP       0x2000
-#define EHEA_CQE_STAT_ERR_CRC      0x1000
-
-/* Defines which bad send cqe stati lead to a port reset */
-#define EHEA_CQE_STAT_RESET_MASK   0x0002
-
-struct ehea_cqe {
-	u64 wr_id;		/* work request ID from WQE */
-	u8 type;
-	u8 valid;
-	u16 status;
-	u16 reserved1;
-	u16 num_bytes_transfered;
-	u16 vlan_tag;
-	u16 inet_checksum_value;
-	u8 reserved2;
-	u8 header_length;
-	u16 reserved3;
-	u16 page_offset;
-	u16 wqe_count;
-	u32 qp_token;
-	u32 timestamp;
-	u32 reserved4;
-	u64 reserved5[3];
-};
-
-#define EHEA_EQE_VALID           EHEA_BMASK_IBM(0, 0)
-#define EHEA_EQE_IS_CQE          EHEA_BMASK_IBM(1, 1)
-#define EHEA_EQE_IDENTIFIER      EHEA_BMASK_IBM(2, 7)
-#define EHEA_EQE_QP_CQ_NUMBER    EHEA_BMASK_IBM(8, 31)
-#define EHEA_EQE_QP_TOKEN        EHEA_BMASK_IBM(32, 63)
-#define EHEA_EQE_CQ_TOKEN        EHEA_BMASK_IBM(32, 63)
-#define EHEA_EQE_KEY             EHEA_BMASK_IBM(32, 63)
-#define EHEA_EQE_PORT_NUMBER     EHEA_BMASK_IBM(56, 63)
-#define EHEA_EQE_EQ_NUMBER       EHEA_BMASK_IBM(48, 63)
-#define EHEA_EQE_SM_ID           EHEA_BMASK_IBM(48, 63)
-#define EHEA_EQE_SM_MECH_NUMBER  EHEA_BMASK_IBM(48, 55)
-#define EHEA_EQE_SM_PORT_NUMBER  EHEA_BMASK_IBM(56, 63)
-
-#define EHEA_AER_RESTYPE_QP  0x8
-#define EHEA_AER_RESTYPE_CQ  0x4
-#define EHEA_AER_RESTYPE_EQ  0x3
-
-/* Defines which affiliated errors lead to a port reset */
-#define EHEA_AER_RESET_MASK   0xFFFFFFFFFEFFFFFFULL
-#define EHEA_AERR_RESET_MASK  0xFFFFFFFFFFFFFFFFULL
-
-struct ehea_eqe {
-	u64 entry;
-};
-
-#define ERROR_DATA_LENGTH  EHEA_BMASK_IBM(52, 63)
-#define ERROR_DATA_TYPE    EHEA_BMASK_IBM(0, 7)
-
-static inline void *hw_qeit_calc(struct hw_queue *queue, u64 q_offset)
-{
-	struct ehea_page *current_page;
-
-	if (q_offset >= queue->queue_length)
-		q_offset -= queue->queue_length;
-	current_page = (queue->queue_pages)[q_offset >> EHEA_PAGESHIFT];
-	return &current_page->entries[q_offset & (EHEA_PAGESIZE - 1)];
-}
-
-static inline void *hw_qeit_get(struct hw_queue *queue)
-{
-	return hw_qeit_calc(queue, queue->current_q_offset);
-}
-
-static inline void hw_qeit_inc(struct hw_queue *queue)
-{
-	queue->current_q_offset += queue->qe_size;
-	if (queue->current_q_offset >= queue->queue_length) {
-		queue->current_q_offset = 0;
-		/* toggle the valid flag */
-		queue->toggle_state = (~queue->toggle_state) & 1;
-	}
-}
-
-static inline void *hw_qeit_get_inc(struct hw_queue *queue)
-{
-	void *retvalue = hw_qeit_get(queue);
-	hw_qeit_inc(queue);
-	return retvalue;
-}
-
-static inline void *hw_qeit_get_inc_valid(struct hw_queue *queue)
-{
-	struct ehea_cqe *retvalue = hw_qeit_get(queue);
-	u8 valid = retvalue->valid;
-	void *pref;
-
-	if ((valid >> 7) == (queue->toggle_state & 1)) {
-		/* this is a good one */
-		hw_qeit_inc(queue);
-		pref = hw_qeit_calc(queue, queue->current_q_offset);
-		prefetch(pref);
-		prefetch(pref + 128);
-	} else
-		retvalue = NULL;
-	return retvalue;
-}
-
-static inline void *hw_qeit_get_valid(struct hw_queue *queue)
-{
-	struct ehea_cqe *retvalue = hw_qeit_get(queue);
-	void *pref;
-	u8 valid;
-
-	pref = hw_qeit_calc(queue, queue->current_q_offset);
-	prefetch(pref);
-	prefetch(pref + 128);
-	prefetch(pref + 256);
-	valid = retvalue->valid;
-	if (!((valid >> 7) == (queue->toggle_state & 1)))
-		retvalue = NULL;
-	return retvalue;
-}
-
-static inline void *hw_qeit_reset(struct hw_queue *queue)
-{
-	queue->current_q_offset = 0;
-	return hw_qeit_get(queue);
-}
-
-static inline void *hw_qeit_eq_get_inc(struct hw_queue *queue)
-{
-	u64 last_entry_in_q = queue->queue_length - queue->qe_size;
-	void *retvalue;
-
-	retvalue = hw_qeit_get(queue);
-	queue->current_q_offset += queue->qe_size;
-	if (queue->current_q_offset > last_entry_in_q) {
-		queue->current_q_offset = 0;
-		queue->toggle_state = (~queue->toggle_state) & 1;
-	}
-	return retvalue;
-}
-
-static inline void *hw_eqit_eq_get_inc_valid(struct hw_queue *queue)
-{
-	void *retvalue = hw_qeit_get(queue);
-	u32 qe = *(u8 *)retvalue;
-	if ((qe >> 7) == (queue->toggle_state & 1))
-		hw_qeit_eq_get_inc(queue);
-	else
-		retvalue = NULL;
-	return retvalue;
-}
-
-static inline struct ehea_rwqe *ehea_get_next_rwqe(struct ehea_qp *qp,
-						   int rq_nr)
-{
-	struct hw_queue *queue;
-
-	if (rq_nr == 1)
-		queue = &qp->hw_rqueue1;
-	else if (rq_nr == 2)
-		queue = &qp->hw_rqueue2;
-	else
-		queue = &qp->hw_rqueue3;
-
-	return hw_qeit_get_inc(queue);
-}
-
-static inline struct ehea_swqe *ehea_get_swqe(struct ehea_qp *my_qp,
-					      int *wqe_index)
-{
-	struct hw_queue *queue = &my_qp->hw_squeue;
-	struct ehea_swqe *wqe_p;
-
-	*wqe_index = (queue->current_q_offset) >> (7 + EHEA_SG_SQ);
-	wqe_p = hw_qeit_get_inc(&my_qp->hw_squeue);
-
-	return wqe_p;
-}
-
-static inline void ehea_post_swqe(struct ehea_qp *my_qp, struct ehea_swqe *swqe)
-{
-	iosync();
-	ehea_update_sqa(my_qp, 1);
-}
-
-static inline struct ehea_cqe *ehea_poll_rq1(struct ehea_qp *qp, int *wqe_index)
-{
-	struct hw_queue *queue = &qp->hw_rqueue1;
-
-	*wqe_index = (queue->current_q_offset) >> (7 + EHEA_SG_RQ1);
-	return hw_qeit_get_valid(queue);
-}
-
-static inline void ehea_inc_cq(struct ehea_cq *cq)
-{
-	hw_qeit_inc(&cq->hw_queue);
-}
-
-static inline void ehea_inc_rq1(struct ehea_qp *qp)
-{
-	hw_qeit_inc(&qp->hw_rqueue1);
-}
-
-static inline struct ehea_cqe *ehea_poll_cq(struct ehea_cq *my_cq)
-{
-	return hw_qeit_get_valid(&my_cq->hw_queue);
-}
-
-#define EHEA_CQ_REGISTER_ORIG 0
-#define EHEA_EQ_REGISTER_ORIG 0
-
-enum ehea_eq_type {
-	EHEA_EQ = 0,		/* event queue              */
-	EHEA_NEQ		/* notification event queue */
-};
-
-struct ehea_eq *ehea_create_eq(struct ehea_adapter *adapter,
-			       enum ehea_eq_type type,
-			       const u32 length, const u8 eqe_gen);
-
-int ehea_destroy_eq(struct ehea_eq *eq);
-
-struct ehea_eqe *ehea_poll_eq(struct ehea_eq *eq);
-
-struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter, int cqe,
-			       u64 eq_handle, u32 cq_token);
-
-int ehea_destroy_cq(struct ehea_cq *cq);
-
-struct ehea_qp *ehea_create_qp(struct ehea_adapter *adapter, u32 pd,
-			       struct ehea_qp_init_attr *init_attr);
-
-int ehea_destroy_qp(struct ehea_qp *qp);
-
-int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr);
-
-int ehea_gen_smr(struct ehea_adapter *adapter, struct ehea_mr *old_mr,
-		 struct ehea_mr *shared_mr);
-
-int ehea_rem_mr(struct ehea_mr *mr);
-
-u64 ehea_error_data(struct ehea_adapter *adapter, u64 res_handle,
-		    u64 *aer, u64 *aerr);
-
-int ehea_add_sect_bmap(unsigned long pfn, unsigned long nr_pages);
-int ehea_rem_sect_bmap(unsigned long pfn, unsigned long nr_pages);
-int ehea_create_busmap(void);
-void ehea_destroy_busmap(void);
-u64 ehea_map_vaddr(void *caddr);
-
-#endif	/* __EHEA_QMR_H__ */
diff -druN linux-libre-3.1-gnu/drivers/net/ehea/Makefile linux-libre-3.2-gnu/drivers/net/ehea/Makefile
--- linux-libre-3.1-gnu/drivers/net/ehea/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/ehea/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#
-# Makefile for the eHEA ethernet device driver for IBM eServer System p
-#
-ehea-y = ehea_main.o ehea_phyp.o ehea_qmr.o ehea_ethtool.o ehea_phyp.o
-obj-$(CONFIG_EHEA) += ehea.o
-
diff -druN linux-libre-3.1-gnu/drivers/net/enc28j60.c linux-libre-3.2-gnu/drivers/net/enc28j60.c
--- linux-libre-3.1-gnu/drivers/net/enc28j60.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enc28j60.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1667 +0,0 @@
-/*
- * Microchip ENC28J60 ethernet driver (MAC + PHY)
- *
- * Copyright (C) 2007 Eurek srl
- * Author: Claudio Lanconelli <lanconelli.claudio@eptar.com>
- * based on enc28j60.c written by David Anders for 2.4 kernel version
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * $Id: enc28j60.c,v 1.22 2007/12/20 10:47:01 claudio Exp $
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/tcp.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
-#include <linux/spi/spi.h>
-
-#include "enc28j60_hw.h"
-
-#define DRV_NAME	"enc28j60"
-#define DRV_VERSION	"1.01"
-
-#define SPI_OPLEN	1
-
-#define ENC28J60_MSG_DEFAULT	\
-	(NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN | NETIF_MSG_LINK)
-
-/* Buffer size required for the largest SPI transfer (i.e., reading a
- * frame). */
-#define SPI_TRANSFER_BUF_LEN	(4 + MAX_FRAMELEN)
-
-#define TX_TIMEOUT	(4 * HZ)
-
-/* Max TX retries in case of collision as suggested by errata datasheet */
-#define MAX_TX_RETRYCOUNT	16
-
-enum {
-	RXFILTER_NORMAL,
-	RXFILTER_MULTI,
-	RXFILTER_PROMISC
-};
-
-/* Driver local data */
-struct enc28j60_net {
-	struct net_device *netdev;
-	struct spi_device *spi;
-	struct mutex lock;
-	struct sk_buff *tx_skb;
-	struct work_struct tx_work;
-	struct work_struct irq_work;
-	struct work_struct setrx_work;
-	struct work_struct restart_work;
-	u8 bank;		/* current register bank selected */
-	u16 next_pk_ptr;	/* next packet pointer within FIFO */
-	u16 max_pk_counter;	/* statistics: max packet counter */
-	u16 tx_retry_count;
-	bool hw_enable;
-	bool full_duplex;
-	int rxfilter;
-	u32 msg_enable;
-	u8 spi_transfer_buf[SPI_TRANSFER_BUF_LEN];
-};
-
-/* use ethtool to change the level for any given device */
-static struct {
-	u32 msg_enable;
-} debug = { -1 };
-
-/*
- * SPI read buffer
- * wait for the SPI transfer and copy received data to destination
- */
-static int
-spi_read_buf(struct enc28j60_net *priv, int len, u8 *data)
-{
-	u8 *rx_buf = priv->spi_transfer_buf + 4;
-	u8 *tx_buf = priv->spi_transfer_buf;
-	struct spi_transfer t = {
-		.tx_buf = tx_buf,
-		.rx_buf = rx_buf,
-		.len = SPI_OPLEN + len,
-	};
-	struct spi_message msg;
-	int ret;
-
-	tx_buf[0] = ENC28J60_READ_BUF_MEM;
-	tx_buf[1] = tx_buf[2] = tx_buf[3] = 0;	/* don't care */
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&t, &msg);
-	ret = spi_sync(priv->spi, &msg);
-	if (ret == 0) {
-		memcpy(data, &rx_buf[SPI_OPLEN], len);
-		ret = msg.status;
-	}
-	if (ret && netif_msg_drv(priv))
-		printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
-			__func__, ret);
-
-	return ret;
-}
-
-/*
- * SPI write buffer
- */
-static int spi_write_buf(struct enc28j60_net *priv, int len,
-			 const u8 *data)
-{
-	int ret;
-
-	if (len > SPI_TRANSFER_BUF_LEN - 1 || len <= 0)
-		ret = -EINVAL;
-	else {
-		priv->spi_transfer_buf[0] = ENC28J60_WRITE_BUF_MEM;
-		memcpy(&priv->spi_transfer_buf[1], data, len);
-		ret = spi_write(priv->spi, priv->spi_transfer_buf, len + 1);
-		if (ret && netif_msg_drv(priv))
-			printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
-				__func__, ret);
-	}
-	return ret;
-}
-
-/*
- * basic SPI read operation
- */
-static u8 spi_read_op(struct enc28j60_net *priv, u8 op,
-			   u8 addr)
-{
-	u8 tx_buf[2];
-	u8 rx_buf[4];
-	u8 val = 0;
-	int ret;
-	int slen = SPI_OPLEN;
-
-	/* do dummy read if needed */
-	if (addr & SPRD_MASK)
-		slen++;
-
-	tx_buf[0] = op | (addr & ADDR_MASK);
-	ret = spi_write_then_read(priv->spi, tx_buf, 1, rx_buf, slen);
-	if (ret)
-		printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
-			__func__, ret);
-	else
-		val = rx_buf[slen - 1];
-
-	return val;
-}
-
-/*
- * basic SPI write operation
- */
-static int spi_write_op(struct enc28j60_net *priv, u8 op,
-			u8 addr, u8 val)
-{
-	int ret;
-
-	priv->spi_transfer_buf[0] = op | (addr & ADDR_MASK);
-	priv->spi_transfer_buf[1] = val;
-	ret = spi_write(priv->spi, priv->spi_transfer_buf, 2);
-	if (ret && netif_msg_drv(priv))
-		printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
-			__func__, ret);
-	return ret;
-}
-
-static void enc28j60_soft_reset(struct enc28j60_net *priv)
-{
-	if (netif_msg_hw(priv))
-		printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__);
-
-	spi_write_op(priv, ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
-	/* Errata workaround #1, CLKRDY check is unreliable,
-	 * delay at least 1 mS instead */
-	udelay(2000);
-}
-
-/*
- * select the current register bank if necessary
- */
-static void enc28j60_set_bank(struct enc28j60_net *priv, u8 addr)
-{
-	u8 b = (addr & BANK_MASK) >> 5;
-
-	/* These registers (EIE, EIR, ESTAT, ECON2, ECON1)
-	 * are present in all banks, no need to switch bank
-	 */
-	if (addr >= EIE && addr <= ECON1)
-		return;
-
-	/* Clear or set each bank selection bit as needed */
-	if ((b & ECON1_BSEL0) != (priv->bank & ECON1_BSEL0)) {
-		if (b & ECON1_BSEL0)
-			spi_write_op(priv, ENC28J60_BIT_FIELD_SET, ECON1,
-					ECON1_BSEL0);
-		else
-			spi_write_op(priv, ENC28J60_BIT_FIELD_CLR, ECON1,
-					ECON1_BSEL0);
-	}
-	if ((b & ECON1_BSEL1) != (priv->bank & ECON1_BSEL1)) {
-		if (b & ECON1_BSEL1)
-			spi_write_op(priv, ENC28J60_BIT_FIELD_SET, ECON1,
-					ECON1_BSEL1);
-		else
-			spi_write_op(priv, ENC28J60_BIT_FIELD_CLR, ECON1,
-					ECON1_BSEL1);
-	}
-	priv->bank = b;
-}
-
-/*
- * Register access routines through the SPI bus.
- * Every register access comes in two flavours:
- * - nolock_xxx: caller needs to invoke mutex_lock, usually to access
- *   atomically more than one register
- * - locked_xxx: caller doesn't need to invoke mutex_lock, single access
- *
- * Some registers can be accessed through the bit field clear and
- * bit field set to avoid a read modify write cycle.
- */
-
-/*
- * Register bit field Set
- */
-static void nolock_reg_bfset(struct enc28j60_net *priv,
-				      u8 addr, u8 mask)
-{
-	enc28j60_set_bank(priv, addr);
-	spi_write_op(priv, ENC28J60_BIT_FIELD_SET, addr, mask);
-}
-
-static void locked_reg_bfset(struct enc28j60_net *priv,
-				      u8 addr, u8 mask)
-{
-	mutex_lock(&priv->lock);
-	nolock_reg_bfset(priv, addr, mask);
-	mutex_unlock(&priv->lock);
-}
-
-/*
- * Register bit field Clear
- */
-static void nolock_reg_bfclr(struct enc28j60_net *priv,
-				      u8 addr, u8 mask)
-{
-	enc28j60_set_bank(priv, addr);
-	spi_write_op(priv, ENC28J60_BIT_FIELD_CLR, addr, mask);
-}
-
-static void locked_reg_bfclr(struct enc28j60_net *priv,
-				      u8 addr, u8 mask)
-{
-	mutex_lock(&priv->lock);
-	nolock_reg_bfclr(priv, addr, mask);
-	mutex_unlock(&priv->lock);
-}
-
-/*
- * Register byte read
- */
-static int nolock_regb_read(struct enc28j60_net *priv,
-				     u8 address)
-{
-	enc28j60_set_bank(priv, address);
-	return spi_read_op(priv, ENC28J60_READ_CTRL_REG, address);
-}
-
-static int locked_regb_read(struct enc28j60_net *priv,
-				     u8 address)
-{
-	int ret;
-
-	mutex_lock(&priv->lock);
-	ret = nolock_regb_read(priv, address);
-	mutex_unlock(&priv->lock);
-
-	return ret;
-}
-
-/*
- * Register word read
- */
-static int nolock_regw_read(struct enc28j60_net *priv,
-				     u8 address)
-{
-	int rl, rh;
-
-	enc28j60_set_bank(priv, address);
-	rl = spi_read_op(priv, ENC28J60_READ_CTRL_REG, address);
-	rh = spi_read_op(priv, ENC28J60_READ_CTRL_REG, address + 1);
-
-	return (rh << 8) | rl;
-}
-
-static int locked_regw_read(struct enc28j60_net *priv,
-				     u8 address)
-{
-	int ret;
-
-	mutex_lock(&priv->lock);
-	ret = nolock_regw_read(priv, address);
-	mutex_unlock(&priv->lock);
-
-	return ret;
-}
-
-/*
- * Register byte write
- */
-static void nolock_regb_write(struct enc28j60_net *priv,
-				       u8 address, u8 data)
-{
-	enc28j60_set_bank(priv, address);
-	spi_write_op(priv, ENC28J60_WRITE_CTRL_REG, address, data);
-}
-
-static void locked_regb_write(struct enc28j60_net *priv,
-				       u8 address, u8 data)
-{
-	mutex_lock(&priv->lock);
-	nolock_regb_write(priv, address, data);
-	mutex_unlock(&priv->lock);
-}
-
-/*
- * Register word write
- */
-static void nolock_regw_write(struct enc28j60_net *priv,
-				       u8 address, u16 data)
-{
-	enc28j60_set_bank(priv, address);
-	spi_write_op(priv, ENC28J60_WRITE_CTRL_REG, address, (u8) data);
-	spi_write_op(priv, ENC28J60_WRITE_CTRL_REG, address + 1,
-		     (u8) (data >> 8));
-}
-
-static void locked_regw_write(struct enc28j60_net *priv,
-				       u8 address, u16 data)
-{
-	mutex_lock(&priv->lock);
-	nolock_regw_write(priv, address, data);
-	mutex_unlock(&priv->lock);
-}
-
-/*
- * Buffer memory read
- * Select the starting address and execute a SPI buffer read
- */
-static void enc28j60_mem_read(struct enc28j60_net *priv,
-				     u16 addr, int len, u8 *data)
-{
-	mutex_lock(&priv->lock);
-	nolock_regw_write(priv, ERDPTL, addr);
-#ifdef CONFIG_ENC28J60_WRITEVERIFY
-	if (netif_msg_drv(priv)) {
-		u16 reg;
-		reg = nolock_regw_read(priv, ERDPTL);
-		if (reg != addr)
-			printk(KERN_DEBUG DRV_NAME ": %s() error writing ERDPT "
-				"(0x%04x - 0x%04x)\n", __func__, reg, addr);
-	}
-#endif
-	spi_read_buf(priv, len, data);
-	mutex_unlock(&priv->lock);
-}
-
-/*
- * Write packet to enc28j60 TX buffer memory
- */
-static void
-enc28j60_packet_write(struct enc28j60_net *priv, int len, const u8 *data)
-{
-	mutex_lock(&priv->lock);
-	/* Set the write pointer to start of transmit buffer area */
-	nolock_regw_write(priv, EWRPTL, TXSTART_INIT);
-#ifdef CONFIG_ENC28J60_WRITEVERIFY
-	if (netif_msg_drv(priv)) {
-		u16 reg;
-		reg = nolock_regw_read(priv, EWRPTL);
-		if (reg != TXSTART_INIT)
-			printk(KERN_DEBUG DRV_NAME
-				": %s() ERWPT:0x%04x != 0x%04x\n",
-				__func__, reg, TXSTART_INIT);
-	}
-#endif
-	/* Set the TXND pointer to correspond to the packet size given */
-	nolock_regw_write(priv, ETXNDL, TXSTART_INIT + len);
-	/* write per-packet control byte */
-	spi_write_op(priv, ENC28J60_WRITE_BUF_MEM, 0, 0x00);
-	if (netif_msg_hw(priv))
-		printk(KERN_DEBUG DRV_NAME
-			": %s() after control byte ERWPT:0x%04x\n",
-			__func__, nolock_regw_read(priv, EWRPTL));
-	/* copy the packet into the transmit buffer */
-	spi_write_buf(priv, len, data);
-	if (netif_msg_hw(priv))
-		printk(KERN_DEBUG DRV_NAME
-			 ": %s() after write packet ERWPT:0x%04x, len=%d\n",
-			 __func__, nolock_regw_read(priv, EWRPTL), len);
-	mutex_unlock(&priv->lock);
-}
-
-static unsigned long msec20_to_jiffies;
-
-static int poll_ready(struct enc28j60_net *priv, u8 reg, u8 mask, u8 val)
-{
-	unsigned long timeout = jiffies + msec20_to_jiffies;
-
-	/* 20 msec timeout read */
-	while ((nolock_regb_read(priv, reg) & mask) != val) {
-		if (time_after(jiffies, timeout)) {
-			if (netif_msg_drv(priv))
-				dev_dbg(&priv->spi->dev,
-					"reg %02x ready timeout!\n", reg);
-			return -ETIMEDOUT;
-		}
-		cpu_relax();
-	}
-	return 0;
-}
-
-/*
- * Wait until the PHY operation is complete.
- */
-static int wait_phy_ready(struct enc28j60_net *priv)
-{
-	return poll_ready(priv, MISTAT, MISTAT_BUSY, 0) ? 0 : 1;
-}
-
-/*
- * PHY register read
- * PHY registers are not accessed directly, but through the MII
- */
-static u16 enc28j60_phy_read(struct enc28j60_net *priv, u8 address)
-{
-	u16 ret;
-
-	mutex_lock(&priv->lock);
-	/* set the PHY register address */
-	nolock_regb_write(priv, MIREGADR, address);
-	/* start the register read operation */
-	nolock_regb_write(priv, MICMD, MICMD_MIIRD);
-	/* wait until the PHY read completes */
-	wait_phy_ready(priv);
-	/* quit reading */
-	nolock_regb_write(priv, MICMD, 0x00);
-	/* return the data */
-	ret  = nolock_regw_read(priv, MIRDL);
-	mutex_unlock(&priv->lock);
-
-	return ret;
-}
-
-static int enc28j60_phy_write(struct enc28j60_net *priv, u8 address, u16 data)
-{
-	int ret;
-
-	mutex_lock(&priv->lock);
-	/* set the PHY register address */
-	nolock_regb_write(priv, MIREGADR, address);
-	/* write the PHY data */
-	nolock_regw_write(priv, MIWRL, data);
-	/* wait until the PHY write completes and return */
-	ret = wait_phy_ready(priv);
-	mutex_unlock(&priv->lock);
-
-	return ret;
-}
-
-/*
- * Program the hardware MAC address from dev->dev_addr.
- */
-static int enc28j60_set_hw_macaddr(struct net_device *ndev)
-{
-	int ret;
-	struct enc28j60_net *priv = netdev_priv(ndev);
-
-	mutex_lock(&priv->lock);
-	if (!priv->hw_enable) {
-		if (netif_msg_drv(priv))
-			printk(KERN_INFO DRV_NAME
-				": %s: Setting MAC address to %pM\n",
-				ndev->name, ndev->dev_addr);
-		/* NOTE: MAC address in ENC28J60 is byte-backward */
-		nolock_regb_write(priv, MAADR5, ndev->dev_addr[0]);
-		nolock_regb_write(priv, MAADR4, ndev->dev_addr[1]);
-		nolock_regb_write(priv, MAADR3, ndev->dev_addr[2]);
-		nolock_regb_write(priv, MAADR2, ndev->dev_addr[3]);
-		nolock_regb_write(priv, MAADR1, ndev->dev_addr[4]);
-		nolock_regb_write(priv, MAADR0, ndev->dev_addr[5]);
-		ret = 0;
-	} else {
-		if (netif_msg_drv(priv))
-			printk(KERN_DEBUG DRV_NAME
-				": %s() Hardware must be disabled to set "
-				"Mac address\n", __func__);
-		ret = -EBUSY;
-	}
-	mutex_unlock(&priv->lock);
-	return ret;
-}
-
-/*
- * Store the new hardware address in dev->dev_addr, and update the MAC.
- */
-static int enc28j60_set_mac_address(struct net_device *dev, void *addr)
-{
-	struct sockaddr *address = addr;
-
-	if (netif_running(dev))
-		return -EBUSY;
-	if (!is_valid_ether_addr(address->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
-	return enc28j60_set_hw_macaddr(dev);
-}
-
-/*
- * Debug routine to dump useful register contents
- */
-static void enc28j60_dump_regs(struct enc28j60_net *priv, const char *msg)
-{
-	mutex_lock(&priv->lock);
-	printk(KERN_DEBUG DRV_NAME " %s\n"
-		"HwRevID: 0x%02x\n"
-		"Cntrl: ECON1 ECON2 ESTAT  EIR  EIE\n"
-		"       0x%02x  0x%02x  0x%02x  0x%02x  0x%02x\n"
-		"MAC  : MACON1 MACON3 MACON4\n"
-		"       0x%02x   0x%02x   0x%02x\n"
-		"Rx   : ERXST  ERXND  ERXWRPT ERXRDPT ERXFCON EPKTCNT MAMXFL\n"
-		"       0x%04x 0x%04x 0x%04x  0x%04x  "
-		"0x%02x    0x%02x    0x%04x\n"
-		"Tx   : ETXST  ETXND  MACLCON1 MACLCON2 MAPHSUP\n"
-		"       0x%04x 0x%04x 0x%02x     0x%02x     0x%02x\n",
-		msg, nolock_regb_read(priv, EREVID),
-		nolock_regb_read(priv, ECON1), nolock_regb_read(priv, ECON2),
-		nolock_regb_read(priv, ESTAT), nolock_regb_read(priv, EIR),
-		nolock_regb_read(priv, EIE), nolock_regb_read(priv, MACON1),
-		nolock_regb_read(priv, MACON3), nolock_regb_read(priv, MACON4),
-		nolock_regw_read(priv, ERXSTL), nolock_regw_read(priv, ERXNDL),
-		nolock_regw_read(priv, ERXWRPTL),
-		nolock_regw_read(priv, ERXRDPTL),
-		nolock_regb_read(priv, ERXFCON),
-		nolock_regb_read(priv, EPKTCNT),
-		nolock_regw_read(priv, MAMXFLL), nolock_regw_read(priv, ETXSTL),
-		nolock_regw_read(priv, ETXNDL),
-		nolock_regb_read(priv, MACLCON1),
-		nolock_regb_read(priv, MACLCON2),
-		nolock_regb_read(priv, MAPHSUP));
-	mutex_unlock(&priv->lock);
-}
-
-/*
- * ERXRDPT need to be set always at odd addresses, refer to errata datasheet
- */
-static u16 erxrdpt_workaround(u16 next_packet_ptr, u16 start, u16 end)
-{
-	u16 erxrdpt;
-
-	if ((next_packet_ptr - 1 < start) || (next_packet_ptr - 1 > end))
-		erxrdpt = end;
-	else
-		erxrdpt = next_packet_ptr - 1;
-
-	return erxrdpt;
-}
-
-/*
- * Calculate wrap around when reading beyond the end of the RX buffer
- */
-static u16 rx_packet_start(u16 ptr)
-{
-	if (ptr + RSV_SIZE > RXEND_INIT)
-		return (ptr + RSV_SIZE) - (RXEND_INIT - RXSTART_INIT + 1);
-	else
-		return ptr + RSV_SIZE;
-}
-
-static void nolock_rxfifo_init(struct enc28j60_net *priv, u16 start, u16 end)
-{
-	u16 erxrdpt;
-
-	if (start > 0x1FFF || end > 0x1FFF || start > end) {
-		if (netif_msg_drv(priv))
-			printk(KERN_ERR DRV_NAME ": %s(%d, %d) RXFIFO "
-				"bad parameters!\n", __func__, start, end);
-		return;
-	}
-	/* set receive buffer start + end */
-	priv->next_pk_ptr = start;
-	nolock_regw_write(priv, ERXSTL, start);
-	erxrdpt = erxrdpt_workaround(priv->next_pk_ptr, start, end);
-	nolock_regw_write(priv, ERXRDPTL, erxrdpt);
-	nolock_regw_write(priv, ERXNDL, end);
-}
-
-static void nolock_txfifo_init(struct enc28j60_net *priv, u16 start, u16 end)
-{
-	if (start > 0x1FFF || end > 0x1FFF || start > end) {
-		if (netif_msg_drv(priv))
-			printk(KERN_ERR DRV_NAME ": %s(%d, %d) TXFIFO "
-				"bad parameters!\n", __func__, start, end);
-		return;
-	}
-	/* set transmit buffer start + end */
-	nolock_regw_write(priv, ETXSTL, start);
-	nolock_regw_write(priv, ETXNDL, end);
-}
-
-/*
- * Low power mode shrinks power consumption about 100x, so we'd like
- * the chip to be in that mode whenever it's inactive.  (However, we
- * can't stay in lowpower mode during suspend with WOL active.)
- */
-static void enc28j60_lowpower(struct enc28j60_net *priv, bool is_low)
-{
-	if (netif_msg_drv(priv))
-		dev_dbg(&priv->spi->dev, "%s power...\n",
-				is_low ? "low" : "high");
-
-	mutex_lock(&priv->lock);
-	if (is_low) {
-		nolock_reg_bfclr(priv, ECON1, ECON1_RXEN);
-		poll_ready(priv, ESTAT, ESTAT_RXBUSY, 0);
-		poll_ready(priv, ECON1, ECON1_TXRTS, 0);
-		/* ECON2_VRPS was set during initialization */
-		nolock_reg_bfset(priv, ECON2, ECON2_PWRSV);
-	} else {
-		nolock_reg_bfclr(priv, ECON2, ECON2_PWRSV);
-		poll_ready(priv, ESTAT, ESTAT_CLKRDY, ESTAT_CLKRDY);
-		/* caller sets ECON1_RXEN */
-	}
-	mutex_unlock(&priv->lock);
-}
-
-static int enc28j60_hw_init(struct enc28j60_net *priv)
-{
-	u8 reg;
-
-	if (netif_msg_drv(priv))
-		printk(KERN_DEBUG DRV_NAME ": %s() - %s\n", __func__,
-			priv->full_duplex ? "FullDuplex" : "HalfDuplex");
-
-	mutex_lock(&priv->lock);
-	/* first reset the chip */
-	enc28j60_soft_reset(priv);
-	/* Clear ECON1 */
-	spi_write_op(priv, ENC28J60_WRITE_CTRL_REG, ECON1, 0x00);
-	priv->bank = 0;
-	priv->hw_enable = false;
-	priv->tx_retry_count = 0;
-	priv->max_pk_counter = 0;
-	priv->rxfilter = RXFILTER_NORMAL;
-	/* enable address auto increment and voltage regulator powersave */
-	nolock_regb_write(priv, ECON2, ECON2_AUTOINC | ECON2_VRPS);
-
-	nolock_rxfifo_init(priv, RXSTART_INIT, RXEND_INIT);
-	nolock_txfifo_init(priv, TXSTART_INIT, TXEND_INIT);
-	mutex_unlock(&priv->lock);
-
-	/*
-	 * Check the RevID.
-	 * If it's 0x00 or 0xFF probably the enc28j60 is not mounted or
-	 * damaged
-	 */
-	reg = locked_regb_read(priv, EREVID);
-	if (netif_msg_drv(priv))
-		printk(KERN_INFO DRV_NAME ": chip RevID: 0x%02x\n", reg);
-	if (reg == 0x00 || reg == 0xff) {
-		if (netif_msg_drv(priv))
-			printk(KERN_DEBUG DRV_NAME ": %s() Invalid RevId %d\n",
-				__func__, reg);
-		return 0;
-	}
-
-	/* default filter mode: (unicast OR broadcast) AND crc valid */
-	locked_regb_write(priv, ERXFCON,
-			    ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_BCEN);
-
-	/* enable MAC receive */
-	locked_regb_write(priv, MACON1,
-			    MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS);
-	/* enable automatic padding and CRC operations */
-	if (priv->full_duplex) {
-		locked_regb_write(priv, MACON3,
-				    MACON3_PADCFG0 | MACON3_TXCRCEN |
-				    MACON3_FRMLNEN | MACON3_FULDPX);
-		/* set inter-frame gap (non-back-to-back) */
-		locked_regb_write(priv, MAIPGL, 0x12);
-		/* set inter-frame gap (back-to-back) */
-		locked_regb_write(priv, MABBIPG, 0x15);
-	} else {
-		locked_regb_write(priv, MACON3,
-				    MACON3_PADCFG0 | MACON3_TXCRCEN |
-				    MACON3_FRMLNEN);
-		locked_regb_write(priv, MACON4, 1 << 6);	/* DEFER bit */
-		/* set inter-frame gap (non-back-to-back) */
-		locked_regw_write(priv, MAIPGL, 0x0C12);
-		/* set inter-frame gap (back-to-back) */
-		locked_regb_write(priv, MABBIPG, 0x12);
-	}
-	/*
-	 * MACLCON1 (default)
-	 * MACLCON2 (default)
-	 * Set the maximum packet size which the controller will accept
-	 */
-	locked_regw_write(priv, MAMXFLL, MAX_FRAMELEN);
-
-	/* Configure LEDs */
-	if (!enc28j60_phy_write(priv, PHLCON, ENC28J60_LAMPS_MODE))
-		return 0;
-
-	if (priv->full_duplex) {
-		if (!enc28j60_phy_write(priv, PHCON1, PHCON1_PDPXMD))
-			return 0;
-		if (!enc28j60_phy_write(priv, PHCON2, 0x00))
-			return 0;
-	} else {
-		if (!enc28j60_phy_write(priv, PHCON1, 0x00))
-			return 0;
-		if (!enc28j60_phy_write(priv, PHCON2, PHCON2_HDLDIS))
-			return 0;
-	}
-	if (netif_msg_hw(priv))
-		enc28j60_dump_regs(priv, "Hw initialized.");
-
-	return 1;
-}
-
-static void enc28j60_hw_enable(struct enc28j60_net *priv)
-{
-	/* enable interrupts */
-	if (netif_msg_hw(priv))
-		printk(KERN_DEBUG DRV_NAME ": %s() enabling interrupts.\n",
-			__func__);
-
-	enc28j60_phy_write(priv, PHIE, PHIE_PGEIE | PHIE_PLNKIE);
-
-	mutex_lock(&priv->lock);
-	nolock_reg_bfclr(priv, EIR, EIR_DMAIF | EIR_LINKIF |
-			 EIR_TXIF | EIR_TXERIF | EIR_RXERIF | EIR_PKTIF);
-	nolock_regb_write(priv, EIE, EIE_INTIE | EIE_PKTIE | EIE_LINKIE |
-			  EIE_TXIE | EIE_TXERIE | EIE_RXERIE);
-
-	/* enable receive logic */
-	nolock_reg_bfset(priv, ECON1, ECON1_RXEN);
-	priv->hw_enable = true;
-	mutex_unlock(&priv->lock);
-}
-
-static void enc28j60_hw_disable(struct enc28j60_net *priv)
-{
-	mutex_lock(&priv->lock);
-	/* disable interrutps and packet reception */
-	nolock_regb_write(priv, EIE, 0x00);
-	nolock_reg_bfclr(priv, ECON1, ECON1_RXEN);
-	priv->hw_enable = false;
-	mutex_unlock(&priv->lock);
-}
-
-static int
-enc28j60_setlink(struct net_device *ndev, u8 autoneg, u16 speed, u8 duplex)
-{
-	struct enc28j60_net *priv = netdev_priv(ndev);
-	int ret = 0;
-
-	if (!priv->hw_enable) {
-		/* link is in low power mode now; duplex setting
-		 * will take effect on next enc28j60_hw_init().
-		 */
-		if (autoneg == AUTONEG_DISABLE && speed == SPEED_10)
-			priv->full_duplex = (duplex == DUPLEX_FULL);
-		else {
-			if (netif_msg_link(priv))
-				dev_warn(&ndev->dev,
-					"unsupported link setting\n");
-			ret = -EOPNOTSUPP;
-		}
-	} else {
-		if (netif_msg_link(priv))
-			dev_warn(&ndev->dev, "Warning: hw must be disabled "
-				"to set link mode\n");
-		ret = -EBUSY;
-	}
-	return ret;
-}
-
-/*
- * Read the Transmit Status Vector
- */
-static void enc28j60_read_tsv(struct enc28j60_net *priv, u8 tsv[TSV_SIZE])
-{
-	int endptr;
-
-	endptr = locked_regw_read(priv, ETXNDL);
-	if (netif_msg_hw(priv))
-		printk(KERN_DEBUG DRV_NAME ": reading TSV at addr:0x%04x\n",
-			 endptr + 1);
-	enc28j60_mem_read(priv, endptr + 1, TSV_SIZE, tsv);
-}
-
-static void enc28j60_dump_tsv(struct enc28j60_net *priv, const char *msg,
-				u8 tsv[TSV_SIZE])
-{
-	u16 tmp1, tmp2;
-
-	printk(KERN_DEBUG DRV_NAME ": %s - TSV:\n", msg);
-	tmp1 = tsv[1];
-	tmp1 <<= 8;
-	tmp1 |= tsv[0];
-
-	tmp2 = tsv[5];
-	tmp2 <<= 8;
-	tmp2 |= tsv[4];
-
-	printk(KERN_DEBUG DRV_NAME ": ByteCount: %d, CollisionCount: %d,"
-		" TotByteOnWire: %d\n", tmp1, tsv[2] & 0x0f, tmp2);
-	printk(KERN_DEBUG DRV_NAME ": TxDone: %d, CRCErr:%d, LenChkErr: %d,"
-		" LenOutOfRange: %d\n", TSV_GETBIT(tsv, TSV_TXDONE),
-		TSV_GETBIT(tsv, TSV_TXCRCERROR),
-		TSV_GETBIT(tsv, TSV_TXLENCHKERROR),
-		TSV_GETBIT(tsv, TSV_TXLENOUTOFRANGE));
-	printk(KERN_DEBUG DRV_NAME ": Multicast: %d, Broadcast: %d, "
-		"PacketDefer: %d, ExDefer: %d\n",
-		TSV_GETBIT(tsv, TSV_TXMULTICAST),
-		TSV_GETBIT(tsv, TSV_TXBROADCAST),
-		TSV_GETBIT(tsv, TSV_TXPACKETDEFER),
-		TSV_GETBIT(tsv, TSV_TXEXDEFER));
-	printk(KERN_DEBUG DRV_NAME ": ExCollision: %d, LateCollision: %d, "
-		 "Giant: %d, Underrun: %d\n",
-		 TSV_GETBIT(tsv, TSV_TXEXCOLLISION),
-		 TSV_GETBIT(tsv, TSV_TXLATECOLLISION),
-		 TSV_GETBIT(tsv, TSV_TXGIANT), TSV_GETBIT(tsv, TSV_TXUNDERRUN));
-	printk(KERN_DEBUG DRV_NAME ": ControlFrame: %d, PauseFrame: %d, "
-		 "BackPressApp: %d, VLanTagFrame: %d\n",
-		 TSV_GETBIT(tsv, TSV_TXCONTROLFRAME),
-		 TSV_GETBIT(tsv, TSV_TXPAUSEFRAME),
-		 TSV_GETBIT(tsv, TSV_BACKPRESSUREAPP),
-		 TSV_GETBIT(tsv, TSV_TXVLANTAGFRAME));
-}
-
-/*
- * Receive Status vector
- */
-static void enc28j60_dump_rsv(struct enc28j60_net *priv, const char *msg,
-			      u16 pk_ptr, int len, u16 sts)
-{
-	printk(KERN_DEBUG DRV_NAME ": %s - NextPk: 0x%04x - RSV:\n",
-		msg, pk_ptr);
-	printk(KERN_DEBUG DRV_NAME ": ByteCount: %d, DribbleNibble: %d\n", len,
-		 RSV_GETBIT(sts, RSV_DRIBBLENIBBLE));
-	printk(KERN_DEBUG DRV_NAME ": RxOK: %d, CRCErr:%d, LenChkErr: %d,"
-		 " LenOutOfRange: %d\n", RSV_GETBIT(sts, RSV_RXOK),
-		 RSV_GETBIT(sts, RSV_CRCERROR),
-		 RSV_GETBIT(sts, RSV_LENCHECKERR),
-		 RSV_GETBIT(sts, RSV_LENOUTOFRANGE));
-	printk(KERN_DEBUG DRV_NAME ": Multicast: %d, Broadcast: %d, "
-		 "LongDropEvent: %d, CarrierEvent: %d\n",
-		 RSV_GETBIT(sts, RSV_RXMULTICAST),
-		 RSV_GETBIT(sts, RSV_RXBROADCAST),
-		 RSV_GETBIT(sts, RSV_RXLONGEVDROPEV),
-		 RSV_GETBIT(sts, RSV_CARRIEREV));
-	printk(KERN_DEBUG DRV_NAME ": ControlFrame: %d, PauseFrame: %d,"
-		 " UnknownOp: %d, VLanTagFrame: %d\n",
-		 RSV_GETBIT(sts, RSV_RXCONTROLFRAME),
-		 RSV_GETBIT(sts, RSV_RXPAUSEFRAME),
-		 RSV_GETBIT(sts, RSV_RXUNKNOWNOPCODE),
-		 RSV_GETBIT(sts, RSV_RXTYPEVLAN));
-}
-
-static void dump_packet(const char *msg, int len, const char *data)
-{
-	printk(KERN_DEBUG DRV_NAME ": %s - packet len:%d\n", msg, len);
-	print_hex_dump(KERN_DEBUG, "pk data: ", DUMP_PREFIX_OFFSET, 16, 1,
-			data, len, true);
-}
-
-/*
- * Hardware receive function.
- * Read the buffer memory, update the FIFO pointer to free the buffer,
- * check the status vector and decrement the packet counter.
- */
-static void enc28j60_hw_rx(struct net_device *ndev)
-{
-	struct enc28j60_net *priv = netdev_priv(ndev);
-	struct sk_buff *skb = NULL;
-	u16 erxrdpt, next_packet, rxstat;
-	u8 rsv[RSV_SIZE];
-	int len;
-
-	if (netif_msg_rx_status(priv))
-		printk(KERN_DEBUG DRV_NAME ": RX pk_addr:0x%04x\n",
-			priv->next_pk_ptr);
-
-	if (unlikely(priv->next_pk_ptr > RXEND_INIT)) {
-		if (netif_msg_rx_err(priv))
-			dev_err(&ndev->dev,
-				"%s() Invalid packet address!! 0x%04x\n",
-				__func__, priv->next_pk_ptr);
-		/* packet address corrupted: reset RX logic */
-		mutex_lock(&priv->lock);
-		nolock_reg_bfclr(priv, ECON1, ECON1_RXEN);
-		nolock_reg_bfset(priv, ECON1, ECON1_RXRST);
-		nolock_reg_bfclr(priv, ECON1, ECON1_RXRST);
-		nolock_rxfifo_init(priv, RXSTART_INIT, RXEND_INIT);
-		nolock_reg_bfclr(priv, EIR, EIR_RXERIF);
-		nolock_reg_bfset(priv, ECON1, ECON1_RXEN);
-		mutex_unlock(&priv->lock);
-		ndev->stats.rx_errors++;
-		return;
-	}
-	/* Read next packet pointer and rx status vector */
-	enc28j60_mem_read(priv, priv->next_pk_ptr, sizeof(rsv), rsv);
-
-	next_packet = rsv[1];
-	next_packet <<= 8;
-	next_packet |= rsv[0];
-
-	len = rsv[3];
-	len <<= 8;
-	len |= rsv[2];
-
-	rxstat = rsv[5];
-	rxstat <<= 8;
-	rxstat |= rsv[4];
-
-	if (netif_msg_rx_status(priv))
-		enc28j60_dump_rsv(priv, __func__, next_packet, len, rxstat);
-
-	if (!RSV_GETBIT(rxstat, RSV_RXOK) || len > MAX_FRAMELEN) {
-		if (netif_msg_rx_err(priv))
-			dev_err(&ndev->dev, "Rx Error (%04x)\n", rxstat);
-		ndev->stats.rx_errors++;
-		if (RSV_GETBIT(rxstat, RSV_CRCERROR))
-			ndev->stats.rx_crc_errors++;
-		if (RSV_GETBIT(rxstat, RSV_LENCHECKERR))
-			ndev->stats.rx_frame_errors++;
-		if (len > MAX_FRAMELEN)
-			ndev->stats.rx_over_errors++;
-	} else {
-		skb = dev_alloc_skb(len + NET_IP_ALIGN);
-		if (!skb) {
-			if (netif_msg_rx_err(priv))
-				dev_err(&ndev->dev,
-					"out of memory for Rx'd frame\n");
-			ndev->stats.rx_dropped++;
-		} else {
-			skb->dev = ndev;
-			skb_reserve(skb, NET_IP_ALIGN);
-			/* copy the packet from the receive buffer */
-			enc28j60_mem_read(priv,
-				rx_packet_start(priv->next_pk_ptr),
-				len, skb_put(skb, len));
-			if (netif_msg_pktdata(priv))
-				dump_packet(__func__, skb->len, skb->data);
-			skb->protocol = eth_type_trans(skb, ndev);
-			/* update statistics */
-			ndev->stats.rx_packets++;
-			ndev->stats.rx_bytes += len;
-			netif_rx_ni(skb);
-		}
-	}
-	/*
-	 * Move the RX read pointer to the start of the next
-	 * received packet.
-	 * This frees the memory we just read out
-	 */
-	erxrdpt = erxrdpt_workaround(next_packet, RXSTART_INIT, RXEND_INIT);
-	if (netif_msg_hw(priv))
-		printk(KERN_DEBUG DRV_NAME ": %s() ERXRDPT:0x%04x\n",
-			__func__, erxrdpt);
-
-	mutex_lock(&priv->lock);
-	nolock_regw_write(priv, ERXRDPTL, erxrdpt);
-#ifdef CONFIG_ENC28J60_WRITEVERIFY
-	if (netif_msg_drv(priv)) {
-		u16 reg;
-		reg = nolock_regw_read(priv, ERXRDPTL);
-		if (reg != erxrdpt)
-			printk(KERN_DEBUG DRV_NAME ": %s() ERXRDPT verify "
-				"error (0x%04x - 0x%04x)\n", __func__,
-				reg, erxrdpt);
-	}
-#endif
-	priv->next_pk_ptr = next_packet;
-	/* we are done with this packet, decrement the packet counter */
-	nolock_reg_bfset(priv, ECON2, ECON2_PKTDEC);
-	mutex_unlock(&priv->lock);
-}
-
-/*
- * Calculate free space in RxFIFO
- */
-static int enc28j60_get_free_rxfifo(struct enc28j60_net *priv)
-{
-	int epkcnt, erxst, erxnd, erxwr, erxrd;
-	int free_space;
-
-	mutex_lock(&priv->lock);
-	epkcnt = nolock_regb_read(priv, EPKTCNT);
-	if (epkcnt >= 255)
-		free_space = -1;
-	else {
-		erxst = nolock_regw_read(priv, ERXSTL);
-		erxnd = nolock_regw_read(priv, ERXNDL);
-		erxwr = nolock_regw_read(priv, ERXWRPTL);
-		erxrd = nolock_regw_read(priv, ERXRDPTL);
-
-		if (erxwr > erxrd)
-			free_space = (erxnd - erxst) - (erxwr - erxrd);
-		else if (erxwr == erxrd)
-			free_space = (erxnd - erxst);
-		else
-			free_space = erxrd - erxwr - 1;
-	}
-	mutex_unlock(&priv->lock);
-	if (netif_msg_rx_status(priv))
-		printk(KERN_DEBUG DRV_NAME ": %s() free_space = %d\n",
-			__func__, free_space);
-	return free_space;
-}
-
-/*
- * Access the PHY to determine link status
- */
-static void enc28j60_check_link_status(struct net_device *ndev)
-{
-	struct enc28j60_net *priv = netdev_priv(ndev);
-	u16 reg;
-	int duplex;
-
-	reg = enc28j60_phy_read(priv, PHSTAT2);
-	if (netif_msg_hw(priv))
-		printk(KERN_DEBUG DRV_NAME ": %s() PHSTAT1: %04x, "
-			"PHSTAT2: %04x\n", __func__,
-			enc28j60_phy_read(priv, PHSTAT1), reg);
-	duplex = reg & PHSTAT2_DPXSTAT;
-
-	if (reg & PHSTAT2_LSTAT) {
-		netif_carrier_on(ndev);
-		if (netif_msg_ifup(priv))
-			dev_info(&ndev->dev, "link up - %s\n",
-				duplex ? "Full duplex" : "Half duplex");
-	} else {
-		if (netif_msg_ifdown(priv))
-			dev_info(&ndev->dev, "link down\n");
-		netif_carrier_off(ndev);
-	}
-}
-
-static void enc28j60_tx_clear(struct net_device *ndev, bool err)
-{
-	struct enc28j60_net *priv = netdev_priv(ndev);
-
-	if (err)
-		ndev->stats.tx_errors++;
-	else
-		ndev->stats.tx_packets++;
-
-	if (priv->tx_skb) {
-		if (!err)
-			ndev->stats.tx_bytes += priv->tx_skb->len;
-		dev_kfree_skb(priv->tx_skb);
-		priv->tx_skb = NULL;
-	}
-	locked_reg_bfclr(priv, ECON1, ECON1_TXRTS);
-	netif_wake_queue(ndev);
-}
-
-/*
- * RX handler
- * ignore PKTIF because is unreliable! (look at the errata datasheet)
- * check EPKTCNT is the suggested workaround.
- * We don't need to clear interrupt flag, automatically done when
- * enc28j60_hw_rx() decrements the packet counter.
- * Returns how many packet processed.
- */
-static int enc28j60_rx_interrupt(struct net_device *ndev)
-{
-	struct enc28j60_net *priv = netdev_priv(ndev);
-	int pk_counter, ret;
-
-	pk_counter = locked_regb_read(priv, EPKTCNT);
-	if (pk_counter && netif_msg_intr(priv))
-		printk(KERN_DEBUG DRV_NAME ": intRX, pk_cnt: %d\n", pk_counter);
-	if (pk_counter > priv->max_pk_counter) {
-		/* update statistics */
-		priv->max_pk_counter = pk_counter;
-		if (netif_msg_rx_status(priv) && priv->max_pk_counter > 1)
-			printk(KERN_DEBUG DRV_NAME ": RX max_pk_cnt: %d\n",
-				priv->max_pk_counter);
-	}
-	ret = pk_counter;
-	while (pk_counter-- > 0)
-		enc28j60_hw_rx(ndev);
-
-	return ret;
-}
-
-static void enc28j60_irq_work_handler(struct work_struct *work)
-{
-	struct enc28j60_net *priv =
-		container_of(work, struct enc28j60_net, irq_work);
-	struct net_device *ndev = priv->netdev;
-	int intflags, loop;
-
-	if (netif_msg_intr(priv))
-		printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__);
-	/* disable further interrupts */
-	locked_reg_bfclr(priv, EIE, EIE_INTIE);
-
-	do {
-		loop = 0;
-		intflags = locked_regb_read(priv, EIR);
-		/* DMA interrupt handler (not currently used) */
-		if ((intflags & EIR_DMAIF) != 0) {
-			loop++;
-			if (netif_msg_intr(priv))
-				printk(KERN_DEBUG DRV_NAME
-					": intDMA(%d)\n", loop);
-			locked_reg_bfclr(priv, EIR, EIR_DMAIF);
-		}
-		/* LINK changed handler */
-		if ((intflags & EIR_LINKIF) != 0) {
-			loop++;
-			if (netif_msg_intr(priv))
-				printk(KERN_DEBUG DRV_NAME
-					": intLINK(%d)\n", loop);
-			enc28j60_check_link_status(ndev);
-			/* read PHIR to clear the flag */
-			enc28j60_phy_read(priv, PHIR);
-		}
-		/* TX complete handler */
-		if ((intflags & EIR_TXIF) != 0) {
-			bool err = false;
-			loop++;
-			if (netif_msg_intr(priv))
-				printk(KERN_DEBUG DRV_NAME
-					": intTX(%d)\n", loop);
-			priv->tx_retry_count = 0;
-			if (locked_regb_read(priv, ESTAT) & ESTAT_TXABRT) {
-				if (netif_msg_tx_err(priv))
-					dev_err(&ndev->dev,
-						"Tx Error (aborted)\n");
-				err = true;
-			}
-			if (netif_msg_tx_done(priv)) {
-				u8 tsv[TSV_SIZE];
-				enc28j60_read_tsv(priv, tsv);
-				enc28j60_dump_tsv(priv, "Tx Done", tsv);
-			}
-			enc28j60_tx_clear(ndev, err);
-			locked_reg_bfclr(priv, EIR, EIR_TXIF);
-		}
-		/* TX Error handler */
-		if ((intflags & EIR_TXERIF) != 0) {
-			u8 tsv[TSV_SIZE];
-
-			loop++;
-			if (netif_msg_intr(priv))
-				printk(KERN_DEBUG DRV_NAME
-					": intTXErr(%d)\n", loop);
-			locked_reg_bfclr(priv, ECON1, ECON1_TXRTS);
-			enc28j60_read_tsv(priv, tsv);
-			if (netif_msg_tx_err(priv))
-				enc28j60_dump_tsv(priv, "Tx Error", tsv);
-			/* Reset TX logic */
-			mutex_lock(&priv->lock);
-			nolock_reg_bfset(priv, ECON1, ECON1_TXRST);
-			nolock_reg_bfclr(priv, ECON1, ECON1_TXRST);
-			nolock_txfifo_init(priv, TXSTART_INIT, TXEND_INIT);
-			mutex_unlock(&priv->lock);
-			/* Transmit Late collision check for retransmit */
-			if (TSV_GETBIT(tsv, TSV_TXLATECOLLISION)) {
-				if (netif_msg_tx_err(priv))
-					printk(KERN_DEBUG DRV_NAME
-						": LateCollision TXErr (%d)\n",
-						priv->tx_retry_count);
-				if (priv->tx_retry_count++ < MAX_TX_RETRYCOUNT)
-					locked_reg_bfset(priv, ECON1,
-							   ECON1_TXRTS);
-				else
-					enc28j60_tx_clear(ndev, true);
-			} else
-				enc28j60_tx_clear(ndev, true);
-			locked_reg_bfclr(priv, EIR, EIR_TXERIF);
-		}
-		/* RX Error handler */
-		if ((intflags & EIR_RXERIF) != 0) {
-			loop++;
-			if (netif_msg_intr(priv))
-				printk(KERN_DEBUG DRV_NAME
-					": intRXErr(%d)\n", loop);
-			/* Check free FIFO space to flag RX overrun */
-			if (enc28j60_get_free_rxfifo(priv) <= 0) {
-				if (netif_msg_rx_err(priv))
-					printk(KERN_DEBUG DRV_NAME
-						": RX Overrun\n");
-				ndev->stats.rx_dropped++;
-			}
-			locked_reg_bfclr(priv, EIR, EIR_RXERIF);
-		}
-		/* RX handler */
-		if (enc28j60_rx_interrupt(ndev))
-			loop++;
-	} while (loop);
-
-	/* re-enable interrupts */
-	locked_reg_bfset(priv, EIE, EIE_INTIE);
-	if (netif_msg_intr(priv))
-		printk(KERN_DEBUG DRV_NAME ": %s() exit\n", __func__);
-}
-
-/*
- * Hardware transmit function.
- * Fill the buffer memory and send the contents of the transmit buffer
- * onto the network
- */
-static void enc28j60_hw_tx(struct enc28j60_net *priv)
-{
-	if (netif_msg_tx_queued(priv))
-		printk(KERN_DEBUG DRV_NAME
-			": Tx Packet Len:%d\n", priv->tx_skb->len);
-
-	if (netif_msg_pktdata(priv))
-		dump_packet(__func__,
-			    priv->tx_skb->len, priv->tx_skb->data);
-	enc28j60_packet_write(priv, priv->tx_skb->len, priv->tx_skb->data);
-
-#ifdef CONFIG_ENC28J60_WRITEVERIFY
-	/* readback and verify written data */
-	if (netif_msg_drv(priv)) {
-		int test_len, k;
-		u8 test_buf[64]; /* limit the test to the first 64 bytes */
-		int okflag;
-
-		test_len = priv->tx_skb->len;
-		if (test_len > sizeof(test_buf))
-			test_len = sizeof(test_buf);
-
-		/* + 1 to skip control byte */
-		enc28j60_mem_read(priv, TXSTART_INIT + 1, test_len, test_buf);
-		okflag = 1;
-		for (k = 0; k < test_len; k++) {
-			if (priv->tx_skb->data[k] != test_buf[k]) {
-				printk(KERN_DEBUG DRV_NAME
-					 ": Error, %d location differ: "
-					 "0x%02x-0x%02x\n", k,
-					 priv->tx_skb->data[k], test_buf[k]);
-				okflag = 0;
-			}
-		}
-		if (!okflag)
-			printk(KERN_DEBUG DRV_NAME ": Tx write buffer, "
-				"verify ERROR!\n");
-	}
-#endif
-	/* set TX request flag */
-	locked_reg_bfset(priv, ECON1, ECON1_TXRTS);
-}
-
-static netdev_tx_t enc28j60_send_packet(struct sk_buff *skb,
-					struct net_device *dev)
-{
-	struct enc28j60_net *priv = netdev_priv(dev);
-
-	if (netif_msg_tx_queued(priv))
-		printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__);
-
-	/* If some error occurs while trying to transmit this
-	 * packet, you should return '1' from this function.
-	 * In such a case you _may not_ do anything to the
-	 * SKB, it is still owned by the network queueing
-	 * layer when an error is returned.  This means you
-	 * may not modify any SKB fields, you may not free
-	 * the SKB, etc.
-	 */
-	netif_stop_queue(dev);
-
-	/* Remember the skb for deferred processing */
-	priv->tx_skb = skb;
-	schedule_work(&priv->tx_work);
-
-	return NETDEV_TX_OK;
-}
-
-static void enc28j60_tx_work_handler(struct work_struct *work)
-{
-	struct enc28j60_net *priv =
-		container_of(work, struct enc28j60_net, tx_work);
-
-	/* actual delivery of data */
-	enc28j60_hw_tx(priv);
-}
-
-static irqreturn_t enc28j60_irq(int irq, void *dev_id)
-{
-	struct enc28j60_net *priv = dev_id;
-
-	/*
-	 * Can't do anything in interrupt context because we need to
-	 * block (spi_sync() is blocking) so fire of the interrupt
-	 * handling workqueue.
-	 * Remember that we access enc28j60 registers through SPI bus
-	 * via spi_sync() call.
-	 */
-	schedule_work(&priv->irq_work);
-
-	return IRQ_HANDLED;
-}
-
-static void enc28j60_tx_timeout(struct net_device *ndev)
-{
-	struct enc28j60_net *priv = netdev_priv(ndev);
-
-	if (netif_msg_timer(priv))
-		dev_err(&ndev->dev, DRV_NAME " tx timeout\n");
-
-	ndev->stats.tx_errors++;
-	/* can't restart safely under softirq */
-	schedule_work(&priv->restart_work);
-}
-
-/*
- * Open/initialize the board. This is called (in the current kernel)
- * sometime after booting when the 'ifconfig' program is run.
- *
- * This routine should set everything up anew at each open, even
- * registers that "should" only need to be set once at boot, so that
- * there is non-reboot way to recover if something goes wrong.
- */
-static int enc28j60_net_open(struct net_device *dev)
-{
-	struct enc28j60_net *priv = netdev_priv(dev);
-
-	if (netif_msg_drv(priv))
-		printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__);
-
-	if (!is_valid_ether_addr(dev->dev_addr)) {
-		if (netif_msg_ifup(priv))
-			dev_err(&dev->dev, "invalid MAC address %pM\n",
-				dev->dev_addr);
-		return -EADDRNOTAVAIL;
-	}
-	/* Reset the hardware here (and take it out of low power mode) */
-	enc28j60_lowpower(priv, false);
-	enc28j60_hw_disable(priv);
-	if (!enc28j60_hw_init(priv)) {
-		if (netif_msg_ifup(priv))
-			dev_err(&dev->dev, "hw_reset() failed\n");
-		return -EINVAL;
-	}
-	/* Update the MAC address (in case user has changed it) */
-	enc28j60_set_hw_macaddr(dev);
-	/* Enable interrupts */
-	enc28j60_hw_enable(priv);
-	/* check link status */
-	enc28j60_check_link_status(dev);
-	/* We are now ready to accept transmit requests from
-	 * the queueing layer of the networking.
-	 */
-	netif_start_queue(dev);
-
-	return 0;
-}
-
-/* The inverse routine to net_open(). */
-static int enc28j60_net_close(struct net_device *dev)
-{
-	struct enc28j60_net *priv = netdev_priv(dev);
-
-	if (netif_msg_drv(priv))
-		printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__);
-
-	enc28j60_hw_disable(priv);
-	enc28j60_lowpower(priv, true);
-	netif_stop_queue(dev);
-
-	return 0;
-}
-
-/*
- * Set or clear the multicast filter for this adapter
- * num_addrs == -1	Promiscuous mode, receive all packets
- * num_addrs == 0	Normal mode, filter out multicast packets
- * num_addrs > 0	Multicast mode, receive normal and MC packets
- */
-static void enc28j60_set_multicast_list(struct net_device *dev)
-{
-	struct enc28j60_net *priv = netdev_priv(dev);
-	int oldfilter = priv->rxfilter;
-
-	if (dev->flags & IFF_PROMISC) {
-		if (netif_msg_link(priv))
-			dev_info(&dev->dev, "promiscuous mode\n");
-		priv->rxfilter = RXFILTER_PROMISC;
-	} else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) {
-		if (netif_msg_link(priv))
-			dev_info(&dev->dev, "%smulticast mode\n",
-				(dev->flags & IFF_ALLMULTI) ? "all-" : "");
-		priv->rxfilter = RXFILTER_MULTI;
-	} else {
-		if (netif_msg_link(priv))
-			dev_info(&dev->dev, "normal mode\n");
-		priv->rxfilter = RXFILTER_NORMAL;
-	}
-
-	if (oldfilter != priv->rxfilter)
-		schedule_work(&priv->setrx_work);
-}
-
-static void enc28j60_setrx_work_handler(struct work_struct *work)
-{
-	struct enc28j60_net *priv =
-		container_of(work, struct enc28j60_net, setrx_work);
-
-	if (priv->rxfilter == RXFILTER_PROMISC) {
-		if (netif_msg_drv(priv))
-			printk(KERN_DEBUG DRV_NAME ": promiscuous mode\n");
-		locked_regb_write(priv, ERXFCON, 0x00);
-	} else if (priv->rxfilter == RXFILTER_MULTI) {
-		if (netif_msg_drv(priv))
-			printk(KERN_DEBUG DRV_NAME ": multicast mode\n");
-		locked_regb_write(priv, ERXFCON,
-					ERXFCON_UCEN | ERXFCON_CRCEN |
-					ERXFCON_BCEN | ERXFCON_MCEN);
-	} else {
-		if (netif_msg_drv(priv))
-			printk(KERN_DEBUG DRV_NAME ": normal mode\n");
-		locked_regb_write(priv, ERXFCON,
-					ERXFCON_UCEN | ERXFCON_CRCEN |
-					ERXFCON_BCEN);
-	}
-}
-
-static void enc28j60_restart_work_handler(struct work_struct *work)
-{
-	struct enc28j60_net *priv =
-			container_of(work, struct enc28j60_net, restart_work);
-	struct net_device *ndev = priv->netdev;
-	int ret;
-
-	rtnl_lock();
-	if (netif_running(ndev)) {
-		enc28j60_net_close(ndev);
-		ret = enc28j60_net_open(ndev);
-		if (unlikely(ret)) {
-			dev_info(&ndev->dev, " could not restart %d\n", ret);
-			dev_close(ndev);
-		}
-	}
-	rtnl_unlock();
-}
-
-/* ......................... ETHTOOL SUPPORT ........................... */
-
-static void
-enc28j60_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-	strlcpy(info->bus_info,
-		dev_name(dev->dev.parent), sizeof(info->bus_info));
-}
-
-static int
-enc28j60_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct enc28j60_net *priv = netdev_priv(dev);
-
-	cmd->transceiver = XCVR_INTERNAL;
-	cmd->supported	= SUPPORTED_10baseT_Half
-			| SUPPORTED_10baseT_Full
-			| SUPPORTED_TP;
-	ethtool_cmd_speed_set(cmd,  SPEED_10);
-	cmd->duplex	= priv->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
-	cmd->port	= PORT_TP;
-	cmd->autoneg	= AUTONEG_DISABLE;
-
-	return 0;
-}
-
-static int
-enc28j60_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	return enc28j60_setlink(dev, cmd->autoneg,
-				ethtool_cmd_speed(cmd), cmd->duplex);
-}
-
-static u32 enc28j60_get_msglevel(struct net_device *dev)
-{
-	struct enc28j60_net *priv = netdev_priv(dev);
-	return priv->msg_enable;
-}
-
-static void enc28j60_set_msglevel(struct net_device *dev, u32 val)
-{
-	struct enc28j60_net *priv = netdev_priv(dev);
-	priv->msg_enable = val;
-}
-
-static const struct ethtool_ops enc28j60_ethtool_ops = {
-	.get_settings	= enc28j60_get_settings,
-	.set_settings	= enc28j60_set_settings,
-	.get_drvinfo	= enc28j60_get_drvinfo,
-	.get_msglevel	= enc28j60_get_msglevel,
-	.set_msglevel	= enc28j60_set_msglevel,
-};
-
-static int enc28j60_chipset_init(struct net_device *dev)
-{
-	struct enc28j60_net *priv = netdev_priv(dev);
-
-	return enc28j60_hw_init(priv);
-}
-
-static const struct net_device_ops enc28j60_netdev_ops = {
-	.ndo_open		= enc28j60_net_open,
-	.ndo_stop		= enc28j60_net_close,
-	.ndo_start_xmit		= enc28j60_send_packet,
-	.ndo_set_multicast_list = enc28j60_set_multicast_list,
-	.ndo_set_mac_address	= enc28j60_set_mac_address,
-	.ndo_tx_timeout		= enc28j60_tx_timeout,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-static int __devinit enc28j60_probe(struct spi_device *spi)
-{
-	struct net_device *dev;
-	struct enc28j60_net *priv;
-	int ret = 0;
-
-	if (netif_msg_drv(&debug))
-		dev_info(&spi->dev, DRV_NAME " Ethernet driver %s loaded\n",
-			DRV_VERSION);
-
-	dev = alloc_etherdev(sizeof(struct enc28j60_net));
-	if (!dev) {
-		if (netif_msg_drv(&debug))
-			dev_err(&spi->dev, DRV_NAME
-				": unable to alloc new ethernet\n");
-		ret = -ENOMEM;
-		goto error_alloc;
-	}
-	priv = netdev_priv(dev);
-
-	priv->netdev = dev;	/* priv to netdev reference */
-	priv->spi = spi;	/* priv to spi reference */
-	priv->msg_enable = netif_msg_init(debug.msg_enable,
-						ENC28J60_MSG_DEFAULT);
-	mutex_init(&priv->lock);
-	INIT_WORK(&priv->tx_work, enc28j60_tx_work_handler);
-	INIT_WORK(&priv->setrx_work, enc28j60_setrx_work_handler);
-	INIT_WORK(&priv->irq_work, enc28j60_irq_work_handler);
-	INIT_WORK(&priv->restart_work, enc28j60_restart_work_handler);
-	dev_set_drvdata(&spi->dev, priv);	/* spi to priv reference */
-	SET_NETDEV_DEV(dev, &spi->dev);
-
-	if (!enc28j60_chipset_init(dev)) {
-		if (netif_msg_probe(priv))
-			dev_info(&spi->dev, DRV_NAME " chip not found\n");
-		ret = -EIO;
-		goto error_irq;
-	}
-	random_ether_addr(dev->dev_addr);
-	enc28j60_set_hw_macaddr(dev);
-
-	/* Board setup must set the relevant edge trigger type;
-	 * level triggers won't currently work.
-	 */
-	ret = request_irq(spi->irq, enc28j60_irq, 0, DRV_NAME, priv);
-	if (ret < 0) {
-		if (netif_msg_probe(priv))
-			dev_err(&spi->dev, DRV_NAME ": request irq %d failed "
-				"(ret = %d)\n", spi->irq, ret);
-		goto error_irq;
-	}
-
-	dev->if_port = IF_PORT_10BASET;
-	dev->irq = spi->irq;
-	dev->netdev_ops = &enc28j60_netdev_ops;
-	dev->watchdog_timeo = TX_TIMEOUT;
-	SET_ETHTOOL_OPS(dev, &enc28j60_ethtool_ops);
-
-	enc28j60_lowpower(priv, true);
-
-	ret = register_netdev(dev);
-	if (ret) {
-		if (netif_msg_probe(priv))
-			dev_err(&spi->dev, "register netdev " DRV_NAME
-				" failed (ret = %d)\n", ret);
-		goto error_register;
-	}
-	dev_info(&dev->dev, DRV_NAME " driver registered\n");
-
-	return 0;
-
-error_register:
-	free_irq(spi->irq, priv);
-error_irq:
-	free_netdev(dev);
-error_alloc:
-	return ret;
-}
-
-static int __devexit enc28j60_remove(struct spi_device *spi)
-{
-	struct enc28j60_net *priv = dev_get_drvdata(&spi->dev);
-
-	if (netif_msg_drv(priv))
-		printk(KERN_DEBUG DRV_NAME ": remove\n");
-
-	unregister_netdev(priv->netdev);
-	free_irq(spi->irq, priv);
-	free_netdev(priv->netdev);
-
-	return 0;
-}
-
-static struct spi_driver enc28j60_driver = {
-	.driver = {
-		   .name = DRV_NAME,
-		   .owner = THIS_MODULE,
-	 },
-	.probe = enc28j60_probe,
-	.remove = __devexit_p(enc28j60_remove),
-};
-
-static int __init enc28j60_init(void)
-{
-	msec20_to_jiffies = msecs_to_jiffies(20);
-
-	return spi_register_driver(&enc28j60_driver);
-}
-
-module_init(enc28j60_init);
-
-static void __exit enc28j60_exit(void)
-{
-	spi_unregister_driver(&enc28j60_driver);
-}
-
-module_exit(enc28j60_exit);
-
-MODULE_DESCRIPTION(DRV_NAME " ethernet driver");
-MODULE_AUTHOR("Claudio Lanconelli <lanconelli.claudio@eptar.com>");
-MODULE_LICENSE("GPL");
-module_param_named(debug, debug.msg_enable, int, 0);
-MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., ffff=all)");
-MODULE_ALIAS("spi:" DRV_NAME);
diff -druN linux-libre-3.1-gnu/drivers/net/enc28j60_hw.h linux-libre-3.2-gnu/drivers/net/enc28j60_hw.h
--- linux-libre-3.1-gnu/drivers/net/enc28j60_hw.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enc28j60_hw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,309 +0,0 @@
-/*
- * enc28j60_hw.h: EDTP FrameThrower style enc28j60 registers
- *
- * $Id: enc28j60_hw.h,v 1.9 2007/12/14 11:59:16 claudio Exp $
- */
-
-#ifndef _ENC28J60_HW_H
-#define _ENC28J60_HW_H
-
-/*
- * ENC28J60 Control Registers
- * Control register definitions are a combination of address,
- * bank number, and Ethernet/MAC/PHY indicator bits.
- * - Register address	(bits 0-4)
- * - Bank number	(bits 5-6)
- * - MAC/MII indicator	(bit 7)
- */
-#define ADDR_MASK	0x1F
-#define BANK_MASK	0x60
-#define SPRD_MASK	0x80
-/* All-bank registers */
-#define EIE		0x1B
-#define EIR		0x1C
-#define ESTAT		0x1D
-#define ECON2		0x1E
-#define ECON1		0x1F
-/* Bank 0 registers */
-#define ERDPTL		(0x00|0x00)
-#define ERDPTH		(0x01|0x00)
-#define EWRPTL		(0x02|0x00)
-#define EWRPTH		(0x03|0x00)
-#define ETXSTL		(0x04|0x00)
-#define ETXSTH		(0x05|0x00)
-#define ETXNDL		(0x06|0x00)
-#define ETXNDH		(0x07|0x00)
-#define ERXSTL		(0x08|0x00)
-#define ERXSTH		(0x09|0x00)
-#define ERXNDL		(0x0A|0x00)
-#define ERXNDH		(0x0B|0x00)
-#define ERXRDPTL	(0x0C|0x00)
-#define ERXRDPTH	(0x0D|0x00)
-#define ERXWRPTL	(0x0E|0x00)
-#define ERXWRPTH	(0x0F|0x00)
-#define EDMASTL		(0x10|0x00)
-#define EDMASTH		(0x11|0x00)
-#define EDMANDL		(0x12|0x00)
-#define EDMANDH		(0x13|0x00)
-#define EDMADSTL	(0x14|0x00)
-#define EDMADSTH	(0x15|0x00)
-#define EDMACSL		(0x16|0x00)
-#define EDMACSH		(0x17|0x00)
-/* Bank 1 registers */
-#define EHT0		(0x00|0x20)
-#define EHT1		(0x01|0x20)
-#define EHT2		(0x02|0x20)
-#define EHT3		(0x03|0x20)
-#define EHT4		(0x04|0x20)
-#define EHT5		(0x05|0x20)
-#define EHT6		(0x06|0x20)
-#define EHT7		(0x07|0x20)
-#define EPMM0		(0x08|0x20)
-#define EPMM1		(0x09|0x20)
-#define EPMM2		(0x0A|0x20)
-#define EPMM3		(0x0B|0x20)
-#define EPMM4		(0x0C|0x20)
-#define EPMM5		(0x0D|0x20)
-#define EPMM6		(0x0E|0x20)
-#define EPMM7		(0x0F|0x20)
-#define EPMCSL		(0x10|0x20)
-#define EPMCSH		(0x11|0x20)
-#define EPMOL		(0x14|0x20)
-#define EPMOH		(0x15|0x20)
-#define EWOLIE		(0x16|0x20)
-#define EWOLIR		(0x17|0x20)
-#define ERXFCON		(0x18|0x20)
-#define EPKTCNT		(0x19|0x20)
-/* Bank 2 registers */
-#define MACON1		(0x00|0x40|SPRD_MASK)
-/* #define MACON2	(0x01|0x40|SPRD_MASK) */
-#define MACON3		(0x02|0x40|SPRD_MASK)
-#define MACON4		(0x03|0x40|SPRD_MASK)
-#define MABBIPG		(0x04|0x40|SPRD_MASK)
-#define MAIPGL		(0x06|0x40|SPRD_MASK)
-#define MAIPGH		(0x07|0x40|SPRD_MASK)
-#define MACLCON1	(0x08|0x40|SPRD_MASK)
-#define MACLCON2	(0x09|0x40|SPRD_MASK)
-#define MAMXFLL		(0x0A|0x40|SPRD_MASK)
-#define MAMXFLH		(0x0B|0x40|SPRD_MASK)
-#define MAPHSUP		(0x0D|0x40|SPRD_MASK)
-#define MICON		(0x11|0x40|SPRD_MASK)
-#define MICMD		(0x12|0x40|SPRD_MASK)
-#define MIREGADR	(0x14|0x40|SPRD_MASK)
-#define MIWRL		(0x16|0x40|SPRD_MASK)
-#define MIWRH		(0x17|0x40|SPRD_MASK)
-#define MIRDL		(0x18|0x40|SPRD_MASK)
-#define MIRDH		(0x19|0x40|SPRD_MASK)
-/* Bank 3 registers */
-#define MAADR1		(0x00|0x60|SPRD_MASK)
-#define MAADR0		(0x01|0x60|SPRD_MASK)
-#define MAADR3		(0x02|0x60|SPRD_MASK)
-#define MAADR2		(0x03|0x60|SPRD_MASK)
-#define MAADR5		(0x04|0x60|SPRD_MASK)
-#define MAADR4		(0x05|0x60|SPRD_MASK)
-#define EBSTSD		(0x06|0x60)
-#define EBSTCON		(0x07|0x60)
-#define EBSTCSL		(0x08|0x60)
-#define EBSTCSH		(0x09|0x60)
-#define MISTAT		(0x0A|0x60|SPRD_MASK)
-#define EREVID		(0x12|0x60)
-#define ECOCON		(0x15|0x60)
-#define EFLOCON		(0x17|0x60)
-#define EPAUSL		(0x18|0x60)
-#define EPAUSH		(0x19|0x60)
-/* PHY registers */
-#define PHCON1		0x00
-#define PHSTAT1		0x01
-#define PHHID1		0x02
-#define PHHID2		0x03
-#define PHCON2		0x10
-#define PHSTAT2		0x11
-#define PHIE		0x12
-#define PHIR		0x13
-#define PHLCON		0x14
-
-/* ENC28J60 EIE Register Bit Definitions */
-#define EIE_INTIE	0x80
-#define EIE_PKTIE	0x40
-#define EIE_DMAIE	0x20
-#define EIE_LINKIE	0x10
-#define EIE_TXIE	0x08
-/* #define EIE_WOLIE	0x04 (reserved) */
-#define EIE_TXERIE	0x02
-#define EIE_RXERIE	0x01
-/* ENC28J60 EIR Register Bit Definitions */
-#define EIR_PKTIF	0x40
-#define EIR_DMAIF	0x20
-#define EIR_LINKIF	0x10
-#define EIR_TXIF	0x08
-/* #define EIR_WOLIF	0x04 (reserved) */
-#define EIR_TXERIF	0x02
-#define EIR_RXERIF	0x01
-/* ENC28J60 ESTAT Register Bit Definitions */
-#define ESTAT_INT	0x80
-#define ESTAT_LATECOL	0x10
-#define ESTAT_RXBUSY	0x04
-#define ESTAT_TXABRT	0x02
-#define ESTAT_CLKRDY	0x01
-/* ENC28J60 ECON2 Register Bit Definitions */
-#define ECON2_AUTOINC	0x80
-#define ECON2_PKTDEC	0x40
-#define ECON2_PWRSV	0x20
-#define ECON2_VRPS	0x08
-/* ENC28J60 ECON1 Register Bit Definitions */
-#define ECON1_TXRST	0x80
-#define ECON1_RXRST	0x40
-#define ECON1_DMAST	0x20
-#define ECON1_CSUMEN	0x10
-#define ECON1_TXRTS	0x08
-#define ECON1_RXEN	0x04
-#define ECON1_BSEL1	0x02
-#define ECON1_BSEL0	0x01
-/* ENC28J60 MACON1 Register Bit Definitions */
-#define MACON1_LOOPBK	0x10
-#define MACON1_TXPAUS	0x08
-#define MACON1_RXPAUS	0x04
-#define MACON1_PASSALL	0x02
-#define MACON1_MARXEN	0x01
-/* ENC28J60 MACON2 Register Bit Definitions */
-#define MACON2_MARST	0x80
-#define MACON2_RNDRST	0x40
-#define MACON2_MARXRST	0x08
-#define MACON2_RFUNRST	0x04
-#define MACON2_MATXRST	0x02
-#define MACON2_TFUNRST	0x01
-/* ENC28J60 MACON3 Register Bit Definitions */
-#define MACON3_PADCFG2	0x80
-#define MACON3_PADCFG1	0x40
-#define MACON3_PADCFG0	0x20
-#define MACON3_TXCRCEN	0x10
-#define MACON3_PHDRLEN	0x08
-#define MACON3_HFRMLEN	0x04
-#define MACON3_FRMLNEN	0x02
-#define MACON3_FULDPX	0x01
-/* ENC28J60 MICMD Register Bit Definitions */
-#define MICMD_MIISCAN	0x02
-#define MICMD_MIIRD	0x01
-/* ENC28J60 MISTAT Register Bit Definitions */
-#define MISTAT_NVALID	0x04
-#define MISTAT_SCAN	0x02
-#define MISTAT_BUSY	0x01
-/* ENC28J60 ERXFCON Register Bit Definitions */
-#define ERXFCON_UCEN	0x80
-#define ERXFCON_ANDOR	0x40
-#define ERXFCON_CRCEN	0x20
-#define ERXFCON_PMEN	0x10
-#define ERXFCON_MPEN	0x08
-#define ERXFCON_HTEN	0x04
-#define ERXFCON_MCEN	0x02
-#define ERXFCON_BCEN	0x01
-
-/* ENC28J60 PHY PHCON1 Register Bit Definitions */
-#define PHCON1_PRST	0x8000
-#define PHCON1_PLOOPBK	0x4000
-#define PHCON1_PPWRSV	0x0800
-#define PHCON1_PDPXMD	0x0100
-/* ENC28J60 PHY PHSTAT1 Register Bit Definitions */
-#define PHSTAT1_PFDPX	0x1000
-#define PHSTAT1_PHDPX	0x0800
-#define PHSTAT1_LLSTAT	0x0004
-#define PHSTAT1_JBSTAT	0x0002
-/* ENC28J60 PHY PHSTAT2 Register Bit Definitions */
-#define PHSTAT2_TXSTAT	(1 << 13)
-#define PHSTAT2_RXSTAT	(1 << 12)
-#define PHSTAT2_COLSTAT	(1 << 11)
-#define PHSTAT2_LSTAT	(1 << 10)
-#define PHSTAT2_DPXSTAT	(1 << 9)
-#define PHSTAT2_PLRITY	(1 << 5)
-/* ENC28J60 PHY PHCON2 Register Bit Definitions */
-#define PHCON2_FRCLINK	0x4000
-#define PHCON2_TXDIS	0x2000
-#define PHCON2_JABBER	0x0400
-#define PHCON2_HDLDIS	0x0100
-/* ENC28J60 PHY PHIE Register Bit Definitions */
-#define PHIE_PLNKIE	(1 << 4)
-#define PHIE_PGEIE	(1 << 1)
-/* ENC28J60 PHY PHIR Register Bit Definitions */
-#define PHIR_PLNKIF	(1 << 4)
-#define PHIR_PGEIF	(1 << 1)
-
-/* ENC28J60 Packet Control Byte Bit Definitions */
-#define PKTCTRL_PHUGEEN		0x08
-#define PKTCTRL_PPADEN		0x04
-#define PKTCTRL_PCRCEN		0x02
-#define PKTCTRL_POVERRIDE	0x01
-
-/* ENC28J60 Transmit Status Vector */
-#define TSV_TXBYTECNT		0
-#define TSV_TXCOLLISIONCNT	16
-#define TSV_TXCRCERROR		20
-#define TSV_TXLENCHKERROR	21
-#define TSV_TXLENOUTOFRANGE	22
-#define TSV_TXDONE		23
-#define TSV_TXMULTICAST		24
-#define TSV_TXBROADCAST		25
-#define TSV_TXPACKETDEFER	26
-#define TSV_TXEXDEFER		27
-#define TSV_TXEXCOLLISION	28
-#define TSV_TXLATECOLLISION	29
-#define TSV_TXGIANT		30
-#define TSV_TXUNDERRUN		31
-#define TSV_TOTBYTETXONWIRE	32
-#define TSV_TXCONTROLFRAME	48
-#define TSV_TXPAUSEFRAME	49
-#define TSV_BACKPRESSUREAPP	50
-#define TSV_TXVLANTAGFRAME	51
-
-#define TSV_SIZE		7
-#define TSV_BYTEOF(x)		((x) / 8)
-#define TSV_BITMASK(x)		(1 << ((x) % 8))
-#define TSV_GETBIT(x, y)	(((x)[TSV_BYTEOF(y)] & TSV_BITMASK(y)) ? 1 : 0)
-
-/* ENC28J60 Receive Status Vector */
-#define RSV_RXLONGEVDROPEV	16
-#define RSV_CARRIEREV		18
-#define RSV_CRCERROR		20
-#define RSV_LENCHECKERR		21
-#define RSV_LENOUTOFRANGE	22
-#define RSV_RXOK		23
-#define RSV_RXMULTICAST		24
-#define RSV_RXBROADCAST		25
-#define RSV_DRIBBLENIBBLE	26
-#define RSV_RXCONTROLFRAME	27
-#define RSV_RXPAUSEFRAME	28
-#define RSV_RXUNKNOWNOPCODE	29
-#define RSV_RXTYPEVLAN		30
-
-#define RSV_SIZE		6
-#define RSV_BITMASK(x)		(1 << ((x) - 16))
-#define RSV_GETBIT(x, y)	(((x) & RSV_BITMASK(y)) ? 1 : 0)
-
-
-/* SPI operation codes */
-#define ENC28J60_READ_CTRL_REG	0x00
-#define ENC28J60_READ_BUF_MEM	0x3A
-#define ENC28J60_WRITE_CTRL_REG 0x40
-#define ENC28J60_WRITE_BUF_MEM	0x7A
-#define ENC28J60_BIT_FIELD_SET	0x80
-#define ENC28J60_BIT_FIELD_CLR	0xA0
-#define ENC28J60_SOFT_RESET	0xFF
-
-
-/* buffer boundaries applied to internal 8K ram
- * entire available packet buffer space is allocated.
- * Give TX buffer space for one full ethernet frame (~1500 bytes)
- * receive buffer gets the rest */
-#define TXSTART_INIT		0x1A00
-#define TXEND_INIT		0x1FFF
-
-/* Put RX buffer at 0 as suggested by the Errata datasheet */
-#define RXSTART_INIT		0x0000
-#define RXEND_INIT		0x19FF
-
-/* maximum ethernet frame length */
-#define MAX_FRAMELEN		1518
-
-/* Preferred half duplex: LEDA: Link status LEDB: Rx/Tx activity */
-#define ENC28J60_LAMPS_MODE	0x3476
-
-#endif
diff -druN linux-libre-3.1-gnu/drivers/net/enic/cq_desc.h linux-libre-3.2-gnu/drivers/net/enic/cq_desc.h
--- linux-libre-3.1-gnu/drivers/net/enic/cq_desc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/cq_desc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,80 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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 _CQ_DESC_H_
-#define _CQ_DESC_H_
-
-/*
- * Completion queue descriptor types
- */
-enum cq_desc_types {
-	CQ_DESC_TYPE_WQ_ENET = 0,
-	CQ_DESC_TYPE_DESC_COPY = 1,
-	CQ_DESC_TYPE_WQ_EXCH = 2,
-	CQ_DESC_TYPE_RQ_ENET = 3,
-	CQ_DESC_TYPE_RQ_FCP = 4,
-};
-
-/* Completion queue descriptor: 16B
- *
- * All completion queues have this basic layout.  The
- * type_specfic area is unique for each completion
- * queue type.
- */
-struct cq_desc {
-	__le16 completed_index;
-	__le16 q_number;
-	u8 type_specfic[11];
-	u8 type_color;
-};
-
-#define CQ_DESC_TYPE_BITS        4
-#define CQ_DESC_TYPE_MASK        ((1 << CQ_DESC_TYPE_BITS) - 1)
-#define CQ_DESC_COLOR_MASK       1
-#define CQ_DESC_COLOR_SHIFT      7
-#define CQ_DESC_Q_NUM_BITS       10
-#define CQ_DESC_Q_NUM_MASK       ((1 << CQ_DESC_Q_NUM_BITS) - 1)
-#define CQ_DESC_COMP_NDX_BITS    12
-#define CQ_DESC_COMP_NDX_MASK    ((1 << CQ_DESC_COMP_NDX_BITS) - 1)
-
-static inline void cq_desc_dec(const struct cq_desc *desc_arg,
-	u8 *type, u8 *color, u16 *q_number, u16 *completed_index)
-{
-	const struct cq_desc *desc = desc_arg;
-	const u8 type_color = desc->type_color;
-
-	*color = (type_color >> CQ_DESC_COLOR_SHIFT) & CQ_DESC_COLOR_MASK;
-
-	/*
-	 * Make sure color bit is read from desc *before* other fields
-	 * are read from desc.  Hardware guarantees color bit is last
-	 * bit (byte) written.  Adding the rmb() prevents the compiler
-	 * and/or CPU from reordering the reads which would potentially
-	 * result in reading stale values.
-	 */
-
-	rmb();
-
-	*type = type_color & CQ_DESC_TYPE_MASK;
-	*q_number = le16_to_cpu(desc->q_number) & CQ_DESC_Q_NUM_MASK;
-	*completed_index = le16_to_cpu(desc->completed_index) &
-		CQ_DESC_COMP_NDX_MASK;
-}
-
-#endif /* _CQ_DESC_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/cq_enet_desc.h linux-libre-3.2-gnu/drivers/net/enic/cq_enet_desc.h
--- linux-libre-3.1-gnu/drivers/net/enic/cq_enet_desc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/cq_enet_desc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,185 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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 _CQ_ENET_DESC_H_
-#define _CQ_ENET_DESC_H_
-
-#include "cq_desc.h"
-
-/* Ethernet completion queue descriptor: 16B */
-struct cq_enet_wq_desc {
-	__le16 completed_index;
-	__le16 q_number;
-	u8 reserved[11];
-	u8 type_color;
-};
-
-static inline void cq_enet_wq_desc_dec(struct cq_enet_wq_desc *desc,
-	u8 *type, u8 *color, u16 *q_number, u16 *completed_index)
-{
-	cq_desc_dec((struct cq_desc *)desc, type,
-		color, q_number, completed_index);
-}
-
-/* Completion queue descriptor: Ethernet receive queue, 16B */
-struct cq_enet_rq_desc {
-	__le16 completed_index_flags;
-	__le16 q_number_rss_type_flags;
-	__le32 rss_hash;
-	__le16 bytes_written_flags;
-	__le16 vlan;
-	__le16 checksum_fcoe;
-	u8 flags;
-	u8 type_color;
-};
-
-#define CQ_ENET_RQ_DESC_FLAGS_INGRESS_PORT          (0x1 << 12)
-#define CQ_ENET_RQ_DESC_FLAGS_FCOE                  (0x1 << 13)
-#define CQ_ENET_RQ_DESC_FLAGS_EOP                   (0x1 << 14)
-#define CQ_ENET_RQ_DESC_FLAGS_SOP                   (0x1 << 15)
-
-#define CQ_ENET_RQ_DESC_RSS_TYPE_BITS               4
-#define CQ_ENET_RQ_DESC_RSS_TYPE_MASK \
-	((1 << CQ_ENET_RQ_DESC_RSS_TYPE_BITS) - 1)
-#define CQ_ENET_RQ_DESC_RSS_TYPE_NONE               0
-#define CQ_ENET_RQ_DESC_RSS_TYPE_IPv4               1
-#define CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv4           2
-#define CQ_ENET_RQ_DESC_RSS_TYPE_IPv6               3
-#define CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6           4
-#define CQ_ENET_RQ_DESC_RSS_TYPE_IPv6_EX            5
-#define CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6_EX        6
-
-#define CQ_ENET_RQ_DESC_FLAGS_CSUM_NOT_CALC         (0x1 << 14)
-
-#define CQ_ENET_RQ_DESC_BYTES_WRITTEN_BITS          14
-#define CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK \
-	((1 << CQ_ENET_RQ_DESC_BYTES_WRITTEN_BITS) - 1)
-#define CQ_ENET_RQ_DESC_FLAGS_TRUNCATED             (0x1 << 14)
-#define CQ_ENET_RQ_DESC_FLAGS_VLAN_STRIPPED         (0x1 << 15)
-
-#define CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_BITS          12
-#define CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_MASK \
-	((1 << CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_BITS) - 1)
-#define CQ_ENET_RQ_DESC_VLAN_TCI_CFI_MASK           (0x1 << 12)
-#define CQ_ENET_RQ_DESC_VLAN_TCI_USER_PRIO_BITS     3
-#define CQ_ENET_RQ_DESC_VLAN_TCI_USER_PRIO_MASK \
-	((1 << CQ_ENET_RQ_DESC_VLAN_TCI_USER_PRIO_BITS) - 1)
-#define CQ_ENET_RQ_DESC_VLAN_TCI_USER_PRIO_SHIFT    13
-
-#define CQ_ENET_RQ_DESC_FCOE_SOF_BITS               8
-#define CQ_ENET_RQ_DESC_FCOE_SOF_MASK \
-	((1 << CQ_ENET_RQ_DESC_FCOE_SOF_BITS) - 1)
-#define CQ_ENET_RQ_DESC_FCOE_EOF_BITS               8
-#define CQ_ENET_RQ_DESC_FCOE_EOF_MASK \
-	((1 << CQ_ENET_RQ_DESC_FCOE_EOF_BITS) - 1)
-#define CQ_ENET_RQ_DESC_FCOE_EOF_SHIFT              8
-
-#define CQ_ENET_RQ_DESC_FLAGS_TCP_UDP_CSUM_OK       (0x1 << 0)
-#define CQ_ENET_RQ_DESC_FCOE_FC_CRC_OK              (0x1 << 0)
-#define CQ_ENET_RQ_DESC_FLAGS_UDP                   (0x1 << 1)
-#define CQ_ENET_RQ_DESC_FCOE_ENC_ERROR              (0x1 << 1)
-#define CQ_ENET_RQ_DESC_FLAGS_TCP                   (0x1 << 2)
-#define CQ_ENET_RQ_DESC_FLAGS_IPV4_CSUM_OK          (0x1 << 3)
-#define CQ_ENET_RQ_DESC_FLAGS_IPV6                  (0x1 << 4)
-#define CQ_ENET_RQ_DESC_FLAGS_IPV4                  (0x1 << 5)
-#define CQ_ENET_RQ_DESC_FLAGS_IPV4_FRAGMENT         (0x1 << 6)
-#define CQ_ENET_RQ_DESC_FLAGS_FCS_OK                (0x1 << 7)
-
-static inline void cq_enet_rq_desc_dec(struct cq_enet_rq_desc *desc,
-	u8 *type, u8 *color, u16 *q_number, u16 *completed_index,
-	u8 *ingress_port, u8 *fcoe, u8 *eop, u8 *sop, u8 *rss_type,
-	u8 *csum_not_calc, u32 *rss_hash, u16 *bytes_written, u8 *packet_error,
-	u8 *vlan_stripped, u16 *vlan_tci, u16 *checksum, u8 *fcoe_sof,
-	u8 *fcoe_fc_crc_ok, u8 *fcoe_enc_error, u8 *fcoe_eof,
-	u8 *tcp_udp_csum_ok, u8 *udp, u8 *tcp, u8 *ipv4_csum_ok,
-	u8 *ipv6, u8 *ipv4, u8 *ipv4_fragment, u8 *fcs_ok)
-{
-	u16 completed_index_flags;
-	u16 q_number_rss_type_flags;
-	u16 bytes_written_flags;
-
-	cq_desc_dec((struct cq_desc *)desc, type,
-		color, q_number, completed_index);
-
-	completed_index_flags = le16_to_cpu(desc->completed_index_flags);
-	q_number_rss_type_flags =
-		le16_to_cpu(desc->q_number_rss_type_flags);
-	bytes_written_flags = le16_to_cpu(desc->bytes_written_flags);
-
-	*ingress_port = (completed_index_flags &
-		CQ_ENET_RQ_DESC_FLAGS_INGRESS_PORT) ? 1 : 0;
-	*fcoe = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_FCOE) ?
-		1 : 0;
-	*eop = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_EOP) ?
-		1 : 0;
-	*sop = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_SOP) ?
-		1 : 0;
-
-	*rss_type = (u8)((q_number_rss_type_flags >> CQ_DESC_Q_NUM_BITS) &
-		CQ_ENET_RQ_DESC_RSS_TYPE_MASK);
-	*csum_not_calc = (q_number_rss_type_flags &
-		CQ_ENET_RQ_DESC_FLAGS_CSUM_NOT_CALC) ? 1 : 0;
-
-	*rss_hash = le32_to_cpu(desc->rss_hash);
-
-	*bytes_written = bytes_written_flags &
-		CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK;
-	*packet_error = (bytes_written_flags &
-		CQ_ENET_RQ_DESC_FLAGS_TRUNCATED) ? 1 : 0;
-	*vlan_stripped = (bytes_written_flags &
-		CQ_ENET_RQ_DESC_FLAGS_VLAN_STRIPPED) ? 1 : 0;
-
-	/*
-	 * Tag Control Information(16) = user_priority(3) + cfi(1) + vlan(12)
-	 */
-	*vlan_tci = le16_to_cpu(desc->vlan);
-
-	if (*fcoe) {
-		*fcoe_sof = (u8)(le16_to_cpu(desc->checksum_fcoe) &
-			CQ_ENET_RQ_DESC_FCOE_SOF_MASK);
-		*fcoe_fc_crc_ok = (desc->flags &
-			CQ_ENET_RQ_DESC_FCOE_FC_CRC_OK) ? 1 : 0;
-		*fcoe_enc_error = (desc->flags &
-			CQ_ENET_RQ_DESC_FCOE_ENC_ERROR) ? 1 : 0;
-		*fcoe_eof = (u8)((desc->checksum_fcoe >>
-			CQ_ENET_RQ_DESC_FCOE_EOF_SHIFT) &
-			CQ_ENET_RQ_DESC_FCOE_EOF_MASK);
-		*checksum = 0;
-	} else {
-		*fcoe_sof = 0;
-		*fcoe_fc_crc_ok = 0;
-		*fcoe_enc_error = 0;
-		*fcoe_eof = 0;
-		*checksum = le16_to_cpu(desc->checksum_fcoe);
-	}
-
-	*tcp_udp_csum_ok =
-		(desc->flags & CQ_ENET_RQ_DESC_FLAGS_TCP_UDP_CSUM_OK) ? 1 : 0;
-	*udp = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_UDP) ? 1 : 0;
-	*tcp = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_TCP) ? 1 : 0;
-	*ipv4_csum_ok =
-		(desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4_CSUM_OK) ? 1 : 0;
-	*ipv6 = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV6) ? 1 : 0;
-	*ipv4 = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4) ? 1 : 0;
-	*ipv4_fragment =
-		(desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4_FRAGMENT) ? 1 : 0;
-	*fcs_ok = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_FCS_OK) ? 1 : 0;
-}
-
-#endif /* _CQ_ENET_DESC_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/enic_dev.c linux-libre-3.2-gnu/drivers/net/enic/enic_dev.c
--- linux-libre-3.1-gnu/drivers/net/enic/enic_dev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/enic_dev.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,286 +0,0 @@
-/*
- * 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_dev_intr_coal_timer_info(struct enic *enic)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_intr_coal_timer_info(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_prov2(struct enic *enic, struct vic_provinfo *vp)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_init_prov2(enic->vdev,
-		(u8 *)vp, vic_provinfo_size(vp));
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-int enic_dev_deinit_done(struct enic *enic, int *status)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_deinit_done(enic->vdev, status);
-	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);
-}
-
-int enic_dev_enable2(struct enic *enic, int active)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_enable2(enic->vdev, active);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-int enic_dev_enable2_done(struct enic *enic, int *status)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_enable2_done(enic->vdev, status);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-int enic_dev_status_to_errno(int devcmd_status)
-{
-	switch (devcmd_status) {
-	case ERR_SUCCESS:
-		return 0;
-	case ERR_EINVAL:
-		return -EINVAL;
-	case ERR_EFAULT:
-		return -EFAULT;
-	case ERR_EPERM:
-		return -EPERM;
-	case ERR_EBUSY:
-		return -EBUSY;
-	case ERR_ECMDUNKNOWN:
-	case ERR_ENOTSUPPORTED:
-		return -EOPNOTSUPP;
-	case ERR_EBADSTATE:
-		return -EINVAL;
-	case ERR_ENOMEM:
-		return -ENOMEM;
-	case ERR_ETIMEDOUT:
-		return -ETIMEDOUT;
-	case ERR_ELINKDOWN:
-		return -ENETDOWN;
-	case ERR_EINPROGRESS:
-		return -EINPROGRESS;
-	case ERR_EMAXRES:
-	default:
-		return (devcmd_status < 0) ? devcmd_status : -1;
-	}
-}
diff -druN linux-libre-3.1-gnu/drivers/net/enic/enic_dev.h linux-libre-3.2-gnu/drivers/net/enic/enic_dev.h
--- linux-libre-3.1-gnu/drivers/net/enic/enic_dev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/enic_dev.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-/*
- * 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_dev_intr_coal_timer_info(struct enic *enic);
-int enic_vnic_dev_deinit(struct enic *enic);
-int enic_dev_init_prov2(struct enic *enic, struct vic_provinfo *vp);
-int enic_dev_deinit_done(struct enic *enic, int *status);
-int enic_dev_enable2(struct enic *enic, int arg);
-int enic_dev_enable2_done(struct enic *enic, int *status);
-int enic_dev_status_to_errno(int devcmd_status);
-
-#endif /* _ENIC_DEV_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/enic.h linux-libre-3.2-gnu/drivers/net/enic/enic.h
--- linux-libre-3.1-gnu/drivers/net/enic/enic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/enic.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,124 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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_H_
-#define _ENIC_H_
-
-#include "vnic_enet.h"
-#include "vnic_dev.h"
-#include "vnic_wq.h"
-#include "vnic_rq.h"
-#include "vnic_cq.h"
-#include "vnic_intr.h"
-#include "vnic_stats.h"
-#include "vnic_nic.h"
-#include "vnic_rss.h"
-
-#define DRV_NAME		"enic"
-#define DRV_DESCRIPTION		"Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION		"2.1.1.24"
-#define DRV_COPYRIGHT		"Copyright 2008-2011 Cisco Systems, Inc"
-
-#define ENIC_BARS_MAX		6
-
-#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)
-
-struct enic_msix_entry {
-	int requested;
-	char devname[IFNAMSIZ];
-	irqreturn_t (*isr)(int, void *);
-	void *devid;
-};
-
-#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)
-#define ENIC_SET_HOST			(1 << 4)
-
-struct enic_port_profile {
-	u32 set;
-	u8 request;
-	char name[PORT_PROFILE_MAX];
-	u8 instance_uuid[PORT_UUID_MAX];
-	u8 host_uuid[PORT_UUID_MAX];
-	u8 vf_mac[ETH_ALEN];
-	u8 mac_addr[ETH_ALEN];
-};
-
-/* Per-instance private data structure */
-struct enic {
-	struct net_device *netdev;
-	struct pci_dev *pdev;
-	struct vnic_enet_config config;
-	struct vnic_dev_bar bar[ENIC_BARS_MAX];
-	struct vnic_dev *vdev;
-	struct timer_list notify_timer;
-	struct work_struct reset;
-	struct work_struct change_mtu_work;
-	struct msix_entry msix_entry[ENIC_INTR_MAX];
-	struct enic_msix_entry msix[ENIC_INTR_MAX];
-	u32 msg_enable;
-	spinlock_t devcmd_lock;
-	u8 mac_addr[ETH_ALEN];
-	u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN];
-	u8 uc_addr[ENIC_UNICAST_PERFECT_FILTERS][ETH_ALEN];
-	unsigned int flags;
-	unsigned int mc_count;
-	unsigned int uc_count;
-	u32 port_mtu;
-	u32 rx_coalesce_usecs;
-	u32 tx_coalesce_usecs;
-	struct enic_port_profile pp;
-
-	/* work queue cache line section */
-	____cacheline_aligned struct vnic_wq wq[ENIC_WQ_MAX];
-	spinlock_t wq_lock[ENIC_WQ_MAX];
-	unsigned int wq_count;
-	u16 loop_enable;
-	u16 loop_tag;
-
-	/* receive queue cache line section */
-	____cacheline_aligned struct vnic_rq rq[ENIC_RQ_MAX];
-	unsigned int rq_count;
-	u64 rq_truncated_pkts;
-	u64 rq_bad_fcs;
-	struct napi_struct napi[ENIC_RQ_MAX];
-
-	/* interrupt resource cache line section */
-	____cacheline_aligned struct vnic_intr intr[ENIC_INTR_MAX];
-	unsigned int intr_count;
-	u32 __iomem *legacy_pba;		/* memory-mapped */
-
-	/* completion queue cache line section */
-	____cacheline_aligned struct vnic_cq cq[ENIC_CQ_MAX];
-	unsigned int cq_count;
-};
-
-static inline struct device *enic_get_dev(struct enic *enic)
-{
-	return &(enic->pdev->dev);
-}
-
-void enic_reset_addr_lists(struct enic *enic);
-
-#endif /* _ENIC_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/enic_main.c linux-libre-3.2-gnu/drivers/net/enic/enic_main.c
--- linux-libre-3.1-gnu/drivers/net/enic/enic_main.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/enic_main.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2513 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_ether.h>
-#include <linux/if_vlan.h>
-#include <linux/ethtool.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/tcp.h>
-#include <linux/rtnetlink.h>
-#include <linux/prefetch.h>
-#include <net/ip6_checksum.h>
-
-#include "cq_enet_desc.h"
-#include "vnic_dev.h"
-#include "vnic_intr.h"
-#include "vnic_stats.h"
-#include "vnic_vic.h"
-#include "enic_res.h"
-#include "enic.h"
-#include "enic_dev.h"
-#include "enic_pp.h"
-
-#define ENIC_NOTIFY_TIMER_PERIOD	(2 * HZ)
-#define WQ_ENET_MAX_DESC_LEN		(1 << WQ_ENET_LEN_BITS)
-#define MAX_TSO				(1 << 16)
-#define ENIC_DESC_MAX_SPLITS		(MAX_TSO / WQ_ENET_MAX_DESC_LEN + 1)
-
-#define PCI_DEVICE_ID_CISCO_VIC_ENET         0x0043  /* ethernet vnic */
-#define PCI_DEVICE_ID_CISCO_VIC_ENET_DYN     0x0044  /* enet dynamic vnic */
-
-/* Supported devices */
-static DEFINE_PCI_DEVICE_TABLE(enic_id_table) = {
-	{ PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) },
-	{ PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_DYN) },
-	{ 0, }	/* end of table */
-};
-
-MODULE_DESCRIPTION(DRV_DESCRIPTION);
-MODULE_AUTHOR("Scott Feldman <scofeldm@cisco.com>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-MODULE_DEVICE_TABLE(pci, enic_id_table);
-
-struct enic_stat {
-	char name[ETH_GSTRING_LEN];
-	unsigned int offset;
-};
-
-#define ENIC_TX_STAT(stat)	\
-	{ .name = #stat, .offset = offsetof(struct vnic_tx_stats, stat) / 8 }
-#define ENIC_RX_STAT(stat)	\
-	{ .name = #stat, .offset = offsetof(struct vnic_rx_stats, stat) / 8 }
-
-static const struct enic_stat enic_tx_stats[] = {
-	ENIC_TX_STAT(tx_frames_ok),
-	ENIC_TX_STAT(tx_unicast_frames_ok),
-	ENIC_TX_STAT(tx_multicast_frames_ok),
-	ENIC_TX_STAT(tx_broadcast_frames_ok),
-	ENIC_TX_STAT(tx_bytes_ok),
-	ENIC_TX_STAT(tx_unicast_bytes_ok),
-	ENIC_TX_STAT(tx_multicast_bytes_ok),
-	ENIC_TX_STAT(tx_broadcast_bytes_ok),
-	ENIC_TX_STAT(tx_drops),
-	ENIC_TX_STAT(tx_errors),
-	ENIC_TX_STAT(tx_tso),
-};
-
-static const struct enic_stat enic_rx_stats[] = {
-	ENIC_RX_STAT(rx_frames_ok),
-	ENIC_RX_STAT(rx_frames_total),
-	ENIC_RX_STAT(rx_unicast_frames_ok),
-	ENIC_RX_STAT(rx_multicast_frames_ok),
-	ENIC_RX_STAT(rx_broadcast_frames_ok),
-	ENIC_RX_STAT(rx_bytes_ok),
-	ENIC_RX_STAT(rx_unicast_bytes_ok),
-	ENIC_RX_STAT(rx_multicast_bytes_ok),
-	ENIC_RX_STAT(rx_broadcast_bytes_ok),
-	ENIC_RX_STAT(rx_drop),
-	ENIC_RX_STAT(rx_no_bufs),
-	ENIC_RX_STAT(rx_errors),
-	ENIC_RX_STAT(rx_rss),
-	ENIC_RX_STAT(rx_crc_errors),
-	ENIC_RX_STAT(rx_frames_64),
-	ENIC_RX_STAT(rx_frames_127),
-	ENIC_RX_STAT(rx_frames_255),
-	ENIC_RX_STAT(rx_frames_511),
-	ENIC_RX_STAT(rx_frames_1023),
-	ENIC_RX_STAT(rx_frames_1518),
-	ENIC_RX_STAT(rx_frames_to_max),
-};
-
-static const unsigned int enic_n_tx_stats = ARRAY_SIZE(enic_tx_stats);
-static const unsigned int enic_n_rx_stats = ARRAY_SIZE(enic_rx_stats);
-
-static int enic_is_dynamic(struct enic *enic)
-{
-	return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN;
-}
-
-static inline unsigned int enic_cq_rq(struct enic *enic, unsigned int rq)
-{
-	return rq;
-}
-
-static inline unsigned int enic_cq_wq(struct enic *enic, unsigned int wq)
-{
-	return enic->rq_count + wq;
-}
-
-static inline unsigned int enic_legacy_io_intr(void)
-{
-	return 0;
-}
-
-static inline unsigned int enic_legacy_err_intr(void)
-{
-	return 1;
-}
-
-static inline unsigned int enic_legacy_notify_intr(void)
-{
-	return 2;
-}
-
-static inline unsigned int enic_msix_rq_intr(struct enic *enic, unsigned int rq)
-{
-	return enic->cq[enic_cq_rq(enic, rq)].interrupt_offset;
-}
-
-static inline unsigned int enic_msix_wq_intr(struct enic *enic, unsigned int wq)
-{
-	return enic->cq[enic_cq_wq(enic, wq)].interrupt_offset;
-}
-
-static inline unsigned int enic_msix_err_intr(struct enic *enic)
-{
-	return enic->rq_count + enic->wq_count;
-}
-
-static inline unsigned int enic_msix_notify_intr(struct enic *enic)
-{
-	return enic->rq_count + enic->wq_count + 1;
-}
-
-static int enic_get_settings(struct net_device *netdev,
-	struct ethtool_cmd *ecmd)
-{
-	struct enic *enic = netdev_priv(netdev);
-
-	ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
-	ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
-	ecmd->port = PORT_FIBRE;
-	ecmd->transceiver = XCVR_EXTERNAL;
-
-	if (netif_carrier_ok(netdev)) {
-		ethtool_cmd_speed_set(ecmd, vnic_dev_port_speed(enic->vdev));
-		ecmd->duplex = DUPLEX_FULL;
-	} else {
-		ethtool_cmd_speed_set(ecmd, -1);
-		ecmd->duplex = -1;
-	}
-
-	ecmd->autoneg = AUTONEG_DISABLE;
-
-	return 0;
-}
-
-static void enic_get_drvinfo(struct net_device *netdev,
-	struct ethtool_drvinfo *drvinfo)
-{
-	struct enic *enic = netdev_priv(netdev);
-	struct vnic_devcmd_fw_info *fw_info;
-
-	enic_dev_fw_info(enic, &fw_info);
-
-	strncpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
-	strncpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version));
-	strncpy(drvinfo->fw_version, fw_info->fw_version,
-		sizeof(drvinfo->fw_version));
-	strncpy(drvinfo->bus_info, pci_name(enic->pdev),
-		sizeof(drvinfo->bus_info));
-}
-
-static void enic_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
-{
-	unsigned int i;
-
-	switch (stringset) {
-	case ETH_SS_STATS:
-		for (i = 0; i < enic_n_tx_stats; i++) {
-			memcpy(data, enic_tx_stats[i].name, ETH_GSTRING_LEN);
-			data += ETH_GSTRING_LEN;
-		}
-		for (i = 0; i < enic_n_rx_stats; i++) {
-			memcpy(data, enic_rx_stats[i].name, ETH_GSTRING_LEN);
-			data += ETH_GSTRING_LEN;
-		}
-		break;
-	}
-}
-
-static int enic_get_sset_count(struct net_device *netdev, int sset)
-{
-	switch (sset) {
-	case ETH_SS_STATS:
-		return enic_n_tx_stats + enic_n_rx_stats;
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void enic_get_ethtool_stats(struct net_device *netdev,
-	struct ethtool_stats *stats, u64 *data)
-{
-	struct enic *enic = netdev_priv(netdev);
-	struct vnic_stats *vstats;
-	unsigned int i;
-
-	enic_dev_stats_dump(enic, &vstats);
-
-	for (i = 0; i < enic_n_tx_stats; i++)
-		*(data++) = ((u64 *)&vstats->tx)[enic_tx_stats[i].offset];
-	for (i = 0; i < enic_n_rx_stats; i++)
-		*(data++) = ((u64 *)&vstats->rx)[enic_rx_stats[i].offset];
-}
-
-static u32 enic_get_msglevel(struct net_device *netdev)
-{
-	struct enic *enic = netdev_priv(netdev);
-	return enic->msg_enable;
-}
-
-static void enic_set_msglevel(struct net_device *netdev, u32 value)
-{
-	struct enic *enic = netdev_priv(netdev);
-	enic->msg_enable = value;
-}
-
-static int enic_get_coalesce(struct net_device *netdev,
-	struct ethtool_coalesce *ecmd)
-{
-	struct enic *enic = netdev_priv(netdev);
-
-	ecmd->tx_coalesce_usecs = enic->tx_coalesce_usecs;
-	ecmd->rx_coalesce_usecs = enic->rx_coalesce_usecs;
-
-	return 0;
-}
-
-static int enic_set_coalesce(struct net_device *netdev,
-	struct ethtool_coalesce *ecmd)
-{
-	struct enic *enic = netdev_priv(netdev);
-	u32 tx_coalesce_usecs;
-	u32 rx_coalesce_usecs;
-	unsigned int i, intr;
-
-	tx_coalesce_usecs = min_t(u32, ecmd->tx_coalesce_usecs,
-		vnic_dev_get_intr_coal_timer_max(enic->vdev));
-	rx_coalesce_usecs = min_t(u32, ecmd->rx_coalesce_usecs,
-		vnic_dev_get_intr_coal_timer_max(enic->vdev));
-
-	switch (vnic_dev_get_intr_mode(enic->vdev)) {
-	case VNIC_DEV_INTR_MODE_INTX:
-		if (tx_coalesce_usecs != rx_coalesce_usecs)
-			return -EINVAL;
-
-		intr = enic_legacy_io_intr();
-		vnic_intr_coalescing_timer_set(&enic->intr[intr],
-			tx_coalesce_usecs);
-		break;
-	case VNIC_DEV_INTR_MODE_MSI:
-		if (tx_coalesce_usecs != rx_coalesce_usecs)
-			return -EINVAL;
-
-		vnic_intr_coalescing_timer_set(&enic->intr[0],
-			tx_coalesce_usecs);
-		break;
-	case VNIC_DEV_INTR_MODE_MSIX:
-		for (i = 0; i < enic->wq_count; i++) {
-			intr = enic_msix_wq_intr(enic, i);
-			vnic_intr_coalescing_timer_set(&enic->intr[intr],
-				tx_coalesce_usecs);
-		}
-
-		for (i = 0; i < enic->rq_count; i++) {
-			intr = enic_msix_rq_intr(enic, i);
-			vnic_intr_coalescing_timer_set(&enic->intr[intr],
-				rx_coalesce_usecs);
-		}
-
-		break;
-	default:
-		break;
-	}
-
-	enic->tx_coalesce_usecs = tx_coalesce_usecs;
-	enic->rx_coalesce_usecs = rx_coalesce_usecs;
-
-	return 0;
-}
-
-static const struct ethtool_ops enic_ethtool_ops = {
-	.get_settings = enic_get_settings,
-	.get_drvinfo = enic_get_drvinfo,
-	.get_msglevel = enic_get_msglevel,
-	.set_msglevel = enic_set_msglevel,
-	.get_link = ethtool_op_get_link,
-	.get_strings = enic_get_strings,
-	.get_sset_count = enic_get_sset_count,
-	.get_ethtool_stats = enic_get_ethtool_stats,
-	.get_coalesce = enic_get_coalesce,
-	.set_coalesce = enic_set_coalesce,
-};
-
-static void enic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf)
-{
-	struct enic *enic = vnic_dev_priv(wq->vdev);
-
-	if (buf->sop)
-		pci_unmap_single(enic->pdev, buf->dma_addr,
-			buf->len, PCI_DMA_TODEVICE);
-	else
-		pci_unmap_page(enic->pdev, buf->dma_addr,
-			buf->len, PCI_DMA_TODEVICE);
-
-	if (buf->os_buf)
-		dev_kfree_skb_any(buf->os_buf);
-}
-
-static void enic_wq_free_buf(struct vnic_wq *wq,
-	struct cq_desc *cq_desc, struct vnic_wq_buf *buf, void *opaque)
-{
-	enic_free_wq_buf(wq, buf);
-}
-
-static int enic_wq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
-	u8 type, u16 q_number, u16 completed_index, void *opaque)
-{
-	struct enic *enic = vnic_dev_priv(vdev);
-
-	spin_lock(&enic->wq_lock[q_number]);
-
-	vnic_wq_service(&enic->wq[q_number], cq_desc,
-		completed_index, enic_wq_free_buf,
-		opaque);
-
-	if (netif_queue_stopped(enic->netdev) &&
-	    vnic_wq_desc_avail(&enic->wq[q_number]) >=
-	    (MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS))
-		netif_wake_queue(enic->netdev);
-
-	spin_unlock(&enic->wq_lock[q_number]);
-
-	return 0;
-}
-
-static void enic_log_q_error(struct enic *enic)
-{
-	unsigned int i;
-	u32 error_status;
-
-	for (i = 0; i < enic->wq_count; i++) {
-		error_status = vnic_wq_error_status(&enic->wq[i]);
-		if (error_status)
-			netdev_err(enic->netdev, "WQ[%d] error_status %d\n",
-				i, error_status);
-	}
-
-	for (i = 0; i < enic->rq_count; i++) {
-		error_status = vnic_rq_error_status(&enic->rq[i]);
-		if (error_status)
-			netdev_err(enic->netdev, "RQ[%d] error_status %d\n",
-				i, error_status);
-	}
-}
-
-static void enic_msglvl_check(struct enic *enic)
-{
-	u32 msg_enable = vnic_dev_msg_lvl(enic->vdev);
-
-	if (msg_enable != enic->msg_enable) {
-		netdev_info(enic->netdev, "msg lvl changed from 0x%x to 0x%x\n",
-			enic->msg_enable, msg_enable);
-		enic->msg_enable = msg_enable;
-	}
-}
-
-static void enic_mtu_check(struct enic *enic)
-{
-	u32 mtu = vnic_dev_mtu(enic->vdev);
-	struct net_device *netdev = enic->netdev;
-
-	if (mtu && mtu != enic->port_mtu) {
-		enic->port_mtu = mtu;
-		if (enic_is_dynamic(enic)) {
-			mtu = max_t(int, ENIC_MIN_MTU,
-				min_t(int, ENIC_MAX_MTU, mtu));
-			if (mtu != netdev->mtu)
-				schedule_work(&enic->change_mtu_work);
-		} else {
-			if (mtu < netdev->mtu)
-				netdev_warn(netdev,
-					"interface MTU (%d) set higher "
-					"than switch port MTU (%d)\n",
-					netdev->mtu, mtu);
-		}
-	}
-}
-
-static void enic_link_check(struct enic *enic)
-{
-	int link_status = vnic_dev_link_status(enic->vdev);
-	int carrier_ok = netif_carrier_ok(enic->netdev);
-
-	if (link_status && !carrier_ok) {
-		netdev_info(enic->netdev, "Link UP\n");
-		netif_carrier_on(enic->netdev);
-	} else if (!link_status && carrier_ok) {
-		netdev_info(enic->netdev, "Link DOWN\n");
-		netif_carrier_off(enic->netdev);
-	}
-}
-
-static void enic_notify_check(struct enic *enic)
-{
-	enic_msglvl_check(enic);
-	enic_mtu_check(enic);
-	enic_link_check(enic);
-}
-
-#define ENIC_TEST_INTR(pba, i) (pba & (1 << i))
-
-static irqreturn_t enic_isr_legacy(int irq, void *data)
-{
-	struct net_device *netdev = data;
-	struct enic *enic = netdev_priv(netdev);
-	unsigned int io_intr = enic_legacy_io_intr();
-	unsigned int err_intr = enic_legacy_err_intr();
-	unsigned int notify_intr = enic_legacy_notify_intr();
-	u32 pba;
-
-	vnic_intr_mask(&enic->intr[io_intr]);
-
-	pba = vnic_intr_legacy_pba(enic->legacy_pba);
-	if (!pba) {
-		vnic_intr_unmask(&enic->intr[io_intr]);
-		return IRQ_NONE;	/* not our interrupt */
-	}
-
-	if (ENIC_TEST_INTR(pba, notify_intr)) {
-		vnic_intr_return_all_credits(&enic->intr[notify_intr]);
-		enic_notify_check(enic);
-	}
-
-	if (ENIC_TEST_INTR(pba, err_intr)) {
-		vnic_intr_return_all_credits(&enic->intr[err_intr]);
-		enic_log_q_error(enic);
-		/* schedule recovery from WQ/RQ error */
-		schedule_work(&enic->reset);
-		return IRQ_HANDLED;
-	}
-
-	if (ENIC_TEST_INTR(pba, io_intr)) {
-		if (napi_schedule_prep(&enic->napi[0]))
-			__napi_schedule(&enic->napi[0]);
-	} else {
-		vnic_intr_unmask(&enic->intr[io_intr]);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t enic_isr_msi(int irq, void *data)
-{
-	struct enic *enic = data;
-
-	/* With MSI, there is no sharing of interrupts, so this is
-	 * our interrupt and there is no need to ack it.  The device
-	 * is not providing per-vector masking, so the OS will not
-	 * write to PCI config space to mask/unmask the interrupt.
-	 * We're using mask_on_assertion for MSI, so the device
-	 * automatically masks the interrupt when the interrupt is
-	 * generated.  Later, when exiting polling, the interrupt
-	 * will be unmasked (see enic_poll).
-	 *
-	 * Also, the device uses the same PCIe Traffic Class (TC)
-	 * for Memory Write data and MSI, so there are no ordering
-	 * issues; the MSI will always arrive at the Root Complex
-	 * _after_ corresponding Memory Writes (i.e. descriptor
-	 * writes).
-	 */
-
-	napi_schedule(&enic->napi[0]);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t enic_isr_msix_rq(int irq, void *data)
-{
-	struct napi_struct *napi = data;
-
-	/* schedule NAPI polling for RQ cleanup */
-	napi_schedule(napi);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t enic_isr_msix_wq(int irq, void *data)
-{
-	struct enic *enic = data;
-	unsigned int cq = enic_cq_wq(enic, 0);
-	unsigned int intr = enic_msix_wq_intr(enic, 0);
-	unsigned int wq_work_to_do = -1; /* no limit */
-	unsigned int wq_work_done;
-
-	wq_work_done = vnic_cq_service(&enic->cq[cq],
-		wq_work_to_do, enic_wq_service, NULL);
-
-	vnic_intr_return_credits(&enic->intr[intr],
-		wq_work_done,
-		1 /* unmask intr */,
-		1 /* reset intr timer */);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t enic_isr_msix_err(int irq, void *data)
-{
-	struct enic *enic = data;
-	unsigned int intr = enic_msix_err_intr(enic);
-
-	vnic_intr_return_all_credits(&enic->intr[intr]);
-
-	enic_log_q_error(enic);
-
-	/* schedule recovery from WQ/RQ error */
-	schedule_work(&enic->reset);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t enic_isr_msix_notify(int irq, void *data)
-{
-	struct enic *enic = data;
-	unsigned int intr = enic_msix_notify_intr(enic);
-
-	vnic_intr_return_all_credits(&enic->intr[intr]);
-	enic_notify_check(enic);
-
-	return IRQ_HANDLED;
-}
-
-static inline void enic_queue_wq_skb_cont(struct enic *enic,
-	struct vnic_wq *wq, struct sk_buff *skb,
-	unsigned int len_left, int loopback)
-{
-	skb_frag_t *frag;
-
-	/* Queue additional data fragments */
-	for (frag = skb_shinfo(skb)->frags; len_left; frag++) {
-		len_left -= frag->size;
-		enic_queue_wq_desc_cont(wq, skb,
-			pci_map_page(enic->pdev, frag->page,
-				frag->page_offset, frag->size,
-				PCI_DMA_TODEVICE),
-			frag->size,
-			(len_left == 0),	/* EOP? */
-			loopback);
-	}
-}
-
-static inline void enic_queue_wq_skb_vlan(struct enic *enic,
-	struct vnic_wq *wq, struct sk_buff *skb,
-	int vlan_tag_insert, unsigned int vlan_tag, int loopback)
-{
-	unsigned int head_len = skb_headlen(skb);
-	unsigned int len_left = skb->len - head_len;
-	int eop = (len_left == 0);
-
-	/* Queue the main skb fragment. The fragments are no larger
-	 * than max MTU(9000)+ETH_HDR_LEN(14) bytes, which is less
-	 * than WQ_ENET_MAX_DESC_LEN length. So only one descriptor
-	 * per fragment is queued.
-	 */
-	enic_queue_wq_desc(wq, skb,
-		pci_map_single(enic->pdev, skb->data,
-			head_len, PCI_DMA_TODEVICE),
-		head_len,
-		vlan_tag_insert, vlan_tag,
-		eop, loopback);
-
-	if (!eop)
-		enic_queue_wq_skb_cont(enic, wq, skb, len_left, loopback);
-}
-
-static inline void enic_queue_wq_skb_csum_l4(struct enic *enic,
-	struct vnic_wq *wq, struct sk_buff *skb,
-	int vlan_tag_insert, unsigned int vlan_tag, int loopback)
-{
-	unsigned int head_len = skb_headlen(skb);
-	unsigned int len_left = skb->len - head_len;
-	unsigned int hdr_len = skb_checksum_start_offset(skb);
-	unsigned int csum_offset = hdr_len + skb->csum_offset;
-	int eop = (len_left == 0);
-
-	/* Queue the main skb fragment. The fragments are no larger
-	 * than max MTU(9000)+ETH_HDR_LEN(14) bytes, which is less
-	 * than WQ_ENET_MAX_DESC_LEN length. So only one descriptor
-	 * per fragment is queued.
-	 */
-	enic_queue_wq_desc_csum_l4(wq, skb,
-		pci_map_single(enic->pdev, skb->data,
-			head_len, PCI_DMA_TODEVICE),
-		head_len,
-		csum_offset,
-		hdr_len,
-		vlan_tag_insert, vlan_tag,
-		eop, loopback);
-
-	if (!eop)
-		enic_queue_wq_skb_cont(enic, wq, skb, len_left, loopback);
-}
-
-static inline void enic_queue_wq_skb_tso(struct enic *enic,
-	struct vnic_wq *wq, struct sk_buff *skb, unsigned int mss,
-	int vlan_tag_insert, unsigned int vlan_tag, int loopback)
-{
-	unsigned int frag_len_left = skb_headlen(skb);
-	unsigned int len_left = skb->len - frag_len_left;
-	unsigned int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-	int eop = (len_left == 0);
-	unsigned int len;
-	dma_addr_t dma_addr;
-	unsigned int offset = 0;
-	skb_frag_t *frag;
-
-	/* Preload TCP csum field with IP pseudo hdr calculated
-	 * with IP length set to zero.  HW will later add in length
-	 * to each TCP segment resulting from the TSO.
-	 */
-
-	if (skb->protocol == cpu_to_be16(ETH_P_IP)) {
-		ip_hdr(skb)->check = 0;
-		tcp_hdr(skb)->check = ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
-			ip_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
-	} else if (skb->protocol == cpu_to_be16(ETH_P_IPV6)) {
-		tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
-			&ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
-	}
-
-	/* Queue WQ_ENET_MAX_DESC_LEN length descriptors
-	 * for the main skb fragment
-	 */
-	while (frag_len_left) {
-		len = min(frag_len_left, (unsigned int)WQ_ENET_MAX_DESC_LEN);
-		dma_addr = pci_map_single(enic->pdev, skb->data + offset,
-				len, PCI_DMA_TODEVICE);
-		enic_queue_wq_desc_tso(wq, skb,
-			dma_addr,
-			len,
-			mss, hdr_len,
-			vlan_tag_insert, vlan_tag,
-			eop && (len == frag_len_left), loopback);
-		frag_len_left -= len;
-		offset += len;
-	}
-
-	if (eop)
-		return;
-
-	/* Queue WQ_ENET_MAX_DESC_LEN length descriptors
-	 * for additional data fragments
-	 */
-	for (frag = skb_shinfo(skb)->frags; len_left; frag++) {
-		len_left -= frag->size;
-		frag_len_left = frag->size;
-		offset = frag->page_offset;
-
-		while (frag_len_left) {
-			len = min(frag_len_left,
-				(unsigned int)WQ_ENET_MAX_DESC_LEN);
-			dma_addr = pci_map_page(enic->pdev, frag->page,
-				offset, len,
-				PCI_DMA_TODEVICE);
-			enic_queue_wq_desc_cont(wq, skb,
-				dma_addr,
-				len,
-				(len_left == 0) &&
-				(len == frag_len_left),		/* EOP? */
-				loopback);
-			frag_len_left -= len;
-			offset += len;
-		}
-	}
-}
-
-static inline void enic_queue_wq_skb(struct enic *enic,
-	struct vnic_wq *wq, struct sk_buff *skb)
-{
-	unsigned int mss = skb_shinfo(skb)->gso_size;
-	unsigned int vlan_tag = 0;
-	int vlan_tag_insert = 0;
-	int loopback = 0;
-
-	if (vlan_tx_tag_present(skb)) {
-		/* VLAN tag from trunking driver */
-		vlan_tag_insert = 1;
-		vlan_tag = vlan_tx_tag_get(skb);
-	} else if (enic->loop_enable) {
-		vlan_tag = enic->loop_tag;
-		loopback = 1;
-	}
-
-	if (mss)
-		enic_queue_wq_skb_tso(enic, wq, skb, mss,
-			vlan_tag_insert, vlan_tag, loopback);
-	else if	(skb->ip_summed == CHECKSUM_PARTIAL)
-		enic_queue_wq_skb_csum_l4(enic, wq, skb,
-			vlan_tag_insert, vlan_tag, loopback);
-	else
-		enic_queue_wq_skb_vlan(enic, wq, skb,
-			vlan_tag_insert, vlan_tag, loopback);
-}
-
-/* netif_tx_lock held, process context with BHs disabled, or BH */
-static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb,
-	struct net_device *netdev)
-{
-	struct enic *enic = netdev_priv(netdev);
-	struct vnic_wq *wq = &enic->wq[0];
-	unsigned long flags;
-
-	if (skb->len <= 0) {
-		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-
-	/* Non-TSO sends must fit within ENIC_NON_TSO_MAX_DESC descs,
-	 * which is very likely.  In the off chance it's going to take
-	 * more than * ENIC_NON_TSO_MAX_DESC, linearize the skb.
-	 */
-
-	if (skb_shinfo(skb)->gso_size == 0 &&
-	    skb_shinfo(skb)->nr_frags + 1 > ENIC_NON_TSO_MAX_DESC &&
-	    skb_linearize(skb)) {
-		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-
-	spin_lock_irqsave(&enic->wq_lock[0], flags);
-
-	if (vnic_wq_desc_avail(wq) <
-	    skb_shinfo(skb)->nr_frags + ENIC_DESC_MAX_SPLITS) {
-		netif_stop_queue(netdev);
-		/* This is a hard error, log it */
-		netdev_err(netdev, "BUG! Tx ring full when queue awake!\n");
-		spin_unlock_irqrestore(&enic->wq_lock[0], flags);
-		return NETDEV_TX_BUSY;
-	}
-
-	enic_queue_wq_skb(enic, wq, skb);
-
-	if (vnic_wq_desc_avail(wq) < MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS)
-		netif_stop_queue(netdev);
-
-	spin_unlock_irqrestore(&enic->wq_lock[0], flags);
-
-	return NETDEV_TX_OK;
-}
-
-/* dev_base_lock rwlock held, nominally process context */
-static struct rtnl_link_stats64 *enic_get_stats(struct net_device *netdev,
-						struct rtnl_link_stats64 *net_stats)
-{
-	struct enic *enic = netdev_priv(netdev);
-	struct vnic_stats *stats;
-
-	enic_dev_stats_dump(enic, &stats);
-
-	net_stats->tx_packets = stats->tx.tx_frames_ok;
-	net_stats->tx_bytes = stats->tx.tx_bytes_ok;
-	net_stats->tx_errors = stats->tx.tx_errors;
-	net_stats->tx_dropped = stats->tx.tx_drops;
-
-	net_stats->rx_packets = stats->rx.rx_frames_ok;
-	net_stats->rx_bytes = stats->rx.rx_bytes_ok;
-	net_stats->rx_errors = stats->rx.rx_errors;
-	net_stats->multicast = stats->rx.rx_multicast_frames_ok;
-	net_stats->rx_over_errors = enic->rq_truncated_pkts;
-	net_stats->rx_crc_errors = enic->rq_bad_fcs;
-	net_stats->rx_dropped = stats->rx.rx_no_bufs + stats->rx.rx_drop;
-
-	return net_stats;
-}
-
-void enic_reset_addr_lists(struct enic *enic)
-{
-	enic->mc_count = 0;
-	enic->uc_count = 0;
-	enic->flags = 0;
-}
-
-static int enic_set_mac_addr(struct net_device *netdev, char *addr)
-{
-	struct enic *enic = netdev_priv(netdev);
-
-	if (enic_is_dynamic(enic)) {
-		if (!is_valid_ether_addr(addr) && !is_zero_ether_addr(addr))
-			return -EADDRNOTAVAIL;
-	} else {
-		if (!is_valid_ether_addr(addr))
-			return -EADDRNOTAVAIL;
-	}
-
-	memcpy(netdev->dev_addr, addr, netdev->addr_len);
-
-	return 0;
-}
-
-static int enic_set_mac_address_dynamic(struct net_device *netdev, void *p)
-{
-	struct enic *enic = netdev_priv(netdev);
-	struct sockaddr *saddr = p;
-	char *addr = saddr->sa_data;
-	int err;
-
-	if (netif_running(enic->netdev)) {
-		err = enic_dev_del_station_addr(enic);
-		if (err)
-			return err;
-	}
-
-	err = enic_set_mac_addr(netdev, addr);
-	if (err)
-		return err;
-
-	if (netif_running(enic->netdev)) {
-		err = enic_dev_add_station_addr(enic);
-		if (err)
-			return err;
-	}
-
-	return err;
-}
-
-static int enic_set_mac_address(struct net_device *netdev, void *p)
-{
-	struct sockaddr *saddr = p;
-	char *addr = saddr->sa_data;
-	struct enic *enic = netdev_priv(netdev);
-	int err;
-
-	err = enic_dev_del_station_addr(enic);
-	if (err)
-		return err;
-
-	err = enic_set_mac_addr(netdev, addr);
-	if (err)
-		return err;
-
-	return enic_dev_add_station_addr(enic);
-}
-
-static void enic_update_multicast_addr_list(struct enic *enic)
-{
-	struct net_device *netdev = enic->netdev;
-	struct netdev_hw_addr *ha;
-	unsigned int mc_count = netdev_mc_count(netdev);
-	u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN];
-	unsigned int i, j;
-
-	if (mc_count > ENIC_MULTICAST_PERFECT_FILTERS) {
-		netdev_warn(netdev, "Registering only %d out of %d "
-			"multicast addresses\n",
-			ENIC_MULTICAST_PERFECT_FILTERS, mc_count);
-		mc_count = ENIC_MULTICAST_PERFECT_FILTERS;
-	}
-
-	/* Is there an easier way?  Trying to minimize to
-	 * calls to add/del multicast addrs.  We keep the
-	 * addrs from the last call in enic->mc_addr and
-	 * look for changes to add/del.
-	 */
-
-	i = 0;
-	netdev_for_each_mc_addr(ha, netdev) {
-		if (i == mc_count)
-			break;
-		memcpy(mc_addr[i++], ha->addr, ETH_ALEN);
-	}
-
-	for (i = 0; i < enic->mc_count; i++) {
-		for (j = 0; j < mc_count; j++)
-			if (compare_ether_addr(enic->mc_addr[i],
-				mc_addr[j]) == 0)
-				break;
-		if (j == mc_count)
-			enic_dev_del_addr(enic, enic->mc_addr[i]);
-	}
-
-	for (i = 0; i < mc_count; i++) {
-		for (j = 0; j < enic->mc_count; j++)
-			if (compare_ether_addr(mc_addr[i],
-				enic->mc_addr[j]) == 0)
-				break;
-		if (j == enic->mc_count)
-			enic_dev_add_addr(enic, mc_addr[i]);
-	}
-
-	/* Save the list to compare against next time
-	 */
-
-	for (i = 0; i < mc_count; i++)
-		memcpy(enic->mc_addr[i], mc_addr[i], ETH_ALEN);
-
-	enic->mc_count = mc_count;
-}
-
-static void enic_update_unicast_addr_list(struct enic *enic)
-{
-	struct net_device *netdev = enic->netdev;
-	struct netdev_hw_addr *ha;
-	unsigned int uc_count = netdev_uc_count(netdev);
-	u8 uc_addr[ENIC_UNICAST_PERFECT_FILTERS][ETH_ALEN];
-	unsigned int i, j;
-
-	if (uc_count > ENIC_UNICAST_PERFECT_FILTERS) {
-		netdev_warn(netdev, "Registering only %d out of %d "
-			"unicast addresses\n",
-			ENIC_UNICAST_PERFECT_FILTERS, uc_count);
-		uc_count = ENIC_UNICAST_PERFECT_FILTERS;
-	}
-
-	/* Is there an easier way?  Trying to minimize to
-	 * calls to add/del unicast addrs.  We keep the
-	 * addrs from the last call in enic->uc_addr and
-	 * look for changes to add/del.
-	 */
-
-	i = 0;
-	netdev_for_each_uc_addr(ha, netdev) {
-		if (i == uc_count)
-			break;
-		memcpy(uc_addr[i++], ha->addr, ETH_ALEN);
-	}
-
-	for (i = 0; i < enic->uc_count; i++) {
-		for (j = 0; j < uc_count; j++)
-			if (compare_ether_addr(enic->uc_addr[i],
-				uc_addr[j]) == 0)
-				break;
-		if (j == uc_count)
-			enic_dev_del_addr(enic, enic->uc_addr[i]);
-	}
-
-	for (i = 0; i < uc_count; i++) {
-		for (j = 0; j < enic->uc_count; j++)
-			if (compare_ether_addr(uc_addr[i],
-				enic->uc_addr[j]) == 0)
-				break;
-		if (j == enic->uc_count)
-			enic_dev_add_addr(enic, uc_addr[i]);
-	}
-
-	/* Save the list to compare against next time
-	 */
-
-	for (i = 0; i < uc_count; i++)
-		memcpy(enic->uc_addr[i], uc_addr[i], ETH_ALEN);
-
-	enic->uc_count = uc_count;
-}
-
-/* netif_tx_lock held, BHs disabled */
-static void enic_set_rx_mode(struct net_device *netdev)
-{
-	struct enic *enic = netdev_priv(netdev);
-	int directed = 1;
-	int multicast = (netdev->flags & IFF_MULTICAST) ? 1 : 0;
-	int broadcast = (netdev->flags & IFF_BROADCAST) ? 1 : 0;
-	int promisc = (netdev->flags & IFF_PROMISC) ||
-		netdev_uc_count(netdev) > ENIC_UNICAST_PERFECT_FILTERS;
-	int allmulti = (netdev->flags & IFF_ALLMULTI) ||
-		netdev_mc_count(netdev) > ENIC_MULTICAST_PERFECT_FILTERS;
-	unsigned int flags = netdev->flags |
-		(allmulti ? IFF_ALLMULTI : 0) |
-		(promisc ? IFF_PROMISC : 0);
-
-	if (enic->flags != flags) {
-		enic->flags = flags;
-		enic_dev_packet_filter(enic, directed,
-			multicast, broadcast, promisc, allmulti);
-	}
-
-	if (!promisc) {
-		enic_update_unicast_addr_list(enic);
-		if (!allmulti)
-			enic_update_multicast_addr_list(enic);
-	}
-}
-
-/* netif_tx_lock held, BHs disabled */
-static void enic_tx_timeout(struct net_device *netdev)
-{
-	struct enic *enic = netdev_priv(netdev);
-	schedule_work(&enic->reset);
-}
-
-static int enic_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
-{
-	struct enic *enic = netdev_priv(netdev);
-
-	if (vf != PORT_SELF_VF)
-		return -EOPNOTSUPP;
-
-	/* Ignore the vf argument for now. We can assume the request
-	 * is coming on a vf.
-	 */
-	if (is_valid_ether_addr(mac)) {
-		memcpy(enic->pp.vf_mac, mac, ETH_ALEN);
-		return 0;
-	} else
-		return -EINVAL;
-}
-
-static int enic_set_vf_port(struct net_device *netdev, int vf,
-	struct nlattr *port[])
-{
-	struct enic *enic = netdev_priv(netdev);
-	struct enic_port_profile prev_pp;
-	int err = 0, restore_pp = 1;
-
-	/* don't support VFs, yet */
-	if (vf != PORT_SELF_VF)
-		return -EOPNOTSUPP;
-
-	if (!port[IFLA_PORT_REQUEST])
-		return -EOPNOTSUPP;
-
-	memcpy(&prev_pp, &enic->pp, sizeof(enic->pp));
-	memset(&enic->pp, 0, sizeof(enic->pp));
-
-	enic->pp.set |= ENIC_SET_REQUEST;
-	enic->pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]);
-
-	if (port[IFLA_PORT_PROFILE]) {
-		enic->pp.set |= ENIC_SET_NAME;
-		memcpy(enic->pp.name, nla_data(port[IFLA_PORT_PROFILE]),
-			PORT_PROFILE_MAX);
-	}
-
-	if (port[IFLA_PORT_INSTANCE_UUID]) {
-		enic->pp.set |= ENIC_SET_INSTANCE;
-		memcpy(enic->pp.instance_uuid,
-			nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX);
-	}
-
-	if (port[IFLA_PORT_HOST_UUID]) {
-		enic->pp.set |= ENIC_SET_HOST;
-		memcpy(enic->pp.host_uuid,
-			nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX);
-	}
-
-	/* Special case handling: mac came from IFLA_VF_MAC */
-	if (!is_zero_ether_addr(prev_pp.vf_mac))
-		memcpy(enic->pp.mac_addr, prev_pp.vf_mac, ETH_ALEN);
-
-		if (is_zero_ether_addr(netdev->dev_addr))
-			random_ether_addr(netdev->dev_addr);
-
-	err = enic_process_set_pp_request(enic, &prev_pp, &restore_pp);
-	if (err) {
-		if (restore_pp) {
-			/* Things are still the way they were: Implicit
-			 * DISASSOCIATE failed
-			 */
-			memcpy(&enic->pp, &prev_pp, sizeof(enic->pp));
-		} else {
-			memset(&enic->pp, 0, sizeof(enic->pp));
-			memset(netdev->dev_addr, 0, ETH_ALEN);
-		}
-	} else {
-		/* Set flag to indicate that the port assoc/disassoc
-		 * request has been sent out to fw
-		 */
-		enic->pp.set |= ENIC_PORT_REQUEST_APPLIED;
-
-		/* If DISASSOCIATE, clean up all assigned/saved macaddresses */
-		if (enic->pp.request == PORT_REQUEST_DISASSOCIATE) {
-			memset(enic->pp.mac_addr, 0, ETH_ALEN);
-			memset(netdev->dev_addr, 0, ETH_ALEN);
-		}
-	}
-
-	memset(enic->pp.vf_mac, 0, ETH_ALEN);
-
-	return err;
-}
-
-static int enic_get_vf_port(struct net_device *netdev, int vf,
-	struct sk_buff *skb)
-{
-	struct enic *enic = netdev_priv(netdev);
-	u16 response = PORT_PROFILE_RESPONSE_SUCCESS;
-	int err;
-
-	if (!(enic->pp.set & ENIC_PORT_REQUEST_APPLIED))
-		return -ENODATA;
-
-	err = enic_process_get_pp_request(enic, enic->pp.request, &response);
-	if (err)
-		return err;
-
-	NLA_PUT_U16(skb, IFLA_PORT_REQUEST, enic->pp.request);
-	NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response);
-	if (enic->pp.set & ENIC_SET_NAME)
-		NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX,
-			enic->pp.name);
-	if (enic->pp.set & ENIC_SET_INSTANCE)
-		NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX,
-			enic->pp.instance_uuid);
-	if (enic->pp.set & ENIC_SET_HOST)
-		NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX,
-			enic->pp.host_uuid);
-
-	return 0;
-
-nla_put_failure:
-	return -EMSGSIZE;
-}
-
-static void enic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf)
-{
-	struct enic *enic = vnic_dev_priv(rq->vdev);
-
-	if (!buf->os_buf)
-		return;
-
-	pci_unmap_single(enic->pdev, buf->dma_addr,
-		buf->len, PCI_DMA_FROMDEVICE);
-	dev_kfree_skb_any(buf->os_buf);
-}
-
-static int enic_rq_alloc_buf(struct vnic_rq *rq)
-{
-	struct enic *enic = vnic_dev_priv(rq->vdev);
-	struct net_device *netdev = enic->netdev;
-	struct sk_buff *skb;
-	unsigned int len = netdev->mtu + VLAN_ETH_HLEN;
-	unsigned int os_buf_index = 0;
-	dma_addr_t dma_addr;
-
-	skb = netdev_alloc_skb_ip_align(netdev, len);
-	if (!skb)
-		return -ENOMEM;
-
-	dma_addr = pci_map_single(enic->pdev, skb->data,
-		len, PCI_DMA_FROMDEVICE);
-
-	enic_queue_rq_desc(rq, skb, os_buf_index,
-		dma_addr, len);
-
-	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)
-{
-	struct enic *enic = vnic_dev_priv(rq->vdev);
-	struct net_device *netdev = enic->netdev;
-	struct sk_buff *skb;
-
-	u8 type, color, eop, sop, ingress_port, vlan_stripped;
-	u8 fcoe, fcoe_sof, fcoe_fc_crc_ok, fcoe_enc_error, fcoe_eof;
-	u8 tcp_udp_csum_ok, udp, tcp, ipv4_csum_ok;
-	u8 ipv6, ipv4, ipv4_fragment, fcs_ok, rss_type, csum_not_calc;
-	u8 packet_error;
-	u16 q_number, completed_index, bytes_written, vlan_tci, checksum;
-	u32 rss_hash;
-
-	if (skipped)
-		return;
-
-	skb = buf->os_buf;
-	prefetch(skb->data - NET_IP_ALIGN);
-	pci_unmap_single(enic->pdev, buf->dma_addr,
-		buf->len, PCI_DMA_FROMDEVICE);
-
-	cq_enet_rq_desc_dec((struct cq_enet_rq_desc *)cq_desc,
-		&type, &color, &q_number, &completed_index,
-		&ingress_port, &fcoe, &eop, &sop, &rss_type,
-		&csum_not_calc, &rss_hash, &bytes_written,
-		&packet_error, &vlan_stripped, &vlan_tci, &checksum,
-		&fcoe_sof, &fcoe_fc_crc_ok, &fcoe_enc_error,
-		&fcoe_eof, &tcp_udp_csum_ok, &udp, &tcp,
-		&ipv4_csum_ok, &ipv6, &ipv4, &ipv4_fragment,
-		&fcs_ok);
-
-	if (packet_error) {
-
-		if (!fcs_ok) {
-			if (bytes_written > 0)
-				enic->rq_bad_fcs++;
-			else if (bytes_written == 0)
-				enic->rq_truncated_pkts++;
-		}
-
-		dev_kfree_skb_any(skb);
-
-		return;
-	}
-
-	if (eop && bytes_written > 0) {
-
-		/* Good receive
-		 */
-
-		skb_put(skb, bytes_written);
-		skb->protocol = eth_type_trans(skb, netdev);
-
-		if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc) {
-			skb->csum = htons(checksum);
-			skb->ip_summed = CHECKSUM_COMPLETE;
-		}
-
-		skb->dev = netdev;
-
-		if (vlan_stripped)
-			__vlan_hwaccel_put_tag(skb, vlan_tci);
-
-		if (netdev->features & NETIF_F_GRO)
-			napi_gro_receive(&enic->napi[q_number], skb);
-		else
-			netif_receive_skb(skb);
-	} else {
-
-		/* Buffer overflow
-		 */
-
-		dev_kfree_skb_any(skb);
-	}
-}
-
-static int enic_rq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
-	u8 type, u16 q_number, u16 completed_index, void *opaque)
-{
-	struct enic *enic = vnic_dev_priv(vdev);
-
-	vnic_rq_service(&enic->rq[q_number], cq_desc,
-		completed_index, VNIC_RQ_RETURN_DESC,
-		enic_rq_indicate_buf, opaque);
-
-	return 0;
-}
-
-static int enic_poll(struct napi_struct *napi, int budget)
-{
-	struct net_device *netdev = napi->dev;
-	struct enic *enic = netdev_priv(netdev);
-	unsigned int cq_rq = enic_cq_rq(enic, 0);
-	unsigned int cq_wq = enic_cq_wq(enic, 0);
-	unsigned int intr = enic_legacy_io_intr();
-	unsigned int rq_work_to_do = budget;
-	unsigned int wq_work_to_do = -1; /* no limit */
-	unsigned int  work_done, rq_work_done, wq_work_done;
-	int err;
-
-	/* Service RQ (first) and WQ
-	 */
-
-	rq_work_done = vnic_cq_service(&enic->cq[cq_rq],
-		rq_work_to_do, enic_rq_service, NULL);
-
-	wq_work_done = vnic_cq_service(&enic->cq[cq_wq],
-		wq_work_to_do, enic_wq_service, NULL);
-
-	/* Accumulate intr event credits for this polling
-	 * cycle.  An intr event is the completion of a
-	 * a WQ or RQ packet.
-	 */
-
-	work_done = rq_work_done + wq_work_done;
-
-	if (work_done > 0)
-		vnic_intr_return_credits(&enic->intr[intr],
-			work_done,
-			0 /* don't unmask intr */,
-			0 /* don't reset intr timer */);
-
-	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.
-	 */
-
-	if (err)
-		rq_work_done = rq_work_to_do;
-
-	if (rq_work_done < rq_work_to_do) {
-
-		/* Some work done, but not enough to stay in polling,
-		 * exit polling
-		 */
-
-		napi_complete(napi);
-		vnic_intr_unmask(&enic->intr[intr]);
-	}
-
-	return rq_work_done;
-}
-
-static int enic_poll_msix(struct napi_struct *napi, int budget)
-{
-	struct net_device *netdev = napi->dev;
-	struct enic *enic = netdev_priv(netdev);
-	unsigned int rq = (napi - &enic->napi[0]);
-	unsigned int cq = enic_cq_rq(enic, rq);
-	unsigned int intr = enic_msix_rq_intr(enic, rq);
-	unsigned int work_to_do = budget;
-	unsigned int work_done;
-	int err;
-
-	/* Service RQ
-	 */
-
-	work_done = vnic_cq_service(&enic->cq[cq],
-		work_to_do, enic_rq_service, NULL);
-
-	/* Return intr event credits for this polling
-	 * cycle.  An intr event is the completion of a
-	 * RQ packet.
-	 */
-
-	if (work_done > 0)
-		vnic_intr_return_credits(&enic->intr[intr],
-			work_done,
-			0 /* don't unmask intr */,
-			0 /* don't reset intr timer */);
-
-	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.
-	 */
-
-	if (err)
-		work_done = work_to_do;
-
-	if (work_done < work_to_do) {
-
-		/* Some work done, but not enough to stay in polling,
-		 * exit polling
-		 */
-
-		napi_complete(napi);
-		vnic_intr_unmask(&enic->intr[intr]);
-	}
-
-	return work_done;
-}
-
-static void enic_notify_timer(unsigned long data)
-{
-	struct enic *enic = (struct enic *)data;
-
-	enic_notify_check(enic);
-
-	mod_timer(&enic->notify_timer,
-		round_jiffies(jiffies + ENIC_NOTIFY_TIMER_PERIOD));
-}
-
-static void enic_free_intr(struct enic *enic)
-{
-	struct net_device *netdev = enic->netdev;
-	unsigned int i;
-
-	switch (vnic_dev_get_intr_mode(enic->vdev)) {
-	case VNIC_DEV_INTR_MODE_INTX:
-		free_irq(enic->pdev->irq, netdev);
-		break;
-	case VNIC_DEV_INTR_MODE_MSI:
-		free_irq(enic->pdev->irq, enic);
-		break;
-	case VNIC_DEV_INTR_MODE_MSIX:
-		for (i = 0; i < ARRAY_SIZE(enic->msix); i++)
-			if (enic->msix[i].requested)
-				free_irq(enic->msix_entry[i].vector,
-					enic->msix[i].devid);
-		break;
-	default:
-		break;
-	}
-}
-
-static int enic_request_intr(struct enic *enic)
-{
-	struct net_device *netdev = enic->netdev;
-	unsigned int i, intr;
-	int err = 0;
-
-	switch (vnic_dev_get_intr_mode(enic->vdev)) {
-
-	case VNIC_DEV_INTR_MODE_INTX:
-
-		err = request_irq(enic->pdev->irq, enic_isr_legacy,
-			IRQF_SHARED, netdev->name, netdev);
-		break;
-
-	case VNIC_DEV_INTR_MODE_MSI:
-
-		err = request_irq(enic->pdev->irq, enic_isr_msi,
-			0, netdev->name, enic);
-		break;
-
-	case VNIC_DEV_INTR_MODE_MSIX:
-
-		for (i = 0; i < enic->rq_count; i++) {
-			intr = enic_msix_rq_intr(enic, i);
-			sprintf(enic->msix[intr].devname,
-				"%.11s-rx-%d", netdev->name, i);
-			enic->msix[intr].isr = enic_isr_msix_rq;
-			enic->msix[intr].devid = &enic->napi[i];
-		}
-
-		for (i = 0; i < enic->wq_count; i++) {
-			intr = enic_msix_wq_intr(enic, i);
-			sprintf(enic->msix[intr].devname,
-				"%.11s-tx-%d", netdev->name, i);
-			enic->msix[intr].isr = enic_isr_msix_wq;
-			enic->msix[intr].devid = enic;
-		}
-
-		intr = enic_msix_err_intr(enic);
-		sprintf(enic->msix[intr].devname,
-			"%.11s-err", netdev->name);
-		enic->msix[intr].isr = enic_isr_msix_err;
-		enic->msix[intr].devid = enic;
-
-		intr = enic_msix_notify_intr(enic);
-		sprintf(enic->msix[intr].devname,
-			"%.11s-notify", netdev->name);
-		enic->msix[intr].isr = enic_isr_msix_notify;
-		enic->msix[intr].devid = enic;
-
-		for (i = 0; i < ARRAY_SIZE(enic->msix); i++)
-			enic->msix[i].requested = 0;
-
-		for (i = 0; i < enic->intr_count; i++) {
-			err = request_irq(enic->msix_entry[i].vector,
-				enic->msix[i].isr, 0,
-				enic->msix[i].devname,
-				enic->msix[i].devid);
-			if (err) {
-				enic_free_intr(enic);
-				break;
-			}
-			enic->msix[i].requested = 1;
-		}
-
-		break;
-
-	default:
-		break;
-	}
-
-	return err;
-}
-
-static void enic_synchronize_irqs(struct enic *enic)
-{
-	unsigned int i;
-
-	switch (vnic_dev_get_intr_mode(enic->vdev)) {
-	case VNIC_DEV_INTR_MODE_INTX:
-	case VNIC_DEV_INTR_MODE_MSI:
-		synchronize_irq(enic->pdev->irq);
-		break;
-	case VNIC_DEV_INTR_MODE_MSIX:
-		for (i = 0; i < enic->intr_count; i++)
-			synchronize_irq(enic->msix_entry[i].vector);
-		break;
-	default:
-		break;
-	}
-}
-
-static int enic_dev_notify_set(struct enic *enic)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	switch (vnic_dev_get_intr_mode(enic->vdev)) {
-	case VNIC_DEV_INTR_MODE_INTX:
-		err = vnic_dev_notify_set(enic->vdev,
-			enic_legacy_notify_intr());
-		break;
-	case VNIC_DEV_INTR_MODE_MSIX:
-		err = vnic_dev_notify_set(enic->vdev,
-			enic_msix_notify_intr(enic));
-		break;
-	default:
-		err = vnic_dev_notify_set(enic->vdev, -1 /* no intr */);
-		break;
-	}
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static void enic_notify_timer_start(struct enic *enic)
-{
-	switch (vnic_dev_get_intr_mode(enic->vdev)) {
-	case VNIC_DEV_INTR_MODE_MSI:
-		mod_timer(&enic->notify_timer, jiffies);
-		break;
-	default:
-		/* Using intr for notification for INTx/MSI-X */
-		break;
-	}
-}
-
-/* rtnl lock is held, process context */
-static int enic_open(struct net_device *netdev)
-{
-	struct enic *enic = netdev_priv(netdev);
-	unsigned int i;
-	int err;
-
-	err = enic_request_intr(enic);
-	if (err) {
-		netdev_err(netdev, "Unable to request irq.\n");
-		return err;
-	}
-
-	err = enic_dev_notify_set(enic);
-	if (err) {
-		netdev_err(netdev,
-			"Failed to alloc notify buffer, aborting.\n");
-		goto err_out_free_intr;
-	}
-
-	for (i = 0; i < enic->rq_count; i++) {
-		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");
-			err = -ENOMEM;
-			goto err_out_notify_unset;
-		}
-	}
-
-	for (i = 0; i < enic->wq_count; i++)
-		vnic_wq_enable(&enic->wq[i]);
-	for (i = 0; i < enic->rq_count; i++)
-		vnic_rq_enable(&enic->rq[i]);
-
-	if (enic_is_dynamic(enic) && !is_zero_ether_addr(enic->pp.mac_addr))
-		enic_dev_add_addr(enic, enic->pp.mac_addr);
-	else
-		enic_dev_add_station_addr(enic);
-	enic_set_rx_mode(netdev);
-
-	netif_wake_queue(netdev);
-
-	for (i = 0; i < enic->rq_count; i++)
-		napi_enable(&enic->napi[i]);
-
-	enic_dev_enable(enic);
-
-	for (i = 0; i < enic->intr_count; i++)
-		vnic_intr_unmask(&enic->intr[i]);
-
-	enic_notify_timer_start(enic);
-
-	return 0;
-
-err_out_notify_unset:
-	enic_dev_notify_unset(enic);
-err_out_free_intr:
-	enic_free_intr(enic);
-
-	return err;
-}
-
-/* rtnl lock is held, process context */
-static int enic_stop(struct net_device *netdev)
-{
-	struct enic *enic = netdev_priv(netdev);
-	unsigned int i;
-	int err;
-
-	for (i = 0; i < enic->intr_count; i++) {
-		vnic_intr_mask(&enic->intr[i]);
-		(void)vnic_intr_masked(&enic->intr[i]); /* flush write */
-	}
-
-	enic_synchronize_irqs(enic);
-
-	del_timer_sync(&enic->notify_timer);
-
-	enic_dev_disable(enic);
-
-	for (i = 0; i < enic->rq_count; i++)
-		napi_disable(&enic->napi[i]);
-
-	netif_carrier_off(netdev);
-	netif_tx_disable(netdev);
-	if (enic_is_dynamic(enic) && !is_zero_ether_addr(enic->pp.mac_addr))
-		enic_dev_del_addr(enic, enic->pp.mac_addr);
-	else
-		enic_dev_del_station_addr(enic);
-
-	for (i = 0; i < enic->wq_count; i++) {
-		err = vnic_wq_disable(&enic->wq[i]);
-		if (err)
-			return err;
-	}
-	for (i = 0; i < enic->rq_count; i++) {
-		err = vnic_rq_disable(&enic->rq[i]);
-		if (err)
-			return err;
-	}
-
-	enic_dev_notify_unset(enic);
-	enic_free_intr(enic);
-
-	for (i = 0; i < enic->wq_count; i++)
-		vnic_wq_clean(&enic->wq[i], enic_free_wq_buf);
-	for (i = 0; i < enic->rq_count; i++)
-		vnic_rq_clean(&enic->rq[i], enic_free_rq_buf);
-	for (i = 0; i < enic->cq_count; i++)
-		vnic_cq_clean(&enic->cq[i]);
-	for (i = 0; i < enic->intr_count; i++)
-		vnic_intr_clean(&enic->intr[i]);
-
-	return 0;
-}
-
-static int enic_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	struct enic *enic = netdev_priv(netdev);
-	int running = netif_running(netdev);
-
-	if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU)
-		return -EINVAL;
-
-	if (enic_is_dynamic(enic))
-		return -EOPNOTSUPP;
-
-	if (running)
-		enic_stop(netdev);
-
-	netdev->mtu = new_mtu;
-
-	if (netdev->mtu > enic->port_mtu)
-		netdev_warn(netdev,
-			"interface MTU (%d) set higher than port MTU (%d)\n",
-			netdev->mtu, enic->port_mtu);
-
-	if (running)
-		enic_open(netdev);
-
-	return 0;
-}
-
-static void enic_change_mtu_work(struct work_struct *work)
-{
-	struct enic *enic = container_of(work, struct enic, change_mtu_work);
-	struct net_device *netdev = enic->netdev;
-	int new_mtu = vnic_dev_mtu(enic->vdev);
-	int err;
-	unsigned int i;
-
-	new_mtu = max_t(int, ENIC_MIN_MTU, min_t(int, ENIC_MAX_MTU, new_mtu));
-
-	rtnl_lock();
-
-	/* Stop RQ */
-	del_timer_sync(&enic->notify_timer);
-
-	for (i = 0; i < enic->rq_count; i++)
-		napi_disable(&enic->napi[i]);
-
-	vnic_intr_mask(&enic->intr[0]);
-	enic_synchronize_irqs(enic);
-	err = vnic_rq_disable(&enic->rq[0]);
-	if (err) {
-		netdev_err(netdev, "Unable to disable RQ.\n");
-		return;
-	}
-	vnic_rq_clean(&enic->rq[0], enic_free_rq_buf);
-	vnic_cq_clean(&enic->cq[0]);
-	vnic_intr_clean(&enic->intr[0]);
-
-	/* Fill RQ with new_mtu-sized buffers */
-	netdev->mtu = new_mtu;
-	vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
-	/* Need at least one buffer on ring to get going */
-	if (vnic_rq_desc_used(&enic->rq[0]) == 0) {
-		netdev_err(netdev, "Unable to alloc receive buffers.\n");
-		return;
-	}
-
-	/* Start RQ */
-	vnic_rq_enable(&enic->rq[0]);
-	napi_enable(&enic->napi[0]);
-	vnic_intr_unmask(&enic->intr[0]);
-	enic_notify_timer_start(enic);
-
-	rtnl_unlock();
-
-	netdev_info(netdev, "interface MTU set as %d\n", netdev->mtu);
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void enic_poll_controller(struct net_device *netdev)
-{
-	struct enic *enic = netdev_priv(netdev);
-	struct vnic_dev *vdev = enic->vdev;
-	unsigned int i, intr;
-
-	switch (vnic_dev_get_intr_mode(vdev)) {
-	case VNIC_DEV_INTR_MODE_MSIX:
-		for (i = 0; i < enic->rq_count; i++) {
-			intr = enic_msix_rq_intr(enic, i);
-			enic_isr_msix_rq(enic->msix_entry[intr].vector,
-				&enic->napi[i]);
-		}
-
-		for (i = 0; i < enic->wq_count; i++) {
-			intr = enic_msix_wq_intr(enic, i);
-			enic_isr_msix_wq(enic->msix_entry[intr].vector, enic);
-		}
-
-		break;
-	case VNIC_DEV_INTR_MODE_MSI:
-		enic_isr_msi(enic->pdev->irq, enic);
-		break;
-	case VNIC_DEV_INTR_MODE_INTX:
-		enic_isr_legacy(enic->pdev->irq, netdev);
-		break;
-	default:
-		break;
-	}
-}
-#endif
-
-static int enic_dev_wait(struct vnic_dev *vdev,
-	int (*start)(struct vnic_dev *, int),
-	int (*finished)(struct vnic_dev *, int *),
-	int arg)
-{
-	unsigned long time;
-	int done;
-	int err;
-
-	BUG_ON(in_interrupt());
-
-	err = start(vdev, arg);
-	if (err)
-		return err;
-
-	/* Wait for func to complete...2 seconds max
-	 */
-
-	time = jiffies + (HZ * 2);
-	do {
-
-		err = finished(vdev, &done);
-		if (err)
-			return err;
-
-		if (done)
-			return 0;
-
-		schedule_timeout_uninterruptible(HZ / 10);
-
-	} while (time_after(time, jiffies));
-
-	return -ETIMEDOUT;
-}
-
-static int enic_dev_open(struct enic *enic)
-{
-	int err;
-
-	err = enic_dev_wait(enic->vdev, vnic_dev_open,
-		vnic_dev_open_done, 0);
-	if (err)
-		dev_err(enic_get_dev(enic), "vNIC device open failed, err %d\n",
-			err);
-
-	return err;
-}
-
-static int enic_dev_hang_reset(struct enic *enic)
-{
-	int err;
-
-	err = enic_dev_wait(enic->vdev, vnic_dev_hang_reset,
-		vnic_dev_hang_reset_done, 0);
-	if (err)
-		netdev_err(enic->netdev, "vNIC hang reset failed, err %d\n",
-			err);
-
-	return err;
-}
-
-static int enic_set_rsskey(struct enic *enic)
-{
-	dma_addr_t rss_key_buf_pa;
-	union vnic_rss_key *rss_key_buf_va = NULL;
-	union vnic_rss_key rss_key = {
-		.key[0].b = {85, 67, 83, 97, 119, 101, 115, 111, 109, 101},
-		.key[1].b = {80, 65, 76, 79, 117, 110, 105, 113, 117, 101},
-		.key[2].b = {76, 73, 78, 85, 88, 114, 111, 99, 107, 115},
-		.key[3].b = {69, 78, 73, 67, 105, 115, 99, 111, 111, 108},
-	};
-	int err;
-
-	rss_key_buf_va = pci_alloc_consistent(enic->pdev,
-		sizeof(union vnic_rss_key), &rss_key_buf_pa);
-	if (!rss_key_buf_va)
-		return -ENOMEM;
-
-	memcpy(rss_key_buf_va, &rss_key, sizeof(union vnic_rss_key));
-
-	spin_lock(&enic->devcmd_lock);
-	err = enic_set_rss_key(enic,
-		rss_key_buf_pa,
-		sizeof(union vnic_rss_key));
-	spin_unlock(&enic->devcmd_lock);
-
-	pci_free_consistent(enic->pdev, sizeof(union vnic_rss_key),
-		rss_key_buf_va, rss_key_buf_pa);
-
-	return err;
-}
-
-static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits)
-{
-	dma_addr_t rss_cpu_buf_pa;
-	union vnic_rss_cpu *rss_cpu_buf_va = NULL;
-	unsigned int i;
-	int err;
-
-	rss_cpu_buf_va = pci_alloc_consistent(enic->pdev,
-		sizeof(union vnic_rss_cpu), &rss_cpu_buf_pa);
-	if (!rss_cpu_buf_va)
-		return -ENOMEM;
-
-	for (i = 0; i < (1 << rss_hash_bits); i++)
-		(*rss_cpu_buf_va).cpu[i/4].b[i%4] = i % enic->rq_count;
-
-	spin_lock(&enic->devcmd_lock);
-	err = enic_set_rss_cpu(enic,
-		rss_cpu_buf_pa,
-		sizeof(union vnic_rss_cpu));
-	spin_unlock(&enic->devcmd_lock);
-
-	pci_free_consistent(enic->pdev, sizeof(union vnic_rss_cpu),
-		rss_cpu_buf_va, rss_cpu_buf_pa);
-
-	return err;
-}
-
-static int enic_set_niccfg(struct enic *enic, u8 rss_default_cpu,
-	u8 rss_hash_type, u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable)
-{
-	const u8 tso_ipid_split_en = 0;
-	const u8 ig_vlan_strip_en = 1;
-	int err;
-
-	/* Enable VLAN tag stripping.
-	*/
-
-	spin_lock(&enic->devcmd_lock);
-	err = enic_set_nic_cfg(enic,
-		rss_default_cpu, rss_hash_type,
-		rss_hash_bits, rss_base_cpu,
-		rss_enable, tso_ipid_split_en,
-		ig_vlan_strip_en);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_set_rss_nic_cfg(struct enic *enic)
-{
-	struct device *dev = enic_get_dev(enic);
-	const u8 rss_default_cpu = 0;
-	const u8 rss_hash_type = NIC_CFG_RSS_HASH_TYPE_IPV4 |
-		NIC_CFG_RSS_HASH_TYPE_TCP_IPV4 |
-		NIC_CFG_RSS_HASH_TYPE_IPV6 |
-		NIC_CFG_RSS_HASH_TYPE_TCP_IPV6;
-	const u8 rss_hash_bits = 7;
-	const u8 rss_base_cpu = 0;
-	u8 rss_enable = ENIC_SETTING(enic, RSS) && (enic->rq_count > 1);
-
-	if (rss_enable) {
-		if (!enic_set_rsskey(enic)) {
-			if (enic_set_rsscpu(enic, rss_hash_bits)) {
-				rss_enable = 0;
-				dev_warn(dev, "RSS disabled, "
-					"Failed to set RSS cpu indirection table.");
-			}
-		} else {
-			rss_enable = 0;
-			dev_warn(dev, "RSS disabled, Failed to set RSS key.\n");
-		}
-	}
-
-	return enic_set_niccfg(enic, rss_default_cpu, rss_hash_type,
-		rss_hash_bits, rss_base_cpu, rss_enable);
-}
-
-static void enic_reset(struct work_struct *work)
-{
-	struct enic *enic = container_of(work, struct enic, reset);
-
-	if (!netif_running(enic->netdev))
-		return;
-
-	rtnl_lock();
-
-	enic_dev_hang_notify(enic);
-	enic_stop(enic->netdev);
-	enic_dev_hang_reset(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);
-	enic_open(enic->netdev);
-
-	rtnl_unlock();
-}
-
-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 = min_t(unsigned int, enic->wq_count, ENIC_WQ_MAX);
-	unsigned int i;
-
-	/* Set interrupt mode (INTx, MSI, MSI-X) depending
-	 * on system capabilities.
-	 *
-	 * Try MSI-X first
-	 *
-	 * We need n RQs, m WQs, n+m CQs, and n+m+2 INTRs
-	 * (the second to last INTR is used for WQ/RQ errors)
-	 * (the last INTR is used for notifications)
-	 */
-
-	BUG_ON(ARRAY_SIZE(enic->msix_entry) < n + m + 2);
-	for (i = 0; i < n + m + 2; i++)
-		enic->msix_entry[i].entry = i;
-
-	/* Use multiple RQs if RSS is enabled
-	 */
-
-	if (ENIC_SETTING(enic, RSS) &&
-	    enic->config.intr_mode < 1 &&
-	    enic->rq_count >= n &&
-	    enic->wq_count >= m &&
-	    enic->cq_count >= n + m &&
-	    enic->intr_count >= n + m + 2) {
-
-		if (!pci_enable_msix(enic->pdev, enic->msix_entry, n + m + 2)) {
-
-			enic->rq_count = n;
-			enic->wq_count = m;
-			enic->cq_count = n + m;
-			enic->intr_count = n + m + 2;
-
-			vnic_dev_set_intr_mode(enic->vdev,
-				VNIC_DEV_INTR_MODE_MSIX);
-
-			return 0;
-		}
-	}
-
-	if (enic->config.intr_mode < 1 &&
-	    enic->rq_count >= 1 &&
-	    enic->wq_count >= m &&
-	    enic->cq_count >= 1 + m &&
-	    enic->intr_count >= 1 + m + 2) {
-		if (!pci_enable_msix(enic->pdev, enic->msix_entry, 1 + m + 2)) {
-
-			enic->rq_count = 1;
-			enic->wq_count = m;
-			enic->cq_count = 1 + m;
-			enic->intr_count = 1 + m + 2;
-
-			vnic_dev_set_intr_mode(enic->vdev,
-				VNIC_DEV_INTR_MODE_MSIX);
-
-			return 0;
-		}
-	}
-
-	/* Next try MSI
-	 *
-	 * We need 1 RQ, 1 WQ, 2 CQs, and 1 INTR
-	 */
-
-	if (enic->config.intr_mode < 2 &&
-	    enic->rq_count >= 1 &&
-	    enic->wq_count >= 1 &&
-	    enic->cq_count >= 2 &&
-	    enic->intr_count >= 1 &&
-	    !pci_enable_msi(enic->pdev)) {
-
-		enic->rq_count = 1;
-		enic->wq_count = 1;
-		enic->cq_count = 2;
-		enic->intr_count = 1;
-
-		vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_MSI);
-
-		return 0;
-	}
-
-	/* Next try INTx
-	 *
-	 * We need 1 RQ, 1 WQ, 2 CQs, and 3 INTRs
-	 * (the first INTR is used for WQ/RQ)
-	 * (the second INTR is used for WQ/RQ errors)
-	 * (the last INTR is used for notifications)
-	 */
-
-	if (enic->config.intr_mode < 3 &&
-	    enic->rq_count >= 1 &&
-	    enic->wq_count >= 1 &&
-	    enic->cq_count >= 2 &&
-	    enic->intr_count >= 3) {
-
-		enic->rq_count = 1;
-		enic->wq_count = 1;
-		enic->cq_count = 2;
-		enic->intr_count = 3;
-
-		vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_INTX);
-
-		return 0;
-	}
-
-	vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_UNKNOWN);
-
-	return -EINVAL;
-}
-
-static void enic_clear_intr_mode(struct enic *enic)
-{
-	switch (vnic_dev_get_intr_mode(enic->vdev)) {
-	case VNIC_DEV_INTR_MODE_MSIX:
-		pci_disable_msix(enic->pdev);
-		break;
-	case VNIC_DEV_INTR_MODE_MSI:
-		pci_disable_msi(enic->pdev);
-		break;
-	default:
-		break;
-	}
-
-	vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_UNKNOWN);
-}
-
-static const struct net_device_ops enic_netdev_dynamic_ops = {
-	.ndo_open		= enic_open,
-	.ndo_stop		= enic_stop,
-	.ndo_start_xmit		= enic_hard_start_xmit,
-	.ndo_get_stats64	= enic_get_stats,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_rx_mode	= enic_set_rx_mode,
-	.ndo_set_multicast_list	= enic_set_rx_mode,
-	.ndo_set_mac_address	= enic_set_mac_address_dynamic,
-	.ndo_change_mtu		= enic_change_mtu,
-	.ndo_vlan_rx_add_vid	= enic_vlan_rx_add_vid,
-	.ndo_vlan_rx_kill_vid	= enic_vlan_rx_kill_vid,
-	.ndo_tx_timeout		= enic_tx_timeout,
-	.ndo_set_vf_port	= enic_set_vf_port,
-	.ndo_get_vf_port	= enic_get_vf_port,
-	.ndo_set_vf_mac		= enic_set_vf_mac,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= enic_poll_controller,
-#endif
-};
-
-static const struct net_device_ops enic_netdev_ops = {
-	.ndo_open		= enic_open,
-	.ndo_stop		= enic_stop,
-	.ndo_start_xmit		= enic_hard_start_xmit,
-	.ndo_get_stats64	= enic_get_stats,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address	= enic_set_mac_address,
-	.ndo_set_rx_mode	= enic_set_rx_mode,
-	.ndo_set_multicast_list	= enic_set_rx_mode,
-	.ndo_change_mtu		= enic_change_mtu,
-	.ndo_vlan_rx_add_vid	= enic_vlan_rx_add_vid,
-	.ndo_vlan_rx_kill_vid	= enic_vlan_rx_kill_vid,
-	.ndo_tx_timeout		= enic_tx_timeout,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= enic_poll_controller,
-#endif
-};
-
-static void enic_dev_deinit(struct enic *enic)
-{
-	unsigned int i;
-
-	for (i = 0; i < enic->rq_count; i++)
-		netif_napi_del(&enic->napi[i]);
-
-	enic_free_vnic_resources(enic);
-	enic_clear_intr_mode(enic);
-}
-
-static int enic_dev_init(struct enic *enic)
-{
-	struct device *dev = enic_get_dev(enic);
-	struct net_device *netdev = enic->netdev;
-	unsigned int i;
-	int err;
-
-	/* Get interrupt coalesce timer info */
-	err = enic_dev_intr_coal_timer_info(enic);
-	if (err) {
-		dev_warn(dev, "Using default conversion factor for "
-			"interrupt coalesce timer\n");
-		vnic_dev_intr_coal_timer_info_default(enic->vdev);
-	}
-
-	/* Get vNIC configuration
-	 */
-
-	err = enic_get_vnic_config(enic);
-	if (err) {
-		dev_err(dev, "Get vNIC configuration failed, aborting\n");
-		return err;
-	}
-
-	/* Get available resource counts
-	 */
-
-	enic_get_res_counts(enic);
-
-	/* Set interrupt mode based on resource counts and system
-	 * capabilities
-	 */
-
-	err = enic_set_intr_mode(enic);
-	if (err) {
-		dev_err(dev, "Failed to set intr mode based on resource "
-			"counts and system capabilities, aborting\n");
-		return err;
-	}
-
-	/* Allocate and configure vNIC resources
-	 */
-
-	err = enic_alloc_vnic_resources(enic);
-	if (err) {
-		dev_err(dev, "Failed to alloc vNIC resources, aborting\n");
-		goto err_out_free_vnic_resources;
-	}
-
-	enic_init_vnic_resources(enic);
-
-	err = enic_set_rss_nic_cfg(enic);
-	if (err) {
-		dev_err(dev, "Failed to config nic, 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);
-		break;
-	case VNIC_DEV_INTR_MODE_MSIX:
-		for (i = 0; i < enic->rq_count; i++)
-			netif_napi_add(netdev, &enic->napi[i],
-				enic_poll_msix, 64);
-		break;
-	}
-
-	return 0;
-
-err_out_free_vnic_resources:
-	enic_clear_intr_mode(enic);
-	enic_free_vnic_resources(enic);
-
-	return err;
-}
-
-static void enic_iounmap(struct enic *enic)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(enic->bar); i++)
-		if (enic->bar[i].vaddr)
-			iounmap(enic->bar[i].vaddr);
-}
-
-static int __devinit enic_probe(struct pci_dev *pdev,
-	const struct pci_device_id *ent)
-{
-	struct device *dev = &pdev->dev;
-	struct net_device *netdev;
-	struct enic *enic;
-	int using_dac = 0;
-	unsigned int i;
-	int err;
-
-	/* Allocate net device structure and initialize.  Private
-	 * instance data is initialized to zero.
-	 */
-
-	netdev = alloc_etherdev(sizeof(struct enic));
-	if (!netdev) {
-		pr_err("Etherdev alloc failed, aborting\n");
-		return -ENOMEM;
-	}
-
-	pci_set_drvdata(pdev, netdev);
-
-	SET_NETDEV_DEV(netdev, &pdev->dev);
-
-	enic = netdev_priv(netdev);
-	enic->netdev = netdev;
-	enic->pdev = pdev;
-
-	/* Setup PCI resources
-	 */
-
-	err = pci_enable_device_mem(pdev);
-	if (err) {
-		dev_err(dev, "Cannot enable PCI device, aborting\n");
-		goto err_out_free_netdev;
-	}
-
-	err = pci_request_regions(pdev, DRV_NAME);
-	if (err) {
-		dev_err(dev, "Cannot request PCI regions, aborting\n");
-		goto err_out_disable_device;
-	}
-
-	pci_set_master(pdev);
-
-	/* Query PCI controller on system for DMA addressing
-	 * limitation for the device.  Try 40-bit first, and
-	 * fail to 32-bit.
-	 */
-
-	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(40));
-	if (err) {
-		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-		if (err) {
-			dev_err(dev, "No usable DMA configuration, aborting\n");
-			goto err_out_release_regions;
-		}
-		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-		if (err) {
-			dev_err(dev, "Unable to obtain %u-bit DMA "
-				"for consistent allocations, aborting\n", 32);
-			goto err_out_release_regions;
-		}
-	} else {
-		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40));
-		if (err) {
-			dev_err(dev, "Unable to obtain %u-bit DMA "
-				"for consistent allocations, aborting\n", 40);
-			goto err_out_release_regions;
-		}
-		using_dac = 1;
-	}
-
-	/* Map vNIC resources from BAR0-5
-	 */
-
-	for (i = 0; i < ARRAY_SIZE(enic->bar); i++) {
-		if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
-			continue;
-		enic->bar[i].len = pci_resource_len(pdev, i);
-		enic->bar[i].vaddr = pci_iomap(pdev, i, enic->bar[i].len);
-		if (!enic->bar[i].vaddr) {
-			dev_err(dev, "Cannot memory-map BAR %d, aborting\n", i);
-			err = -ENODEV;
-			goto err_out_iounmap;
-		}
-		enic->bar[i].bus_addr = pci_resource_start(pdev, i);
-	}
-
-	/* Register vNIC device
-	 */
-
-	enic->vdev = vnic_dev_register(NULL, enic, pdev, enic->bar,
-		ARRAY_SIZE(enic->bar));
-	if (!enic->vdev) {
-		dev_err(dev, "vNIC registration failed, aborting\n");
-		err = -ENODEV;
-		goto err_out_iounmap;
-	}
-
-	/* Issue device open to get device in known state
-	 */
-
-	err = enic_dev_open(enic);
-	if (err) {
-		dev_err(dev, "vNIC dev open failed, aborting\n");
-		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
-	 * to wait here for the vnic-to-switch link initialization
-	 * to complete; link UP notification is the indication that
-	 * the process is complete.
-	 */
-
-	netif_carrier_off(netdev);
-
-	/* Do not call dev_init for a dynamic vnic.
-	 * For a dynamic vnic, init_prov_info will be
-	 * called later by an upper layer.
-	 */
-
-	if (!enic_is_dynamic(enic)) {
-		err = vnic_dev_init(enic->vdev, 0);
-		if (err) {
-			dev_err(dev, "vNIC dev init failed, aborting\n");
-			goto err_out_dev_close;
-		}
-	}
-
-	err = enic_dev_init(enic);
-	if (err) {
-		dev_err(dev, "Device initialization failed, aborting\n");
-		goto err_out_dev_close;
-	}
-
-	/* Setup notification timer, HW reset task, and wq locks
-	 */
-
-	init_timer(&enic->notify_timer);
-	enic->notify_timer.function = enic_notify_timer;
-	enic->notify_timer.data = (unsigned long)enic;
-
-	INIT_WORK(&enic->reset, enic_reset);
-	INIT_WORK(&enic->change_mtu_work, enic_change_mtu_work);
-
-	for (i = 0; i < enic->wq_count; i++)
-		spin_lock_init(&enic->wq_lock[i]);
-
-	/* Register net device
-	 */
-
-	enic->port_mtu = enic->config.mtu;
-	(void)enic_change_mtu(netdev, enic->port_mtu);
-
-	err = enic_set_mac_addr(netdev, enic->mac_addr);
-	if (err) {
-		dev_err(dev, "Invalid MAC address, aborting\n");
-		goto err_out_dev_deinit;
-	}
-
-	enic->tx_coalesce_usecs = enic->config.intr_timer_usec;
-	enic->rx_coalesce_usecs = enic->tx_coalesce_usecs;
-
-	if (enic_is_dynamic(enic))
-		netdev->netdev_ops = &enic_netdev_dynamic_ops;
-	else
-		netdev->netdev_ops = &enic_netdev_ops;
-
-	netdev->watchdog_timeo = 2 * HZ;
-	netdev->ethtool_ops = &enic_ethtool_ops;
-
-	netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-	if (ENIC_SETTING(enic, LOOP)) {
-		netdev->features &= ~NETIF_F_HW_VLAN_TX;
-		enic->loop_enable = 1;
-		enic->loop_tag = enic->config.loop_tag;
-		dev_info(dev, "loopback tag=0x%04x\n", enic->loop_tag);
-	}
-	if (ENIC_SETTING(enic, TXCSUM))
-		netdev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM;
-	if (ENIC_SETTING(enic, TSO))
-		netdev->hw_features |= NETIF_F_TSO |
-			NETIF_F_TSO6 | NETIF_F_TSO_ECN;
-	if (ENIC_SETTING(enic, RXCSUM))
-		netdev->hw_features |= NETIF_F_RXCSUM;
-
-	netdev->features |= netdev->hw_features;
-
-	if (using_dac)
-		netdev->features |= NETIF_F_HIGHDMA;
-
-	err = register_netdev(netdev);
-	if (err) {
-		dev_err(dev, "Cannot register net device, aborting\n");
-		goto err_out_dev_deinit;
-	}
-
-	return 0;
-
-err_out_dev_deinit:
-	enic_dev_deinit(enic);
-err_out_dev_close:
-	vnic_dev_close(enic->vdev);
-err_out_vnic_unregister:
-	vnic_dev_unregister(enic->vdev);
-err_out_iounmap:
-	enic_iounmap(enic);
-err_out_release_regions:
-	pci_release_regions(pdev);
-err_out_disable_device:
-	pci_disable_device(pdev);
-err_out_free_netdev:
-	pci_set_drvdata(pdev, NULL);
-	free_netdev(netdev);
-
-	return err;
-}
-
-static void __devexit enic_remove(struct pci_dev *pdev)
-{
-	struct net_device *netdev = pci_get_drvdata(pdev);
-
-	if (netdev) {
-		struct enic *enic = netdev_priv(netdev);
-
-		cancel_work_sync(&enic->reset);
-		cancel_work_sync(&enic->change_mtu_work);
-		unregister_netdev(netdev);
-		enic_dev_deinit(enic);
-		vnic_dev_close(enic->vdev);
-		vnic_dev_unregister(enic->vdev);
-		enic_iounmap(enic);
-		pci_release_regions(pdev);
-		pci_disable_device(pdev);
-		pci_set_drvdata(pdev, NULL);
-		free_netdev(netdev);
-	}
-}
-
-static struct pci_driver enic_driver = {
-	.name = DRV_NAME,
-	.id_table = enic_id_table,
-	.probe = enic_probe,
-	.remove = __devexit_p(enic_remove),
-};
-
-static int __init enic_init_module(void)
-{
-	pr_info("%s, ver %s\n", DRV_DESCRIPTION, DRV_VERSION);
-
-	return pci_register_driver(&enic_driver);
-}
-
-static void __exit enic_cleanup_module(void)
-{
-	pci_unregister_driver(&enic_driver);
-}
-
-module_init(enic_init_module);
-module_exit(enic_cleanup_module);
diff -druN linux-libre-3.1-gnu/drivers/net/enic/enic_pp.c linux-libre-3.2-gnu/drivers/net/enic/enic_pp.c
--- linux-libre-3.1-gnu/drivers/net/enic/enic_pp.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/enic_pp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,264 +0,0 @@
-/*
- * 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/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/rtnetlink.h>
-#include <net/ip.h>
-
-#include "vnic_vic.h"
-#include "enic_res.h"
-#include "enic.h"
-#include "enic_dev.h"
-
-static int enic_set_port_profile(struct enic *enic)
-{
-	struct net_device *netdev = enic->netdev;
-	struct vic_provinfo *vp;
-	const u8 oui[3] = VIC_PROVINFO_CISCO_OUI;
-	const u16 os_type = htons(VIC_GENERIC_PROV_OS_TYPE_LINUX);
-	char uuid_str[38];
-	char client_mac_str[18];
-	u8 *client_mac;
-	int err;
-
-	if (!(enic->pp.set & ENIC_SET_NAME) || !strlen(enic->pp.name))
-		return -EINVAL;
-
-	vp = vic_provinfo_alloc(GFP_KERNEL, oui,
-		VIC_PROVINFO_GENERIC_TYPE);
-	if (!vp)
-		return -ENOMEM;
-
-	VIC_PROVINFO_ADD_TLV(vp,
-		VIC_GENERIC_PROV_TLV_PORT_PROFILE_NAME_STR,
-		strlen(enic->pp.name) + 1, enic->pp.name);
-
-	if (!is_zero_ether_addr(enic->pp.mac_addr))
-		client_mac = enic->pp.mac_addr;
-	else
-		client_mac = netdev->dev_addr;
-
-	VIC_PROVINFO_ADD_TLV(vp,
-		VIC_GENERIC_PROV_TLV_CLIENT_MAC_ADDR,
-		ETH_ALEN, client_mac);
-
-	snprintf(client_mac_str, sizeof(client_mac_str), "%pM", client_mac);
-	VIC_PROVINFO_ADD_TLV(vp,
-		VIC_GENERIC_PROV_TLV_CLUSTER_PORT_UUID_STR,
-		sizeof(client_mac_str), client_mac_str);
-
-	if (enic->pp.set & ENIC_SET_INSTANCE) {
-		sprintf(uuid_str, "%pUB", enic->pp.instance_uuid);
-		VIC_PROVINFO_ADD_TLV(vp,
-			VIC_GENERIC_PROV_TLV_CLIENT_UUID_STR,
-			sizeof(uuid_str), uuid_str);
-	}
-
-	if (enic->pp.set & ENIC_SET_HOST) {
-		sprintf(uuid_str, "%pUB", enic->pp.host_uuid);
-		VIC_PROVINFO_ADD_TLV(vp,
-			VIC_GENERIC_PROV_TLV_HOST_UUID_STR,
-			sizeof(uuid_str), uuid_str);
-	}
-
-	VIC_PROVINFO_ADD_TLV(vp,
-		VIC_GENERIC_PROV_TLV_OS_TYPE,
-		sizeof(os_type), &os_type);
-
-	err = enic_dev_status_to_errno(enic_dev_init_prov2(enic, vp));
-
-add_tlv_failure:
-	vic_provinfo_free(vp);
-
-	return err;
-}
-
-static int enic_unset_port_profile(struct enic *enic)
-{
-	int err;
-
-	err = enic_vnic_dev_deinit(enic);
-	if (err)
-		return enic_dev_status_to_errno(err);
-
-	enic_reset_addr_lists(enic);
-
-	return 0;
-}
-
-static int enic_are_pp_different(struct enic_port_profile *pp1,
-		struct enic_port_profile *pp2)
-{
-	return strcmp(pp1->name, pp2->name) | !!memcmp(pp1->instance_uuid,
-		pp2->instance_uuid, PORT_UUID_MAX) |
-		!!memcmp(pp1->host_uuid, pp2->host_uuid, PORT_UUID_MAX) |
-		!!memcmp(pp1->mac_addr, pp2->mac_addr, ETH_ALEN);
-}
-
-static int enic_pp_preassociate(struct enic *enic,
-	struct enic_port_profile *prev_pp, int *restore_pp);
-static int enic_pp_disassociate(struct enic *enic,
-	struct enic_port_profile *prev_pp, int *restore_pp);
-static int enic_pp_preassociate_rr(struct enic *enic,
-	struct enic_port_profile *prev_pp, int *restore_pp);
-static int enic_pp_associate(struct enic *enic,
-	struct enic_port_profile *prev_pp, int *restore_pp);
-
-static int (*enic_pp_handlers[])(struct enic *enic,
-		struct enic_port_profile *prev_state, int *restore_pp) = {
-	[PORT_REQUEST_PREASSOCIATE]	= enic_pp_preassociate,
-	[PORT_REQUEST_PREASSOCIATE_RR]	= enic_pp_preassociate_rr,
-	[PORT_REQUEST_ASSOCIATE]	= enic_pp_associate,
-	[PORT_REQUEST_DISASSOCIATE]	= enic_pp_disassociate,
-};
-
-static const int enic_pp_handlers_count =
-			sizeof(enic_pp_handlers)/sizeof(*enic_pp_handlers);
-
-static int enic_pp_preassociate(struct enic *enic,
-	struct enic_port_profile *prev_pp, int *restore_pp)
-{
-	return -EOPNOTSUPP;
-}
-
-static int enic_pp_disassociate(struct enic *enic,
-	struct enic_port_profile *prev_pp, int *restore_pp)
-{
-	return enic_unset_port_profile(enic);
-}
-
-static int enic_pp_preassociate_rr(struct enic *enic,
-	struct enic_port_profile *prev_pp, int *restore_pp)
-{
-	int err;
-	int active = 0;
-
-	if (enic->pp.request != PORT_REQUEST_ASSOCIATE) {
-		/* If pre-associate is not part of an associate.
-		We always disassociate first */
-		err = enic_pp_handlers[PORT_REQUEST_DISASSOCIATE](enic,
-			prev_pp, restore_pp);
-		if (err)
-			return err;
-
-		*restore_pp = 0;
-	}
-
-	*restore_pp = 0;
-
-	err = enic_set_port_profile(enic);
-	if (err)
-		return err;
-
-	/* If pre-associate is not part of an associate. */
-	if (enic->pp.request != PORT_REQUEST_ASSOCIATE)
-		err = enic_dev_status_to_errno(enic_dev_enable2(enic, active));
-
-	return err;
-}
-
-static int enic_pp_associate(struct enic *enic,
-	struct enic_port_profile *prev_pp, int *restore_pp)
-{
-	int err;
-	int active = 1;
-
-	/* Check if a pre-associate was called before */
-	if (prev_pp->request != PORT_REQUEST_PREASSOCIATE_RR ||
-		(prev_pp->request == PORT_REQUEST_PREASSOCIATE_RR &&
-			enic_are_pp_different(prev_pp, &enic->pp))) {
-		err = enic_pp_handlers[PORT_REQUEST_DISASSOCIATE](
-			enic, prev_pp, restore_pp);
-		if (err)
-			return err;
-
-		*restore_pp = 0;
-	}
-
-	err = enic_pp_handlers[PORT_REQUEST_PREASSOCIATE_RR](
-			enic, prev_pp, restore_pp);
-	if (err)
-		return err;
-
-	*restore_pp = 0;
-
-	return enic_dev_status_to_errno(enic_dev_enable2(enic, active));
-}
-
-int enic_process_set_pp_request(struct enic *enic,
-	struct enic_port_profile *prev_pp, int *restore_pp)
-{
-	if (enic->pp.request < enic_pp_handlers_count
-		&& enic_pp_handlers[enic->pp.request])
-		return enic_pp_handlers[enic->pp.request](enic,
-			prev_pp, restore_pp);
-	else
-		return -EOPNOTSUPP;
-}
-
-int enic_process_get_pp_request(struct enic *enic, int request,
-	u16 *response)
-{
-	int err, status = ERR_SUCCESS;
-
-	switch (request) {
-
-	case PORT_REQUEST_PREASSOCIATE_RR:
-	case PORT_REQUEST_ASSOCIATE:
-		err = enic_dev_enable2_done(enic, &status);
-		break;
-
-	case PORT_REQUEST_DISASSOCIATE:
-		err = enic_dev_deinit_done(enic, &status);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	if (err)
-		status = err;
-
-	switch (status) {
-	case ERR_SUCCESS:
-		*response = PORT_PROFILE_RESPONSE_SUCCESS;
-		break;
-	case ERR_EINVAL:
-		*response = PORT_PROFILE_RESPONSE_INVALID;
-		break;
-	case ERR_EBADSTATE:
-		*response = PORT_PROFILE_RESPONSE_BADSTATE;
-		break;
-	case ERR_ENOMEM:
-		*response = PORT_PROFILE_RESPONSE_INSUFFICIENT_RESOURCES;
-		break;
-	case ERR_EINPROGRESS:
-		*response = PORT_PROFILE_RESPONSE_INPROGRESS;
-		break;
-	default:
-		*response = PORT_PROFILE_RESPONSE_ERROR;
-		break;
-	}
-
-	return 0;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/enic/enic_pp.h linux-libre-3.2-gnu/drivers/net/enic/enic_pp.h
--- linux-libre-3.1-gnu/drivers/net/enic/enic_pp.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/enic_pp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-/*
- * 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_PP_H_
-#define _ENIC_PP_H_
-
-int enic_process_set_pp_request(struct enic *enic,
-	struct enic_port_profile *prev_pp, int *restore_pp);
-int enic_process_get_pp_request(struct enic *enic, int request,
-	u16 *response);
-
-#endif /* _ENIC_PP_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/enic_res.c linux-libre-3.2-gnu/drivers/net/enic/enic_res.c
--- linux-libre-3.1-gnu/drivers/net/enic/enic_res.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/enic_res.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,384 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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/kernel.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-
-#include "wq_enet_desc.h"
-#include "rq_enet_desc.h"
-#include "cq_enet_desc.h"
-#include "vnic_resource.h"
-#include "vnic_enet.h"
-#include "vnic_dev.h"
-#include "vnic_wq.h"
-#include "vnic_rq.h"
-#include "vnic_cq.h"
-#include "vnic_intr.h"
-#include "vnic_stats.h"
-#include "vnic_nic.h"
-#include "vnic_rss.h"
-#include "enic_res.h"
-#include "enic.h"
-
-int enic_get_vnic_config(struct enic *enic)
-{
-	struct vnic_enet_config *c = &enic->config;
-	int err;
-
-	err = vnic_dev_mac_addr(enic->vdev, enic->mac_addr);
-	if (err) {
-		dev_err(enic_get_dev(enic),
-			"Error getting MAC addr, %d\n", err);
-		return err;
-	}
-
-#define GET_CONFIG(m) \
-	do { \
-		err = vnic_dev_spec(enic->vdev, \
-			offsetof(struct vnic_enet_config, m), \
-			sizeof(c->m), &c->m); \
-		if (err) { \
-			dev_err(enic_get_dev(enic), \
-				"Error getting %s, %d\n", #m, err); \
-			return err; \
-		} \
-	} while (0)
-
-	GET_CONFIG(flags);
-	GET_CONFIG(wq_desc_count);
-	GET_CONFIG(rq_desc_count);
-	GET_CONFIG(mtu);
-	GET_CONFIG(intr_timer_type);
-	GET_CONFIG(intr_mode);
-	GET_CONFIG(intr_timer_usec);
-	GET_CONFIG(loop_tag);
-
-	c->wq_desc_count =
-		min_t(u32, ENIC_MAX_WQ_DESCS,
-		max_t(u32, ENIC_MIN_WQ_DESCS,
-		c->wq_desc_count));
-	c->wq_desc_count &= 0xffffffe0; /* must be aligned to groups of 32 */
-
-	c->rq_desc_count =
-		min_t(u32, ENIC_MAX_RQ_DESCS,
-		max_t(u32, ENIC_MIN_RQ_DESCS,
-		c->rq_desc_count));
-	c->rq_desc_count &= 0xffffffe0; /* must be aligned to groups of 32 */
-
-	if (c->mtu == 0)
-		c->mtu = 1500;
-	c->mtu = min_t(u16, ENIC_MAX_MTU,
-		max_t(u16, ENIC_MIN_MTU,
-		c->mtu));
-
-	c->intr_timer_usec = min_t(u32, c->intr_timer_usec,
-		vnic_dev_get_intr_coal_timer_max(enic->vdev));
-
-	dev_info(enic_get_dev(enic),
-		"vNIC MAC addr %pM wq/rq %d/%d mtu %d\n",
-		enic->mac_addr, c->wq_desc_count, c->rq_desc_count, c->mtu);
-
-	dev_info(enic_get_dev(enic), "vNIC csum tx/rx %s/%s "
-		"tso/lro %s/%s rss %s intr mode %s type %s timer %d usec "
-		"loopback tag 0x%04x\n",
-		ENIC_SETTING(enic, TXCSUM) ? "yes" : "no",
-		ENIC_SETTING(enic, RXCSUM) ? "yes" : "no",
-		ENIC_SETTING(enic, TSO) ? "yes" : "no",
-		ENIC_SETTING(enic, LRO) ? "yes" : "no",
-		ENIC_SETTING(enic, RSS) ? "yes" : "no",
-		c->intr_mode == VENET_INTR_MODE_INTX ? "INTx" :
-		c->intr_mode == VENET_INTR_MODE_MSI ? "MSI" :
-		c->intr_mode == VENET_INTR_MODE_ANY ? "any" :
-		"unknown",
-		c->intr_timer_type == VENET_INTR_TYPE_MIN ? "min" :
-		c->intr_timer_type == VENET_INTR_TYPE_IDLE ? "idle" :
-		"unknown",
-		c->intr_timer_usec,
-		c->loop_tag);
-
-	return 0;
-}
-
-int enic_add_vlan(struct enic *enic, u16 vlanid)
-{
-	u64 a0 = vlanid, a1 = 0;
-	int wait = 1000;
-	int err;
-
-	err = vnic_dev_cmd(enic->vdev, CMD_VLAN_ADD, &a0, &a1, wait);
-	if (err)
-		dev_err(enic_get_dev(enic), "Can't add vlan id, %d\n", err);
-
-	return err;
-}
-
-int enic_del_vlan(struct enic *enic, u16 vlanid)
-{
-	u64 a0 = vlanid, a1 = 0;
-	int wait = 1000;
-	int err;
-
-	err = vnic_dev_cmd(enic->vdev, CMD_VLAN_DEL, &a0, &a1, wait);
-	if (err)
-		dev_err(enic_get_dev(enic), "Can't delete vlan id, %d\n", err);
-
-	return err;
-}
-
-int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type,
-	u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en,
-	u8 ig_vlan_strip_en)
-{
-	u64 a0, a1;
-	u32 nic_cfg;
-	int wait = 1000;
-
-	vnic_set_nic_cfg(&nic_cfg, rss_default_cpu,
-		rss_hash_type, rss_hash_bits, rss_base_cpu,
-		rss_enable, tso_ipid_split_en, ig_vlan_strip_en);
-
-	a0 = nic_cfg;
-	a1 = 0;
-
-	return vnic_dev_cmd(enic->vdev, CMD_NIC_CFG, &a0, &a1, wait);
-}
-
-int enic_set_rss_key(struct enic *enic, dma_addr_t key_pa, u64 len)
-{
-	u64 a0 = (u64)key_pa, a1 = len;
-	int wait = 1000;
-
-	return vnic_dev_cmd(enic->vdev, CMD_RSS_KEY, &a0, &a1, wait);
-}
-
-int enic_set_rss_cpu(struct enic *enic, dma_addr_t cpu_pa, u64 len)
-{
-	u64 a0 = (u64)cpu_pa, a1 = len;
-	int wait = 1000;
-
-	return vnic_dev_cmd(enic->vdev, CMD_RSS_CPU, &a0, &a1, wait);
-}
-
-void enic_free_vnic_resources(struct enic *enic)
-{
-	unsigned int i;
-
-	for (i = 0; i < enic->wq_count; i++)
-		vnic_wq_free(&enic->wq[i]);
-	for (i = 0; i < enic->rq_count; i++)
-		vnic_rq_free(&enic->rq[i]);
-	for (i = 0; i < enic->cq_count; i++)
-		vnic_cq_free(&enic->cq[i]);
-	for (i = 0; i < enic->intr_count; i++)
-		vnic_intr_free(&enic->intr[i]);
-}
-
-void enic_get_res_counts(struct enic *enic)
-{
-	enic->wq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ);
-	enic->rq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ);
-	enic->cq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ);
-	enic->intr_count = vnic_dev_get_res_count(enic->vdev,
-		RES_TYPE_INTR_CTRL);
-
-	dev_info(enic_get_dev(enic),
-		"vNIC resources avail: wq %d rq %d cq %d intr %d\n",
-		enic->wq_count, enic->rq_count,
-		enic->cq_count, enic->intr_count);
-}
-
-void enic_init_vnic_resources(struct enic *enic)
-{
-	enum vnic_dev_intr_mode intr_mode;
-	unsigned int mask_on_assertion;
-	unsigned int interrupt_offset;
-	unsigned int error_interrupt_enable;
-	unsigned int error_interrupt_offset;
-	unsigned int cq_index;
-	unsigned int i;
-
-	intr_mode = vnic_dev_get_intr_mode(enic->vdev);
-
-	/* Init RQ/WQ resources.
-	 *
-	 * RQ[0 - n-1] point to CQ[0 - n-1]
-	 * WQ[0 - m-1] point to CQ[n - n+m-1]
-	 *
-	 * Error interrupt is not enabled for MSI.
-	 */
-
-	switch (intr_mode) {
-	case VNIC_DEV_INTR_MODE_INTX:
-	case VNIC_DEV_INTR_MODE_MSIX:
-		error_interrupt_enable = 1;
-		error_interrupt_offset = enic->intr_count - 2;
-		break;
-	default:
-		error_interrupt_enable = 0;
-		error_interrupt_offset = 0;
-		break;
-	}
-
-	for (i = 0; i < enic->rq_count; i++) {
-		cq_index = i;
-		vnic_rq_init(&enic->rq[i],
-			cq_index,
-			error_interrupt_enable,
-			error_interrupt_offset);
-	}
-
-	for (i = 0; i < enic->wq_count; i++) {
-		cq_index = enic->rq_count + i;
-		vnic_wq_init(&enic->wq[i],
-			cq_index,
-			error_interrupt_enable,
-			error_interrupt_offset);
-	}
-
-	/* Init CQ resources
-	 *
-	 * CQ[0 - n+m-1] point to INTR[0] for INTx, MSI
-	 * CQ[0 - n+m-1] point to INTR[0 - n+m-1] for MSI-X
-	 */
-
-	for (i = 0; i < enic->cq_count; i++) {
-
-		switch (intr_mode) {
-		case VNIC_DEV_INTR_MODE_MSIX:
-			interrupt_offset = i;
-			break;
-		default:
-			interrupt_offset = 0;
-			break;
-		}
-
-		vnic_cq_init(&enic->cq[i],
-			0 /* flow_control_enable */,
-			1 /* color_enable */,
-			0 /* cq_head */,
-			0 /* cq_tail */,
-			1 /* cq_tail_color */,
-			1 /* interrupt_enable */,
-			1 /* cq_entry_enable */,
-			0 /* cq_message_enable */,
-			interrupt_offset,
-			0 /* cq_message_addr */);
-	}
-
-	/* Init INTR resources
-	 *
-	 * mask_on_assertion is not used for INTx due to the level-
-	 * triggered nature of INTx
-	 */
-
-	switch (intr_mode) {
-	case VNIC_DEV_INTR_MODE_MSI:
-	case VNIC_DEV_INTR_MODE_MSIX:
-		mask_on_assertion = 1;
-		break;
-	default:
-		mask_on_assertion = 0;
-		break;
-	}
-
-	for (i = 0; i < enic->intr_count; i++) {
-		vnic_intr_init(&enic->intr[i],
-			enic->config.intr_timer_usec,
-			enic->config.intr_timer_type,
-			mask_on_assertion);
-	}
-}
-
-int enic_alloc_vnic_resources(struct enic *enic)
-{
-	enum vnic_dev_intr_mode intr_mode;
-	unsigned int i;
-	int err;
-
-	intr_mode = vnic_dev_get_intr_mode(enic->vdev);
-
-	dev_info(enic_get_dev(enic), "vNIC resources used:  "
-		"wq %d rq %d cq %d intr %d intr mode %s\n",
-		enic->wq_count, enic->rq_count,
-		enic->cq_count, enic->intr_count,
-		intr_mode == VNIC_DEV_INTR_MODE_INTX ? "legacy PCI INTx" :
-		intr_mode == VNIC_DEV_INTR_MODE_MSI ? "MSI" :
-		intr_mode == VNIC_DEV_INTR_MODE_MSIX ? "MSI-X" :
-		"unknown");
-
-	/* Allocate queue resources
-	 */
-
-	for (i = 0; i < enic->wq_count; i++) {
-		err = vnic_wq_alloc(enic->vdev, &enic->wq[i], i,
-			enic->config.wq_desc_count,
-			sizeof(struct wq_enet_desc));
-		if (err)
-			goto err_out_cleanup;
-	}
-
-	for (i = 0; i < enic->rq_count; i++) {
-		err = vnic_rq_alloc(enic->vdev, &enic->rq[i], i,
-			enic->config.rq_desc_count,
-			sizeof(struct rq_enet_desc));
-		if (err)
-			goto err_out_cleanup;
-	}
-
-	for (i = 0; i < enic->cq_count; i++) {
-		if (i < enic->rq_count)
-			err = vnic_cq_alloc(enic->vdev, &enic->cq[i], i,
-				enic->config.rq_desc_count,
-				sizeof(struct cq_enet_rq_desc));
-		else
-			err = vnic_cq_alloc(enic->vdev, &enic->cq[i], i,
-				enic->config.wq_desc_count,
-				sizeof(struct cq_enet_wq_desc));
-		if (err)
-			goto err_out_cleanup;
-	}
-
-	for (i = 0; i < enic->intr_count; i++) {
-		err = vnic_intr_alloc(enic->vdev, &enic->intr[i], i);
-		if (err)
-			goto err_out_cleanup;
-	}
-
-	/* Hook remaining resource
-	 */
-
-	enic->legacy_pba = vnic_dev_get_res(enic->vdev,
-		RES_TYPE_INTR_PBA_LEGACY, 0);
-	if (!enic->legacy_pba && intr_mode == VNIC_DEV_INTR_MODE_INTX) {
-		dev_err(enic_get_dev(enic),
-			"Failed to hook legacy pba resource\n");
-		err = -ENODEV;
-		goto err_out_cleanup;
-	}
-
-	return 0;
-
-err_out_cleanup:
-	enic_free_vnic_resources(enic);
-
-	return err;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/enic/enic_res.h linux-libre-3.2-gnu/drivers/net/enic/enic_res.h
--- linux-libre-3.1-gnu/drivers/net/enic/enic_res.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/enic_res.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,148 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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_RES_H_
-#define _ENIC_RES_H_
-
-#include "wq_enet_desc.h"
-#include "rq_enet_desc.h"
-#include "vnic_wq.h"
-#include "vnic_rq.h"
-
-#define ENIC_MIN_WQ_DESCS		64
-#define ENIC_MAX_WQ_DESCS		4096
-#define ENIC_MIN_RQ_DESCS		64
-#define ENIC_MAX_RQ_DESCS		4096
-
-#define ENIC_MIN_MTU			68
-#define ENIC_MAX_MTU			9000
-
-#define ENIC_MULTICAST_PERFECT_FILTERS	32
-#define ENIC_UNICAST_PERFECT_FILTERS	32
-
-#define ENIC_NON_TSO_MAX_DESC		16
-
-#define ENIC_SETTING(enic, f) ((enic->config.flags & VENETF_##f) ? 1 : 0)
-
-static inline void enic_queue_wq_desc_ex(struct vnic_wq *wq,
-	void *os_buf, dma_addr_t dma_addr, unsigned int len,
-	unsigned int mss_or_csum_offset, unsigned int hdr_len,
-	int vlan_tag_insert, unsigned int vlan_tag,
-	int offload_mode, int cq_entry, int sop, int eop, int loopback)
-{
-	struct wq_enet_desc *desc = vnic_wq_next_desc(wq);
-
-	wq_enet_desc_enc(desc,
-		(u64)dma_addr | VNIC_PADDR_TARGET,
-		(u16)len,
-		(u16)mss_or_csum_offset,
-		(u16)hdr_len, (u8)offload_mode,
-		(u8)eop, (u8)cq_entry,
-		0, /* fcoe_encap */
-		(u8)vlan_tag_insert,
-		(u16)vlan_tag,
-		(u8)loopback);
-
-	vnic_wq_post(wq, os_buf, dma_addr, len, sop, eop);
-}
-
-static inline void enic_queue_wq_desc_cont(struct vnic_wq *wq,
-	void *os_buf, dma_addr_t dma_addr, unsigned int len,
-	int eop, int loopback)
-{
-	enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len,
-		0, 0, 0, 0, 0,
-		eop, 0 /* !SOP */, eop, loopback);
-}
-
-static inline void enic_queue_wq_desc(struct vnic_wq *wq, void *os_buf,
-	dma_addr_t dma_addr, unsigned int len, int vlan_tag_insert,
-	unsigned int vlan_tag, int eop, int loopback)
-{
-	enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len,
-		0, 0, vlan_tag_insert, vlan_tag,
-		WQ_ENET_OFFLOAD_MODE_CSUM,
-		eop, 1 /* SOP */, eop, loopback);
-}
-
-static inline void enic_queue_wq_desc_csum(struct vnic_wq *wq,
-	void *os_buf, dma_addr_t dma_addr, unsigned int len,
-	int ip_csum, int tcpudp_csum, int vlan_tag_insert,
-	unsigned int vlan_tag, int eop, int loopback)
-{
-	enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len,
-		(ip_csum ? 1 : 0) + (tcpudp_csum ? 2 : 0),
-		0, vlan_tag_insert, vlan_tag,
-		WQ_ENET_OFFLOAD_MODE_CSUM,
-		eop, 1 /* SOP */, eop, loopback);
-}
-
-static inline void enic_queue_wq_desc_csum_l4(struct vnic_wq *wq,
-	void *os_buf, dma_addr_t dma_addr, unsigned int len,
-	unsigned int csum_offset, unsigned int hdr_len,
-	int vlan_tag_insert, unsigned int vlan_tag, int eop, int loopback)
-{
-	enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len,
-		csum_offset, hdr_len, vlan_tag_insert, vlan_tag,
-		WQ_ENET_OFFLOAD_MODE_CSUM_L4,
-		eop, 1 /* SOP */, eop, loopback);
-}
-
-static inline void enic_queue_wq_desc_tso(struct vnic_wq *wq,
-	void *os_buf, dma_addr_t dma_addr, unsigned int len,
-	unsigned int mss, unsigned int hdr_len, int vlan_tag_insert,
-	unsigned int vlan_tag, int eop, int loopback)
-{
-	enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len,
-		mss, hdr_len, vlan_tag_insert, vlan_tag,
-		WQ_ENET_OFFLOAD_MODE_TSO,
-		eop, 1 /* SOP */, eop, loopback);
-}
-
-static inline void enic_queue_rq_desc(struct vnic_rq *rq,
-	void *os_buf, unsigned int os_buf_index,
-	dma_addr_t dma_addr, unsigned int len)
-{
-	struct rq_enet_desc *desc = vnic_rq_next_desc(rq);
-	u8 type = os_buf_index ?
-		RQ_ENET_TYPE_NOT_SOP : RQ_ENET_TYPE_ONLY_SOP;
-
-	rq_enet_desc_enc(desc,
-		(u64)dma_addr | VNIC_PADDR_TARGET,
-		type, (u16)len);
-
-	vnic_rq_post(rq, os_buf, os_buf_index, dma_addr, len);
-}
-
-struct enic;
-
-int enic_get_vnic_config(struct enic *);
-int enic_add_vlan(struct enic *enic, u16 vlanid);
-int enic_del_vlan(struct enic *enic, u16 vlanid);
-int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type,
-	u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en,
-	u8 ig_vlan_strip_en);
-int enic_set_rss_key(struct enic *enic, dma_addr_t key_pa, u64 len);
-int enic_set_rss_cpu(struct enic *enic, dma_addr_t cpu_pa, u64 len);
-void enic_get_res_counts(struct enic *enic);
-void enic_init_vnic_resources(struct enic *enic);
-int enic_alloc_vnic_resources(struct enic *);
-void enic_free_vnic_resources(struct enic *);
-
-#endif /* _ENIC_RES_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/Makefile linux-libre-3.2-gnu/drivers/net/enic/Makefile
--- linux-libre-3.1-gnu/drivers/net/enic/Makefile	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-obj-$(CONFIG_ENIC) := enic.o
-
-enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \
-	enic_res.o enic_dev.o enic_pp.o vnic_dev.o vnic_rq.o vnic_vic.o
-
diff -druN linux-libre-3.1-gnu/drivers/net/enic/rq_enet_desc.h linux-libre-3.2-gnu/drivers/net/enic/rq_enet_desc.h
--- linux-libre-3.1-gnu/drivers/net/enic/rq_enet_desc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/rq_enet_desc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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 _RQ_ENET_DESC_H_
-#define _RQ_ENET_DESC_H_
-
-/* Ethernet receive queue descriptor: 16B */
-struct rq_enet_desc {
-	__le64 address;
-	__le16 length_type;
-	u8 reserved[6];
-};
-
-enum rq_enet_type_types {
-	RQ_ENET_TYPE_ONLY_SOP = 0,
-	RQ_ENET_TYPE_NOT_SOP = 1,
-	RQ_ENET_TYPE_RESV2 = 2,
-	RQ_ENET_TYPE_RESV3 = 3,
-};
-
-#define RQ_ENET_ADDR_BITS		64
-#define RQ_ENET_LEN_BITS		14
-#define RQ_ENET_LEN_MASK		((1 << RQ_ENET_LEN_BITS) - 1)
-#define RQ_ENET_TYPE_BITS		2
-#define RQ_ENET_TYPE_MASK		((1 << RQ_ENET_TYPE_BITS) - 1)
-
-static inline void rq_enet_desc_enc(struct rq_enet_desc *desc,
-	u64 address, u8 type, u16 length)
-{
-	desc->address = cpu_to_le64(address);
-	desc->length_type = cpu_to_le16((length & RQ_ENET_LEN_MASK) |
-		((type & RQ_ENET_TYPE_MASK) << RQ_ENET_LEN_BITS));
-}
-
-static inline void rq_enet_desc_dec(struct rq_enet_desc *desc,
-	u64 *address, u8 *type, u16 *length)
-{
-	*address = le64_to_cpu(desc->address);
-	*length = le16_to_cpu(desc->length_type) & RQ_ENET_LEN_MASK;
-	*type = (u8)((le16_to_cpu(desc->length_type) >> RQ_ENET_LEN_BITS) &
-		RQ_ENET_TYPE_MASK);
-}
-
-#endif /* _RQ_ENET_DESC_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_cq.c linux-libre-3.2-gnu/drivers/net/enic/vnic_cq.c
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_cq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_cq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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/kernel.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-#include "vnic_dev.h"
-#include "vnic_cq.h"
-
-void vnic_cq_free(struct vnic_cq *cq)
-{
-	vnic_dev_free_desc_ring(cq->vdev, &cq->ring);
-
-	cq->ctrl = NULL;
-}
-
-int vnic_cq_alloc(struct vnic_dev *vdev, struct vnic_cq *cq, unsigned int index,
-	unsigned int desc_count, unsigned int desc_size)
-{
-	int err;
-
-	cq->index = index;
-	cq->vdev = vdev;
-
-	cq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_CQ, index);
-	if (!cq->ctrl) {
-		pr_err("Failed to hook CQ[%d] resource\n", index);
-		return -EINVAL;
-	}
-
-	err = vnic_dev_alloc_desc_ring(vdev, &cq->ring, desc_count, desc_size);
-	if (err)
-		return err;
-
-	return 0;
-}
-
-void vnic_cq_init(struct vnic_cq *cq, unsigned int flow_control_enable,
-	unsigned int color_enable, unsigned int cq_head, unsigned int cq_tail,
-	unsigned int cq_tail_color, unsigned int interrupt_enable,
-	unsigned int cq_entry_enable, unsigned int cq_message_enable,
-	unsigned int interrupt_offset, u64 cq_message_addr)
-{
-	u64 paddr;
-
-	paddr = (u64)cq->ring.base_addr | VNIC_PADDR_TARGET;
-	writeq(paddr, &cq->ctrl->ring_base);
-	iowrite32(cq->ring.desc_count, &cq->ctrl->ring_size);
-	iowrite32(flow_control_enable, &cq->ctrl->flow_control_enable);
-	iowrite32(color_enable, &cq->ctrl->color_enable);
-	iowrite32(cq_head, &cq->ctrl->cq_head);
-	iowrite32(cq_tail, &cq->ctrl->cq_tail);
-	iowrite32(cq_tail_color, &cq->ctrl->cq_tail_color);
-	iowrite32(interrupt_enable, &cq->ctrl->interrupt_enable);
-	iowrite32(cq_entry_enable, &cq->ctrl->cq_entry_enable);
-	iowrite32(cq_message_enable, &cq->ctrl->cq_message_enable);
-	iowrite32(interrupt_offset, &cq->ctrl->interrupt_offset);
-	writeq(cq_message_addr, &cq->ctrl->cq_message_addr);
-
-	cq->interrupt_offset = interrupt_offset;
-}
-
-void vnic_cq_clean(struct vnic_cq *cq)
-{
-	cq->to_clean = 0;
-	cq->last_color = 0;
-
-	iowrite32(0, &cq->ctrl->cq_head);
-	iowrite32(0, &cq->ctrl->cq_tail);
-	iowrite32(1, &cq->ctrl->cq_tail_color);
-
-	vnic_dev_clear_desc_ring(&cq->ring);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_cq.h linux-libre-3.2-gnu/drivers/net/enic/vnic_cq.h
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_cq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_cq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,114 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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 _VNIC_CQ_H_
-#define _VNIC_CQ_H_
-
-#include "cq_desc.h"
-#include "vnic_dev.h"
-
-/* Completion queue control */
-struct vnic_cq_ctrl {
-	u64 ring_base;			/* 0x00 */
-	u32 ring_size;			/* 0x08 */
-	u32 pad0;
-	u32 flow_control_enable;	/* 0x10 */
-	u32 pad1;
-	u32 color_enable;		/* 0x18 */
-	u32 pad2;
-	u32 cq_head;			/* 0x20 */
-	u32 pad3;
-	u32 cq_tail;			/* 0x28 */
-	u32 pad4;
-	u32 cq_tail_color;		/* 0x30 */
-	u32 pad5;
-	u32 interrupt_enable;		/* 0x38 */
-	u32 pad6;
-	u32 cq_entry_enable;		/* 0x40 */
-	u32 pad7;
-	u32 cq_message_enable;		/* 0x48 */
-	u32 pad8;
-	u32 interrupt_offset;		/* 0x50 */
-	u32 pad9;
-	u64 cq_message_addr;		/* 0x58 */
-	u32 pad10;
-};
-
-struct vnic_cq {
-	unsigned int index;
-	struct vnic_dev *vdev;
-	struct vnic_cq_ctrl __iomem *ctrl;              /* memory-mapped */
-	struct vnic_dev_ring ring;
-	unsigned int to_clean;
-	unsigned int last_color;
-	unsigned int interrupt_offset;
-};
-
-static inline unsigned int vnic_cq_service(struct vnic_cq *cq,
-	unsigned int work_to_do,
-	int (*q_service)(struct vnic_dev *vdev, struct cq_desc *cq_desc,
-	u8 type, u16 q_number, u16 completed_index, void *opaque),
-	void *opaque)
-{
-	struct cq_desc *cq_desc;
-	unsigned int work_done = 0;
-	u16 q_number, completed_index;
-	u8 type, color;
-
-	cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs +
-		cq->ring.desc_size * cq->to_clean);
-	cq_desc_dec(cq_desc, &type, &color,
-		&q_number, &completed_index);
-
-	while (color != cq->last_color) {
-
-		if ((*q_service)(cq->vdev, cq_desc, type,
-			q_number, completed_index, opaque))
-			break;
-
-		cq->to_clean++;
-		if (cq->to_clean == cq->ring.desc_count) {
-			cq->to_clean = 0;
-			cq->last_color = cq->last_color ? 0 : 1;
-		}
-
-		cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs +
-			cq->ring.desc_size * cq->to_clean);
-		cq_desc_dec(cq_desc, &type, &color,
-			&q_number, &completed_index);
-
-		work_done++;
-		if (work_done >= work_to_do)
-			break;
-	}
-
-	return work_done;
-}
-
-void vnic_cq_free(struct vnic_cq *cq);
-int vnic_cq_alloc(struct vnic_dev *vdev, struct vnic_cq *cq, unsigned int index,
-	unsigned int desc_count, unsigned int desc_size);
-void vnic_cq_init(struct vnic_cq *cq, unsigned int flow_control_enable,
-	unsigned int color_enable, unsigned int cq_head, unsigned int cq_tail,
-	unsigned int cq_tail_color, unsigned int interrupt_enable,
-	unsigned int cq_entry_enable, unsigned int message_enable,
-	unsigned int interrupt_offset, u64 message_addr);
-void vnic_cq_clean(struct vnic_cq *cq);
-
-#endif /* _VNIC_CQ_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_dev.c linux-libre-3.2-gnu/drivers/net/enic/vnic_dev.c
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_dev.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_dev.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1003 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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/kernel.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/if_ether.h>
-
-#include "vnic_resource.h"
-#include "vnic_devcmd.h"
-#include "vnic_dev.h"
-#include "vnic_stats.h"
-
-enum vnic_proxy_type {
-	PROXY_NONE,
-	PROXY_BY_BDF,
-};
-
-struct vnic_res {
-	void __iomem *vaddr;
-	dma_addr_t bus_addr;
-	unsigned int count;
-};
-
-struct vnic_intr_coal_timer_info {
-	u32 mul;
-	u32 div;
-	u32 max_usec;
-};
-
-struct vnic_dev {
-	void *priv;
-	struct pci_dev *pdev;
-	struct vnic_res res[RES_TYPE_MAX];
-	enum vnic_dev_intr_mode intr_mode;
-	struct vnic_devcmd __iomem *devcmd;
-	struct vnic_devcmd_notify *notify;
-	struct vnic_devcmd_notify notify_copy;
-	dma_addr_t notify_pa;
-	u32 notify_sz;
-	dma_addr_t linkstatus_pa;
-	struct vnic_stats *stats;
-	dma_addr_t stats_pa;
-	struct vnic_devcmd_fw_info *fw_info;
-	dma_addr_t fw_info_pa;
-	enum vnic_proxy_type proxy;
-	u32 proxy_index;
-	u64 args[VNIC_DEVCMD_NARGS];
-	struct vnic_intr_coal_timer_info intr_coal_timer_info;
-};
-
-#define VNIC_MAX_RES_HDR_SIZE \
-	(sizeof(struct vnic_resource_header) + \
-	sizeof(struct vnic_resource) * RES_TYPE_MAX)
-#define VNIC_RES_STRIDE	128
-
-void *vnic_dev_priv(struct vnic_dev *vdev)
-{
-	return vdev->priv;
-}
-
-static int vnic_dev_discover_res(struct vnic_dev *vdev,
-	struct vnic_dev_bar *bar, unsigned int num_bars)
-{
-	struct vnic_resource_header __iomem *rh;
-	struct mgmt_barmap_hdr __iomem *mrh;
-	struct vnic_resource __iomem *r;
-	u8 type;
-
-	if (num_bars == 0)
-		return -EINVAL;
-
-	if (bar->len < VNIC_MAX_RES_HDR_SIZE) {
-		pr_err("vNIC BAR0 res hdr length error\n");
-		return -EINVAL;
-	}
-
-	rh  = bar->vaddr;
-	mrh = bar->vaddr;
-	if (!rh) {
-		pr_err("vNIC BAR0 res hdr not mem-mapped\n");
-		return -EINVAL;
-	}
-
-	/* Check for mgmt vnic in addition to normal vnic */
-	if ((ioread32(&rh->magic) != VNIC_RES_MAGIC) ||
-		(ioread32(&rh->version) != VNIC_RES_VERSION)) {
-		if ((ioread32(&mrh->magic) != MGMTVNIC_MAGIC) ||
-			(ioread32(&mrh->version) != MGMTVNIC_VERSION)) {
-			pr_err("vNIC BAR0 res magic/version error "
-			"exp (%lx/%lx) or (%lx/%lx), curr (%x/%x)\n",
-			VNIC_RES_MAGIC, VNIC_RES_VERSION,
-			MGMTVNIC_MAGIC, MGMTVNIC_VERSION,
-			ioread32(&rh->magic), ioread32(&rh->version));
-			return -EINVAL;
-		}
-	}
-
-	if (ioread32(&mrh->magic) == MGMTVNIC_MAGIC)
-		r = (struct vnic_resource __iomem *)(mrh + 1);
-	else
-		r = (struct vnic_resource __iomem *)(rh + 1);
-
-
-	while ((type = ioread8(&r->type)) != RES_TYPE_EOL) {
-
-		u8 bar_num = ioread8(&r->bar);
-		u32 bar_offset = ioread32(&r->bar_offset);
-		u32 count = ioread32(&r->count);
-		u32 len;
-
-		r++;
-
-		if (bar_num >= num_bars)
-			continue;
-
-		if (!bar[bar_num].len || !bar[bar_num].vaddr)
-			continue;
-
-		switch (type) {
-		case RES_TYPE_WQ:
-		case RES_TYPE_RQ:
-		case RES_TYPE_CQ:
-		case RES_TYPE_INTR_CTRL:
-			/* each count is stride bytes long */
-			len = count * VNIC_RES_STRIDE;
-			if (len + bar_offset > bar[bar_num].len) {
-				pr_err("vNIC BAR0 resource %d "
-					"out-of-bounds, offset 0x%x + "
-					"size 0x%x > bar len 0x%lx\n",
-					type, bar_offset,
-					len,
-					bar[bar_num].len);
-				return -EINVAL;
-			}
-			break;
-		case RES_TYPE_INTR_PBA_LEGACY:
-		case RES_TYPE_DEVCMD:
-			len = count;
-			break;
-		default:
-			continue;
-		}
-
-		vdev->res[type].count = count;
-		vdev->res[type].vaddr = (char __iomem *)bar[bar_num].vaddr +
-			bar_offset;
-		vdev->res[type].bus_addr = bar[bar_num].bus_addr + bar_offset;
-	}
-
-	return 0;
-}
-
-unsigned int vnic_dev_get_res_count(struct vnic_dev *vdev,
-	enum vnic_res_type type)
-{
-	return vdev->res[type].count;
-}
-
-void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type,
-	unsigned int index)
-{
-	if (!vdev->res[type].vaddr)
-		return NULL;
-
-	switch (type) {
-	case RES_TYPE_WQ:
-	case RES_TYPE_RQ:
-	case RES_TYPE_CQ:
-	case RES_TYPE_INTR_CTRL:
-		return (char __iomem *)vdev->res[type].vaddr +
-			index * VNIC_RES_STRIDE;
-	default:
-		return (char __iomem *)vdev->res[type].vaddr;
-	}
-}
-
-static unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
-	unsigned int desc_count, unsigned int desc_size)
-{
-	/* The base address of the desc rings must be 512 byte aligned.
-	 * Descriptor count is aligned to groups of 32 descriptors.  A
-	 * count of 0 means the maximum 4096 descriptors.  Descriptor
-	 * size is aligned to 16 bytes.
-	 */
-
-	unsigned int count_align = 32;
-	unsigned int desc_align = 16;
-
-	ring->base_align = 512;
-
-	if (desc_count == 0)
-		desc_count = 4096;
-
-	ring->desc_count = ALIGN(desc_count, count_align);
-
-	ring->desc_size = ALIGN(desc_size, desc_align);
-
-	ring->size = ring->desc_count * ring->desc_size;
-	ring->size_unaligned = ring->size + ring->base_align;
-
-	return ring->size_unaligned;
-}
-
-void vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring)
-{
-	memset(ring->descs, 0, ring->size);
-}
-
-int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring,
-	unsigned int desc_count, unsigned int desc_size)
-{
-	vnic_dev_desc_ring_size(ring, desc_count, desc_size);
-
-	ring->descs_unaligned = pci_alloc_consistent(vdev->pdev,
-		ring->size_unaligned,
-		&ring->base_addr_unaligned);
-
-	if (!ring->descs_unaligned) {
-		pr_err("Failed to allocate ring (size=%d), aborting\n",
-			(int)ring->size);
-		return -ENOMEM;
-	}
-
-	ring->base_addr = ALIGN(ring->base_addr_unaligned,
-		ring->base_align);
-	ring->descs = (u8 *)ring->descs_unaligned +
-		(ring->base_addr - ring->base_addr_unaligned);
-
-	vnic_dev_clear_desc_ring(ring);
-
-	ring->desc_avail = ring->desc_count - 1;
-
-	return 0;
-}
-
-void vnic_dev_free_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring)
-{
-	if (ring->descs) {
-		pci_free_consistent(vdev->pdev,
-			ring->size_unaligned,
-			ring->descs_unaligned,
-			ring->base_addr_unaligned);
-		ring->descs = NULL;
-	}
-}
-
-static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
-	int wait)
-{
-	struct vnic_devcmd __iomem *devcmd = vdev->devcmd;
-	unsigned int i;
-	int delay;
-	u32 status;
-	int err;
-
-	status = ioread32(&devcmd->status);
-	if (status == 0xFFFFFFFF) {
-		/* PCI-e target device is gone */
-		return -ENODEV;
-	}
-	if (status & STAT_BUSY) {
-		pr_err("Busy devcmd %d\n", _CMD_N(cmd));
-		return -EBUSY;
-	}
-
-	if (_CMD_DIR(cmd) & _CMD_DIR_WRITE) {
-		for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
-			writeq(vdev->args[i], &devcmd->args[i]);
-		wmb();
-	}
-
-	iowrite32(cmd, &devcmd->cmd);
-
-	if ((_CMD_FLAGS(cmd) & _CMD_FLAGS_NOWAIT))
-		return 0;
-
-	for (delay = 0; delay < wait; delay++) {
-
-		udelay(100);
-
-		status = ioread32(&devcmd->status);
-		if (status == 0xFFFFFFFF) {
-			/* PCI-e target device is gone */
-			return -ENODEV;
-		}
-
-		if (!(status & STAT_BUSY)) {
-
-			if (status & STAT_ERROR) {
-				err = (int)readq(&devcmd->args[0]);
-				if (err != ERR_ECMDUNKNOWN ||
-				    cmd != CMD_CAPABILITY)
-					pr_err("Error %d devcmd %d\n",
-						err, _CMD_N(cmd));
-				return err;
-			}
-
-			if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
-				rmb();
-				for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
-					vdev->args[i] = readq(&devcmd->args[i]);
-			}
-
-			return 0;
-		}
-	}
-
-	pr_err("Timedout devcmd %d\n", _CMD_N(cmd));
-	return -ETIMEDOUT;
-}
-
-static int vnic_dev_cmd_proxy_by_bdf(struct vnic_dev *vdev,
-	enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait)
-{
-	u32 status;
-	int err;
-
-	memset(vdev->args, 0, sizeof(vdev->args));
-
-	vdev->args[0] = vdev->proxy_index; /* bdf */
-	vdev->args[1] = cmd;
-	vdev->args[2] = *a0;
-	vdev->args[3] = *a1;
-
-	err = _vnic_dev_cmd(vdev, CMD_PROXY_BY_BDF, wait);
-	if (err)
-		return err;
-
-	status = (u32)vdev->args[0];
-	if (status & STAT_ERROR) {
-		err = (int)vdev->args[1];
-		if (err != ERR_ECMDUNKNOWN ||
-		    cmd != CMD_CAPABILITY)
-			pr_err("Error %d proxy devcmd %d\n", err, _CMD_N(cmd));
-		return err;
-	}
-
-	*a0 = vdev->args[1];
-	*a1 = vdev->args[2];
-
-	return 0;
-}
-
-static int vnic_dev_cmd_no_proxy(struct vnic_dev *vdev,
-	enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait)
-{
-	int err;
-
-	vdev->args[0] = *a0;
-	vdev->args[1] = *a1;
-
-	err = _vnic_dev_cmd(vdev, cmd, wait);
-
-	*a0 = vdev->args[0];
-	*a1 = vdev->args[1];
-
-	return err;
-}
-
-int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
-	u64 *a0, u64 *a1, int wait)
-{
-	memset(vdev->args, 0, sizeof(vdev->args));
-
-	switch (vdev->proxy) {
-	case PROXY_BY_BDF:
-		return vnic_dev_cmd_proxy_by_bdf(vdev, cmd, a0, a1, wait);
-	case PROXY_NONE:
-	default:
-		return vnic_dev_cmd_no_proxy(vdev, cmd, a0, a1, wait);
-	}
-}
-
-static int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd)
-{
-	u64 a0 = (u32)cmd, a1 = 0;
-	int wait = 1000;
-	int err;
-
-	err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait);
-
-	return !(err || a0);
-}
-
-int vnic_dev_fw_info(struct vnic_dev *vdev,
-	struct vnic_devcmd_fw_info **fw_info)
-{
-	u64 a0, a1 = 0;
-	int wait = 1000;
-	int err = 0;
-
-	if (!vdev->fw_info) {
-		vdev->fw_info = pci_alloc_consistent(vdev->pdev,
-			sizeof(struct vnic_devcmd_fw_info),
-			&vdev->fw_info_pa);
-		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;
-
-	return err;
-}
-
-int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, unsigned int size,
-	void *value)
-{
-	u64 a0, a1;
-	int wait = 1000;
-	int err;
-
-	a0 = offset;
-	a1 = size;
-
-	err = vnic_dev_cmd(vdev, CMD_DEV_SPEC, &a0, &a1, wait);
-
-	switch (size) {
-	case 1: *(u8 *)value = (u8)a0; break;
-	case 2: *(u16 *)value = (u16)a0; break;
-	case 4: *(u32 *)value = (u32)a0; break;
-	case 8: *(u64 *)value = a0; break;
-	default: BUG(); break;
-	}
-
-	return err;
-}
-
-int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats)
-{
-	u64 a0, a1;
-	int wait = 1000;
-
-	if (!vdev->stats) {
-		vdev->stats = pci_alloc_consistent(vdev->pdev,
-			sizeof(struct vnic_stats), &vdev->stats_pa);
-		if (!vdev->stats)
-			return -ENOMEM;
-	}
-
-	*stats = vdev->stats;
-	a0 = vdev->stats_pa;
-	a1 = sizeof(struct vnic_stats);
-
-	return vnic_dev_cmd(vdev, CMD_STATS_DUMP, &a0, &a1, wait);
-}
-
-int vnic_dev_close(struct vnic_dev *vdev)
-{
-	u64 a0 = 0, a1 = 0;
-	int wait = 1000;
-	return vnic_dev_cmd(vdev, CMD_CLOSE, &a0, &a1, wait);
-}
-
-int vnic_dev_enable_wait(struct vnic_dev *vdev)
-{
-	u64 a0 = 0, a1 = 0;
-	int wait = 1000;
-	int err;
-
-	err = vnic_dev_cmd(vdev, CMD_ENABLE_WAIT, &a0, &a1, wait);
-	if (err == ERR_ECMDUNKNOWN)
-		return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait);
-
-	return err;
-}
-
-int vnic_dev_disable(struct vnic_dev *vdev)
-{
-	u64 a0 = 0, a1 = 0;
-	int wait = 1000;
-	return vnic_dev_cmd(vdev, CMD_DISABLE, &a0, &a1, wait);
-}
-
-int vnic_dev_open(struct vnic_dev *vdev, int arg)
-{
-	u64 a0 = (u32)arg, a1 = 0;
-	int wait = 1000;
-	return vnic_dev_cmd(vdev, CMD_OPEN, &a0, &a1, wait);
-}
-
-int vnic_dev_open_done(struct vnic_dev *vdev, int *done)
-{
-	u64 a0 = 0, a1 = 0;
-	int wait = 1000;
-	int err;
-
-	*done = 0;
-
-	err = vnic_dev_cmd(vdev, CMD_OPEN_STATUS, &a0, &a1, wait);
-	if (err)
-		return err;
-
-	*done = (a0 == 0);
-
-	return 0;
-}
-
-static int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg)
-{
-	u64 a0 = (u32)arg, a1 = 0;
-	int wait = 1000;
-	return vnic_dev_cmd(vdev, CMD_SOFT_RESET, &a0, &a1, wait);
-}
-
-static int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done)
-{
-	u64 a0 = 0, a1 = 0;
-	int wait = 1000;
-	int err;
-
-	*done = 0;
-
-	err = vnic_dev_cmd(vdev, CMD_SOFT_RESET_STATUS, &a0, &a1, wait);
-	if (err)
-		return err;
-
-	*done = (a0 == 0);
-
-	return 0;
-}
-
-int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg)
-{
-	u64 a0 = (u32)arg, a1 = 0;
-	int wait = 1000;
-	int err;
-
-	err = vnic_dev_cmd(vdev, CMD_HANG_RESET, &a0, &a1, wait);
-	if (err == ERR_ECMDUNKNOWN) {
-		err = vnic_dev_soft_reset(vdev, arg);
-		if (err)
-			return err;
-
-		return vnic_dev_init(vdev, 0);
-	}
-
-	return err;
-}
-
-int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done)
-{
-	u64 a0 = 0, a1 = 0;
-	int wait = 1000;
-	int err;
-
-	*done = 0;
-
-	err = vnic_dev_cmd(vdev, CMD_HANG_RESET_STATUS, &a0, &a1, wait);
-	if (err) {
-		if (err == ERR_ECMDUNKNOWN)
-			return vnic_dev_soft_reset_done(vdev, done);
-		return err;
-	}
-
-	*done = (a0 == 0);
-
-	return 0;
-}
-
-int vnic_dev_hang_notify(struct vnic_dev *vdev)
-{
-	u64 a0, a1;
-	int wait = 1000;
-	return vnic_dev_cmd(vdev, CMD_HANG_NOTIFY, &a0, &a1, wait);
-}
-
-int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr)
-{
-	u64 a0, a1;
-	int wait = 1000;
-	int err, i;
-
-	for (i = 0; i < ETH_ALEN; i++)
-		mac_addr[i] = 0;
-
-	err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait);
-	if (err)
-		return err;
-
-	for (i = 0; i < ETH_ALEN; i++)
-		mac_addr[i] = ((u8 *)&a0)[i];
-
-	return 0;
-}
-
-int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
-	int broadcast, int promisc, int allmulti)
-{
-	u64 a0, a1 = 0;
-	int wait = 1000;
-	int err;
-
-	a0 = (directed ? CMD_PFILTER_DIRECTED : 0) |
-	     (multicast ? CMD_PFILTER_MULTICAST : 0) |
-	     (broadcast ? CMD_PFILTER_BROADCAST : 0) |
-	     (promisc ? CMD_PFILTER_PROMISCUOUS : 0) |
-	     (allmulti ? CMD_PFILTER_ALL_MULTICAST : 0);
-
-	err = vnic_dev_cmd(vdev, CMD_PACKET_FILTER, &a0, &a1, wait);
-	if (err)
-		pr_err("Can't set packet filter\n");
-
-	return err;
-}
-
-int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
-{
-	u64 a0 = 0, a1 = 0;
-	int wait = 1000;
-	int err;
-	int i;
-
-	for (i = 0; i < ETH_ALEN; i++)
-		((u8 *)&a0)[i] = addr[i];
-
-	err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
-	if (err)
-		pr_err("Can't add addr [%pM], %d\n", addr, err);
-
-	return err;
-}
-
-int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
-{
-	u64 a0 = 0, a1 = 0;
-	int wait = 1000;
-	int err;
-	int i;
-
-	for (i = 0; i < ETH_ALEN; i++)
-		((u8 *)&a0)[i] = addr[i];
-
-	err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait);
-	if (err)
-		pr_err("Can't del addr [%pM], %d\n", addr, err);
-
-	return err;
-}
-
-int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev,
-	u8 ig_vlan_rewrite_mode)
-{
-	u64 a0 = ig_vlan_rewrite_mode, a1 = 0;
-	int wait = 1000;
-	int err;
-
-	err = vnic_dev_cmd(vdev, CMD_IG_VLAN_REWRITE_MODE, &a0, &a1, wait);
-	if (err == ERR_ECMDUNKNOWN)
-		return 0;
-
-	return err;
-}
-
-static int vnic_dev_notify_setcmd(struct vnic_dev *vdev,
-	void *notify_addr, dma_addr_t notify_pa, u16 intr)
-{
-	u64 a0, a1;
-	int wait = 1000;
-	int r;
-
-	memset(notify_addr, 0, sizeof(struct vnic_devcmd_notify));
-	vdev->notify = notify_addr;
-	vdev->notify_pa = notify_pa;
-
-	a0 = (u64)notify_pa;
-	a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL;
-	a1 += sizeof(struct vnic_devcmd_notify);
-
-	r = vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
-	vdev->notify_sz = (r == 0) ? (u32)a1 : 0;
-	return r;
-}
-
-int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr)
-{
-	void *notify_addr;
-	dma_addr_t notify_pa;
-
-	if (vdev->notify || vdev->notify_pa) {
-		pr_err("notify block %p still allocated", vdev->notify);
-		return -EINVAL;
-	}
-
-	notify_addr = pci_alloc_consistent(vdev->pdev,
-			sizeof(struct vnic_devcmd_notify),
-			&notify_pa);
-	if (!notify_addr)
-		return -ENOMEM;
-
-	return vnic_dev_notify_setcmd(vdev, notify_addr, notify_pa, intr);
-}
-
-static int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev)
-{
-	u64 a0, a1;
-	int wait = 1000;
-	int err;
-
-	a0 = 0;  /* paddr = 0 to unset notify buffer */
-	a1 = 0x0000ffff00000000ULL; /* intr num = -1 to unreg for intr */
-	a1 += sizeof(struct vnic_devcmd_notify);
-
-	err = vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
-	vdev->notify = NULL;
-	vdev->notify_pa = 0;
-	vdev->notify_sz = 0;
-
-	return err;
-}
-
-int vnic_dev_notify_unset(struct vnic_dev *vdev)
-{
-	if (vdev->notify) {
-		pci_free_consistent(vdev->pdev,
-			sizeof(struct vnic_devcmd_notify),
-			vdev->notify,
-			vdev->notify_pa);
-	}
-
-	return vnic_dev_notify_unsetcmd(vdev);
-}
-
-static int vnic_dev_notify_ready(struct vnic_dev *vdev)
-{
-	u32 *words;
-	unsigned int nwords = vdev->notify_sz / 4;
-	unsigned int i;
-	u32 csum;
-
-	if (!vdev->notify || !vdev->notify_sz)
-		return 0;
-
-	do {
-		csum = 0;
-		memcpy(&vdev->notify_copy, vdev->notify, vdev->notify_sz);
-		words = (u32 *)&vdev->notify_copy;
-		for (i = 1; i < nwords; i++)
-			csum += words[i];
-	} while (csum != words[0]);
-
-	return 1;
-}
-
-int vnic_dev_init(struct vnic_dev *vdev, int arg)
-{
-	u64 a0 = (u32)arg, a1 = 0;
-	int wait = 1000;
-	int r = 0;
-
-	if (vnic_dev_capable(vdev, CMD_INIT))
-		r = vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait);
-	else {
-		vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait);
-		if (a0 & CMD_INITF_DEFAULT_MAC) {
-			/* Emulate these for old CMD_INIT_v1 which
-			 * didn't pass a0 so no CMD_INITF_*.
-			 */
-			vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait);
-			vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
-		}
-	}
-	return r;
-}
-
-int vnic_dev_deinit(struct vnic_dev *vdev)
-{
-	u64 a0 = 0, a1 = 0;
-	int wait = 1000;
-
-	return vnic_dev_cmd(vdev, CMD_DEINIT, &a0, &a1, wait);
-}
-
-void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev)
-{
-	/* Default: hardware intr coal timer is in units of 1.5 usecs */
-	vdev->intr_coal_timer_info.mul = 2;
-	vdev->intr_coal_timer_info.div = 3;
-	vdev->intr_coal_timer_info.max_usec =
-		vnic_dev_intr_coal_timer_hw_to_usec(vdev, 0xffff);
-}
-
-int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev)
-{
-	int wait = 1000;
-	int err;
-
-	memset(vdev->args, 0, sizeof(vdev->args));
-
-	err = _vnic_dev_cmd(vdev, CMD_INTR_COAL_CONVERT, wait);
-
-	/* Use defaults when firmware doesn't support the devcmd at all or
-	 * supports it for only specific hardware
-	 */
-	if ((err == ERR_ECMDUNKNOWN) ||
-		(!err && !(vdev->args[0] && vdev->args[1] && vdev->args[2]))) {
-		pr_warning("Using default conversion factor for "
-			"interrupt coalesce timer\n");
-		vnic_dev_intr_coal_timer_info_default(vdev);
-		return 0;
-	}
-
-	vdev->intr_coal_timer_info.mul = (u32) vdev->args[0];
-	vdev->intr_coal_timer_info.div = (u32) vdev->args[1];
-	vdev->intr_coal_timer_info.max_usec = (u32) vdev->args[2];
-
-	return err;
-}
-
-int vnic_dev_link_status(struct vnic_dev *vdev)
-{
-	if (!vnic_dev_notify_ready(vdev))
-		return 0;
-
-	return vdev->notify_copy.link_state;
-}
-
-u32 vnic_dev_port_speed(struct vnic_dev *vdev)
-{
-	if (!vnic_dev_notify_ready(vdev))
-		return 0;
-
-	return vdev->notify_copy.port_speed;
-}
-
-u32 vnic_dev_msg_lvl(struct vnic_dev *vdev)
-{
-	if (!vnic_dev_notify_ready(vdev))
-		return 0;
-
-	return vdev->notify_copy.msglvl;
-}
-
-u32 vnic_dev_mtu(struct vnic_dev *vdev)
-{
-	if (!vnic_dev_notify_ready(vdev))
-		return 0;
-
-	return vdev->notify_copy.mtu;
-}
-
-void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
-	enum vnic_dev_intr_mode intr_mode)
-{
-	vdev->intr_mode = intr_mode;
-}
-
-enum vnic_dev_intr_mode vnic_dev_get_intr_mode(
-	struct vnic_dev *vdev)
-{
-	return vdev->intr_mode;
-}
-
-u32 vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev, u32 usec)
-{
-	return (usec * vdev->intr_coal_timer_info.mul) /
-		vdev->intr_coal_timer_info.div;
-}
-
-u32 vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev *vdev, u32 hw_cycles)
-{
-	return (hw_cycles * vdev->intr_coal_timer_info.div) /
-		vdev->intr_coal_timer_info.mul;
-}
-
-u32 vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev)
-{
-	return vdev->intr_coal_timer_info.max_usec;
-}
-
-void vnic_dev_unregister(struct vnic_dev *vdev)
-{
-	if (vdev) {
-		if (vdev->notify)
-			pci_free_consistent(vdev->pdev,
-				sizeof(struct vnic_devcmd_notify),
-				vdev->notify,
-				vdev->notify_pa);
-		if (vdev->stats)
-			pci_free_consistent(vdev->pdev,
-				sizeof(struct vnic_stats),
-				vdev->stats, vdev->stats_pa);
-		if (vdev->fw_info)
-			pci_free_consistent(vdev->pdev,
-				sizeof(struct vnic_devcmd_fw_info),
-				vdev->fw_info, vdev->fw_info_pa);
-		kfree(vdev);
-	}
-}
-
-struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
-	void *priv, struct pci_dev *pdev, struct vnic_dev_bar *bar,
-	unsigned int num_bars)
-{
-	if (!vdev) {
-		vdev = kzalloc(sizeof(struct vnic_dev), GFP_ATOMIC);
-		if (!vdev)
-			return NULL;
-	}
-
-	vdev->priv = priv;
-	vdev->pdev = pdev;
-
-	if (vnic_dev_discover_res(vdev, bar, num_bars))
-		goto err_out;
-
-	vdev->devcmd = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD, 0);
-	if (!vdev->devcmd)
-		goto err_out;
-
-	return vdev;
-
-err_out:
-	vnic_dev_unregister(vdev);
-	return NULL;
-}
-
-int vnic_dev_init_prov2(struct vnic_dev *vdev, u8 *buf, u32 len)
-{
-	u64 a0, a1 = len;
-	int wait = 1000;
-	dma_addr_t prov_pa;
-	void *prov_buf;
-	int ret;
-
-	prov_buf = pci_alloc_consistent(vdev->pdev, len, &prov_pa);
-	if (!prov_buf)
-		return -ENOMEM;
-
-	memcpy(prov_buf, buf, len);
-
-	a0 = prov_pa;
-
-	ret = vnic_dev_cmd(vdev, CMD_INIT_PROV_INFO2, &a0, &a1, wait);
-
-	pci_free_consistent(vdev->pdev, len, prov_buf, prov_pa);
-
-	return ret;
-}
-
-int vnic_dev_enable2(struct vnic_dev *vdev, int active)
-{
-	u64 a0, a1 = 0;
-	int wait = 1000;
-
-	a0 = (active ? CMD_ENABLE2_ACTIVE : 0);
-
-	return vnic_dev_cmd(vdev, CMD_ENABLE2, &a0, &a1, wait);
-}
-
-static int vnic_dev_cmd_status(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
-	int *status)
-{
-	u64 a0 = cmd, a1 = 0;
-	int wait = 1000;
-	int ret;
-
-	ret = vnic_dev_cmd(vdev, CMD_STATUS, &a0, &a1, wait);
-	if (!ret)
-		*status = (int)a0;
-
-	return ret;
-}
-
-int vnic_dev_enable2_done(struct vnic_dev *vdev, int *status)
-{
-	return vnic_dev_cmd_status(vdev, CMD_ENABLE2, status);
-}
-
-int vnic_dev_deinit_done(struct vnic_dev *vdev, int *status)
-{
-	return vnic_dev_cmd_status(vdev, CMD_DEINIT, status);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_devcmd.h linux-libre-3.2-gnu/drivers/net/enic/vnic_devcmd.h
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_devcmd.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_devcmd.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,450 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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 _VNIC_DEVCMD_H_
-#define _VNIC_DEVCMD_H_
-
-#define _CMD_NBITS      14
-#define _CMD_VTYPEBITS	10
-#define _CMD_FLAGSBITS  6
-#define _CMD_DIRBITS	2
-
-#define _CMD_NMASK      ((1 << _CMD_NBITS)-1)
-#define _CMD_VTYPEMASK  ((1 << _CMD_VTYPEBITS)-1)
-#define _CMD_FLAGSMASK  ((1 << _CMD_FLAGSBITS)-1)
-#define _CMD_DIRMASK    ((1 << _CMD_DIRBITS)-1)
-
-#define _CMD_NSHIFT     0
-#define _CMD_VTYPESHIFT (_CMD_NSHIFT+_CMD_NBITS)
-#define _CMD_FLAGSSHIFT (_CMD_VTYPESHIFT+_CMD_VTYPEBITS)
-#define _CMD_DIRSHIFT   (_CMD_FLAGSSHIFT+_CMD_FLAGSBITS)
-
-/*
- * Direction bits (from host perspective).
- */
-#define _CMD_DIR_NONE   0U
-#define _CMD_DIR_WRITE  1U
-#define _CMD_DIR_READ   2U
-#define _CMD_DIR_RW     (_CMD_DIR_WRITE | _CMD_DIR_READ)
-
-/*
- * Flag bits.
- */
-#define _CMD_FLAGS_NONE 0U
-#define _CMD_FLAGS_NOWAIT 1U
-
-/*
- * vNIC type bits.
- */
-#define _CMD_VTYPE_NONE  0U
-#define _CMD_VTYPE_ENET  1U
-#define _CMD_VTYPE_FC    2U
-#define _CMD_VTYPE_SCSI  4U
-#define _CMD_VTYPE_ALL   (_CMD_VTYPE_ENET | _CMD_VTYPE_FC | _CMD_VTYPE_SCSI)
-
-/*
- * Used to create cmds..
-*/
-#define _CMDCF(dir, flags, vtype, nr)  \
-	(((dir)   << _CMD_DIRSHIFT) | \
-	((flags) << _CMD_FLAGSSHIFT) | \
-	((vtype) << _CMD_VTYPESHIFT) | \
-	((nr)    << _CMD_NSHIFT))
-#define _CMDC(dir, vtype, nr)    _CMDCF(dir, 0, vtype, nr)
-#define _CMDCNW(dir, vtype, nr)  _CMDCF(dir, _CMD_FLAGS_NOWAIT, vtype, nr)
-
-/*
- * Used to decode cmds..
-*/
-#define _CMD_DIR(cmd)            (((cmd) >> _CMD_DIRSHIFT) & _CMD_DIRMASK)
-#define _CMD_FLAGS(cmd)          (((cmd) >> _CMD_FLAGSSHIFT) & _CMD_FLAGSMASK)
-#define _CMD_VTYPE(cmd)          (((cmd) >> _CMD_VTYPESHIFT) & _CMD_VTYPEMASK)
-#define _CMD_N(cmd)              (((cmd) >> _CMD_NSHIFT) & _CMD_NMASK)
-
-enum vnic_devcmd_cmd {
-	CMD_NONE                = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_NONE, 0),
-
-	/*
-	 * 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
-	 *    out: a0=value */
-	CMD_DEV_SPEC            = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 2),
-
-	/* stats clear */
-	CMD_STATS_CLEAR         = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 3),
-
-	/* stats dump in mem: (u64)a0=paddr to stats area,
-	 *                    (u16)a1=sizeof stats area */
-	CMD_STATS_DUMP          = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 4),
-
-	/* set Rx packet filter: (u32)a0=filters (see CMD_PFILTER_*) */
-	CMD_PACKET_FILTER	= _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 7),
-
-	/* set Rx packet filter for all: (u32)a0=filters (see CMD_PFILTER_*) */
-	CMD_PACKET_FILTER_ALL   = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 7),
-
-	/* hang detection notification */
-	CMD_HANG_NOTIFY         = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 8),
-
-	/* MAC address in (u48)a0 */
-	CMD_MAC_ADDR            = _CMDC(_CMD_DIR_READ,
-					_CMD_VTYPE_ENET | _CMD_VTYPE_FC, 9),
-
-	/* add addr from (u48)a0 */
-	CMD_ADDR_ADD            = _CMDCNW(_CMD_DIR_WRITE,
-					_CMD_VTYPE_ENET | _CMD_VTYPE_FC, 12),
-
-	/* del addr from (u48)a0 */
-	CMD_ADDR_DEL            = _CMDCNW(_CMD_DIR_WRITE,
-					_CMD_VTYPE_ENET | _CMD_VTYPE_FC, 13),
-
-	/* add VLAN id in (u16)a0 */
-	CMD_VLAN_ADD            = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 14),
-
-	/* del VLAN id in (u16)a0 */
-	CMD_VLAN_DEL            = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 15),
-
-	/* nic_cfg in (u32)a0 */
-	CMD_NIC_CFG             = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 16),
-
-	/* union vnic_rss_key in mem: (u64)a0=paddr, (u16)a1=len */
-	CMD_RSS_KEY             = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 17),
-
-	/* union vnic_rss_cpu in mem: (u64)a0=paddr, (u16)a1=len */
-	CMD_RSS_CPU             = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 18),
-
-	/* initiate softreset */
-	CMD_SOFT_RESET          = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 19),
-
-	/* softreset status:
-	 *    out: a0=0 reset complete, a0=1 reset in progress */
-	CMD_SOFT_RESET_STATUS   = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 20),
-
-	/* set struct vnic_devcmd_notify buffer in mem:
-	 * in:
-	 *   (u64)a0=paddr to notify (set paddr=0 to unset)
-	 *   (u32)a1 & 0x00000000ffffffff=sizeof(struct vnic_devcmd_notify)
-	 *   (u16)a1 & 0x0000ffff00000000=intr num (-1 for no intr)
-	 * out:
-	 *   (u32)a1 = effective size
-	 */
-	CMD_NOTIFY              = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 21),
-
-	/* UNDI API: (u64)a0=paddr to s_PXENV_UNDI_ struct,
-	 *           (u8)a1=PXENV_UNDI_xxx */
-	CMD_UNDI                = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 22),
-
-	/* initiate open sequence (u32)a0=flags (see CMD_OPENF_*) */
-	CMD_OPEN		= _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 23),
-
-	/* open status:
-	 *    out: a0=0 open complete, a0=1 open in progress */
-	CMD_OPEN_STATUS		= _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 24),
-
-	/* close vnic */
-	CMD_CLOSE		= _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 25),
-
-	/* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */
-/***** Replaced by CMD_INIT *****/
-	CMD_INIT_v1		= _CMDCNW(_CMD_DIR_READ, _CMD_VTYPE_ALL, 26),
-
-	/* variant of CMD_INIT, with provisioning info
-	 *     (u64)a0=paddr of vnic_devcmd_provinfo
-	 *     (u32)a1=sizeof provision info */
-	CMD_INIT_PROV_INFO	= _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 27),
-
-	/* enable virtual link */
-	CMD_ENABLE		= _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 28),
-
-	/* enable virtual link, waiting variant. */
-	CMD_ENABLE_WAIT		= _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 28),
-
-	/* disable virtual link */
-	CMD_DISABLE		= _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 29),
-
-	/* stats dump sum of all vnic stats on same uplink in mem:
-	 *     (u64)a0=paddr
-	 *     (u16)a1=sizeof stats area */
-	CMD_STATS_DUMP_ALL	= _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 30),
-
-	/* init status:
-	 *    out: a0=0 init complete, a0=1 init in progress
-	 *         if a0=0, a1=errno */
-	CMD_INIT_STATUS		= _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 31),
-
-	/* INT13 API: (u64)a0=paddr to vnic_int13_params struct
-	 *            (u32)a1=INT13_CMD_xxx */
-	CMD_INT13               = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_FC, 32),
-
-	/* logical uplink enable/disable: (u64)a0: 0/1=disable/enable */
-	CMD_LOGICAL_UPLINK      = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 33),
-
-	/* undo initialize of virtual link */
-	CMD_DEINIT		= _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 34),
-
-	/* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */
-	CMD_INIT		= _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 35),
-
-	/* check fw capability of a cmd:
-	 * in:  (u32)a0=cmd
-	 * out: (u32)a0=errno, 0:valid cmd, a1=supported VNIC_STF_* bits */
-	CMD_CAPABILITY		= _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 36),
-
-	/* persistent binding info
-	 * in:  (u64)a0=paddr of arg
-	 *      (u32)a1=CMD_PERBI_XXX */
-	CMD_PERBI		= _CMDC(_CMD_DIR_RW, _CMD_VTYPE_FC, 37),
-
-	/* Interrupt Assert Register functionality
-	 * in: (u16)a0=interrupt number to assert
-	 */
-	CMD_IAR			= _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 38),
-
-	/* initiate hangreset, like softreset after hang detected */
-	CMD_HANG_RESET		= _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 39),
-
-	/* hangreset status:
-	 *    out: a0=0 reset complete, a0=1 reset in progress */
-	CMD_HANG_RESET_STATUS   = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 40),
-
-	/*
-	 * Set hw ingress packet vlan rewrite mode:
-	 * in:  (u32)a0=new vlan rewrite mode
-	 * out: (u32)a0=old vlan rewrite mode */
-	CMD_IG_VLAN_REWRITE_MODE = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ENET, 41),
-
-	/*
-	 * in:  (u16)a0=bdf of target vnic
-	 *      (u32)a1=cmd to proxy
-	 *      a2-a15=args to cmd in a1
-	 * out: (u32)a0=status of proxied cmd
-	 *      a1-a15=out args of proxied cmd */
-	CMD_PROXY_BY_BDF =	_CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 42),
-
-	/*
-	 * As for BY_BDF except a0 is index of hvnlink subordinate vnic
-	 * or SR-IOV virtual vnic
-	 */
-	CMD_PROXY_BY_INDEX =    _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 43),
-
-	/*
-	 * For HPP toggle:
-	 * adapter-info-get
-	 * in:  (u64)a0=phsical address of buffer passed in from caller.
-	 *      (u16)a1=size of buffer specified in a0.
-	 * out: (u64)a0=phsical address of buffer passed in from caller.
-	 *      (u16)a1=actual bytes from VIF-CONFIG-INFO TLV, or
-	 *              0 if no VIF-CONFIG-INFO TLV was ever received. */
-	CMD_CONFIG_INFO_GET     = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 44),
-
-	/* init_prov_info2:
-	 * Variant of CMD_INIT_PROV_INFO, where it will not try to enable
-	 * the vnic until CMD_ENABLE2 is issued.
-	 *     (u64)a0=paddr of vnic_devcmd_provinfo
-	 *     (u32)a1=sizeof provision info */
-	CMD_INIT_PROV_INFO2  = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 47),
-
-	/* enable2:
-	 *      (u32)a0=0                  ==> standby
-	 *             =CMD_ENABLE2_ACTIVE ==> active
-	 */
-	CMD_ENABLE2 = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 48),
-
-	/*
-	 * cmd_status:
-	 *     Returns the status of the specified command
-	 * Input:
-	 *     a0 = command for which status is being queried.
-	 *          Possible values are:
-	 *              CMD_SOFT_RESET
-	 *              CMD_HANG_RESET
-	 *              CMD_OPEN
-	 *              CMD_INIT
-	 *              CMD_INIT_PROV_INFO
-	 *              CMD_DEINIT
-	 *              CMD_INIT_PROV_INFO2
-	 *              CMD_ENABLE2
-	 * Output:
-	 *     if status == STAT_ERROR
-	 *        a0 = ERR_ENOTSUPPORTED - status for command in a0 is
-	 *                                 not supported
-	 *     if status == STAT_NONE
-	 *        a0 = status of the devcmd specified in a0 as follows.
-	 *             ERR_SUCCESS   - command in a0 completed successfully
-	 *             ERR_EINPROGRESS - command in a0 is still in progress
-	 */
-	CMD_STATUS = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 49),
-
-	/*
-	 * Returns interrupt coalescing timer conversion factors.
-	 * After calling this devcmd, ENIC driver can convert
-	 * interrupt coalescing timer in usec into CPU cycles as follows:
-	 *
-	 *   intr_timer_cycles = intr_timer_usec * multiplier / divisor
-	 *
-	 * Interrupt coalescing timer in usecs can be obtained from
-	 * CPU cycles as follows:
-	 *
-	 *   intr_timer_usec = intr_timer_cycles * divisor / multiplier
-	 *
-	 * in: none
-	 * out: (u32)a0 = multiplier
-	 *      (u32)a1 = divisor
-	 *      (u32)a2 = maximum timer value in usec
-	 */
-	CMD_INTR_COAL_CONVERT = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 50),
-};
-
-/* CMD_ENABLE2 flags */
-#define CMD_ENABLE2_ACTIVE  0x1
-
-/* flags for CMD_OPEN */
-#define CMD_OPENF_OPROM		0x1	/* open coming from option rom */
-
-/* flags for CMD_INIT */
-#define CMD_INITF_DEFAULT_MAC	0x1	/* init with default mac addr */
-
-/* flags for CMD_PACKET_FILTER */
-#define CMD_PFILTER_DIRECTED		0x01
-#define CMD_PFILTER_MULTICAST		0x02
-#define CMD_PFILTER_BROADCAST		0x04
-#define CMD_PFILTER_PROMISCUOUS		0x08
-#define CMD_PFILTER_ALL_MULTICAST	0x10
-
-/* rewrite modes for CMD_IG_VLAN_REWRITE_MODE */
-#define IG_VLAN_REWRITE_MODE_DEFAULT_TRUNK              0
-#define IG_VLAN_REWRITE_MODE_UNTAG_DEFAULT_VLAN         1
-#define IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN  2
-#define IG_VLAN_REWRITE_MODE_PASS_THRU                  3
-
-enum vnic_devcmd_status {
-	STAT_NONE = 0,
-	STAT_BUSY = 1 << 0,	/* cmd in progress */
-	STAT_ERROR = 1 << 1,	/* last cmd caused error (code in a0) */
-};
-
-enum vnic_devcmd_error {
-	ERR_SUCCESS = 0,
-	ERR_EINVAL = 1,
-	ERR_EFAULT = 2,
-	ERR_EPERM = 3,
-	ERR_EBUSY = 4,
-	ERR_ECMDUNKNOWN = 5,
-	ERR_EBADSTATE = 6,
-	ERR_ENOMEM = 7,
-	ERR_ETIMEDOUT = 8,
-	ERR_ELINKDOWN = 9,
-	ERR_EMAXRES = 10,
-	ERR_ENOTSUPPORTED = 11,
-	ERR_EINPROGRESS = 12,
-};
-
-/*
- * 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 {
-	u32 csum;		/* checksum over following words */
-
-	u32 link_state;		/* link up == 1 */
-	u32 port_speed;		/* effective port speed (rate limit) */
-	u32 mtu;		/* MTU */
-	u32 msglvl;		/* requested driver msg lvl */
-	u32 uif;		/* uplink interface */
-	u32 status;		/* status bits (see VNIC_STF_*) */
-	u32 error;		/* error code (see ERR_*) for first ERR */
-	u32 link_down_cnt;	/* running count of link down transitions */
-	u32 perbi_rebuild_cnt;	/* running count of perbi rebuilds */
-};
-#define VNIC_STF_FATAL_ERR	0x0001	/* fatal fw error */
-#define VNIC_STF_STD_PAUSE	0x0002	/* standard link-level pause on */
-#define VNIC_STF_PFC_PAUSE	0x0004	/* priority flow control pause on */
-/* all supported status flags */
-#define VNIC_STF_ALL		(VNIC_STF_FATAL_ERR |\
-				 VNIC_STF_STD_PAUSE |\
-				 VNIC_STF_PFC_PAUSE |\
-				 0)
-
-struct vnic_devcmd_provinfo {
-	u8 oui[3];
-	u8 type;
-	u8 data[0];
-};
-
-/*
- * Writing cmd register causes STAT_BUSY to get set in status register.
- * When cmd completes, STAT_BUSY will be cleared.
- *
- * If cmd completed successfully STAT_ERROR will be clear
- * and args registers contain cmd-specific results.
- *
- * If cmd error, STAT_ERROR will be set and args[0] contains error code.
- *
- * status register is read-only.  While STAT_BUSY is set,
- * all other register contents are read-only.
- */
-
-/* Make sizeof(vnic_devcmd) a power-of-2 for I/O BAR. */
-#define VNIC_DEVCMD_NARGS 15
-struct vnic_devcmd {
-	u32 status;			/* RO */
-	u32 cmd;			/* RW */
-	u64 args[VNIC_DEVCMD_NARGS];	/* RW cmd args (little-endian) */
-};
-
-#endif /* _VNIC_DEVCMD_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_dev.h linux-libre-3.2-gnu/drivers/net/enic/vnic_dev.h
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_dev.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_dev.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,133 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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 _VNIC_DEV_H_
-#define _VNIC_DEV_H_
-
-#include "vnic_resource.h"
-#include "vnic_devcmd.h"
-
-#ifndef VNIC_PADDR_TARGET
-#define VNIC_PADDR_TARGET	0x0000000000000000ULL
-#endif
-
-#ifndef readq
-static inline u64 readq(void __iomem *reg)
-{
-	return (((u64)readl(reg + 0x4UL) << 32) |
-		(u64)readl(reg));
-}
-
-static inline void writeq(u64 val, void __iomem *reg)
-{
-	writel(val & 0xffffffff, reg);
-	writel(val >> 32, reg + 0x4UL);
-}
-#endif
-
-#undef pr_fmt
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-enum vnic_dev_intr_mode {
-	VNIC_DEV_INTR_MODE_UNKNOWN,
-	VNIC_DEV_INTR_MODE_INTX,
-	VNIC_DEV_INTR_MODE_MSI,
-	VNIC_DEV_INTR_MODE_MSIX,
-};
-
-struct vnic_dev_bar {
-	void __iomem *vaddr;
-	dma_addr_t bus_addr;
-	unsigned long len;
-};
-
-struct vnic_dev_ring {
-	void *descs;
-	size_t size;
-	dma_addr_t base_addr;
-	size_t base_align;
-	void *descs_unaligned;
-	size_t size_unaligned;
-	dma_addr_t base_addr_unaligned;
-	unsigned int desc_size;
-	unsigned int desc_count;
-	unsigned int desc_avail;
-};
-
-struct vnic_dev;
-struct vnic_stats;
-
-void *vnic_dev_priv(struct vnic_dev *vdev);
-unsigned int vnic_dev_get_res_count(struct vnic_dev *vdev,
-	enum vnic_res_type type);
-void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type,
-	unsigned int index);
-void vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring);
-int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring,
-	unsigned int desc_count, unsigned int desc_size);
-void vnic_dev_free_desc_ring(struct vnic_dev *vdev,
-	struct vnic_dev_ring *ring);
-int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
-	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_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);
-int vnic_dev_hang_notify(struct vnic_dev *vdev);
-int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
-	int broadcast, int promisc, int allmulti);
-int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr);
-int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr);
-int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr);
-int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr);
-int vnic_dev_notify_unset(struct vnic_dev *vdev);
-int vnic_dev_link_status(struct vnic_dev *vdev);
-u32 vnic_dev_port_speed(struct vnic_dev *vdev);
-u32 vnic_dev_msg_lvl(struct vnic_dev *vdev);
-u32 vnic_dev_mtu(struct vnic_dev *vdev);
-int vnic_dev_close(struct vnic_dev *vdev);
-int vnic_dev_enable_wait(struct vnic_dev *vdev);
-int vnic_dev_disable(struct vnic_dev *vdev);
-int vnic_dev_open(struct vnic_dev *vdev, int arg);
-int vnic_dev_open_done(struct vnic_dev *vdev, int *done);
-int vnic_dev_init(struct vnic_dev *vdev, int arg);
-int vnic_dev_deinit(struct vnic_dev *vdev);
-void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev);
-int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev);
-int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg);
-int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done);
-void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
-	enum vnic_dev_intr_mode intr_mode);
-enum vnic_dev_intr_mode vnic_dev_get_intr_mode(struct vnic_dev *vdev);
-u32 vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev, u32 usec);
-u32 vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev *vdev, u32 hw_cycles);
-u32 vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev);
-void vnic_dev_unregister(struct vnic_dev *vdev);
-int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev,
-	u8 ig_vlan_rewrite_mode);
-struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
-	void *priv, struct pci_dev *pdev, struct vnic_dev_bar *bar,
-	unsigned int num_bars);
-int vnic_dev_init_prov2(struct vnic_dev *vdev, u8 *buf, u32 len);
-int vnic_dev_enable2(struct vnic_dev *vdev, int active);
-int vnic_dev_enable2_done(struct vnic_dev *vdev, int *status);
-int vnic_dev_deinit_done(struct vnic_dev *vdev, int *status);
-
-#endif /* _VNIC_DEV_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_enet.h linux-libre-3.2-gnu/drivers/net/enic/vnic_enet.h
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_enet.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_enet.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,57 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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 _VNIC_ENIC_H_
-#define _VNIC_ENIC_H_
-
-/* Device-specific region: enet configuration */
-struct vnic_enet_config {
-	u32 flags;
-	u32 wq_desc_count;
-	u32 rq_desc_count;
-	u16 mtu;
-	u16 intr_timer_deprecated;
-	u8 intr_timer_type;
-	u8 intr_mode;
-	char devname[16];
-	u32 intr_timer_usec;
-	u16 loop_tag;
-};
-
-#define VENETF_TSO		0x1	/* TSO enabled */
-#define VENETF_LRO		0x2	/* LRO enabled */
-#define VENETF_RXCSUM		0x4	/* RX csum enabled */
-#define VENETF_TXCSUM		0x8	/* TX csum enabled */
-#define VENETF_RSS		0x10	/* RSS enabled */
-#define VENETF_RSSHASH_IPV4	0x20	/* Hash on IPv4 fields */
-#define VENETF_RSSHASH_TCPIPV4	0x40	/* Hash on TCP + IPv4 fields */
-#define VENETF_RSSHASH_IPV6	0x80	/* Hash on IPv6 fields */
-#define VENETF_RSSHASH_TCPIPV6	0x100	/* Hash on TCP + IPv6 fields */
-#define VENETF_RSSHASH_IPV6_EX	0x200	/* Hash on IPv6 extended fields */
-#define VENETF_RSSHASH_TCPIPV6_EX 0x400	/* Hash on TCP + IPv6 ext. fields */
-#define VENETF_LOOP		0x800	/* Loopback enabled */
-
-#define VENET_INTR_TYPE_MIN	0	/* Timer specs min interrupt spacing */
-#define VENET_INTR_TYPE_IDLE	1	/* Timer specs idle time before irq */
-
-#define VENET_INTR_MODE_ANY	0	/* Try MSI-X, then MSI, then INTx */
-#define VENET_INTR_MODE_MSI	1	/* Try MSI then INTx */
-#define VENET_INTR_MODE_INTX	2	/* Try INTx only */
-
-#endif /* _VNIC_ENIC_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_intr.c linux-libre-3.2-gnu/drivers/net/enic/vnic_intr.c
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_intr.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_intr.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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/kernel.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-
-#include "vnic_dev.h"
-#include "vnic_intr.h"
-
-void vnic_intr_free(struct vnic_intr *intr)
-{
-	intr->ctrl = NULL;
-}
-
-int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr,
-	unsigned int index)
-{
-	intr->index = index;
-	intr->vdev = vdev;
-
-	intr->ctrl = vnic_dev_get_res(vdev, RES_TYPE_INTR_CTRL, index);
-	if (!intr->ctrl) {
-		pr_err("Failed to hook INTR[%d].ctrl resource\n", index);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-void vnic_intr_init(struct vnic_intr *intr, u32 coalescing_timer,
-	unsigned int coalescing_type, unsigned int mask_on_assertion)
-{
-	vnic_intr_coalescing_timer_set(intr, coalescing_timer);
-	iowrite32(coalescing_type, &intr->ctrl->coalescing_type);
-	iowrite32(mask_on_assertion, &intr->ctrl->mask_on_assertion);
-	iowrite32(0, &intr->ctrl->int_credits);
-}
-
-void vnic_intr_coalescing_timer_set(struct vnic_intr *intr,
-	u32 coalescing_timer)
-{
-	iowrite32(vnic_dev_intr_coal_timer_usec_to_hw(intr->vdev,
-		coalescing_timer), &intr->ctrl->coalescing_timer);
-}
-
-void vnic_intr_clean(struct vnic_intr *intr)
-{
-	iowrite32(0, &intr->ctrl->int_credits);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_intr.h linux-libre-3.2-gnu/drivers/net/enic/vnic_intr.h
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_intr.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_intr.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,111 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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 _VNIC_INTR_H_
-#define _VNIC_INTR_H_
-
-#include <linux/pci.h>
-
-#include "vnic_dev.h"
-
-#define VNIC_INTR_TIMER_TYPE_ABS	0
-#define VNIC_INTR_TIMER_TYPE_QUIET	1
-
-/* Interrupt control */
-struct vnic_intr_ctrl {
-	u32 coalescing_timer;		/* 0x00 */
-	u32 pad0;
-	u32 coalescing_value;		/* 0x08 */
-	u32 pad1;
-	u32 coalescing_type;		/* 0x10 */
-	u32 pad2;
-	u32 mask_on_assertion;		/* 0x18 */
-	u32 pad3;
-	u32 mask;			/* 0x20 */
-	u32 pad4;
-	u32 int_credits;		/* 0x28 */
-	u32 pad5;
-	u32 int_credit_return;		/* 0x30 */
-	u32 pad6;
-};
-
-struct vnic_intr {
-	unsigned int index;
-	struct vnic_dev *vdev;
-	struct vnic_intr_ctrl __iomem *ctrl;		/* memory-mapped */
-};
-
-static inline void vnic_intr_unmask(struct vnic_intr *intr)
-{
-	iowrite32(0, &intr->ctrl->mask);
-}
-
-static inline void vnic_intr_mask(struct vnic_intr *intr)
-{
-	iowrite32(1, &intr->ctrl->mask);
-}
-
-static inline int vnic_intr_masked(struct vnic_intr *intr)
-{
-	return ioread32(&intr->ctrl->mask);
-}
-
-static inline void vnic_intr_return_credits(struct vnic_intr *intr,
-	unsigned int credits, int unmask, int reset_timer)
-{
-#define VNIC_INTR_UNMASK_SHIFT		16
-#define VNIC_INTR_RESET_TIMER_SHIFT	17
-
-	u32 int_credit_return = (credits & 0xffff) |
-		(unmask ? (1 << VNIC_INTR_UNMASK_SHIFT) : 0) |
-		(reset_timer ? (1 << VNIC_INTR_RESET_TIMER_SHIFT) : 0);
-
-	iowrite32(int_credit_return, &intr->ctrl->int_credit_return);
-}
-
-static inline unsigned int vnic_intr_credits(struct vnic_intr *intr)
-{
-	return ioread32(&intr->ctrl->int_credits);
-}
-
-static inline void vnic_intr_return_all_credits(struct vnic_intr *intr)
-{
-	unsigned int credits = vnic_intr_credits(intr);
-	int unmask = 1;
-	int reset_timer = 1;
-
-	vnic_intr_return_credits(intr, credits, unmask, reset_timer);
-}
-
-static inline u32 vnic_intr_legacy_pba(u32 __iomem *legacy_pba)
-{
-	/* read PBA without clearing */
-	return ioread32(legacy_pba);
-}
-
-void vnic_intr_free(struct vnic_intr *intr);
-int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr,
-	unsigned int index);
-void vnic_intr_init(struct vnic_intr *intr, u32 coalescing_timer,
-	unsigned int coalescing_type, unsigned int mask_on_assertion);
-void vnic_intr_coalescing_timer_set(struct vnic_intr *intr,
-	u32 coalescing_timer);
-void vnic_intr_clean(struct vnic_intr *intr);
-
-#endif /* _VNIC_INTR_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_nic.h linux-libre-3.2-gnu/drivers/net/enic/vnic_nic.h
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_nic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_nic.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,72 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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 _VNIC_NIC_H_
-#define _VNIC_NIC_H_
-
-#define NIC_CFG_RSS_DEFAULT_CPU_MASK_FIELD	0xffUL
-#define NIC_CFG_RSS_DEFAULT_CPU_SHIFT		0
-#define NIC_CFG_RSS_HASH_TYPE			(0xffUL << 8)
-#define NIC_CFG_RSS_HASH_TYPE_MASK_FIELD	0xffUL
-#define NIC_CFG_RSS_HASH_TYPE_SHIFT		8
-#define NIC_CFG_RSS_HASH_BITS			(7UL << 16)
-#define NIC_CFG_RSS_HASH_BITS_MASK_FIELD	7UL
-#define NIC_CFG_RSS_HASH_BITS_SHIFT		16
-#define NIC_CFG_RSS_BASE_CPU			(7UL << 19)
-#define NIC_CFG_RSS_BASE_CPU_MASK_FIELD		7UL
-#define NIC_CFG_RSS_BASE_CPU_SHIFT		19
-#define NIC_CFG_RSS_ENABLE			(1UL << 22)
-#define NIC_CFG_RSS_ENABLE_MASK_FIELD		1UL
-#define NIC_CFG_RSS_ENABLE_SHIFT		22
-#define NIC_CFG_TSO_IPID_SPLIT_EN		(1UL << 23)
-#define NIC_CFG_TSO_IPID_SPLIT_EN_MASK_FIELD	1UL
-#define NIC_CFG_TSO_IPID_SPLIT_EN_SHIFT		23
-#define NIC_CFG_IG_VLAN_STRIP_EN		(1UL << 24)
-#define NIC_CFG_IG_VLAN_STRIP_EN_MASK_FIELD	1UL
-#define NIC_CFG_IG_VLAN_STRIP_EN_SHIFT		24
-
-#define NIC_CFG_RSS_HASH_TYPE_IPV4		(1 << 1)
-#define NIC_CFG_RSS_HASH_TYPE_TCP_IPV4		(1 << 2)
-#define NIC_CFG_RSS_HASH_TYPE_IPV6		(1 << 3)
-#define NIC_CFG_RSS_HASH_TYPE_TCP_IPV6		(1 << 4)
-#define NIC_CFG_RSS_HASH_TYPE_IPV6_EX		(1 << 5)
-#define NIC_CFG_RSS_HASH_TYPE_TCP_IPV6_EX	(1 << 6)
-
-static inline void vnic_set_nic_cfg(u32 *nic_cfg,
-	u8 rss_default_cpu, u8 rss_hash_type,
-	u8 rss_hash_bits, u8 rss_base_cpu,
-	u8 rss_enable, u8 tso_ipid_split_en,
-	u8 ig_vlan_strip_en)
-{
-	*nic_cfg = (rss_default_cpu & NIC_CFG_RSS_DEFAULT_CPU_MASK_FIELD) |
-		((rss_hash_type & NIC_CFG_RSS_HASH_TYPE_MASK_FIELD)
-			<< NIC_CFG_RSS_HASH_TYPE_SHIFT) |
-		((rss_hash_bits & NIC_CFG_RSS_HASH_BITS_MASK_FIELD)
-			<< NIC_CFG_RSS_HASH_BITS_SHIFT) |
-		((rss_base_cpu & NIC_CFG_RSS_BASE_CPU_MASK_FIELD)
-			<< NIC_CFG_RSS_BASE_CPU_SHIFT) |
-		((rss_enable & NIC_CFG_RSS_ENABLE_MASK_FIELD)
-			<< NIC_CFG_RSS_ENABLE_SHIFT) |
-		((tso_ipid_split_en & NIC_CFG_TSO_IPID_SPLIT_EN_MASK_FIELD)
-			<< NIC_CFG_TSO_IPID_SPLIT_EN_SHIFT) |
-		((ig_vlan_strip_en & NIC_CFG_IG_VLAN_STRIP_EN_MASK_FIELD)
-			<< NIC_CFG_IG_VLAN_STRIP_EN_SHIFT);
-}
-
-#endif /* _VNIC_NIC_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_resource.h linux-libre-3.2-gnu/drivers/net/enic/vnic_resource.h
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_resource.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_resource.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,76 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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 _VNIC_RESOURCE_H_
-#define _VNIC_RESOURCE_H_
-
-#define VNIC_RES_MAGIC		0x766E6963L	/* 'vnic' */
-#define VNIC_RES_VERSION	0x00000000L
-#define MGMTVNIC_MAGIC		0x544d474dL	/* 'MGMT' */
-#define MGMTVNIC_VERSION	0x00000000L
-
-/* The MAC address assigned to the CFG vNIC is fixed. */
-#define MGMTVNIC_MAC		{ 0x02, 0x00, 0x54, 0x4d, 0x47, 0x4d }
-
-/* vNIC resource types */
-enum vnic_res_type {
-	RES_TYPE_EOL,			/* End-of-list */
-	RES_TYPE_WQ,			/* Work queues */
-	RES_TYPE_RQ,			/* Receive queues */
-	RES_TYPE_CQ,			/* Completion queues */
-	RES_TYPE_RSVD1,
-	RES_TYPE_NIC_CFG,		/* Enet NIC config registers */
-	RES_TYPE_RSVD2,
-	RES_TYPE_RSVD3,
-	RES_TYPE_RSVD4,
-	RES_TYPE_RSVD5,
-	RES_TYPE_INTR_CTRL,		/* Interrupt ctrl table */
-	RES_TYPE_INTR_TABLE,		/* MSI/MSI-X Interrupt table */
-	RES_TYPE_INTR_PBA,		/* MSI/MSI-X PBA table */
-	RES_TYPE_INTR_PBA_LEGACY,	/* Legacy intr status */
-	RES_TYPE_RSVD6,
-	RES_TYPE_RSVD7,
-	RES_TYPE_DEVCMD,		/* Device command region */
-	RES_TYPE_PASS_THRU_PAGE,	/* Pass-thru page */
-
-	RES_TYPE_MAX,			/* Count of resource types */
-};
-
-struct vnic_resource_header {
-	u32 magic;
-	u32 version;
-};
-
-struct mgmt_barmap_hdr {
-	u32 magic;			/* magic number */
-	u32 version;			/* header format version */
-	u16 lif;			/* loopback lif for mgmt frames */
-	u16 pci_slot;			/* installed pci slot */
-	char serial[16];		/* card serial number */
-};
-
-struct vnic_resource {
-	u8 type;
-	u8 bar;
-	u8 pad[2];
-	u32 bar_offset;
-	u32 count;
-};
-
-#endif /* _VNIC_RESOURCE_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_rq.c linux-libre-3.2-gnu/drivers/net/enic/vnic_rq.c
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_rq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_rq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,221 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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/kernel.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-
-#include "vnic_dev.h"
-#include "vnic_rq.h"
-
-static int vnic_rq_alloc_bufs(struct vnic_rq *rq)
-{
-	struct vnic_rq_buf *buf;
-	struct vnic_dev *vdev;
-	unsigned int i, j, count = rq->ring.desc_count;
-	unsigned int blks = VNIC_RQ_BUF_BLKS_NEEDED(count);
-
-	vdev = rq->vdev;
-
-	for (i = 0; i < blks; i++) {
-		rq->bufs[i] = kzalloc(VNIC_RQ_BUF_BLK_SZ(count), GFP_ATOMIC);
-		if (!rq->bufs[i]) {
-			pr_err("Failed to alloc rq_bufs\n");
-			return -ENOMEM;
-		}
-	}
-
-	for (i = 0; i < blks; i++) {
-		buf = rq->bufs[i];
-		for (j = 0; j < VNIC_RQ_BUF_BLK_ENTRIES(count); j++) {
-			buf->index = i * VNIC_RQ_BUF_BLK_ENTRIES(count) + j;
-			buf->desc = (u8 *)rq->ring.descs +
-				rq->ring.desc_size * buf->index;
-			if (buf->index + 1 == count) {
-				buf->next = rq->bufs[0];
-				break;
-			} else if (j + 1 == VNIC_RQ_BUF_BLK_ENTRIES(count)) {
-				buf->next = rq->bufs[i + 1];
-			} else {
-				buf->next = buf + 1;
-				buf++;
-			}
-		}
-	}
-
-	rq->to_use = rq->to_clean = rq->bufs[0];
-
-	return 0;
-}
-
-void vnic_rq_free(struct vnic_rq *rq)
-{
-	struct vnic_dev *vdev;
-	unsigned int i;
-
-	vdev = rq->vdev;
-
-	vnic_dev_free_desc_ring(vdev, &rq->ring);
-
-	for (i = 0; i < VNIC_RQ_BUF_BLKS_MAX; i++) {
-		if (rq->bufs[i]) {
-			kfree(rq->bufs[i]);
-			rq->bufs[i] = NULL;
-		}
-	}
-
-	rq->ctrl = NULL;
-}
-
-int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index,
-	unsigned int desc_count, unsigned int desc_size)
-{
-	int err;
-
-	rq->index = index;
-	rq->vdev = vdev;
-
-	rq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_RQ, index);
-	if (!rq->ctrl) {
-		pr_err("Failed to hook RQ[%d] resource\n", index);
-		return -EINVAL;
-	}
-
-	vnic_rq_disable(rq);
-
-	err = vnic_dev_alloc_desc_ring(vdev, &rq->ring, desc_count, desc_size);
-	if (err)
-		return err;
-
-	err = vnic_rq_alloc_bufs(rq);
-	if (err) {
-		vnic_rq_free(rq);
-		return err;
-	}
-
-	return 0;
-}
-
-static void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index,
-	unsigned int fetch_index, unsigned int posted_index,
-	unsigned int error_interrupt_enable,
-	unsigned int error_interrupt_offset)
-{
-	u64 paddr;
-	unsigned int count = rq->ring.desc_count;
-
-	paddr = (u64)rq->ring.base_addr | VNIC_PADDR_TARGET;
-	writeq(paddr, &rq->ctrl->ring_base);
-	iowrite32(count, &rq->ctrl->ring_size);
-	iowrite32(cq_index, &rq->ctrl->cq_index);
-	iowrite32(error_interrupt_enable, &rq->ctrl->error_interrupt_enable);
-	iowrite32(error_interrupt_offset, &rq->ctrl->error_interrupt_offset);
-	iowrite32(0, &rq->ctrl->dropped_packet_count);
-	iowrite32(0, &rq->ctrl->error_status);
-	iowrite32(fetch_index, &rq->ctrl->fetch_index);
-	iowrite32(posted_index, &rq->ctrl->posted_index);
-
-	rq->to_use = rq->to_clean =
-		&rq->bufs[fetch_index / VNIC_RQ_BUF_BLK_ENTRIES(count)]
-			[fetch_index % VNIC_RQ_BUF_BLK_ENTRIES(count)];
-}
-
-void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
-	unsigned int error_interrupt_enable,
-	unsigned int error_interrupt_offset)
-{
-	u32 fetch_index;
-
-	/* Use current fetch_index as the ring starting point */
-	fetch_index = ioread32(&rq->ctrl->fetch_index);
-
-	if (fetch_index == 0xFFFFFFFF) { /* check for hardware gone  */
-		/* Hardware surprise removal: reset fetch_index */
-		fetch_index = 0;
-	}
-
-	vnic_rq_init_start(rq, cq_index,
-		fetch_index, fetch_index,
-		error_interrupt_enable,
-		error_interrupt_offset);
-}
-
-unsigned int vnic_rq_error_status(struct vnic_rq *rq)
-{
-	return ioread32(&rq->ctrl->error_status);
-}
-
-void vnic_rq_enable(struct vnic_rq *rq)
-{
-	iowrite32(1, &rq->ctrl->enable);
-}
-
-int vnic_rq_disable(struct vnic_rq *rq)
-{
-	unsigned int wait;
-
-	iowrite32(0, &rq->ctrl->enable);
-
-	/* Wait for HW to ACK disable request */
-	for (wait = 0; wait < 1000; wait++) {
-		if (!(ioread32(&rq->ctrl->running)))
-			return 0;
-		udelay(10);
-	}
-
-	pr_err("Failed to disable RQ[%d]\n", rq->index);
-
-	return -ETIMEDOUT;
-}
-
-void vnic_rq_clean(struct vnic_rq *rq,
-	void (*buf_clean)(struct vnic_rq *rq, struct vnic_rq_buf *buf))
-{
-	struct vnic_rq_buf *buf;
-	u32 fetch_index;
-	unsigned int count = rq->ring.desc_count;
-
-	buf = rq->to_clean;
-
-	while (vnic_rq_desc_used(rq) > 0) {
-
-		(*buf_clean)(rq, buf);
-
-		buf = rq->to_clean = buf->next;
-		rq->ring.desc_avail++;
-	}
-
-	/* Use current fetch_index as the ring starting point */
-	fetch_index = ioread32(&rq->ctrl->fetch_index);
-
-	if (fetch_index == 0xFFFFFFFF) { /* check for hardware gone  */
-		/* Hardware surprise removal: reset fetch_index */
-		fetch_index = 0;
-	}
-	rq->to_use = rq->to_clean =
-		&rq->bufs[fetch_index / VNIC_RQ_BUF_BLK_ENTRIES(count)]
-			[fetch_index % VNIC_RQ_BUF_BLK_ENTRIES(count)];
-	iowrite32(fetch_index, &rq->ctrl->posted_index);
-
-	vnic_dev_clear_desc_ring(&rq->ring);
-}
-
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_rq.h linux-libre-3.2-gnu/drivers/net/enic/vnic_rq.h
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_rq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_rq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,209 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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 _VNIC_RQ_H_
-#define _VNIC_RQ_H_
-
-#include <linux/pci.h>
-
-#include "vnic_dev.h"
-#include "vnic_cq.h"
-
-/* Receive queue control */
-struct vnic_rq_ctrl {
-	u64 ring_base;			/* 0x00 */
-	u32 ring_size;			/* 0x08 */
-	u32 pad0;
-	u32 posted_index;		/* 0x10 */
-	u32 pad1;
-	u32 cq_index;			/* 0x18 */
-	u32 pad2;
-	u32 enable;			/* 0x20 */
-	u32 pad3;
-	u32 running;			/* 0x28 */
-	u32 pad4;
-	u32 fetch_index;		/* 0x30 */
-	u32 pad5;
-	u32 error_interrupt_enable;	/* 0x38 */
-	u32 pad6;
-	u32 error_interrupt_offset;	/* 0x40 */
-	u32 pad7;
-	u32 error_status;		/* 0x48 */
-	u32 pad8;
-	u32 dropped_packet_count;	/* 0x50 */
-	u32 pad9;
-	u32 dropped_packet_count_rc;	/* 0x58 */
-	u32 pad10;
-};
-
-/* Break the vnic_rq_buf allocations into blocks of 32/64 entries */
-#define VNIC_RQ_BUF_MIN_BLK_ENTRIES 32
-#define VNIC_RQ_BUF_DFLT_BLK_ENTRIES 64
-#define VNIC_RQ_BUF_BLK_ENTRIES(entries) \
-	((unsigned int)((entries < VNIC_RQ_BUF_DFLT_BLK_ENTRIES) ? \
-	VNIC_RQ_BUF_MIN_BLK_ENTRIES : VNIC_RQ_BUF_DFLT_BLK_ENTRIES))
-#define VNIC_RQ_BUF_BLK_SZ(entries) \
-	(VNIC_RQ_BUF_BLK_ENTRIES(entries) * sizeof(struct vnic_rq_buf))
-#define VNIC_RQ_BUF_BLKS_NEEDED(entries) \
-	DIV_ROUND_UP(entries, VNIC_RQ_BUF_BLK_ENTRIES(entries))
-#define VNIC_RQ_BUF_BLKS_MAX VNIC_RQ_BUF_BLKS_NEEDED(4096)
-
-struct vnic_rq_buf {
-	struct vnic_rq_buf *next;
-	dma_addr_t dma_addr;
-	void *os_buf;
-	unsigned int os_buf_index;
-	unsigned int len;
-	unsigned int index;
-	void *desc;
-};
-
-struct vnic_rq {
-	unsigned int index;
-	struct vnic_dev *vdev;
-	struct vnic_rq_ctrl __iomem *ctrl;              /* memory-mapped */
-	struct vnic_dev_ring ring;
-	struct vnic_rq_buf *bufs[VNIC_RQ_BUF_BLKS_MAX];
-	struct vnic_rq_buf *to_use;
-	struct vnic_rq_buf *to_clean;
-	void *os_buf_head;
-	unsigned int pkts_outstanding;
-};
-
-static inline unsigned int vnic_rq_desc_avail(struct vnic_rq *rq)
-{
-	/* how many does SW own? */
-	return rq->ring.desc_avail;
-}
-
-static inline unsigned int vnic_rq_desc_used(struct vnic_rq *rq)
-{
-	/* how many does HW own? */
-	return rq->ring.desc_count - rq->ring.desc_avail - 1;
-}
-
-static inline void *vnic_rq_next_desc(struct vnic_rq *rq)
-{
-	return rq->to_use->desc;
-}
-
-static inline unsigned int vnic_rq_next_index(struct vnic_rq *rq)
-{
-	return rq->to_use->index;
-}
-
-static inline void vnic_rq_post(struct vnic_rq *rq,
-	void *os_buf, unsigned int os_buf_index,
-	dma_addr_t dma_addr, unsigned int len)
-{
-	struct vnic_rq_buf *buf = rq->to_use;
-
-	buf->os_buf = os_buf;
-	buf->os_buf_index = os_buf_index;
-	buf->dma_addr = dma_addr;
-	buf->len = len;
-
-	buf = buf->next;
-	rq->to_use = buf;
-	rq->ring.desc_avail--;
-
-	/* Move the posted_index every nth descriptor
-	 */
-
-#ifndef VNIC_RQ_RETURN_RATE
-#define VNIC_RQ_RETURN_RATE		0xf	/* keep 2^n - 1 */
-#endif
-
-	if ((buf->index & VNIC_RQ_RETURN_RATE) == 0) {
-		/* Adding write memory barrier prevents compiler and/or CPU
-		 * reordering, thus avoiding descriptor posting before
-		 * descriptor is initialized. Otherwise, hardware can read
-		 * stale descriptor fields.
-		 */
-		wmb();
-		iowrite32(buf->index, &rq->ctrl->posted_index);
-	}
-}
-
-static inline void vnic_rq_return_descs(struct vnic_rq *rq, unsigned int count)
-{
-	rq->ring.desc_avail += count;
-}
-
-enum desc_return_options {
-	VNIC_RQ_RETURN_DESC,
-	VNIC_RQ_DEFER_RETURN_DESC,
-};
-
-static inline void vnic_rq_service(struct vnic_rq *rq,
-	struct cq_desc *cq_desc, u16 completed_index,
-	int desc_return, void (*buf_service)(struct vnic_rq *rq,
-	struct cq_desc *cq_desc, struct vnic_rq_buf *buf,
-	int skipped, void *opaque), void *opaque)
-{
-	struct vnic_rq_buf *buf;
-	int skipped;
-
-	buf = rq->to_clean;
-	while (1) {
-
-		skipped = (buf->index != completed_index);
-
-		(*buf_service)(rq, cq_desc, buf, skipped, opaque);
-
-		if (desc_return == VNIC_RQ_RETURN_DESC)
-			rq->ring.desc_avail++;
-
-		rq->to_clean = buf->next;
-
-		if (!skipped)
-			break;
-
-		buf = rq->to_clean;
-	}
-}
-
-static inline int vnic_rq_fill(struct vnic_rq *rq,
-	int (*buf_fill)(struct vnic_rq *rq))
-{
-	int err;
-
-	while (vnic_rq_desc_avail(rq) > 0) {
-
-		err = (*buf_fill)(rq);
-		if (err)
-			return err;
-	}
-
-	return 0;
-}
-
-void vnic_rq_free(struct vnic_rq *rq);
-int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index,
-	unsigned int desc_count, unsigned int desc_size);
-void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
-	unsigned int error_interrupt_enable,
-	unsigned int error_interrupt_offset);
-unsigned int vnic_rq_error_status(struct vnic_rq *rq);
-void vnic_rq_enable(struct vnic_rq *rq);
-int vnic_rq_disable(struct vnic_rq *rq);
-void vnic_rq_clean(struct vnic_rq *rq,
-	void (*buf_clean)(struct vnic_rq *rq, struct vnic_rq_buf *buf));
-
-#endif /* _VNIC_RQ_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_rss.h linux-libre-3.2-gnu/drivers/net/enic/vnic_rss.h
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_rss.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_rss.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,40 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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 _VNIC_RSS_H_
-#define _VNIC_RSS_H_
-
-/* RSS key array */
-union vnic_rss_key {
-	struct {
-		u8 b[10];
-		u8 b_pad[6];
-	} key[4];
-	u64 raw[8];
-};
-
-/* RSS cpu array */
-union vnic_rss_cpu {
-	struct {
-		u8 b[4] ;
-		u8 b_pad[4];
-	} cpu[32];
-	u64 raw[32];
-};
-
-#endif /* _VNIC_RSS_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_stats.h linux-libre-3.2-gnu/drivers/net/enic/vnic_stats.h
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_stats.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_stats.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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 _VNIC_STATS_H_
-#define _VNIC_STATS_H_
-
-/* Tx statistics */
-struct vnic_tx_stats {
-	u64 tx_frames_ok;
-	u64 tx_unicast_frames_ok;
-	u64 tx_multicast_frames_ok;
-	u64 tx_broadcast_frames_ok;
-	u64 tx_bytes_ok;
-	u64 tx_unicast_bytes_ok;
-	u64 tx_multicast_bytes_ok;
-	u64 tx_broadcast_bytes_ok;
-	u64 tx_drops;
-	u64 tx_errors;
-	u64 tx_tso;
-	u64 rsvd[16];
-};
-
-/* Rx statistics */
-struct vnic_rx_stats {
-	u64 rx_frames_ok;
-	u64 rx_frames_total;
-	u64 rx_unicast_frames_ok;
-	u64 rx_multicast_frames_ok;
-	u64 rx_broadcast_frames_ok;
-	u64 rx_bytes_ok;
-	u64 rx_unicast_bytes_ok;
-	u64 rx_multicast_bytes_ok;
-	u64 rx_broadcast_bytes_ok;
-	u64 rx_drop;
-	u64 rx_no_bufs;
-	u64 rx_errors;
-	u64 rx_rss;
-	u64 rx_crc_errors;
-	u64 rx_frames_64;
-	u64 rx_frames_127;
-	u64 rx_frames_255;
-	u64 rx_frames_511;
-	u64 rx_frames_1023;
-	u64 rx_frames_1518;
-	u64 rx_frames_to_max;
-	u64 rsvd[16];
-};
-
-struct vnic_stats {
-	struct vnic_tx_stats tx;
-	struct vnic_rx_stats rx;
-};
-
-#endif /* _VNIC_STATS_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_vic.c linux-libre-3.2-gnu/drivers/net/enic/vnic_vic.c
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_vic.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_vic.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,79 +0,0 @@
-/*
- * Copyright 2010 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/kernel.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-
-#include "vnic_vic.h"
-
-struct vic_provinfo *vic_provinfo_alloc(gfp_t flags, const u8 *oui,
-	const u8 type)
-{
-	struct vic_provinfo *vp;
-
-	if (!oui)
-		return NULL;
-
-	vp = kzalloc(VIC_PROVINFO_MAX_DATA, flags);
-	if (!vp)
-		return NULL;
-
-	memcpy(vp->oui, oui, sizeof(vp->oui));
-	vp->type = type;
-	vp->length = htonl(sizeof(vp->num_tlvs));
-
-	return vp;
-}
-
-void vic_provinfo_free(struct vic_provinfo *vp)
-{
-	kfree(vp);
-}
-
-int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length,
-	const void *value)
-{
-	struct vic_provinfo_tlv *tlv;
-
-	if (!vp || !value)
-		return -EINVAL;
-
-	if (ntohl(vp->length) + offsetof(struct vic_provinfo_tlv, value) +
-		length > VIC_PROVINFO_MAX_TLV_DATA)
-		return -ENOMEM;
-
-	tlv = (struct vic_provinfo_tlv *)((u8 *)vp->tlv +
-		ntohl(vp->length) - sizeof(vp->num_tlvs));
-
-	tlv->type = htons(type);
-	tlv->length = htons(length);
-	memcpy(tlv->value, value, length);
-
-	vp->num_tlvs = htonl(ntohl(vp->num_tlvs) + 1);
-	vp->length = htonl(ntohl(vp->length) +
-		offsetof(struct vic_provinfo_tlv, value) + length);
-
-	return 0;
-}
-
-size_t vic_provinfo_size(struct vic_provinfo *vp)
-{
-	return vp ?  ntohl(vp->length) + sizeof(*vp) - sizeof(vp->num_tlvs) : 0;
-}
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_vic.h linux-libre-3.2-gnu/drivers/net/enic/vnic_vic.h
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_vic.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_vic.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-/*
- * Copyright 2010 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 _VNIC_VIC_H_
-#define _VNIC_VIC_H_
-
-/* Note: All integer fields in NETWORK byte order */
-
-/* Note: String field lengths include null char */
-
-#define VIC_PROVINFO_CISCO_OUI		{ 0x00, 0x00, 0x0c }
-#define VIC_PROVINFO_GENERIC_TYPE		0x4
-
-enum vic_generic_prov_tlv_type {
-	VIC_GENERIC_PROV_TLV_PORT_PROFILE_NAME_STR = 0,
-	VIC_GENERIC_PROV_TLV_CLIENT_MAC_ADDR = 1,
-	VIC_GENERIC_PROV_TLV_CLIENT_NAME_STR = 2,
-	VIC_GENERIC_PROV_TLV_CLUSTER_PORT_NAME_STR = 3,
-	VIC_GENERIC_PROV_TLV_CLUSTER_PORT_UUID_STR = 4,
-	VIC_GENERIC_PROV_TLV_CLUSTER_UUID_STR = 5,
-	VIC_GENERIC_PROV_TLV_CLUSTER_NAME_STR = 7,
-	VIC_GENERIC_PROV_TLV_HOST_UUID_STR = 8,
-	VIC_GENERIC_PROV_TLV_CLIENT_UUID_STR = 9,
-	VIC_GENERIC_PROV_TLV_INCARNATION_NUMBER = 10,
-	VIC_GENERIC_PROV_TLV_OS_TYPE = 11,
-	VIC_GENERIC_PROV_TLV_OS_VENDOR = 12,
-	VIC_GENERIC_PROV_TLV_CLIENT_TYPE = 15,
-};
-
-enum vic_generic_prov_os_type {
-	VIC_GENERIC_PROV_OS_TYPE_UNKNOWN = 0,
-	VIC_GENERIC_PROV_OS_TYPE_ESX = 1,
-	VIC_GENERIC_PROV_OS_TYPE_LINUX = 2,
-	VIC_GENERIC_PROV_OS_TYPE_WINDOWS = 3,
-	VIC_GENERIC_PROV_OS_TYPE_SOLARIS = 4,
-};
-
-struct vic_provinfo {
-	u8 oui[3];		/* OUI of data provider */
-	u8 type;		/* provider-specific type */
-	u32 length;		/* length of data below */
-	u32 num_tlvs;		/* number of tlvs */
-	struct vic_provinfo_tlv {
-		u16 type;
-		u16 length;
-		u8 value[0];
-	} tlv[0];
-} __packed;
-
-#define VIC_PROVINFO_ADD_TLV(vp, tlvtype, tlvlen, data) \
-	do { \
-		err = vic_provinfo_add_tlv(vp, tlvtype, tlvlen, data); \
-		if (err) \
-			goto add_tlv_failure; \
-	} while (0)
-
-#define VIC_PROVINFO_MAX_DATA		1385
-#define VIC_PROVINFO_MAX_TLV_DATA (VIC_PROVINFO_MAX_DATA - \
-	sizeof(struct vic_provinfo))
-
-struct vic_provinfo *vic_provinfo_alloc(gfp_t flags, const u8 *oui,
-	const u8 type);
-void vic_provinfo_free(struct vic_provinfo *vp);
-int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length,
-	const void *value);
-size_t vic_provinfo_size(struct vic_provinfo *vp);
-
-#endif	/* _VNIC_VIC_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_wq.c linux-libre-3.2-gnu/drivers/net/enic/vnic_wq.c
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_wq.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_wq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,200 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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/kernel.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-
-#include "vnic_dev.h"
-#include "vnic_wq.h"
-
-static int vnic_wq_alloc_bufs(struct vnic_wq *wq)
-{
-	struct vnic_wq_buf *buf;
-	struct vnic_dev *vdev;
-	unsigned int i, j, count = wq->ring.desc_count;
-	unsigned int blks = VNIC_WQ_BUF_BLKS_NEEDED(count);
-
-	vdev = wq->vdev;
-
-	for (i = 0; i < blks; i++) {
-		wq->bufs[i] = kzalloc(VNIC_WQ_BUF_BLK_SZ(count), GFP_ATOMIC);
-		if (!wq->bufs[i]) {
-			pr_err("Failed to alloc wq_bufs\n");
-			return -ENOMEM;
-		}
-	}
-
-	for (i = 0; i < blks; i++) {
-		buf = wq->bufs[i];
-		for (j = 0; j < VNIC_WQ_BUF_BLK_ENTRIES(count); j++) {
-			buf->index = i * VNIC_WQ_BUF_BLK_ENTRIES(count) + j;
-			buf->desc = (u8 *)wq->ring.descs +
-				wq->ring.desc_size * buf->index;
-			if (buf->index + 1 == count) {
-				buf->next = wq->bufs[0];
-				break;
-			} else if (j + 1 == VNIC_WQ_BUF_BLK_ENTRIES(count)) {
-				buf->next = wq->bufs[i + 1];
-			} else {
-				buf->next = buf + 1;
-				buf++;
-			}
-		}
-	}
-
-	wq->to_use = wq->to_clean = wq->bufs[0];
-
-	return 0;
-}
-
-void vnic_wq_free(struct vnic_wq *wq)
-{
-	struct vnic_dev *vdev;
-	unsigned int i;
-
-	vdev = wq->vdev;
-
-	vnic_dev_free_desc_ring(vdev, &wq->ring);
-
-	for (i = 0; i < VNIC_WQ_BUF_BLKS_MAX; i++) {
-		if (wq->bufs[i]) {
-			kfree(wq->bufs[i]);
-			wq->bufs[i] = NULL;
-		}
-	}
-
-	wq->ctrl = NULL;
-}
-
-int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index,
-	unsigned int desc_count, unsigned int desc_size)
-{
-	int err;
-
-	wq->index = index;
-	wq->vdev = vdev;
-
-	wq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_WQ, index);
-	if (!wq->ctrl) {
-		pr_err("Failed to hook WQ[%d] resource\n", index);
-		return -EINVAL;
-	}
-
-	vnic_wq_disable(wq);
-
-	err = vnic_dev_alloc_desc_ring(vdev, &wq->ring, desc_count, desc_size);
-	if (err)
-		return err;
-
-	err = vnic_wq_alloc_bufs(wq);
-	if (err) {
-		vnic_wq_free(wq);
-		return err;
-	}
-
-	return 0;
-}
-
-static void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,
-	unsigned int fetch_index, unsigned int posted_index,
-	unsigned int error_interrupt_enable,
-	unsigned int error_interrupt_offset)
-{
-	u64 paddr;
-	unsigned int count = wq->ring.desc_count;
-
-	paddr = (u64)wq->ring.base_addr | VNIC_PADDR_TARGET;
-	writeq(paddr, &wq->ctrl->ring_base);
-	iowrite32(count, &wq->ctrl->ring_size);
-	iowrite32(fetch_index, &wq->ctrl->fetch_index);
-	iowrite32(posted_index, &wq->ctrl->posted_index);
-	iowrite32(cq_index, &wq->ctrl->cq_index);
-	iowrite32(error_interrupt_enable, &wq->ctrl->error_interrupt_enable);
-	iowrite32(error_interrupt_offset, &wq->ctrl->error_interrupt_offset);
-	iowrite32(0, &wq->ctrl->error_status);
-
-	wq->to_use = wq->to_clean =
-		&wq->bufs[fetch_index / VNIC_WQ_BUF_BLK_ENTRIES(count)]
-			[fetch_index % VNIC_WQ_BUF_BLK_ENTRIES(count)];
-}
-
-void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index,
-	unsigned int error_interrupt_enable,
-	unsigned int error_interrupt_offset)
-{
-	vnic_wq_init_start(wq, cq_index, 0, 0,
-		error_interrupt_enable,
-		error_interrupt_offset);
-}
-
-unsigned int vnic_wq_error_status(struct vnic_wq *wq)
-{
-	return ioread32(&wq->ctrl->error_status);
-}
-
-void vnic_wq_enable(struct vnic_wq *wq)
-{
-	iowrite32(1, &wq->ctrl->enable);
-}
-
-int vnic_wq_disable(struct vnic_wq *wq)
-{
-	unsigned int wait;
-
-	iowrite32(0, &wq->ctrl->enable);
-
-	/* Wait for HW to ACK disable request */
-	for (wait = 0; wait < 1000; wait++) {
-		if (!(ioread32(&wq->ctrl->running)))
-			return 0;
-		udelay(10);
-	}
-
-	pr_err("Failed to disable WQ[%d]\n", wq->index);
-
-	return -ETIMEDOUT;
-}
-
-void vnic_wq_clean(struct vnic_wq *wq,
-	void (*buf_clean)(struct vnic_wq *wq, struct vnic_wq_buf *buf))
-{
-	struct vnic_wq_buf *buf;
-
-	buf = wq->to_clean;
-
-	while (vnic_wq_desc_used(wq) > 0) {
-
-		(*buf_clean)(wq, buf);
-
-		buf = wq->to_clean = buf->next;
-		wq->ring.desc_avail++;
-	}
-
-	wq->to_use = wq->to_clean = wq->bufs[0];
-
-	iowrite32(0, &wq->ctrl->fetch_index);
-	iowrite32(0, &wq->ctrl->posted_index);
-	iowrite32(0, &wq->ctrl->error_status);
-
-	vnic_dev_clear_desc_ring(&wq->ring);
-}
diff -druN linux-libre-3.1-gnu/drivers/net/enic/vnic_wq.h linux-libre-3.2-gnu/drivers/net/enic/vnic_wq.h
--- linux-libre-3.1-gnu/drivers/net/enic/vnic_wq.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/vnic_wq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,165 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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 _VNIC_WQ_H_
-#define _VNIC_WQ_H_
-
-#include <linux/pci.h>
-
-#include "vnic_dev.h"
-#include "vnic_cq.h"
-
-/* Work queue control */
-struct vnic_wq_ctrl {
-	u64 ring_base;			/* 0x00 */
-	u32 ring_size;			/* 0x08 */
-	u32 pad0;
-	u32 posted_index;		/* 0x10 */
-	u32 pad1;
-	u32 cq_index;			/* 0x18 */
-	u32 pad2;
-	u32 enable;			/* 0x20 */
-	u32 pad3;
-	u32 running;			/* 0x28 */
-	u32 pad4;
-	u32 fetch_index;		/* 0x30 */
-	u32 pad5;
-	u32 dca_value;			/* 0x38 */
-	u32 pad6;
-	u32 error_interrupt_enable;	/* 0x40 */
-	u32 pad7;
-	u32 error_interrupt_offset;	/* 0x48 */
-	u32 pad8;
-	u32 error_status;		/* 0x50 */
-	u32 pad9;
-};
-
-struct vnic_wq_buf {
-	struct vnic_wq_buf *next;
-	dma_addr_t dma_addr;
-	void *os_buf;
-	unsigned int len;
-	unsigned int index;
-	int sop;
-	void *desc;
-};
-
-/* Break the vnic_wq_buf allocations into blocks of 32/64 entries */
-#define VNIC_WQ_BUF_MIN_BLK_ENTRIES 32
-#define VNIC_WQ_BUF_DFLT_BLK_ENTRIES 64
-#define VNIC_WQ_BUF_BLK_ENTRIES(entries) \
-	((unsigned int)((entries < VNIC_WQ_BUF_DFLT_BLK_ENTRIES) ? \
-	VNIC_WQ_BUF_MIN_BLK_ENTRIES : VNIC_WQ_BUF_DFLT_BLK_ENTRIES))
-#define VNIC_WQ_BUF_BLK_SZ(entries) \
-	(VNIC_WQ_BUF_BLK_ENTRIES(entries) * sizeof(struct vnic_wq_buf))
-#define VNIC_WQ_BUF_BLKS_NEEDED(entries) \
-	DIV_ROUND_UP(entries, VNIC_WQ_BUF_BLK_ENTRIES(entries))
-#define VNIC_WQ_BUF_BLKS_MAX VNIC_WQ_BUF_BLKS_NEEDED(4096)
-
-struct vnic_wq {
-	unsigned int index;
-	struct vnic_dev *vdev;
-	struct vnic_wq_ctrl __iomem *ctrl;              /* memory-mapped */
-	struct vnic_dev_ring ring;
-	struct vnic_wq_buf *bufs[VNIC_WQ_BUF_BLKS_MAX];
-	struct vnic_wq_buf *to_use;
-	struct vnic_wq_buf *to_clean;
-	unsigned int pkts_outstanding;
-};
-
-static inline unsigned int vnic_wq_desc_avail(struct vnic_wq *wq)
-{
-	/* how many does SW own? */
-	return wq->ring.desc_avail;
-}
-
-static inline unsigned int vnic_wq_desc_used(struct vnic_wq *wq)
-{
-	/* how many does HW own? */
-	return wq->ring.desc_count - wq->ring.desc_avail - 1;
-}
-
-static inline void *vnic_wq_next_desc(struct vnic_wq *wq)
-{
-	return wq->to_use->desc;
-}
-
-static inline void vnic_wq_post(struct vnic_wq *wq,
-	void *os_buf, dma_addr_t dma_addr,
-	unsigned int len, int sop, int eop)
-{
-	struct vnic_wq_buf *buf = wq->to_use;
-
-	buf->sop = sop;
-	buf->os_buf = eop ? os_buf : NULL;
-	buf->dma_addr = dma_addr;
-	buf->len = len;
-
-	buf = buf->next;
-	if (eop) {
-		/* Adding write memory barrier prevents compiler and/or CPU
-		 * reordering, thus avoiding descriptor posting before
-		 * descriptor is initialized. Otherwise, hardware can read
-		 * stale descriptor fields.
-		 */
-		wmb();
-		iowrite32(buf->index, &wq->ctrl->posted_index);
-	}
-	wq->to_use = buf;
-
-	wq->ring.desc_avail--;
-}
-
-static inline void vnic_wq_service(struct vnic_wq *wq,
-	struct cq_desc *cq_desc, u16 completed_index,
-	void (*buf_service)(struct vnic_wq *wq,
-	struct cq_desc *cq_desc, struct vnic_wq_buf *buf, void *opaque),
-	void *opaque)
-{
-	struct vnic_wq_buf *buf;
-
-	buf = wq->to_clean;
-	while (1) {
-
-		(*buf_service)(wq, cq_desc, buf, opaque);
-
-		wq->ring.desc_avail++;
-
-		wq->to_clean = buf->next;
-
-		if (buf->index == completed_index)
-			break;
-
-		buf = wq->to_clean;
-	}
-}
-
-void vnic_wq_free(struct vnic_wq *wq);
-int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index,
-	unsigned int desc_count, unsigned int desc_size);
-void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index,
-	unsigned int error_interrupt_enable,
-	unsigned int error_interrupt_offset);
-unsigned int vnic_wq_error_status(struct vnic_wq *wq);
-void vnic_wq_enable(struct vnic_wq *wq);
-int vnic_wq_disable(struct vnic_wq *wq);
-void vnic_wq_clean(struct vnic_wq *wq,
-	void (*buf_clean)(struct vnic_wq *wq, struct vnic_wq_buf *buf));
-
-#endif /* _VNIC_WQ_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/enic/wq_enet_desc.h linux-libre-3.2-gnu/drivers/net/enic/wq_enet_desc.h
--- linux-libre-3.1-gnu/drivers/net/enic/wq_enet_desc.h	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/enic/wq_enet_desc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +0,0 @@
-/*
- * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
- * Copyright 2007 Nuova 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 _WQ_ENET_DESC_H_
-#define _WQ_ENET_DESC_H_
-
-/* Ethernet work queue descriptor: 16B */
-struct wq_enet_desc {
-	__le64 address;
-	__le16 length;
-	__le16 mss_loopback;
-	__le16 header_length_flags;
-	__le16 vlan_tag;
-};
-
-#define WQ_ENET_ADDR_BITS		64
-#define WQ_ENET_LEN_BITS		14
-#define WQ_ENET_LEN_MASK		((1 << WQ_ENET_LEN_BITS) - 1)
-#define WQ_ENET_MSS_BITS		14
-#define WQ_ENET_MSS_MASK		((1 << WQ_ENET_MSS_BITS) - 1)
-#define WQ_ENET_MSS_SHIFT		2
-#define WQ_ENET_LOOPBACK_SHIFT		1
-#define WQ_ENET_HDRLEN_BITS		10
-#define WQ_ENET_HDRLEN_MASK		((1 << WQ_ENET_HDRLEN_BITS) - 1)
-#define WQ_ENET_FLAGS_OM_BITS		2
-#define WQ_ENET_FLAGS_OM_MASK		((1 << WQ_ENET_FLAGS_OM_BITS) - 1)
-#define WQ_ENET_FLAGS_EOP_SHIFT		12
-#define WQ_ENET_FLAGS_CQ_ENTRY_SHIFT	13
-#define WQ_ENET_FLAGS_FCOE_ENCAP_SHIFT	14
-#define WQ_ENET_FLAGS_VLAN_TAG_INSERT_SHIFT	15
-
-#define WQ_ENET_OFFLOAD_MODE_CSUM	0
-#define WQ_ENET_OFFLOAD_MODE_RESERVED	1
-#define WQ_ENET_OFFLOAD_MODE_CSUM_L4	2
-#define WQ_ENET_OFFLOAD_MODE_TSO	3
-
-static inline void wq_enet_desc_enc(struct wq_enet_desc *desc,
-	u64 address, u16 length, u16 mss, u16 header_length,
-	u8 offload_mode, u8 eop, u8 cq_entry, u8 fcoe_encap,
-	u8 vlan_tag_insert, u16 vlan_tag, u8 loopback)
-{
-	desc->address = cpu_to_le64(address);
-	desc->length = cpu_to_le16(length & WQ_ENET_LEN_MASK);
-	desc->mss_loopback = cpu_to_le16((mss & WQ_ENET_MSS_MASK) <<
-		WQ_ENET_MSS_SHIFT | (loopback & 1) << WQ_ENET_LOOPBACK_SHIFT);
-	desc->header_length_flags = cpu_to_le16(
-		(header_length & WQ_ENET_HDRLEN_MASK) |
-		(offload_mode & WQ_ENET_FLAGS_OM_MASK) << WQ_ENET_HDRLEN_BITS |
-		(eop & 1) << WQ_ENET_FLAGS_EOP_SHIFT |
-		(cq_entry & 1) << WQ_ENET_FLAGS_CQ_ENTRY_SHIFT |
-		(fcoe_encap & 1) << WQ_ENET_FLAGS_FCOE_ENCAP_SHIFT |
-		(vlan_tag_insert & 1) << WQ_ENET_FLAGS_VLAN_TAG_INSERT_SHIFT);
-	desc->vlan_tag = cpu_to_le16(vlan_tag);
-}
-
-static inline void wq_enet_desc_dec(struct wq_enet_desc *desc,
-	u64 *address, u16 *length, u16 *mss, u16 *header_length,
-	u8 *offload_mode, u8 *eop, u8 *cq_entry, u8 *fcoe_encap,
-	u8 *vlan_tag_insert, u16 *vlan_tag, u8 *loopback)
-{
-	*address = le64_to_cpu(desc->address);
-	*length = le16_to_cpu(desc->length) & WQ_ENET_LEN_MASK;
-	*mss = (le16_to_cpu(desc->mss_loopback) >> WQ_ENET_MSS_SHIFT) &
-		WQ_ENET_MSS_MASK;
-	*loopback = (u8)((le16_to_cpu(desc->mss_loopback) >>
-		WQ_ENET_LOOPBACK_SHIFT) & 1);
-	*header_length = le16_to_cpu(desc->header_length_flags) &
-		WQ_ENET_HDRLEN_MASK;
-	*offload_mode = (u8)((le16_to_cpu(desc->header_length_flags) >>
-		WQ_ENET_HDRLEN_BITS) & WQ_ENET_FLAGS_OM_MASK);
-	*eop = (u8)((le16_to_cpu(desc->header_length_flags) >>
-		WQ_ENET_FLAGS_EOP_SHIFT) & 1);
-	*cq_entry = (u8)((le16_to_cpu(desc->header_length_flags) >>
-		WQ_ENET_FLAGS_CQ_ENTRY_SHIFT) & 1);
-	*fcoe_encap = (u8)((le16_to_cpu(desc->header_length_flags) >>
-		WQ_ENET_FLAGS_FCOE_ENCAP_SHIFT) & 1);
-	*vlan_tag_insert = (u8)((le16_to_cpu(desc->header_length_flags) >>
-		WQ_ENET_FLAGS_VLAN_TAG_INSERT_SHIFT) & 1);
-	*vlan_tag = le16_to_cpu(desc->vlan_tag);
-}
-
-#endif /* _WQ_ENET_DESC_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/epic100.c linux-libre-3.2-gnu/drivers/net/epic100.c
--- linux-libre-3.1-gnu/drivers/net/epic100.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/epic100.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1609 +0,0 @@
-/* epic100.c: A SMC 83c170 EPIC/100 Fast Ethernet driver for Linux. */
-/*
-	Written/copyright 1997-2001 by Donald Becker.
-
-	This software may be used and distributed according to the terms of
-	the GNU General Public License (GPL), incorporated herein by reference.
-	Drivers based on or derived from this code fall under the GPL and must
-	retain the authorship, copyright and license notice.  This file is not
-	a complete program and may only be used when the entire operating
-	system is licensed under the GPL.
-
-	This driver is for the SMC83c170/175 "EPIC" series, as used on the
-	SMC EtherPower II 9432 PCI adapter, and several CardBus cards.
-
-	The author may be reached as becker@scyld.com, or C/O
-	Scyld Computing Corporation
-	410 Severn Ave., Suite 210
-	Annapolis MD 21403
-
-	Information and updates available at
-	http://www.scyld.com/network/epic100.html
-	[this link no longer provides anything useful -jgarzik]
-
-	---------------------------------------------------------------------
-
-*/
-
-#define DRV_NAME        "epic100"
-#define DRV_VERSION     "2.1"
-#define DRV_RELDATE     "Sept 11, 2006"
-
-/* The user-configurable values.
-   These may be modified when a driver module is loaded.*/
-
-static int debug = 1;			/* 1 normal messages, 0 quiet .. 7 verbose. */
-
-/* Used to pass the full-duplex flag, etc. */
-#define MAX_UNITS 8		/* More are supported, limit only on options */
-static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-
-/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
-   Setting to > 1518 effectively disables this feature. */
-static int rx_copybreak;
-
-/* Operational parameters that are set at compile time. */
-
-/* Keep the ring sizes a power of two for operational efficiency.
-   The compiler will convert <unsigned>'%'<2^N> into a bit mask.
-   Making the Tx ring too large decreases the effectiveness of channel
-   bonding and packet priority.
-   There are no ill effects from too-large receive rings. */
-#define TX_RING_SIZE	256
-#define TX_QUEUE_LEN	240		/* Limit ring entries actually used.  */
-#define RX_RING_SIZE	256
-#define TX_TOTAL_SIZE	TX_RING_SIZE*sizeof(struct epic_tx_desc)
-#define RX_TOTAL_SIZE	RX_RING_SIZE*sizeof(struct epic_rx_desc)
-
-/* Operational parameters that usually are not changed. */
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  (2*HZ)
-
-#define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
-
-/* Bytes transferred to chip before transmission starts. */
-/* Initial threshold, increased on underflow, rounded down to 4 byte units. */
-#define TX_FIFO_THRESH 256
-#define RX_FIFO_THRESH 1		/* 0-3, 0==32, 64,96, or 3==128 bytes  */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-#include <linux/crc32.h>
-#include <linux/bitops.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/byteorder.h>
-
-/* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
-DRV_NAME ".c:v1.11 1/7/2001 Written by Donald Becker <becker@scyld.com>\n";
-static char version2[] __devinitdata =
-"  (unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
-
-MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
-MODULE_DESCRIPTION("SMC 83c170 EPIC series Ethernet driver");
-MODULE_LICENSE("GPL");
-
-module_param(debug, int, 0);
-module_param(rx_copybreak, int, 0);
-module_param_array(options, int, NULL, 0);
-module_param_array(full_duplex, int, NULL, 0);
-MODULE_PARM_DESC(debug, "EPIC/100 debug level (0-5)");
-MODULE_PARM_DESC(options, "EPIC/100: Bits 0-3: media type, bit 4: full duplex");
-MODULE_PARM_DESC(rx_copybreak, "EPIC/100 copy breakpoint for copy-only-tiny-frames");
-MODULE_PARM_DESC(full_duplex, "EPIC/100 full duplex setting(s) (1)");
-
-/*
-				Theory of Operation
-
-I. Board Compatibility
-
-This device driver is designed for the SMC "EPIC/100", the SMC
-single-chip Ethernet controllers for PCI.  This chip is used on
-the SMC EtherPower II boards.
-
-II. Board-specific settings
-
-PCI bus devices are configured by the system at boot time, so no jumpers
-need to be set on the board.  The system BIOS will assign the
-PCI INTA signal to a (preferably otherwise unused) system IRQ line.
-Note: Kernel versions earlier than 1.3.73 do not support shared PCI
-interrupt lines.
-
-III. Driver operation
-
-IIIa. Ring buffers
-
-IVb. References
-
-http://www.smsc.com/media/Downloads_Public/discontinued/83c171.pdf
-http://www.smsc.com/media/Downloads_Public/discontinued/83c175.pdf
-http://scyld.com/expert/NWay.html
-http://www.national.com/pf/DP/DP83840A.html
-
-IVc. Errata
-
-*/
-
-
-enum chip_capability_flags { MII_PWRDWN=1, TYPE2_INTR=2, NO_MII=4 };
-
-#define EPIC_TOTAL_SIZE 0x100
-#define USE_IO_OPS 1
-
-typedef enum {
-	SMSC_83C170_0,
-	SMSC_83C170,
-	SMSC_83C175,
-} chip_t;
-
-
-struct epic_chip_info {
-	const char *name;
-        int drv_flags;                          /* Driver use, intended as capability flags. */
-};
-
-
-/* indexed by chip_t */
-static const struct epic_chip_info pci_id_tbl[] = {
-	{ "SMSC EPIC/100 83c170",	TYPE2_INTR | NO_MII | MII_PWRDWN },
-	{ "SMSC EPIC/100 83c170",	TYPE2_INTR },
-	{ "SMSC EPIC/C 83c175",		TYPE2_INTR | MII_PWRDWN },
-};
-
-
-static DEFINE_PCI_DEVICE_TABLE(epic_pci_tbl) = {
-	{ 0x10B8, 0x0005, 0x1092, 0x0AB4, 0, 0, SMSC_83C170_0 },
-	{ 0x10B8, 0x0005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMSC_83C170 },
-	{ 0x10B8, 0x0006, PCI_ANY_ID, PCI_ANY_ID,
-	  PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, SMSC_83C175 },
-	{ 0,}
-};
-MODULE_DEVICE_TABLE (pci, epic_pci_tbl);
-
-
-#ifndef USE_IO_OPS
-#undef inb
-#undef inw
-#undef inl
-#undef outb
-#undef outw
-#undef outl
-#define inb readb
-#define inw readw
-#define inl readl
-#define outb writeb
-#define outw writew
-#define outl writel
-#endif
-
-/* Offsets to registers, using the (ugh) SMC names. */
-enum epic_registers {
-  COMMAND=0, INTSTAT=4, INTMASK=8, GENCTL=0x0C, NVCTL=0x10, EECTL=0x14,
-  PCIBurstCnt=0x18,
-  TEST1=0x1C, CRCCNT=0x20, ALICNT=0x24, MPCNT=0x28,	/* Rx error counters. */
-  MIICtrl=0x30, MIIData=0x34, MIICfg=0x38,
-  LAN0=64,						/* MAC address. */
-  MC0=80,						/* Multicast filter table. */
-  RxCtrl=96, TxCtrl=112, TxSTAT=0x74,
-  PRxCDAR=0x84, RxSTAT=0xA4, EarlyRx=0xB0, PTxCDAR=0xC4, TxThresh=0xDC,
-};
-
-/* Interrupt register bits, using my own meaningful names. */
-enum IntrStatus {
-	TxIdle=0x40000, RxIdle=0x20000, IntrSummary=0x010000,
-	PCIBusErr170=0x7000, PCIBusErr175=0x1000, PhyEvent175=0x8000,
-	RxStarted=0x0800, RxEarlyWarn=0x0400, CntFull=0x0200, TxUnderrun=0x0100,
-	TxEmpty=0x0080, TxDone=0x0020, RxError=0x0010,
-	RxOverflow=0x0008, RxFull=0x0004, RxHeader=0x0002, RxDone=0x0001,
-};
-enum CommandBits {
-	StopRx=1, StartRx=2, TxQueued=4, RxQueued=8,
-	StopTxDMA=0x20, StopRxDMA=0x40, RestartTx=0x80,
-};
-
-#define EpicRemoved	0xffffffff	/* Chip failed or removed (CardBus) */
-
-#define EpicNapiEvent	(TxEmpty | TxDone | \
-			 RxDone | RxStarted | RxEarlyWarn | RxOverflow | RxFull)
-#define EpicNormalEvent	(0x0000ffff & ~EpicNapiEvent)
-
-static const u16 media2miictl[16] = {
-	0, 0x0C00, 0x0C00, 0x2000,  0x0100, 0x2100, 0, 0,
-	0, 0, 0, 0,  0, 0, 0, 0 };
-
-/*
- * The EPIC100 Rx and Tx buffer descriptors.  Note that these
- * really ARE host-endian; it's not a misannotation.  We tell
- * the card to byteswap them internally on big-endian hosts -
- * look for #ifdef __BIG_ENDIAN in epic_open().
- */
-
-struct epic_tx_desc {
-	u32 txstatus;
-	u32 bufaddr;
-	u32 buflength;
-	u32 next;
-};
-
-struct epic_rx_desc {
-	u32 rxstatus;
-	u32 bufaddr;
-	u32 buflength;
-	u32 next;
-};
-
-enum desc_status_bits {
-	DescOwn=0x8000,
-};
-
-#define PRIV_ALIGN	15 	/* Required alignment mask */
-struct epic_private {
-	struct epic_rx_desc *rx_ring;
-	struct epic_tx_desc *tx_ring;
-	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
-	struct sk_buff* tx_skbuff[TX_RING_SIZE];
-	/* The addresses of receive-in-place skbuffs. */
-	struct sk_buff* rx_skbuff[RX_RING_SIZE];
-
-	dma_addr_t tx_ring_dma;
-	dma_addr_t rx_ring_dma;
-
-	/* Ring pointers. */
-	spinlock_t lock;				/* Group with Tx control cache line. */
-	spinlock_t napi_lock;
-	struct napi_struct napi;
-	unsigned int reschedule_in_poll;
-	unsigned int cur_tx, dirty_tx;
-
-	unsigned int cur_rx, dirty_rx;
-	u32 irq_mask;
-	unsigned int rx_buf_sz;				/* Based on MTU+slack. */
-
-	struct pci_dev *pci_dev;			/* PCI bus location. */
-	int chip_id, chip_flags;
-
-	struct timer_list timer;			/* Media selection timer. */
-	int tx_threshold;
-	unsigned char mc_filter[8];
-	signed char phys[4];				/* MII device addresses. */
-	u16 advertising;					/* NWay media advertisement */
-	int mii_phy_cnt;
-	struct mii_if_info mii;
-	unsigned int tx_full:1;				/* The Tx queue is full. */
-	unsigned int default_port:4;		/* Last dev->if_port value. */
-};
-
-static int epic_open(struct net_device *dev);
-static int read_eeprom(long ioaddr, int location);
-static int mdio_read(struct net_device *dev, int phy_id, int location);
-static void mdio_write(struct net_device *dev, int phy_id, int loc, int val);
-static void epic_restart(struct net_device *dev);
-static void epic_timer(unsigned long data);
-static void epic_tx_timeout(struct net_device *dev);
-static void epic_init_ring(struct net_device *dev);
-static netdev_tx_t epic_start_xmit(struct sk_buff *skb,
-				   struct net_device *dev);
-static int epic_rx(struct net_device *dev, int budget);
-static int epic_poll(struct napi_struct *napi, int budget);
-static irqreturn_t epic_interrupt(int irq, void *dev_instance);
-static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static const struct ethtool_ops netdev_ethtool_ops;
-static int epic_close(struct net_device *dev);
-static struct net_device_stats *epic_get_stats(struct net_device *dev);
-static void set_rx_mode(struct net_device *dev);
-
-static const struct net_device_ops epic_netdev_ops = {
-	.ndo_open		= epic_open,
-	.ndo_stop		= epic_close,
-	.ndo_start_xmit		= epic_start_xmit,
-	.ndo_tx_timeout 	= epic_tx_timeout,
-	.ndo_get_stats		= epic_get_stats,
-	.ndo_set_multicast_list = set_rx_mode,
-	.ndo_do_ioctl 		= netdev_ioctl,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-static int __devinit epic_init_one (struct pci_dev *pdev,
-				    const struct pci_device_id *ent)
-{
-	static int card_idx = -1;
-	long ioaddr;
-	int chip_idx = (int) ent->driver_data;
-	int irq;
-	struct net_device *dev;
-	struct epic_private *ep;
-	int i, ret, option = 0, duplex = 0;
-	void *ring_space;
-	dma_addr_t ring_dma;
-
-/* when built into the kernel, we only print version if device is found */
-#ifndef MODULE
-	static int printed_version;
-	if (!printed_version++)
-		printk(KERN_INFO "%s%s", version, version2);
-#endif
-
-	card_idx++;
-
-	ret = pci_enable_device(pdev);
-	if (ret)
-		goto out;
-	irq = pdev->irq;
-
-	if (pci_resource_len(pdev, 0) < EPIC_TOTAL_SIZE) {
-		dev_err(&pdev->dev, "no PCI region space\n");
-		ret = -ENODEV;
-		goto err_out_disable;
-	}
-
-	pci_set_master(pdev);
-
-	ret = pci_request_regions(pdev, DRV_NAME);
-	if (ret < 0)
-		goto err_out_disable;
-
-	ret = -ENOMEM;
-
-	dev = alloc_etherdev(sizeof (*ep));
-	if (!dev) {
-		dev_err(&pdev->dev, "no memory for eth device\n");
-		goto err_out_free_res;
-	}
-	SET_NETDEV_DEV(dev, &pdev->dev);
-
-#ifdef USE_IO_OPS
-	ioaddr = pci_resource_start (pdev, 0);
-#else
-	ioaddr = pci_resource_start (pdev, 1);
-	ioaddr = (long) pci_ioremap_bar(pdev, 1);
-	if (!ioaddr) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		goto err_out_free_netdev;
-	}
-#endif
-
-	pci_set_drvdata(pdev, dev);
-	ep = netdev_priv(dev);
-	ep->mii.dev = dev;
-	ep->mii.mdio_read = mdio_read;
-	ep->mii.mdio_write = mdio_write;
-	ep->mii.phy_id_mask = 0x1f;
-	ep->mii.reg_num_mask = 0x1f;
-
-	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
-	if (!ring_space)
-		goto err_out_iounmap;
-	ep->tx_ring = ring_space;
-	ep->tx_ring_dma = ring_dma;
-
-	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
-	if (!ring_space)
-		goto err_out_unmap_tx;
-	ep->rx_ring = ring_space;
-	ep->rx_ring_dma = ring_dma;
-
-	if (dev->mem_start) {
-		option = dev->mem_start;
-		duplex = (dev->mem_start & 16) ? 1 : 0;
-	} else if (card_idx >= 0  &&  card_idx < MAX_UNITS) {
-		if (options[card_idx] >= 0)
-			option = options[card_idx];
-		if (full_duplex[card_idx] >= 0)
-			duplex = full_duplex[card_idx];
-	}
-
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-
-	spin_lock_init(&ep->lock);
-	spin_lock_init(&ep->napi_lock);
-	ep->reschedule_in_poll = 0;
-
-	/* Bring the chip out of low-power mode. */
-	outl(0x4200, ioaddr + GENCTL);
-	/* Magic?!  If we don't set this bit the MII interface won't work. */
-	/* This magic is documented in SMSC app note 7.15 */
-	for (i = 16; i > 0; i--)
-		outl(0x0008, ioaddr + TEST1);
-
-	/* Turn on the MII transceiver. */
-	outl(0x12, ioaddr + MIICfg);
-	if (chip_idx == 1)
-		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
-	outl(0x0200, ioaddr + GENCTL);
-
-	/* Note: the '175 does not have a serial EEPROM. */
-	for (i = 0; i < 3; i++)
-		((__le16 *)dev->dev_addr)[i] = cpu_to_le16(inw(ioaddr + LAN0 + i*4));
-
-	if (debug > 2) {
-		dev_printk(KERN_DEBUG, &pdev->dev, "EEPROM contents:\n");
-		for (i = 0; i < 64; i++)
-			printk(" %4.4x%s", read_eeprom(ioaddr, i),
-				   i % 16 == 15 ? "\n" : "");
-	}
-
-	ep->pci_dev = pdev;
-	ep->chip_id = chip_idx;
-	ep->chip_flags = pci_id_tbl[chip_idx].drv_flags;
-	ep->irq_mask =
-		(ep->chip_flags & TYPE2_INTR ?  PCIBusErr175 : PCIBusErr170)
-		 | CntFull | TxUnderrun | EpicNapiEvent;
-
-	/* Find the connected MII xcvrs.
-	   Doing this in open() would allow detecting external xcvrs later, but
-	   takes much time and no cards have external MII. */
-	{
-		int phy, phy_idx = 0;
-		for (phy = 1; phy < 32 && phy_idx < sizeof(ep->phys); phy++) {
-			int mii_status = mdio_read(dev, phy, MII_BMSR);
-			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
-				ep->phys[phy_idx++] = phy;
-				dev_info(&pdev->dev,
-					"MII transceiver #%d control "
-					"%4.4x status %4.4x.\n",
-					phy, mdio_read(dev, phy, 0), mii_status);
-			}
-		}
-		ep->mii_phy_cnt = phy_idx;
-		if (phy_idx != 0) {
-			phy = ep->phys[0];
-			ep->mii.advertising = mdio_read(dev, phy, MII_ADVERTISE);
-			dev_info(&pdev->dev,
-				"Autonegotiation advertising %4.4x link "
-				   "partner %4.4x.\n",
-				   ep->mii.advertising, mdio_read(dev, phy, 5));
-		} else if ( ! (ep->chip_flags & NO_MII)) {
-			dev_warn(&pdev->dev,
-				"***WARNING***: No MII transceiver found!\n");
-			/* Use the known PHY address of the EPII. */
-			ep->phys[0] = 3;
-		}
-		ep->mii.phy_id = ep->phys[0];
-	}
-
-	/* Turn off the MII xcvr (175 only!), leave the chip in low-power mode. */
-	if (ep->chip_flags & MII_PWRDWN)
-		outl(inl(ioaddr + NVCTL) & ~0x483C, ioaddr + NVCTL);
-	outl(0x0008, ioaddr + GENCTL);
-
-	/* The lower four bits are the media type. */
-	if (duplex) {
-		ep->mii.force_media = ep->mii.full_duplex = 1;
-		dev_info(&pdev->dev, "Forced full duplex requested.\n");
-	}
-	dev->if_port = ep->default_port = option;
-
-	/* The Epic-specific entries in the device structure. */
-	dev->netdev_ops = &epic_netdev_ops;
-	dev->ethtool_ops = &netdev_ethtool_ops;
-	dev->watchdog_timeo = TX_TIMEOUT;
-	netif_napi_add(dev, &ep->napi, epic_poll, 64);
-
-	ret = register_netdev(dev);
-	if (ret < 0)
-		goto err_out_unmap_rx;
-
-	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, %pM\n",
-	       dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq,
-	       dev->dev_addr);
-
-out:
-	return ret;
-
-err_out_unmap_rx:
-	pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma);
-err_out_unmap_tx:
-	pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma);
-err_out_iounmap:
-#ifndef USE_IO_OPS
-	iounmap(ioaddr);
-err_out_free_netdev:
-#endif
-	free_netdev(dev);
-err_out_free_res:
-	pci_release_regions(pdev);
-err_out_disable:
-	pci_disable_device(pdev);
-	goto out;
-}
-
-/* Serial EEPROM section. */
-
-/*  EEPROM_Ctrl bits. */
-#define EE_SHIFT_CLK	0x04	/* EEPROM shift clock. */
-#define EE_CS			0x02	/* EEPROM chip select. */
-#define EE_DATA_WRITE	0x08	/* EEPROM chip data in. */
-#define EE_WRITE_0		0x01
-#define EE_WRITE_1		0x09
-#define EE_DATA_READ	0x10	/* EEPROM chip data out. */
-#define EE_ENB			(0x0001 | EE_CS)
-
-/* Delay between EEPROM clock transitions.
-   This serves to flush the operation to the PCI bus.
- */
-
-#define eeprom_delay()	inl(ee_addr)
-
-/* The EEPROM commands include the alway-set leading bit. */
-#define EE_WRITE_CMD	(5 << 6)
-#define EE_READ64_CMD	(6 << 6)
-#define EE_READ256_CMD	(6 << 8)
-#define EE_ERASE_CMD	(7 << 6)
-
-static void epic_disable_int(struct net_device *dev, struct epic_private *ep)
-{
-	long ioaddr = dev->base_addr;
-
-	outl(0x00000000, ioaddr + INTMASK);
-}
-
-static inline void __epic_pci_commit(long ioaddr)
-{
-#ifndef USE_IO_OPS
-	inl(ioaddr + INTMASK);
-#endif
-}
-
-static inline void epic_napi_irq_off(struct net_device *dev,
-				     struct epic_private *ep)
-{
-	long ioaddr = dev->base_addr;
-
-	outl(ep->irq_mask & ~EpicNapiEvent, ioaddr + INTMASK);
-	__epic_pci_commit(ioaddr);
-}
-
-static inline void epic_napi_irq_on(struct net_device *dev,
-				    struct epic_private *ep)
-{
-	long ioaddr = dev->base_addr;
-
-	/* No need to commit possible posted write */
-	outl(ep->irq_mask | EpicNapiEvent, ioaddr + INTMASK);
-}
-
-static int __devinit read_eeprom(long ioaddr, int location)
-{
-	int i;
-	int retval = 0;
-	long ee_addr = ioaddr + EECTL;
-	int read_cmd = location |
-		(inl(ee_addr) & 0x40 ? EE_READ64_CMD : EE_READ256_CMD);
-
-	outl(EE_ENB & ~EE_CS, ee_addr);
-	outl(EE_ENB, ee_addr);
-
-	/* Shift the read command bits out. */
-	for (i = 12; i >= 0; i--) {
-		short dataval = (read_cmd & (1 << i)) ? EE_WRITE_1 : EE_WRITE_0;
-		outl(EE_ENB | dataval, ee_addr);
-		eeprom_delay();
-		outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
-		eeprom_delay();
-	}
-	outl(EE_ENB, ee_addr);
-
-	for (i = 16; i > 0; i--) {
-		outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
-		eeprom_delay();
-		retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
-		outl(EE_ENB, ee_addr);
-		eeprom_delay();
-	}
-
-	/* Terminate the EEPROM access. */
-	outl(EE_ENB & ~EE_CS, ee_addr);
-	return retval;
-}
-
-#define MII_READOP		1
-#define MII_WRITEOP		2
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
-	long ioaddr = dev->base_addr;
-	int read_cmd = (phy_id << 9) | (location << 4) | MII_READOP;
-	int i;
-
-	outl(read_cmd, ioaddr + MIICtrl);
-	/* Typical operation takes 25 loops. */
-	for (i = 400; i > 0; i--) {
-		barrier();
-		if ((inl(ioaddr + MIICtrl) & MII_READOP) == 0) {
-			/* Work around read failure bug. */
-			if (phy_id == 1 && location < 6 &&
-			    inw(ioaddr + MIIData) == 0xffff) {
-				outl(read_cmd, ioaddr + MIICtrl);
-				continue;
-			}
-			return inw(ioaddr + MIIData);
-		}
-	}
-	return 0xffff;
-}
-
-static void mdio_write(struct net_device *dev, int phy_id, int loc, int value)
-{
-	long ioaddr = dev->base_addr;
-	int i;
-
-	outw(value, ioaddr + MIIData);
-	outl((phy_id << 9) | (loc << 4) | MII_WRITEOP, ioaddr + MIICtrl);
-	for (i = 10000; i > 0; i--) {
-		barrier();
-		if ((inl(ioaddr + MIICtrl) & MII_WRITEOP) == 0)
-			break;
-	}
-}
-
-
-static int epic_open(struct net_device *dev)
-{
-	struct epic_private *ep = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	int i;
-	int retval;
-
-	/* Soft reset the chip. */
-	outl(0x4001, ioaddr + GENCTL);
-
-	napi_enable(&ep->napi);
-	if ((retval = request_irq(dev->irq, epic_interrupt, IRQF_SHARED, dev->name, dev))) {
-		napi_disable(&ep->napi);
-		return retval;
-	}
-
-	epic_init_ring(dev);
-
-	outl(0x4000, ioaddr + GENCTL);
-	/* This magic is documented in SMSC app note 7.15 */
-	for (i = 16; i > 0; i--)
-		outl(0x0008, ioaddr + TEST1);
-
-	/* Pull the chip out of low-power mode, enable interrupts, and set for
-	   PCI read multiple.  The MIIcfg setting and strange write order are
-	   required by the details of which bits are reset and the transceiver
-	   wiring on the Ositech CardBus card.
-	*/
-#if 0
-	outl(dev->if_port == 1 ? 0x13 : 0x12, ioaddr + MIICfg);
-#endif
-	if (ep->chip_flags & MII_PWRDWN)
-		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
-
-	/* Tell the chip to byteswap descriptors on big-endian hosts */
-#ifdef __BIG_ENDIAN
-	outl(0x4432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
-	inl(ioaddr + GENCTL);
-	outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
-#else
-	outl(0x4412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
-	inl(ioaddr + GENCTL);
-	outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
-#endif
-
-	udelay(20); /* Looks like EPII needs that if you want reliable RX init. FIXME: pci posting bug? */
-
-	for (i = 0; i < 3; i++)
-		outl(le16_to_cpu(((__le16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4);
-
-	ep->tx_threshold = TX_FIFO_THRESH;
-	outl(ep->tx_threshold, ioaddr + TxThresh);
-
-	if (media2miictl[dev->if_port & 15]) {
-		if (ep->mii_phy_cnt)
-			mdio_write(dev, ep->phys[0], MII_BMCR, media2miictl[dev->if_port&15]);
-		if (dev->if_port == 1) {
-			if (debug > 1)
-				printk(KERN_INFO "%s: Using the 10base2 transceiver, MII "
-					   "status %4.4x.\n",
-					   dev->name, mdio_read(dev, ep->phys[0], MII_BMSR));
-		}
-	} else {
-		int mii_lpa = mdio_read(dev, ep->phys[0], MII_LPA);
-		if (mii_lpa != 0xffff) {
-			if ((mii_lpa & LPA_100FULL) || (mii_lpa & 0x01C0) == LPA_10FULL)
-				ep->mii.full_duplex = 1;
-			else if (! (mii_lpa & LPA_LPACK))
-				mdio_write(dev, ep->phys[0], MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART);
-			if (debug > 1)
-				printk(KERN_INFO "%s: Setting %s-duplex based on MII xcvr %d"
-					   " register read of %4.4x.\n", dev->name,
-					   ep->mii.full_duplex ? "full" : "half",
-					   ep->phys[0], mii_lpa);
-		}
-	}
-
-	outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
-	outl(ep->rx_ring_dma, ioaddr + PRxCDAR);
-	outl(ep->tx_ring_dma, ioaddr + PTxCDAR);
-
-	/* Start the chip's Rx process. */
-	set_rx_mode(dev);
-	outl(StartRx | RxQueued, ioaddr + COMMAND);
-
-	netif_start_queue(dev);
-
-	/* Enable interrupts by setting the interrupt mask. */
-	outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
-		 | CntFull | TxUnderrun
-		 | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK);
-
-	if (debug > 1)
-		printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x "
-			   "%s-duplex.\n",
-			   dev->name, ioaddr, dev->irq, (int)inl(ioaddr + GENCTL),
-			   ep->mii.full_duplex ? "full" : "half");
-
-	/* Set the timer to switch to check for link beat and perhaps switch
-	   to an alternate media type. */
-	init_timer(&ep->timer);
-	ep->timer.expires = jiffies + 3*HZ;
-	ep->timer.data = (unsigned long)dev;
-	ep->timer.function = epic_timer;				/* timer handler */
-	add_timer(&ep->timer);
-
-	return 0;
-}
-
-/* Reset the chip to recover from a PCI transaction error.
-   This may occur at interrupt time. */
-static void epic_pause(struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-
-	netif_stop_queue (dev);
-
-	/* Disable interrupts by clearing the interrupt mask. */
-	outl(0x00000000, ioaddr + INTMASK);
-	/* Stop the chip's Tx and Rx DMA processes. */
-	outw(StopRx | StopTxDMA | StopRxDMA, ioaddr + COMMAND);
-
-	/* Update the error counts. */
-	if (inw(ioaddr + COMMAND) != 0xffff) {
-		dev->stats.rx_missed_errors += inb(ioaddr + MPCNT);
-		dev->stats.rx_frame_errors += inb(ioaddr + ALICNT);
-		dev->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
-	}
-
-	/* Remove the packets on the Rx queue. */
-	epic_rx(dev, RX_RING_SIZE);
-}
-
-static void epic_restart(struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-	struct epic_private *ep = netdev_priv(dev);
-	int i;
-
-	/* Soft reset the chip. */
-	outl(0x4001, ioaddr + GENCTL);
-
-	printk(KERN_DEBUG "%s: Restarting the EPIC chip, Rx %d/%d Tx %d/%d.\n",
-		   dev->name, ep->cur_rx, ep->dirty_rx, ep->dirty_tx, ep->cur_tx);
-	udelay(1);
-
-	/* This magic is documented in SMSC app note 7.15 */
-	for (i = 16; i > 0; i--)
-		outl(0x0008, ioaddr + TEST1);
-
-#ifdef __BIG_ENDIAN
-	outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
-#else
-	outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
-#endif
-	outl(dev->if_port == 1 ? 0x13 : 0x12, ioaddr + MIICfg);
-	if (ep->chip_flags & MII_PWRDWN)
-		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
-
-	for (i = 0; i < 3; i++)
-		outl(le16_to_cpu(((__le16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4);
-
-	ep->tx_threshold = TX_FIFO_THRESH;
-	outl(ep->tx_threshold, ioaddr + TxThresh);
-	outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
-	outl(ep->rx_ring_dma + (ep->cur_rx%RX_RING_SIZE)*
-		sizeof(struct epic_rx_desc), ioaddr + PRxCDAR);
-	outl(ep->tx_ring_dma + (ep->dirty_tx%TX_RING_SIZE)*
-		 sizeof(struct epic_tx_desc), ioaddr + PTxCDAR);
-
-	/* Start the chip's Rx process. */
-	set_rx_mode(dev);
-	outl(StartRx | RxQueued, ioaddr + COMMAND);
-
-	/* Enable interrupts by setting the interrupt mask. */
-	outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
-		 | CntFull | TxUnderrun
-		 | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK);
-
-	printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x"
-		   " interrupt %4.4x.\n",
-		   dev->name, (int)inl(ioaddr + COMMAND), (int)inl(ioaddr + GENCTL),
-		   (int)inl(ioaddr + INTSTAT));
-}
-
-static void check_media(struct net_device *dev)
-{
-	struct epic_private *ep = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	int mii_lpa = ep->mii_phy_cnt ? mdio_read(dev, ep->phys[0], MII_LPA) : 0;
-	int negotiated = mii_lpa & ep->mii.advertising;
-	int duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
-
-	if (ep->mii.force_media)
-		return;
-	if (mii_lpa == 0xffff)		/* Bogus read */
-		return;
-	if (ep->mii.full_duplex != duplex) {
-		ep->mii.full_duplex = duplex;
-		printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link"
-			   " partner capability of %4.4x.\n", dev->name,
-			   ep->mii.full_duplex ? "full" : "half", ep->phys[0], mii_lpa);
-		outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
-	}
-}
-
-static void epic_timer(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *)data;
-	struct epic_private *ep = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	int next_tick = 5*HZ;
-
-	if (debug > 3) {
-		printk(KERN_DEBUG "%s: Media monitor tick, Tx status %8.8x.\n",
-			   dev->name, (int)inl(ioaddr + TxSTAT));
-		printk(KERN_DEBUG "%s: Other registers are IntMask %4.4x "
-			   "IntStatus %4.4x RxStatus %4.4x.\n",
-			   dev->name, (int)inl(ioaddr + INTMASK),
-			   (int)inl(ioaddr + INTSTAT), (int)inl(ioaddr + RxSTAT));
-	}
-
-	check_media(dev);
-
-	ep->timer.expires = jiffies + next_tick;
-	add_timer(&ep->timer);
-}
-
-static void epic_tx_timeout(struct net_device *dev)
-{
-	struct epic_private *ep = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-
-	if (debug > 0) {
-		printk(KERN_WARNING "%s: Transmit timeout using MII device, "
-			   "Tx status %4.4x.\n",
-			   dev->name, (int)inw(ioaddr + TxSTAT));
-		if (debug > 1) {
-			printk(KERN_DEBUG "%s: Tx indices: dirty_tx %d, cur_tx %d.\n",
-				   dev->name, ep->dirty_tx, ep->cur_tx);
-		}
-	}
-	if (inw(ioaddr + TxSTAT) & 0x10) {		/* Tx FIFO underflow. */
-		dev->stats.tx_fifo_errors++;
-		outl(RestartTx, ioaddr + COMMAND);
-	} else {
-		epic_restart(dev);
-		outl(TxQueued, dev->base_addr + COMMAND);
-	}
-
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	dev->stats.tx_errors++;
-	if (!ep->tx_full)
-		netif_wake_queue(dev);
-}
-
-/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void epic_init_ring(struct net_device *dev)
-{
-	struct epic_private *ep = netdev_priv(dev);
-	int i;
-
-	ep->tx_full = 0;
-	ep->dirty_tx = ep->cur_tx = 0;
-	ep->cur_rx = ep->dirty_rx = 0;
-	ep->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
-
-	/* Initialize all Rx descriptors. */
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		ep->rx_ring[i].rxstatus = 0;
-		ep->rx_ring[i].buflength = ep->rx_buf_sz;
-		ep->rx_ring[i].next = ep->rx_ring_dma +
-				      (i+1)*sizeof(struct epic_rx_desc);
-		ep->rx_skbuff[i] = NULL;
-	}
-	/* Mark the last entry as wrapping the ring. */
-	ep->rx_ring[i-1].next = ep->rx_ring_dma;
-
-	/* Fill in the Rx buffers.  Handle allocation failure gracefully. */
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		struct sk_buff *skb = dev_alloc_skb(ep->rx_buf_sz + 2);
-		ep->rx_skbuff[i] = skb;
-		if (skb == NULL)
-			break;
-		skb_reserve(skb, 2);	/* 16 byte align the IP header. */
-		ep->rx_ring[i].bufaddr = pci_map_single(ep->pci_dev,
-			skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
-		ep->rx_ring[i].rxstatus = DescOwn;
-	}
-	ep->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
-
-	/* The Tx buffer descriptor is filled in as needed, but we
-	   do need to clear the ownership bit. */
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		ep->tx_skbuff[i] = NULL;
-		ep->tx_ring[i].txstatus = 0x0000;
-		ep->tx_ring[i].next = ep->tx_ring_dma +
-			(i+1)*sizeof(struct epic_tx_desc);
-	}
-	ep->tx_ring[i-1].next = ep->tx_ring_dma;
-}
-
-static netdev_tx_t epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct epic_private *ep = netdev_priv(dev);
-	int entry, free_count;
-	u32 ctrl_word;
-	unsigned long flags;
-
-	if (skb_padto(skb, ETH_ZLEN))
-		return NETDEV_TX_OK;
-
-	/* Caution: the write order is important here, set the field with the
-	   "ownership" bit last. */
-
-	/* Calculate the next Tx descriptor entry. */
-	spin_lock_irqsave(&ep->lock, flags);
-	free_count = ep->cur_tx - ep->dirty_tx;
-	entry = ep->cur_tx % TX_RING_SIZE;
-
-	ep->tx_skbuff[entry] = skb;
-	ep->tx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, skb->data,
-		 			            skb->len, PCI_DMA_TODEVICE);
-	if (free_count < TX_QUEUE_LEN/2) {/* Typical path */
-		ctrl_word = 0x100000; /* No interrupt */
-	} else if (free_count == TX_QUEUE_LEN/2) {
-		ctrl_word = 0x140000; /* Tx-done intr. */
-	} else if (free_count < TX_QUEUE_LEN - 1) {
-		ctrl_word = 0x100000; /* No Tx-done intr. */
-	} else {
-		/* Leave room for an additional entry. */
-		ctrl_word = 0x140000; /* Tx-done intr. */
-		ep->tx_full = 1;
-	}
-	ep->tx_ring[entry].buflength = ctrl_word | skb->len;
-	ep->tx_ring[entry].txstatus =
-		((skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN) << 16)
-			    | DescOwn;
-
-	ep->cur_tx++;
-	if (ep->tx_full)
-		netif_stop_queue(dev);
-
-	spin_unlock_irqrestore(&ep->lock, flags);
-	/* Trigger an immediate transmit demand. */
-	outl(TxQueued, dev->base_addr + COMMAND);
-
-	if (debug > 4)
-		printk(KERN_DEBUG "%s: Queued Tx packet size %d to slot %d, "
-			   "flag %2.2x Tx status %8.8x.\n",
-			   dev->name, (int)skb->len, entry, ctrl_word,
-			   (int)inl(dev->base_addr + TxSTAT));
-
-	return NETDEV_TX_OK;
-}
-
-static void epic_tx_error(struct net_device *dev, struct epic_private *ep,
-			  int status)
-{
-	struct net_device_stats *stats = &dev->stats;
-
-#ifndef final_version
-	/* There was an major error, log it. */
-	if (debug > 1)
-		printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
-		       dev->name, status);
-#endif
-	stats->tx_errors++;
-	if (status & 0x1050)
-		stats->tx_aborted_errors++;
-	if (status & 0x0008)
-		stats->tx_carrier_errors++;
-	if (status & 0x0040)
-		stats->tx_window_errors++;
-	if (status & 0x0010)
-		stats->tx_fifo_errors++;
-}
-
-static void epic_tx(struct net_device *dev, struct epic_private *ep)
-{
-	unsigned int dirty_tx, cur_tx;
-
-	/*
-	 * Note: if this lock becomes a problem we can narrow the locked
-	 * region at the cost of occasionally grabbing the lock more times.
-	 */
-	cur_tx = ep->cur_tx;
-	for (dirty_tx = ep->dirty_tx; cur_tx - dirty_tx > 0; dirty_tx++) {
-		struct sk_buff *skb;
-		int entry = dirty_tx % TX_RING_SIZE;
-		int txstatus = ep->tx_ring[entry].txstatus;
-
-		if (txstatus & DescOwn)
-			break;	/* It still hasn't been Txed */
-
-		if (likely(txstatus & 0x0001)) {
-			dev->stats.collisions += (txstatus >> 8) & 15;
-			dev->stats.tx_packets++;
-			dev->stats.tx_bytes += ep->tx_skbuff[entry]->len;
-		} else
-			epic_tx_error(dev, ep, txstatus);
-
-		/* Free the original skb. */
-		skb = ep->tx_skbuff[entry];
-		pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr,
-				 skb->len, PCI_DMA_TODEVICE);
-		dev_kfree_skb_irq(skb);
-		ep->tx_skbuff[entry] = NULL;
-	}
-
-#ifndef final_version
-	if (cur_tx - dirty_tx > TX_RING_SIZE) {
-		printk(KERN_WARNING
-		       "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
-		       dev->name, dirty_tx, cur_tx, ep->tx_full);
-		dirty_tx += TX_RING_SIZE;
-	}
-#endif
-	ep->dirty_tx = dirty_tx;
-	if (ep->tx_full && cur_tx - dirty_tx < TX_QUEUE_LEN - 4) {
-		/* The ring is no longer full, allow new TX entries. */
-		ep->tx_full = 0;
-		netif_wake_queue(dev);
-	}
-}
-
-/* The interrupt handler does all of the Rx thread work and cleans up
-   after the Tx thread. */
-static irqreturn_t epic_interrupt(int irq, void *dev_instance)
-{
-	struct net_device *dev = dev_instance;
-	struct epic_private *ep = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	unsigned int handled = 0;
-	int status;
-
-	status = inl(ioaddr + INTSTAT);
-	/* Acknowledge all of the current interrupt sources ASAP. */
-	outl(status & EpicNormalEvent, ioaddr + INTSTAT);
-
-	if (debug > 4) {
-		printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new "
-				   "intstat=%#8.8x.\n", dev->name, status,
-				   (int)inl(ioaddr + INTSTAT));
-	}
-
-	if ((status & IntrSummary) == 0)
-		goto out;
-
-	handled = 1;
-
-	if ((status & EpicNapiEvent) && !ep->reschedule_in_poll) {
-		spin_lock(&ep->napi_lock);
-		if (napi_schedule_prep(&ep->napi)) {
-			epic_napi_irq_off(dev, ep);
-			__napi_schedule(&ep->napi);
-		} else
-			ep->reschedule_in_poll++;
-		spin_unlock(&ep->napi_lock);
-	}
-	status &= ~EpicNapiEvent;
-
-	/* Check uncommon events all at once. */
-	if (status & (CntFull | TxUnderrun | PCIBusErr170 | PCIBusErr175)) {
-		if (status == EpicRemoved)
-			goto out;
-
-		/* Always update the error counts to avoid overhead later. */
-		dev->stats.rx_missed_errors += inb(ioaddr + MPCNT);
-		dev->stats.rx_frame_errors += inb(ioaddr + ALICNT);
-		dev->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
-
-		if (status & TxUnderrun) { /* Tx FIFO underflow. */
-			dev->stats.tx_fifo_errors++;
-			outl(ep->tx_threshold += 128, ioaddr + TxThresh);
-			/* Restart the transmit process. */
-			outl(RestartTx, ioaddr + COMMAND);
-		}
-		if (status & PCIBusErr170) {
-			printk(KERN_ERR "%s: PCI Bus Error! status %4.4x.\n",
-					 dev->name, status);
-			epic_pause(dev);
-			epic_restart(dev);
-		}
-		/* Clear all error sources. */
-		outl(status & 0x7f18, ioaddr + INTSTAT);
-	}
-
-out:
-	if (debug > 3) {
-		printk(KERN_DEBUG "%s: exit interrupt, intr_status=%#4.4x.\n",
-				   dev->name, status);
-	}
-
-	return IRQ_RETVAL(handled);
-}
-
-static int epic_rx(struct net_device *dev, int budget)
-{
-	struct epic_private *ep = netdev_priv(dev);
-	int entry = ep->cur_rx % RX_RING_SIZE;
-	int rx_work_limit = ep->dirty_rx + RX_RING_SIZE - ep->cur_rx;
-	int work_done = 0;
-
-	if (debug > 4)
-		printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry,
-			   ep->rx_ring[entry].rxstatus);
-
-	if (rx_work_limit > budget)
-		rx_work_limit = budget;
-
-	/* If we own the next entry, it's a new packet. Send it up. */
-	while ((ep->rx_ring[entry].rxstatus & DescOwn) == 0) {
-		int status = ep->rx_ring[entry].rxstatus;
-
-		if (debug > 4)
-			printk(KERN_DEBUG "  epic_rx() status was %8.8x.\n", status);
-		if (--rx_work_limit < 0)
-			break;
-		if (status & 0x2006) {
-			if (debug > 2)
-				printk(KERN_DEBUG "%s: epic_rx() error status was %8.8x.\n",
-					   dev->name, status);
-			if (status & 0x2000) {
-				printk(KERN_WARNING "%s: Oversized Ethernet frame spanned "
-					   "multiple buffers, status %4.4x!\n", dev->name, status);
-				dev->stats.rx_length_errors++;
-			} else if (status & 0x0006)
-				/* Rx Frame errors are counted in hardware. */
-				dev->stats.rx_errors++;
-		} else {
-			/* Malloc up new buffer, compatible with net-2e. */
-			/* Omit the four octet CRC from the length. */
-			short pkt_len = (status >> 16) - 4;
-			struct sk_buff *skb;
-
-			if (pkt_len > PKT_BUF_SZ - 4) {
-				printk(KERN_ERR "%s: Oversized Ethernet frame, status %x "
-					   "%d bytes.\n",
-					   dev->name, status, pkt_len);
-				pkt_len = 1514;
-			}
-			/* Check if the packet is long enough to accept without copying
-			   to a minimally-sized skbuff. */
-			if (pkt_len < rx_copybreak &&
-			    (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
-				skb_reserve(skb, 2);	/* 16 byte align the IP header */
-				pci_dma_sync_single_for_cpu(ep->pci_dev,
-							    ep->rx_ring[entry].bufaddr,
-							    ep->rx_buf_sz,
-							    PCI_DMA_FROMDEVICE);
-				skb_copy_to_linear_data(skb, ep->rx_skbuff[entry]->data, pkt_len);
-				skb_put(skb, pkt_len);
-				pci_dma_sync_single_for_device(ep->pci_dev,
-							       ep->rx_ring[entry].bufaddr,
-							       ep->rx_buf_sz,
-							       PCI_DMA_FROMDEVICE);
-			} else {
-				pci_unmap_single(ep->pci_dev,
-					ep->rx_ring[entry].bufaddr,
-					ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
-				skb_put(skb = ep->rx_skbuff[entry], pkt_len);
-				ep->rx_skbuff[entry] = NULL;
-			}
-			skb->protocol = eth_type_trans(skb, dev);
-			netif_receive_skb(skb);
-			dev->stats.rx_packets++;
-			dev->stats.rx_bytes += pkt_len;
-		}
-		work_done++;
-		entry = (++ep->cur_rx) % RX_RING_SIZE;
-	}
-
-	/* Refill the Rx ring buffers. */
-	for (; ep->cur_rx - ep->dirty_rx > 0; ep->dirty_rx++) {
-		entry = ep->dirty_rx % RX_RING_SIZE;
-		if (ep->rx_skbuff[entry] == NULL) {
-			struct sk_buff *skb;
-			skb = ep->rx_skbuff[entry] = dev_alloc_skb(ep->rx_buf_sz + 2);
-			if (skb == NULL)
-				break;
-			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			ep->rx_ring[entry].bufaddr = pci_map_single(ep->pci_dev,
-				skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
-			work_done++;
-		}
-		/* AV: shouldn't we add a barrier here? */
-		ep->rx_ring[entry].rxstatus = DescOwn;
-	}
-	return work_done;
-}
-
-static void epic_rx_err(struct net_device *dev, struct epic_private *ep)
-{
-	long ioaddr = dev->base_addr;
-	int status;
-
-	status = inl(ioaddr + INTSTAT);
-
-	if (status == EpicRemoved)
-		return;
-	if (status & RxOverflow) 	/* Missed a Rx frame. */
-		dev->stats.rx_errors++;
-	if (status & (RxOverflow | RxFull))
-		outw(RxQueued, ioaddr + COMMAND);
-}
-
-static int epic_poll(struct napi_struct *napi, int budget)
-{
-	struct epic_private *ep = container_of(napi, struct epic_private, napi);
-	struct net_device *dev = ep->mii.dev;
-	int work_done = 0;
-	long ioaddr = dev->base_addr;
-
-rx_action:
-
-	epic_tx(dev, ep);
-
-	work_done += epic_rx(dev, budget);
-
-	epic_rx_err(dev, ep);
-
-	if (work_done < budget) {
-		unsigned long flags;
-		int more;
-
-		/* A bit baroque but it avoids a (space hungry) spin_unlock */
-
-		spin_lock_irqsave(&ep->napi_lock, flags);
-
-		more = ep->reschedule_in_poll;
-		if (!more) {
-			__napi_complete(napi);
-			outl(EpicNapiEvent, ioaddr + INTSTAT);
-			epic_napi_irq_on(dev, ep);
-		} else
-			ep->reschedule_in_poll--;
-
-		spin_unlock_irqrestore(&ep->napi_lock, flags);
-
-		if (more)
-			goto rx_action;
-	}
-
-	return work_done;
-}
-
-static int epic_close(struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-	struct epic_private *ep = netdev_priv(dev);
-	struct sk_buff *skb;
-	int i;
-
-	netif_stop_queue(dev);
-	napi_disable(&ep->napi);
-
-	if (debug > 1)
-		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
-			   dev->name, (int)inl(ioaddr + INTSTAT));
-
-	del_timer_sync(&ep->timer);
-
-	epic_disable_int(dev, ep);
-
-	free_irq(dev->irq, dev);
-
-	epic_pause(dev);
-
-	/* Free all the skbuffs in the Rx queue. */
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		skb = ep->rx_skbuff[i];
-		ep->rx_skbuff[i] = NULL;
-		ep->rx_ring[i].rxstatus = 0;		/* Not owned by Epic chip. */
-		ep->rx_ring[i].buflength = 0;
-		if (skb) {
-			pci_unmap_single(ep->pci_dev, ep->rx_ring[i].bufaddr,
-				 	 ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
-			dev_kfree_skb(skb);
-		}
-		ep->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */
-	}
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		skb = ep->tx_skbuff[i];
-		ep->tx_skbuff[i] = NULL;
-		if (!skb)
-			continue;
-		pci_unmap_single(ep->pci_dev, ep->tx_ring[i].bufaddr,
-				 skb->len, PCI_DMA_TODEVICE);
-		dev_kfree_skb(skb);
-	}
-
-	/* Green! Leave the chip in low-power mode. */
-	outl(0x0008, ioaddr + GENCTL);
-
-	return 0;
-}
-
-static struct net_device_stats *epic_get_stats(struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-
-	if (netif_running(dev)) {
-		/* Update the error counts. */
-		dev->stats.rx_missed_errors += inb(ioaddr + MPCNT);
-		dev->stats.rx_frame_errors += inb(ioaddr + ALICNT);
-		dev->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
-	}
-
-	return &dev->stats;
-}
-
-/* Set or clear the multicast filter for this adaptor.
-   Note that we only use exclusion around actually queueing the
-   new frame, not around filling ep->setup_frame.  This is non-deterministic
-   when re-entered but still correct. */
-
-static void set_rx_mode(struct net_device *dev)
-{
-	long ioaddr = dev->base_addr;
-	struct epic_private *ep = netdev_priv(dev);
-	unsigned char mc_filter[8];		 /* Multicast hash filter */
-	int i;
-
-	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
-		outl(0x002C, ioaddr + RxCtrl);
-		/* Unconditionally log net taps. */
-		memset(mc_filter, 0xff, sizeof(mc_filter));
-	} else if ((!netdev_mc_empty(dev)) || (dev->flags & IFF_ALLMULTI)) {
-		/* There is apparently a chip bug, so the multicast filter
-		   is never enabled. */
-		/* Too many to filter perfectly -- accept all multicasts. */
-		memset(mc_filter, 0xff, sizeof(mc_filter));
-		outl(0x000C, ioaddr + RxCtrl);
-	} else if (netdev_mc_empty(dev)) {
-		outl(0x0004, ioaddr + RxCtrl);
-		return;
-	} else {					/* Never executed, for now. */
-		struct netdev_hw_addr *ha;
-
-		memset(mc_filter, 0, sizeof(mc_filter));
-		netdev_for_each_mc_addr(ha, dev) {
-			unsigned int bit_nr =
-				ether_crc_le(ETH_ALEN, ha->addr) & 0x3f;
-			mc_filter[bit_nr >> 3] |= (1 << bit_nr);
-		}
-	}
-	/* ToDo: perhaps we need to stop the Tx and Rx process here? */
-	if (memcmp(mc_filter, ep->mc_filter, sizeof(mc_filter))) {
-		for (i = 0; i < 4; i++)
-			outw(((u16 *)mc_filter)[i], ioaddr + MC0 + i*4);
-		memcpy(ep->mc_filter, mc_filter, sizeof(mc_filter));
-	}
-}
-
-static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct epic_private *np = netdev_priv(dev);
-
-	strcpy (info->driver, DRV_NAME);
-	strcpy (info->version, DRV_VERSION);
-	strcpy (info->bus_info, pci_name(np->pci_dev));
-}
-
-static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct epic_private *np = netdev_priv(dev);
-	int rc;
-
-	spin_lock_irq(&np->lock);
-	rc = mii_ethtool_gset(&np->mii, cmd);
-	spin_unlock_irq(&np->lock);
-
-	return rc;
-}
-
-static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct epic_private *np = netdev_priv(dev);
-	int rc;
-
-	spin_lock_irq(&np->lock);
-	rc = mii_ethtool_sset(&np->mii, cmd);
-	spin_unlock_irq(&np->lock);
-
-	return rc;
-}
-
-static int netdev_nway_reset(struct net_device *dev)
-{
-	struct epic_private *np = netdev_priv(dev);
-	return mii_nway_restart(&np->mii);
-}
-
-static u32 netdev_get_link(struct net_device *dev)
-{
-	struct epic_private *np = netdev_priv(dev);
-	return mii_link_ok(&np->mii);
-}
-
-static u32 netdev_get_msglevel(struct net_device *dev)
-{
-	return debug;
-}
-
-static void netdev_set_msglevel(struct net_device *dev, u32 value)
-{
-	debug = value;
-}
-
-static int ethtool_begin(struct net_device *dev)
-{
-	unsigned long ioaddr = dev->base_addr;
-	/* power-up, if interface is down */
-	if (! netif_running(dev)) {
-		outl(0x0200, ioaddr + GENCTL);
-		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
-	}
-	return 0;
-}
-
-static void ethtool_complete(struct net_device *dev)
-{
-	unsigned long ioaddr = dev->base_addr;
-	/* power-down, if interface is down */
-	if (! netif_running(dev)) {
-		outl(0x0008, ioaddr + GENCTL);
-		outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
-	}
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-	.get_drvinfo		= netdev_get_drvinfo,
-	.get_settings		= netdev_get_settings,
-	.set_settings		= netdev_set_settings,
-	.nway_reset		= netdev_nway_reset,
-	.get_link		= netdev_get_link,
-	.get_msglevel		= netdev_get_msglevel,
-	.set_msglevel		= netdev_set_msglevel,
-	.begin			= ethtool_begin,
-	.complete		= ethtool_complete
-};
-
-static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct epic_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	struct mii_ioctl_data *data = if_mii(rq);
-	int rc;
-
-	/* power-up, if interface is down */
-	if (! netif_running(dev)) {
-		outl(0x0200, ioaddr + GENCTL);
-		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
-	}
-
-	/* all non-ethtool ioctls (the SIOC[GS]MIIxxx ioctls) */
-	spin_lock_irq(&np->lock);
-	rc = generic_mii_ioctl(&np->mii, data, cmd, NULL);
-	spin_unlock_irq(&np->lock);
-
-	/* power-down, if interface is down */
-	if (! netif_running(dev)) {
-		outl(0x0008, ioaddr + GENCTL);
-		outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
-	}
-	return rc;
-}
-
-
-static void __devexit epic_remove_one (struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct epic_private *ep = netdev_priv(dev);
-
-	pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma);
-	pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma);
-	unregister_netdev(dev);
-#ifndef USE_IO_OPS
-	iounmap((void*) dev->base_addr);
-#endif
-	pci_release_regions(pdev);
-	free_netdev(dev);
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-	/* pci_power_off(pdev, -1); */
-}
-
-
-#ifdef CONFIG_PM
-
-static int epic_suspend (struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	long ioaddr = dev->base_addr;
-
-	if (!netif_running(dev))
-		return 0;
-	epic_pause(dev);
-	/* Put the chip into low-power mode. */
-	outl(0x0008, ioaddr + GENCTL);
-	/* pci_power_off(pdev, -1); */
-	return 0;
-}
-
-
-static int epic_resume (struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-
-	if (!netif_running(dev))
-		return 0;
-	epic_restart(dev);
-	/* pci_power_on(pdev); */
-	return 0;
-}
-
-#endif /* CONFIG_PM */
-
-
-static struct pci_driver epic_driver = {
-	.name		= DRV_NAME,
-	.id_table	= epic_pci_tbl,
-	.probe		= epic_init_one,
-	.remove		= __devexit_p(epic_remove_one),
-#ifdef CONFIG_PM
-	.suspend	= epic_suspend,
-	.resume		= epic_resume,
-#endif /* CONFIG_PM */
-};
-
-
-static int __init epic_init (void)
-{
-/* when a module, this is printed whether or not devices are found in probe */
-#ifdef MODULE
-	printk (KERN_INFO "%s%s",
-		version, version2);
-#endif
-
-	return pci_register_driver(&epic_driver);
-}
-
-
-static void __exit epic_cleanup (void)
-{
-	pci_unregister_driver (&epic_driver);
-}
-
-
-module_init(epic_init);
-module_exit(epic_cleanup);
diff -druN linux-libre-3.1-gnu/drivers/net/es3210.c linux-libre-3.2-gnu/drivers/net/es3210.c
--- linux-libre-3.1-gnu/drivers/net/es3210.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/es3210.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,446 +0,0 @@
-/*
-	es3210.c
-
-	Linux driver for Racal-Interlan ES3210 EISA Network Adapter
-
-	Copyright (C) 1996, Paul Gortmaker.
-
-	This software may be used and distributed according to the terms
-	of the GNU General Public License, incorporated herein by reference.
-
-	Information and Code Sources:
-
-	1) The existing myriad of Linux 8390 drivers written by Donald Becker.
-
-	2) Once again Russ Nelson's asm packet driver provided additional info.
-
-	3) Info for getting IRQ and sh-mem gleaned from the EISA cfg files.
-	   Too bad it doesn't work -- see below.
-
-	The ES3210 is an EISA shared memory NS8390 implementation. Note
-	that all memory copies to/from the board must be 32bit transfers.
-	Which rules out using eth_io_copy_and_sum() in this driver.
-
-	Apparently there are two slightly different revisions of the
-	card, since there are two distinct EISA cfg files (!rii0101.cfg
-	and !rii0102.cfg) One has media select in the cfg file and the
-	other doesn't. Hopefully this will work with either.
-
-	That is about all I can tell you about it, having never actually
-	even seen one of these cards. :)  Try http://www.interlan.com
-	if you want more info.
-
-	Thanks go to Mark Salazar for testing v0.02 of this driver.
-
-	Bugs, to-fix, etc:
-
-	1) The EISA cfg ports that are *supposed* to have the IRQ and shared
-	   mem values just read 0xff all the time. Hrrmpf. Apparently the
-	   same happens with the packet driver as the code for reading
-	   these registers is disabled there. In the meantime, boot with:
-	   ether=<IRQ>,0,0x<shared_mem_addr>,eth0 to override the IRQ and
-	   shared memory detection. (The i/o port detection is okay.)
-
-	2) Module support currently untested. Probably works though.
-
-*/
-
-static const char version[] =
-	"es3210.c: Driver revision v0.03, 14/09/96\n";
-
-#include <linux/module.h>
-#include <linux/eisa.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include "8390.h"
-
-static int es_probe1(struct net_device *dev, int ioaddr);
-
-static void es_reset_8390(struct net_device *dev);
-
-static void es_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
-static void es_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset);
-static void es_block_output(struct net_device *dev, int count, const unsigned char *buf, int start_page);
-
-#define ES_START_PG	0x00    /* First page of TX buffer		*/
-#define ES_STOP_PG	0x40    /* Last page +1 of RX ring		*/
-
-#define ES_IO_EXTENT	0x37	/* The cfg file says 0xc90 -> 0xcc7	*/
-#define ES_ID_PORT	0xc80	/* Same for all EISA cards 		*/
-#define ES_SA_PROM	0xc90	/* Start of e'net addr.			*/
-#define ES_RESET_PORT	0xc84	/* From the packet driver source	*/
-#define ES_NIC_OFFSET	0xca0	/* Hello, the 8390 is *here*		*/
-
-#define ES_ADDR0	0x02	/* 3 byte vendor prefix			*/
-#define ES_ADDR1	0x07
-#define ES_ADDR2	0x01
-
-/*
- * Two card revisions. EISA ID's are always rev. minor, rev. major,, and
- * then the three vendor letters stored in 5 bits each, with an "a" = 1.
- * For eg: "rii" = 10010 01001 01001 = 0x4929, which is how the EISA
- * config utility determines automagically what config file(s) to use.
- */
-#define ES_EISA_ID1	0x01012949	/* !rii0101.cfg 		*/
-#define ES_EISA_ID2	0x02012949	/* !rii0102.cfg 		*/
-
-#define ES_CFG1		0xcc0	/* IOPORT(1) --> IOPORT(6) in cfg file	*/
-#define ES_CFG2		0xcc1
-#define ES_CFG3		0xcc2
-#define ES_CFG4		0xcc3
-#define ES_CFG5		0xcc4
-#define ES_CFG6		0xc84	/* NB: 0xc84 is also "reset" port.	*/
-
-/*
- *	You can OR any of the following bits together and assign it
- *	to ES_DEBUG to get verbose driver info during operation.
- *	Some of these don't do anything yet.
- */
-
-#define ES_D_PROBE	0x01
-#define ES_D_RX_PKT	0x02
-#define ES_D_TX_PKT	0x04
-#define ED_D_IRQ	0x08
-
-#define ES_DEBUG	0
-
-static unsigned char lo_irq_map[] __initdata = {3, 4, 5, 6, 7, 9, 10};
-static unsigned char hi_irq_map[] __initdata = {11, 12, 0, 14, 0, 0, 0, 15};
-
-/*
- *	Probe for the card. The best way is to read the EISA ID if it
- *	is known. Then we check the prefix of the station address
- *	PROM for a match against the Racal-Interlan assigned value.
- */
-
-static int __init do_es_probe(struct net_device *dev)
-{
-	unsigned short ioaddr = dev->base_addr;
-	int irq = dev->irq;
-	int mem_start = dev->mem_start;
-
-	if (ioaddr > 0x1ff)		/* Check a single specified location. */
-		return es_probe1(dev, ioaddr);
-	else if (ioaddr > 0)		/* Don't probe at all. */
-		return -ENXIO;
-
-	if (!EISA_bus) {
-#if ES_DEBUG & ES_D_PROBE
-		printk("es3210.c: Not EISA bus. Not probing high ports.\n");
-#endif
-		return -ENXIO;
-	}
-
-	/* EISA spec allows for up to 16 slots, but 8 is typical. */
-	for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
-		if (es_probe1(dev, ioaddr) == 0)
-			return 0;
-		dev->irq = irq;
-		dev->mem_start = mem_start;
-	}
-
-	return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init es_probe(int unit)
-{
-	struct net_device *dev = alloc_ei_netdev();
-	int err;
-
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	sprintf(dev->name, "eth%d", unit);
-	netdev_boot_setup_check(dev);
-
-	err = do_es_probe(dev);
-	if (err)
-		goto out;
-	return dev;
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-#endif
-
-static int __init es_probe1(struct net_device *dev, int ioaddr)
-{
-	int i, retval;
-	unsigned long eisa_id;
-
-	if (!request_region(ioaddr + ES_SA_PROM, ES_IO_EXTENT, "es3210"))
-		return -ENODEV;
-
-#if ES_DEBUG & ES_D_PROBE
-	printk("es3210.c: probe at %#x, ID %#8x\n", ioaddr, inl(ioaddr + ES_ID_PORT));
-	printk("es3210.c: config regs: %#x %#x %#x %#x %#x %#x\n",
-		inb(ioaddr + ES_CFG1), inb(ioaddr + ES_CFG2), inb(ioaddr + ES_CFG3),
-		inb(ioaddr + ES_CFG4), inb(ioaddr + ES_CFG5), inb(ioaddr + ES_CFG6));
-#endif
-
-/*	Check the EISA ID of the card. */
-	eisa_id = inl(ioaddr + ES_ID_PORT);
-	if ((eisa_id != ES_EISA_ID1) && (eisa_id != ES_EISA_ID2)) {
-		retval = -ENODEV;
-		goto out;
-	}
-
-	for (i = 0; i < ETHER_ADDR_LEN ; i++)
-		dev->dev_addr[i] = inb(ioaddr + ES_SA_PROM + i);
-
-/*	Check the Racal vendor ID as well. */
-	if (dev->dev_addr[0] != ES_ADDR0 ||
-	    dev->dev_addr[1] != ES_ADDR1 ||
-	    dev->dev_addr[2] != ES_ADDR2) {
-		printk("es3210.c: card not found %pM (invalid_prefix).\n",
-		       dev->dev_addr);
-		retval = -ENODEV;
-		goto out;
-	}
-
-	printk("es3210.c: ES3210 rev. %ld at %#x, node %pM",
-	       eisa_id>>24, ioaddr, dev->dev_addr);
-
-	/* Snarf the interrupt now. */
-	if (dev->irq == 0) {
-		unsigned char hi_irq = inb(ioaddr + ES_CFG2) & 0x07;
-		unsigned char lo_irq = inb(ioaddr + ES_CFG1) & 0xfe;
-
-		if (hi_irq != 0) {
-			dev->irq = hi_irq_map[hi_irq - 1];
-		} else {
-			int i = 0;
-			while (lo_irq > (1<<i)) i++;
-			dev->irq = lo_irq_map[i];
-		}
-		printk(" using IRQ %d", dev->irq);
-#if ES_DEBUG & ES_D_PROBE
-		printk("es3210.c: hi_irq %#x, lo_irq %#x, dev->irq = %d\n",
-					hi_irq, lo_irq, dev->irq);
-#endif
-	} else {
-		if (dev->irq == 2)
-			dev->irq = 9;			/* Doh! */
-		printk(" assigning IRQ %d", dev->irq);
-	}
-
-	if (request_irq(dev->irq, ei_interrupt, 0, "es3210", dev)) {
-		printk (" unable to get IRQ %d.\n", dev->irq);
-		retval = -EAGAIN;
-		goto out;
-	}
-
-	if (dev->mem_start == 0) {
-		unsigned char mem_enabled = inb(ioaddr + ES_CFG2) & 0xc0;
-		unsigned char mem_bits = inb(ioaddr + ES_CFG3) & 0x07;
-
-		if (mem_enabled != 0x80) {
-			printk(" shared mem disabled - giving up\n");
-			retval = -ENXIO;
-			goto out1;
-		}
-		dev->mem_start = 0xC0000 + mem_bits*0x4000;
-		printk(" using ");
-	} else {
-		printk(" assigning ");
-	}
-
-	ei_status.mem = ioremap(dev->mem_start, (ES_STOP_PG - ES_START_PG)*256);
-	if (!ei_status.mem) {
-		printk("ioremap failed - giving up\n");
-		retval = -ENXIO;
-		goto out1;
-	}
-
-	dev->mem_end = dev->mem_start + (ES_STOP_PG - ES_START_PG)*256;
-
-	printk("mem %#lx-%#lx\n", dev->mem_start, dev->mem_end-1);
-
-#if ES_DEBUG & ES_D_PROBE
-	if (inb(ioaddr + ES_CFG5))
-		printk("es3210: Warning - DMA channel enabled, but not used here.\n");
-#endif
-	/* Note, point at the 8390, and not the card... */
-	dev->base_addr = ioaddr + ES_NIC_OFFSET;
-
-	ei_status.name = "ES3210";
-	ei_status.tx_start_page = ES_START_PG;
-	ei_status.rx_start_page = ES_START_PG + TX_PAGES;
-	ei_status.stop_page = ES_STOP_PG;
-	ei_status.word16 = 1;
-
-	if (ei_debug > 0)
-		printk(version);
-
-	ei_status.reset_8390 = &es_reset_8390;
-	ei_status.block_input = &es_block_input;
-	ei_status.block_output = &es_block_output;
-	ei_status.get_8390_hdr = &es_get_8390_hdr;
-
-	dev->netdev_ops = &ei_netdev_ops;
-	NS8390_init(dev, 0);
-
-	retval = register_netdev(dev);
-	if (retval)
-		goto out1;
-	return 0;
-out1:
-	free_irq(dev->irq, dev);
-out:
-	release_region(ioaddr + ES_SA_PROM, ES_IO_EXTENT);
-	return retval;
-}
-
-/*
- *	Reset as per the packet driver method. Judging by the EISA cfg
- *	file, this just toggles the "Board Enable" bits (bit 2 and 0).
- */
-
-static void es_reset_8390(struct net_device *dev)
-{
-	unsigned short ioaddr = dev->base_addr;
-	unsigned long end;
-
-	outb(0x04, ioaddr + ES_RESET_PORT);
-	if (ei_debug > 1) printk("%s: resetting the ES3210...", dev->name);
-
-	end = jiffies + 2*HZ/100;
-        while ((signed)(end - jiffies) > 0) continue;
-
-	ei_status.txing = 0;
-	outb(0x01, ioaddr + ES_RESET_PORT);
-	if (ei_debug > 1) printk("reset done\n");
-}
-
-/*
- *	Note: In the following three functions is the implicit assumption
- *	that the associated memcpy will only use "rep; movsl" as long as
- *	we keep the counts as some multiple of doublewords. This is a
- *	requirement of the hardware, and also prevents us from using
- *	eth_io_copy_and_sum() since we can't guarantee it will limit
- *	itself to doubleword access.
- */
-
-/*
- *	Grab the 8390 specific header. Similar to the block_input routine, but
- *	we don't need to be concerned with ring wrap as the header will be at
- *	the start of a page, so we optimize accordingly. (A single doubleword.)
- */
-
-static void
-es_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-	void __iomem *hdr_start = ei_status.mem + ((ring_page - ES_START_PG)<<8);
-	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
-	hdr->count = (hdr->count + 3) & ~3;     /* Round up allocation. */
-}
-
-/*
- *	Block input and output are easy on shared memory ethercards, the only
- *	complication is when the ring buffer wraps. The count will already
- *	be rounded up to a doubleword value via es_get_8390_hdr() above.
- */
-
-static void es_block_input(struct net_device *dev, int count, struct sk_buff *skb,
-						  int ring_offset)
-{
-	void __iomem *xfer_start = ei_status.mem + ring_offset - ES_START_PG*256;
-
-	if (ring_offset + count > ES_STOP_PG*256) {
-		/* Packet wraps over end of ring buffer. */
-		int semi_count = ES_STOP_PG*256 - ring_offset;
-		memcpy_fromio(skb->data, xfer_start, semi_count);
-		count -= semi_count;
-		memcpy_fromio(skb->data + semi_count, ei_status.mem, count);
-	} else {
-		/* Packet is in one chunk. */
-		memcpy_fromio(skb->data, xfer_start, count);
-	}
-}
-
-static void es_block_output(struct net_device *dev, int count,
-				const unsigned char *buf, int start_page)
-{
-	void __iomem *shmem = ei_status.mem + ((start_page - ES_START_PG)<<8);
-
-	count = (count + 3) & ~3;     /* Round up to doubleword */
-	memcpy_toio(shmem, buf, count);
-}
-
-#ifdef MODULE
-#define MAX_ES_CARDS	4	/* Max number of ES3210 cards per module */
-#define NAMELEN		8	/* # of chars for storing dev->name */
-static struct net_device *dev_es3210[MAX_ES_CARDS];
-static int io[MAX_ES_CARDS];
-static int irq[MAX_ES_CARDS];
-static int mem[MAX_ES_CARDS];
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(mem, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es)");
-MODULE_PARM_DESC(irq, "IRQ number(s)");
-MODULE_PARM_DESC(mem, "memory base address(es)");
-MODULE_DESCRIPTION("Racal-Interlan ES3210 EISA ethernet driver");
-MODULE_LICENSE("GPL");
-
-int __init init_module(void)
-{
-	struct net_device *dev;
-	int this_dev, found = 0;
-
-	for (this_dev = 0; this_dev < MAX_ES_CARDS; this_dev++) {
-		if (io[this_dev] == 0 && this_dev != 0)
-			break;
-		dev = alloc_ei_netdev();
-		if (!dev)
-			break;
-		dev->irq = irq[this_dev];
-		dev->base_addr = io[this_dev];
-		dev->mem_start = mem[this_dev];
-		if (do_es_probe(dev) == 0) {
-			dev_es3210[found++] = dev;
-			continue;
-		}
-		free_netdev(dev);
-		printk(KERN_WARNING "es3210.c: No es3210 card found (i/o = 0x%x).\n", io[this_dev]);
-		break;
-	}
-	if (found)
-		return 0;
-	return -ENXIO;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-	free_irq(dev->irq, dev);
-	release_region(dev->base_addr, ES_IO_EXTENT);
-	iounmap(ei_status.mem);
-}
-
-void __exit
-cleanup_module(void)
-{
-	int this_dev;
-
-	for (this_dev = 0; this_dev < MAX_ES_CARDS; this_dev++) {
-		struct net_device *dev = dev_es3210[this_dev];
-		if (dev) {
-			unregister_netdev(dev);
-			cleanup_card(dev);
-			free_netdev(dev);
-		}
-	}
-}
-#endif /* MODULE */
-
diff -druN linux-libre-3.1-gnu/drivers/net/eth16i.c linux-libre-3.2-gnu/drivers/net/eth16i.c
--- linux-libre-3.1-gnu/drivers/net/eth16i.c	2011-10-24 03:10:05.000000000 -0400
+++ linux-libre-3.2-gnu/drivers/net/eth16i.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1484 +0,0 @@
-/* eth16i.c An ICL EtherTeam 16i and 32 EISA ethernet driver for Linux
-
-   Written 1994-1999 by Mika Kuoppala
-
-   Copyright (C) 1994-1999 by Mika Kuoppala
-   Based on skeleton.c and heavily on at1700.c by Donald Becker
-
-   This software may be used and distributed according to the terms
-   of the GNU General Public License, incorporated herein by reference.
-
-   The author may be reached as miku@iki.fi
-
-   This driver supports following cards :
-	- ICL EtherTeam 16i
-	- ICL EtherTeam 32 EISA
-	  (Uses true 32 bit transfers rather than 16i compatibility mode)
-
-   Example Module usage:
-        insmod eth16i.o io=0x2a0 mediatype=bnc
-
-	mediatype can be one of the following: bnc,tp,dix,auto,eprom
-
-	'auto' will try to autoprobe mediatype.
-	'eprom' will use whatever type defined in eprom.
-
-   I have benchmarked driver with PII/300Mhz as a ftp client
-   and 486/33Mhz as a ftp server. Top speed was 1128.37 kilobytes/sec.
-
-   Sources:
-     - skeleton.c  a sample network driver core for linux,
-       written by Donald Becker <becker@scyld.com>
-     - at1700.c a driver for Allied Telesis AT1700, written
-       by Donald Becker.
-     - e16iSRV.asm a Netware 3.X Server Driver for ICL EtherTeam16i
-       written by Markku Viima
-     - The Fujitsu MB86965 databook.
-
-   Author thanks following persons due to their valueble assistance:
-        Markku Viima (ICL)
-	Ari Valve (ICL)
-	Donald Becker
-	Kurt Huwig <kurt@huwig.de>
-
-   Revision history:
-
-   Version	Date		Description
-
-   0.01         15.12-94        Initial version (card detection)
-   0.02         23.01-95        Interrupt is now hooked correctly
-   0.03         01.02-95        Rewrote initialization part
-   0.04         07.02-95        Base skeleton done...
-                                Made a few changes to signature checking
-                                to make it a bit reliable.
-                                - fixed bug in tx_buf mapping
-                                - fixed bug in initialization (DLC_EN
-                                  wasn't enabled when initialization
-                                  was done.)
-   0.05         08.02-95        If there were more than one packet to send,
-                                transmit was jammed due to invalid
-                                register write...now fixed
-   0.06         19.02-95        Rewrote interrupt handling
-   0.07         13.04-95        Wrote EEPROM read routines
-                                Card configuration now set according to
-                                data read from EEPROM
-   0.08         23.06-95        Wrote part that tries to probe used interface
-                                port if AUTO is selected
-
-   0.09         01.09-95        Added module support
-
-   0.10         04.09-95        Fixed receive packet allocation to work
-                                with kernels > 1.3.x
-
-   0.20		20.09-95	Added support for EtherTeam32 EISA
-
-   0.21         17.10-95        Removed the unnecessary extern
-				init_etherdev() declaration. Some
-				other cleanups.
-
-   0.22		22.02-96	Receive buffer was not flushed
-				correctly when faulty packet was
-				received. Now fixed.
-
-   0.23		26.02-96	Made resetting the adapter
-			 	more reliable.
-
-   0.24		27.02-96	Rewrote faulty packet handling in eth16i_rx
-
-   0.25		22.05-96	kfree() was missing from cleanup_module.
-
-   0.26		11.06-96	Sometimes card was not found by
-				check_signature(). Now made more reliable.
-
-   0.27		23.06-96	Oops. 16 consecutive collisions halted
-				adapter. Now will try to retransmit
-				MAX_COL_16 times before finally giving up.
-
-   0.28	        28.10-97	Added dev_id parameter (NULL) for free_irq
-
-   0.29         29.10-97        Multiple card support for module users
-
-   0.30         30.10-97        Fixed irq allocation bug.
-                                (request_irq moved from probe to open)
-
-   0.30a        21.08-98        Card detection made more relaxed. Driver
-                                had problems with some TCP/IP-PROM boots
-				to find the card. Suggested by
-				Kurt Huwig <kurt@huwig.de>
-
-   0.31         28.08-98        Media interface port can now be selected
-                                with module parameters or kernel
-				boot parameters.
-
-   0.32         31.08-98        IRQ was never freed if open/close
-                                pair wasn't called. Now fixed.
-
-   0.33         10.09-98        When eth16i_open() was called after
-                                eth16i_close() chip never recovered.
-				Now more shallow reset is made on
-				close.
-
-   0.34         29.06-99	Fixed one bad #ifdef.
-				Changed ioaddr -> io for consistency
-
-   0.35         01.07-99        transmit,-receive bytes were never
-                                updated in stats.
-
-   Bugs:
-	In some cases the media interface autoprobing code doesn't find
-	the correct interface type. In this case you can
-	manually choose the interface type in DOS with E16IC.EXE which is
-	configuration software for EtherTeam16i and EtherTeam32 cards.
-	This is also true for IRQ setting. You cannot use module
-	parameter to configure IRQ of the card (yet).
-
-   To do:
-	- Real multicast support
-	- Rewrite the media interface autoprobing code. Its _horrible_ !
-	- Possibly merge all the MB86965 specific code to external
-	  module for use by eth16.c and Donald's at1700.c
-	- IRQ configuration with module parameter. I will do
-	  this when i will get enough info about setting
-	  irq without configuration utility.
-*/
-
-static char *version =
-    "eth16i.c: v0.35 01-Jul-1999 Mika Kuoppala (miku@iki.fi)\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-#include <linux/jiffies.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/dma.h>
-
-
-
-/* Few macros */
-#define BITSET(ioaddr, bnum)   ((outb(((inb(ioaddr)) | (bnum)), ioaddr)))
-#define BITCLR(ioaddr, bnum)   ((outb(((inb(ioaddr)) & (~(bnum))), ioaddr)))
-
-/* This is the I/O address space for Etherteam 16i adapter. */
-#define ETH16I_IO_EXTENT       32
-
-/* Ticks before deciding that transmit has timed out */
-#define TX_TIMEOUT             (400*HZ/1000)
-
-/* Maximum loop count when receiving packets */
-#define MAX_RX_LOOP            20
-
-/* Some interrupt masks */
-#define ETH16I_INTR_ON	       0xef8a       /* Higher is receive mask */
-#define ETH16I_INTR_OFF	       0x0000
-
-/* Buffers header status byte meanings */
-#define PKT_GOOD               BIT(5)
-#define PKT_GOOD_RMT           BIT(4)
-#define PKT_SHORT              BIT(3)
-#define PKT_ALIGN_ERR          BIT(2)
-#define PKT_CRC_ERR            BIT(1)
-#define PKT_RX_BUF_OVERFLOW    BIT(0)
-
-/* Transmit status register (DLCR0) */
-#define TX_STATUS_REG          0
-#define TX_DONE                BIT(7)
-#define NET_BUSY               BIT(6)
-#define TX_PKT_RCD             BIT(5)
-#define CR_LOST                BIT(4)
-#define TX_JABBER_ERR	       BIT(3)
-#define COLLISION              BIT(2)
-#define COLLISIONS_16          BIT(1)
-
-/* Receive status register (DLCR1) */
-#define RX_STATUS_REG          1
-#define RX_PKT                 BIT(7)  /* Packet received */
-#define BUS_RD_ERR             BIT(6)
-#define SHORT_PKT_ERR          BIT(3)
-#define ALIGN_ERR              BIT(2)
-#define CRC_ERR                BIT(1)
-#define RX_BUF_OVERFLOW        BIT(0)
-
-/* Transmit Interrupt Enable Register (DLCR2) */
-#define TX_INTR_REG            2
-#define TX_INTR_DONE           BIT(7)
-#define TX_INTR_COL            BIT(2)
-#define TX_INTR_16_COL         BIT(1)
-
-/* Receive Interrupt Enable Register (DLCR3) */
-#define RX_INTR_REG            3
-#define RX_INTR_RECEIVE        BIT(7)
-#define RX_INTR_SHORT_PKT      BIT(3)
-#define RX_INTR_CRC_ERR        BIT(1)
-#define RX_INTR_BUF_OVERFLOW   BIT(0)
-
-/* Transmit Mode Register (DLCR4) */
-#define TRANSMIT_MODE_REG      4
-#define LOOPBACK_CONTROL       BIT(1)
-#define CONTROL_OUTPUT         BIT(2)
-
-/* Receive Mode Register (DLCR5) */
-#define RECEIVE_MODE_REG       5
-#define RX_BUFFER_EMPTY        BIT(6)
-#define ACCEPT_BAD_PACKETS     BIT(5)
-#define RECEIVE_SHORT_ADDR     BIT(4)
-#define ACCEPT_SHORT_PACKETS   BIT(3)
-#define REMOTE_RESET           BIT(2)
-
-#define ADDRESS_FILTER_MODE    BIT(1) | BIT(0)
-#define REJECT_ALL             0
-#define ACCEPT_ALL             3
-#define MODE_1                 1            /* NODE ID, BC, MC, 2-24th bit */
-#define MODE_2                 2            /* NODE ID, BC, MC, Hash Table */
-
-/* Configuration Register 0 (DLCR6) */
-#define CONFIG_REG_0           6
-#define DLC_EN                 BIT(7)
-#define SRAM_CYCLE_TIME_100NS  BIT(6)
-#define SYSTEM_BUS_WIDTH_8     BIT(5)       /* 1 = 8bit, 0 = 16bit */
-#define BUFFER_WIDTH_8         BIT(4)       /* 1 = 8bit, 0 = 16bit */
-#define TBS1                   BIT(3)
-#define TBS0                   BIT(2)
-#define SRAM_BS1               BIT(1)       /* 00=8kb,  01=16kb  */
-#define SRAM_BS0               BIT(0)       /* 10=32kb, 11=64kb  */
-
-#ifndef ETH16I_TX_BUF_SIZE                   /* 0 = 2kb, 1 = 4kb  */
-#define ETH16I_TX_BUF_SIZE     3             /* 2 = 8kb, 3 = 16kb */
-#endif
-#define TX_BUF_1x2048          0
-#define TX_BUF_2x2048          1
-#define TX_BUF_2x4098          2
-#define TX_BUF_2x8192          3
-
-/* Configuration Register 1 (DLCR7) */
-#define CONFIG_REG_1           7
-#define POWERUP                BIT(5)
-
-/* Transmit start register */
-#define TRANSMIT_START_REG     10
-#define TRANSMIT_START_RB      2
-#define TX_START               BIT(7)       /* Rest of register bit indicate*/
-                                            /* number of packets in tx buffer*/
-/* Node ID registers (DLCR8-13) */
-#define NODE_ID_0              8
-#define NODE_ID_RB             0
-
-/* Hash Table registers (HT8-15) */
-#define HASH_TABLE_0           8
-#define HASH_TABLE_RB          1
-
-/* Buffer memory ports */
-#define BUFFER_MEM_PORT_LB     8
-#define DATAPORT               BUFFER_MEM_PORT_LB
-#define BUFFER_MEM_PORT_HB     9
-
-/* 16 Collision control register (BMPR11) */
-#define COL_16_REG             11
-#define HALT_ON_16             0x00
-#define RETRANS_AND_HALT_ON_16 0x02
-
-/* Maximum number of attempts to send after 16 concecutive collisions */
-#define MAX_COL_16	       10
-
-/* DMA Burst and Transceiver Mode Register (BMPR13) */
-#define TRANSCEIVER_MODE_REG   13
-#define TRANSCEIVER_MODE_RB    2
-#define IO_BASE_UNLOCK	       BIT(7)
-#define LOWER_SQUELCH_TRESH    BIT(6)
-#define LINK_TEST_DISABLE      BIT(5)
-#define AUI_SELECT             BIT(4)
-#define DIS_AUTO_PORT_SEL      BIT(3)
-
-/* Filter Self Receive Register (BMPR14)  */
-#define FILTER_SELF_RX_REG     14
-#define SKIP_RX_PACKET         BIT(2)
-#define FILTER_SELF_RECEIVE    BIT(0)
-
-/* EEPROM Control Register (BMPR 16) */
-#define EEPROM_CTRL_REG        16
-
-/* EEPROM Data Register (BMPR 17) */
-#define EEPROM_DATA_REG        17
-
-/* NMC93CSx6 EEPROM Control Bits */
-#define CS_0                   0x00
-#define CS_1                   0x20
-#define SK_0                   0x00
-#define SK_1                   0x40
-#define DI_0                   0x00
-#define DI_1                   0x80
-
-/* NMC93CSx6 EEPROM Instructions */
-#define EEPROM_READ            0x80
-
-/* NMC93CSx6 EEPROM Addresses */
-#define E_NODEID_0             0x02
-#define E_NODEID_1             0x03
-#define E_NODEID_2             0x04
-#define E_PORT_SELECT          0x14
-  #define E_PORT_BNC           0x00
-  #define E_PORT_DIX           0x01
-  #define E_PORT_TP            0x02
-  #define E_PORT_AUTO          0x03
-  #define E_PORT_FROM_EPROM    0x04
-#define E_PRODUCT_CFG          0x30
-
-
-/* Macro to slow down io between EEPROM clock transitions */
-#define eeprom_slow_io() do { int _i = 40; while(--_i > 0) { inb(0x80); }}while(0)
-
-/* Jumperless Configuration Register (BMPR19) */
-#define JUMPERLESS_CONFIG      19
-
-/* ID ROM registers, writing to them also resets some parts of chip */
-#define ID_ROM_0               24
-#define ID_ROM_7               31
-#define RESET                  ID_ROM_0
-
-/* This is the I/O address list to be probed when seeking the card */
-static unsigned int eth16i_portlist[] __initdata = {
-	0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
-};
-
-static unsigned int eth32i_portlist[] __initdata = {
-	0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000,
-	0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0
-};
-
-/* This is the Interrupt lookup table for Eth16i card */
-static unsigned int eth16i_irqmap[] __initdata = { 9, 10, 5, 15, 0 };
-#define NUM_OF_ISA_IRQS    4
-
-/* This is the Interrupt lookup table for Eth32i card */
-static unsigned int eth32i_irqmap[] __initdata = { 3, 5, 7, 9, 10, 11, 12, 15, 0 };
-#define EISA_IRQ_REG	0xc89
-#define NUM_OF_EISA_IRQS   8
-
-static unsigned int eth16i_tx_buf_map[] = { 2048, 2048, 4096, 8192 };
-
-/* Use 0 for production, 1 for verification, >2 for debug */
-#ifndef ETH16I_DEBUG
-#define ETH16I_DEBUG 0
-#endif
-static unsigned int eth16i_debug = ETH16I_DEBUG;
-
-/* Information for each board */
-
-struct eth16i_local {
-	unsigned char     tx_started;
-	unsigned char     tx_buf_busy;
-	unsigned short    tx_queue;  /* Number of packets in transmit buffer */
-	unsigned short    tx_queue_len;
-	unsigned int      tx_buf_size;
-	unsigned long     open_time;
-	unsigned long     tx_buffered_packets;
-	unsigned long     tx_buffered_bytes;
-	unsigned long     col_16;
-	spinlock_t	  lock;
-};
-
-/* Function prototypes */
-
-static int     eth16i_probe1(struct net_device *dev, int ioaddr);
-static int     eth16i_check_signature(int ioaddr);
-static int     eth16i_probe_port(int ioaddr);
-static void    eth16i_set_port(int ioaddr, int porttype);
-static int     eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l);
-static int     eth16i_receive_probe_packet(int ioaddr);
-static int     eth16i_get_irq(int ioaddr);
-static int     eth16i_read_eeprom(int ioaddr, int offset);
-static int     eth16i_read_eeprom_word(int ioaddr);
-static void    eth16i_eeprom_cmd(int ioaddr, unsigned char command);
-static int     eth16i_open(struct net_device *dev);
-static int     eth16i_close(struct net_device *dev);
-static netdev_tx_t eth16i_tx(struct sk_buff *skb, struct net_device *dev);
-static void    eth16i_rx(struct net_device *dev);
-static void    eth16i_timeout(struct net_device *dev);
-static irqreturn_t eth16i_interrupt(int irq, void *dev_id);
-static void    eth16i_reset(struct net_device *dev);
-static void    eth16i_timeout(struct net_device *dev);
-static void    eth16i_skip_packet(struct net_device *dev);
-static void    eth16i_multicast(struct net_device *dev);
-static void    eth16i_select_regbank(unsigned char regbank, int ioaddr);
-static void    eth16i_initialize(struct net_device *dev, int boot);
-
-#if 0
-static int     eth16i_set_irq(struct net_device *dev);
-#endif
-
-#ifdef MODULE
-static ushort  eth16i_parse_mediatype(const char* s);
-#endif
-
-static char cardname[] __initdata = "ICL EtherTeam 16i/32";
-
-static int __init do_eth16i_probe(struct net_device *dev)
-{
-	int i;
-	int ioaddr;
-	int base_addr = dev->base_addr;
-
-	if(eth16i_debug > 4)
-		printk(KERN_DEBUG "Probing started for %s\n", cardname);
-
-	if(base_addr > 0x1ff)           /* Check only single location */
-		return eth16i_probe1(dev, base_addr);
-	else if(base_addr != 0)         /* Don't probe at all */
-		return -ENXIO;
-
-	/* Seek card from the ISA io address space */
-	for(i = 0; (ioaddr = eth16i_portlist[i]) ; i++)
-		if(eth16i_probe1(dev, ioaddr) == 0)
-			return 0;
-
-	/* Seek card from the EISA io address space */
-	for(i = 0; (ioaddr = eth32i_portlist[i]) ; i++)
-		if(eth16i_probe1(dev, ioaddr) == 0)
-			return 0;
-
-	return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init eth16i_probe(int unit)
-{
-	struct net_device *dev = alloc_etherdev(sizeof(struct eth16i_local));
-	int err;
-
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	sprintf(dev->name, "eth%d", unit);
-	netdev_boot_setup_check(dev);
-
-	err = do_eth16i_probe(dev);
-	if (err)
-		goto out;
-	return dev;
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-#endif
-
-static const struct net_device_ops eth16i_netdev_ops = {
-	.ndo_open               = eth16i_open,
-	.ndo_stop               = eth16i_close,
-	.ndo_start_xmit    	= eth16i_tx,
-	.ndo_set_multicast_list = eth16i_multicast,
-	.ndo_tx_timeout 	= eth16i_timeout,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
-{
-	struct eth16i_local *lp = netdev_priv(dev);
-	static unsigned version_printed;
-	int retval;
-
-	/* Let's grab the region */
-	if (!request_region(ioaddr, ETH16I_IO_EXTENT, cardname))
-		return -EBUSY;
-
-	/*
-	  The MB86985 chip has on register which holds information in which
-	  io address the chip lies. First read this register and compare
-	  it to our current io address and if match then this could
-	  be our chip.
-	  */
-
-	if(ioaddr < 0x1000) {
-		if(eth16i_portlist[(inb(ioaddr + JUMPERLESS_CONFIG) & 0x07)]
-		   != ioaddr) {
-			retval = -ENODEV;
-			goto out;
-		}
-	}
-
-	/* Now we will go a bit deeper and try to find the chip's signature */
-
-	if(eth16i_check_signature(ioaddr) != 0) {
-		retval = -ENODEV;
-		goto out;
-	}
-
-	/*
-	   Now it seems that we have found a ethernet chip in this particular
-	   ioaddr. The MB86985 chip has this feature, that when you read a
-	   certain register it will increase it's io base address to next
-	   configurable slot. Now when we have found the chip, first thing is
-	   to make sure that the chip's ioaddr will hold still here.
-	   */
-
-	eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
-	outb(0x00, ioaddr + TRANSCEIVER_MODE_REG);
-
-	outb(0x00, ioaddr + RESET);             /* Reset some parts of chip */
-	BITSET(ioaddr + CONFIG_REG_0, BIT(7));  /* Disable the data link */
-
-	if( (eth16i_debug & version_printed++) == 0)
-		printk(KERN_INFO "%s", version);
-
-	dev->base_addr = ioaddr;
-	dev->irq = eth16i_get_irq(ioaddr);
-
-	/* Try to obtain interrupt vector */
-
-	if ((retval = request_irq(dev->irq, (void *)&eth16i_interrupt, 0, cardname, dev))) {
-		printk(KERN_WARNING "%s at %#3x, but is unusable due to conflicting IRQ %d.\n",
-		       cardname, ioaddr, dev->irq);
-		goto out;
-	}
-
-	printk(KERN_INFO "%s: %s at %#3x, IRQ %d, ",
-	       dev->name, cardname, ioaddr, dev->irq);
-
-
-	/* Now we will have to lock the chip's io address */
-	eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
-	outb(0x38, ioaddr + TRANSCEIVER_MODE_REG);
-
-	eth16i_initialize(dev, 1); /* Initialize rest of the chip's registers */
-
-	/* Now let's same some energy by shutting down the chip ;) */
-	BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
-
-	/* Initialize the device structure */
-	dev->netdev_ops         = &eth16i_netdev_ops;
-	dev->watchdog_timeo	= TX_TIMEOUT;
-	spin_lock_init(&lp->lock);
-
-	retval = register_netdev(dev);
-	if (retval)
-		goto out1;
-	return 0;
-out1:
-	free_irq(dev->irq, dev);
-out:
-	release_region(ioaddr, ETH16I_IO_EXTENT);
-	return retval;
-}
-
-
-static void eth16i_initialize(struct net_device *dev, int boot)
-{
-	int ioaddr = dev->base_addr;
-	int i, node_w = 0;
-	unsigned char node_byte = 0;
-
-	/* Setup station address */
-	eth16i_select_regbank(NODE_ID_RB, ioaddr);
-	for(i = 0 ; i < 3 ; i++) {
-		unsigned short node_val = eth16i_read_eeprom(ioaddr, E_NODEID_0 + i);
-		((unsigned short *)dev->dev_addr)[i] = ntohs(node_val);
-	}
-
-	for(i = 0; i < 6; i++) {
-		outb( ((unsigned char *)dev->dev_addr)[i], ioaddr + NODE_ID_0 + i);
-		if(boot) {
-			printk("%02x", inb(ioaddr + NODE_ID_0 + i));
-			if(i != 5)
-				printk(":");
-		}
-	}
-
-	/* Now we will set multicast addresses to accept none */
-	eth16i_select_regbank(HASH_TABLE_RB, ioaddr);
-	for(i = 0; i < 8; i++)
-		outb(0x00, ioaddr + HASH_TABLE_0 + i);
-
-	/*
-	  Now let's disable the transmitter and receiver, set the buffer ram
-	  cycle time, bus width and buffer data path width. Also we shall
-	  set transmit buffer size and total buffer size.
-	  */
-
-	eth16i_select_regbank(2, ioaddr);
-
-	node_byte = 0;
-	node_w = eth16i_read_eeprom(ioaddr, E_PRODUCT_CFG);
-
-	if( (node_w & 0xFF00) == 0x0800)
-		node_byte |= BUFFER_WIDTH_8;
-
-	node_byte |= SRAM_BS1;
-
-	if( (node_w & 0x00FF) == 64)
-		node_byte |= SRAM_BS0;
-
-	node_byte |= DLC_EN | SRAM_CYCLE_TIME_100NS | (ETH16I_TX_BUF_SIZE << 2);
-
-	outb(node_byte, ioaddr + CONFIG_REG_0);
-
-	/* We shall halt the transmitting, if 16 collisions are detected */
-	outb(HALT_ON_16, ioaddr + COL_16_REG);
-
-#ifdef MODULE
-	/* if_port already set by init_module() */
-#else
-	dev->if_port = (dev->mem_start < E_PORT_FROM_EPROM) ?
-		dev->mem_start : E_PORT_FROM_EPROM;
-#endif
-
-	/* Set interface port type */
-	if(boot) {
-		static const char * const porttype[] = {
-			"BNC", "DIX", "TP", "AUTO", "FROM_EPROM"
-		};
-
-		switch(dev->if_port)
-		{
-
-		case E_PORT_FROM_EPROM:
-			dev->if_port = eth16i_read_eeprom(ioaddr, E_PORT_SELECT);
-			break;
-
-		case E_PORT_AUTO:
-			dev->if_port = eth16i_probe_port(ioaddr);
-			break;
-
-		case E_PORT_BNC:
-		case E_PORT_TP:
-		case E_PORT_DIX:
-			break;
-		}
-
-		printk(" %s interface.\n", porttype[dev->if_port]);
-
-		eth16i_set_port(ioaddr, dev->if_port);
-	}
-
-	/* Set Receive Mode to normal operation */
-	outb(MODE_2, ioaddr + RECEIVE_MODE_REG);
-}
-
-static int eth16i_probe_port(int ioaddr)
-{
-	int i;
-	int retcode;
-	unsigned char dummy_packet[64];
-
-	/* Powerup the chip */
-	outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
-
-	BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
-
-	eth16i_select_regbank(NODE_ID_RB, ioaddr);
-
-	for(i = 0; i < 6; i++) {
-		dummy_packet[i] = inb(ioaddr + NODE_ID_0 + i);
-		dummy_packet[i+6] = inb(ioaddr + NODE_ID_0 + i);
-	}
-
-	dummy_packet[12] = 0x00;
-	dummy_packet[13] = 0x04;
-	memset(dummy_packet + 14, 0, sizeof(dummy_packet) - 14);
-
-	eth16i_select_regbank(2, ioaddr);
-
-	for(i = 0; i < 3; i++) {
-		BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
-		BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
-		eth16i_set_port(ioaddr, i);
-
-		if(eth16i_debug > 1)
-			printk(KERN_DEBUG "Set port number %d\n", i);
-
-		retcode = eth16i_send_probe_packet(ioaddr, dummy_packet, 64);
-		if(retcode == 0) {
-			retcode = eth16i_receive_probe_packet(ioaddr);
-			if(retcode != -1) {
-				if(eth16i_debug > 1)
-					printk(KERN_DEBUG "Eth16i interface port found at %d\n", i);
-				return i;
-			}
-		}
-		else {
-			if(eth16i_debug > 1)
-				printk(KERN_DEBUG "TRANSMIT_DONE timeout when probing interface port\n");
-		}
-	}
-
-	if( eth16i_debug > 1)
-		printk(KERN_DEBUG "Using default port\n");
-
-	return E_PORT_BNC;
-}
-
-static void eth16i_set_port(int ioaddr, int porttype)
-{
-	unsigned short temp = 0;
-
-	eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
-	outb(LOOPBACK_CONTROL, ioaddr + TRANSMIT_MODE_REG);
-
-	temp |= DIS_AUTO_PORT_SEL;
-
-	switch(porttype) {
-
-	case E_PORT_BNC :
-		temp |= AUI_SELECT;
-		break;
-
-	case E_PORT_TP :
-		break;
-
-	case E_PORT_DIX :
-		temp |= AUI_SELECT;
-		BITSET(ioaddr + TRANSMIT_MODE_REG, CONTROL_OUTPUT);
-		break;
-	}
-
-	outb(temp, ioaddr + TRANSCEIVER_MODE_REG);
-
-	if(eth16i_debug > 1) {
-		printk(KERN_DEBUG "TRANSMIT_MODE_REG = %x\n", inb(ioaddr + TRANSMIT_MODE_REG));
-		printk(KERN_DEBUG "TRANSCEIVER_MODE_REG = %x\n",
-		       inb(ioaddr+TRANSCEIVER_MODE_REG));
-	}
-}
-
-static int eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l)
-{
-	unsigned long starttime;
-
-	outb(0xff, ioaddr + TX_STATUS_REG);
-
-	outw(l, ioaddr + DATAPORT);
-	outsw(ioaddr + DATAPORT, (unsigned short *)b, (l + 1) >> 1);
-
-	starttime = jiffies;
-	outb(TX_START | 1, ioaddr + TRANSMIT_START_REG);
-
-	while( (inb(ioaddr + TX_STATUS_REG) & 0x80) == 0) {
-		if( time_after(jiffies, starttime + TX_TIMEOUT)) {
-			return -1;
-		}
-	}
-
-	return 0;
-}
-
-static int eth16i_receive_probe_packet(int ioaddr)
-{
-	unsigned long starttime;
-
-	starttime = jiffies;
-
-	while((inb(ioaddr + TX_STATUS_REG) & 0x20) == 0) {
-		if( time_after(jiffies, starttime + TX_TIMEOUT)) {
-
-			if(eth16i_debug > 1)
-				printk(KERN_DEBUG "Timeout occurred waiting transmit packet received\n");
-			starttime = jiffies;
-			while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) {
-				if( time_after(jiffies, starttime + TX_TIMEOUT)) {
-					if(eth16i_debug > 1)
-						printk(KERN_DEBUG "Timeout occurred waiting receive packet\n");
-					return -1;
-				}
-			}
-
-			if(eth16i_debug > 1)
-				printk(KERN_DEBUG "RECEIVE_PACKET\n");
-			return 0; /* Found receive packet */
-		}
-	}
-
-	if(eth16i_debug > 1) {
-		printk(KERN_DEBUG "TRANSMIT_PACKET_RECEIVED %x\n", inb(ioaddr + TX_STATUS_REG));
-		printk(KERN_DEBUG "RX_STATUS_REG = %x\n", inb(ioaddr + RX_STATUS_REG));
-	}
-
-	return 0; /* Return success */
-}
-
-#if 0
-static int eth16i_set_irq(struct net_device* dev)
-{
-	const int ioaddr = dev->base_addr;
-	const int irq = dev->irq;
-	int i = 0;
-
-	if(ioaddr < 0x1000) {
-		while(eth16i_irqmap[i] && eth16i_irqmap[i] != irq)
-			i++;
-
-		if(i < NUM_OF_ISA_IRQS) {
-			u8 cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
-			cbyte = (cbyte & 0x3F) | (i << 6);
-			outb(cbyte, ioaddr + JUMPERLESS_CONFIG);
-			return 0;
-		}
-	}
-	else {
-		printk(KERN_NOTICE "%s: EISA Interrupt cannot be set. Use EISA Configuration utility.\n", dev->name);
-	}
-
-	return -1;
-
-}
-#endif
-
-static int __init eth16i_get_irq(int ioaddr)
-{
-	unsigned char cbyte;
-
-	if( ioaddr < 0x1000) {
-		cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
-		return eth16i_irqmap[((cbyte & 0xC0) >> 6)];
-	} else {  /* Oh..the card is EISA so method getting IRQ different */
-		unsigned short index = 0;
-		cbyte = inb(ioaddr + EISA_IRQ_REG);
-		while( (cbyte & 0x01) == 0) {
-			cbyte = cbyte >> 1;
-			index++;
-		}
-		return eth32i_irqmap[index];
-	}
-}
-
-static int __init eth16i_check_signature(int ioaddr)
-{
-	int i;
-	unsigned char creg[4] = { 0 };
-
-	for(i = 0; i < 4 ; i++) {
-
-		creg[i] = inb(ioaddr + TRANSMIT_MODE_REG + i);
-
-		if(eth16i_debug > 1)
-			printk("eth16i: read signature byte %x at %x\n",
-			       creg[i],
-			       ioaddr + TRANSMIT_MODE_REG + i);
-	}
-
-	creg[0] &= 0x0F;      /* Mask collision cnr */
-	creg[2] &= 0x7F;      /* Mask DCLEN bit */
-
-#if 0
-	/*
-	   This was removed because the card was sometimes left to state
-	   from which it couldn't be find anymore. If there is need
-	   to more strict check still this have to be fixed.
-	   */
-	if( ! ((creg[0] == 0x06) && (creg[1] == 0x41)) ) {
-		if(creg[1] != 0x42)
-			return -1;
-	}
-#endif
-
-	if( !((creg[2] == 0x36) && (creg[3] == 0xE0)) ) {
-		creg[2] &= 0x40;
-		creg[3] &= 0x03;
-
-		if( !((creg[2] == 0x40) && (creg[3] == 0x00)) )
-			return -1;
-	}
-
-	if(eth16i_read_eeprom(ioaddr, E_NODEID_0) != 0)
-		return -1;
-
-	if((eth16i_read_eeprom(ioaddr, E_NODEID_1) & 0xFF00) != 0x4B00)
-		return -1;
-
-	return 0;
-}
-
-static int eth16i_read_eeprom(int ioaddr, int offset)
-{
-	int data = 0;
-
-	eth16i_eeprom_cmd(ioaddr, EEPROM_READ | offset);
-	outb(CS_1, ioaddr + EEPROM_CTRL_REG);
-	data = eth16i_read_eeprom_word(ioaddr);
-	outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
-
-	return data;
-}
-
-static int eth16i_read_eeprom_word(int ioaddr)
-{
-	int i;
-	int data = 0;
-
-	for(i = 16; i > 0; i--) {
-		outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
-		eeprom_slow_io();
-		outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
-		eeprom_slow_io();
-		data = (data << 1) |
-			((inb(ioaddr + EEPROM_DATA_REG) & DI_1) ? 1 : 0);
-
-		eeprom_slow_io();
-	}
-
-	return data;
-}
-
-static void eth16i_eeprom_cmd(int ioaddr, unsigned char command)
-{
-	int i;
-
-	outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
-	outb(DI_0, ioaddr + EEPROM_DATA_REG);
-	outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
-	outb(DI_1, ioaddr + EEPROM_DATA_REG);
-	outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
-
-	for(i = 7; i >= 0; i--) {
-		short cmd = ( (command & (1 << i)) ? DI_1 : DI_0 );
-		outb(cmd, ioaddr + EEPROM_DATA_REG);
-		outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
-		eeprom_slow_io();
-		outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
-		eeprom_slow_io();
-	}
-}
-
-static int eth16i_open(struct net_device *dev)
-{
-	struct eth16i_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-
-	/* Powerup the chip */
-	outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
-
-	/* Initialize the chip */
-	eth16i_initialize(dev, 0);
-
-	/* Set the transmit buffer size */
-	lp->tx_buf_size = eth16i_tx_buf_map[ETH16I_TX_BUF_SIZE & 0x03];
-
-	if(eth16i_debug > 0)
-		printk(KERN_DEBUG "%s: transmit buffer size %d\n",
-		       dev->name, lp->tx_buf_size);
-
-	/* Now enable Transmitter and Receiver sections */
-	BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
-
-	/* Now switch to register bank 2, for run time operation */
-	eth16i_select_regbank(2, ioaddr);
-
-	lp->open_time = jiffies;
-	lp->tx_started = 0;
-	lp->tx_queue = 0;
-	lp->tx_queue_len = 0;
-
-	/* Turn on interrupts*/
-	outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-
-	netif_start_queue(dev);
-	return 0;
-}
-
-static int eth16i_close(struct net_device *dev)
-{
-	struct eth16i_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-
-	eth16i_reset(dev);
-
-	/* Turn off interrupts*/
-	outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
-
-	netif_stop_queue(dev);
-
-	lp->open_time = 0;
-
-	/* Disable transmit and receive */
-	BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
-
-	/* Reset the chip */
-	/* outb(0xff, ioaddr + RESET); */
-	/* outw(0xffff, ioaddr + TX_STATUS_REG);    */
-
-	outb(0x00, ioaddr + CONFIG_REG_1);
-
-	return 0;
-}
-
-static void eth16i_timeout(struct net_device *dev)
-{
-	struct eth16i_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-	/*
-	   If we get here, some higher level has decided that
-	   we are broken. There should really be a "kick me"
-	   function call instead.
-	   */
-
-	outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
-	printk(KERN_WARNING "%s: transmit timed out with status %04x, %s ?\n",
-	       dev->name,
-	inw(ioaddr + TX_STATUS_REG),  (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ?
-		       "IRQ conflict" : "network cable problem");
-
-	dev->trans_start = jiffies; /* prevent tx timeout */
-
-	/* Let's dump all registers */
-	if(eth16i_debug > 0) {
-		printk(KERN_DEBUG "%s: timeout: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
-		       dev->name, inb(ioaddr + 0),
-		       inb(ioaddr + 1), inb(ioaddr + 2),
-		       inb(ioaddr + 3), inb(ioaddr + 4),
-		       inb(ioaddr + 5),
-		       inb(ioaddr + 6), inb(ioaddr + 7));
-
-		printk(KERN_DEBUG "%s: transmit start reg: %02x. collision reg %02x\n",
-		       dev->name, inb(ioaddr + TRANSMIT_START_REG),
-		       inb(ioaddr + COL_16_REG));
-			printk(KERN_DEBUG "lp->tx_queue = %d\n", lp->tx_queue);
-		printk(KERN_DEBUG "lp->tx_queue_len = %d\n", lp->tx_queue_len);
-		printk(KERN_DEBUG "lp->tx_started = %d\n", lp->tx_started);
-	}
-	dev->stats.tx_errors++;
-	eth16i_reset(dev);
-	dev->trans_start = jiffies; /* prevent tx timeout */
-	outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-	netif_wake_queue(dev);
-}
-
-static netdev_tx_t eth16i_tx(struct sk_buff *skb, struct net_device *dev)
-{
-	struct eth16i_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-	int status = 0;
-	ushort length = skb->len;
-	unsigned char *buf;
-	unsigned long flags;
-
-	if (length < ETH_ZLEN) {
-		if (skb_padto(skb, ETH_ZLEN))
-			return NETDEV_TX_OK;
-		length = ETH_ZLEN;
-	}
-	buf = skb->data;
-
-	netif_stop_queue(dev);
-
-	/* Turn off TX interrupts */
-	outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
-
-	/* We would be better doing the disable_irq tricks the 3c509 does,
-	   that would make this suck a lot less */
-
-	spin_lock_irqsave(&lp->lock, flags);
-
-	if( (length + 2) > (lp->tx_buf_size - lp->tx_queue_len)) {
-		if(eth16i_debug > 0)
-			printk(KERN_WARNING "%s: Transmit buffer full.\n", dev->name);
-	}
-	else {
-		outw(length, ioaddr + DATAPORT);
-
-		if( ioaddr < 0x1000 )
-			outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
-		else {
-			unsigned char frag = length % 4;
-			outsl(ioaddr + DATAPORT, buf, length >> 2);
-			if( frag != 0 ) {
-				outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1);
-				if( frag == 3 )
-					outsw(ioaddr + DATAPORT,
-					      (buf + (length & 0xFFFC) + 2), 1);
-			}
-		}
-		lp->tx_buffered_packets++;
-		lp->tx_buffered_bytes = length;
-		lp->tx_queue++;
-		lp->tx_queue_len += length + 2;
-	}
-	lp->tx_buf_busy = 0;
-
-	if(lp->tx_started == 0) {
-		/* If the transmitter is idle..always trigger a transmit */
-		outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
-		lp->tx_queue = 0;
-		lp->tx_queue_len = 0;
-		lp->tx_started = 1;
-		netif_wake_queue(dev);
-	}
-	else if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
-		/* There is still more room for one more packet in tx buffer */
-		netif_wake_queue(dev);
-	}
-
-	spin_unlock_irqrestore(&lp->lock, flags);
-
-	outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-	/* Turn TX interrupts back on */
-	/* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */
-	status = 0;
-	dev_kfree_skb(skb);
-	return NETDEV_TX_OK;
-}
-
-static void eth16i_rx(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	int boguscount = MAX_RX_LOOP;
-
-	/* Loop until all packets have been read */
-	while( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) {
-
-		/* Read status byte from receive buffer */
-		ushort status = inw(ioaddr + DATAPORT);
-
-		/* Get the size of the packet from receive buffer */
-		ushort pkt_len = inw(ioaddr + DATAPORT);
-
-		if(eth16i_debug > 4)
-			printk(KERN_DEBUG "%s: Receiving packet mode %02x status %04x.\n",
-			       dev->name,
-			       inb(ioaddr + RECEIVE_MODE_REG), status);
-
-		if( !(status & PKT_GOOD) ) {
-			dev->stats.rx_errors++;
-
-			if( (pkt_len < ETH_ZLEN) || (pkt_len > ETH_FRAME_LEN) ) {
-				dev->stats.rx_length_errors++;
-				eth16i_reset(dev);
-				return;
-			}
-			else {
-				eth16i_skip_packet(dev);
-				dev->stats.rx_dropped++;
-			}
-		}
-		else {   /* Ok so now we should have a good packet */
-			struct sk_buff *skb;
-
-			skb = dev_alloc_skb(pkt_len + 3);
-			if( skb == NULL ) {
-				printk(KERN_WARNING "%s: Could'n allocate memory for packet (len %d)\n",
-				       dev->name, pkt_len);
-				eth16i_skip_packet(dev);
-				dev->stats.rx_dropped++;
-				break;
-			}
-
-			skb_reserve(skb,2);
-
-			/*
-			   Now let's get the packet out of buffer.
-			   size is (pkt_len + 1) >> 1, cause we are now reading words
-			   and it have to be even aligned.
-			   */
-
-			if(ioaddr < 0x1000)
-				insw(ioaddr + DATAPORT, skb_put(skb, pkt_len),
-				     (pkt_len + 1) >> 1);
-			else {
-				unsigned char *buf = skb_put(skb, pkt_len);
-				unsigned char frag = pkt_len % 4;
-
-				insl(ioaddr + DATAPORT, buf, pkt_len >> 2);
-
-				if(frag != 0) {
-					unsigned short rest[2];
-					rest[0] = inw( ioaddr + DATAPORT );
-					if(frag == 3)
-						rest[1] = inw( ioaddr + DATAPORT );
-
-					memcpy(buf + (pkt_len & 0xfffc), (char *)rest, frag);
-				}
-			}
-
-			skb->protocol=eth_type_trans(skb, dev);
-
-			if( eth16i_debug > 5 ) {
-				int i;
-				printk(KERN_DEBUG "%s: Received packet of length %d.\n",
-				       dev->name, pkt_len);
-				for(i = 0; i < 14; i++)
-					printk(KERN_DEBUG " %02x", skb->data[i]);
-				printk(KERN_DEBUG ".\n");
-			}
-			netif_rx(skb);
-			dev->stats.rx_packets++;
-			dev->stats.rx_bytes += pkt_len;
-
-		} /* else */
-
-		if(--boguscount <= 0)
-			break;
-
-	} /* while */
-}
-
-static irqreturn_t eth16i_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct eth16i_local *lp;
-	int ioaddr = 0, status;
-	int handled = 0;
-
-	ioaddr = dev->base_addr;
-	lp = netdev_priv(dev);
-
-	/* Turn off all interrupts from adapter */
-	outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
-
-	/* eth16i_tx won't be called */
-	spin_lock(&lp->lock);
-
-	status = inw(ioaddr + TX_STATUS_REG);      /* Get the status */
-	outw(status, ioaddr + TX_STATUS_REG);      /* Clear status bits */
-
-	if (status)
-		handled = 1;
-
-	if(eth16i_debug > 3)
-		printk(KERN_DEBUG "%s: Interrupt with status %04x.\n", dev->name, status);
-
-	if( status & 0x7f00 ) {
-
-		dev->stats.rx_errors++;
-
-		if(status & (BUS_RD_ERR << 8) )
-			printk(KERN_WARNING "%s: Bus read error.\n",dev->name);
-		if(status & (SHORT_PKT_ERR << 8) )   dev->stats.rx_length_errors++;
-		if(status & (ALIGN_ERR << 8) )       dev->stats.rx_frame_errors++;
-		if(status & (CRC_ERR << 8) )	    dev->stats.rx_crc_errors++;
-		if(status & (RX_BUF_OVERFLOW << 8) ) dev->stats.rx_over_errors++;
-	}
-	if( status & 0x001a) {
-
-		dev->stats.tx_errors++;
-
-		if(status & CR_LOST) dev->stats.tx_carrier_errors++;
-		if(status & TX_JABBER_ERR) dev->stats.tx_window_errors++;
-
-#if 0
-		if(status & COLLISION) {
-			dev->stats.collisions +=
-				((inb(ioaddr+TRANSMIT_MODE_REG) & 0xF0) >> 4);
-		}
-#endif
-		if(status & COLLISIONS_16) {
-			if(lp->col_16 < MAX_COL_16) {
-				lp->col_16++;
-				dev->stats.collisions++;
-				/* Resume transmitting, skip failed packet */
-				outb(0x02, ioaddr + COL_16_REG);
-			}
-			else {
-				printk(KERN_WARNING "%s: bailing out due to many consecutive 16-in-a-row collisions. Network cable problem?\n", dev->name);
-			}
-		}
-	}
-
-	if( status & 0x00ff ) {          /* Let's check the transmit status reg */
-
-		if(status & TX_DONE) {         /* The transmit has been done */
-			dev->stats.tx_packets = lp->tx_buffered_packets;
-			dev->stats.tx_bytes += lp->tx_buffered_bytes;
-			lp->col_16 = 0;
-
-			if(lp->tx_queue) {           /* Is there still packets ? */
-				/* There was packet(s) so start transmitting and write also
-				   how many packets there is to be sended */
-				outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
-				lp->tx_queue = 0;
-				lp->tx_queue_len = 0;
-				lp->tx_started = 1;
-			}
-			else {
-				lp->tx_started = 0;
-			}
-			netif_wake_queue(dev);
-		}
-	}
-
-	if( ( status & 0x8000 ) ||
-	    ( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) ) {
-		eth16i_rx(dev);  /* We have packet in receive buffer */
-	}
-
-	/* Turn interrupts back on */
-	outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-
-	if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
-		/* There is still more room for one more packet in tx buffer */
-		netif_wake_queue(dev);
-	}
-
-	spin_unlock(&lp->lock);
-
-	return IRQ_RETVAL(handled);
-}
-
-static void eth16i_skip_packet(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-
-	inw(ioaddr + DATAPORT);
-	inw(ioaddr + DATAPORT);
-	inw(ioaddr + DATAPORT);
-
-	outb(SKIP_RX_PACKET, ioaddr + FILTER_SELF_RX_REG);
-	while( inb( ioaddr + FILTER_SELF_RX_REG ) != 0);
-}
-
-static void eth16i_reset(struct net_device *dev)
-{
-	struct eth16i_local *lp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-
-	if(eth16i_debug > 1)
-		printk(KERN_DEBUG "%s: Resetting device.\n", dev->name);
-
-	BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
-	outw(0xffff, ioaddr + TX_STATUS_REG);
-	eth16i_select_regbank(2, ioaddr);
-
-	lp->tx_started = 0;
-	lp->tx_buf_busy = 0;
-	lp->tx_queue = 0;
-	lp->tx_queue_len = 0;
-	BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
-}
-
-static void eth16i_multicast(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-
-	if (!netdev_mc_empty(dev) || dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
-	{
-		outb(3, ioaddr + RECEIVE_MODE_REG);
-	} else {
-		outb(2, ioaddr + RECEIVE_MODE_REG);
-	}
-}
-
-static void eth16i_select_regbank(unsigned char banknbr, int ioaddr)
-{
-	unsigned char data;
-
-	data = inb(ioaddr + CONFIG_REG_1);
-	outb( ((data & 0xF3) | ( (banknbr & 0x03) << 2)), ioaddr + CONFIG_REG_1);
-}
-
-#ifdef MODULE
-
-static ushort eth16i_parse_mediatype(const char* s)
-{
-	if(!s)
-		return E_PORT_FROM_EPROM;
-
-        if (!strncmp(s, "bnc", 3))
-		return E_PORT_BNC;
-        else if (!strncmp(s, "tp", 2))
-                return E_PORT_TP;
-        else if (!strncmp(s, "dix", 3))
-                return E_PORT_DIX;
-        else if (!strncmp(s, "auto", 4))
-		return E_PORT_AUTO;
-	else
-		return E_PORT_FROM_EPROM;
-}
-
-#define MAX_ETH16I_CARDS 4  /* Max number of Eth16i cards per module */
-
-static struct net_device *dev_eth16i[MAX_ETH16I_CARDS];
-static int io[MAX_ETH16I_CARDS];
-#if 0
-static int irq[MAX_ETH16I_CARDS];
-#endif
-static char* mediatype[MAX_ETH16I_CARDS];
-static int debug = -1;
-
-MODULE_AUTHOR("Mika Kuoppala <miku@iki.fi>");
-MODULE_DESCRIPTION("ICL EtherTeam 16i/32 driver");
-MODULE_LICENSE("GPL");
-
-
-module_param_array(io, int, NULL, 0);
-MODULE_PARM_DESC(io, "eth16i I/O base address(es)");
-
-#if 0
-module_param_array(irq, int, NULL, 0);
-MODULE_PARM_DESC(irq, "eth16i interrupt request number");
-#endif
-
-module_param_array(mediatype, charp, NULL, 0);
-MODULE_PARM_DESC(mediatype, "eth16i media type of interface(s) (bnc,tp,dix,auto,eprom)");
-
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "eth16i debug level (0-6)");
-
-int __init init_module(void)
-{
-	int this_dev, found = 0;
-	struct net_device *dev;
-
-	for (this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++) {
-		dev = alloc_etherdev(sizeof(struct eth16i_local));
-		if (!dev)
-			break;
-
-		dev->base_addr = io[this_dev];
-
-	        if(debug != -1)
-			eth16i_debug = debug;
-
-		if(eth16i_debug > 1)
-			printk(KERN_NOTICE "eth16i(%d): interface type %s\n", this_dev, mediatype[this_dev] ? mediatype[this_dev] : "none" );
-
-		dev->if_port = eth16i_parse_mediatype(mediatype[this_dev]);
-
-		if(io[this_dev] == 0) {
-			if (this_dev != 0) { /* Only autoprobe 1st one */
-				free_netdev(dev);
-				break;
-			}
-
-			printk(KERN_NOTICE "eth16i.c: Presently autoprobing (not recommended) for a single card.\n");
-		}
-
-		if (do_eth16i_probe(dev) == 0) {
-			dev_eth16i[found++] = dev;
-			continue;
-		}
-		printk(KERN_WARNING "eth16i.c No Eth16i card found (i/o = 0x%x).\n",
-		       io[this_dev]);
-		free_netdev(dev);
-		break;
-	}
-	if (found)
-		return 0;
-	return -ENXIO;
-}
-
-void __exit cleanup_module(void)
-{
-	int this_dev;
-
-	for(this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++) {
-		struct net_device *dev = dev_eth16i[this_dev];
-
-		if (netdev_priv(dev)) {
-			unregister_netdev(dev);
-			free_irq(dev->irq, dev);
-			release_region(dev->base_addr, ETH16I_IO_EXTENT);
-			free_netdev(dev);
-		}
-	}
-}
-#endif /* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/3com/3c501.c linux-libre-3.2-gnu/drivers/net/ethernet/3com/3c501.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/3com/3c501.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/3com/3c501.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,896 @@
+/* 3c501.c: A 3Com 3c501 Ethernet driver for Linux. */
+/*
+    Written 1992,1993,1994  Donald Becker
+
+    Copyright 1993 United States Government as represented by the
+    Director, National Security Agency.  This software may be used and
+    distributed according to the terms of the GNU General Public License,
+    incorporated herein by reference.
+
+    This is a device driver for the 3Com Etherlink 3c501.
+    Do not purchase this card, even as a joke.  It's performance is horrible,
+    and it breaks in many ways.
+
+    The original author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+    Fixed (again!) the missing interrupt locking on TX/RX shifting.
+	Alan Cox <alan@lxorguk.ukuu.org.uk>
+
+    Removed calls to init_etherdev since they are no longer needed, and
+    cleaned up modularization just a bit. The driver still allows only
+    the default address for cards when loaded as a module, but that's
+    really less braindead than anyone using a 3c501 board. :)
+		    19950208 (invid@msen.com)
+
+    Added traps for interrupts hitting the window as we clear and TX load
+    the board. Now getting 150K/second FTP with a 3c501 card. Still playing
+    with a TX-TX optimisation to see if we can touch 180-200K/second as seems
+    theoretically maximum.
+		19950402 Alan Cox <alan@lxorguk.ukuu.org.uk>
+
+    Cleaned up for 2.3.x because we broke SMP now.
+		20000208 Alan Cox <alan@lxorguk.ukuu.org.uk>
+
+    Check up pass for 2.5. Nothing significant changed
+		20021009 Alan Cox <alan@lxorguk.ukuu.org.uk>
+
+    Fixed zero fill corner case
+		20030104 Alan Cox <alan@lxorguk.ukuu.org.uk>
+
+
+   For the avoidance of doubt the "preferred form" of this code is one which
+   is in an open non patent encumbered format. Where cryptographic key signing
+   forms part of the process of creating an executable the information
+   including keys needed to generate an equivalently functional executable
+   are deemed to be part of the source code.
+
+*/
+
+
+/**
+ * DOC: 3c501 Card Notes
+ *
+ *  Some notes on this thing if you have to hack it.  [Alan]
+ *
+ *  Some documentation is available from 3Com. Due to the boards age
+ *  standard responses when you ask for this will range from 'be serious'
+ *  to 'give it to a museum'. The documentation is incomplete and mostly
+ *  of historical interest anyway.
+ *
+ *  The basic system is a single buffer which can be used to receive or
+ *  transmit a packet. A third command mode exists when you are setting
+ *  things up.
+ *
+ *  If it's transmitting it's not receiving and vice versa. In fact the
+ *  time to get the board back into useful state after an operation is
+ *  quite large.
+ *
+ *  The driver works by keeping the board in receive mode waiting for a
+ *  packet to arrive. When one arrives it is copied out of the buffer
+ *  and delivered to the kernel. The card is reloaded and off we go.
+ *
+ *  When transmitting lp->txing is set and the card is reset (from
+ *  receive mode) [possibly losing a packet just received] to command
+ *  mode. A packet is loaded and transmit mode triggered. The interrupt
+ *  handler runs different code for transmit interrupts and can handle
+ *  returning to receive mode or retransmissions (yes you have to help
+ *  out with those too).
+ *
+ * DOC: Problems
+ *
+ *  There are a wide variety of undocumented error returns from the card
+ *  and you basically have to kick the board and pray if they turn up. Most
+ *  only occur under extreme load or if you do something the board doesn't
+ *  like (eg touching a register at the wrong time).
+ *
+ *  The driver is less efficient than it could be. It switches through
+ *  receive mode even if more transmits are queued. If this worries you buy
+ *  a real Ethernet card.
+ *
+ *  The combination of slow receive restart and no real multicast
+ *  filter makes the board unusable with a kernel compiled for IP
+ *  multicasting in a real multicast environment. That's down to the board,
+ *  but even with no multicast programs running a multicast IP kernel is
+ *  in group 224.0.0.1 and you will therefore be listening to all multicasts.
+ *  One nv conference running over that Ethernet and you can give up.
+ *
+ */
+
+#define DRV_NAME	"3c501"
+#define DRV_VERSION	"2002/10/09"
+
+
+static const char version[] =
+	DRV_NAME ".c: " DRV_VERSION " Alan Cox (alan@lxorguk.ukuu.org.uk).\n";
+
+/*
+ *	Braindamage remaining:
+ *	The 3c501 board.
+ */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/fcntl.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+#include <linux/ethtool.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+
+#include "3c501.h"
+
+/*
+ *	The boilerplate probe code.
+ */
+
+static int io = 0x280;
+static int irq = 5;
+static int mem_start;
+
+/**
+ * el1_probe:		-	probe for a 3c501
+ * @dev: The device structure passed in to probe.
+ *
+ * This can be called from two places. The network layer will probe using
+ * a device structure passed in with the probe information completed. For a
+ * modular driver we use #init_module to fill in our own structure and probe
+ * for it.
+ *
+ * Returns 0 on success. ENXIO if asked not to probe and ENODEV if asked to
+ * probe and failing to find anything.
+ */
+
+struct net_device * __init el1_probe(int unit)
+{
+	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
+	static const unsigned ports[] = { 0x280, 0x300, 0};
+	const unsigned *port;
+	int err = 0;
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	if (unit >= 0) {
+		sprintf(dev->name, "eth%d", unit);
+		netdev_boot_setup_check(dev);
+		io = dev->base_addr;
+		irq = dev->irq;
+		mem_start = dev->mem_start & 7;
+	}
+
+	if (io > 0x1ff) {	/* Check a single specified location. */
+		err = el1_probe1(dev, io);
+	} else if (io != 0) {
+		err = -ENXIO;		/* Don't probe at all. */
+	} else {
+		for (port = ports; *port && el1_probe1(dev, *port); port++)
+			;
+		if (!*port)
+			err = -ENODEV;
+	}
+	if (err)
+		goto out;
+	err = register_netdev(dev);
+	if (err)
+		goto out1;
+	return dev;
+out1:
+	release_region(dev->base_addr, EL1_IO_EXTENT);
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+
+static const struct net_device_ops el_netdev_ops = {
+	.ndo_open		= el_open,
+	.ndo_stop		= el1_close,
+	.ndo_start_xmit 	= el_start_xmit,
+	.ndo_tx_timeout		= el_timeout,
+	.ndo_set_rx_mode	= set_multicast_list,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+/**
+ *	el1_probe1:
+ *	@dev: The device structure to use
+ *	@ioaddr: An I/O address to probe at.
+ *
+ *	The actual probe. This is iterated over by #el1_probe in order to
+ *	check all the applicable device locations.
+ *
+ *	Returns 0 for a success, in which case the device is activated,
+ *	EAGAIN if the IRQ is in use by another driver, and ENODEV if the
+ *	board cannot be found.
+ */
+
+static int __init el1_probe1(struct net_device *dev, int ioaddr)
+{
+	struct net_local *lp;
+	const char *mname;		/* Vendor name */
+	unsigned char station_addr[6];
+	int autoirq = 0;
+	int i;
+
+	/*
+	 *	Reserve I/O resource for exclusive use by this driver
+	 */
+
+	if (!request_region(ioaddr, EL1_IO_EXTENT, DRV_NAME))
+		return -ENODEV;
+
+	/*
+	 *	Read the station address PROM data from the special port.
+	 */
+
+	for (i = 0; i < 6; i++) {
+		outw(i, ioaddr + EL1_DATAPTR);
+		station_addr[i] = inb(ioaddr + EL1_SAPROM);
+	}
+	/*
+	 *	Check the first three octets of the S.A. for 3Com's prefix, or
+	 *	for the Sager NP943 prefix.
+	 */
+
+	if (station_addr[0] == 0x02 && station_addr[1] == 0x60 &&
+	    station_addr[2] == 0x8c)
+		mname = "3c501";
+	else if (station_addr[0] == 0x00 && station_addr[1] == 0x80 &&
+		 station_addr[2] == 0xC8)
+		mname = "NP943";
+	else {
+		release_region(ioaddr, EL1_IO_EXTENT);
+		return -ENODEV;
+	}
+
+	/*
+	 *	We auto-IRQ by shutting off the interrupt line and letting it
+	 *	float high.
+	 */
+
+	dev->irq = irq;
+
+	if (dev->irq < 2) {
+		unsigned long irq_mask;
+
+		irq_mask = probe_irq_on();
+		inb(RX_STATUS);		/* Clear pending interrupts. */
+		inb(TX_STATUS);
+		outb(AX_LOOP + 1, AX_CMD);
+
+		outb(0x00, AX_CMD);
+
+		mdelay(20);
+		autoirq = probe_irq_off(irq_mask);
+
+		if (autoirq == 0) {
+			pr_warning("%s probe at %#x failed to detect IRQ line.\n",
+				mname, ioaddr);
+			release_region(ioaddr, EL1_IO_EXTENT);
+			return -EAGAIN;
+		}
+	}
+
+	outb(AX_RESET+AX_LOOP, AX_CMD);			/* Loopback mode. */
+	dev->base_addr = ioaddr;
+	memcpy(dev->dev_addr, station_addr, ETH_ALEN);
+
+	if (mem_start & 0xf)
+		el_debug = mem_start & 0x7;
+	if (autoirq)
+		dev->irq = autoirq;
+
+	pr_info("%s: %s EtherLink at %#lx, using %sIRQ %d.\n",
+			dev->name, mname, dev->base_addr,
+			autoirq ? "auto":"assigned ", dev->irq);
+
+#ifdef CONFIG_IP_MULTICAST
+	pr_warning("WARNING: Use of the 3c501 in a multicast kernel is NOT recommended.\n");
+#endif
+
+	if (el_debug)
+		pr_debug("%s", version);
+
+	lp = netdev_priv(dev);
+	memset(lp, 0, sizeof(struct net_local));
+	spin_lock_init(&lp->lock);
+
+	/*
+	 *	The EL1-specific entries in the device structure.
+	 */
+
+	dev->netdev_ops = &el_netdev_ops;
+	dev->watchdog_timeo = HZ;
+	dev->ethtool_ops = &netdev_ethtool_ops;
+	return 0;
+}
+
+/**
+ *	el1_open:
+ *	@dev: device that is being opened
+ *
+ *	When an ifconfig is issued which changes the device flags to include
+ *	IFF_UP this function is called. It is only called when the change
+ *	occurs, not when the interface remains up. #el1_close will be called
+ *	when it goes down.
+ *
+ *	Returns 0 for a successful open, or -EAGAIN if someone has run off
+ *	with our interrupt line.
+ */
+
+static int el_open(struct net_device *dev)
+{
+	int retval;
+	int ioaddr = dev->base_addr;
+	struct net_local *lp = netdev_priv(dev);
+	unsigned long flags;
+
+	if (el_debug > 2)
+		pr_debug("%s: Doing el_open()...\n", dev->name);
+
+	retval = request_irq(dev->irq, el_interrupt, 0, dev->name, dev);
+	if (retval)
+		return retval;
+
+	spin_lock_irqsave(&lp->lock, flags);
+	el_reset(dev);
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	lp->txing = 0;		/* Board in RX mode */
+	outb(AX_RX, AX_CMD);	/* Aux control, irq and receive enabled */
+	netif_start_queue(dev);
+	return 0;
+}
+
+/**
+ * el_timeout:
+ * @dev: The 3c501 card that has timed out
+ *
+ * Attempt to restart the board. This is basically a mixture of extreme
+ * violence and prayer
+ *
+ */
+
+static void el_timeout(struct net_device *dev)
+{
+	struct net_local *lp = netdev_priv(dev);
+	int ioaddr = dev->base_addr;
+
+	if (el_debug)
+		pr_debug("%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n",
+			dev->name, inb(TX_STATUS),
+			inb(AX_STATUS), inb(RX_STATUS));
+	dev->stats.tx_errors++;
+	outb(TX_NORM, TX_CMD);
+	outb(RX_NORM, RX_CMD);
+	outb(AX_OFF, AX_CMD);	/* Just trigger a false interrupt. */
+	outb(AX_RX, AX_CMD);	/* Aux control, irq and receive enabled */
+	lp->txing = 0;		/* Ripped back in to RX */
+	netif_wake_queue(dev);
+}
+
+
+/**
+ * el_start_xmit:
+ * @skb: The packet that is queued to be sent
+ * @dev: The 3c501 card we want to throw it down
+ *
+ * Attempt to send a packet to a 3c501 card. There are some interesting
+ * catches here because the 3c501 is an extremely old and therefore
+ * stupid piece of technology.
+ *
+ * If we are handling an interrupt on the other CPU we cannot load a packet
+ * 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 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
+ * lock while loading 1500 bytes onto the controller we would drop a lot of
+ * serial port characters. This requires we do extra locking, but we have
+ * no real choice.
+ */
+
+static netdev_tx_t el_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct net_local *lp = netdev_priv(dev);
+	int ioaddr = dev->base_addr;
+	unsigned long flags;
+
+	/*
+	 *	Avoid incoming interrupts between us flipping txing and flipping
+	 *	mode as the driver assumes txing is a faithful indicator of card
+	 *	state
+	 */
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	/*
+	 *	Avoid timer-based retransmission conflicts.
+	 */
+
+	netif_stop_queue(dev);
+
+	do {
+		int len = skb->len;
+		int pad = 0;
+		int gp_start;
+		unsigned char *buf = skb->data;
+
+		if (len < ETH_ZLEN)
+			pad = ETH_ZLEN - len;
+
+		gp_start = 0x800 - (len + pad);
+
+		lp->tx_pkt_start = gp_start;
+		lp->collisions = 0;
+
+		dev->stats.tx_bytes += skb->len;
+
+		/*
+		 *	Command mode with status cleared should [in theory]
+		 *	mean no more interrupts can be pending on the card.
+		 */
+
+		outb_p(AX_SYS, AX_CMD);
+		inb_p(RX_STATUS);
+		inb_p(TX_STATUS);
+
+		lp->loading = 1;
+		lp->txing = 1;
+
+		/*
+		 *	Turn interrupts back on while we spend a pleasant
+		 *	afternoon loading bytes into the board
+		 */
+
+		spin_unlock_irqrestore(&lp->lock, flags);
+
+		/* Set rx packet area to 0. */
+		outw(0x00, RX_BUF_CLR);
+		/* aim - packet will be loaded into buffer start */
+		outw(gp_start, GP_LOW);
+		/* load buffer (usual thing each byte increments the pointer) */
+		outsb(DATAPORT, buf, len);
+		if (pad) {
+			while (pad--)		/* Zero fill buffer tail */
+				outb(0, DATAPORT);
+		}
+		/* the board reuses the same register */
+		outw(gp_start, GP_LOW);
+
+		if (lp->loading != 2) {
+			/* fire ... Trigger xmit.  */
+			outb(AX_XMIT, AX_CMD);
+			lp->loading = 0;
+			if (el_debug > 2)
+				pr_debug(" queued xmit.\n");
+			dev_kfree_skb(skb);
+			return NETDEV_TX_OK;
+		}
+		/* A receive upset our load, despite our best efforts */
+		if (el_debug > 2)
+			pr_debug("%s: burped during tx load.\n", dev->name);
+		spin_lock_irqsave(&lp->lock, flags);
+	} while (1);
+}
+
+/**
+ * el_interrupt:
+ * @irq: Interrupt number
+ * @dev_id: The 3c501 that burped
+ *
+ * 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 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
+ * speak of. We simply pull the packet out of its PIO buffer (which is slow)
+ * and queue it for the kernel. Then we reset the card for the next packet.
+ *
+ * We sometimes get surprise interrupts late both because the SMP IRQ delivery
+ * is message passing and because the card sometimes seems to deliver late. I
+ * think if it is part way through a receive and the mode is changed it carries
+ * on receiving and sends us an interrupt. We have to band aid all these cases
+ * to get a sensible 150kBytes/second performance. Even then you want a small
+ * TCP window.
+ */
+
+static irqreturn_t el_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct net_local *lp;
+	int ioaddr;
+	int axsr;			/* Aux. status reg. */
+
+	ioaddr = dev->base_addr;
+	lp = netdev_priv(dev);
+
+	spin_lock(&lp->lock);
+
+	/*
+	 *	What happened ?
+	 */
+
+	axsr = inb(AX_STATUS);
+
+	/*
+	 *	Log it
+	 */
+
+	if (el_debug > 3)
+		pr_debug("%s: el_interrupt() aux=%#02x\n", dev->name, axsr);
+
+	if (lp->loading == 1 && !lp->txing)
+		pr_warning("%s: Inconsistent state loading while not in tx\n",
+			dev->name);
+
+	if (lp->txing) {
+		/*
+		 *	Board in transmit mode. May be loading. If we are
+		 *	loading we shouldn't have got this.
+		 */
+		int txsr = inb(TX_STATUS);
+
+		if (lp->loading == 1) {
+			if (el_debug > 2)
+				pr_debug("%s: Interrupt while loading [txsr=%02x gp=%04x rp=%04x]\n",
+					dev->name, txsr, inw(GP_LOW), inw(RX_LOW));
+
+			/* Force a reload */
+			lp->loading = 2;
+			spin_unlock(&lp->lock);
+			goto out;
+		}
+		if (el_debug > 6)
+			pr_debug("%s: txsr=%02x gp=%04x rp=%04x\n", dev->name,
+					txsr, inw(GP_LOW), inw(RX_LOW));
+
+		if ((axsr & 0x80) && (txsr & TX_READY) == 0) {
+			/*
+			 *	FIXME: is there a logic to whether to keep
+			 *	on trying or reset immediately ?
+			 */
+			if (el_debug > 1)
+				pr_debug("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x gp=%03x rp=%03x.\n",
+					dev->name, txsr, axsr,
+					inw(ioaddr + EL1_DATAPTR),
+					inw(ioaddr + EL1_RXPTR));
+			lp->txing = 0;
+			netif_wake_queue(dev);
+		} else if (txsr & TX_16COLLISIONS) {
+			/*
+			 *	Timed out
+			 */
+			if (el_debug)
+				pr_debug("%s: Transmit failed 16 times, Ethernet jammed?\n", dev->name);
+			outb(AX_SYS, AX_CMD);
+			lp->txing = 0;
+			dev->stats.tx_aborted_errors++;
+			netif_wake_queue(dev);
+		} else if (txsr & TX_COLLISION) {
+			/*
+			 *	Retrigger xmit.
+			 */
+
+			if (el_debug > 6)
+				pr_debug("%s: retransmitting after a collision.\n", dev->name);
+			/*
+			 *	Poor little chip can't reset its own start
+			 *	pointer
+			 */
+
+			outb(AX_SYS, AX_CMD);
+			outw(lp->tx_pkt_start, GP_LOW);
+			outb(AX_XMIT, AX_CMD);
+			dev->stats.collisions++;
+			spin_unlock(&lp->lock);
+			goto out;
+		} else {
+			/*
+			 *	It worked.. we will now fall through and receive
+			 */
+			dev->stats.tx_packets++;
+			if (el_debug > 6)
+				pr_debug("%s: Tx succeeded %s\n", dev->name,
+					(txsr & TX_RDY) ? "." : "but tx is busy!");
+			/*
+			 *	This is safe the interrupt is atomic WRT itself.
+			 */
+			lp->txing = 0;
+			/* In case more to transmit */
+			netif_wake_queue(dev);
+		}
+	} else {
+		/*
+		 *	In receive mode.
+		 */
+
+		int rxsr = inb(RX_STATUS);
+		if (el_debug > 5)
+			pr_debug("%s: rxsr=%02x txsr=%02x rp=%04x\n",
+				dev->name, rxsr, inb(TX_STATUS), inw(RX_LOW));
+		/*
+		 *	Just reading rx_status fixes most errors.
+		 */
+		if (rxsr & RX_MISSED)
+			dev->stats.rx_missed_errors++;
+		else if (rxsr & RX_RUNT) {
+			/* Handled to avoid board lock-up. */
+			dev->stats.rx_length_errors++;
+			if (el_debug > 5)
+				pr_debug("%s: runt.\n", dev->name);
+		} else if (rxsr & RX_GOOD) {
+			/*
+			 *	Receive worked.
+			 */
+			el_receive(dev);
+		} else {
+			/*
+			 *	Nothing?  Something is broken!
+			 */
+			if (el_debug > 2)
+				pr_debug("%s: No packet seen, rxsr=%02x **resetting 3c501***\n",
+					dev->name, rxsr);
+			el_reset(dev);
+		}
+	}
+
+	/*
+	 *	Move into receive mode
+	 */
+
+	outb(AX_RX, AX_CMD);
+	outw(0x00, RX_BUF_CLR);
+	inb(RX_STATUS);		/* Be certain that interrupts are cleared. */
+	inb(TX_STATUS);
+	spin_unlock(&lp->lock);
+out:
+	return IRQ_HANDLED;
+}
+
+
+/**
+ * el_receive:
+ * @dev: Device to pull the packets from
+ *
+ * We have a good packet. Well, not really "good", just mostly not broken.
+ * We must check everything to see if it is good. In particular we occasionally
+ * get wild packet sizes from the card. If the packet seems sane we PIO it
+ * off the card and queue it for the protocol layers.
+ */
+
+static void el_receive(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr;
+	int pkt_len;
+	struct sk_buff *skb;
+
+	pkt_len = inw(RX_LOW);
+
+	if (el_debug > 4)
+		pr_debug(" el_receive %d.\n", pkt_len);
+
+	if (pkt_len < 60 || pkt_len > 1536) {
+		if (el_debug)
+			pr_debug("%s: bogus packet, length=%d\n",
+						dev->name, pkt_len);
+		dev->stats.rx_over_errors++;
+		return;
+	}
+
+	/*
+	 *	Command mode so we can empty the buffer
+	 */
+
+	outb(AX_SYS, AX_CMD);
+	skb = dev_alloc_skb(pkt_len+2);
+
+	/*
+	 *	Start of frame
+	 */
+
+	outw(0x00, GP_LOW);
+	if (skb == NULL) {
+		pr_info("%s: Memory squeeze, dropping packet.\n", dev->name);
+		dev->stats.rx_dropped++;
+		return;
+	} else {
+		skb_reserve(skb, 2);	/* Force 16 byte alignment */
+		/*
+		 *	The read increments through the bytes. The interrupt
+		 *	handler will fix the pointer when it returns to
+		 *	receive mode.
+		 */
+		insb(DATAPORT, skb_put(skb, pkt_len), pkt_len);
+		skb->protocol = eth_type_trans(skb, dev);
+		netif_rx(skb);
+		dev->stats.rx_packets++;
+		dev->stats.rx_bytes += pkt_len;
+	}
+}
+
+/**
+ * el_reset: Reset a 3c501 card
+ * @dev: The 3c501 card about to get zapped
+ *
+ * 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.
+ */
+
+static void  el_reset(struct net_device *dev)
+{
+	struct net_local *lp = netdev_priv(dev);
+	int ioaddr = dev->base_addr;
+
+	if (el_debug > 2)
+		pr_info("3c501 reset...\n");
+	outb(AX_RESET, AX_CMD);		/* Reset the chip */
+	/* Aux control, irq and loopback enabled */
+	outb(AX_LOOP, AX_CMD);
+	{
+		int i;
+		for (i = 0; i < 6; i++)	/* Set the station address. */
+			outb(dev->dev_addr[i], ioaddr + i);
+	}
+
+	outw(0, RX_BUF_CLR);		/* Set rx packet area to 0. */
+	outb(TX_NORM, TX_CMD);		/* tx irq on done, collision */
+	outb(RX_NORM, RX_CMD);		/* Set Rx commands. */
+	inb(RX_STATUS);			/* Clear status. */
+	inb(TX_STATUS);
+	lp->txing = 0;
+}
+
+/**
+ * el1_close:
+ * @dev: 3c501 card to shut down
+ *
+ * Close a 3c501 card. The IFF_UP flag has been cleared by the user via
+ * the SIOCSIFFLAGS ioctl. We stop any further transmissions being queued,
+ * and then disable the interrupts. Finally we reset the chip. The effects
+ * of the rest will be cleaned up by #el1_open. Always returns 0 indicating
+ * a success.
+ */
+
+static int el1_close(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr;
+
+	if (el_debug > 2)
+		pr_info("%s: Shutting down Ethernet card at %#x.\n",
+						dev->name, ioaddr);
+
+	netif_stop_queue(dev);
+
+	/*
+	 *	Free and disable the IRQ.
+	 */
+
+	free_irq(dev->irq, dev);
+	outb(AX_RESET, AX_CMD);		/* Reset the chip */
+
+	return 0;
+}
+
+/**
+ * set_multicast_list:
+ * @dev: The device to adjust
+ *
+ * Set or clear the multicast filter for this adaptor to use the best-effort
+ * filtering supported. The 3c501 supports only three modes of filtering.
+ * It always receives broadcasts and packets for itself. You can choose to
+ * optionally receive all packets, or all multicast packets on top of this.
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr;
+
+	if (dev->flags & IFF_PROMISC) {
+		outb(RX_PROM, RX_CMD);
+		inb(RX_STATUS);
+	} else if (!netdev_mc_empty(dev) || dev->flags & IFF_ALLMULTI) {
+		/* Multicast or all multicast is the same */
+		outb(RX_MULT, RX_CMD);
+		inb(RX_STATUS);		/* Clear status. */
+	} else {
+		outb(RX_NORM, RX_CMD);
+		inb(RX_STATUS);
+	}
+}
+
+
+static void netdev_get_drvinfo(struct net_device *dev,
+			       struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	sprintf(info->bus_info, "ISA 0x%lx", dev->base_addr);
+}
+
+static u32 netdev_get_msglevel(struct net_device *dev)
+{
+	return debug;
+}
+
+static void netdev_set_msglevel(struct net_device *dev, u32 level)
+{
+	debug = level;
+}
+
+static const struct ethtool_ops netdev_ethtool_ops = {
+	.get_drvinfo		= netdev_get_drvinfo,
+	.get_msglevel		= netdev_get_msglevel,
+	.set_msglevel		= netdev_set_msglevel,
+};
+
+#ifdef MODULE
+
+static struct net_device *dev_3c501;
+
+module_param(io, int, 0);
+module_param(irq, int, 0);
+MODULE_PARM_DESC(io, "EtherLink I/O base address");
+MODULE_PARM_DESC(irq, "EtherLink IRQ number");
+
+/**
+ * init_module:
+ *
+ * When the driver is loaded as a module this function is called. We fake up
+ * a device structure with the base I/O and interrupt set as if it were being
+ * called from Space.c. This minimises the extra code that would otherwise
+ * be required.
+ *
+ * Returns 0 for success or -EIO if a card is not found. Returning an error
+ * here also causes the module to be unloaded
+ */
+
+int __init init_module(void)
+{
+	dev_3c501 = el1_probe(-1);
+	if (IS_ERR(dev_3c501))
+		return PTR_ERR(dev_3c501);
+	return 0;
+}
+
+/**
+ * cleanup_module:
+ *
+ * The module is being unloaded. We unhook our network device from the system
+ * and then free up the resources we took when the card was found.
+ */
+
+void __exit cleanup_module(void)
+{
+	struct net_device *dev = dev_3c501;
+	unregister_netdev(dev);
+	release_region(dev->base_addr, EL1_IO_EXTENT);
+	free_netdev(dev);
+}
+
+#endif /* MODULE */
+
+MODULE_AUTHOR("Donald Becker, Alan Cox");
+MODULE_DESCRIPTION("Support for the ancient 3Com 3c501 ethernet card");
+MODULE_LICENSE("GPL");
+
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/3com/3c501.h linux-libre-3.2-gnu/drivers/net/ethernet/3com/3c501.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/3com/3c501.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/3com/3c501.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,91 @@
+
+/*
+ *	Index to functions.
+ */
+
+static int  el1_probe1(struct net_device *dev, int ioaddr);
+static int  el_open(struct net_device *dev);
+static void el_timeout(struct net_device *dev);
+static netdev_tx_t el_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static irqreturn_t el_interrupt(int irq, void *dev_id);
+static void el_receive(struct net_device *dev);
+static void el_reset(struct net_device *dev);
+static int  el1_close(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+static const struct ethtool_ops netdev_ethtool_ops;
+
+#define EL1_IO_EXTENT	16
+
+#ifndef EL_DEBUG
+#define EL_DEBUG  0	/* use 0 for production, 1 for devel., >2 for debug */
+#endif			/* Anything above 5 is wordy death! */
+#define debug el_debug
+static int el_debug = EL_DEBUG;
+
+/*
+ *	Board-specific info in netdev_priv(dev).
+ */
+
+struct net_local
+{
+	int		tx_pkt_start;	/* The length of the current Tx packet. */
+	int		collisions;	/* Tx collisions this packet */
+	int		loading;	/* Spot buffer load collisions */
+	int		txing;		/* True if card is in TX mode */
+	spinlock_t	lock;		/* Serializing lock */
+};
+
+
+#define RX_STATUS (ioaddr + 0x06)
+#define RX_CMD	  RX_STATUS
+#define TX_STATUS (ioaddr + 0x07)
+#define TX_CMD	  TX_STATUS
+#define GP_LOW 	  (ioaddr + 0x08)
+#define GP_HIGH   (ioaddr + 0x09)
+#define RX_BUF_CLR (ioaddr + 0x0A)
+#define RX_LOW	  (ioaddr + 0x0A)
+#define RX_HIGH   (ioaddr + 0x0B)
+#define SAPROM	  (ioaddr + 0x0C)
+#define AX_STATUS (ioaddr + 0x0E)
+#define AX_CMD	  AX_STATUS
+#define DATAPORT  (ioaddr + 0x0F)
+#define TX_RDY 0x08		/* In TX_STATUS */
+
+#define EL1_DATAPTR	0x08
+#define EL1_RXPTR	0x0A
+#define EL1_SAPROM	0x0C
+#define EL1_DATAPORT 	0x0f
+
+/*
+ *	Writes to the ax command register.
+ */
+
+#define AX_OFF	0x00			/* Irq off, buffer access on */
+#define AX_SYS  0x40			/* Load the buffer */
+#define AX_XMIT 0x44			/* Transmit a packet */
+#define AX_RX	0x48			/* Receive a packet */
+#define AX_LOOP	0x0C			/* Loopback mode */
+#define AX_RESET 0x80
+
+/*
+ *	Normal receive mode written to RX_STATUS.  We must intr on short packets
+ *	to avoid bogus rx lockups.
+ */
+
+#define RX_NORM 0xA8		/* 0x68 == all addrs, 0xA8 only to me. */
+#define RX_PROM 0x68		/* Senior Prom, uhmm promiscuous mode. */
+#define RX_MULT 0xE8		/* Accept multicast packets. */
+#define TX_NORM 0x0A		/* Interrupt on everything that might hang the chip */
+
+/*
+ *	TX_STATUS register.
+ */
+
+#define TX_COLLISION 0x02
+#define TX_16COLLISIONS 0x04
+#define TX_READY 0x08
+
+#define RX_RUNT 0x08
+#define RX_MISSED 0x01		/* Missed a packet due to 3c501 braindamage. */
+#define RX_GOOD	0x30		/* Good packet 0x20, or simple overflow 0x10. */
+
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/3com/3c509.c linux-libre-3.2-gnu/drivers/net/ethernet/3com/3c509.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/3com/3c509.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/3com/3c509.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1594 @@
+/* 3c509.c: A 3c509 EtherLink3 ethernet driver for linux. */
+/*
+	Written 1993-2000 by Donald Becker.
+
+	Copyright 1994-2000 by Donald Becker.
+	Copyright 1993 United States Government as represented by the
+	Director, National Security Agency.	 This software may be used and
+	distributed according to the terms of the GNU General Public License,
+	incorporated herein by reference.
+
+	This driver is for the 3Com EtherLinkIII series.
+
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+	Known limitations:
+	Because of the way 3c509 ISA detection works it's difficult to predict
+	a priori which of several ISA-mode cards will be detected first.
+
+	This driver does not use predictive interrupt mode, resulting in higher
+	packet latency but lower overhead.  If interrupts are disabled for an
+	unusually long time it could also result in missed packets, but in
+	practice this rarely happens.
+
+
+	FIXES:
+		Alan Cox:       Removed the 'Unexpected interrupt' bug.
+		Michael Meskes:	Upgraded to Donald Becker's version 1.07.
+		Alan Cox:	Increased the eeprom delay. Regardless of
+				what the docs say some people definitely
+				get problems with lower (but in card spec)
+				delays
+		v1.10 4/21/97 Fixed module code so that multiple cards may be detected,
+				other cleanups.  -djb
+		Andrea Arcangeli:	Upgraded to Donald Becker's version 1.12.
+		Rick Payne:	Fixed SMP race condition
+		v1.13 9/8/97 Made 'max_interrupt_work' an insmod-settable variable -djb
+		v1.14 10/15/97 Avoided waiting..discard message for fast machines -djb
+		v1.15 1/31/98 Faster recovery for Tx errors. -djb
+		v1.16 2/3/98 Different ID port handling to avoid sound cards. -djb
+		v1.18 12Mar2001 Andrew Morton
+			- Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz)
+			- Reviewed against 1.18 from scyld.com
+		v1.18a 17Nov2001 Jeff Garzik <jgarzik@pobox.com>
+			- ethtool support
+		v1.18b 1Mar2002 Zwane Mwaikambo <zwane@commfireservices.com>
+			- Power Management support
+		v1.18c 1Mar2002 David Ruggiero <jdr@farfalle.com>
+			- Full duplex support
+		v1.19  16Oct2002 Zwane Mwaikambo <zwane@linuxpower.ca>
+			- Additional ethtool features
+		v1.19a 28Oct2002 Davud Ruggiero <jdr@farfalle.com>
+			- Increase *read_eeprom udelay to workaround oops with 2 cards.
+		v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
+			- Introduce driver model for EISA cards.
+		v1.20  04Feb2008 Ondrej Zary <linux@rainbow-software.org>
+			- convert to isa_driver and pnp_driver and some cleanups
+*/
+
+#define DRV_NAME	"3c509"
+#define DRV_VERSION	"1.20"
+#define DRV_RELDATE	"04Feb2008"
+
+/* A few values that may be tweaked. */
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  (400*HZ/1000)
+
+#include <linux/module.h>
+#include <linux/mca.h>
+#include <linux/isa.h>
+#include <linux/pnp.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/pm.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>	/* for udelay() */
+#include <linux/spinlock.h>
+#include <linux/ethtool.h>
+#include <linux/device.h>
+#include <linux/eisa.h>
+#include <linux/bitops.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+static char version[] __devinitdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
+
+#ifdef EL3_DEBUG
+static int el3_debug = EL3_DEBUG;
+#else
+static int el3_debug = 2;
+#endif
+
+/* Used to do a global count of all the cards in the system.  Must be
+ * a global variable so that the mca/eisa probe routines can increment
+ * it */
+static int el3_cards = 0;
+#define EL3_MAX_CARDS 8
+
+/* To minimize the size of the driver source I only define operating
+   constants if they are used several times.  You'll need the manual
+   anyway if you want to understand driver details. */
+/* Offsets from base I/O address. */
+#define EL3_DATA 0x00
+#define EL3_CMD 0x0e
+#define EL3_STATUS 0x0e
+#define	EEPROM_READ 0x80
+
+#define EL3_IO_EXTENT	16
+
+#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
+
+
+/* The top five bits written to EL3_CMD are a command, the lower
+   11 bits are the parameter, if applicable. */
+enum c509cmd {
+	TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
+	RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11,
+	TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
+	FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
+	SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
+	SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11,
+	StatsDisable = 22<<11, StopCoax = 23<<11, PowerUp = 27<<11,
+	PowerDown = 28<<11, PowerAuto = 29<<11};
+
+enum c509status {
+	IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
+	TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
+	IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000, };
+
+/* The SetRxFilter command accepts the following classes: */
+enum RxFilter {
+	RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 };
+
+/* Register window 1 offsets, the window used in normal operation. */
+#define TX_FIFO		0x00
+#define RX_FIFO		0x00
+#define RX_STATUS 	0x08
+#define TX_STATUS 	0x0B
+#define TX_FREE		0x0C		/* Remaining free bytes in Tx buffer. */
+
+#define WN0_CONF_CTRL	0x04		/* Window 0: Configuration control register */
+#define WN0_ADDR_CONF	0x06		/* Window 0: Address configuration register */
+#define WN0_IRQ		0x08		/* Window 0: Set IRQ line in bits 12-15. */
+#define WN4_MEDIA	0x0A		/* Window 4: Various transcvr/media bits. */
+#define	MEDIA_TP	0x00C0		/* Enable link beat and jabber for 10baseT. */
+#define WN4_NETDIAG	0x06		/* Window 4: Net diagnostic */
+#define FD_ENABLE	0x8000		/* Enable full-duplex ("external loopback") */
+
+/*
+ * Must be a power of two (we use a binary and in the
+ * circular queue)
+ */
+#define SKB_QUEUE_SIZE	64
+
+enum el3_cardtype { EL3_ISA, EL3_PNP, EL3_MCA, EL3_EISA };
+
+struct el3_private {
+	spinlock_t lock;
+	/* skb send-queue */
+	int head, size;
+	struct sk_buff *queue[SKB_QUEUE_SIZE];
+	enum el3_cardtype type;
+};
+static int id_port;
+static int current_tag;
+static struct net_device *el3_devs[EL3_MAX_CARDS];
+
+/* Parameters that may be passed into the module. */
+static int debug = -1;
+static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 10;
+#ifdef CONFIG_PNP
+static int nopnp;
+#endif
+
+static int __devinit el3_common_init(struct net_device *dev);
+static void el3_common_remove(struct net_device *dev);
+static ushort id_read_eeprom(int index);
+static ushort read_eeprom(int ioaddr, int index);
+static int el3_open(struct net_device *dev);
+static netdev_tx_t el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static irqreturn_t el3_interrupt(int irq, void *dev_id);
+static void update_stats(struct net_device *dev);
+static struct net_device_stats *el3_get_stats(struct net_device *dev);
+static int el3_rx(struct net_device *dev);
+static int el3_close(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+static void el3_tx_timeout (struct net_device *dev);
+static void el3_down(struct net_device *dev);
+static void el3_up(struct net_device *dev);
+static const struct ethtool_ops ethtool_ops;
+#ifdef CONFIG_PM
+static int el3_suspend(struct device *, pm_message_t);
+static int el3_resume(struct device *);
+#else
+#define el3_suspend NULL
+#define el3_resume NULL
+#endif
+
+
+/* generic device remove for all device types */
+static int el3_device_remove (struct device *device);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void el3_poll_controller(struct net_device *dev);
+#endif
+
+/* Return 0 on success, 1 on error, 2 when found already detected PnP card */
+static int el3_isa_id_sequence(__be16 *phys_addr)
+{
+	short lrs_state = 0xff;
+	int i;
+
+	/* ISA boards are detected by sending the ID sequence to the
+	   ID_PORT.  We find cards past the first by setting the 'current_tag'
+	   on cards as they are found.  Cards with their tag set will not
+	   respond to subsequent ID sequences. */
+
+	outb(0x00, id_port);
+	outb(0x00, id_port);
+	for (i = 0; i < 255; i++) {
+		outb(lrs_state, id_port);
+		lrs_state <<= 1;
+		lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
+	}
+	/* For the first probe, clear all board's tag registers. */
+	if (current_tag == 0)
+		outb(0xd0, id_port);
+	else			/* Otherwise kill off already-found boards. */
+		outb(0xd8, id_port);
+	if (id_read_eeprom(7) != 0x6d50)
+		return 1;
+	/* Read in EEPROM data, which does contention-select.
+	   Only the lowest address board will stay "on-line".
+	   3Com got the byte order backwards. */
+	for (i = 0; i < 3; i++)
+		phys_addr[i] = htons(id_read_eeprom(i));
+#ifdef CONFIG_PNP
+	if (!nopnp) {
+		/* The ISA PnP 3c509 cards respond to the ID sequence too.
+		   This check is needed in order not to register them twice. */
+		for (i = 0; i < el3_cards; i++) {
+			struct el3_private *lp = netdev_priv(el3_devs[i]);
+			if (lp->type == EL3_PNP &&
+			    !memcmp(phys_addr, el3_devs[i]->dev_addr,
+				    ETH_ALEN)) {
+				if (el3_debug > 3)
+					pr_debug("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
+						phys_addr[0] & 0xff, phys_addr[0] >> 8,
+						phys_addr[1] & 0xff, phys_addr[1] >> 8,
+						phys_addr[2] & 0xff, phys_addr[2] >> 8);
+				/* Set the adaptor tag so that the next card can be found. */
+				outb(0xd0 + ++current_tag, id_port);
+				return 2;
+			}
+		}
+	}
+#endif /* CONFIG_PNP */
+	return 0;
+
+}
+
+static void __devinit el3_dev_fill(struct net_device *dev, __be16 *phys_addr,
+				   int ioaddr, int irq, int if_port,
+				   enum el3_cardtype type)
+{
+	struct el3_private *lp = netdev_priv(dev);
+
+	memcpy(dev->dev_addr, phys_addr, ETH_ALEN);
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+	dev->if_port = if_port;
+	lp->type = type;
+}
+
+static int __devinit el3_isa_match(struct device *pdev,
+				   unsigned int ndev)
+{
+	struct net_device *dev;
+	int ioaddr, isa_irq, if_port, err;
+	unsigned int iobase;
+	__be16 phys_addr[3];
+
+	while ((err = el3_isa_id_sequence(phys_addr)) == 2)
+		;	/* Skip to next card when PnP card found */
+	if (err == 1)
+		return 0;
+
+	iobase = id_read_eeprom(8);
+	if_port = iobase >> 14;
+	ioaddr = 0x200 + ((iobase & 0x1f) << 4);
+	if (irq[el3_cards] > 1 && irq[el3_cards] < 16)
+		isa_irq = irq[el3_cards];
+	else
+		isa_irq = id_read_eeprom(9) >> 12;
+
+	dev = alloc_etherdev(sizeof(struct el3_private));
+	if (!dev)
+		return -ENOMEM;
+
+	netdev_boot_setup_check(dev);
+
+	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-isa")) {
+		free_netdev(dev);
+		return 0;
+	}
+
+	/* Set the adaptor tag so that the next card can be found. */
+	outb(0xd0 + ++current_tag, id_port);
+
+	/* Activate the adaptor at the EEPROM location. */
+	outb((ioaddr >> 4) | 0xe0, id_port);
+
+	EL3WINDOW(0);
+	if (inw(ioaddr) != 0x6d50) {
+		free_netdev(dev);
+		return 0;
+	}
+
+	/* Free the interrupt so that some other card can use it. */
+	outw(0x0f00, ioaddr + WN0_IRQ);
+
+	el3_dev_fill(dev, phys_addr, ioaddr, isa_irq, if_port, EL3_ISA);
+	dev_set_drvdata(pdev, dev);
+	if (el3_common_init(dev)) {
+		free_netdev(dev);
+		return 0;
+	}
+
+	el3_devs[el3_cards++] = dev;
+	return 1;
+}
+
+static int __devexit el3_isa_remove(struct device *pdev,
+				    unsigned int ndev)
+{
+	el3_device_remove(pdev);
+	dev_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int el3_isa_suspend(struct device *dev, unsigned int n,
+			   pm_message_t state)
+{
+	current_tag = 0;
+	return el3_suspend(dev, state);
+}
+
+static int el3_isa_resume(struct device *dev, unsigned int n)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	int ioaddr = ndev->base_addr, err;
+	__be16 phys_addr[3];
+
+	while ((err = el3_isa_id_sequence(phys_addr)) == 2)
+		;	/* Skip to next card when PnP card found */
+	if (err == 1)
+		return 0;
+	/* Set the adaptor tag so that the next card can be found. */
+	outb(0xd0 + ++current_tag, id_port);
+	/* Enable the card */
+	outb((ioaddr >> 4) | 0xe0, id_port);
+	EL3WINDOW(0);
+	if (inw(ioaddr) != 0x6d50)
+		return 1;
+	/* Free the interrupt so that some other card can use it. */
+	outw(0x0f00, ioaddr + WN0_IRQ);
+	return el3_resume(dev);
+}
+#endif
+
+static struct isa_driver el3_isa_driver = {
+	.match		= el3_isa_match,
+	.remove		= __devexit_p(el3_isa_remove),
+#ifdef CONFIG_PM
+	.suspend	= el3_isa_suspend,
+	.resume		= el3_isa_resume,
+#endif
+	.driver		= {
+		.name	= "3c509"
+	},
+};
+static int isa_registered;
+
+#ifdef CONFIG_PNP
+static struct pnp_device_id el3_pnp_ids[] = {
+	{ .id = "TCM5090" }, /* 3Com Etherlink III (TP) */
+	{ .id = "TCM5091" }, /* 3Com Etherlink III */
+	{ .id = "TCM5094" }, /* 3Com Etherlink III (combo) */
+	{ .id = "TCM5095" }, /* 3Com Etherlink III (TPO) */
+	{ .id = "TCM5098" }, /* 3Com Etherlink III (TPC) */
+	{ .id = "PNP80f7" }, /* 3Com Etherlink III compatible */
+	{ .id = "PNP80f8" }, /* 3Com Etherlink III compatible */
+	{ .id = "" }
+};
+MODULE_DEVICE_TABLE(pnp, el3_pnp_ids);
+
+static int __devinit el3_pnp_probe(struct pnp_dev *pdev,
+				    const struct pnp_device_id *id)
+{
+	short i;
+	int ioaddr, irq, if_port;
+	__be16 phys_addr[3];
+	struct net_device *dev = NULL;
+	int err;
+
+	ioaddr = pnp_port_start(pdev, 0);
+	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-pnp"))
+		return -EBUSY;
+	irq = pnp_irq(pdev, 0);
+	EL3WINDOW(0);
+	for (i = 0; i < 3; i++)
+		phys_addr[i] = htons(read_eeprom(ioaddr, i));
+	if_port = read_eeprom(ioaddr, 8) >> 14;
+	dev = alloc_etherdev(sizeof(struct el3_private));
+	if (!dev) {
+		release_region(ioaddr, EL3_IO_EXTENT);
+		return -ENOMEM;
+	}
+	SET_NETDEV_DEV(dev, &pdev->dev);
+	netdev_boot_setup_check(dev);
+
+	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_PNP);
+	pnp_set_drvdata(pdev, dev);
+	err = el3_common_init(dev);
+
+	if (err) {
+		pnp_set_drvdata(pdev, NULL);
+		free_netdev(dev);
+		return err;
+	}
+
+	el3_devs[el3_cards++] = dev;
+	return 0;
+}
+
+static void __devexit el3_pnp_remove(struct pnp_dev *pdev)
+{
+	el3_common_remove(pnp_get_drvdata(pdev));
+	pnp_set_drvdata(pdev, NULL);
+}
+
+#ifdef CONFIG_PM
+static int el3_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
+{
+	return el3_suspend(&pdev->dev, state);
+}
+
+static int el3_pnp_resume(struct pnp_dev *pdev)
+{
+	return el3_resume(&pdev->dev);
+}
+#endif
+
+static struct pnp_driver el3_pnp_driver = {
+	.name		= "3c509",
+	.id_table	= el3_pnp_ids,
+	.probe		= el3_pnp_probe,
+	.remove		= __devexit_p(el3_pnp_remove),
+#ifdef CONFIG_PM
+	.suspend	= el3_pnp_suspend,
+	.resume		= el3_pnp_resume,
+#endif
+};
+static int pnp_registered;
+#endif /* CONFIG_PNP */
+
+#ifdef CONFIG_EISA
+static struct eisa_device_id el3_eisa_ids[] = {
+		{ "TCM5090" },
+		{ "TCM5091" },
+		{ "TCM5092" },
+		{ "TCM5093" },
+		{ "TCM5094" },
+		{ "TCM5095" },
+		{ "TCM5098" },
+		{ "" }
+};
+MODULE_DEVICE_TABLE(eisa, el3_eisa_ids);
+
+static int el3_eisa_probe (struct device *device);
+
+static struct eisa_driver el3_eisa_driver = {
+		.id_table = el3_eisa_ids,
+		.driver   = {
+				.name    = "3c579",
+				.probe   = el3_eisa_probe,
+				.remove  = __devexit_p (el3_device_remove),
+				.suspend = el3_suspend,
+				.resume  = el3_resume,
+		}
+};
+static int eisa_registered;
+#endif
+
+#ifdef CONFIG_MCA
+static int el3_mca_probe(struct device *dev);
+
+static short el3_mca_adapter_ids[] __initdata = {
+		0x627c,
+		0x627d,
+		0x62db,
+		0x62f6,
+		0x62f7,
+		0x0000
+};
+
+static char *el3_mca_adapter_names[] __initdata = {
+		"3Com 3c529 EtherLink III (10base2)",
+		"3Com 3c529 EtherLink III (10baseT)",
+		"3Com 3c529 EtherLink III (test mode)",
+		"3Com 3c529 EtherLink III (TP or coax)",
+		"3Com 3c529 EtherLink III (TP)",
+		NULL
+};
+
+static struct mca_driver el3_mca_driver = {
+		.id_table = el3_mca_adapter_ids,
+		.driver = {
+				.name = "3c529",
+				.bus = &mca_bus_type,
+				.probe = el3_mca_probe,
+				.remove = __devexit_p(el3_device_remove),
+				.suspend = el3_suspend,
+				.resume  = el3_resume,
+		},
+};
+static int mca_registered;
+#endif /* CONFIG_MCA */
+
+static const struct net_device_ops netdev_ops = {
+	.ndo_open 		= el3_open,
+	.ndo_stop	 	= el3_close,
+	.ndo_start_xmit 	= el3_start_xmit,
+	.ndo_get_stats 		= el3_get_stats,
+	.ndo_set_rx_mode	= set_multicast_list,
+	.ndo_tx_timeout 	= el3_tx_timeout,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= el3_poll_controller,
+#endif
+};
+
+static int __devinit el3_common_init(struct net_device *dev)
+{
+	struct el3_private *lp = netdev_priv(dev);
+	int err;
+	const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
+
+	spin_lock_init(&lp->lock);
+
+	if (dev->mem_start & 0x05) { /* xcvr codes 1/3/4/12 */
+		dev->if_port = (dev->mem_start & 0x0f);
+	} else { /* xcvr codes 0/8 */
+		/* use eeprom value, but save user's full-duplex selection */
+		dev->if_port |= (dev->mem_start & 0x08);
+	}
+
+	/* The EL3-specific entries in the device structure. */
+	dev->netdev_ops = &netdev_ops;
+	dev->watchdog_timeo = TX_TIMEOUT;
+	SET_ETHTOOL_OPS(dev, &ethtool_ops);
+
+	err = register_netdev(dev);
+	if (err) {
+		pr_err("Failed to register 3c5x9 at %#3.3lx, IRQ %d.\n",
+			dev->base_addr, dev->irq);
+		release_region(dev->base_addr, EL3_IO_EXTENT);
+		return err;
+	}
+
+	pr_info("%s: 3c5x9 found at %#3.3lx, %s port, address %pM, IRQ %d.\n",
+	       dev->name, dev->base_addr, if_names[(dev->if_port & 0x03)],
+	       dev->dev_addr, dev->irq);
+
+	if (el3_debug > 0)
+		pr_info("%s", version);
+	return 0;
+
+}
+
+static void el3_common_remove (struct net_device *dev)
+{
+	unregister_netdev (dev);
+	release_region(dev->base_addr, EL3_IO_EXTENT);
+	free_netdev (dev);
+}
+
+#ifdef CONFIG_MCA
+static int __init el3_mca_probe(struct device *device)
+{
+	/* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch,
+	 * heavily modified by Chris Beauregard
+	 * (cpbeaure@csclub.uwaterloo.ca) to support standard MCA
+	 * probing.
+	 *
+	 * redone for multi-card detection by ZP Gu (zpg@castle.net)
+	 * now works as a module */
+
+	short i;
+	int ioaddr, irq, if_port;
+	__be16 phys_addr[3];
+	struct net_device *dev = NULL;
+	u_char pos4, pos5;
+	struct mca_device *mdev = to_mca_device(device);
+	int slot = mdev->slot;
+	int err;
+
+	pos4 = mca_device_read_stored_pos(mdev, 4);
+	pos5 = mca_device_read_stored_pos(mdev, 5);
+
+	ioaddr = ((short)((pos4&0xfc)|0x02)) << 8;
+	irq = pos5 & 0x0f;
+
+
+	pr_info("3c529: found %s at slot %d\n",
+		el3_mca_adapter_names[mdev->index], slot + 1);
+
+	/* claim the slot */
+	strncpy(mdev->name, el3_mca_adapter_names[mdev->index],
+			sizeof(mdev->name));
+	mca_device_set_claim(mdev, 1);
+
+	if_port = pos4 & 0x03;
+
+	irq = mca_device_transform_irq(mdev, irq);
+	ioaddr = mca_device_transform_ioport(mdev, ioaddr);
+	if (el3_debug > 2) {
+		pr_debug("3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
+	}
+	EL3WINDOW(0);
+	for (i = 0; i < 3; i++)
+		phys_addr[i] = htons(read_eeprom(ioaddr, i));
+
+	dev = alloc_etherdev(sizeof (struct el3_private));
+	if (dev == NULL) {
+		release_region(ioaddr, EL3_IO_EXTENT);
+		return -ENOMEM;
+	}
+
+	netdev_boot_setup_check(dev);
+
+	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_MCA);
+	dev_set_drvdata(device, dev);
+	err = el3_common_init(dev);
+
+	if (err) {
+		dev_set_drvdata(device, NULL);
+		free_netdev(dev);
+		return -ENOMEM;
+	}
+
+	el3_devs[el3_cards++] = dev;
+	return 0;
+}
+
+#endif /* CONFIG_MCA */
+
+#ifdef CONFIG_EISA
+static int __init el3_eisa_probe (struct device *device)
+{
+	short i;
+	int ioaddr, irq, if_port;
+	__be16 phys_addr[3];
+	struct net_device *dev = NULL;
+	struct eisa_device *edev;
+	int err;
+
+	/* Yeepee, The driver framework is calling us ! */
+	edev = to_eisa_device (device);
+	ioaddr = edev->base_addr;
+
+	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c579-eisa"))
+		return -EBUSY;
+
+	/* Change the register set to the configuration window 0. */
+	outw(SelectWindow | 0, ioaddr + 0xC80 + EL3_CMD);
+
+	irq = inw(ioaddr + WN0_IRQ) >> 12;
+	if_port = inw(ioaddr + 6)>>14;
+	for (i = 0; i < 3; i++)
+		phys_addr[i] = htons(read_eeprom(ioaddr, i));
+
+	/* Restore the "Product ID" to the EEPROM read register. */
+	read_eeprom(ioaddr, 3);
+
+	dev = alloc_etherdev(sizeof (struct el3_private));
+	if (dev == NULL) {
+		release_region(ioaddr, EL3_IO_EXTENT);
+		return -ENOMEM;
+	}
+
+	netdev_boot_setup_check(dev);
+
+	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_EISA);
+	eisa_set_drvdata (edev, dev);
+	err = el3_common_init(dev);
+
+	if (err) {
+		eisa_set_drvdata (edev, NULL);
+		free_netdev(dev);
+		return err;
+	}
+
+	el3_devs[el3_cards++] = dev;
+	return 0;
+}
+#endif
+
+/* This remove works for all device types.
+ *
+ * The net dev must be stored in the driver data field */
+static int __devexit el3_device_remove (struct device *device)
+{
+	struct net_device *dev;
+
+	dev = dev_get_drvdata(device);
+
+	el3_common_remove (dev);
+	return 0;
+}
+
+/* Read a word from the EEPROM using the regular EEPROM access register.
+   Assume that we are in register window zero.
+ */
+static ushort read_eeprom(int ioaddr, int index)
+{
+	outw(EEPROM_READ + index, ioaddr + 10);
+	/* Pause for at least 162 us. for the read to take place.
+	   Some chips seem to require much longer */
+	mdelay(2);
+	return inw(ioaddr + 12);
+}
+
+/* Read a word from the EEPROM when in the ISA ID probe state. */
+static ushort id_read_eeprom(int index)
+{
+	int bit, word = 0;
+
+	/* Issue read command, and pause for at least 162 us. for it to complete.
+	   Assume extra-fast 16Mhz bus. */
+	outb(EEPROM_READ + index, id_port);
+
+	/* Pause for at least 162 us. for the read to take place. */
+	/* Some chips seem to require much longer */
+	mdelay(4);
+
+	for (bit = 15; bit >= 0; bit--)
+		word = (word << 1) + (inb(id_port) & 0x01);
+
+	if (el3_debug > 3)
+		pr_debug("  3c509 EEPROM word %d %#4.4x.\n", index, word);
+
+	return word;
+}
+
+
+static int
+el3_open(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr;
+	int i;
+
+	outw(TxReset, ioaddr + EL3_CMD);
+	outw(RxReset, ioaddr + EL3_CMD);
+	outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
+
+	i = request_irq(dev->irq, el3_interrupt, 0, dev->name, dev);
+	if (i)
+		return i;
+
+	EL3WINDOW(0);
+	if (el3_debug > 3)
+		pr_debug("%s: Opening, IRQ %d	 status@%x %4.4x.\n", dev->name,
+			   dev->irq, ioaddr + EL3_STATUS, inw(ioaddr + EL3_STATUS));
+
+	el3_up(dev);
+
+	if (el3_debug > 3)
+		pr_debug("%s: Opened 3c509  IRQ %d  status %4.4x.\n",
+			   dev->name, dev->irq, inw(ioaddr + EL3_STATUS));
+
+	return 0;
+}
+
+static void
+el3_tx_timeout (struct net_device *dev)
+{
+	int ioaddr = dev->base_addr;
+
+	/* Transmitter timeout, serious problems. */
+	pr_warning("%s: transmit timed out, Tx_status %2.2x status %4.4x Tx FIFO room %d.\n",
+		   dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
+		   inw(ioaddr + TX_FREE));
+	dev->stats.tx_errors++;
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	/* Issue TX_RESET and TX_START commands. */
+	outw(TxReset, ioaddr + EL3_CMD);
+	outw(TxEnable, ioaddr + EL3_CMD);
+	netif_wake_queue(dev);
+}
+
+
+static netdev_tx_t
+el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct el3_private *lp = netdev_priv(dev);
+	int ioaddr = dev->base_addr;
+	unsigned long flags;
+
+	netif_stop_queue (dev);
+
+	dev->stats.tx_bytes += skb->len;
+
+	if (el3_debug > 4) {
+		pr_debug("%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
+			   dev->name, skb->len, inw(ioaddr + EL3_STATUS));
+	}
+#if 0
+#ifndef final_version
+	{	/* Error-checking code, delete someday. */
+		ushort status = inw(ioaddr + EL3_STATUS);
+		if (status & 0x0001 && 		/* IRQ line active, missed one. */
+		    inw(ioaddr + EL3_STATUS) & 1) { 			/* Make sure. */
+			pr_debug("%s: Missed interrupt, status then %04x now %04x"
+				   "  Tx %2.2x Rx %4.4x.\n", dev->name, status,
+				   inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS),
+				   inw(ioaddr + RX_STATUS));
+			/* Fake interrupt trigger by masking, acknowledge interrupts. */
+			outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
+			outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
+				 ioaddr + EL3_CMD);
+			outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
+		}
+	}
+#endif
+#endif
+	/*
+	 *	We lock the driver against other processors. Note
+	 *	we don't need to lock versus the IRQ as we suspended
+	 *	that. This means that we lose the ability to take
+	 *	an RX during a TX upload. That sucks a bit with SMP
+	 *	on an original 3c509 (2K buffer)
+	 *
+	 *	Using disable_irq stops us crapping on other
+	 *	time sensitive devices.
+	 */
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	/* Put out the doubleword header... */
+	outw(skb->len, ioaddr + TX_FIFO);
+	outw(0x00, ioaddr + TX_FIFO);
+	/* ... and the packet rounded to a doubleword. */
+	outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+
+	if (inw(ioaddr + TX_FREE) > 1536)
+		netif_start_queue(dev);
+	else
+		/* Interrupt us when the FIFO has room for max-sized packet. */
+		outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	dev_kfree_skb (skb);
+
+	/* Clear the Tx status stack. */
+	{
+		short tx_status;
+		int i = 4;
+
+		while (--i > 0	&&	(tx_status = inb(ioaddr + TX_STATUS)) > 0) {
+			if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
+			if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
+			if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
+			outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
+		}
+	}
+	return NETDEV_TX_OK;
+}
+
+/* The EL3 interrupt handler. */
+static irqreturn_t
+el3_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct el3_private *lp;
+	int ioaddr, status;
+	int i = max_interrupt_work;
+
+	lp = netdev_priv(dev);
+	spin_lock(&lp->lock);
+
+	ioaddr = dev->base_addr;
+
+	if (el3_debug > 4) {
+		status = inw(ioaddr + EL3_STATUS);
+		pr_debug("%s: interrupt, status %4.4x.\n", dev->name, status);
+	}
+
+	while ((status = inw(ioaddr + EL3_STATUS)) &
+		   (IntLatch | RxComplete | StatsFull)) {
+
+		if (status & RxComplete)
+			el3_rx(dev);
+
+		if (status & TxAvailable) {
+			if (el3_debug > 5)
+				pr_debug("	TX room bit was handled.\n");
+			/* There's room in the FIFO for a full-sized packet. */
+			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
+			netif_wake_queue (dev);
+		}
+		if (status & (AdapterFailure | RxEarly | StatsFull | TxComplete)) {
+			/* Handle all uncommon interrupts. */
+			if (status & StatsFull)				/* Empty statistics. */
+				update_stats(dev);
+			if (status & RxEarly) {				/* Rx early is unused. */
+				el3_rx(dev);
+				outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
+			}
+			if (status & TxComplete) {			/* Really Tx error. */
+				short tx_status;
+				int i = 4;
+
+				while (--i>0 && (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
+					if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
+					if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
+					if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
+					outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
+				}
+			}
+			if (status & AdapterFailure) {
+				/* Adapter failure requires Rx reset and reinit. */
+				outw(RxReset, ioaddr + EL3_CMD);
+				/* Set the Rx filter to the current state. */
+				outw(SetRxFilter | RxStation | RxBroadcast
+					 | (dev->flags & IFF_ALLMULTI ? RxMulticast : 0)
+					 | (dev->flags & IFF_PROMISC ? RxProm : 0),
+					 ioaddr + EL3_CMD);
+				outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
+				outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
+			}
+		}
+
+		if (--i < 0) {
+			pr_err("%s: Infinite loop in interrupt, status %4.4x.\n",
+				   dev->name, status);
+			/* Clear all interrupts. */
+			outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
+			break;
+		}
+		/* Acknowledge the IRQ. */
+		outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); /* Ack IRQ */
+	}
+
+	if (el3_debug > 4) {
+		pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name,
+			   inw(ioaddr + EL3_STATUS));
+	}
+	spin_unlock(&lp->lock);
+	return IRQ_HANDLED;
+}
+
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void el3_poll_controller(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	el3_interrupt(dev->irq, dev);
+	enable_irq(dev->irq);
+}
+#endif
+
+static struct net_device_stats *
+el3_get_stats(struct net_device *dev)
+{
+	struct el3_private *lp = netdev_priv(dev);
+	unsigned long flags;
+
+	/*
+	 *	This is fast enough not to bother with disable IRQ
+	 *	stuff.
+	 */
+
+	spin_lock_irqsave(&lp->lock, flags);
+	update_stats(dev);
+	spin_unlock_irqrestore(&lp->lock, flags);
+	return &dev->stats;
+}
+
+/*  Update statistics.  We change to register window 6, so this should be run
+	single-threaded if the device is active. This is expected to be a rare
+	operation, and it's simpler for the rest of the driver to assume that
+	window 1 is always valid rather than use a special window-state variable.
+	*/
+static void update_stats(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr;
+
+	if (el3_debug > 5)
+		pr_debug("   Updating the statistics.\n");
+	/* Turn off statistics updates while reading. */
+	outw(StatsDisable, ioaddr + EL3_CMD);
+	/* Switch to the stats window, and read everything. */
+	EL3WINDOW(6);
+	dev->stats.tx_carrier_errors 	+= inb(ioaddr + 0);
+	dev->stats.tx_heartbeat_errors	+= inb(ioaddr + 1);
+	/* Multiple collisions. */	   inb(ioaddr + 2);
+	dev->stats.collisions		+= inb(ioaddr + 3);
+	dev->stats.tx_window_errors	+= inb(ioaddr + 4);
+	dev->stats.rx_fifo_errors	+= inb(ioaddr + 5);
+	dev->stats.tx_packets		+= inb(ioaddr + 6);
+	/* Rx packets	*/		   inb(ioaddr + 7);
+	/* Tx deferrals */		   inb(ioaddr + 8);
+	inw(ioaddr + 10);	/* Total Rx and Tx octets. */
+	inw(ioaddr + 12);
+
+	/* Back to window 1, and turn statistics back on. */
+	EL3WINDOW(1);
+	outw(StatsEnable, ioaddr + EL3_CMD);
+}
+
+static int
+el3_rx(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr;
+	short rx_status;
+
+	if (el3_debug > 5)
+		pr_debug("   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
+			   inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
+	while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) {
+		if (rx_status & 0x4000) { /* Error, update stats. */
+			short error = rx_status & 0x3800;
+
+			outw(RxDiscard, ioaddr + EL3_CMD);
+			dev->stats.rx_errors++;
+			switch (error) {
+			case 0x0000:		dev->stats.rx_over_errors++; break;
+			case 0x0800:		dev->stats.rx_length_errors++; break;
+			case 0x1000:		dev->stats.rx_frame_errors++; break;
+			case 0x1800:		dev->stats.rx_length_errors++; break;
+			case 0x2000:		dev->stats.rx_frame_errors++; break;
+			case 0x2800:		dev->stats.rx_crc_errors++; break;
+			}
+		} else {
+			short pkt_len = rx_status & 0x7ff;
+			struct sk_buff *skb;
+
+			skb = dev_alloc_skb(pkt_len+5);
+			if (el3_debug > 4)
+				pr_debug("Receiving packet size %d status %4.4x.\n",
+					   pkt_len, rx_status);
+			if (skb != NULL) {
+				skb_reserve(skb, 2);     /* Align IP on 16 byte */
+
+				/* 'skb->data' points to the start of sk_buff data area. */
+				insl(ioaddr + RX_FIFO, skb_put(skb,pkt_len),
+					 (pkt_len + 3) >> 2);
+
+				outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
+				skb->protocol = eth_type_trans(skb,dev);
+				netif_rx(skb);
+				dev->stats.rx_bytes += pkt_len;
+				dev->stats.rx_packets++;
+				continue;
+			}
+			outw(RxDiscard, ioaddr + EL3_CMD);
+			dev->stats.rx_dropped++;
+			if (el3_debug)
+				pr_debug("%s: Couldn't allocate a sk_buff of size %d.\n",
+					   dev->name, pkt_len);
+		}
+		inw(ioaddr + EL3_STATUS); 				/* Delay. */
+		while (inw(ioaddr + EL3_STATUS) & 0x1000)
+			pr_debug("	Waiting for 3c509 to discard packet, status %x.\n",
+				   inw(ioaddr + EL3_STATUS) );
+	}
+
+	return 0;
+}
+
+/*
+ *     Set or clear the multicast filter for this adaptor.
+ */
+static void
+set_multicast_list(struct net_device *dev)
+{
+	unsigned long flags;
+	struct el3_private *lp = netdev_priv(dev);
+	int ioaddr = dev->base_addr;
+	int mc_count = netdev_mc_count(dev);
+
+	if (el3_debug > 1) {
+		static int old;
+		if (old != mc_count) {
+			old = mc_count;
+			pr_debug("%s: Setting Rx mode to %d addresses.\n",
+				 dev->name, mc_count);
+		}
+	}
+	spin_lock_irqsave(&lp->lock, flags);
+	if (dev->flags&IFF_PROMISC) {
+		outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
+			 ioaddr + EL3_CMD);
+	}
+	else if (mc_count || (dev->flags&IFF_ALLMULTI)) {
+		outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast, ioaddr + EL3_CMD);
+	}
+	else
+		outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
+	spin_unlock_irqrestore(&lp->lock, flags);
+}
+
+static int
+el3_close(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr;
+	struct el3_private *lp = netdev_priv(dev);
+
+	if (el3_debug > 2)
+		pr_debug("%s: Shutting down ethercard.\n", dev->name);
+
+	el3_down(dev);
+
+	free_irq(dev->irq, dev);
+	/* Switching back to window 0 disables the IRQ. */
+	EL3WINDOW(0);
+	if (lp->type != EL3_EISA) {
+		/* But we explicitly zero the IRQ line select anyway. Don't do
+		 * it on EISA cards, it prevents the module from getting an
+		 * IRQ after unload+reload... */
+		outw(0x0f00, ioaddr + WN0_IRQ);
+	}
+
+	return 0;
+}
+
+static int
+el3_link_ok(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr;
+	u16 tmp;
+
+	EL3WINDOW(4);
+	tmp = inw(ioaddr + WN4_MEDIA);
+	EL3WINDOW(1);
+	return tmp & (1<<11);
+}
+
+static int
+el3_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	u16 tmp;
+	int ioaddr = dev->base_addr;
+
+	EL3WINDOW(0);
+	/* obtain current transceiver via WN4_MEDIA? */
+	tmp = inw(ioaddr + WN0_ADDR_CONF);
+	ecmd->transceiver = XCVR_INTERNAL;
+	switch (tmp >> 14) {
+	case 0:
+		ecmd->port = PORT_TP;
+		break;
+	case 1:
+		ecmd->port = PORT_AUI;
+		ecmd->transceiver = XCVR_EXTERNAL;
+		break;
+	case 3:
+		ecmd->port = PORT_BNC;
+	default:
+		break;
+	}
+
+	ecmd->duplex = DUPLEX_HALF;
+	ecmd->supported = 0;
+	tmp = inw(ioaddr + WN0_CONF_CTRL);
+	if (tmp & (1<<13))
+		ecmd->supported |= SUPPORTED_AUI;
+	if (tmp & (1<<12))
+		ecmd->supported |= SUPPORTED_BNC;
+	if (tmp & (1<<9)) {
+		ecmd->supported |= SUPPORTED_TP | SUPPORTED_10baseT_Half |
+				SUPPORTED_10baseT_Full;	/* hmm... */
+		EL3WINDOW(4);
+		tmp = inw(ioaddr + WN4_NETDIAG);
+		if (tmp & FD_ENABLE)
+			ecmd->duplex = DUPLEX_FULL;
+	}
+
+	ethtool_cmd_speed_set(ecmd, SPEED_10);
+	EL3WINDOW(1);
+	return 0;
+}
+
+static int
+el3_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	u16 tmp;
+	int ioaddr = dev->base_addr;
+
+	if (ecmd->speed != SPEED_10)
+		return -EINVAL;
+	if ((ecmd->duplex != DUPLEX_HALF) && (ecmd->duplex != DUPLEX_FULL))
+		return -EINVAL;
+	if ((ecmd->transceiver != XCVR_INTERNAL) && (ecmd->transceiver != XCVR_EXTERNAL))
+		return -EINVAL;
+
+	/* change XCVR type */
+	EL3WINDOW(0);
+	tmp = inw(ioaddr + WN0_ADDR_CONF);
+	switch (ecmd->port) {
+	case PORT_TP:
+		tmp &= ~(3<<14);
+		dev->if_port = 0;
+		break;
+	case PORT_AUI:
+		tmp |= (1<<14);
+		dev->if_port = 1;
+		break;
+	case PORT_BNC:
+		tmp |= (3<<14);
+		dev->if_port = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	outw(tmp, ioaddr + WN0_ADDR_CONF);
+	if (dev->if_port == 3) {
+		/* fire up the DC-DC convertor if BNC gets enabled */
+		tmp = inw(ioaddr + WN0_ADDR_CONF);
+		if (tmp & (3 << 14)) {
+			outw(StartCoax, ioaddr + EL3_CMD);
+			udelay(800);
+		} else
+			return -EIO;
+	}
+
+	EL3WINDOW(4);
+	tmp = inw(ioaddr + WN4_NETDIAG);
+	if (ecmd->duplex == DUPLEX_FULL)
+		tmp |= FD_ENABLE;
+	else
+		tmp &= ~FD_ENABLE;
+	outw(tmp, ioaddr + WN4_NETDIAG);
+	EL3WINDOW(1);
+
+	return 0;
+}
+
+static void el3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+}
+
+static int el3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct el3_private *lp = netdev_priv(dev);
+	int ret;
+
+	spin_lock_irq(&lp->lock);
+	ret = el3_netdev_get_ecmd(dev, ecmd);
+	spin_unlock_irq(&lp->lock);
+	return ret;
+}
+
+static int el3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct el3_private *lp = netdev_priv(dev);
+	int ret;
+
+	spin_lock_irq(&lp->lock);
+	ret = el3_netdev_set_ecmd(dev, ecmd);
+	spin_unlock_irq(&lp->lock);
+	return ret;
+}
+
+static u32 el3_get_link(struct net_device *dev)
+{
+	struct el3_private *lp = netdev_priv(dev);
+	u32 ret;
+
+	spin_lock_irq(&lp->lock);
+	ret = el3_link_ok(dev);
+	spin_unlock_irq(&lp->lock);
+	return ret;
+}
+
+static u32 el3_get_msglevel(struct net_device *dev)
+{
+	return el3_debug;
+}
+
+static void el3_set_msglevel(struct net_device *dev, u32 v)
+{
+	el3_debug = v;
+}
+
+static const struct ethtool_ops ethtool_ops = {
+	.get_drvinfo = el3_get_drvinfo,
+	.get_settings = el3_get_settings,
+	.set_settings = el3_set_settings,
+	.get_link = el3_get_link,
+	.get_msglevel = el3_get_msglevel,
+	.set_msglevel = el3_set_msglevel,
+};
+
+static void
+el3_down(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr;
+
+	netif_stop_queue(dev);
+
+	/* Turn off statistics ASAP.  We update lp->stats below. */
+	outw(StatsDisable, ioaddr + EL3_CMD);
+
+	/* Disable the receiver and transmitter. */
+	outw(RxDisable, ioaddr + EL3_CMD);
+	outw(TxDisable, ioaddr + EL3_CMD);
+
+	if (dev->if_port == 3)
+		/* Turn off thinnet power.  Green! */
+		outw(StopCoax, ioaddr + EL3_CMD);
+	else if (dev->if_port == 0) {
+		/* Disable link beat and jabber, if_port may change here next open(). */
+		EL3WINDOW(4);
+		outw(inw(ioaddr + WN4_MEDIA) & ~MEDIA_TP, ioaddr + WN4_MEDIA);
+	}
+
+	outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
+
+	update_stats(dev);
+}
+
+static void
+el3_up(struct net_device *dev)
+{
+	int i, sw_info, net_diag;
+	int ioaddr = dev->base_addr;
+
+	/* Activating the board required and does no harm otherwise */
+	outw(0x0001, ioaddr + 4);
+
+	/* Set the IRQ line. */
+	outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
+
+	/* Set the station address in window 2 each time opened. */
+	EL3WINDOW(2);
+
+	for (i = 0; i < 6; i++)
+		outb(dev->dev_addr[i], ioaddr + i);
+
+	if ((dev->if_port & 0x03) == 3) /* BNC interface */
+		/* Start the thinnet transceiver. We should really wait 50ms...*/
+		outw(StartCoax, ioaddr + EL3_CMD);
+	else if ((dev->if_port & 0x03) == 0) { /* 10baseT interface */
+		/* Combine secondary sw_info word (the adapter level) and primary
+			sw_info word (duplex setting plus other useless bits) */
+		EL3WINDOW(0);
+		sw_info = (read_eeprom(ioaddr, 0x14) & 0x400f) |
+			(read_eeprom(ioaddr, 0x0d) & 0xBff0);
+
+		EL3WINDOW(4);
+		net_diag = inw(ioaddr + WN4_NETDIAG);
+		net_diag = (net_diag | FD_ENABLE); /* temporarily assume full-duplex will be set */
+		pr_info("%s: ", dev->name);
+		switch (dev->if_port & 0x0c) {
+			case 12:
+				/* force full-duplex mode if 3c5x9b */
+				if (sw_info & 0x000f) {
+					pr_cont("Forcing 3c5x9b full-duplex mode");
+					break;
+				}
+			case 8:
+				/* set full-duplex mode based on eeprom config setting */
+				if ((sw_info & 0x000f) && (sw_info & 0x8000)) {
+					pr_cont("Setting 3c5x9b full-duplex mode (from EEPROM configuration bit)");
+					break;
+				}
+			default:
+				/* xcvr=(0 || 4) OR user has an old 3c5x9 non "B" model */
+				pr_cont("Setting 3c5x9/3c5x9B half-duplex mode");
+				net_diag = (net_diag & ~FD_ENABLE); /* disable full duplex */
+		}
+
+		outw(net_diag, ioaddr + WN4_NETDIAG);
+		pr_cont(" if_port: %d, sw_info: %4.4x\n", dev->if_port, sw_info);
+		if (el3_debug > 3)
+			pr_debug("%s: 3c5x9 net diag word is now: %4.4x.\n", dev->name, net_diag);
+		/* Enable link beat and jabber check. */
+		outw(inw(ioaddr + WN4_MEDIA) | MEDIA_TP, ioaddr + WN4_MEDIA);
+	}
+
+	/* Switch to the stats window, and clear all stats by reading. */
+	outw(StatsDisable, ioaddr + EL3_CMD);
+	EL3WINDOW(6);
+	for (i = 0; i < 9; i++)
+		inb(ioaddr + i);
+	inw(ioaddr + 10);
+	inw(ioaddr + 12);
+
+	/* Switch to register set 1 for normal use. */
+	EL3WINDOW(1);
+
+	/* Accept b-case and phys addr only. */
+	outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
+	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
+
+	outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
+	outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
+	/* Allow status bits to be seen. */
+	outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
+	/* Ack all pending events, and set active indicator mask. */
+	outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
+		 ioaddr + EL3_CMD);
+	outw(SetIntrEnb | IntLatch|TxAvailable|TxComplete|RxComplete|StatsFull,
+		 ioaddr + EL3_CMD);
+
+	netif_start_queue(dev);
+}
+
+/* Power Management support functions */
+#ifdef CONFIG_PM
+
+static int
+el3_suspend(struct device *pdev, pm_message_t state)
+{
+	unsigned long flags;
+	struct net_device *dev;
+	struct el3_private *lp;
+	int ioaddr;
+
+	dev = dev_get_drvdata(pdev);
+	lp = netdev_priv(dev);
+	ioaddr = dev->base_addr;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	if (netif_running(dev))
+		netif_device_detach(dev);
+
+	el3_down(dev);
+	outw(PowerDown, ioaddr + EL3_CMD);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+	return 0;
+}
+
+static int
+el3_resume(struct device *pdev)
+{
+	unsigned long flags;
+	struct net_device *dev;
+	struct el3_private *lp;
+	int ioaddr;
+
+	dev = dev_get_drvdata(pdev);
+	lp = netdev_priv(dev);
+	ioaddr = dev->base_addr;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	outw(PowerUp, ioaddr + EL3_CMD);
+	EL3WINDOW(0);
+	el3_up(dev);
+
+	if (netif_running(dev))
+		netif_device_attach(dev);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+	return 0;
+}
+
+#endif /* CONFIG_PM */
+
+module_param(debug,int, 0);
+module_param_array(irq, int, NULL, 0);
+module_param(max_interrupt_work, int, 0);
+MODULE_PARM_DESC(debug, "debug level (0-6)");
+MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
+MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
+#ifdef CONFIG_PNP
+module_param(nopnp, int, 0);
+MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
+#endif	/* CONFIG_PNP */
+MODULE_DESCRIPTION("3Com Etherlink III (3c509, 3c509B, 3c529, 3c579) ethernet driver");
+MODULE_LICENSE("GPL");
+
+static int __init el3_init_module(void)
+{
+	int ret = 0;
+
+	if (debug >= 0)
+		el3_debug = debug;
+
+#ifdef CONFIG_PNP
+	if (!nopnp) {
+		ret = pnp_register_driver(&el3_pnp_driver);
+		if (!ret)
+			pnp_registered = 1;
+	}
+#endif
+	/* Select an open I/O location at 0x1*0 to do ISA contention select. */
+	/* Start with 0x110 to avoid some sound cards.*/
+	for (id_port = 0x110 ; id_port < 0x200; id_port += 0x10) {
+		if (!request_region(id_port, 1, "3c509-control"))
+			continue;
+		outb(0x00, id_port);
+		outb(0xff, id_port);
+		if (inb(id_port) & 0x01)
+			break;
+		else
+			release_region(id_port, 1);
+	}
+	if (id_port >= 0x200) {
+		id_port = 0;
+		pr_err("No I/O port available for 3c509 activation.\n");
+	} else {
+		ret = isa_register_driver(&el3_isa_driver, EL3_MAX_CARDS);
+		if (!ret)
+			isa_registered = 1;
+	}
+#ifdef CONFIG_EISA
+	ret = eisa_driver_register(&el3_eisa_driver);
+	if (!ret)
+		eisa_registered = 1;
+#endif
+#ifdef CONFIG_MCA
+	ret = mca_register_driver(&el3_mca_driver);
+	if (!ret)
+		mca_registered = 1;
+#endif
+
+#ifdef CONFIG_PNP
+	if (pnp_registered)
+		ret = 0;
+#endif
+	if (isa_registered)
+		ret = 0;
+#ifdef CONFIG_EISA
+	if (eisa_registered)
+		ret = 0;
+#endif
+#ifdef CONFIG_MCA
+	if (mca_registered)
+		ret = 0;
+#endif
+	return ret;
+}
+
+static void __exit el3_cleanup_module(void)
+{
+#ifdef CONFIG_PNP
+	if (pnp_registered)
+		pnp_unregister_driver(&el3_pnp_driver);
+#endif
+	if (isa_registered)
+		isa_unregister_driver(&el3_isa_driver);
+	if (id_port)
+		release_region(id_port, 1);
+#ifdef CONFIG_EISA
+	if (eisa_registered)
+		eisa_driver_unregister(&el3_eisa_driver);
+#endif
+#ifdef CONFIG_MCA
+	if (mca_registered)
+		mca_unregister_driver(&el3_mca_driver);
+#endif
+}
+
+module_init (el3_init_module);
+module_exit (el3_cleanup_module);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/3com/3c515.c linux-libre-3.2-gnu/drivers/net/ethernet/3com/3c515.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/3com/3c515.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/3com/3c515.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1584 @@
+/*
+	Written 1997-1998 by Donald Becker.
+
+	This software may be used and distributed according to the terms
+	of the GNU General Public License, incorporated herein by reference.
+
+	This driver is for the 3Com ISA EtherLink XL "Corkscrew" 3c515 ethercard.
+
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+
+	2000/2/2- Added support for kernel-level ISAPnP
+		by Stephen Frost <sfrost@snowman.net> and Alessandro Zummo
+	Cleaned up for 2.3.x/softnet by Jeff Garzik and Alan Cox.
+
+	2001/11/17 - Added ethtool support (jgarzik)
+
+	2002/10/28 - Locking updates for 2.5 (alan@lxorguk.ukuu.org.uk)
+
+*/
+
+#define DRV_NAME		"3c515"
+#define DRV_VERSION		"0.99t-ac"
+#define DRV_RELDATE		"28-Oct-2002"
+
+static char *version =
+DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " becker@scyld.com and others\n";
+
+#define CORKSCREW 1
+
+/* "Knobs" that adjust features and parameters. */
+/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
+   Setting to > 1512 effectively disables this feature. */
+static int rx_copybreak = 200;
+
+/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
+static const int mtu = 1500;
+
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 20;
+
+/* Enable the automatic media selection code -- usually set. */
+#define AUTOMEDIA 1
+
+/* Allow the use of fragment bus master transfers instead of only
+   programmed-I/O for Vortex cards.  Full-bus-master transfers are always
+   enabled by default on Boomerang cards.  If VORTEX_BUS_MASTER is defined,
+   the feature may be turned on using 'options'. */
+#define VORTEX_BUS_MASTER
+
+/* A few values that may be tweaked. */
+/* Keep the ring sizes a power of two for efficiency. */
+#define TX_RING_SIZE	16
+#define RX_RING_SIZE	16
+#define PKT_BUF_SZ		1536	/* Size of each temporary Rx buffer. */
+
+#include <linux/module.h>
+#include <linux/isapnp.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#define NEW_MULTICAST
+#include <linux/delay.h>
+
+#define MAX_UNITS 8
+
+MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
+MODULE_DESCRIPTION("3Com 3c515 Corkscrew driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+/* "Knobs" for adjusting internal parameters. */
+/* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */
+#define DRIVER_DEBUG 1
+/* Some values here only for performance evaluation and path-coverage
+   debugging. */
+static int rx_nocopy, rx_copy, queued_packet;
+
+/* Number of times to check to see if the Tx FIFO has space, used in some
+   limited cases. */
+#define WAIT_TX_AVAIL 200
+
+/* Operational parameter that usually are not changed. */
+#define TX_TIMEOUT  ((4*HZ)/10)	/* Time in jiffies before concluding Tx hung */
+
+/* The size here is somewhat misleading: the Corkscrew also uses the ISA
+   aliased registers at <base>+0x400.
+   */
+#define CORKSCREW_TOTAL_SIZE 0x20
+
+#ifdef DRIVER_DEBUG
+static int corkscrew_debug = DRIVER_DEBUG;
+#else
+static int corkscrew_debug = 1;
+#endif
+
+#define CORKSCREW_ID 10
+
+/*
+				Theory of Operation
+
+I. Board Compatibility
+
+This device driver is designed for the 3Com 3c515 ISA Fast EtherLink XL,
+3Com's ISA bus adapter for Fast Ethernet.  Due to the unique I/O port layout,
+it's not practical to integrate this driver with the other EtherLink drivers.
+
+II. Board-specific settings
+
+The Corkscrew has an EEPROM for configuration, but no special settings are
+needed for Linux.
+
+III. Driver operation
+
+The 3c515 series use an interface that's very similar to the 3c900 "Boomerang"
+PCI cards, with the bus master interface extensively modified to work with
+the ISA bus.
+
+The card is capable of full-bus-master transfers with separate
+lists of transmit and receive descriptors, similar to the AMD LANCE/PCnet,
+DEC Tulip and Intel Speedo3.
+
+This driver uses a "RX_COPYBREAK" scheme rather than a fixed intermediate
+receive buffer.  This scheme allocates full-sized skbuffs as receive
+buffers.  The value RX_COPYBREAK is used as the copying breakpoint: it is
+chosen to trade-off the memory wasted by passing the full-sized skbuff to
+the queue layer for all frames vs. the copying cost of copying a frame to a
+correctly-sized skbuff.
+
+
+IIIC. Synchronization
+The driver runs as two independent, single-threaded flows of control.  One
+is the send-packet routine, which enforces single-threaded use by the netif
+layer.  The other thread is the interrupt handler, which is single
+threaded by the hardware and other software.
+
+IV. Notes
+
+Thanks to Terry Murphy of 3Com for providing documentation and a development
+board.
+
+The names "Vortex", "Boomerang" and "Corkscrew" are the internal 3Com
+project names.  I use these names to eliminate confusion -- 3Com product
+numbers and names are very similar and often confused.
+
+The new chips support both ethernet (1.5K) and FDDI (4.5K) frame sizes!
+This driver only supports ethernet frames because of the recent MTU limit
+of 1.5K, but the changes to support 4.5K are minimal.
+*/
+
+/* Operational definitions.
+   These are not used by other compilation units and thus are not
+   exported in a ".h" file.
+
+   First the windows.  There are eight register windows, with the command
+   and status registers available in each.
+   */
+#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
+#define EL3_CMD 0x0e
+#define EL3_STATUS 0x0e
+
+/* The top five bits written to EL3_CMD are a command, the lower
+   11 bits are the parameter, if applicable.
+   Note that 11 parameters bits was fine for ethernet, but the new chips
+   can handle FDDI length frames (~4500 octets) and now parameters count
+   32-bit 'Dwords' rather than octets. */
+
+enum corkscrew_cmd {
+	TotalReset = 0 << 11, SelectWindow = 1 << 11, StartCoax = 2 << 11,
+	RxDisable = 3 << 11, RxEnable = 4 << 11, RxReset = 5 << 11,
+	UpStall = 6 << 11, UpUnstall = (6 << 11) + 1, DownStall = (6 << 11) + 2,
+	DownUnstall = (6 << 11) + 3, RxDiscard = 8 << 11, TxEnable = 9 << 11,
+	TxDisable = 10 << 11, TxReset = 11 << 11, FakeIntr = 12 << 11,
+	AckIntr = 13 << 11, SetIntrEnb = 14 << 11, SetStatusEnb = 15 << 11,
+	SetRxFilter = 16 << 11, SetRxThreshold = 17 << 11,
+	SetTxThreshold = 18 << 11, SetTxStart = 19 << 11, StartDMAUp = 20 << 11,
+	StartDMADown = (20 << 11) + 1, StatsEnable = 21 << 11,
+	StatsDisable = 22 << 11, StopCoax = 23 << 11,
+};
+
+/* The SetRxFilter command accepts the following classes: */
+enum RxFilter {
+	RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
+};
+
+/* Bits in the general status register. */
+enum corkscrew_status {
+	IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
+	TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
+	IntReq = 0x0040, StatsFull = 0x0080,
+	DMADone = 1 << 8, DownComplete = 1 << 9, UpComplete = 1 << 10,
+	DMAInProgress = 1 << 11,	/* DMA controller is still busy. */
+	CmdInProgress = 1 << 12,	/* EL3_CMD is still busy. */
+};
+
+/* Register window 1 offsets, the window used in normal operation.
+   On the Corkscrew this window is always mapped at offsets 0x10-0x1f. */
+enum Window1 {
+	TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14,
+	RxStatus = 0x18, Timer = 0x1A, TxStatus = 0x1B,
+	TxFree = 0x1C,		/* Remaining free bytes in Tx buffer. */
+};
+enum Window0 {
+	Wn0IRQ = 0x08,
+#if defined(CORKSCREW)
+	Wn0EepromCmd = 0x200A,	/* Corkscrew EEPROM command register. */
+	Wn0EepromData = 0x200C,	/* Corkscrew EEPROM results register. */
+#else
+	Wn0EepromCmd = 10,	/* Window 0: EEPROM command register. */
+	Wn0EepromData = 12,	/* Window 0: EEPROM results register. */
+#endif
+};
+enum Win0_EEPROM_bits {
+	EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
+	EEPROM_EWENB = 0x30,	/* Enable erasing/writing for 10 msec. */
+	EEPROM_EWDIS = 0x00,	/* Disable EWENB before 10 msec timeout. */
+};
+
+/* EEPROM locations. */
+enum eeprom_offset {
+	PhysAddr01 = 0, PhysAddr23 = 1, PhysAddr45 = 2, ModelID = 3,
+	EtherLink3ID = 7,
+};
+
+enum Window3 {			/* Window 3: MAC/config bits. */
+	Wn3_Config = 0, Wn3_MAC_Ctrl = 6, Wn3_Options = 8,
+};
+enum wn3_config {
+	Ram_size = 7,
+	Ram_width = 8,
+	Ram_speed = 0x30,
+	Rom_size = 0xc0,
+	Ram_split_shift = 16,
+	Ram_split = 3 << Ram_split_shift,
+	Xcvr_shift = 20,
+	Xcvr = 7 << Xcvr_shift,
+	Autoselect = 0x1000000,
+};
+
+enum Window4 {
+	Wn4_NetDiag = 6, Wn4_Media = 10,	/* Window 4: Xcvr/media bits. */
+};
+enum Win4_Media_bits {
+	Media_SQE = 0x0008,	/* Enable SQE error counting for AUI. */
+	Media_10TP = 0x00C0,	/* Enable link beat and jabber for 10baseT. */
+	Media_Lnk = 0x0080,	/* Enable just link beat for 100TX/100FX. */
+	Media_LnkBeat = 0x0800,
+};
+enum Window7 {			/* Window 7: Bus Master control. */
+	Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
+};
+
+/* Boomerang-style bus master control registers.  Note ISA aliases! */
+enum MasterCtrl {
+	PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen =
+	    0x40c,
+	TxFreeThreshold = 0x40f, UpPktStatus = 0x410, UpListPtr = 0x418,
+};
+
+/* The Rx and Tx descriptor lists.
+   Caution Alpha hackers: these types are 32 bits!  Note also the 8 byte
+   alignment contraint on tx_ring[] and rx_ring[]. */
+struct boom_rx_desc {
+	u32 next;
+	s32 status;
+	u32 addr;
+	s32 length;
+};
+
+/* Values for the Rx status entry. */
+enum rx_desc_status {
+	RxDComplete = 0x00008000, RxDError = 0x4000,
+	/* See boomerang_rx() for actual error bits */
+};
+
+struct boom_tx_desc {
+	u32 next;
+	s32 status;
+	u32 addr;
+	s32 length;
+};
+
+struct corkscrew_private {
+	const char *product_name;
+	struct list_head list;
+	struct net_device *our_dev;
+	/* The Rx and Tx rings are here to keep them quad-word-aligned. */
+	struct boom_rx_desc rx_ring[RX_RING_SIZE];
+	struct boom_tx_desc tx_ring[TX_RING_SIZE];
+	/* The addresses of transmit- and receive-in-place skbuffs. */
+	struct sk_buff *rx_skbuff[RX_RING_SIZE];
+	struct sk_buff *tx_skbuff[TX_RING_SIZE];
+	unsigned int cur_rx, cur_tx;	/* The next free ring entry */
+	unsigned int dirty_rx, dirty_tx;/* The ring entries to be free()ed. */
+	struct sk_buff *tx_skb;	/* Packet being eaten by bus master ctrl.  */
+	struct timer_list timer;	/* Media selection timer. */
+	int capabilities	;	/* Adapter capabilities word. */
+	int options;			/* User-settable misc. driver options. */
+	int last_rx_packets;		/* For media autoselection. */
+	unsigned int available_media:8,	/* From Wn3_Options */
+		media_override:3,	/* Passed-in media type. */
+		default_media:3,	/* Read from the EEPROM. */
+		full_duplex:1, autoselect:1, bus_master:1,	/* Vortex can only do a fragment bus-m. */
+		full_bus_master_tx:1, full_bus_master_rx:1,	/* Boomerang  */
+		tx_full:1;
+	spinlock_t lock;
+	struct device *dev;
+};
+
+/* The action to take with a media selection timer tick.
+   Note that we deviate from the 3Com order by checking 10base2 before AUI.
+ */
+enum xcvr_types {
+	XCVR_10baseT = 0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,
+	XCVR_100baseFx, XCVR_MII = 6, XCVR_Default = 8,
+};
+
+static struct media_table {
+	char *name;
+	unsigned int media_bits:16,	/* Bits to set in Wn4_Media register. */
+		mask:8,			/* The transceiver-present bit in Wn3_Config. */
+		next:8;			/* The media type to try next. */
+	short wait;			/* Time before we check media status. */
+} media_tbl[] = {
+	{ "10baseT", Media_10TP, 0x08, XCVR_10base2, (14 * HZ) / 10 },
+	{ "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1 * HZ) / 10},
+	{ "undefined", 0, 0x80, XCVR_10baseT, 10000},
+	{ "10base2", 0, 0x10, XCVR_AUI, (1 * HZ) / 10},
+	{ "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14 * HZ) / 10},
+	{ "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14 * HZ) / 10},
+	{ "MII", 0, 0x40, XCVR_10baseT, 3 * HZ},
+	{ "undefined", 0, 0x01, XCVR_10baseT, 10000},
+	{ "Default", 0, 0xFF, XCVR_10baseT, 10000},
+};
+
+#ifdef __ISAPNP__
+static struct isapnp_device_id corkscrew_isapnp_adapters[] = {
+	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5051),
+		(long) "3Com Fast EtherLink ISA" },
+	{ }	/* terminate list */
+};
+
+MODULE_DEVICE_TABLE(isapnp, corkscrew_isapnp_adapters);
+
+static int nopnp;
+#endif /* __ISAPNP__ */
+
+static struct net_device *corkscrew_scan(int unit);
+static int corkscrew_setup(struct net_device *dev, int ioaddr,
+			    struct pnp_dev *idev, int card_number);
+static int corkscrew_open(struct net_device *dev);
+static void corkscrew_timer(unsigned long arg);
+static netdev_tx_t corkscrew_start_xmit(struct sk_buff *skb,
+					struct net_device *dev);
+static int corkscrew_rx(struct net_device *dev);
+static void corkscrew_timeout(struct net_device *dev);
+static int boomerang_rx(struct net_device *dev);
+static irqreturn_t corkscrew_interrupt(int irq, void *dev_id);
+static int corkscrew_close(struct net_device *dev);
+static void update_stats(int addr, struct net_device *dev);
+static struct net_device_stats *corkscrew_get_stats(struct net_device *dev);
+static void set_rx_mode(struct net_device *dev);
+static const struct ethtool_ops netdev_ethtool_ops;
+
+
+/*
+   Unfortunately maximizing the shared code between the integrated and
+   module version of the driver results in a complicated set of initialization
+   procedures.
+   init_module() -- modules /  tc59x_init()  -- built-in
+		The wrappers for corkscrew_scan()
+   corkscrew_scan()  		 The common routine that scans for PCI and EISA cards
+   corkscrew_found_device() Allocate a device structure when we find a card.
+					Different versions exist for modules and built-in.
+   corkscrew_probe1()		Fill in the device structure -- this is separated
+					so that the modules code can put it in dev->init.
+*/
+/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
+/* Note: this is the only limit on the number of cards supported!! */
+static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1, };
+
+#ifdef MODULE
+static int debug = -1;
+
+module_param(debug, int, 0);
+module_param_array(options, int, NULL, 0);
+module_param(rx_copybreak, int, 0);
+module_param(max_interrupt_work, int, 0);
+MODULE_PARM_DESC(debug, "3c515 debug level (0-6)");
+MODULE_PARM_DESC(options, "3c515: Bits 0-2: media type, bit 3: full duplex, bit 4: bus mastering");
+MODULE_PARM_DESC(rx_copybreak, "3c515 copy breakpoint for copy-only-tiny-frames");
+MODULE_PARM_DESC(max_interrupt_work, "3c515 maximum events handled per interrupt");
+
+/* A list of all installed Vortex devices, for removing the driver module. */
+/* we will need locking (and refcounting) if we ever use it for more */
+static LIST_HEAD(root_corkscrew_dev);
+
+int init_module(void)
+{
+	int found = 0;
+	if (debug >= 0)
+		corkscrew_debug = debug;
+	if (corkscrew_debug)
+		pr_debug("%s", version);
+	while (corkscrew_scan(-1))
+		found++;
+	return found ? 0 : -ENODEV;
+}
+
+#else
+struct net_device *tc515_probe(int unit)
+{
+	struct net_device *dev = corkscrew_scan(unit);
+	static int printed;
+
+	if (!dev)
+		return ERR_PTR(-ENODEV);
+
+	if (corkscrew_debug > 0 && !printed) {
+		printed = 1;
+		pr_debug("%s", version);
+	}
+
+	return dev;
+}
+#endif				/* not MODULE */
+
+static int check_device(unsigned ioaddr)
+{
+	int timer;
+
+	if (!request_region(ioaddr, CORKSCREW_TOTAL_SIZE, "3c515"))
+		return 0;
+	/* Check the resource configuration for a matching ioaddr. */
+	if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0)) {
+		release_region(ioaddr, CORKSCREW_TOTAL_SIZE);
+		return 0;
+	}
+	/* Verify by reading the device ID from the EEPROM. */
+	outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd);
+	/* Pause for at least 162 us. for the read to take place. */
+	for (timer = 4; timer >= 0; timer--) {
+		udelay(162);
+		if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
+			break;
+	}
+	if (inw(ioaddr + Wn0EepromData) != 0x6d50) {
+		release_region(ioaddr, CORKSCREW_TOTAL_SIZE);
+		return 0;
+	}
+	return 1;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+	struct corkscrew_private *vp = netdev_priv(dev);
+	list_del_init(&vp->list);
+	if (dev->dma)
+		free_dma(dev->dma);
+	outw(TotalReset, dev->base_addr + EL3_CMD);
+	release_region(dev->base_addr, CORKSCREW_TOTAL_SIZE);
+	if (vp->dev)
+		pnp_device_detach(to_pnp_dev(vp->dev));
+}
+
+static struct net_device *corkscrew_scan(int unit)
+{
+	struct net_device *dev;
+	static int cards_found = 0;
+	static int ioaddr;
+	int err;
+#ifdef __ISAPNP__
+	short i;
+	static int pnp_cards;
+#endif
+
+	dev = alloc_etherdev(sizeof(struct corkscrew_private));
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	if (unit >= 0) {
+		sprintf(dev->name, "eth%d", unit);
+		netdev_boot_setup_check(dev);
+	}
+
+#ifdef __ISAPNP__
+	if(nopnp == 1)
+		goto no_pnp;
+	for(i=0; corkscrew_isapnp_adapters[i].vendor != 0; i++) {
+		struct pnp_dev *idev = NULL;
+		int irq;
+		while((idev = pnp_find_dev(NULL,
+					   corkscrew_isapnp_adapters[i].vendor,
+					   corkscrew_isapnp_adapters[i].function,
+					   idev))) {
+
+			if (pnp_device_attach(idev) < 0)
+				continue;
+			if (pnp_activate_dev(idev) < 0) {
+				pr_warning("pnp activate failed (out of resources?)\n");
+				pnp_device_detach(idev);
+				continue;
+			}
+			if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) {
+				pnp_device_detach(idev);
+				continue;
+			}
+			ioaddr = pnp_port_start(idev, 0);
+			irq = pnp_irq(idev, 0);
+			if (!check_device(ioaddr)) {
+				pnp_device_detach(idev);
+				continue;
+			}
+			if(corkscrew_debug)
+				pr_debug("ISAPNP reports %s at i/o 0x%x, irq %d\n",
+					(char*) corkscrew_isapnp_adapters[i].driver_data, ioaddr, irq);
+			pr_info("3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
+		     		inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
+			/* irq = inw(ioaddr + 0x2002) & 15; */ /* Use the irq from isapnp */
+			SET_NETDEV_DEV(dev, &idev->dev);
+			pnp_cards++;
+			err = corkscrew_setup(dev, ioaddr, idev, cards_found++);
+			if (!err)
+				return dev;
+			cleanup_card(dev);
+		}
+	}
+no_pnp:
+#endif /* __ISAPNP__ */
+
+	/* Check all locations on the ISA bus -- evil! */
+	for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20) {
+		if (!check_device(ioaddr))
+			continue;
+
+		pr_info("3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
+		     inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
+		err = corkscrew_setup(dev, ioaddr, NULL, cards_found++);
+		if (!err)
+			return dev;
+		cleanup_card(dev);
+	}
+	free_netdev(dev);
+	return NULL;
+}
+
+
+static const struct net_device_ops netdev_ops = {
+	.ndo_open		= corkscrew_open,
+	.ndo_stop		= corkscrew_close,
+	.ndo_start_xmit		= corkscrew_start_xmit,
+	.ndo_tx_timeout		= corkscrew_timeout,
+	.ndo_get_stats		= corkscrew_get_stats,
+	.ndo_set_rx_mode	= set_rx_mode,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+
+static int corkscrew_setup(struct net_device *dev, int ioaddr,
+			    struct pnp_dev *idev, int card_number)
+{
+	struct corkscrew_private *vp = netdev_priv(dev);
+	unsigned int eeprom[0x40], checksum = 0;	/* EEPROM contents */
+	int i;
+	int irq;
+
+#ifdef __ISAPNP__
+	if (idev) {
+		irq = pnp_irq(idev, 0);
+		vp->dev = &idev->dev;
+	} else {
+		irq = inw(ioaddr + 0x2002) & 15;
+	}
+#else
+	irq = inw(ioaddr + 0x2002) & 15;
+#endif
+
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+	dev->dma = inw(ioaddr + 0x2000) & 7;
+	vp->product_name = "3c515";
+	vp->options = dev->mem_start;
+	vp->our_dev = dev;
+
+	if (!vp->options) {
+		 if (card_number >= MAX_UNITS)
+			vp->options = -1;
+		else
+			vp->options = options[card_number];
+	}
+
+	if (vp->options >= 0) {
+		vp->media_override = vp->options & 7;
+		if (vp->media_override == 2)
+			vp->media_override = 0;
+		vp->full_duplex = (vp->options & 8) ? 1 : 0;
+		vp->bus_master = (vp->options & 16) ? 1 : 0;
+	} else {
+		vp->media_override = 7;
+		vp->full_duplex = 0;
+		vp->bus_master = 0;
+	}
+#ifdef MODULE
+	list_add(&vp->list, &root_corkscrew_dev);
+#endif
+
+	pr_info("%s: 3Com %s at %#3x,", dev->name, vp->product_name, ioaddr);
+
+	spin_lock_init(&vp->lock);
+
+	/* Read the station address from the EEPROM. */
+	EL3WINDOW(0);
+	for (i = 0; i < 0x18; i++) {
+		__be16 *phys_addr = (__be16 *) dev->dev_addr;
+		int timer;
+		outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
+		/* Pause for at least 162 us. for the read to take place. */
+		for (timer = 4; timer >= 0; timer--) {
+			udelay(162);
+			if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
+				break;
+		}
+		eeprom[i] = inw(ioaddr + Wn0EepromData);
+		checksum ^= eeprom[i];
+		if (i < 3)
+			phys_addr[i] = htons(eeprom[i]);
+	}
+	checksum = (checksum ^ (checksum >> 8)) & 0xff;
+	if (checksum != 0x00)
+		pr_cont(" ***INVALID CHECKSUM %4.4x*** ", checksum);
+	pr_cont(" %pM", dev->dev_addr);
+	if (eeprom[16] == 0x11c7) {	/* Corkscrew */
+		if (request_dma(dev->dma, "3c515")) {
+			pr_cont(", DMA %d allocation failed", dev->dma);
+			dev->dma = 0;
+		} else
+			pr_cont(", DMA %d", dev->dma);
+	}
+	pr_cont(", IRQ %d\n", dev->irq);
+	/* Tell them about an invalid IRQ. */
+	if (corkscrew_debug && (dev->irq <= 0 || dev->irq > 15))
+		pr_warning(" *** Warning: this IRQ is unlikely to work! ***\n");
+
+	{
+		static const char * const ram_split[] = {
+			"5:3", "3:1", "1:1", "3:5"
+		};
+		__u32 config;
+		EL3WINDOW(3);
+		vp->available_media = inw(ioaddr + Wn3_Options);
+		config = inl(ioaddr + Wn3_Config);
+		if (corkscrew_debug > 1)
+			pr_info("  Internal config register is %4.4x, transceivers %#x.\n",
+				config, inw(ioaddr + Wn3_Options));
+		pr_info("  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
+			8 << config & Ram_size,
+			config & Ram_width ? "word" : "byte",
+			ram_split[(config & Ram_split) >> Ram_split_shift],
+			config & Autoselect ? "autoselect/" : "",
+			media_tbl[(config & Xcvr) >> Xcvr_shift].name);
+		vp->default_media = (config & Xcvr) >> Xcvr_shift;
+		vp->autoselect = config & Autoselect ? 1 : 0;
+		dev->if_port = vp->default_media;
+	}
+	if (vp->media_override != 7) {
+		pr_info("  Media override to transceiver type %d (%s).\n",
+		       vp->media_override,
+		       media_tbl[vp->media_override].name);
+		dev->if_port = vp->media_override;
+	}
+
+	vp->capabilities = eeprom[16];
+	vp->full_bus_master_tx = (vp->capabilities & 0x20) ? 1 : 0;
+	/* Rx is broken at 10mbps, so we always disable it. */
+	/* vp->full_bus_master_rx = 0; */
+	vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0;
+
+	/* The 3c51x-specific entries in the device structure. */
+	dev->netdev_ops = &netdev_ops;
+	dev->watchdog_timeo = (400 * HZ) / 1000;
+	dev->ethtool_ops = &netdev_ethtool_ops;
+
+	return register_netdev(dev);
+}
+
+
+static int corkscrew_open(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr;
+	struct corkscrew_private *vp = netdev_priv(dev);
+	__u32 config;
+	int i;
+
+	/* Before initializing select the active media port. */
+	EL3WINDOW(3);
+	if (vp->full_duplex)
+		outb(0x20, ioaddr + Wn3_MAC_Ctrl);	/* Set the full-duplex bit. */
+	config = inl(ioaddr + Wn3_Config);
+
+	if (vp->media_override != 7) {
+		if (corkscrew_debug > 1)
+			pr_info("%s: Media override to transceiver %d (%s).\n",
+				dev->name, vp->media_override,
+				media_tbl[vp->media_override].name);
+		dev->if_port = vp->media_override;
+	} else if (vp->autoselect) {
+		/* Find first available media type, starting with 100baseTx. */
+		dev->if_port = 4;
+		while (!(vp->available_media & media_tbl[dev->if_port].mask))
+			dev->if_port = media_tbl[dev->if_port].next;
+
+		if (corkscrew_debug > 1)
+			pr_debug("%s: Initial media type %s.\n",
+			       dev->name, media_tbl[dev->if_port].name);
+
+		init_timer(&vp->timer);
+		vp->timer.expires = jiffies + media_tbl[dev->if_port].wait;
+		vp->timer.data = (unsigned long) dev;
+		vp->timer.function = corkscrew_timer;	/* timer handler */
+		add_timer(&vp->timer);
+	} else
+		dev->if_port = vp->default_media;
+
+	config = (config & ~Xcvr) | (dev->if_port << Xcvr_shift);
+	outl(config, ioaddr + Wn3_Config);
+
+	if (corkscrew_debug > 1) {
+		pr_debug("%s: corkscrew_open() InternalConfig %8.8x.\n",
+		       dev->name, config);
+	}
+
+	outw(TxReset, ioaddr + EL3_CMD);
+	for (i = 20; i >= 0; i--)
+		if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
+			break;
+
+	outw(RxReset, ioaddr + EL3_CMD);
+	/* Wait a few ticks for the RxReset command to complete. */
+	for (i = 20; i >= 0; i--)
+		if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
+			break;
+
+	outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
+
+	/* Use the now-standard shared IRQ implementation. */
+	if (vp->capabilities == 0x11c7) {
+		/* Corkscrew: Cannot share ISA resources. */
+		if (dev->irq == 0 ||
+		    dev->dma == 0 ||
+		    request_irq(dev->irq, corkscrew_interrupt, 0,
+				vp->product_name, dev))
+			return -EAGAIN;
+		enable_dma(dev->dma);
+		set_dma_mode(dev->dma, DMA_MODE_CASCADE);
+	} else if (request_irq(dev->irq, corkscrew_interrupt, IRQF_SHARED,
+			       vp->product_name, dev)) {
+		return -EAGAIN;
+	}
+
+	if (corkscrew_debug > 1) {
+		EL3WINDOW(4);
+		pr_debug("%s: corkscrew_open() irq %d media status %4.4x.\n",
+		       dev->name, dev->irq, inw(ioaddr + Wn4_Media));
+	}
+
+	/* Set the station address and mask in window 2 each time opened. */
+	EL3WINDOW(2);
+	for (i = 0; i < 6; i++)
+		outb(dev->dev_addr[i], ioaddr + i);
+	for (; i < 12; i += 2)
+		outw(0, ioaddr + i);
+
+	if (dev->if_port == 3)
+		/* Start the thinnet transceiver. We should really wait 50ms... */
+		outw(StartCoax, ioaddr + EL3_CMD);
+	EL3WINDOW(4);
+	outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP | Media_SQE)) |
+	     media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
+
+	/* Switch to the stats window, and clear all stats by reading. */
+	outw(StatsDisable, ioaddr + EL3_CMD);
+	EL3WINDOW(6);
+	for (i = 0; i < 10; i++)
+		inb(ioaddr + i);
+	inw(ioaddr + 10);
+	inw(ioaddr + 12);
+	/* New: On the Vortex we must also clear the BadSSD counter. */
+	EL3WINDOW(4);
+	inb(ioaddr + 12);
+	/* ..and on the Boomerang we enable the extra statistics bits. */
+	outw(0x0040, ioaddr + Wn4_NetDiag);
+
+	/* Switch to register set 7 for normal use. */
+	EL3WINDOW(7);
+
+	if (vp->full_bus_master_rx) {	/* Boomerang bus master. */
+		vp->cur_rx = vp->dirty_rx = 0;
+		if (corkscrew_debug > 2)
+			pr_debug("%s:  Filling in the Rx ring.\n", dev->name);
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			struct sk_buff *skb;
+			if (i < (RX_RING_SIZE - 1))
+				vp->rx_ring[i].next =
+				    isa_virt_to_bus(&vp->rx_ring[i + 1]);
+			else
+				vp->rx_ring[i].next = 0;
+			vp->rx_ring[i].status = 0;	/* Clear complete bit. */
+			vp->rx_ring[i].length = PKT_BUF_SZ | 0x80000000;
+			skb = dev_alloc_skb(PKT_BUF_SZ);
+			vp->rx_skbuff[i] = skb;
+			if (skb == NULL)
+				break;	/* Bad news!  */
+			skb->dev = dev;	/* Mark as being used by this device. */
+			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
+			vp->rx_ring[i].addr = isa_virt_to_bus(skb->data);
+		}
+		if (i != 0)
+			vp->rx_ring[i - 1].next =
+				isa_virt_to_bus(&vp->rx_ring[0]);	/* Wrap the ring. */
+		outl(isa_virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
+	}
+	if (vp->full_bus_master_tx) {	/* Boomerang bus master Tx. */
+		vp->cur_tx = vp->dirty_tx = 0;
+		outb(PKT_BUF_SZ >> 8, ioaddr + TxFreeThreshold);	/* Room for a packet. */
+		/* Clear the Tx ring. */
+		for (i = 0; i < TX_RING_SIZE; i++)
+			vp->tx_skbuff[i] = NULL;
+		outl(0, ioaddr + DownListPtr);
+	}
+	/* Set receiver mode: presumably accept b-case and phys addr only. */
+	set_rx_mode(dev);
+	outw(StatsEnable, ioaddr + EL3_CMD);	/* Turn on statistics. */
+
+	netif_start_queue(dev);
+
+	outw(RxEnable, ioaddr + EL3_CMD);	/* Enable the receiver. */
+	outw(TxEnable, ioaddr + EL3_CMD);	/* Enable transmitter. */
+	/* Allow status bits to be seen. */
+	outw(SetStatusEnb | AdapterFailure | IntReq | StatsFull |
+	     (vp->full_bus_master_tx ? DownComplete : TxAvailable) |
+	     (vp->full_bus_master_rx ? UpComplete : RxComplete) |
+	     (vp->bus_master ? DMADone : 0), ioaddr + EL3_CMD);
+	/* Ack all pending events, and set active indicator mask. */
+	outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
+	     ioaddr + EL3_CMD);
+	outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
+	     | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
+	     ioaddr + EL3_CMD);
+
+	return 0;
+}
+
+static void corkscrew_timer(unsigned long data)
+{
+#ifdef AUTOMEDIA
+	struct net_device *dev = (struct net_device *) data;
+	struct corkscrew_private *vp = netdev_priv(dev);
+	int ioaddr = dev->base_addr;
+	unsigned long flags;
+	int ok = 0;
+
+	if (corkscrew_debug > 1)
+		pr_debug("%s: Media selection timer tick happened, %s.\n",
+		       dev->name, media_tbl[dev->if_port].name);
+
+	spin_lock_irqsave(&vp->lock, flags);
+
+	{
+		int old_window = inw(ioaddr + EL3_CMD) >> 13;
+		int media_status;
+		EL3WINDOW(4);
+		media_status = inw(ioaddr + Wn4_Media);
+		switch (dev->if_port) {
+		case 0:
+		case 4:
+		case 5:	/* 10baseT, 100baseTX, 100baseFX  */
+			if (media_status & Media_LnkBeat) {
+				ok = 1;
+				if (corkscrew_debug > 1)
+					pr_debug("%s: Media %s has link beat, %x.\n",
+						dev->name,
+						media_tbl[dev->if_port].name,
+						media_status);
+			} else if (corkscrew_debug > 1)
+				pr_debug("%s: Media %s is has no link beat, %x.\n",
+					dev->name,
+					media_tbl[dev->if_port].name,
+					media_status);
+
+			break;
+		default:	/* Other media types handled by Tx timeouts. */
+			if (corkscrew_debug > 1)
+				pr_debug("%s: Media %s is has no indication, %x.\n",
+					dev->name,
+					media_tbl[dev->if_port].name,
+					media_status);
+			ok = 1;
+		}
+		if (!ok) {
+			__u32 config;
+
+			do {
+				dev->if_port =
+				    media_tbl[dev->if_port].next;
+			}
+			while (!(vp->available_media & media_tbl[dev->if_port].mask));
+
+			if (dev->if_port == 8) {	/* Go back to default. */
+				dev->if_port = vp->default_media;
+				if (corkscrew_debug > 1)
+					pr_debug("%s: Media selection failing, using default %s port.\n",
+						dev->name,
+						media_tbl[dev->if_port].name);
+			} else {
+				if (corkscrew_debug > 1)
+					pr_debug("%s: Media selection failed, now trying %s port.\n",
+						dev->name,
+						media_tbl[dev->if_port].name);
+				vp->timer.expires = jiffies + media_tbl[dev->if_port].wait;
+				add_timer(&vp->timer);
+			}
+			outw((media_status & ~(Media_10TP | Media_SQE)) |
+			     media_tbl[dev->if_port].media_bits,
+			     ioaddr + Wn4_Media);
+
+			EL3WINDOW(3);
+			config = inl(ioaddr + Wn3_Config);
+			config = (config & ~Xcvr) | (dev->if_port << Xcvr_shift);
+			outl(config, ioaddr + Wn3_Config);
+
+			outw(dev->if_port == 3 ? StartCoax : StopCoax,
+			     ioaddr + EL3_CMD);
+		}
+		EL3WINDOW(old_window);
+	}
+
+	spin_unlock_irqrestore(&vp->lock, flags);
+	if (corkscrew_debug > 1)
+		pr_debug("%s: Media selection timer finished, %s.\n",
+		       dev->name, media_tbl[dev->if_port].name);
+
+#endif				/* AUTOMEDIA */
+}
+
+static void corkscrew_timeout(struct net_device *dev)
+{
+	int i;
+	struct corkscrew_private *vp = netdev_priv(dev);
+	int ioaddr = dev->base_addr;
+
+	pr_warning("%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
+	       dev->name, inb(ioaddr + TxStatus),
+	       inw(ioaddr + EL3_STATUS));
+	/* Slight code bloat to be user friendly. */
+	if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
+		pr_warning("%s: Transmitter encountered 16 collisions --"
+		       " network cable problem?\n", dev->name);
+#ifndef final_version
+	pr_debug("  Flags; bus-master %d, full %d; dirty %d current %d.\n",
+	       vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx,
+	       vp->cur_tx);
+	pr_debug("  Down list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr),
+	       &vp->tx_ring[0]);
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		pr_debug("  %d: %p  length %8.8x status %8.8x\n", i,
+		       &vp->tx_ring[i],
+		       vp->tx_ring[i].length, vp->tx_ring[i].status);
+	}
+#endif
+	/* Issue TX_RESET and TX_START commands. */
+	outw(TxReset, ioaddr + EL3_CMD);
+	for (i = 20; i >= 0; i--)
+		if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
+			break;
+	outw(TxEnable, ioaddr + EL3_CMD);
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	dev->stats.tx_errors++;
+	dev->stats.tx_dropped++;
+	netif_wake_queue(dev);
+}
+
+static netdev_tx_t corkscrew_start_xmit(struct sk_buff *skb,
+					struct net_device *dev)
+{
+	struct corkscrew_private *vp = netdev_priv(dev);
+	int ioaddr = dev->base_addr;
+
+	/* Block a timer-based transmit from overlapping. */
+
+	netif_stop_queue(dev);
+
+	if (vp->full_bus_master_tx) {	/* BOOMERANG bus-master */
+		/* Calculate the next Tx descriptor entry. */
+		int entry = vp->cur_tx % TX_RING_SIZE;
+		struct boom_tx_desc *prev_entry;
+		unsigned long flags;
+		int i;
+
+		if (vp->tx_full)	/* No room to transmit with */
+			return NETDEV_TX_BUSY;
+		if (vp->cur_tx != 0)
+			prev_entry = &vp->tx_ring[(vp->cur_tx - 1) % TX_RING_SIZE];
+		else
+			prev_entry = NULL;
+		if (corkscrew_debug > 3)
+			pr_debug("%s: Trying to send a packet, Tx index %d.\n",
+				dev->name, vp->cur_tx);
+		/* vp->tx_full = 1; */
+		vp->tx_skbuff[entry] = skb;
+		vp->tx_ring[entry].next = 0;
+		vp->tx_ring[entry].addr = isa_virt_to_bus(skb->data);
+		vp->tx_ring[entry].length = skb->len | 0x80000000;
+		vp->tx_ring[entry].status = skb->len | 0x80000000;
+
+		spin_lock_irqsave(&vp->lock, flags);
+		outw(DownStall, ioaddr + EL3_CMD);
+		/* Wait for the stall to complete. */
+		for (i = 20; i >= 0; i--)
+			if ((inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0)
+				break;
+		if (prev_entry)
+			prev_entry->next = isa_virt_to_bus(&vp->tx_ring[entry]);
+		if (inl(ioaddr + DownListPtr) == 0) {
+			outl(isa_virt_to_bus(&vp->tx_ring[entry]),
+			     ioaddr + DownListPtr);
+			queued_packet++;
+		}
+		outw(DownUnstall, ioaddr + EL3_CMD);
+		spin_unlock_irqrestore(&vp->lock, flags);
+
+		vp->cur_tx++;
+		if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)
+			vp->tx_full = 1;
+		else {		/* Clear previous interrupt enable. */
+			if (prev_entry)
+				prev_entry->status &= ~0x80000000;
+			netif_wake_queue(dev);
+		}
+		return NETDEV_TX_OK;
+	}
+	/* Put out the doubleword header... */
+	outl(skb->len, ioaddr + TX_FIFO);
+	dev->stats.tx_bytes += skb->len;
+#ifdef VORTEX_BUS_MASTER
+	if (vp->bus_master) {
+		/* Set the bus-master controller to transfer the packet. */
+		outl((int) (skb->data), ioaddr + Wn7_MasterAddr);
+		outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
+		vp->tx_skb = skb;
+		outw(StartDMADown, ioaddr + EL3_CMD);
+		/* queue will be woken at the DMADone interrupt. */
+	} else {
+		/* ... and the packet rounded to a doubleword. */
+		outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+		dev_kfree_skb(skb);
+		if (inw(ioaddr + TxFree) > 1536) {
+			netif_wake_queue(dev);
+		} else
+			/* Interrupt us when the FIFO has room for max-sized packet. */
+			outw(SetTxThreshold + (1536 >> 2),
+			     ioaddr + EL3_CMD);
+	}
+#else
+	/* ... and the packet rounded to a doubleword. */
+	outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+	dev_kfree_skb(skb);
+	if (inw(ioaddr + TxFree) > 1536) {
+		netif_wake_queue(dev);
+	} else
+		/* Interrupt us when the FIFO has room for max-sized packet. */
+		outw(SetTxThreshold + (1536 >> 2), ioaddr + EL3_CMD);
+#endif				/* bus master */
+
+
+	/* Clear the Tx status stack. */
+	{
+		short tx_status;
+		int i = 4;
+
+		while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) {
+			if (tx_status & 0x3C) {	/* A Tx-disabling error occurred.  */
+				if (corkscrew_debug > 2)
+					pr_debug("%s: Tx error, status %2.2x.\n",
+						dev->name, tx_status);
+				if (tx_status & 0x04)
+					dev->stats.tx_fifo_errors++;
+				if (tx_status & 0x38)
+					dev->stats.tx_aborted_errors++;
+				if (tx_status & 0x30) {
+					int j;
+					outw(TxReset, ioaddr + EL3_CMD);
+					for (j = 20; j >= 0; j--)
+						if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
+							break;
+				}
+				outw(TxEnable, ioaddr + EL3_CMD);
+			}
+			outb(0x00, ioaddr + TxStatus);	/* Pop the status stack. */
+		}
+	}
+	return NETDEV_TX_OK;
+}
+
+/* The interrupt handler does all of the Rx thread work and cleans up
+   after the Tx thread. */
+
+static irqreturn_t corkscrew_interrupt(int irq, void *dev_id)
+{
+	/* Use the now-standard shared IRQ implementation. */
+	struct net_device *dev = dev_id;
+	struct corkscrew_private *lp = netdev_priv(dev);
+	int ioaddr, status;
+	int latency;
+	int i = max_interrupt_work;
+
+	ioaddr = dev->base_addr;
+	latency = inb(ioaddr + Timer);
+
+	spin_lock(&lp->lock);
+
+	status = inw(ioaddr + EL3_STATUS);
+
+	if (corkscrew_debug > 4)
+		pr_debug("%s: interrupt, status %4.4x, timer %d.\n",
+			dev->name, status, latency);
+	if ((status & 0xE000) != 0xE000) {
+		static int donedidthis;
+		/* Some interrupt controllers store a bogus interrupt from boot-time.
+		   Ignore a single early interrupt, but don't hang the machine for
+		   other interrupt problems. */
+		if (donedidthis++ > 100) {
+			pr_err("%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n",
+				   dev->name, status, netif_running(dev));
+			free_irq(dev->irq, dev);
+			dev->irq = -1;
+		}
+	}
+
+	do {
+		if (corkscrew_debug > 5)
+			pr_debug("%s: In interrupt loop, status %4.4x.\n",
+			       dev->name, status);
+		if (status & RxComplete)
+			corkscrew_rx(dev);
+
+		if (status & TxAvailable) {
+			if (corkscrew_debug > 5)
+				pr_debug("	TX room bit was handled.\n");
+			/* There's room in the FIFO for a full-sized packet. */
+			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
+			netif_wake_queue(dev);
+		}
+		if (status & DownComplete) {
+			unsigned int dirty_tx = lp->dirty_tx;
+
+			while (lp->cur_tx - dirty_tx > 0) {
+				int entry = dirty_tx % TX_RING_SIZE;
+				if (inl(ioaddr + DownListPtr) == isa_virt_to_bus(&lp->tx_ring[entry]))
+					break;	/* It still hasn't been processed. */
+				if (lp->tx_skbuff[entry]) {
+					dev_kfree_skb_irq(lp->tx_skbuff[entry]);
+					lp->tx_skbuff[entry] = NULL;
+				}
+				dirty_tx++;
+			}
+			lp->dirty_tx = dirty_tx;
+			outw(AckIntr | DownComplete, ioaddr + EL3_CMD);
+			if (lp->tx_full && (lp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
+				lp->tx_full = 0;
+				netif_wake_queue(dev);
+			}
+		}
+#ifdef VORTEX_BUS_MASTER
+		if (status & DMADone) {
+			outw(0x1000, ioaddr + Wn7_MasterStatus);	/* Ack the event. */
+			dev_kfree_skb_irq(lp->tx_skb);	/* Release the transferred buffer */
+			netif_wake_queue(dev);
+		}
+#endif
+		if (status & UpComplete) {
+			boomerang_rx(dev);
+			outw(AckIntr | UpComplete, ioaddr + EL3_CMD);
+		}
+		if (status & (AdapterFailure | RxEarly | StatsFull)) {
+			/* Handle all uncommon interrupts at once. */
+			if (status & RxEarly) {	/* Rx early is unused. */
+				corkscrew_rx(dev);
+				outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
+			}
+			if (status & StatsFull) {	/* Empty statistics. */
+				static int DoneDidThat;
+				if (corkscrew_debug > 4)
+					pr_debug("%s: Updating stats.\n", dev->name);
+				update_stats(ioaddr, dev);
+				/* DEBUG HACK: Disable statistics as an interrupt source. */
+				/* This occurs when we have the wrong media type! */
+				if (DoneDidThat == 0 && inw(ioaddr + EL3_STATUS) & StatsFull) {
+					int win, reg;
+					pr_notice("%s: Updating stats failed, disabling stats as an interrupt source.\n",
+						dev->name);
+					for (win = 0; win < 8; win++) {
+						EL3WINDOW(win);
+						pr_notice("Vortex window %d:", win);
+						for (reg = 0; reg < 16; reg++)
+							pr_cont(" %2.2x", inb(ioaddr + reg));
+						pr_cont("\n");
+					}
+					EL3WINDOW(7);
+					outw(SetIntrEnb | TxAvailable |
+					     RxComplete | AdapterFailure |
+					     UpComplete | DownComplete |
+					     TxComplete, ioaddr + EL3_CMD);
+					DoneDidThat++;
+				}
+			}
+			if (status & AdapterFailure) {
+				/* Adapter failure requires Rx reset and reinit. */
+				outw(RxReset, ioaddr + EL3_CMD);
+				/* Set the Rx filter to the current state. */
+				set_rx_mode(dev);
+				outw(RxEnable, ioaddr + EL3_CMD);	/* Re-enable the receiver. */
+				outw(AckIntr | AdapterFailure,
+				     ioaddr + EL3_CMD);
+			}
+		}
+
+		if (--i < 0) {
+			pr_err("%s: Too much work in interrupt, status %4.4x. Disabling functions (%4.4x).\n",
+				dev->name, status, SetStatusEnb | ((~status) & 0x7FE));
+			/* Disable all pending interrupts. */
+			outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD);
+			outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
+			break;
+		}
+		/* Acknowledge the IRQ. */
+		outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
+
+	} while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
+
+	spin_unlock(&lp->lock);
+
+	if (corkscrew_debug > 4)
+		pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name, status);
+	return IRQ_HANDLED;
+}
+
+static int corkscrew_rx(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr;
+	int i;
+	short rx_status;
+
+	if (corkscrew_debug > 5)
+		pr_debug("   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
+		     inw(ioaddr + EL3_STATUS), inw(ioaddr + RxStatus));
+	while ((rx_status = inw(ioaddr + RxStatus)) > 0) {
+		if (rx_status & 0x4000) {	/* Error, update stats. */
+			unsigned char rx_error = inb(ioaddr + RxErrors);
+			if (corkscrew_debug > 2)
+				pr_debug(" Rx error: status %2.2x.\n",
+				       rx_error);
+			dev->stats.rx_errors++;
+			if (rx_error & 0x01)
+				dev->stats.rx_over_errors++;
+			if (rx_error & 0x02)
+				dev->stats.rx_length_errors++;
+			if (rx_error & 0x04)
+				dev->stats.rx_frame_errors++;
+			if (rx_error & 0x08)
+				dev->stats.rx_crc_errors++;
+			if (rx_error & 0x10)
+				dev->stats.rx_length_errors++;
+		} else {
+			/* The packet length: up to 4.5K!. */
+			short pkt_len = rx_status & 0x1fff;
+			struct sk_buff *skb;
+
+			skb = dev_alloc_skb(pkt_len + 5 + 2);
+			if (corkscrew_debug > 4)
+				pr_debug("Receiving packet size %d status %4.4x.\n",
+				     pkt_len, rx_status);
+			if (skb != NULL) {
+				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
+				/* 'skb_put()' points to the start of sk_buff data area. */
+				insl(ioaddr + RX_FIFO,
+				     skb_put(skb, pkt_len),
+				     (pkt_len + 3) >> 2);
+				outw(RxDiscard, ioaddr + EL3_CMD);	/* Pop top Rx packet. */
+				skb->protocol = eth_type_trans(skb, dev);
+				netif_rx(skb);
+				dev->stats.rx_packets++;
+				dev->stats.rx_bytes += pkt_len;
+				/* Wait a limited time to go to next packet. */
+				for (i = 200; i >= 0; i--)
+					if (! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+						break;
+				continue;
+			} else if (corkscrew_debug)
+				pr_debug("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, pkt_len);
+		}
+		outw(RxDiscard, ioaddr + EL3_CMD);
+		dev->stats.rx_dropped++;
+		/* Wait a limited time to skip this packet. */
+		for (i = 200; i >= 0; i--)
+			if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
+				break;
+	}
+	return 0;
+}
+
+static int boomerang_rx(struct net_device *dev)
+{
+	struct corkscrew_private *vp = netdev_priv(dev);
+	int entry = vp->cur_rx % RX_RING_SIZE;
+	int ioaddr = dev->base_addr;
+	int rx_status;
+
+	if (corkscrew_debug > 5)
+		pr_debug("   In boomerang_rx(), status %4.4x, rx_status %4.4x.\n",
+			inw(ioaddr + EL3_STATUS), inw(ioaddr + RxStatus));
+	while ((rx_status = vp->rx_ring[entry].status) & RxDComplete) {
+		if (rx_status & RxDError) {	/* Error, update stats. */
+			unsigned char rx_error = rx_status >> 16;
+			if (corkscrew_debug > 2)
+				pr_debug(" Rx error: status %2.2x.\n",
+				       rx_error);
+			dev->stats.rx_errors++;
+			if (rx_error & 0x01)
+				dev->stats.rx_over_errors++;
+			if (rx_error & 0x02)
+				dev->stats.rx_length_errors++;
+			if (rx_error & 0x04)
+				dev->stats.rx_frame_errors++;
+			if (rx_error & 0x08)
+				dev->stats.rx_crc_errors++;
+			if (rx_error & 0x10)
+				dev->stats.rx_length_errors++;
+		} else {
+			/* The packet length: up to 4.5K!. */
+			short pkt_len = rx_status & 0x1fff;
+			struct sk_buff *skb;
+
+			dev->stats.rx_bytes += pkt_len;
+			if (corkscrew_debug > 4)
+				pr_debug("Receiving packet size %d status %4.4x.\n",
+				     pkt_len, rx_status);
+
+			/* Check if the packet is long enough to just accept without
+			   copying to a properly sized skbuff. */
+			if (pkt_len < rx_copybreak &&
+			    (skb = dev_alloc_skb(pkt_len + 4)) != NULL) {
+				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
+				/* 'skb_put()' points to the start of sk_buff data area. */
+				memcpy(skb_put(skb, pkt_len),
+				       isa_bus_to_virt(vp->rx_ring[entry].
+						   addr), pkt_len);
+				rx_copy++;
+			} else {
+				void *temp;
+				/* Pass up the skbuff already on the Rx ring. */
+				skb = vp->rx_skbuff[entry];
+				vp->rx_skbuff[entry] = NULL;
+				temp = skb_put(skb, pkt_len);
+				/* Remove this checking code for final release. */
+				if (isa_bus_to_virt(vp->rx_ring[entry].addr) != temp)
+					pr_warning("%s: Warning -- the skbuff addresses do not match"
+					     " in boomerang_rx: %p vs. %p / %p.\n",
+					     dev->name,
+					     isa_bus_to_virt(vp->
+							 rx_ring[entry].
+							 addr), skb->head,
+					     temp);
+				rx_nocopy++;
+			}
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+			dev->stats.rx_packets++;
+		}
+		entry = (++vp->cur_rx) % RX_RING_SIZE;
+	}
+	/* Refill the Rx ring buffers. */
+	for (; vp->cur_rx - vp->dirty_rx > 0; vp->dirty_rx++) {
+		struct sk_buff *skb;
+		entry = vp->dirty_rx % RX_RING_SIZE;
+		if (vp->rx_skbuff[entry] == NULL) {
+			skb = dev_alloc_skb(PKT_BUF_SZ);
+			if (skb == NULL)
+				break;	/* Bad news!  */
+			skb->dev = dev;	/* Mark as being used by this device. */
+			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
+			vp->rx_ring[entry].addr = isa_virt_to_bus(skb->data);
+			vp->rx_skbuff[entry] = skb;
+		}
+		vp->rx_ring[entry].status = 0;	/* Clear complete bit. */
+	}
+	return 0;
+}
+
+static int corkscrew_close(struct net_device *dev)
+{
+	struct corkscrew_private *vp = netdev_priv(dev);
+	int ioaddr = dev->base_addr;
+	int i;
+
+	netif_stop_queue(dev);
+
+	if (corkscrew_debug > 1) {
+		pr_debug("%s: corkscrew_close() status %4.4x, Tx status %2.2x.\n",
+		     dev->name, inw(ioaddr + EL3_STATUS),
+		     inb(ioaddr + TxStatus));
+		pr_debug("%s: corkscrew close stats: rx_nocopy %d rx_copy %d tx_queued %d.\n",
+			dev->name, rx_nocopy, rx_copy, queued_packet);
+	}
+
+	del_timer(&vp->timer);
+
+	/* Turn off statistics ASAP.  We update lp->stats below. */
+	outw(StatsDisable, ioaddr + EL3_CMD);
+
+	/* Disable the receiver and transmitter. */
+	outw(RxDisable, ioaddr + EL3_CMD);
+	outw(TxDisable, ioaddr + EL3_CMD);
+
+	if (dev->if_port == XCVR_10base2)
+		/* Turn off thinnet power.  Green! */
+		outw(StopCoax, ioaddr + EL3_CMD);
+
+	free_irq(dev->irq, dev);
+
+	outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
+
+	update_stats(ioaddr, dev);
+	if (vp->full_bus_master_rx) {	/* Free Boomerang bus master Rx buffers. */
+		outl(0, ioaddr + UpListPtr);
+		for (i = 0; i < RX_RING_SIZE; i++)
+			if (vp->rx_skbuff[i]) {
+				dev_kfree_skb(vp->rx_skbuff[i]);
+				vp->rx_skbuff[i] = NULL;
+			}
+	}
+	if (vp->full_bus_master_tx) {	/* Free Boomerang bus master Tx buffers. */
+		outl(0, ioaddr + DownListPtr);
+		for (i = 0; i < TX_RING_SIZE; i++)
+			if (vp->tx_skbuff[i]) {
+				dev_kfree_skb(vp->tx_skbuff[i]);
+				vp->tx_skbuff[i] = NULL;
+			}
+	}
+
+	return 0;
+}
+
+static struct net_device_stats *corkscrew_get_stats(struct net_device *dev)
+{
+	struct corkscrew_private *vp = netdev_priv(dev);
+	unsigned long flags;
+
+	if (netif_running(dev)) {
+		spin_lock_irqsave(&vp->lock, flags);
+		update_stats(dev->base_addr, dev);
+		spin_unlock_irqrestore(&vp->lock, flags);
+	}
+	return &dev->stats;
+}
+
+/*  Update statistics.
+	Unlike with the EL3 we need not worry about interrupts changing
+	the window setting from underneath us, but we must still guard
+	against a race condition with a StatsUpdate interrupt updating the
+	table.  This is done by checking that the ASM (!) code generated uses
+	atomic updates with '+='.
+	*/
+static void update_stats(int ioaddr, struct net_device *dev)
+{
+	/* Unlike the 3c5x9 we need not turn off stats updates while reading. */
+	/* Switch to the stats window, and read everything. */
+	EL3WINDOW(6);
+	dev->stats.tx_carrier_errors += inb(ioaddr + 0);
+	dev->stats.tx_heartbeat_errors += inb(ioaddr + 1);
+	/* Multiple collisions. */ inb(ioaddr + 2);
+	dev->stats.collisions += inb(ioaddr + 3);
+	dev->stats.tx_window_errors += inb(ioaddr + 4);
+	dev->stats.rx_fifo_errors += inb(ioaddr + 5);
+	dev->stats.tx_packets += inb(ioaddr + 6);
+	dev->stats.tx_packets += (inb(ioaddr + 9) & 0x30) << 4;
+						/* Rx packets   */ inb(ioaddr + 7);
+						/* Must read to clear */
+	/* Tx deferrals */ inb(ioaddr + 8);
+	/* Don't bother with register 9, an extension of registers 6&7.
+	   If we do use the 6&7 values the atomic update assumption above
+	   is invalid. */
+	inw(ioaddr + 10);	/* Total Rx and Tx octets. */
+	inw(ioaddr + 12);
+	/* New: On the Vortex we must also clear the BadSSD counter. */
+	EL3WINDOW(4);
+	inb(ioaddr + 12);
+
+	/* We change back to window 7 (not 1) with the Vortex. */
+	EL3WINDOW(7);
+}
+
+/* This new version of set_rx_mode() supports v1.4 kernels.
+   The Vortex chip has no documented multicast filter, so the only
+   multicast setting is to receive all multicast frames.  At least
+   the chip has a very clean way to set the mode, unlike many others. */
+static void set_rx_mode(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr;
+	short new_mode;
+
+	if (dev->flags & IFF_PROMISC) {
+		if (corkscrew_debug > 3)
+			pr_debug("%s: Setting promiscuous mode.\n",
+			       dev->name);
+		new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm;
+	} else if (!netdev_mc_empty(dev) || dev->flags & IFF_ALLMULTI) {
+		new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast;
+	} else
+		new_mode = SetRxFilter | RxStation | RxBroadcast;
+
+	outw(new_mode, ioaddr + EL3_CMD);
+}
+
+static void netdev_get_drvinfo(struct net_device *dev,
+			       struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	sprintf(info->bus_info, "ISA 0x%lx", dev->base_addr);
+}
+
+static u32 netdev_get_msglevel(struct net_device *dev)
+{
+	return corkscrew_debug;
+}
+
+static void netdev_set_msglevel(struct net_device *dev, u32 level)
+{
+	corkscrew_debug = level;
+}
+
+static const struct ethtool_ops netdev_ethtool_ops = {
+	.get_drvinfo		= netdev_get_drvinfo,
+	.get_msglevel		= netdev_get_msglevel,
+	.set_msglevel		= netdev_set_msglevel,
+};
+
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+	while (!list_empty(&root_corkscrew_dev)) {
+		struct net_device *dev;
+		struct corkscrew_private *vp;
+
+		vp = list_entry(root_corkscrew_dev.next,
+				struct corkscrew_private, list);
+		dev = vp->our_dev;
+		unregister_netdev(dev);
+		cleanup_card(dev);
+		free_netdev(dev);
+	}
+}
+#endif				/* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/3com/3c574_cs.c linux-libre-3.2-gnu/drivers/net/ethernet/3com/3c574_cs.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/3com/3c574_cs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/3com/3c574_cs.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1181 @@
+/* 3c574.c: A PCMCIA ethernet driver for the 3com 3c574 "RoadRunner".
+
+	Written 1993-1998 by
+	Donald Becker, becker@scyld.com, (driver core) and
+	David Hinds, dahinds@users.sourceforge.net (from his PC card code).
+	Locking fixes (C) Copyright 2003 Red Hat Inc
+
+	This software may be used and distributed according to the terms of
+	the GNU General Public License, incorporated herein by reference.
+
+	This driver derives from Donald Becker's 3c509 core, which has the
+	following copyright:
+	Copyright 1993 United States Government as represented by the
+	Director, National Security Agency.
+	
+
+*/
+
+/*
+				Theory of Operation
+
+I. Board Compatibility
+
+This device driver is designed for the 3Com 3c574 PC card Fast Ethernet
+Adapter.
+
+II. Board-specific settings
+
+None -- PC cards are autoconfigured.
+
+III. Driver operation
+
+The 3c574 uses a Boomerang-style interface, without the bus-master capability.
+See the Boomerang driver and documentation for most details.
+
+IV. Notes and chip documentation.
+
+Two added registers are used to enhance PIO performance, RunnerRdCtrl and
+RunnerWrCtrl.  These are 11 bit down-counters that are preloaded with the
+count of word (16 bits) reads or writes the driver is about to do to the Rx
+or Tx FIFO.  The chip is then able to hide the internal-PCI-bus to PC-card
+translation latency by buffering the I/O operations with an 8 word FIFO.
+Note: No other chip accesses are permitted when this buffer is used.
+
+A second enhancement is that both attribute and common memory space
+0x0800-0x0fff can translated to the PIO FIFO.  Thus memory operations (faster
+with *some* PCcard bridges) may be used instead of I/O operations.
+This is enabled by setting the 0x10 bit in the PCMCIA LAN COR.
+
+Some slow PC card bridges work better if they never see a WAIT signal.
+This is configured by setting the 0x20 bit in the PCMCIA LAN COR.
+Only do this after testing that it is reliable and improves performance.
+
+The upper five bits of RunnerRdCtrl are used to window into PCcard
+configuration space registers.  Window 0 is the regular Boomerang/Odie
+register set, 1-5 are various PC card control registers, and 16-31 are
+the (reversed!) CIS table.
+
+A final note: writing the InternalConfig register in window 3 with an
+invalid ramWidth is Very Bad.
+
+V. References
+
+http://www.scyld.com/expert/NWay.html
+http://www.national.com/opf/DP/DP83840A.html
+
+Thanks to Terry Murphy of 3Com for providing development information for
+earlier 3Com products.
+
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+#include <linux/bitops.h>
+#include <linux/mii.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ciscode.h>
+#include <pcmcia/ds.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+/*====================================================================*/
+
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
+MODULE_DESCRIPTION("3Com 3c574 series PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");
+
+#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
+
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+INT_MODULE_PARM(max_interrupt_work, 32);
+
+/* Force full duplex modes? */
+INT_MODULE_PARM(full_duplex, 0);
+
+/* Autodetect link polarity reversal? */
+INT_MODULE_PARM(auto_polarity, 1);
+
+
+/*====================================================================*/
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  ((800*HZ)/1000)
+
+/* To minimize the size of the driver source and make the driver more
+   readable not all constants are symbolically defined.
+   You'll need the manual if you want to understand driver details anyway. */
+/* Offsets from base I/O address. */
+#define EL3_DATA	0x00
+#define EL3_CMD		0x0e
+#define EL3_STATUS	0x0e
+
+#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
+
+/* The top five bits written to EL3_CMD are a command, the lower
+   11 bits are the parameter, if applicable. */
+enum el3_cmds {
+	TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
+	RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11,
+	TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
+	FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
+	SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
+	SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11,
+	StatsDisable = 22<<11, StopCoax = 23<<11,
+};
+
+enum elxl_status {
+	IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
+	TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
+	IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000 };
+
+/* The SetRxFilter command accepts the following classes: */
+enum RxFilter {
+	RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
+};
+
+enum Window0 {
+	Wn0EepromCmd = 10, Wn0EepromData = 12, /* EEPROM command/address, data. */
+	IntrStatus=0x0E,		/* Valid in all windows. */
+};
+/* These assumes the larger EEPROM. */
+enum Win0_EEPROM_cmds {
+	EEPROM_Read = 0x200, EEPROM_WRITE = 0x100, EEPROM_ERASE = 0x300,
+	EEPROM_EWENB = 0x30,		/* Enable erasing/writing for 10 msec. */
+	EEPROM_EWDIS = 0x00,		/* Disable EWENB before 10 msec timeout. */
+};
+
+/* Register window 1 offsets, the window used in normal operation.
+   On the "Odie" this window is always mapped at offsets 0x10-0x1f.
+   Except for TxFree, which is overlapped by RunnerWrCtrl. */
+enum Window1 {
+	TX_FIFO = 0x10,  RX_FIFO = 0x10,  RxErrors = 0x14,
+	RxStatus = 0x18,  Timer=0x1A, TxStatus = 0x1B,
+	TxFree = 0x0C, /* Remaining free bytes in Tx buffer. */
+	RunnerRdCtrl = 0x16, RunnerWrCtrl = 0x1c,
+};
+
+enum Window3 {			/* Window 3: MAC/config bits. */
+	Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
+};
+enum wn3_config {
+	Ram_size = 7,
+	Ram_width = 8,
+	Ram_speed = 0x30,
+	Rom_size = 0xc0,
+	Ram_split_shift = 16,
+	Ram_split = 3 << Ram_split_shift,
+	Xcvr_shift = 20,
+	Xcvr = 7 << Xcvr_shift,
+	Autoselect = 0x1000000,
+};
+
+enum Window4 {		/* Window 4: Xcvr/media bits. */
+	Wn4_FIFODiag = 4, Wn4_NetDiag = 6, Wn4_PhysicalMgmt=8, Wn4_Media = 10,
+};
+
+#define MEDIA_TP	0x00C0	/* Enable link beat and jabber for 10baseT. */
+
+struct el3_private {
+	struct pcmcia_device	*p_dev;
+	u16 advertising, partner;		/* NWay media advertisement */
+	unsigned char phys;			/* MII device address */
+	unsigned int autoselect:1, default_media:3;	/* Read from the EEPROM/Wn3_Config. */
+	/* for transceiver monitoring */
+	struct timer_list media;
+	unsigned short media_status;
+	unsigned short fast_poll;
+	unsigned long last_irq;
+	spinlock_t window_lock;			/* Guards the Window selection */
+};
+
+/* Set iff a MII transceiver on any interface requires mdio preamble.
+   This only set with the original DP83840 on older 3c905 boards, so the extra
+   code size of a per-interface flag is not worthwhile. */
+static char mii_preamble_required = 0;
+
+/* Index of functions. */
+
+static int tc574_config(struct pcmcia_device *link);
+static void tc574_release(struct pcmcia_device *link);
+
+static void mdio_sync(unsigned int ioaddr, int bits);
+static int mdio_read(unsigned int ioaddr, int phy_id, int location);
+static void mdio_write(unsigned int ioaddr, int phy_id, int location,
+		       int value);
+static unsigned short read_eeprom(unsigned int ioaddr, int index);
+static void tc574_wait_for_completion(struct net_device *dev, int cmd);
+
+static void tc574_reset(struct net_device *dev);
+static void media_check(unsigned long arg);
+static int el3_open(struct net_device *dev);
+static netdev_tx_t el3_start_xmit(struct sk_buff *skb,
+					struct net_device *dev);
+static irqreturn_t el3_interrupt(int irq, void *dev_id);
+static void update_stats(struct net_device *dev);
+static struct net_device_stats *el3_get_stats(struct net_device *dev);
+static int el3_rx(struct net_device *dev, int worklimit);
+static int el3_close(struct net_device *dev);
+static void el3_tx_timeout(struct net_device *dev);
+static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static void set_rx_mode(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+
+static void tc574_detach(struct pcmcia_device *p_dev);
+
+/*
+	tc574_attach() creates an "instance" of the driver, allocating
+	local data structures for one device.  The device is registered
+	with Card Services.
+*/
+static const struct net_device_ops el3_netdev_ops = {
+	.ndo_open 		= el3_open,
+	.ndo_stop 		= el3_close,
+	.ndo_start_xmit		= el3_start_xmit,
+	.ndo_tx_timeout 	= el3_tx_timeout,
+	.ndo_get_stats		= el3_get_stats,
+	.ndo_do_ioctl		= el3_ioctl,
+	.ndo_set_rx_mode	= set_multicast_list,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+static int tc574_probe(struct pcmcia_device *link)
+{
+	struct el3_private *lp;
+	struct net_device *dev;
+
+	dev_dbg(&link->dev, "3c574_attach()\n");
+
+	/* Create the PC card device object. */
+	dev = alloc_etherdev(sizeof(struct el3_private));
+	if (!dev)
+		return -ENOMEM;
+	lp = netdev_priv(dev);
+	link->priv = dev;
+	lp->p_dev = link;
+
+	spin_lock_init(&lp->window_lock);
+	link->resource[0]->end = 32;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
+	link->config_flags |= CONF_ENABLE_IRQ;
+	link->config_index = 1;
+
+	dev->netdev_ops = &el3_netdev_ops;
+	dev->watchdog_timeo = TX_TIMEOUT;
+
+	return tc574_config(link);
+}
+
+static void tc574_detach(struct pcmcia_device *link)
+{
+	struct net_device *dev = link->priv;
+
+	dev_dbg(&link->dev, "3c574_detach()\n");
+
+	unregister_netdev(dev);
+
+	tc574_release(link);
+
+	free_netdev(dev);
+} /* tc574_detach */
+
+static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
+
+static int tc574_config(struct pcmcia_device *link)
+{
+	struct net_device *dev = link->priv;
+	struct el3_private *lp = netdev_priv(dev);
+	int ret, i, j;
+	unsigned int ioaddr;
+	__be16 *phys_addr;
+	char *cardname;
+	__u32 config;
+	u8 *buf;
+	size_t len;
+
+	phys_addr = (__be16 *)dev->dev_addr;
+
+	dev_dbg(&link->dev, "3c574_config()\n");
+
+	link->io_lines = 16;
+
+	for (i = j = 0; j < 0x400; j += 0x20) {
+		link->resource[0]->start = j ^ 0x300;
+		i = pcmcia_request_io(link);
+		if (i == 0)
+			break;
+	}
+	if (i != 0)
+		goto failed;
+
+	ret = pcmcia_request_irq(link, el3_interrupt);
+	if (ret)
+		goto failed;
+
+	ret = pcmcia_enable_device(link);
+	if (ret)
+		goto failed;
+
+	dev->irq = link->irq;
+	dev->base_addr = link->resource[0]->start;
+
+	ioaddr = dev->base_addr;
+
+	/* The 3c574 normally uses an EEPROM for configuration info, including
+	   the hardware address.  The future products may include a modem chip
+	   and put the address in the CIS. */
+
+	len = pcmcia_get_tuple(link, 0x88, &buf);
+	if (buf && len >= 6) {
+		for (i = 0; i < 3; i++)
+			phys_addr[i] = htons(le16_to_cpu(buf[i * 2]));
+		kfree(buf);
+	} else {
+		kfree(buf); /* 0 < len < 6 */
+		EL3WINDOW(0);
+		for (i = 0; i < 3; i++)
+			phys_addr[i] = htons(read_eeprom(ioaddr, i + 10));
+		if (phys_addr[0] == htons(0x6060)) {
+			pr_notice("IO port conflict at 0x%03lx-0x%03lx\n",
+				  dev->base_addr, dev->base_addr+15);
+			goto failed;
+		}
+	}
+	if (link->prod_id[1])
+		cardname = link->prod_id[1];
+	else
+		cardname = "3Com 3c574";
+
+	{
+		u_char mcr;
+		outw(2<<11, ioaddr + RunnerRdCtrl);
+		mcr = inb(ioaddr + 2);
+		outw(0<<11, ioaddr + RunnerRdCtrl);
+		pr_info("  ASIC rev %d,", mcr>>3);
+		EL3WINDOW(3);
+		config = inl(ioaddr + Wn3_Config);
+		lp->default_media = (config & Xcvr) >> Xcvr_shift;
+		lp->autoselect = config & Autoselect ? 1 : 0;
+	}
+
+	init_timer(&lp->media);
+
+	{
+		int phy;
+		
+		/* Roadrunner only: Turn on the MII transceiver */
+		outw(0x8040, ioaddr + Wn3_Options);
+		mdelay(1);
+		outw(0xc040, ioaddr + Wn3_Options);
+		tc574_wait_for_completion(dev, TxReset);
+		tc574_wait_for_completion(dev, RxReset);
+		mdelay(1);
+		outw(0x8040, ioaddr + Wn3_Options);
+		
+		EL3WINDOW(4);
+		for (phy = 1; phy <= 32; phy++) {
+			int mii_status;
+			mdio_sync(ioaddr, 32);
+			mii_status = mdio_read(ioaddr, phy & 0x1f, 1);
+			if (mii_status != 0xffff) {
+				lp->phys = phy & 0x1f;
+				dev_dbg(&link->dev, "  MII transceiver at "
+					"index %d, status %x.\n",
+					  phy, mii_status);
+				if ((mii_status & 0x0040) == 0)
+					mii_preamble_required = 1;
+				break;
+			}
+		}
+		if (phy > 32) {
+			pr_notice("  No MII transceivers found!\n");
+			goto failed;
+		}
+		i = mdio_read(ioaddr, lp->phys, 16) | 0x40;
+		mdio_write(ioaddr, lp->phys, 16, i);
+		lp->advertising = mdio_read(ioaddr, lp->phys, 4);
+		if (full_duplex) {
+			/* Only advertise the FD media types. */
+			lp->advertising &= ~0x02a0;
+			mdio_write(ioaddr, lp->phys, 4, lp->advertising);
+		}
+	}
+
+	SET_NETDEV_DEV(dev, &link->dev);
+
+	if (register_netdev(dev) != 0) {
+		pr_notice("register_netdev() failed\n");
+		goto failed;
+	}
+
+	netdev_info(dev, "%s at io %#3lx, irq %d, hw_addr %pM\n",
+		    cardname, dev->base_addr, dev->irq, dev->dev_addr);
+	netdev_info(dev, " %dK FIFO split %s Rx:Tx, %sMII interface.\n",
+		    8 << config & Ram_size,
+		    ram_split[(config & Ram_split) >> Ram_split_shift],
+		    config & Autoselect ? "autoselect " : "");
+
+	return 0;
+
+failed:
+	tc574_release(link);
+	return -ENODEV;
+
+} /* tc574_config */
+
+static void tc574_release(struct pcmcia_device *link)
+{
+	pcmcia_disable_device(link);
+}
+
+static int tc574_suspend(struct pcmcia_device *link)
+{
+	struct net_device *dev = link->priv;
+
+	if (link->open)
+		netif_device_detach(dev);
+
+	return 0;
+}
+
+static int tc574_resume(struct pcmcia_device *link)
+{
+	struct net_device *dev = link->priv;
+
+	if (link->open) {
+		tc574_reset(dev);
+		netif_device_attach(dev);
+	}
+
+	return 0;
+}
+
+static void dump_status(struct net_device *dev)
+{
+	unsigned int ioaddr = dev->base_addr;
+	EL3WINDOW(1);
+	netdev_info(dev, "  irq status %04x, rx status %04x, tx status %02x, tx free %04x\n",
+		    inw(ioaddr+EL3_STATUS),
+		    inw(ioaddr+RxStatus), inb(ioaddr+TxStatus),
+		    inw(ioaddr+TxFree));
+	EL3WINDOW(4);
+	netdev_info(dev, "  diagnostics: fifo %04x net %04x ethernet %04x media %04x\n",
+		    inw(ioaddr+0x04), inw(ioaddr+0x06),
+		    inw(ioaddr+0x08), inw(ioaddr+0x0a));
+	EL3WINDOW(1);
+}
+
+/*
+  Use this for commands that may take time to finish
+*/
+static void tc574_wait_for_completion(struct net_device *dev, int cmd)
+{
+	int i = 1500;
+	outw(cmd, dev->base_addr + EL3_CMD);
+	while (--i > 0)
+		if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) break;
+	if (i == 0)
+		netdev_notice(dev, "command 0x%04x did not complete!\n", cmd);
+}
+
+/* Read a word from the EEPROM using the regular EEPROM access register.
+   Assume that we are in register window zero.
+ */
+static unsigned short read_eeprom(unsigned int ioaddr, int index)
+{
+	int timer;
+	outw(EEPROM_Read + index, ioaddr + Wn0EepromCmd);
+	/* Pause for at least 162 usec for the read to take place. */
+	for (timer = 1620; timer >= 0; timer--) {
+		if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0)
+			break;
+	}
+	return inw(ioaddr + Wn0EepromData);
+}
+
+/* MII transceiver control section.
+   Read and write the MII registers using software-generated serial
+   MDIO protocol.  See the MII specifications or DP83840A data sheet
+   for details.
+   The maxium data clock rate is 2.5 Mhz.  The timing is easily met by the
+   slow PC card interface. */
+
+#define MDIO_SHIFT_CLK	0x01
+#define MDIO_DIR_WRITE	0x04
+#define MDIO_DATA_WRITE0 (0x00 | MDIO_DIR_WRITE)
+#define MDIO_DATA_WRITE1 (0x02 | MDIO_DIR_WRITE)
+#define MDIO_DATA_READ	0x02
+#define MDIO_ENB_IN		0x00
+
+/* Generate the preamble required for initial synchronization and
+   a few older transceivers. */
+static void mdio_sync(unsigned int ioaddr, int bits)
+{
+	unsigned int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+
+	/* Establish sync by sending at least 32 logic ones. */
+	while (-- bits >= 0) {
+		outw(MDIO_DATA_WRITE1, mdio_addr);
+		outw(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+	}
+}
+
+static int mdio_read(unsigned int ioaddr, int phy_id, int location)
+{
+	int i;
+	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+	unsigned int retval = 0;
+	unsigned int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+
+	if (mii_preamble_required)
+		mdio_sync(ioaddr, 32);
+
+	/* Shift the read command bits out. */
+	for (i = 14; i >= 0; i--) {
+		int dataval = (read_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+		outw(dataval, mdio_addr);
+		outw(dataval | MDIO_SHIFT_CLK, mdio_addr);
+	}
+	/* Read the two transition, 16 data, and wire-idle bits. */
+	for (i = 19; i > 0; i--) {
+		outw(MDIO_ENB_IN, mdio_addr);
+		retval = (retval << 1) | ((inw(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
+		outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+	}
+	return (retval>>1) & 0xffff;
+}
+
+static void mdio_write(unsigned int ioaddr, int phy_id, int location, int value)
+{
+	int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
+	unsigned int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+	int i;
+
+	if (mii_preamble_required)
+		mdio_sync(ioaddr, 32);
+
+	/* Shift the command bits out. */
+	for (i = 31; i >= 0; i--) {
+		int dataval = (write_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+		outw(dataval, mdio_addr);
+		outw(dataval | MDIO_SHIFT_CLK, mdio_addr);
+	}
+	/* Leave the interface idle. */
+	for (i = 1; i >= 0; i--) {
+		outw(MDIO_ENB_IN, mdio_addr);
+		outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+	}
+}
+
+/* Reset and restore all of the 3c574 registers. */
+static void tc574_reset(struct net_device *dev)
+{
+	struct el3_private *lp = netdev_priv(dev);
+	int i;
+	unsigned int ioaddr = dev->base_addr;
+	unsigned long flags;
+
+	tc574_wait_for_completion(dev, TotalReset|0x10);
+
+	spin_lock_irqsave(&lp->window_lock, flags);
+	/* Clear any transactions in progress. */
+	outw(0, ioaddr + RunnerWrCtrl);
+	outw(0, ioaddr + RunnerRdCtrl);
+
+	/* Set the station address and mask. */
+	EL3WINDOW(2);
+	for (i = 0; i < 6; i++)
+		outb(dev->dev_addr[i], ioaddr + i);
+	for (; i < 12; i+=2)
+		outw(0, ioaddr + i);
+
+	/* Reset config options */
+	EL3WINDOW(3);
+	outb((dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl);
+	outl((lp->autoselect ? 0x01000000 : 0) | 0x0062001b,
+		 ioaddr + Wn3_Config);
+	/* Roadrunner only: Turn on the MII transceiver. */
+	outw(0x8040, ioaddr + Wn3_Options);
+	mdelay(1);
+	outw(0xc040, ioaddr + Wn3_Options);
+	EL3WINDOW(1);
+	spin_unlock_irqrestore(&lp->window_lock, flags);
+	
+	tc574_wait_for_completion(dev, TxReset);
+	tc574_wait_for_completion(dev, RxReset);
+	mdelay(1);
+	spin_lock_irqsave(&lp->window_lock, flags);
+	EL3WINDOW(3);
+	outw(0x8040, ioaddr + Wn3_Options);
+
+	/* Switch to the stats window, and clear all stats by reading. */
+	outw(StatsDisable, ioaddr + EL3_CMD);
+	EL3WINDOW(6);
+	for (i = 0; i < 10; i++)
+		inb(ioaddr + i);
+	inw(ioaddr + 10);
+	inw(ioaddr + 12);
+	EL3WINDOW(4);
+	inb(ioaddr + 12);
+	inb(ioaddr + 13);
+
+	/* .. enable any extra statistics bits.. */
+	outw(0x0040, ioaddr + Wn4_NetDiag);
+	
+	EL3WINDOW(1);
+	spin_unlock_irqrestore(&lp->window_lock, flags);
+	
+	/* .. re-sync MII and re-fill what NWay is advertising. */
+	mdio_sync(ioaddr, 32);
+	mdio_write(ioaddr, lp->phys, 4, lp->advertising);
+	if (!auto_polarity) {
+		/* works for TDK 78Q2120 series MII's */
+		i = mdio_read(ioaddr, lp->phys, 16) | 0x20;
+		mdio_write(ioaddr, lp->phys, 16, i);
+	}
+
+	spin_lock_irqsave(&lp->window_lock, flags);
+	/* Switch to register set 1 for normal use, just for TxFree. */
+	set_rx_mode(dev);
+	spin_unlock_irqrestore(&lp->window_lock, flags);
+	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
+	outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
+	outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
+	/* Allow status bits to be seen. */
+	outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
+	/* Ack all pending events, and set active indicator mask. */
+	outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
+		 ioaddr + EL3_CMD);
+	outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
+		 | AdapterFailure | RxEarly, ioaddr + EL3_CMD);
+}
+
+static int el3_open(struct net_device *dev)
+{
+	struct el3_private *lp = netdev_priv(dev);
+	struct pcmcia_device *link = lp->p_dev;
+
+	if (!pcmcia_dev_present(link))
+		return -ENODEV;
+	
+	link->open++;
+	netif_start_queue(dev);
+	
+	tc574_reset(dev);
+	lp->media.function = media_check;
+	lp->media.data = (unsigned long) dev;
+	lp->media.expires = jiffies + HZ;
+	add_timer(&lp->media);
+	
+	dev_dbg(&link->dev, "%s: opened, status %4.4x.\n",
+		  dev->name, inw(dev->base_addr + EL3_STATUS));
+	
+	return 0;
+}
+
+static void el3_tx_timeout(struct net_device *dev)
+{
+	unsigned int ioaddr = dev->base_addr;
+	
+	netdev_notice(dev, "Transmit timed out!\n");
+	dump_status(dev);
+	dev->stats.tx_errors++;
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	/* Issue TX_RESET and TX_START commands. */
+	tc574_wait_for_completion(dev, TxReset);
+	outw(TxEnable, ioaddr + EL3_CMD);
+	netif_wake_queue(dev);
+}
+
+static void pop_tx_status(struct net_device *dev)
+{
+	unsigned int ioaddr = dev->base_addr;
+	int i;
+    
+	/* Clear the Tx status stack. */
+	for (i = 32; i > 0; i--) {
+		u_char tx_status = inb(ioaddr + TxStatus);
+		if (!(tx_status & 0x84))
+			break;
+		/* reset transmitter on jabber error or underrun */
+		if (tx_status & 0x30)
+			tc574_wait_for_completion(dev, TxReset);
+		if (tx_status & 0x38) {
+			pr_debug("%s: transmit error: status 0x%02x\n",
+				  dev->name, tx_status);
+			outw(TxEnable, ioaddr + EL3_CMD);
+			dev->stats.tx_aborted_errors++;
+		}
+		outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */
+	}
+}
+
+static netdev_tx_t el3_start_xmit(struct sk_buff *skb,
+					struct net_device *dev)
+{
+	unsigned int ioaddr = dev->base_addr;
+	struct el3_private *lp = netdev_priv(dev);
+	unsigned long flags;
+
+	pr_debug("%s: el3_start_xmit(length = %ld) called, "
+		  "status %4.4x.\n", dev->name, (long)skb->len,
+		  inw(ioaddr + EL3_STATUS));
+
+	spin_lock_irqsave(&lp->window_lock, flags);
+
+	dev->stats.tx_bytes += skb->len;
+
+	/* Put out the doubleword header... */
+	outw(skb->len, ioaddr + TX_FIFO);
+	outw(0, ioaddr + TX_FIFO);
+	/* ... and the packet rounded to a doubleword. */
+	outsl(ioaddr + TX_FIFO, skb->data, (skb->len+3)>>2);
+
+	/* TxFree appears only in Window 1, not offset 0x1c. */
+	if (inw(ioaddr + TxFree) <= 1536) {
+		netif_stop_queue(dev);
+		/* Interrupt us when the FIFO has room for max-sized packet. 
+		   The threshold is in units of dwords. */
+		outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+	}
+
+	pop_tx_status(dev);
+	spin_unlock_irqrestore(&lp->window_lock, flags);
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+/* The EL3 interrupt handler. */
+static irqreturn_t el3_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct el3_private *lp = netdev_priv(dev);
+	unsigned int ioaddr;
+	unsigned status;
+	int work_budget = max_interrupt_work;
+	int handled = 0;
+
+	if (!netif_device_present(dev))
+		return IRQ_NONE;
+	ioaddr = dev->base_addr;
+
+	pr_debug("%s: interrupt, status %4.4x.\n",
+		  dev->name, inw(ioaddr + EL3_STATUS));
+
+	spin_lock(&lp->window_lock);
+	
+	while ((status = inw(ioaddr + EL3_STATUS)) &
+		   (IntLatch | RxComplete | RxEarly | StatsFull)) {
+		if (!netif_device_present(dev) ||
+			((status & 0xe000) != 0x2000)) {
+			pr_debug("%s: Interrupt from dead card\n", dev->name);
+			break;
+		}
+
+		handled = 1;
+
+		if (status & RxComplete)
+			work_budget = el3_rx(dev, work_budget);
+
+		if (status & TxAvailable) {
+			pr_debug("  TX room bit was handled.\n");
+			/* There's room in the FIFO for a full-sized packet. */
+			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
+			netif_wake_queue(dev);
+		}
+
+		if (status & TxComplete)
+			pop_tx_status(dev);
+
+		if (status & (AdapterFailure | RxEarly | StatsFull)) {
+			/* Handle all uncommon interrupts. */
+			if (status & StatsFull)
+				update_stats(dev);
+			if (status & RxEarly) {
+				work_budget = el3_rx(dev, work_budget);
+				outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
+			}
+			if (status & AdapterFailure) {
+				u16 fifo_diag;
+				EL3WINDOW(4);
+				fifo_diag = inw(ioaddr + Wn4_FIFODiag);
+				EL3WINDOW(1);
+				netdev_notice(dev, "adapter failure, FIFO diagnostic register %04x\n",
+					      fifo_diag);
+				if (fifo_diag & 0x0400) {
+					/* Tx overrun */
+					tc574_wait_for_completion(dev, TxReset);
+					outw(TxEnable, ioaddr + EL3_CMD);
+				}
+				if (fifo_diag & 0x2000) {
+					/* Rx underrun */
+					tc574_wait_for_completion(dev, RxReset);
+					set_rx_mode(dev);
+					outw(RxEnable, ioaddr + EL3_CMD);
+				}
+				outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
+			}
+		}
+
+		if (--work_budget < 0) {
+			pr_debug("%s: Too much work in interrupt, "
+				  "status %4.4x.\n", dev->name, status);
+			/* Clear all interrupts */
+			outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
+			break;
+		}
+		/* Acknowledge the IRQ. */
+		outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
+	}
+
+	pr_debug("%s: exiting interrupt, status %4.4x.\n",
+		  dev->name, inw(ioaddr + EL3_STATUS));
+		  
+	spin_unlock(&lp->window_lock);
+	return IRQ_RETVAL(handled);
+}
+
+/*
+    This timer serves two purposes: to check for missed interrupts
+	(and as a last resort, poll the NIC for events), and to monitor
+	the MII, reporting changes in cable status.
+*/
+static void media_check(unsigned long arg)
+{
+	struct net_device *dev = (struct net_device *) arg;
+	struct el3_private *lp = netdev_priv(dev);
+	unsigned int ioaddr = dev->base_addr;
+	unsigned long flags;
+	unsigned short /* cable, */ media, partner;
+
+	if (!netif_device_present(dev))
+		goto reschedule;
+	
+	/* Check for pending interrupt with expired latency timer: with
+	   this, we can limp along even if the interrupt is blocked */
+	if ((inw(ioaddr + EL3_STATUS) & IntLatch) && (inb(ioaddr + Timer) == 0xff)) {
+		if (!lp->fast_poll)
+			netdev_info(dev, "interrupt(s) dropped!\n");
+
+		local_irq_save(flags);
+		el3_interrupt(dev->irq, dev);
+		local_irq_restore(flags);
+
+		lp->fast_poll = HZ;
+	}
+	if (lp->fast_poll) {
+		lp->fast_poll--;
+		lp->media.expires = jiffies + 2*HZ/100;
+		add_timer(&lp->media);
+		return;
+	}
+
+	spin_lock_irqsave(&lp->window_lock, flags);
+	EL3WINDOW(4);
+	media = mdio_read(ioaddr, lp->phys, 1);
+	partner = mdio_read(ioaddr, lp->phys, 5);
+	EL3WINDOW(1);
+	
+	if (media != lp->media_status) {
+		if ((media ^ lp->media_status) & 0x0004)
+			netdev_info(dev, "%s link beat\n",
+				    (lp->media_status & 0x0004) ? "lost" : "found");
+		if ((media ^ lp->media_status) & 0x0020) {
+			lp->partner = 0;
+			if (lp->media_status & 0x0020) {
+				netdev_info(dev, "autonegotiation restarted\n");
+			} else if (partner) {
+				partner &= lp->advertising;
+				lp->partner = partner;
+				netdev_info(dev, "autonegotiation complete: "
+					    "%dbaseT-%cD selected\n",
+					    (partner & 0x0180) ? 100 : 10,
+					    (partner & 0x0140) ? 'F' : 'H');
+			} else {
+				netdev_info(dev, "link partner did not autonegotiate\n");
+			}
+
+			EL3WINDOW(3);
+			outb((partner & 0x0140 ? 0x20 : 0) |
+				 (dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl);
+			EL3WINDOW(1);
+
+		}
+		if (media & 0x0010)
+			netdev_info(dev, "remote fault detected\n");
+		if (media & 0x0002)
+			netdev_info(dev, "jabber detected\n");
+		lp->media_status = media;
+	}
+	spin_unlock_irqrestore(&lp->window_lock, flags);
+
+reschedule:
+	lp->media.expires = jiffies + HZ;
+	add_timer(&lp->media);
+}
+
+static struct net_device_stats *el3_get_stats(struct net_device *dev)
+{
+	struct el3_private *lp = netdev_priv(dev);
+
+	if (netif_device_present(dev)) {
+		unsigned long flags;
+		spin_lock_irqsave(&lp->window_lock, flags);
+		update_stats(dev);
+		spin_unlock_irqrestore(&lp->window_lock, flags);
+	}
+	return &dev->stats;
+}
+
+/*  Update statistics.
+	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)
+{
+	unsigned int ioaddr = dev->base_addr;
+	u8 rx, tx, up;
+
+	pr_debug("%s: updating the statistics.\n", dev->name);
+
+	if (inw(ioaddr+EL3_STATUS) == 0xffff) /* No card. */
+		return;
+		
+	/* Unlike the 3c509 we need not turn off stats updates while reading. */
+	/* Switch to the stats window, and read everything. */
+	EL3WINDOW(6);
+	dev->stats.tx_carrier_errors 		+= inb(ioaddr + 0);
+	dev->stats.tx_heartbeat_errors		+= inb(ioaddr + 1);
+	/* Multiple collisions. */	   	inb(ioaddr + 2);
+	dev->stats.collisions			+= inb(ioaddr + 3);
+	dev->stats.tx_window_errors		+= inb(ioaddr + 4);
+	dev->stats.rx_fifo_errors		+= inb(ioaddr + 5);
+	dev->stats.tx_packets			+= inb(ioaddr + 6);
+	up		 			 = inb(ioaddr + 9);
+	dev->stats.tx_packets			+= (up&0x30) << 4;
+	/* Rx packets   */			   inb(ioaddr + 7);
+	/* Tx deferrals */			   inb(ioaddr + 8);
+	rx		 			 = inw(ioaddr + 10);
+	tx					 = inw(ioaddr + 12);
+
+	EL3WINDOW(4);
+	/* BadSSD */				   inb(ioaddr + 12);
+	up					 = inb(ioaddr + 13);
+
+	EL3WINDOW(1);
+}
+
+static int el3_rx(struct net_device *dev, int worklimit)
+{
+	unsigned int ioaddr = dev->base_addr;
+	short rx_status;
+	
+	pr_debug("%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n",
+		  dev->name, inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
+	while (!((rx_status = inw(ioaddr + RxStatus)) & 0x8000) &&
+			worklimit > 0) {
+		worklimit--;
+		if (rx_status & 0x4000) { /* Error, update stats. */
+			short error = rx_status & 0x3800;
+			dev->stats.rx_errors++;
+			switch (error) {
+			case 0x0000:	dev->stats.rx_over_errors++; break;
+			case 0x0800:	dev->stats.rx_length_errors++; break;
+			case 0x1000:	dev->stats.rx_frame_errors++; break;
+			case 0x1800:	dev->stats.rx_length_errors++; break;
+			case 0x2000:	dev->stats.rx_frame_errors++; break;
+			case 0x2800:	dev->stats.rx_crc_errors++; break;
+			}
+		} else {
+			short pkt_len = rx_status & 0x7ff;
+			struct sk_buff *skb;
+
+			skb = dev_alloc_skb(pkt_len+5);
+
+			pr_debug("  Receiving packet size %d status %4.4x.\n",
+				  pkt_len, rx_status);
+			if (skb != NULL) {
+				skb_reserve(skb, 2);
+				insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len),
+						((pkt_len+3)>>2));
+				skb->protocol = eth_type_trans(skb, dev);
+				netif_rx(skb);
+				dev->stats.rx_packets++;
+				dev->stats.rx_bytes += pkt_len;
+			} else {
+				pr_debug("%s: couldn't allocate a sk_buff of"
+					  " size %d.\n", dev->name, pkt_len);
+				dev->stats.rx_dropped++;
+			}
+		}
+		tc574_wait_for_completion(dev, RxDiscard);
+	}
+
+	return worklimit;
+}
+
+/* Provide ioctl() calls to examine the MII xcvr state. */
+static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct el3_private *lp = netdev_priv(dev);
+	unsigned int ioaddr = dev->base_addr;
+	struct mii_ioctl_data *data = if_mii(rq);
+	int phy = lp->phys & 0x1f;
+
+	pr_debug("%s: In ioct(%-.6s, %#4.4x) %4.4x %4.4x %4.4x %4.4x.\n",
+		  dev->name, rq->ifr_ifrn.ifrn_name, cmd,
+		  data->phy_id, data->reg_num, data->val_in, data->val_out);
+
+	switch(cmd) {
+	case SIOCGMIIPHY:		/* Get the address of the PHY in use. */
+		data->phy_id = phy;
+	case SIOCGMIIREG:		/* Read the specified MII register. */
+		{
+			int saved_window;
+			unsigned long flags;
+
+			spin_lock_irqsave(&lp->window_lock, flags);
+			saved_window = inw(ioaddr + EL3_CMD) >> 13;
+			EL3WINDOW(4);
+			data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f,
+						  data->reg_num & 0x1f);
+			EL3WINDOW(saved_window);
+			spin_unlock_irqrestore(&lp->window_lock, flags);
+			return 0;
+		}
+	case SIOCSMIIREG:		/* Write the specified MII register */
+		{
+			int saved_window;
+                       unsigned long flags;
+
+			spin_lock_irqsave(&lp->window_lock, flags);
+			saved_window = inw(ioaddr + EL3_CMD) >> 13;
+			EL3WINDOW(4);
+			mdio_write(ioaddr, data->phy_id & 0x1f,
+				   data->reg_num & 0x1f, data->val_in);
+			EL3WINDOW(saved_window);
+			spin_unlock_irqrestore(&lp->window_lock, flags);
+			return 0;
+		}
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+/* The Odie chip has a 64 bin multicast filter, but the bit layout is not
+   documented.  Until it is we revert to receiving all multicast frames when
+   any multicast reception is desired.
+   Note: My other drivers emit a log message whenever promiscuous mode is
+   entered to help detect password sniffers.  This is less desirable on
+   typical PC card machines, so we omit the message.
+   */
+
+static void set_rx_mode(struct net_device *dev)
+{
+	unsigned int ioaddr = dev->base_addr;
+
+	if (dev->flags & IFF_PROMISC)
+		outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
+			 ioaddr + EL3_CMD);
+	else if (!netdev_mc_empty(dev) || (dev->flags & IFF_ALLMULTI))
+		outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
+	else
+		outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
+}
+
+static void set_multicast_list(struct net_device *dev)
+{
+	struct el3_private *lp = netdev_priv(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&lp->window_lock, flags);
+	set_rx_mode(dev);
+	spin_unlock_irqrestore(&lp->window_lock, flags);
+}
+
+static int el3_close(struct net_device *dev)
+{
+	unsigned int ioaddr = dev->base_addr;
+	struct el3_private *lp = netdev_priv(dev);
+	struct pcmcia_device *link = lp->p_dev;
+
+	dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name);
+	
+	if (pcmcia_dev_present(link)) {
+		unsigned long flags;
+
+		/* Turn off statistics ASAP.  We update lp->stats below. */
+		outw(StatsDisable, ioaddr + EL3_CMD);
+		
+		/* Disable the receiver and transmitter. */
+		outw(RxDisable, ioaddr + EL3_CMD);
+		outw(TxDisable, ioaddr + EL3_CMD);
+		
+		/* Note: Switching to window 0 may disable the IRQ. */
+		EL3WINDOW(0);
+		spin_lock_irqsave(&lp->window_lock, flags);
+		update_stats(dev);
+		spin_unlock_irqrestore(&lp->window_lock, flags);
+
+		/* force interrupts off */
+		outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
+	}
+
+	link->open--;
+	netif_stop_queue(dev);
+	del_timer_sync(&lp->media);
+
+	return 0;
+}
+
+static const struct pcmcia_device_id tc574_ids[] = {
+	PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0574),
+	PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
+	PCMCIA_DEVICE_NULL,
+};
+MODULE_DEVICE_TABLE(pcmcia, tc574_ids);
+
+static struct pcmcia_driver tc574_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "3c574_cs",
+	.probe		= tc574_probe,
+	.remove		= tc574_detach,
+	.id_table       = tc574_ids,
+	.suspend	= tc574_suspend,
+	.resume		= tc574_resume,
+};
+
+static int __init init_tc574(void)
+{
+	return pcmcia_register_driver(&tc574_driver);
+}
+
+static void __exit exit_tc574(void)
+{
+	pcmcia_unregister_driver(&tc574_driver);
+}
+
+module_init(init_tc574);
+module_exit(exit_tc574);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/3com/3c589_cs.c linux-libre-3.2-gnu/drivers/net/ethernet/3com/3c589_cs.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/3com/3c589_cs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/3com/3c589_cs.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,943 @@
+/*======================================================================
+
+    A PCMCIA ethernet driver for the 3com 3c589 card.
+
+    Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
+
+    3c589_cs.c 1.162 2001/10/13 00:08:50
+
+    The network driver code is based on Donald Becker's 3c589 code:
+
+    Written 1994 by Donald Becker.
+    Copyright 1993 United States Government as represented by the
+    Director, National Security Agency.  This software may be used and
+    distributed according to the terms of the GNU General Public License,
+    incorporated herein by reference.
+    Donald Becker may be reached at becker@scyld.com
+
+    Updated for 2.5.x by Alan Cox <alan@lxorguk.ukuu.org.uk>
+
+======================================================================*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define DRV_NAME	"3c589_cs"
+#define DRV_VERSION	"1.162-ac"
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+#include <linux/bitops.h>
+#include <linux/jiffies.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ciscode.h>
+#include <pcmcia/ds.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+/* To minimize the size of the driver source I only define operating
+   constants if they are used several times.  You'll need the manual
+   if you want to understand driver details. */
+/* Offsets from base I/O address. */
+#define EL3_DATA	0x00
+#define EL3_TIMER	0x0a
+#define EL3_CMD		0x0e
+#define EL3_STATUS	0x0e
+
+#define EEPROM_READ	0x0080
+#define EEPROM_BUSY	0x8000
+
+#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
+
+/* The top five bits written to EL3_CMD are a command, the lower
+   11 bits are the parameter, if applicable. */
+enum c509cmd {
+	TotalReset	= 0<<11,
+	SelectWindow	= 1<<11,
+	StartCoax	= 2<<11,
+	RxDisable	= 3<<11,
+	RxEnable	= 4<<11,
+	RxReset		= 5<<11,
+	RxDiscard	= 8<<11,
+	TxEnable	= 9<<11,
+	TxDisable	= 10<<11,
+	TxReset		= 11<<11,
+	FakeIntr	= 12<<11,
+	AckIntr		= 13<<11,
+	SetIntrEnb	= 14<<11,
+	SetStatusEnb	= 15<<11,
+	SetRxFilter	= 16<<11,
+	SetRxThreshold	= 17<<11,
+	SetTxThreshold	= 18<<11,
+	SetTxStart	= 19<<11,
+	StatsEnable	= 21<<11,
+	StatsDisable	= 22<<11,
+	StopCoax	= 23<<11
+};
+
+enum c509status {
+	IntLatch	= 0x0001,
+	AdapterFailure	= 0x0002,
+	TxComplete	= 0x0004,
+	TxAvailable	= 0x0008,
+	RxComplete	= 0x0010,
+	RxEarly		= 0x0020,
+	IntReq		= 0x0040,
+	StatsFull	= 0x0080,
+	CmdBusy		= 0x1000
+};
+
+/* The SetRxFilter command accepts the following classes: */
+enum RxFilter {
+	RxStation	= 1,
+	RxMulticast	= 2,
+	RxBroadcast	= 4,
+	RxProm		= 8
+};
+
+/* Register window 1 offsets, the window used in normal operation. */
+#define TX_FIFO		0x00
+#define RX_FIFO		0x00
+#define RX_STATUS	0x08
+#define TX_STATUS	0x0B
+#define TX_FREE		0x0C	/* Remaining free bytes in Tx buffer. */
+
+#define WN0_IRQ		0x08	/* Window 0: Set IRQ line in bits 12-15. */
+#define WN4_MEDIA	0x0A	/* Window 4: Various transcvr/media bits. */
+#define MEDIA_TP	0x00C0	/* Enable link beat and jabber for 10baseT. */
+#define MEDIA_LED	0x0001	/* Enable link light on 3C589E cards. */
+
+/* Time in jiffies before concluding Tx hung */
+#define TX_TIMEOUT	((400*HZ)/1000)
+
+struct el3_private {
+	struct pcmcia_device	*p_dev;
+	/* For transceiver monitoring */
+	struct timer_list	media;
+	u16			media_status;
+	u16			fast_poll;
+	unsigned long		last_irq;
+	spinlock_t		lock;
+};
+
+static const char *if_names[] = { "auto", "10baseT", "10base2", "AUI" };
+
+/*====================================================================*/
+
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
+MODULE_DESCRIPTION("3Com 3c589 series PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");
+
+#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
+
+/* Special hook for setting if_port when module is loaded */
+INT_MODULE_PARM(if_port, 0);
+
+
+/*====================================================================*/
+
+static int tc589_config(struct pcmcia_device *link);
+static void tc589_release(struct pcmcia_device *link);
+
+static u16 read_eeprom(unsigned int ioaddr, int index);
+static void tc589_reset(struct net_device *dev);
+static void media_check(unsigned long arg);
+static int el3_config(struct net_device *dev, struct ifmap *map);
+static int el3_open(struct net_device *dev);
+static netdev_tx_t el3_start_xmit(struct sk_buff *skb,
+					struct net_device *dev);
+static irqreturn_t el3_interrupt(int irq, void *dev_id);
+static void update_stats(struct net_device *dev);
+static struct net_device_stats *el3_get_stats(struct net_device *dev);
+static int el3_rx(struct net_device *dev);
+static int el3_close(struct net_device *dev);
+static void el3_tx_timeout(struct net_device *dev);
+static void set_rx_mode(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+static const struct ethtool_ops netdev_ethtool_ops;
+
+static void tc589_detach(struct pcmcia_device *p_dev);
+
+static const struct net_device_ops el3_netdev_ops = {
+	.ndo_open		= el3_open,
+	.ndo_stop		= el3_close,
+	.ndo_start_xmit		= el3_start_xmit,
+	.ndo_tx_timeout		= el3_tx_timeout,
+	.ndo_set_config		= el3_config,
+	.ndo_get_stats		= el3_get_stats,
+	.ndo_set_rx_mode	= set_multicast_list,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+static int tc589_probe(struct pcmcia_device *link)
+{
+    struct el3_private *lp;
+    struct net_device *dev;
+
+    dev_dbg(&link->dev, "3c589_attach()\n");
+
+    /* Create new ethernet device */
+    dev = alloc_etherdev(sizeof(struct el3_private));
+    if (!dev)
+	 return -ENOMEM;
+    lp = netdev_priv(dev);
+    link->priv = dev;
+    lp->p_dev = link;
+
+    spin_lock_init(&lp->lock);
+    link->resource[0]->end = 16;
+    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
+
+    link->config_flags |= CONF_ENABLE_IRQ;
+    link->config_index = 1;
+
+    dev->netdev_ops = &el3_netdev_ops;
+    dev->watchdog_timeo = TX_TIMEOUT;
+
+    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+
+    return tc589_config(link);
+}
+
+static void tc589_detach(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+
+    dev_dbg(&link->dev, "3c589_detach\n");
+
+    unregister_netdev(dev);
+
+    tc589_release(link);
+
+    free_netdev(dev);
+} /* tc589_detach */
+
+static int tc589_config(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    __be16 *phys_addr;
+    int ret, i, j, multi = 0, fifo;
+    unsigned int ioaddr;
+    static const char * const ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
+    u8 *buf;
+    size_t len;
+
+    dev_dbg(&link->dev, "3c589_config\n");
+
+    phys_addr = (__be16 *)dev->dev_addr;
+    /* Is this a 3c562? */
+    if (link->manf_id != MANFID_3COM)
+	    dev_info(&link->dev, "hmmm, is this really a 3Com card??\n");
+    multi = (link->card_id == PRODID_3COM_3C562);
+
+    link->io_lines = 16;
+
+    /* For the 3c562, the base address must be xx00-xx7f */
+    for (i = j = 0; j < 0x400; j += 0x10) {
+	if (multi && (j & 0x80)) continue;
+	link->resource[0]->start = j ^ 0x300;
+	i = pcmcia_request_io(link);
+	if (i == 0)
+		break;
+    }
+    if (i != 0)
+	goto failed;
+
+    ret = pcmcia_request_irq(link, el3_interrupt);
+    if (ret)
+	    goto failed;
+
+    ret = pcmcia_enable_device(link);
+    if (ret)
+	    goto failed;
+
+    dev->irq = link->irq;
+    dev->base_addr = link->resource[0]->start;
+    ioaddr = dev->base_addr;
+    EL3WINDOW(0);
+
+    /* The 3c589 has an extra EEPROM for configuration info, including
+       the hardware address.  The 3c562 puts the address in the CIS. */
+    len = pcmcia_get_tuple(link, 0x88, &buf);
+    if (buf && len >= 6) {
+	    for (i = 0; i < 3; i++)
+		    phys_addr[i] = htons(le16_to_cpu(buf[i*2]));
+	    kfree(buf);
+    } else {
+	kfree(buf); /* 0 < len < 6 */
+	for (i = 0; i < 3; i++)
+	    phys_addr[i] = htons(read_eeprom(ioaddr, i));
+	if (phys_addr[0] == htons(0x6060)) {
+	    dev_err(&link->dev, "IO port conflict at 0x%03lx-0x%03lx\n",
+		    dev->base_addr, dev->base_addr+15);
+	    goto failed;
+	}
+    }
+
+    /* The address and resource configuration register aren't loaded from
+       the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */
+    outw(0x3f00, ioaddr + 8);
+    fifo = inl(ioaddr);
+
+    /* The if_port symbol can be set when the module is loaded */
+    if ((if_port >= 0) && (if_port <= 3))
+	dev->if_port = if_port;
+    else
+	dev_err(&link->dev, "invalid if_port requested\n");
+
+    SET_NETDEV_DEV(dev, &link->dev);
+
+    if (register_netdev(dev) != 0) {
+	    dev_err(&link->dev, "register_netdev() failed\n");
+	goto failed;
+    }
+
+    netdev_info(dev, "3Com 3c%s, io %#3lx, irq %d, hw_addr %pM\n",
+		(multi ? "562" : "589"), dev->base_addr, dev->irq,
+		dev->dev_addr);
+    netdev_info(dev, "  %dK FIFO split %s Rx:Tx, %s xcvr\n",
+		(fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3],
+		if_names[dev->if_port]);
+    return 0;
+
+failed:
+    tc589_release(link);
+    return -ENODEV;
+} /* tc589_config */
+
+static void tc589_release(struct pcmcia_device *link)
+{
+	pcmcia_disable_device(link);
+}
+
+static int tc589_suspend(struct pcmcia_device *link)
+{
+	struct net_device *dev = link->priv;
+
+	if (link->open)
+		netif_device_detach(dev);
+
+	return 0;
+}
+
+static int tc589_resume(struct pcmcia_device *link)
+{
+	struct net_device *dev = link->priv;
+
+	if (link->open) {
+		tc589_reset(dev);
+		netif_device_attach(dev);
+	}
+
+	return 0;
+}
+
+/*====================================================================*/
+
+/*
+  Use this for commands that may take time to finish
+*/
+static void tc589_wait_for_completion(struct net_device *dev, int cmd)
+{
+    int i = 100;
+    outw(cmd, dev->base_addr + EL3_CMD);
+    while (--i > 0)
+	if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) break;
+    if (i == 0)
+	netdev_warn(dev, "command 0x%04x did not complete!\n", cmd);
+}
+
+/*
+  Read a word from the EEPROM using the regular EEPROM access register.
+  Assume that we are in register window zero.
+*/
+static u16 read_eeprom(unsigned int ioaddr, int index)
+{
+    int i;
+    outw(EEPROM_READ + index, ioaddr + 10);
+    /* Reading the eeprom takes 162 us */
+    for (i = 1620; i >= 0; i--)
+	if ((inw(ioaddr + 10) & EEPROM_BUSY) == 0)
+	    break;
+    return inw(ioaddr + 12);
+}
+
+/*
+  Set transceiver type, perhaps to something other than what the user
+  specified in dev->if_port.
+*/
+static void tc589_set_xcvr(struct net_device *dev, int if_port)
+{
+    struct el3_private *lp = netdev_priv(dev);
+    unsigned int ioaddr = dev->base_addr;
+
+    EL3WINDOW(0);
+    switch (if_port) {
+    case 0: case 1: outw(0, ioaddr + 6); break;
+    case 2: outw(3<<14, ioaddr + 6); break;
+    case 3: outw(1<<14, ioaddr + 6); break;
+    }
+    /* On PCMCIA, this just turns on the LED */
+    outw((if_port == 2) ? StartCoax : StopCoax, ioaddr + EL3_CMD);
+    /* 10baseT interface, enable link beat and jabber check. */
+    EL3WINDOW(4);
+    outw(MEDIA_LED | ((if_port < 2) ? MEDIA_TP : 0), ioaddr + WN4_MEDIA);
+    EL3WINDOW(1);
+    if (if_port == 2)
+	lp->media_status = ((dev->if_port == 0) ? 0x8000 : 0x4000);
+    else
+	lp->media_status = ((dev->if_port == 0) ? 0x4010 : 0x8800);
+}
+
+static void dump_status(struct net_device *dev)
+{
+    unsigned int ioaddr = dev->base_addr;
+    EL3WINDOW(1);
+    netdev_info(dev, "  irq status %04x, rx status %04x, tx status %02x  tx free %04x\n",
+		inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS),
+		inb(ioaddr+TX_STATUS), inw(ioaddr+TX_FREE));
+    EL3WINDOW(4);
+    netdev_info(dev, "  diagnostics: fifo %04x net %04x ethernet %04x media %04x\n",
+		inw(ioaddr+0x04), inw(ioaddr+0x06), inw(ioaddr+0x08),
+		inw(ioaddr+0x0a));
+    EL3WINDOW(1);
+}
+
+/* Reset and restore all of the 3c589 registers. */
+static void tc589_reset(struct net_device *dev)
+{
+    unsigned int ioaddr = dev->base_addr;
+    int i;
+
+    EL3WINDOW(0);
+    outw(0x0001, ioaddr + 4);			/* Activate board. */
+    outw(0x3f00, ioaddr + 8);			/* Set the IRQ line. */
+
+    /* Set the station address in window 2. */
+    EL3WINDOW(2);
+    for (i = 0; i < 6; i++)
+	outb(dev->dev_addr[i], ioaddr + i);
+
+    tc589_set_xcvr(dev, dev->if_port);
+
+    /* Switch to the stats window, and clear all stats by reading. */
+    outw(StatsDisable, ioaddr + EL3_CMD);
+    EL3WINDOW(6);
+    for (i = 0; i < 9; i++)
+	inb(ioaddr+i);
+    inw(ioaddr + 10);
+    inw(ioaddr + 12);
+
+    /* Switch to register set 1 for normal use. */
+    EL3WINDOW(1);
+
+    set_rx_mode(dev);
+    outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
+    outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
+    outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
+    /* Allow status bits to be seen. */
+    outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
+    /* Ack all pending events, and set active indicator mask. */
+    outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
+	 ioaddr + EL3_CMD);
+    outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
+	 | AdapterFailure, ioaddr + EL3_CMD);
+}
+
+static void netdev_get_drvinfo(struct net_device *dev,
+			       struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	sprintf(info->bus_info, "PCMCIA 0x%lx", dev->base_addr);
+}
+
+static const struct ethtool_ops netdev_ethtool_ops = {
+	.get_drvinfo		= netdev_get_drvinfo,
+};
+
+static int el3_config(struct net_device *dev, struct ifmap *map)
+{
+    if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
+	if (map->port <= 3) {
+	    dev->if_port = map->port;
+	    netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]);
+	    tc589_set_xcvr(dev, dev->if_port);
+	} else
+	    return -EINVAL;
+    }
+    return 0;
+}
+
+static int el3_open(struct net_device *dev)
+{
+    struct el3_private *lp = netdev_priv(dev);
+    struct pcmcia_device *link = lp->p_dev;
+
+    if (!pcmcia_dev_present(link))
+	return -ENODEV;
+
+    link->open++;
+    netif_start_queue(dev);
+
+    tc589_reset(dev);
+    init_timer(&lp->media);
+    lp->media.function = media_check;
+    lp->media.data = (unsigned long) dev;
+    lp->media.expires = jiffies + HZ;
+    add_timer(&lp->media);
+
+    dev_dbg(&link->dev, "%s: opened, status %4.4x.\n",
+	  dev->name, inw(dev->base_addr + EL3_STATUS));
+
+    return 0;
+}
+
+static void el3_tx_timeout(struct net_device *dev)
+{
+    unsigned int ioaddr = dev->base_addr;
+
+    netdev_warn(dev, "Transmit timed out!\n");
+    dump_status(dev);
+    dev->stats.tx_errors++;
+    dev->trans_start = jiffies; /* prevent tx timeout */
+    /* Issue TX_RESET and TX_START commands. */
+    tc589_wait_for_completion(dev, TxReset);
+    outw(TxEnable, ioaddr + EL3_CMD);
+    netif_wake_queue(dev);
+}
+
+static void pop_tx_status(struct net_device *dev)
+{
+    unsigned int ioaddr = dev->base_addr;
+    int i;
+
+    /* Clear the Tx status stack. */
+    for (i = 32; i > 0; i--) {
+	u_char tx_status = inb(ioaddr + TX_STATUS);
+	if (!(tx_status & 0x84)) break;
+	/* reset transmitter on jabber error or underrun */
+	if (tx_status & 0x30)
+		tc589_wait_for_completion(dev, TxReset);
+	if (tx_status & 0x38) {
+		netdev_dbg(dev, "transmit error: status 0x%02x\n", tx_status);
+		outw(TxEnable, ioaddr + EL3_CMD);
+		dev->stats.tx_aborted_errors++;
+	}
+	outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
+    }
+}
+
+static netdev_tx_t el3_start_xmit(struct sk_buff *skb,
+					struct net_device *dev)
+{
+    unsigned int ioaddr = dev->base_addr;
+    struct el3_private *priv = netdev_priv(dev);
+    unsigned long flags;
+
+    netdev_dbg(dev, "el3_start_xmit(length = %ld) called, status %4.4x.\n",
+	       (long)skb->len, inw(ioaddr + EL3_STATUS));
+
+    spin_lock_irqsave(&priv->lock, flags);
+
+    dev->stats.tx_bytes += skb->len;
+
+    /* Put out the doubleword header... */
+    outw(skb->len, ioaddr + TX_FIFO);
+    outw(0x00, ioaddr + TX_FIFO);
+    /* ... and the packet rounded to a doubleword. */
+    outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+
+    if (inw(ioaddr + TX_FREE) <= 1536) {
+	netif_stop_queue(dev);
+	/* Interrupt us when the FIFO has room for max-sized packet. */
+	outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
+    }
+
+    pop_tx_status(dev);
+    spin_unlock_irqrestore(&priv->lock, flags);
+    dev_kfree_skb(skb);
+
+    return NETDEV_TX_OK;
+}
+
+/* The EL3 interrupt handler. */
+static irqreturn_t el3_interrupt(int irq, void *dev_id)
+{
+    struct net_device *dev = (struct net_device *) dev_id;
+    struct el3_private *lp = netdev_priv(dev);
+    unsigned int ioaddr;
+    __u16 status;
+    int i = 0, handled = 1;
+
+    if (!netif_device_present(dev))
+	return IRQ_NONE;
+
+    ioaddr = dev->base_addr;
+
+    netdev_dbg(dev, "interrupt, status %4.4x.\n", inw(ioaddr + EL3_STATUS));
+
+    spin_lock(&lp->lock);
+    while ((status = inw(ioaddr + EL3_STATUS)) &
+	(IntLatch | RxComplete | StatsFull)) {
+	if ((status & 0xe000) != 0x2000) {
+		netdev_dbg(dev, "interrupt from dead card\n");
+		handled = 0;
+		break;
+	}
+	if (status & RxComplete)
+		el3_rx(dev);
+	if (status & TxAvailable) {
+		netdev_dbg(dev, "    TX room bit was handled.\n");
+		/* There's room in the FIFO for a full-sized packet. */
+		outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
+		netif_wake_queue(dev);
+	}
+	if (status & TxComplete)
+		pop_tx_status(dev);
+	if (status & (AdapterFailure | RxEarly | StatsFull)) {
+	    /* Handle all uncommon interrupts. */
+	    if (status & StatsFull)		/* Empty statistics. */
+		update_stats(dev);
+	    if (status & RxEarly) {		/* Rx early is unused. */
+		el3_rx(dev);
+		outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
+	    }
+	    if (status & AdapterFailure) {
+		u16 fifo_diag;
+		EL3WINDOW(4);
+		fifo_diag = inw(ioaddr + 4);
+		EL3WINDOW(1);
+		netdev_warn(dev, "adapter failure, FIFO diagnostic register %04x.\n",
+			    fifo_diag);
+		if (fifo_diag & 0x0400) {
+		    /* Tx overrun */
+		    tc589_wait_for_completion(dev, TxReset);
+		    outw(TxEnable, ioaddr + EL3_CMD);
+		}
+		if (fifo_diag & 0x2000) {
+		    /* Rx underrun */
+		    tc589_wait_for_completion(dev, RxReset);
+		    set_rx_mode(dev);
+		    outw(RxEnable, ioaddr + EL3_CMD);
+		}
+		outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
+	    }
+	}
+	if (++i > 10) {
+		netdev_err(dev, "infinite loop in interrupt, status %4.4x.\n",
+			   status);
+		/* Clear all interrupts */
+		outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
+		break;
+	}
+	/* Acknowledge the IRQ. */
+	outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
+    }
+    lp->last_irq = jiffies;
+    spin_unlock(&lp->lock);
+    netdev_dbg(dev, "exiting interrupt, status %4.4x.\n",
+	       inw(ioaddr + EL3_STATUS));
+    return IRQ_RETVAL(handled);
+}
+
+static void media_check(unsigned long arg)
+{
+    struct net_device *dev = (struct net_device *)(arg);
+    struct el3_private *lp = netdev_priv(dev);
+    unsigned int ioaddr = dev->base_addr;
+    u16 media, errs;
+    unsigned long flags;
+
+    if (!netif_device_present(dev)) goto reschedule;
+
+    /* Check for pending interrupt with expired latency timer: with
+       this, we can limp along even if the interrupt is blocked */
+    if ((inw(ioaddr + EL3_STATUS) & IntLatch) &&
+	(inb(ioaddr + EL3_TIMER) == 0xff)) {
+	if (!lp->fast_poll)
+		netdev_warn(dev, "interrupt(s) dropped!\n");
+
+	local_irq_save(flags);
+	el3_interrupt(dev->irq, dev);
+	local_irq_restore(flags);
+
+	lp->fast_poll = HZ;
+    }
+    if (lp->fast_poll) {
+	lp->fast_poll--;
+	lp->media.expires = jiffies + HZ/100;
+	add_timer(&lp->media);
+	return;
+    }
+
+    /* lp->lock guards the EL3 window. Window should always be 1 except
+       when the lock is held */
+    spin_lock_irqsave(&lp->lock, flags);
+    EL3WINDOW(4);
+    media = inw(ioaddr+WN4_MEDIA) & 0xc810;
+
+    /* Ignore collisions unless we've had no irq's recently */
+    if (time_before(jiffies, lp->last_irq + HZ)) {
+	media &= ~0x0010;
+    } else {
+	/* Try harder to detect carrier errors */
+	EL3WINDOW(6);
+	outw(StatsDisable, ioaddr + EL3_CMD);
+	errs = inb(ioaddr + 0);
+	outw(StatsEnable, ioaddr + EL3_CMD);
+	dev->stats.tx_carrier_errors += errs;
+	if (errs || (lp->media_status & 0x0010)) media |= 0x0010;
+    }
+
+    if (media != lp->media_status) {
+	if ((media & lp->media_status & 0x8000) &&
+	    ((lp->media_status ^ media) & 0x0800))
+		netdev_info(dev, "%s link beat\n",
+			    (lp->media_status & 0x0800 ? "lost" : "found"));
+	else if ((media & lp->media_status & 0x4000) &&
+		 ((lp->media_status ^ media) & 0x0010))
+		netdev_info(dev, "coax cable %s\n",
+			    (lp->media_status & 0x0010 ? "ok" : "problem"));
+	if (dev->if_port == 0) {
+	    if (media & 0x8000) {
+		if (media & 0x0800)
+			netdev_info(dev, "flipped to 10baseT\n");
+		else
+			tc589_set_xcvr(dev, 2);
+	    } else if (media & 0x4000) {
+		if (media & 0x0010)
+		    tc589_set_xcvr(dev, 1);
+		else
+		    netdev_info(dev, "flipped to 10base2\n");
+	    }
+	}
+	lp->media_status = media;
+    }
+
+    EL3WINDOW(1);
+    spin_unlock_irqrestore(&lp->lock, flags);
+
+reschedule:
+    lp->media.expires = jiffies + HZ;
+    add_timer(&lp->media);
+}
+
+static struct net_device_stats *el3_get_stats(struct net_device *dev)
+{
+    struct el3_private *lp = netdev_priv(dev);
+    unsigned long flags;
+    struct pcmcia_device *link = lp->p_dev;
+
+    if (pcmcia_dev_present(link)) {
+	spin_lock_irqsave(&lp->lock, flags);
+	update_stats(dev);
+	spin_unlock_irqrestore(&lp->lock, flags);
+    }
+    return &dev->stats;
+}
+
+/*
+  Update statistics.  We change to register window 6, so this should be run
+  single-threaded if the device is active. This is expected to be a rare
+  operation, and it's simpler for the rest of the driver to assume that
+  window 1 is always valid rather than use a special window-state variable.
+
+  Caller must hold the lock for this
+*/
+static void update_stats(struct net_device *dev)
+{
+    unsigned int ioaddr = dev->base_addr;
+
+    netdev_dbg(dev, "updating the statistics.\n");
+    /* Turn off statistics updates while reading. */
+    outw(StatsDisable, ioaddr + EL3_CMD);
+    /* Switch to the stats window, and read everything. */
+    EL3WINDOW(6);
+    dev->stats.tx_carrier_errors	+= inb(ioaddr + 0);
+    dev->stats.tx_heartbeat_errors	+= inb(ioaddr + 1);
+    /* Multiple collisions. */		inb(ioaddr + 2);
+    dev->stats.collisions		+= inb(ioaddr + 3);
+    dev->stats.tx_window_errors		+= inb(ioaddr + 4);
+    dev->stats.rx_fifo_errors		+= inb(ioaddr + 5);
+    dev->stats.tx_packets		+= inb(ioaddr + 6);
+    /* Rx packets   */			inb(ioaddr + 7);
+    /* Tx deferrals */			inb(ioaddr + 8);
+    /* Rx octets */			inw(ioaddr + 10);
+    /* Tx octets */			inw(ioaddr + 12);
+
+    /* Back to window 1, and turn statistics back on. */
+    EL3WINDOW(1);
+    outw(StatsEnable, ioaddr + EL3_CMD);
+}
+
+static int el3_rx(struct net_device *dev)
+{
+    unsigned int ioaddr = dev->base_addr;
+    int worklimit = 32;
+    short rx_status;
+
+    netdev_dbg(dev, "in rx_packet(), status %4.4x, rx_status %4.4x.\n",
+	       inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
+    while (!((rx_status = inw(ioaddr + RX_STATUS)) & 0x8000) &&
+		    worklimit > 0) {
+	worklimit--;
+	if (rx_status & 0x4000) { /* Error, update stats. */
+	    short error = rx_status & 0x3800;
+	    dev->stats.rx_errors++;
+	    switch (error) {
+	    case 0x0000:	dev->stats.rx_over_errors++; break;
+	    case 0x0800:	dev->stats.rx_length_errors++; break;
+	    case 0x1000:	dev->stats.rx_frame_errors++; break;
+	    case 0x1800:	dev->stats.rx_length_errors++; break;
+	    case 0x2000:	dev->stats.rx_frame_errors++; break;
+	    case 0x2800:	dev->stats.rx_crc_errors++; break;
+	    }
+	} else {
+	    short pkt_len = rx_status & 0x7ff;
+	    struct sk_buff *skb;
+
+	    skb = dev_alloc_skb(pkt_len+5);
+
+	    netdev_dbg(dev, "    Receiving packet size %d status %4.4x.\n",
+		       pkt_len, rx_status);
+	    if (skb != NULL) {
+		skb_reserve(skb, 2);
+		insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len),
+			(pkt_len+3)>>2);
+		skb->protocol = eth_type_trans(skb, dev);
+		netif_rx(skb);
+		dev->stats.rx_packets++;
+		dev->stats.rx_bytes += pkt_len;
+	    } else {
+		netdev_dbg(dev, "couldn't allocate a sk_buff of size %d.\n",
+			   pkt_len);
+		dev->stats.rx_dropped++;
+	    }
+	}
+	/* Pop the top of the Rx FIFO */
+	tc589_wait_for_completion(dev, RxDiscard);
+    }
+    if (worklimit == 0)
+	netdev_warn(dev, "too much work in el3_rx!\n");
+    return 0;
+}
+
+static void set_rx_mode(struct net_device *dev)
+{
+    unsigned int ioaddr = dev->base_addr;
+    u16 opts = SetRxFilter | RxStation | RxBroadcast;
+
+    if (dev->flags & IFF_PROMISC)
+	opts |= RxMulticast | RxProm;
+    else if (!netdev_mc_empty(dev) || (dev->flags & IFF_ALLMULTI))
+	opts |= RxMulticast;
+    outw(opts, ioaddr + EL3_CMD);
+}
+
+static void set_multicast_list(struct net_device *dev)
+{
+	struct el3_private *priv = netdev_priv(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	set_rx_mode(dev);
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int el3_close(struct net_device *dev)
+{
+    struct el3_private *lp = netdev_priv(dev);
+    struct pcmcia_device *link = lp->p_dev;
+    unsigned int ioaddr = dev->base_addr;
+
+    dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name);
+
+    if (pcmcia_dev_present(link)) {
+	/* Turn off statistics ASAP.  We update dev->stats below. */
+	outw(StatsDisable, ioaddr + EL3_CMD);
+
+	/* Disable the receiver and transmitter. */
+	outw(RxDisable, ioaddr + EL3_CMD);
+	outw(TxDisable, ioaddr + EL3_CMD);
+
+	if (dev->if_port == 2)
+	    /* Turn off thinnet power.  Green! */
+	    outw(StopCoax, ioaddr + EL3_CMD);
+	else if (dev->if_port == 1) {
+	    /* Disable link beat and jabber */
+	    EL3WINDOW(4);
+	    outw(0, ioaddr + WN4_MEDIA);
+	}
+
+	/* Switching back to window 0 disables the IRQ. */
+	EL3WINDOW(0);
+	/* But we explicitly zero the IRQ line select anyway. */
+	outw(0x0f00, ioaddr + WN0_IRQ);
+
+	/* Check if the card still exists */
+	if ((inw(ioaddr+EL3_STATUS) & 0xe000) == 0x2000)
+	    update_stats(dev);
+    }
+
+    link->open--;
+    netif_stop_queue(dev);
+    del_timer_sync(&lp->media);
+
+    return 0;
+}
+
+static const struct pcmcia_device_id tc589_ids[] = {
+	PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0101, 0x0562),
+	PCMCIA_MFC_DEVICE_PROD_ID1(0, "Motorola MARQUIS", 0xf03e4e77),
+	PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0589),
+	PCMCIA_DEVICE_PROD_ID12("Farallon", "ENet", 0x58d93fc4, 0x992c2202),
+	PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0035, "cis/3CXEM556.cis"),
+	PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x003d, "cis/3CXEM556.cis"),
+	PCMCIA_DEVICE_NULL,
+};
+MODULE_DEVICE_TABLE(pcmcia, tc589_ids);
+
+static struct pcmcia_driver tc589_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "3c589_cs",
+	.probe		= tc589_probe,
+	.remove		= tc589_detach,
+	.id_table	= tc589_ids,
+	.suspend	= tc589_suspend,
+	.resume		= tc589_resume,
+};
+
+static int __init init_tc589(void)
+{
+	return pcmcia_register_driver(&tc589_driver);
+}
+
+static void __exit exit_tc589(void)
+{
+	pcmcia_unregister_driver(&tc589_driver);
+}
+
+module_init(init_tc589);
+module_exit(exit_tc589);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/3com/3c59x.c linux-libre-3.2-gnu/drivers/net/ethernet/3com/3c59x.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/3com/3c59x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/3com/3c59x.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,3327 @@
+/* EtherLinkXL.c: A 3Com EtherLink PCI III/XL ethernet driver for linux. */
+/*
+	Written 1996-1999 by Donald Becker.
+
+	This software may be used and distributed according to the terms
+	of the GNU General Public License, incorporated herein by reference.
+
+	This driver is for the 3Com "Vortex" and "Boomerang" series ethercards.
+	Members of the series include Fast EtherLink 3c590/3c592/3c595/3c597
+	and the EtherLink XL 3c900 and 3c905 cards.
+
+	Problem reports and questions should be directed to
+	vortex@scyld.com
+
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+*/
+
+/*
+ * FIXME: This driver _could_ support MTU changing, but doesn't.  See Don's hamachi.c implementation
+ * as well as other drivers
+ *
+ * NOTE: If you make 'vortex_debug' a constant (#define vortex_debug 0) the driver shrinks by 2k
+ * due to dead code elimination.  There will be some performance benefits from this due to
+ * elimination of all the tests and reduced cache footprint.
+ */
+
+
+#define DRV_NAME	"3c59x"
+
+
+
+/* A few values that may be tweaked. */
+/* Keep the ring sizes a power of two for efficiency. */
+#define TX_RING_SIZE	16
+#define RX_RING_SIZE	32
+#define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
+
+/* "Knobs" that adjust features and parameters. */
+/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
+   Setting to > 1512 effectively disables this feature. */
+#ifndef __arm__
+static int rx_copybreak = 200;
+#else
+/* ARM systems perform better by disregarding the bus-master
+   transfer capability of these cards. -- rmk */
+static int rx_copybreak = 1513;
+#endif
+/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
+static const int mtu = 1500;
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 32;
+/* Tx timeout interval (millisecs) */
+static int watchdog = 5000;
+
+/* Allow aggregation of Tx interrupts.  Saves CPU load at the cost
+ * of possible Tx stalls if the system is blocking interrupts
+ * somewhere else.  Undefine this to disable.
+ */
+#define tx_interrupt_mitigation 1
+
+/* Put out somewhat more debugging messages. (0: no msg, 1 minimal .. 6). */
+#define vortex_debug debug
+#ifdef VORTEX_DEBUG
+static int vortex_debug = VORTEX_DEBUG;
+#else
+static int vortex_debug = 1;
+#endif
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/mii.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/highmem.h>
+#include <linux/eisa.h>
+#include <linux/bitops.h>
+#include <linux/jiffies.h>
+#include <linux/gfp.h>
+#include <asm/irq.h>			/* For nr_irqs only. */
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+/* Kernel compatibility defines, some common to David Hinds' PCMCIA package.
+   This is only in the support-all-kernels source code. */
+
+#define RUN_AT(x) (jiffies + (x))
+
+#include <linux/delay.h>
+
+
+static const char version[] __devinitconst =
+	DRV_NAME ": Donald Becker and others.\n";
+
+MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
+MODULE_DESCRIPTION("3Com 3c59x/3c9xx ethernet driver ");
+MODULE_LICENSE("GPL");
+
+
+/* Operational parameter that usually are not changed. */
+
+/* The Vortex size is twice that of the original EtherLinkIII series: the
+   runtime register window, window 1, is now always mapped in.
+   The Boomerang size is twice as large as the Vortex -- it has additional
+   bus master control registers. */
+#define VORTEX_TOTAL_SIZE 0x20
+#define BOOMERANG_TOTAL_SIZE 0x40
+
+/* Set iff a MII transceiver on any interface requires mdio preamble.
+   This only set with the original DP83840 on older 3c905 boards, so the extra
+   code size of a per-interface flag is not worthwhile. */
+static char mii_preamble_required;
+
+#define PFX DRV_NAME ": "
+
+
+
+/*
+				Theory of Operation
+
+I. Board Compatibility
+
+This device driver is designed for the 3Com FastEtherLink and FastEtherLink
+XL, 3Com's PCI to 10/100baseT adapters.  It also works with the 10Mbs
+versions of the FastEtherLink cards.  The supported product IDs are
+  3c590, 3c592, 3c595, 3c597, 3c900, 3c905
+
+The related ISA 3c515 is supported with a separate driver, 3c515.c, included
+with the kernel source or available from
+    cesdis.gsfc.nasa.gov:/pub/linux/drivers/3c515.html
+
+II. Board-specific settings
+
+PCI bus devices are configured by the system at boot time, so no jumpers
+need to be set on the board.  The system BIOS should be set to assign the
+PCI INTA signal to an otherwise unused system IRQ line.
+
+The EEPROM settings for media type and forced-full-duplex are observed.
+The EEPROM media type should be left at the default "autoselect" unless using
+10base2 or AUI connections which cannot be reliably detected.
+
+III. Driver operation
+
+The 3c59x series use an interface that's very similar to the previous 3c5x9
+series.  The primary interface is two programmed-I/O FIFOs, with an
+alternate single-contiguous-region bus-master transfer (see next).
+
+The 3c900 "Boomerang" series uses a full-bus-master interface with separate
+lists of transmit and receive descriptors, similar to the AMD LANCE/PCnet,
+DEC Tulip and Intel Speedo3.  The first chip version retains a compatible
+programmed-I/O interface that has been removed in 'B' and subsequent board
+revisions.
+
+One extension that is advertised in a very large font is that the adapters
+are capable of being bus masters.  On the Vortex chip this capability was
+only for a single contiguous region making it far less useful than the full
+bus master capability.  There is a significant performance impact of taking
+an extra interrupt or polling for the completion of each transfer, as well
+as difficulty sharing the single transfer engine between the transmit and
+receive threads.  Using DMA transfers is a win only with large blocks or
+with the flawed versions of the Intel Orion motherboard PCI controller.
+
+The Boomerang chip's full-bus-master interface is useful, and has the
+currently-unused advantages over other similar chips that queued transmit
+packets may be reordered and receive buffer groups are associated with a
+single frame.
+
+With full-bus-master support, this driver uses a "RX_COPYBREAK" scheme.
+Rather than a fixed intermediate receive buffer, this scheme allocates
+full-sized skbuffs as receive buffers.  The value RX_COPYBREAK is used as
+the copying breakpoint: it is chosen to trade-off the memory wasted by
+passing the full-sized skbuff to the queue layer for all frames vs. the
+copying cost of copying a frame to a correctly-sized skbuff.
+
+IIIC. Synchronization
+The driver runs as two independent, single-threaded flows of control.  One
+is the send-packet routine, which enforces single-threaded use by the
+dev->tbusy flag.  The other thread is the interrupt handler, which is single
+threaded by the hardware and other software.
+
+IV. Notes
+
+Thanks to Cameron Spitzer and Terry Murphy of 3Com for providing development
+3c590, 3c595, and 3c900 boards.
+The name "Vortex" is the internal 3Com project name for the PCI ASIC, and
+the EISA version is called "Demon".  According to Terry these names come
+from rides at the local amusement park.
+
+The new chips support both ethernet (1.5K) and FDDI (4.5K) packet sizes!
+This driver only supports ethernet packets because of the skbuff allocation
+limit of 4K.
+*/
+
+/* This table drives the PCI probe routines.  It's mostly boilerplate in all
+   of the drivers, and will likely be provided by some future kernel.
+*/
+enum pci_flags_bit {
+	PCI_USES_MASTER=4,
+};
+
+enum {	IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4, IS_TORNADO=8,
+	EEPROM_8BIT=0x10,	/* AKPM: Uses 0x230 as the base bitmaps for EEPROM reads */
+	HAS_PWR_CTRL=0x20, HAS_MII=0x40, HAS_NWAY=0x80, HAS_CB_FNS=0x100,
+	INVERT_MII_PWR=0x200, INVERT_LED_PWR=0x400, MAX_COLLISION_RESET=0x800,
+	EEPROM_OFFSET=0x1000, HAS_HWCKSM=0x2000, WNO_XCVR_PWR=0x4000,
+	EXTRA_PREAMBLE=0x8000, EEPROM_RESET=0x10000, };
+
+enum vortex_chips {
+	CH_3C590 = 0,
+	CH_3C592,
+	CH_3C597,
+	CH_3C595_1,
+	CH_3C595_2,
+
+	CH_3C595_3,
+	CH_3C900_1,
+	CH_3C900_2,
+	CH_3C900_3,
+	CH_3C900_4,
+
+	CH_3C900_5,
+	CH_3C900B_FL,
+	CH_3C905_1,
+	CH_3C905_2,
+	CH_3C905B_TX,
+	CH_3C905B_1,
+
+	CH_3C905B_2,
+	CH_3C905B_FX,
+	CH_3C905C,
+	CH_3C9202,
+	CH_3C980,
+	CH_3C9805,
+
+	CH_3CSOHO100_TX,
+	CH_3C555,
+	CH_3C556,
+	CH_3C556B,
+	CH_3C575,
+
+	CH_3C575_1,
+	CH_3CCFE575,
+	CH_3CCFE575CT,
+	CH_3CCFE656,
+	CH_3CCFEM656,
+
+	CH_3CCFEM656_1,
+	CH_3C450,
+	CH_3C920,
+	CH_3C982A,
+	CH_3C982B,
+
+	CH_905BT4,
+	CH_920B_EMB_WNM,
+};
+
+
+/* note: this array directly indexed by above enums, and MUST
+ * be kept in sync with both the enums above, and the PCI device
+ * table below
+ */
+static struct vortex_chip_info {
+	const char *name;
+	int flags;
+	int drv_flags;
+	int io_size;
+} vortex_info_tbl[] __devinitdata = {
+	{"3c590 Vortex 10Mbps",
+	 PCI_USES_MASTER, IS_VORTEX, 32, },
+	{"3c592 EISA 10Mbps Demon/Vortex",					/* AKPM: from Don's 3c59x_cb.c 0.49H */
+	 PCI_USES_MASTER, IS_VORTEX, 32, },
+	{"3c597 EISA Fast Demon/Vortex",					/* AKPM: from Don's 3c59x_cb.c 0.49H */
+	 PCI_USES_MASTER, IS_VORTEX, 32, },
+	{"3c595 Vortex 100baseTx",
+	 PCI_USES_MASTER, IS_VORTEX, 32, },
+	{"3c595 Vortex 100baseT4",
+	 PCI_USES_MASTER, IS_VORTEX, 32, },
+
+	{"3c595 Vortex 100base-MII",
+	 PCI_USES_MASTER, IS_VORTEX, 32, },
+	{"3c900 Boomerang 10baseT",
+	 PCI_USES_MASTER, IS_BOOMERANG|EEPROM_RESET, 64, },
+	{"3c900 Boomerang 10Mbps Combo",
+	 PCI_USES_MASTER, IS_BOOMERANG|EEPROM_RESET, 64, },
+	{"3c900 Cyclone 10Mbps TPO",						/* AKPM: from Don's 0.99M */
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
+	{"3c900 Cyclone 10Mbps Combo",
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
+
+	{"3c900 Cyclone 10Mbps TPC",						/* AKPM: from Don's 0.99M */
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
+	{"3c900B-FL Cyclone 10base-FL",
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
+	{"3c905 Boomerang 100baseTx",
+	 PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, },
+	{"3c905 Boomerang 100baseT4",
+	 PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, },
+	{"3C905B-TX Fast Etherlink XL PCI",
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
+	{"3c905B Cyclone 100baseTx",
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
+
+	{"3c905B Cyclone 10/100/BNC",
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
+	{"3c905B-FX Cyclone 100baseFx",
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
+	{"3c905C Tornado",
+	PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
+	{"3c920B-EMB-WNM (ATI Radeon 9100 IGP)",
+	 PCI_USES_MASTER, IS_TORNADO|HAS_MII|HAS_HWCKSM, 128, },
+	{"3c980 Cyclone",
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
+
+	{"3c980C Python-T",
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
+	{"3cSOHO100-TX Hurricane",
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
+	{"3c555 Laptop Hurricane",
+	 PCI_USES_MASTER, IS_CYCLONE|EEPROM_8BIT|HAS_HWCKSM, 128, },
+	{"3c556 Laptop Tornado",
+	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_8BIT|HAS_CB_FNS|INVERT_MII_PWR|
+									HAS_HWCKSM, 128, },
+	{"3c556B Laptop Hurricane",
+	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_OFFSET|HAS_CB_FNS|INVERT_MII_PWR|
+	                                WNO_XCVR_PWR|HAS_HWCKSM, 128, },
+
+	{"3c575 [Megahertz] 10/100 LAN 	CardBus",
+	PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, },
+	{"3c575 Boomerang CardBus",
+	 PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, },
+	{"3CCFE575BT Cyclone CardBus",
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|
+									INVERT_LED_PWR|HAS_HWCKSM, 128, },
+	{"3CCFE575CT Tornado CardBus",
+	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
+									MAX_COLLISION_RESET|HAS_HWCKSM, 128, },
+	{"3CCFE656 Cyclone CardBus",
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
+									INVERT_LED_PWR|HAS_HWCKSM, 128, },
+
+	{"3CCFEM656B Cyclone+Winmodem CardBus",
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
+									INVERT_LED_PWR|HAS_HWCKSM, 128, },
+	{"3CXFEM656C Tornado+Winmodem CardBus",			/* From pcmcia-cs-3.1.5 */
+	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
+									MAX_COLLISION_RESET|HAS_HWCKSM, 128, },
+	{"3c450 HomePNA Tornado",						/* AKPM: from Don's 0.99Q */
+	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
+	{"3c920 Tornado",
+	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
+	{"3c982 Hydra Dual Port A",
+	 PCI_USES_MASTER, IS_TORNADO|HAS_HWCKSM|HAS_NWAY, 128, },
+
+	{"3c982 Hydra Dual Port B",
+	 PCI_USES_MASTER, IS_TORNADO|HAS_HWCKSM|HAS_NWAY, 128, },
+	{"3c905B-T4",
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
+	{"3c920B-EMB-WNM Tornado",
+	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
+
+	{NULL,}, /* NULL terminated list. */
+};
+
+
+static DEFINE_PCI_DEVICE_TABLE(vortex_pci_tbl) = {
+	{ 0x10B7, 0x5900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C590 },
+	{ 0x10B7, 0x5920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C592 },
+	{ 0x10B7, 0x5970, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C597 },
+	{ 0x10B7, 0x5950, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C595_1 },
+	{ 0x10B7, 0x5951, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C595_2 },
+
+	{ 0x10B7, 0x5952, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C595_3 },
+	{ 0x10B7, 0x9000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_1 },
+	{ 0x10B7, 0x9001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_2 },
+	{ 0x10B7, 0x9004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_3 },
+	{ 0x10B7, 0x9005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_4 },
+
+	{ 0x10B7, 0x9006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_5 },
+	{ 0x10B7, 0x900A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900B_FL },
+	{ 0x10B7, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_1 },
+	{ 0x10B7, 0x9051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_2 },
+	{ 0x10B7, 0x9054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_TX },
+	{ 0x10B7, 0x9055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_1 },
+
+	{ 0x10B7, 0x9058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_2 },
+	{ 0x10B7, 0x905A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_FX },
+	{ 0x10B7, 0x9200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905C },
+	{ 0x10B7, 0x9202, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C9202 },
+	{ 0x10B7, 0x9800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C980 },
+	{ 0x10B7, 0x9805, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C9805 },
+
+	{ 0x10B7, 0x7646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CSOHO100_TX },
+	{ 0x10B7, 0x5055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C555 },
+	{ 0x10B7, 0x6055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C556 },
+	{ 0x10B7, 0x6056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C556B },
+	{ 0x10B7, 0x5b57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575 },
+
+	{ 0x10B7, 0x5057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575_1 },
+	{ 0x10B7, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575 },
+	{ 0x10B7, 0x5257, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575CT },
+	{ 0x10B7, 0x6560, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE656 },
+	{ 0x10B7, 0x6562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656 },
+
+	{ 0x10B7, 0x6564, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656_1 },
+	{ 0x10B7, 0x4500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C450 },
+	{ 0x10B7, 0x9201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C920 },
+	{ 0x10B7, 0x1201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C982A },
+	{ 0x10B7, 0x1202, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C982B },
+
+	{ 0x10B7, 0x9056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_905BT4 },
+	{ 0x10B7, 0x9210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_920B_EMB_WNM },
+
+	{0,}						/* 0 terminated list. */
+};
+MODULE_DEVICE_TABLE(pci, vortex_pci_tbl);
+
+
+/* Operational definitions.
+   These are not used by other compilation units and thus are not
+   exported in a ".h" file.
+
+   First the windows.  There are eight register windows, with the command
+   and status registers available in each.
+   */
+#define EL3_CMD 0x0e
+#define EL3_STATUS 0x0e
+
+/* The top five bits written to EL3_CMD are a command, the lower
+   11 bits are the parameter, if applicable.
+   Note that 11 parameters bits was fine for ethernet, but the new chip
+   can handle FDDI length frames (~4500 octets) and now parameters count
+   32-bit 'Dwords' rather than octets. */
+
+enum vortex_cmd {
+	TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
+	RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11,
+	UpStall = 6<<11, UpUnstall = (6<<11)+1,
+	DownStall = (6<<11)+2, DownUnstall = (6<<11)+3,
+	RxDiscard = 8<<11, TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
+	FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
+	SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
+	SetTxThreshold = 18<<11, SetTxStart = 19<<11,
+	StartDMAUp = 20<<11, StartDMADown = (20<<11)+1, StatsEnable = 21<<11,
+	StatsDisable = 22<<11, StopCoax = 23<<11, SetFilterBit = 25<<11,};
+
+/* The SetRxFilter command accepts the following classes: */
+enum RxFilter {
+	RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 };
+
+/* Bits in the general status register. */
+enum vortex_status {
+	IntLatch = 0x0001, HostError = 0x0002, TxComplete = 0x0004,
+	TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
+	IntReq = 0x0040, StatsFull = 0x0080,
+	DMADone = 1<<8, DownComplete = 1<<9, UpComplete = 1<<10,
+	DMAInProgress = 1<<11,			/* DMA controller is still busy.*/
+	CmdInProgress = 1<<12,			/* EL3_CMD is still busy.*/
+};
+
+/* Register window 1 offsets, the window used in normal operation.
+   On the Vortex this window is always mapped at offsets 0x10-0x1f. */
+enum Window1 {
+	TX_FIFO = 0x10,  RX_FIFO = 0x10,  RxErrors = 0x14,
+	RxStatus = 0x18,  Timer=0x1A, TxStatus = 0x1B,
+	TxFree = 0x1C, /* Remaining free bytes in Tx buffer. */
+};
+enum Window0 {
+	Wn0EepromCmd = 10,		/* Window 0: EEPROM command register. */
+	Wn0EepromData = 12,		/* Window 0: EEPROM results register. */
+	IntrStatus=0x0E,		/* Valid in all windows. */
+};
+enum Win0_EEPROM_bits {
+	EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
+	EEPROM_EWENB = 0x30,		/* Enable erasing/writing for 10 msec. */
+	EEPROM_EWDIS = 0x00,		/* Disable EWENB before 10 msec timeout. */
+};
+/* EEPROM locations. */
+enum eeprom_offset {
+	PhysAddr01=0, PhysAddr23=1, PhysAddr45=2, ModelID=3,
+	EtherLink3ID=7, IFXcvrIO=8, IRQLine=9,
+	NodeAddr01=10, NodeAddr23=11, NodeAddr45=12,
+	DriverTune=13, Checksum=15};
+
+enum Window2 {			/* Window 2. */
+	Wn2_ResetOptions=12,
+};
+enum Window3 {			/* Window 3: MAC/config bits. */
+	Wn3_Config=0, Wn3_MaxPktSize=4, Wn3_MAC_Ctrl=6, Wn3_Options=8,
+};
+
+#define BFEXT(value, offset, bitcount)  \
+    ((((unsigned long)(value)) >> (offset)) & ((1 << (bitcount)) - 1))
+
+#define BFINS(lhs, rhs, offset, bitcount)					\
+	(((lhs) & ~((((1 << (bitcount)) - 1)) << (offset))) |	\
+	(((rhs) & ((1 << (bitcount)) - 1)) << (offset)))
+
+#define RAM_SIZE(v)		BFEXT(v, 0, 3)
+#define RAM_WIDTH(v)	BFEXT(v, 3, 1)
+#define RAM_SPEED(v)	BFEXT(v, 4, 2)
+#define ROM_SIZE(v)		BFEXT(v, 6, 2)
+#define RAM_SPLIT(v)	BFEXT(v, 16, 2)
+#define XCVR(v)			BFEXT(v, 20, 4)
+#define AUTOSELECT(v)	BFEXT(v, 24, 1)
+
+enum Window4 {		/* Window 4: Xcvr/media bits. */
+	Wn4_FIFODiag = 4, Wn4_NetDiag = 6, Wn4_PhysicalMgmt=8, Wn4_Media = 10,
+};
+enum Win4_Media_bits {
+	Media_SQE = 0x0008,		/* Enable SQE error counting for AUI. */
+	Media_10TP = 0x00C0,	/* Enable link beat and jabber for 10baseT. */
+	Media_Lnk = 0x0080,		/* Enable just link beat for 100TX/100FX. */
+	Media_LnkBeat = 0x0800,
+};
+enum Window7 {					/* Window 7: Bus Master control. */
+	Wn7_MasterAddr = 0, Wn7_VlanEtherType=4, Wn7_MasterLen = 6,
+	Wn7_MasterStatus = 12,
+};
+/* Boomerang bus master control registers. */
+enum MasterCtrl {
+	PktStatus = 0x20, DownListPtr = 0x24, FragAddr = 0x28, FragLen = 0x2c,
+	TxFreeThreshold = 0x2f, UpPktStatus = 0x30, UpListPtr = 0x38,
+};
+
+/* The Rx and Tx descriptor lists.
+   Caution Alpha hackers: these types are 32 bits!  Note also the 8 byte
+   alignment contraint on tx_ring[] and rx_ring[]. */
+#define LAST_FRAG 	0x80000000			/* Last Addr/Len pair in descriptor. */
+#define DN_COMPLETE	0x00010000			/* This packet has been downloaded */
+struct boom_rx_desc {
+	__le32 next;					/* Last entry points to 0.   */
+	__le32 status;
+	__le32 addr;					/* Up to 63 addr/len pairs possible. */
+	__le32 length;					/* Set LAST_FRAG to indicate last pair. */
+};
+/* Values for the Rx status entry. */
+enum rx_desc_status {
+	RxDComplete=0x00008000, RxDError=0x4000,
+	/* See boomerang_rx() for actual error bits */
+	IPChksumErr=1<<25, TCPChksumErr=1<<26, UDPChksumErr=1<<27,
+	IPChksumValid=1<<29, TCPChksumValid=1<<30, UDPChksumValid=1<<31,
+};
+
+#ifdef MAX_SKB_FRAGS
+#define DO_ZEROCOPY 1
+#else
+#define DO_ZEROCOPY 0
+#endif
+
+struct boom_tx_desc {
+	__le32 next;					/* Last entry points to 0.   */
+	__le32 status;					/* bits 0:12 length, others see below.  */
+#if DO_ZEROCOPY
+	struct {
+		__le32 addr;
+		__le32 length;
+	} frag[1+MAX_SKB_FRAGS];
+#else
+		__le32 addr;
+		__le32 length;
+#endif
+};
+
+/* Values for the Tx status entry. */
+enum tx_desc_status {
+	CRCDisable=0x2000, TxDComplete=0x8000,
+	AddIPChksum=0x02000000, AddTCPChksum=0x04000000, AddUDPChksum=0x08000000,
+	TxIntrUploaded=0x80000000,		/* IRQ when in FIFO, but maybe not sent. */
+};
+
+/* Chip features we care about in vp->capabilities, read from the EEPROM. */
+enum ChipCaps { CapBusMaster=0x20, CapPwrMgmt=0x2000 };
+
+struct vortex_extra_stats {
+	unsigned long tx_deferred;
+	unsigned long tx_max_collisions;
+	unsigned long tx_multiple_collisions;
+	unsigned long tx_single_collisions;
+	unsigned long rx_bad_ssd;
+};
+
+struct vortex_private {
+	/* The Rx and Tx rings should be quad-word-aligned. */
+	struct boom_rx_desc* rx_ring;
+	struct boom_tx_desc* tx_ring;
+	dma_addr_t rx_ring_dma;
+	dma_addr_t tx_ring_dma;
+	/* The addresses of transmit- and receive-in-place skbuffs. */
+	struct sk_buff* rx_skbuff[RX_RING_SIZE];
+	struct sk_buff* tx_skbuff[TX_RING_SIZE];
+	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
+	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
+	struct vortex_extra_stats xstats;	/* NIC-specific extra stats */
+	struct sk_buff *tx_skb;				/* Packet being eaten by bus master ctrl.  */
+	dma_addr_t tx_skb_dma;				/* Allocated DMA address for bus master ctrl DMA.   */
+
+	/* PCI configuration space information. */
+	struct device *gendev;
+	void __iomem *ioaddr;			/* IO address space */
+	void __iomem *cb_fn_base;		/* CardBus function status addr space. */
+
+	/* Some values here only for performance evaluation and path-coverage */
+	int rx_nocopy, rx_copy, queued_packet, rx_csumhits;
+	int card_idx;
+
+	/* The remainder are related to chip state, mostly media selection. */
+	struct timer_list timer;			/* Media selection timer. */
+	struct timer_list rx_oom_timer;		/* Rx skb allocation retry timer */
+	int options;						/* User-settable misc. driver options. */
+	unsigned int media_override:4, 		/* Passed-in media type. */
+		default_media:4,				/* Read from the EEPROM/Wn3_Config. */
+		full_duplex:1, autoselect:1,
+		bus_master:1,					/* Vortex can only do a fragment bus-m. */
+		full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang  */
+		flow_ctrl:1,					/* Use 802.3x flow control (PAUSE only) */
+		partner_flow_ctrl:1,			/* Partner supports flow control */
+		has_nway:1,
+		enable_wol:1,					/* Wake-on-LAN is enabled */
+		pm_state_valid:1,				/* pci_dev->saved_config_space has sane contents */
+		open:1,
+		medialock:1,
+		must_free_region:1,				/* Flag: if zero, Cardbus owns the I/O region */
+		large_frames:1,			/* accept large frames */
+		handling_irq:1;			/* private in_irq indicator */
+	/* {get|set}_wol operations are already serialized by rtnl.
+	 * no additional locking is required for the enable_wol and acpi_set_WOL()
+	 */
+	int drv_flags;
+	u16 status_enable;
+	u16 intr_enable;
+	u16 available_media;				/* From Wn3_Options. */
+	u16 capabilities, info1, info2;		/* Various, from EEPROM. */
+	u16 advertising;					/* NWay media advertisement */
+	unsigned char phys[2];				/* MII device addresses. */
+	u16 deferred;						/* Resend these interrupts when we
+										 * bale from the ISR */
+	u16 io_size;						/* Size of PCI region (for release_region) */
+
+	/* Serialises access to hardware other than MII and variables below.
+	 * The lock hierarchy is rtnl_lock > {lock, mii_lock} > window_lock. */
+	spinlock_t lock;
+
+	spinlock_t mii_lock;		/* Serialises access to MII */
+	struct mii_if_info mii;		/* MII lib hooks/info */
+	spinlock_t window_lock;		/* Serialises access to windowed regs */
+	int window;			/* Register window */
+};
+
+static void window_set(struct vortex_private *vp, int window)
+{
+	if (window != vp->window) {
+		iowrite16(SelectWindow + window, vp->ioaddr + EL3_CMD);
+		vp->window = window;
+	}
+}
+
+#define DEFINE_WINDOW_IO(size)						\
+static u ## size							\
+window_read ## size(struct vortex_private *vp, int window, int addr)	\
+{									\
+	unsigned long flags;						\
+	u ## size ret;							\
+	spin_lock_irqsave(&vp->window_lock, flags);			\
+	window_set(vp, window);						\
+	ret = ioread ## size(vp->ioaddr + addr);			\
+	spin_unlock_irqrestore(&vp->window_lock, flags);		\
+	return ret;							\
+}									\
+static void								\
+window_write ## size(struct vortex_private *vp, u ## size value,	\
+		     int window, int addr)				\
+{									\
+	unsigned long flags;						\
+	spin_lock_irqsave(&vp->window_lock, flags);			\
+	window_set(vp, window);						\
+	iowrite ## size(value, vp->ioaddr + addr);			\
+	spin_unlock_irqrestore(&vp->window_lock, flags);		\
+}
+DEFINE_WINDOW_IO(8)
+DEFINE_WINDOW_IO(16)
+DEFINE_WINDOW_IO(32)
+
+#ifdef CONFIG_PCI
+#define DEVICE_PCI(dev) (((dev)->bus == &pci_bus_type) ? to_pci_dev((dev)) : NULL)
+#else
+#define DEVICE_PCI(dev) NULL
+#endif
+
+#define VORTEX_PCI(vp)							\
+	((struct pci_dev *) (((vp)->gendev) ? DEVICE_PCI((vp)->gendev) : NULL))
+
+#ifdef CONFIG_EISA
+#define DEVICE_EISA(dev) (((dev)->bus == &eisa_bus_type) ? to_eisa_device((dev)) : NULL)
+#else
+#define DEVICE_EISA(dev) NULL
+#endif
+
+#define VORTEX_EISA(vp)							\
+	((struct eisa_device *) (((vp)->gendev) ? DEVICE_EISA((vp)->gendev) : NULL))
+
+/* The action to take with a media selection timer tick.
+   Note that we deviate from the 3Com order by checking 10base2 before AUI.
+ */
+enum xcvr_types {
+	XCVR_10baseT=0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,
+	XCVR_100baseFx, XCVR_MII=6, XCVR_NWAY=8, XCVR_ExtMII=9, XCVR_Default=10,
+};
+
+static const struct media_table {
+	char *name;
+	unsigned int media_bits:16,		/* Bits to set in Wn4_Media register. */
+		mask:8,						/* The transceiver-present bit in Wn3_Config.*/
+		next:8;						/* The media type to try next. */
+	int wait;						/* Time before we check media status. */
+} media_tbl[] = {
+  {	"10baseT",   Media_10TP,0x08, XCVR_10base2, (14*HZ)/10},
+  { "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1*HZ)/10},
+  { "undefined", 0,			0x80, XCVR_10baseT, 10000},
+  { "10base2",   0,			0x10, XCVR_AUI,		(1*HZ)/10},
+  { "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14*HZ)/10},
+  { "100baseFX", Media_Lnk, 0x04, XCVR_MII,		(14*HZ)/10},
+  { "MII",		 0,			0x41, XCVR_10baseT, 3*HZ },
+  { "undefined", 0,			0x01, XCVR_10baseT, 10000},
+  { "Autonegotiate", 0,		0x41, XCVR_10baseT, 3*HZ},
+  { "MII-External",	 0,		0x41, XCVR_10baseT, 3*HZ },
+  { "Default",	 0,			0xFF, XCVR_10baseT, 10000},
+};
+
+static struct {
+	const char str[ETH_GSTRING_LEN];
+} ethtool_stats_keys[] = {
+	{ "tx_deferred" },
+	{ "tx_max_collisions" },
+	{ "tx_multiple_collisions" },
+	{ "tx_single_collisions" },
+	{ "rx_bad_ssd" },
+};
+
+/* number of ETHTOOL_GSTATS u64's */
+#define VORTEX_NUM_STATS    5
+
+static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
+				   int chip_idx, int card_idx);
+static int vortex_up(struct net_device *dev);
+static void vortex_down(struct net_device *dev, int final);
+static int vortex_open(struct net_device *dev);
+static void mdio_sync(struct vortex_private *vp, int bits);
+static int mdio_read(struct net_device *dev, int phy_id, int location);
+static void mdio_write(struct net_device *vp, int phy_id, int location, int value);
+static void vortex_timer(unsigned long arg);
+static void rx_oom_timer(unsigned long arg);
+static netdev_tx_t vortex_start_xmit(struct sk_buff *skb,
+				     struct net_device *dev);
+static netdev_tx_t boomerang_start_xmit(struct sk_buff *skb,
+					struct net_device *dev);
+static int vortex_rx(struct net_device *dev);
+static int boomerang_rx(struct net_device *dev);
+static irqreturn_t vortex_interrupt(int irq, void *dev_id);
+static irqreturn_t boomerang_interrupt(int irq, void *dev_id);
+static int vortex_close(struct net_device *dev);
+static void dump_tx_ring(struct net_device *dev);
+static void update_stats(void __iomem *ioaddr, struct net_device *dev);
+static struct net_device_stats *vortex_get_stats(struct net_device *dev);
+static void set_rx_mode(struct net_device *dev);
+#ifdef CONFIG_PCI
+static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+#endif
+static void vortex_tx_timeout(struct net_device *dev);
+static void acpi_set_WOL(struct net_device *dev);
+static const struct ethtool_ops vortex_ethtool_ops;
+static void set_8021q_mode(struct net_device *dev, int enable);
+
+/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
+/* Option count limit only -- unlimited interfaces are supported. */
+#define MAX_UNITS 8
+static int options[MAX_UNITS] = { [0 ... MAX_UNITS-1] = -1 };
+static int full_duplex[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
+static int hw_checksums[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
+static int flow_ctrl[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
+static int enable_wol[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
+static int use_mmio[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
+static int global_options = -1;
+static int global_full_duplex = -1;
+static int global_enable_wol = -1;
+static int global_use_mmio = -1;
+
+/* Variables to work-around the Compaq PCI BIOS32 problem. */
+static int compaq_ioaddr, compaq_irq, compaq_device_id = 0x5900;
+static struct net_device *compaq_net_device;
+
+static int vortex_cards_found;
+
+module_param(debug, int, 0);
+module_param(global_options, int, 0);
+module_param_array(options, int, NULL, 0);
+module_param(global_full_duplex, int, 0);
+module_param_array(full_duplex, int, NULL, 0);
+module_param_array(hw_checksums, int, NULL, 0);
+module_param_array(flow_ctrl, int, NULL, 0);
+module_param(global_enable_wol, int, 0);
+module_param_array(enable_wol, int, NULL, 0);
+module_param(rx_copybreak, int, 0);
+module_param(max_interrupt_work, int, 0);
+module_param(compaq_ioaddr, int, 0);
+module_param(compaq_irq, int, 0);
+module_param(compaq_device_id, int, 0);
+module_param(watchdog, int, 0);
+module_param(global_use_mmio, int, 0);
+module_param_array(use_mmio, int, NULL, 0);
+MODULE_PARM_DESC(debug, "3c59x debug level (0-6)");
+MODULE_PARM_DESC(options, "3c59x: Bits 0-3: media type, bit 4: bus mastering, bit 9: full duplex");
+MODULE_PARM_DESC(global_options, "3c59x: same as options, but applies to all NICs if options is unset");
+MODULE_PARM_DESC(full_duplex, "3c59x full duplex setting(s) (1)");
+MODULE_PARM_DESC(global_full_duplex, "3c59x: same as full_duplex, but applies to all NICs if full_duplex is unset");
+MODULE_PARM_DESC(hw_checksums, "3c59x Hardware checksum checking by adapter(s) (0-1)");
+MODULE_PARM_DESC(flow_ctrl, "3c59x 802.3x flow control usage (PAUSE only) (0-1)");
+MODULE_PARM_DESC(enable_wol, "3c59x: Turn on Wake-on-LAN for adapter(s) (0-1)");
+MODULE_PARM_DESC(global_enable_wol, "3c59x: same as enable_wol, but applies to all NICs if enable_wol is unset");
+MODULE_PARM_DESC(rx_copybreak, "3c59x copy breakpoint for copy-only-tiny-frames");
+MODULE_PARM_DESC(max_interrupt_work, "3c59x maximum events handled per interrupt");
+MODULE_PARM_DESC(compaq_ioaddr, "3c59x PCI I/O base address (Compaq BIOS problem workaround)");
+MODULE_PARM_DESC(compaq_irq, "3c59x PCI IRQ number (Compaq BIOS problem workaround)");
+MODULE_PARM_DESC(compaq_device_id, "3c59x PCI device ID (Compaq BIOS problem workaround)");
+MODULE_PARM_DESC(watchdog, "3c59x transmit timeout in milliseconds");
+MODULE_PARM_DESC(global_use_mmio, "3c59x: same as use_mmio, but applies to all NICs if options is unset");
+MODULE_PARM_DESC(use_mmio, "3c59x: use memory-mapped PCI I/O resource (0-1)");
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void poll_vortex(struct net_device *dev)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	unsigned long flags;
+	local_irq_save(flags);
+	(vp->full_bus_master_rx ? boomerang_interrupt:vortex_interrupt)(dev->irq,dev);
+	local_irq_restore(flags);
+}
+#endif
+
+#ifdef CONFIG_PM
+
+static int vortex_suspend(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct net_device *ndev = pci_get_drvdata(pdev);
+
+	if (!ndev || !netif_running(ndev))
+		return 0;
+
+	netif_device_detach(ndev);
+	vortex_down(ndev, 1);
+
+	return 0;
+}
+
+static int vortex_resume(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct net_device *ndev = pci_get_drvdata(pdev);
+	int err;
+
+	if (!ndev || !netif_running(ndev))
+		return 0;
+
+	err = vortex_up(ndev);
+	if (err)
+		return err;
+
+	netif_device_attach(ndev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops vortex_pm_ops = {
+	.suspend = vortex_suspend,
+	.resume = vortex_resume,
+	.freeze = vortex_suspend,
+	.thaw = vortex_resume,
+	.poweroff = vortex_suspend,
+	.restore = vortex_resume,
+};
+
+#define VORTEX_PM_OPS (&vortex_pm_ops)
+
+#else /* !CONFIG_PM */
+
+#define VORTEX_PM_OPS NULL
+
+#endif /* !CONFIG_PM */
+
+#ifdef CONFIG_EISA
+static struct eisa_device_id vortex_eisa_ids[] = {
+	{ "TCM5920", CH_3C592 },
+	{ "TCM5970", CH_3C597 },
+	{ "" }
+};
+MODULE_DEVICE_TABLE(eisa, vortex_eisa_ids);
+
+static int __init vortex_eisa_probe(struct device *device)
+{
+	void __iomem *ioaddr;
+	struct eisa_device *edev;
+
+	edev = to_eisa_device(device);
+
+	if (!request_region(edev->base_addr, VORTEX_TOTAL_SIZE, DRV_NAME))
+		return -EBUSY;
+
+	ioaddr = ioport_map(edev->base_addr, VORTEX_TOTAL_SIZE);
+
+	if (vortex_probe1(device, ioaddr, ioread16(ioaddr + 0xC88) >> 12,
+					  edev->id.driver_data, vortex_cards_found)) {
+		release_region(edev->base_addr, VORTEX_TOTAL_SIZE);
+		return -ENODEV;
+	}
+
+	vortex_cards_found++;
+
+	return 0;
+}
+
+static int __devexit vortex_eisa_remove(struct device *device)
+{
+	struct eisa_device *edev;
+	struct net_device *dev;
+	struct vortex_private *vp;
+	void __iomem *ioaddr;
+
+	edev = to_eisa_device(device);
+	dev = eisa_get_drvdata(edev);
+
+	if (!dev) {
+		pr_err("vortex_eisa_remove called for Compaq device!\n");
+		BUG();
+	}
+
+	vp = netdev_priv(dev);
+	ioaddr = vp->ioaddr;
+
+	unregister_netdev(dev);
+	iowrite16(TotalReset|0x14, ioaddr + EL3_CMD);
+	release_region(dev->base_addr, VORTEX_TOTAL_SIZE);
+
+	free_netdev(dev);
+	return 0;
+}
+
+static struct eisa_driver vortex_eisa_driver = {
+	.id_table = vortex_eisa_ids,
+	.driver   = {
+		.name    = "3c59x",
+		.probe   = vortex_eisa_probe,
+		.remove  = __devexit_p(vortex_eisa_remove)
+	}
+};
+
+#endif /* CONFIG_EISA */
+
+/* returns count found (>= 0), or negative on error */
+static int __init vortex_eisa_init(void)
+{
+	int eisa_found = 0;
+	int orig_cards_found = vortex_cards_found;
+
+#ifdef CONFIG_EISA
+	int err;
+
+	err = eisa_driver_register (&vortex_eisa_driver);
+	if (!err) {
+		/*
+		 * Because of the way EISA bus is probed, we cannot assume
+		 * 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 happened...
+		 */
+		eisa_found = 1;
+	}
+#endif
+
+	/* Special code to work-around the Compaq PCI BIOS32 problem. */
+	if (compaq_ioaddr) {
+		vortex_probe1(NULL, ioport_map(compaq_ioaddr, VORTEX_TOTAL_SIZE),
+			      compaq_irq, compaq_device_id, vortex_cards_found++);
+	}
+
+	return vortex_cards_found - orig_cards_found + eisa_found;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit vortex_init_one(struct pci_dev *pdev,
+				      const struct pci_device_id *ent)
+{
+	int rc, unit, pci_bar;
+	struct vortex_chip_info *vci;
+	void __iomem *ioaddr;
+
+	/* wake up and enable device */
+	rc = pci_enable_device(pdev);
+	if (rc < 0)
+		goto out;
+
+	unit = vortex_cards_found;
+
+	if (global_use_mmio < 0 && (unit >= MAX_UNITS || use_mmio[unit] < 0)) {
+		/* Determine the default if the user didn't override us */
+		vci = &vortex_info_tbl[ent->driver_data];
+		pci_bar = vci->drv_flags & (IS_CYCLONE | IS_TORNADO) ? 1 : 0;
+	} else if (unit < MAX_UNITS && use_mmio[unit] >= 0)
+		pci_bar = use_mmio[unit] ? 1 : 0;
+	else
+		pci_bar = global_use_mmio ? 1 : 0;
+
+	ioaddr = pci_iomap(pdev, pci_bar, 0);
+	if (!ioaddr) /* If mapping fails, fall-back to BAR 0... */
+		ioaddr = pci_iomap(pdev, 0, 0);
+	if (!ioaddr) {
+		pci_disable_device(pdev);
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	rc = vortex_probe1(&pdev->dev, ioaddr, pdev->irq,
+			   ent->driver_data, unit);
+	if (rc < 0) {
+		pci_iounmap(pdev, ioaddr);
+		pci_disable_device(pdev);
+		goto out;
+	}
+
+	vortex_cards_found++;
+
+out:
+	return rc;
+}
+
+static const struct net_device_ops boomrang_netdev_ops = {
+	.ndo_open		= vortex_open,
+	.ndo_stop		= vortex_close,
+	.ndo_start_xmit		= boomerang_start_xmit,
+	.ndo_tx_timeout		= vortex_tx_timeout,
+	.ndo_get_stats		= vortex_get_stats,
+#ifdef CONFIG_PCI
+	.ndo_do_ioctl 		= vortex_ioctl,
+#endif
+	.ndo_set_rx_mode	= set_rx_mode,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= poll_vortex,
+#endif
+};
+
+static const struct net_device_ops vortex_netdev_ops = {
+	.ndo_open		= vortex_open,
+	.ndo_stop		= vortex_close,
+	.ndo_start_xmit		= vortex_start_xmit,
+	.ndo_tx_timeout		= vortex_tx_timeout,
+	.ndo_get_stats		= vortex_get_stats,
+#ifdef CONFIG_PCI
+	.ndo_do_ioctl 		= vortex_ioctl,
+#endif
+	.ndo_set_rx_mode	= set_rx_mode,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= poll_vortex,
+#endif
+};
+
+/*
+ * Start up the PCI/EISA device which is described by *gendev.
+ * Return 0 on success.
+ *
+ * NOTE: pdev can be NULL, for the case of a Compaq device
+ */
+static int __devinit vortex_probe1(struct device *gendev,
+				   void __iomem *ioaddr, int irq,
+				   int chip_idx, int card_idx)
+{
+	struct vortex_private *vp;
+	int option;
+	unsigned int eeprom[0x40], checksum = 0;		/* EEPROM contents */
+	int i, step;
+	struct net_device *dev;
+	static int printed_version;
+	int retval, print_info;
+	struct vortex_chip_info * const vci = &vortex_info_tbl[chip_idx];
+	const char *print_name = "3c59x";
+	struct pci_dev *pdev = NULL;
+	struct eisa_device *edev = NULL;
+
+	if (!printed_version) {
+		pr_info("%s", version);
+		printed_version = 1;
+	}
+
+	if (gendev) {
+		if ((pdev = DEVICE_PCI(gendev))) {
+			print_name = pci_name(pdev);
+		}
+
+		if ((edev = DEVICE_EISA(gendev))) {
+			print_name = dev_name(&edev->dev);
+		}
+	}
+
+	dev = alloc_etherdev(sizeof(*vp));
+	retval = -ENOMEM;
+	if (!dev) {
+		pr_err(PFX "unable to allocate etherdev, aborting\n");
+		goto out;
+	}
+	SET_NETDEV_DEV(dev, gendev);
+	vp = netdev_priv(dev);
+
+	option = global_options;
+
+	/* The lower four bits are the media type. */
+	if (dev->mem_start) {
+		/*
+		 * The 'options' param is passed in as the third arg to the
+		 * LILO 'ether=' argument for non-modular use
+		 */
+		option = dev->mem_start;
+	}
+	else if (card_idx < MAX_UNITS) {
+		if (options[card_idx] >= 0)
+			option = options[card_idx];
+	}
+
+	if (option > 0) {
+		if (option & 0x8000)
+			vortex_debug = 7;
+		if (option & 0x4000)
+			vortex_debug = 2;
+		if (option & 0x0400)
+			vp->enable_wol = 1;
+	}
+
+	print_info = (vortex_debug > 1);
+	if (print_info)
+		pr_info("See Documentation/networking/vortex.txt\n");
+
+	pr_info("%s: 3Com %s %s at %p.\n",
+	       print_name,
+	       pdev ? "PCI" : "EISA",
+	       vci->name,
+	       ioaddr);
+
+	dev->base_addr = (unsigned long)ioaddr;
+	dev->irq = irq;
+	dev->mtu = mtu;
+	vp->ioaddr = ioaddr;
+	vp->large_frames = mtu > 1500;
+	vp->drv_flags = vci->drv_flags;
+	vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0;
+	vp->io_size = vci->io_size;
+	vp->card_idx = card_idx;
+	vp->window = -1;
+
+	/* module list only for Compaq device */
+	if (gendev == NULL) {
+		compaq_net_device = dev;
+	}
+
+	/* PCI-only startup logic */
+	if (pdev) {
+		/* EISA resources already marked, so only PCI needs to do this here */
+		/* Ignore return value, because Cardbus drivers already allocate for us */
+		if (request_region(dev->base_addr, vci->io_size, print_name) != NULL)
+			vp->must_free_region = 1;
+
+		/* enable bus-mastering if necessary */
+		if (vci->flags & PCI_USES_MASTER)
+			pci_set_master(pdev);
+
+		if (vci->drv_flags & IS_VORTEX) {
+			u8 pci_latency;
+			u8 new_latency = 248;
+
+			/* Check the PCI latency value.  On the 3c590 series the latency timer
+			   must be set to the maximum value to avoid data corruption that occurs
+			   when the timer expires during a transfer.  This bug exists the Vortex
+			   chip only. */
+			pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
+			if (pci_latency < new_latency) {
+				pr_info("%s: Overriding PCI latency timer (CFLT) setting of %d, new value is %d.\n",
+					print_name, pci_latency, new_latency);
+				pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency);
+			}
+		}
+	}
+
+	spin_lock_init(&vp->lock);
+	spin_lock_init(&vp->mii_lock);
+	spin_lock_init(&vp->window_lock);
+	vp->gendev = gendev;
+	vp->mii.dev = dev;
+	vp->mii.mdio_read = mdio_read;
+	vp->mii.mdio_write = mdio_write;
+	vp->mii.phy_id_mask = 0x1f;
+	vp->mii.reg_num_mask = 0x1f;
+
+	/* Makes sure rings are at least 16 byte aligned. */
+	vp->rx_ring = pci_alloc_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE
+					   + sizeof(struct boom_tx_desc) * TX_RING_SIZE,
+					   &vp->rx_ring_dma);
+	retval = -ENOMEM;
+	if (!vp->rx_ring)
+		goto free_region;
+
+	vp->tx_ring = (struct boom_tx_desc *)(vp->rx_ring + RX_RING_SIZE);
+	vp->tx_ring_dma = vp->rx_ring_dma + sizeof(struct boom_rx_desc) * RX_RING_SIZE;
+
+	/* if we are a PCI driver, we store info in pdev->driver_data
+	 * instead of a module list */
+	if (pdev)
+		pci_set_drvdata(pdev, dev);
+	if (edev)
+		eisa_set_drvdata(edev, dev);
+
+	vp->media_override = 7;
+	if (option >= 0) {
+		vp->media_override = ((option & 7) == 2)  ?  0  :  option & 15;
+		if (vp->media_override != 7)
+			vp->medialock = 1;
+		vp->full_duplex = (option & 0x200) ? 1 : 0;
+		vp->bus_master = (option & 16) ? 1 : 0;
+	}
+
+	if (global_full_duplex > 0)
+		vp->full_duplex = 1;
+	if (global_enable_wol > 0)
+		vp->enable_wol = 1;
+
+	if (card_idx < MAX_UNITS) {
+		if (full_duplex[card_idx] > 0)
+			vp->full_duplex = 1;
+		if (flow_ctrl[card_idx] > 0)
+			vp->flow_ctrl = 1;
+		if (enable_wol[card_idx] > 0)
+			vp->enable_wol = 1;
+	}
+
+	vp->mii.force_media = vp->full_duplex;
+	vp->options = option;
+	/* Read the station address from the EEPROM. */
+	{
+		int base;
+
+		if (vci->drv_flags & EEPROM_8BIT)
+			base = 0x230;
+		else if (vci->drv_flags & EEPROM_OFFSET)
+			base = EEPROM_Read + 0x30;
+		else
+			base = EEPROM_Read;
+
+		for (i = 0; i < 0x40; i++) {
+			int timer;
+			window_write16(vp, base + i, 0, Wn0EepromCmd);
+			/* Pause for at least 162 us. for the read to take place. */
+			for (timer = 10; timer >= 0; timer--) {
+				udelay(162);
+				if ((window_read16(vp, 0, Wn0EepromCmd) &
+				     0x8000) == 0)
+					break;
+			}
+			eeprom[i] = window_read16(vp, 0, Wn0EepromData);
+		}
+	}
+	for (i = 0; i < 0x18; i++)
+		checksum ^= eeprom[i];
+	checksum = (checksum ^ (checksum >> 8)) & 0xff;
+	if (checksum != 0x00) {		/* Grrr, needless incompatible change 3Com. */
+		while (i < 0x21)
+			checksum ^= eeprom[i++];
+		checksum = (checksum ^ (checksum >> 8)) & 0xff;
+	}
+	if ((checksum != 0x00) && !(vci->drv_flags & IS_TORNADO))
+		pr_cont(" ***INVALID CHECKSUM %4.4x*** ", checksum);
+	for (i = 0; i < 3; i++)
+		((__be16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]);
+	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+	if (print_info)
+		pr_cont(" %pM", dev->dev_addr);
+	/* Unfortunately an all zero eeprom passes the checksum and this
+	   gets found in the wild in failure cases. Crypto is hard 8) */
+	if (!is_valid_ether_addr(dev->dev_addr)) {
+		retval = -EINVAL;
+		pr_err("*** EEPROM MAC address is invalid.\n");
+		goto free_ring;	/* With every pack */
+	}
+	for (i = 0; i < 6; i++)
+		window_write8(vp, dev->dev_addr[i], 2, i);
+
+	if (print_info)
+		pr_cont(", IRQ %d\n", dev->irq);
+	/* Tell them about an invalid IRQ. */
+	if (dev->irq <= 0 || dev->irq >= nr_irqs)
+		pr_warning(" *** Warning: IRQ %d is unlikely to work! ***\n",
+			   dev->irq);
+
+	step = (window_read8(vp, 4, Wn4_NetDiag) & 0x1e) >> 1;
+	if (print_info) {
+		pr_info("  product code %02x%02x rev %02x.%d date %02d-%02d-%02d\n",
+			eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14],
+			step, (eeprom[4]>>5) & 15, eeprom[4] & 31, eeprom[4]>>9);
+	}
+
+
+	if (pdev && vci->drv_flags & HAS_CB_FNS) {
+		unsigned short n;
+
+		vp->cb_fn_base = pci_iomap(pdev, 2, 0);
+		if (!vp->cb_fn_base) {
+			retval = -ENOMEM;
+			goto free_ring;
+		}
+
+		if (print_info) {
+			pr_info("%s: CardBus functions mapped %16.16llx->%p\n",
+				print_name,
+				(unsigned long long)pci_resource_start(pdev, 2),
+				vp->cb_fn_base);
+		}
+
+		n = window_read16(vp, 2, Wn2_ResetOptions) & ~0x4010;
+		if (vp->drv_flags & INVERT_LED_PWR)
+			n |= 0x10;
+		if (vp->drv_flags & INVERT_MII_PWR)
+			n |= 0x4000;
+		window_write16(vp, n, 2, Wn2_ResetOptions);
+		if (vp->drv_flags & WNO_XCVR_PWR) {
+			window_write16(vp, 0x0800, 0, 0);
+		}
+	}
+
+	/* Extract our information from the EEPROM data. */
+	vp->info1 = eeprom[13];
+	vp->info2 = eeprom[15];
+	vp->capabilities = eeprom[16];
+
+	if (vp->info1 & 0x8000) {
+		vp->full_duplex = 1;
+		if (print_info)
+			pr_info("Full duplex capable\n");
+	}
+
+	{
+		static const char * const ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
+		unsigned int config;
+		vp->available_media = window_read16(vp, 3, Wn3_Options);
+		if ((vp->available_media & 0xff) == 0)		/* Broken 3c916 */
+			vp->available_media = 0x40;
+		config = window_read32(vp, 3, Wn3_Config);
+		if (print_info) {
+			pr_debug("  Internal config register is %4.4x, transceivers %#x.\n",
+				config, window_read16(vp, 3, Wn3_Options));
+			pr_info("  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
+				   8 << RAM_SIZE(config),
+				   RAM_WIDTH(config) ? "word" : "byte",
+				   ram_split[RAM_SPLIT(config)],
+				   AUTOSELECT(config) ? "autoselect/" : "",
+				   XCVR(config) > XCVR_ExtMII ? "<invalid transceiver>" :
+				   media_tbl[XCVR(config)].name);
+		}
+		vp->default_media = XCVR(config);
+		if (vp->default_media == XCVR_NWAY)
+			vp->has_nway = 1;
+		vp->autoselect = AUTOSELECT(config);
+	}
+
+	if (vp->media_override != 7) {
+		pr_info("%s:  Media override to transceiver type %d (%s).\n",
+				print_name, vp->media_override,
+				media_tbl[vp->media_override].name);
+		dev->if_port = vp->media_override;
+	} else
+		dev->if_port = vp->default_media;
+
+	if ((vp->available_media & 0x40) || (vci->drv_flags & HAS_NWAY) ||
+		dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
+		int phy, phy_idx = 0;
+		mii_preamble_required++;
+		if (vp->drv_flags & EXTRA_PREAMBLE)
+			mii_preamble_required++;
+		mdio_sync(vp, 32);
+		mdio_read(dev, 24, MII_BMSR);
+		for (phy = 0; phy < 32 && phy_idx < 1; phy++) {
+			int mii_status, phyx;
+
+			/*
+			 * For the 3c905CX we look at index 24 first, because it bogusly
+			 * reports an external PHY at all indices
+			 */
+			if (phy == 0)
+				phyx = 24;
+			else if (phy <= 24)
+				phyx = phy - 1;
+			else
+				phyx = phy;
+			mii_status = mdio_read(dev, phyx, MII_BMSR);
+			if (mii_status  &&  mii_status != 0xffff) {
+				vp->phys[phy_idx++] = phyx;
+				if (print_info) {
+					pr_info("  MII transceiver found at address %d, status %4x.\n",
+						phyx, mii_status);
+				}
+				if ((mii_status & 0x0040) == 0)
+					mii_preamble_required++;
+			}
+		}
+		mii_preamble_required--;
+		if (phy_idx == 0) {
+			pr_warning("  ***WARNING*** No MII transceivers found!\n");
+			vp->phys[0] = 24;
+		} else {
+			vp->advertising = mdio_read(dev, vp->phys[0], MII_ADVERTISE);
+			if (vp->full_duplex) {
+				/* Only advertise the FD media types. */
+				vp->advertising &= ~0x02A0;
+				mdio_write(dev, vp->phys[0], 4, vp->advertising);
+			}
+		}
+		vp->mii.phy_id = vp->phys[0];
+	}
+
+	if (vp->capabilities & CapBusMaster) {
+		vp->full_bus_master_tx = 1;
+		if (print_info) {
+			pr_info("  Enabling bus-master transmits and %s receives.\n",
+			(vp->info2 & 1) ? "early" : "whole-frame" );
+		}
+		vp->full_bus_master_rx = (vp->info2 & 1) ? 1 : 2;
+		vp->bus_master = 0;		/* AKPM: vortex only */
+	}
+
+	/* The 3c59x-specific entries in the device structure. */
+	if (vp->full_bus_master_tx) {
+		dev->netdev_ops = &boomrang_netdev_ops;
+		/* Actually, it still should work with iommu. */
+		if (card_idx < MAX_UNITS &&
+		    ((hw_checksums[card_idx] == -1 && (vp->drv_flags & HAS_HWCKSM)) ||
+				hw_checksums[card_idx] == 1)) {
+			dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+		}
+	} else
+		dev->netdev_ops =  &vortex_netdev_ops;
+
+	if (print_info) {
+		pr_info("%s: scatter/gather %sabled. h/w checksums %sabled\n",
+				print_name,
+				(dev->features & NETIF_F_SG) ? "en":"dis",
+				(dev->features & NETIF_F_IP_CSUM) ? "en":"dis");
+	}
+
+	dev->ethtool_ops = &vortex_ethtool_ops;
+	dev->watchdog_timeo = (watchdog * HZ) / 1000;
+
+	if (pdev) {
+		vp->pm_state_valid = 1;
+ 		pci_save_state(VORTEX_PCI(vp));
+ 		acpi_set_WOL(dev);
+	}
+	retval = register_netdev(dev);
+	if (retval == 0)
+		return 0;
+
+free_ring:
+	pci_free_consistent(pdev,
+						sizeof(struct boom_rx_desc) * RX_RING_SIZE
+							+ sizeof(struct boom_tx_desc) * TX_RING_SIZE,
+						vp->rx_ring,
+						vp->rx_ring_dma);
+free_region:
+	if (vp->must_free_region)
+		release_region(dev->base_addr, vci->io_size);
+	free_netdev(dev);
+	pr_err(PFX "vortex_probe1 fails.  Returns %d\n", retval);
+out:
+	return retval;
+}
+
+static void
+issue_and_wait(struct net_device *dev, int cmd)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	void __iomem *ioaddr = vp->ioaddr;
+	int i;
+
+	iowrite16(cmd, ioaddr + EL3_CMD);
+	for (i = 0; i < 2000; i++) {
+		if (!(ioread16(ioaddr + EL3_STATUS) & CmdInProgress))
+			return;
+	}
+
+	/* OK, that didn't work.  Do it the slow way.  One second */
+	for (i = 0; i < 100000; i++) {
+		if (!(ioread16(ioaddr + EL3_STATUS) & CmdInProgress)) {
+			if (vortex_debug > 1)
+				pr_info("%s: command 0x%04x took %d usecs\n",
+					   dev->name, cmd, i * 10);
+			return;
+		}
+		udelay(10);
+	}
+	pr_err("%s: command 0x%04x did not complete! Status=0x%x\n",
+			   dev->name, cmd, ioread16(ioaddr + EL3_STATUS));
+}
+
+static void
+vortex_set_duplex(struct net_device *dev)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+
+	pr_info("%s:  setting %s-duplex.\n",
+		dev->name, (vp->full_duplex) ? "full" : "half");
+
+	/* Set the full-duplex bit. */
+	window_write16(vp,
+		       ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
+		       (vp->large_frames ? 0x40 : 0) |
+		       ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ?
+			0x100 : 0),
+		       3, Wn3_MAC_Ctrl);
+}
+
+static void vortex_check_media(struct net_device *dev, unsigned int init)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	unsigned int ok_to_print = 0;
+
+	if (vortex_debug > 3)
+		ok_to_print = 1;
+
+	if (mii_check_media(&vp->mii, ok_to_print, init)) {
+		vp->full_duplex = vp->mii.full_duplex;
+		vortex_set_duplex(dev);
+	} else if (init) {
+		vortex_set_duplex(dev);
+	}
+}
+
+static int
+vortex_up(struct net_device *dev)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	void __iomem *ioaddr = vp->ioaddr;
+	unsigned int config;
+	int i, mii_reg1, mii_reg5, err = 0;
+
+	if (VORTEX_PCI(vp)) {
+		pci_set_power_state(VORTEX_PCI(vp), PCI_D0);	/* Go active */
+		if (vp->pm_state_valid)
+			pci_restore_state(VORTEX_PCI(vp));
+		err = pci_enable_device(VORTEX_PCI(vp));
+		if (err) {
+			pr_warning("%s: Could not enable device\n",
+				dev->name);
+			goto err_out;
+		}
+	}
+
+	/* Before initializing select the active media port. */
+	config = window_read32(vp, 3, Wn3_Config);
+
+	if (vp->media_override != 7) {
+		pr_info("%s: Media override to transceiver %d (%s).\n",
+			   dev->name, vp->media_override,
+			   media_tbl[vp->media_override].name);
+		dev->if_port = vp->media_override;
+	} else if (vp->autoselect) {
+		if (vp->has_nway) {
+			if (vortex_debug > 1)
+				pr_info("%s: using NWAY device table, not %d\n",
+								dev->name, dev->if_port);
+			dev->if_port = XCVR_NWAY;
+		} else {
+			/* Find first available media type, starting with 100baseTx. */
+			dev->if_port = XCVR_100baseTx;
+			while (! (vp->available_media & media_tbl[dev->if_port].mask))
+				dev->if_port = media_tbl[dev->if_port].next;
+			if (vortex_debug > 1)
+				pr_info("%s: first available media type: %s\n",
+					dev->name, media_tbl[dev->if_port].name);
+		}
+	} else {
+		dev->if_port = vp->default_media;
+		if (vortex_debug > 1)
+			pr_info("%s: using default media %s\n",
+				dev->name, media_tbl[dev->if_port].name);
+	}
+
+	init_timer(&vp->timer);
+	vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
+	vp->timer.data = (unsigned long)dev;
+	vp->timer.function = vortex_timer;		/* timer handler */
+	add_timer(&vp->timer);
+
+	init_timer(&vp->rx_oom_timer);
+	vp->rx_oom_timer.data = (unsigned long)dev;
+	vp->rx_oom_timer.function = rx_oom_timer;
+
+	if (vortex_debug > 1)
+		pr_debug("%s: Initial media type %s.\n",
+			   dev->name, media_tbl[dev->if_port].name);
+
+	vp->full_duplex = vp->mii.force_media;
+	config = BFINS(config, dev->if_port, 20, 4);
+	if (vortex_debug > 6)
+		pr_debug("vortex_up(): writing 0x%x to InternalConfig\n", config);
+	window_write32(vp, config, 3, Wn3_Config);
+
+	if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
+		mii_reg1 = mdio_read(dev, vp->phys[0], MII_BMSR);
+		mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA);
+		vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0);
+		vp->mii.full_duplex = vp->full_duplex;
+
+		vortex_check_media(dev, 1);
+	}
+	else
+		vortex_set_duplex(dev);
+
+	issue_and_wait(dev, TxReset);
+	/*
+	 * Don't reset the PHY - that upsets autonegotiation during DHCP operations.
+	 */
+	issue_and_wait(dev, RxReset|0x04);
+
+
+	iowrite16(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
+
+	if (vortex_debug > 1) {
+		pr_debug("%s: vortex_up() irq %d media status %4.4x.\n",
+			   dev->name, dev->irq, window_read16(vp, 4, Wn4_Media));
+	}
+
+	/* Set the station address and mask in window 2 each time opened. */
+	for (i = 0; i < 6; i++)
+		window_write8(vp, dev->dev_addr[i], 2, i);
+	for (; i < 12; i+=2)
+		window_write16(vp, 0, 2, i);
+
+	if (vp->cb_fn_base) {
+		unsigned short n = window_read16(vp, 2, Wn2_ResetOptions) & ~0x4010;
+		if (vp->drv_flags & INVERT_LED_PWR)
+			n |= 0x10;
+		if (vp->drv_flags & INVERT_MII_PWR)
+			n |= 0x4000;
+		window_write16(vp, n, 2, Wn2_ResetOptions);
+	}
+
+	if (dev->if_port == XCVR_10base2)
+		/* Start the thinnet transceiver. We should really wait 50ms...*/
+		iowrite16(StartCoax, ioaddr + EL3_CMD);
+	if (dev->if_port != XCVR_NWAY) {
+		window_write16(vp,
+			       (window_read16(vp, 4, Wn4_Media) &
+				~(Media_10TP|Media_SQE)) |
+			       media_tbl[dev->if_port].media_bits,
+			       4, Wn4_Media);
+	}
+
+	/* Switch to the stats window, and clear all stats by reading. */
+	iowrite16(StatsDisable, ioaddr + EL3_CMD);
+	for (i = 0; i < 10; i++)
+		window_read8(vp, 6, i);
+	window_read16(vp, 6, 10);
+	window_read16(vp, 6, 12);
+	/* New: On the Vortex we must also clear the BadSSD counter. */
+	window_read8(vp, 4, 12);
+	/* ..and on the Boomerang we enable the extra statistics bits. */
+	window_write16(vp, 0x0040, 4, Wn4_NetDiag);
+
+	if (vp->full_bus_master_rx) { /* Boomerang bus master. */
+		vp->cur_rx = vp->dirty_rx = 0;
+		/* Initialize the RxEarly register as recommended. */
+		iowrite16(SetRxThreshold + (1536>>2), ioaddr + EL3_CMD);
+		iowrite32(0x0020, ioaddr + PktStatus);
+		iowrite32(vp->rx_ring_dma, ioaddr + UpListPtr);
+	}
+	if (vp->full_bus_master_tx) { 		/* Boomerang bus master Tx. */
+		vp->cur_tx = vp->dirty_tx = 0;
+		if (vp->drv_flags & IS_BOOMERANG)
+			iowrite8(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */
+		/* Clear the Rx, Tx rings. */
+		for (i = 0; i < RX_RING_SIZE; i++)	/* AKPM: this is done in vortex_open, too */
+			vp->rx_ring[i].status = 0;
+		for (i = 0; i < TX_RING_SIZE; i++)
+			vp->tx_skbuff[i] = NULL;
+		iowrite32(0, ioaddr + DownListPtr);
+	}
+	/* Set receiver mode: presumably accept b-case and phys addr only. */
+	set_rx_mode(dev);
+	/* enable 802.1q tagged frames */
+	set_8021q_mode(dev, 1);
+	iowrite16(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
+
+	iowrite16(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
+	iowrite16(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
+	/* Allow status bits to be seen. */
+	vp->status_enable = SetStatusEnb | HostError|IntReq|StatsFull|TxComplete|
+		(vp->full_bus_master_tx ? DownComplete : TxAvailable) |
+		(vp->full_bus_master_rx ? UpComplete : RxComplete) |
+		(vp->bus_master ? DMADone : 0);
+	vp->intr_enable = SetIntrEnb | IntLatch | TxAvailable |
+		(vp->full_bus_master_rx ? 0 : RxComplete) |
+		StatsFull | HostError | TxComplete | IntReq
+		| (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete;
+	iowrite16(vp->status_enable, ioaddr + EL3_CMD);
+	/* Ack all pending events, and set active indicator mask. */
+	iowrite16(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
+		 ioaddr + EL3_CMD);
+	iowrite16(vp->intr_enable, ioaddr + EL3_CMD);
+	if (vp->cb_fn_base)			/* The PCMCIA people are idiots.  */
+		iowrite32(0x8000, vp->cb_fn_base + 4);
+	netif_start_queue (dev);
+err_out:
+	return err;
+}
+
+static int
+vortex_open(struct net_device *dev)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	int i;
+	int retval;
+
+	/* Use the now-standard shared IRQ implementation. */
+	if ((retval = request_irq(dev->irq, vp->full_bus_master_rx ?
+				boomerang_interrupt : vortex_interrupt, IRQF_SHARED, dev->name, dev))) {
+		pr_err("%s: Could not reserve IRQ %d\n", dev->name, dev->irq);
+		goto err;
+	}
+
+	if (vp->full_bus_master_rx) { /* Boomerang bus master. */
+		if (vortex_debug > 2)
+			pr_debug("%s:  Filling in the Rx ring.\n", dev->name);
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			struct sk_buff *skb;
+			vp->rx_ring[i].next = cpu_to_le32(vp->rx_ring_dma + sizeof(struct boom_rx_desc) * (i+1));
+			vp->rx_ring[i].status = 0;	/* Clear complete bit. */
+			vp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG);
+
+			skb = __netdev_alloc_skb(dev, PKT_BUF_SZ + NET_IP_ALIGN,
+						 GFP_KERNEL);
+			vp->rx_skbuff[i] = skb;
+			if (skb == NULL)
+				break;			/* Bad news!  */
+
+			skb_reserve(skb, NET_IP_ALIGN);	/* Align IP on 16 byte boundaries */
+			vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));
+		}
+		if (i != RX_RING_SIZE) {
+			int j;
+			pr_emerg("%s: no memory for rx ring\n", dev->name);
+			for (j = 0; j < i; j++) {
+				if (vp->rx_skbuff[j]) {
+					dev_kfree_skb(vp->rx_skbuff[j]);
+					vp->rx_skbuff[j] = NULL;
+				}
+			}
+			retval = -ENOMEM;
+			goto err_free_irq;
+		}
+		/* Wrap the ring. */
+		vp->rx_ring[i-1].next = cpu_to_le32(vp->rx_ring_dma);
+	}
+
+	retval = vortex_up(dev);
+	if (!retval)
+		goto out;
+
+err_free_irq:
+	free_irq(dev->irq, dev);
+err:
+	if (vortex_debug > 1)
+		pr_err("%s: vortex_open() fails: returning %d\n", dev->name, retval);
+out:
+	return retval;
+}
+
+static void
+vortex_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct vortex_private *vp = netdev_priv(dev);
+	void __iomem *ioaddr = vp->ioaddr;
+	int next_tick = 60*HZ;
+	int ok = 0;
+	int media_status;
+
+	if (vortex_debug > 2) {
+		pr_debug("%s: Media selection timer tick happened, %s.\n",
+			   dev->name, media_tbl[dev->if_port].name);
+		pr_debug("dev->watchdog_timeo=%d\n", dev->watchdog_timeo);
+	}
+
+	media_status = window_read16(vp, 4, Wn4_Media);
+	switch (dev->if_port) {
+	case XCVR_10baseT:  case XCVR_100baseTx:  case XCVR_100baseFx:
+		if (media_status & Media_LnkBeat) {
+			netif_carrier_on(dev);
+			ok = 1;
+			if (vortex_debug > 1)
+				pr_debug("%s: Media %s has link beat, %x.\n",
+					   dev->name, media_tbl[dev->if_port].name, media_status);
+		} else {
+			netif_carrier_off(dev);
+			if (vortex_debug > 1) {
+				pr_debug("%s: Media %s has no link beat, %x.\n",
+					   dev->name, media_tbl[dev->if_port].name, media_status);
+			}
+		}
+		break;
+	case XCVR_MII: case XCVR_NWAY:
+		{
+			ok = 1;
+			vortex_check_media(dev, 0);
+		}
+		break;
+	  default:					/* Other media types handled by Tx timeouts. */
+		if (vortex_debug > 1)
+		  pr_debug("%s: Media %s has no indication, %x.\n",
+				 dev->name, media_tbl[dev->if_port].name, media_status);
+		ok = 1;
+	}
+
+	if (!netif_carrier_ok(dev))
+		next_tick = 5*HZ;
+
+	if (vp->medialock)
+		goto leave_media_alone;
+
+	if (!ok) {
+		unsigned int config;
+
+		spin_lock_irq(&vp->lock);
+
+		do {
+			dev->if_port = media_tbl[dev->if_port].next;
+		} while ( ! (vp->available_media & media_tbl[dev->if_port].mask));
+		if (dev->if_port == XCVR_Default) { /* Go back to default. */
+		  dev->if_port = vp->default_media;
+		  if (vortex_debug > 1)
+			pr_debug("%s: Media selection failing, using default %s port.\n",
+				   dev->name, media_tbl[dev->if_port].name);
+		} else {
+			if (vortex_debug > 1)
+				pr_debug("%s: Media selection failed, now trying %s port.\n",
+					   dev->name, media_tbl[dev->if_port].name);
+			next_tick = media_tbl[dev->if_port].wait;
+		}
+		window_write16(vp,
+			       (media_status & ~(Media_10TP|Media_SQE)) |
+			       media_tbl[dev->if_port].media_bits,
+			       4, Wn4_Media);
+
+		config = window_read32(vp, 3, Wn3_Config);
+		config = BFINS(config, dev->if_port, 20, 4);
+		window_write32(vp, config, 3, Wn3_Config);
+
+		iowrite16(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax,
+			 ioaddr + EL3_CMD);
+		if (vortex_debug > 1)
+			pr_debug("wrote 0x%08x to Wn3_Config\n", config);
+		/* AKPM: FIXME: Should reset Rx & Tx here.  P60 of 3c90xc.pdf */
+
+		spin_unlock_irq(&vp->lock);
+	}
+
+leave_media_alone:
+	if (vortex_debug > 2)
+	  pr_debug("%s: Media selection timer finished, %s.\n",
+			 dev->name, media_tbl[dev->if_port].name);
+
+	mod_timer(&vp->timer, RUN_AT(next_tick));
+	if (vp->deferred)
+		iowrite16(FakeIntr, ioaddr + EL3_CMD);
+}
+
+static void vortex_tx_timeout(struct net_device *dev)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	void __iomem *ioaddr = vp->ioaddr;
+
+	pr_err("%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
+		   dev->name, ioread8(ioaddr + TxStatus),
+		   ioread16(ioaddr + EL3_STATUS));
+	pr_err("  diagnostics: net %04x media %04x dma %08x fifo %04x\n",
+			window_read16(vp, 4, Wn4_NetDiag),
+			window_read16(vp, 4, Wn4_Media),
+			ioread32(ioaddr + PktStatus),
+			window_read16(vp, 4, Wn4_FIFODiag));
+	/* Slight code bloat to be user friendly. */
+	if ((ioread8(ioaddr + TxStatus) & 0x88) == 0x88)
+		pr_err("%s: Transmitter encountered 16 collisions --"
+			   " network cable problem?\n", dev->name);
+	if (ioread16(ioaddr + EL3_STATUS) & IntLatch) {
+		pr_err("%s: Interrupt posted but not delivered --"
+			   " IRQ blocked by another device?\n", dev->name);
+		/* Bad idea here.. but we might as well handle a few events. */
+		{
+			/*
+			 * Block interrupts because vortex_interrupt does a bare spin_lock()
+			 */
+			unsigned long flags;
+			local_irq_save(flags);
+			if (vp->full_bus_master_tx)
+				boomerang_interrupt(dev->irq, dev);
+			else
+				vortex_interrupt(dev->irq, dev);
+			local_irq_restore(flags);
+		}
+	}
+
+	if (vortex_debug > 0)
+		dump_tx_ring(dev);
+
+	issue_and_wait(dev, TxReset);
+
+	dev->stats.tx_errors++;
+	if (vp->full_bus_master_tx) {
+		pr_debug("%s: Resetting the Tx ring pointer.\n", dev->name);
+		if (vp->cur_tx - vp->dirty_tx > 0  &&  ioread32(ioaddr + DownListPtr) == 0)
+			iowrite32(vp->tx_ring_dma + (vp->dirty_tx % TX_RING_SIZE) * sizeof(struct boom_tx_desc),
+				 ioaddr + DownListPtr);
+		if (vp->cur_tx - vp->dirty_tx < TX_RING_SIZE)
+			netif_wake_queue (dev);
+		if (vp->drv_flags & IS_BOOMERANG)
+			iowrite8(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
+		iowrite16(DownUnstall, ioaddr + EL3_CMD);
+	} else {
+		dev->stats.tx_dropped++;
+		netif_wake_queue(dev);
+	}
+
+	/* Issue Tx Enable */
+	iowrite16(TxEnable, ioaddr + EL3_CMD);
+	dev->trans_start = jiffies; /* prevent tx timeout */
+}
+
+/*
+ * Handle uncommon interrupt sources.  This is a separate routine to minimize
+ * the cache impact.
+ */
+static void
+vortex_error(struct net_device *dev, int status)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	void __iomem *ioaddr = vp->ioaddr;
+	int do_tx_reset = 0, reset_mask = 0;
+	unsigned char tx_status = 0;
+
+	if (vortex_debug > 2) {
+		pr_err("%s: vortex_error(), status=0x%x\n", dev->name, status);
+	}
+
+	if (status & TxComplete) {			/* Really "TxError" for us. */
+		tx_status = ioread8(ioaddr + TxStatus);
+		/* Presumably a tx-timeout. We must merely re-enable. */
+		if (vortex_debug > 2 ||
+		    (tx_status != 0x88 && vortex_debug > 0)) {
+			pr_err("%s: Transmit error, Tx status register %2.2x.\n",
+				   dev->name, tx_status);
+			if (tx_status == 0x82) {
+				pr_err("Probably a duplex mismatch.  See "
+						"Documentation/networking/vortex.txt\n");
+			}
+			dump_tx_ring(dev);
+		}
+		if (tx_status & 0x14)  dev->stats.tx_fifo_errors++;
+		if (tx_status & 0x38)  dev->stats.tx_aborted_errors++;
+		if (tx_status & 0x08)  vp->xstats.tx_max_collisions++;
+		iowrite8(0, ioaddr + TxStatus);
+		if (tx_status & 0x30) {			/* txJabber or txUnderrun */
+			do_tx_reset = 1;
+		} else if ((tx_status & 0x08) && (vp->drv_flags & MAX_COLLISION_RESET))  {	/* maxCollisions */
+			do_tx_reset = 1;
+			reset_mask = 0x0108;		/* Reset interface logic, but not download logic */
+		} else {				/* Merely re-enable the transmitter. */
+			iowrite16(TxEnable, ioaddr + EL3_CMD);
+		}
+	}
+
+	if (status & RxEarly)				/* Rx early is unused. */
+		iowrite16(AckIntr | RxEarly, ioaddr + EL3_CMD);
+
+	if (status & StatsFull) {			/* Empty statistics. */
+		static int DoneDidThat;
+		if (vortex_debug > 4)
+			pr_debug("%s: Updating stats.\n", dev->name);
+		update_stats(ioaddr, dev);
+		/* HACK: Disable statistics as an interrupt source. */
+		/* This occurs when we have the wrong media type! */
+		if (DoneDidThat == 0  &&
+			ioread16(ioaddr + EL3_STATUS) & StatsFull) {
+			pr_warning("%s: Updating statistics failed, disabling "
+				   "stats as an interrupt source.\n", dev->name);
+			iowrite16(SetIntrEnb |
+				  (window_read16(vp, 5, 10) & ~StatsFull),
+				  ioaddr + EL3_CMD);
+			vp->intr_enable &= ~StatsFull;
+			DoneDidThat++;
+		}
+	}
+	if (status & IntReq) {		/* Restore all interrupt sources.  */
+		iowrite16(vp->status_enable, ioaddr + EL3_CMD);
+		iowrite16(vp->intr_enable, ioaddr + EL3_CMD);
+	}
+	if (status & HostError) {
+		u16 fifo_diag;
+		fifo_diag = window_read16(vp, 4, Wn4_FIFODiag);
+		pr_err("%s: Host error, FIFO diagnostic register %4.4x.\n",
+			   dev->name, fifo_diag);
+		/* Adapter failure requires Tx/Rx reset and reinit. */
+		if (vp->full_bus_master_tx) {
+			int bus_status = ioread32(ioaddr + PktStatus);
+			/* 0x80000000 PCI master abort. */
+			/* 0x40000000 PCI target abort. */
+			if (vortex_debug)
+				pr_err("%s: PCI bus error, bus status %8.8x\n", dev->name, bus_status);
+
+			/* In this case, blow the card away */
+			/* Must not enter D3 or we can't legally issue the reset! */
+			vortex_down(dev, 0);
+			issue_and_wait(dev, TotalReset | 0xff);
+			vortex_up(dev);		/* AKPM: bug.  vortex_up() assumes that the rx ring is full. It may not be. */
+		} else if (fifo_diag & 0x0400)
+			do_tx_reset = 1;
+		if (fifo_diag & 0x3000) {
+			/* Reset Rx fifo and upload logic */
+			issue_and_wait(dev, RxReset|0x07);
+			/* Set the Rx filter to the current state. */
+			set_rx_mode(dev);
+			/* enable 802.1q VLAN tagged frames */
+			set_8021q_mode(dev, 1);
+			iowrite16(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
+			iowrite16(AckIntr | HostError, ioaddr + EL3_CMD);
+		}
+	}
+
+	if (do_tx_reset) {
+		issue_and_wait(dev, TxReset|reset_mask);
+		iowrite16(TxEnable, ioaddr + EL3_CMD);
+		if (!vp->full_bus_master_tx)
+			netif_wake_queue(dev);
+	}
+}
+
+static netdev_tx_t
+vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	void __iomem *ioaddr = vp->ioaddr;
+
+	/* Put out the doubleword header... */
+	iowrite32(skb->len, ioaddr + TX_FIFO);
+	if (vp->bus_master) {
+		/* Set the bus-master controller to transfer the packet. */
+		int len = (skb->len + 3) & ~3;
+		vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len,
+						PCI_DMA_TODEVICE);
+		spin_lock_irq(&vp->window_lock);
+		window_set(vp, 7);
+		iowrite32(vp->tx_skb_dma, ioaddr + Wn7_MasterAddr);
+		iowrite16(len, ioaddr + Wn7_MasterLen);
+		spin_unlock_irq(&vp->window_lock);
+		vp->tx_skb = skb;
+		iowrite16(StartDMADown, ioaddr + EL3_CMD);
+		/* netif_wake_queue() will be called at the DMADone interrupt. */
+	} else {
+		/* ... and the packet rounded to a doubleword. */
+		iowrite32_rep(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+		dev_kfree_skb (skb);
+		if (ioread16(ioaddr + TxFree) > 1536) {
+			netif_start_queue (dev);	/* AKPM: redundant? */
+		} else {
+			/* Interrupt us when the FIFO has room for max-sized packet. */
+			netif_stop_queue(dev);
+			iowrite16(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+		}
+	}
+
+
+	/* Clear the Tx status stack. */
+	{
+		int tx_status;
+		int i = 32;
+
+		while (--i > 0	&&	(tx_status = ioread8(ioaddr + TxStatus)) > 0) {
+			if (tx_status & 0x3C) {		/* A Tx-disabling error occurred.  */
+				if (vortex_debug > 2)
+				  pr_debug("%s: Tx error, status %2.2x.\n",
+						 dev->name, tx_status);
+				if (tx_status & 0x04) dev->stats.tx_fifo_errors++;
+				if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
+				if (tx_status & 0x30) {
+					issue_and_wait(dev, TxReset);
+				}
+				iowrite16(TxEnable, ioaddr + EL3_CMD);
+			}
+			iowrite8(0x00, ioaddr + TxStatus); /* Pop the status stack. */
+		}
+	}
+	return NETDEV_TX_OK;
+}
+
+static netdev_tx_t
+boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	void __iomem *ioaddr = vp->ioaddr;
+	/* Calculate the next Tx descriptor entry. */
+	int entry = vp->cur_tx % TX_RING_SIZE;
+	struct boom_tx_desc *prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE];
+	unsigned long flags;
+
+	if (vortex_debug > 6) {
+		pr_debug("boomerang_start_xmit()\n");
+		pr_debug("%s: Trying to send a packet, Tx index %d.\n",
+			   dev->name, vp->cur_tx);
+	}
+
+	/*
+	 * We can't allow a recursion from our interrupt handler back into the
+	 * tx routine, as they take the same spin lock, and that causes
+	 * deadlock.  Just return NETDEV_TX_BUSY and let the stack try again in
+	 * a bit
+	 */
+	if (vp->handling_irq)
+		return NETDEV_TX_BUSY;
+
+	if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) {
+		if (vortex_debug > 0)
+			pr_warning("%s: BUG! Tx Ring full, refusing to send buffer.\n",
+				   dev->name);
+		netif_stop_queue(dev);
+		return NETDEV_TX_BUSY;
+	}
+
+	vp->tx_skbuff[entry] = skb;
+
+	vp->tx_ring[entry].next = 0;
+#if DO_ZEROCOPY
+	if (skb->ip_summed != CHECKSUM_PARTIAL)
+			vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
+	else
+			vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded | AddTCPChksum | AddUDPChksum);
+
+	if (!skb_shinfo(skb)->nr_frags) {
+		vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data,
+										skb->len, PCI_DMA_TODEVICE));
+		vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb->len | LAST_FRAG);
+	} else {
+		int i;
+
+		vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data,
+										skb_headlen(skb), PCI_DMA_TODEVICE));
+		vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb_headlen(skb));
+
+		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+			vp->tx_ring[entry].frag[i+1].addr =
+					cpu_to_le32(pci_map_single(
+						VORTEX_PCI(vp),
+						(void *)skb_frag_address(frag),
+						skb_frag_size(frag), PCI_DMA_TODEVICE));
+
+			if (i == skb_shinfo(skb)->nr_frags-1)
+					vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(skb_frag_size(frag)|LAST_FRAG);
+			else
+					vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(skb_frag_size(frag));
+		}
+	}
+#else
+	vp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, skb->len, PCI_DMA_TODEVICE));
+	vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
+	vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
+#endif
+
+	spin_lock_irqsave(&vp->lock, flags);
+	/* Wait for the stall to complete. */
+	issue_and_wait(dev, DownStall);
+	prev_entry->next = cpu_to_le32(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc));
+	if (ioread32(ioaddr + DownListPtr) == 0) {
+		iowrite32(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc), ioaddr + DownListPtr);
+		vp->queued_packet++;
+	}
+
+	vp->cur_tx++;
+	if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1) {
+		netif_stop_queue (dev);
+	} else {					/* Clear previous interrupt enable. */
+#if defined(tx_interrupt_mitigation)
+		/* Dubious. If in boomeang_interrupt "faster" cyclone ifdef
+		 * were selected, this would corrupt DN_COMPLETE. No?
+		 */
+		prev_entry->status &= cpu_to_le32(~TxIntrUploaded);
+#endif
+	}
+	iowrite16(DownUnstall, ioaddr + EL3_CMD);
+	spin_unlock_irqrestore(&vp->lock, flags);
+	return NETDEV_TX_OK;
+}
+
+/* The interrupt handler does all of the Rx thread work and cleans up
+   after the Tx thread. */
+
+/*
+ * This is the ISR for the vortex series chips.
+ * full_bus_master_tx == 0 && full_bus_master_rx == 0
+ */
+
+static irqreturn_t
+vortex_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct vortex_private *vp = netdev_priv(dev);
+	void __iomem *ioaddr;
+	int status;
+	int work_done = max_interrupt_work;
+	int handled = 0;
+
+	ioaddr = vp->ioaddr;
+	spin_lock(&vp->lock);
+
+	status = ioread16(ioaddr + EL3_STATUS);
+
+	if (vortex_debug > 6)
+		pr_debug("vortex_interrupt(). status=0x%4x\n", status);
+
+	if ((status & IntLatch) == 0)
+		goto handler_exit;		/* No interrupt: shared IRQs cause this */
+	handled = 1;
+
+	if (status & IntReq) {
+		status |= vp->deferred;
+		vp->deferred = 0;
+	}
+
+	if (status == 0xffff)		/* h/w no longer present (hotplug)? */
+		goto handler_exit;
+
+	if (vortex_debug > 4)
+		pr_debug("%s: interrupt, status %4.4x, latency %d ticks.\n",
+			   dev->name, status, ioread8(ioaddr + Timer));
+
+	spin_lock(&vp->window_lock);
+	window_set(vp, 7);
+
+	do {
+		if (vortex_debug > 5)
+				pr_debug("%s: In interrupt loop, status %4.4x.\n",
+					   dev->name, status);
+		if (status & RxComplete)
+			vortex_rx(dev);
+
+		if (status & TxAvailable) {
+			if (vortex_debug > 5)
+				pr_debug("	TX room bit was handled.\n");
+			/* There's room in the FIFO for a full-sized packet. */
+			iowrite16(AckIntr | TxAvailable, ioaddr + EL3_CMD);
+			netif_wake_queue (dev);
+		}
+
+		if (status & DMADone) {
+			if (ioread16(ioaddr + Wn7_MasterStatus) & 0x1000) {
+				iowrite16(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
+				pci_unmap_single(VORTEX_PCI(vp), vp->tx_skb_dma, (vp->tx_skb->len + 3) & ~3, PCI_DMA_TODEVICE);
+				dev_kfree_skb_irq(vp->tx_skb); /* Release the transferred buffer */
+				if (ioread16(ioaddr + TxFree) > 1536) {
+					/*
+					 * AKPM: FIXME: I don't think we need this.  If the queue was stopped due to
+					 * insufficient FIFO room, the TxAvailable test will succeed and call
+					 * netif_wake_queue()
+					 */
+					netif_wake_queue(dev);
+				} else { /* Interrupt when FIFO has room for max-sized packet. */
+					iowrite16(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+					netif_stop_queue(dev);
+				}
+			}
+		}
+		/* Check for all uncommon interrupts at once. */
+		if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) {
+			if (status == 0xffff)
+				break;
+			if (status & RxEarly)
+				vortex_rx(dev);
+			spin_unlock(&vp->window_lock);
+			vortex_error(dev, status);
+			spin_lock(&vp->window_lock);
+			window_set(vp, 7);
+		}
+
+		if (--work_done < 0) {
+			pr_warning("%s: Too much work in interrupt, status %4.4x.\n",
+				dev->name, status);
+			/* Disable all pending interrupts. */
+			do {
+				vp->deferred |= status;
+				iowrite16(SetStatusEnb | (~vp->deferred & vp->status_enable),
+					 ioaddr + EL3_CMD);
+				iowrite16(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
+			} while ((status = ioread16(ioaddr + EL3_CMD)) & IntLatch);
+			/* The timer will reenable interrupts. */
+			mod_timer(&vp->timer, jiffies + 1*HZ);
+			break;
+		}
+		/* Acknowledge the IRQ. */
+		iowrite16(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
+	} while ((status = ioread16(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
+
+	spin_unlock(&vp->window_lock);
+
+	if (vortex_debug > 4)
+		pr_debug("%s: exiting interrupt, status %4.4x.\n",
+			   dev->name, status);
+handler_exit:
+	spin_unlock(&vp->lock);
+	return IRQ_RETVAL(handled);
+}
+
+/*
+ * This is the ISR for the boomerang series chips.
+ * full_bus_master_tx == 1 && full_bus_master_rx == 1
+ */
+
+static irqreturn_t
+boomerang_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct vortex_private *vp = netdev_priv(dev);
+	void __iomem *ioaddr;
+	int status;
+	int work_done = max_interrupt_work;
+
+	ioaddr = vp->ioaddr;
+
+
+	/*
+	 * It seems dopey to put the spinlock this early, but we could race against vortex_tx_timeout
+	 * and boomerang_start_xmit
+	 */
+	spin_lock(&vp->lock);
+	vp->handling_irq = 1;
+
+	status = ioread16(ioaddr + EL3_STATUS);
+
+	if (vortex_debug > 6)
+		pr_debug("boomerang_interrupt. status=0x%4x\n", status);
+
+	if ((status & IntLatch) == 0)
+		goto handler_exit;		/* No interrupt: shared IRQs can cause this */
+
+	if (status == 0xffff) {		/* h/w no longer present (hotplug)? */
+		if (vortex_debug > 1)
+			pr_debug("boomerang_interrupt(1): status = 0xffff\n");
+		goto handler_exit;
+	}
+
+	if (status & IntReq) {
+		status |= vp->deferred;
+		vp->deferred = 0;
+	}
+
+	if (vortex_debug > 4)
+		pr_debug("%s: interrupt, status %4.4x, latency %d ticks.\n",
+			   dev->name, status, ioread8(ioaddr + Timer));
+	do {
+		if (vortex_debug > 5)
+				pr_debug("%s: In interrupt loop, status %4.4x.\n",
+					   dev->name, status);
+		if (status & UpComplete) {
+			iowrite16(AckIntr | UpComplete, ioaddr + EL3_CMD);
+			if (vortex_debug > 5)
+				pr_debug("boomerang_interrupt->boomerang_rx\n");
+			boomerang_rx(dev);
+		}
+
+		if (status & DownComplete) {
+			unsigned int dirty_tx = vp->dirty_tx;
+
+			iowrite16(AckIntr | DownComplete, ioaddr + EL3_CMD);
+			while (vp->cur_tx - dirty_tx > 0) {
+				int entry = dirty_tx % TX_RING_SIZE;
+#if 1	/* AKPM: the latter is faster, but cyclone-only */
+				if (ioread32(ioaddr + DownListPtr) ==
+					vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc))
+					break;			/* It still hasn't been processed. */
+#else
+				if ((vp->tx_ring[entry].status & DN_COMPLETE) == 0)
+					break;			/* It still hasn't been processed. */
+#endif
+
+				if (vp->tx_skbuff[entry]) {
+					struct sk_buff *skb = vp->tx_skbuff[entry];
+#if DO_ZEROCOPY
+					int i;
+					for (i=0; i<=skb_shinfo(skb)->nr_frags; i++)
+							pci_unmap_single(VORTEX_PCI(vp),
+											 le32_to_cpu(vp->tx_ring[entry].frag[i].addr),
+											 le32_to_cpu(vp->tx_ring[entry].frag[i].length)&0xFFF,
+											 PCI_DMA_TODEVICE);
+#else
+					pci_unmap_single(VORTEX_PCI(vp),
+						le32_to_cpu(vp->tx_ring[entry].addr), skb->len, PCI_DMA_TODEVICE);
+#endif
+					dev_kfree_skb_irq(skb);
+					vp->tx_skbuff[entry] = NULL;
+				} else {
+					pr_debug("boomerang_interrupt: no skb!\n");
+				}
+				/* dev->stats.tx_packets++;  Counted below. */
+				dirty_tx++;
+			}
+			vp->dirty_tx = dirty_tx;
+			if (vp->cur_tx - dirty_tx <= TX_RING_SIZE - 1) {
+				if (vortex_debug > 6)
+					pr_debug("boomerang_interrupt: wake queue\n");
+				netif_wake_queue (dev);
+			}
+		}
+
+		/* Check for all uncommon interrupts at once. */
+		if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq))
+			vortex_error(dev, status);
+
+		if (--work_done < 0) {
+			pr_warning("%s: Too much work in interrupt, status %4.4x.\n",
+				dev->name, status);
+			/* Disable all pending interrupts. */
+			do {
+				vp->deferred |= status;
+				iowrite16(SetStatusEnb | (~vp->deferred & vp->status_enable),
+					 ioaddr + EL3_CMD);
+				iowrite16(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
+			} while ((status = ioread16(ioaddr + EL3_CMD)) & IntLatch);
+			/* The timer will reenable interrupts. */
+			mod_timer(&vp->timer, jiffies + 1*HZ);
+			break;
+		}
+		/* Acknowledge the IRQ. */
+		iowrite16(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
+		if (vp->cb_fn_base)			/* The PCMCIA people are idiots.  */
+			iowrite32(0x8000, vp->cb_fn_base + 4);
+
+	} while ((status = ioread16(ioaddr + EL3_STATUS)) & IntLatch);
+
+	if (vortex_debug > 4)
+		pr_debug("%s: exiting interrupt, status %4.4x.\n",
+			   dev->name, status);
+handler_exit:
+	vp->handling_irq = 0;
+	spin_unlock(&vp->lock);
+	return IRQ_HANDLED;
+}
+
+static int vortex_rx(struct net_device *dev)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	void __iomem *ioaddr = vp->ioaddr;
+	int i;
+	short rx_status;
+
+	if (vortex_debug > 5)
+		pr_debug("vortex_rx(): status %4.4x, rx_status %4.4x.\n",
+			   ioread16(ioaddr+EL3_STATUS), ioread16(ioaddr+RxStatus));
+	while ((rx_status = ioread16(ioaddr + RxStatus)) > 0) {
+		if (rx_status & 0x4000) { /* Error, update stats. */
+			unsigned char rx_error = ioread8(ioaddr + RxErrors);
+			if (vortex_debug > 2)
+				pr_debug(" Rx error: status %2.2x.\n", rx_error);
+			dev->stats.rx_errors++;
+			if (rx_error & 0x01)  dev->stats.rx_over_errors++;
+			if (rx_error & 0x02)  dev->stats.rx_length_errors++;
+			if (rx_error & 0x04)  dev->stats.rx_frame_errors++;
+			if (rx_error & 0x08)  dev->stats.rx_crc_errors++;
+			if (rx_error & 0x10)  dev->stats.rx_length_errors++;
+		} else {
+			/* The packet length: up to 4.5K!. */
+			int pkt_len = rx_status & 0x1fff;
+			struct sk_buff *skb;
+
+			skb = dev_alloc_skb(pkt_len + 5);
+			if (vortex_debug > 4)
+				pr_debug("Receiving packet size %d status %4.4x.\n",
+					   pkt_len, rx_status);
+			if (skb != NULL) {
+				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
+				/* 'skb_put()' points to the start of sk_buff data area. */
+				if (vp->bus_master &&
+					! (ioread16(ioaddr + Wn7_MasterStatus) & 0x8000)) {
+					dma_addr_t dma = pci_map_single(VORTEX_PCI(vp), skb_put(skb, pkt_len),
+									   pkt_len, PCI_DMA_FROMDEVICE);
+					iowrite32(dma, ioaddr + Wn7_MasterAddr);
+					iowrite16((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
+					iowrite16(StartDMAUp, ioaddr + EL3_CMD);
+					while (ioread16(ioaddr + Wn7_MasterStatus) & 0x8000)
+						;
+					pci_unmap_single(VORTEX_PCI(vp), dma, pkt_len, PCI_DMA_FROMDEVICE);
+				} else {
+					ioread32_rep(ioaddr + RX_FIFO,
+					             skb_put(skb, pkt_len),
+						     (pkt_len + 3) >> 2);
+				}
+				iowrite16(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
+				skb->protocol = eth_type_trans(skb, dev);
+				netif_rx(skb);
+				dev->stats.rx_packets++;
+				/* Wait a limited time to go to next packet. */
+				for (i = 200; i >= 0; i--)
+					if ( ! (ioread16(ioaddr + EL3_STATUS) & CmdInProgress))
+						break;
+				continue;
+			} else if (vortex_debug > 0)
+				pr_notice("%s: No memory to allocate a sk_buff of size %d.\n",
+					dev->name, pkt_len);
+			dev->stats.rx_dropped++;
+		}
+		issue_and_wait(dev, RxDiscard);
+	}
+
+	return 0;
+}
+
+static int
+boomerang_rx(struct net_device *dev)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	int entry = vp->cur_rx % RX_RING_SIZE;
+	void __iomem *ioaddr = vp->ioaddr;
+	int rx_status;
+	int rx_work_limit = vp->dirty_rx + RX_RING_SIZE - vp->cur_rx;
+
+	if (vortex_debug > 5)
+		pr_debug("boomerang_rx(): status %4.4x\n", ioread16(ioaddr+EL3_STATUS));
+
+	while ((rx_status = le32_to_cpu(vp->rx_ring[entry].status)) & RxDComplete){
+		if (--rx_work_limit < 0)
+			break;
+		if (rx_status & RxDError) { /* Error, update stats. */
+			unsigned char rx_error = rx_status >> 16;
+			if (vortex_debug > 2)
+				pr_debug(" Rx error: status %2.2x.\n", rx_error);
+			dev->stats.rx_errors++;
+			if (rx_error & 0x01)  dev->stats.rx_over_errors++;
+			if (rx_error & 0x02)  dev->stats.rx_length_errors++;
+			if (rx_error & 0x04)  dev->stats.rx_frame_errors++;
+			if (rx_error & 0x08)  dev->stats.rx_crc_errors++;
+			if (rx_error & 0x10)  dev->stats.rx_length_errors++;
+		} else {
+			/* The packet length: up to 4.5K!. */
+			int pkt_len = rx_status & 0x1fff;
+			struct sk_buff *skb;
+			dma_addr_t dma = le32_to_cpu(vp->rx_ring[entry].addr);
+
+			if (vortex_debug > 4)
+				pr_debug("Receiving packet size %d status %4.4x.\n",
+					   pkt_len, rx_status);
+
+			/* Check if the packet is long enough to just accept without
+			   copying to a properly sized skbuff. */
+			if (pkt_len < rx_copybreak && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
+				pci_dma_sync_single_for_cpu(VORTEX_PCI(vp), dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+				/* 'skb_put()' points to the start of sk_buff data area. */
+				memcpy(skb_put(skb, pkt_len),
+					   vp->rx_skbuff[entry]->data,
+					   pkt_len);
+				pci_dma_sync_single_for_device(VORTEX_PCI(vp), dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+				vp->rx_copy++;
+			} else {
+				/* Pass up the skbuff already on the Rx ring. */
+				skb = vp->rx_skbuff[entry];
+				vp->rx_skbuff[entry] = NULL;
+				skb_put(skb, pkt_len);
+				pci_unmap_single(VORTEX_PCI(vp), dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+				vp->rx_nocopy++;
+			}
+			skb->protocol = eth_type_trans(skb, dev);
+			{					/* Use hardware checksum info. */
+				int csum_bits = rx_status & 0xee000000;
+				if (csum_bits &&
+					(csum_bits == (IPChksumValid | TCPChksumValid) ||
+					 csum_bits == (IPChksumValid | UDPChksumValid))) {
+					skb->ip_summed = CHECKSUM_UNNECESSARY;
+					vp->rx_csumhits++;
+				}
+			}
+			netif_rx(skb);
+			dev->stats.rx_packets++;
+		}
+		entry = (++vp->cur_rx) % RX_RING_SIZE;
+	}
+	/* Refill the Rx ring buffers. */
+	for (; vp->cur_rx - vp->dirty_rx > 0; vp->dirty_rx++) {
+		struct sk_buff *skb;
+		entry = vp->dirty_rx % RX_RING_SIZE;
+		if (vp->rx_skbuff[entry] == NULL) {
+			skb = netdev_alloc_skb_ip_align(dev, PKT_BUF_SZ);
+			if (skb == NULL) {
+				static unsigned long last_jif;
+				if (time_after(jiffies, last_jif + 10 * HZ)) {
+					pr_warning("%s: memory shortage\n", dev->name);
+					last_jif = jiffies;
+				}
+				if ((vp->cur_rx - vp->dirty_rx) == RX_RING_SIZE)
+					mod_timer(&vp->rx_oom_timer, RUN_AT(HZ * 1));
+				break;			/* Bad news!  */
+			}
+
+			vp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));
+			vp->rx_skbuff[entry] = skb;
+		}
+		vp->rx_ring[entry].status = 0;	/* Clear complete bit. */
+		iowrite16(UpUnstall, ioaddr + EL3_CMD);
+	}
+	return 0;
+}
+
+/*
+ * If we've hit a total OOM refilling the Rx ring we poll once a second
+ * for some memory.  Otherwise there is no way to restart the rx process.
+ */
+static void
+rx_oom_timer(unsigned long arg)
+{
+	struct net_device *dev = (struct net_device *)arg;
+	struct vortex_private *vp = netdev_priv(dev);
+
+	spin_lock_irq(&vp->lock);
+	if ((vp->cur_rx - vp->dirty_rx) == RX_RING_SIZE)	/* This test is redundant, but makes me feel good */
+		boomerang_rx(dev);
+	if (vortex_debug > 1) {
+		pr_debug("%s: rx_oom_timer %s\n", dev->name,
+			((vp->cur_rx - vp->dirty_rx) != RX_RING_SIZE) ? "succeeded" : "retrying");
+	}
+	spin_unlock_irq(&vp->lock);
+}
+
+static void
+vortex_down(struct net_device *dev, int final_down)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	void __iomem *ioaddr = vp->ioaddr;
+
+	netif_stop_queue (dev);
+
+	del_timer_sync(&vp->rx_oom_timer);
+	del_timer_sync(&vp->timer);
+
+	/* Turn off statistics ASAP.  We update dev->stats below. */
+	iowrite16(StatsDisable, ioaddr + EL3_CMD);
+
+	/* Disable the receiver and transmitter. */
+	iowrite16(RxDisable, ioaddr + EL3_CMD);
+	iowrite16(TxDisable, ioaddr + EL3_CMD);
+
+	/* Disable receiving 802.1q tagged frames */
+	set_8021q_mode(dev, 0);
+
+	if (dev->if_port == XCVR_10base2)
+		/* Turn off thinnet power.  Green! */
+		iowrite16(StopCoax, ioaddr + EL3_CMD);
+
+	iowrite16(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
+
+	update_stats(ioaddr, dev);
+	if (vp->full_bus_master_rx)
+		iowrite32(0, ioaddr + UpListPtr);
+	if (vp->full_bus_master_tx)
+		iowrite32(0, ioaddr + DownListPtr);
+
+	if (final_down && VORTEX_PCI(vp)) {
+		vp->pm_state_valid = 1;
+		pci_save_state(VORTEX_PCI(vp));
+		acpi_set_WOL(dev);
+	}
+}
+
+static int
+vortex_close(struct net_device *dev)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	void __iomem *ioaddr = vp->ioaddr;
+	int i;
+
+	if (netif_device_present(dev))
+		vortex_down(dev, 1);
+
+	if (vortex_debug > 1) {
+		pr_debug("%s: vortex_close() status %4.4x, Tx status %2.2x.\n",
+			   dev->name, ioread16(ioaddr + EL3_STATUS), ioread8(ioaddr + TxStatus));
+		pr_debug("%s: vortex close stats: rx_nocopy %d rx_copy %d"
+			   " tx_queued %d Rx pre-checksummed %d.\n",
+			   dev->name, vp->rx_nocopy, vp->rx_copy, vp->queued_packet, vp->rx_csumhits);
+	}
+
+#if DO_ZEROCOPY
+	if (vp->rx_csumhits &&
+	    (vp->drv_flags & HAS_HWCKSM) == 0 &&
+	    (vp->card_idx >= MAX_UNITS || hw_checksums[vp->card_idx] == -1)) {
+		pr_warning("%s supports hardware checksums, and we're not using them!\n", dev->name);
+	}
+#endif
+
+	free_irq(dev->irq, dev);
+
+	if (vp->full_bus_master_rx) { /* Free Boomerang bus master Rx buffers. */
+		for (i = 0; i < RX_RING_SIZE; i++)
+			if (vp->rx_skbuff[i]) {
+				pci_unmap_single(	VORTEX_PCI(vp), le32_to_cpu(vp->rx_ring[i].addr),
+									PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+				dev_kfree_skb(vp->rx_skbuff[i]);
+				vp->rx_skbuff[i] = NULL;
+			}
+	}
+	if (vp->full_bus_master_tx) { /* Free Boomerang bus master Tx buffers. */
+		for (i = 0; i < TX_RING_SIZE; i++) {
+			if (vp->tx_skbuff[i]) {
+				struct sk_buff *skb = vp->tx_skbuff[i];
+#if DO_ZEROCOPY
+				int k;
+
+				for (k=0; k<=skb_shinfo(skb)->nr_frags; k++)
+						pci_unmap_single(VORTEX_PCI(vp),
+										 le32_to_cpu(vp->tx_ring[i].frag[k].addr),
+										 le32_to_cpu(vp->tx_ring[i].frag[k].length)&0xFFF,
+										 PCI_DMA_TODEVICE);
+#else
+				pci_unmap_single(VORTEX_PCI(vp), le32_to_cpu(vp->tx_ring[i].addr), skb->len, PCI_DMA_TODEVICE);
+#endif
+				dev_kfree_skb(skb);
+				vp->tx_skbuff[i] = NULL;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static void
+dump_tx_ring(struct net_device *dev)
+{
+	if (vortex_debug > 0) {
+	struct vortex_private *vp = netdev_priv(dev);
+		void __iomem *ioaddr = vp->ioaddr;
+
+		if (vp->full_bus_master_tx) {
+			int i;
+			int stalled = ioread32(ioaddr + PktStatus) & 0x04;	/* Possible racy. But it's only debug stuff */
+
+			pr_err("  Flags; bus-master %d, dirty %d(%d) current %d(%d)\n",
+					vp->full_bus_master_tx,
+					vp->dirty_tx, vp->dirty_tx % TX_RING_SIZE,
+					vp->cur_tx, vp->cur_tx % TX_RING_SIZE);
+			pr_err("  Transmit list %8.8x vs. %p.\n",
+				   ioread32(ioaddr + DownListPtr),
+				   &vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]);
+			issue_and_wait(dev, DownStall);
+			for (i = 0; i < TX_RING_SIZE; i++) {
+				unsigned int length;
+
+#if DO_ZEROCOPY
+				length = le32_to_cpu(vp->tx_ring[i].frag[0].length);
+#else
+				length = le32_to_cpu(vp->tx_ring[i].length);
+#endif
+				pr_err("  %d: @%p  length %8.8x status %8.8x\n",
+					   i, &vp->tx_ring[i], length,
+					   le32_to_cpu(vp->tx_ring[i].status));
+			}
+			if (!stalled)
+				iowrite16(DownUnstall, ioaddr + EL3_CMD);
+		}
+	}
+}
+
+static struct net_device_stats *vortex_get_stats(struct net_device *dev)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	void __iomem *ioaddr = vp->ioaddr;
+	unsigned long flags;
+
+	if (netif_device_present(dev)) {	/* AKPM: Used to be netif_running */
+		spin_lock_irqsave (&vp->lock, flags);
+		update_stats(ioaddr, dev);
+		spin_unlock_irqrestore (&vp->lock, flags);
+	}
+	return &dev->stats;
+}
+
+/*  Update statistics.
+	Unlike with the EL3 we need not worry about interrupts changing
+	the window setting from underneath us, but we must still guard
+	against a race condition with a StatsUpdate interrupt updating the
+	table.  This is done by checking that the ASM (!) code generated uses
+	atomic updates with '+='.
+	*/
+static void update_stats(void __iomem *ioaddr, struct net_device *dev)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+
+	/* Unlike the 3c5x9 we need not turn off stats updates while reading. */
+	/* Switch to the stats window, and read everything. */
+	dev->stats.tx_carrier_errors		+= window_read8(vp, 6, 0);
+	dev->stats.tx_heartbeat_errors		+= window_read8(vp, 6, 1);
+	dev->stats.tx_window_errors		+= window_read8(vp, 6, 4);
+	dev->stats.rx_fifo_errors		+= window_read8(vp, 6, 5);
+	dev->stats.tx_packets			+= window_read8(vp, 6, 6);
+	dev->stats.tx_packets			+= (window_read8(vp, 6, 9) &
+						    0x30) << 4;
+	/* Rx packets	*/			window_read8(vp, 6, 7);   /* Must read to clear */
+	/* Don't bother with register 9, an extension of registers 6&7.
+	   If we do use the 6&7 values the atomic update assumption above
+	   is invalid. */
+	dev->stats.rx_bytes 			+= window_read16(vp, 6, 10);
+	dev->stats.tx_bytes 			+= window_read16(vp, 6, 12);
+	/* Extra stats for get_ethtool_stats() */
+	vp->xstats.tx_multiple_collisions	+= window_read8(vp, 6, 2);
+	vp->xstats.tx_single_collisions         += window_read8(vp, 6, 3);
+	vp->xstats.tx_deferred			+= window_read8(vp, 6, 8);
+	vp->xstats.rx_bad_ssd			+= window_read8(vp, 4, 12);
+
+	dev->stats.collisions = vp->xstats.tx_multiple_collisions
+		+ vp->xstats.tx_single_collisions
+		+ vp->xstats.tx_max_collisions;
+
+	{
+		u8 up = window_read8(vp, 4, 13);
+		dev->stats.rx_bytes += (up & 0x0f) << 16;
+		dev->stats.tx_bytes += (up & 0xf0) << 12;
+	}
+}
+
+static int vortex_nway_reset(struct net_device *dev)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+
+	return mii_nway_restart(&vp->mii);
+}
+
+static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+
+	return mii_ethtool_gset(&vp->mii, cmd);
+}
+
+static int vortex_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+
+	return mii_ethtool_sset(&vp->mii, cmd);
+}
+
+static u32 vortex_get_msglevel(struct net_device *dev)
+{
+	return vortex_debug;
+}
+
+static void vortex_set_msglevel(struct net_device *dev, u32 dbg)
+{
+	vortex_debug = dbg;
+}
+
+static int vortex_get_sset_count(struct net_device *dev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS:
+		return VORTEX_NUM_STATS;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void vortex_get_ethtool_stats(struct net_device *dev,
+	struct ethtool_stats *stats, u64 *data)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	void __iomem *ioaddr = vp->ioaddr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vp->lock, flags);
+	update_stats(ioaddr, dev);
+	spin_unlock_irqrestore(&vp->lock, flags);
+
+	data[0] = vp->xstats.tx_deferred;
+	data[1] = vp->xstats.tx_max_collisions;
+	data[2] = vp->xstats.tx_multiple_collisions;
+	data[3] = vp->xstats.tx_single_collisions;
+	data[4] = vp->xstats.rx_bad_ssd;
+}
+
+
+static void vortex_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+	switch (stringset) {
+	case ETH_SS_STATS:
+		memcpy(data, &ethtool_stats_keys, sizeof(ethtool_stats_keys));
+		break;
+	default:
+		WARN_ON(1);
+		break;
+	}
+}
+
+static void vortex_get_drvinfo(struct net_device *dev,
+					struct ethtool_drvinfo *info)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+
+	strcpy(info->driver, DRV_NAME);
+	if (VORTEX_PCI(vp)) {
+		strcpy(info->bus_info, pci_name(VORTEX_PCI(vp)));
+	} else {
+		if (VORTEX_EISA(vp))
+			strcpy(info->bus_info, dev_name(vp->gendev));
+		else
+			sprintf(info->bus_info, "EISA 0x%lx %d",
+					dev->base_addr, dev->irq);
+	}
+}
+
+static void vortex_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+
+	if (!VORTEX_PCI(vp))
+		return;
+
+	wol->supported = WAKE_MAGIC;
+
+	wol->wolopts = 0;
+	if (vp->enable_wol)
+		wol->wolopts |= WAKE_MAGIC;
+}
+
+static int vortex_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+
+	if (!VORTEX_PCI(vp))
+		return -EOPNOTSUPP;
+
+	if (wol->wolopts & ~WAKE_MAGIC)
+		return -EINVAL;
+
+	if (wol->wolopts & WAKE_MAGIC)
+		vp->enable_wol = 1;
+	else
+		vp->enable_wol = 0;
+	acpi_set_WOL(dev);
+
+	return 0;
+}
+
+static const struct ethtool_ops vortex_ethtool_ops = {
+	.get_drvinfo		= vortex_get_drvinfo,
+	.get_strings            = vortex_get_strings,
+	.get_msglevel           = vortex_get_msglevel,
+	.set_msglevel           = vortex_set_msglevel,
+	.get_ethtool_stats      = vortex_get_ethtool_stats,
+	.get_sset_count		= vortex_get_sset_count,
+	.get_settings           = vortex_get_settings,
+	.set_settings           = vortex_set_settings,
+	.get_link               = ethtool_op_get_link,
+	.nway_reset             = vortex_nway_reset,
+	.get_wol                = vortex_get_wol,
+	.set_wol                = vortex_set_wol,
+};
+
+#ifdef CONFIG_PCI
+/*
+ *	Must power the device up to do MDIO operations
+ */
+static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int err;
+	struct vortex_private *vp = netdev_priv(dev);
+	pci_power_t state = 0;
+
+	if(VORTEX_PCI(vp))
+		state = VORTEX_PCI(vp)->current_state;
+
+	/* The kernel core really should have pci_get_power_state() */
+
+	if(state != 0)
+		pci_set_power_state(VORTEX_PCI(vp), PCI_D0);
+	err = generic_mii_ioctl(&vp->mii, if_mii(rq), cmd, NULL);
+	if(state != 0)
+		pci_set_power_state(VORTEX_PCI(vp), state);
+
+	return err;
+}
+#endif
+
+
+/* Pre-Cyclone chips have no documented multicast filter, so the only
+   multicast setting is to receive all multicast frames.  At least
+   the chip has a very clean way to set the mode, unlike many others. */
+static void set_rx_mode(struct net_device *dev)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	void __iomem *ioaddr = vp->ioaddr;
+	int new_mode;
+
+	if (dev->flags & IFF_PROMISC) {
+		if (vortex_debug > 3)
+			pr_notice("%s: Setting promiscuous mode.\n", dev->name);
+		new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast|RxProm;
+	} else	if (!netdev_mc_empty(dev) || dev->flags & IFF_ALLMULTI) {
+		new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast;
+	} else
+		new_mode = SetRxFilter | RxStation | RxBroadcast;
+
+	iowrite16(new_mode, ioaddr + EL3_CMD);
+}
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+/* Setup the card so that it can receive frames with an 802.1q VLAN tag.
+   Note that this must be done after each RxReset due to some backwards
+   compatibility logic in the Cyclone and Tornado ASICs */
+
+/* The Ethernet Type used for 802.1q tagged frames */
+#define VLAN_ETHER_TYPE 0x8100
+
+static void set_8021q_mode(struct net_device *dev, int enable)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	int mac_ctrl;
+
+	if ((vp->drv_flags&IS_CYCLONE) || (vp->drv_flags&IS_TORNADO)) {
+		/* cyclone and tornado chipsets can recognize 802.1q
+		 * tagged frames and treat them correctly */
+
+		int max_pkt_size = dev->mtu+14;	/* MTU+Ethernet header */
+		if (enable)
+			max_pkt_size += 4;	/* 802.1Q VLAN tag */
+
+		window_write16(vp, max_pkt_size, 3, Wn3_MaxPktSize);
+
+		/* set VlanEtherType to let the hardware checksumming
+		   treat tagged frames correctly */
+		window_write16(vp, VLAN_ETHER_TYPE, 7, Wn7_VlanEtherType);
+	} else {
+		/* on older cards we have to enable large frames */
+
+		vp->large_frames = dev->mtu > 1500 || enable;
+
+		mac_ctrl = window_read16(vp, 3, Wn3_MAC_Ctrl);
+		if (vp->large_frames)
+			mac_ctrl |= 0x40;
+		else
+			mac_ctrl &= ~0x40;
+		window_write16(vp, mac_ctrl, 3, Wn3_MAC_Ctrl);
+	}
+}
+#else
+
+static void set_8021q_mode(struct net_device *dev, int enable)
+{
+}
+
+
+#endif
+
+/* MII transceiver control section.
+   Read and write the MII registers using software-generated serial
+   MDIO protocol.  See the MII specifications or DP83840A data sheet
+   for details. */
+
+/* The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
+   met by back-to-back PCI I/O cycles, but we insert a delay to avoid
+   "overclocking" issues. */
+static void mdio_delay(struct vortex_private *vp)
+{
+	window_read32(vp, 4, Wn4_PhysicalMgmt);
+}
+
+#define MDIO_SHIFT_CLK	0x01
+#define MDIO_DIR_WRITE	0x04
+#define MDIO_DATA_WRITE0 (0x00 | MDIO_DIR_WRITE)
+#define MDIO_DATA_WRITE1 (0x02 | MDIO_DIR_WRITE)
+#define MDIO_DATA_READ	0x02
+#define MDIO_ENB_IN		0x00
+
+/* Generate the preamble required for initial synchronization and
+   a few older transceivers. */
+static void mdio_sync(struct vortex_private *vp, int bits)
+{
+	/* Establish sync by sending at least 32 logic ones. */
+	while (-- bits >= 0) {
+		window_write16(vp, MDIO_DATA_WRITE1, 4, Wn4_PhysicalMgmt);
+		mdio_delay(vp);
+		window_write16(vp, MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK,
+			       4, Wn4_PhysicalMgmt);
+		mdio_delay(vp);
+	}
+}
+
+static int mdio_read(struct net_device *dev, int phy_id, int location)
+{
+	int i;
+	struct vortex_private *vp = netdev_priv(dev);
+	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+	unsigned int retval = 0;
+
+	spin_lock_bh(&vp->mii_lock);
+
+	if (mii_preamble_required)
+		mdio_sync(vp, 32);
+
+	/* Shift the read command bits out. */
+	for (i = 14; i >= 0; i--) {
+		int dataval = (read_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+		window_write16(vp, dataval, 4, Wn4_PhysicalMgmt);
+		mdio_delay(vp);
+		window_write16(vp, dataval | MDIO_SHIFT_CLK,
+			       4, Wn4_PhysicalMgmt);
+		mdio_delay(vp);
+	}
+	/* Read the two transition, 16 data, and wire-idle bits. */
+	for (i = 19; i > 0; i--) {
+		window_write16(vp, MDIO_ENB_IN, 4, Wn4_PhysicalMgmt);
+		mdio_delay(vp);
+		retval = (retval << 1) |
+			((window_read16(vp, 4, Wn4_PhysicalMgmt) &
+			  MDIO_DATA_READ) ? 1 : 0);
+		window_write16(vp, MDIO_ENB_IN | MDIO_SHIFT_CLK,
+			       4, Wn4_PhysicalMgmt);
+		mdio_delay(vp);
+	}
+
+	spin_unlock_bh(&vp->mii_lock);
+
+	return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff;
+}
+
+static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
+	int i;
+
+	spin_lock_bh(&vp->mii_lock);
+
+	if (mii_preamble_required)
+		mdio_sync(vp, 32);
+
+	/* Shift the command bits out. */
+	for (i = 31; i >= 0; i--) {
+		int dataval = (write_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+		window_write16(vp, dataval, 4, Wn4_PhysicalMgmt);
+		mdio_delay(vp);
+		window_write16(vp, dataval | MDIO_SHIFT_CLK,
+			       4, Wn4_PhysicalMgmt);
+		mdio_delay(vp);
+	}
+	/* Leave the interface idle. */
+	for (i = 1; i >= 0; i--) {
+		window_write16(vp, MDIO_ENB_IN, 4, Wn4_PhysicalMgmt);
+		mdio_delay(vp);
+		window_write16(vp, MDIO_ENB_IN | MDIO_SHIFT_CLK,
+			       4, Wn4_PhysicalMgmt);
+		mdio_delay(vp);
+	}
+
+	spin_unlock_bh(&vp->mii_lock);
+}
+
+/* ACPI: Advanced Configuration and Power Interface. */
+/* Set Wake-On-LAN mode and put the board into D3 (power-down) state. */
+static void acpi_set_WOL(struct net_device *dev)
+{
+	struct vortex_private *vp = netdev_priv(dev);
+	void __iomem *ioaddr = vp->ioaddr;
+
+	device_set_wakeup_enable(vp->gendev, vp->enable_wol);
+
+	if (vp->enable_wol) {
+		/* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */
+		window_write16(vp, 2, 7, 0x0c);
+		/* The RxFilter must accept the WOL frames. */
+		iowrite16(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
+		iowrite16(RxEnable, ioaddr + EL3_CMD);
+
+		if (pci_enable_wake(VORTEX_PCI(vp), PCI_D3hot, 1)) {
+			pr_info("%s: WOL not supported.\n", pci_name(VORTEX_PCI(vp)));
+
+			vp->enable_wol = 0;
+			return;
+		}
+
+		if (VORTEX_PCI(vp)->current_state < PCI_D3hot)
+			return;
+
+		/* Change the power state to D3; RxEnable doesn't take effect. */
+		pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot);
+	}
+}
+
+
+static void __devexit vortex_remove_one(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct vortex_private *vp;
+
+	if (!dev) {
+		pr_err("vortex_remove_one called for Compaq device!\n");
+		BUG();
+	}
+
+	vp = netdev_priv(dev);
+
+	if (vp->cb_fn_base)
+		pci_iounmap(VORTEX_PCI(vp), vp->cb_fn_base);
+
+	unregister_netdev(dev);
+
+	if (VORTEX_PCI(vp)) {
+		pci_set_power_state(VORTEX_PCI(vp), PCI_D0);	/* Go active */
+		if (vp->pm_state_valid)
+			pci_restore_state(VORTEX_PCI(vp));
+		pci_disable_device(VORTEX_PCI(vp));
+	}
+	/* Should really use issue_and_wait() here */
+	iowrite16(TotalReset | ((vp->drv_flags & EEPROM_RESET) ? 0x04 : 0x14),
+	     vp->ioaddr + EL3_CMD);
+
+	pci_iounmap(VORTEX_PCI(vp), vp->ioaddr);
+
+	pci_free_consistent(pdev,
+						sizeof(struct boom_rx_desc) * RX_RING_SIZE
+							+ sizeof(struct boom_tx_desc) * TX_RING_SIZE,
+						vp->rx_ring,
+						vp->rx_ring_dma);
+	if (vp->must_free_region)
+		release_region(dev->base_addr, vp->io_size);
+	free_netdev(dev);
+}
+
+
+static struct pci_driver vortex_driver = {
+	.name		= "3c59x",
+	.probe		= vortex_init_one,
+	.remove		= __devexit_p(vortex_remove_one),
+	.id_table	= vortex_pci_tbl,
+	.driver.pm	= VORTEX_PM_OPS,
+};
+
+
+static int vortex_have_pci;
+static int vortex_have_eisa;
+
+
+static int __init vortex_init(void)
+{
+	int pci_rc, eisa_rc;
+
+	pci_rc = pci_register_driver(&vortex_driver);
+	eisa_rc = vortex_eisa_init();
+
+	if (pci_rc == 0)
+		vortex_have_pci = 1;
+	if (eisa_rc > 0)
+		vortex_have_eisa = 1;
+
+	return (vortex_have_pci + vortex_have_eisa) ? 0 : -ENODEV;
+}
+
+
+static void __exit vortex_eisa_cleanup(void)
+{
+	struct vortex_private *vp;
+	void __iomem *ioaddr;
+
+#ifdef CONFIG_EISA
+	/* Take care of the EISA devices */
+	eisa_driver_unregister(&vortex_eisa_driver);
+#endif
+
+	if (compaq_net_device) {
+		vp = netdev_priv(compaq_net_device);
+		ioaddr = ioport_map(compaq_net_device->base_addr,
+		                    VORTEX_TOTAL_SIZE);
+
+		unregister_netdev(compaq_net_device);
+		iowrite16(TotalReset, ioaddr + EL3_CMD);
+		release_region(compaq_net_device->base_addr,
+		               VORTEX_TOTAL_SIZE);
+
+		free_netdev(compaq_net_device);
+	}
+}
+
+
+static void __exit vortex_cleanup(void)
+{
+	if (vortex_have_pci)
+		pci_unregister_driver(&vortex_driver);
+	if (vortex_have_eisa)
+		vortex_eisa_cleanup();
+}
+
+
+module_init(vortex_init);
+module_exit(vortex_cleanup);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/3com/Kconfig linux-libre-3.2-gnu/drivers/net/ethernet/3com/Kconfig
--- linux-libre-3.1-gnu/drivers/net/ethernet/3com/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/3com/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,122 @@
+#
+# 3Com Ethernet device configuration
+#
+
+config NET_VENDOR_3COM
+	bool "3Com devices"
+	default y
+	depends on ISA || EISA || MCA || PCI || PCMCIA
+	---help---
+	  If you have a network (Ethernet) card belonging to this class, say Y
+	  and read the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  Note that the answer to this question doesn't directly affect the
+	  kernel: saying N will just cause the configurator to skip all
+	  the questions about 3Com cards. If you say Y, you will be asked for
+	  your specific card in the following questions.
+
+if NET_VENDOR_3COM
+
+config EL1
+	tristate "3c501 \"EtherLink\" support"
+	depends on ISA
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.  Also, consider buying a
+	  new card, since the 3c501 is slow, broken, and obsolete: you will
+	  have problems.  Some people suggest to ping ("man ping") a nearby
+	  machine every minute ("man cron") when using this card.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called 3c501.
+
+config EL3
+	tristate "3c509/3c529 (MCA)/3c579 \"EtherLink III\" support"
+	depends on (ISA || EISA || MCA)
+	---help---
+	  If you have a network (Ethernet) card belonging to the 3Com
+	  EtherLinkIII series, say Y and read the Ethernet-HOWTO, available
+	  from <http://www.tldp.org/docs.html#howto>.
+
+	  If your card is not working you may need to use the DOS
+	  setup disk to disable Plug & Play mode, and to select the default
+	  media type.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called 3c509.
+
+config 3C515
+	tristate "3c515 ISA \"Fast EtherLink\""
+	depends on (ISA || EISA) && ISA_DMA_API
+	---help---
+	  If you have a 3Com ISA EtherLink XL "Corkscrew" 3c515 Fast Ethernet
+	  network card, say Y and read the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called 3c515.
+
+config PCMCIA_3C574
+	tristate "3Com 3c574 PCMCIA support"
+	depends on PCMCIA
+	---help---
+	  Say Y here if you intend to attach a 3Com 3c574 or compatible PCMCIA
+	  (PC-card) Fast Ethernet card to your computer.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called 3c574_cs.  If unsure, say N.
+
+config PCMCIA_3C589
+	tristate "3Com 3c589 PCMCIA support"
+	depends on PCMCIA
+	---help---
+	  Say Y here if you intend to attach a 3Com 3c589 or compatible PCMCIA
+	  (PC-card) Ethernet card to your computer.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called 3c589_cs.  If unsure, say N.
+
+config VORTEX
+	tristate "3c590/3c900 series (592/595/597) \"Vortex/Boomerang\" support"
+	depends on (PCI || EISA)
+	select NET_CORE
+	select MII
+	---help---
+	  This option enables driver support for a large number of 10Mbps and
+	  10/100Mbps EISA, PCI and PCMCIA 3Com network cards:
+
+	  "Vortex"    (Fast EtherLink 3c590/3c592/3c595/3c597) EISA and PCI
+	  "Boomerang" (EtherLink XL 3c900 or 3c905)            PCI
+	  "Cyclone"   (3c540/3c900/3c905/3c980/3c575/3c656)    PCI and Cardbus
+	  "Tornado"   (3c905)                                  PCI
+	  "Hurricane" (3c555/3cSOHO)                           PCI
+
+	  If you have such a card, say Y and read the Ethernet-HOWTO,
+	  available from <http://www.tldp.org/docs.html#howto>. More
+	  specific information is in
+	  <file:Documentation/networking/vortex.txt> and in the comments at
+	  the beginning of <file:drivers/net/3c59x.c>.
+
+	  To compile this support as a module, choose M here.
+
+config TYPHOON
+	tristate "3cr990 series \"Typhoon\" support"
+	depends on PCI
+	select CRC32
+	---help---
+	  This option enables driver support for the 3cr990 series of cards:
+
+	  3C990-TX, 3CR990-TX-95, 3CR990-TX-97, 3CR990-FX-95, 3CR990-FX-97,
+	  3CR990SVR, 3CR990SVR95, 3CR990SVR97, 3CR990-FX-95 Server,
+	  3CR990-FX-97 Server, 3C990B-TX-M, 3C990BSVR
+
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called typhoon.
+
+endif # NET_VENDOR_3COM
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/3com/Makefile linux-libre-3.2-gnu/drivers/net/ethernet/3com/Makefile
--- linux-libre-3.1-gnu/drivers/net/ethernet/3com/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/3com/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,11 @@
+#
+# Makefile for the 3Com Ethernet device drivers
+#
+
+obj-$(CONFIG_EL1) += 3c501.o
+obj-$(CONFIG_EL3) += 3c509.o
+obj-$(CONFIG_3C515) += 3c515.o
+obj-$(CONFIG_PCMCIA_3C589) += 3c589_cs.o
+obj-$(CONFIG_PCMCIA_3C574) += 3c574_cs.o
+obj-$(CONFIG_VORTEX) += 3c59x.o
+obj-$(CONFIG_TYPHOON) += typhoon.o
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/3com/typhoon.c linux-libre-3.2-gnu/drivers/net/ethernet/3com/typhoon.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/3com/typhoon.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/3com/typhoon.c	2012-03-19 21:50:04.000000000 -0400
@@ -0,0 +1,2569 @@
+/* typhoon.c: A Linux Ethernet device driver for 3Com 3CR990 family of NICs */
+/*
+	Written 2002-2004 by David Dillow <dave@thedillows.org>
+	Based on code written 1998-2000 by Donald Becker <becker@scyld.com> and
+	Linux 2.2.x driver by David P. McLean <davidpmclean@yahoo.com>.
+
+	This software may be used and distributed according to the terms of
+	the GNU General Public License (GPL), incorporated herein by reference.
+	Drivers based on or derived from this code fall under the GPL and must
+	retain the authorship, copyright and license notice.  This file is not
+	a complete program and may only be used when the entire operating
+	system is licensed under the GPL.
+
+	This software is available on a public web site. It may enable
+	cryptographic capabilities of the 3Com hardware, and may be
+	exported from the United States under License Exception "TSU"
+	pursuant to 15 C.F.R. Section 740.13(e).
+
+	This work was funded by the National Library of Medicine under
+	the Department of Energy project number 0274DD06D1 and NLM project
+	number Y1-LM-2015-01.
+
+	This driver is designed for the 3Com 3CR990 Family of cards with the
+	3XP Processor. It has been tested on x86 and sparc64.
+
+	KNOWN ISSUES:
+	*) Cannot DMA Rx packets to a 2 byte aligned address. Also firmware
+		issue. Hopefully 3Com will fix it.
+	*) Waiting for a command response takes 8ms due to non-preemptable
+		polling. Only significant for getting stats and creating
+		SAs, but an ugly wart never the less.
+
+	TODO:
+	*) Doesn't do IPSEC offloading. Yet. Keep yer pants on, it's coming.
+	*) Add more support for ethtool (especially for NIC stats)
+	*) Allow disabling of RX checksum offloading
+	*) Fix MAC changing to work while the interface is up
+		(Need to put commands on the TX ring, which changes
+		the locking)
+	*) Add in FCS to {rx,tx}_bytes, since the hardware doesn't. See
+		http://oss.sgi.com/cgi-bin/mesg.cgi?a=netdev&i=20031215152211.7003fe8e.rddunlap%40osdl.org
+*/
+
+/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
+ * Setting to > 1518 effectively disables this feature.
+ */
+static int rx_copybreak = 200;
+
+/* Should we use MMIO or Port IO?
+ * 0: Port IO
+ * 1: MMIO
+ * 2: Try MMIO, fallback to Port IO
+ */
+static unsigned int use_mmio = 2;
+
+/* end user-configurable values */
+
+/* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
+ */
+static const int multicast_filter_limit = 32;
+
+/* Operational parameters that are set at compile time. */
+
+/* Keep the ring sizes a power of two for compile efficiency.
+ * The compiler will convert <unsigned>'%'<2^N> into a bit mask.
+ * Making the Tx ring too large decreases the effectiveness of channel
+ * bonding and packet priority.
+ * There are no ill effects from too-large receive rings.
+ *
+ * We don't currently use the Hi Tx ring so, don't make it very big.
+ *
+ * Beware that if we start using the Hi Tx ring, we will need to change
+ * typhoon_num_free_tx() and typhoon_tx_complete() to account for that.
+ */
+#define TXHI_ENTRIES		2
+#define TXLO_ENTRIES		128
+#define RX_ENTRIES		32
+#define COMMAND_ENTRIES		16
+#define RESPONSE_ENTRIES	32
+
+#define COMMAND_RING_SIZE	(COMMAND_ENTRIES * sizeof(struct cmd_desc))
+#define RESPONSE_RING_SIZE	(RESPONSE_ENTRIES * sizeof(struct resp_desc))
+
+/* The 3XP will preload and remove 64 entries from the free buffer
+ * list, and we need one entry to keep the ring from wrapping, so
+ * to keep this a power of two, we use 128 entries.
+ */
+#define RXFREE_ENTRIES		128
+#define RXENT_ENTRIES		(RXFREE_ENTRIES - 1)
+
+/* Operational parameters that usually are not changed. */
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  (2*HZ)
+
+#define PKT_BUF_SZ		1536
+#define FIRMWARE_NAME		"/*(DEBLOBBED)*/"
+
+#define pr_fmt(fmt)		KBUILD_MODNAME " " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/crc32.h>
+#include <linux/bitops.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/in6.h>
+#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
+
+#include "typhoon.h"
+
+MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
+/*(DEBLOBBED)*/
+MODULE_DESCRIPTION("3Com Typhoon Family (3C990, 3CR990, and variants)");
+MODULE_PARM_DESC(rx_copybreak, "Packets smaller than this are copied and "
+			       "the buffer given back to the NIC. Default "
+			       "is 200.");
+MODULE_PARM_DESC(use_mmio, "Use MMIO (1) or PIO(0) to access the NIC. "
+			   "Default is to try MMIO and fallback to PIO.");
+module_param(rx_copybreak, int, 0);
+module_param(use_mmio, int, 0);
+
+#if defined(NETIF_F_TSO) && MAX_SKB_FRAGS > 32
+#warning Typhoon only supports 32 entries in its SG list for TSO, disabling TSO
+#undef NETIF_F_TSO
+#endif
+
+#if TXLO_ENTRIES <= (2 * MAX_SKB_FRAGS)
+#error TX ring too small!
+#endif
+
+struct typhoon_card_info {
+	const char *name;
+	const int capabilities;
+};
+
+#define TYPHOON_CRYPTO_NONE		0x00
+#define TYPHOON_CRYPTO_DES		0x01
+#define TYPHOON_CRYPTO_3DES		0x02
+#define	TYPHOON_CRYPTO_VARIABLE		0x04
+#define TYPHOON_FIBER			0x08
+#define TYPHOON_WAKEUP_NEEDS_RESET	0x10
+
+enum typhoon_cards {
+	TYPHOON_TX = 0, TYPHOON_TX95, TYPHOON_TX97, TYPHOON_SVR,
+	TYPHOON_SVR95, TYPHOON_SVR97, TYPHOON_TXM, TYPHOON_BSVR,
+	TYPHOON_FX95, TYPHOON_FX97, TYPHOON_FX95SVR, TYPHOON_FX97SVR,
+	TYPHOON_FXM,
+};
+
+/* directly indexed by enum typhoon_cards, above */
+static struct typhoon_card_info typhoon_card_info[] __devinitdata = {
+	{ "3Com Typhoon (3C990-TX)",
+		TYPHOON_CRYPTO_NONE},
+	{ "3Com Typhoon (3CR990-TX-95)",
+		TYPHOON_CRYPTO_DES},
+	{ "3Com Typhoon (3CR990-TX-97)",
+	 	TYPHOON_CRYPTO_DES | TYPHOON_CRYPTO_3DES},
+	{ "3Com Typhoon (3C990SVR)",
+		TYPHOON_CRYPTO_NONE},
+	{ "3Com Typhoon (3CR990SVR95)",
+		TYPHOON_CRYPTO_DES},
+	{ "3Com Typhoon (3CR990SVR97)",
+	 	TYPHOON_CRYPTO_DES | TYPHOON_CRYPTO_3DES},
+	{ "3Com Typhoon2 (3C990B-TX-M)",
+		TYPHOON_CRYPTO_VARIABLE},
+	{ "3Com Typhoon2 (3C990BSVR)",
+		TYPHOON_CRYPTO_VARIABLE},
+	{ "3Com Typhoon (3CR990-FX-95)",
+		TYPHOON_CRYPTO_DES | TYPHOON_FIBER},
+	{ "3Com Typhoon (3CR990-FX-97)",
+	 	TYPHOON_CRYPTO_DES | TYPHOON_CRYPTO_3DES | TYPHOON_FIBER},
+	{ "3Com Typhoon (3CR990-FX-95 Server)",
+	 	TYPHOON_CRYPTO_DES | TYPHOON_FIBER},
+	{ "3Com Typhoon (3CR990-FX-97 Server)",
+	 	TYPHOON_CRYPTO_DES | TYPHOON_CRYPTO_3DES | TYPHOON_FIBER},
+	{ "3Com Typhoon2 (3C990B-FX-97)",
+		TYPHOON_CRYPTO_VARIABLE | TYPHOON_FIBER},
+};
+
+/* Notes on the new subsystem numbering scheme:
+ * bits 0-1 indicate crypto capabilities: (0) variable, (1) DES, or (2) 3DES
+ * bit 4 indicates if this card has secured firmware (we don't support it)
+ * bit 8 indicates if this is a (0) copper or (1) fiber card
+ * bits 12-16 indicate card type: (0) client and (1) server
+ */
+static DEFINE_PCI_DEVICE_TABLE(typhoon_pci_tbl) = {
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0,TYPHOON_TX },
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990_TX_95,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPHOON_TX95 },
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990_TX_97,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPHOON_TX97 },
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990B,
+	  PCI_ANY_ID, 0x1000, 0, 0, TYPHOON_TXM },
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990B,
+	  PCI_ANY_ID, 0x1102, 0, 0, TYPHOON_FXM },
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990B,
+	  PCI_ANY_ID, 0x2000, 0, 0, TYPHOON_BSVR },
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990_FX,
+	  PCI_ANY_ID, 0x1101, 0, 0, TYPHOON_FX95 },
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990_FX,
+	  PCI_ANY_ID, 0x1102, 0, 0, TYPHOON_FX97 },
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990_FX,
+	  PCI_ANY_ID, 0x2101, 0, 0, TYPHOON_FX95SVR },
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990_FX,
+	  PCI_ANY_ID, 0x2102, 0, 0, TYPHOON_FX97SVR },
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990SVR95,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPHOON_SVR95 },
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990SVR97,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPHOON_SVR97 },
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990SVR,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPHOON_SVR },
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, typhoon_pci_tbl);
+
+/* Define the shared memory area
+ * Align everything the 3XP will normally be using.
+ * We'll need to move/align txHi if we start using that ring.
+ */
+#define __3xp_aligned	____cacheline_aligned
+struct typhoon_shared {
+	struct typhoon_interface	iface;
+	struct typhoon_indexes		indexes			__3xp_aligned;
+	struct tx_desc			txLo[TXLO_ENTRIES] 	__3xp_aligned;
+	struct rx_desc			rxLo[RX_ENTRIES]	__3xp_aligned;
+	struct rx_desc			rxHi[RX_ENTRIES]	__3xp_aligned;
+	struct cmd_desc			cmd[COMMAND_ENTRIES]	__3xp_aligned;
+	struct resp_desc		resp[RESPONSE_ENTRIES]	__3xp_aligned;
+	struct rx_free			rxBuff[RXFREE_ENTRIES]	__3xp_aligned;
+	u32				zeroWord;
+	struct tx_desc			txHi[TXHI_ENTRIES];
+} __packed;
+
+struct rxbuff_ent {
+	struct sk_buff *skb;
+	dma_addr_t	dma_addr;
+};
+
+struct typhoon {
+	/* Tx cache line section */
+	struct transmit_ring 	txLoRing	____cacheline_aligned;
+	struct pci_dev *	tx_pdev;
+	void __iomem		*tx_ioaddr;
+	u32			txlo_dma_addr;
+
+	/* Irq/Rx cache line section */
+	void __iomem		*ioaddr		____cacheline_aligned;
+	struct typhoon_indexes *indexes;
+	u8			awaiting_resp;
+	u8			duplex;
+	u8			speed;
+	u8			card_state;
+	struct basic_ring	rxLoRing;
+	struct pci_dev *	pdev;
+	struct net_device *	dev;
+	struct napi_struct	napi;
+	struct basic_ring	rxHiRing;
+	struct basic_ring	rxBuffRing;
+	struct rxbuff_ent	rxbuffers[RXENT_ENTRIES];
+
+	/* general section */
+	spinlock_t		command_lock	____cacheline_aligned;
+	struct basic_ring	cmdRing;
+	struct basic_ring	respRing;
+	struct net_device_stats	stats;
+	struct net_device_stats	stats_saved;
+	struct typhoon_shared *	shared;
+	dma_addr_t		shared_dma;
+	__le16			xcvr_select;
+	__le16			wol_events;
+	__le32			offload;
+
+	/* unused stuff (future use) */
+	int			capabilities;
+	struct transmit_ring 	txHiRing;
+};
+
+enum completion_wait_values {
+	NoWait = 0, WaitNoSleep, WaitSleep,
+};
+
+/* These are the values for the typhoon.card_state variable.
+ * These determine where the statistics will come from in get_stats().
+ * The sleep image does not support the statistics we need.
+ */
+enum state_values {
+	Sleeping = 0, Running,
+};
+
+/* PCI writes are not guaranteed to be posted in order, but outstanding writes
+ * cannot pass a read, so this forces current writes to post.
+ */
+#define typhoon_post_pci_writes(x) \
+	do { if(likely(use_mmio)) ioread32(x+TYPHOON_REG_HEARTBEAT); } while(0)
+
+/* We'll wait up to six seconds for a reset, and half a second normally.
+ */
+#define TYPHOON_UDELAY			50
+#define TYPHOON_RESET_TIMEOUT_SLEEP	(6 * HZ)
+#define TYPHOON_RESET_TIMEOUT_NOSLEEP	((6 * 1000000) / TYPHOON_UDELAY)
+#define TYPHOON_WAIT_TIMEOUT		((1000000 / 2) / TYPHOON_UDELAY)
+
+#if defined(NETIF_F_TSO)
+#define skb_tso_size(x)		(skb_shinfo(x)->gso_size)
+#define TSO_NUM_DESCRIPTORS	2
+#define TSO_OFFLOAD_ON		TYPHOON_OFFLOAD_TCP_SEGMENT
+#else
+#define NETIF_F_TSO 		0
+#define skb_tso_size(x) 	0
+#define TSO_NUM_DESCRIPTORS	0
+#define TSO_OFFLOAD_ON		0
+#endif
+
+static inline void
+typhoon_inc_index(u32 *index, const int count, const int num_entries)
+{
+	/* Increment a ring index -- we can use this for all rings execept
+	 * the Rx rings, as they use different size descriptors
+	 * otherwise, everything is the same size as a cmd_desc
+	 */
+	*index += count * sizeof(struct cmd_desc);
+	*index %= num_entries * sizeof(struct cmd_desc);
+}
+
+static inline void
+typhoon_inc_cmd_index(u32 *index, const int count)
+{
+	typhoon_inc_index(index, count, COMMAND_ENTRIES);
+}
+
+static inline void
+typhoon_inc_resp_index(u32 *index, const int count)
+{
+	typhoon_inc_index(index, count, RESPONSE_ENTRIES);
+}
+
+static inline void
+typhoon_inc_rxfree_index(u32 *index, const int count)
+{
+	typhoon_inc_index(index, count, RXFREE_ENTRIES);
+}
+
+static inline void
+typhoon_inc_tx_index(u32 *index, const int count)
+{
+	/* if we start using the Hi Tx ring, this needs updateing */
+	typhoon_inc_index(index, count, TXLO_ENTRIES);
+}
+
+static inline void
+typhoon_inc_rx_index(u32 *index, const int count)
+{
+	/* sizeof(struct rx_desc) != sizeof(struct cmd_desc) */
+	*index += count * sizeof(struct rx_desc);
+	*index %= RX_ENTRIES * sizeof(struct rx_desc);
+}
+
+static int
+typhoon_reset(void __iomem *ioaddr, int wait_type)
+{
+	int i, err = 0;
+	int timeout;
+
+	if(wait_type == WaitNoSleep)
+		timeout = TYPHOON_RESET_TIMEOUT_NOSLEEP;
+	else
+		timeout = TYPHOON_RESET_TIMEOUT_SLEEP;
+
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
+
+	iowrite32(TYPHOON_RESET_ALL, ioaddr + TYPHOON_REG_SOFT_RESET);
+	typhoon_post_pci_writes(ioaddr);
+	udelay(1);
+	iowrite32(TYPHOON_RESET_NONE, ioaddr + TYPHOON_REG_SOFT_RESET);
+
+	if(wait_type != NoWait) {
+		for(i = 0; i < timeout; i++) {
+			if(ioread32(ioaddr + TYPHOON_REG_STATUS) ==
+			   TYPHOON_STATUS_WAITING_FOR_HOST)
+				goto out;
+
+			if(wait_type == WaitSleep)
+				schedule_timeout_uninterruptible(1);
+			else
+				udelay(TYPHOON_UDELAY);
+		}
+
+		err = -ETIMEDOUT;
+	}
+
+out:
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
+
+	/* The 3XP seems to need a little extra time to complete the load
+	 * of the sleep image before we can reliably boot it. Failure to
+	 * do this occasionally results in a hung adapter after boot in
+	 * typhoon_init_one() while trying to read the MAC address or
+	 * putting the card to sleep. 3Com's driver waits 5ms, but
+	 * that seems to be overkill. However, if we can sleep, we might
+	 * as well give it that much time. Otherwise, we'll give it 500us,
+	 * which should be enough (I've see it work well at 100us, but still
+	 * saw occasional problems.)
+	 */
+	if(wait_type == WaitSleep)
+		msleep(5);
+	else
+		udelay(500);
+	return err;
+}
+
+static int
+typhoon_wait_status(void __iomem *ioaddr, u32 wait_value)
+{
+	int i, err = 0;
+
+	for(i = 0; i < TYPHOON_WAIT_TIMEOUT; i++) {
+		if(ioread32(ioaddr + TYPHOON_REG_STATUS) == wait_value)
+			goto out;
+		udelay(TYPHOON_UDELAY);
+	}
+
+	err = -ETIMEDOUT;
+
+out:
+	return err;
+}
+
+static inline void
+typhoon_media_status(struct net_device *dev, struct resp_desc *resp)
+{
+	if(resp->parm1 & TYPHOON_MEDIA_STAT_NO_LINK)
+		netif_carrier_off(dev);
+	else
+		netif_carrier_on(dev);
+}
+
+static inline void
+typhoon_hello(struct typhoon *tp)
+{
+	struct basic_ring *ring = &tp->cmdRing;
+	struct cmd_desc *cmd;
+
+	/* We only get a hello request if we've not sent anything to the
+	 * card in a long while. If the lock is held, then we're in the
+	 * process of issuing a command, so we don't need to respond.
+	 */
+	if(spin_trylock(&tp->command_lock)) {
+		cmd = (struct cmd_desc *)(ring->ringBase + ring->lastWrite);
+		typhoon_inc_cmd_index(&ring->lastWrite, 1);
+
+		INIT_COMMAND_NO_RESPONSE(cmd, TYPHOON_CMD_HELLO_RESP);
+		wmb();
+		iowrite32(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY);
+		spin_unlock(&tp->command_lock);
+	}
+}
+
+static int
+typhoon_process_response(struct typhoon *tp, int resp_size,
+				struct resp_desc *resp_save)
+{
+	struct typhoon_indexes *indexes = tp->indexes;
+	struct resp_desc *resp;
+	u8 *base = tp->respRing.ringBase;
+	int count, len, wrap_len;
+	u32 cleared;
+	u32 ready;
+
+	cleared = le32_to_cpu(indexes->respCleared);
+	ready = le32_to_cpu(indexes->respReady);
+	while(cleared != ready) {
+		resp = (struct resp_desc *)(base + cleared);
+		count = resp->numDesc + 1;
+		if(resp_save && resp->seqNo) {
+			if(count > resp_size) {
+				resp_save->flags = TYPHOON_RESP_ERROR;
+				goto cleanup;
+			}
+
+			wrap_len = 0;
+			len = count * sizeof(*resp);
+			if(unlikely(cleared + len > RESPONSE_RING_SIZE)) {
+				wrap_len = cleared + len - RESPONSE_RING_SIZE;
+				len = RESPONSE_RING_SIZE - cleared;
+			}
+
+			memcpy(resp_save, resp, len);
+			if(unlikely(wrap_len)) {
+				resp_save += len / sizeof(*resp);
+				memcpy(resp_save, base, wrap_len);
+			}
+
+			resp_save = NULL;
+		} else if(resp->cmd == TYPHOON_CMD_READ_MEDIA_STATUS) {
+			typhoon_media_status(tp->dev, resp);
+		} else if(resp->cmd == TYPHOON_CMD_HELLO_RESP) {
+			typhoon_hello(tp);
+		} else {
+			netdev_err(tp->dev,
+				   "dumping unexpected response 0x%04x:%d:0x%02x:0x%04x:%08x:%08x\n",
+				   le16_to_cpu(resp->cmd),
+				   resp->numDesc, resp->flags,
+				   le16_to_cpu(resp->parm1),
+				   le32_to_cpu(resp->parm2),
+				   le32_to_cpu(resp->parm3));
+		}
+
+cleanup:
+		typhoon_inc_resp_index(&cleared, count);
+	}
+
+	indexes->respCleared = cpu_to_le32(cleared);
+	wmb();
+	return resp_save == NULL;
+}
+
+static inline int
+typhoon_num_free(int lastWrite, int lastRead, int ringSize)
+{
+	/* this works for all descriptors but rx_desc, as they are a
+	 * different size than the cmd_desc -- everyone else is the same
+	 */
+	lastWrite /= sizeof(struct cmd_desc);
+	lastRead /= sizeof(struct cmd_desc);
+	return (ringSize + lastRead - lastWrite - 1) % ringSize;
+}
+
+static inline int
+typhoon_num_free_cmd(struct typhoon *tp)
+{
+	int lastWrite = tp->cmdRing.lastWrite;
+	int cmdCleared = le32_to_cpu(tp->indexes->cmdCleared);
+
+	return typhoon_num_free(lastWrite, cmdCleared, COMMAND_ENTRIES);
+}
+
+static inline int
+typhoon_num_free_resp(struct typhoon *tp)
+{
+	int respReady = le32_to_cpu(tp->indexes->respReady);
+	int respCleared = le32_to_cpu(tp->indexes->respCleared);
+
+	return typhoon_num_free(respReady, respCleared, RESPONSE_ENTRIES);
+}
+
+static inline int
+typhoon_num_free_tx(struct transmit_ring *ring)
+{
+	/* if we start using the Hi Tx ring, this needs updating */
+	return typhoon_num_free(ring->lastWrite, ring->lastRead, TXLO_ENTRIES);
+}
+
+static int
+typhoon_issue_command(struct typhoon *tp, int num_cmd, struct cmd_desc *cmd,
+		      int num_resp, struct resp_desc *resp)
+{
+	struct typhoon_indexes *indexes = tp->indexes;
+	struct basic_ring *ring = &tp->cmdRing;
+	struct resp_desc local_resp;
+	int i, err = 0;
+	int got_resp;
+	int freeCmd, freeResp;
+	int len, wrap_len;
+
+	spin_lock(&tp->command_lock);
+
+	freeCmd = typhoon_num_free_cmd(tp);
+	freeResp = typhoon_num_free_resp(tp);
+
+	if(freeCmd < num_cmd || freeResp < num_resp) {
+		netdev_err(tp->dev, "no descs for cmd, had (needed) %d (%d) cmd, %d (%d) resp\n",
+			   freeCmd, num_cmd, freeResp, num_resp);
+		err = -ENOMEM;
+		goto out;
+	}
+
+	if(cmd->flags & TYPHOON_CMD_RESPOND) {
+		/* If we're expecting a response, but the caller hasn't given
+		 * us a place to put it, we'll provide one.
+		 */
+		tp->awaiting_resp = 1;
+		if(resp == NULL) {
+			resp = &local_resp;
+			num_resp = 1;
+		}
+	}
+
+	wrap_len = 0;
+	len = num_cmd * sizeof(*cmd);
+	if(unlikely(ring->lastWrite + len > COMMAND_RING_SIZE)) {
+		wrap_len = ring->lastWrite + len - COMMAND_RING_SIZE;
+		len = COMMAND_RING_SIZE - ring->lastWrite;
+	}
+
+	memcpy(ring->ringBase + ring->lastWrite, cmd, len);
+	if(unlikely(wrap_len)) {
+		struct cmd_desc *wrap_ptr = cmd;
+		wrap_ptr += len / sizeof(*cmd);
+		memcpy(ring->ringBase, wrap_ptr, wrap_len);
+	}
+
+	typhoon_inc_cmd_index(&ring->lastWrite, num_cmd);
+
+	/* "I feel a presence... another warrior is on the mesa."
+	 */
+	wmb();
+	iowrite32(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY);
+	typhoon_post_pci_writes(tp->ioaddr);
+
+	if((cmd->flags & TYPHOON_CMD_RESPOND) == 0)
+		goto out;
+
+	/* Ugh. We'll be here about 8ms, spinning our thumbs, unable to
+	 * preempt or do anything other than take interrupts. So, don't
+	 * wait for a response unless you have to.
+	 *
+	 * I've thought about trying to sleep here, but we're called
+	 * from many contexts that don't allow that. Also, given the way
+	 * 3Com has implemented irq coalescing, we would likely timeout --
+	 * this has been observed in real life!
+	 *
+	 * The big killer is we have to wait to get stats from the card,
+	 * though we could go to a periodic refresh of those if we don't
+	 * mind them getting somewhat stale. The rest of the waiting
+	 * commands occur during open/close/suspend/resume, so they aren't
+	 * time critical. Creating SAs in the future will also have to
+	 * wait here.
+	 */
+	got_resp = 0;
+	for(i = 0; i < TYPHOON_WAIT_TIMEOUT && !got_resp; i++) {
+		if(indexes->respCleared != indexes->respReady)
+			got_resp = typhoon_process_response(tp, num_resp,
+								resp);
+		udelay(TYPHOON_UDELAY);
+	}
+
+	if(!got_resp) {
+		err = -ETIMEDOUT;
+		goto out;
+	}
+
+	/* Collect the error response even if we don't care about the
+	 * rest of the response
+	 */
+	if(resp->flags & TYPHOON_RESP_ERROR)
+		err = -EIO;
+
+out:
+	if(tp->awaiting_resp) {
+		tp->awaiting_resp = 0;
+		smp_wmb();
+
+		/* Ugh. If a response was added to the ring between
+		 * the call to typhoon_process_response() and the clearing
+		 * of tp->awaiting_resp, we could have missed the interrupt
+		 * and it could hang in the ring an indeterminate amount of
+		 * time. So, check for it, and interrupt ourselves if this
+		 * is the case.
+		 */
+		if(indexes->respCleared != indexes->respReady)
+			iowrite32(1, tp->ioaddr + TYPHOON_REG_SELF_INTERRUPT);
+	}
+
+	spin_unlock(&tp->command_lock);
+	return err;
+}
+
+static inline void
+typhoon_tso_fill(struct sk_buff *skb, struct transmit_ring *txRing,
+			u32 ring_dma)
+{
+	struct tcpopt_desc *tcpd;
+	u32 tcpd_offset = ring_dma;
+
+	tcpd = (struct tcpopt_desc *) (txRing->ringBase + txRing->lastWrite);
+	tcpd_offset += txRing->lastWrite;
+	tcpd_offset += offsetof(struct tcpopt_desc, bytesTx);
+	typhoon_inc_tx_index(&txRing->lastWrite, 1);
+
+	tcpd->flags = TYPHOON_OPT_DESC | TYPHOON_OPT_TCP_SEG;
+	tcpd->numDesc = 1;
+	tcpd->mss_flags = cpu_to_le16(skb_tso_size(skb));
+	tcpd->mss_flags |= TYPHOON_TSO_FIRST | TYPHOON_TSO_LAST;
+	tcpd->respAddrLo = cpu_to_le32(tcpd_offset);
+	tcpd->bytesTx = cpu_to_le32(skb->len);
+	tcpd->status = 0;
+}
+
+static netdev_tx_t
+typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	struct typhoon *tp = netdev_priv(dev);
+	struct transmit_ring *txRing;
+	struct tx_desc *txd, *first_txd;
+	dma_addr_t skb_dma;
+	int numDesc;
+
+	/* we have two rings to choose from, but we only use txLo for now
+	 * If we start using the Hi ring as well, we'll need to update
+	 * typhoon_stop_runtime(), typhoon_interrupt(), typhoon_num_free_tx(),
+	 * and TXHI_ENTRIES to match, as well as update the TSO code below
+	 * to get the right DMA address
+	 */
+	txRing = &tp->txLoRing;
+
+	/* We need one descriptor for each fragment of the sk_buff, plus the
+	 * one for the ->data area of it.
+	 *
+	 * The docs say a maximum of 16 fragment descriptors per TCP option
+	 * descriptor, then make a new packet descriptor and option descriptor
+	 * for the next 16 fragments. The engineers say just an option
+	 * descriptor is needed. I've tested up to 26 fragments with a single
+	 * packet descriptor/option descriptor combo, so I use that for now.
+	 *
+	 * If problems develop with TSO, check this first.
+	 */
+	numDesc = skb_shinfo(skb)->nr_frags + 1;
+	if (skb_is_gso(skb))
+		numDesc++;
+
+	/* When checking for free space in the ring, we need to also
+	 * account for the initial Tx descriptor, and we always must leave
+	 * at least one descriptor unused in the ring so that it doesn't
+	 * wrap and look empty.
+	 *
+	 * The only time we should loop here is when we hit the race
+	 * between marking the queue awake and updating the cleared index.
+	 * Just loop and it will appear. This comes from the acenic driver.
+	 */
+	while(unlikely(typhoon_num_free_tx(txRing) < (numDesc + 2)))
+		smp_rmb();
+
+	first_txd = (struct tx_desc *) (txRing->ringBase + txRing->lastWrite);
+	typhoon_inc_tx_index(&txRing->lastWrite, 1);
+
+	first_txd->flags = TYPHOON_TX_DESC | TYPHOON_DESC_VALID;
+	first_txd->numDesc = 0;
+	first_txd->len = 0;
+	first_txd->tx_addr = (u64)((unsigned long) skb);
+	first_txd->processFlags = 0;
+
+	if(skb->ip_summed == CHECKSUM_PARTIAL) {
+		/* The 3XP will figure out if this is UDP/TCP */
+		first_txd->processFlags |= TYPHOON_TX_PF_TCP_CHKSUM;
+		first_txd->processFlags |= TYPHOON_TX_PF_UDP_CHKSUM;
+		first_txd->processFlags |= TYPHOON_TX_PF_IP_CHKSUM;
+	}
+
+	if(vlan_tx_tag_present(skb)) {
+		first_txd->processFlags |=
+		    TYPHOON_TX_PF_INSERT_VLAN | TYPHOON_TX_PF_VLAN_PRIORITY;
+		first_txd->processFlags |=
+		    cpu_to_le32(htons(vlan_tx_tag_get(skb)) <<
+				TYPHOON_TX_PF_VLAN_TAG_SHIFT);
+	}
+
+	if (skb_is_gso(skb)) {
+		first_txd->processFlags |= TYPHOON_TX_PF_TCP_SEGMENT;
+		first_txd->numDesc++;
+
+		typhoon_tso_fill(skb, txRing, tp->txlo_dma_addr);
+	}
+
+	txd = (struct tx_desc *) (txRing->ringBase + txRing->lastWrite);
+	typhoon_inc_tx_index(&txRing->lastWrite, 1);
+
+	/* No need to worry about padding packet -- the firmware pads
+	 * it with zeros to ETH_ZLEN for us.
+	 */
+	if(skb_shinfo(skb)->nr_frags == 0) {
+		skb_dma = pci_map_single(tp->tx_pdev, skb->data, skb->len,
+				       PCI_DMA_TODEVICE);
+		txd->flags = TYPHOON_FRAG_DESC | TYPHOON_DESC_VALID;
+		txd->len = cpu_to_le16(skb->len);
+		txd->frag.addr = cpu_to_le32(skb_dma);
+		txd->frag.addrHi = 0;
+		first_txd->numDesc++;
+	} else {
+		int i, len;
+
+		len = skb_headlen(skb);
+		skb_dma = pci_map_single(tp->tx_pdev, skb->data, len,
+				         PCI_DMA_TODEVICE);
+		txd->flags = TYPHOON_FRAG_DESC | TYPHOON_DESC_VALID;
+		txd->len = cpu_to_le16(len);
+		txd->frag.addr = cpu_to_le32(skb_dma);
+		txd->frag.addrHi = 0;
+		first_txd->numDesc++;
+
+		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+			const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+			void *frag_addr;
+
+			txd = (struct tx_desc *) (txRing->ringBase +
+						txRing->lastWrite);
+			typhoon_inc_tx_index(&txRing->lastWrite, 1);
+
+			len = skb_frag_size(frag);
+			frag_addr = skb_frag_address(frag);
+			skb_dma = pci_map_single(tp->tx_pdev, frag_addr, len,
+					 PCI_DMA_TODEVICE);
+			txd->flags = TYPHOON_FRAG_DESC | TYPHOON_DESC_VALID;
+			txd->len = cpu_to_le16(len);
+			txd->frag.addr = cpu_to_le32(skb_dma);
+			txd->frag.addrHi = 0;
+			first_txd->numDesc++;
+		}
+	}
+
+	/* Kick the 3XP
+	 */
+	wmb();
+	iowrite32(txRing->lastWrite, tp->tx_ioaddr + txRing->writeRegister);
+
+	/* If we don't have room to put the worst case packet on the
+	 * queue, then we must stop the queue. We need 2 extra
+	 * descriptors -- one to prevent ring wrap, and one for the
+	 * Tx header.
+	 */
+	numDesc = MAX_SKB_FRAGS + TSO_NUM_DESCRIPTORS + 1;
+
+	if(typhoon_num_free_tx(txRing) < (numDesc + 2)) {
+		netif_stop_queue(dev);
+
+		/* A Tx complete IRQ could have gotten between, making
+		 * the ring free again. Only need to recheck here, since
+		 * Tx is serialized.
+		 */
+		if(typhoon_num_free_tx(txRing) >= (numDesc + 2))
+			netif_wake_queue(dev);
+	}
+
+	return NETDEV_TX_OK;
+}
+
+static void
+typhoon_set_rx_mode(struct net_device *dev)
+{
+	struct typhoon *tp = netdev_priv(dev);
+	struct cmd_desc xp_cmd;
+	u32 mc_filter[2];
+	__le16 filter;
+
+	filter = TYPHOON_RX_FILTER_DIRECTED | TYPHOON_RX_FILTER_BROADCAST;
+	if(dev->flags & IFF_PROMISC) {
+		filter |= TYPHOON_RX_FILTER_PROMISCOUS;
+	} else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
+		  (dev->flags & IFF_ALLMULTI)) {
+		/* Too many to match, or accept all multicasts. */
+		filter |= TYPHOON_RX_FILTER_ALL_MCAST;
+	} else if (!netdev_mc_empty(dev)) {
+		struct netdev_hw_addr *ha;
+
+		memset(mc_filter, 0, sizeof(mc_filter));
+		netdev_for_each_mc_addr(ha, dev) {
+			int bit = ether_crc(ETH_ALEN, ha->addr) & 0x3f;
+			mc_filter[bit >> 5] |= 1 << (bit & 0x1f);
+		}
+
+		INIT_COMMAND_NO_RESPONSE(&xp_cmd,
+					 TYPHOON_CMD_SET_MULTICAST_HASH);
+		xp_cmd.parm1 = TYPHOON_MCAST_HASH_SET;
+		xp_cmd.parm2 = cpu_to_le32(mc_filter[0]);
+		xp_cmd.parm3 = cpu_to_le32(mc_filter[1]);
+		typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
+
+		filter |= TYPHOON_RX_FILTER_MCAST_HASH;
+	}
+
+	INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_SET_RX_FILTER);
+	xp_cmd.parm1 = filter;
+	typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
+}
+
+static int
+typhoon_do_get_stats(struct typhoon *tp)
+{
+	struct net_device_stats *stats = &tp->stats;
+	struct net_device_stats *saved = &tp->stats_saved;
+	struct cmd_desc xp_cmd;
+	struct resp_desc xp_resp[7];
+	struct stats_resp *s = (struct stats_resp *) xp_resp;
+	int err;
+
+	INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_STATS);
+	err = typhoon_issue_command(tp, 1, &xp_cmd, 7, xp_resp);
+	if(err < 0)
+		return err;
+
+	/* 3Com's Linux driver uses txMultipleCollisions as it's
+	 * collisions value, but there is some other collision info as well...
+	 *
+	 * The extra status reported would be a good candidate for
+	 * ethtool_ops->get_{strings,stats}()
+	 */
+	stats->tx_packets = le32_to_cpu(s->txPackets) +
+			saved->tx_packets;
+	stats->tx_bytes = le64_to_cpu(s->txBytes) +
+			saved->tx_bytes;
+	stats->tx_errors = le32_to_cpu(s->txCarrierLost) +
+			saved->tx_errors;
+	stats->tx_carrier_errors = le32_to_cpu(s->txCarrierLost) +
+			saved->tx_carrier_errors;
+	stats->collisions = le32_to_cpu(s->txMultipleCollisions) +
+			saved->collisions;
+	stats->rx_packets = le32_to_cpu(s->rxPacketsGood) +
+			saved->rx_packets;
+	stats->rx_bytes = le64_to_cpu(s->rxBytesGood) +
+			saved->rx_bytes;
+	stats->rx_fifo_errors = le32_to_cpu(s->rxFifoOverruns) +
+			saved->rx_fifo_errors;
+	stats->rx_errors = le32_to_cpu(s->rxFifoOverruns) +
+			le32_to_cpu(s->BadSSD) + le32_to_cpu(s->rxCrcErrors) +
+			saved->rx_errors;
+	stats->rx_crc_errors = le32_to_cpu(s->rxCrcErrors) +
+			saved->rx_crc_errors;
+	stats->rx_length_errors = le32_to_cpu(s->rxOversized) +
+			saved->rx_length_errors;
+	tp->speed = (s->linkStatus & TYPHOON_LINK_100MBPS) ?
+			SPEED_100 : SPEED_10;
+	tp->duplex = (s->linkStatus & TYPHOON_LINK_FULL_DUPLEX) ?
+			DUPLEX_FULL : DUPLEX_HALF;
+
+	return 0;
+}
+
+static struct net_device_stats *
+typhoon_get_stats(struct net_device *dev)
+{
+	struct typhoon *tp = netdev_priv(dev);
+	struct net_device_stats *stats = &tp->stats;
+	struct net_device_stats *saved = &tp->stats_saved;
+
+	smp_rmb();
+	if(tp->card_state == Sleeping)
+		return saved;
+
+	if(typhoon_do_get_stats(tp) < 0) {
+		netdev_err(dev, "error getting stats\n");
+		return saved;
+	}
+
+	return stats;
+}
+
+static int
+typhoon_set_mac_address(struct net_device *dev, void *addr)
+{
+	struct sockaddr *saddr = (struct sockaddr *) addr;
+
+	if(netif_running(dev))
+		return -EBUSY;
+
+	memcpy(dev->dev_addr, saddr->sa_data, dev->addr_len);
+	return 0;
+}
+
+static void
+typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	struct typhoon *tp = netdev_priv(dev);
+	struct pci_dev *pci_dev = tp->pdev;
+	struct cmd_desc xp_cmd;
+	struct resp_desc xp_resp[3];
+
+	smp_rmb();
+	if(tp->card_state == Sleeping) {
+		strcpy(info->fw_version, "Sleep image");
+	} else {
+		INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_VERSIONS);
+		if(typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) {
+			strcpy(info->fw_version, "Unknown runtime");
+		} else {
+			u32 sleep_ver = le32_to_cpu(xp_resp[0].parm2);
+			snprintf(info->fw_version, 32, "%02x.%03x.%03x",
+				 sleep_ver >> 24, (sleep_ver >> 12) & 0xfff,
+				 sleep_ver & 0xfff);
+		}
+	}
+
+	strcpy(info->driver, KBUILD_MODNAME);
+	strcpy(info->bus_info, pci_name(pci_dev));
+}
+
+static int
+typhoon_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct typhoon *tp = netdev_priv(dev);
+
+	cmd->supported = SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+				SUPPORTED_Autoneg;
+
+	switch (tp->xcvr_select) {
+	case TYPHOON_XCVR_10HALF:
+		cmd->advertising = ADVERTISED_10baseT_Half;
+		break;
+	case TYPHOON_XCVR_10FULL:
+		cmd->advertising = ADVERTISED_10baseT_Full;
+		break;
+	case TYPHOON_XCVR_100HALF:
+		cmd->advertising = ADVERTISED_100baseT_Half;
+		break;
+	case TYPHOON_XCVR_100FULL:
+		cmd->advertising = ADVERTISED_100baseT_Full;
+		break;
+	case TYPHOON_XCVR_AUTONEG:
+		cmd->advertising = ADVERTISED_10baseT_Half |
+					    ADVERTISED_10baseT_Full |
+					    ADVERTISED_100baseT_Half |
+					    ADVERTISED_100baseT_Full |
+					    ADVERTISED_Autoneg;
+		break;
+	}
+
+	if(tp->capabilities & TYPHOON_FIBER) {
+		cmd->supported |= SUPPORTED_FIBRE;
+		cmd->advertising |= ADVERTISED_FIBRE;
+		cmd->port = PORT_FIBRE;
+	} else {
+		cmd->supported |= SUPPORTED_10baseT_Half |
+		    			SUPPORTED_10baseT_Full |
+					SUPPORTED_TP;
+		cmd->advertising |= ADVERTISED_TP;
+		cmd->port = PORT_TP;
+	}
+
+	/* need to get stats to make these link speed/duplex valid */
+	typhoon_do_get_stats(tp);
+	ethtool_cmd_speed_set(cmd, tp->speed);
+	cmd->duplex = tp->duplex;
+	cmd->phy_address = 0;
+	cmd->transceiver = XCVR_INTERNAL;
+	if(tp->xcvr_select == TYPHOON_XCVR_AUTONEG)
+		cmd->autoneg = AUTONEG_ENABLE;
+	else
+		cmd->autoneg = AUTONEG_DISABLE;
+	cmd->maxtxpkt = 1;
+	cmd->maxrxpkt = 1;
+
+	return 0;
+}
+
+static int
+typhoon_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct typhoon *tp = netdev_priv(dev);
+	u32 speed = ethtool_cmd_speed(cmd);
+	struct cmd_desc xp_cmd;
+	__le16 xcvr;
+	int err;
+
+	err = -EINVAL;
+	if (cmd->autoneg == AUTONEG_ENABLE) {
+		xcvr = TYPHOON_XCVR_AUTONEG;
+	} else {
+		if (cmd->duplex == DUPLEX_HALF) {
+			if (speed == SPEED_10)
+				xcvr = TYPHOON_XCVR_10HALF;
+			else if (speed == SPEED_100)
+				xcvr = TYPHOON_XCVR_100HALF;
+			else
+				goto out;
+		} else if (cmd->duplex == DUPLEX_FULL) {
+			if (speed == SPEED_10)
+				xcvr = TYPHOON_XCVR_10FULL;
+			else if (speed == SPEED_100)
+				xcvr = TYPHOON_XCVR_100FULL;
+			else
+				goto out;
+		} else
+			goto out;
+	}
+
+	INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_XCVR_SELECT);
+	xp_cmd.parm1 = xcvr;
+	err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
+	if(err < 0)
+		goto out;
+
+	tp->xcvr_select = xcvr;
+	if(cmd->autoneg == AUTONEG_ENABLE) {
+		tp->speed = 0xff;	/* invalid */
+		tp->duplex = 0xff;	/* invalid */
+	} else {
+		tp->speed = speed;
+		tp->duplex = cmd->duplex;
+	}
+
+out:
+	return err;
+}
+
+static void
+typhoon_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct typhoon *tp = netdev_priv(dev);
+
+	wol->supported = WAKE_PHY | WAKE_MAGIC;
+	wol->wolopts = 0;
+	if(tp->wol_events & TYPHOON_WAKE_LINK_EVENT)
+		wol->wolopts |= WAKE_PHY;
+	if(tp->wol_events & TYPHOON_WAKE_MAGIC_PKT)
+		wol->wolopts |= WAKE_MAGIC;
+	memset(&wol->sopass, 0, sizeof(wol->sopass));
+}
+
+static int
+typhoon_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct typhoon *tp = netdev_priv(dev);
+
+	if(wol->wolopts & ~(WAKE_PHY | WAKE_MAGIC))
+		return -EINVAL;
+
+	tp->wol_events = 0;
+	if(wol->wolopts & WAKE_PHY)
+		tp->wol_events |= TYPHOON_WAKE_LINK_EVENT;
+	if(wol->wolopts & WAKE_MAGIC)
+		tp->wol_events |= TYPHOON_WAKE_MAGIC_PKT;
+
+	return 0;
+}
+
+static void
+typhoon_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
+{
+	ering->rx_max_pending = RXENT_ENTRIES;
+	ering->tx_max_pending = TXLO_ENTRIES - 1;
+
+	ering->rx_pending = RXENT_ENTRIES;
+	ering->tx_pending = TXLO_ENTRIES - 1;
+}
+
+static const struct ethtool_ops typhoon_ethtool_ops = {
+	.get_settings		= typhoon_get_settings,
+	.set_settings		= typhoon_set_settings,
+	.get_drvinfo		= typhoon_get_drvinfo,
+	.get_wol		= typhoon_get_wol,
+	.set_wol		= typhoon_set_wol,
+	.get_link		= ethtool_op_get_link,
+	.get_ringparam		= typhoon_get_ringparam,
+};
+
+static int
+typhoon_wait_interrupt(void __iomem *ioaddr)
+{
+	int i, err = 0;
+
+	for(i = 0; i < TYPHOON_WAIT_TIMEOUT; i++) {
+		if(ioread32(ioaddr + TYPHOON_REG_INTR_STATUS) &
+		   TYPHOON_INTR_BOOTCMD)
+			goto out;
+		udelay(TYPHOON_UDELAY);
+	}
+
+	err = -ETIMEDOUT;
+
+out:
+	iowrite32(TYPHOON_INTR_BOOTCMD, ioaddr + TYPHOON_REG_INTR_STATUS);
+	return err;
+}
+
+#define shared_offset(x)	offsetof(struct typhoon_shared, x)
+
+static void
+typhoon_init_interface(struct typhoon *tp)
+{
+	struct typhoon_interface *iface = &tp->shared->iface;
+	dma_addr_t shared_dma;
+
+	memset(tp->shared, 0, sizeof(struct typhoon_shared));
+
+	/* The *Hi members of iface are all init'd to zero by the memset().
+	 */
+	shared_dma = tp->shared_dma + shared_offset(indexes);
+	iface->ringIndex = cpu_to_le32(shared_dma);
+
+	shared_dma = tp->shared_dma + shared_offset(txLo);
+	iface->txLoAddr = cpu_to_le32(shared_dma);
+	iface->txLoSize = cpu_to_le32(TXLO_ENTRIES * sizeof(struct tx_desc));
+
+	shared_dma = tp->shared_dma + shared_offset(txHi);
+	iface->txHiAddr = cpu_to_le32(shared_dma);
+	iface->txHiSize = cpu_to_le32(TXHI_ENTRIES * sizeof(struct tx_desc));
+
+	shared_dma = tp->shared_dma + shared_offset(rxBuff);
+	iface->rxBuffAddr = cpu_to_le32(shared_dma);
+	iface->rxBuffSize = cpu_to_le32(RXFREE_ENTRIES *
+					sizeof(struct rx_free));
+
+	shared_dma = tp->shared_dma + shared_offset(rxLo);
+	iface->rxLoAddr = cpu_to_le32(shared_dma);
+	iface->rxLoSize = cpu_to_le32(RX_ENTRIES * sizeof(struct rx_desc));
+
+	shared_dma = tp->shared_dma + shared_offset(rxHi);
+	iface->rxHiAddr = cpu_to_le32(shared_dma);
+	iface->rxHiSize = cpu_to_le32(RX_ENTRIES * sizeof(struct rx_desc));
+
+	shared_dma = tp->shared_dma + shared_offset(cmd);
+	iface->cmdAddr = cpu_to_le32(shared_dma);
+	iface->cmdSize = cpu_to_le32(COMMAND_RING_SIZE);
+
+	shared_dma = tp->shared_dma + shared_offset(resp);
+	iface->respAddr = cpu_to_le32(shared_dma);
+	iface->respSize = cpu_to_le32(RESPONSE_RING_SIZE);
+
+	shared_dma = tp->shared_dma + shared_offset(zeroWord);
+	iface->zeroAddr = cpu_to_le32(shared_dma);
+
+	tp->indexes = &tp->shared->indexes;
+	tp->txLoRing.ringBase = (u8 *) tp->shared->txLo;
+	tp->txHiRing.ringBase = (u8 *) tp->shared->txHi;
+	tp->rxLoRing.ringBase = (u8 *) tp->shared->rxLo;
+	tp->rxHiRing.ringBase = (u8 *) tp->shared->rxHi;
+	tp->rxBuffRing.ringBase = (u8 *) tp->shared->rxBuff;
+	tp->cmdRing.ringBase = (u8 *) tp->shared->cmd;
+	tp->respRing.ringBase = (u8 *) tp->shared->resp;
+
+	tp->txLoRing.writeRegister = TYPHOON_REG_TX_LO_READY;
+	tp->txHiRing.writeRegister = TYPHOON_REG_TX_HI_READY;
+
+	tp->txlo_dma_addr = le32_to_cpu(iface->txLoAddr);
+	tp->card_state = Sleeping;
+
+	tp->offload = TYPHOON_OFFLOAD_IP_CHKSUM | TYPHOON_OFFLOAD_TCP_CHKSUM;
+	tp->offload |= TYPHOON_OFFLOAD_UDP_CHKSUM | TSO_OFFLOAD_ON;
+	tp->offload |= TYPHOON_OFFLOAD_VLAN;
+
+	spin_lock_init(&tp->command_lock);
+
+	/* Force the writes to the shared memory area out before continuing. */
+	wmb();
+}
+
+static void
+typhoon_init_rings(struct typhoon *tp)
+{
+	memset(tp->indexes, 0, sizeof(struct typhoon_indexes));
+
+	tp->txLoRing.lastWrite = 0;
+	tp->txHiRing.lastWrite = 0;
+	tp->rxLoRing.lastWrite = 0;
+	tp->rxHiRing.lastWrite = 0;
+	tp->rxBuffRing.lastWrite = 0;
+	tp->cmdRing.lastWrite = 0;
+	tp->respRing.lastWrite = 0;
+
+	tp->txLoRing.lastRead = 0;
+	tp->txHiRing.lastRead = 0;
+}
+
+static const struct firmware *typhoon_fw;
+
+static int
+typhoon_reject_firmware(struct typhoon *tp)
+{
+	const struct typhoon_file_header *fHdr;
+	const struct typhoon_section_header *sHdr;
+	const u8 *image_data;
+	u32 numSections;
+	u32 section_len;
+	u32 remaining;
+	int err;
+
+	if (typhoon_fw)
+		return 0;
+
+	err = reject_firmware(&typhoon_fw, FIRMWARE_NAME, &tp->pdev->dev);
+	if (err) {
+		netdev_err(tp->dev, "Failed to load firmware \"%s\"\n",
+			   FIRMWARE_NAME);
+		return err;
+	}
+
+	image_data = (u8 *) typhoon_fw->data;
+	remaining = typhoon_fw->size;
+	if (remaining < sizeof(struct typhoon_file_header))
+		goto invalid_fw;
+
+	fHdr = (struct typhoon_file_header *) image_data;
+	if (memcmp(fHdr->tag, "TYPHOON", 8))
+		goto invalid_fw;
+
+	numSections = le32_to_cpu(fHdr->numSections);
+	image_data += sizeof(struct typhoon_file_header);
+	remaining -= sizeof(struct typhoon_file_header);
+
+	while (numSections--) {
+		if (remaining < sizeof(struct typhoon_section_header))
+			goto invalid_fw;
+
+		sHdr = (struct typhoon_section_header *) image_data;
+		image_data += sizeof(struct typhoon_section_header);
+		section_len = le32_to_cpu(sHdr->len);
+
+		if (remaining < section_len)
+			goto invalid_fw;
+
+		image_data += section_len;
+		remaining -= section_len;
+	}
+
+	return 0;
+
+invalid_fw:
+	netdev_err(tp->dev, "Invalid firmware image\n");
+	release_firmware(typhoon_fw);
+	typhoon_fw = NULL;
+	return -EINVAL;
+}
+
+static int
+typhoon_download_firmware(struct typhoon *tp)
+{
+	void __iomem *ioaddr = tp->ioaddr;
+	struct pci_dev *pdev = tp->pdev;
+	const struct typhoon_file_header *fHdr;
+	const struct typhoon_section_header *sHdr;
+	const u8 *image_data;
+	void *dpage;
+	dma_addr_t dpage_dma;
+	__sum16 csum;
+	u32 irqEnabled;
+	u32 irqMasked;
+	u32 numSections;
+	u32 section_len;
+	u32 len;
+	u32 load_addr;
+	u32 hmac;
+	int i;
+	int err;
+
+	image_data = (u8 *) typhoon_fw->data;
+	fHdr = (struct typhoon_file_header *) image_data;
+
+	/* Cannot just map the firmware image using pci_map_single() as
+	 * the firmware is vmalloc()'d and may not be physically contiguous,
+	 * so we allocate some consistent memory to copy the sections into.
+	 */
+	err = -ENOMEM;
+	dpage = pci_alloc_consistent(pdev, PAGE_SIZE, &dpage_dma);
+	if(!dpage) {
+		netdev_err(tp->dev, "no DMA mem for firmware\n");
+		goto err_out;
+	}
+
+	irqEnabled = ioread32(ioaddr + TYPHOON_REG_INTR_ENABLE);
+	iowrite32(irqEnabled | TYPHOON_INTR_BOOTCMD,
+	       ioaddr + TYPHOON_REG_INTR_ENABLE);
+	irqMasked = ioread32(ioaddr + TYPHOON_REG_INTR_MASK);
+	iowrite32(irqMasked | TYPHOON_INTR_BOOTCMD,
+	       ioaddr + TYPHOON_REG_INTR_MASK);
+
+	err = -ETIMEDOUT;
+	if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_HOST) < 0) {
+		netdev_err(tp->dev, "card ready timeout\n");
+		goto err_out_irq;
+	}
+
+	numSections = le32_to_cpu(fHdr->numSections);
+	load_addr = le32_to_cpu(fHdr->startAddr);
+
+	iowrite32(TYPHOON_INTR_BOOTCMD, ioaddr + TYPHOON_REG_INTR_STATUS);
+	iowrite32(load_addr, ioaddr + TYPHOON_REG_DOWNLOAD_BOOT_ADDR);
+	hmac = le32_to_cpu(fHdr->hmacDigest[0]);
+	iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_0);
+	hmac = le32_to_cpu(fHdr->hmacDigest[1]);
+	iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_1);
+	hmac = le32_to_cpu(fHdr->hmacDigest[2]);
+	iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_2);
+	hmac = le32_to_cpu(fHdr->hmacDigest[3]);
+	iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_3);
+	hmac = le32_to_cpu(fHdr->hmacDigest[4]);
+	iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_4);
+	typhoon_post_pci_writes(ioaddr);
+	iowrite32(TYPHOON_BOOTCMD_RUNTIME_IMAGE, ioaddr + TYPHOON_REG_COMMAND);
+
+	image_data += sizeof(struct typhoon_file_header);
+
+	/* The ioread32() in typhoon_wait_interrupt() will force the
+	 * last write to the command register to post, so
+	 * we don't need a typhoon_post_pci_writes() after it.
+	 */
+	for(i = 0; i < numSections; i++) {
+		sHdr = (struct typhoon_section_header *) image_data;
+		image_data += sizeof(struct typhoon_section_header);
+		load_addr = le32_to_cpu(sHdr->startAddr);
+		section_len = le32_to_cpu(sHdr->len);
+
+		while(section_len) {
+			len = min_t(u32, section_len, PAGE_SIZE);
+
+			if(typhoon_wait_interrupt(ioaddr) < 0 ||
+			   ioread32(ioaddr + TYPHOON_REG_STATUS) !=
+			   TYPHOON_STATUS_WAITING_FOR_SEGMENT) {
+				netdev_err(tp->dev, "segment ready timeout\n");
+				goto err_out_irq;
+			}
+
+			/* Do an pseudo IPv4 checksum on the data -- first
+			 * need to convert each u16 to cpu order before
+			 * summing. Fortunately, due to the properties of
+			 * the checksum, we can do this once, at the end.
+			 */
+			csum = csum_fold(csum_partial_copy_nocheck(image_data,
+								   dpage, len,
+								   0));
+
+			iowrite32(len, ioaddr + TYPHOON_REG_BOOT_LENGTH);
+			iowrite32(le16_to_cpu((__force __le16)csum),
+					ioaddr + TYPHOON_REG_BOOT_CHECKSUM);
+			iowrite32(load_addr,
+					ioaddr + TYPHOON_REG_BOOT_DEST_ADDR);
+			iowrite32(0, ioaddr + TYPHOON_REG_BOOT_DATA_HI);
+			iowrite32(dpage_dma, ioaddr + TYPHOON_REG_BOOT_DATA_LO);
+			typhoon_post_pci_writes(ioaddr);
+			iowrite32(TYPHOON_BOOTCMD_SEG_AVAILABLE,
+					ioaddr + TYPHOON_REG_COMMAND);
+
+			image_data += len;
+			load_addr += len;
+			section_len -= len;
+		}
+	}
+
+	if(typhoon_wait_interrupt(ioaddr) < 0 ||
+	   ioread32(ioaddr + TYPHOON_REG_STATUS) !=
+	   TYPHOON_STATUS_WAITING_FOR_SEGMENT) {
+		netdev_err(tp->dev, "final segment ready timeout\n");
+		goto err_out_irq;
+	}
+
+	iowrite32(TYPHOON_BOOTCMD_DNLD_COMPLETE, ioaddr + TYPHOON_REG_COMMAND);
+
+	if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_BOOT) < 0) {
+		netdev_err(tp->dev, "boot ready timeout, status 0x%0x\n",
+			   ioread32(ioaddr + TYPHOON_REG_STATUS));
+		goto err_out_irq;
+	}
+
+	err = 0;
+
+err_out_irq:
+	iowrite32(irqMasked, ioaddr + TYPHOON_REG_INTR_MASK);
+	iowrite32(irqEnabled, ioaddr + TYPHOON_REG_INTR_ENABLE);
+
+	pci_free_consistent(pdev, PAGE_SIZE, dpage, dpage_dma);
+
+err_out:
+	return err;
+}
+
+static int
+typhoon_boot_3XP(struct typhoon *tp, u32 initial_status)
+{
+	void __iomem *ioaddr = tp->ioaddr;
+
+	if(typhoon_wait_status(ioaddr, initial_status) < 0) {
+		netdev_err(tp->dev, "boot ready timeout\n");
+		goto out_timeout;
+	}
+
+	iowrite32(0, ioaddr + TYPHOON_REG_BOOT_RECORD_ADDR_HI);
+	iowrite32(tp->shared_dma, ioaddr + TYPHOON_REG_BOOT_RECORD_ADDR_LO);
+	typhoon_post_pci_writes(ioaddr);
+	iowrite32(TYPHOON_BOOTCMD_REG_BOOT_RECORD,
+				ioaddr + TYPHOON_REG_COMMAND);
+
+	if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_RUNNING) < 0) {
+		netdev_err(tp->dev, "boot finish timeout (status 0x%x)\n",
+			   ioread32(ioaddr + TYPHOON_REG_STATUS));
+		goto out_timeout;
+	}
+
+	/* Clear the Transmit and Command ready registers
+	 */
+	iowrite32(0, ioaddr + TYPHOON_REG_TX_HI_READY);
+	iowrite32(0, ioaddr + TYPHOON_REG_CMD_READY);
+	iowrite32(0, ioaddr + TYPHOON_REG_TX_LO_READY);
+	typhoon_post_pci_writes(ioaddr);
+	iowrite32(TYPHOON_BOOTCMD_BOOT, ioaddr + TYPHOON_REG_COMMAND);
+
+	return 0;
+
+out_timeout:
+	return -ETIMEDOUT;
+}
+
+static u32
+typhoon_clean_tx(struct typhoon *tp, struct transmit_ring *txRing,
+			volatile __le32 * index)
+{
+	u32 lastRead = txRing->lastRead;
+	struct tx_desc *tx;
+	dma_addr_t skb_dma;
+	int dma_len;
+	int type;
+
+	while(lastRead != le32_to_cpu(*index)) {
+		tx = (struct tx_desc *) (txRing->ringBase + lastRead);
+		type = tx->flags & TYPHOON_TYPE_MASK;
+
+		if(type == TYPHOON_TX_DESC) {
+			/* This tx_desc describes a packet.
+			 */
+			unsigned long ptr = tx->tx_addr;
+			struct sk_buff *skb = (struct sk_buff *) ptr;
+			dev_kfree_skb_irq(skb);
+		} else if(type == TYPHOON_FRAG_DESC) {
+			/* This tx_desc describes a memory mapping. Free it.
+			 */
+			skb_dma = (dma_addr_t) le32_to_cpu(tx->frag.addr);
+			dma_len = le16_to_cpu(tx->len);
+			pci_unmap_single(tp->pdev, skb_dma, dma_len,
+				       PCI_DMA_TODEVICE);
+		}
+
+		tx->flags = 0;
+		typhoon_inc_tx_index(&lastRead, 1);
+	}
+
+	return lastRead;
+}
+
+static void
+typhoon_tx_complete(struct typhoon *tp, struct transmit_ring *txRing,
+			volatile __le32 * index)
+{
+	u32 lastRead;
+	int numDesc = MAX_SKB_FRAGS + 1;
+
+	/* This will need changing if we start to use the Hi Tx ring. */
+	lastRead = typhoon_clean_tx(tp, txRing, index);
+	if(netif_queue_stopped(tp->dev) && typhoon_num_free(txRing->lastWrite,
+				lastRead, TXLO_ENTRIES) > (numDesc + 2))
+		netif_wake_queue(tp->dev);
+
+	txRing->lastRead = lastRead;
+	smp_wmb();
+}
+
+static void
+typhoon_recycle_rx_skb(struct typhoon *tp, u32 idx)
+{
+	struct typhoon_indexes *indexes = tp->indexes;
+	struct rxbuff_ent *rxb = &tp->rxbuffers[idx];
+	struct basic_ring *ring = &tp->rxBuffRing;
+	struct rx_free *r;
+
+	if((ring->lastWrite + sizeof(*r)) % (RXFREE_ENTRIES * sizeof(*r)) ==
+				le32_to_cpu(indexes->rxBuffCleared)) {
+		/* no room in ring, just drop the skb
+		 */
+		dev_kfree_skb_any(rxb->skb);
+		rxb->skb = NULL;
+		return;
+	}
+
+	r = (struct rx_free *) (ring->ringBase + ring->lastWrite);
+	typhoon_inc_rxfree_index(&ring->lastWrite, 1);
+	r->virtAddr = idx;
+	r->physAddr = cpu_to_le32(rxb->dma_addr);
+
+	/* Tell the card about it */
+	wmb();
+	indexes->rxBuffReady = cpu_to_le32(ring->lastWrite);
+}
+
+static int
+typhoon_alloc_rx_skb(struct typhoon *tp, u32 idx)
+{
+	struct typhoon_indexes *indexes = tp->indexes;
+	struct rxbuff_ent *rxb = &tp->rxbuffers[idx];
+	struct basic_ring *ring = &tp->rxBuffRing;
+	struct rx_free *r;
+	struct sk_buff *skb;
+	dma_addr_t dma_addr;
+
+	rxb->skb = NULL;
+
+	if((ring->lastWrite + sizeof(*r)) % (RXFREE_ENTRIES * sizeof(*r)) ==
+				le32_to_cpu(indexes->rxBuffCleared))
+		return -ENOMEM;
+
+	skb = dev_alloc_skb(PKT_BUF_SZ);
+	if(!skb)
+		return -ENOMEM;
+
+#if 0
+	/* Please, 3com, fix the firmware to allow DMA to a unaligned
+	 * address! Pretty please?
+	 */
+	skb_reserve(skb, 2);
+#endif
+
+	skb->dev = tp->dev;
+	dma_addr = pci_map_single(tp->pdev, skb->data,
+				  PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+
+	/* Since no card does 64 bit DAC, the high bits will never
+	 * change from zero.
+	 */
+	r = (struct rx_free *) (ring->ringBase + ring->lastWrite);
+	typhoon_inc_rxfree_index(&ring->lastWrite, 1);
+	r->virtAddr = idx;
+	r->physAddr = cpu_to_le32(dma_addr);
+	rxb->skb = skb;
+	rxb->dma_addr = dma_addr;
+
+	/* Tell the card about it */
+	wmb();
+	indexes->rxBuffReady = cpu_to_le32(ring->lastWrite);
+	return 0;
+}
+
+static int
+typhoon_rx(struct typhoon *tp, struct basic_ring *rxRing, volatile __le32 * ready,
+	   volatile __le32 * cleared, int budget)
+{
+	struct rx_desc *rx;
+	struct sk_buff *skb, *new_skb;
+	struct rxbuff_ent *rxb;
+	dma_addr_t dma_addr;
+	u32 local_ready;
+	u32 rxaddr;
+	int pkt_len;
+	u32 idx;
+	__le32 csum_bits;
+	int received;
+
+	received = 0;
+	local_ready = le32_to_cpu(*ready);
+	rxaddr = le32_to_cpu(*cleared);
+	while(rxaddr != local_ready && budget > 0) {
+		rx = (struct rx_desc *) (rxRing->ringBase + rxaddr);
+		idx = rx->addr;
+		rxb = &tp->rxbuffers[idx];
+		skb = rxb->skb;
+		dma_addr = rxb->dma_addr;
+
+		typhoon_inc_rx_index(&rxaddr, 1);
+
+		if(rx->flags & TYPHOON_RX_ERROR) {
+			typhoon_recycle_rx_skb(tp, idx);
+			continue;
+		}
+
+		pkt_len = le16_to_cpu(rx->frameLen);
+
+		if(pkt_len < rx_copybreak &&
+		   (new_skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+			skb_reserve(new_skb, 2);
+			pci_dma_sync_single_for_cpu(tp->pdev, dma_addr,
+						    PKT_BUF_SZ,
+						    PCI_DMA_FROMDEVICE);
+			skb_copy_to_linear_data(new_skb, skb->data, pkt_len);
+			pci_dma_sync_single_for_device(tp->pdev, dma_addr,
+						       PKT_BUF_SZ,
+						       PCI_DMA_FROMDEVICE);
+			skb_put(new_skb, pkt_len);
+			typhoon_recycle_rx_skb(tp, idx);
+		} else {
+			new_skb = skb;
+			skb_put(new_skb, pkt_len);
+			pci_unmap_single(tp->pdev, dma_addr, PKT_BUF_SZ,
+				       PCI_DMA_FROMDEVICE);
+			typhoon_alloc_rx_skb(tp, idx);
+		}
+		new_skb->protocol = eth_type_trans(new_skb, tp->dev);
+		csum_bits = rx->rxStatus & (TYPHOON_RX_IP_CHK_GOOD |
+			TYPHOON_RX_UDP_CHK_GOOD | TYPHOON_RX_TCP_CHK_GOOD);
+		if(csum_bits ==
+		   (TYPHOON_RX_IP_CHK_GOOD | TYPHOON_RX_TCP_CHK_GOOD) ||
+		   csum_bits ==
+		   (TYPHOON_RX_IP_CHK_GOOD | TYPHOON_RX_UDP_CHK_GOOD)) {
+			new_skb->ip_summed = CHECKSUM_UNNECESSARY;
+		} else
+			skb_checksum_none_assert(new_skb);
+
+		if (rx->rxStatus & TYPHOON_RX_VLAN)
+			__vlan_hwaccel_put_tag(new_skb,
+					       ntohl(rx->vlanTag) & 0xffff);
+		netif_receive_skb(new_skb);
+
+		received++;
+		budget--;
+	}
+	*cleared = cpu_to_le32(rxaddr);
+
+	return received;
+}
+
+static void
+typhoon_fill_free_ring(struct typhoon *tp)
+{
+	u32 i;
+
+	for(i = 0; i < RXENT_ENTRIES; i++) {
+		struct rxbuff_ent *rxb = &tp->rxbuffers[i];
+		if(rxb->skb)
+			continue;
+		if(typhoon_alloc_rx_skb(tp, i) < 0)
+			break;
+	}
+}
+
+static int
+typhoon_poll(struct napi_struct *napi, int budget)
+{
+	struct typhoon *tp = container_of(napi, struct typhoon, napi);
+	struct typhoon_indexes *indexes = tp->indexes;
+	int work_done;
+
+	rmb();
+	if(!tp->awaiting_resp && indexes->respReady != indexes->respCleared)
+			typhoon_process_response(tp, 0, NULL);
+
+	if(le32_to_cpu(indexes->txLoCleared) != tp->txLoRing.lastRead)
+		typhoon_tx_complete(tp, &tp->txLoRing, &indexes->txLoCleared);
+
+	work_done = 0;
+
+	if(indexes->rxHiCleared != indexes->rxHiReady) {
+		work_done += typhoon_rx(tp, &tp->rxHiRing, &indexes->rxHiReady,
+			   		&indexes->rxHiCleared, budget);
+	}
+
+	if(indexes->rxLoCleared != indexes->rxLoReady) {
+		work_done += typhoon_rx(tp, &tp->rxLoRing, &indexes->rxLoReady,
+					&indexes->rxLoCleared, budget - work_done);
+	}
+
+	if(le32_to_cpu(indexes->rxBuffCleared) == tp->rxBuffRing.lastWrite) {
+		/* rxBuff ring is empty, try to fill it. */
+		typhoon_fill_free_ring(tp);
+	}
+
+	if (work_done < budget) {
+		napi_complete(napi);
+		iowrite32(TYPHOON_INTR_NONE,
+				tp->ioaddr + TYPHOON_REG_INTR_MASK);
+		typhoon_post_pci_writes(tp->ioaddr);
+	}
+
+	return work_done;
+}
+
+static irqreturn_t
+typhoon_interrupt(int irq, void *dev_instance)
+{
+	struct net_device *dev = dev_instance;
+	struct typhoon *tp = netdev_priv(dev);
+	void __iomem *ioaddr = tp->ioaddr;
+	u32 intr_status;
+
+	intr_status = ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
+	if(!(intr_status & TYPHOON_INTR_HOST_INT))
+		return IRQ_NONE;
+
+	iowrite32(intr_status, ioaddr + TYPHOON_REG_INTR_STATUS);
+
+	if (napi_schedule_prep(&tp->napi)) {
+		iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
+		typhoon_post_pci_writes(ioaddr);
+		__napi_schedule(&tp->napi);
+	} else {
+		netdev_err(dev, "Error, poll already scheduled\n");
+	}
+	return IRQ_HANDLED;
+}
+
+static void
+typhoon_free_rx_rings(struct typhoon *tp)
+{
+	u32 i;
+
+	for(i = 0; i < RXENT_ENTRIES; i++) {
+		struct rxbuff_ent *rxb = &tp->rxbuffers[i];
+		if(rxb->skb) {
+			pci_unmap_single(tp->pdev, rxb->dma_addr, PKT_BUF_SZ,
+				       PCI_DMA_FROMDEVICE);
+			dev_kfree_skb(rxb->skb);
+			rxb->skb = NULL;
+		}
+	}
+}
+
+static int
+typhoon_sleep(struct typhoon *tp, pci_power_t state, __le16 events)
+{
+	struct pci_dev *pdev = tp->pdev;
+	void __iomem *ioaddr = tp->ioaddr;
+	struct cmd_desc xp_cmd;
+	int err;
+
+	INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_ENABLE_WAKE_EVENTS);
+	xp_cmd.parm1 = events;
+	err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
+	if(err < 0) {
+		netdev_err(tp->dev, "typhoon_sleep(): wake events cmd err %d\n",
+			   err);
+		return err;
+	}
+
+	INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_GOTO_SLEEP);
+	err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
+	if(err < 0) {
+		netdev_err(tp->dev, "typhoon_sleep(): sleep cmd err %d\n", err);
+		return err;
+	}
+
+	if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_SLEEPING) < 0)
+		return -ETIMEDOUT;
+
+	/* Since we cannot monitor the status of the link while sleeping,
+	 * tell the world it went away.
+	 */
+	netif_carrier_off(tp->dev);
+
+	pci_enable_wake(tp->pdev, state, 1);
+	pci_disable_device(pdev);
+	return pci_set_power_state(pdev, state);
+}
+
+static int
+typhoon_wakeup(struct typhoon *tp, int wait_type)
+{
+	struct pci_dev *pdev = tp->pdev;
+	void __iomem *ioaddr = tp->ioaddr;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+
+	/* Post 2.x.x versions of the Sleep Image require a reset before
+	 * we can download the Runtime Image. But let's not make users of
+	 * the old firmware pay for the reset.
+	 */
+	iowrite32(TYPHOON_BOOTCMD_WAKEUP, ioaddr + TYPHOON_REG_COMMAND);
+	if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_HOST) < 0 ||
+			(tp->capabilities & TYPHOON_WAKEUP_NEEDS_RESET))
+		return typhoon_reset(ioaddr, wait_type);
+
+	return 0;
+}
+
+static int
+typhoon_start_runtime(struct typhoon *tp)
+{
+	struct net_device *dev = tp->dev;
+	void __iomem *ioaddr = tp->ioaddr;
+	struct cmd_desc xp_cmd;
+	int err;
+
+	typhoon_init_rings(tp);
+	typhoon_fill_free_ring(tp);
+
+	err = typhoon_download_firmware(tp);
+	if(err < 0) {
+		netdev_err(tp->dev, "cannot load runtime on 3XP\n");
+		goto error_out;
+	}
+
+	if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_BOOT) < 0) {
+		netdev_err(tp->dev, "cannot boot 3XP\n");
+		err = -EIO;
+		goto error_out;
+	}
+
+	INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_SET_MAX_PKT_SIZE);
+	xp_cmd.parm1 = cpu_to_le16(PKT_BUF_SZ);
+	err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
+	if(err < 0)
+		goto error_out;
+
+	INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_SET_MAC_ADDRESS);
+	xp_cmd.parm1 = cpu_to_le16(ntohs(*(__be16 *)&dev->dev_addr[0]));
+	xp_cmd.parm2 = cpu_to_le32(ntohl(*(__be32 *)&dev->dev_addr[2]));
+	err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
+	if(err < 0)
+		goto error_out;
+
+	/* Disable IRQ coalescing -- we can reenable it when 3Com gives
+	 * us some more information on how to control it.
+	 */
+	INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_IRQ_COALESCE_CTRL);
+	xp_cmd.parm1 = 0;
+	err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
+	if(err < 0)
+		goto error_out;
+
+	INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_XCVR_SELECT);
+	xp_cmd.parm1 = tp->xcvr_select;
+	err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
+	if(err < 0)
+		goto error_out;
+
+	INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_VLAN_TYPE_WRITE);
+	xp_cmd.parm1 = cpu_to_le16(ETH_P_8021Q);
+	err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
+	if(err < 0)
+		goto error_out;
+
+	INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_SET_OFFLOAD_TASKS);
+	xp_cmd.parm2 = tp->offload;
+	xp_cmd.parm3 = tp->offload;
+	err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
+	if(err < 0)
+		goto error_out;
+
+	typhoon_set_rx_mode(dev);
+
+	INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_TX_ENABLE);
+	err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
+	if(err < 0)
+		goto error_out;
+
+	INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_RX_ENABLE);
+	err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
+	if(err < 0)
+		goto error_out;
+
+	tp->card_state = Running;
+	smp_wmb();
+
+	iowrite32(TYPHOON_INTR_ENABLE_ALL, ioaddr + TYPHOON_REG_INTR_ENABLE);
+	iowrite32(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_MASK);
+	typhoon_post_pci_writes(ioaddr);
+
+	return 0;
+
+error_out:
+	typhoon_reset(ioaddr, WaitNoSleep);
+	typhoon_free_rx_rings(tp);
+	typhoon_init_rings(tp);
+	return err;
+}
+
+static int
+typhoon_stop_runtime(struct typhoon *tp, int wait_type)
+{
+	struct typhoon_indexes *indexes = tp->indexes;
+	struct transmit_ring *txLo = &tp->txLoRing;
+	void __iomem *ioaddr = tp->ioaddr;
+	struct cmd_desc xp_cmd;
+	int i;
+
+	/* Disable interrupts early, since we can't schedule a poll
+	 * when called with !netif_running(). This will be posted
+	 * when we force the posting of the command.
+	 */
+	iowrite32(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_ENABLE);
+
+	INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_RX_DISABLE);
+	typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
+
+	/* Wait 1/2 sec for any outstanding transmits to occur
+	 * We'll cleanup after the reset if this times out.
+	 */
+	for(i = 0; i < TYPHOON_WAIT_TIMEOUT; i++) {
+		if(indexes->txLoCleared == cpu_to_le32(txLo->lastWrite))
+			break;
+		udelay(TYPHOON_UDELAY);
+	}
+
+	if(i == TYPHOON_WAIT_TIMEOUT)
+		netdev_err(tp->dev, "halt timed out waiting for Tx to complete\n");
+
+	INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_TX_DISABLE);
+	typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
+
+	/* save the statistics so when we bring the interface up again,
+	 * the values reported to userspace are correct.
+	 */
+	tp->card_state = Sleeping;
+	smp_wmb();
+	typhoon_do_get_stats(tp);
+	memcpy(&tp->stats_saved, &tp->stats, sizeof(struct net_device_stats));
+
+	INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_HALT);
+	typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
+
+	if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_HALTED) < 0)
+		netdev_err(tp->dev, "timed out waiting for 3XP to halt\n");
+
+	if(typhoon_reset(ioaddr, wait_type) < 0) {
+		netdev_err(tp->dev, "unable to reset 3XP\n");
+		return -ETIMEDOUT;
+	}
+
+	/* cleanup any outstanding Tx packets */
+	if(indexes->txLoCleared != cpu_to_le32(txLo->lastWrite)) {
+		indexes->txLoCleared = cpu_to_le32(txLo->lastWrite);
+		typhoon_clean_tx(tp, &tp->txLoRing, &indexes->txLoCleared);
+	}
+
+	return 0;
+}
+
+static void
+typhoon_tx_timeout(struct net_device *dev)
+{
+	struct typhoon *tp = netdev_priv(dev);
+
+	if(typhoon_reset(tp->ioaddr, WaitNoSleep) < 0) {
+		netdev_warn(dev, "could not reset in tx timeout\n");
+		goto truly_dead;
+	}
+
+	/* If we ever start using the Hi ring, it will need cleaning too */
+	typhoon_clean_tx(tp, &tp->txLoRing, &tp->indexes->txLoCleared);
+	typhoon_free_rx_rings(tp);
+
+	if(typhoon_start_runtime(tp) < 0) {
+		netdev_err(dev, "could not start runtime in tx timeout\n");
+		goto truly_dead;
+        }
+
+	netif_wake_queue(dev);
+	return;
+
+truly_dead:
+	/* Reset the hardware, and turn off carrier to avoid more timeouts */
+	typhoon_reset(tp->ioaddr, NoWait);
+	netif_carrier_off(dev);
+}
+
+static int
+typhoon_open(struct net_device *dev)
+{
+	struct typhoon *tp = netdev_priv(dev);
+	int err;
+
+	err = typhoon_reject_firmware(tp);
+	if (err)
+		goto out;
+
+	err = typhoon_wakeup(tp, WaitSleep);
+	if(err < 0) {
+		netdev_err(dev, "unable to wakeup device\n");
+		goto out_sleep;
+	}
+
+	err = request_irq(dev->irq, typhoon_interrupt, IRQF_SHARED,
+				dev->name, dev);
+	if(err < 0)
+		goto out_sleep;
+
+	napi_enable(&tp->napi);
+
+	err = typhoon_start_runtime(tp);
+	if(err < 0) {
+		napi_disable(&tp->napi);
+		goto out_irq;
+	}
+
+	netif_start_queue(dev);
+	return 0;
+
+out_irq:
+	free_irq(dev->irq, dev);
+
+out_sleep:
+	if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST) < 0) {
+		netdev_err(dev, "unable to reboot into sleep img\n");
+		typhoon_reset(tp->ioaddr, NoWait);
+		goto out;
+	}
+
+	if(typhoon_sleep(tp, PCI_D3hot, 0) < 0)
+		netdev_err(dev, "unable to go back to sleep\n");
+
+out:
+	return err;
+}
+
+static int
+typhoon_close(struct net_device *dev)
+{
+	struct typhoon *tp = netdev_priv(dev);
+
+	netif_stop_queue(dev);
+	napi_disable(&tp->napi);
+
+	if(typhoon_stop_runtime(tp, WaitSleep) < 0)
+		netdev_err(dev, "unable to stop runtime\n");
+
+	/* Make sure there is no irq handler running on a different CPU. */
+	free_irq(dev->irq, dev);
+
+	typhoon_free_rx_rings(tp);
+	typhoon_init_rings(tp);
+
+	if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST) < 0)
+		netdev_err(dev, "unable to boot sleep image\n");
+
+	if(typhoon_sleep(tp, PCI_D3hot, 0) < 0)
+		netdev_err(dev, "unable to put card to sleep\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int
+typhoon_resume(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct typhoon *tp = netdev_priv(dev);
+
+	/* If we're down, resume when we are upped.
+	 */
+	if(!netif_running(dev))
+		return 0;
+
+	if(typhoon_wakeup(tp, WaitNoSleep) < 0) {
+		netdev_err(dev, "critical: could not wake up in resume\n");
+		goto reset;
+	}
+
+	if(typhoon_start_runtime(tp) < 0) {
+		netdev_err(dev, "critical: could not start runtime in resume\n");
+		goto reset;
+	}
+
+	netif_device_attach(dev);
+	return 0;
+
+reset:
+	typhoon_reset(tp->ioaddr, NoWait);
+	return -EBUSY;
+}
+
+static int
+typhoon_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct typhoon *tp = netdev_priv(dev);
+	struct cmd_desc xp_cmd;
+
+	/* If we're down, we're already suspended.
+	 */
+	if(!netif_running(dev))
+		return 0;
+
+	/* TYPHOON_OFFLOAD_VLAN is always on now, so this doesn't work */
+	if(tp->wol_events & TYPHOON_WAKE_MAGIC_PKT)
+		netdev_warn(dev, "cannot do WAKE_MAGIC with VLAN offloading\n");
+
+	netif_device_detach(dev);
+
+	if(typhoon_stop_runtime(tp, WaitNoSleep) < 0) {
+		netdev_err(dev, "unable to stop runtime\n");
+		goto need_resume;
+	}
+
+	typhoon_free_rx_rings(tp);
+	typhoon_init_rings(tp);
+
+	if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST) < 0) {
+		netdev_err(dev, "unable to boot sleep image\n");
+		goto need_resume;
+	}
+
+	INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_SET_MAC_ADDRESS);
+	xp_cmd.parm1 = cpu_to_le16(ntohs(*(__be16 *)&dev->dev_addr[0]));
+	xp_cmd.parm2 = cpu_to_le32(ntohl(*(__be32 *)&dev->dev_addr[2]));
+	if(typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL) < 0) {
+		netdev_err(dev, "unable to set mac address in suspend\n");
+		goto need_resume;
+	}
+
+	INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_SET_RX_FILTER);
+	xp_cmd.parm1 = TYPHOON_RX_FILTER_DIRECTED | TYPHOON_RX_FILTER_BROADCAST;
+	if(typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL) < 0) {
+		netdev_err(dev, "unable to set rx filter in suspend\n");
+		goto need_resume;
+	}
+
+	if(typhoon_sleep(tp, pci_choose_state(pdev, state), tp->wol_events) < 0) {
+		netdev_err(dev, "unable to put card to sleep\n");
+		goto need_resume;
+	}
+
+	return 0;
+
+need_resume:
+	typhoon_resume(pdev);
+	return -EBUSY;
+}
+#endif
+
+static int __devinit
+typhoon_test_mmio(struct pci_dev *pdev)
+{
+	void __iomem *ioaddr = pci_iomap(pdev, 1, 128);
+	int mode = 0;
+	u32 val;
+
+	if(!ioaddr)
+		goto out;
+
+	if(ioread32(ioaddr + TYPHOON_REG_STATUS) !=
+				TYPHOON_STATUS_WAITING_FOR_HOST)
+		goto out_unmap;
+
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_ENABLE);
+
+	/* Ok, see if we can change our interrupt status register by
+	 * sending ourselves an interrupt. If so, then MMIO works.
+	 * The 50usec delay is arbitrary -- it could probably be smaller.
+	 */
+	val = ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
+	if((val & TYPHOON_INTR_SELF) == 0) {
+		iowrite32(1, ioaddr + TYPHOON_REG_SELF_INTERRUPT);
+		ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
+		udelay(50);
+		val = ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
+		if(val & TYPHOON_INTR_SELF)
+			mode = 1;
+	}
+
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
+	iowrite32(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_ENABLE);
+	ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
+
+out_unmap:
+	pci_iounmap(pdev, ioaddr);
+
+out:
+	if(!mode)
+		pr_info("%s: falling back to port IO\n", pci_name(pdev));
+	return mode;
+}
+
+static const struct net_device_ops typhoon_netdev_ops = {
+	.ndo_open		= typhoon_open,
+	.ndo_stop		= typhoon_close,
+	.ndo_start_xmit		= typhoon_start_tx,
+	.ndo_set_rx_mode	= typhoon_set_rx_mode,
+	.ndo_tx_timeout		= typhoon_tx_timeout,
+	.ndo_get_stats		= typhoon_get_stats,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= typhoon_set_mac_address,
+	.ndo_change_mtu		= eth_change_mtu,
+};
+
+static int __devinit
+typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct net_device *dev;
+	struct typhoon *tp;
+	int card_id = (int) ent->driver_data;
+	void __iomem *ioaddr;
+	void *shared;
+	dma_addr_t shared_dma;
+	struct cmd_desc xp_cmd;
+	struct resp_desc xp_resp[3];
+	int err = 0;
+	const char *err_msg;
+
+	dev = alloc_etherdev(sizeof(*tp));
+	if(dev == NULL) {
+		err_msg = "unable to alloc new net device";
+		err = -ENOMEM;
+		goto error_out;
+	}
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	err = pci_enable_device(pdev);
+	if(err < 0) {
+		err_msg = "unable to enable device";
+		goto error_out_dev;
+	}
+
+	err = pci_set_mwi(pdev);
+	if(err < 0) {
+		err_msg = "unable to set MWI";
+		goto error_out_disable;
+	}
+
+	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if(err < 0) {
+		err_msg = "No usable DMA configuration";
+		goto error_out_mwi;
+	}
+
+	/* sanity checks on IO and MMIO BARs
+	 */
+	if(!(pci_resource_flags(pdev, 0) & IORESOURCE_IO)) {
+		err_msg = "region #1 not a PCI IO resource, aborting";
+		err = -ENODEV;
+		goto error_out_mwi;
+	}
+	if(pci_resource_len(pdev, 0) < 128) {
+		err_msg = "Invalid PCI IO region size, aborting";
+		err = -ENODEV;
+		goto error_out_mwi;
+	}
+	if(!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
+		err_msg = "region #1 not a PCI MMIO resource, aborting";
+		err = -ENODEV;
+		goto error_out_mwi;
+	}
+	if(pci_resource_len(pdev, 1) < 128) {
+		err_msg = "Invalid PCI MMIO region size, aborting";
+		err = -ENODEV;
+		goto error_out_mwi;
+	}
+
+	err = pci_request_regions(pdev, KBUILD_MODNAME);
+	if(err < 0) {
+		err_msg = "could not request regions";
+		goto error_out_mwi;
+	}
+
+	/* map our registers
+	 */
+	if(use_mmio != 0 && use_mmio != 1)
+		use_mmio = typhoon_test_mmio(pdev);
+
+	ioaddr = pci_iomap(pdev, use_mmio, 128);
+	if (!ioaddr) {
+		err_msg = "cannot remap registers, aborting";
+		err = -EIO;
+		goto error_out_regions;
+	}
+
+	/* allocate pci dma space for rx and tx descriptor rings
+	 */
+	shared = pci_alloc_consistent(pdev, sizeof(struct typhoon_shared),
+				      &shared_dma);
+	if(!shared) {
+		err_msg = "could not allocate DMA memory";
+		err = -ENOMEM;
+		goto error_out_remap;
+	}
+
+	dev->irq = pdev->irq;
+	tp = netdev_priv(dev);
+	tp->shared = shared;
+	tp->shared_dma = shared_dma;
+	tp->pdev = pdev;
+	tp->tx_pdev = pdev;
+	tp->ioaddr = ioaddr;
+	tp->tx_ioaddr = ioaddr;
+	tp->dev = dev;
+
+	/* Init sequence:
+	 * 1) Reset the adapter to clear any bad juju
+	 * 2) Reload the sleep image
+	 * 3) Boot the sleep image
+	 * 4) Get the hardware address.
+	 * 5) Put the card to sleep.
+	 */
+	if (typhoon_reset(ioaddr, WaitSleep) < 0) {
+		err_msg = "could not reset 3XP";
+		err = -EIO;
+		goto error_out_dma;
+	}
+
+	/* Now that we've reset the 3XP and are sure it's not going to
+	 * write all over memory, enable bus mastering, and save our
+	 * state for resuming after a suspend.
+	 */
+	pci_set_master(pdev);
+	pci_save_state(pdev);
+
+	typhoon_init_interface(tp);
+	typhoon_init_rings(tp);
+
+	if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST) < 0) {
+		err_msg = "cannot boot 3XP sleep image";
+		err = -EIO;
+		goto error_out_reset;
+	}
+
+	INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_MAC_ADDRESS);
+	if(typhoon_issue_command(tp, 1, &xp_cmd, 1, xp_resp) < 0) {
+		err_msg = "cannot read MAC address";
+		err = -EIO;
+		goto error_out_reset;
+	}
+
+	*(__be16 *)&dev->dev_addr[0] = htons(le16_to_cpu(xp_resp[0].parm1));
+	*(__be32 *)&dev->dev_addr[2] = htonl(le32_to_cpu(xp_resp[0].parm2));
+
+	if(!is_valid_ether_addr(dev->dev_addr)) {
+		err_msg = "Could not obtain valid ethernet address, aborting";
+		goto error_out_reset;
+	}
+
+	/* Read the Sleep Image version last, so the response is valid
+	 * later when we print out the version reported.
+	 */
+	INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_VERSIONS);
+	if(typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) {
+		err_msg = "Could not get Sleep Image version";
+		goto error_out_reset;
+	}
+
+	tp->capabilities = typhoon_card_info[card_id].capabilities;
+	tp->xcvr_select = TYPHOON_XCVR_AUTONEG;
+
+	/* Typhoon 1.0 Sleep Images return one response descriptor to the
+	 * READ_VERSIONS command. Those versions are OK after waking up
+	 * from sleep without needing a reset. Typhoon 1.1+ Sleep Images
+	 * seem to need a little extra help to get started. Since we don't
+	 * know how to nudge it along, just kick it.
+	 */
+	if(xp_resp[0].numDesc != 0)
+		tp->capabilities |= TYPHOON_WAKEUP_NEEDS_RESET;
+
+	if(typhoon_sleep(tp, PCI_D3hot, 0) < 0) {
+		err_msg = "cannot put adapter to sleep";
+		err = -EIO;
+		goto error_out_reset;
+	}
+
+	/* The chip-specific entries in the device structure. */
+	dev->netdev_ops		= &typhoon_netdev_ops;
+	netif_napi_add(dev, &tp->napi, typhoon_poll, 16);
+	dev->watchdog_timeo	= TX_TIMEOUT;
+
+	SET_ETHTOOL_OPS(dev, &typhoon_ethtool_ops);
+
+	/* We can handle scatter gather, up to 16 entries, and
+	 * we can do IP checksumming (only version 4, doh...)
+	 *
+	 * There's no way to turn off the RX VLAN offloading and stripping
+	 * on the current 3XP firmware -- it does not respect the offload
+	 * settings -- so we only allow the user to toggle the TX processing.
+	 */
+	dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
+		NETIF_F_HW_VLAN_TX;
+	dev->features = dev->hw_features |
+		NETIF_F_HW_VLAN_RX | NETIF_F_RXCSUM;
+
+	if(register_netdev(dev) < 0) {
+		err_msg = "unable to register netdev";
+		goto error_out_reset;
+	}
+
+	pci_set_drvdata(pdev, dev);
+
+	netdev_info(dev, "%s at %s 0x%llx, %pM\n",
+		    typhoon_card_info[card_id].name,
+		    use_mmio ? "MMIO" : "IO",
+		    (unsigned long long)pci_resource_start(pdev, use_mmio),
+		    dev->dev_addr);
+
+	/* xp_resp still contains the response to the READ_VERSIONS command.
+	 * For debugging, let the user know what version he has.
+	 */
+	if(xp_resp[0].numDesc == 0) {
+		/* This is the Typhoon 1.0 type Sleep Image, last 16 bits
+		 * of version is Month/Day of build.
+		 */
+		u16 monthday = le32_to_cpu(xp_resp[0].parm2) & 0xffff;
+		netdev_info(dev, "Typhoon 1.0 Sleep Image built %02u/%02u/2000\n",
+			    monthday >> 8, monthday & 0xff);
+	} else if(xp_resp[0].numDesc == 2) {
+		/* This is the Typhoon 1.1+ type Sleep Image
+		 */
+		u32 sleep_ver = le32_to_cpu(xp_resp[0].parm2);
+		u8 *ver_string = (u8 *) &xp_resp[1];
+		ver_string[25] = 0;
+		netdev_info(dev, "Typhoon 1.1+ Sleep Image version %02x.%03x.%03x %s\n",
+			    sleep_ver >> 24, (sleep_ver >> 12) & 0xfff,
+			    sleep_ver & 0xfff, ver_string);
+	} else {
+		netdev_warn(dev, "Unknown Sleep Image version (%u:%04x)\n",
+			    xp_resp[0].numDesc, le32_to_cpu(xp_resp[0].parm2));
+	}
+
+	return 0;
+
+error_out_reset:
+	typhoon_reset(ioaddr, NoWait);
+
+error_out_dma:
+	pci_free_consistent(pdev, sizeof(struct typhoon_shared),
+			    shared, shared_dma);
+error_out_remap:
+	pci_iounmap(pdev, ioaddr);
+error_out_regions:
+	pci_release_regions(pdev);
+error_out_mwi:
+	pci_clear_mwi(pdev);
+error_out_disable:
+	pci_disable_device(pdev);
+error_out_dev:
+	free_netdev(dev);
+error_out:
+	pr_err("%s: %s\n", pci_name(pdev), err_msg);
+	return err;
+}
+
+static void __devexit
+typhoon_remove_one(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct typhoon *tp = netdev_priv(dev);
+
+	unregister_netdev(dev);
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	typhoon_reset(tp->ioaddr, NoWait);
+	pci_iounmap(pdev, tp->ioaddr);
+	pci_free_consistent(pdev, sizeof(struct typhoon_shared),
+			    tp->shared, tp->shared_dma);
+	pci_release_regions(pdev);
+	pci_clear_mwi(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+	free_netdev(dev);
+}
+
+static struct pci_driver typhoon_driver = {
+	.name		= KBUILD_MODNAME,
+	.id_table	= typhoon_pci_tbl,
+	.probe		= typhoon_init_one,
+	.remove		= __devexit_p(typhoon_remove_one),
+#ifdef CONFIG_PM
+	.suspend	= typhoon_suspend,
+	.resume		= typhoon_resume,
+#endif
+};
+
+static int __init
+typhoon_init(void)
+{
+	return pci_register_driver(&typhoon_driver);
+}
+
+static void __exit
+typhoon_cleanup(void)
+{
+	if (typhoon_fw)
+		release_firmware(typhoon_fw);
+	pci_unregister_driver(&typhoon_driver);
+}
+
+module_init(typhoon_init);
+module_exit(typhoon_cleanup);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/3com/typhoon.h linux-libre-3.2-gnu/drivers/net/ethernet/3com/typhoon.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/3com/typhoon.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/3com/typhoon.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,624 @@
+/* typhoon.h:	chip info for the 3Com 3CR990 family of controllers */
+/*
+	Written 2002-2003 by David Dillow <dave@thedillows.org>
+
+	This software may be used and distributed according to the terms of
+	the GNU General Public License (GPL), incorporated herein by reference.
+	Drivers based on or derived from this code fall under the GPL and must
+	retain the authorship, copyright and license notice.  This file is not
+	a complete program and may only be used when the entire operating
+	system is licensed under the GPL.
+
+	This software is available on a public web site. It may enable
+	cryptographic capabilities of the 3Com hardware, and may be
+	exported from the United States under License Exception "TSU"
+	pursuant to 15 C.F.R. Section 740.13(e).
+
+	This work was funded by the National Library of Medicine under
+	the Department of Energy project number 0274DD06D1 and NLM project
+	number Y1-LM-2015-01.
+*/
+
+/* All Typhoon ring positions are specificed in bytes, and point to the
+ * first "clean" entry in the ring -- ie the next entry we use for whatever
+ * purpose.
+ */
+
+/* The Typhoon basic ring
+ * ringBase:  where this ring lives (our virtual address)
+ * lastWrite: the next entry we'll use
+ */
+struct basic_ring {
+	u8 *ringBase;
+	u32 lastWrite;
+};
+
+/* The Typoon transmit ring -- same as a basic ring, plus:
+ * lastRead:      where we're at in regard to cleaning up the ring
+ * writeRegister: register to use for writing (different for Hi & Lo rings)
+ */
+struct transmit_ring {
+	u8 *ringBase;
+	u32 lastWrite;
+	u32 lastRead;
+	int writeRegister;
+};
+
+/* The host<->Typhoon ring index structure
+ * This indicates the current positions in the rings
+ *
+ * All values must be in little endian format for the 3XP
+ *
+ * rxHiCleared:   entry we've cleared to in the Hi receive ring
+ * rxLoCleared:   entry we've cleared to in the Lo receive ring
+ * rxBuffReady:   next entry we'll put a free buffer in
+ * respCleared:   entry we've cleared to in the response ring
+ *
+ * txLoCleared:   entry the NIC has cleared to in the Lo transmit ring
+ * txHiCleared:   entry the NIC has cleared to in the Hi transmit ring
+ * rxLoReady:     entry the NIC has filled to in the Lo receive ring
+ * rxBuffCleared: entry the NIC has cleared in the free buffer ring
+ * cmdCleared:    entry the NIC has cleared in the command ring
+ * respReady:     entry the NIC has filled to in the response ring
+ * rxHiReady:     entry the NIC has filled to in the Hi receive ring
+ */
+struct typhoon_indexes {
+	/* The first four are written by the host, and read by the NIC */
+	volatile __le32 rxHiCleared;
+	volatile __le32 rxLoCleared;
+	volatile __le32 rxBuffReady;
+	volatile __le32 respCleared;
+
+	/* The remaining are written by the NIC, and read by the host */
+	volatile __le32 txLoCleared;
+	volatile __le32 txHiCleared;
+	volatile __le32 rxLoReady;
+	volatile __le32 rxBuffCleared;
+	volatile __le32 cmdCleared;
+	volatile __le32 respReady;
+	volatile __le32 rxHiReady;
+} __packed;
+
+/* The host<->Typhoon interface
+ * Our means of communicating where things are
+ *
+ * All values must be in little endian format for the 3XP
+ *
+ * ringIndex:   64 bit bus address of the index structure
+ * txLoAddr:    64 bit bus address of the Lo transmit ring
+ * txLoSize:    size (in bytes) of the Lo transmit ring
+ * txHi*:       as above for the Hi priority transmit ring
+ * rxLo*:       as above for the Lo priority receive ring
+ * rxBuff*:     as above for the free buffer ring
+ * cmd*:        as above for the command ring
+ * resp*:       as above for the response ring
+ * zeroAddr:    64 bit bus address of a zero word (for DMA)
+ * rxHi*:       as above for the Hi Priority receive ring
+ *
+ * While there is room for 64 bit addresses, current versions of the 3XP
+ * only do 32 bit addresses, so the *Hi for each of the above will always
+ * be zero.
+ */
+struct typhoon_interface {
+	__le32 ringIndex;
+	__le32 ringIndexHi;
+	__le32 txLoAddr;
+	__le32 txLoAddrHi;
+	__le32 txLoSize;
+	__le32 txHiAddr;
+	__le32 txHiAddrHi;
+	__le32 txHiSize;
+	__le32 rxLoAddr;
+	__le32 rxLoAddrHi;
+	__le32 rxLoSize;
+	__le32 rxBuffAddr;
+	__le32 rxBuffAddrHi;
+	__le32 rxBuffSize;
+	__le32 cmdAddr;
+	__le32 cmdAddrHi;
+	__le32 cmdSize;
+	__le32 respAddr;
+	__le32 respAddrHi;
+	__le32 respSize;
+	__le32 zeroAddr;
+	__le32 zeroAddrHi;
+	__le32 rxHiAddr;
+	__le32 rxHiAddrHi;
+	__le32 rxHiSize;
+} __packed;
+
+/* The Typhoon transmit/fragment descriptor
+ *
+ * A packet is described by a packet descriptor, followed by option descriptors,
+ * if any, then one or more fragment descriptors.
+ *
+ * Packet descriptor:
+ * flags:	Descriptor type
+ * len:i	zero, or length of this packet
+ * addr*:	8 bytes of opaque data to the firmware -- for skb pointer
+ * processFlags: Determine offload tasks to perform on this packet.
+ *
+ * Fragment descriptor:
+ * flags:	Descriptor type
+ * len:i	length of this fragment
+ * addr:	low bytes of DMA address for this part of the packet
+ * addrHi:	hi bytes of DMA address for this part of the packet
+ * processFlags: must be zero
+ *
+ * TYPHOON_DESC_VALID is not mentioned in their docs, but their Linux
+ * driver uses it.
+ */
+struct tx_desc {
+	u8  flags;
+#define TYPHOON_TYPE_MASK	0x07
+#define 	TYPHOON_FRAG_DESC	0x00
+#define 	TYPHOON_TX_DESC		0x01
+#define 	TYPHOON_CMD_DESC	0x02
+#define 	TYPHOON_OPT_DESC	0x03
+#define 	TYPHOON_RX_DESC		0x04
+#define 	TYPHOON_RESP_DESC	0x05
+#define TYPHOON_OPT_TYPE_MASK	0xf0
+#define 	TYPHOON_OPT_IPSEC	0x00
+#define 	TYPHOON_OPT_TCP_SEG	0x10
+#define TYPHOON_CMD_RESPOND	0x40
+#define TYPHOON_RESP_ERROR	0x40
+#define TYPHOON_RX_ERROR	0x40
+#define TYPHOON_DESC_VALID	0x80
+	u8  numDesc;
+	__le16 len;
+	union {
+		struct {
+			__le32 addr;
+			__le32 addrHi;
+		} frag;
+		u64 tx_addr;	/* opaque for hardware, for TX_DESC */
+	};
+	__le32 processFlags;
+#define TYPHOON_TX_PF_NO_CRC		cpu_to_le32(0x00000001)
+#define TYPHOON_TX_PF_IP_CHKSUM		cpu_to_le32(0x00000002)
+#define TYPHOON_TX_PF_TCP_CHKSUM	cpu_to_le32(0x00000004)
+#define TYPHOON_TX_PF_TCP_SEGMENT	cpu_to_le32(0x00000008)
+#define TYPHOON_TX_PF_INSERT_VLAN	cpu_to_le32(0x00000010)
+#define TYPHOON_TX_PF_IPSEC		cpu_to_le32(0x00000020)
+#define TYPHOON_TX_PF_VLAN_PRIORITY	cpu_to_le32(0x00000040)
+#define TYPHOON_TX_PF_UDP_CHKSUM	cpu_to_le32(0x00000080)
+#define TYPHOON_TX_PF_PAD_FRAME		cpu_to_le32(0x00000100)
+#define TYPHOON_TX_PF_RESERVED		cpu_to_le32(0x00000e00)
+#define TYPHOON_TX_PF_VLAN_MASK		cpu_to_le32(0x0ffff000)
+#define TYPHOON_TX_PF_INTERNAL		cpu_to_le32(0xf0000000)
+#define TYPHOON_TX_PF_VLAN_TAG_SHIFT	12
+} __packed;
+
+/* The TCP Segmentation offload option descriptor
+ *
+ * flags:	descriptor type
+ * numDesc:	must be 1
+ * mss_flags:	bits 0-11 (little endian) are MSS, 12 is first TSO descriptor
+ *			13 is list TSO descriptor, set both if only one TSO
+ * respAddrLo:	low bytes of address of the bytesTx field of this descriptor
+ * bytesTx:	total number of bytes in this TSO request
+ * status:	0 on completion
+ */
+struct tcpopt_desc {
+	u8  flags;
+	u8  numDesc;
+	__le16 mss_flags;
+#define TYPHOON_TSO_FIRST		cpu_to_le16(0x1000)
+#define TYPHOON_TSO_LAST		cpu_to_le16(0x2000)
+	__le32 respAddrLo;
+	__le32 bytesTx;
+	__le32 status;
+} __packed;
+
+/* The IPSEC Offload descriptor
+ *
+ * flags:	descriptor type
+ * numDesc:	must be 1
+ * ipsecFlags:	bit 0: 0 -- generate IV, 1 -- use supplied IV
+ * sa1, sa2:	Security Association IDs for this packet
+ * reserved:	set to 0
+ */
+struct ipsec_desc {
+	u8  flags;
+	u8  numDesc;
+	__le16 ipsecFlags;
+#define TYPHOON_IPSEC_GEN_IV	cpu_to_le16(0x0000)
+#define TYPHOON_IPSEC_USE_IV	cpu_to_le16(0x0001)
+	__le32 sa1;
+	__le32 sa2;
+	__le32 reserved;
+} __packed;
+
+/* The Typhoon receive descriptor (Updated by NIC)
+ *
+ * flags:         Descriptor type, error indication
+ * numDesc:       Always zero
+ * frameLen:      the size of the packet received
+ * addr:          low 32 bytes of the virtual addr passed in for this buffer
+ * addrHi:        high 32 bytes of the virtual addr passed in for this buffer
+ * rxStatus:      Error if set in flags, otherwise result of offload processing
+ * filterResults: results of filtering on packet, not used
+ * ipsecResults:  Results of IPSEC processing
+ * vlanTag:       the 801.2q TCI from the packet
+ */
+struct rx_desc {
+	u8  flags;
+	u8  numDesc;
+	__le16 frameLen;
+	u32 addr;	/* opaque, comes from virtAddr */
+	u32 addrHi;	/* opaque, comes from virtAddrHi */
+	__le32 rxStatus;
+#define TYPHOON_RX_ERR_INTERNAL		cpu_to_le32(0x00000000)
+#define TYPHOON_RX_ERR_FIFO_UNDERRUN	cpu_to_le32(0x00000001)
+#define TYPHOON_RX_ERR_BAD_SSD		cpu_to_le32(0x00000002)
+#define TYPHOON_RX_ERR_RUNT		cpu_to_le32(0x00000003)
+#define TYPHOON_RX_ERR_CRC		cpu_to_le32(0x00000004)
+#define TYPHOON_RX_ERR_OVERSIZE		cpu_to_le32(0x00000005)
+#define TYPHOON_RX_ERR_ALIGN		cpu_to_le32(0x00000006)
+#define TYPHOON_RX_ERR_DRIBBLE		cpu_to_le32(0x00000007)
+#define TYPHOON_RX_PROTO_MASK		cpu_to_le32(0x00000003)
+#define TYPHOON_RX_PROTO_UNKNOWN	cpu_to_le32(0x00000000)
+#define TYPHOON_RX_PROTO_IP		cpu_to_le32(0x00000001)
+#define TYPHOON_RX_PROTO_IPX		cpu_to_le32(0x00000002)
+#define TYPHOON_RX_VLAN			cpu_to_le32(0x00000004)
+#define TYPHOON_RX_IP_FRAG		cpu_to_le32(0x00000008)
+#define TYPHOON_RX_IPSEC		cpu_to_le32(0x00000010)
+#define TYPHOON_RX_IP_CHK_FAIL		cpu_to_le32(0x00000020)
+#define TYPHOON_RX_TCP_CHK_FAIL		cpu_to_le32(0x00000040)
+#define TYPHOON_RX_UDP_CHK_FAIL		cpu_to_le32(0x00000080)
+#define TYPHOON_RX_IP_CHK_GOOD		cpu_to_le32(0x00000100)
+#define TYPHOON_RX_TCP_CHK_GOOD		cpu_to_le32(0x00000200)
+#define TYPHOON_RX_UDP_CHK_GOOD		cpu_to_le32(0x00000400)
+	__le16 filterResults;
+#define TYPHOON_RX_FILTER_MASK		cpu_to_le16(0x7fff)
+#define TYPHOON_RX_FILTERED		cpu_to_le16(0x8000)
+	__le16 ipsecResults;
+#define TYPHOON_RX_OUTER_AH_GOOD	cpu_to_le16(0x0001)
+#define TYPHOON_RX_OUTER_ESP_GOOD	cpu_to_le16(0x0002)
+#define TYPHOON_RX_INNER_AH_GOOD	cpu_to_le16(0x0004)
+#define TYPHOON_RX_INNER_ESP_GOOD	cpu_to_le16(0x0008)
+#define TYPHOON_RX_OUTER_AH_FAIL	cpu_to_le16(0x0010)
+#define TYPHOON_RX_OUTER_ESP_FAIL	cpu_to_le16(0x0020)
+#define TYPHOON_RX_INNER_AH_FAIL	cpu_to_le16(0x0040)
+#define TYPHOON_RX_INNER_ESP_FAIL	cpu_to_le16(0x0080)
+#define TYPHOON_RX_UNKNOWN_SA		cpu_to_le16(0x0100)
+#define TYPHOON_RX_ESP_FORMAT_ERR	cpu_to_le16(0x0200)
+	__be32 vlanTag;
+} __packed;
+
+/* The Typhoon free buffer descriptor, used to give a buffer to the NIC
+ *
+ * physAddr:    low 32 bits of the bus address of the buffer
+ * physAddrHi:  high 32 bits of the bus address of the buffer, always zero
+ * virtAddr:    low 32 bits of the skb address
+ * virtAddrHi:  high 32 bits of the skb address, always zero
+ *
+ * the virt* address is basically two 32 bit cookies, just passed back
+ * from the NIC
+ */
+struct rx_free {
+	__le32 physAddr;
+	__le32 physAddrHi;
+	u32 virtAddr;
+	u32 virtAddrHi;
+} __packed;
+
+/* The Typhoon command descriptor, used for commands and responses
+ *
+ * flags:   descriptor type
+ * numDesc: number of descriptors following in this command/response,
+ *				ie, zero for a one descriptor command
+ * cmd:     the command
+ * seqNo:   sequence number (unused)
+ * parm1:   use varies by command
+ * parm2:   use varies by command
+ * parm3:   use varies by command
+ */
+struct cmd_desc {
+	u8  flags;
+	u8  numDesc;
+	__le16 cmd;
+#define TYPHOON_CMD_TX_ENABLE		cpu_to_le16(0x0001)
+#define TYPHOON_CMD_TX_DISABLE		cpu_to_le16(0x0002)
+#define TYPHOON_CMD_RX_ENABLE		cpu_to_le16(0x0003)
+#define TYPHOON_CMD_RX_DISABLE		cpu_to_le16(0x0004)
+#define TYPHOON_CMD_SET_RX_FILTER	cpu_to_le16(0x0005)
+#define TYPHOON_CMD_READ_STATS		cpu_to_le16(0x0007)
+#define TYPHOON_CMD_XCVR_SELECT		cpu_to_le16(0x0013)
+#define TYPHOON_CMD_SET_MAX_PKT_SIZE	cpu_to_le16(0x001a)
+#define TYPHOON_CMD_READ_MEDIA_STATUS	cpu_to_le16(0x001b)
+#define TYPHOON_CMD_GOTO_SLEEP		cpu_to_le16(0x0023)
+#define TYPHOON_CMD_SET_MULTICAST_HASH	cpu_to_le16(0x0025)
+#define TYPHOON_CMD_SET_MAC_ADDRESS	cpu_to_le16(0x0026)
+#define TYPHOON_CMD_READ_MAC_ADDRESS	cpu_to_le16(0x0027)
+#define TYPHOON_CMD_VLAN_TYPE_WRITE	cpu_to_le16(0x002b)
+#define TYPHOON_CMD_CREATE_SA		cpu_to_le16(0x0034)
+#define TYPHOON_CMD_DELETE_SA		cpu_to_le16(0x0035)
+#define TYPHOON_CMD_READ_VERSIONS	cpu_to_le16(0x0043)
+#define TYPHOON_CMD_IRQ_COALESCE_CTRL	cpu_to_le16(0x0045)
+#define TYPHOON_CMD_ENABLE_WAKE_EVENTS	cpu_to_le16(0x0049)
+#define TYPHOON_CMD_SET_OFFLOAD_TASKS	cpu_to_le16(0x004f)
+#define TYPHOON_CMD_HELLO_RESP		cpu_to_le16(0x0057)
+#define TYPHOON_CMD_HALT		cpu_to_le16(0x005d)
+#define TYPHOON_CMD_READ_IPSEC_INFO	cpu_to_le16(0x005e)
+#define TYPHOON_CMD_GET_IPSEC_ENABLE	cpu_to_le16(0x0067)
+#define TYPHOON_CMD_GET_CMD_LVL		cpu_to_le16(0x0069)
+	u16 seqNo;
+	__le16 parm1;
+	__le32 parm2;
+	__le32 parm3;
+} __packed;
+
+/* The Typhoon response descriptor, see command descriptor for details
+ */
+struct resp_desc {
+	u8  flags;
+	u8  numDesc;
+	__le16 cmd;
+	__le16 seqNo;
+	__le16 parm1;
+	__le32 parm2;
+	__le32 parm3;
+} __packed;
+
+#define INIT_COMMAND_NO_RESPONSE(x, command)				\
+	do { struct cmd_desc *_ptr = (x);				\
+		memset(_ptr, 0, sizeof(struct cmd_desc));		\
+		_ptr->flags = TYPHOON_CMD_DESC | TYPHOON_DESC_VALID;	\
+		_ptr->cmd = command;					\
+	} while(0)
+
+/* We set seqNo to 1 if we're expecting a response from this command */
+#define INIT_COMMAND_WITH_RESPONSE(x, command)				\
+	do { struct cmd_desc *_ptr = (x);				\
+		memset(_ptr, 0, sizeof(struct cmd_desc));		\
+		_ptr->flags = TYPHOON_CMD_RESPOND | TYPHOON_CMD_DESC;	\
+		_ptr->flags |= TYPHOON_DESC_VALID; 			\
+		_ptr->cmd = command;					\
+		_ptr->seqNo = 1;					\
+	} while(0)
+
+/* TYPHOON_CMD_SET_RX_FILTER filter bits (cmd.parm1)
+ */
+#define TYPHOON_RX_FILTER_DIRECTED	cpu_to_le16(0x0001)
+#define TYPHOON_RX_FILTER_ALL_MCAST	cpu_to_le16(0x0002)
+#define TYPHOON_RX_FILTER_BROADCAST	cpu_to_le16(0x0004)
+#define TYPHOON_RX_FILTER_PROMISCOUS	cpu_to_le16(0x0008)
+#define TYPHOON_RX_FILTER_MCAST_HASH	cpu_to_le16(0x0010)
+
+/* TYPHOON_CMD_READ_STATS response format
+ */
+struct stats_resp {
+	u8  flags;
+	u8  numDesc;
+	__le16 cmd;
+	__le16 seqNo;
+	__le16 unused;
+	__le32 txPackets;
+	__le64 txBytes;
+	__le32 txDeferred;
+	__le32 txLateCollisions;
+	__le32 txCollisions;
+	__le32 txCarrierLost;
+	__le32 txMultipleCollisions;
+	__le32 txExcessiveCollisions;
+	__le32 txFifoUnderruns;
+	__le32 txMulticastTxOverflows;
+	__le32 txFiltered;
+	__le32 rxPacketsGood;
+	__le64 rxBytesGood;
+	__le32 rxFifoOverruns;
+	__le32 BadSSD;
+	__le32 rxCrcErrors;
+	__le32 rxOversized;
+	__le32 rxBroadcast;
+	__le32 rxMulticast;
+	__le32 rxOverflow;
+	__le32 rxFiltered;
+	__le32 linkStatus;
+#define TYPHOON_LINK_STAT_MASK		cpu_to_le32(0x00000001)
+#define TYPHOON_LINK_GOOD		cpu_to_le32(0x00000001)
+#define TYPHOON_LINK_BAD		cpu_to_le32(0x00000000)
+#define TYPHOON_LINK_SPEED_MASK		cpu_to_le32(0x00000002)
+#define TYPHOON_LINK_100MBPS		cpu_to_le32(0x00000002)
+#define TYPHOON_LINK_10MBPS		cpu_to_le32(0x00000000)
+#define TYPHOON_LINK_DUPLEX_MASK	cpu_to_le32(0x00000004)
+#define TYPHOON_LINK_FULL_DUPLEX	cpu_to_le32(0x00000004)
+#define TYPHOON_LINK_HALF_DUPLEX	cpu_to_le32(0x00000000)
+	__le32 unused2;
+	__le32 unused3;
+} __packed;
+
+/* TYPHOON_CMD_XCVR_SELECT xcvr values (resp.parm1)
+ */
+#define TYPHOON_XCVR_10HALF	cpu_to_le16(0x0000)
+#define TYPHOON_XCVR_10FULL	cpu_to_le16(0x0001)
+#define TYPHOON_XCVR_100HALF	cpu_to_le16(0x0002)
+#define TYPHOON_XCVR_100FULL	cpu_to_le16(0x0003)
+#define TYPHOON_XCVR_AUTONEG	cpu_to_le16(0x0004)
+
+/* TYPHOON_CMD_READ_MEDIA_STATUS (resp.parm1)
+ */
+#define TYPHOON_MEDIA_STAT_CRC_STRIP_DISABLE	cpu_to_le16(0x0004)
+#define TYPHOON_MEDIA_STAT_COLLISION_DETECT	cpu_to_le16(0x0010)
+#define TYPHOON_MEDIA_STAT_CARRIER_SENSE	cpu_to_le16(0x0020)
+#define TYPHOON_MEDIA_STAT_POLARITY_REV		cpu_to_le16(0x0400)
+#define TYPHOON_MEDIA_STAT_NO_LINK		cpu_to_le16(0x0800)
+
+/* TYPHOON_CMD_SET_MULTICAST_HASH enable values (cmd.parm1)
+ */
+#define TYPHOON_MCAST_HASH_DISABLE	cpu_to_le16(0x0000)
+#define TYPHOON_MCAST_HASH_ENABLE	cpu_to_le16(0x0001)
+#define TYPHOON_MCAST_HASH_SET		cpu_to_le16(0x0002)
+
+/* TYPHOON_CMD_CREATE_SA descriptor and settings
+ */
+struct sa_descriptor {
+	u8  flags;
+	u8  numDesc;
+	u16 cmd;
+	u16 seqNo;
+	u16 mode;
+#define TYPHOON_SA_MODE_NULL		cpu_to_le16(0x0000)
+#define TYPHOON_SA_MODE_AH		cpu_to_le16(0x0001)
+#define TYPHOON_SA_MODE_ESP		cpu_to_le16(0x0002)
+	u8  hashFlags;
+#define TYPHOON_SA_HASH_ENABLE		0x01
+#define TYPHOON_SA_HASH_SHA1		0x02
+#define TYPHOON_SA_HASH_MD5		0x04
+	u8  direction;
+#define TYPHOON_SA_DIR_RX		0x00
+#define TYPHOON_SA_DIR_TX		0x01
+	u8  encryptionFlags;
+#define TYPHOON_SA_ENCRYPT_ENABLE	0x01
+#define TYPHOON_SA_ENCRYPT_DES		0x02
+#define TYPHOON_SA_ENCRYPT_3DES		0x00
+#define TYPHOON_SA_ENCRYPT_3DES_2KEY	0x00
+#define TYPHOON_SA_ENCRYPT_3DES_3KEY	0x04
+#define TYPHOON_SA_ENCRYPT_CBC		0x08
+#define TYPHOON_SA_ENCRYPT_ECB		0x00
+	u8  specifyIndex;
+#define TYPHOON_SA_SPECIFY_INDEX	0x01
+#define TYPHOON_SA_GENERATE_INDEX	0x00
+	u32 SPI;
+	u32 destAddr;
+	u32 destMask;
+	u8  integKey[20];
+	u8  confKey[24];
+	u32 index;
+	u32 unused;
+	u32 unused2;
+} __packed;
+
+/* TYPHOON_CMD_SET_OFFLOAD_TASKS bits (cmd.parm2 (Tx) & cmd.parm3 (Rx))
+ * This is all for IPv4.
+ */
+#define TYPHOON_OFFLOAD_TCP_CHKSUM	cpu_to_le32(0x00000002)
+#define TYPHOON_OFFLOAD_UDP_CHKSUM	cpu_to_le32(0x00000004)
+#define TYPHOON_OFFLOAD_IP_CHKSUM	cpu_to_le32(0x00000008)
+#define TYPHOON_OFFLOAD_IPSEC		cpu_to_le32(0x00000010)
+#define TYPHOON_OFFLOAD_BCAST_THROTTLE	cpu_to_le32(0x00000020)
+#define TYPHOON_OFFLOAD_DHCP_PREVENT	cpu_to_le32(0x00000040)
+#define TYPHOON_OFFLOAD_VLAN		cpu_to_le32(0x00000080)
+#define TYPHOON_OFFLOAD_FILTERING	cpu_to_le32(0x00000100)
+#define TYPHOON_OFFLOAD_TCP_SEGMENT	cpu_to_le32(0x00000200)
+
+/* TYPHOON_CMD_ENABLE_WAKE_EVENTS bits (cmd.parm1)
+ */
+#define TYPHOON_WAKE_MAGIC_PKT		cpu_to_le16(0x01)
+#define TYPHOON_WAKE_LINK_EVENT		cpu_to_le16(0x02)
+#define TYPHOON_WAKE_ICMP_ECHO		cpu_to_le16(0x04)
+#define TYPHOON_WAKE_ARP		cpu_to_le16(0x08)
+
+/* These are used to load the firmware image on the NIC
+ */
+struct typhoon_file_header {
+	u8  tag[8];
+	__le32 version;
+	__le32 numSections;
+	__le32 startAddr;
+	__le32 hmacDigest[5];
+} __packed;
+
+struct typhoon_section_header {
+	__le32 len;
+	u16 checksum;
+	u16 reserved;
+	__le32 startAddr;
+} __packed;
+
+/* The Typhoon Register offsets
+ */
+#define TYPHOON_REG_SOFT_RESET			0x00
+#define TYPHOON_REG_INTR_STATUS			0x04
+#define TYPHOON_REG_INTR_ENABLE			0x08
+#define TYPHOON_REG_INTR_MASK			0x0c
+#define TYPHOON_REG_SELF_INTERRUPT		0x10
+#define TYPHOON_REG_HOST2ARM7			0x14
+#define TYPHOON_REG_HOST2ARM6			0x18
+#define TYPHOON_REG_HOST2ARM5			0x1c
+#define TYPHOON_REG_HOST2ARM4			0x20
+#define TYPHOON_REG_HOST2ARM3			0x24
+#define TYPHOON_REG_HOST2ARM2			0x28
+#define TYPHOON_REG_HOST2ARM1			0x2c
+#define TYPHOON_REG_HOST2ARM0			0x30
+#define TYPHOON_REG_ARM2HOST3			0x34
+#define TYPHOON_REG_ARM2HOST2			0x38
+#define TYPHOON_REG_ARM2HOST1			0x3c
+#define TYPHOON_REG_ARM2HOST0			0x40
+
+#define TYPHOON_REG_BOOT_DATA_LO		TYPHOON_REG_HOST2ARM5
+#define TYPHOON_REG_BOOT_DATA_HI		TYPHOON_REG_HOST2ARM4
+#define TYPHOON_REG_BOOT_DEST_ADDR		TYPHOON_REG_HOST2ARM3
+#define TYPHOON_REG_BOOT_CHECKSUM		TYPHOON_REG_HOST2ARM2
+#define TYPHOON_REG_BOOT_LENGTH			TYPHOON_REG_HOST2ARM1
+
+#define TYPHOON_REG_DOWNLOAD_BOOT_ADDR		TYPHOON_REG_HOST2ARM1
+#define TYPHOON_REG_DOWNLOAD_HMAC_0		TYPHOON_REG_HOST2ARM2
+#define TYPHOON_REG_DOWNLOAD_HMAC_1		TYPHOON_REG_HOST2ARM3
+#define TYPHOON_REG_DOWNLOAD_HMAC_2		TYPHOON_REG_HOST2ARM4
+#define TYPHOON_REG_DOWNLOAD_HMAC_3		TYPHOON_REG_HOST2ARM5
+#define TYPHOON_REG_DOWNLOAD_HMAC_4		TYPHOON_REG_HOST2ARM6
+
+#define TYPHOON_REG_BOOT_RECORD_ADDR_HI		TYPHOON_REG_HOST2ARM2
+#define TYPHOON_REG_BOOT_RECORD_ADDR_LO		TYPHOON_REG_HOST2ARM1
+
+#define TYPHOON_REG_TX_LO_READY			TYPHOON_REG_HOST2ARM3
+#define TYPHOON_REG_CMD_READY			TYPHOON_REG_HOST2ARM2
+#define TYPHOON_REG_TX_HI_READY			TYPHOON_REG_HOST2ARM1
+
+#define TYPHOON_REG_COMMAND			TYPHOON_REG_HOST2ARM0
+#define TYPHOON_REG_HEARTBEAT			TYPHOON_REG_ARM2HOST3
+#define TYPHOON_REG_STATUS			TYPHOON_REG_ARM2HOST0
+
+/* 3XP Reset values (TYPHOON_REG_SOFT_RESET)
+ */
+#define TYPHOON_RESET_ALL	0x7f
+#define TYPHOON_RESET_NONE	0x00
+
+/* 3XP irq bits (TYPHOON_REG_INTR{STATUS,ENABLE,MASK})
+ *
+ * Some of these came from OpenBSD, as the 3Com docs have it wrong
+ * (INTR_SELF) or don't list it at all (INTR_*_ABORT)
+ *
+ * Enabling irqs on the Heartbeat reg (ArmToHost3) gets you an irq
+ * about every 8ms, so don't do it.
+ */
+#define TYPHOON_INTR_HOST_INT		0x00000001
+#define TYPHOON_INTR_ARM2HOST0		0x00000002
+#define TYPHOON_INTR_ARM2HOST1		0x00000004
+#define TYPHOON_INTR_ARM2HOST2		0x00000008
+#define TYPHOON_INTR_ARM2HOST3		0x00000010
+#define TYPHOON_INTR_DMA0		0x00000020
+#define TYPHOON_INTR_DMA1		0x00000040
+#define TYPHOON_INTR_DMA2		0x00000080
+#define TYPHOON_INTR_DMA3		0x00000100
+#define TYPHOON_INTR_MASTER_ABORT	0x00000200
+#define TYPHOON_INTR_TARGET_ABORT	0x00000400
+#define TYPHOON_INTR_SELF		0x00000800
+#define TYPHOON_INTR_RESERVED		0xfffff000
+
+#define TYPHOON_INTR_BOOTCMD		TYPHOON_INTR_ARM2HOST0
+
+#define TYPHOON_INTR_ENABLE_ALL		0xffffffef
+#define TYPHOON_INTR_ALL		0xffffffff
+#define TYPHOON_INTR_NONE		0x00000000
+
+/* The commands for the 3XP chip (TYPHOON_REG_COMMAND)
+ */
+#define TYPHOON_BOOTCMD_BOOT			0x00
+#define TYPHOON_BOOTCMD_WAKEUP			0xfa
+#define TYPHOON_BOOTCMD_DNLD_COMPLETE		0xfb
+#define TYPHOON_BOOTCMD_SEG_AVAILABLE		0xfc
+#define TYPHOON_BOOTCMD_RUNTIME_IMAGE		0xfd
+#define TYPHOON_BOOTCMD_REG_BOOT_RECORD		0xff
+
+/* 3XP Status values (TYPHOON_REG_STATUS)
+ */
+#define TYPHOON_STATUS_WAITING_FOR_BOOT		0x07
+#define TYPHOON_STATUS_SECOND_INIT		0x08
+#define TYPHOON_STATUS_RUNNING			0x09
+#define TYPHOON_STATUS_WAITING_FOR_HOST		0x0d
+#define TYPHOON_STATUS_WAITING_FOR_SEGMENT	0x10
+#define TYPHOON_STATUS_SLEEPING			0x11
+#define TYPHOON_STATUS_HALTED			0x14
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/3c503.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/3c503.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/3c503.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/3c503.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,778 @@
+/* 3c503.c: A shared-memory NS8390 ethernet driver for linux. */
+/*
+    Written 1992-94 by Donald Becker.
+
+    Copyright 1993 United States Government as represented by the
+    Director, National Security Agency.  This software may be used and
+    distributed according to the terms of the GNU General Public License,
+    incorporated herein by reference.
+
+    The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+
+    This driver should work with the 3c503 and 3c503/16.  It should be used
+    in shared memory mode for best performance, although it may also work
+    in programmed-I/O mode.
+
+    Sources:
+    EtherLink II Technical Reference Manual,
+    EtherLink II/16 Technical Reference Manual Supplement,
+    3Com Corporation, 5400 Bayfront Plaza, Santa Clara CA 95052-8145
+
+    The Crynwr 3c503 packet driver.
+
+    Changelog:
+
+    Paul Gortmaker	: add support for the 2nd 8kB of RAM on 16 bit cards.
+    Paul Gortmaker	: multiple card support for module users.
+    rjohnson@analogic.com : Fix up PIO interface for efficient operation.
+    Jeff Garzik		: ethtool support
+
+*/
+
+#define DRV_NAME	"3c503"
+#define DRV_VERSION	"1.10a"
+#define DRV_RELDATE	"11/17/2001"
+
+
+static const char version[] =
+    DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Donald Becker (becker@scyld.com)\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+
+#include "8390.h"
+#include "3c503.h"
+#define WRD_COUNT 4
+
+static int el2_pio_probe(struct net_device *dev);
+static int el2_probe1(struct net_device *dev, int ioaddr);
+
+/* A zero-terminated list of I/O addresses to be probed in PIO mode. */
+static unsigned int netcard_portlist[] __initdata =
+	{ 0x300,0x310,0x330,0x350,0x250,0x280,0x2a0,0x2e0,0};
+
+#define EL2_IO_EXTENT	16
+
+static int el2_open(struct net_device *dev);
+static int el2_close(struct net_device *dev);
+static void el2_reset_8390(struct net_device *dev);
+static void el2_init_card(struct net_device *dev);
+static void el2_block_output(struct net_device *dev, int count,
+			     const unsigned char *buf, int start_page);
+static void el2_block_input(struct net_device *dev, int count, struct sk_buff *skb,
+			   int ring_offset);
+static void el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+			 int ring_page);
+static const struct ethtool_ops netdev_ethtool_ops;
+
+
+/* This routine probes for a memory-mapped 3c503 board by looking for
+   the "location register" at the end of the jumpered boot PROM space.
+   This works even if a PROM isn't there.
+
+   If the ethercard isn't found there is an optional probe for
+   ethercard jumpered to programmed-I/O mode.
+   */
+static int __init do_el2_probe(struct net_device *dev)
+{
+    int *addr, addrs[] = { 0xddffe, 0xd9ffe, 0xcdffe, 0xc9ffe, 0};
+    int base_addr = dev->base_addr;
+    int irq = dev->irq;
+
+    if (base_addr > 0x1ff)	/* Check a single specified location. */
+	return el2_probe1(dev, base_addr);
+    else if (base_addr != 0)		/* Don't probe at all. */
+	return -ENXIO;
+
+    for (addr = addrs; *addr; addr++) {
+	void __iomem *p = ioremap(*addr, 1);
+	unsigned base_bits;
+	int i;
+
+	if (!p)
+		continue;
+	base_bits = readb(p);
+	iounmap(p);
+	i = ffs(base_bits) - 1;
+	if (i == -1 || base_bits != (1 << i))
+	    continue;
+	if (el2_probe1(dev, netcard_portlist[i]) == 0)
+	    return 0;
+	dev->irq = irq;
+    }
+#if ! defined(no_probe_nonshared_memory)
+    return el2_pio_probe(dev);
+#else
+    return -ENODEV;
+#endif
+}
+
+/*  Try all of the locations that aren't obviously empty.  This touches
+    a lot of locations, and is much riskier than the code above. */
+static int __init
+el2_pio_probe(struct net_device *dev)
+{
+    int i;
+    int base_addr = dev->base_addr;
+    int irq = dev->irq;
+
+    if (base_addr > 0x1ff)	/* Check a single specified location. */
+	return el2_probe1(dev, base_addr);
+    else if (base_addr != 0)	/* Don't probe at all. */
+	return -ENXIO;
+
+    for (i = 0; netcard_portlist[i]; i++) {
+	if (el2_probe1(dev, netcard_portlist[i]) == 0)
+	    return 0;
+	dev->irq = irq;
+    }
+
+    return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init el2_probe(int unit)
+{
+	struct net_device *dev = alloc_eip_netdev();
+	int err;
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+
+	err = do_el2_probe(dev);
+	if (err)
+		goto out;
+	return dev;
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+#endif
+
+static const struct net_device_ops el2_netdev_ops = {
+	.ndo_open		= el2_open,
+	.ndo_stop		= el2_close,
+
+	.ndo_start_xmit		= eip_start_xmit,
+	.ndo_tx_timeout		= eip_tx_timeout,
+	.ndo_get_stats		= eip_get_stats,
+	.ndo_set_rx_mode	= eip_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 	= eip_poll,
+#endif
+};
+
+/* Probe for the Etherlink II card at I/O port base IOADDR,
+   returning non-zero on success.  If found, set the station
+   address and memory parameters in DEVICE. */
+static int __init
+el2_probe1(struct net_device *dev, int ioaddr)
+{
+    int i, iobase_reg, membase_reg, saved_406, wordlength, retval;
+    static unsigned version_printed;
+    unsigned long vendor_id;
+
+    if (!request_region(ioaddr, EL2_IO_EXTENT, DRV_NAME))
+	return -EBUSY;
+
+    if (!request_region(ioaddr + 0x400, 8, DRV_NAME)) {
+	retval = -EBUSY;
+	goto out;
+    }
+
+    /* Reset and/or avoid any lurking NE2000 */
+    if (inb(ioaddr + 0x408) == 0xff) {
+    	mdelay(1);
+	retval = -ENODEV;
+	goto out1;
+    }
+
+    /* We verify that it's a 3C503 board by checking the first three octets
+       of its ethernet address. */
+    iobase_reg = inb(ioaddr+0x403);
+    membase_reg = inb(ioaddr+0x404);
+    /* ASIC location registers should be 0 or have only a single bit set. */
+    if ((iobase_reg  & (iobase_reg - 1)) ||
+	(membase_reg & (membase_reg - 1))) {
+	retval = -ENODEV;
+	goto out1;
+    }
+    saved_406 = inb_p(ioaddr + 0x406);
+    outb_p(ECNTRL_RESET|ECNTRL_THIN, ioaddr + 0x406); /* Reset it... */
+    outb_p(ECNTRL_THIN, ioaddr + 0x406);
+    /* Map the station addr PROM into the lower I/O ports. We now check
+       for both the old and new 3Com prefix */
+    outb(ECNTRL_SAPROM|ECNTRL_THIN, ioaddr + 0x406);
+    vendor_id = inb(ioaddr)*0x10000 + inb(ioaddr + 1)*0x100 + inb(ioaddr + 2);
+    if ((vendor_id != OLD_3COM_ID) && (vendor_id != NEW_3COM_ID)) {
+	/* Restore the register we frobbed. */
+	outb(saved_406, ioaddr + 0x406);
+	retval = -ENODEV;
+	goto out1;
+    }
+
+    if (ei_debug  &&  version_printed++ == 0)
+	pr_debug("%s", version);
+
+    dev->base_addr = ioaddr;
+
+    pr_info("%s: 3c503 at i/o base %#3x, node ", dev->name, ioaddr);
+
+    /* Retrieve and print the ethernet address. */
+    for (i = 0; i < 6; i++)
+	dev->dev_addr[i] = inb(ioaddr + i);
+    pr_cont("%pM", dev->dev_addr);
+
+    /* Map the 8390 back into the window. */
+    outb(ECNTRL_THIN, ioaddr + 0x406);
+
+    /* Check for EL2/16 as described in tech. man. */
+    outb_p(E8390_PAGE0, ioaddr + E8390_CMD);
+    outb_p(0, ioaddr + EN0_DCFG);
+    outb_p(E8390_PAGE2, ioaddr + E8390_CMD);
+    wordlength = inb_p(ioaddr + EN0_DCFG) & ENDCFG_WTS;
+    outb_p(E8390_PAGE0, ioaddr + E8390_CMD);
+
+    /* Probe for, turn on and clear the board's shared memory. */
+    if (ei_debug > 2)
+	pr_cont(" memory jumpers %2.2x ", membase_reg);
+    outb(EGACFR_NORM, ioaddr + 0x405);	/* Enable RAM */
+
+    /* This should be probed for (or set via an ioctl()) at run-time.
+       Right now we use a sleazy hack to pass in the interface number
+       at boot-time via the low bits of the mem_end field.  That value is
+       unused, and the low bits would be discarded even if it was used. */
+#if defined(EI8390_THICK) || defined(EL2_AUI)
+    ei_status.interface_num = 1;
+#else
+    ei_status.interface_num = dev->mem_end & 0xf;
+#endif
+    pr_cont(", using %sternal xcvr.\n", ei_status.interface_num == 0 ? "in" : "ex");
+
+    if ((membase_reg & 0xf0) == 0) {
+	dev->mem_start = 0;
+	ei_status.name = "3c503-PIO";
+	ei_status.mem = NULL;
+    } else {
+	dev->mem_start = ((membase_reg & 0xc0) ? 0xD8000 : 0xC8000) +
+	    ((membase_reg & 0xA0) ? 0x4000 : 0);
+#define EL2_MEMSIZE (EL2_MB1_STOP_PG - EL2_MB1_START_PG)*256
+	ei_status.mem = ioremap(dev->mem_start, EL2_MEMSIZE);
+
+#ifdef EL2MEMTEST
+	/* This has never found an error, but someone might care.
+	   Note that it only tests the 2nd 8kB on 16kB 3c503/16
+	   cards between card addr. 0x2000 and 0x3fff. */
+	{			/* Check the card's memory. */
+	    void __iomem *mem_base = ei_status.mem;
+	    unsigned int test_val = 0xbbadf00d;
+	    writel(0xba5eba5e, mem_base);
+	    for (i = sizeof(test_val); i < EL2_MEMSIZE; i+=sizeof(test_val)) {
+		writel(test_val, mem_base + i);
+		if (readl(mem_base) != 0xba5eba5e ||
+		    readl(mem_base + i) != test_val) {
+		    pr_warning("3c503: memory failure or memory address conflict.\n");
+		    dev->mem_start = 0;
+		    ei_status.name = "3c503-PIO";
+		    iounmap(mem_base);
+		    ei_status.mem = NULL;
+		    break;
+		}
+		test_val += 0x55555555;
+		writel(0, mem_base + i);
+	    }
+	}
+#endif  /* EL2MEMTEST */
+
+	if (dev->mem_start)
+		dev->mem_end = dev->mem_start + EL2_MEMSIZE;
+
+	if (wordlength) {	/* No Tx pages to skip over to get to Rx */
+		ei_status.priv = 0;
+		ei_status.name = "3c503/16";
+	} else {
+		ei_status.priv = TX_PAGES * 256;
+		ei_status.name = "3c503";
+	}
+    }
+
+    /*
+	Divide up the memory on the card. This is the same regardless of
+	whether shared-mem or PIO is used. For 16 bit cards (16kB RAM),
+	we use the entire 8k of bank1 for an Rx ring. We only use 3k
+	of the bank0 for 2 full size Tx packet slots. For 8 bit cards,
+	(8kB RAM) we use 3kB of bank1 for two Tx slots, and the remaining
+	5kB for an Rx ring.  */
+
+    if (wordlength) {
+	ei_status.tx_start_page = EL2_MB0_START_PG;
+	ei_status.rx_start_page = EL2_MB1_START_PG;
+    } else {
+	ei_status.tx_start_page = EL2_MB1_START_PG;
+	ei_status.rx_start_page = EL2_MB1_START_PG + TX_PAGES;
+    }
+
+    /* Finish setting the board's parameters. */
+    ei_status.stop_page = EL2_MB1_STOP_PG;
+    ei_status.word16 = wordlength;
+    ei_status.reset_8390 = el2_reset_8390;
+    ei_status.get_8390_hdr = el2_get_8390_hdr;
+    ei_status.block_input = el2_block_input;
+    ei_status.block_output = el2_block_output;
+
+    if (dev->irq == 2)
+	dev->irq = 9;
+    else if (dev->irq > 5 && dev->irq != 9) {
+	pr_warning("3c503: configured interrupt %d invalid, will use autoIRQ.\n",
+	       dev->irq);
+	dev->irq = 0;
+    }
+
+    ei_status.saved_irq = dev->irq;
+
+    dev->netdev_ops = &el2_netdev_ops;
+    dev->ethtool_ops = &netdev_ethtool_ops;
+
+    retval = register_netdev(dev);
+    if (retval)
+	goto out1;
+
+    if (dev->mem_start)
+	pr_info("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n",
+		dev->name, ei_status.name, (wordlength+1)<<3,
+		dev->mem_start, dev->mem_end-1);
+
+    else
+    {
+	ei_status.tx_start_page = EL2_MB1_START_PG;
+	ei_status.rx_start_page = EL2_MB1_START_PG + TX_PAGES;
+	pr_info("%s: %s, %dkB RAM, using programmed I/O (REJUMPER for SHARED MEMORY).\n",
+	       dev->name, ei_status.name, (wordlength+1)<<3);
+    }
+    release_region(ioaddr + 0x400, 8);
+    return 0;
+out1:
+    release_region(ioaddr + 0x400, 8);
+out:
+    release_region(ioaddr, EL2_IO_EXTENT);
+    return retval;
+}
+
+static irqreturn_t el2_probe_interrupt(int irq, void *seen)
+{
+	*(bool *)seen = true;
+	return IRQ_HANDLED;
+}
+
+static int
+el2_open(struct net_device *dev)
+{
+    int retval;
+
+    if (dev->irq < 2) {
+	static const int irqlist[] = {5, 9, 3, 4, 0};
+	const int *irqp = irqlist;
+
+	outb(EGACFR_NORM, E33G_GACFR);	/* Enable RAM and interrupts. */
+	do {
+		bool seen;
+
+		retval = request_irq(*irqp, el2_probe_interrupt, 0,
+				     dev->name, &seen);
+		if (retval == -EBUSY)
+			continue;
+		if (retval < 0)
+			goto err_disable;
+
+		/* Twinkle the interrupt, and check if it's seen. */
+		seen = false;
+		smp_wmb();
+		outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR);
+		outb_p(0x00, E33G_IDCFR);
+		msleep(1);
+		free_irq(*irqp, &seen);
+		if (!seen)
+			continue;
+
+		retval = request_irq(dev->irq = *irqp, eip_interrupt, 0,
+				     dev->name, dev);
+		if (retval == -EBUSY)
+			continue;
+		if (retval < 0)
+			goto err_disable;
+		break;
+	} while (*++irqp);
+
+	if (*irqp == 0) {
+	err_disable:
+	    outb(EGACFR_IRQOFF, E33G_GACFR);	/* disable interrupts. */
+	    return -EAGAIN;
+	}
+    } else {
+	if ((retval = request_irq(dev->irq, eip_interrupt, 0, dev->name, dev))) {
+	    return retval;
+	}
+    }
+
+    el2_init_card(dev);
+    eip_open(dev);
+    return 0;
+}
+
+static int
+el2_close(struct net_device *dev)
+{
+    free_irq(dev->irq, dev);
+    dev->irq = ei_status.saved_irq;
+    outb(EGACFR_IRQOFF, E33G_GACFR);	/* disable interrupts. */
+
+    eip_close(dev);
+    return 0;
+}
+
+/* This is called whenever we have a unrecoverable failure:
+       transmit timeout
+       Bad ring buffer packet header
+ */
+static void
+el2_reset_8390(struct net_device *dev)
+{
+    if (ei_debug > 1) {
+	pr_debug("%s: Resetting the 3c503 board...", dev->name);
+	pr_cont(" %#lx=%#02x %#lx=%#02x %#lx=%#02x...", E33G_IDCFR, inb(E33G_IDCFR),
+	       E33G_CNTRL, inb(E33G_CNTRL), E33G_GACFR, inb(E33G_GACFR));
+    }
+    outb_p(ECNTRL_RESET|ECNTRL_THIN, E33G_CNTRL);
+    ei_status.txing = 0;
+    outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
+    el2_init_card(dev);
+    if (ei_debug > 1)
+	pr_cont("done\n");
+}
+
+/* Initialize the 3c503 GA registers after a reset. */
+static void
+el2_init_card(struct net_device *dev)
+{
+    /* Unmap the station PROM and select the DIX or BNC connector. */
+    outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
+
+    /* Set ASIC copy of rx's first and last+1 buffer pages */
+    /* These must be the same as in the 8390. */
+    outb(ei_status.rx_start_page, E33G_STARTPG);
+    outb(ei_status.stop_page,  E33G_STOPPG);
+
+    /* Point the vector pointer registers somewhere ?harmless?. */
+    outb(0xff, E33G_VP2);	/* Point at the ROM restart location 0xffff0 */
+    outb(0xff, E33G_VP1);
+    outb(0x00, E33G_VP0);
+    /* Turn off all interrupts until we're opened. */
+    outb_p(0x00,  dev->base_addr + EN0_IMR);
+    /* Enable IRQs iff started. */
+    outb(EGACFR_NORM, E33G_GACFR);
+
+    /* Set the interrupt line. */
+    outb_p((0x04 << (dev->irq == 9 ? 2 : dev->irq)), E33G_IDCFR);
+    outb_p((WRD_COUNT << 1), E33G_DRQCNT);	/* Set burst size to 8 */
+    outb_p(0x20, E33G_DMAAH);	/* Put a valid addr in the GA DMA */
+    outb_p(0x00, E33G_DMAAL);
+    return;			/* We always succeed */
+}
+
+/*
+ * Either use the shared memory (if enabled on the board) or put the packet
+ * out through the ASIC FIFO.
+ */
+static void
+el2_block_output(struct net_device *dev, int count,
+		 const unsigned char *buf, int start_page)
+{
+    unsigned short int *wrd;
+    int boguscount;		/* timeout counter */
+    unsigned short word;	/* temporary for better machine code */
+    void __iomem *base = ei_status.mem;
+
+    if (ei_status.word16)      /* Tx packets go into bank 0 on EL2/16 card */
+	outb(EGACFR_RSEL|EGACFR_TCM, E33G_GACFR);
+    else
+	outb(EGACFR_NORM, E33G_GACFR);
+
+    if (base) {	/* Shared memory transfer */
+	memcpy_toio(base + ((start_page - ei_status.tx_start_page) << 8),
+			buf, count);
+	outb(EGACFR_NORM, E33G_GACFR);	/* Back to bank1 in case on bank0 */
+	return;
+    }
+
+/*
+ *  No shared memory, put the packet out the other way.
+ *  Set up then start the internal memory transfer to Tx Start Page
+ */
+
+    word = (unsigned short)start_page;
+    outb(word&0xFF, E33G_DMAAH);
+    outb(word>>8, E33G_DMAAL);
+
+    outb_p((ei_status.interface_num ? ECNTRL_AUI : ECNTRL_THIN ) | ECNTRL_OUTPUT
+	   | ECNTRL_START, E33G_CNTRL);
+
+/*
+ *  Here I am going to write data to the FIFO as quickly as possible.
+ *  Note that E33G_FIFOH is defined incorrectly. It is really
+ *  E33G_FIFOL, the lowest port address for both the byte and
+ *  word write. Variable 'count' is NOT checked. Caller must supply a
+ *  valid count. Note that I may write a harmless extra byte to the
+ *  8390 if the byte-count was not even.
+ */
+    wrd = (unsigned short int *) buf;
+    count  = (count + 1) >> 1;
+    for(;;)
+    {
+        boguscount = 0x1000;
+        while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
+        {
+            if(!boguscount--)
+            {
+                pr_notice("%s: FIFO blocked in el2_block_output.\n", dev->name);
+                el2_reset_8390(dev);
+                goto blocked;
+            }
+        }
+        if(count > WRD_COUNT)
+        {
+            outsw(E33G_FIFOH, wrd, WRD_COUNT);
+            wrd   += WRD_COUNT;
+            count -= WRD_COUNT;
+        }
+        else
+        {
+            outsw(E33G_FIFOH, wrd, count);
+            break;
+        }
+    }
+    blocked:;
+    outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
+}
+
+/* Read the 4 byte, page aligned 8390 specific header. */
+static void
+el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+    int boguscount;
+    void __iomem *base = ei_status.mem;
+    unsigned short word;
+
+    if (base) {       /* Use the shared memory. */
+	void __iomem *hdr_start = base + ((ring_page - EL2_MB1_START_PG)<<8);
+	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	hdr->count = le16_to_cpu(hdr->count);
+	return;
+    }
+
+/*
+ *  No shared memory, use programmed I/O.
+ */
+
+    word = (unsigned short)ring_page;
+    outb(word&0xFF, E33G_DMAAH);
+    outb(word>>8, E33G_DMAAL);
+
+    outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT
+	   | ECNTRL_START, E33G_CNTRL);
+    boguscount = 0x1000;
+    while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
+    {
+        if(!boguscount--)
+        {
+            pr_notice("%s: FIFO blocked in el2_get_8390_hdr.\n", dev->name);
+            memset(hdr, 0x00, sizeof(struct e8390_pkt_hdr));
+            el2_reset_8390(dev);
+            goto blocked;
+        }
+    }
+    insw(E33G_FIFOH, hdr, (sizeof(struct e8390_pkt_hdr))>> 1);
+    blocked:;
+    outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
+}
+
+
+static void
+el2_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+    int boguscount = 0;
+    void __iomem *base = ei_status.mem;
+    unsigned short int *buf;
+    unsigned short word;
+
+    /* Maybe enable shared memory just be to be safe... nahh.*/
+    if (base) {	/* Use the shared memory. */
+	ring_offset -= (EL2_MB1_START_PG<<8);
+	if (ring_offset + count > EL2_MEMSIZE) {
+	    /* We must wrap the input move. */
+	    int semi_count = EL2_MEMSIZE - ring_offset;
+	    memcpy_fromio(skb->data, base + ring_offset, semi_count);
+	    count -= semi_count;
+	    memcpy_fromio(skb->data + semi_count, base + ei_status.priv, count);
+	} else {
+		memcpy_fromio(skb->data, base + ring_offset, count);
+	}
+	return;
+    }
+
+/*
+ *  No shared memory, use programmed I/O.
+ */
+    word = (unsigned short) ring_offset;
+    outb(word>>8, E33G_DMAAH);
+    outb(word&0xFF, E33G_DMAAL);
+
+    outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT
+	   | ECNTRL_START, E33G_CNTRL);
+
+/*
+ *  Here I also try to get data as fast as possible. I am betting that I
+ *  can read one extra byte without clobbering anything in the kernel because
+ *  this would only occur on an odd byte-count and allocation of skb->data
+ *  is word-aligned. Variable 'count' is NOT checked. Caller must check
+ *  for a valid count.
+ *  [This is currently quite safe.... but if one day the 3c503 explodes
+ *   you know where to come looking ;)]
+ */
+
+    buf =  (unsigned short int *) skb->data;
+    count =  (count + 1) >> 1;
+    for(;;)
+    {
+        boguscount = 0x1000;
+        while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
+        {
+            if(!boguscount--)
+            {
+                pr_notice("%s: FIFO blocked in el2_block_input.\n", dev->name);
+                el2_reset_8390(dev);
+                goto blocked;
+            }
+        }
+        if(count > WRD_COUNT)
+        {
+            insw(E33G_FIFOH, buf, WRD_COUNT);
+            buf   += WRD_COUNT;
+            count -= WRD_COUNT;
+        }
+        else
+        {
+            insw(E33G_FIFOH, buf, count);
+            break;
+        }
+    }
+    blocked:;
+    outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
+}
+
+
+static void netdev_get_drvinfo(struct net_device *dev,
+			       struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	sprintf(info->bus_info, "ISA 0x%lx", dev->base_addr);
+}
+
+static const struct ethtool_ops netdev_ethtool_ops = {
+	.get_drvinfo		= netdev_get_drvinfo,
+};
+
+#ifdef MODULE
+#define MAX_EL2_CARDS	4	/* Max number of EL2 cards per module */
+
+static struct net_device *dev_el2[MAX_EL2_CARDS];
+static int io[MAX_EL2_CARDS];
+static int irq[MAX_EL2_CARDS];
+static int xcvr[MAX_EL2_CARDS];	/* choose int. or ext. xcvr */
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(xcvr, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
+MODULE_PARM_DESC(xcvr, "transceiver(s) (0=internal, 1=external)");
+MODULE_DESCRIPTION("3Com ISA EtherLink II, II/16 (3c503, 3c503/16) driver");
+MODULE_LICENSE("GPL");
+
+/* This is set up so that only a single autoprobe takes place per call.
+ISA device autoprobes on a running machine are not recommended. */
+int __init
+init_module(void)
+{
+	struct net_device *dev;
+	int this_dev, found = 0;
+
+	for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) {
+		if (io[this_dev] == 0)  {
+			if (this_dev != 0) break; /* only autoprobe 1st one */
+			pr_notice("3c503.c: Presently autoprobing (not recommended) for a single card.\n");
+		}
+		dev = alloc_eip_netdev();
+		if (!dev)
+			break;
+		dev->irq = irq[this_dev];
+		dev->base_addr = io[this_dev];
+		dev->mem_end = xcvr[this_dev];	/* low 4bits = xcvr sel. */
+		if (do_el2_probe(dev) == 0) {
+			dev_el2[found++] = dev;
+			continue;
+		}
+		free_netdev(dev);
+		pr_warning("3c503.c: No 3c503 card found (i/o = 0x%x).\n", io[this_dev]);
+		break;
+	}
+	if (found)
+		return 0;
+	return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+	/* NB: el2_close() handles free_irq */
+	release_region(dev->base_addr, EL2_IO_EXTENT);
+	if (ei_status.mem)
+		iounmap(ei_status.mem);
+}
+
+void __exit
+cleanup_module(void)
+{
+	int this_dev;
+
+	for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) {
+		struct net_device *dev = dev_el2[this_dev];
+		if (dev) {
+			unregister_netdev(dev);
+			cleanup_card(dev);
+			free_netdev(dev);
+		}
+	}
+}
+#endif /* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/3c503.h linux-libre-3.2-gnu/drivers/net/ethernet/8390/3c503.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/3c503.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/3c503.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,91 @@
+/* Definitions for the 3Com 3c503 Etherlink 2. */
+/* This file is distributed under the GPL.
+   Many of these names and comments are directly from the Crynwr packet
+   drivers, which are released under the GPL. */
+
+#define EL2H (dev->base_addr + 0x400)
+#define EL2L (dev->base_addr)
+
+/* Vendor unique hardware addr. prefix. 3Com has 2 because they ran
+   out of available addresses on the first one... */
+
+#define OLD_3COM_ID	0x02608c
+#define NEW_3COM_ID	0x0020af
+
+/* Shared memory management parameters. NB: The 8 bit cards have only
+   one bank (MB1) which serves both Tx and Rx packet space. The 16bit
+   cards have 2 banks, MB0 for Tx packets, and MB1 for Rx packets.
+   You choose which bank appears in the sh. mem window with EGACFR_MBSn */
+
+#define EL2_MB0_START_PG	(0x00)	/* EL2/16 Tx packets go in bank 0 */
+#define EL2_MB1_START_PG	(0x20)	/* First page of bank 1 */
+#define EL2_MB1_STOP_PG		(0x40)	/* Last page +1 of bank 1 */
+
+/* 3Com 3c503 ASIC registers */
+#define E33G_STARTPG	(EL2H+0)	/* Start page, matching EN0_STARTPG */
+#define E33G_STOPPG	(EL2H+1)	/* Stop page, must match EN0_STOPPG */
+#define E33G_DRQCNT	(EL2H+2)	/* DMA burst count */
+#define E33G_IOBASE	(EL2H+3)	/* Read of I/O base jumpers. */
+	/* (non-useful, but it also appears at the end of EPROM space) */
+#define E33G_ROMBASE	(EL2H+4)	/* Read of memory base jumpers. */
+#define E33G_GACFR	(EL2H+5)	/* Config/setup bits for the ASIC GA */
+#define E33G_CNTRL	(EL2H+6)	/* Board's main control register */
+#define E33G_STATUS	(EL2H+7)	/* Status on completions. */
+#define E33G_IDCFR	(EL2H+8)	/* Interrupt/DMA config register */
+				/* (Which IRQ to assert, DMA chan to use) */
+#define E33G_DMAAH	(EL2H+9)	/* High byte of DMA address reg */
+#define E33G_DMAAL	(EL2H+10)	/* Low byte of DMA address reg */
+/* "Vector pointer" - if this address matches a read, the EPROM (rather than
+   shared RAM) is mapped into memory space. */
+#define E33G_VP2	(EL2H+11)
+#define E33G_VP1	(EL2H+12)
+#define E33G_VP0	(EL2H+13)
+#define E33G_FIFOH	(EL2H+14)	/* FIFO for programmed I/O moves */
+#define E33G_FIFOL	(EL2H+15)	/* ... low byte of above. */
+
+/* Bits in E33G_CNTRL register: */
+
+#define ECNTRL_RESET	(0x01)	/* Software reset of the ASIC and 8390 */
+#define ECNTRL_THIN	(0x02)	/* Onboard xcvr enable, AUI disable */
+#define ECNTRL_AUI	(0x00)	/* Onboard xcvr disable, AUI enable */
+#define ECNTRL_SAPROM	(0x04)	/* Map the station address prom */
+#define ECNTRL_DBLBFR	(0x20)	/* FIFO configuration bit */
+#define ECNTRL_OUTPUT	(0x40)	/* PC-to-3C503 direction if 1 */
+#define ECNTRL_INPUT	(0x00)	/* 3C503-to-PC direction if 0 */
+#define ECNTRL_START	(0x80)	/* Start the DMA logic */
+
+/* Bits in E33G_STATUS register: */
+
+#define ESTAT_DPRDY	(0x80)	/* Data port (of FIFO) ready */
+#define ESTAT_UFLW	(0x40)	/* Tried to read FIFO when it was empty */
+#define ESTAT_OFLW	(0x20)	/* Tried to write FIFO when it was full */
+#define ESTAT_DTC	(0x10)	/* Terminal Count from PC bus DMA logic */
+#define ESTAT_DIP	(0x08)	/* DMA In Progress */
+
+/* Bits in E33G_GACFR register: */
+
+#define EGACFR_NIM	(0x80)	/* NIC interrupt mask */
+#define EGACFR_TCM	(0x40)	/* DMA term. count interrupt mask */
+#define EGACFR_RSEL	(0x08)	/* Map a bank of card mem into system mem */
+#define EGACFR_MBS2	(0x04)	/* Memory bank select, bit 2. */
+#define EGACFR_MBS1	(0x02)	/* Memory bank select, bit 1. */
+#define EGACFR_MBS0	(0x01)	/* Memory bank select, bit 0. */
+
+#define EGACFR_NORM	(0x49)	/* TCM | RSEL | MBS0 */
+#define EGACFR_IRQOFF	(0xc9)	/* TCM | RSEL | MBS0 | NIM */
+
+/*
+	MBS2	MBS1	MBS0	Sh. mem windows card mem at:
+	----	----	----	-----------------------------
+	0	0	0	0x0000 -- bank 0
+	0	0	1	0x2000 -- bank 1 (only choice for 8bit card)
+	0	1	0	0x4000 -- bank 2, not used
+	0	1	1	0x6000 -- bank 3, not used
+
+There was going to be a 32k card that used bank 2 and 3, but it
+never got produced.
+
+*/
+
+
+/* End of 3C503 parameter definitions */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/8390.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/8390.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/8390.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/8390.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,103 @@
+/* 8390 core for usual drivers */
+
+static const char version[] =
+    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include "lib8390.c"
+
+int ei_open(struct net_device *dev)
+{
+	return __ei_open(dev);
+}
+EXPORT_SYMBOL(ei_open);
+
+int ei_close(struct net_device *dev)
+{
+	return __ei_close(dev);
+}
+EXPORT_SYMBOL(ei_close);
+
+netdev_tx_t ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	return __ei_start_xmit(skb, dev);
+}
+EXPORT_SYMBOL(ei_start_xmit);
+
+struct net_device_stats *ei_get_stats(struct net_device *dev)
+{
+	return __ei_get_stats(dev);
+}
+EXPORT_SYMBOL(ei_get_stats);
+
+void ei_set_multicast_list(struct net_device *dev)
+{
+	__ei_set_multicast_list(dev);
+}
+EXPORT_SYMBOL(ei_set_multicast_list);
+
+void ei_tx_timeout(struct net_device *dev)
+{
+	__ei_tx_timeout(dev);
+}
+EXPORT_SYMBOL(ei_tx_timeout);
+
+irqreturn_t ei_interrupt(int irq, void *dev_id)
+{
+	return __ei_interrupt(irq, dev_id);
+}
+EXPORT_SYMBOL(ei_interrupt);
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+void ei_poll(struct net_device *dev)
+{
+	__ei_poll(dev);
+}
+EXPORT_SYMBOL(ei_poll);
+#endif
+
+const struct net_device_ops ei_netdev_ops = {
+	.ndo_open		= ei_open,
+	.ndo_stop		= ei_close,
+	.ndo_start_xmit		= ei_start_xmit,
+	.ndo_tx_timeout		= ei_tx_timeout,
+	.ndo_get_stats		= ei_get_stats,
+	.ndo_set_rx_mode	= 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,
+#endif
+};
+EXPORT_SYMBOL(ei_netdev_ops);
+
+struct net_device *__alloc_ei_netdev(int size)
+{
+	struct net_device *dev = ____alloc_ei_netdev(size);
+	if (dev)
+		dev->netdev_ops = &ei_netdev_ops;
+	return dev;
+}
+EXPORT_SYMBOL(__alloc_ei_netdev);
+
+void NS8390_init(struct net_device *dev, int startp)
+{
+	__NS8390_init(dev, startp);
+}
+EXPORT_SYMBOL(NS8390_init);
+
+#if defined(MODULE)
+
+static int __init ns8390_module_init(void)
+{
+	return 0;
+}
+
+static void __exit ns8390_module_exit(void)
+{
+}
+
+module_init(ns8390_module_init);
+module_exit(ns8390_module_exit);
+#endif /* MODULE */
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/8390.h linux-libre-3.2-gnu/drivers/net/ethernet/8390/8390.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/8390.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/8390.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,232 @@
+/* Generic NS8390 register definitions. */
+/* This file is part of Donald Becker's 8390 drivers, and is distributed
+   under the same license. Auto-loading of 8390.o only in v2.2 - Paul G.
+   Some of these names and comments originated from the Crynwr
+   packet drivers, which are distributed under the GPL. */
+
+#ifndef _8390_h
+#define _8390_h
+
+#include <linux/if_ether.h>
+#include <linux/ioport.h>
+#include <linux/irqreturn.h>
+#include <linux/skbuff.h>
+
+#define TX_PAGES 12	/* Two Tx slots */
+
+#define ETHER_ADDR_LEN 6
+
+/* The 8390 specific per-packet-header format. */
+struct e8390_pkt_hdr {
+  unsigned char status; /* status */
+  unsigned char next;   /* pointer to next packet. */
+  unsigned short count; /* header + packet length in bytes */
+};
+
+#ifdef notdef
+extern int ei_debug;
+#else
+#define ei_debug 1
+#endif
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+extern void ei_poll(struct net_device *dev);
+extern void eip_poll(struct net_device *dev);
+#endif
+
+
+/* Without I/O delay - non ISA or later chips */
+extern void NS8390_init(struct net_device *dev, int startp);
+extern int ei_open(struct net_device *dev);
+extern int ei_close(struct net_device *dev);
+extern irqreturn_t ei_interrupt(int irq, void *dev_id);
+extern void ei_tx_timeout(struct net_device *dev);
+extern netdev_tx_t ei_start_xmit(struct sk_buff *skb, struct net_device *dev);
+extern void ei_set_multicast_list(struct net_device *dev);
+extern struct net_device_stats *ei_get_stats(struct net_device *dev);
+
+extern const struct net_device_ops ei_netdev_ops;
+
+extern struct net_device *__alloc_ei_netdev(int size);
+static inline struct net_device *alloc_ei_netdev(void)
+{
+	return __alloc_ei_netdev(0);
+}
+
+/* With I/O delay form */
+extern void NS8390p_init(struct net_device *dev, int startp);
+extern int eip_open(struct net_device *dev);
+extern int eip_close(struct net_device *dev);
+extern irqreturn_t eip_interrupt(int irq, void *dev_id);
+extern void eip_tx_timeout(struct net_device *dev);
+extern netdev_tx_t eip_start_xmit(struct sk_buff *skb, struct net_device *dev);
+extern void eip_set_multicast_list(struct net_device *dev);
+extern struct net_device_stats *eip_get_stats(struct net_device *dev);
+
+extern const struct net_device_ops eip_netdev_ops;
+
+extern struct net_device *__alloc_eip_netdev(int size);
+static inline struct net_device *alloc_eip_netdev(void)
+{
+	return __alloc_eip_netdev(0);
+}
+
+/* You have one of these per-board */
+struct ei_device {
+	const char *name;
+	void (*reset_8390)(struct net_device *);
+	void (*get_8390_hdr)(struct net_device *, struct e8390_pkt_hdr *, int);
+	void (*block_output)(struct net_device *, int, const unsigned char *, int);
+	void (*block_input)(struct net_device *, int, struct sk_buff *, int);
+	unsigned long rmem_start;
+	unsigned long rmem_end;
+	void __iomem *mem;
+	unsigned char mcfilter[8];
+	unsigned open:1;
+	unsigned word16:1;  		/* We have the 16-bit (vs 8-bit) version of the card. */
+	unsigned bigendian:1;		/* 16-bit big endian mode. Do NOT */
+					/* set this on random 8390 clones! */
+	unsigned txing:1;		/* Transmit Active */
+	unsigned irqlock:1;		/* 8390's intrs disabled when '1'. */
+	unsigned dmaing:1;		/* Remote DMA Active */
+	unsigned char tx_start_page, rx_start_page, stop_page;
+	unsigned char current_page;	/* Read pointer in buffer  */
+	unsigned char interface_num;	/* Net port (AUI, 10bT.) to use. */
+	unsigned char txqueue;		/* Tx Packet buffer queue length. */
+	short tx1, tx2;			/* Packet lengths for ping-pong tx. */
+	short lasttx;			/* Alpha version consistency check. */
+	unsigned char reg0;		/* Register '0' in a WD8013 */
+	unsigned char reg5;		/* Register '5' in a WD8013 */
+	unsigned char saved_irq;	/* Original dev->irq value. */
+	u32 *reg_offset;		/* Register mapping table */
+	spinlock_t page_lock;		/* Page register locks */
+	unsigned long priv;		/* Private field to store bus IDs etc. */
+#ifdef AX88796_PLATFORM
+	unsigned char rxcr_base;	/* default value for RXCR */
+#endif
+};
+
+/* The maximum number of 8390 interrupt service routines called per IRQ. */
+#define MAX_SERVICE 12
+
+/* The maximum time waited (in jiffies) before assuming a Tx failed. (20ms) */
+#define TX_TIMEOUT (20*HZ/100)
+
+#define ei_status (*(struct ei_device *)netdev_priv(dev))
+
+/* Some generic ethernet register configurations. */
+#define E8390_TX_IRQ_MASK	0xa	/* For register EN0_ISR */
+#define E8390_RX_IRQ_MASK	0x5
+
+#ifdef AX88796_PLATFORM
+#define E8390_RXCONFIG		(ei_status.rxcr_base | 0x04)
+#define E8390_RXOFF		(ei_status.rxcr_base | 0x20)
+#else
+#define E8390_RXCONFIG		0x4	/* EN0_RXCR: broadcasts, no multicast,errors */
+#define E8390_RXOFF		0x20	/* EN0_RXCR: Accept no packets */
+#endif
+
+#define E8390_TXCONFIG		0x00	/* EN0_TXCR: Normal transmit mode */
+#define E8390_TXOFF		0x02	/* EN0_TXCR: Transmitter off */
+
+
+/*  Register accessed at EN_CMD, the 8390 base addr.  */
+#define E8390_STOP	0x01	/* Stop and reset the chip */
+#define E8390_START	0x02	/* Start the chip, clear reset */
+#define E8390_TRANS	0x04	/* Transmit a frame */
+#define E8390_RREAD	0x08	/* Remote read */
+#define E8390_RWRITE	0x10	/* Remote write  */
+#define E8390_NODMA	0x20	/* Remote DMA */
+#define E8390_PAGE0	0x00	/* Select page chip registers */
+#define E8390_PAGE1	0x40	/* using the two high-order bits */
+#define E8390_PAGE2	0x80	/* Page 3 is invalid. */
+
+/*
+ *	Only generate indirect loads given a machine that needs them.
+ *      - removed AMIGA_PCMCIA from this list, handled as ISA io now
+ *	- the _p for generates no delay by default 8390p.c overrides this.
+ */
+
+#ifndef ei_inb
+#define ei_inb(_p)	inb(_p)
+#define ei_outb(_v,_p)	outb(_v,_p)
+#define ei_inb_p(_p)	inb(_p)
+#define ei_outb_p(_v,_p) outb(_v,_p)
+#endif
+
+#ifndef EI_SHIFT
+#define EI_SHIFT(x)	(x)
+#endif
+
+#define E8390_CMD	EI_SHIFT(0x00)  /* The command register (for all pages) */
+/* Page 0 register offsets. */
+#define EN0_CLDALO	EI_SHIFT(0x01)	/* Low byte of current local dma addr  RD */
+#define EN0_STARTPG	EI_SHIFT(0x01)	/* Starting page of ring bfr WR */
+#define EN0_CLDAHI	EI_SHIFT(0x02)	/* High byte of current local dma addr  RD */
+#define EN0_STOPPG	EI_SHIFT(0x02)	/* Ending page +1 of ring bfr WR */
+#define EN0_BOUNDARY	EI_SHIFT(0x03)	/* Boundary page of ring bfr RD WR */
+#define EN0_TSR		EI_SHIFT(0x04)	/* Transmit status reg RD */
+#define EN0_TPSR	EI_SHIFT(0x04)	/* Transmit starting page WR */
+#define EN0_NCR		EI_SHIFT(0x05)	/* Number of collision reg RD */
+#define EN0_TCNTLO	EI_SHIFT(0x05)	/* Low  byte of tx byte count WR */
+#define EN0_FIFO	EI_SHIFT(0x06)	/* FIFO RD */
+#define EN0_TCNTHI	EI_SHIFT(0x06)	/* High byte of tx byte count WR */
+#define EN0_ISR		EI_SHIFT(0x07)	/* Interrupt status reg RD WR */
+#define EN0_CRDALO	EI_SHIFT(0x08)	/* low byte of current remote dma address RD */
+#define EN0_RSARLO	EI_SHIFT(0x08)	/* Remote start address reg 0 */
+#define EN0_CRDAHI	EI_SHIFT(0x09)	/* high byte, current remote dma address RD */
+#define EN0_RSARHI	EI_SHIFT(0x09)	/* Remote start address reg 1 */
+#define EN0_RCNTLO	EI_SHIFT(0x0a)	/* Remote byte count reg WR */
+#define EN0_RCNTHI	EI_SHIFT(0x0b)	/* Remote byte count reg WR */
+#define EN0_RSR		EI_SHIFT(0x0c)	/* rx status reg RD */
+#define EN0_RXCR	EI_SHIFT(0x0c)	/* RX configuration reg WR */
+#define EN0_TXCR	EI_SHIFT(0x0d)	/* TX configuration reg WR */
+#define EN0_COUNTER0	EI_SHIFT(0x0d)	/* Rcv alignment error counter RD */
+#define EN0_DCFG	EI_SHIFT(0x0e)	/* Data configuration reg WR */
+#define EN0_COUNTER1	EI_SHIFT(0x0e)	/* Rcv CRC error counter RD */
+#define EN0_IMR		EI_SHIFT(0x0f)	/* Interrupt mask reg WR */
+#define EN0_COUNTER2	EI_SHIFT(0x0f)	/* Rcv missed frame error counter RD */
+
+/* Bits in EN0_ISR - Interrupt status register */
+#define ENISR_RX	0x01	/* Receiver, no error */
+#define ENISR_TX	0x02	/* Transmitter, no error */
+#define ENISR_RX_ERR	0x04	/* Receiver, with error */
+#define ENISR_TX_ERR	0x08	/* Transmitter, with error */
+#define ENISR_OVER	0x10	/* Receiver overwrote the ring */
+#define ENISR_COUNTERS	0x20	/* Counters need emptying */
+#define ENISR_RDC	0x40	/* remote dma complete */
+#define ENISR_RESET	0x80	/* Reset completed */
+#define ENISR_ALL	0x3f	/* Interrupts we will enable */
+
+/* Bits in EN0_DCFG - Data config register */
+#define ENDCFG_WTS	0x01	/* word transfer mode selection */
+#define ENDCFG_BOS	0x02	/* byte order selection */
+
+/* Page 1 register offsets. */
+#define EN1_PHYS   EI_SHIFT(0x01)	/* This board's physical enet addr RD WR */
+#define EN1_PHYS_SHIFT(i)  EI_SHIFT(i+1) /* Get and set mac address */
+#define EN1_CURPAG EI_SHIFT(0x07)	/* Current memory page RD WR */
+#define EN1_MULT   EI_SHIFT(0x08)	/* Multicast filter mask array (8 bytes) RD WR */
+#define EN1_MULT_SHIFT(i)  EI_SHIFT(8+i) /* Get and set multicast filter */
+
+/* Bits in received packet status byte and EN0_RSR*/
+#define ENRSR_RXOK	0x01	/* Received a good packet */
+#define ENRSR_CRC	0x02	/* CRC error */
+#define ENRSR_FAE	0x04	/* frame alignment error */
+#define ENRSR_FO	0x08	/* FIFO overrun */
+#define ENRSR_MPA	0x10	/* missed pkt */
+#define ENRSR_PHY	0x20	/* physical/multicast address */
+#define ENRSR_DIS	0x40	/* receiver disable. set in monitor mode */
+#define ENRSR_DEF	0x80	/* deferring */
+
+/* Transmitted packet status, EN0_TSR. */
+#define ENTSR_PTX 0x01	/* Packet transmitted without error */
+#define ENTSR_ND  0x02	/* The transmit wasn't deferred. */
+#define ENTSR_COL 0x04	/* The transmit collided at least once. */
+#define ENTSR_ABT 0x08  /* The transmit collided 16 times, and was deferred. */
+#define ENTSR_CRS 0x10	/* The carrier sense was lost. */
+#define ENTSR_FU  0x20  /* A "FIFO underrun" occurred during transmit. */
+#define ENTSR_CDH 0x40	/* The collision detect "heartbeat" signal was lost. */
+#define ENTSR_OWC 0x80  /* There was an out-of-window collision. */
+
+#endif /* _8390_h */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/8390p.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/8390p.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/8390p.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/8390p.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,105 @@
+/* 8390 core for ISA devices needing bus delays */
+
+static const char version[] =
+    "8390p.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#define ei_inb(_p)	inb(_p)
+#define ei_outb(_v, _p)	outb(_v, _p)
+#define ei_inb_p(_p)	inb_p(_p)
+#define ei_outb_p(_v, _p) outb_p(_v, _p)
+
+#include "lib8390.c"
+
+int eip_open(struct net_device *dev)
+{
+	return __ei_open(dev);
+}
+EXPORT_SYMBOL(eip_open);
+
+int eip_close(struct net_device *dev)
+{
+	return __ei_close(dev);
+}
+EXPORT_SYMBOL(eip_close);
+
+netdev_tx_t eip_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	return __ei_start_xmit(skb, dev);
+}
+EXPORT_SYMBOL(eip_start_xmit);
+
+struct net_device_stats *eip_get_stats(struct net_device *dev)
+{
+	return __ei_get_stats(dev);
+}
+EXPORT_SYMBOL(eip_get_stats);
+
+void eip_set_multicast_list(struct net_device *dev)
+{
+	__ei_set_multicast_list(dev);
+}
+EXPORT_SYMBOL(eip_set_multicast_list);
+
+void eip_tx_timeout(struct net_device *dev)
+{
+	__ei_tx_timeout(dev);
+}
+EXPORT_SYMBOL(eip_tx_timeout);
+
+irqreturn_t eip_interrupt(int irq, void *dev_id)
+{
+	return __ei_interrupt(irq, dev_id);
+}
+EXPORT_SYMBOL(eip_interrupt);
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+void eip_poll(struct net_device *dev)
+{
+	__ei_poll(dev);
+}
+EXPORT_SYMBOL(eip_poll);
+#endif
+
+const struct net_device_ops eip_netdev_ops = {
+	.ndo_open		= eip_open,
+	.ndo_stop		= eip_close,
+	.ndo_start_xmit		= eip_start_xmit,
+	.ndo_tx_timeout		= eip_tx_timeout,
+	.ndo_get_stats		= eip_get_stats,
+	.ndo_set_rx_mode	= eip_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	= eip_poll,
+#endif
+};
+EXPORT_SYMBOL(eip_netdev_ops);
+
+struct net_device *__alloc_eip_netdev(int size)
+{
+	struct net_device *dev = ____alloc_ei_netdev(size);
+	if (dev)
+		dev->netdev_ops = &eip_netdev_ops;
+	return dev;
+}
+EXPORT_SYMBOL(__alloc_eip_netdev);
+
+void NS8390p_init(struct net_device *dev, int startp)
+{
+	__NS8390_init(dev, startp);
+}
+EXPORT_SYMBOL(NS8390p_init);
+
+static int __init NS8390p_init_module(void)
+{
+	return 0;
+}
+
+static void __exit NS8390p_cleanup_module(void)
+{
+}
+
+module_init(NS8390p_init_module);
+module_exit(NS8390p_cleanup_module);
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/ac3200.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/ac3200.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/ac3200.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/ac3200.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,432 @@
+/* ac3200.c: A driver for the Ansel Communications EISA ethernet adaptor. */
+/*
+	Written 1993, 1994 by Donald Becker.
+	Copyright 1993 United States Government as represented by the Director,
+	National Security Agency.  This software may only be used and distributed
+	according to the terms of the GNU General Public License as modified by SRC,
+	incorporated herein by reference.
+
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+	This is driver for the Ansel Communications Model 3200 EISA Ethernet LAN
+	Adapter.  The programming information is from the users manual, as related
+	by glee@ardnassak.math.clemson.edu.
+
+	Changelog:
+
+	Paul Gortmaker 05/98	: add support for shared mem above 1MB.
+
+  */
+
+static const char version[] =
+	"ac3200.c:v1.01 7/1/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include <linux/module.h>
+#include <linux/eisa.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "8390.h"
+
+#define DRV_NAME	"ac3200"
+
+/* Offsets from the base address. */
+#define AC_NIC_BASE	0x00
+#define AC_SA_PROM	0x16			/* The station address PROM. */
+#define AC_ADDR0	0x00			/* Prefix station address values. */
+#define AC_ADDR1	0x40
+#define AC_ADDR2	0x90
+#define AC_ID_PORT	0xC80
+#define AC_EISA_ID	0x0110d305
+#define AC_RESET_PORT	0xC84
+#define AC_RESET	0x00
+#define AC_ENABLE	0x01
+#define AC_CONFIG	0xC90	/* The configuration port. */
+
+#define AC_IO_EXTENT 0x20
+                                /* Actually accessed is:
+								 * AC_NIC_BASE (0-15)
+								 * AC_SA_PROM (0-5)
+								 * AC_ID_PORT (0-3)
+								 * AC_RESET_PORT
+								 * AC_CONFIG
+								 */
+
+/* Decoding of the configuration register. */
+static unsigned char config2irqmap[8] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
+static int addrmap[8] =
+{0xFF0000, 0xFE0000, 0xFD0000, 0xFFF0000, 0xFFE0000, 0xFFC0000,  0xD0000, 0 };
+static const char *port_name[4] = { "10baseT", "invalid", "AUI", "10base2"};
+
+#define config2irq(configval)	config2irqmap[((configval) >> 3) & 7]
+#define config2mem(configval)	addrmap[(configval) & 7]
+#define config2name(configval)	port_name[((configval) >> 6) & 3]
+
+/* First and last 8390 pages. */
+#define AC_START_PG		0x00	/* First page of 8390 TX buffer */
+#define AC_STOP_PG		0x80	/* Last page +1 of the 8390 RX ring */
+
+static int ac_probe1(int ioaddr, struct net_device *dev);
+
+static int ac_open(struct net_device *dev);
+static void ac_reset_8390(struct net_device *dev);
+static void ac_block_input(struct net_device *dev, int count,
+					struct sk_buff *skb, int ring_offset);
+static void ac_block_output(struct net_device *dev, const int count,
+							const unsigned char *buf, const int start_page);
+static void ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+					int ring_page);
+
+static int ac_close_card(struct net_device *dev);
+
+
+/*	Probe for the AC3200.
+
+	The AC3200 can be identified by either the EISA configuration registers,
+	or the unique value in the station address PROM.
+	*/
+
+static int __init do_ac3200_probe(struct net_device *dev)
+{
+	unsigned short ioaddr = dev->base_addr;
+	int irq = dev->irq;
+	int mem_start = dev->mem_start;
+
+	if (ioaddr > 0x1ff)		/* Check a single specified location. */
+		return ac_probe1(ioaddr, dev);
+	else if (ioaddr > 0)		/* Don't probe at all. */
+		return -ENXIO;
+
+	if ( ! EISA_bus)
+		return -ENXIO;
+
+	for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
+		if (ac_probe1(ioaddr, dev) == 0)
+			return 0;
+		dev->irq = irq;
+		dev->mem_start = mem_start;
+	}
+
+	return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init ac3200_probe(int unit)
+{
+	struct net_device *dev = alloc_ei_netdev();
+	int err;
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+
+	err = do_ac3200_probe(dev);
+	if (err)
+		goto out;
+	return dev;
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+#endif
+
+static const struct net_device_ops ac_netdev_ops = {
+	.ndo_open		= ac_open,
+	.ndo_stop 		= ac_close_card,
+
+	.ndo_start_xmit		= ei_start_xmit,
+	.ndo_tx_timeout		= ei_tx_timeout,
+	.ndo_get_stats		= ei_get_stats,
+	.ndo_set_rx_mode	= 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,
+#endif
+};
+
+static int __init ac_probe1(int ioaddr, struct net_device *dev)
+{
+	int i, retval;
+
+	if (!request_region(ioaddr, AC_IO_EXTENT, DRV_NAME))
+		return -EBUSY;
+
+	if (inb_p(ioaddr + AC_ID_PORT) == 0xff) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	if (inl(ioaddr + AC_ID_PORT) != AC_EISA_ID) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+#ifndef final_version
+	printk(KERN_DEBUG "AC3200 ethercard configuration register is %#02x,"
+		   " EISA ID %02x %02x %02x %02x.\n", inb(ioaddr + AC_CONFIG),
+		   inb(ioaddr + AC_ID_PORT + 0), inb(ioaddr + AC_ID_PORT + 1),
+		   inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3));
+#endif
+
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i);
+
+	printk(KERN_DEBUG "AC3200 in EISA slot %d, node %pM",
+	       ioaddr/0x1000, dev->dev_addr);
+#if 0
+	/* Check the vendor ID/prefix. Redundant after checking the EISA ID */
+	if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0
+		|| inb(ioaddr + AC_SA_PROM + 1) != AC_ADDR1
+		|| inb(ioaddr + AC_SA_PROM + 2) != AC_ADDR2 ) {
+		printk(", not found (invalid prefix).\n");
+		retval = -ENODEV;
+		goto out;
+	}
+#endif
+
+	/* Assign and allocate the interrupt now. */
+	if (dev->irq == 0) {
+		dev->irq = config2irq(inb(ioaddr + AC_CONFIG));
+		printk(", using");
+	} else {
+		dev->irq = irq_canonicalize(dev->irq);
+		printk(", assigning");
+	}
+
+	retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
+	if (retval) {
+		printk (" nothing! Unable to get IRQ %d.\n", dev->irq);
+		goto out;
+	}
+
+	printk(" IRQ %d, %s port\n", dev->irq, port_name[dev->if_port]);
+
+	dev->base_addr = ioaddr;
+
+#ifdef notyet
+	if (dev->mem_start)	{		/* Override the value from the board. */
+		for (i = 0; i < 7; i++)
+			if (addrmap[i] == dev->mem_start)
+				break;
+		if (i >= 7)
+			i = 0;
+		outb((inb(ioaddr + AC_CONFIG) & ~7) | i, ioaddr + AC_CONFIG);
+	}
+#endif
+
+	dev->if_port = inb(ioaddr + AC_CONFIG) >> 6;
+	dev->mem_start = config2mem(inb(ioaddr + AC_CONFIG));
+
+	printk("%s: AC3200 at %#3x with %dkB memory at physical address %#lx.\n",
+			dev->name, ioaddr, AC_STOP_PG/4, dev->mem_start);
+
+	/*
+	 *  BEWARE!! Some dain-bramaged EISA SCUs will allow you to put
+	 *  the card mem within the region covered by `normal' RAM  !!!
+	 *
+	 *  ioremap() will fail in that case.
+	 */
+	ei_status.mem = ioremap(dev->mem_start, AC_STOP_PG*0x100);
+	if (!ei_status.mem) {
+		printk(KERN_ERR "ac3200.c: Unable to remap card memory above 1MB !!\n");
+		printk(KERN_ERR "ac3200.c: Try using EISA SCU to set memory below 1MB.\n");
+		printk(KERN_ERR "ac3200.c: Driver NOT installed.\n");
+		retval = -EINVAL;
+		goto out1;
+	}
+	printk("ac3200.c: remapped %dkB card memory to virtual address %p\n",
+			AC_STOP_PG/4, ei_status.mem);
+
+	dev->mem_start = (unsigned long)ei_status.mem;
+	dev->mem_end = dev->mem_start + (AC_STOP_PG - AC_START_PG)*256;
+
+	ei_status.name = "AC3200";
+	ei_status.tx_start_page = AC_START_PG;
+	ei_status.rx_start_page = AC_START_PG + TX_PAGES;
+	ei_status.stop_page = AC_STOP_PG;
+	ei_status.word16 = 1;
+
+	if (ei_debug > 0)
+		printk(version);
+
+	ei_status.reset_8390 = &ac_reset_8390;
+	ei_status.block_input = &ac_block_input;
+	ei_status.block_output = &ac_block_output;
+	ei_status.get_8390_hdr = &ac_get_8390_hdr;
+
+	dev->netdev_ops = &ac_netdev_ops;
+	NS8390_init(dev, 0);
+
+	retval = register_netdev(dev);
+	if (retval)
+		goto out2;
+	return 0;
+out2:
+	if (ei_status.reg0)
+		iounmap(ei_status.mem);
+out1:
+	free_irq(dev->irq, dev);
+out:
+	release_region(ioaddr, AC_IO_EXTENT);
+	return retval;
+}
+
+static int ac_open(struct net_device *dev)
+{
+#ifdef notyet
+	/* Someday we may enable the IRQ and shared memory here. */
+	int ioaddr = dev->base_addr;
+#endif
+
+	ei_open(dev);
+	return 0;
+}
+
+static void ac_reset_8390(struct net_device *dev)
+{
+	ushort ioaddr = dev->base_addr;
+
+	outb(AC_RESET, ioaddr + AC_RESET_PORT);
+	if (ei_debug > 1) printk("resetting AC3200, t=%ld...", jiffies);
+
+	ei_status.txing = 0;
+	outb(AC_ENABLE, ioaddr + AC_RESET_PORT);
+	if (ei_debug > 1) printk("reset done\n");
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void
+ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	void __iomem *hdr_start = ei_status.mem + ((ring_page - AC_START_PG)<<8);
+	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+}
+
+/*  Block input and output are easy on shared memory ethercards, the only
+	complication is when the ring buffer wraps. */
+
+static void ac_block_input(struct net_device *dev, int count, struct sk_buff *skb,
+						  int ring_offset)
+{
+	void __iomem *start = ei_status.mem + ring_offset - AC_START_PG*256;
+
+	if (ring_offset + count > AC_STOP_PG*256) {
+		/* We must wrap the input move. */
+		int semi_count = AC_STOP_PG*256 - ring_offset;
+		memcpy_fromio(skb->data, start, semi_count);
+		count -= semi_count;
+		memcpy_fromio(skb->data + semi_count,
+				ei_status.mem + TX_PAGES*256, count);
+	} else {
+		memcpy_fromio(skb->data, start, count);
+	}
+}
+
+static void ac_block_output(struct net_device *dev, int count,
+							const unsigned char *buf, int start_page)
+{
+	void __iomem *shmem = ei_status.mem + ((start_page - AC_START_PG)<<8);
+
+	memcpy_toio(shmem, buf, count);
+}
+
+static int ac_close_card(struct net_device *dev)
+{
+	if (ei_debug > 1)
+		printk("%s: Shutting down ethercard.\n", dev->name);
+
+#ifdef notyet
+	/* We should someday disable shared memory and interrupts. */
+	outb(0x00, ioaddr + 6);	/* Disable interrupts. */
+	free_irq(dev->irq, dev);
+#endif
+
+	ei_close(dev);
+	return 0;
+}
+
+#ifdef MODULE
+#define MAX_AC32_CARDS	4	/* Max number of AC32 cards per module */
+static struct net_device *dev_ac32[MAX_AC32_CARDS];
+static int io[MAX_AC32_CARDS];
+static int irq[MAX_AC32_CARDS];
+static int mem[MAX_AC32_CARDS];
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(mem, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s)");
+MODULE_PARM_DESC(mem, "Memory base address(es)");
+MODULE_DESCRIPTION("Ansel AC3200 EISA ethernet driver");
+MODULE_LICENSE("GPL");
+
+static int __init ac3200_module_init(void)
+{
+	struct net_device *dev;
+	int this_dev, found = 0;
+
+	for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
+		if (io[this_dev] == 0 && this_dev != 0)
+			break;
+		dev = alloc_ei_netdev();
+		if (!dev)
+			break;
+		dev->irq = irq[this_dev];
+		dev->base_addr = io[this_dev];
+		dev->mem_start = mem[this_dev];		/* Currently ignored by driver */
+		if (do_ac3200_probe(dev) == 0) {
+			dev_ac32[found++] = dev;
+			continue;
+		}
+		free_netdev(dev);
+		printk(KERN_WARNING "ac3200.c: No ac3200 card found (i/o = 0x%x).\n", io[this_dev]);
+		break;
+	}
+	if (found)
+		return 0;
+	return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+	/* Someday free_irq may be in ac_close_card() */
+	free_irq(dev->irq, dev);
+	release_region(dev->base_addr, AC_IO_EXTENT);
+	iounmap(ei_status.mem);
+}
+
+static void __exit ac3200_module_exit(void)
+{
+	int this_dev;
+
+	for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
+		struct net_device *dev = dev_ac32[this_dev];
+		if (dev) {
+			unregister_netdev(dev);
+			cleanup_card(dev);
+			free_netdev(dev);
+		}
+	}
+}
+module_init(ac3200_module_init);
+module_exit(ac3200_module_exit);
+#endif /* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/apne.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/apne.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/apne.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/apne.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,620 @@
+/*
+ * Amiga Linux/68k 8390 based PCMCIA Ethernet Driver for the Amiga 1200
+ *
+ * (C) Copyright 1997 Alain Malek
+ *                    (Alain.Malek@cryogen.com)
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is based on
+ *
+ * ne.c:       A general non-shared-memory NS8390 ethernet driver for linux
+ *             Written 1992-94 by Donald Becker.
+ *
+ * 8390.c:     A general NS8390 ethernet driver core for linux.
+ *             Written 1992-94 by Donald Becker.
+ *
+ * cnetdevice: A Sana-II ethernet driver for AmigaOS
+ *             Written by Bruce Abbott (bhabbott@inhb.co.nz)
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of the Linux
+ * distribution for more details.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+#include <asm/amigayle.h>
+#include <asm/amipcmcia.h>
+
+#include "8390.h"
+
+/* ---- No user-serviceable parts below ---- */
+
+#define DRV_NAME "apne"
+
+#define NE_BASE	 (dev->base_addr)
+#define NE_CMD	 		0x00
+#define NE_DATAPORT		0x10            /* NatSemi-defined port window offset. */
+#define NE_RESET		0x1f            /* Issue a read to reset, a write to clear. */
+#define NE_IO_EXTENT	        0x20
+
+#define NE_EN0_ISR		0x07
+#define NE_EN0_DCFG		0x0e
+
+#define NE_EN0_RSARLO	        0x08
+#define NE_EN0_RSARHI	        0x09
+#define NE_EN0_RCNTLO	        0x0a
+#define NE_EN0_RXCR		0x0c
+#define NE_EN0_TXCR		0x0d
+#define NE_EN0_RCNTHI	        0x0b
+#define NE_EN0_IMR		0x0f
+
+#define NE1SM_START_PG	0x20	/* First page of TX buffer */
+#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 */
+
+
+struct net_device * __init apne_probe(int unit);
+static int apne_probe1(struct net_device *dev, int ioaddr);
+
+static void apne_reset_8390(struct net_device *dev);
+static void apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+			  int ring_page);
+static void apne_block_input(struct net_device *dev, int count,
+								struct sk_buff *skb, int ring_offset);
+static void apne_block_output(struct net_device *dev, const int count,
+							const unsigned char *buf, const int start_page);
+static irqreturn_t apne_interrupt(int irq, void *dev_id);
+
+static int init_pcmcia(void);
+
+/* IO base address used for nic */
+
+#define IOBASE 0x300
+
+/*
+   use MANUAL_CONFIG and MANUAL_OFFSET for enabling IO by hand
+   you can find the values to use by looking at the cnet.device
+   config file example (the default values are for the CNET40BC card)
+*/
+
+/*
+#define MANUAL_CONFIG 0x20
+#define MANUAL_OFFSET 0x3f8
+
+#define MANUAL_HWADDR0 0x00
+#define MANUAL_HWADDR1 0x12
+#define MANUAL_HWADDR2 0x34
+#define MANUAL_HWADDR3 0x56
+#define MANUAL_HWADDR4 0x78
+#define MANUAL_HWADDR5 0x9a
+*/
+
+static const char version[] =
+    "apne.c:v1.1 7/10/98 Alain Malek (Alain.Malek@cryogen.ch)\n";
+
+static int apne_owned;	/* signal if card already owned */
+
+struct net_device * __init apne_probe(int unit)
+{
+	struct net_device *dev;
+#ifndef MANUAL_CONFIG
+	char tuple[8];
+#endif
+	int err;
+
+	if (!MACH_IS_AMIGA)
+		return ERR_PTR(-ENODEV);
+
+	if (apne_owned)
+		return ERR_PTR(-ENODEV);
+
+	if ( !(AMIGAHW_PRESENT(PCMCIA)) )
+		return ERR_PTR(-ENODEV);
+
+	printk("Looking for PCMCIA ethernet card : ");
+
+	/* check if a card is inserted */
+	if (!(PCMCIA_INSERTED)) {
+		printk("NO PCMCIA card inserted\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	dev = alloc_ei_netdev();
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+	if (unit >= 0) {
+		sprintf(dev->name, "eth%d", unit);
+		netdev_boot_setup_check(dev);
+	}
+
+	/* disable pcmcia irq for readtuple */
+	pcmcia_disable_irq();
+
+#ifndef MANUAL_CONFIG
+	if ((pcmcia_copy_tuple(CISTPL_FUNCID, tuple, 8) < 3) ||
+		(tuple[2] != CISTPL_FUNCID_NETWORK)) {
+		printk("not an ethernet card\n");
+		/* XXX: shouldn't we re-enable irq here? */
+		free_netdev(dev);
+		return ERR_PTR(-ENODEV);
+	}
+#endif
+
+	printk("ethernet PCMCIA card inserted\n");
+
+	if (!init_pcmcia()) {
+		/* XXX: shouldn't we re-enable irq here? */
+		free_netdev(dev);
+		return ERR_PTR(-ENODEV);
+	}
+
+	if (!request_region(IOBASE, 0x20, DRV_NAME)) {
+		free_netdev(dev);
+		return ERR_PTR(-EBUSY);
+	}
+
+	err = apne_probe1(dev, IOBASE);
+	if (err) {
+		release_region(IOBASE, 0x20);
+		free_netdev(dev);
+		return ERR_PTR(err);
+	}
+	err = register_netdev(dev);
+	if (!err)
+		return dev;
+
+	pcmcia_disable_irq();
+	free_irq(IRQ_AMIGA_PORTS, dev);
+	pcmcia_reset();
+	release_region(IOBASE, 0x20);
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+
+static int __init apne_probe1(struct net_device *dev, int ioaddr)
+{
+    int i;
+    unsigned char SA_prom[32];
+    int wordlength = 2;
+    const char *name = NULL;
+    int start_page, stop_page;
+#ifndef MANUAL_HWADDR0
+    int neX000, ctron;
+#endif
+    static unsigned version_printed;
+
+    if (ei_debug  &&  version_printed++ == 0)
+	printk(version);
+
+    printk("PCMCIA NE*000 ethercard probe");
+
+    /* Reset card. Who knows what dain-bramaged state it was left in. */
+    {	unsigned long reset_start_time = jiffies;
+
+	outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
+
+	while ((inb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
+		if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
+			printk(" not found (no reset ack).\n");
+			return -ENODEV;
+		}
+
+	outb(0xff, ioaddr + NE_EN0_ISR);		/* Ack all intr. */
+    }
+
+#ifndef MANUAL_HWADDR0
+
+    /* Read the 16 bytes of station address PROM.
+       We must first initialize registers, similar to NS8390_init(eifdev, 0).
+       We can't reliably read the SAPROM address without this.
+       (I learned the hard way!). */
+    {
+	struct {unsigned long value, offset; } program_seq[] = {
+	    {E8390_NODMA+E8390_PAGE0+E8390_STOP, NE_CMD}, /* Select page 0*/
+	    {0x48,	NE_EN0_DCFG},	/* Set byte-wide (0x48) access. */
+	    {0x00,	NE_EN0_RCNTLO},	/* Clear the count regs. */
+	    {0x00,	NE_EN0_RCNTHI},
+	    {0x00,	NE_EN0_IMR},	/* Mask completion irq. */
+	    {0xFF,	NE_EN0_ISR},
+	    {E8390_RXOFF, NE_EN0_RXCR},	/* 0x20  Set to monitor */
+	    {E8390_TXOFF, NE_EN0_TXCR},	/* 0x02  and loopback mode. */
+	    {32,	NE_EN0_RCNTLO},
+	    {0x00,	NE_EN0_RCNTHI},
+	    {0x00,	NE_EN0_RSARLO},	/* DMA starting at 0x0000. */
+	    {0x00,	NE_EN0_RSARHI},
+	    {E8390_RREAD+E8390_START, NE_CMD},
+	};
+	for (i = 0; i < ARRAY_SIZE(program_seq); i++) {
+	    outb(program_seq[i].value, ioaddr + program_seq[i].offset);
+	}
+
+    }
+    for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
+	SA_prom[i] = inb(ioaddr + NE_DATAPORT);
+	SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
+	if (SA_prom[i] != SA_prom[i+1])
+	    wordlength = 1;
+    }
+
+    /*	At this point, wordlength *only* tells us if the SA_prom is doubled
+	up or not because some broken PCI cards don't respect the byte-wide
+	request in program_seq above, and hence don't have doubled up values.
+	These broken cards would otherwise be detected as an ne1000.  */
+
+    if (wordlength == 2)
+	for (i = 0; i < 16; i++)
+		SA_prom[i] = SA_prom[i+i];
+
+    if (wordlength == 2) {
+	/* We must set the 8390 for word mode. */
+	outb(0x49, ioaddr + NE_EN0_DCFG);
+	start_page = NESM_START_PG;
+	stop_page = NESM_STOP_PG;
+    } else {
+	start_page = NE1SM_START_PG;
+	stop_page = NE1SM_STOP_PG;
+    }
+
+    neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
+    ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
+
+    /* Set up the rest of the parameters. */
+    if (neX000) {
+	name = (wordlength == 2) ? "NE2000" : "NE1000";
+    } else if (ctron) {
+	name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
+	start_page = 0x01;
+	stop_page = (wordlength == 2) ? 0x40 : 0x20;
+    } else {
+	printk(" not found.\n");
+	return -ENXIO;
+
+    }
+
+#else
+    wordlength = 2;
+    /* We must set the 8390 for word mode. */
+    outb(0x49, ioaddr + NE_EN0_DCFG);
+    start_page = NESM_START_PG;
+    stop_page = NESM_STOP_PG;
+
+    SA_prom[0] = MANUAL_HWADDR0;
+    SA_prom[1] = MANUAL_HWADDR1;
+    SA_prom[2] = MANUAL_HWADDR2;
+    SA_prom[3] = MANUAL_HWADDR3;
+    SA_prom[4] = MANUAL_HWADDR4;
+    SA_prom[5] = MANUAL_HWADDR5;
+    name = "NE2000";
+#endif
+
+    dev->base_addr = ioaddr;
+    dev->irq = IRQ_AMIGA_PORTS;
+    dev->netdev_ops = &ei_netdev_ops;
+
+    /* Install the Interrupt handler */
+    i = request_irq(dev->irq, apne_interrupt, IRQF_SHARED, DRV_NAME, dev);
+    if (i) return i;
+
+    for(i = 0; i < ETHER_ADDR_LEN; i++)
+	dev->dev_addr[i] = SA_prom[i];
+
+    printk(" %pM\n", dev->dev_addr);
+
+    printk("%s: %s found.\n", dev->name, name);
+
+    ei_status.name = name;
+    ei_status.tx_start_page = start_page;
+    ei_status.stop_page = stop_page;
+    ei_status.word16 = (wordlength == 2);
+
+    ei_status.rx_start_page = start_page + TX_PAGES;
+
+    ei_status.reset_8390 = &apne_reset_8390;
+    ei_status.block_input = &apne_block_input;
+    ei_status.block_output = &apne_block_output;
+    ei_status.get_8390_hdr = &apne_get_8390_hdr;
+
+    NS8390_init(dev, 0);
+
+    pcmcia_ack_int(pcmcia_get_intreq());		/* ack PCMCIA int req */
+    pcmcia_enable_irq();
+
+    apne_owned = 1;
+
+    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. */
+static void
+apne_reset_8390(struct net_device *dev)
+{
+    unsigned long reset_start_time = jiffies;
+
+    init_pcmcia();
+
+    if (ei_debug > 1) printk("resetting the 8390 t=%ld...", jiffies);
+
+    outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+    ei_status.txing = 0;
+    ei_status.dmaing = 0;
+
+    /* This check _should_not_ be necessary, omit eventually. */
+    while ((inb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0)
+	if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
+	    printk("%s: ne_reset_8390() did not complete.\n", dev->name);
+	    break;
+	}
+    outb(ENISR_RESET, NE_BASE + NE_EN0_ISR);	/* Ack intr. */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void
+apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+
+    int nic_base = dev->base_addr;
+    int cnt;
+    char *ptrc;
+    short *ptrs;
+
+    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+    if (ei_status.dmaing) {
+	printk("%s: DMAing conflict in ne_get_8390_hdr "
+	   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+	   dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
+	return;
+    }
+
+    ei_status.dmaing |= 0x01;
+    outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+    outb(ENISR_RDC, nic_base + NE_EN0_ISR);
+    outb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
+    outb(0, nic_base + NE_EN0_RCNTHI);
+    outb(0, nic_base + NE_EN0_RSARLO);		/* On page boundary */
+    outb(ring_page, nic_base + NE_EN0_RSARHI);
+    outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+    if (ei_status.word16) {
+        ptrs = (short*)hdr;
+        for(cnt = 0; cnt < (sizeof(struct e8390_pkt_hdr)>>1); cnt++)
+            *ptrs++ = inw(NE_BASE + NE_DATAPORT);
+    } else {
+        ptrc = (char*)hdr;
+        for(cnt = 0; cnt < sizeof(struct e8390_pkt_hdr); cnt++)
+            *ptrc++ = inb(NE_BASE + NE_DATAPORT);
+    }
+
+    outb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
+    ei_status.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 outb. */
+
+static void
+apne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+    int nic_base = dev->base_addr;
+    char *buf = skb->data;
+    char *ptrc;
+    short *ptrs;
+    int cnt;
+
+    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+    if (ei_status.dmaing) {
+	printk("%s: DMAing conflict in ne_block_input "
+	   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+	   dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
+	return;
+    }
+    ei_status.dmaing |= 0x01;
+    outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+    outb(ENISR_RDC, nic_base + NE_EN0_ISR);
+    outb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+    outb(count >> 8, nic_base + NE_EN0_RCNTHI);
+    outb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
+    outb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
+    outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+    if (ei_status.word16) {
+      ptrs = (short*)buf;
+      for (cnt = 0; cnt < (count>>1); cnt++)
+        *ptrs++ = inw(NE_BASE + NE_DATAPORT);
+      if (count & 0x01) {
+	buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+      }
+    } else {
+      ptrc = (char*)buf;
+      for (cnt = 0; cnt < count; cnt++)
+        *ptrc++ = inb(NE_BASE + NE_DATAPORT);
+    }
+
+    outb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
+    ei_status.dmaing &= ~0x01;
+}
+
+static void
+apne_block_output(struct net_device *dev, int count,
+		const unsigned char *buf, const int start_page)
+{
+    int nic_base = NE_BASE;
+    unsigned long dma_start;
+    char *ptrc;
+    short *ptrs;
+    int cnt;
+
+    /* 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))
+      count++;
+
+    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+    if (ei_status.dmaing) {
+	printk("%s: DMAing conflict in ne_block_output."
+	   "[DMAstat:%d][irqlock:%d][intr:%d]\n",
+	   dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
+	return;
+    }
+    ei_status.dmaing |= 0x01;
+    /* We should already be in page 0, but to be safe... */
+    outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+    outb(ENISR_RDC, nic_base + NE_EN0_ISR);
+
+   /* Now the normal output. */
+    outb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+    outb(count >> 8,   nic_base + NE_EN0_RCNTHI);
+    outb(0x00, nic_base + NE_EN0_RSARLO);
+    outb(start_page, nic_base + NE_EN0_RSARHI);
+
+    outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+    if (ei_status.word16) {
+        ptrs = (short*)buf;
+        for (cnt = 0; cnt < count>>1; cnt++)
+            outw(*ptrs++, NE_BASE+NE_DATAPORT);
+    } else {
+        ptrc = (char*)buf;
+        for (cnt = 0; cnt < count; cnt++)
+	    outb(*ptrc++, NE_BASE + NE_DATAPORT);
+    }
+
+    dma_start = jiffies;
+
+    while ((inb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
+	if (time_after(jiffies, dma_start + 2*HZ/100)) {	/* 20ms */
+		printk("%s: timeout waiting for Tx RDC.\n", dev->name);
+		apne_reset_8390(dev);
+		NS8390_init(dev,1);
+		break;
+	}
+
+    outb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
+    ei_status.dmaing &= ~0x01;
+}
+
+static irqreturn_t apne_interrupt(int irq, void *dev_id)
+{
+    unsigned char pcmcia_intreq;
+
+    if (!(gayle.inten & GAYLE_IRQ_IRQ))
+        return IRQ_NONE;
+
+    pcmcia_intreq = pcmcia_get_intreq();
+
+    if (!(pcmcia_intreq & GAYLE_IRQ_IRQ)) {
+        pcmcia_ack_int(pcmcia_intreq);
+        return IRQ_NONE;
+    }
+    if (ei_debug > 3)
+        printk("pcmcia intreq = %x\n", pcmcia_intreq);
+    pcmcia_disable_irq();			/* to get rid of the sti() within ei_interrupt */
+    ei_interrupt(irq, dev_id);
+    pcmcia_ack_int(pcmcia_get_intreq());
+    pcmcia_enable_irq();
+    return IRQ_HANDLED;
+}
+
+#ifdef MODULE
+static struct net_device *apne_dev;
+
+static int __init apne_module_init(void)
+{
+	apne_dev = apne_probe(-1);
+	if (IS_ERR(apne_dev))
+		return PTR_ERR(apne_dev);
+	return 0;
+}
+
+static void __exit apne_module_exit(void)
+{
+	unregister_netdev(apne_dev);
+
+	pcmcia_disable_irq();
+
+	free_irq(IRQ_AMIGA_PORTS, apne_dev);
+
+	pcmcia_reset();
+
+	release_region(IOBASE, 0x20);
+
+	free_netdev(apne_dev);
+}
+module_init(apne_module_init);
+module_exit(apne_module_exit);
+#endif
+
+static int init_pcmcia(void)
+{
+	u_char config;
+#ifndef MANUAL_CONFIG
+	u_char tuple[32];
+	int offset_len;
+#endif
+	u_long offset;
+
+	pcmcia_reset();
+	pcmcia_program_voltage(PCMCIA_0V);
+	pcmcia_access_speed(PCMCIA_SPEED_250NS);
+	pcmcia_write_enable();
+
+#ifdef MANUAL_CONFIG
+	config = MANUAL_CONFIG;
+#else
+	/* get and write config byte to enable IO port */
+
+	if (pcmcia_copy_tuple(CISTPL_CFTABLE_ENTRY, tuple, 32) < 3)
+		return 0;
+
+	config = tuple[2] & 0x3f;
+#endif
+#ifdef MANUAL_OFFSET
+	offset = MANUAL_OFFSET;
+#else
+	if (pcmcia_copy_tuple(CISTPL_CONFIG, tuple, 32) < 6)
+		return 0;
+
+	offset_len = (tuple[2] & 0x3) + 1;
+	offset = 0;
+	while(offset_len--) {
+		offset = (offset << 8) | tuple[4+offset_len];
+	}
+#endif
+
+	out_8(GAYLE_ATTRIBUTE+offset, config);
+
+	return 1;
+}
+
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/ax88796.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/ax88796.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/ax88796.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/ax88796.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1010 @@
+/* drivers/net/ax88796.c
+ *
+ * Copyright 2005,2007 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Asix AX88796 10/100 Ethernet controller support
+ *	Based on ne.c, by Donald Becker, et-al.
+ *
+ * This program is free software; you can 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/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/mdio-bitbang.h>
+#include <linux/phy.h>
+#include <linux/eeprom_93cx6.h>
+#include <linux/slab.h>
+
+#include <net/ax88796.h>
+
+#include <asm/system.h>
+
+/* 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_start_xmit ax_ei_start_xmit
+#define __ei_tx_timeout ax_ei_tx_timeout
+#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 ____alloc_ei_netdev ax__alloc_ei_netdev
+#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_outb(_v, _a) writeb(_v, ax_convert_addr(_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)])
+
+/* Ensure we have our RCR base value */
+#define AX88796_PLATFORM
+
+static unsigned char version[] = "ax88796.c: Copyright 2005,2007 Simtec Electronics\n";
+
+#include "lib8390.c"
+
+#define DRV_NAME "ax88796"
+#define DRV_VERSION "1.00"
+
+/* from ne.c */
+#define NE_CMD		EI_SHIFT(0x00)
+#define NE_RESET	EI_SHIFT(0x1f)
+#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 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 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;
+
+	void __iomem *map2;
+	const struct ax_plat_data *plat;
+
+	unsigned char running;
+	unsigned char resume_open;
+	unsigned int irqflags;
+
+	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);
+}
+
+/*
+ * 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);
+	void __iomem *ioaddr = ei_local->mem;
+	int reg0;
+	int regd;
+
+	reg0 = ei_inb(ioaddr);
+	if (reg0 == 0xFF)
+		return -ENODEV;
+
+	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_inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
+	if (ei_inb(ioaddr + EN0_COUNTER0) != 0) {
+		ei_outb(reg0, ioaddr);
+		ei_outb(regd, ioaddr + 0x0d);	/* Restore the old values. */
+		return -ENODEV;
+	}
+
+	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.
+ */
+static void ax_reset_8390(struct net_device *dev)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	unsigned long reset_start_time = jiffies;
+	void __iomem *addr = (void __iomem *)dev->base_addr;
+
+	if (ei_debug > 1)
+		netdev_dbg(dev, "resetting the 8390 t=%ld\n", jiffies);
+
+	ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
+
+	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) {
+			netdev_warn(dev, "%s: did not complete.\n", __func__);
+			break;
+		}
+	}
+
+	ei_outb(ENISR_RESET, addr + EN0_ISR);	/* Ack intr. */
+}
+
+
+static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+			    int ring_page)
+{
+	struct ei_device *ei_local = netdev_priv(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_local->dmaing) {
+		netdev_err(dev, "DMAing conflict in %s "
+			"[DMAstat:%d][irqlock:%d].\n",
+			__func__,
+			ei_local->dmaing, ei_local->irqlock);
+		return;
+	}
+
+	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_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));
+
+	ei_outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	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.
+ */
+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);
+	void __iomem *nic_base = ei_local->mem;
+	char *buf = skb->data;
+
+	if (ei_local->dmaing) {
+		netdev_err(dev,
+			"DMAing conflict in %s "
+			"[DMAstat:%d][irqlock:%d].\n",
+			__func__,
+			ei_local->dmaing, ei_local->irqlock);
+		return;
+	}
+
+	ei_local->dmaing |= 0x01;
+
+	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_local->word16) {
+		readsw(nic_base + NE_DATAPORT, buf, count >> 1);
+		if (count & 0x01)
+			buf[count-1] = ei_inb(nic_base + NE_DATAPORT);
+
+	} else {
+		readsb(nic_base + NE_DATAPORT, buf, count);
+	}
+
+	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);
+	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_local->word16 && (count & 0x01))
+		count++;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+	if (ei_local->dmaing) {
+		netdev_err(dev, "DMAing conflict in %s."
+			"[DMAstat:%d][irqlock:%d]\n",
+			__func__,
+		       ei_local->dmaing, ei_local->irqlock);
+		return;
+	}
+
+	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);
+
+	ei_outb(ENISR_RDC, nic_base + EN0_ISR);
+
+	/* Now the normal output. */
+	ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
+	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_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 */
+			netdev_warn(dev, "timeout waiting for Tx RDC.\n");
+			ax_reset_8390(dev);
+			ax_NS8390_init(dev, 1);
+			break;
+		}
+	}
+
+	ei_outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_local->dmaing &= ~0x01;
+}
+
+/* definitions for accessing MII/EEPROM interface */
+
+#define AX_MEMR			EI_SHIFT(0x14)
+#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_handle_link_change(struct net_device *dev)
+{
+	struct ax_device  *ax = to_ax_dev(dev);
+	struct phy_device *phy_dev = ax->phy_dev;
+	int status_change = 0;
+
+	if (phy_dev->link && ((ax->speed != phy_dev->speed) ||
+			     (ax->duplex != phy_dev->duplex))) {
+
+		ax->speed = phy_dev->speed;
+		ax->duplex = phy_dev->duplex;
+		status_change = 1;
+	}
+
+	if (phy_dev->link != ax->link) {
+		if (!phy_dev->link) {
+			ax->speed = 0;
+			ax->duplex = -1;
+		}
+		ax->link = phy_dev->link;
+
+		status_change = 1;
+	}
+
+	if (status_change)
+		phy_print_status(phy_dev);
+}
+
+static int ax_mii_probe(struct net_device *dev)
+{
+	struct ax_device  *ax = to_ax_dev(dev);
+	struct phy_device *phy_dev = NULL;
+	int ret;
+
+	/* find the first phy */
+	phy_dev = phy_find_first(ax->mii_bus);
+	if (!phy_dev) {
+		netdev_err(dev, "no PHY found\n");
+		return -ENODEV;
+	}
+
+	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;
+	}
+
+	/* mask with MAC supported features */
+	phy_dev->supported &= PHY_BASIC_FEATURES;
+	phy_dev->advertising = phy_dev->supported;
+
+	ax->phy_dev = phy_dev;
+
+	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);
+
+	return 0;
+}
+
+static void ax_phy_switch(struct net_device *dev, int on)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	struct ax_device *ax = to_ax_dev(dev);
+
+	u8 reg_gpoc =  ax->plat->gpoc_val;
+
+	if (!!on)
+		reg_gpoc &= ~AX_GPOC_PPDSET;
+	else
+		reg_gpoc |= AX_GPOC_PPDSET;
+
+	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);
+	int ret;
+
+	netdev_dbg(dev, "open\n");
+
+	ret = request_irq(dev->irq, ax_ei_interrupt, ax->irqflags,
+			  dev->name, dev);
+	if (ret)
+		goto failed_request_irq;
+
+	/* turn the phy on (if turned off) */
+	ax_phy_switch(dev, 1);
+
+	ret = ax_mii_probe(dev);
+	if (ret)
+		goto failed_mii_probe;
+	phy_start(ax->phy_dev);
+
+	ret = ax_ei_open(dev);
+	if (ret)
+		goto failed_ax_ei_open;
+
+	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);
+
+	netdev_dbg(dev, "close\n");
+
+	ax->running = 0;
+	wmb();
+
+	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;
+}
+
+static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+	struct ax_device *ax = to_ax_dev(dev);
+	struct phy_device *phy_dev = ax->phy_dev;
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	if (!phy_dev)
+		return -ENODEV;
+
+	return phy_mii_ioctl(phy_dev, req, cmd);
+}
+
+/* ethtool ops */
+
+static void ax_get_drvinfo(struct net_device *dev,
+			   struct ethtool_drvinfo *info)
+{
+	struct platform_device *pdev = to_platform_device(dev->dev.parent);
+
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	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);
+	struct phy_device *phy_dev = ax->phy_dev;
+
+	if (!phy_dev)
+		return -ENODEV;
+
+	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);
+	struct phy_device *phy_dev = ax->phy_dev;
+
+	if (!phy_dev)
+		return -ENODEV;
+
+	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,
+	.get_link		= ethtool_op_get_link,
+};
+
+#ifdef CONFIG_AX88796_93CX6
+static void ax_eeprom_register_read(struct eeprom_93cx6 *eeprom)
+{
+	struct ei_device *ei_local = eeprom->data;
+	u8 reg = ei_inb(ei_local->mem + AX_MEMR);
+
+	eeprom->reg_data_in = reg & AX_MEMR_EEI;
+	eeprom->reg_data_out = reg & AX_MEMR_EEO; /* Input pin */
+	eeprom->reg_data_clock = reg & AX_MEMR_EECLK;
+	eeprom->reg_chip_select = reg & AX_MEMR_EECS;
+}
+
+static void ax_eeprom_register_write(struct eeprom_93cx6 *eeprom)
+{
+	struct ei_device *ei_local = eeprom->data;
+	u8 reg = ei_inb(ei_local->mem + AX_MEMR);
+
+	reg &= ~(AX_MEMR_EEI | AX_MEMR_EECLK | AX_MEMR_EECS);
+
+	if (eeprom->reg_data_in)
+		reg |= AX_MEMR_EEI;
+	if (eeprom->reg_data_clock)
+		reg |= AX_MEMR_EECLK;
+	if (eeprom->reg_chip_select)
+		reg |= AX_MEMR_EECS;
+
+	ei_outb(reg, ei_local->mem + AX_MEMR);
+	udelay(10);
+}
+#endif
+
+static const struct net_device_ops ax_netdev_ops = {
+	.ndo_open		= ax_open,
+	.ndo_stop		= ax_close,
+	.ndo_do_ioctl		= ax_ioctl,
+
+	.ndo_start_xmit		= ax_ei_start_xmit,
+	.ndo_tx_timeout		= ax_ei_tx_timeout,
+	.ndo_get_stats		= ax_ei_get_stats,
+	.ndo_set_rx_mode	= ax_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	= 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);
+
+	/* 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
+ *
+ * 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)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	struct ax_device *ax = to_ax_dev(dev);
+	void __iomem *ioaddr = ei_local->mem;
+	unsigned int start_page;
+	unsigned int stop_page;
+	int ret;
+	int i;
+
+	ret = ax_initial_check(dev);
+	if (ret)
+		goto err_out;
+
+	/* setup goes here */
+
+	ax_initial_setup(dev, ei_local);
+
+	/* read the mac from the card prom if we need it */
+
+	if (ax->plat->flags & AXFLG_HAS_EEPROM) {
+		unsigned char SA_prom[32];
+
+		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);
+		}
+
+		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);
+	}
+
+#ifdef CONFIG_AX88796_93CX6
+	if (ax->plat->flags & AXFLG_HAS_93CX6) {
+		unsigned char mac_addr[6];
+		struct eeprom_93cx6 eeprom;
+
+		eeprom.data = ei_local;
+		eeprom.register_read = ax_eeprom_register_read;
+		eeprom.register_write = ax_eeprom_register_write;
+		eeprom.width = PCI_EEPROM_WIDTH_93C56;
+
+		eeprom_93cx6_multiread(&eeprom, 0,
+				       (__le16 __force *)mac_addr,
+				       sizeof(mac_addr) >> 1);
+
+		memcpy(dev->dev_addr, mac_addr, 6);
+	}
+#endif
+	if (ax->plat->wordlength == 2) {
+		/* We must set the 8390 for word mode. */
+		ei_outb(ax->plat->dcr_val, ei_local->mem + EN0_DCFG);
+		start_page = NESM_START_PG;
+		stop_page = NESM_STOP_PG;
+	} else {
+		start_page = NE1SM_START_PG;
+		stop_page = NE1SM_STOP_PG;
+	}
+
+	/* 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_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_local->stop_page = ei_local->tx_start_page + PACKETBUF_MEMSIZE;
+#endif
+
+	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;
+
+	ret = ax_mii_init(dev);
+	if (ret)
+		goto out_irq;
+
+	ax_NS8390_init(dev, 0);
+
+	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:
+	/* cleanup irq */
+	free_irq(dev->irq, dev);
+ err_out:
+	return ret;
+}
+
+static int ax_remove(struct platform_device *pdev)
+{
+	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_local->mem);
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+
+	if (ax->map2) {
+		iounmap(ax->map2);
+		mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+		release_mem_region(mem->start, resource_size(mem));
+	}
+
+	free_netdev(dev);
+
+	return 0;
+}
+
+/*
+ * 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.
+ */
+static int ax_probe(struct platform_device *pdev)
+{
+	struct net_device *dev;
+	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));
+	if (dev == NULL)
+		return -ENOMEM;
+
+	/* ok, let's setup our device */
+	SET_NETDEV_DEV(dev, &pdev->dev);
+	ei_local = netdev_priv(dev);
+	ax = to_ax_dev(dev);
+
+	ax->plat = pdev->dev.platform_data;
+	platform_set_drvdata(pdev, dev);
+
+	ei_local->rxcr_base = ax->plat->rcr_val;
+
+	/* find the platform resources */
+	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 = irq->start;
+	ax->irqflags = irq->flags & IRQF_TRIGGER_MASK;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "no MEM specified\n");
+		ret = -ENXIO;
+		goto exit_mem;
+	}
+
+	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_local->reg_offset = ax->plat->reg_offsets;
+	else {
+		ei_local->reg_offset = ax->reg_offsets;
+		for (ret = 0; ret < 0x18; ret++)
+			ax->reg_offsets[ret] = (mem_size / 0x18) * ret;
+	}
+
+	if (!request_mem_region(mem->start, mem_size, pdev->name)) {
+		dev_err(&pdev->dev, "cannot reserve registers\n");
+		ret = -ENXIO;
+		goto exit_mem;
+	}
+
+	ei_local->mem = ioremap(mem->start, mem_size);
+	dev->base_addr = (unsigned long)ei_local->mem;
+
+	if (ei_local->mem == NULL) {
+		dev_err(&pdev->dev, "Cannot ioremap area %pR\n", mem);
+
+		ret = -ENXIO;
+		goto exit_req;
+	}
+
+	/* look for reset area */
+	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] = (mem_size / 0x20) * ret;
+		}
+	} else {
+		mem2_size = resource_size(mem2);
+
+		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(mem2->start, mem2_size);
+		if (!ax->map2) {
+			dev_err(&pdev->dev, "cannot map reset register\n");
+			ret = -ENXIO;
+			goto exit_mem2;
+		}
+
+		ei_local->reg_offset[0x1f] = ax->map2 - ei_local->mem;
+	}
+
+	/* got resources, now initialise and register device */
+	ret = ax_init_dev(dev);
+	if (!ret)
+		return 0;
+
+	if (!ax->map2)
+		goto exit_mem1;
+
+	iounmap(ax->map2);
+
+ exit_mem2:
+	release_mem_region(mem2->start, mem2_size);
+
+ exit_mem1:
+	iounmap(ei_local->mem);
+
+ exit_req:
+	release_mem_region(mem->start, mem_size);
+
+ exit_mem:
+	free_netdev(dev);
+
+	return ret;
+}
+
+/* suspend and resume */
+
+#ifdef CONFIG_PM
+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);
+
+	ax->resume_open = ax->running;
+
+	netif_device_detach(ndev);
+	ax_close(ndev);
+
+	return 0;
+}
+
+static int ax_resume(struct platform_device *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct ax_device *ax = to_ax_dev(ndev);
+
+	ax_initial_setup(ndev, netdev_priv(ndev));
+	ax_NS8390_init(ndev, ax->resume_open);
+	netif_device_attach(ndev);
+
+	if (ax->resume_open)
+		ax_open(ndev);
+
+	return 0;
+}
+
+#else
+#define ax_suspend NULL
+#define ax_resume NULL
+#endif
+
+static struct platform_driver axdrv = {
+	.driver	= {
+		.name		= "ax88796",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= ax_probe,
+	.remove		= ax_remove,
+	.suspend	= ax_suspend,
+	.resume		= ax_resume,
+};
+
+static int __init axdrv_init(void)
+{
+	return platform_driver_register(&axdrv);
+}
+
+static void __exit axdrv_exit(void)
+{
+	platform_driver_unregister(&axdrv);
+}
+
+module_init(axdrv_init);
+module_exit(axdrv_exit);
+
+MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
+MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:ax88796");
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/axnet_cs.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/axnet_cs.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/axnet_cs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/axnet_cs.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1725 @@
+/*======================================================================
+
+    A PCMCIA ethernet driver for Asix AX88190-based cards
+
+    The Asix AX88190 is a NS8390-derived chipset with a few nasty
+    idiosyncracies that make it very inconvenient to support with a
+    standard 8390 driver.  This driver is based on pcnet_cs, with the
+    tweaked 8390 code grafted on the end.  Much of what I did was to
+    clean up and update a similar driver supplied by Asix, which was
+    adapted by William Lee, william@asix.com.tw.
+
+    Copyright (C) 2001 David A. Hinds -- dahinds@users.sourceforge.net
+
+    axnet_cs.c 1.28 2002/06/29 06:27:37
+
+    The network driver code is based on Donald Becker's NE2000 code:
+
+    Written 1992,1993 by Donald Becker.
+    Copyright 1993 United States Government as represented by the
+    Director, National Security Agency.  This software may be used and
+    distributed according to the terms of the GNU General Public License,
+    incorporated herein by reference.
+    Donald Becker may be reached at becker@scyld.com
+
+======================================================================*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include "8390.h"
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ciscode.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#define AXNET_CMD	0x00
+#define AXNET_DATAPORT	0x10	/* NatSemi-defined port window offset. */
+#define AXNET_RESET	0x1f	/* Issue a read to reset, a write to clear. */
+#define AXNET_MII_EEP	0x14	/* Offset of MII access port */
+#define AXNET_TEST	0x15	/* Offset of TEST Register port */
+#define AXNET_GPIO	0x17	/* Offset of General Purpose Register Port */
+
+#define AXNET_START_PG	0x40	/* First page of TX buffer */
+#define AXNET_STOP_PG	0x80	/* Last page +1 of RX ring */
+
+#define AXNET_RDC_TIMEOUT 0x02	/* Max wait in jiffies for Tx RDC */
+
+#define IS_AX88190	0x0001
+#define IS_AX88790	0x0002
+
+/*====================================================================*/
+
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
+MODULE_DESCRIPTION("Asix AX88190 PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");
+
+
+/*====================================================================*/
+
+static int axnet_config(struct pcmcia_device *link);
+static void axnet_release(struct pcmcia_device *link);
+static int axnet_open(struct net_device *dev);
+static int axnet_close(struct net_device *dev);
+static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static netdev_tx_t axnet_start_xmit(struct sk_buff *skb,
+					  struct net_device *dev);
+static struct net_device_stats *get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+static void axnet_tx_timeout(struct net_device *dev);
+static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
+static void ei_watchdog(u_long arg);
+static void axnet_reset_8390(struct net_device *dev);
+
+static int mdio_read(unsigned int addr, int phy_id, int loc);
+static void mdio_write(unsigned int addr, int phy_id, int loc, int value);
+
+static void get_8390_hdr(struct net_device *,
+			 struct e8390_pkt_hdr *, int);
+static void block_input(struct net_device *dev, int count,
+			struct sk_buff *skb, int ring_offset);
+static void block_output(struct net_device *dev, int count,
+			 const u_char *buf, const int start_page);
+
+static void axnet_detach(struct pcmcia_device *p_dev);
+
+static void AX88190_init(struct net_device *dev, int startp);
+static int ax_open(struct net_device *dev);
+static int ax_close(struct net_device *dev);
+static irqreturn_t ax_interrupt(int irq, void *dev_id);
+
+/*====================================================================*/
+
+typedef struct axnet_dev_t {
+	struct pcmcia_device	*p_dev;
+	caddr_t	base;
+	struct timer_list	watchdog;
+	int	stale, fast_poll;
+	u_short	link_status;
+	u_char	duplex_flag;
+	int	phy_id;
+	int	flags;
+	int	active_low;
+} axnet_dev_t;
+
+static inline axnet_dev_t *PRIV(struct net_device *dev)
+{
+	void *p = (char *)netdev_priv(dev) + sizeof(struct ei_device);
+	return p;
+}
+
+static const struct net_device_ops axnet_netdev_ops = {
+	.ndo_open 		= axnet_open,
+	.ndo_stop		= axnet_close,
+	.ndo_do_ioctl		= axnet_ioctl,
+	.ndo_start_xmit		= axnet_start_xmit,
+	.ndo_tx_timeout		= axnet_tx_timeout,
+	.ndo_get_stats		= get_stats,
+	.ndo_set_rx_mode	= set_multicast_list,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+static int axnet_probe(struct pcmcia_device *link)
+{
+    axnet_dev_t *info;
+    struct net_device *dev;
+    struct ei_device *ei_local;
+
+    dev_dbg(&link->dev, "axnet_attach()\n");
+
+    dev = alloc_etherdev(sizeof(struct ei_device) + sizeof(axnet_dev_t));
+    if (!dev)
+	return -ENOMEM;
+
+    ei_local = netdev_priv(dev);
+    spin_lock_init(&ei_local->page_lock);
+
+    info = PRIV(dev);
+    info->p_dev = link;
+    link->priv = dev;
+    link->config_flags |= CONF_ENABLE_IRQ;
+
+    dev->netdev_ops = &axnet_netdev_ops;
+
+    dev->watchdog_timeo = TX_TIMEOUT;
+
+    return axnet_config(link);
+} /* axnet_attach */
+
+static void axnet_detach(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+
+    dev_dbg(&link->dev, "axnet_detach(0x%p)\n", link);
+
+    unregister_netdev(dev);
+
+    axnet_release(link);
+
+    free_netdev(dev);
+} /* axnet_detach */
+
+/*======================================================================
+
+    This probes for a card's hardware address by reading the PROM.
+
+======================================================================*/
+
+static int get_prom(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    unsigned int ioaddr = dev->base_addr;
+    int i, j;
+
+    /* This is based on drivers/net/ne.c */
+    struct {
+	u_char value, offset;
+    } program_seq[] = {
+	{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+	{0x01,	EN0_DCFG},	/* Set word-wide access. */
+	{0x00,	EN0_RCNTLO},	/* Clear the count regs. */
+	{0x00,	EN0_RCNTHI},
+	{0x00,	EN0_IMR},	/* Mask completion irq. */
+	{0xFF,	EN0_ISR},
+	{E8390_RXOFF|0x40, EN0_RXCR},	/* 0x60  Set to monitor */
+	{E8390_TXOFF, EN0_TXCR},	/* 0x02  and loopback mode. */
+	{0x10,	EN0_RCNTLO},
+	{0x00,	EN0_RCNTHI},
+	{0x00,	EN0_RSARLO},	/* DMA starting at 0x0400. */
+	{0x04,	EN0_RSARHI},
+	{E8390_RREAD+E8390_START, E8390_CMD},
+    };
+
+    /* Not much of a test, but the alternatives are messy */
+    if (link->config_base != 0x03c0)
+	return 0;
+
+    axnet_reset_8390(dev);
+    mdelay(10);
+
+    for (i = 0; i < ARRAY_SIZE(program_seq); i++)
+	outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
+
+    for (i = 0; i < 6; i += 2) {
+	j = inw(ioaddr + AXNET_DATAPORT);
+	dev->dev_addr[i] = j & 0xff;
+	dev->dev_addr[i+1] = j >> 8;
+    }
+    return 1;
+} /* get_prom */
+
+static int try_io_port(struct pcmcia_device *link)
+{
+    int j, ret;
+    link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+    link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+    if (link->resource[0]->end == 32) {
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+	/* for master/slave multifunction cards */
+	if (link->resource[1]->end > 0)
+	    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+    } else {
+	/* This should be two 16-port windows */
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
+    }
+    if (link->resource[0]->start == 0) {
+	for (j = 0; j < 0x400; j += 0x20) {
+	    link->resource[0]->start = j ^ 0x300;
+	    link->resource[1]->start = (j ^ 0x300) + 0x10;
+	    link->io_lines = 16;
+	    ret = pcmcia_request_io(link);
+	    if (ret == 0)
+		    return ret;
+	}
+	return ret;
+    } else {
+	return pcmcia_request_io(link);
+    }
+}
+
+static int axnet_configcheck(struct pcmcia_device *p_dev, void *priv_data)
+{
+	if (p_dev->config_index == 0)
+		return -EINVAL;
+
+	p_dev->config_index = 0x05;
+	if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
+		return -ENODEV;
+
+	return try_io_port(p_dev);
+}
+
+static int axnet_config(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    axnet_dev_t *info = PRIV(dev);
+    int i, j, j2, ret;
+
+    dev_dbg(&link->dev, "axnet_config(0x%p)\n", link);
+
+    /* don't trust the CIS on this; Linksys got it wrong */
+    link->config_regs = 0x63;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+    ret = pcmcia_loop_config(link, axnet_configcheck, NULL);
+    if (ret != 0)
+	goto failed;
+
+    if (!link->irq)
+	    goto failed;
+
+    if (resource_size(link->resource[1]) == 8)
+	link->config_flags |= CONF_ENABLE_SPKR;
+    
+    ret = pcmcia_enable_device(link);
+    if (ret)
+	    goto failed;
+
+    dev->irq = link->irq;
+    dev->base_addr = link->resource[0]->start;
+
+    if (!get_prom(link)) {
+	pr_notice("this is not an AX88190 card!\n");
+	pr_notice("use pcnet_cs instead.\n");
+	goto failed;
+    }
+
+    ei_status.name = "AX88190";
+    ei_status.word16 = 1;
+    ei_status.tx_start_page = AXNET_START_PG;
+    ei_status.rx_start_page = AXNET_START_PG + TX_PAGES;
+    ei_status.stop_page = AXNET_STOP_PG;
+    ei_status.reset_8390 = axnet_reset_8390;
+    ei_status.get_8390_hdr = get_8390_hdr;
+    ei_status.block_input = block_input;
+    ei_status.block_output = block_output;
+
+    if (inb(dev->base_addr + AXNET_TEST) != 0)
+	info->flags |= IS_AX88790;
+    else
+	info->flags |= IS_AX88190;
+
+    if (info->flags & IS_AX88790)
+	outb(0x10, dev->base_addr + AXNET_GPIO);  /* select Internal PHY */
+
+    info->active_low = 0;
+
+    for (i = 0; i < 32; i++) {
+	j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
+	j2 = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 2);
+	if (j == j2) continue;
+	if ((j != 0) && (j != 0xffff)) break;
+    }
+
+    if (i == 32) {
+	/* Maybe PHY is in power down mode. (PPD_SET = 1)
+	   Bit 2 of CCSR is active low. */
+	pcmcia_write_config_byte(link, CISREG_CCSR, 0x04);
+	for (i = 0; i < 32; i++) {
+	    j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
+	    j2 = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 2);
+	    if (j == j2) continue;
+	    if ((j != 0) && (j != 0xffff)) {
+		info->active_low = 1;
+		break;
+	    }
+	}
+    }
+
+    info->phy_id = (i < 32) ? i : -1;
+    SET_NETDEV_DEV(dev, &link->dev);
+
+    if (register_netdev(dev) != 0) {
+	pr_notice("register_netdev() failed\n");
+	goto failed;
+    }
+
+    netdev_info(dev, "Asix AX88%d90: io %#3lx, irq %d, hw_addr %pM\n",
+		((info->flags & IS_AX88790) ? 7 : 1),
+		dev->base_addr, dev->irq, dev->dev_addr);
+    if (info->phy_id != -1) {
+	netdev_dbg(dev, "  MII transceiver at index %d, status %x\n",
+		   info->phy_id, j);
+    } else {
+	netdev_notice(dev, "  No MII transceivers found!\n");
+    }
+    return 0;
+
+failed:
+    axnet_release(link);
+    return -ENODEV;
+} /* axnet_config */
+
+static void axnet_release(struct pcmcia_device *link)
+{
+	pcmcia_disable_device(link);
+}
+
+static int axnet_suspend(struct pcmcia_device *link)
+{
+	struct net_device *dev = link->priv;
+
+	if (link->open)
+		netif_device_detach(dev);
+
+	return 0;
+}
+
+static int axnet_resume(struct pcmcia_device *link)
+{
+	struct net_device *dev = link->priv;
+	axnet_dev_t *info = PRIV(dev);
+
+	if (link->open) {
+		if (info->active_low == 1)
+			pcmcia_write_config_byte(link, CISREG_CCSR, 0x04);
+
+		axnet_reset_8390(dev);
+		AX88190_init(dev, 1);
+		netif_device_attach(dev);
+	}
+
+	return 0;
+}
+
+
+/*======================================================================
+
+    MII interface support
+
+======================================================================*/
+
+#define MDIO_SHIFT_CLK		0x01
+#define MDIO_DATA_WRITE0	0x00
+#define MDIO_DATA_WRITE1	0x08
+#define MDIO_DATA_READ		0x04
+#define MDIO_MASK		0x0f
+#define MDIO_ENB_IN		0x02
+
+static void mdio_sync(unsigned int addr)
+{
+    int bits;
+    for (bits = 0; bits < 32; bits++) {
+	outb_p(MDIO_DATA_WRITE1, addr);
+	outb_p(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);
+    }
+}
+
+static int mdio_read(unsigned int addr, int phy_id, int loc)
+{
+    u_int cmd = (0xf6<<10)|(phy_id<<5)|loc;
+    int i, retval = 0;
+
+    mdio_sync(addr);
+    for (i = 14; i >= 0; i--) {
+	int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+	outb_p(dat, addr);
+	outb_p(dat | MDIO_SHIFT_CLK, addr);
+    }
+    for (i = 19; i > 0; i--) {
+	outb_p(MDIO_ENB_IN, addr);
+	retval = (retval << 1) | ((inb_p(addr) & MDIO_DATA_READ) != 0);
+	outb_p(MDIO_ENB_IN | MDIO_SHIFT_CLK, addr);
+    }
+    return (retval>>1) & 0xffff;
+}
+
+static void mdio_write(unsigned int addr, int phy_id, int loc, int value)
+{
+    u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
+    int i;
+
+    mdio_sync(addr);
+    for (i = 31; i >= 0; i--) {
+	int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+	outb_p(dat, addr);
+	outb_p(dat | MDIO_SHIFT_CLK, addr);
+    }
+    for (i = 1; i >= 0; i--) {
+	outb_p(MDIO_ENB_IN, addr);
+	outb_p(MDIO_ENB_IN | MDIO_SHIFT_CLK, addr);
+    }
+}
+
+/*====================================================================*/
+
+static int axnet_open(struct net_device *dev)
+{
+    int ret;
+    axnet_dev_t *info = PRIV(dev);
+    struct pcmcia_device *link = info->p_dev;
+    unsigned int nic_base = dev->base_addr;
+    
+    dev_dbg(&link->dev, "axnet_open('%s')\n", dev->name);
+
+    if (!pcmcia_dev_present(link))
+	return -ENODEV;
+
+    outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */
+    ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
+    if (ret)
+	    return ret;
+
+    link->open++;
+
+    info->link_status = 0x00;
+    init_timer(&info->watchdog);
+    info->watchdog.function = ei_watchdog;
+    info->watchdog.data = (u_long)dev;
+    info->watchdog.expires = jiffies + HZ;
+    add_timer(&info->watchdog);
+
+    return ax_open(dev);
+} /* axnet_open */
+
+/*====================================================================*/
+
+static int axnet_close(struct net_device *dev)
+{
+    axnet_dev_t *info = PRIV(dev);
+    struct pcmcia_device *link = info->p_dev;
+
+    dev_dbg(&link->dev, "axnet_close('%s')\n", dev->name);
+
+    ax_close(dev);
+    free_irq(dev->irq, dev);
+    
+    link->open--;
+    netif_stop_queue(dev);
+    del_timer_sync(&info->watchdog);
+
+    return 0;
+} /* axnet_close */
+
+/*======================================================================
+
+    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 axnet_reset_8390(struct net_device *dev)
+{
+    unsigned int nic_base = dev->base_addr;
+    int i;
+
+    ei_status.txing = ei_status.dmaing = 0;
+
+    outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, nic_base + E8390_CMD);
+
+    outb(inb(nic_base + AXNET_RESET), nic_base + AXNET_RESET);
+
+    for (i = 0; i < 100; i++) {
+	if ((inb_p(nic_base+EN0_ISR) & ENISR_RESET) != 0)
+	    break;
+	udelay(100);
+    }
+    outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */
+    
+    if (i == 100)
+	netdev_err(dev, "axnet_reset_8390() did not complete\n");
+    
+} /* axnet_reset_8390 */
+
+/*====================================================================*/
+
+static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
+{
+    struct net_device *dev = dev_id;
+    PRIV(dev)->stale = 0;
+    return ax_interrupt(irq, dev_id);
+}
+
+static void ei_watchdog(u_long arg)
+{
+    struct net_device *dev = (struct net_device *)(arg);
+    axnet_dev_t *info = PRIV(dev);
+    unsigned int nic_base = dev->base_addr;
+    unsigned int mii_addr = nic_base + AXNET_MII_EEP;
+    u_short link;
+
+    if (!netif_device_present(dev)) goto reschedule;
+
+    /* Check for pending interrupt with expired latency timer: with
+       this, we can limp along even if the interrupt is blocked */
+    if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
+	if (!info->fast_poll)
+	    netdev_info(dev, "interrupt(s) dropped!\n");
+	ei_irq_wrapper(dev->irq, dev);
+	info->fast_poll = HZ;
+    }
+    if (info->fast_poll) {
+	info->fast_poll--;
+	info->watchdog.expires = jiffies + 1;
+	add_timer(&info->watchdog);
+	return;
+    }
+
+    if (info->phy_id < 0)
+	goto reschedule;
+    link = mdio_read(mii_addr, info->phy_id, 1);
+    if (!link || (link == 0xffff)) {
+	netdev_info(dev, "MII is missing!\n");
+	info->phy_id = -1;
+	goto reschedule;
+    }
+
+    link &= 0x0004;
+    if (link != info->link_status) {
+	u_short p = mdio_read(mii_addr, info->phy_id, 5);
+	netdev_info(dev, "%s link beat\n", link ? "found" : "lost");
+	if (link) {
+	    info->duplex_flag = (p & 0x0140) ? 0x80 : 0x00;
+	    if (p)
+		netdev_info(dev, "autonegotiation complete: %dbaseT-%cD selected\n",
+			    (p & 0x0180) ? 100 : 10, (p & 0x0140) ? 'F' : 'H');
+	    else
+		netdev_info(dev, "link partner did not autonegotiate\n");
+	    AX88190_init(dev, 1);
+	}
+	info->link_status = link;
+    }
+
+reschedule:
+    info->watchdog.expires = jiffies + HZ;
+    add_timer(&info->watchdog);
+}
+
+/*====================================================================*/
+
+static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+    axnet_dev_t *info = PRIV(dev);
+    struct mii_ioctl_data *data = if_mii(rq);
+    unsigned int mii_addr = dev->base_addr + AXNET_MII_EEP;
+    switch (cmd) {
+    case SIOCGMIIPHY:
+	data->phy_id = info->phy_id;
+    case SIOCGMIIREG:		/* Read MII PHY register. */
+	data->val_out = mdio_read(mii_addr, data->phy_id, data->reg_num & 0x1f);
+	return 0;
+    case SIOCSMIIREG:		/* Write MII PHY register. */
+	mdio_write(mii_addr, data->phy_id, data->reg_num & 0x1f, data->val_in);
+	return 0;
+    }
+    return -EOPNOTSUPP;
+}
+
+/*====================================================================*/
+
+static void get_8390_hdr(struct net_device *dev,
+			 struct e8390_pkt_hdr *hdr,
+			 int ring_page)
+{
+    unsigned int nic_base = dev->base_addr;
+
+    outb_p(0, nic_base + EN0_RSARLO);		/* On page boundary */
+    outb_p(ring_page, nic_base + EN0_RSARHI);
+    outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD);
+
+    insw(nic_base + AXNET_DATAPORT, hdr,
+	    sizeof(struct e8390_pkt_hdr)>>1);
+    /* Fix for big endian systems */
+    hdr->count = le16_to_cpu(hdr->count);
+
+}
+
+/*====================================================================*/
+
+static void block_input(struct net_device *dev, int count,
+			struct sk_buff *skb, int ring_offset)
+{
+    unsigned int nic_base = dev->base_addr;
+    int xfer_count = count;
+    char *buf = skb->data;
+
+    if ((ei_debug > 4) && (count != 4))
+	    pr_debug("%s: [bi=%d]\n", dev->name, count+4);
+    outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
+    outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
+    outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD);
+
+    insw(nic_base + AXNET_DATAPORT,buf,count>>1);
+    if (count & 0x01)
+	buf[count-1] = inb(nic_base + AXNET_DATAPORT), xfer_count++;
+
+}
+
+/*====================================================================*/
+
+static void block_output(struct net_device *dev, int count,
+			 const u_char *buf, const int start_page)
+{
+    unsigned int nic_base = dev->base_addr;
+
+    pr_debug("%s: [bo=%d]\n", dev->name, count);
+
+    /* 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 (count & 0x01)
+	count++;
+
+    outb_p(0x00, nic_base + EN0_RSARLO);
+    outb_p(start_page, nic_base + EN0_RSARHI);
+    outb_p(E8390_RWRITE+E8390_START, nic_base + AXNET_CMD);
+    outsw(nic_base + AXNET_DATAPORT, buf, count>>1);
+}
+
+static const struct pcmcia_device_id axnet_ids[] = {
+	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x016c, 0x0081),
+	PCMCIA_DEVICE_MANF_CARD(0x018a, 0x0301),
+	PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x2328),
+	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0301),
+	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0303),
+	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0309),
+	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1106),
+	PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab),
+	PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202), 
+	PCMCIA_DEVICE_MANF_CARD(0xffff, 0x1090),
+	PCMCIA_DEVICE_PROD_ID12("AmbiCom,Inc.", "Fast Ethernet PC Card(AMB8110)", 0x49b020a7, 0x119cc9fc),
+	PCMCIA_DEVICE_PROD_ID124("Fast Ethernet", "16-bit PC Card", "AX88190", 0xb4be14e3, 0x9a12eb6a, 0xab9be5ef),
+	PCMCIA_DEVICE_PROD_ID12("ASIX", "AX88190", 0x0959823b, 0xab9be5ef),
+	PCMCIA_DEVICE_PROD_ID12("Billionton", "LNA-100B", 0x552ab682, 0xbc3b87e1),
+	PCMCIA_DEVICE_PROD_ID12("CHEETAH ETHERCARD", "EN2228", 0x00fa7bc8, 0x00e990cc),
+	PCMCIA_DEVICE_PROD_ID12("CNet", "CNF301", 0xbc477dde, 0x78c5f40b),
+	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXD", 0x5261440f, 0x436768c5),
+	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEtherII PCC-TXD", 0x5261440f, 0x730df72e),
+	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXM", 0x5261440f, 0x3abbd061),
+	PCMCIA_DEVICE_PROD_ID12("Dynalink", "L100C16", 0x55632fd5, 0x66bc2a90),
+	PCMCIA_DEVICE_PROD_ID12("IO DATA", "ETXPCM", 0x547e66dc, 0x233adac2),
+	PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V3)", 0x0733cc81, 0x232019a8),
+	PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC3-TX", 0x481e0094, 0xf91af609),
+	PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA411", 0x9aa79dc3, 0x40fad875),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "100BASE", 0x281f1c5d, 0x7c2add04),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEtherCard", 0x281f1c5d, 0x7ef26116),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FEP501", 0x281f1c5d, 0x2e272058),
+	PCMCIA_DEVICE_PROD_ID14("Network Everywhere", "AX88190", 0x820a67b6,  0xab9be5ef),
+	PCMCIA_DEVICE_NULL,
+};
+MODULE_DEVICE_TABLE(pcmcia, axnet_ids);
+
+static struct pcmcia_driver axnet_cs_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "axnet_cs",
+	.probe		= axnet_probe,
+	.remove		= axnet_detach,
+	.id_table       = axnet_ids,
+	.suspend	= axnet_suspend,
+	.resume		= axnet_resume,
+};
+
+static int __init init_axnet_cs(void)
+{
+	return pcmcia_register_driver(&axnet_cs_driver);
+}
+
+static void __exit exit_axnet_cs(void)
+{
+	pcmcia_unregister_driver(&axnet_cs_driver);
+}
+
+module_init(init_axnet_cs);
+module_exit(exit_axnet_cs);
+
+/*====================================================================*/
+
+/* 8390.c: A general NS8390 ethernet driver core for linux. */
+/*
+	Written 1992-94 by Donald Becker.
+  
+	Copyright 1993 United States Government as represented by the
+	Director, National Security Agency.
+
+	This software may be used and distributed according to the terms
+	of the GNU General Public License, incorporated herein by reference.
+
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+  This is the chip-specific code for many 8390-based ethernet adaptors.
+  This is not a complete driver, it must be combined with board-specific
+  code such as ne.c, wd.c, 3c503.c, etc.
+
+  Seeing how at least eight drivers use this code, (not counting the
+  PCMCIA ones either) it is easy to break some card by what seems like
+  a simple innocent change. Please contact me or Donald if you think
+  you have found something that needs changing. -- PG
+
+  Changelog:
+
+  Paul Gortmaker	: remove set_bit lock, other cleanups.
+  Paul Gortmaker	: add ei_get_8390_hdr() so we can pass skb's to 
+			  ei_block_input() for eth_io_copy_and_sum().
+  Paul Gortmaker	: exchange static int ei_pingpong for a #define,
+			  also add better Tx error handling.
+  Paul Gortmaker	: rewrite Rx overrun handling as per NS specs.
+  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 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.
+  Alan Cox		: Spinlocking work, added 'BUG_83C690'
+  Paul Gortmaker	: Separate out Tx timeout code from Tx path.
+
+  Sources:
+  The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
+
+  */
+
+#include <linux/bitops.h>
+#include <asm/irq.h>
+#include <linux/fcntl.h>
+#include <linux/in.h>
+#include <linux/interrupt.h>
+
+#define BUG_83C690
+
+/* These are the operational function interfaces to board-specific
+   routines.
+	void reset_8390(struct net_device *dev)
+		Resets the board associated with DEV, including a hardware reset of
+		the 8390.  This is only called when there is a transmit timeout, and
+		it is always followed by 8390_init().
+	void block_output(struct net_device *dev, int count, const unsigned char *buf,
+					  int start_page)
+		Write the COUNT bytes of BUF to the packet buffer at START_PAGE.  The
+		"page" value uses the 8390's 256-byte pages.
+	void get_8390_hdr(struct net_device *dev, struct e8390_hdr *hdr, int ring_page)
+		Read the 4 byte, page aligned 8390 header. *If* there is a
+		subsequent read, it will be of the rest of the packet.
+	void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+		Read COUNT bytes from the packet buffer into the skb data area. Start 
+		reading from RING_OFFSET, the address as the 8390 sees it.  This will always
+		follow the read of the 8390 header. 
+*/
+#define ei_reset_8390 (ei_local->reset_8390)
+#define ei_block_output (ei_local->block_output)
+#define ei_block_input (ei_local->block_input)
+#define ei_get_8390_hdr (ei_local->get_8390_hdr)
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#ifndef ei_debug
+int ei_debug = 1;
+#endif
+
+/* Index to functions. */
+static void ei_tx_intr(struct net_device *dev);
+static void ei_tx_err(struct net_device *dev);
+static void ei_receive(struct net_device *dev);
+static void ei_rx_overrun(struct net_device *dev);
+
+/* Routines generic to NS8390-based boards. */
+static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
+								int start_page);
+static void do_set_multicast_list(struct net_device *dev);
+
+/*
+ *	SMP and the 8390 setup.
+ *
+ *	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
+ *	before unlocking. Even pure readers must take the lock to protect in 
+ *	page 0.
+ *
+ *	To make life difficult the chip can also be very slow. We therefore can't
+ *	just use spinlocks. For the longer lockups we disable the irq the device
+ *	sits on and hold the lock. We must hold the lock because there is a dual
+ *	processor case other than interrupts (get stats/set multicast list in
+ *	parallel with each other and transmit).
+ *
+ *	Note: in theory we can just disable the irq on the card _but_ there is
+ *	a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs"
+ *	enter lock, take the queued irq. So we waddle instead of flying.
+ *
+ *	Finally by special arrangement for the purpose of being generally 
+ *	annoying the transmit function is called bh atomic. That places
+ *	restrictions on the user context callers as disable_irq won't save
+ *	them.
+ */
+ 
+/**
+ * ax_open - Open/initialize the board.
+ * @dev: network device to initialize
+ *
+ * This routine goes all-out, setting everything
+ * up anew at each open, even though many of these registers should only
+ * need to be set once at boot.
+ */
+static int ax_open(struct net_device *dev)
+{
+	unsigned long flags;
+	struct ei_device *ei_local = netdev_priv(dev);
+
+	/*
+	 *	Grab the page lock so we own the register set, then call
+	 *	the init function.
+	 */
+      
+      	spin_lock_irqsave(&ei_local->page_lock, flags);
+	AX88190_init(dev, 1);
+	/* Set the flag before we drop the lock, That way the IRQ arrives
+	   after its set and we get no silly warnings */
+	netif_start_queue(dev);
+      	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+	ei_local->irqlock = 0;
+	return 0;
+}
+
+#define dev_lock(dev) (((struct ei_device *)netdev_priv(dev))->page_lock)
+
+/**
+ * ax_close - shut down network device
+ * @dev: network device to close
+ *
+ * Opposite of ax_open(). Only used when "ifconfig <devname> down" is done.
+ */
+static int ax_close(struct net_device *dev)
+{
+	unsigned long flags;
+
+	/*
+	 *      Hold the page lock during close
+	 */
+
+	spin_lock_irqsave(&dev_lock(dev), flags);
+	AX88190_init(dev, 0);
+	spin_unlock_irqrestore(&dev_lock(dev), flags);
+	netif_stop_queue(dev);
+	return 0;
+}
+
+/**
+ * axnet_tx_timeout - handle transmit time out condition
+ * @dev: network device which has apparently fallen asleep
+ *
+ * Called by kernel when device never acknowledges a transmit has
+ * completed (or failed) - i.e. never posted a Tx related interrupt.
+ */
+
+static void axnet_tx_timeout(struct net_device *dev)
+{
+	long e8390_base = dev->base_addr;
+	struct ei_device *ei_local = netdev_priv(dev);
+	int txsr, isr, tickssofar = jiffies - dev_trans_start(dev);
+	unsigned long flags;
+
+	dev->stats.tx_errors++;
+
+	spin_lock_irqsave(&ei_local->page_lock, flags);
+	txsr = inb(e8390_base+EN0_TSR);
+	isr = inb(e8390_base+EN0_ISR);
+	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+	netdev_printk(KERN_DEBUG, dev,
+		      "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
+		      (txsr & ENTSR_ABT) ? "excess collisions." :
+		      (isr) ? "lost interrupt?" : "cable problem?",
+		      txsr, isr, tickssofar);
+
+	if (!isr && !dev->stats.tx_packets) 
+	{
+		/* The 8390 probably hasn't gotten on the cable yet. */
+		ei_local->interface_num ^= 1;   /* Try a different xcvr.  */
+	}
+
+	/* Ugly but a reset can be slow, yet must be protected */
+		
+	spin_lock_irqsave(&ei_local->page_lock, flags);
+		
+	/* Try to restart the card.  Perhaps the user has fixed something. */
+	ei_reset_8390(dev);
+	AX88190_init(dev, 1);
+		
+	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+	netif_wake_queue(dev);
+}
+    
+/**
+ * axnet_start_xmit - begin packet transmission
+ * @skb: packet to be sent
+ * @dev: network device to which packet is sent
+ *
+ * Sends a packet to an 8390 network device.
+ */
+ 
+static netdev_tx_t axnet_start_xmit(struct sk_buff *skb,
+					  struct net_device *dev)
+{
+	long e8390_base = dev->base_addr;
+	struct ei_device *ei_local = netdev_priv(dev);
+	int length, send_length, output_page;
+	unsigned long flags;
+	u8 packet[ETH_ZLEN];
+	
+	netif_stop_queue(dev);
+
+	length = skb->len;
+
+	/* Mask interrupts from the ethercard. 
+	   SMP: We have to grab the lock here otherwise the IRQ handler
+	   on another CPU can flip window and race the IRQ mask set. We end
+	   up trashing the mcast filter not disabling irqs if we don't lock */
+	   
+	spin_lock_irqsave(&ei_local->page_lock, flags);
+	outb_p(0x00, e8390_base + EN0_IMR);
+	
+	/*
+	 *	Slow phase with lock held.
+	 */
+	 
+	ei_local->irqlock = 1;
+
+	send_length = max(length, ETH_ZLEN);
+
+	/*
+	 * We have two Tx slots available for use. Find the first free
+	 * slot, and then perform some sanity checks. With two Tx bufs,
+	 * you get very close to transmitting back-to-back packets. With
+	 * only one Tx buf, the transmitter sits idle while you reload the
+	 * card, leaving a substantial gap between each transmitted packet.
+	 */
+
+	if (ei_local->tx1 == 0) 
+	{
+		output_page = ei_local->tx_start_page;
+		ei_local->tx1 = send_length;
+		if (ei_debug  &&  ei_local->tx2 > 0)
+			netdev_printk(KERN_DEBUG, dev,
+				      "idle transmitter tx2=%d, lasttx=%d, txing=%d\n",
+				      ei_local->tx2, ei_local->lasttx,
+				      ei_local->txing);
+	}
+	else if (ei_local->tx2 == 0) 
+	{
+		output_page = ei_local->tx_start_page + TX_PAGES/2;
+		ei_local->tx2 = send_length;
+		if (ei_debug  &&  ei_local->tx1 > 0)
+			netdev_printk(KERN_DEBUG, dev,
+				      "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n",
+				      ei_local->tx1, ei_local->lasttx,
+				      ei_local->txing);
+	}
+	else
+	{	/* We should never get here. */
+		if (ei_debug)
+			netdev_printk(KERN_DEBUG, dev,
+				      "No Tx buffers free! tx1=%d tx2=%d last=%d\n",
+				      ei_local->tx1, ei_local->tx2,
+				      ei_local->lasttx);
+		ei_local->irqlock = 0;
+		netif_stop_queue(dev);
+		outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+		spin_unlock_irqrestore(&ei_local->page_lock, flags);
+		dev->stats.tx_errors++;
+		return NETDEV_TX_BUSY;
+	}
+
+	/*
+	 * Okay, now upload the packet and trigger a send if the transmitter
+	 * isn't already sending. If it is busy, the interrupt handler will
+	 * trigger the send later, upon receiving a Tx done interrupt.
+	 */
+
+	if (length == skb->len)
+		ei_block_output(dev, length, skb->data, output_page);
+	else {
+		memset(packet, 0, ETH_ZLEN);
+		skb_copy_from_linear_data(skb, packet, skb->len);
+		ei_block_output(dev, length, packet, output_page);
+	}
+	
+	if (! ei_local->txing) 
+	{
+		ei_local->txing = 1;
+		NS8390_trigger_send(dev, send_length, output_page);
+		dev->trans_start = jiffies;
+		if (output_page == ei_local->tx_start_page) 
+		{
+			ei_local->tx1 = -1;
+			ei_local->lasttx = -1;
+		}
+		else 
+		{
+			ei_local->tx2 = -1;
+			ei_local->lasttx = -2;
+		}
+	}
+	else ei_local->txqueue++;
+
+	if (ei_local->tx1  &&  ei_local->tx2)
+		netif_stop_queue(dev);
+	else
+		netif_start_queue(dev);
+
+	/* Turn 8390 interrupts back on. */
+	ei_local->irqlock = 0;
+	outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+	
+	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+	dev_kfree_skb (skb);
+	dev->stats.tx_bytes += send_length;
+    
+	return NETDEV_TX_OK;
+}
+
+/**
+ * ax_interrupt - handle the interrupts from an 8390
+ * @irq: interrupt number
+ * @dev_id: a pointer to the net_device
+ *
+ * Handle the ether interface interrupts. We pull packets from
+ * the 8390 via the card specific functions and fire them at the networking
+ * stack. We also handle transmit completions and wake the transmit path if
+ * necessary. We also update the counters and do other housekeeping as
+ * needed.
+ */
+
+static irqreturn_t ax_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	long e8390_base;
+	int interrupts, nr_serviced = 0, i;
+	struct ei_device *ei_local;
+    	int handled = 0;
+	unsigned long flags;
+
+	e8390_base = dev->base_addr;
+	ei_local = netdev_priv(dev);
+
+	/*
+	 *	Protect the irq test too.
+	 */
+	 
+	spin_lock_irqsave(&ei_local->page_lock, flags);
+
+	if (ei_local->irqlock) {
+#if 1 /* This might just be an interrupt for a PCI device sharing this line */
+		const char *msg;
+		/* The "irqlock" check is only for testing. */
+		if (ei_local->irqlock)
+			msg = "Interrupted while interrupts are masked!";
+		else
+			msg = "Reentering the interrupt handler!";
+		netdev_info(dev, "%s, isr=%#2x imr=%#2x\n",
+			    msg,
+			    inb_p(e8390_base + EN0_ISR),
+			    inb_p(e8390_base + EN0_IMR));
+#endif
+		spin_unlock_irqrestore(&ei_local->page_lock, flags);
+		return IRQ_NONE;
+	}
+    
+	if (ei_debug > 3)
+		netdev_printk(KERN_DEBUG, dev, "interrupt(isr=%#2.2x)\n",
+			      inb_p(e8390_base + EN0_ISR));
+
+	outb_p(0x00, e8390_base + EN0_ISR);
+	ei_local->irqlock = 1;
+   
+	/* !!Assumption!! -- we stay in page 0.	 Don't break this. */
+	while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0 &&
+	       ++nr_serviced < MAX_SERVICE)
+	{
+		if (!netif_running(dev) || (interrupts == 0xff)) {
+			if (ei_debug > 1)
+				netdev_warn(dev,
+					    "interrupt from stopped card\n");
+			outb_p(interrupts, e8390_base + EN0_ISR);
+			interrupts = 0;
+			break;
+		}
+		handled = 1;
+
+		/* AX88190 bug fix. */
+		outb_p(interrupts, e8390_base + EN0_ISR);
+		for (i = 0; i < 10; i++) {
+			if (!(inb(e8390_base + EN0_ISR) & interrupts))
+				break;
+			outb_p(0, e8390_base + EN0_ISR);
+			outb_p(interrupts, e8390_base + EN0_ISR);
+		}
+		if (interrupts & ENISR_OVER) 
+			ei_rx_overrun(dev);
+		else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) 
+		{
+			/* Got a good (?) packet. */
+			ei_receive(dev);
+		}
+		/* Push the next to-transmit packet through. */
+		if (interrupts & ENISR_TX)
+			ei_tx_intr(dev);
+		else if (interrupts & ENISR_TX_ERR)
+			ei_tx_err(dev);
+
+		if (interrupts & ENISR_COUNTERS) 
+		{
+			dev->stats.rx_frame_errors += inb_p(e8390_base + EN0_COUNTER0);
+			dev->stats.rx_crc_errors   += inb_p(e8390_base + EN0_COUNTER1);
+			dev->stats.rx_missed_errors+= inb_p(e8390_base + EN0_COUNTER2);
+		}
+	}
+    
+	if (interrupts && ei_debug > 3) 
+	{
+		handled = 1;
+		if (nr_serviced >= MAX_SERVICE) 
+		{
+			/* 0xFF is valid for a card removal */
+			if(interrupts!=0xFF)
+				netdev_warn(dev, "Too much work at interrupt, status %#2.2x\n",
+					    interrupts);
+			outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
+		} else {
+			netdev_warn(dev, "unknown interrupt %#2x\n",
+				    interrupts);
+			outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
+		}
+	}
+
+	/* Turn 8390 interrupts back on. */
+	ei_local->irqlock = 0;
+	outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+
+	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+	return IRQ_RETVAL(handled);
+}
+
+/**
+ * ei_tx_err - handle transmitter error
+ * @dev: network device which threw the exception
+ *
+ * A transmitter error has happened. Most likely excess collisions (which
+ * is a fairly normal condition). If the error is one where the Tx will
+ * have been aborted, we try and send another one right away, instead of
+ * letting the failed packet sit and collect dust in the Tx buffer. This
+ * is a much better solution as it avoids kernel based Tx timeouts, and
+ * an unnecessary card reset.
+ *
+ * Called with lock held.
+ */
+
+static void ei_tx_err(struct net_device *dev)
+{
+	long e8390_base = dev->base_addr;
+	unsigned char txsr = inb_p(e8390_base+EN0_TSR);
+	unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
+
+#ifdef VERBOSE_ERROR_DUMP
+	netdev_printk(KERN_DEBUG, dev,
+		      "transmitter error (%#2x):", txsr);
+	if (txsr & ENTSR_ABT)
+		pr_cont(" excess-collisions");
+	if (txsr & ENTSR_ND)
+		pr_cont(" non-deferral");
+	if (txsr & ENTSR_CRS)
+		pr_cont(" lost-carrier");
+	if (txsr & ENTSR_FU)
+		pr_cont(" FIFO-underrun");
+	if (txsr & ENTSR_CDH)
+		pr_cont(" lost-heartbeat");
+	pr_cont("\n");
+#endif
+
+	if (tx_was_aborted)
+		ei_tx_intr(dev);
+	else 
+	{
+		dev->stats.tx_errors++;
+		if (txsr & ENTSR_CRS) dev->stats.tx_carrier_errors++;
+		if (txsr & ENTSR_CDH) dev->stats.tx_heartbeat_errors++;
+		if (txsr & ENTSR_OWC) dev->stats.tx_window_errors++;
+	}
+}
+
+/**
+ * ei_tx_intr - transmit interrupt handler
+ * @dev: network device for which tx intr is handled
+ *
+ * We have finished a transmit: check for errors and then trigger the next
+ * packet to be sent. Called with lock held.
+ */
+
+static void ei_tx_intr(struct net_device *dev)
+{
+	long e8390_base = dev->base_addr;
+	struct ei_device *ei_local = netdev_priv(dev);
+	int status = inb(e8390_base + EN0_TSR);
+    
+	/*
+	 * There are two Tx buffers, see which one finished, and trigger
+	 * the send of another one if it exists.
+	 */
+	ei_local->txqueue--;
+
+	if (ei_local->tx1 < 0) 
+	{
+		if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
+			netdev_err(dev, "%s: bogus last_tx_buffer %d, tx1=%d\n",
+				   ei_local->name, ei_local->lasttx,
+				   ei_local->tx1);
+		ei_local->tx1 = 0;
+		if (ei_local->tx2 > 0) 
+		{
+			ei_local->txing = 1;
+			NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
+			dev->trans_start = jiffies;
+			ei_local->tx2 = -1,
+			ei_local->lasttx = 2;
+		}
+		else ei_local->lasttx = 20, ei_local->txing = 0;	
+	}
+	else if (ei_local->tx2 < 0) 
+	{
+		if (ei_local->lasttx != 2  &&  ei_local->lasttx != -2)
+			netdev_info(dev, "%s: bogus last_tx_buffer %d, tx2=%d\n",
+				    ei_local->name, ei_local->lasttx,
+				    ei_local->tx2);
+		ei_local->tx2 = 0;
+		if (ei_local->tx1 > 0) 
+		{
+			ei_local->txing = 1;
+			NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
+			dev->trans_start = jiffies;
+			ei_local->tx1 = -1;
+			ei_local->lasttx = 1;
+		}
+		else
+			ei_local->lasttx = 10, ei_local->txing = 0;
+	}
+//	else
+//		netdev_warn(dev, "unexpected TX-done interrupt, lasttx=%d\n",
+//			    ei_local->lasttx);
+
+	/* Minimize Tx latency: update the statistics after we restart TXing. */
+	if (status & ENTSR_COL)
+		dev->stats.collisions++;
+	if (status & ENTSR_PTX)
+		dev->stats.tx_packets++;
+	else 
+	{
+		dev->stats.tx_errors++;
+		if (status & ENTSR_ABT) 
+		{
+			dev->stats.tx_aborted_errors++;
+			dev->stats.collisions += 16;
+		}
+		if (status & ENTSR_CRS) 
+			dev->stats.tx_carrier_errors++;
+		if (status & ENTSR_FU) 
+			dev->stats.tx_fifo_errors++;
+		if (status & ENTSR_CDH)
+			dev->stats.tx_heartbeat_errors++;
+		if (status & ENTSR_OWC)
+			dev->stats.tx_window_errors++;
+	}
+	netif_wake_queue(dev);
+}
+
+/**
+ * ei_receive - receive some packets
+ * @dev: network device with which receive will be run
+ *
+ * We have a good packet(s), get it/them out of the buffers. 
+ * Called with lock held.
+ */
+
+static void ei_receive(struct net_device *dev)
+{
+	long e8390_base = dev->base_addr;
+	struct ei_device *ei_local = netdev_priv(dev);
+	unsigned char rxing_page, this_frame, next_frame;
+	unsigned short current_offset;
+	int rx_pkt_count = 0;
+	struct e8390_pkt_hdr rx_frame;
+    
+	while (++rx_pkt_count < 10) 
+	{
+		int pkt_len, pkt_stat;
+		
+		/* Get the rx page (incoming packet pointer). */
+		rxing_page = inb_p(e8390_base + EN1_CURPAG -1);
+		
+		/* Remove one frame from the ring.  Boundary is always a page behind. */
+		this_frame = inb_p(e8390_base + EN0_BOUNDARY) + 1;
+		if (this_frame >= ei_local->stop_page)
+			this_frame = ei_local->rx_start_page;
+		
+		/* Someday we'll omit the previous, iff we never get this message.
+		   (There is at least one clone claimed to have a problem.)  
+		   
+		   Keep quiet if it looks like a card removal. One problem here
+		   is that some clones crash in roughly the same way.
+		 */
+		if (ei_debug > 0  &&  this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF))
+		    netdev_err(dev, "mismatched read page pointers %2x vs %2x\n",
+			       this_frame, ei_local->current_page);
+		
+		if (this_frame == rxing_page)	/* Read all the frames? */
+			break;				/* Done for now */
+		
+		current_offset = this_frame << 8;
+		ei_get_8390_hdr(dev, &rx_frame, this_frame);
+		
+		pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr);
+		pkt_stat = rx_frame.status;
+		
+		next_frame = this_frame + 1 + ((pkt_len+4)>>8);
+		
+		if (pkt_len < 60  ||  pkt_len > 1518) 
+		{
+			if (ei_debug)
+				netdev_printk(KERN_DEBUG, dev,
+					      "bogus packet size: %d, status=%#2x nxpg=%#2x\n",
+					      rx_frame.count, rx_frame.status,
+					      rx_frame.next);
+			dev->stats.rx_errors++;
+			dev->stats.rx_length_errors++;
+		}
+		 else if ((pkt_stat & 0x0F) == ENRSR_RXOK) 
+		{
+			struct sk_buff *skb;
+			
+			skb = dev_alloc_skb(pkt_len+2);
+			if (skb == NULL) 
+			{
+				if (ei_debug > 1)
+					netdev_printk(KERN_DEBUG, dev,
+						      "Couldn't allocate a sk_buff of size %d\n",
+						      pkt_len);
+				dev->stats.rx_dropped++;
+				break;
+			}
+			else
+			{
+				skb_reserve(skb,2);	/* IP headers on 16 byte boundaries */
+				skb_put(skb, pkt_len);	/* Make room */
+				ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
+				skb->protocol=eth_type_trans(skb,dev);
+				netif_rx(skb);
+				dev->stats.rx_packets++;
+				dev->stats.rx_bytes += pkt_len;
+				if (pkt_stat & ENRSR_PHY)
+					dev->stats.multicast++;
+			}
+		} 
+		else 
+		{
+			if (ei_debug)
+				netdev_printk(KERN_DEBUG, dev,
+					      "bogus packet: status=%#2x nxpg=%#2x size=%d\n",
+					      rx_frame.status, rx_frame.next,
+					      rx_frame.count);
+			dev->stats.rx_errors++;
+			/* NB: The NIC counts CRC, frame and missed errors. */
+			if (pkt_stat & ENRSR_FO)
+				dev->stats.rx_fifo_errors++;
+		}
+		next_frame = rx_frame.next;
+		
+		/* This _should_ never happen: it's here for avoiding bad clones. */
+		if (next_frame >= ei_local->stop_page) {
+			netdev_info(dev, "next frame inconsistency, %#2x\n",
+				    next_frame);
+			next_frame = ei_local->rx_start_page;
+		}
+		ei_local->current_page = next_frame;
+		outb_p(next_frame-1, e8390_base+EN0_BOUNDARY);
+	}
+}
+
+/**
+ * ei_rx_overrun - handle receiver overrun
+ * @dev: network device which threw exception
+ *
+ * We have a receiver overrun: we have to kick the 8390 to get it started
+ * again. Problem is that you have to kick it exactly as NS prescribes in
+ * the updated datasheets, or "the NIC may act in an unpredictable manner."
+ * This includes causing "the NIC to defer indefinitely when it is stopped
+ * on a busy network."  Ugh.
+ * Called with lock held. Don't call this with the interrupts off or your
+ * computer will hate you - it takes 10ms or so. 
+ */
+
+static void ei_rx_overrun(struct net_device *dev)
+{
+	axnet_dev_t *info = PRIV(dev);
+	long e8390_base = dev->base_addr;
+	unsigned char was_txing, must_resend = 0;
+    
+	/*
+	 * Record whether a Tx was in progress and then issue the
+	 * stop command.
+	 */
+	was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
+    
+	if (ei_debug > 1)
+		netdev_printk(KERN_DEBUG, dev, "Receiver overrun\n");
+	dev->stats.rx_over_errors++;
+    
+	/* 
+	 * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total.
+	 * We wait at least 2ms.
+	 */
+
+	mdelay(2);
+
+	/*
+	 * Reset RBCR[01] back to zero as per magic incantation.
+	 */
+	outb_p(0x00, e8390_base+EN0_RCNTLO);
+	outb_p(0x00, e8390_base+EN0_RCNTHI);
+
+	/*
+	 * See if any Tx was interrupted or not. According to NS, this
+	 * step is vital, and skipping it will cause no end of havoc.
+	 */
+
+	if (was_txing)
+	{ 
+		unsigned char tx_completed = inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
+		if (!tx_completed)
+			must_resend = 1;
+	}
+
+	/*
+	 * Have to enter loopback mode and then restart the NIC before
+	 * you are allowed to slurp packets up off the ring.
+	 */
+	outb_p(E8390_TXOFF, e8390_base + EN0_TXCR);
+	outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
+
+	/*
+	 * Clear the Rx ring of all the debris, and ack the interrupt.
+	 */
+	ei_receive(dev);
+
+	/*
+	 * Leave loopback mode, and resend any packet that got stopped.
+	 */
+	outb_p(E8390_TXCONFIG | info->duplex_flag, e8390_base + EN0_TXCR); 
+	if (must_resend)
+    		outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
+}
+
+/*
+ *	Collect the stats. This is called unlocked and from several contexts.
+ */
+ 
+static struct net_device_stats *get_stats(struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+	struct ei_device *ei_local = netdev_priv(dev);
+	unsigned long flags;
+    
+	/* If the card is stopped, just return the present stats. */
+	if (!netif_running(dev))
+		return &dev->stats;
+
+	spin_lock_irqsave(&ei_local->page_lock,flags);
+	/* Read the counter registers, assuming we are in page 0. */
+	dev->stats.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0);
+	dev->stats.rx_crc_errors   += inb_p(ioaddr + EN0_COUNTER1);
+	dev->stats.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2);
+	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+    
+	return &dev->stats;
+}
+
+/*
+ * Form the 64 bit 8390 multicast table from the linked list of addresses
+ * associated with this dev structure.
+ */
+ 
+static inline void make_mc_bits(u8 *bits, struct net_device *dev)
+{
+	struct netdev_hw_addr *ha;
+	u32 crc;
+
+	netdev_for_each_mc_addr(ha, dev) {
+		crc = ether_crc(ETH_ALEN, ha->addr);
+		/* 
+		 * The 8390 uses the 6 most significant bits of the
+		 * CRC to index the multicast table.
+		 */
+		bits[crc>>29] |= (1<<((crc>>26)&7));
+	}
+}
+
+/**
+ * do_set_multicast_list - set/clear multicast filter
+ * @dev: net device for which multicast filter is adjusted
+ *
+ *	Set or clear the multicast filter for this adaptor.
+ *	Must be called with lock held. 
+ */
+ 
+static void do_set_multicast_list(struct net_device *dev)
+{
+	long e8390_base = dev->base_addr;
+	int i;
+	struct ei_device *ei_local = netdev_priv(dev);
+
+	if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
+		memset(ei_local->mcfilter, 0, 8);
+		if (!netdev_mc_empty(dev))
+			make_mc_bits(ei_local->mcfilter, dev);
+	} else {
+		/* set to accept-all */
+		memset(ei_local->mcfilter, 0xFF, 8);
+	}
+
+	outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
+	for(i = 0; i < 8; i++) 
+	{
+		outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
+	}
+	outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
+
+  	if(dev->flags&IFF_PROMISC)
+  		outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR);
+	else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev))
+  		outb_p(E8390_RXCONFIG | 0x48, e8390_base + EN0_RXCR);
+  	else
+  		outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR);
+
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
+}
+
+/*
+ *	Called without lock held. This is invoked from user context and may
+ *	be parallel to just about everything else. Its also fairly quick and
+ *	not called too often. Must protect against both bh and irq users
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_lock(dev), flags);
+	do_set_multicast_list(dev);
+	spin_unlock_irqrestore(&dev_lock(dev), flags);
+}	
+
+/* This page of functions should be 8390 generic */
+/* Follow National Semi's recommendations for initializing the "NIC". */
+
+/**
+ * AX88190_init - initialize 8390 hardware
+ * @dev: network device to initialize
+ * @startp: boolean.  non-zero value to initiate chip processing
+ *
+ *	Must be called with lock held.
+ */
+
+static void AX88190_init(struct net_device *dev, int startp)
+{
+	axnet_dev_t *info = PRIV(dev);
+	long e8390_base = dev->base_addr;
+	struct ei_device *ei_local = netdev_priv(dev);
+	int i;
+	int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48;
+    
+	if(sizeof(struct e8390_pkt_hdr)!=4)
+    		panic("8390.c: header struct mispacked\n");    
+	/* Follow National Semi's recommendations for initing the DP83902. */
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */
+	outb_p(endcfg, e8390_base + EN0_DCFG);	/* 0x48 or 0x49 */
+	/* Clear the remote byte count registers. */
+	outb_p(0x00,  e8390_base + EN0_RCNTLO);
+	outb_p(0x00,  e8390_base + EN0_RCNTHI);
+	/* Set to monitor and loopback mode -- this is vital!. */
+	outb_p(E8390_RXOFF|0x40, e8390_base + EN0_RXCR); /* 0x60 */
+	outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
+	/* Set the transmit page and receive ring. */
+	outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR);
+	ei_local->tx1 = ei_local->tx2 = 0;
+	outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG);
+	outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY);	/* 3c503 says 0x3f,NS0x26*/
+	ei_local->current_page = ei_local->rx_start_page;		/* assert boundary+1 */
+	outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG);
+	/* Clear the pending interrupts and mask. */
+	outb_p(0xFF, e8390_base + EN0_ISR);
+	outb_p(0x00,  e8390_base + EN0_IMR);
+    
+	/* Copy the station address into the DS8390 registers. */
+
+	outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
+	for(i = 0; i < 6; i++) 
+	{
+		outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
+		if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
+			netdev_err(dev, "Hw. address read/write mismap %d\n", i);
+	}
+
+	outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
+
+	netif_start_queue(dev);
+	ei_local->tx1 = ei_local->tx2 = 0;
+	ei_local->txing = 0;
+
+	if (info->flags & IS_AX88790)	/* select Internal PHY */
+		outb(0x10, e8390_base + AXNET_GPIO);
+
+	if (startp) 
+	{
+		outb_p(0xff,  e8390_base + EN0_ISR);
+		outb_p(ENISR_ALL,  e8390_base + EN0_IMR);
+		outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
+		outb_p(E8390_TXCONFIG | info->duplex_flag,
+		       e8390_base + EN0_TXCR); /* xmit on. */
+		/* 3c503 TechMan says rxconfig only after the NIC is started. */
+		outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR); /* rx on, */
+		do_set_multicast_list(dev);	/* (re)load the mcast table */
+	}
+}
+
+/* Trigger a transmit start, assuming the length is valid. 
+   Always called with the page lock held */
+   
+static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
+								int start_page)
+{
+	long e8390_base = dev->base_addr;
+ 	struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev);
+    
+	if (inb_p(e8390_base) & E8390_TRANS) 
+	{
+		netdev_warn(dev, "trigger_send() called with the transmitter busy\n");
+		return;
+	}
+	outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
+	outb_p(length >> 8, e8390_base + EN0_TCNTHI);
+	outb_p(start_page, e8390_base + EN0_TPSR);
+	outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD);
+}
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/e2100.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/e2100.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/e2100.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/e2100.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,490 @@
+/* e2100.c: A Cabletron E2100 series ethernet driver for linux. */
+/*
+	Written 1993-1994 by Donald Becker.
+
+	Copyright 1994 by Donald Becker.
+	Copyright 1993 United States Government as represented by the
+	Director, National Security Agency.  This software may be used and
+	distributed according to the terms of the GNU General Public License,
+	incorporated herein by reference.
+
+	This is a driver for the Cabletron E2100 series ethercards.
+
+	The Author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+	The E2100 series ethercard is a fairly generic shared memory 8390
+	implementation.  The only unusual aspect is the way the shared memory
+	registers are set: first you do an inb() in what is normally the
+	station address region, and the low three bits of next outb() *address*
+	is used	as the write value for that register.  Either someone wasn't
+	too used to dem bit en bites, or they were trying to obfuscate the
+	programming interface.
+
+	There is an additional complication when setting the window on the packet
+	buffer.  You must first do a read into the packet buffer region with the
+	low 8 address bits the address setting the page for the start of the packet
+	buffer window, and then do the above operation.  See mem_on() for details.
+
+	One bug on the chip is that even a hard reset won't disable the memory
+	window, usually resulting in a hung machine if mem_off() isn't called.
+	If this happens, you must power down the machine for about 30 seconds.
+*/
+
+static const char version[] =
+	"e2100.c:v1.01 7/21/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "8390.h"
+
+#define DRV_NAME "e2100"
+
+static int e21_probe_list[] = {0x300, 0x280, 0x380, 0x220, 0};
+
+/* Offsets from the base_addr.
+   Read from the ASIC register, and the low three bits of the next outb()
+   address is used to set the corresponding register. */
+#define E21_NIC_OFFSET  0		/* Offset to the 8390 NIC. */
+#define E21_ASIC		0x10
+#define E21_MEM_ENABLE	0x10
+#define  E21_MEM_ON		0x05	/* Enable memory in 16 bit mode. */
+#define  E21_MEM_ON_8	0x07	/* Enable memory in  8 bit mode. */
+#define E21_MEM_BASE	0x11
+#define E21_IRQ_LOW		0x12	/* The low three bits of the IRQ number. */
+#define E21_IRQ_HIGH	0x14	/* The high IRQ bit and media select ...  */
+#define E21_MEDIA		0x14	/* (alias). */
+#define  E21_ALT_IFPORT 0x02	/* Set to use the other (BNC,AUI) port. */
+#define  E21_BIG_MEM	0x04	/* Use a bigger (64K) buffer (we don't) */
+#define E21_SAPROM		0x10	/* Offset to station address data. */
+#define E21_IO_EXTENT	 0x20
+
+static inline void mem_on(short port, volatile char __iomem *mem_base,
+						  unsigned char start_page )
+{
+	/* This is a little weird: set the shared memory window by doing a
+	   read.  The low address bits specify the starting page. */
+	readb(mem_base+start_page);
+	inb(port + E21_MEM_ENABLE);
+	outb(E21_MEM_ON, port + E21_MEM_ENABLE + E21_MEM_ON);
+}
+
+static inline void mem_off(short port)
+{
+	inb(port + E21_MEM_ENABLE);
+	outb(0x00, port + E21_MEM_ENABLE);
+}
+
+/* In other drivers I put the TX pages first, but the E2100 window circuitry
+   is designed to have a 4K Tx region last. The windowing circuitry wraps the
+   window at 0x2fff->0x0000 so that the packets at e.g. 0x2f00 in the RX ring
+   appear contiguously in the window. */
+#define E21_RX_START_PG		0x00	/* First page of RX buffer */
+#define E21_RX_STOP_PG		0x30	/* Last page +1 of RX ring */
+#define E21_BIG_RX_STOP_PG	0xF0	/* Last page +1 of RX ring */
+#define E21_TX_START_PG		E21_RX_STOP_PG	/* First page of TX buffer */
+
+static int e21_probe1(struct net_device *dev, int ioaddr);
+
+static int e21_open(struct net_device *dev);
+static void e21_reset_8390(struct net_device *dev);
+static void e21_block_input(struct net_device *dev, int count,
+						   struct sk_buff *skb, int ring_offset);
+static void e21_block_output(struct net_device *dev, int count,
+							 const unsigned char *buf, int start_page);
+static void e21_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+							int ring_page);
+static int e21_open(struct net_device *dev);
+static int e21_close(struct net_device *dev);
+
+
+/*  Probe for the E2100 series ethercards.  These cards have an 8390 at the
+	base address and the station address at both offset 0x10 and 0x18.  I read
+	the station address from offset 0x18 to avoid the dataport of NE2000
+	ethercards, and look for Ctron's unique ID (first three octets of the
+	station address).
+ */
+
+static int  __init do_e2100_probe(struct net_device *dev)
+{
+	int *port;
+	int base_addr = dev->base_addr;
+	int irq = dev->irq;
+
+	if (base_addr > 0x1ff)		/* Check a single specified location. */
+		return e21_probe1(dev, base_addr);
+	else if (base_addr != 0)	/* Don't probe at all. */
+		return -ENXIO;
+
+	for (port = e21_probe_list; *port; port++) {
+		dev->irq = irq;
+		if (e21_probe1(dev, *port) == 0)
+			return 0;
+	}
+
+	return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init e2100_probe(int unit)
+{
+	struct net_device *dev = alloc_ei_netdev();
+	int err;
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+
+	err = do_e2100_probe(dev);
+	if (err)
+		goto out;
+	return dev;
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+#endif
+
+static const struct net_device_ops e21_netdev_ops = {
+	.ndo_open		= e21_open,
+	.ndo_stop		= e21_close,
+
+	.ndo_start_xmit		= ei_start_xmit,
+	.ndo_tx_timeout		= ei_tx_timeout,
+	.ndo_get_stats		= ei_get_stats,
+	.ndo_set_rx_mode	= 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,
+#endif
+};
+
+static int __init e21_probe1(struct net_device *dev, int ioaddr)
+{
+	int i, status, retval;
+	unsigned char *station_addr = dev->dev_addr;
+	static unsigned version_printed;
+
+	if (!request_region(ioaddr, E21_IO_EXTENT, DRV_NAME))
+		return -EBUSY;
+
+	/* First check the station address for the Ctron prefix. */
+	if (inb(ioaddr + E21_SAPROM + 0) != 0x00 ||
+	    inb(ioaddr + E21_SAPROM + 1) != 0x00 ||
+	    inb(ioaddr + E21_SAPROM + 2) != 0x1d) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	/* Verify by making certain that there is a 8390 at there. */
+	outb(E8390_NODMA + E8390_STOP, ioaddr);
+	udelay(1);	/* we want to delay one I/O cycle - which is 2MHz */
+	status = inb(ioaddr);
+	if (status != 0x21 && status != 0x23) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	/* Read the station address PROM.  */
+	for (i = 0; i < 6; i++)
+		station_addr[i] = inb(ioaddr + E21_SAPROM + i);
+
+	inb(ioaddr + E21_MEDIA); 		/* Point to media selection. */
+	outb(0, ioaddr + E21_ASIC); 	/* and disable the secondary interface. */
+
+	if (ei_debug  &&  version_printed++ == 0)
+		printk(version);
+
+	for (i = 0; i < 6; i++)
+		printk(" %02X", station_addr[i]);
+
+	if (dev->irq < 2) {
+		static const int irqlist[] = {15, 11, 10, 12, 5, 9, 3, 4};
+		for (i = 0; i < ARRAY_SIZE(irqlist); i++)
+			if (request_irq (irqlist[i], NULL, 0, "bogus", NULL) != -EBUSY) {
+				dev->irq = irqlist[i];
+				break;
+			}
+		if (i >= ARRAY_SIZE(irqlist)) {
+			printk(" unable to get IRQ %d.\n", dev->irq);
+			retval = -EAGAIN;
+			goto out;
+		}
+	} else if (dev->irq == 2)	/* Fixup luser bogosity: IRQ2 is really IRQ9 */
+		dev->irq = 9;
+
+	/* The 8390 is at the base address. */
+	dev->base_addr = ioaddr;
+
+	ei_status.name = "E2100";
+	ei_status.word16 = 1;
+	ei_status.tx_start_page = E21_TX_START_PG;
+	ei_status.rx_start_page = E21_RX_START_PG;
+	ei_status.stop_page = E21_RX_STOP_PG;
+	ei_status.saved_irq = dev->irq;
+
+	/* Check the media port used.  The port can be passed in on the
+	   low mem_end bits. */
+	if (dev->mem_end & 15)
+		dev->if_port = dev->mem_end & 7;
+	else {
+		dev->if_port = 0;
+		inb(ioaddr + E21_MEDIA); 	/* Turn automatic media detection on. */
+		for(i = 0; i < 6; i++)
+			if (station_addr[i] != inb(ioaddr + E21_SAPROM + 8 + i)) {
+				dev->if_port = 1;
+				break;
+			}
+	}
+
+	/* Never map in the E21 shared memory unless you are actively using it.
+	   Also, the shared memory has effective only one setting -- spread all
+	   over the 128K region! */
+	if (dev->mem_start == 0)
+		dev->mem_start = 0xd0000;
+
+	ei_status.mem = ioremap(dev->mem_start, 2*1024);
+	if (!ei_status.mem) {
+		printk("unable to remap memory\n");
+		retval = -EAGAIN;
+		goto out;
+	}
+
+#ifdef notdef
+	/* These values are unused.  The E2100 has a 2K window into the packet
+	   buffer.  The window can be set to start on any page boundary. */
+	ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
+	dev->mem_end = ei_status.rmem_end = dev->mem_start + 2*1024;
+#endif
+
+	printk(", IRQ %d, %s media, memory @ %#lx.\n", dev->irq,
+		   dev->if_port ? "secondary" : "primary", dev->mem_start);
+
+	ei_status.reset_8390 = &e21_reset_8390;
+	ei_status.block_input = &e21_block_input;
+	ei_status.block_output = &e21_block_output;
+	ei_status.get_8390_hdr = &e21_get_8390_hdr;
+
+	dev->netdev_ops = &e21_netdev_ops;
+	NS8390_init(dev, 0);
+
+	retval = register_netdev(dev);
+	if (retval)
+		goto out;
+	return 0;
+out:
+	release_region(ioaddr, E21_IO_EXTENT);
+	return retval;
+}
+
+static int
+e21_open(struct net_device *dev)
+{
+	short ioaddr = dev->base_addr;
+	int retval;
+
+	if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev)))
+		return retval;
+
+	/* Set the interrupt line and memory base on the hardware. */
+	inb(ioaddr + E21_IRQ_LOW);
+	outb(0, ioaddr + E21_ASIC + (dev->irq & 7));
+	inb(ioaddr + E21_IRQ_HIGH); 			/* High IRQ bit, and if_port. */
+	outb(0, ioaddr + E21_ASIC + (dev->irq > 7 ? 1:0)
+		   + (dev->if_port ? E21_ALT_IFPORT : 0));
+	inb(ioaddr + E21_MEM_BASE);
+	outb(0, ioaddr + E21_ASIC + ((dev->mem_start >> 17) & 7));
+
+	ei_open(dev);
+	return 0;
+}
+
+static void
+e21_reset_8390(struct net_device *dev)
+{
+	short ioaddr = dev->base_addr;
+
+	outb(0x01, ioaddr);
+	if (ei_debug > 1) printk("resetting the E2180x3 t=%ld...", jiffies);
+	ei_status.txing = 0;
+
+	/* Set up the ASIC registers, just in case something changed them. */
+
+	if (ei_debug > 1) printk("reset done\n");
+}
+
+/* Grab the 8390 specific header. We put the 2k window so the header page
+   appears at the start of the shared memory. */
+
+static void
+e21_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+
+	short ioaddr = dev->base_addr;
+	char __iomem *shared_mem = ei_status.mem;
+
+	mem_on(ioaddr, shared_mem, ring_page);
+
+#ifdef notdef
+	/* Officially this is what we are doing, but the readl() is faster */
+	memcpy_fromio(hdr, shared_mem, sizeof(struct e8390_pkt_hdr));
+#else
+	((unsigned int*)hdr)[0] = readl(shared_mem);
+#endif
+
+	/* Turn off memory access: we would need to reprogram the window anyway. */
+	mem_off(ioaddr);
+
+}
+
+/*  Block input and output are easy on shared memory ethercards.
+	The E21xx makes block_input() especially easy by wrapping the top
+	ring buffer to the bottom automatically. */
+static void
+e21_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+	short ioaddr = dev->base_addr;
+	char __iomem *shared_mem = ei_status.mem;
+
+	mem_on(ioaddr, shared_mem, (ring_offset>>8));
+
+	memcpy_fromio(skb->data, ei_status.mem + (ring_offset & 0xff), count);
+
+	mem_off(ioaddr);
+}
+
+static void
+e21_block_output(struct net_device *dev, int count, const unsigned char *buf,
+				 int start_page)
+{
+	short ioaddr = dev->base_addr;
+	volatile char __iomem *shared_mem = ei_status.mem;
+
+	/* Set the shared memory window start by doing a read, with the low address
+	   bits specifying the starting page. */
+	readb(shared_mem + start_page);
+	mem_on(ioaddr, shared_mem, start_page);
+
+	memcpy_toio(shared_mem, buf, count);
+	mem_off(ioaddr);
+}
+
+static int
+e21_close(struct net_device *dev)
+{
+	short ioaddr = dev->base_addr;
+
+	if (ei_debug > 1)
+		printk("%s: Shutting down ethercard.\n", dev->name);
+
+	free_irq(dev->irq, dev);
+	dev->irq = ei_status.saved_irq;
+
+	/* Shut off the interrupt line and secondary interface. */
+	inb(ioaddr + E21_IRQ_LOW);
+	outb(0, ioaddr + E21_ASIC);
+	inb(ioaddr + E21_IRQ_HIGH); 			/* High IRQ bit, and if_port. */
+	outb(0, ioaddr + E21_ASIC);
+
+	ei_close(dev);
+
+	/* Double-check that the memory has been turned off, because really
+	   really bad things happen if it isn't. */
+	mem_off(ioaddr);
+
+	return 0;
+}
+
+
+#ifdef MODULE
+#define MAX_E21_CARDS	4	/* Max number of E21 cards per module */
+static struct net_device *dev_e21[MAX_E21_CARDS];
+static int io[MAX_E21_CARDS];
+static int irq[MAX_E21_CARDS];
+static int mem[MAX_E21_CARDS];
+static int xcvr[MAX_E21_CARDS];		/* choose int. or ext. xcvr */
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(mem, int, NULL, 0);
+module_param_array(xcvr, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s)");
+MODULE_PARM_DESC(mem, " memory base address(es)");
+MODULE_PARM_DESC(xcvr, "transceiver(s) (0=internal, 1=external)");
+MODULE_DESCRIPTION("Cabletron E2100 ISA ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* This is set up so that only a single autoprobe takes place per call.
+ISA device autoprobes on a running machine are not recommended. */
+
+int __init init_module(void)
+{
+	struct net_device *dev;
+	int this_dev, found = 0;
+
+	for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
+		if (io[this_dev] == 0)  {
+			if (this_dev != 0) break; /* only autoprobe 1st one */
+			printk(KERN_NOTICE "e2100.c: Presently autoprobing (not recommended) for a single card.\n");
+		}
+		dev = alloc_ei_netdev();
+		if (!dev)
+			break;
+		dev->irq = irq[this_dev];
+		dev->base_addr = io[this_dev];
+		dev->mem_start = mem[this_dev];
+		dev->mem_end = xcvr[this_dev];	/* low 4bits = xcvr sel. */
+		if (do_e2100_probe(dev) == 0) {
+			dev_e21[found++] = dev;
+			continue;
+		}
+		free_netdev(dev);
+		printk(KERN_WARNING "e2100.c: No E2100 card found (i/o = 0x%x).\n", io[this_dev]);
+		break;
+	}
+	if (found)
+		return 0;
+	return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+	/* NB: e21_close() handles free_irq */
+	iounmap(ei_status.mem);
+	release_region(dev->base_addr, E21_IO_EXTENT);
+}
+
+void __exit
+cleanup_module(void)
+{
+	int this_dev;
+
+	for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
+		struct net_device *dev = dev_e21[this_dev];
+		if (dev) {
+			unregister_netdev(dev);
+			cleanup_card(dev);
+			free_netdev(dev);
+		}
+	}
+}
+#endif /* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/es3210.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/es3210.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/es3210.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/es3210.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,446 @@
+/*
+	es3210.c
+
+	Linux driver for Racal-Interlan ES3210 EISA Network Adapter
+
+	Copyright (C) 1996, Paul Gortmaker.
+
+	This software may be used and distributed according to the terms
+	of the GNU General Public License, incorporated herein by reference.
+
+	Information and Code Sources:
+
+	1) The existing myriad of Linux 8390 drivers written by Donald Becker.
+
+	2) Once again Russ Nelson's asm packet driver provided additional info.
+
+	3) Info for getting IRQ and sh-mem gleaned from the EISA cfg files.
+	   Too bad it doesn't work -- see below.
+
+	The ES3210 is an EISA shared memory NS8390 implementation. Note
+	that all memory copies to/from the board must be 32bit transfers.
+	Which rules out using eth_io_copy_and_sum() in this driver.
+
+	Apparently there are two slightly different revisions of the
+	card, since there are two distinct EISA cfg files (!rii0101.cfg
+	and !rii0102.cfg) One has media select in the cfg file and the
+	other doesn't. Hopefully this will work with either.
+
+	That is about all I can tell you about it, having never actually
+	even seen one of these cards. :)  Try http://www.interlan.com
+	if you want more info.
+
+	Thanks go to Mark Salazar for testing v0.02 of this driver.
+
+	Bugs, to-fix, etc:
+
+	1) The EISA cfg ports that are *supposed* to have the IRQ and shared
+	   mem values just read 0xff all the time. Hrrmpf. Apparently the
+	   same happens with the packet driver as the code for reading
+	   these registers is disabled there. In the meantime, boot with:
+	   ether=<IRQ>,0,0x<shared_mem_addr>,eth0 to override the IRQ and
+	   shared memory detection. (The i/o port detection is okay.)
+
+	2) Module support currently untested. Probably works though.
+
+*/
+
+static const char version[] =
+	"es3210.c: Driver revision v0.03, 14/09/96\n";
+
+#include <linux/module.h>
+#include <linux/eisa.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "8390.h"
+
+static int es_probe1(struct net_device *dev, int ioaddr);
+
+static void es_reset_8390(struct net_device *dev);
+
+static void es_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
+static void es_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset);
+static void es_block_output(struct net_device *dev, int count, const unsigned char *buf, int start_page);
+
+#define ES_START_PG	0x00    /* First page of TX buffer		*/
+#define ES_STOP_PG	0x40    /* Last page +1 of RX ring		*/
+
+#define ES_IO_EXTENT	0x37	/* The cfg file says 0xc90 -> 0xcc7	*/
+#define ES_ID_PORT	0xc80	/* Same for all EISA cards 		*/
+#define ES_SA_PROM	0xc90	/* Start of e'net addr.			*/
+#define ES_RESET_PORT	0xc84	/* From the packet driver source	*/
+#define ES_NIC_OFFSET	0xca0	/* Hello, the 8390 is *here*		*/
+
+#define ES_ADDR0	0x02	/* 3 byte vendor prefix			*/
+#define ES_ADDR1	0x07
+#define ES_ADDR2	0x01
+
+/*
+ * Two card revisions. EISA ID's are always rev. minor, rev. major,, and
+ * then the three vendor letters stored in 5 bits each, with an "a" = 1.
+ * For eg: "rii" = 10010 01001 01001 = 0x4929, which is how the EISA
+ * config utility determines automagically what config file(s) to use.
+ */
+#define ES_EISA_ID1	0x01012949	/* !rii0101.cfg 		*/
+#define ES_EISA_ID2	0x02012949	/* !rii0102.cfg 		*/
+
+#define ES_CFG1		0xcc0	/* IOPORT(1) --> IOPORT(6) in cfg file	*/
+#define ES_CFG2		0xcc1
+#define ES_CFG3		0xcc2
+#define ES_CFG4		0xcc3
+#define ES_CFG5		0xcc4
+#define ES_CFG6		0xc84	/* NB: 0xc84 is also "reset" port.	*/
+
+/*
+ *	You can OR any of the following bits together and assign it
+ *	to ES_DEBUG to get verbose driver info during operation.
+ *	Some of these don't do anything yet.
+ */
+
+#define ES_D_PROBE	0x01
+#define ES_D_RX_PKT	0x02
+#define ES_D_TX_PKT	0x04
+#define ED_D_IRQ	0x08
+
+#define ES_DEBUG	0
+
+static unsigned char lo_irq_map[] __initdata = {3, 4, 5, 6, 7, 9, 10};
+static unsigned char hi_irq_map[] __initdata = {11, 12, 0, 14, 0, 0, 0, 15};
+
+/*
+ *	Probe for the card. The best way is to read the EISA ID if it
+ *	is known. Then we check the prefix of the station address
+ *	PROM for a match against the Racal-Interlan assigned value.
+ */
+
+static int __init do_es_probe(struct net_device *dev)
+{
+	unsigned short ioaddr = dev->base_addr;
+	int irq = dev->irq;
+	int mem_start = dev->mem_start;
+
+	if (ioaddr > 0x1ff)		/* Check a single specified location. */
+		return es_probe1(dev, ioaddr);
+	else if (ioaddr > 0)		/* Don't probe at all. */
+		return -ENXIO;
+
+	if (!EISA_bus) {
+#if ES_DEBUG & ES_D_PROBE
+		printk("es3210.c: Not EISA bus. Not probing high ports.\n");
+#endif
+		return -ENXIO;
+	}
+
+	/* EISA spec allows for up to 16 slots, but 8 is typical. */
+	for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
+		if (es_probe1(dev, ioaddr) == 0)
+			return 0;
+		dev->irq = irq;
+		dev->mem_start = mem_start;
+	}
+
+	return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init es_probe(int unit)
+{
+	struct net_device *dev = alloc_ei_netdev();
+	int err;
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+
+	err = do_es_probe(dev);
+	if (err)
+		goto out;
+	return dev;
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+#endif
+
+static int __init es_probe1(struct net_device *dev, int ioaddr)
+{
+	int i, retval;
+	unsigned long eisa_id;
+
+	if (!request_region(ioaddr + ES_SA_PROM, ES_IO_EXTENT, "es3210"))
+		return -ENODEV;
+
+#if ES_DEBUG & ES_D_PROBE
+	printk("es3210.c: probe at %#x, ID %#8x\n", ioaddr, inl(ioaddr + ES_ID_PORT));
+	printk("es3210.c: config regs: %#x %#x %#x %#x %#x %#x\n",
+		inb(ioaddr + ES_CFG1), inb(ioaddr + ES_CFG2), inb(ioaddr + ES_CFG3),
+		inb(ioaddr + ES_CFG4), inb(ioaddr + ES_CFG5), inb(ioaddr + ES_CFG6));
+#endif
+
+/*	Check the EISA ID of the card. */
+	eisa_id = inl(ioaddr + ES_ID_PORT);
+	if ((eisa_id != ES_EISA_ID1) && (eisa_id != ES_EISA_ID2)) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	for (i = 0; i < ETHER_ADDR_LEN ; i++)
+		dev->dev_addr[i] = inb(ioaddr + ES_SA_PROM + i);
+
+/*	Check the Racal vendor ID as well. */
+	if (dev->dev_addr[0] != ES_ADDR0 ||
+	    dev->dev_addr[1] != ES_ADDR1 ||
+	    dev->dev_addr[2] != ES_ADDR2) {
+		printk("es3210.c: card not found %pM (invalid_prefix).\n",
+		       dev->dev_addr);
+		retval = -ENODEV;
+		goto out;
+	}
+
+	printk("es3210.c: ES3210 rev. %ld at %#x, node %pM",
+	       eisa_id>>24, ioaddr, dev->dev_addr);
+
+	/* Snarf the interrupt now. */
+	if (dev->irq == 0) {
+		unsigned char hi_irq = inb(ioaddr + ES_CFG2) & 0x07;
+		unsigned char lo_irq = inb(ioaddr + ES_CFG1) & 0xfe;
+
+		if (hi_irq != 0) {
+			dev->irq = hi_irq_map[hi_irq - 1];
+		} else {
+			int i = 0;
+			while (lo_irq > (1<<i)) i++;
+			dev->irq = lo_irq_map[i];
+		}
+		printk(" using IRQ %d", dev->irq);
+#if ES_DEBUG & ES_D_PROBE
+		printk("es3210.c: hi_irq %#x, lo_irq %#x, dev->irq = %d\n",
+					hi_irq, lo_irq, dev->irq);
+#endif
+	} else {
+		if (dev->irq == 2)
+			dev->irq = 9;			/* Doh! */
+		printk(" assigning IRQ %d", dev->irq);
+	}
+
+	if (request_irq(dev->irq, ei_interrupt, 0, "es3210", dev)) {
+		printk (" unable to get IRQ %d.\n", dev->irq);
+		retval = -EAGAIN;
+		goto out;
+	}
+
+	if (dev->mem_start == 0) {
+		unsigned char mem_enabled = inb(ioaddr + ES_CFG2) & 0xc0;
+		unsigned char mem_bits = inb(ioaddr + ES_CFG3) & 0x07;
+
+		if (mem_enabled != 0x80) {
+			printk(" shared mem disabled - giving up\n");
+			retval = -ENXIO;
+			goto out1;
+		}
+		dev->mem_start = 0xC0000 + mem_bits*0x4000;
+		printk(" using ");
+	} else {
+		printk(" assigning ");
+	}
+
+	ei_status.mem = ioremap(dev->mem_start, (ES_STOP_PG - ES_START_PG)*256);
+	if (!ei_status.mem) {
+		printk("ioremap failed - giving up\n");
+		retval = -ENXIO;
+		goto out1;
+	}
+
+	dev->mem_end = dev->mem_start + (ES_STOP_PG - ES_START_PG)*256;
+
+	printk("mem %#lx-%#lx\n", dev->mem_start, dev->mem_end-1);
+
+#if ES_DEBUG & ES_D_PROBE
+	if (inb(ioaddr + ES_CFG5))
+		printk("es3210: Warning - DMA channel enabled, but not used here.\n");
+#endif
+	/* Note, point at the 8390, and not the card... */
+	dev->base_addr = ioaddr + ES_NIC_OFFSET;
+
+	ei_status.name = "ES3210";
+	ei_status.tx_start_page = ES_START_PG;
+	ei_status.rx_start_page = ES_START_PG + TX_PAGES;
+	ei_status.stop_page = ES_STOP_PG;
+	ei_status.word16 = 1;
+
+	if (ei_debug > 0)
+		printk(version);
+
+	ei_status.reset_8390 = &es_reset_8390;
+	ei_status.block_input = &es_block_input;
+	ei_status.block_output = &es_block_output;
+	ei_status.get_8390_hdr = &es_get_8390_hdr;
+
+	dev->netdev_ops = &ei_netdev_ops;
+	NS8390_init(dev, 0);
+
+	retval = register_netdev(dev);
+	if (retval)
+		goto out1;
+	return 0;
+out1:
+	free_irq(dev->irq, dev);
+out:
+	release_region(ioaddr + ES_SA_PROM, ES_IO_EXTENT);
+	return retval;
+}
+
+/*
+ *	Reset as per the packet driver method. Judging by the EISA cfg
+ *	file, this just toggles the "Board Enable" bits (bit 2 and 0).
+ */
+
+static void es_reset_8390(struct net_device *dev)
+{
+	unsigned short ioaddr = dev->base_addr;
+	unsigned long end;
+
+	outb(0x04, ioaddr + ES_RESET_PORT);
+	if (ei_debug > 1) printk("%s: resetting the ES3210...", dev->name);
+
+	end = jiffies + 2*HZ/100;
+        while ((signed)(end - jiffies) > 0) continue;
+
+	ei_status.txing = 0;
+	outb(0x01, ioaddr + ES_RESET_PORT);
+	if (ei_debug > 1) printk("reset done\n");
+}
+
+/*
+ *	Note: In the following three functions is the implicit assumption
+ *	that the associated memcpy will only use "rep; movsl" as long as
+ *	we keep the counts as some multiple of doublewords. This is a
+ *	requirement of the hardware, and also prevents us from using
+ *	eth_io_copy_and_sum() since we can't guarantee it will limit
+ *	itself to doubleword access.
+ */
+
+/*
+ *	Grab the 8390 specific header. Similar to the block_input routine, but
+ *	we don't need to be concerned with ring wrap as the header will be at
+ *	the start of a page, so we optimize accordingly. (A single doubleword.)
+ */
+
+static void
+es_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	void __iomem *hdr_start = ei_status.mem + ((ring_page - ES_START_PG)<<8);
+	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	hdr->count = (hdr->count + 3) & ~3;     /* Round up allocation. */
+}
+
+/*
+ *	Block input and output are easy on shared memory ethercards, the only
+ *	complication is when the ring buffer wraps. The count will already
+ *	be rounded up to a doubleword value via es_get_8390_hdr() above.
+ */
+
+static void es_block_input(struct net_device *dev, int count, struct sk_buff *skb,
+						  int ring_offset)
+{
+	void __iomem *xfer_start = ei_status.mem + ring_offset - ES_START_PG*256;
+
+	if (ring_offset + count > ES_STOP_PG*256) {
+		/* Packet wraps over end of ring buffer. */
+		int semi_count = ES_STOP_PG*256 - ring_offset;
+		memcpy_fromio(skb->data, xfer_start, semi_count);
+		count -= semi_count;
+		memcpy_fromio(skb->data + semi_count, ei_status.mem, count);
+	} else {
+		/* Packet is in one chunk. */
+		memcpy_fromio(skb->data, xfer_start, count);
+	}
+}
+
+static void es_block_output(struct net_device *dev, int count,
+				const unsigned char *buf, int start_page)
+{
+	void __iomem *shmem = ei_status.mem + ((start_page - ES_START_PG)<<8);
+
+	count = (count + 3) & ~3;     /* Round up to doubleword */
+	memcpy_toio(shmem, buf, count);
+}
+
+#ifdef MODULE
+#define MAX_ES_CARDS	4	/* Max number of ES3210 cards per module */
+#define NAMELEN		8	/* # of chars for storing dev->name */
+static struct net_device *dev_es3210[MAX_ES_CARDS];
+static int io[MAX_ES_CARDS];
+static int irq[MAX_ES_CARDS];
+static int mem[MAX_ES_CARDS];
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(mem, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s)");
+MODULE_PARM_DESC(mem, "memory base address(es)");
+MODULE_DESCRIPTION("Racal-Interlan ES3210 EISA ethernet driver");
+MODULE_LICENSE("GPL");
+
+int __init init_module(void)
+{
+	struct net_device *dev;
+	int this_dev, found = 0;
+
+	for (this_dev = 0; this_dev < MAX_ES_CARDS; this_dev++) {
+		if (io[this_dev] == 0 && this_dev != 0)
+			break;
+		dev = alloc_ei_netdev();
+		if (!dev)
+			break;
+		dev->irq = irq[this_dev];
+		dev->base_addr = io[this_dev];
+		dev->mem_start = mem[this_dev];
+		if (do_es_probe(dev) == 0) {
+			dev_es3210[found++] = dev;
+			continue;
+		}
+		free_netdev(dev);
+		printk(KERN_WARNING "es3210.c: No es3210 card found (i/o = 0x%x).\n", io[this_dev]);
+		break;
+	}
+	if (found)
+		return 0;
+	return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+	free_irq(dev->irq, dev);
+	release_region(dev->base_addr, ES_IO_EXTENT);
+	iounmap(ei_status.mem);
+}
+
+void __exit
+cleanup_module(void)
+{
+	int this_dev;
+
+	for (this_dev = 0; this_dev < MAX_ES_CARDS; this_dev++) {
+		struct net_device *dev = dev_es3210[this_dev];
+		if (dev) {
+			unregister_netdev(dev);
+			cleanup_card(dev);
+			free_netdev(dev);
+		}
+	}
+}
+#endif /* MODULE */
+
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/etherh.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/etherh.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/etherh.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/etherh.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,866 @@
+/*
+ *  linux/drivers/acorn/net/etherh.c
+ *
+ *  Copyright (C) 2000-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.
+ *
+ * NS8390 I-cubed EtherH and ANT EtherM specific driver
+ * Thanks to I-Cubed for information on their cards.
+ * EtherM conversion (C) 1999 Chris Kemp and Tim Watterton
+ * EtherM integration (C) 2000 Aleph One Ltd (Tak-Shing Chan)
+ * EtherM integration re-engineered by Russell King.
+ *
+ * Changelog:
+ *  08-12-1996	RMK	1.00	Created
+ *		RMK	1.03	Added support for EtherLan500 cards
+ *  23-11-1997	RMK	1.04	Added media autodetection
+ *  16-04-1998	RMK	1.05	Improved media autodetection
+ *  10-02-2000	RMK	1.06	Updated for 2.3.43
+ *  13-05-2000	RMK	1.07	Updated for 2.3.99-pre8
+ *  12-10-1999  CK/TEW		EtherM driver first release
+ *  21-12-2000	TTC		EtherH/EtherM integration
+ *  25-12-2000	RMK	1.08	Clean integration of EtherM into this driver.
+ *  03-01-2002	RMK	1.09	Always enable IRQs if we're in the nic slot.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/jiffies.h>
+
+#include <asm/system.h>
+#include <asm/ecard.h>
+#include <asm/io.h>
+
+#define EI_SHIFT(x)	(ei_local->reg_offset[x])
+
+#define ei_inb(_p)	 readb((void __iomem *)_p)
+#define ei_outb(_v,_p)	 writeb(_v,(void __iomem *)_p)
+#define ei_inb_p(_p)	 readb((void __iomem *)_p)
+#define ei_outb_p(_v,_p) writeb(_v,(void __iomem *)_p)
+
+#define NET_DEBUG  0
+#define DEBUG_INIT 2
+
+#define DRV_NAME	"etherh"
+#define DRV_VERSION	"1.11"
+
+static char version[] __initdata =
+	"EtherH/EtherM Driver (c) 2002-2004 Russell King " DRV_VERSION "\n";
+
+#include "lib8390.c"
+
+static unsigned int net_debug = NET_DEBUG;
+
+struct etherh_priv {
+	void __iomem	*ioc_fast;
+	void __iomem	*memc;
+	void __iomem	*dma_base;
+	unsigned int	id;
+	void __iomem	*ctrl_port;
+	unsigned char	ctrl;
+	u32		supported;
+};
+
+struct etherh_data {
+	unsigned long	ns8390_offset;
+	unsigned long	dataport_offset;
+	unsigned long	ctrlport_offset;
+	int		ctrl_ioc;
+	const char	name[16];
+	u32		supported;
+	unsigned char	tx_start_page;
+	unsigned char	stop_page;
+};
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("EtherH/EtherM driver");
+MODULE_LICENSE("GPL");
+
+#define ETHERH500_DATAPORT	0x800	/* MEMC */
+#define ETHERH500_NS8390	0x000	/* MEMC */
+#define ETHERH500_CTRLPORT	0x800	/* IOC  */
+
+#define ETHERH600_DATAPORT	0x040	/* MEMC */
+#define ETHERH600_NS8390	0x800	/* MEMC */
+#define ETHERH600_CTRLPORT	0x200	/* MEMC */
+
+#define ETHERH_CP_IE		1
+#define ETHERH_CP_IF		2
+#define ETHERH_CP_HEARTBEAT	2
+
+#define ETHERH_TX_START_PAGE	1
+#define ETHERH_STOP_PAGE	127
+
+/*
+ * These came from CK/TEW
+ */
+#define ETHERM_DATAPORT		0x200	/* MEMC */
+#define ETHERM_NS8390		0x800	/* MEMC */
+#define ETHERM_CTRLPORT		0x23c	/* MEMC */
+
+#define ETHERM_TX_START_PAGE	64
+#define ETHERM_STOP_PAGE	127
+
+/* ------------------------------------------------------------------------ */
+
+#define etherh_priv(dev) \
+ ((struct etherh_priv *)(((char *)netdev_priv(dev)) + sizeof(struct ei_device)))
+
+static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned char mask)
+{
+	unsigned char ctrl = eh->ctrl | mask;
+	eh->ctrl = ctrl;
+	writeb(ctrl, eh->ctrl_port);
+}
+
+static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned char mask)
+{
+	unsigned char ctrl = eh->ctrl & ~mask;
+	eh->ctrl = ctrl;
+	writeb(ctrl, eh->ctrl_port);
+}
+
+static inline unsigned int etherh_get_stat(struct etherh_priv *eh)
+{
+	return readb(eh->ctrl_port);
+}
+
+
+
+
+static void etherh_irq_enable(ecard_t *ec, int irqnr)
+{
+	struct etherh_priv *eh = ec->irq_data;
+
+	etherh_set_ctrl(eh, ETHERH_CP_IE);
+}
+
+static void etherh_irq_disable(ecard_t *ec, int irqnr)
+{
+	struct etherh_priv *eh = ec->irq_data;
+
+	etherh_clr_ctrl(eh, ETHERH_CP_IE);
+}
+
+static expansioncard_ops_t etherh_ops = {
+	.irqenable	= etherh_irq_enable,
+	.irqdisable	= etherh_irq_disable,
+};
+
+
+
+
+static void
+etherh_setif(struct net_device *dev)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	unsigned long flags;
+	void __iomem *addr;
+
+	local_irq_save(flags);
+
+	/* set the interface type */
+	switch (etherh_priv(dev)->id) {
+	case PROD_I3_ETHERLAN600:
+	case PROD_I3_ETHERLAN600A:
+		addr = (void __iomem *)dev->base_addr + EN0_RCNTHI;
+
+		switch (dev->if_port) {
+		case IF_PORT_10BASE2:
+			writeb((readb(addr) & 0xf8) | 1, addr);
+			break;
+		case IF_PORT_10BASET:
+			writeb((readb(addr) & 0xf8), addr);
+			break;
+		}
+		break;
+
+	case PROD_I3_ETHERLAN500:
+		switch (dev->if_port) {
+		case IF_PORT_10BASE2:
+			etherh_clr_ctrl(etherh_priv(dev), ETHERH_CP_IF);
+			break;
+
+		case IF_PORT_10BASET:
+			etherh_set_ctrl(etherh_priv(dev), ETHERH_CP_IF);
+			break;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	local_irq_restore(flags);
+}
+
+static int
+etherh_getifstat(struct net_device *dev)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	void __iomem *addr;
+	int stat = 0;
+
+	switch (etherh_priv(dev)->id) {
+	case PROD_I3_ETHERLAN600:
+	case PROD_I3_ETHERLAN600A:
+		addr = (void __iomem *)dev->base_addr + EN0_RCNTHI;
+		switch (dev->if_port) {
+		case IF_PORT_10BASE2:
+			stat = 1;
+			break;
+		case IF_PORT_10BASET:
+			stat = readb(addr) & 4;
+			break;
+		}
+		break;
+
+	case PROD_I3_ETHERLAN500:
+		switch (dev->if_port) {
+		case IF_PORT_10BASE2:
+			stat = 1;
+			break;
+		case IF_PORT_10BASET:
+			stat = etherh_get_stat(etherh_priv(dev)) & ETHERH_CP_HEARTBEAT;
+			break;
+		}
+		break;
+
+	default:
+		stat = 0;
+		break;
+	}
+
+	return stat != 0;
+}
+
+/*
+ * Configure the interface.  Note that we ignore the other
+ * parts of ifmap, since its mostly meaningless for this driver.
+ */
+static int etherh_set_config(struct net_device *dev, struct ifmap *map)
+{
+	switch (map->port) {
+	case IF_PORT_10BASE2:
+	case IF_PORT_10BASET:
+		/*
+		 * If the user explicitly sets the interface
+		 * media type, turn off automedia detection.
+		 */
+		dev->flags &= ~IFF_AUTOMEDIA;
+		dev->if_port = map->port;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	etherh_setif(dev);
+
+	return 0;
+}
+
+/*
+ * Reset the 8390 (hard reset).  Note that we can't actually do this.
+ */
+static void
+etherh_reset(struct net_device *dev)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	void __iomem *addr = (void __iomem *)dev->base_addr;
+
+	writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, addr);
+
+	/*
+	 * See if we need to change the interface type.
+	 * Note that we use 'interface_num' as a flag
+	 * to indicate that we need to change the media.
+	 */
+	if (dev->flags & IFF_AUTOMEDIA && ei_local->interface_num) {
+		ei_local->interface_num = 0;
+
+		if (dev->if_port == IF_PORT_10BASET)
+			dev->if_port = IF_PORT_10BASE2;
+		else
+			dev->if_port = IF_PORT_10BASET;
+
+		etherh_setif(dev);
+	}
+}
+
+/*
+ * Write a block of data out to the 8390
+ */
+static void
+etherh_block_output (struct net_device *dev, int count, const unsigned char *buf, int start_page)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	unsigned long dma_start;
+	void __iomem *dma_base, *addr;
+
+	if (ei_local->dmaing) {
+		printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: "
+			" DMAstat %d irqlock %d\n", dev->name,
+			ei_local->dmaing, ei_local->irqlock);
+		return;
+	}
+
+	/*
+	 * Make sure we have a round number of bytes if we're in word mode.
+	 */
+	if (count & 1 && ei_local->word16)
+		count++;
+
+	ei_local->dmaing = 1;
+
+	addr = (void __iomem *)dev->base_addr;
+	dma_base = etherh_priv(dev)->dma_base;
+
+	count = (count + 1) & ~1;
+	writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
+
+	writeb (0x42, addr + EN0_RCNTLO);
+	writeb (0x00, addr + EN0_RCNTHI);
+	writeb (0x42, addr + EN0_RSARLO);
+	writeb (0x00, addr + EN0_RSARHI);
+	writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
+
+	udelay (1);
+
+	writeb (ENISR_RDC, addr + EN0_ISR);
+	writeb (count, addr + EN0_RCNTLO);
+	writeb (count >> 8, addr + EN0_RCNTHI);
+	writeb (0, addr + EN0_RSARLO);
+	writeb (start_page, addr + EN0_RSARHI);
+	writeb (E8390_RWRITE | E8390_START, addr + E8390_CMD);
+
+	if (ei_local->word16)
+		writesw (dma_base, buf, count >> 1);
+	else
+		writesb (dma_base, buf, count);
+
+	dma_start = jiffies;
+
+	while ((readb (addr + EN0_ISR) & ENISR_RDC) == 0)
+		if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
+			printk(KERN_ERR "%s: timeout waiting for TX RDC\n",
+				dev->name);
+			etherh_reset (dev);
+			__NS8390_init (dev, 1);
+			break;
+		}
+
+	writeb (ENISR_RDC, addr + EN0_ISR);
+	ei_local->dmaing = 0;
+}
+
+/*
+ * Read a block of data from the 8390
+ */
+static void
+etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	unsigned char *buf;
+	void __iomem *dma_base, *addr;
+
+	if (ei_local->dmaing) {
+		printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: "
+			" DMAstat %d irqlock %d\n", dev->name,
+			ei_local->dmaing, ei_local->irqlock);
+		return;
+	}
+
+	ei_local->dmaing = 1;
+
+	addr = (void __iomem *)dev->base_addr;
+	dma_base = etherh_priv(dev)->dma_base;
+
+	buf = skb->data;
+	writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
+	writeb (count, addr + EN0_RCNTLO);
+	writeb (count >> 8, addr + EN0_RCNTHI);
+	writeb (ring_offset, addr + EN0_RSARLO);
+	writeb (ring_offset >> 8, addr + EN0_RSARHI);
+	writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
+
+	if (ei_local->word16) {
+		readsw (dma_base, buf, count >> 1);
+		if (count & 1)
+			buf[count - 1] = readb (dma_base);
+	} else
+		readsb (dma_base, buf, count);
+
+	writeb (ENISR_RDC, addr + EN0_ISR);
+	ei_local->dmaing = 0;
+}
+
+/*
+ * Read a header from the 8390
+ */
+static void
+etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	void __iomem *dma_base, *addr;
+
+	if (ei_local->dmaing) {
+		printk(KERN_ERR "%s: DMAing conflict in etherh_get_header: "
+			" DMAstat %d irqlock %d\n", dev->name,
+			ei_local->dmaing, ei_local->irqlock);
+		return;
+	}
+
+	ei_local->dmaing = 1;
+
+	addr = (void __iomem *)dev->base_addr;
+	dma_base = etherh_priv(dev)->dma_base;
+
+	writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
+	writeb (sizeof (*hdr), addr + EN0_RCNTLO);
+	writeb (0, addr + EN0_RCNTHI);
+	writeb (0, addr + EN0_RSARLO);
+	writeb (ring_page, addr + EN0_RSARHI);
+	writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
+
+	if (ei_local->word16)
+		readsw (dma_base, hdr, sizeof (*hdr) >> 1);
+	else
+		readsb (dma_base, hdr, sizeof (*hdr));
+
+	writeb (ENISR_RDC, addr + EN0_ISR);
+	ei_local->dmaing = 0;
+}
+
+/*
+ * Open/initialize the board.  This is called (in the current kernel)
+ * sometime after booting when the 'ifconfig' program is run.
+ *
+ * This routine should set everything up anew at each open, even
+ * registers that "should" only need to be set once at boot, so that
+ * there is non-reboot way to recover if something goes wrong.
+ */
+static int
+etherh_open(struct net_device *dev)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+
+	if (!is_valid_ether_addr(dev->dev_addr)) {
+		printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
+			dev->name);
+		return -EINVAL;
+	}
+
+	if (request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev))
+		return -EAGAIN;
+
+	/*
+	 * Make sure that we aren't going to change the
+	 * media type on the next reset - we are about to
+	 * do automedia manually now.
+	 */
+	ei_local->interface_num = 0;
+
+	/*
+	 * If we are doing automedia detection, do it now.
+	 * This is more reliable than the 8390's detection.
+	 */
+	if (dev->flags & IFF_AUTOMEDIA) {
+		dev->if_port = IF_PORT_10BASET;
+		etherh_setif(dev);
+		mdelay(1);
+		if (!etherh_getifstat(dev)) {
+			dev->if_port = IF_PORT_10BASE2;
+			etherh_setif(dev);
+		}
+	} else
+		etherh_setif(dev);
+
+	etherh_reset(dev);
+	__ei_open(dev);
+
+	return 0;
+}
+
+/*
+ * The inverse routine to etherh_open().
+ */
+static int
+etherh_close(struct net_device *dev)
+{
+	__ei_close (dev);
+	free_irq (dev->irq, dev);
+	return 0;
+}
+
+/*
+ * Initialisation
+ */
+
+static void __init etherh_banner(void)
+{
+	static int version_printed;
+
+	if (net_debug && version_printed++ == 0)
+		printk(KERN_INFO "%s", version);
+}
+
+/*
+ * Read the ethernet address string from the on board rom.
+ * This is an ascii string...
+ */
+static int __devinit etherh_addr(char *addr, struct expansion_card *ec)
+{
+	struct in_chunk_dir cd;
+	char *s;
+	
+	if (!ecard_readchunk(&cd, ec, 0xf5, 0)) {
+		printk(KERN_ERR "%s: unable to read podule description string\n",
+		       dev_name(&ec->dev));
+		goto no_addr;
+	}
+
+	s = strchr(cd.d.string, '(');
+	if (s) {
+		int i;
+
+		for (i = 0; i < 6; i++) {
+			addr[i] = simple_strtoul(s + 1, &s, 0x10);
+			if (*s != (i == 5? ')' : ':'))
+				break;
+		}
+
+		if (i == 6)
+			return 0;
+	}
+
+	printk(KERN_ERR "%s: unable to parse MAC address: %s\n",
+	       dev_name(&ec->dev), cd.d.string);
+
+ no_addr:
+	return -ENODEV;
+}
+
+/*
+ * Create an ethernet address from the system serial number.
+ */
+static int __init etherm_addr(char *addr)
+{
+	unsigned int serial;
+
+	if (system_serial_low == 0 && system_serial_high == 0)
+		return -ENODEV;
+
+	serial = system_serial_low | system_serial_high;
+
+	addr[0] = 0;
+	addr[1] = 0;
+	addr[2] = 0xa4;
+	addr[3] = 0x10 + (serial >> 24);
+	addr[4] = serial >> 16;
+	addr[5] = serial >> 8;
+	return 0;
+}
+
+static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+	strlcpy(info->bus_info, dev_name(dev->dev.parent),
+		sizeof(info->bus_info));
+}
+
+static int etherh_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	cmd->supported	= etherh_priv(dev)->supported;
+	ethtool_cmd_speed_set(cmd, SPEED_10);
+	cmd->duplex	= DUPLEX_HALF;
+	cmd->port	= dev->if_port == IF_PORT_10BASET ? PORT_TP : PORT_BNC;
+	cmd->autoneg	= (dev->flags & IFF_AUTOMEDIA ?
+			   AUTONEG_ENABLE : AUTONEG_DISABLE);
+	return 0;
+}
+
+static int etherh_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	switch (cmd->autoneg) {
+	case AUTONEG_ENABLE:
+		dev->flags |= IFF_AUTOMEDIA;
+		break;
+
+	case AUTONEG_DISABLE:
+		switch (cmd->port) {
+		case PORT_TP:
+			dev->if_port = IF_PORT_10BASET;
+			break;
+
+		case PORT_BNC:
+			dev->if_port = IF_PORT_10BASE2;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+		dev->flags &= ~IFF_AUTOMEDIA;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	etherh_setif(dev);
+
+	return 0;
+}
+
+static const struct ethtool_ops etherh_ethtool_ops = {
+	.get_settings	= etherh_get_settings,
+	.set_settings	= etherh_set_settings,
+	.get_drvinfo	= etherh_get_drvinfo,
+};
+
+static const struct net_device_ops etherh_netdev_ops = {
+	.ndo_open		= etherh_open,
+	.ndo_stop		= etherh_close,
+	.ndo_set_config		= etherh_set_config,
+	.ndo_start_xmit		= __ei_start_xmit,
+	.ndo_tx_timeout		= __ei_tx_timeout,
+	.ndo_get_stats		= __ei_get_stats,
+	.ndo_set_rx_mode	= __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,
+#endif
+};
+
+static u32 etherh_regoffsets[16];
+static u32 etherm_regoffsets[16];
+
+static int __devinit
+etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
+{
+	const struct etherh_data *data = id->data;
+	struct ei_device *ei_local;
+	struct net_device *dev;
+	struct etherh_priv *eh;
+	int ret;
+
+	etherh_banner();
+
+	ret = ecard_request_resources(ec);
+	if (ret)
+		goto out;
+
+	dev = ____alloc_ei_netdev(sizeof(struct etherh_priv));
+	if (!dev) {
+		ret = -ENOMEM;
+		goto release;
+	}
+
+	SET_NETDEV_DEV(dev, &ec->dev);
+
+	dev->netdev_ops		= &etherh_netdev_ops;
+	dev->irq		= ec->irq;
+	dev->ethtool_ops	= &etherh_ethtool_ops;
+
+	if (data->supported & SUPPORTED_Autoneg)
+		dev->flags |= IFF_AUTOMEDIA;
+	if (data->supported & SUPPORTED_TP) {
+		dev->flags |= IFF_PORTSEL;
+		dev->if_port = IF_PORT_10BASET;
+	} else if (data->supported & SUPPORTED_BNC) {
+		dev->flags |= IFF_PORTSEL;
+		dev->if_port = IF_PORT_10BASE2;
+	} else
+		dev->if_port = IF_PORT_UNKNOWN;
+
+	eh = etherh_priv(dev);
+	eh->supported		= data->supported;
+	eh->ctrl		= 0;
+	eh->id			= ec->cid.product;
+	eh->memc		= ecardm_iomap(ec, ECARD_RES_MEMC, 0, PAGE_SIZE);
+	if (!eh->memc) {
+		ret = -ENOMEM;
+		goto free;
+	}
+
+	eh->ctrl_port = eh->memc;
+	if (data->ctrl_ioc) {
+		eh->ioc_fast = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, PAGE_SIZE);
+		if (!eh->ioc_fast) {
+			ret = -ENOMEM;
+			goto free;
+		}
+		eh->ctrl_port = eh->ioc_fast;
+	}
+
+	dev->base_addr = (unsigned long)eh->memc + data->ns8390_offset;
+	eh->dma_base = eh->memc + data->dataport_offset;
+	eh->ctrl_port += data->ctrlport_offset;
+
+	/*
+	 * IRQ and control port handling - only for non-NIC slot cards.
+	 */
+	if (ec->slot_no != 8) {
+		ecard_setirq(ec, &etherh_ops, eh);
+	} else {
+		/*
+		 * If we're in the NIC slot, make sure the IRQ is enabled
+		 */
+		etherh_set_ctrl(eh, ETHERH_CP_IE);
+	}
+
+	ei_local = netdev_priv(dev);
+	spin_lock_init(&ei_local->page_lock);
+
+	if (ec->cid.product == PROD_ANT_ETHERM) {
+		etherm_addr(dev->dev_addr);
+		ei_local->reg_offset = etherm_regoffsets;
+	} else {
+		etherh_addr(dev->dev_addr, ec);
+		ei_local->reg_offset = etherh_regoffsets;
+	}
+
+	ei_local->name          = dev->name;
+	ei_local->word16        = 1;
+	ei_local->tx_start_page = data->tx_start_page;
+	ei_local->rx_start_page = ei_local->tx_start_page + TX_PAGES;
+	ei_local->stop_page     = data->stop_page;
+	ei_local->reset_8390    = etherh_reset;
+	ei_local->block_input   = etherh_block_input;
+	ei_local->block_output  = etherh_block_output;
+	ei_local->get_8390_hdr  = etherh_get_header;
+	ei_local->interface_num = 0;
+
+	etherh_reset(dev);
+	__NS8390_init(dev, 0);
+
+	ret = register_netdev(dev);
+	if (ret)
+		goto free;
+
+	printk(KERN_INFO "%s: %s in slot %d, %pM\n",
+		dev->name, data->name, ec->slot_no, dev->dev_addr);
+
+	ecard_set_drvdata(ec, dev);
+
+	return 0;
+
+ free:
+	free_netdev(dev);
+ release:
+	ecard_release_resources(ec);
+ out:
+	return ret;
+}
+
+static void __devexit etherh_remove(struct expansion_card *ec)
+{
+	struct net_device *dev = ecard_get_drvdata(ec);
+
+	ecard_set_drvdata(ec, NULL);
+
+	unregister_netdev(dev);
+
+	free_netdev(dev);
+
+	ecard_release_resources(ec);
+}
+
+static struct etherh_data etherm_data = {
+	.ns8390_offset		= ETHERM_NS8390,
+	.dataport_offset	= ETHERM_NS8390 + ETHERM_DATAPORT,
+	.ctrlport_offset	= ETHERM_NS8390 + ETHERM_CTRLPORT,
+	.name			= "ANT EtherM",
+	.supported		= SUPPORTED_10baseT_Half,
+	.tx_start_page		= ETHERM_TX_START_PAGE,
+	.stop_page		= ETHERM_STOP_PAGE,
+};
+
+static struct etherh_data etherlan500_data = {
+	.ns8390_offset		= ETHERH500_NS8390,
+	.dataport_offset	= ETHERH500_NS8390 + ETHERH500_DATAPORT,
+	.ctrlport_offset	= ETHERH500_CTRLPORT,
+	.ctrl_ioc		= 1,
+	.name			= "i3 EtherH 500",
+	.supported		= SUPPORTED_10baseT_Half,
+	.tx_start_page		= ETHERH_TX_START_PAGE,
+	.stop_page		= ETHERH_STOP_PAGE,
+};
+
+static struct etherh_data etherlan600_data = {
+	.ns8390_offset		= ETHERH600_NS8390,
+	.dataport_offset	= ETHERH600_NS8390 + ETHERH600_DATAPORT,
+	.ctrlport_offset	= ETHERH600_NS8390 + ETHERH600_CTRLPORT,
+	.name			= "i3 EtherH 600",
+	.supported		= SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg,
+	.tx_start_page		= ETHERH_TX_START_PAGE,
+	.stop_page		= ETHERH_STOP_PAGE,
+};
+
+static struct etherh_data etherlan600a_data = {
+	.ns8390_offset		= ETHERH600_NS8390,
+	.dataport_offset	= ETHERH600_NS8390 + ETHERH600_DATAPORT,
+	.ctrlport_offset	= ETHERH600_NS8390 + ETHERH600_CTRLPORT,
+	.name			= "i3 EtherH 600A",
+	.supported		= SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg,
+	.tx_start_page		= ETHERH_TX_START_PAGE,
+	.stop_page		= ETHERH_STOP_PAGE,
+};
+
+static const struct ecard_id etherh_ids[] = {
+	{ MANU_ANT, PROD_ANT_ETHERM,      &etherm_data       },
+	{ MANU_I3,  PROD_I3_ETHERLAN500,  &etherlan500_data  },
+	{ MANU_I3,  PROD_I3_ETHERLAN600,  &etherlan600_data  },
+	{ MANU_I3,  PROD_I3_ETHERLAN600A, &etherlan600a_data },
+	{ 0xffff,   0xffff }
+};
+
+static struct ecard_driver etherh_driver = {
+	.probe		= etherh_probe,
+	.remove		= __devexit_p(etherh_remove),
+	.id_table	= etherh_ids,
+	.drv = {
+		.name	= DRV_NAME,
+	},
+};
+
+static int __init etherh_init(void)
+{
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		etherh_regoffsets[i] = i << 2;
+		etherm_regoffsets[i] = i << 5;
+	}
+
+	return ecard_register_driver(&etherh_driver);
+}
+
+static void __exit etherh_exit(void)
+{
+	ecard_remove_driver(&etherh_driver);
+}
+
+module_init(etherh_init);
+module_exit(etherh_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/hp.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/hp.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/hp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/hp.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,439 @@
+/* hp.c: A HP LAN ethernet driver for linux. */
+/*
+	Written 1993-94 by Donald Becker.
+
+	Copyright 1993 United States Government as represented by the
+	Director, National Security Agency.
+
+	This software may be used and distributed according to the terms
+	of the GNU General Public License, incorporated herein by reference.
+
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+	This is a driver for the HP PC-LAN adaptors.
+
+	Sources:
+	  The Crynwr packet driver.
+*/
+
+static const char version[] =
+	"hp.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include "8390.h"
+
+#define DRV_NAME "hp"
+
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int hppclan_portlist[] __initdata =
+{ 0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0};
+
+#define HP_IO_EXTENT	32
+
+#define HP_DATAPORT		0x0c	/* "Remote DMA" data port. */
+#define HP_ID			0x07
+#define HP_CONFIGURE	0x08	/* Configuration register. */
+#define	 HP_RUN			0x01	/* 1 == Run, 0 == reset. */
+#define	 HP_IRQ			0x0E	/* Mask for software-configured IRQ line. */
+#define	 HP_DATAON		0x10	/* Turn on dataport */
+#define NIC_OFFSET		0x10	/* Offset the 8390 registers. */
+
+#define HP_START_PG		0x00	/* First page of TX buffer */
+#define HP_8BSTOP_PG	0x80	/* Last page +1 of RX ring */
+#define HP_16BSTOP_PG	0xFF	/* Same, for 16 bit cards. */
+
+static int hp_probe1(struct net_device *dev, int ioaddr);
+
+static void hp_reset_8390(struct net_device *dev);
+static void hp_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+					int ring_page);
+static void hp_block_input(struct net_device *dev, int count,
+					struct sk_buff *skb , int ring_offset);
+static void hp_block_output(struct net_device *dev, int count,
+							const unsigned char *buf, int start_page);
+
+static void hp_init_card(struct net_device *dev);
+
+/* The map from IRQ number to HP_CONFIGURE register setting. */
+/* My default is IRQ5	             0  1  2  3  4  5  6  7  8  9 10 11 */
+static char irqmap[16] __initdata= { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0};
+
+
+/*	Probe for an HP LAN adaptor.
+	Also initialize the card and fill in STATION_ADDR with the station
+	address. */
+
+static int __init do_hp_probe(struct net_device *dev)
+{
+	int i;
+	int base_addr = dev->base_addr;
+	int irq = dev->irq;
+
+	if (base_addr > 0x1ff)		/* Check a single specified location. */
+		return hp_probe1(dev, base_addr);
+	else if (base_addr != 0)	/* Don't probe at all. */
+		return -ENXIO;
+
+	for (i = 0; hppclan_portlist[i]; i++) {
+		if (hp_probe1(dev, hppclan_portlist[i]) == 0)
+			return 0;
+		dev->irq = irq;
+	}
+
+	return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init hp_probe(int unit)
+{
+	struct net_device *dev = alloc_eip_netdev();
+	int err;
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+
+	err = do_hp_probe(dev);
+	if (err)
+		goto out;
+	return dev;
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+#endif
+
+static int __init hp_probe1(struct net_device *dev, int ioaddr)
+{
+	int i, retval, board_id, wordmode;
+	const char *name;
+	static unsigned version_printed;
+
+	if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME))
+		return -EBUSY;
+
+	/* Check for the HP physical address, 08 00 09 xx xx xx. */
+	/* This really isn't good enough: we may pick up HP LANCE boards
+	   also!  Avoid the lance 0x5757 signature. */
+	if (inb(ioaddr) != 0x08
+		|| inb(ioaddr+1) != 0x00
+		|| inb(ioaddr+2) != 0x09
+		|| inb(ioaddr+14) == 0x57) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	/* Set up the parameters based on the board ID.
+	   If you have additional mappings, please mail them to me -djb. */
+	if ((board_id = inb(ioaddr + HP_ID)) & 0x80) {
+		name = "HP27247";
+		wordmode = 1;
+	} else {
+		name = "HP27250";
+		wordmode = 0;
+	}
+
+	if (ei_debug  &&  version_printed++ == 0)
+		printk(version);
+
+	printk("%s: %s (ID %02x) at %#3x,", dev->name, name, board_id, ioaddr);
+
+	for(i = 0; i < ETHER_ADDR_LEN; i++)
+		dev->dev_addr[i] = inb(ioaddr + i);
+
+	printk(" %pM", dev->dev_addr);
+
+	/* Snarf the interrupt now.  Someday this could be moved to open(). */
+	if (dev->irq < 2) {
+		static const int irq_16list[] = { 11, 10, 5, 3, 4, 7, 9, 0};
+		static const int irq_8list[] = { 7, 5, 3, 4, 9, 0};
+		const int *irqp = wordmode ? irq_16list : irq_8list;
+		do {
+			int irq = *irqp;
+			if (request_irq (irq, NULL, 0, "bogus", NULL) != -EBUSY) {
+				unsigned long cookie = probe_irq_on();
+				/* Twinkle the interrupt, and check if it's seen. */
+				outb_p(irqmap[irq] | HP_RUN, ioaddr + HP_CONFIGURE);
+				outb_p( 0x00 | HP_RUN, ioaddr + HP_CONFIGURE);
+				if (irq == probe_irq_off(cookie)		 /* It's a good IRQ line! */
+					&& request_irq (irq, eip_interrupt, 0, DRV_NAME, dev) == 0) {
+					printk(" selecting IRQ %d.\n", irq);
+					dev->irq = *irqp;
+					break;
+				}
+			}
+		} while (*++irqp);
+		if (*irqp == 0) {
+			printk(" no free IRQ lines.\n");
+			retval = -EBUSY;
+			goto out;
+		}
+	} else {
+		if (dev->irq == 2)
+			dev->irq = 9;
+		if ((retval = request_irq(dev->irq, eip_interrupt, 0, DRV_NAME, dev))) {
+			printk (" unable to get IRQ %d.\n", dev->irq);
+			goto out;
+		}
+	}
+
+	/* Set the base address to point to the NIC, not the "real" base! */
+	dev->base_addr = ioaddr + NIC_OFFSET;
+	dev->netdev_ops = &eip_netdev_ops;
+
+	ei_status.name = name;
+	ei_status.word16 = wordmode;
+	ei_status.tx_start_page = HP_START_PG;
+	ei_status.rx_start_page = HP_START_PG + TX_PAGES;
+	ei_status.stop_page = wordmode ? HP_16BSTOP_PG : HP_8BSTOP_PG;
+
+	ei_status.reset_8390 = hp_reset_8390;
+	ei_status.get_8390_hdr = hp_get_8390_hdr;
+	ei_status.block_input = hp_block_input;
+	ei_status.block_output = hp_block_output;
+	hp_init_card(dev);
+
+	retval = register_netdev(dev);
+	if (retval)
+		goto out1;
+	return 0;
+out1:
+	free_irq(dev->irq, dev);
+out:
+	release_region(ioaddr, HP_IO_EXTENT);
+	return retval;
+}
+
+static void
+hp_reset_8390(struct net_device *dev)
+{
+	int hp_base = dev->base_addr - NIC_OFFSET;
+	int saved_config = inb_p(hp_base + HP_CONFIGURE);
+
+	if (ei_debug > 1) printk("resetting the 8390 time=%ld...", jiffies);
+	outb_p(0x00, hp_base + HP_CONFIGURE);
+	ei_status.txing = 0;
+	/* Pause just a few cycles for the hardware reset to take place. */
+	udelay(5);
+
+	outb_p(saved_config, hp_base + HP_CONFIGURE);
+	udelay(5);
+
+	if ((inb_p(hp_base+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0)
+		printk("%s: hp_reset_8390() did not complete.\n", dev->name);
+
+	if (ei_debug > 1) printk("8390 reset done (%ld).", jiffies);
+}
+
+static void
+hp_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	int nic_base = dev->base_addr;
+	int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
+
+	outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base);
+	outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+	outb_p(0, nic_base + EN0_RCNTHI);
+	outb_p(0, nic_base + EN0_RSARLO);	/* On page boundary */
+	outb_p(ring_page, nic_base + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, nic_base);
+
+	if (ei_status.word16)
+	  insw(nic_base - NIC_OFFSET + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+	else
+	  insb(nic_base - NIC_OFFSET + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+
+	outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
+}
+
+/* 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 HP LAN doesn't use shared memory -- we put the packet
+   out through the "remote DMA" dataport. */
+
+static void
+hp_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+	int nic_base = dev->base_addr;
+	int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
+	int xfer_count = count;
+	char *buf = skb->data;
+
+	outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base);
+	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+	outb_p(count >> 8, nic_base + EN0_RCNTHI);
+	outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
+	outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, nic_base);
+	if (ei_status.word16) {
+	  insw(nic_base - NIC_OFFSET + HP_DATAPORT,buf,count>>1);
+	  if (count & 0x01)
+		buf[count-1] = inb(nic_base - NIC_OFFSET + HP_DATAPORT), xfer_count++;
+	} else {
+		insb(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count);
+	}
+	/* This is for the ALPHA version only, remove for later releases. */
+	if (ei_debug > 0) {			/* DMA termination address check... */
+	  int high = inb_p(nic_base + EN0_RSARHI);
+	  int low = inb_p(nic_base + EN0_RSARLO);
+	  int addr = (high << 8) + low;
+	  /* Check only the lower 8 bits so we can ignore ring wrap. */
+	  if (((ring_offset + xfer_count) & 0xff) != (addr & 0xff))
+		printk("%s: RX transfer address mismatch, %#4.4x vs. %#4.4x (actual).\n",
+			   dev->name, ring_offset + xfer_count, addr);
+	}
+	outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
+}
+
+static void
+hp_block_output(struct net_device *dev, int count,
+				const unsigned char *buf, int start_page)
+{
+	int nic_base = dev->base_addr;
+	int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
+
+	outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
+	/* 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))
+	  count++;
+	/* We should already be in page 0, but to be safe... */
+	outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base);
+
+#ifdef NE8390_RW_BUGFIX
+	/* Handle the read-before-write bug the same way as the
+	   Crynwr packet driver -- the NatSemi method doesn't work. */
+	outb_p(0x42, nic_base + EN0_RCNTLO);
+	outb_p(0,	nic_base + EN0_RCNTHI);
+	outb_p(0xff, nic_base + EN0_RSARLO);
+	outb_p(0x00, nic_base + EN0_RSARHI);
+#define NE_CMD	 	0x00
+	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+	/* Make certain that the dummy read has occurred. */
+	inb_p(0x61);
+	inb_p(0x61);
+#endif
+
+	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+	outb_p(count >> 8,	 nic_base + EN0_RCNTHI);
+	outb_p(0x00, nic_base + EN0_RSARLO);
+	outb_p(start_page, nic_base + EN0_RSARHI);
+
+	outb_p(E8390_RWRITE+E8390_START, nic_base);
+	if (ei_status.word16) {
+		/* Use the 'rep' sequence for 16 bit boards. */
+		outsw(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count>>1);
+	} else {
+		outsb(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count);
+	}
+
+	/* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here -- it's broken! */
+
+	/* This is for the ALPHA version only, remove for later releases. */
+	if (ei_debug > 0) {			/* DMA termination address check... */
+	  int high = inb_p(nic_base + EN0_RSARHI);
+	  int low  = inb_p(nic_base + EN0_RSARLO);
+	  int addr = (high << 8) + low;
+	  if ((start_page << 8) + count != addr)
+		printk("%s: TX Transfer address mismatch, %#4.4x vs. %#4.4x.\n",
+			   dev->name, (start_page << 8) + count, addr);
+	}
+	outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
+}
+
+/* This function resets the ethercard if something screws up. */
+static void __init
+hp_init_card(struct net_device *dev)
+{
+	int irq = dev->irq;
+	NS8390p_init(dev, 0);
+	outb_p(irqmap[irq&0x0f] | HP_RUN,
+		   dev->base_addr - NIC_OFFSET + HP_CONFIGURE);
+}
+
+#ifdef MODULE
+#define MAX_HP_CARDS	4	/* Max number of HP cards per module */
+static struct net_device *dev_hp[MAX_HP_CARDS];
+static int io[MAX_HP_CARDS];
+static int irq[MAX_HP_CARDS];
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
+MODULE_DESCRIPTION("HP PC-LAN ISA ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* This is set up so that only a single autoprobe takes place per call.
+ISA device autoprobes on a running machine are not recommended. */
+int __init
+init_module(void)
+{
+	struct net_device *dev;
+	int this_dev, found = 0;
+
+	for (this_dev = 0; this_dev < MAX_HP_CARDS; this_dev++) {
+		if (io[this_dev] == 0)  {
+			if (this_dev != 0) break; /* only autoprobe 1st one */
+			printk(KERN_NOTICE "hp.c: Presently autoprobing (not recommended) for a single card.\n");
+		}
+		dev = alloc_eip_netdev();
+		if (!dev)
+			break;
+		dev->irq = irq[this_dev];
+		dev->base_addr = io[this_dev];
+		if (do_hp_probe(dev) == 0) {
+			dev_hp[found++] = dev;
+			continue;
+		}
+		free_netdev(dev);
+		printk(KERN_WARNING "hp.c: No HP card found (i/o = 0x%x).\n", io[this_dev]);
+		break;
+	}
+	if (found)
+		return 0;
+	return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+	free_irq(dev->irq, dev);
+	release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
+}
+
+void __exit
+cleanup_module(void)
+{
+	int this_dev;
+
+	for (this_dev = 0; this_dev < MAX_HP_CARDS; this_dev++) {
+		struct net_device *dev = dev_hp[this_dev];
+		if (dev) {
+			unregister_netdev(dev);
+			cleanup_card(dev);
+			free_netdev(dev);
+		}
+	}
+}
+#endif /* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/hp-plus.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/hp-plus.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/hp-plus.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/hp-plus.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,506 @@
+/* hp-plus.c: A HP PCLAN/plus ethernet driver for linux. */
+/*
+	Written 1994 by Donald Becker.
+
+	This driver is for the Hewlett Packard PC LAN (27***) plus ethercards.
+	These cards are sold under several model numbers, usually 2724*.
+
+	This software may be used and distributed according to the terms
+	of the GNU General Public License, incorporated herein by reference.
+
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+	As is often the case, a great deal of credit is owed to Russ Nelson.
+	The Crynwr packet driver was my primary source of HP-specific
+	programming information.
+*/
+
+static const char version[] =
+"hp-plus.c:v1.10 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include <linux/module.h>
+
+#include <linux/string.h>		/* Important -- this inlines word moves. */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include "8390.h"
+
+#define DRV_NAME "hp-plus"
+
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int hpplus_portlist[] __initdata =
+{0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0};
+
+/*
+   The HP EtherTwist chip implementation is a fairly routine DP8390
+   implementation.  It allows both shared memory and programmed-I/O buffer
+   access, using a custom interface for both.  The programmed-I/O mode is
+   entirely implemented in the HP EtherTwist chip, bypassing the problem
+   ridden built-in 8390 facilities used on NE2000 designs.  The shared
+   memory mode is likewise special, with an offset register used to make
+   packets appear at the shared memory base.  Both modes use a base and bounds
+   page register to hide the Rx ring buffer wrap -- a packet that spans the
+   end of physical buffer memory appears continuous to the driver. (c.f. the
+   3c503 and Cabletron E2100)
+
+   A special note: the internal buffer of the board is only 8 bits wide.
+   This lays several nasty traps for the unaware:
+   - the 8390 must be programmed for byte-wide operations
+   - all I/O and memory operations must work on whole words (the access
+     latches are serially preloaded and have no byte-swapping ability).
+
+   This board is laid out in I/O space much like the earlier HP boards:
+   the first 16 locations are for the board registers, and the second 16 are
+   for the 8390.  The board is easy to identify, with both a dedicated 16 bit
+   ID register and a constant 0x530* value in the upper bits of the paging
+   register.
+*/
+
+#define HP_ID			0x00	/* ID register, always 0x4850. */
+#define HP_PAGING		0x02	/* Registers visible @ 8-f, see PageName. */
+#define HPP_OPTION		0x04	/* Bitmapped options, see HP_Option.	*/
+#define HPP_OUT_ADDR	0x08	/* I/O output location in Perf_Page.	*/
+#define HPP_IN_ADDR		0x0A	/* I/O input location in Perf_Page.		*/
+#define HP_DATAPORT		0x0c	/* I/O data transfer in Perf_Page.		*/
+#define NIC_OFFSET		0x10	/* Offset to the 8390 registers.		*/
+#define HP_IO_EXTENT	32
+
+#define HP_START_PG		0x00	/* First page of TX buffer */
+#define HP_STOP_PG		0x80	/* Last page +1 of RX ring */
+
+/* The register set selected in HP_PAGING. */
+enum PageName {
+	Perf_Page = 0,				/* Normal operation. */
+	MAC_Page = 1,				/* The ethernet address (+checksum). */
+	HW_Page = 2,				/* EEPROM-loaded hardware parameters. */
+	LAN_Page = 4,				/* Transceiver selection, testing, etc. */
+	ID_Page = 6 };
+
+/* The bit definitions for the HPP_OPTION register. */
+enum HP_Option {
+	NICReset = 1, ChipReset = 2, 	/* Active low, really UNreset. */
+	EnableIRQ = 4, FakeIntr = 8, BootROMEnb = 0x10, IOEnb = 0x20,
+	MemEnable = 0x40, ZeroWait = 0x80, MemDisable = 0x1000, };
+
+static int hpp_probe1(struct net_device *dev, int ioaddr);
+
+static void hpp_reset_8390(struct net_device *dev);
+static int hpp_open(struct net_device *dev);
+static int hpp_close(struct net_device *dev);
+static void hpp_mem_block_input(struct net_device *dev, int count,
+						  struct sk_buff *skb, int ring_offset);
+static void hpp_mem_block_output(struct net_device *dev, int count,
+							const unsigned char *buf, int start_page);
+static void hpp_mem_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+						  int ring_page);
+static void hpp_io_block_input(struct net_device *dev, int count,
+						  struct sk_buff *skb, int ring_offset);
+static void hpp_io_block_output(struct net_device *dev, int count,
+							const unsigned char *buf, int start_page);
+static void hpp_io_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+						  int ring_page);
+
+
+/*	Probe a list of addresses for an HP LAN+ adaptor.
+	This routine is almost boilerplate. */
+
+static int __init do_hpp_probe(struct net_device *dev)
+{
+	int i;
+	int base_addr = dev->base_addr;
+	int irq = dev->irq;
+
+	if (base_addr > 0x1ff)		/* Check a single specified location. */
+		return hpp_probe1(dev, base_addr);
+	else if (base_addr != 0)	/* Don't probe at all. */
+		return -ENXIO;
+
+	for (i = 0; hpplus_portlist[i]; i++) {
+		if (hpp_probe1(dev, hpplus_portlist[i]) == 0)
+			return 0;
+		dev->irq = irq;
+	}
+
+	return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init hp_plus_probe(int unit)
+{
+	struct net_device *dev = alloc_eip_netdev();
+	int err;
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+
+	err = do_hpp_probe(dev);
+	if (err)
+		goto out;
+	return dev;
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+#endif
+
+static const struct net_device_ops hpp_netdev_ops = {
+	.ndo_open		= hpp_open,
+	.ndo_stop		= hpp_close,
+	.ndo_start_xmit		= eip_start_xmit,
+	.ndo_tx_timeout		= eip_tx_timeout,
+	.ndo_get_stats		= eip_get_stats,
+	.ndo_set_rx_mode	= eip_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	= eip_poll,
+#endif
+};
+
+
+/* Do the interesting part of the probe at a single address. */
+static int __init hpp_probe1(struct net_device *dev, int ioaddr)
+{
+	int i, retval;
+	unsigned char checksum = 0;
+	const char name[] = "HP-PC-LAN+";
+	int mem_start;
+	static unsigned version_printed;
+
+	if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME))
+		return -EBUSY;
+
+	/* Check for the HP+ signature, 50 48 0x 53. */
+	if (inw(ioaddr + HP_ID) != 0x4850 ||
+	    (inw(ioaddr + HP_PAGING) & 0xfff0) != 0x5300) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	if (ei_debug  &&  version_printed++ == 0)
+		printk(version);
+
+	printk("%s: %s at %#3x, ", dev->name, name, ioaddr);
+
+	/* Retrieve and checksum the station address. */
+	outw(MAC_Page, ioaddr + HP_PAGING);
+
+	for(i = 0; i < ETHER_ADDR_LEN; i++) {
+		unsigned char inval = inb(ioaddr + 8 + i);
+		dev->dev_addr[i] = inval;
+		checksum += inval;
+	}
+	checksum += inb(ioaddr + 14);
+
+	printk("%pM", dev->dev_addr);
+
+	if (checksum != 0xff) {
+		printk(" bad checksum %2.2x.\n", checksum);
+		retval = -ENODEV;
+		goto out;
+	} else {
+		/* Point at the Software Configuration Flags. */
+		outw(ID_Page, ioaddr + HP_PAGING);
+		printk(" ID %4.4x", inw(ioaddr + 12));
+	}
+
+	/* Read the IRQ line. */
+	outw(HW_Page, ioaddr + HP_PAGING);
+	{
+		int irq = inb(ioaddr + 13) & 0x0f;
+		int option = inw(ioaddr + HPP_OPTION);
+
+		dev->irq = irq;
+		if (option & MemEnable) {
+			mem_start = inw(ioaddr + 9) << 8;
+			printk(", IRQ %d, memory address %#x.\n", irq, mem_start);
+		} else {
+			mem_start = 0;
+			printk(", IRQ %d, programmed-I/O mode.\n", irq);
+		}
+	}
+
+	/* Set the wrap registers for string I/O reads.   */
+	outw((HP_START_PG + TX_PAGES/2) | ((HP_STOP_PG - 1) << 8), ioaddr + 14);
+
+	/* Set the base address to point to the NIC, not the "real" base! */
+	dev->base_addr = ioaddr + NIC_OFFSET;
+
+	dev->netdev_ops = &hpp_netdev_ops;
+
+	ei_status.name = name;
+	ei_status.word16 = 0;		/* Agggghhhhh! Debug time: 2 days! */
+	ei_status.tx_start_page = HP_START_PG;
+	ei_status.rx_start_page = HP_START_PG + TX_PAGES/2;
+	ei_status.stop_page = HP_STOP_PG;
+
+	ei_status.reset_8390 = &hpp_reset_8390;
+	ei_status.block_input = &hpp_io_block_input;
+	ei_status.block_output = &hpp_io_block_output;
+	ei_status.get_8390_hdr = &hpp_io_get_8390_hdr;
+
+	/* Check if the memory_enable flag is set in the option register. */
+	if (mem_start) {
+		ei_status.block_input = &hpp_mem_block_input;
+		ei_status.block_output = &hpp_mem_block_output;
+		ei_status.get_8390_hdr = &hpp_mem_get_8390_hdr;
+		dev->mem_start = mem_start;
+		ei_status.mem = ioremap(mem_start,
+					(HP_STOP_PG - HP_START_PG)*256);
+		if (!ei_status.mem) {
+			retval = -ENOMEM;
+			goto out;
+		}
+		ei_status.rmem_start = dev->mem_start + TX_PAGES/2*256;
+		dev->mem_end = ei_status.rmem_end
+			= dev->mem_start + (HP_STOP_PG - HP_START_PG)*256;
+	}
+
+	outw(Perf_Page, ioaddr + HP_PAGING);
+	NS8390p_init(dev, 0);
+	/* Leave the 8390 and HP chip reset. */
+	outw(inw(ioaddr + HPP_OPTION) & ~EnableIRQ, ioaddr + HPP_OPTION);
+
+	retval = register_netdev(dev);
+	if (retval)
+		goto out1;
+	return 0;
+out1:
+	iounmap(ei_status.mem);
+out:
+	release_region(ioaddr, HP_IO_EXTENT);
+	return retval;
+}
+
+static int
+hpp_open(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr - NIC_OFFSET;
+	int option_reg;
+	int retval;
+
+	if ((retval = request_irq(dev->irq, eip_interrupt, 0, dev->name, dev))) {
+	    return retval;
+	}
+
+	/* Reset the 8390 and HP chip. */
+	option_reg = inw(ioaddr + HPP_OPTION);
+	outw(option_reg & ~(NICReset + ChipReset), ioaddr + HPP_OPTION);
+	udelay(5);
+	/* Unreset the board and enable interrupts. */
+	outw(option_reg | (EnableIRQ + NICReset + ChipReset), ioaddr + HPP_OPTION);
+
+	/* Set the wrap registers for programmed-I/O operation.   */
+	outw(HW_Page, ioaddr + HP_PAGING);
+	outw((HP_START_PG + TX_PAGES/2) | ((HP_STOP_PG - 1) << 8), ioaddr + 14);
+
+	/* Select the operational page. */
+	outw(Perf_Page, ioaddr + HP_PAGING);
+
+	return eip_open(dev);
+}
+
+static int
+hpp_close(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr - NIC_OFFSET;
+	int option_reg = inw(ioaddr + HPP_OPTION);
+
+	free_irq(dev->irq, dev);
+	eip_close(dev);
+	outw((option_reg & ~EnableIRQ) | MemDisable | NICReset | ChipReset,
+		 ioaddr + HPP_OPTION);
+
+	return 0;
+}
+
+static void
+hpp_reset_8390(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr - NIC_OFFSET;
+	int option_reg = inw(ioaddr + HPP_OPTION);
+
+	if (ei_debug > 1) printk("resetting the 8390 time=%ld...", jiffies);
+
+	outw(option_reg & ~(NICReset + ChipReset), ioaddr + HPP_OPTION);
+	/* Pause a few cycles for the hardware reset to take place. */
+	udelay(5);
+	ei_status.txing = 0;
+	outw(option_reg | (EnableIRQ + NICReset + ChipReset), ioaddr + HPP_OPTION);
+
+	udelay(5);
+
+
+	if ((inb_p(ioaddr+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0)
+		printk("%s: hp_reset_8390() did not complete.\n", dev->name);
+
+	if (ei_debug > 1) printk("8390 reset done (%ld).", jiffies);
+}
+
+/* The programmed-I/O version of reading the 4 byte 8390 specific header.
+   Note that transfer with the EtherTwist+ must be on word boundaries. */
+
+static void
+hpp_io_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	int ioaddr = dev->base_addr - NIC_OFFSET;
+
+	outw((ring_page<<8), ioaddr + HPP_IN_ADDR);
+	insw(ioaddr + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+}
+
+/* Block input and output, similar to the Crynwr packet driver. */
+
+static void
+hpp_io_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+	int ioaddr = dev->base_addr - NIC_OFFSET;
+	char *buf = skb->data;
+
+	outw(ring_offset, ioaddr + HPP_IN_ADDR);
+	insw(ioaddr + HP_DATAPORT, buf, count>>1);
+	if (count & 0x01)
+        buf[count-1] = inw(ioaddr + HP_DATAPORT);
+}
+
+/* The corresponding shared memory versions of the above 2 functions. */
+
+static void
+hpp_mem_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	int ioaddr = dev->base_addr - NIC_OFFSET;
+	int option_reg = inw(ioaddr + HPP_OPTION);
+
+	outw((ring_page<<8), ioaddr + HPP_IN_ADDR);
+	outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
+	memcpy_fromio(hdr, ei_status.mem, sizeof(struct e8390_pkt_hdr));
+	outw(option_reg, ioaddr + HPP_OPTION);
+	hdr->count = (le16_to_cpu(hdr->count) + 3) & ~3;	/* Round up allocation. */
+}
+
+static void
+hpp_mem_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+	int ioaddr = dev->base_addr - NIC_OFFSET;
+	int option_reg = inw(ioaddr + HPP_OPTION);
+
+	outw(ring_offset, ioaddr + HPP_IN_ADDR);
+
+	outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
+
+	/* Caution: this relies on get_8390_hdr() rounding up count!
+	   Also note that we *can't* use eth_io_copy_and_sum() because
+	   it will not always copy "count" bytes (e.g. padded IP).  */
+
+	memcpy_fromio(skb->data, ei_status.mem, count);
+	outw(option_reg, ioaddr + HPP_OPTION);
+}
+
+/* A special note: we *must* always transfer >=16 bit words.
+   It's always safe to round up, so we do. */
+static void
+hpp_io_block_output(struct net_device *dev, int count,
+					const unsigned char *buf, int start_page)
+{
+	int ioaddr = dev->base_addr - NIC_OFFSET;
+	outw(start_page << 8, ioaddr + HPP_OUT_ADDR);
+	outsl(ioaddr + HP_DATAPORT, buf, (count+3)>>2);
+}
+
+static void
+hpp_mem_block_output(struct net_device *dev, int count,
+				const unsigned char *buf, int start_page)
+{
+	int ioaddr = dev->base_addr - NIC_OFFSET;
+	int option_reg = inw(ioaddr + HPP_OPTION);
+
+	outw(start_page << 8, ioaddr + HPP_OUT_ADDR);
+	outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
+	memcpy_toio(ei_status.mem, buf, (count + 3) & ~3);
+	outw(option_reg, ioaddr + HPP_OPTION);
+}
+
+
+#ifdef MODULE
+#define MAX_HPP_CARDS	4	/* Max number of HPP cards per module */
+static struct net_device *dev_hpp[MAX_HPP_CARDS];
+static int io[MAX_HPP_CARDS];
+static int irq[MAX_HPP_CARDS];
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O port address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s); ignored if properly detected");
+MODULE_DESCRIPTION("HP PC-LAN+ ISA ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* This is set up so that only a single autoprobe takes place per call.
+ISA device autoprobes on a running machine are not recommended. */
+int __init
+init_module(void)
+{
+	struct net_device *dev;
+	int this_dev, found = 0;
+
+	for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) {
+		if (io[this_dev] == 0)  {
+			if (this_dev != 0) break; /* only autoprobe 1st one */
+			printk(KERN_NOTICE "hp-plus.c: Presently autoprobing (not recommended) for a single card.\n");
+		}
+		dev = alloc_eip_netdev();
+		if (!dev)
+			break;
+		dev->irq = irq[this_dev];
+		dev->base_addr = io[this_dev];
+		if (do_hpp_probe(dev) == 0) {
+			dev_hpp[found++] = dev;
+			continue;
+		}
+		free_netdev(dev);
+		printk(KERN_WARNING "hp-plus.c: No HP-Plus card found (i/o = 0x%x).\n", io[this_dev]);
+		break;
+	}
+	if (found)
+		return 0;
+	return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+	/* NB: hpp_close() handles free_irq */
+	iounmap(ei_status.mem);
+	release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
+}
+
+void __exit
+cleanup_module(void)
+{
+	int this_dev;
+
+	for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) {
+		struct net_device *dev = dev_hpp[this_dev];
+		if (dev) {
+			unregister_netdev(dev);
+			cleanup_card(dev);
+			free_netdev(dev);
+		}
+	}
+}
+#endif /* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/hydra.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/hydra.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/hydra.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/hydra.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,273 @@
+/* New Hydra driver using generic 8390 core */
+/* Based on old hydra driver by Topi Kanerva (topi@susanna.oulu.fi) */
+
+/* This file is subject to the terms and conditions of the GNU General      */
+/* Public License.  See the file COPYING in the main directory of the       */
+/* Linux distribution for more details.                                     */
+
+/* Peter De Schrijver (p2@mind.be) */
+/* Oldenburg 2000 */
+
+/* The Amiganet is a Zorro-II board made by Hydra Systems. It contains a    */
+/* NS8390 NIC (network interface controller) clone, 16 or 64K on-board RAM  */
+/* and 10BASE-2 (thin coax) and AUI connectors.                             */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+#include <linux/zorro.h>
+
+#define EI_SHIFT(x)	(ei_local->reg_offset[x])
+#define ei_inb(port)   in_8(port)
+#define ei_outb(val,port)  out_8(port,val)
+#define ei_inb_p(port)   in_8(port)
+#define ei_outb_p(val,port)  out_8(port,val)
+
+static const char version[] =
+    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include "lib8390.c"
+
+#define NE_EN0_DCFG     (0x0e*2)
+
+#define NESM_START_PG   0x0    /* First page of TX buffer */
+#define NESM_STOP_PG    0x40    /* Last page +1 of RX ring */
+
+#define HYDRA_NIC_BASE 0xffe1
+#define HYDRA_ADDRPROM 0xffc0
+#define HYDRA_VERSION "v3.0alpha"
+
+#define WORDSWAP(a)     ((((a)>>8)&0xff) | ((a)<<8))
+
+
+static int __devinit hydra_init_one(struct zorro_dev *z,
+				    const struct zorro_device_id *ent);
+static int __devinit hydra_init(struct zorro_dev *z);
+static int hydra_open(struct net_device *dev);
+static int hydra_close(struct net_device *dev);
+static void hydra_reset_8390(struct net_device *dev);
+static void hydra_get_8390_hdr(struct net_device *dev,
+			       struct e8390_pkt_hdr *hdr, int ring_page);
+static void hydra_block_input(struct net_device *dev, int count,
+			      struct sk_buff *skb, int ring_offset);
+static void hydra_block_output(struct net_device *dev, int count,
+			       const unsigned char *buf, int start_page);
+static void __devexit hydra_remove_one(struct zorro_dev *z);
+
+static struct zorro_device_id hydra_zorro_tbl[] __devinitdata = {
+    { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET },
+    { 0 }
+};
+MODULE_DEVICE_TABLE(zorro, hydra_zorro_tbl);
+
+static struct zorro_driver hydra_driver = {
+    .name	= "hydra",
+    .id_table	= hydra_zorro_tbl,
+    .probe	= hydra_init_one,
+    .remove	= __devexit_p(hydra_remove_one),
+};
+
+static int __devinit hydra_init_one(struct zorro_dev *z,
+				    const struct zorro_device_id *ent)
+{
+    int err;
+
+    if (!request_mem_region(z->resource.start, 0x10000, "Hydra"))
+	return -EBUSY;
+    if ((err = hydra_init(z))) {
+	release_mem_region(z->resource.start, 0x10000);
+	return -EBUSY;
+    }
+    return 0;
+}
+
+static const struct net_device_ops hydra_netdev_ops = {
+	.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_rx_mode	= __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,
+#endif
+};
+
+static int __devinit hydra_init(struct zorro_dev *z)
+{
+    struct net_device *dev;
+    unsigned long board = ZTWO_VADDR(z->resource.start);
+    unsigned long ioaddr = board+HYDRA_NIC_BASE;
+    const char name[] = "NE2000";
+    int start_page, stop_page;
+    int j;
+    int err;
+
+    static u32 hydra_offsets[16] = {
+	0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
+    };
+
+    dev = ____alloc_ei_netdev(0);
+    if (!dev)
+	return -ENOMEM;
+
+    for(j = 0; j < ETHER_ADDR_LEN; j++)
+	dev->dev_addr[j] = *((u8 *)(board + HYDRA_ADDRPROM + 2*j));
+
+    /* We must set the 8390 for word mode. */
+    z_writeb(0x4b, ioaddr + NE_EN0_DCFG);
+    start_page = NESM_START_PG;
+    stop_page = NESM_STOP_PG;
+
+    dev->base_addr = ioaddr;
+    dev->irq = IRQ_AMIGA_PORTS;
+
+    /* Install the Interrupt handler */
+    if (request_irq(IRQ_AMIGA_PORTS, __ei_interrupt, IRQF_SHARED, "Hydra Ethernet",
+		    dev)) {
+	free_netdev(dev);
+	return -EAGAIN;
+    }
+
+    ei_status.name = name;
+    ei_status.tx_start_page = start_page;
+    ei_status.stop_page = stop_page;
+    ei_status.word16 = 1;
+    ei_status.bigendian = 1;
+
+    ei_status.rx_start_page = start_page + TX_PAGES;
+
+    ei_status.reset_8390 = hydra_reset_8390;
+    ei_status.block_input = hydra_block_input;
+    ei_status.block_output = hydra_block_output;
+    ei_status.get_8390_hdr = hydra_get_8390_hdr;
+    ei_status.reg_offset = hydra_offsets;
+
+    dev->netdev_ops = &hydra_netdev_ops;
+    __NS8390_init(dev, 0);
+
+    err = register_netdev(dev);
+    if (err) {
+	free_irq(IRQ_AMIGA_PORTS, dev);
+	free_netdev(dev);
+	return err;
+    }
+
+    zorro_set_drvdata(z, dev);
+
+    pr_info("%s: Hydra at %pR, address %pM (hydra.c " HYDRA_VERSION ")\n",
+	    dev->name, &z->resource, dev->dev_addr);
+
+    return 0;
+}
+
+static int hydra_open(struct net_device *dev)
+{
+    __ei_open(dev);
+    return 0;
+}
+
+static int hydra_close(struct net_device *dev)
+{
+    if (ei_debug > 1)
+	printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
+    __ei_close(dev);
+    return 0;
+}
+
+static void hydra_reset_8390(struct net_device *dev)
+{
+    printk(KERN_INFO "Hydra hw reset not there\n");
+}
+
+static void hydra_get_8390_hdr(struct net_device *dev,
+			       struct e8390_pkt_hdr *hdr, int ring_page)
+{
+    int nic_base = dev->base_addr;
+    short *ptrs;
+    unsigned long hdr_start= (nic_base-HYDRA_NIC_BASE) +
+			     ((ring_page - NESM_START_PG)<<8);
+    ptrs = (short *)hdr;
+
+    *(ptrs++) = z_readw(hdr_start);
+    *((short *)hdr) = WORDSWAP(*((short *)hdr));
+    hdr_start += 2;
+    *(ptrs++) = z_readw(hdr_start);
+    *((short *)hdr+1) = WORDSWAP(*((short *)hdr+1));
+}
+
+static void hydra_block_input(struct net_device *dev, int count,
+			      struct sk_buff *skb, int ring_offset)
+{
+    unsigned long nic_base = dev->base_addr;
+    unsigned long mem_base = nic_base - HYDRA_NIC_BASE;
+    unsigned long xfer_start = mem_base + ring_offset - (NESM_START_PG<<8);
+
+    if (count&1)
+	count++;
+
+    if (xfer_start+count >  mem_base + (NESM_STOP_PG<<8)) {
+	int semi_count = (mem_base + (NESM_STOP_PG<<8)) - xfer_start;
+
+	z_memcpy_fromio(skb->data,xfer_start,semi_count);
+	count -= semi_count;
+	z_memcpy_fromio(skb->data+semi_count, mem_base, count);
+    } else
+	z_memcpy_fromio(skb->data, xfer_start,count);
+
+}
+
+static void hydra_block_output(struct net_device *dev, int count,
+			       const unsigned char *buf, int start_page)
+{
+    unsigned long nic_base = dev->base_addr;
+    unsigned long mem_base = nic_base - HYDRA_NIC_BASE;
+
+    if (count&1)
+	count++;
+
+    z_memcpy_toio(mem_base+((start_page - NESM_START_PG)<<8), buf, count);
+}
+
+static void __devexit hydra_remove_one(struct zorro_dev *z)
+{
+    struct net_device *dev = zorro_get_drvdata(z);
+
+    unregister_netdev(dev);
+    free_irq(IRQ_AMIGA_PORTS, dev);
+    release_mem_region(ZTWO_PADDR(dev->base_addr)-HYDRA_NIC_BASE, 0x10000);
+    free_netdev(dev);
+}
+
+static int __init hydra_init_module(void)
+{
+    return zorro_register_driver(&hydra_driver);
+}
+
+static void __exit hydra_cleanup_module(void)
+{
+    zorro_unregister_driver(&hydra_driver);
+}
+
+module_init(hydra_init_module);
+module_exit(hydra_cleanup_module);
+
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/Kconfig linux-libre-3.2-gnu/drivers/net/ethernet/8390/Kconfig
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,337 @@
+#
+# 8390 device configuration
+#
+
+config NET_VENDOR_8390
+	bool "National Semi-conductor 8390 devices"
+	default y
+	depends on NET_VENDOR_NATSEMI && (AMIGA_PCMCIA || PCI || SUPERH || \
+		   ISA || MCA || EISA || MAC || M32R || MACH_TX49XX || \
+		   MCA_LEGACY || H8300 || ARM || MIPS || ZORRO || PCMCIA || \
+		   EXPERIMENTAL)
+	---help---
+	  If you have a network (Ethernet) card belonging to this class, say Y
+	  and read the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  Note that the answer to this question doesn't directly affect the
+	  kernel: saying N will just cause the configurator to skip all
+	  the questions about Western Digital cards. If you say Y, you will be
+	  asked for your specific card in the following questions.
+
+if NET_VENDOR_8390
+
+config EL2
+	tristate "3c503 \"EtherLink II\" support"
+	depends on ISA
+	select CRC32
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called 3c503.
+
+config AC3200
+	tristate "Ansel Communications EISA 3200 support (EXPERIMENTAL)"
+	depends on PCI && (ISA || EISA) && EXPERIMENTAL
+	select CRC32
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called ac3200.
+
+config PCMCIA_AXNET
+	tristate "Asix AX88190 PCMCIA support"
+	depends on PCMCIA
+	---help---
+	  Say Y here if you intend to attach an Asix AX88190-based PCMCIA
+	  (PC-card) Fast Ethernet card to your computer.  These cards are
+	  nearly NE2000 compatible but need a separate driver due to a few
+	  misfeatures.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called axnet_cs.  If unsure, say N.
+
+config AX88796
+	tristate "ASIX AX88796 NE2000 clone support"
+	depends on (ARM || MIPS || SUPERH)
+	select PHYLIB
+	select MDIO_BITBANG
+	---help---
+	  AX88796 driver, using platform bus to provide
+	  chip detection and resources
+
+config AX88796_93CX6
+	bool "ASIX AX88796 external 93CX6 eeprom support"
+	depends on AX88796
+	select EEPROM_93CX6
+	---help---
+	  Select this if your platform comes with an external 93CX6 eeprom.
+
+config E2100
+	tristate "Cabletron E21xx support"
+	depends on ISA
+	select CRC32
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called e2100.
+
+config ES3210
+	tristate "Racal-Interlan EISA ES3210 support (EXPERIMENTAL)"
+	depends on PCI && EISA && EXPERIMENTAL
+	select CRC32
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called es3210.
+
+config HPLAN_PLUS
+	tristate "HP PCLAN+ (27247B and 27252A) support"
+	depends on ISA
+	select CRC32
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called hp-plus.
+
+config HPLAN
+	tristate "HP PCLAN (27245 and other 27xxx series) support"
+	depends on ISA
+	select CRC32
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called hp.
+
+config HYDRA
+	tristate "Hydra support"
+	depends on ZORRO
+	select CRC32
+	---help---
+	  If you have a Hydra Ethernet adapter, say Y. Otherwise, say N.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called hydra.
+
+config ARM_ETHERH
+	tristate "I-cubed EtherH/ANT EtherM support"
+	depends on ARM && ARCH_ACORN
+	select CRC32
+	---help---
+	  If you have an Acorn system with one of these network cards, you
+	  should say Y to this option if you wish to use it with Linux.
+
+config LNE390
+	tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)"
+	depends on PCI && EISA && EXPERIMENTAL
+	select CRC32
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called lne390.
+
+config MAC8390
+	bool "Macintosh NS 8390 based ethernet cards"
+	depends on MAC
+	select CRC32
+	---help---
+	  If you want to include a driver to support Nubus or LC-PDS
+	  Ethernet cards using an NS8390 chipset or its equivalent, say Y
+	  and read the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+config NE2000
+	tristate "NE2000/NE1000 support"
+	depends on (ISA || (Q40 && m) || M32R || MACH_TX49XX)
+	select CRC32
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.  Many Ethernet cards
+	  without a specific driver are compatible with NE2000.
+
+	  If you have a PCI NE2000 card however, say N here and Y to "PCI
+	  NE2000 and clone support" under "EISA, VLB, PCI and on board
+	  controllers" below. If you have a NE2000 card and are running on
+	  an MCA system (a bus system used on some IBM PS/2 computers and
+	  laptops), say N here and Y to "NE/2 (ne2000 MCA version) support",
+	  below.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called ne.
+
+config NE2_MCA
+	tristate "NE/2 (ne2000 MCA version) support"
+	depends on MCA_LEGACY
+	select CRC32
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called ne2.
+
+config NE2K_PCI
+	tristate "PCI NE2000 and clones support (see help)"
+	depends on PCI
+	select CRC32
+	---help---
+	  This driver is for NE2000 compatible PCI cards. It will not work
+	  with ISA NE2000 cards (they have their own driver, "NE2000/NE1000
+	  support" below). If you have a PCI NE2000 network (Ethernet) card,
+	  say Y and read the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  This driver also works for the following NE2000 clone cards:
+	  RealTek RTL-8029  Winbond 89C940  Compex RL2000  KTI ET32P2
+	  NetVin NV5000SC   Via 86C926      SureCom NE34   Winbond
+	  Holtek HT80232    Holtek HT80229
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called ne2k-pci.
+
+config APNE
+	tristate "PCMCIA NE2000 support"
+	depends on AMIGA_PCMCIA
+	select CRC32
+	---help---
+	  If you have a PCMCIA NE2000 compatible adapter, say Y.  Otherwise,
+	  say N.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called apne.
+
+config NE3210
+	tristate "Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)"
+	depends on PCI && EISA && EXPERIMENTAL
+	select CRC32
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.  Note that this driver
+	  will NOT WORK for NE3200 cards as they are completely different.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called ne3210.
+
+config PCMCIA_PCNET
+	tristate "NE2000 compatible PCMCIA support"
+	depends on PCMCIA
+	select CRC32
+	---help---
+	  Say Y here if you intend to attach an NE2000 compatible PCMCIA
+	  (PC-card) Ethernet or Fast Ethernet card to your computer.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called pcnet_cs.  If unsure, say N.
+
+config NE_H8300
+	tristate "NE2000 compatible support for H8/300"
+	depends on H8300
+	---help---
+	  Say Y here if you want to use the NE2000 compatible
+	  controller on the Renesas H8/300 processor.
+
+config STNIC
+	tristate "National DP83902AV  support"
+	depends on SUPERH
+	select CRC32
+	---help---
+	  Support for cards based on the National Semiconductor DP83902AV
+	  ST-NIC Serial Network Interface Controller for Twisted Pair.  This
+	  is a 10Mbit/sec Ethernet controller.  Product overview and specs at
+	  <http://www.national.com/pf/DP/DP83902A.html>.
+
+	  If unsure, say N.
+
+config ULTRAMCA
+	tristate "SMC Ultra MCA support"
+	depends on MCA
+	select CRC32
+	---help---
+	  If you have a network (Ethernet) card of this type and are running
+	  an MCA based system (PS/2), say Y and read the Ethernet-HOWTO,
+	  available from <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called smc-mca.
+
+config ULTRA
+	tristate "SMC Ultra support"
+	depends on ISA
+	select CRC32
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  Important: There have been many reports that, with some motherboards
+	  mixing an SMC Ultra and an Adaptec AHA154x SCSI card (or compatible,
+	  such as some BusLogic models) causes corruption problems with many
+	  operating systems. The Linux smc-ultra driver has a work-around for
+	  this but keep it in mind if you have such a SCSI card and have
+	  problems.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called smc-ultra.
+
+config ULTRA32
+	tristate "SMC Ultra32 EISA support"
+	depends on EISA
+	select CRC32
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called smc-ultra32.
+
+config WD80x3
+	tristate "WD80*3 support"
+	depends on ISA
+	select CRC32
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called wd.
+
+config ZORRO8390
+	tristate "Zorro NS8390-based Ethernet support"
+	depends on ZORRO
+	select CRC32
+	---help---
+	  This driver is for Zorro Ethernet cards using an NS8390-compatible
+	  chipset, like the Village Tronic Ariadne II and the Individual
+	  Computers X-Surf Ethernet cards. If you have such a card, say Y.
+	  Otherwise, say N.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called zorro8390.
+
+endif # NET_VENDOR_8390
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/lib8390.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/lib8390.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/lib8390.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/lib8390.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1080 @@
+/* 8390.c: A general NS8390 ethernet driver core for linux. */
+/*
+	Written 1992-94 by Donald Becker.
+
+	Copyright 1993 United States Government as represented by the
+	Director, National Security Agency.
+
+	This software may be used and distributed according to the terms
+	of the GNU General Public License, incorporated herein by reference.
+
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+
+  This is the chip-specific code for many 8390-based ethernet adaptors.
+  This is not a complete driver, it must be combined with board-specific
+  code such as ne.c, wd.c, 3c503.c, etc.
+
+  Seeing how at least eight drivers use this code, (not counting the
+  PCMCIA ones either) it is easy to break some card by what seems like
+  a simple innocent change. Please contact me or Donald if you think
+  you have found something that needs changing. -- PG
+
+
+  Changelog:
+
+  Paul Gortmaker	: remove set_bit lock, other cleanups.
+  Paul Gortmaker	: add ei_get_8390_hdr() so we can pass skb's to
+			  ei_block_input() for eth_io_copy_and_sum().
+  Paul Gortmaker	: exchange static int ei_pingpong for a #define,
+			  also add better Tx error handling.
+  Paul Gortmaker	: rewrite Rx overrun handling as per NS specs.
+  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 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.
+  Alan Cox		: Spinlocking work, added 'BUG_83C690'
+  Paul Gortmaker	: Separate out Tx timeout code from Tx path.
+  Paul Gortmaker	: Remove old unused single Tx buffer code.
+  Hayato Fujiwara	: Add m32r support.
+  Paul Gortmaker	: use skb_padto() instead of stack scratch area
+
+  Sources:
+  The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
+
+  */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/bitops.h>
+#include <asm/system.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fcntl.h>
+#include <linux/in.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#define NS8390_CORE
+#include "8390.h"
+
+#define BUG_83C690
+
+/* These are the operational function interfaces to board-specific
+   routines.
+	void reset_8390(struct net_device *dev)
+		Resets the board associated with DEV, including a hardware reset of
+		the 8390.  This is only called when there is a transmit timeout, and
+		it is always followed by 8390_init().
+	void block_output(struct net_device *dev, int count, const unsigned char *buf,
+					  int start_page)
+		Write the COUNT bytes of BUF to the packet buffer at START_PAGE.  The
+		"page" value uses the 8390's 256-byte pages.
+	void get_8390_hdr(struct net_device *dev, struct e8390_hdr *hdr, int ring_page)
+		Read the 4 byte, page aligned 8390 header. *If* there is a
+		subsequent read, it will be of the rest of the packet.
+	void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+		Read COUNT bytes from the packet buffer into the skb data area. Start
+		reading from RING_OFFSET, the address as the 8390 sees it.  This will always
+		follow the read of the 8390 header.
+*/
+#define ei_reset_8390 (ei_local->reset_8390)
+#define ei_block_output (ei_local->block_output)
+#define ei_block_input (ei_local->block_input)
+#define ei_get_8390_hdr (ei_local->get_8390_hdr)
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#ifndef ei_debug
+int ei_debug = 1;
+#endif
+
+/* Index to functions. */
+static void ei_tx_intr(struct net_device *dev);
+static void ei_tx_err(struct net_device *dev);
+static void ei_receive(struct net_device *dev);
+static void ei_rx_overrun(struct net_device *dev);
+
+/* Routines generic to NS8390-based boards. */
+static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
+								int start_page);
+static void do_set_multicast_list(struct net_device *dev);
+static void __NS8390_init(struct net_device *dev, int startp);
+
+/*
+ *	SMP and the 8390 setup.
+ *
+ *	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
+ *	before unlocking. Even pure readers must take the lock to protect in
+ *	page 0.
+ *
+ *	To make life difficult the chip can also be very slow. We therefore can't
+ *	just use spinlocks. For the longer lockups we disable the irq the device
+ *	sits on and hold the lock. We must hold the lock because there is a dual
+ *	processor case other than interrupts (get stats/set multicast list in
+ *	parallel with each other and transmit).
+ *
+ *	Note: in theory we can just disable the irq on the card _but_ there is
+ *	a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs"
+ *	enter lock, take the queued irq. So we waddle instead of flying.
+ *
+ *	Finally by special arrangement for the purpose of being generally
+ *	annoying the transmit function is called bh atomic. That places
+ *	restrictions on the user context callers as disable_irq won't save
+ *	them.
+ *
+ *	Additional explanation of problems with locking by Alan Cox:
+ *
+ *	"The author (me) didn't use spin_lock_irqsave because the slowness of the
+ *	card means that approach caused horrible problems like losing serial data
+ *	at 38400 baud on some chips. Remember many 8390 nics on PCI were ISA
+ *	chips with FPGA front ends.
+ *
+ *	Ok the logic behind the 8390 is very simple:
+ *
+ *	Things to know
+ *		- IRQ delivery is asynchronous to the PCI bus
+ *		- Blocking the local CPU IRQ via spin locks was too slow
+ *		- The chip has register windows needing locking work
+ *
+ *	So the path was once (I say once as people appear to have changed it
+ *	in the mean time and it now looks rather bogus if the changes to use
+ *	disable_irq_nosync_irqsave are disabling the local IRQ)
+ *
+ *
+ *		Take the page lock
+ *		Mask the IRQ on chip
+ *		Disable the IRQ (but not mask locally- someone seems to have
+ *			broken this with the lock validator stuff)
+ *			[This must be _nosync as the page lock may otherwise
+ *				deadlock us]
+ *		Drop the page lock and turn IRQs back on
+ *
+ *		At this point an existing IRQ may still be running but we can't
+ *		get a new one
+ *
+ *		Take the lock (so we know the IRQ has terminated) but don't mask
+ *	the IRQs on the processor
+ *		Set irqlock [for debug]
+ *
+ *		Transmit (slow as ****)
+ *
+ *		re-enable the IRQ
+ *
+ *
+ *	We have to use disable_irq because otherwise you will get delayed
+ *	interrupts on the APIC bus deadlocking the transmit path.
+ *
+ *	Quite hairy but the chip simply wasn't designed for SMP and you can't
+ *	even ACK an interrupt without risking corrupting other parallel
+ *	activities on the chip." [lkml, 25 Jul 2007]
+ */
+
+
+
+/**
+ * ei_open - Open/initialize the board.
+ * @dev: network device to initialize
+ *
+ * This routine goes all-out, setting everything
+ * up anew at each open, even though many of these registers should only
+ * need to be set once at boot.
+ */
+static int __ei_open(struct net_device *dev)
+{
+	unsigned long flags;
+	struct ei_device *ei_local = netdev_priv(dev);
+
+	if (dev->watchdog_timeo <= 0)
+		dev->watchdog_timeo = TX_TIMEOUT;
+
+	/*
+	 *	Grab the page lock so we own the register set, then call
+	 *	the init function.
+	 */
+
+	spin_lock_irqsave(&ei_local->page_lock, flags);
+	__NS8390_init(dev, 1);
+	/* Set the flag before we drop the lock, That way the IRQ arrives
+	   after its set and we get no silly warnings */
+	netif_start_queue(dev);
+	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+	ei_local->irqlock = 0;
+	return 0;
+}
+
+/**
+ * ei_close - shut down network device
+ * @dev: network device to close
+ *
+ * Opposite of ei_open(). Only used when "ifconfig <devname> down" is done.
+ */
+static int __ei_close(struct net_device *dev)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	unsigned long flags;
+
+	/*
+	 *	Hold the page lock during close
+	 */
+
+	spin_lock_irqsave(&ei_local->page_lock, flags);
+	__NS8390_init(dev, 0);
+	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+	netif_stop_queue(dev);
+	return 0;
+}
+
+/**
+ * ei_tx_timeout - handle transmit time out condition
+ * @dev: network device which has apparently fallen asleep
+ *
+ * Called by kernel when device never acknowledges a transmit has
+ * completed (or failed) - i.e. never posted a Tx related interrupt.
+ */
+
+static void __ei_tx_timeout(struct net_device *dev)
+{
+	unsigned long e8390_base = dev->base_addr;
+	struct ei_device *ei_local = netdev_priv(dev);
+	int txsr, isr, tickssofar = jiffies - dev_trans_start(dev);
+	unsigned long flags;
+
+	dev->stats.tx_errors++;
+
+	spin_lock_irqsave(&ei_local->page_lock, flags);
+	txsr = ei_inb(e8390_base+EN0_TSR);
+	isr = ei_inb(e8390_base+EN0_ISR);
+	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+	netdev_dbg(dev, "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d\n",
+		   (txsr & ENTSR_ABT) ? "excess collisions." :
+		   (isr) ? "lost interrupt?" : "cable problem?",
+		   txsr, isr, tickssofar);
+
+	if (!isr && !dev->stats.tx_packets) {
+		/* The 8390 probably hasn't gotten on the cable yet. */
+		ei_local->interface_num ^= 1;   /* Try a different xcvr.  */
+	}
+
+	/* Ugly but a reset can be slow, yet must be protected */
+
+	disable_irq_nosync_lockdep(dev->irq);
+	spin_lock(&ei_local->page_lock);
+
+	/* Try to restart the card.  Perhaps the user has fixed something. */
+	ei_reset_8390(dev);
+	__NS8390_init(dev, 1);
+
+	spin_unlock(&ei_local->page_lock);
+	enable_irq_lockdep(dev->irq);
+	netif_wake_queue(dev);
+}
+
+/**
+ * ei_start_xmit - begin packet transmission
+ * @skb: packet to be sent
+ * @dev: network device to which packet is sent
+ *
+ * Sends a packet to an 8390 network device.
+ */
+
+static netdev_tx_t __ei_start_xmit(struct sk_buff *skb,
+				   struct net_device *dev)
+{
+	unsigned long e8390_base = dev->base_addr;
+	struct ei_device *ei_local = netdev_priv(dev);
+	int send_length = skb->len, output_page;
+	unsigned long flags;
+	char buf[ETH_ZLEN];
+	char *data = skb->data;
+
+	if (skb->len < ETH_ZLEN) {
+		memset(buf, 0, ETH_ZLEN);	/* more efficient than doing just the needed bits */
+		memcpy(buf, data, skb->len);
+		send_length = ETH_ZLEN;
+		data = buf;
+	}
+
+	/* Mask interrupts from the ethercard.
+	   SMP: We have to grab the lock here otherwise the IRQ handler
+	   on another CPU can flip window and race the IRQ mask set. We end
+	   up trashing the mcast filter not disabling irqs if we don't lock */
+
+	spin_lock_irqsave(&ei_local->page_lock, flags);
+	ei_outb_p(0x00, e8390_base + EN0_IMR);
+	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+
+	/*
+	 *	Slow phase with lock held.
+	 */
+
+	disable_irq_nosync_lockdep_irqsave(dev->irq, &flags);
+
+	spin_lock(&ei_local->page_lock);
+
+	ei_local->irqlock = 1;
+
+	/*
+	 * We have two Tx slots available for use. Find the first free
+	 * slot, and then perform some sanity checks. With two Tx bufs,
+	 * you get very close to transmitting back-to-back packets. With
+	 * only one Tx buf, the transmitter sits idle while you reload the
+	 * card, leaving a substantial gap between each transmitted packet.
+	 */
+
+	if (ei_local->tx1 == 0) {
+		output_page = ei_local->tx_start_page;
+		ei_local->tx1 = send_length;
+		if (ei_debug  &&  ei_local->tx2 > 0)
+			netdev_dbg(dev, "idle transmitter tx2=%d, lasttx=%d, txing=%d\n",
+				   ei_local->tx2, ei_local->lasttx, ei_local->txing);
+	} else if (ei_local->tx2 == 0) {
+		output_page = ei_local->tx_start_page + TX_PAGES/2;
+		ei_local->tx2 = send_length;
+		if (ei_debug  &&  ei_local->tx1 > 0)
+			netdev_dbg(dev, "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n",
+				   ei_local->tx1, ei_local->lasttx, ei_local->txing);
+	} else {			/* We should never get here. */
+		if (ei_debug)
+			netdev_dbg(dev, "No Tx buffers free! tx1=%d tx2=%d last=%d\n",
+				   ei_local->tx1, ei_local->tx2, ei_local->lasttx);
+		ei_local->irqlock = 0;
+		netif_stop_queue(dev);
+		ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+		spin_unlock(&ei_local->page_lock);
+		enable_irq_lockdep_irqrestore(dev->irq, &flags);
+		dev->stats.tx_errors++;
+		return NETDEV_TX_BUSY;
+	}
+
+	/*
+	 * Okay, now upload the packet and trigger a send if the transmitter
+	 * isn't already sending. If it is busy, the interrupt handler will
+	 * trigger the send later, upon receiving a Tx done interrupt.
+	 */
+
+	ei_block_output(dev, send_length, data, output_page);
+
+	if (!ei_local->txing) {
+		ei_local->txing = 1;
+		NS8390_trigger_send(dev, send_length, output_page);
+		if (output_page == ei_local->tx_start_page) {
+			ei_local->tx1 = -1;
+			ei_local->lasttx = -1;
+		} else {
+			ei_local->tx2 = -1;
+			ei_local->lasttx = -2;
+		}
+	} else
+		ei_local->txqueue++;
+
+	if (ei_local->tx1  &&  ei_local->tx2)
+		netif_stop_queue(dev);
+	else
+		netif_start_queue(dev);
+
+	/* Turn 8390 interrupts back on. */
+	ei_local->irqlock = 0;
+	ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+
+	spin_unlock(&ei_local->page_lock);
+	enable_irq_lockdep_irqrestore(dev->irq, &flags);
+	skb_tx_timestamp(skb);
+	dev_kfree_skb(skb);
+	dev->stats.tx_bytes += send_length;
+
+	return NETDEV_TX_OK;
+}
+
+/**
+ * ei_interrupt - handle the interrupts from an 8390
+ * @irq: interrupt number
+ * @dev_id: a pointer to the net_device
+ *
+ * Handle the ether interface interrupts. We pull packets from
+ * the 8390 via the card specific functions and fire them at the networking
+ * stack. We also handle transmit completions and wake the transmit path if
+ * necessary. We also update the counters and do other housekeeping as
+ * needed.
+ */
+
+static irqreturn_t __ei_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	unsigned long e8390_base = dev->base_addr;
+	int interrupts, nr_serviced = 0;
+	struct ei_device *ei_local = netdev_priv(dev);
+
+	/*
+	 *	Protect the irq test too.
+	 */
+
+	spin_lock(&ei_local->page_lock);
+
+	if (ei_local->irqlock) {
+		/*
+		 * This might just be an interrupt for a PCI device sharing
+		 * this line
+		 */
+		netdev_err(dev, "Interrupted while interrupts are masked! isr=%#2x imr=%#2x\n",
+			   ei_inb_p(e8390_base + EN0_ISR),
+			   ei_inb_p(e8390_base + EN0_IMR));
+		spin_unlock(&ei_local->page_lock);
+		return IRQ_NONE;
+	}
+
+	/* Change to page 0 and read the intr status reg. */
+	ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
+	if (ei_debug > 3)
+		netdev_dbg(dev, "interrupt(isr=%#2.2x)\n",
+			   ei_inb_p(e8390_base + EN0_ISR));
+
+	/* !!Assumption!! -- we stay in page 0.	 Don't break this. */
+	while ((interrupts = ei_inb_p(e8390_base + EN0_ISR)) != 0 &&
+	       ++nr_serviced < MAX_SERVICE) {
+		if (!netif_running(dev)) {
+			netdev_warn(dev, "interrupt from stopped card\n");
+			/* rmk - acknowledge the interrupts */
+			ei_outb_p(interrupts, e8390_base + EN0_ISR);
+			interrupts = 0;
+			break;
+		}
+		if (interrupts & ENISR_OVER)
+			ei_rx_overrun(dev);
+		else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) {
+			/* Got a good (?) packet. */
+			ei_receive(dev);
+		}
+		/* Push the next to-transmit packet through. */
+		if (interrupts & ENISR_TX)
+			ei_tx_intr(dev);
+		else if (interrupts & ENISR_TX_ERR)
+			ei_tx_err(dev);
+
+		if (interrupts & ENISR_COUNTERS) {
+			dev->stats.rx_frame_errors += ei_inb_p(e8390_base + EN0_COUNTER0);
+			dev->stats.rx_crc_errors   += ei_inb_p(e8390_base + EN0_COUNTER1);
+			dev->stats.rx_missed_errors += ei_inb_p(e8390_base + EN0_COUNTER2);
+			ei_outb_p(ENISR_COUNTERS, e8390_base + EN0_ISR); /* Ack intr. */
+		}
+
+		/* Ignore any RDC interrupts that make it back to here. */
+		if (interrupts & ENISR_RDC)
+			ei_outb_p(ENISR_RDC, e8390_base + EN0_ISR);
+
+		ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
+	}
+
+	if (interrupts && ei_debug) {
+		ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
+		if (nr_serviced >= MAX_SERVICE) {
+			/* 0xFF is valid for a card removal */
+			if (interrupts != 0xFF)
+				netdev_warn(dev, "Too much work at interrupt, status %#2.2x\n",
+					    interrupts);
+			ei_outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
+		} else {
+			netdev_warn(dev, "unknown interrupt %#2x\n", interrupts);
+			ei_outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
+		}
+	}
+	spin_unlock(&ei_local->page_lock);
+	return IRQ_RETVAL(nr_serviced > 0);
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void __ei_poll(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	__ei_interrupt(dev->irq, dev);
+	enable_irq(dev->irq);
+}
+#endif
+
+/**
+ * ei_tx_err - handle transmitter error
+ * @dev: network device which threw the exception
+ *
+ * A transmitter error has happened. Most likely excess collisions (which
+ * is a fairly normal condition). If the error is one where the Tx will
+ * have been aborted, we try and send another one right away, instead of
+ * letting the failed packet sit and collect dust in the Tx buffer. This
+ * is a much better solution as it avoids kernel based Tx timeouts, and
+ * an unnecessary card reset.
+ *
+ * Called with lock held.
+ */
+
+static void ei_tx_err(struct net_device *dev)
+{
+	unsigned long e8390_base = dev->base_addr;
+	/* ei_local is used on some platforms via the EI_SHIFT macro */
+	struct ei_device *ei_local __maybe_unused = netdev_priv(dev);
+	unsigned char txsr = ei_inb_p(e8390_base+EN0_TSR);
+	unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
+
+#ifdef VERBOSE_ERROR_DUMP
+	netdev_dbg(dev, "transmitter error (%#2x):", txsr);
+	if (txsr & ENTSR_ABT)
+		pr_cont(" excess-collisions ");
+	if (txsr & ENTSR_ND)
+		pr_cont(" non-deferral ");
+	if (txsr & ENTSR_CRS)
+		pr_cont(" lost-carrier ");
+	if (txsr & ENTSR_FU)
+		pr_cont(" FIFO-underrun ");
+	if (txsr & ENTSR_CDH)
+		pr_cont(" lost-heartbeat ");
+	pr_cont("\n");
+#endif
+
+	ei_outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */
+
+	if (tx_was_aborted)
+		ei_tx_intr(dev);
+	else {
+		dev->stats.tx_errors++;
+		if (txsr & ENTSR_CRS)
+			dev->stats.tx_carrier_errors++;
+		if (txsr & ENTSR_CDH)
+			dev->stats.tx_heartbeat_errors++;
+		if (txsr & ENTSR_OWC)
+			dev->stats.tx_window_errors++;
+	}
+}
+
+/**
+ * ei_tx_intr - transmit interrupt handler
+ * @dev: network device for which tx intr is handled
+ *
+ * We have finished a transmit: check for errors and then trigger the next
+ * packet to be sent. Called with lock held.
+ */
+
+static void ei_tx_intr(struct net_device *dev)
+{
+	unsigned long e8390_base = dev->base_addr;
+	struct ei_device *ei_local = netdev_priv(dev);
+	int status = ei_inb(e8390_base + EN0_TSR);
+
+	ei_outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */
+
+	/*
+	 * There are two Tx buffers, see which one finished, and trigger
+	 * the send of another one if it exists.
+	 */
+	ei_local->txqueue--;
+
+	if (ei_local->tx1 < 0) {
+		if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
+			pr_err("%s: bogus last_tx_buffer %d, tx1=%d\n",
+			       ei_local->name, ei_local->lasttx, ei_local->tx1);
+		ei_local->tx1 = 0;
+		if (ei_local->tx2 > 0) {
+			ei_local->txing = 1;
+			NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
+			dev->trans_start = jiffies;
+			ei_local->tx2 = -1,
+			ei_local->lasttx = 2;
+		} else
+			ei_local->lasttx = 20, ei_local->txing = 0;
+	} else if (ei_local->tx2 < 0) {
+		if (ei_local->lasttx != 2  &&  ei_local->lasttx != -2)
+			pr_err("%s: bogus last_tx_buffer %d, tx2=%d\n",
+			       ei_local->name, ei_local->lasttx, ei_local->tx2);
+		ei_local->tx2 = 0;
+		if (ei_local->tx1 > 0) {
+			ei_local->txing = 1;
+			NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
+			dev->trans_start = jiffies;
+			ei_local->tx1 = -1;
+			ei_local->lasttx = 1;
+		} else
+			ei_local->lasttx = 10, ei_local->txing = 0;
+	} /* else
+		netdev_warn(dev, "unexpected TX-done interrupt, lasttx=%d\n",
+			    ei_local->lasttx);
+*/
+
+	/* Minimize Tx latency: update the statistics after we restart TXing. */
+	if (status & ENTSR_COL)
+		dev->stats.collisions++;
+	if (status & ENTSR_PTX)
+		dev->stats.tx_packets++;
+	else {
+		dev->stats.tx_errors++;
+		if (status & ENTSR_ABT) {
+			dev->stats.tx_aborted_errors++;
+			dev->stats.collisions += 16;
+		}
+		if (status & ENTSR_CRS)
+			dev->stats.tx_carrier_errors++;
+		if (status & ENTSR_FU)
+			dev->stats.tx_fifo_errors++;
+		if (status & ENTSR_CDH)
+			dev->stats.tx_heartbeat_errors++;
+		if (status & ENTSR_OWC)
+			dev->stats.tx_window_errors++;
+	}
+	netif_wake_queue(dev);
+}
+
+/**
+ * ei_receive - receive some packets
+ * @dev: network device with which receive will be run
+ *
+ * We have a good packet(s), get it/them out of the buffers.
+ * Called with lock held.
+ */
+
+static void ei_receive(struct net_device *dev)
+{
+	unsigned long e8390_base = dev->base_addr;
+	struct ei_device *ei_local = netdev_priv(dev);
+	unsigned char rxing_page, this_frame, next_frame;
+	unsigned short current_offset;
+	int rx_pkt_count = 0;
+	struct e8390_pkt_hdr rx_frame;
+	int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page;
+
+	while (++rx_pkt_count < 10) {
+		int pkt_len, pkt_stat;
+
+		/* Get the rx page (incoming packet pointer). */
+		ei_outb_p(E8390_NODMA+E8390_PAGE1, e8390_base + E8390_CMD);
+		rxing_page = ei_inb_p(e8390_base + EN1_CURPAG);
+		ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
+
+		/* Remove one frame from the ring.  Boundary is always a page behind. */
+		this_frame = ei_inb_p(e8390_base + EN0_BOUNDARY) + 1;
+		if (this_frame >= ei_local->stop_page)
+			this_frame = ei_local->rx_start_page;
+
+		/* Someday we'll omit the previous, iff we never get this message.
+		   (There is at least one clone claimed to have a problem.)
+
+		   Keep quiet if it looks like a card removal. One problem here
+		   is that some clones crash in roughly the same way.
+		 */
+		if (ei_debug > 0 &&
+		    this_frame != ei_local->current_page &&
+		    (this_frame != 0x0 || rxing_page != 0xFF))
+			netdev_err(dev, "mismatched read page pointers %2x vs %2x\n",
+				   this_frame, ei_local->current_page);
+
+		if (this_frame == rxing_page)	/* Read all the frames? */
+			break;				/* Done for now */
+
+		current_offset = this_frame << 8;
+		ei_get_8390_hdr(dev, &rx_frame, this_frame);
+
+		pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr);
+		pkt_stat = rx_frame.status;
+
+		next_frame = this_frame + 1 + ((pkt_len+4)>>8);
+
+		/* Check for bogosity warned by 3c503 book: the status byte is never
+		   written.  This happened a lot during testing! This code should be
+		   cleaned up someday. */
+		if (rx_frame.next != next_frame &&
+		    rx_frame.next != next_frame + 1 &&
+		    rx_frame.next != next_frame - num_rx_pages &&
+		    rx_frame.next != next_frame + 1 - num_rx_pages) {
+			ei_local->current_page = rxing_page;
+			ei_outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY);
+			dev->stats.rx_errors++;
+			continue;
+		}
+
+		if (pkt_len < 60  ||  pkt_len > 1518) {
+			if (ei_debug)
+				netdev_dbg(dev, "bogus packet size: %d, status=%#2x nxpg=%#2x\n",
+					   rx_frame.count, rx_frame.status,
+					   rx_frame.next);
+			dev->stats.rx_errors++;
+			dev->stats.rx_length_errors++;
+		} else if ((pkt_stat & 0x0F) == ENRSR_RXOK) {
+			struct sk_buff *skb;
+
+			skb = dev_alloc_skb(pkt_len+2);
+			if (skb == NULL) {
+				if (ei_debug > 1)
+					netdev_dbg(dev, "Couldn't allocate a sk_buff of size %d\n",
+						   pkt_len);
+				dev->stats.rx_dropped++;
+				break;
+			} else {
+				skb_reserve(skb, 2);	/* IP headers on 16 byte boundaries */
+				skb_put(skb, pkt_len);	/* Make room */
+				ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
+				skb->protocol = eth_type_trans(skb, dev);
+				if (!skb_defer_rx_timestamp(skb))
+					netif_rx(skb);
+				dev->stats.rx_packets++;
+				dev->stats.rx_bytes += pkt_len;
+				if (pkt_stat & ENRSR_PHY)
+					dev->stats.multicast++;
+			}
+		} else {
+			if (ei_debug)
+				netdev_dbg(dev, "bogus packet: status=%#2x nxpg=%#2x size=%d\n",
+					   rx_frame.status, rx_frame.next,
+					   rx_frame.count);
+			dev->stats.rx_errors++;
+			/* NB: The NIC counts CRC, frame and missed errors. */
+			if (pkt_stat & ENRSR_FO)
+				dev->stats.rx_fifo_errors++;
+		}
+		next_frame = rx_frame.next;
+
+		/* This _should_ never happen: it's here for avoiding bad clones. */
+		if (next_frame >= ei_local->stop_page) {
+			netdev_notice(dev, "next frame inconsistency, %#2x\n",
+				      next_frame);
+			next_frame = ei_local->rx_start_page;
+		}
+		ei_local->current_page = next_frame;
+		ei_outb_p(next_frame-1, e8390_base+EN0_BOUNDARY);
+	}
+
+	/* We used to also ack ENISR_OVER here, but that would sometimes mask
+	   a real overrun, leaving the 8390 in a stopped state with rec'vr off. */
+	ei_outb_p(ENISR_RX+ENISR_RX_ERR, e8390_base+EN0_ISR);
+}
+
+/**
+ * ei_rx_overrun - handle receiver overrun
+ * @dev: network device which threw exception
+ *
+ * We have a receiver overrun: we have to kick the 8390 to get it started
+ * again. Problem is that you have to kick it exactly as NS prescribes in
+ * the updated datasheets, or "the NIC may act in an unpredictable manner."
+ * This includes causing "the NIC to defer indefinitely when it is stopped
+ * on a busy network."  Ugh.
+ * Called with lock held. Don't call this with the interrupts off or your
+ * computer will hate you - it takes 10ms or so.
+ */
+
+static void ei_rx_overrun(struct net_device *dev)
+{
+	unsigned long e8390_base = dev->base_addr;
+	unsigned char was_txing, must_resend = 0;
+	/* ei_local is used on some platforms via the EI_SHIFT macro */
+	struct ei_device *ei_local __maybe_unused = netdev_priv(dev);
+
+	/*
+	 * Record whether a Tx was in progress and then issue the
+	 * stop command.
+	 */
+	was_txing = ei_inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
+	ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
+
+	if (ei_debug > 1)
+		netdev_dbg(dev, "Receiver overrun\n");
+	dev->stats.rx_over_errors++;
+
+	/*
+	 * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total.
+	 * Early datasheets said to poll the reset bit, but now they say that
+	 * it "is not a reliable indicator and subsequently should be ignored."
+	 * We wait at least 10ms.
+	 */
+
+	mdelay(10);
+
+	/*
+	 * Reset RBCR[01] back to zero as per magic incantation.
+	 */
+	ei_outb_p(0x00, e8390_base+EN0_RCNTLO);
+	ei_outb_p(0x00, e8390_base+EN0_RCNTHI);
+
+	/*
+	 * See if any Tx was interrupted or not. According to NS, this
+	 * step is vital, and skipping it will cause no end of havoc.
+	 */
+
+	if (was_txing) {
+		unsigned char tx_completed = ei_inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
+		if (!tx_completed)
+			must_resend = 1;
+	}
+
+	/*
+	 * Have to enter loopback mode and then restart the NIC before
+	 * you are allowed to slurp packets up off the ring.
+	 */
+	ei_outb_p(E8390_TXOFF, e8390_base + EN0_TXCR);
+	ei_outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
+
+	/*
+	 * Clear the Rx ring of all the debris, and ack the interrupt.
+	 */
+	ei_receive(dev);
+	ei_outb_p(ENISR_OVER, e8390_base+EN0_ISR);
+
+	/*
+	 * Leave loopback mode, and resend any packet that got stopped.
+	 */
+	ei_outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR);
+	if (must_resend)
+		ei_outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
+}
+
+/*
+ *	Collect the stats. This is called unlocked and from several contexts.
+ */
+
+static struct net_device_stats *__ei_get_stats(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct ei_device *ei_local = netdev_priv(dev);
+	unsigned long flags;
+
+	/* If the card is stopped, just return the present stats. */
+	if (!netif_running(dev))
+		return &dev->stats;
+
+	spin_lock_irqsave(&ei_local->page_lock, flags);
+	/* Read the counter registers, assuming we are in page 0. */
+	dev->stats.rx_frame_errors  += ei_inb_p(ioaddr + EN0_COUNTER0);
+	dev->stats.rx_crc_errors    += ei_inb_p(ioaddr + EN0_COUNTER1);
+	dev->stats.rx_missed_errors += ei_inb_p(ioaddr + EN0_COUNTER2);
+	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+	return &dev->stats;
+}
+
+/*
+ * Form the 64 bit 8390 multicast table from the linked list of addresses
+ * associated with this dev structure.
+ */
+
+static inline void make_mc_bits(u8 *bits, struct net_device *dev)
+{
+	struct netdev_hw_addr *ha;
+
+	netdev_for_each_mc_addr(ha, dev) {
+		u32 crc = ether_crc(ETH_ALEN, ha->addr);
+		/*
+		 * The 8390 uses the 6 most significant bits of the
+		 * CRC to index the multicast table.
+		 */
+		bits[crc>>29] |= (1<<((crc>>26)&7));
+	}
+}
+
+/**
+ * do_set_multicast_list - set/clear multicast filter
+ * @dev: net device for which multicast filter is adjusted
+ *
+ *	Set or clear the multicast filter for this adaptor. May be called
+ *	from a BH in 2.1.x. Must be called with lock held.
+ */
+
+static void do_set_multicast_list(struct net_device *dev)
+{
+	unsigned long e8390_base = dev->base_addr;
+	int i;
+	struct ei_device *ei_local = netdev_priv(dev);
+
+	if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
+		memset(ei_local->mcfilter, 0, 8);
+		if (!netdev_mc_empty(dev))
+			make_mc_bits(ei_local->mcfilter, dev);
+	} else
+		memset(ei_local->mcfilter, 0xFF, 8);	/* mcast set to accept-all */
+
+	/*
+	 * DP8390 manuals don't specify any magic sequence for altering
+	 * the multicast regs on an already running card. To be safe, we
+	 * ensure multicast mode is off prior to loading up the new hash
+	 * table. If this proves to be not enough, we can always resort
+	 * to stopping the NIC, loading the table and then restarting.
+	 *
+	 * Bug Alert!  The MC regs on the SMC 83C690 (SMC Elite and SMC
+	 * Elite16) appear to be write-only. The NS 8390 data sheet lists
+	 * them as r/w so this is a bug.  The SMC 83C790 (SMC Ultra and
+	 * Ultra32 EISA) appears to have this bug fixed.
+	 */
+
+	if (netif_running(dev))
+		ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
+	ei_outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
+	for (i = 0; i < 8; i++) {
+		ei_outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
+#ifndef BUG_83C690
+		if (ei_inb_p(e8390_base + EN1_MULT_SHIFT(i)) != ei_local->mcfilter[i])
+			netdev_err(dev, "Multicast filter read/write mismap %d\n",
+				   i);
+#endif
+	}
+	ei_outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
+
+	if (dev->flags&IFF_PROMISC)
+		ei_outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
+	else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev))
+		ei_outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
+	else
+		ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
+}
+
+/*
+ *	Called without lock held. This is invoked from user context and may
+ *	be parallel to just about everything else. Its also fairly quick and
+ *	not called too often. Must protect against both bh and irq users
+ */
+
+static void __ei_set_multicast_list(struct net_device *dev)
+{
+	unsigned long flags;
+	struct ei_device *ei_local = netdev_priv(dev);
+
+	spin_lock_irqsave(&ei_local->page_lock, flags);
+	do_set_multicast_list(dev);
+	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+}
+
+/**
+ * ethdev_setup - init rest of 8390 device struct
+ * @dev: network device structure to init
+ *
+ * Initialize the rest of the 8390 device structure.  Do NOT __init
+ * this, as it is used by 8390 based modular drivers too.
+ */
+
+static void ethdev_setup(struct net_device *dev)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	if (ei_debug > 1)
+		printk(version);
+
+	ether_setup(dev);
+
+	spin_lock_init(&ei_local->page_lock);
+}
+
+/**
+ * alloc_ei_netdev - alloc_etherdev counterpart for 8390
+ * @size: extra bytes to allocate
+ *
+ * Allocate 8390-specific net_device.
+ */
+static struct net_device *____alloc_ei_netdev(int size)
+{
+	return alloc_netdev(sizeof(struct ei_device) + size, "eth%d",
+				ethdev_setup);
+}
+
+
+
+
+/* This page of functions should be 8390 generic */
+/* Follow National Semi's recommendations for initializing the "NIC". */
+
+/**
+ * NS8390_init - initialize 8390 hardware
+ * @dev: network device to initialize
+ * @startp: boolean.  non-zero value to initiate chip processing
+ *
+ *	Must be called with lock held.
+ */
+
+static void __NS8390_init(struct net_device *dev, int startp)
+{
+	unsigned long e8390_base = dev->base_addr;
+	struct ei_device *ei_local = netdev_priv(dev);
+	int i;
+	int endcfg = ei_local->word16
+	    ? (0x48 | ENDCFG_WTS | (ei_local->bigendian ? ENDCFG_BOS : 0))
+	    : 0x48;
+
+	if (sizeof(struct e8390_pkt_hdr) != 4)
+		panic("8390.c: header struct mispacked\n");
+	/* Follow National Semi's recommendations for initing the DP83902. */
+	ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */
+	ei_outb_p(endcfg, e8390_base + EN0_DCFG);	/* 0x48 or 0x49 */
+	/* Clear the remote byte count registers. */
+	ei_outb_p(0x00,  e8390_base + EN0_RCNTLO);
+	ei_outb_p(0x00,  e8390_base + EN0_RCNTHI);
+	/* Set to monitor and loopback mode -- this is vital!. */
+	ei_outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */
+	ei_outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
+	/* Set the transmit page and receive ring. */
+	ei_outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR);
+	ei_local->tx1 = ei_local->tx2 = 0;
+	ei_outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG);
+	ei_outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY);	/* 3c503 says 0x3f,NS0x26*/
+	ei_local->current_page = ei_local->rx_start_page;		/* assert boundary+1 */
+	ei_outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG);
+	/* Clear the pending interrupts and mask. */
+	ei_outb_p(0xFF, e8390_base + EN0_ISR);
+	ei_outb_p(0x00,  e8390_base + EN0_IMR);
+
+	/* Copy the station address into the DS8390 registers. */
+
+	ei_outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
+	for (i = 0; i < 6; i++) {
+		ei_outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
+		if (ei_debug > 1 &&
+		    ei_inb_p(e8390_base + EN1_PHYS_SHIFT(i)) != dev->dev_addr[i])
+			netdev_err(dev, "Hw. address read/write mismap %d\n", i);
+	}
+
+	ei_outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
+	ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
+
+	ei_local->tx1 = ei_local->tx2 = 0;
+	ei_local->txing = 0;
+
+	if (startp) {
+		ei_outb_p(0xff,  e8390_base + EN0_ISR);
+		ei_outb_p(ENISR_ALL,  e8390_base + EN0_IMR);
+		ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
+		ei_outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */
+		/* 3c503 TechMan says rxconfig only after the NIC is started. */
+		ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on,  */
+		do_set_multicast_list(dev);	/* (re)load the mcast table */
+	}
+}
+
+/* Trigger a transmit start, assuming the length is valid.
+   Always called with the page lock held */
+
+static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
+								int start_page)
+{
+	unsigned long e8390_base = dev->base_addr;
+	struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev);
+
+	ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);
+
+	if (ei_inb_p(e8390_base + E8390_CMD) & E8390_TRANS) {
+		netdev_warn(dev, "trigger_send() called with the transmitter busy\n");
+		return;
+	}
+	ei_outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
+	ei_outb_p(length >> 8, e8390_base + EN0_TCNTHI);
+	ei_outb_p(start_page, e8390_base + EN0_TPSR);
+	ei_outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD);
+}
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/lne390.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/lne390.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/lne390.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/lne390.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,434 @@
+/*
+	lne390.c
+
+	Linux driver for Mylex LNE390 EISA Network Adapter
+
+	Copyright (C) 1996-1998, Paul Gortmaker.
+
+	This software may be used and distributed according to the terms
+	of the GNU General Public License, incorporated herein by reference.
+
+	Information and Code Sources:
+
+	1) Based upon framework of es3210 driver.
+	2) The existing myriad of other Linux 8390 drivers by Donald Becker.
+	3) Russ Nelson's asm packet driver provided additional info.
+	4) Info for getting IRQ and sh-mem gleaned from the EISA cfg files.
+
+	The LNE390 is an EISA shared memory NS8390 implementation. Note
+	that all memory copies to/from the board must be 32bit transfers.
+	There are two versions of the card: the lne390a and the lne390b.
+	Going by the EISA cfg files, the "a" has jumpers to select between
+	BNC/AUI, but the "b" also has RJ-45 and selection is via the SCU.
+	The shared memory address selection is also slightly different.
+	Note that shared memory address > 1MB are supported with this driver.
+
+	You can try <http://www.mylex.com> if you want more info, as I've
+	never even seen one of these cards.  :)
+
+	Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/09/01
+	- get rid of check_region
+	- no need to check if dev == NULL in lne390_probe1
+*/
+
+static const char *version =
+	"lne390.c: Driver revision v0.99.1, 01/09/2000\n";
+
+#include <linux/module.h>
+#include <linux/eisa.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "8390.h"
+
+#define DRV_NAME "lne390"
+
+static int lne390_probe1(struct net_device *dev, int ioaddr);
+
+static void lne390_reset_8390(struct net_device *dev);
+
+static void lne390_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
+static void lne390_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset);
+static void lne390_block_output(struct net_device *dev, int count, const unsigned char *buf, const int start_page);
+
+#define LNE390_START_PG		0x00    /* First page of TX buffer	*/
+#define LNE390_STOP_PG		0x80    /* Last page +1 of RX ring	*/
+
+#define LNE390_ID_PORT		0xc80	/* Same for all EISA cards 	*/
+#define LNE390_IO_EXTENT	0x20
+#define LNE390_SA_PROM		0x16	/* Start of e'net addr.		*/
+#define LNE390_RESET_PORT	0xc84	/* From the pkt driver source	*/
+#define LNE390_NIC_OFFSET	0x00	/* Hello, the 8390 is *here*	*/
+
+#define LNE390_ADDR0		0x00	/* 3 byte vendor prefix		*/
+#define LNE390_ADDR1		0x80
+#define LNE390_ADDR2		0xe5
+
+#define LNE390_ID0	0x10009835	/* 0x3598 = 01101 01100 11000 = mlx */
+#define LNE390_ID1	0x11009835	/* above is the 390A, this is 390B  */
+
+#define LNE390_CFG1		0xc84	/* NB: 0xc84 is also "reset" port. */
+#define LNE390_CFG2		0xc90
+
+/*
+ *	You can OR any of the following bits together and assign it
+ *	to LNE390_DEBUG to get verbose driver info during operation.
+ *	Currently only the probe one is implemented.
+ */
+
+#define LNE390_D_PROBE	0x01
+#define LNE390_D_RX_PKT	0x02
+#define LNE390_D_TX_PKT	0x04
+#define LNE390_D_IRQ	0x08
+
+#define LNE390_DEBUG	0
+
+static unsigned char irq_map[] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
+static unsigned int shmem_mapA[] __initdata = {0xff, 0xfe, 0xfd, 0xfff, 0xffe, 0xffc, 0x0d, 0x0};
+static unsigned int shmem_mapB[] __initdata = {0xff, 0xfe, 0x0e, 0xfff, 0xffe, 0xffc, 0x0d, 0x0};
+
+/*
+ *	Probe for the card. The best way is to read the EISA ID if it
+ *	is known. Then we can check the prefix of the station address
+ *	PROM for a match against the value assigned to Mylex.
+ */
+
+static int __init do_lne390_probe(struct net_device *dev)
+{
+	unsigned short ioaddr = dev->base_addr;
+	int irq = dev->irq;
+	int mem_start = dev->mem_start;
+	int ret;
+
+	if (ioaddr > 0x1ff) {		/* Check a single specified location. */
+		if (!request_region(ioaddr, LNE390_IO_EXTENT, DRV_NAME))
+			return -EBUSY;
+		ret = lne390_probe1(dev, ioaddr);
+		if (ret)
+			release_region(ioaddr, LNE390_IO_EXTENT);
+		return ret;
+	}
+	else if (ioaddr > 0)		/* Don't probe at all. */
+		return -ENXIO;
+
+	if (!EISA_bus) {
+#if LNE390_DEBUG & LNE390_D_PROBE
+		printk("lne390-debug: Not an EISA bus. Not probing high ports.\n");
+#endif
+		return -ENXIO;
+	}
+
+	/* EISA spec allows for up to 16 slots, but 8 is typical. */
+	for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
+		if (!request_region(ioaddr, LNE390_IO_EXTENT, DRV_NAME))
+			continue;
+		if (lne390_probe1(dev, ioaddr) == 0)
+			return 0;
+		release_region(ioaddr, LNE390_IO_EXTENT);
+		dev->irq = irq;
+		dev->mem_start = mem_start;
+	}
+
+	return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init lne390_probe(int unit)
+{
+	struct net_device *dev = alloc_ei_netdev();
+	int err;
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+
+	err = do_lne390_probe(dev);
+	if (err)
+		goto out;
+	return dev;
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+#endif
+
+static int __init lne390_probe1(struct net_device *dev, int ioaddr)
+{
+	int i, revision, ret;
+	unsigned long eisa_id;
+
+	if (inb_p(ioaddr + LNE390_ID_PORT) == 0xff) return -ENODEV;
+
+#if LNE390_DEBUG & LNE390_D_PROBE
+	printk("lne390-debug: probe at %#x, ID %#8x\n", ioaddr, inl(ioaddr + LNE390_ID_PORT));
+	printk("lne390-debug: config regs: %#x %#x\n",
+		inb(ioaddr + LNE390_CFG1), inb(ioaddr + LNE390_CFG2));
+#endif
+
+
+/*	Check the EISA ID of the card. */
+	eisa_id = inl(ioaddr + LNE390_ID_PORT);
+	if ((eisa_id != LNE390_ID0) && (eisa_id != LNE390_ID1)) {
+		return -ENODEV;
+	}
+
+	revision = (eisa_id >> 24) & 0x01;	/* 0 = rev A, 1 rev B */
+
+#if 0
+/*	Check the Mylex vendor ID as well. Not really required. */
+	if (inb(ioaddr + LNE390_SA_PROM + 0) != LNE390_ADDR0
+		|| inb(ioaddr + LNE390_SA_PROM + 1) != LNE390_ADDR1
+		|| inb(ioaddr + LNE390_SA_PROM + 2) != LNE390_ADDR2 ) {
+		printk("lne390.c: card not found");
+		for(i = 0; i < ETHER_ADDR_LEN; i++)
+			printk(" %02x", inb(ioaddr + LNE390_SA_PROM + i));
+		printk(" (invalid prefix).\n");
+		return -ENODEV;
+	}
+#endif
+
+	for(i = 0; i < ETHER_ADDR_LEN; i++)
+		dev->dev_addr[i] = inb(ioaddr + LNE390_SA_PROM + i);
+	printk("lne390.c: LNE390%X in EISA slot %d, address %pM.\n",
+	       0xa+revision, ioaddr/0x1000, dev->dev_addr);
+
+	printk("lne390.c: ");
+
+	/* Snarf the interrupt now. CFG file has them all listed as `edge' with share=NO */
+	if (dev->irq == 0) {
+		unsigned char irq_reg = inb(ioaddr + LNE390_CFG2) >> 3;
+		dev->irq = irq_map[irq_reg & 0x07];
+		printk("using");
+	} else {
+		/* This is useless unless we reprogram the card here too */
+		if (dev->irq == 2) dev->irq = 9;	/* Doh! */
+		printk("assigning");
+	}
+	printk(" IRQ %d,", dev->irq);
+
+	if ((ret = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev))) {
+		printk (" unable to get IRQ %d.\n", dev->irq);
+		return ret;
+	}
+
+	if (dev->mem_start == 0) {
+		unsigned char mem_reg = inb(ioaddr + LNE390_CFG2) & 0x07;
+
+		if (revision)	/* LNE390B */
+			dev->mem_start = shmem_mapB[mem_reg] * 0x10000;
+		else		/* LNE390A */
+			dev->mem_start = shmem_mapA[mem_reg] * 0x10000;
+		printk(" using ");
+	} else {
+		/* Should check for value in shmem_map and reprogram the card to use it */
+		dev->mem_start &= 0xfff0000;
+		printk(" assigning ");
+	}
+
+	printk("%dkB memory at physical address %#lx\n",
+			LNE390_STOP_PG/4, dev->mem_start);
+
+	/*
+	   BEWARE!! Some dain-bramaged EISA SCUs will allow you to put
+	   the card mem within the region covered by `normal' RAM  !!!
+
+	   ioremap() will fail in that case.
+	*/
+	ei_status.mem = ioremap(dev->mem_start, LNE390_STOP_PG*0x100);
+	if (!ei_status.mem) {
+		printk(KERN_ERR "lne390.c: Unable to remap card memory above 1MB !!\n");
+		printk(KERN_ERR "lne390.c: Try using EISA SCU to set memory below 1MB.\n");
+		printk(KERN_ERR "lne390.c: Driver NOT installed.\n");
+		ret = -EAGAIN;
+		goto cleanup;
+	}
+	printk("lne390.c: remapped %dkB card memory to virtual address %p\n",
+			LNE390_STOP_PG/4, ei_status.mem);
+
+	dev->mem_start = (unsigned long)ei_status.mem;
+	dev->mem_end = dev->mem_start + (LNE390_STOP_PG - LNE390_START_PG)*256;
+
+	/* The 8390 offset is zero for the LNE390 */
+	dev->base_addr = ioaddr;
+
+	ei_status.name = "LNE390";
+	ei_status.tx_start_page = LNE390_START_PG;
+	ei_status.rx_start_page = LNE390_START_PG + TX_PAGES;
+	ei_status.stop_page = LNE390_STOP_PG;
+	ei_status.word16 = 1;
+
+	if (ei_debug > 0)
+		printk(version);
+
+	ei_status.reset_8390 = &lne390_reset_8390;
+	ei_status.block_input = &lne390_block_input;
+	ei_status.block_output = &lne390_block_output;
+	ei_status.get_8390_hdr = &lne390_get_8390_hdr;
+
+	dev->netdev_ops = &ei_netdev_ops;
+	NS8390_init(dev, 0);
+
+	ret = register_netdev(dev);
+	if (ret)
+		goto unmap;
+	return 0;
+unmap:
+	if (ei_status.reg0)
+		iounmap(ei_status.mem);
+cleanup:
+	free_irq(dev->irq, dev);
+	return ret;
+}
+
+/*
+ *	Reset as per the packet driver method. Judging by the EISA cfg
+ *	file, this just toggles the "Board Enable" bits (bit 2 and 0).
+ */
+
+static void lne390_reset_8390(struct net_device *dev)
+{
+	unsigned short ioaddr = dev->base_addr;
+
+	outb(0x04, ioaddr + LNE390_RESET_PORT);
+	if (ei_debug > 1) printk("%s: resetting the LNE390...", dev->name);
+
+	mdelay(2);
+
+	ei_status.txing = 0;
+	outb(0x01, ioaddr + LNE390_RESET_PORT);
+	if (ei_debug > 1) printk("reset done\n");
+}
+
+/*
+ *	Note: In the following three functions is the implicit assumption
+ *	that the associated memcpy will only use "rep; movsl" as long as
+ *	we keep the counts as some multiple of doublewords. This is a
+ *	requirement of the hardware, and also prevents us from using
+ *	eth_io_copy_and_sum() since we can't guarantee it will limit
+ *	itself to doubleword access.
+ */
+
+/*
+ *	Grab the 8390 specific header. Similar to the block_input routine, but
+ *	we don't need to be concerned with ring wrap as the header will be at
+ *	the start of a page, so we optimize accordingly. (A single doubleword.)
+ */
+
+static void
+lne390_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	void __iomem *hdr_start = ei_status.mem + ((ring_page - LNE390_START_PG)<<8);
+	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	hdr->count = (hdr->count + 3) & ~3;     /* Round up allocation. */
+}
+
+/*
+ *	Block input and output are easy on shared memory ethercards, the only
+ *	complication is when the ring buffer wraps. The count will already
+ *	be rounded up to a doubleword value via lne390_get_8390_hdr() above.
+ */
+
+static void lne390_block_input(struct net_device *dev, int count, struct sk_buff *skb,
+						  int ring_offset)
+{
+	void __iomem *xfer_start = ei_status.mem + ring_offset - (LNE390_START_PG<<8);
+
+	if (ring_offset + count > (LNE390_STOP_PG<<8)) {
+		/* Packet wraps over end of ring buffer. */
+		int semi_count = (LNE390_STOP_PG<<8) - ring_offset;
+		memcpy_fromio(skb->data, xfer_start, semi_count);
+		count -= semi_count;
+		memcpy_fromio(skb->data + semi_count,
+			ei_status.mem + (TX_PAGES<<8), count);
+	} else {
+		/* Packet is in one chunk. */
+		memcpy_fromio(skb->data, xfer_start, count);
+	}
+}
+
+static void lne390_block_output(struct net_device *dev, int count,
+				const unsigned char *buf, int start_page)
+{
+	void __iomem *shmem = ei_status.mem + ((start_page - LNE390_START_PG)<<8);
+
+	count = (count + 3) & ~3;     /* Round up to doubleword */
+	memcpy_toio(shmem, buf, count);
+}
+
+
+#ifdef MODULE
+#define MAX_LNE_CARDS	4	/* Max number of LNE390 cards per module */
+static struct net_device *dev_lne[MAX_LNE_CARDS];
+static int io[MAX_LNE_CARDS];
+static int irq[MAX_LNE_CARDS];
+static int mem[MAX_LNE_CARDS];
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(mem, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s)");
+MODULE_PARM_DESC(mem, "memory base address(es)");
+MODULE_DESCRIPTION("Mylex LNE390A/B EISA Ethernet driver");
+MODULE_LICENSE("GPL");
+
+int __init init_module(void)
+{
+	struct net_device *dev;
+	int this_dev, found = 0;
+
+	for (this_dev = 0; this_dev < MAX_LNE_CARDS; this_dev++) {
+		if (io[this_dev] == 0 && this_dev != 0)
+			break;
+		dev = alloc_ei_netdev();
+		if (!dev)
+			break;
+		dev->irq = irq[this_dev];
+		dev->base_addr = io[this_dev];
+		dev->mem_start = mem[this_dev];
+		if (do_lne390_probe(dev) == 0) {
+			dev_lne[found++] = dev;
+			continue;
+		}
+		free_netdev(dev);
+		printk(KERN_WARNING "lne390.c: No LNE390 card found (i/o = 0x%x).\n", io[this_dev]);
+		break;
+	}
+	if (found)
+		return 0;
+	return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+	free_irq(dev->irq, dev);
+	release_region(dev->base_addr, LNE390_IO_EXTENT);
+	iounmap(ei_status.mem);
+}
+
+void __exit cleanup_module(void)
+{
+	int this_dev;
+
+	for (this_dev = 0; this_dev < MAX_LNE_CARDS; this_dev++) {
+		struct net_device *dev = dev_lne[this_dev];
+		if (dev) {
+			unregister_netdev(dev);
+			cleanup_card(dev);
+			free_netdev(dev);
+		}
+	}
+}
+#endif /* MODULE */
+
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/mac8390.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/mac8390.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/mac8390.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/mac8390.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,874 @@
+/* mac8390.c: New driver for 8390-based Nubus (or Nubus-alike)
+   Ethernet cards on Linux */
+/* Based on the former daynaport.c driver, by Alan Cox.  Some code
+   taken from or inspired by skeleton.c by Donald Becker, acenic.c by
+   Jes Sorensen, and ne2k-pci.c by Donald Becker and Paul Gortmaker.
+
+   This software may be used and distributed according to the terms of
+   the GNU Public License, incorporated herein by reference.  */
+
+/* 2000-02-28: support added for Dayna and Kinetics cards by
+   A.G.deWijn@phys.uu.nl */
+/* 2000-04-04: support added for Dayna2 by bart@etpmod.phys.tue.nl */
+/* 2001-04-18: support for DaynaPort E/LC-M by rayk@knightsmanor.org */
+/* 2001-05-15: support for Cabletron ported from old daynaport driver
+ * and fixed access to Sonic Sys card which masquerades as a Farallon
+ * by rayk@knightsmanor.org */
+/* 2002-12-30: Try to support more cards, some clues from NetBSD driver */
+/* 2003-12-26: Make sure Asante cards always work. */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/nubus.h>
+#include <linux/in.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/hwtest.h>
+#include <asm/macints.h>
+
+static char version[] =
+	"v0.4 2001-05-15 David Huggins-Daines <dhd@debian.org> and others\n";
+
+#define EI_SHIFT(x)	(ei_local->reg_offset[x])
+#define ei_inb(port)	in_8(port)
+#define ei_outb(val, port)	out_8(port, val)
+#define ei_inb_p(port)	in_8(port)
+#define ei_outb_p(val, port)	out_8(port, val)
+
+#include "lib8390.c"
+
+#define WD_START_PG			0x00	/* First page of TX buffer */
+#define CABLETRON_RX_START_PG		0x00    /* First page of RX buffer */
+#define CABLETRON_RX_STOP_PG		0x30    /* Last page +1 of RX ring */
+#define CABLETRON_TX_START_PG		CABLETRON_RX_STOP_PG
+						/* First page of TX buffer */
+
+/*
+ * Unfortunately it seems we have to hardcode these for the moment
+ * Shouldn't the card know about this?
+ * Does anyone know where to read it off the card?
+ * Do we trust the data provided by the card?
+ */
+
+#define DAYNA_8390_BASE		0x80000
+#define DAYNA_8390_MEM		0x00000
+
+#define CABLETRON_8390_BASE	0x90000
+#define CABLETRON_8390_MEM	0x00000
+
+#define INTERLAN_8390_BASE	0xE0000
+#define INTERLAN_8390_MEM	0xD0000
+
+enum mac8390_type {
+	MAC8390_NONE = -1,
+	MAC8390_APPLE,
+	MAC8390_ASANTE,
+	MAC8390_FARALLON,
+	MAC8390_CABLETRON,
+	MAC8390_DAYNA,
+	MAC8390_INTERLAN,
+	MAC8390_KINETICS,
+};
+
+static const char *cardname[] = {
+	"apple",
+	"asante",
+	"farallon",
+	"cabletron",
+	"dayna",
+	"interlan",
+	"kinetics",
+};
+
+static const int word16[] = {
+	1, /* apple */
+	1, /* asante */
+	1, /* farallon */
+	1, /* cabletron */
+	0, /* dayna */
+	1, /* interlan */
+	0, /* kinetics */
+};
+
+/* on which cards do we use NuBus resources? */
+static const int useresources[] = {
+	1, /* apple */
+	1, /* asante */
+	1, /* farallon */
+	0, /* cabletron */
+	0, /* dayna */
+	0, /* interlan */
+	0, /* kinetics */
+};
+
+enum mac8390_access {
+	ACCESS_UNKNOWN = 0,
+	ACCESS_32,
+	ACCESS_16,
+};
+
+extern int mac8390_memtest(struct net_device *dev);
+static int mac8390_initdev(struct net_device *dev, struct nubus_dev *ndev,
+			   enum mac8390_type type);
+
+static int mac8390_open(struct net_device *dev);
+static int mac8390_close(struct net_device *dev);
+static void mac8390_no_reset(struct net_device *dev);
+static void interlan_reset(struct net_device *dev);
+
+/* Sane (32-bit chunk memory read/write) - Some Farallon and Apple do this*/
+static void sane_get_8390_hdr(struct net_device *dev,
+			      struct e8390_pkt_hdr *hdr, int ring_page);
+static void sane_block_input(struct net_device *dev, int count,
+			     struct sk_buff *skb, int ring_offset);
+static void sane_block_output(struct net_device *dev, int count,
+			      const unsigned char *buf, const int start_page);
+
+/* dayna_memcpy to and from card */
+static void dayna_memcpy_fromcard(struct net_device *dev, void *to,
+				int from, int count);
+static void dayna_memcpy_tocard(struct net_device *dev, int to,
+			      const void *from, int count);
+
+/* Dayna - Dayna/Kinetics use this */
+static void dayna_get_8390_hdr(struct net_device *dev,
+			       struct e8390_pkt_hdr *hdr, int ring_page);
+static void dayna_block_input(struct net_device *dev, int count,
+			      struct sk_buff *skb, int ring_offset);
+static void dayna_block_output(struct net_device *dev, int count,
+			       const unsigned char *buf, int start_page);
+
+#define memcpy_fromio(a, b, c)	memcpy((a), (void *)(b), (c))
+#define memcpy_toio(a, b, c)	memcpy((void *)(a), (b), (c))
+
+#define memcmp_withio(a, b, c)	memcmp((a), (void *)(b), (c))
+
+/* Slow Sane (16-bit chunk memory read/write) Cabletron uses this */
+static void slow_sane_get_8390_hdr(struct net_device *dev,
+				   struct e8390_pkt_hdr *hdr, int ring_page);
+static void slow_sane_block_input(struct net_device *dev, int count,
+				  struct sk_buff *skb, int ring_offset);
+static void slow_sane_block_output(struct net_device *dev, int count,
+				   const unsigned char *buf, int start_page);
+static void word_memcpy_tocard(unsigned long tp, const void *fp, int count);
+static void word_memcpy_fromcard(void *tp, unsigned long fp, int count);
+
+static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev)
+{
+	switch (dev->dr_sw) {
+	case NUBUS_DRSW_3COM:
+		switch (dev->dr_hw) {
+		case NUBUS_DRHW_APPLE_SONIC_NB:
+		case NUBUS_DRHW_APPLE_SONIC_LC:
+		case NUBUS_DRHW_SONNET:
+			return MAC8390_NONE;
+			break;
+		default:
+			return MAC8390_APPLE;
+			break;
+		}
+		break;
+
+	case NUBUS_DRSW_APPLE:
+		switch (dev->dr_hw) {
+		case NUBUS_DRHW_ASANTE_LC:
+			return MAC8390_NONE;
+			break;
+		case NUBUS_DRHW_CABLETRON:
+			return MAC8390_CABLETRON;
+			break;
+		default:
+			return MAC8390_APPLE;
+			break;
+		}
+		break;
+
+	case NUBUS_DRSW_ASANTE:
+		return MAC8390_ASANTE;
+		break;
+
+	case NUBUS_DRSW_TECHWORKS:
+	case NUBUS_DRSW_DAYNA2:
+	case NUBUS_DRSW_DAYNA_LC:
+		if (dev->dr_hw == NUBUS_DRHW_CABLETRON)
+			return MAC8390_CABLETRON;
+		else
+			return MAC8390_APPLE;
+		break;
+
+	case NUBUS_DRSW_FARALLON:
+		return MAC8390_FARALLON;
+		break;
+
+	case NUBUS_DRSW_KINETICS:
+		switch (dev->dr_hw) {
+		case NUBUS_DRHW_INTERLAN:
+			return MAC8390_INTERLAN;
+			break;
+		default:
+			return MAC8390_KINETICS;
+			break;
+		}
+		break;
+
+	case NUBUS_DRSW_DAYNA:
+		/*
+		 * These correspond to Dayna Sonic cards
+		 * which use the macsonic driver
+		 */
+		if (dev->dr_hw == NUBUS_DRHW_SMC9194 ||
+		    dev->dr_hw == NUBUS_DRHW_INTERLAN)
+			return MAC8390_NONE;
+		else
+			return MAC8390_DAYNA;
+		break;
+	}
+	return MAC8390_NONE;
+}
+
+static enum mac8390_access __init mac8390_testio(volatile unsigned long membase)
+{
+	unsigned long outdata = 0xA5A0B5B0;
+	unsigned long indata =  0x00000000;
+	/* Try writing 32 bits */
+	memcpy_toio(membase, &outdata, 4);
+	/* Now compare them */
+	if (memcmp_withio(&outdata, membase, 4) == 0)
+		return ACCESS_32;
+	/* Write 16 bit output */
+	word_memcpy_tocard(membase, &outdata, 4);
+	/* Now read it back */
+	word_memcpy_fromcard(&indata, membase, 4);
+	if (outdata == indata)
+		return ACCESS_16;
+	return ACCESS_UNKNOWN;
+}
+
+static int __init mac8390_memsize(unsigned long membase)
+{
+	unsigned long flags;
+	int i, j;
+
+	local_irq_save(flags);
+	/* Check up to 32K in 4K increments */
+	for (i = 0; i < 8; i++) {
+		volatile unsigned short *m = (unsigned short *)(membase + (i * 0x1000));
+
+		/* Unwriteable - we have a fully decoded card and the
+		   RAM end located */
+		if (hwreg_present(m) == 0)
+			break;
+
+		/* write a distinctive byte */
+		*m = 0xA5A0 | i;
+		/* check that we read back what we wrote */
+		if (*m != (0xA5A0 | i))
+			break;
+
+		/* check for partial decode and wrap */
+		for (j = 0; j < i; j++) {
+			volatile unsigned short *p = (unsigned short *)(membase + (j * 0x1000));
+			if (*p != (0xA5A0 | j))
+				break;
+		}
+	}
+	local_irq_restore(flags);
+	/*
+	 * in any case, we stopped once we tried one block too many,
+	 * or once we reached 32K
+	 */
+	return i * 0x1000;
+}
+
+static bool __init mac8390_init(struct net_device *dev, struct nubus_dev *ndev,
+				enum mac8390_type cardtype)
+{
+	struct nubus_dir dir;
+	struct nubus_dirent ent;
+	int offset;
+	volatile unsigned short *i;
+
+	printk_once(KERN_INFO pr_fmt("%s"), version);
+
+	dev->irq = SLOT2IRQ(ndev->board->slot);
+	/* This is getting to be a habit */
+	dev->base_addr = (ndev->board->slot_addr |
+			  ((ndev->board->slot & 0xf) << 20));
+
+	/*
+	 * Get some Nubus info - we will trust the card's idea
+	 * of where its memory and registers are.
+	 */
+
+	if (nubus_get_func_dir(ndev, &dir) == -1) {
+		pr_err("%s: Unable to get Nubus functional directory for slot %X!\n",
+		       dev->name, ndev->board->slot);
+		return false;
+	}
+
+	/* Get the MAC address */
+	if (nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent) == -1) {
+		pr_info("%s: Couldn't get MAC address!\n", dev->name);
+		return false;
+	}
+
+	nubus_get_rsrc_mem(dev->dev_addr, &ent, 6);
+
+	if (useresources[cardtype] == 1) {
+		nubus_rewinddir(&dir);
+		if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_BASEOS,
+				    &ent) == -1) {
+			pr_err("%s: Memory offset resource for slot %X not found!\n",
+			       dev->name, ndev->board->slot);
+			return false;
+		}
+		nubus_get_rsrc_mem(&offset, &ent, 4);
+		dev->mem_start = dev->base_addr + offset;
+		/* yes, this is how the Apple driver does it */
+		dev->base_addr = dev->mem_start + 0x10000;
+		nubus_rewinddir(&dir);
+		if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_LENGTH,
+				    &ent) == -1) {
+			pr_info("%s: Memory length resource for slot %X not found, probing\n",
+				dev->name, ndev->board->slot);
+			offset = mac8390_memsize(dev->mem_start);
+		} else {
+			nubus_get_rsrc_mem(&offset, &ent, 4);
+		}
+		dev->mem_end = dev->mem_start + offset;
+	} else {
+		switch (cardtype) {
+		case MAC8390_KINETICS:
+		case MAC8390_DAYNA: /* it's the same */
+			dev->base_addr = (int)(ndev->board->slot_addr +
+					       DAYNA_8390_BASE);
+			dev->mem_start = (int)(ndev->board->slot_addr +
+					       DAYNA_8390_MEM);
+			dev->mem_end = dev->mem_start +
+				       mac8390_memsize(dev->mem_start);
+			break;
+		case MAC8390_INTERLAN:
+			dev->base_addr = (int)(ndev->board->slot_addr +
+					       INTERLAN_8390_BASE);
+			dev->mem_start = (int)(ndev->board->slot_addr +
+					       INTERLAN_8390_MEM);
+			dev->mem_end = dev->mem_start +
+				       mac8390_memsize(dev->mem_start);
+			break;
+		case MAC8390_CABLETRON:
+			dev->base_addr = (int)(ndev->board->slot_addr +
+					       CABLETRON_8390_BASE);
+			dev->mem_start = (int)(ndev->board->slot_addr +
+					       CABLETRON_8390_MEM);
+			/* The base address is unreadable if 0x00
+			 * has been written to the command register
+			 * Reset the chip by writing E8390_NODMA +
+			 *   E8390_PAGE0 + E8390_STOP just to be
+			 *   sure
+			 */
+			i = (void *)dev->base_addr;
+			*i = 0x21;
+			dev->mem_end = dev->mem_start +
+				       mac8390_memsize(dev->mem_start);
+			break;
+
+		default:
+			pr_err("Card type %s is unsupported, sorry\n",
+			       ndev->board->name);
+			return false;
+		}
+	}
+
+	return true;
+}
+
+struct net_device * __init mac8390_probe(int unit)
+{
+	struct net_device *dev;
+	struct nubus_dev *ndev = NULL;
+	int err = -ENODEV;
+
+	static unsigned int slots;
+
+	enum mac8390_type cardtype;
+
+	/* probably should check for Nubus instead */
+
+	if (!MACH_IS_MAC)
+		return ERR_PTR(-ENODEV);
+
+	dev = ____alloc_ei_netdev(0);
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	if (unit >= 0)
+		sprintf(dev->name, "eth%d", unit);
+
+	while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK, NUBUS_TYPE_ETHERNET,
+				       ndev))) {
+		/* Have we seen it already? */
+		if (slots & (1 << ndev->board->slot))
+			continue;
+		slots |= 1 << ndev->board->slot;
+
+		cardtype = mac8390_ident(ndev);
+		if (cardtype == MAC8390_NONE)
+			continue;
+
+		if (!mac8390_init(dev, ndev, cardtype))
+			continue;
+
+		/* Do the nasty 8390 stuff */
+		if (!mac8390_initdev(dev, ndev, cardtype))
+			break;
+	}
+
+	if (!ndev)
+		goto out;
+	err = register_netdev(dev);
+	if (err)
+		goto out;
+	return dev;
+
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+
+#ifdef MODULE
+MODULE_AUTHOR("David Huggins-Daines <dhd@debian.org> and others");
+MODULE_DESCRIPTION("Macintosh NS8390-based Nubus Ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* overkill, of course */
+static struct net_device *dev_mac8390[15];
+int init_module(void)
+{
+	int i;
+	for (i = 0; i < 15; i++) {
+		struct net_device *dev = mac8390_probe(-1);
+		if (IS_ERR(dev))
+			break;
+		dev_mac890[i] = dev;
+	}
+	if (!i) {
+		pr_notice("No useable cards found, driver NOT installed.\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	int i;
+	for (i = 0; i < 15; i++) {
+		struct net_device *dev = dev_mac890[i];
+		if (dev) {
+			unregister_netdev(dev);
+			free_netdev(dev);
+		}
+	}
+}
+
+#endif /* MODULE */
+
+static const struct net_device_ops mac8390_netdev_ops = {
+	.ndo_open 		= mac8390_open,
+	.ndo_stop		= mac8390_close,
+	.ndo_start_xmit		= __ei_start_xmit,
+	.ndo_tx_timeout		= __ei_tx_timeout,
+	.ndo_get_stats		= __ei_get_stats,
+	.ndo_set_rx_mode	= __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,
+#endif
+};
+
+static int __init mac8390_initdev(struct net_device *dev,
+				  struct nubus_dev *ndev,
+				  enum mac8390_type type)
+{
+	static u32 fwrd4_offsets[16] = {
+		0,      4,      8,      12,
+		16,     20,     24,     28,
+		32,     36,     40,     44,
+		48,     52,     56,     60
+	};
+	static u32 back4_offsets[16] = {
+		60,     56,     52,     48,
+		44,     40,     36,     32,
+		28,     24,     20,     16,
+		12,     8,      4,      0
+	};
+	static u32 fwrd2_offsets[16] = {
+		0,      2,      4,      6,
+		8,     10,     12,     14,
+		16,    18,     20,     22,
+		24,    26,     28,     30
+	};
+
+	int access_bitmode = 0;
+
+	/* Now fill in our stuff */
+	dev->netdev_ops = &mac8390_netdev_ops;
+
+	/* GAR, ei_status is actually a macro even though it looks global */
+	ei_status.name = cardname[type];
+	ei_status.word16 = word16[type];
+
+	/* Cabletron's TX/RX buffers are backwards */
+	if (type == MAC8390_CABLETRON) {
+		ei_status.tx_start_page = CABLETRON_TX_START_PG;
+		ei_status.rx_start_page = CABLETRON_RX_START_PG;
+		ei_status.stop_page = CABLETRON_RX_STOP_PG;
+		ei_status.rmem_start = dev->mem_start;
+		ei_status.rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256;
+	} else {
+		ei_status.tx_start_page = WD_START_PG;
+		ei_status.rx_start_page = WD_START_PG + TX_PAGES;
+		ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
+		ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
+		ei_status.rmem_end = dev->mem_end;
+	}
+
+	/* Fill in model-specific information and functions */
+	switch (type) {
+	case MAC8390_FARALLON:
+	case MAC8390_APPLE:
+		switch (mac8390_testio(dev->mem_start)) {
+		case ACCESS_UNKNOWN:
+			pr_err("Don't know how to access card memory!\n");
+			return -ENODEV;
+			break;
+
+		case ACCESS_16:
+			/* 16 bit card, register map is reversed */
+			ei_status.reset_8390 = mac8390_no_reset;
+			ei_status.block_input = slow_sane_block_input;
+			ei_status.block_output = slow_sane_block_output;
+			ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
+			ei_status.reg_offset = back4_offsets;
+			break;
+
+		case ACCESS_32:
+			/* 32 bit card, register map is reversed */
+			ei_status.reset_8390 = mac8390_no_reset;
+			ei_status.block_input = sane_block_input;
+			ei_status.block_output = sane_block_output;
+			ei_status.get_8390_hdr = sane_get_8390_hdr;
+			ei_status.reg_offset = back4_offsets;
+			access_bitmode = 1;
+			break;
+		}
+		break;
+
+	case MAC8390_ASANTE:
+		/* Some Asante cards pass the 32 bit test
+		 * but overwrite system memory when run at 32 bit.
+		 * so we run them all at 16 bit.
+		 */
+		ei_status.reset_8390 = mac8390_no_reset;
+		ei_status.block_input = slow_sane_block_input;
+		ei_status.block_output = slow_sane_block_output;
+		ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
+		ei_status.reg_offset = back4_offsets;
+		break;
+
+	case MAC8390_CABLETRON:
+		/* 16 bit card, register map is short forward */
+		ei_status.reset_8390 = mac8390_no_reset;
+		ei_status.block_input = slow_sane_block_input;
+		ei_status.block_output = slow_sane_block_output;
+		ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
+		ei_status.reg_offset = fwrd2_offsets;
+		break;
+
+	case MAC8390_DAYNA:
+	case MAC8390_KINETICS:
+		/* 16 bit memory, register map is forward */
+		/* dayna and similar */
+		ei_status.reset_8390 = mac8390_no_reset;
+		ei_status.block_input = dayna_block_input;
+		ei_status.block_output = dayna_block_output;
+		ei_status.get_8390_hdr = dayna_get_8390_hdr;
+		ei_status.reg_offset = fwrd4_offsets;
+		break;
+
+	case MAC8390_INTERLAN:
+		/* 16 bit memory, register map is forward */
+		ei_status.reset_8390 = interlan_reset;
+		ei_status.block_input = slow_sane_block_input;
+		ei_status.block_output = slow_sane_block_output;
+		ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
+		ei_status.reg_offset = fwrd4_offsets;
+		break;
+
+	default:
+		pr_err("Card type %s is unsupported, sorry\n",
+		       ndev->board->name);
+		return -ENODEV;
+	}
+
+	__NS8390_init(dev, 0);
+
+	/* Good, done, now spit out some messages */
+	pr_info("%s: %s in slot %X (type %s)\n",
+		dev->name, ndev->board->name, ndev->board->slot,
+		cardname[type]);
+	pr_info("MAC %pM IRQ %d, %d KB shared memory at %#lx, %d-bit access.\n",
+		dev->dev_addr, dev->irq,
+		(unsigned int)(dev->mem_end - dev->mem_start) >> 10,
+		dev->mem_start, access_bitmode ? 32 : 16);
+	return 0;
+}
+
+static int mac8390_open(struct net_device *dev)
+{
+	int err;
+
+	__ei_open(dev);
+	err = request_irq(dev->irq, __ei_interrupt, 0, "8390 Ethernet", dev);
+	if (err)
+		pr_err("%s: unable to get IRQ %d\n", dev->name, dev->irq);
+	return err;
+}
+
+static int mac8390_close(struct net_device *dev)
+{
+	free_irq(dev->irq, dev);
+	__ei_close(dev);
+	return 0;
+}
+
+static void mac8390_no_reset(struct net_device *dev)
+{
+	ei_status.txing = 0;
+	if (ei_debug > 1)
+		pr_info("reset not supported\n");
+}
+
+static void interlan_reset(struct net_device *dev)
+{
+	unsigned char *target = nubus_slot_addr(IRQ2SLOT(dev->irq));
+	if (ei_debug > 1)
+		pr_info("Need to reset the NS8390 t=%lu...", jiffies);
+	ei_status.txing = 0;
+	target[0xC0000] = 0;
+	if (ei_debug > 1)
+		pr_cont("reset complete\n");
+}
+
+/* dayna_memcpy_fromio/dayna_memcpy_toio */
+/* directly from daynaport.c by Alan Cox */
+static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from,
+				  int count)
+{
+	volatile unsigned char *ptr;
+	unsigned char *target = to;
+	from <<= 1;	/* word, skip overhead */
+	ptr = (unsigned char *)(dev->mem_start+from);
+	/* Leading byte? */
+	if (from & 2) {
+		*target++ = ptr[-1];
+		ptr += 2;
+		count--;
+	}
+	while (count >= 2) {
+		*(unsigned short *)target = *(unsigned short volatile *)ptr;
+		ptr += 4;			/* skip cruft */
+		target += 2;
+		count -= 2;
+	}
+	/* Trailing byte? */
+	if (count)
+		*target = *ptr;
+}
+
+static void dayna_memcpy_tocard(struct net_device *dev, int to,
+				const void *from, int count)
+{
+	volatile unsigned short *ptr;
+	const unsigned char *src = from;
+	to <<= 1;	/* word, skip overhead */
+	ptr = (unsigned short *)(dev->mem_start+to);
+	/* Leading byte? */
+	if (to & 2) {		/* avoid a byte write (stomps on other data) */
+		ptr[-1] = (ptr[-1]&0xFF00)|*src++;
+		ptr++;
+		count--;
+	}
+	while (count >= 2) {
+		*ptr++ = *(unsigned short *)src;	/* Copy and */
+		ptr++;			/* skip cruft */
+		src += 2;
+		count -= 2;
+	}
+	/* Trailing byte? */
+	if (count) {
+		/* card doesn't like byte writes */
+		*ptr = (*ptr & 0x00FF) | (*src << 8);
+	}
+}
+
+/* sane block input/output */
+static void sane_get_8390_hdr(struct net_device *dev,
+			      struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
+	memcpy_fromio(hdr, dev->mem_start + hdr_start, 4);
+	/* Fix endianness */
+	hdr->count = swab16(hdr->count);
+}
+
+static void sane_block_input(struct net_device *dev, int count,
+			     struct sk_buff *skb, int ring_offset)
+{
+	unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
+	unsigned long xfer_start = xfer_base + dev->mem_start;
+
+	if (xfer_start + count > ei_status.rmem_end) {
+		/* We must wrap the input move. */
+		int semi_count = ei_status.rmem_end - xfer_start;
+		memcpy_fromio(skb->data, dev->mem_start + xfer_base,
+			      semi_count);
+		count -= semi_count;
+		memcpy_fromio(skb->data + semi_count, ei_status.rmem_start,
+			      count);
+	} else {
+		memcpy_fromio(skb->data, dev->mem_start + xfer_base, count);
+	}
+}
+
+static void sane_block_output(struct net_device *dev, int count,
+			      const unsigned char *buf, int start_page)
+{
+	long shmem = (start_page - WD_START_PG)<<8;
+
+	memcpy_toio(dev->mem_start + shmem, buf, count);
+}
+
+/* dayna block input/output */
+static void dayna_get_8390_hdr(struct net_device *dev,
+			       struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
+
+	dayna_memcpy_fromcard(dev, hdr, hdr_start, 4);
+	/* Fix endianness */
+	hdr->count = (hdr->count & 0xFF) << 8 | (hdr->count >> 8);
+}
+
+static void dayna_block_input(struct net_device *dev, int count,
+			      struct sk_buff *skb, int ring_offset)
+{
+	unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
+	unsigned long xfer_start = xfer_base+dev->mem_start;
+
+	/* Note the offset math is done in card memory space which is word
+	   per long onto our space. */
+
+	if (xfer_start + count > ei_status.rmem_end) {
+		/* We must wrap the input move. */
+		int semi_count = ei_status.rmem_end - xfer_start;
+		dayna_memcpy_fromcard(dev, skb->data, xfer_base, semi_count);
+		count -= semi_count;
+		dayna_memcpy_fromcard(dev, skb->data + semi_count,
+				      ei_status.rmem_start - dev->mem_start,
+				      count);
+	} else {
+		dayna_memcpy_fromcard(dev, skb->data, xfer_base, count);
+	}
+}
+
+static void dayna_block_output(struct net_device *dev, int count,
+			       const unsigned char *buf,
+			       int start_page)
+{
+	long shmem = (start_page - WD_START_PG)<<8;
+
+	dayna_memcpy_tocard(dev, shmem, buf, count);
+}
+
+/* Cabletron block I/O */
+static void slow_sane_get_8390_hdr(struct net_device *dev,
+				   struct e8390_pkt_hdr *hdr,
+				   int ring_page)
+{
+	unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
+	word_memcpy_fromcard(hdr, dev->mem_start + hdr_start, 4);
+	/* Register endianism - fix here rather than 8390.c */
+	hdr->count = (hdr->count&0xFF)<<8|(hdr->count>>8);
+}
+
+static void slow_sane_block_input(struct net_device *dev, int count,
+				  struct sk_buff *skb, int ring_offset)
+{
+	unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
+	unsigned long xfer_start = xfer_base+dev->mem_start;
+
+	if (xfer_start + count > ei_status.rmem_end) {
+		/* We must wrap the input move. */
+		int semi_count = ei_status.rmem_end - xfer_start;
+		word_memcpy_fromcard(skb->data, dev->mem_start + xfer_base,
+				     semi_count);
+		count -= semi_count;
+		word_memcpy_fromcard(skb->data + semi_count,
+				     ei_status.rmem_start, count);
+	} else {
+		word_memcpy_fromcard(skb->data, dev->mem_start + xfer_base,
+				     count);
+	}
+}
+
+static void slow_sane_block_output(struct net_device *dev, int count,
+				   const unsigned char *buf, int start_page)
+{
+	long shmem = (start_page - WD_START_PG)<<8;
+
+	word_memcpy_tocard(dev->mem_start + shmem, buf, count);
+}
+
+static void word_memcpy_tocard(unsigned long tp, const void *fp, int count)
+{
+	volatile unsigned short *to = (void *)tp;
+	const unsigned short *from = fp;
+
+	count++;
+	count /= 2;
+
+	while (count--)
+		*to++ = *from++;
+}
+
+static void word_memcpy_fromcard(void *tp, unsigned long fp, int count)
+{
+	unsigned short *to = tp;
+	const volatile unsigned short *from = (const void *)fp;
+
+	count++;
+	count /= 2;
+
+	while (count--)
+		*to++ = *from++;
+}
+
+
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/Makefile linux-libre-3.2-gnu/drivers/net/ethernet/8390/Makefile
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,29 @@
+#
+# Makefile for the 8390 network device drivers.
+#
+
+obj-$(CONFIG_MAC8390) += mac8390.o
+obj-$(CONFIG_AC3200) += ac3200.o 8390.o
+obj-$(CONFIG_APNE) += apne.o 8390.o
+obj-$(CONFIG_ARM_ETHERH) += etherh.o
+obj-$(CONFIG_AX88796) += ax88796.o
+obj-$(CONFIG_E2100) += e2100.o 8390.o
+obj-$(CONFIG_EL2) += 3c503.o 8390p.o
+obj-$(CONFIG_ES3210) += es3210.o 8390.o
+obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390p.o
+obj-$(CONFIG_HPLAN) += hp.o 8390p.o
+obj-$(CONFIG_HYDRA) += hydra.o 8390.o
+obj-$(CONFIG_LNE390) += lne390.o 8390.o
+obj-$(CONFIG_NE2000) += ne.o 8390p.o
+obj-$(CONFIG_NE2_MCA) += ne2.o 8390p.o
+obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
+obj-$(CONFIG_NE3210) += ne3210.o 8390.o
+obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
+obj-$(CONFIG_PCMCIA_AXNET) += axnet_cs.o 8390.o
+obj-$(CONFIG_PCMCIA_PCNET) += pcnet_cs.o 8390.o
+obj-$(CONFIG_STNIC) += stnic.o 8390.o
+obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o
+obj-$(CONFIG_ULTRA32) += smc-ultra32.o 8390.o
+obj-$(CONFIG_ULTRAMCA) += smc-mca.o 8390.o
+obj-$(CONFIG_WD80x3) += wd.o 8390.o
+obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/ne2.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/ne2.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/ne2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/ne2.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,799 @@
+/* ne2.c: A NE/2 Ethernet Driver for Linux. */
+/*
+   Based on the NE2000 driver written by Donald Becker (1992-94).
+   modified by Wim Dumon (Apr 1996)
+
+   This software may be used and distributed according to the terms
+   of the GNU General Public License, incorporated herein by reference.
+
+   The author may be reached as wimpie@linux.cc.kuleuven.ac.be
+
+   Currently supported: NE/2
+   This patch was never tested on other MCA-ethernet adapters, but it
+   might work. Just give it a try and let me know if you have problems.
+   Also mail me if it really works, please!
+
+   Changelog:
+   Mon Feb  3 16:26:02 MET 1997
+   - adapted the driver to work with the 2.1.25 kernel
+   - multiple ne2 support (untested)
+   - module support (untested)
+
+   Fri Aug 28 00:18:36 CET 1998 (David Weinehall)
+   - fixed a few minor typos
+   - made the MODULE_PARM conditional (it only works with the v2.1.x kernels)
+   - fixed the module support (Now it's working...)
+
+   Mon Sep  7 19:01:44 CET 1998 (David Weinehall)
+   - added support for Arco Electronics AE/2-card (experimental)
+
+   Mon Sep 14 09:53:42 CET 1998 (David Weinehall)
+   - added support for Compex ENET-16MC/P (experimental)
+
+   Tue Sep 15 16:21:12 CET 1998 (David Weinehall, Magnus Jonsson, Tomas Ogren)
+   - Miscellaneous bugfixes
+
+   Tue Sep 19 16:21:12 CET 1998 (Magnus Jonsson)
+   - Cleanup
+
+   Wed Sep 23 14:33:34 CET 1998 (David Weinehall)
+   - Restructuring and rewriting for v2.1.x compliance
+
+   Wed Oct 14 17:19:21 CET 1998 (David Weinehall)
+   - Added code that unregisters irq and proc-info
+   - Version# bump
+
+   Mon Nov 16 15:28:23 CET 1998 (Wim Dumon)
+   - pass 'dev' as last parameter of request_irq in stead of 'NULL'
+
+   Wed Feb  7 21:24:00 CET 2001 (Alfred Arnold)
+   - added support for the D-Link DE-320CT
+
+   *    WARNING
+	-------
+	This is alpha-test software.  It is not guaranteed to work. As a
+	matter of fact, I'm quite sure there are *LOTS* of bugs in here. I
+	would like to hear from you if you use this driver, even if it works.
+	If it doesn't work, be sure to send me a mail with the problems !
+*/
+
+static const char *version = "ne2.c:v0.91 Nov 16 1998 Wim Dumon <wimpie@kotnet.org>\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/mca-legacy.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/bitops.h>
+#include <linux/jiffies.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include "8390.h"
+
+#define DRV_NAME "ne2"
+
+/* Some defines that people can play with if so inclined. */
+
+/* Do we perform extra sanity checks on stuff ? */
+/* #define NE_SANITY_CHECK */
+
+/* Do we implement the read before write bugfix ? */
+/* #define NE_RW_BUGFIX */
+
+/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
+/* #define PACKETBUF_MEMSIZE	0x40 */
+
+
+/* ---- No user-serviceable parts below ---- */
+
+#define NE_BASE	 (dev->base_addr)
+#define NE_CMD	 	0x00
+#define NE_DATAPORT	0x10	/* NatSemi-defined port window offset. */
+#define NE_RESET	0x20	/* Issue a read to reset, a write to clear. */
+#define NE_IO_EXTENT	0x30
+
+#define NE1SM_START_PG	0x20	/* First page of TX buffer */
+#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 */
+
+/* From the .ADF file: */
+static unsigned int addresses[7] __initdata =
+		{0x1000, 0x2020, 0x8020, 0xa0a0, 0xb0b0, 0xc0c0, 0xc3d0};
+static int irqs[4] __initdata = {3, 4, 5, 9};
+
+/* From the D-Link ADF file: */
+static unsigned int dlink_addresses[4] __initdata =
+                {0x300, 0x320, 0x340, 0x360};
+static int dlink_irqs[8] __initdata = {3, 4, 5, 9, 10, 11, 14, 15};
+
+struct ne2_adapters_t {
+	unsigned int	id;
+	char		*name;
+};
+
+static struct ne2_adapters_t ne2_adapters[] __initdata = {
+	{ 0x6354, "Arco Ethernet Adapter AE/2" },
+	{ 0x70DE, "Compex ENET-16 MC/P" },
+	{ 0x7154, "Novell Ethernet Adapter NE/2" },
+        { 0x56ea, "D-Link DE-320CT" },
+	{ 0x0000, NULL }
+};
+
+extern int netcard_probe(struct net_device *dev);
+
+static int ne2_probe1(struct net_device *dev, int slot);
+
+static void ne_reset_8390(struct net_device *dev);
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+		int ring_page);
+static void ne_block_input(struct net_device *dev, int count,
+		struct sk_buff *skb, int ring_offset);
+static void ne_block_output(struct net_device *dev, const int count,
+		const unsigned char *buf, const int start_page);
+
+
+/*
+ * special code to read the DE-320's MAC address EEPROM.  In contrast to a
+ * standard NE design, this is a serial EEPROM (93C46) that has to be read
+ * bit by bit.  The EEPROM cotrol port at base + 0x1e has the following
+ * layout:
+ *
+ * Bit 0 = Data out (read from EEPROM)
+ * Bit 1 = Data in  (write to EEPROM)
+ * Bit 2 = Clock
+ * Bit 3 = Chip Select
+ * Bit 7 = ~50 kHz clock for defined delays
+ *
+ */
+
+static void __init dlink_put_eeprom(unsigned char value, unsigned int addr)
+{
+	int z;
+	unsigned char v1, v2;
+
+	/* write the value to the NIC EEPROM register */
+
+	outb(value, addr + 0x1e);
+
+	/* now wait the clock line to toggle twice.  Effectively, we are
+	   waiting (at least) for one clock cycle */
+
+	for (z = 0; z < 2; z++) {
+		do {
+			v1 = inb(addr + 0x1e);
+			v2 = inb(addr + 0x1e);
+		}
+		while (!((v1 ^ v2) & 0x80));
+	}
+}
+
+static void __init dlink_send_eeprom_bit(unsigned int bit, unsigned int addr)
+{
+	/* shift data bit into correct position */
+
+	bit = bit << 1;
+
+	/* write value, keep clock line high for two cycles */
+
+	dlink_put_eeprom(0x09 | bit, addr);
+	dlink_put_eeprom(0x0d | bit, addr);
+	dlink_put_eeprom(0x0d | bit, addr);
+	dlink_put_eeprom(0x09 | bit, addr);
+}
+
+static void __init dlink_send_eeprom_word(unsigned int value, unsigned int len, unsigned int addr)
+{
+	int z;
+
+	/* adjust bits so that they are left-aligned in a 16-bit-word */
+
+	value = value << (16 - len);
+
+	/* shift bits out to the EEPROM */
+
+	for (z = 0; z < len; z++) {
+		dlink_send_eeprom_bit((value & 0x8000) >> 15, addr);
+		value = value << 1;
+	}
+}
+
+static unsigned int __init dlink_get_eeprom(unsigned int eeaddr, unsigned int addr)
+{
+	int z;
+	unsigned int value = 0;
+
+	/* pull the CS line low for a moment.  This resets the EEPROM-
+	   internal logic, and makes it ready for a new command. */
+
+	dlink_put_eeprom(0x01, addr);
+	dlink_put_eeprom(0x09, addr);
+
+	/* send one start bit, read command (1 - 0), plus the address to
+           the EEPROM */
+
+	dlink_send_eeprom_word(0x0180 | (eeaddr & 0x3f), 9, addr);
+
+	/* get the data word.  We clock by sending 0s to the EEPROM, which
+	   get ignored during the read process */
+
+	for (z = 0; z < 16; z++) {
+		dlink_send_eeprom_bit(0, addr);
+		value = (value << 1) | (inb(addr + 0x1e) & 0x01);
+	}
+
+	return value;
+}
+
+/*
+ * Note that at boot, this probe only picks up one card at a time.
+ */
+
+static int __init do_ne2_probe(struct net_device *dev)
+{
+	static int current_mca_slot = -1;
+	int i;
+	int adapter_found = 0;
+
+	/* Do not check any supplied i/o locations.
+	   POS registers usually don't fail :) */
+
+	/* MCA cards have POS registers.
+	   Autodetecting MCA cards is extremely simple.
+	   Just search for the card. */
+
+	for(i = 0; (ne2_adapters[i].name != NULL) && !adapter_found; i++) {
+		current_mca_slot =
+			mca_find_unused_adapter(ne2_adapters[i].id, 0);
+
+		if((current_mca_slot != MCA_NOTFOUND) && !adapter_found) {
+			int res;
+			mca_set_adapter_name(current_mca_slot,
+					ne2_adapters[i].name);
+			mca_mark_as_used(current_mca_slot);
+
+			res = ne2_probe1(dev, current_mca_slot);
+			if (res)
+				mca_mark_as_unused(current_mca_slot);
+			return res;
+		}
+	}
+	return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init ne2_probe(int unit)
+{
+	struct net_device *dev = alloc_eip_netdev();
+	int err;
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+
+	err = do_ne2_probe(dev);
+	if (err)
+		goto out;
+	return dev;
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+#endif
+
+static int ne2_procinfo(char *buf, int slot, struct net_device *dev)
+{
+	int len=0;
+
+	len += sprintf(buf+len, "The NE/2 Ethernet Adapter\n" );
+	len += sprintf(buf+len, "Driver written by Wim Dumon ");
+	len += sprintf(buf+len, "<wimpie@kotnet.org>\n");
+	len += sprintf(buf+len, "Modified by ");
+	len += sprintf(buf+len, "David Weinehall <tao@acc.umu.se>\n");
+	len += sprintf(buf+len, "and by Magnus Jonsson <bigfoot@acc.umu.se>\n");
+	len += sprintf(buf+len, "Based on the original NE2000 drivers\n" );
+	len += sprintf(buf+len, "Base IO: %#x\n", (unsigned int)dev->base_addr);
+	len += sprintf(buf+len, "IRQ    : %d\n", dev->irq);
+	len += sprintf(buf+len, "HW addr : %pM\n", dev->dev_addr);
+
+	return len;
+}
+
+static int __init ne2_probe1(struct net_device *dev, int slot)
+{
+	int i, base_addr, irq, retval;
+	unsigned char POS;
+	unsigned char SA_prom[32];
+	const char *name = "NE/2";
+	int start_page, stop_page;
+	static unsigned version_printed;
+
+	if (ei_debug && version_printed++ == 0)
+		printk(version);
+
+	printk("NE/2 ethercard found in slot %d:", slot);
+
+	/* Read base IO and IRQ from the POS-registers */
+	POS = mca_read_stored_pos(slot, 2);
+	if(!(POS % 2)) {
+		printk(" disabled.\n");
+		return -ENODEV;
+	}
+
+	/* handle different POS register structure for D-Link card */
+
+	if (mca_read_stored_pos(slot, 0) == 0xea) {
+		base_addr = dlink_addresses[(POS >> 5) & 0x03];
+		irq = dlink_irqs[(POS >> 2) & 0x07];
+	}
+        else {
+		i = (POS & 0xE)>>1;
+		/* printk("Halleluja sdog, als er na de pijl een 1 staat is 1 - 1 == 0"
+	   	" en zou het moeten werken -> %d\n", i);
+	   	The above line was for remote testing, thanx to sdog ... */
+		base_addr = addresses[i - 1];
+		irq = irqs[(POS & 0x60)>>5];
+	}
+
+	if (!request_region(base_addr, NE_IO_EXTENT, DRV_NAME))
+		return -EBUSY;
+
+#ifdef DEBUG
+	printk("POS info : pos 2 = %#x ; base = %#x ; irq = %ld\n", POS,
+			base_addr, irq);
+#endif
+
+#ifndef CRYNWR_WAY
+	/* Reset the card the way they do it in the Crynwr packet driver */
+	for (i=0; i<8; i++)
+		outb(0x0, base_addr + NE_RESET);
+	inb(base_addr + NE_RESET);
+	outb(0x21, base_addr + NE_CMD);
+	if (inb(base_addr + NE_CMD) != 0x21) {
+		printk("NE/2 adapter not responding\n");
+		retval = -ENODEV;
+		goto out;
+	}
+
+	/* In the crynwr sources they do a RAM-test here. I skip it. I suppose
+	   my RAM is okay.  Suppose your memory is broken.  Then this test
+	   should fail and you won't be able to use your card.  But if I do not
+	   test, you won't be able to use your card, neither.  So this test
+	   won't help you. */
+
+#else  /* _I_ never tested it this way .. Go ahead and try ...*/
+	/* Reset card. Who knows what dain-bramaged state it was left in. */
+	{
+		unsigned long reset_start_time = jiffies;
+
+		/* DON'T change these to inb_p/outb_p or reset will fail on
+		   clones.. */
+		outb(inb(base_addr + NE_RESET), base_addr + NE_RESET);
+
+		while ((inb_p(base_addr + EN0_ISR) & ENISR_RESET) == 0)
+			if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
+				printk(" not found (no reset ack).\n");
+				retval = -ENODEV;
+				goto out;
+			}
+
+		outb_p(0xff, base_addr + EN0_ISR);         /* Ack all intr. */
+	}
+#endif
+
+
+	/* Read the 16 bytes of station address PROM.
+	   We must first initialize registers, similar to
+	   NS8390p_init(eifdev, 0).
+	   We can't reliably read the SAPROM address without this.
+	   (I learned the hard way!). */
+	{
+		struct {
+			unsigned char value, offset;
+		} program_seq[] = {
+						/* Select page 0 */
+			{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD},
+			{0x49,	EN0_DCFG},  /* Set WORD-wide (0x49) access. */
+			{0x00,	EN0_RCNTLO},  /* Clear the count regs. */
+			{0x00,	EN0_RCNTHI},
+			{0x00,	EN0_IMR},  /* Mask completion irq. */
+			{0xFF,	EN0_ISR},
+			{E8390_RXOFF, EN0_RXCR},  /* 0x20  Set to monitor */
+			{E8390_TXOFF, EN0_TXCR},  /* 0x02  and loopback mode. */
+			{32,	EN0_RCNTLO},
+			{0x00,	EN0_RCNTHI},
+			{0x00,	EN0_RSARLO},  /* DMA starting at 0x0000. */
+			{0x00,	EN0_RSARHI},
+			{E8390_RREAD+E8390_START, E8390_CMD},
+		};
+
+		for (i = 0; i < ARRAY_SIZE(program_seq); i++)
+			outb_p(program_seq[i].value, base_addr +
+				program_seq[i].offset);
+
+	}
+	for(i = 0; i < 6 /*sizeof(SA_prom)*/; i+=1) {
+		SA_prom[i] = inb(base_addr + NE_DATAPORT);
+	}
+
+	/* I don't know whether the previous sequence includes the general
+           board reset procedure, so better don't omit it and just overwrite
+           the garbage read from a DE-320 with correct stuff. */
+
+	if (mca_read_stored_pos(slot, 0) == 0xea) {
+		unsigned int v;
+
+		for (i = 0; i < 3; i++) {
+ 			v = dlink_get_eeprom(i, base_addr);
+			SA_prom[(i << 1)    ] = v & 0xff;
+			SA_prom[(i << 1) + 1] = (v >> 8) & 0xff;
+		}
+	}
+
+	start_page = NESM_START_PG;
+	stop_page = NESM_STOP_PG;
+
+	dev->irq=irq;
+
+	/* Snarf the interrupt now.  There's no point in waiting since we cannot
+	   share and the board will usually be enabled. */
+	retval = request_irq(dev->irq, eip_interrupt, 0, DRV_NAME, dev);
+	if (retval) {
+		printk (" unable to get IRQ %d (irqval=%d).\n",
+				dev->irq, retval);
+		goto out;
+	}
+
+	dev->base_addr = base_addr;
+
+	for(i = 0; i < ETHER_ADDR_LEN; i++)
+		dev->dev_addr[i] = SA_prom[i];
+
+	printk(" %pM\n", dev->dev_addr);
+
+	printk("%s: %s found at %#x, using IRQ %d.\n",
+			dev->name, name, base_addr, dev->irq);
+
+	mca_set_adapter_procfn(slot, (MCA_ProcFn) ne2_procinfo, dev);
+
+	ei_status.name = name;
+	ei_status.tx_start_page = start_page;
+	ei_status.stop_page = stop_page;
+	ei_status.word16 = (2 == 2);
+
+	ei_status.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;
+#endif
+
+	ei_status.reset_8390 = &ne_reset_8390;
+	ei_status.block_input = &ne_block_input;
+	ei_status.block_output = &ne_block_output;
+	ei_status.get_8390_hdr = &ne_get_8390_hdr;
+
+	ei_status.priv = slot;
+
+	dev->netdev_ops = &eip_netdev_ops;
+	NS8390p_init(dev, 0);
+
+	retval = register_netdev(dev);
+	if (retval)
+		goto out1;
+	return 0;
+out1:
+	mca_set_adapter_procfn( ei_status.priv, NULL, NULL);
+	free_irq(dev->irq, dev);
+out:
+	release_region(base_addr, NE_IO_EXTENT);
+	return retval;
+}
+
+/* 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 ne_reset_8390(struct net_device *dev)
+{
+	unsigned long reset_start_time = jiffies;
+
+	if (ei_debug > 1)
+		printk("resetting the 8390 t=%ld...", jiffies);
+
+	/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
+	outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+	ei_status.txing = 0;
+	ei_status.dmaing = 0;
+
+	/* This check _should_not_ be necessary, omit eventually. */
+	while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
+		if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
+			printk("%s: ne_reset_8390() did not complete.\n",
+					dev->name);
+			break;
+		}
+	outb_p(ENISR_RESET, NE_BASE + EN0_ISR);	/* Ack intr. */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+		int ring_page)
+{
+
+	int nic_base = dev->base_addr;
+
+	/* This *shouldn't* happen.
+	   If it does, it's the last thing you'll see */
+	if (ei_status.dmaing) {
+		printk("%s: DMAing conflict in ne_get_8390_hdr "
+				"[DMAstat:%d][irqlock:%d].\n",
+				dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+
+	ei_status.dmaing |= 0x01;
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+	outb_p(0, nic_base + EN0_RCNTHI);
+	outb_p(0, nic_base + EN0_RSARLO);		/* On page boundary */
+	outb_p(ring_page, nic_base + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+	if (ei_status.word16)
+		insw(NE_BASE + NE_DATAPORT, hdr,
+				sizeof(struct e8390_pkt_hdr)>>1);
+	else
+		insb(NE_BASE + NE_DATAPORT, hdr,
+				sizeof(struct e8390_pkt_hdr));
+
+	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+}
+
+/* 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 outb. */
+
+static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb,
+		int ring_offset)
+{
+#ifdef NE_SANITY_CHECK
+	int xfer_count = count;
+#endif
+	int nic_base = dev->base_addr;
+	char *buf = skb->data;
+
+	/* This *shouldn't* happen.
+	   If it does, it's the last thing you'll see */
+	if (ei_status.dmaing) {
+		printk("%s: DMAing conflict in ne_block_input "
+				"[DMAstat:%d][irqlock:%d].\n",
+				dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+	ei_status.dmaing |= 0x01;
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+	outb_p(count >> 8, nic_base + EN0_RCNTHI);
+	outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
+	outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+	if (ei_status.word16) {
+		insw(NE_BASE + NE_DATAPORT,buf,count>>1);
+		if (count & 0x01) {
+			buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+#ifdef NE_SANITY_CHECK
+			xfer_count++;
+#endif
+		}
+	} else {
+		insb(NE_BASE + NE_DATAPORT, buf, count);
+	}
+
+#ifdef NE_SANITY_CHECK
+	/* This was for the ALPHA version only, but enough people have
+	   been encountering problems so it is still here.  If you see
+	   this message you either 1) have a slightly incompatible clone
+	   or 2) have noise/speed problems with your bus. */
+	if (ei_debug > 1) {	/* DMA termination address check... */
+		int addr, tries = 20;
+		do {
+			/* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
+			   -- it's broken for Rx on some cards! */
+			int high = inb_p(nic_base + EN0_RSARHI);
+			int low = inb_p(nic_base + EN0_RSARLO);
+			addr = (high << 8) + low;
+			if (((ring_offset + xfer_count) & 0xff) == low)
+				break;
+		} while (--tries > 0);
+		if (tries <= 0)
+			printk("%s: RX transfer address mismatch,"
+				"%#4.4x (expected) vs. %#4.4x (actual).\n",
+				dev->name, ring_offset + xfer_count, addr);
+	}
+#endif
+	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+}
+
+static void ne_block_output(struct net_device *dev, int count,
+		const unsigned char *buf, const int start_page)
+{
+	int nic_base = NE_BASE;
+	unsigned long dma_start;
+#ifdef NE_SANITY_CHECK
+	int retries = 0;
+#endif
+
+	/* 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))
+		count++;
+
+	/* This *shouldn't* happen.
+	   If it does, it's the last thing you'll see */
+	if (ei_status.dmaing) {
+		printk("%s: DMAing conflict in ne_block_output."
+				"[DMAstat:%d][irqlock:%d]\n",
+				dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+	ei_status.dmaing |= 0x01;
+	/* We should already be in page 0, but to be safe... */
+	outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+#ifdef NE_SANITY_CHECK
+retry:
+#endif
+
+#ifdef NE8390_RW_BUGFIX
+	/* Handle the read-before-write bug the same way as the
+	   Crynwr packet driver -- the NatSemi method doesn't work.
+	   Actually this doesn't always work either, but if you have
+	   problems with your NEx000 this is better than nothing! */
+	outb_p(0x42, nic_base + EN0_RCNTLO);
+	outb_p(0x00, nic_base + EN0_RCNTHI);
+	outb_p(0x42, nic_base + EN0_RSARLO);
+	outb_p(0x00, nic_base + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+	/* Make certain that the dummy read has occurred. */
+	SLOW_DOWN_IO;
+	SLOW_DOWN_IO;
+	SLOW_DOWN_IO;
+#endif
+
+	outb_p(ENISR_RDC, nic_base + EN0_ISR);
+
+	/* Now the normal output. */
+	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+	outb_p(count >> 8,   nic_base + EN0_RCNTHI);
+	outb_p(0x00, nic_base + EN0_RSARLO);
+	outb_p(start_page, nic_base + EN0_RSARHI);
+
+	outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+	if (ei_status.word16) {
+		outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
+	} else {
+		outsb(NE_BASE + NE_DATAPORT, buf, count);
+	}
+
+	dma_start = jiffies;
+
+#ifdef NE_SANITY_CHECK
+	/* This was for the ALPHA version only, but enough people have
+	   been encountering problems so it is still here. */
+
+	if (ei_debug > 1) {		/* DMA termination address check... */
+		int addr, tries = 20;
+		do {
+			int high = inb_p(nic_base + EN0_RSARHI);
+			int low = inb_p(nic_base + EN0_RSARLO);
+			addr = (high << 8) + low;
+			if ((start_page << 8) + count == addr)
+				break;
+		} while (--tries > 0);
+		if (tries <= 0) {
+			printk("%s: Tx packet transfer address mismatch,"
+					"%#4.4x (expected) vs. %#4.4x (actual).\n",
+					dev->name, (start_page << 8) + count, addr);
+			if (retries++ == 0)
+				goto retry;
+		}
+	}
+#endif
+
+	while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
+		if (time_after(jiffies, dma_start + 2*HZ/100)) {		/* 20ms */
+			printk("%s: timeout waiting for Tx RDC.\n", dev->name);
+			ne_reset_8390(dev);
+			NS8390p_init(dev, 1);
+			break;
+		}
+
+	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+}
+
+
+#ifdef MODULE
+#define MAX_NE_CARDS	4	/* Max number of NE cards per module */
+static struct net_device *dev_ne[MAX_NE_CARDS];
+static int io[MAX_NE_CARDS];
+static int irq[MAX_NE_CARDS];
+static int bad[MAX_NE_CARDS];	/* 0xbad = bad sig or no reset ack */
+MODULE_LICENSE("GPL");
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(bad, int, NULL, 0);
+MODULE_PARM_DESC(io, "(ignored)");
+MODULE_PARM_DESC(irq, "(ignored)");
+MODULE_PARM_DESC(bad, "(ignored)");
+
+/* Module code fixed by David Weinehall */
+
+int __init init_module(void)
+{
+	struct net_device *dev;
+	int this_dev, found = 0;
+
+	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+		dev = alloc_eip_netdev();
+		if (!dev)
+			break;
+		dev->irq = irq[this_dev];
+		dev->mem_end = bad[this_dev];
+		dev->base_addr = io[this_dev];
+		if (do_ne2_probe(dev) == 0) {
+			dev_ne[found++] = dev;
+			continue;
+		}
+		free_netdev(dev);
+		break;
+	}
+	if (found)
+		return 0;
+	printk(KERN_WARNING "ne2.c: No NE/2 card found\n");
+	return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+	mca_mark_as_unused(ei_status.priv);
+	mca_set_adapter_procfn( ei_status.priv, NULL, NULL);
+	free_irq(dev->irq, dev);
+	release_region(dev->base_addr, NE_IO_EXTENT);
+}
+
+void __exit cleanup_module(void)
+{
+	int this_dev;
+
+	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+		struct net_device *dev = dev_ne[this_dev];
+		if (dev) {
+			unregister_netdev(dev);
+			cleanup_card(dev);
+			free_netdev(dev);
+		}
+	}
+}
+#endif /* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/ne2k-pci.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/ne2k-pci.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/ne2k-pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/ne2k-pci.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,726 @@
+/* ne2k-pci.c: A NE2000 clone on PCI bus driver for Linux. */
+/*
+	A Linux device driver for PCI NE2000 clones.
+
+	Authors and other copyright holders:
+	1992-2000 by Donald Becker, NE2000 core and various modifications.
+	1995-1998 by Paul Gortmaker, core modifications and PCI support.
+	Copyright 1993 assigned to the United States Government as represented
+	by the Director, National Security Agency.
+
+	This software may be used and distributed according to the terms of
+	the GNU General Public License (GPL), incorporated herein by reference.
+	Drivers based on or derived from this code fall under the GPL and must
+	retain the authorship, copyright and license notice.  This file is not
+	a complete program and may only be used when the entire operating
+	system is licensed under the GPL.
+
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+	Issues remaining:
+	People are making PCI ne2000 clones! Oh the horror, the horror...
+	Limited full-duplex support.
+*/
+
+#define DRV_NAME	"ne2k-pci"
+#define DRV_VERSION	"1.03"
+#define DRV_RELDATE	"9/22/2003"
+
+
+/* The user-configurable values.
+   These may be modified when a driver module is loaded.*/
+
+static int debug = 1;			/* 1 normal messages, 0 quiet .. 7 verbose. */
+
+#define MAX_UNITS 8				/* More are supported, limit only on options */
+/* Used to pass the full-duplex flag, etc. */
+static int full_duplex[MAX_UNITS];
+static int options[MAX_UNITS];
+
+/* Force a non std. amount of memory.  Units are 256 byte pages. */
+/* #define PACKETBUF_MEMSIZE	0x40 */
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "8390.h"
+
+/* These identify the driver base version and may not be removed. */
+static const char version[] __devinitconst =
+	KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE
+	" D. Becker/P. Gortmaker\n";
+
+#if defined(__powerpc__)
+#define inl_le(addr)  le32_to_cpu(inl(addr))
+#define inw_le(addr)  le16_to_cpu(inw(addr))
+#endif
+
+#define PFX DRV_NAME ": "
+
+MODULE_AUTHOR("Donald Becker / Paul Gortmaker");
+MODULE_DESCRIPTION("PCI NE2000 clone driver");
+MODULE_LICENSE("GPL");
+
+module_param(debug, int, 0);
+module_param_array(options, int, NULL, 0);
+module_param_array(full_duplex, int, NULL, 0);
+MODULE_PARM_DESC(debug, "debug level (1-2)");
+MODULE_PARM_DESC(options, "Bit 5: full duplex");
+MODULE_PARM_DESC(full_duplex, "full duplex setting(s) (1)");
+
+/* Some defines that people can play with if so inclined. */
+
+/* Use 32 bit data-movement operations instead of 16 bit. */
+#define USE_LONGIO
+
+/* Do we implement the read before write bugfix ? */
+/* #define NE_RW_BUGFIX */
+
+/* Flags.  We rename an existing ei_status field to store flags! */
+/* Thus only the low 8 bits are usable for non-init-time flags. */
+#define ne2k_flags reg0
+enum {
+	ONLY_16BIT_IO=8, ONLY_32BIT_IO=4,	/* Chip can do only 16/32-bit xfers. */
+	FORCE_FDX=0x20,						/* User override. */
+	REALTEK_FDX=0x40, HOLTEK_FDX=0x80,
+	STOP_PG_0x60=0x100,
+};
+
+enum ne2k_pci_chipsets {
+	CH_RealTek_RTL_8029 = 0,
+	CH_Winbond_89C940,
+	CH_Compex_RL2000,
+	CH_KTI_ET32P2,
+	CH_NetVin_NV5000SC,
+	CH_Via_86C926,
+	CH_SureCom_NE34,
+	CH_Winbond_W89C940F,
+	CH_Holtek_HT80232,
+	CH_Holtek_HT80229,
+	CH_Winbond_89C940_8c4a,
+};
+
+
+static struct {
+	char *name;
+	int flags;
+} pci_clone_list[] __devinitdata = {
+	{"RealTek RTL-8029", REALTEK_FDX},
+	{"Winbond 89C940", 0},
+	{"Compex RL2000", 0},
+	{"KTI ET32P2", 0},
+	{"NetVin NV5000SC", 0},
+	{"Via 86C926", ONLY_16BIT_IO},
+	{"SureCom NE34", 0},
+	{"Winbond W89C940F", 0},
+	{"Holtek HT80232", ONLY_16BIT_IO | HOLTEK_FDX},
+	{"Holtek HT80229", ONLY_32BIT_IO | HOLTEK_FDX | STOP_PG_0x60 },
+	{"Winbond W89C940(misprogrammed)", 0},
+	{NULL,}
+};
+
+
+static DEFINE_PCI_DEVICE_TABLE(ne2k_pci_tbl) = {
+	{ 0x10ec, 0x8029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RealTek_RTL_8029 },
+	{ 0x1050, 0x0940, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_89C940 },
+	{ 0x11f6, 0x1401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Compex_RL2000 },
+	{ 0x8e2e, 0x3000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_KTI_ET32P2 },
+	{ 0x4a14, 0x5000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_NetVin_NV5000SC },
+	{ 0x1106, 0x0926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Via_86C926 },
+	{ 0x10bd, 0x0e34, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_SureCom_NE34 },
+	{ 0x1050, 0x5a5a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_W89C940F },
+	{ 0x12c3, 0x0058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80232 },
+	{ 0x12c3, 0x5598, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80229 },
+	{ 0x8c4a, 0x1980, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_89C940_8c4a },
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, ne2k_pci_tbl);
+
+
+/* ---- No user-serviceable parts below ---- */
+
+#define NE_BASE	 (dev->base_addr)
+#define NE_CMD	 	0x00
+#define NE_DATAPORT	0x10	/* NatSemi-defined port window offset. */
+#define NE_RESET	0x1f	/* Issue a read to reset, a write to clear. */
+#define NE_IO_EXTENT	0x20
+
+#define NESM_START_PG	0x40	/* First page of TX buffer */
+#define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
+
+
+static int ne2k_pci_open(struct net_device *dev);
+static int ne2k_pci_close(struct net_device *dev);
+
+static void ne2k_pci_reset_8390(struct net_device *dev);
+static void ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+			  int ring_page);
+static void ne2k_pci_block_input(struct net_device *dev, int count,
+			  struct sk_buff *skb, int ring_offset);
+static void ne2k_pci_block_output(struct net_device *dev, const int count,
+		const unsigned char *buf, const int start_page);
+static const struct ethtool_ops ne2k_pci_ethtool_ops;
+
+
+
+/* There is no room in the standard 8390 structure for extra info we need,
+   so we build a meta/outer-wrapper structure.. */
+struct ne2k_pci_card {
+	struct net_device *dev;
+	struct pci_dev *pci_dev;
+};
+
+
+
+/*
+  NEx000-clone boards have a Station Address (SA) PROM (SAPROM) in the packet
+  buffer memory space.  By-the-spec NE2000 clones have 0x57,0x57 in bytes
+  0x0e,0x0f of the SAPROM, while other supposed NE2000 clones must be
+  detected by their SA prefix.
+
+  Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
+  mode results in doubled values, which can be detected and compensated for.
+
+  The probe is also responsible for initializing the card and filling
+  in the 'dev' and 'ei_status' structures.
+*/
+
+static const struct net_device_ops ne2k_netdev_ops = {
+	.ndo_open		= ne2k_pci_open,
+	.ndo_stop		= ne2k_pci_close,
+	.ndo_start_xmit		= ei_start_xmit,
+	.ndo_tx_timeout		= ei_tx_timeout,
+	.ndo_get_stats		= ei_get_stats,
+	.ndo_set_rx_mode	= 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,
+#endif
+};
+
+static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
+				     const struct pci_device_id *ent)
+{
+	struct net_device *dev;
+	int i;
+	unsigned char SA_prom[32];
+	int start_page, stop_page;
+	int irq, reg0, chip_idx = ent->driver_data;
+	static unsigned int fnd_cnt;
+	long ioaddr;
+	int flags = pci_clone_list[chip_idx].flags;
+
+/* when built into the kernel, we only print version if device is found */
+#ifndef MODULE
+	static int printed_version;
+	if (!printed_version++)
+		printk(version);
+#endif
+
+	fnd_cnt++;
+
+	i = pci_enable_device (pdev);
+	if (i)
+		return i;
+
+	ioaddr = pci_resource_start (pdev, 0);
+	irq = pdev->irq;
+
+	if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_IO) == 0)) {
+		dev_err(&pdev->dev, "no I/O resource at PCI BAR #0\n");
+		return -ENODEV;
+	}
+
+	if (request_region (ioaddr, NE_IO_EXTENT, DRV_NAME) == NULL) {
+		dev_err(&pdev->dev, "I/O resource 0x%x @ 0x%lx busy\n",
+			NE_IO_EXTENT, ioaddr);
+		return -EBUSY;
+	}
+
+	reg0 = inb(ioaddr);
+	if (reg0 == 0xFF)
+		goto err_out_free_res;
+
+	/* Do a preliminary verification that we have a 8390. */
+	{
+		int regd;
+		outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
+		regd = inb(ioaddr + 0x0d);
+		outb(0xff, ioaddr + 0x0d);
+		outb(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
+		inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
+		if (inb(ioaddr + EN0_COUNTER0) != 0) {
+			outb(reg0, ioaddr);
+			outb(regd, ioaddr + 0x0d);	/* Restore the old values. */
+			goto err_out_free_res;
+		}
+	}
+
+	/* Allocate net_device, dev->priv; fill in 8390 specific dev fields. */
+	dev = alloc_ei_netdev();
+	if (!dev) {
+		dev_err(&pdev->dev, "cannot allocate ethernet device\n");
+		goto err_out_free_res;
+	}
+	dev->netdev_ops = &ne2k_netdev_ops;
+
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	/* Reset card. Who knows what dain-bramaged state it was left in. */
+	{
+		unsigned long reset_start_time = jiffies;
+
+		outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
+
+		/* This looks like a horrible timing loop, but it should never take
+		   more than a few cycles.
+		*/
+		while ((inb(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
+			/* Limit wait: '2' avoids jiffy roll-over. */
+			if (jiffies - reset_start_time > 2) {
+				dev_err(&pdev->dev,
+					"Card failure (no reset ack).\n");
+				goto err_out_free_netdev;
+			}
+
+		outb(0xff, ioaddr + EN0_ISR);		/* Ack all intr. */
+	}
+
+	/* Read the 16 bytes of station address PROM.
+	   We must first initialize registers, similar to NS8390_init(eifdev, 0).
+	   We can't reliably read the SAPROM address without this.
+	   (I learned the hard way!). */
+	{
+		struct {unsigned char value, offset; } program_seq[] = {
+			{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+			{0x49,	EN0_DCFG},	/* Set word-wide access. */
+			{0x00,	EN0_RCNTLO},	/* Clear the count regs. */
+			{0x00,	EN0_RCNTHI},
+			{0x00,	EN0_IMR},	/* Mask completion irq. */
+			{0xFF,	EN0_ISR},
+			{E8390_RXOFF, EN0_RXCR},	/* 0x20  Set to monitor */
+			{E8390_TXOFF, EN0_TXCR},	/* 0x02  and loopback mode. */
+			{32,	EN0_RCNTLO},
+			{0x00,	EN0_RCNTHI},
+			{0x00,	EN0_RSARLO},	/* DMA starting at 0x0000. */
+			{0x00,	EN0_RSARHI},
+			{E8390_RREAD+E8390_START, E8390_CMD},
+		};
+		for (i = 0; i < ARRAY_SIZE(program_seq); i++)
+			outb(program_seq[i].value, ioaddr + program_seq[i].offset);
+
+	}
+
+	/* Note: all PCI cards have at least 16 bit access, so we don't have
+	   to check for 8 bit cards.  Most cards permit 32 bit access. */
+	if (flags & ONLY_32BIT_IO) {
+		for (i = 0; i < 4 ; i++)
+			((u32 *)SA_prom)[i] = le32_to_cpu(inl(ioaddr + NE_DATAPORT));
+	} else
+		for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++)
+			SA_prom[i] = inb(ioaddr + NE_DATAPORT);
+
+	/* We always set the 8390 registers for word mode. */
+	outb(0x49, ioaddr + EN0_DCFG);
+	start_page = NESM_START_PG;
+
+	stop_page = flags & STOP_PG_0x60 ? 0x60 : NESM_STOP_PG;
+
+	/* Set up the rest of the parameters. */
+	dev->irq = irq;
+	dev->base_addr = ioaddr;
+	pci_set_drvdata(pdev, dev);
+
+	ei_status.name = pci_clone_list[chip_idx].name;
+	ei_status.tx_start_page = start_page;
+	ei_status.stop_page = stop_page;
+	ei_status.word16 = 1;
+	ei_status.ne2k_flags = flags;
+	if (fnd_cnt < MAX_UNITS) {
+		if (full_duplex[fnd_cnt] > 0  ||  (options[fnd_cnt] & FORCE_FDX))
+			ei_status.ne2k_flags |= FORCE_FDX;
+	}
+
+	ei_status.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;
+#endif
+
+	ei_status.reset_8390 = &ne2k_pci_reset_8390;
+	ei_status.block_input = &ne2k_pci_block_input;
+	ei_status.block_output = &ne2k_pci_block_output;
+	ei_status.get_8390_hdr = &ne2k_pci_get_8390_hdr;
+	ei_status.priv = (unsigned long) pdev;
+
+	dev->ethtool_ops = &ne2k_pci_ethtool_ops;
+	NS8390_init(dev, 0);
+
+	memcpy(dev->dev_addr, SA_prom, dev->addr_len);
+	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
+	i = register_netdev(dev);
+	if (i)
+		goto err_out_free_netdev;
+
+	printk("%s: %s found at %#lx, IRQ %d, %pM.\n",
+	       dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq,
+	       dev->dev_addr);
+
+	return 0;
+
+err_out_free_netdev:
+	free_netdev (dev);
+err_out_free_res:
+	release_region (ioaddr, NE_IO_EXTENT);
+	pci_set_drvdata (pdev, NULL);
+	return -ENODEV;
+
+}
+
+/*
+ * Magic incantation sequence for full duplex on the supported cards.
+ */
+static inline int set_realtek_fdx(struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+
+	outb(0xC0 + E8390_NODMA, ioaddr + NE_CMD); /* Page 3 */
+	outb(0xC0, ioaddr + 0x01); /* Enable writes to CONFIG3 */
+	outb(0x40, ioaddr + 0x06); /* Enable full duplex */
+	outb(0x00, ioaddr + 0x01); /* Disable writes to CONFIG3 */
+	outb(E8390_PAGE0 + E8390_NODMA, ioaddr + NE_CMD); /* Page 0 */
+	return 0;
+}
+
+static inline int set_holtek_fdx(struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+
+	outb(inb(ioaddr + 0x20) | 0x80, ioaddr + 0x20);
+	return 0;
+}
+
+static int ne2k_pci_set_fdx(struct net_device *dev)
+{
+	if (ei_status.ne2k_flags & REALTEK_FDX)
+		return set_realtek_fdx(dev);
+	else if (ei_status.ne2k_flags & HOLTEK_FDX)
+		return set_holtek_fdx(dev);
+
+	return -EOPNOTSUPP;
+}
+
+static int ne2k_pci_open(struct net_device *dev)
+{
+	int ret = request_irq(dev->irq, ei_interrupt, IRQF_SHARED, dev->name, dev);
+	if (ret)
+		return ret;
+
+	if (ei_status.ne2k_flags & FORCE_FDX)
+		ne2k_pci_set_fdx(dev);
+
+	ei_open(dev);
+	return 0;
+}
+
+static int ne2k_pci_close(struct net_device *dev)
+{
+	ei_close(dev);
+	free_irq(dev->irq, dev);
+	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. */
+static void ne2k_pci_reset_8390(struct net_device *dev)
+{
+	unsigned long reset_start_time = jiffies;
+
+	if (debug > 1) printk("%s: Resetting the 8390 t=%ld...",
+						  dev->name, jiffies);
+
+	outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+	ei_status.txing = 0;
+	ei_status.dmaing = 0;
+
+	/* This check _should_not_ be necessary, omit eventually. */
+	while ((inb(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
+		if (jiffies - reset_start_time > 2) {
+			printk("%s: ne2k_pci_reset_8390() did not complete.\n", dev->name);
+			break;
+		}
+	outb(ENISR_RESET, NE_BASE + EN0_ISR);	/* Ack intr. */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+
+	long nic_base = dev->base_addr;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+	if (ei_status.dmaing) {
+		printk("%s: DMAing conflict in ne2k_pci_get_8390_hdr "
+			   "[DMAstat:%d][irqlock:%d].\n",
+			   dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+
+	ei_status.dmaing |= 0x01;
+	outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+	outb(0, nic_base + EN0_RCNTHI);
+	outb(0, nic_base + EN0_RSARLO);		/* On page boundary */
+	outb(ring_page, nic_base + EN0_RSARHI);
+	outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+	if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
+		insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+	} else {
+		*(u32*)hdr = le32_to_cpu(inl(NE_BASE + NE_DATAPORT));
+		le16_to_cpus(&hdr->count);
+	}
+
+	outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+}
+
+/* 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 outb. */
+
+static void ne2k_pci_block_input(struct net_device *dev, int count,
+				 struct sk_buff *skb, int ring_offset)
+{
+	long nic_base = dev->base_addr;
+	char *buf = skb->data;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+	if (ei_status.dmaing) {
+		printk("%s: DMAing conflict in ne2k_pci_block_input "
+			   "[DMAstat:%d][irqlock:%d].\n",
+			   dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+	ei_status.dmaing |= 0x01;
+	if (ei_status.ne2k_flags & ONLY_32BIT_IO)
+		count = (count + 3) & 0xFFFC;
+	outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	outb(count & 0xff, nic_base + EN0_RCNTLO);
+	outb(count >> 8, nic_base + EN0_RCNTHI);
+	outb(ring_offset & 0xff, nic_base + EN0_RSARLO);
+	outb(ring_offset >> 8, nic_base + EN0_RSARHI);
+	outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+	if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
+		insw(NE_BASE + NE_DATAPORT,buf,count>>1);
+		if (count & 0x01) {
+			buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+		}
+	} else {
+		insl(NE_BASE + NE_DATAPORT, buf, count>>2);
+		if (count & 3) {
+			buf += count & ~3;
+			if (count & 2) {
+				__le16 *b = (__le16 *)buf;
+
+				*b++ = cpu_to_le16(inw(NE_BASE + NE_DATAPORT));
+				buf = (char *)b;
+			}
+			if (count & 1)
+				*buf = inb(NE_BASE + NE_DATAPORT);
+		}
+	}
+
+	outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+}
+
+static void ne2k_pci_block_output(struct net_device *dev, int count,
+				  const unsigned char *buf, const int start_page)
+{
+	long nic_base = NE_BASE;
+	unsigned long dma_start;
+
+	/* On little-endian it's always safe to round the count up for
+	   word writes. */
+	if (ei_status.ne2k_flags & ONLY_32BIT_IO)
+		count = (count + 3) & 0xFFFC;
+	else
+		if (count & 0x01)
+			count++;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+	if (ei_status.dmaing) {
+		printk("%s: DMAing conflict in ne2k_pci_block_output."
+			   "[DMAstat:%d][irqlock:%d]\n",
+			   dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+	ei_status.dmaing |= 0x01;
+	/* We should already be in page 0, but to be safe... */
+	outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+#ifdef NE8390_RW_BUGFIX
+	/* Handle the read-before-write bug the same way as the
+	   Crynwr packet driver -- the NatSemi method doesn't work.
+	   Actually this doesn't always work either, but if you have
+	   problems with your NEx000 this is better than nothing! */
+	outb(0x42, nic_base + EN0_RCNTLO);
+	outb(0x00, nic_base + EN0_RCNTHI);
+	outb(0x42, nic_base + EN0_RSARLO);
+	outb(0x00, nic_base + EN0_RSARHI);
+	outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+#endif
+	outb(ENISR_RDC, nic_base + EN0_ISR);
+
+   /* Now the normal output. */
+	outb(count & 0xff, nic_base + EN0_RCNTLO);
+	outb(count >> 8,   nic_base + EN0_RCNTHI);
+	outb(0x00, nic_base + EN0_RSARLO);
+	outb(start_page, nic_base + EN0_RSARHI);
+	outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+	if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
+		outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
+	} else {
+		outsl(NE_BASE + NE_DATAPORT, buf, count>>2);
+		if (count & 3) {
+			buf += count & ~3;
+			if (count & 2) {
+				__le16 *b = (__le16 *)buf;
+
+				outw(le16_to_cpu(*b++), NE_BASE + NE_DATAPORT);
+				buf = (char *)b;
+			}
+		}
+	}
+
+	dma_start = jiffies;
+
+	while ((inb(nic_base + EN0_ISR) & ENISR_RDC) == 0)
+		if (jiffies - dma_start > 2) {			/* Avoid clock roll-over. */
+			printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
+			ne2k_pci_reset_8390(dev);
+			NS8390_init(dev,1);
+			break;
+		}
+
+	outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+}
+
+static void ne2k_pci_get_drvinfo(struct net_device *dev,
+				 struct ethtool_drvinfo *info)
+{
+	struct ei_device *ei = netdev_priv(dev);
+	struct pci_dev *pci_dev = (struct pci_dev *) ei->priv;
+
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, pci_name(pci_dev));
+}
+
+static const struct ethtool_ops ne2k_pci_ethtool_ops = {
+	.get_drvinfo		= ne2k_pci_get_drvinfo,
+};
+
+static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	BUG_ON(!dev);
+	unregister_netdev(dev);
+	release_region(dev->base_addr, NE_IO_EXTENT);
+	free_netdev(dev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+}
+
+#ifdef CONFIG_PM
+static int ne2k_pci_suspend (struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *dev = pci_get_drvdata (pdev);
+
+	netif_device_detach(dev);
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+	return 0;
+}
+
+static int ne2k_pci_resume (struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata (pdev);
+	int rc;
+
+	pci_set_power_state(pdev, 0);
+	pci_restore_state(pdev);
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	NS8390_init(dev, 1);
+	netif_device_attach(dev);
+
+	return 0;
+}
+
+#endif /* CONFIG_PM */
+
+
+static struct pci_driver ne2k_driver = {
+	.name		= DRV_NAME,
+	.probe		= ne2k_pci_init_one,
+	.remove		= __devexit_p(ne2k_pci_remove_one),
+	.id_table	= ne2k_pci_tbl,
+#ifdef CONFIG_PM
+	.suspend	= ne2k_pci_suspend,
+	.resume		= ne2k_pci_resume,
+#endif /* CONFIG_PM */
+
+};
+
+
+static int __init ne2k_pci_init(void)
+{
+/* when a module, this is printed whether or not devices are found in probe */
+#ifdef MODULE
+	printk(version);
+#endif
+	return pci_register_driver(&ne2k_driver);
+}
+
+
+static void __exit ne2k_pci_cleanup(void)
+{
+	pci_unregister_driver (&ne2k_driver);
+}
+
+module_init(ne2k_pci_init);
+module_exit(ne2k_pci_cleanup);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/ne3210.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/ne3210.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/ne3210.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/ne3210.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,347 @@
+/*
+	ne3210.c
+
+	Linux driver for Novell NE3210 EISA Network Adapter
+
+	Copyright (C) 1998, Paul Gortmaker.
+
+	This software may be used and distributed according to the terms
+	of the GNU General Public License, incorporated herein by reference.
+
+	Information and Code Sources:
+
+	1) Based upon my other EISA 8390 drivers (lne390, es3210, smc-ultra32)
+	2) The existing myriad of other Linux 8390 drivers by Donald Becker.
+	3) Info for getting IRQ and sh-mem gleaned from the EISA cfg file
+
+	The NE3210 is an EISA shared memory NS8390 implementation.  Shared
+	memory address > 1MB should work with this driver.
+
+	Note that the .cfg file (3/11/93, v1.0) has AUI and BNC switched
+	around (or perhaps there are some defective/backwards cards ???)
+
+	This driver WILL NOT WORK FOR THE NE3200 - it is completely different
+	and does not use an 8390 at all.
+
+	Updated to EISA probing API 5/2003 by Marc Zyngier.
+*/
+
+#include <linux/module.h>
+#include <linux/eisa.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "8390.h"
+
+#define DRV_NAME "ne3210"
+
+static void ne3210_reset_8390(struct net_device *dev);
+
+static void ne3210_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
+static void ne3210_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset);
+static void ne3210_block_output(struct net_device *dev, int count, const unsigned char *buf, const int start_page);
+
+#define NE3210_START_PG		0x00    /* First page of TX buffer	*/
+#define NE3210_STOP_PG		0x80    /* Last page +1 of RX ring	*/
+
+#define NE3210_IO_EXTENT	0x20
+#define NE3210_SA_PROM		0x16	/* Start of e'net addr.		*/
+#define NE3210_RESET_PORT	0xc84
+#define NE3210_NIC_OFFSET	0x00	/* Hello, the 8390 is *here*	*/
+
+#define NE3210_ADDR0		0x00	/* 3 byte vendor prefix		*/
+#define NE3210_ADDR1		0x00
+#define NE3210_ADDR2		0x1b
+
+#define NE3210_CFG1		0xc84	/* NB: 0xc84 is also "reset" port. */
+#define NE3210_CFG2		0xc90
+#define NE3210_CFG_EXTENT       (NE3210_CFG2 - NE3210_CFG1 + 1)
+
+/*
+ *	You can OR any of the following bits together and assign it
+ *	to NE3210_DEBUG to get verbose driver info during operation.
+ *	Currently only the probe one is implemented.
+ */
+
+#define NE3210_D_PROBE	0x01
+#define NE3210_D_RX_PKT	0x02
+#define NE3210_D_TX_PKT	0x04
+#define NE3210_D_IRQ	0x08
+
+#define NE3210_DEBUG	0x0
+
+static unsigned char irq_map[] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
+static unsigned int shmem_map[] __initdata = {0xff0, 0xfe0, 0xfff0, 0xd8, 0xffe0, 0xffc0, 0xd0, 0x0};
+static const char *ifmap[] __initdata = {"UTP", "?", "BNC", "AUI"};
+static int ifmap_val[] __initdata = {
+		IF_PORT_10BASET,
+		IF_PORT_UNKNOWN,
+		IF_PORT_10BASE2,
+		IF_PORT_AUI,
+};
+
+static int __init ne3210_eisa_probe (struct device *device)
+{
+	unsigned long ioaddr, phys_mem;
+	int i, retval, port_index;
+	struct eisa_device *edev = to_eisa_device (device);
+	struct net_device *dev;
+
+	/* Allocate dev->priv and fill in 8390 specific dev fields. */
+	if (!(dev = alloc_ei_netdev ())) {
+		printk ("ne3210.c: unable to allocate memory for dev!\n");
+		return -ENOMEM;
+	}
+
+	SET_NETDEV_DEV(dev, device);
+	dev_set_drvdata(device, dev);
+	ioaddr = edev->base_addr;
+
+	if (!request_region(ioaddr, NE3210_IO_EXTENT, DRV_NAME)) {
+		retval = -EBUSY;
+		goto out;
+	}
+
+	if (!request_region(ioaddr + NE3210_CFG1,
+			    NE3210_CFG_EXTENT, DRV_NAME)) {
+		retval = -EBUSY;
+		goto out1;
+	}
+
+#if NE3210_DEBUG & NE3210_D_PROBE
+	printk("ne3210-debug: probe at %#x, ID %s\n", ioaddr, edev->id.sig);
+	printk("ne3210-debug: config regs: %#x %#x\n",
+		inb(ioaddr + NE3210_CFG1), inb(ioaddr + NE3210_CFG2));
+#endif
+
+	port_index = inb(ioaddr + NE3210_CFG2) >> 6;
+	for(i = 0; i < ETHER_ADDR_LEN; i++)
+		dev->dev_addr[i] = inb(ioaddr + NE3210_SA_PROM + i);
+	printk("ne3210.c: NE3210 in EISA slot %d, media: %s, addr: %pM.\n",
+		edev->slot, ifmap[port_index], dev->dev_addr);
+
+	/* Snarf the interrupt now. CFG file has them all listed as `edge' with share=NO */
+	dev->irq = irq_map[(inb(ioaddr + NE3210_CFG2) >> 3) & 0x07];
+	printk("ne3210.c: using IRQ %d, ", dev->irq);
+
+	retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
+	if (retval) {
+		printk (" unable to get IRQ %d.\n", dev->irq);
+		goto out2;
+	}
+
+	phys_mem = shmem_map[inb(ioaddr + NE3210_CFG2) & 0x07] * 0x1000;
+
+	/*
+	   BEWARE!! Some dain-bramaged EISA SCUs will allow you to put
+	   the card mem within the region covered by `normal' RAM  !!!
+	*/
+	if (phys_mem > 1024*1024) {	/* phys addr > 1MB */
+		if (phys_mem < virt_to_phys(high_memory)) {
+			printk(KERN_CRIT "ne3210.c: Card RAM overlaps with normal memory!!!\n");
+			printk(KERN_CRIT "ne3210.c: Use EISA SCU to set card memory below 1MB,\n");
+			printk(KERN_CRIT "ne3210.c: or to an address above 0x%llx.\n",
+				(u64)virt_to_phys(high_memory));
+			printk(KERN_CRIT "ne3210.c: Driver NOT installed.\n");
+			retval = -EINVAL;
+			goto out3;
+		}
+	}
+
+	if (!request_mem_region (phys_mem, NE3210_STOP_PG*0x100, DRV_NAME)) {
+		printk ("ne3210.c: Unable to request shared memory at physical address %#lx\n",
+			phys_mem);
+		goto out3;
+	}
+
+	printk("%dkB memory at physical address %#lx\n",
+	       NE3210_STOP_PG/4, phys_mem);
+
+	ei_status.mem = ioremap(phys_mem, NE3210_STOP_PG*0x100);
+	if (!ei_status.mem) {
+		printk(KERN_ERR "ne3210.c: Unable to remap card memory !!\n");
+		printk(KERN_ERR "ne3210.c: Driver NOT installed.\n");
+		retval = -EAGAIN;
+		goto out4;
+	}
+	printk("ne3210.c: remapped %dkB card memory to virtual address %p\n",
+	       NE3210_STOP_PG/4, ei_status.mem);
+	dev->mem_start = (unsigned long)ei_status.mem;
+	dev->mem_end = dev->mem_start + (NE3210_STOP_PG - NE3210_START_PG)*256;
+
+	/* The 8390 offset is zero for the NE3210 */
+	dev->base_addr = ioaddr;
+
+	ei_status.name = "NE3210";
+	ei_status.tx_start_page = NE3210_START_PG;
+	ei_status.rx_start_page = NE3210_START_PG + TX_PAGES;
+	ei_status.stop_page = NE3210_STOP_PG;
+	ei_status.word16 = 1;
+	ei_status.priv = phys_mem;
+
+	if (ei_debug > 0)
+		printk("ne3210 loaded.\n");
+
+	ei_status.reset_8390 = &ne3210_reset_8390;
+	ei_status.block_input = &ne3210_block_input;
+	ei_status.block_output = &ne3210_block_output;
+	ei_status.get_8390_hdr = &ne3210_get_8390_hdr;
+
+	dev->netdev_ops = &ei_netdev_ops;
+
+	dev->if_port = ifmap_val[port_index];
+
+	if ((retval = register_netdev (dev)))
+		goto out5;
+
+	NS8390_init(dev, 0);
+	return 0;
+
+ out5:
+	iounmap(ei_status.mem);
+ out4:
+	release_mem_region (phys_mem, NE3210_STOP_PG*0x100);
+ out3:
+	free_irq (dev->irq, dev);
+ out2:
+	release_region (ioaddr + NE3210_CFG1, NE3210_CFG_EXTENT);
+ out1:
+	release_region (ioaddr, NE3210_IO_EXTENT);
+ out:
+	free_netdev (dev);
+
+	return retval;
+}
+
+static int __devexit ne3210_eisa_remove (struct device *device)
+{
+	struct net_device  *dev    = dev_get_drvdata(device);
+	unsigned long       ioaddr = to_eisa_device (device)->base_addr;
+
+	unregister_netdev (dev);
+	iounmap(ei_status.mem);
+	release_mem_region (ei_status.priv, NE3210_STOP_PG*0x100);
+	free_irq (dev->irq, dev);
+	release_region (ioaddr + NE3210_CFG1, NE3210_CFG_EXTENT);
+	release_region (ioaddr, NE3210_IO_EXTENT);
+	free_netdev (dev);
+
+	return 0;
+}
+
+/*
+ *	Reset by toggling the "Board Enable" bits (bit 2 and 0).
+ */
+
+static void ne3210_reset_8390(struct net_device *dev)
+{
+	unsigned short ioaddr = dev->base_addr;
+
+	outb(0x04, ioaddr + NE3210_RESET_PORT);
+	if (ei_debug > 1) printk("%s: resetting the NE3210...", dev->name);
+
+	mdelay(2);
+
+	ei_status.txing = 0;
+	outb(0x01, ioaddr + NE3210_RESET_PORT);
+	if (ei_debug > 1) printk("reset done\n");
+}
+
+/*
+ *	Note: In the following three functions is the implicit assumption
+ *	that the associated memcpy will only use "rep; movsl" as long as
+ *	we keep the counts as some multiple of doublewords. This is a
+ *	requirement of the hardware, and also prevents us from using
+ *	eth_io_copy_and_sum() since we can't guarantee it will limit
+ *	itself to doubleword access.
+ */
+
+/*
+ *	Grab the 8390 specific header. Similar to the block_input routine, but
+ *	we don't need to be concerned with ring wrap as the header will be at
+ *	the start of a page, so we optimize accordingly. (A single doubleword.)
+ */
+
+static void
+ne3210_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	void __iomem *hdr_start = ei_status.mem + ((ring_page - NE3210_START_PG)<<8);
+	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	hdr->count = (hdr->count + 3) & ~3;     /* Round up allocation. */
+}
+
+/*
+ *	Block input and output are easy on shared memory ethercards, the only
+ *	complication is when the ring buffer wraps. The count will already
+ *	be rounded up to a doubleword value via ne3210_get_8390_hdr() above.
+ */
+
+static void ne3210_block_input(struct net_device *dev, int count, struct sk_buff *skb,
+						  int ring_offset)
+{
+	void __iomem *start = ei_status.mem + ring_offset - NE3210_START_PG*256;
+
+	if (ring_offset + count > NE3210_STOP_PG*256) {
+		/* Packet wraps over end of ring buffer. */
+		int semi_count = NE3210_STOP_PG*256 - ring_offset;
+		memcpy_fromio(skb->data, start, semi_count);
+		count -= semi_count;
+		memcpy_fromio(skb->data + semi_count,
+				ei_status.mem + TX_PAGES*256, count);
+	} else {
+		/* Packet is in one chunk. */
+		memcpy_fromio(skb->data, start, count);
+	}
+}
+
+static void ne3210_block_output(struct net_device *dev, int count,
+				const unsigned char *buf, int start_page)
+{
+	void __iomem *shmem = ei_status.mem + ((start_page - NE3210_START_PG)<<8);
+
+	count = (count + 3) & ~3;     /* Round up to doubleword */
+	memcpy_toio(shmem, buf, count);
+}
+
+static struct eisa_device_id ne3210_ids[] = {
+	{ "EGL0101" },
+	{ "NVL1801" },
+	{ "" },
+};
+MODULE_DEVICE_TABLE(eisa, ne3210_ids);
+
+static struct eisa_driver ne3210_eisa_driver = {
+	.id_table = ne3210_ids,
+	.driver   = {
+		.name   = "ne3210",
+		.probe  = ne3210_eisa_probe,
+		.remove = __devexit_p (ne3210_eisa_remove),
+	},
+};
+
+MODULE_DESCRIPTION("NE3210 EISA Ethernet driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(eisa, ne3210_ids);
+
+static int ne3210_init(void)
+{
+	return eisa_driver_register (&ne3210_eisa_driver);
+}
+
+static void ne3210_cleanup(void)
+{
+	eisa_driver_unregister (&ne3210_eisa_driver);
+}
+
+module_init (ne3210_init);
+module_exit (ne3210_cleanup);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/ne.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/ne.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/ne.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/ne.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1008 @@
+/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
+/*
+    Written 1992-94 by Donald Becker.
+
+    Copyright 1993 United States Government as represented by the
+    Director, National Security Agency.
+
+    This software may be used and distributed according to the terms
+    of the GNU General Public License, incorporated herein by reference.
+
+    The author may be reached as becker@scyld.com, or C/O
+    Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
+
+    This driver should work with many programmed-I/O 8390-based ethernet
+    boards.  Currently it supports the NE1000, NE2000, many clones,
+    and some Cabletron products.
+
+    Changelog:
+
+    Paul Gortmaker	: use ENISR_RDC to monitor Tx PIO uploads, made
+			  sanity checks and bad clone support optional.
+    Paul Gortmaker	: new reset code, reset card after probe at boot.
+    Paul Gortmaker	: multiple card support for module users.
+    Paul Gortmaker	: Support for PCI ne2k clones, similar to lance.c
+    Paul Gortmaker	: Allow users with bad cards to avoid full probe.
+    Paul Gortmaker	: PCI probe changes, more PCI cards supported.
+    rjohnson@analogic.com : Changed init order so an interrupt will only
+    occur after memory is allocated for dev->priv. Deallocated memory
+    last in cleanup_modue()
+    Richard Guenther    : Added support for ISAPnP cards
+    Paul Gortmaker	: Discontinued PCI support - use ne2k-pci.c instead.
+    Hayato Fujiwara	: Add m32r support.
+
+*/
+
+/* Routines for the NatSemi-based designs (NE[12]000). */
+
+static const char version1[] =
+"ne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)\n";
+static const char version2[] =
+"Last modified Nov 1, 2000 by Paul Gortmaker\n";
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/isapnp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include "8390.h"
+
+#define DRV_NAME "ne"
+
+/* Some defines that people can play with if so inclined. */
+
+/* Do we support clones that don't adhere to 14,15 of the SAprom ? */
+#define SUPPORT_NE_BAD_CLONES
+/* 0xbad = bad sig or no reset ack */
+#define BAD 0xbad
+
+#define MAX_NE_CARDS	4	/* Max number of NE cards per module */
+static struct platform_device *pdev_ne[MAX_NE_CARDS];
+static int io[MAX_NE_CARDS];
+static int irq[MAX_NE_CARDS];
+static int bad[MAX_NE_CARDS];
+
+#ifdef MODULE
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(bad, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es),required");
+MODULE_PARM_DESC(irq, "IRQ number(s)");
+MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures");
+MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver");
+MODULE_LICENSE("GPL");
+#endif /* MODULE */
+
+/* Do we perform extra sanity checks on stuff ? */
+/* #define NE_SANITY_CHECK */
+
+/* Do we implement the read before write bugfix ? */
+/* #define NE_RW_BUGFIX */
+
+/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
+/* #define PACKETBUF_MEMSIZE	0x40 */
+
+/* This is set up so that no ISA autoprobe takes place. We can't guarantee
+that the ne2k probe is the last 8390 based probe to take place (as it
+is at boot) and so the probe will get confused by any other 8390 cards.
+ISA device autoprobes on a running machine are not recommended anyway. */
+#if !defined(MODULE) && (defined(CONFIG_ISA) || defined(CONFIG_M32R))
+/* Do we need a portlist for the ISA auto-probe ? */
+#define NEEDS_PORTLIST
+#endif
+
+/* A zero-terminated list of I/O addresses to be probed at boot. */
+#ifdef NEEDS_PORTLIST
+static unsigned int netcard_portlist[] __initdata = {
+	0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0
+};
+#endif
+
+static struct isapnp_device_id isapnp_clone_list[] __initdata = {
+	{	ISAPNP_CARD_ID('A','X','E',0x2011),
+		ISAPNP_VENDOR('A','X','E'), ISAPNP_FUNCTION(0x2011),
+		(long) "NetGear EA201" },
+	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+		ISAPNP_VENDOR('E','D','I'), ISAPNP_FUNCTION(0x0216),
+		(long) "NN NE2000" },
+	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+		ISAPNP_VENDOR('P','N','P'), ISAPNP_FUNCTION(0x80d6),
+		(long) "Generic PNP" },
+	{ }	/* terminate list */
+};
+
+MODULE_DEVICE_TABLE(isapnp, isapnp_clone_list);
+
+#ifdef SUPPORT_NE_BAD_CLONES
+/* A list of bad clones that we none-the-less recognize. */
+static struct { const char *name8, *name16; unsigned char SAprefix[4];}
+bad_clone_list[] __initdata = {
+    {"DE100", "DE200", {0x00, 0xDE, 0x01,}},
+    {"DE120", "DE220", {0x00, 0x80, 0xc8,}},
+    {"DFI1000", "DFI2000", {'D', 'F', 'I',}}, /* Original, eh?  */
+    {"EtherNext UTP8", "EtherNext UTP16", {0x00, 0x00, 0x79}},
+    {"NE1000","NE2000-invalid", {0x00, 0x00, 0xd8}}, /* Ancient real NE1000. */
+    {"NN1000", "NN2000",  {0x08, 0x03, 0x08}}, /* Outlaw no-name clone. */
+    {"4-DIM8","4-DIM16", {0x00,0x00,0x4d,}},  /* Outlaw 4-Dimension cards. */
+    {"Con-Intl_8", "Con-Intl_16", {0x00, 0x00, 0x24}}, /* Connect Int'nl */
+    {"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */
+    {"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */
+    {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
+    {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
+    {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
+#ifdef CONFIG_MACH_TX49XX
+    {"RBHMA4X00-RTL8019", "RBHMA4X00-RTL8019", {0x00, 0x60, 0x0a}},  /* Toshiba built-in */
+#endif
+    {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
+    {NULL,}
+};
+#endif
+
+/* ---- No user-serviceable parts below ---- */
+
+#define NE_BASE	 (dev->base_addr)
+#define NE_CMD	 	0x00
+#define NE_DATAPORT	0x10	/* NatSemi-defined port window offset. */
+#define NE_RESET	0x1f	/* Issue a read to reset, a write to clear. */
+#define NE_IO_EXTENT	0x20
+
+#define NE1SM_START_PG	0x20	/* First page of TX buffer */
+#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 */
+
+#if defined(CONFIG_PLAT_MAPPI)
+#  define DCR_VAL 0x4b
+#elif defined(CONFIG_PLAT_OAKS32R)  || \
+   defined(CONFIG_MACH_TX49XX)
+#  define DCR_VAL 0x48		/* 8-bit mode */
+#else
+#  define DCR_VAL 0x49
+#endif
+
+static int ne_probe1(struct net_device *dev, unsigned long ioaddr);
+static int ne_probe_isapnp(struct net_device *dev);
+
+static void ne_reset_8390(struct net_device *dev);
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+			  int ring_page);
+static void ne_block_input(struct net_device *dev, int count,
+			  struct sk_buff *skb, int ring_offset);
+static void ne_block_output(struct net_device *dev, const int count,
+		const unsigned char *buf, const int start_page);
+
+
+/*  Probe for various non-shared-memory ethercards.
+
+   NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
+   buffer memory space.  NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
+   the SAPROM, while other supposed NE2000 clones must be detected by their
+   SA prefix.
+
+   Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
+   mode results in doubled values, which can be detected and compensated for.
+
+   The probe is also responsible for initializing the card and filling
+   in the 'dev' and 'ei_status' structures.
+
+   We use the minimum memory size for some ethercard product lines, iff we can't
+   distinguish models.  You can increase the packet buffer size by setting
+   PACKETBUF_MEMSIZE.  Reported Cabletron packet buffer locations are:
+	E1010   starts at 0x100 and ends at 0x2000.
+	E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
+	E2010	 starts at 0x100 and ends at 0x4000.
+	E2010-x starts at 0x100 and ends at 0xffff.  */
+
+static int __init do_ne_probe(struct net_device *dev)
+{
+	unsigned long base_addr = dev->base_addr;
+#ifdef NEEDS_PORTLIST
+	int orig_irq = dev->irq;
+#endif
+
+	/* First check any supplied i/o locations. User knows best. <cough> */
+	if (base_addr > 0x1ff) {	/* Check a single specified location. */
+		int ret = ne_probe1(dev, base_addr);
+		if (ret)
+			printk(KERN_WARNING "ne.c: No NE*000 card found at "
+				"i/o = %#lx\n", base_addr);
+		return ret;
+	}
+	else if (base_addr != 0)	/* Don't probe at all. */
+		return -ENXIO;
+
+	/* Then look for any installed ISAPnP clones */
+	if (isapnp_present() && (ne_probe_isapnp(dev) == 0))
+		return 0;
+
+#ifdef NEEDS_PORTLIST
+	/* Last resort. The semi-risky ISA auto-probe. */
+	for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
+		int ioaddr = netcard_portlist[base_addr];
+		dev->irq = orig_irq;
+		if (ne_probe1(dev, ioaddr) == 0)
+			return 0;
+	}
+#endif
+
+	return -ENODEV;
+}
+
+static int __init ne_probe_isapnp(struct net_device *dev)
+{
+	int i;
+
+	for (i = 0; isapnp_clone_list[i].vendor != 0; i++) {
+		struct pnp_dev *idev = NULL;
+
+		while ((idev = pnp_find_dev(NULL,
+					    isapnp_clone_list[i].vendor,
+					    isapnp_clone_list[i].function,
+					    idev))) {
+			/* Avoid already found cards from previous calls */
+			if (pnp_device_attach(idev) < 0)
+				continue;
+			if (pnp_activate_dev(idev) < 0) {
+			      	pnp_device_detach(idev);
+			      	continue;
+			}
+			/* if no io and irq, search for next */
+			if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) {
+				pnp_device_detach(idev);
+				continue;
+			}
+			/* found it */
+			dev->base_addr = pnp_port_start(idev, 0);
+			dev->irq = pnp_irq(idev, 0);
+			printk(KERN_INFO "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
+				(char *) isapnp_clone_list[i].driver_data,
+				dev->base_addr, dev->irq);
+			if (ne_probe1(dev, dev->base_addr) != 0) {	/* Shouldn't happen. */
+				printk(KERN_ERR "ne.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr);
+				pnp_device_detach(idev);
+				return -ENXIO;
+			}
+			ei_status.priv = (unsigned long)idev;
+			break;
+		}
+		if (!idev)
+			continue;
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
+{
+	int i;
+	unsigned char SA_prom[32];
+	int wordlength = 2;
+	const char *name = NULL;
+	int start_page, stop_page;
+	int neX000, ctron, copam, bad_card;
+	int reg0, ret;
+	static unsigned version_printed;
+
+	if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
+		return -EBUSY;
+
+	reg0 = inb_p(ioaddr);
+	if (reg0 == 0xFF) {
+		ret = -ENODEV;
+		goto err_out;
+	}
+
+	/* Do a preliminary verification that we have a 8390. */
+	{
+		int regd;
+		outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
+		regd = inb_p(ioaddr + 0x0d);
+		outb_p(0xff, ioaddr + 0x0d);
+		outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
+		inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
+		if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
+			outb_p(reg0, ioaddr);
+			outb_p(regd, ioaddr + 0x0d);	/* Restore the old values. */
+			ret = -ENODEV;
+			goto err_out;
+		}
+	}
+
+	if (ei_debug  &&  version_printed++ == 0)
+		printk(KERN_INFO "%s%s", version1, version2);
+
+	printk(KERN_INFO "NE*000 ethercard probe at %#3lx:", ioaddr);
+
+	/* A user with a poor card that fails to ack the reset, or that
+	   does not have a valid 0x57,0x57 signature can still use this
+	   without having to recompile. Specifying an i/o address along
+	   with an otherwise unused dev->mem_end value of "0xBAD" will
+	   cause the driver to skip these parts of the probe. */
+
+	bad_card = ((dev->base_addr != 0) && (dev->mem_end == BAD));
+
+	/* Reset card. Who knows what dain-bramaged state it was left in. */
+
+	{
+		unsigned long reset_start_time = jiffies;
+
+		/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
+		outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
+
+		while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
+		if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
+			if (bad_card) {
+				printk(" (warning: no reset ack)");
+				break;
+			} else {
+				printk(" not found (no reset ack).\n");
+				ret = -ENODEV;
+				goto err_out;
+			}
+		}
+
+		outb_p(0xff, ioaddr + EN0_ISR);		/* Ack all intr. */
+	}
+
+	/* Read the 16 bytes of station address PROM.
+	   We must first initialize registers, similar to NS8390p_init(eifdev, 0).
+	   We can't reliably read the SAPROM address without this.
+	   (I learned the hard way!). */
+	{
+		struct {unsigned char value, offset; } program_seq[] =
+		{
+			{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+			{0x48,	EN0_DCFG},	/* Set byte-wide (0x48) access. */
+			{0x00,	EN0_RCNTLO},	/* Clear the count regs. */
+			{0x00,	EN0_RCNTHI},
+			{0x00,	EN0_IMR},	/* Mask completion irq. */
+			{0xFF,	EN0_ISR},
+			{E8390_RXOFF, EN0_RXCR},	/* 0x20  Set to monitor */
+			{E8390_TXOFF, EN0_TXCR},	/* 0x02  and loopback mode. */
+			{32,	EN0_RCNTLO},
+			{0x00,	EN0_RCNTHI},
+			{0x00,	EN0_RSARLO},	/* DMA starting at 0x0000. */
+			{0x00,	EN0_RSARHI},
+			{E8390_RREAD+E8390_START, E8390_CMD},
+		};
+
+		for (i = 0; i < ARRAY_SIZE(program_seq); i++)
+			outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
+
+	}
+	for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
+		SA_prom[i] = inb(ioaddr + NE_DATAPORT);
+		SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
+		if (SA_prom[i] != SA_prom[i+1])
+			wordlength = 1;
+	}
+
+	if (wordlength == 2)
+	{
+		for (i = 0; i < 16; i++)
+			SA_prom[i] = SA_prom[i+i];
+		/* We must set the 8390 for word mode. */
+		outb_p(DCR_VAL, ioaddr + EN0_DCFG);
+		start_page = NESM_START_PG;
+
+		/*
+		 * Realtek RTL8019AS datasheet says that the PSTOP register
+		 * shouldn't exceed 0x60 in 8-bit mode.
+		 * This chip can be identified by reading the signature from
+		 * the  remote byte count registers (otherwise write-only)...
+		 */
+		if ((DCR_VAL & 0x01) == 0 &&		/* 8-bit mode */
+		    inb(ioaddr + EN0_RCNTLO) == 0x50 &&
+		    inb(ioaddr + EN0_RCNTHI) == 0x70)
+			stop_page = 0x60;
+		else
+			stop_page = NESM_STOP_PG;
+	} else {
+		start_page = NE1SM_START_PG;
+		stop_page  = NE1SM_STOP_PG;
+	}
+
+#if  defined(CONFIG_PLAT_MAPPI) || defined(CONFIG_PLAT_OAKS32R)
+	neX000 = ((SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57)
+		|| (SA_prom[14] == 0x42 && SA_prom[15] == 0x42));
+#else
+	neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
+#endif
+	ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
+	copam =  (SA_prom[14] == 0x49 && SA_prom[15] == 0x00);
+
+	/* Set up the rest of the parameters. */
+	if (neX000 || bad_card || copam) {
+		name = (wordlength == 2) ? "NE2000" : "NE1000";
+	}
+	else if (ctron)
+	{
+		name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
+		start_page = 0x01;
+		stop_page = (wordlength == 2) ? 0x40 : 0x20;
+	}
+	else
+	{
+#ifdef SUPPORT_NE_BAD_CLONES
+		/* Ack!  Well, there might be a *bad* NE*000 clone there.
+		   Check for total bogus addresses. */
+		for (i = 0; bad_clone_list[i].name8; i++)
+		{
+			if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
+				SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
+				SA_prom[2] == bad_clone_list[i].SAprefix[2])
+			{
+				if (wordlength == 2)
+				{
+					name = bad_clone_list[i].name16;
+				} else {
+					name = bad_clone_list[i].name8;
+				}
+				break;
+			}
+		}
+		if (bad_clone_list[i].name8 == NULL)
+		{
+			printk(" not found (invalid signature %2.2x %2.2x).\n",
+				SA_prom[14], SA_prom[15]);
+			ret = -ENXIO;
+			goto err_out;
+		}
+#else
+		printk(" not found.\n");
+		ret = -ENXIO;
+		goto err_out;
+#endif
+	}
+
+	if (dev->irq < 2)
+	{
+		unsigned long cookie = probe_irq_on();
+		outb_p(0x50, ioaddr + EN0_IMR);	/* Enable one interrupt. */
+		outb_p(0x00, ioaddr + EN0_RCNTLO);
+		outb_p(0x00, ioaddr + EN0_RCNTHI);
+		outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
+		mdelay(10);		/* wait 10ms for interrupt to propagate */
+		outb_p(0x00, ioaddr + EN0_IMR); 		/* Mask it again. */
+		dev->irq = probe_irq_off(cookie);
+		if (ei_debug > 2)
+			printk(" autoirq is %d\n", dev->irq);
+	} else if (dev->irq == 2)
+		/* Fixup for users that don't know that IRQ 2 is really IRQ 9,
+		   or don't know which one to set. */
+		dev->irq = 9;
+
+	if (! dev->irq) {
+		printk(" failed to detect IRQ line.\n");
+		ret = -EAGAIN;
+		goto err_out;
+	}
+
+	/* Snarf the interrupt now.  There's no point in waiting since we cannot
+	   share and the board will usually be enabled. */
+	ret = request_irq(dev->irq, eip_interrupt, 0, name, dev);
+	if (ret) {
+		printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
+		goto err_out;
+	}
+
+	dev->base_addr = ioaddr;
+
+#ifdef CONFIG_PLAT_MAPPI
+	outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
+		ioaddr + E8390_CMD); /* 0x61 */
+	for (i = 0 ; i < ETHER_ADDR_LEN ; i++) {
+		dev->dev_addr[i] = SA_prom[i]
+			= inb_p(ioaddr + EN1_PHYS_SHIFT(i));
+	}
+#else
+	for(i = 0; i < ETHER_ADDR_LEN; i++) {
+		dev->dev_addr[i] = SA_prom[i];
+	}
+#endif
+
+	printk("%pM\n", dev->dev_addr);
+
+	ei_status.name = name;
+	ei_status.tx_start_page = start_page;
+	ei_status.stop_page = stop_page;
+
+	/* Use 16-bit mode only if this wasn't overridden by DCR_VAL */
+	ei_status.word16 = (wordlength == 2 && (DCR_VAL & 0x01));
+
+	ei_status.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;
+#endif
+
+	ei_status.reset_8390 = &ne_reset_8390;
+	ei_status.block_input = &ne_block_input;
+	ei_status.block_output = &ne_block_output;
+	ei_status.get_8390_hdr = &ne_get_8390_hdr;
+	ei_status.priv = 0;
+
+	dev->netdev_ops = &eip_netdev_ops;
+	NS8390p_init(dev, 0);
+
+	ret = register_netdev(dev);
+	if (ret)
+		goto out_irq;
+	printk(KERN_INFO "%s: %s found at %#lx, using IRQ %d.\n",
+	       dev->name, name, ioaddr, dev->irq);
+	return 0;
+
+out_irq:
+	free_irq(dev->irq, dev);
+err_out:
+	release_region(ioaddr, NE_IO_EXTENT);
+	return ret;
+}
+
+/* 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 ne_reset_8390(struct net_device *dev)
+{
+	unsigned long reset_start_time = jiffies;
+
+	if (ei_debug > 1)
+		printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
+
+	/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
+	outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+	ei_status.txing = 0;
+	ei_status.dmaing = 0;
+
+	/* This check _should_not_ be necessary, omit eventually. */
+	while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
+		if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
+			printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
+			break;
+		}
+	outb_p(ENISR_RESET, NE_BASE + EN0_ISR);	/* Ack intr. */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	int nic_base = dev->base_addr;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+
+	if (ei_status.dmaing)
+	{
+		printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
+			"[DMAstat:%d][irqlock:%d].\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+
+	ei_status.dmaing |= 0x01;
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+	outb_p(0, nic_base + EN0_RCNTHI);
+	outb_p(0, nic_base + EN0_RSARLO);		/* On page boundary */
+	outb_p(ring_page, nic_base + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+	if (ei_status.word16)
+		insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+	else
+		insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+
+	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.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 outb. */
+
+static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+#ifdef NE_SANITY_CHECK
+	int xfer_count = count;
+#endif
+	int nic_base = dev->base_addr;
+	char *buf = skb->data;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+	if (ei_status.dmaing)
+	{
+		printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
+			"[DMAstat:%d][irqlock:%d].\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+	ei_status.dmaing |= 0x01;
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+	outb_p(count >> 8, nic_base + EN0_RCNTHI);
+	outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
+	outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+	if (ei_status.word16)
+	{
+		insw(NE_BASE + NE_DATAPORT,buf,count>>1);
+		if (count & 0x01)
+		{
+			buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+#ifdef NE_SANITY_CHECK
+			xfer_count++;
+#endif
+		}
+	} else {
+		insb(NE_BASE + NE_DATAPORT, buf, count);
+	}
+
+#ifdef NE_SANITY_CHECK
+	/* This was for the ALPHA version only, but enough people have
+	   been encountering problems so it is still here.  If you see
+	   this message you either 1) have a slightly incompatible clone
+	   or 2) have noise/speed problems with your bus. */
+
+	if (ei_debug > 1)
+	{
+		/* DMA termination address check... */
+		int addr, tries = 20;
+		do {
+			/* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
+			   -- it's broken for Rx on some cards! */
+			int high = inb_p(nic_base + EN0_RSARHI);
+			int low = inb_p(nic_base + EN0_RSARLO);
+			addr = (high << 8) + low;
+			if (((ring_offset + xfer_count) & 0xff) == low)
+				break;
+		} while (--tries > 0);
+	 	if (tries <= 0)
+			printk(KERN_WARNING "%s: RX transfer address mismatch,"
+				"%#4.4x (expected) vs. %#4.4x (actual).\n",
+				dev->name, ring_offset + xfer_count, addr);
+	}
+#endif
+	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+}
+
+static void ne_block_output(struct net_device *dev, int count,
+		const unsigned char *buf, const int start_page)
+{
+	int nic_base = NE_BASE;
+	unsigned long dma_start;
+#ifdef NE_SANITY_CHECK
+	int retries = 0;
+#endif
+
+	/* 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))
+		count++;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+	if (ei_status.dmaing)
+	{
+		printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
+			"[DMAstat:%d][irqlock:%d]\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+	ei_status.dmaing |= 0x01;
+	/* We should already be in page 0, but to be safe... */
+	outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+#ifdef NE_SANITY_CHECK
+retry:
+#endif
+
+#ifdef NE8390_RW_BUGFIX
+	/* Handle the read-before-write bug the same way as the
+	   Crynwr packet driver -- the NatSemi method doesn't work.
+	   Actually this doesn't always work either, but if you have
+	   problems with your NEx000 this is better than nothing! */
+
+	outb_p(0x42, nic_base + EN0_RCNTLO);
+	outb_p(0x00,   nic_base + EN0_RCNTHI);
+	outb_p(0x42, nic_base + EN0_RSARLO);
+	outb_p(0x00, nic_base + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+	/* Make certain that the dummy read has occurred. */
+	udelay(6);
+#endif
+
+	outb_p(ENISR_RDC, nic_base + EN0_ISR);
+
+	/* Now the normal output. */
+	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+	outb_p(count >> 8,   nic_base + EN0_RCNTHI);
+	outb_p(0x00, nic_base + EN0_RSARLO);
+	outb_p(start_page, nic_base + EN0_RSARHI);
+
+	outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+	if (ei_status.word16) {
+		outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
+	} else {
+		outsb(NE_BASE + NE_DATAPORT, buf, count);
+	}
+
+	dma_start = jiffies;
+
+#ifdef NE_SANITY_CHECK
+	/* This was for the ALPHA version only, but enough people have
+	   been encountering problems so it is still here. */
+
+	if (ei_debug > 1)
+	{
+		/* DMA termination address check... */
+		int addr, tries = 20;
+		do {
+			int high = inb_p(nic_base + EN0_RSARHI);
+			int low = inb_p(nic_base + EN0_RSARLO);
+			addr = (high << 8) + low;
+			if ((start_page << 8) + count == addr)
+				break;
+		} while (--tries > 0);
+
+		if (tries <= 0)
+		{
+			printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
+				"%#4.4x (expected) vs. %#4.4x (actual).\n",
+				dev->name, (start_page << 8) + count, addr);
+			if (retries++ == 0)
+				goto retry;
+		}
+	}
+#endif
+
+	while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
+		if (time_after(jiffies, dma_start + 2*HZ/100)) {		/* 20ms */
+			printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
+			ne_reset_8390(dev);
+			NS8390p_init(dev, 1);
+			break;
+		}
+
+	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+}
+
+static int __init ne_drv_probe(struct platform_device *pdev)
+{
+	struct net_device *dev;
+	int err, this_dev = pdev->id;
+	struct resource *res;
+
+	dev = alloc_eip_netdev();
+	if (!dev)
+		return -ENOMEM;
+
+	/* ne.c doesn't populate resources in platform_device, but
+	 * rbtx4927_ne_init and rbtx4938_ne_init do register devices
+	 * with resources.
+	 */
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (res) {
+		dev->base_addr = res->start;
+		dev->irq = platform_get_irq(pdev, 0);
+	} else {
+		if (this_dev < 0 || this_dev >= MAX_NE_CARDS) {
+			free_netdev(dev);
+			return -EINVAL;
+		}
+		dev->base_addr = io[this_dev];
+		dev->irq = irq[this_dev];
+		dev->mem_end = bad[this_dev];
+	}
+	err = do_ne_probe(dev);
+	if (err) {
+		free_netdev(dev);
+		return err;
+	}
+	platform_set_drvdata(pdev, dev);
+
+	/* Update with any values found by probing, don't update if
+	 * resources were specified.
+	 */
+	if (!res) {
+		io[this_dev] = dev->base_addr;
+		irq[this_dev] = dev->irq;
+	}
+	return 0;
+}
+
+static int ne_drv_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+
+	if (dev) {
+		struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+		netif_device_detach(dev);
+		unregister_netdev(dev);
+		if (idev)
+			pnp_device_detach(idev);
+		/* Careful ne_drv_remove can be called twice, once from
+		 * the platform_driver.remove and again when the
+		 * platform_device is being removed.
+		 */
+		ei_status.priv = 0;
+		free_irq(dev->irq, dev);
+		release_region(dev->base_addr, NE_IO_EXTENT);
+		free_netdev(dev);
+		platform_set_drvdata(pdev, NULL);
+	}
+	return 0;
+}
+
+/* Remove unused devices or all if true. */
+static void ne_loop_rm_unreg(int all)
+{
+	int this_dev;
+	struct platform_device *pdev;
+	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+		pdev = pdev_ne[this_dev];
+		/* No network device == unused */
+		if (pdev && (!platform_get_drvdata(pdev) || all)) {
+			ne_drv_remove(pdev);
+			platform_device_unregister(pdev);
+			pdev_ne[this_dev] = NULL;
+		}
+	}
+}
+
+#ifdef CONFIG_PM
+static int ne_drv_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+
+	if (netif_running(dev)) {
+		struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+		netif_device_detach(dev);
+		if (idev)
+			pnp_stop_dev(idev);
+	}
+	return 0;
+}
+
+static int ne_drv_resume(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+
+	if (netif_running(dev)) {
+		struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+		if (idev)
+			pnp_start_dev(idev);
+		ne_reset_8390(dev);
+		NS8390p_init(dev, 1);
+		netif_device_attach(dev);
+	}
+	return 0;
+}
+#else
+#define ne_drv_suspend NULL
+#define ne_drv_resume NULL
+#endif
+
+static struct platform_driver ne_driver = {
+	.remove		= ne_drv_remove,
+	.suspend	= ne_drv_suspend,
+	.resume		= ne_drv_resume,
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static void __init ne_add_devices(void)
+{
+	int this_dev;
+	struct platform_device *pdev;
+
+	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+		if (pdev_ne[this_dev])
+			continue;
+		pdev = platform_device_register_simple(
+			DRV_NAME, this_dev, NULL, 0);
+		if (IS_ERR(pdev))
+			continue;
+		pdev_ne[this_dev] = pdev;
+	}
+}
+
+#ifdef MODULE
+int __init init_module(void)
+{
+	int retval;
+	ne_add_devices();
+	retval = platform_driver_probe(&ne_driver, ne_drv_probe);
+	if (retval) {
+		if (io[0] == 0)
+			printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\""
+				" value(s) for ISA cards.\n");
+		ne_loop_rm_unreg(1);
+		return retval;
+	}
+
+	/* Unregister unused platform_devices. */
+	ne_loop_rm_unreg(0);
+	return retval;
+}
+#else /* MODULE */
+static int __init ne_init(void)
+{
+	int retval = platform_driver_probe(&ne_driver, ne_drv_probe);
+
+	/* Unregister unused platform_devices. */
+	ne_loop_rm_unreg(0);
+	return retval;
+}
+module_init(ne_init);
+
+struct net_device * __init ne_probe(int unit)
+{
+	int this_dev;
+	struct net_device *dev;
+
+	/* Find an empty slot, that is no net_device and zero io port. */
+	this_dev = 0;
+	while ((pdev_ne[this_dev] && platform_get_drvdata(pdev_ne[this_dev])) ||
+		io[this_dev]) {
+		if (++this_dev == MAX_NE_CARDS)
+			return ERR_PTR(-ENOMEM);
+	}
+
+	/* Get irq, io from kernel command line */
+	dev = alloc_eip_netdev();
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+
+	io[this_dev] = dev->base_addr;
+	irq[this_dev] = dev->irq;
+	bad[this_dev] = dev->mem_end;
+
+	free_netdev(dev);
+
+	ne_add_devices();
+
+	/* return the first device found */
+	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+		if (pdev_ne[this_dev]) {
+			dev = platform_get_drvdata(pdev_ne[this_dev]);
+			if (dev)
+				return dev;
+		}
+	}
+
+	return ERR_PTR(-ENODEV);
+}
+#endif /* MODULE */
+
+static void __exit ne_exit(void)
+{
+	platform_driver_unregister(&ne_driver);
+	ne_loop_rm_unreg(1);
+}
+module_exit(ne_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/ne-h8300.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/ne-h8300.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/ne-h8300.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/ne-h8300.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,685 @@
+/* ne-h8300.c: A NE2000 clone on H8/300 driver for linux. */
+/*
+    original ne.c
+    Written 1992-94 by Donald Becker.
+
+    Copyright 1993 United States Government as represented by the
+    Director, National Security Agency.
+
+    This software may be used and distributed according to the terms
+    of the GNU General Public License, incorporated herein by reference.
+
+    The author may be reached as becker@scyld.com, or C/O
+    Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
+
+    H8/300 modified
+    Yoshinori Sato <ysato@users.sourceforge.jp>
+*/
+
+static const char version1[] =
+"ne-h8300.c:v1.00 2004/04/11 ysato\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/jiffies.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#define EI_SHIFT(x)	(ei_local->reg_offset[x])
+
+#include "8390.h"
+
+#define DRV_NAME "ne-h8300"
+
+/* Some defines that people can play with if so inclined. */
+
+/* Do we perform extra sanity checks on stuff ? */
+/* #define NE_SANITY_CHECK */
+
+/* Do we implement the read before write bugfix ? */
+/* #define NE_RW_BUGFIX */
+
+/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
+/* #define PACKETBUF_MEMSIZE	0x40 */
+
+/* A zero-terminated list of I/O addresses to be probed at boot. */
+
+/* ---- No user-serviceable parts below ---- */
+
+static const char version[] =
+    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include "lib8390.c"
+
+#define NE_BASE	 (dev->base_addr)
+#define NE_CMD	 	0x00
+#define NE_DATAPORT	(ei_status.word16?0x20:0x10)	/* NatSemi-defined port window offset. */
+#define NE_RESET	(ei_status.word16?0x3f:0x1f)	/* Issue a read to reset, a write to clear. */
+#define NE_IO_EXTENT	(ei_status.word16?0x40:0x20)
+
+#define NESM_START_PG	0x40	/* First page of TX buffer */
+#define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
+
+static int ne_probe1(struct net_device *dev, int ioaddr);
+
+static int ne_open(struct net_device *dev);
+static int ne_close(struct net_device *dev);
+
+static void ne_reset_8390(struct net_device *dev);
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+			  int ring_page);
+static void ne_block_input(struct net_device *dev, int count,
+			  struct sk_buff *skb, int ring_offset);
+static void ne_block_output(struct net_device *dev, const int count,
+		const unsigned char *buf, const int start_page);
+
+
+static u32 reg_offset[16];
+
+static int __init init_reg_offset(struct net_device *dev,unsigned long base_addr)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	int i;
+	unsigned char bus_width;
+
+	bus_width = *(volatile unsigned char *)ABWCR;
+	bus_width &= 1 << ((base_addr >> 21) & 7);
+
+	for (i = 0; i < ARRAY_SIZE(reg_offset); i++)
+		if (bus_width == 0)
+			reg_offset[i] = i * 2 + 1;
+		else
+			reg_offset[i] = i;
+
+	ei_local->reg_offset = reg_offset;
+	return 0;
+}
+
+static int __initdata h8300_ne_count = 0;
+#ifdef CONFIG_H8300H_H8MAX
+static unsigned long __initdata h8300_ne_base[] = { 0x800600 };
+static int h8300_ne_irq[] = {EXT_IRQ4};
+#endif
+#ifdef CONFIG_H8300H_AKI3068NET
+static unsigned long __initdata h8300_ne_base[] = { 0x200000 };
+static int h8300_ne_irq[] = {EXT_IRQ5};
+#endif
+
+static inline int init_dev(struct net_device *dev)
+{
+	if (h8300_ne_count < ARRAY_SIZE(h8300_ne_base)) {
+		dev->base_addr = h8300_ne_base[h8300_ne_count];
+		dev->irq       = h8300_ne_irq[h8300_ne_count];
+		h8300_ne_count++;
+		return 0;
+	} else
+		return -ENODEV;
+}
+
+/*  Probe for various non-shared-memory ethercards.
+
+   NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
+   buffer memory space.  NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
+   the SAPROM, while other supposed NE2000 clones must be detected by their
+   SA prefix.
+
+   Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
+   mode results in doubled values, which can be detected and compensated for.
+
+   The probe is also responsible for initializing the card and filling
+   in the 'dev' and 'ei_status' structures.
+
+   We use the minimum memory size for some ethercard product lines, iff we can't
+   distinguish models.  You can increase the packet buffer size by setting
+   PACKETBUF_MEMSIZE.  Reported Cabletron packet buffer locations are:
+	E1010   starts at 0x100 and ends at 0x2000.
+	E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
+	E2010	 starts at 0x100 and ends at 0x4000.
+	E2010-x starts at 0x100 and ends at 0xffff.  */
+
+static int __init do_ne_probe(struct net_device *dev)
+{
+	unsigned int base_addr = dev->base_addr;
+
+	/* First check any supplied i/o locations. User knows best. <cough> */
+	if (base_addr > 0x1ff)	/* Check a single specified location. */
+		return ne_probe1(dev, base_addr);
+	else if (base_addr != 0)	/* Don't probe at all. */
+		return -ENXIO;
+
+	return -ENODEV;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+	free_irq(dev->irq, dev);
+	release_region(dev->base_addr, NE_IO_EXTENT);
+}
+
+#ifndef MODULE
+struct net_device * __init ne_probe(int unit)
+{
+	struct net_device *dev = ____alloc_ei_netdev(0);
+	int err;
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	if (init_dev(dev))
+		return ERR_PTR(-ENODEV);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+
+	err = init_reg_offset(dev, dev->base_addr);
+	if (err)
+		goto out;
+
+	err = do_ne_probe(dev);
+	if (err)
+		goto out;
+	return dev;
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+#endif
+
+static const struct net_device_ops ne_netdev_ops = {
+	.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_rx_mode	= __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,
+#endif
+};
+
+static int __init ne_probe1(struct net_device *dev, int ioaddr)
+{
+	int i;
+	unsigned char SA_prom[16];
+	int wordlength = 2;
+	const char *name = NULL;
+	int start_page, stop_page;
+	int reg0, ret;
+	static unsigned version_printed;
+	struct ei_device *ei_local = netdev_priv(dev);
+	unsigned char bus_width;
+
+	if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
+		return -EBUSY;
+
+	reg0 = inb_p(ioaddr);
+	if (reg0 == 0xFF) {
+		ret = -ENODEV;
+		goto err_out;
+	}
+
+	/* Do a preliminary verification that we have a 8390. */
+	{
+		int regd;
+		outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
+		regd = inb_p(ioaddr + EI_SHIFT(0x0d));
+		outb_p(0xff, ioaddr + EI_SHIFT(0x0d));
+		outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
+		inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
+		if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
+			outb_p(reg0, ioaddr + EI_SHIFT(0));
+			outb_p(regd, ioaddr + EI_SHIFT(0x0d));	/* Restore the old values. */
+			ret = -ENODEV;
+			goto err_out;
+		}
+	}
+
+	if (ei_debug  &&  version_printed++ == 0)
+		printk(KERN_INFO "%s", version1);
+
+	printk(KERN_INFO "NE*000 ethercard probe at %08x:", ioaddr);
+
+	/* Read the 16 bytes of station address PROM.
+	   We must first initialize registers, similar to NS8390_init(eifdev, 0).
+	   We can't reliably read the SAPROM address without this.
+	   (I learned the hard way!). */
+	{
+		struct {unsigned char value, offset; } program_seq[] =
+		{
+			{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+			{0x48,	EN0_DCFG},	/* Set byte-wide (0x48) access. */
+			{0x00,	EN0_RCNTLO},	/* Clear the count regs. */
+			{0x00,	EN0_RCNTHI},
+			{0x00,	EN0_IMR},	/* Mask completion irq. */
+			{0xFF,	EN0_ISR},
+			{E8390_RXOFF, EN0_RXCR},	/* 0x20  Set to monitor */
+			{E8390_TXOFF, EN0_TXCR},	/* 0x02  and loopback mode. */
+			{32,	EN0_RCNTLO},
+			{0x00,	EN0_RCNTHI},
+			{0x00,	EN0_RSARLO},	/* DMA starting at 0x0000. */
+			{0x00,	EN0_RSARHI},
+			{E8390_RREAD+E8390_START, E8390_CMD},
+		};
+
+		for (i = 0; i < ARRAY_SIZE(program_seq); i++)
+			outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
+
+	}
+	bus_width = *(volatile unsigned char *)ABWCR;
+	bus_width &= 1 << ((ioaddr >> 21) & 7);
+	ei_status.word16 = (bus_width == 0); /* temporary setting */
+	for(i = 0; i < 16 /*sizeof(SA_prom)*/; i++) {
+		SA_prom[i] = inb_p(ioaddr + NE_DATAPORT);
+		inb_p(ioaddr + NE_DATAPORT); /* dummy read */
+	}
+
+	start_page = NESM_START_PG;
+	stop_page = NESM_STOP_PG;
+
+	if (bus_width)
+		wordlength = 1;
+	else
+		outb_p(0x49, ioaddr + EN0_DCFG);
+
+	/* Set up the rest of the parameters. */
+	name = (wordlength == 2) ? "NE2000" : "NE1000";
+
+	if (! dev->irq) {
+		printk(" failed to detect IRQ line.\n");
+		ret = -EAGAIN;
+		goto err_out;
+	}
+
+	/* Snarf the interrupt now.  There's no point in waiting since we cannot
+	   share and the board will usually be enabled. */
+	ret = request_irq(dev->irq, __ei_interrupt, 0, name, dev);
+	if (ret) {
+		printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
+		goto err_out;
+	}
+
+	dev->base_addr = ioaddr;
+
+	for(i = 0; i < ETHER_ADDR_LEN; i++)
+		dev->dev_addr[i] = SA_prom[i];
+	printk(" %pM\n", dev->dev_addr);
+
+	printk("%s: %s found at %#x, using IRQ %d.\n",
+		dev->name, name, ioaddr, dev->irq);
+
+	ei_status.name = name;
+	ei_status.tx_start_page = start_page;
+	ei_status.stop_page = stop_page;
+	ei_status.word16 = (wordlength == 2);
+
+	ei_status.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;
+#endif
+
+	ei_status.reset_8390 = &ne_reset_8390;
+	ei_status.block_input = &ne_block_input;
+	ei_status.block_output = &ne_block_output;
+	ei_status.get_8390_hdr = &ne_get_8390_hdr;
+	ei_status.priv = 0;
+
+	dev->netdev_ops = &ne_netdev_ops;
+
+	__NS8390_init(dev, 0);
+
+	ret = register_netdev(dev);
+	if (ret)
+		goto out_irq;
+	return 0;
+out_irq:
+	free_irq(dev->irq, dev);
+err_out:
+	release_region(ioaddr, NE_IO_EXTENT);
+	return ret;
+}
+
+static int ne_open(struct net_device *dev)
+{
+	__ei_open(dev);
+	return 0;
+}
+
+static int ne_close(struct net_device *dev)
+{
+	if (ei_debug > 1)
+		printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
+	__ei_close(dev);
+	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. */
+
+static void ne_reset_8390(struct net_device *dev)
+{
+	unsigned long reset_start_time = jiffies;
+	struct ei_device *ei_local = netdev_priv(dev);
+
+	if (ei_debug > 1)
+		printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
+
+	/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
+	outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+	ei_status.txing = 0;
+	ei_status.dmaing = 0;
+
+	/* This check _should_not_ be necessary, omit eventually. */
+	while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
+		if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
+			printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
+			break;
+		}
+	outb_p(ENISR_RESET, NE_BASE + EN0_ISR);	/* Ack intr. */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+
+	if (ei_status.dmaing)
+	{
+		printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
+			"[DMAstat:%d][irqlock:%d].\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+
+	ei_status.dmaing |= 0x01;
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, NE_BASE + NE_CMD);
+	outb_p(sizeof(struct e8390_pkt_hdr), NE_BASE + EN0_RCNTLO);
+	outb_p(0, NE_BASE + EN0_RCNTHI);
+	outb_p(0, NE_BASE + EN0_RSARLO);		/* On page boundary */
+	outb_p(ring_page, NE_BASE + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, NE_BASE + NE_CMD);
+
+	if (ei_status.word16) {
+		int len;
+		unsigned short *p = (unsigned short *)hdr;
+		for (len = sizeof(struct e8390_pkt_hdr)>>1; len > 0; len--)
+			*p++ = inw(NE_BASE + NE_DATAPORT);
+	} else
+		insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+
+	outb_p(ENISR_RDC, NE_BASE + EN0_ISR);	/* Ack intr. */
+	ei_status.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 outb. */
+
+static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+#ifdef NE_SANITY_CHECK
+	int xfer_count = count;
+#endif
+	char *buf = skb->data;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+	if (ei_status.dmaing)
+	{
+		printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
+			"[DMAstat:%d][irqlock:%d].\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+	ei_status.dmaing |= 0x01;
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, NE_BASE + NE_CMD);
+	outb_p(count & 0xff, NE_BASE + EN0_RCNTLO);
+	outb_p(count >> 8, NE_BASE + EN0_RCNTHI);
+	outb_p(ring_offset & 0xff, NE_BASE + EN0_RSARLO);
+	outb_p(ring_offset >> 8, NE_BASE + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, NE_BASE + NE_CMD);
+	if (ei_status.word16)
+	{
+		int len;
+		unsigned short *p = (unsigned short *)buf;
+		for (len = count>>1; len > 0; len--)
+			*p++ = inw(NE_BASE + NE_DATAPORT);
+		if (count & 0x01)
+		{
+			buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+#ifdef NE_SANITY_CHECK
+			xfer_count++;
+#endif
+		}
+	} else {
+		insb(NE_BASE + NE_DATAPORT, buf, count);
+	}
+
+#ifdef NE_SANITY_CHECK
+	/* This was for the ALPHA version only, but enough people have
+	   been encountering problems so it is still here.  If you see
+	   this message you either 1) have a slightly incompatible clone
+	   or 2) have noise/speed problems with your bus. */
+
+	if (ei_debug > 1)
+	{
+		/* DMA termination address check... */
+		int addr, tries = 20;
+		do {
+			/* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
+			   -- it's broken for Rx on some cards! */
+			int high = inb_p(NE_BASE + EN0_RSARHI);
+			int low = inb_p(NE_BASE + EN0_RSARLO);
+			addr = (high << 8) + low;
+			if (((ring_offset + xfer_count) & 0xff) == low)
+				break;
+		} while (--tries > 0);
+	 	if (tries <= 0)
+			printk(KERN_WARNING "%s: RX transfer address mismatch,"
+				"%#4.4x (expected) vs. %#4.4x (actual).\n",
+				dev->name, ring_offset + xfer_count, addr);
+	}
+#endif
+	outb_p(ENISR_RDC, NE_BASE + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+}
+
+static void ne_block_output(struct net_device *dev, int count,
+		const unsigned char *buf, const int start_page)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	unsigned long dma_start;
+#ifdef NE_SANITY_CHECK
+	int retries = 0;
+#endif
+
+	/* 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))
+		count++;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+	if (ei_status.dmaing)
+	{
+		printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
+			"[DMAstat:%d][irqlock:%d]\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+	ei_status.dmaing |= 0x01;
+	/* We should already be in page 0, but to be safe... */
+	outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, NE_BASE + NE_CMD);
+
+#ifdef NE_SANITY_CHECK
+retry:
+#endif
+
+#ifdef NE8390_RW_BUGFIX
+	/* Handle the read-before-write bug the same way as the
+	   Crynwr packet driver -- the NatSemi method doesn't work.
+	   Actually this doesn't always work either, but if you have
+	   problems with your NEx000 this is better than nothing! */
+
+	outb_p(0x42, NE_BASE + EN0_RCNTLO);
+	outb_p(0x00, NE_BASE + EN0_RCNTHI);
+	outb_p(0x42, NE_BASE + EN0_RSARLO);
+	outb_p(0x00, NE_BASE + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, NE_BASE + NE_CMD);
+	/* Make certain that the dummy read has occurred. */
+	udelay(6);
+#endif
+
+	outb_p(ENISR_RDC, NE_BASE + EN0_ISR);
+
+	/* Now the normal output. */
+	outb_p(count & 0xff, NE_BASE + EN0_RCNTLO);
+	outb_p(count >> 8,   NE_BASE + EN0_RCNTHI);
+	outb_p(0x00, NE_BASE + EN0_RSARLO);
+	outb_p(start_page, NE_BASE + EN0_RSARHI);
+
+	outb_p(E8390_RWRITE+E8390_START, NE_BASE + NE_CMD);
+	if (ei_status.word16) {
+		int len;
+		unsigned short *p = (unsigned short *)buf;
+		for (len = count>>1; len > 0; len--)
+			outw(*p++, NE_BASE + NE_DATAPORT);
+	} else {
+		outsb(NE_BASE + NE_DATAPORT, buf, count);
+	}
+
+	dma_start = jiffies;
+
+#ifdef NE_SANITY_CHECK
+	/* This was for the ALPHA version only, but enough people have
+	   been encountering problems so it is still here. */
+
+	if (ei_debug > 1)
+	{
+		/* DMA termination address check... */
+		int addr, tries = 20;
+		do {
+			int high = inb_p(NE_BASE + EN0_RSARHI);
+			int low = inb_p(NE_BASE + EN0_RSARLO);
+			addr = (high << 8) + low;
+			if ((start_page << 8) + count == addr)
+				break;
+		} while (--tries > 0);
+
+		if (tries <= 0)
+		{
+			printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
+				"%#4.4x (expected) vs. %#4.4x (actual).\n",
+				dev->name, (start_page << 8) + count, addr);
+			if (retries++ == 0)
+				goto retry;
+		}
+	}
+#endif
+
+	while ((inb_p(NE_BASE + EN0_ISR) & ENISR_RDC) == 0)
+		if (time_after(jiffies, dma_start + 2*HZ/100)) {		/* 20ms */
+			printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
+			ne_reset_8390(dev);
+			__NS8390_init(dev,1);
+			break;
+		}
+
+	outb_p(ENISR_RDC, NE_BASE + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+}
+
+
+#ifdef MODULE
+#define MAX_NE_CARDS	1	/* Max number of NE cards per module */
+static struct net_device *dev_ne[MAX_NE_CARDS];
+static int io[MAX_NE_CARDS];
+static int irq[MAX_NE_CARDS];
+static int bad[MAX_NE_CARDS];	/* 0xbad = bad sig or no reset ack */
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(bad, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s)");
+MODULE_DESCRIPTION("H8/300 NE2000 Ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* This is set up so that no ISA autoprobe takes place. We can't guarantee
+that the ne2k probe is the last 8390 based probe to take place (as it
+is at boot) and so the probe will get confused by any other 8390 cards.
+ISA device autoprobes on a running machine are not recommended anyway. */
+
+int init_module(void)
+{
+	int this_dev, found = 0;
+	int err;
+
+	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+		struct net_device *dev = ____alloc_ei_netdev(0);
+		if (!dev)
+			break;
+		if (io[this_dev]) {
+			dev->irq = irq[this_dev];
+			dev->mem_end = bad[this_dev];
+			dev->base_addr = io[this_dev];
+		} else {
+			dev->base_addr = h8300_ne_base[this_dev];
+			dev->irq = h8300_ne_irq[this_dev];
+		}
+		err = init_reg_offset(dev, dev->base_addr);
+		if (!err) {
+			if (do_ne_probe(dev) == 0) {
+				dev_ne[found++] = dev;
+				continue;
+			}
+		}
+		free_netdev(dev);
+		if (found)
+			break;
+		if (io[this_dev] != 0)
+			printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", dev->base_addr);
+		else
+			printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
+		return -ENXIO;
+	}
+	if (found)
+		return 0;
+	return -ENODEV;
+}
+
+void cleanup_module(void)
+{
+	int this_dev;
+
+	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+		struct net_device *dev = dev_ne[this_dev];
+		if (dev) {
+			unregister_netdev(dev);
+			cleanup_card(dev);
+			free_netdev(dev);
+		}
+	}
+}
+#endif /* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/pcnet_cs.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/pcnet_cs.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/pcnet_cs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/pcnet_cs.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1710 @@
+/*======================================================================
+
+    A PCMCIA ethernet driver for NS8390-based cards
+
+    This driver supports the D-Link DE-650 and Linksys EthernetCard
+    cards, the newer D-Link and Linksys combo cards, Accton EN2212
+    cards, the RPTI EP400, and the PreMax PE-200 in non-shared-memory
+    mode, and the IBM Credit Card Adapter, the NE4100, the Thomas
+    Conrad ethernet card, and the Kingston KNE-PCM/x in shared-memory
+    mode.  It will also handle the Socket EA card in either mode.
+
+    Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
+
+    pcnet_cs.c 1.153 2003/11/09 18:53:09
+
+    The network driver code is based on Donald Becker's NE2000 code:
+
+    Written 1992,1993 by Donald Becker.
+    Copyright 1993 United States Government as represented by the
+    Director, National Security Agency.  This software may be used and
+    distributed according to the terms of the GNU General Public License,
+    incorporated herein by reference.
+    Donald Becker may be reached at becker@scyld.com
+
+    Based also on Keith Moore's changes to Don Becker's code, for IBM
+    CCAE support.  Drivers merged back together, and shared-memory
+    Socket EA support added, by Ken Raeburn, September 1995.
+
+======================================================================*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/log2.h>
+#include <linux/etherdevice.h>
+#include <linux/mii.h>
+#include "8390.h"
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ciscode.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#define PCNET_CMD	0x00
+#define PCNET_DATAPORT	0x10	/* NatSemi-defined port window offset. */
+#define PCNET_RESET	0x1f	/* Issue a read to reset, a write to clear. */
+#define PCNET_MISC	0x18	/* For IBM CCAE and Socket EA cards */
+
+#define PCNET_START_PG	0x40	/* First page of TX buffer */
+#define PCNET_STOP_PG	0x80	/* Last page +1 of RX ring */
+
+/* Socket EA cards have a larger packet buffer */
+#define SOCKET_START_PG	0x01
+#define SOCKET_STOP_PG	0xff
+
+#define PCNET_RDC_TIMEOUT (2*HZ/100)	/* Max wait in jiffies for Tx RDC */
+
+static const char *if_names[] = { "auto", "10baseT", "10base2"};
+
+
+/*====================================================================*/
+
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
+MODULE_DESCRIPTION("NE2000 compatible PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");
+
+#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
+
+INT_MODULE_PARM(if_port,	1);	/* Transceiver type */
+INT_MODULE_PARM(use_big_buf,	1);	/* use 64K packet buffer? */
+INT_MODULE_PARM(mem_speed,	0);	/* shared mem speed, in ns */
+INT_MODULE_PARM(delay_output,	0);	/* pause after xmit? */
+INT_MODULE_PARM(delay_time,	4);	/* in usec */
+INT_MODULE_PARM(use_shmem,	-1);	/* use shared memory? */
+INT_MODULE_PARM(full_duplex,	0);	/* full duplex? */
+
+/* Ugh!  Let the user hardwire the hardware address for queer cards */
+static int hw_addr[6] = { 0, /* ... */ };
+module_param_array(hw_addr, int, NULL, 0);
+
+/*====================================================================*/
+
+static void mii_phy_probe(struct net_device *dev);
+static int pcnet_config(struct pcmcia_device *link);
+static void pcnet_release(struct pcmcia_device *link);
+static int pcnet_open(struct net_device *dev);
+static int pcnet_close(struct net_device *dev);
+static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
+static void ei_watchdog(u_long arg);
+static void pcnet_reset_8390(struct net_device *dev);
+static int set_config(struct net_device *dev, struct ifmap *map);
+static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
+			      int stop_pg, int cm_offset);
+static int setup_dma_config(struct pcmcia_device *link, int start_pg,
+			    int stop_pg);
+
+static void pcnet_detach(struct pcmcia_device *p_dev);
+
+/*====================================================================*/
+
+typedef struct hw_info_t {
+    u_int	offset;
+    u_char	a0, a1, a2;
+    u_int	flags;
+} hw_info_t;
+
+#define DELAY_OUTPUT	0x01
+#define HAS_MISC_REG	0x02
+#define USE_BIG_BUF	0x04
+#define HAS_IBM_MISC	0x08
+#define IS_DL10019	0x10
+#define IS_DL10022	0x20
+#define HAS_MII		0x40
+#define USE_SHMEM	0x80	/* autodetected */
+
+#define AM79C9XX_HOME_PHY	0x00006B90  /* HomePNA PHY */
+#define AM79C9XX_ETH_PHY	0x00006B70  /* 10baseT PHY */
+#define MII_PHYID_REV_MASK	0xfffffff0
+#define MII_PHYID_REG1		0x02
+#define MII_PHYID_REG2		0x03
+
+static hw_info_t hw_info[] = {
+    { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT },
+    { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 },
+    { /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 },
+    { /* ASANTE FriendlyNet */ 0x4910, 0x00, 0x00, 0x94,
+      DELAY_OUTPUT | HAS_IBM_MISC },
+    { /* Danpex EN-6200P2 */ 0x0110, 0x00, 0x40, 0xc7, 0 },
+    { /* DataTrek NetCard */ 0x0ff0, 0x00, 0x20, 0xe8, 0 },
+    { /* Dayna CommuniCard E */ 0x0110, 0x00, 0x80, 0x19, 0 },
+    { /* D-Link DE-650 */ 0x0040, 0x00, 0x80, 0xc8, 0 },
+    { /* EP-210 Ethernet */ 0x0110, 0x00, 0x40, 0x33, 0 },
+    { /* EP4000 Ethernet */ 0x01c0, 0x00, 0x00, 0xb4, 0 },
+    { /* Epson EEN10B */ 0x0ff0, 0x00, 0x00, 0x48,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* ELECOM Laneed LD-CDWA */ 0xb8, 0x08, 0x00, 0x42, 0 },
+    { /* Hypertec Ethernet */ 0x01c0, 0x00, 0x40, 0x4c, 0 },
+    { /* IBM CCAE */ 0x0ff0, 0x08, 0x00, 0x5a,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* IBM CCAE */ 0x0ff0, 0x00, 0x04, 0xac,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* IBM CCAE */ 0x0ff0, 0x00, 0x06, 0x29,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* IBM FME */ 0x0374, 0x08, 0x00, 0x5a,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* IBM FME */ 0x0374, 0x00, 0x04, 0xac,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* Kansai KLA-PCM/T */ 0x0ff0, 0x00, 0x60, 0x87,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* NSC DP83903 */ 0x0374, 0x08, 0x00, 0x17,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* NSC DP83903 */ 0x0374, 0x00, 0xc0, 0xa8,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* NSC DP83903 */ 0x0374, 0x00, 0xa0, 0xb0,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* NSC DP83903 */ 0x0198, 0x00, 0x20, 0xe0,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* I-O DATA PCLA/T */ 0x0ff0, 0x00, 0xa0, 0xb0, 0 },
+    { /* Katron PE-520 */ 0x0110, 0x00, 0x40, 0xf6, 0 },
+    { /* Kingston KNE-PCM/x */ 0x0ff0, 0x00, 0xc0, 0xf0,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* Kingston KNE-PCM/x */ 0x0ff0, 0xe2, 0x0c, 0x0f,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* Kingston KNE-PC2 */ 0x0180, 0x00, 0xc0, 0xf0, 0 },
+    { /* Maxtech PCN2000 */ 0x5000, 0x00, 0x00, 0xe8, 0 },
+    { /* NDC Instant-Link */ 0x003a, 0x00, 0x80, 0xc6, 0 },
+    { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 },
+    { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* PreMax PE-200 */ 0x07f0, 0x00, 0x20, 0xe0, 0 },
+    { /* RPTI EP400 */ 0x0110, 0x00, 0x40, 0x95, 0 },
+    { /* SCM Ethernet */ 0x0ff0, 0x00, 0x20, 0xcb, 0 },
+    { /* Socket EA */ 0x4000, 0x00, 0xc0, 0x1b,
+      DELAY_OUTPUT | HAS_MISC_REG | USE_BIG_BUF },
+    { /* Socket LP-E CF+ */ 0x01c0, 0x00, 0xc0, 0x1b, 0 },
+    { /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 },
+    { /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 },
+    { /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 },
+    { /* PCMCIA Technology OEM */ 0x01c8, 0x00, 0xa0, 0x0c, 0 }
+};
+
+#define NR_INFO		ARRAY_SIZE(hw_info)
+
+static hw_info_t default_info = { 0, 0, 0, 0, 0 };
+static hw_info_t dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII };
+static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII };
+
+typedef struct pcnet_dev_t {
+	struct pcmcia_device	*p_dev;
+    u_int		flags;
+    void		__iomem *base;
+    struct timer_list	watchdog;
+    int			stale, fast_poll;
+    u_char		phy_id;
+    u_char		eth_phy, pna_phy;
+    u_short		link_status;
+    u_long		mii_reset;
+} pcnet_dev_t;
+
+static inline pcnet_dev_t *PRIV(struct net_device *dev)
+{
+	char *p = netdev_priv(dev);
+	return (pcnet_dev_t *)(p + sizeof(struct ei_device));
+}
+
+static const struct net_device_ops pcnet_netdev_ops = {
+	.ndo_open		= pcnet_open,
+	.ndo_stop		= pcnet_close,
+	.ndo_set_config		= set_config,
+	.ndo_start_xmit 	= ei_start_xmit,
+	.ndo_get_stats		= ei_get_stats,
+	.ndo_do_ioctl 		= ei_ioctl,
+	.ndo_set_rx_mode	= ei_set_multicast_list,
+	.ndo_tx_timeout 	= ei_tx_timeout,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller 	= ei_poll,
+#endif
+};
+
+static int pcnet_probe(struct pcmcia_device *link)
+{
+    pcnet_dev_t *info;
+    struct net_device *dev;
+
+    dev_dbg(&link->dev, "pcnet_attach()\n");
+
+    /* Create new ethernet device */
+    dev = __alloc_ei_netdev(sizeof(pcnet_dev_t));
+    if (!dev) return -ENOMEM;
+    info = PRIV(dev);
+    info->p_dev = link;
+    link->priv = dev;
+
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
+    dev->netdev_ops = &pcnet_netdev_ops;
+
+    return pcnet_config(link);
+} /* pcnet_attach */
+
+static void pcnet_detach(struct pcmcia_device *link)
+{
+	struct net_device *dev = link->priv;
+
+	dev_dbg(&link->dev, "pcnet_detach\n");
+
+	unregister_netdev(dev);
+
+	pcnet_release(link);
+
+	free_netdev(dev);
+} /* pcnet_detach */
+
+/*======================================================================
+
+    This probes for a card's hardware address, for card types that
+    encode this information in their CIS.
+
+======================================================================*/
+
+static hw_info_t *get_hwinfo(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    u_char __iomem *base, *virt;
+    int i, j;
+
+    /* Allocate a small memory window */
+    link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+    link->resource[2]->start = 0; link->resource[2]->end = 0;
+    i = pcmcia_request_window(link, link->resource[2], 0);
+    if (i != 0)
+	return NULL;
+
+    virt = ioremap(link->resource[2]->start,
+	    resource_size(link->resource[2]));
+    for (i = 0; i < NR_INFO; i++) {
+	pcmcia_map_mem_page(link, link->resource[2],
+		hw_info[i].offset & ~(resource_size(link->resource[2])-1));
+	base = &virt[hw_info[i].offset & (resource_size(link->resource[2])-1)];
+	if ((readb(base+0) == hw_info[i].a0) &&
+	    (readb(base+2) == hw_info[i].a1) &&
+	    (readb(base+4) == hw_info[i].a2)) {
+		for (j = 0; j < 6; j++)
+		    dev->dev_addr[j] = readb(base + (j<<1));
+		break;
+	}
+    }
+
+    iounmap(virt);
+    j = pcmcia_release_window(link, link->resource[2]);
+    return (i < NR_INFO) ? hw_info+i : NULL;
+} /* get_hwinfo */
+
+/*======================================================================
+
+    This probes for a card's hardware address by reading the PROM.
+    It checks the address against a list of known types, then falls
+    back to a simple NE2000 clone signature check.
+
+======================================================================*/
+
+static hw_info_t *get_prom(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    unsigned int ioaddr = dev->base_addr;
+    u_char prom[32];
+    int i, j;
+
+    /* This is lifted straight from drivers/net/ne.c */
+    struct {
+	u_char value, offset;
+    } program_seq[] = {
+	{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+	{0x48,	EN0_DCFG},	/* Set byte-wide (0x48) access. */
+	{0x00,	EN0_RCNTLO},	/* Clear the count regs. */
+	{0x00,	EN0_RCNTHI},
+	{0x00,	EN0_IMR},	/* Mask completion irq. */
+	{0xFF,	EN0_ISR},
+	{E8390_RXOFF, EN0_RXCR},	/* 0x20  Set to monitor */
+	{E8390_TXOFF, EN0_TXCR},	/* 0x02  and loopback mode. */
+	{32,	EN0_RCNTLO},
+	{0x00,	EN0_RCNTHI},
+	{0x00,	EN0_RSARLO},	/* DMA starting at 0x0000. */
+	{0x00,	EN0_RSARHI},
+	{E8390_RREAD+E8390_START, E8390_CMD},
+    };
+
+    pcnet_reset_8390(dev);
+    mdelay(10);
+
+    for (i = 0; i < ARRAY_SIZE(program_seq); i++)
+	outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
+
+    for (i = 0; i < 32; i++)
+	prom[i] = inb(ioaddr + PCNET_DATAPORT);
+    for (i = 0; i < NR_INFO; i++) {
+	if ((prom[0] == hw_info[i].a0) &&
+	    (prom[2] == hw_info[i].a1) &&
+	    (prom[4] == hw_info[i].a2))
+	    break;
+    }
+    if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) {
+	for (j = 0; j < 6; j++)
+	    dev->dev_addr[j] = prom[j<<1];
+	return (i < NR_INFO) ? hw_info+i : &default_info;
+    }
+    return NULL;
+} /* get_prom */
+
+/*======================================================================
+
+    For DL10019 based cards, like the Linksys EtherFast
+
+======================================================================*/
+
+static hw_info_t *get_dl10019(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    int i;
+    u_char sum;
+
+    for (sum = 0, i = 0x14; i < 0x1c; i++)
+	sum += inb_p(dev->base_addr + i);
+    if (sum != 0xff)
+	return NULL;
+    for (i = 0; i < 6; i++)
+	dev->dev_addr[i] = inb_p(dev->base_addr + 0x14 + i);
+    i = inb(dev->base_addr + 0x1f);
+    return ((i == 0x91)||(i == 0x99)) ? &dl10022_info : &dl10019_info;
+}
+
+/*======================================================================
+
+    For Asix AX88190 based cards
+
+======================================================================*/
+
+static hw_info_t *get_ax88190(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    unsigned int ioaddr = dev->base_addr;
+    int i, j;
+
+    /* Not much of a test, but the alternatives are messy */
+    if (link->config_base != 0x03c0)
+	return NULL;
+
+    outb_p(0x01, ioaddr + EN0_DCFG);	/* Set word-wide access. */
+    outb_p(0x00, ioaddr + EN0_RSARLO);	/* DMA starting at 0x0400. */
+    outb_p(0x04, ioaddr + EN0_RSARHI);
+    outb_p(E8390_RREAD+E8390_START, ioaddr + E8390_CMD);
+
+    for (i = 0; i < 6; i += 2) {
+	j = inw(ioaddr + PCNET_DATAPORT);
+	dev->dev_addr[i] = j & 0xff;
+	dev->dev_addr[i+1] = j >> 8;
+    }
+    return NULL;
+}
+
+/*======================================================================
+
+    This should be totally unnecessary... but when we can't figure
+    out the hardware address any other way, we'll let the user hard
+    wire it when the module is initialized.
+
+======================================================================*/
+
+static hw_info_t *get_hwired(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    int i;
+
+    for (i = 0; i < 6; i++)
+	if (hw_addr[i] != 0) break;
+    if (i == 6)
+	return NULL;
+
+    for (i = 0; i < 6; i++)
+	dev->dev_addr[i] = hw_addr[i];
+
+    return &default_info;
+} /* get_hwired */
+
+static int try_io_port(struct pcmcia_device *link)
+{
+    int j, ret;
+    link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+    link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+    if (link->resource[0]->end == 32) {
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+	if (link->resource[1]->end > 0) {
+	    /* for master/slave multifunction cards */
+	    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+	}
+    } else {
+	/* This should be two 16-port windows */
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
+    }
+    if (link->resource[0]->start == 0) {
+	for (j = 0; j < 0x400; j += 0x20) {
+	    link->resource[0]->start = j ^ 0x300;
+	    link->resource[1]->start = (j ^ 0x300) + 0x10;
+	    link->io_lines = 16;
+	    ret = pcmcia_request_io(link);
+	    if (ret == 0)
+		    return ret;
+	}
+	return ret;
+    } else {
+	return pcmcia_request_io(link);
+    }
+}
+
+static int pcnet_confcheck(struct pcmcia_device *p_dev, void *priv_data)
+{
+	int *priv = priv_data;
+	int try = (*priv & 0x1);
+
+	*priv &= (p_dev->resource[2]->end >= 0x4000) ? 0x10 : ~0x10;
+
+	if (p_dev->config_index == 0)
+		return -EINVAL;
+
+	if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
+		return -EINVAL;
+
+	if (try)
+		p_dev->io_lines = 16;
+	return try_io_port(p_dev);
+}
+
+static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
+				   int *has_shmem, int try)
+{
+	struct net_device *dev = link->priv;
+	hw_info_t *local_hw_info;
+	pcnet_dev_t *info = PRIV(dev);
+	int priv = try;
+	int ret;
+
+	ret = pcmcia_loop_config(link, pcnet_confcheck, &priv);
+	if (ret) {
+		dev_warn(&link->dev, "no useable port range found\n");
+		return NULL;
+	}
+	*has_shmem = (priv & 0x10);
+
+	if (!link->irq)
+		return NULL;
+
+	if (resource_size(link->resource[1]) == 8)
+		link->config_flags |= CONF_ENABLE_SPKR;
+
+	if ((link->manf_id == MANFID_IBM) &&
+	    (link->card_id == PRODID_IBM_HOME_AND_AWAY))
+		link->config_index |= 0x10;
+
+	ret = pcmcia_enable_device(link);
+	if (ret)
+		return NULL;
+
+	dev->irq = link->irq;
+	dev->base_addr = link->resource[0]->start;
+
+	if (info->flags & HAS_MISC_REG) {
+		if ((if_port == 1) || (if_port == 2))
+			dev->if_port = if_port;
+		else
+			dev_notice(&link->dev, "invalid if_port requested\n");
+	} else
+		dev->if_port = 0;
+
+	if ((link->config_base == 0x03c0) &&
+	    (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) {
+		dev_info(&link->dev,
+			"this is an AX88190 card - use axnet_cs instead.\n");
+		return NULL;
+	}
+
+	local_hw_info = get_hwinfo(link);
+	if (!local_hw_info)
+		local_hw_info = get_prom(link);
+	if (!local_hw_info)
+		local_hw_info = get_dl10019(link);
+	if (!local_hw_info)
+		local_hw_info = get_ax88190(link);
+	if (!local_hw_info)
+		local_hw_info = get_hwired(link);
+
+	return local_hw_info;
+}
+
+static int pcnet_config(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    pcnet_dev_t *info = PRIV(dev);
+    int start_pg, stop_pg, cm_offset;
+    int has_shmem = 0;
+    hw_info_t *local_hw_info;
+
+    dev_dbg(&link->dev, "pcnet_config\n");
+
+    local_hw_info = pcnet_try_config(link, &has_shmem, 0);
+    if (!local_hw_info) {
+	    /* check whether forcing io_lines to 16 helps... */
+	    pcmcia_disable_device(link);
+	    local_hw_info = pcnet_try_config(link, &has_shmem, 1);
+	    if (local_hw_info == NULL) {
+		    dev_notice(&link->dev, "unable to read hardware net"
+			    " address for io base %#3lx\n", dev->base_addr);
+		    goto failed;
+	    }
+    }
+
+    info->flags = local_hw_info->flags;
+    /* Check for user overrides */
+    info->flags |= (delay_output) ? DELAY_OUTPUT : 0;
+    if ((link->manf_id == MANFID_SOCKET) &&
+	((link->card_id == PRODID_SOCKET_LPE) ||
+	 (link->card_id == PRODID_SOCKET_LPE_CF) ||
+	 (link->card_id == PRODID_SOCKET_EIO)))
+	info->flags &= ~USE_BIG_BUF;
+    if (!use_big_buf)
+	info->flags &= ~USE_BIG_BUF;
+
+    if (info->flags & USE_BIG_BUF) {
+	start_pg = SOCKET_START_PG;
+	stop_pg = SOCKET_STOP_PG;
+	cm_offset = 0x10000;
+    } else {
+	start_pg = PCNET_START_PG;
+	stop_pg = PCNET_STOP_PG;
+	cm_offset = 0;
+    }
+
+    /* has_shmem is ignored if use_shmem != -1 */
+    if ((use_shmem == 0) || (!has_shmem && (use_shmem == -1)) ||
+	(setup_shmem_window(link, start_pg, stop_pg, cm_offset) != 0))
+	setup_dma_config(link, start_pg, stop_pg);
+
+    ei_status.name = "NE2000";
+    ei_status.word16 = 1;
+    ei_status.reset_8390 = pcnet_reset_8390;
+
+    if (info->flags & (IS_DL10019|IS_DL10022))
+	mii_phy_probe(dev);
+
+    SET_NETDEV_DEV(dev, &link->dev);
+
+    if (register_netdev(dev) != 0) {
+	pr_notice("register_netdev() failed\n");
+	goto failed;
+    }
+
+    if (info->flags & (IS_DL10019|IS_DL10022)) {
+	u_char id = inb(dev->base_addr + 0x1a);
+	netdev_info(dev, "NE2000 (DL100%d rev %02x): ",
+	       (info->flags & IS_DL10022) ? 22 : 19, id);
+	if (info->pna_phy)
+	    pr_cont("PNA, ");
+    } else {
+	netdev_info(dev, "NE2000 Compatible: ");
+    }
+    pr_cont("io %#3lx, irq %d,", dev->base_addr, dev->irq);
+    if (info->flags & USE_SHMEM)
+	pr_cont(" mem %#5lx,", dev->mem_start);
+    if (info->flags & HAS_MISC_REG)
+	pr_cont(" %s xcvr,", if_names[dev->if_port]);
+    pr_cont(" hw_addr %pM\n", dev->dev_addr);
+    return 0;
+
+failed:
+    pcnet_release(link);
+    return -ENODEV;
+} /* pcnet_config */
+
+static void pcnet_release(struct pcmcia_device *link)
+{
+	pcnet_dev_t *info = PRIV(link->priv);
+
+	dev_dbg(&link->dev, "pcnet_release\n");
+
+	if (info->flags & USE_SHMEM)
+		iounmap(info->base);
+
+	pcmcia_disable_device(link);
+}
+
+static int pcnet_suspend(struct pcmcia_device *link)
+{
+	struct net_device *dev = link->priv;
+
+	if (link->open)
+		netif_device_detach(dev);
+
+	return 0;
+}
+
+static int pcnet_resume(struct pcmcia_device *link)
+{
+	struct net_device *dev = link->priv;
+
+	if (link->open) {
+		pcnet_reset_8390(dev);
+		NS8390_init(dev, 1);
+		netif_device_attach(dev);
+	}
+
+	return 0;
+}
+
+
+/*======================================================================
+
+    MII interface support for DL10019 and DL10022 based cards
+
+    On the DL10019, the MII IO direction bit is 0x10; on the DL10022
+    it is 0x20.  Setting both bits seems to work on both card types.
+
+======================================================================*/
+
+#define DLINK_GPIO		0x1c
+#define DLINK_DIAG		0x1d
+#define DLINK_EEPROM		0x1e
+
+#define MDIO_SHIFT_CLK		0x80
+#define MDIO_DATA_OUT		0x40
+#define MDIO_DIR_WRITE		0x30
+#define MDIO_DATA_WRITE0	(MDIO_DIR_WRITE)
+#define MDIO_DATA_WRITE1	(MDIO_DIR_WRITE | MDIO_DATA_OUT)
+#define MDIO_DATA_READ		0x10
+#define MDIO_MASK		0x0f
+
+static void mdio_sync(unsigned int addr)
+{
+    int bits, mask = inb(addr) & MDIO_MASK;
+    for (bits = 0; bits < 32; bits++) {
+	outb(mask | MDIO_DATA_WRITE1, addr);
+	outb(mask | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);
+    }
+}
+
+static int mdio_read(unsigned int addr, int phy_id, int loc)
+{
+    u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
+    int i, retval = 0, mask = inb(addr) & MDIO_MASK;
+
+    mdio_sync(addr);
+    for (i = 13; i >= 0; i--) {
+	int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+	outb(mask | dat, addr);
+	outb(mask | dat | MDIO_SHIFT_CLK, addr);
+    }
+    for (i = 19; i > 0; i--) {
+	outb(mask, addr);
+	retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0);
+	outb(mask | MDIO_SHIFT_CLK, addr);
+    }
+    return (retval>>1) & 0xffff;
+}
+
+static void mdio_write(unsigned int addr, int phy_id, int loc, int value)
+{
+    u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
+    int i, mask = inb(addr) & MDIO_MASK;
+
+    mdio_sync(addr);
+    for (i = 31; i >= 0; i--) {
+	int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+	outb(mask | dat, addr);
+	outb(mask | dat | MDIO_SHIFT_CLK, addr);
+    }
+    for (i = 1; i >= 0; i--) {
+	outb(mask, addr);
+	outb(mask | MDIO_SHIFT_CLK, addr);
+    }
+}
+
+/*======================================================================
+
+    EEPROM access routines for DL10019 and DL10022 based cards
+
+======================================================================*/
+
+#define EE_EEP		0x40
+#define EE_ASIC		0x10
+#define EE_CS		0x08
+#define EE_CK		0x04
+#define EE_DO		0x02
+#define EE_DI		0x01
+#define EE_ADOT		0x01	/* DataOut for ASIC */
+#define EE_READ_CMD	0x06
+
+#define DL19FDUPLX	0x0400	/* DL10019 Full duplex mode */
+
+static int read_eeprom(unsigned int ioaddr, int location)
+{
+    int i, retval = 0;
+    unsigned int ee_addr = ioaddr + DLINK_EEPROM;
+    int read_cmd = location | (EE_READ_CMD << 8);
+
+    outb(0, ee_addr);
+    outb(EE_EEP|EE_CS, ee_addr);
+
+    /* Shift the read command bits out. */
+    for (i = 10; i >= 0; i--) {
+	short dataval = (read_cmd & (1 << i)) ? EE_DO : 0;
+	outb_p(EE_EEP|EE_CS|dataval, ee_addr);
+	outb_p(EE_EEP|EE_CS|dataval|EE_CK, ee_addr);
+    }
+    outb(EE_EEP|EE_CS, ee_addr);
+
+    for (i = 16; i > 0; i--) {
+	outb_p(EE_EEP|EE_CS | EE_CK, ee_addr);
+	retval = (retval << 1) | ((inb(ee_addr) & EE_DI) ? 1 : 0);
+	outb_p(EE_EEP|EE_CS, ee_addr);
+    }
+
+    /* Terminate the EEPROM access. */
+    outb(0, ee_addr);
+    return retval;
+}
+
+/*
+    The internal ASIC registers can be changed by EEPROM READ access
+    with EE_ASIC bit set.
+    In ASIC mode, EE_ADOT is used to output the data to the ASIC.
+*/
+
+static void write_asic(unsigned int ioaddr, int location, short asic_data)
+{
+	int i;
+	unsigned int ee_addr = ioaddr + DLINK_EEPROM;
+	short dataval;
+	int read_cmd = location | (EE_READ_CMD << 8);
+
+	asic_data |= read_eeprom(ioaddr, location);
+
+	outb(0, ee_addr);
+	outb(EE_ASIC|EE_CS|EE_DI, ee_addr);
+
+	read_cmd = read_cmd >> 1;
+
+	/* Shift the read command bits out. */
+	for (i = 9; i >= 0; i--) {
+		dataval = (read_cmd & (1 << i)) ? EE_DO : 0;
+		outb_p(EE_ASIC|EE_CS|EE_DI|dataval, ee_addr);
+		outb_p(EE_ASIC|EE_CS|EE_DI|dataval|EE_CK, ee_addr);
+		outb_p(EE_ASIC|EE_CS|EE_DI|dataval, ee_addr);
+	}
+	// sync
+	outb(EE_ASIC|EE_CS, ee_addr);
+	outb(EE_ASIC|EE_CS|EE_CK, ee_addr);
+	outb(EE_ASIC|EE_CS, ee_addr);
+
+	for (i = 15; i >= 0; i--) {
+		dataval = (asic_data & (1 << i)) ? EE_ADOT : 0;
+		outb_p(EE_ASIC|EE_CS|dataval, ee_addr);
+		outb_p(EE_ASIC|EE_CS|dataval|EE_CK, ee_addr);
+		outb_p(EE_ASIC|EE_CS|dataval, ee_addr);
+	}
+
+	/* Terminate the ASIC access. */
+	outb(EE_ASIC|EE_DI, ee_addr);
+	outb(EE_ASIC|EE_DI| EE_CK, ee_addr);
+	outb(EE_ASIC|EE_DI, ee_addr);
+
+	outb(0, ee_addr);
+}
+
+/*====================================================================*/
+
+static void set_misc_reg(struct net_device *dev)
+{
+    unsigned int nic_base = dev->base_addr;
+    pcnet_dev_t *info = PRIV(dev);
+    u_char tmp;
+
+    if (info->flags & HAS_MISC_REG) {
+	tmp = inb_p(nic_base + PCNET_MISC) & ~3;
+	if (dev->if_port == 2)
+	    tmp |= 1;
+	if (info->flags & USE_BIG_BUF)
+	    tmp |= 2;
+	if (info->flags & HAS_IBM_MISC)
+	    tmp |= 8;
+	outb_p(tmp, nic_base + PCNET_MISC);
+    }
+    if (info->flags & IS_DL10022) {
+	if (info->flags & HAS_MII) {
+	    /* Advertise 100F, 100H, 10F, 10H */
+	    mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 4, 0x01e1);
+	    /* Restart MII autonegotiation */
+	    mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000);
+	    mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200);
+	    info->mii_reset = jiffies;
+	} else {
+	    outb(full_duplex ? 4 : 0, nic_base + DLINK_DIAG);
+	}
+    } else if (info->flags & IS_DL10019) {
+	/* Advertise 100F, 100H, 10F, 10H */
+	mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 4, 0x01e1);
+	/* Restart MII autonegotiation */
+	mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000);
+	mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200);
+    }
+}
+
+/*====================================================================*/
+
+static void mii_phy_probe(struct net_device *dev)
+{
+    pcnet_dev_t *info = PRIV(dev);
+    unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
+    int i;
+    u_int tmp, phyid;
+
+    for (i = 31; i >= 0; i--) {
+	tmp = mdio_read(mii_addr, i, 1);
+	if ((tmp == 0) || (tmp == 0xffff))
+	    continue;
+	tmp = mdio_read(mii_addr, i, MII_PHYID_REG1);
+	phyid = tmp << 16;
+	phyid |= mdio_read(mii_addr, i, MII_PHYID_REG2);
+	phyid &= MII_PHYID_REV_MASK;
+	netdev_dbg(dev, "MII at %d is 0x%08x\n", i, phyid);
+	if (phyid == AM79C9XX_HOME_PHY) {
+	    info->pna_phy = i;
+	} else if (phyid != AM79C9XX_ETH_PHY) {
+	    info->eth_phy = i;
+	}
+    }
+}
+
+static int pcnet_open(struct net_device *dev)
+{
+    int ret;
+    pcnet_dev_t *info = PRIV(dev);
+    struct pcmcia_device *link = info->p_dev;
+    unsigned int nic_base = dev->base_addr;
+
+    dev_dbg(&link->dev, "pcnet_open('%s')\n", dev->name);
+
+    if (!pcmcia_dev_present(link))
+	return -ENODEV;
+
+    set_misc_reg(dev);
+
+    outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */
+    ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev->name, dev);
+    if (ret)
+	    return ret;
+
+    link->open++;
+
+    info->phy_id = info->eth_phy;
+    info->link_status = 0x00;
+    init_timer(&info->watchdog);
+    info->watchdog.function = ei_watchdog;
+    info->watchdog.data = (u_long)dev;
+    info->watchdog.expires = jiffies + HZ;
+    add_timer(&info->watchdog);
+
+    return ei_open(dev);
+} /* pcnet_open */
+
+/*====================================================================*/
+
+static int pcnet_close(struct net_device *dev)
+{
+    pcnet_dev_t *info = PRIV(dev);
+    struct pcmcia_device *link = info->p_dev;
+
+    dev_dbg(&link->dev, "pcnet_close('%s')\n", dev->name);
+
+    ei_close(dev);
+    free_irq(dev->irq, dev);
+
+    link->open--;
+    netif_stop_queue(dev);
+    del_timer_sync(&info->watchdog);
+
+    return 0;
+} /* pcnet_close */
+
+/*======================================================================
+
+    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 pcnet_reset_8390(struct net_device *dev)
+{
+    unsigned int nic_base = dev->base_addr;
+    int i;
+
+    ei_status.txing = ei_status.dmaing = 0;
+
+    outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, nic_base + E8390_CMD);
+
+    outb(inb(nic_base + PCNET_RESET), nic_base + PCNET_RESET);
+
+    for (i = 0; i < 100; i++) {
+	if ((inb_p(nic_base+EN0_ISR) & ENISR_RESET) != 0)
+	    break;
+	udelay(100);
+    }
+    outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */
+
+    if (i == 100)
+	netdev_err(dev, "pcnet_reset_8390() did not complete.\n");
+
+    set_misc_reg(dev);
+
+} /* pcnet_reset_8390 */
+
+/*====================================================================*/
+
+static int set_config(struct net_device *dev, struct ifmap *map)
+{
+    pcnet_dev_t *info = PRIV(dev);
+    if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
+	if (!(info->flags & HAS_MISC_REG))
+	    return -EOPNOTSUPP;
+	else if ((map->port < 1) || (map->port > 2))
+	    return -EINVAL;
+	dev->if_port = map->port;
+	netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]);
+	NS8390_init(dev, 1);
+    }
+    return 0;
+}
+
+/*====================================================================*/
+
+static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
+{
+    struct net_device *dev = dev_id;
+    pcnet_dev_t *info;
+    irqreturn_t ret = ei_interrupt(irq, dev_id);
+
+    if (ret == IRQ_HANDLED) {
+	    info = PRIV(dev);
+	    info->stale = 0;
+    }
+    return ret;
+}
+
+static void ei_watchdog(u_long arg)
+{
+    struct net_device *dev = (struct net_device *)arg;
+    pcnet_dev_t *info = PRIV(dev);
+    unsigned int nic_base = dev->base_addr;
+    unsigned int mii_addr = nic_base + DLINK_GPIO;
+    u_short link;
+
+    if (!netif_device_present(dev)) goto reschedule;
+
+    /* Check for pending interrupt with expired latency timer: with
+       this, we can limp along even if the interrupt is blocked */
+    if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
+	if (!info->fast_poll)
+	    netdev_info(dev, "interrupt(s) dropped!\n");
+	ei_irq_wrapper(dev->irq, dev);
+	info->fast_poll = HZ;
+    }
+    if (info->fast_poll) {
+	info->fast_poll--;
+	info->watchdog.expires = jiffies + 1;
+	add_timer(&info->watchdog);
+	return;
+    }
+
+    if (!(info->flags & HAS_MII))
+	goto reschedule;
+
+    mdio_read(mii_addr, info->phy_id, 1);
+    link = mdio_read(mii_addr, info->phy_id, 1);
+    if (!link || (link == 0xffff)) {
+	if (info->eth_phy) {
+	    info->phy_id = info->eth_phy = 0;
+	} else {
+	    netdev_info(dev, "MII is missing!\n");
+	    info->flags &= ~HAS_MII;
+	}
+	goto reschedule;
+    }
+
+    link &= 0x0004;
+    if (link != info->link_status) {
+	u_short p = mdio_read(mii_addr, info->phy_id, 5);
+	netdev_info(dev, "%s link beat\n", link ? "found" : "lost");
+	if (link && (info->flags & IS_DL10022)) {
+	    /* Disable collision detection on full duplex links */
+	    outb((p & 0x0140) ? 4 : 0, nic_base + DLINK_DIAG);
+	} else if (link && (info->flags & IS_DL10019)) {
+	    /* Disable collision detection on full duplex links */
+	    write_asic(dev->base_addr, 4, (p & 0x140) ? DL19FDUPLX : 0);
+	}
+	if (link) {
+	    if (info->phy_id == info->eth_phy) {
+		if (p)
+		    netdev_info(dev, "autonegotiation complete: "
+			   "%sbaseT-%cD selected\n",
+			   ((p & 0x0180) ? "100" : "10"),
+			   ((p & 0x0140) ? 'F' : 'H'));
+		else
+		    netdev_info(dev, "link partner did not autonegotiate\n");
+	    }
+	    NS8390_init(dev, 1);
+	}
+	info->link_status = link;
+    }
+    if (info->pna_phy && time_after(jiffies, info->mii_reset + 6*HZ)) {
+	link = mdio_read(mii_addr, info->eth_phy, 1) & 0x0004;
+	if (((info->phy_id == info->pna_phy) && link) ||
+	    ((info->phy_id != info->pna_phy) && !link)) {
+	    /* isolate this MII and try flipping to the other one */
+	    mdio_write(mii_addr, info->phy_id, 0, 0x0400);
+	    info->phy_id ^= info->pna_phy ^ info->eth_phy;
+	    netdev_info(dev, "switched to %s transceiver\n",
+		   (info->phy_id == info->eth_phy) ? "ethernet" : "PNA");
+	    mdio_write(mii_addr, info->phy_id, 0,
+		       (info->phy_id == info->eth_phy) ? 0x1000 : 0);
+	    info->link_status = 0;
+	    info->mii_reset = jiffies;
+	}
+    }
+
+reschedule:
+    info->watchdog.expires = jiffies + HZ;
+    add_timer(&info->watchdog);
+}
+
+/*====================================================================*/
+
+
+static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+    pcnet_dev_t *info = PRIV(dev);
+    struct mii_ioctl_data *data = if_mii(rq);
+    unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
+
+    if (!(info->flags & (IS_DL10019|IS_DL10022)))
+	return -EINVAL;
+
+    switch (cmd) {
+    case SIOCGMIIPHY:
+	data->phy_id = info->phy_id;
+    case SIOCGMIIREG:		/* Read MII PHY register. */
+	data->val_out = mdio_read(mii_addr, data->phy_id, data->reg_num & 0x1f);
+	return 0;
+    case SIOCSMIIREG:		/* Write MII PHY register. */
+	mdio_write(mii_addr, data->phy_id, data->reg_num & 0x1f, data->val_in);
+	return 0;
+    }
+    return -EOPNOTSUPP;
+}
+
+/*====================================================================*/
+
+static void dma_get_8390_hdr(struct net_device *dev,
+			     struct e8390_pkt_hdr *hdr,
+			     int ring_page)
+{
+    unsigned int nic_base = dev->base_addr;
+
+    if (ei_status.dmaing) {
+	netdev_notice(dev, "DMAing conflict in dma_block_input."
+	       "[DMAstat:%1x][irqlock:%1x]\n",
+	       ei_status.dmaing, ei_status.irqlock);
+	return;
+    }
+
+    ei_status.dmaing |= 0x01;
+    outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD);
+    outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+    outb_p(0, nic_base + EN0_RCNTHI);
+    outb_p(0, nic_base + EN0_RSARLO);		/* On page boundary */
+    outb_p(ring_page, nic_base + EN0_RSARHI);
+    outb_p(E8390_RREAD+E8390_START, nic_base + PCNET_CMD);
+
+    insw(nic_base + PCNET_DATAPORT, hdr,
+	    sizeof(struct e8390_pkt_hdr)>>1);
+    /* Fix for big endian systems */
+    hdr->count = le16_to_cpu(hdr->count);
+
+    outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+    ei_status.dmaing &= ~0x01;
+}
+
+/*====================================================================*/
+
+static void dma_block_input(struct net_device *dev, int count,
+			    struct sk_buff *skb, int ring_offset)
+{
+    unsigned int nic_base = dev->base_addr;
+    int xfer_count = count;
+    char *buf = skb->data;
+
+    if ((ei_debug > 4) && (count != 4))
+	netdev_dbg(dev, "[bi=%d]\n", count+4);
+    if (ei_status.dmaing) {
+	netdev_notice(dev, "DMAing conflict in dma_block_input."
+	       "[DMAstat:%1x][irqlock:%1x]\n",
+	       ei_status.dmaing, ei_status.irqlock);
+	return;
+    }
+    ei_status.dmaing |= 0x01;
+    outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD);
+    outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+    outb_p(count >> 8, nic_base + EN0_RCNTHI);
+    outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
+    outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
+    outb_p(E8390_RREAD+E8390_START, nic_base + PCNET_CMD);
+
+    insw(nic_base + PCNET_DATAPORT,buf,count>>1);
+    if (count & 0x01)
+	buf[count-1] = inb(nic_base + PCNET_DATAPORT), xfer_count++;
+
+    /* This was for the ALPHA version only, but enough people have been
+       encountering problems that it is still here. */
+#ifdef PCMCIA_DEBUG
+    if (ei_debug > 4) {		/* DMA termination address check... */
+	int addr, tries = 20;
+	do {
+	    /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
+	       -- it's broken for Rx on some cards! */
+	    int high = inb_p(nic_base + EN0_RSARHI);
+	    int low = inb_p(nic_base + EN0_RSARLO);
+	    addr = (high << 8) + low;
+	    if (((ring_offset + xfer_count) & 0xff) == (addr & 0xff))
+		break;
+	} while (--tries > 0);
+	if (tries <= 0)
+	    netdev_notice(dev, "RX transfer address mismatch,"
+		   "%#4.4x (expected) vs. %#4.4x (actual).\n",
+		   ring_offset + xfer_count, addr);
+    }
+#endif
+    outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+    ei_status.dmaing &= ~0x01;
+} /* dma_block_input */
+
+/*====================================================================*/
+
+static void dma_block_output(struct net_device *dev, int count,
+			     const u_char *buf, const int start_page)
+{
+    unsigned int nic_base = dev->base_addr;
+    pcnet_dev_t *info = PRIV(dev);
+#ifdef PCMCIA_DEBUG
+    int retries = 0;
+#endif
+    u_long dma_start;
+
+#ifdef PCMCIA_DEBUG
+    if (ei_debug > 4)
+	netdev_dbg(dev, "[bo=%d]\n", count);
+#endif
+
+    /* 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 (count & 0x01)
+	count++;
+    if (ei_status.dmaing) {
+	netdev_notice(dev, "DMAing conflict in dma_block_output."
+	       "[DMAstat:%1x][irqlock:%1x]\n",
+	       ei_status.dmaing, ei_status.irqlock);
+	return;
+    }
+    ei_status.dmaing |= 0x01;
+    /* We should already be in page 0, but to be safe... */
+    outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base+PCNET_CMD);
+
+#ifdef PCMCIA_DEBUG
+  retry:
+#endif
+
+    outb_p(ENISR_RDC, nic_base + EN0_ISR);
+
+    /* Now the normal output. */
+    outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+    outb_p(count >> 8,   nic_base + EN0_RCNTHI);
+    outb_p(0x00, nic_base + EN0_RSARLO);
+    outb_p(start_page, nic_base + EN0_RSARHI);
+
+    outb_p(E8390_RWRITE+E8390_START, nic_base + PCNET_CMD);
+    outsw(nic_base + PCNET_DATAPORT, buf, count>>1);
+
+    dma_start = jiffies;
+
+#ifdef PCMCIA_DEBUG
+    /* This was for the ALPHA version only, but enough people have been
+       encountering problems that it is still here. */
+    if (ei_debug > 4) {	/* DMA termination address check... */
+	int addr, tries = 20;
+	do {
+	    int high = inb_p(nic_base + EN0_RSARHI);
+	    int low = inb_p(nic_base + EN0_RSARLO);
+	    addr = (high << 8) + low;
+	    if ((start_page << 8) + count == addr)
+		break;
+	} while (--tries > 0);
+	if (tries <= 0) {
+	    netdev_notice(dev, "Tx packet transfer address mismatch,"
+		   "%#4.4x (expected) vs. %#4.4x (actual).\n",
+		   (start_page << 8) + count, addr);
+	    if (retries++ == 0)
+		goto retry;
+	}
+    }
+#endif
+
+    while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
+	if (time_after(jiffies, dma_start + PCNET_RDC_TIMEOUT)) {
+	    netdev_notice(dev, "timeout waiting for Tx RDC.\n");
+	    pcnet_reset_8390(dev);
+	    NS8390_init(dev, 1);
+	    break;
+	}
+
+    outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+    if (info->flags & DELAY_OUTPUT)
+	udelay((long)delay_time);
+    ei_status.dmaing &= ~0x01;
+}
+
+/*====================================================================*/
+
+static int setup_dma_config(struct pcmcia_device *link, int start_pg,
+			    int stop_pg)
+{
+    struct net_device *dev = link->priv;
+
+    ei_status.tx_start_page = start_pg;
+    ei_status.rx_start_page = start_pg + TX_PAGES;
+    ei_status.stop_page = stop_pg;
+
+    /* set up block i/o functions */
+    ei_status.get_8390_hdr = dma_get_8390_hdr;
+    ei_status.block_input = dma_block_input;
+    ei_status.block_output = dma_block_output;
+
+    return 0;
+}
+
+/*====================================================================*/
+
+static void copyin(void *dest, void __iomem *src, int c)
+{
+    u_short *d = dest;
+    u_short __iomem *s = src;
+    int odd;
+
+    if (c <= 0)
+	return;
+    odd = (c & 1); c >>= 1;
+
+    if (c) {
+	do { *d++ = __raw_readw(s++); } while (--c);
+    }
+    /* get last byte by fetching a word and masking */
+    if (odd)
+	*((u_char *)d) = readw(s) & 0xff;
+}
+
+static void copyout(void __iomem *dest, const void *src, int c)
+{
+    u_short __iomem *d = dest;
+    const u_short *s = src;
+    int odd;
+
+    if (c <= 0)
+	return;
+    odd = (c & 1); c >>= 1;
+
+    if (c) {
+	do { __raw_writew(*s++, d++); } while (--c);
+    }
+    /* copy last byte doing a read-modify-write */
+    if (odd)
+	writew((readw(d) & 0xff00) | *(u_char *)s, d);
+}
+
+/*====================================================================*/
+
+static void shmem_get_8390_hdr(struct net_device *dev,
+			       struct e8390_pkt_hdr *hdr,
+			       int ring_page)
+{
+    void __iomem *xfer_start = ei_status.mem + (TX_PAGES<<8)
+				+ (ring_page << 8)
+				- (ei_status.rx_start_page << 8);
+
+    copyin(hdr, xfer_start, sizeof(struct e8390_pkt_hdr));
+    /* Fix for big endian systems */
+    hdr->count = le16_to_cpu(hdr->count);
+}
+
+/*====================================================================*/
+
+static void shmem_block_input(struct net_device *dev, int count,
+			      struct sk_buff *skb, int ring_offset)
+{
+    void __iomem *base = ei_status.mem;
+    unsigned long offset = (TX_PAGES<<8) + ring_offset
+				- (ei_status.rx_start_page << 8);
+    char *buf = skb->data;
+
+    if (offset + count > ei_status.priv) {
+	/* We must wrap the input move. */
+	int semi_count = ei_status.priv - offset;
+	copyin(buf, base + offset, semi_count);
+	buf += semi_count;
+	offset = TX_PAGES<<8;
+	count -= semi_count;
+    }
+    copyin(buf, base + offset, count);
+}
+
+/*====================================================================*/
+
+static void shmem_block_output(struct net_device *dev, int count,
+			       const u_char *buf, const int start_page)
+{
+    void __iomem *shmem = ei_status.mem + (start_page << 8);
+    shmem -= ei_status.tx_start_page << 8;
+    copyout(shmem, buf, count);
+}
+
+/*====================================================================*/
+
+static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
+			      int stop_pg, int cm_offset)
+{
+    struct net_device *dev = link->priv;
+    pcnet_dev_t *info = PRIV(dev);
+    int i, window_size, offset, ret;
+
+    window_size = (stop_pg - start_pg) << 8;
+    if (window_size > 32 * 1024)
+	window_size = 32 * 1024;
+
+    /* Make sure it's a power of two.  */
+    window_size = roundup_pow_of_two(window_size);
+
+    /* Allocate a memory window */
+    link->resource[3]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+    link->resource[3]->flags |= WIN_USE_WAIT;
+    link->resource[3]->start = 0; link->resource[3]->end = window_size;
+    ret = pcmcia_request_window(link, link->resource[3], mem_speed);
+    if (ret)
+	    goto failed;
+
+    offset = (start_pg << 8) + cm_offset;
+    offset -= offset % window_size;
+    ret = pcmcia_map_mem_page(link, link->resource[3], offset);
+    if (ret)
+	    goto failed;
+
+    /* Try scribbling on the buffer */
+    info->base = ioremap(link->resource[3]->start,
+			resource_size(link->resource[3]));
+    for (i = 0; i < (TX_PAGES<<8); i += 2)
+	__raw_writew((i>>1), info->base+offset+i);
+    udelay(100);
+    for (i = 0; i < (TX_PAGES<<8); i += 2)
+	if (__raw_readw(info->base+offset+i) != (i>>1)) break;
+    pcnet_reset_8390(dev);
+    if (i != (TX_PAGES<<8)) {
+	iounmap(info->base);
+	pcmcia_release_window(link, link->resource[3]);
+	info->base = NULL;
+	goto failed;
+    }
+
+    ei_status.mem = info->base + offset;
+    ei_status.priv = resource_size(link->resource[3]);
+    dev->mem_start = (u_long)ei_status.mem;
+    dev->mem_end = dev->mem_start + resource_size(link->resource[3]);
+
+    ei_status.tx_start_page = start_pg;
+    ei_status.rx_start_page = start_pg + TX_PAGES;
+    ei_status.stop_page = start_pg + (
+	    (resource_size(link->resource[3]) - offset) >> 8);
+
+    /* set up block i/o functions */
+    ei_status.get_8390_hdr = shmem_get_8390_hdr;
+    ei_status.block_input = shmem_block_input;
+    ei_status.block_output = shmem_block_output;
+
+    info->flags |= USE_SHMEM;
+    return 0;
+
+failed:
+    return 1;
+}
+
+/*====================================================================*/
+
+static const struct pcmcia_device_id pcnet_ids[] = {
+	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0057, 0x0021),
+	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0104, 0x000a),
+	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0xea15),
+	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0x3341),
+	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0xc0ab),
+	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x021b, 0x0101),
+	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x08a1, 0xc0ab),
+	PCMCIA_PFC_DEVICE_PROD_ID12(0, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4),
+	PCMCIA_PFC_DEVICE_PROD_ID12(0, "ATKK", "LM33-PCM-T", 0xba9eb7e2, 0x077c174e),
+	PCMCIA_PFC_DEVICE_PROD_ID12(0, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
+	PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
+	PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
+	PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
+	PCMCIA_PFC_DEVICE_PROD_ID12(0, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
+	PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
+	PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
+	PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card       ", 0xb569a6e5, 0x5bd4ff2c),
+	PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3),
+	PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15),
+	PCMCIA_MFC_DEVICE_PROD_ID123(0, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f),
+	PCMCIA_MFC_DEVICE_PROD_ID2(0, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
+	PCMCIA_DEVICE_MANF_CARD(0x0057, 0x1004),
+	PCMCIA_DEVICE_MANF_CARD(0x0104, 0x000d),
+	PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0075),
+	PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0145),
+	PCMCIA_DEVICE_MANF_CARD(0x0149, 0x0230),
+	PCMCIA_DEVICE_MANF_CARD(0x0149, 0x4530),
+	PCMCIA_DEVICE_MANF_CARD(0x0149, 0xc1ab),
+	PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0110),
+	PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x8041),
+	PCMCIA_DEVICE_MANF_CARD(0x0213, 0x2452),
+	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0300),
+	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0307),
+	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030a),
+	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103),
+	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121),
+	PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941),
+	PCMCIA_DEVICE_PROD_ID1234("Socket", "CF 10/100 Ethernet Card", "Revision B", "05/11/06", 0xb38bcc2e, 0x4de88352, 0xeaca6c8d, 0x7e57c22e),
+	PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b),
+	PCMCIA_DEVICE_PROD_ID123("CNet  ", "CN30BC", "ETHERNET", 0x9fe55d3d, 0x85601198, 0x3ff7175b),
+	PCMCIA_DEVICE_PROD_ID123("Digital", "Ethernet", "Adapter", 0x9999ab35, 0x00b2e941, 0x4b0d829e),
+	PCMCIA_DEVICE_PROD_ID123("Edimax Technology Inc.", "PCMCIA", "Ethernet Card", 0x738a0019, 0x281f1c5d, 0x5e9d92c0),
+	PCMCIA_DEVICE_PROD_ID123("EFA   ", "EFA207", "ETHERNET", 0x3d294be4, 0xeb9aab6c, 0x3ff7175b),
+	PCMCIA_DEVICE_PROD_ID123("I-O DATA", "PCLA", "ETHERNET", 0x1d55d7ec, 0xe4c64d34, 0x3ff7175b),
+	PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCLATE", "ETHERNET", 0x547e66dc, 0x6b260753, 0x3ff7175b),
+	PCMCIA_DEVICE_PROD_ID123("KingMax Technology Inc.", "EN10-T2", "PCMCIA Ethernet Card", 0x932b7189, 0x699e4436, 0x6f6652e0),
+	PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2216", 0x281f1c5d, 0xd4cd2f20, 0xb87add82),
+	PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2620", 0x281f1c5d, 0xd4cd2f20, 0x7d3d83a8),
+	PCMCIA_DEVICE_PROD_ID1("2412LAN", 0x67f236ab),
+	PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2212", 0xdfc6b5b2, 0xcb112a11),
+	PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2216-PCMCIA-ETHERNET", 0xdfc6b5b2, 0x5542bfff),
+	PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA100-PCM-T V2 100/10M LAN PC Card", 0xbb7fbdd7, 0xcd91cc68),
+	PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA100-PCM V2", 0x36634a66, 0xc6d05997),
+  	PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA-PCM_V2", 0xbb7fBdd7, 0x28e299f8),
+	PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA-PCM V3", 0x36634a66, 0x62241d96),
+	PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8010", 0x5070a7f9, 0x82f96e96),
+	PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8610", 0x5070a7f9, 0x86741224),
+	PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002", 0x93b15570, 0x75ec3efb),
+	PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002T", 0x93b15570, 0x461c5247),
+	PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8010", 0x93b15570, 0x82f96e96),
+	PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet", 0x578ba6e7, 0x0a9888c1),
+	PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet 10/100", 0x578ba6e7, 0x939fedbd),
+	PCMCIA_DEVICE_PROD_ID12("AROWANA", "PCMCIA Ethernet LAN Card", 0x313adbc8, 0x08d9f190),
+	PCMCIA_DEVICE_PROD_ID12("ASANTE", "FriendlyNet PC Card", 0x3a7ade0f, 0x41c64504),
+	PCMCIA_DEVICE_PROD_ID12("Billionton", "LNT-10TB", 0x552ab682, 0xeeb1ba6a),
+	PCMCIA_DEVICE_PROD_ID12("CF", "10Base-Ethernet", 0x44ebf863, 0x93ae4d79),
+	PCMCIA_DEVICE_PROD_ID12("CNet", "CN40BC Ethernet", 0xbc477dde, 0xfba775a7),
+	PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "BASEline PCMCIA 10 MBit Ethernetadapter", 0xfa2e424d, 0xe9190d8a),
+	PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "FASTline PCMCIA 10/100 Fast-Ethernet", 0xfa2e424d, 0x3953d9b9),
+	PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722),
+	PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2),
+	PCMCIA_DEVICE_PROD_ID12("corega", "Ether CF-TD", 0x0a21501a, 0x6589340a),
+	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether CF-TD LAN Card", 0x5261440f, 0x8797663b),
+	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd),
+	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d),
+	PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d),
+	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa),
+	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-TD", 0x5261440f, 0x47d5ca83),
+	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9),
+	PCMCIA_DEVICE_PROD_ID12("Corega,K.K.", "Ethernet LAN Card", 0x110d26d9, 0x9fd2f0a2),
+	PCMCIA_DEVICE_PROD_ID12("corega,K.K.", "Ethernet LAN Card", 0x9791a90e, 0x9fd2f0a2),
+	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "(CG-LAPCCTXD)", 0x5261440f, 0x73ec0d88),
+	PCMCIA_DEVICE_PROD_ID12("CouplerlessPCMCIA", "100BASE", 0xee5af0ad, 0x7c2add04),
+	PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-010", 0x77008979, 0x9d8d445d),
+	PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-110E 10/100M LAN Card", 0x77008979, 0xfd184814),
+	PCMCIA_DEVICE_PROD_ID12("DataTrek.", "NetCard ", 0x5cd66d9d, 0x84697ce0),
+	PCMCIA_DEVICE_PROD_ID12("Dayna Communications, Inc.", "CommuniCard E", 0x0c629325, 0xb4e7dbaf),
+	PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100", 0x697403d8, 0xe160b995),
+	PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100 Dongless", 0x697403d8, 0xa6d3b233),
+	PCMCIA_DEVICE_PROD_ID12("DIGITAL", "DEPCM-XX", 0x69616cb3, 0xe600e76e),
+	PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-650", 0x1a424a1c, 0xf28c8398),
+	PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660", 0x1a424a1c, 0xd9a1d05b),
+	PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660+", 0x1a424a1c, 0x50dcd0ec),
+	PCMCIA_DEVICE_PROD_ID12("D-Link", "DFE-650", 0x1a424a1c, 0x0f0073f9),
+	PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 PC Card", 0x725b842d, 0xf1efee84),
+	PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 Port Attached PC Card", 0x725b842d, 0x2db1f8e9),
+	PCMCIA_DEVICE_PROD_ID12("Dynalink", "L10BC", 0x55632fd5, 0xdc65f2b1),
+	PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10BC", 0x6a26d1cf, 0xdc65f2b1),
+	PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10C", 0x6a26d1cf, 0xc4f84efb),
+	PCMCIA_DEVICE_PROD_ID12("E-CARD", "E-CARD", 0x6701da11, 0x6701da11),
+	PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet 10BaseT card", 0x53c864c6, 0xedd059f6),
+	PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet Combo card", 0x53c864c6, 0x929c486c),
+	PCMCIA_DEVICE_PROD_ID12("Ethernet", "Adapter", 0x00b2e941, 0x4b0d829e),
+	PCMCIA_DEVICE_PROD_ID12("Ethernet Adapter", "E2000 PCMCIA Ethernet", 0x96767301, 0x71fbbc61),
+	PCMCIA_DEVICE_PROD_ID12("Ethernet PCMCIA adapter", "EP-210", 0x8dd86181, 0xf2b52517),
+	PCMCIA_DEVICE_PROD_ID12("Fast Ethernet", "Adapter", 0xb4be14e3, 0x4b0d829e),
+	PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2000", 0x2a151fac, 0xf00555cb),
+	PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2220", 0x2a151fac, 0xc1b7e327),
+	PCMCIA_DEVICE_PROD_ID12("GVC", "NIC-2000p", 0x76e171bd, 0x6eb1c947),
+	PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "Ethernet", 0xe3736c88, 0x00b2e941),
+	PCMCIA_DEVICE_PROD_ID12("IC-CARD", "IC-CARD", 0x60cb09a6, 0x60cb09a6),
+	PCMCIA_DEVICE_PROD_ID12("IC-CARD+", "IC-CARD+", 0x93693494, 0x93693494),
+	PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCETTX", 0x547e66dc, 0x6fc5459b),
+	PCMCIA_DEVICE_PROD_ID12("iPort", "10/100 Ethernet Card", 0x56c538d2, 0x11b0ffc0),
+	PCMCIA_DEVICE_PROD_ID12("KANSAI ELECTRIC CO.,LTD", "KLA-PCM/T", 0xb18dc3b4, 0xcc51a956),
+	PCMCIA_DEVICE_PROD_ID12("KENTRONICS", "KEP-230", 0xaf8144c9, 0x868f6616),
+	PCMCIA_DEVICE_PROD_ID12("KCI", "PE520 PCMCIA Ethernet Adapter", 0xa89b87d3, 0x1eb88e64),
+	PCMCIA_DEVICE_PROD_ID12("KINGMAX", "EN10T2T", 0x7bcb459a, 0xa5c81fa5),
+	PCMCIA_DEVICE_PROD_ID12("Kingston", "KNE-PC2", 0x1128e633, 0xce2a89b3),
+	PCMCIA_DEVICE_PROD_ID12("Kingston Technology Corp.", "EtheRx PC Card Ethernet Adapter", 0x313c7be3, 0x0afb54a2),
+	PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-10/100CD", 0x1b7827b2, 0xcda71d1c),
+	PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDF", 0x1b7827b2, 0xfec71e40),
+	PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDL/T", 0x1b7827b2, 0x79fba4f7),
+	PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDS", 0x1b7827b2, 0x931afaab),
+	PCMCIA_DEVICE_PROD_ID12("LEMEL", "LM-N89TX PRO", 0xbbefb52f, 0xd2897a97),
+	PCMCIA_DEVICE_PROD_ID12("Linksys", "Combo PCMCIA EthernetCard (EC2T)", 0x0733cc81, 0x32ee8c78),
+	PCMCIA_DEVICE_PROD_ID12("LINKSYS", "E-CARD", 0xf7cb0b07, 0x6701da11),
+	PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 Integrated PC Card (PCM100)", 0x0733cc81, 0x453c3f9d),
+	PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100)", 0x0733cc81, 0x66c5a389),
+	PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V2)", 0x0733cc81, 0x3a3b28e9),
+	PCMCIA_DEVICE_PROD_ID12("Linksys", "HomeLink Phoneline + 10/100 Network PC Card (PCM100H1)", 0x733cc81, 0x7a3e5c3a),
+	PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TX", 0x88fcdeda, 0x6d772737),
+	PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TE", 0x88fcdeda, 0x0e714bee),
+	PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN20T", 0x88fcdeda, 0x81090922),
+	PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN10TE", 0x88fcdeda, 0xc1e2521c),
+	PCMCIA_DEVICE_PROD_ID12("LONGSHINE", "PCMCIA Ethernet Card", 0xf866b0b0, 0x6f6652e0),
+	PCMCIA_DEVICE_PROD_ID12("MACNICA", "ME1-JEIDA", 0x20841b68, 0xaf8a3578),
+	PCMCIA_DEVICE_PROD_ID12("Macsense", "MPC-10", 0xd830297f, 0xd265c307),
+	PCMCIA_DEVICE_PROD_ID12("Matsushita Electric Industrial Co.,LTD.", "CF-VEL211", 0x44445376, 0x8ded41d4),
+	PCMCIA_DEVICE_PROD_ID12("MAXTECH", "PCN2000", 0x78d64bc0, 0xca0ca4b8),
+	PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-T", 0x481e0094, 0xa2eb0cf3),
+	PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-TX", 0x481e0094, 0x41a6916c),
+	PCMCIA_DEVICE_PROD_ID12("Microcom C.E.", "Travel Card LAN 10/100", 0x4b91cec7, 0xe70220d6),
+	PCMCIA_DEVICE_PROD_ID12("Microdyne", "NE4200", 0x2e6da59b, 0x0478e472),
+	PCMCIA_DEVICE_PROD_ID12("MIDORI ELEC.", "LT-PCMT", 0x648d55c1, 0xbde526c7),
+	PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover 4100", 0x36e1191f, 0x60c229b9),
+	PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover NE4100", 0x36e1191f, 0xa6617ec8),
+	PCMCIA_DEVICE_PROD_ID12("NEC", "PC-9801N-J12", 0x18df0ba0, 0xbc912d76),
+	PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA410TX", 0x9aa79dc3, 0x60e5bc0e),
+	PCMCIA_DEVICE_PROD_ID12("Network Everywhere", "Fast Ethernet 10/100 PC Card", 0x820a67b6, 0x31ed1a5f),
+	PCMCIA_DEVICE_PROD_ID12("NextCom K.K.", "Next Hawk", 0xaedaec74, 0xad050ef1),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100Mbps Ethernet Card", 0x281f1c5d, 0x6e41773b),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet", 0x281f1c5d, 0x00b2e941),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET", 0x281f1c5d, 0x3ff7175b),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet 10BaseT Card", 0x281f1c5d, 0x4de2f6c8),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Card", 0x281f1c5d, 0x5e9d92c0),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Combo card", 0x281f1c5d, 0x929c486c),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET V1.0", 0x281f1c5d, 0x4d8817c8),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEthernet", 0x281f1c5d, 0xfe871eeb),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast-Ethernet", 0x281f1c5d, 0x45f1f3b4),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FAST ETHERNET CARD", 0x281f1c5d, 0xec5dbca7),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA LAN", "Ethernet", 0x7500e246, 0x00b2e941),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "LNT-10TN", 0x281f1c5d, 0xe707f641),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "UE2212", 0x281f1c5d, 0xbf17199b),
+	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "    Ethernet NE2000 Compatible", 0x281f1c5d, 0x42d5d7e1),
+	PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10baseT 3.3V", 0xebf91155, 0x30074c80),
+	PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50),
+	PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110),
+	PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941),
+	PCMCIA_DEVICE_PROD_ID12("RIOS Systems Co.", "PC CARD3 ETHERNET", 0x7dd33481, 0x10b41826),
+	PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df),
+	PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0),
+	PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd),
+	PCMCIA_DEVICE_PROD_ID12("RPTI LTD.", "EP400", 0xc53ac515, 0x81e39388),
+	PCMCIA_DEVICE_PROD_ID12("SCM", "Ethernet Combo card", 0xbdc3b102, 0x929c486c),
+	PCMCIA_DEVICE_PROD_ID12("Seiko Epson Corp.", "Ethernet", 0x09928730, 0x00b2e941),
+	PCMCIA_DEVICE_PROD_ID12("SMC", "EZCard-10-PCMCIA", 0xc4f8b18b, 0xfb21d265),
+	PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision D", 0xc70a4760, 0x2ade483e),
+	PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision E", 0xc70a4760, 0x5dd978a8),
+	PCMCIA_DEVICE_PROD_ID12("TDK", "LAK-CD031 for PCMCIA", 0x1eae9475, 0x0ed386fa),
+	PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE450T", 0x466b05f0, 0x8b74bc4f),
+	PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE550T", 0x466b05f0, 0x33c8db2a),
+	PCMCIA_DEVICE_PROD_ID13("Hypertec",  "EP401", 0x8787bec7, 0xf6e4a31e),
+	PCMCIA_DEVICE_PROD_ID13("KingMax Technology Inc.", "Ethernet Card", 0x932b7189, 0x5e9d92c0),
+	PCMCIA_DEVICE_PROD_ID13("LONGSHINE", "EP401", 0xf866b0b0, 0xf6e4a31e),
+	PCMCIA_DEVICE_PROD_ID13("Xircom", "CFE-10", 0x2e3ee845, 0x22a49f89),
+	PCMCIA_DEVICE_PROD_ID1("CyQ've 10 Base-T LAN CARD", 0x94faf360),
+	PCMCIA_DEVICE_PROD_ID1("EP-210 PCMCIA LAN CARD.", 0x8850b4de),
+	PCMCIA_DEVICE_PROD_ID1("ETHER-C16", 0x06a8514f),
+	PCMCIA_DEVICE_PROD_ID1("NE2000 Compatible", 0x75b8ad5a),
+	PCMCIA_DEVICE_PROD_ID2("EN-6200P2", 0xa996d078),
+	/* too generic! */
+	/* PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100 Ethernet Card", 0x281f1c5d, 0x11b0ffc0), */
+	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"),
+	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"),
+	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
+	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
+	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
+	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
+	PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
+	PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
+	PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"),
+	PCMCIA_DEVICE_CIS_PROD_ID12("Allied Telesis,K.K", "Ethernet LAN Card", 0x2ad62f3c, 0x9fd2f0a2, "cis/LA-PCM.cis"),
+	PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "cis/PE520.cis"),
+	PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "cis/NE2K.cis"),
+	PCMCIA_DEVICE_CIS_PROD_ID12("PMX   ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "cis/PE-200.cis"),
+	PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "cis/tamarack.cis"),
+	PCMCIA_DEVICE_PROD_ID12("Ethernet", "CF Size PC Card", 0x00b2e941, 0x43ac239b),
+	PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0",
+		0xb4be14e3, 0x43ac239b, 0x0877b627),
+	PCMCIA_DEVICE_NULL
+};
+MODULE_DEVICE_TABLE(pcmcia, pcnet_ids);
+MODULE_FIRMWARE("cis/PCMLM28.cis");
+MODULE_FIRMWARE("cis/DP83903.cis");
+MODULE_FIRMWARE("cis/LA-PCM.cis");
+MODULE_FIRMWARE("cis/PE520.cis");
+MODULE_FIRMWARE("cis/NE2K.cis");
+MODULE_FIRMWARE("cis/PE-200.cis");
+MODULE_FIRMWARE("cis/tamarack.cis");
+
+static struct pcmcia_driver pcnet_driver = {
+	.name		= "pcnet_cs",
+	.probe		= pcnet_probe,
+	.remove		= pcnet_detach,
+	.owner		= THIS_MODULE,
+	.id_table	= pcnet_ids,
+	.suspend	= pcnet_suspend,
+	.resume		= pcnet_resume,
+};
+
+static int __init init_pcnet_cs(void)
+{
+    return pcmcia_register_driver(&pcnet_driver);
+}
+
+static void __exit exit_pcnet_cs(void)
+{
+    pcmcia_unregister_driver(&pcnet_driver);
+}
+
+module_init(init_pcnet_cs);
+module_exit(exit_pcnet_cs);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/smc-mca.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/smc-mca.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/smc-mca.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/smc-mca.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,576 @@
+/* smc-mca.c: A SMC Ultra ethernet driver for linux. */
+/*
+    Most of this driver, except for ultramca_probe is nearly
+    verbatim from smc-ultra.c by Donald Becker. The rest is
+    written and copyright 1996 by David Weis, weisd3458@uni.edu
+
+    This is a driver for the SMC Ultra and SMC EtherEZ ethercards.
+
+    This driver uses the cards in the 8390-compatible, shared memory mode.
+    Most of the run-time complexity is handled by the generic code in
+    8390.c.
+
+    This driver enables the shared memory only when doing the actual data
+    transfers to avoid a bug in early version of the card that corrupted
+    data transferred by a AHA1542.
+
+    This driver does not support the programmed-I/O data transfer mode of
+    the EtherEZ.  That support (if available) is smc-ez.c.  Nor does it
+    use the non-8390-compatible "Altego" mode. (No support currently planned.)
+
+    Changelog:
+
+    Paul Gortmaker	 : multiple card support for module users.
+    David Weis		 : Micro Channel-ized it.
+    Tom Sightler	 : Added support for IBM PS/2 Ethernet Adapter/A
+    Christopher Turcksin : Changed MCA-probe so that multiple adapters are
+			   found correctly (Jul 16, 1997)
+    Chris Beauregard	 : Tried to merge the two changes above (Dec 15, 1997)
+    Tom Sightler	 : Fixed minor detection bug caused by above merge
+    Tom Sightler	 : Added support for three more Western Digital
+			   MCA-adapters
+    Tom Sightler	 : Added support for 2.2.x mca_find_unused_adapter
+    Hartmut Schmidt	 : - Modified parameter detection to handle each
+			     card differently depending on a switch-list
+			   - 'card_ver' removed from the adapter list
+			   - Some minor bug fixes
+*/
+
+#include <linux/mca.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "8390.h"
+
+#define DRV_NAME "smc-mca"
+
+static int ultramca_open(struct net_device *dev);
+static void ultramca_reset_8390(struct net_device *dev);
+static void ultramca_get_8390_hdr(struct net_device *dev,
+                                  struct e8390_pkt_hdr *hdr,
+                                  int ring_page);
+static void ultramca_block_input(struct net_device *dev, int count,
+                                 struct sk_buff *skb,
+                                 int ring_offset);
+static void ultramca_block_output(struct net_device *dev, int count,
+                                  const unsigned char *buf,
+                                  const int start_page);
+static int ultramca_close_card(struct net_device *dev);
+
+#define START_PG        0x00    /* First page of TX buffer */
+
+#define ULTRA_CMDREG 0      /* Offset to ASIC command register. */
+#define ULTRA_RESET  0x80   /* Board reset, in ULTRA_CMDREG. */
+#define ULTRA_MEMENB 0x40   /* Enable the shared memory. */
+#define ULTRA_NIC_OFFSET 16 /* NIC register offset from the base_addr. */
+#define ULTRA_IO_EXTENT 32
+#define EN0_ERWCNT      0x08  /* Early receive warning count. */
+
+#define _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A            0
+#define _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A            1
+#define _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A              2
+#define _6fc1_WD_Starcard_PLUS_A_WD8003ST_A                            3
+#define _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A                        4
+#define _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A        5
+#define _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A        6
+#define _efe5_IBM_PS2_Adapter_A_for_Ethernet                           7
+
+struct smc_mca_adapters_t {
+	unsigned int id;
+	char *name;
+};
+
+#define MAX_ULTRAMCA_CARDS 4	/* Max number of Ultra cards per module */
+
+static int ultra_io[MAX_ULTRAMCA_CARDS];
+static int ultra_irq[MAX_ULTRAMCA_CARDS];
+MODULE_LICENSE("GPL");
+
+module_param_array(ultra_io, int, NULL, 0);
+module_param_array(ultra_irq, int, NULL, 0);
+MODULE_PARM_DESC(ultra_io, "SMC Ultra/EtherEZ MCA I/O base address(es)");
+MODULE_PARM_DESC(ultra_irq, "SMC Ultra/EtherEZ MCA IRQ number(s)");
+
+static const struct {
+  unsigned int base_addr;
+} addr_table[] = {
+    { 0x0800 },
+    { 0x1800 },
+    { 0x2800 },
+    { 0x3800 },
+    { 0x4800 },
+    { 0x5800 },
+    { 0x6800 },
+    { 0x7800 },
+    { 0x8800 },
+    { 0x9800 },
+    { 0xa800 },
+    { 0xb800 },
+    { 0xc800 },
+    { 0xd800 },
+    { 0xe800 },
+    { 0xf800 }
+};
+
+#define MEM_MASK 64
+
+static const struct {
+  unsigned char mem_index;
+  unsigned long mem_start;
+  unsigned char num_pages;
+} mem_table[] = {
+    { 16, 0x0c0000, 40 },
+    { 18, 0x0c4000, 40 },
+    { 20, 0x0c8000, 40 },
+    { 22, 0x0cc000, 40 },
+    { 24, 0x0d0000, 40 },
+    { 26, 0x0d4000, 40 },
+    { 28, 0x0d8000, 40 },
+    { 30, 0x0dc000, 40 },
+    {144, 0xfc0000, 40 },
+    {148, 0xfc8000, 40 },
+    {154, 0xfd0000, 40 },
+    {156, 0xfd8000, 40 },
+    {  0, 0x0c0000, 20 },
+    {  1, 0x0c2000, 20 },
+    {  2, 0x0c4000, 20 },
+    {  3, 0x0c6000, 20 }
+};
+
+#define IRQ_MASK 243
+static const struct {
+   unsigned char new_irq;
+   unsigned char old_irq;
+} irq_table[] = {
+   {  3,  3 },
+   {  4,  4 },
+   { 10, 10 },
+   { 14, 15 }
+};
+
+static short smc_mca_adapter_ids[] __initdata = {
+	0x61c8,
+	0x61c9,
+	0x6fc0,
+	0x6fc1,
+	0x6fc2,
+	0xefd4,
+	0xefd5,
+	0xefe5,
+	0x0000
+};
+
+static char *smc_mca_adapter_names[] __initdata = {
+	"SMC Ethercard PLUS Elite/A BNC/AUI (WD8013EP/A)",
+	"SMC Ethercard PLUS Elite/A UTP/AUI (WD8013WP/A)",
+	"WD Ethercard PLUS/A (WD8003E/A or WD8003ET/A)",
+	"WD Starcard PLUS/A (WD8003ST/A)",
+	"WD Ethercard PLUS 10T/A (WD8003W/A)",
+	"IBM PS/2 Adapter/A for Ethernet UTP/AUI (WD8013WP/A)",
+	"IBM PS/2 Adapter/A for Ethernet BNC/AUI (WD8013EP/A)",
+	"IBM PS/2 Adapter/A for Ethernet",
+	NULL
+};
+
+static int ultra_found = 0;
+
+
+static const struct net_device_ops ultramca_netdev_ops = {
+	.ndo_open		= ultramca_open,
+	.ndo_stop		= ultramca_close_card,
+
+	.ndo_start_xmit		= ei_start_xmit,
+	.ndo_tx_timeout		= ei_tx_timeout,
+	.ndo_get_stats		= ei_get_stats,
+	.ndo_set_rx_mode	= 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,
+#endif
+};
+
+static int __init ultramca_probe(struct device *gen_dev)
+{
+	unsigned short ioaddr;
+	struct net_device *dev;
+	unsigned char reg4, num_pages;
+	struct mca_device *mca_dev = to_mca_device(gen_dev);
+	char slot = mca_dev->slot;
+	unsigned char pos2 = 0xff, pos3 = 0xff, pos4 = 0xff, pos5 = 0xff;
+	int i, rc;
+	int adapter = mca_dev->index;
+	int tbase = 0;
+	int tirq = 0;
+	int base_addr = ultra_io[ultra_found];
+	int irq = ultra_irq[ultra_found];
+
+	if (base_addr || irq) {
+		printk(KERN_INFO "Probing for SMC MCA adapter");
+		if (base_addr) {
+			printk(KERN_INFO " at I/O address 0x%04x%c",
+			       base_addr, irq ? ' ' : '\n');
+		}
+		if (irq) {
+			printk(KERN_INFO "using irq %d\n", irq);
+		}
+	}
+
+	tirq = 0;
+	tbase = 0;
+
+	/* If we're trying to match a specificied irq or io address,
+	 * we'll reject the adapter found unless it's the one we're
+	 * looking for */
+
+	pos2 = mca_device_read_stored_pos(mca_dev, 2); /* io_addr */
+	pos3 = mca_device_read_stored_pos(mca_dev, 3); /* shared mem */
+	pos4 = mca_device_read_stored_pos(mca_dev, 4); /* ROM bios addr range */
+	pos5 = mca_device_read_stored_pos(mca_dev, 5); /* irq, media and RIPL */
+
+	/* Test the following conditions:
+	 * - If an irq parameter is supplied, compare it
+	 *   with the irq of the adapter we found
+	 * - If a base_addr paramater is given, compare it
+	 *   with the base_addr of the adapter we found
+	 * - Check that the irq and the base_addr of the
+	 *   adapter we found is not already in use by
+	 *   this driver
+	 */
+
+	switch (mca_dev->index) {
+	case _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A:
+	case _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A:
+	case _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A:
+	case _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A:
+		{
+			tbase = addr_table[(pos2 & 0xf0) >> 4].base_addr;
+			tirq  = irq_table[(pos5 & 0xc) >> 2].new_irq;
+			break;
+		}
+	case _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A:
+	case _6fc1_WD_Starcard_PLUS_A_WD8003ST_A:
+	case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A:
+	case _efe5_IBM_PS2_Adapter_A_for_Ethernet:
+		{
+			tbase = ((pos2 & 0x0fe) * 0x10);
+			tirq  = irq_table[(pos5 & 3)].old_irq;
+			break;
+		}
+	}
+
+	if(!tirq || !tbase ||
+	   (irq && irq != tirq) ||
+	   (base_addr && tbase != base_addr))
+		/* FIXME: we're trying to force the ordering of the
+		 * devices here, there should be a way of getting this
+		 * to happen */
+		return -ENXIO;
+
+        /* Adapter found. */
+	dev  = alloc_ei_netdev();
+	if(!dev)
+		return -ENODEV;
+
+	SET_NETDEV_DEV(dev, gen_dev);
+	mca_device_set_name(mca_dev, smc_mca_adapter_names[adapter]);
+	mca_device_set_claim(mca_dev, 1);
+
+	printk(KERN_INFO "smc_mca: %s found in slot %d\n",
+		       smc_mca_adapter_names[adapter], slot + 1);
+
+	ultra_found++;
+
+	dev->base_addr = ioaddr = mca_device_transform_ioport(mca_dev, tbase);
+	dev->irq       = mca_device_transform_irq(mca_dev, tirq);
+	dev->mem_start = 0;
+	num_pages      = 40;
+
+	switch (adapter) {	/* card-# in const array above [hs] */
+		case _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A:
+		case _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A:
+		{
+			for (i = 0; i < 16; i++) { /* taking 16 counts
+						    * up to 15 [hs] */
+				if (mem_table[i].mem_index == (pos3 & ~MEM_MASK)) {
+					dev->mem_start = (unsigned long)
+					  mca_device_transform_memory(mca_dev, (void *)mem_table[i].mem_start);
+					num_pages = mem_table[i].num_pages;
+				}
+			}
+			break;
+		}
+		case _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A:
+		case _6fc1_WD_Starcard_PLUS_A_WD8003ST_A:
+		case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A:
+		case _efe5_IBM_PS2_Adapter_A_for_Ethernet:
+		{
+			dev->mem_start = (unsigned long)
+			  mca_device_transform_memory(mca_dev, (void *)((pos3 & 0xfc) * 0x1000));
+			num_pages = 0x40;
+			break;
+		}
+		case _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A:
+		case _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A:
+		{
+			/* courtesy of gamera@quartz.ocn.ne.jp, pos3 indicates
+			 * the index of the 0x2000 step.
+			 * beware different number of pages [hs]
+			 */
+			dev->mem_start = (unsigned long)
+			  mca_device_transform_memory(mca_dev, (void *)(0xc0000 + (0x2000 * (pos3 & 0xf))));
+			num_pages = 0x20 + (2 * (pos3 & 0x10));
+			break;
+		}
+	}
+
+	/* sanity check, shouldn't happen */
+	if (dev->mem_start == 0) {
+		rc = -ENODEV;
+		goto err_unclaim;
+	}
+
+	if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME)) {
+		rc = -ENODEV;
+		goto err_unclaim;
+	}
+
+	reg4 = inb(ioaddr + 4) & 0x7f;
+	outb(reg4, ioaddr + 4);
+
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = inb(ioaddr + 8 + i);
+
+	printk(KERN_INFO "smc_mca[%d]: Parameters: %#3x, %pM",
+	       slot + 1, ioaddr, dev->dev_addr);
+
+	/* Switch from the station address to the alternate register set
+	 * and read the useful registers there.
+	 */
+
+	outb(0x80 | reg4, ioaddr + 4);
+
+	/* Enable FINE16 mode to avoid BIOS ROM width mismatches @ reboot.
+	 */
+
+	outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
+
+	/* Switch back to the station address register set so that
+	 * the MS-DOS driver can find the card after a warm boot.
+	 */
+
+	outb(reg4, ioaddr + 4);
+
+	dev_set_drvdata(gen_dev, dev);
+
+	/* The 8390 isn't at the base address, so fake the offset
+	 */
+
+	dev->base_addr = ioaddr + ULTRA_NIC_OFFSET;
+
+	ei_status.name = "SMC Ultra MCA";
+	ei_status.word16 = 1;
+	ei_status.tx_start_page = START_PG;
+	ei_status.rx_start_page = START_PG + TX_PAGES;
+	ei_status.stop_page = num_pages;
+
+	ei_status.mem = ioremap(dev->mem_start, (ei_status.stop_page - START_PG) * 256);
+	if (!ei_status.mem) {
+		rc = -ENOMEM;
+		goto err_release_region;
+	}
+
+	dev->mem_end = dev->mem_start + (ei_status.stop_page - START_PG) * 256;
+
+	printk(", IRQ %d memory %#lx-%#lx.\n",
+	dev->irq, dev->mem_start, dev->mem_end - 1);
+
+	ei_status.reset_8390 = &ultramca_reset_8390;
+	ei_status.block_input = &ultramca_block_input;
+	ei_status.block_output = &ultramca_block_output;
+	ei_status.get_8390_hdr = &ultramca_get_8390_hdr;
+
+	ei_status.priv = slot;
+
+	dev->netdev_ops = &ultramca_netdev_ops;
+
+	NS8390_init(dev, 0);
+
+	rc = register_netdev(dev);
+	if (rc)
+		goto err_unmap;
+
+	return 0;
+
+err_unmap:
+	iounmap(ei_status.mem);
+err_release_region:
+	release_region(ioaddr, ULTRA_IO_EXTENT);
+err_unclaim:
+	mca_device_set_claim(mca_dev, 0);
+	free_netdev(dev);
+	return rc;
+}
+
+static int ultramca_open(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+	int retval;
+
+	if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev)))
+		return retval;
+
+	outb(ULTRA_MEMENB, ioaddr); /* Enable memory */
+	outb(0x80, ioaddr + 5);     /* ??? */
+	outb(0x01, ioaddr + 6);     /* Enable interrupts and memory. */
+	outb(0x04, ioaddr + 5);     /* ??? */
+
+	/* Set the early receive warning level in window 0 high enough not
+	 * to receive ERW interrupts.
+	 */
+
+	/* outb_p(E8390_NODMA + E8390_PAGE0, dev->base_addr);
+	 * outb(0xff, dev->base_addr + EN0_ERWCNT);
+	 */
+
+	ei_open(dev);
+	return 0;
+}
+
+static void ultramca_reset_8390(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+
+	outb(ULTRA_RESET, ioaddr);
+	if (ei_debug > 1)
+		printk("resetting Ultra, t=%ld...", jiffies);
+	ei_status.txing = 0;
+
+	outb(0x80, ioaddr + 5);     /* ??? */
+	outb(0x01, ioaddr + 6);     /* Enable interrupts and memory. */
+
+	if (ei_debug > 1)
+		printk("reset done\n");
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+ * we don't need to be concerned with ring wrap as the header will be at
+ * the start of a page, so we optimize accordingly.
+ */
+
+static void ultramca_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	void __iomem *hdr_start = ei_status.mem + ((ring_page - START_PG) << 8);
+
+#ifdef notdef
+	/* Officially this is what we are doing, but the readl() is faster */
+	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+#else
+	((unsigned int*)hdr)[0] = readl(hdr_start);
+#endif
+}
+
+/* Block input and output are easy on shared memory ethercards, the only
+ * complication is when the ring buffer wraps.
+ */
+
+static void ultramca_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+	void __iomem *xfer_start = ei_status.mem + ring_offset - START_PG * 256;
+
+	if (ring_offset + count > ei_status.stop_page * 256) {
+		/* We must wrap the input move. */
+		int semi_count = ei_status.stop_page * 256 - ring_offset;
+		memcpy_fromio(skb->data, xfer_start, semi_count);
+		count -= semi_count;
+		memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
+	} else {
+		memcpy_fromio(skb->data, xfer_start, count);
+	}
+
+}
+
+static void ultramca_block_output(struct net_device *dev, int count, const unsigned char *buf,
+                int start_page)
+{
+	void __iomem *shmem = ei_status.mem + ((start_page - START_PG) << 8);
+
+	memcpy_toio(shmem, buf, count);
+}
+
+static int ultramca_close_card(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+
+	netif_stop_queue(dev);
+
+	if (ei_debug > 1)
+		printk("%s: Shutting down ethercard.\n", dev->name);
+
+	outb(0x00, ioaddr + 6);     /* Disable interrupts. */
+	free_irq(dev->irq, dev);
+
+	NS8390_init(dev, 0);
+	/* We should someday disable shared memory and change to 8-bit mode
+         * "just in case"...
+	 */
+
+	return 0;
+}
+
+static int ultramca_remove(struct device *gen_dev)
+{
+	struct mca_device *mca_dev = to_mca_device(gen_dev);
+	struct net_device *dev = dev_get_drvdata(gen_dev);
+
+	if (dev) {
+		/* NB: ultra_close_card() does free_irq */
+		int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;
+
+		unregister_netdev(dev);
+		mca_device_set_claim(mca_dev, 0);
+		release_region(ioaddr, ULTRA_IO_EXTENT);
+		iounmap(ei_status.mem);
+		free_netdev(dev);
+	}
+	return 0;
+}
+
+
+static struct mca_driver ultra_driver = {
+	.id_table = smc_mca_adapter_ids,
+	.driver = {
+		.name = "smc-mca",
+		.bus = &mca_bus_type,
+		.probe = ultramca_probe,
+		.remove = ultramca_remove,
+	}
+};
+
+static int __init ultramca_init_module(void)
+{
+	if(!MCA_bus)
+		return -ENXIO;
+
+	mca_register_driver(&ultra_driver);
+
+	return ultra_found ? 0 : -ENXIO;
+}
+
+static void __exit ultramca_cleanup_module(void)
+{
+	mca_unregister_driver(&ultra_driver);
+}
+module_init(ultramca_init_module);
+module_exit(ultramca_cleanup_module);
+
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/smc-ultra32.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/smc-ultra32.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/smc-ultra32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/smc-ultra32.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,464 @@
+/* 	smc-ultra32.c: An SMC Ultra32 EISA ethernet driver for linux.
+
+Sources:
+
+	This driver is based on (cloned from) the ISA SMC Ultra driver
+	written by Donald Becker. Modifications to support the EISA
+	version of the card by Paul Gortmaker and Leonard N. Zubkoff.
+
+	This software may be used and distributed according to the terms
+	of the GNU General Public License, incorporated herein by reference.
+
+Theory of Operation:
+
+	The SMC Ultra32C card uses the SMC 83c790 chip which is also
+	found on the ISA SMC Ultra cards. It has a shared memory mode of
+	operation that makes it similar to the ISA version of the card.
+	The main difference is that the EISA card has 32KB of RAM, but
+	only an 8KB window into that memory. The EISA card also can be
+	set for a bus-mastering mode of operation via the ECU, but that
+	is not (and probably will never be) supported by this driver.
+	The ECU should be run to enable shared memory and to disable the
+	bus-mastering feature for use with linux.
+
+	By programming the 8390 to use only 8KB RAM, the modifications
+	to the ISA driver can be limited to the probe and initialization
+	code. This allows easy integration of EISA support into the ISA
+	driver. However, the driver development kit from SMC provided the
+	register information for sliding the 8KB window, and hence the 8390
+	is programmed to use the full 32KB RAM.
+
+	Unfortunately this required code changes outside the probe/init
+	routines, and thus we decided to separate the EISA driver from
+	the ISA one. In this way, ISA users don't end up with a larger
+	driver due to the EISA code, and EISA users don't end up with a
+	larger driver due to the ISA EtherEZ PIO code. The driver is
+	similar to the 3c503/16 driver, in that the window must be set
+	back to the 1st 8KB of space for access to the two 8390 Tx slots.
+
+	In testing, using only 8KB RAM (3 Tx / 5 Rx) didn't appear to
+	be a limiting factor, since the EISA bus could get packets off
+	the card fast enough, but having the use of lots of RAM as Rx
+	space is extra insurance if interrupt latencies become excessive.
+
+*/
+
+static const char *version = "smc-ultra32.c: 06/97 v1.00\n";
+
+
+#include <linux/module.h>
+#include <linux/eisa.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "8390.h"
+
+#define DRV_NAME "smc-ultra32"
+
+static int ultra32_probe1(struct net_device *dev, int ioaddr);
+static int ultra32_open(struct net_device *dev);
+static void ultra32_reset_8390(struct net_device *dev);
+static void ultra32_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+				 int ring_page);
+static void ultra32_block_input(struct net_device *dev, int count,
+				struct sk_buff *skb, int ring_offset);
+static void ultra32_block_output(struct net_device *dev, int count,
+				 const unsigned char *buf,
+				 const int start_page);
+static int ultra32_close(struct net_device *dev);
+
+#define ULTRA32_CMDREG	0	/* Offset to ASIC command register. */
+#define	 ULTRA32_RESET	0x80	/* Board reset, in ULTRA32_CMDREG. */
+#define	 ULTRA32_MEMENB	0x40	/* Enable the shared memory. */
+#define ULTRA32_NIC_OFFSET 16	/* NIC register offset from the base_addr. */
+#define ULTRA32_IO_EXTENT 32
+#define EN0_ERWCNT		0x08	/* Early receive warning count. */
+
+/*
+ * Defines that apply only to the Ultra32 EISA card. Note that
+ * "smc" = 10011 01101 00011 = 0x4da3, and hence !smc8010.cfg translates
+ * into an EISA ID of 0x1080A34D
+ */
+#define ULTRA32_BASE	0xca0
+#define ULTRA32_ID	0x1080a34d
+#define ULTRA32_IDPORT	(-0x20)	/* 0xc80 */
+/* Config regs 1->7 from the EISA !SMC8010.CFG file. */
+#define ULTRA32_CFG1	0x04	/* 0xca4 */
+#define ULTRA32_CFG2	0x05	/* 0xca5 */
+#define ULTRA32_CFG3	(-0x18)	/* 0xc88 */
+#define ULTRA32_CFG4	(-0x17)	/* 0xc89 */
+#define ULTRA32_CFG5	(-0x16)	/* 0xc8a */
+#define ULTRA32_CFG6	(-0x15)	/* 0xc8b */
+#define ULTRA32_CFG7	0x0d	/* 0xcad */
+
+static void cleanup_card(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET;
+	/* NB: ultra32_close_card() does free_irq */
+	release_region(ioaddr, ULTRA32_IO_EXTENT);
+	iounmap(ei_status.mem);
+}
+
+/*	Probe for the Ultra32.  This looks like a 8013 with the station
+	address PROM at I/O ports <base>+8 to <base>+13, with a checksum
+	following.
+*/
+
+struct net_device * __init ultra32_probe(int unit)
+{
+	struct net_device *dev;
+	int base;
+	int irq;
+	int err = -ENODEV;
+
+	if (!EISA_bus)
+		return ERR_PTR(-ENODEV);
+
+	dev = alloc_ei_netdev();
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	if (unit >= 0) {
+		sprintf(dev->name, "eth%d", unit);
+		netdev_boot_setup_check(dev);
+	}
+
+	irq = dev->irq;
+
+	/* EISA spec allows for up to 16 slots, but 8 is typical. */
+	for (base = 0x1000 + ULTRA32_BASE; base < 0x9000; base += 0x1000) {
+		if (ultra32_probe1(dev, base) == 0)
+			break;
+		dev->irq = irq;
+	}
+	if (base >= 0x9000)
+		goto out;
+	err = register_netdev(dev);
+	if (err)
+		goto out1;
+	return dev;
+out1:
+	cleanup_card(dev);
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+
+
+static const struct net_device_ops ultra32_netdev_ops = {
+	.ndo_open 		= ultra32_open,
+	.ndo_stop 		= ultra32_close,
+	.ndo_start_xmit		= ei_start_xmit,
+	.ndo_tx_timeout		= ei_tx_timeout,
+	.ndo_get_stats		= ei_get_stats,
+	.ndo_set_rx_mode	= 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,
+#endif
+};
+
+static int __init ultra32_probe1(struct net_device *dev, int ioaddr)
+{
+	int i, edge, media, retval;
+	int checksum = 0;
+	const char *model_name;
+	static unsigned version_printed;
+	/* Values from various config regs. */
+	unsigned char idreg;
+	unsigned char reg4;
+	const char *ifmap[] = {"UTP No Link", "", "UTP/AUI", "UTP/BNC"};
+
+	if (!request_region(ioaddr, ULTRA32_IO_EXTENT, DRV_NAME))
+		return -EBUSY;
+
+	if (inb(ioaddr + ULTRA32_IDPORT) == 0xff ||
+	    inl(ioaddr + ULTRA32_IDPORT) != ULTRA32_ID) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	media = inb(ioaddr + ULTRA32_CFG7) & 0x03;
+	edge = inb(ioaddr + ULTRA32_CFG5) & 0x08;
+	printk("SMC Ultra32 in EISA Slot %d, Media: %s, %s IRQs.\n",
+		ioaddr >> 12, ifmap[media],
+		(edge ? "Edge Triggered" : "Level Sensitive"));
+
+	idreg = inb(ioaddr + 7);
+	reg4 = inb(ioaddr + 4) & 0x7f;
+
+	/* Check the ID nibble. */
+	if ((idreg & 0xf0) != 0x20) {			/* SMC Ultra */
+		retval = -ENODEV;
+		goto out;
+	}
+
+	/* Select the station address register set. */
+	outb(reg4, ioaddr + 4);
+
+	for (i = 0; i < 8; i++)
+		checksum += inb(ioaddr + 8 + i);
+	if ((checksum & 0xff) != 0xff) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	if (ei_debug  &&  version_printed++ == 0)
+		printk(version);
+
+	model_name = "SMC Ultra32";
+
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = inb(ioaddr + 8 + i);
+
+	printk("%s: %s at 0x%X, %pM",
+	       dev->name, model_name, ioaddr, dev->dev_addr);
+
+	/* Switch from the station address to the alternate register set and
+	   read the useful registers there. */
+	outb(0x80 | reg4, ioaddr + 4);
+
+	/* Enable FINE16 mode to avoid BIOS ROM width mismatches @ reboot. */
+	outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
+
+	/* Reset RAM addr. */
+	outb(0x00, ioaddr + 0x0b);
+
+	/* Switch back to the station address register set so that the
+	   MS-DOS driver can find the card after a warm boot. */
+	outb(reg4, ioaddr + 4);
+
+	if ((inb(ioaddr + ULTRA32_CFG5) & 0x40) == 0) {
+		printk("\nsmc-ultra32: Card RAM is disabled!  "
+		       "Run EISA config utility.\n");
+		retval = -ENODEV;
+		goto out;
+	}
+	if ((inb(ioaddr + ULTRA32_CFG2) & 0x04) == 0)
+		printk("\nsmc-ultra32: Ignoring Bus-Master enable bit.  "
+		       "Run EISA config utility.\n");
+
+	if (dev->irq < 2) {
+		unsigned char irqmap[] = {0, 9, 3, 5, 7, 10, 11, 15};
+		int irq = irqmap[inb(ioaddr + ULTRA32_CFG5) & 0x07];
+		if (irq == 0) {
+			printk(", failed to detect IRQ line.\n");
+			retval = -EAGAIN;
+			goto out;
+		}
+		dev->irq = irq;
+	}
+
+	/* The 8390 isn't at the base address, so fake the offset */
+	dev->base_addr = ioaddr + ULTRA32_NIC_OFFSET;
+
+	/* Save RAM address in the unused reg0 to avoid excess inb's. */
+	ei_status.reg0 = inb(ioaddr + ULTRA32_CFG3) & 0xfc;
+
+	dev->mem_start =  0xc0000 + ((ei_status.reg0 & 0x7c) << 11);
+
+	ei_status.name = model_name;
+	ei_status.word16 = 1;
+	ei_status.tx_start_page = 0;
+	ei_status.rx_start_page = TX_PAGES;
+	/* All Ultra32 cards have 32KB memory with an 8KB window. */
+	ei_status.stop_page = 128;
+
+	ei_status.mem = ioremap(dev->mem_start, 0x2000);
+	if (!ei_status.mem) {
+		printk(", failed to ioremap.\n");
+		retval = -ENOMEM;
+		goto out;
+	}
+	dev->mem_end = dev->mem_start + 0x1fff;
+
+	printk(", IRQ %d, 32KB memory, 8KB window at 0x%lx-0x%lx.\n",
+	       dev->irq, dev->mem_start, dev->mem_end);
+	ei_status.block_input = &ultra32_block_input;
+	ei_status.block_output = &ultra32_block_output;
+	ei_status.get_8390_hdr = &ultra32_get_8390_hdr;
+	ei_status.reset_8390 = &ultra32_reset_8390;
+
+	dev->netdev_ops = &ultra32_netdev_ops;
+	NS8390_init(dev, 0);
+
+	return 0;
+out:
+	release_region(ioaddr, ULTRA32_IO_EXTENT);
+	return retval;
+}
+
+static int ultra32_open(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* ASIC addr */
+	int irq_flags = (inb(ioaddr + ULTRA32_CFG5) & 0x08) ? 0 : IRQF_SHARED;
+	int retval;
+
+	retval = request_irq(dev->irq, ei_interrupt, irq_flags, dev->name, dev);
+	if (retval)
+		return retval;
+
+	outb(ULTRA32_MEMENB, ioaddr); /* Enable Shared Memory. */
+	outb(0x80, ioaddr + ULTRA32_CFG6); /* Enable Interrupts. */
+	outb(0x84, ioaddr + 5);	/* Enable MEM16 & Disable Bus Master. */
+	outb(0x01, ioaddr + 6);	/* Enable Interrupts. */
+	/* Set the early receive warning level in window 0 high enough not
+	   to receive ERW interrupts. */
+	outb_p(E8390_NODMA+E8390_PAGE0, dev->base_addr);
+	outb(0xff, dev->base_addr + EN0_ERWCNT);
+	ei_open(dev);
+	return 0;
+}
+
+static int ultra32_close(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* CMDREG */
+
+	netif_stop_queue(dev);
+
+	if (ei_debug > 1)
+		printk("%s: Shutting down ethercard.\n", dev->name);
+
+	outb(0x00, ioaddr + ULTRA32_CFG6); /* Disable Interrupts. */
+	outb(0x00, ioaddr + 6);		/* Disable interrupts. */
+	free_irq(dev->irq, dev);
+
+	NS8390_init(dev, 0);
+
+	return 0;
+}
+
+static void ultra32_reset_8390(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* ASIC base addr */
+
+	outb(ULTRA32_RESET, ioaddr);
+	if (ei_debug > 1) printk("resetting Ultra32, t=%ld...", jiffies);
+	ei_status.txing = 0;
+
+	outb(ULTRA32_MEMENB, ioaddr); /* Enable Shared Memory. */
+	outb(0x80, ioaddr + ULTRA32_CFG6); /* Enable Interrupts. */
+	outb(0x84, ioaddr + 5);	/* Enable MEM16 & Disable Bus Master. */
+	outb(0x01, ioaddr + 6);	/* Enable Interrupts. */
+	if (ei_debug > 1) printk("reset done\n");
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void ultra32_get_8390_hdr(struct net_device *dev,
+				 struct e8390_pkt_hdr *hdr,
+				 int ring_page)
+{
+	void __iomem *hdr_start = ei_status.mem + ((ring_page & 0x1f) << 8);
+	unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3;
+
+	/* Select correct 8KB Window. */
+	outb(ei_status.reg0 | ((ring_page & 0x60) >> 5), RamReg);
+
+#ifdef __BIG_ENDIAN
+	/* Officially this is what we are doing, but the readl() is faster */
+	/* unfortunately it isn't endian aware of the struct               */
+	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	hdr->count = le16_to_cpu(hdr->count);
+#else
+	((unsigned int*)hdr)[0] = readl(hdr_start);
+#endif
+}
+
+/* Block input and output are easy on shared memory ethercards, the only
+   complication is when the ring buffer wraps, or in this case, when a
+   packet spans an 8KB boundary. Note that the current 8KB segment is
+   already set by the get_8390_hdr routine. */
+
+static void ultra32_block_input(struct net_device *dev,
+				int count,
+				struct sk_buff *skb,
+				int ring_offset)
+{
+	void __iomem *xfer_start = ei_status.mem + (ring_offset & 0x1fff);
+	unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3;
+
+	if ((ring_offset & ~0x1fff) != ((ring_offset + count - 1) & ~0x1fff)) {
+		int semi_count = 8192 - (ring_offset & 0x1FFF);
+		memcpy_fromio(skb->data, xfer_start, semi_count);
+		count -= semi_count;
+		if (ring_offset < 96*256) {
+			/* Select next 8KB Window. */
+			ring_offset += semi_count;
+			outb(ei_status.reg0 | ((ring_offset & 0x6000) >> 13), RamReg);
+			memcpy_fromio(skb->data + semi_count, ei_status.mem, count);
+		} else {
+			/* Select first 8KB Window. */
+			outb(ei_status.reg0, RamReg);
+			memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
+		}
+	} else {
+		memcpy_fromio(skb->data, xfer_start, count);
+	}
+}
+
+static void ultra32_block_output(struct net_device *dev,
+				 int count,
+				 const unsigned char *buf,
+				 int start_page)
+{
+	void __iomem *xfer_start = ei_status.mem + (start_page<<8);
+	unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3;
+
+	/* Select first 8KB Window. */
+	outb(ei_status.reg0, RamReg);
+
+	memcpy_toio(xfer_start, buf, count);
+}
+
+#ifdef MODULE
+#define MAX_ULTRA32_CARDS   4	/* Max number of Ultra cards per module */
+static struct net_device *dev_ultra[MAX_ULTRA32_CARDS];
+
+MODULE_DESCRIPTION("SMC Ultra32 EISA ethernet driver");
+MODULE_LICENSE("GPL");
+
+int __init init_module(void)
+{
+	int this_dev, found = 0;
+
+	for (this_dev = 0; this_dev < MAX_ULTRA32_CARDS; this_dev++) {
+		struct net_device *dev = ultra32_probe(-1);
+		if (IS_ERR(dev))
+			break;
+		dev_ultra[found++] = dev;
+	}
+	if (found)
+		return 0;
+	printk(KERN_WARNING "smc-ultra32.c: No SMC Ultra32 found.\n");
+	return -ENXIO;
+}
+
+void __exit cleanup_module(void)
+{
+	int this_dev;
+
+	for (this_dev = 0; this_dev < MAX_ULTRA32_CARDS; this_dev++) {
+		struct net_device *dev = dev_ultra[this_dev];
+		if (dev) {
+			unregister_netdev(dev);
+			cleanup_card(dev);
+			free_netdev(dev);
+		}
+	}
+}
+#endif /* MODULE */
+
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/smc-ultra.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/smc-ultra.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/smc-ultra.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/smc-ultra.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,622 @@
+/* smc-ultra.c: A SMC Ultra ethernet driver for linux. */
+/*
+	This is a driver for the SMC Ultra and SMC EtherEZ ISA ethercards.
+
+	Written 1993-1998 by Donald Becker.
+
+	Copyright 1993 United States Government as represented by the
+	Director, National Security Agency.
+
+	This software may be used and distributed according to the terms
+	of the GNU General Public License, incorporated herein by reference.
+
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+	This driver uses the cards in the 8390-compatible mode.
+	Most of the run-time complexity is handled by the generic code in
+	8390.c.  The code in this file is responsible for
+
+		ultra_probe()	 	Detecting and initializing the card.
+		ultra_probe1()
+		ultra_probe_isapnp()
+
+		ultra_open()		The card-specific details of starting, stopping
+		ultra_reset_8390()	and resetting the 8390 NIC core.
+		ultra_close()
+
+		ultra_block_input()		Routines for reading and writing blocks of
+		ultra_block_output()	packet buffer memory.
+		ultra_pio_input()
+		ultra_pio_output()
+
+	This driver enables the shared memory only when doing the actual data
+	transfers to avoid a bug in early version of the card that corrupted
+	data transferred by a AHA1542.
+
+	This driver now supports the programmed-I/O (PIO) data transfer mode of
+	the EtherEZ. It does not use the non-8390-compatible "Altego" mode.
+	That support (if available) is in smc-ez.c.
+
+	Changelog:
+
+	Paul Gortmaker	: multiple card support for module users.
+	Donald Becker	: 4/17/96 PIO support, minor potential problems avoided.
+	Donald Becker	: 6/6/96 correctly set auto-wrap bit.
+	Alexander Sotirov : 1/20/01 Added support for ISAPnP cards
+
+	Note about the ISA PnP support:
+
+	This driver can not autoprobe for more than one SMC EtherEZ PnP card.
+	You have to configure the second card manually through the /proc/isapnp
+	interface and then load the module with an explicit io=0x___ option.
+*/
+
+static const char version[] =
+	"smc-ultra.c:v2.02 2/3/98 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/isapnp.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "8390.h"
+
+#define DRV_NAME "smc-ultra"
+
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int ultra_portlist[] __initdata =
+{0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0};
+
+static int ultra_probe1(struct net_device *dev, int ioaddr);
+
+#ifdef __ISAPNP__
+static int ultra_probe_isapnp(struct net_device *dev);
+#endif
+
+static int ultra_open(struct net_device *dev);
+static void ultra_reset_8390(struct net_device *dev);
+static void ultra_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+						int ring_page);
+static void ultra_block_input(struct net_device *dev, int count,
+						  struct sk_buff *skb, int ring_offset);
+static void ultra_block_output(struct net_device *dev, int count,
+							const unsigned char *buf, const int start_page);
+static void ultra_pio_get_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+						int ring_page);
+static void ultra_pio_input(struct net_device *dev, int count,
+						  struct sk_buff *skb, int ring_offset);
+static void ultra_pio_output(struct net_device *dev, int count,
+							 const unsigned char *buf, const int start_page);
+static int ultra_close_card(struct net_device *dev);
+
+#ifdef __ISAPNP__
+static struct isapnp_device_id ultra_device_ids[] __initdata = {
+        {       ISAPNP_VENDOR('S','M','C'), ISAPNP_FUNCTION(0x8416),
+                ISAPNP_VENDOR('S','M','C'), ISAPNP_FUNCTION(0x8416),
+                (long) "SMC EtherEZ (8416)" },
+        { }	/* terminate list */
+};
+
+MODULE_DEVICE_TABLE(isapnp, ultra_device_ids);
+#endif
+
+
+#define START_PG		0x00	/* First page of TX buffer */
+
+#define ULTRA_CMDREG	0		/* Offset to ASIC command register. */
+#define	 ULTRA_RESET	0x80	/* Board reset, in ULTRA_CMDREG. */
+#define	 ULTRA_MEMENB	0x40	/* Enable the shared memory. */
+#define IOPD	0x02			/* I/O Pipe Data (16 bits), PIO operation. */
+#define IOPA	0x07			/* I/O Pipe Address for PIO operation. */
+#define ULTRA_NIC_OFFSET  16	/* NIC register offset from the base_addr. */
+#define ULTRA_IO_EXTENT 32
+#define EN0_ERWCNT		0x08	/* Early receive warning count. */
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void ultra_poll(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	ei_interrupt(dev->irq, dev);
+	enable_irq(dev->irq);
+}
+#endif
+/*	Probe for the Ultra.  This looks like a 8013 with the station
+	address PROM at I/O ports <base>+8 to <base>+13, with a checksum
+	following.
+*/
+
+static int __init do_ultra_probe(struct net_device *dev)
+{
+	int i;
+	int base_addr = dev->base_addr;
+	int irq = dev->irq;
+
+	if (base_addr > 0x1ff)		/* Check a single specified location. */
+		return ultra_probe1(dev, base_addr);
+	else if (base_addr != 0)	/* Don't probe at all. */
+		return -ENXIO;
+
+#ifdef __ISAPNP__
+	/* Look for any installed ISAPnP cards */
+	if (isapnp_present() && (ultra_probe_isapnp(dev) == 0))
+		return 0;
+#endif
+
+	for (i = 0; ultra_portlist[i]; i++) {
+		dev->irq = irq;
+		if (ultra_probe1(dev, ultra_portlist[i]) == 0)
+			return 0;
+	}
+
+	return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init ultra_probe(int unit)
+{
+	struct net_device *dev = alloc_ei_netdev();
+	int err;
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+
+	err = do_ultra_probe(dev);
+	if (err)
+		goto out;
+	return dev;
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+#endif
+
+static const struct net_device_ops ultra_netdev_ops = {
+	.ndo_open		= ultra_open,
+	.ndo_stop		= ultra_close_card,
+
+	.ndo_start_xmit		= ei_start_xmit,
+	.ndo_tx_timeout		= ei_tx_timeout,
+	.ndo_get_stats		= ei_get_stats,
+	.ndo_set_rx_mode	= 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 	= ultra_poll,
+#endif
+};
+
+static int __init ultra_probe1(struct net_device *dev, int ioaddr)
+{
+	int i, retval;
+	int checksum = 0;
+	const char *model_name;
+	unsigned char eeprom_irq = 0;
+	static unsigned version_printed;
+	/* Values from various config regs. */
+	unsigned char num_pages, irqreg, addr, piomode;
+	unsigned char idreg = inb(ioaddr + 7);
+	unsigned char reg4 = inb(ioaddr + 4) & 0x7f;
+
+	if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME))
+		return -EBUSY;
+
+	/* Check the ID nibble. */
+	if ((idreg & 0xF0) != 0x20 			/* SMC Ultra */
+		&& (idreg & 0xF0) != 0x40) {		/* SMC EtherEZ */
+		retval = -ENODEV;
+		goto out;
+	}
+
+	/* Select the station address register set. */
+	outb(reg4, ioaddr + 4);
+
+	for (i = 0; i < 8; i++)
+		checksum += inb(ioaddr + 8 + i);
+	if ((checksum & 0xff) != 0xFF) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	if (ei_debug  &&  version_printed++ == 0)
+		printk(version);
+
+	model_name = (idreg & 0xF0) == 0x20 ? "SMC Ultra" : "SMC EtherEZ";
+
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = inb(ioaddr + 8 + i);
+
+	printk("%s: %s at %#3x, %pM", dev->name, model_name,
+	       ioaddr, dev->dev_addr);
+
+	/* Switch from the station address to the alternate register set and
+	   read the useful registers there. */
+	outb(0x80 | reg4, ioaddr + 4);
+
+	/* Enabled FINE16 mode to avoid BIOS ROM width mismatches @ reboot. */
+	outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
+	piomode = inb(ioaddr + 0x8);
+	addr = inb(ioaddr + 0xb);
+	irqreg = inb(ioaddr + 0xd);
+
+	/* Switch back to the station address register set so that the MS-DOS driver
+	   can find the card after a warm boot. */
+	outb(reg4, ioaddr + 4);
+
+	if (dev->irq < 2) {
+		unsigned char irqmap[] = {0, 9, 3, 5, 7, 10, 11, 15};
+		int irq;
+
+		/* The IRQ bits are split. */
+		irq = irqmap[((irqreg & 0x40) >> 4) + ((irqreg & 0x0c) >> 2)];
+
+		if (irq == 0) {
+			printk(", failed to detect IRQ line.\n");
+			retval =  -EAGAIN;
+			goto out;
+		}
+		dev->irq = irq;
+		eeprom_irq = 1;
+	}
+
+	/* The 8390 isn't at the base address, so fake the offset */
+	dev->base_addr = ioaddr+ULTRA_NIC_OFFSET;
+
+	{
+		static const int addr_tbl[4] = {
+			0x0C0000, 0x0E0000, 0xFC0000, 0xFE0000
+		};
+		static const short num_pages_tbl[4] = {
+			0x20, 0x40, 0x80, 0xff
+		};
+
+		dev->mem_start = ((addr & 0x0f) << 13) + addr_tbl[(addr >> 6) & 3] ;
+		num_pages = num_pages_tbl[(addr >> 4) & 3];
+	}
+
+	ei_status.name = model_name;
+	ei_status.word16 = 1;
+	ei_status.tx_start_page = START_PG;
+	ei_status.rx_start_page = START_PG + TX_PAGES;
+	ei_status.stop_page = num_pages;
+
+	ei_status.mem = ioremap(dev->mem_start, (ei_status.stop_page - START_PG)*256);
+	if (!ei_status.mem) {
+		printk(", failed to ioremap.\n");
+		retval =  -ENOMEM;
+		goto out;
+	}
+
+	dev->mem_end = dev->mem_start + (ei_status.stop_page - START_PG)*256;
+
+	if (piomode) {
+		printk(",%s IRQ %d programmed-I/O mode.\n",
+			   eeprom_irq ? "EEPROM" : "assigned ", dev->irq);
+		ei_status.block_input = &ultra_pio_input;
+		ei_status.block_output = &ultra_pio_output;
+		ei_status.get_8390_hdr = &ultra_pio_get_hdr;
+	} else {
+		printk(",%s IRQ %d memory %#lx-%#lx.\n", eeprom_irq ? "" : "assigned ",
+			   dev->irq, dev->mem_start, dev->mem_end-1);
+		ei_status.block_input = &ultra_block_input;
+		ei_status.block_output = &ultra_block_output;
+		ei_status.get_8390_hdr = &ultra_get_8390_hdr;
+	}
+	ei_status.reset_8390 = &ultra_reset_8390;
+
+	dev->netdev_ops = &ultra_netdev_ops;
+	NS8390_init(dev, 0);
+
+	retval = register_netdev(dev);
+	if (retval)
+		goto out;
+	return 0;
+out:
+	release_region(ioaddr, ULTRA_IO_EXTENT);
+	return retval;
+}
+
+#ifdef __ISAPNP__
+static int __init ultra_probe_isapnp(struct net_device *dev)
+{
+        int i;
+
+        for (i = 0; ultra_device_ids[i].vendor != 0; i++) {
+		struct pnp_dev *idev = NULL;
+
+                while ((idev = pnp_find_dev(NULL,
+                                            ultra_device_ids[i].vendor,
+                                            ultra_device_ids[i].function,
+                                            idev))) {
+                        /* Avoid already found cards from previous calls */
+                        if (pnp_device_attach(idev) < 0)
+                        	continue;
+                        if (pnp_activate_dev(idev) < 0) {
+                              __again:
+                        	pnp_device_detach(idev);
+                        	continue;
+                        }
+			/* if no io and irq, search for next */
+			if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0))
+				goto __again;
+                        /* found it */
+			dev->base_addr = pnp_port_start(idev, 0);
+			dev->irq = pnp_irq(idev, 0);
+                        printk(KERN_INFO "smc-ultra.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
+                                (char *) ultra_device_ids[i].driver_data,
+                                dev->base_addr, dev->irq);
+                        if (ultra_probe1(dev, dev->base_addr) != 0) {      /* Shouldn't happen. */
+                                printk(KERN_ERR "smc-ultra.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr);
+                                pnp_device_detach(idev);
+				return -ENXIO;
+                        }
+                        ei_status.priv = (unsigned long)idev;
+                        break;
+                }
+                if (!idev)
+                        continue;
+                return 0;
+        }
+
+        return -ENODEV;
+}
+#endif
+
+static int
+ultra_open(struct net_device *dev)
+{
+	int retval;
+	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+	unsigned char irq2reg[] = {0, 0, 0x04, 0x08, 0, 0x0C, 0, 0x40,
+				   0, 0x04, 0x44, 0x48, 0, 0, 0, 0x4C, };
+
+	retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev);
+	if (retval)
+		return retval;
+
+	outb(0x00, ioaddr);	/* Disable shared memory for safety. */
+	outb(0x80, ioaddr + 5);
+	/* Set the IRQ line. */
+	outb(inb(ioaddr + 4) | 0x80, ioaddr + 4);
+	outb((inb(ioaddr + 13) & ~0x4C) | irq2reg[dev->irq], ioaddr + 13);
+	outb(inb(ioaddr + 4) & 0x7f, ioaddr + 4);
+
+	if (ei_status.block_input == &ultra_pio_input) {
+		outb(0x11, ioaddr + 6);		/* Enable interrupts and PIO. */
+		outb(0x01, ioaddr + 0x19);  	/* Enable ring read auto-wrap. */
+	} else
+		outb(0x01, ioaddr + 6);		/* Enable interrupts and memory. */
+	/* Set the early receive warning level in window 0 high enough not
+	   to receive ERW interrupts. */
+	outb_p(E8390_NODMA+E8390_PAGE0, dev->base_addr);
+	outb(0xff, dev->base_addr + EN0_ERWCNT);
+	ei_open(dev);
+	return 0;
+}
+
+static void
+ultra_reset_8390(struct net_device *dev)
+{
+	int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */
+
+	outb(ULTRA_RESET, cmd_port);
+	if (ei_debug > 1) printk("resetting Ultra, t=%ld...", jiffies);
+	ei_status.txing = 0;
+
+	outb(0x00, cmd_port);	/* Disable shared memory for safety. */
+	outb(0x80, cmd_port + 5);
+	if (ei_status.block_input == &ultra_pio_input)
+		outb(0x11, cmd_port + 6);		/* Enable interrupts and PIO. */
+	else
+		outb(0x01, cmd_port + 6);		/* Enable interrupts and memory. */
+
+	if (ei_debug > 1) printk("reset done\n");
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void
+ultra_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	void __iomem *hdr_start = ei_status.mem + ((ring_page - START_PG)<<8);
+
+	outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);	/* shmem on */
+#ifdef __BIG_ENDIAN
+	/* Officially this is what we are doing, but the readl() is faster */
+	/* unfortunately it isn't endian aware of the struct               */
+	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	hdr->count = le16_to_cpu(hdr->count);
+#else
+	((unsigned int*)hdr)[0] = readl(hdr_start);
+#endif
+	outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem off */
+}
+
+/* Block input and output are easy on shared memory ethercards, the only
+   complication is when the ring buffer wraps. */
+
+static void
+ultra_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+	void __iomem *xfer_start = ei_status.mem + ring_offset - (START_PG<<8);
+
+	/* Enable shared memory. */
+	outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);
+
+	if (ring_offset + count > ei_status.stop_page*256) {
+		/* We must wrap the input move. */
+		int semi_count = ei_status.stop_page*256 - ring_offset;
+		memcpy_fromio(skb->data, xfer_start, semi_count);
+		count -= semi_count;
+		memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
+	} else {
+		memcpy_fromio(skb->data, xfer_start, count);
+	}
+
+	outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET);	/* Disable memory. */
+}
+
+static void
+ultra_block_output(struct net_device *dev, int count, const unsigned char *buf,
+				int start_page)
+{
+	void __iomem *shmem = ei_status.mem + ((start_page - START_PG)<<8);
+
+	/* Enable shared memory. */
+	outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);
+
+	memcpy_toio(shmem, buf, count);
+
+	outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */
+}
+
+/* The identical operations for programmed I/O cards.
+   The PIO model is trivial to use: the 16 bit start address is written
+   byte-sequentially to IOPA, with no intervening I/O operations, and the
+   data is read or written to the IOPD data port.
+   The only potential complication is that the address register is shared
+   and must be always be rewritten between each read/write direction change.
+   This is no problem for us, as the 8390 code ensures that we are single
+   threaded. */
+static void ultra_pio_get_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+						int ring_page)
+{
+	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+	outb(0x00, ioaddr + IOPA);	/* Set the address, LSB first. */
+	outb(ring_page, ioaddr + IOPA);
+	insw(ioaddr + IOPD, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+}
+
+static void ultra_pio_input(struct net_device *dev, int count,
+						  struct sk_buff *skb, int ring_offset)
+{
+	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+    char *buf = skb->data;
+
+	/* For now set the address again, although it should already be correct. */
+	outb(ring_offset, ioaddr + IOPA);	/* Set the address, LSB first. */
+	outb(ring_offset >> 8, ioaddr + IOPA);
+	/* We know skbuffs are padded to at least word alignment. */
+	insw(ioaddr + IOPD, buf, (count+1)>>1);
+}
+
+static void ultra_pio_output(struct net_device *dev, int count,
+							const unsigned char *buf, const int start_page)
+{
+	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+	outb(0x00, ioaddr + IOPA);	/* Set the address, LSB first. */
+	outb(start_page, ioaddr + IOPA);
+	/* An extra odd byte is OK here as well. */
+	outsw(ioaddr + IOPD, buf, (count+1)>>1);
+}
+
+static int
+ultra_close_card(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* CMDREG */
+
+	netif_stop_queue(dev);
+
+	if (ei_debug > 1)
+		printk("%s: Shutting down ethercard.\n", dev->name);
+
+	outb(0x00, ioaddr + 6);		/* Disable interrupts. */
+	free_irq(dev->irq, dev);
+
+	NS8390_init(dev, 0);
+
+	/* We should someday disable shared memory and change to 8-bit mode
+	   "just in case"... */
+
+	return 0;
+}
+
+
+#ifdef MODULE
+#define MAX_ULTRA_CARDS	4	/* Max number of Ultra cards per module */
+static struct net_device *dev_ultra[MAX_ULTRA_CARDS];
+static int io[MAX_ULTRA_CARDS];
+static int irq[MAX_ULTRA_CARDS];
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
+MODULE_DESCRIPTION("SMC Ultra/EtherEZ ISA/PnP Ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* This is set up so that only a single autoprobe takes place per call.
+ISA device autoprobes on a running machine are not recommended. */
+int __init
+init_module(void)
+{
+	struct net_device *dev;
+	int this_dev, found = 0;
+
+	for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) {
+		if (io[this_dev] == 0)  {
+			if (this_dev != 0) break; /* only autoprobe 1st one */
+			printk(KERN_NOTICE "smc-ultra.c: Presently autoprobing (not recommended) for a single card.\n");
+		}
+		dev = alloc_ei_netdev();
+		if (!dev)
+			break;
+		dev->irq = irq[this_dev];
+		dev->base_addr = io[this_dev];
+		if (do_ultra_probe(dev) == 0) {
+			dev_ultra[found++] = dev;
+			continue;
+		}
+		free_netdev(dev);
+		printk(KERN_WARNING "smc-ultra.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]);
+		break;
+	}
+	if (found)
+		return 0;
+	return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+	/* NB: ultra_close_card() does free_irq */
+#ifdef __ISAPNP__
+	struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+	if (idev)
+		pnp_device_detach(idev);
+#endif
+	release_region(dev->base_addr - ULTRA_NIC_OFFSET, ULTRA_IO_EXTENT);
+	iounmap(ei_status.mem);
+}
+
+void __exit
+cleanup_module(void)
+{
+	int this_dev;
+
+	for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) {
+		struct net_device *dev = dev_ultra[this_dev];
+		if (dev) {
+			unregister_netdev(dev);
+			cleanup_card(dev);
+			free_netdev(dev);
+		}
+	}
+}
+#endif /* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/stnic.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/stnic.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/stnic.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/stnic.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,294 @@
+/* stnic.c : A SH7750 specific part of driver for NS DP83902A ST-NIC.
+ *
+ * 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) 1999 kaz Kojima
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <mach-se/mach/se.h>
+#include <asm/machvec.h>
+#ifdef CONFIG_SH_STANDARD_BIOS
+#include <asm/sh_bios.h>
+#endif
+
+#include "8390.h"
+
+#define DRV_NAME "stnic"
+
+#define byte	unsigned char
+#define half	unsigned short
+#define word	unsigned int
+#define vbyte	volatile unsigned char
+#define vhalf	volatile unsigned short
+#define vword	volatile unsigned int
+
+#define STNIC_RUN	0x01	/* 1 == Run, 0 == reset. */
+
+#define START_PG	0	/* First page of TX buffer */
+#define STOP_PG		128	/* Last page +1 of RX ring */
+
+/* Alias */
+#define STNIC_CR	E8390_CMD
+#define PG0_RSAR0	EN0_RSARLO
+#define PG0_RSAR1	EN0_RSARHI
+#define PG0_RBCR0	EN0_RCNTLO
+#define PG0_RBCR1	EN0_RCNTHI
+
+#define CR_RRD		E8390_RREAD
+#define CR_RWR		E8390_RWRITE
+#define CR_PG0		E8390_PAGE0
+#define CR_STA		E8390_START
+#define CR_RDMA		E8390_NODMA
+
+/* FIXME! YOU MUST SET YOUR OWN ETHER ADDRESS.  */
+static byte stnic_eadr[6] =
+{0x00, 0xc0, 0x6e, 0x00, 0x00, 0x07};
+
+static struct net_device *stnic_dev;
+
+static void stnic_reset (struct net_device *dev);
+static void stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
+			   int ring_page);
+static void stnic_block_input (struct net_device *dev, int count,
+			       struct sk_buff *skb , int ring_offset);
+static void stnic_block_output (struct net_device *dev, int count,
+				const unsigned char *buf, int start_page);
+
+static void stnic_init (struct net_device *dev);
+
+/* SH7750 specific read/write io. */
+static inline void
+STNIC_DELAY (void)
+{
+  vword trash;
+  trash = *(vword *) 0xa0000000;
+  trash = *(vword *) 0xa0000000;
+  trash = *(vword *) 0xa0000000;
+}
+
+static inline byte
+STNIC_READ (int reg)
+{
+  byte val;
+
+  val = (*(vhalf *) (PA_83902 + ((reg) << 1)) >> 8) & 0xff;
+  STNIC_DELAY ();
+  return val;
+}
+
+static inline void
+STNIC_WRITE (int reg, byte val)
+{
+  *(vhalf *) (PA_83902 + ((reg) << 1)) = ((half) (val) << 8);
+  STNIC_DELAY ();
+}
+
+static int __init stnic_probe(void)
+{
+  struct net_device *dev;
+  int i, err;
+
+  /* If we are not running on a SolutionEngine, give up now */
+  if (! MACH_SE)
+    return -ENODEV;
+
+  /* New style probing API */
+  dev = alloc_ei_netdev();
+  if (!dev)
+  	return -ENOMEM;
+
+#ifdef CONFIG_SH_STANDARD_BIOS
+  sh_bios_get_node_addr (stnic_eadr);
+#endif
+  for (i = 0; i < ETHER_ADDR_LEN; i++)
+    dev->dev_addr[i] = stnic_eadr[i];
+
+  /* Set the base address to point to the NIC, not the "real" base! */
+  dev->base_addr = 0x1000;
+  dev->irq = IRQ_STNIC;
+  dev->netdev_ops = &ei_netdev_ops;
+
+  /* Snarf the interrupt now.  There's no point in waiting since we cannot
+     share and the board will usually be enabled. */
+  err = request_irq (dev->irq, ei_interrupt, 0, DRV_NAME, dev);
+  if (err)  {
+      printk (KERN_EMERG " unable to get IRQ %d.\n", dev->irq);
+      free_netdev(dev);
+      return err;
+    }
+
+  ei_status.name = dev->name;
+  ei_status.word16 = 1;
+#ifdef __LITTLE_ENDIAN__
+  ei_status.bigendian = 0;
+#else
+  ei_status.bigendian = 1;
+#endif
+  ei_status.tx_start_page = START_PG;
+  ei_status.rx_start_page = START_PG + TX_PAGES;
+  ei_status.stop_page = STOP_PG;
+
+  ei_status.reset_8390 = &stnic_reset;
+  ei_status.get_8390_hdr = &stnic_get_hdr;
+  ei_status.block_input = &stnic_block_input;
+  ei_status.block_output = &stnic_block_output;
+
+  stnic_init (dev);
+
+  err = register_netdev(dev);
+  if (err) {
+    free_irq(dev->irq, dev);
+    free_netdev(dev);
+    return err;
+  }
+  stnic_dev = dev;
+
+  printk (KERN_INFO "NS ST-NIC 83902A\n");
+
+  return 0;
+}
+
+static void
+stnic_reset (struct net_device *dev)
+{
+  *(vhalf *) PA_83902_RST = 0;
+  udelay (5);
+  if (ei_debug > 1)
+    printk (KERN_WARNING "8390 reset done (%ld).\n", jiffies);
+  *(vhalf *) PA_83902_RST = ~0;
+  udelay (5);
+}
+
+static void
+stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
+	       int ring_page)
+{
+  half buf[2];
+
+  STNIC_WRITE (PG0_RSAR0, 0);
+  STNIC_WRITE (PG0_RSAR1, ring_page);
+  STNIC_WRITE (PG0_RBCR0, 4);
+  STNIC_WRITE (PG0_RBCR1, 0);
+  STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
+
+  buf[0] = *(vhalf *) PA_83902_IF;
+  STNIC_DELAY ();
+  buf[1] = *(vhalf *) PA_83902_IF;
+  STNIC_DELAY ();
+  hdr->next = buf[0] >> 8;
+  hdr->status = buf[0] & 0xff;
+#ifdef __LITTLE_ENDIAN__
+  hdr->count = buf[1];
+#else
+  hdr->count = ((buf[1] >> 8) & 0xff) | (buf[1] << 8);
+#endif
+
+  if (ei_debug > 1)
+    printk (KERN_DEBUG "ring %x status %02x next %02x count %04x.\n",
+	    ring_page, hdr->status, hdr->next, hdr->count);
+
+  STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
+}
+
+/* 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 HP LAN doesn't use shared memory -- we put the packet
+   out through the "remote DMA" dataport. */
+
+static void
+stnic_block_input (struct net_device *dev, int length, struct sk_buff *skb,
+		   int offset)
+{
+  char *buf = skb->data;
+  half val;
+
+  STNIC_WRITE (PG0_RSAR0, offset & 0xff);
+  STNIC_WRITE (PG0_RSAR1, offset >> 8);
+  STNIC_WRITE (PG0_RBCR0, length & 0xff);
+  STNIC_WRITE (PG0_RBCR1, length >> 8);
+  STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
+
+  if (length & 1)
+    length++;
+
+  while (length > 0)
+    {
+      val = *(vhalf *) PA_83902_IF;
+#ifdef __LITTLE_ENDIAN__
+      *buf++ = val & 0xff;
+      *buf++ = val >> 8;
+#else
+      *buf++ = val >> 8;
+      *buf++ = val & 0xff;
+#endif
+      STNIC_DELAY ();
+      length -= sizeof (half);
+    }
+
+  STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
+}
+
+static void
+stnic_block_output (struct net_device *dev, int length,
+		    const unsigned char *buf, int output_page)
+{
+  STNIC_WRITE (PG0_RBCR0, 1);	/* Write non-zero value */
+  STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
+  STNIC_DELAY ();
+
+  STNIC_WRITE (PG0_RBCR0, length & 0xff);
+  STNIC_WRITE (PG0_RBCR1, length >> 8);
+  STNIC_WRITE (PG0_RSAR0, 0);
+  STNIC_WRITE (PG0_RSAR1, output_page);
+  STNIC_WRITE (STNIC_CR, CR_RWR | CR_PG0 | CR_STA);
+
+  if (length & 1)
+    length++;
+
+  while (length > 0)
+    {
+#ifdef __LITTLE_ENDIAN__
+      *(vhalf *) PA_83902_IF = ((half) buf[1] << 8) | buf[0];
+#else
+      *(vhalf *) PA_83902_IF = ((half) buf[0] << 8) | buf[1];
+#endif
+      STNIC_DELAY ();
+      buf += sizeof (half);
+      length -= sizeof (half);
+    }
+
+  STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
+}
+
+/* This function resets the STNIC if something screws up.  */
+static void
+stnic_init (struct net_device *dev)
+{
+  stnic_reset (dev);
+  NS8390_init (dev, 0);
+}
+
+static void __exit stnic_cleanup(void)
+{
+	unregister_netdev(stnic_dev);
+	free_irq(stnic_dev->irq, stnic_dev);
+	free_netdev(stnic_dev);
+}
+
+module_init(stnic_probe);
+module_exit(stnic_cleanup);
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/wd.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/wd.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/wd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/wd.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,567 @@
+/* wd.c: A WD80x3 ethernet driver for linux. */
+/*
+	Written 1993-94 by Donald Becker.
+
+	Copyright 1993 United States Government as represented by the
+	Director, National Security Agency.
+
+	This software may be used and distributed according to the terms
+	of the GNU General Public License, incorporated herein by reference.
+
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+	This is a driver for WD8003 and WD8013 "compatible" ethercards.
+
+	Thanks to Russ Nelson (nelson@crnwyr.com) for loaning me a WD8013.
+
+	Changelog:
+
+	Paul Gortmaker	: multiple card support for module users, support
+			  for non-standard memory sizes.
+
+
+*/
+
+static const char version[] =
+	"wd.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "8390.h"
+
+#define DRV_NAME "wd"
+
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int wd_portlist[] __initdata =
+{0x300, 0x280, 0x380, 0x240, 0};
+
+static int wd_probe1(struct net_device *dev, int ioaddr);
+
+static int wd_open(struct net_device *dev);
+static void wd_reset_8390(struct net_device *dev);
+static void wd_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+						int ring_page);
+static void wd_block_input(struct net_device *dev, int count,
+						  struct sk_buff *skb, int ring_offset);
+static void wd_block_output(struct net_device *dev, int count,
+							const unsigned char *buf, int start_page);
+static int wd_close(struct net_device *dev);
+
+
+#define WD_START_PG		0x00	/* First page of TX buffer */
+#define WD03_STOP_PG	0x20	/* Last page +1 of RX ring */
+#define WD13_STOP_PG	0x40	/* Last page +1 of RX ring */
+
+#define WD_CMDREG		0		/* Offset to ASIC command register. */
+#define	 WD_RESET		0x80	/* Board reset, in WD_CMDREG. */
+#define	 WD_MEMENB		0x40	/* Enable the shared memory. */
+#define WD_CMDREG5		5		/* Offset to 16-bit-only ASIC register 5. */
+#define	 ISA16			0x80	/* Enable 16 bit access from the ISA bus. */
+#define	 NIC16			0x40	/* Enable 16 bit access from the 8390. */
+#define WD_NIC_OFFSET	16		/* Offset to the 8390 from the base_addr. */
+#define WD_IO_EXTENT	32
+
+
+/*	Probe for the WD8003 and WD8013.  These cards have the station
+	address PROM at I/O ports <base>+8 to <base>+13, with a checksum
+	following. A Soundblaster can have the same checksum as an WDethercard,
+	so we have an extra exclusionary check for it.
+
+	The wd_probe1() routine initializes the card and fills the
+	station address field. */
+
+static int __init do_wd_probe(struct net_device *dev)
+{
+	int i;
+	struct resource *r;
+	int base_addr = dev->base_addr;
+	int irq = dev->irq;
+	int mem_start = dev->mem_start;
+	int mem_end = dev->mem_end;
+
+	if (base_addr > 0x1ff) {	/* Check a user specified location. */
+		r = request_region(base_addr, WD_IO_EXTENT, "wd-probe");
+		if ( r == NULL)
+			return -EBUSY;
+		i = wd_probe1(dev, base_addr);
+		if (i != 0)
+			release_region(base_addr, WD_IO_EXTENT);
+		else
+			r->name = dev->name;
+		return i;
+	}
+	else if (base_addr != 0)	/* Don't probe at all. */
+		return -ENXIO;
+
+	for (i = 0; wd_portlist[i]; i++) {
+		int ioaddr = wd_portlist[i];
+		r = request_region(ioaddr, WD_IO_EXTENT, "wd-probe");
+		if (r == NULL)
+			continue;
+		if (wd_probe1(dev, ioaddr) == 0) {
+			r->name = dev->name;
+			return 0;
+		}
+		release_region(ioaddr, WD_IO_EXTENT);
+		dev->irq = irq;
+		dev->mem_start = mem_start;
+		dev->mem_end = mem_end;
+	}
+
+	return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init wd_probe(int unit)
+{
+	struct net_device *dev = alloc_ei_netdev();
+	int err;
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+
+	err = do_wd_probe(dev);
+	if (err)
+		goto out;
+	return dev;
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+#endif
+
+static const struct net_device_ops wd_netdev_ops = {
+	.ndo_open		= wd_open,
+	.ndo_stop		= wd_close,
+	.ndo_start_xmit		= ei_start_xmit,
+	.ndo_tx_timeout		= ei_tx_timeout,
+	.ndo_get_stats		= ei_get_stats,
+	.ndo_set_rx_mode	= 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,
+#endif
+};
+
+static int __init wd_probe1(struct net_device *dev, int ioaddr)
+{
+	int i;
+	int err;
+	int checksum = 0;
+	int ancient = 0;			/* An old card without config registers. */
+	int word16 = 0;				/* 0 = 8 bit, 1 = 16 bit */
+	const char *model_name;
+	static unsigned version_printed;
+
+	for (i = 0; i < 8; i++)
+		checksum += inb(ioaddr + 8 + i);
+	if (inb(ioaddr + 8) == 0xff 	/* Extra check to avoid soundcard. */
+		|| inb(ioaddr + 9) == 0xff
+		|| (checksum & 0xff) != 0xFF)
+		return -ENODEV;
+
+	/* Check for semi-valid mem_start/end values if supplied. */
+	if ((dev->mem_start % 0x2000) || (dev->mem_end % 0x2000)) {
+		printk(KERN_WARNING "wd.c: user supplied mem_start or mem_end not on 8kB boundary - ignored.\n");
+		dev->mem_start = 0;
+		dev->mem_end = 0;
+	}
+
+	if (ei_debug  &&  version_printed++ == 0)
+		printk(version);
+
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = inb(ioaddr + 8 + i);
+
+	printk("%s: WD80x3 at %#3x, %pM",
+	       dev->name, ioaddr, dev->dev_addr);
+
+	/* The following PureData probe code was contributed by
+	   Mike Jagdis <jaggy@purplet.demon.co.uk>. Puredata does software
+	   configuration differently from others so we have to check for them.
+	   This detects an 8 bit, 16 bit or dumb (Toshiba, jumpered) card.
+	   */
+	if (inb(ioaddr+0) == 'P' && inb(ioaddr+1) == 'D') {
+		unsigned char reg5 = inb(ioaddr+5);
+
+		switch (inb(ioaddr+2)) {
+		case 0x03: word16 = 0; model_name = "PDI8023-8";	break;
+		case 0x05: word16 = 0; model_name = "PDUC8023";	break;
+		case 0x0a: word16 = 1; model_name = "PDI8023-16"; break;
+			/* Either 0x01 (dumb) or they've released a new version. */
+		default:	 word16 = 0; model_name = "PDI8023";	break;
+		}
+		dev->mem_start = ((reg5 & 0x1c) + 0xc0) << 12;
+		dev->irq = (reg5 & 0xe0) == 0xe0 ? 10 : (reg5 >> 5) + 1;
+	} else {								/* End of PureData probe */
+		/* This method of checking for a 16-bit board is borrowed from the
+		   we.c driver.  A simpler method is just to look in ASIC reg. 0x03.
+		   I'm comparing the two method in alpha test to make certain they
+		   return the same result. */
+		/* Check for the old 8 bit board - it has register 0/8 aliasing.
+		   Do NOT check i>=6 here -- it hangs the old 8003 boards! */
+		for (i = 0; i < 6; i++)
+			if (inb(ioaddr+i) != inb(ioaddr+8+i))
+				break;
+		if (i >= 6) {
+			ancient = 1;
+			model_name = "WD8003-old";
+			word16 = 0;
+		} else {
+			int tmp = inb(ioaddr+1); /* fiddle with 16bit bit */
+			outb( tmp ^ 0x01, ioaddr+1 ); /* attempt to clear 16bit bit */
+			if (((inb( ioaddr+1) & 0x01) == 0x01) /* A 16 bit card */
+				&& (tmp & 0x01) == 0x01	) {				/* In a 16 slot. */
+				int asic_reg5 = inb(ioaddr+WD_CMDREG5);
+				/* Magic to set ASIC to word-wide mode. */
+				outb( NIC16 | (asic_reg5&0x1f), ioaddr+WD_CMDREG5);
+				outb(tmp, ioaddr+1);
+				model_name = "WD8013";
+				word16 = 1;		/* We have a 16bit board here! */
+			} else {
+				model_name = "WD8003";
+				word16 = 0;
+			}
+			outb(tmp, ioaddr+1);			/* Restore original reg1 value. */
+		}
+#ifndef final_version
+		if ( !ancient && (inb(ioaddr+1) & 0x01) != (word16 & 0x01))
+			printk("\nWD80?3: Bus width conflict, %d (probe) != %d (reg report).",
+				   word16 ? 16 : 8, (inb(ioaddr+1) & 0x01) ? 16 : 8);
+#endif
+	}
+
+#if defined(WD_SHMEM) && WD_SHMEM > 0x80000
+	/* Allow a compile-time override.	 */
+	dev->mem_start = WD_SHMEM;
+#else
+	if (dev->mem_start == 0) {
+		/* Sanity and old 8003 check */
+		int reg0 = inb(ioaddr);
+		if (reg0 == 0xff || reg0 == 0) {
+			/* Future plan: this could check a few likely locations first. */
+			dev->mem_start = 0xd0000;
+			printk(" assigning address %#lx", dev->mem_start);
+		} else {
+			int high_addr_bits = inb(ioaddr+WD_CMDREG5) & 0x1f;
+			/* Some boards don't have the register 5 -- it returns 0xff. */
+			if (high_addr_bits == 0x1f || word16 == 0)
+				high_addr_bits = 0x01;
+			dev->mem_start = ((reg0&0x3f) << 13) + (high_addr_bits << 19);
+		}
+	}
+#endif
+
+	/* The 8390 isn't at the base address -- the ASIC regs are there! */
+	dev->base_addr = ioaddr+WD_NIC_OFFSET;
+
+	if (dev->irq < 2) {
+		static const int irqmap[] = {9, 3, 5, 7, 10, 11, 15, 4};
+		int reg1 = inb(ioaddr+1);
+		int reg4 = inb(ioaddr+4);
+		if (ancient || reg1 == 0xff) {	/* Ack!! No way to read the IRQ! */
+			short nic_addr = ioaddr+WD_NIC_OFFSET;
+			unsigned long irq_mask;
+
+			/* We have an old-style ethercard that doesn't report its IRQ
+			   line.  Do autoirq to find the IRQ line. Note that this IS NOT
+			   a reliable way to trigger an interrupt. */
+			outb_p(E8390_NODMA + E8390_STOP, nic_addr);
+			outb(0x00, nic_addr+EN0_IMR);	/* Disable all intrs. */
+
+			irq_mask = probe_irq_on();
+			outb_p(0xff, nic_addr + EN0_IMR);	/* Enable all interrupts. */
+			outb_p(0x00, nic_addr + EN0_RCNTLO);
+			outb_p(0x00, nic_addr + EN0_RCNTHI);
+			outb(E8390_RREAD+E8390_START, nic_addr); /* Trigger it... */
+			mdelay(20);
+			dev->irq = probe_irq_off(irq_mask);
+
+			outb_p(0x00, nic_addr+EN0_IMR);	/* Mask all intrs. again. */
+
+			if (ei_debug > 2)
+				printk(" autoirq is %d", dev->irq);
+			if (dev->irq < 2)
+				dev->irq = word16 ? 10 : 5;
+		} else
+			dev->irq = irqmap[((reg4 >> 5) & 0x03) + (reg1 & 0x04)];
+	} else if (dev->irq == 2)		/* Fixup bogosity: IRQ2 is really IRQ9 */
+		dev->irq = 9;
+
+	/* Snarf the interrupt now.  There's no point in waiting since we cannot
+	   share and the board will usually be enabled. */
+	i = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
+	if (i) {
+		printk (" unable to get IRQ %d.\n", dev->irq);
+		return i;
+	}
+
+	/* OK, were are certain this is going to work.  Setup the device. */
+	ei_status.name = model_name;
+	ei_status.word16 = word16;
+	ei_status.tx_start_page = WD_START_PG;
+	ei_status.rx_start_page = WD_START_PG + TX_PAGES;
+
+	/* Don't map in the shared memory until the board is actually opened. */
+
+	/* Some cards (eg WD8003EBT) can be jumpered for more (32k!) memory. */
+	if (dev->mem_end != 0) {
+		ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
+		ei_status.priv = dev->mem_end - dev->mem_start;
+	} else {
+		ei_status.stop_page = word16 ? WD13_STOP_PG : WD03_STOP_PG;
+		dev->mem_end = dev->mem_start + (ei_status.stop_page - WD_START_PG)*256;
+		ei_status.priv = (ei_status.stop_page - WD_START_PG)*256;
+	}
+
+	ei_status.mem = ioremap(dev->mem_start, ei_status.priv);
+	if (!ei_status.mem) {
+		free_irq(dev->irq, dev);
+		return -ENOMEM;
+	}
+
+	printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
+		   model_name, dev->irq, dev->mem_start, dev->mem_end-1);
+
+	ei_status.reset_8390 = wd_reset_8390;
+	ei_status.block_input = wd_block_input;
+	ei_status.block_output = wd_block_output;
+	ei_status.get_8390_hdr = wd_get_8390_hdr;
+
+	dev->netdev_ops = &wd_netdev_ops;
+	NS8390_init(dev, 0);
+
+#if 1
+	/* Enable interrupt generation on softconfig cards -- M.U */
+	/* .. but possibly potentially unsafe - Donald */
+	if (inb(ioaddr+14) & 0x20)
+		outb(inb(ioaddr+4)|0x80, ioaddr+4);
+#endif
+
+	err = register_netdev(dev);
+	if (err) {
+		free_irq(dev->irq, dev);
+		iounmap(ei_status.mem);
+	}
+	return err;
+}
+
+static int
+wd_open(struct net_device *dev)
+{
+  int ioaddr = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
+
+  /* Map in the shared memory. Always set register 0 last to remain
+	 compatible with very old boards. */
+  ei_status.reg0 = ((dev->mem_start>>13) & 0x3f) | WD_MEMENB;
+  ei_status.reg5 = ((dev->mem_start>>19) & 0x1f) | NIC16;
+
+  if (ei_status.word16)
+	  outb(ei_status.reg5, ioaddr+WD_CMDREG5);
+  outb(ei_status.reg0, ioaddr); /* WD_CMDREG */
+
+  return ei_open(dev);
+}
+
+static void
+wd_reset_8390(struct net_device *dev)
+{
+	int wd_cmd_port = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
+
+	outb(WD_RESET, wd_cmd_port);
+	if (ei_debug > 1) printk("resetting the WD80x3 t=%lu...", jiffies);
+	ei_status.txing = 0;
+
+	/* Set up the ASIC registers, just in case something changed them. */
+	outb((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), wd_cmd_port);
+	if (ei_status.word16)
+		outb(NIC16 | ((dev->mem_start>>19) & 0x1f), wd_cmd_port+WD_CMDREG5);
+
+	if (ei_debug > 1) printk("reset done\n");
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void
+wd_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+
+	int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
+	void __iomem *hdr_start = ei_status.mem + ((ring_page - WD_START_PG)<<8);
+
+	/* We'll always get a 4 byte header read followed by a packet read, so
+	   we enable 16 bit mode before the header, and disable after the body. */
+	if (ei_status.word16)
+		outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
+
+#ifdef __BIG_ENDIAN
+	/* Officially this is what we are doing, but the readl() is faster */
+	/* unfortunately it isn't endian aware of the struct               */
+	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	hdr->count = le16_to_cpu(hdr->count);
+#else
+	((unsigned int*)hdr)[0] = readl(hdr_start);
+#endif
+}
+
+/* Block input and output are easy on shared memory ethercards, and trivial
+   on the Western digital card where there is no choice of how to do it.
+   The only complications are that the ring buffer wraps, and need to map
+   switch between 8- and 16-bit modes. */
+
+static void
+wd_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+	int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
+	unsigned long offset = ring_offset - (WD_START_PG<<8);
+	void __iomem *xfer_start = ei_status.mem + offset;
+
+	if (offset + count > ei_status.priv) {
+		/* We must wrap the input move. */
+		int semi_count = ei_status.priv - offset;
+		memcpy_fromio(skb->data, xfer_start, semi_count);
+		count -= semi_count;
+		memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
+	} else {
+		/* Packet is in one chunk -- we can copy + cksum. */
+		memcpy_fromio(skb->data, xfer_start, count);
+	}
+
+	/* Turn off 16 bit access so that reboot works.	 ISA brain-damage */
+	if (ei_status.word16)
+		outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
+}
+
+static void
+wd_block_output(struct net_device *dev, int count, const unsigned char *buf,
+				int start_page)
+{
+	int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
+	void __iomem *shmem = ei_status.mem + ((start_page - WD_START_PG)<<8);
+
+
+	if (ei_status.word16) {
+		/* Turn on and off 16 bit access so that reboot works. */
+		outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
+		memcpy_toio(shmem, buf, count);
+		outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
+	} else
+		memcpy_toio(shmem, buf, count);
+}
+
+
+static int
+wd_close(struct net_device *dev)
+{
+	int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
+
+	if (ei_debug > 1)
+		printk("%s: Shutting down ethercard.\n", dev->name);
+	ei_close(dev);
+
+	/* Change from 16-bit to 8-bit shared memory so reboot works. */
+	if (ei_status.word16)
+		outb(ei_status.reg5, wd_cmdreg + WD_CMDREG5 );
+
+	/* And disable the shared memory. */
+	outb(ei_status.reg0 & ~WD_MEMENB, wd_cmdreg);
+
+	return 0;
+}
+
+
+#ifdef MODULE
+#define MAX_WD_CARDS	4	/* Max number of wd cards per module */
+static struct net_device *dev_wd[MAX_WD_CARDS];
+static int io[MAX_WD_CARDS];
+static int irq[MAX_WD_CARDS];
+static int mem[MAX_WD_CARDS];
+static int mem_end[MAX_WD_CARDS];	/* for non std. mem size */
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(mem, int, NULL, 0);
+module_param_array(mem_end, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s) (ignored for PureData boards)");
+MODULE_PARM_DESC(mem, "memory base address(es)(ignored for PureData boards)");
+MODULE_PARM_DESC(mem_end, "memory end address(es)");
+MODULE_DESCRIPTION("ISA Western Digital wd8003/wd8013 ; SMC Elite, Elite16 ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* This is set up so that only a single autoprobe takes place per call.
+ISA device autoprobes on a running machine are not recommended. */
+
+int __init init_module(void)
+{
+	struct net_device *dev;
+	int this_dev, found = 0;
+
+	for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
+		if (io[this_dev] == 0)  {
+			if (this_dev != 0) break; /* only autoprobe 1st one */
+			printk(KERN_NOTICE "wd.c: Presently autoprobing (not recommended) for a single card.\n");
+		}
+		dev = alloc_ei_netdev();
+		if (!dev)
+			break;
+		dev->irq = irq[this_dev];
+		dev->base_addr = io[this_dev];
+		dev->mem_start = mem[this_dev];
+		dev->mem_end = mem_end[this_dev];
+		if (do_wd_probe(dev) == 0) {
+			dev_wd[found++] = dev;
+			continue;
+		}
+		free_netdev(dev);
+		printk(KERN_WARNING "wd.c: No wd80x3 card found (i/o = 0x%x).\n", io[this_dev]);
+		break;
+	}
+	if (found)
+		return 0;
+	return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+	free_irq(dev->irq, dev);
+	release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT);
+	iounmap(ei_status.mem);
+}
+
+void __exit
+cleanup_module(void)
+{
+	int this_dev;
+
+	for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
+		struct net_device *dev = dev_wd[this_dev];
+		if (dev) {
+			unregister_netdev(dev);
+			cleanup_card(dev);
+			free_netdev(dev);
+		}
+	}
+}
+#endif /* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/8390/zorro8390.c linux-libre-3.2-gnu/drivers/net/ethernet/8390/zorro8390.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/8390/zorro8390.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/8390/zorro8390.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,452 @@
+/*
+ *  Amiga Linux/m68k and Linux/PPC Zorro NS8390 Ethernet Driver
+ *
+ *  (C) Copyright 1998-2000 by some Elitist 680x0 Users(TM)
+ *
+ *  ---------------------------------------------------------------------------
+ *
+ *  This program is based on all the other NE2000 drivers for Linux
+ *
+ *  ---------------------------------------------------------------------------
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of the Linux
+ *  distribution for more details.
+ *
+ *  ---------------------------------------------------------------------------
+ *
+ *  The Ariadne II and X-Surf are Zorro-II boards containing Realtek RTL8019AS
+ *  Ethernet Controllers.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/zorro.h>
+#include <linux/jiffies.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+
+#define EI_SHIFT(x)		(ei_local->reg_offset[x])
+#define ei_inb(port)		in_8(port)
+#define ei_outb(val, port)	out_8(port, val)
+#define ei_inb_p(port)		in_8(port)
+#define ei_outb_p(val, port)	out_8(port, val)
+
+static const char version[] =
+	"8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include "lib8390.c"
+
+#define DRV_NAME	"zorro8390"
+
+#define NE_BASE		(dev->base_addr)
+#define NE_CMD		(0x00 * 2)
+#define NE_DATAPORT	(0x10 * 2)	/* NatSemi-defined port window offset */
+#define NE_RESET	(0x1f * 2)	/* Issue a read to reset,
+					 * a write to clear. */
+#define NE_IO_EXTENT	(0x20 * 2)
+
+#define NE_EN0_ISR	(0x07 * 2)
+#define NE_EN0_DCFG	(0x0e * 2)
+
+#define NE_EN0_RSARLO	(0x08 * 2)
+#define NE_EN0_RSARHI	(0x09 * 2)
+#define NE_EN0_RCNTLO	(0x0a * 2)
+#define NE_EN0_RXCR	(0x0c * 2)
+#define NE_EN0_TXCR	(0x0d * 2)
+#define NE_EN0_RCNTHI	(0x0b * 2)
+#define NE_EN0_IMR	(0x0f * 2)
+
+#define NESM_START_PG	0x40	/* First page of TX buffer */
+#define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
+
+#define WORDSWAP(a)	((((a) >> 8) & 0xff) | ((a) << 8))
+
+static struct card_info {
+	zorro_id id;
+	const char *name;
+	unsigned int offset;
+} cards[] __devinitdata = {
+	{ ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, "Ariadne II", 0x0600 },
+	{ ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 },
+};
+
+/* 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 zorro8390_reset_8390(struct net_device *dev)
+{
+	unsigned long reset_start_time = jiffies;
+
+	if (ei_debug > 1)
+		netdev_dbg(dev, "resetting - t=%ld...\n", jiffies);
+
+	z_writeb(z_readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+	ei_status.txing = 0;
+	ei_status.dmaing = 0;
+
+	/* This check _should_not_ be necessary, omit eventually. */
+	while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RESET) == 0)
+		if (time_after(jiffies, reset_start_time + 2 * HZ / 100)) {
+			netdev_warn(dev, "%s: did not complete\n", __func__);
+			break;
+		}
+	z_writeb(ENISR_RESET, NE_BASE + NE_EN0_ISR);	/* Ack intr */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+ * we don't need to be concerned with ring wrap as the header will be at
+ * the start of a page, so we optimize accordingly.
+ */
+static void zorro8390_get_8390_hdr(struct net_device *dev,
+				   struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	int nic_base = dev->base_addr;
+	int cnt;
+	short *ptrs;
+
+	/* This *shouldn't* happen.
+	 * If it does, it's the last thing you'll see
+	 */
+	if (ei_status.dmaing) {
+		netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
+			   __func__, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+
+	ei_status.dmaing |= 0x01;
+	z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
+	z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+	z_writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
+	z_writeb(0, nic_base + NE_EN0_RCNTHI);
+	z_writeb(0, nic_base + NE_EN0_RSARLO);		/* On page boundary */
+	z_writeb(ring_page, nic_base + NE_EN0_RSARHI);
+	z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+	ptrs = (short *)hdr;
+	for (cnt = 0; cnt < sizeof(struct e8390_pkt_hdr) >> 1; cnt++)
+		*ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
+
+	z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr */
+
+	hdr->count = WORDSWAP(hdr->count);
+
+	ei_status.dmaing &= ~0x01;
+}
+
+/* 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 z_writeb.
+ */
+static void zorro8390_block_input(struct net_device *dev, int count,
+				  struct sk_buff *skb, int ring_offset)
+{
+	int nic_base = dev->base_addr;
+	char *buf = skb->data;
+	short *ptrs;
+	int cnt;
+
+	/* This *shouldn't* happen.
+	 * If it does, it's the last thing you'll see
+	 */
+	if (ei_status.dmaing) {
+		netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
+			   __func__, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+	ei_status.dmaing |= 0x01;
+	z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
+	z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+	z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+	z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
+	z_writeb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
+	z_writeb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
+	z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+	ptrs = (short *)buf;
+	for (cnt = 0; cnt < count >> 1; cnt++)
+		*ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
+	if (count & 0x01)
+		buf[count - 1] = z_readb(NE_BASE + NE_DATAPORT);
+
+	z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr */
+	ei_status.dmaing &= ~0x01;
+}
+
+static void zorro8390_block_output(struct net_device *dev, int count,
+				   const unsigned char *buf,
+				   const int start_page)
+{
+	int nic_base = NE_BASE;
+	unsigned long dma_start;
+	short *ptrs;
+	int cnt;
+
+	/* 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 (count & 0x01)
+		count++;
+
+	/* This *shouldn't* happen.
+	 * If it does, it's the last thing you'll see
+	 */
+	if (ei_status.dmaing) {
+		netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
+			   __func__, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+	ei_status.dmaing |= 0x01;
+	/* We should already be in page 0, but to be safe... */
+	z_writeb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+	z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+
+	/* Now the normal output. */
+	z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+	z_writeb(count >> 8,   nic_base + NE_EN0_RCNTHI);
+	z_writeb(0x00, nic_base + NE_EN0_RSARLO);
+	z_writeb(start_page, nic_base + NE_EN0_RSARHI);
+
+	z_writeb(E8390_RWRITE + E8390_START, nic_base + NE_CMD);
+	ptrs = (short *)buf;
+	for (cnt = 0; cnt < count >> 1; cnt++)
+		z_writew(*ptrs++, NE_BASE + NE_DATAPORT);
+
+	dma_start = jiffies;
+
+	while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
+		if (time_after(jiffies, dma_start + 2 * HZ / 100)) {
+					/* 20ms */
+			netdev_err(dev, "timeout waiting for Tx RDC\n");
+			zorro8390_reset_8390(dev);
+			__NS8390_init(dev, 1);
+			break;
+		}
+
+	z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr */
+	ei_status.dmaing &= ~0x01;
+}
+
+static int zorro8390_open(struct net_device *dev)
+{
+	__ei_open(dev);
+	return 0;
+}
+
+static int zorro8390_close(struct net_device *dev)
+{
+	if (ei_debug > 1)
+		netdev_dbg(dev, "Shutting down ethercard\n");
+	__ei_close(dev);
+	return 0;
+}
+
+static void __devexit zorro8390_remove_one(struct zorro_dev *z)
+{
+	struct net_device *dev = zorro_get_drvdata(z);
+
+	unregister_netdev(dev);
+	free_irq(IRQ_AMIGA_PORTS, dev);
+	release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT * 2);
+	free_netdev(dev);
+}
+
+static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = {
+	{ ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, },
+	{ ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl);
+
+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_rx_mode	= __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,
+#endif
+};
+
+static int __devinit zorro8390_init(struct net_device *dev,
+				    unsigned long board, const char *name,
+				    unsigned long ioaddr)
+{
+	int i;
+	int err;
+	unsigned char SA_prom[32];
+	int start_page, stop_page;
+	static u32 zorro8390_offsets[16] = {
+		0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+		0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
+	};
+
+	/* Reset card. Who knows what dain-bramaged state it was left in. */
+	{
+		unsigned long reset_start_time = jiffies;
+
+		z_writeb(z_readb(ioaddr + NE_RESET), ioaddr + NE_RESET);
+
+		while ((z_readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
+			if (time_after(jiffies,
+				       reset_start_time + 2 * HZ / 100)) {
+				netdev_warn(dev, "not found (no reset ack)\n");
+				return -ENODEV;
+			}
+
+		z_writeb(0xff, ioaddr + NE_EN0_ISR);	/* Ack all intr. */
+	}
+
+	/* Read the 16 bytes of station address PROM.
+	 * We must first initialize registers,
+	 * similar to NS8390_init(eifdev, 0).
+	 * We can't reliably read the SAPROM address without this.
+	 * (I learned the hard way!).
+	 */
+	{
+		static const struct {
+			u32 value;
+			u32 offset;
+		} program_seq[] = {
+			{E8390_NODMA + E8390_PAGE0 + E8390_STOP, NE_CMD},
+						/* Select page 0 */
+			{0x48,	NE_EN0_DCFG},	/* 0x48: Set byte-wide access */
+			{0x00,	NE_EN0_RCNTLO},	/* Clear the count regs */
+			{0x00,	NE_EN0_RCNTHI},
+			{0x00,	NE_EN0_IMR},	/* Mask completion irq */
+			{0xFF,	NE_EN0_ISR},
+			{E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */
+			{E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode */
+			{32,	NE_EN0_RCNTLO},
+			{0x00,	NE_EN0_RCNTHI},
+			{0x00,	NE_EN0_RSARLO},	/* DMA starting at 0x0000 */
+			{0x00,	NE_EN0_RSARHI},
+			{E8390_RREAD + E8390_START, NE_CMD},
+		};
+		for (i = 0; i < ARRAY_SIZE(program_seq); i++)
+			z_writeb(program_seq[i].value,
+				 ioaddr + program_seq[i].offset);
+	}
+	for (i = 0; i < 16; i++) {
+		SA_prom[i] = z_readb(ioaddr + NE_DATAPORT);
+		(void)z_readb(ioaddr + NE_DATAPORT);
+	}
+
+	/* We must set the 8390 for word mode. */
+	z_writeb(0x49, ioaddr + NE_EN0_DCFG);
+	start_page = NESM_START_PG;
+	stop_page = NESM_STOP_PG;
+
+	dev->base_addr = ioaddr;
+	dev->irq = IRQ_AMIGA_PORTS;
+
+	/* Install the Interrupt handler */
+	i = request_irq(IRQ_AMIGA_PORTS, __ei_interrupt,
+			IRQF_SHARED, DRV_NAME, dev);
+	if (i)
+		return i;
+
+	for (i = 0; i < ETHER_ADDR_LEN; i++)
+		dev->dev_addr[i] = SA_prom[i];
+
+	pr_debug("Found ethernet address: %pM\n", dev->dev_addr);
+
+	ei_status.name = name;
+	ei_status.tx_start_page = start_page;
+	ei_status.stop_page = stop_page;
+	ei_status.word16 = 1;
+
+	ei_status.rx_start_page = start_page + TX_PAGES;
+
+	ei_status.reset_8390 = zorro8390_reset_8390;
+	ei_status.block_input = zorro8390_block_input;
+	ei_status.block_output = zorro8390_block_output;
+	ei_status.get_8390_hdr = zorro8390_get_8390_hdr;
+	ei_status.reg_offset = zorro8390_offsets;
+
+	dev->netdev_ops = &zorro8390_netdev_ops;
+	__NS8390_init(dev, 0);
+	err = register_netdev(dev);
+	if (err) {
+		free_irq(IRQ_AMIGA_PORTS, dev);
+		return err;
+	}
+
+	netdev_info(dev, "%s at 0x%08lx, Ethernet Address %pM\n",
+		    name, board, dev->dev_addr);
+
+	return 0;
+}
+
+static int __devinit zorro8390_init_one(struct zorro_dev *z,
+					const struct zorro_device_id *ent)
+{
+	struct net_device *dev;
+	unsigned long board, ioaddr;
+	int err, i;
+
+	for (i = ARRAY_SIZE(cards) - 1; i >= 0; i--)
+		if (z->id == cards[i].id)
+			break;
+	if (i < 0)
+		return -ENODEV;
+
+	board = z->resource.start;
+	ioaddr = board + cards[i].offset;
+	dev = ____alloc_ei_netdev(0);
+	if (!dev)
+		return -ENOMEM;
+	if (!request_mem_region(ioaddr, NE_IO_EXTENT * 2, DRV_NAME)) {
+		free_netdev(dev);
+		return -EBUSY;
+	}
+	err = zorro8390_init(dev, board, cards[i].name, ZTWO_VADDR(ioaddr));
+	if (err) {
+		release_mem_region(ioaddr, NE_IO_EXTENT * 2);
+		free_netdev(dev);
+		return err;
+	}
+	zorro_set_drvdata(z, dev);
+	return 0;
+}
+
+static struct zorro_driver zorro8390_driver = {
+	.name		= "zorro8390",
+	.id_table	= zorro8390_zorro_tbl,
+	.probe		= zorro8390_init_one,
+	.remove		= __devexit_p(zorro8390_remove_one),
+};
+
+static int __init zorro8390_init_module(void)
+{
+	return zorro_register_driver(&zorro8390_driver);
+}
+
+static void __exit zorro8390_cleanup_module(void)
+{
+	zorro_unregister_driver(&zorro8390_driver);
+}
+
+module_init(zorro8390_init_module);
+module_exit(zorro8390_cleanup_module);
+
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/adaptec/Kconfig linux-libre-3.2-gnu/drivers/net/ethernet/adaptec/Kconfig
--- linux-libre-3.1-gnu/drivers/net/ethernet/adaptec/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/adaptec/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,36 @@
+#
+# Adaptec network device configuration
+#
+
+config NET_VENDOR_ADAPTEC
+	bool "Adaptec devices"
+	default y
+	depends on PCI
+	---help---
+	  If you have a network (Ethernet) card belonging to this class, say Y
+	  and read the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  Note that the answer to this question doesn't directly affect the
+	  kernel: saying N will just cause the configurator to skip all
+	  the questions about Adaptec cards. If you say Y, you will be asked for
+	  your specific card in the following questions.
+
+if NET_VENDOR_ADAPTEC
+
+config ADAPTEC_STARFIRE
+	tristate "Adaptec Starfire/DuraLAN support"
+	depends on PCI
+	select CRC32
+	select NET_CORE
+	select MII
+	---help---
+	  Say Y here if you have an Adaptec Starfire (or DuraLAN) PCI network
+	  adapter. The DuraLAN chip is used on the 64 bit PCI boards from
+	  Adaptec e.g. the ANA-6922A. The older 32 bit boards use the tulip
+	  driver.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called starfire.  This is recommended.
+
+endif # NET_VENDOR_ADAPTEC
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/adaptec/Makefile linux-libre-3.2-gnu/drivers/net/ethernet/adaptec/Makefile
--- linux-libre-3.1-gnu/drivers/net/ethernet/adaptec/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/adaptec/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+#
+# Makefile for the Adaptec network device drivers.
+#
+
+obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/adaptec/starfire.c linux-libre-3.2-gnu/drivers/net/ethernet/adaptec/starfire.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/adaptec/starfire.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/adaptec/starfire.c	2012-03-19 21:44:34.000000000 -0400
@@ -0,0 +1,2090 @@
+/* starfire.c: Linux device driver for the Adaptec Starfire network adapter. */
+/*
+	Written 1998-2000 by Donald Becker.
+
+	Current maintainer is Ion Badulescu <ionut ta badula tod org>. Please
+	send all bug reports to me, and not to Donald Becker, as this code
+	has been heavily modified from Donald's original version.
+
+	This software may be used and distributed according to the terms of
+	the GNU General Public License (GPL), incorporated herein by reference.
+	Drivers based on or derived from this code fall under the GPL and must
+	retain the authorship, copyright and license notice.  This file is not
+	a complete program and may only be used when the entire operating
+	system is licensed under the GPL.
+
+	The information below comes from Donald Becker's original driver:
+
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+	Support and updates available at
+	http://www.scyld.com/network/starfire.html
+	[link no longer provides useful info -jgarzik]
+
+*/
+
+#define DRV_NAME	"starfire"
+#define DRV_VERSION	"2.1"
+#define DRV_RELDATE	"July  6, 2008"
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/crc32.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/if_vlan.h>
+#include <linux/mm.h>
+#include <linux/firmware.h>
+#include <asm/processor.h>		/* Processor type for cache alignment. */
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/*
+ * The current frame processor firmware fails to checksum a fragment
+ * of length 1. If and when this is fixed, the #define below can be removed.
+ */
+#define HAS_BROKEN_FIRMWARE
+
+/*
+ * If using the broken firmware, data must be padded to the next 32-bit boundary.
+ */
+#ifdef HAS_BROKEN_FIRMWARE
+#define PADDING_MASK 3
+#endif
+
+/*
+ * Define this if using the driver with the zero-copy patch
+ */
+#define ZEROCOPY
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+#define VLAN_SUPPORT
+#endif
+
+/* The user-configurable values.
+   These may be modified when a driver module is loaded.*/
+
+/* Used for tuning interrupt latency vs. overhead. */
+static int intr_latency;
+static int small_frames;
+
+static int debug = 1;			/* 1 normal messages, 0 quiet .. 7 verbose. */
+static int max_interrupt_work = 20;
+static int mtu;
+/* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
+   The Starfire has a 512 element hash table based on the Ethernet CRC. */
+static const int multicast_filter_limit = 512;
+/* Whether to do TCP/UDP checksums in hardware */
+static int enable_hw_cksum = 1;
+
+#define PKT_BUF_SZ	1536		/* Size of each temporary Rx buffer.*/
+/*
+ * Set the copy breakpoint for the copy-only-tiny-frames scheme.
+ * Setting to > 1518 effectively disables this feature.
+ *
+ * NOTE:
+ * The ia64 doesn't allow for unaligned loads even of integers being
+ * misaligned on a 2 byte boundary. Thus always force copying of
+ * packets as the starfire doesn't allow for misaligned DMAs ;-(
+ * 23/10/2000 - Jes
+ *
+ * The Alpha and the Sparc don't like unaligned loads, either. On Sparc64,
+ * at least, having unaligned frames leads to a rather serious performance
+ * penalty. -Ion
+ */
+#if defined(__ia64__) || defined(__alpha__) || defined(__sparc__)
+static int rx_copybreak = PKT_BUF_SZ;
+#else
+static int rx_copybreak /* = 0 */;
+#endif
+
+/* PCI DMA burst size -- on sparc64 we want to force it to 64 bytes, on the others the default of 128 is fine. */
+#ifdef __sparc__
+#define DMA_BURST_SIZE 64
+#else
+#define DMA_BURST_SIZE 128
+#endif
+
+/* Used to pass the media type, etc.
+   Both 'options[]' and 'full_duplex[]' exist for driver interoperability.
+   The media type is usually passed in 'options[]'.
+   These variables are deprecated, use ethtool instead. -Ion
+*/
+#define MAX_UNITS 8		/* More are supported, limit only on options */
+static int options[MAX_UNITS] = {0, };
+static int full_duplex[MAX_UNITS] = {0, };
+
+/* Operational parameters that are set at compile time. */
+
+/* The "native" ring sizes are either 256 or 2048.
+   However in some modes a descriptor may be marked to wrap the ring earlier.
+*/
+#define RX_RING_SIZE	256
+#define TX_RING_SIZE	32
+/* The completion queues are fixed at 1024 entries i.e. 4K or 8KB. */
+#define DONE_Q_SIZE	1024
+/* All queues must be aligned on a 256-byte boundary */
+#define QUEUE_ALIGN	256
+
+#if RX_RING_SIZE > 256
+#define RX_Q_ENTRIES Rx2048QEntries
+#else
+#define RX_Q_ENTRIES Rx256QEntries
+#endif
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT	(2 * HZ)
+
+#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
+#define cpu_to_dma(x) cpu_to_le64(x)
+#define dma_to_cpu(x) le64_to_cpu(x)
+#define RX_DESC_Q_ADDR_SIZE RxDescQAddr64bit
+#define TX_DESC_Q_ADDR_SIZE TxDescQAddr64bit
+#define RX_COMPL_Q_ADDR_SIZE RxComplQAddr64bit
+#define TX_COMPL_Q_ADDR_SIZE TxComplQAddr64bit
+#define RX_DESC_ADDR_SIZE RxDescAddr64bit
+#else  /* 32-bit dma_addr_t */
+#define netdrv_addr_t __le32
+#define cpu_to_dma(x) cpu_to_le32(x)
+#define dma_to_cpu(x) le32_to_cpu(x)
+#define RX_DESC_Q_ADDR_SIZE RxDescQAddr32bit
+#define TX_DESC_Q_ADDR_SIZE TxDescQAddr32bit
+#define RX_COMPL_Q_ADDR_SIZE RxComplQAddr32bit
+#define TX_COMPL_Q_ADDR_SIZE TxComplQAddr32bit
+#define RX_DESC_ADDR_SIZE RxDescAddr32bit
+#endif
+
+#define skb_first_frag_len(skb)	skb_headlen(skb)
+#define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1)
+
+/* Firmware names */
+#define FIRMWARE_RX	"/*(DEBLOBBED)*/"
+#define FIRMWARE_TX	"/*(DEBLOBBED)*/"
+
+/* These identify the driver base version and may not be removed. */
+static const char version[] __devinitconst =
+KERN_INFO "starfire.c:v1.03 7/26/2000  Written by Donald Becker <becker@scyld.com>\n"
+" (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
+
+MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
+MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+/*(DEBLOBBED)*/
+
+module_param(max_interrupt_work, int, 0);
+module_param(mtu, int, 0);
+module_param(debug, int, 0);
+module_param(rx_copybreak, int, 0);
+module_param(intr_latency, int, 0);
+module_param(small_frames, int, 0);
+module_param_array(options, int, NULL, 0);
+module_param_array(full_duplex, int, NULL, 0);
+module_param(enable_hw_cksum, int, 0);
+MODULE_PARM_DESC(max_interrupt_work, "Maximum events handled per interrupt");
+MODULE_PARM_DESC(mtu, "MTU (all boards)");
+MODULE_PARM_DESC(debug, "Debug level (0-6)");
+MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
+MODULE_PARM_DESC(intr_latency, "Maximum interrupt latency, in microseconds");
+MODULE_PARM_DESC(small_frames, "Maximum size of receive frames that bypass interrupt latency (0,64,128,256,512)");
+MODULE_PARM_DESC(options, "Deprecated: Bits 0-3: media type, bit 17: full duplex");
+MODULE_PARM_DESC(full_duplex, "Deprecated: Forced full-duplex setting (0/1)");
+MODULE_PARM_DESC(enable_hw_cksum, "Enable/disable hardware cksum support (0/1)");
+
+/*
+				Theory of Operation
+
+I. Board Compatibility
+
+This driver is for the Adaptec 6915 "Starfire" 64 bit PCI Ethernet adapter.
+
+II. Board-specific settings
+
+III. Driver operation
+
+IIIa. Ring buffers
+
+The Starfire hardware uses multiple fixed-size descriptor queues/rings.  The
+ring sizes are set fixed by the hardware, but may optionally be wrapped
+earlier by the END bit in the descriptor.
+This driver uses that hardware queue size for the Rx ring, where a large
+number of entries has no ill effect beyond increases the potential backlog.
+The Tx ring is wrapped with the END bit, since a large hardware Tx queue
+disables the queue layer priority ordering and we have no mechanism to
+utilize the hardware two-level priority queue.  When modifying the
+RX/TX_RING_SIZE pay close attention to page sizes and the ring-empty warning
+levels.
+
+IIIb/c. Transmit/Receive Structure
+
+See the Adaptec manual for the many possible structures, and options for
+each structure.  There are far too many to document all of them here.
+
+For transmit this driver uses type 0/1 transmit descriptors (depending
+on the 32/64 bitness of the architecture), and relies on automatic
+minimum-length padding.  It does not use the completion queue
+consumer index, but instead checks for non-zero status entries.
+
+For receive this driver uses type 2/3 receive descriptors.  The driver
+allocates full frame size skbuffs for the Rx ring buffers, so all frames
+should fit in a single descriptor.  The driver does not use the completion
+queue consumer index, but instead checks for non-zero status entries.
+
+When an incoming frame is less than RX_COPYBREAK bytes long, a fresh skbuff
+is allocated and the frame is copied to the new skbuff.  When the incoming
+frame is larger, the skbuff is passed directly up the protocol stack.
+Buffers consumed this way are replaced by newly allocated skbuffs in a later
+phase of receive.
+
+A notable aspect of operation is that unaligned buffers are not permitted by
+the Starfire hardware.  Thus the IP header at offset 14 in an ethernet frame
+isn't longword aligned, which may cause problems on some machine
+e.g. Alphas and IA64. For these architectures, the driver is forced to copy
+the frame into a new skbuff unconditionally. Copied frames are put into the
+skbuff at an offset of "+2", thus 16-byte aligning the IP header.
+
+IIId. Synchronization
+
+The driver runs as two independent, single-threaded flows of control.  One
+is the send-packet routine, which enforces single-threaded use by the
+dev->tbusy flag.  The other thread is the interrupt handler, which is single
+threaded by the hardware and interrupt handling software.
+
+The send packet thread has partial control over the Tx ring and the netif_queue
+status. If the number of free Tx slots in the ring falls below a certain number
+(currently hardcoded to 4), it signals the upper layer to stop the queue.
+
+The interrupt handler has exclusive control over the Rx ring and records stats
+from the Tx ring.  After reaping the stats, it marks the Tx queue entry as
+empty by incrementing the dirty_tx mark. Iff the netif_queue is stopped and the
+number of free Tx slow is above the threshold, it signals the upper layer to
+restart the queue.
+
+IV. Notes
+
+IVb. References
+
+The Adaptec Starfire manuals, available only from Adaptec.
+http://www.scyld.com/expert/100mbps.html
+http://www.scyld.com/expert/NWay.html
+
+IVc. Errata
+
+- StopOnPerr is broken, don't enable
+- Hardware ethernet padding exposes random data, perform software padding
+  instead (unverified -- works correctly for all the hardware I have)
+
+*/
+
+
+
+enum chip_capability_flags {CanHaveMII=1, };
+
+enum chipset {
+	CH_6915 = 0,
+};
+
+static DEFINE_PCI_DEVICE_TABLE(starfire_pci_tbl) = {
+	{ PCI_VDEVICE(ADAPTEC, 0x6915), CH_6915 },
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, starfire_pci_tbl);
+
+/* A chip capabilities table, matching the CH_xxx entries in xxx_pci_tbl[] above. */
+static const struct chip_info {
+	const char *name;
+	int drv_flags;
+} netdrv_tbl[] __devinitdata = {
+	{ "Adaptec Starfire 6915", CanHaveMII },
+};
+
+
+/* Offsets to the device registers.
+   Unlike software-only systems, device drivers interact with complex hardware.
+   It's not useful to define symbolic names for every register bit in the
+   device.  The name can only partially document the semantics and make
+   the driver longer and more difficult to read.
+   In general, only the important configuration values or bits changed
+   multiple times should be defined symbolically.
+*/
+enum register_offsets {
+	PCIDeviceConfig=0x50040, GenCtrl=0x50070, IntrTimerCtrl=0x50074,
+	IntrClear=0x50080, IntrStatus=0x50084, IntrEnable=0x50088,
+	MIICtrl=0x52000, TxStationAddr=0x50120, EEPROMCtrl=0x51000,
+	GPIOCtrl=0x5008C, TxDescCtrl=0x50090,
+	TxRingPtr=0x50098, HiPriTxRingPtr=0x50094, /* Low and High priority. */
+	TxRingHiAddr=0x5009C,		/* 64 bit address extension. */
+	TxProducerIdx=0x500A0, TxConsumerIdx=0x500A4,
+	TxThreshold=0x500B0,
+	CompletionHiAddr=0x500B4, TxCompletionAddr=0x500B8,
+	RxCompletionAddr=0x500BC, RxCompletionQ2Addr=0x500C0,
+	CompletionQConsumerIdx=0x500C4, RxDMACtrl=0x500D0,
+	RxDescQCtrl=0x500D4, RxDescQHiAddr=0x500DC, RxDescQAddr=0x500E0,
+	RxDescQIdx=0x500E8, RxDMAStatus=0x500F0, RxFilterMode=0x500F4,
+	TxMode=0x55000, VlanType=0x55064,
+	PerfFilterTable=0x56000, HashTable=0x56100,
+	TxGfpMem=0x58000, RxGfpMem=0x5a000,
+};
+
+/*
+ * Bits in the interrupt status/mask registers.
+ * Warning: setting Intr[Ab]NormalSummary in the IntrEnable register
+ * enables all the interrupt sources that are or'ed into those status bits.
+ */
+enum intr_status_bits {
+	IntrLinkChange=0xf0000000, IntrStatsMax=0x08000000,
+	IntrAbnormalSummary=0x02000000, IntrGeneralTimer=0x01000000,
+	IntrSoftware=0x800000, IntrRxComplQ1Low=0x400000,
+	IntrTxComplQLow=0x200000, IntrPCI=0x100000,
+	IntrDMAErr=0x080000, IntrTxDataLow=0x040000,
+	IntrRxComplQ2Low=0x020000, IntrRxDescQ1Low=0x010000,
+	IntrNormalSummary=0x8000, IntrTxDone=0x4000,
+	IntrTxDMADone=0x2000, IntrTxEmpty=0x1000,
+	IntrEarlyRxQ2=0x0800, IntrEarlyRxQ1=0x0400,
+	IntrRxQ2Done=0x0200, IntrRxQ1Done=0x0100,
+	IntrRxGFPDead=0x80, IntrRxDescQ2Low=0x40,
+	IntrNoTxCsum=0x20, IntrTxBadID=0x10,
+	IntrHiPriTxBadID=0x08, IntrRxGfp=0x04,
+	IntrTxGfp=0x02, IntrPCIPad=0x01,
+	/* not quite bits */
+	IntrRxDone=IntrRxQ2Done | IntrRxQ1Done,
+	IntrRxEmpty=IntrRxDescQ1Low | IntrRxDescQ2Low,
+	IntrNormalMask=0xff00, IntrAbnormalMask=0x3ff00fe,
+};
+
+/* Bits in the RxFilterMode register. */
+enum rx_mode_bits {
+	AcceptBroadcast=0x04, AcceptAllMulticast=0x02, AcceptAll=0x01,
+	AcceptMulticast=0x10, PerfectFilter=0x40, HashFilter=0x30,
+	PerfectFilterVlan=0x80, MinVLANPrio=0xE000, VlanMode=0x0200,
+	WakeupOnGFP=0x0800,
+};
+
+/* Bits in the TxMode register */
+enum tx_mode_bits {
+	MiiSoftReset=0x8000, MIILoopback=0x4000,
+	TxFlowEnable=0x0800, RxFlowEnable=0x0400,
+	PadEnable=0x04, FullDuplex=0x02, HugeFrame=0x01,
+};
+
+/* Bits in the TxDescCtrl register. */
+enum tx_ctrl_bits {
+	TxDescSpaceUnlim=0x00, TxDescSpace32=0x10, TxDescSpace64=0x20,
+	TxDescSpace128=0x30, TxDescSpace256=0x40,
+	TxDescType0=0x00, TxDescType1=0x01, TxDescType2=0x02,
+	TxDescType3=0x03, TxDescType4=0x04,
+	TxNoDMACompletion=0x08,
+	TxDescQAddr64bit=0x80, TxDescQAddr32bit=0,
+	TxHiPriFIFOThreshShift=24, TxPadLenShift=16,
+	TxDMABurstSizeShift=8,
+};
+
+/* Bits in the RxDescQCtrl register. */
+enum rx_ctrl_bits {
+	RxBufferLenShift=16, RxMinDescrThreshShift=0,
+	RxPrefetchMode=0x8000, RxVariableQ=0x2000,
+	Rx2048QEntries=0x4000, Rx256QEntries=0,
+	RxDescAddr64bit=0x1000, RxDescAddr32bit=0,
+	RxDescQAddr64bit=0x0100, RxDescQAddr32bit=0,
+	RxDescSpace4=0x000, RxDescSpace8=0x100,
+	RxDescSpace16=0x200, RxDescSpace32=0x300,
+	RxDescSpace64=0x400, RxDescSpace128=0x500,
+	RxConsumerWrEn=0x80,
+};
+
+/* Bits in the RxDMACtrl register. */
+enum rx_dmactrl_bits {
+	RxReportBadFrames=0x80000000, RxDMAShortFrames=0x40000000,
+	RxDMABadFrames=0x20000000, RxDMACrcErrorFrames=0x10000000,
+	RxDMAControlFrame=0x08000000, RxDMAPauseFrame=0x04000000,
+	RxChecksumIgnore=0, RxChecksumRejectTCPUDP=0x02000000,
+	RxChecksumRejectTCPOnly=0x01000000,
+	RxCompletionQ2Enable=0x800000,
+	RxDMAQ2Disable=0, RxDMAQ2FPOnly=0x100000,
+	RxDMAQ2SmallPkt=0x200000, RxDMAQ2HighPrio=0x300000,
+	RxDMAQ2NonIP=0x400000,
+	RxUseBackupQueue=0x080000, RxDMACRC=0x040000,
+	RxEarlyIntThreshShift=12, RxHighPrioThreshShift=8,
+	RxBurstSizeShift=0,
+};
+
+/* Bits in the RxCompletionAddr register */
+enum rx_compl_bits {
+	RxComplQAddr64bit=0x80, RxComplQAddr32bit=0,
+	RxComplProducerWrEn=0x40,
+	RxComplType0=0x00, RxComplType1=0x10,
+	RxComplType2=0x20, RxComplType3=0x30,
+	RxComplThreshShift=0,
+};
+
+/* Bits in the TxCompletionAddr register */
+enum tx_compl_bits {
+	TxComplQAddr64bit=0x80, TxComplQAddr32bit=0,
+	TxComplProducerWrEn=0x40,
+	TxComplIntrStatus=0x20,
+	CommonQueueMode=0x10,
+	TxComplThreshShift=0,
+};
+
+/* Bits in the GenCtrl register */
+enum gen_ctrl_bits {
+	RxEnable=0x05, TxEnable=0x0a,
+	RxGFPEnable=0x10, TxGFPEnable=0x20,
+};
+
+/* Bits in the IntrTimerCtrl register */
+enum intr_ctrl_bits {
+	Timer10X=0x800, EnableIntrMasking=0x60, SmallFrameBypass=0x100,
+	SmallFrame64=0, SmallFrame128=0x200, SmallFrame256=0x400, SmallFrame512=0x600,
+	IntrLatencyMask=0x1f,
+};
+
+/* The Rx and Tx buffer descriptors. */
+struct starfire_rx_desc {
+	netdrv_addr_t rxaddr;
+};
+enum rx_desc_bits {
+	RxDescValid=1, RxDescEndRing=2,
+};
+
+/* Completion queue entry. */
+struct short_rx_done_desc {
+	__le32 status;			/* Low 16 bits is length. */
+};
+struct basic_rx_done_desc {
+	__le32 status;			/* Low 16 bits is length. */
+	__le16 vlanid;
+	__le16 status2;
+};
+struct csum_rx_done_desc {
+	__le32 status;			/* Low 16 bits is length. */
+	__le16 csum;			/* Partial checksum */
+	__le16 status2;
+};
+struct full_rx_done_desc {
+	__le32 status;			/* Low 16 bits is length. */
+	__le16 status3;
+	__le16 status2;
+	__le16 vlanid;
+	__le16 csum;			/* partial checksum */
+	__le32 timestamp;
+};
+/* XXX: this is ugly and I'm not sure it's worth the trouble -Ion */
+#ifdef VLAN_SUPPORT
+typedef struct full_rx_done_desc rx_done_desc;
+#define RxComplType RxComplType3
+#else  /* not VLAN_SUPPORT */
+typedef struct csum_rx_done_desc rx_done_desc;
+#define RxComplType RxComplType2
+#endif /* not VLAN_SUPPORT */
+
+enum rx_done_bits {
+	RxOK=0x20000000, RxFIFOErr=0x10000000, RxBufQ2=0x08000000,
+};
+
+/* Type 1 Tx descriptor. */
+struct starfire_tx_desc_1 {
+	__le32 status;			/* Upper bits are status, lower 16 length. */
+	__le32 addr;
+};
+
+/* Type 2 Tx descriptor. */
+struct starfire_tx_desc_2 {
+	__le32 status;			/* Upper bits are status, lower 16 length. */
+	__le32 reserved;
+	__le64 addr;
+};
+
+#ifdef ADDR_64BITS
+typedef struct starfire_tx_desc_2 starfire_tx_desc;
+#define TX_DESC_TYPE TxDescType2
+#else  /* not ADDR_64BITS */
+typedef struct starfire_tx_desc_1 starfire_tx_desc;
+#define TX_DESC_TYPE TxDescType1
+#endif /* not ADDR_64BITS */
+#define TX_DESC_SPACING TxDescSpaceUnlim
+
+enum tx_desc_bits {
+	TxDescID=0xB0000000,
+	TxCRCEn=0x01000000, TxDescIntr=0x08000000,
+	TxRingWrap=0x04000000, TxCalTCP=0x02000000,
+};
+struct tx_done_desc {
+	__le32 status;			/* timestamp, index. */
+#if 0
+	__le32 intrstatus;		/* interrupt status */
+#endif
+};
+
+struct rx_ring_info {
+	struct sk_buff *skb;
+	dma_addr_t mapping;
+};
+struct tx_ring_info {
+	struct sk_buff *skb;
+	dma_addr_t mapping;
+	unsigned int used_slots;
+};
+
+#define PHY_CNT		2
+struct netdev_private {
+	/* Descriptor rings first for alignment. */
+	struct starfire_rx_desc *rx_ring;
+	starfire_tx_desc *tx_ring;
+	dma_addr_t rx_ring_dma;
+	dma_addr_t tx_ring_dma;
+	/* The addresses of rx/tx-in-place skbuffs. */
+	struct rx_ring_info rx_info[RX_RING_SIZE];
+	struct tx_ring_info tx_info[TX_RING_SIZE];
+	/* Pointers to completion queues (full pages). */
+	rx_done_desc *rx_done_q;
+	dma_addr_t rx_done_q_dma;
+	unsigned int rx_done;
+	struct tx_done_desc *tx_done_q;
+	dma_addr_t tx_done_q_dma;
+	unsigned int tx_done;
+	struct napi_struct napi;
+	struct net_device *dev;
+	struct pci_dev *pci_dev;
+#ifdef VLAN_SUPPORT
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
+#endif
+	void *queue_mem;
+	dma_addr_t queue_mem_dma;
+	size_t queue_mem_size;
+
+	/* Frequently used values: keep some adjacent for cache effect. */
+	spinlock_t lock;
+	unsigned int cur_rx, dirty_rx;	/* Producer/consumer ring indices */
+	unsigned int cur_tx, dirty_tx, reap_tx;
+	unsigned int rx_buf_sz;		/* Based on MTU+slack. */
+	/* These values keep track of the transceiver/media in use. */
+	int speed100;			/* Set if speed == 100MBit. */
+	u32 tx_mode;
+	u32 intr_timer_ctrl;
+	u8 tx_threshold;
+	/* MII transceiver section. */
+	struct mii_if_info mii_if;		/* MII lib hooks/info */
+	int phy_cnt;			/* MII device addresses. */
+	unsigned char phys[PHY_CNT];	/* MII device addresses. */
+	void __iomem *base;
+};
+
+
+static int	mdio_read(struct net_device *dev, int phy_id, int location);
+static void	mdio_write(struct net_device *dev, int phy_id, int location, int value);
+static int	netdev_open(struct net_device *dev);
+static void	check_duplex(struct net_device *dev);
+static void	tx_timeout(struct net_device *dev);
+static void	init_ring(struct net_device *dev);
+static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev);
+static irqreturn_t intr_handler(int irq, void *dev_instance);
+static void	netdev_error(struct net_device *dev, int intr_status);
+static int	__netdev_rx(struct net_device *dev, int *quota);
+static int	netdev_poll(struct napi_struct *napi, int budget);
+static void	refill_rx_ring(struct net_device *dev);
+static void	netdev_error(struct net_device *dev, int intr_status);
+static void	set_rx_mode(struct net_device *dev);
+static struct net_device_stats *get_stats(struct net_device *dev);
+static int	netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int	netdev_close(struct net_device *dev);
+static void	netdev_media_change(struct net_device *dev);
+static const struct ethtool_ops ethtool_ops;
+
+
+#ifdef VLAN_SUPPORT
+static void netdev_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
+{
+	struct netdev_private *np = netdev_priv(dev);
+
+	spin_lock(&np->lock);
+	if (debug > 1)
+		printk("%s: Adding vlanid %d to vlan filter\n", dev->name, vid);
+	set_bit(vid, np->active_vlans);
+	set_rx_mode(dev);
+	spin_unlock(&np->lock);
+}
+
+static void netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+{
+	struct netdev_private *np = netdev_priv(dev);
+
+	spin_lock(&np->lock);
+	if (debug > 1)
+		printk("%s: removing vlanid %d from vlan filter\n", dev->name, vid);
+	clear_bit(vid, np->active_vlans);
+	set_rx_mode(dev);
+	spin_unlock(&np->lock);
+}
+#endif /* VLAN_SUPPORT */
+
+
+static const struct net_device_ops netdev_ops = {
+	.ndo_open		= netdev_open,
+	.ndo_stop		= netdev_close,
+	.ndo_start_xmit		= start_tx,
+	.ndo_tx_timeout		= tx_timeout,
+	.ndo_get_stats		= get_stats,
+	.ndo_set_rx_mode	= set_rx_mode,
+	.ndo_do_ioctl		= netdev_ioctl,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+#ifdef VLAN_SUPPORT
+	.ndo_vlan_rx_add_vid	= netdev_vlan_rx_add_vid,
+	.ndo_vlan_rx_kill_vid	= netdev_vlan_rx_kill_vid,
+#endif
+};
+
+static int __devinit starfire_init_one(struct pci_dev *pdev,
+				       const struct pci_device_id *ent)
+{
+	struct netdev_private *np;
+	int i, irq, option, chip_idx = ent->driver_data;
+	struct net_device *dev;
+	static int card_idx = -1;
+	long ioaddr;
+	void __iomem *base;
+	int drv_flags, io_size;
+	int boguscnt;
+
+/* when built into the kernel, we only print version if device is found */
+#ifndef MODULE
+	static int printed_version;
+	if (!printed_version++)
+		printk(version);
+#endif
+
+	card_idx++;
+
+	if (pci_enable_device (pdev))
+		return -EIO;
+
+	ioaddr = pci_resource_start(pdev, 0);
+	io_size = pci_resource_len(pdev, 0);
+	if (!ioaddr || ((pci_resource_flags(pdev, 0) & IORESOURCE_MEM) == 0)) {
+		printk(KERN_ERR DRV_NAME " %d: no PCI MEM resources, aborting\n", card_idx);
+		return -ENODEV;
+	}
+
+	dev = alloc_etherdev(sizeof(*np));
+	if (!dev) {
+		printk(KERN_ERR DRV_NAME " %d: cannot alloc etherdev, aborting\n", card_idx);
+		return -ENOMEM;
+	}
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	irq = pdev->irq;
+
+	if (pci_request_regions (pdev, DRV_NAME)) {
+		printk(KERN_ERR DRV_NAME " %d: cannot reserve PCI resources, aborting\n", card_idx);
+		goto err_out_free_netdev;
+	}
+
+	base = ioremap(ioaddr, io_size);
+	if (!base) {
+		printk(KERN_ERR DRV_NAME " %d: cannot remap %#x @ %#lx, aborting\n",
+			card_idx, io_size, ioaddr);
+		goto err_out_free_res;
+	}
+
+	pci_set_master(pdev);
+
+	/* enable MWI -- it vastly improves Rx performance on sparc64 */
+	pci_try_set_mwi(pdev);
+
+#ifdef ZEROCOPY
+	/* Starfire can do TCP/UDP checksumming */
+	if (enable_hw_cksum)
+		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+#endif /* ZEROCOPY */
+
+#ifdef VLAN_SUPPORT
+	dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
+#endif /* VLAN_RX_KILL_VID */
+#ifdef ADDR_64BITS
+	dev->features |= NETIF_F_HIGHDMA;
+#endif /* ADDR_64BITS */
+
+	/* Serial EEPROM reads are hidden by the hardware. */
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = readb(base + EEPROMCtrl + 20 - i);
+
+#if ! defined(final_version) /* Dump the EEPROM contents during development. */
+	if (debug > 4)
+		for (i = 0; i < 0x20; i++)
+			printk("%2.2x%s",
+			       (unsigned int)readb(base + EEPROMCtrl + i),
+			       i % 16 != 15 ? " " : "\n");
+#endif
+
+	/* Issue soft reset */
+	writel(MiiSoftReset, base + TxMode);
+	udelay(1000);
+	writel(0, base + TxMode);
+
+	/* Reset the chip to erase previous misconfiguration. */
+	writel(1, base + PCIDeviceConfig);
+	boguscnt = 1000;
+	while (--boguscnt > 0) {
+		udelay(10);
+		if ((readl(base + PCIDeviceConfig) & 1) == 0)
+			break;
+	}
+	if (boguscnt == 0)
+		printk("%s: chipset reset never completed!\n", dev->name);
+	/* wait a little longer */
+	udelay(1000);
+
+	dev->base_addr = (unsigned long)base;
+	dev->irq = irq;
+
+	np = netdev_priv(dev);
+	np->dev = dev;
+	np->base = base;
+	spin_lock_init(&np->lock);
+	pci_set_drvdata(pdev, dev);
+
+	np->pci_dev = pdev;
+
+	np->mii_if.dev = dev;
+	np->mii_if.mdio_read = mdio_read;
+	np->mii_if.mdio_write = mdio_write;
+	np->mii_if.phy_id_mask = 0x1f;
+	np->mii_if.reg_num_mask = 0x1f;
+
+	drv_flags = netdrv_tbl[chip_idx].drv_flags;
+
+	option = card_idx < MAX_UNITS ? options[card_idx] : 0;
+	if (dev->mem_start)
+		option = dev->mem_start;
+
+	/* The lower four bits are the media type. */
+	if (option & 0x200)
+		np->mii_if.full_duplex = 1;
+
+	if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
+		np->mii_if.full_duplex = 1;
+
+	if (np->mii_if.full_duplex)
+		np->mii_if.force_media = 1;
+	else
+		np->mii_if.force_media = 0;
+	np->speed100 = 1;
+
+	/* timer resolution is 128 * 0.8us */
+	np->intr_timer_ctrl = (((intr_latency * 10) / 1024) & IntrLatencyMask) |
+		Timer10X | EnableIntrMasking;
+
+	if (small_frames > 0) {
+		np->intr_timer_ctrl |= SmallFrameBypass;
+		switch (small_frames) {
+		case 1 ... 64:
+			np->intr_timer_ctrl |= SmallFrame64;
+			break;
+		case 65 ... 128:
+			np->intr_timer_ctrl |= SmallFrame128;
+			break;
+		case 129 ... 256:
+			np->intr_timer_ctrl |= SmallFrame256;
+			break;
+		default:
+			np->intr_timer_ctrl |= SmallFrame512;
+			if (small_frames > 512)
+				printk("Adjusting small_frames down to 512\n");
+			break;
+		}
+	}
+
+	dev->netdev_ops = &netdev_ops;
+	dev->watchdog_timeo = TX_TIMEOUT;
+	SET_ETHTOOL_OPS(dev, &ethtool_ops);
+
+	netif_napi_add(dev, &np->napi, netdev_poll, max_interrupt_work);
+
+	if (mtu)
+		dev->mtu = mtu;
+
+	if (register_netdev(dev))
+		goto err_out_cleardev;
+
+	printk(KERN_INFO "%s: %s at %p, %pM, IRQ %d.\n",
+	       dev->name, netdrv_tbl[chip_idx].name, base,
+	       dev->dev_addr, irq);
+
+	if (drv_flags & CanHaveMII) {
+		int phy, phy_idx = 0;
+		int mii_status;
+		for (phy = 0; phy < 32 && phy_idx < PHY_CNT; phy++) {
+			mdio_write(dev, phy, MII_BMCR, BMCR_RESET);
+			mdelay(100);
+			boguscnt = 1000;
+			while (--boguscnt > 0)
+				if ((mdio_read(dev, phy, MII_BMCR) & BMCR_RESET) == 0)
+					break;
+			if (boguscnt == 0) {
+				printk("%s: PHY#%d reset never completed!\n", dev->name, phy);
+				continue;
+			}
+			mii_status = mdio_read(dev, phy, MII_BMSR);
+			if (mii_status != 0) {
+				np->phys[phy_idx++] = phy;
+				np->mii_if.advertising = mdio_read(dev, phy, MII_ADVERTISE);
+				printk(KERN_INFO "%s: MII PHY found at address %d, status "
+					   "%#4.4x advertising %#4.4x.\n",
+					   dev->name, phy, mii_status, np->mii_if.advertising);
+				/* there can be only one PHY on-board */
+				break;
+			}
+		}
+		np->phy_cnt = phy_idx;
+		if (np->phy_cnt > 0)
+			np->mii_if.phy_id = np->phys[0];
+		else
+			memset(&np->mii_if, 0, sizeof(np->mii_if));
+	}
+
+	printk(KERN_INFO "%s: scatter-gather and hardware TCP cksumming %s.\n",
+	       dev->name, enable_hw_cksum ? "enabled" : "disabled");
+	return 0;
+
+err_out_cleardev:
+	pci_set_drvdata(pdev, NULL);
+	iounmap(base);
+err_out_free_res:
+	pci_release_regions (pdev);
+err_out_free_netdev:
+	free_netdev(dev);
+	return -ENODEV;
+}
+
+
+/* Read the MII Management Data I/O (MDIO) interfaces. */
+static int mdio_read(struct net_device *dev, int phy_id, int location)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *mdio_addr = np->base + MIICtrl + (phy_id<<7) + (location<<2);
+	int result, boguscnt=1000;
+	/* ??? Should we add a busy-wait here? */
+	do {
+		result = readl(mdio_addr);
+	} while ((result & 0xC0000000) != 0x80000000 && --boguscnt > 0);
+	if (boguscnt == 0)
+		return 0;
+	if ((result & 0xffff) == 0xffff)
+		return 0;
+	return result & 0xffff;
+}
+
+
+static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *mdio_addr = np->base + MIICtrl + (phy_id<<7) + (location<<2);
+	writel(value, mdio_addr);
+	/* The busy-wait will occur before a read. */
+}
+
+
+static int netdev_open(struct net_device *dev)
+{
+	const struct firmware *fw_rx, *fw_tx;
+	const __be32 *fw_rx_data, *fw_tx_data;
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->base;
+	int i, retval;
+	size_t tx_size, rx_size;
+	size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size;
+
+	/* Do we ever need to reset the chip??? */
+
+	retval = request_irq(dev->irq, intr_handler, IRQF_SHARED, dev->name, dev);
+	if (retval)
+		return retval;
+
+	/* Disable the Rx and Tx, and reset the chip. */
+	writel(0, ioaddr + GenCtrl);
+	writel(1, ioaddr + PCIDeviceConfig);
+	if (debug > 1)
+		printk(KERN_DEBUG "%s: netdev_open() irq %d.\n",
+		       dev->name, dev->irq);
+
+	/* Allocate the various queues. */
+	if (!np->queue_mem) {
+		tx_done_q_size = ((sizeof(struct tx_done_desc) * DONE_Q_SIZE + QUEUE_ALIGN - 1) / QUEUE_ALIGN) * QUEUE_ALIGN;
+		rx_done_q_size = ((sizeof(rx_done_desc) * DONE_Q_SIZE + QUEUE_ALIGN - 1) / QUEUE_ALIGN) * QUEUE_ALIGN;
+		tx_ring_size = ((sizeof(starfire_tx_desc) * TX_RING_SIZE + QUEUE_ALIGN - 1) / QUEUE_ALIGN) * QUEUE_ALIGN;
+		rx_ring_size = sizeof(struct starfire_rx_desc) * RX_RING_SIZE;
+		np->queue_mem_size = tx_done_q_size + rx_done_q_size + tx_ring_size + rx_ring_size;
+		np->queue_mem = pci_alloc_consistent(np->pci_dev, np->queue_mem_size, &np->queue_mem_dma);
+		if (np->queue_mem == NULL) {
+			free_irq(dev->irq, dev);
+			return -ENOMEM;
+		}
+
+		np->tx_done_q     = np->queue_mem;
+		np->tx_done_q_dma = np->queue_mem_dma;
+		np->rx_done_q     = (void *) np->tx_done_q + tx_done_q_size;
+		np->rx_done_q_dma = np->tx_done_q_dma + tx_done_q_size;
+		np->tx_ring       = (void *) np->rx_done_q + rx_done_q_size;
+		np->tx_ring_dma   = np->rx_done_q_dma + rx_done_q_size;
+		np->rx_ring       = (void *) np->tx_ring + tx_ring_size;
+		np->rx_ring_dma   = np->tx_ring_dma + tx_ring_size;
+	}
+
+	/* Start with no carrier, it gets adjusted later */
+	netif_carrier_off(dev);
+	init_ring(dev);
+	/* Set the size of the Rx buffers. */
+	writel((np->rx_buf_sz << RxBufferLenShift) |
+	       (0 << RxMinDescrThreshShift) |
+	       RxPrefetchMode | RxVariableQ |
+	       RX_Q_ENTRIES |
+	       RX_DESC_Q_ADDR_SIZE | RX_DESC_ADDR_SIZE |
+	       RxDescSpace4,
+	       ioaddr + RxDescQCtrl);
+
+	/* Set up the Rx DMA controller. */
+	writel(RxChecksumIgnore |
+	       (0 << RxEarlyIntThreshShift) |
+	       (6 << RxHighPrioThreshShift) |
+	       ((DMA_BURST_SIZE / 32) << RxBurstSizeShift),
+	       ioaddr + RxDMACtrl);
+
+	/* Set Tx descriptor */
+	writel((2 << TxHiPriFIFOThreshShift) |
+	       (0 << TxPadLenShift) |
+	       ((DMA_BURST_SIZE / 32) << TxDMABurstSizeShift) |
+	       TX_DESC_Q_ADDR_SIZE |
+	       TX_DESC_SPACING | TX_DESC_TYPE,
+	       ioaddr + TxDescCtrl);
+
+	writel( (np->queue_mem_dma >> 16) >> 16, ioaddr + RxDescQHiAddr);
+	writel( (np->queue_mem_dma >> 16) >> 16, ioaddr + TxRingHiAddr);
+	writel( (np->queue_mem_dma >> 16) >> 16, ioaddr + CompletionHiAddr);
+	writel(np->rx_ring_dma, ioaddr + RxDescQAddr);
+	writel(np->tx_ring_dma, ioaddr + TxRingPtr);
+
+	writel(np->tx_done_q_dma, ioaddr + TxCompletionAddr);
+	writel(np->rx_done_q_dma |
+	       RxComplType |
+	       (0 << RxComplThreshShift),
+	       ioaddr + RxCompletionAddr);
+
+	if (debug > 1)
+		printk(KERN_DEBUG "%s: Filling in the station address.\n", dev->name);
+
+	/* Fill both the Tx SA register and the Rx perfect filter. */
+	for (i = 0; i < 6; i++)
+		writeb(dev->dev_addr[i], ioaddr + TxStationAddr + 5 - i);
+	/* The first entry is special because it bypasses the VLAN filter.
+	   Don't use it. */
+	writew(0, ioaddr + PerfFilterTable);
+	writew(0, ioaddr + PerfFilterTable + 4);
+	writew(0, ioaddr + PerfFilterTable + 8);
+	for (i = 1; i < 16; i++) {
+		__be16 *eaddrs = (__be16 *)dev->dev_addr;
+		void __iomem *setup_frm = ioaddr + PerfFilterTable + i * 16;
+		writew(be16_to_cpu(eaddrs[2]), setup_frm); setup_frm += 4;
+		writew(be16_to_cpu(eaddrs[1]), setup_frm); setup_frm += 4;
+		writew(be16_to_cpu(eaddrs[0]), setup_frm); setup_frm += 8;
+	}
+
+	/* Initialize other registers. */
+	/* Configure the PCI bus bursts and FIFO thresholds. */
+	np->tx_mode = TxFlowEnable|RxFlowEnable|PadEnable;	/* modified when link is up. */
+	writel(MiiSoftReset | np->tx_mode, ioaddr + TxMode);
+	udelay(1000);
+	writel(np->tx_mode, ioaddr + TxMode);
+	np->tx_threshold = 4;
+	writel(np->tx_threshold, ioaddr + TxThreshold);
+
+	writel(np->intr_timer_ctrl, ioaddr + IntrTimerCtrl);
+
+	napi_enable(&np->napi);
+
+	netif_start_queue(dev);
+
+	if (debug > 1)
+		printk(KERN_DEBUG "%s: Setting the Rx and Tx modes.\n", dev->name);
+	set_rx_mode(dev);
+
+	np->mii_if.advertising = mdio_read(dev, np->phys[0], MII_ADVERTISE);
+	check_duplex(dev);
+
+	/* Enable GPIO interrupts on link change */
+	writel(0x0f00ff00, ioaddr + GPIOCtrl);
+
+	/* Set the interrupt mask */
+	writel(IntrRxDone | IntrRxEmpty | IntrDMAErr |
+	       IntrTxDMADone | IntrStatsMax | IntrLinkChange |
+	       IntrRxGFPDead | IntrNoTxCsum | IntrTxBadID,
+	       ioaddr + IntrEnable);
+	/* Enable PCI interrupts. */
+	writel(0x00800000 | readl(ioaddr + PCIDeviceConfig),
+	       ioaddr + PCIDeviceConfig);
+
+#ifdef VLAN_SUPPORT
+	/* Set VLAN type to 802.1q */
+	writel(ETH_P_8021Q, ioaddr + VlanType);
+#endif /* VLAN_SUPPORT */
+
+	retval = reject_firmware(&fw_rx, FIRMWARE_RX, &np->pci_dev->dev);
+	if (retval) {
+		printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n",
+		       FIRMWARE_RX);
+		goto out_init;
+	}
+	if (fw_rx->size % 4) {
+		printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n",
+		       fw_rx->size, FIRMWARE_RX);
+		retval = -EINVAL;
+		goto out_rx;
+	}
+	retval = reject_firmware(&fw_tx, FIRMWARE_TX, &np->pci_dev->dev);
+	if (retval) {
+		printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n",
+		       FIRMWARE_TX);
+		goto out_rx;
+	}
+	if (fw_tx->size % 4) {
+		printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n",
+		       fw_tx->size, FIRMWARE_TX);
+		retval = -EINVAL;
+		goto out_tx;
+	}
+	fw_rx_data = (const __be32 *)&fw_rx->data[0];
+	fw_tx_data = (const __be32 *)&fw_tx->data[0];
+	rx_size = fw_rx->size / 4;
+	tx_size = fw_tx->size / 4;
+
+	/* Load Rx/Tx firmware into the frame processors */
+	for (i = 0; i < rx_size; i++)
+		writel(be32_to_cpup(&fw_rx_data[i]), ioaddr + RxGfpMem + i * 4);
+	for (i = 0; i < tx_size; i++)
+		writel(be32_to_cpup(&fw_tx_data[i]), ioaddr + TxGfpMem + i * 4);
+	if (enable_hw_cksum)
+		/* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
+		writel(TxEnable|TxGFPEnable|RxEnable|RxGFPEnable, ioaddr + GenCtrl);
+	else
+		/* Enable the Rx and Tx units only. */
+		writel(TxEnable|RxEnable, ioaddr + GenCtrl);
+
+	if (debug > 1)
+		printk(KERN_DEBUG "%s: Done netdev_open().\n",
+		       dev->name);
+
+out_tx:
+	release_firmware(fw_tx);
+out_rx:
+	release_firmware(fw_rx);
+out_init:
+	if (retval)
+		netdev_close(dev);
+	return retval;
+}
+
+
+static void check_duplex(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	u16 reg0;
+	int silly_count = 1000;
+
+	mdio_write(dev, np->phys[0], MII_ADVERTISE, np->mii_if.advertising);
+	mdio_write(dev, np->phys[0], MII_BMCR, BMCR_RESET);
+	udelay(500);
+	while (--silly_count && mdio_read(dev, np->phys[0], MII_BMCR) & BMCR_RESET)
+		/* do nothing */;
+	if (!silly_count) {
+		printk("%s: MII reset failed!\n", dev->name);
+		return;
+	}
+
+	reg0 = mdio_read(dev, np->phys[0], MII_BMCR);
+
+	if (!np->mii_if.force_media) {
+		reg0 |= BMCR_ANENABLE | BMCR_ANRESTART;
+	} else {
+		reg0 &= ~(BMCR_ANENABLE | BMCR_ANRESTART);
+		if (np->speed100)
+			reg0 |= BMCR_SPEED100;
+		if (np->mii_if.full_duplex)
+			reg0 |= BMCR_FULLDPLX;
+		printk(KERN_DEBUG "%s: Link forced to %sMbit %s-duplex\n",
+		       dev->name,
+		       np->speed100 ? "100" : "10",
+		       np->mii_if.full_duplex ? "full" : "half");
+	}
+	mdio_write(dev, np->phys[0], MII_BMCR, reg0);
+}
+
+
+static void tx_timeout(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->base;
+	int old_debug;
+
+	printk(KERN_WARNING "%s: Transmit timed out, status %#8.8x, "
+	       "resetting...\n", dev->name, (int) readl(ioaddr + IntrStatus));
+
+	/* Perhaps we should reinitialize the hardware here. */
+
+	/*
+	 * Stop and restart the interface.
+	 * Cheat and increase the debug level temporarily.
+	 */
+	old_debug = debug;
+	debug = 2;
+	netdev_close(dev);
+	netdev_open(dev);
+	debug = old_debug;
+
+	/* Trigger an immediate transmit demand. */
+
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	dev->stats.tx_errors++;
+	netif_wake_queue(dev);
+}
+
+
+/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+static void init_ring(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	int i;
+
+	np->cur_rx = np->cur_tx = np->reap_tx = 0;
+	np->dirty_rx = np->dirty_tx = np->rx_done = np->tx_done = 0;
+
+	np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
+
+	/* Fill in the Rx buffers.  Handle allocation failure gracefully. */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz);
+		np->rx_info[i].skb = skb;
+		if (skb == NULL)
+			break;
+		np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+		skb->dev = dev;			/* Mark as being used by this device. */
+		/* Grrr, we cannot offset to correctly align the IP header. */
+		np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid);
+	}
+	writew(i - 1, np->base + RxDescQIdx);
+	np->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
+
+	/* Clear the remainder of the Rx buffer ring. */
+	for (  ; i < RX_RING_SIZE; i++) {
+		np->rx_ring[i].rxaddr = 0;
+		np->rx_info[i].skb = NULL;
+		np->rx_info[i].mapping = 0;
+	}
+	/* Mark the last entry as wrapping the ring. */
+	np->rx_ring[RX_RING_SIZE - 1].rxaddr |= cpu_to_dma(RxDescEndRing);
+
+	/* Clear the completion rings. */
+	for (i = 0; i < DONE_Q_SIZE; i++) {
+		np->rx_done_q[i].status = 0;
+		np->tx_done_q[i].status = 0;
+	}
+
+	for (i = 0; i < TX_RING_SIZE; i++)
+		memset(&np->tx_info[i], 0, sizeof(np->tx_info[i]));
+}
+
+
+static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	unsigned int entry;
+	u32 status;
+	int i;
+
+	/*
+	 * be cautious here, wrapping the queue has weird semantics
+	 * and we may not have enough slots even when it seems we do.
+	 */
+	if ((np->cur_tx - np->dirty_tx) + skb_num_frags(skb) * 2 > TX_RING_SIZE) {
+		netif_stop_queue(dev);
+		return NETDEV_TX_BUSY;
+	}
+
+#if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE)
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		if (skb_padto(skb, (skb->len + PADDING_MASK) & ~PADDING_MASK))
+			return NETDEV_TX_OK;
+	}
+#endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
+
+	entry = np->cur_tx % TX_RING_SIZE;
+	for (i = 0; i < skb_num_frags(skb); i++) {
+		int wrap_ring = 0;
+		status = TxDescID;
+
+		if (i == 0) {
+			np->tx_info[entry].skb = skb;
+			status |= TxCRCEn;
+			if (entry >= TX_RING_SIZE - skb_num_frags(skb)) {
+				status |= TxRingWrap;
+				wrap_ring = 1;
+			}
+			if (np->reap_tx) {
+				status |= TxDescIntr;
+				np->reap_tx = 0;
+			}
+			if (skb->ip_summed == CHECKSUM_PARTIAL) {
+				status |= TxCalTCP;
+				dev->stats.tx_compressed++;
+			}
+			status |= skb_first_frag_len(skb) | (skb_num_frags(skb) << 16);
+
+			np->tx_info[entry].mapping =
+				pci_map_single(np->pci_dev, skb->data, skb_first_frag_len(skb), PCI_DMA_TODEVICE);
+		} else {
+			const skb_frag_t *this_frag = &skb_shinfo(skb)->frags[i - 1];
+			status |= skb_frag_size(this_frag);
+			np->tx_info[entry].mapping =
+				pci_map_single(np->pci_dev,
+					       skb_frag_address(this_frag),
+					       skb_frag_size(this_frag),
+					       PCI_DMA_TODEVICE);
+		}
+
+		np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping);
+		np->tx_ring[entry].status = cpu_to_le32(status);
+		if (debug > 3)
+			printk(KERN_DEBUG "%s: Tx #%d/#%d slot %d status %#8.8x.\n",
+			       dev->name, np->cur_tx, np->dirty_tx,
+			       entry, status);
+		if (wrap_ring) {
+			np->tx_info[entry].used_slots = TX_RING_SIZE - entry;
+			np->cur_tx += np->tx_info[entry].used_slots;
+			entry = 0;
+		} else {
+			np->tx_info[entry].used_slots = 1;
+			np->cur_tx += np->tx_info[entry].used_slots;
+			entry++;
+		}
+		/* scavenge the tx descriptors twice per TX_RING_SIZE */
+		if (np->cur_tx % (TX_RING_SIZE / 2) == 0)
+			np->reap_tx = 1;
+	}
+
+	/* Non-x86: explicitly flush descriptor cache lines here. */
+	/* Ensure all descriptors are written back before the transmit is
+	   initiated. - Jes */
+	wmb();
+
+	/* Update the producer index. */
+	writel(entry * (sizeof(starfire_tx_desc) / 8), np->base + TxProducerIdx);
+
+	/* 4 is arbitrary, but should be ok */
+	if ((np->cur_tx - np->dirty_tx) + 4 > TX_RING_SIZE)
+		netif_stop_queue(dev);
+
+	return NETDEV_TX_OK;
+}
+
+
+/* The interrupt handler does all of the Rx thread work and cleans up
+   after the Tx thread. */
+static irqreturn_t intr_handler(int irq, void *dev_instance)
+{
+	struct net_device *dev = dev_instance;
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->base;
+	int boguscnt = max_interrupt_work;
+	int consumer;
+	int tx_status;
+	int handled = 0;
+
+	do {
+		u32 intr_status = readl(ioaddr + IntrClear);
+
+		if (debug > 4)
+			printk(KERN_DEBUG "%s: Interrupt status %#8.8x.\n",
+			       dev->name, intr_status);
+
+		if (intr_status == 0 || intr_status == (u32) -1)
+			break;
+
+		handled = 1;
+
+		if (intr_status & (IntrRxDone | IntrRxEmpty)) {
+			u32 enable;
+
+			if (likely(napi_schedule_prep(&np->napi))) {
+				__napi_schedule(&np->napi);
+				enable = readl(ioaddr + IntrEnable);
+				enable &= ~(IntrRxDone | IntrRxEmpty);
+				writel(enable, ioaddr + IntrEnable);
+				/* flush PCI posting buffers */
+				readl(ioaddr + IntrEnable);
+			} else {
+				/* Paranoia check */
+				enable = readl(ioaddr + IntrEnable);
+				if (enable & (IntrRxDone | IntrRxEmpty)) {
+					printk(KERN_INFO
+					       "%s: interrupt while in poll!\n",
+					       dev->name);
+					enable &= ~(IntrRxDone | IntrRxEmpty);
+					writel(enable, ioaddr + IntrEnable);
+				}
+			}
+		}
+
+		/* Scavenge the skbuff list based on the Tx-done queue.
+		   There are redundant checks here that may be cleaned up
+		   after the driver has proven to be reliable. */
+		consumer = readl(ioaddr + TxConsumerIdx);
+		if (debug > 3)
+			printk(KERN_DEBUG "%s: Tx Consumer index is %d.\n",
+			       dev->name, consumer);
+
+		while ((tx_status = le32_to_cpu(np->tx_done_q[np->tx_done].status)) != 0) {
+			if (debug > 3)
+				printk(KERN_DEBUG "%s: Tx completion #%d entry %d is %#8.8x.\n",
+				       dev->name, np->dirty_tx, np->tx_done, tx_status);
+			if ((tx_status & 0xe0000000) == 0xa0000000) {
+				dev->stats.tx_packets++;
+			} else if ((tx_status & 0xe0000000) == 0x80000000) {
+				u16 entry = (tx_status & 0x7fff) / sizeof(starfire_tx_desc);
+				struct sk_buff *skb = np->tx_info[entry].skb;
+				np->tx_info[entry].skb = NULL;
+				pci_unmap_single(np->pci_dev,
+						 np->tx_info[entry].mapping,
+						 skb_first_frag_len(skb),
+						 PCI_DMA_TODEVICE);
+				np->tx_info[entry].mapping = 0;
+				np->dirty_tx += np->tx_info[entry].used_slots;
+				entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE;
+				{
+					int i;
+					for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+						pci_unmap_single(np->pci_dev,
+								 np->tx_info[entry].mapping,
+								 skb_frag_size(&skb_shinfo(skb)->frags[i]),
+								 PCI_DMA_TODEVICE);
+						np->dirty_tx++;
+						entry++;
+					}
+				}
+
+				dev_kfree_skb_irq(skb);
+			}
+			np->tx_done_q[np->tx_done].status = 0;
+			np->tx_done = (np->tx_done + 1) % DONE_Q_SIZE;
+		}
+		writew(np->tx_done, ioaddr + CompletionQConsumerIdx + 2);
+
+		if (netif_queue_stopped(dev) &&
+		    (np->cur_tx - np->dirty_tx + 4 < TX_RING_SIZE)) {
+			/* The ring is no longer full, wake the queue. */
+			netif_wake_queue(dev);
+		}
+
+		/* Stats overflow */
+		if (intr_status & IntrStatsMax)
+			get_stats(dev);
+
+		/* Media change interrupt. */
+		if (intr_status & IntrLinkChange)
+			netdev_media_change(dev);
+
+		/* Abnormal error summary/uncommon events handlers. */
+		if (intr_status & IntrAbnormalSummary)
+			netdev_error(dev, intr_status);
+
+		if (--boguscnt < 0) {
+			if (debug > 1)
+				printk(KERN_WARNING "%s: Too much work at interrupt, "
+				       "status=%#8.8x.\n",
+				       dev->name, intr_status);
+			break;
+		}
+	} while (1);
+
+	if (debug > 4)
+		printk(KERN_DEBUG "%s: exiting interrupt, status=%#8.8x.\n",
+		       dev->name, (int) readl(ioaddr + IntrStatus));
+	return IRQ_RETVAL(handled);
+}
+
+
+/*
+ * This routine is logically part of the interrupt/poll handler, but separated
+ * for clarity and better register allocation.
+ */
+static int __netdev_rx(struct net_device *dev, int *quota)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	u32 desc_status;
+	int retcode = 0;
+
+	/* If EOP is set on the next entry, it's a new packet. Send it up. */
+	while ((desc_status = le32_to_cpu(np->rx_done_q[np->rx_done].status)) != 0) {
+		struct sk_buff *skb;
+		u16 pkt_len;
+		int entry;
+		rx_done_desc *desc = &np->rx_done_q[np->rx_done];
+
+		if (debug > 4)
+			printk(KERN_DEBUG "  netdev_rx() status of %d was %#8.8x.\n", np->rx_done, desc_status);
+		if (!(desc_status & RxOK)) {
+			/* There was an error. */
+			if (debug > 2)
+				printk(KERN_DEBUG "  netdev_rx() Rx error was %#8.8x.\n", desc_status);
+			dev->stats.rx_errors++;
+			if (desc_status & RxFIFOErr)
+				dev->stats.rx_fifo_errors++;
+			goto next_rx;
+		}
+
+		if (*quota <= 0) {	/* out of rx quota */
+			retcode = 1;
+			goto out;
+		}
+		(*quota)--;
+
+		pkt_len = desc_status;	/* Implicitly Truncate */
+		entry = (desc_status >> 16) & 0x7ff;
+
+		if (debug > 4)
+			printk(KERN_DEBUG "  netdev_rx() normal Rx pkt length %d, quota %d.\n", pkt_len, *quota);
+		/* Check if the packet is long enough to accept without copying
+		   to a minimally-sized skbuff. */
+		if (pkt_len < rx_copybreak &&
+		    (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+			skb_reserve(skb, 2);	/* 16 byte align the IP header */
+			pci_dma_sync_single_for_cpu(np->pci_dev,
+						    np->rx_info[entry].mapping,
+						    pkt_len, PCI_DMA_FROMDEVICE);
+			skb_copy_to_linear_data(skb, np->rx_info[entry].skb->data, pkt_len);
+			pci_dma_sync_single_for_device(np->pci_dev,
+						       np->rx_info[entry].mapping,
+						       pkt_len, PCI_DMA_FROMDEVICE);
+			skb_put(skb, pkt_len);
+		} else {
+			pci_unmap_single(np->pci_dev, np->rx_info[entry].mapping, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+			skb = np->rx_info[entry].skb;
+			skb_put(skb, pkt_len);
+			np->rx_info[entry].skb = NULL;
+			np->rx_info[entry].mapping = 0;
+		}
+#ifndef final_version			/* Remove after testing. */
+		/* You will want this info for the initial debug. */
+		if (debug > 5) {
+			printk(KERN_DEBUG "  Rx data %pM %pM %2.2x%2.2x.\n",
+			       skb->data, skb->data + 6,
+			       skb->data[12], skb->data[13]);
+		}
+#endif
+
+		skb->protocol = eth_type_trans(skb, dev);
+#ifdef VLAN_SUPPORT
+		if (debug > 4)
+			printk(KERN_DEBUG "  netdev_rx() status2 of %d was %#4.4x.\n", np->rx_done, le16_to_cpu(desc->status2));
+#endif
+		if (le16_to_cpu(desc->status2) & 0x0100) {
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+			dev->stats.rx_compressed++;
+		}
+		/*
+		 * This feature doesn't seem to be working, at least
+		 * with the two firmware versions I have. If the GFP sees
+		 * an IP fragment, it either ignores it completely, or reports
+		 * "bad checksum" on it.
+		 *
+		 * Maybe I missed something -- corrections are welcome.
+		 * Until then, the printk stays. :-) -Ion
+		 */
+		else if (le16_to_cpu(desc->status2) & 0x0040) {
+			skb->ip_summed = CHECKSUM_COMPLETE;
+			skb->csum = le16_to_cpu(desc->csum);
+			printk(KERN_DEBUG "%s: checksum_hw, status2 = %#x\n", dev->name, le16_to_cpu(desc->status2));
+		}
+#ifdef VLAN_SUPPORT
+		if (le16_to_cpu(desc->status2) & 0x0200) {
+			u16 vlid = le16_to_cpu(desc->vlanid);
+
+			if (debug > 4) {
+				printk(KERN_DEBUG "  netdev_rx() vlanid = %d\n",
+				       vlid);
+			}
+			__vlan_hwaccel_put_tag(skb, vlid);
+		}
+#endif /* VLAN_SUPPORT */
+		netif_receive_skb(skb);
+		dev->stats.rx_packets++;
+
+	next_rx:
+		np->cur_rx++;
+		desc->status = 0;
+		np->rx_done = (np->rx_done + 1) % DONE_Q_SIZE;
+	}
+
+	if (*quota == 0) {	/* out of rx quota */
+		retcode = 1;
+		goto out;
+	}
+	writew(np->rx_done, np->base + CompletionQConsumerIdx);
+
+ out:
+	refill_rx_ring(dev);
+	if (debug > 5)
+		printk(KERN_DEBUG "  exiting netdev_rx(): %d, status of %d was %#8.8x.\n",
+		       retcode, np->rx_done, desc_status);
+	return retcode;
+}
+
+static int netdev_poll(struct napi_struct *napi, int budget)
+{
+	struct netdev_private *np = container_of(napi, struct netdev_private, napi);
+	struct net_device *dev = np->dev;
+	u32 intr_status;
+	void __iomem *ioaddr = np->base;
+	int quota = budget;
+
+	do {
+		writel(IntrRxDone | IntrRxEmpty, ioaddr + IntrClear);
+
+		if (__netdev_rx(dev, &quota))
+			goto out;
+
+		intr_status = readl(ioaddr + IntrStatus);
+	} while (intr_status & (IntrRxDone | IntrRxEmpty));
+
+	napi_complete(napi);
+	intr_status = readl(ioaddr + IntrEnable);
+	intr_status |= IntrRxDone | IntrRxEmpty;
+	writel(intr_status, ioaddr + IntrEnable);
+
+ out:
+	if (debug > 5)
+		printk(KERN_DEBUG "  exiting netdev_poll(): %d.\n",
+		       budget - quota);
+
+	/* Restart Rx engine if stopped. */
+	return budget - quota;
+}
+
+static void refill_rx_ring(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	struct sk_buff *skb;
+	int entry = -1;
+
+	/* Refill the Rx ring buffers. */
+	for (; np->cur_rx - np->dirty_rx > 0; np->dirty_rx++) {
+		entry = np->dirty_rx % RX_RING_SIZE;
+		if (np->rx_info[entry].skb == NULL) {
+			skb = dev_alloc_skb(np->rx_buf_sz);
+			np->rx_info[entry].skb = skb;
+			if (skb == NULL)
+				break;	/* Better luck next round. */
+			np->rx_info[entry].mapping =
+				pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+			skb->dev = dev;	/* Mark as being used by this device. */
+			np->rx_ring[entry].rxaddr =
+				cpu_to_dma(np->rx_info[entry].mapping | RxDescValid);
+		}
+		if (entry == RX_RING_SIZE - 1)
+			np->rx_ring[entry].rxaddr |= cpu_to_dma(RxDescEndRing);
+	}
+	if (entry >= 0)
+		writew(entry, np->base + RxDescQIdx);
+}
+
+
+static void netdev_media_change(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->base;
+	u16 reg0, reg1, reg4, reg5;
+	u32 new_tx_mode;
+	u32 new_intr_timer_ctrl;
+
+	/* reset status first */
+	mdio_read(dev, np->phys[0], MII_BMCR);
+	mdio_read(dev, np->phys[0], MII_BMSR);
+
+	reg0 = mdio_read(dev, np->phys[0], MII_BMCR);
+	reg1 = mdio_read(dev, np->phys[0], MII_BMSR);
+
+	if (reg1 & BMSR_LSTATUS) {
+		/* link is up */
+		if (reg0 & BMCR_ANENABLE) {
+			/* autonegotiation is enabled */
+			reg4 = mdio_read(dev, np->phys[0], MII_ADVERTISE);
+			reg5 = mdio_read(dev, np->phys[0], MII_LPA);
+			if (reg4 & ADVERTISE_100FULL && reg5 & LPA_100FULL) {
+				np->speed100 = 1;
+				np->mii_if.full_duplex = 1;
+			} else if (reg4 & ADVERTISE_100HALF && reg5 & LPA_100HALF) {
+				np->speed100 = 1;
+				np->mii_if.full_duplex = 0;
+			} else if (reg4 & ADVERTISE_10FULL && reg5 & LPA_10FULL) {
+				np->speed100 = 0;
+				np->mii_if.full_duplex = 1;
+			} else {
+				np->speed100 = 0;
+				np->mii_if.full_duplex = 0;
+			}
+		} else {
+			/* autonegotiation is disabled */
+			if (reg0 & BMCR_SPEED100)
+				np->speed100 = 1;
+			else
+				np->speed100 = 0;
+			if (reg0 & BMCR_FULLDPLX)
+				np->mii_if.full_duplex = 1;
+			else
+				np->mii_if.full_duplex = 0;
+		}
+		netif_carrier_on(dev);
+		printk(KERN_DEBUG "%s: Link is up, running at %sMbit %s-duplex\n",
+		       dev->name,
+		       np->speed100 ? "100" : "10",
+		       np->mii_if.full_duplex ? "full" : "half");
+
+		new_tx_mode = np->tx_mode & ~FullDuplex;	/* duplex setting */
+		if (np->mii_if.full_duplex)
+			new_tx_mode |= FullDuplex;
+		if (np->tx_mode != new_tx_mode) {
+			np->tx_mode = new_tx_mode;
+			writel(np->tx_mode | MiiSoftReset, ioaddr + TxMode);
+			udelay(1000);
+			writel(np->tx_mode, ioaddr + TxMode);
+		}
+
+		new_intr_timer_ctrl = np->intr_timer_ctrl & ~Timer10X;
+		if (np->speed100)
+			new_intr_timer_ctrl |= Timer10X;
+		if (np->intr_timer_ctrl != new_intr_timer_ctrl) {
+			np->intr_timer_ctrl = new_intr_timer_ctrl;
+			writel(new_intr_timer_ctrl, ioaddr + IntrTimerCtrl);
+		}
+	} else {
+		netif_carrier_off(dev);
+		printk(KERN_DEBUG "%s: Link is down\n", dev->name);
+	}
+}
+
+
+static void netdev_error(struct net_device *dev, int intr_status)
+{
+	struct netdev_private *np = netdev_priv(dev);
+
+	/* Came close to underrunning the Tx FIFO, increase threshold. */
+	if (intr_status & IntrTxDataLow) {
+		if (np->tx_threshold <= PKT_BUF_SZ / 16) {
+			writel(++np->tx_threshold, np->base + TxThreshold);
+			printk(KERN_NOTICE "%s: PCI bus congestion, increasing Tx FIFO threshold to %d bytes\n",
+			       dev->name, np->tx_threshold * 16);
+		} else
+			printk(KERN_WARNING "%s: PCI Tx underflow -- adapter is probably malfunctioning\n", dev->name);
+	}
+	if (intr_status & IntrRxGFPDead) {
+		dev->stats.rx_fifo_errors++;
+		dev->stats.rx_errors++;
+	}
+	if (intr_status & (IntrNoTxCsum | IntrDMAErr)) {
+		dev->stats.tx_fifo_errors++;
+		dev->stats.tx_errors++;
+	}
+	if ((intr_status & ~(IntrNormalMask | IntrAbnormalSummary | IntrLinkChange | IntrStatsMax | IntrTxDataLow | IntrRxGFPDead | IntrNoTxCsum | IntrPCIPad)) && debug)
+		printk(KERN_ERR "%s: Something Wicked happened! %#8.8x.\n",
+		       dev->name, intr_status);
+}
+
+
+static struct net_device_stats *get_stats(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->base;
+
+	/* This adapter architecture needs no SMP locks. */
+	dev->stats.tx_bytes = readl(ioaddr + 0x57010);
+	dev->stats.rx_bytes = readl(ioaddr + 0x57044);
+	dev->stats.tx_packets = readl(ioaddr + 0x57000);
+	dev->stats.tx_aborted_errors =
+		readl(ioaddr + 0x57024) + readl(ioaddr + 0x57028);
+	dev->stats.tx_window_errors = readl(ioaddr + 0x57018);
+	dev->stats.collisions =
+		readl(ioaddr + 0x57004) + readl(ioaddr + 0x57008);
+
+	/* The chip only need report frame silently dropped. */
+	dev->stats.rx_dropped += readw(ioaddr + RxDMAStatus);
+	writew(0, ioaddr + RxDMAStatus);
+	dev->stats.rx_crc_errors = readl(ioaddr + 0x5703C);
+	dev->stats.rx_frame_errors = readl(ioaddr + 0x57040);
+	dev->stats.rx_length_errors = readl(ioaddr + 0x57058);
+	dev->stats.rx_missed_errors = readl(ioaddr + 0x5707C);
+
+	return &dev->stats;
+}
+
+#ifdef VLAN_SUPPORT
+static u32 set_vlan_mode(struct netdev_private *np)
+{
+	u32 ret = VlanMode;
+	u16 vid;
+	void __iomem *filter_addr = np->base + HashTable + 8;
+	int vlan_count = 0;
+
+	for_each_set_bit(vid, np->active_vlans, VLAN_N_VID) {
+		if (vlan_count == 32)
+			break;
+		writew(vid, filter_addr);
+		filter_addr += 16;
+		vlan_count++;
+	}
+	if (vlan_count == 32) {
+		ret |= PerfectFilterVlan;
+		while (vlan_count < 32) {
+			writew(0, filter_addr);
+			filter_addr += 16;
+			vlan_count++;
+		}
+	}
+	return ret;
+}
+#endif /* VLAN_SUPPORT */
+
+static void set_rx_mode(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->base;
+	u32 rx_mode = MinVLANPrio;
+	struct netdev_hw_addr *ha;
+	int i;
+
+#ifdef VLAN_SUPPORT
+	rx_mode |= set_vlan_mode(np);
+#endif /* VLAN_SUPPORT */
+
+	if (dev->flags & IFF_PROMISC) {	/* Set promiscuous. */
+		rx_mode |= AcceptAll;
+	} else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
+		   (dev->flags & IFF_ALLMULTI)) {
+		/* Too many to match, or accept all multicasts. */
+		rx_mode |= AcceptBroadcast|AcceptAllMulticast|PerfectFilter;
+	} else if (netdev_mc_count(dev) <= 14) {
+		/* Use the 16 element perfect filter, skip first two entries. */
+		void __iomem *filter_addr = ioaddr + PerfFilterTable + 2 * 16;
+		__be16 *eaddrs;
+		netdev_for_each_mc_addr(ha, dev) {
+			eaddrs = (__be16 *) ha->addr;
+			writew(be16_to_cpu(eaddrs[2]), filter_addr); filter_addr += 4;
+			writew(be16_to_cpu(eaddrs[1]), filter_addr); filter_addr += 4;
+			writew(be16_to_cpu(eaddrs[0]), filter_addr); filter_addr += 8;
+		}
+		eaddrs = (__be16 *)dev->dev_addr;
+		i = netdev_mc_count(dev) + 2;
+		while (i++ < 16) {
+			writew(be16_to_cpu(eaddrs[0]), filter_addr); filter_addr += 4;
+			writew(be16_to_cpu(eaddrs[1]), filter_addr); filter_addr += 4;
+			writew(be16_to_cpu(eaddrs[2]), filter_addr); filter_addr += 8;
+		}
+		rx_mode |= AcceptBroadcast|PerfectFilter;
+	} else {
+		/* Must use a multicast hash table. */
+		void __iomem *filter_addr;
+		__be16 *eaddrs;
+		__le16 mc_filter[32] __attribute__ ((aligned(sizeof(long))));	/* Multicast hash filter */
+
+		memset(mc_filter, 0, sizeof(mc_filter));
+		netdev_for_each_mc_addr(ha, dev) {
+			/* The chip uses the upper 9 CRC bits
+			   as index into the hash table */
+			int bit_nr = ether_crc_le(ETH_ALEN, ha->addr) >> 23;
+			__le32 *fptr = (__le32 *) &mc_filter[(bit_nr >> 4) & ~1];
+
+			*fptr |= cpu_to_le32(1 << (bit_nr & 31));
+		}
+		/* Clear the perfect filter list, skip first two entries. */
+		filter_addr = ioaddr + PerfFilterTable + 2 * 16;
+		eaddrs = (__be16 *)dev->dev_addr;
+		for (i = 2; i < 16; i++) {
+			writew(be16_to_cpu(eaddrs[0]), filter_addr); filter_addr += 4;
+			writew(be16_to_cpu(eaddrs[1]), filter_addr); filter_addr += 4;
+			writew(be16_to_cpu(eaddrs[2]), filter_addr); filter_addr += 8;
+		}
+		for (filter_addr = ioaddr + HashTable, i = 0; i < 32; filter_addr+= 16, i++)
+			writew(mc_filter[i], filter_addr);
+		rx_mode |= AcceptBroadcast|PerfectFilter|HashFilter;
+	}
+	writel(rx_mode, ioaddr + RxFilterMode);
+}
+
+static int check_if_running(struct net_device *dev)
+{
+	if (!netif_running(dev))
+		return -EINVAL;
+	return 0;
+}
+
+static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, pci_name(np->pci_dev));
+}
+
+static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	spin_lock_irq(&np->lock);
+	mii_ethtool_gset(&np->mii_if, ecmd);
+	spin_unlock_irq(&np->lock);
+	return 0;
+}
+
+static int set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	int res;
+	spin_lock_irq(&np->lock);
+	res = mii_ethtool_sset(&np->mii_if, ecmd);
+	spin_unlock_irq(&np->lock);
+	check_duplex(dev);
+	return res;
+}
+
+static int nway_reset(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	return mii_nway_restart(&np->mii_if);
+}
+
+static u32 get_link(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	return mii_link_ok(&np->mii_if);
+}
+
+static u32 get_msglevel(struct net_device *dev)
+{
+	return debug;
+}
+
+static void set_msglevel(struct net_device *dev, u32 val)
+{
+	debug = val;
+}
+
+static const struct ethtool_ops ethtool_ops = {
+	.begin = check_if_running,
+	.get_drvinfo = get_drvinfo,
+	.get_settings = get_settings,
+	.set_settings = set_settings,
+	.nway_reset = nway_reset,
+	.get_link = get_link,
+	.get_msglevel = get_msglevel,
+	.set_msglevel = set_msglevel,
+};
+
+static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	struct mii_ioctl_data *data = if_mii(rq);
+	int rc;
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	spin_lock_irq(&np->lock);
+	rc = generic_mii_ioctl(&np->mii_if, data, cmd, NULL);
+	spin_unlock_irq(&np->lock);
+
+	if ((cmd == SIOCSMIIREG) && (data->phy_id == np->phys[0]))
+		check_duplex(dev);
+
+	return rc;
+}
+
+static int netdev_close(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->base;
+	int i;
+
+	netif_stop_queue(dev);
+
+	napi_disable(&np->napi);
+
+	if (debug > 1) {
+		printk(KERN_DEBUG "%s: Shutting down ethercard, Intr status %#8.8x.\n",
+			   dev->name, (int) readl(ioaddr + IntrStatus));
+		printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d, Rx %d / %d.\n",
+		       dev->name, np->cur_tx, np->dirty_tx,
+		       np->cur_rx, np->dirty_rx);
+	}
+
+	/* Disable interrupts by clearing the interrupt mask. */
+	writel(0, ioaddr + IntrEnable);
+
+	/* Stop the chip's Tx and Rx processes. */
+	writel(0, ioaddr + GenCtrl);
+	readl(ioaddr + GenCtrl);
+
+	if (debug > 5) {
+		printk(KERN_DEBUG"  Tx ring at %#llx:\n",
+		       (long long) np->tx_ring_dma);
+		for (i = 0; i < 8 /* TX_RING_SIZE is huge! */; i++)
+			printk(KERN_DEBUG " #%d desc. %#8.8x %#llx -> %#8.8x.\n",
+			       i, le32_to_cpu(np->tx_ring[i].status),
+			       (long long) dma_to_cpu(np->tx_ring[i].addr),
+			       le32_to_cpu(np->tx_done_q[i].status));
+		printk(KERN_DEBUG "  Rx ring at %#llx -> %p:\n",
+		       (long long) np->rx_ring_dma, np->rx_done_q);
+		if (np->rx_done_q)
+			for (i = 0; i < 8 /* RX_RING_SIZE */; i++) {
+				printk(KERN_DEBUG " #%d desc. %#llx -> %#8.8x\n",
+				       i, (long long) dma_to_cpu(np->rx_ring[i].rxaddr), le32_to_cpu(np->rx_done_q[i].status));
+		}
+	}
+
+	free_irq(dev->irq, dev);
+
+	/* Free all the skbuffs in the Rx queue. */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		np->rx_ring[i].rxaddr = cpu_to_dma(0xBADF00D0); /* An invalid address. */
+		if (np->rx_info[i].skb != NULL) {
+			pci_unmap_single(np->pci_dev, np->rx_info[i].mapping, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+			dev_kfree_skb(np->rx_info[i].skb);
+		}
+		np->rx_info[i].skb = NULL;
+		np->rx_info[i].mapping = 0;
+	}
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		struct sk_buff *skb = np->tx_info[i].skb;
+		if (skb == NULL)
+			continue;
+		pci_unmap_single(np->pci_dev,
+				 np->tx_info[i].mapping,
+				 skb_first_frag_len(skb), PCI_DMA_TODEVICE);
+		np->tx_info[i].mapping = 0;
+		dev_kfree_skb(skb);
+		np->tx_info[i].skb = NULL;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int starfire_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	if (netif_running(dev)) {
+		netif_device_detach(dev);
+		netdev_close(dev);
+	}
+
+	pci_save_state(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev,state));
+
+	return 0;
+}
+
+static int starfire_resume(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+
+	if (netif_running(dev)) {
+		netdev_open(dev);
+		netif_device_attach(dev);
+	}
+
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+
+static void __devexit starfire_remove_one (struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct netdev_private *np = netdev_priv(dev);
+
+	BUG_ON(!dev);
+
+	unregister_netdev(dev);
+
+	if (np->queue_mem)
+		pci_free_consistent(pdev, np->queue_mem_size, np->queue_mem, np->queue_mem_dma);
+
+
+	/* XXX: add wakeup code -- requires firmware for MagicPacket */
+	pci_set_power_state(pdev, PCI_D3hot);	/* go to sleep in D3 mode */
+	pci_disable_device(pdev);
+
+	iounmap(np->base);
+	pci_release_regions(pdev);
+
+	pci_set_drvdata(pdev, NULL);
+	free_netdev(dev);			/* Will also free np!! */
+}
+
+
+static struct pci_driver starfire_driver = {
+	.name		= DRV_NAME,
+	.probe		= starfire_init_one,
+	.remove		= __devexit_p(starfire_remove_one),
+#ifdef CONFIG_PM
+	.suspend	= starfire_suspend,
+	.resume		= starfire_resume,
+#endif /* CONFIG_PM */
+	.id_table	= starfire_pci_tbl,
+};
+
+
+static int __init starfire_init (void)
+{
+/* when a module, this is printed whether or not devices are found in probe */
+#ifdef MODULE
+	printk(version);
+
+	printk(KERN_INFO DRV_NAME ": polling (NAPI) enabled\n");
+#endif
+
+	BUILD_BUG_ON(sizeof(dma_addr_t) != sizeof(netdrv_addr_t));
+
+	return pci_register_driver(&starfire_driver);
+}
+
+
+static void __exit starfire_cleanup (void)
+{
+	pci_unregister_driver (&starfire_driver);
+}
+
+
+module_init(starfire_init);
+module_exit(starfire_cleanup);
+
+
+/*
+ * Local variables:
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/adi/bfin_mac.c linux-libre-3.2-gnu/drivers/net/ethernet/adi/bfin_mac.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/adi/bfin_mac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/adi/bfin_mac.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1767 @@
+/*
+ * Blackfin On-Chip MAC Driver
+ *
+ * Copyright 2004-2010 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#define DRV_VERSION	"1.1"
+#define DRV_DESC	"Blackfin on-chip Ethernet MAC driver"
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/crc32.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/platform_device.h>
+
+#include <asm/dma.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/div64.h>
+#include <asm/dpmc.h>
+#include <asm/blackfin.h>
+#include <asm/cacheflush.h>
+#include <asm/portmux.h>
+#include <mach/pll.h>
+
+#include "bfin_mac.h"
+
+MODULE_AUTHOR("Bryan Wu, Luke Yang");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_ALIAS("platform:bfin_mac");
+
+#if defined(CONFIG_BFIN_MAC_USE_L1)
+# define bfin_mac_alloc(dma_handle, size, num)  l1_data_sram_zalloc(size*num)
+# define bfin_mac_free(dma_handle, ptr, num)    l1_data_sram_free(ptr)
+#else
+# define bfin_mac_alloc(dma_handle, size, num) \
+	dma_alloc_coherent(NULL, size*num, dma_handle, GFP_KERNEL)
+# define bfin_mac_free(dma_handle, ptr, num) \
+	dma_free_coherent(NULL, sizeof(*ptr)*num, ptr, dma_handle)
+#endif
+
+#define PKT_BUF_SZ 1580
+
+#define MAX_TIMEOUT_CNT	500
+
+/* pointers to maintain transmit list */
+static struct net_dma_desc_tx *tx_list_head;
+static struct net_dma_desc_tx *tx_list_tail;
+static struct net_dma_desc_rx *rx_list_head;
+static struct net_dma_desc_rx *rx_list_tail;
+static struct net_dma_desc_rx *current_rx_ptr;
+static struct net_dma_desc_tx *current_tx_ptr;
+static struct net_dma_desc_tx *tx_desc;
+static struct net_dma_desc_rx *rx_desc;
+
+static void desc_list_free(void)
+{
+	struct net_dma_desc_rx *r;
+	struct net_dma_desc_tx *t;
+	int i;
+#if !defined(CONFIG_BFIN_MAC_USE_L1)
+	dma_addr_t dma_handle = 0;
+#endif
+
+	if (tx_desc) {
+		t = tx_list_head;
+		for (i = 0; i < CONFIG_BFIN_TX_DESC_NUM; i++) {
+			if (t) {
+				if (t->skb) {
+					dev_kfree_skb(t->skb);
+					t->skb = NULL;
+				}
+				t = t->next;
+			}
+		}
+		bfin_mac_free(dma_handle, tx_desc, CONFIG_BFIN_TX_DESC_NUM);
+	}
+
+	if (rx_desc) {
+		r = rx_list_head;
+		for (i = 0; i < CONFIG_BFIN_RX_DESC_NUM; i++) {
+			if (r) {
+				if (r->skb) {
+					dev_kfree_skb(r->skb);
+					r->skb = NULL;
+				}
+				r = r->next;
+			}
+		}
+		bfin_mac_free(dma_handle, rx_desc, CONFIG_BFIN_RX_DESC_NUM);
+	}
+}
+
+static int desc_list_init(void)
+{
+	int i;
+	struct sk_buff *new_skb;
+#if !defined(CONFIG_BFIN_MAC_USE_L1)
+	/*
+	 * This dma_handle is useless in Blackfin dma_alloc_coherent().
+	 * The real dma handler is the return value of dma_alloc_coherent().
+	 */
+	dma_addr_t dma_handle;
+#endif
+
+	tx_desc = bfin_mac_alloc(&dma_handle,
+				sizeof(struct net_dma_desc_tx),
+				CONFIG_BFIN_TX_DESC_NUM);
+	if (tx_desc == NULL)
+		goto init_error;
+
+	rx_desc = bfin_mac_alloc(&dma_handle,
+				sizeof(struct net_dma_desc_rx),
+				CONFIG_BFIN_RX_DESC_NUM);
+	if (rx_desc == NULL)
+		goto init_error;
+
+	/* init tx_list */
+	tx_list_head = tx_list_tail = tx_desc;
+
+	for (i = 0; i < CONFIG_BFIN_TX_DESC_NUM; i++) {
+		struct net_dma_desc_tx *t = tx_desc + i;
+		struct dma_descriptor *a = &(t->desc_a);
+		struct dma_descriptor *b = &(t->desc_b);
+
+		/*
+		 * disable DMA
+		 * read from memory WNR = 0
+		 * wordsize is 32 bits
+		 * 6 half words is desc size
+		 * large desc flow
+		 */
+		a->config = WDSIZE_32 | NDSIZE_6 | DMAFLOW_LARGE;
+		a->start_addr = (unsigned long)t->packet;
+		a->x_count = 0;
+		a->next_dma_desc = b;
+
+		/*
+		 * enabled DMA
+		 * write to memory WNR = 1
+		 * wordsize is 32 bits
+		 * disable interrupt
+		 * 6 half words is desc size
+		 * large desc flow
+		 */
+		b->config = DMAEN | WNR | WDSIZE_32 | NDSIZE_6 | DMAFLOW_LARGE;
+		b->start_addr = (unsigned long)(&(t->status));
+		b->x_count = 0;
+
+		t->skb = NULL;
+		tx_list_tail->desc_b.next_dma_desc = a;
+		tx_list_tail->next = t;
+		tx_list_tail = t;
+	}
+	tx_list_tail->next = tx_list_head;	/* tx_list is a circle */
+	tx_list_tail->desc_b.next_dma_desc = &(tx_list_head->desc_a);
+	current_tx_ptr = tx_list_head;
+
+	/* init rx_list */
+	rx_list_head = rx_list_tail = rx_desc;
+
+	for (i = 0; i < CONFIG_BFIN_RX_DESC_NUM; i++) {
+		struct net_dma_desc_rx *r = rx_desc + i;
+		struct dma_descriptor *a = &(r->desc_a);
+		struct dma_descriptor *b = &(r->desc_b);
+
+		/* allocate a new skb for next time receive */
+		new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN);
+		if (!new_skb) {
+			pr_notice("init: low on mem - packet dropped\n");
+			goto init_error;
+		}
+		skb_reserve(new_skb, NET_IP_ALIGN);
+		/* Invidate the data cache of skb->data range when it is write back
+		 * cache. It will prevent overwritting the new data from DMA
+		 */
+		blackfin_dcache_invalidate_range((unsigned long)new_skb->head,
+					 (unsigned long)new_skb->end);
+		r->skb = new_skb;
+
+		/*
+		 * enabled DMA
+		 * write to memory WNR = 1
+		 * wordsize is 32 bits
+		 * disable interrupt
+		 * 6 half words is desc size
+		 * large desc flow
+		 */
+		a->config = DMAEN | WNR | WDSIZE_32 | NDSIZE_6 | DMAFLOW_LARGE;
+		/* since RXDWA is enabled */
+		a->start_addr = (unsigned long)new_skb->data - 2;
+		a->x_count = 0;
+		a->next_dma_desc = b;
+
+		/*
+		 * enabled DMA
+		 * write to memory WNR = 1
+		 * wordsize is 32 bits
+		 * enable interrupt
+		 * 6 half words is desc size
+		 * large desc flow
+		 */
+		b->config = DMAEN | WNR | WDSIZE_32 | DI_EN |
+				NDSIZE_6 | DMAFLOW_LARGE;
+		b->start_addr = (unsigned long)(&(r->status));
+		b->x_count = 0;
+
+		rx_list_tail->desc_b.next_dma_desc = a;
+		rx_list_tail->next = r;
+		rx_list_tail = r;
+	}
+	rx_list_tail->next = rx_list_head;	/* rx_list is a circle */
+	rx_list_tail->desc_b.next_dma_desc = &(rx_list_head->desc_a);
+	current_rx_ptr = rx_list_head;
+
+	return 0;
+
+init_error:
+	desc_list_free();
+	pr_err("kmalloc failed\n");
+	return -ENOMEM;
+}
+
+
+/*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/
+
+/*
+ * MII operations
+ */
+/* Wait until the previous MDC/MDIO transaction has completed */
+static int bfin_mdio_poll(void)
+{
+	int timeout_cnt = MAX_TIMEOUT_CNT;
+
+	/* poll the STABUSY bit */
+	while ((bfin_read_EMAC_STAADD()) & STABUSY) {
+		udelay(1);
+		if (timeout_cnt-- < 0) {
+			pr_err("wait MDC/MDIO transaction to complete timeout\n");
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+/* Read an off-chip register in a PHY through the MDC/MDIO port */
+static int bfin_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
+{
+	int ret;
+
+	ret = bfin_mdio_poll();
+	if (ret)
+		return ret;
+
+	/* read mode */
+	bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) |
+				SET_REGAD((u16) regnum) |
+				STABUSY);
+
+	ret = bfin_mdio_poll();
+	if (ret)
+		return ret;
+
+	return (int) bfin_read_EMAC_STADAT();
+}
+
+/* Write an off-chip register in a PHY through the MDC/MDIO port */
+static int bfin_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
+			      u16 value)
+{
+	int ret;
+
+	ret = bfin_mdio_poll();
+	if (ret)
+		return ret;
+
+	bfin_write_EMAC_STADAT((u32) value);
+
+	/* write mode */
+	bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) |
+				SET_REGAD((u16) regnum) |
+				STAOP |
+				STABUSY);
+
+	return bfin_mdio_poll();
+}
+
+static int bfin_mdiobus_reset(struct mii_bus *bus)
+{
+	return 0;
+}
+
+static void bfin_mac_adjust_link(struct net_device *dev)
+{
+	struct bfin_mac_local *lp = netdev_priv(dev);
+	struct phy_device *phydev = lp->phydev;
+	unsigned long flags;
+	int new_state = 0;
+
+	spin_lock_irqsave(&lp->lock, flags);
+	if (phydev->link) {
+		/* Now we make sure that we can be in full duplex mode.
+		 * If not, we operate in half-duplex mode. */
+		if (phydev->duplex != lp->old_duplex) {
+			u32 opmode = bfin_read_EMAC_OPMODE();
+			new_state = 1;
+
+			if (phydev->duplex)
+				opmode |= FDMODE;
+			else
+				opmode &= ~(FDMODE);
+
+			bfin_write_EMAC_OPMODE(opmode);
+			lp->old_duplex = phydev->duplex;
+		}
+
+		if (phydev->speed != lp->old_speed) {
+			if (phydev->interface == PHY_INTERFACE_MODE_RMII) {
+				u32 opmode = bfin_read_EMAC_OPMODE();
+				switch (phydev->speed) {
+				case 10:
+					opmode |= RMII_10;
+					break;
+				case 100:
+					opmode &= ~RMII_10;
+					break;
+				default:
+					netdev_warn(dev,
+						"Ack! Speed (%d) is not 10/100!\n",
+						phydev->speed);
+					break;
+				}
+				bfin_write_EMAC_OPMODE(opmode);
+			}
+
+			new_state = 1;
+			lp->old_speed = phydev->speed;
+		}
+
+		if (!lp->old_link) {
+			new_state = 1;
+			lp->old_link = 1;
+		}
+	} else if (lp->old_link) {
+		new_state = 1;
+		lp->old_link = 0;
+		lp->old_speed = 0;
+		lp->old_duplex = -1;
+	}
+
+	if (new_state) {
+		u32 opmode = bfin_read_EMAC_OPMODE();
+		phy_print_status(phydev);
+		pr_debug("EMAC_OPMODE = 0x%08x\n", opmode);
+	}
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+}
+
+/* MDC  = 2.5 MHz */
+#define MDC_CLK 2500000
+
+static int mii_probe(struct net_device *dev, int phy_mode)
+{
+	struct bfin_mac_local *lp = netdev_priv(dev);
+	struct phy_device *phydev = NULL;
+	unsigned short sysctl;
+	int i;
+	u32 sclk, mdc_div;
+
+	/* Enable PHY output early */
+	if (!(bfin_read_VR_CTL() & CLKBUFOE))
+		bfin_write_VR_CTL(bfin_read_VR_CTL() | CLKBUFOE);
+
+	sclk = get_sclk();
+	mdc_div = ((sclk / MDC_CLK) / 2) - 1;
+
+	sysctl = bfin_read_EMAC_SYSCTL();
+	sysctl = (sysctl & ~MDCDIV) | SET_MDCDIV(mdc_div);
+	bfin_write_EMAC_SYSCTL(sysctl);
+
+	/* search for connected PHY device */
+	for (i = 0; i < PHY_MAX_ADDR; ++i) {
+		struct phy_device *const tmp_phydev = lp->mii_bus->phy_map[i];
+
+		if (!tmp_phydev)
+			continue; /* no PHY here... */
+
+		phydev = tmp_phydev;
+		break; /* found it */
+	}
+
+	/* now we are supposed to have a proper phydev, to attach to... */
+	if (!phydev) {
+		netdev_err(dev, "no phy device found\n");
+		return -ENODEV;
+	}
+
+	if (phy_mode != PHY_INTERFACE_MODE_RMII &&
+		phy_mode != PHY_INTERFACE_MODE_MII) {
+		netdev_err(dev, "invalid phy interface mode\n");
+		return -EINVAL;
+	}
+
+	phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link,
+			0, phy_mode);
+
+	if (IS_ERR(phydev)) {
+		netdev_err(dev, "could not attach PHY\n");
+		return PTR_ERR(phydev);
+	}
+
+	/* mask with MAC supported features */
+	phydev->supported &= (SUPPORTED_10baseT_Half
+			      | SUPPORTED_10baseT_Full
+			      | SUPPORTED_100baseT_Half
+			      | SUPPORTED_100baseT_Full
+			      | SUPPORTED_Autoneg
+			      | SUPPORTED_Pause | SUPPORTED_Asym_Pause
+			      | SUPPORTED_MII
+			      | SUPPORTED_TP);
+
+	phydev->advertising = phydev->supported;
+
+	lp->old_link = 0;
+	lp->old_speed = 0;
+	lp->old_duplex = -1;
+	lp->phydev = phydev;
+
+	pr_info("attached PHY driver [%s] "
+	        "(mii_bus:phy_addr=%s, irq=%d, mdc_clk=%dHz(mdc_div=%d)@sclk=%dMHz)\n",
+	        phydev->drv->name, dev_name(&phydev->dev), phydev->irq,
+	        MDC_CLK, mdc_div, sclk/1000000);
+
+	return 0;
+}
+
+/*
+ * Ethtool support
+ */
+
+/*
+ * interrupt routine for magic packet wakeup
+ */
+static irqreturn_t bfin_mac_wake_interrupt(int irq, void *dev_id)
+{
+	return IRQ_HANDLED;
+}
+
+static int
+bfin_mac_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct bfin_mac_local *lp = netdev_priv(dev);
+
+	if (lp->phydev)
+		return phy_ethtool_gset(lp->phydev, cmd);
+
+	return -EINVAL;
+}
+
+static int
+bfin_mac_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct bfin_mac_local *lp = netdev_priv(dev);
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (lp->phydev)
+		return phy_ethtool_sset(lp->phydev, cmd);
+
+	return -EINVAL;
+}
+
+static void bfin_mac_ethtool_getdrvinfo(struct net_device *dev,
+					struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, KBUILD_MODNAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->fw_version, "N/A");
+	strcpy(info->bus_info, dev_name(&dev->dev));
+}
+
+static void bfin_mac_ethtool_getwol(struct net_device *dev,
+	struct ethtool_wolinfo *wolinfo)
+{
+	struct bfin_mac_local *lp = netdev_priv(dev);
+
+	wolinfo->supported = WAKE_MAGIC;
+	wolinfo->wolopts = lp->wol;
+}
+
+static int bfin_mac_ethtool_setwol(struct net_device *dev,
+	struct ethtool_wolinfo *wolinfo)
+{
+	struct bfin_mac_local *lp = netdev_priv(dev);
+	int rc;
+
+	if (wolinfo->wolopts & (WAKE_MAGICSECURE |
+				WAKE_UCAST |
+				WAKE_MCAST |
+				WAKE_BCAST |
+				WAKE_ARP))
+		return -EOPNOTSUPP;
+
+	lp->wol = wolinfo->wolopts;
+
+	if (lp->wol && !lp->irq_wake_requested) {
+		/* register wake irq handler */
+		rc = request_irq(IRQ_MAC_WAKEDET, bfin_mac_wake_interrupt,
+				 IRQF_DISABLED, "EMAC_WAKE", dev);
+		if (rc)
+			return rc;
+		lp->irq_wake_requested = true;
+	}
+
+	if (!lp->wol && lp->irq_wake_requested) {
+		free_irq(IRQ_MAC_WAKEDET, dev);
+		lp->irq_wake_requested = false;
+	}
+
+	/* Make sure the PHY driver doesn't suspend */
+	device_init_wakeup(&dev->dev, lp->wol);
+
+	return 0;
+}
+
+static const struct ethtool_ops bfin_mac_ethtool_ops = {
+	.get_settings = bfin_mac_ethtool_getsettings,
+	.set_settings = bfin_mac_ethtool_setsettings,
+	.get_link = ethtool_op_get_link,
+	.get_drvinfo = bfin_mac_ethtool_getdrvinfo,
+	.get_wol = bfin_mac_ethtool_getwol,
+	.set_wol = bfin_mac_ethtool_setwol,
+};
+
+/**************************************************************************/
+static void setup_system_regs(struct net_device *dev)
+{
+	struct bfin_mac_local *lp = netdev_priv(dev);
+	int i;
+	unsigned short sysctl;
+
+	/*
+	 * Odd word alignment for Receive Frame DMA word
+	 * Configure checksum support and rcve frame word alignment
+	 */
+	sysctl = bfin_read_EMAC_SYSCTL();
+	/*
+	 * check if interrupt is requested for any PHY,
+	 * enable PHY interrupt only if needed
+	 */
+	for (i = 0; i < PHY_MAX_ADDR; ++i)
+		if (lp->mii_bus->irq[i] != PHY_POLL)
+			break;
+	if (i < PHY_MAX_ADDR)
+		sysctl |= PHYIE;
+	sysctl |= RXDWA;
+#if defined(BFIN_MAC_CSUM_OFFLOAD)
+	sysctl |= RXCKS;
+#else
+	sysctl &= ~RXCKS;
+#endif
+	bfin_write_EMAC_SYSCTL(sysctl);
+
+	bfin_write_EMAC_MMC_CTL(RSTC | CROLL);
+
+	/* Set vlan regs to let 1522 bytes long packets pass through */
+	bfin_write_EMAC_VLAN1(lp->vlan1_mask);
+	bfin_write_EMAC_VLAN2(lp->vlan2_mask);
+
+	/* Initialize the TX DMA channel registers */
+	bfin_write_DMA2_X_COUNT(0);
+	bfin_write_DMA2_X_MODIFY(4);
+	bfin_write_DMA2_Y_COUNT(0);
+	bfin_write_DMA2_Y_MODIFY(0);
+
+	/* Initialize the RX DMA channel registers */
+	bfin_write_DMA1_X_COUNT(0);
+	bfin_write_DMA1_X_MODIFY(4);
+	bfin_write_DMA1_Y_COUNT(0);
+	bfin_write_DMA1_Y_MODIFY(0);
+}
+
+static void setup_mac_addr(u8 *mac_addr)
+{
+	u32 addr_low = le32_to_cpu(*(__le32 *) & mac_addr[0]);
+	u16 addr_hi = le16_to_cpu(*(__le16 *) & mac_addr[4]);
+
+	/* this depends on a little-endian machine */
+	bfin_write_EMAC_ADDRLO(addr_low);
+	bfin_write_EMAC_ADDRHI(addr_hi);
+}
+
+static int bfin_mac_set_mac_address(struct net_device *dev, void *p)
+{
+	struct sockaddr *addr = p;
+	if (netif_running(dev))
+		return -EBUSY;
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+	setup_mac_addr(dev->dev_addr);
+	return 0;
+}
+
+#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP
+#define bfin_mac_hwtstamp_is_none(cfg) ((cfg) == HWTSTAMP_FILTER_NONE)
+
+static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
+		struct ifreq *ifr, int cmd)
+{
+	struct hwtstamp_config config;
+	struct bfin_mac_local *lp = netdev_priv(netdev);
+	u16 ptpctl;
+	u32 ptpfv1, ptpfv2, ptpfv3, ptpfoff;
+
+	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+		return -EFAULT;
+
+	pr_debug("%s config flag:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
+			__func__, config.flags, config.tx_type, config.rx_filter);
+
+	/* reserved for future extensions */
+	if (config.flags)
+		return -EINVAL;
+
+	if ((config.tx_type != HWTSTAMP_TX_OFF) &&
+			(config.tx_type != HWTSTAMP_TX_ON))
+		return -ERANGE;
+
+	ptpctl = bfin_read_EMAC_PTP_CTL();
+
+	switch (config.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		/*
+		 * Dont allow any timestamping
+		 */
+		ptpfv3 = 0xFFFFFFFF;
+		bfin_write_EMAC_PTP_FV3(ptpfv3);
+		break;
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+		/*
+		 * Clear the five comparison mask bits (bits[12:8]) in EMAC_PTP_CTL)
+		 * to enable all the field matches.
+		 */
+		ptpctl &= ~0x1F00;
+		bfin_write_EMAC_PTP_CTL(ptpctl);
+		/*
+		 * Keep the default values of the EMAC_PTP_FOFF register.
+		 */
+		ptpfoff = 0x4A24170C;
+		bfin_write_EMAC_PTP_FOFF(ptpfoff);
+		/*
+		 * Keep the default values of the EMAC_PTP_FV1 and EMAC_PTP_FV2
+		 * registers.
+		 */
+		ptpfv1 = 0x11040800;
+		bfin_write_EMAC_PTP_FV1(ptpfv1);
+		ptpfv2 = 0x0140013F;
+		bfin_write_EMAC_PTP_FV2(ptpfv2);
+		/*
+		 * The default value (0xFFFC) allows the timestamping of both
+		 * received Sync messages and Delay_Req messages.
+		 */
+		ptpfv3 = 0xFFFFFFFC;
+		bfin_write_EMAC_PTP_FV3(ptpfv3);
+
+		config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
+		break;
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+		/* Clear all five comparison mask bits (bits[12:8]) in the
+		 * EMAC_PTP_CTL register to enable all the field matches.
+		 */
+		ptpctl &= ~0x1F00;
+		bfin_write_EMAC_PTP_CTL(ptpctl);
+		/*
+		 * Keep the default values of the EMAC_PTP_FOFF register, except set
+		 * the PTPCOF field to 0x2A.
+		 */
+		ptpfoff = 0x2A24170C;
+		bfin_write_EMAC_PTP_FOFF(ptpfoff);
+		/*
+		 * Keep the default values of the EMAC_PTP_FV1 and EMAC_PTP_FV2
+		 * registers.
+		 */
+		ptpfv1 = 0x11040800;
+		bfin_write_EMAC_PTP_FV1(ptpfv1);
+		ptpfv2 = 0x0140013F;
+		bfin_write_EMAC_PTP_FV2(ptpfv2);
+		/*
+		 * To allow the timestamping of Pdelay_Req and Pdelay_Resp, set
+		 * the value to 0xFFF0.
+		 */
+		ptpfv3 = 0xFFFFFFF0;
+		bfin_write_EMAC_PTP_FV3(ptpfv3);
+
+		config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
+		break;
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+		/*
+		 * Clear bits 8 and 12 of the EMAC_PTP_CTL register to enable only the
+		 * EFTM and PTPCM field comparison.
+		 */
+		ptpctl &= ~0x1100;
+		bfin_write_EMAC_PTP_CTL(ptpctl);
+		/*
+		 * Keep the default values of all the fields of the EMAC_PTP_FOFF
+		 * register, except set the PTPCOF field to 0x0E.
+		 */
+		ptpfoff = 0x0E24170C;
+		bfin_write_EMAC_PTP_FOFF(ptpfoff);
+		/*
+		 * Program bits [15:0] of the EMAC_PTP_FV1 register to 0x88F7, which
+		 * corresponds to PTP messages on the MAC layer.
+		 */
+		ptpfv1 = 0x110488F7;
+		bfin_write_EMAC_PTP_FV1(ptpfv1);
+		ptpfv2 = 0x0140013F;
+		bfin_write_EMAC_PTP_FV2(ptpfv2);
+		/*
+		 * To allow the timestamping of Pdelay_Req and Pdelay_Resp
+		 * messages, set the value to 0xFFF0.
+		 */
+		ptpfv3 = 0xFFFFFFF0;
+		bfin_write_EMAC_PTP_FV3(ptpfv3);
+
+		config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	if (config.tx_type == HWTSTAMP_TX_OFF &&
+	    bfin_mac_hwtstamp_is_none(config.rx_filter)) {
+		ptpctl &= ~PTP_EN;
+		bfin_write_EMAC_PTP_CTL(ptpctl);
+
+		SSYNC();
+	} else {
+		ptpctl |= PTP_EN;
+		bfin_write_EMAC_PTP_CTL(ptpctl);
+
+		/*
+		 * clear any existing timestamp
+		 */
+		bfin_read_EMAC_PTP_RXSNAPLO();
+		bfin_read_EMAC_PTP_RXSNAPHI();
+
+		bfin_read_EMAC_PTP_TXSNAPLO();
+		bfin_read_EMAC_PTP_TXSNAPHI();
+
+		/*
+		 * Set registers so that rollover occurs soon to test this.
+		 */
+		bfin_write_EMAC_PTP_TIMELO(0x00000000);
+		bfin_write_EMAC_PTP_TIMEHI(0xFF800000);
+
+		SSYNC();
+
+		lp->compare.last_update = 0;
+		timecounter_init(&lp->clock,
+				&lp->cycles,
+				ktime_to_ns(ktime_get_real()));
+		timecompare_update(&lp->compare, 0);
+	}
+
+	lp->stamp_cfg = config;
+	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
+		-EFAULT : 0;
+}
+
+static void bfin_dump_hwtamp(char *s, ktime_t *hw, ktime_t *ts, struct timecompare *cmp)
+{
+	ktime_t sys = ktime_get_real();
+
+	pr_debug("%s %s hardware:%d,%d transform system:%d,%d system:%d,%d, cmp:%lld, %lld\n",
+			__func__, s, hw->tv.sec, hw->tv.nsec, ts->tv.sec, ts->tv.nsec, sys.tv.sec,
+			sys.tv.nsec, cmp->offset, cmp->skew);
+}
+
+static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
+{
+	struct bfin_mac_local *lp = netdev_priv(netdev);
+
+	if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
+		int timeout_cnt = MAX_TIMEOUT_CNT;
+
+		/* When doing time stamping, keep the connection to the socket
+		 * a while longer
+		 */
+		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+
+		/*
+		 * The timestamping is done at the EMAC module's MII/RMII interface
+		 * when the module sees the Start of Frame of an event message packet. This
+		 * interface is the closest possible place to the physical Ethernet transmission
+		 * medium, providing the best timing accuracy.
+		 */
+		while ((!(bfin_read_EMAC_PTP_ISTAT() & TXTL)) && (--timeout_cnt))
+			udelay(1);
+		if (timeout_cnt == 0)
+			netdev_err(netdev, "timestamp the TX packet failed\n");
+		else {
+			struct skb_shared_hwtstamps shhwtstamps;
+			u64 ns;
+			u64 regval;
+
+			regval = bfin_read_EMAC_PTP_TXSNAPLO();
+			regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32;
+			memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+			ns = timecounter_cyc2time(&lp->clock,
+					regval);
+			timecompare_update(&lp->compare, ns);
+			shhwtstamps.hwtstamp = ns_to_ktime(ns);
+			shhwtstamps.syststamp =
+				timecompare_transform(&lp->compare, ns);
+			skb_tstamp_tx(skb, &shhwtstamps);
+
+			bfin_dump_hwtamp("TX", &shhwtstamps.hwtstamp, &shhwtstamps.syststamp, &lp->compare);
+		}
+	}
+}
+
+static void bfin_rx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
+{
+	struct bfin_mac_local *lp = netdev_priv(netdev);
+	u32 valid;
+	u64 regval, ns;
+	struct skb_shared_hwtstamps *shhwtstamps;
+
+	if (bfin_mac_hwtstamp_is_none(lp->stamp_cfg.rx_filter))
+		return;
+
+	valid = bfin_read_EMAC_PTP_ISTAT() & RXEL;
+	if (!valid)
+		return;
+
+	shhwtstamps = skb_hwtstamps(skb);
+
+	regval = bfin_read_EMAC_PTP_RXSNAPLO();
+	regval |= (u64)bfin_read_EMAC_PTP_RXSNAPHI() << 32;
+	ns = timecounter_cyc2time(&lp->clock, regval);
+	timecompare_update(&lp->compare, ns);
+	memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+	shhwtstamps->hwtstamp = ns_to_ktime(ns);
+	shhwtstamps->syststamp = timecompare_transform(&lp->compare, ns);
+
+	bfin_dump_hwtamp("RX", &shhwtstamps->hwtstamp, &shhwtstamps->syststamp, &lp->compare);
+}
+
+/*
+ * bfin_read_clock - read raw cycle counter (to be used by time counter)
+ */
+static cycle_t bfin_read_clock(const struct cyclecounter *tc)
+{
+	u64 stamp;
+
+	stamp =  bfin_read_EMAC_PTP_TIMELO();
+	stamp |= (u64)bfin_read_EMAC_PTP_TIMEHI() << 32ULL;
+
+	return stamp;
+}
+
+#define PTP_CLK 25000000
+
+static void bfin_mac_hwtstamp_init(struct net_device *netdev)
+{
+	struct bfin_mac_local *lp = netdev_priv(netdev);
+	u64 append;
+
+	/* Initialize hardware timer */
+	append = PTP_CLK * (1ULL << 32);
+	do_div(append, get_sclk());
+	bfin_write_EMAC_PTP_ADDEND((u32)append);
+
+	memset(&lp->cycles, 0, sizeof(lp->cycles));
+	lp->cycles.read = bfin_read_clock;
+	lp->cycles.mask = CLOCKSOURCE_MASK(64);
+	lp->cycles.mult = 1000000000 / PTP_CLK;
+	lp->cycles.shift = 0;
+
+	/* Synchronize our NIC clock against system wall clock */
+	memset(&lp->compare, 0, sizeof(lp->compare));
+	lp->compare.source = &lp->clock;
+	lp->compare.target = ktime_get_real;
+	lp->compare.num_samples = 10;
+
+	/* Initialize hwstamp config */
+	lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE;
+	lp->stamp_cfg.tx_type = HWTSTAMP_TX_OFF;
+}
+
+#else
+# define bfin_mac_hwtstamp_is_none(cfg) 0
+# define bfin_mac_hwtstamp_init(dev)
+# define bfin_mac_hwtstamp_ioctl(dev, ifr, cmd) (-EOPNOTSUPP)
+# define bfin_rx_hwtstamp(dev, skb)
+# define bfin_tx_hwtstamp(dev, skb)
+#endif
+
+static inline void _tx_reclaim_skb(void)
+{
+	do {
+		tx_list_head->desc_a.config &= ~DMAEN;
+		tx_list_head->status.status_word = 0;
+		if (tx_list_head->skb) {
+			dev_kfree_skb(tx_list_head->skb);
+			tx_list_head->skb = NULL;
+		}
+		tx_list_head = tx_list_head->next;
+
+	} while (tx_list_head->status.status_word != 0);
+}
+
+static void tx_reclaim_skb(struct bfin_mac_local *lp)
+{
+	int timeout_cnt = MAX_TIMEOUT_CNT;
+
+	if (tx_list_head->status.status_word != 0)
+		_tx_reclaim_skb();
+
+	if (current_tx_ptr->next == tx_list_head) {
+		while (tx_list_head->status.status_word == 0) {
+			/* slow down polling to avoid too many queue stop. */
+			udelay(10);
+			/* reclaim skb if DMA is not running. */
+			if (!(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN))
+				break;
+			if (timeout_cnt-- < 0)
+				break;
+		}
+
+		if (timeout_cnt >= 0)
+			_tx_reclaim_skb();
+		else
+			netif_stop_queue(lp->ndev);
+	}
+
+	if (current_tx_ptr->next != tx_list_head &&
+		netif_queue_stopped(lp->ndev))
+		netif_wake_queue(lp->ndev);
+
+	if (tx_list_head != current_tx_ptr) {
+		/* shorten the timer interval if tx queue is stopped */
+		if (netif_queue_stopped(lp->ndev))
+			lp->tx_reclaim_timer.expires =
+				jiffies + (TX_RECLAIM_JIFFIES >> 4);
+		else
+			lp->tx_reclaim_timer.expires =
+				jiffies + TX_RECLAIM_JIFFIES;
+
+		mod_timer(&lp->tx_reclaim_timer,
+			lp->tx_reclaim_timer.expires);
+	}
+
+	return;
+}
+
+static void tx_reclaim_skb_timeout(unsigned long lp)
+{
+	tx_reclaim_skb((struct bfin_mac_local *)lp);
+}
+
+static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
+				struct net_device *dev)
+{
+	struct bfin_mac_local *lp = netdev_priv(dev);
+	u16 *data;
+	u32 data_align = (unsigned long)(skb->data) & 0x3;
+
+	current_tx_ptr->skb = skb;
+
+	if (data_align == 0x2) {
+		/* move skb->data to current_tx_ptr payload */
+		data = (u16 *)(skb->data) - 1;
+		*data = (u16)(skb->len);
+		/*
+		 * When transmitting an Ethernet packet, the PTP_TSYNC module requires
+		 * a DMA_Length_Word field associated with the packet. The lower 12 bits
+		 * of this field are the length of the packet payload in bytes and the higher
+		 * 4 bits are the timestamping enable field.
+		 */
+		if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
+			*data |= 0x1000;
+
+		current_tx_ptr->desc_a.start_addr = (u32)data;
+		/* this is important! */
+		blackfin_dcache_flush_range((u32)data,
+				(u32)((u8 *)data + skb->len + 4));
+	} else {
+		*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
+		/* enable timestamping for the sent packet */
+		if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
+			*((u16 *)(current_tx_ptr->packet)) |= 0x1000;
+		memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
+			skb->len);
+		current_tx_ptr->desc_a.start_addr =
+			(u32)current_tx_ptr->packet;
+		blackfin_dcache_flush_range(
+			(u32)current_tx_ptr->packet,
+			(u32)(current_tx_ptr->packet + skb->len + 2));
+	}
+
+	/* make sure the internal data buffers in the core are drained
+	 * so that the DMA descriptors are completely written when the
+	 * DMA engine goes to fetch them below
+	 */
+	SSYNC();
+
+	/* always clear status buffer before start tx dma */
+	current_tx_ptr->status.status_word = 0;
+
+	/* enable this packet's dma */
+	current_tx_ptr->desc_a.config |= DMAEN;
+
+	/* tx dma is running, just return */
+	if (bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)
+		goto out;
+
+	/* tx dma is not running */
+	bfin_write_DMA2_NEXT_DESC_PTR(&(current_tx_ptr->desc_a));
+	/* dma enabled, read from memory, size is 6 */
+	bfin_write_DMA2_CONFIG(current_tx_ptr->desc_a.config);
+	/* Turn on the EMAC tx */
+	bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE);
+
+out:
+	bfin_tx_hwtstamp(dev, skb);
+
+	current_tx_ptr = current_tx_ptr->next;
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += (skb->len);
+
+	tx_reclaim_skb(lp);
+
+	return NETDEV_TX_OK;
+}
+
+#define IP_HEADER_OFF  0
+#define RX_ERROR_MASK (RX_LONG | RX_ALIGN | RX_CRC | RX_LEN | \
+	RX_FRAG | RX_ADDR | RX_DMAO | RX_PHY | RX_LATE | RX_RANGE)
+
+static void bfin_mac_rx(struct net_device *dev)
+{
+	struct sk_buff *skb, *new_skb;
+	unsigned short len;
+	struct bfin_mac_local *lp __maybe_unused = netdev_priv(dev);
+#if defined(BFIN_MAC_CSUM_OFFLOAD)
+	unsigned int i;
+	unsigned char fcs[ETH_FCS_LEN + 1];
+#endif
+
+	/* check if frame status word reports an error condition
+	 * we which case we simply drop the packet
+	 */
+	if (current_rx_ptr->status.status_word & RX_ERROR_MASK) {
+		netdev_notice(dev, "rx: receive error - packet dropped\n");
+		dev->stats.rx_dropped++;
+		goto out;
+	}
+
+	/* allocate a new skb for next time receive */
+	skb = current_rx_ptr->skb;
+
+	new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN);
+	if (!new_skb) {
+		netdev_notice(dev, "rx: low on mem - packet dropped\n");
+		dev->stats.rx_dropped++;
+		goto out;
+	}
+	/* reserve 2 bytes for RXDWA padding */
+	skb_reserve(new_skb, NET_IP_ALIGN);
+	/* Invidate the data cache of skb->data range when it is write back
+	 * cache. It will prevent overwritting the new data from DMA
+	 */
+	blackfin_dcache_invalidate_range((unsigned long)new_skb->head,
+					 (unsigned long)new_skb->end);
+
+	current_rx_ptr->skb = new_skb;
+	current_rx_ptr->desc_a.start_addr = (unsigned long)new_skb->data - 2;
+
+	len = (unsigned short)((current_rx_ptr->status.status_word) & RX_FRLEN);
+	/* Deduce Ethernet FCS length from Ethernet payload length */
+	len -= ETH_FCS_LEN;
+	skb_put(skb, len);
+
+	skb->protocol = eth_type_trans(skb, dev);
+
+	bfin_rx_hwtstamp(dev, skb);
+
+#if defined(BFIN_MAC_CSUM_OFFLOAD)
+	/* Checksum offloading only works for IPv4 packets with the standard IP header
+	 * length of 20 bytes, because the blackfin MAC checksum calculation is
+	 * based on that assumption. We must NOT use the calculated checksum if our
+	 * IP version or header break that assumption.
+	 */
+	if (skb->data[IP_HEADER_OFF] == 0x45) {
+		skb->csum = current_rx_ptr->status.ip_payload_csum;
+		/*
+		 * Deduce Ethernet FCS from hardware generated IP payload checksum.
+		 * IP checksum is based on 16-bit one's complement algorithm.
+		 * To deduce a value from checksum is equal to add its inversion.
+		 * If the IP payload len is odd, the inversed FCS should also
+		 * begin from odd address and leave first byte zero.
+		 */
+		if (skb->len % 2) {
+			fcs[0] = 0;
+			for (i = 0; i < ETH_FCS_LEN; i++)
+				fcs[i + 1] = ~skb->data[skb->len + i];
+			skb->csum = csum_partial(fcs, ETH_FCS_LEN + 1, skb->csum);
+		} else {
+			for (i = 0; i < ETH_FCS_LEN; i++)
+				fcs[i] = ~skb->data[skb->len + i];
+			skb->csum = csum_partial(fcs, ETH_FCS_LEN, skb->csum);
+		}
+		skb->ip_summed = CHECKSUM_COMPLETE;
+	}
+#endif
+
+	netif_rx(skb);
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += len;
+out:
+	current_rx_ptr->status.status_word = 0x00000000;
+	current_rx_ptr = current_rx_ptr->next;
+}
+
+/* interrupt routine to handle rx and error signal */
+static irqreturn_t bfin_mac_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	int number = 0;
+
+get_one_packet:
+	if (current_rx_ptr->status.status_word == 0) {
+		/* no more new packet received */
+		if (number == 0) {
+			if (current_rx_ptr->next->status.status_word != 0) {
+				current_rx_ptr = current_rx_ptr->next;
+				goto real_rx;
+			}
+		}
+		bfin_write_DMA1_IRQ_STATUS(bfin_read_DMA1_IRQ_STATUS() |
+					   DMA_DONE | DMA_ERR);
+		return IRQ_HANDLED;
+	}
+
+real_rx:
+	bfin_mac_rx(dev);
+	number++;
+	goto get_one_packet;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void bfin_mac_poll(struct net_device *dev)
+{
+	struct bfin_mac_local *lp = netdev_priv(dev);
+
+	disable_irq(IRQ_MAC_RX);
+	bfin_mac_interrupt(IRQ_MAC_RX, dev);
+	tx_reclaim_skb(lp);
+	enable_irq(IRQ_MAC_RX);
+}
+#endif				/* CONFIG_NET_POLL_CONTROLLER */
+
+static void bfin_mac_disable(void)
+{
+	unsigned int opmode;
+
+	opmode = bfin_read_EMAC_OPMODE();
+	opmode &= (~RE);
+	opmode &= (~TE);
+	/* Turn off the EMAC */
+	bfin_write_EMAC_OPMODE(opmode);
+}
+
+/*
+ * Enable Interrupts, Receive, and Transmit
+ */
+static int bfin_mac_enable(struct phy_device *phydev)
+{
+	int ret;
+	u32 opmode;
+
+	pr_debug("%s\n", __func__);
+
+	/* Set RX DMA */
+	bfin_write_DMA1_NEXT_DESC_PTR(&(rx_list_head->desc_a));
+	bfin_write_DMA1_CONFIG(rx_list_head->desc_a.config);
+
+	/* Wait MII done */
+	ret = bfin_mdio_poll();
+	if (ret)
+		return ret;
+
+	/* We enable only RX here */
+	/* ASTP   : Enable Automatic Pad Stripping
+	   PR     : Promiscuous Mode for test
+	   PSF    : Receive frames with total length less than 64 bytes.
+	   FDMODE : Full Duplex Mode
+	   LB     : Internal Loopback for test
+	   RE     : Receiver Enable */
+	opmode = bfin_read_EMAC_OPMODE();
+	if (opmode & FDMODE)
+		opmode |= PSF;
+	else
+		opmode |= DRO | DC | PSF;
+	opmode |= RE;
+
+	if (phydev->interface == PHY_INTERFACE_MODE_RMII) {
+		opmode |= RMII; /* For Now only 100MBit are supported */
+#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
+	}
+
+	/* Turn on the EMAC rx */
+	bfin_write_EMAC_OPMODE(opmode);
+
+	return 0;
+}
+
+/* Our watchdog timed out. Called by the networking layer */
+static void bfin_mac_timeout(struct net_device *dev)
+{
+	struct bfin_mac_local *lp = netdev_priv(dev);
+
+	pr_debug("%s: %s\n", dev->name, __func__);
+
+	bfin_mac_disable();
+
+	del_timer(&lp->tx_reclaim_timer);
+
+	/* reset tx queue and free skb */
+	while (tx_list_head != current_tx_ptr) {
+		tx_list_head->desc_a.config &= ~DMAEN;
+		tx_list_head->status.status_word = 0;
+		if (tx_list_head->skb) {
+			dev_kfree_skb(tx_list_head->skb);
+			tx_list_head->skb = NULL;
+		}
+		tx_list_head = tx_list_head->next;
+	}
+
+	if (netif_queue_stopped(lp->ndev))
+		netif_wake_queue(lp->ndev);
+
+	bfin_mac_enable(lp->phydev);
+
+	/* We can accept TX packets again */
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	netif_wake_queue(dev);
+}
+
+static void bfin_mac_multicast_hash(struct net_device *dev)
+{
+	u32 emac_hashhi, emac_hashlo;
+	struct netdev_hw_addr *ha;
+	u32 crc;
+
+	emac_hashhi = emac_hashlo = 0;
+
+	netdev_for_each_mc_addr(ha, dev) {
+		crc = ether_crc(ETH_ALEN, ha->addr);
+		crc >>= 26;
+
+		if (crc & 0x20)
+			emac_hashhi |= 1 << (crc & 0x1f);
+		else
+			emac_hashlo |= 1 << (crc & 0x1f);
+	}
+
+	bfin_write_EMAC_HASHHI(emac_hashhi);
+	bfin_write_EMAC_HASHLO(emac_hashlo);
+}
+
+/*
+ * This routine will, depending on the values passed to it,
+ * either make it accept multicast packets, go into
+ * promiscuous mode (for TCPDUMP and cousins) or accept
+ * a select set of multicast packets
+ */
+static void bfin_mac_set_multicast_list(struct net_device *dev)
+{
+	u32 sysctl;
+
+	if (dev->flags & IFF_PROMISC) {
+		netdev_info(dev, "set promisc mode\n");
+		sysctl = bfin_read_EMAC_OPMODE();
+		sysctl |= PR;
+		bfin_write_EMAC_OPMODE(sysctl);
+	} else if (dev->flags & IFF_ALLMULTI) {
+		/* accept all multicast */
+		sysctl = bfin_read_EMAC_OPMODE();
+		sysctl |= PAM;
+		bfin_write_EMAC_OPMODE(sysctl);
+	} else if (!netdev_mc_empty(dev)) {
+		/* set up multicast hash table */
+		sysctl = bfin_read_EMAC_OPMODE();
+		sysctl |= HM;
+		bfin_write_EMAC_OPMODE(sysctl);
+		bfin_mac_multicast_hash(dev);
+	} else {
+		/* clear promisc or multicast mode */
+		sysctl = bfin_read_EMAC_OPMODE();
+		sysctl &= ~(RAF | PAM);
+		bfin_write_EMAC_OPMODE(sysctl);
+	}
+}
+
+static int bfin_mac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	struct bfin_mac_local *lp = netdev_priv(netdev);
+
+	if (!netif_running(netdev))
+		return -EINVAL;
+
+	switch (cmd) {
+	case SIOCSHWTSTAMP:
+		return bfin_mac_hwtstamp_ioctl(netdev, ifr, cmd);
+	default:
+		if (lp->phydev)
+			return phy_mii_ioctl(lp->phydev, ifr, cmd);
+		else
+			return -EOPNOTSUPP;
+	}
+}
+
+/*
+ * this puts the device in an inactive state
+ */
+static void bfin_mac_shutdown(struct net_device *dev)
+{
+	/* Turn off the EMAC */
+	bfin_write_EMAC_OPMODE(0x00000000);
+	/* Turn off the EMAC RX DMA */
+	bfin_write_DMA1_CONFIG(0x0000);
+	bfin_write_DMA2_CONFIG(0x0000);
+}
+
+/*
+ * Open and Initialize the interface
+ *
+ * Set up everything, reset the card, etc..
+ */
+static int bfin_mac_open(struct net_device *dev)
+{
+	struct bfin_mac_local *lp = netdev_priv(dev);
+	int ret;
+	pr_debug("%s: %s\n", dev->name, __func__);
+
+	/*
+	 * Check that the address is valid.  If its not, refuse
+	 * to bring the device up.  The user must specify an
+	 * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
+	 */
+	if (!is_valid_ether_addr(dev->dev_addr)) {
+		netdev_warn(dev, "no valid ethernet hw addr\n");
+		return -EINVAL;
+	}
+
+	/* initial rx and tx list */
+	ret = desc_list_init();
+	if (ret)
+		return ret;
+
+	phy_start(lp->phydev);
+	phy_write(lp->phydev, MII_BMCR, BMCR_RESET);
+	setup_system_regs(dev);
+	setup_mac_addr(dev->dev_addr);
+
+	bfin_mac_disable();
+	ret = bfin_mac_enable(lp->phydev);
+	if (ret)
+		return ret;
+	pr_debug("hardware init finished\n");
+
+	netif_start_queue(dev);
+	netif_carrier_on(dev);
+
+	return 0;
+}
+
+/*
+ * this makes the board clean up everything that it can
+ * and not talk to the outside world.   Caused by
+ * an 'ifconfig ethX down'
+ */
+static int bfin_mac_close(struct net_device *dev)
+{
+	struct bfin_mac_local *lp = netdev_priv(dev);
+	pr_debug("%s: %s\n", dev->name, __func__);
+
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+
+	phy_stop(lp->phydev);
+	phy_write(lp->phydev, MII_BMCR, BMCR_PDOWN);
+
+	/* clear everything */
+	bfin_mac_shutdown(dev);
+
+	/* free the rx/tx buffers */
+	desc_list_free();
+
+	return 0;
+}
+
+static const struct net_device_ops bfin_mac_netdev_ops = {
+	.ndo_open		= bfin_mac_open,
+	.ndo_stop		= bfin_mac_close,
+	.ndo_start_xmit		= bfin_mac_hard_start_xmit,
+	.ndo_set_mac_address	= bfin_mac_set_mac_address,
+	.ndo_tx_timeout		= bfin_mac_timeout,
+	.ndo_set_rx_mode	= bfin_mac_set_multicast_list,
+	.ndo_do_ioctl           = bfin_mac_ioctl,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_change_mtu		= eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= bfin_mac_poll,
+#endif
+};
+
+static int __devinit bfin_mac_probe(struct platform_device *pdev)
+{
+	struct net_device *ndev;
+	struct bfin_mac_local *lp;
+	struct platform_device *pd;
+	struct bfin_mii_bus_platform_data *mii_bus_data;
+	int rc;
+
+	ndev = alloc_etherdev(sizeof(struct bfin_mac_local));
+	if (!ndev) {
+		dev_err(&pdev->dev, "Cannot allocate net device!\n");
+		return -ENOMEM;
+	}
+
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+	platform_set_drvdata(pdev, ndev);
+	lp = netdev_priv(ndev);
+	lp->ndev = ndev;
+
+	/* Grab the MAC address in the MAC */
+	*(__le32 *) (&(ndev->dev_addr[0])) = cpu_to_le32(bfin_read_EMAC_ADDRLO());
+	*(__le16 *) (&(ndev->dev_addr[4])) = cpu_to_le16((u16) bfin_read_EMAC_ADDRHI());
+
+	/* probe mac */
+	/*todo: how to proble? which is revision_register */
+	bfin_write_EMAC_ADDRLO(0x12345678);
+	if (bfin_read_EMAC_ADDRLO() != 0x12345678) {
+		dev_err(&pdev->dev, "Cannot detect Blackfin on-chip ethernet MAC controller!\n");
+		rc = -ENODEV;
+		goto out_err_probe_mac;
+	}
+
+
+	/*
+	 * Is it valid? (Did bootloader initialize it?)
+	 * Grab the MAC from the board somehow
+	 * this is done in the arch/blackfin/mach-bfxxx/boards/eth_mac.c
+	 */
+	if (!is_valid_ether_addr(ndev->dev_addr))
+		bfin_get_ether_addr(ndev->dev_addr);
+
+	/* If still not valid, get a random one */
+	if (!is_valid_ether_addr(ndev->dev_addr))
+		random_ether_addr(ndev->dev_addr);
+
+	setup_mac_addr(ndev->dev_addr);
+
+	if (!pdev->dev.platform_data) {
+		dev_err(&pdev->dev, "Cannot get platform device bfin_mii_bus!\n");
+		rc = -ENODEV;
+		goto out_err_probe_mac;
+	}
+	pd = pdev->dev.platform_data;
+	lp->mii_bus = platform_get_drvdata(pd);
+	if (!lp->mii_bus) {
+		dev_err(&pdev->dev, "Cannot get mii_bus!\n");
+		rc = -ENODEV;
+		goto out_err_probe_mac;
+	}
+	lp->mii_bus->priv = ndev;
+	mii_bus_data = pd->dev.platform_data;
+
+	rc = mii_probe(ndev, mii_bus_data->phy_mode);
+	if (rc) {
+		dev_err(&pdev->dev, "MII Probe failed!\n");
+		goto out_err_mii_probe;
+	}
+
+	lp->vlan1_mask = ETH_P_8021Q | mii_bus_data->vlan1_mask;
+	lp->vlan2_mask = ETH_P_8021Q | mii_bus_data->vlan2_mask;
+
+	/* Fill in the fields of the device structure with ethernet values. */
+	ether_setup(ndev);
+
+	ndev->netdev_ops = &bfin_mac_netdev_ops;
+	ndev->ethtool_ops = &bfin_mac_ethtool_ops;
+
+	init_timer(&lp->tx_reclaim_timer);
+	lp->tx_reclaim_timer.data = (unsigned long)lp;
+	lp->tx_reclaim_timer.function = tx_reclaim_skb_timeout;
+
+	spin_lock_init(&lp->lock);
+
+	/* now, enable interrupts */
+	/* register irq handler */
+	rc = request_irq(IRQ_MAC_RX, bfin_mac_interrupt,
+			IRQF_DISABLED, "EMAC_RX", ndev);
+	if (rc) {
+		dev_err(&pdev->dev, "Cannot request Blackfin MAC RX IRQ!\n");
+		rc = -EBUSY;
+		goto out_err_request_irq;
+	}
+
+	rc = register_netdev(ndev);
+	if (rc) {
+		dev_err(&pdev->dev, "Cannot register net device!\n");
+		goto out_err_reg_ndev;
+	}
+
+	bfin_mac_hwtstamp_init(ndev);
+
+	/* now, print out the card info, in a short format.. */
+	netdev_info(ndev, "%s, Version %s\n", DRV_DESC, DRV_VERSION);
+
+	return 0;
+
+out_err_reg_ndev:
+	free_irq(IRQ_MAC_RX, ndev);
+out_err_request_irq:
+out_err_mii_probe:
+	mdiobus_unregister(lp->mii_bus);
+	mdiobus_free(lp->mii_bus);
+out_err_probe_mac:
+	platform_set_drvdata(pdev, NULL);
+	free_netdev(ndev);
+
+	return rc;
+}
+
+static int __devexit bfin_mac_remove(struct platform_device *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct bfin_mac_local *lp = netdev_priv(ndev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	lp->mii_bus->priv = NULL;
+
+	unregister_netdev(ndev);
+
+	free_irq(IRQ_MAC_RX, ndev);
+
+	free_netdev(ndev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_mac_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	struct net_device *net_dev = platform_get_drvdata(pdev);
+	struct bfin_mac_local *lp = netdev_priv(net_dev);
+
+	if (lp->wol) {
+		bfin_write_EMAC_OPMODE((bfin_read_EMAC_OPMODE() & ~TE) | RE);
+		bfin_write_EMAC_WKUP_CTL(MPKE);
+		enable_irq_wake(IRQ_MAC_WAKEDET);
+	} else {
+		if (netif_running(net_dev))
+			bfin_mac_close(net_dev);
+	}
+
+	return 0;
+}
+
+static int bfin_mac_resume(struct platform_device *pdev)
+{
+	struct net_device *net_dev = platform_get_drvdata(pdev);
+	struct bfin_mac_local *lp = netdev_priv(net_dev);
+
+	if (lp->wol) {
+		bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE);
+		bfin_write_EMAC_WKUP_CTL(0);
+		disable_irq_wake(IRQ_MAC_WAKEDET);
+	} else {
+		if (netif_running(net_dev))
+			bfin_mac_open(net_dev);
+	}
+
+	return 0;
+}
+#else
+#define bfin_mac_suspend NULL
+#define bfin_mac_resume NULL
+#endif	/* CONFIG_PM */
+
+static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
+{
+	struct mii_bus *miibus;
+	struct bfin_mii_bus_platform_data *mii_bus_pd;
+	const unsigned short *pin_req;
+	int rc, i;
+
+	mii_bus_pd = dev_get_platdata(&pdev->dev);
+	if (!mii_bus_pd) {
+		dev_err(&pdev->dev, "No peripherals in platform data!\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * We are setting up a network card,
+	 * so set the GPIO pins to Ethernet mode
+	 */
+	pin_req = mii_bus_pd->mac_peripherals;
+	rc = peripheral_request_list(pin_req, KBUILD_MODNAME);
+	if (rc) {
+		dev_err(&pdev->dev, "Requesting peripherals failed!\n");
+		return rc;
+	}
+
+	rc = -ENOMEM;
+	miibus = mdiobus_alloc();
+	if (miibus == NULL)
+		goto out_err_alloc;
+	miibus->read = bfin_mdiobus_read;
+	miibus->write = bfin_mdiobus_write;
+	miibus->reset = bfin_mdiobus_reset;
+
+	miibus->parent = &pdev->dev;
+	miibus->name = "bfin_mii_bus";
+	miibus->phy_mask = mii_bus_pd->phy_mask;
+
+	snprintf(miibus->id, MII_BUS_ID_SIZE, "0");
+	miibus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+	if (!miibus->irq)
+		goto out_err_irq_alloc;
+
+	for (i = rc; i < PHY_MAX_ADDR; ++i)
+		miibus->irq[i] = PHY_POLL;
+
+	rc = clamp(mii_bus_pd->phydev_number, 0, PHY_MAX_ADDR);
+	if (rc != mii_bus_pd->phydev_number)
+		dev_err(&pdev->dev, "Invalid number (%i) of phydevs\n",
+			mii_bus_pd->phydev_number);
+	for (i = 0; i < rc; ++i) {
+		unsigned short phyaddr = mii_bus_pd->phydev_data[i].addr;
+		if (phyaddr < PHY_MAX_ADDR)
+			miibus->irq[phyaddr] = mii_bus_pd->phydev_data[i].irq;
+		else
+			dev_err(&pdev->dev,
+				"Invalid PHY address %i for phydev %i\n",
+				phyaddr, i);
+	}
+
+	rc = mdiobus_register(miibus);
+	if (rc) {
+		dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
+		goto out_err_mdiobus_register;
+	}
+
+	platform_set_drvdata(pdev, miibus);
+	return 0;
+
+out_err_mdiobus_register:
+	kfree(miibus->irq);
+out_err_irq_alloc:
+	mdiobus_free(miibus);
+out_err_alloc:
+	peripheral_free_list(pin_req);
+
+	return rc;
+}
+
+static int __devexit bfin_mii_bus_remove(struct platform_device *pdev)
+{
+	struct mii_bus *miibus = platform_get_drvdata(pdev);
+	struct bfin_mii_bus_platform_data *mii_bus_pd =
+		dev_get_platdata(&pdev->dev);
+
+	platform_set_drvdata(pdev, NULL);
+	mdiobus_unregister(miibus);
+	kfree(miibus->irq);
+	mdiobus_free(miibus);
+	peripheral_free_list(mii_bus_pd->mac_peripherals);
+
+	return 0;
+}
+
+static struct platform_driver bfin_mii_bus_driver = {
+	.probe = bfin_mii_bus_probe,
+	.remove = __devexit_p(bfin_mii_bus_remove),
+	.driver = {
+		.name = "bfin_mii_bus",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static struct platform_driver bfin_mac_driver = {
+	.probe = bfin_mac_probe,
+	.remove = __devexit_p(bfin_mac_remove),
+	.resume = bfin_mac_resume,
+	.suspend = bfin_mac_suspend,
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init bfin_mac_init(void)
+{
+	int ret;
+	ret = platform_driver_register(&bfin_mii_bus_driver);
+	if (!ret)
+		return platform_driver_register(&bfin_mac_driver);
+	return -ENODEV;
+}
+
+module_init(bfin_mac_init);
+
+static void __exit bfin_mac_cleanup(void)
+{
+	platform_driver_unregister(&bfin_mac_driver);
+	platform_driver_unregister(&bfin_mii_bus_driver);
+}
+
+module_exit(bfin_mac_cleanup);
+
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/adi/bfin_mac.h linux-libre-3.2-gnu/drivers/net/ethernet/adi/bfin_mac.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/adi/bfin_mac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/adi/bfin_mac.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,106 @@
+/*
+ * Blackfin On-Chip MAC Driver
+ *
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+#ifndef _BFIN_MAC_H_
+#define _BFIN_MAC_H_
+
+#include <linux/net_tstamp.h>
+#include <linux/clocksource.h>
+#include <linux/timecompare.h>
+#include <linux/timer.h>
+#include <linux/etherdevice.h>
+#include <linux/bfin_mac.h>
+
+/*
+ * Disable hardware checksum for bug #5600 if writeback cache is
+ * enabled. Otherwize, corrupted RX packet will be sent up stack
+ * without error mark.
+ */
+#ifndef CONFIG_BFIN_EXTMEM_WRITEBACK
+#define BFIN_MAC_CSUM_OFFLOAD
+#endif
+
+#define TX_RECLAIM_JIFFIES (HZ / 5)
+
+struct dma_descriptor {
+	struct dma_descriptor *next_dma_desc;
+	unsigned long start_addr;
+	unsigned short config;
+	unsigned short x_count;
+};
+
+struct status_area_rx {
+#if defined(BFIN_MAC_CSUM_OFFLOAD)
+	unsigned short ip_hdr_csum;	/* ip header checksum */
+	/* ip payload(udp or tcp or others) checksum */
+	unsigned short ip_payload_csum;
+#endif
+	unsigned long status_word;	/* the frame status word */
+};
+
+struct status_area_tx {
+	unsigned long status_word;	/* the frame status word */
+};
+
+/* use two descriptors for a packet */
+struct net_dma_desc_rx {
+	struct net_dma_desc_rx *next;
+	struct sk_buff *skb;
+	struct dma_descriptor desc_a;
+	struct dma_descriptor desc_b;
+	struct status_area_rx status;
+};
+
+/* use two descriptors for a packet */
+struct net_dma_desc_tx {
+	struct net_dma_desc_tx *next;
+	struct sk_buff *skb;
+	struct dma_descriptor desc_a;
+	struct dma_descriptor desc_b;
+	unsigned char packet[1560];
+	struct status_area_tx status;
+};
+
+struct bfin_mac_local {
+	/*
+	 * these are things that the kernel wants me to keep, so users
+	 * can find out semi-useless statistics of how well the card is
+	 * performing
+	 */
+	struct net_device_stats stats;
+
+	spinlock_t lock;
+
+	int wol;		/* Wake On Lan */
+	int irq_wake_requested;
+	struct timer_list tx_reclaim_timer;
+	struct net_device *ndev;
+
+	/* Data for EMAC_VLAN1 regs */
+	u16 vlan1_mask, vlan2_mask;
+
+	/* MII and PHY stuffs */
+	int old_link;          /* used by bf537_adjust_link */
+	int old_speed;
+	int old_duplex;
+
+	struct phy_device *phydev;
+	struct mii_bus *mii_bus;
+
+#if defined(CONFIG_BFIN_MAC_USE_HWSTAMP)
+	struct cyclecounter cycles;
+	struct timecounter clock;
+	struct timecompare compare;
+	struct hwtstamp_config stamp_cfg;
+#endif
+};
+
+extern void bfin_get_ether_addr(char *addr);
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/adi/Kconfig linux-libre-3.2-gnu/drivers/net/ethernet/adi/Kconfig
--- linux-libre-3.1-gnu/drivers/net/ethernet/adi/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/adi/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,69 @@
+#
+# Blackfin device configuration
+#
+
+config NET_BFIN
+	bool "Blackfin devices"
+	depends on BF516 || BF518 || BF526 || BF527 || BF536 || BF537
+	---help---
+	  If you have a network (Ethernet) card belonging to this class, say Y.
+	  Make sure you know the name of your card. Read the Ethernet-HOWTO,
+	  available from <http://www.tldp.org/docs.html#howto>.
+
+	  If unsure, say Y.
+
+	  Note that the answer to this question doesn't directly affect the
+	  kernel: saying N will just cause the configurator to skip all
+	  the remaining Blackfin card questions. If you say Y, you will be
+	  asked for your specific card in the following questions.
+
+if NET_BFIN
+
+config BFIN_MAC
+	tristate "Blackfin on-chip MAC support"
+	depends on (BF516 || BF518 || BF526 || BF527 || BF536 || BF537)
+	select CRC32
+	select NET_CORE
+	select MII
+	select PHYLIB
+	select BFIN_MAC_USE_L1 if DMA_UNCACHED_NONE
+	---help---
+	  This is the driver for Blackfin on-chip mac device. Say Y if you want
+	  it compiled into the kernel. This driver is also available as a
+	  module ( = code which can be inserted in and removed from the running
+	  kernel whenever you want). The module will be called bfin_mac.
+
+config BFIN_MAC_USE_L1
+	bool "Use L1 memory for rx/tx packets"
+	depends on BFIN_MAC && (BF527 || BF537)
+	default y
+	---help---
+	  To get maximum network performance, you should use L1 memory as rx/tx
+	  buffers. Say N here if you want to reserve L1 memory for other uses.
+
+config BFIN_TX_DESC_NUM
+	int "Number of transmit buffer packets"
+	depends on BFIN_MAC
+	range 6 10 if BFIN_MAC_USE_L1
+	range 10 100
+	default "10"
+	---help---
+	  Set the number of buffer packets used in driver.
+
+config BFIN_RX_DESC_NUM
+	int "Number of receive buffer packets"
+	depends on BFIN_MAC
+	range 20 100 if BFIN_MAC_USE_L1
+	range 20 800
+	default "20"
+	---help---
+	  Set the number of buffer packets used in driver.
+
+config BFIN_MAC_USE_HWSTAMP
+	bool "Use IEEE 1588 hwstamp"
+	depends on BFIN_MAC && BF518
+	default y
+	---help---
+	  To support the IEEE 1588 Precision Time Protocol (PTP), select y here
+
+endif # NET_BFIN
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/adi/Makefile linux-libre-3.2-gnu/drivers/net/ethernet/adi/Makefile
--- linux-libre-3.1-gnu/drivers/net/ethernet/adi/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/adi/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+#
+# Makefile for the Blackfin device drivers.
+#
+
+obj-$(CONFIG_BFIN_MAC) += bfin_mac.o
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/aeroflex/greth.c linux-libre-3.2-gnu/drivers/net/ethernet/aeroflex/greth.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/aeroflex/greth.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/aeroflex/greth.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1641 @@
+/*
+ * Aeroflex Gaisler GRETH 10/100/1G Ethernet MAC.
+ *
+ * 2005-2010 (c) Aeroflex Gaisler AB
+ *
+ * This driver supports GRETH 10/100 and GRETH 10/100/1G Ethernet MACs
+ * available in the GRLIB VHDL IP core library.
+ *
+ * Full documentation of both cores can be found here:
+ * http://www.gaisler.com/products/grlib/grip.pdf
+ *
+ * The Gigabit version supports scatter/gather DMA, any alignment of
+ * buffers and checksum offloading.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Contributors: Kristoffer Glembo
+ *               Daniel Hellstrom
+ *               Marko Isomaki
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/io.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <asm/cacheflush.h>
+#include <asm/byteorder.h>
+
+#ifdef CONFIG_SPARC
+#include <asm/idprom.h>
+#endif
+
+#include "greth.h"
+
+#define GRETH_DEF_MSG_ENABLE	  \
+	(NETIF_MSG_DRV		| \
+	 NETIF_MSG_PROBE	| \
+	 NETIF_MSG_LINK		| \
+	 NETIF_MSG_IFDOWN	| \
+	 NETIF_MSG_IFUP		| \
+	 NETIF_MSG_RX_ERR	| \
+	 NETIF_MSG_TX_ERR)
+
+static int greth_debug = -1;	/* -1 == use GRETH_DEF_MSG_ENABLE as value */
+module_param(greth_debug, int, 0);
+MODULE_PARM_DESC(greth_debug, "GRETH bitmapped debugging message enable value");
+
+/* Accept MAC address of the form macaddr=0x08,0x00,0x20,0x30,0x40,0x50 */
+static int macaddr[6];
+module_param_array(macaddr, int, NULL, 0);
+MODULE_PARM_DESC(macaddr, "GRETH Ethernet MAC address");
+
+static int greth_edcl = 1;
+module_param(greth_edcl, int, 0);
+MODULE_PARM_DESC(greth_edcl, "GRETH EDCL usage indicator. Set to 1 if EDCL is used.");
+
+static int greth_open(struct net_device *dev);
+static netdev_tx_t greth_start_xmit(struct sk_buff *skb,
+	   struct net_device *dev);
+static netdev_tx_t greth_start_xmit_gbit(struct sk_buff *skb,
+	   struct net_device *dev);
+static int greth_rx(struct net_device *dev, int limit);
+static int greth_rx_gbit(struct net_device *dev, int limit);
+static void greth_clean_tx(struct net_device *dev);
+static void greth_clean_tx_gbit(struct net_device *dev);
+static irqreturn_t greth_interrupt(int irq, void *dev_id);
+static int greth_close(struct net_device *dev);
+static int greth_set_mac_add(struct net_device *dev, void *p);
+static void greth_set_multicast_list(struct net_device *dev);
+
+#define GRETH_REGLOAD(a)	    (be32_to_cpu(__raw_readl(&(a))))
+#define GRETH_REGSAVE(a, v)         (__raw_writel(cpu_to_be32(v), &(a)))
+#define GRETH_REGORIN(a, v)         (GRETH_REGSAVE(a, (GRETH_REGLOAD(a) | (v))))
+#define GRETH_REGANDIN(a, v)        (GRETH_REGSAVE(a, (GRETH_REGLOAD(a) & (v))))
+
+#define NEXT_TX(N)      (((N) + 1) & GRETH_TXBD_NUM_MASK)
+#define SKIP_TX(N, C)   (((N) + C) & GRETH_TXBD_NUM_MASK)
+#define NEXT_RX(N)      (((N) + 1) & GRETH_RXBD_NUM_MASK)
+
+static void greth_print_rx_packet(void *addr, int len)
+{
+	print_hex_dump(KERN_DEBUG, "RX: ", DUMP_PREFIX_OFFSET, 16, 1,
+			addr, len, true);
+}
+
+static void greth_print_tx_packet(struct sk_buff *skb)
+{
+	int i;
+	int length;
+
+	if (skb_shinfo(skb)->nr_frags == 0)
+		length = skb->len;
+	else
+		length = skb_headlen(skb);
+
+	print_hex_dump(KERN_DEBUG, "TX: ", DUMP_PREFIX_OFFSET, 16, 1,
+			skb->data, length, true);
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+
+		print_hex_dump(KERN_DEBUG, "TX: ", DUMP_PREFIX_OFFSET, 16, 1,
+			       skb_frag_address(&skb_shinfo(skb)->frags[i]),
+			       skb_shinfo(skb)->frags[i].size, true);
+	}
+}
+
+static inline void greth_enable_tx(struct greth_private *greth)
+{
+	wmb();
+	GRETH_REGORIN(greth->regs->control, GRETH_TXEN);
+}
+
+static inline void greth_disable_tx(struct greth_private *greth)
+{
+	GRETH_REGANDIN(greth->regs->control, ~GRETH_TXEN);
+}
+
+static inline void greth_enable_rx(struct greth_private *greth)
+{
+	wmb();
+	GRETH_REGORIN(greth->regs->control, GRETH_RXEN);
+}
+
+static inline void greth_disable_rx(struct greth_private *greth)
+{
+	GRETH_REGANDIN(greth->regs->control, ~GRETH_RXEN);
+}
+
+static inline void greth_enable_irqs(struct greth_private *greth)
+{
+	GRETH_REGORIN(greth->regs->control, GRETH_RXI | GRETH_TXI);
+}
+
+static inline void greth_disable_irqs(struct greth_private *greth)
+{
+	GRETH_REGANDIN(greth->regs->control, ~(GRETH_RXI|GRETH_TXI));
+}
+
+static inline void greth_write_bd(u32 *bd, u32 val)
+{
+	__raw_writel(cpu_to_be32(val), bd);
+}
+
+static inline u32 greth_read_bd(u32 *bd)
+{
+	return be32_to_cpu(__raw_readl(bd));
+}
+
+static void greth_clean_rings(struct greth_private *greth)
+{
+	int i;
+	struct greth_bd *rx_bdp = greth->rx_bd_base;
+	struct greth_bd *tx_bdp = greth->tx_bd_base;
+
+	if (greth->gbit_mac) {
+
+		/* Free and unmap RX buffers */
+		for (i = 0; i < GRETH_RXBD_NUM; i++, rx_bdp++) {
+			if (greth->rx_skbuff[i] != NULL) {
+				dev_kfree_skb(greth->rx_skbuff[i]);
+				dma_unmap_single(greth->dev,
+						 greth_read_bd(&rx_bdp->addr),
+						 MAX_FRAME_SIZE+NET_IP_ALIGN,
+						 DMA_FROM_DEVICE);
+			}
+		}
+
+		/* TX buffers */
+		while (greth->tx_free < GRETH_TXBD_NUM) {
+
+			struct sk_buff *skb = greth->tx_skbuff[greth->tx_last];
+			int nr_frags = skb_shinfo(skb)->nr_frags;
+			tx_bdp = greth->tx_bd_base + greth->tx_last;
+			greth->tx_last = NEXT_TX(greth->tx_last);
+
+			dma_unmap_single(greth->dev,
+					 greth_read_bd(&tx_bdp->addr),
+					 skb_headlen(skb),
+					 DMA_TO_DEVICE);
+
+			for (i = 0; i < nr_frags; i++) {
+				skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+				tx_bdp = greth->tx_bd_base + greth->tx_last;
+
+				dma_unmap_page(greth->dev,
+					       greth_read_bd(&tx_bdp->addr),
+					       skb_frag_size(frag),
+					       DMA_TO_DEVICE);
+
+				greth->tx_last = NEXT_TX(greth->tx_last);
+			}
+			greth->tx_free += nr_frags+1;
+			dev_kfree_skb(skb);
+		}
+
+
+	} else { /* 10/100 Mbps MAC */
+
+		for (i = 0; i < GRETH_RXBD_NUM; i++, rx_bdp++) {
+			kfree(greth->rx_bufs[i]);
+			dma_unmap_single(greth->dev,
+					 greth_read_bd(&rx_bdp->addr),
+					 MAX_FRAME_SIZE,
+					 DMA_FROM_DEVICE);
+		}
+		for (i = 0; i < GRETH_TXBD_NUM; i++, tx_bdp++) {
+			kfree(greth->tx_bufs[i]);
+			dma_unmap_single(greth->dev,
+					 greth_read_bd(&tx_bdp->addr),
+					 MAX_FRAME_SIZE,
+					 DMA_TO_DEVICE);
+		}
+	}
+}
+
+static int greth_init_rings(struct greth_private *greth)
+{
+	struct sk_buff *skb;
+	struct greth_bd *rx_bd, *tx_bd;
+	u32 dma_addr;
+	int i;
+
+	rx_bd = greth->rx_bd_base;
+	tx_bd = greth->tx_bd_base;
+
+	/* Initialize descriptor rings and buffers */
+	if (greth->gbit_mac) {
+
+		for (i = 0; i < GRETH_RXBD_NUM; i++) {
+			skb = netdev_alloc_skb(greth->netdev, MAX_FRAME_SIZE+NET_IP_ALIGN);
+			if (skb == NULL) {
+				if (netif_msg_ifup(greth))
+					dev_err(greth->dev, "Error allocating DMA ring.\n");
+				goto cleanup;
+			}
+			skb_reserve(skb, NET_IP_ALIGN);
+			dma_addr = dma_map_single(greth->dev,
+						  skb->data,
+						  MAX_FRAME_SIZE+NET_IP_ALIGN,
+						  DMA_FROM_DEVICE);
+
+			if (dma_mapping_error(greth->dev, dma_addr)) {
+				if (netif_msg_ifup(greth))
+					dev_err(greth->dev, "Could not create initial DMA mapping\n");
+				goto cleanup;
+			}
+			greth->rx_skbuff[i] = skb;
+			greth_write_bd(&rx_bd[i].addr, dma_addr);
+			greth_write_bd(&rx_bd[i].stat, GRETH_BD_EN | GRETH_BD_IE);
+		}
+
+	} else {
+
+		/* 10/100 MAC uses a fixed set of buffers and copy to/from SKBs */
+		for (i = 0; i < GRETH_RXBD_NUM; i++) {
+
+			greth->rx_bufs[i] = kmalloc(MAX_FRAME_SIZE, GFP_KERNEL);
+
+			if (greth->rx_bufs[i] == NULL) {
+				if (netif_msg_ifup(greth))
+					dev_err(greth->dev, "Error allocating DMA ring.\n");
+				goto cleanup;
+			}
+
+			dma_addr = dma_map_single(greth->dev,
+						  greth->rx_bufs[i],
+						  MAX_FRAME_SIZE,
+						  DMA_FROM_DEVICE);
+
+			if (dma_mapping_error(greth->dev, dma_addr)) {
+				if (netif_msg_ifup(greth))
+					dev_err(greth->dev, "Could not create initial DMA mapping\n");
+				goto cleanup;
+			}
+			greth_write_bd(&rx_bd[i].addr, dma_addr);
+			greth_write_bd(&rx_bd[i].stat, GRETH_BD_EN | GRETH_BD_IE);
+		}
+		for (i = 0; i < GRETH_TXBD_NUM; i++) {
+
+			greth->tx_bufs[i] = kmalloc(MAX_FRAME_SIZE, GFP_KERNEL);
+
+			if (greth->tx_bufs[i] == NULL) {
+				if (netif_msg_ifup(greth))
+					dev_err(greth->dev, "Error allocating DMA ring.\n");
+				goto cleanup;
+			}
+
+			dma_addr = dma_map_single(greth->dev,
+						  greth->tx_bufs[i],
+						  MAX_FRAME_SIZE,
+						  DMA_TO_DEVICE);
+
+			if (dma_mapping_error(greth->dev, dma_addr)) {
+				if (netif_msg_ifup(greth))
+					dev_err(greth->dev, "Could not create initial DMA mapping\n");
+				goto cleanup;
+			}
+			greth_write_bd(&tx_bd[i].addr, dma_addr);
+			greth_write_bd(&tx_bd[i].stat, 0);
+		}
+	}
+	greth_write_bd(&rx_bd[GRETH_RXBD_NUM - 1].stat,
+		       greth_read_bd(&rx_bd[GRETH_RXBD_NUM - 1].stat) | GRETH_BD_WR);
+
+	/* Initialize pointers. */
+	greth->rx_cur = 0;
+	greth->tx_next = 0;
+	greth->tx_last = 0;
+	greth->tx_free = GRETH_TXBD_NUM;
+
+	/* Initialize descriptor base address */
+	GRETH_REGSAVE(greth->regs->tx_desc_p, greth->tx_bd_base_phys);
+	GRETH_REGSAVE(greth->regs->rx_desc_p, greth->rx_bd_base_phys);
+
+	return 0;
+
+cleanup:
+	greth_clean_rings(greth);
+	return -ENOMEM;
+}
+
+static int greth_open(struct net_device *dev)
+{
+	struct greth_private *greth = netdev_priv(dev);
+	int err;
+
+	err = greth_init_rings(greth);
+	if (err) {
+		if (netif_msg_ifup(greth))
+			dev_err(&dev->dev, "Could not allocate memory for DMA rings\n");
+		return err;
+	}
+
+	err = request_irq(greth->irq, greth_interrupt, 0, "eth", (void *) dev);
+	if (err) {
+		if (netif_msg_ifup(greth))
+			dev_err(&dev->dev, "Could not allocate interrupt %d\n", dev->irq);
+		greth_clean_rings(greth);
+		return err;
+	}
+
+	if (netif_msg_ifup(greth))
+		dev_dbg(&dev->dev, " starting queue\n");
+	netif_start_queue(dev);
+
+	GRETH_REGSAVE(greth->regs->status, 0xFF);
+
+	napi_enable(&greth->napi);
+
+	greth_enable_irqs(greth);
+	greth_enable_tx(greth);
+	greth_enable_rx(greth);
+	return 0;
+
+}
+
+static int greth_close(struct net_device *dev)
+{
+	struct greth_private *greth = netdev_priv(dev);
+
+	napi_disable(&greth->napi);
+
+	greth_disable_irqs(greth);
+	greth_disable_tx(greth);
+	greth_disable_rx(greth);
+
+	netif_stop_queue(dev);
+
+	free_irq(greth->irq, (void *) dev);
+
+	greth_clean_rings(greth);
+
+	return 0;
+}
+
+static netdev_tx_t
+greth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct greth_private *greth = netdev_priv(dev);
+	struct greth_bd *bdp;
+	int err = NETDEV_TX_OK;
+	u32 status, dma_addr, ctrl;
+	unsigned long flags;
+
+	/* Clean TX Ring */
+	greth_clean_tx(greth->netdev);
+
+	if (unlikely(greth->tx_free <= 0)) {
+		spin_lock_irqsave(&greth->devlock, flags);/*save from poll/irq*/
+		ctrl = GRETH_REGLOAD(greth->regs->control);
+		/* Enable TX IRQ only if not already in poll() routine */
+		if (ctrl & GRETH_RXI)
+			GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI);
+		netif_stop_queue(dev);
+		spin_unlock_irqrestore(&greth->devlock, flags);
+		return NETDEV_TX_BUSY;
+	}
+
+	if (netif_msg_pktdata(greth))
+		greth_print_tx_packet(skb);
+
+
+	if (unlikely(skb->len > MAX_FRAME_SIZE)) {
+		dev->stats.tx_errors++;
+		goto out;
+	}
+
+	bdp = greth->tx_bd_base + greth->tx_next;
+	dma_addr = greth_read_bd(&bdp->addr);
+
+	memcpy((unsigned char *) phys_to_virt(dma_addr), skb->data, skb->len);
+
+	dma_sync_single_for_device(greth->dev, dma_addr, skb->len, DMA_TO_DEVICE);
+
+	status = GRETH_BD_EN | GRETH_BD_IE | (skb->len & GRETH_BD_LEN);
+	greth->tx_bufs_length[greth->tx_next] = skb->len & GRETH_BD_LEN;
+
+	/* Wrap around descriptor ring */
+	if (greth->tx_next == GRETH_TXBD_NUM_MASK) {
+		status |= GRETH_BD_WR;
+	}
+
+	greth->tx_next = NEXT_TX(greth->tx_next);
+	greth->tx_free--;
+
+	/* Write descriptor control word and enable transmission */
+	greth_write_bd(&bdp->stat, status);
+	spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/
+	greth_enable_tx(greth);
+	spin_unlock_irqrestore(&greth->devlock, flags);
+
+out:
+	dev_kfree_skb(skb);
+	return err;
+}
+
+
+static netdev_tx_t
+greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct greth_private *greth = netdev_priv(dev);
+	struct greth_bd *bdp;
+	u32 status = 0, dma_addr, ctrl;
+	int curr_tx, nr_frags, i, err = NETDEV_TX_OK;
+	unsigned long flags;
+
+	nr_frags = skb_shinfo(skb)->nr_frags;
+
+	/* Clean TX Ring */
+	greth_clean_tx_gbit(dev);
+
+	if (greth->tx_free < nr_frags + 1) {
+		spin_lock_irqsave(&greth->devlock, flags);/*save from poll/irq*/
+		ctrl = GRETH_REGLOAD(greth->regs->control);
+		/* Enable TX IRQ only if not already in poll() routine */
+		if (ctrl & GRETH_RXI)
+			GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI);
+		netif_stop_queue(dev);
+		spin_unlock_irqrestore(&greth->devlock, flags);
+		err = NETDEV_TX_BUSY;
+		goto out;
+	}
+
+	if (netif_msg_pktdata(greth))
+		greth_print_tx_packet(skb);
+
+	if (unlikely(skb->len > MAX_FRAME_SIZE)) {
+		dev->stats.tx_errors++;
+		goto out;
+	}
+
+	/* Save skb pointer. */
+	greth->tx_skbuff[greth->tx_next] = skb;
+
+	/* Linear buf */
+	if (nr_frags != 0)
+		status = GRETH_TXBD_MORE;
+
+	if (skb->ip_summed == CHECKSUM_PARTIAL)
+		status |= GRETH_TXBD_CSALL;
+	status |= skb_headlen(skb) & GRETH_BD_LEN;
+	if (greth->tx_next == GRETH_TXBD_NUM_MASK)
+		status |= GRETH_BD_WR;
+
+
+	bdp = greth->tx_bd_base + greth->tx_next;
+	greth_write_bd(&bdp->stat, status);
+	dma_addr = dma_map_single(greth->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
+
+	if (unlikely(dma_mapping_error(greth->dev, dma_addr)))
+		goto map_error;
+
+	greth_write_bd(&bdp->addr, dma_addr);
+
+	curr_tx = NEXT_TX(greth->tx_next);
+
+	/* Frags */
+	for (i = 0; i < nr_frags; i++) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+		greth->tx_skbuff[curr_tx] = NULL;
+		bdp = greth->tx_bd_base + curr_tx;
+
+		status = GRETH_BD_EN;
+		if (skb->ip_summed == CHECKSUM_PARTIAL)
+			status |= GRETH_TXBD_CSALL;
+		status |= skb_frag_size(frag) & GRETH_BD_LEN;
+
+		/* Wrap around descriptor ring */
+		if (curr_tx == GRETH_TXBD_NUM_MASK)
+			status |= GRETH_BD_WR;
+
+		/* More fragments left */
+		if (i < nr_frags - 1)
+			status |= GRETH_TXBD_MORE;
+		else
+			status |= GRETH_BD_IE; /* enable IRQ on last fragment */
+
+		greth_write_bd(&bdp->stat, status);
+
+		dma_addr = skb_frag_dma_map(greth->dev, frag, 0, skb_frag_size(frag),
+					    DMA_TO_DEVICE);
+
+		if (unlikely(dma_mapping_error(greth->dev, dma_addr)))
+			goto frag_map_error;
+
+		greth_write_bd(&bdp->addr, dma_addr);
+
+		curr_tx = NEXT_TX(curr_tx);
+	}
+
+	wmb();
+
+	/* Enable the descriptor chain by enabling the first descriptor */
+	bdp = greth->tx_bd_base + greth->tx_next;
+	greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN);
+	greth->tx_next = curr_tx;
+	greth->tx_free -= nr_frags + 1;
+
+	wmb();
+
+	spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/
+	greth_enable_tx(greth);
+	spin_unlock_irqrestore(&greth->devlock, flags);
+
+	return NETDEV_TX_OK;
+
+frag_map_error:
+	/* Unmap SKB mappings that succeeded and disable descriptor */
+	for (i = 0; greth->tx_next + i != curr_tx; i++) {
+		bdp = greth->tx_bd_base + greth->tx_next + i;
+		dma_unmap_single(greth->dev,
+				 greth_read_bd(&bdp->addr),
+				 greth_read_bd(&bdp->stat) & GRETH_BD_LEN,
+				 DMA_TO_DEVICE);
+		greth_write_bd(&bdp->stat, 0);
+	}
+map_error:
+	if (net_ratelimit())
+		dev_warn(greth->dev, "Could not create TX DMA mapping\n");
+	dev_kfree_skb(skb);
+out:
+	return err;
+}
+
+static irqreturn_t greth_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct greth_private *greth;
+	u32 status, ctrl;
+	irqreturn_t retval = IRQ_NONE;
+
+	greth = netdev_priv(dev);
+
+	spin_lock(&greth->devlock);
+
+	/* Get the interrupt events that caused us to be here. */
+	status = GRETH_REGLOAD(greth->regs->status);
+
+	/* Must see if interrupts are enabled also, INT_TX|INT_RX flags may be
+	 * set regardless of whether IRQ is enabled or not. Especially
+	 * important when shared IRQ.
+	 */
+	ctrl = GRETH_REGLOAD(greth->regs->control);
+
+	/* Handle rx and tx interrupts through poll */
+	if (((status & (GRETH_INT_RE | GRETH_INT_RX)) && (ctrl & GRETH_RXI)) ||
+	    ((status & (GRETH_INT_TE | GRETH_INT_TX)) && (ctrl & GRETH_TXI))) {
+		retval = IRQ_HANDLED;
+
+		/* Disable interrupts and schedule poll() */
+		greth_disable_irqs(greth);
+		napi_schedule(&greth->napi);
+	}
+
+	mmiowb();
+	spin_unlock(&greth->devlock);
+
+	return retval;
+}
+
+static void greth_clean_tx(struct net_device *dev)
+{
+	struct greth_private *greth;
+	struct greth_bd *bdp;
+	u32 stat;
+
+	greth = netdev_priv(dev);
+
+	while (1) {
+		bdp = greth->tx_bd_base + greth->tx_last;
+		GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX);
+		mb();
+		stat = greth_read_bd(&bdp->stat);
+
+		if (unlikely(stat & GRETH_BD_EN))
+			break;
+
+		if (greth->tx_free == GRETH_TXBD_NUM)
+			break;
+
+		/* Check status for errors */
+		if (unlikely(stat & GRETH_TXBD_STATUS)) {
+			dev->stats.tx_errors++;
+			if (stat & GRETH_TXBD_ERR_AL)
+				dev->stats.tx_aborted_errors++;
+			if (stat & GRETH_TXBD_ERR_UE)
+				dev->stats.tx_fifo_errors++;
+		}
+		dev->stats.tx_packets++;
+		dev->stats.tx_bytes += greth->tx_bufs_length[greth->tx_last];
+		greth->tx_last = NEXT_TX(greth->tx_last);
+		greth->tx_free++;
+	}
+
+	if (greth->tx_free > 0) {
+		netif_wake_queue(dev);
+	}
+
+}
+
+static inline void greth_update_tx_stats(struct net_device *dev, u32 stat)
+{
+	/* Check status for errors */
+	if (unlikely(stat & GRETH_TXBD_STATUS)) {
+		dev->stats.tx_errors++;
+		if (stat & GRETH_TXBD_ERR_AL)
+			dev->stats.tx_aborted_errors++;
+		if (stat & GRETH_TXBD_ERR_UE)
+			dev->stats.tx_fifo_errors++;
+		if (stat & GRETH_TXBD_ERR_LC)
+			dev->stats.tx_aborted_errors++;
+	}
+	dev->stats.tx_packets++;
+}
+
+static void greth_clean_tx_gbit(struct net_device *dev)
+{
+	struct greth_private *greth;
+	struct greth_bd *bdp, *bdp_last_frag;
+	struct sk_buff *skb;
+	u32 stat;
+	int nr_frags, i;
+
+	greth = netdev_priv(dev);
+
+	while (greth->tx_free < GRETH_TXBD_NUM) {
+
+		skb = greth->tx_skbuff[greth->tx_last];
+
+		nr_frags = skb_shinfo(skb)->nr_frags;
+
+		/* We only clean fully completed SKBs */
+		bdp_last_frag = greth->tx_bd_base + SKIP_TX(greth->tx_last, nr_frags);
+
+		GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX);
+		mb();
+		stat = greth_read_bd(&bdp_last_frag->stat);
+
+		if (stat & GRETH_BD_EN)
+			break;
+
+		greth->tx_skbuff[greth->tx_last] = NULL;
+
+		greth_update_tx_stats(dev, stat);
+		dev->stats.tx_bytes += skb->len;
+
+		bdp = greth->tx_bd_base + greth->tx_last;
+
+		greth->tx_last = NEXT_TX(greth->tx_last);
+
+		dma_unmap_single(greth->dev,
+				 greth_read_bd(&bdp->addr),
+				 skb_headlen(skb),
+				 DMA_TO_DEVICE);
+
+		for (i = 0; i < nr_frags; i++) {
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+			bdp = greth->tx_bd_base + greth->tx_last;
+
+			dma_unmap_page(greth->dev,
+				       greth_read_bd(&bdp->addr),
+				       skb_frag_size(frag),
+				       DMA_TO_DEVICE);
+
+			greth->tx_last = NEXT_TX(greth->tx_last);
+		}
+		greth->tx_free += nr_frags+1;
+		dev_kfree_skb(skb);
+	}
+
+	if (netif_queue_stopped(dev) && (greth->tx_free > (MAX_SKB_FRAGS+1)))
+		netif_wake_queue(dev);
+}
+
+static int greth_rx(struct net_device *dev, int limit)
+{
+	struct greth_private *greth;
+	struct greth_bd *bdp;
+	struct sk_buff *skb;
+	int pkt_len;
+	int bad, count;
+	u32 status, dma_addr;
+	unsigned long flags;
+
+	greth = netdev_priv(dev);
+
+	for (count = 0; count < limit; ++count) {
+
+		bdp = greth->rx_bd_base + greth->rx_cur;
+		GRETH_REGSAVE(greth->regs->status, GRETH_INT_RE | GRETH_INT_RX);
+		mb();
+		status = greth_read_bd(&bdp->stat);
+
+		if (unlikely(status & GRETH_BD_EN)) {
+			break;
+		}
+
+		dma_addr = greth_read_bd(&bdp->addr);
+		bad = 0;
+
+		/* Check status for errors. */
+		if (unlikely(status & GRETH_RXBD_STATUS)) {
+			if (status & GRETH_RXBD_ERR_FT) {
+				dev->stats.rx_length_errors++;
+				bad = 1;
+			}
+			if (status & (GRETH_RXBD_ERR_AE | GRETH_RXBD_ERR_OE)) {
+				dev->stats.rx_frame_errors++;
+				bad = 1;
+			}
+			if (status & GRETH_RXBD_ERR_CRC) {
+				dev->stats.rx_crc_errors++;
+				bad = 1;
+			}
+		}
+		if (unlikely(bad)) {
+			dev->stats.rx_errors++;
+
+		} else {
+
+			pkt_len = status & GRETH_BD_LEN;
+
+			skb = netdev_alloc_skb(dev, pkt_len + NET_IP_ALIGN);
+
+			if (unlikely(skb == NULL)) {
+
+				if (net_ratelimit())
+					dev_warn(&dev->dev, "low on memory - " "packet dropped\n");
+
+				dev->stats.rx_dropped++;
+
+			} else {
+				skb_reserve(skb, NET_IP_ALIGN);
+				skb->dev = dev;
+
+				dma_sync_single_for_cpu(greth->dev,
+							dma_addr,
+							pkt_len,
+							DMA_FROM_DEVICE);
+
+				if (netif_msg_pktdata(greth))
+					greth_print_rx_packet(phys_to_virt(dma_addr), pkt_len);
+
+				memcpy(skb_put(skb, pkt_len), phys_to_virt(dma_addr), pkt_len);
+
+				skb->protocol = eth_type_trans(skb, dev);
+				dev->stats.rx_bytes += pkt_len;
+				dev->stats.rx_packets++;
+				netif_receive_skb(skb);
+			}
+		}
+
+		status = GRETH_BD_EN | GRETH_BD_IE;
+		if (greth->rx_cur == GRETH_RXBD_NUM_MASK) {
+			status |= GRETH_BD_WR;
+		}
+
+		wmb();
+		greth_write_bd(&bdp->stat, status);
+
+		dma_sync_single_for_device(greth->dev, dma_addr, MAX_FRAME_SIZE, DMA_FROM_DEVICE);
+
+		spin_lock_irqsave(&greth->devlock, flags); /* save from XMIT */
+		greth_enable_rx(greth);
+		spin_unlock_irqrestore(&greth->devlock, flags);
+
+		greth->rx_cur = NEXT_RX(greth->rx_cur);
+	}
+
+	return count;
+}
+
+static inline int hw_checksummed(u32 status)
+{
+
+	if (status & GRETH_RXBD_IP_FRAG)
+		return 0;
+
+	if (status & GRETH_RXBD_IP && status & GRETH_RXBD_IP_CSERR)
+		return 0;
+
+	if (status & GRETH_RXBD_UDP && status & GRETH_RXBD_UDP_CSERR)
+		return 0;
+
+	if (status & GRETH_RXBD_TCP && status & GRETH_RXBD_TCP_CSERR)
+		return 0;
+
+	return 1;
+}
+
+static int greth_rx_gbit(struct net_device *dev, int limit)
+{
+	struct greth_private *greth;
+	struct greth_bd *bdp;
+	struct sk_buff *skb, *newskb;
+	int pkt_len;
+	int bad, count = 0;
+	u32 status, dma_addr;
+	unsigned long flags;
+
+	greth = netdev_priv(dev);
+
+	for (count = 0; count < limit; ++count) {
+
+		bdp = greth->rx_bd_base + greth->rx_cur;
+		skb = greth->rx_skbuff[greth->rx_cur];
+		GRETH_REGSAVE(greth->regs->status, GRETH_INT_RE | GRETH_INT_RX);
+		mb();
+		status = greth_read_bd(&bdp->stat);
+		bad = 0;
+
+		if (status & GRETH_BD_EN)
+			break;
+
+		/* Check status for errors. */
+		if (unlikely(status & GRETH_RXBD_STATUS)) {
+
+			if (status & GRETH_RXBD_ERR_FT) {
+				dev->stats.rx_length_errors++;
+				bad = 1;
+			} else if (status &
+				   (GRETH_RXBD_ERR_AE | GRETH_RXBD_ERR_OE | GRETH_RXBD_ERR_LE)) {
+				dev->stats.rx_frame_errors++;
+				bad = 1;
+			} else if (status & GRETH_RXBD_ERR_CRC) {
+				dev->stats.rx_crc_errors++;
+				bad = 1;
+			}
+		}
+
+		/* Allocate new skb to replace current, not needed if the
+		 * current skb can be reused */
+		if (!bad && (newskb=netdev_alloc_skb(dev, MAX_FRAME_SIZE + NET_IP_ALIGN))) {
+			skb_reserve(newskb, NET_IP_ALIGN);
+
+			dma_addr = dma_map_single(greth->dev,
+						      newskb->data,
+						      MAX_FRAME_SIZE + NET_IP_ALIGN,
+						      DMA_FROM_DEVICE);
+
+			if (!dma_mapping_error(greth->dev, dma_addr)) {
+				/* Process the incoming frame. */
+				pkt_len = status & GRETH_BD_LEN;
+
+				dma_unmap_single(greth->dev,
+						 greth_read_bd(&bdp->addr),
+						 MAX_FRAME_SIZE + NET_IP_ALIGN,
+						 DMA_FROM_DEVICE);
+
+				if (netif_msg_pktdata(greth))
+					greth_print_rx_packet(phys_to_virt(greth_read_bd(&bdp->addr)), pkt_len);
+
+				skb_put(skb, pkt_len);
+
+				if (dev->features & NETIF_F_RXCSUM && hw_checksummed(status))
+					skb->ip_summed = CHECKSUM_UNNECESSARY;
+				else
+					skb_checksum_none_assert(skb);
+
+				skb->protocol = eth_type_trans(skb, dev);
+				dev->stats.rx_packets++;
+				dev->stats.rx_bytes += pkt_len;
+				netif_receive_skb(skb);
+
+				greth->rx_skbuff[greth->rx_cur] = newskb;
+				greth_write_bd(&bdp->addr, dma_addr);
+			} else {
+				if (net_ratelimit())
+					dev_warn(greth->dev, "Could not create DMA mapping, dropping packet\n");
+				dev_kfree_skb(newskb);
+				/* reusing current skb, so it is a drop */
+				dev->stats.rx_dropped++;
+			}
+		} else if (bad) {
+			/* Bad Frame transfer, the skb is reused */
+			dev->stats.rx_dropped++;
+		} else {
+			/* Failed Allocating a new skb. This is rather stupid
+			 * but the current "filled" skb is reused, as if
+			 * transfer failure. One could argue that RX descriptor
+			 * table handling should be divided into cleaning and
+			 * filling as the TX part of the driver
+			 */
+			if (net_ratelimit())
+				dev_warn(greth->dev, "Could not allocate SKB, dropping packet\n");
+			/* reusing current skb, so it is a drop */
+			dev->stats.rx_dropped++;
+		}
+
+		status = GRETH_BD_EN | GRETH_BD_IE;
+		if (greth->rx_cur == GRETH_RXBD_NUM_MASK) {
+			status |= GRETH_BD_WR;
+		}
+
+		wmb();
+		greth_write_bd(&bdp->stat, status);
+		spin_lock_irqsave(&greth->devlock, flags);
+		greth_enable_rx(greth);
+		spin_unlock_irqrestore(&greth->devlock, flags);
+		greth->rx_cur = NEXT_RX(greth->rx_cur);
+	}
+
+	return count;
+
+}
+
+static int greth_poll(struct napi_struct *napi, int budget)
+{
+	struct greth_private *greth;
+	int work_done = 0;
+	unsigned long flags;
+	u32 mask, ctrl;
+	greth = container_of(napi, struct greth_private, napi);
+
+restart_txrx_poll:
+	if (netif_queue_stopped(greth->netdev)) {
+		if (greth->gbit_mac)
+			greth_clean_tx_gbit(greth->netdev);
+		else
+			greth_clean_tx(greth->netdev);
+	}
+
+	if (greth->gbit_mac) {
+		work_done += greth_rx_gbit(greth->netdev, budget - work_done);
+	} else {
+		work_done += greth_rx(greth->netdev, budget - work_done);
+	}
+
+	if (work_done < budget) {
+
+		spin_lock_irqsave(&greth->devlock, flags);
+
+		ctrl = GRETH_REGLOAD(greth->regs->control);
+		if (netif_queue_stopped(greth->netdev)) {
+			GRETH_REGSAVE(greth->regs->control,
+					ctrl | GRETH_TXI | GRETH_RXI);
+			mask = GRETH_INT_RX | GRETH_INT_RE |
+			       GRETH_INT_TX | GRETH_INT_TE;
+		} else {
+			GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_RXI);
+			mask = GRETH_INT_RX | GRETH_INT_RE;
+		}
+
+		if (GRETH_REGLOAD(greth->regs->status) & mask) {
+			GRETH_REGSAVE(greth->regs->control, ctrl);
+			spin_unlock_irqrestore(&greth->devlock, flags);
+			goto restart_txrx_poll;
+		} else {
+			__napi_complete(napi);
+			spin_unlock_irqrestore(&greth->devlock, flags);
+		}
+	}
+
+	return work_done;
+}
+
+static int greth_set_mac_add(struct net_device *dev, void *p)
+{
+	struct sockaddr *addr = p;
+	struct greth_private *greth;
+	struct greth_regs *regs;
+
+	greth = netdev_priv(dev);
+	regs = (struct greth_regs *) greth->regs;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EINVAL;
+
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+	GRETH_REGSAVE(regs->esa_msb, dev->dev_addr[0] << 8 | dev->dev_addr[1]);
+	GRETH_REGSAVE(regs->esa_lsb, dev->dev_addr[2] << 24 | dev->dev_addr[3] << 16 |
+		      dev->dev_addr[4] << 8 | dev->dev_addr[5]);
+
+	return 0;
+}
+
+static u32 greth_hash_get_index(__u8 *addr)
+{
+	return (ether_crc(6, addr)) & 0x3F;
+}
+
+static void greth_set_hash_filter(struct net_device *dev)
+{
+	struct netdev_hw_addr *ha;
+	struct greth_private *greth = netdev_priv(dev);
+	struct greth_regs *regs = (struct greth_regs *) greth->regs;
+	u32 mc_filter[2];
+	unsigned int bitnr;
+
+	mc_filter[0] = mc_filter[1] = 0;
+
+	netdev_for_each_mc_addr(ha, dev) {
+		bitnr = greth_hash_get_index(ha->addr);
+		mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
+	}
+
+	GRETH_REGSAVE(regs->hash_msb, mc_filter[1]);
+	GRETH_REGSAVE(regs->hash_lsb, mc_filter[0]);
+}
+
+static void greth_set_multicast_list(struct net_device *dev)
+{
+	int cfg;
+	struct greth_private *greth = netdev_priv(dev);
+	struct greth_regs *regs = (struct greth_regs *) greth->regs;
+
+	cfg = GRETH_REGLOAD(regs->control);
+	if (dev->flags & IFF_PROMISC)
+		cfg |= GRETH_CTRL_PR;
+	else
+		cfg &= ~GRETH_CTRL_PR;
+
+	if (greth->multicast) {
+		if (dev->flags & IFF_ALLMULTI) {
+			GRETH_REGSAVE(regs->hash_msb, -1);
+			GRETH_REGSAVE(regs->hash_lsb, -1);
+			cfg |= GRETH_CTRL_MCEN;
+			GRETH_REGSAVE(regs->control, cfg);
+			return;
+		}
+
+		if (netdev_mc_empty(dev)) {
+			cfg &= ~GRETH_CTRL_MCEN;
+			GRETH_REGSAVE(regs->control, cfg);
+			return;
+		}
+
+		/* Setup multicast filter */
+		greth_set_hash_filter(dev);
+		cfg |= GRETH_CTRL_MCEN;
+	}
+	GRETH_REGSAVE(regs->control, cfg);
+}
+
+static u32 greth_get_msglevel(struct net_device *dev)
+{
+	struct greth_private *greth = netdev_priv(dev);
+	return greth->msg_enable;
+}
+
+static void greth_set_msglevel(struct net_device *dev, u32 value)
+{
+	struct greth_private *greth = netdev_priv(dev);
+	greth->msg_enable = value;
+}
+static int greth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct greth_private *greth = netdev_priv(dev);
+	struct phy_device *phy = greth->phy;
+
+	if (!phy)
+		return -ENODEV;
+
+	return phy_ethtool_gset(phy, cmd);
+}
+
+static int greth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct greth_private *greth = netdev_priv(dev);
+	struct phy_device *phy = greth->phy;
+
+	if (!phy)
+		return -ENODEV;
+
+	return phy_ethtool_sset(phy, cmd);
+}
+
+static int greth_get_regs_len(struct net_device *dev)
+{
+	return sizeof(struct greth_regs);
+}
+
+static void greth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	struct greth_private *greth = netdev_priv(dev);
+
+	strncpy(info->driver, dev_driver_string(greth->dev), 32);
+	strncpy(info->version, "revision: 1.0", 32);
+	strncpy(info->bus_info, greth->dev->bus->name, 32);
+	strncpy(info->fw_version, "N/A", 32);
+	info->eedump_len = 0;
+	info->regdump_len = sizeof(struct greth_regs);
+}
+
+static void greth_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
+{
+	int i;
+	struct greth_private *greth = netdev_priv(dev);
+	u32 __iomem *greth_regs = (u32 __iomem *) greth->regs;
+	u32 *buff = p;
+
+	for (i = 0; i < sizeof(struct greth_regs) / sizeof(u32); i++)
+		buff[i] = greth_read_bd(&greth_regs[i]);
+}
+
+static const struct ethtool_ops greth_ethtool_ops = {
+	.get_msglevel		= greth_get_msglevel,
+	.set_msglevel		= greth_set_msglevel,
+	.get_settings		= greth_get_settings,
+	.set_settings		= greth_set_settings,
+	.get_drvinfo		= greth_get_drvinfo,
+	.get_regs_len           = greth_get_regs_len,
+	.get_regs               = greth_get_regs,
+	.get_link		= ethtool_op_get_link,
+};
+
+static struct net_device_ops greth_netdev_ops = {
+	.ndo_open		= greth_open,
+	.ndo_stop		= greth_close,
+	.ndo_start_xmit		= greth_start_xmit,
+	.ndo_set_mac_address	= greth_set_mac_add,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+static inline int wait_for_mdio(struct greth_private *greth)
+{
+	unsigned long timeout = jiffies + 4*HZ/100;
+	while (GRETH_REGLOAD(greth->regs->mdio) & GRETH_MII_BUSY) {
+		if (time_after(jiffies, timeout))
+			return 0;
+	}
+	return 1;
+}
+
+static int greth_mdio_read(struct mii_bus *bus, int phy, int reg)
+{
+	struct greth_private *greth = bus->priv;
+	int data;
+
+	if (!wait_for_mdio(greth))
+		return -EBUSY;
+
+	GRETH_REGSAVE(greth->regs->mdio, ((phy & 0x1F) << 11) | ((reg & 0x1F) << 6) | 2);
+
+	if (!wait_for_mdio(greth))
+		return -EBUSY;
+
+	if (!(GRETH_REGLOAD(greth->regs->mdio) & GRETH_MII_NVALID)) {
+		data = (GRETH_REGLOAD(greth->regs->mdio) >> 16) & 0xFFFF;
+		return data;
+
+	} else {
+		return -1;
+	}
+}
+
+static int greth_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
+{
+	struct greth_private *greth = bus->priv;
+
+	if (!wait_for_mdio(greth))
+		return -EBUSY;
+
+	GRETH_REGSAVE(greth->regs->mdio,
+		      ((val & 0xFFFF) << 16) | ((phy & 0x1F) << 11) | ((reg & 0x1F) << 6) | 1);
+
+	if (!wait_for_mdio(greth))
+		return -EBUSY;
+
+	return 0;
+}
+
+static int greth_mdio_reset(struct mii_bus *bus)
+{
+	return 0;
+}
+
+static void greth_link_change(struct net_device *dev)
+{
+	struct greth_private *greth = netdev_priv(dev);
+	struct phy_device *phydev = greth->phy;
+	unsigned long flags;
+	int status_change = 0;
+	u32 ctrl;
+
+	spin_lock_irqsave(&greth->devlock, flags);
+
+	if (phydev->link) {
+
+		if ((greth->speed != phydev->speed) || (greth->duplex != phydev->duplex)) {
+			ctrl = GRETH_REGLOAD(greth->regs->control) &
+			       ~(GRETH_CTRL_FD | GRETH_CTRL_SP | GRETH_CTRL_GB);
+
+			if (phydev->duplex)
+				ctrl |= GRETH_CTRL_FD;
+
+			if (phydev->speed == SPEED_100)
+				ctrl |= GRETH_CTRL_SP;
+			else if (phydev->speed == SPEED_1000)
+				ctrl |= GRETH_CTRL_GB;
+
+			GRETH_REGSAVE(greth->regs->control, ctrl);
+			greth->speed = phydev->speed;
+			greth->duplex = phydev->duplex;
+			status_change = 1;
+		}
+	}
+
+	if (phydev->link != greth->link) {
+		if (!phydev->link) {
+			greth->speed = 0;
+			greth->duplex = -1;
+		}
+		greth->link = phydev->link;
+
+		status_change = 1;
+	}
+
+	spin_unlock_irqrestore(&greth->devlock, flags);
+
+	if (status_change) {
+		if (phydev->link)
+			pr_debug("%s: link up (%d/%s)\n",
+				dev->name, phydev->speed,
+				DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
+		else
+			pr_debug("%s: link down\n", dev->name);
+	}
+}
+
+static int greth_mdio_probe(struct net_device *dev)
+{
+	struct greth_private *greth = netdev_priv(dev);
+	struct phy_device *phy = NULL;
+	int ret;
+
+	/* Find the first PHY */
+	phy = phy_find_first(greth->mdio);
+
+	if (!phy) {
+		if (netif_msg_probe(greth))
+			dev_err(&dev->dev, "no PHY found\n");
+		return -ENXIO;
+	}
+
+	ret = phy_connect_direct(dev, phy, &greth_link_change,
+			0, greth->gbit_mac ?
+			PHY_INTERFACE_MODE_GMII :
+			PHY_INTERFACE_MODE_MII);
+	if (ret) {
+		if (netif_msg_ifup(greth))
+			dev_err(&dev->dev, "could not attach to PHY\n");
+		return ret;
+	}
+
+	if (greth->gbit_mac)
+		phy->supported &= PHY_GBIT_FEATURES;
+	else
+		phy->supported &= PHY_BASIC_FEATURES;
+
+	phy->advertising = phy->supported;
+
+	greth->link = 0;
+	greth->speed = 0;
+	greth->duplex = -1;
+	greth->phy = phy;
+
+	return 0;
+}
+
+static inline int phy_aneg_done(struct phy_device *phydev)
+{
+	int retval;
+
+	retval = phy_read(phydev, MII_BMSR);
+
+	return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
+}
+
+static int greth_mdio_init(struct greth_private *greth)
+{
+	int ret, phy;
+	unsigned long timeout;
+
+	greth->mdio = mdiobus_alloc();
+	if (!greth->mdio) {
+		return -ENOMEM;
+	}
+
+	greth->mdio->name = "greth-mdio";
+	snprintf(greth->mdio->id, MII_BUS_ID_SIZE, "%s-%d", greth->mdio->name, greth->irq);
+	greth->mdio->read = greth_mdio_read;
+	greth->mdio->write = greth_mdio_write;
+	greth->mdio->reset = greth_mdio_reset;
+	greth->mdio->priv = greth;
+
+	greth->mdio->irq = greth->mdio_irqs;
+
+	for (phy = 0; phy < PHY_MAX_ADDR; phy++)
+		greth->mdio->irq[phy] = PHY_POLL;
+
+	ret = mdiobus_register(greth->mdio);
+	if (ret) {
+		goto error;
+	}
+
+	ret = greth_mdio_probe(greth->netdev);
+	if (ret) {
+		if (netif_msg_probe(greth))
+			dev_err(&greth->netdev->dev, "failed to probe MDIO bus\n");
+		goto unreg_mdio;
+	}
+
+	phy_start(greth->phy);
+
+	/* If Ethernet debug link is used make autoneg happen right away */
+	if (greth->edcl && greth_edcl == 1) {
+		phy_start_aneg(greth->phy);
+		timeout = jiffies + 6*HZ;
+		while (!phy_aneg_done(greth->phy) && time_before(jiffies, timeout)) {
+		}
+		genphy_read_status(greth->phy);
+		greth_link_change(greth->netdev);
+	}
+
+	return 0;
+
+unreg_mdio:
+	mdiobus_unregister(greth->mdio);
+error:
+	mdiobus_free(greth->mdio);
+	return ret;
+}
+
+/* Initialize the GRETH MAC */
+static int __devinit greth_of_probe(struct platform_device *ofdev)
+{
+	struct net_device *dev;
+	struct greth_private *greth;
+	struct greth_regs *regs;
+
+	int i;
+	int err;
+	int tmp;
+	unsigned long timeout;
+
+	dev = alloc_etherdev(sizeof(struct greth_private));
+
+	if (dev == NULL)
+		return -ENOMEM;
+
+	greth = netdev_priv(dev);
+	greth->netdev = dev;
+	greth->dev = &ofdev->dev;
+
+	if (greth_debug > 0)
+		greth->msg_enable = greth_debug;
+	else
+		greth->msg_enable = GRETH_DEF_MSG_ENABLE;
+
+	spin_lock_init(&greth->devlock);
+
+	greth->regs = of_ioremap(&ofdev->resource[0], 0,
+				 resource_size(&ofdev->resource[0]),
+				 "grlib-greth regs");
+
+	if (greth->regs == NULL) {
+		if (netif_msg_probe(greth))
+			dev_err(greth->dev, "ioremap failure.\n");
+		err = -EIO;
+		goto error1;
+	}
+
+	regs = (struct greth_regs *) greth->regs;
+	greth->irq = ofdev->archdata.irqs[0];
+
+	dev_set_drvdata(greth->dev, dev);
+	SET_NETDEV_DEV(dev, greth->dev);
+
+	if (netif_msg_probe(greth))
+		dev_dbg(greth->dev, "reseting controller.\n");
+
+	/* Reset the controller. */
+	GRETH_REGSAVE(regs->control, GRETH_RESET);
+
+	/* Wait for MAC to reset itself */
+	timeout = jiffies + HZ/100;
+	while (GRETH_REGLOAD(regs->control) & GRETH_RESET) {
+		if (time_after(jiffies, timeout)) {
+			err = -EIO;
+			if (netif_msg_probe(greth))
+				dev_err(greth->dev, "timeout when waiting for reset.\n");
+			goto error2;
+		}
+	}
+
+	/* Get default PHY address  */
+	greth->phyaddr = (GRETH_REGLOAD(regs->mdio) >> 11) & 0x1F;
+
+	/* Check if we have GBIT capable MAC */
+	tmp = GRETH_REGLOAD(regs->control);
+	greth->gbit_mac = (tmp >> 27) & 1;
+
+	/* Check for multicast capability */
+	greth->multicast = (tmp >> 25) & 1;
+
+	greth->edcl = (tmp >> 31) & 1;
+
+	/* If we have EDCL we disable the EDCL speed-duplex FSM so
+	 * it doesn't interfere with the software */
+	if (greth->edcl != 0)
+		GRETH_REGORIN(regs->control, GRETH_CTRL_DISDUPLEX);
+
+	/* Check if MAC can handle MDIO interrupts */
+	greth->mdio_int_en = (tmp >> 26) & 1;
+
+	err = greth_mdio_init(greth);
+	if (err) {
+		if (netif_msg_probe(greth))
+			dev_err(greth->dev, "failed to register MDIO bus\n");
+		goto error2;
+	}
+
+	/* Allocate TX descriptor ring in coherent memory */
+	greth->tx_bd_base = (struct greth_bd *) dma_alloc_coherent(greth->dev,
+								   1024,
+								   &greth->tx_bd_base_phys,
+								   GFP_KERNEL);
+
+	if (!greth->tx_bd_base) {
+		if (netif_msg_probe(greth))
+			dev_err(&dev->dev, "could not allocate descriptor memory.\n");
+		err = -ENOMEM;
+		goto error3;
+	}
+
+	memset(greth->tx_bd_base, 0, 1024);
+
+	/* Allocate RX descriptor ring in coherent memory */
+	greth->rx_bd_base = (struct greth_bd *) dma_alloc_coherent(greth->dev,
+								   1024,
+								   &greth->rx_bd_base_phys,
+								   GFP_KERNEL);
+
+	if (!greth->rx_bd_base) {
+		if (netif_msg_probe(greth))
+			dev_err(greth->dev, "could not allocate descriptor memory.\n");
+		err = -ENOMEM;
+		goto error4;
+	}
+
+	memset(greth->rx_bd_base, 0, 1024);
+
+	/* Get MAC address from: module param, OF property or ID prom */
+	for (i = 0; i < 6; i++) {
+		if (macaddr[i] != 0)
+			break;
+	}
+	if (i == 6) {
+		const unsigned char *addr;
+		int len;
+		addr = of_get_property(ofdev->dev.of_node, "local-mac-address",
+					&len);
+		if (addr != NULL && len == 6) {
+			for (i = 0; i < 6; i++)
+				macaddr[i] = (unsigned int) addr[i];
+		} else {
+#ifdef CONFIG_SPARC
+			for (i = 0; i < 6; i++)
+				macaddr[i] = (unsigned int) idprom->id_ethaddr[i];
+#endif
+		}
+	}
+
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = macaddr[i];
+
+	macaddr[5]++;
+
+	if (!is_valid_ether_addr(&dev->dev_addr[0])) {
+		if (netif_msg_probe(greth))
+			dev_err(greth->dev, "no valid ethernet address, aborting.\n");
+		err = -EINVAL;
+		goto error5;
+	}
+
+	GRETH_REGSAVE(regs->esa_msb, dev->dev_addr[0] << 8 | dev->dev_addr[1]);
+	GRETH_REGSAVE(regs->esa_lsb, dev->dev_addr[2] << 24 | dev->dev_addr[3] << 16 |
+		      dev->dev_addr[4] << 8 | dev->dev_addr[5]);
+
+	/* Clear all pending interrupts except PHY irq */
+	GRETH_REGSAVE(regs->status, 0xFF);
+
+	if (greth->gbit_mac) {
+		dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
+			NETIF_F_RXCSUM;
+		dev->features = dev->hw_features | NETIF_F_HIGHDMA;
+		greth_netdev_ops.ndo_start_xmit = greth_start_xmit_gbit;
+	}
+
+	if (greth->multicast) {
+		greth_netdev_ops.ndo_set_rx_mode = greth_set_multicast_list;
+		dev->flags |= IFF_MULTICAST;
+	} else {
+		dev->flags &= ~IFF_MULTICAST;
+	}
+
+	dev->netdev_ops = &greth_netdev_ops;
+	dev->ethtool_ops = &greth_ethtool_ops;
+
+	err = register_netdev(dev);
+	if (err) {
+		if (netif_msg_probe(greth))
+			dev_err(greth->dev, "netdevice registration failed.\n");
+		goto error5;
+	}
+
+	/* setup NAPI */
+	netif_napi_add(dev, &greth->napi, greth_poll, 64);
+
+	return 0;
+
+error5:
+	dma_free_coherent(greth->dev, 1024, greth->rx_bd_base, greth->rx_bd_base_phys);
+error4:
+	dma_free_coherent(greth->dev, 1024, greth->tx_bd_base, greth->tx_bd_base_phys);
+error3:
+	mdiobus_unregister(greth->mdio);
+error2:
+	of_iounmap(&ofdev->resource[0], greth->regs, resource_size(&ofdev->resource[0]));
+error1:
+	free_netdev(dev);
+	return err;
+}
+
+static int __devexit greth_of_remove(struct platform_device *of_dev)
+{
+	struct net_device *ndev = dev_get_drvdata(&of_dev->dev);
+	struct greth_private *greth = netdev_priv(ndev);
+
+	/* Free descriptor areas */
+	dma_free_coherent(&of_dev->dev, 1024, greth->rx_bd_base, greth->rx_bd_base_phys);
+
+	dma_free_coherent(&of_dev->dev, 1024, greth->tx_bd_base, greth->tx_bd_base_phys);
+
+	dev_set_drvdata(&of_dev->dev, NULL);
+
+	if (greth->phy)
+		phy_stop(greth->phy);
+	mdiobus_unregister(greth->mdio);
+
+	unregister_netdev(ndev);
+	free_netdev(ndev);
+
+	of_iounmap(&of_dev->resource[0], greth->regs, resource_size(&of_dev->resource[0]));
+
+	return 0;
+}
+
+static struct of_device_id greth_of_match[] = {
+	{
+	 .name = "GAISLER_ETHMAC",
+	 },
+	{
+	 .name = "01_01d",
+	 },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, greth_of_match);
+
+static struct platform_driver greth_of_driver = {
+	.driver = {
+		.name = "grlib-greth",
+		.owner = THIS_MODULE,
+		.of_match_table = greth_of_match,
+	},
+	.probe = greth_of_probe,
+	.remove = __devexit_p(greth_of_remove),
+};
+
+static int __init greth_init(void)
+{
+	return platform_driver_register(&greth_of_driver);
+}
+
+static void __exit greth_cleanup(void)
+{
+	platform_driver_unregister(&greth_of_driver);
+}
+
+module_init(greth_init);
+module_exit(greth_cleanup);
+
+MODULE_AUTHOR("Aeroflex Gaisler AB.");
+MODULE_DESCRIPTION("Aeroflex Gaisler Ethernet MAC driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/aeroflex/greth.h linux-libre-3.2-gnu/drivers/net/ethernet/aeroflex/greth.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/aeroflex/greth.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/aeroflex/greth.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,142 @@
+#ifndef GRETH_H
+#define GRETH_H
+
+#include <linux/phy.h>
+
+/* Register bits and masks */
+#define GRETH_RESET 0x40
+#define GRETH_MII_BUSY 0x8
+#define GRETH_MII_NVALID 0x10
+
+#define GRETH_CTRL_FD         0x10
+#define GRETH_CTRL_PR         0x20
+#define GRETH_CTRL_SP         0x80
+#define GRETH_CTRL_GB         0x100
+#define GRETH_CTRL_PSTATIEN   0x400
+#define GRETH_CTRL_MCEN       0x800
+#define GRETH_CTRL_DISDUPLEX  0x1000
+#define GRETH_STATUS_PHYSTAT  0x100
+
+#define GRETH_BD_EN 0x800
+#define GRETH_BD_WR 0x1000
+#define GRETH_BD_IE 0x2000
+#define GRETH_BD_LEN 0x7FF
+
+#define GRETH_TXEN 0x1
+#define GRETH_INT_TE 0x2
+#define GRETH_INT_TX 0x8
+#define GRETH_TXI 0x4
+#define GRETH_TXBD_STATUS 0x0001C000
+#define GRETH_TXBD_MORE 0x20000
+#define GRETH_TXBD_IPCS 0x40000
+#define GRETH_TXBD_TCPCS 0x80000
+#define GRETH_TXBD_UDPCS 0x100000
+#define GRETH_TXBD_CSALL (GRETH_TXBD_IPCS | GRETH_TXBD_TCPCS | GRETH_TXBD_UDPCS)
+#define GRETH_TXBD_ERR_LC 0x10000
+#define GRETH_TXBD_ERR_UE 0x4000
+#define GRETH_TXBD_ERR_AL 0x8000
+
+#define GRETH_INT_RE         0x1
+#define GRETH_INT_RX         0x4
+#define GRETH_RXEN           0x2
+#define GRETH_RXI            0x8
+#define GRETH_RXBD_STATUS    0xFFFFC000
+#define GRETH_RXBD_ERR_AE    0x4000
+#define GRETH_RXBD_ERR_FT    0x8000
+#define GRETH_RXBD_ERR_CRC   0x10000
+#define GRETH_RXBD_ERR_OE    0x20000
+#define GRETH_RXBD_ERR_LE    0x40000
+#define GRETH_RXBD_IP        0x80000
+#define GRETH_RXBD_IP_CSERR  0x100000
+#define GRETH_RXBD_UDP       0x200000
+#define GRETH_RXBD_UDP_CSERR 0x400000
+#define GRETH_RXBD_TCP       0x800000
+#define GRETH_RXBD_TCP_CSERR 0x1000000
+#define GRETH_RXBD_IP_FRAG   0x2000000
+#define GRETH_RXBD_MCAST     0x4000000
+
+/* Descriptor parameters */
+#define GRETH_TXBD_NUM 128
+#define GRETH_TXBD_NUM_MASK (GRETH_TXBD_NUM-1)
+#define GRETH_TX_BUF_SIZE 2048
+#define GRETH_RXBD_NUM 128
+#define GRETH_RXBD_NUM_MASK (GRETH_RXBD_NUM-1)
+#define GRETH_RX_BUF_SIZE 2048
+
+/* Buffers per page */
+#define GRETH_RX_BUF_PPGAE	(PAGE_SIZE/GRETH_RX_BUF_SIZE)
+#define GRETH_TX_BUF_PPGAE	(PAGE_SIZE/GRETH_TX_BUF_SIZE)
+
+/* How many pages are needed for buffers */
+#define GRETH_RX_BUF_PAGE_NUM	(GRETH_RXBD_NUM/GRETH_RX_BUF_PPGAE)
+#define GRETH_TX_BUF_PAGE_NUM	(GRETH_TXBD_NUM/GRETH_TX_BUF_PPGAE)
+
+/* Buffer size.
+ * Gbit MAC uses tagged maximum frame size which is 1518 excluding CRC.
+ * Set to 1520 to make all buffers word aligned for non-gbit MAC.
+ */
+#define MAX_FRAME_SIZE		1520
+
+/* GRETH APB registers */
+struct greth_regs {
+	u32 control;
+	u32 status;
+	u32 esa_msb;
+	u32 esa_lsb;
+	u32 mdio;
+	u32 tx_desc_p;
+	u32 rx_desc_p;
+	u32 edclip;
+	u32 hash_msb;
+	u32 hash_lsb;
+};
+
+/* GRETH buffer descriptor */
+struct greth_bd {
+	u32 stat;
+	u32 addr;
+};
+
+struct greth_private {
+	struct sk_buff *rx_skbuff[GRETH_RXBD_NUM];
+	struct sk_buff *tx_skbuff[GRETH_TXBD_NUM];
+
+	unsigned char *tx_bufs[GRETH_TXBD_NUM];
+	unsigned char *rx_bufs[GRETH_RXBD_NUM];
+	u16 tx_bufs_length[GRETH_TXBD_NUM];
+
+	u16 tx_next;
+	u16 tx_last;
+	u16 tx_free;
+	u16 rx_cur;
+
+	struct greth_regs *regs;	/* Address of controller registers. */
+	struct greth_bd *rx_bd_base;	/* Address of Rx BDs. */
+	struct greth_bd *tx_bd_base;	/* Address of Tx BDs. */
+	dma_addr_t rx_bd_base_phys;
+	dma_addr_t tx_bd_base_phys;
+
+	int irq;
+
+	struct device *dev;	        /* Pointer to platform_device->dev */
+	struct net_device *netdev;
+	struct napi_struct napi;
+	spinlock_t devlock;
+
+	struct phy_device *phy;
+	struct mii_bus *mdio;
+	int mdio_irqs[PHY_MAX_ADDR];
+	unsigned int link;
+	unsigned int speed;
+	unsigned int duplex;
+
+	u32 msg_enable;
+
+	u8 phyaddr;
+	u8 multicast;
+	u8 gbit_mac;
+	u8 mdio_int_en;
+	u8 edcl;
+};
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/aeroflex/Kconfig linux-libre-3.2-gnu/drivers/net/ethernet/aeroflex/Kconfig
--- linux-libre-3.1-gnu/drivers/net/ethernet/aeroflex/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/aeroflex/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,11 @@
+#
+# Aeroflex Gaisler network device configuration
+#
+
+config GRETH
+	tristate "Aeroflex Gaisler GRETH Ethernet MAC support"
+	depends on SPARC
+	select PHYLIB
+	select CRC32
+	---help---
+	  Say Y here if you want to use the Aeroflex Gaisler GRETH Ethernet MAC.
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/aeroflex/Makefile linux-libre-3.2-gnu/drivers/net/ethernet/aeroflex/Makefile
--- linux-libre-3.1-gnu/drivers/net/ethernet/aeroflex/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/aeroflex/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+#
+# Makefile for the Aeroflex Gaisler network device drivers.
+#
+
+obj-$(CONFIG_GRETH) += greth.o
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/alteon/acenic.c linux-libre-3.2-gnu/drivers/net/ethernet/alteon/acenic.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/alteon/acenic.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/alteon/acenic.c	2012-03-19 21:44:12.000000000 -0400
@@ -0,0 +1,3206 @@
+/*
+ * acenic.c: Linux driver for the Alteon AceNIC Gigabit Ethernet card
+ *           and other Tigon based cards.
+ *
+ * Copyright 1998-2002 by Jes Sorensen, <jes@trained-monkey.org>.
+ *
+ * Thanks to Alteon and 3Com for providing hardware and documentation
+ * enabling me to write this driver.
+ *
+ * A mailing list for discussing the use of this driver has been
+ * setup, please subscribe to the lists if you have any questions
+ * about the driver. Send mail to linux-acenic-help@sunsite.auc.dk to
+ * see how to subscribe.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Additional credits:
+ *   Pete Wyckoff <wyckoff@ca.sandia.gov>: Initial Linux/Alpha and trace
+ *       dump support. The trace dump support has not been
+ *       integrated yet however.
+ *   Troy Benjegerdes: Big Endian (PPC) patches.
+ *   Nate Stahl: Better out of memory handling and stats support.
+ *   Aman Singla: Nasty race between interrupt handler and tx code dealing
+ *                with 'testing the tx_ret_csm and setting tx_full'
+ *   David S. Miller <davem@redhat.com>: conversion to new PCI dma mapping
+ *                                       infrastructure and Sparc support
+ *   Pierrick Pinasseau (CERN): For lending me an Ultra 5 to test the
+ *                              driver under Linux/Sparc64
+ *   Matt Domsch <Matt_Domsch@dell.com>: Detect Alteon 1000baseT cards
+ *                                       ETHTOOL_GDRVINFO support
+ *   Chip Salzenberg <chip@valinux.com>: Fix race condition between tx
+ *                                       handler and close() cleanup.
+ *   Ken Aaker <kdaaker@rchland.vnet.ibm.com>: Correct check for whether
+ *                                       memory mapped IO is enabled to
+ *                                       make the driver work on RS/6000.
+ *   Takayoshi Kouchi <kouchi@hpc.bs1.fc.nec.co.jp>: Identifying problem
+ *                                       where the driver would disable
+ *                                       bus master mode if it had to disable
+ *                                       write and invalidate.
+ *   Stephen Hack <stephen_hack@hp.com>: Fixed ace_set_mac_addr for little
+ *                                       endian systems.
+ *   Val Henson <vhenson@esscom.com>:    Reset Jumbo skb producer and
+ *                                       rx producer index when
+ *                                       flushing the Jumbo ring.
+ *   Hans Grobler <grobh@sun.ac.za>:     Memory leak fixes in the
+ *                                       driver init path.
+ *   Grant Grundler <grundler@cup.hp.com>: PCI write posting fixes.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/sockios.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/prefetch.h>
+#include <linux/if_vlan.h>
+
+#ifdef SIOCETHTOOL
+#include <linux/ethtool.h>
+#endif
+
+#include <net/sock.h>
+#include <net/ip.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+
+#define DRV_NAME "acenic"
+
+#undef INDEX_DEBUG
+
+#ifdef CONFIG_ACENIC_OMIT_TIGON_I
+#define ACE_IS_TIGON_I(ap)	0
+#define ACE_TX_RING_ENTRIES(ap)	MAX_TX_RING_ENTRIES
+#else
+#define ACE_IS_TIGON_I(ap)	(ap->version == 1)
+#define ACE_TX_RING_ENTRIES(ap)	ap->tx_ring_entries
+#endif
+
+#ifndef PCI_VENDOR_ID_ALTEON
+#define PCI_VENDOR_ID_ALTEON		0x12ae
+#endif
+#ifndef PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE
+#define PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE  0x0001
+#define PCI_DEVICE_ID_ALTEON_ACENIC_COPPER 0x0002
+#endif
+#ifndef PCI_DEVICE_ID_3COM_3C985
+#define PCI_DEVICE_ID_3COM_3C985	0x0001
+#endif
+#ifndef PCI_VENDOR_ID_NETGEAR
+#define PCI_VENDOR_ID_NETGEAR		0x1385
+#define PCI_DEVICE_ID_NETGEAR_GA620	0x620a
+#endif
+#ifndef PCI_DEVICE_ID_NETGEAR_GA620T
+#define PCI_DEVICE_ID_NETGEAR_GA620T	0x630a
+#endif
+
+
+/*
+ * Farallon used the DEC vendor ID by mistake and they seem not
+ * to care - stinky!
+ */
+#ifndef PCI_DEVICE_ID_FARALLON_PN9000SX
+#define PCI_DEVICE_ID_FARALLON_PN9000SX	0x1a
+#endif
+#ifndef PCI_DEVICE_ID_FARALLON_PN9100T
+#define PCI_DEVICE_ID_FARALLON_PN9100T  0xfa
+#endif
+#ifndef PCI_VENDOR_ID_SGI
+#define PCI_VENDOR_ID_SGI		0x10a9
+#endif
+#ifndef PCI_DEVICE_ID_SGI_ACENIC
+#define PCI_DEVICE_ID_SGI_ACENIC	0x0009
+#endif
+
+static DEFINE_PCI_DEVICE_TABLE(acenic_pci_tbl) = {
+	{ PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
+	{ PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_COPPER,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C985,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
+	{ PCI_VENDOR_ID_NETGEAR, PCI_DEVICE_ID_NETGEAR_GA620,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
+	{ PCI_VENDOR_ID_NETGEAR, PCI_DEVICE_ID_NETGEAR_GA620T,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
+	/*
+	 * Farallon used the DEC vendor ID on their cards incorrectly,
+	 * then later Alteon's ID.
+	 */
+	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_FARALLON_PN9000SX,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
+	{ PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_FARALLON_PN9100T,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
+	{ PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_ACENIC,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
+
+#define ace_sync_irq(irq)	synchronize_irq(irq)
+
+#ifndef offset_in_page
+#define offset_in_page(ptr)	((unsigned long)(ptr) & ~PAGE_MASK)
+#endif
+
+#define ACE_MAX_MOD_PARMS	8
+#define BOARD_IDX_STATIC	0
+#define BOARD_IDX_OVERFLOW	-1
+
+#include "acenic.h"
+
+/*
+ * These must be defined before the firmware is included.
+ */
+#define MAX_TEXT_LEN	96*1024
+#define MAX_RODATA_LEN	8*1024
+#define MAX_DATA_LEN	2*1024
+
+#ifndef tigon2FwReleaseLocal
+#define tigon2FwReleaseLocal 0
+#endif
+
+/*
+ * This driver currently supports Tigon I and Tigon II based cards
+ * including the Alteon AceNIC, the 3Com 3C985[B] and NetGear
+ * GA620. The driver should also work on the SGI, DEC and Farallon
+ * versions of the card, however I have not been able to test that
+ * myself.
+ *
+ * This card is really neat, it supports receive hardware checksumming
+ * and jumbo frames (up to 9000 bytes) and does a lot of work in the
+ * firmware. Also the programming interface is quite neat, except for
+ * the parts dealing with the i2c eeprom on the card ;-)
+ *
+ * Using jumbo frames:
+ *
+ * To enable jumbo frames, simply specify an mtu between 1500 and 9000
+ * bytes to ifconfig. Jumbo frames can be enabled or disabled at any time
+ * by running `ifconfig eth<X> mtu <MTU>' with <X> being the Ethernet
+ * interface number and <MTU> being the MTU value.
+ *
+ * Module parameters:
+ *
+ * When compiled as a loadable module, the driver allows for a number
+ * of module parameters to be specified. The driver supports the
+ * following module parameters:
+ *
+ *  trace=<val> - Firmware trace level. This requires special traced
+ *                firmware to replace the firmware supplied with
+ *                the driver - for debugging purposes only.
+ *
+ *  link=<val>  - Link state. Normally you want to use the default link
+ *                parameters set by the driver. This can be used to
+ *                override these in case your switch doesn't negotiate
+ *                the link properly. Valid values are:
+ *         0x0001 - Force half duplex link.
+ *         0x0002 - Do not negotiate line speed with the other end.
+ *         0x0010 - 10Mbit/sec link.
+ *         0x0020 - 100Mbit/sec link.
+ *         0x0040 - 1000Mbit/sec link.
+ *         0x0100 - Do not negotiate flow control.
+ *         0x0200 - Enable RX flow control Y
+ *         0x0400 - Enable TX flow control Y (Tigon II NICs only).
+ *                Default value is 0x0270, ie. enable link+flow
+ *                control negotiation. Negotiating the highest
+ *                possible link speed with RX flow control enabled.
+ *
+ *                When disabling link speed negotiation, only one link
+ *                speed is allowed to be specified!
+ *
+ *  tx_coal_tick=<val> - number of coalescing clock ticks (us) allowed
+ *                to wait for more packets to arive before
+ *                interrupting the host, from the time the first
+ *                packet arrives.
+ *
+ *  rx_coal_tick=<val> - number of coalescing clock ticks (us) allowed
+ *                to wait for more packets to arive in the transmit ring,
+ *                before interrupting the host, after transmitting the
+ *                first packet in the ring.
+ *
+ *  max_tx_desc=<val> - maximum number of transmit descriptors
+ *                (packets) transmitted before interrupting the host.
+ *
+ *  max_rx_desc=<val> - maximum number of receive descriptors
+ *                (packets) received before interrupting the host.
+ *
+ *  tx_ratio=<val> - 7 bit value (0 - 63) specifying the split in 64th
+ *                increments of the NIC's on board memory to be used for
+ *                transmit and receive buffers. For the 1MB NIC app. 800KB
+ *                is available, on the 1/2MB NIC app. 300KB is available.
+ *                68KB will always be available as a minimum for both
+ *                directions. The default value is a 50/50 split.
+ *  dis_pci_mem_inval=<val> - disable PCI memory write and invalidate
+ *                operations, default (1) is to always disable this as
+ *                that is what Alteon does on NT. I have not been able
+ *                to measure any real performance differences with
+ *                this on my systems. Set <val>=0 if you want to
+ *                enable these operations.
+ *
+ * If you use more than one NIC, specify the parameters for the
+ * individual NICs with a comma, ie. trace=0,0x00001fff,0 you want to
+ * run tracing on NIC #2 but not on NIC #1 and #3.
+ *
+ * TODO:
+ *
+ * - Proper multicast support.
+ * - NIC dump support.
+ * - More tuning parameters.
+ *
+ * The mini ring is not used under Linux and I am not sure it makes sense
+ * to actually use it.
+ *
+ * New interrupt handler strategy:
+ *
+ * The old interrupt handler worked using the traditional method of
+ * replacing an skbuff with a new one when a packet arrives. However
+ * the rx rings do not need to contain a static number of buffer
+ * descriptors, thus it makes sense to move the memory allocation out
+ * of the main interrupt handler and do it in a bottom half handler
+ * and only allocate new buffers when the number of buffers in the
+ * ring is below a certain threshold. In order to avoid starving the
+ * NIC under heavy load it is however necessary to force allocation
+ * when hitting a minimum threshold. The strategy for alloction is as
+ * follows:
+ *
+ *     RX_LOW_BUF_THRES    - allocate buffers in the bottom half
+ *     RX_PANIC_LOW_THRES  - we are very low on buffers, allocate
+ *                           the buffers in the interrupt handler
+ *     RX_RING_THRES       - maximum number of buffers in the rx ring
+ *     RX_MINI_THRES       - maximum number of buffers in the mini ring
+ *     RX_JUMBO_THRES      - maximum number of buffers in the jumbo ring
+ *
+ * One advantagous side effect of this allocation approach is that the
+ * entire rx processing can be done without holding any spin lock
+ * since the rx rings and registers are totally independent of the tx
+ * ring and its registers.  This of course includes the kmalloc's of
+ * new skb's. Thus start_xmit can run in parallel with rx processing
+ * and the memory allocation on SMP systems.
+ *
+ * Note that running the skb reallocation in a bottom half opens up
+ * another can of races which needs to be handled properly. In
+ * particular it can happen that the interrupt handler tries to run
+ * the reallocation while the bottom half is either running on another
+ * CPU or was interrupted on the same CPU. To get around this the
+ * driver uses bitops to prevent the reallocation routines from being
+ * reentered.
+ *
+ * TX handling can also be done without holding any spin lock, wheee
+ * this is fun! since tx_ret_csm is only written to by the interrupt
+ * handler. The case to be aware of is when shutting down the device
+ * and cleaning up where it is necessary to make sure that
+ * start_xmit() is not running while this is happening. Well DaveM
+ * informs me that this case is already protected against ... bye bye
+ * Mr. Spin Lock, it was nice to know you.
+ *
+ * TX interrupts are now partly disabled so the NIC will only generate
+ * TX interrupts for the number of coal ticks, not for the number of
+ * TX packets in the queue. This should reduce the number of TX only,
+ * ie. when no RX processing is done, interrupts seen.
+ */
+
+/*
+ * Threshold values for RX buffer allocation - the low water marks for
+ * when to start refilling the rings are set to 75% of the ring
+ * sizes. It seems to make sense to refill the rings entirely from the
+ * intrrupt handler once it gets below the panic threshold, that way
+ * we don't risk that the refilling is moved to another CPU when the
+ * one running the interrupt handler just got the slab code hot in its
+ * cache.
+ */
+#define RX_RING_SIZE		72
+#define RX_MINI_SIZE		64
+#define RX_JUMBO_SIZE		48
+
+#define RX_PANIC_STD_THRES	16
+#define RX_PANIC_STD_REFILL	(3*RX_PANIC_STD_THRES)/2
+#define RX_LOW_STD_THRES	(3*RX_RING_SIZE)/4
+#define RX_PANIC_MINI_THRES	12
+#define RX_PANIC_MINI_REFILL	(3*RX_PANIC_MINI_THRES)/2
+#define RX_LOW_MINI_THRES	(3*RX_MINI_SIZE)/4
+#define RX_PANIC_JUMBO_THRES	6
+#define RX_PANIC_JUMBO_REFILL	(3*RX_PANIC_JUMBO_THRES)/2
+#define RX_LOW_JUMBO_THRES	(3*RX_JUMBO_SIZE)/4
+
+
+/*
+ * Size of the mini ring entries, basically these just should be big
+ * enough to take TCP ACKs
+ */
+#define ACE_MINI_SIZE		100
+
+#define ACE_MINI_BUFSIZE	ACE_MINI_SIZE
+#define ACE_STD_BUFSIZE		(ACE_STD_MTU + ETH_HLEN + 4)
+#define ACE_JUMBO_BUFSIZE	(ACE_JUMBO_MTU + ETH_HLEN + 4)
+
+/*
+ * There seems to be a magic difference in the effect between 995 and 996
+ * but little difference between 900 and 995 ... no idea why.
+ *
+ * There is now a default set of tuning parameters which is set, depending
+ * on whether or not the user enables Jumbo frames. It's assumed that if
+ * Jumbo frames are enabled, the user wants optimal tuning for that case.
+ */
+#define DEF_TX_COAL		400 /* 996 */
+#define DEF_TX_MAX_DESC		60  /* was 40 */
+#define DEF_RX_COAL		120 /* 1000 */
+#define DEF_RX_MAX_DESC		25
+#define DEF_TX_RATIO		21 /* 24 */
+
+#define DEF_JUMBO_TX_COAL	20
+#define DEF_JUMBO_TX_MAX_DESC	60
+#define DEF_JUMBO_RX_COAL	30
+#define DEF_JUMBO_RX_MAX_DESC	6
+#define DEF_JUMBO_TX_RATIO	21
+
+#if tigon2FwReleaseLocal < 20001118
+/*
+ * Standard firmware and early modifications duplicate
+ * IRQ load without this flag (coal timer is never reset).
+ * Note that with this flag tx_coal should be less than
+ * time to xmit full tx ring.
+ * 400usec is not so bad for tx ring size of 128.
+ */
+#define TX_COAL_INTS_ONLY	1	/* worth it */
+#else
+/*
+ * With modified firmware, this is not necessary, but still useful.
+ */
+#define TX_COAL_INTS_ONLY	1
+#endif
+
+#define DEF_TRACE		0
+#define DEF_STAT		(2 * TICKS_PER_SEC)
+
+
+static int link_state[ACE_MAX_MOD_PARMS];
+static int trace[ACE_MAX_MOD_PARMS];
+static int tx_coal_tick[ACE_MAX_MOD_PARMS];
+static int rx_coal_tick[ACE_MAX_MOD_PARMS];
+static int max_tx_desc[ACE_MAX_MOD_PARMS];
+static int max_rx_desc[ACE_MAX_MOD_PARMS];
+static int tx_ratio[ACE_MAX_MOD_PARMS];
+static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};
+
+MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver");
+#ifndef CONFIG_ACENIC_OMIT_TIGON_I
+/*(DEBLOBBED)*/
+#endif
+/*(DEBLOBBED)*/
+
+module_param_array_named(link, link_state, int, NULL, 0);
+module_param_array(trace, int, NULL, 0);
+module_param_array(tx_coal_tick, int, NULL, 0);
+module_param_array(max_tx_desc, int, NULL, 0);
+module_param_array(rx_coal_tick, int, NULL, 0);
+module_param_array(max_rx_desc, int, NULL, 0);
+module_param_array(tx_ratio, int, NULL, 0);
+MODULE_PARM_DESC(link, "AceNIC/3C985/NetGear link state");
+MODULE_PARM_DESC(trace, "AceNIC/3C985/NetGear firmware trace level");
+MODULE_PARM_DESC(tx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first tx descriptor arrives");
+MODULE_PARM_DESC(max_tx_desc, "AceNIC/3C985/GA620 max number of transmit descriptors to wait");
+MODULE_PARM_DESC(rx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first rx descriptor arrives");
+MODULE_PARM_DESC(max_rx_desc, "AceNIC/3C985/GA620 max number of receive descriptors to wait");
+MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)");
+
+
+static const char version[] __devinitconst =
+  "acenic.c: v0.92 08/05/2002  Jes Sorensen, linux-acenic@SunSITE.dk\n"
+  "                            http://home.cern.ch/~jes/gige/acenic.html\n";
+
+static int ace_get_settings(struct net_device *, struct ethtool_cmd *);
+static int ace_set_settings(struct net_device *, struct ethtool_cmd *);
+static void ace_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
+
+static const struct ethtool_ops ace_ethtool_ops = {
+	.get_settings = ace_get_settings,
+	.set_settings = ace_set_settings,
+	.get_drvinfo = ace_get_drvinfo,
+};
+
+static void ace_watchdog(struct net_device *dev);
+
+static const struct net_device_ops ace_netdev_ops = {
+	.ndo_open		= ace_open,
+	.ndo_stop		= ace_close,
+	.ndo_tx_timeout		= ace_watchdog,
+	.ndo_get_stats		= ace_get_stats,
+	.ndo_start_xmit		= ace_start_xmit,
+	.ndo_set_rx_mode	= ace_set_multicast_list,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= ace_set_mac_addr,
+	.ndo_change_mtu		= ace_change_mtu,
+};
+
+static int __devinit acenic_probe_one(struct pci_dev *pdev,
+		const struct pci_device_id *id)
+{
+	struct net_device *dev;
+	struct ace_private *ap;
+	static int boards_found;
+
+	dev = alloc_etherdev(sizeof(struct ace_private));
+	if (dev == NULL) {
+		printk(KERN_ERR "acenic: Unable to allocate "
+		       "net_device structure!\n");
+		return -ENOMEM;
+	}
+
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	ap = netdev_priv(dev);
+	ap->pdev = pdev;
+	ap->name = pci_name(pdev);
+
+	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+
+	dev->watchdog_timeo = 5*HZ;
+
+	dev->netdev_ops = &ace_netdev_ops;
+	SET_ETHTOOL_OPS(dev, &ace_ethtool_ops);
+
+	/* we only display this string ONCE */
+	if (!boards_found)
+		printk(version);
+
+	if (pci_enable_device(pdev))
+		goto fail_free_netdev;
+
+	/*
+	 * Enable master mode before we start playing with the
+	 * pci_command word since pci_set_master() will modify
+	 * it.
+	 */
+	pci_set_master(pdev);
+
+	pci_read_config_word(pdev, PCI_COMMAND, &ap->pci_command);
+
+	/* OpenFirmware on Mac's does not set this - DOH.. */
+	if (!(ap->pci_command & PCI_COMMAND_MEMORY)) {
+		printk(KERN_INFO "%s: Enabling PCI Memory Mapped "
+		       "access - was not enabled by BIOS/Firmware\n",
+		       ap->name);
+		ap->pci_command = ap->pci_command | PCI_COMMAND_MEMORY;
+		pci_write_config_word(ap->pdev, PCI_COMMAND,
+				      ap->pci_command);
+		wmb();
+	}
+
+	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &ap->pci_latency);
+	if (ap->pci_latency <= 0x40) {
+		ap->pci_latency = 0x40;
+		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, ap->pci_latency);
+	}
+
+	/*
+	 * Remap the regs into kernel space - this is abuse of
+	 * dev->base_addr since it was means for I/O port
+	 * addresses but who gives a damn.
+	 */
+	dev->base_addr = pci_resource_start(pdev, 0);
+	ap->regs = ioremap(dev->base_addr, 0x4000);
+	if (!ap->regs) {
+		printk(KERN_ERR "%s:  Unable to map I/O register, "
+		       "AceNIC %i will be disabled.\n",
+		       ap->name, boards_found);
+		goto fail_free_netdev;
+	}
+
+	switch(pdev->vendor) {
+	case PCI_VENDOR_ID_ALTEON:
+		if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) {
+			printk(KERN_INFO "%s: Farallon PN9100-T ",
+			       ap->name);
+		} else {
+			printk(KERN_INFO "%s: Alteon AceNIC ",
+			       ap->name);
+		}
+		break;
+	case PCI_VENDOR_ID_3COM:
+		printk(KERN_INFO "%s: 3Com 3C985 ", ap->name);
+		break;
+	case PCI_VENDOR_ID_NETGEAR:
+		printk(KERN_INFO "%s: NetGear GA620 ", ap->name);
+		break;
+	case PCI_VENDOR_ID_DEC:
+		if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX) {
+			printk(KERN_INFO "%s: Farallon PN9000-SX ",
+			       ap->name);
+			break;
+		}
+	case PCI_VENDOR_ID_SGI:
+		printk(KERN_INFO "%s: SGI AceNIC ", ap->name);
+		break;
+	default:
+		printk(KERN_INFO "%s: Unknown AceNIC ", ap->name);
+		break;
+	}
+
+	printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr);
+	printk("irq %d\n", pdev->irq);
+
+#ifdef CONFIG_ACENIC_OMIT_TIGON_I
+	if ((readl(&ap->regs->HostCtrl) >> 28) == 4) {
+		printk(KERN_ERR "%s: Driver compiled without Tigon I"
+		       " support - NIC disabled\n", dev->name);
+		goto fail_uninit;
+	}
+#endif
+
+	if (ace_allocate_descriptors(dev))
+		goto fail_free_netdev;
+
+#ifdef MODULE
+	if (boards_found >= ACE_MAX_MOD_PARMS)
+		ap->board_idx = BOARD_IDX_OVERFLOW;
+	else
+		ap->board_idx = boards_found;
+#else
+	ap->board_idx = BOARD_IDX_STATIC;
+#endif
+
+	if (ace_init(dev))
+		goto fail_free_netdev;
+
+	if (register_netdev(dev)) {
+		printk(KERN_ERR "acenic: device registration failed\n");
+		goto fail_uninit;
+	}
+	ap->name = dev->name;
+
+	if (ap->pci_using_dac)
+		dev->features |= NETIF_F_HIGHDMA;
+
+	pci_set_drvdata(pdev, dev);
+
+	boards_found++;
+	return 0;
+
+ fail_uninit:
+	ace_init_cleanup(dev);
+ fail_free_netdev:
+	free_netdev(dev);
+	return -ENODEV;
+}
+
+static void __devexit acenic_remove_one(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	short i;
+
+	unregister_netdev(dev);
+
+	writel(readl(&regs->CpuCtrl) | CPU_HALT, &regs->CpuCtrl);
+	if (ap->version >= 2)
+		writel(readl(&regs->CpuBCtrl) | CPU_HALT, &regs->CpuBCtrl);
+
+	/*
+	 * This clears any pending interrupts
+	 */
+	writel(1, &regs->Mb0Lo);
+	readl(&regs->CpuCtrl);	/* flush */
+
+	/*
+	 * Make sure no other CPUs are processing interrupts
+	 * on the card before the buffers are being released.
+	 * Otherwise one might experience some `interesting'
+	 * effects.
+	 *
+	 * Then release the RX buffers - jumbo buffers were
+	 * already released in ace_close().
+	 */
+	ace_sync_irq(dev->irq);
+
+	for (i = 0; i < RX_STD_RING_ENTRIES; i++) {
+		struct sk_buff *skb = ap->skb->rx_std_skbuff[i].skb;
+
+		if (skb) {
+			struct ring_info *ringp;
+			dma_addr_t mapping;
+
+			ringp = &ap->skb->rx_std_skbuff[i];
+			mapping = dma_unmap_addr(ringp, mapping);
+			pci_unmap_page(ap->pdev, mapping,
+				       ACE_STD_BUFSIZE,
+				       PCI_DMA_FROMDEVICE);
+
+			ap->rx_std_ring[i].size = 0;
+			ap->skb->rx_std_skbuff[i].skb = NULL;
+			dev_kfree_skb(skb);
+		}
+	}
+
+	if (ap->version >= 2) {
+		for (i = 0; i < RX_MINI_RING_ENTRIES; i++) {
+			struct sk_buff *skb = ap->skb->rx_mini_skbuff[i].skb;
+
+			if (skb) {
+				struct ring_info *ringp;
+				dma_addr_t mapping;
+
+				ringp = &ap->skb->rx_mini_skbuff[i];
+				mapping = dma_unmap_addr(ringp,mapping);
+				pci_unmap_page(ap->pdev, mapping,
+					       ACE_MINI_BUFSIZE,
+					       PCI_DMA_FROMDEVICE);
+
+				ap->rx_mini_ring[i].size = 0;
+				ap->skb->rx_mini_skbuff[i].skb = NULL;
+				dev_kfree_skb(skb);
+			}
+		}
+	}
+
+	for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++) {
+		struct sk_buff *skb = ap->skb->rx_jumbo_skbuff[i].skb;
+		if (skb) {
+			struct ring_info *ringp;
+			dma_addr_t mapping;
+
+			ringp = &ap->skb->rx_jumbo_skbuff[i];
+			mapping = dma_unmap_addr(ringp, mapping);
+			pci_unmap_page(ap->pdev, mapping,
+				       ACE_JUMBO_BUFSIZE,
+				       PCI_DMA_FROMDEVICE);
+
+			ap->rx_jumbo_ring[i].size = 0;
+			ap->skb->rx_jumbo_skbuff[i].skb = NULL;
+			dev_kfree_skb(skb);
+		}
+	}
+
+	ace_init_cleanup(dev);
+	free_netdev(dev);
+}
+
+static struct pci_driver acenic_pci_driver = {
+	.name		= "acenic",
+	.id_table	= acenic_pci_tbl,
+	.probe		= acenic_probe_one,
+	.remove		= __devexit_p(acenic_remove_one),
+};
+
+static int __init acenic_init(void)
+{
+	return pci_register_driver(&acenic_pci_driver);
+}
+
+static void __exit acenic_exit(void)
+{
+	pci_unregister_driver(&acenic_pci_driver);
+}
+
+module_init(acenic_init);
+module_exit(acenic_exit);
+
+static void ace_free_descriptors(struct net_device *dev)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	int size;
+
+	if (ap->rx_std_ring != NULL) {
+		size = (sizeof(struct rx_desc) *
+			(RX_STD_RING_ENTRIES +
+			 RX_JUMBO_RING_ENTRIES +
+			 RX_MINI_RING_ENTRIES +
+			 RX_RETURN_RING_ENTRIES));
+		pci_free_consistent(ap->pdev, size, ap->rx_std_ring,
+				    ap->rx_ring_base_dma);
+		ap->rx_std_ring = NULL;
+		ap->rx_jumbo_ring = NULL;
+		ap->rx_mini_ring = NULL;
+		ap->rx_return_ring = NULL;
+	}
+	if (ap->evt_ring != NULL) {
+		size = (sizeof(struct event) * EVT_RING_ENTRIES);
+		pci_free_consistent(ap->pdev, size, ap->evt_ring,
+				    ap->evt_ring_dma);
+		ap->evt_ring = NULL;
+	}
+	if (ap->tx_ring != NULL && !ACE_IS_TIGON_I(ap)) {
+		size = (sizeof(struct tx_desc) * MAX_TX_RING_ENTRIES);
+		pci_free_consistent(ap->pdev, size, ap->tx_ring,
+				    ap->tx_ring_dma);
+	}
+	ap->tx_ring = NULL;
+
+	if (ap->evt_prd != NULL) {
+		pci_free_consistent(ap->pdev, sizeof(u32),
+				    (void *)ap->evt_prd, ap->evt_prd_dma);
+		ap->evt_prd = NULL;
+	}
+	if (ap->rx_ret_prd != NULL) {
+		pci_free_consistent(ap->pdev, sizeof(u32),
+				    (void *)ap->rx_ret_prd,
+				    ap->rx_ret_prd_dma);
+		ap->rx_ret_prd = NULL;
+	}
+	if (ap->tx_csm != NULL) {
+		pci_free_consistent(ap->pdev, sizeof(u32),
+				    (void *)ap->tx_csm, ap->tx_csm_dma);
+		ap->tx_csm = NULL;
+	}
+}
+
+
+static int ace_allocate_descriptors(struct net_device *dev)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	int size;
+
+	size = (sizeof(struct rx_desc) *
+		(RX_STD_RING_ENTRIES +
+		 RX_JUMBO_RING_ENTRIES +
+		 RX_MINI_RING_ENTRIES +
+		 RX_RETURN_RING_ENTRIES));
+
+	ap->rx_std_ring = pci_alloc_consistent(ap->pdev, size,
+					       &ap->rx_ring_base_dma);
+	if (ap->rx_std_ring == NULL)
+		goto fail;
+
+	ap->rx_jumbo_ring = ap->rx_std_ring + RX_STD_RING_ENTRIES;
+	ap->rx_mini_ring = ap->rx_jumbo_ring + RX_JUMBO_RING_ENTRIES;
+	ap->rx_return_ring = ap->rx_mini_ring + RX_MINI_RING_ENTRIES;
+
+	size = (sizeof(struct event) * EVT_RING_ENTRIES);
+
+	ap->evt_ring = pci_alloc_consistent(ap->pdev, size, &ap->evt_ring_dma);
+
+	if (ap->evt_ring == NULL)
+		goto fail;
+
+	/*
+	 * Only allocate a host TX ring for the Tigon II, the Tigon I
+	 * has to use PCI registers for this ;-(
+	 */
+	if (!ACE_IS_TIGON_I(ap)) {
+		size = (sizeof(struct tx_desc) * MAX_TX_RING_ENTRIES);
+
+		ap->tx_ring = pci_alloc_consistent(ap->pdev, size,
+						   &ap->tx_ring_dma);
+
+		if (ap->tx_ring == NULL)
+			goto fail;
+	}
+
+	ap->evt_prd = pci_alloc_consistent(ap->pdev, sizeof(u32),
+					   &ap->evt_prd_dma);
+	if (ap->evt_prd == NULL)
+		goto fail;
+
+	ap->rx_ret_prd = pci_alloc_consistent(ap->pdev, sizeof(u32),
+					      &ap->rx_ret_prd_dma);
+	if (ap->rx_ret_prd == NULL)
+		goto fail;
+
+	ap->tx_csm = pci_alloc_consistent(ap->pdev, sizeof(u32),
+					  &ap->tx_csm_dma);
+	if (ap->tx_csm == NULL)
+		goto fail;
+
+	return 0;
+
+fail:
+	/* Clean up. */
+	ace_init_cleanup(dev);
+	return 1;
+}
+
+
+/*
+ * Generic cleanup handling data allocated during init. Used when the
+ * module is unloaded or if an error occurs during initialization
+ */
+static void ace_init_cleanup(struct net_device *dev)
+{
+	struct ace_private *ap;
+
+	ap = netdev_priv(dev);
+
+	ace_free_descriptors(dev);
+
+	if (ap->info)
+		pci_free_consistent(ap->pdev, sizeof(struct ace_info),
+				    ap->info, ap->info_dma);
+	kfree(ap->skb);
+	kfree(ap->trace_buf);
+
+	if (dev->irq)
+		free_irq(dev->irq, dev);
+
+	iounmap(ap->regs);
+}
+
+
+/*
+ * Commands are considered to be slow.
+ */
+static inline void ace_issue_cmd(struct ace_regs __iomem *regs, struct cmd *cmd)
+{
+	u32 idx;
+
+	idx = readl(&regs->CmdPrd);
+
+	writel(*(u32 *)(cmd), &regs->CmdRng[idx]);
+	idx = (idx + 1) % CMD_RING_ENTRIES;
+
+	writel(idx, &regs->CmdPrd);
+}
+
+
+static int __devinit ace_init(struct net_device *dev)
+{
+	struct ace_private *ap;
+	struct ace_regs __iomem *regs;
+	struct ace_info *info = NULL;
+	struct pci_dev *pdev;
+	unsigned long myjif;
+	u64 tmp_ptr;
+	u32 tig_ver, mac1, mac2, tmp, pci_state;
+	int board_idx, ecode = 0;
+	short i;
+	unsigned char cache_size;
+
+	ap = netdev_priv(dev);
+	regs = ap->regs;
+
+	board_idx = ap->board_idx;
+
+	/*
+	 * aman@sgi.com - its useful to do a NIC reset here to
+	 * address the `Firmware not running' problem subsequent
+	 * to any crashes involving the NIC
+	 */
+	writel(HW_RESET | (HW_RESET << 24), &regs->HostCtrl);
+	readl(&regs->HostCtrl);		/* PCI write posting */
+	udelay(5);
+
+	/*
+	 * Don't access any other registers before this point!
+	 */
+#ifdef __BIG_ENDIAN
+	/*
+	 * This will most likely need BYTE_SWAP once we switch
+	 * to using __raw_writel()
+	 */
+	writel((WORD_SWAP | CLR_INT | ((WORD_SWAP | CLR_INT) << 24)),
+	       &regs->HostCtrl);
+#else
+	writel((CLR_INT | WORD_SWAP | ((CLR_INT | WORD_SWAP) << 24)),
+	       &regs->HostCtrl);
+#endif
+	readl(&regs->HostCtrl);		/* PCI write posting */
+
+	/*
+	 * Stop the NIC CPU and clear pending interrupts
+	 */
+	writel(readl(&regs->CpuCtrl) | CPU_HALT, &regs->CpuCtrl);
+	readl(&regs->CpuCtrl);		/* PCI write posting */
+	writel(0, &regs->Mb0Lo);
+
+	tig_ver = readl(&regs->HostCtrl) >> 28;
+
+	switch(tig_ver){
+#ifndef CONFIG_ACENIC_OMIT_TIGON_I
+	case 4:
+	case 5:
+		printk(KERN_INFO "  Tigon I  (Rev. %i), Firmware: %i.%i.%i, ",
+		       tig_ver, ap->firmware_major, ap->firmware_minor,
+		       ap->firmware_fix);
+		writel(0, &regs->LocalCtrl);
+		ap->version = 1;
+		ap->tx_ring_entries = TIGON_I_TX_RING_ENTRIES;
+		break;
+#endif
+	case 6:
+		printk(KERN_INFO "  Tigon II (Rev. %i), Firmware: %i.%i.%i, ",
+		       tig_ver, ap->firmware_major, ap->firmware_minor,
+		       ap->firmware_fix);
+		writel(readl(&regs->CpuBCtrl) | CPU_HALT, &regs->CpuBCtrl);
+		readl(&regs->CpuBCtrl);		/* PCI write posting */
+		/*
+		 * The SRAM bank size does _not_ indicate the amount
+		 * of memory on the card, it controls the _bank_ size!
+		 * Ie. a 1MB AceNIC will have two banks of 512KB.
+		 */
+		writel(SRAM_BANK_512K, &regs->LocalCtrl);
+		writel(SYNC_SRAM_TIMING, &regs->MiscCfg);
+		ap->version = 2;
+		ap->tx_ring_entries = MAX_TX_RING_ENTRIES;
+		break;
+	default:
+		printk(KERN_WARNING "  Unsupported Tigon version detected "
+		       "(%i)\n", tig_ver);
+		ecode = -ENODEV;
+		goto init_error;
+	}
+
+	/*
+	 * ModeStat _must_ be set after the SRAM settings as this change
+	 * seems to corrupt the ModeStat and possible other registers.
+	 * The SRAM settings survive resets and setting it to the same
+	 * value a second time works as well. This is what caused the
+	 * `Firmware not running' problem on the Tigon II.
+	 */
+#ifdef __BIG_ENDIAN
+	writel(ACE_BYTE_SWAP_DMA | ACE_WARN | ACE_FATAL | ACE_BYTE_SWAP_BD |
+	       ACE_WORD_SWAP_BD | ACE_NO_JUMBO_FRAG, &regs->ModeStat);
+#else
+	writel(ACE_BYTE_SWAP_DMA | ACE_WARN | ACE_FATAL |
+	       ACE_WORD_SWAP_BD | ACE_NO_JUMBO_FRAG, &regs->ModeStat);
+#endif
+	readl(&regs->ModeStat);		/* PCI write posting */
+
+	mac1 = 0;
+	for(i = 0; i < 4; i++) {
+		int t;
+
+		mac1 = mac1 << 8;
+		t = read_eeprom_byte(dev, 0x8c+i);
+		if (t < 0) {
+			ecode = -EIO;
+			goto init_error;
+		} else
+			mac1 |= (t & 0xff);
+	}
+	mac2 = 0;
+	for(i = 4; i < 8; i++) {
+		int t;
+
+		mac2 = mac2 << 8;
+		t = read_eeprom_byte(dev, 0x8c+i);
+		if (t < 0) {
+			ecode = -EIO;
+			goto init_error;
+		} else
+			mac2 |= (t & 0xff);
+	}
+
+	writel(mac1, &regs->MacAddrHi);
+	writel(mac2, &regs->MacAddrLo);
+
+	dev->dev_addr[0] = (mac1 >> 8) & 0xff;
+	dev->dev_addr[1] = mac1 & 0xff;
+	dev->dev_addr[2] = (mac2 >> 24) & 0xff;
+	dev->dev_addr[3] = (mac2 >> 16) & 0xff;
+	dev->dev_addr[4] = (mac2 >> 8) & 0xff;
+	dev->dev_addr[5] = mac2 & 0xff;
+
+	printk("MAC: %pM\n", dev->dev_addr);
+
+	/*
+	 * Looks like this is necessary to deal with on all architectures,
+	 * even this %$#%$# N440BX Intel based thing doesn't get it right.
+	 * Ie. having two NICs in the machine, one will have the cache
+	 * line set at boot time, the other will not.
+	 */
+	pdev = ap->pdev;
+	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_size);
+	cache_size <<= 2;
+	if (cache_size != SMP_CACHE_BYTES) {
+		printk(KERN_INFO "  PCI cache line size set incorrectly "
+		       "(%i bytes) by BIOS/FW, ", cache_size);
+		if (cache_size > SMP_CACHE_BYTES)
+			printk("expecting %i\n", SMP_CACHE_BYTES);
+		else {
+			printk("correcting to %i\n", SMP_CACHE_BYTES);
+			pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE,
+					      SMP_CACHE_BYTES >> 2);
+		}
+	}
+
+	pci_state = readl(&regs->PciState);
+	printk(KERN_INFO "  PCI bus width: %i bits, speed: %iMHz, "
+	       "latency: %i clks\n",
+	       	(pci_state & PCI_32BIT) ? 32 : 64,
+		(pci_state & PCI_66MHZ) ? 66 : 33,
+		ap->pci_latency);
+
+	/*
+	 * Set the max DMA transfer size. Seems that for most systems
+	 * the performance is better when no MAX parameter is
+	 * set. However for systems enabling PCI write and invalidate,
+	 * DMA writes must be set to the L1 cache line size to get
+	 * optimal performance.
+	 *
+	 * The default is now to turn the PCI write and invalidate off
+	 * - that is what Alteon does for NT.
+	 */
+	tmp = READ_CMD_MEM | WRITE_CMD_MEM;
+	if (ap->version >= 2) {
+		tmp |= (MEM_READ_MULTIPLE | (pci_state & PCI_66MHZ));
+		/*
+		 * Tuning parameters only supported for 8 cards
+		 */
+		if (board_idx == BOARD_IDX_OVERFLOW ||
+		    dis_pci_mem_inval[board_idx]) {
+			if (ap->pci_command & PCI_COMMAND_INVALIDATE) {
+				ap->pci_command &= ~PCI_COMMAND_INVALIDATE;
+				pci_write_config_word(pdev, PCI_COMMAND,
+						      ap->pci_command);
+				printk(KERN_INFO "  Disabling PCI memory "
+				       "write and invalidate\n");
+			}
+		} else if (ap->pci_command & PCI_COMMAND_INVALIDATE) {
+			printk(KERN_INFO "  PCI memory write & invalidate "
+			       "enabled by BIOS, enabling counter measures\n");
+
+			switch(SMP_CACHE_BYTES) {
+			case 16:
+				tmp |= DMA_WRITE_MAX_16;
+				break;
+			case 32:
+				tmp |= DMA_WRITE_MAX_32;
+				break;
+			case 64:
+				tmp |= DMA_WRITE_MAX_64;
+				break;
+			case 128:
+				tmp |= DMA_WRITE_MAX_128;
+				break;
+			default:
+				printk(KERN_INFO "  Cache line size %i not "
+				       "supported, PCI write and invalidate "
+				       "disabled\n", SMP_CACHE_BYTES);
+				ap->pci_command &= ~PCI_COMMAND_INVALIDATE;
+				pci_write_config_word(pdev, PCI_COMMAND,
+						      ap->pci_command);
+			}
+		}
+	}
+
+#ifdef __sparc__
+	/*
+	 * On this platform, we know what the best dma settings
+	 * are.  We use 64-byte maximum bursts, because if we
+	 * burst larger than the cache line size (or even cross
+	 * a 64byte boundary in a single burst) the UltraSparc
+	 * PCI controller will disconnect at 64-byte multiples.
+	 *
+	 * Read-multiple will be properly enabled above, and when
+	 * set will give the PCI controller proper hints about
+	 * prefetching.
+	 */
+	tmp &= ~DMA_READ_WRITE_MASK;
+	tmp |= DMA_READ_MAX_64;
+	tmp |= DMA_WRITE_MAX_64;
+#endif
+#ifdef __alpha__
+	tmp &= ~DMA_READ_WRITE_MASK;
+	tmp |= DMA_READ_MAX_128;
+	/*
+	 * All the docs say MUST NOT. Well, I did.
+	 * Nothing terrible happens, if we load wrong size.
+	 * Bit w&i still works better!
+	 */
+	tmp |= DMA_WRITE_MAX_128;
+#endif
+	writel(tmp, &regs->PciState);
+
+#if 0
+	/*
+	 * The Host PCI bus controller driver has to set FBB.
+	 * If all devices on that PCI bus support FBB, then the controller
+	 * can enable FBB support in the Host PCI Bus controller (or on
+	 * the PCI-PCI bridge if that applies).
+	 * -ggg
+	 */
+	/*
+	 * I have received reports from people having problems when this
+	 * bit is enabled.
+	 */
+	if (!(ap->pci_command & PCI_COMMAND_FAST_BACK)) {
+		printk(KERN_INFO "  Enabling PCI Fast Back to Back\n");
+		ap->pci_command |= PCI_COMMAND_FAST_BACK;
+		pci_write_config_word(pdev, PCI_COMMAND, ap->pci_command);
+	}
+#endif
+
+	/*
+	 * Configure DMA attributes.
+	 */
+	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+		ap->pci_using_dac = 1;
+	} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+		ap->pci_using_dac = 0;
+	} else {
+		ecode = -ENODEV;
+		goto init_error;
+	}
+
+	/*
+	 * Initialize the generic info block and the command+event rings
+	 * and the control blocks for the transmit and receive rings
+	 * as they need to be setup once and for all.
+	 */
+	if (!(info = pci_alloc_consistent(ap->pdev, sizeof(struct ace_info),
+					  &ap->info_dma))) {
+		ecode = -EAGAIN;
+		goto init_error;
+	}
+	ap->info = info;
+
+	/*
+	 * Get the memory for the skb rings.
+	 */
+	if (!(ap->skb = kmalloc(sizeof(struct ace_skb), GFP_KERNEL))) {
+		ecode = -EAGAIN;
+		goto init_error;
+	}
+
+	ecode = request_irq(pdev->irq, ace_interrupt, IRQF_SHARED,
+			    DRV_NAME, dev);
+	if (ecode) {
+		printk(KERN_WARNING "%s: Requested IRQ %d is busy\n",
+		       DRV_NAME, pdev->irq);
+		goto init_error;
+	} else
+		dev->irq = pdev->irq;
+
+#ifdef INDEX_DEBUG
+	spin_lock_init(&ap->debug_lock);
+	ap->last_tx = ACE_TX_RING_ENTRIES(ap) - 1;
+	ap->last_std_rx = 0;
+	ap->last_mini_rx = 0;
+#endif
+
+	memset(ap->info, 0, sizeof(struct ace_info));
+	memset(ap->skb, 0, sizeof(struct ace_skb));
+
+	ecode = ace_load_firmware(dev);
+	if (ecode)
+		goto init_error;
+
+	ap->fw_running = 0;
+
+	tmp_ptr = ap->info_dma;
+	writel(tmp_ptr >> 32, &regs->InfoPtrHi);
+	writel(tmp_ptr & 0xffffffff, &regs->InfoPtrLo);
+
+	memset(ap->evt_ring, 0, EVT_RING_ENTRIES * sizeof(struct event));
+
+	set_aceaddr(&info->evt_ctrl.rngptr, ap->evt_ring_dma);
+	info->evt_ctrl.flags = 0;
+
+	*(ap->evt_prd) = 0;
+	wmb();
+	set_aceaddr(&info->evt_prd_ptr, ap->evt_prd_dma);
+	writel(0, &regs->EvtCsm);
+
+	set_aceaddr(&info->cmd_ctrl.rngptr, 0x100);
+	info->cmd_ctrl.flags = 0;
+	info->cmd_ctrl.max_len = 0;
+
+	for (i = 0; i < CMD_RING_ENTRIES; i++)
+		writel(0, &regs->CmdRng[i]);
+
+	writel(0, &regs->CmdPrd);
+	writel(0, &regs->CmdCsm);
+
+	tmp_ptr = ap->info_dma;
+	tmp_ptr += (unsigned long) &(((struct ace_info *)0)->s.stats);
+	set_aceaddr(&info->stats2_ptr, (dma_addr_t) tmp_ptr);
+
+	set_aceaddr(&info->rx_std_ctrl.rngptr, ap->rx_ring_base_dma);
+	info->rx_std_ctrl.max_len = ACE_STD_BUFSIZE;
+	info->rx_std_ctrl.flags =
+	  RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | RCB_FLG_VLAN_ASSIST;
+
+	memset(ap->rx_std_ring, 0,
+	       RX_STD_RING_ENTRIES * sizeof(struct rx_desc));
+
+	for (i = 0; i < RX_STD_RING_ENTRIES; i++)
+		ap->rx_std_ring[i].flags = BD_FLG_TCP_UDP_SUM;
+
+	ap->rx_std_skbprd = 0;
+	atomic_set(&ap->cur_rx_bufs, 0);
+
+	set_aceaddr(&info->rx_jumbo_ctrl.rngptr,
+		    (ap->rx_ring_base_dma +
+		     (sizeof(struct rx_desc) * RX_STD_RING_ENTRIES)));
+	info->rx_jumbo_ctrl.max_len = 0;
+	info->rx_jumbo_ctrl.flags =
+	  RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | RCB_FLG_VLAN_ASSIST;
+
+	memset(ap->rx_jumbo_ring, 0,
+	       RX_JUMBO_RING_ENTRIES * sizeof(struct rx_desc));
+
+	for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++)
+		ap->rx_jumbo_ring[i].flags = BD_FLG_TCP_UDP_SUM | BD_FLG_JUMBO;
+
+	ap->rx_jumbo_skbprd = 0;
+	atomic_set(&ap->cur_jumbo_bufs, 0);
+
+	memset(ap->rx_mini_ring, 0,
+	       RX_MINI_RING_ENTRIES * sizeof(struct rx_desc));
+
+	if (ap->version >= 2) {
+		set_aceaddr(&info->rx_mini_ctrl.rngptr,
+			    (ap->rx_ring_base_dma +
+			     (sizeof(struct rx_desc) *
+			      (RX_STD_RING_ENTRIES +
+			       RX_JUMBO_RING_ENTRIES))));
+		info->rx_mini_ctrl.max_len = ACE_MINI_SIZE;
+		info->rx_mini_ctrl.flags =
+		  RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR|RCB_FLG_VLAN_ASSIST;
+
+		for (i = 0; i < RX_MINI_RING_ENTRIES; i++)
+			ap->rx_mini_ring[i].flags =
+				BD_FLG_TCP_UDP_SUM | BD_FLG_MINI;
+	} else {
+		set_aceaddr(&info->rx_mini_ctrl.rngptr, 0);
+		info->rx_mini_ctrl.flags = RCB_FLG_RNG_DISABLE;
+		info->rx_mini_ctrl.max_len = 0;
+	}
+
+	ap->rx_mini_skbprd = 0;
+	atomic_set(&ap->cur_mini_bufs, 0);
+
+	set_aceaddr(&info->rx_return_ctrl.rngptr,
+		    (ap->rx_ring_base_dma +
+		     (sizeof(struct rx_desc) *
+		      (RX_STD_RING_ENTRIES +
+		       RX_JUMBO_RING_ENTRIES +
+		       RX_MINI_RING_ENTRIES))));
+	info->rx_return_ctrl.flags = 0;
+	info->rx_return_ctrl.max_len = RX_RETURN_RING_ENTRIES;
+
+	memset(ap->rx_return_ring, 0,
+	       RX_RETURN_RING_ENTRIES * sizeof(struct rx_desc));
+
+	set_aceaddr(&info->rx_ret_prd_ptr, ap->rx_ret_prd_dma);
+	*(ap->rx_ret_prd) = 0;
+
+	writel(TX_RING_BASE, &regs->WinBase);
+
+	if (ACE_IS_TIGON_I(ap)) {
+		ap->tx_ring = (__force struct tx_desc *) regs->Window;
+		for (i = 0; i < (TIGON_I_TX_RING_ENTRIES
+				 * sizeof(struct tx_desc)) / sizeof(u32); i++)
+			writel(0, (__force void __iomem *)ap->tx_ring  + i * 4);
+
+		set_aceaddr(&info->tx_ctrl.rngptr, TX_RING_BASE);
+	} else {
+		memset(ap->tx_ring, 0,
+		       MAX_TX_RING_ENTRIES * sizeof(struct tx_desc));
+
+		set_aceaddr(&info->tx_ctrl.rngptr, ap->tx_ring_dma);
+	}
+
+	info->tx_ctrl.max_len = ACE_TX_RING_ENTRIES(ap);
+	tmp = RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | RCB_FLG_VLAN_ASSIST;
+
+	/*
+	 * The Tigon I does not like having the TX ring in host memory ;-(
+	 */
+	if (!ACE_IS_TIGON_I(ap))
+		tmp |= RCB_FLG_TX_HOST_RING;
+#if TX_COAL_INTS_ONLY
+	tmp |= RCB_FLG_COAL_INT_ONLY;
+#endif
+	info->tx_ctrl.flags = tmp;
+
+	set_aceaddr(&info->tx_csm_ptr, ap->tx_csm_dma);
+
+	/*
+	 * Potential item for tuning parameter
+	 */
+#if 0 /* NO */
+	writel(DMA_THRESH_16W, &regs->DmaReadCfg);
+	writel(DMA_THRESH_16W, &regs->DmaWriteCfg);
+#else
+	writel(DMA_THRESH_8W, &regs->DmaReadCfg);
+	writel(DMA_THRESH_8W, &regs->DmaWriteCfg);
+#endif
+
+	writel(0, &regs->MaskInt);
+	writel(1, &regs->IfIdx);
+#if 0
+	/*
+	 * McKinley boxes do not like us fiddling with AssistState
+	 * this early
+	 */
+	writel(1, &regs->AssistState);
+#endif
+
+	writel(DEF_STAT, &regs->TuneStatTicks);
+	writel(DEF_TRACE, &regs->TuneTrace);
+
+	ace_set_rxtx_parms(dev, 0);
+
+	if (board_idx == BOARD_IDX_OVERFLOW) {
+		printk(KERN_WARNING "%s: more than %i NICs detected, "
+		       "ignoring module parameters!\n",
+		       ap->name, ACE_MAX_MOD_PARMS);
+	} else if (board_idx >= 0) {
+		if (tx_coal_tick[board_idx])
+			writel(tx_coal_tick[board_idx],
+			       &regs->TuneTxCoalTicks);
+		if (max_tx_desc[board_idx])
+			writel(max_tx_desc[board_idx], &regs->TuneMaxTxDesc);
+
+		if (rx_coal_tick[board_idx])
+			writel(rx_coal_tick[board_idx],
+			       &regs->TuneRxCoalTicks);
+		if (max_rx_desc[board_idx])
+			writel(max_rx_desc[board_idx], &regs->TuneMaxRxDesc);
+
+		if (trace[board_idx])
+			writel(trace[board_idx], &regs->TuneTrace);
+
+		if ((tx_ratio[board_idx] > 0) && (tx_ratio[board_idx] < 64))
+			writel(tx_ratio[board_idx], &regs->TxBufRat);
+	}
+
+	/*
+	 * Default link parameters
+	 */
+	tmp = LNK_ENABLE | LNK_FULL_DUPLEX | LNK_1000MB | LNK_100MB |
+		LNK_10MB | LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL | LNK_NEGOTIATE;
+	if(ap->version >= 2)
+		tmp |= LNK_TX_FLOW_CTL_Y;
+
+	/*
+	 * Override link default parameters
+	 */
+	if ((board_idx >= 0) && link_state[board_idx]) {
+		int option = link_state[board_idx];
+
+		tmp = LNK_ENABLE;
+
+		if (option & 0x01) {
+			printk(KERN_INFO "%s: Setting half duplex link\n",
+			       ap->name);
+			tmp &= ~LNK_FULL_DUPLEX;
+		}
+		if (option & 0x02)
+			tmp &= ~LNK_NEGOTIATE;
+		if (option & 0x10)
+			tmp |= LNK_10MB;
+		if (option & 0x20)
+			tmp |= LNK_100MB;
+		if (option & 0x40)
+			tmp |= LNK_1000MB;
+		if ((option & 0x70) == 0) {
+			printk(KERN_WARNING "%s: No media speed specified, "
+			       "forcing auto negotiation\n", ap->name);
+			tmp |= LNK_NEGOTIATE | LNK_1000MB |
+				LNK_100MB | LNK_10MB;
+		}
+		if ((option & 0x100) == 0)
+			tmp |= LNK_NEG_FCTL;
+		else
+			printk(KERN_INFO "%s: Disabling flow control "
+			       "negotiation\n", ap->name);
+		if (option & 0x200)
+			tmp |= LNK_RX_FLOW_CTL_Y;
+		if ((option & 0x400) && (ap->version >= 2)) {
+			printk(KERN_INFO "%s: Enabling TX flow control\n",
+			       ap->name);
+			tmp |= LNK_TX_FLOW_CTL_Y;
+		}
+	}
+
+	ap->link = tmp;
+	writel(tmp, &regs->TuneLink);
+	if (ap->version >= 2)
+		writel(tmp, &regs->TuneFastLink);
+
+	writel(ap->firmware_start, &regs->Pc);
+
+	writel(0, &regs->Mb0Lo);
+
+	/*
+	 * Set tx_csm before we start receiving interrupts, otherwise
+	 * the interrupt handler might think it is supposed to process
+	 * tx ints before we are up and running, which may cause a null
+	 * pointer access in the int handler.
+	 */
+	ap->cur_rx = 0;
+	ap->tx_prd = *(ap->tx_csm) = ap->tx_ret_csm = 0;
+
+	wmb();
+	ace_set_txprd(regs, ap, 0);
+	writel(0, &regs->RxRetCsm);
+
+       /*
+	* Enable DMA engine now.
+	* If we do this sooner, Mckinley box pukes.
+	* I assume it's because Tigon II DMA engine wants to check
+	* *something* even before the CPU is started.
+	*/
+       writel(1, &regs->AssistState);  /* enable DMA */
+
+	/*
+	 * Start the NIC CPU
+	 */
+	writel(readl(&regs->CpuCtrl) & ~(CPU_HALT|CPU_TRACE), &regs->CpuCtrl);
+	readl(&regs->CpuCtrl);
+
+	/*
+	 * Wait for the firmware to spin up - max 3 seconds.
+	 */
+	myjif = jiffies + 3 * HZ;
+	while (time_before(jiffies, myjif) && !ap->fw_running)
+		cpu_relax();
+
+	if (!ap->fw_running) {
+		printk(KERN_ERR "%s: Firmware NOT running!\n", ap->name);
+
+		ace_dump_trace(ap);
+		writel(readl(&regs->CpuCtrl) | CPU_HALT, &regs->CpuCtrl);
+		readl(&regs->CpuCtrl);
+
+		/* aman@sgi.com - account for badly behaving firmware/NIC:
+		 * - have observed that the NIC may continue to generate
+		 *   interrupts for some reason; attempt to stop it - halt
+		 *   second CPU for Tigon II cards, and also clear Mb0
+		 * - if we're a module, we'll fail to load if this was
+		 *   the only GbE card in the system => if the kernel does
+		 *   see an interrupt from the NIC, code to handle it is
+		 *   gone and OOps! - so free_irq also
+		 */
+		if (ap->version >= 2)
+			writel(readl(&regs->CpuBCtrl) | CPU_HALT,
+			       &regs->CpuBCtrl);
+		writel(0, &regs->Mb0Lo);
+		readl(&regs->Mb0Lo);
+
+		ecode = -EBUSY;
+		goto init_error;
+	}
+
+	/*
+	 * We load the ring here as there seem to be no way to tell the
+	 * firmware to wipe the ring without re-initializing it.
+	 */
+	if (!test_and_set_bit(0, &ap->std_refill_busy))
+		ace_load_std_rx_ring(dev, RX_RING_SIZE);
+	else
+		printk(KERN_ERR "%s: Someone is busy refilling the RX ring\n",
+		       ap->name);
+	if (ap->version >= 2) {
+		if (!test_and_set_bit(0, &ap->mini_refill_busy))
+			ace_load_mini_rx_ring(dev, RX_MINI_SIZE);
+		else
+			printk(KERN_ERR "%s: Someone is busy refilling "
+			       "the RX mini ring\n", ap->name);
+	}
+	return 0;
+
+ init_error:
+	ace_init_cleanup(dev);
+	return ecode;
+}
+
+
+static void ace_set_rxtx_parms(struct net_device *dev, int jumbo)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	int board_idx = ap->board_idx;
+
+	if (board_idx >= 0) {
+		if (!jumbo) {
+			if (!tx_coal_tick[board_idx])
+				writel(DEF_TX_COAL, &regs->TuneTxCoalTicks);
+			if (!max_tx_desc[board_idx])
+				writel(DEF_TX_MAX_DESC, &regs->TuneMaxTxDesc);
+			if (!rx_coal_tick[board_idx])
+				writel(DEF_RX_COAL, &regs->TuneRxCoalTicks);
+			if (!max_rx_desc[board_idx])
+				writel(DEF_RX_MAX_DESC, &regs->TuneMaxRxDesc);
+			if (!tx_ratio[board_idx])
+				writel(DEF_TX_RATIO, &regs->TxBufRat);
+		} else {
+			if (!tx_coal_tick[board_idx])
+				writel(DEF_JUMBO_TX_COAL,
+				       &regs->TuneTxCoalTicks);
+			if (!max_tx_desc[board_idx])
+				writel(DEF_JUMBO_TX_MAX_DESC,
+				       &regs->TuneMaxTxDesc);
+			if (!rx_coal_tick[board_idx])
+				writel(DEF_JUMBO_RX_COAL,
+				       &regs->TuneRxCoalTicks);
+			if (!max_rx_desc[board_idx])
+				writel(DEF_JUMBO_RX_MAX_DESC,
+				       &regs->TuneMaxRxDesc);
+			if (!tx_ratio[board_idx])
+				writel(DEF_JUMBO_TX_RATIO, &regs->TxBufRat);
+		}
+	}
+}
+
+
+static void ace_watchdog(struct net_device *data)
+{
+	struct net_device *dev = data;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+
+	/*
+	 * We haven't received a stats update event for more than 2.5
+	 * seconds and there is data in the transmit queue, thus we
+	 * assume the card is stuck.
+	 */
+	if (*ap->tx_csm != ap->tx_ret_csm) {
+		printk(KERN_WARNING "%s: Transmitter is stuck, %08x\n",
+		       dev->name, (unsigned int)readl(&regs->HostCtrl));
+		/* This can happen due to ieee flow control. */
+	} else {
+		printk(KERN_DEBUG "%s: BUG... transmitter died. Kicking it.\n",
+		       dev->name);
+#if 0
+		netif_wake_queue(dev);
+#endif
+	}
+}
+
+
+static void ace_tasklet(unsigned long arg)
+{
+	struct net_device *dev = (struct net_device *) arg;
+	struct ace_private *ap = netdev_priv(dev);
+	int cur_size;
+
+	cur_size = atomic_read(&ap->cur_rx_bufs);
+	if ((cur_size < RX_LOW_STD_THRES) &&
+	    !test_and_set_bit(0, &ap->std_refill_busy)) {
+#ifdef DEBUG
+		printk("refilling buffers (current %i)\n", cur_size);
+#endif
+		ace_load_std_rx_ring(dev, RX_RING_SIZE - cur_size);
+	}
+
+	if (ap->version >= 2) {
+		cur_size = atomic_read(&ap->cur_mini_bufs);
+		if ((cur_size < RX_LOW_MINI_THRES) &&
+		    !test_and_set_bit(0, &ap->mini_refill_busy)) {
+#ifdef DEBUG
+			printk("refilling mini buffers (current %i)\n",
+			       cur_size);
+#endif
+			ace_load_mini_rx_ring(dev, RX_MINI_SIZE - cur_size);
+		}
+	}
+
+	cur_size = atomic_read(&ap->cur_jumbo_bufs);
+	if (ap->jumbo && (cur_size < RX_LOW_JUMBO_THRES) &&
+	    !test_and_set_bit(0, &ap->jumbo_refill_busy)) {
+#ifdef DEBUG
+		printk("refilling jumbo buffers (current %i)\n", cur_size);
+#endif
+		ace_load_jumbo_rx_ring(dev, RX_JUMBO_SIZE - cur_size);
+	}
+	ap->tasklet_pending = 0;
+}
+
+
+/*
+ * Copy the contents of the NIC's trace buffer to kernel memory.
+ */
+static void ace_dump_trace(struct ace_private *ap)
+{
+#if 0
+	if (!ap->trace_buf)
+		if (!(ap->trace_buf = kmalloc(ACE_TRACE_SIZE, GFP_KERNEL)))
+		    return;
+#endif
+}
+
+
+/*
+ * Load the standard rx ring.
+ *
+ * Loading rings is safe without holding the spin lock since this is
+ * done only before the device is enabled, thus no interrupts are
+ * generated and by the interrupt handler/tasklet handler.
+ */
+static void ace_load_std_rx_ring(struct net_device *dev, int nr_bufs)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	short i, idx;
+
+
+	prefetchw(&ap->cur_rx_bufs);
+
+	idx = ap->rx_std_skbprd;
+
+	for (i = 0; i < nr_bufs; i++) {
+		struct sk_buff *skb;
+		struct rx_desc *rd;
+		dma_addr_t mapping;
+
+		skb = netdev_alloc_skb_ip_align(dev, ACE_STD_BUFSIZE);
+		if (!skb)
+			break;
+
+		mapping = pci_map_page(ap->pdev, virt_to_page(skb->data),
+				       offset_in_page(skb->data),
+				       ACE_STD_BUFSIZE,
+				       PCI_DMA_FROMDEVICE);
+		ap->skb->rx_std_skbuff[idx].skb = skb;
+		dma_unmap_addr_set(&ap->skb->rx_std_skbuff[idx],
+				   mapping, mapping);
+
+		rd = &ap->rx_std_ring[idx];
+		set_aceaddr(&rd->addr, mapping);
+		rd->size = ACE_STD_BUFSIZE;
+		rd->idx = idx;
+		idx = (idx + 1) % RX_STD_RING_ENTRIES;
+	}
+
+	if (!i)
+		goto error_out;
+
+	atomic_add(i, &ap->cur_rx_bufs);
+	ap->rx_std_skbprd = idx;
+
+	if (ACE_IS_TIGON_I(ap)) {
+		struct cmd cmd;
+		cmd.evt = C_SET_RX_PRD_IDX;
+		cmd.code = 0;
+		cmd.idx = ap->rx_std_skbprd;
+		ace_issue_cmd(regs, &cmd);
+	} else {
+		writel(idx, &regs->RxStdPrd);
+		wmb();
+	}
+
+ out:
+	clear_bit(0, &ap->std_refill_busy);
+	return;
+
+ error_out:
+	printk(KERN_INFO "Out of memory when allocating "
+	       "standard receive buffers\n");
+	goto out;
+}
+
+
+static void ace_load_mini_rx_ring(struct net_device *dev, int nr_bufs)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	short i, idx;
+
+	prefetchw(&ap->cur_mini_bufs);
+
+	idx = ap->rx_mini_skbprd;
+	for (i = 0; i < nr_bufs; i++) {
+		struct sk_buff *skb;
+		struct rx_desc *rd;
+		dma_addr_t mapping;
+
+		skb = netdev_alloc_skb_ip_align(dev, ACE_MINI_BUFSIZE);
+		if (!skb)
+			break;
+
+		mapping = pci_map_page(ap->pdev, virt_to_page(skb->data),
+				       offset_in_page(skb->data),
+				       ACE_MINI_BUFSIZE,
+				       PCI_DMA_FROMDEVICE);
+		ap->skb->rx_mini_skbuff[idx].skb = skb;
+		dma_unmap_addr_set(&ap->skb->rx_mini_skbuff[idx],
+				   mapping, mapping);
+
+		rd = &ap->rx_mini_ring[idx];
+		set_aceaddr(&rd->addr, mapping);
+		rd->size = ACE_MINI_BUFSIZE;
+		rd->idx = idx;
+		idx = (idx + 1) % RX_MINI_RING_ENTRIES;
+	}
+
+	if (!i)
+		goto error_out;
+
+	atomic_add(i, &ap->cur_mini_bufs);
+
+	ap->rx_mini_skbprd = idx;
+
+	writel(idx, &regs->RxMiniPrd);
+	wmb();
+
+ out:
+	clear_bit(0, &ap->mini_refill_busy);
+	return;
+ error_out:
+	printk(KERN_INFO "Out of memory when allocating "
+	       "mini receive buffers\n");
+	goto out;
+}
+
+
+/*
+ * Load the jumbo rx ring, this may happen at any time if the MTU
+ * is changed to a value > 1500.
+ */
+static void ace_load_jumbo_rx_ring(struct net_device *dev, int nr_bufs)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	short i, idx;
+
+	idx = ap->rx_jumbo_skbprd;
+
+	for (i = 0; i < nr_bufs; i++) {
+		struct sk_buff *skb;
+		struct rx_desc *rd;
+		dma_addr_t mapping;
+
+		skb = netdev_alloc_skb_ip_align(dev, ACE_JUMBO_BUFSIZE);
+		if (!skb)
+			break;
+
+		mapping = pci_map_page(ap->pdev, virt_to_page(skb->data),
+				       offset_in_page(skb->data),
+				       ACE_JUMBO_BUFSIZE,
+				       PCI_DMA_FROMDEVICE);
+		ap->skb->rx_jumbo_skbuff[idx].skb = skb;
+		dma_unmap_addr_set(&ap->skb->rx_jumbo_skbuff[idx],
+				   mapping, mapping);
+
+		rd = &ap->rx_jumbo_ring[idx];
+		set_aceaddr(&rd->addr, mapping);
+		rd->size = ACE_JUMBO_BUFSIZE;
+		rd->idx = idx;
+		idx = (idx + 1) % RX_JUMBO_RING_ENTRIES;
+	}
+
+	if (!i)
+		goto error_out;
+
+	atomic_add(i, &ap->cur_jumbo_bufs);
+	ap->rx_jumbo_skbprd = idx;
+
+	if (ACE_IS_TIGON_I(ap)) {
+		struct cmd cmd;
+		cmd.evt = C_SET_RX_JUMBO_PRD_IDX;
+		cmd.code = 0;
+		cmd.idx = ap->rx_jumbo_skbprd;
+		ace_issue_cmd(regs, &cmd);
+	} else {
+		writel(idx, &regs->RxJumboPrd);
+		wmb();
+	}
+
+ out:
+	clear_bit(0, &ap->jumbo_refill_busy);
+	return;
+ error_out:
+	if (net_ratelimit())
+		printk(KERN_INFO "Out of memory when allocating "
+		       "jumbo receive buffers\n");
+	goto out;
+}
+
+
+/*
+ * All events are considered to be slow (RX/TX ints do not generate
+ * events) and are handled here, outside the main interrupt handler,
+ * to reduce the size of the handler.
+ */
+static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd)
+{
+	struct ace_private *ap;
+
+	ap = netdev_priv(dev);
+
+	while (evtcsm != evtprd) {
+		switch (ap->evt_ring[evtcsm].evt) {
+		case E_FW_RUNNING:
+			printk(KERN_INFO "%s: Firmware up and running\n",
+			       ap->name);
+			ap->fw_running = 1;
+			wmb();
+			break;
+		case E_STATS_UPDATED:
+			break;
+		case E_LNK_STATE:
+		{
+			u16 code = ap->evt_ring[evtcsm].code;
+			switch (code) {
+			case E_C_LINK_UP:
+			{
+				u32 state = readl(&ap->regs->GigLnkState);
+				printk(KERN_WARNING "%s: Optical link UP "
+				       "(%s Duplex, Flow Control: %s%s)\n",
+				       ap->name,
+				       state & LNK_FULL_DUPLEX ? "Full":"Half",
+				       state & LNK_TX_FLOW_CTL_Y ? "TX " : "",
+				       state & LNK_RX_FLOW_CTL_Y ? "RX" : "");
+				break;
+			}
+			case E_C_LINK_DOWN:
+				printk(KERN_WARNING "%s: Optical link DOWN\n",
+				       ap->name);
+				break;
+			case E_C_LINK_10_100:
+				printk(KERN_WARNING "%s: 10/100BaseT link "
+				       "UP\n", ap->name);
+				break;
+			default:
+				printk(KERN_ERR "%s: Unknown optical link "
+				       "state %02x\n", ap->name, code);
+			}
+			break;
+		}
+		case E_ERROR:
+			switch(ap->evt_ring[evtcsm].code) {
+			case E_C_ERR_INVAL_CMD:
+				printk(KERN_ERR "%s: invalid command error\n",
+				       ap->name);
+				break;
+			case E_C_ERR_UNIMP_CMD:
+				printk(KERN_ERR "%s: unimplemented command "
+				       "error\n", ap->name);
+				break;
+			case E_C_ERR_BAD_CFG:
+				printk(KERN_ERR "%s: bad config error\n",
+				       ap->name);
+				break;
+			default:
+				printk(KERN_ERR "%s: unknown error %02x\n",
+				       ap->name, ap->evt_ring[evtcsm].code);
+			}
+			break;
+		case E_RESET_JUMBO_RNG:
+		{
+			int i;
+			for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++) {
+				if (ap->skb->rx_jumbo_skbuff[i].skb) {
+					ap->rx_jumbo_ring[i].size = 0;
+					set_aceaddr(&ap->rx_jumbo_ring[i].addr, 0);
+					dev_kfree_skb(ap->skb->rx_jumbo_skbuff[i].skb);
+					ap->skb->rx_jumbo_skbuff[i].skb = NULL;
+				}
+			}
+
+ 			if (ACE_IS_TIGON_I(ap)) {
+ 				struct cmd cmd;
+ 				cmd.evt = C_SET_RX_JUMBO_PRD_IDX;
+ 				cmd.code = 0;
+ 				cmd.idx = 0;
+ 				ace_issue_cmd(ap->regs, &cmd);
+ 			} else {
+ 				writel(0, &((ap->regs)->RxJumboPrd));
+ 				wmb();
+ 			}
+
+			ap->jumbo = 0;
+			ap->rx_jumbo_skbprd = 0;
+			printk(KERN_INFO "%s: Jumbo ring flushed\n",
+			       ap->name);
+			clear_bit(0, &ap->jumbo_refill_busy);
+			break;
+		}
+		default:
+			printk(KERN_ERR "%s: Unhandled event 0x%02x\n",
+			       ap->name, ap->evt_ring[evtcsm].evt);
+		}
+		evtcsm = (evtcsm + 1) % EVT_RING_ENTRIES;
+	}
+
+	return evtcsm;
+}
+
+
+static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	u32 idx;
+	int mini_count = 0, std_count = 0;
+
+	idx = rxretcsm;
+
+	prefetchw(&ap->cur_rx_bufs);
+	prefetchw(&ap->cur_mini_bufs);
+
+	while (idx != rxretprd) {
+		struct ring_info *rip;
+		struct sk_buff *skb;
+		struct rx_desc *rxdesc, *retdesc;
+		u32 skbidx;
+		int bd_flags, desc_type, mapsize;
+		u16 csum;
+
+
+		/* make sure the rx descriptor isn't read before rxretprd */
+		if (idx == rxretcsm)
+			rmb();
+
+		retdesc = &ap->rx_return_ring[idx];
+		skbidx = retdesc->idx;
+		bd_flags = retdesc->flags;
+		desc_type = bd_flags & (BD_FLG_JUMBO | BD_FLG_MINI);
+
+		switch(desc_type) {
+			/*
+			 * Normal frames do not have any flags set
+			 *
+			 * Mini and normal frames arrive frequently,
+			 * so use a local counter to avoid doing
+			 * atomic operations for each packet arriving.
+			 */
+		case 0:
+			rip = &ap->skb->rx_std_skbuff[skbidx];
+			mapsize = ACE_STD_BUFSIZE;
+			rxdesc = &ap->rx_std_ring[skbidx];
+			std_count++;
+			break;
+		case BD_FLG_JUMBO:
+			rip = &ap->skb->rx_jumbo_skbuff[skbidx];
+			mapsize = ACE_JUMBO_BUFSIZE;
+			rxdesc = &ap->rx_jumbo_ring[skbidx];
+			atomic_dec(&ap->cur_jumbo_bufs);
+			break;
+		case BD_FLG_MINI:
+			rip = &ap->skb->rx_mini_skbuff[skbidx];
+			mapsize = ACE_MINI_BUFSIZE;
+			rxdesc = &ap->rx_mini_ring[skbidx];
+			mini_count++;
+			break;
+		default:
+			printk(KERN_INFO "%s: unknown frame type (0x%02x) "
+			       "returned by NIC\n", dev->name,
+			       retdesc->flags);
+			goto error;
+		}
+
+		skb = rip->skb;
+		rip->skb = NULL;
+		pci_unmap_page(ap->pdev,
+			       dma_unmap_addr(rip, mapping),
+			       mapsize,
+			       PCI_DMA_FROMDEVICE);
+		skb_put(skb, retdesc->size);
+
+		/*
+		 * Fly baby, fly!
+		 */
+		csum = retdesc->tcp_udp_csum;
+
+		skb->protocol = eth_type_trans(skb, dev);
+
+		/*
+		 * Instead of forcing the poor tigon mips cpu to calculate
+		 * pseudo hdr checksum, we do this ourselves.
+		 */
+		if (bd_flags & BD_FLG_TCP_UDP_SUM) {
+			skb->csum = htons(csum);
+			skb->ip_summed = CHECKSUM_COMPLETE;
+		} else {
+			skb_checksum_none_assert(skb);
+		}
+
+		/* send it up */
+		if ((bd_flags & BD_FLG_VLAN_TAG))
+			__vlan_hwaccel_put_tag(skb, retdesc->vlan);
+		netif_rx(skb);
+
+		dev->stats.rx_packets++;
+		dev->stats.rx_bytes += retdesc->size;
+
+		idx = (idx + 1) % RX_RETURN_RING_ENTRIES;
+	}
+
+	atomic_sub(std_count, &ap->cur_rx_bufs);
+	if (!ACE_IS_TIGON_I(ap))
+		atomic_sub(mini_count, &ap->cur_mini_bufs);
+
+ out:
+	/*
+	 * According to the documentation RxRetCsm is obsolete with
+	 * the 12.3.x Firmware - my Tigon I NICs seem to disagree!
+	 */
+	if (ACE_IS_TIGON_I(ap)) {
+		writel(idx, &ap->regs->RxRetCsm);
+	}
+	ap->cur_rx = idx;
+
+	return;
+ error:
+	idx = rxretprd;
+	goto out;
+}
+
+
+static inline void ace_tx_int(struct net_device *dev,
+			      u32 txcsm, u32 idx)
+{
+	struct ace_private *ap = netdev_priv(dev);
+
+	do {
+		struct sk_buff *skb;
+		struct tx_ring_info *info;
+
+		info = ap->skb->tx_skbuff + idx;
+		skb = info->skb;
+
+		if (dma_unmap_len(info, maplen)) {
+			pci_unmap_page(ap->pdev, dma_unmap_addr(info, mapping),
+				       dma_unmap_len(info, maplen),
+				       PCI_DMA_TODEVICE);
+			dma_unmap_len_set(info, maplen, 0);
+		}
+
+		if (skb) {
+			dev->stats.tx_packets++;
+			dev->stats.tx_bytes += skb->len;
+			dev_kfree_skb_irq(skb);
+			info->skb = NULL;
+		}
+
+		idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
+	} while (idx != txcsm);
+
+	if (netif_queue_stopped(dev))
+		netif_wake_queue(dev);
+
+	wmb();
+	ap->tx_ret_csm = txcsm;
+
+	/* So... tx_ret_csm is advanced _after_ check for device wakeup.
+	 *
+	 * We could try to make it before. In this case we would get
+	 * the following race condition: hard_start_xmit on other cpu
+	 * enters after we advanced tx_ret_csm and fills space,
+	 * which we have just freed, so that we make illegal device wakeup.
+	 * There is no good way to workaround this (at entry
+	 * to ace_start_xmit detects this condition and prevents
+	 * ring corruption, but it is not a good workaround.)
+	 *
+	 * When tx_ret_csm is advanced after, we wake up device _only_
+	 * if we really have some space in ring (though the core doing
+	 * hard_start_xmit can see full ring for some period and has to
+	 * synchronize.) Superb.
+	 * BUT! We get another subtle race condition. hard_start_xmit
+	 * may think that ring is full between wakeup and advancing
+	 * tx_ret_csm and will stop device instantly! It is not so bad.
+	 * We are guaranteed that there is something in ring, so that
+	 * the next irq will resume transmission. To speedup this we could
+	 * mark descriptor, which closes ring with BD_FLG_COAL_NOW
+	 * (see ace_start_xmit).
+	 *
+	 * Well, this dilemma exists in all lock-free devices.
+	 * We, following scheme used in drivers by Donald Becker,
+	 * select the least dangerous.
+	 *							--ANK
+	 */
+}
+
+
+static irqreturn_t ace_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = (struct net_device *)dev_id;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	u32 idx;
+	u32 txcsm, rxretcsm, rxretprd;
+	u32 evtcsm, evtprd;
+
+	/*
+	 * In case of PCI shared interrupts or spurious interrupts,
+	 * we want to make sure it is actually our interrupt before
+	 * spending any time in here.
+	 */
+	if (!(readl(&regs->HostCtrl) & IN_INT))
+		return IRQ_NONE;
+
+	/*
+	 * ACK intr now. Otherwise we will lose updates to rx_ret_prd,
+	 * which happened _after_ rxretprd = *ap->rx_ret_prd; but before
+	 * writel(0, &regs->Mb0Lo).
+	 *
+	 * "IRQ avoidance" recommended in docs applies to IRQs served
+	 * threads and it is wrong even for that case.
+	 */
+	writel(0, &regs->Mb0Lo);
+	readl(&regs->Mb0Lo);
+
+	/*
+	 * There is no conflict between transmit handling in
+	 * start_xmit and receive processing, thus there is no reason
+	 * to take a spin lock for RX handling. Wait until we start
+	 * working on the other stuff - hey we don't need a spin lock
+	 * anymore.
+	 */
+	rxretprd = *ap->rx_ret_prd;
+	rxretcsm = ap->cur_rx;
+
+	if (rxretprd != rxretcsm)
+		ace_rx_int(dev, rxretprd, rxretcsm);
+
+	txcsm = *ap->tx_csm;
+	idx = ap->tx_ret_csm;
+
+	if (txcsm != idx) {
+		/*
+		 * If each skb takes only one descriptor this check degenerates
+		 * to identity, because new space has just been opened.
+		 * But if skbs are fragmented we must check that this index
+		 * update releases enough of space, otherwise we just
+		 * wait for device to make more work.
+		 */
+		if (!tx_ring_full(ap, txcsm, ap->tx_prd))
+			ace_tx_int(dev, txcsm, idx);
+	}
+
+	evtcsm = readl(&regs->EvtCsm);
+	evtprd = *ap->evt_prd;
+
+	if (evtcsm != evtprd) {
+		evtcsm = ace_handle_event(dev, evtcsm, evtprd);
+		writel(evtcsm, &regs->EvtCsm);
+	}
+
+	/*
+	 * This has to go last in the interrupt handler and run with
+	 * the spin lock released ... what lock?
+	 */
+	if (netif_running(dev)) {
+		int cur_size;
+		int run_tasklet = 0;
+
+		cur_size = atomic_read(&ap->cur_rx_bufs);
+		if (cur_size < RX_LOW_STD_THRES) {
+			if ((cur_size < RX_PANIC_STD_THRES) &&
+			    !test_and_set_bit(0, &ap->std_refill_busy)) {
+#ifdef DEBUG
+				printk("low on std buffers %i\n", cur_size);
+#endif
+				ace_load_std_rx_ring(dev,
+						     RX_RING_SIZE - cur_size);
+			} else
+				run_tasklet = 1;
+		}
+
+		if (!ACE_IS_TIGON_I(ap)) {
+			cur_size = atomic_read(&ap->cur_mini_bufs);
+			if (cur_size < RX_LOW_MINI_THRES) {
+				if ((cur_size < RX_PANIC_MINI_THRES) &&
+				    !test_and_set_bit(0,
+						      &ap->mini_refill_busy)) {
+#ifdef DEBUG
+					printk("low on mini buffers %i\n",
+					       cur_size);
+#endif
+					ace_load_mini_rx_ring(dev,
+							      RX_MINI_SIZE - cur_size);
+				} else
+					run_tasklet = 1;
+			}
+		}
+
+		if (ap->jumbo) {
+			cur_size = atomic_read(&ap->cur_jumbo_bufs);
+			if (cur_size < RX_LOW_JUMBO_THRES) {
+				if ((cur_size < RX_PANIC_JUMBO_THRES) &&
+				    !test_and_set_bit(0,
+						      &ap->jumbo_refill_busy)){
+#ifdef DEBUG
+					printk("low on jumbo buffers %i\n",
+					       cur_size);
+#endif
+					ace_load_jumbo_rx_ring(dev,
+							       RX_JUMBO_SIZE - cur_size);
+				} else
+					run_tasklet = 1;
+			}
+		}
+		if (run_tasklet && !ap->tasklet_pending) {
+			ap->tasklet_pending = 1;
+			tasklet_schedule(&ap->ace_tasklet);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int ace_open(struct net_device *dev)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	struct cmd cmd;
+
+	if (!(ap->fw_running)) {
+		printk(KERN_WARNING "%s: Firmware not running!\n", dev->name);
+		return -EBUSY;
+	}
+
+	writel(dev->mtu + ETH_HLEN + 4, &regs->IfMtu);
+
+	cmd.evt = C_CLEAR_STATS;
+	cmd.code = 0;
+	cmd.idx = 0;
+	ace_issue_cmd(regs, &cmd);
+
+	cmd.evt = C_HOST_STATE;
+	cmd.code = C_C_STACK_UP;
+	cmd.idx = 0;
+	ace_issue_cmd(regs, &cmd);
+
+	if (ap->jumbo &&
+	    !test_and_set_bit(0, &ap->jumbo_refill_busy))
+		ace_load_jumbo_rx_ring(dev, RX_JUMBO_SIZE);
+
+	if (dev->flags & IFF_PROMISC) {
+		cmd.evt = C_SET_PROMISC_MODE;
+		cmd.code = C_C_PROMISC_ENABLE;
+		cmd.idx = 0;
+		ace_issue_cmd(regs, &cmd);
+
+		ap->promisc = 1;
+	}else
+		ap->promisc = 0;
+	ap->mcast_all = 0;
+
+#if 0
+	cmd.evt = C_LNK_NEGOTIATION;
+	cmd.code = 0;
+	cmd.idx = 0;
+	ace_issue_cmd(regs, &cmd);
+#endif
+
+	netif_start_queue(dev);
+
+	/*
+	 * Setup the bottom half rx ring refill handler
+	 */
+	tasklet_init(&ap->ace_tasklet, ace_tasklet, (unsigned long)dev);
+	return 0;
+}
+
+
+static int ace_close(struct net_device *dev)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	struct cmd cmd;
+	unsigned long flags;
+	short i;
+
+	/*
+	 * Without (or before) releasing irq and stopping hardware, this
+	 * is an absolute non-sense, by the way. It will be reset instantly
+	 * by the first irq.
+	 */
+	netif_stop_queue(dev);
+
+
+	if (ap->promisc) {
+		cmd.evt = C_SET_PROMISC_MODE;
+		cmd.code = C_C_PROMISC_DISABLE;
+		cmd.idx = 0;
+		ace_issue_cmd(regs, &cmd);
+		ap->promisc = 0;
+	}
+
+	cmd.evt = C_HOST_STATE;
+	cmd.code = C_C_STACK_DOWN;
+	cmd.idx = 0;
+	ace_issue_cmd(regs, &cmd);
+
+	tasklet_kill(&ap->ace_tasklet);
+
+	/*
+	 * Make sure one CPU is not processing packets while
+	 * buffers are being released by another.
+	 */
+
+	local_irq_save(flags);
+	ace_mask_irq(dev);
+
+	for (i = 0; i < ACE_TX_RING_ENTRIES(ap); i++) {
+		struct sk_buff *skb;
+		struct tx_ring_info *info;
+
+		info = ap->skb->tx_skbuff + i;
+		skb = info->skb;
+
+		if (dma_unmap_len(info, maplen)) {
+			if (ACE_IS_TIGON_I(ap)) {
+				/* NB: TIGON_1 is special, tx_ring is in io space */
+				struct tx_desc __iomem *tx;
+				tx = (__force struct tx_desc __iomem *) &ap->tx_ring[i];
+				writel(0, &tx->addr.addrhi);
+				writel(0, &tx->addr.addrlo);
+				writel(0, &tx->flagsize);
+			} else
+				memset(ap->tx_ring + i, 0,
+				       sizeof(struct tx_desc));
+			pci_unmap_page(ap->pdev, dma_unmap_addr(info, mapping),
+				       dma_unmap_len(info, maplen),
+				       PCI_DMA_TODEVICE);
+			dma_unmap_len_set(info, maplen, 0);
+		}
+		if (skb) {
+			dev_kfree_skb(skb);
+			info->skb = NULL;
+		}
+	}
+
+	if (ap->jumbo) {
+		cmd.evt = C_RESET_JUMBO_RNG;
+		cmd.code = 0;
+		cmd.idx = 0;
+		ace_issue_cmd(regs, &cmd);
+	}
+
+	ace_unmask_irq(dev);
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+
+static inline dma_addr_t
+ace_map_tx_skb(struct ace_private *ap, struct sk_buff *skb,
+	       struct sk_buff *tail, u32 idx)
+{
+	dma_addr_t mapping;
+	struct tx_ring_info *info;
+
+	mapping = pci_map_page(ap->pdev, virt_to_page(skb->data),
+			       offset_in_page(skb->data),
+			       skb->len, PCI_DMA_TODEVICE);
+
+	info = ap->skb->tx_skbuff + idx;
+	info->skb = tail;
+	dma_unmap_addr_set(info, mapping, mapping);
+	dma_unmap_len_set(info, maplen, skb->len);
+	return mapping;
+}
+
+
+static inline void
+ace_load_tx_bd(struct ace_private *ap, struct tx_desc *desc, u64 addr,
+	       u32 flagsize, u32 vlan_tag)
+{
+#if !USE_TX_COAL_NOW
+	flagsize &= ~BD_FLG_COAL_NOW;
+#endif
+
+	if (ACE_IS_TIGON_I(ap)) {
+		struct tx_desc __iomem *io = (__force struct tx_desc __iomem *) desc;
+		writel(addr >> 32, &io->addr.addrhi);
+		writel(addr & 0xffffffff, &io->addr.addrlo);
+		writel(flagsize, &io->flagsize);
+		writel(vlan_tag, &io->vlanres);
+	} else {
+		desc->addr.addrhi = addr >> 32;
+		desc->addr.addrlo = addr;
+		desc->flagsize = flagsize;
+		desc->vlanres = vlan_tag;
+	}
+}
+
+
+static netdev_tx_t ace_start_xmit(struct sk_buff *skb,
+				  struct net_device *dev)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	struct tx_desc *desc;
+	u32 idx, flagsize;
+	unsigned long maxjiff = jiffies + 3*HZ;
+
+restart:
+	idx = ap->tx_prd;
+
+	if (tx_ring_full(ap, ap->tx_ret_csm, idx))
+		goto overflow;
+
+	if (!skb_shinfo(skb)->nr_frags)	{
+		dma_addr_t mapping;
+		u32 vlan_tag = 0;
+
+		mapping = ace_map_tx_skb(ap, skb, skb, idx);
+		flagsize = (skb->len << 16) | (BD_FLG_END);
+		if (skb->ip_summed == CHECKSUM_PARTIAL)
+			flagsize |= BD_FLG_TCP_UDP_SUM;
+		if (vlan_tx_tag_present(skb)) {
+			flagsize |= BD_FLG_VLAN_TAG;
+			vlan_tag = vlan_tx_tag_get(skb);
+		}
+		desc = ap->tx_ring + idx;
+		idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
+
+		/* Look at ace_tx_int for explanations. */
+		if (tx_ring_full(ap, ap->tx_ret_csm, idx))
+			flagsize |= BD_FLG_COAL_NOW;
+
+		ace_load_tx_bd(ap, desc, mapping, flagsize, vlan_tag);
+	} else {
+		dma_addr_t mapping;
+		u32 vlan_tag = 0;
+		int i, len = 0;
+
+		mapping = ace_map_tx_skb(ap, skb, NULL, idx);
+		flagsize = (skb_headlen(skb) << 16);
+		if (skb->ip_summed == CHECKSUM_PARTIAL)
+			flagsize |= BD_FLG_TCP_UDP_SUM;
+		if (vlan_tx_tag_present(skb)) {
+			flagsize |= BD_FLG_VLAN_TAG;
+			vlan_tag = vlan_tx_tag_get(skb);
+		}
+
+		ace_load_tx_bd(ap, ap->tx_ring + idx, mapping, flagsize, vlan_tag);
+
+		idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
+
+		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+			const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+			struct tx_ring_info *info;
+
+			len += skb_frag_size(frag);
+			info = ap->skb->tx_skbuff + idx;
+			desc = ap->tx_ring + idx;
+
+			mapping = skb_frag_dma_map(&ap->pdev->dev, frag, 0,
+						   skb_frag_size(frag),
+						   DMA_TO_DEVICE);
+
+			flagsize = skb_frag_size(frag) << 16;
+			if (skb->ip_summed == CHECKSUM_PARTIAL)
+				flagsize |= BD_FLG_TCP_UDP_SUM;
+			idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
+
+			if (i == skb_shinfo(skb)->nr_frags - 1) {
+				flagsize |= BD_FLG_END;
+				if (tx_ring_full(ap, ap->tx_ret_csm, idx))
+					flagsize |= BD_FLG_COAL_NOW;
+
+				/*
+				 * Only the last fragment frees
+				 * the skb!
+				 */
+				info->skb = skb;
+			} else {
+				info->skb = NULL;
+			}
+			dma_unmap_addr_set(info, mapping, mapping);
+			dma_unmap_len_set(info, maplen, skb_frag_size(frag));
+			ace_load_tx_bd(ap, desc, mapping, flagsize, vlan_tag);
+		}
+	}
+
+ 	wmb();
+ 	ap->tx_prd = idx;
+ 	ace_set_txprd(regs, ap, idx);
+
+	if (flagsize & BD_FLG_COAL_NOW) {
+		netif_stop_queue(dev);
+
+		/*
+		 * A TX-descriptor producer (an IRQ) might have gotten
+		 * between, making the ring free again. Since xmit is
+		 * serialized, this is the only situation we have to
+		 * re-test.
+		 */
+		if (!tx_ring_full(ap, ap->tx_ret_csm, idx))
+			netif_wake_queue(dev);
+	}
+
+	return NETDEV_TX_OK;
+
+overflow:
+	/*
+	 * This race condition is unavoidable with lock-free drivers.
+	 * We wake up the queue _before_ tx_prd is advanced, so that we can
+	 * enter hard_start_xmit too early, while tx ring still looks closed.
+	 * This happens ~1-4 times per 100000 packets, so that we can allow
+	 * to loop syncing to other CPU. Probably, we need an additional
+	 * wmb() in ace_tx_intr as well.
+	 *
+	 * Note that this race is relieved by reserving one more entry
+	 * in tx ring than it is necessary (see original non-SG driver).
+	 * However, with SG we need to reserve 2*MAX_SKB_FRAGS+1, which
+	 * is already overkill.
+	 *
+	 * Alternative is to return with 1 not throttling queue. In this
+	 * case loop becomes longer, no more useful effects.
+	 */
+	if (time_before(jiffies, maxjiff)) {
+		barrier();
+		cpu_relax();
+		goto restart;
+	}
+
+	/* The ring is stuck full. */
+	printk(KERN_WARNING "%s: Transmit ring stuck full\n", dev->name);
+	return NETDEV_TX_BUSY;
+}
+
+
+static int ace_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+
+	if (new_mtu > ACE_JUMBO_MTU)
+		return -EINVAL;
+
+	writel(new_mtu + ETH_HLEN + 4, &regs->IfMtu);
+	dev->mtu = new_mtu;
+
+	if (new_mtu > ACE_STD_MTU) {
+		if (!(ap->jumbo)) {
+			printk(KERN_INFO "%s: Enabling Jumbo frame "
+			       "support\n", dev->name);
+			ap->jumbo = 1;
+			if (!test_and_set_bit(0, &ap->jumbo_refill_busy))
+				ace_load_jumbo_rx_ring(dev, RX_JUMBO_SIZE);
+			ace_set_rxtx_parms(dev, 1);
+		}
+	} else {
+		while (test_and_set_bit(0, &ap->jumbo_refill_busy));
+		ace_sync_irq(dev->irq);
+		ace_set_rxtx_parms(dev, 0);
+		if (ap->jumbo) {
+			struct cmd cmd;
+
+			cmd.evt = C_RESET_JUMBO_RNG;
+			cmd.code = 0;
+			cmd.idx = 0;
+			ace_issue_cmd(regs, &cmd);
+		}
+	}
+
+	return 0;
+}
+
+static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	u32 link;
+
+	memset(ecmd, 0, sizeof(struct ethtool_cmd));
+	ecmd->supported =
+		(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+		 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+		 SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full |
+		 SUPPORTED_Autoneg | SUPPORTED_FIBRE);
+
+	ecmd->port = PORT_FIBRE;
+	ecmd->transceiver = XCVR_INTERNAL;
+
+	link = readl(&regs->GigLnkState);
+	if (link & LNK_1000MB)
+		ethtool_cmd_speed_set(ecmd, SPEED_1000);
+	else {
+		link = readl(&regs->FastLnkState);
+		if (link & LNK_100MB)
+			ethtool_cmd_speed_set(ecmd, SPEED_100);
+		else if (link & LNK_10MB)
+			ethtool_cmd_speed_set(ecmd, SPEED_10);
+		else
+			ethtool_cmd_speed_set(ecmd, 0);
+	}
+	if (link & LNK_FULL_DUPLEX)
+		ecmd->duplex = DUPLEX_FULL;
+	else
+		ecmd->duplex = DUPLEX_HALF;
+
+	if (link & LNK_NEGOTIATE)
+		ecmd->autoneg = AUTONEG_ENABLE;
+	else
+		ecmd->autoneg = AUTONEG_DISABLE;
+
+#if 0
+	/*
+	 * Current struct ethtool_cmd is insufficient
+	 */
+	ecmd->trace = readl(&regs->TuneTrace);
+
+	ecmd->txcoal = readl(&regs->TuneTxCoalTicks);
+	ecmd->rxcoal = readl(&regs->TuneRxCoalTicks);
+#endif
+	ecmd->maxtxpkt = readl(&regs->TuneMaxTxDesc);
+	ecmd->maxrxpkt = readl(&regs->TuneMaxRxDesc);
+
+	return 0;
+}
+
+static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	u32 link, speed;
+
+	link = readl(&regs->GigLnkState);
+	if (link & LNK_1000MB)
+		speed = SPEED_1000;
+	else {
+		link = readl(&regs->FastLnkState);
+		if (link & LNK_100MB)
+			speed = SPEED_100;
+		else if (link & LNK_10MB)
+			speed = SPEED_10;
+		else
+			speed = SPEED_100;
+	}
+
+	link = LNK_ENABLE | LNK_1000MB | LNK_100MB | LNK_10MB |
+		LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL;
+	if (!ACE_IS_TIGON_I(ap))
+		link |= LNK_TX_FLOW_CTL_Y;
+	if (ecmd->autoneg == AUTONEG_ENABLE)
+		link |= LNK_NEGOTIATE;
+	if (ethtool_cmd_speed(ecmd) != speed) {
+		link &= ~(LNK_1000MB | LNK_100MB | LNK_10MB);
+		switch (ethtool_cmd_speed(ecmd)) {
+		case SPEED_1000:
+			link |= LNK_1000MB;
+			break;
+		case SPEED_100:
+			link |= LNK_100MB;
+			break;
+		case SPEED_10:
+			link |= LNK_10MB;
+			break;
+		}
+	}
+
+	if (ecmd->duplex == DUPLEX_FULL)
+		link |= LNK_FULL_DUPLEX;
+
+	if (link != ap->link) {
+		struct cmd cmd;
+		printk(KERN_INFO "%s: Renegotiating link state\n",
+		       dev->name);
+
+		ap->link = link;
+		writel(link, &regs->TuneLink);
+		if (!ACE_IS_TIGON_I(ap))
+			writel(link, &regs->TuneFastLink);
+		wmb();
+
+		cmd.evt = C_LNK_NEGOTIATION;
+		cmd.code = 0;
+		cmd.idx = 0;
+		ace_issue_cmd(regs, &cmd);
+	}
+	return 0;
+}
+
+static void ace_get_drvinfo(struct net_device *dev,
+			    struct ethtool_drvinfo *info)
+{
+	struct ace_private *ap = netdev_priv(dev);
+
+	strlcpy(info->driver, "acenic", sizeof(info->driver));
+	snprintf(info->version, sizeof(info->version), "%i.%i.%i",
+		 ap->firmware_major, ap->firmware_minor,
+		 ap->firmware_fix);
+
+	if (ap->pdev)
+		strlcpy(info->bus_info, pci_name(ap->pdev),
+			sizeof(info->bus_info));
+
+}
+
+/*
+ * Set the hardware MAC address.
+ */
+static int ace_set_mac_addr(struct net_device *dev, void *p)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	struct sockaddr *addr=p;
+	u8 *da;
+	struct cmd cmd;
+
+	if(netif_running(dev))
+		return -EBUSY;
+
+	memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
+
+	da = (u8 *)dev->dev_addr;
+
+	writel(da[0] << 8 | da[1], &regs->MacAddrHi);
+	writel((da[2] << 24) | (da[3] << 16) | (da[4] << 8) | da[5],
+	       &regs->MacAddrLo);
+
+	cmd.evt = C_SET_MAC_ADDR;
+	cmd.code = 0;
+	cmd.idx = 0;
+	ace_issue_cmd(regs, &cmd);
+
+	return 0;
+}
+
+
+static void ace_set_multicast_list(struct net_device *dev)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	struct cmd cmd;
+
+	if ((dev->flags & IFF_ALLMULTI) && !(ap->mcast_all)) {
+		cmd.evt = C_SET_MULTICAST_MODE;
+		cmd.code = C_C_MCAST_ENABLE;
+		cmd.idx = 0;
+		ace_issue_cmd(regs, &cmd);
+		ap->mcast_all = 1;
+	} else if (ap->mcast_all) {
+		cmd.evt = C_SET_MULTICAST_MODE;
+		cmd.code = C_C_MCAST_DISABLE;
+		cmd.idx = 0;
+		ace_issue_cmd(regs, &cmd);
+		ap->mcast_all = 0;
+	}
+
+	if ((dev->flags & IFF_PROMISC) && !(ap->promisc)) {
+		cmd.evt = C_SET_PROMISC_MODE;
+		cmd.code = C_C_PROMISC_ENABLE;
+		cmd.idx = 0;
+		ace_issue_cmd(regs, &cmd);
+		ap->promisc = 1;
+	}else if (!(dev->flags & IFF_PROMISC) && (ap->promisc)) {
+		cmd.evt = C_SET_PROMISC_MODE;
+		cmd.code = C_C_PROMISC_DISABLE;
+		cmd.idx = 0;
+		ace_issue_cmd(regs, &cmd);
+		ap->promisc = 0;
+	}
+
+	/*
+	 * For the time being multicast relies on the upper layers
+	 * filtering it properly. The Firmware does not allow one to
+	 * set the entire multicast list at a time and keeping track of
+	 * it here is going to be messy.
+	 */
+	if (!netdev_mc_empty(dev) && !ap->mcast_all) {
+		cmd.evt = C_SET_MULTICAST_MODE;
+		cmd.code = C_C_MCAST_ENABLE;
+		cmd.idx = 0;
+		ace_issue_cmd(regs, &cmd);
+	}else if (!ap->mcast_all) {
+		cmd.evt = C_SET_MULTICAST_MODE;
+		cmd.code = C_C_MCAST_DISABLE;
+		cmd.idx = 0;
+		ace_issue_cmd(regs, &cmd);
+	}
+}
+
+
+static struct net_device_stats *ace_get_stats(struct net_device *dev)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_mac_stats __iomem *mac_stats =
+		(struct ace_mac_stats __iomem *)ap->regs->Stats;
+
+	dev->stats.rx_missed_errors = readl(&mac_stats->drop_space);
+	dev->stats.multicast = readl(&mac_stats->kept_mc);
+	dev->stats.collisions = readl(&mac_stats->coll);
+
+	return &dev->stats;
+}
+
+
+static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src,
+			       u32 dest, int size)
+{
+	void __iomem *tdest;
+	short tsize, i;
+
+	if (size <= 0)
+		return;
+
+	while (size > 0) {
+		tsize = min_t(u32, ((~dest & (ACE_WINDOW_SIZE - 1)) + 1),
+			    min_t(u32, size, ACE_WINDOW_SIZE));
+		tdest = (void __iomem *) &regs->Window +
+			(dest & (ACE_WINDOW_SIZE - 1));
+		writel(dest & ~(ACE_WINDOW_SIZE - 1), &regs->WinBase);
+		for (i = 0; i < (tsize / 4); i++) {
+			/* Firmware is big-endian */
+			writel(be32_to_cpup(src), tdest);
+			src++;
+			tdest += 4;
+			dest += 4;
+			size -= 4;
+		}
+	}
+}
+
+
+static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int size)
+{
+	void __iomem *tdest;
+	short tsize = 0, i;
+
+	if (size <= 0)
+		return;
+
+	while (size > 0) {
+		tsize = min_t(u32, ((~dest & (ACE_WINDOW_SIZE - 1)) + 1),
+				min_t(u32, size, ACE_WINDOW_SIZE));
+		tdest = (void __iomem *) &regs->Window +
+			(dest & (ACE_WINDOW_SIZE - 1));
+		writel(dest & ~(ACE_WINDOW_SIZE - 1), &regs->WinBase);
+
+		for (i = 0; i < (tsize / 4); i++) {
+			writel(0, tdest + i*4);
+		}
+
+		dest += tsize;
+		size -= tsize;
+	}
+}
+
+
+/*
+ * Download the firmware into the SRAM on the NIC
+ *
+ * This operation requires the NIC to be halted and is performed with
+ * interrupts disabled and with the spinlock hold.
+ */
+static int __devinit ace_load_firmware(struct net_device *dev)
+{
+	const struct firmware *fw;
+	const char *fw_name = "/*(DEBLOBBED)*/";
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	const __be32 *fw_data;
+	u32 load_addr;
+	int ret;
+
+	if (!(readl(&regs->CpuCtrl) & CPU_HALTED)) {
+		printk(KERN_ERR "%s: trying to download firmware while the "
+		       "CPU is running!\n", ap->name);
+		return -EFAULT;
+	}
+
+	if (ACE_IS_TIGON_I(ap))
+		fw_name = "/*(DEBLOBBED)*/";
+
+	ret = reject_firmware(&fw, fw_name, &ap->pdev->dev);
+	if (ret) {
+		printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n",
+		       ap->name, fw_name);
+		return ret;
+	}
+
+	fw_data = (void *)fw->data;
+
+	/* Firmware blob starts with version numbers, followed by
+	   load and start address. Remainder is the blob to be loaded
+	   contiguously from load address. We don't bother to represent
+	   the BSS/SBSS sections any more, since we were clearing the
+	   whole thing anyway. */
+	ap->firmware_major = fw->data[0];
+	ap->firmware_minor = fw->data[1];
+	ap->firmware_fix = fw->data[2];
+
+	ap->firmware_start = be32_to_cpu(fw_data[1]);
+	if (ap->firmware_start < 0x4000 || ap->firmware_start >= 0x80000) {
+		printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n",
+		       ap->name, ap->firmware_start, fw_name);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	load_addr = be32_to_cpu(fw_data[2]);
+	if (load_addr < 0x4000 || load_addr >= 0x80000) {
+		printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n",
+		       ap->name, load_addr, fw_name);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Do not try to clear more than 512KiB or we end up seeing
+	 * funny things on NICs with only 512KiB SRAM
+	 */
+	ace_clear(regs, 0x2000, 0x80000-0x2000);
+	ace_copy(regs, &fw_data[3], load_addr, fw->size-12);
+ out:
+	release_firmware(fw);
+	return ret;
+}
+
+
+/*
+ * The eeprom on the AceNIC is an Atmel i2c EEPROM.
+ *
+ * Accessing the EEPROM is `interesting' to say the least - don't read
+ * this code right after dinner.
+ *
+ * This is all about black magic and bit-banging the device .... I
+ * wonder in what hospital they have put the guy who designed the i2c
+ * specs.
+ *
+ * Oh yes, this is only the beginning!
+ *
+ * Thanks to Stevarino Webinski for helping tracking down the bugs in the
+ * code i2c readout code by beta testing all my hacks.
+ */
+static void __devinit eeprom_start(struct ace_regs __iomem *regs)
+{
+	u32 local;
+
+	readl(&regs->LocalCtrl);
+	udelay(ACE_SHORT_DELAY);
+	local = readl(&regs->LocalCtrl);
+	local |= EEPROM_DATA_OUT | EEPROM_WRITE_ENABLE;
+	writel(local, &regs->LocalCtrl);
+	readl(&regs->LocalCtrl);
+	mb();
+	udelay(ACE_SHORT_DELAY);
+	local |= EEPROM_CLK_OUT;
+	writel(local, &regs->LocalCtrl);
+	readl(&regs->LocalCtrl);
+	mb();
+	udelay(ACE_SHORT_DELAY);
+	local &= ~EEPROM_DATA_OUT;
+	writel(local, &regs->LocalCtrl);
+	readl(&regs->LocalCtrl);
+	mb();
+	udelay(ACE_SHORT_DELAY);
+	local &= ~EEPROM_CLK_OUT;
+	writel(local, &regs->LocalCtrl);
+	readl(&regs->LocalCtrl);
+	mb();
+}
+
+
+static void __devinit eeprom_prep(struct ace_regs __iomem *regs, u8 magic)
+{
+	short i;
+	u32 local;
+
+	udelay(ACE_SHORT_DELAY);
+	local = readl(&regs->LocalCtrl);
+	local &= ~EEPROM_DATA_OUT;
+	local |= EEPROM_WRITE_ENABLE;
+	writel(local, &regs->LocalCtrl);
+	readl(&regs->LocalCtrl);
+	mb();
+
+	for (i = 0; i < 8; i++, magic <<= 1) {
+		udelay(ACE_SHORT_DELAY);
+		if (magic & 0x80)
+			local |= EEPROM_DATA_OUT;
+		else
+			local &= ~EEPROM_DATA_OUT;
+		writel(local, &regs->LocalCtrl);
+		readl(&regs->LocalCtrl);
+		mb();
+
+		udelay(ACE_SHORT_DELAY);
+		local |= EEPROM_CLK_OUT;
+		writel(local, &regs->LocalCtrl);
+		readl(&regs->LocalCtrl);
+		mb();
+		udelay(ACE_SHORT_DELAY);
+		local &= ~(EEPROM_CLK_OUT | EEPROM_DATA_OUT);
+		writel(local, &regs->LocalCtrl);
+		readl(&regs->LocalCtrl);
+		mb();
+	}
+}
+
+
+static int __devinit eeprom_check_ack(struct ace_regs __iomem *regs)
+{
+	int state;
+	u32 local;
+
+	local = readl(&regs->LocalCtrl);
+	local &= ~EEPROM_WRITE_ENABLE;
+	writel(local, &regs->LocalCtrl);
+	readl(&regs->LocalCtrl);
+	mb();
+	udelay(ACE_LONG_DELAY);
+	local |= EEPROM_CLK_OUT;
+	writel(local, &regs->LocalCtrl);
+	readl(&regs->LocalCtrl);
+	mb();
+	udelay(ACE_SHORT_DELAY);
+	/* sample data in middle of high clk */
+	state = (readl(&regs->LocalCtrl) & EEPROM_DATA_IN) != 0;
+	udelay(ACE_SHORT_DELAY);
+	mb();
+	writel(readl(&regs->LocalCtrl) & ~EEPROM_CLK_OUT, &regs->LocalCtrl);
+	readl(&regs->LocalCtrl);
+	mb();
+
+	return state;
+}
+
+
+static void __devinit eeprom_stop(struct ace_regs __iomem *regs)
+{
+	u32 local;
+
+	udelay(ACE_SHORT_DELAY);
+	local = readl(&regs->LocalCtrl);
+	local |= EEPROM_WRITE_ENABLE;
+	writel(local, &regs->LocalCtrl);
+	readl(&regs->LocalCtrl);
+	mb();
+	udelay(ACE_SHORT_DELAY);
+	local &= ~EEPROM_DATA_OUT;
+	writel(local, &regs->LocalCtrl);
+	readl(&regs->LocalCtrl);
+	mb();
+	udelay(ACE_SHORT_DELAY);
+	local |= EEPROM_CLK_OUT;
+	writel(local, &regs->LocalCtrl);
+	readl(&regs->LocalCtrl);
+	mb();
+	udelay(ACE_SHORT_DELAY);
+	local |= EEPROM_DATA_OUT;
+	writel(local, &regs->LocalCtrl);
+	readl(&regs->LocalCtrl);
+	mb();
+	udelay(ACE_LONG_DELAY);
+	local &= ~EEPROM_CLK_OUT;
+	writel(local, &regs->LocalCtrl);
+	mb();
+}
+
+
+/*
+ * Read a whole byte from the EEPROM.
+ */
+static int __devinit read_eeprom_byte(struct net_device *dev,
+				   unsigned long offset)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	unsigned long flags;
+	u32 local;
+	int result = 0;
+	short i;
+
+	/*
+	 * Don't take interrupts on this CPU will bit banging
+	 * the %#%#@$ I2C device
+	 */
+	local_irq_save(flags);
+
+	eeprom_start(regs);
+
+	eeprom_prep(regs, EEPROM_WRITE_SELECT);
+	if (eeprom_check_ack(regs)) {
+		local_irq_restore(flags);
+		printk(KERN_ERR "%s: Unable to sync eeprom\n", ap->name);
+		result = -EIO;
+		goto eeprom_read_error;
+	}
+
+	eeprom_prep(regs, (offset >> 8) & 0xff);
+	if (eeprom_check_ack(regs)) {
+		local_irq_restore(flags);
+		printk(KERN_ERR "%s: Unable to set address byte 0\n",
+		       ap->name);
+		result = -EIO;
+		goto eeprom_read_error;
+	}
+
+	eeprom_prep(regs, offset & 0xff);
+	if (eeprom_check_ack(regs)) {
+		local_irq_restore(flags);
+		printk(KERN_ERR "%s: Unable to set address byte 1\n",
+		       ap->name);
+		result = -EIO;
+		goto eeprom_read_error;
+	}
+
+	eeprom_start(regs);
+	eeprom_prep(regs, EEPROM_READ_SELECT);
+	if (eeprom_check_ack(regs)) {
+		local_irq_restore(flags);
+		printk(KERN_ERR "%s: Unable to set READ_SELECT\n",
+		       ap->name);
+		result = -EIO;
+		goto eeprom_read_error;
+	}
+
+	for (i = 0; i < 8; i++) {
+		local = readl(&regs->LocalCtrl);
+		local &= ~EEPROM_WRITE_ENABLE;
+		writel(local, &regs->LocalCtrl);
+		readl(&regs->LocalCtrl);
+		udelay(ACE_LONG_DELAY);
+		mb();
+		local |= EEPROM_CLK_OUT;
+		writel(local, &regs->LocalCtrl);
+		readl(&regs->LocalCtrl);
+		mb();
+		udelay(ACE_SHORT_DELAY);
+		/* sample data mid high clk */
+		result = (result << 1) |
+			((readl(&regs->LocalCtrl) & EEPROM_DATA_IN) != 0);
+		udelay(ACE_SHORT_DELAY);
+		mb();
+		local = readl(&regs->LocalCtrl);
+		local &= ~EEPROM_CLK_OUT;
+		writel(local, &regs->LocalCtrl);
+		readl(&regs->LocalCtrl);
+		udelay(ACE_SHORT_DELAY);
+		mb();
+		if (i == 7) {
+			local |= EEPROM_WRITE_ENABLE;
+			writel(local, &regs->LocalCtrl);
+			readl(&regs->LocalCtrl);
+			mb();
+			udelay(ACE_SHORT_DELAY);
+		}
+	}
+
+	local |= EEPROM_DATA_OUT;
+	writel(local, &regs->LocalCtrl);
+	readl(&regs->LocalCtrl);
+	mb();
+	udelay(ACE_SHORT_DELAY);
+	writel(readl(&regs->LocalCtrl) | EEPROM_CLK_OUT, &regs->LocalCtrl);
+	readl(&regs->LocalCtrl);
+	udelay(ACE_LONG_DELAY);
+	writel(readl(&regs->LocalCtrl) & ~EEPROM_CLK_OUT, &regs->LocalCtrl);
+	readl(&regs->LocalCtrl);
+	mb();
+	udelay(ACE_SHORT_DELAY);
+	eeprom_stop(regs);
+
+	local_irq_restore(flags);
+ out:
+	return result;
+
+ eeprom_read_error:
+	printk(KERN_ERR "%s: Unable to read eeprom byte 0x%02lx\n",
+	       ap->name, offset);
+	goto out;
+}
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/alteon/acenic.h linux-libre-3.2-gnu/drivers/net/ethernet/alteon/acenic.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/alteon/acenic.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/alteon/acenic.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,790 @@
+#ifndef _ACENIC_H_
+#define _ACENIC_H_
+#include <linux/interrupt.h>
+
+
+/*
+ * Generate TX index update each time, when TX ring is closed.
+ * Normally, this is not useful, because results in more dma (and irqs
+ * without TX_COAL_INTS_ONLY).
+ */
+#define USE_TX_COAL_NOW	 0
+
+/*
+ * Addressing:
+ *
+ * The Tigon uses 64-bit host addresses, regardless of their actual
+ * length, and it expects a big-endian format. For 32 bit systems the
+ * upper 32 bits of the address are simply ignored (zero), however for
+ * little endian 64 bit systems (Alpha) this looks strange with the
+ * two parts of the address word being swapped.
+ *
+ * The addresses are split in two 32 bit words for all architectures
+ * as some of them are in PCI shared memory and it is necessary to use
+ * readl/writel to access them.
+ *
+ * The addressing code is derived from Pete Wyckoff's work, but
+ * modified to deal properly with readl/writel usage.
+ */
+
+struct ace_regs {
+	u32	pad0[16];	/* PCI control registers */
+
+	u32	HostCtrl;	/* 0x40 */
+	u32	LocalCtrl;
+
+	u32	pad1[2];
+
+	u32	MiscCfg;	/* 0x50 */
+
+	u32	pad2[2];
+
+	u32	PciState;
+
+	u32	pad3[2];	/* 0x60 */
+
+	u32	WinBase;
+	u32	WinData;
+
+	u32	pad4[12];	/* 0x70 */
+
+	u32	DmaWriteState;	/* 0xa0 */
+	u32	pad5[3];
+	u32	DmaReadState;	/* 0xb0 */
+
+	u32	pad6[26];
+
+	u32	AssistState;
+
+	u32	pad7[8];	/* 0x120 */
+
+	u32	CpuCtrl;	/* 0x140 */
+	u32	Pc;
+
+	u32	pad8[3];
+
+	u32	SramAddr;	/* 0x154 */
+	u32	SramData;
+
+	u32	pad9[49];
+
+	u32	MacRxState;	/* 0x220 */
+
+	u32	pad10[7];
+
+	u32	CpuBCtrl;	/* 0x240 */
+	u32	PcB;
+
+	u32	pad11[3];
+
+	u32	SramBAddr;	/* 0x254 */
+	u32	SramBData;
+
+	u32	pad12[105];
+
+	u32	pad13[32];	/* 0x400 */
+	u32	Stats[32];
+
+	u32	Mb0Hi;		/* 0x500 */
+	u32	Mb0Lo;
+	u32	Mb1Hi;
+	u32	CmdPrd;
+	u32	Mb2Hi;
+	u32	TxPrd;
+	u32	Mb3Hi;
+	u32	RxStdPrd;
+	u32	Mb4Hi;
+	u32	RxJumboPrd;
+	u32	Mb5Hi;
+	u32	RxMiniPrd;
+	u32	Mb6Hi;
+	u32	Mb6Lo;
+	u32	Mb7Hi;
+	u32	Mb7Lo;
+	u32	Mb8Hi;
+	u32	Mb8Lo;
+	u32	Mb9Hi;
+	u32	Mb9Lo;
+	u32	MbAHi;
+	u32	MbALo;
+	u32	MbBHi;
+	u32	MbBLo;
+	u32	MbCHi;
+	u32	MbCLo;
+	u32	MbDHi;
+	u32	MbDLo;
+	u32	MbEHi;
+	u32	MbELo;
+	u32	MbFHi;
+	u32	MbFLo;
+
+	u32	pad14[32];
+
+	u32	MacAddrHi;	/* 0x600 */
+	u32	MacAddrLo;
+	u32	InfoPtrHi;
+	u32	InfoPtrLo;
+	u32	MultiCastHi;	/* 0x610 */
+	u32	MultiCastLo;
+	u32	ModeStat;
+	u32	DmaReadCfg;
+	u32	DmaWriteCfg;	/* 0x620 */
+	u32	TxBufRat;
+	u32	EvtCsm;
+	u32	CmdCsm;
+	u32	TuneRxCoalTicks;/* 0x630 */
+	u32	TuneTxCoalTicks;
+	u32	TuneStatTicks;
+	u32	TuneMaxTxDesc;
+	u32	TuneMaxRxDesc;	/* 0x640 */
+	u32	TuneTrace;
+	u32	TuneLink;
+	u32	TuneFastLink;
+	u32	TracePtr;	/* 0x650 */
+	u32	TraceStrt;
+	u32	TraceLen;
+	u32	IfIdx;
+	u32	IfMtu;		/* 0x660 */
+	u32	MaskInt;
+	u32	GigLnkState;
+	u32	FastLnkState;
+	u32	pad16[4];	/* 0x670 */
+	u32	RxRetCsm;	/* 0x680 */
+
+	u32	pad17[31];
+
+	u32	CmdRng[64];	/* 0x700 */
+	u32	Window[0x200];
+};
+
+
+typedef struct {
+	u32 addrhi;
+	u32 addrlo;
+} aceaddr;
+
+
+#define ACE_WINDOW_SIZE	0x800
+
+#define ACE_JUMBO_MTU 9000
+#define ACE_STD_MTU 1500
+
+#define ACE_TRACE_SIZE 0x8000
+
+/*
+ * Host control register bits.
+ */
+
+#define IN_INT		0x01
+#define CLR_INT		0x02
+#define HW_RESET	0x08
+#define BYTE_SWAP	0x10
+#define WORD_SWAP	0x20
+#define MASK_INTS	0x40
+
+/*
+ * Local control register bits.
+ */
+
+#define EEPROM_DATA_IN		0x800000
+#define EEPROM_DATA_OUT		0x400000
+#define EEPROM_WRITE_ENABLE	0x200000
+#define EEPROM_CLK_OUT		0x100000
+
+#define EEPROM_BASE		0xa0000000
+
+#define EEPROM_WRITE_SELECT	0xa0
+#define EEPROM_READ_SELECT	0xa1
+
+#define SRAM_BANK_512K		0x200
+
+
+/*
+ * udelay() values for when clocking the eeprom
+ */
+#define ACE_SHORT_DELAY		2
+#define ACE_LONG_DELAY		4
+
+
+/*
+ * Misc Config bits
+ */
+
+#define SYNC_SRAM_TIMING	0x100000
+
+
+/*
+ * CPU state bits.
+ */
+
+#define CPU_RESET		0x01
+#define CPU_TRACE		0x02
+#define CPU_PROM_FAILED		0x10
+#define CPU_HALT		0x00010000
+#define CPU_HALTED		0xffff0000
+
+
+/*
+ * PCI State bits.
+ */
+
+#define DMA_READ_MAX_4		0x04
+#define DMA_READ_MAX_16		0x08
+#define DMA_READ_MAX_32		0x0c
+#define DMA_READ_MAX_64		0x10
+#define DMA_READ_MAX_128	0x14
+#define DMA_READ_MAX_256	0x18
+#define DMA_READ_MAX_1K		0x1c
+#define DMA_WRITE_MAX_4		0x20
+#define DMA_WRITE_MAX_16	0x40
+#define DMA_WRITE_MAX_32	0x60
+#define DMA_WRITE_MAX_64	0x80
+#define DMA_WRITE_MAX_128	0xa0
+#define DMA_WRITE_MAX_256	0xc0
+#define DMA_WRITE_MAX_1K	0xe0
+#define DMA_READ_WRITE_MASK	0xfc
+#define MEM_READ_MULTIPLE	0x00020000
+#define PCI_66MHZ		0x00080000
+#define PCI_32BIT		0x00100000
+#define DMA_WRITE_ALL_ALIGN	0x00800000
+#define READ_CMD_MEM		0x06000000
+#define WRITE_CMD_MEM		0x70000000
+
+
+/*
+ * Mode status
+ */
+
+#define ACE_BYTE_SWAP_BD	0x02
+#define ACE_WORD_SWAP_BD	0x04		/* not actually used */
+#define ACE_WARN		0x08
+#define ACE_BYTE_SWAP_DMA	0x10
+#define ACE_NO_JUMBO_FRAG	0x200
+#define ACE_FATAL		0x40000000
+
+
+/*
+ * DMA config
+ */
+
+#define DMA_THRESH_1W		0x10
+#define DMA_THRESH_2W		0x20
+#define DMA_THRESH_4W		0x40
+#define DMA_THRESH_8W		0x80
+#define DMA_THRESH_16W		0x100
+#define DMA_THRESH_32W		0x0	/* not described in doc, but exists. */
+
+
+/*
+ * Tuning parameters
+ */
+
+#define TICKS_PER_SEC		1000000
+
+
+/*
+ * Link bits
+ */
+
+#define LNK_PREF		0x00008000
+#define LNK_10MB		0x00010000
+#define LNK_100MB		0x00020000
+#define LNK_1000MB		0x00040000
+#define LNK_FULL_DUPLEX		0x00080000
+#define LNK_HALF_DUPLEX		0x00100000
+#define LNK_TX_FLOW_CTL_Y	0x00200000
+#define LNK_NEG_ADVANCED	0x00400000
+#define LNK_RX_FLOW_CTL_Y	0x00800000
+#define LNK_NIC			0x01000000
+#define LNK_JAM			0x02000000
+#define LNK_JUMBO		0x04000000
+#define LNK_ALTEON		0x08000000
+#define LNK_NEG_FCTL		0x10000000
+#define LNK_NEGOTIATE		0x20000000
+#define LNK_ENABLE		0x40000000
+#define LNK_UP			0x80000000
+
+
+/*
+ * Event definitions
+ */
+
+#define EVT_RING_ENTRIES	256
+#define EVT_RING_SIZE	(EVT_RING_ENTRIES * sizeof(struct event))
+
+struct event {
+#ifdef __LITTLE_ENDIAN_BITFIELD
+	u32	idx:12;
+	u32	code:12;
+	u32	evt:8;
+#else
+	u32	evt:8;
+	u32	code:12;
+	u32	idx:12;
+#endif
+	u32     pad;
+};
+
+
+/*
+ * Events
+ */
+
+#define E_FW_RUNNING		0x01
+#define E_STATS_UPDATED		0x04
+
+#define E_STATS_UPDATE		0x04
+
+#define E_LNK_STATE		0x06
+#define E_C_LINK_UP		0x01
+#define E_C_LINK_DOWN		0x02
+#define E_C_LINK_10_100		0x03
+
+#define E_ERROR			0x07
+#define E_C_ERR_INVAL_CMD	0x01
+#define E_C_ERR_UNIMP_CMD	0x02
+#define E_C_ERR_BAD_CFG		0x03
+
+#define E_MCAST_LIST		0x08
+#define E_C_MCAST_ADDR_ADD	0x01
+#define E_C_MCAST_ADDR_DEL	0x02
+
+#define E_RESET_JUMBO_RNG	0x09
+
+
+/*
+ * Commands
+ */
+
+#define CMD_RING_ENTRIES	64
+
+struct cmd {
+#ifdef __LITTLE_ENDIAN_BITFIELD
+	u32	idx:12;
+	u32	code:12;
+	u32	evt:8;
+#else
+	u32	evt:8;
+	u32	code:12;
+	u32	idx:12;
+#endif
+};
+
+
+#define C_HOST_STATE		0x01
+#define C_C_STACK_UP		0x01
+#define C_C_STACK_DOWN		0x02
+
+#define C_FDR_FILTERING		0x02
+#define C_C_FDR_FILT_ENABLE	0x01
+#define C_C_FDR_FILT_DISABLE	0x02
+
+#define C_SET_RX_PRD_IDX	0x03
+#define C_UPDATE_STATS		0x04
+#define C_RESET_JUMBO_RNG	0x05
+#define C_ADD_MULTICAST_ADDR	0x08
+#define C_DEL_MULTICAST_ADDR	0x09
+
+#define C_SET_PROMISC_MODE	0x0a
+#define C_C_PROMISC_ENABLE	0x01
+#define C_C_PROMISC_DISABLE	0x02
+
+#define C_LNK_NEGOTIATION	0x0b
+#define C_C_NEGOTIATE_BOTH	0x00
+#define C_C_NEGOTIATE_GIG	0x01
+#define C_C_NEGOTIATE_10_100	0x02
+
+#define C_SET_MAC_ADDR		0x0c
+#define C_CLEAR_PROFILE		0x0d
+
+#define C_SET_MULTICAST_MODE	0x0e
+#define C_C_MCAST_ENABLE	0x01
+#define C_C_MCAST_DISABLE	0x02
+
+#define C_CLEAR_STATS		0x0f
+#define C_SET_RX_JUMBO_PRD_IDX	0x10
+#define C_REFRESH_STATS		0x11
+
+
+/*
+ * Descriptor flags
+ */
+#define BD_FLG_TCP_UDP_SUM	0x01
+#define BD_FLG_IP_SUM		0x02
+#define BD_FLG_END		0x04
+#define BD_FLG_MORE		0x08
+#define BD_FLG_JUMBO		0x10
+#define BD_FLG_UCAST		0x20
+#define BD_FLG_MCAST		0x40
+#define BD_FLG_BCAST		0x60
+#define BD_FLG_TYP_MASK		0x60
+#define BD_FLG_IP_FRAG		0x80
+#define BD_FLG_IP_FRAG_END	0x100
+#define BD_FLG_VLAN_TAG		0x200
+#define BD_FLG_FRAME_ERROR	0x400
+#define BD_FLG_COAL_NOW		0x800
+#define BD_FLG_MINI		0x1000
+
+
+/*
+ * Ring Control block flags
+ */
+#define RCB_FLG_TCP_UDP_SUM	0x01
+#define RCB_FLG_IP_SUM		0x02
+#define RCB_FLG_NO_PSEUDO_HDR	0x08
+#define RCB_FLG_VLAN_ASSIST	0x10
+#define RCB_FLG_COAL_INT_ONLY	0x20
+#define RCB_FLG_TX_HOST_RING	0x40
+#define RCB_FLG_IEEE_SNAP_SUM	0x80
+#define RCB_FLG_EXT_RX_BD	0x100
+#define RCB_FLG_RNG_DISABLE	0x200
+
+
+/*
+ * TX ring - maximum TX ring entries for Tigon I's is 128
+ */
+#define MAX_TX_RING_ENTRIES	256
+#define TIGON_I_TX_RING_ENTRIES	128
+#define TX_RING_SIZE		(MAX_TX_RING_ENTRIES * sizeof(struct tx_desc))
+#define TX_RING_BASE		0x3800
+
+struct tx_desc{
+        aceaddr	addr;
+	u32	flagsize;
+#if 0
+/*
+ * This is in PCI shared mem and must be accessed with readl/writel
+ * real layout is:
+ */
+#if __LITTLE_ENDIAN
+	u16	flags;
+	u16	size;
+	u16	vlan;
+	u16	reserved;
+#else
+	u16	size;
+	u16	flags;
+	u16	reserved;
+	u16	vlan;
+#endif
+#endif
+	u32	vlanres;
+};
+
+
+#define RX_STD_RING_ENTRIES	512
+#define RX_STD_RING_SIZE	(RX_STD_RING_ENTRIES * sizeof(struct rx_desc))
+
+#define RX_JUMBO_RING_ENTRIES	256
+#define RX_JUMBO_RING_SIZE	(RX_JUMBO_RING_ENTRIES *sizeof(struct rx_desc))
+
+#define RX_MINI_RING_ENTRIES	1024
+#define RX_MINI_RING_SIZE	(RX_MINI_RING_ENTRIES *sizeof(struct rx_desc))
+
+#define RX_RETURN_RING_ENTRIES	2048
+#define RX_RETURN_RING_SIZE	(RX_MAX_RETURN_RING_ENTRIES * \
+				 sizeof(struct rx_desc))
+
+struct rx_desc{
+	aceaddr	addr;
+#ifdef __LITTLE_ENDIAN
+	u16	size;
+	u16	idx;
+#else
+	u16	idx;
+	u16	size;
+#endif
+#ifdef __LITTLE_ENDIAN
+	u16	flags;
+	u16	type;
+#else
+	u16	type;
+	u16	flags;
+#endif
+#ifdef __LITTLE_ENDIAN
+	u16	tcp_udp_csum;
+	u16	ip_csum;
+#else
+	u16	ip_csum;
+	u16	tcp_udp_csum;
+#endif
+#ifdef __LITTLE_ENDIAN
+	u16	vlan;
+	u16	err_flags;
+#else
+	u16	err_flags;
+	u16	vlan;
+#endif
+	u32	reserved;
+	u32	opague;
+};
+
+
+/*
+ * This struct is shared with the NIC firmware.
+ */
+struct ring_ctrl {
+	aceaddr	rngptr;
+#ifdef __LITTLE_ENDIAN
+	u16	flags;
+	u16	max_len;
+#else
+	u16	max_len;
+	u16	flags;
+#endif
+	u32	pad;
+};
+
+
+struct ace_mac_stats {
+	u32 excess_colls;
+	u32 coll_1;
+	u32 coll_2;
+	u32 coll_3;
+	u32 coll_4;
+	u32 coll_5;
+	u32 coll_6;
+	u32 coll_7;
+	u32 coll_8;
+	u32 coll_9;
+	u32 coll_10;
+	u32 coll_11;
+	u32 coll_12;
+	u32 coll_13;
+	u32 coll_14;
+	u32 coll_15;
+	u32 late_coll;
+	u32 defers;
+	u32 crc_err;
+	u32 underrun;
+	u32 crs_err;
+	u32 pad[3];
+	u32 drop_ula;
+	u32 drop_mc;
+	u32 drop_fc;
+	u32 drop_space;
+	u32 coll;
+	u32 kept_bc;
+	u32 kept_mc;
+	u32 kept_uc;
+};
+
+
+struct ace_info {
+	union {
+		u32 stats[256];
+	} s;
+	struct ring_ctrl	evt_ctrl;
+	struct ring_ctrl	cmd_ctrl;
+	struct ring_ctrl	tx_ctrl;
+	struct ring_ctrl	rx_std_ctrl;
+	struct ring_ctrl	rx_jumbo_ctrl;
+	struct ring_ctrl	rx_mini_ctrl;
+	struct ring_ctrl	rx_return_ctrl;
+	aceaddr	evt_prd_ptr;
+	aceaddr	rx_ret_prd_ptr;
+	aceaddr	tx_csm_ptr;
+	aceaddr	stats2_ptr;
+};
+
+
+struct ring_info {
+	struct sk_buff		*skb;
+	DEFINE_DMA_UNMAP_ADDR(mapping);
+};
+
+
+/*
+ * Funny... As soon as we add maplen on alpha, it starts to work
+ * much slower. Hmm... is it because struct does not fit to one cacheline?
+ * So, split tx_ring_info.
+ */
+struct tx_ring_info {
+	struct sk_buff		*skb;
+	DEFINE_DMA_UNMAP_ADDR(mapping);
+	DEFINE_DMA_UNMAP_LEN(maplen);
+};
+
+
+/*
+ * struct ace_skb holding the rings of skb's. This is an awful lot of
+ * pointers, but I don't see any other smart mode to do this in an
+ * efficient manner ;-(
+ */
+struct ace_skb
+{
+	struct tx_ring_info	tx_skbuff[MAX_TX_RING_ENTRIES];
+	struct ring_info	rx_std_skbuff[RX_STD_RING_ENTRIES];
+	struct ring_info	rx_mini_skbuff[RX_MINI_RING_ENTRIES];
+	struct ring_info	rx_jumbo_skbuff[RX_JUMBO_RING_ENTRIES];
+};
+
+
+/*
+ * Struct private for the AceNIC.
+ *
+ * Elements are grouped so variables used by the tx handling goes
+ * together, and will go into the same cache lines etc. in order to
+ * avoid cache line contention between the rx and tx handling on SMP.
+ *
+ * Frequently accessed variables are put at the beginning of the
+ * struct to help the compiler generate better/shorter code.
+ */
+struct ace_private
+{
+	struct ace_info		*info;
+	struct ace_regs	__iomem	*regs;		/* register base */
+	struct ace_skb		*skb;
+	dma_addr_t		info_dma;	/* 32/64 bit */
+
+	int			version, link;
+	int			promisc, mcast_all;
+
+	/*
+	 * TX elements
+	 */
+	struct tx_desc		*tx_ring;
+	u32			tx_prd;
+	volatile u32		tx_ret_csm;
+	int			tx_ring_entries;
+
+	/*
+	 * RX elements
+	 */
+	unsigned long		std_refill_busy
+				__attribute__ ((aligned (SMP_CACHE_BYTES)));
+	unsigned long		mini_refill_busy, jumbo_refill_busy;
+	atomic_t		cur_rx_bufs;
+	atomic_t		cur_mini_bufs;
+	atomic_t		cur_jumbo_bufs;
+	u32			rx_std_skbprd, rx_mini_skbprd, rx_jumbo_skbprd;
+	u32			cur_rx;
+
+	struct rx_desc		*rx_std_ring;
+	struct rx_desc		*rx_jumbo_ring;
+	struct rx_desc		*rx_mini_ring;
+	struct rx_desc		*rx_return_ring;
+
+	int			tasklet_pending, jumbo;
+	struct tasklet_struct	ace_tasklet;
+
+	struct event		*evt_ring;
+
+	volatile u32		*evt_prd, *rx_ret_prd, *tx_csm;
+
+	dma_addr_t		tx_ring_dma;	/* 32/64 bit */
+	dma_addr_t		rx_ring_base_dma;
+	dma_addr_t		evt_ring_dma;
+	dma_addr_t		evt_prd_dma, rx_ret_prd_dma, tx_csm_dma;
+
+	unsigned char		*trace_buf;
+	struct pci_dev		*pdev;
+	struct net_device	*next;
+	volatile int		fw_running;
+	int			board_idx;
+	u16			pci_command;
+	u8			pci_latency;
+	const char		*name;
+#ifdef INDEX_DEBUG
+	spinlock_t		debug_lock
+				__attribute__ ((aligned (SMP_CACHE_BYTES)));
+	u32			last_tx, last_std_rx, last_mini_rx;
+#endif
+	int			pci_using_dac;
+	u8			firmware_major;
+	u8			firmware_minor;
+	u8			firmware_fix;
+	u32			firmware_start;
+};
+
+
+#define TX_RESERVED	MAX_SKB_FRAGS
+
+static inline int tx_space (struct ace_private *ap, u32 csm, u32 prd)
+{
+	return (csm - prd - 1) & (ACE_TX_RING_ENTRIES(ap) - 1);
+}
+
+#define tx_free(ap) 		tx_space((ap)->tx_ret_csm, (ap)->tx_prd, ap)
+#define tx_ring_full(ap, csm, prd)	(tx_space(ap, csm, prd) <= TX_RESERVED)
+
+static inline void set_aceaddr(aceaddr *aa, dma_addr_t addr)
+{
+	u64 baddr = (u64) addr;
+	aa->addrlo = baddr & 0xffffffff;
+	aa->addrhi = baddr >> 32;
+	wmb();
+}
+
+
+static inline void ace_set_txprd(struct ace_regs __iomem *regs,
+				 struct ace_private *ap, u32 value)
+{
+#ifdef INDEX_DEBUG
+	unsigned long flags;
+	spin_lock_irqsave(&ap->debug_lock, flags);
+	writel(value, &regs->TxPrd);
+	if (value == ap->last_tx)
+		printk(KERN_ERR "AceNIC RACE ALERT! writing identical value "
+		       "to tx producer (%i)\n", value);
+	ap->last_tx = value;
+	spin_unlock_irqrestore(&ap->debug_lock, flags);
+#else
+	writel(value, &regs->TxPrd);
+#endif
+	wmb();
+}
+
+
+static inline void ace_mask_irq(struct net_device *dev)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+
+	if (ACE_IS_TIGON_I(ap))
+		writel(1, &regs->MaskInt);
+	else
+		writel(readl(&regs->HostCtrl) | MASK_INTS, &regs->HostCtrl);
+
+	ace_sync_irq(dev->irq);
+}
+
+
+static inline void ace_unmask_irq(struct net_device *dev)
+{
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+
+	if (ACE_IS_TIGON_I(ap))
+		writel(0, &regs->MaskInt);
+	else
+		writel(readl(&regs->HostCtrl) & ~MASK_INTS, &regs->HostCtrl);
+}
+
+
+/*
+ * Prototypes
+ */
+static int ace_init(struct net_device *dev);
+static void ace_load_std_rx_ring(struct net_device *dev, int nr_bufs);
+static void ace_load_mini_rx_ring(struct net_device *dev, int nr_bufs);
+static void ace_load_jumbo_rx_ring(struct net_device *dev, int nr_bufs);
+static irqreturn_t ace_interrupt(int irq, void *dev_id);
+static int ace_load_firmware(struct net_device *dev);
+static int ace_open(struct net_device *dev);
+static netdev_tx_t ace_start_xmit(struct sk_buff *skb,
+				  struct net_device *dev);
+static int ace_close(struct net_device *dev);
+static void ace_tasklet(unsigned long dev);
+static void ace_dump_trace(struct ace_private *ap);
+static void ace_set_multicast_list(struct net_device *dev);
+static int ace_change_mtu(struct net_device *dev, int new_mtu);
+static int ace_set_mac_addr(struct net_device *dev, void *p);
+static void ace_set_rxtx_parms(struct net_device *dev, int jumbo);
+static int ace_allocate_descriptors(struct net_device *dev);
+static void ace_free_descriptors(struct net_device *dev);
+static void ace_init_cleanup(struct net_device *dev);
+static struct net_device_stats *ace_get_stats(struct net_device *dev);
+static int read_eeprom_byte(struct net_device *dev, unsigned long offset);
+
+#endif /* _ACENIC_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/alteon/Kconfig linux-libre-3.2-gnu/drivers/net/ethernet/alteon/Kconfig
--- linux-libre-3.1-gnu/drivers/net/ethernet/alteon/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/alteon/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,48 @@
+#
+# Alteon network device configuration
+#
+
+config NET_VENDOR_ALTEON
+	bool "Alteon devices"
+	default y
+	depends on PCI
+	---help---
+	  If you have a network (Ethernet) card belonging to this class, say Y
+	  and read the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  Note that the answer to this question doesn't directly affect the
+	  kernel: saying N will just cause the configurator to skip all
+	  the questions about Alteon cards. If you say Y, you will be asked for
+	  your specific card in the following questions.
+
+if NET_VENDOR_ALTEON
+
+config ACENIC
+	tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support"
+	depends on PCI
+	---help---
+	  Say Y here if you have an Alteon AceNIC, 3Com 3C985(B), NetGear
+	  GA620, SGI Gigabit or Farallon PN9000-SX PCI Gigabit Ethernet
+	  adapter. The driver allows for using the Jumbo Frame option (9000
+	  bytes/frame) however it requires that your switches can handle this
+	  as well. To enable Jumbo Frames, add `mtu 9000' to your ifconfig
+	  line.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called acenic.
+
+config ACENIC_OMIT_TIGON_I
+	bool "Omit support for old Tigon I based AceNICs"
+	depends on ACENIC
+	---help---
+	  Say Y here if you only have Tigon II based AceNICs and want to leave
+	  out support for the older Tigon I based cards which are no longer
+	  being sold (ie. the original Alteon AceNIC and 3Com 3C985 (non B
+	  version)).  This will reduce the size of the driver object by
+	  app. 100KB.  If you are not sure whether your card is a Tigon I or a
+	  Tigon II, say N here.
+
+	  The safe and default value for this is N.
+
+endif # NET_VENDOR_ALTEON
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/alteon/Makefile linux-libre-3.2-gnu/drivers/net/ethernet/alteon/Makefile
--- linux-libre-3.1-gnu/drivers/net/ethernet/alteon/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/alteon/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,5 @@
+#
+# Makefile for the Alteon network device drivers.
+#
+
+obj-$(CONFIG_ACENIC) += acenic.o
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/7990.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/7990.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/7990.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/7990.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,662 @@
+/*
+ * 7990.c -- LANCE ethernet IC generic routines.
+ * This is an attempt to separate out the bits of various ethernet
+ * drivers that are common because they all use the AMD 7990 LANCE
+ * (Local Area Network Controller for Ethernet) chip.
+ *
+ * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
+ *
+ * Most of this stuff was obtained by looking at other LANCE drivers,
+ * in particular a2065.[ch]. The AMD C-LANCE datasheet was also helpful.
+ * NB: this was made easy by the fact that Jes Sorensen had cleaned up
+ * most of a2025 and sunlance with the aim of merging them, so the
+ * common code was pretty obvious.
+ */
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/route.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <asm/irq.h>
+/* Used for the temporal inet entries and routing */
+#include <linux/socket.h>
+#include <linux/bitops.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/pgtable.h>
+#ifdef CONFIG_HP300
+#include <asm/blinken.h>
+#endif
+
+#include "7990.h"
+
+#define WRITERAP(lp,x) out_be16(lp->base + LANCE_RAP, (x))
+#define WRITERDP(lp,x) out_be16(lp->base + LANCE_RDP, (x))
+#define READRDP(lp) in_be16(lp->base + LANCE_RDP)
+
+#if defined(CONFIG_HPLANCE) || defined(CONFIG_HPLANCE_MODULE)
+#include "hplance.h"
+
+#undef WRITERAP
+#undef WRITERDP
+#undef READRDP
+
+#if defined(CONFIG_MVME147_NET) || defined(CONFIG_MVME147_NET_MODULE)
+
+/* Lossage Factor Nine, Mr Sulu. */
+#define WRITERAP(lp,x) (lp->writerap(lp,x))
+#define WRITERDP(lp,x) (lp->writerdp(lp,x))
+#define READRDP(lp) (lp->readrdp(lp))
+
+#else
+
+/* These inlines can be used if only CONFIG_HPLANCE is defined */
+static inline void WRITERAP(struct lance_private *lp, __u16 value)
+{
+	do {
+		out_be16(lp->base + HPLANCE_REGOFF + LANCE_RAP, value);
+	} while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
+}
+
+static inline void WRITERDP(struct lance_private *lp, __u16 value)
+{
+	do {
+		out_be16(lp->base + HPLANCE_REGOFF + LANCE_RDP, value);
+	} while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
+}
+
+static inline __u16 READRDP(struct lance_private *lp)
+{
+	__u16 value;
+	do {
+		value = in_be16(lp->base + HPLANCE_REGOFF + LANCE_RDP);
+	} while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
+	return value;
+}
+
+#endif
+#endif /* CONFIG_HPLANCE || CONFIG_HPLANCE_MODULE */
+
+/* debugging output macros, various flavours */
+/* #define TEST_HITS */
+#ifdef UNDEF
+#define PRINT_RINGS() \
+do { \
+        int t; \
+        for (t=0; t < RX_RING_SIZE; t++) { \
+                printk("R%d: @(%02X %04X) len %04X, mblen %04X, bits %02X\n",\
+                       t, ib->brx_ring[t].rmd1_hadr, ib->brx_ring[t].rmd0,\
+                       ib->brx_ring[t].length,\
+                       ib->brx_ring[t].mblength, ib->brx_ring[t].rmd1_bits);\
+        }\
+        for (t=0; t < TX_RING_SIZE; t++) { \
+                printk("T%d: @(%02X %04X) len %04X, misc %04X, bits %02X\n",\
+                       t, ib->btx_ring[t].tmd1_hadr, ib->btx_ring[t].tmd0,\
+                       ib->btx_ring[t].length,\
+                       ib->btx_ring[t].misc, ib->btx_ring[t].tmd1_bits);\
+        }\
+} while (0)
+#else
+#define PRINT_RINGS()
+#endif
+
+/* Load the CSR registers. The LANCE has to be STOPped when we do this! */
+static void load_csrs (struct lance_private *lp)
+{
+        volatile struct lance_init_block *aib = lp->lance_init_block;
+        int leptr;
+
+        leptr = LANCE_ADDR (aib);
+
+        WRITERAP(lp, LE_CSR1);                    /* load address of init block */
+        WRITERDP(lp, leptr & 0xFFFF);
+        WRITERAP(lp, LE_CSR2);
+        WRITERDP(lp, leptr >> 16);
+        WRITERAP(lp, LE_CSR3);
+        WRITERDP(lp, lp->busmaster_regval);       /* set byteswap/ALEctrl/byte ctrl */
+
+        /* Point back to csr0 */
+        WRITERAP(lp, LE_CSR0);
+}
+
+/* #define to 0 or 1 appropriately */
+#define DEBUG_IRING 0
+/* Set up the Lance Rx and Tx rings and the init block */
+static void lance_init_ring (struct net_device *dev)
+{
+        struct lance_private *lp = netdev_priv(dev);
+        volatile struct lance_init_block *ib = lp->init_block;
+        volatile struct lance_init_block *aib; /* for LANCE_ADDR computations */
+        int leptr;
+        int i;
+
+        aib = lp->lance_init_block;
+
+        lp->rx_new = lp->tx_new = 0;
+        lp->rx_old = lp->tx_old = 0;
+
+        ib->mode = LE_MO_PROM;                             /* normal, enable Tx & Rx */
+
+        /* Copy the ethernet address to the lance init block
+         * Notice that we do a byteswap if we're big endian.
+         * [I think this is the right criterion; at least, sunlance,
+         * a2065 and atarilance do the byteswap and lance.c (PC) doesn't.
+         * However, the datasheet says that the BSWAP bit doesn't affect
+         * the init block, so surely it should be low byte first for
+         * everybody? Um.]
+         * We could define the ib->physaddr as three 16bit values and
+         * use (addr[1] << 8) | addr[0] & co, but this is more efficient.
+         */
+#ifdef __BIG_ENDIAN
+        ib->phys_addr [0] = dev->dev_addr [1];
+        ib->phys_addr [1] = dev->dev_addr [0];
+        ib->phys_addr [2] = dev->dev_addr [3];
+        ib->phys_addr [3] = dev->dev_addr [2];
+        ib->phys_addr [4] = dev->dev_addr [5];
+        ib->phys_addr [5] = dev->dev_addr [4];
+#else
+        for (i=0; i<6; i++)
+           ib->phys_addr[i] = dev->dev_addr[i];
+#endif
+
+        if (DEBUG_IRING)
+                printk ("TX rings:\n");
+
+	lp->tx_full = 0;
+        /* Setup the Tx ring entries */
+        for (i = 0; i < (1<<lp->lance_log_tx_bufs); i++) {
+                leptr = LANCE_ADDR(&aib->tx_buf[i][0]);
+                ib->btx_ring [i].tmd0      = leptr;
+                ib->btx_ring [i].tmd1_hadr = leptr >> 16;
+                ib->btx_ring [i].tmd1_bits = 0;
+                ib->btx_ring [i].length    = 0xf000; /* The ones required by tmd2 */
+                ib->btx_ring [i].misc      = 0;
+                if (DEBUG_IRING)
+                   printk ("%d: 0x%8.8x\n", i, leptr);
+        }
+
+        /* Setup the Rx ring entries */
+        if (DEBUG_IRING)
+                printk ("RX rings:\n");
+        for (i = 0; i < (1<<lp->lance_log_rx_bufs); i++) {
+                leptr = LANCE_ADDR(&aib->rx_buf[i][0]);
+
+                ib->brx_ring [i].rmd0      = leptr;
+                ib->brx_ring [i].rmd1_hadr = leptr >> 16;
+                ib->brx_ring [i].rmd1_bits = LE_R1_OWN;
+                /* 0xf000 == bits that must be one (reserved, presumably) */
+                ib->brx_ring [i].length    = -RX_BUFF_SIZE | 0xf000;
+                ib->brx_ring [i].mblength  = 0;
+                if (DEBUG_IRING)
+                        printk ("%d: 0x%8.8x\n", i, leptr);
+        }
+
+        /* Setup the initialization block */
+
+        /* Setup rx descriptor pointer */
+        leptr = LANCE_ADDR(&aib->brx_ring);
+        ib->rx_len = (lp->lance_log_rx_bufs << 13) | (leptr >> 16);
+        ib->rx_ptr = leptr;
+        if (DEBUG_IRING)
+                printk ("RX ptr: %8.8x\n", leptr);
+
+        /* Setup tx descriptor pointer */
+        leptr = LANCE_ADDR(&aib->btx_ring);
+        ib->tx_len = (lp->lance_log_tx_bufs << 13) | (leptr >> 16);
+        ib->tx_ptr = leptr;
+        if (DEBUG_IRING)
+                printk ("TX ptr: %8.8x\n", leptr);
+
+        /* Clear the multicast filter */
+        ib->filter [0] = 0;
+        ib->filter [1] = 0;
+        PRINT_RINGS();
+}
+
+/* LANCE must be STOPped before we do this, too... */
+static int init_restart_lance (struct lance_private *lp)
+{
+        int i;
+
+        WRITERAP(lp, LE_CSR0);
+        WRITERDP(lp, LE_C0_INIT);
+
+        /* Need a hook here for sunlance ledma stuff */
+
+        /* Wait for the lance to complete initialization */
+        for (i = 0; (i < 100) && !(READRDP(lp) & (LE_C0_ERR | LE_C0_IDON)); i++)
+                barrier();
+        if ((i == 100) || (READRDP(lp) & LE_C0_ERR)) {
+                printk ("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, READRDP(lp));
+                return -1;
+        }
+
+        /* Clear IDON by writing a "1", enable interrupts and start lance */
+        WRITERDP(lp, LE_C0_IDON);
+        WRITERDP(lp, LE_C0_INEA | LE_C0_STRT);
+
+        return 0;
+}
+
+static int lance_reset (struct net_device *dev)
+{
+        struct lance_private *lp = netdev_priv(dev);
+        int status;
+
+        /* Stop the lance */
+        WRITERAP(lp, LE_CSR0);
+        WRITERDP(lp, LE_C0_STOP);
+
+        load_csrs (lp);
+        lance_init_ring (dev);
+        dev->trans_start = jiffies; /* prevent tx timeout */
+        status = init_restart_lance (lp);
+#ifdef DEBUG_DRIVER
+        printk ("Lance restart=%d\n", status);
+#endif
+        return status;
+}
+
+static int lance_rx (struct net_device *dev)
+{
+        struct lance_private *lp = netdev_priv(dev);
+        volatile struct lance_init_block *ib = lp->init_block;
+        volatile struct lance_rx_desc *rd;
+        unsigned char bits;
+#ifdef TEST_HITS
+        int i;
+#endif
+
+#ifdef TEST_HITS
+        printk ("[");
+        for (i = 0; i < RX_RING_SIZE; i++) {
+                if (i == lp->rx_new)
+                        printk ("%s",
+                                ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "_" : "X");
+                else
+                        printk ("%s",
+                                ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "." : "1");
+        }
+        printk ("]");
+#endif
+#ifdef CONFIG_HP300
+	blinken_leds(0x40, 0);
+#endif
+        WRITERDP(lp, LE_C0_RINT | LE_C0_INEA);     /* ack Rx int, reenable ints */
+        for (rd = &ib->brx_ring [lp->rx_new];     /* For each Rx ring we own... */
+             !((bits = rd->rmd1_bits) & LE_R1_OWN);
+             rd = &ib->brx_ring [lp->rx_new]) {
+
+                /* We got an incomplete frame? */
+                if ((bits & LE_R1_POK) != LE_R1_POK) {
+                        dev->stats.rx_over_errors++;
+                        dev->stats.rx_errors++;
+                        continue;
+                } else if (bits & LE_R1_ERR) {
+                        /* Count only the end frame as a rx error,
+                         * not the beginning
+                         */
+                        if (bits & LE_R1_BUF) dev->stats.rx_fifo_errors++;
+                        if (bits & LE_R1_CRC) dev->stats.rx_crc_errors++;
+                        if (bits & LE_R1_OFL) dev->stats.rx_over_errors++;
+                        if (bits & LE_R1_FRA) dev->stats.rx_frame_errors++;
+                        if (bits & LE_R1_EOP) dev->stats.rx_errors++;
+                } else {
+			int len = (rd->mblength & 0xfff) - 4;
+			struct sk_buff *skb = dev_alloc_skb (len+2);
+
+                        if (!skb) {
+                                printk ("%s: Memory squeeze, deferring packet.\n",
+                                        dev->name);
+                                dev->stats.rx_dropped++;
+                                rd->mblength = 0;
+                                rd->rmd1_bits = LE_R1_OWN;
+                                lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask;
+                                return 0;
+                        }
+
+                        skb_reserve (skb, 2);           /* 16 byte align */
+                        skb_put (skb, len);             /* make room */
+                        skb_copy_to_linear_data(skb,
+                                         (unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
+                                         len);
+                        skb->protocol = eth_type_trans (skb, dev);
+			netif_rx (skb);
+			dev->stats.rx_packets++;
+			dev->stats.rx_bytes += len;
+                }
+
+                /* Return the packet to the pool */
+                rd->mblength = 0;
+                rd->rmd1_bits = LE_R1_OWN;
+                lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask;
+        }
+        return 0;
+}
+
+static int lance_tx (struct net_device *dev)
+{
+        struct lance_private *lp = netdev_priv(dev);
+        volatile struct lance_init_block *ib = lp->init_block;
+        volatile struct lance_tx_desc *td;
+        int i, j;
+        int status;
+
+#ifdef CONFIG_HP300
+	blinken_leds(0x80, 0);
+#endif
+        /* csr0 is 2f3 */
+        WRITERDP(lp, LE_C0_TINT | LE_C0_INEA);
+        /* csr0 is 73 */
+
+        j = lp->tx_old;
+        for (i = j; i != lp->tx_new; i = j) {
+                td = &ib->btx_ring [i];
+
+                /* If we hit a packet not owned by us, stop */
+                if (td->tmd1_bits & LE_T1_OWN)
+                        break;
+
+                if (td->tmd1_bits & LE_T1_ERR) {
+                        status = td->misc;
+
+                        dev->stats.tx_errors++;
+                        if (status & LE_T3_RTY)  dev->stats.tx_aborted_errors++;
+                        if (status & LE_T3_LCOL) dev->stats.tx_window_errors++;
+
+                        if (status & LE_T3_CLOS) {
+                                dev->stats.tx_carrier_errors++;
+                                if (lp->auto_select) {
+                                        lp->tpe = 1 - lp->tpe;
+                                        printk("%s: Carrier Lost, trying %s\n",
+                                               dev->name, lp->tpe?"TPE":"AUI");
+                                        /* Stop the lance */
+                                        WRITERAP(lp, LE_CSR0);
+                                        WRITERDP(lp, LE_C0_STOP);
+                                        lance_init_ring (dev);
+                                        load_csrs (lp);
+                                        init_restart_lance (lp);
+                                        return 0;
+                                }
+                        }
+
+                        /* buffer errors and underflows turn off the transmitter */
+                        /* Restart the adapter */
+                        if (status & (LE_T3_BUF|LE_T3_UFL)) {
+                                dev->stats.tx_fifo_errors++;
+
+                                printk ("%s: Tx: ERR_BUF|ERR_UFL, restarting\n",
+                                        dev->name);
+                                /* Stop the lance */
+                                WRITERAP(lp, LE_CSR0);
+                                WRITERDP(lp, LE_C0_STOP);
+                                lance_init_ring (dev);
+                                load_csrs (lp);
+                                init_restart_lance (lp);
+                                return 0;
+                        }
+                } else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) {
+                        /*
+                         * So we don't count the packet more than once.
+                         */
+                        td->tmd1_bits &= ~(LE_T1_POK);
+
+                        /* One collision before packet was sent. */
+                        if (td->tmd1_bits & LE_T1_EONE)
+                                dev->stats.collisions++;
+
+                        /* More than one collision, be optimistic. */
+                        if (td->tmd1_bits & LE_T1_EMORE)
+                                dev->stats.collisions += 2;
+
+                        dev->stats.tx_packets++;
+                }
+
+                j = (j + 1) & lp->tx_ring_mod_mask;
+        }
+        lp->tx_old = j;
+        WRITERDP(lp, LE_C0_TINT | LE_C0_INEA);
+        return 0;
+}
+
+static irqreturn_t
+lance_interrupt (int irq, void *dev_id)
+{
+        struct net_device *dev = (struct net_device *)dev_id;
+        struct lance_private *lp = netdev_priv(dev);
+        int csr0;
+
+	spin_lock (&lp->devlock);
+
+        WRITERAP(lp, LE_CSR0);              /* LANCE Controller Status */
+        csr0 = READRDP(lp);
+
+        PRINT_RINGS();
+
+        if (!(csr0 & LE_C0_INTR)) {     /* Check if any interrupt has */
+		spin_unlock (&lp->devlock);
+                return IRQ_NONE;        /* been generated by the Lance. */
+	}
+
+        /* Acknowledge all the interrupt sources ASAP */
+        WRITERDP(lp, csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|LE_C0_INIT));
+
+        if ((csr0 & LE_C0_ERR)) {
+                /* Clear the error condition */
+                WRITERDP(lp, LE_C0_BABL|LE_C0_ERR|LE_C0_MISS|LE_C0_INEA);
+        }
+
+        if (csr0 & LE_C0_RINT)
+                lance_rx (dev);
+
+        if (csr0 & LE_C0_TINT)
+                lance_tx (dev);
+
+        /* Log misc errors. */
+        if (csr0 & LE_C0_BABL)
+                dev->stats.tx_errors++;       /* Tx babble. */
+        if (csr0 & LE_C0_MISS)
+                dev->stats.rx_errors++;       /* Missed a Rx frame. */
+        if (csr0 & LE_C0_MERR) {
+                printk("%s: Bus master arbitration failure, status %4.4x.\n",
+                       dev->name, csr0);
+                /* Restart the chip. */
+                WRITERDP(lp, LE_C0_STRT);
+        }
+
+        if (lp->tx_full && netif_queue_stopped(dev) && (TX_BUFFS_AVAIL >= 0)) {
+		lp->tx_full = 0;
+		netif_wake_queue (dev);
+        }
+
+        WRITERAP(lp, LE_CSR0);
+        WRITERDP(lp, LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|LE_C0_IDON|LE_C0_INEA);
+
+	spin_unlock (&lp->devlock);
+	return IRQ_HANDLED;
+}
+
+int lance_open (struct net_device *dev)
+{
+        struct lance_private *lp = netdev_priv(dev);
+	int res;
+
+        /* Install the Interrupt handler. Or we could shunt this out to specific drivers? */
+        if (request_irq(lp->irq, lance_interrupt, IRQF_SHARED, lp->name, dev))
+                return -EAGAIN;
+
+        res = lance_reset(dev);
+	spin_lock_init(&lp->devlock);
+	netif_start_queue (dev);
+
+	return res;
+}
+EXPORT_SYMBOL_GPL(lance_open);
+
+int lance_close (struct net_device *dev)
+{
+        struct lance_private *lp = netdev_priv(dev);
+
+	netif_stop_queue (dev);
+
+        /* Stop the LANCE */
+        WRITERAP(lp, LE_CSR0);
+        WRITERDP(lp, LE_C0_STOP);
+
+        free_irq(lp->irq, dev);
+
+        return 0;
+}
+EXPORT_SYMBOL_GPL(lance_close);
+
+void lance_tx_timeout(struct net_device *dev)
+{
+	printk("lance_tx_timeout\n");
+	lance_reset(dev);
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	netif_wake_queue (dev);
+}
+EXPORT_SYMBOL_GPL(lance_tx_timeout);
+
+int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
+{
+        struct lance_private *lp = netdev_priv(dev);
+        volatile struct lance_init_block *ib = lp->init_block;
+        int entry, skblen, len;
+        static int outs;
+	unsigned long flags;
+
+        if (!TX_BUFFS_AVAIL)
+                return NETDEV_TX_LOCKED;
+
+	netif_stop_queue (dev);
+
+        skblen = skb->len;
+
+#ifdef DEBUG_DRIVER
+        /* dump the packet */
+        {
+                int i;
+
+                for (i = 0; i < 64; i++) {
+                        if ((i % 16) == 0)
+                                printk ("\n");
+                        printk ("%2.2x ", skb->data [i]);
+                }
+        }
+#endif
+        len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
+        entry = lp->tx_new & lp->tx_ring_mod_mask;
+        ib->btx_ring [entry].length = (-len) | 0xf000;
+        ib->btx_ring [entry].misc = 0;
+
+	if (skb->len < ETH_ZLEN)
+		memset((void *)&ib->tx_buf[entry][0], 0, ETH_ZLEN);
+        skb_copy_from_linear_data(skb, (void *)&ib->tx_buf[entry][0], skblen);
+
+        /* Now, give the packet to the lance */
+        ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
+        lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask;
+
+        outs++;
+        /* Kick the lance: transmit now */
+        WRITERDP(lp, LE_C0_INEA | LE_C0_TDMD);
+        dev_kfree_skb (skb);
+
+	spin_lock_irqsave (&lp->devlock, flags);
+        if (TX_BUFFS_AVAIL)
+		netif_start_queue (dev);
+	else
+		lp->tx_full = 1;
+	spin_unlock_irqrestore (&lp->devlock, flags);
+
+        return NETDEV_TX_OK;
+}
+EXPORT_SYMBOL_GPL(lance_start_xmit);
+
+/* taken from the depca driver via a2065.c */
+static void lance_load_multicast (struct net_device *dev)
+{
+        struct lance_private *lp = netdev_priv(dev);
+        volatile struct lance_init_block *ib = lp->init_block;
+        volatile u16 *mcast_table = (u16 *)&ib->filter;
+	struct netdev_hw_addr *ha;
+        u32 crc;
+
+        /* set all multicast bits */
+        if (dev->flags & IFF_ALLMULTI){
+                ib->filter [0] = 0xffffffff;
+                ib->filter [1] = 0xffffffff;
+                return;
+        }
+        /* clear the multicast filter */
+        ib->filter [0] = 0;
+        ib->filter [1] = 0;
+
+        /* Add addresses */
+	netdev_for_each_mc_addr(ha, dev) {
+		crc = ether_crc_le(6, ha->addr);
+                crc = crc >> 26;
+                mcast_table [crc >> 4] |= 1 << (crc & 0xf);
+        }
+}
+
+
+void lance_set_multicast (struct net_device *dev)
+{
+        struct lance_private *lp = netdev_priv(dev);
+        volatile struct lance_init_block *ib = lp->init_block;
+	int stopped;
+
+	stopped = netif_queue_stopped(dev);
+	if (!stopped)
+		netif_stop_queue (dev);
+
+        while (lp->tx_old != lp->tx_new)
+                schedule();
+
+        WRITERAP(lp, LE_CSR0);
+        WRITERDP(lp, LE_C0_STOP);
+        lance_init_ring (dev);
+
+        if (dev->flags & IFF_PROMISC) {
+                ib->mode |= LE_MO_PROM;
+        } else {
+                ib->mode &= ~LE_MO_PROM;
+                lance_load_multicast (dev);
+        }
+        load_csrs (lp);
+        init_restart_lance (lp);
+
+	if (!stopped)
+		netif_start_queue (dev);
+}
+EXPORT_SYMBOL_GPL(lance_set_multicast);
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+void lance_poll(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+
+	spin_lock (&lp->devlock);
+	WRITERAP(lp, LE_CSR0);
+	WRITERDP(lp, LE_C0_STRT);
+	spin_unlock (&lp->devlock);
+	lance_interrupt(dev->irq, dev);
+}
+#endif
+
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/7990.h linux-libre-3.2-gnu/drivers/net/ethernet/amd/7990.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/7990.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/7990.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,254 @@
+/*
+ * 7990.h -- LANCE ethernet IC generic routines.
+ * This is an attempt to separate out the bits of various ethernet
+ * drivers that are common because they all use the AMD 7990 LANCE
+ * (Local Area Network Controller for Ethernet) chip.
+ *
+ * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
+ *
+ * Most of this stuff was obtained by looking at other LANCE drivers,
+ * in particular a2065.[ch]. The AMD C-LANCE datasheet was also helpful.
+ */
+
+#ifndef _7990_H
+#define _7990_H
+
+/* The lance only has two register locations. We communicate mostly via memory. */
+#define LANCE_RDP	0	/* Register Data Port */
+#define LANCE_RAP	2	/* Register Address Port */
+
+/* Transmit/receive ring definitions.
+ * We allow the specific drivers to override these defaults if they want to.
+ * NB: according to lance.c, increasing the number of buffers is a waste
+ * of space and reduces the chance that an upper layer will be able to
+ * reorder queued Tx packets based on priority. [Clearly there is a minimum
+ * limit too: too small and we drop rx packets and can't tx at full speed.]
+ * 4+4 seems to be the usual setting; the atarilance driver uses 3 and 5.
+ */
+
+/* Blast! This won't work. The problem is that we can't specify a default
+ * setting because that would cause the lance_init_block struct to be
+ * too long (and overflow the RAM on shared-memory cards like the HP LANCE.
+ */
+#ifndef LANCE_LOG_TX_BUFFERS
+#define LANCE_LOG_TX_BUFFERS 1
+#define LANCE_LOG_RX_BUFFERS 3
+#endif
+
+#define TX_RING_SIZE (1<<LANCE_LOG_TX_BUFFERS)
+#define RX_RING_SIZE (1<<LANCE_LOG_RX_BUFFERS)
+#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
+#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
+#define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29)
+#define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)
+#define PKT_BUFF_SIZE (1544)
+#define RX_BUFF_SIZE PKT_BUFF_SIZE
+#define TX_BUFF_SIZE PKT_BUFF_SIZE
+
+/* Each receive buffer is described by a receive message descriptor (RMD) */
+struct lance_rx_desc {
+	volatile unsigned short rmd0;        /* low address of packet */
+	volatile unsigned char  rmd1_bits;   /* descriptor bits */
+	volatile unsigned char  rmd1_hadr;   /* high address of packet */
+	volatile short    length;    	    /* This length is 2s complement (negative)!
+				     * Buffer length
+				     */
+	volatile unsigned short mblength;    /* Actual number of bytes received */
+};
+
+/* Ditto for TMD: */
+struct lance_tx_desc {
+	volatile unsigned short tmd0;        /* low address of packet */
+	volatile unsigned char  tmd1_bits;   /* descriptor bits */
+	volatile unsigned char  tmd1_hadr;   /* high address of packet */
+	volatile short    length;       	    /* Length is 2s complement (negative)! */
+	volatile unsigned short misc;
+};
+
+/* There are three memory structures accessed by the LANCE:
+ * the initialization block, the receive and transmit descriptor rings,
+ * and the data buffers themselves. In fact we might as well put the
+ * init block,the Tx and Rx rings and the buffers together in memory:
+ */
+struct lance_init_block {
+        volatile unsigned short mode;            /* Pre-set mode (reg. 15) */
+        volatile unsigned char phys_addr[6];     /* Physical ethernet address */
+        volatile unsigned filter[2];             /* Multicast filter (64 bits) */
+
+        /* Receive and transmit ring base, along with extra bits. */
+        volatile unsigned short rx_ptr;          /* receive descriptor addr */
+        volatile unsigned short rx_len;          /* receive len and high addr */
+        volatile unsigned short tx_ptr;          /* transmit descriptor addr */
+        volatile unsigned short tx_len;          /* transmit len and high addr */
+
+        /* The Tx and Rx ring entries must be aligned on 8-byte boundaries.
+         * This will be true if this whole struct is 8-byte aligned.
+         */
+        volatile struct lance_tx_desc btx_ring[TX_RING_SIZE];
+        volatile struct lance_rx_desc brx_ring[RX_RING_SIZE];
+
+        volatile char   tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
+        volatile char   rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
+        /* we use this just to make the struct big enough that we can move its startaddr
+         * in order to force alignment to an eight byte boundary.
+         */
+};
+
+/* This is where we keep all the stuff the driver needs to know about.
+ * I'm definitely unhappy about the mechanism for allowing specific
+ * drivers to add things...
+ */
+struct lance_private
+{
+        char *name;
+	unsigned long base;
+        volatile struct lance_init_block *init_block; /* CPU address of RAM */
+        volatile struct lance_init_block *lance_init_block; /* LANCE address of RAM */
+
+        int rx_new, tx_new;
+        int rx_old, tx_old;
+
+        int lance_log_rx_bufs, lance_log_tx_bufs;
+        int rx_ring_mod_mask, tx_ring_mod_mask;
+
+        int tpe;                                  /* TPE is selected */
+        int auto_select;                          /* cable-selection is by carrier */
+        unsigned short busmaster_regval;
+
+        unsigned int irq;                         /* IRQ to register */
+
+        /* This is because the HP LANCE is disgusting and you have to check
+         * a DIO-specific register every time you read/write the LANCE regs :-<
+         * [could we get away with making these some sort of macro?]
+         */
+        void (*writerap)(void *, unsigned short);
+        void (*writerdp)(void *, unsigned short);
+        unsigned short (*readrdp)(void *);
+	spinlock_t devlock;
+	char tx_full;
+};
+
+/*
+ *              Am7990 Control and Status Registers
+ */
+#define LE_CSR0         0x0000          /* LANCE Controller Status */
+#define LE_CSR1         0x0001          /* IADR[15:0] (bit0==0 ie word aligned) */
+#define LE_CSR2         0x0002          /* IADR[23:16] (high bits reserved) */
+#define LE_CSR3         0x0003          /* Misc */
+
+/*
+ *		Bit definitions for CSR0 (LANCE Controller Status)
+ */
+#define LE_C0_ERR	0x8000		/* Error = BABL | CERR | MISS | MERR */
+#define LE_C0_BABL	0x4000		/* Babble: Transmitted too many bits */
+#define LE_C0_CERR	0x2000		/* No Heartbeat (10BASE-T) */
+#define LE_C0_MISS	0x1000		/* Missed Frame (no rx buffer to put it in) */
+#define LE_C0_MERR	0x0800		/* Memory Error */
+#define LE_C0_RINT	0x0400		/* Receive Interrupt */
+#define LE_C0_TINT	0x0200		/* Transmit Interrupt */
+#define LE_C0_IDON	0x0100		/* Initialization Done */
+#define LE_C0_INTR	0x0080		/* Interrupt Flag
+                                         = BABL | MISS | MERR | RINT | TINT | IDON */
+#define LE_C0_INEA	0x0040		/* Interrupt Enable */
+#define LE_C0_RXON	0x0020		/* Receive On */
+#define LE_C0_TXON	0x0010		/* Transmit On */
+#define LE_C0_TDMD	0x0008		/* Transmit Demand */
+#define LE_C0_STOP	0x0004		/* Stop */
+#define LE_C0_STRT	0x0002		/* Start */
+#define LE_C0_INIT	0x0001		/* Initialize */
+
+
+/*
+ *		Bit definitions for CSR3
+ */
+#define LE_C3_BSWP	0x0004		/* Byte Swap
+					   (on for big endian byte order) */
+#define LE_C3_ACON	0x0002		/* ALE Control
+					   (on for active low ALE) */
+#define LE_C3_BCON	0x0001		/* Byte Control */
+
+
+/*
+ *		Mode Flags
+ */
+#define LE_MO_PROM	0x8000		/* Promiscuous Mode */
+/* these next ones 0x4000 -- 0x0080 are not available on the LANCE 7990,
+ * but they are in NetBSD's am7990.h, presumably for backwards-compatible chips
+ */
+#define LE_MO_DRCVBC  0x4000          /* disable receive broadcast */
+#define LE_MO_DRCVPA  0x2000          /* disable physical address detection */
+#define LE_MO_DLNKTST 0x1000          /* disable link status */
+#define LE_MO_DAPC    0x0800          /* disable automatic polarity correction */
+#define LE_MO_MENDECL 0x0400          /* MENDEC loopback mode */
+#define LE_MO_LRTTSEL 0x0200          /* lower RX threshold / TX mode selection */
+#define LE_MO_PSEL1   0x0100          /* port selection bit1 */
+#define LE_MO_PSEL0   0x0080          /* port selection bit0 */
+/* and this one is from the C-LANCE data sheet... */
+#define LE_MO_EMBA      0x0080          /* Enable Modified Backoff Algorithm
+                                           (C-LANCE, not original LANCE) */
+#define LE_MO_INTL	0x0040		/* Internal Loopback */
+#define LE_MO_DRTY	0x0020		/* Disable Retry */
+#define LE_MO_FCOLL	0x0010		/* Force Collision */
+#define LE_MO_DXMTFCS	0x0008		/* Disable Transmit CRC */
+#define LE_MO_LOOP	0x0004		/* Loopback Enable */
+#define LE_MO_DTX	0x0002		/* Disable Transmitter */
+#define LE_MO_DRX	0x0001		/* Disable Receiver */
+
+
+/*
+ *		Receive Flags
+ */
+#define LE_R1_OWN	0x80		/* LANCE owns the descriptor */
+#define LE_R1_ERR	0x40		/* Error */
+#define LE_R1_FRA	0x20		/* Framing Error */
+#define LE_R1_OFL	0x10		/* Overflow Error */
+#define LE_R1_CRC	0x08		/* CRC Error */
+#define LE_R1_BUF	0x04		/* Buffer Error */
+#define LE_R1_SOP	0x02		/* Start of Packet */
+#define LE_R1_EOP	0x01		/* End of Packet */
+#define LE_R1_POK       0x03		/* Packet is complete: SOP + EOP */
+
+
+/*
+ *		Transmit Flags
+ */
+#define LE_T1_OWN	0x80		/* LANCE owns the descriptor */
+#define LE_T1_ERR	0x40		/* Error */
+#define LE_T1_RES	0x20		/* Reserved, LANCE writes this with a zero */
+#define LE_T1_EMORE	0x10		/* More than one retry needed */
+#define LE_T1_EONE	0x08		/* One retry needed */
+#define LE_T1_EDEF	0x04		/* Deferred */
+#define LE_T1_SOP	0x02		/* Start of Packet */
+#define LE_T1_EOP	0x01		/* End of Packet */
+#define LE_T1_POK	0x03		/* Packet is complete: SOP + EOP */
+
+/*
+ *		Error Flags
+ */
+#define LE_T3_BUF 	0x8000		/* Buffer Error */
+#define LE_T3_UFL 	0x4000		/* Underflow Error */
+#define LE_T3_LCOL 	0x1000		/* Late Collision */
+#define LE_T3_CLOS 	0x0800		/* Loss of Carrier */
+#define LE_T3_RTY 	0x0400		/* Retry Error */
+#define LE_T3_TDR	0x03ff		/* Time Domain Reflectometry */
+
+/* Miscellaneous useful macros */
+
+#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
+                        lp->tx_old+lp->tx_ring_mod_mask-lp->tx_new:\
+                        lp->tx_old - lp->tx_new-1)
+
+/* The LANCE only uses 24 bit addresses. This does the obvious thing. */
+#define LANCE_ADDR(x) ((int)(x) & ~0xff000000)
+
+/* Now the prototypes we export */
+extern int lance_open(struct net_device *dev);
+extern int lance_close (struct net_device *dev);
+extern int lance_start_xmit (struct sk_buff *skb, struct net_device *dev);
+extern void lance_set_multicast (struct net_device *dev);
+extern void lance_tx_timeout(struct net_device *dev);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+extern void lance_poll(struct net_device *dev);
+#endif
+
+#endif /* ndef _7990_H */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/a2065.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/a2065.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/a2065.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/a2065.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,781 @@
+/*
+ * Amiga Linux/68k A2065 Ethernet Driver
+ *
+ * (C) Copyright 1995-2003 by Geert Uytterhoeven <geert@linux-m68k.org>
+ *
+ * Fixes and tips by:
+ *	- Janos Farkas (CHEXUM@sparta.banki.hu)
+ *	- Jes Degn Soerensen (jds@kom.auc.dk)
+ *	- Matt Domsch (Matt_Domsch@dell.com)
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is based on
+ *
+ *	ariadne.?:	Amiga Linux/68k Ariadne Ethernet Driver
+ *			(C) Copyright 1995 by Geert Uytterhoeven,
+ *                                            Peter De Schrijver
+ *
+ *	lance.c:	An AMD LANCE ethernet driver for linux.
+ *			Written 1993-94 by Donald Becker.
+ *
+ *	Am79C960:	PCnet(tm)-ISA Single-Chip Ethernet Controller
+ *			Advanced Micro Devices
+ *			Publication #16907, Rev. B, Amendment/0, May 1994
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of the Linux
+ * distribution for more details.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * The A2065 is a Zorro-II board made by Commodore/Ameristar. It contains:
+ *
+ *	- an Am7990 Local Area Network Controller for Ethernet (LANCE) with
+ *	  both 10BASE-2 (thin coax) and AUI (DB-15) connectors
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+/*#define DEBUG*/
+/*#define TEST_HITS*/
+
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/skbuff.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+#include <linux/zorro.h>
+#include <linux/bitops.h>
+
+#include <asm/irq.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+
+#include "a2065.h"
+
+/* Transmit/Receive Ring Definitions */
+
+#define LANCE_LOG_TX_BUFFERS	(2)
+#define LANCE_LOG_RX_BUFFERS	(4)
+
+#define TX_RING_SIZE		(1 << LANCE_LOG_TX_BUFFERS)
+#define RX_RING_SIZE		(1 << LANCE_LOG_RX_BUFFERS)
+
+#define TX_RING_MOD_MASK	(TX_RING_SIZE - 1)
+#define RX_RING_MOD_MASK	(RX_RING_SIZE - 1)
+
+#define PKT_BUF_SIZE		(1544)
+#define RX_BUFF_SIZE            PKT_BUF_SIZE
+#define TX_BUFF_SIZE            PKT_BUF_SIZE
+
+/* Layout of the Lance's RAM Buffer */
+
+struct lance_init_block {
+	unsigned short mode;		/* Pre-set mode (reg. 15) */
+	unsigned char phys_addr[6];     /* Physical ethernet address */
+	unsigned filter[2];		/* Multicast filter. */
+
+	/* Receive and transmit ring base, along with extra bits. */
+	unsigned short rx_ptr;		/* receive descriptor addr */
+	unsigned short rx_len;		/* receive len and high addr */
+	unsigned short tx_ptr;		/* transmit descriptor addr */
+	unsigned short tx_len;		/* transmit len and high addr */
+
+	/* The Tx and Rx ring entries must aligned on 8-byte boundaries. */
+	struct lance_rx_desc brx_ring[RX_RING_SIZE];
+	struct lance_tx_desc btx_ring[TX_RING_SIZE];
+
+	char rx_buf[RX_RING_SIZE][RX_BUFF_SIZE];
+	char tx_buf[TX_RING_SIZE][TX_BUFF_SIZE];
+};
+
+/* Private Device Data */
+
+struct lance_private {
+	char *name;
+	volatile struct lance_regs *ll;
+	volatile struct lance_init_block *init_block;	    /* Hosts view */
+	volatile struct lance_init_block *lance_init_block; /* Lance view */
+
+	int rx_new, tx_new;
+	int rx_old, tx_old;
+
+	int lance_log_rx_bufs, lance_log_tx_bufs;
+	int rx_ring_mod_mask, tx_ring_mod_mask;
+
+	int tpe;		      /* cable-selection is TPE */
+	int auto_select;	      /* cable-selection by carrier */
+	unsigned short busmaster_regval;
+
+#ifdef CONFIG_SUNLANCE
+	struct Linux_SBus_DMA *ledma; /* if set this points to ledma and arch=4m */
+	int burst_sizes;	      /* ledma SBus burst sizes */
+#endif
+	struct timer_list         multicast_timer;
+};
+
+#define LANCE_ADDR(x) ((int)(x) & ~0xff000000)
+
+/* Load the CSR registers */
+static void load_csrs(struct lance_private *lp)
+{
+	volatile struct lance_regs *ll = lp->ll;
+	volatile struct lance_init_block *aib = lp->lance_init_block;
+	int leptr = LANCE_ADDR(aib);
+
+	ll->rap = LE_CSR1;
+	ll->rdp = (leptr & 0xFFFF);
+	ll->rap = LE_CSR2;
+	ll->rdp = leptr >> 16;
+	ll->rap = LE_CSR3;
+	ll->rdp = lp->busmaster_regval;
+
+	/* Point back to csr0 */
+	ll->rap = LE_CSR0;
+}
+
+/* Setup the Lance Rx and Tx rings */
+static void lance_init_ring(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_init_block *ib = lp->init_block;
+	volatile struct lance_init_block *aib = lp->lance_init_block;
+					/* for LANCE_ADDR computations */
+	int leptr;
+	int i;
+
+	/* Lock out other processes while setting up hardware */
+	netif_stop_queue(dev);
+	lp->rx_new = lp->tx_new = 0;
+	lp->rx_old = lp->tx_old = 0;
+
+	ib->mode = 0;
+
+	/* Copy the ethernet address to the lance init block
+	 * Note that on the sparc you need to swap the ethernet address.
+	 */
+	ib->phys_addr[0] = dev->dev_addr[1];
+	ib->phys_addr[1] = dev->dev_addr[0];
+	ib->phys_addr[2] = dev->dev_addr[3];
+	ib->phys_addr[3] = dev->dev_addr[2];
+	ib->phys_addr[4] = dev->dev_addr[5];
+	ib->phys_addr[5] = dev->dev_addr[4];
+
+	/* Setup the Tx ring entries */
+	netdev_dbg(dev, "TX rings:\n");
+	for (i = 0; i <= 1 << lp->lance_log_tx_bufs; i++) {
+		leptr = LANCE_ADDR(&aib->tx_buf[i][0]);
+		ib->btx_ring[i].tmd0      = leptr;
+		ib->btx_ring[i].tmd1_hadr = leptr >> 16;
+		ib->btx_ring[i].tmd1_bits = 0;
+		ib->btx_ring[i].length    = 0xf000; /* The ones required by tmd2 */
+		ib->btx_ring[i].misc      = 0;
+		if (i < 3)
+			netdev_dbg(dev, "%d: 0x%08x\n", i, leptr);
+	}
+
+	/* Setup the Rx ring entries */
+	netdev_dbg(dev, "RX rings:\n");
+	for (i = 0; i < 1 << lp->lance_log_rx_bufs; i++) {
+		leptr = LANCE_ADDR(&aib->rx_buf[i][0]);
+
+		ib->brx_ring[i].rmd0      = leptr;
+		ib->brx_ring[i].rmd1_hadr = leptr >> 16;
+		ib->brx_ring[i].rmd1_bits = LE_R1_OWN;
+		ib->brx_ring[i].length    = -RX_BUFF_SIZE | 0xf000;
+		ib->brx_ring[i].mblength  = 0;
+		if (i < 3)
+			netdev_dbg(dev, "%d: 0x%08x\n", i, leptr);
+	}
+
+	/* Setup the initialization block */
+
+	/* Setup rx descriptor pointer */
+	leptr = LANCE_ADDR(&aib->brx_ring);
+	ib->rx_len = (lp->lance_log_rx_bufs << 13) | (leptr >> 16);
+	ib->rx_ptr = leptr;
+	netdev_dbg(dev, "RX ptr: %08x\n", leptr);
+
+	/* Setup tx descriptor pointer */
+	leptr = LANCE_ADDR(&aib->btx_ring);
+	ib->tx_len = (lp->lance_log_tx_bufs << 13) | (leptr >> 16);
+	ib->tx_ptr = leptr;
+	netdev_dbg(dev, "TX ptr: %08x\n", leptr);
+
+	/* Clear the multicast filter */
+	ib->filter[0] = 0;
+	ib->filter[1] = 0;
+}
+
+static int init_restart_lance(struct lance_private *lp)
+{
+	volatile struct lance_regs *ll = lp->ll;
+	int i;
+
+	ll->rap = LE_CSR0;
+	ll->rdp = LE_C0_INIT;
+
+	/* Wait for the lance to complete initialization */
+	for (i = 0; (i < 100) && !(ll->rdp & (LE_C0_ERR | LE_C0_IDON)); i++)
+		barrier();
+	if ((i == 100) || (ll->rdp & LE_C0_ERR)) {
+		pr_err("unopened after %d ticks, csr0=%04x\n", i, ll->rdp);
+		return -EIO;
+	}
+
+	/* Clear IDON by writing a "1", enable interrupts and start lance */
+	ll->rdp = LE_C0_IDON;
+	ll->rdp = LE_C0_INEA | LE_C0_STRT;
+
+	return 0;
+}
+
+static int lance_rx(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_init_block *ib = lp->init_block;
+	volatile struct lance_regs *ll = lp->ll;
+	volatile struct lance_rx_desc *rd;
+	unsigned char bits;
+
+#ifdef TEST_HITS
+	int i;
+	char buf[RX_RING_SIZE + 1];
+
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		char r1_own = ib->brx_ring[i].rmd1_bits & LE_R1_OWN;
+		if (i == lp->rx_new)
+			buf[i] = r1_own ? '_' : 'X';
+		else
+			buf[i] = r1_own ? '.' : '1';
+	}
+	buf[RX_RING_SIZE] = 0;
+
+	pr_debug("RxRing TestHits: [%s]\n", buf);
+#endif
+
+	ll->rdp = LE_C0_RINT | LE_C0_INEA;
+	for (rd = &ib->brx_ring[lp->rx_new];
+	     !((bits = rd->rmd1_bits) & LE_R1_OWN);
+	     rd = &ib->brx_ring[lp->rx_new]) {
+
+		/* We got an incomplete frame? */
+		if ((bits & LE_R1_POK) != LE_R1_POK) {
+			dev->stats.rx_over_errors++;
+			dev->stats.rx_errors++;
+			continue;
+		} else if (bits & LE_R1_ERR) {
+			/* Count only the end frame as a rx error,
+			 * not the beginning
+			 */
+			if (bits & LE_R1_BUF)
+				dev->stats.rx_fifo_errors++;
+			if (bits & LE_R1_CRC)
+				dev->stats.rx_crc_errors++;
+			if (bits & LE_R1_OFL)
+				dev->stats.rx_over_errors++;
+			if (bits & LE_R1_FRA)
+				dev->stats.rx_frame_errors++;
+			if (bits & LE_R1_EOP)
+				dev->stats.rx_errors++;
+		} else {
+			int len = (rd->mblength & 0xfff) - 4;
+			struct sk_buff *skb = dev_alloc_skb(len + 2);
+
+			if (!skb) {
+				netdev_warn(dev, "Memory squeeze, deferring packet\n");
+				dev->stats.rx_dropped++;
+				rd->mblength = 0;
+				rd->rmd1_bits = LE_R1_OWN;
+				lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask;
+				return 0;
+			}
+
+			skb_reserve(skb, 2);		/* 16 byte align */
+			skb_put(skb, len);		/* make room */
+			skb_copy_to_linear_data(skb,
+				 (unsigned char *)&ib->rx_buf[lp->rx_new][0],
+				 len);
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+			dev->stats.rx_packets++;
+			dev->stats.rx_bytes += len;
+		}
+
+		/* Return the packet to the pool */
+		rd->mblength = 0;
+		rd->rmd1_bits = LE_R1_OWN;
+		lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask;
+	}
+	return 0;
+}
+
+static int lance_tx(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_init_block *ib = lp->init_block;
+	volatile struct lance_regs *ll = lp->ll;
+	volatile struct lance_tx_desc *td;
+	int i, j;
+	int status;
+
+	/* csr0 is 2f3 */
+	ll->rdp = LE_C0_TINT | LE_C0_INEA;
+	/* csr0 is 73 */
+
+	j = lp->tx_old;
+	for (i = j; i != lp->tx_new; i = j) {
+		td = &ib->btx_ring[i];
+
+		/* If we hit a packet not owned by us, stop */
+		if (td->tmd1_bits & LE_T1_OWN)
+			break;
+
+		if (td->tmd1_bits & LE_T1_ERR) {
+			status = td->misc;
+
+			dev->stats.tx_errors++;
+			if (status & LE_T3_RTY)
+				dev->stats.tx_aborted_errors++;
+			if (status & LE_T3_LCOL)
+				dev->stats.tx_window_errors++;
+
+			if (status & LE_T3_CLOS) {
+				dev->stats.tx_carrier_errors++;
+				if (lp->auto_select) {
+					lp->tpe = 1 - lp->tpe;
+					netdev_err(dev, "Carrier Lost, trying %s\n",
+						   lp->tpe ? "TPE" : "AUI");
+					/* Stop the lance */
+					ll->rap = LE_CSR0;
+					ll->rdp = LE_C0_STOP;
+					lance_init_ring(dev);
+					load_csrs(lp);
+					init_restart_lance(lp);
+					return 0;
+				}
+			}
+
+			/* buffer errors and underflows turn off
+			 * the transmitter, so restart the adapter
+			 */
+			if (status & (LE_T3_BUF | LE_T3_UFL)) {
+				dev->stats.tx_fifo_errors++;
+
+				netdev_err(dev, "Tx: ERR_BUF|ERR_UFL, restarting\n");
+				/* Stop the lance */
+				ll->rap = LE_CSR0;
+				ll->rdp = LE_C0_STOP;
+				lance_init_ring(dev);
+				load_csrs(lp);
+				init_restart_lance(lp);
+				return 0;
+			}
+		} else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) {
+			/* So we don't count the packet more than once. */
+			td->tmd1_bits &= ~(LE_T1_POK);
+
+			/* One collision before packet was sent. */
+			if (td->tmd1_bits & LE_T1_EONE)
+				dev->stats.collisions++;
+
+			/* More than one collision, be optimistic. */
+			if (td->tmd1_bits & LE_T1_EMORE)
+				dev->stats.collisions += 2;
+
+			dev->stats.tx_packets++;
+		}
+
+		j = (j + 1) & lp->tx_ring_mod_mask;
+	}
+	lp->tx_old = j;
+	ll->rdp = LE_C0_TINT | LE_C0_INEA;
+	return 0;
+}
+
+static int lance_tx_buffs_avail(struct lance_private *lp)
+{
+	if (lp->tx_old <= lp->tx_new)
+		return lp->tx_old + lp->tx_ring_mod_mask - lp->tx_new;
+	return lp->tx_old - lp->tx_new - 1;
+}
+
+static irqreturn_t lance_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_regs *ll = lp->ll;
+	int csr0;
+
+	ll->rap = LE_CSR0;		/* LANCE Controller Status */
+	csr0 = ll->rdp;
+
+	if (!(csr0 & LE_C0_INTR))	/* Check if any interrupt has */
+		return IRQ_NONE;	/* been generated by the Lance. */
+
+	/* Acknowledge all the interrupt sources ASAP */
+	ll->rdp = csr0 & ~(LE_C0_INEA | LE_C0_TDMD | LE_C0_STOP | LE_C0_STRT |
+			   LE_C0_INIT);
+
+	if (csr0 & LE_C0_ERR) {
+		/* Clear the error condition */
+		ll->rdp = LE_C0_BABL | LE_C0_ERR | LE_C0_MISS | LE_C0_INEA;
+	}
+
+	if (csr0 & LE_C0_RINT)
+		lance_rx(dev);
+
+	if (csr0 & LE_C0_TINT)
+		lance_tx(dev);
+
+	/* Log misc errors. */
+	if (csr0 & LE_C0_BABL)
+		dev->stats.tx_errors++;       /* Tx babble. */
+	if (csr0 & LE_C0_MISS)
+		dev->stats.rx_errors++;       /* Missed a Rx frame. */
+	if (csr0 & LE_C0_MERR) {
+		netdev_err(dev, "Bus master arbitration failure, status %04x\n",
+			   csr0);
+		/* Restart the chip. */
+		ll->rdp = LE_C0_STRT;
+	}
+
+	if (netif_queue_stopped(dev) && lance_tx_buffs_avail(lp) > 0)
+		netif_wake_queue(dev);
+
+	ll->rap = LE_CSR0;
+	ll->rdp = (LE_C0_BABL | LE_C0_CERR | LE_C0_MISS | LE_C0_MERR |
+		   LE_C0_IDON | LE_C0_INEA);
+	return IRQ_HANDLED;
+}
+
+static int lance_open(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_regs *ll = lp->ll;
+	int ret;
+
+	/* Stop the Lance */
+	ll->rap = LE_CSR0;
+	ll->rdp = LE_C0_STOP;
+
+	/* Install the Interrupt handler */
+	ret = request_irq(IRQ_AMIGA_PORTS, lance_interrupt, IRQF_SHARED,
+			  dev->name, dev);
+	if (ret)
+		return ret;
+
+	load_csrs(lp);
+	lance_init_ring(dev);
+
+	netif_start_queue(dev);
+
+	return init_restart_lance(lp);
+}
+
+static int lance_close(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_regs *ll = lp->ll;
+
+	netif_stop_queue(dev);
+	del_timer_sync(&lp->multicast_timer);
+
+	/* Stop the card */
+	ll->rap = LE_CSR0;
+	ll->rdp = LE_C0_STOP;
+
+	free_irq(IRQ_AMIGA_PORTS, dev);
+	return 0;
+}
+
+static inline int lance_reset(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_regs *ll = lp->ll;
+	int status;
+
+	/* Stop the lance */
+	ll->rap = LE_CSR0;
+	ll->rdp = LE_C0_STOP;
+
+	load_csrs(lp);
+
+	lance_init_ring(dev);
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	netif_start_queue(dev);
+
+	status = init_restart_lance(lp);
+	netdev_dbg(dev, "Lance restart=%d\n", status);
+
+	return status;
+}
+
+static void lance_tx_timeout(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_regs *ll = lp->ll;
+
+	netdev_err(dev, "transmit timed out, status %04x, reset\n", ll->rdp);
+	lance_reset(dev);
+	netif_wake_queue(dev);
+}
+
+static netdev_tx_t lance_start_xmit(struct sk_buff *skb,
+				    struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_regs *ll = lp->ll;
+	volatile struct lance_init_block *ib = lp->init_block;
+	int entry, skblen;
+	int status = NETDEV_TX_OK;
+	unsigned long flags;
+
+	if (skb_padto(skb, ETH_ZLEN))
+		return NETDEV_TX_OK;
+	skblen = max_t(unsigned, skb->len, ETH_ZLEN);
+
+	local_irq_save(flags);
+
+	if (!lance_tx_buffs_avail(lp)) {
+		local_irq_restore(flags);
+		return NETDEV_TX_LOCKED;
+	}
+
+#ifdef DEBUG
+	/* dump the packet */
+	print_hex_dump(KERN_DEBUG, "skb->data: ", DUMP_PREFIX_NONE,
+		       16, 1, skb->data, 64, true);
+#endif
+	entry = lp->tx_new & lp->tx_ring_mod_mask;
+	ib->btx_ring[entry].length = (-skblen) | 0xf000;
+	ib->btx_ring[entry].misc = 0;
+
+	skb_copy_from_linear_data(skb, (void *)&ib->tx_buf[entry][0], skblen);
+
+	/* Now, give the packet to the lance */
+	ib->btx_ring[entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN);
+	lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask;
+	dev->stats.tx_bytes += skblen;
+
+	if (lance_tx_buffs_avail(lp) <= 0)
+		netif_stop_queue(dev);
+
+	/* Kick the lance: transmit now */
+	ll->rdp = LE_C0_INEA | LE_C0_TDMD;
+	dev_kfree_skb(skb);
+
+	local_irq_restore(flags);
+
+	return status;
+}
+
+/* taken from the depca driver */
+static void lance_load_multicast(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_init_block *ib = lp->init_block;
+	volatile u16 *mcast_table = (u16 *)&ib->filter;
+	struct netdev_hw_addr *ha;
+	u32 crc;
+
+	/* set all multicast bits */
+	if (dev->flags & IFF_ALLMULTI) {
+		ib->filter[0] = 0xffffffff;
+		ib->filter[1] = 0xffffffff;
+		return;
+	}
+	/* clear the multicast filter */
+	ib->filter[0] = 0;
+	ib->filter[1] = 0;
+
+	/* Add addresses */
+	netdev_for_each_mc_addr(ha, dev) {
+		crc = ether_crc_le(6, ha->addr);
+		crc = crc >> 26;
+		mcast_table[crc >> 4] |= 1 << (crc & 0xf);
+	}
+}
+
+static void lance_set_multicast(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_init_block *ib = lp->init_block;
+	volatile struct lance_regs *ll = lp->ll;
+
+	if (!netif_running(dev))
+		return;
+
+	if (lp->tx_old != lp->tx_new) {
+		mod_timer(&lp->multicast_timer, jiffies + 4);
+		netif_wake_queue(dev);
+		return;
+	}
+
+	netif_stop_queue(dev);
+
+	ll->rap = LE_CSR0;
+	ll->rdp = LE_C0_STOP;
+	lance_init_ring(dev);
+
+	if (dev->flags & IFF_PROMISC) {
+		ib->mode |= LE_MO_PROM;
+	} else {
+		ib->mode &= ~LE_MO_PROM;
+		lance_load_multicast(dev);
+	}
+	load_csrs(lp);
+	init_restart_lance(lp);
+	netif_wake_queue(dev);
+}
+
+static int __devinit a2065_init_one(struct zorro_dev *z,
+				    const struct zorro_device_id *ent);
+static void __devexit a2065_remove_one(struct zorro_dev *z);
+
+
+static struct zorro_device_id a2065_zorro_tbl[] __devinitdata = {
+	{ ZORRO_PROD_CBM_A2065_1 },
+	{ ZORRO_PROD_CBM_A2065_2 },
+	{ ZORRO_PROD_AMERISTAR_A2065 },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(zorro, a2065_zorro_tbl);
+
+static struct zorro_driver a2065_driver = {
+	.name		= "a2065",
+	.id_table	= a2065_zorro_tbl,
+	.probe		= a2065_init_one,
+	.remove		= __devexit_p(a2065_remove_one),
+};
+
+static const struct net_device_ops lance_netdev_ops = {
+	.ndo_open		= lance_open,
+	.ndo_stop		= lance_close,
+	.ndo_start_xmit		= lance_start_xmit,
+	.ndo_tx_timeout		= lance_tx_timeout,
+	.ndo_set_rx_mode	= lance_set_multicast,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
+static int __devinit a2065_init_one(struct zorro_dev *z,
+				    const struct zorro_device_id *ent)
+{
+	struct net_device *dev;
+	struct lance_private *priv;
+	unsigned long board = z->resource.start;
+	unsigned long base_addr = board + A2065_LANCE;
+	unsigned long mem_start = board + A2065_RAM;
+	struct resource *r1, *r2;
+	int err;
+
+	r1 = request_mem_region(base_addr, sizeof(struct lance_regs),
+				"Am7990");
+	if (!r1)
+		return -EBUSY;
+	r2 = request_mem_region(mem_start, A2065_RAM_SIZE, "RAM");
+	if (!r2) {
+		release_mem_region(base_addr, sizeof(struct lance_regs));
+		return -EBUSY;
+	}
+
+	dev = alloc_etherdev(sizeof(struct lance_private));
+	if (dev == NULL) {
+		release_mem_region(base_addr, sizeof(struct lance_regs));
+		release_mem_region(mem_start, A2065_RAM_SIZE);
+		return -ENOMEM;
+	}
+
+	priv = netdev_priv(dev);
+
+	r1->name = dev->name;
+	r2->name = dev->name;
+
+	dev->dev_addr[0] = 0x00;
+	if (z->id != ZORRO_PROD_AMERISTAR_A2065) {	/* Commodore */
+		dev->dev_addr[1] = 0x80;
+		dev->dev_addr[2] = 0x10;
+	} else {					/* Ameristar */
+		dev->dev_addr[1] = 0x00;
+		dev->dev_addr[2] = 0x9f;
+	}
+	dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff;
+	dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff;
+	dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
+	dev->base_addr = ZTWO_VADDR(base_addr);
+	dev->mem_start = ZTWO_VADDR(mem_start);
+	dev->mem_end = dev->mem_start + A2065_RAM_SIZE;
+
+	priv->ll = (volatile struct lance_regs *)dev->base_addr;
+	priv->init_block = (struct lance_init_block *)dev->mem_start;
+	priv->lance_init_block = (struct lance_init_block *)A2065_RAM;
+	priv->auto_select = 0;
+	priv->busmaster_regval = LE_C3_BSWP;
+
+	priv->lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;
+	priv->lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
+	priv->rx_ring_mod_mask = RX_RING_MOD_MASK;
+	priv->tx_ring_mod_mask = TX_RING_MOD_MASK;
+
+	dev->netdev_ops = &lance_netdev_ops;
+	dev->watchdog_timeo = 5*HZ;
+	dev->dma = 0;
+
+	init_timer(&priv->multicast_timer);
+	priv->multicast_timer.data = (unsigned long) dev;
+	priv->multicast_timer.function =
+		(void (*)(unsigned long))lance_set_multicast;
+
+	err = register_netdev(dev);
+	if (err) {
+		release_mem_region(base_addr, sizeof(struct lance_regs));
+		release_mem_region(mem_start, A2065_RAM_SIZE);
+		free_netdev(dev);
+		return err;
+	}
+	zorro_set_drvdata(z, dev);
+
+	netdev_info(dev, "A2065 at 0x%08lx, Ethernet Address %pM\n",
+		    board, dev->dev_addr);
+
+	return 0;
+}
+
+
+static void __devexit a2065_remove_one(struct zorro_dev *z)
+{
+	struct net_device *dev = zorro_get_drvdata(z);
+
+	unregister_netdev(dev);
+	release_mem_region(ZTWO_PADDR(dev->base_addr),
+			   sizeof(struct lance_regs));
+	release_mem_region(ZTWO_PADDR(dev->mem_start), A2065_RAM_SIZE);
+	free_netdev(dev);
+}
+
+static int __init a2065_init_module(void)
+{
+	return zorro_register_driver(&a2065_driver);
+}
+
+static void __exit a2065_cleanup_module(void)
+{
+	zorro_unregister_driver(&a2065_driver);
+}
+
+module_init(a2065_init_module);
+module_exit(a2065_cleanup_module);
+
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/a2065.h linux-libre-3.2-gnu/drivers/net/ethernet/amd/a2065.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/a2065.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/a2065.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,173 @@
+/*
+ * Amiga Linux/68k A2065 Ethernet Driver
+ *
+ * (C) Copyright 1995 by Geert Uytterhoeven <geert@linux-m68k.org>
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * This program is based on
+ *
+ *	ariadne.?:	Amiga Linux/68k Ariadne Ethernet Driver
+ *			(C) Copyright 1995 by Geert Uytterhoeven,
+ *			Peter De Schrijver
+ *
+ *	lance.c:	An AMD LANCE ethernet driver for linux.
+ *			Written 1993-94 by Donald Becker.
+ *
+ *	Am79C960:	PCnet(tm)-ISA Single-Chip Ethernet Controller
+ *			Advanced Micro Devices
+ *			Publication #16907, Rev. B, Amendment/0, May 1994
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of the Linux
+ * distribution for more details.
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * The A2065 is a Zorro-II board made by Commodore/Ameristar. It contains:
+ *
+ *	- an Am7990 Local Area Network Controller for Ethernet (LANCE) with
+ *	  both 10BASE-2 (thin coax) and AUI (DB-15) connectors
+ */
+
+
+/*
+ *		Am7990 Local Area Network Controller for Ethernet (LANCE)
+ */
+
+struct lance_regs {
+	unsigned short rdp;		/* Register Data Port */
+	unsigned short rap;		/* Register Address Port */
+};
+
+
+/*
+ *		Am7990 Control and Status Registers
+ */
+
+#define LE_CSR0		0x0000		/* LANCE Controller Status */
+#define LE_CSR1		0x0001		/* IADR[15:0] */
+#define LE_CSR2		0x0002		/* IADR[23:16] */
+#define LE_CSR3		0x0003		/* Misc */
+
+
+/*
+ *		Bit definitions for CSR0 (LANCE Controller Status)
+ */
+
+#define LE_C0_ERR	0x8000		/* Error */
+#define LE_C0_BABL	0x4000		/* Babble: Transmitted too many bits */
+#define LE_C0_CERR	0x2000		/* No Heartbeat (10BASE-T) */
+#define LE_C0_MISS	0x1000		/* Missed Frame */
+#define LE_C0_MERR	0x0800		/* Memory Error */
+#define LE_C0_RINT	0x0400		/* Receive Interrupt */
+#define LE_C0_TINT	0x0200		/* Transmit Interrupt */
+#define LE_C0_IDON	0x0100		/* Initialization Done */
+#define LE_C0_INTR	0x0080		/* Interrupt Flag */
+#define LE_C0_INEA	0x0040		/* Interrupt Enable */
+#define LE_C0_RXON	0x0020		/* Receive On */
+#define LE_C0_TXON	0x0010		/* Transmit On */
+#define LE_C0_TDMD	0x0008		/* Transmit Demand */
+#define LE_C0_STOP	0x0004		/* Stop */
+#define LE_C0_STRT	0x0002		/* Start */
+#define LE_C0_INIT	0x0001		/* Initialize */
+
+
+/*
+ *		Bit definitions for CSR3
+ */
+
+#define LE_C3_BSWP	0x0004		/* Byte Swap
+					   (on for big endian byte order) */
+#define LE_C3_ACON	0x0002		/* ALE Control
+					   (on for active low ALE) */
+#define LE_C3_BCON	0x0001		/* Byte Control */
+
+
+/*
+ *		Mode Flags
+ */
+
+#define LE_MO_PROM	0x8000		/* Promiscuous Mode */
+#define LE_MO_INTL	0x0040		/* Internal Loopback */
+#define LE_MO_DRTY	0x0020		/* Disable Retry */
+#define LE_MO_FCOLL	0x0010		/* Force Collision */
+#define LE_MO_DXMTFCS	0x0008		/* Disable Transmit CRC */
+#define LE_MO_LOOP	0x0004		/* Loopback Enable */
+#define LE_MO_DTX	0x0002		/* Disable Transmitter */
+#define LE_MO_DRX	0x0001		/* Disable Receiver */
+
+
+struct lance_rx_desc {
+	unsigned short rmd0;        /* low address of packet */
+	unsigned char  rmd1_bits;   /* descriptor bits */
+	unsigned char  rmd1_hadr;   /* high address of packet */
+	short    length;    	    /* This length is 2s complement (negative)!
+				     * Buffer length
+				     */
+	unsigned short mblength;    /* Aactual number of bytes received */
+};
+
+struct lance_tx_desc {
+	unsigned short tmd0;        /* low address of packet */
+	unsigned char  tmd1_bits;   /* descriptor bits */
+	unsigned char  tmd1_hadr;   /* high address of packet */
+	short    length;       	    /* Length is 2s complement (negative)! */
+	unsigned short misc;
+};
+
+
+/*
+ *		Receive Flags
+ */
+
+#define LE_R1_OWN	0x80		/* LANCE owns the descriptor */
+#define LE_R1_ERR	0x40		/* Error */
+#define LE_R1_FRA	0x20		/* Framing Error */
+#define LE_R1_OFL	0x10		/* Overflow Error */
+#define LE_R1_CRC	0x08		/* CRC Error */
+#define LE_R1_BUF	0x04		/* Buffer Error */
+#define LE_R1_SOP	0x02		/* Start of Packet */
+#define LE_R1_EOP	0x01		/* End of Packet */
+#define LE_R1_POK       0x03		/* Packet is complete: SOP + EOP */
+
+
+/*
+ *		Transmit Flags
+ */
+
+#define LE_T1_OWN	0x80		/* LANCE owns the descriptor */
+#define LE_T1_ERR	0x40		/* Error */
+#define LE_T1_RES	0x20		/* Reserved,
+					   LANCE writes this with a zero */
+#define LE_T1_EMORE	0x10		/* More than one retry needed */
+#define LE_T1_EONE	0x08		/* One retry needed */
+#define LE_T1_EDEF	0x04		/* Deferred */
+#define LE_T1_SOP	0x02		/* Start of Packet */
+#define LE_T1_EOP	0x01		/* End of Packet */
+#define LE_T1_POK	0x03		/* Packet is complete: SOP + EOP */
+
+
+/*
+ *		Error Flags
+ */
+
+#define LE_T3_BUF 	0x8000		/* Buffer Error */
+#define LE_T3_UFL 	0x4000		/* Underflow Error */
+#define LE_T3_LCOL 	0x1000		/* Late Collision */
+#define LE_T3_CLOS 	0x0800		/* Loss of Carrier */
+#define LE_T3_RTY 	0x0400		/* Retry Error */
+#define LE_T3_TDR	0x03ff		/* Time Domain Reflectometry */
+
+
+/*
+ *		A2065 Expansion Board Structure
+ */
+
+#define A2065_LANCE		0x4000
+
+#define A2065_RAM		0x8000
+#define A2065_RAM_SIZE		0x8000
+
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/am79c961a.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/am79c961a.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/am79c961a.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/am79c961a.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,770 @@
+/*
+ *  linux/drivers/net/am79c961.c
+ *
+ *  by Russell King <rmk@arm.linux.org.uk> 1995-2001.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Derived from various things including skeleton.c
+ *
+ * This is a special driver for the am79c961A Lance chip used in the
+ * Intel (formally Digital Equipment Corp) EBSA110 platform.  Please
+ * note that this can not be built as a module (it doesn't make sense).
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/system.h>
+
+#define TX_BUFFERS 15
+#define RX_BUFFERS 25
+
+#include "am79c961a.h"
+
+static irqreturn_t
+am79c961_interrupt (int irq, void *dev_id);
+
+static unsigned int net_debug = NET_DEBUG;
+
+static const char version[] =
+	"am79c961 ethernet driver (C) 1995-2001 Russell King v0.04\n";
+
+/* --------------------------------------------------------------------------- */
+
+#ifdef __arm__
+static void write_rreg(u_long base, u_int reg, u_int val)
+{
+	asm volatile(
+	"str%?h	%1, [%2]	@ NET_RAP\n\t"
+	"str%?h	%0, [%2, #-4]	@ NET_RDP"
+	:
+	: "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
+}
+
+static inline unsigned short read_rreg(u_long base_addr, u_int reg)
+{
+	unsigned short v;
+	asm volatile(
+	"str%?h	%1, [%2]	@ NET_RAP\n\t"
+	"ldr%?h	%0, [%2, #-4]	@ NET_RDP"
+	: "=r" (v)
+	: "r" (reg), "r" (ISAIO_BASE + 0x0464));
+	return v;
+}
+
+static inline void write_ireg(u_long base, u_int reg, u_int val)
+{
+	asm volatile(
+	"str%?h	%1, [%2]	@ NET_RAP\n\t"
+	"str%?h	%0, [%2, #8]	@ NET_IDP"
+	:
+	: "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
+}
+
+static inline unsigned short read_ireg(u_long base_addr, u_int reg)
+{
+	u_short v;
+	asm volatile(
+	"str%?h	%1, [%2]	@ NAT_RAP\n\t"
+	"ldr%?h	%0, [%2, #8]	@ NET_IDP\n\t"
+	: "=r" (v)
+	: "r" (reg), "r" (ISAIO_BASE + 0x0464));
+	return v;
+}
+
+#define am_writeword(dev,off,val) __raw_writew(val, ISAMEM_BASE + ((off) << 1))
+#define am_readword(dev,off)      __raw_readw(ISAMEM_BASE + ((off) << 1))
+
+static void
+am_writebuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length)
+{
+	offset = ISAMEM_BASE + (offset << 1);
+	length = (length + 1) & ~1;
+	if ((int)buf & 2) {
+		asm volatile("str%?h	%2, [%0], #4"
+		 : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
+		buf += 2;
+		length -= 2;
+	}
+	while (length > 8) {
+		register unsigned int tmp asm("r2"), tmp2 asm("r3");
+		asm volatile(
+			"ldm%?ia	%0!, {%1, %2}"
+			: "+r" (buf), "=&r" (tmp), "=&r" (tmp2));
+		length -= 8;
+		asm volatile(
+			"str%?h	%1, [%0], #4\n\t"
+			"mov%?	%1, %1, lsr #16\n\t"
+			"str%?h	%1, [%0], #4\n\t"
+			"str%?h	%2, [%0], #4\n\t"
+			"mov%?	%2, %2, lsr #16\n\t"
+			"str%?h	%2, [%0], #4"
+		: "+r" (offset), "=&r" (tmp), "=&r" (tmp2));
+	}
+	while (length > 0) {
+		asm volatile("str%?h	%2, [%0], #4"
+		 : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
+		buf += 2;
+		length -= 2;
+	}
+}
+
+static void
+am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length)
+{
+	offset = ISAMEM_BASE + (offset << 1);
+	length = (length + 1) & ~1;
+	if ((int)buf & 2) {
+		unsigned int tmp;
+		asm volatile(
+			"ldr%?h	%2, [%0], #4\n\t"
+			"str%?b	%2, [%1], #1\n\t"
+			"mov%?	%2, %2, lsr #8\n\t"
+			"str%?b	%2, [%1], #1"
+		: "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
+		length -= 2;
+	}
+	while (length > 8) {
+		register unsigned int tmp asm("r2"), tmp2 asm("r3"), tmp3;
+		asm volatile(
+			"ldr%?h	%2, [%0], #4\n\t"
+			"ldr%?h	%4, [%0], #4\n\t"
+			"ldr%?h	%3, [%0], #4\n\t"
+			"orr%?	%2, %2, %4, lsl #16\n\t"
+			"ldr%?h	%4, [%0], #4\n\t"
+			"orr%?	%3, %3, %4, lsl #16\n\t"
+			"stm%?ia	%1!, {%2, %3}"
+		: "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
+		: "0" (offset), "1" (buf));
+		length -= 8;
+	}
+	while (length > 0) {
+		unsigned int tmp;
+		asm volatile(
+			"ldr%?h	%2, [%0], #4\n\t"
+			"str%?b	%2, [%1], #1\n\t"
+			"mov%?	%2, %2, lsr #8\n\t"
+			"str%?b	%2, [%1], #1"
+		: "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
+		length -= 2;
+	}
+}
+#else
+#error Not compatible
+#endif
+
+static int
+am79c961_ramtest(struct net_device *dev, unsigned int val)
+{
+	unsigned char *buffer = kmalloc (65536, GFP_KERNEL);
+	int i, error = 0, errorcount = 0;
+
+	if (!buffer)
+		return 0;
+	memset (buffer, val, 65536);
+	am_writebuffer(dev, 0, buffer, 65536);
+	memset (buffer, val ^ 255, 65536);
+	am_readbuffer(dev, 0, buffer, 65536);
+	for (i = 0; i < 65536; i++) {
+		if (buffer[i] != val && !error) {
+			printk ("%s: buffer error (%02X %02X) %05X - ", dev->name, val, buffer[i], i);
+			error = 1;
+			errorcount ++;
+		} else if (error && buffer[i] == val) {
+			printk ("%05X\n", i);
+			error = 0;
+		}
+	}
+	if (error)
+		printk ("10000\n");
+	kfree (buffer);
+	return errorcount;
+}
+
+static void am79c961_mc_hash(char *addr, u16 *hash)
+{
+	int idx, bit;
+	u32 crc;
+
+	crc = ether_crc_le(ETH_ALEN, addr);
+
+	idx = crc >> 30;
+	bit = (crc >> 26) & 15;
+
+	hash[idx] |= 1 << bit;
+}
+
+static unsigned int am79c961_get_rx_mode(struct net_device *dev, u16 *hash)
+{
+	unsigned int mode = MODE_PORT_10BT;
+
+	if (dev->flags & IFF_PROMISC) {
+		mode |= MODE_PROMISC;
+		memset(hash, 0xff, 4 * sizeof(*hash));
+	} else if (dev->flags & IFF_ALLMULTI) {
+		memset(hash, 0xff, 4 * sizeof(*hash));
+	} else {
+		struct netdev_hw_addr *ha;
+
+		memset(hash, 0, 4 * sizeof(*hash));
+
+		netdev_for_each_mc_addr(ha, dev)
+			am79c961_mc_hash(ha->addr, hash);
+	}
+
+	return mode;
+}
+
+static void
+am79c961_init_for_open(struct net_device *dev)
+{
+	struct dev_priv *priv = netdev_priv(dev);
+	unsigned long flags;
+	unsigned char *p;
+	u_int hdr_addr, first_free_addr;
+	u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash);
+	int i;
+
+	/*
+	 * Stop the chip.
+	 */
+	spin_lock_irqsave(&priv->chip_lock, flags);
+	write_rreg (dev->base_addr, CSR0, CSR0_BABL|CSR0_CERR|CSR0_MISS|CSR0_MERR|CSR0_TINT|CSR0_RINT|CSR0_STOP);
+	spin_unlock_irqrestore(&priv->chip_lock, flags);
+
+	write_ireg (dev->base_addr, 5, 0x00a0); /* Receive address LED */
+	write_ireg (dev->base_addr, 6, 0x0081); /* Collision LED */
+	write_ireg (dev->base_addr, 7, 0x0090); /* XMIT LED */
+	write_ireg (dev->base_addr, 2, 0x0000); /* MODE register selects media */
+
+	for (i = LADRL; i <= LADRH; i++)
+		write_rreg (dev->base_addr, i, multi_hash[i - LADRL]);
+
+	for (i = PADRL, p = dev->dev_addr; i <= PADRH; i++, p += 2)
+		write_rreg (dev->base_addr, i, p[0] | (p[1] << 8));
+
+	write_rreg (dev->base_addr, MODE, mode);
+	write_rreg (dev->base_addr, POLLINT, 0);
+	write_rreg (dev->base_addr, SIZERXR, -RX_BUFFERS);
+	write_rreg (dev->base_addr, SIZETXR, -TX_BUFFERS);
+
+	first_free_addr = RX_BUFFERS * 8 + TX_BUFFERS * 8 + 16;
+	hdr_addr = 0;
+
+	priv->rxhead = 0;
+	priv->rxtail = 0;
+	priv->rxhdr = hdr_addr;
+
+	for (i = 0; i < RX_BUFFERS; i++) {
+		priv->rxbuffer[i] = first_free_addr;
+		am_writeword (dev, hdr_addr, first_free_addr);
+		am_writeword (dev, hdr_addr + 2, RMD_OWN);
+		am_writeword (dev, hdr_addr + 4, (-1600));
+		am_writeword (dev, hdr_addr + 6, 0);
+		first_free_addr += 1600;
+		hdr_addr += 8;
+	}
+	priv->txhead = 0;
+	priv->txtail = 0;
+	priv->txhdr = hdr_addr;
+	for (i = 0; i < TX_BUFFERS; i++) {
+		priv->txbuffer[i] = first_free_addr;
+		am_writeword (dev, hdr_addr, first_free_addr);
+		am_writeword (dev, hdr_addr + 2, TMD_STP|TMD_ENP);
+		am_writeword (dev, hdr_addr + 4, 0xf000);
+		am_writeword (dev, hdr_addr + 6, 0);
+		first_free_addr += 1600;
+		hdr_addr += 8;
+	}
+
+	write_rreg (dev->base_addr, BASERXL, priv->rxhdr);
+	write_rreg (dev->base_addr, BASERXH, 0);
+	write_rreg (dev->base_addr, BASETXL, priv->txhdr);
+	write_rreg (dev->base_addr, BASERXH, 0);
+	write_rreg (dev->base_addr, CSR0, CSR0_STOP);
+	write_rreg (dev->base_addr, CSR3, CSR3_IDONM|CSR3_BABLM|CSR3_DXSUFLO);
+	write_rreg (dev->base_addr, CSR4, CSR4_APAD_XMIT|CSR4_MFCOM|CSR4_RCVCCOM|CSR4_TXSTRTM|CSR4_JABM);
+	write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT);
+}
+
+static void am79c961_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct dev_priv *priv = netdev_priv(dev);
+	unsigned int lnkstat, carrier;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->chip_lock, flags);
+	lnkstat = read_ireg(dev->base_addr, ISALED0) & ISALED0_LNKST;
+	spin_unlock_irqrestore(&priv->chip_lock, flags);
+	carrier = netif_carrier_ok(dev);
+
+	if (lnkstat && !carrier) {
+		netif_carrier_on(dev);
+		printk("%s: link up\n", dev->name);
+	} else if (!lnkstat && carrier) {
+		netif_carrier_off(dev);
+		printk("%s: link down\n", dev->name);
+	}
+
+	mod_timer(&priv->timer, jiffies + msecs_to_jiffies(500));
+}
+
+/*
+ * Open/initialize the board.
+ */
+static int
+am79c961_open(struct net_device *dev)
+{
+	struct dev_priv *priv = netdev_priv(dev);
+	int ret;
+
+	ret = request_irq(dev->irq, am79c961_interrupt, 0, dev->name, dev);
+	if (ret)
+		return ret;
+
+	am79c961_init_for_open(dev);
+
+	netif_carrier_off(dev);
+
+	priv->timer.expires = jiffies;
+	add_timer(&priv->timer);
+
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+/*
+ * The inverse routine to am79c961_open().
+ */
+static int
+am79c961_close(struct net_device *dev)
+{
+	struct dev_priv *priv = netdev_priv(dev);
+	unsigned long flags;
+
+	del_timer_sync(&priv->timer);
+
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+
+	spin_lock_irqsave(&priv->chip_lock, flags);
+	write_rreg (dev->base_addr, CSR0, CSR0_STOP);
+	write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
+	spin_unlock_irqrestore(&priv->chip_lock, flags);
+
+	free_irq (dev->irq, dev);
+
+	return 0;
+}
+
+/*
+ * Set or clear promiscuous/multicast mode filter for this adapter.
+ */
+static void am79c961_setmulticastlist (struct net_device *dev)
+{
+	struct dev_priv *priv = netdev_priv(dev);
+	unsigned long flags;
+	u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash);
+	int i, stopped;
+
+	spin_lock_irqsave(&priv->chip_lock, flags);
+
+	stopped = read_rreg(dev->base_addr, CSR0) & CSR0_STOP;
+
+	if (!stopped) {
+		/*
+		 * Put the chip into suspend mode
+		 */
+		write_rreg(dev->base_addr, CTRL1, CTRL1_SPND);
+
+		/*
+		 * Spin waiting for chip to report suspend mode
+		 */
+		while ((read_rreg(dev->base_addr, CTRL1) & CTRL1_SPND) == 0) {
+			spin_unlock_irqrestore(&priv->chip_lock, flags);
+			nop();
+			spin_lock_irqsave(&priv->chip_lock, flags);
+		}
+	}
+
+	/*
+	 * Update the multicast hash table
+	 */
+	for (i = 0; i < ARRAY_SIZE(multi_hash); i++)
+		write_rreg(dev->base_addr, i + LADRL, multi_hash[i]);
+
+	/*
+	 * Write the mode register
+	 */
+	write_rreg(dev->base_addr, MODE, mode);
+
+	if (!stopped) {
+		/*
+		 * Put the chip back into running mode
+		 */
+		write_rreg(dev->base_addr, CTRL1, 0);
+	}
+
+	spin_unlock_irqrestore(&priv->chip_lock, flags);
+}
+
+static void am79c961_timeout(struct net_device *dev)
+{
+	printk(KERN_WARNING "%s: transmit timed out, network cable problem?\n",
+		dev->name);
+
+	/*
+	 * ought to do some setup of the tx side here
+	 */
+
+	netif_wake_queue(dev);
+}
+
+/*
+ * Transmit a packet
+ */
+static int
+am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev)
+{
+	struct dev_priv *priv = netdev_priv(dev);
+	unsigned int hdraddr, bufaddr;
+	unsigned int head;
+	unsigned long flags;
+
+	head = priv->txhead;
+	hdraddr = priv->txhdr + (head << 3);
+	bufaddr = priv->txbuffer[head];
+	head += 1;
+	if (head >= TX_BUFFERS)
+		head = 0;
+
+	am_writebuffer (dev, bufaddr, skb->data, skb->len);
+	am_writeword (dev, hdraddr + 4, -skb->len);
+	am_writeword (dev, hdraddr + 2, TMD_OWN|TMD_STP|TMD_ENP);
+	priv->txhead = head;
+
+	spin_lock_irqsave(&priv->chip_lock, flags);
+	write_rreg (dev->base_addr, CSR0, CSR0_TDMD|CSR0_IENA);
+	spin_unlock_irqrestore(&priv->chip_lock, flags);
+
+	/*
+	 * If the next packet is owned by the ethernet device,
+	 * then the tx ring is full and we can't add another
+	 * packet.
+	 */
+	if (am_readword(dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN)
+		netif_stop_queue(dev);
+
+	dev_kfree_skb(skb);
+
+	return NETDEV_TX_OK;
+}
+
+/*
+ * If we have a good packet(s), get it/them out of the buffers.
+ */
+static void
+am79c961_rx(struct net_device *dev, struct dev_priv *priv)
+{
+	do {
+		struct sk_buff *skb;
+		u_int hdraddr;
+		u_int pktaddr;
+		u_int status;
+		int len;
+
+		hdraddr = priv->rxhdr + (priv->rxtail << 3);
+		pktaddr = priv->rxbuffer[priv->rxtail];
+
+		status = am_readword (dev, hdraddr + 2);
+		if (status & RMD_OWN) /* do we own it? */
+			break;
+
+		priv->rxtail ++;
+		if (priv->rxtail >= RX_BUFFERS)
+			priv->rxtail = 0;
+
+		if ((status & (RMD_ERR|RMD_STP|RMD_ENP)) != (RMD_STP|RMD_ENP)) {
+			am_writeword (dev, hdraddr + 2, RMD_OWN);
+			dev->stats.rx_errors++;
+			if (status & RMD_ERR) {
+				if (status & RMD_FRAM)
+					dev->stats.rx_frame_errors++;
+				if (status & RMD_CRC)
+					dev->stats.rx_crc_errors++;
+			} else if (status & RMD_STP)
+				dev->stats.rx_length_errors++;
+			continue;
+		}
+
+		len = am_readword(dev, hdraddr + 6);
+		skb = dev_alloc_skb(len + 2);
+
+		if (skb) {
+			skb_reserve(skb, 2);
+
+			am_readbuffer(dev, pktaddr, skb_put(skb, len), len);
+			am_writeword(dev, hdraddr + 2, RMD_OWN);
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+			dev->stats.rx_bytes += len;
+			dev->stats.rx_packets++;
+		} else {
+			am_writeword (dev, hdraddr + 2, RMD_OWN);
+			printk (KERN_WARNING "%s: memory squeeze, dropping packet.\n", dev->name);
+			dev->stats.rx_dropped++;
+			break;
+		}
+	} while (1);
+}
+
+/*
+ * Update stats for the transmitted packet
+ */
+static void
+am79c961_tx(struct net_device *dev, struct dev_priv *priv)
+{
+	do {
+		short len;
+		u_int hdraddr;
+		u_int status;
+
+		hdraddr = priv->txhdr + (priv->txtail << 3);
+		status = am_readword (dev, hdraddr + 2);
+		if (status & TMD_OWN)
+			break;
+
+		priv->txtail ++;
+		if (priv->txtail >= TX_BUFFERS)
+			priv->txtail = 0;
+
+		if (status & TMD_ERR) {
+			u_int status2;
+
+			dev->stats.tx_errors++;
+
+			status2 = am_readword (dev, hdraddr + 6);
+
+			/*
+			 * Clear the error byte
+			 */
+			am_writeword (dev, hdraddr + 6, 0);
+
+			if (status2 & TST_RTRY)
+				dev->stats.collisions += 16;
+			if (status2 & TST_LCOL)
+				dev->stats.tx_window_errors++;
+			if (status2 & TST_LCAR)
+				dev->stats.tx_carrier_errors++;
+			if (status2 & TST_UFLO)
+				dev->stats.tx_fifo_errors++;
+			continue;
+		}
+		dev->stats.tx_packets++;
+		len = am_readword (dev, hdraddr + 4);
+		dev->stats.tx_bytes += -len;
+	} while (priv->txtail != priv->txhead);
+
+	netif_wake_queue(dev);
+}
+
+static irqreturn_t
+am79c961_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = (struct net_device *)dev_id;
+	struct dev_priv *priv = netdev_priv(dev);
+	u_int status, n = 100;
+	int handled = 0;
+
+	do {
+		status = read_rreg(dev->base_addr, CSR0);
+		write_rreg(dev->base_addr, CSR0, status &
+			   (CSR0_IENA|CSR0_TINT|CSR0_RINT|
+			    CSR0_MERR|CSR0_MISS|CSR0_CERR|CSR0_BABL));
+
+		if (status & CSR0_RINT) {
+			handled = 1;
+			am79c961_rx(dev, priv);
+		}
+		if (status & CSR0_TINT) {
+			handled = 1;
+			am79c961_tx(dev, priv);
+		}
+		if (status & CSR0_MISS) {
+			handled = 1;
+			dev->stats.rx_dropped++;
+		}
+		if (status & CSR0_CERR) {
+			handled = 1;
+			mod_timer(&priv->timer, jiffies);
+		}
+	} while (--n && status & (CSR0_RINT | CSR0_TINT));
+
+	return IRQ_RETVAL(handled);
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void am79c961_poll_controller(struct net_device *dev)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+	am79c961_interrupt(dev->irq, dev);
+	local_irq_restore(flags);
+}
+#endif
+
+/*
+ * Initialise the chip.  Note that we always expect
+ * to be entered with interrupts enabled.
+ */
+static int
+am79c961_hw_init(struct net_device *dev)
+{
+	struct dev_priv *priv = netdev_priv(dev);
+
+	spin_lock_irq(&priv->chip_lock);
+	write_rreg (dev->base_addr, CSR0, CSR0_STOP);
+	write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
+	spin_unlock_irq(&priv->chip_lock);
+
+	am79c961_ramtest(dev, 0x66);
+	am79c961_ramtest(dev, 0x99);
+
+	return 0;
+}
+
+static void __init am79c961_banner(void)
+{
+	static unsigned version_printed;
+
+	if (net_debug && version_printed++ == 0)
+		printk(KERN_INFO "%s", version);
+}
+static const struct net_device_ops am79c961_netdev_ops = {
+	.ndo_open		= am79c961_open,
+	.ndo_stop		= am79c961_close,
+	.ndo_start_xmit		= am79c961_sendpacket,
+	.ndo_set_rx_mode	= am79c961_setmulticastlist,
+	.ndo_tx_timeout		= am79c961_timeout,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address	= eth_mac_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= am79c961_poll_controller,
+#endif
+};
+
+static int __devinit am79c961_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct net_device *dev;
+	struct dev_priv *priv;
+	int i, ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!res)
+		return -ENODEV;
+
+	dev = alloc_etherdev(sizeof(struct dev_priv));
+	ret = -ENOMEM;
+	if (!dev)
+		goto out;
+
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	priv = netdev_priv(dev);
+
+	/*
+	 * Fixed address and IRQ lines here.
+	 * The PNP initialisation should have been
+	 * done by the ether bootp loader.
+	 */
+	dev->base_addr = res->start;
+	ret = platform_get_irq(pdev, 0);
+
+	if (ret < 0) {
+		ret = -ENODEV;
+		goto nodev;
+	}
+	dev->irq = ret;
+
+	ret = -ENODEV;
+	if (!request_region(dev->base_addr, 0x18, dev->name))
+		goto nodev;
+
+	/*
+	 * Reset the device.
+	 */
+	inb(dev->base_addr + NET_RESET);
+	udelay(5);
+
+	/*
+	 * Check the manufacturer part of the
+	 * ether address.
+	 */
+	if (inb(dev->base_addr) != 0x08 ||
+	    inb(dev->base_addr + 2) != 0x00 ||
+	    inb(dev->base_addr + 4) != 0x2b)
+	    	goto release;
+
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = inb(dev->base_addr + i * 2) & 0xff;
+
+	am79c961_banner();
+
+	spin_lock_init(&priv->chip_lock);
+	init_timer(&priv->timer);
+	priv->timer.data = (unsigned long)dev;
+	priv->timer.function = am79c961_timer;
+
+	if (am79c961_hw_init(dev))
+		goto release;
+
+	dev->netdev_ops = &am79c961_netdev_ops;
+
+	ret = register_netdev(dev);
+	if (ret == 0) {
+		printk(KERN_INFO "%s: ether address %pM\n",
+		       dev->name, dev->dev_addr);
+		return 0;
+	}
+
+release:
+	release_region(dev->base_addr, 0x18);
+nodev:
+	free_netdev(dev);
+out:
+	return ret;
+}
+
+static struct platform_driver am79c961_driver = {
+	.probe		= am79c961_probe,
+	.driver		= {
+		.name	= "am79c961",
+	},
+};
+
+static int __init am79c961_init(void)
+{
+	return platform_driver_register(&am79c961_driver);
+}
+
+__initcall(am79c961_init);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/am79c961a.h linux-libre-3.2-gnu/drivers/net/ethernet/amd/am79c961a.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/am79c961a.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/am79c961a.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,145 @@
+/*
+ * linux/drivers/net/arm/am79c961a.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 _LINUX_am79c961a_H
+#define _LINUX_am79c961a_H
+
+/* use 0 for production, 1 for verification, >2 for debug. debug flags: */
+#define DEBUG_TX	 2
+#define DEBUG_RX	 4
+#define DEBUG_INT	 8
+#define DEBUG_IC	16
+#ifndef NET_DEBUG
+#define NET_DEBUG 	0
+#endif
+
+#define NET_UID		0
+#define NET_RDP		0x10
+#define NET_RAP		0x12
+#define NET_RESET	0x14
+#define NET_IDP		0x16
+
+/*
+ * RAP registers
+ */
+#define CSR0		0
+#define CSR0_INIT	0x0001
+#define CSR0_STRT	0x0002
+#define CSR0_STOP	0x0004
+#define CSR0_TDMD	0x0008
+#define CSR0_TXON	0x0010
+#define CSR0_RXON	0x0020
+#define CSR0_IENA	0x0040
+#define CSR0_INTR	0x0080
+#define CSR0_IDON	0x0100
+#define CSR0_TINT	0x0200
+#define CSR0_RINT	0x0400
+#define CSR0_MERR	0x0800
+#define CSR0_MISS	0x1000
+#define CSR0_CERR	0x2000
+#define CSR0_BABL	0x4000
+#define CSR0_ERR	0x8000
+
+#define CSR3		3
+#define CSR3_EMBA	0x0008
+#define CSR3_DXMT2PD	0x0010
+#define CSR3_LAPPEN	0x0020
+#define CSR3_DXSUFLO	0x0040
+#define CSR3_IDONM	0x0100
+#define CSR3_TINTM	0x0200
+#define CSR3_RINTM	0x0400
+#define CSR3_MERRM	0x0800
+#define CSR3_MISSM	0x1000
+#define CSR3_BABLM	0x4000
+#define CSR3_MASKALL	0x5F00
+
+#define CSR4		4
+#define CSR4_JABM	0x0001
+#define CSR4_JAB	0x0002
+#define CSR4_TXSTRTM	0x0004
+#define CSR4_TXSTRT	0x0008
+#define CSR4_RCVCCOM	0x0010
+#define CSR4_RCVCCO	0x0020
+#define CSR4_MFCOM	0x0100
+#define CSR4_MFCO	0x0200
+#define CSR4_ASTRP_RCV	0x0400
+#define CSR4_APAD_XMIT	0x0800
+
+#define CTRL1		5
+#define CTRL1_SPND	0x0001
+
+#define LADRL		8
+#define LADRM1		9
+#define LADRM2		10
+#define LADRH		11
+#define PADRL		12
+#define PADRM		13
+#define PADRH		14
+
+#define MODE		15
+#define MODE_DISRX	0x0001
+#define MODE_DISTX	0x0002
+#define MODE_LOOP	0x0004
+#define MODE_DTCRC	0x0008
+#define MODE_COLL	0x0010
+#define MODE_DRETRY	0x0020
+#define MODE_INTLOOP	0x0040
+#define MODE_PORT_AUI	0x0000
+#define MODE_PORT_10BT	0x0080
+#define MODE_DRXPA	0x2000
+#define MODE_DRXBA	0x4000
+#define MODE_PROMISC	0x8000
+
+#define BASERXL		24
+#define BASERXH		25
+#define BASETXL		30
+#define BASETXH		31
+
+#define POLLINT		47
+
+#define SIZERXR		76
+#define SIZETXR		78
+
+#define CSR_MFC		112
+
+#define RMD_ENP		0x0100
+#define RMD_STP		0x0200
+#define RMD_CRC		0x0800
+#define RMD_FRAM	0x2000
+#define RMD_ERR		0x4000
+#define RMD_OWN		0x8000
+
+#define TMD_ENP		0x0100
+#define TMD_STP		0x0200
+#define TMD_MORE	0x1000
+#define TMD_ERR		0x4000
+#define TMD_OWN		0x8000
+
+#define TST_RTRY	0x0400
+#define TST_LCAR	0x0800
+#define TST_LCOL	0x1000
+#define TST_UFLO	0x4000
+#define TST_BUFF	0x8000
+
+#define ISALED0		0x0004
+#define ISALED0_LNKST	0x8000
+
+struct dev_priv {
+    unsigned long	rxbuffer[RX_BUFFERS];
+    unsigned long	txbuffer[TX_BUFFERS];
+    unsigned char	txhead;
+    unsigned char	txtail;
+    unsigned char	rxhead;
+    unsigned char	rxtail;
+    unsigned long	rxhdr;
+    unsigned long	txhdr;
+    spinlock_t		chip_lock;
+    struct timer_list	timer;
+};
+
+#endif
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/amd8111e.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/amd8111e.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/amd8111e.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/amd8111e.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1992 @@
+
+/* Advanced  Micro Devices Inc. AMD8111E Linux Network Driver
+ * Copyright (C) 2004 Advanced Micro Devices
+ *
+ *
+ * Copyright 2001,2002 Jeff Garzik <jgarzik@mandrakesoft.com> [ 8139cp.c,tg3.c ]
+ * Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com)[ tg3.c]
+ * Copyright 1996-1999 Thomas Bogendoerfer [ pcnet32.c ]
+ * Derived from the lance driver written 1993,1994,1995 by Donald Becker.
+ * Copyright 1993 United States Government as represented by the
+ *	Director, National Security Agency.[ pcnet32.c ]
+ * Carsten Langgaard, carstenl@mips.com [ pcnet32.c ]
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+
+Module Name:
+
+	amd8111e.c
+
+Abstract:
+
+ 	 AMD8111 based 10/100 Ethernet Controller Driver.
+
+Environment:
+
+	Kernel Mode
+
+Revision History:
+ 	3.0.0
+	   Initial Revision.
+	3.0.1
+	 1. Dynamic interrupt coalescing.
+	 2. Removed prev_stats.
+	 3. MII support.
+	 4. Dynamic IPG support
+	3.0.2  05/29/2003
+	 1. Bug fix: Fixed failure to send jumbo packets larger than 4k.
+	 2. Bug fix: Fixed VLAN support failure.
+	 3. Bug fix: Fixed receive interrupt coalescing bug.
+	 4. Dynamic IPG support is disabled by default.
+	3.0.3 06/05/2003
+	 1. Bug fix: Fixed failure to close the interface if SMP is enabled.
+	3.0.4 12/09/2003
+	 1. Added set_mac_address routine for bonding driver support.
+	 2. Tested the driver for bonding support
+	 3. Bug fix: Fixed mismach in actual receive buffer lenth and lenth
+	    indicated to the h/w.
+	 4. Modified amd8111e_rx() routine to receive all the received packets
+	    in the first interrupt.
+	 5. Bug fix: Corrected  rx_errors  reported in get_stats() function.
+	3.0.5 03/22/2004
+	 1. Added NAPI support
+
+*/
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/if_vlan.h>
+#include <linux/ctype.h>
+#include <linux/crc32.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+#define AMD8111E_VLAN_TAG_USED 1
+#else
+#define AMD8111E_VLAN_TAG_USED 0
+#endif
+
+#include "amd8111e.h"
+#define MODULE_NAME	"amd8111e"
+#define MODULE_VERS	"3.0.7"
+MODULE_AUTHOR("Advanced Micro Devices, Inc.");
+MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version "MODULE_VERS);
+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 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);
+MODULE_PARM_DESC(dynamic_ipg, "Enable or Disable dynamic IPG, 1: Enable, 0: Disable");
+
+static DEFINE_PCI_DEVICE_TABLE(amd8111e_pci_tbl) = {
+
+	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD8111E_7462,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ 0, }
+
+};
+/*
+This function will read the PHY registers.
+*/
+static int amd8111e_read_phy(struct amd8111e_priv* lp, int phy_id, int reg, u32* val)
+{
+	void __iomem *mmio = lp->mmio;
+	unsigned int reg_val;
+	unsigned int repeat= REPEAT_CNT;
+
+	reg_val = readl(mmio + PHY_ACCESS);
+	while (reg_val & PHY_CMD_ACTIVE)
+		reg_val = readl( mmio + PHY_ACCESS );
+
+	writel( PHY_RD_CMD | ((phy_id & 0x1f) << 21) |
+			   ((reg & 0x1f) << 16),  mmio +PHY_ACCESS);
+	do{
+		reg_val = readl(mmio + PHY_ACCESS);
+		udelay(30);  /* It takes 30 us to read/write data */
+	} while (--repeat && (reg_val & PHY_CMD_ACTIVE));
+	if(reg_val & PHY_RD_ERR)
+		goto err_phy_read;
+
+	*val = reg_val & 0xffff;
+	return 0;
+err_phy_read:
+	*val = 0;
+	return -EINVAL;
+
+}
+
+/*
+This function will write into PHY registers.
+*/
+static int amd8111e_write_phy(struct amd8111e_priv* lp,int phy_id, int reg, u32 val)
+{
+	unsigned int repeat = REPEAT_CNT;
+	void __iomem *mmio = lp->mmio;
+	unsigned int reg_val;
+
+	reg_val = readl(mmio + PHY_ACCESS);
+	while (reg_val & PHY_CMD_ACTIVE)
+		reg_val = readl( mmio + PHY_ACCESS );
+
+	writel( PHY_WR_CMD | ((phy_id & 0x1f) << 21) |
+			   ((reg & 0x1f) << 16)|val, mmio + PHY_ACCESS);
+
+	do{
+		reg_val = readl(mmio + PHY_ACCESS);
+		udelay(30);  /* It takes 30 us to read/write the data */
+	} while (--repeat && (reg_val & PHY_CMD_ACTIVE));
+
+	if(reg_val & PHY_RD_ERR)
+		goto err_phy_write;
+
+	return 0;
+
+err_phy_write:
+	return -EINVAL;
+
+}
+/*
+This is the mii register read function provided to the mii interface.
+*/
+static int amd8111e_mdio_read(struct net_device * dev, int phy_id, int reg_num)
+{
+	struct amd8111e_priv* lp = netdev_priv(dev);
+	unsigned int reg_val;
+
+	amd8111e_read_phy(lp,phy_id,reg_num,&reg_val);
+	return reg_val;
+
+}
+
+/*
+This is the mii register write function provided to the mii interface.
+*/
+static void amd8111e_mdio_write(struct net_device * dev, int phy_id, int reg_num, int val)
+{
+	struct amd8111e_priv* lp = netdev_priv(dev);
+
+	amd8111e_write_phy(lp, phy_id, reg_num, val);
+}
+
+/*
+This function will set PHY speed. During initialization sets the original speed to 100 full.
+*/
+static void amd8111e_set_ext_phy(struct net_device *dev)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	u32 bmcr,advert,tmp;
+
+	/* Determine mii register values to set the speed */
+	advert = amd8111e_mdio_read(dev, lp->ext_phy_addr, MII_ADVERTISE);
+	tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+	switch (lp->ext_phy_option){
+
+		default:
+		case SPEED_AUTONEG: /* advertise all values */
+			tmp |= ( ADVERTISE_10HALF|ADVERTISE_10FULL|
+				ADVERTISE_100HALF|ADVERTISE_100FULL) ;
+			break;
+		case SPEED10_HALF:
+			tmp |= ADVERTISE_10HALF;
+			break;
+		case SPEED10_FULL:
+			tmp |= ADVERTISE_10FULL;
+			break;
+		case SPEED100_HALF:
+			tmp |= ADVERTISE_100HALF;
+			break;
+		case SPEED100_FULL:
+			tmp |= ADVERTISE_100FULL;
+			break;
+	}
+
+	if(advert != tmp)
+		amd8111e_mdio_write(dev, lp->ext_phy_addr, MII_ADVERTISE, tmp);
+	/* Restart auto negotiation */
+	bmcr = amd8111e_mdio_read(dev, lp->ext_phy_addr, MII_BMCR);
+	bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+	amd8111e_mdio_write(dev, lp->ext_phy_addr, MII_BMCR, bmcr);
+
+}
+
+/*
+This function will unmap skb->data space and will free
+all transmit and receive skbuffs.
+*/
+static int amd8111e_free_skbs(struct net_device *dev)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	struct sk_buff* rx_skbuff;
+	int i;
+
+	/* Freeing transmit skbs */
+	for(i = 0; i < NUM_TX_BUFFERS; i++){
+		if(lp->tx_skbuff[i]){
+			pci_unmap_single(lp->pci_dev,lp->tx_dma_addr[i],					lp->tx_skbuff[i]->len,PCI_DMA_TODEVICE);
+			dev_kfree_skb (lp->tx_skbuff[i]);
+			lp->tx_skbuff[i] = NULL;
+			lp->tx_dma_addr[i] = 0;
+		}
+	}
+	/* Freeing previously allocated receive buffers */
+	for (i = 0; i < NUM_RX_BUFFERS; i++){
+		rx_skbuff = lp->rx_skbuff[i];
+		if(rx_skbuff != NULL){
+			pci_unmap_single(lp->pci_dev,lp->rx_dma_addr[i],
+				  lp->rx_buff_len - 2,PCI_DMA_FROMDEVICE);
+			dev_kfree_skb(lp->rx_skbuff[i]);
+			lp->rx_skbuff[i] = NULL;
+			lp->rx_dma_addr[i] = 0;
+		}
+	}
+
+	return 0;
+}
+
+/*
+This will set the receive buffer length corresponding to the mtu size of networkinterface.
+*/
+static inline void amd8111e_set_rx_buff_len(struct net_device* dev)
+{
+	struct amd8111e_priv* lp = netdev_priv(dev);
+	unsigned int mtu = dev->mtu;
+
+	if (mtu > ETH_DATA_LEN){
+		/* MTU + ethernet header + FCS
+		+ optional VLAN tag + skb reserve space 2 */
+
+		lp->rx_buff_len = mtu + ETH_HLEN + 10;
+		lp->options |= OPTION_JUMBO_ENABLE;
+	} else{
+		lp->rx_buff_len = PKT_BUFF_SZ;
+		lp->options &= ~OPTION_JUMBO_ENABLE;
+	}
+}
+
+/*
+This function will free all the previously allocated buffers, determine new receive buffer length  and will allocate new receive buffers. This function also allocates and initializes both the transmitter and receive hardware descriptors.
+ */
+static int amd8111e_init_ring(struct net_device *dev)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	int i;
+
+	lp->rx_idx = lp->tx_idx = 0;
+	lp->tx_complete_idx = 0;
+	lp->tx_ring_idx = 0;
+
+
+	if(lp->opened)
+		/* Free previously allocated transmit and receive skbs */
+		amd8111e_free_skbs(dev);
+
+	else{
+		 /* allocate the tx and rx descriptors */
+	     	if((lp->tx_ring = pci_alloc_consistent(lp->pci_dev,
+			sizeof(struct amd8111e_tx_dr)*NUM_TX_RING_DR,
+			&lp->tx_ring_dma_addr)) == NULL)
+
+			goto err_no_mem;
+
+	     	if((lp->rx_ring = pci_alloc_consistent(lp->pci_dev,
+			sizeof(struct amd8111e_rx_dr)*NUM_RX_RING_DR,
+			&lp->rx_ring_dma_addr)) == NULL)
+
+			goto err_free_tx_ring;
+
+	}
+	/* Set new receive buff size */
+	amd8111e_set_rx_buff_len(dev);
+
+	/* Allocating receive  skbs */
+	for (i = 0; i < NUM_RX_BUFFERS; i++) {
+
+		if (!(lp->rx_skbuff[i] = dev_alloc_skb(lp->rx_buff_len))) {
+				/* Release previos allocated skbs */
+				for(--i; i >= 0 ;i--)
+					dev_kfree_skb(lp->rx_skbuff[i]);
+				goto err_free_rx_ring;
+		}
+		skb_reserve(lp->rx_skbuff[i],2);
+	}
+        /* Initilaizing receive descriptors */
+	for (i = 0; i < NUM_RX_BUFFERS; i++) {
+		lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev,
+			lp->rx_skbuff[i]->data,lp->rx_buff_len-2, PCI_DMA_FROMDEVICE);
+
+		lp->rx_ring[i].buff_phy_addr = cpu_to_le32(lp->rx_dma_addr[i]);
+		lp->rx_ring[i].buff_count = cpu_to_le16(lp->rx_buff_len-2);
+		wmb();
+		lp->rx_ring[i].rx_flags = cpu_to_le16(OWN_BIT);
+	}
+
+	/* Initializing transmit descriptors */
+	for (i = 0; i < NUM_TX_RING_DR; i++) {
+		lp->tx_ring[i].buff_phy_addr = 0;
+		lp->tx_ring[i].tx_flags = 0;
+		lp->tx_ring[i].buff_count = 0;
+	}
+
+	return 0;
+
+err_free_rx_ring:
+
+	pci_free_consistent(lp->pci_dev,
+		sizeof(struct amd8111e_rx_dr)*NUM_RX_RING_DR,lp->rx_ring,
+		lp->rx_ring_dma_addr);
+
+err_free_tx_ring:
+
+	pci_free_consistent(lp->pci_dev,
+		 sizeof(struct amd8111e_tx_dr)*NUM_TX_RING_DR,lp->tx_ring,
+		 lp->tx_ring_dma_addr);
+
+err_no_mem:
+	return -ENOMEM;
+}
+/* This function will set the interrupt coalescing according to the input arguments */
+static int amd8111e_set_coalesce(struct net_device * dev, enum coal_mode cmod)
+{
+	unsigned int timeout;
+	unsigned int event_count;
+
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	void __iomem *mmio = lp->mmio;
+	struct amd8111e_coalesce_conf * coal_conf = &lp->coal_conf;
+
+
+	switch(cmod)
+	{
+		case RX_INTR_COAL :
+			timeout = coal_conf->rx_timeout;
+			event_count = coal_conf->rx_event_count;
+			if( timeout > MAX_TIMEOUT ||
+					event_count > MAX_EVENT_COUNT )
+				return -EINVAL;
+
+			timeout = timeout * DELAY_TIMER_CONV;
+			writel(VAL0|STINTEN, mmio+INTEN0);
+			writel((u32)DLY_INT_A_R0|( event_count<< 16 )|timeout,
+							mmio+DLY_INT_A);
+			break;
+
+		case TX_INTR_COAL :
+			timeout = coal_conf->tx_timeout;
+			event_count = coal_conf->tx_event_count;
+			if( timeout > MAX_TIMEOUT ||
+					event_count > MAX_EVENT_COUNT )
+				return -EINVAL;
+
+
+			timeout = timeout * DELAY_TIMER_CONV;
+			writel(VAL0|STINTEN,mmio+INTEN0);
+			writel((u32)DLY_INT_B_T0|( event_count<< 16 )|timeout,
+							 mmio+DLY_INT_B);
+			break;
+
+		case DISABLE_COAL:
+			writel(0,mmio+STVAL);
+			writel(STINTEN, mmio+INTEN0);
+			writel(0, mmio +DLY_INT_B);
+			writel(0, mmio+DLY_INT_A);
+			break;
+		 case ENABLE_COAL:
+		       /* Start the timer */
+			writel((u32)SOFT_TIMER_FREQ, mmio+STVAL); /*  0.5 sec */
+			writel(VAL0|STINTEN, mmio+INTEN0);
+			break;
+		default:
+			break;
+
+   }
+	return 0;
+
+}
+
+/*
+This function initializes the device registers  and starts the device.
+*/
+static int amd8111e_restart(struct net_device *dev)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	void __iomem *mmio = lp->mmio;
+	int i,reg_val;
+
+	/* stop the chip */
+	 writel(RUN, mmio + CMD0);
+
+	if(amd8111e_init_ring(dev))
+		return -ENOMEM;
+
+	/* enable the port manager and set auto negotiation always */
+	writel((u32) VAL1|EN_PMGR, mmio + CMD3 );
+	writel((u32)XPHYANE|XPHYRST , mmio + CTRL2);
+
+	amd8111e_set_ext_phy(dev);
+
+	/* set control registers */
+	reg_val = readl(mmio + CTRL1);
+	reg_val &= ~XMTSP_MASK;
+	writel( reg_val| XMTSP_128 | CACHE_ALIGN, mmio + CTRL1 );
+
+	/* enable interrupt */
+	writel( APINT5EN | APINT4EN | APINT3EN | APINT2EN | APINT1EN |
+		APINT0EN | MIIPDTINTEN | MCCIINTEN | MCCINTEN | MREINTEN |
+		SPNDINTEN | MPINTEN | SINTEN | STINTEN, mmio + INTEN0);
+
+	writel(VAL3 | LCINTEN | VAL1 | TINTEN0 | VAL0 | RINTEN0, mmio + INTEN0);
+
+	/* initialize tx and rx ring base addresses */
+	writel((u32)lp->tx_ring_dma_addr,mmio + XMT_RING_BASE_ADDR0);
+	writel((u32)lp->rx_ring_dma_addr,mmio+ RCV_RING_BASE_ADDR0);
+
+	writew((u32)NUM_TX_RING_DR, mmio + XMT_RING_LEN0);
+	writew((u16)NUM_RX_RING_DR, mmio + RCV_RING_LEN0);
+
+	/* set default IPG to 96 */
+	writew((u32)DEFAULT_IPG,mmio+IPG);
+	writew((u32)(DEFAULT_IPG-IFS1_DELTA), mmio + IFS1);
+
+	if(lp->options & OPTION_JUMBO_ENABLE){
+		writel((u32)VAL2|JUMBO, mmio + CMD3);
+		/* Reset REX_UFLO */
+		writel( REX_UFLO, mmio + CMD2);
+		/* Should not set REX_UFLO for jumbo frames */
+		writel( VAL0 | APAD_XMT|REX_RTRY , mmio + CMD2);
+	}else{
+		writel( VAL0 | APAD_XMT | REX_RTRY|REX_UFLO, mmio + CMD2);
+		writel((u32)JUMBO, mmio + CMD3);
+	}
+
+#if AMD8111E_VLAN_TAG_USED
+	writel((u32) VAL2|VSIZE|VL_TAG_DEL, mmio + CMD3);
+#endif
+	writel( VAL0 | APAD_XMT | REX_RTRY, mmio + CMD2 );
+
+	/* Setting the MAC address to the device */
+	for(i = 0; i < ETH_ADDR_LEN; i++)
+		writeb( dev->dev_addr[i], mmio + PADR + i );
+
+	/* Enable interrupt coalesce */
+	if(lp->options & OPTION_INTR_COAL_ENABLE){
+		printk(KERN_INFO "%s: Interrupt Coalescing Enabled.\n",
+								dev->name);
+		amd8111e_set_coalesce(dev,ENABLE_COAL);
+	}
+
+	/* set RUN bit to start the chip */
+	writel(VAL2 | RDMD0, mmio + CMD0);
+	writel(VAL0 | INTREN | RUN, mmio + CMD0);
+
+	/* To avoid PCI posting bug */
+	readl(mmio+CMD0);
+	return 0;
+}
+/*
+This function clears necessary the device registers.
+*/
+static void amd8111e_init_hw_default( struct amd8111e_priv* lp)
+{
+	unsigned int reg_val;
+	unsigned int logic_filter[2] ={0,};
+	void __iomem *mmio = lp->mmio;
+
+
+        /* stop the chip */
+	writel(RUN, mmio + CMD0);
+
+	/* AUTOPOLL0 Register *//*TBD default value is 8100 in FPS */
+	writew( 0x8100 | lp->ext_phy_addr, mmio + AUTOPOLL0);
+
+	/* Clear RCV_RING_BASE_ADDR */
+	writel(0, mmio + RCV_RING_BASE_ADDR0);
+
+	/* Clear XMT_RING_BASE_ADDR */
+	writel(0, mmio + XMT_RING_BASE_ADDR0);
+	writel(0, mmio + XMT_RING_BASE_ADDR1);
+	writel(0, mmio + XMT_RING_BASE_ADDR2);
+	writel(0, mmio + XMT_RING_BASE_ADDR3);
+
+	/* Clear CMD0  */
+	writel(CMD0_CLEAR,mmio + CMD0);
+
+	/* Clear CMD2 */
+	writel(CMD2_CLEAR, mmio +CMD2);
+
+	/* Clear CMD7 */
+	writel(CMD7_CLEAR , mmio + CMD7);
+
+	/* Clear DLY_INT_A and DLY_INT_B */
+	writel(0x0, mmio + DLY_INT_A);
+	writel(0x0, mmio + DLY_INT_B);
+
+	/* Clear FLOW_CONTROL */
+	writel(0x0, mmio + FLOW_CONTROL);
+
+	/* Clear INT0  write 1 to clear register */
+	reg_val = readl(mmio + INT0);
+	writel(reg_val, mmio + INT0);
+
+	/* Clear STVAL */
+	writel(0x0, mmio + STVAL);
+
+	/* Clear INTEN0 */
+	writel( INTEN0_CLEAR, mmio + INTEN0);
+
+	/* Clear LADRF */
+	writel(0x0 , mmio + LADRF);
+
+	/* Set SRAM_SIZE & SRAM_BOUNDARY registers  */
+	writel( 0x80010,mmio + SRAM_SIZE);
+
+	/* Clear RCV_RING0_LEN */
+	writel(0x0, mmio +  RCV_RING_LEN0);
+
+	/* Clear XMT_RING0/1/2/3_LEN */
+	writel(0x0, mmio +  XMT_RING_LEN0);
+	writel(0x0, mmio +  XMT_RING_LEN1);
+	writel(0x0, mmio +  XMT_RING_LEN2);
+	writel(0x0, mmio +  XMT_RING_LEN3);
+
+	/* Clear XMT_RING_LIMIT */
+	writel(0x0, mmio + XMT_RING_LIMIT);
+
+	/* Clear MIB */
+	writew(MIB_CLEAR, mmio + MIB_ADDR);
+
+	/* Clear LARF */
+	amd8111e_writeq(*(u64*)logic_filter,mmio+LADRF);
+
+	/* SRAM_SIZE register */
+	reg_val = readl(mmio + SRAM_SIZE);
+
+	if(lp->options & OPTION_JUMBO_ENABLE)
+		writel( VAL2|JUMBO, mmio + CMD3);
+#if AMD8111E_VLAN_TAG_USED
+	writel(VAL2|VSIZE|VL_TAG_DEL, mmio + CMD3 );
+#endif
+	/* Set default value to CTRL1 Register */
+	writel(CTRL1_DEFAULT, mmio + CTRL1);
+
+	/* To avoid PCI posting bug */
+	readl(mmio + CMD2);
+
+}
+
+/*
+This function disables the interrupt and clears all the pending
+interrupts in INT0
+ */
+static void amd8111e_disable_interrupt(struct amd8111e_priv* lp)
+{
+	u32 intr0;
+
+	/* Disable interrupt */
+	writel(INTREN, lp->mmio + CMD0);
+
+	/* Clear INT0 */
+	intr0 = readl(lp->mmio + INT0);
+	writel(intr0, lp->mmio + INT0);
+
+	/* To avoid PCI posting bug */
+	readl(lp->mmio + INT0);
+
+}
+
+/*
+This function stops the chip.
+*/
+static void amd8111e_stop_chip(struct amd8111e_priv* lp)
+{
+	writel(RUN, lp->mmio + CMD0);
+
+	/* To avoid PCI posting bug */
+	readl(lp->mmio + CMD0);
+}
+
+/*
+This function frees the  transmiter and receiver descriptor rings.
+*/
+static void amd8111e_free_ring(struct amd8111e_priv* lp)
+{
+	/* Free transmit and receive descriptor rings */
+	if(lp->rx_ring){
+		pci_free_consistent(lp->pci_dev,
+			sizeof(struct amd8111e_rx_dr)*NUM_RX_RING_DR,
+			lp->rx_ring, lp->rx_ring_dma_addr);
+		lp->rx_ring = NULL;
+	}
+
+	if(lp->tx_ring){
+		pci_free_consistent(lp->pci_dev,
+			sizeof(struct amd8111e_tx_dr)*NUM_TX_RING_DR,
+			lp->tx_ring, lp->tx_ring_dma_addr);
+
+		lp->tx_ring = NULL;
+	}
+
+}
+
+/*
+This function will free all the transmit skbs that are actually transmitted by the device. It will check the ownership of the skb before freeing the skb.
+*/
+static int amd8111e_tx(struct net_device *dev)
+{
+	struct amd8111e_priv* lp = netdev_priv(dev);
+	int tx_index = lp->tx_complete_idx & TX_RING_DR_MOD_MASK;
+	int status;
+	/* Complete all the transmit packet */
+	while (lp->tx_complete_idx != lp->tx_idx){
+		tx_index =  lp->tx_complete_idx & TX_RING_DR_MOD_MASK;
+		status = le16_to_cpu(lp->tx_ring[tx_index].tx_flags);
+
+		if(status & OWN_BIT)
+			break;	/* It still hasn't been Txed */
+
+		lp->tx_ring[tx_index].buff_phy_addr = 0;
+
+		/* We must free the original skb */
+		if (lp->tx_skbuff[tx_index]) {
+			pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[tx_index],
+				  	lp->tx_skbuff[tx_index]->len,
+					PCI_DMA_TODEVICE);
+			dev_kfree_skb_irq (lp->tx_skbuff[tx_index]);
+			lp->tx_skbuff[tx_index] = NULL;
+			lp->tx_dma_addr[tx_index] = 0;
+		}
+		lp->tx_complete_idx++;
+		/*COAL update tx coalescing parameters */
+		lp->coal_conf.tx_packets++;
+		lp->coal_conf.tx_bytes +=
+			le16_to_cpu(lp->tx_ring[tx_index].buff_count);
+
+		if (netif_queue_stopped(dev) &&
+			lp->tx_complete_idx > lp->tx_idx - NUM_TX_BUFFERS +2){
+			/* The ring is no longer full, clear tbusy. */
+			/* lp->tx_full = 0; */
+			netif_wake_queue (dev);
+		}
+	}
+	return 0;
+}
+
+/* This function handles the driver receive operation in polling mode */
+static int amd8111e_rx_poll(struct napi_struct *napi, int budget)
+{
+	struct amd8111e_priv *lp = container_of(napi, struct amd8111e_priv, napi);
+	struct net_device *dev = lp->amd8111e_net_dev;
+	int rx_index = lp->rx_idx & RX_RING_DR_MOD_MASK;
+	void __iomem *mmio = lp->mmio;
+	struct sk_buff *skb,*new_skb;
+	int min_pkt_len, status;
+	unsigned int intr0;
+	int num_rx_pkt = 0;
+	short pkt_len;
+#if AMD8111E_VLAN_TAG_USED
+	short vtag;
+#endif
+	int rx_pkt_limit = budget;
+	unsigned long flags;
+
+	do{
+		/* process receive packets until we use the quota*/
+		/* If we own the next entry, it's a new packet. Send it up. */
+		while(1) {
+			status = le16_to_cpu(lp->rx_ring[rx_index].rx_flags);
+			if (status & OWN_BIT)
+				break;
+
+			/*
+			 * There is a tricky error noted by John Murphy,
+			 * <murf@perftech.com> to Russ Nelson: Even with
+			 * full-sized * buffers it's possible for a
+			 * jabber packet to use two buffers, with only
+			 * the last correctly noting the error.
+			 */
+
+			if(status & ERR_BIT) {
+				/* reseting flags */
+				lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
+				goto err_next_pkt;
+			}
+			/* check for STP and ENP */
+			if(!((status & STP_BIT) && (status & ENP_BIT))){
+				/* reseting flags */
+				lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
+				goto err_next_pkt;
+			}
+			pkt_len = le16_to_cpu(lp->rx_ring[rx_index].msg_count) - 4;
+
+#if AMD8111E_VLAN_TAG_USED
+			vtag = status & TT_MASK;
+			/*MAC will strip vlan tag*/
+			if (vtag != 0)
+				min_pkt_len =MIN_PKT_LEN - 4;
+			else
+#endif
+				min_pkt_len =MIN_PKT_LEN;
+
+			if (pkt_len < min_pkt_len) {
+				lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
+				lp->drv_rx_errors++;
+				goto err_next_pkt;
+			}
+			if(--rx_pkt_limit < 0)
+				goto rx_not_empty;
+			if(!(new_skb = dev_alloc_skb(lp->rx_buff_len))){
+				/* if allocation fail,
+				   ignore that pkt and go to next one */
+				lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
+				lp->drv_rx_errors++;
+				goto err_next_pkt;
+			}
+
+			skb_reserve(new_skb, 2);
+			skb = lp->rx_skbuff[rx_index];
+			pci_unmap_single(lp->pci_dev,lp->rx_dma_addr[rx_index],
+					 lp->rx_buff_len-2, PCI_DMA_FROMDEVICE);
+			skb_put(skb, pkt_len);
+			lp->rx_skbuff[rx_index] = new_skb;
+			lp->rx_dma_addr[rx_index] = pci_map_single(lp->pci_dev,
+								   new_skb->data,
+								   lp->rx_buff_len-2,
+								   PCI_DMA_FROMDEVICE);
+
+			skb->protocol = eth_type_trans(skb, dev);
+
+#if AMD8111E_VLAN_TAG_USED
+			if (vtag == TT_VLAN_TAGGED){
+				u16 vlan_tag = le16_to_cpu(lp->rx_ring[rx_index].tag_ctrl_info);
+				__vlan_hwaccel_put_tag(skb, vlan_tag);
+			}
+#endif
+			netif_receive_skb(skb);
+			/*COAL update rx coalescing parameters*/
+			lp->coal_conf.rx_packets++;
+			lp->coal_conf.rx_bytes += pkt_len;
+			num_rx_pkt++;
+
+		err_next_pkt:
+			lp->rx_ring[rx_index].buff_phy_addr
+				= cpu_to_le32(lp->rx_dma_addr[rx_index]);
+			lp->rx_ring[rx_index].buff_count =
+				cpu_to_le16(lp->rx_buff_len-2);
+			wmb();
+			lp->rx_ring[rx_index].rx_flags |= cpu_to_le16(OWN_BIT);
+			rx_index = (++lp->rx_idx) & RX_RING_DR_MOD_MASK;
+		}
+		/* Check the interrupt status register for more packets in the
+		   mean time. Process them since we have not used up our quota.*/
+
+		intr0 = readl(mmio + INT0);
+		/*Ack receive packets */
+		writel(intr0 & RINT0,mmio + INT0);
+
+	} while(intr0 & RINT0);
+
+	if (rx_pkt_limit > 0) {
+		/* Receive descriptor is empty now */
+		spin_lock_irqsave(&lp->lock, flags);
+		__napi_complete(napi);
+		writel(VAL0|RINTEN0, mmio + INTEN0);
+		writel(VAL2 | RDMD0, mmio + CMD0);
+		spin_unlock_irqrestore(&lp->lock, flags);
+	}
+
+rx_not_empty:
+	return num_rx_pkt;
+}
+
+/*
+This function will indicate the link status to the kernel.
+*/
+static int amd8111e_link_change(struct net_device* dev)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	int status0,speed;
+
+	/* read the link change */
+     	status0 = readl(lp->mmio + STAT0);
+
+	if(status0 & LINK_STATS){
+		if(status0 & AUTONEG_COMPLETE)
+			lp->link_config.autoneg = AUTONEG_ENABLE;
+		else
+			lp->link_config.autoneg = AUTONEG_DISABLE;
+
+		if(status0 & FULL_DPLX)
+			lp->link_config.duplex = DUPLEX_FULL;
+		else
+			lp->link_config.duplex = DUPLEX_HALF;
+		speed = (status0 & SPEED_MASK) >> 7;
+		if(speed == PHY_SPEED_10)
+			lp->link_config.speed = SPEED_10;
+		else if(speed == PHY_SPEED_100)
+			lp->link_config.speed = SPEED_100;
+
+		printk(KERN_INFO "%s: Link is Up. Speed is %s Mbps %s Duplex\n",			dev->name,
+		       (lp->link_config.speed == SPEED_100) ? "100": "10",
+		       (lp->link_config.duplex == DUPLEX_FULL)? "Full": "Half");
+		netif_carrier_on(dev);
+	}
+	else{
+		lp->link_config.speed = SPEED_INVALID;
+		lp->link_config.duplex = DUPLEX_INVALID;
+		lp->link_config.autoneg = AUTONEG_INVALID;
+		printk(KERN_INFO "%s: Link is Down.\n",dev->name);
+		netif_carrier_off(dev);
+	}
+
+	return 0;
+}
+/*
+This function reads the mib counters.
+*/
+static int amd8111e_read_mib(void __iomem *mmio, u8 MIB_COUNTER)
+{
+	unsigned int  status;
+	unsigned  int data;
+	unsigned int repeat = REPEAT_CNT;
+
+	writew( MIB_RD_CMD | MIB_COUNTER, mmio + MIB_ADDR);
+	do {
+		status = readw(mmio + MIB_ADDR);
+		udelay(2);	/* controller takes MAX 2 us to get mib data */
+	}
+	while (--repeat && (status & MIB_CMD_ACTIVE));
+
+	data = readl(mmio + MIB_DATA);
+	return data;
+}
+
+/*
+ * This function reads the mib registers and returns the hardware statistics.
+ * It updates previous internal driver statistics with new values.
+ */
+static struct net_device_stats *amd8111e_get_stats(struct net_device *dev)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	void __iomem *mmio = lp->mmio;
+	unsigned long flags;
+	struct net_device_stats *new_stats = &dev->stats;
+
+	if (!lp->opened)
+		return new_stats;
+	spin_lock_irqsave (&lp->lock, flags);
+
+	/* stats.rx_packets */
+	new_stats->rx_packets = amd8111e_read_mib(mmio, rcv_broadcast_pkts)+
+				amd8111e_read_mib(mmio, rcv_multicast_pkts)+
+				amd8111e_read_mib(mmio, rcv_unicast_pkts);
+
+	/* stats.tx_packets */
+	new_stats->tx_packets = amd8111e_read_mib(mmio, xmt_packets);
+
+	/*stats.rx_bytes */
+	new_stats->rx_bytes = amd8111e_read_mib(mmio, rcv_octets);
+
+	/* stats.tx_bytes */
+	new_stats->tx_bytes = amd8111e_read_mib(mmio, xmt_octets);
+
+	/* stats.rx_errors */
+	/* hw errors + errors driver reported */
+	new_stats->rx_errors = amd8111e_read_mib(mmio, rcv_undersize_pkts)+
+				amd8111e_read_mib(mmio, rcv_fragments)+
+				amd8111e_read_mib(mmio, rcv_jabbers)+
+				amd8111e_read_mib(mmio, rcv_alignment_errors)+
+				amd8111e_read_mib(mmio, rcv_fcs_errors)+
+				amd8111e_read_mib(mmio, rcv_miss_pkts)+
+				lp->drv_rx_errors;
+
+	/* stats.tx_errors */
+	new_stats->tx_errors = amd8111e_read_mib(mmio, xmt_underrun_pkts);
+
+	/* stats.rx_dropped*/
+	new_stats->rx_dropped = amd8111e_read_mib(mmio, rcv_miss_pkts);
+
+	/* stats.tx_dropped*/
+	new_stats->tx_dropped = amd8111e_read_mib(mmio,  xmt_underrun_pkts);
+
+	/* stats.multicast*/
+	new_stats->multicast = amd8111e_read_mib(mmio, rcv_multicast_pkts);
+
+	/* stats.collisions*/
+	new_stats->collisions = amd8111e_read_mib(mmio, xmt_collisions);
+
+	/* stats.rx_length_errors*/
+	new_stats->rx_length_errors =
+		amd8111e_read_mib(mmio, rcv_undersize_pkts)+
+		amd8111e_read_mib(mmio, rcv_oversize_pkts);
+
+	/* stats.rx_over_errors*/
+	new_stats->rx_over_errors = amd8111e_read_mib(mmio, rcv_miss_pkts);
+
+	/* stats.rx_crc_errors*/
+	new_stats->rx_crc_errors = amd8111e_read_mib(mmio, rcv_fcs_errors);
+
+	/* stats.rx_frame_errors*/
+	new_stats->rx_frame_errors =
+		amd8111e_read_mib(mmio, rcv_alignment_errors);
+
+	/* stats.rx_fifo_errors */
+	new_stats->rx_fifo_errors = amd8111e_read_mib(mmio, rcv_miss_pkts);
+
+	/* stats.rx_missed_errors */
+	new_stats->rx_missed_errors = amd8111e_read_mib(mmio, rcv_miss_pkts);
+
+	/* stats.tx_aborted_errors*/
+	new_stats->tx_aborted_errors =
+		amd8111e_read_mib(mmio, xmt_excessive_collision);
+
+	/* stats.tx_carrier_errors*/
+	new_stats->tx_carrier_errors =
+		amd8111e_read_mib(mmio, xmt_loss_carrier);
+
+	/* stats.tx_fifo_errors*/
+	new_stats->tx_fifo_errors = amd8111e_read_mib(mmio, xmt_underrun_pkts);
+
+	/* stats.tx_window_errors*/
+	new_stats->tx_window_errors =
+		amd8111e_read_mib(mmio, xmt_late_collision);
+
+	/* Reset the mibs for collecting new statistics */
+	/* writew(MIB_CLEAR, mmio + MIB_ADDR);*/
+
+	spin_unlock_irqrestore (&lp->lock, flags);
+
+	return new_stats;
+}
+/* This function recalculate the interrupt coalescing  mode on every interrupt
+according to the datarate and the packet rate.
+*/
+static int amd8111e_calc_coalesce(struct net_device *dev)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	struct amd8111e_coalesce_conf * coal_conf = &lp->coal_conf;
+	int tx_pkt_rate;
+	int rx_pkt_rate;
+	int tx_data_rate;
+	int rx_data_rate;
+	int rx_pkt_size;
+	int tx_pkt_size;
+
+	tx_pkt_rate = coal_conf->tx_packets - coal_conf->tx_prev_packets;
+	coal_conf->tx_prev_packets =  coal_conf->tx_packets;
+
+	tx_data_rate = coal_conf->tx_bytes - coal_conf->tx_prev_bytes;
+	coal_conf->tx_prev_bytes =  coal_conf->tx_bytes;
+
+	rx_pkt_rate = coal_conf->rx_packets - coal_conf->rx_prev_packets;
+	coal_conf->rx_prev_packets =  coal_conf->rx_packets;
+
+	rx_data_rate = coal_conf->rx_bytes - coal_conf->rx_prev_bytes;
+	coal_conf->rx_prev_bytes =  coal_conf->rx_bytes;
+
+	if(rx_pkt_rate < 800){
+		if(coal_conf->rx_coal_type != NO_COALESCE){
+
+			coal_conf->rx_timeout = 0x0;
+			coal_conf->rx_event_count = 0;
+			amd8111e_set_coalesce(dev,RX_INTR_COAL);
+			coal_conf->rx_coal_type = NO_COALESCE;
+		}
+	}
+	else{
+
+		rx_pkt_size = rx_data_rate/rx_pkt_rate;
+		if (rx_pkt_size < 128){
+			if(coal_conf->rx_coal_type != NO_COALESCE){
+
+				coal_conf->rx_timeout = 0;
+				coal_conf->rx_event_count = 0;
+				amd8111e_set_coalesce(dev,RX_INTR_COAL);
+				coal_conf->rx_coal_type = NO_COALESCE;
+			}
+
+		}
+		else if ( (rx_pkt_size >= 128) && (rx_pkt_size < 512) ){
+
+			if(coal_conf->rx_coal_type !=  LOW_COALESCE){
+				coal_conf->rx_timeout = 1;
+				coal_conf->rx_event_count = 4;
+				amd8111e_set_coalesce(dev,RX_INTR_COAL);
+				coal_conf->rx_coal_type = LOW_COALESCE;
+			}
+		}
+		else if ((rx_pkt_size >= 512) && (rx_pkt_size < 1024)){
+
+			if(coal_conf->rx_coal_type !=  MEDIUM_COALESCE){
+				coal_conf->rx_timeout = 1;
+				coal_conf->rx_event_count = 4;
+				amd8111e_set_coalesce(dev,RX_INTR_COAL);
+				coal_conf->rx_coal_type = MEDIUM_COALESCE;
+			}
+
+		}
+		else if(rx_pkt_size >= 1024){
+			if(coal_conf->rx_coal_type !=  HIGH_COALESCE){
+				coal_conf->rx_timeout = 2;
+				coal_conf->rx_event_count = 3;
+				amd8111e_set_coalesce(dev,RX_INTR_COAL);
+				coal_conf->rx_coal_type = HIGH_COALESCE;
+			}
+		}
+	}
+    	/* NOW FOR TX INTR COALESC */
+	if(tx_pkt_rate < 800){
+		if(coal_conf->tx_coal_type != NO_COALESCE){
+
+			coal_conf->tx_timeout = 0x0;
+			coal_conf->tx_event_count = 0;
+			amd8111e_set_coalesce(dev,TX_INTR_COAL);
+			coal_conf->tx_coal_type = NO_COALESCE;
+		}
+	}
+	else{
+
+		tx_pkt_size = tx_data_rate/tx_pkt_rate;
+		if (tx_pkt_size < 128){
+
+			if(coal_conf->tx_coal_type != NO_COALESCE){
+
+				coal_conf->tx_timeout = 0;
+				coal_conf->tx_event_count = 0;
+				amd8111e_set_coalesce(dev,TX_INTR_COAL);
+				coal_conf->tx_coal_type = NO_COALESCE;
+			}
+
+		}
+		else if ( (tx_pkt_size >= 128) && (tx_pkt_size < 512) ){
+
+			if(coal_conf->tx_coal_type !=  LOW_COALESCE){
+				coal_conf->tx_timeout = 1;
+				coal_conf->tx_event_count = 2;
+				amd8111e_set_coalesce(dev,TX_INTR_COAL);
+				coal_conf->tx_coal_type = LOW_COALESCE;
+
+			}
+		}
+		else if ((tx_pkt_size >= 512) && (tx_pkt_size < 1024)){
+
+			if(coal_conf->tx_coal_type !=  MEDIUM_COALESCE){
+				coal_conf->tx_timeout = 2;
+				coal_conf->tx_event_count = 5;
+				amd8111e_set_coalesce(dev,TX_INTR_COAL);
+				coal_conf->tx_coal_type = MEDIUM_COALESCE;
+			}
+
+		}
+		else if(tx_pkt_size >= 1024){
+			if (tx_pkt_size >= 1024){
+				if(coal_conf->tx_coal_type !=  HIGH_COALESCE){
+					coal_conf->tx_timeout = 4;
+					coal_conf->tx_event_count = 8;
+					amd8111e_set_coalesce(dev,TX_INTR_COAL);
+					coal_conf->tx_coal_type = HIGH_COALESCE;
+				}
+			}
+		}
+	}
+	return 0;
+
+}
+/*
+This is device interrupt function. It handles transmit, receive,link change and hardware timer interrupts.
+*/
+static irqreturn_t amd8111e_interrupt(int irq, void *dev_id)
+{
+
+	struct net_device * dev = (struct net_device *) dev_id;
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	void __iomem *mmio = lp->mmio;
+	unsigned int intr0, intren0;
+	unsigned int handled = 1;
+
+	if(unlikely(dev == NULL))
+		return IRQ_NONE;
+
+	spin_lock(&lp->lock);
+
+	/* disabling interrupt */
+	writel(INTREN, mmio + CMD0);
+
+	/* Read interrupt status */
+	intr0 = readl(mmio + INT0);
+	intren0 = readl(mmio + INTEN0);
+
+	/* Process all the INT event until INTR bit is clear. */
+
+	if (!(intr0 & INTR)){
+		handled = 0;
+		goto err_no_interrupt;
+	}
+
+	/* Current driver processes 4 interrupts : RINT,TINT,LCINT,STINT */
+	writel(intr0, mmio + INT0);
+
+	/* Check if Receive Interrupt has occurred. */
+	if (intr0 & RINT0) {
+		if (napi_schedule_prep(&lp->napi)) {
+			/* Disable receive interupts */
+			writel(RINTEN0, mmio + INTEN0);
+			/* Schedule a polling routine */
+			__napi_schedule(&lp->napi);
+		} else if (intren0 & RINTEN0) {
+			printk("************Driver bug! interrupt while in poll\n");
+			/* Fix by disable receive interrupts */
+			writel(RINTEN0, mmio + INTEN0);
+		}
+	}
+
+	/* Check if  Transmit Interrupt has occurred. */
+	if (intr0 & TINT0)
+		amd8111e_tx(dev);
+
+	/* Check if  Link Change Interrupt has occurred. */
+	if (intr0 & LCINT)
+		amd8111e_link_change(dev);
+
+	/* Check if Hardware Timer Interrupt has occurred. */
+	if (intr0 & STINT)
+		amd8111e_calc_coalesce(dev);
+
+err_no_interrupt:
+	writel( VAL0 | INTREN,mmio + CMD0);
+
+	spin_unlock(&lp->lock);
+
+	return IRQ_RETVAL(handled);
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void amd8111e_poll(struct net_device *dev)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+	amd8111e_interrupt(0, dev);
+	local_irq_restore(flags);
+}
+#endif
+
+
+/*
+This function closes the network interface and updates the statistics so that most recent statistics will be available after the interface is down.
+*/
+static int amd8111e_close(struct net_device * dev)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	netif_stop_queue(dev);
+
+	napi_disable(&lp->napi);
+
+	spin_lock_irq(&lp->lock);
+
+	amd8111e_disable_interrupt(lp);
+	amd8111e_stop_chip(lp);
+
+	/* Free transmit and receive skbs */
+	amd8111e_free_skbs(lp->amd8111e_net_dev);
+
+	netif_carrier_off(lp->amd8111e_net_dev);
+
+	/* Delete ipg timer */
+	if(lp->options & OPTION_DYN_IPG_ENABLE)
+		del_timer_sync(&lp->ipg_data.ipg_timer);
+
+	spin_unlock_irq(&lp->lock);
+	free_irq(dev->irq, dev);
+	amd8111e_free_ring(lp);
+
+	/* Update the statistics before closing */
+	amd8111e_get_stats(dev);
+	lp->opened = 0;
+	return 0;
+}
+/* This function opens new interface.It requests irq for the device, initializes the device,buffers and descriptors, and starts the device.
+*/
+static int amd8111e_open(struct net_device * dev )
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+
+	if(dev->irq ==0 || request_irq(dev->irq, amd8111e_interrupt, IRQF_SHARED,
+					 dev->name, dev))
+		return -EAGAIN;
+
+	napi_enable(&lp->napi);
+
+	spin_lock_irq(&lp->lock);
+
+	amd8111e_init_hw_default(lp);
+
+	if(amd8111e_restart(dev)){
+		spin_unlock_irq(&lp->lock);
+		napi_disable(&lp->napi);
+		if (dev->irq)
+			free_irq(dev->irq, dev);
+		return -ENOMEM;
+	}
+	/* Start ipg timer */
+	if(lp->options & OPTION_DYN_IPG_ENABLE){
+		add_timer(&lp->ipg_data.ipg_timer);
+		printk(KERN_INFO "%s: Dynamic IPG Enabled.\n",dev->name);
+	}
+
+	lp->opened = 1;
+
+	spin_unlock_irq(&lp->lock);
+
+	netif_start_queue(dev);
+
+	return 0;
+}
+/*
+This function checks if there is any transmit  descriptors available to queue more packet.
+*/
+static int amd8111e_tx_queue_avail(struct amd8111e_priv* lp )
+{
+	int tx_index = lp->tx_idx & TX_BUFF_MOD_MASK;
+	if (lp->tx_skbuff[tx_index])
+		return -1;
+	else
+		return 0;
+
+}
+/*
+This function will queue the transmit packets to the descriptors and will trigger the send operation. It also initializes the transmit descriptors with buffer physical address, byte count, ownership to hardware etc.
+*/
+
+static netdev_tx_t amd8111e_start_xmit(struct sk_buff *skb,
+				       struct net_device * dev)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	int tx_index;
+	unsigned long flags;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	tx_index = lp->tx_idx & TX_RING_DR_MOD_MASK;
+
+	lp->tx_ring[tx_index].buff_count = cpu_to_le16(skb->len);
+
+	lp->tx_skbuff[tx_index] = skb;
+	lp->tx_ring[tx_index].tx_flags = 0;
+
+#if AMD8111E_VLAN_TAG_USED
+	if (vlan_tx_tag_present(skb)) {
+		lp->tx_ring[tx_index].tag_ctrl_cmd |=
+				cpu_to_le16(TCC_VLAN_INSERT);
+		lp->tx_ring[tx_index].tag_ctrl_info =
+				cpu_to_le16(vlan_tx_tag_get(skb));
+
+	}
+#endif
+	lp->tx_dma_addr[tx_index] =
+	    pci_map_single(lp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
+	lp->tx_ring[tx_index].buff_phy_addr =
+	    cpu_to_le32(lp->tx_dma_addr[tx_index]);
+
+	/*  Set FCS and LTINT bits */
+	wmb();
+	lp->tx_ring[tx_index].tx_flags |=
+	    cpu_to_le16(OWN_BIT | STP_BIT | ENP_BIT|ADD_FCS_BIT|LTINT_BIT);
+
+	lp->tx_idx++;
+
+	/* Trigger an immediate send poll. */
+	writel( VAL1 | TDMD0, lp->mmio + CMD0);
+	writel( VAL2 | RDMD0,lp->mmio + CMD0);
+
+	if(amd8111e_tx_queue_avail(lp) < 0){
+		netif_stop_queue(dev);
+	}
+	spin_unlock_irqrestore(&lp->lock, flags);
+	return NETDEV_TX_OK;
+}
+/*
+This function returns all the memory mapped registers of the device.
+*/
+static void amd8111e_read_regs(struct amd8111e_priv *lp, u32 *buf)
+{
+	void __iomem *mmio = lp->mmio;
+	/* Read only necessary registers */
+	buf[0] = readl(mmio + XMT_RING_BASE_ADDR0);
+	buf[1] = readl(mmio + XMT_RING_LEN0);
+	buf[2] = readl(mmio + RCV_RING_BASE_ADDR0);
+	buf[3] = readl(mmio + RCV_RING_LEN0);
+	buf[4] = readl(mmio + CMD0);
+	buf[5] = readl(mmio + CMD2);
+	buf[6] = readl(mmio + CMD3);
+	buf[7] = readl(mmio + CMD7);
+	buf[8] = readl(mmio + INT0);
+	buf[9] = readl(mmio + INTEN0);
+	buf[10] = readl(mmio + LADRF);
+	buf[11] = readl(mmio + LADRF+4);
+	buf[12] = readl(mmio + STAT0);
+}
+
+
+/*
+This function sets promiscuos mode, all-multi mode or the multicast address
+list to the device.
+*/
+static void amd8111e_set_multicast_list(struct net_device *dev)
+{
+	struct netdev_hw_addr *ha;
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	u32 mc_filter[2] ;
+	int bit_num;
+
+	if(dev->flags & IFF_PROMISC){
+		writel( VAL2 | PROM, lp->mmio + CMD2);
+		return;
+	}
+	else
+		writel( PROM, lp->mmio + CMD2);
+	if (dev->flags & IFF_ALLMULTI ||
+	    netdev_mc_count(dev) > MAX_FILTER_SIZE) {
+		/* get all multicast packet */
+		mc_filter[1] = mc_filter[0] = 0xffffffff;
+		lp->options |= OPTION_MULTICAST_ENABLE;
+		amd8111e_writeq(*(u64*)mc_filter,lp->mmio + LADRF);
+		return;
+	}
+	if (netdev_mc_empty(dev)) {
+		/* get only own packets */
+		mc_filter[1] = mc_filter[0] = 0;
+		lp->options &= ~OPTION_MULTICAST_ENABLE;
+		amd8111e_writeq(*(u64*)mc_filter,lp->mmio + LADRF);
+		/* disable promiscuous mode */
+		writel(PROM, lp->mmio + CMD2);
+		return;
+	}
+	/* load all the multicast addresses in the logic filter */
+	lp->options |= OPTION_MULTICAST_ENABLE;
+	mc_filter[1] = mc_filter[0] = 0;
+	netdev_for_each_mc_addr(ha, dev) {
+		bit_num = (ether_crc_le(ETH_ALEN, ha->addr) >> 26) & 0x3f;
+		mc_filter[bit_num >> 5] |= 1 << (bit_num & 31);
+	}
+	amd8111e_writeq(*(u64*)mc_filter,lp->mmio+ LADRF);
+
+	/* To eliminate PCI posting bug */
+	readl(lp->mmio + CMD2);
+
+}
+
+static void amd8111e_get_drvinfo(struct net_device* dev, struct ethtool_drvinfo *info)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	struct pci_dev *pci_dev = lp->pci_dev;
+	strcpy (info->driver, MODULE_NAME);
+	strcpy (info->version, MODULE_VERS);
+	sprintf(info->fw_version,"%u",chip_version);
+	strcpy (info->bus_info, pci_name(pci_dev));
+}
+
+static int amd8111e_get_regs_len(struct net_device *dev)
+{
+	return AMD8111E_REG_DUMP_LEN;
+}
+
+static void amd8111e_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	regs->version = 0;
+	amd8111e_read_regs(lp, buf);
+}
+
+static int amd8111e_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	spin_lock_irq(&lp->lock);
+	mii_ethtool_gset(&lp->mii_if, ecmd);
+	spin_unlock_irq(&lp->lock);
+	return 0;
+}
+
+static int amd8111e_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	int res;
+	spin_lock_irq(&lp->lock);
+	res = mii_ethtool_sset(&lp->mii_if, ecmd);
+	spin_unlock_irq(&lp->lock);
+	return res;
+}
+
+static int amd8111e_nway_reset(struct net_device *dev)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	return mii_nway_restart(&lp->mii_if);
+}
+
+static u32 amd8111e_get_link(struct net_device *dev)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	return mii_link_ok(&lp->mii_if);
+}
+
+static void amd8111e_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol_info)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	wol_info->supported = WAKE_MAGIC|WAKE_PHY;
+	if (lp->options & OPTION_WOL_ENABLE)
+		wol_info->wolopts = WAKE_MAGIC;
+}
+
+static int amd8111e_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol_info)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	if (wol_info->wolopts & ~(WAKE_MAGIC|WAKE_PHY))
+		return -EINVAL;
+	spin_lock_irq(&lp->lock);
+	if (wol_info->wolopts & WAKE_MAGIC)
+		lp->options |=
+			(OPTION_WOL_ENABLE | OPTION_WAKE_MAGIC_ENABLE);
+	else if(wol_info->wolopts & WAKE_PHY)
+		lp->options |=
+			(OPTION_WOL_ENABLE | OPTION_WAKE_PHY_ENABLE);
+	else
+		lp->options &= ~OPTION_WOL_ENABLE;
+	spin_unlock_irq(&lp->lock);
+	return 0;
+}
+
+static const struct ethtool_ops ops = {
+	.get_drvinfo = amd8111e_get_drvinfo,
+	.get_regs_len = amd8111e_get_regs_len,
+	.get_regs = amd8111e_get_regs,
+	.get_settings = amd8111e_get_settings,
+	.set_settings = amd8111e_set_settings,
+	.nway_reset = amd8111e_nway_reset,
+	.get_link = amd8111e_get_link,
+	.get_wol = amd8111e_get_wol,
+	.set_wol = amd8111e_set_wol,
+};
+
+/*
+This function handles all the  ethtool ioctls. It gives driver info, gets/sets driver speed, gets memory mapped register values, forces auto negotiation, sets/gets WOL options for ethtool application.
+*/
+
+static int amd8111e_ioctl(struct net_device * dev , struct ifreq *ifr, int cmd)
+{
+	struct mii_ioctl_data *data = if_mii(ifr);
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	int err;
+	u32 mii_regval;
+
+	switch(cmd) {
+	case SIOCGMIIPHY:
+		data->phy_id = lp->ext_phy_addr;
+
+	/* fallthru */
+	case SIOCGMIIREG:
+
+		spin_lock_irq(&lp->lock);
+		err = amd8111e_read_phy(lp, data->phy_id,
+			data->reg_num & PHY_REG_ADDR_MASK, &mii_regval);
+		spin_unlock_irq(&lp->lock);
+
+		data->val_out = mii_regval;
+		return err;
+
+	case SIOCSMIIREG:
+
+		spin_lock_irq(&lp->lock);
+		err = amd8111e_write_phy(lp, data->phy_id,
+			data->reg_num & PHY_REG_ADDR_MASK, data->val_in);
+		spin_unlock_irq(&lp->lock);
+
+		return err;
+
+	default:
+		/* do nothing */
+		break;
+	}
+	return -EOPNOTSUPP;
+}
+static int amd8111e_set_mac_address(struct net_device *dev, void *p)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	int i;
+	struct sockaddr *addr = p;
+
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+	spin_lock_irq(&lp->lock);
+	/* Setting the MAC address to the device */
+	for(i = 0; i < ETH_ADDR_LEN; i++)
+		writeb( dev->dev_addr[i], lp->mmio + PADR + i );
+
+	spin_unlock_irq(&lp->lock);
+
+	return 0;
+}
+
+/*
+This function changes the mtu of the device. It restarts the device  to initialize the descriptor with new receive buffers.
+*/
+static int amd8111e_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	int err;
+
+	if ((new_mtu < AMD8111E_MIN_MTU) || (new_mtu > AMD8111E_MAX_MTU))
+		return -EINVAL;
+
+	if (!netif_running(dev)) {
+		/* new_mtu will be used
+		   when device starts netxt time */
+		dev->mtu = new_mtu;
+		return 0;
+	}
+
+	spin_lock_irq(&lp->lock);
+
+        /* stop the chip */
+	writel(RUN, lp->mmio + CMD0);
+
+	dev->mtu = new_mtu;
+
+	err = amd8111e_restart(dev);
+	spin_unlock_irq(&lp->lock);
+	if(!err)
+		netif_start_queue(dev);
+	return err;
+}
+
+static int amd8111e_enable_magicpkt(struct amd8111e_priv* lp)
+{
+	writel( VAL1|MPPLBA, lp->mmio + CMD3);
+	writel( VAL0|MPEN_SW, lp->mmio + CMD7);
+
+	/* To eliminate PCI posting bug */
+	readl(lp->mmio + CMD7);
+	return 0;
+}
+
+static int amd8111e_enable_link_change(struct amd8111e_priv* lp)
+{
+
+	/* Adapter is already stoped/suspended/interrupt-disabled */
+	writel(VAL0|LCMODE_SW,lp->mmio + CMD7);
+
+	/* To eliminate PCI posting bug */
+	readl(lp->mmio + CMD7);
+	return 0;
+}
+
+/*
+ * This function is called when a packet transmission fails to complete
+ * within a reasonable period, on the assumption that an interrupt have
+ * failed or the interface is locked up. This function will reinitialize
+ * the hardware.
+ */
+static void amd8111e_tx_timeout(struct net_device *dev)
+{
+	struct amd8111e_priv* lp = netdev_priv(dev);
+	int err;
+
+	printk(KERN_ERR "%s: transmit timed out, resetting\n",
+	 					      dev->name);
+	spin_lock_irq(&lp->lock);
+	err = amd8111e_restart(dev);
+	spin_unlock_irq(&lp->lock);
+	if(!err)
+		netif_wake_queue(dev);
+}
+static int amd8111e_suspend(struct pci_dev *pci_dev, pm_message_t state)
+{
+	struct net_device *dev = pci_get_drvdata(pci_dev);
+	struct amd8111e_priv *lp = netdev_priv(dev);
+
+	if (!netif_running(dev))
+		return 0;
+
+	/* disable the interrupt */
+	spin_lock_irq(&lp->lock);
+	amd8111e_disable_interrupt(lp);
+	spin_unlock_irq(&lp->lock);
+
+	netif_device_detach(dev);
+
+	/* stop chip */
+	spin_lock_irq(&lp->lock);
+	if(lp->options & OPTION_DYN_IPG_ENABLE)
+		del_timer_sync(&lp->ipg_data.ipg_timer);
+	amd8111e_stop_chip(lp);
+	spin_unlock_irq(&lp->lock);
+
+	if(lp->options & OPTION_WOL_ENABLE){
+		 /* enable wol */
+		if(lp->options & OPTION_WAKE_MAGIC_ENABLE)
+			amd8111e_enable_magicpkt(lp);
+		if(lp->options & OPTION_WAKE_PHY_ENABLE)
+			amd8111e_enable_link_change(lp);
+
+		pci_enable_wake(pci_dev, PCI_D3hot, 1);
+		pci_enable_wake(pci_dev, PCI_D3cold, 1);
+
+	}
+	else{
+		pci_enable_wake(pci_dev, PCI_D3hot, 0);
+		pci_enable_wake(pci_dev, PCI_D3cold, 0);
+	}
+
+	pci_save_state(pci_dev);
+	pci_set_power_state(pci_dev, PCI_D3hot);
+
+	return 0;
+}
+static int amd8111e_resume(struct pci_dev *pci_dev)
+{
+	struct net_device *dev = pci_get_drvdata(pci_dev);
+	struct amd8111e_priv *lp = netdev_priv(dev);
+
+	if (!netif_running(dev))
+		return 0;
+
+	pci_set_power_state(pci_dev, PCI_D0);
+	pci_restore_state(pci_dev);
+
+	pci_enable_wake(pci_dev, PCI_D3hot, 0);
+	pci_enable_wake(pci_dev, PCI_D3cold, 0); /* D3 cold */
+
+	netif_device_attach(dev);
+
+	spin_lock_irq(&lp->lock);
+	amd8111e_restart(dev);
+	/* Restart ipg timer */
+	if(lp->options & OPTION_DYN_IPG_ENABLE)
+		mod_timer(&lp->ipg_data.ipg_timer,
+				jiffies + IPG_CONVERGE_JIFFIES);
+	spin_unlock_irq(&lp->lock);
+
+	return 0;
+}
+
+
+static void __devexit amd8111e_remove_one(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	if (dev) {
+		unregister_netdev(dev);
+		iounmap(((struct amd8111e_priv *)netdev_priv(dev))->mmio);
+		free_netdev(dev);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		pci_set_drvdata(pdev, NULL);
+	}
+}
+static void amd8111e_config_ipg(struct net_device* dev)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	struct ipg_info* ipg_data = &lp->ipg_data;
+	void __iomem *mmio = lp->mmio;
+	unsigned int prev_col_cnt = ipg_data->col_cnt;
+	unsigned int total_col_cnt;
+	unsigned int tmp_ipg;
+
+	if(lp->link_config.duplex == DUPLEX_FULL){
+		ipg_data->ipg = DEFAULT_IPG;
+		return;
+	}
+
+	if(ipg_data->ipg_state == SSTATE){
+
+		if(ipg_data->timer_tick == IPG_STABLE_TIME){
+
+			ipg_data->timer_tick = 0;
+			ipg_data->ipg = MIN_IPG - IPG_STEP;
+			ipg_data->current_ipg = MIN_IPG;
+			ipg_data->diff_col_cnt = 0xFFFFFFFF;
+			ipg_data->ipg_state = CSTATE;
+		}
+		else
+			ipg_data->timer_tick++;
+	}
+
+	if(ipg_data->ipg_state == CSTATE){
+
+		/* Get the current collision count */
+
+		total_col_cnt = ipg_data->col_cnt =
+				amd8111e_read_mib(mmio, xmt_collisions);
+
+		if ((total_col_cnt - prev_col_cnt) <
+				(ipg_data->diff_col_cnt)){
+
+			ipg_data->diff_col_cnt =
+				total_col_cnt - prev_col_cnt ;
+
+			ipg_data->ipg = ipg_data->current_ipg;
+		}
+
+		ipg_data->current_ipg += IPG_STEP;
+
+		if (ipg_data->current_ipg <= MAX_IPG)
+			tmp_ipg = ipg_data->current_ipg;
+		else{
+			tmp_ipg = ipg_data->ipg;
+			ipg_data->ipg_state = SSTATE;
+		}
+		writew((u32)tmp_ipg, mmio + IPG);
+		writew((u32)(tmp_ipg - IFS1_DELTA), mmio + IFS1);
+	}
+	 mod_timer(&lp->ipg_data.ipg_timer, jiffies + IPG_CONVERGE_JIFFIES);
+	return;
+
+}
+
+static void __devinit amd8111e_probe_ext_phy(struct net_device* dev)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	int i;
+
+	for (i = 0x1e; i >= 0; i--) {
+		u32 id1, id2;
+
+		if (amd8111e_read_phy(lp, i, MII_PHYSID1, &id1))
+			continue;
+		if (amd8111e_read_phy(lp, i, MII_PHYSID2, &id2))
+			continue;
+		lp->ext_phy_id = (id1 << 16) | id2;
+		lp->ext_phy_addr = i;
+		return;
+	}
+	lp->ext_phy_id = 0;
+	lp->ext_phy_addr = 1;
+}
+
+static const struct net_device_ops amd8111e_netdev_ops = {
+	.ndo_open		= amd8111e_open,
+	.ndo_stop		= amd8111e_close,
+	.ndo_start_xmit		= amd8111e_start_xmit,
+	.ndo_tx_timeout		= amd8111e_tx_timeout,
+	.ndo_get_stats		= amd8111e_get_stats,
+	.ndo_set_rx_mode	= amd8111e_set_multicast_list,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= amd8111e_set_mac_address,
+	.ndo_do_ioctl		= amd8111e_ioctl,
+	.ndo_change_mtu		= amd8111e_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	 = amd8111e_poll,
+#endif
+};
+
+static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
+				  const struct pci_device_id *ent)
+{
+	int err,i,pm_cap;
+	unsigned long reg_addr,reg_len;
+	struct amd8111e_priv* lp;
+	struct net_device* dev;
+
+	err = pci_enable_device(pdev);
+	if(err){
+		printk(KERN_ERR "amd8111e: Cannot enable new PCI device, "
+			"exiting.\n");
+		return err;
+	}
+
+	if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)){
+		printk(KERN_ERR "amd8111e: Cannot find PCI base address, "
+		       "exiting.\n");
+		err = -ENODEV;
+		goto err_disable_pdev;
+	}
+
+	err = pci_request_regions(pdev, MODULE_NAME);
+	if(err){
+		printk(KERN_ERR "amd8111e: Cannot obtain PCI resources, "
+		       "exiting.\n");
+		goto err_disable_pdev;
+	}
+
+	pci_set_master(pdev);
+
+	/* Find power-management capability. */
+	if((pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM))==0){
+		printk(KERN_ERR "amd8111e: No Power Management capability, "
+		       "exiting.\n");
+		goto err_free_reg;
+	}
+
+	/* Initialize DMA */
+	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) < 0) {
+		printk(KERN_ERR "amd8111e: DMA not supported,"
+			"exiting.\n");
+		goto err_free_reg;
+	}
+
+	reg_addr = pci_resource_start(pdev, 0);
+	reg_len = pci_resource_len(pdev, 0);
+
+	dev = alloc_etherdev(sizeof(struct amd8111e_priv));
+	if (!dev) {
+		printk(KERN_ERR "amd8111e: Etherdev alloc failed, exiting.\n");
+		err = -ENOMEM;
+		goto err_free_reg;
+	}
+
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+#if AMD8111E_VLAN_TAG_USED
+	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX ;
+#endif
+
+	lp = netdev_priv(dev);
+	lp->pci_dev = pdev;
+	lp->amd8111e_net_dev = dev;
+	lp->pm_cap = pm_cap;
+
+	spin_lock_init(&lp->lock);
+
+	lp->mmio = ioremap(reg_addr, reg_len);
+	if (!lp->mmio) {
+		printk(KERN_ERR "amd8111e: Cannot map device registers, "
+		       "exiting\n");
+		err = -ENOMEM;
+		goto err_free_dev;
+	}
+
+	/* Initializing MAC address */
+	for(i = 0; i < ETH_ADDR_LEN; i++)
+		dev->dev_addr[i] = readb(lp->mmio + PADR + i);
+
+	/* Setting user defined parametrs */
+	lp->ext_phy_option = speed_duplex[card_idx];
+	if(coalesce[card_idx])
+		lp->options |= OPTION_INTR_COAL_ENABLE;
+	if(dynamic_ipg[card_idx++])
+		lp->options |= OPTION_DYN_IPG_ENABLE;
+
+
+	/* Initialize driver entry points */
+	dev->netdev_ops = &amd8111e_netdev_ops;
+	SET_ETHTOOL_OPS(dev, &ops);
+	dev->irq =pdev->irq;
+	dev->watchdog_timeo = AMD8111E_TX_TIMEOUT;
+	netif_napi_add(dev, &lp->napi, amd8111e_rx_poll, 32);
+
+#if AMD8111E_VLAN_TAG_USED
+	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+#endif
+	/* Probe the external PHY */
+	amd8111e_probe_ext_phy(dev);
+
+	/* setting mii default values */
+	lp->mii_if.dev = dev;
+	lp->mii_if.mdio_read = amd8111e_mdio_read;
+	lp->mii_if.mdio_write = amd8111e_mdio_write;
+	lp->mii_if.phy_id = lp->ext_phy_addr;
+
+	/* Set receive buffer length and set jumbo option*/
+	amd8111e_set_rx_buff_len(dev);
+
+
+	err = register_netdev(dev);
+	if (err) {
+		printk(KERN_ERR "amd8111e: Cannot register net device, "
+		       "exiting.\n");
+		goto err_iounmap;
+	}
+
+	pci_set_drvdata(pdev, dev);
+
+	/* Initialize software ipg timer */
+	if(lp->options & OPTION_DYN_IPG_ENABLE){
+		init_timer(&lp->ipg_data.ipg_timer);
+		lp->ipg_data.ipg_timer.data = (unsigned long) dev;
+		lp->ipg_data.ipg_timer.function = (void *)&amd8111e_config_ipg;
+		lp->ipg_data.ipg_timer.expires = jiffies +
+						 IPG_CONVERGE_JIFFIES;
+		lp->ipg_data.ipg = DEFAULT_IPG;
+		lp->ipg_data.ipg_state = CSTATE;
+	}
+
+	/*  display driver and device information */
+
+    	chip_version = (readl(lp->mmio + CHIPID) & 0xf0000000)>>28;
+	printk(KERN_INFO "%s: AMD-8111e Driver Version: %s\n",
+	       dev->name,MODULE_VERS);
+	printk(KERN_INFO "%s: [ Rev %x ] PCI 10/100BaseT Ethernet %pM\n",
+	       dev->name, chip_version, dev->dev_addr);
+	if (lp->ext_phy_id)
+		printk(KERN_INFO "%s: Found MII PHY ID 0x%08x at address 0x%02x\n",
+		       dev->name, lp->ext_phy_id, lp->ext_phy_addr);
+	else
+		printk(KERN_INFO "%s: Couldn't detect MII PHY, assuming address 0x01\n",
+		       dev->name);
+    	return 0;
+err_iounmap:
+	iounmap(lp->mmio);
+
+err_free_dev:
+	free_netdev(dev);
+
+err_free_reg:
+	pci_release_regions(pdev);
+
+err_disable_pdev:
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+	return err;
+
+}
+
+static struct pci_driver amd8111e_driver = {
+	.name   	= MODULE_NAME,
+	.id_table	= amd8111e_pci_tbl,
+	.probe		= amd8111e_probe_one,
+	.remove		= __devexit_p(amd8111e_remove_one),
+	.suspend	= amd8111e_suspend,
+	.resume		= amd8111e_resume
+};
+
+static int __init amd8111e_init(void)
+{
+	return pci_register_driver(&amd8111e_driver);
+}
+
+static void __exit amd8111e_cleanup(void)
+{
+	pci_unregister_driver(&amd8111e_driver);
+}
+
+module_init(amd8111e_init);
+module_exit(amd8111e_cleanup);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/amd8111e.h linux-libre-3.2-gnu/drivers/net/ethernet/amd/amd8111e.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/amd8111e.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/amd8111e.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,816 @@
+/*
+ * Advanced  Micro Devices Inc. AMD8111E Linux Network Driver
+ * Copyright (C) 2003 Advanced Micro 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+
+Module Name:
+
+    amd8111e.h
+
+Abstract:
+
+ 	 AMD8111 based 10/100 Ethernet Controller driver definitions.
+
+Environment:
+
+	Kernel Mode
+
+Revision History:
+ 	3.0.0
+	   Initial Revision.
+	3.0.1
+*/
+
+#ifndef _AMD811E_H
+#define _AMD811E_H
+
+/* Command style register access
+
+Registers CMD0, CMD2, CMD3,CMD7 and INTEN0 uses a write access technique called command style access. It allows the write to selected bits of this register without altering the bits that are not selected. Command style registers are divided into 4 bytes that can be written independently. Higher order bit of each byte is the  value bit that specifies the value that will be written into the selected bits of register.
+
+eg., if the value 10011010b is written into the least significant byte of a command style register, bits 1,3 and 4 of the register will be set to 1, and the other bits will not be altered. If the value 00011010b is written into the same byte, bits 1,3 and 4 will be cleared to 0 and the other bits will not be altered.
+
+*/
+
+/*  Offset for Memory Mapped Registers. */
+/* 32 bit registers */
+
+#define  ASF_STAT		0x00	/* ASF status register */
+#define CHIPID			0x04	/* Chip ID regsiter */
+#define	MIB_DATA		0x10	/* MIB data register */
+#define MIB_ADDR		0x14	/* MIB address register */
+#define STAT0			0x30	/* Status0 register */
+#define INT0			0x38	/* Interrupt0 register */
+#define INTEN0			0x40	/* Interrupt0  enable register*/
+#define CMD0			0x48	/* Command0 register */
+#define CMD2			0x50	/* Command2 register */
+#define CMD3			0x54	/* Command3 resiter */
+#define CMD7			0x64	/* Command7 register */
+
+#define CTRL1 			0x6C	/* Control1 register */
+#define CTRL2 			0x70	/* Control2 register */
+
+#define XMT_RING_LIMIT		0x7C	/* Transmit ring limit register */
+
+#define AUTOPOLL0		0x88	/* Auto-poll0 register */
+#define AUTOPOLL1		0x8A	/* Auto-poll1 register */
+#define AUTOPOLL2		0x8C	/* Auto-poll2 register */
+#define AUTOPOLL3		0x8E	/* Auto-poll3 register */
+#define AUTOPOLL4		0x90	/* Auto-poll4 register */
+#define	AUTOPOLL5		0x92	/* Auto-poll5 register */
+
+#define AP_VALUE		0x98	/* Auto-poll value register */
+#define DLY_INT_A		0xA8	/* Group A delayed interrupt register */
+#define DLY_INT_B		0xAC	/* Group B delayed interrupt register */
+
+#define FLOW_CONTROL		0xC8	/* Flow control register */
+#define PHY_ACCESS		0xD0	/* PHY access register */
+
+#define STVAL			0xD8	/* Software timer value register */
+
+#define XMT_RING_BASE_ADDR0	0x100	/* Transmit ring0 base addr register */
+#define XMT_RING_BASE_ADDR1	0x108	/* Transmit ring1 base addr register */
+#define XMT_RING_BASE_ADDR2	0x110	/* Transmit ring2 base addr register */
+#define XMT_RING_BASE_ADDR3	0x118	/* Transmit ring2 base addr register */
+
+#define RCV_RING_BASE_ADDR0	0x120	/* Transmit ring0 base addr register */
+
+#define PMAT0			0x190	/* OnNow pattern register0 */
+#define PMAT1			0x194	/* OnNow pattern register1 */
+
+/* 16bit registers */
+
+#define XMT_RING_LEN0		0x140	/* Transmit Ring0 length register */
+#define XMT_RING_LEN1		0x144	/* Transmit Ring1 length register */
+#define XMT_RING_LEN2		0x148 	/* Transmit Ring2 length register */
+#define XMT_RING_LEN3		0x14C	/* Transmit Ring3 length register */
+
+#define RCV_RING_LEN0		0x150	/* Receive Ring0 length register */
+
+#define SRAM_SIZE		0x178	/* SRAM size register */
+#define SRAM_BOUNDARY		0x17A	/* SRAM boundary register */
+
+/* 48bit register */
+
+#define PADR			0x160	/* Physical address register */
+
+#define IFS1			0x18C	/* Inter-frame spacing Part1 register */
+#define IFS			0x18D	/* Inter-frame spacing register */
+#define IPG			0x18E	/* Inter-frame gap register */
+/* 64bit register */
+
+#define LADRF			0x168	/* Logical address filter register */
+
+
+/* Register Bit Definitions */
+typedef enum {
+
+	ASF_INIT_DONE		= (1 << 1),
+	ASF_INIT_PRESENT	= (1 << 0),
+
+}STAT_ASF_BITS;
+
+typedef enum {
+
+	MIB_CMD_ACTIVE		= (1 << 15 ),
+	MIB_RD_CMD		= (1 << 13 ),
+	MIB_CLEAR		= (1 << 12 ),
+	MIB_ADDRESS		= (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)|
+					(1 << 4) | (1 << 5),
+}MIB_ADDR_BITS;
+
+
+typedef enum {
+
+	PMAT_DET		= (1 << 12),
+	MP_DET		        = (1 << 11),
+	LC_DET			= (1 << 10),
+	SPEED_MASK		= (1 << 9)|(1 << 8)|(1 << 7),
+	FULL_DPLX		= (1 << 6),
+	LINK_STATS		= (1 << 5),
+	AUTONEG_COMPLETE	= (1 << 4),
+	MIIPD			= (1 << 3),
+	RX_SUSPENDED		= (1 << 2),
+	TX_SUSPENDED		= (1 << 1),
+	RUNNING			= (1 << 0),
+
+}STAT0_BITS;
+
+#define PHY_SPEED_10		0x2
+#define PHY_SPEED_100		0x3
+
+/* INT0				0x38, 32bit register */
+typedef enum {
+
+	INTR			= (1 << 31),
+	PCSINT			= (1 << 28),
+	LCINT			= (1 << 27),
+	APINT5			= (1 << 26),
+	APINT4			= (1 << 25),
+	APINT3			= (1 << 24),
+	TINT_SUM		= (1 << 23),
+	APINT2			= (1 << 22),
+	APINT1			= (1 << 21),
+	APINT0			= (1 << 20),
+	MIIPDTINT		= (1 << 19),
+	MCCINT			= (1 << 17),
+	MREINT			= (1 << 16),
+	RINT_SUM		= (1 << 15),
+	SPNDINT			= (1 << 14),
+	MPINT			= (1 << 13),
+	SINT			= (1 << 12),
+	TINT3			= (1 << 11),
+	TINT2			= (1 << 10),
+	TINT1			= (1 << 9),
+	TINT0			= (1 << 8),
+	UINT			= (1 << 7),
+	STINT			= (1 << 4),
+	RINT0			= (1 << 0),
+
+}INT0_BITS;
+
+typedef enum {
+
+	VAL3			= (1 << 31),   /* VAL bit for byte 3 */
+	VAL2			= (1 << 23),   /* VAL bit for byte 2 */
+	VAL1			= (1 << 15),   /* VAL bit for byte 1 */
+	VAL0			= (1 << 7),    /* VAL bit for byte 0 */
+
+}VAL_BITS;
+
+typedef enum {
+
+	/* VAL3 */
+	LCINTEN			= (1 << 27),
+	APINT5EN		= (1 << 26),
+	APINT4EN		= (1 << 25),
+	APINT3EN		= (1 << 24),
+	/* VAL2 */
+	APINT2EN		= (1 << 22),
+	APINT1EN		= (1 << 21),
+	APINT0EN		= (1 << 20),
+	MIIPDTINTEN		= (1 << 19),
+	MCCIINTEN		= (1 << 18),
+	MCCINTEN		= (1 << 17),
+	MREINTEN		= (1 << 16),
+	/* VAL1 */
+	SPNDINTEN		= (1 << 14),
+	MPINTEN			= (1 << 13),
+	TINTEN3			= (1 << 11),
+	SINTEN			= (1 << 12),
+	TINTEN2			= (1 << 10),
+	TINTEN1			= (1 << 9),
+	TINTEN0			= (1 << 8),
+	/* VAL0 */
+	STINTEN			= (1 << 4),
+	RINTEN0			= (1 << 0),
+
+	INTEN0_CLEAR 		= 0x1F7F7F1F, /* Command style register */
+
+}INTEN0_BITS;
+
+typedef enum {
+	/* VAL2 */
+	RDMD0			= (1 << 16),
+	/* VAL1 */
+	TDMD3			= (1 << 11),
+	TDMD2			= (1 << 10),
+	TDMD1			= (1 << 9),
+	TDMD0			= (1 << 8),
+	/* VAL0 */
+	UINTCMD			= (1 << 6),
+	RX_FAST_SPND		= (1 << 5),
+	TX_FAST_SPND		= (1 << 4),
+	RX_SPND			= (1 << 3),
+	TX_SPND			= (1 << 2),
+	INTREN			= (1 << 1),
+	RUN			= (1 << 0),
+
+	CMD0_CLEAR 		= 0x000F0F7F,   /* Command style register */
+
+}CMD0_BITS;
+
+typedef enum {
+
+	/* VAL3 */
+	CONDUIT_MODE		= (1 << 29),
+	/* VAL2 */
+	RPA			= (1 << 19),
+	DRCVPA			= (1 << 18),
+	DRCVBC			= (1 << 17),
+	PROM			= (1 << 16),
+	/* VAL1 */
+	ASTRP_RCV		= (1 << 13),
+	RCV_DROP0	  	= (1 << 12),
+	EMBA			= (1 << 11),
+	DXMT2PD			= (1 << 10),
+	LTINTEN			= (1 << 9),
+	DXMTFCS			= (1 << 8),
+	/* VAL0 */
+	APAD_XMT		= (1 << 6),
+	DRTY			= (1 << 5),
+	INLOOP			= (1 << 4),
+	EXLOOP			= (1 << 3),
+	REX_RTRY		= (1 << 2),
+	REX_UFLO		= (1 << 1),
+	REX_LCOL		= (1 << 0),
+
+	CMD2_CLEAR 		= 0x3F7F3F7F,   /* Command style register */
+
+}CMD2_BITS;
+
+typedef enum {
+
+	/* VAL3 */
+	ASF_INIT_DONE_ALIAS	= (1 << 29),
+	/* VAL2 */
+	JUMBO			= (1 << 21),
+	VSIZE			= (1 << 20),
+	VLONLY			= (1 << 19),
+	VL_TAG_DEL		= (1 << 18),
+	/* VAL1 */
+	EN_PMGR			= (1 << 14),
+	INTLEVEL		= (1 << 13),
+	FORCE_FULL_DUPLEX	= (1 << 12),
+	FORCE_LINK_STATUS	= (1 << 11),
+	APEP			= (1 << 10),
+	MPPLBA			= (1 << 9),
+	/* VAL0 */
+	RESET_PHY_PULSE		= (1 << 2),
+	RESET_PHY		= (1 << 1),
+	PHY_RST_POL		= (1 << 0),
+
+}CMD3_BITS;
+
+
+typedef enum {
+
+	/* VAL0 */
+	PMAT_SAVE_MATCH		= (1 << 4),
+	PMAT_MODE		= (1 << 3),
+	MPEN_SW			= (1 << 1),
+	LCMODE_SW		= (1 << 0),
+
+	CMD7_CLEAR  		= 0x0000001B	/* Command style register */
+
+}CMD7_BITS;
+
+
+typedef enum {
+
+	RESET_PHY_WIDTH		= (0xF << 16) | (0xF<< 20), /* 0x00FF0000 */
+	XMTSP_MASK		= (1 << 9) | (1 << 8),	/* 9:8 */
+	XMTSP_128		= (1 << 9),	/* 9 */
+	XMTSP_64		= (1 << 8),
+	CACHE_ALIGN		= (1 << 4),
+	BURST_LIMIT_MASK	= (0xF << 0 ),
+	CTRL1_DEFAULT		= 0x00010111,
+
+}CTRL1_BITS;
+
+typedef enum {
+
+	FMDC_MASK		= (1 << 9)|(1 << 8),	/* 9:8 */
+	XPHYRST			= (1 << 7),
+	XPHYANE			= (1 << 6),
+	XPHYFD			= (1 << 5),
+	XPHYSP			= (1 << 4) | (1 << 3),	/* 4:3 */
+	APDW_MASK		= (1 <<	2) | (1 << 1) | (1 << 0), /* 2:0 */
+
+}CTRL2_BITS;
+
+/* XMT_RING_LIMIT		0x7C, 32bit register */
+typedef enum {
+
+	XMT_RING2_LIMIT		= (0xFF << 16),	/* 23:16 */
+	XMT_RING1_LIMIT		= (0xFF << 8),	/* 15:8 */
+	XMT_RING0_LIMIT		= (0xFF << 0), 	/* 7:0 */
+
+}XMT_RING_LIMIT_BITS;
+
+typedef enum {
+
+	AP_REG0_EN		= (1 << 15),
+	AP_REG0_ADDR_MASK	= (0xF << 8) |(1 << 12),/* 12:8 */
+	AP_PHY0_ADDR_MASK	= (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL0_BITS;
+
+/* AUTOPOLL1			0x8A, 16bit register */
+typedef enum {
+
+	AP_REG1_EN		= (1 << 15),
+	AP_REG1_ADDR_MASK	= (0xF << 8) |(1 << 12),/* 12:8 */
+	AP_PRE_SUP1		= (1 << 6),
+	AP_PHY1_DFLT		= (1 << 5),
+	AP_PHY1_ADDR_MASK	= (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL1_BITS;
+
+
+typedef enum {
+
+	AP_REG2_EN		= (1 << 15),
+	AP_REG2_ADDR_MASK	= (0xF << 8) |(1 << 12),/* 12:8 */
+	AP_PRE_SUP2		= (1 << 6),
+	AP_PHY2_DFLT		= (1 << 5),
+	AP_PHY2_ADDR_MASK	= (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL2_BITS;
+
+typedef enum {
+
+	AP_REG3_EN		= (1 << 15),
+	AP_REG3_ADDR_MASK	= (0xF << 8) |(1 << 12),/* 12:8 */
+	AP_PRE_SUP3		= (1 << 6),
+	AP_PHY3_DFLT		= (1 << 5),
+	AP_PHY3_ADDR_MASK	= (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL3_BITS;
+
+
+typedef enum {
+
+	AP_REG4_EN		= (1 << 15),
+	AP_REG4_ADDR_MASK	= (0xF << 8) |(1 << 12),/* 12:8 */
+	AP_PRE_SUP4		= (1 << 6),
+	AP_PHY4_DFLT		= (1 << 5),
+	AP_PHY4_ADDR_MASK	= (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL4_BITS;
+
+
+typedef enum {
+
+	AP_REG5_EN		= (1 << 15),
+	AP_REG5_ADDR_MASK	= (0xF << 8) |(1 << 12),/* 12:8 */
+	AP_PRE_SUP5		= (1 << 6),
+	AP_PHY5_DFLT		= (1 << 5),
+	AP_PHY5_ADDR_MASK	= (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL5_BITS;
+
+
+
+
+/* AP_VALUE 			0x98, 32bit ragister */
+typedef enum {
+
+	AP_VAL_ACTIVE		= (1 << 31),
+	AP_VAL_RD_CMD		= ( 1 << 29),
+	AP_ADDR			= (1 << 18)|(1 << 17)|(1 << 16), /* 18:16 */
+	AP_VAL			= (0xF << 0) | (0xF << 4) |( 0xF << 8) |
+				  (0xF << 12),	/* 15:0 */
+
+}AP_VALUE_BITS;
+
+typedef enum {
+
+	DLY_INT_A_R3		= (1 << 31),
+	DLY_INT_A_R2		= (1 << 30),
+	DLY_INT_A_R1		= (1 << 29),
+	DLY_INT_A_R0		= (1 << 28),
+	DLY_INT_A_T3		= (1 << 27),
+	DLY_INT_A_T2		= (1 << 26),
+	DLY_INT_A_T1		= (1 << 25),
+	DLY_INT_A_T0		= ( 1 << 24),
+	EVENT_COUNT_A		= (0xF << 16) | (0x1 << 20),/* 20:16 */
+	MAX_DELAY_TIME_A	= (0xF << 0) | (0xF << 4) | (1 << 8)|
+				  (1 << 9) | (1 << 10),	/* 10:0 */
+
+}DLY_INT_A_BITS;
+
+typedef enum {
+
+	DLY_INT_B_R3		= (1 << 31),
+	DLY_INT_B_R2		= (1 << 30),
+	DLY_INT_B_R1		= (1 << 29),
+	DLY_INT_B_R0		= (1 << 28),
+	DLY_INT_B_T3		= (1 << 27),
+	DLY_INT_B_T2		= (1 << 26),
+	DLY_INT_B_T1		= (1 << 25),
+	DLY_INT_B_T0		= ( 1 << 24),
+	EVENT_COUNT_B		= (0xF << 16) | (0x1 << 20),/* 20:16 */
+	MAX_DELAY_TIME_B	= (0xF << 0) | (0xF << 4) | (1 << 8)|
+				  (1 << 9) | (1 << 10),	/* 10:0 */
+}DLY_INT_B_BITS;
+
+
+/* FLOW_CONTROL 		0xC8, 32bit register */
+typedef enum {
+
+	PAUSE_LEN_CHG		= (1 << 30),
+	FTPE			= (1 << 22),
+	FRPE			= (1 << 21),
+	NAPA			= (1 << 20),
+	NPA			= (1 << 19),
+	FIXP			= ( 1 << 18),
+	FCCMD			= ( 1 << 16),
+	PAUSE_LEN		= (0xF << 0) | (0xF << 4) |( 0xF << 8) |	 				  (0xF << 12),	/* 15:0 */
+
+}FLOW_CONTROL_BITS;
+
+/* PHY_ ACCESS			0xD0, 32bit register */
+typedef enum {
+
+	PHY_CMD_ACTIVE		= (1 << 31),
+	PHY_WR_CMD		= (1 << 30),
+	PHY_RD_CMD		= (1 << 29),
+	PHY_RD_ERR		= (1 << 28),
+	PHY_PRE_SUP		= (1 << 27),
+	PHY_ADDR		= (1 << 21) | (1 << 22) | (1 << 23)|
+				  	(1 << 24) |(1 << 25),/* 25:21 */
+	PHY_REG_ADDR		= (1 << 16) | (1 << 17) | (1 << 18)|	 			  	   	  	(1 << 19) | (1 << 20),/* 20:16 */
+	PHY_DATA		= (0xF << 0)|(0xF << 4) |(0xF << 8)|
+					(0xF << 12),/* 15:0 */
+
+}PHY_ACCESS_BITS;
+
+
+/* PMAT0			0x190,	 32bit register */
+typedef enum {
+	PMR_ACTIVE		= (1 << 31),
+	PMR_WR_CMD		= (1 << 30),
+	PMR_RD_CMD		= (1 << 29),
+	PMR_BANK		= (1 <<28),
+	PMR_ADDR		= (0xF << 16)|(1 << 20)|(1 << 21)|
+				  	(1 << 22),/* 22:16 */
+	PMR_B4			= (0xF << 0) | (0xF << 4),/* 15:0 */
+}PMAT0_BITS;
+
+
+/* PMAT1			0x194,	 32bit register */
+typedef enum {
+	PMR_B3			= (0xF << 24) | (0xF <<28),/* 31:24 */
+	PMR_B2			= (0xF << 16) |(0xF << 20),/* 23:16 */
+	PMR_B1			= (0xF << 8) | (0xF <<12), /* 15:8 */
+	PMR_B0			= (0xF << 0)|(0xF << 4),/* 7:0 */
+}PMAT1_BITS;
+
+/************************************************************************/
+/*                                                                      */
+/*                      MIB counter definitions                         */
+/*                                                                      */
+/************************************************************************/
+
+#define rcv_miss_pkts				0x00
+#define rcv_octets				0x01
+#define rcv_broadcast_pkts			0x02
+#define rcv_multicast_pkts			0x03
+#define rcv_undersize_pkts			0x04
+#define rcv_oversize_pkts			0x05
+#define rcv_fragments				0x06
+#define rcv_jabbers				0x07
+#define rcv_unicast_pkts			0x08
+#define rcv_alignment_errors			0x09
+#define rcv_fcs_errors				0x0A
+#define rcv_good_octets				0x0B
+#define rcv_mac_ctrl				0x0C
+#define rcv_flow_ctrl				0x0D
+#define rcv_pkts_64_octets			0x0E
+#define rcv_pkts_65to127_octets			0x0F
+#define rcv_pkts_128to255_octets		0x10
+#define rcv_pkts_256to511_octets		0x11
+#define rcv_pkts_512to1023_octets		0x12
+#define rcv_pkts_1024to1518_octets		0x13
+#define rcv_unsupported_opcode			0x14
+#define rcv_symbol_errors			0x15
+#define rcv_drop_pkts_ring1			0x16
+#define rcv_drop_pkts_ring2			0x17
+#define rcv_drop_pkts_ring3			0x18
+#define rcv_drop_pkts_ring4			0x19
+#define rcv_jumbo_pkts				0x1A
+
+#define xmt_underrun_pkts			0x20
+#define xmt_octets				0x21
+#define xmt_packets				0x22
+#define xmt_broadcast_pkts			0x23
+#define xmt_multicast_pkts			0x24
+#define xmt_collisions				0x25
+#define xmt_unicast_pkts			0x26
+#define xmt_one_collision			0x27
+#define xmt_multiple_collision			0x28
+#define xmt_deferred_transmit			0x29
+#define xmt_late_collision			0x2A
+#define xmt_excessive_defer			0x2B
+#define xmt_loss_carrier			0x2C
+#define xmt_excessive_collision			0x2D
+#define xmt_back_pressure			0x2E
+#define xmt_flow_ctrl				0x2F
+#define xmt_pkts_64_octets			0x30
+#define xmt_pkts_65to127_octets			0x31
+#define xmt_pkts_128to255_octets		0x32
+#define xmt_pkts_256to511_octets		0x33
+#define xmt_pkts_512to1023_octets		0x34
+#define xmt_pkts_1024to1518_octet		0x35
+#define xmt_oversize_pkts			0x36
+#define xmt_jumbo_pkts				0x37
+
+
+/* Driver definitions */
+
+#define	 PCI_VENDOR_ID_AMD		0x1022
+#define  PCI_DEVICE_ID_AMD8111E_7462	0x7462
+
+#define MAX_UNITS			8 /* Maximum number of devices possible */
+
+#define NUM_TX_BUFFERS			32 /* Number of transmit buffers */
+#define NUM_RX_BUFFERS			32 /* Number of receive buffers */
+
+#define TX_BUFF_MOD_MASK         	31 /* (NUM_TX_BUFFERS -1) */
+#define RX_BUFF_MOD_MASK         	31 /* (NUM_RX_BUFFERS -1) */
+
+#define NUM_TX_RING_DR			32
+#define NUM_RX_RING_DR			32
+
+#define TX_RING_DR_MOD_MASK         	31 /* (NUM_TX_RING_DR -1) */
+#define RX_RING_DR_MOD_MASK         	31 /* (NUM_RX_RING_DR -1) */
+
+#define MAX_FILTER_SIZE			64 /* Maximum multicast address */
+#define AMD8111E_MIN_MTU	 	60
+#define AMD8111E_MAX_MTU		9000
+
+#define PKT_BUFF_SZ			1536
+#define MIN_PKT_LEN			60
+#define ETH_ADDR_LEN			6
+
+#define  AMD8111E_TX_TIMEOUT		(3 * HZ)/* 3 sec */
+#define SOFT_TIMER_FREQ 		0xBEBC  /* 0.5 sec */
+#define DELAY_TIMER_CONV		50    /* msec to 10 usec conversion.
+						 Only 500 usec resolution */
+#define OPTION_VLAN_ENABLE		0x0001
+#define OPTION_JUMBO_ENABLE		0x0002
+#define OPTION_MULTICAST_ENABLE		0x0004
+#define OPTION_WOL_ENABLE		0x0008
+#define OPTION_WAKE_MAGIC_ENABLE	0x0010
+#define OPTION_WAKE_PHY_ENABLE		0x0020
+#define OPTION_INTR_COAL_ENABLE		0x0040
+#define OPTION_DYN_IPG_ENABLE	        0x0080
+
+#define PHY_REG_ADDR_MASK		0x1f
+
+/* ipg parameters */
+#define DEFAULT_IPG			0x60
+#define IFS1_DELTA			36
+#define	IPG_CONVERGE_JIFFIES (HZ/2)
+#define	IPG_STABLE_TIME	5
+#define	MIN_IPG	96
+#define	MAX_IPG	255
+#define IPG_STEP	16
+#define CSTATE  1
+#define SSTATE  2
+
+/* Assume contoller gets data 10 times the maximum processing time */
+#define  REPEAT_CNT			10
+
+/* amd8111e decriptor flag definitions */
+typedef enum {
+
+	OWN_BIT		=	(1 << 15),
+	ADD_FCS_BIT	=	(1 << 13),
+	LTINT_BIT	=	(1 << 12),
+	STP_BIT		=	(1 << 9),
+	ENP_BIT		=	(1 << 8),
+	KILL_BIT	= 	(1 << 6),
+	TCC_VLAN_INSERT	=	(1 << 1),
+	TCC_VLAN_REPLACE =	(1 << 1) |( 1<< 0),
+
+}TX_FLAG_BITS;
+
+typedef enum {
+	ERR_BIT 	=	(1 << 14),
+	FRAM_BIT	=  	(1 << 13),
+	OFLO_BIT	=       (1 << 12),
+	CRC_BIT		=	(1 << 11),
+	PAM_BIT		=	(1 << 6),
+	LAFM_BIT	= 	(1 << 5),
+	BAM_BIT		=	(1 << 4),
+	TT_VLAN_TAGGED	= 	(1 << 3) |(1 << 2),/* 0x000 */
+	TT_PRTY_TAGGED	=	(1 << 3),/* 0x0008 */
+
+}RX_FLAG_BITS;
+
+#define RESET_RX_FLAGS		0x0000
+#define TT_MASK			0x000c
+#define TCC_MASK		0x0003
+
+/* driver ioctl parameters */
+#define AMD8111E_REG_DUMP_LEN	 13*sizeof(u32)
+
+/* amd8111e desriptor format */
+
+struct amd8111e_tx_dr{
+
+	__le16 buff_count; /* Size of the buffer pointed by this descriptor */
+
+	__le16 tx_flags;
+
+	__le16 tag_ctrl_info;
+
+	__le16 tag_ctrl_cmd;
+
+	__le32 buff_phy_addr;
+
+	__le32 reserved;
+};
+
+struct amd8111e_rx_dr{
+
+	__le32 reserved;
+
+	__le16 msg_count; /* Received message len */
+
+	__le16 tag_ctrl_info;
+
+	__le16 buff_count;  /* Len of the buffer pointed by descriptor. */
+
+	__le16 rx_flags;
+
+	__le32 buff_phy_addr;
+
+};
+struct amd8111e_link_config{
+
+#define SPEED_INVALID		0xffff
+#define DUPLEX_INVALID		0xff
+#define AUTONEG_INVALID		0xff
+
+	unsigned long			orig_phy_option;
+	u16				speed;
+	u8				duplex;
+	u8				autoneg;
+	u8				reserved;  /* 32bit alignment */
+};
+
+enum coal_type{
+
+	NO_COALESCE,
+	LOW_COALESCE,
+	MEDIUM_COALESCE,
+	HIGH_COALESCE,
+
+};
+
+enum coal_mode{
+       	RX_INTR_COAL,
+	TX_INTR_COAL,
+	DISABLE_COAL,
+	ENABLE_COAL,
+
+};
+#define MAX_TIMEOUT	40
+#define MAX_EVENT_COUNT 31
+struct amd8111e_coalesce_conf{
+
+	unsigned int rx_timeout;
+	unsigned int rx_event_count;
+	unsigned long rx_packets;
+	unsigned long rx_prev_packets;
+	unsigned long rx_bytes;
+	unsigned long rx_prev_bytes;
+	unsigned int rx_coal_type;
+
+	unsigned int tx_timeout;
+	unsigned int tx_event_count;
+	unsigned long tx_packets;
+	unsigned long tx_prev_packets;
+	unsigned long tx_bytes;
+	unsigned long tx_prev_bytes;
+	unsigned int tx_coal_type;
+
+};
+struct ipg_info{
+
+	unsigned int ipg_state;
+	unsigned int ipg;
+	unsigned int current_ipg;
+	unsigned int col_cnt;
+	unsigned int diff_col_cnt;
+	unsigned int timer_tick;
+	unsigned int prev_ipg;
+	struct timer_list ipg_timer;
+};
+
+struct amd8111e_priv{
+
+	struct amd8111e_tx_dr*  tx_ring;
+	struct amd8111e_rx_dr* rx_ring;
+	dma_addr_t tx_ring_dma_addr;	/* tx descriptor ring base address */
+	dma_addr_t rx_ring_dma_addr;	/* rx descriptor ring base address */
+	const char *name;
+	struct pci_dev *pci_dev;	/* Ptr to the associated pci_dev */
+	struct net_device* amd8111e_net_dev; 	/* ptr to associated net_device */
+	/* Transmit and recive skbs */
+	struct sk_buff *tx_skbuff[NUM_TX_BUFFERS];
+	struct sk_buff *rx_skbuff[NUM_RX_BUFFERS];
+	/* Transmit and receive dma mapped addr */
+	dma_addr_t tx_dma_addr[NUM_TX_BUFFERS];
+	dma_addr_t rx_dma_addr[NUM_RX_BUFFERS];
+	/* Reg memory mapped address */
+	void __iomem *mmio;
+
+	struct napi_struct napi;
+
+	spinlock_t lock;	/* Guard lock */
+	unsigned long rx_idx, tx_idx;	/* The next free ring entry */
+	unsigned long tx_complete_idx;
+	unsigned long tx_ring_complete_idx;
+	unsigned long tx_ring_idx;
+	unsigned int rx_buff_len;	/* Buffer length of rx buffers */
+	int options;		/* Options enabled/disabled for the device */
+
+	unsigned long ext_phy_option;
+	int ext_phy_addr;
+	u32 ext_phy_id;
+
+	struct amd8111e_link_config link_config;
+	int pm_cap;
+
+	struct net_device *next;
+	int mii;
+	struct mii_if_info mii_if;
+	char opened;
+	unsigned int drv_rx_errors;
+	struct amd8111e_coalesce_conf coal_conf;
+
+	struct ipg_info  ipg_data;
+
+};
+
+/* kernel provided writeq does not write 64 bits into the amd8111e device register instead writes only higher 32bits data into lower 32bits of the register.
+BUG? */
+#define  amd8111e_writeq(_UlData,_memMap)   \
+		writel(*(u32*)(&_UlData), _memMap);	\
+		writel(*(u32*)((u8*)(&_UlData)+4), _memMap+4)
+
+/* maps the external speed options to internal value */
+typedef enum {
+	SPEED_AUTONEG,
+	SPEED10_HALF,
+	SPEED10_FULL,
+	SPEED100_HALF,
+	SPEED100_FULL,
+}EXT_PHY_OPTION;
+
+static int card_idx;
+static int speed_duplex[MAX_UNITS] = { 0, };
+static int coalesce[MAX_UNITS] = {1,1,1,1,1,1,1,1};
+static int dynamic_ipg[MAX_UNITS] = {0,0,0,0,0,0,0,0};
+static unsigned int chip_version;
+
+#endif /* _AMD8111E_H */
+
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/ariadne.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/ariadne.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/ariadne.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/ariadne.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,793 @@
+/*
+ *  Amiga Linux/m68k Ariadne Ethernet Driver
+ *
+ *  Â© Copyright 1995-2003 by Geert Uytterhoeven (geert@linux-m68k.org)
+ *			     Peter De Schrijver (p2@mind.be)
+ *
+ *  ---------------------------------------------------------------------------
+ *
+ *  This program is based on
+ *
+ *	lance.c:	An AMD LANCE ethernet driver for linux.
+ *			Written 1993-94 by Donald Becker.
+ *
+ *	Am79C960:	PCnet(tm)-ISA Single-Chip Ethernet Controller
+ *			Advanced Micro Devices
+ *			Publication #16907, Rev. B, Amendment/0, May 1994
+ *
+ *	MC68230:	Parallel Interface/Timer (PI/T)
+ *			Motorola Semiconductors, December, 1983
+ *
+ *  ---------------------------------------------------------------------------
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of the Linux
+ *  distribution for more details.
+ *
+ *  ---------------------------------------------------------------------------
+ *
+ *  The Ariadne is a Zorro-II board made by Village Tronic. It contains:
+ *
+ *	- an Am79C960 PCnet-ISA Single-Chip Ethernet Controller with both
+ *	  10BASE-2 (thin coax) and 10BASE-T (UTP) connectors
+ *
+ *	- an MC68230 Parallel Interface/Timer configured as 2 parallel ports
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+/*#define DEBUG*/
+
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/interrupt.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/zorro.h>
+#include <linux/bitops.h>
+
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+#include <asm/irq.h>
+
+#include "ariadne.h"
+
+#ifdef ARIADNE_DEBUG
+int ariadne_debug = ARIADNE_DEBUG;
+#else
+int ariadne_debug = 1;
+#endif
+
+/* Macros to Fix Endianness problems */
+
+/* Swap the Bytes in a WORD */
+#define swapw(x)	(((x >> 8) & 0x00ff) | ((x << 8) & 0xff00))
+/* Get the Low BYTE in a WORD */
+#define lowb(x)		(x & 0xff)
+/* Get the Swapped High WORD in a LONG */
+#define swhighw(x)	((((x) >> 8) & 0xff00) | (((x) >> 24) & 0x00ff))
+/* Get the Swapped Low WORD in a LONG */
+#define swloww(x)	((((x) << 8) & 0xff00) | (((x) >> 8) & 0x00ff))
+
+/* Transmit/Receive Ring Definitions */
+
+#define TX_RING_SIZE	5
+#define RX_RING_SIZE	16
+
+#define PKT_BUF_SIZE	1520
+
+/* Private Device Data */
+
+struct ariadne_private {
+	volatile struct TDRE *tx_ring[TX_RING_SIZE];
+	volatile struct RDRE *rx_ring[RX_RING_SIZE];
+	volatile u_short *tx_buff[TX_RING_SIZE];
+	volatile u_short *rx_buff[RX_RING_SIZE];
+	int cur_tx, cur_rx;		/* The next free ring entry */
+	int dirty_tx;			/* The ring entries to be free()ed */
+	char tx_full;
+};
+
+/* Structure Created in the Ariadne's RAM Buffer */
+
+struct lancedata {
+	struct TDRE tx_ring[TX_RING_SIZE];
+	struct RDRE rx_ring[RX_RING_SIZE];
+	u_short tx_buff[TX_RING_SIZE][PKT_BUF_SIZE / sizeof(u_short)];
+	u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE / sizeof(u_short)];
+};
+
+static void memcpyw(volatile u_short *dest, u_short *src, int len)
+{
+	while (len >= 2) {
+		*(dest++) = *(src++);
+		len -= 2;
+	}
+	if (len == 1)
+		*dest = (*(u_char *)src) << 8;
+}
+
+static void ariadne_init_ring(struct net_device *dev)
+{
+	struct ariadne_private *priv = netdev_priv(dev);
+	volatile struct lancedata *lancedata = (struct lancedata *)dev->mem_start;
+	int i;
+
+	netif_stop_queue(dev);
+
+	priv->tx_full = 0;
+	priv->cur_rx = priv->cur_tx = 0;
+	priv->dirty_tx = 0;
+
+	/* Set up TX Ring */
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		volatile struct TDRE *t = &lancedata->tx_ring[i];
+		t->TMD0 = swloww(ARIADNE_RAM +
+				 offsetof(struct lancedata, tx_buff[i]));
+		t->TMD1 = swhighw(ARIADNE_RAM +
+				  offsetof(struct lancedata, tx_buff[i])) |
+			TF_STP | TF_ENP;
+		t->TMD2 = swapw((u_short)-PKT_BUF_SIZE);
+		t->TMD3 = 0;
+		priv->tx_ring[i] = &lancedata->tx_ring[i];
+		priv->tx_buff[i] = lancedata->tx_buff[i];
+		netdev_dbg(dev, "TX Entry %2d at %p, Buf at %p\n",
+			   i, &lancedata->tx_ring[i], lancedata->tx_buff[i]);
+	}
+
+	/* Set up RX Ring */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		volatile struct RDRE *r = &lancedata->rx_ring[i];
+		r->RMD0 = swloww(ARIADNE_RAM +
+				 offsetof(struct lancedata, rx_buff[i]));
+		r->RMD1 = swhighw(ARIADNE_RAM +
+				  offsetof(struct lancedata, rx_buff[i])) |
+			RF_OWN;
+		r->RMD2 = swapw((u_short)-PKT_BUF_SIZE);
+		r->RMD3 = 0x0000;
+		priv->rx_ring[i] = &lancedata->rx_ring[i];
+		priv->rx_buff[i] = lancedata->rx_buff[i];
+		netdev_dbg(dev, "RX Entry %2d at %p, Buf at %p\n",
+			   i, &lancedata->rx_ring[i], lancedata->rx_buff[i]);
+	}
+}
+
+static int ariadne_rx(struct net_device *dev)
+{
+	struct ariadne_private *priv = netdev_priv(dev);
+	int entry = priv->cur_rx % RX_RING_SIZE;
+	int i;
+
+	/* If we own the next entry, it's a new packet. Send it up */
+	while (!(lowb(priv->rx_ring[entry]->RMD1) & RF_OWN)) {
+		int status = lowb(priv->rx_ring[entry]->RMD1);
+
+		if (status != (RF_STP | RF_ENP)) {	/* There was an error */
+			/* There is a tricky error noted by
+			 * John Murphy <murf@perftech.com> to Russ Nelson:
+			 * Even with full-sized buffers it's possible for a
+			 * jabber packet to use two buffers, with only the
+			 * last correctly noting the error
+			 */
+			/* Only count a general error at the end of a packet */
+			if (status & RF_ENP)
+				dev->stats.rx_errors++;
+			if (status & RF_FRAM)
+				dev->stats.rx_frame_errors++;
+			if (status & RF_OFLO)
+				dev->stats.rx_over_errors++;
+			if (status & RF_CRC)
+				dev->stats.rx_crc_errors++;
+			if (status & RF_BUFF)
+				dev->stats.rx_fifo_errors++;
+			priv->rx_ring[entry]->RMD1 &= 0xff00 | RF_STP | RF_ENP;
+		} else {
+			/* Malloc up new buffer, compatible with net-3 */
+			short pkt_len = swapw(priv->rx_ring[entry]->RMD3);
+			struct sk_buff *skb;
+
+			skb = dev_alloc_skb(pkt_len + 2);
+			if (skb == NULL) {
+				netdev_warn(dev, "Memory squeeze, deferring packet\n");
+				for (i = 0; i < RX_RING_SIZE; i++)
+					if (lowb(priv->rx_ring[(entry + i) % RX_RING_SIZE]->RMD1) & RF_OWN)
+						break;
+
+				if (i > RX_RING_SIZE - 2) {
+					dev->stats.rx_dropped++;
+					priv->rx_ring[entry]->RMD1 |= RF_OWN;
+					priv->cur_rx++;
+				}
+				break;
+			}
+
+
+			skb_reserve(skb, 2);	/* 16 byte align */
+			skb_put(skb, pkt_len);	/* Make room */
+			skb_copy_to_linear_data(skb,
+						(const void *)priv->rx_buff[entry],
+						pkt_len);
+			skb->protocol = eth_type_trans(skb, dev);
+			netdev_dbg(dev, "RX pkt type 0x%04x from %pM to %pM data 0x%08x len %d\n",
+				   ((u_short *)skb->data)[6],
+				   skb->data + 6, skb->data,
+				   (int)skb->data, (int)skb->len);
+
+			netif_rx(skb);
+			dev->stats.rx_packets++;
+			dev->stats.rx_bytes += pkt_len;
+		}
+
+		priv->rx_ring[entry]->RMD1 |= RF_OWN;
+		entry = (++priv->cur_rx) % RX_RING_SIZE;
+	}
+
+	priv->cur_rx = priv->cur_rx % RX_RING_SIZE;
+
+	/* We should check that at least two ring entries are free.
+	 * If not, we should free one and mark stats->rx_dropped++
+	 */
+
+	return 0;
+}
+
+static irqreturn_t ariadne_interrupt(int irq, void *data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+	struct ariadne_private *priv;
+	int csr0, boguscnt;
+	int handled = 0;
+
+	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
+
+	if (!(lance->RDP & INTR))	/* Check if any interrupt has been */
+		return IRQ_NONE;	/* generated by the board */
+
+	priv = netdev_priv(dev);
+
+	boguscnt = 10;
+	while ((csr0 = lance->RDP) & (ERR | RINT | TINT) && --boguscnt >= 0) {
+		/* Acknowledge all of the current interrupt sources ASAP */
+		lance->RDP = csr0 & ~(INEA | TDMD | STOP | STRT | INIT);
+
+#ifdef DEBUG
+		if (ariadne_debug > 5) {
+			netdev_dbg(dev, "interrupt  csr0=%#02x new csr=%#02x [",
+				   csr0, lance->RDP);
+			if (csr0 & INTR)
+				pr_cont(" INTR");
+			if (csr0 & INEA)
+				pr_cont(" INEA");
+			if (csr0 & RXON)
+				pr_cont(" RXON");
+			if (csr0 & TXON)
+				pr_cont(" TXON");
+			if (csr0 & TDMD)
+				pr_cont(" TDMD");
+			if (csr0 & STOP)
+				pr_cont(" STOP");
+			if (csr0 & STRT)
+				pr_cont(" STRT");
+			if (csr0 & INIT)
+				pr_cont(" INIT");
+			if (csr0 & ERR)
+				pr_cont(" ERR");
+			if (csr0 & BABL)
+				pr_cont(" BABL");
+			if (csr0 & CERR)
+				pr_cont(" CERR");
+			if (csr0 & MISS)
+				pr_cont(" MISS");
+			if (csr0 & MERR)
+				pr_cont(" MERR");
+			if (csr0 & RINT)
+				pr_cont(" RINT");
+			if (csr0 & TINT)
+				pr_cont(" TINT");
+			if (csr0 & IDON)
+				pr_cont(" IDON");
+			pr_cont(" ]\n");
+		}
+#endif
+
+		if (csr0 & RINT) {	/* Rx interrupt */
+			handled = 1;
+			ariadne_rx(dev);
+		}
+
+		if (csr0 & TINT) {	/* Tx-done interrupt */
+			int dirty_tx = priv->dirty_tx;
+
+			handled = 1;
+			while (dirty_tx < priv->cur_tx) {
+				int entry = dirty_tx % TX_RING_SIZE;
+				int status = lowb(priv->tx_ring[entry]->TMD1);
+
+				if (status & TF_OWN)
+					break;	/* It still hasn't been Txed */
+
+				priv->tx_ring[entry]->TMD1 &= 0xff00;
+
+				if (status & TF_ERR) {
+					/* There was an major error, log it */
+					int err_status = priv->tx_ring[entry]->TMD3;
+					dev->stats.tx_errors++;
+					if (err_status & EF_RTRY)
+						dev->stats.tx_aborted_errors++;
+					if (err_status & EF_LCAR)
+						dev->stats.tx_carrier_errors++;
+					if (err_status & EF_LCOL)
+						dev->stats.tx_window_errors++;
+					if (err_status & EF_UFLO) {
+						/* Ackk!  On FIFO errors the Tx unit is turned off! */
+						dev->stats.tx_fifo_errors++;
+						/* Remove this verbosity later! */
+						netdev_err(dev, "Tx FIFO error! Status %04x\n",
+							   csr0);
+						/* Restart the chip */
+						lance->RDP = STRT;
+					}
+				} else {
+					if (status & (TF_MORE | TF_ONE))
+						dev->stats.collisions++;
+					dev->stats.tx_packets++;
+				}
+				dirty_tx++;
+			}
+
+#ifndef final_version
+			if (priv->cur_tx - dirty_tx >= TX_RING_SIZE) {
+				netdev_err(dev, "out-of-sync dirty pointer, %d vs. %d, full=%d\n",
+					   dirty_tx, priv->cur_tx,
+					   priv->tx_full);
+				dirty_tx += TX_RING_SIZE;
+			}
+#endif
+
+			if (priv->tx_full && netif_queue_stopped(dev) &&
+			    dirty_tx > priv->cur_tx - TX_RING_SIZE + 2) {
+				/* The ring is no longer full */
+				priv->tx_full = 0;
+				netif_wake_queue(dev);
+			}
+
+			priv->dirty_tx = dirty_tx;
+		}
+
+		/* Log misc errors */
+		if (csr0 & BABL) {
+			handled = 1;
+			dev->stats.tx_errors++;	/* Tx babble */
+		}
+		if (csr0 & MISS) {
+			handled = 1;
+			dev->stats.rx_errors++;	/* Missed a Rx frame */
+		}
+		if (csr0 & MERR) {
+			handled = 1;
+			netdev_err(dev, "Bus master arbitration failure, status %04x\n",
+				   csr0);
+			/* Restart the chip */
+			lance->RDP = STRT;
+		}
+	}
+
+	/* Clear any other interrupt, and set interrupt enable */
+	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
+	lance->RDP = INEA | BABL | CERR | MISS | MERR | IDON;
+
+	if (ariadne_debug > 4)
+		netdev_dbg(dev, "exiting interrupt, csr%d=%#04x\n",
+			   lance->RAP, lance->RDP);
+
+	return IRQ_RETVAL(handled);
+}
+
+static int ariadne_open(struct net_device *dev)
+{
+	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+	u_short in;
+	u_long version;
+	int i;
+
+	/* Reset the LANCE */
+	in = lance->Reset;
+
+	/* Stop the LANCE */
+	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
+	lance->RDP = STOP;
+
+	/* Check the LANCE version */
+	lance->RAP = CSR88;		/* Chip ID */
+	version = swapw(lance->RDP);
+	lance->RAP = CSR89;		/* Chip ID */
+	version |= swapw(lance->RDP) << 16;
+	if ((version & 0x00000fff) != 0x00000003) {
+		pr_warn("Couldn't find AMD Ethernet Chip\n");
+		return -EAGAIN;
+	}
+	if ((version & 0x0ffff000) != 0x00003000) {
+		pr_warn("Couldn't find Am79C960 (Wrong part number = %ld)\n",
+		       (version & 0x0ffff000) >> 12);
+		return -EAGAIN;
+	}
+
+	netdev_dbg(dev, "Am79C960 (PCnet-ISA) Revision %ld\n",
+		   (version & 0xf0000000) >> 28);
+
+	ariadne_init_ring(dev);
+
+	/* Miscellaneous Stuff */
+	lance->RAP = CSR3;		/* Interrupt Masks and Deferral Control */
+	lance->RDP = 0x0000;
+	lance->RAP = CSR4;		/* Test and Features Control */
+	lance->RDP = DPOLL | APAD_XMT | MFCOM | RCVCCOM | TXSTRTM | JABM;
+
+	/* Set the Multicast Table */
+	lance->RAP = CSR8;		/* Logical Address Filter, LADRF[15:0] */
+	lance->RDP = 0x0000;
+	lance->RAP = CSR9;		/* Logical Address Filter, LADRF[31:16] */
+	lance->RDP = 0x0000;
+	lance->RAP = CSR10;		/* Logical Address Filter, LADRF[47:32] */
+	lance->RDP = 0x0000;
+	lance->RAP = CSR11;		/* Logical Address Filter, LADRF[63:48] */
+	lance->RDP = 0x0000;
+
+	/* Set the Ethernet Hardware Address */
+	lance->RAP = CSR12;		/* Physical Address Register, PADR[15:0] */
+	lance->RDP = ((u_short *)&dev->dev_addr[0])[0];
+	lance->RAP = CSR13;		/* Physical Address Register, PADR[31:16] */
+	lance->RDP = ((u_short *)&dev->dev_addr[0])[1];
+	lance->RAP = CSR14;		/* Physical Address Register, PADR[47:32] */
+	lance->RDP = ((u_short *)&dev->dev_addr[0])[2];
+
+	/* Set the Init Block Mode */
+	lance->RAP = CSR15;		/* Mode Register */
+	lance->RDP = 0x0000;
+
+	/* Set the Transmit Descriptor Ring Pointer */
+	lance->RAP = CSR30;		/* Base Address of Transmit Ring */
+	lance->RDP = swloww(ARIADNE_RAM + offsetof(struct lancedata, tx_ring));
+	lance->RAP = CSR31;		/* Base Address of transmit Ring */
+	lance->RDP = swhighw(ARIADNE_RAM + offsetof(struct lancedata, tx_ring));
+
+	/* Set the Receive Descriptor Ring Pointer */
+	lance->RAP = CSR24;		/* Base Address of Receive Ring */
+	lance->RDP = swloww(ARIADNE_RAM + offsetof(struct lancedata, rx_ring));
+	lance->RAP = CSR25;		/* Base Address of Receive Ring */
+	lance->RDP = swhighw(ARIADNE_RAM + offsetof(struct lancedata, rx_ring));
+
+	/* Set the Number of RX and TX Ring Entries */
+	lance->RAP = CSR76;		/* Receive Ring Length */
+	lance->RDP = swapw(((u_short)-RX_RING_SIZE));
+	lance->RAP = CSR78;		/* Transmit Ring Length */
+	lance->RDP = swapw(((u_short)-TX_RING_SIZE));
+
+	/* Enable Media Interface Port Auto Select (10BASE-2/10BASE-T) */
+	lance->RAP = ISACSR2;		/* Miscellaneous Configuration */
+	lance->IDP = ASEL;
+
+	/* LED Control */
+	lance->RAP = ISACSR5;		/* LED1 Status */
+	lance->IDP = PSE|XMTE;
+	lance->RAP = ISACSR6;	/* LED2 Status */
+	lance->IDP = PSE|COLE;
+	lance->RAP = ISACSR7;	/* LED3 Status */
+	lance->IDP = PSE|RCVE;
+
+	netif_start_queue(dev);
+
+	i = request_irq(IRQ_AMIGA_PORTS, ariadne_interrupt, IRQF_SHARED,
+			dev->name, dev);
+	if (i)
+		return i;
+
+	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
+	lance->RDP = INEA | STRT;
+
+	return 0;
+}
+
+static int ariadne_close(struct net_device *dev)
+{
+	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+
+	netif_stop_queue(dev);
+
+	lance->RAP = CSR112;		/* Missed Frame Count */
+	dev->stats.rx_missed_errors = swapw(lance->RDP);
+	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
+
+	if (ariadne_debug > 1) {
+		netdev_dbg(dev, "Shutting down ethercard, status was %02x\n",
+			   lance->RDP);
+		netdev_dbg(dev, "%lu packets missed\n",
+			   dev->stats.rx_missed_errors);
+	}
+
+	/* We stop the LANCE here -- it occasionally polls memory if we don't */
+	lance->RDP = STOP;
+
+	free_irq(IRQ_AMIGA_PORTS, dev);
+
+	return 0;
+}
+
+static inline void ariadne_reset(struct net_device *dev)
+{
+	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+
+	lance->RAP = CSR0;	/* PCnet-ISA Controller Status */
+	lance->RDP = STOP;
+	ariadne_init_ring(dev);
+	lance->RDP = INEA | STRT;
+	netif_start_queue(dev);
+}
+
+static void ariadne_tx_timeout(struct net_device *dev)
+{
+	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+
+	netdev_err(dev, "transmit timed out, status %04x, resetting\n",
+		   lance->RDP);
+	ariadne_reset(dev);
+	netif_wake_queue(dev);
+}
+
+static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb,
+				      struct net_device *dev)
+{
+	struct ariadne_private *priv = netdev_priv(dev);
+	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+	int entry;
+	unsigned long flags;
+	int len = skb->len;
+
+#if 0
+	if (ariadne_debug > 3) {
+		lance->RAP = CSR0;	/* PCnet-ISA Controller Status */
+		netdev_dbg(dev, "%s: csr0 %04x\n", __func__, lance->RDP);
+		lance->RDP = 0x0000;
+	}
+#endif
+
+	/* FIXME: is the 79C960 new enough to do its own padding right ? */
+	if (skb->len < ETH_ZLEN) {
+		if (skb_padto(skb, ETH_ZLEN))
+			return NETDEV_TX_OK;
+		len = ETH_ZLEN;
+	}
+
+	/* Fill in a Tx ring entry */
+
+	netdev_dbg(dev, "TX pkt type 0x%04x from %pM to %pM data 0x%08x len %d\n",
+		   ((u_short *)skb->data)[6],
+		   skb->data + 6, skb->data,
+		   (int)skb->data, (int)skb->len);
+
+	local_irq_save(flags);
+
+	entry = priv->cur_tx % TX_RING_SIZE;
+
+	/* Caution: the write order is important here, set the base address with
+	   the "ownership" bits last */
+
+	priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len);
+	priv->tx_ring[entry]->TMD3 = 0x0000;
+	memcpyw(priv->tx_buff[entry], (u_short *)skb->data, len);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_DEBUG, "tx_buff: ", DUMP_PREFIX_OFFSET, 16, 1,
+		       (void *)priv->tx_buff[entry],
+		       skb->len > 64 ? 64 : skb->len, true);
+#endif
+
+	priv->tx_ring[entry]->TMD1 = (priv->tx_ring[entry]->TMD1 & 0xff00)
+		| TF_OWN | TF_STP | TF_ENP;
+
+	dev_kfree_skb(skb);
+
+	priv->cur_tx++;
+	if ((priv->cur_tx >= TX_RING_SIZE) &&
+	    (priv->dirty_tx >= TX_RING_SIZE)) {
+
+		netdev_dbg(dev, "*** Subtracting TX_RING_SIZE from cur_tx (%d) and dirty_tx (%d)\n",
+			   priv->cur_tx, priv->dirty_tx);
+
+		priv->cur_tx -= TX_RING_SIZE;
+		priv->dirty_tx -= TX_RING_SIZE;
+	}
+	dev->stats.tx_bytes += len;
+
+	/* Trigger an immediate send poll */
+	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
+	lance->RDP = INEA | TDMD;
+
+	if (lowb(priv->tx_ring[(entry + 1) % TX_RING_SIZE]->TMD1) != 0) {
+		netif_stop_queue(dev);
+		priv->tx_full = 1;
+	}
+	local_irq_restore(flags);
+
+	return NETDEV_TX_OK;
+}
+
+static struct net_device_stats *ariadne_get_stats(struct net_device *dev)
+{
+	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+	short saved_addr;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	saved_addr = lance->RAP;
+	lance->RAP = CSR112;		/* Missed Frame Count */
+	dev->stats.rx_missed_errors = swapw(lance->RDP);
+	lance->RAP = saved_addr;
+	local_irq_restore(flags);
+
+	return &dev->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+ * num_addrs == -1	Promiscuous mode, receive all packets
+ * num_addrs == 0	Normal mode, clear multicast list
+ * num_addrs > 0	Multicast mode, receive normal and MC packets,
+ * 			and do best-effort filtering.
+ */
+static void set_multicast_list(struct net_device *dev)
+{
+	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+
+	if (!netif_running(dev))
+		return;
+
+	netif_stop_queue(dev);
+
+	/* We take the simple way out and always enable promiscuous mode */
+	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
+	lance->RDP = STOP;		/* Temporarily stop the lance */
+	ariadne_init_ring(dev);
+
+	if (dev->flags & IFF_PROMISC) {
+		lance->RAP = CSR15;	/* Mode Register */
+		lance->RDP = PROM;	/* Set promiscuous mode */
+	} else {
+		short multicast_table[4];
+		int num_addrs = netdev_mc_count(dev);
+		int i;
+		/* We don't use the multicast table,
+		 * but rely on upper-layer filtering
+		 */
+		memset(multicast_table, (num_addrs == 0) ? 0 : -1,
+		       sizeof(multicast_table));
+		for (i = 0; i < 4; i++) {
+			lance->RAP = CSR8 + (i << 8);
+					/* Logical Address Filter */
+			lance->RDP = swapw(multicast_table[i]);
+		}
+		lance->RAP = CSR15;	/* Mode Register */
+		lance->RDP = 0x0000;	/* Unset promiscuous mode */
+	}
+
+	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
+	lance->RDP = INEA | STRT | IDON;/* Resume normal operation */
+
+	netif_wake_queue(dev);
+}
+
+
+static void __devexit ariadne_remove_one(struct zorro_dev *z)
+{
+	struct net_device *dev = zorro_get_drvdata(z);
+
+	unregister_netdev(dev);
+	release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960));
+	release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE);
+	free_netdev(dev);
+}
+
+static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = {
+	{ ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl);
+
+static const struct net_device_ops ariadne_netdev_ops = {
+	.ndo_open		= ariadne_open,
+	.ndo_stop		= ariadne_close,
+	.ndo_start_xmit		= ariadne_start_xmit,
+	.ndo_tx_timeout		= ariadne_tx_timeout,
+	.ndo_get_stats		= ariadne_get_stats,
+	.ndo_set_rx_mode	= set_multicast_list,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
+static int __devinit ariadne_init_one(struct zorro_dev *z,
+				      const struct zorro_device_id *ent)
+{
+	unsigned long board = z->resource.start;
+	unsigned long base_addr = board + ARIADNE_LANCE;
+	unsigned long mem_start = board + ARIADNE_RAM;
+	struct resource *r1, *r2;
+	struct net_device *dev;
+	struct ariadne_private *priv;
+	int err;
+
+	r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960");
+	if (!r1)
+		return -EBUSY;
+	r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM");
+	if (!r2) {
+		release_mem_region(base_addr, sizeof(struct Am79C960));
+		return -EBUSY;
+	}
+
+	dev = alloc_etherdev(sizeof(struct ariadne_private));
+	if (dev == NULL) {
+		release_mem_region(base_addr, sizeof(struct Am79C960));
+		release_mem_region(mem_start, ARIADNE_RAM_SIZE);
+		return -ENOMEM;
+	}
+
+	priv = netdev_priv(dev);
+
+	r1->name = dev->name;
+	r2->name = dev->name;
+
+	dev->dev_addr[0] = 0x00;
+	dev->dev_addr[1] = 0x60;
+	dev->dev_addr[2] = 0x30;
+	dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff;
+	dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff;
+	dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
+	dev->base_addr = ZTWO_VADDR(base_addr);
+	dev->mem_start = ZTWO_VADDR(mem_start);
+	dev->mem_end = dev->mem_start + ARIADNE_RAM_SIZE;
+
+	dev->netdev_ops = &ariadne_netdev_ops;
+	dev->watchdog_timeo = 5 * HZ;
+
+	err = register_netdev(dev);
+	if (err) {
+		release_mem_region(base_addr, sizeof(struct Am79C960));
+		release_mem_region(mem_start, ARIADNE_RAM_SIZE);
+		free_netdev(dev);
+		return err;
+	}
+	zorro_set_drvdata(z, dev);
+
+	netdev_info(dev, "Ariadne at 0x%08lx, Ethernet Address %pM\n",
+		    board, dev->dev_addr);
+
+	return 0;
+}
+
+static struct zorro_driver ariadne_driver = {
+	.name		= "ariadne",
+	.id_table	= ariadne_zorro_tbl,
+	.probe		= ariadne_init_one,
+	.remove		= __devexit_p(ariadne_remove_one),
+};
+
+static int __init ariadne_init_module(void)
+{
+	return zorro_register_driver(&ariadne_driver);
+}
+
+static void __exit ariadne_cleanup_module(void)
+{
+	zorro_unregister_driver(&ariadne_driver);
+}
+
+module_init(ariadne_init_module);
+module_exit(ariadne_cleanup_module);
+
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/ariadne.h linux-libre-3.2-gnu/drivers/net/ethernet/amd/ariadne.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/ariadne.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/ariadne.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,415 @@
+/*
+ *  Amiga Linux/m68k Ariadne Ethernet Driver
+ *
+ *  Â© Copyright 1995 by Geert Uytterhoeven (geert@linux-m68k.org)
+ *			Peter De Schrijver
+ *		       (Peter.DeSchrijver@linux.cc.kuleuven.ac.be)
+ *
+ *  ----------------------------------------------------------------------------------
+ *
+ *  This program is based on
+ *
+ *	lance.c:	An AMD LANCE ethernet driver for linux.
+ *			Written 1993-94 by Donald Becker.
+ *
+ *	Am79C960:	PCnet(tm)-ISA Single-Chip Ethernet Controller
+ *			Advanced Micro Devices
+ *			Publication #16907, Rev. B, Amendment/0, May 1994
+ *
+ *	MC68230:	Parallel Interface/Timer (PI/T)
+ *			Motorola Semiconductors, December, 1983
+ *
+ *  ----------------------------------------------------------------------------------
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of the Linux
+ *  distribution for more details.
+ *
+ *  ----------------------------------------------------------------------------------
+ *
+ *  The Ariadne is a Zorro-II board made by Village Tronic. It contains:
+ *
+ *	- an Am79C960 PCnet-ISA Single-Chip Ethernet Controller with both
+ *	  10BASE-2 (thin coax) and 10BASE-T (UTP) connectors
+ *
+ *	- an MC68230 Parallel Interface/Timer configured as 2 parallel ports
+ */
+
+
+    /*
+     *	Am79C960 PCnet-ISA
+     */
+
+struct Am79C960 {
+    volatile u_short AddressPROM[8];
+				/* IEEE Address PROM (Unused in the Ariadne) */
+    volatile u_short RDP;	/* Register Data Port */
+    volatile u_short RAP;	/* Register Address Port */
+    volatile u_short Reset;	/* Reset Chip on Read Access */
+    volatile u_short IDP;	/* ISACSR Data Port */
+};
+
+
+    /*
+     *	Am79C960 Control and Status Registers
+     *
+     *	These values are already swap()ed!!
+     *
+     *	Only registers marked with a `-' are intended for network software
+     *	access
+     */
+
+#define CSR0		0x0000	/* - PCnet-ISA Controller Status */
+#define CSR1		0x0100	/* - IADR[15:0] */
+#define CSR2		0x0200	/* - IADR[23:16] */
+#define CSR3		0x0300	/* - Interrupt Masks and Deferral Control */
+#define CSR4		0x0400	/* - Test and Features Control */
+#define CSR6		0x0600	/*   RCV/XMT Descriptor Table Length */
+#define CSR8		0x0800	/* - Logical Address Filter, LADRF[15:0] */
+#define CSR9		0x0900	/* - Logical Address Filter, LADRF[31:16] */
+#define CSR10		0x0a00	/* - Logical Address Filter, LADRF[47:32] */
+#define CSR11		0x0b00	/* - Logical Address Filter, LADRF[63:48] */
+#define CSR12		0x0c00	/* - Physical Address Register, PADR[15:0] */
+#define CSR13		0x0d00	/* - Physical Address Register, PADR[31:16] */
+#define CSR14		0x0e00	/* - Physical Address Register, PADR[47:32] */
+#define CSR15		0x0f00	/* - Mode Register */
+#define CSR16		0x1000	/*   Initialization Block Address Lower */
+#define CSR17		0x1100	/*   Initialization Block Address Upper */
+#define CSR18		0x1200	/*   Current Receive Buffer Address */
+#define CSR19		0x1300	/*   Current Receive Buffer Address */
+#define CSR20		0x1400	/*   Current Transmit Buffer Address */
+#define CSR21		0x1500	/*   Current Transmit Buffer Address */
+#define CSR22		0x1600	/*   Next Receive Buffer Address */
+#define CSR23		0x1700	/*   Next Receive Buffer Address */
+#define CSR24		0x1800	/* - Base Address of Receive Ring */
+#define CSR25		0x1900	/* - Base Address of Receive Ring */
+#define CSR26		0x1a00	/*   Next Receive Descriptor Address */
+#define CSR27		0x1b00	/*   Next Receive Descriptor Address */
+#define CSR28		0x1c00	/*   Current Receive Descriptor Address */
+#define CSR29		0x1d00	/*   Current Receive Descriptor Address */
+#define CSR30		0x1e00	/* - Base Address of Transmit Ring */
+#define CSR31		0x1f00	/* - Base Address of transmit Ring */
+#define CSR32		0x2000	/*   Next Transmit Descriptor Address */
+#define CSR33		0x2100	/*   Next Transmit Descriptor Address */
+#define CSR34		0x2200	/*   Current Transmit Descriptor Address */
+#define CSR35		0x2300	/*   Current Transmit Descriptor Address */
+#define CSR36		0x2400	/*   Next Next Receive Descriptor Address */
+#define CSR37		0x2500	/*   Next Next Receive Descriptor Address */
+#define CSR38		0x2600	/*   Next Next Transmit Descriptor Address */
+#define CSR39		0x2700	/*   Next Next Transmit Descriptor Address */
+#define CSR40		0x2800	/*   Current Receive Status and Byte Count */
+#define CSR41		0x2900	/*   Current Receive Status and Byte Count */
+#define CSR42		0x2a00	/*   Current Transmit Status and Byte Count */
+#define CSR43		0x2b00	/*   Current Transmit Status and Byte Count */
+#define CSR44		0x2c00	/*   Next Receive Status and Byte Count */
+#define CSR45		0x2d00	/*   Next Receive Status and Byte Count */
+#define CSR46		0x2e00	/*   Poll Time Counter */
+#define CSR47		0x2f00	/*   Polling Interval */
+#define CSR48		0x3000	/*   Temporary Storage */
+#define CSR49		0x3100	/*   Temporary Storage */
+#define CSR50		0x3200	/*   Temporary Storage */
+#define CSR51		0x3300	/*   Temporary Storage */
+#define CSR52		0x3400	/*   Temporary Storage */
+#define CSR53		0x3500	/*   Temporary Storage */
+#define CSR54		0x3600	/*   Temporary Storage */
+#define CSR55		0x3700	/*   Temporary Storage */
+#define CSR56		0x3800	/*   Temporary Storage */
+#define CSR57		0x3900	/*   Temporary Storage */
+#define CSR58		0x3a00	/*   Temporary Storage */
+#define CSR59		0x3b00	/*   Temporary Storage */
+#define CSR60		0x3c00	/*   Previous Transmit Descriptor Address */
+#define CSR61		0x3d00	/*   Previous Transmit Descriptor Address */
+#define CSR62		0x3e00	/*   Previous Transmit Status and Byte Count */
+#define CSR63		0x3f00	/*   Previous Transmit Status and Byte Count */
+#define CSR64		0x4000	/*   Next Transmit Buffer Address */
+#define CSR65		0x4100	/*   Next Transmit Buffer Address */
+#define CSR66		0x4200	/*   Next Transmit Status and Byte Count */
+#define CSR67		0x4300	/*   Next Transmit Status and Byte Count */
+#define CSR68		0x4400	/*   Transmit Status Temporary Storage */
+#define CSR69		0x4500	/*   Transmit Status Temporary Storage */
+#define CSR70		0x4600	/*   Temporary Storage */
+#define CSR71		0x4700	/*   Temporary Storage */
+#define CSR72		0x4800	/*   Receive Ring Counter */
+#define CSR74		0x4a00	/*   Transmit Ring Counter */
+#define CSR76		0x4c00	/* - Receive Ring Length */
+#define CSR78		0x4e00	/* - Transmit Ring Length */
+#define CSR80		0x5000	/* - Burst and FIFO Threshold Control */
+#define CSR82		0x5200	/* - Bus Activity Timer */
+#define CSR84		0x5400	/*   DMA Address */
+#define CSR85		0x5500	/*   DMA Address */
+#define CSR86		0x5600	/*   Buffer Byte Counter */
+#define CSR88		0x5800	/* - Chip ID */
+#define CSR89		0x5900	/* - Chip ID */
+#define CSR92		0x5c00	/*   Ring Length Conversion */
+#define CSR94		0x5e00	/*   Transmit Time Domain Reflectometry Count */
+#define CSR96		0x6000	/*   Bus Interface Scratch Register 0 */
+#define CSR97		0x6100	/*   Bus Interface Scratch Register 0 */
+#define CSR98		0x6200	/*   Bus Interface Scratch Register 1 */
+#define CSR99		0x6300	/*   Bus Interface Scratch Register 1 */
+#define CSR104		0x6800	/*   SWAP */
+#define CSR105		0x6900	/*   SWAP */
+#define CSR108		0x6c00	/*   Buffer Management Scratch */
+#define CSR109		0x6d00	/*   Buffer Management Scratch */
+#define CSR112		0x7000	/* - Missed Frame Count */
+#define CSR114		0x7200	/* - Receive Collision Count */
+#define CSR124		0x7c00	/* - Buffer Management Unit Test */
+
+
+    /*
+     *	Am79C960 ISA Control and Status Registers
+     *
+     *	These values are already swap()ed!!
+     */
+
+#define ISACSR0		0x0000	/* Master Mode Read Active */
+#define ISACSR1		0x0100	/* Master Mode Write Active */
+#define ISACSR2		0x0200	/* Miscellaneous Configuration */
+#define ISACSR4		0x0400	/* LED0 Status (Link Integrity) */
+#define ISACSR5		0x0500	/* LED1 Status */
+#define ISACSR6		0x0600	/* LED2 Status */
+#define ISACSR7		0x0700	/* LED3 Status */
+
+
+    /*
+     *	Bit definitions for CSR0 (PCnet-ISA Controller Status)
+     *
+     *	These values are already swap()ed!!
+     */
+
+#define ERR		0x0080	/* Error */
+#define BABL		0x0040	/* Babble: Transmitted too many bits */
+#define CERR		0x0020	/* No Heartbeat (10BASE-T) */
+#define MISS		0x0010	/* Missed Frame */
+#define MERR		0x0008	/* Memory Error */
+#define RINT		0x0004	/* Receive Interrupt */
+#define TINT		0x0002	/* Transmit Interrupt */
+#define IDON		0x0001	/* Initialization Done */
+#define INTR		0x8000	/* Interrupt Flag */
+#define INEA		0x4000	/* Interrupt Enable */
+#define RXON		0x2000	/* Receive On */
+#define TXON		0x1000	/* Transmit On */
+#define TDMD		0x0800	/* Transmit Demand */
+#define STOP		0x0400	/* Stop */
+#define STRT		0x0200	/* Start */
+#define INIT		0x0100	/* Initialize */
+
+
+    /*
+     *	Bit definitions for CSR3 (Interrupt Masks and Deferral Control)
+     *
+     *	These values are already swap()ed!!
+     */
+
+#define BABLM		0x0040	/* Babble Mask */
+#define MISSM		0x0010	/* Missed Frame Mask */
+#define MERRM		0x0008	/* Memory Error Mask */
+#define RINTM		0x0004	/* Receive Interrupt Mask */
+#define TINTM		0x0002	/* Transmit Interrupt Mask */
+#define IDONM		0x0001	/* Initialization Done Mask */
+#define DXMT2PD		0x1000	/* Disable Transmit Two Part Deferral */
+#define EMBA		0x0800	/* Enable Modified Back-off Algorithm */
+
+
+    /*
+     *	Bit definitions for CSR4 (Test and Features Control)
+     *
+     *	These values are already swap()ed!!
+     */
+
+#define ENTST		0x0080	/* Enable Test Mode */
+#define DMAPLUS		0x0040	/* Disable Burst Transaction Counter */
+#define TIMER		0x0020	/* Timer Enable Register */
+#define DPOLL		0x0010	/* Disable Transmit Polling */
+#define APAD_XMT	0x0008	/* Auto Pad Transmit */
+#define ASTRP_RCV	0x0004	/* Auto Pad Stripping */
+#define MFCO		0x0002	/* Missed Frame Counter Overflow Interrupt */
+#define MFCOM		0x0001	/* Missed Frame Counter Overflow Mask */
+#define RCVCCO		0x2000	/* Receive Collision Counter Overflow Interrupt */
+#define RCVCCOM		0x1000	/* Receive Collision Counter Overflow Mask */
+#define TXSTRT		0x0800	/* Transmit Start Status */
+#define TXSTRTM		0x0400	/* Transmit Start Mask */
+#define JAB		0x0200	/* Jabber Error */
+#define JABM		0x0100	/* Jabber Error Mask */
+
+
+    /*
+     *	Bit definitions for CSR15 (Mode Register)
+     *
+     *	These values are already swap()ed!!
+     */
+
+#define PROM		0x0080	/* Promiscuous Mode */
+#define DRCVBC		0x0040	/* Disable Receive Broadcast */
+#define DRCVPA		0x0020	/* Disable Receive Physical Address */
+#define DLNKTST		0x0010	/* Disable Link Status */
+#define DAPC		0x0008	/* Disable Automatic Polarity Correction */
+#define MENDECL		0x0004	/* MENDEC Loopback Mode */
+#define LRTTSEL		0x0002	/* Low Receive Threshold/Transmit Mode Select */
+#define PORTSEL1	0x0001	/* Port Select Bits */
+#define PORTSEL2	0x8000	/* Port Select Bits */
+#define INTL		0x4000	/* Internal Loopback */
+#define DRTY		0x2000	/* Disable Retry */
+#define FCOLL		0x1000	/* Force Collision */
+#define DXMTFCS		0x0800	/* Disable Transmit CRC */
+#define LOOP		0x0400	/* Loopback Enable */
+#define DTX		0x0200	/* Disable Transmitter */
+#define DRX		0x0100	/* Disable Receiver */
+
+
+    /*
+     *	Bit definitions for ISACSR2 (Miscellaneous Configuration)
+     *
+     *	These values are already swap()ed!!
+     */
+
+#define ASEL		0x0200	/* Media Interface Port Auto Select */
+
+
+    /*
+     *	Bit definitions for ISACSR5-7 (LED1-3 Status)
+     *
+     *	These values are already swap()ed!!
+     */
+
+#define LEDOUT		0x0080	/* Current LED Status */
+#define PSE		0x8000	/* Pulse Stretcher Enable */
+#define XMTE		0x1000	/* Enable Transmit Status Signal */
+#define RVPOLE		0x0800	/* Enable Receive Polarity Signal */
+#define RCVE		0x0400	/* Enable Receive Status Signal */
+#define JABE		0x0200	/* Enable Jabber Signal */
+#define COLE		0x0100	/* Enable Collision Signal */
+
+
+    /*
+     *	Receive Descriptor Ring Entry
+     */
+
+struct RDRE {
+    volatile u_short RMD0;	/* LADR[15:0] */
+    volatile u_short RMD1;	/* HADR[23:16] | Receive Flags */
+    volatile u_short RMD2;	/* Buffer Byte Count (two's complement) */
+    volatile u_short RMD3;	/* Message Byte Count */
+};
+
+
+    /*
+     *	Transmit Descriptor Ring Entry
+     */
+
+struct TDRE {
+    volatile u_short TMD0;	/* LADR[15:0] */
+    volatile u_short TMD1;	/* HADR[23:16] | Transmit Flags */
+    volatile u_short TMD2;	/* Buffer Byte Count (two's complement) */
+    volatile u_short TMD3;	/* Error Flags */
+};
+
+
+    /*
+     *	Receive Flags
+     */
+
+#define RF_OWN		0x0080	/* PCnet-ISA controller owns the descriptor */
+#define RF_ERR		0x0040	/* Error */
+#define RF_FRAM		0x0020	/* Framing Error */
+#define RF_OFLO		0x0010	/* Overflow Error */
+#define RF_CRC		0x0008	/* CRC Error */
+#define RF_BUFF		0x0004	/* Buffer Error */
+#define RF_STP		0x0002	/* Start of Packet */
+#define RF_ENP		0x0001	/* End of Packet */
+
+
+    /*
+     *	Transmit Flags
+     */
+
+#define TF_OWN		0x0080	/* PCnet-ISA controller owns the descriptor */
+#define TF_ERR		0x0040	/* Error */
+#define TF_ADD_FCS	0x0020	/* Controls FCS Generation */
+#define TF_MORE		0x0010	/* More than one retry needed */
+#define TF_ONE		0x0008	/* One retry needed */
+#define TF_DEF		0x0004	/* Deferred */
+#define TF_STP		0x0002	/* Start of Packet */
+#define TF_ENP		0x0001	/* End of Packet */
+
+
+    /*
+     *	Error Flags
+     */
+
+#define EF_BUFF		0x0080	/* Buffer Error */
+#define EF_UFLO		0x0040	/* Underflow Error */
+#define EF_LCOL		0x0010	/* Late Collision */
+#define EF_LCAR		0x0008	/* Loss of Carrier */
+#define EF_RTRY		0x0004	/* Retry Error */
+#define EF_TDR		0xff03	/* Time Domain Reflectometry */
+
+
+
+    /*
+     *	MC68230 Parallel Interface/Timer
+     */
+
+struct MC68230 {
+    volatile u_char PGCR;	/* Port General Control Register */
+    u_char Pad1[1];
+    volatile u_char PSRR;	/* Port Service Request Register */
+    u_char Pad2[1];
+    volatile u_char PADDR;	/* Port A Data Direction Register */
+    u_char Pad3[1];
+    volatile u_char PBDDR;	/* Port B Data Direction Register */
+    u_char Pad4[1];
+    volatile u_char PCDDR;	/* Port C Data Direction Register */
+    u_char Pad5[1];
+    volatile u_char PIVR;	/* Port Interrupt Vector Register */
+    u_char Pad6[1];
+    volatile u_char PACR;	/* Port A Control Register */
+    u_char Pad7[1];
+    volatile u_char PBCR;	/* Port B Control Register */
+    u_char Pad8[1];
+    volatile u_char PADR;	/* Port A Data Register */
+    u_char Pad9[1];
+    volatile u_char PBDR;	/* Port B Data Register */
+    u_char Pad10[1];
+    volatile u_char PAAR;	/* Port A Alternate Register */
+    u_char Pad11[1];
+    volatile u_char PBAR;	/* Port B Alternate Register */
+    u_char Pad12[1];
+    volatile u_char PCDR;	/* Port C Data Register */
+    u_char Pad13[1];
+    volatile u_char PSR;	/* Port Status Register */
+    u_char Pad14[5];
+    volatile u_char TCR;	/* Timer Control Register */
+    u_char Pad15[1];
+    volatile u_char TIVR;	/* Timer Interrupt Vector Register */
+    u_char Pad16[3];
+    volatile u_char CPRH;	/* Counter Preload Register (High) */
+    u_char Pad17[1];
+    volatile u_char CPRM;	/* Counter Preload Register (Mid) */
+    u_char Pad18[1];
+    volatile u_char CPRL;	/* Counter Preload Register (Low) */
+    u_char Pad19[3];
+    volatile u_char CNTRH;	/* Count Register (High) */
+    u_char Pad20[1];
+    volatile u_char CNTRM;	/* Count Register (Mid) */
+    u_char Pad21[1];
+    volatile u_char CNTRL;	/* Count Register (Low) */
+    u_char Pad22[1];
+    volatile u_char TSR;	/* Timer Status Register */
+    u_char Pad23[11];
+};
+
+
+    /*
+     *	Ariadne Expansion Board Structure
+     */
+
+#define ARIADNE_LANCE		0x360
+
+#define ARIADNE_PIT		0x1000
+
+#define ARIADNE_BOOTPROM	0x4000	/* I guess it's here :-) */
+#define ARIADNE_BOOTPROM_SIZE	0x4000
+
+#define ARIADNE_RAM		0x8000	/* Always access WORDs!! */
+#define ARIADNE_RAM_SIZE	0x8000
+
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/atarilance.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/atarilance.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/atarilance.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/atarilance.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1176 @@
+/* atarilance.c: Ethernet driver for VME Lance cards on the Atari */
+/*
+	Written 1995/96 by Roman Hodek (Roman.Hodek@informatik.uni-erlangen.de)
+
+	This software may be used and distributed according to the terms
+	of the GNU General Public License, incorporated herein by reference.
+
+	This drivers was written with the following sources of reference:
+	 - The driver for the Riebl Lance card by the TU Vienna.
+	 - The modified TUW driver for PAM's VME cards
+	 - The PC-Linux driver for Lance cards (but this is for bus master
+       cards, not the shared memory ones)
+	 - The Amiga Ariadne driver
+
+	v1.0: (in 1.2.13pl4/0.9.13)
+	      Initial version
+	v1.1: (in 1.2.13pl5)
+	      more comments
+		  deleted some debugging stuff
+		  optimized register access (keep AREG pointing to CSR0)
+		  following AMD, CSR0_STRT should be set only after IDON is detected
+		  use memcpy() for data transfers, that also employs long word moves
+		  better probe procedure for 24-bit systems
+          non-VME-RieblCards need extra delays in memcpy
+		  must also do write test, since 0xfxe00000 may hit ROM
+		  use 8/32 tx/rx buffers, which should give better NFS performance;
+		    this is made possible by shifting the last packet buffer after the
+		    RieblCard reserved area
+    v1.2: (in 1.2.13pl8)
+	      again fixed probing for the Falcon; 0xfe01000 hits phys. 0x00010000
+		  and thus RAM, in case of no Lance found all memory contents have to
+		  be restored!
+		  Now possible to compile as module.
+	v1.3: 03/30/96 Jes Sorensen, Roman (in 1.3)
+	      Several little 1.3 adaptions
+		  When the lance is stopped it jumps back into little-endian
+		  mode. It is therefore necessary to put it back where it
+		  belongs, in big endian mode, in order to make things work.
+		  This might be the reason why multicast-mode didn't work
+		  before, but I'm not able to test it as I only got an Amiga
+		  (we had similar problems with the A2065 driver).
+
+*/
+
+static char version[] = "atarilance.c: v1.3 04/04/96 "
+					   "Roman.Hodek@informatik.uni-erlangen.de\n";
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/atarihw.h>
+#include <asm/atariints.h>
+#include <asm/io.h>
+
+/* Debug level:
+ *  0 = silent, print only serious errors
+ *  1 = normal, print error messages
+ *  2 = debug, print debug infos
+ *  3 = debug, print even more debug infos (packet data)
+ */
+
+#define	LANCE_DEBUG	1
+
+#ifdef LANCE_DEBUG
+static int lance_debug = LANCE_DEBUG;
+#else
+static int lance_debug = 1;
+#endif
+module_param(lance_debug, int, 0);
+MODULE_PARM_DESC(lance_debug, "atarilance debug level (0-3)");
+MODULE_LICENSE("GPL");
+
+/* Print debug messages on probing? */
+#undef LANCE_DEBUG_PROBE
+
+#define	DPRINTK(n,a)							\
+	do {										\
+		if (lance_debug >= n)					\
+			printk a;							\
+	} while( 0 )
+
+#ifdef LANCE_DEBUG_PROBE
+# define PROBE_PRINT(a)	printk a
+#else
+# define PROBE_PRINT(a)
+#endif
+
+/* These define the number of Rx and Tx buffers as log2. (Only powers
+ * of two are valid)
+ * Much more rx buffers (32) are reserved than tx buffers (8), since receiving
+ * is more time critical then sending and packets may have to remain in the
+ * board's memory when main memory is low.
+ */
+
+#define TX_LOG_RING_SIZE			3
+#define RX_LOG_RING_SIZE			5
+
+/* These are the derived values */
+
+#define TX_RING_SIZE			(1 << TX_LOG_RING_SIZE)
+#define TX_RING_LEN_BITS		(TX_LOG_RING_SIZE << 5)
+#define	TX_RING_MOD_MASK		(TX_RING_SIZE - 1)
+
+#define RX_RING_SIZE			(1 << RX_LOG_RING_SIZE)
+#define RX_RING_LEN_BITS		(RX_LOG_RING_SIZE << 5)
+#define	RX_RING_MOD_MASK		(RX_RING_SIZE - 1)
+
+#define TX_TIMEOUT	(HZ/5)
+
+/* The LANCE Rx and Tx ring descriptors. */
+struct lance_rx_head {
+	unsigned short			base;		/* Low word of base addr */
+	volatile unsigned char	flag;
+	unsigned char			base_hi;	/* High word of base addr (unused) */
+	short					buf_length;	/* This length is 2s complement! */
+	volatile short			msg_length;	/* This length is "normal". */
+};
+
+struct lance_tx_head {
+	unsigned short			base;		/* Low word of base addr */
+	volatile unsigned char	flag;
+	unsigned char			base_hi;	/* High word of base addr (unused) */
+	short					length;		/* Length is 2s complement! */
+	volatile short			misc;
+};
+
+struct ringdesc {
+	unsigned short	adr_lo;		/* Low 16 bits of address */
+	unsigned char	len;		/* Length bits */
+	unsigned char	adr_hi;		/* High 8 bits of address (unused) */
+};
+
+/* The LANCE initialization block, described in databook. */
+struct lance_init_block {
+	unsigned short	mode;		/* Pre-set mode */
+	unsigned char	hwaddr[6];	/* Physical ethernet address */
+	unsigned		filter[2];	/* Multicast filter (unused). */
+	/* Receive and transmit ring base, along with length bits. */
+	struct ringdesc	rx_ring;
+	struct ringdesc	tx_ring;
+};
+
+/* The whole layout of the Lance shared memory */
+struct lance_memory {
+	struct lance_init_block	init;
+	struct lance_tx_head	tx_head[TX_RING_SIZE];
+	struct lance_rx_head	rx_head[RX_RING_SIZE];
+	char					packet_area[0];	/* packet data follow after the
+											 * init block and the ring
+											 * descriptors and are located
+											 * at runtime */
+};
+
+/* RieblCard specifics:
+ * The original TOS driver for these cards reserves the area from offset
+ * 0xee70 to 0xeebb for storing configuration data. Of interest to us is the
+ * Ethernet address there, and the magic for verifying the data's validity.
+ * The reserved area isn't touch by packet buffers. Furthermore, offset 0xfffe
+ * is reserved for the interrupt vector number.
+ */
+#define	RIEBL_RSVD_START	0xee70
+#define	RIEBL_RSVD_END		0xeec0
+#define RIEBL_MAGIC			0x09051990
+#define RIEBL_MAGIC_ADDR	((unsigned long *)(((char *)MEM) + 0xee8a))
+#define RIEBL_HWADDR_ADDR	((unsigned char *)(((char *)MEM) + 0xee8e))
+#define RIEBL_IVEC_ADDR		((unsigned short *)(((char *)MEM) + 0xfffe))
+
+/* This is a default address for the old RieblCards without a battery
+ * that have no ethernet address at boot time. 00:00:36:04 is the
+ * prefix for Riebl cards, the 00:00 at the end is arbitrary.
+ */
+
+static unsigned char OldRieblDefHwaddr[6] = {
+	0x00, 0x00, 0x36, 0x04, 0x00, 0x00
+};
+
+
+/* I/O registers of the Lance chip */
+
+struct lance_ioreg {
+/* base+0x0 */	volatile unsigned short	data;
+/* base+0x2 */	volatile unsigned short	addr;
+				unsigned char			_dummy1[3];
+/* base+0x7 */	volatile unsigned char	ivec;
+				unsigned char			_dummy2[5];
+/* base+0xd */	volatile unsigned char	eeprom;
+				unsigned char			_dummy3;
+/* base+0xf */	volatile unsigned char	mem;
+};
+
+/* Types of boards this driver supports */
+
+enum lance_type {
+	OLD_RIEBL,		/* old Riebl card without battery */
+	NEW_RIEBL,		/* new Riebl card with battery */
+	PAM_CARD		/* PAM card with EEPROM */
+};
+
+static char *lance_names[] = {
+	"Riebl-Card (without battery)",
+	"Riebl-Card (with battery)",
+	"PAM intern card"
+};
+
+/* The driver's private device structure */
+
+struct lance_private {
+	enum lance_type		cardtype;
+	struct lance_ioreg	*iobase;
+	struct lance_memory	*mem;
+	int		 	cur_rx, cur_tx;	/* The next free ring entry */
+	int			dirty_tx;		/* Ring entries to be freed. */
+				/* copy function */
+	void			*(*memcpy_f)( void *, const void *, size_t );
+/* This must be long for set_bit() */
+	long			tx_full;
+	spinlock_t		devlock;
+};
+
+/* I/O register access macros */
+
+#define	MEM		lp->mem
+#define	DREG	IO->data
+#define	AREG	IO->addr
+#define	REGA(a)	(*( AREG = (a), &DREG ))
+
+/* Definitions for packet buffer access: */
+#define PKT_BUF_SZ		1544
+/* Get the address of a packet buffer corresponding to a given buffer head */
+#define	PKTBUF_ADDR(head)	(((unsigned char *)(MEM)) + (head)->base)
+
+/* Possible memory/IO addresses for probing */
+
+static struct lance_addr {
+	unsigned long	memaddr;
+	unsigned long	ioaddr;
+	int				slow_flag;
+} lance_addr_list[] = {
+	{ 0xfe010000, 0xfe00fff0, 0 },	/* RieblCard VME in TT */
+	{ 0xffc10000, 0xffc0fff0, 0 },	/* RieblCard VME in MegaSTE
+									   (highest byte stripped) */
+	{ 0xffe00000, 0xffff7000, 1 },	/* RieblCard in ST
+									   (highest byte stripped) */
+	{ 0xffd00000, 0xffff7000, 1 },	/* RieblCard in ST with hw modif. to
+									   avoid conflict with ROM
+									   (highest byte stripped) */
+	{ 0xffcf0000, 0xffcffff0, 0 },	/* PAMCard VME in TT and MSTE
+									   (highest byte stripped) */
+	{ 0xfecf0000, 0xfecffff0, 0 },	/* Rhotron's PAMCard VME in TT and MSTE
+									   (highest byte stripped) */
+};
+
+#define	N_LANCE_ADDR	ARRAY_SIZE(lance_addr_list)
+
+
+/* Definitions for the Lance */
+
+/* tx_head flags */
+#define TMD1_ENP		0x01	/* end of packet */
+#define TMD1_STP		0x02	/* start of packet */
+#define TMD1_DEF		0x04	/* deferred */
+#define TMD1_ONE		0x08	/* one retry needed */
+#define TMD1_MORE		0x10	/* more than one retry needed */
+#define TMD1_ERR		0x40	/* error summary */
+#define TMD1_OWN 		0x80	/* ownership (set: chip owns) */
+
+#define TMD1_OWN_CHIP	TMD1_OWN
+#define TMD1_OWN_HOST	0
+
+/* tx_head misc field */
+#define TMD3_TDR		0x03FF	/* Time Domain Reflectometry counter */
+#define TMD3_RTRY		0x0400	/* failed after 16 retries */
+#define TMD3_LCAR		0x0800	/* carrier lost */
+#define TMD3_LCOL		0x1000	/* late collision */
+#define TMD3_UFLO		0x4000	/* underflow (late memory) */
+#define TMD3_BUFF		0x8000	/* buffering error (no ENP) */
+
+/* rx_head flags */
+#define RMD1_ENP		0x01	/* end of packet */
+#define RMD1_STP		0x02	/* start of packet */
+#define RMD1_BUFF		0x04	/* buffer error */
+#define RMD1_CRC		0x08	/* CRC error */
+#define RMD1_OFLO		0x10	/* overflow */
+#define RMD1_FRAM		0x20	/* framing error */
+#define RMD1_ERR		0x40	/* error summary */
+#define RMD1_OWN 		0x80	/* ownership (set: ship owns) */
+
+#define RMD1_OWN_CHIP	RMD1_OWN
+#define RMD1_OWN_HOST	0
+
+/* register names */
+#define CSR0	0		/* mode/status */
+#define CSR1	1		/* init block addr (low) */
+#define CSR2	2		/* init block addr (high) */
+#define CSR3	3		/* misc */
+#define CSR8	8	  	/* address filter */
+#define CSR15	15		/* promiscuous mode */
+
+/* CSR0 */
+/* (R=readable, W=writeable, S=set on write, C=clear on write) */
+#define CSR0_INIT	0x0001		/* initialize (RS) */
+#define CSR0_STRT	0x0002		/* start (RS) */
+#define CSR0_STOP	0x0004		/* stop (RS) */
+#define CSR0_TDMD	0x0008		/* transmit demand (RS) */
+#define CSR0_TXON	0x0010		/* transmitter on (R) */
+#define CSR0_RXON	0x0020		/* receiver on (R) */
+#define CSR0_INEA	0x0040		/* interrupt enable (RW) */
+#define CSR0_INTR	0x0080		/* interrupt active (R) */
+#define CSR0_IDON	0x0100		/* initialization done (RC) */
+#define CSR0_TINT	0x0200		/* transmitter interrupt (RC) */
+#define CSR0_RINT	0x0400		/* receiver interrupt (RC) */
+#define CSR0_MERR	0x0800		/* memory error (RC) */
+#define CSR0_MISS	0x1000		/* missed frame (RC) */
+#define CSR0_CERR	0x2000		/* carrier error (no heartbeat :-) (RC) */
+#define CSR0_BABL	0x4000		/* babble: tx-ed too many bits (RC) */
+#define CSR0_ERR	0x8000		/* error (RC) */
+
+/* CSR3 */
+#define CSR3_BCON	0x0001		/* byte control */
+#define CSR3_ACON	0x0002		/* ALE control */
+#define CSR3_BSWP	0x0004		/* byte swap (1=big endian) */
+
+
+
+/***************************** Prototypes *****************************/
+
+static unsigned long lance_probe1( struct net_device *dev, struct lance_addr
+                                   *init_rec );
+static int lance_open( struct net_device *dev );
+static void lance_init_ring( struct net_device *dev );
+static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev );
+static irqreturn_t lance_interrupt( int irq, void *dev_id );
+static int lance_rx( struct net_device *dev );
+static int lance_close( struct net_device *dev );
+static void set_multicast_list( struct net_device *dev );
+static int lance_set_mac_address( struct net_device *dev, void *addr );
+static void lance_tx_timeout (struct net_device *dev);
+
+/************************* End of Prototypes **************************/
+
+
+
+
+
+static void *slow_memcpy( void *dst, const void *src, size_t len )
+
+{	char *cto = dst;
+	const char *cfrom = src;
+
+	while( len-- ) {
+		*cto++ = *cfrom++;
+		MFPDELAY();
+	}
+	return dst;
+}
+
+
+struct net_device * __init atarilance_probe(int unit)
+{
+	int i;
+	static int found;
+	struct net_device *dev;
+	int err = -ENODEV;
+
+	if (!MACH_IS_ATARI || found)
+		/* Assume there's only one board possible... That seems true, since
+		 * the Riebl/PAM board's address cannot be changed. */
+		return ERR_PTR(-ENODEV);
+
+	dev = alloc_etherdev(sizeof(struct lance_private));
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+	if (unit >= 0) {
+		sprintf(dev->name, "eth%d", unit);
+		netdev_boot_setup_check(dev);
+	}
+
+	for( i = 0; i < N_LANCE_ADDR; ++i ) {
+		if (lance_probe1( dev, &lance_addr_list[i] )) {
+			found = 1;
+			err = register_netdev(dev);
+			if (!err)
+				return dev;
+			free_irq(dev->irq, dev);
+			break;
+		}
+	}
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+
+
+/* Derived from hwreg_present() in atari/config.c: */
+
+static noinline int __init addr_accessible(volatile void *regp, int wordflag,
+					   int writeflag)
+{
+	int		ret;
+	unsigned long	flags;
+	long	*vbr, save_berr;
+
+	local_irq_save(flags);
+
+	__asm__ __volatile__ ( "movec	%/vbr,%0" : "=r" (vbr) : );
+	save_berr = vbr[2];
+
+	__asm__ __volatile__
+	(	"movel	%/sp,%/d1\n\t"
+		"movel	#Lberr,%2@\n\t"
+		"moveq	#0,%0\n\t"
+		"tstl   %3\n\t"
+		"bne	1f\n\t"
+		"moveb	%1@,%/d0\n\t"
+		"nop	\n\t"
+		"bra	2f\n"
+"1:		 movew	%1@,%/d0\n\t"
+		"nop	\n"
+"2:		 tstl   %4\n\t"
+		"beq	2f\n\t"
+		"tstl	%3\n\t"
+		"bne	1f\n\t"
+		"clrb	%1@\n\t"
+		"nop	\n\t"
+		"moveb	%/d0,%1@\n\t"
+		"nop	\n\t"
+		"bra	2f\n"
+"1:		 clrw	%1@\n\t"
+		"nop	\n\t"
+		"movew	%/d0,%1@\n\t"
+		"nop	\n"
+"2:		 moveq	#1,%0\n"
+"Lberr:	 movel	%/d1,%/sp"
+		: "=&d" (ret)
+		: "a" (regp), "a" (&vbr[2]), "rm" (wordflag), "rm" (writeflag)
+		: "d0", "d1", "memory"
+	);
+
+	vbr[2] = save_berr;
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static const struct net_device_ops lance_netdev_ops = {
+	.ndo_open		= lance_open,
+	.ndo_stop		= lance_close,
+	.ndo_start_xmit		= lance_start_xmit,
+	.ndo_set_rx_mode	= set_multicast_list,
+	.ndo_set_mac_address	= lance_set_mac_address,
+	.ndo_tx_timeout		= lance_tx_timeout,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_change_mtu		= eth_change_mtu,
+};
+
+static unsigned long __init lance_probe1( struct net_device *dev,
+					   struct lance_addr *init_rec )
+{
+	volatile unsigned short *memaddr =
+		(volatile unsigned short *)init_rec->memaddr;
+	volatile unsigned short *ioaddr =
+		(volatile unsigned short *)init_rec->ioaddr;
+	struct lance_private	*lp;
+	struct lance_ioreg		*IO;
+	int 					i;
+	static int 				did_version;
+	unsigned short			save1, save2;
+
+	PROBE_PRINT(( "Probing for Lance card at mem %#lx io %#lx\n",
+				  (long)memaddr, (long)ioaddr ));
+
+	/* Test whether memory readable and writable */
+	PROBE_PRINT(( "lance_probe1: testing memory to be accessible\n" ));
+	if (!addr_accessible( memaddr, 1, 1 )) goto probe_fail;
+
+	/* Written values should come back... */
+	PROBE_PRINT(( "lance_probe1: testing memory to be writable (1)\n" ));
+	save1 = *memaddr;
+	*memaddr = 0x0001;
+	if (*memaddr != 0x0001) goto probe_fail;
+	PROBE_PRINT(( "lance_probe1: testing memory to be writable (2)\n" ));
+	*memaddr = 0x0000;
+	if (*memaddr != 0x0000) goto probe_fail;
+	*memaddr = save1;
+
+	/* First port should be readable and writable */
+	PROBE_PRINT(( "lance_probe1: testing ioport to be accessible\n" ));
+	if (!addr_accessible( ioaddr, 1, 1 )) goto probe_fail;
+
+	/* and written values should be readable */
+	PROBE_PRINT(( "lance_probe1: testing ioport to be writeable\n" ));
+	save2 = ioaddr[1];
+	ioaddr[1] = 0x0001;
+	if (ioaddr[1] != 0x0001) goto probe_fail;
+
+	/* The CSR0_INIT bit should not be readable */
+	PROBE_PRINT(( "lance_probe1: testing CSR0 register function (1)\n" ));
+	save1 = ioaddr[0];
+	ioaddr[1] = CSR0;
+	ioaddr[0] = CSR0_INIT | CSR0_STOP;
+	if (ioaddr[0] != CSR0_STOP) {
+		ioaddr[0] = save1;
+		ioaddr[1] = save2;
+		goto probe_fail;
+	}
+	PROBE_PRINT(( "lance_probe1: testing CSR0 register function (2)\n" ));
+	ioaddr[0] = CSR0_STOP;
+	if (ioaddr[0] != CSR0_STOP) {
+		ioaddr[0] = save1;
+		ioaddr[1] = save2;
+		goto probe_fail;
+	}
+
+	/* Now ok... */
+	PROBE_PRINT(( "lance_probe1: Lance card detected\n" ));
+	goto probe_ok;
+
+  probe_fail:
+	return 0;
+
+  probe_ok:
+	lp = netdev_priv(dev);
+	MEM = (struct lance_memory *)memaddr;
+	IO = lp->iobase = (struct lance_ioreg *)ioaddr;
+	dev->base_addr = (unsigned long)ioaddr; /* informational only */
+	lp->memcpy_f = init_rec->slow_flag ? slow_memcpy : memcpy;
+
+	REGA( CSR0 ) = CSR0_STOP;
+
+	/* Now test for type: If the eeprom I/O port is readable, it is a
+	 * PAM card */
+	if (addr_accessible( &(IO->eeprom), 0, 0 )) {
+		/* Switch back to Ram */
+		i = IO->mem;
+		lp->cardtype = PAM_CARD;
+	}
+	else if (*RIEBL_MAGIC_ADDR == RIEBL_MAGIC) {
+		lp->cardtype = NEW_RIEBL;
+	}
+	else
+		lp->cardtype = OLD_RIEBL;
+
+	if (lp->cardtype == PAM_CARD ||
+		memaddr == (unsigned short *)0xffe00000) {
+		/* PAMs card and Riebl on ST use level 5 autovector */
+		if (request_irq(IRQ_AUTO_5, lance_interrupt, IRQ_TYPE_PRIO,
+		            "PAM,Riebl-ST Ethernet", dev)) {
+			printk( "Lance: request for irq %d failed\n", IRQ_AUTO_5 );
+			return 0;
+		}
+		dev->irq = (unsigned short)IRQ_AUTO_5;
+	}
+	else {
+		/* For VME-RieblCards, request a free VME int;
+		 * (This must be unsigned long, since dev->irq is short and the
+		 * IRQ_MACHSPEC bit would be cut off...)
+		 */
+		unsigned long irq = atari_register_vme_int();
+		if (!irq) {
+			printk( "Lance: request for VME interrupt failed\n" );
+			return 0;
+		}
+		if (request_irq(irq, lance_interrupt, IRQ_TYPE_PRIO,
+		            "Riebl-VME Ethernet", dev)) {
+			printk( "Lance: request for irq %ld failed\n", irq );
+			return 0;
+		}
+		dev->irq = irq;
+	}
+
+	printk("%s: %s at io %#lx, mem %#lx, irq %d%s, hwaddr ",
+		   dev->name, lance_names[lp->cardtype],
+		   (unsigned long)ioaddr,
+		   (unsigned long)memaddr,
+		   dev->irq,
+		   init_rec->slow_flag ? " (slow memcpy)" : "" );
+
+	/* Get the ethernet address */
+	switch( lp->cardtype ) {
+	  case OLD_RIEBL:
+		/* No ethernet address! (Set some default address) */
+		memcpy( dev->dev_addr, OldRieblDefHwaddr, 6 );
+		break;
+	  case NEW_RIEBL:
+		lp->memcpy_f( dev->dev_addr, RIEBL_HWADDR_ADDR, 6 );
+		break;
+	  case PAM_CARD:
+		i = IO->eeprom;
+		for( i = 0; i < 6; ++i )
+			dev->dev_addr[i] =
+				((((unsigned short *)MEM)[i*2] & 0x0f) << 4) |
+				((((unsigned short *)MEM)[i*2+1] & 0x0f));
+		i = IO->mem;
+		break;
+	}
+	printk("%pM\n", dev->dev_addr);
+	if (lp->cardtype == OLD_RIEBL) {
+		printk( "%s: Warning: This is a default ethernet address!\n",
+				dev->name );
+		printk( "      Use \"ifconfig hw ether ...\" to set the address.\n" );
+	}
+
+	spin_lock_init(&lp->devlock);
+
+	MEM->init.mode = 0x0000;		/* Disable Rx and Tx. */
+	for( i = 0; i < 6; i++ )
+		MEM->init.hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */
+	MEM->init.filter[0] = 0x00000000;
+	MEM->init.filter[1] = 0x00000000;
+	MEM->init.rx_ring.adr_lo = offsetof( struct lance_memory, rx_head );
+	MEM->init.rx_ring.adr_hi = 0;
+	MEM->init.rx_ring.len    = RX_RING_LEN_BITS;
+	MEM->init.tx_ring.adr_lo = offsetof( struct lance_memory, tx_head );
+	MEM->init.tx_ring.adr_hi = 0;
+	MEM->init.tx_ring.len    = TX_RING_LEN_BITS;
+
+	if (lp->cardtype == PAM_CARD)
+		IO->ivec = IRQ_SOURCE_TO_VECTOR(dev->irq);
+	else
+		*RIEBL_IVEC_ADDR = IRQ_SOURCE_TO_VECTOR(dev->irq);
+
+	if (did_version++ == 0)
+		DPRINTK( 1, ( version ));
+
+	dev->netdev_ops = &lance_netdev_ops;
+
+	/* XXX MSch */
+	dev->watchdog_timeo = TX_TIMEOUT;
+
+	return 1;
+}
+
+
+static int lance_open( struct net_device *dev )
+{
+	struct lance_private *lp = netdev_priv(dev);
+	struct lance_ioreg	 *IO = lp->iobase;
+	int i;
+
+	DPRINTK( 2, ( "%s: lance_open()\n", dev->name ));
+
+	lance_init_ring(dev);
+	/* Re-initialize the LANCE, and start it when done. */
+
+	REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
+	REGA( CSR2 ) = 0;
+	REGA( CSR1 ) = 0;
+	REGA( CSR0 ) = CSR0_INIT;
+	/* From now on, AREG is kept to point to CSR0 */
+
+	i = 1000000;
+	while (--i > 0)
+		if (DREG & CSR0_IDON)
+			break;
+	if (i <= 0 || (DREG & CSR0_ERR)) {
+		DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n",
+					  dev->name, i, DREG ));
+		DREG = CSR0_STOP;
+		return -EIO;
+	}
+	DREG = CSR0_IDON;
+	DREG = CSR0_STRT;
+	DREG = CSR0_INEA;
+
+	netif_start_queue (dev);
+
+	DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG ));
+
+	return 0;
+}
+
+
+/* Initialize the LANCE Rx and Tx rings. */
+
+static void lance_init_ring( struct net_device *dev )
+{
+	struct lance_private *lp = netdev_priv(dev);
+	int i;
+	unsigned offset;
+
+	lp->tx_full = 0;
+	lp->cur_rx = lp->cur_tx = 0;
+	lp->dirty_tx = 0;
+
+	offset = offsetof( struct lance_memory, packet_area );
+
+/* If the packet buffer at offset 'o' would conflict with the reserved area
+ * of RieblCards, advance it */
+#define	CHECK_OFFSET(o)														 \
+	do {																	 \
+		if (lp->cardtype == OLD_RIEBL || lp->cardtype == NEW_RIEBL) {		 \
+			if (((o) < RIEBL_RSVD_START) ? (o)+PKT_BUF_SZ > RIEBL_RSVD_START \
+										 : (o) < RIEBL_RSVD_END)			 \
+				(o) = RIEBL_RSVD_END;										 \
+		}																	 \
+	} while(0)
+
+	for( i = 0; i < TX_RING_SIZE; i++ ) {
+		CHECK_OFFSET(offset);
+		MEM->tx_head[i].base = offset;
+		MEM->tx_head[i].flag = TMD1_OWN_HOST;
+ 		MEM->tx_head[i].base_hi = 0;
+		MEM->tx_head[i].length = 0;
+		MEM->tx_head[i].misc = 0;
+		offset += PKT_BUF_SZ;
+	}
+
+	for( i = 0; i < RX_RING_SIZE; i++ ) {
+		CHECK_OFFSET(offset);
+		MEM->rx_head[i].base = offset;
+		MEM->rx_head[i].flag = TMD1_OWN_CHIP;
+		MEM->rx_head[i].base_hi = 0;
+		MEM->rx_head[i].buf_length = -PKT_BUF_SZ;
+		MEM->rx_head[i].msg_length = 0;
+		offset += PKT_BUF_SZ;
+	}
+}
+
+
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+
+
+static void lance_tx_timeout (struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	struct lance_ioreg	 *IO = lp->iobase;
+
+	AREG = CSR0;
+	DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n",
+			  dev->name, DREG ));
+	DREG = CSR0_STOP;
+	/*
+	 * Always set BSWP after a STOP as STOP puts it back into
+	 * little endian mode.
+	 */
+	REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
+	dev->stats.tx_errors++;
+#ifndef final_version
+		{	int i;
+			DPRINTK( 2, ( "Ring data: dirty_tx %d cur_tx %d%s cur_rx %d\n",
+						  lp->dirty_tx, lp->cur_tx,
+						  lp->tx_full ? " (full)" : "",
+						  lp->cur_rx ));
+			for( i = 0 ; i < RX_RING_SIZE; i++ )
+				DPRINTK( 2, ( "rx #%d: base=%04x blen=%04x mlen=%04x\n",
+							  i, MEM->rx_head[i].base,
+							  -MEM->rx_head[i].buf_length,
+							  MEM->rx_head[i].msg_length ));
+			for( i = 0 ; i < TX_RING_SIZE; i++ )
+				DPRINTK( 2, ( "tx #%d: base=%04x len=%04x misc=%04x\n",
+							  i, MEM->tx_head[i].base,
+							  -MEM->tx_head[i].length,
+							  MEM->tx_head[i].misc ));
+		}
+#endif
+	/* XXX MSch: maybe purge/reinit ring here */
+	/* lance_restart, essentially */
+	lance_init_ring(dev);
+	REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT;
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	netif_wake_queue(dev);
+}
+
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+
+static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
+{
+	struct lance_private *lp = netdev_priv(dev);
+	struct lance_ioreg	 *IO = lp->iobase;
+	int entry, len;
+	struct lance_tx_head *head;
+	unsigned long flags;
+
+	DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n",
+				  dev->name, DREG ));
+
+
+	/* The old LANCE chips doesn't automatically pad buffers to min. size. */
+	len = skb->len;
+	if (len < ETH_ZLEN)
+		len = ETH_ZLEN;
+	/* PAM-Card has a bug: Can only send packets with even number of bytes! */
+	else if (lp->cardtype == PAM_CARD && (len & 1))
+		++len;
+
+	if (len > skb->len) {
+		if (skb_padto(skb, len))
+			return NETDEV_TX_OK;
+	}
+
+	netif_stop_queue (dev);
+
+	/* Fill in a Tx ring entry */
+	if (lance_debug >= 3) {
+		printk( "%s: TX pkt type 0x%04x from %pM to %pM"
+				" data at 0x%08x len %d\n",
+				dev->name, ((u_short *)skb->data)[6],
+				&skb->data[6], skb->data,
+				(int)skb->data, (int)skb->len );
+	}
+
+	/* We're not prepared for the int until the last flags are set/reset. And
+	 * the int may happen already after setting the OWN_CHIP... */
+	spin_lock_irqsave (&lp->devlock, flags);
+
+	/* Mask to ring buffer boundary. */
+	entry = lp->cur_tx & TX_RING_MOD_MASK;
+	head  = &(MEM->tx_head[entry]);
+
+	/* Caution: the write order is important here, set the "ownership" bits
+	 * last.
+	 */
+
+
+	head->length = -len;
+	head->misc = 0;
+	lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len );
+	head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP;
+	dev->stats.tx_bytes += skb->len;
+	dev_kfree_skb( skb );
+	lp->cur_tx++;
+	while( lp->cur_tx >= TX_RING_SIZE && lp->dirty_tx >= TX_RING_SIZE ) {
+		lp->cur_tx -= TX_RING_SIZE;
+		lp->dirty_tx -= TX_RING_SIZE;
+	}
+
+	/* Trigger an immediate send poll. */
+	DREG = CSR0_INEA | CSR0_TDMD;
+
+	if ((MEM->tx_head[(entry+1) & TX_RING_MOD_MASK].flag & TMD1_OWN) ==
+		TMD1_OWN_HOST)
+		netif_start_queue (dev);
+	else
+		lp->tx_full = 1;
+	spin_unlock_irqrestore (&lp->devlock, flags);
+
+	return NETDEV_TX_OK;
+}
+
+/* The LANCE interrupt handler. */
+
+static irqreturn_t lance_interrupt( int irq, void *dev_id )
+{
+	struct net_device *dev = dev_id;
+	struct lance_private *lp;
+	struct lance_ioreg	 *IO;
+	int csr0, boguscnt = 10;
+	int handled = 0;
+
+	if (dev == NULL) {
+		DPRINTK( 1, ( "lance_interrupt(): interrupt for unknown device.\n" ));
+		return IRQ_NONE;
+	}
+
+	lp = netdev_priv(dev);
+	IO = lp->iobase;
+	spin_lock (&lp->devlock);
+
+	AREG = CSR0;
+
+	while( ((csr0 = DREG) & (CSR0_ERR | CSR0_TINT | CSR0_RINT)) &&
+		   --boguscnt >= 0) {
+		handled = 1;
+		/* Acknowledge all of the current interrupt sources ASAP. */
+		DREG = csr0 & ~(CSR0_INIT | CSR0_STRT | CSR0_STOP |
+									CSR0_TDMD | CSR0_INEA);
+
+		DPRINTK( 2, ( "%s: interrupt  csr0=%04x new csr=%04x.\n",
+					  dev->name, csr0, DREG ));
+
+		if (csr0 & CSR0_RINT)			/* Rx interrupt */
+			lance_rx( dev );
+
+		if (csr0 & CSR0_TINT) {			/* Tx-done interrupt */
+			int dirty_tx = lp->dirty_tx;
+
+			while( dirty_tx < lp->cur_tx) {
+				int entry = dirty_tx & TX_RING_MOD_MASK;
+				int status = MEM->tx_head[entry].flag;
+
+				if (status & TMD1_OWN_CHIP)
+					break;			/* It still hasn't been Txed */
+
+				MEM->tx_head[entry].flag = 0;
+
+				if (status & TMD1_ERR) {
+					/* There was an major error, log it. */
+					int err_status = MEM->tx_head[entry].misc;
+					dev->stats.tx_errors++;
+					if (err_status & TMD3_RTRY) dev->stats.tx_aborted_errors++;
+					if (err_status & TMD3_LCAR) dev->stats.tx_carrier_errors++;
+					if (err_status & TMD3_LCOL) dev->stats.tx_window_errors++;
+					if (err_status & TMD3_UFLO) {
+						/* Ackk!  On FIFO errors the Tx unit is turned off! */
+						dev->stats.tx_fifo_errors++;
+						/* Remove this verbosity later! */
+						DPRINTK( 1, ( "%s: Tx FIFO error! Status %04x\n",
+									  dev->name, csr0 ));
+						/* Restart the chip. */
+						DREG = CSR0_STRT;
+					}
+				} else {
+					if (status & (TMD1_MORE | TMD1_ONE | TMD1_DEF))
+						dev->stats.collisions++;
+					dev->stats.tx_packets++;
+				}
+
+				/* XXX MSch: free skb?? */
+				dirty_tx++;
+			}
+
+#ifndef final_version
+			if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) {
+				DPRINTK( 0, ( "out-of-sync dirty pointer,"
+							  " %d vs. %d, full=%ld.\n",
+							  dirty_tx, lp->cur_tx, lp->tx_full ));
+				dirty_tx += TX_RING_SIZE;
+			}
+#endif
+
+			if (lp->tx_full && (netif_queue_stopped(dev)) &&
+				dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+				/* The ring is no longer full, clear tbusy. */
+				lp->tx_full = 0;
+				netif_wake_queue (dev);
+			}
+
+			lp->dirty_tx = dirty_tx;
+		}
+
+		/* Log misc errors. */
+		if (csr0 & CSR0_BABL) dev->stats.tx_errors++; /* Tx babble. */
+		if (csr0 & CSR0_MISS) dev->stats.rx_errors++; /* Missed a Rx frame. */
+		if (csr0 & CSR0_MERR) {
+			DPRINTK( 1, ( "%s: Bus master arbitration failure (?!?), "
+						  "status %04x.\n", dev->name, csr0 ));
+			/* Restart the chip. */
+			DREG = CSR0_STRT;
+		}
+	}
+
+    /* Clear any other interrupt, and set interrupt enable. */
+	DREG = CSR0_BABL | CSR0_CERR | CSR0_MISS | CSR0_MERR |
+		   CSR0_IDON | CSR0_INEA;
+
+	DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n",
+				  dev->name, DREG ));
+
+	spin_unlock (&lp->devlock);
+	return IRQ_RETVAL(handled);
+}
+
+
+static int lance_rx( struct net_device *dev )
+{
+	struct lance_private *lp = netdev_priv(dev);
+	int entry = lp->cur_rx & RX_RING_MOD_MASK;
+	int i;
+
+	DPRINTK( 2, ( "%s: rx int, flag=%04x\n", dev->name,
+				  MEM->rx_head[entry].flag ));
+
+	/* If we own the next entry, it's a new packet. Send it up. */
+	while( (MEM->rx_head[entry].flag & RMD1_OWN) == RMD1_OWN_HOST ) {
+		struct lance_rx_head *head = &(MEM->rx_head[entry]);
+		int status = head->flag;
+
+		if (status != (RMD1_ENP|RMD1_STP)) {		/* There was an error. */
+			/* There is a tricky error noted by John Murphy,
+			   <murf@perftech.com> to Russ Nelson: Even with full-sized
+			   buffers it's possible for a jabber packet to use two
+			   buffers, with only the last correctly noting the error. */
+			if (status & RMD1_ENP)	/* Only count a general error at the */
+				dev->stats.rx_errors++; /* end of a packet.*/
+			if (status & RMD1_FRAM) dev->stats.rx_frame_errors++;
+			if (status & RMD1_OFLO) dev->stats.rx_over_errors++;
+			if (status & RMD1_CRC) dev->stats.rx_crc_errors++;
+			if (status & RMD1_BUFF) dev->stats.rx_fifo_errors++;
+			head->flag &= (RMD1_ENP|RMD1_STP);
+		} else {
+			/* Malloc up new buffer, compatible with net-3. */
+			short pkt_len = head->msg_length & 0xfff;
+			struct sk_buff *skb;
+
+			if (pkt_len < 60) {
+				printk( "%s: Runt packet!\n", dev->name );
+				dev->stats.rx_errors++;
+			}
+			else {
+				skb = dev_alloc_skb( pkt_len+2 );
+				if (skb == NULL) {
+					DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n",
+								  dev->name ));
+					for( i = 0; i < RX_RING_SIZE; i++ )
+						if (MEM->rx_head[(entry+i) & RX_RING_MOD_MASK].flag &
+							RMD1_OWN_CHIP)
+							break;
+
+					if (i > RX_RING_SIZE - 2) {
+						dev->stats.rx_dropped++;
+						head->flag |= RMD1_OWN_CHIP;
+						lp->cur_rx++;
+					}
+					break;
+				}
+
+				if (lance_debug >= 3) {
+					u_char *data = PKTBUF_ADDR(head);
+
+					printk(KERN_DEBUG "%s: RX pkt type 0x%04x from %pM to %pM "
+						   "data %02x %02x %02x %02x %02x %02x %02x %02x "
+						   "len %d\n",
+						   dev->name, ((u_short *)data)[6],
+						   &data[6], data,
+						   data[15], data[16], data[17], data[18],
+						   data[19], data[20], data[21], data[22],
+						   pkt_len);
+				}
+
+				skb_reserve( skb, 2 );	/* 16 byte align */
+				skb_put( skb, pkt_len );	/* Make room */
+				lp->memcpy_f( skb->data, PKTBUF_ADDR(head), pkt_len );
+				skb->protocol = eth_type_trans( skb, dev );
+				netif_rx( skb );
+				dev->stats.rx_packets++;
+				dev->stats.rx_bytes += pkt_len;
+			}
+		}
+
+		head->flag |= RMD1_OWN_CHIP;
+		entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
+	}
+	lp->cur_rx &= RX_RING_MOD_MASK;
+
+	/* From lance.c (Donald Becker): */
+	/* We should check that at least two ring entries are free.	 If not,
+	   we should free one and mark stats->rx_dropped++. */
+
+	return 0;
+}
+
+
+static int lance_close( struct net_device *dev )
+{
+	struct lance_private *lp = netdev_priv(dev);
+	struct lance_ioreg	 *IO = lp->iobase;
+
+	netif_stop_queue (dev);
+
+	AREG = CSR0;
+
+	DPRINTK( 2, ( "%s: Shutting down ethercard, status was %2.2x.\n",
+				  dev->name, DREG ));
+
+	/* We stop the LANCE here -- it occasionally polls
+	   memory if we don't. */
+	DREG = CSR0_STOP;
+
+	return 0;
+}
+
+
+/* Set or clear the multicast filter for this adaptor.
+   num_addrs == -1		Promiscuous mode, receive all packets
+   num_addrs == 0		Normal mode, clear multicast list
+   num_addrs > 0		Multicast mode, receive normal and MC packets, and do
+						best-effort filtering.
+ */
+
+static void set_multicast_list( struct net_device *dev )
+{
+	struct lance_private *lp = netdev_priv(dev);
+	struct lance_ioreg	 *IO = lp->iobase;
+
+	if (netif_running(dev))
+		/* Only possible if board is already started */
+		return;
+
+	/* We take the simple way out and always enable promiscuous mode. */
+	DREG = CSR0_STOP; /* Temporarily stop the lance. */
+
+	if (dev->flags & IFF_PROMISC) {
+		/* Log any net taps. */
+		DPRINTK( 2, ( "%s: Promiscuous mode enabled.\n", dev->name ));
+		REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */
+	} else {
+		short multicast_table[4];
+		int num_addrs = netdev_mc_count(dev);
+		int i;
+		/* We don't use the multicast table, but rely on upper-layer
+		 * filtering. */
+		memset( multicast_table, (num_addrs == 0) ? 0 : -1,
+				sizeof(multicast_table) );
+		for( i = 0; i < 4; i++ )
+			REGA( CSR8+i ) = multicast_table[i];
+		REGA( CSR15 ) = 0; /* Unset promiscuous mode */
+	}
+
+	/*
+	 * Always set BSWP after a STOP as STOP puts it back into
+	 * little endian mode.
+	 */
+	REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
+
+	/* Resume normal operation and reset AREG to CSR0 */
+	REGA( CSR0 ) = CSR0_IDON | CSR0_INEA | CSR0_STRT;
+}
+
+
+/* This is needed for old RieblCards and possible for new RieblCards */
+
+static int lance_set_mac_address( struct net_device *dev, void *addr )
+{
+	struct lance_private *lp = netdev_priv(dev);
+	struct sockaddr *saddr = addr;
+	int i;
+
+	if (lp->cardtype != OLD_RIEBL && lp->cardtype != NEW_RIEBL)
+		return -EOPNOTSUPP;
+
+	if (netif_running(dev)) {
+		/* Only possible while card isn't started */
+		DPRINTK( 1, ( "%s: hwaddr can be set only while card isn't open.\n",
+					  dev->name ));
+		return -EIO;
+	}
+
+	memcpy( dev->dev_addr, saddr->sa_data, dev->addr_len );
+	for( i = 0; i < 6; i++ )
+		MEM->init.hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */
+	lp->memcpy_f( RIEBL_HWADDR_ADDR, dev->dev_addr, 6 );
+	/* set also the magic for future sessions */
+	*RIEBL_MAGIC_ADDR = RIEBL_MAGIC;
+
+	return 0;
+}
+
+
+#ifdef MODULE
+static struct net_device *atarilance_dev;
+
+static int __init atarilance_module_init(void)
+{
+	atarilance_dev = atarilance_probe(-1);
+	if (IS_ERR(atarilance_dev))
+		return PTR_ERR(atarilance_dev);
+	return 0;
+}
+
+static void __exit atarilance_module_exit(void)
+{
+	unregister_netdev(atarilance_dev);
+	free_irq(atarilance_dev->irq, atarilance_dev);
+	free_netdev(atarilance_dev);
+}
+module_init(atarilance_module_init);
+module_exit(atarilance_module_exit);
+#endif /* MODULE */
+
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  tab-width: 4
+ * End:
+ */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/au1000_eth.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/au1000_eth.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/au1000_eth.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/au1000_eth.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1356 @@
+/*
+ *
+ * Alchemy Au1x00 ethernet driver
+ *
+ * Copyright 2001-2003, 2006 MontaVista Software Inc.
+ * Copyright 2002 TimeSys Corp.
+ * Added ethtool/mii-tool support,
+ * Copyright 2004 Matt Porter <mporter@kernel.crashing.org>
+ * Update: 2004 Bjoern Riemer, riemer@fokus.fraunhofer.de
+ * or riemer@riemer-nt.de: fixed the link beat detection with
+ * ioctls (SIOCGMIIPHY)
+ * Copyright 2006 Herbert Valerio Riedel <hvr@gnu.org>
+ *  converted to use linux-2.6.x's PHY framework
+ *
+ * Author: MontaVista Software, Inc.
+ *		ppopov@mvista.com or source@mvista.com
+ *
+ * ########################################################################
+ *
+ *  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.
+ *
+ * ########################################################################
+ *
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/capability.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/crc32.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/cpu.h>
+#include <linux/io.h>
+
+#include <asm/mipsregs.h>
+#include <asm/irq.h>
+#include <asm/processor.h>
+
+#include <au1000.h>
+#include <au1xxx_eth.h>
+#include <prom.h>
+
+#include "au1000_eth.h"
+
+#ifdef AU1000_ETH_DEBUG
+static int au1000_debug = 5;
+#else
+static int au1000_debug = 3;
+#endif
+
+#define AU1000_DEF_MSG_ENABLE	(NETIF_MSG_DRV	| \
+				NETIF_MSG_PROBE	| \
+				NETIF_MSG_LINK)
+
+#define DRV_NAME	"au1000_eth"
+#define DRV_VERSION	"1.7"
+#define DRV_AUTHOR	"Pete Popov <ppopov@embeddedalley.com>"
+#define DRV_DESC	"Au1xxx on-chip Ethernet driver"
+
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+/*
+ * Theory of operation
+ *
+ * The Au1000 MACs use a simple rx and tx descriptor ring scheme.
+ * There are four receive and four transmit descriptors.  These
+ * descriptors are not in memory; rather, they are just a set of
+ * hardware registers.
+ *
+ * Since the Au1000 has a coherent data cache, the receive and
+ * transmit buffers are allocated from the KSEG0 segment. The
+ * hardware registers, however, are still mapped at KSEG1 to
+ * make sure there's no out-of-order writes, and that all writes
+ * complete immediately.
+ */
+
+/*
+ * board-specific configurations
+ *
+ * PHY detection algorithm
+ *
+ * If phy_static_config is undefined, the PHY setup is
+ * autodetected:
+ *
+ * mii_probe() first searches the current MAC's MII bus for a PHY,
+ * selecting the first (or last, if phy_search_highest_addr is
+ * defined) PHY address not already claimed by another netdev.
+ *
+ * If nothing was found that way when searching for the 2nd ethernet
+ * controller's PHY and phy1_search_mac0 is defined, then
+ * the first MII bus is searched as well for an unclaimed PHY; this is
+ * needed in case of a dual-PHY accessible only through the MAC0's MII
+ * bus.
+ *
+ * Finally, if no PHY is found, then the corresponding ethernet
+ * controller is not registered to the network subsystem.
+ */
+
+/* autodetection defaults: phy1_search_mac0 */
+
+/* static PHY setup
+ *
+ * most boards PHY setup should be detectable properly with the
+ * autodetection algorithm in mii_probe(), but in some cases (e.g. if
+ * you have a switch attached, or want to use the PHY's interrupt
+ * notification capabilities) you can provide a static PHY
+ * configuration here
+ *
+ * IRQs may only be set, if a PHY address was configured
+ * If a PHY address is given, also a bus id is required to be set
+ *
+ * ps: make sure the used irqs are configured properly in the board
+ * specific irq-map
+ */
+
+static void au1000_enable_mac(struct net_device *dev, int force_reset)
+{
+	unsigned long flags;
+	struct au1000_private *aup = netdev_priv(dev);
+
+	spin_lock_irqsave(&aup->lock, flags);
+
+	if (force_reset || (!aup->mac_enabled)) {
+		writel(MAC_EN_CLOCK_ENABLE, aup->enable);
+		au_sync_delay(2);
+		writel((MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
+				| MAC_EN_CLOCK_ENABLE), aup->enable);
+		au_sync_delay(2);
+
+		aup->mac_enabled = 1;
+	}
+
+	spin_unlock_irqrestore(&aup->lock, flags);
+}
+
+/*
+ * MII operations
+ */
+static int au1000_mdio_read(struct net_device *dev, int phy_addr, int reg)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+	u32 *const mii_control_reg = &aup->mac->mii_control;
+	u32 *const mii_data_reg = &aup->mac->mii_data;
+	u32 timedout = 20;
+	u32 mii_control;
+
+	while (readl(mii_control_reg) & MAC_MII_BUSY) {
+		mdelay(1);
+		if (--timedout == 0) {
+			netdev_err(dev, "read_MII busy timeout!!\n");
+			return -1;
+		}
+	}
+
+	mii_control = MAC_SET_MII_SELECT_REG(reg) |
+		MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_READ;
+
+	writel(mii_control, mii_control_reg);
+
+	timedout = 20;
+	while (readl(mii_control_reg) & MAC_MII_BUSY) {
+		mdelay(1);
+		if (--timedout == 0) {
+			netdev_err(dev, "mdio_read busy timeout!!\n");
+			return -1;
+		}
+	}
+	return readl(mii_data_reg);
+}
+
+static void au1000_mdio_write(struct net_device *dev, int phy_addr,
+			      int reg, u16 value)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+	u32 *const mii_control_reg = &aup->mac->mii_control;
+	u32 *const mii_data_reg = &aup->mac->mii_data;
+	u32 timedout = 20;
+	u32 mii_control;
+
+	while (readl(mii_control_reg) & MAC_MII_BUSY) {
+		mdelay(1);
+		if (--timedout == 0) {
+			netdev_err(dev, "mdio_write busy timeout!!\n");
+			return;
+		}
+	}
+
+	mii_control = MAC_SET_MII_SELECT_REG(reg) |
+		MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_WRITE;
+
+	writel(value, mii_data_reg);
+	writel(mii_control, mii_control_reg);
+}
+
+static int au1000_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
+{
+	/* WARNING: bus->phy_map[phy_addr].attached_dev == dev does
+	 * _NOT_ hold (e.g. when PHY is accessed through other MAC's MII bus)
+	 */
+	struct net_device *const dev = bus->priv;
+
+	/* make sure the MAC associated with this
+	 * mii_bus is enabled
+	 */
+	au1000_enable_mac(dev, 0);
+
+	return au1000_mdio_read(dev, phy_addr, regnum);
+}
+
+static int au1000_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
+				u16 value)
+{
+	struct net_device *const dev = bus->priv;
+
+	/* make sure the MAC associated with this
+	 * mii_bus is enabled
+	 */
+	au1000_enable_mac(dev, 0);
+
+	au1000_mdio_write(dev, phy_addr, regnum, value);
+	return 0;
+}
+
+static int au1000_mdiobus_reset(struct mii_bus *bus)
+{
+	struct net_device *const dev = bus->priv;
+
+	/* make sure the MAC associated with this
+	 * mii_bus is enabled
+	 */
+	au1000_enable_mac(dev, 0);
+
+	return 0;
+}
+
+static void au1000_hard_stop(struct net_device *dev)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+	u32 reg;
+
+	netif_dbg(aup, drv, dev, "hard stop\n");
+
+	reg = readl(&aup->mac->control);
+	reg &= ~(MAC_RX_ENABLE | MAC_TX_ENABLE);
+	writel(reg, &aup->mac->control);
+	au_sync_delay(10);
+}
+
+static void au1000_enable_rx_tx(struct net_device *dev)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+	u32 reg;
+
+	netif_dbg(aup, hw, dev, "enable_rx_tx\n");
+
+	reg = readl(&aup->mac->control);
+	reg |= (MAC_RX_ENABLE | MAC_TX_ENABLE);
+	writel(reg, &aup->mac->control);
+	au_sync_delay(10);
+}
+
+static void
+au1000_adjust_link(struct net_device *dev)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+	struct phy_device *phydev = aup->phy_dev;
+	unsigned long flags;
+	u32 reg;
+
+	int status_change = 0;
+
+	BUG_ON(!aup->phy_dev);
+
+	spin_lock_irqsave(&aup->lock, flags);
+
+	if (phydev->link && (aup->old_speed != phydev->speed)) {
+		/* speed changed */
+
+		switch (phydev->speed) {
+		case SPEED_10:
+		case SPEED_100:
+			break;
+		default:
+			netdev_warn(dev, "Speed (%d) is not 10/100 ???\n",
+							phydev->speed);
+			break;
+		}
+
+		aup->old_speed = phydev->speed;
+
+		status_change = 1;
+	}
+
+	if (phydev->link && (aup->old_duplex != phydev->duplex)) {
+		/* duplex mode changed */
+
+		/* switching duplex mode requires to disable rx and tx! */
+		au1000_hard_stop(dev);
+
+		reg = readl(&aup->mac->control);
+		if (DUPLEX_FULL == phydev->duplex) {
+			reg |= MAC_FULL_DUPLEX;
+			reg &= ~MAC_DISABLE_RX_OWN;
+		} else {
+			reg &= ~MAC_FULL_DUPLEX;
+			reg |= MAC_DISABLE_RX_OWN;
+		}
+		writel(reg, &aup->mac->control);
+		au_sync_delay(1);
+
+		au1000_enable_rx_tx(dev);
+		aup->old_duplex = phydev->duplex;
+
+		status_change = 1;
+	}
+
+	if (phydev->link != aup->old_link) {
+		/* link state changed */
+
+		if (!phydev->link) {
+			/* link went down */
+			aup->old_speed = 0;
+			aup->old_duplex = -1;
+		}
+
+		aup->old_link = phydev->link;
+		status_change = 1;
+	}
+
+	spin_unlock_irqrestore(&aup->lock, flags);
+
+	if (status_change) {
+		if (phydev->link)
+			netdev_info(dev, "link up (%d/%s)\n",
+			       phydev->speed,
+			       DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
+		else
+			netdev_info(dev, "link down\n");
+	}
+}
+
+static int au1000_mii_probe(struct net_device *dev)
+{
+	struct au1000_private *const aup = netdev_priv(dev);
+	struct phy_device *phydev = NULL;
+	int phy_addr;
+
+	if (aup->phy_static_config) {
+		BUG_ON(aup->mac_id < 0 || aup->mac_id > 1);
+
+		if (aup->phy_addr)
+			phydev = aup->mii_bus->phy_map[aup->phy_addr];
+		else
+			netdev_info(dev, "using PHY-less setup\n");
+		return 0;
+	}
+
+	/* find the first (lowest address) PHY
+	 * on the current MAC's MII bus
+	 */
+	for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++)
+		if (aup->mii_bus->phy_map[phy_addr]) {
+			phydev = aup->mii_bus->phy_map[phy_addr];
+			if (!aup->phy_search_highest_addr)
+				/* break out with first one found */
+				break;
+		}
+
+	if (aup->phy1_search_mac0) {
+		/* try harder to find a PHY */
+		if (!phydev && (aup->mac_id == 1)) {
+			/* no PHY found, maybe we have a dual PHY? */
+			dev_info(&dev->dev, ": no PHY found on MAC1, "
+				"let's see if it's attached to MAC0...\n");
+
+			/* find the first (lowest address) non-attached
+			 * PHY on the MAC0 MII bus
+			 */
+			for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+				struct phy_device *const tmp_phydev =
+					aup->mii_bus->phy_map[phy_addr];
+
+				if (aup->mac_id == 1)
+					break;
+
+				/* no PHY here... */
+				if (!tmp_phydev)
+					continue;
+
+				/* already claimed by MAC0 */
+				if (tmp_phydev->attached_dev)
+					continue;
+
+				phydev = tmp_phydev;
+				break; /* found it */
+			}
+		}
+	}
+
+	if (!phydev) {
+		netdev_err(dev, "no PHY found\n");
+		return -1;
+	}
+
+	/* now we are supposed to have a proper phydev, to attach to... */
+	BUG_ON(phydev->attached_dev);
+
+	phydev = phy_connect(dev, dev_name(&phydev->dev), &au1000_adjust_link,
+			0, PHY_INTERFACE_MODE_MII);
+
+	if (IS_ERR(phydev)) {
+		netdev_err(dev, "Could not attach to PHY\n");
+		return PTR_ERR(phydev);
+	}
+
+	/* mask with MAC supported features */
+	phydev->supported &= (SUPPORTED_10baseT_Half
+			      | SUPPORTED_10baseT_Full
+			      | SUPPORTED_100baseT_Half
+			      | SUPPORTED_100baseT_Full
+			      | SUPPORTED_Autoneg
+			      /* | SUPPORTED_Pause | SUPPORTED_Asym_Pause */
+			      | SUPPORTED_MII
+			      | SUPPORTED_TP);
+
+	phydev->advertising = phydev->supported;
+
+	aup->old_link = 0;
+	aup->old_speed = 0;
+	aup->old_duplex = -1;
+	aup->phy_dev = phydev;
+
+	netdev_info(dev, "attached PHY driver [%s] "
+	       "(mii_bus:phy_addr=%s, irq=%d)\n",
+	       phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
+
+	return 0;
+}
+
+
+/*
+ * Buffer allocation/deallocation routines. The buffer descriptor returned
+ * has the virtual and dma address of a buffer suitable for
+ * both, receive and transmit operations.
+ */
+static struct db_dest *au1000_GetFreeDB(struct au1000_private *aup)
+{
+	struct db_dest *pDB;
+	pDB = aup->pDBfree;
+
+	if (pDB)
+		aup->pDBfree = pDB->pnext;
+
+	return pDB;
+}
+
+void au1000_ReleaseDB(struct au1000_private *aup, struct db_dest *pDB)
+{
+	struct db_dest *pDBfree = aup->pDBfree;
+	if (pDBfree)
+		pDBfree->pnext = pDB;
+	aup->pDBfree = pDB;
+}
+
+static void au1000_reset_mac_unlocked(struct net_device *dev)
+{
+	struct au1000_private *const aup = netdev_priv(dev);
+	int i;
+
+	au1000_hard_stop(dev);
+
+	writel(MAC_EN_CLOCK_ENABLE, aup->enable);
+	au_sync_delay(2);
+	writel(0, aup->enable);
+	au_sync_delay(2);
+
+	aup->tx_full = 0;
+	for (i = 0; i < NUM_RX_DMA; i++) {
+		/* reset control bits */
+		aup->rx_dma_ring[i]->buff_stat &= ~0xf;
+	}
+	for (i = 0; i < NUM_TX_DMA; i++) {
+		/* reset control bits */
+		aup->tx_dma_ring[i]->buff_stat &= ~0xf;
+	}
+
+	aup->mac_enabled = 0;
+
+}
+
+static void au1000_reset_mac(struct net_device *dev)
+{
+	struct au1000_private *const aup = netdev_priv(dev);
+	unsigned long flags;
+
+	netif_dbg(aup, hw, dev, "reset mac, aup %x\n",
+					(unsigned)aup);
+
+	spin_lock_irqsave(&aup->lock, flags);
+
+	au1000_reset_mac_unlocked(dev);
+
+	spin_unlock_irqrestore(&aup->lock, flags);
+}
+
+/*
+ * Setup the receive and transmit "rings".  These pointers are the addresses
+ * of the rx and tx MAC DMA registers so they are fixed by the hardware --
+ * these are not descriptors sitting in memory.
+ */
+static void
+au1000_setup_hw_rings(struct au1000_private *aup, void __iomem *tx_base)
+{
+	int i;
+
+	for (i = 0; i < NUM_RX_DMA; i++) {
+		aup->rx_dma_ring[i] = (struct rx_dma *)
+			(tx_base + 0x100 + sizeof(struct rx_dma) * i);
+	}
+	for (i = 0; i < NUM_TX_DMA; i++) {
+		aup->tx_dma_ring[i] = (struct tx_dma *)
+			(tx_base + sizeof(struct tx_dma) * i);
+	}
+}
+
+/*
+ * ethtool operations
+ */
+
+static int au1000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+
+	if (aup->phy_dev)
+		return phy_ethtool_gset(aup->phy_dev, cmd);
+
+	return -EINVAL;
+}
+
+static int au1000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (aup->phy_dev)
+		return phy_ethtool_sset(aup->phy_dev, cmd);
+
+	return -EINVAL;
+}
+
+static void
+au1000_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	info->fw_version[0] = '\0';
+	sprintf(info->bus_info, "%s %d", DRV_NAME, aup->mac_id);
+	info->regdump_len = 0;
+}
+
+static void au1000_set_msglevel(struct net_device *dev, u32 value)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+	aup->msg_enable = value;
+}
+
+static u32 au1000_get_msglevel(struct net_device *dev)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+	return aup->msg_enable;
+}
+
+static const struct ethtool_ops au1000_ethtool_ops = {
+	.get_settings = au1000_get_settings,
+	.set_settings = au1000_set_settings,
+	.get_drvinfo = au1000_get_drvinfo,
+	.get_link = ethtool_op_get_link,
+	.get_msglevel = au1000_get_msglevel,
+	.set_msglevel = au1000_set_msglevel,
+};
+
+
+/*
+ * Initialize the interface.
+ *
+ * When the device powers up, the clocks are disabled and the
+ * mac is in reset state.  When the interface is closed, we
+ * do the same -- reset the device and disable the clocks to
+ * conserve power. Thus, whenever au1000_init() is called,
+ * the device should already be in reset state.
+ */
+static int au1000_init(struct net_device *dev)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+	unsigned long flags;
+	int i;
+	u32 control;
+
+	netif_dbg(aup, hw, dev, "au1000_init\n");
+
+	/* bring the device out of reset */
+	au1000_enable_mac(dev, 1);
+
+	spin_lock_irqsave(&aup->lock, flags);
+
+	writel(0, &aup->mac->control);
+	aup->tx_head = (aup->tx_dma_ring[0]->buff_stat & 0xC) >> 2;
+	aup->tx_tail = aup->tx_head;
+	aup->rx_head = (aup->rx_dma_ring[0]->buff_stat & 0xC) >> 2;
+
+	writel(dev->dev_addr[5]<<8 | dev->dev_addr[4],
+					&aup->mac->mac_addr_high);
+	writel(dev->dev_addr[3]<<24 | dev->dev_addr[2]<<16 |
+		dev->dev_addr[1]<<8 | dev->dev_addr[0],
+					&aup->mac->mac_addr_low);
+
+
+	for (i = 0; i < NUM_RX_DMA; i++)
+		aup->rx_dma_ring[i]->buff_stat |= RX_DMA_ENABLE;
+
+	au_sync();
+
+	control = MAC_RX_ENABLE | MAC_TX_ENABLE;
+#ifndef CONFIG_CPU_LITTLE_ENDIAN
+	control |= MAC_BIG_ENDIAN;
+#endif
+	if (aup->phy_dev) {
+		if (aup->phy_dev->link && (DUPLEX_FULL == aup->phy_dev->duplex))
+			control |= MAC_FULL_DUPLEX;
+		else
+			control |= MAC_DISABLE_RX_OWN;
+	} else { /* PHY-less op, assume full-duplex */
+		control |= MAC_FULL_DUPLEX;
+	}
+
+	writel(control, &aup->mac->control);
+	writel(0x8100, &aup->mac->vlan1_tag); /* activate vlan support */
+	au_sync();
+
+	spin_unlock_irqrestore(&aup->lock, flags);
+	return 0;
+}
+
+static inline void au1000_update_rx_stats(struct net_device *dev, u32 status)
+{
+	struct net_device_stats *ps = &dev->stats;
+
+	ps->rx_packets++;
+	if (status & RX_MCAST_FRAME)
+		ps->multicast++;
+
+	if (status & RX_ERROR) {
+		ps->rx_errors++;
+		if (status & RX_MISSED_FRAME)
+			ps->rx_missed_errors++;
+		if (status & (RX_OVERLEN | RX_RUNT | RX_LEN_ERROR))
+			ps->rx_length_errors++;
+		if (status & RX_CRC_ERROR)
+			ps->rx_crc_errors++;
+		if (status & RX_COLL)
+			ps->collisions++;
+	} else
+		ps->rx_bytes += status & RX_FRAME_LEN_MASK;
+
+}
+
+/*
+ * Au1000 receive routine.
+ */
+static int au1000_rx(struct net_device *dev)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+	struct sk_buff *skb;
+	struct rx_dma *prxd;
+	u32 buff_stat, status;
+	struct db_dest *pDB;
+	u32	frmlen;
+
+	netif_dbg(aup, rx_status, dev, "au1000_rx head %d\n", aup->rx_head);
+
+	prxd = aup->rx_dma_ring[aup->rx_head];
+	buff_stat = prxd->buff_stat;
+	while (buff_stat & RX_T_DONE)  {
+		status = prxd->status;
+		pDB = aup->rx_db_inuse[aup->rx_head];
+		au1000_update_rx_stats(dev, status);
+		if (!(status & RX_ERROR))  {
+
+			/* good frame */
+			frmlen = (status & RX_FRAME_LEN_MASK);
+			frmlen -= 4; /* Remove FCS */
+			skb = dev_alloc_skb(frmlen + 2);
+			if (skb == NULL) {
+				netdev_err(dev, "Memory squeeze, dropping packet.\n");
+				dev->stats.rx_dropped++;
+				continue;
+			}
+			skb_reserve(skb, 2);	/* 16 byte IP header align */
+			skb_copy_to_linear_data(skb,
+				(unsigned char *)pDB->vaddr, frmlen);
+			skb_put(skb, frmlen);
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);	/* pass the packet to upper layers */
+		} else {
+			if (au1000_debug > 4) {
+				pr_err("rx_error(s):");
+				if (status & RX_MISSED_FRAME)
+					pr_cont(" miss");
+				if (status & RX_WDOG_TIMER)
+					pr_cont(" wdog");
+				if (status & RX_RUNT)
+					pr_cont(" runt");
+				if (status & RX_OVERLEN)
+					pr_cont(" overlen");
+				if (status & RX_COLL)
+					pr_cont(" coll");
+				if (status & RX_MII_ERROR)
+					pr_cont(" mii error");
+				if (status & RX_CRC_ERROR)
+					pr_cont(" crc error");
+				if (status & RX_LEN_ERROR)
+					pr_cont(" len error");
+				if (status & RX_U_CNTRL_FRAME)
+					pr_cont(" u control frame");
+				pr_cont("\n");
+			}
+		}
+		prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE);
+		aup->rx_head = (aup->rx_head + 1) & (NUM_RX_DMA - 1);
+		au_sync();
+
+		/* next descriptor */
+		prxd = aup->rx_dma_ring[aup->rx_head];
+		buff_stat = prxd->buff_stat;
+	}
+	return 0;
+}
+
+static void au1000_update_tx_stats(struct net_device *dev, u32 status)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+	struct net_device_stats *ps = &dev->stats;
+
+	if (status & TX_FRAME_ABORTED) {
+		if (!aup->phy_dev || (DUPLEX_FULL == aup->phy_dev->duplex)) {
+			if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) {
+				/* any other tx errors are only valid
+				 * in half duplex mode
+				 */
+				ps->tx_errors++;
+				ps->tx_aborted_errors++;
+			}
+		} else {
+			ps->tx_errors++;
+			ps->tx_aborted_errors++;
+			if (status & (TX_NO_CARRIER | TX_LOSS_CARRIER))
+				ps->tx_carrier_errors++;
+		}
+	}
+}
+
+/*
+ * Called from the interrupt service routine to acknowledge
+ * the TX DONE bits.  This is a must if the irq is setup as
+ * edge triggered.
+ */
+static void au1000_tx_ack(struct net_device *dev)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+	struct tx_dma *ptxd;
+
+	ptxd = aup->tx_dma_ring[aup->tx_tail];
+
+	while (ptxd->buff_stat & TX_T_DONE) {
+		au1000_update_tx_stats(dev, ptxd->status);
+		ptxd->buff_stat &= ~TX_T_DONE;
+		ptxd->len = 0;
+		au_sync();
+
+		aup->tx_tail = (aup->tx_tail + 1) & (NUM_TX_DMA - 1);
+		ptxd = aup->tx_dma_ring[aup->tx_tail];
+
+		if (aup->tx_full) {
+			aup->tx_full = 0;
+			netif_wake_queue(dev);
+		}
+	}
+}
+
+/*
+ * Au1000 interrupt service routine.
+ */
+static irqreturn_t au1000_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+
+	/* Handle RX interrupts first to minimize chance of overrun */
+
+	au1000_rx(dev);
+	au1000_tx_ack(dev);
+	return IRQ_RETVAL(1);
+}
+
+static int au1000_open(struct net_device *dev)
+{
+	int retval;
+	struct au1000_private *aup = netdev_priv(dev);
+
+	netif_dbg(aup, drv, dev, "open: dev=%p\n", dev);
+
+	retval = request_irq(dev->irq, au1000_interrupt, 0,
+					dev->name, dev);
+	if (retval) {
+		netdev_err(dev, "unable to get IRQ %d\n", dev->irq);
+		return retval;
+	}
+
+	retval = au1000_init(dev);
+	if (retval) {
+		netdev_err(dev, "error in au1000_init\n");
+		free_irq(dev->irq, dev);
+		return retval;
+	}
+
+	if (aup->phy_dev) {
+		/* cause the PHY state machine to schedule a link state check */
+		aup->phy_dev->state = PHY_CHANGELINK;
+		phy_start(aup->phy_dev);
+	}
+
+	netif_start_queue(dev);
+
+	netif_dbg(aup, drv, dev, "open: Initialization done.\n");
+
+	return 0;
+}
+
+static int au1000_close(struct net_device *dev)
+{
+	unsigned long flags;
+	struct au1000_private *const aup = netdev_priv(dev);
+
+	netif_dbg(aup, drv, dev, "close: dev=%p\n", dev);
+
+	if (aup->phy_dev)
+		phy_stop(aup->phy_dev);
+
+	spin_lock_irqsave(&aup->lock, flags);
+
+	au1000_reset_mac_unlocked(dev);
+
+	/* stop the device */
+	netif_stop_queue(dev);
+
+	/* disable the interrupt */
+	free_irq(dev->irq, dev);
+	spin_unlock_irqrestore(&aup->lock, flags);
+
+	return 0;
+}
+
+/*
+ * Au1000 transmit routine.
+ */
+static netdev_tx_t au1000_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+	struct net_device_stats *ps = &dev->stats;
+	struct tx_dma *ptxd;
+	u32 buff_stat;
+	struct db_dest *pDB;
+	int i;
+
+	netif_dbg(aup, tx_queued, dev, "tx: aup %x len=%d, data=%p, head %d\n",
+				(unsigned)aup, skb->len,
+				skb->data, aup->tx_head);
+
+	ptxd = aup->tx_dma_ring[aup->tx_head];
+	buff_stat = ptxd->buff_stat;
+	if (buff_stat & TX_DMA_ENABLE) {
+		/* We've wrapped around and the transmitter is still busy */
+		netif_stop_queue(dev);
+		aup->tx_full = 1;
+		return NETDEV_TX_BUSY;
+	} else if (buff_stat & TX_T_DONE) {
+		au1000_update_tx_stats(dev, ptxd->status);
+		ptxd->len = 0;
+	}
+
+	if (aup->tx_full) {
+		aup->tx_full = 0;
+		netif_wake_queue(dev);
+	}
+
+	pDB = aup->tx_db_inuse[aup->tx_head];
+	skb_copy_from_linear_data(skb, (void *)pDB->vaddr, skb->len);
+	if (skb->len < ETH_ZLEN) {
+		for (i = skb->len; i < ETH_ZLEN; i++)
+			((char *)pDB->vaddr)[i] = 0;
+
+		ptxd->len = ETH_ZLEN;
+	} else
+		ptxd->len = skb->len;
+
+	ps->tx_packets++;
+	ps->tx_bytes += ptxd->len;
+
+	ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE;
+	au_sync();
+	dev_kfree_skb(skb);
+	aup->tx_head = (aup->tx_head + 1) & (NUM_TX_DMA - 1);
+	return NETDEV_TX_OK;
+}
+
+/*
+ * The Tx ring has been full longer than the watchdog timeout
+ * value. The transmitter must be hung?
+ */
+static void au1000_tx_timeout(struct net_device *dev)
+{
+	netdev_err(dev, "au1000_tx_timeout: dev=%p\n", dev);
+	au1000_reset_mac(dev);
+	au1000_init(dev);
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	netif_wake_queue(dev);
+}
+
+static void au1000_multicast_list(struct net_device *dev)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+	u32 reg;
+
+	netif_dbg(aup, drv, dev, "%s: flags=%x\n", __func__, dev->flags);
+	reg = readl(&aup->mac->control);
+	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
+		reg |= MAC_PROMISCUOUS;
+	} else if ((dev->flags & IFF_ALLMULTI)  ||
+			   netdev_mc_count(dev) > MULTICAST_FILTER_LIMIT) {
+		reg |= MAC_PASS_ALL_MULTI;
+		reg &= ~MAC_PROMISCUOUS;
+		netdev_info(dev, "Pass all multicast\n");
+	} else {
+		struct netdev_hw_addr *ha;
+		u32 mc_filter[2];	/* Multicast hash filter */
+
+		mc_filter[1] = mc_filter[0] = 0;
+		netdev_for_each_mc_addr(ha, dev)
+			set_bit(ether_crc(ETH_ALEN, ha->addr)>>26,
+					(long *)mc_filter);
+		writel(mc_filter[1], &aup->mac->multi_hash_high);
+		writel(mc_filter[0], &aup->mac->multi_hash_low);
+		reg &= ~MAC_PROMISCUOUS;
+		reg |= MAC_HASH_MODE;
+	}
+	writel(reg, &aup->mac->control);
+}
+
+static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct au1000_private *aup = netdev_priv(dev);
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	if (!aup->phy_dev)
+		return -EINVAL; /* PHY not controllable */
+
+	return phy_mii_ioctl(aup->phy_dev, rq, cmd);
+}
+
+static const struct net_device_ops au1000_netdev_ops = {
+	.ndo_open		= au1000_open,
+	.ndo_stop		= au1000_close,
+	.ndo_start_xmit		= au1000_tx,
+	.ndo_set_rx_mode	= au1000_multicast_list,
+	.ndo_do_ioctl		= au1000_ioctl,
+	.ndo_tx_timeout		= au1000_tx_timeout,
+	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_change_mtu		= eth_change_mtu,
+};
+
+static int __devinit au1000_probe(struct platform_device *pdev)
+{
+	static unsigned version_printed;
+	struct au1000_private *aup = NULL;
+	struct au1000_eth_platform_data *pd;
+	struct net_device *dev = NULL;
+	struct db_dest *pDB, *pDBfree;
+	int irq, i, err = 0;
+	struct resource *base, *macen, *macdma;
+
+	base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!base) {
+		dev_err(&pdev->dev, "failed to retrieve base register\n");
+		err = -ENODEV;
+		goto out;
+	}
+
+	macen = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!macen) {
+		dev_err(&pdev->dev, "failed to retrieve MAC Enable register\n");
+		err = -ENODEV;
+		goto out;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "failed to retrieve IRQ\n");
+		err = -ENODEV;
+		goto out;
+	}
+
+	macdma = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (!macdma) {
+		dev_err(&pdev->dev, "failed to retrieve MACDMA registers\n");
+		err = -ENODEV;
+		goto out;
+	}
+
+	if (!request_mem_region(base->start, resource_size(base),
+							pdev->name)) {
+		dev_err(&pdev->dev, "failed to request memory region for base registers\n");
+		err = -ENXIO;
+		goto out;
+	}
+
+	if (!request_mem_region(macen->start, resource_size(macen),
+							pdev->name)) {
+		dev_err(&pdev->dev, "failed to request memory region for MAC enable register\n");
+		err = -ENXIO;
+		goto err_request;
+	}
+
+	if (!request_mem_region(macdma->start, resource_size(macdma),
+							pdev->name)) {
+		dev_err(&pdev->dev, "failed to request MACDMA memory region\n");
+		err = -ENXIO;
+		goto err_macdma;
+	}
+
+	dev = alloc_etherdev(sizeof(struct au1000_private));
+	if (!dev) {
+		dev_err(&pdev->dev, "alloc_etherdev failed\n");
+		err = -ENOMEM;
+		goto err_alloc;
+	}
+
+	SET_NETDEV_DEV(dev, &pdev->dev);
+	platform_set_drvdata(pdev, dev);
+	aup = netdev_priv(dev);
+
+	spin_lock_init(&aup->lock);
+	aup->msg_enable = (au1000_debug < 4 ?
+				AU1000_DEF_MSG_ENABLE : au1000_debug);
+
+	/* Allocate the data buffers
+	 * Snooping works fine with eth on all au1xxx
+	 */
+	aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE *
+						(NUM_TX_BUFFS + NUM_RX_BUFFS),
+						&aup->dma_addr,	0);
+	if (!aup->vaddr) {
+		dev_err(&pdev->dev, "failed to allocate data buffers\n");
+		err = -ENOMEM;
+		goto err_vaddr;
+	}
+
+	/* aup->mac is the base address of the MAC's registers */
+	aup->mac = (struct mac_reg *)
+			ioremap_nocache(base->start, resource_size(base));
+	if (!aup->mac) {
+		dev_err(&pdev->dev, "failed to ioremap MAC registers\n");
+		err = -ENXIO;
+		goto err_remap1;
+	}
+
+	/* Setup some variables for quick register address access */
+	aup->enable = (u32 *)ioremap_nocache(macen->start,
+						resource_size(macen));
+	if (!aup->enable) {
+		dev_err(&pdev->dev, "failed to ioremap MAC enable register\n");
+		err = -ENXIO;
+		goto err_remap2;
+	}
+	aup->mac_id = pdev->id;
+
+	aup->macdma = ioremap_nocache(macdma->start, resource_size(macdma));
+	if (!aup->macdma) {
+		dev_err(&pdev->dev, "failed to ioremap MACDMA registers\n");
+		err = -ENXIO;
+		goto err_remap3;
+	}
+
+	au1000_setup_hw_rings(aup, aup->macdma);
+
+	/* set a random MAC now in case platform_data doesn't provide one */
+	random_ether_addr(dev->dev_addr);
+
+	writel(0, aup->enable);
+	aup->mac_enabled = 0;
+
+	pd = pdev->dev.platform_data;
+	if (!pd) {
+		dev_info(&pdev->dev, "no platform_data passed,"
+					" PHY search on MAC0\n");
+		aup->phy1_search_mac0 = 1;
+	} else {
+		if (is_valid_ether_addr(pd->mac))
+			memcpy(dev->dev_addr, pd->mac, 6);
+
+		aup->phy_static_config = pd->phy_static_config;
+		aup->phy_search_highest_addr = pd->phy_search_highest_addr;
+		aup->phy1_search_mac0 = pd->phy1_search_mac0;
+		aup->phy_addr = pd->phy_addr;
+		aup->phy_busid = pd->phy_busid;
+		aup->phy_irq = pd->phy_irq;
+	}
+
+	if (aup->phy_busid && aup->phy_busid > 0) {
+		dev_err(&pdev->dev, "MAC0-associated PHY attached 2nd MACs MII bus not supported yet\n");
+		err = -ENODEV;
+		goto err_mdiobus_alloc;
+	}
+
+	aup->mii_bus = mdiobus_alloc();
+	if (aup->mii_bus == NULL) {
+		dev_err(&pdev->dev, "failed to allocate mdiobus structure\n");
+		err = -ENOMEM;
+		goto err_mdiobus_alloc;
+	}
+
+	aup->mii_bus->priv = dev;
+	aup->mii_bus->read = au1000_mdiobus_read;
+	aup->mii_bus->write = au1000_mdiobus_write;
+	aup->mii_bus->reset = au1000_mdiobus_reset;
+	aup->mii_bus->name = "au1000_eth_mii";
+	snprintf(aup->mii_bus->id, MII_BUS_ID_SIZE, "%x", aup->mac_id);
+	aup->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+	if (aup->mii_bus->irq == NULL)
+		goto err_out;
+
+	for (i = 0; i < PHY_MAX_ADDR; ++i)
+		aup->mii_bus->irq[i] = PHY_POLL;
+	/* if known, set corresponding PHY IRQs */
+	if (aup->phy_static_config)
+		if (aup->phy_irq && aup->phy_busid == aup->mac_id)
+			aup->mii_bus->irq[aup->phy_addr] = aup->phy_irq;
+
+	err = mdiobus_register(aup->mii_bus);
+	if (err) {
+		dev_err(&pdev->dev, "failed to register MDIO bus\n");
+		goto err_mdiobus_reg;
+	}
+
+	if (au1000_mii_probe(dev) != 0)
+		goto err_out;
+
+	pDBfree = NULL;
+	/* setup the data buffer descriptors and attach a buffer to each one */
+	pDB = aup->db;
+	for (i = 0; i < (NUM_TX_BUFFS+NUM_RX_BUFFS); i++) {
+		pDB->pnext = pDBfree;
+		pDBfree = pDB;
+		pDB->vaddr = (u32 *)((unsigned)aup->vaddr + MAX_BUF_SIZE*i);
+		pDB->dma_addr = (dma_addr_t)virt_to_bus(pDB->vaddr);
+		pDB++;
+	}
+	aup->pDBfree = pDBfree;
+
+	for (i = 0; i < NUM_RX_DMA; i++) {
+		pDB = au1000_GetFreeDB(aup);
+		if (!pDB)
+			goto err_out;
+
+		aup->rx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
+		aup->rx_db_inuse[i] = pDB;
+	}
+	for (i = 0; i < NUM_TX_DMA; i++) {
+		pDB = au1000_GetFreeDB(aup);
+		if (!pDB)
+			goto err_out;
+
+		aup->tx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
+		aup->tx_dma_ring[i]->len = 0;
+		aup->tx_db_inuse[i] = pDB;
+	}
+
+	dev->base_addr = base->start;
+	dev->irq = irq;
+	dev->netdev_ops = &au1000_netdev_ops;
+	SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
+	dev->watchdog_timeo = ETH_TX_TIMEOUT;
+
+	/*
+	 * The boot code uses the ethernet controller, so reset it to start
+	 * fresh.  au1000_init() expects that the device is in reset state.
+	 */
+	au1000_reset_mac(dev);
+
+	err = register_netdev(dev);
+	if (err) {
+		netdev_err(dev, "Cannot register net device, aborting.\n");
+		goto err_out;
+	}
+
+	netdev_info(dev, "Au1xx0 Ethernet found at 0x%lx, irq %d\n",
+			(unsigned long)base->start, irq);
+	if (version_printed++ == 0)
+		pr_info("%s version %s %s\n",
+					DRV_NAME, DRV_VERSION, DRV_AUTHOR);
+
+	return 0;
+
+err_out:
+	if (aup->mii_bus != NULL)
+		mdiobus_unregister(aup->mii_bus);
+
+	/* here we should have a valid dev plus aup-> register addresses
+	 * so we can reset the mac properly.
+	 */
+	au1000_reset_mac(dev);
+
+	for (i = 0; i < NUM_RX_DMA; i++) {
+		if (aup->rx_db_inuse[i])
+			au1000_ReleaseDB(aup, aup->rx_db_inuse[i]);
+	}
+	for (i = 0; i < NUM_TX_DMA; i++) {
+		if (aup->tx_db_inuse[i])
+			au1000_ReleaseDB(aup, aup->tx_db_inuse[i]);
+	}
+err_mdiobus_reg:
+	mdiobus_free(aup->mii_bus);
+err_mdiobus_alloc:
+	iounmap(aup->macdma);
+err_remap3:
+	iounmap(aup->enable);
+err_remap2:
+	iounmap(aup->mac);
+err_remap1:
+	dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
+			     (void *)aup->vaddr, aup->dma_addr);
+err_vaddr:
+	free_netdev(dev);
+err_alloc:
+	release_mem_region(macdma->start, resource_size(macdma));
+err_macdma:
+	release_mem_region(macen->start, resource_size(macen));
+err_request:
+	release_mem_region(base->start, resource_size(base));
+out:
+	return err;
+}
+
+static int __devexit au1000_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct au1000_private *aup = netdev_priv(dev);
+	int i;
+	struct resource *base, *macen;
+
+	platform_set_drvdata(pdev, NULL);
+
+	unregister_netdev(dev);
+	mdiobus_unregister(aup->mii_bus);
+	mdiobus_free(aup->mii_bus);
+
+	for (i = 0; i < NUM_RX_DMA; i++)
+		if (aup->rx_db_inuse[i])
+			au1000_ReleaseDB(aup, aup->rx_db_inuse[i]);
+
+	for (i = 0; i < NUM_TX_DMA; i++)
+		if (aup->tx_db_inuse[i])
+			au1000_ReleaseDB(aup, aup->tx_db_inuse[i]);
+
+	dma_free_noncoherent(NULL, MAX_BUF_SIZE *
+			(NUM_TX_BUFFS + NUM_RX_BUFFS),
+			(void *)aup->vaddr, aup->dma_addr);
+
+	iounmap(aup->macdma);
+	iounmap(aup->mac);
+	iounmap(aup->enable);
+
+	base = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	release_mem_region(base->start, resource_size(base));
+
+	base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(base->start, resource_size(base));
+
+	macen = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	release_mem_region(macen->start, resource_size(macen));
+
+	free_netdev(dev);
+
+	return 0;
+}
+
+static struct platform_driver au1000_eth_driver = {
+	.probe  = au1000_probe,
+	.remove = __devexit_p(au1000_remove),
+	.driver = {
+		.name   = "au1000-eth",
+		.owner  = THIS_MODULE,
+	},
+};
+MODULE_ALIAS("platform:au1000-eth");
+
+
+static int __init au1000_init_module(void)
+{
+	return platform_driver_register(&au1000_eth_driver);
+}
+
+static void __exit au1000_exit_module(void)
+{
+	platform_driver_unregister(&au1000_eth_driver);
+}
+
+module_init(au1000_init_module);
+module_exit(au1000_exit_module);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/au1000_eth.h linux-libre-3.2-gnu/drivers/net/ethernet/amd/au1000_eth.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/au1000_eth.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/au1000_eth.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,134 @@
+/*
+ *
+ * Alchemy Au1x00 ethernet driver include file
+ *
+ * Author: Pete Popov <ppopov@mvista.com>
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ * ########################################################################
+ *
+ *  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.
+ *
+ * ########################################################################
+ *
+ *
+ */
+
+
+#define MAC_IOSIZE 0x10000
+#define NUM_RX_DMA 4       /* Au1x00 has 4 rx hardware descriptors */
+#define NUM_TX_DMA 4       /* Au1x00 has 4 tx hardware descriptors */
+
+#define NUM_RX_BUFFS 4
+#define NUM_TX_BUFFS 4
+#define MAX_BUF_SIZE 2048
+
+#define ETH_TX_TIMEOUT (HZ/4)
+#define MAC_MIN_PKT_SIZE 64
+
+#define MULTICAST_FILTER_LIMIT 64
+
+/*
+ * Data Buffer Descriptor. Data buffers must be aligned on 32 byte
+ * boundary for both, receive and transmit.
+ */
+struct db_dest {
+	struct db_dest *pnext;
+	u32 *vaddr;
+	dma_addr_t dma_addr;
+};
+
+/*
+ * The transmit and receive descriptors are memory
+ * mapped registers.
+ */
+struct tx_dma {
+	u32 status;
+	u32 buff_stat;
+	u32 len;
+	u32 pad;
+};
+
+struct rx_dma {
+	u32 status;
+	u32 buff_stat;
+	u32 pad[2];
+};
+
+
+/*
+ * MAC control registers, memory mapped.
+ */
+struct mac_reg {
+	u32 control;
+	u32 mac_addr_high;
+	u32 mac_addr_low;
+	u32 multi_hash_high;
+	u32 multi_hash_low;
+	u32 mii_control;
+	u32 mii_data;
+	u32 flow_control;
+	u32 vlan1_tag;
+	u32 vlan2_tag;
+};
+
+
+struct au1000_private {
+	struct db_dest *pDBfree;
+	struct db_dest db[NUM_RX_BUFFS+NUM_TX_BUFFS];
+	struct rx_dma *rx_dma_ring[NUM_RX_DMA];
+	struct tx_dma *tx_dma_ring[NUM_TX_DMA];
+	struct db_dest *rx_db_inuse[NUM_RX_DMA];
+	struct db_dest *tx_db_inuse[NUM_TX_DMA];
+	u32 rx_head;
+	u32 tx_head;
+	u32 tx_tail;
+	u32 tx_full;
+
+	int mac_id;
+
+	int mac_enabled;       /* whether MAC is currently enabled and running
+				* (req. for mdio)
+				*/
+
+	int old_link;          /* used by au1000_adjust_link */
+	int old_speed;
+	int old_duplex;
+
+	struct phy_device *phy_dev;
+	struct mii_bus *mii_bus;
+
+	/* PHY configuration */
+	int phy_static_config;
+	int phy_search_highest_addr;
+	int phy1_search_mac0;
+
+	int phy_addr;
+	int phy_busid;
+	int phy_irq;
+
+	/* These variables are just for quick access
+	 * to certain regs addresses.
+	 */
+	struct mac_reg *mac;  /* mac registers                      */
+	u32 *enable;     /* address of MAC Enable Register     */
+	void __iomem *macdma;	/* base of MAC DMA port */
+	u32 vaddr;                /* virtual address of rx/tx buffers   */
+	dma_addr_t dma_addr;      /* dma address of rx/tx buffers       */
+
+	spinlock_t lock;       /* Serialise access to device */
+
+	u32 msg_enable;
+};
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/declance.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/declance.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/declance.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/declance.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1381 @@
+/*
+ *    Lance ethernet driver for the MIPS processor based
+ *      DECstation family
+ *
+ *
+ *      adopted from sunlance.c by Richard van den Berg
+ *
+ *      Copyright (C) 2002, 2003, 2005, 2006  Maciej W. Rozycki
+ *
+ *      additional sources:
+ *      - PMAD-AA TURBOchannel Ethernet Module Functional Specification,
+ *        Revision 1.2
+ *
+ *      History:
+ *
+ *      v0.001: The kernel accepts the code and it shows the hardware address.
+ *
+ *      v0.002: Removed most sparc stuff, left only some module and dma stuff.
+ *
+ *      v0.003: Enhanced base address calculation from proposals by
+ *              Harald Koerfgen and Thomas Riemer.
+ *
+ *      v0.004: lance-regs is pointing at the right addresses, added prom
+ *              check. First start of address mapping and DMA.
+ *
+ *      v0.005: started to play around with LANCE-DMA. This driver will not
+ *              work for non IOASIC lances. HK
+ *
+ *      v0.006: added pointer arrays to lance_private and setup routine for
+ *              them in dec_lance_init. HK
+ *
+ *      v0.007: Big shit. The LANCE seems to use a different DMA mechanism to
+ *              access the init block. This looks like one (short) word at a
+ *              time, but the smallest amount the IOASIC can transfer is a
+ *              (long) word. So we have a 2-2 padding here. Changed
+ *              lance_init_block accordingly. The 16-16 padding for the buffers
+ *              seems to be correct. HK
+ *
+ *      v0.008: mods to make PMAX_LANCE work. 01/09/1999 triemer
+ *
+ *      v0.009: Module support fixes, multiple interfaces support, various
+ *              bits. macro
+ *
+ *      v0.010: Fixes for the PMAD mapping of the LANCE buffer and for the
+ *              PMAX requirement to only use halfword accesses to the
+ *              buffer. macro
+ *
+ *      v0.011: Converted the PMAD to the driver model. macro
+ */
+
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/if_ether.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/spinlock.h>
+#include <linux/stddef.h>
+#include <linux/string.h>
+#include <linux/tc.h>
+#include <linux/types.h>
+
+#include <asm/addrspace.h>
+#include <asm/system.h>
+
+#include <asm/dec/interrupts.h>
+#include <asm/dec/ioasic.h>
+#include <asm/dec/ioasic_addrs.h>
+#include <asm/dec/kn01.h>
+#include <asm/dec/machtype.h>
+#include <asm/dec/system.h>
+
+static char version[] __devinitdata =
+"declance.c: v0.011 by Linux MIPS DECstation task force\n";
+
+MODULE_AUTHOR("Linux MIPS DECstation task force");
+MODULE_DESCRIPTION("DEC LANCE (DECstation onboard, PMAD-xx) driver");
+MODULE_LICENSE("GPL");
+
+#define __unused __attribute__ ((unused))
+
+/*
+ * card types
+ */
+#define ASIC_LANCE 1
+#define PMAD_LANCE 2
+#define PMAX_LANCE 3
+
+
+#define LE_CSR0 0
+#define LE_CSR1 1
+#define LE_CSR2 2
+#define LE_CSR3 3
+
+#define LE_MO_PROM      0x8000	/* Enable promiscuous mode */
+
+#define	LE_C0_ERR	0x8000	/* Error: set if BAB, SQE, MISS or ME is set */
+#define	LE_C0_BABL	0x4000	/* BAB:  Babble: tx timeout. */
+#define	LE_C0_CERR	0x2000	/* SQE:  Signal quality error */
+#define	LE_C0_MISS	0x1000	/* MISS: Missed a packet */
+#define	LE_C0_MERR	0x0800	/* ME:   Memory error */
+#define	LE_C0_RINT	0x0400	/* Received interrupt */
+#define	LE_C0_TINT	0x0200	/* Transmitter Interrupt */
+#define	LE_C0_IDON	0x0100	/* IFIN: Init finished. */
+#define	LE_C0_INTR	0x0080	/* Interrupt or error */
+#define	LE_C0_INEA	0x0040	/* Interrupt enable */
+#define	LE_C0_RXON	0x0020	/* Receiver on */
+#define	LE_C0_TXON	0x0010	/* Transmitter on */
+#define	LE_C0_TDMD	0x0008	/* Transmitter demand */
+#define	LE_C0_STOP	0x0004	/* Stop the card */
+#define	LE_C0_STRT	0x0002	/* Start the card */
+#define	LE_C0_INIT	0x0001	/* Init the card */
+
+#define	LE_C3_BSWP	0x4	/* SWAP */
+#define	LE_C3_ACON	0x2	/* ALE Control */
+#define	LE_C3_BCON	0x1	/* Byte control */
+
+/* Receive message descriptor 1 */
+#define LE_R1_OWN	0x8000	/* Who owns the entry */
+#define LE_R1_ERR	0x4000	/* Error: if FRA, OFL, CRC or BUF is set */
+#define LE_R1_FRA	0x2000	/* FRA: Frame error */
+#define LE_R1_OFL	0x1000	/* OFL: Frame overflow */
+#define LE_R1_CRC	0x0800	/* CRC error */
+#define LE_R1_BUF	0x0400	/* BUF: Buffer error */
+#define LE_R1_SOP	0x0200	/* Start of packet */
+#define LE_R1_EOP	0x0100	/* End of packet */
+#define LE_R1_POK	0x0300	/* Packet is complete: SOP + EOP */
+
+/* Transmit message descriptor 1 */
+#define LE_T1_OWN	0x8000	/* Lance owns the packet */
+#define LE_T1_ERR	0x4000	/* Error summary */
+#define LE_T1_EMORE	0x1000	/* Error: more than one retry needed */
+#define LE_T1_EONE	0x0800	/* Error: one retry needed */
+#define LE_T1_EDEF	0x0400	/* Error: deferred */
+#define LE_T1_SOP	0x0200	/* Start of packet */
+#define LE_T1_EOP	0x0100	/* End of packet */
+#define LE_T1_POK	0x0300	/* Packet is complete: SOP + EOP */
+
+#define LE_T3_BUF       0x8000	/* Buffer error */
+#define LE_T3_UFL       0x4000	/* Error underflow */
+#define LE_T3_LCOL      0x1000	/* Error late collision */
+#define LE_T3_CLOS      0x0800	/* Error carrier loss */
+#define LE_T3_RTY       0x0400	/* Error retry */
+#define LE_T3_TDR       0x03ff	/* Time Domain Reflectometry counter */
+
+/* Define: 2^4 Tx buffers and 2^4 Rx buffers */
+
+#ifndef LANCE_LOG_TX_BUFFERS
+#define LANCE_LOG_TX_BUFFERS 4
+#define LANCE_LOG_RX_BUFFERS 4
+#endif
+
+#define TX_RING_SIZE			(1 << (LANCE_LOG_TX_BUFFERS))
+#define TX_RING_MOD_MASK		(TX_RING_SIZE - 1)
+
+#define RX_RING_SIZE			(1 << (LANCE_LOG_RX_BUFFERS))
+#define RX_RING_MOD_MASK		(RX_RING_SIZE - 1)
+
+#define PKT_BUF_SZ		1536
+#define RX_BUFF_SIZE            PKT_BUF_SZ
+#define TX_BUFF_SIZE            PKT_BUF_SZ
+
+#undef TEST_HITS
+#define ZERO 0
+
+/*
+ * The DS2100/3100 have a linear 64 kB buffer which supports halfword
+ * accesses only.  Each halfword of the buffer is word-aligned in the
+ * CPU address space.
+ *
+ * The PMAD-AA has a 128 kB buffer on-board.
+ *
+ * The IOASIC LANCE devices use a shared memory region.  This region
+ * as seen from the CPU is (max) 128 kB long and has to be on an 128 kB
+ * boundary.  The LANCE sees this as a 64 kB long continuous memory
+ * region.
+ *
+ * The LANCE's DMA address is used as an index in this buffer and DMA
+ * takes place in bursts of eight 16-bit words which are packed into
+ * four 32-bit words by the IOASIC.  This leads to a strange padding:
+ * 16 bytes of valid data followed by a 16 byte gap :-(.
+ */
+
+struct lance_rx_desc {
+	unsigned short rmd0;		/* low address of packet */
+	unsigned short rmd1;		/* high address of packet
+					   and descriptor bits */
+	short length;			/* 2s complement (negative!)
+					   of buffer length */
+	unsigned short mblength;	/* actual number of bytes received */
+};
+
+struct lance_tx_desc {
+	unsigned short tmd0;		/* low address of packet */
+	unsigned short tmd1;		/* high address of packet
+					   and descriptor bits */
+	short length;			/* 2s complement (negative!)
+					   of buffer length */
+	unsigned short misc;
+};
+
+
+/* First part of the LANCE initialization block, described in databook. */
+struct lance_init_block {
+	unsigned short mode;		/* pre-set mode (reg. 15) */
+
+	unsigned short phys_addr[3];	/* physical ethernet address */
+	unsigned short filter[4];	/* multicast filter */
+
+	/* Receive and transmit ring base, along with extra bits. */
+	unsigned short rx_ptr;		/* receive descriptor addr */
+	unsigned short rx_len;		/* receive len and high addr */
+	unsigned short tx_ptr;		/* transmit descriptor addr */
+	unsigned short tx_len;		/* transmit len and high addr */
+
+	short gap[4];
+
+	/* The buffer descriptors */
+	struct lance_rx_desc brx_ring[RX_RING_SIZE];
+	struct lance_tx_desc btx_ring[TX_RING_SIZE];
+};
+
+#define BUF_OFFSET_CPU sizeof(struct lance_init_block)
+#define BUF_OFFSET_LNC sizeof(struct lance_init_block)
+
+#define shift_off(off, type)						\
+	(type == ASIC_LANCE || type == PMAX_LANCE ? off << 1 : off)
+
+#define lib_off(rt, type)						\
+	shift_off(offsetof(struct lance_init_block, rt), type)
+
+#define lib_ptr(ib, rt, type) 						\
+	((volatile u16 *)((u8 *)(ib) + lib_off(rt, type)))
+
+#define rds_off(rt, type)						\
+	shift_off(offsetof(struct lance_rx_desc, rt), type)
+
+#define rds_ptr(rd, rt, type) 						\
+	((volatile u16 *)((u8 *)(rd) + rds_off(rt, type)))
+
+#define tds_off(rt, type)						\
+	shift_off(offsetof(struct lance_tx_desc, rt), type)
+
+#define tds_ptr(td, rt, type) 						\
+	((volatile u16 *)((u8 *)(td) + tds_off(rt, type)))
+
+struct lance_private {
+	struct net_device *next;
+	int type;
+	int dma_irq;
+	volatile struct lance_regs *ll;
+
+	spinlock_t	lock;
+
+	int rx_new, tx_new;
+	int rx_old, tx_old;
+
+	unsigned short busmaster_regval;
+
+	struct timer_list       multicast_timer;
+
+	/* Pointers to the ring buffers as seen from the CPU */
+	char *rx_buf_ptr_cpu[RX_RING_SIZE];
+	char *tx_buf_ptr_cpu[TX_RING_SIZE];
+
+	/* Pointers to the ring buffers as seen from the LANCE */
+	uint rx_buf_ptr_lnc[RX_RING_SIZE];
+	uint tx_buf_ptr_lnc[TX_RING_SIZE];
+};
+
+#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
+			lp->tx_old+TX_RING_MOD_MASK-lp->tx_new:\
+			lp->tx_old - lp->tx_new-1)
+
+/* The lance control ports are at an absolute address, machine and tc-slot
+ * dependent.
+ * DECstations do only 32-bit access and the LANCE uses 16 bit addresses,
+ * so we have to give the structure an extra member making rap pointing
+ * at the right address
+ */
+struct lance_regs {
+	volatile unsigned short rdp;	/* register data port */
+	unsigned short pad;
+	volatile unsigned short rap;	/* register address port */
+};
+
+int dec_lance_debug = 2;
+
+static struct tc_driver dec_lance_tc_driver;
+static struct net_device *root_lance_dev;
+
+static inline void writereg(volatile unsigned short *regptr, short value)
+{
+	*regptr = value;
+	iob();
+}
+
+/* Load the CSR registers */
+static void load_csrs(struct lance_private *lp)
+{
+	volatile struct lance_regs *ll = lp->ll;
+	uint leptr;
+
+	/* The address space as seen from the LANCE
+	 * begins at address 0. HK
+	 */
+	leptr = 0;
+
+	writereg(&ll->rap, LE_CSR1);
+	writereg(&ll->rdp, (leptr & 0xFFFF));
+	writereg(&ll->rap, LE_CSR2);
+	writereg(&ll->rdp, leptr >> 16);
+	writereg(&ll->rap, LE_CSR3);
+	writereg(&ll->rdp, lp->busmaster_regval);
+
+	/* Point back to csr0 */
+	writereg(&ll->rap, LE_CSR0);
+}
+
+/*
+ * Our specialized copy routines
+ *
+ */
+static void cp_to_buf(const int type, void *to, const void *from, int len)
+{
+	unsigned short *tp;
+	const unsigned short *fp;
+	unsigned short clen;
+	unsigned char *rtp;
+	const unsigned char *rfp;
+
+	if (type == PMAD_LANCE) {
+		memcpy(to, from, len);
+	} else if (type == PMAX_LANCE) {
+		clen = len >> 1;
+		tp = to;
+		fp = from;
+
+		while (clen--) {
+			*tp++ = *fp++;
+			tp++;
+		}
+
+		clen = len & 1;
+		rtp = tp;
+		rfp = fp;
+		while (clen--) {
+			*rtp++ = *rfp++;
+		}
+	} else {
+		/*
+		 * copy 16 Byte chunks
+		 */
+		clen = len >> 4;
+		tp = to;
+		fp = from;
+		while (clen--) {
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			tp += 8;
+		}
+
+		/*
+		 * do the rest, if any.
+		 */
+		clen = len & 15;
+		rtp = (unsigned char *) tp;
+		rfp = (unsigned char *) fp;
+		while (clen--) {
+			*rtp++ = *rfp++;
+		}
+	}
+
+	iob();
+}
+
+static void cp_from_buf(const int type, void *to, const void *from, int len)
+{
+	unsigned short *tp;
+	const unsigned short *fp;
+	unsigned short clen;
+	unsigned char *rtp;
+	const unsigned char *rfp;
+
+	if (type == PMAD_LANCE) {
+		memcpy(to, from, len);
+	} else if (type == PMAX_LANCE) {
+		clen = len >> 1;
+		tp = to;
+		fp = from;
+		while (clen--) {
+			*tp++ = *fp++;
+			fp++;
+		}
+
+		clen = len & 1;
+
+		rtp = tp;
+		rfp = fp;
+
+		while (clen--) {
+			*rtp++ = *rfp++;
+		}
+	} else {
+
+		/*
+		 * copy 16 Byte chunks
+		 */
+		clen = len >> 4;
+		tp = to;
+		fp = from;
+		while (clen--) {
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			fp += 8;
+		}
+
+		/*
+		 * do the rest, if any.
+		 */
+		clen = len & 15;
+		rtp = (unsigned char *) tp;
+		rfp = (unsigned char *) fp;
+		while (clen--) {
+			*rtp++ = *rfp++;
+		}
+
+
+	}
+
+}
+
+/* Setup the Lance Rx and Tx rings */
+static void lance_init_ring(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile u16 *ib = (volatile u16 *)dev->mem_start;
+	uint leptr;
+	int i;
+
+	/* Lock out other processes while setting up hardware */
+	netif_stop_queue(dev);
+	lp->rx_new = lp->tx_new = 0;
+	lp->rx_old = lp->tx_old = 0;
+
+	/* Copy the ethernet address to the lance init block.
+	 * XXX bit 0 of the physical address registers has to be zero
+	 */
+	*lib_ptr(ib, phys_addr[0], lp->type) = (dev->dev_addr[1] << 8) |
+				     dev->dev_addr[0];
+	*lib_ptr(ib, phys_addr[1], lp->type) = (dev->dev_addr[3] << 8) |
+				     dev->dev_addr[2];
+	*lib_ptr(ib, phys_addr[2], lp->type) = (dev->dev_addr[5] << 8) |
+				     dev->dev_addr[4];
+	/* Setup the initialization block */
+
+	/* Setup rx descriptor pointer */
+	leptr = offsetof(struct lance_init_block, brx_ring);
+	*lib_ptr(ib, rx_len, lp->type) = (LANCE_LOG_RX_BUFFERS << 13) |
+					 (leptr >> 16);
+	*lib_ptr(ib, rx_ptr, lp->type) = leptr;
+	if (ZERO)
+		printk("RX ptr: %8.8x(%8.8x)\n",
+		       leptr, lib_off(brx_ring, lp->type));
+
+	/* Setup tx descriptor pointer */
+	leptr = offsetof(struct lance_init_block, btx_ring);
+	*lib_ptr(ib, tx_len, lp->type) = (LANCE_LOG_TX_BUFFERS << 13) |
+					 (leptr >> 16);
+	*lib_ptr(ib, tx_ptr, lp->type) = leptr;
+	if (ZERO)
+		printk("TX ptr: %8.8x(%8.8x)\n",
+		       leptr, lib_off(btx_ring, lp->type));
+
+	if (ZERO)
+		printk("TX rings:\n");
+
+	/* Setup the Tx ring entries */
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		leptr = lp->tx_buf_ptr_lnc[i];
+		*lib_ptr(ib, btx_ring[i].tmd0, lp->type) = leptr;
+		*lib_ptr(ib, btx_ring[i].tmd1, lp->type) = (leptr >> 16) &
+							   0xff;
+		*lib_ptr(ib, btx_ring[i].length, lp->type) = 0xf000;
+						/* The ones required by tmd2 */
+		*lib_ptr(ib, btx_ring[i].misc, lp->type) = 0;
+		if (i < 3 && ZERO)
+			printk("%d: 0x%8.8x(0x%8.8x)\n",
+			       i, leptr, (uint)lp->tx_buf_ptr_cpu[i]);
+	}
+
+	/* Setup the Rx ring entries */
+	if (ZERO)
+		printk("RX rings:\n");
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		leptr = lp->rx_buf_ptr_lnc[i];
+		*lib_ptr(ib, brx_ring[i].rmd0, lp->type) = leptr;
+		*lib_ptr(ib, brx_ring[i].rmd1, lp->type) = ((leptr >> 16) &
+							    0xff) |
+							   LE_R1_OWN;
+		*lib_ptr(ib, brx_ring[i].length, lp->type) = -RX_BUFF_SIZE |
+							     0xf000;
+		*lib_ptr(ib, brx_ring[i].mblength, lp->type) = 0;
+		if (i < 3 && ZERO)
+			printk("%d: 0x%8.8x(0x%8.8x)\n",
+			       i, leptr, (uint)lp->rx_buf_ptr_cpu[i]);
+	}
+	iob();
+}
+
+static int init_restart_lance(struct lance_private *lp)
+{
+	volatile struct lance_regs *ll = lp->ll;
+	int i;
+
+	writereg(&ll->rap, LE_CSR0);
+	writereg(&ll->rdp, LE_C0_INIT);
+
+	/* Wait for the lance to complete initialization */
+	for (i = 0; (i < 100) && !(ll->rdp & LE_C0_IDON); i++) {
+		udelay(10);
+	}
+	if ((i == 100) || (ll->rdp & LE_C0_ERR)) {
+		printk("LANCE unopened after %d ticks, csr0=%4.4x.\n",
+		       i, ll->rdp);
+		return -1;
+	}
+	if ((ll->rdp & LE_C0_ERR)) {
+		printk("LANCE unopened after %d ticks, csr0=%4.4x.\n",
+		       i, ll->rdp);
+		return -1;
+	}
+	writereg(&ll->rdp, LE_C0_IDON);
+	writereg(&ll->rdp, LE_C0_STRT);
+	writereg(&ll->rdp, LE_C0_INEA);
+
+	return 0;
+}
+
+static int lance_rx(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile u16 *ib = (volatile u16 *)dev->mem_start;
+	volatile u16 *rd;
+	unsigned short bits;
+	int entry, len;
+	struct sk_buff *skb;
+
+#ifdef TEST_HITS
+	{
+		int i;
+
+		printk("[");
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			if (i == lp->rx_new)
+				printk("%s", *lib_ptr(ib, brx_ring[i].rmd1,
+						      lp->type) &
+					     LE_R1_OWN ? "_" : "X");
+			else
+				printk("%s", *lib_ptr(ib, brx_ring[i].rmd1,
+						      lp->type) &
+					     LE_R1_OWN ? "." : "1");
+		}
+		printk("]");
+	}
+#endif
+
+	for (rd = lib_ptr(ib, brx_ring[lp->rx_new], lp->type);
+	     !((bits = *rds_ptr(rd, rmd1, lp->type)) & LE_R1_OWN);
+	     rd = lib_ptr(ib, brx_ring[lp->rx_new], lp->type)) {
+		entry = lp->rx_new;
+
+		/* We got an incomplete frame? */
+		if ((bits & LE_R1_POK) != LE_R1_POK) {
+			dev->stats.rx_over_errors++;
+			dev->stats.rx_errors++;
+		} else if (bits & LE_R1_ERR) {
+			/* Count only the end frame as a rx error,
+			 * not the beginning
+			 */
+			if (bits & LE_R1_BUF)
+				dev->stats.rx_fifo_errors++;
+			if (bits & LE_R1_CRC)
+				dev->stats.rx_crc_errors++;
+			if (bits & LE_R1_OFL)
+				dev->stats.rx_over_errors++;
+			if (bits & LE_R1_FRA)
+				dev->stats.rx_frame_errors++;
+			if (bits & LE_R1_EOP)
+				dev->stats.rx_errors++;
+		} else {
+			len = (*rds_ptr(rd, mblength, lp->type) & 0xfff) - 4;
+			skb = dev_alloc_skb(len + 2);
+
+			if (skb == 0) {
+				printk("%s: Memory squeeze, deferring packet.\n",
+				       dev->name);
+				dev->stats.rx_dropped++;
+				*rds_ptr(rd, mblength, lp->type) = 0;
+				*rds_ptr(rd, rmd1, lp->type) =
+					((lp->rx_buf_ptr_lnc[entry] >> 16) &
+					 0xff) | LE_R1_OWN;
+				lp->rx_new = (entry + 1) & RX_RING_MOD_MASK;
+				return 0;
+			}
+			dev->stats.rx_bytes += len;
+
+			skb_reserve(skb, 2);	/* 16 byte align */
+			skb_put(skb, len);	/* make room */
+
+			cp_from_buf(lp->type, skb->data,
+				    (char *)lp->rx_buf_ptr_cpu[entry], len);
+
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+			dev->stats.rx_packets++;
+		}
+
+		/* Return the packet to the pool */
+		*rds_ptr(rd, mblength, lp->type) = 0;
+		*rds_ptr(rd, length, lp->type) = -RX_BUFF_SIZE | 0xf000;
+		*rds_ptr(rd, rmd1, lp->type) =
+			((lp->rx_buf_ptr_lnc[entry] >> 16) & 0xff) | LE_R1_OWN;
+		lp->rx_new = (entry + 1) & RX_RING_MOD_MASK;
+	}
+	return 0;
+}
+
+static void lance_tx(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile u16 *ib = (volatile u16 *)dev->mem_start;
+	volatile struct lance_regs *ll = lp->ll;
+	volatile u16 *td;
+	int i, j;
+	int status;
+
+	j = lp->tx_old;
+
+	spin_lock(&lp->lock);
+
+	for (i = j; i != lp->tx_new; i = j) {
+		td = lib_ptr(ib, btx_ring[i], lp->type);
+		/* If we hit a packet not owned by us, stop */
+		if (*tds_ptr(td, tmd1, lp->type) & LE_T1_OWN)
+			break;
+
+		if (*tds_ptr(td, tmd1, lp->type) & LE_T1_ERR) {
+			status = *tds_ptr(td, misc, lp->type);
+
+			dev->stats.tx_errors++;
+			if (status & LE_T3_RTY)
+				dev->stats.tx_aborted_errors++;
+			if (status & LE_T3_LCOL)
+				dev->stats.tx_window_errors++;
+
+			if (status & LE_T3_CLOS) {
+				dev->stats.tx_carrier_errors++;
+				printk("%s: Carrier Lost\n", dev->name);
+				/* Stop the lance */
+				writereg(&ll->rap, LE_CSR0);
+				writereg(&ll->rdp, LE_C0_STOP);
+				lance_init_ring(dev);
+				load_csrs(lp);
+				init_restart_lance(lp);
+				goto out;
+			}
+			/* Buffer errors and underflows turn off the
+			 * transmitter, restart the adapter.
+			 */
+			if (status & (LE_T3_BUF | LE_T3_UFL)) {
+				dev->stats.tx_fifo_errors++;
+
+				printk("%s: Tx: ERR_BUF|ERR_UFL, restarting\n",
+				       dev->name);
+				/* Stop the lance */
+				writereg(&ll->rap, LE_CSR0);
+				writereg(&ll->rdp, LE_C0_STOP);
+				lance_init_ring(dev);
+				load_csrs(lp);
+				init_restart_lance(lp);
+				goto out;
+			}
+		} else if ((*tds_ptr(td, tmd1, lp->type) & LE_T1_POK) ==
+			   LE_T1_POK) {
+			/*
+			 * So we don't count the packet more than once.
+			 */
+			*tds_ptr(td, tmd1, lp->type) &= ~(LE_T1_POK);
+
+			/* One collision before packet was sent. */
+			if (*tds_ptr(td, tmd1, lp->type) & LE_T1_EONE)
+				dev->stats.collisions++;
+
+			/* More than one collision, be optimistic. */
+			if (*tds_ptr(td, tmd1, lp->type) & LE_T1_EMORE)
+				dev->stats.collisions += 2;
+
+			dev->stats.tx_packets++;
+		}
+		j = (j + 1) & TX_RING_MOD_MASK;
+	}
+	lp->tx_old = j;
+out:
+	if (netif_queue_stopped(dev) &&
+	    TX_BUFFS_AVAIL > 0)
+		netif_wake_queue(dev);
+
+	spin_unlock(&lp->lock);
+}
+
+static irqreturn_t lance_dma_merr_int(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+
+	printk(KERN_ERR "%s: DMA error\n", dev->name);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t lance_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_regs *ll = lp->ll;
+	int csr0;
+
+	writereg(&ll->rap, LE_CSR0);
+	csr0 = ll->rdp;
+
+	/* Acknowledge all the interrupt sources ASAP */
+	writereg(&ll->rdp, csr0 & (LE_C0_INTR | LE_C0_TINT | LE_C0_RINT));
+
+	if ((csr0 & LE_C0_ERR)) {
+		/* Clear the error condition */
+		writereg(&ll->rdp, LE_C0_BABL | LE_C0_ERR | LE_C0_MISS |
+			 LE_C0_CERR | LE_C0_MERR);
+	}
+	if (csr0 & LE_C0_RINT)
+		lance_rx(dev);
+
+	if (csr0 & LE_C0_TINT)
+		lance_tx(dev);
+
+	if (csr0 & LE_C0_BABL)
+		dev->stats.tx_errors++;
+
+	if (csr0 & LE_C0_MISS)
+		dev->stats.rx_errors++;
+
+	if (csr0 & LE_C0_MERR) {
+		printk("%s: Memory error, status %04x\n", dev->name, csr0);
+
+		writereg(&ll->rdp, LE_C0_STOP);
+
+		lance_init_ring(dev);
+		load_csrs(lp);
+		init_restart_lance(lp);
+		netif_wake_queue(dev);
+	}
+
+	writereg(&ll->rdp, LE_C0_INEA);
+	writereg(&ll->rdp, LE_C0_INEA);
+	return IRQ_HANDLED;
+}
+
+static int lance_open(struct net_device *dev)
+{
+	volatile u16 *ib = (volatile u16 *)dev->mem_start;
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_regs *ll = lp->ll;
+	int status = 0;
+
+	/* Stop the Lance */
+	writereg(&ll->rap, LE_CSR0);
+	writereg(&ll->rdp, LE_C0_STOP);
+
+	/* Set mode and clear multicast filter only at device open,
+	 * so that lance_init_ring() called at any error will not
+	 * forget multicast filters.
+	 *
+	 * BTW it is common bug in all lance drivers! --ANK
+	 */
+	*lib_ptr(ib, mode, lp->type) = 0;
+	*lib_ptr(ib, filter[0], lp->type) = 0;
+	*lib_ptr(ib, filter[1], lp->type) = 0;
+	*lib_ptr(ib, filter[2], lp->type) = 0;
+	*lib_ptr(ib, filter[3], lp->type) = 0;
+
+	lance_init_ring(dev);
+	load_csrs(lp);
+
+	netif_start_queue(dev);
+
+	/* Associate IRQ with lance_interrupt */
+	if (request_irq(dev->irq, lance_interrupt, 0, "lance", dev)) {
+		printk("%s: Can't get IRQ %d\n", dev->name, dev->irq);
+		return -EAGAIN;
+	}
+	if (lp->dma_irq >= 0) {
+		unsigned long flags;
+
+		if (request_irq(lp->dma_irq, lance_dma_merr_int, 0,
+				"lance error", dev)) {
+			free_irq(dev->irq, dev);
+			printk("%s: Can't get DMA IRQ %d\n", dev->name,
+				lp->dma_irq);
+			return -EAGAIN;
+		}
+
+		spin_lock_irqsave(&ioasic_ssr_lock, flags);
+
+		fast_mb();
+		/* Enable I/O ASIC LANCE DMA.  */
+		ioasic_write(IO_REG_SSR,
+			     ioasic_read(IO_REG_SSR) | IO_SSR_LANCE_DMA_EN);
+
+		fast_mb();
+		spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
+	}
+
+	status = init_restart_lance(lp);
+	return status;
+}
+
+static int lance_close(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_regs *ll = lp->ll;
+
+	netif_stop_queue(dev);
+	del_timer_sync(&lp->multicast_timer);
+
+	/* Stop the card */
+	writereg(&ll->rap, LE_CSR0);
+	writereg(&ll->rdp, LE_C0_STOP);
+
+	if (lp->dma_irq >= 0) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&ioasic_ssr_lock, flags);
+
+		fast_mb();
+		/* Disable I/O ASIC LANCE DMA.  */
+		ioasic_write(IO_REG_SSR,
+			     ioasic_read(IO_REG_SSR) & ~IO_SSR_LANCE_DMA_EN);
+
+		fast_iob();
+		spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
+
+		free_irq(lp->dma_irq, dev);
+	}
+	free_irq(dev->irq, dev);
+	return 0;
+}
+
+static inline int lance_reset(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_regs *ll = lp->ll;
+	int status;
+
+	/* Stop the lance */
+	writereg(&ll->rap, LE_CSR0);
+	writereg(&ll->rdp, LE_C0_STOP);
+
+	lance_init_ring(dev);
+	load_csrs(lp);
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	status = init_restart_lance(lp);
+	return status;
+}
+
+static void lance_tx_timeout(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_regs *ll = lp->ll;
+
+	printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n",
+		dev->name, ll->rdp);
+	lance_reset(dev);
+	netif_wake_queue(dev);
+}
+
+static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_regs *ll = lp->ll;
+	volatile u16 *ib = (volatile u16 *)dev->mem_start;
+	unsigned long flags;
+	int entry, len;
+
+	len = skb->len;
+
+	if (len < ETH_ZLEN) {
+		if (skb_padto(skb, ETH_ZLEN))
+			return NETDEV_TX_OK;
+		len = ETH_ZLEN;
+	}
+
+	dev->stats.tx_bytes += len;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	entry = lp->tx_new;
+	*lib_ptr(ib, btx_ring[entry].length, lp->type) = (-len);
+	*lib_ptr(ib, btx_ring[entry].misc, lp->type) = 0;
+
+	cp_to_buf(lp->type, (char *)lp->tx_buf_ptr_cpu[entry], skb->data, len);
+
+	/* Now, give the packet to the lance */
+	*lib_ptr(ib, btx_ring[entry].tmd1, lp->type) =
+		((lp->tx_buf_ptr_lnc[entry] >> 16) & 0xff) |
+		(LE_T1_POK | LE_T1_OWN);
+	lp->tx_new = (entry + 1) & TX_RING_MOD_MASK;
+
+	if (TX_BUFFS_AVAIL <= 0)
+		netif_stop_queue(dev);
+
+	/* Kick the lance: transmit now */
+	writereg(&ll->rdp, LE_C0_INEA | LE_C0_TDMD);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	dev_kfree_skb(skb);
+
+ 	return NETDEV_TX_OK;
+}
+
+static void lance_load_multicast(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile u16 *ib = (volatile u16 *)dev->mem_start;
+	struct netdev_hw_addr *ha;
+	u32 crc;
+
+	/* set all multicast bits */
+	if (dev->flags & IFF_ALLMULTI) {
+		*lib_ptr(ib, filter[0], lp->type) = 0xffff;
+		*lib_ptr(ib, filter[1], lp->type) = 0xffff;
+		*lib_ptr(ib, filter[2], lp->type) = 0xffff;
+		*lib_ptr(ib, filter[3], lp->type) = 0xffff;
+		return;
+	}
+	/* clear the multicast filter */
+	*lib_ptr(ib, filter[0], lp->type) = 0;
+	*lib_ptr(ib, filter[1], lp->type) = 0;
+	*lib_ptr(ib, filter[2], lp->type) = 0;
+	*lib_ptr(ib, filter[3], lp->type) = 0;
+
+	/* Add addresses */
+	netdev_for_each_mc_addr(ha, dev) {
+		crc = ether_crc_le(ETH_ALEN, ha->addr);
+		crc = crc >> 26;
+		*lib_ptr(ib, filter[crc >> 4], lp->type) |= 1 << (crc & 0xf);
+	}
+}
+
+static void lance_set_multicast(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	volatile u16 *ib = (volatile u16 *)dev->mem_start;
+	volatile struct lance_regs *ll = lp->ll;
+
+	if (!netif_running(dev))
+		return;
+
+	if (lp->tx_old != lp->tx_new) {
+		mod_timer(&lp->multicast_timer, jiffies + 4 * HZ/100);
+		netif_wake_queue(dev);
+		return;
+	}
+
+	netif_stop_queue(dev);
+
+	writereg(&ll->rap, LE_CSR0);
+	writereg(&ll->rdp, LE_C0_STOP);
+
+	lance_init_ring(dev);
+
+	if (dev->flags & IFF_PROMISC) {
+		*lib_ptr(ib, mode, lp->type) |= LE_MO_PROM;
+	} else {
+		*lib_ptr(ib, mode, lp->type) &= ~LE_MO_PROM;
+		lance_load_multicast(dev);
+	}
+	load_csrs(lp);
+	init_restart_lance(lp);
+	netif_wake_queue(dev);
+}
+
+static void lance_set_multicast_retry(unsigned long _opaque)
+{
+	struct net_device *dev = (struct net_device *) _opaque;
+
+	lance_set_multicast(dev);
+}
+
+static const struct net_device_ops lance_netdev_ops = {
+	.ndo_open		= lance_open,
+	.ndo_stop		= lance_close,
+	.ndo_start_xmit		= lance_start_xmit,
+	.ndo_tx_timeout		= lance_tx_timeout,
+	.ndo_set_rx_mode	= lance_set_multicast,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
+static int __devinit dec_lance_probe(struct device *bdev, const int type)
+{
+	static unsigned version_printed;
+	static const char fmt[] = "declance%d";
+	char name[10];
+	struct net_device *dev;
+	struct lance_private *lp;
+	volatile struct lance_regs *ll;
+	resource_size_t start = 0, len = 0;
+	int i, ret;
+	unsigned long esar_base;
+	unsigned char *esar;
+
+	if (dec_lance_debug && version_printed++ == 0)
+		printk(version);
+
+	if (bdev)
+		snprintf(name, sizeof(name), "%s", dev_name(bdev));
+	else {
+		i = 0;
+		dev = root_lance_dev;
+		while (dev) {
+			i++;
+			lp = netdev_priv(dev);
+			dev = lp->next;
+		}
+		snprintf(name, sizeof(name), fmt, i);
+	}
+
+	dev = alloc_etherdev(sizeof(struct lance_private));
+	if (!dev) {
+		printk(KERN_ERR "%s: Unable to allocate etherdev, aborting.\n",
+			name);
+		ret = -ENOMEM;
+		goto err_out;
+	}
+
+	/*
+	 * alloc_etherdev ensures the data structures used by the LANCE
+	 * are aligned.
+	 */
+	lp = netdev_priv(dev);
+	spin_lock_init(&lp->lock);
+
+	lp->type = type;
+	switch (type) {
+	case ASIC_LANCE:
+		dev->base_addr = CKSEG1ADDR(dec_kn_slot_base + IOASIC_LANCE);
+
+		/* buffer space for the on-board LANCE shared memory */
+		/*
+		 * FIXME: ugly hack!
+		 */
+		dev->mem_start = CKSEG1ADDR(0x00020000);
+		dev->mem_end = dev->mem_start + 0x00020000;
+		dev->irq = dec_interrupt[DEC_IRQ_LANCE];
+		esar_base = CKSEG1ADDR(dec_kn_slot_base + IOASIC_ESAR);
+
+		/* Workaround crash with booting KN04 2.1k from Disk */
+		memset((void *)dev->mem_start, 0,
+		       dev->mem_end - dev->mem_start);
+
+		/*
+		 * setup the pointer arrays, this sucks [tm] :-(
+		 */
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			lp->rx_buf_ptr_cpu[i] =
+				(char *)(dev->mem_start + 2 * BUF_OFFSET_CPU +
+					 2 * i * RX_BUFF_SIZE);
+			lp->rx_buf_ptr_lnc[i] =
+				(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
+		}
+		for (i = 0; i < TX_RING_SIZE; i++) {
+			lp->tx_buf_ptr_cpu[i] =
+				(char *)(dev->mem_start + 2 * BUF_OFFSET_CPU +
+					 2 * RX_RING_SIZE * RX_BUFF_SIZE +
+					 2 * i * TX_BUFF_SIZE);
+			lp->tx_buf_ptr_lnc[i] =
+				(BUF_OFFSET_LNC +
+				 RX_RING_SIZE * RX_BUFF_SIZE +
+				 i * TX_BUFF_SIZE);
+		}
+
+		/* Setup I/O ASIC LANCE DMA.  */
+		lp->dma_irq = dec_interrupt[DEC_IRQ_LANCE_MERR];
+		ioasic_write(IO_REG_LANCE_DMA_P,
+			     CPHYSADDR(dev->mem_start) << 3);
+
+		break;
+#ifdef CONFIG_TC
+	case PMAD_LANCE:
+		dev_set_drvdata(bdev, dev);
+
+		start = to_tc_dev(bdev)->resource.start;
+		len = to_tc_dev(bdev)->resource.end - start + 1;
+		if (!request_mem_region(start, len, dev_name(bdev))) {
+			printk(KERN_ERR
+			       "%s: Unable to reserve MMIO resource\n",
+			       dev_name(bdev));
+			ret = -EBUSY;
+			goto err_out_dev;
+		}
+
+		dev->mem_start = CKSEG1ADDR(start);
+		dev->mem_end = dev->mem_start + 0x100000;
+		dev->base_addr = dev->mem_start + 0x100000;
+		dev->irq = to_tc_dev(bdev)->interrupt;
+		esar_base = dev->mem_start + 0x1c0002;
+		lp->dma_irq = -1;
+
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			lp->rx_buf_ptr_cpu[i] =
+				(char *)(dev->mem_start + BUF_OFFSET_CPU +
+					 i * RX_BUFF_SIZE);
+			lp->rx_buf_ptr_lnc[i] =
+				(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
+		}
+		for (i = 0; i < TX_RING_SIZE; i++) {
+			lp->tx_buf_ptr_cpu[i] =
+				(char *)(dev->mem_start + BUF_OFFSET_CPU +
+					 RX_RING_SIZE * RX_BUFF_SIZE +
+					 i * TX_BUFF_SIZE);
+			lp->tx_buf_ptr_lnc[i] =
+				(BUF_OFFSET_LNC +
+				 RX_RING_SIZE * RX_BUFF_SIZE +
+				 i * TX_BUFF_SIZE);
+		}
+
+		break;
+#endif
+	case PMAX_LANCE:
+		dev->irq = dec_interrupt[DEC_IRQ_LANCE];
+		dev->base_addr = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE);
+		dev->mem_start = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE_MEM);
+		dev->mem_end = dev->mem_start + KN01_SLOT_SIZE;
+		esar_base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_ESAR + 1);
+		lp->dma_irq = -1;
+
+		/*
+		 * setup the pointer arrays, this sucks [tm] :-(
+		 */
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			lp->rx_buf_ptr_cpu[i] =
+				(char *)(dev->mem_start + 2 * BUF_OFFSET_CPU +
+					 2 * i * RX_BUFF_SIZE);
+			lp->rx_buf_ptr_lnc[i] =
+				(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
+		}
+		for (i = 0; i < TX_RING_SIZE; i++) {
+			lp->tx_buf_ptr_cpu[i] =
+				(char *)(dev->mem_start + 2 * BUF_OFFSET_CPU +
+					 2 * RX_RING_SIZE * RX_BUFF_SIZE +
+					 2 * i * TX_BUFF_SIZE);
+			lp->tx_buf_ptr_lnc[i] =
+				(BUF_OFFSET_LNC +
+				 RX_RING_SIZE * RX_BUFF_SIZE +
+				 i * TX_BUFF_SIZE);
+		}
+
+		break;
+
+	default:
+		printk(KERN_ERR "%s: declance_init called with unknown type\n",
+			name);
+		ret = -ENODEV;
+		goto err_out_dev;
+	}
+
+	ll = (struct lance_regs *) dev->base_addr;
+	esar = (unsigned char *) esar_base;
+
+	/* prom checks */
+	/* First, check for test pattern */
+	if (esar[0x60] != 0xff && esar[0x64] != 0x00 &&
+	    esar[0x68] != 0x55 && esar[0x6c] != 0xaa) {
+		printk(KERN_ERR
+			"%s: Ethernet station address prom not found!\n",
+			name);
+		ret = -ENODEV;
+		goto err_out_resource;
+	}
+	/* Check the prom contents */
+	for (i = 0; i < 8; i++) {
+		if (esar[i * 4] != esar[0x3c - i * 4] &&
+		    esar[i * 4] != esar[0x40 + i * 4] &&
+		    esar[0x3c - i * 4] != esar[0x40 + i * 4]) {
+			printk(KERN_ERR "%s: Something is wrong with the "
+				"ethernet station address prom!\n", name);
+			ret = -ENODEV;
+			goto err_out_resource;
+		}
+	}
+
+	/* Copy the ethernet address to the device structure, later to the
+	 * lance initialization block so the lance gets it every time it's
+	 * (re)initialized.
+	 */
+	switch (type) {
+	case ASIC_LANCE:
+		printk("%s: IOASIC onboard LANCE", name);
+		break;
+	case PMAD_LANCE:
+		printk("%s: PMAD-AA", name);
+		break;
+	case PMAX_LANCE:
+		printk("%s: PMAX onboard LANCE", name);
+		break;
+	}
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = esar[i * 4];
+
+	printk(", addr = %pM, irq = %d\n", dev->dev_addr, dev->irq);
+
+	dev->netdev_ops = &lance_netdev_ops;
+	dev->watchdog_timeo = 5*HZ;
+
+	/* lp->ll is the location of the registers for lance card */
+	lp->ll = ll;
+
+	/* busmaster_regval (CSR3) should be zero according to the PMAD-AA
+	 * specification.
+	 */
+	lp->busmaster_regval = 0;
+
+	dev->dma = 0;
+
+	/* We cannot sleep if the chip is busy during a
+	 * multicast list update event, because such events
+	 * can occur from interrupts (ex. IPv6).  So we
+	 * use a timer to try again later when necessary. -DaveM
+	 */
+	init_timer(&lp->multicast_timer);
+	lp->multicast_timer.data = (unsigned long) dev;
+	lp->multicast_timer.function = lance_set_multicast_retry;
+
+	ret = register_netdev(dev);
+	if (ret) {
+		printk(KERN_ERR
+			"%s: Unable to register netdev, aborting.\n", name);
+		goto err_out_resource;
+	}
+
+	if (!bdev) {
+		lp->next = root_lance_dev;
+		root_lance_dev = dev;
+	}
+
+	printk("%s: registered as %s.\n", name, dev->name);
+	return 0;
+
+err_out_resource:
+	if (bdev)
+		release_mem_region(start, len);
+
+err_out_dev:
+	free_netdev(dev);
+
+err_out:
+	return ret;
+}
+
+static void __exit dec_lance_remove(struct device *bdev)
+{
+	struct net_device *dev = dev_get_drvdata(bdev);
+	resource_size_t start, len;
+
+	unregister_netdev(dev);
+	start = to_tc_dev(bdev)->resource.start;
+	len = to_tc_dev(bdev)->resource.end - start + 1;
+	release_mem_region(start, len);
+	free_netdev(dev);
+}
+
+/* Find all the lance cards on the system and initialize them */
+static int __init dec_lance_platform_probe(void)
+{
+	int count = 0;
+
+	if (dec_interrupt[DEC_IRQ_LANCE] >= 0) {
+		if (dec_interrupt[DEC_IRQ_LANCE_MERR] >= 0) {
+			if (dec_lance_probe(NULL, ASIC_LANCE) >= 0)
+				count++;
+		} else if (!TURBOCHANNEL) {
+			if (dec_lance_probe(NULL, PMAX_LANCE) >= 0)
+				count++;
+		}
+	}
+
+	return (count > 0) ? 0 : -ENODEV;
+}
+
+static void __exit dec_lance_platform_remove(void)
+{
+	while (root_lance_dev) {
+		struct net_device *dev = root_lance_dev;
+		struct lance_private *lp = netdev_priv(dev);
+
+		unregister_netdev(dev);
+		root_lance_dev = lp->next;
+		free_netdev(dev);
+	}
+}
+
+#ifdef CONFIG_TC
+static int __devinit dec_lance_tc_probe(struct device *dev);
+static int __exit dec_lance_tc_remove(struct device *dev);
+
+static const struct tc_device_id dec_lance_tc_table[] = {
+	{ "DEC     ", "PMAD-AA " },
+	{ }
+};
+MODULE_DEVICE_TABLE(tc, dec_lance_tc_table);
+
+static struct tc_driver dec_lance_tc_driver = {
+	.id_table	= dec_lance_tc_table,
+	.driver		= {
+		.name	= "declance",
+		.bus	= &tc_bus_type,
+		.probe	= dec_lance_tc_probe,
+		.remove	= __exit_p(dec_lance_tc_remove),
+	},
+};
+
+static int __devinit dec_lance_tc_probe(struct device *dev)
+{
+        int status = dec_lance_probe(dev, PMAD_LANCE);
+        if (!status)
+                get_device(dev);
+        return status;
+}
+
+static int __exit dec_lance_tc_remove(struct device *dev)
+{
+        put_device(dev);
+        dec_lance_remove(dev);
+        return 0;
+}
+#endif
+
+static int __init dec_lance_init(void)
+{
+	int status;
+
+	status = tc_register_driver(&dec_lance_tc_driver);
+	if (!status)
+		dec_lance_platform_probe();
+	return status;
+}
+
+static void __exit dec_lance_exit(void)
+{
+	dec_lance_platform_remove();
+	tc_unregister_driver(&dec_lance_tc_driver);
+}
+
+
+module_init(dec_lance_init);
+module_exit(dec_lance_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/depca.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/depca.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/depca.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/depca.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2111 @@
+/*  depca.c: A DIGITAL DEPCA & EtherWORKS ethernet driver for linux.
+
+    Written 1994, 1995 by David C. Davies.
+
+
+                      Copyright 1994 David C. Davies
+		                   and
+			 United States Government
+	 (as represented by the Director, National Security Agency).
+
+               Copyright 1995  Digital Equipment Corporation.
+
+
+    This software may be used and distributed according to the terms of
+    the GNU General Public License, incorporated herein by reference.
+
+    This driver is written for the Digital Equipment Corporation series
+    of DEPCA and EtherWORKS ethernet cards:
+
+        DEPCA       (the original)
+    	DE100
+    	DE101
+	DE200 Turbo
+	DE201 Turbo
+	DE202 Turbo (TP BNC)
+	DE210
+	DE422       (EISA)
+
+    The  driver has been tested on DE100, DE200 and DE202 cards  in  a
+    relatively busy network. The DE422 has been tested a little.
+
+    This  driver will NOT work   for the DE203,  DE204  and DE205 series  of
+    cards,  since they have  a  new custom ASIC in   place of the AMD  LANCE
+    chip.  See the 'ewrk3.c'   driver in the  Linux  source tree for running
+    those cards.
+
+    I have benchmarked the driver with a  DE100 at 595kB/s to (542kB/s from)
+    a DECstation 5000/200.
+
+    The author may be reached at davies@maniac.ultranet.com
+
+    =========================================================================
+
+    The  driver was originally based  on   the 'lance.c' driver from  Donald
+    Becker   which  is included with  the  standard  driver distribution for
+    linux.  V0.4  is  a complete  re-write  with only  the kernel  interface
+    remaining from the original code.
+
+    1) Lance.c code in /linux/drivers/net/
+    2) "Ethernet/IEEE 802.3 Family. 1992 World Network Data Book/Handbook",
+       AMD, 1992 [(800) 222-9323].
+    3) "Am79C90 CMOS Local Area Network Controller for Ethernet (C-LANCE)",
+       AMD, Pub. #17881, May 1993.
+    4) "Am79C960 PCnet-ISA(tm), Single-Chip Ethernet Controller for ISA",
+       AMD, Pub. #16907, May 1992
+    5) "DEC EtherWORKS LC Ethernet Controller Owners Manual",
+       Digital Equipment corporation, 1990, Pub. #EK-DE100-OM.003
+    6) "DEC EtherWORKS Turbo Ethernet Controller Owners Manual",
+       Digital Equipment corporation, 1990, Pub. #EK-DE200-OM.003
+    7) "DEPCA Hardware Reference Manual", Pub. #EK-DEPCA-PR
+       Digital Equipment Corporation, 1989
+    8) "DEC EtherWORKS Turbo_(TP BNC) Ethernet Controller Owners Manual",
+       Digital Equipment corporation, 1991, Pub. #EK-DE202-OM.001
+
+
+    Peter Bauer's depca.c (V0.5) was referred to when debugging V0.1 of this
+    driver.
+
+    The original DEPCA  card requires that the  ethernet ROM address counter
+    be enabled to count and has an 8 bit NICSR.  The ROM counter enabling is
+    only  done when a  0x08 is read as the  first address octet (to minimise
+    the chances  of writing over some  other hardware's  I/O register).  The
+    NICSR accesses   have been changed  to  byte accesses  for all the cards
+    supported by this driver, since there is only one  useful bit in the MSB
+    (remote boot timeout) and it  is not used.  Also, there  is a maximum of
+    only 48kB network  RAM for this  card.  My thanks  to Torbjorn Lindh for
+    help debugging all this (and holding my feet to  the fire until I got it
+    right).
+
+    The DE200  series  boards have  on-board 64kB  RAM for  use  as a shared
+    memory network  buffer. Only the DE100  cards make use  of a  2kB buffer
+    mode which has not  been implemented in  this driver (only the 32kB  and
+    64kB modes are supported [16kB/48kB for the original DEPCA]).
+
+    At the most only 2 DEPCA cards can  be supported on  the ISA bus because
+    there is only provision  for two I/O base addresses  on each card (0x300
+    and 0x200). The I/O address is detected by searching for a byte sequence
+    in the Ethernet station address PROM at the expected I/O address for the
+    Ethernet  PROM.   The shared memory  base   address  is 'autoprobed'  by
+    looking  for the self  test PROM  and detecting the  card name.   When a
+    second  DEPCA is  detected,  information  is   placed in the   base_addr
+    variable of the  next device structure (which  is created if necessary),
+    thus  enabling ethif_probe  initialization  for the device.  More than 2
+    EISA cards can  be  supported, but  care will  be  needed assigning  the
+    shared memory to ensure that each slot has the  correct IRQ, I/O address
+    and shared memory address assigned.
+
+    ************************************************************************
+
+    NOTE: If you are using two  ISA DEPCAs, it is  important that you assign
+    the base memory addresses correctly.   The  driver autoprobes I/O  0x300
+    then 0x200.  The  base memory address for  the first device must be less
+    than that of the second so that the auto probe will correctly assign the
+    I/O and memory addresses on the same card.  I can't think of a way to do
+    this unambiguously at the moment, since there is nothing on the cards to
+    tie I/O and memory information together.
+
+    I am unable  to  test  2 cards   together for now,    so this  code   is
+    unchecked. All reports, good or bad, are welcome.
+
+    ************************************************************************
+
+    The board IRQ   setting must be  at an  unused IRQ which  is auto-probed
+    using Donald Becker's autoprobe routines. DEPCA and DE100 board IRQs are
+    {2,3,4,5,7}, whereas the  DE200 is at {5,9,10,11,15}.  Note that IRQ2 is
+    really IRQ9 in machines with 16 IRQ lines.
+
+    No 16MB memory  limitation should exist with this  driver as DMA is  not
+    used and the common memory area is in low memory on the network card (my
+    current system has 20MB and I've not had problems yet).
+
+    The ability to load this driver as a loadable module has been added. To
+    utilise this ability, you have to do <8 things:
+
+    0) have a copy of the loadable modules code installed on your system.
+    1) copy depca.c from the  /linux/drivers/net directory to your favourite
+    temporary directory.
+    2) if you wish, edit the  source code near  line 1530 to reflect the I/O
+    address and IRQ you're using (see also 5).
+    3) compile  depca.c, but include -DMODULE in  the command line to ensure
+    that the correct bits are compiled (see end of source code).
+    4) if you are wanting to add a new  card, goto 5. Otherwise, recompile a
+    kernel with the depca configuration turned off and reboot.
+    5) insmod depca.o [irq=7] [io=0x200] [mem=0xd0000] [adapter_name=DE100]
+       [Alan Cox: Changed the code to allow command line irq/io assignments]
+       [Dave Davies: Changed the code to allow command line mem/name
+                                                                assignments]
+    6) run the net startup bits for your eth?? interface manually
+    (usually /etc/rc.inet[12] at boot time).
+    7) enjoy!
+
+    Note that autoprobing is not allowed in loadable modules - the system is
+    already up and running and you're messing with interrupts.
+
+    To unload a module, turn off the associated interface
+    'ifconfig eth?? down' then 'rmmod depca'.
+
+    To assign a base memory address for the shared memory  when running as a
+    loadable module, see 5 above.  To include the adapter  name (if you have
+    no PROM  but know the card name)  also see 5  above. Note that this last
+    option  will not work  with kernel  built-in  depca's.
+
+    The shared memory assignment for a loadable module  makes sense to avoid
+    the 'memory autoprobe' picking the wrong shared memory  (for the case of
+    2 depca's in a PC).
+
+    ************************************************************************
+    Support for MCA EtherWORKS cards added 11-3-98.
+    Verified to work with up to 2 DE212 cards in a system (although not
+      fully stress-tested).
+
+    Currently known bugs/limitations:
+
+    Note:  with the MCA stuff as a module, it trusts the MCA configuration,
+           not the command line for IRQ and memory address.  You can
+           specify them if you want, but it will throw your values out.
+           You still have to pass the IO address it was configured as
+           though.
+
+    ************************************************************************
+    TO DO:
+    ------
+
+
+    Revision History
+    ----------------
+
+    Version   Date        Description
+
+      0.1     25-jan-94   Initial writing.
+      0.2     27-jan-94   Added LANCE TX hardware buffer chaining.
+      0.3      1-feb-94   Added multiple DEPCA support.
+      0.31     4-feb-94   Added DE202 recognition.
+      0.32    19-feb-94   Tidy up. Improve multi-DEPCA support.
+      0.33    25-feb-94   Fix DEPCA ethernet ROM counter enable.
+                          Add jabber packet fix from murf@perftech.com
+			  and becker@super.org
+      0.34     7-mar-94   Fix DEPCA max network memory RAM & NICSR access.
+      0.35     8-mar-94   Added DE201 recognition. Tidied up.
+      0.351   30-apr-94   Added EISA support. Added DE422 recognition.
+      0.36    16-may-94   DE422 fix released.
+      0.37    22-jul-94   Added MODULE support
+      0.38    15-aug-94   Added DBR ROM switch in depca_close().
+                          Multi DEPCA bug fix.
+      0.38axp 15-sep-94   Special version for Alpha AXP Linux V1.0.
+      0.381   12-dec-94   Added DE101 recognition, fix multicast bug.
+      0.382    9-feb-95   Fix recognition bug reported by <bkm@star.rl.ac.uk>.
+      0.383   22-feb-95   Fix for conflict with VESA SCSI reported by
+                          <stromain@alf.dec.com>
+      0.384   17-mar-95   Fix a ring full bug reported by <bkm@star.rl.ac.uk>
+      0.385    3-apr-95   Fix a recognition bug reported by
+                                                <ryan.niemi@lastfrontier.com>
+      0.386   21-apr-95   Fix the last fix...sorry, must be galloping senility
+      0.40    25-May-95   Rewrite for portability & updated.
+                          ALPHA support from <jestabro@amt.tay1.dec.com>
+      0.41    26-Jun-95   Added verify_area() calls in depca_ioctl() from
+                          suggestion by <heiko@colossus.escape.de>
+      0.42    27-Dec-95   Add 'mem' shared memory assignment for loadable
+                          modules.
+                          Add 'adapter_name' for loadable modules when no PROM.
+			  Both above from a suggestion by
+			  <pchen@woodruffs121.residence.gatech.edu>.
+			  Add new multicasting code.
+      0.421   22-Apr-96	  Fix alloc_device() bug <jari@markkus2.fimr.fi>
+      0.422   29-Apr-96	  Fix depca_hw_init() bug <jari@markkus2.fimr.fi>
+      0.423    7-Jun-96   Fix module load bug <kmg@barco.be>
+      0.43    16-Aug-96   Update alloc_device() to conform to de4x5.c
+      0.44     1-Sep-97   Fix *_probe() to test check_region() first - bug
+                           reported by <mmogilvi@elbert.uccs.edu>
+      0.45     3-Nov-98   Added support for MCA EtherWORKS (DE210/DE212) cards
+                           by <tymm@computer.org>
+      0.451    5-Nov-98   Fixed mca stuff cuz I'm a dummy. <tymm@computer.org>
+      0.5     14-Nov-98   Re-spin for 2.1.x kernels.
+      0.51    27-Jun-99   Correct received packet length for CRC from
+                           report by <worm@dkik.dk>
+      0.52    16-Oct-00   Fixes for 2.3 io memory accesses
+                          Fix show-stopper (ints left masked) in depca_interrupt
+			   by <peterd@pnd-pc.demon.co.uk>
+      0.53    12-Jan-01	  Release resources on failure, bss tidbits
+      			   by acme@conectiva.com.br
+      0.54    08-Nov-01	  use library crc32 functions
+      			   by Matt_Domsch@dell.com
+      0.55    01-Mar-03   Use EISA/sysfs framework <maz@wild-wind.fr.eu.org>
+
+    =========================================================================
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/time.h>
+#include <linux/types.h>
+#include <linux/unistd.h>
+#include <linux/ctype.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#ifdef CONFIG_MCA
+#include <linux/mca.h>
+#endif
+
+#ifdef CONFIG_EISA
+#include <linux/eisa.h>
+#endif
+
+#include "depca.h"
+
+static char version[] __initdata = "depca.c:v0.53 2001/1/12 davies@maniac.ultranet.com\n";
+
+#ifdef DEPCA_DEBUG
+static int depca_debug = DEPCA_DEBUG;
+#else
+static int depca_debug = 1;
+#endif
+
+#define DEPCA_NDA 0xffe0	/* No Device Address */
+
+#define TX_TIMEOUT (1*HZ)
+
+/*
+** Ethernet PROM defines
+*/
+#define PROBE_LENGTH    32
+#define ETH_PROM_SIG    0xAA5500FFUL
+
+/*
+** Set the number of Tx and Rx buffers. Ensure that the memory requested
+** here is <= to the amount of shared memory set up by the board switches.
+** The number of descriptors MUST BE A POWER OF 2.
+**
+** total_memory = NUM_RX_DESC*(8+RX_BUFF_SZ) + NUM_TX_DESC*(8+TX_BUFF_SZ)
+*/
+#define NUM_RX_DESC     8	/* Number of RX descriptors */
+#define NUM_TX_DESC     8	/* Number of TX descriptors */
+#define RX_BUFF_SZ	1536	/* Buffer size for each Rx buffer */
+#define TX_BUFF_SZ	1536	/* Buffer size for each Tx buffer */
+
+/*
+** EISA bus defines
+*/
+#define DEPCA_EISA_IO_PORTS 0x0c00	/* I/O port base address, slot 0 */
+
+/*
+** ISA Bus defines
+*/
+#define DEPCA_RAM_BASE_ADDRESSES {0xc0000,0xd0000,0xe0000,0x00000}
+#define DEPCA_TOTAL_SIZE 0x10
+
+static struct {
+	u_long iobase;
+	struct platform_device *device;
+} depca_io_ports[] = {
+	{ 0x300, NULL },
+	{ 0x200, NULL },
+	{ 0    , NULL },
+};
+
+/*
+** Name <-> Adapter mapping
+*/
+#define DEPCA_SIGNATURE {"DEPCA",\
+			 "DE100","DE101",\
+                         "DE200","DE201","DE202",\
+			 "DE210","DE212",\
+                         "DE422",\
+                         ""}
+
+static char* __initdata depca_signature[] = DEPCA_SIGNATURE;
+
+enum depca_type {
+	DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown
+};
+
+static char depca_string[] = "depca";
+
+static int depca_device_remove (struct device *device);
+
+#ifdef CONFIG_EISA
+static struct eisa_device_id depca_eisa_ids[] = {
+	{ "DEC4220", de422 },
+	{ "" }
+};
+MODULE_DEVICE_TABLE(eisa, depca_eisa_ids);
+
+static int depca_eisa_probe  (struct device *device);
+
+static struct eisa_driver depca_eisa_driver = {
+	.id_table = depca_eisa_ids,
+	.driver   = {
+		.name    = depca_string,
+		.probe   = depca_eisa_probe,
+		.remove  = __devexit_p (depca_device_remove)
+	}
+};
+#endif
+
+#ifdef CONFIG_MCA
+/*
+** Adapter ID for the MCA EtherWORKS DE210/212 adapter
+*/
+#define DE210_ID 0x628d
+#define DE212_ID 0x6def
+
+static short depca_mca_adapter_ids[] = {
+	DE210_ID,
+	DE212_ID,
+	0x0000
+};
+
+static char *depca_mca_adapter_name[] = {
+	"DEC EtherWORKS MC Adapter (DE210)",
+	"DEC EtherWORKS MC Adapter (DE212)",
+	NULL
+};
+
+static enum depca_type depca_mca_adapter_type[] = {
+	de210,
+	de212,
+	0
+};
+
+static int depca_mca_probe (struct device *);
+
+static struct mca_driver depca_mca_driver = {
+	.id_table = depca_mca_adapter_ids,
+	.driver   = {
+		.name   = depca_string,
+		.bus    = &mca_bus_type,
+		.probe  = depca_mca_probe,
+		.remove = __devexit_p(depca_device_remove),
+	},
+};
+#endif
+
+static int depca_isa_probe (struct platform_device *);
+
+static int __devexit depca_isa_remove(struct platform_device *pdev)
+{
+	return depca_device_remove(&pdev->dev);
+}
+
+static struct platform_driver depca_isa_driver = {
+	.probe  = depca_isa_probe,
+	.remove = __devexit_p(depca_isa_remove),
+	.driver	= {
+		.name   = depca_string,
+	},
+};
+
+/*
+** Miscellaneous info...
+*/
+#define DEPCA_STRLEN 16
+
+/*
+** Memory Alignment. Each descriptor is 4 longwords long. To force a
+** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and
+** DESC_ALIGN. DEPCA_ALIGN aligns the start address of the private memory area
+** and hence the RX descriptor ring's first entry.
+*/
+#define DEPCA_ALIGN4      ((u_long)4 - 1)	/* 1 longword align */
+#define DEPCA_ALIGN8      ((u_long)8 - 1)	/* 2 longword (quadword) align */
+#define DEPCA_ALIGN         DEPCA_ALIGN8	/* Keep the LANCE happy... */
+
+/*
+** The DEPCA Rx and Tx ring descriptors.
+*/
+struct depca_rx_desc {
+	volatile s32 base;
+	s16 buf_length;		/* This length is negative 2's complement! */
+	s16 msg_length;		/* This length is "normal". */
+};
+
+struct depca_tx_desc {
+	volatile s32 base;
+	s16 length;		/* This length is negative 2's complement! */
+	s16 misc;		/* Errors and TDR info */
+};
+
+#define LA_MASK 0x0000ffff	/* LANCE address mask for mapping network RAM
+				   to LANCE memory address space */
+
+/*
+** The Lance initialization block, described in databook, in common memory.
+*/
+struct depca_init {
+	u16 mode;		/* Mode register */
+	u8 phys_addr[ETH_ALEN];	/* Physical ethernet address */
+	u8 mcast_table[8];	/* Multicast Hash Table. */
+	u32 rx_ring;		/* Rx ring base pointer & ring length */
+	u32 tx_ring;		/* Tx ring base pointer & ring length */
+};
+
+#define DEPCA_PKT_STAT_SZ 16
+#define DEPCA_PKT_BIN_SZ  128	/* Should be >=100 unless you
+				   increase DEPCA_PKT_STAT_SZ */
+struct depca_private {
+	char adapter_name[DEPCA_STRLEN];	/* /proc/ioports string                  */
+	enum depca_type adapter;		/* Adapter type */
+	enum {
+                DEPCA_BUS_MCA = 1,
+                DEPCA_BUS_ISA,
+                DEPCA_BUS_EISA,
+        } depca_bus;	        /* type of bus */
+	struct depca_init init_block;	/* Shadow Initialization block            */
+/* CPU address space fields */
+	struct depca_rx_desc __iomem *rx_ring;	/* Pointer to start of RX descriptor ring */
+	struct depca_tx_desc __iomem *tx_ring;	/* Pointer to start of TX descriptor ring */
+	void __iomem *rx_buff[NUM_RX_DESC];	/* CPU virt address of sh'd memory buffs  */
+	void __iomem *tx_buff[NUM_TX_DESC];	/* CPU virt address of sh'd memory buffs  */
+	void __iomem *sh_mem;	/* CPU mapped virt address of device RAM  */
+	u_long mem_start;	/* Bus address of device RAM (before remap) */
+	u_long mem_len;		/* device memory size */
+/* Device address space fields */
+	u_long device_ram_start;	/* Start of RAM in device addr space      */
+/* Offsets used in both address spaces */
+	u_long rx_ring_offset;	/* Offset from start of RAM to rx_ring    */
+	u_long tx_ring_offset;	/* Offset from start of RAM to tx_ring    */
+	u_long buffs_offset;	/* LANCE Rx and Tx buffers start address. */
+/* Kernel-only (not device) fields */
+	int rx_new, tx_new;	/* The next free ring entry               */
+	int rx_old, tx_old;	/* The ring entries to be free()ed.       */
+	spinlock_t lock;
+	struct {		/* Private stats counters                 */
+		u32 bins[DEPCA_PKT_STAT_SZ];
+		u32 unicast;
+		u32 multicast;
+		u32 broadcast;
+		u32 excessive_collisions;
+		u32 tx_underruns;
+		u32 excessive_underruns;
+	} pktStats;
+	int txRingMask;		/* TX ring mask                           */
+	int rxRingMask;		/* RX ring mask                           */
+	s32 rx_rlen;		/* log2(rxRingMask+1) for the descriptors */
+	s32 tx_rlen;		/* log2(txRingMask+1) for the descriptors */
+};
+
+/*
+** The transmit ring full condition is described by the tx_old and tx_new
+** pointers by:
+**    tx_old            = tx_new    Empty ring
+**    tx_old            = tx_new+1  Full ring
+**    tx_old+txRingMask = tx_new    Full ring  (wrapped condition)
+*/
+#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
+			 lp->tx_old+lp->txRingMask-lp->tx_new:\
+                         lp->tx_old               -lp->tx_new-1)
+
+/*
+** Public Functions
+*/
+static int depca_open(struct net_device *dev);
+static netdev_tx_t depca_start_xmit(struct sk_buff *skb,
+				    struct net_device *dev);
+static irqreturn_t depca_interrupt(int irq, void *dev_id);
+static int depca_close(struct net_device *dev);
+static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static void depca_tx_timeout(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+
+/*
+** Private functions
+*/
+static void depca_init_ring(struct net_device *dev);
+static int depca_rx(struct net_device *dev);
+static int depca_tx(struct net_device *dev);
+
+static void LoadCSRs(struct net_device *dev);
+static int InitRestartDepca(struct net_device *dev);
+static int DepcaSignature(char *name, u_long paddr);
+static int DevicePresent(u_long ioaddr);
+static int get_hw_addr(struct net_device *dev);
+static void SetMulticastFilter(struct net_device *dev);
+static int load_packet(struct net_device *dev, struct sk_buff *skb);
+static void depca_dbg_open(struct net_device *dev);
+
+static u_char de1xx_irq[] __initdata = { 2, 3, 4, 5, 7, 9, 0 };
+static u_char de2xx_irq[] __initdata = { 5, 9, 10, 11, 15, 0 };
+static u_char de422_irq[] __initdata = { 5, 9, 10, 11, 0 };
+static u_char *depca_irq;
+
+static int irq;
+static int io;
+static char *adapter_name;
+static int mem;			/* For loadable module assignment
+				   use insmod mem=0x????? .... */
+module_param (irq, int, 0);
+module_param (io, int, 0);
+module_param (adapter_name, charp, 0);
+module_param (mem, int, 0);
+MODULE_PARM_DESC(irq, "DEPCA IRQ number");
+MODULE_PARM_DESC(io, "DEPCA I/O base address");
+MODULE_PARM_DESC(adapter_name, "DEPCA adapter name");
+MODULE_PARM_DESC(mem, "DEPCA shared memory address");
+MODULE_LICENSE("GPL");
+
+/*
+** Miscellaneous defines...
+*/
+#define STOP_DEPCA \
+    outw(CSR0, DEPCA_ADDR);\
+    outw(STOP, DEPCA_DATA)
+
+static const struct net_device_ops depca_netdev_ops = {
+	.ndo_open 		= depca_open,
+	.ndo_start_xmit 	= depca_start_xmit,
+	.ndo_stop 		= depca_close,
+	.ndo_set_rx_mode	= set_multicast_list,
+	.ndo_do_ioctl 		= depca_ioctl,
+	.ndo_tx_timeout 	= depca_tx_timeout,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+static int __init depca_hw_init (struct net_device *dev, struct device *device)
+{
+	struct depca_private *lp;
+	int i, j, offset, netRAM, mem_len, status = 0;
+	s16 nicsr;
+	u_long ioaddr;
+	u_long mem_start;
+
+	/*
+	 * We are now supposed to enter this function with the
+	 * following fields filled with proper values :
+	 *
+	 * dev->base_addr
+	 * lp->mem_start
+	 * lp->depca_bus
+	 * lp->adapter
+	 *
+	 * dev->irq can be set if known from device configuration (on
+	 * MCA or EISA) or module option. Otherwise, it will be auto
+	 * detected.
+	 */
+
+	ioaddr = dev->base_addr;
+
+	STOP_DEPCA;
+
+	nicsr = inb(DEPCA_NICSR);
+	nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM);
+	outb(nicsr, DEPCA_NICSR);
+
+	if (inw(DEPCA_DATA) != STOP) {
+		return -ENXIO;
+	}
+
+	lp = netdev_priv(dev);
+	mem_start = lp->mem_start;
+
+	if (!mem_start || lp->adapter < DEPCA || lp->adapter >=unknown)
+		return -ENXIO;
+
+	printk("%s: %s at 0x%04lx",
+	       dev_name(device), depca_signature[lp->adapter], ioaddr);
+
+	switch (lp->depca_bus) {
+#ifdef CONFIG_MCA
+	case DEPCA_BUS_MCA:
+		printk(" (MCA slot %d)", to_mca_device(device)->slot + 1);
+		break;
+#endif
+
+#ifdef CONFIG_EISA
+	case DEPCA_BUS_EISA:
+		printk(" (EISA slot %d)", to_eisa_device(device)->slot);
+		break;
+#endif
+
+	case DEPCA_BUS_ISA:
+		break;
+
+	default:
+		printk("Unknown DEPCA bus %d\n", lp->depca_bus);
+		return -ENXIO;
+	}
+
+	printk(", h/w address ");
+	status = get_hw_addr(dev);
+	printk("%pM", dev->dev_addr);
+	if (status != 0) {
+		printk("      which has an Ethernet PROM CRC error.\n");
+		return -ENXIO;
+	}
+
+	/* Set up the maximum amount of network RAM(kB) */
+	netRAM = ((lp->adapter != DEPCA) ? 64 : 48);
+	if ((nicsr & _128KB) && (lp->adapter == de422))
+		netRAM = 128;
+
+	/* Shared Memory Base Address */
+	if (nicsr & BUF) {
+		nicsr &= ~BS;	/* DEPCA RAM in top 32k */
+		netRAM -= 32;
+
+		/* Only EISA/ISA needs start address to be re-computed */
+		if (lp->depca_bus != DEPCA_BUS_MCA)
+			mem_start += 0x8000;
+	}
+
+	if ((mem_len = (NUM_RX_DESC * (sizeof(struct depca_rx_desc) + RX_BUFF_SZ) + NUM_TX_DESC * (sizeof(struct depca_tx_desc) + TX_BUFF_SZ) + sizeof(struct depca_init)))
+	    > (netRAM << 10)) {
+		printk(",\n       requests %dkB RAM: only %dkB is available!\n", (mem_len >> 10), netRAM);
+		return -ENXIO;
+	}
+
+	printk(",\n      has %dkB RAM at 0x%.5lx", netRAM, mem_start);
+
+	/* Enable the shadow RAM. */
+	if (lp->adapter != DEPCA) {
+		nicsr |= SHE;
+		outb(nicsr, DEPCA_NICSR);
+	}
+
+	spin_lock_init(&lp->lock);
+	sprintf(lp->adapter_name, "%s (%s)",
+		depca_signature[lp->adapter], dev_name(device));
+	status = -EBUSY;
+
+	/* Initialisation Block */
+	if (!request_mem_region (mem_start, mem_len, lp->adapter_name)) {
+		printk(KERN_ERR "depca: cannot request ISA memory, aborting\n");
+		goto out_priv;
+	}
+
+	status = -EIO;
+	lp->sh_mem = ioremap(mem_start, mem_len);
+	if (lp->sh_mem == NULL) {
+		printk(KERN_ERR "depca: cannot remap ISA memory, aborting\n");
+		goto out1;
+	}
+
+	lp->mem_start = mem_start;
+	lp->mem_len   = mem_len;
+	lp->device_ram_start = mem_start & LA_MASK;
+
+	offset = 0;
+	offset += sizeof(struct depca_init);
+
+	/* Tx & Rx descriptors (aligned to a quadword boundary) */
+	offset = (offset + DEPCA_ALIGN) & ~DEPCA_ALIGN;
+	lp->rx_ring = lp->sh_mem + offset;
+	lp->rx_ring_offset = offset;
+
+	offset += (sizeof(struct depca_rx_desc) * NUM_RX_DESC);
+	lp->tx_ring = lp->sh_mem + offset;
+	lp->tx_ring_offset = offset;
+
+	offset += (sizeof(struct depca_tx_desc) * NUM_TX_DESC);
+
+	lp->buffs_offset = offset;
+
+	/* Finish initialising the ring information. */
+	lp->rxRingMask = NUM_RX_DESC - 1;
+	lp->txRingMask = NUM_TX_DESC - 1;
+
+	/* Calculate Tx/Rx RLEN size for the descriptors. */
+	for (i = 0, j = lp->rxRingMask; j > 0; i++) {
+		j >>= 1;
+	}
+	lp->rx_rlen = (s32) (i << 29);
+	for (i = 0, j = lp->txRingMask; j > 0; i++) {
+		j >>= 1;
+	}
+	lp->tx_rlen = (s32) (i << 29);
+
+	/* Load the initialisation block */
+	depca_init_ring(dev);
+
+	/* Initialise the control and status registers */
+	LoadCSRs(dev);
+
+	/* Enable DEPCA board interrupts for autoprobing */
+	nicsr = ((nicsr & ~IM) | IEN);
+	outb(nicsr, DEPCA_NICSR);
+
+	/* To auto-IRQ we enable the initialization-done and DMA err,
+	   interrupts. For now we will always get a DMA error. */
+	if (dev->irq < 2) {
+		unsigned char irqnum;
+		unsigned long irq_mask, delay;
+
+		irq_mask = probe_irq_on();
+
+		/* Assign the correct irq list */
+		switch (lp->adapter) {
+		case DEPCA:
+		case de100:
+		case de101:
+			depca_irq = de1xx_irq;
+			break;
+		case de200:
+		case de201:
+		case de202:
+		case de210:
+		case de212:
+			depca_irq = de2xx_irq;
+			break;
+		case de422:
+			depca_irq = de422_irq;
+			break;
+
+		default:
+			break;	/* Not reached */
+		}
+
+		/* Trigger an initialization just for the interrupt. */
+		outw(INEA | INIT, DEPCA_DATA);
+
+		delay = jiffies + HZ/50;
+		while (time_before(jiffies, delay))
+			yield();
+
+		irqnum = probe_irq_off(irq_mask);
+
+		status = -ENXIO;
+		if (!irqnum) {
+			printk(" and failed to detect IRQ line.\n");
+			goto out2;
+		} else {
+			for (dev->irq = 0, i = 0; (depca_irq[i]) && (!dev->irq); i++)
+				if (irqnum == depca_irq[i]) {
+					dev->irq = irqnum;
+					printk(" and uses IRQ%d.\n", dev->irq);
+				}
+
+			if (!dev->irq) {
+				printk(" but incorrect IRQ line detected.\n");
+				goto out2;
+			}
+		}
+	} else {
+		printk(" and assigned IRQ%d.\n", dev->irq);
+	}
+
+	if (depca_debug > 1) {
+		printk(version);
+	}
+
+	/* The DEPCA-specific entries in the device structure. */
+	dev->netdev_ops = &depca_netdev_ops;
+	dev->watchdog_timeo = TX_TIMEOUT;
+
+	dev->mem_start = 0;
+
+	dev_set_drvdata(device, dev);
+	SET_NETDEV_DEV (dev, device);
+
+	status = register_netdev(dev);
+	if (status == 0)
+		return 0;
+out2:
+	iounmap(lp->sh_mem);
+out1:
+	release_mem_region (mem_start, mem_len);
+out_priv:
+	return status;
+}
+
+
+static int depca_open(struct net_device *dev)
+{
+	struct depca_private *lp = netdev_priv(dev);
+	u_long ioaddr = dev->base_addr;
+	s16 nicsr;
+	int status = 0;
+
+	STOP_DEPCA;
+	nicsr = inb(DEPCA_NICSR);
+
+	/* Make sure the shadow RAM is enabled */
+	if (lp->adapter != DEPCA) {
+		nicsr |= SHE;
+		outb(nicsr, DEPCA_NICSR);
+	}
+
+	/* Re-initialize the DEPCA... */
+	depca_init_ring(dev);
+	LoadCSRs(dev);
+
+	depca_dbg_open(dev);
+
+	if (request_irq(dev->irq, depca_interrupt, 0, lp->adapter_name, dev)) {
+		printk("depca_open(): Requested IRQ%d is busy\n", dev->irq);
+		status = -EAGAIN;
+	} else {
+
+		/* Enable DEPCA board interrupts and turn off LED */
+		nicsr = ((nicsr & ~IM & ~LED) | IEN);
+		outb(nicsr, DEPCA_NICSR);
+		outw(CSR0, DEPCA_ADDR);
+
+		netif_start_queue(dev);
+
+		status = InitRestartDepca(dev);
+
+		if (depca_debug > 1) {
+			printk("CSR0: 0x%4.4x\n", inw(DEPCA_DATA));
+			printk("nicsr: 0x%02x\n", inb(DEPCA_NICSR));
+		}
+	}
+	return status;
+}
+
+/* Initialize the lance Rx and Tx descriptor rings. */
+static void depca_init_ring(struct net_device *dev)
+{
+	struct depca_private *lp = netdev_priv(dev);
+	u_int i;
+	u_long offset;
+
+	/* Lock out other processes whilst setting up the hardware */
+	netif_stop_queue(dev);
+
+	lp->rx_new = lp->tx_new = 0;
+	lp->rx_old = lp->tx_old = 0;
+
+	/* Initialize the base address and length of each buffer in the ring */
+	for (i = 0; i <= lp->rxRingMask; i++) {
+		offset = lp->buffs_offset + i * RX_BUFF_SZ;
+		writel((lp->device_ram_start + offset) | R_OWN, &lp->rx_ring[i].base);
+		writew(-RX_BUFF_SZ, &lp->rx_ring[i].buf_length);
+		lp->rx_buff[i] = lp->sh_mem + offset;
+	}
+
+	for (i = 0; i <= lp->txRingMask; i++) {
+		offset = lp->buffs_offset + (i + lp->rxRingMask + 1) * TX_BUFF_SZ;
+		writel((lp->device_ram_start + offset) & 0x00ffffff, &lp->tx_ring[i].base);
+		lp->tx_buff[i] = lp->sh_mem + offset;
+	}
+
+	/* Set up the initialization block */
+	lp->init_block.rx_ring = (lp->device_ram_start + lp->rx_ring_offset) | lp->rx_rlen;
+	lp->init_block.tx_ring = (lp->device_ram_start + lp->tx_ring_offset) | lp->tx_rlen;
+
+	SetMulticastFilter(dev);
+
+	for (i = 0; i < ETH_ALEN; i++) {
+		lp->init_block.phys_addr[i] = dev->dev_addr[i];
+	}
+
+	lp->init_block.mode = 0x0000;	/* Enable the Tx and Rx */
+}
+
+
+static void depca_tx_timeout(struct net_device *dev)
+{
+	u_long ioaddr = dev->base_addr;
+
+	printk("%s: transmit timed out, status %04x, resetting.\n", dev->name, inw(DEPCA_DATA));
+
+	STOP_DEPCA;
+	depca_init_ring(dev);
+	LoadCSRs(dev);
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	netif_wake_queue(dev);
+	InitRestartDepca(dev);
+}
+
+
+/*
+** Writes a socket buffer to TX descriptor ring and starts transmission
+*/
+static netdev_tx_t depca_start_xmit(struct sk_buff *skb,
+				    struct net_device *dev)
+{
+	struct depca_private *lp = netdev_priv(dev);
+	u_long ioaddr = dev->base_addr;
+	int status = 0;
+
+	/* Transmitter timeout, serious problems. */
+	if (skb->len < 1)
+		goto out;
+
+	if (skb_padto(skb, ETH_ZLEN))
+		goto out;
+
+	netif_stop_queue(dev);
+
+	if (TX_BUFFS_AVAIL) {	/* Fill in a Tx ring entry */
+		status = load_packet(dev, skb);
+
+		if (!status) {
+			/* Trigger an immediate send demand. */
+			outw(CSR0, DEPCA_ADDR);
+			outw(INEA | TDMD, DEPCA_DATA);
+
+			dev_kfree_skb(skb);
+		}
+		if (TX_BUFFS_AVAIL)
+			netif_start_queue(dev);
+	} else
+		status = NETDEV_TX_LOCKED;
+
+      out:
+	return status;
+}
+
+/*
+** The DEPCA interrupt handler.
+*/
+static irqreturn_t depca_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct depca_private *lp;
+	s16 csr0, nicsr;
+	u_long ioaddr;
+
+	if (dev == NULL) {
+		printk("depca_interrupt(): irq %d for unknown device.\n", irq);
+		return IRQ_NONE;
+	}
+
+	lp = netdev_priv(dev);
+	ioaddr = dev->base_addr;
+
+	spin_lock(&lp->lock);
+
+	/* mask the DEPCA board interrupts and turn on the LED */
+	nicsr = inb(DEPCA_NICSR);
+	nicsr |= (IM | LED);
+	outb(nicsr, DEPCA_NICSR);
+
+	outw(CSR0, DEPCA_ADDR);
+	csr0 = inw(DEPCA_DATA);
+
+	/* Acknowledge all of the current interrupt sources ASAP. */
+	outw(csr0 & INTE, DEPCA_DATA);
+
+	if (csr0 & RINT)	/* Rx interrupt (packet arrived) */
+		depca_rx(dev);
+
+	if (csr0 & TINT)	/* Tx interrupt (packet sent) */
+		depca_tx(dev);
+
+	/* Any resources available? */
+	if ((TX_BUFFS_AVAIL >= 0) && netif_queue_stopped(dev)) {
+		netif_wake_queue(dev);
+	}
+
+	/* Unmask the DEPCA board interrupts and turn off the LED */
+	nicsr = (nicsr & ~IM & ~LED);
+	outb(nicsr, DEPCA_NICSR);
+
+	spin_unlock(&lp->lock);
+	return IRQ_HANDLED;
+}
+
+/* Called with lp->lock held */
+static int depca_rx(struct net_device *dev)
+{
+	struct depca_private *lp = netdev_priv(dev);
+	int i, entry;
+	s32 status;
+
+	for (entry = lp->rx_new; !(readl(&lp->rx_ring[entry].base) & R_OWN); entry = lp->rx_new) {
+		status = readl(&lp->rx_ring[entry].base) >> 16;
+		if (status & R_STP) {	/* Remember start of frame */
+			lp->rx_old = entry;
+		}
+		if (status & R_ENP) {	/* Valid frame status */
+			if (status & R_ERR) {	/* There was an error. */
+				dev->stats.rx_errors++;	/* Update the error stats. */
+				if (status & R_FRAM)
+					dev->stats.rx_frame_errors++;
+				if (status & R_OFLO)
+					dev->stats.rx_over_errors++;
+				if (status & R_CRC)
+					dev->stats.rx_crc_errors++;
+				if (status & R_BUFF)
+					dev->stats.rx_fifo_errors++;
+			} else {
+				short len, pkt_len = readw(&lp->rx_ring[entry].msg_length) - 4;
+				struct sk_buff *skb;
+
+				skb = dev_alloc_skb(pkt_len + 2);
+				if (skb != NULL) {
+					unsigned char *buf;
+					skb_reserve(skb, 2);	/* 16 byte align the IP header */
+					buf = skb_put(skb, pkt_len);
+					if (entry < lp->rx_old) {	/* Wrapped buffer */
+						len = (lp->rxRingMask - lp->rx_old + 1) * RX_BUFF_SZ;
+						memcpy_fromio(buf, lp->rx_buff[lp->rx_old], len);
+						memcpy_fromio(buf + len, lp->rx_buff[0], pkt_len - len);
+					} else {	/* Linear buffer */
+						memcpy_fromio(buf, lp->rx_buff[lp->rx_old], pkt_len);
+					}
+
+					/*
+					   ** Notify the upper protocol layers that there is another
+					   ** packet to handle
+					 */
+					skb->protocol = eth_type_trans(skb, dev);
+					netif_rx(skb);
+
+					/*
+					   ** Update stats
+					 */
+					dev->stats.rx_packets++;
+					dev->stats.rx_bytes += pkt_len;
+					for (i = 1; i < DEPCA_PKT_STAT_SZ - 1; i++) {
+						if (pkt_len < (i * DEPCA_PKT_BIN_SZ)) {
+							lp->pktStats.bins[i]++;
+							i = DEPCA_PKT_STAT_SZ;
+						}
+					}
+					if (is_multicast_ether_addr(buf)) {
+						if (is_broadcast_ether_addr(buf)) {
+							lp->pktStats.broadcast++;
+						} else {
+							lp->pktStats.multicast++;
+						}
+					} else if (compare_ether_addr(buf, dev->dev_addr) == 0) {
+						lp->pktStats.unicast++;
+					}
+
+					lp->pktStats.bins[0]++;	/* Duplicates stats.rx_packets */
+					if (lp->pktStats.bins[0] == 0) {	/* Reset counters */
+						memset((char *) &lp->pktStats, 0, sizeof(lp->pktStats));
+					}
+				} else {
+					printk("%s: Memory squeeze, deferring packet.\n", dev->name);
+					dev->stats.rx_dropped++;	/* Really, deferred. */
+					break;
+				}
+			}
+			/* Change buffer ownership for this last frame, back to the adapter */
+			for (; lp->rx_old != entry; lp->rx_old = (lp->rx_old + 1) & lp->rxRingMask) {
+				writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN, &lp->rx_ring[lp->rx_old].base);
+			}
+			writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base);
+		}
+
+		/*
+		   ** Update entry information
+		 */
+		lp->rx_new = (lp->rx_new + 1) & lp->rxRingMask;
+	}
+
+	return 0;
+}
+
+/*
+** Buffer sent - check for buffer errors.
+** Called with lp->lock held
+*/
+static int depca_tx(struct net_device *dev)
+{
+	struct depca_private *lp = netdev_priv(dev);
+	int entry;
+	s32 status;
+	u_long ioaddr = dev->base_addr;
+
+	for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) {
+		status = readl(&lp->tx_ring[entry].base) >> 16;
+
+		if (status < 0) {	/* Packet not yet sent! */
+			break;
+		} else if (status & T_ERR) {	/* An error occurred. */
+			status = readl(&lp->tx_ring[entry].misc);
+			dev->stats.tx_errors++;
+			if (status & TMD3_RTRY)
+				dev->stats.tx_aborted_errors++;
+			if (status & TMD3_LCAR)
+				dev->stats.tx_carrier_errors++;
+			if (status & TMD3_LCOL)
+				dev->stats.tx_window_errors++;
+			if (status & TMD3_UFLO)
+				dev->stats.tx_fifo_errors++;
+			if (status & (TMD3_BUFF | TMD3_UFLO)) {
+				/* Trigger an immediate send demand. */
+				outw(CSR0, DEPCA_ADDR);
+				outw(INEA | TDMD, DEPCA_DATA);
+			}
+		} else if (status & (T_MORE | T_ONE)) {
+			dev->stats.collisions++;
+		} else {
+			dev->stats.tx_packets++;
+		}
+
+		/* Update all the pointers */
+		lp->tx_old = (lp->tx_old + 1) & lp->txRingMask;
+	}
+
+	return 0;
+}
+
+static int depca_close(struct net_device *dev)
+{
+	struct depca_private *lp = netdev_priv(dev);
+	s16 nicsr;
+	u_long ioaddr = dev->base_addr;
+
+	netif_stop_queue(dev);
+
+	outw(CSR0, DEPCA_ADDR);
+
+	if (depca_debug > 1) {
+		printk("%s: Shutting down ethercard, status was %2.2x.\n", dev->name, inw(DEPCA_DATA));
+	}
+
+	/*
+	   ** We stop the DEPCA here -- it occasionally polls
+	   ** memory if we don't.
+	 */
+	outw(STOP, DEPCA_DATA);
+
+	/*
+	   ** Give back the ROM in case the user wants to go to DOS
+	 */
+	if (lp->adapter != DEPCA) {
+		nicsr = inb(DEPCA_NICSR);
+		nicsr &= ~SHE;
+		outb(nicsr, DEPCA_NICSR);
+	}
+
+	/*
+	   ** Free the associated irq
+	 */
+	free_irq(dev->irq, dev);
+	return 0;
+}
+
+static void LoadCSRs(struct net_device *dev)
+{
+	struct depca_private *lp = netdev_priv(dev);
+	u_long ioaddr = dev->base_addr;
+
+	outw(CSR1, DEPCA_ADDR);	/* initialisation block address LSW */
+	outw((u16) lp->device_ram_start, DEPCA_DATA);
+	outw(CSR2, DEPCA_ADDR);	/* initialisation block address MSW */
+	outw((u16) (lp->device_ram_start >> 16), DEPCA_DATA);
+	outw(CSR3, DEPCA_ADDR);	/* ALE control */
+	outw(ACON, DEPCA_DATA);
+
+	outw(CSR0, DEPCA_ADDR);	/* Point back to CSR0 */
+}
+
+static int InitRestartDepca(struct net_device *dev)
+{
+	struct depca_private *lp = netdev_priv(dev);
+	u_long ioaddr = dev->base_addr;
+	int i, status = 0;
+
+	/* Copy the shadow init_block to shared memory */
+	memcpy_toio(lp->sh_mem, &lp->init_block, sizeof(struct depca_init));
+
+	outw(CSR0, DEPCA_ADDR);	/* point back to CSR0 */
+	outw(INIT, DEPCA_DATA);	/* initialize DEPCA */
+
+	/* wait for lance to complete initialisation */
+	for (i = 0; (i < 100) && !(inw(DEPCA_DATA) & IDON); i++);
+
+	if (i != 100) {
+		/* clear IDON by writing a "1", enable interrupts and start lance */
+		outw(IDON | INEA | STRT, DEPCA_DATA);
+		if (depca_debug > 2) {
+			printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, lp->mem_start, inw(DEPCA_DATA));
+		}
+	} else {
+		printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, lp->mem_start, inw(DEPCA_DATA));
+		status = -1;
+	}
+
+	return status;
+}
+
+/*
+** Set or clear the multicast filter for this adaptor.
+*/
+static void set_multicast_list(struct net_device *dev)
+{
+	struct depca_private *lp = netdev_priv(dev);
+	u_long ioaddr = dev->base_addr;
+
+	netif_stop_queue(dev);
+	while (lp->tx_old != lp->tx_new);	/* Wait for the ring to empty */
+
+	STOP_DEPCA;	/* Temporarily stop the depca.  */
+	depca_init_ring(dev);	/* Initialize the descriptor rings */
+
+	if (dev->flags & IFF_PROMISC) {	/* Set promiscuous mode */
+		lp->init_block.mode |= PROM;
+	} else {
+		SetMulticastFilter(dev);
+		lp->init_block.mode &= ~PROM;	/* Unset promiscuous mode */
+	}
+
+	LoadCSRs(dev);	/* Reload CSR3 */
+	InitRestartDepca(dev);	/* Resume normal operation. */
+	netif_start_queue(dev);	/* Unlock the TX ring */
+}
+
+/*
+** Calculate the hash code and update the logical address filter
+** from a list of ethernet multicast addresses.
+** Big endian crc one liner is mine, all mine, ha ha ha ha!
+** LANCE calculates its hash codes big endian.
+*/
+static void SetMulticastFilter(struct net_device *dev)
+{
+	struct depca_private *lp = netdev_priv(dev);
+	struct netdev_hw_addr *ha;
+	int i, j, bit, byte;
+	u16 hashcode;
+	u32 crc;
+
+	if (dev->flags & IFF_ALLMULTI) {	/* Set all multicast bits */
+		for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) {
+			lp->init_block.mcast_table[i] = (char) 0xff;
+		}
+	} else {
+		for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) {	/* Clear the multicast table */
+			lp->init_block.mcast_table[i] = 0;
+		}
+		/* Add multicast addresses */
+		netdev_for_each_mc_addr(ha, dev) {
+			crc = ether_crc(ETH_ALEN, ha->addr);
+			hashcode = (crc & 1);	/* hashcode is 6 LSb of CRC ... */
+			for (j = 0; j < 5; j++) {	/* ... in reverse order. */
+				hashcode = (hashcode << 1) | ((crc >>= 1) & 1);
+			}
+
+			byte = hashcode >> 3;	/* bit[3-5] -> byte in filter */
+			bit = 1 << (hashcode & 0x07);	/* bit[0-2] -> bit in byte */
+			lp->init_block.mcast_table[byte] |= bit;
+		}
+	}
+}
+
+static int __init depca_common_init (u_long ioaddr, struct net_device **devp)
+{
+	int status = 0;
+
+	if (!request_region (ioaddr, DEPCA_TOTAL_SIZE, depca_string)) {
+		status = -EBUSY;
+		goto out;
+	}
+
+	if (DevicePresent(ioaddr)) {
+		status = -ENODEV;
+		goto out_release;
+	}
+
+	if (!(*devp = alloc_etherdev (sizeof (struct depca_private)))) {
+		status = -ENOMEM;
+		goto out_release;
+	}
+
+	return 0;
+
+ out_release:
+	release_region (ioaddr, DEPCA_TOTAL_SIZE);
+ out:
+	return status;
+}
+
+#ifdef CONFIG_MCA
+/*
+** Microchannel bus I/O device probe
+*/
+static int __init depca_mca_probe(struct device *device)
+{
+	unsigned char pos[2];
+	unsigned char where;
+	unsigned long iobase, mem_start;
+	int irq, err;
+	struct mca_device *mdev = to_mca_device (device);
+	struct net_device *dev;
+	struct depca_private *lp;
+
+	/*
+	** Search for the adapter.  If an address has been given, search
+	** specifically for the card at that address.  Otherwise find the
+	** first card in the system.
+	*/
+
+	pos[0] = mca_device_read_stored_pos(mdev, 2);
+	pos[1] = mca_device_read_stored_pos(mdev, 3);
+
+	/*
+	** IO of card is handled by bits 1 and 2 of pos0.
+	**
+	**    bit2 bit1    IO
+	**       0    0    0x2c00
+	**       0    1    0x2c10
+	**       1    0    0x2c20
+	**       1    1    0x2c30
+	*/
+	where = (pos[0] & 6) >> 1;
+	iobase = 0x2c00 + (0x10 * where);
+
+	/*
+	** Found the adapter we were looking for. Now start setting it up.
+	**
+	** First work on decoding the IRQ.  It's stored in the lower 4 bits
+	** of pos1.  Bits are as follows (from the ADF file):
+	**
+	**      Bits
+	**   3   2   1   0    IRQ
+	**   --------------------
+	**   0   0   1   0     5
+	**   0   0   0   1     9
+	**   0   1   0   0    10
+	**   1   0   0   0    11
+	*/
+	where = pos[1] & 0x0f;
+	switch (where) {
+	case 1:
+		irq = 9;
+		break;
+	case 2:
+		irq = 5;
+		break;
+	case 4:
+		irq = 10;
+		break;
+	case 8:
+		irq = 11;
+		break;
+	default:
+		printk("%s: mca_probe IRQ error.  You should never get here (%d).\n", mdev->name, where);
+		return -EINVAL;
+	}
+
+	/*
+	** Shared memory address of adapter is stored in bits 3-5 of pos0.
+	** They are mapped as follows:
+	**
+	**    Bit
+	**   5  4  3       Memory Addresses
+	**   0  0  0       C0000-CFFFF (64K)
+	**   1  0  0       C8000-CFFFF (32K)
+	**   0  0  1       D0000-DFFFF (64K)
+	**   1  0  1       D8000-DFFFF (32K)
+	**   0  1  0       E0000-EFFFF (64K)
+	**   1  1  0       E8000-EFFFF (32K)
+	*/
+	where = (pos[0] & 0x18) >> 3;
+	mem_start = 0xc0000 + (where * 0x10000);
+	if (pos[0] & 0x20) {
+		mem_start += 0x8000;
+	}
+
+	/* claim the slot */
+	strncpy(mdev->name, depca_mca_adapter_name[mdev->index],
+		sizeof(mdev->name));
+	mca_device_set_claim(mdev, 1);
+
+        /*
+	** Get everything allocated and initialized...  (almost just
+	** like the ISA and EISA probes)
+	*/
+	irq = mca_device_transform_irq(mdev, irq);
+	iobase = mca_device_transform_ioport(mdev, iobase);
+
+	if ((err = depca_common_init (iobase, &dev)))
+		goto out_unclaim;
+
+	dev->irq = irq;
+	dev->base_addr = iobase;
+	lp = netdev_priv(dev);
+	lp->depca_bus = DEPCA_BUS_MCA;
+	lp->adapter = depca_mca_adapter_type[mdev->index];
+	lp->mem_start = mem_start;
+
+	if ((err = depca_hw_init(dev, device)))
+		goto out_free;
+
+	return 0;
+
+ out_free:
+	free_netdev (dev);
+	release_region (iobase, DEPCA_TOTAL_SIZE);
+ out_unclaim:
+	mca_device_set_claim(mdev, 0);
+
+	return err;
+}
+#endif
+
+/*
+** ISA bus I/O device probe
+*/
+
+static void __init depca_platform_probe (void)
+{
+	int i;
+	struct platform_device *pldev;
+
+	for (i = 0; depca_io_ports[i].iobase; i++) {
+		depca_io_ports[i].device = NULL;
+
+		/* if an address has been specified on the command
+		 * line, use it (if valid) */
+		if (io && io != depca_io_ports[i].iobase)
+			continue;
+
+		pldev = platform_device_alloc(depca_string, i);
+		if (!pldev)
+			continue;
+
+		pldev->dev.platform_data = (void *) depca_io_ports[i].iobase;
+		depca_io_ports[i].device = pldev;
+
+		if (platform_device_add(pldev)) {
+			depca_io_ports[i].device = NULL;
+			pldev->dev.platform_data = NULL;
+			platform_device_put(pldev);
+			continue;
+		}
+
+		if (!pldev->dev.driver) {
+		/* The driver was not bound to this device, there was
+		 * no hardware at this address. Unregister it, as the
+		 * release function will take care of freeing the
+		 * allocated structure */
+
+			depca_io_ports[i].device = NULL;
+			pldev->dev.platform_data = NULL;
+			platform_device_unregister (pldev);
+		}
+	}
+}
+
+static enum depca_type __init depca_shmem_probe (ulong *mem_start)
+{
+	u_long mem_base[] = DEPCA_RAM_BASE_ADDRESSES;
+	enum depca_type adapter = unknown;
+	int i;
+
+	for (i = 0; mem_base[i]; i++) {
+		*mem_start = mem ? mem : mem_base[i];
+		adapter = DepcaSignature (adapter_name, *mem_start);
+		if (adapter != unknown)
+			break;
+	}
+
+	return adapter;
+}
+
+static int __devinit depca_isa_probe (struct platform_device *device)
+{
+	struct net_device *dev;
+	struct depca_private *lp;
+	u_long ioaddr, mem_start = 0;
+	enum depca_type adapter = unknown;
+	int status = 0;
+
+	ioaddr = (u_long) device->dev.platform_data;
+
+	if ((status = depca_common_init (ioaddr, &dev)))
+		goto out;
+
+	adapter = depca_shmem_probe (&mem_start);
+
+	if (adapter == unknown) {
+		status = -ENODEV;
+		goto out_free;
+	}
+
+	dev->base_addr = ioaddr;
+	dev->irq = irq;		/* Use whatever value the user gave
+				 * us, and 0 if he didn't. */
+	lp = netdev_priv(dev);
+	lp->depca_bus = DEPCA_BUS_ISA;
+	lp->adapter = adapter;
+	lp->mem_start = mem_start;
+
+	if ((status = depca_hw_init(dev, &device->dev)))
+		goto out_free;
+
+	return 0;
+
+ out_free:
+	free_netdev (dev);
+	release_region (ioaddr, DEPCA_TOTAL_SIZE);
+ out:
+	return status;
+}
+
+/*
+** EISA callbacks from sysfs.
+*/
+
+#ifdef CONFIG_EISA
+static int __init depca_eisa_probe (struct device *device)
+{
+	enum depca_type adapter = unknown;
+	struct eisa_device *edev;
+	struct net_device *dev;
+	struct depca_private *lp;
+	u_long ioaddr, mem_start;
+	int status = 0;
+
+	edev = to_eisa_device (device);
+	ioaddr = edev->base_addr + DEPCA_EISA_IO_PORTS;
+
+	if ((status = depca_common_init (ioaddr, &dev)))
+		goto out;
+
+	/* It would have been nice to get card configuration from the
+	 * card. Unfortunately, this register is write-only (shares
+	 * it's address with the ethernet prom)... As we don't parse
+	 * the EISA configuration structures (yet... :-), just rely on
+	 * the ISA probing to sort it out... */
+
+	adapter = depca_shmem_probe (&mem_start);
+	if (adapter == unknown) {
+		status = -ENODEV;
+		goto out_free;
+	}
+
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+	lp = netdev_priv(dev);
+	lp->depca_bus = DEPCA_BUS_EISA;
+	lp->adapter = edev->id.driver_data;
+	lp->mem_start = mem_start;
+
+	if ((status = depca_hw_init(dev, device)))
+		goto out_free;
+
+	return 0;
+
+ out_free:
+	free_netdev (dev);
+	release_region (ioaddr, DEPCA_TOTAL_SIZE);
+ out:
+	return status;
+}
+#endif
+
+static int __devexit depca_device_remove (struct device *device)
+{
+	struct net_device *dev;
+	struct depca_private *lp;
+	int bus;
+
+	dev  = dev_get_drvdata(device);
+	lp   = netdev_priv(dev);
+
+	unregister_netdev (dev);
+	iounmap (lp->sh_mem);
+	release_mem_region (lp->mem_start, lp->mem_len);
+	release_region (dev->base_addr, DEPCA_TOTAL_SIZE);
+	bus = lp->depca_bus;
+	free_netdev (dev);
+
+	return 0;
+}
+
+/*
+** Look for a particular board name in the on-board Remote Diagnostics
+** and Boot (readb) ROM. This will also give us a clue to the network RAM
+** base address.
+*/
+static int __init DepcaSignature(char *name, u_long base_addr)
+{
+	u_int i, j, k;
+	void __iomem *ptr;
+	char tmpstr[16];
+	u_long prom_addr = base_addr + 0xc000;
+	u_long mem_addr = base_addr + 0x8000; /* 32KB */
+
+	/* Can't reserve the prom region, it is already marked as
+	 * used, at least on x86. Instead, reserve a memory region a
+	 * board would certainly use. If it works, go ahead. If not,
+	 * run like hell... */
+
+	if (!request_mem_region (mem_addr, 16, depca_string))
+		return unknown;
+
+	/* Copy the first 16 bytes of ROM */
+
+	ptr = ioremap(prom_addr, 16);
+	if (ptr == NULL) {
+		printk(KERN_ERR "depca: I/O remap failed at %lx\n", prom_addr);
+		return unknown;
+	}
+	for (i = 0; i < 16; i++) {
+		tmpstr[i] = readb(ptr + i);
+	}
+	iounmap(ptr);
+
+	release_mem_region (mem_addr, 16);
+
+	/* Check if PROM contains a valid string */
+	for (i = 0; *depca_signature[i] != '\0'; i++) {
+		for (j = 0, k = 0; j < 16 && k < strlen(depca_signature[i]); j++) {
+			if (depca_signature[i][k] == tmpstr[j]) {	/* track signature */
+				k++;
+			} else {	/* lost signature; begin search again */
+				k = 0;
+			}
+		}
+		if (k == strlen(depca_signature[i]))
+			break;
+	}
+
+	/* Check if name string is valid, provided there's no PROM */
+	if (name && *name && (i == unknown)) {
+		for (i = 0; *depca_signature[i] != '\0'; i++) {
+			if (strcmp(name, depca_signature[i]) == 0)
+				break;
+		}
+	}
+
+	return i;
+}
+
+/*
+** Look for a special sequence in the Ethernet station address PROM that
+** is common across all DEPCA products. Note that the original DEPCA needs
+** its ROM address counter to be initialized and enabled. Only enable
+** if the first address octet is a 0x08 - this minimises the chances of
+** messing around with some other hardware, but it assumes that this DEPCA
+** card initialized itself correctly.
+**
+** Search the Ethernet address ROM for the signature. Since the ROM address
+** counter can start at an arbitrary point, the search must include the entire
+** probe sequence length plus the (length_of_the_signature - 1).
+** Stop the search IMMEDIATELY after the signature is found so that the
+** PROM address counter is correctly positioned at the start of the
+** ethernet address for later read out.
+*/
+static int __init DevicePresent(u_long ioaddr)
+{
+	union {
+		struct {
+			u32 a;
+			u32 b;
+		} llsig;
+		char Sig[sizeof(u32) << 1];
+	}
+	dev;
+	short sigLength = 0;
+	s8 data;
+	s16 nicsr;
+	int i, j, status = 0;
+
+	data = inb(DEPCA_PROM);	/* clear counter on DEPCA */
+	data = inb(DEPCA_PROM);	/* read data */
+
+	if (data == 0x08) {	/* Enable counter on DEPCA */
+		nicsr = inb(DEPCA_NICSR);
+		nicsr |= AAC;
+		outb(nicsr, DEPCA_NICSR);
+	}
+
+	dev.llsig.a = ETH_PROM_SIG;
+	dev.llsig.b = ETH_PROM_SIG;
+	sigLength = sizeof(u32) << 1;
+
+	for (i = 0, j = 0; j < sigLength && i < PROBE_LENGTH + sigLength - 1; i++) {
+		data = inb(DEPCA_PROM);
+		if (dev.Sig[j] == data) {	/* track signature */
+			j++;
+		} else {	/* lost signature; begin search again */
+			if (data == dev.Sig[0]) {	/* rare case.... */
+				j = 1;
+			} else {
+				j = 0;
+			}
+		}
+	}
+
+	if (j != sigLength) {
+		status = -ENODEV;	/* search failed */
+	}
+
+	return status;
+}
+
+/*
+** The DE100 and DE101 PROM accesses were made non-standard for some bizarre
+** reason: access the upper half of the PROM with x=0; access the lower half
+** with x=1.
+*/
+static int __init get_hw_addr(struct net_device *dev)
+{
+	u_long ioaddr = dev->base_addr;
+	struct depca_private *lp = netdev_priv(dev);
+	int i, k, tmp, status = 0;
+	u_short j, x, chksum;
+
+	x = (((lp->adapter == de100) || (lp->adapter == de101)) ? 1 : 0);
+
+	for (i = 0, k = 0, j = 0; j < 3; j++) {
+		k <<= 1;
+		if (k > 0xffff)
+			k -= 0xffff;
+
+		k += (u_char) (tmp = inb(DEPCA_PROM + x));
+		dev->dev_addr[i++] = (u_char) tmp;
+		k += (u_short) ((tmp = inb(DEPCA_PROM + x)) << 8);
+		dev->dev_addr[i++] = (u_char) tmp;
+
+		if (k > 0xffff)
+			k -= 0xffff;
+	}
+	if (k == 0xffff)
+		k = 0;
+
+	chksum = (u_char) inb(DEPCA_PROM + x);
+	chksum |= (u_short) (inb(DEPCA_PROM + x) << 8);
+	if (k != chksum)
+		status = -1;
+
+	return status;
+}
+
+/*
+** Load a packet into the shared memory
+*/
+static int load_packet(struct net_device *dev, struct sk_buff *skb)
+{
+	struct depca_private *lp = netdev_priv(dev);
+	int i, entry, end, len, status = NETDEV_TX_OK;
+
+	entry = lp->tx_new;	/* Ring around buffer number. */
+	end = (entry + (skb->len - 1) / TX_BUFF_SZ) & lp->txRingMask;
+	if (!(readl(&lp->tx_ring[end].base) & T_OWN)) {	/* Enough room? */
+		/*
+		   ** Caution: the write order is important here... don't set up the
+		   ** ownership rights until all the other information is in place.
+		 */
+		if (end < entry) {	/* wrapped buffer */
+			len = (lp->txRingMask - entry + 1) * TX_BUFF_SZ;
+			memcpy_toio(lp->tx_buff[entry], skb->data, len);
+			memcpy_toio(lp->tx_buff[0], skb->data + len, skb->len - len);
+		} else {	/* linear buffer */
+			memcpy_toio(lp->tx_buff[entry], skb->data, skb->len);
+		}
+
+		/* set up the buffer descriptors */
+		len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
+		for (i = entry; i != end; i = (i+1) & lp->txRingMask) {
+			/* clean out flags */
+			writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base);
+			writew(0x0000, &lp->tx_ring[i].misc);	/* clears other error flags */
+			writew(-TX_BUFF_SZ, &lp->tx_ring[i].length);	/* packet length in buffer */
+			len -= TX_BUFF_SZ;
+		}
+		/* clean out flags */
+		writel(readl(&lp->tx_ring[end].base) & ~T_FLAGS, &lp->tx_ring[end].base);
+		writew(0x0000, &lp->tx_ring[end].misc);	/* clears other error flags */
+		writew(-len, &lp->tx_ring[end].length);	/* packet length in last buff */
+
+		/* start of packet */
+		writel(readl(&lp->tx_ring[entry].base) | T_STP, &lp->tx_ring[entry].base);
+		/* end of packet */
+		writel(readl(&lp->tx_ring[end].base) | T_ENP, &lp->tx_ring[end].base);
+
+		for (i = end; i != entry; --i) {
+			/* ownership of packet */
+			writel(readl(&lp->tx_ring[i].base) | T_OWN, &lp->tx_ring[i].base);
+			if (i == 0)
+				i = lp->txRingMask + 1;
+		}
+		writel(readl(&lp->tx_ring[entry].base) | T_OWN, &lp->tx_ring[entry].base);
+
+		lp->tx_new = (++end) & lp->txRingMask;	/* update current pointers */
+	} else {
+		status = NETDEV_TX_LOCKED;
+	}
+
+	return status;
+}
+
+static void depca_dbg_open(struct net_device *dev)
+{
+	struct depca_private *lp = netdev_priv(dev);
+	u_long ioaddr = dev->base_addr;
+	struct depca_init *p = &lp->init_block;
+	int i;
+
+	if (depca_debug > 1) {
+		/* Do not copy the shadow init block into shared memory */
+		/* Debugging should not affect normal operation! */
+		/* The shadow init block will get copied across during InitRestartDepca */
+		printk("%s: depca open with irq %d\n", dev->name, dev->irq);
+		printk("Descriptor head addresses (CPU):\n");
+		printk("        0x%lx  0x%lx\n", (u_long) lp->rx_ring, (u_long) lp->tx_ring);
+		printk("Descriptor addresses (CPU):\nRX: ");
+		for (i = 0; i < lp->rxRingMask; i++) {
+			if (i < 3) {
+				printk("%p ", &lp->rx_ring[i].base);
+			}
+		}
+		printk("...%p\n", &lp->rx_ring[i].base);
+		printk("TX: ");
+		for (i = 0; i < lp->txRingMask; i++) {
+			if (i < 3) {
+				printk("%p ", &lp->tx_ring[i].base);
+			}
+		}
+		printk("...%p\n", &lp->tx_ring[i].base);
+		printk("\nDescriptor buffers (Device):\nRX: ");
+		for (i = 0; i < lp->rxRingMask; i++) {
+			if (i < 3) {
+				printk("0x%8.8x  ", readl(&lp->rx_ring[i].base));
+			}
+		}
+		printk("...0x%8.8x\n", readl(&lp->rx_ring[i].base));
+		printk("TX: ");
+		for (i = 0; i < lp->txRingMask; i++) {
+			if (i < 3) {
+				printk("0x%8.8x  ", readl(&lp->tx_ring[i].base));
+			}
+		}
+		printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base));
+		printk("Initialisation block at 0x%8.8lx(Phys)\n", lp->mem_start);
+		printk("        mode: 0x%4.4x\n", p->mode);
+		printk("        physical address: %pM\n", p->phys_addr);
+		printk("        multicast hash table: ");
+		for (i = 0; i < (HASH_TABLE_LEN >> 3) - 1; i++) {
+			printk("%2.2x:", p->mcast_table[i]);
+		}
+		printk("%2.2x\n", p->mcast_table[i]);
+		printk("        rx_ring at: 0x%8.8x\n", p->rx_ring);
+		printk("        tx_ring at: 0x%8.8x\n", p->tx_ring);
+		printk("buffers (Phys): 0x%8.8lx\n", lp->mem_start + lp->buffs_offset);
+		printk("Ring size:\nRX: %d  Log2(rxRingMask): 0x%8.8x\n", (int) lp->rxRingMask + 1, lp->rx_rlen);
+		printk("TX: %d  Log2(txRingMask): 0x%8.8x\n", (int) lp->txRingMask + 1, lp->tx_rlen);
+		outw(CSR2, DEPCA_ADDR);
+		printk("CSR2&1: 0x%4.4x", inw(DEPCA_DATA));
+		outw(CSR1, DEPCA_ADDR);
+		printk("%4.4x\n", inw(DEPCA_DATA));
+		outw(CSR3, DEPCA_ADDR);
+		printk("CSR3: 0x%4.4x\n", inw(DEPCA_DATA));
+	}
+}
+
+/*
+** Perform IOCTL call functions here. Some are privileged operations and the
+** effective uid is checked in those cases.
+** All multicast IOCTLs will not work here and are for testing purposes only.
+*/
+static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct depca_private *lp = netdev_priv(dev);
+	struct depca_ioctl *ioc = (struct depca_ioctl *) &rq->ifr_ifru;
+	int i, status = 0;
+	u_long ioaddr = dev->base_addr;
+	union {
+		u8 addr[(HASH_TABLE_LEN * ETH_ALEN)];
+		u16 sval[(HASH_TABLE_LEN * ETH_ALEN) >> 1];
+		u32 lval[(HASH_TABLE_LEN * ETH_ALEN) >> 2];
+	} tmp;
+	unsigned long flags;
+	void *buf;
+
+	switch (ioc->cmd) {
+	case DEPCA_GET_HWADDR:	/* Get the hardware address */
+		for (i = 0; i < ETH_ALEN; i++) {
+			tmp.addr[i] = dev->dev_addr[i];
+		}
+		ioc->len = ETH_ALEN;
+		if (copy_to_user(ioc->data, tmp.addr, ioc->len))
+			return -EFAULT;
+		break;
+
+	case DEPCA_SET_HWADDR:	/* Set the hardware address */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN))
+			return -EFAULT;
+		for (i = 0; i < ETH_ALEN; i++) {
+			dev->dev_addr[i] = tmp.addr[i];
+		}
+		netif_stop_queue(dev);
+		while (lp->tx_old != lp->tx_new)
+			cpu_relax();	/* Wait for the ring to empty */
+
+		STOP_DEPCA;	/* Temporarily stop the depca.  */
+		depca_init_ring(dev);	/* Initialize the descriptor rings */
+		LoadCSRs(dev);	/* Reload CSR3 */
+		InitRestartDepca(dev);	/* Resume normal operation. */
+		netif_start_queue(dev);	/* Unlock the TX ring */
+		break;
+
+	case DEPCA_SET_PROM:	/* Set Promiscuous Mode */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		netif_stop_queue(dev);
+		while (lp->tx_old != lp->tx_new)
+			cpu_relax();	/* Wait for the ring to empty */
+
+		STOP_DEPCA;	/* Temporarily stop the depca.  */
+		depca_init_ring(dev);	/* Initialize the descriptor rings */
+		lp->init_block.mode |= PROM;	/* Set promiscuous mode */
+
+		LoadCSRs(dev);	/* Reload CSR3 */
+		InitRestartDepca(dev);	/* Resume normal operation. */
+		netif_start_queue(dev);	/* Unlock the TX ring */
+		break;
+
+	case DEPCA_CLR_PROM:	/* Clear Promiscuous Mode */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		netif_stop_queue(dev);
+		while (lp->tx_old != lp->tx_new)
+			cpu_relax();	/* Wait for the ring to empty */
+
+		STOP_DEPCA;	/* Temporarily stop the depca.  */
+		depca_init_ring(dev);	/* Initialize the descriptor rings */
+		lp->init_block.mode &= ~PROM;	/* Clear promiscuous mode */
+
+		LoadCSRs(dev);	/* Reload CSR3 */
+		InitRestartDepca(dev);	/* Resume normal operation. */
+		netif_start_queue(dev);	/* Unlock the TX ring */
+		break;
+
+	case DEPCA_SAY_BOO:	/* Say "Boo!" to the kernel log file */
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		printk("%s: Boo!\n", dev->name);
+		break;
+
+	case DEPCA_GET_MCA:	/* Get the multicast address table */
+		ioc->len = (HASH_TABLE_LEN >> 3);
+		if (copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len))
+			return -EFAULT;
+		break;
+
+	case DEPCA_SET_MCA:	/* Set a multicast address */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (ioc->len >= HASH_TABLE_LEN)
+			return -EINVAL;
+		if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len))
+			return -EFAULT;
+		set_multicast_list(dev);
+		break;
+
+	case DEPCA_CLR_MCA:	/* Clear all multicast addresses */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		set_multicast_list(dev);
+		break;
+
+	case DEPCA_MCA_EN:	/* Enable pass all multicast addressing */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		set_multicast_list(dev);
+		break;
+
+	case DEPCA_GET_STATS:	/* Get the driver statistics */
+		ioc->len = sizeof(lp->pktStats);
+		buf = kmalloc(ioc->len, GFP_KERNEL);
+		if(!buf)
+			return -ENOMEM;
+		spin_lock_irqsave(&lp->lock, flags);
+		memcpy(buf, &lp->pktStats, ioc->len);
+		spin_unlock_irqrestore(&lp->lock, flags);
+		if (copy_to_user(ioc->data, buf, ioc->len))
+			status = -EFAULT;
+		kfree(buf);
+		break;
+
+	case DEPCA_CLR_STATS:	/* Zero out the driver statistics */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		spin_lock_irqsave(&lp->lock, flags);
+		memset(&lp->pktStats, 0, sizeof(lp->pktStats));
+		spin_unlock_irqrestore(&lp->lock, flags);
+		break;
+
+	case DEPCA_GET_REG:	/* Get the DEPCA Registers */
+		i = 0;
+		tmp.sval[i++] = inw(DEPCA_NICSR);
+		outw(CSR0, DEPCA_ADDR);	/* status register */
+		tmp.sval[i++] = inw(DEPCA_DATA);
+		memcpy(&tmp.sval[i], &lp->init_block, sizeof(struct depca_init));
+		ioc->len = i + sizeof(struct depca_init);
+		if (copy_to_user(ioc->data, tmp.addr, ioc->len))
+			return -EFAULT;
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return status;
+}
+
+static int __init depca_module_init (void)
+{
+	int err = 0;
+
+#ifdef CONFIG_MCA
+	err = mca_register_driver(&depca_mca_driver);
+	if (err)
+		goto err;
+#endif
+#ifdef CONFIG_EISA
+	err = eisa_driver_register(&depca_eisa_driver);
+	if (err)
+		goto err_mca;
+#endif
+	err = platform_driver_register(&depca_isa_driver);
+	if (err)
+		goto err_eisa;
+
+	depca_platform_probe();
+	return 0;
+
+err_eisa:
+#ifdef CONFIG_EISA
+	eisa_driver_unregister(&depca_eisa_driver);
+err_mca:
+#endif
+#ifdef CONFIG_MCA
+	mca_unregister_driver(&depca_mca_driver);
+err:
+#endif
+	return err;
+}
+
+static void __exit depca_module_exit (void)
+{
+	int i;
+#ifdef CONFIG_MCA
+        mca_unregister_driver (&depca_mca_driver);
+#endif
+#ifdef CONFIG_EISA
+        eisa_driver_unregister (&depca_eisa_driver);
+#endif
+	platform_driver_unregister (&depca_isa_driver);
+
+	for (i = 0; depca_io_ports[i].iobase; i++) {
+		if (depca_io_ports[i].device) {
+			depca_io_ports[i].device->dev.platform_data = NULL;
+			platform_device_unregister (depca_io_ports[i].device);
+			depca_io_ports[i].device = NULL;
+		}
+	}
+}
+
+module_init (depca_module_init);
+module_exit (depca_module_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/depca.h linux-libre-3.2-gnu/drivers/net/ethernet/amd/depca.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/depca.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/depca.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,183 @@
+/*
+    Written 1994 by David C. Davies.
+
+    Copyright 1994 David C. Davies. This software may be used and distributed
+    according to the terms of the GNU General Public License, incorporated herein by
+    reference.
+*/
+
+/*
+** I/O addresses. Note that the 2k buffer option is not supported in
+** this driver.
+*/
+#define DEPCA_NICSR ioaddr+0x00   /* Network interface CSR */
+#define DEPCA_RBI   ioaddr+0x02   /* RAM buffer index (2k buffer mode) */
+#define DEPCA_DATA  ioaddr+0x04   /* LANCE registers' data port */
+#define DEPCA_ADDR  ioaddr+0x06   /* LANCE registers' address port */
+#define DEPCA_HBASE ioaddr+0x08   /* EISA high memory base address reg. */
+#define DEPCA_PROM  ioaddr+0x0c   /* Ethernet address ROM data port */
+#define DEPCA_CNFG  ioaddr+0x0c   /* EISA Configuration port */
+#define DEPCA_RBSA  ioaddr+0x0e   /* RAM buffer starting address (2k buff.) */
+
+/*
+** These are LANCE registers addressable through DEPCA_ADDR
+*/
+#define CSR0       0
+#define CSR1       1
+#define CSR2       2
+#define CSR3       3
+
+/*
+** NETWORK INTERFACE CSR (NI_CSR) bit definitions
+*/
+
+#define TO       	0x0100	/* Time Out for remote boot */
+#define SHE      	0x0080  /* SHadow memory Enable */
+#define BS       	0x0040  /* Bank Select */
+#define BUF      	0x0020	/* BUFfer size (1->32k, 0->64k) */
+#define RBE      	0x0010	/* Remote Boot Enable (1->net boot) */
+#define AAC      	0x0008  /* Address ROM Address Counter (1->enable) */
+#define _128KB      	0x0008  /* 128kB Network RAM (1->enable) */
+#define IM       	0x0004	/* Interrupt Mask (1->mask) */
+#define IEN      	0x0002	/* Interrupt tristate ENable (1->enable) */
+#define LED      	0x0001	/* LED control */
+
+/*
+** Control and Status Register 0 (CSR0) bit definitions
+*/
+
+#define ERR     	0x8000 	/* Error summary */
+#define BABL    	0x4000 	/* Babble transmitter timeout error  */
+#define CERR    	0x2000 	/* Collision Error */
+#define MISS    	0x1000 	/* Missed packet */
+#define MERR    	0x0800 	/* Memory Error */
+#define RINT    	0x0400 	/* Receiver Interrupt */
+#define TINT    	0x0200 	/* Transmit Interrupt */
+#define IDON    	0x0100 	/* Initialization Done */
+#define INTR    	0x0080 	/* Interrupt Flag */
+#define INEA    	0x0040 	/* Interrupt Enable */
+#define RXON    	0x0020 	/* Receiver on */
+#define TXON    	0x0010 	/* Transmitter on */
+#define TDMD    	0x0008 	/* Transmit Demand */
+#define STOP    	0x0004 	/* Stop */
+#define STRT    	0x0002 	/* Start */
+#define INIT    	0x0001 	/* Initialize */
+#define INTM            0xff00  /* Interrupt Mask */
+#define INTE            0xfff0  /* Interrupt Enable */
+
+/*
+** CONTROL AND STATUS REGISTER 3 (CSR3)
+*/
+
+#define BSWP    	0x0004	/* Byte SWaP */
+#define ACON    	0x0002	/* ALE control */
+#define BCON    	0x0001	/* Byte CONtrol */
+
+/*
+** Initialization Block Mode Register
+*/
+
+#define PROM       	0x8000 	/* Promiscuous Mode */
+#define EMBA       	0x0080	/* Enable Modified Back-off Algorithm */
+#define INTL       	0x0040 	/* Internal Loopback */
+#define DRTY       	0x0020 	/* Disable Retry */
+#define COLL       	0x0010 	/* Force Collision */
+#define DTCR       	0x0008 	/* Disable Transmit CRC */
+#define LOOP       	0x0004 	/* Loopback */
+#define DTX        	0x0002 	/* Disable the Transmitter */
+#define DRX        	0x0001 	/* Disable the Receiver */
+
+/*
+** Receive Message Descriptor 1 (RMD1) bit definitions.
+*/
+
+#define R_OWN       0x80000000 	/* Owner bit 0 = host, 1 = lance */
+#define R_ERR     	0x4000 	/* Error Summary */
+#define R_FRAM    	0x2000 	/* Framing Error */
+#define R_OFLO    	0x1000 	/* Overflow Error */
+#define R_CRC     	0x0800 	/* CRC Error */
+#define R_BUFF    	0x0400 	/* Buffer Error */
+#define R_STP     	0x0200 	/* Start of Packet */
+#define R_ENP     	0x0100 	/* End of Packet */
+
+/*
+** Transmit Message Descriptor 1 (TMD1) bit definitions.
+*/
+
+#define T_OWN       0x80000000 	/* Owner bit 0 = host, 1 = lance */
+#define T_ERR     	0x4000 	/* Error Summary */
+#define T_ADD_FCS 	0x2000 	/* More the 1 retry needed to Xmit */
+#define T_MORE    	0x1000	/* >1 retry to transmit packet */
+#define T_ONE     	0x0800 	/* 1 try needed to transmit the packet */
+#define T_DEF     	0x0400 	/* Deferred */
+#define T_STP       0x02000000 	/* Start of Packet */
+#define T_ENP       0x01000000	/* End of Packet */
+#define T_FLAGS     0xff000000  /* TX Flags Field */
+
+/*
+** Transmit Message Descriptor 3 (TMD3) bit definitions.
+*/
+
+#define TMD3_BUFF    0x8000	/* BUFFer error */
+#define TMD3_UFLO    0x4000	/* UnderFLOw error */
+#define TMD3_RES     0x2000	/* REServed */
+#define TMD3_LCOL    0x1000	/* Late COLlision */
+#define TMD3_LCAR    0x0800	/* Loss of CARrier */
+#define TMD3_RTRY    0x0400	/* ReTRY error */
+
+/*
+** EISA configuration Register (CNFG) bit definitions
+*/
+
+#define TIMEOUT       	0x0100	/* 0:2.5 mins, 1: 30 secs */
+#define REMOTE      	0x0080  /* Remote Boot Enable -> 1 */
+#define IRQ11       	0x0040  /* Enable -> 1 */
+#define IRQ10    	0x0020	/* Enable -> 1 */
+#define IRQ9    	0x0010	/* Enable -> 1 */
+#define IRQ5      	0x0008  /* Enable -> 1 */
+#define BUFF     	0x0004	/* 0: 64kB or 128kB, 1: 32kB */
+#define PADR16   	0x0002	/* RAM on 64kB boundary */
+#define PADR17    	0x0001	/* RAM on 128kB boundary */
+
+/*
+** Miscellaneous
+*/
+#define HASH_TABLE_LEN   64           /* Bits */
+#define HASH_BITS        0x003f       /* 6 LS bits */
+
+#define MASK_INTERRUPTS   1
+#define UNMASK_INTERRUPTS 0
+
+#define EISA_EN         0x0001        /* Enable EISA bus buffers */
+#define EISA_ID         iobase+0x0080 /* ID long word for EISA card */
+#define EISA_CTRL       iobase+0x0084 /* Control word for EISA card */
+
+/*
+** Include the IOCTL stuff
+*/
+#include <linux/sockios.h>
+
+struct depca_ioctl {
+	unsigned short cmd;                /* Command to run */
+	unsigned short len;                /* Length of the data buffer */
+	unsigned char  __user *data;       /* Pointer to the data buffer */
+};
+
+/*
+** Recognised commands for the driver
+*/
+#define DEPCA_GET_HWADDR	0x01 /* Get the hardware address */
+#define DEPCA_SET_HWADDR	0x02 /* Get the hardware address */
+#define DEPCA_SET_PROM  	0x03 /* Set Promiscuous Mode */
+#define DEPCA_CLR_PROM  	0x04 /* Clear Promiscuous Mode */
+#define DEPCA_SAY_BOO	        0x05 /* Say "Boo!" to the kernel log file */
+#define DEPCA_GET_MCA   	0x06 /* Get a multicast address */
+#define DEPCA_SET_MCA   	0x07 /* Set a multicast address */
+#define DEPCA_CLR_MCA    	0x08 /* Clear a multicast address */
+#define DEPCA_MCA_EN    	0x09 /* Enable a multicast address group */
+#define DEPCA_GET_STATS  	0x0a /* Get the driver statistics */
+#define DEPCA_CLR_STATS 	0x0b /* Zero out the driver statistics */
+#define DEPCA_GET_REG   	0x0c /* Get the Register contents */
+#define DEPCA_SET_REG   	0x0d /* Set the Register contents */
+#define DEPCA_DUMP              0x0f /* Dump the DEPCA Status */
+
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/hplance.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/hplance.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/hplance.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/hplance.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,242 @@
+/* hplance.c  : the  Linux/hp300/lance ethernet driver
+ *
+ * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
+ * Based on the Sun Lance driver and the NetBSD HP Lance driver
+ * Uses the generic 7990.c LANCE code.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+/* Used for the temporal inet entries and routing */
+#include <linux/socket.h>
+#include <linux/route.h>
+#include <linux/dio.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+
+#include "hplance.h"
+
+/* We have 16834 bytes of RAM for the init block and buffers. This places
+ * an upper limit on the number of buffers we can use. NetBSD uses 8 Rx
+ * buffers and 2 Tx buffers.
+ */
+#define LANCE_LOG_TX_BUFFERS 1
+#define LANCE_LOG_RX_BUFFERS 3
+
+#include "7990.h"                                 /* use generic LANCE code */
+
+/* Our private data structure */
+struct hplance_private {
+	struct lance_private lance;
+};
+
+/* function prototypes... This is easy because all the grot is in the
+ * generic LANCE support. All we have to support is probing for boards,
+ * plus board-specific init, open and close actions.
+ * Oh, and we need to tell the generic code how to read and write LANCE registers...
+ */
+static int __devinit hplance_init_one(struct dio_dev *d,
+				const struct dio_device_id *ent);
+static void __devinit hplance_init(struct net_device *dev,
+				struct dio_dev *d);
+static void __devexit hplance_remove_one(struct dio_dev *d);
+static void hplance_writerap(void *priv, unsigned short value);
+static void hplance_writerdp(void *priv, unsigned short value);
+static unsigned short hplance_readrdp(void *priv);
+static int hplance_open(struct net_device *dev);
+static int hplance_close(struct net_device *dev);
+
+static struct dio_device_id hplance_dio_tbl[] = {
+	{ DIO_ID_LAN },
+	{ 0 }
+};
+
+static struct dio_driver hplance_driver = {
+	.name      = "hplance",
+	.id_table  = hplance_dio_tbl,
+	.probe     = hplance_init_one,
+	.remove    = __devexit_p(hplance_remove_one),
+};
+
+static const struct net_device_ops hplance_netdev_ops = {
+	.ndo_open		= hplance_open,
+	.ndo_stop		= hplance_close,
+	.ndo_start_xmit		= lance_start_xmit,
+	.ndo_set_rx_mode	= lance_set_multicast,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= lance_poll,
+#endif
+};
+
+/* Find all the HP Lance boards and initialise them... */
+static int __devinit hplance_init_one(struct dio_dev *d,
+				const struct dio_device_id *ent)
+{
+	struct net_device *dev;
+	int err = -ENOMEM;
+	int i;
+
+	dev = alloc_etherdev(sizeof(struct hplance_private));
+	if (!dev)
+		goto out;
+
+	err = -EBUSY;
+	if (!request_mem_region(dio_resource_start(d),
+				dio_resource_len(d), d->name))
+		goto out_free_netdev;
+
+	hplance_init(dev, d);
+	err = register_netdev(dev);
+	if (err)
+		goto out_release_mem_region;
+
+	dio_set_drvdata(d, dev);
+
+	printk(KERN_INFO "%s: %s; select code %d, addr %2.2x", dev->name, d->name, d->scode, dev->dev_addr[0]);
+
+	for (i=1; i<6; i++) {
+		printk(":%2.2x", dev->dev_addr[i]);
+	}
+
+	printk(", irq %d\n", d->ipl);
+
+	return 0;
+
+ out_release_mem_region:
+	release_mem_region(dio_resource_start(d), dio_resource_len(d));
+ out_free_netdev:
+	free_netdev(dev);
+ out:
+	return err;
+}
+
+static void __devexit hplance_remove_one(struct dio_dev *d)
+{
+	struct net_device *dev = dio_get_drvdata(d);
+
+	unregister_netdev(dev);
+	release_mem_region(dio_resource_start(d), dio_resource_len(d));
+	free_netdev(dev);
+}
+
+/* Initialise a single lance board at the given DIO device */
+static void __devinit hplance_init(struct net_device *dev, struct dio_dev *d)
+{
+        unsigned long va = (d->resource.start + DIO_VIRADDRBASE);
+        struct hplance_private *lp;
+        int i;
+
+        /* reset the board */
+        out_8(va+DIO_IDOFF, 0xff);
+        udelay(100);                              /* ariba! ariba! udelay! udelay! */
+
+        /* Fill the dev fields */
+        dev->base_addr = va;
+        dev->netdev_ops = &hplance_netdev_ops;
+        dev->dma = 0;
+
+        for (i=0; i<6; i++) {
+                /* The NVRAM holds our ethernet address, one nibble per byte,
+                 * at bytes NVRAMOFF+1,3,5,7,9...
+                 */
+                dev->dev_addr[i] = ((in_8(va + HPLANCE_NVRAMOFF + i*4 + 1) & 0xF) << 4)
+                        | (in_8(va + HPLANCE_NVRAMOFF + i*4 + 3) & 0xF);
+        }
+
+        lp = netdev_priv(dev);
+        lp->lance.name = (char*)d->name;                /* discards const, shut up gcc */
+        lp->lance.base = va;
+        lp->lance.init_block = (struct lance_init_block *)(va + HPLANCE_MEMOFF); /* CPU addr */
+        lp->lance.lance_init_block = NULL;              /* LANCE addr of same RAM */
+        lp->lance.busmaster_regval = LE_C3_BSWP;        /* we're bigendian */
+        lp->lance.irq = d->ipl;
+        lp->lance.writerap = hplance_writerap;
+        lp->lance.writerdp = hplance_writerdp;
+        lp->lance.readrdp = hplance_readrdp;
+        lp->lance.lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;
+        lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
+        lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK;
+        lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK;
+}
+
+/* This is disgusting. We have to check the DIO status register for ack every
+ * time we read or write the LANCE registers.
+ */
+static void hplance_writerap(void *priv, unsigned short value)
+{
+	struct lance_private *lp = (struct lance_private *)priv;
+	do {
+		out_be16(lp->base + HPLANCE_REGOFF + LANCE_RAP, value);
+	} while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
+}
+
+static void hplance_writerdp(void *priv, unsigned short value)
+{
+	struct lance_private *lp = (struct lance_private *)priv;
+	do {
+		out_be16(lp->base + HPLANCE_REGOFF + LANCE_RDP, value);
+	} while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
+}
+
+static unsigned short hplance_readrdp(void *priv)
+{
+	struct lance_private *lp = (struct lance_private *)priv;
+	__u16 value;
+	do {
+		value = in_be16(lp->base + HPLANCE_REGOFF + LANCE_RDP);
+	} while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
+	return value;
+}
+
+static int hplance_open(struct net_device *dev)
+{
+        int status;
+        struct lance_private *lp = netdev_priv(dev);
+
+        status = lance_open(dev);                 /* call generic lance open code */
+        if (status)
+                return status;
+        /* enable interrupts at board level. */
+        out_8(lp->base + HPLANCE_STATUS, LE_IE);
+
+        return 0;
+}
+
+static int hplance_close(struct net_device *dev)
+{
+        struct lance_private *lp = netdev_priv(dev);
+
+        out_8(lp->base + HPLANCE_STATUS, 0);	/* disable interrupts at boardlevel */
+        lance_close(dev);
+        return 0;
+}
+
+static int __init hplance_init_module(void)
+{
+	return dio_register_driver(&hplance_driver);
+}
+
+static void __exit hplance_cleanup_module(void)
+{
+        dio_unregister_driver(&hplance_driver);
+}
+
+module_init(hplance_init_module);
+module_exit(hplance_cleanup_module);
+
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/hplance.h linux-libre-3.2-gnu/drivers/net/ethernet/amd/hplance.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/hplance.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/hplance.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,26 @@
+/* Random defines and structures for the HP Lance driver.
+ * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
+ * Based on the Sun Lance driver and the NetBSD HP Lance driver
+ */
+
+/* Registers */
+#define HPLANCE_ID		0x01		/* DIO register: ID byte */
+#define HPLANCE_STATUS		0x03		/* DIO register: interrupt enable/status */
+
+/* Control and status bits for the status register */
+#define LE_IE 0x80                                /* interrupt enable */
+#define LE_IR 0x40                                /* interrupt requested */
+#define LE_LOCK 0x08                              /* lock status register */
+#define LE_ACK 0x04                               /* ack of lock */
+#define LE_JAB 0x02                               /* loss of tx clock (???) */
+/* We can also extract the IPL from the status register with the standard
+ * DIO_IPL(hplance) macro, or using dio_scodetoipl()
+ */
+
+/* These are the offsets for the DIO regs (hplance_reg), lance_ioreg,
+ * memory and NVRAM:
+ */
+#define HPLANCE_IDOFF 0                           /* board baseaddr */
+#define HPLANCE_REGOFF 0x4000                     /* lance registers */
+#define HPLANCE_MEMOFF 0x8000                     /* struct lance_init_block */
+#define HPLANCE_NVRAMOFF 0xC008                   /* etheraddress as one *nibble* per byte */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/Kconfig linux-libre-3.2-gnu/drivers/net/ethernet/amd/Kconfig
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,195 @@
+#
+# AMD network device configuration
+#
+
+config NET_VENDOR_AMD
+	bool "AMD devices"
+	default y
+	depends on DIO || MACH_DECSTATION || MVME147 || ATARI || SUN3 || \
+		   SUN3X || SBUS || PCI || ZORRO || (ISA && ISA_DMA_API) || \
+		   (ARM && ARCH_EBSA110) || ISA || EISA || MCA || PCMCIA
+	---help---
+	  If you have a network (Ethernet) chipset belonging to this class,
+	  say Y.
+
+	  Note that the answer to this question does not directly affect
+	  the kernel: saying N will just case the configurator to skip all
+	  the questions regarding AMD chipsets. If you say Y, you will be asked
+	  for your specific chipset/driver in the following questions.
+
+if NET_VENDOR_AMD
+
+config A2065
+	tristate "A2065 support"
+	depends on ZORRO
+	select CRC32
+	---help---
+	  If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise,
+	  say N.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called a2065.
+
+config AMD8111_ETH
+	tristate "AMD 8111 (new PCI LANCE) support"
+	depends on PCI
+	select CRC32
+	select NET_CORE
+	select MII
+	---help---
+	  If you have an AMD 8111-based PCI LANCE ethernet card,
+	  answer Y here and read the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called amd8111e.
+
+config LANCE
+	tristate "AMD LANCE and PCnet (AT1500 and NE2100) support"
+	depends on ISA && ISA_DMA_API
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>. Some LinkSys cards are
+	  of this type.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called lance.  This is recommended.
+
+config PCNET32
+	tristate "AMD PCnet32 PCI support"
+	depends on PCI
+	select CRC32
+	select NET_CORE
+	select MII
+	---help---
+	  If you have a PCnet32 or PCnetPCI based network (Ethernet) card,
+	  answer Y here and read the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called pcnet32.
+
+config ARIADNE
+	tristate "Ariadne support"
+	depends on ZORRO
+	---help---
+	  If you have a Village Tronic Ariadne Ethernet adapter, say Y.
+	  Otherwise, say N.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called ariadne.
+
+config ARM_AM79C961A
+	bool "ARM EBSA110 AM79C961A support"
+	depends on ARM && ARCH_EBSA110
+	select CRC32
+	---help---
+	  If you wish to compile a kernel for the EBSA-110, then you should
+	  always answer Y to this.
+
+config ATARILANCE
+	tristate "Atari LANCE support"
+	depends on ATARI
+	---help---
+	  Say Y to include support for several Atari Ethernet adapters based
+	  on the AMD LANCE chipset: RieblCard (with or without battery), or
+	  PAMCard VME (also the version by Rhotron, with different addresses).
+
+config DECLANCE
+	tristate "DEC LANCE ethernet controller support"
+	depends on MACH_DECSTATION
+	select CRC32
+	---help---
+	  This driver is for the series of Ethernet controllers produced by
+	  DEC (now Compaq) based on the AMD LANCE chipset, including the
+	  DEPCA series.  (This chipset is better known via the NE2100 cards.)
+
+config DEPCA
+	tristate "DEPCA, DE10x, DE200, DE201, DE202, DE422 support"
+	depends on (ISA || EISA || MCA)
+	select CRC32
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto> as well as
+	  <file:drivers/net/depca.c>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called depca.
+
+config HPLANCE
+	bool "HP on-board LANCE support"
+	depends on DIO
+	select CRC32
+	---help---
+	  If you want to use the builtin "LANCE" Ethernet controller on an
+	  HP300 machine, say Y here.
+
+config MIPS_AU1X00_ENET
+	tristate "MIPS AU1000 Ethernet support"
+	depends on MIPS_ALCHEMY
+	select PHYLIB
+	select CRC32
+	---help---
+	  If you have an Alchemy Semi AU1X00 based system
+	  say Y.  Otherwise, say N.
+
+config MVME147_NET
+	tristate "MVME147 (LANCE) Ethernet support"
+	depends on MVME147
+	select CRC32
+	---help---
+	  Support for the on-board Ethernet interface on the Motorola MVME147
+	  single-board computer.  Say Y here to include the
+	  driver for this chip in your kernel.
+	  To compile this driver as a module, choose M here.
+
+config PCMCIA_NMCLAN
+	tristate "New Media PCMCIA support"
+	depends on PCMCIA
+	help
+	  Say Y here if you intend to attach a New Media Ethernet or LiveWire
+	  PCMCIA (PC-card) Ethernet card to your computer.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called nmclan_cs.  If unsure, say N.
+
+config NI65
+	tristate "NI6510 support"
+	depends on ISA && ISA_DMA_API
+	---help---
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called ni65.
+
+config SUN3LANCE
+	tristate "Sun3/Sun3x on-board LANCE support"
+	depends on (SUN3 || SUN3X)
+	---help---
+	  Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80)
+	  featured an AMD LANCE 10Mbit Ethernet controller on board; say Y
+	  here to compile in the Linux driver for this and enable Ethernet.
+	  General Linux information on the Sun 3 and 3x series (now
+	  discontinued) is at
+	  <http://www.angelfire.com/ca2/tech68k/sun3.html>.
+
+	  If you're not building a kernel for a Sun 3, say N.
+
+config SUNLANCE
+	tristate "Sun LANCE support"
+	depends on SBUS
+	select CRC32
+	---help---
+	  This driver supports the "le" interface present on all 32-bit Sparc
+	  systems, on some older Ultra systems and as an Sbus option.  These
+	  cards are based on the AMD LANCE chipset, which is better known
+	  via the NE2100 cards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called sunlance.
+
+endif # NET_VENDOR_AMD
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/lance.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/lance.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/lance.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/lance.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1313 @@
+/* lance.c: An AMD LANCE/PCnet ethernet driver for Linux. */
+/*
+	Written/copyright 1993-1998 by Donald Becker.
+
+	Copyright 1993 United States Government as represented by the
+	Director, National Security Agency.
+	This software may be used and distributed according to the terms
+	of the GNU General Public License, incorporated herein by reference.
+
+	This driver is for the Allied Telesis AT1500 and HP J2405A, and should work
+	with most other LANCE-based bus-master (NE2100/NE2500) ethercards.
+
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+	Andrey V. Savochkin:
+	- alignment problem with 1.3.* kernel and some minor changes.
+	Thomas Bogendoerfer (tsbogend@bigbug.franken.de):
+	- added support for Linux/Alpha, but removed most of it, because
+        it worked only for the PCI chip.
+      - added hook for the 32bit lance driver
+      - added PCnetPCI II (79C970A) to chip table
+	Paul Gortmaker (gpg109@rsphy1.anu.edu.au):
+	- hopefully fix above so Linux/Alpha can use ISA cards too.
+    8/20/96 Fixed 7990 autoIRQ failure and reversed unneeded alignment -djb
+    v1.12 10/27/97 Module support -djb
+    v1.14  2/3/98 Module support modified, made PCI support optional -djb
+    v1.15 5/27/99 Fixed bug in the cleanup_module(). dev->priv was freed
+                  before unregister_netdev() which caused NULL pointer
+                  reference later in the chain (in rtnetlink_fill_ifinfo())
+                  -- Mika Kuoppala <miku@iki.fi>
+
+    Forward ported v1.14 to 2.1.129, merged the PCI and misc changes from
+    the 2.1 version of the old driver - Alan Cox
+
+    Get rid of check_region, check kmalloc return in lance_probe1
+    Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 11/01/2001
+
+	Reworked detection, added support for Racal InterLan EtherBlaster cards
+	Vesselin Kostadinov <vesok at yahoo dot com > - 22/4/2004
+*/
+
+static const char version[] = "lance.c:v1.16 2006/11/09 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/mm.h>
+#include <linux/bitops.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+
+static unsigned int lance_portlist[] __initdata = { 0x300, 0x320, 0x340, 0x360, 0};
+static int lance_probe1(struct net_device *dev, int ioaddr, int irq, int options);
+static int __init do_lance_probe(struct net_device *dev);
+
+
+static struct card {
+	char id_offset14;
+	char id_offset15;
+} cards[] = {
+	{	//"normal"
+		.id_offset14 = 0x57,
+		.id_offset15 = 0x57,
+	},
+	{	//NI6510EB
+		.id_offset14 = 0x52,
+		.id_offset15 = 0x44,
+	},
+	{	//Racal InterLan EtherBlaster
+		.id_offset14 = 0x52,
+		.id_offset15 = 0x49,
+	},
+};
+#define NUM_CARDS 3
+
+#ifdef LANCE_DEBUG
+static int lance_debug = LANCE_DEBUG;
+#else
+static int lance_debug = 1;
+#endif
+
+/*
+				Theory of Operation
+
+I. Board Compatibility
+
+This device driver is designed for the AMD 79C960, the "PCnet-ISA
+single-chip ethernet controller for ISA".  This chip is used in a wide
+variety of boards from vendors such as Allied Telesis, HP, Kingston,
+and Boca.  This driver is also intended to work with older AMD 7990
+designs, such as the NE1500 and NE2100, and newer 79C961.  For convenience,
+I use the name LANCE to refer to all of the AMD chips, even though it properly
+refers only to the original 7990.
+
+II. Board-specific settings
+
+The driver is designed to work the boards that use the faster
+bus-master mode, rather than in shared memory mode.	 (Only older designs
+have on-board buffer memory needed to support the slower shared memory mode.)
+
+Most ISA boards have jumpered settings for the I/O base, IRQ line, and DMA
+channel.  This driver probes the likely base addresses:
+{0x300, 0x320, 0x340, 0x360}.
+After the board is found it generates a DMA-timeout interrupt and uses
+autoIRQ to find the IRQ line.  The DMA channel can be set with the low bits
+of the otherwise-unused dev->mem_start value (aka PARAM1).  If unset it is
+probed for by enabling each free DMA channel in turn and checking if
+initialization succeeds.
+
+The HP-J2405A board is an exception: with this board it is easy to read the
+EEPROM-set values for the base, IRQ, and DMA.  (Of course you must already
+_know_ the base address -- that field is for writing the EEPROM.)
+
+III. Driver operation
+
+IIIa. Ring buffers
+The LANCE uses ring buffers of Tx and Rx descriptors.  Each entry describes
+the base and length of the data buffer, along with status bits.	 The length
+of these buffers is set by LANCE_LOG_{RX,TX}_BUFFERS, which is log_2() of
+the buffer length (rather than being directly the buffer length) for
+implementation ease.  The current values are 2 (Tx) and 4 (Rx), which leads to
+ring sizes of 4 (Tx) and 16 (Rx).  Increasing the number of ring entries
+needlessly uses extra space and reduces the chance that an upper layer will
+be able to reorder queued Tx packets based on priority.	 Decreasing the number
+of entries makes it more difficult to achieve back-to-back packet transmission
+and increases the chance that Rx ring will overflow.  (Consider the worst case
+of receiving back-to-back minimum-sized packets.)
+
+The LANCE has the capability to "chain" both Rx and Tx buffers, but this driver
+statically allocates full-sized (slightly oversized -- PKT_BUF_SZ) buffers to
+avoid the administrative overhead. For the Rx side this avoids dynamically
+allocating full-sized buffers "just in case", at the expense of a
+memory-to-memory data copy for each packet received.  For most systems this
+is a good tradeoff: the Rx buffer will always be in low memory, the copy
+is inexpensive, and it primes the cache for later packet processing.  For Tx
+the buffers are only used when needed as low-memory bounce buffers.
+
+IIIB. 16M memory limitations.
+For the ISA bus master mode all structures used directly by the LANCE,
+the initialization block, Rx and Tx rings, and data buffers, must be
+accessible from the ISA bus, i.e. in the lower 16M of real memory.
+This is a problem for current Linux kernels on >16M machines. The network
+devices are initialized after memory initialization, and the kernel doles out
+memory from the top of memory downward.	 The current solution is to have a
+special network initialization routine that's called before memory
+initialization; this will eventually be generalized for all network devices.
+As mentioned before, low-memory "bounce-buffers" are used when needed.
+
+IIIC. Synchronization
+The driver runs as two independent, single-threaded flows of control.  One
+is the send-packet routine, which enforces single-threaded use by the
+dev->tbusy flag.  The other thread is the interrupt handler, which is single
+threaded by the hardware and other software.
+
+The send packet thread has partial control over the Tx ring and 'dev->tbusy'
+flag.  It sets the tbusy flag whenever it's queuing a Tx packet. If the next
+queue slot is empty, it clears the tbusy flag when finished otherwise it sets
+the 'lp->tx_full' flag.
+
+The interrupt handler has exclusive control over the Rx ring and records stats
+from the Tx ring. (The Tx-done interrupt can't be selectively turned off, so
+we can't avoid the interrupt overhead by having the Tx routine reap the Tx
+stats.)	 After reaping the stats, it marks the queue entry as empty by setting
+the 'base' to zero. Iff the 'lp->tx_full' flag is set, it clears both the
+tx_full and tbusy flags.
+
+*/
+
+/* Set the number of Tx and Rx buffers, using Log_2(# buffers).
+   Reasonable default values are 16 Tx buffers, and 16 Rx buffers.
+   That translates to 4 and 4 (16 == 2^^4).
+   This is a compile-time option for efficiency.
+   */
+#ifndef LANCE_LOG_TX_BUFFERS
+#define LANCE_LOG_TX_BUFFERS 4
+#define LANCE_LOG_RX_BUFFERS 4
+#endif
+
+#define TX_RING_SIZE			(1 << (LANCE_LOG_TX_BUFFERS))
+#define TX_RING_MOD_MASK		(TX_RING_SIZE - 1)
+#define TX_RING_LEN_BITS		((LANCE_LOG_TX_BUFFERS) << 29)
+
+#define RX_RING_SIZE			(1 << (LANCE_LOG_RX_BUFFERS))
+#define RX_RING_MOD_MASK		(RX_RING_SIZE - 1)
+#define RX_RING_LEN_BITS		((LANCE_LOG_RX_BUFFERS) << 29)
+
+#define PKT_BUF_SZ		1544
+
+/* Offsets from base I/O address. */
+#define LANCE_DATA 0x10
+#define LANCE_ADDR 0x12
+#define LANCE_RESET 0x14
+#define LANCE_BUS_IF 0x16
+#define LANCE_TOTAL_SIZE 0x18
+
+#define TX_TIMEOUT	(HZ/5)
+
+/* The LANCE Rx and Tx ring descriptors. */
+struct lance_rx_head {
+	s32 base;
+	s16 buf_length;			/* This length is 2s complement (negative)! */
+	s16 msg_length;			/* This length is "normal". */
+};
+
+struct lance_tx_head {
+	s32 base;
+	s16 length;				/* Length is 2s complement (negative)! */
+	s16 misc;
+};
+
+/* The LANCE initialization block, described in databook. */
+struct lance_init_block {
+	u16 mode;		/* Pre-set mode (reg. 15) */
+	u8  phys_addr[6]; /* Physical ethernet address */
+	u32 filter[2];			/* Multicast filter (unused). */
+	/* Receive and transmit ring base, along with extra bits. */
+	u32  rx_ring;			/* Tx and Rx ring base pointers */
+	u32  tx_ring;
+};
+
+struct lance_private {
+	/* The Tx and Rx ring entries must be aligned on 8-byte boundaries. */
+	struct lance_rx_head rx_ring[RX_RING_SIZE];
+	struct lance_tx_head tx_ring[TX_RING_SIZE];
+	struct lance_init_block	init_block;
+	const char *name;
+	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
+	struct sk_buff* tx_skbuff[TX_RING_SIZE];
+	/* The addresses of receive-in-place skbuffs. */
+	struct sk_buff* rx_skbuff[RX_RING_SIZE];
+	unsigned long rx_buffs;		/* Address of Rx and Tx buffers. */
+	/* Tx low-memory "bounce buffer" address. */
+	char (*tx_bounce_buffs)[PKT_BUF_SZ];
+	int cur_rx, cur_tx;			/* The next free ring entry */
+	int dirty_rx, dirty_tx;		/* The ring entries to be free()ed. */
+	int dma;
+	unsigned char chip_version;	/* See lance_chip_type. */
+	spinlock_t devlock;
+};
+
+#define LANCE_MUST_PAD          0x00000001
+#define LANCE_ENABLE_AUTOSELECT 0x00000002
+#define LANCE_MUST_REINIT_RING  0x00000004
+#define LANCE_MUST_UNRESET      0x00000008
+#define LANCE_HAS_MISSED_FRAME  0x00000010
+
+/* A mapping from the chip ID number to the part number and features.
+   These are from the datasheets -- in real life the '970 version
+   reportedly has the same ID as the '965. */
+static struct lance_chip_type {
+	int id_number;
+	const char *name;
+	int flags;
+} chip_table[] = {
+	{0x0000, "LANCE 7990",				/* Ancient lance chip.  */
+		LANCE_MUST_PAD + LANCE_MUST_UNRESET},
+	{0x0003, "PCnet/ISA 79C960",		/* 79C960 PCnet/ISA.  */
+		LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
+			LANCE_HAS_MISSED_FRAME},
+	{0x2260, "PCnet/ISA+ 79C961",		/* 79C961 PCnet/ISA+, Plug-n-Play.  */
+		LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
+			LANCE_HAS_MISSED_FRAME},
+	{0x2420, "PCnet/PCI 79C970",		/* 79C970 or 79C974 PCnet-SCSI, PCI. */
+		LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
+			LANCE_HAS_MISSED_FRAME},
+	/* Bug: the PCnet/PCI actually uses the PCnet/VLB ID number, so just call
+		it the PCnet32. */
+	{0x2430, "PCnet32",					/* 79C965 PCnet for VL bus. */
+		LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
+			LANCE_HAS_MISSED_FRAME},
+        {0x2621, "PCnet/PCI-II 79C970A",        /* 79C970A PCInetPCI II. */
+                LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
+                        LANCE_HAS_MISSED_FRAME},
+	{0x0, 	 "PCnet (unknown)",
+		LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
+			LANCE_HAS_MISSED_FRAME},
+};
+
+enum {OLD_LANCE = 0, PCNET_ISA=1, PCNET_ISAP=2, PCNET_PCI=3, PCNET_VLB=4, PCNET_PCI_II=5, LANCE_UNKNOWN=6};
+
+
+/* Non-zero if lance_probe1() needs to allocate low-memory bounce buffers.
+   Assume yes until we know the memory size. */
+static unsigned char lance_need_isa_bounce_buffers = 1;
+
+static int lance_open(struct net_device *dev);
+static void lance_init_ring(struct net_device *dev, gfp_t mode);
+static netdev_tx_t lance_start_xmit(struct sk_buff *skb,
+				    struct net_device *dev);
+static int lance_rx(struct net_device *dev);
+static irqreturn_t lance_interrupt(int irq, void *dev_id);
+static int lance_close(struct net_device *dev);
+static struct net_device_stats *lance_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+static void lance_tx_timeout (struct net_device *dev);
+
+
+
+#ifdef MODULE
+#define MAX_CARDS		8	/* Max number of interfaces (cards) per module */
+
+static struct net_device *dev_lance[MAX_CARDS];
+static int io[MAX_CARDS];
+static int dma[MAX_CARDS];
+static int irq[MAX_CARDS];
+
+module_param_array(io, int, NULL, 0);
+module_param_array(dma, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param(lance_debug, int, 0);
+MODULE_PARM_DESC(io, "LANCE/PCnet I/O base address(es),required");
+MODULE_PARM_DESC(dma, "LANCE/PCnet ISA DMA channel (ignored for some devices)");
+MODULE_PARM_DESC(irq, "LANCE/PCnet IRQ number (ignored for some devices)");
+MODULE_PARM_DESC(lance_debug, "LANCE/PCnet debug level (0-7)");
+
+int __init init_module(void)
+{
+	struct net_device *dev;
+	int this_dev, found = 0;
+
+	for (this_dev = 0; this_dev < MAX_CARDS; this_dev++) {
+		if (io[this_dev] == 0)  {
+			if (this_dev != 0) /* only complain once */
+				break;
+			printk(KERN_NOTICE "lance.c: Module autoprobing not allowed. Append \"io=0xNNN\" value(s).\n");
+			return -EPERM;
+		}
+		dev = alloc_etherdev(0);
+		if (!dev)
+			break;
+		dev->irq = irq[this_dev];
+		dev->base_addr = io[this_dev];
+		dev->dma = dma[this_dev];
+		if (do_lance_probe(dev) == 0) {
+			dev_lance[found++] = dev;
+			continue;
+		}
+		free_netdev(dev);
+		break;
+	}
+	if (found != 0)
+		return 0;
+	return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+	struct lance_private *lp = dev->ml_priv;
+	if (dev->dma != 4)
+		free_dma(dev->dma);
+	release_region(dev->base_addr, LANCE_TOTAL_SIZE);
+	kfree(lp->tx_bounce_buffs);
+	kfree((void*)lp->rx_buffs);
+	kfree(lp);
+}
+
+void __exit cleanup_module(void)
+{
+	int this_dev;
+
+	for (this_dev = 0; this_dev < MAX_CARDS; this_dev++) {
+		struct net_device *dev = dev_lance[this_dev];
+		if (dev) {
+			unregister_netdev(dev);
+			cleanup_card(dev);
+			free_netdev(dev);
+		}
+	}
+}
+#endif /* MODULE */
+MODULE_LICENSE("GPL");
+
+
+/* Starting in v2.1.*, the LANCE/PCnet probe is now similar to the other
+   board probes now that kmalloc() can allocate ISA DMA-able regions.
+   This also allows the LANCE driver to be used as a module.
+   */
+static int __init do_lance_probe(struct net_device *dev)
+{
+	unsigned int *port;
+	int result;
+
+	if (high_memory <= phys_to_virt(16*1024*1024))
+		lance_need_isa_bounce_buffers = 0;
+
+	for (port = lance_portlist; *port; port++) {
+		int ioaddr = *port;
+		struct resource *r = request_region(ioaddr, LANCE_TOTAL_SIZE,
+							"lance-probe");
+
+		if (r) {
+			/* Detect the card with minimal I/O reads */
+			char offset14 = inb(ioaddr + 14);
+			int card;
+			for (card = 0; card < NUM_CARDS; ++card)
+				if (cards[card].id_offset14 == offset14)
+					break;
+			if (card < NUM_CARDS) {/*yes, the first byte matches*/
+				char offset15 = inb(ioaddr + 15);
+				for (card = 0; card < NUM_CARDS; ++card)
+					if ((cards[card].id_offset14 == offset14) &&
+						(cards[card].id_offset15 == offset15))
+						break;
+			}
+			if (card < NUM_CARDS) { /*Signature OK*/
+				result = lance_probe1(dev, ioaddr, 0, 0);
+				if (!result) {
+					struct lance_private *lp = dev->ml_priv;
+					int ver = lp->chip_version;
+
+					r->name = chip_table[ver].name;
+					return 0;
+				}
+			}
+			release_region(ioaddr, LANCE_TOTAL_SIZE);
+		}
+	}
+	return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init lance_probe(int unit)
+{
+	struct net_device *dev = alloc_etherdev(0);
+	int err;
+
+	if (!dev)
+		return ERR_PTR(-ENODEV);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+
+	err = do_lance_probe(dev);
+	if (err)
+		goto out;
+	return dev;
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+#endif
+
+static const struct net_device_ops lance_netdev_ops = {
+	.ndo_open 		= lance_open,
+	.ndo_start_xmit		= lance_start_xmit,
+	.ndo_stop		= lance_close,
+	.ndo_get_stats		= lance_get_stats,
+	.ndo_set_rx_mode	= set_multicast_list,
+	.ndo_tx_timeout		= lance_tx_timeout,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int options)
+{
+	struct lance_private *lp;
+	unsigned long dma_channels;	/* Mark spuriously-busy DMA channels */
+	int i, reset_val, lance_version;
+	const char *chipname;
+	/* Flags for specific chips or boards. */
+	unsigned char hpJ2405A = 0;	/* HP ISA adaptor */
+	int hp_builtin = 0;		/* HP on-board ethernet. */
+	static int did_version;		/* Already printed version info. */
+	unsigned long flags;
+	int err = -ENOMEM;
+	void __iomem *bios;
+
+	/* First we look for special cases.
+	   Check for HP's on-board ethernet by looking for 'HP' in the BIOS.
+	   There are two HP versions, check the BIOS for the configuration port.
+	   This method provided by L. Julliard, Laurent_Julliard@grenoble.hp.com.
+	   */
+	bios = ioremap(0xf00f0, 0x14);
+	if (!bios)
+		return -ENOMEM;
+	if (readw(bios + 0x12) == 0x5048)  {
+		static const short ioaddr_table[] = { 0x300, 0x320, 0x340, 0x360};
+		int hp_port = (readl(bios + 1) & 1)  ? 0x499 : 0x99;
+		/* We can have boards other than the built-in!  Verify this is on-board. */
+		if ((inb(hp_port) & 0xc0) == 0x80 &&
+		    ioaddr_table[inb(hp_port) & 3] == ioaddr)
+			hp_builtin = hp_port;
+	}
+	iounmap(bios);
+	/* We also recognize the HP Vectra on-board here, but check below. */
+	hpJ2405A = (inb(ioaddr) == 0x08 && inb(ioaddr+1) == 0x00 &&
+		    inb(ioaddr+2) == 0x09);
+
+	/* Reset the LANCE.	 */
+	reset_val = inw(ioaddr+LANCE_RESET); /* Reset the LANCE */
+
+	/* The Un-Reset needed is only needed for the real NE2100, and will
+	   confuse the HP board. */
+	if (!hpJ2405A)
+		outw(reset_val, ioaddr+LANCE_RESET);
+
+	outw(0x0000, ioaddr+LANCE_ADDR); /* Switch to window 0 */
+	if (inw(ioaddr+LANCE_DATA) != 0x0004)
+		return -ENODEV;
+
+	/* Get the version of the chip. */
+	outw(88, ioaddr+LANCE_ADDR);
+	if (inw(ioaddr+LANCE_ADDR) != 88) {
+		lance_version = 0;
+	} else {			/* Good, it's a newer chip. */
+		int chip_version = inw(ioaddr+LANCE_DATA);
+		outw(89, ioaddr+LANCE_ADDR);
+		chip_version |= inw(ioaddr+LANCE_DATA) << 16;
+		if (lance_debug > 2)
+			printk("  LANCE chip version is %#x.\n", chip_version);
+		if ((chip_version & 0xfff) != 0x003)
+			return -ENODEV;
+		chip_version = (chip_version >> 12) & 0xffff;
+		for (lance_version = 1; chip_table[lance_version].id_number; lance_version++) {
+			if (chip_table[lance_version].id_number == chip_version)
+				break;
+		}
+	}
+
+	/* We can't allocate private data from alloc_etherdev() because it must
+	   a ISA DMA-able region. */
+	chipname = chip_table[lance_version].name;
+	printk("%s: %s at %#3x, ", dev->name, chipname, ioaddr);
+
+	/* There is a 16 byte station address PROM at the base address.
+	   The first six bytes are the station address. */
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = inb(ioaddr + i);
+	printk("%pM", dev->dev_addr);
+
+	dev->base_addr = ioaddr;
+	/* Make certain the data structures used by the LANCE are aligned and DMAble. */
+
+	lp = kzalloc(sizeof(*lp), GFP_DMA | GFP_KERNEL);
+	if(lp==NULL)
+		return -ENODEV;
+	if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp);
+	dev->ml_priv = lp;
+	lp->name = chipname;
+	lp->rx_buffs = (unsigned long)kmalloc(PKT_BUF_SZ*RX_RING_SIZE,
+						  GFP_DMA | GFP_KERNEL);
+	if (!lp->rx_buffs)
+		goto out_lp;
+	if (lance_need_isa_bounce_buffers) {
+		lp->tx_bounce_buffs = kmalloc(PKT_BUF_SZ*TX_RING_SIZE,
+						  GFP_DMA | GFP_KERNEL);
+		if (!lp->tx_bounce_buffs)
+			goto out_rx;
+	} else
+		lp->tx_bounce_buffs = NULL;
+
+	lp->chip_version = lance_version;
+	spin_lock_init(&lp->devlock);
+
+	lp->init_block.mode = 0x0003;		/* Disable Rx and Tx. */
+	for (i = 0; i < 6; i++)
+		lp->init_block.phys_addr[i] = dev->dev_addr[i];
+	lp->init_block.filter[0] = 0x00000000;
+	lp->init_block.filter[1] = 0x00000000;
+	lp->init_block.rx_ring = ((u32)isa_virt_to_bus(lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
+	lp->init_block.tx_ring = ((u32)isa_virt_to_bus(lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;
+
+	outw(0x0001, ioaddr+LANCE_ADDR);
+	inw(ioaddr+LANCE_ADDR);
+	outw((short) (u32) isa_virt_to_bus(&lp->init_block), ioaddr+LANCE_DATA);
+	outw(0x0002, ioaddr+LANCE_ADDR);
+	inw(ioaddr+LANCE_ADDR);
+	outw(((u32)isa_virt_to_bus(&lp->init_block)) >> 16, ioaddr+LANCE_DATA);
+	outw(0x0000, ioaddr+LANCE_ADDR);
+	inw(ioaddr+LANCE_ADDR);
+
+	if (irq) {					/* Set iff PCI card. */
+		dev->dma = 4;			/* Native bus-master, no DMA channel needed. */
+		dev->irq = irq;
+	} else if (hp_builtin) {
+		static const char dma_tbl[4] = {3, 5, 6, 0};
+		static const char irq_tbl[4] = {3, 4, 5, 9};
+		unsigned char port_val = inb(hp_builtin);
+		dev->dma = dma_tbl[(port_val >> 4) & 3];
+		dev->irq = irq_tbl[(port_val >> 2) & 3];
+		printk(" HP Vectra IRQ %d DMA %d.\n", dev->irq, dev->dma);
+	} else if (hpJ2405A) {
+		static const char dma_tbl[4] = {3, 5, 6, 7};
+		static const char irq_tbl[8] = {3, 4, 5, 9, 10, 11, 12, 15};
+		short reset_val = inw(ioaddr+LANCE_RESET);
+		dev->dma = dma_tbl[(reset_val >> 2) & 3];
+		dev->irq = irq_tbl[(reset_val >> 4) & 7];
+		printk(" HP J2405A IRQ %d DMA %d.\n", dev->irq, dev->dma);
+	} else if (lance_version == PCNET_ISAP) {		/* The plug-n-play version. */
+		short bus_info;
+		outw(8, ioaddr+LANCE_ADDR);
+		bus_info = inw(ioaddr+LANCE_BUS_IF);
+		dev->dma = bus_info & 0x07;
+		dev->irq = (bus_info >> 4) & 0x0F;
+	} else {
+		/* The DMA channel may be passed in PARAM1. */
+		if (dev->mem_start & 0x07)
+			dev->dma = dev->mem_start & 0x07;
+	}
+
+	if (dev->dma == 0) {
+		/* Read the DMA channel status register, so that we can avoid
+		   stuck DMA channels in the DMA detection below. */
+		dma_channels = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) |
+			(inb(DMA2_STAT_REG) & 0xf0);
+	}
+	err = -ENODEV;
+	if (dev->irq >= 2)
+		printk(" assigned IRQ %d", dev->irq);
+	else if (lance_version != 0)  {	/* 7990 boards need DMA detection first. */
+		unsigned long irq_mask;
+
+		/* To auto-IRQ we enable the initialization-done and DMA error
+		   interrupts. For ISA boards we get a DMA error, but VLB and PCI
+		   boards will work. */
+		irq_mask = probe_irq_on();
+
+		/* Trigger an initialization just for the interrupt. */
+		outw(0x0041, ioaddr+LANCE_DATA);
+
+		mdelay(20);
+		dev->irq = probe_irq_off(irq_mask);
+		if (dev->irq)
+			printk(", probed IRQ %d", dev->irq);
+		else {
+			printk(", failed to detect IRQ line.\n");
+			goto out_tx;
+		}
+
+		/* Check for the initialization done bit, 0x0100, which means
+		   that we don't need a DMA channel. */
+		if (inw(ioaddr+LANCE_DATA) & 0x0100)
+			dev->dma = 4;
+	}
+
+	if (dev->dma == 4) {
+		printk(", no DMA needed.\n");
+	} else if (dev->dma) {
+		if (request_dma(dev->dma, chipname)) {
+			printk("DMA %d allocation failed.\n", dev->dma);
+			goto out_tx;
+		} else
+			printk(", assigned DMA %d.\n", dev->dma);
+	} else {			/* OK, we have to auto-DMA. */
+		for (i = 0; i < 4; i++) {
+			static const char dmas[] = { 5, 6, 7, 3 };
+			int dma = dmas[i];
+			int boguscnt;
+
+			/* Don't enable a permanently busy DMA channel, or the machine
+			   will hang. */
+			if (test_bit(dma, &dma_channels))
+				continue;
+			outw(0x7f04, ioaddr+LANCE_DATA); /* Clear the memory error bits. */
+			if (request_dma(dma, chipname))
+				continue;
+
+			flags=claim_dma_lock();
+			set_dma_mode(dma, DMA_MODE_CASCADE);
+			enable_dma(dma);
+			release_dma_lock(flags);
+
+			/* Trigger an initialization. */
+			outw(0x0001, ioaddr+LANCE_DATA);
+			for (boguscnt = 100; boguscnt > 0; --boguscnt)
+				if (inw(ioaddr+LANCE_DATA) & 0x0900)
+					break;
+			if (inw(ioaddr+LANCE_DATA) & 0x0100) {
+				dev->dma = dma;
+				printk(", DMA %d.\n", dev->dma);
+				break;
+			} else {
+				flags=claim_dma_lock();
+				disable_dma(dma);
+				release_dma_lock(flags);
+				free_dma(dma);
+			}
+		}
+		if (i == 4) {			/* Failure: bail. */
+			printk("DMA detection failed.\n");
+			goto out_tx;
+		}
+	}
+
+	if (lance_version == 0 && dev->irq == 0) {
+		/* We may auto-IRQ now that we have a DMA channel. */
+		/* Trigger an initialization just for the interrupt. */
+		unsigned long irq_mask;
+
+		irq_mask = probe_irq_on();
+		outw(0x0041, ioaddr+LANCE_DATA);
+
+		mdelay(40);
+		dev->irq = probe_irq_off(irq_mask);
+		if (dev->irq == 0) {
+			printk("  Failed to detect the 7990 IRQ line.\n");
+			goto out_dma;
+		}
+		printk("  Auto-IRQ detected IRQ%d.\n", dev->irq);
+	}
+
+	if (chip_table[lp->chip_version].flags & LANCE_ENABLE_AUTOSELECT) {
+		/* Turn on auto-select of media (10baseT or BNC) so that the user
+		   can watch the LEDs even if the board isn't opened. */
+		outw(0x0002, ioaddr+LANCE_ADDR);
+		/* Don't touch 10base2 power bit. */
+		outw(inw(ioaddr+LANCE_BUS_IF) | 0x0002, ioaddr+LANCE_BUS_IF);
+	}
+
+	if (lance_debug > 0  &&  did_version++ == 0)
+		printk(version);
+
+	/* The LANCE-specific entries in the device structure. */
+	dev->netdev_ops = &lance_netdev_ops;
+	dev->watchdog_timeo = TX_TIMEOUT;
+
+	err = register_netdev(dev);
+	if (err)
+		goto out_dma;
+	return 0;
+out_dma:
+	if (dev->dma != 4)
+		free_dma(dev->dma);
+out_tx:
+	kfree(lp->tx_bounce_buffs);
+out_rx:
+	kfree((void*)lp->rx_buffs);
+out_lp:
+	kfree(lp);
+	return err;
+}
+
+
+static int
+lance_open(struct net_device *dev)
+{
+	struct lance_private *lp = dev->ml_priv;
+	int ioaddr = dev->base_addr;
+	int i;
+
+	if (dev->irq == 0 ||
+		request_irq(dev->irq, lance_interrupt, 0, lp->name, dev)) {
+		return -EAGAIN;
+	}
+
+	/* We used to allocate DMA here, but that was silly.
+	   DMA lines can't be shared!  We now permanently allocate them. */
+
+	/* Reset the LANCE */
+	inw(ioaddr+LANCE_RESET);
+
+	/* The DMA controller is used as a no-operation slave, "cascade mode". */
+	if (dev->dma != 4) {
+		unsigned long flags=claim_dma_lock();
+		enable_dma(dev->dma);
+		set_dma_mode(dev->dma, DMA_MODE_CASCADE);
+		release_dma_lock(flags);
+	}
+
+	/* Un-Reset the LANCE, needed only for the NE2100. */
+	if (chip_table[lp->chip_version].flags & LANCE_MUST_UNRESET)
+		outw(0, ioaddr+LANCE_RESET);
+
+	if (chip_table[lp->chip_version].flags & LANCE_ENABLE_AUTOSELECT) {
+		/* This is 79C960-specific: Turn on auto-select of media (AUI, BNC). */
+		outw(0x0002, ioaddr+LANCE_ADDR);
+		/* Only touch autoselect bit. */
+		outw(inw(ioaddr+LANCE_BUS_IF) | 0x0002, ioaddr+LANCE_BUS_IF);
+ 	}
+
+	if (lance_debug > 1)
+		printk("%s: lance_open() irq %d dma %d tx/rx rings %#x/%#x init %#x.\n",
+			   dev->name, dev->irq, dev->dma,
+		           (u32) isa_virt_to_bus(lp->tx_ring),
+		           (u32) isa_virt_to_bus(lp->rx_ring),
+			   (u32) isa_virt_to_bus(&lp->init_block));
+
+	lance_init_ring(dev, GFP_KERNEL);
+	/* Re-initialize the LANCE, and start it when done. */
+	outw(0x0001, ioaddr+LANCE_ADDR);
+	outw((short) (u32) isa_virt_to_bus(&lp->init_block), ioaddr+LANCE_DATA);
+	outw(0x0002, ioaddr+LANCE_ADDR);
+	outw(((u32)isa_virt_to_bus(&lp->init_block)) >> 16, ioaddr+LANCE_DATA);
+
+	outw(0x0004, ioaddr+LANCE_ADDR);
+	outw(0x0915, ioaddr+LANCE_DATA);
+
+	outw(0x0000, ioaddr+LANCE_ADDR);
+	outw(0x0001, ioaddr+LANCE_DATA);
+
+	netif_start_queue (dev);
+
+	i = 0;
+	while (i++ < 100)
+		if (inw(ioaddr+LANCE_DATA) & 0x0100)
+			break;
+	/*
+	 * We used to clear the InitDone bit, 0x0100, here but Mark Stockton
+	 * reports that doing so triggers a bug in the '974.
+	 */
+ 	outw(0x0042, ioaddr+LANCE_DATA);
+
+	if (lance_debug > 2)
+		printk("%s: LANCE open after %d ticks, init block %#x csr0 %4.4x.\n",
+			   dev->name, i, (u32) isa_virt_to_bus(&lp->init_block), inw(ioaddr+LANCE_DATA));
+
+	return 0;					/* Always succeed */
+}
+
+/* The LANCE has been halted for one reason or another (busmaster memory
+   arbitration error, Tx FIFO underflow, driver stopped it to reconfigure,
+   etc.).  Modern LANCE variants always reload their ring-buffer
+   configuration when restarted, so we must reinitialize our ring
+   context before restarting.  As part of this reinitialization,
+   find all packets still on the Tx ring and pretend that they had been
+   sent (in effect, drop the packets on the floor) - the higher-level
+   protocols will time out and retransmit.  It'd be better to shuffle
+   these skbs to a temp list and then actually re-Tx them after
+   restarting the chip, but I'm too lazy to do so right now.  dplatt@3do.com
+*/
+
+static void
+lance_purge_ring(struct net_device *dev)
+{
+	struct lance_private *lp = dev->ml_priv;
+	int i;
+
+	/* Free all the skbuffs in the Rx and Tx queues. */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		struct sk_buff *skb = lp->rx_skbuff[i];
+		lp->rx_skbuff[i] = NULL;
+		lp->rx_ring[i].base = 0;		/* Not owned by LANCE chip. */
+		if (skb)
+			dev_kfree_skb_any(skb);
+	}
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		if (lp->tx_skbuff[i]) {
+			dev_kfree_skb_any(lp->tx_skbuff[i]);
+			lp->tx_skbuff[i] = NULL;
+		}
+	}
+}
+
+
+/* Initialize the LANCE Rx and Tx rings. */
+static void
+lance_init_ring(struct net_device *dev, gfp_t gfp)
+{
+	struct lance_private *lp = dev->ml_priv;
+	int i;
+
+	lp->cur_rx = lp->cur_tx = 0;
+	lp->dirty_rx = lp->dirty_tx = 0;
+
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		struct sk_buff *skb;
+		void *rx_buff;
+
+		skb = alloc_skb(PKT_BUF_SZ, GFP_DMA | gfp);
+		lp->rx_skbuff[i] = skb;
+		if (skb) {
+			skb->dev = dev;
+			rx_buff = skb->data;
+		} else
+			rx_buff = kmalloc(PKT_BUF_SZ, GFP_DMA | gfp);
+		if (rx_buff == NULL)
+			lp->rx_ring[i].base = 0;
+		else
+			lp->rx_ring[i].base = (u32)isa_virt_to_bus(rx_buff) | 0x80000000;
+		lp->rx_ring[i].buf_length = -PKT_BUF_SZ;
+	}
+	/* The Tx buffer address is filled in as needed, but we do need to clear
+	   the upper ownership bit. */
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		lp->tx_skbuff[i] = NULL;
+		lp->tx_ring[i].base = 0;
+	}
+
+	lp->init_block.mode = 0x0000;
+	for (i = 0; i < 6; i++)
+		lp->init_block.phys_addr[i] = dev->dev_addr[i];
+	lp->init_block.filter[0] = 0x00000000;
+	lp->init_block.filter[1] = 0x00000000;
+	lp->init_block.rx_ring = ((u32)isa_virt_to_bus(lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
+	lp->init_block.tx_ring = ((u32)isa_virt_to_bus(lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;
+}
+
+static void
+lance_restart(struct net_device *dev, unsigned int csr0_bits, int must_reinit)
+{
+	struct lance_private *lp = dev->ml_priv;
+
+	if (must_reinit ||
+		(chip_table[lp->chip_version].flags & LANCE_MUST_REINIT_RING)) {
+		lance_purge_ring(dev);
+		lance_init_ring(dev, GFP_ATOMIC);
+	}
+	outw(0x0000,    dev->base_addr + LANCE_ADDR);
+	outw(csr0_bits, dev->base_addr + LANCE_DATA);
+}
+
+
+static void lance_tx_timeout (struct net_device *dev)
+{
+	struct lance_private *lp = (struct lance_private *) dev->ml_priv;
+	int ioaddr = dev->base_addr;
+
+	outw (0, ioaddr + LANCE_ADDR);
+	printk ("%s: transmit timed out, status %4.4x, resetting.\n",
+		dev->name, inw (ioaddr + LANCE_DATA));
+	outw (0x0004, ioaddr + LANCE_DATA);
+	dev->stats.tx_errors++;
+#ifndef final_version
+	if (lance_debug > 3) {
+		int i;
+		printk (" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
+		  lp->dirty_tx, lp->cur_tx, netif_queue_stopped(dev) ? " (full)" : "",
+			lp->cur_rx);
+		for (i = 0; i < RX_RING_SIZE; i++)
+			printk ("%s %08x %04x %04x", i & 0x3 ? "" : "\n ",
+			 lp->rx_ring[i].base, -lp->rx_ring[i].buf_length,
+				lp->rx_ring[i].msg_length);
+		for (i = 0; i < TX_RING_SIZE; i++)
+			printk ("%s %08x %04x %04x", i & 0x3 ? "" : "\n ",
+			     lp->tx_ring[i].base, -lp->tx_ring[i].length,
+				lp->tx_ring[i].misc);
+		printk ("\n");
+	}
+#endif
+	lance_restart (dev, 0x0043, 1);
+
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	netif_wake_queue (dev);
+}
+
+
+static netdev_tx_t lance_start_xmit(struct sk_buff *skb,
+				    struct net_device *dev)
+{
+	struct lance_private *lp = dev->ml_priv;
+	int ioaddr = dev->base_addr;
+	int entry;
+	unsigned long flags;
+
+	spin_lock_irqsave(&lp->devlock, flags);
+
+	if (lance_debug > 3) {
+		outw(0x0000, ioaddr+LANCE_ADDR);
+		printk("%s: lance_start_xmit() called, csr0 %4.4x.\n", dev->name,
+			   inw(ioaddr+LANCE_DATA));
+		outw(0x0000, ioaddr+LANCE_DATA);
+	}
+
+	/* Fill in a Tx ring entry */
+
+	/* Mask to ring buffer boundary. */
+	entry = lp->cur_tx & TX_RING_MOD_MASK;
+
+	/* Caution: the write order is important here, set the base address
+	   with the "ownership" bits last. */
+
+	/* The old LANCE chips doesn't automatically pad buffers to min. size. */
+	if (chip_table[lp->chip_version].flags & LANCE_MUST_PAD) {
+		if (skb->len < ETH_ZLEN) {
+			if (skb_padto(skb, ETH_ZLEN))
+				goto out;
+			lp->tx_ring[entry].length = -ETH_ZLEN;
+		}
+		else
+			lp->tx_ring[entry].length = -skb->len;
+	} else
+		lp->tx_ring[entry].length = -skb->len;
+
+	lp->tx_ring[entry].misc = 0x0000;
+
+	dev->stats.tx_bytes += skb->len;
+
+	/* If any part of this buffer is >16M we must copy it to a low-memory
+	   buffer. */
+	if ((u32)isa_virt_to_bus(skb->data) + skb->len > 0x01000000) {
+		if (lance_debug > 5)
+			printk("%s: bouncing a high-memory packet (%#x).\n",
+				   dev->name, (u32)isa_virt_to_bus(skb->data));
+		skb_copy_from_linear_data(skb, &lp->tx_bounce_buffs[entry], skb->len);
+		lp->tx_ring[entry].base =
+			((u32)isa_virt_to_bus((lp->tx_bounce_buffs + entry)) & 0xffffff) | 0x83000000;
+		dev_kfree_skb(skb);
+	} else {
+		lp->tx_skbuff[entry] = skb;
+		lp->tx_ring[entry].base = ((u32)isa_virt_to_bus(skb->data) & 0xffffff) | 0x83000000;
+	}
+	lp->cur_tx++;
+
+	/* Trigger an immediate send poll. */
+	outw(0x0000, ioaddr+LANCE_ADDR);
+	outw(0x0048, ioaddr+LANCE_DATA);
+
+	if ((lp->cur_tx - lp->dirty_tx) >= TX_RING_SIZE)
+		netif_stop_queue(dev);
+
+out:
+	spin_unlock_irqrestore(&lp->devlock, flags);
+	return NETDEV_TX_OK;
+}
+
+/* The LANCE interrupt handler. */
+static irqreturn_t lance_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct lance_private *lp;
+	int csr0, ioaddr, boguscnt=10;
+	int must_restart;
+
+	ioaddr = dev->base_addr;
+	lp = dev->ml_priv;
+
+	spin_lock (&lp->devlock);
+
+	outw(0x00, dev->base_addr + LANCE_ADDR);
+	while ((csr0 = inw(dev->base_addr + LANCE_DATA)) & 0x8600 &&
+	       --boguscnt >= 0) {
+		/* Acknowledge all of the current interrupt sources ASAP. */
+		outw(csr0 & ~0x004f, dev->base_addr + LANCE_DATA);
+
+		must_restart = 0;
+
+		if (lance_debug > 5)
+			printk("%s: interrupt  csr0=%#2.2x new csr=%#2.2x.\n",
+				   dev->name, csr0, inw(dev->base_addr + LANCE_DATA));
+
+		if (csr0 & 0x0400)			/* Rx interrupt */
+			lance_rx(dev);
+
+		if (csr0 & 0x0200) {		/* Tx-done interrupt */
+			int dirty_tx = lp->dirty_tx;
+
+			while (dirty_tx < lp->cur_tx) {
+				int entry = dirty_tx & TX_RING_MOD_MASK;
+				int status = lp->tx_ring[entry].base;
+
+				if (status < 0)
+					break;			/* It still hasn't been Txed */
+
+				lp->tx_ring[entry].base = 0;
+
+				if (status & 0x40000000) {
+					/* There was an major error, log it. */
+					int err_status = lp->tx_ring[entry].misc;
+					dev->stats.tx_errors++;
+					if (err_status & 0x0400)
+						dev->stats.tx_aborted_errors++;
+					if (err_status & 0x0800)
+						dev->stats.tx_carrier_errors++;
+					if (err_status & 0x1000)
+						dev->stats.tx_window_errors++;
+					if (err_status & 0x4000) {
+						/* Ackk!  On FIFO errors the Tx unit is turned off! */
+						dev->stats.tx_fifo_errors++;
+						/* Remove this verbosity later! */
+						printk("%s: Tx FIFO error! Status %4.4x.\n",
+							   dev->name, csr0);
+						/* Restart the chip. */
+						must_restart = 1;
+					}
+				} else {
+					if (status & 0x18000000)
+						dev->stats.collisions++;
+					dev->stats.tx_packets++;
+				}
+
+				/* We must free the original skb if it's not a data-only copy
+				   in the bounce buffer. */
+				if (lp->tx_skbuff[entry]) {
+					dev_kfree_skb_irq(lp->tx_skbuff[entry]);
+					lp->tx_skbuff[entry] = NULL;
+				}
+				dirty_tx++;
+			}
+
+#ifndef final_version
+			if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) {
+				printk("out-of-sync dirty pointer, %d vs. %d, full=%s.\n",
+					   dirty_tx, lp->cur_tx,
+					   netif_queue_stopped(dev) ? "yes" : "no");
+				dirty_tx += TX_RING_SIZE;
+			}
+#endif
+
+			/* if the ring is no longer full, accept more packets */
+			if (netif_queue_stopped(dev) &&
+			    dirty_tx > lp->cur_tx - TX_RING_SIZE + 2)
+				netif_wake_queue (dev);
+
+			lp->dirty_tx = dirty_tx;
+		}
+
+		/* Log misc errors. */
+		if (csr0 & 0x4000)
+			dev->stats.tx_errors++; /* Tx babble. */
+		if (csr0 & 0x1000)
+			dev->stats.rx_errors++; /* Missed a Rx frame. */
+		if (csr0 & 0x0800) {
+			printk("%s: Bus master arbitration failure, status %4.4x.\n",
+				   dev->name, csr0);
+			/* Restart the chip. */
+			must_restart = 1;
+		}
+
+		if (must_restart) {
+			/* stop the chip to clear the error condition, then restart */
+			outw(0x0000, dev->base_addr + LANCE_ADDR);
+			outw(0x0004, dev->base_addr + LANCE_DATA);
+			lance_restart(dev, 0x0002, 0);
+		}
+	}
+
+	/* Clear any other interrupt, and set interrupt enable. */
+	outw(0x0000, dev->base_addr + LANCE_ADDR);
+	outw(0x7940, dev->base_addr + LANCE_DATA);
+
+	if (lance_debug > 4)
+		printk("%s: exiting interrupt, csr%d=%#4.4x.\n",
+			   dev->name, inw(ioaddr + LANCE_ADDR),
+			   inw(dev->base_addr + LANCE_DATA));
+
+	spin_unlock (&lp->devlock);
+	return IRQ_HANDLED;
+}
+
+static int
+lance_rx(struct net_device *dev)
+{
+	struct lance_private *lp = dev->ml_priv;
+	int entry = lp->cur_rx & RX_RING_MOD_MASK;
+	int i;
+
+	/* If we own the next entry, it's a new packet. Send it up. */
+	while (lp->rx_ring[entry].base >= 0) {
+		int status = lp->rx_ring[entry].base >> 24;
+
+		if (status != 0x03) {			/* There was an error. */
+			/* There is a tricky error noted by John Murphy,
+			   <murf@perftech.com> to Russ Nelson: Even with full-sized
+			   buffers it's possible for a jabber packet to use two
+			   buffers, with only the last correctly noting the error. */
+			if (status & 0x01)	/* Only count a general error at the */
+				dev->stats.rx_errors++; /* end of a packet.*/
+			if (status & 0x20)
+				dev->stats.rx_frame_errors++;
+			if (status & 0x10)
+				dev->stats.rx_over_errors++;
+			if (status & 0x08)
+				dev->stats.rx_crc_errors++;
+			if (status & 0x04)
+				dev->stats.rx_fifo_errors++;
+			lp->rx_ring[entry].base &= 0x03ffffff;
+		}
+		else
+		{
+			/* Malloc up new buffer, compatible with net3. */
+			short pkt_len = (lp->rx_ring[entry].msg_length & 0xfff)-4;
+			struct sk_buff *skb;
+
+			if(pkt_len<60)
+			{
+				printk("%s: Runt packet!\n",dev->name);
+				dev->stats.rx_errors++;
+			}
+			else
+			{
+				skb = dev_alloc_skb(pkt_len+2);
+				if (skb == NULL)
+				{
+					printk("%s: Memory squeeze, deferring packet.\n", dev->name);
+					for (i=0; i < RX_RING_SIZE; i++)
+						if (lp->rx_ring[(entry+i) & RX_RING_MOD_MASK].base < 0)
+							break;
+
+					if (i > RX_RING_SIZE -2)
+					{
+						dev->stats.rx_dropped++;
+						lp->rx_ring[entry].base |= 0x80000000;
+						lp->cur_rx++;
+					}
+					break;
+				}
+				skb_reserve(skb,2);	/* 16 byte align */
+				skb_put(skb,pkt_len);	/* Make room */
+				skb_copy_to_linear_data(skb,
+					(unsigned char *)isa_bus_to_virt((lp->rx_ring[entry].base & 0x00ffffff)),
+					pkt_len);
+				skb->protocol=eth_type_trans(skb,dev);
+				netif_rx(skb);
+				dev->stats.rx_packets++;
+				dev->stats.rx_bytes += pkt_len;
+			}
+		}
+		/* The docs say that the buffer length isn't touched, but Andrew Boyd
+		   of QNX reports that some revs of the 79C965 clear it. */
+		lp->rx_ring[entry].buf_length = -PKT_BUF_SZ;
+		lp->rx_ring[entry].base |= 0x80000000;
+		entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
+	}
+
+	/* We should check that at least two ring entries are free.	 If not,
+	   we should free one and mark stats->rx_dropped++. */
+
+	return 0;
+}
+
+static int
+lance_close(struct net_device *dev)
+{
+	int ioaddr = dev->base_addr;
+	struct lance_private *lp = dev->ml_priv;
+
+	netif_stop_queue (dev);
+
+	if (chip_table[lp->chip_version].flags & LANCE_HAS_MISSED_FRAME) {
+		outw(112, ioaddr+LANCE_ADDR);
+		dev->stats.rx_missed_errors = inw(ioaddr+LANCE_DATA);
+	}
+	outw(0, ioaddr+LANCE_ADDR);
+
+	if (lance_debug > 1)
+		printk("%s: Shutting down ethercard, status was %2.2x.\n",
+			   dev->name, inw(ioaddr+LANCE_DATA));
+
+	/* We stop the LANCE here -- it occasionally polls
+	   memory if we don't. */
+	outw(0x0004, ioaddr+LANCE_DATA);
+
+	if (dev->dma != 4)
+	{
+		unsigned long flags=claim_dma_lock();
+		disable_dma(dev->dma);
+		release_dma_lock(flags);
+	}
+	free_irq(dev->irq, dev);
+
+	lance_purge_ring(dev);
+
+	return 0;
+}
+
+static struct net_device_stats *lance_get_stats(struct net_device *dev)
+{
+	struct lance_private *lp = dev->ml_priv;
+
+	if (chip_table[lp->chip_version].flags & LANCE_HAS_MISSED_FRAME) {
+		short ioaddr = dev->base_addr;
+		short saved_addr;
+		unsigned long flags;
+
+		spin_lock_irqsave(&lp->devlock, flags);
+		saved_addr = inw(ioaddr+LANCE_ADDR);
+		outw(112, ioaddr+LANCE_ADDR);
+		dev->stats.rx_missed_errors = inw(ioaddr+LANCE_DATA);
+		outw(saved_addr, ioaddr+LANCE_ADDR);
+		spin_unlock_irqrestore(&lp->devlock, flags);
+	}
+
+	return &dev->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+	short ioaddr = dev->base_addr;
+
+	outw(0, ioaddr+LANCE_ADDR);
+	outw(0x0004, ioaddr+LANCE_DATA); /* Temporarily stop the lance.	 */
+
+	if (dev->flags&IFF_PROMISC) {
+		outw(15, ioaddr+LANCE_ADDR);
+		outw(0x8000, ioaddr+LANCE_DATA); /* Set promiscuous mode */
+	} else {
+		short multicast_table[4];
+		int i;
+		int num_addrs=netdev_mc_count(dev);
+		if(dev->flags&IFF_ALLMULTI)
+			num_addrs=1;
+		/* FIXIT: We don't use the multicast table, but rely on upper-layer filtering. */
+		memset(multicast_table, (num_addrs == 0) ? 0 : -1, sizeof(multicast_table));
+		for (i = 0; i < 4; i++) {
+			outw(8 + i, ioaddr+LANCE_ADDR);
+			outw(multicast_table[i], ioaddr+LANCE_DATA);
+		}
+		outw(15, ioaddr+LANCE_ADDR);
+		outw(0x0000, ioaddr+LANCE_DATA); /* Unset promiscuous mode */
+	}
+
+	lance_restart(dev, 0x0142, 0); /*  Resume normal operation */
+
+}
+
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/Makefile linux-libre-3.2-gnu/drivers/net/ethernet/amd/Makefile
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,20 @@
+#
+# Makefile for the AMD network device drivers.
+#
+
+obj-$(CONFIG_A2065) += a2065.o
+obj-$(CONFIG_AMD8111_ETH) += amd8111e.o
+obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o
+obj-$(CONFIG_ARIADNE) += ariadne.o
+obj-$(CONFIG_ATARILANCE) += atarilance.o
+obj-$(CONFIG_DECLANCE) += declance.o
+obj-$(CONFIG_DEPCA) += depca.o
+obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
+obj-$(CONFIG_LANCE) += lance.o
+obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
+obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
+obj-$(CONFIG_PCMCIA_NMCLAN) += nmclan_cs.o
+obj-$(CONFIG_NI65) += ni65.o
+obj-$(CONFIG_PCNET32) += pcnet32.o
+obj-$(CONFIG_SUN3LANCE) += sun3lance.o
+obj-$(CONFIG_SUNLANCE) += sunlance.o
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/mvme147.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/mvme147.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/mvme147.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/mvme147.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,205 @@
+/* mvme147.c  : the  Linux/mvme147/lance ethernet driver
+ *
+ * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
+ * Based on the Sun Lance driver and the NetBSD HP Lance driver
+ * Uses the generic 7990.c LANCE code.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/gfp.h>
+/* Used for the temporal inet entries and routing */
+#include <linux/socket.h>
+#include <linux/route.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/mvme147hw.h>
+
+/* We have 16834 bytes of RAM for the init block and buffers. This places
+ * an upper limit on the number of buffers we can use. NetBSD uses 8 Rx
+ * buffers and 2 Tx buffers.
+ */
+#define LANCE_LOG_TX_BUFFERS 1
+#define LANCE_LOG_RX_BUFFERS 3
+
+#include "7990.h"                                 /* use generic LANCE code */
+
+/* Our private data structure */
+struct m147lance_private {
+	struct lance_private lance;
+	unsigned long ram;
+};
+
+/* function prototypes... This is easy because all the grot is in the
+ * generic LANCE support. All we have to support is probing for boards,
+ * plus board-specific init, open and close actions.
+ * Oh, and we need to tell the generic code how to read and write LANCE registers...
+ */
+static int m147lance_open(struct net_device *dev);
+static int m147lance_close(struct net_device *dev);
+static void m147lance_writerap(struct lance_private *lp, unsigned short value);
+static void m147lance_writerdp(struct lance_private *lp, unsigned short value);
+static unsigned short m147lance_readrdp(struct lance_private *lp);
+
+typedef void (*writerap_t)(void *, unsigned short);
+typedef void (*writerdp_t)(void *, unsigned short);
+typedef unsigned short (*readrdp_t)(void *);
+
+static const struct net_device_ops lance_netdev_ops = {
+	.ndo_open		= m147lance_open,
+	.ndo_stop		= m147lance_close,
+	.ndo_start_xmit		= lance_start_xmit,
+	.ndo_set_rx_mode	= lance_set_multicast,
+	.ndo_tx_timeout		= lance_tx_timeout,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
+/* Initialise the one and only on-board 7990 */
+struct net_device * __init mvme147lance_probe(int unit)
+{
+	struct net_device *dev;
+	static int called;
+	static const char name[] = "MVME147 LANCE";
+	struct m147lance_private *lp;
+	u_long *addr;
+	u_long address;
+	int err;
+
+	if (!MACH_IS_MVME147 || called)
+		return ERR_PTR(-ENODEV);
+	called++;
+
+	dev = alloc_etherdev(sizeof(struct m147lance_private));
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	if (unit >= 0)
+		sprintf(dev->name, "eth%d", unit);
+
+	/* Fill the dev fields */
+	dev->base_addr = (unsigned long)MVME147_LANCE_BASE;
+	dev->netdev_ops = &lance_netdev_ops;
+	dev->dma = 0;
+
+	addr=(u_long *)ETHERNET_ADDRESS;
+	address = *addr;
+	dev->dev_addr[0]=0x08;
+	dev->dev_addr[1]=0x00;
+	dev->dev_addr[2]=0x3e;
+	address=address>>8;
+	dev->dev_addr[5]=address&0xff;
+	address=address>>8;
+	dev->dev_addr[4]=address&0xff;
+	address=address>>8;
+	dev->dev_addr[3]=address&0xff;
+
+	printk("%s: MVME147 at 0x%08lx, irq %d, "
+	       "Hardware Address %pM\n",
+	       dev->name, dev->base_addr, MVME147_LANCE_IRQ,
+	       dev->dev_addr);
+
+	lp = netdev_priv(dev);
+	lp->ram = __get_dma_pages(GFP_ATOMIC, 3);	/* 16K */
+	if (!lp->ram)
+	{
+		printk("%s: No memory for LANCE buffers\n", dev->name);
+		free_netdev(dev);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	lp->lance.name = (char*)name;                   /* discards const, shut up gcc */
+	lp->lance.base = dev->base_addr;
+	lp->lance.init_block = (struct lance_init_block *)(lp->ram); /* CPU addr */
+	lp->lance.lance_init_block = (struct lance_init_block *)(lp->ram);                 /* LANCE addr of same RAM */
+	lp->lance.busmaster_regval = LE_C3_BSWP;        /* we're bigendian */
+	lp->lance.irq = MVME147_LANCE_IRQ;
+	lp->lance.writerap = (writerap_t)m147lance_writerap;
+	lp->lance.writerdp = (writerdp_t)m147lance_writerdp;
+	lp->lance.readrdp = (readrdp_t)m147lance_readrdp;
+	lp->lance.lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;
+	lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
+	lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK;
+	lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK;
+
+	err = register_netdev(dev);
+	if (err) {
+		free_pages(lp->ram, 3);
+		free_netdev(dev);
+		return ERR_PTR(err);
+	}
+
+	return dev;
+}
+
+static void m147lance_writerap(struct lance_private *lp, unsigned short value)
+{
+	out_be16(lp->base + LANCE_RAP, value);
+}
+
+static void m147lance_writerdp(struct lance_private *lp, unsigned short value)
+{
+	out_be16(lp->base + LANCE_RDP, value);
+}
+
+static unsigned short m147lance_readrdp(struct lance_private *lp)
+{
+	return in_be16(lp->base + LANCE_RDP);
+}
+
+static int m147lance_open(struct net_device *dev)
+{
+	int status;
+
+	status = lance_open(dev);                 /* call generic lance open code */
+	if (status)
+		return status;
+	/* enable interrupts at board level. */
+	m147_pcc->lan_cntrl=0;       /* clear the interrupts (if any) */
+	m147_pcc->lan_cntrl=0x08 | 0x04;     /* Enable irq 4 */
+
+	return 0;
+}
+
+static int m147lance_close(struct net_device *dev)
+{
+	/* disable interrupts at boardlevel */
+	m147_pcc->lan_cntrl=0x0; /* disable interrupts */
+	lance_close(dev);
+	return 0;
+}
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+static struct net_device *dev_mvme147_lance;
+int __init init_module(void)
+{
+	dev_mvme147_lance = mvme147lance_probe(-1);
+	if (IS_ERR(dev_mvme147_lance))
+		return PTR_ERR(dev_mvme147_lance);
+	return 0;
+}
+
+void __exit cleanup_module(void)
+{
+	struct m147lance_private *lp = netdev_priv(dev_mvme147_lance);
+	unregister_netdev(dev_mvme147_lance);
+	free_pages(lp->ram, 3);
+	free_netdev(dev_mvme147_lance);
+}
+
+#endif /* MODULE */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/ni65.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/ni65.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/ni65.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/ni65.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1254 @@
+/*
+ * ni6510 (am7990 'lance' chip) driver for Linux-net-3
+ * BETAcode v0.71 (96/09/29) for 2.0.0 (or later)
+ * copyrights (c) 1994,1995,1996 by M.Hipp
+ *
+ * This driver can handle the old ni6510 board and the newer ni6510
+ * EtherBlaster. (probably it also works with every full NE2100
+ * compatible card)
+ *
+ * driver probes: io: 0x360,0x300,0x320,0x340 / dma: 3,5,6,7
+ *
+ * This is an extension to the Linux operating system, and is covered by the
+ * same GNU General Public License that covers the Linux-kernel.
+ *
+ * comments/bugs/suggestions can be sent to:
+ *   Michael Hipp
+ *   email: hippm@informatik.uni-tuebingen.de
+ *
+ * sources:
+ *   some things are from the 'ni6510-packet-driver for dos by Russ Nelson'
+ *   and from the original drivers by D.Becker
+ *
+ * known problems:
+ *   - on some PCI boards (including my own) the card/board/ISA-bridge has
+ *     problems with bus master DMA. This results in lotsa overruns.
+ *     It may help to '#define RCV_PARANOIA_CHECK' or try to #undef
+ *     the XMT and RCV_VIA_SKB option .. this reduces driver performance.
+ *     Or just play with your BIOS options to optimize ISA-DMA access.
+ *     Maybe you also wanna play with the LOW_PERFORAMCE and MID_PERFORMANCE
+ *     defines -> please report me your experience then
+ *   - Harald reported for ASUS SP3G mainboards, that you should use
+ *     the 'optimal settings' from the user's manual on page 3-12!
+ *
+ * credits:
+ *   thanx to Jason Sullivan for sending me a ni6510 card!
+ *   lot of debug runs with ASUS SP3G Boards (Intel Saturn) by Harald Koenig
+ *
+ * simple performance test: (486DX-33/Ni6510-EB receives from 486DX4-100/Ni6510-EB)
+ *    average: FTP -> 8384421 bytes received in 8.5 seconds
+ *           (no RCV_VIA_SKB,no XMT_VIA_SKB,PARANOIA_CHECK,4 XMIT BUFS, 8 RCV_BUFFS)
+ *    peak: FTP -> 8384421 bytes received in 7.5 seconds
+ *           (RCV_VIA_SKB,XMT_VIA_SKB,no PARANOIA_CHECK,1(!) XMIT BUF, 16 RCV BUFFS)
+ */
+
+/*
+ * 99.Jun.8: added support for /proc/net/dev byte count for xosview (HK)
+ * 96.Sept.29: virt_to_bus stuff added for new memory modell
+ * 96.April.29: Added Harald Koenig's Patches (MH)
+ * 96.April.13: enhanced error handling .. more tests (MH)
+ * 96.April.5/6: a lot of performance tests. Got it stable now (hopefully) (MH)
+ * 96.April.1: (no joke ;) .. added EtherBlaster and Module support (MH)
+ * 96.Feb.19: fixed a few bugs .. cleanups .. tested for 1.3.66 (MH)
+ *            hopefully no more 16MB limit
+ *
+ * 95.Nov.18: multicast tweaked (AC).
+ *
+ * 94.Aug.22: changes in xmit_intr (ack more than one xmitted-packet), ni65_send_packet (p->lock) (MH)
+ *
+ * 94.July.16: fixed bugs in recv_skb and skb-alloc stuff  (MH)
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/module.h>
+#include <linux/bitops.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include "ni65.h"
+
+/*
+ * the current setting allows an acceptable performance
+ * for 'RCV_PARANOIA_CHECK' read the 'known problems' part in
+ * the header of this file
+ * 'invert' the defines for max. performance. This may cause DMA problems
+ * on some boards (e.g on my ASUS SP3G)
+ */
+#undef XMT_VIA_SKB
+#undef RCV_VIA_SKB
+#define RCV_PARANOIA_CHECK
+
+#define MID_PERFORMANCE
+
+#if   defined( LOW_PERFORMANCE )
+ static int isa0=7,isa1=7,csr80=0x0c10;
+#elif defined( MID_PERFORMANCE )
+ static int isa0=5,isa1=5,csr80=0x2810;
+#else	/* high performance */
+ static int isa0=4,isa1=4,csr80=0x0017;
+#endif
+
+/*
+ * a few card/vendor specific defines
+ */
+#define NI65_ID0    0x00
+#define NI65_ID1    0x55
+#define NI65_EB_ID0 0x52
+#define NI65_EB_ID1 0x44
+#define NE2100_ID0  0x57
+#define NE2100_ID1  0x57
+
+#define PORT p->cmdr_addr
+
+/*
+ * buffer configuration
+ */
+#if 1
+#define RMDNUM 16
+#define RMDNUMMASK 0x80000000
+#else
+#define RMDNUM 8
+#define RMDNUMMASK 0x60000000 /* log2(RMDNUM)<<29 */
+#endif
+
+#if 0
+#define TMDNUM 1
+#define TMDNUMMASK 0x00000000
+#else
+#define TMDNUM 4
+#define TMDNUMMASK 0x40000000 /* log2(TMDNUM)<<29 */
+#endif
+
+/* slightly oversized */
+#define R_BUF_SIZE 1544
+#define T_BUF_SIZE 1544
+
+/*
+ * lance register defines
+ */
+#define L_DATAREG 0x00
+#define L_ADDRREG 0x02
+#define L_RESET   0x04
+#define L_CONFIG  0x05
+#define L_BUSIF   0x06
+
+/*
+ * to access the lance/am7990-regs, you have to write
+ * reg-number into L_ADDRREG, then you can access it using L_DATAREG
+ */
+#define CSR0  0x00
+#define CSR1  0x01
+#define CSR2  0x02
+#define CSR3  0x03
+
+#define INIT_RING_BEFORE_START	0x1
+#define FULL_RESET_ON_ERROR	0x2
+
+#if 0
+#define writereg(val,reg) {outw(reg,PORT+L_ADDRREG);inw(PORT+L_ADDRREG); \
+                           outw(val,PORT+L_DATAREG);inw(PORT+L_DATAREG);}
+#define readreg(reg) (outw(reg,PORT+L_ADDRREG),inw(PORT+L_ADDRREG),\
+                       inw(PORT+L_DATAREG))
+#if 0
+#define writedatareg(val) {outw(val,PORT+L_DATAREG);inw(PORT+L_DATAREG);}
+#else
+#define writedatareg(val) {  writereg(val,CSR0); }
+#endif
+#else
+#define writereg(val,reg) {outw(reg,PORT+L_ADDRREG);outw(val,PORT+L_DATAREG);}
+#define readreg(reg) (outw(reg,PORT+L_ADDRREG),inw(PORT+L_DATAREG))
+#define writedatareg(val) { writereg(val,CSR0); }
+#endif
+
+static unsigned char ni_vendor[] = { 0x02,0x07,0x01 };
+
+static struct card {
+	unsigned char id0,id1;
+	short id_offset;
+	short total_size;
+	short cmd_offset;
+	short addr_offset;
+	unsigned char *vendor_id;
+	char *cardname;
+	unsigned long config;
+} cards[] = {
+	{
+		.id0	     = NI65_ID0,
+		.id1	     = NI65_ID1,
+		.id_offset   = 0x0e,
+		.total_size  = 0x10,
+		.cmd_offset  = 0x0,
+		.addr_offset = 0x8,
+		.vendor_id   = ni_vendor,
+		.cardname    = "ni6510",
+		.config	     = 0x1,
+       	},
+	{
+		.id0	     = NI65_EB_ID0,
+		.id1	     = NI65_EB_ID1,
+		.id_offset   = 0x0e,
+		.total_size  = 0x18,
+		.cmd_offset  = 0x10,
+		.addr_offset = 0x0,
+		.vendor_id   = ni_vendor,
+		.cardname    = "ni6510 EtherBlaster",
+		.config	     = 0x2,
+       	},
+	{
+		.id0	     = NE2100_ID0,
+		.id1	     = NE2100_ID1,
+		.id_offset   = 0x0e,
+		.total_size  = 0x18,
+		.cmd_offset  = 0x10,
+		.addr_offset = 0x0,
+		.vendor_id   = NULL,
+		.cardname    = "generic NE2100",
+		.config	     = 0x0,
+	},
+};
+#define NUM_CARDS 3
+
+struct priv
+{
+	struct rmd rmdhead[RMDNUM];
+	struct tmd tmdhead[TMDNUM];
+	struct init_block ib;
+	int rmdnum;
+	int tmdnum,tmdlast;
+#ifdef RCV_VIA_SKB
+	struct sk_buff *recv_skb[RMDNUM];
+#else
+	void *recvbounce[RMDNUM];
+#endif
+#ifdef XMT_VIA_SKB
+	struct sk_buff *tmd_skb[TMDNUM];
+#endif
+	void *tmdbounce[TMDNUM];
+	int tmdbouncenum;
+	int lock,xmit_queued;
+
+	void *self;
+	int cmdr_addr;
+	int cardno;
+	int features;
+	spinlock_t ring_lock;
+};
+
+static int  ni65_probe1(struct net_device *dev,int);
+static irqreturn_t ni65_interrupt(int irq, void * dev_id);
+static void ni65_recv_intr(struct net_device *dev,int);
+static void ni65_xmit_intr(struct net_device *dev,int);
+static int  ni65_open(struct net_device *dev);
+static int  ni65_lance_reinit(struct net_device *dev);
+static void ni65_init_lance(struct priv *p,unsigned char*,int,int);
+static netdev_tx_t ni65_send_packet(struct sk_buff *skb,
+				    struct net_device *dev);
+static void  ni65_timeout(struct net_device *dev);
+static int  ni65_close(struct net_device *dev);
+static int  ni65_alloc_buffer(struct net_device *dev);
+static void ni65_free_buffer(struct priv *p);
+static void set_multicast_list(struct net_device *dev);
+
+static int irqtab[] __initdata = { 9,12,15,5 }; /* irq config-translate */
+static int dmatab[] __initdata = { 0,3,5,6,7 }; /* dma config-translate and autodetect */
+
+static int debuglevel = 1;
+
+/*
+ * set 'performance' registers .. we must STOP lance for that
+ */
+static void ni65_set_performance(struct priv *p)
+{
+	writereg(CSR0_STOP | CSR0_CLRALL,CSR0); /* STOP */
+
+	if( !(cards[p->cardno].config & 0x02) )
+		return;
+
+	outw(80,PORT+L_ADDRREG);
+	if(inw(PORT+L_ADDRREG) != 80)
+		return;
+
+	writereg( (csr80 & 0x3fff) ,80); /* FIFO watermarks */
+	outw(0,PORT+L_ADDRREG);
+	outw((short)isa0,PORT+L_BUSIF); /* write ISA 0: DMA_R : isa0 * 50ns */
+	outw(1,PORT+L_ADDRREG);
+	outw((short)isa1,PORT+L_BUSIF); /* write ISA 1: DMA_W : isa1 * 50ns	*/
+
+	outw(CSR0,PORT+L_ADDRREG);	/* switch back to CSR0 */
+}
+
+/*
+ * open interface (up)
+ */
+static int ni65_open(struct net_device *dev)
+{
+	struct priv *p = dev->ml_priv;
+	int irqval = request_irq(dev->irq, ni65_interrupt,0,
+                        cards[p->cardno].cardname,dev);
+	if (irqval) {
+		printk(KERN_ERR "%s: unable to get IRQ %d (irqval=%d).\n",
+		          dev->name,dev->irq, irqval);
+		return -EAGAIN;
+	}
+
+	if(ni65_lance_reinit(dev))
+	{
+		netif_start_queue(dev);
+		return 0;
+	}
+	else
+	{
+		free_irq(dev->irq,dev);
+		return -EAGAIN;
+	}
+}
+
+/*
+ * close interface (down)
+ */
+static int ni65_close(struct net_device *dev)
+{
+	struct priv *p = dev->ml_priv;
+
+	netif_stop_queue(dev);
+
+	outw(inw(PORT+L_RESET),PORT+L_RESET); /* that's the hard way */
+
+#ifdef XMT_VIA_SKB
+	{
+		int i;
+		for(i=0;i<TMDNUM;i++)
+		{
+			if(p->tmd_skb[i]) {
+				dev_kfree_skb(p->tmd_skb[i]);
+				p->tmd_skb[i] = NULL;
+			}
+		}
+	}
+#endif
+	free_irq(dev->irq,dev);
+	return 0;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+	struct priv *p = dev->ml_priv;
+	disable_dma(dev->dma);
+	free_dma(dev->dma);
+	release_region(dev->base_addr, cards[p->cardno].total_size);
+	ni65_free_buffer(p);
+}
+
+/* set: io,irq,dma or set it when calling insmod */
+static int irq;
+static int io;
+static int dma;
+
+/*
+ * Probe The Card (not the lance-chip)
+ */
+struct net_device * __init ni65_probe(int unit)
+{
+	struct net_device *dev = alloc_etherdev(0);
+	static const int ports[] = { 0x360, 0x300, 0x320, 0x340, 0 };
+	const int *port;
+	int err = 0;
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	if (unit >= 0) {
+		sprintf(dev->name, "eth%d", unit);
+		netdev_boot_setup_check(dev);
+		irq = dev->irq;
+		dma = dev->dma;
+	} else {
+		dev->base_addr = io;
+	}
+
+	if (dev->base_addr > 0x1ff) { /* Check a single specified location. */
+		err = ni65_probe1(dev, dev->base_addr);
+	} else if (dev->base_addr > 0) { /* Don't probe at all. */
+		err = -ENXIO;
+	} else {
+		for (port = ports; *port && ni65_probe1(dev, *port); port++)
+			;
+		if (!*port)
+			err = -ENODEV;
+	}
+	if (err)
+		goto out;
+
+	err = register_netdev(dev);
+	if (err)
+		goto out1;
+	return dev;
+out1:
+	cleanup_card(dev);
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+
+static const struct net_device_ops ni65_netdev_ops = {
+	.ndo_open		= ni65_open,
+	.ndo_stop		= ni65_close,
+	.ndo_start_xmit		= ni65_send_packet,
+	.ndo_tx_timeout		= ni65_timeout,
+	.ndo_set_rx_mode	= set_multicast_list,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+/*
+ * this is the real card probe ..
+ */
+static int __init ni65_probe1(struct net_device *dev,int ioaddr)
+{
+	int i,j;
+	struct priv *p;
+	unsigned long flags;
+
+	dev->irq = irq;
+	dev->dma = dma;
+
+	for(i=0;i<NUM_CARDS;i++) {
+		if(!request_region(ioaddr, cards[i].total_size, cards[i].cardname))
+			continue;
+		if(cards[i].id_offset >= 0) {
+			if(inb(ioaddr+cards[i].id_offset+0) != cards[i].id0 ||
+				 inb(ioaddr+cards[i].id_offset+1) != cards[i].id1) {
+				 release_region(ioaddr, cards[i].total_size);
+				 continue;
+			}
+		}
+		if(cards[i].vendor_id) {
+			for(j=0;j<3;j++)
+				if(inb(ioaddr+cards[i].addr_offset+j) != cards[i].vendor_id[j]) {
+					release_region(ioaddr, cards[i].total_size);
+					continue;
+			  }
+		}
+		break;
+	}
+	if(i == NUM_CARDS)
+		return -ENODEV;
+
+	for(j=0;j<6;j++)
+		dev->dev_addr[j] = inb(ioaddr+cards[i].addr_offset+j);
+
+	if( (j=ni65_alloc_buffer(dev)) < 0) {
+		release_region(ioaddr, cards[i].total_size);
+		return j;
+	}
+	p = dev->ml_priv;
+	p->cmdr_addr = ioaddr + cards[i].cmd_offset;
+	p->cardno = i;
+	spin_lock_init(&p->ring_lock);
+
+	printk(KERN_INFO "%s: %s found at %#3x, ", dev->name, cards[p->cardno].cardname , ioaddr);
+
+	outw(inw(PORT+L_RESET),PORT+L_RESET); /* first: reset the card */
+	if( (j=readreg(CSR0)) != 0x4) {
+		 printk("failed.\n");
+		 printk(KERN_ERR "%s: Can't RESET card: %04x\n", dev->name, j);
+		 ni65_free_buffer(p);
+		 release_region(ioaddr, cards[p->cardno].total_size);
+		 return -EAGAIN;
+	}
+
+	outw(88,PORT+L_ADDRREG);
+	if(inw(PORT+L_ADDRREG) == 88) {
+		unsigned long v;
+		v = inw(PORT+L_DATAREG);
+		v <<= 16;
+		outw(89,PORT+L_ADDRREG);
+		v |= inw(PORT+L_DATAREG);
+		printk("Version %#08lx, ",v);
+		p->features = INIT_RING_BEFORE_START;
+	}
+	else {
+		printk("ancient LANCE, ");
+		p->features = 0x0;
+	}
+
+	if(test_bit(0,&cards[i].config)) {
+		dev->irq = irqtab[(inw(ioaddr+L_CONFIG)>>2)&3];
+		dev->dma = dmatab[inw(ioaddr+L_CONFIG)&3];
+		printk("IRQ %d (from card), DMA %d (from card).\n",dev->irq,dev->dma);
+	}
+	else {
+		if(dev->dma == 0) {
+		/* 'stuck test' from lance.c */
+			unsigned long dma_channels =
+				((inb(DMA1_STAT_REG) >> 4) & 0x0f)
+				| (inb(DMA2_STAT_REG) & 0xf0);
+			for(i=1;i<5;i++) {
+				int dma = dmatab[i];
+				if(test_bit(dma,&dma_channels) || request_dma(dma,"ni6510"))
+					continue;
+
+				flags=claim_dma_lock();
+				disable_dma(dma);
+				set_dma_mode(dma,DMA_MODE_CASCADE);
+				enable_dma(dma);
+				release_dma_lock(flags);
+
+				ni65_init_lance(p,dev->dev_addr,0,0); /* trigger memory access */
+
+				flags=claim_dma_lock();
+				disable_dma(dma);
+				free_dma(dma);
+				release_dma_lock(flags);
+
+				if(readreg(CSR0) & CSR0_IDON)
+					break;
+			}
+			if(i == 5) {
+				printk("failed.\n");
+				printk(KERN_ERR "%s: Can't detect DMA channel!\n", dev->name);
+				ni65_free_buffer(p);
+				release_region(ioaddr, cards[p->cardno].total_size);
+				return -EAGAIN;
+			}
+			dev->dma = dmatab[i];
+			printk("DMA %d (autodetected), ",dev->dma);
+		}
+		else
+			printk("DMA %d (assigned), ",dev->dma);
+
+		if(dev->irq < 2)
+		{
+			unsigned long irq_mask;
+
+			ni65_init_lance(p,dev->dev_addr,0,0);
+			irq_mask = probe_irq_on();
+			writereg(CSR0_INIT|CSR0_INEA,CSR0); /* trigger interrupt */
+			msleep(20);
+			dev->irq = probe_irq_off(irq_mask);
+			if(!dev->irq)
+			{
+				printk("Failed to detect IRQ line!\n");
+				ni65_free_buffer(p);
+				release_region(ioaddr, cards[p->cardno].total_size);
+				return -EAGAIN;
+			}
+			printk("IRQ %d (autodetected).\n",dev->irq);
+		}
+		else
+			printk("IRQ %d (assigned).\n",dev->irq);
+	}
+
+	if(request_dma(dev->dma, cards[p->cardno].cardname ) != 0)
+	{
+		printk(KERN_ERR "%s: Can't request dma-channel %d\n",dev->name,(int) dev->dma);
+		ni65_free_buffer(p);
+		release_region(ioaddr, cards[p->cardno].total_size);
+		return -EAGAIN;
+	}
+
+	dev->base_addr = ioaddr;
+	dev->netdev_ops = &ni65_netdev_ops;
+	dev->watchdog_timeo	= HZ/2;
+
+	return 0; /* everything is OK */
+}
+
+/*
+ * set lance register and trigger init
+ */
+static void ni65_init_lance(struct priv *p,unsigned char *daddr,int filter,int mode)
+{
+	int i;
+	u32 pib;
+
+	writereg(CSR0_CLRALL|CSR0_STOP,CSR0);
+
+	for(i=0;i<6;i++)
+		p->ib.eaddr[i] = daddr[i];
+
+	for(i=0;i<8;i++)
+		p->ib.filter[i] = filter;
+	p->ib.mode = mode;
+
+	p->ib.trp = (u32) isa_virt_to_bus(p->tmdhead) | TMDNUMMASK;
+	p->ib.rrp = (u32) isa_virt_to_bus(p->rmdhead) | RMDNUMMASK;
+	writereg(0,CSR3);	/* busmaster/no word-swap */
+	pib = (u32) isa_virt_to_bus(&p->ib);
+	writereg(pib & 0xffff,CSR1);
+	writereg(pib >> 16,CSR2);
+
+	writereg(CSR0_INIT,CSR0); /* this changes L_ADDRREG to CSR0 */
+
+	for(i=0;i<32;i++)
+	{
+		mdelay(4);
+		if(inw(PORT+L_DATAREG) & (CSR0_IDON | CSR0_MERR) )
+			break; /* init ok ? */
+	}
+}
+
+/*
+ * allocate memory area and check the 16MB border
+ */
+static void *ni65_alloc_mem(struct net_device *dev,char *what,int size,int type)
+{
+	struct sk_buff *skb=NULL;
+	unsigned char *ptr;
+	void *ret;
+
+	if(type) {
+		ret = skb = alloc_skb(2+16+size,GFP_KERNEL|GFP_DMA);
+		if(!skb) {
+			printk(KERN_WARNING "%s: unable to allocate %s memory.\n",dev->name,what);
+			return NULL;
+		}
+		skb_reserve(skb,2+16);
+		skb_put(skb,R_BUF_SIZE);	 /* grab the whole space .. (not necessary) */
+		ptr = skb->data;
+	}
+	else {
+		ret = ptr = kmalloc(T_BUF_SIZE,GFP_KERNEL | GFP_DMA);
+		if(!ret) {
+			printk(KERN_WARNING "%s: unable to allocate %s memory.\n",dev->name,what);
+			return NULL;
+		}
+	}
+	if( (u32) virt_to_phys(ptr+size) > 0x1000000) {
+		printk(KERN_WARNING "%s: unable to allocate %s memory in lower 16MB!\n",dev->name,what);
+		if(type)
+			kfree_skb(skb);
+		else
+			kfree(ptr);
+		return NULL;
+	}
+	return ret;
+}
+
+/*
+ * allocate all memory structures .. send/recv buffers etc ...
+ */
+static int ni65_alloc_buffer(struct net_device *dev)
+{
+	unsigned char *ptr;
+	struct priv *p;
+	int i;
+
+	/*
+	 * we need 8-aligned memory ..
+	 */
+	ptr = ni65_alloc_mem(dev,"BUFFER",sizeof(struct priv)+8,0);
+	if(!ptr)
+		return -ENOMEM;
+
+	p = dev->ml_priv = (struct priv *) (((unsigned long) ptr + 7) & ~0x7);
+	memset((char *)p, 0, sizeof(struct priv));
+	p->self = ptr;
+
+	for(i=0;i<TMDNUM;i++)
+	{
+#ifdef XMT_VIA_SKB
+		p->tmd_skb[i] = NULL;
+#endif
+		p->tmdbounce[i] = ni65_alloc_mem(dev,"XMIT",T_BUF_SIZE,0);
+		if(!p->tmdbounce[i]) {
+			ni65_free_buffer(p);
+			return -ENOMEM;
+		}
+	}
+
+	for(i=0;i<RMDNUM;i++)
+	{
+#ifdef RCV_VIA_SKB
+		p->recv_skb[i] = ni65_alloc_mem(dev,"RECV",R_BUF_SIZE,1);
+		if(!p->recv_skb[i]) {
+			ni65_free_buffer(p);
+			return -ENOMEM;
+		}
+#else
+		p->recvbounce[i] = ni65_alloc_mem(dev,"RECV",R_BUF_SIZE,0);
+		if(!p->recvbounce[i]) {
+			ni65_free_buffer(p);
+			return -ENOMEM;
+		}
+#endif
+	}
+
+	return 0; /* everything is OK */
+}
+
+/*
+ * free buffers and private struct
+ */
+static void ni65_free_buffer(struct priv *p)
+{
+	int i;
+
+	if(!p)
+		return;
+
+	for(i=0;i<TMDNUM;i++) {
+		kfree(p->tmdbounce[i]);
+#ifdef XMT_VIA_SKB
+		if(p->tmd_skb[i])
+			dev_kfree_skb(p->tmd_skb[i]);
+#endif
+	}
+
+	for(i=0;i<RMDNUM;i++)
+	{
+#ifdef RCV_VIA_SKB
+		if(p->recv_skb[i])
+			dev_kfree_skb(p->recv_skb[i]);
+#else
+		kfree(p->recvbounce[i]);
+#endif
+	}
+	kfree(p->self);
+}
+
+
+/*
+ * stop and (re)start lance .. e.g after an error
+ */
+static void ni65_stop_start(struct net_device *dev,struct priv *p)
+{
+	int csr0 = CSR0_INEA;
+
+	writedatareg(CSR0_STOP);
+
+	if(debuglevel > 1)
+		printk(KERN_DEBUG "ni65_stop_start\n");
+
+	if(p->features & INIT_RING_BEFORE_START) {
+		int i;
+#ifdef XMT_VIA_SKB
+		struct sk_buff *skb_save[TMDNUM];
+#endif
+		unsigned long buffer[TMDNUM];
+		short blen[TMDNUM];
+
+		if(p->xmit_queued) {
+			while(1) {
+				if((p->tmdhead[p->tmdlast].u.s.status & XMIT_OWN))
+					break;
+				p->tmdlast = (p->tmdlast + 1) & (TMDNUM-1);
+				if(p->tmdlast == p->tmdnum)
+					break;
+			}
+		}
+
+		for(i=0;i<TMDNUM;i++) {
+			struct tmd *tmdp = p->tmdhead + i;
+#ifdef XMT_VIA_SKB
+			skb_save[i] = p->tmd_skb[i];
+#endif
+			buffer[i] = (u32) isa_bus_to_virt(tmdp->u.buffer);
+			blen[i] = tmdp->blen;
+			tmdp->u.s.status = 0x0;
+		}
+
+		for(i=0;i<RMDNUM;i++) {
+			struct rmd *rmdp = p->rmdhead + i;
+			rmdp->u.s.status = RCV_OWN;
+		}
+		p->tmdnum = p->xmit_queued = 0;
+		writedatareg(CSR0_STRT | csr0);
+
+		for(i=0;i<TMDNUM;i++) {
+			int num = (i + p->tmdlast) & (TMDNUM-1);
+			p->tmdhead[i].u.buffer = (u32) isa_virt_to_bus((char *)buffer[num]); /* status is part of buffer field */
+			p->tmdhead[i].blen = blen[num];
+			if(p->tmdhead[i].u.s.status & XMIT_OWN) {
+				 p->tmdnum = (p->tmdnum + 1) & (TMDNUM-1);
+				 p->xmit_queued = 1;
+	 writedatareg(CSR0_TDMD | CSR0_INEA | csr0);
+			}
+#ifdef XMT_VIA_SKB
+			p->tmd_skb[i] = skb_save[num];
+#endif
+		}
+		p->rmdnum = p->tmdlast = 0;
+		if(!p->lock)
+			if (p->tmdnum || !p->xmit_queued)
+				netif_wake_queue(dev);
+		dev->trans_start = jiffies; /* prevent tx timeout */
+	}
+	else
+		writedatareg(CSR0_STRT | csr0);
+}
+
+/*
+ * init lance (write init-values .. init-buffers) (open-helper)
+ */
+static int ni65_lance_reinit(struct net_device *dev)
+{
+	 int i;
+	 struct priv *p = dev->ml_priv;
+	 unsigned long flags;
+
+	 p->lock = 0;
+	 p->xmit_queued = 0;
+
+	 flags=claim_dma_lock();
+	 disable_dma(dev->dma); /* I've never worked with dma, but we do it like the packetdriver */
+	 set_dma_mode(dev->dma,DMA_MODE_CASCADE);
+	 enable_dma(dev->dma);
+	 release_dma_lock(flags);
+
+	 outw(inw(PORT+L_RESET),PORT+L_RESET); /* first: reset the card */
+	 if( (i=readreg(CSR0) ) != 0x4)
+	 {
+		 printk(KERN_ERR "%s: can't RESET %s card: %04x\n",dev->name,
+							cards[p->cardno].cardname,(int) i);
+		 flags=claim_dma_lock();
+		 disable_dma(dev->dma);
+		 release_dma_lock(flags);
+		 return 0;
+	 }
+
+	 p->rmdnum = p->tmdnum = p->tmdlast = p->tmdbouncenum = 0;
+	 for(i=0;i<TMDNUM;i++)
+	 {
+		 struct tmd *tmdp = p->tmdhead + i;
+#ifdef XMT_VIA_SKB
+		 if(p->tmd_skb[i]) {
+			 dev_kfree_skb(p->tmd_skb[i]);
+			 p->tmd_skb[i] = NULL;
+		 }
+#endif
+		 tmdp->u.buffer = 0x0;
+		 tmdp->u.s.status = XMIT_START | XMIT_END;
+		 tmdp->blen = tmdp->status2 = 0;
+	 }
+
+	 for(i=0;i<RMDNUM;i++)
+	 {
+		 struct rmd *rmdp = p->rmdhead + i;
+#ifdef RCV_VIA_SKB
+		 rmdp->u.buffer = (u32) isa_virt_to_bus(p->recv_skb[i]->data);
+#else
+		 rmdp->u.buffer = (u32) isa_virt_to_bus(p->recvbounce[i]);
+#endif
+		 rmdp->blen = -(R_BUF_SIZE-8);
+		 rmdp->mlen = 0;
+		 rmdp->u.s.status = RCV_OWN;
+	 }
+
+	 if(dev->flags & IFF_PROMISC)
+		 ni65_init_lance(p,dev->dev_addr,0x00,M_PROM);
+	 else if (netdev_mc_count(dev) || dev->flags & IFF_ALLMULTI)
+		 ni65_init_lance(p,dev->dev_addr,0xff,0x0);
+	 else
+		 ni65_init_lance(p,dev->dev_addr,0x00,0x00);
+
+	/*
+	 * ni65_set_lance_mem() sets L_ADDRREG to CSR0
+	 * NOW, WE WILL NEVER CHANGE THE L_ADDRREG, CSR0 IS ALWAYS SELECTED
+	 */
+
+	 if(inw(PORT+L_DATAREG) & CSR0_IDON)	{
+		 ni65_set_performance(p);
+					 /* init OK: start lance , enable interrupts */
+		 writedatareg(CSR0_CLRALL | CSR0_INEA | CSR0_STRT);
+		 return 1; /* ->OK */
+	 }
+	 printk(KERN_ERR "%s: can't init lance, status: %04x\n",dev->name,(int) inw(PORT+L_DATAREG));
+	 flags=claim_dma_lock();
+	 disable_dma(dev->dma);
+	 release_dma_lock(flags);
+	 return 0; /* ->Error */
+}
+
+/*
+ * interrupt handler
+ */
+static irqreturn_t ni65_interrupt(int irq, void * dev_id)
+{
+	int csr0 = 0;
+	struct net_device *dev = dev_id;
+	struct priv *p;
+	int bcnt = 32;
+
+	p = dev->ml_priv;
+
+	spin_lock(&p->ring_lock);
+
+	while(--bcnt) {
+		csr0 = inw(PORT+L_DATAREG);
+
+#if 0
+		writedatareg( (csr0 & CSR0_CLRALL) ); /* ack interrupts, disable int. */
+#else
+		writedatareg( (csr0 & CSR0_CLRALL) | CSR0_INEA ); /* ack interrupts, interrupts enabled */
+#endif
+
+		if(!(csr0 & (CSR0_ERR | CSR0_RINT | CSR0_TINT)))
+			break;
+
+		if(csr0 & CSR0_RINT) /* RECV-int? */
+			ni65_recv_intr(dev,csr0);
+		if(csr0 & CSR0_TINT) /* XMIT-int? */
+			ni65_xmit_intr(dev,csr0);
+
+		if(csr0 & CSR0_ERR)
+		{
+			if(debuglevel > 1)
+				printk(KERN_ERR "%s: general error: %04x.\n",dev->name,csr0);
+			if(csr0 & CSR0_BABL)
+				dev->stats.tx_errors++;
+			if(csr0 & CSR0_MISS) {
+				int i;
+				for(i=0;i<RMDNUM;i++)
+					printk("%02x ",p->rmdhead[i].u.s.status);
+				printk("\n");
+				dev->stats.rx_errors++;
+			}
+			if(csr0 & CSR0_MERR) {
+				if(debuglevel > 1)
+					printk(KERN_ERR "%s: Ooops .. memory error: %04x.\n",dev->name,csr0);
+				ni65_stop_start(dev,p);
+			}
+		}
+	}
+
+#ifdef RCV_PARANOIA_CHECK
+{
+ int j;
+ for(j=0;j<RMDNUM;j++)
+ {
+	int i, num2;
+	for(i=RMDNUM-1;i>0;i--) {
+		 num2 = (p->rmdnum + i) & (RMDNUM-1);
+		 if(!(p->rmdhead[num2].u.s.status & RCV_OWN))
+				break;
+	}
+
+	if(i) {
+		int k, num1;
+		for(k=0;k<RMDNUM;k++) {
+			num1 = (p->rmdnum + k) & (RMDNUM-1);
+			if(!(p->rmdhead[num1].u.s.status & RCV_OWN))
+				break;
+		}
+		if(!k)
+			break;
+
+		if(debuglevel > 0)
+		{
+			char buf[256],*buf1;
+			buf1 = buf;
+			for(k=0;k<RMDNUM;k++) {
+				sprintf(buf1,"%02x ",(p->rmdhead[k].u.s.status)); /* & RCV_OWN) ); */
+				buf1 += 3;
+			}
+			*buf1 = 0;
+			printk(KERN_ERR "%s: Ooops, receive ring corrupted %2d %2d | %s\n",dev->name,p->rmdnum,i,buf);
+		}
+
+		p->rmdnum = num1;
+		ni65_recv_intr(dev,csr0);
+		if((p->rmdhead[num2].u.s.status & RCV_OWN))
+			break;	/* ok, we are 'in sync' again */
+	}
+	else
+		break;
+ }
+}
+#endif
+
+	if( (csr0 & (CSR0_RXON | CSR0_TXON)) != (CSR0_RXON | CSR0_TXON) ) {
+		printk(KERN_DEBUG "%s: RX or TX was offline -> restart\n",dev->name);
+		ni65_stop_start(dev,p);
+	}
+	else
+		writedatareg(CSR0_INEA);
+
+	spin_unlock(&p->ring_lock);
+	return IRQ_HANDLED;
+}
+
+/*
+ * We have received an Xmit-Interrupt ..
+ * send a new packet if necessary
+ */
+static void ni65_xmit_intr(struct net_device *dev,int csr0)
+{
+	struct priv *p = dev->ml_priv;
+
+	while(p->xmit_queued)
+	{
+		struct tmd *tmdp = p->tmdhead + p->tmdlast;
+		int tmdstat = tmdp->u.s.status;
+
+		if(tmdstat & XMIT_OWN)
+			break;
+
+		if(tmdstat & XMIT_ERR)
+		{
+#if 0
+			if(tmdp->status2 & XMIT_TDRMASK && debuglevel > 3)
+				printk(KERN_ERR "%s: tdr-problems (e.g. no resistor)\n",dev->name);
+#endif
+		 /* checking some errors */
+			if(tmdp->status2 & XMIT_RTRY)
+				dev->stats.tx_aborted_errors++;
+			if(tmdp->status2 & XMIT_LCAR)
+				dev->stats.tx_carrier_errors++;
+			if(tmdp->status2 & (XMIT_BUFF | XMIT_UFLO )) {
+		/* this stops the xmitter */
+				dev->stats.tx_fifo_errors++;
+				if(debuglevel > 0)
+					printk(KERN_ERR "%s: Xmit FIFO/BUFF error\n",dev->name);
+				if(p->features & INIT_RING_BEFORE_START) {
+					tmdp->u.s.status = XMIT_OWN | XMIT_START | XMIT_END;	/* test: resend this frame */
+					ni65_stop_start(dev,p);
+					break;	/* no more Xmit processing .. */
+				}
+				else
+				 ni65_stop_start(dev,p);
+			}
+			if(debuglevel > 2)
+				printk(KERN_ERR "%s: xmit-error: %04x %02x-%04x\n",dev->name,csr0,(int) tmdstat,(int) tmdp->status2);
+			if(!(csr0 & CSR0_BABL)) /* don't count errors twice */
+				dev->stats.tx_errors++;
+			tmdp->status2 = 0;
+		}
+		else {
+			dev->stats.tx_bytes -= (short)(tmdp->blen);
+			dev->stats.tx_packets++;
+		}
+
+#ifdef XMT_VIA_SKB
+		if(p->tmd_skb[p->tmdlast]) {
+			 dev_kfree_skb_irq(p->tmd_skb[p->tmdlast]);
+			 p->tmd_skb[p->tmdlast] = NULL;
+		}
+#endif
+
+		p->tmdlast = (p->tmdlast + 1) & (TMDNUM-1);
+		if(p->tmdlast == p->tmdnum)
+			p->xmit_queued = 0;
+	}
+	netif_wake_queue(dev);
+}
+
+/*
+ * We have received a packet
+ */
+static void ni65_recv_intr(struct net_device *dev,int csr0)
+{
+	struct rmd *rmdp;
+	int rmdstat,len;
+	int cnt=0;
+	struct priv *p = dev->ml_priv;
+
+	rmdp = p->rmdhead + p->rmdnum;
+	while(!( (rmdstat = rmdp->u.s.status) & RCV_OWN))
+	{
+		cnt++;
+		if( (rmdstat & (RCV_START | RCV_END | RCV_ERR)) != (RCV_START | RCV_END) ) /* error or oversized? */
+		{
+			if(!(rmdstat & RCV_ERR)) {
+				if(rmdstat & RCV_START)
+				{
+					dev->stats.rx_length_errors++;
+					printk(KERN_ERR "%s: recv, packet too long: %d\n",dev->name,rmdp->mlen & 0x0fff);
+				}
+			}
+			else {
+				if(debuglevel > 2)
+					printk(KERN_ERR "%s: receive-error: %04x, lance-status: %04x/%04x\n",
+									dev->name,(int) rmdstat,csr0,(int) inw(PORT+L_DATAREG) );
+				if(rmdstat & RCV_FRAM)
+					dev->stats.rx_frame_errors++;
+				if(rmdstat & RCV_OFLO)
+					dev->stats.rx_over_errors++;
+				if(rmdstat & RCV_CRC)
+					dev->stats.rx_crc_errors++;
+				if(rmdstat & RCV_BUF_ERR)
+					dev->stats.rx_fifo_errors++;
+			}
+			if(!(csr0 & CSR0_MISS)) /* don't count errors twice */
+				dev->stats.rx_errors++;
+		}
+		else if( (len = (rmdp->mlen & 0x0fff) - 4) >= 60)
+		{
+#ifdef RCV_VIA_SKB
+			struct sk_buff *skb = alloc_skb(R_BUF_SIZE+2+16,GFP_ATOMIC);
+			if (skb)
+				skb_reserve(skb,16);
+#else
+			struct sk_buff *skb = dev_alloc_skb(len+2);
+#endif
+			if(skb)
+			{
+				skb_reserve(skb,2);
+#ifdef RCV_VIA_SKB
+				if( (unsigned long) (skb->data + R_BUF_SIZE) > 0x1000000) {
+					skb_put(skb,len);
+					skb_copy_to_linear_data(skb, (unsigned char *)(p->recv_skb[p->rmdnum]->data),len);
+				}
+				else {
+					struct sk_buff *skb1 = p->recv_skb[p->rmdnum];
+					skb_put(skb,R_BUF_SIZE);
+					p->recv_skb[p->rmdnum] = skb;
+					rmdp->u.buffer = (u32) isa_virt_to_bus(skb->data);
+					skb = skb1;
+					skb_trim(skb,len);
+				}
+#else
+				skb_put(skb,len);
+				skb_copy_to_linear_data(skb, (unsigned char *) p->recvbounce[p->rmdnum],len);
+#endif
+				dev->stats.rx_packets++;
+				dev->stats.rx_bytes += len;
+				skb->protocol=eth_type_trans(skb,dev);
+				netif_rx(skb);
+			}
+			else
+			{
+				printk(KERN_ERR "%s: can't alloc new sk_buff\n",dev->name);
+				dev->stats.rx_dropped++;
+			}
+		}
+		else {
+			printk(KERN_INFO "%s: received runt packet\n",dev->name);
+			dev->stats.rx_errors++;
+		}
+		rmdp->blen = -(R_BUF_SIZE-8);
+		rmdp->mlen = 0;
+		rmdp->u.s.status = RCV_OWN; /* change owner */
+		p->rmdnum = (p->rmdnum + 1) & (RMDNUM-1);
+		rmdp = p->rmdhead + p->rmdnum;
+	}
+}
+
+/*
+ * kick xmitter ..
+ */
+
+static void ni65_timeout(struct net_device *dev)
+{
+	int i;
+	struct priv *p = dev->ml_priv;
+
+	printk(KERN_ERR "%s: xmitter timed out, try to restart!\n",dev->name);
+	for(i=0;i<TMDNUM;i++)
+		printk("%02x ",p->tmdhead[i].u.s.status);
+	printk("\n");
+	ni65_lance_reinit(dev);
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	netif_wake_queue(dev);
+}
+
+/*
+ *	Send a packet
+ */
+
+static netdev_tx_t ni65_send_packet(struct sk_buff *skb,
+				    struct net_device *dev)
+{
+	struct priv *p = dev->ml_priv;
+
+	netif_stop_queue(dev);
+
+	if (test_and_set_bit(0, (void*)&p->lock)) {
+		printk(KERN_ERR "%s: Queue was locked.\n", dev->name);
+		return NETDEV_TX_BUSY;
+	}
+
+	{
+		short len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+		struct tmd *tmdp;
+		unsigned long flags;
+
+#ifdef XMT_VIA_SKB
+		if( (unsigned long) (skb->data + skb->len) > 0x1000000) {
+#endif
+
+			skb_copy_from_linear_data(skb, p->tmdbounce[p->tmdbouncenum],
+				      skb->len > T_BUF_SIZE ? T_BUF_SIZE :
+							      skb->len);
+			if (len > skb->len)
+				memset((char *)p->tmdbounce[p->tmdbouncenum]+skb->len, 0, len-skb->len);
+			dev_kfree_skb (skb);
+
+			spin_lock_irqsave(&p->ring_lock, flags);
+			tmdp = p->tmdhead + p->tmdnum;
+			tmdp->u.buffer = (u32) isa_virt_to_bus(p->tmdbounce[p->tmdbouncenum]);
+			p->tmdbouncenum = (p->tmdbouncenum + 1) & (TMDNUM - 1);
+
+#ifdef XMT_VIA_SKB
+		}
+		else {
+			spin_lock_irqsave(&p->ring_lock, flags);
+
+			tmdp = p->tmdhead + p->tmdnum;
+			tmdp->u.buffer = (u32) isa_virt_to_bus(skb->data);
+			p->tmd_skb[p->tmdnum] = skb;
+		}
+#endif
+		tmdp->blen = -len;
+
+		tmdp->u.s.status = XMIT_OWN | XMIT_START | XMIT_END;
+		writedatareg(CSR0_TDMD | CSR0_INEA); /* enable xmit & interrupt */
+
+		p->xmit_queued = 1;
+		p->tmdnum = (p->tmdnum + 1) & (TMDNUM-1);
+
+		if(p->tmdnum != p->tmdlast)
+			netif_wake_queue(dev);
+
+		p->lock = 0;
+
+		spin_unlock_irqrestore(&p->ring_lock, flags);
+	}
+
+	return NETDEV_TX_OK;
+}
+
+static void set_multicast_list(struct net_device *dev)
+{
+	if(!ni65_lance_reinit(dev))
+		printk(KERN_ERR "%s: Can't switch card into MC mode!\n",dev->name);
+	netif_wake_queue(dev);
+}
+
+#ifdef MODULE
+static struct net_device *dev_ni65;
+
+module_param(irq, int, 0);
+module_param(io, int, 0);
+module_param(dma, int, 0);
+MODULE_PARM_DESC(irq, "ni6510 IRQ number (ignored for some cards)");
+MODULE_PARM_DESC(io, "ni6510 I/O base address");
+MODULE_PARM_DESC(dma, "ni6510 ISA DMA channel (ignored for some cards)");
+
+int __init init_module(void)
+{
+ 	dev_ni65 = ni65_probe(-1);
+	return IS_ERR(dev_ni65) ? PTR_ERR(dev_ni65) : 0;
+}
+
+void __exit cleanup_module(void)
+{
+ 	unregister_netdev(dev_ni65);
+ 	cleanup_card(dev_ni65);
+ 	free_netdev(dev_ni65);
+}
+#endif /* MODULE */
+
+MODULE_LICENSE("GPL");
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/ni65.h linux-libre-3.2-gnu/drivers/net/ethernet/amd/ni65.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/ni65.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/ni65.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,121 @@
+/* am7990 (lance) definitions
+ *
+ * This is an extension to the Linux operating system, and is covered by
+ * same GNU General Public License that covers that work.
+ *
+ * Michael Hipp
+ * email: mhipp@student.uni-tuebingen.de
+ *
+ * sources: (mail me or ask archie if you need them)
+ *    crynwr-packet-driver
+ */
+
+/*
+ * 	Control and Status Register 0 (CSR0) bit definitions
+ * (R=Readable) (W=Writeable) (S=Set on write) (C-Clear on write)
+ *
+ */
+
+#define CSR0_ERR	0x8000	/* Error summary (R) */
+#define CSR0_BABL	0x4000	/* Babble transmitter timeout error (RC) */
+#define CSR0_CERR	0x2000	/* Collision Error (RC) */
+#define CSR0_MISS	0x1000	/* Missed packet (RC) */
+#define CSR0_MERR	0x0800	/* Memory Error (RC) */
+#define CSR0_RINT	0x0400	/* Receiver Interrupt (RC) */
+#define CSR0_TINT       0x0200	/* Transmit Interrupt (RC) */
+#define CSR0_IDON	0x0100	/* Initialization Done (RC) */
+#define CSR0_INTR	0x0080	/* Interrupt Flag (R) */
+#define CSR0_INEA	0x0040	/* Interrupt Enable (RW) */
+#define CSR0_RXON	0x0020	/* Receiver on (R) */
+#define CSR0_TXON	0x0010	/* Transmitter on (R) */
+#define CSR0_TDMD	0x0008	/* Transmit Demand (RS) */
+#define CSR0_STOP	0x0004	/* Stop (RS) */
+#define CSR0_STRT	0x0002	/* Start (RS) */
+#define CSR0_INIT	0x0001	/* Initialize (RS) */
+
+#define CSR0_CLRALL    0x7f00	/* mask for all clearable bits */
+/*
+ *	Initialization Block  Mode operation Bit Definitions.
+ */
+
+#define M_PROM		0x8000	/* Promiscuous Mode */
+#define M_INTL		0x0040	/* Internal Loopback */
+#define M_DRTY		0x0020	/* Disable Retry */
+#define M_COLL		0x0010	/* Force Collision */
+#define M_DTCR		0x0008	/* Disable Transmit CRC) */
+#define M_LOOP		0x0004	/* Loopback */
+#define M_DTX		0x0002	/* Disable the Transmitter */
+#define M_DRX		0x0001	/* Disable the Receiver */
+
+
+/*
+ * 	Receive message descriptor bit definitions.
+ */
+
+#define RCV_OWN		0x80	/* owner bit 0 = host, 1 = lance */
+#define RCV_ERR		0x40	/* Error Summary */
+#define RCV_FRAM	0x20	/* Framing Error */
+#define RCV_OFLO	0x10	/* Overflow Error */
+#define RCV_CRC		0x08	/* CRC Error */
+#define RCV_BUF_ERR	0x04	/* Buffer Error */
+#define RCV_START	0x02	/* Start of Packet */
+#define RCV_END		0x01	/* End of Packet */
+
+
+/*
+ *	Transmit  message descriptor bit definitions.
+ */
+
+#define XMIT_OWN	0x80	/* owner bit 0 = host, 1 = lance */
+#define XMIT_ERR	0x40	/* Error Summary */
+#define XMIT_RETRY	0x10	/* more the 1 retry needed to Xmit */
+#define XMIT_1_RETRY	0x08	/* one retry needed to Xmit */
+#define XMIT_DEF	0x04	/* Deferred */
+#define XMIT_START	0x02	/* Start of Packet */
+#define XMIT_END	0x01	/* End of Packet */
+
+/*
+ * transmit status (2) (valid if XMIT_ERR == 1)
+ */
+
+#define XMIT_TDRMASK    0x03ff	/* time-domain-reflectometer-value */
+#define XMIT_RTRY 	0x0400	/* Failed after 16 retransmissions  */
+#define XMIT_LCAR 	0x0800	/* Loss of Carrier */
+#define XMIT_LCOL 	0x1000	/* Late collision */
+#define XMIT_RESERV 	0x2000	/* Reserved */
+#define XMIT_UFLO 	0x4000	/* Underflow (late memory) */
+#define XMIT_BUFF 	0x8000	/* Buffering error (no ENP) */
+
+struct init_block {
+	unsigned short mode;
+	unsigned char eaddr[6];
+	unsigned char filter[8];
+	/* bit 29-31: number of rmd's (power of 2) */
+	u32 rrp;		/* receive ring pointer (align 8) */
+	/* bit 29-31: number of tmd's (power of 2) */
+	u32 trp;		/* transmit ring pointer (align 8) */
+};
+
+struct rmd {			/* Receive Message Descriptor */
+	union {
+		volatile u32 buffer;
+		struct {
+			volatile unsigned char dummy[3];
+			volatile unsigned char status;
+		} s;
+	} u;
+	volatile short blen;
+	volatile unsigned short mlen;
+};
+
+struct tmd {
+	union {
+		volatile u32 buffer;
+		struct {
+			volatile unsigned char dummy[3];
+			volatile unsigned char status;
+		} s;
+	} u;
+	volatile unsigned short blen;
+	volatile unsigned short status2;
+};
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/nmclan_cs.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/nmclan_cs.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/nmclan_cs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/nmclan_cs.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1525 @@
+/* ----------------------------------------------------------------------------
+Linux PCMCIA ethernet adapter driver for the New Media Ethernet LAN.
+  nmclan_cs.c,v 0.16 1995/07/01 06:42:17 rpao Exp rpao
+
+  The Ethernet LAN uses the Advanced Micro Devices (AMD) Am79C940 Media
+  Access Controller for Ethernet (MACE).  It is essentially the Am2150
+  PCMCIA Ethernet card contained in the Am2150 Demo Kit.
+
+Written by Roger C. Pao <rpao@paonet.org>
+  Copyright 1995 Roger C. Pao
+  Linux 2.5 cleanups Copyright Red Hat 2003
+
+  This software may be used and distributed according to the terms of
+  the GNU General Public License.
+
+Ported to Linux 1.3.* network driver environment by
+  Matti Aarnio <mea@utu.fi>
+
+References
+
+  Am2150 Technical Reference Manual, Revision 1.0, August 17, 1993
+  Am79C940 (MACE) Data Sheet, 1994
+  Am79C90 (C-LANCE) Data Sheet, 1994
+  Linux PCMCIA Programmer's Guide v1.17
+  /usr/src/linux/net/inet/dev.c, Linux kernel 1.2.8
+
+  Eric Mears, New Media Corporation
+  Tom Pollard, New Media Corporation
+  Dean Siasoyco, New Media Corporation
+  Ken Lesniak, Silicon Graphics, Inc. <lesniak@boston.sgi.com>
+  Donald Becker <becker@scyld.com>
+  David Hinds <dahinds@users.sourceforge.net>
+
+  The Linux client driver is based on the 3c589_cs.c client driver by
+  David Hinds.
+
+  The Linux network driver outline is based on the 3c589_cs.c driver,
+  the 8390.c driver, and the example skeleton.c kernel code, which are
+  by Donald Becker.
+
+  The Am2150 network driver hardware interface code is based on the
+  OS/9000 driver for the New Media Ethernet LAN by Eric Mears.
+
+  Special thanks for testing and help in debugging this driver goes
+  to Ken Lesniak.
+
+-------------------------------------------------------------------------------
+Driver Notes and Issues
+-------------------------------------------------------------------------------
+
+1. Developed on a Dell 320SLi
+   PCMCIA Card Services 2.6.2
+   Linux dell 1.2.10 #1 Thu Jun 29 20:23:41 PDT 1995 i386
+
+2. rc.pcmcia may require loading pcmcia_core with io_speed=300:
+   'insmod pcmcia_core.o io_speed=300'.
+   This will avoid problems with fast systems which causes rx_framecnt
+   to return random values.
+
+3. If hot extraction does not work for you, use 'ifconfig eth0 down'
+   before extraction.
+
+4. There is a bad slow-down problem in this driver.
+
+5. Future: Multicast processing.  In the meantime, do _not_ compile your
+   kernel with multicast ip enabled.
+
+-------------------------------------------------------------------------------
+History
+-------------------------------------------------------------------------------
+Log: nmclan_cs.c,v
+ * 2.5.75-ac1 2003/07/11 Alan Cox <alan@lxorguk.ukuu.org.uk>
+ * Fixed hang on card eject as we probe it
+ * Cleaned up to use new style locking.
+ *
+ * Revision 0.16  1995/07/01  06:42:17  rpao
+ * Bug fix: nmclan_reset() called CardServices incorrectly.
+ *
+ * Revision 0.15  1995/05/24  08:09:47  rpao
+ * Re-implement MULTI_TX dev->tbusy handling.
+ *
+ * Revision 0.14  1995/05/23  03:19:30  rpao
+ * Added, in nmclan_config(), "tuple.Attributes = 0;".
+ * Modified MACE ID check to ignore chip revision level.
+ * Avoid tx_free_frames race condition between _start_xmit and _interrupt.
+ *
+ * Revision 0.13  1995/05/18  05:56:34  rpao
+ * Statistics changes.
+ * Bug fix: nmclan_reset did not enable TX and RX: call restore_multicast_list.
+ * Bug fix: mace_interrupt checks ~MACE_IMR_DEFAULT.  Fixes driver lockup.
+ *
+ * Revision 0.12  1995/05/14  00:12:23  rpao
+ * Statistics overhaul.
+ *
+
+95/05/13 rpao	V0.10a
+		Bug fix: MACE statistics counters used wrong I/O ports.
+		Bug fix: mace_interrupt() needed to allow statistics to be
+		processed without RX or TX interrupts pending.
+95/05/11 rpao	V0.10
+		Multiple transmit request processing.
+		Modified statistics to use MACE counters where possible.
+95/05/10 rpao	V0.09 Bug fix: Must use IO_DATA_PATH_WIDTH_AUTO.
+		*Released
+95/05/10 rpao	V0.08
+		Bug fix: Make all non-exported functions private by using
+		static keyword.
+		Bug fix: Test IntrCnt _before_ reading MACE_IR.
+95/05/10 rpao	V0.07 Statistics.
+95/05/09 rpao	V0.06 Fix rx_framecnt problem by addition of PCIC wait states.
+
+---------------------------------------------------------------------------- */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define DRV_NAME	"nmclan_cs"
+#define DRV_VERSION	"0.16"
+
+
+/* ----------------------------------------------------------------------------
+Conditional Compilation Options
+---------------------------------------------------------------------------- */
+
+#define MULTI_TX			0
+#define RESET_ON_TIMEOUT		1
+#define TX_INTERRUPTABLE		1
+#define RESET_XILINX			0
+
+/* ----------------------------------------------------------------------------
+Include Files
+---------------------------------------------------------------------------- */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+#include <linux/bitops.h>
+
+#include <pcmcia/cisreg.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+/* ----------------------------------------------------------------------------
+Defines
+---------------------------------------------------------------------------- */
+
+#define ETHER_ADDR_LEN			ETH_ALEN
+					/* 6 bytes in an Ethernet Address */
+#define MACE_LADRF_LEN			8
+					/* 8 bytes in Logical Address Filter */
+
+/* Loop Control Defines */
+#define MACE_MAX_IR_ITERATIONS		10
+#define MACE_MAX_RX_ITERATIONS		12
+	/*
+	TBD: Dean brought this up, and I assumed the hardware would
+	handle it:
+
+	If MACE_MAX_RX_ITERATIONS is > 1, rx_framecnt may still be
+	non-zero when the isr exits.  We may not get another interrupt
+	to process the remaining packets for some time.
+	*/
+
+/*
+The Am2150 has a Xilinx XC3042 field programmable gate array (FPGA)
+which manages the interface between the MACE and the PCMCIA bus.  It
+also includes buffer management for the 32K x 8 SRAM to control up to
+four transmit and 12 receive frames at a time.
+*/
+#define AM2150_MAX_TX_FRAMES		4
+#define AM2150_MAX_RX_FRAMES		12
+
+/* Am2150 Ethernet Card I/O Mapping */
+#define AM2150_RCV			0x00
+#define AM2150_XMT			0x04
+#define AM2150_XMT_SKIP			0x09
+#define AM2150_RCV_NEXT			0x0A
+#define AM2150_RCV_FRAME_COUNT		0x0B
+#define AM2150_MACE_BANK		0x0C
+#define AM2150_MACE_BASE		0x10
+
+/* MACE Registers */
+#define MACE_RCVFIFO			0
+#define MACE_XMTFIFO			1
+#define MACE_XMTFC			2
+#define MACE_XMTFS			3
+#define MACE_XMTRC			4
+#define MACE_RCVFC			5
+#define MACE_RCVFS			6
+#define MACE_FIFOFC			7
+#define MACE_IR				8
+#define MACE_IMR			9
+#define MACE_PR				10
+#define MACE_BIUCC			11
+#define MACE_FIFOCC			12
+#define MACE_MACCC			13
+#define MACE_PLSCC			14
+#define MACE_PHYCC			15
+#define MACE_CHIPIDL			16
+#define MACE_CHIPIDH			17
+#define MACE_IAC			18
+/* Reserved */
+#define MACE_LADRF			20
+#define MACE_PADR			21
+/* Reserved */
+/* Reserved */
+#define MACE_MPC			24
+/* Reserved */
+#define MACE_RNTPC			26
+#define MACE_RCVCC			27
+/* Reserved */
+#define MACE_UTR			29
+#define MACE_RTR1			30
+#define MACE_RTR2			31
+
+/* MACE Bit Masks */
+#define MACE_XMTRC_EXDEF		0x80
+#define MACE_XMTRC_XMTRC		0x0F
+
+#define MACE_XMTFS_XMTSV		0x80
+#define MACE_XMTFS_UFLO			0x40
+#define MACE_XMTFS_LCOL			0x20
+#define MACE_XMTFS_MORE			0x10
+#define MACE_XMTFS_ONE			0x08
+#define MACE_XMTFS_DEFER		0x04
+#define MACE_XMTFS_LCAR			0x02
+#define MACE_XMTFS_RTRY			0x01
+
+#define MACE_RCVFS_RCVSTS		0xF000
+#define MACE_RCVFS_OFLO			0x8000
+#define MACE_RCVFS_CLSN			0x4000
+#define MACE_RCVFS_FRAM			0x2000
+#define MACE_RCVFS_FCS			0x1000
+
+#define MACE_FIFOFC_RCVFC		0xF0
+#define MACE_FIFOFC_XMTFC		0x0F
+
+#define MACE_IR_JAB			0x80
+#define MACE_IR_BABL			0x40
+#define MACE_IR_CERR			0x20
+#define MACE_IR_RCVCCO			0x10
+#define MACE_IR_RNTPCO			0x08
+#define MACE_IR_MPCO			0x04
+#define MACE_IR_RCVINT			0x02
+#define MACE_IR_XMTINT			0x01
+
+#define MACE_MACCC_PROM			0x80
+#define MACE_MACCC_DXMT2PD		0x40
+#define MACE_MACCC_EMBA			0x20
+#define MACE_MACCC_RESERVED		0x10
+#define MACE_MACCC_DRCVPA		0x08
+#define MACE_MACCC_DRCVBC		0x04
+#define MACE_MACCC_ENXMT		0x02
+#define MACE_MACCC_ENRCV		0x01
+
+#define MACE_PHYCC_LNKFL		0x80
+#define MACE_PHYCC_DLNKTST		0x40
+#define MACE_PHYCC_REVPOL		0x20
+#define MACE_PHYCC_DAPC			0x10
+#define MACE_PHYCC_LRT			0x08
+#define MACE_PHYCC_ASEL			0x04
+#define MACE_PHYCC_RWAKE		0x02
+#define MACE_PHYCC_AWAKE		0x01
+
+#define MACE_IAC_ADDRCHG		0x80
+#define MACE_IAC_PHYADDR		0x04
+#define MACE_IAC_LOGADDR		0x02
+
+#define MACE_UTR_RTRE			0x80
+#define MACE_UTR_RTRD			0x40
+#define MACE_UTR_RPA			0x20
+#define MACE_UTR_FCOLL			0x10
+#define MACE_UTR_RCVFCSE		0x08
+#define MACE_UTR_LOOP_INCL_MENDEC	0x06
+#define MACE_UTR_LOOP_NO_MENDEC		0x04
+#define MACE_UTR_LOOP_EXTERNAL		0x02
+#define MACE_UTR_LOOP_NONE		0x00
+#define MACE_UTR_RESERVED		0x01
+
+/* Switch MACE register bank (only 0 and 1 are valid) */
+#define MACEBANK(win_num) outb((win_num), ioaddr + AM2150_MACE_BANK)
+
+#define MACE_IMR_DEFAULT \
+  (0xFF - \
+    ( \
+      MACE_IR_CERR | \
+      MACE_IR_RCVCCO | \
+      MACE_IR_RNTPCO | \
+      MACE_IR_MPCO | \
+      MACE_IR_RCVINT | \
+      MACE_IR_XMTINT \
+    ) \
+  )
+#undef MACE_IMR_DEFAULT
+#define MACE_IMR_DEFAULT 0x00 /* New statistics handling: grab everything */
+
+#define TX_TIMEOUT		((400*HZ)/1000)
+
+/* ----------------------------------------------------------------------------
+Type Definitions
+---------------------------------------------------------------------------- */
+
+typedef struct _mace_statistics {
+    /* MACE_XMTFS */
+    int xmtsv;
+    int uflo;
+    int lcol;
+    int more;
+    int one;
+    int defer;
+    int lcar;
+    int rtry;
+
+    /* MACE_XMTRC */
+    int exdef;
+    int xmtrc;
+
+    /* RFS1--Receive Status (RCVSTS) */
+    int oflo;
+    int clsn;
+    int fram;
+    int fcs;
+
+    /* RFS2--Runt Packet Count (RNTPC) */
+    int rfs_rntpc;
+
+    /* RFS3--Receive Collision Count (RCVCC) */
+    int rfs_rcvcc;
+
+    /* MACE_IR */
+    int jab;
+    int babl;
+    int cerr;
+    int rcvcco;
+    int rntpco;
+    int mpco;
+
+    /* MACE_MPC */
+    int mpc;
+
+    /* MACE_RNTPC */
+    int rntpc;
+
+    /* MACE_RCVCC */
+    int rcvcc;
+} mace_statistics;
+
+typedef struct _mace_private {
+	struct pcmcia_device	*p_dev;
+    struct net_device_stats linux_stats; /* Linux statistics counters */
+    mace_statistics mace_stats; /* MACE chip statistics counters */
+
+    /* restore_multicast_list() state variables */
+    int multicast_ladrf[MACE_LADRF_LEN]; /* Logical address filter */
+    int multicast_num_addrs;
+
+    char tx_free_frames; /* Number of free transmit frame buffers */
+    char tx_irq_disabled; /* MACE TX interrupt disabled */
+    
+    spinlock_t bank_lock; /* Must be held if you step off bank 0 */
+} mace_private;
+
+/* ----------------------------------------------------------------------------
+Private Global Variables
+---------------------------------------------------------------------------- */
+
+static const char *if_names[]={
+    "Auto", "10baseT", "BNC",
+};
+
+/* ----------------------------------------------------------------------------
+Parameters
+	These are the parameters that can be set during loading with
+	'insmod'.
+---------------------------------------------------------------------------- */
+
+MODULE_DESCRIPTION("New Media PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");
+
+#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
+
+/* 0=auto, 1=10baseT, 2 = 10base2, default=auto */
+INT_MODULE_PARM(if_port, 0);
+
+
+/* ----------------------------------------------------------------------------
+Function Prototypes
+---------------------------------------------------------------------------- */
+
+static int nmclan_config(struct pcmcia_device *link);
+static void nmclan_release(struct pcmcia_device *link);
+
+static void nmclan_reset(struct net_device *dev);
+static int mace_config(struct net_device *dev, struct ifmap *map);
+static int mace_open(struct net_device *dev);
+static int mace_close(struct net_device *dev);
+static netdev_tx_t mace_start_xmit(struct sk_buff *skb,
+					 struct net_device *dev);
+static void mace_tx_timeout(struct net_device *dev);
+static irqreturn_t mace_interrupt(int irq, void *dev_id);
+static struct net_device_stats *mace_get_stats(struct net_device *dev);
+static int mace_rx(struct net_device *dev, unsigned char RxCnt);
+static void restore_multicast_list(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+static const struct ethtool_ops netdev_ethtool_ops;
+
+
+static void nmclan_detach(struct pcmcia_device *p_dev);
+
+static const struct net_device_ops mace_netdev_ops = {
+	.ndo_open		= mace_open,
+	.ndo_stop		= mace_close,
+	.ndo_start_xmit		= mace_start_xmit,
+	.ndo_tx_timeout		= mace_tx_timeout,
+	.ndo_set_config		= mace_config,
+	.ndo_get_stats		= mace_get_stats,
+	.ndo_set_rx_mode	= set_multicast_list,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+static int nmclan_probe(struct pcmcia_device *link)
+{
+    mace_private *lp;
+    struct net_device *dev;
+
+    dev_dbg(&link->dev, "nmclan_attach()\n");
+
+    /* Create new ethernet device */
+    dev = alloc_etherdev(sizeof(mace_private));
+    if (!dev)
+	    return -ENOMEM;
+    lp = netdev_priv(dev);
+    lp->p_dev = link;
+    link->priv = dev;
+    
+    spin_lock_init(&lp->bank_lock);
+    link->resource[0]->end = 32;
+    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+    link->config_flags |= CONF_ENABLE_IRQ;
+    link->config_index = 1;
+    link->config_regs = PRESENT_OPTION;
+
+    lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
+
+    dev->netdev_ops = &mace_netdev_ops;
+    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+    dev->watchdog_timeo = TX_TIMEOUT;
+
+    return nmclan_config(link);
+} /* nmclan_attach */
+
+static void nmclan_detach(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+
+    dev_dbg(&link->dev, "nmclan_detach\n");
+
+    unregister_netdev(dev);
+
+    nmclan_release(link);
+
+    free_netdev(dev);
+} /* nmclan_detach */
+
+/* ----------------------------------------------------------------------------
+mace_read
+	Reads a MACE register.  This is bank independent; however, the
+	caller must ensure that this call is not interruptable.  We are
+	assuming that during normal operation, the MACE is always in
+	bank 0.
+---------------------------------------------------------------------------- */
+static int mace_read(mace_private *lp, unsigned int ioaddr, int reg)
+{
+  int data = 0xFF;
+  unsigned long flags;
+
+  switch (reg >> 4) {
+    case 0: /* register 0-15 */
+      data = inb(ioaddr + AM2150_MACE_BASE + reg);
+      break;
+    case 1: /* register 16-31 */
+      spin_lock_irqsave(&lp->bank_lock, flags);
+      MACEBANK(1);
+      data = inb(ioaddr + AM2150_MACE_BASE + (reg & 0x0F));
+      MACEBANK(0);
+      spin_unlock_irqrestore(&lp->bank_lock, flags);
+      break;
+  }
+  return data & 0xFF;
+} /* mace_read */
+
+/* ----------------------------------------------------------------------------
+mace_write
+	Writes to a MACE register.  This is bank independent; however,
+	the caller must ensure that this call is not interruptable.  We
+	are assuming that during normal operation, the MACE is always in
+	bank 0.
+---------------------------------------------------------------------------- */
+static void mace_write(mace_private *lp, unsigned int ioaddr, int reg,
+		       int data)
+{
+  unsigned long flags;
+
+  switch (reg >> 4) {
+    case 0: /* register 0-15 */
+      outb(data & 0xFF, ioaddr + AM2150_MACE_BASE + reg);
+      break;
+    case 1: /* register 16-31 */
+      spin_lock_irqsave(&lp->bank_lock, flags);
+      MACEBANK(1);
+      outb(data & 0xFF, ioaddr + AM2150_MACE_BASE + (reg & 0x0F));
+      MACEBANK(0);
+      spin_unlock_irqrestore(&lp->bank_lock, flags);
+      break;
+  }
+} /* mace_write */
+
+/* ----------------------------------------------------------------------------
+mace_init
+	Resets the MACE chip.
+---------------------------------------------------------------------------- */
+static int mace_init(mace_private *lp, unsigned int ioaddr, char *enet_addr)
+{
+  int i;
+  int ct = 0;
+
+  /* MACE Software reset */
+  mace_write(lp, ioaddr, MACE_BIUCC, 1);
+  while (mace_read(lp, ioaddr, MACE_BIUCC) & 0x01) {
+    /* Wait for reset bit to be cleared automatically after <= 200ns */;
+    if(++ct > 500)
+    {
+	pr_err("reset failed, card removed?\n");
+    	return -1;
+    }
+    udelay(1);
+  }
+  mace_write(lp, ioaddr, MACE_BIUCC, 0);
+
+  /* The Am2150 requires that the MACE FIFOs operate in burst mode. */
+  mace_write(lp, ioaddr, MACE_FIFOCC, 0x0F);
+
+  mace_write(lp,ioaddr, MACE_RCVFC, 0); /* Disable Auto Strip Receive */
+  mace_write(lp, ioaddr, MACE_IMR, 0xFF); /* Disable all interrupts until _open */
+
+  /*
+   * Bit 2-1 PORTSEL[1-0] Port Select.
+   * 00 AUI/10Base-2
+   * 01 10Base-T
+   * 10 DAI Port (reserved in Am2150)
+   * 11 GPSI
+   * For this card, only the first two are valid.
+   * So, PLSCC should be set to
+   * 0x00 for 10Base-2
+   * 0x02 for 10Base-T
+   * Or just set ASEL in PHYCC below!
+   */
+  switch (if_port) {
+    case 1:
+      mace_write(lp, ioaddr, MACE_PLSCC, 0x02);
+      break;
+    case 2:
+      mace_write(lp, ioaddr, MACE_PLSCC, 0x00);
+      break;
+    default:
+      mace_write(lp, ioaddr, MACE_PHYCC, /* ASEL */ 4);
+      /* ASEL Auto Select.  When set, the PORTSEL[1-0] bits are overridden,
+	 and the MACE device will automatically select the operating media
+	 interface port. */
+      break;
+  }
+
+  mace_write(lp, ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_PHYADDR);
+  /* Poll ADDRCHG bit */
+  ct = 0;
+  while (mace_read(lp, ioaddr, MACE_IAC) & MACE_IAC_ADDRCHG)
+  {
+  	if(++ ct > 500)
+  	{
+		pr_err("ADDRCHG timeout, card removed?\n");
+  		return -1;
+  	}
+  }
+  /* Set PADR register */
+  for (i = 0; i < ETHER_ADDR_LEN; i++)
+    mace_write(lp, ioaddr, MACE_PADR, enet_addr[i]);
+
+  /* MAC Configuration Control Register should be written last */
+  /* Let set_multicast_list set this. */
+  /* mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); */
+  mace_write(lp, ioaddr, MACE_MACCC, 0x00);
+  return 0;
+} /* mace_init */
+
+static int nmclan_config(struct pcmcia_device *link)
+{
+  struct net_device *dev = link->priv;
+  mace_private *lp = netdev_priv(dev);
+  u8 *buf;
+  size_t len;
+  int i, ret;
+  unsigned int ioaddr;
+
+  dev_dbg(&link->dev, "nmclan_config\n");
+
+  link->io_lines = 5;
+  ret = pcmcia_request_io(link);
+  if (ret)
+	  goto failed;
+  ret = pcmcia_request_exclusive_irq(link, mace_interrupt);
+  if (ret)
+	  goto failed;
+  ret = pcmcia_enable_device(link);
+  if (ret)
+	  goto failed;
+
+  dev->irq = link->irq;
+  dev->base_addr = link->resource[0]->start;
+
+  ioaddr = dev->base_addr;
+
+  /* Read the ethernet address from the CIS. */
+  len = pcmcia_get_tuple(link, 0x80, &buf);
+  if (!buf || len < ETHER_ADDR_LEN) {
+	  kfree(buf);
+	  goto failed;
+  }
+  memcpy(dev->dev_addr, buf, ETHER_ADDR_LEN);
+  kfree(buf);
+
+  /* Verify configuration by reading the MACE ID. */
+  {
+    char sig[2];
+
+    sig[0] = mace_read(lp, ioaddr, MACE_CHIPIDL);
+    sig[1] = mace_read(lp, ioaddr, MACE_CHIPIDH);
+    if ((sig[0] == 0x40) && ((sig[1] & 0x0F) == 0x09)) {
+      dev_dbg(&link->dev, "nmclan_cs configured: mace id=%x %x\n",
+	    sig[0], sig[1]);
+    } else {
+      pr_notice("mace id not found: %x %x should be 0x40 0x?9\n",
+		sig[0], sig[1]);
+      return -ENODEV;
+    }
+  }
+
+  if(mace_init(lp, ioaddr, dev->dev_addr) == -1)
+  	goto failed;
+
+  /* The if_port symbol can be set when the module is loaded */
+  if (if_port <= 2)
+    dev->if_port = if_port;
+  else
+    pr_notice("invalid if_port requested\n");
+
+  SET_NETDEV_DEV(dev, &link->dev);
+
+  i = register_netdev(dev);
+  if (i != 0) {
+    pr_notice("register_netdev() failed\n");
+    goto failed;
+  }
+
+  netdev_info(dev, "nmclan: port %#3lx, irq %d, %s port, hw_addr %pM\n",
+	      dev->base_addr, dev->irq, if_names[dev->if_port], dev->dev_addr);
+  return 0;
+
+failed:
+	nmclan_release(link);
+	return -ENODEV;
+} /* nmclan_config */
+
+static void nmclan_release(struct pcmcia_device *link)
+{
+	dev_dbg(&link->dev, "nmclan_release\n");
+	pcmcia_disable_device(link);
+}
+
+static int nmclan_suspend(struct pcmcia_device *link)
+{
+	struct net_device *dev = link->priv;
+
+	if (link->open)
+		netif_device_detach(dev);
+
+	return 0;
+}
+
+static int nmclan_resume(struct pcmcia_device *link)
+{
+	struct net_device *dev = link->priv;
+
+	if (link->open) {
+		nmclan_reset(dev);
+		netif_device_attach(dev);
+	}
+
+	return 0;
+}
+
+
+/* ----------------------------------------------------------------------------
+nmclan_reset
+	Reset and restore all of the Xilinx and MACE registers.
+---------------------------------------------------------------------------- */
+static void nmclan_reset(struct net_device *dev)
+{
+  mace_private *lp = netdev_priv(dev);
+
+#if RESET_XILINX
+  struct pcmcia_device *link = &lp->link;
+  u8 OrigCorValue;
+
+  /* Save original COR value */
+  pcmcia_read_config_byte(link, CISREG_COR, &OrigCorValue);
+
+  /* Reset Xilinx */
+  dev_dbg(&link->dev, "nmclan_reset: OrigCorValue=0x%x, resetting...\n",
+	OrigCorValue);
+  pcmcia_write_config_byte(link, CISREG_COR, COR_SOFT_RESET);
+  /* Need to wait for 20 ms for PCMCIA to finish reset. */
+
+  /* Restore original COR configuration index */
+  pcmcia_write_config_byte(link, CISREG_COR,
+			  (COR_LEVEL_REQ | (OrigCorValue & COR_CONFIG_MASK)));
+  /* Xilinx is now completely reset along with the MACE chip. */
+  lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
+
+#endif /* #if RESET_XILINX */
+
+  /* Xilinx is now completely reset along with the MACE chip. */
+  lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
+
+  /* Reinitialize the MACE chip for operation. */
+  mace_init(lp, dev->base_addr, dev->dev_addr);
+  mace_write(lp, dev->base_addr, MACE_IMR, MACE_IMR_DEFAULT);
+
+  /* Restore the multicast list and enable TX and RX. */
+  restore_multicast_list(dev);
+} /* nmclan_reset */
+
+/* ----------------------------------------------------------------------------
+mace_config
+	[Someone tell me what this is supposed to do?  Is if_port a defined
+	standard?  If so, there should be defines to indicate 1=10Base-T,
+	2=10Base-2, etc. including limited automatic detection.]
+---------------------------------------------------------------------------- */
+static int mace_config(struct net_device *dev, struct ifmap *map)
+{
+  if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
+    if (map->port <= 2) {
+      dev->if_port = map->port;
+      netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]);
+    } else
+      return -EINVAL;
+  }
+  return 0;
+} /* mace_config */
+
+/* ----------------------------------------------------------------------------
+mace_open
+	Open device driver.
+---------------------------------------------------------------------------- */
+static int mace_open(struct net_device *dev)
+{
+  unsigned int ioaddr = dev->base_addr;
+  mace_private *lp = netdev_priv(dev);
+  struct pcmcia_device *link = lp->p_dev;
+
+  if (!pcmcia_dev_present(link))
+    return -ENODEV;
+
+  link->open++;
+
+  MACEBANK(0);
+
+  netif_start_queue(dev);
+  nmclan_reset(dev);
+
+  return 0; /* Always succeed */
+} /* mace_open */
+
+/* ----------------------------------------------------------------------------
+mace_close
+	Closes device driver.
+---------------------------------------------------------------------------- */
+static int mace_close(struct net_device *dev)
+{
+  unsigned int ioaddr = dev->base_addr;
+  mace_private *lp = netdev_priv(dev);
+  struct pcmcia_device *link = lp->p_dev;
+
+  dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name);
+
+  /* Mask off all interrupts from the MACE chip. */
+  outb(0xFF, ioaddr + AM2150_MACE_BASE + MACE_IMR);
+
+  link->open--;
+  netif_stop_queue(dev);
+
+  return 0;
+} /* mace_close */
+
+static void netdev_get_drvinfo(struct net_device *dev,
+			       struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	sprintf(info->bus_info, "PCMCIA 0x%lx", dev->base_addr);
+}
+
+static const struct ethtool_ops netdev_ethtool_ops = {
+	.get_drvinfo		= netdev_get_drvinfo,
+};
+
+/* ----------------------------------------------------------------------------
+mace_start_xmit
+	This routine begins the packet transmit function.  When completed,
+	it will generate a transmit interrupt.
+
+	According to /usr/src/linux/net/inet/dev.c, if _start_xmit
+	returns 0, the "packet is now solely the responsibility of the
+	driver."  If _start_xmit returns non-zero, the "transmission
+	failed, put skb back into a list."
+---------------------------------------------------------------------------- */
+
+static void mace_tx_timeout(struct net_device *dev)
+{
+  mace_private *lp = netdev_priv(dev);
+  struct pcmcia_device *link = lp->p_dev;
+
+  netdev_notice(dev, "transmit timed out -- ");
+#if RESET_ON_TIMEOUT
+  pr_cont("resetting card\n");
+  pcmcia_reset_card(link->socket);
+#else /* #if RESET_ON_TIMEOUT */
+  pr_cont("NOT resetting card\n");
+#endif /* #if RESET_ON_TIMEOUT */
+  dev->trans_start = jiffies; /* prevent tx timeout */
+  netif_wake_queue(dev);
+}
+
+static netdev_tx_t mace_start_xmit(struct sk_buff *skb,
+					 struct net_device *dev)
+{
+  mace_private *lp = netdev_priv(dev);
+  unsigned int ioaddr = dev->base_addr;
+
+  netif_stop_queue(dev);
+
+  pr_debug("%s: mace_start_xmit(length = %ld) called.\n",
+	dev->name, (long)skb->len);
+
+#if (!TX_INTERRUPTABLE)
+  /* Disable MACE TX interrupts. */
+  outb(MACE_IMR_DEFAULT | MACE_IR_XMTINT,
+    ioaddr + AM2150_MACE_BASE + MACE_IMR);
+  lp->tx_irq_disabled=1;
+#endif /* #if (!TX_INTERRUPTABLE) */
+
+  {
+    /* This block must not be interrupted by another transmit request!
+       mace_tx_timeout will take care of timer-based retransmissions from
+       the upper layers.  The interrupt handler is guaranteed never to
+       service a transmit interrupt while we are in here.
+    */
+
+    lp->linux_stats.tx_bytes += skb->len;
+    lp->tx_free_frames--;
+
+    /* WARNING: Write the _exact_ number of bytes written in the header! */
+    /* Put out the word header [must be an outw()] . . . */
+    outw(skb->len, ioaddr + AM2150_XMT);
+    /* . . . and the packet [may be any combination of outw() and outb()] */
+    outsw(ioaddr + AM2150_XMT, skb->data, skb->len >> 1);
+    if (skb->len & 1) {
+      /* Odd byte transfer */
+      outb(skb->data[skb->len-1], ioaddr + AM2150_XMT);
+    }
+
+#if MULTI_TX
+    if (lp->tx_free_frames > 0)
+      netif_start_queue(dev);
+#endif /* #if MULTI_TX */
+  }
+
+#if (!TX_INTERRUPTABLE)
+  /* Re-enable MACE TX interrupts. */
+  lp->tx_irq_disabled=0;
+  outb(MACE_IMR_DEFAULT, ioaddr + AM2150_MACE_BASE + MACE_IMR);
+#endif /* #if (!TX_INTERRUPTABLE) */
+
+  dev_kfree_skb(skb);
+
+  return NETDEV_TX_OK;
+} /* mace_start_xmit */
+
+/* ----------------------------------------------------------------------------
+mace_interrupt
+	The interrupt handler.
+---------------------------------------------------------------------------- */
+static irqreturn_t mace_interrupt(int irq, void *dev_id)
+{
+  struct net_device *dev = (struct net_device *) dev_id;
+  mace_private *lp = netdev_priv(dev);
+  unsigned int ioaddr;
+  int status;
+  int IntrCnt = MACE_MAX_IR_ITERATIONS;
+
+  if (dev == NULL) {
+    pr_debug("mace_interrupt(): irq 0x%X for unknown device.\n",
+	  irq);
+    return IRQ_NONE;
+  }
+
+  ioaddr = dev->base_addr;
+
+  if (lp->tx_irq_disabled) {
+    const char *msg;
+    if (lp->tx_irq_disabled)
+      msg = "Interrupt with tx_irq_disabled";
+    else
+      msg = "Re-entering the interrupt handler";
+    netdev_notice(dev, "%s [isr=%02X, imr=%02X]\n",
+		  msg,
+		  inb(ioaddr + AM2150_MACE_BASE + MACE_IR),
+		  inb(ioaddr + AM2150_MACE_BASE + MACE_IMR));
+    /* WARNING: MACE_IR has been read! */
+    return IRQ_NONE;
+  }
+
+  if (!netif_device_present(dev)) {
+    netdev_dbg(dev, "interrupt from dead card\n");
+    return IRQ_NONE;
+  }
+
+  do {
+    /* WARNING: MACE_IR is a READ/CLEAR port! */
+    status = inb(ioaddr + AM2150_MACE_BASE + MACE_IR);
+
+    pr_debug("mace_interrupt: irq 0x%X status 0x%X.\n", irq, status);
+
+    if (status & MACE_IR_RCVINT) {
+      mace_rx(dev, MACE_MAX_RX_ITERATIONS);
+    }
+
+    if (status & MACE_IR_XMTINT) {
+      unsigned char fifofc;
+      unsigned char xmtrc;
+      unsigned char xmtfs;
+
+      fifofc = inb(ioaddr + AM2150_MACE_BASE + MACE_FIFOFC);
+      if ((fifofc & MACE_FIFOFC_XMTFC)==0) {
+	lp->linux_stats.tx_errors++;
+	outb(0xFF, ioaddr + AM2150_XMT_SKIP);
+      }
+
+      /* Transmit Retry Count (XMTRC, reg 4) */
+      xmtrc = inb(ioaddr + AM2150_MACE_BASE + MACE_XMTRC);
+      if (xmtrc & MACE_XMTRC_EXDEF) lp->mace_stats.exdef++;
+      lp->mace_stats.xmtrc += (xmtrc & MACE_XMTRC_XMTRC);
+
+      if (
+        (xmtfs = inb(ioaddr + AM2150_MACE_BASE + MACE_XMTFS)) &
+        MACE_XMTFS_XMTSV /* Transmit Status Valid */
+      ) {
+	lp->mace_stats.xmtsv++;
+
+	if (xmtfs & ~MACE_XMTFS_XMTSV) {
+	  if (xmtfs & MACE_XMTFS_UFLO) {
+	    /* Underflow.  Indicates that the Transmit FIFO emptied before
+	       the end of frame was reached. */
+	    lp->mace_stats.uflo++;
+	  }
+	  if (xmtfs & MACE_XMTFS_LCOL) {
+	    /* Late Collision */
+	    lp->mace_stats.lcol++;
+	  }
+	  if (xmtfs & MACE_XMTFS_MORE) {
+	    /* MORE than one retry was needed */
+	    lp->mace_stats.more++;
+	  }
+	  if (xmtfs & MACE_XMTFS_ONE) {
+	    /* Exactly ONE retry occurred */
+	    lp->mace_stats.one++;
+	  }
+	  if (xmtfs & MACE_XMTFS_DEFER) {
+	    /* Transmission was defered */
+	    lp->mace_stats.defer++;
+	  }
+	  if (xmtfs & MACE_XMTFS_LCAR) {
+	    /* Loss of carrier */
+	    lp->mace_stats.lcar++;
+	  }
+	  if (xmtfs & MACE_XMTFS_RTRY) {
+	    /* Retry error: transmit aborted after 16 attempts */
+	    lp->mace_stats.rtry++;
+	  }
+        } /* if (xmtfs & ~MACE_XMTFS_XMTSV) */
+
+      } /* if (xmtfs & MACE_XMTFS_XMTSV) */
+
+      lp->linux_stats.tx_packets++;
+      lp->tx_free_frames++;
+      netif_wake_queue(dev);
+    } /* if (status & MACE_IR_XMTINT) */
+
+    if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) {
+      if (status & MACE_IR_JAB) {
+        /* Jabber Error.  Excessive transmit duration (20-150ms). */
+        lp->mace_stats.jab++;
+      }
+      if (status & MACE_IR_BABL) {
+        /* Babble Error.  >1518 bytes transmitted. */
+        lp->mace_stats.babl++;
+      }
+      if (status & MACE_IR_CERR) {
+	/* Collision Error.  CERR indicates the absence of the
+	   Signal Quality Error Test message after a packet
+	   transmission. */
+        lp->mace_stats.cerr++;
+      }
+      if (status & MACE_IR_RCVCCO) {
+        /* Receive Collision Count Overflow; */
+        lp->mace_stats.rcvcco++;
+      }
+      if (status & MACE_IR_RNTPCO) {
+        /* Runt Packet Count Overflow */
+        lp->mace_stats.rntpco++;
+      }
+      if (status & MACE_IR_MPCO) {
+        /* Missed Packet Count Overflow */
+        lp->mace_stats.mpco++;
+      }
+    } /* if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) */
+
+  } while ((status & ~MACE_IMR_DEFAULT) && (--IntrCnt));
+
+  return IRQ_HANDLED;
+} /* mace_interrupt */
+
+/* ----------------------------------------------------------------------------
+mace_rx
+	Receives packets.
+---------------------------------------------------------------------------- */
+static int mace_rx(struct net_device *dev, unsigned char RxCnt)
+{
+  mace_private *lp = netdev_priv(dev);
+  unsigned int ioaddr = dev->base_addr;
+  unsigned char rx_framecnt;
+  unsigned short rx_status;
+
+  while (
+    ((rx_framecnt = inb(ioaddr + AM2150_RCV_FRAME_COUNT)) > 0) &&
+    (rx_framecnt <= 12) && /* rx_framecnt==0xFF if card is extracted. */
+    (RxCnt--)
+  ) {
+    rx_status = inw(ioaddr + AM2150_RCV);
+
+    pr_debug("%s: in mace_rx(), framecnt 0x%X, rx_status"
+	  " 0x%X.\n", dev->name, rx_framecnt, rx_status);
+
+    if (rx_status & MACE_RCVFS_RCVSTS) { /* Error, update stats. */
+      lp->linux_stats.rx_errors++;
+      if (rx_status & MACE_RCVFS_OFLO) {
+        lp->mace_stats.oflo++;
+      }
+      if (rx_status & MACE_RCVFS_CLSN) {
+        lp->mace_stats.clsn++;
+      }
+      if (rx_status & MACE_RCVFS_FRAM) {
+	lp->mace_stats.fram++;
+      }
+      if (rx_status & MACE_RCVFS_FCS) {
+        lp->mace_stats.fcs++;
+      }
+    } else {
+      short pkt_len = (rx_status & ~MACE_RCVFS_RCVSTS) - 4;
+        /* Auto Strip is off, always subtract 4 */
+      struct sk_buff *skb;
+
+      lp->mace_stats.rfs_rntpc += inb(ioaddr + AM2150_RCV);
+        /* runt packet count */
+      lp->mace_stats.rfs_rcvcc += inb(ioaddr + AM2150_RCV);
+        /* rcv collision count */
+
+      pr_debug("    receiving packet size 0x%X rx_status"
+	    " 0x%X.\n", pkt_len, rx_status);
+
+      skb = dev_alloc_skb(pkt_len+2);
+
+      if (skb != NULL) {
+	skb_reserve(skb, 2);
+	insw(ioaddr + AM2150_RCV, skb_put(skb, pkt_len), pkt_len>>1);
+	if (pkt_len & 1)
+	    *(skb_tail_pointer(skb) - 1) = inb(ioaddr + AM2150_RCV);
+	skb->protocol = eth_type_trans(skb, dev);
+	
+	netif_rx(skb); /* Send the packet to the upper (protocol) layers. */
+
+	lp->linux_stats.rx_packets++;
+	lp->linux_stats.rx_bytes += pkt_len;
+	outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */
+	continue;
+      } else {
+	pr_debug("%s: couldn't allocate a sk_buff of size"
+	      " %d.\n", dev->name, pkt_len);
+	lp->linux_stats.rx_dropped++;
+      }
+    }
+    outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */
+  } /* while */
+
+  return 0;
+} /* mace_rx */
+
+/* ----------------------------------------------------------------------------
+pr_linux_stats
+---------------------------------------------------------------------------- */
+static void pr_linux_stats(struct net_device_stats *pstats)
+{
+  pr_debug("pr_linux_stats\n");
+  pr_debug(" rx_packets=%-7ld        tx_packets=%ld\n",
+	(long)pstats->rx_packets, (long)pstats->tx_packets);
+  pr_debug(" rx_errors=%-7ld         tx_errors=%ld\n",
+	(long)pstats->rx_errors, (long)pstats->tx_errors);
+  pr_debug(" rx_dropped=%-7ld        tx_dropped=%ld\n",
+	(long)pstats->rx_dropped, (long)pstats->tx_dropped);
+  pr_debug(" multicast=%-7ld         collisions=%ld\n",
+	(long)pstats->multicast, (long)pstats->collisions);
+
+  pr_debug(" rx_length_errors=%-7ld  rx_over_errors=%ld\n",
+	(long)pstats->rx_length_errors, (long)pstats->rx_over_errors);
+  pr_debug(" rx_crc_errors=%-7ld     rx_frame_errors=%ld\n",
+	(long)pstats->rx_crc_errors, (long)pstats->rx_frame_errors);
+  pr_debug(" rx_fifo_errors=%-7ld    rx_missed_errors=%ld\n",
+	(long)pstats->rx_fifo_errors, (long)pstats->rx_missed_errors);
+
+  pr_debug(" tx_aborted_errors=%-7ld tx_carrier_errors=%ld\n",
+	(long)pstats->tx_aborted_errors, (long)pstats->tx_carrier_errors);
+  pr_debug(" tx_fifo_errors=%-7ld    tx_heartbeat_errors=%ld\n",
+	(long)pstats->tx_fifo_errors, (long)pstats->tx_heartbeat_errors);
+  pr_debug(" tx_window_errors=%ld\n",
+	(long)pstats->tx_window_errors);
+} /* pr_linux_stats */
+
+/* ----------------------------------------------------------------------------
+pr_mace_stats
+---------------------------------------------------------------------------- */
+static void pr_mace_stats(mace_statistics *pstats)
+{
+  pr_debug("pr_mace_stats\n");
+
+  pr_debug(" xmtsv=%-7d             uflo=%d\n",
+	pstats->xmtsv, pstats->uflo);
+  pr_debug(" lcol=%-7d              more=%d\n",
+	pstats->lcol, pstats->more);
+  pr_debug(" one=%-7d               defer=%d\n",
+	pstats->one, pstats->defer);
+  pr_debug(" lcar=%-7d              rtry=%d\n",
+	pstats->lcar, pstats->rtry);
+
+  /* MACE_XMTRC */
+  pr_debug(" exdef=%-7d             xmtrc=%d\n",
+	pstats->exdef, pstats->xmtrc);
+
+  /* RFS1--Receive Status (RCVSTS) */
+  pr_debug(" oflo=%-7d              clsn=%d\n",
+	pstats->oflo, pstats->clsn);
+  pr_debug(" fram=%-7d              fcs=%d\n",
+	pstats->fram, pstats->fcs);
+
+  /* RFS2--Runt Packet Count (RNTPC) */
+  /* RFS3--Receive Collision Count (RCVCC) */
+  pr_debug(" rfs_rntpc=%-7d         rfs_rcvcc=%d\n",
+	pstats->rfs_rntpc, pstats->rfs_rcvcc);
+
+  /* MACE_IR */
+  pr_debug(" jab=%-7d               babl=%d\n",
+	pstats->jab, pstats->babl);
+  pr_debug(" cerr=%-7d              rcvcco=%d\n",
+	pstats->cerr, pstats->rcvcco);
+  pr_debug(" rntpco=%-7d            mpco=%d\n",
+	pstats->rntpco, pstats->mpco);
+
+  /* MACE_MPC */
+  pr_debug(" mpc=%d\n", pstats->mpc);
+
+  /* MACE_RNTPC */
+  pr_debug(" rntpc=%d\n", pstats->rntpc);
+
+  /* MACE_RCVCC */
+  pr_debug(" rcvcc=%d\n", pstats->rcvcc);
+
+} /* pr_mace_stats */
+
+/* ----------------------------------------------------------------------------
+update_stats
+	Update statistics.  We change to register window 1, so this
+	should be run single-threaded if the device is active. This is
+	expected to be a rare operation, and it's simpler for the rest
+	of the driver to assume that window 0 is always valid rather
+	than use a special window-state variable.
+
+	oflo & uflo should _never_ occur since it would mean the Xilinx
+	was not able to transfer data between the MACE FIFO and the
+	card's SRAM fast enough.  If this happens, something is
+	seriously wrong with the hardware.
+---------------------------------------------------------------------------- */
+static void update_stats(unsigned int ioaddr, struct net_device *dev)
+{
+  mace_private *lp = netdev_priv(dev);
+
+  lp->mace_stats.rcvcc += mace_read(lp, ioaddr, MACE_RCVCC);
+  lp->mace_stats.rntpc += mace_read(lp, ioaddr, MACE_RNTPC);
+  lp->mace_stats.mpc += mace_read(lp, ioaddr, MACE_MPC);
+  /* At this point, mace_stats is fully updated for this call.
+     We may now update the linux_stats. */
+
+  /* The MACE has no equivalent for linux_stats field which are commented
+     out. */
+
+  /* lp->linux_stats.multicast; */
+  lp->linux_stats.collisions = 
+    lp->mace_stats.rcvcco * 256 + lp->mace_stats.rcvcc;
+    /* Collision: The MACE may retry sending a packet 15 times
+       before giving up.  The retry count is in XMTRC.
+       Does each retry constitute a collision?
+       If so, why doesn't the RCVCC record these collisions? */
+
+  /* detailed rx_errors: */
+  lp->linux_stats.rx_length_errors = 
+    lp->mace_stats.rntpco * 256 + lp->mace_stats.rntpc;
+  /* lp->linux_stats.rx_over_errors */
+  lp->linux_stats.rx_crc_errors = lp->mace_stats.fcs;
+  lp->linux_stats.rx_frame_errors = lp->mace_stats.fram;
+  lp->linux_stats.rx_fifo_errors = lp->mace_stats.oflo;
+  lp->linux_stats.rx_missed_errors = 
+    lp->mace_stats.mpco * 256 + lp->mace_stats.mpc;
+
+  /* detailed tx_errors */
+  lp->linux_stats.tx_aborted_errors = lp->mace_stats.rtry;
+  lp->linux_stats.tx_carrier_errors = lp->mace_stats.lcar;
+    /* LCAR usually results from bad cabling. */
+  lp->linux_stats.tx_fifo_errors = lp->mace_stats.uflo;
+  lp->linux_stats.tx_heartbeat_errors = lp->mace_stats.cerr;
+  /* lp->linux_stats.tx_window_errors; */
+} /* update_stats */
+
+/* ----------------------------------------------------------------------------
+mace_get_stats
+	Gathers ethernet statistics from the MACE chip.
+---------------------------------------------------------------------------- */
+static struct net_device_stats *mace_get_stats(struct net_device *dev)
+{
+  mace_private *lp = netdev_priv(dev);
+
+  update_stats(dev->base_addr, dev);
+
+  pr_debug("%s: updating the statistics.\n", dev->name);
+  pr_linux_stats(&lp->linux_stats);
+  pr_mace_stats(&lp->mace_stats);
+
+  return &lp->linux_stats;
+} /* net_device_stats */
+
+/* ----------------------------------------------------------------------------
+updateCRC
+	Modified from Am79C90 data sheet.
+---------------------------------------------------------------------------- */
+
+#ifdef BROKEN_MULTICAST
+
+static void updateCRC(int *CRC, int bit)
+{
+  static const int poly[]={
+    1,1,1,0, 1,1,0,1,
+    1,0,1,1, 1,0,0,0,
+    1,0,0,0, 0,0,1,1,
+    0,0,1,0, 0,0,0,0
+  }; /* CRC polynomial.  poly[n] = coefficient of the x**n term of the
+	CRC generator polynomial. */
+
+  int j;
+
+  /* shift CRC and control bit (CRC[32]) */
+  for (j = 32; j > 0; j--)
+    CRC[j] = CRC[j-1];
+  CRC[0] = 0;
+
+  /* If bit XOR(control bit) = 1, set CRC = CRC XOR polynomial. */
+  if (bit ^ CRC[32])
+    for (j = 0; j < 32; j++)
+      CRC[j] ^= poly[j];
+} /* updateCRC */
+
+/* ----------------------------------------------------------------------------
+BuildLAF
+	Build logical address filter.
+	Modified from Am79C90 data sheet.
+
+Input
+	ladrf: logical address filter (contents initialized to 0)
+	adr: ethernet address
+---------------------------------------------------------------------------- */
+static void BuildLAF(int *ladrf, int *adr)
+{
+  int CRC[33]={1}; /* CRC register, 1 word/bit + extra control bit */
+
+  int i, byte; /* temporary array indices */
+  int hashcode; /* the output object */
+
+  CRC[32]=0;
+
+  for (byte = 0; byte < 6; byte++)
+    for (i = 0; i < 8; i++)
+      updateCRC(CRC, (adr[byte] >> i) & 1);
+
+  hashcode = 0;
+  for (i = 0; i < 6; i++)
+    hashcode = (hashcode << 1) + CRC[i];
+
+  byte = hashcode >> 3;
+  ladrf[byte] |= (1 << (hashcode & 7));
+
+#ifdef PCMCIA_DEBUG
+  if (0)
+    printk(KERN_DEBUG "    adr =%pM\n", adr);
+  printk(KERN_DEBUG "    hashcode = %d(decimal), ladrf[0:63] =", hashcode);
+  for (i = 0; i < 8; i++)
+    pr_cont(" %02X", ladrf[i]);
+  pr_cont("\n");
+#endif
+} /* BuildLAF */
+
+/* ----------------------------------------------------------------------------
+restore_multicast_list
+	Restores the multicast filter for MACE chip to the last
+	set_multicast_list() call.
+
+Input
+	multicast_num_addrs
+	multicast_ladrf[]
+---------------------------------------------------------------------------- */
+static void restore_multicast_list(struct net_device *dev)
+{
+  mace_private *lp = netdev_priv(dev);
+  int num_addrs = lp->multicast_num_addrs;
+  int *ladrf = lp->multicast_ladrf;
+  unsigned int ioaddr = dev->base_addr;
+  int i;
+
+  pr_debug("%s: restoring Rx mode to %d addresses.\n",
+	dev->name, num_addrs);
+
+  if (num_addrs > 0) {
+
+    pr_debug("Attempt to restore multicast list detected.\n");
+
+    mace_write(lp, ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_LOGADDR);
+    /* Poll ADDRCHG bit */
+    while (mace_read(lp, ioaddr, MACE_IAC) & MACE_IAC_ADDRCHG)
+      ;
+    /* Set LADRF register */
+    for (i = 0; i < MACE_LADRF_LEN; i++)
+      mace_write(lp, ioaddr, MACE_LADRF, ladrf[i]);
+
+    mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_RCVFCSE | MACE_UTR_LOOP_EXTERNAL);
+    mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV);
+
+  } else if (num_addrs < 0) {
+
+    /* Promiscuous mode: receive all packets */
+    mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
+    mace_write(lp, ioaddr, MACE_MACCC,
+      MACE_MACCC_PROM | MACE_MACCC_ENXMT | MACE_MACCC_ENRCV
+    );
+
+  } else {
+
+    /* Normal mode */
+    mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
+    mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV);
+
+  }
+} /* restore_multicast_list */
+
+/* ----------------------------------------------------------------------------
+set_multicast_list
+	Set or clear the multicast filter for this adaptor.
+
+Input
+	num_addrs == -1	Promiscuous mode, receive all packets
+	num_addrs == 0	Normal mode, clear multicast list
+	num_addrs > 0	Multicast mode, receive normal and MC packets, and do
+			best-effort filtering.
+Output
+	multicast_num_addrs
+	multicast_ladrf[]
+---------------------------------------------------------------------------- */
+
+static void set_multicast_list(struct net_device *dev)
+{
+  mace_private *lp = netdev_priv(dev);
+  int adr[ETHER_ADDR_LEN] = {0}; /* Ethernet address */
+  struct netdev_hw_addr *ha;
+
+#ifdef PCMCIA_DEBUG
+  {
+    static int old;
+    if (netdev_mc_count(dev) != old) {
+      old = netdev_mc_count(dev);
+      pr_debug("%s: setting Rx mode to %d addresses.\n",
+	    dev->name, old);
+    }
+  }
+#endif
+
+  /* Set multicast_num_addrs. */
+  lp->multicast_num_addrs = netdev_mc_count(dev);
+
+  /* Set multicast_ladrf. */
+  if (num_addrs > 0) {
+    /* Calculate multicast logical address filter */
+    memset(lp->multicast_ladrf, 0, MACE_LADRF_LEN);
+    netdev_for_each_mc_addr(ha, dev) {
+      memcpy(adr, ha->addr, ETHER_ADDR_LEN);
+      BuildLAF(lp->multicast_ladrf, adr);
+    }
+  }
+
+  restore_multicast_list(dev);
+
+} /* set_multicast_list */
+
+#endif /* BROKEN_MULTICAST */
+
+static void restore_multicast_list(struct net_device *dev)
+{
+  unsigned int ioaddr = dev->base_addr;
+  mace_private *lp = netdev_priv(dev);
+
+  pr_debug("%s: restoring Rx mode to %d addresses.\n", dev->name,
+	lp->multicast_num_addrs);
+
+  if (dev->flags & IFF_PROMISC) {
+    /* Promiscuous mode: receive all packets */
+    mace_write(lp,ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
+    mace_write(lp, ioaddr, MACE_MACCC,
+      MACE_MACCC_PROM | MACE_MACCC_ENXMT | MACE_MACCC_ENRCV
+    );
+  } else {
+    /* Normal mode */
+    mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
+    mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV);
+  }
+} /* restore_multicast_list */
+
+static void set_multicast_list(struct net_device *dev)
+{
+  mace_private *lp = netdev_priv(dev);
+
+#ifdef PCMCIA_DEBUG
+  {
+    static int old;
+    if (netdev_mc_count(dev) != old) {
+      old = netdev_mc_count(dev);
+      pr_debug("%s: setting Rx mode to %d addresses.\n",
+	    dev->name, old);
+    }
+  }
+#endif
+
+  lp->multicast_num_addrs = netdev_mc_count(dev);
+  restore_multicast_list(dev);
+
+} /* set_multicast_list */
+
+static const struct pcmcia_device_id nmclan_ids[] = {
+	PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "Ethernet", 0x085a850b, 0x00b2e941),
+	PCMCIA_DEVICE_PROD_ID12("Portable Add-ons", "Ethernet+", 0xebf1d60, 0xad673aaf),
+	PCMCIA_DEVICE_NULL,
+};
+MODULE_DEVICE_TABLE(pcmcia, nmclan_ids);
+
+static struct pcmcia_driver nmclan_cs_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "nmclan_cs",
+	.probe		= nmclan_probe,
+	.remove		= nmclan_detach,
+	.id_table       = nmclan_ids,
+	.suspend	= nmclan_suspend,
+	.resume		= nmclan_resume,
+};
+
+static int __init init_nmclan_cs(void)
+{
+	return pcmcia_register_driver(&nmclan_cs_driver);
+}
+
+static void __exit exit_nmclan_cs(void)
+{
+	pcmcia_unregister_driver(&nmclan_cs_driver);
+}
+
+module_init(init_nmclan_cs);
+module_exit(exit_nmclan_cs);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/pcnet32.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/pcnet32.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/pcnet32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/pcnet32.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2937 @@
+/* pcnet32.c: An AMD PCnet32 ethernet driver for linux. */
+/*
+ *	Copyright 1996-1999 Thomas Bogendoerfer
+ *
+ *	Derived from the lance driver written 1993,1994,1995 by Donald Becker.
+ *
+ *	Copyright 1993 United States Government as represented by the
+ *	Director, National Security Agency.
+ *
+ *	This software may be used and distributed according to the terms
+ *	of the GNU General Public License, incorporated herein by reference.
+ *
+ *	This driver is for PCnet32 and PCnetPCI based ethercards
+ */
+/**************************************************************************
+ *  23 Oct, 2000.
+ *  Fixed a few bugs, related to running the controller in 32bit mode.
+ *
+ *  Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define DRV_NAME	"pcnet32"
+#define DRV_VERSION	"1.35"
+#define DRV_RELDATE	"21.Apr.2008"
+#define PFX		DRV_NAME ": "
+
+static const char *const version =
+    DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/moduleparam.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <asm/dma.h>
+#include <asm/irq.h>
+
+/*
+ * PCI device identifiers for "new style" Linux PCI Device Drivers
+ */
+static DEFINE_PCI_DEVICE_TABLE(pcnet32_pci_tbl) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE), },
+
+	/*
+	 * Adapters that were sold with IBM's RS/6000 or pSeries hardware have
+	 * the incorrect vendor id.
+	 */
+	{ PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE),
+	  .class = (PCI_CLASS_NETWORK_ETHERNET << 8), .class_mask = 0xffff00, },
+
+	{ }	/* terminate list */
+};
+
+MODULE_DEVICE_TABLE(pci, pcnet32_pci_tbl);
+
+static int cards_found;
+
+/*
+ * VLB I/O addresses
+ */
+static unsigned int pcnet32_portlist[] =
+    { 0x300, 0x320, 0x340, 0x360, 0 };
+
+static int pcnet32_debug;
+static int tx_start = 1;	/* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */
+static int pcnet32vlb;		/* check for VLB cards ? */
+
+static struct net_device *pcnet32_dev;
+
+static int max_interrupt_work = 2;
+static int rx_copybreak = 200;
+
+#define PCNET32_PORT_AUI      0x00
+#define PCNET32_PORT_10BT     0x01
+#define PCNET32_PORT_GPSI     0x02
+#define PCNET32_PORT_MII      0x03
+
+#define PCNET32_PORT_PORTSEL  0x03
+#define PCNET32_PORT_ASEL     0x04
+#define PCNET32_PORT_100      0x40
+#define PCNET32_PORT_FD	      0x80
+
+#define PCNET32_DMA_MASK 0xffffffff
+
+#define PCNET32_WATCHDOG_TIMEOUT (jiffies + (2 * HZ))
+#define PCNET32_BLINK_TIMEOUT	(jiffies + (HZ/4))
+
+/*
+ * table to translate option values from tulip
+ * to internal options
+ */
+static const unsigned char options_mapping[] = {
+	PCNET32_PORT_ASEL,			/*  0 Auto-select      */
+	PCNET32_PORT_AUI,			/*  1 BNC/AUI          */
+	PCNET32_PORT_AUI,			/*  2 AUI/BNC          */
+	PCNET32_PORT_ASEL,			/*  3 not supported    */
+	PCNET32_PORT_10BT | PCNET32_PORT_FD,	/*  4 10baseT-FD       */
+	PCNET32_PORT_ASEL,			/*  5 not supported    */
+	PCNET32_PORT_ASEL,			/*  6 not supported    */
+	PCNET32_PORT_ASEL,			/*  7 not supported    */
+	PCNET32_PORT_ASEL,			/*  8 not supported    */
+	PCNET32_PORT_MII,			/*  9 MII 10baseT      */
+	PCNET32_PORT_MII | PCNET32_PORT_FD,	/* 10 MII 10baseT-FD   */
+	PCNET32_PORT_MII,			/* 11 MII (autosel)    */
+	PCNET32_PORT_10BT,			/* 12 10BaseT          */
+	PCNET32_PORT_MII | PCNET32_PORT_100,	/* 13 MII 100BaseTx    */
+						/* 14 MII 100BaseTx-FD */
+	PCNET32_PORT_MII | PCNET32_PORT_100 | PCNET32_PORT_FD,
+	PCNET32_PORT_ASEL			/* 15 not supported    */
+};
+
+static const char pcnet32_gstrings_test[][ETH_GSTRING_LEN] = {
+	"Loopback test  (offline)"
+};
+
+#define PCNET32_TEST_LEN	ARRAY_SIZE(pcnet32_gstrings_test)
+
+#define PCNET32_NUM_REGS 136
+
+#define MAX_UNITS 8		/* More are supported, limit only on options */
+static int options[MAX_UNITS];
+static int full_duplex[MAX_UNITS];
+static int homepna[MAX_UNITS];
+
+/*
+ *				Theory of Operation
+ *
+ * This driver uses the same software structure as the normal lance
+ * driver. So look for a verbose description in lance.c. The differences
+ * to the normal lance driver is the use of the 32bit mode of PCnet32
+ * and PCnetPCI chips. Because these chips are 32bit chips, there is no
+ * 16MB limitation and we don't need bounce buffers.
+ */
+
+/*
+ * Set the number of Tx and Rx buffers, using Log_2(# buffers).
+ * Reasonable default values are 4 Tx buffers, and 16 Rx buffers.
+ * That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4).
+ */
+#ifndef PCNET32_LOG_TX_BUFFERS
+#define PCNET32_LOG_TX_BUFFERS		4
+#define PCNET32_LOG_RX_BUFFERS		5
+#define PCNET32_LOG_MAX_TX_BUFFERS	9	/* 2^9 == 512 */
+#define PCNET32_LOG_MAX_RX_BUFFERS	9
+#endif
+
+#define TX_RING_SIZE		(1 << (PCNET32_LOG_TX_BUFFERS))
+#define TX_MAX_RING_SIZE	(1 << (PCNET32_LOG_MAX_TX_BUFFERS))
+
+#define RX_RING_SIZE		(1 << (PCNET32_LOG_RX_BUFFERS))
+#define RX_MAX_RING_SIZE	(1 << (PCNET32_LOG_MAX_RX_BUFFERS))
+
+#define PKT_BUF_SKB		1544
+/* actual buffer length after being aligned */
+#define PKT_BUF_SIZE		(PKT_BUF_SKB - NET_IP_ALIGN)
+/* chip wants twos complement of the (aligned) buffer length */
+#define NEG_BUF_SIZE		(NET_IP_ALIGN - PKT_BUF_SKB)
+
+/* Offsets from base I/O address. */
+#define PCNET32_WIO_RDP		0x10
+#define PCNET32_WIO_RAP		0x12
+#define PCNET32_WIO_RESET	0x14
+#define PCNET32_WIO_BDP		0x16
+
+#define PCNET32_DWIO_RDP	0x10
+#define PCNET32_DWIO_RAP	0x14
+#define PCNET32_DWIO_RESET	0x18
+#define PCNET32_DWIO_BDP	0x1C
+
+#define PCNET32_TOTAL_SIZE	0x20
+
+#define CSR0		0
+#define CSR0_INIT	0x1
+#define CSR0_START	0x2
+#define CSR0_STOP	0x4
+#define CSR0_TXPOLL	0x8
+#define CSR0_INTEN	0x40
+#define CSR0_IDON	0x0100
+#define CSR0_NORMAL	(CSR0_START | CSR0_INTEN)
+#define PCNET32_INIT_LOW	1
+#define PCNET32_INIT_HIGH	2
+#define CSR3		3
+#define CSR4		4
+#define CSR5		5
+#define CSR5_SUSPEND	0x0001
+#define CSR15		15
+#define PCNET32_MC_FILTER	8
+
+#define PCNET32_79C970A	0x2621
+
+/* The PCNET32 Rx and Tx ring descriptors. */
+struct pcnet32_rx_head {
+	__le32	base;
+	__le16	buf_length;	/* two`s complement of length */
+	__le16	status;
+	__le32	msg_length;
+	__le32	reserved;
+};
+
+struct pcnet32_tx_head {
+	__le32	base;
+	__le16	length;		/* two`s complement of length */
+	__le16	status;
+	__le32	misc;
+	__le32	reserved;
+};
+
+/* The PCNET32 32-Bit initialization block, described in databook. */
+struct pcnet32_init_block {
+	__le16	mode;
+	__le16	tlen_rlen;
+	u8	phys_addr[6];
+	__le16	reserved;
+	__le32	filter[2];
+	/* Receive and transmit ring base, along with extra bits. */
+	__le32	rx_ring;
+	__le32	tx_ring;
+};
+
+/* PCnet32 access functions */
+struct pcnet32_access {
+	u16	(*read_csr) (unsigned long, int);
+	void	(*write_csr) (unsigned long, int, u16);
+	u16	(*read_bcr) (unsigned long, int);
+	void	(*write_bcr) (unsigned long, int, u16);
+	u16	(*read_rap) (unsigned long);
+	void	(*write_rap) (unsigned long, u16);
+	void	(*reset) (unsigned long);
+};
+
+/*
+ * The first field of pcnet32_private is read by the ethernet device
+ * so the structure should be allocated using pci_alloc_consistent().
+ */
+struct pcnet32_private {
+	struct pcnet32_init_block *init_block;
+	/* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */
+	struct pcnet32_rx_head	*rx_ring;
+	struct pcnet32_tx_head	*tx_ring;
+	dma_addr_t		init_dma_addr;/* DMA address of beginning of the init block,
+				   returned by pci_alloc_consistent */
+	struct pci_dev		*pci_dev;
+	const char		*name;
+	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
+	struct sk_buff		**tx_skbuff;
+	struct sk_buff		**rx_skbuff;
+	dma_addr_t		*tx_dma_addr;
+	dma_addr_t		*rx_dma_addr;
+	const struct pcnet32_access *a;
+	spinlock_t		lock;		/* Guard lock */
+	unsigned int		cur_rx, cur_tx;	/* The next free ring entry */
+	unsigned int		rx_ring_size;	/* current rx ring size */
+	unsigned int		tx_ring_size;	/* current tx ring size */
+	unsigned int		rx_mod_mask;	/* rx ring modular mask */
+	unsigned int		tx_mod_mask;	/* tx ring modular mask */
+	unsigned short		rx_len_bits;
+	unsigned short		tx_len_bits;
+	dma_addr_t		rx_ring_dma_addr;
+	dma_addr_t		tx_ring_dma_addr;
+	unsigned int		dirty_rx,	/* ring entries to be freed. */
+				dirty_tx;
+
+	struct net_device	*dev;
+	struct napi_struct	napi;
+	char			tx_full;
+	char			phycount;	/* number of phys found */
+	int			options;
+	unsigned int		shared_irq:1,	/* shared irq possible */
+				dxsuflo:1,   /* disable transmit stop on uflo */
+				mii:1;		/* mii port available */
+	struct net_device	*next;
+	struct mii_if_info	mii_if;
+	struct timer_list	watchdog_timer;
+	u32			msg_enable;	/* debug message level */
+
+	/* each bit indicates an available PHY */
+	u32			phymask;
+	unsigned short		chip_version;	/* which variant this is */
+
+	/* saved registers during ethtool blink */
+	u16 			save_regs[4];
+};
+
+static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
+static int pcnet32_probe1(unsigned long, int, struct pci_dev *);
+static int pcnet32_open(struct net_device *);
+static int pcnet32_init_ring(struct net_device *);
+static netdev_tx_t pcnet32_start_xmit(struct sk_buff *,
+				      struct net_device *);
+static void pcnet32_tx_timeout(struct net_device *dev);
+static irqreturn_t pcnet32_interrupt(int, void *);
+static int pcnet32_close(struct net_device *);
+static struct net_device_stats *pcnet32_get_stats(struct net_device *);
+static void pcnet32_load_multicast(struct net_device *dev);
+static void pcnet32_set_multicast_list(struct net_device *);
+static int pcnet32_ioctl(struct net_device *, struct ifreq *, int);
+static void pcnet32_watchdog(struct net_device *);
+static int mdio_read(struct net_device *dev, int phy_id, int reg_num);
+static void mdio_write(struct net_device *dev, int phy_id, int reg_num,
+		       int val);
+static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits);
+static void pcnet32_ethtool_test(struct net_device *dev,
+				 struct ethtool_test *eth_test, u64 * data);
+static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1);
+static int pcnet32_get_regs_len(struct net_device *dev);
+static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+			     void *ptr);
+static void pcnet32_purge_tx_ring(struct net_device *dev);
+static int pcnet32_alloc_ring(struct net_device *dev, const char *name);
+static void pcnet32_free_ring(struct net_device *dev);
+static void pcnet32_check_media(struct net_device *dev, int verbose);
+
+static u16 pcnet32_wio_read_csr(unsigned long addr, int index)
+{
+	outw(index, addr + PCNET32_WIO_RAP);
+	return inw(addr + PCNET32_WIO_RDP);
+}
+
+static void pcnet32_wio_write_csr(unsigned long addr, int index, u16 val)
+{
+	outw(index, addr + PCNET32_WIO_RAP);
+	outw(val, addr + PCNET32_WIO_RDP);
+}
+
+static u16 pcnet32_wio_read_bcr(unsigned long addr, int index)
+{
+	outw(index, addr + PCNET32_WIO_RAP);
+	return inw(addr + PCNET32_WIO_BDP);
+}
+
+static void pcnet32_wio_write_bcr(unsigned long addr, int index, u16 val)
+{
+	outw(index, addr + PCNET32_WIO_RAP);
+	outw(val, addr + PCNET32_WIO_BDP);
+}
+
+static u16 pcnet32_wio_read_rap(unsigned long addr)
+{
+	return inw(addr + PCNET32_WIO_RAP);
+}
+
+static void pcnet32_wio_write_rap(unsigned long addr, u16 val)
+{
+	outw(val, addr + PCNET32_WIO_RAP);
+}
+
+static void pcnet32_wio_reset(unsigned long addr)
+{
+	inw(addr + PCNET32_WIO_RESET);
+}
+
+static int pcnet32_wio_check(unsigned long addr)
+{
+	outw(88, addr + PCNET32_WIO_RAP);
+	return inw(addr + PCNET32_WIO_RAP) == 88;
+}
+
+static const struct pcnet32_access pcnet32_wio = {
+	.read_csr = pcnet32_wio_read_csr,
+	.write_csr = pcnet32_wio_write_csr,
+	.read_bcr = pcnet32_wio_read_bcr,
+	.write_bcr = pcnet32_wio_write_bcr,
+	.read_rap = pcnet32_wio_read_rap,
+	.write_rap = pcnet32_wio_write_rap,
+	.reset = pcnet32_wio_reset
+};
+
+static u16 pcnet32_dwio_read_csr(unsigned long addr, int index)
+{
+	outl(index, addr + PCNET32_DWIO_RAP);
+	return inl(addr + PCNET32_DWIO_RDP) & 0xffff;
+}
+
+static void pcnet32_dwio_write_csr(unsigned long addr, int index, u16 val)
+{
+	outl(index, addr + PCNET32_DWIO_RAP);
+	outl(val, addr + PCNET32_DWIO_RDP);
+}
+
+static u16 pcnet32_dwio_read_bcr(unsigned long addr, int index)
+{
+	outl(index, addr + PCNET32_DWIO_RAP);
+	return inl(addr + PCNET32_DWIO_BDP) & 0xffff;
+}
+
+static void pcnet32_dwio_write_bcr(unsigned long addr, int index, u16 val)
+{
+	outl(index, addr + PCNET32_DWIO_RAP);
+	outl(val, addr + PCNET32_DWIO_BDP);
+}
+
+static u16 pcnet32_dwio_read_rap(unsigned long addr)
+{
+	return inl(addr + PCNET32_DWIO_RAP) & 0xffff;
+}
+
+static void pcnet32_dwio_write_rap(unsigned long addr, u16 val)
+{
+	outl(val, addr + PCNET32_DWIO_RAP);
+}
+
+static void pcnet32_dwio_reset(unsigned long addr)
+{
+	inl(addr + PCNET32_DWIO_RESET);
+}
+
+static int pcnet32_dwio_check(unsigned long addr)
+{
+	outl(88, addr + PCNET32_DWIO_RAP);
+	return (inl(addr + PCNET32_DWIO_RAP) & 0xffff) == 88;
+}
+
+static const struct pcnet32_access pcnet32_dwio = {
+	.read_csr = pcnet32_dwio_read_csr,
+	.write_csr = pcnet32_dwio_write_csr,
+	.read_bcr = pcnet32_dwio_read_bcr,
+	.write_bcr = pcnet32_dwio_write_bcr,
+	.read_rap = pcnet32_dwio_read_rap,
+	.write_rap = pcnet32_dwio_write_rap,
+	.reset = pcnet32_dwio_reset
+};
+
+static void pcnet32_netif_stop(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	napi_disable(&lp->napi);
+	netif_tx_disable(dev);
+}
+
+static void pcnet32_netif_start(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	ulong ioaddr = dev->base_addr;
+	u16 val;
+
+	netif_wake_queue(dev);
+	val = lp->a->read_csr(ioaddr, CSR3);
+	val &= 0x00ff;
+	lp->a->write_csr(ioaddr, CSR3, val);
+	napi_enable(&lp->napi);
+}
+
+/*
+ * Allocate space for the new sized tx ring.
+ * Free old resources
+ * Save new resources.
+ * Any failure keeps old resources.
+ * Must be called with lp->lock held.
+ */
+static void pcnet32_realloc_tx_ring(struct net_device *dev,
+				    struct pcnet32_private *lp,
+				    unsigned int size)
+{
+	dma_addr_t new_ring_dma_addr;
+	dma_addr_t *new_dma_addr_list;
+	struct pcnet32_tx_head *new_tx_ring;
+	struct sk_buff **new_skb_list;
+
+	pcnet32_purge_tx_ring(dev);
+
+	new_tx_ring = pci_alloc_consistent(lp->pci_dev,
+					   sizeof(struct pcnet32_tx_head) *
+					   (1 << size),
+					   &new_ring_dma_addr);
+	if (new_tx_ring == NULL) {
+		netif_err(lp, drv, dev, "Consistent memory allocation failed\n");
+		return;
+	}
+	memset(new_tx_ring, 0, sizeof(struct pcnet32_tx_head) * (1 << size));
+
+	new_dma_addr_list = kcalloc((1 << size), sizeof(dma_addr_t),
+				GFP_ATOMIC);
+	if (!new_dma_addr_list) {
+		netif_err(lp, drv, dev, "Memory allocation failed\n");
+		goto free_new_tx_ring;
+	}
+
+	new_skb_list = kcalloc((1 << size), sizeof(struct sk_buff *),
+				GFP_ATOMIC);
+	if (!new_skb_list) {
+		netif_err(lp, drv, dev, "Memory allocation failed\n");
+		goto free_new_lists;
+	}
+
+	kfree(lp->tx_skbuff);
+	kfree(lp->tx_dma_addr);
+	pci_free_consistent(lp->pci_dev,
+			    sizeof(struct pcnet32_tx_head) *
+			    lp->tx_ring_size, lp->tx_ring,
+			    lp->tx_ring_dma_addr);
+
+	lp->tx_ring_size = (1 << size);
+	lp->tx_mod_mask = lp->tx_ring_size - 1;
+	lp->tx_len_bits = (size << 12);
+	lp->tx_ring = new_tx_ring;
+	lp->tx_ring_dma_addr = new_ring_dma_addr;
+	lp->tx_dma_addr = new_dma_addr_list;
+	lp->tx_skbuff = new_skb_list;
+	return;
+
+free_new_lists:
+	kfree(new_dma_addr_list);
+free_new_tx_ring:
+	pci_free_consistent(lp->pci_dev,
+			    sizeof(struct pcnet32_tx_head) *
+			    (1 << size),
+			    new_tx_ring,
+			    new_ring_dma_addr);
+}
+
+/*
+ * Allocate space for the new sized rx ring.
+ * Re-use old receive buffers.
+ *   alloc extra buffers
+ *   free unneeded buffers
+ *   free unneeded buffers
+ * Save new resources.
+ * Any failure keeps old resources.
+ * Must be called with lp->lock held.
+ */
+static void pcnet32_realloc_rx_ring(struct net_device *dev,
+				    struct pcnet32_private *lp,
+				    unsigned int size)
+{
+	dma_addr_t new_ring_dma_addr;
+	dma_addr_t *new_dma_addr_list;
+	struct pcnet32_rx_head *new_rx_ring;
+	struct sk_buff **new_skb_list;
+	int new, overlap;
+
+	new_rx_ring = pci_alloc_consistent(lp->pci_dev,
+					   sizeof(struct pcnet32_rx_head) *
+					   (1 << size),
+					   &new_ring_dma_addr);
+	if (new_rx_ring == NULL) {
+		netif_err(lp, drv, dev, "Consistent memory allocation failed\n");
+		return;
+	}
+	memset(new_rx_ring, 0, sizeof(struct pcnet32_rx_head) * (1 << size));
+
+	new_dma_addr_list = kcalloc((1 << size), sizeof(dma_addr_t),
+				GFP_ATOMIC);
+	if (!new_dma_addr_list) {
+		netif_err(lp, drv, dev, "Memory allocation failed\n");
+		goto free_new_rx_ring;
+	}
+
+	new_skb_list = kcalloc((1 << size), sizeof(struct sk_buff *),
+				GFP_ATOMIC);
+	if (!new_skb_list) {
+		netif_err(lp, drv, dev, "Memory allocation failed\n");
+		goto free_new_lists;
+	}
+
+	/* first copy the current receive buffers */
+	overlap = min(size, lp->rx_ring_size);
+	for (new = 0; new < overlap; new++) {
+		new_rx_ring[new] = lp->rx_ring[new];
+		new_dma_addr_list[new] = lp->rx_dma_addr[new];
+		new_skb_list[new] = lp->rx_skbuff[new];
+	}
+	/* now allocate any new buffers needed */
+	for (; new < size; new++) {
+		struct sk_buff *rx_skbuff;
+		new_skb_list[new] = dev_alloc_skb(PKT_BUF_SKB);
+		rx_skbuff = new_skb_list[new];
+		if (!rx_skbuff) {
+			/* keep the original lists and buffers */
+			netif_err(lp, drv, dev, "%s dev_alloc_skb failed\n",
+				  __func__);
+			goto free_all_new;
+		}
+		skb_reserve(rx_skbuff, NET_IP_ALIGN);
+
+		new_dma_addr_list[new] =
+			    pci_map_single(lp->pci_dev, rx_skbuff->data,
+					   PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
+		new_rx_ring[new].base = cpu_to_le32(new_dma_addr_list[new]);
+		new_rx_ring[new].buf_length = cpu_to_le16(NEG_BUF_SIZE);
+		new_rx_ring[new].status = cpu_to_le16(0x8000);
+	}
+	/* and free any unneeded buffers */
+	for (; new < lp->rx_ring_size; new++) {
+		if (lp->rx_skbuff[new]) {
+			pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[new],
+					 PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
+			dev_kfree_skb(lp->rx_skbuff[new]);
+		}
+	}
+
+	kfree(lp->rx_skbuff);
+	kfree(lp->rx_dma_addr);
+	pci_free_consistent(lp->pci_dev,
+			    sizeof(struct pcnet32_rx_head) *
+			    lp->rx_ring_size, lp->rx_ring,
+			    lp->rx_ring_dma_addr);
+
+	lp->rx_ring_size = (1 << size);
+	lp->rx_mod_mask = lp->rx_ring_size - 1;
+	lp->rx_len_bits = (size << 4);
+	lp->rx_ring = new_rx_ring;
+	lp->rx_ring_dma_addr = new_ring_dma_addr;
+	lp->rx_dma_addr = new_dma_addr_list;
+	lp->rx_skbuff = new_skb_list;
+	return;
+
+free_all_new:
+	while (--new >= lp->rx_ring_size) {
+		if (new_skb_list[new]) {
+			pci_unmap_single(lp->pci_dev, new_dma_addr_list[new],
+					 PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
+			dev_kfree_skb(new_skb_list[new]);
+		}
+	}
+	kfree(new_skb_list);
+free_new_lists:
+	kfree(new_dma_addr_list);
+free_new_rx_ring:
+	pci_free_consistent(lp->pci_dev,
+			    sizeof(struct pcnet32_rx_head) *
+			    (1 << size),
+			    new_rx_ring,
+			    new_ring_dma_addr);
+}
+
+static void pcnet32_purge_rx_ring(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	int i;
+
+	/* free all allocated skbuffs */
+	for (i = 0; i < lp->rx_ring_size; i++) {
+		lp->rx_ring[i].status = 0;	/* CPU owns buffer */
+		wmb();		/* Make sure adapter sees owner change */
+		if (lp->rx_skbuff[i]) {
+			pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i],
+					 PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
+			dev_kfree_skb_any(lp->rx_skbuff[i]);
+		}
+		lp->rx_skbuff[i] = NULL;
+		lp->rx_dma_addr[i] = 0;
+	}
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void pcnet32_poll_controller(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	pcnet32_interrupt(0, dev);
+	enable_irq(dev->irq);
+}
+#endif
+
+static int pcnet32_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	unsigned long flags;
+	int r = -EOPNOTSUPP;
+
+	if (lp->mii) {
+		spin_lock_irqsave(&lp->lock, flags);
+		mii_ethtool_gset(&lp->mii_if, cmd);
+		spin_unlock_irqrestore(&lp->lock, flags);
+		r = 0;
+	}
+	return r;
+}
+
+static int pcnet32_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	unsigned long flags;
+	int r = -EOPNOTSUPP;
+
+	if (lp->mii) {
+		spin_lock_irqsave(&lp->lock, flags);
+		r = mii_ethtool_sset(&lp->mii_if, cmd);
+		spin_unlock_irqrestore(&lp->lock, flags);
+	}
+	return r;
+}
+
+static void pcnet32_get_drvinfo(struct net_device *dev,
+				struct ethtool_drvinfo *info)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	if (lp->pci_dev)
+		strcpy(info->bus_info, pci_name(lp->pci_dev));
+	else
+		sprintf(info->bus_info, "VLB 0x%lx", dev->base_addr);
+}
+
+static u32 pcnet32_get_link(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	unsigned long flags;
+	int r;
+
+	spin_lock_irqsave(&lp->lock, flags);
+	if (lp->mii) {
+		r = mii_link_ok(&lp->mii_if);
+	} else if (lp->chip_version >= PCNET32_79C970A) {
+		ulong ioaddr = dev->base_addr;	/* card base I/O address */
+		r = (lp->a->read_bcr(ioaddr, 4) != 0xc0);
+	} else {	/* can not detect link on really old chips */
+		r = 1;
+	}
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return r;
+}
+
+static u32 pcnet32_get_msglevel(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	return lp->msg_enable;
+}
+
+static void pcnet32_set_msglevel(struct net_device *dev, u32 value)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	lp->msg_enable = value;
+}
+
+static int pcnet32_nway_reset(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	unsigned long flags;
+	int r = -EOPNOTSUPP;
+
+	if (lp->mii) {
+		spin_lock_irqsave(&lp->lock, flags);
+		r = mii_nway_restart(&lp->mii_if);
+		spin_unlock_irqrestore(&lp->lock, flags);
+	}
+	return r;
+}
+
+static void pcnet32_get_ringparam(struct net_device *dev,
+				  struct ethtool_ringparam *ering)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+
+	ering->tx_max_pending = TX_MAX_RING_SIZE;
+	ering->tx_pending = lp->tx_ring_size;
+	ering->rx_max_pending = RX_MAX_RING_SIZE;
+	ering->rx_pending = lp->rx_ring_size;
+}
+
+static int pcnet32_set_ringparam(struct net_device *dev,
+				 struct ethtool_ringparam *ering)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	unsigned long flags;
+	unsigned int size;
+	ulong ioaddr = dev->base_addr;
+	int i;
+
+	if (ering->rx_mini_pending || ering->rx_jumbo_pending)
+		return -EINVAL;
+
+	if (netif_running(dev))
+		pcnet32_netif_stop(dev);
+
+	spin_lock_irqsave(&lp->lock, flags);
+	lp->a->write_csr(ioaddr, CSR0, CSR0_STOP);	/* stop the chip */
+
+	size = min(ering->tx_pending, (unsigned int)TX_MAX_RING_SIZE);
+
+	/* set the minimum ring size to 4, to allow the loopback test to work
+	 * unchanged.
+	 */
+	for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) {
+		if (size <= (1 << i))
+			break;
+	}
+	if ((1 << i) != lp->tx_ring_size)
+		pcnet32_realloc_tx_ring(dev, lp, i);
+
+	size = min(ering->rx_pending, (unsigned int)RX_MAX_RING_SIZE);
+	for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) {
+		if (size <= (1 << i))
+			break;
+	}
+	if ((1 << i) != lp->rx_ring_size)
+		pcnet32_realloc_rx_ring(dev, lp, i);
+
+	lp->napi.weight = lp->rx_ring_size / 2;
+
+	if (netif_running(dev)) {
+		pcnet32_netif_start(dev);
+		pcnet32_restart(dev, CSR0_NORMAL);
+	}
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	netif_info(lp, drv, dev, "Ring Param Settings: RX: %d, TX: %d\n",
+		   lp->rx_ring_size, lp->tx_ring_size);
+
+	return 0;
+}
+
+static void pcnet32_get_strings(struct net_device *dev, u32 stringset,
+				u8 *data)
+{
+	memcpy(data, pcnet32_gstrings_test, sizeof(pcnet32_gstrings_test));
+}
+
+static int pcnet32_get_sset_count(struct net_device *dev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_TEST:
+		return PCNET32_TEST_LEN;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void pcnet32_ethtool_test(struct net_device *dev,
+				 struct ethtool_test *test, u64 * data)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	int rc;
+
+	if (test->flags == ETH_TEST_FL_OFFLINE) {
+		rc = pcnet32_loopback_test(dev, data);
+		if (rc) {
+			netif_printk(lp, hw, KERN_DEBUG, dev,
+				     "Loopback test failed\n");
+			test->flags |= ETH_TEST_FL_FAILED;
+		} else
+			netif_printk(lp, hw, KERN_DEBUG, dev,
+				     "Loopback test passed\n");
+	} else
+		netif_printk(lp, hw, KERN_DEBUG, dev,
+			     "No tests to run (specify 'Offline' on ethtool)\n");
+}				/* end pcnet32_ethtool_test */
+
+static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	const struct pcnet32_access *a = lp->a;	/* access to registers */
+	ulong ioaddr = dev->base_addr;	/* card base I/O address */
+	struct sk_buff *skb;	/* sk buff */
+	int x, i;		/* counters */
+	int numbuffs = 4;	/* number of TX/RX buffers and descs */
+	u16 status = 0x8300;	/* TX ring status */
+	__le16 teststatus;	/* test of ring status */
+	int rc;			/* return code */
+	int size;		/* size of packets */
+	unsigned char *packet;	/* source packet data */
+	static const int data_len = 60;	/* length of source packets */
+	unsigned long flags;
+	unsigned long ticks;
+
+	rc = 1;			/* default to fail */
+
+	if (netif_running(dev))
+		pcnet32_netif_stop(dev);
+
+	spin_lock_irqsave(&lp->lock, flags);
+	lp->a->write_csr(ioaddr, CSR0, CSR0_STOP);	/* stop the chip */
+
+	numbuffs = min(numbuffs, (int)min(lp->rx_ring_size, lp->tx_ring_size));
+
+	/* Reset the PCNET32 */
+	lp->a->reset(ioaddr);
+	lp->a->write_csr(ioaddr, CSR4, 0x0915);	/* auto tx pad */
+
+	/* switch pcnet32 to 32bit mode */
+	lp->a->write_bcr(ioaddr, 20, 2);
+
+	/* purge & init rings but don't actually restart */
+	pcnet32_restart(dev, 0x0000);
+
+	lp->a->write_csr(ioaddr, CSR0, CSR0_STOP);	/* Set STOP bit */
+
+	/* Initialize Transmit buffers. */
+	size = data_len + 15;
+	for (x = 0; x < numbuffs; x++) {
+		skb = dev_alloc_skb(size);
+		if (!skb) {
+			netif_printk(lp, hw, KERN_DEBUG, dev,
+				     "Cannot allocate skb at line: %d!\n",
+				     __LINE__);
+			goto clean_up;
+		}
+		packet = skb->data;
+		skb_put(skb, size);	/* create space for data */
+		lp->tx_skbuff[x] = skb;
+		lp->tx_ring[x].length = cpu_to_le16(-skb->len);
+		lp->tx_ring[x].misc = 0;
+
+		/* put DA and SA into the skb */
+		for (i = 0; i < 6; i++)
+			*packet++ = dev->dev_addr[i];
+		for (i = 0; i < 6; i++)
+			*packet++ = dev->dev_addr[i];
+		/* type */
+		*packet++ = 0x08;
+		*packet++ = 0x06;
+		/* packet number */
+		*packet++ = x;
+		/* fill packet with data */
+		for (i = 0; i < data_len; i++)
+			*packet++ = i;
+
+		lp->tx_dma_addr[x] =
+			pci_map_single(lp->pci_dev, skb->data, skb->len,
+				       PCI_DMA_TODEVICE);
+		lp->tx_ring[x].base = cpu_to_le32(lp->tx_dma_addr[x]);
+		wmb();	/* Make sure owner changes after all others are visible */
+		lp->tx_ring[x].status = cpu_to_le16(status);
+	}
+
+	x = a->read_bcr(ioaddr, 32);	/* set internal loopback in BCR32 */
+	a->write_bcr(ioaddr, 32, x | 0x0002);
+
+	/* set int loopback in CSR15 */
+	x = a->read_csr(ioaddr, CSR15) & 0xfffc;
+	lp->a->write_csr(ioaddr, CSR15, x | 0x0044);
+
+	teststatus = cpu_to_le16(0x8000);
+	lp->a->write_csr(ioaddr, CSR0, CSR0_START);	/* Set STRT bit */
+
+	/* Check status of descriptors */
+	for (x = 0; x < numbuffs; x++) {
+		ticks = 0;
+		rmb();
+		while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) {
+			spin_unlock_irqrestore(&lp->lock, flags);
+			msleep(1);
+			spin_lock_irqsave(&lp->lock, flags);
+			rmb();
+			ticks++;
+		}
+		if (ticks == 200) {
+			netif_err(lp, hw, dev, "Desc %d failed to reset!\n", x);
+			break;
+		}
+	}
+
+	lp->a->write_csr(ioaddr, CSR0, CSR0_STOP);	/* Set STOP bit */
+	wmb();
+	if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) {
+		netdev_printk(KERN_DEBUG, dev, "RX loopback packets:\n");
+
+		for (x = 0; x < numbuffs; x++) {
+			netdev_printk(KERN_DEBUG, dev, "Packet %d: ", x);
+			skb = lp->rx_skbuff[x];
+			for (i = 0; i < size; i++)
+				pr_cont(" %02x", *(skb->data + i));
+			pr_cont("\n");
+		}
+	}
+
+	x = 0;
+	rc = 0;
+	while (x < numbuffs && !rc) {
+		skb = lp->rx_skbuff[x];
+		packet = lp->tx_skbuff[x]->data;
+		for (i = 0; i < size; i++) {
+			if (*(skb->data + i) != packet[i]) {
+				netif_printk(lp, hw, KERN_DEBUG, dev,
+					     "Error in compare! %2x - %02x %02x\n",
+					     i, *(skb->data + i), packet[i]);
+				rc = 1;
+				break;
+			}
+		}
+		x++;
+	}
+
+clean_up:
+	*data1 = rc;
+	pcnet32_purge_tx_ring(dev);
+
+	x = a->read_csr(ioaddr, CSR15);
+	a->write_csr(ioaddr, CSR15, (x & ~0x0044));	/* reset bits 6 and 2 */
+
+	x = a->read_bcr(ioaddr, 32);	/* reset internal loopback */
+	a->write_bcr(ioaddr, 32, (x & ~0x0002));
+
+	if (netif_running(dev)) {
+		pcnet32_netif_start(dev);
+		pcnet32_restart(dev, CSR0_NORMAL);
+	} else {
+		pcnet32_purge_rx_ring(dev);
+		lp->a->write_bcr(ioaddr, 20, 4);	/* return to 16bit mode */
+	}
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return rc;
+}				/* end pcnet32_loopback_test  */
+
+static int pcnet32_set_phys_id(struct net_device *dev,
+			       enum ethtool_phys_id_state state)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	const struct pcnet32_access *a = lp->a;
+	ulong ioaddr = dev->base_addr;
+	unsigned long flags;
+	int i;
+
+	switch (state) {
+	case ETHTOOL_ID_ACTIVE:
+		/* Save the current value of the bcrs */
+		spin_lock_irqsave(&lp->lock, flags);
+		for (i = 4; i < 8; i++)
+			lp->save_regs[i - 4] = a->read_bcr(ioaddr, i);
+		spin_unlock_irqrestore(&lp->lock, flags);
+		return 2;	/* cycle on/off twice per second */
+
+	case ETHTOOL_ID_ON:
+	case ETHTOOL_ID_OFF:
+		/* Blink the led */
+		spin_lock_irqsave(&lp->lock, flags);
+		for (i = 4; i < 8; i++)
+			a->write_bcr(ioaddr, i, a->read_bcr(ioaddr, i) ^ 0x4000);
+		spin_unlock_irqrestore(&lp->lock, flags);
+		break;
+
+	case ETHTOOL_ID_INACTIVE:
+		/* Restore the original value of the bcrs */
+		spin_lock_irqsave(&lp->lock, flags);
+		for (i = 4; i < 8; i++)
+			a->write_bcr(ioaddr, i, lp->save_regs[i - 4]);
+		spin_unlock_irqrestore(&lp->lock, flags);
+	}
+	return 0;
+}
+
+/*
+ * lp->lock must be held.
+ */
+static int pcnet32_suspend(struct net_device *dev, unsigned long *flags,
+		int can_sleep)
+{
+	int csr5;
+	struct pcnet32_private *lp = netdev_priv(dev);
+	const struct pcnet32_access *a = lp->a;
+	ulong ioaddr = dev->base_addr;
+	int ticks;
+
+	/* really old chips have to be stopped. */
+	if (lp->chip_version < PCNET32_79C970A)
+		return 0;
+
+	/* set SUSPEND (SPND) - CSR5 bit 0 */
+	csr5 = a->read_csr(ioaddr, CSR5);
+	a->write_csr(ioaddr, CSR5, csr5 | CSR5_SUSPEND);
+
+	/* poll waiting for bit to be set */
+	ticks = 0;
+	while (!(a->read_csr(ioaddr, CSR5) & CSR5_SUSPEND)) {
+		spin_unlock_irqrestore(&lp->lock, *flags);
+		if (can_sleep)
+			msleep(1);
+		else
+			mdelay(1);
+		spin_lock_irqsave(&lp->lock, *flags);
+		ticks++;
+		if (ticks > 200) {
+			netif_printk(lp, hw, KERN_DEBUG, dev,
+				     "Error getting into suspend!\n");
+			return 0;
+		}
+	}
+	return 1;
+}
+
+/*
+ * process one receive descriptor entry
+ */
+
+static void pcnet32_rx_entry(struct net_device *dev,
+			     struct pcnet32_private *lp,
+			     struct pcnet32_rx_head *rxp,
+			     int entry)
+{
+	int status = (short)le16_to_cpu(rxp->status) >> 8;
+	int rx_in_place = 0;
+	struct sk_buff *skb;
+	short pkt_len;
+
+	if (status != 0x03) {	/* There was an error. */
+		/*
+		 * There is a tricky error noted by John Murphy,
+		 * <murf@perftech.com> to Russ Nelson: Even with full-sized
+		 * buffers it's possible for a jabber packet to use two
+		 * buffers, with only the last correctly noting the error.
+		 */
+		if (status & 0x01)	/* Only count a general error at the */
+			dev->stats.rx_errors++;	/* end of a packet. */
+		if (status & 0x20)
+			dev->stats.rx_frame_errors++;
+		if (status & 0x10)
+			dev->stats.rx_over_errors++;
+		if (status & 0x08)
+			dev->stats.rx_crc_errors++;
+		if (status & 0x04)
+			dev->stats.rx_fifo_errors++;
+		return;
+	}
+
+	pkt_len = (le32_to_cpu(rxp->msg_length) & 0xfff) - 4;
+
+	/* Discard oversize frames. */
+	if (unlikely(pkt_len > PKT_BUF_SIZE)) {
+		netif_err(lp, drv, dev, "Impossible packet size %d!\n",
+			  pkt_len);
+		dev->stats.rx_errors++;
+		return;
+	}
+	if (pkt_len < 60) {
+		netif_err(lp, rx_err, dev, "Runt packet!\n");
+		dev->stats.rx_errors++;
+		return;
+	}
+
+	if (pkt_len > rx_copybreak) {
+		struct sk_buff *newskb;
+
+		newskb = dev_alloc_skb(PKT_BUF_SKB);
+		if (newskb) {
+			skb_reserve(newskb, NET_IP_ALIGN);
+			skb = lp->rx_skbuff[entry];
+			pci_unmap_single(lp->pci_dev,
+					 lp->rx_dma_addr[entry],
+					 PKT_BUF_SIZE,
+					 PCI_DMA_FROMDEVICE);
+			skb_put(skb, pkt_len);
+			lp->rx_skbuff[entry] = newskb;
+			lp->rx_dma_addr[entry] =
+					    pci_map_single(lp->pci_dev,
+							   newskb->data,
+							   PKT_BUF_SIZE,
+							   PCI_DMA_FROMDEVICE);
+			rxp->base = cpu_to_le32(lp->rx_dma_addr[entry]);
+			rx_in_place = 1;
+		} else
+			skb = NULL;
+	} else
+		skb = dev_alloc_skb(pkt_len + NET_IP_ALIGN);
+
+	if (skb == NULL) {
+		netif_err(lp, drv, dev, "Memory squeeze, dropping packet\n");
+		dev->stats.rx_dropped++;
+		return;
+	}
+	if (!rx_in_place) {
+		skb_reserve(skb, NET_IP_ALIGN);
+		skb_put(skb, pkt_len);	/* Make room */
+		pci_dma_sync_single_for_cpu(lp->pci_dev,
+					    lp->rx_dma_addr[entry],
+					    pkt_len,
+					    PCI_DMA_FROMDEVICE);
+		skb_copy_to_linear_data(skb,
+				 (unsigned char *)(lp->rx_skbuff[entry]->data),
+				 pkt_len);
+		pci_dma_sync_single_for_device(lp->pci_dev,
+					       lp->rx_dma_addr[entry],
+					       pkt_len,
+					       PCI_DMA_FROMDEVICE);
+	}
+	dev->stats.rx_bytes += skb->len;
+	skb->protocol = eth_type_trans(skb, dev);
+	netif_receive_skb(skb);
+	dev->stats.rx_packets++;
+}
+
+static int pcnet32_rx(struct net_device *dev, int budget)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	int entry = lp->cur_rx & lp->rx_mod_mask;
+	struct pcnet32_rx_head *rxp = &lp->rx_ring[entry];
+	int npackets = 0;
+
+	/* If we own the next entry, it's a new packet. Send it up. */
+	while (npackets < budget && (short)le16_to_cpu(rxp->status) >= 0) {
+		pcnet32_rx_entry(dev, lp, rxp, entry);
+		npackets += 1;
+		/*
+		 * The docs say that the buffer length isn't touched, but Andrew
+		 * Boyd of QNX reports that some revs of the 79C965 clear it.
+		 */
+		rxp->buf_length = cpu_to_le16(NEG_BUF_SIZE);
+		wmb();	/* Make sure owner changes after others are visible */
+		rxp->status = cpu_to_le16(0x8000);
+		entry = (++lp->cur_rx) & lp->rx_mod_mask;
+		rxp = &lp->rx_ring[entry];
+	}
+
+	return npackets;
+}
+
+static int pcnet32_tx(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	unsigned int dirty_tx = lp->dirty_tx;
+	int delta;
+	int must_restart = 0;
+
+	while (dirty_tx != lp->cur_tx) {
+		int entry = dirty_tx & lp->tx_mod_mask;
+		int status = (short)le16_to_cpu(lp->tx_ring[entry].status);
+
+		if (status < 0)
+			break;	/* It still hasn't been Txed */
+
+		lp->tx_ring[entry].base = 0;
+
+		if (status & 0x4000) {
+			/* There was a major error, log it. */
+			int err_status = le32_to_cpu(lp->tx_ring[entry].misc);
+			dev->stats.tx_errors++;
+			netif_err(lp, tx_err, dev,
+				  "Tx error status=%04x err_status=%08x\n",
+				  status, err_status);
+			if (err_status & 0x04000000)
+				dev->stats.tx_aborted_errors++;
+			if (err_status & 0x08000000)
+				dev->stats.tx_carrier_errors++;
+			if (err_status & 0x10000000)
+				dev->stats.tx_window_errors++;
+#ifndef DO_DXSUFLO
+			if (err_status & 0x40000000) {
+				dev->stats.tx_fifo_errors++;
+				/* Ackk!  On FIFO errors the Tx unit is turned off! */
+				/* Remove this verbosity later! */
+				netif_err(lp, tx_err, dev, "Tx FIFO error!\n");
+				must_restart = 1;
+			}
+#else
+			if (err_status & 0x40000000) {
+				dev->stats.tx_fifo_errors++;
+				if (!lp->dxsuflo) {	/* If controller doesn't recover ... */
+					/* Ackk!  On FIFO errors the Tx unit is turned off! */
+					/* Remove this verbosity later! */
+					netif_err(lp, tx_err, dev, "Tx FIFO error!\n");
+					must_restart = 1;
+				}
+			}
+#endif
+		} else {
+			if (status & 0x1800)
+				dev->stats.collisions++;
+			dev->stats.tx_packets++;
+		}
+
+		/* We must free the original skb */
+		if (lp->tx_skbuff[entry]) {
+			pci_unmap_single(lp->pci_dev,
+					 lp->tx_dma_addr[entry],
+					 lp->tx_skbuff[entry]->
+					 len, PCI_DMA_TODEVICE);
+			dev_kfree_skb_any(lp->tx_skbuff[entry]);
+			lp->tx_skbuff[entry] = NULL;
+			lp->tx_dma_addr[entry] = 0;
+		}
+		dirty_tx++;
+	}
+
+	delta = (lp->cur_tx - dirty_tx) & (lp->tx_mod_mask + lp->tx_ring_size);
+	if (delta > lp->tx_ring_size) {
+		netif_err(lp, drv, dev, "out-of-sync dirty pointer, %d vs. %d, full=%d\n",
+			  dirty_tx, lp->cur_tx, lp->tx_full);
+		dirty_tx += lp->tx_ring_size;
+		delta -= lp->tx_ring_size;
+	}
+
+	if (lp->tx_full &&
+	    netif_queue_stopped(dev) &&
+	    delta < lp->tx_ring_size - 2) {
+		/* The ring is no longer full, clear tbusy. */
+		lp->tx_full = 0;
+		netif_wake_queue(dev);
+	}
+	lp->dirty_tx = dirty_tx;
+
+	return must_restart;
+}
+
+static int pcnet32_poll(struct napi_struct *napi, int budget)
+{
+	struct pcnet32_private *lp = container_of(napi, struct pcnet32_private, napi);
+	struct net_device *dev = lp->dev;
+	unsigned long ioaddr = dev->base_addr;
+	unsigned long flags;
+	int work_done;
+	u16 val;
+
+	work_done = pcnet32_rx(dev, budget);
+
+	spin_lock_irqsave(&lp->lock, flags);
+	if (pcnet32_tx(dev)) {
+		/* reset the chip to clear the error condition, then restart */
+		lp->a->reset(ioaddr);
+		lp->a->write_csr(ioaddr, CSR4, 0x0915);	/* auto tx pad */
+		pcnet32_restart(dev, CSR0_START);
+		netif_wake_queue(dev);
+	}
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	if (work_done < budget) {
+		spin_lock_irqsave(&lp->lock, flags);
+
+		__napi_complete(napi);
+
+		/* clear interrupt masks */
+		val = lp->a->read_csr(ioaddr, CSR3);
+		val &= 0x00ff;
+		lp->a->write_csr(ioaddr, CSR3, val);
+
+		/* Set interrupt enable. */
+		lp->a->write_csr(ioaddr, CSR0, CSR0_INTEN);
+
+		spin_unlock_irqrestore(&lp->lock, flags);
+	}
+	return work_done;
+}
+
+#define PCNET32_REGS_PER_PHY	32
+#define PCNET32_MAX_PHYS	32
+static int pcnet32_get_regs_len(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	int j = lp->phycount * PCNET32_REGS_PER_PHY;
+
+	return (PCNET32_NUM_REGS + j) * sizeof(u16);
+}
+
+static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+			     void *ptr)
+{
+	int i, csr0;
+	u16 *buff = ptr;
+	struct pcnet32_private *lp = netdev_priv(dev);
+	const struct pcnet32_access *a = lp->a;
+	ulong ioaddr = dev->base_addr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	csr0 = a->read_csr(ioaddr, CSR0);
+	if (!(csr0 & CSR0_STOP))	/* If not stopped */
+		pcnet32_suspend(dev, &flags, 1);
+
+	/* read address PROM */
+	for (i = 0; i < 16; i += 2)
+		*buff++ = inw(ioaddr + i);
+
+	/* read control and status registers */
+	for (i = 0; i < 90; i++)
+		*buff++ = a->read_csr(ioaddr, i);
+
+	*buff++ = a->read_csr(ioaddr, 112);
+	*buff++ = a->read_csr(ioaddr, 114);
+
+	/* read bus configuration registers */
+	for (i = 0; i < 30; i++)
+		*buff++ = a->read_bcr(ioaddr, i);
+
+	*buff++ = 0;		/* skip bcr30 so as not to hang 79C976 */
+
+	for (i = 31; i < 36; i++)
+		*buff++ = a->read_bcr(ioaddr, i);
+
+	/* read mii phy registers */
+	if (lp->mii) {
+		int j;
+		for (j = 0; j < PCNET32_MAX_PHYS; j++) {
+			if (lp->phymask & (1 << j)) {
+				for (i = 0; i < PCNET32_REGS_PER_PHY; i++) {
+					lp->a->write_bcr(ioaddr, 33,
+							(j << 5) | i);
+					*buff++ = lp->a->read_bcr(ioaddr, 34);
+				}
+			}
+		}
+	}
+
+	if (!(csr0 & CSR0_STOP)) {	/* If not stopped */
+		int csr5;
+
+		/* clear SUSPEND (SPND) - CSR5 bit 0 */
+		csr5 = a->read_csr(ioaddr, CSR5);
+		a->write_csr(ioaddr, CSR5, csr5 & (~CSR5_SUSPEND));
+	}
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+}
+
+static const struct ethtool_ops pcnet32_ethtool_ops = {
+	.get_settings		= pcnet32_get_settings,
+	.set_settings		= pcnet32_set_settings,
+	.get_drvinfo		= pcnet32_get_drvinfo,
+	.get_msglevel		= pcnet32_get_msglevel,
+	.set_msglevel		= pcnet32_set_msglevel,
+	.nway_reset		= pcnet32_nway_reset,
+	.get_link		= pcnet32_get_link,
+	.get_ringparam		= pcnet32_get_ringparam,
+	.set_ringparam		= pcnet32_set_ringparam,
+	.get_strings		= pcnet32_get_strings,
+	.self_test		= pcnet32_ethtool_test,
+	.set_phys_id		= pcnet32_set_phys_id,
+	.get_regs_len		= pcnet32_get_regs_len,
+	.get_regs		= pcnet32_get_regs,
+	.get_sset_count		= pcnet32_get_sset_count,
+};
+
+/* only probes for non-PCI devices, the rest are handled by
+ * pci_register_driver via pcnet32_probe_pci */
+
+static void __devinit pcnet32_probe_vlbus(unsigned int *pcnet32_portlist)
+{
+	unsigned int *port, ioaddr;
+
+	/* search for PCnet32 VLB cards at known addresses */
+	for (port = pcnet32_portlist; (ioaddr = *port); port++) {
+		if (request_region
+		    (ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_vlbus")) {
+			/* check if there is really a pcnet chip on that ioaddr */
+			if ((inb(ioaddr + 14) == 0x57) &&
+			    (inb(ioaddr + 15) == 0x57)) {
+				pcnet32_probe1(ioaddr, 0, NULL);
+			} else {
+				release_region(ioaddr, PCNET32_TOTAL_SIZE);
+			}
+		}
+	}
+}
+
+static int __devinit
+pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	unsigned long ioaddr;
+	int err;
+
+	err = pci_enable_device(pdev);
+	if (err < 0) {
+		if (pcnet32_debug & NETIF_MSG_PROBE)
+			pr_err("failed to enable device -- err=%d\n", err);
+		return err;
+	}
+	pci_set_master(pdev);
+
+	ioaddr = pci_resource_start(pdev, 0);
+	if (!ioaddr) {
+		if (pcnet32_debug & NETIF_MSG_PROBE)
+			pr_err("card has no PCI IO resources, aborting\n");
+		return -ENODEV;
+	}
+
+	if (!pci_dma_supported(pdev, PCNET32_DMA_MASK)) {
+		if (pcnet32_debug & NETIF_MSG_PROBE)
+			pr_err("architecture does not support 32bit PCI busmaster DMA\n");
+		return -ENODEV;
+	}
+	if (!request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci")) {
+		if (pcnet32_debug & NETIF_MSG_PROBE)
+			pr_err("io address range already allocated\n");
+		return -EBUSY;
+	}
+
+	err = pcnet32_probe1(ioaddr, 1, pdev);
+	if (err < 0)
+		pci_disable_device(pdev);
+
+	return err;
+}
+
+static const struct net_device_ops pcnet32_netdev_ops = {
+	.ndo_open		= pcnet32_open,
+	.ndo_stop 		= pcnet32_close,
+	.ndo_start_xmit		= pcnet32_start_xmit,
+	.ndo_tx_timeout		= pcnet32_tx_timeout,
+	.ndo_get_stats		= pcnet32_get_stats,
+	.ndo_set_rx_mode	= pcnet32_set_multicast_list,
+	.ndo_do_ioctl		= pcnet32_ioctl,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= pcnet32_poll_controller,
+#endif
+};
+
+/* pcnet32_probe1
+ *  Called from both pcnet32_probe_vlbus and pcnet_probe_pci.
+ *  pdev will be NULL when called from pcnet32_probe_vlbus.
+ */
+static int __devinit
+pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
+{
+	struct pcnet32_private *lp;
+	int i, media;
+	int fdx, mii, fset, dxsuflo;
+	int chip_version;
+	char *chipname;
+	struct net_device *dev;
+	const struct pcnet32_access *a = NULL;
+	u8 promaddr[6];
+	int ret = -ENODEV;
+
+	/* reset the chip */
+	pcnet32_wio_reset(ioaddr);
+
+	/* NOTE: 16-bit check is first, otherwise some older PCnet chips fail */
+	if (pcnet32_wio_read_csr(ioaddr, 0) == 4 && pcnet32_wio_check(ioaddr)) {
+		a = &pcnet32_wio;
+	} else {
+		pcnet32_dwio_reset(ioaddr);
+		if (pcnet32_dwio_read_csr(ioaddr, 0) == 4 &&
+		    pcnet32_dwio_check(ioaddr)) {
+			a = &pcnet32_dwio;
+		} else {
+			if (pcnet32_debug & NETIF_MSG_PROBE)
+				pr_err("No access methods\n");
+			goto err_release_region;
+		}
+	}
+
+	chip_version =
+	    a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr, 89) << 16);
+	if ((pcnet32_debug & NETIF_MSG_PROBE) && (pcnet32_debug & NETIF_MSG_HW))
+		pr_info("  PCnet chip version is %#x\n", chip_version);
+	if ((chip_version & 0xfff) != 0x003) {
+		if (pcnet32_debug & NETIF_MSG_PROBE)
+			pr_info("Unsupported chip version\n");
+		goto err_release_region;
+	}
+
+	/* initialize variables */
+	fdx = mii = fset = dxsuflo = 0;
+	chip_version = (chip_version >> 12) & 0xffff;
+
+	switch (chip_version) {
+	case 0x2420:
+		chipname = "PCnet/PCI 79C970";	/* PCI */
+		break;
+	case 0x2430:
+		if (shared)
+			chipname = "PCnet/PCI 79C970";	/* 970 gives the wrong chip id back */
+		else
+			chipname = "PCnet/32 79C965";	/* 486/VL bus */
+		break;
+	case 0x2621:
+		chipname = "PCnet/PCI II 79C970A";	/* PCI */
+		fdx = 1;
+		break;
+	case 0x2623:
+		chipname = "PCnet/FAST 79C971";	/* PCI */
+		fdx = 1;
+		mii = 1;
+		fset = 1;
+		break;
+	case 0x2624:
+		chipname = "PCnet/FAST+ 79C972";	/* PCI */
+		fdx = 1;
+		mii = 1;
+		fset = 1;
+		break;
+	case 0x2625:
+		chipname = "PCnet/FAST III 79C973";	/* PCI */
+		fdx = 1;
+		mii = 1;
+		break;
+	case 0x2626:
+		chipname = "PCnet/Home 79C978";	/* PCI */
+		fdx = 1;
+		/*
+		 * This is based on specs published at www.amd.com.  This section
+		 * assumes that a card with a 79C978 wants to go into standard
+		 * ethernet mode.  The 79C978 can also go into 1Mb HomePNA mode,
+		 * and the module option homepna=1 can select this instead.
+		 */
+		media = a->read_bcr(ioaddr, 49);
+		media &= ~3;	/* default to 10Mb ethernet */
+		if (cards_found < MAX_UNITS && homepna[cards_found])
+			media |= 1;	/* switch to home wiring mode */
+		if (pcnet32_debug & NETIF_MSG_PROBE)
+			printk(KERN_DEBUG PFX "media set to %sMbit mode\n",
+			       (media & 1) ? "1" : "10");
+		a->write_bcr(ioaddr, 49, media);
+		break;
+	case 0x2627:
+		chipname = "PCnet/FAST III 79C975";	/* PCI */
+		fdx = 1;
+		mii = 1;
+		break;
+	case 0x2628:
+		chipname = "PCnet/PRO 79C976";
+		fdx = 1;
+		mii = 1;
+		break;
+	default:
+		if (pcnet32_debug & NETIF_MSG_PROBE)
+			pr_info("PCnet version %#x, no PCnet32 chip\n",
+				chip_version);
+		goto err_release_region;
+	}
+
+	/*
+	 *  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 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.
+	 */
+
+	if (fset) {
+		a->write_bcr(ioaddr, 18, (a->read_bcr(ioaddr, 18) | 0x0860));
+		a->write_csr(ioaddr, 80,
+			     (a->read_csr(ioaddr, 80) & 0x0C00) | 0x0c00);
+		dxsuflo = 1;
+	}
+
+	dev = alloc_etherdev(sizeof(*lp));
+	if (!dev) {
+		if (pcnet32_debug & NETIF_MSG_PROBE)
+			pr_err("Memory allocation failed\n");
+		ret = -ENOMEM;
+		goto err_release_region;
+	}
+
+	if (pdev)
+		SET_NETDEV_DEV(dev, &pdev->dev);
+
+	if (pcnet32_debug & NETIF_MSG_PROBE)
+		pr_info("%s at %#3lx,", chipname, ioaddr);
+
+	/* In most chips, after a chip reset, the ethernet address is read from the
+	 * station address PROM at the base address and programmed into the
+	 * "Physical Address Registers" CSR12-14.
+	 * As a precautionary measure, we read the PROM values and complain if
+	 * they disagree with the CSRs.  If they miscompare, and the PROM addr
+	 * is valid, then the PROM addr is used.
+	 */
+	for (i = 0; i < 3; i++) {
+		unsigned int val;
+		val = a->read_csr(ioaddr, i + 12) & 0x0ffff;
+		/* There may be endianness issues here. */
+		dev->dev_addr[2 * i] = val & 0x0ff;
+		dev->dev_addr[2 * i + 1] = (val >> 8) & 0x0ff;
+	}
+
+	/* read PROM address and compare with CSR address */
+	for (i = 0; i < 6; i++)
+		promaddr[i] = inb(ioaddr + i);
+
+	if (memcmp(promaddr, dev->dev_addr, 6) ||
+	    !is_valid_ether_addr(dev->dev_addr)) {
+		if (is_valid_ether_addr(promaddr)) {
+			if (pcnet32_debug & NETIF_MSG_PROBE) {
+				pr_cont(" warning: CSR address invalid,\n");
+				pr_info("    using instead PROM address of");
+			}
+			memcpy(dev->dev_addr, promaddr, 6);
+		}
+	}
+	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
+	/* if the ethernet address is not valid, force to 00:00:00:00:00:00 */
+	if (!is_valid_ether_addr(dev->perm_addr))
+		memset(dev->dev_addr, 0, ETH_ALEN);
+
+	if (pcnet32_debug & NETIF_MSG_PROBE) {
+		pr_cont(" %pM", dev->dev_addr);
+
+		/* Version 0x2623 and 0x2624 */
+		if (((chip_version + 1) & 0xfffe) == 0x2624) {
+			i = a->read_csr(ioaddr, 80) & 0x0C00;	/* Check tx_start_pt */
+			pr_info("    tx_start_pt(0x%04x):", i);
+			switch (i >> 10) {
+			case 0:
+				pr_cont("  20 bytes,");
+				break;
+			case 1:
+				pr_cont("  64 bytes,");
+				break;
+			case 2:
+				pr_cont(" 128 bytes,");
+				break;
+			case 3:
+				pr_cont("~220 bytes,");
+				break;
+			}
+			i = a->read_bcr(ioaddr, 18);	/* Check Burst/Bus control */
+			pr_cont(" BCR18(%x):", i & 0xffff);
+			if (i & (1 << 5))
+				pr_cont("BurstWrEn ");
+			if (i & (1 << 6))
+				pr_cont("BurstRdEn ");
+			if (i & (1 << 7))
+				pr_cont("DWordIO ");
+			if (i & (1 << 11))
+				pr_cont("NoUFlow ");
+			i = a->read_bcr(ioaddr, 25);
+			pr_info("    SRAMSIZE=0x%04x,", i << 8);
+			i = a->read_bcr(ioaddr, 26);
+			pr_cont(" SRAM_BND=0x%04x,", i << 8);
+			i = a->read_bcr(ioaddr, 27);
+			if (i & (1 << 14))
+				pr_cont("LowLatRx");
+		}
+	}
+
+	dev->base_addr = ioaddr;
+	lp = netdev_priv(dev);
+	/* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */
+	lp->init_block = pci_alloc_consistent(pdev, sizeof(*lp->init_block),
+					      &lp->init_dma_addr);
+	if (!lp->init_block) {
+		if (pcnet32_debug & NETIF_MSG_PROBE)
+			pr_err("Consistent memory allocation failed\n");
+		ret = -ENOMEM;
+		goto err_free_netdev;
+	}
+	lp->pci_dev = pdev;
+
+	lp->dev = dev;
+
+	spin_lock_init(&lp->lock);
+
+	lp->name = chipname;
+	lp->shared_irq = shared;
+	lp->tx_ring_size = TX_RING_SIZE;	/* default tx ring size */
+	lp->rx_ring_size = RX_RING_SIZE;	/* default rx ring size */
+	lp->tx_mod_mask = lp->tx_ring_size - 1;
+	lp->rx_mod_mask = lp->rx_ring_size - 1;
+	lp->tx_len_bits = (PCNET32_LOG_TX_BUFFERS << 12);
+	lp->rx_len_bits = (PCNET32_LOG_RX_BUFFERS << 4);
+	lp->mii_if.full_duplex = fdx;
+	lp->mii_if.phy_id_mask = 0x1f;
+	lp->mii_if.reg_num_mask = 0x1f;
+	lp->dxsuflo = dxsuflo;
+	lp->mii = mii;
+	lp->chip_version = chip_version;
+	lp->msg_enable = pcnet32_debug;
+	if ((cards_found >= MAX_UNITS) ||
+	    (options[cards_found] >= sizeof(options_mapping)))
+		lp->options = PCNET32_PORT_ASEL;
+	else
+		lp->options = options_mapping[options[cards_found]];
+	lp->mii_if.dev = dev;
+	lp->mii_if.mdio_read = mdio_read;
+	lp->mii_if.mdio_write = mdio_write;
+
+	/* napi.weight is used in both the napi and non-napi cases */
+	lp->napi.weight = lp->rx_ring_size / 2;
+
+	netif_napi_add(dev, &lp->napi, pcnet32_poll, lp->rx_ring_size / 2);
+
+	if (fdx && !(lp->options & PCNET32_PORT_ASEL) &&
+	    ((cards_found >= MAX_UNITS) || full_duplex[cards_found]))
+		lp->options |= PCNET32_PORT_FD;
+
+	lp->a = a;
+
+	/* prior to register_netdev, dev->name is not yet correct */
+	if (pcnet32_alloc_ring(dev, pci_name(lp->pci_dev))) {
+		ret = -ENOMEM;
+		goto err_free_ring;
+	}
+	/* detect special T1/E1 WAN card by checking for MAC address */
+	if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0 &&
+	    dev->dev_addr[2] == 0x75)
+		lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;
+
+	lp->init_block->mode = cpu_to_le16(0x0003);	/* Disable Rx and Tx. */
+	lp->init_block->tlen_rlen =
+	    cpu_to_le16(lp->tx_len_bits | lp->rx_len_bits);
+	for (i = 0; i < 6; i++)
+		lp->init_block->phys_addr[i] = dev->dev_addr[i];
+	lp->init_block->filter[0] = 0x00000000;
+	lp->init_block->filter[1] = 0x00000000;
+	lp->init_block->rx_ring = cpu_to_le32(lp->rx_ring_dma_addr);
+	lp->init_block->tx_ring = cpu_to_le32(lp->tx_ring_dma_addr);
+
+	/* switch pcnet32 to 32bit mode */
+	a->write_bcr(ioaddr, 20, 2);
+
+	a->write_csr(ioaddr, 1, (lp->init_dma_addr & 0xffff));
+	a->write_csr(ioaddr, 2, (lp->init_dma_addr >> 16));
+
+	if (pdev) {		/* use the IRQ provided by PCI */
+		dev->irq = pdev->irq;
+		if (pcnet32_debug & NETIF_MSG_PROBE)
+			pr_cont(" assigned IRQ %d\n", dev->irq);
+	} else {
+		unsigned long irq_mask = probe_irq_on();
+
+		/*
+		 * To auto-IRQ we enable the initialization-done and DMA error
+		 * interrupts. For ISA boards we get a DMA error, but VLB and PCI
+		 * boards will work.
+		 */
+		/* Trigger an initialization just for the interrupt. */
+		a->write_csr(ioaddr, CSR0, CSR0_INTEN | CSR0_INIT);
+		mdelay(1);
+
+		dev->irq = probe_irq_off(irq_mask);
+		if (!dev->irq) {
+			if (pcnet32_debug & NETIF_MSG_PROBE)
+				pr_cont(", failed to detect IRQ line\n");
+			ret = -ENODEV;
+			goto err_free_ring;
+		}
+		if (pcnet32_debug & NETIF_MSG_PROBE)
+			pr_cont(", probed IRQ %d\n", dev->irq);
+	}
+
+	/* Set the mii phy_id so that we can query the link state */
+	if (lp->mii) {
+		/* lp->phycount and lp->phymask are set to 0 by memset above */
+
+		lp->mii_if.phy_id = ((lp->a->read_bcr(ioaddr, 33)) >> 5) & 0x1f;
+		/* scan for PHYs */
+		for (i = 0; i < PCNET32_MAX_PHYS; i++) {
+			unsigned short id1, id2;
+
+			id1 = mdio_read(dev, i, MII_PHYSID1);
+			if (id1 == 0xffff)
+				continue;
+			id2 = mdio_read(dev, i, MII_PHYSID2);
+			if (id2 == 0xffff)
+				continue;
+			if (i == 31 && ((chip_version + 1) & 0xfffe) == 0x2624)
+				continue;	/* 79C971 & 79C972 have phantom phy at id 31 */
+			lp->phycount++;
+			lp->phymask |= (1 << i);
+			lp->mii_if.phy_id = i;
+			if (pcnet32_debug & NETIF_MSG_PROBE)
+				pr_info("Found PHY %04x:%04x at address %d\n",
+					id1, id2, i);
+		}
+		lp->a->write_bcr(ioaddr, 33, (lp->mii_if.phy_id) << 5);
+		if (lp->phycount > 1)
+			lp->options |= PCNET32_PORT_MII;
+	}
+
+	init_timer(&lp->watchdog_timer);
+	lp->watchdog_timer.data = (unsigned long)dev;
+	lp->watchdog_timer.function = (void *)&pcnet32_watchdog;
+
+	/* The PCNET32-specific entries in the device structure. */
+	dev->netdev_ops = &pcnet32_netdev_ops;
+	dev->ethtool_ops = &pcnet32_ethtool_ops;
+	dev->watchdog_timeo = (5 * HZ);
+
+	/* Fill in the generic fields of the device structure. */
+	if (register_netdev(dev))
+		goto err_free_ring;
+
+	if (pdev) {
+		pci_set_drvdata(pdev, dev);
+	} else {
+		lp->next = pcnet32_dev;
+		pcnet32_dev = dev;
+	}
+
+	if (pcnet32_debug & NETIF_MSG_PROBE)
+		pr_info("%s: registered as %s\n", dev->name, lp->name);
+	cards_found++;
+
+	/* enable LED writes */
+	a->write_bcr(ioaddr, 2, a->read_bcr(ioaddr, 2) | 0x1000);
+
+	return 0;
+
+err_free_ring:
+	pcnet32_free_ring(dev);
+	pci_free_consistent(lp->pci_dev, sizeof(*lp->init_block),
+			    lp->init_block, lp->init_dma_addr);
+err_free_netdev:
+	free_netdev(dev);
+err_release_region:
+	release_region(ioaddr, PCNET32_TOTAL_SIZE);
+	return ret;
+}
+
+/* if any allocation fails, caller must also call pcnet32_free_ring */
+static int pcnet32_alloc_ring(struct net_device *dev, const char *name)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+
+	lp->tx_ring = pci_alloc_consistent(lp->pci_dev,
+					   sizeof(struct pcnet32_tx_head) *
+					   lp->tx_ring_size,
+					   &lp->tx_ring_dma_addr);
+	if (lp->tx_ring == NULL) {
+		netif_err(lp, drv, dev, "Consistent memory allocation failed\n");
+		return -ENOMEM;
+	}
+
+	lp->rx_ring = pci_alloc_consistent(lp->pci_dev,
+					   sizeof(struct pcnet32_rx_head) *
+					   lp->rx_ring_size,
+					   &lp->rx_ring_dma_addr);
+	if (lp->rx_ring == NULL) {
+		netif_err(lp, drv, dev, "Consistent memory allocation failed\n");
+		return -ENOMEM;
+	}
+
+	lp->tx_dma_addr = kcalloc(lp->tx_ring_size, sizeof(dma_addr_t),
+				  GFP_ATOMIC);
+	if (!lp->tx_dma_addr) {
+		netif_err(lp, drv, dev, "Memory allocation failed\n");
+		return -ENOMEM;
+	}
+
+	lp->rx_dma_addr = kcalloc(lp->rx_ring_size, sizeof(dma_addr_t),
+				  GFP_ATOMIC);
+	if (!lp->rx_dma_addr) {
+		netif_err(lp, drv, dev, "Memory allocation failed\n");
+		return -ENOMEM;
+	}
+
+	lp->tx_skbuff = kcalloc(lp->tx_ring_size, sizeof(struct sk_buff *),
+				GFP_ATOMIC);
+	if (!lp->tx_skbuff) {
+		netif_err(lp, drv, dev, "Memory allocation failed\n");
+		return -ENOMEM;
+	}
+
+	lp->rx_skbuff = kcalloc(lp->rx_ring_size, sizeof(struct sk_buff *),
+				GFP_ATOMIC);
+	if (!lp->rx_skbuff) {
+		netif_err(lp, drv, dev, "Memory allocation failed\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void pcnet32_free_ring(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+
+	kfree(lp->tx_skbuff);
+	lp->tx_skbuff = NULL;
+
+	kfree(lp->rx_skbuff);
+	lp->rx_skbuff = NULL;
+
+	kfree(lp->tx_dma_addr);
+	lp->tx_dma_addr = NULL;
+
+	kfree(lp->rx_dma_addr);
+	lp->rx_dma_addr = NULL;
+
+	if (lp->tx_ring) {
+		pci_free_consistent(lp->pci_dev,
+				    sizeof(struct pcnet32_tx_head) *
+				    lp->tx_ring_size, lp->tx_ring,
+				    lp->tx_ring_dma_addr);
+		lp->tx_ring = NULL;
+	}
+
+	if (lp->rx_ring) {
+		pci_free_consistent(lp->pci_dev,
+				    sizeof(struct pcnet32_rx_head) *
+				    lp->rx_ring_size, lp->rx_ring,
+				    lp->rx_ring_dma_addr);
+		lp->rx_ring = NULL;
+	}
+}
+
+static int pcnet32_open(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	struct pci_dev *pdev = lp->pci_dev;
+	unsigned long ioaddr = dev->base_addr;
+	u16 val;
+	int i;
+	int rc;
+	unsigned long flags;
+
+	if (request_irq(dev->irq, pcnet32_interrupt,
+			lp->shared_irq ? IRQF_SHARED : 0, dev->name,
+			(void *)dev)) {
+		return -EAGAIN;
+	}
+
+	spin_lock_irqsave(&lp->lock, flags);
+	/* Check for a valid station address */
+	if (!is_valid_ether_addr(dev->dev_addr)) {
+		rc = -EINVAL;
+		goto err_free_irq;
+	}
+
+	/* Reset the PCNET32 */
+	lp->a->reset(ioaddr);
+
+	/* switch pcnet32 to 32bit mode */
+	lp->a->write_bcr(ioaddr, 20, 2);
+
+	netif_printk(lp, ifup, KERN_DEBUG, dev,
+		     "%s() irq %d tx/rx rings %#x/%#x init %#x\n",
+		     __func__, dev->irq, (u32) (lp->tx_ring_dma_addr),
+		     (u32) (lp->rx_ring_dma_addr),
+		     (u32) (lp->init_dma_addr));
+
+	/* set/reset autoselect bit */
+	val = lp->a->read_bcr(ioaddr, 2) & ~2;
+	if (lp->options & PCNET32_PORT_ASEL)
+		val |= 2;
+	lp->a->write_bcr(ioaddr, 2, val);
+
+	/* handle full duplex setting */
+	if (lp->mii_if.full_duplex) {
+		val = lp->a->read_bcr(ioaddr, 9) & ~3;
+		if (lp->options & PCNET32_PORT_FD) {
+			val |= 1;
+			if (lp->options == (PCNET32_PORT_FD | PCNET32_PORT_AUI))
+				val |= 2;
+		} else if (lp->options & PCNET32_PORT_ASEL) {
+			/* workaround of xSeries250, turn on for 79C975 only */
+			if (lp->chip_version == 0x2627)
+				val |= 3;
+		}
+		lp->a->write_bcr(ioaddr, 9, val);
+	}
+
+	/* set/reset GPSI bit in test register */
+	val = lp->a->read_csr(ioaddr, 124) & ~0x10;
+	if ((lp->options & PCNET32_PORT_PORTSEL) == PCNET32_PORT_GPSI)
+		val |= 0x10;
+	lp->a->write_csr(ioaddr, 124, val);
+
+	/* Allied Telesyn AT 2700/2701 FX are 100Mbit only and do not negotiate */
+	if (pdev && pdev->subsystem_vendor == PCI_VENDOR_ID_AT &&
+	    (pdev->subsystem_device == PCI_SUBDEVICE_ID_AT_2700FX ||
+	     pdev->subsystem_device == PCI_SUBDEVICE_ID_AT_2701FX)) {
+		if (lp->options & PCNET32_PORT_ASEL) {
+			lp->options = PCNET32_PORT_FD | PCNET32_PORT_100;
+			netif_printk(lp, link, KERN_DEBUG, dev,
+				     "Setting 100Mb-Full Duplex\n");
+		}
+	}
+	if (lp->phycount < 2) {
+		/*
+		 * 24 Jun 2004 according AMD, in order to change the PHY,
+		 * DANAS (or DISPM for 79C976) must be set; then select the speed,
+		 * duplex, and/or enable auto negotiation, and clear DANAS
+		 */
+		if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) {
+			lp->a->write_bcr(ioaddr, 32,
+					lp->a->read_bcr(ioaddr, 32) | 0x0080);
+			/* disable Auto Negotiation, set 10Mpbs, HD */
+			val = lp->a->read_bcr(ioaddr, 32) & ~0xb8;
+			if (lp->options & PCNET32_PORT_FD)
+				val |= 0x10;
+			if (lp->options & PCNET32_PORT_100)
+				val |= 0x08;
+			lp->a->write_bcr(ioaddr, 32, val);
+		} else {
+			if (lp->options & PCNET32_PORT_ASEL) {
+				lp->a->write_bcr(ioaddr, 32,
+						lp->a->read_bcr(ioaddr,
+							       32) | 0x0080);
+				/* enable auto negotiate, setup, disable fd */
+				val = lp->a->read_bcr(ioaddr, 32) & ~0x98;
+				val |= 0x20;
+				lp->a->write_bcr(ioaddr, 32, val);
+			}
+		}
+	} else {
+		int first_phy = -1;
+		u16 bmcr;
+		u32 bcr9;
+		struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
+
+		/*
+		 * There is really no good other way to handle multiple PHYs
+		 * other than turning off all automatics
+		 */
+		val = lp->a->read_bcr(ioaddr, 2);
+		lp->a->write_bcr(ioaddr, 2, val & ~2);
+		val = lp->a->read_bcr(ioaddr, 32);
+		lp->a->write_bcr(ioaddr, 32, val & ~(1 << 7));	/* stop MII manager */
+
+		if (!(lp->options & PCNET32_PORT_ASEL)) {
+			/* setup ecmd */
+			ecmd.port = PORT_MII;
+			ecmd.transceiver = XCVR_INTERNAL;
+			ecmd.autoneg = AUTONEG_DISABLE;
+			ethtool_cmd_speed_set(&ecmd,
+					      (lp->options & PCNET32_PORT_100) ?
+					      SPEED_100 : SPEED_10);
+			bcr9 = lp->a->read_bcr(ioaddr, 9);
+
+			if (lp->options & PCNET32_PORT_FD) {
+				ecmd.duplex = DUPLEX_FULL;
+				bcr9 |= (1 << 0);
+			} else {
+				ecmd.duplex = DUPLEX_HALF;
+				bcr9 |= ~(1 << 0);
+			}
+			lp->a->write_bcr(ioaddr, 9, bcr9);
+		}
+
+		for (i = 0; i < PCNET32_MAX_PHYS; i++) {
+			if (lp->phymask & (1 << i)) {
+				/* isolate all but the first PHY */
+				bmcr = mdio_read(dev, i, MII_BMCR);
+				if (first_phy == -1) {
+					first_phy = i;
+					mdio_write(dev, i, MII_BMCR,
+						   bmcr & ~BMCR_ISOLATE);
+				} else {
+					mdio_write(dev, i, MII_BMCR,
+						   bmcr | BMCR_ISOLATE);
+				}
+				/* use mii_ethtool_sset to setup PHY */
+				lp->mii_if.phy_id = i;
+				ecmd.phy_address = i;
+				if (lp->options & PCNET32_PORT_ASEL) {
+					mii_ethtool_gset(&lp->mii_if, &ecmd);
+					ecmd.autoneg = AUTONEG_ENABLE;
+				}
+				mii_ethtool_sset(&lp->mii_if, &ecmd);
+			}
+		}
+		lp->mii_if.phy_id = first_phy;
+		netif_info(lp, link, dev, "Using PHY number %d\n", first_phy);
+	}
+
+#ifdef DO_DXSUFLO
+	if (lp->dxsuflo) {	/* Disable transmit stop on underflow */
+		val = lp->a->read_csr(ioaddr, CSR3);
+		val |= 0x40;
+		lp->a->write_csr(ioaddr, CSR3, val);
+	}
+#endif
+
+	lp->init_block->mode =
+	    cpu_to_le16((lp->options & PCNET32_PORT_PORTSEL) << 7);
+	pcnet32_load_multicast(dev);
+
+	if (pcnet32_init_ring(dev)) {
+		rc = -ENOMEM;
+		goto err_free_ring;
+	}
+
+	napi_enable(&lp->napi);
+
+	/* Re-initialize the PCNET32, and start it when done. */
+	lp->a->write_csr(ioaddr, 1, (lp->init_dma_addr & 0xffff));
+	lp->a->write_csr(ioaddr, 2, (lp->init_dma_addr >> 16));
+
+	lp->a->write_csr(ioaddr, CSR4, 0x0915);	/* auto tx pad */
+	lp->a->write_csr(ioaddr, CSR0, CSR0_INIT);
+
+	netif_start_queue(dev);
+
+	if (lp->chip_version >= PCNET32_79C970A) {
+		/* Print the link status and start the watchdog */
+		pcnet32_check_media(dev, 1);
+		mod_timer(&lp->watchdog_timer, PCNET32_WATCHDOG_TIMEOUT);
+	}
+
+	i = 0;
+	while (i++ < 100)
+		if (lp->a->read_csr(ioaddr, CSR0) & CSR0_IDON)
+			break;
+	/*
+	 * We used to clear the InitDone bit, 0x0100, here but Mark Stockton
+	 * reports that doing so triggers a bug in the '974.
+	 */
+	lp->a->write_csr(ioaddr, CSR0, CSR0_NORMAL);
+
+	netif_printk(lp, ifup, KERN_DEBUG, dev,
+		     "pcnet32 open after %d ticks, init block %#x csr0 %4.4x\n",
+		     i,
+		     (u32) (lp->init_dma_addr),
+		     lp->a->read_csr(ioaddr, CSR0));
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return 0;		/* Always succeed */
+
+err_free_ring:
+	/* free any allocated skbuffs */
+	pcnet32_purge_rx_ring(dev);
+
+	/*
+	 * Switch back to 16bit mode to avoid problems with dumb
+	 * DOS packet driver after a warm reboot
+	 */
+	lp->a->write_bcr(ioaddr, 20, 4);
+
+err_free_irq:
+	spin_unlock_irqrestore(&lp->lock, flags);
+	free_irq(dev->irq, dev);
+	return rc;
+}
+
+/*
+ * The LANCE has been halted for one reason or another (busmaster memory
+ * arbitration error, Tx FIFO underflow, driver stopped it to reconfigure,
+ * etc.).  Modern LANCE variants always reload their ring-buffer
+ * configuration when restarted, so we must reinitialize our ring
+ * context before restarting.  As part of this reinitialization,
+ * find all packets still on the Tx ring and pretend that they had been
+ * sent (in effect, drop the packets on the floor) - the higher-level
+ * protocols will time out and retransmit.  It'd be better to shuffle
+ * these skbs to a temp list and then actually re-Tx them after
+ * restarting the chip, but I'm too lazy to do so right now.  dplatt@3do.com
+ */
+
+static void pcnet32_purge_tx_ring(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	int i;
+
+	for (i = 0; i < lp->tx_ring_size; i++) {
+		lp->tx_ring[i].status = 0;	/* CPU owns buffer */
+		wmb();		/* Make sure adapter sees owner change */
+		if (lp->tx_skbuff[i]) {
+			pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i],
+					 lp->tx_skbuff[i]->len,
+					 PCI_DMA_TODEVICE);
+			dev_kfree_skb_any(lp->tx_skbuff[i]);
+		}
+		lp->tx_skbuff[i] = NULL;
+		lp->tx_dma_addr[i] = 0;
+	}
+}
+
+/* Initialize the PCNET32 Rx and Tx rings. */
+static int pcnet32_init_ring(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	int i;
+
+	lp->tx_full = 0;
+	lp->cur_rx = lp->cur_tx = 0;
+	lp->dirty_rx = lp->dirty_tx = 0;
+
+	for (i = 0; i < lp->rx_ring_size; i++) {
+		struct sk_buff *rx_skbuff = lp->rx_skbuff[i];
+		if (rx_skbuff == NULL) {
+			lp->rx_skbuff[i] = dev_alloc_skb(PKT_BUF_SKB);
+			rx_skbuff = lp->rx_skbuff[i];
+			if (!rx_skbuff) {
+				/* there is not much we can do at this point */
+				netif_err(lp, drv, dev, "%s dev_alloc_skb failed\n",
+					  __func__);
+				return -1;
+			}
+			skb_reserve(rx_skbuff, NET_IP_ALIGN);
+		}
+
+		rmb();
+		if (lp->rx_dma_addr[i] == 0)
+			lp->rx_dma_addr[i] =
+			    pci_map_single(lp->pci_dev, rx_skbuff->data,
+					   PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
+		lp->rx_ring[i].base = cpu_to_le32(lp->rx_dma_addr[i]);
+		lp->rx_ring[i].buf_length = cpu_to_le16(NEG_BUF_SIZE);
+		wmb();		/* Make sure owner changes after all others are visible */
+		lp->rx_ring[i].status = cpu_to_le16(0x8000);
+	}
+	/* The Tx buffer address is filled in as needed, but we do need to clear
+	 * the upper ownership bit. */
+	for (i = 0; i < lp->tx_ring_size; i++) {
+		lp->tx_ring[i].status = 0;	/* CPU owns buffer */
+		wmb();		/* Make sure adapter sees owner change */
+		lp->tx_ring[i].base = 0;
+		lp->tx_dma_addr[i] = 0;
+	}
+
+	lp->init_block->tlen_rlen =
+	    cpu_to_le16(lp->tx_len_bits | lp->rx_len_bits);
+	for (i = 0; i < 6; i++)
+		lp->init_block->phys_addr[i] = dev->dev_addr[i];
+	lp->init_block->rx_ring = cpu_to_le32(lp->rx_ring_dma_addr);
+	lp->init_block->tx_ring = cpu_to_le32(lp->tx_ring_dma_addr);
+	wmb();			/* Make sure all changes are visible */
+	return 0;
+}
+
+/* the pcnet32 has been issued a stop or reset.  Wait for the stop bit
+ * then flush the pending transmit operations, re-initialize the ring,
+ * and tell the chip to initialize.
+ */
+static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	int i;
+
+	/* wait for stop */
+	for (i = 0; i < 100; i++)
+		if (lp->a->read_csr(ioaddr, CSR0) & CSR0_STOP)
+			break;
+
+	if (i >= 100)
+		netif_err(lp, drv, dev, "%s timed out waiting for stop\n",
+			  __func__);
+
+	pcnet32_purge_tx_ring(dev);
+	if (pcnet32_init_ring(dev))
+		return;
+
+	/* ReInit Ring */
+	lp->a->write_csr(ioaddr, CSR0, CSR0_INIT);
+	i = 0;
+	while (i++ < 1000)
+		if (lp->a->read_csr(ioaddr, CSR0) & CSR0_IDON)
+			break;
+
+	lp->a->write_csr(ioaddr, CSR0, csr0_bits);
+}
+
+static void pcnet32_tx_timeout(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr, flags;
+
+	spin_lock_irqsave(&lp->lock, flags);
+	/* Transmitter timeout, serious problems. */
+	if (pcnet32_debug & NETIF_MSG_DRV)
+		pr_err("%s: transmit timed out, status %4.4x, resetting\n",
+		       dev->name, lp->a->read_csr(ioaddr, CSR0));
+	lp->a->write_csr(ioaddr, CSR0, CSR0_STOP);
+	dev->stats.tx_errors++;
+	if (netif_msg_tx_err(lp)) {
+		int i;
+		printk(KERN_DEBUG
+		       " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
+		       lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
+		       lp->cur_rx);
+		for (i = 0; i < lp->rx_ring_size; i++)
+			printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
+			       le32_to_cpu(lp->rx_ring[i].base),
+			       (-le16_to_cpu(lp->rx_ring[i].buf_length)) &
+			       0xffff, le32_to_cpu(lp->rx_ring[i].msg_length),
+			       le16_to_cpu(lp->rx_ring[i].status));
+		for (i = 0; i < lp->tx_ring_size; i++)
+			printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
+			       le32_to_cpu(lp->tx_ring[i].base),
+			       (-le16_to_cpu(lp->tx_ring[i].length)) & 0xffff,
+			       le32_to_cpu(lp->tx_ring[i].misc),
+			       le16_to_cpu(lp->tx_ring[i].status));
+		printk("\n");
+	}
+	pcnet32_restart(dev, CSR0_NORMAL);
+
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	netif_wake_queue(dev);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+}
+
+static netdev_tx_t pcnet32_start_xmit(struct sk_buff *skb,
+				      struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	u16 status;
+	int entry;
+	unsigned long flags;
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	netif_printk(lp, tx_queued, KERN_DEBUG, dev,
+		     "%s() called, csr0 %4.4x\n",
+		     __func__, lp->a->read_csr(ioaddr, CSR0));
+
+	/* Default status -- will not enable Successful-TxDone
+	 * interrupt when that option is available to us.
+	 */
+	status = 0x8300;
+
+	/* Fill in a Tx ring entry */
+
+	/* Mask to ring buffer boundary. */
+	entry = lp->cur_tx & lp->tx_mod_mask;
+
+	/* Caution: the write order is important here, set the status
+	 * with the "ownership" bits last. */
+
+	lp->tx_ring[entry].length = cpu_to_le16(-skb->len);
+
+	lp->tx_ring[entry].misc = 0x00000000;
+
+	lp->tx_skbuff[entry] = skb;
+	lp->tx_dma_addr[entry] =
+	    pci_map_single(lp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
+	lp->tx_ring[entry].base = cpu_to_le32(lp->tx_dma_addr[entry]);
+	wmb();			/* Make sure owner changes after all others are visible */
+	lp->tx_ring[entry].status = cpu_to_le16(status);
+
+	lp->cur_tx++;
+	dev->stats.tx_bytes += skb->len;
+
+	/* Trigger an immediate send poll. */
+	lp->a->write_csr(ioaddr, CSR0, CSR0_INTEN | CSR0_TXPOLL);
+
+	if (lp->tx_ring[(entry + 1) & lp->tx_mod_mask].base != 0) {
+		lp->tx_full = 1;
+		netif_stop_queue(dev);
+	}
+	spin_unlock_irqrestore(&lp->lock, flags);
+	return NETDEV_TX_OK;
+}
+
+/* The PCNET32 interrupt handler. */
+static irqreturn_t
+pcnet32_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct pcnet32_private *lp;
+	unsigned long ioaddr;
+	u16 csr0;
+	int boguscnt = max_interrupt_work;
+
+	ioaddr = dev->base_addr;
+	lp = netdev_priv(dev);
+
+	spin_lock(&lp->lock);
+
+	csr0 = lp->a->read_csr(ioaddr, CSR0);
+	while ((csr0 & 0x8f00) && --boguscnt >= 0) {
+		if (csr0 == 0xffff)
+			break;	/* PCMCIA remove happened */
+		/* Acknowledge all of the current interrupt sources ASAP. */
+		lp->a->write_csr(ioaddr, CSR0, csr0 & ~0x004f);
+
+		netif_printk(lp, intr, KERN_DEBUG, dev,
+			     "interrupt  csr0=%#2.2x new csr=%#2.2x\n",
+			     csr0, lp->a->read_csr(ioaddr, CSR0));
+
+		/* Log misc errors. */
+		if (csr0 & 0x4000)
+			dev->stats.tx_errors++;	/* Tx babble. */
+		if (csr0 & 0x1000) {
+			/*
+			 * This happens when our receive ring is full. This
+			 * shouldn't be a problem as we will see normal rx
+			 * interrupts for the frames in the receive ring.  But
+			 * there are some PCI chipsets (I can reproduce this
+			 * on SP3G with Intel saturn chipset) which have
+			 * sometimes problems and will fill up the receive
+			 * ring with error descriptors.  In this situation we
+			 * don't get a rx interrupt, but a missed frame
+			 * interrupt sooner or later.
+			 */
+			dev->stats.rx_errors++;	/* Missed a Rx frame. */
+		}
+		if (csr0 & 0x0800) {
+			netif_err(lp, drv, dev, "Bus master arbitration failure, status %4.4x\n",
+				  csr0);
+			/* unlike for the lance, there is no restart needed */
+		}
+		if (napi_schedule_prep(&lp->napi)) {
+			u16 val;
+			/* set interrupt masks */
+			val = lp->a->read_csr(ioaddr, CSR3);
+			val |= 0x5f00;
+			lp->a->write_csr(ioaddr, CSR3, val);
+
+			__napi_schedule(&lp->napi);
+			break;
+		}
+		csr0 = lp->a->read_csr(ioaddr, CSR0);
+	}
+
+	netif_printk(lp, intr, KERN_DEBUG, dev,
+		     "exiting interrupt, csr0=%#4.4x\n",
+		     lp->a->read_csr(ioaddr, CSR0));
+
+	spin_unlock(&lp->lock);
+
+	return IRQ_HANDLED;
+}
+
+static int pcnet32_close(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct pcnet32_private *lp = netdev_priv(dev);
+	unsigned long flags;
+
+	del_timer_sync(&lp->watchdog_timer);
+
+	netif_stop_queue(dev);
+	napi_disable(&lp->napi);
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	dev->stats.rx_missed_errors = lp->a->read_csr(ioaddr, 112);
+
+	netif_printk(lp, ifdown, KERN_DEBUG, dev,
+		     "Shutting down ethercard, status was %2.2x\n",
+		     lp->a->read_csr(ioaddr, CSR0));
+
+	/* We stop the PCNET32 here -- it occasionally polls memory if we don't. */
+	lp->a->write_csr(ioaddr, CSR0, CSR0_STOP);
+
+	/*
+	 * Switch back to 16bit mode to avoid problems with dumb
+	 * DOS packet driver after a warm reboot
+	 */
+	lp->a->write_bcr(ioaddr, 20, 4);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	free_irq(dev->irq, dev);
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	pcnet32_purge_rx_ring(dev);
+	pcnet32_purge_tx_ring(dev);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return 0;
+}
+
+static struct net_device_stats *pcnet32_get_stats(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&lp->lock, flags);
+	dev->stats.rx_missed_errors = lp->a->read_csr(ioaddr, 112);
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	return &dev->stats;
+}
+
+/* taken from the sunlance driver, which it took from the depca driver */
+static void pcnet32_load_multicast(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	volatile struct pcnet32_init_block *ib = lp->init_block;
+	volatile __le16 *mcast_table = (__le16 *)ib->filter;
+	struct netdev_hw_addr *ha;
+	unsigned long ioaddr = dev->base_addr;
+	int i;
+	u32 crc;
+
+	/* set all multicast bits */
+	if (dev->flags & IFF_ALLMULTI) {
+		ib->filter[0] = cpu_to_le32(~0U);
+		ib->filter[1] = cpu_to_le32(~0U);
+		lp->a->write_csr(ioaddr, PCNET32_MC_FILTER, 0xffff);
+		lp->a->write_csr(ioaddr, PCNET32_MC_FILTER+1, 0xffff);
+		lp->a->write_csr(ioaddr, PCNET32_MC_FILTER+2, 0xffff);
+		lp->a->write_csr(ioaddr, PCNET32_MC_FILTER+3, 0xffff);
+		return;
+	}
+	/* clear the multicast filter */
+	ib->filter[0] = 0;
+	ib->filter[1] = 0;
+
+	/* Add addresses */
+	netdev_for_each_mc_addr(ha, dev) {
+		crc = ether_crc_le(6, ha->addr);
+		crc = crc >> 26;
+		mcast_table[crc >> 4] |= cpu_to_le16(1 << (crc & 0xf));
+	}
+	for (i = 0; i < 4; i++)
+		lp->a->write_csr(ioaddr, PCNET32_MC_FILTER + i,
+				le16_to_cpu(mcast_table[i]));
+}
+
+/*
+ * Set or clear the multicast filter for this adaptor.
+ */
+static void pcnet32_set_multicast_list(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr, flags;
+	struct pcnet32_private *lp = netdev_priv(dev);
+	int csr15, suspended;
+
+	spin_lock_irqsave(&lp->lock, flags);
+	suspended = pcnet32_suspend(dev, &flags, 0);
+	csr15 = lp->a->read_csr(ioaddr, CSR15);
+	if (dev->flags & IFF_PROMISC) {
+		/* Log any net taps. */
+		netif_info(lp, hw, dev, "Promiscuous mode enabled\n");
+		lp->init_block->mode =
+		    cpu_to_le16(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) <<
+				7);
+		lp->a->write_csr(ioaddr, CSR15, csr15 | 0x8000);
+	} else {
+		lp->init_block->mode =
+		    cpu_to_le16((lp->options & PCNET32_PORT_PORTSEL) << 7);
+		lp->a->write_csr(ioaddr, CSR15, csr15 & 0x7fff);
+		pcnet32_load_multicast(dev);
+	}
+
+	if (suspended) {
+		int csr5;
+		/* clear SUSPEND (SPND) - CSR5 bit 0 */
+		csr5 = lp->a->read_csr(ioaddr, CSR5);
+		lp->a->write_csr(ioaddr, CSR5, csr5 & (~CSR5_SUSPEND));
+	} else {
+		lp->a->write_csr(ioaddr, CSR0, CSR0_STOP);
+		pcnet32_restart(dev, CSR0_NORMAL);
+		netif_wake_queue(dev);
+	}
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+}
+
+/* This routine assumes that the lp->lock is held */
+static int mdio_read(struct net_device *dev, int phy_id, int reg_num)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	u16 val_out;
+
+	if (!lp->mii)
+		return 0;
+
+	lp->a->write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f));
+	val_out = lp->a->read_bcr(ioaddr, 34);
+
+	return val_out;
+}
+
+/* This routine assumes that the lp->lock is held */
+static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+
+	if (!lp->mii)
+		return;
+
+	lp->a->write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f));
+	lp->a->write_bcr(ioaddr, 34, val);
+}
+
+static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	int rc;
+	unsigned long flags;
+
+	/* SIOC[GS]MIIxxx ioctls */
+	if (lp->mii) {
+		spin_lock_irqsave(&lp->lock, flags);
+		rc = generic_mii_ioctl(&lp->mii_if, if_mii(rq), cmd, NULL);
+		spin_unlock_irqrestore(&lp->lock, flags);
+	} else {
+		rc = -EOPNOTSUPP;
+	}
+
+	return rc;
+}
+
+static int pcnet32_check_otherphy(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	struct mii_if_info mii = lp->mii_if;
+	u16 bmcr;
+	int i;
+
+	for (i = 0; i < PCNET32_MAX_PHYS; i++) {
+		if (i == lp->mii_if.phy_id)
+			continue;	/* skip active phy */
+		if (lp->phymask & (1 << i)) {
+			mii.phy_id = i;
+			if (mii_link_ok(&mii)) {
+				/* found PHY with active link */
+				netif_info(lp, link, dev, "Using PHY number %d\n",
+					   i);
+
+				/* isolate inactive phy */
+				bmcr =
+				    mdio_read(dev, lp->mii_if.phy_id, MII_BMCR);
+				mdio_write(dev, lp->mii_if.phy_id, MII_BMCR,
+					   bmcr | BMCR_ISOLATE);
+
+				/* de-isolate new phy */
+				bmcr = mdio_read(dev, i, MII_BMCR);
+				mdio_write(dev, i, MII_BMCR,
+					   bmcr & ~BMCR_ISOLATE);
+
+				/* set new phy address */
+				lp->mii_if.phy_id = i;
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+
+/*
+ * Show the status of the media.  Similar to mii_check_media however it
+ * correctly shows the link speed for all (tested) pcnet32 variants.
+ * Devices with no mii just report link state without speed.
+ *
+ * Caller is assumed to hold and release the lp->lock.
+ */
+
+static void pcnet32_check_media(struct net_device *dev, int verbose)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	int curr_link;
+	int prev_link = netif_carrier_ok(dev) ? 1 : 0;
+	u32 bcr9;
+
+	if (lp->mii) {
+		curr_link = mii_link_ok(&lp->mii_if);
+	} else {
+		ulong ioaddr = dev->base_addr;	/* card base I/O address */
+		curr_link = (lp->a->read_bcr(ioaddr, 4) != 0xc0);
+	}
+	if (!curr_link) {
+		if (prev_link || verbose) {
+			netif_carrier_off(dev);
+			netif_info(lp, link, dev, "link down\n");
+		}
+		if (lp->phycount > 1) {
+			curr_link = pcnet32_check_otherphy(dev);
+			prev_link = 0;
+		}
+	} else if (verbose || !prev_link) {
+		netif_carrier_on(dev);
+		if (lp->mii) {
+			if (netif_msg_link(lp)) {
+				struct ethtool_cmd ecmd = {
+					.cmd = ETHTOOL_GSET };
+				mii_ethtool_gset(&lp->mii_if, &ecmd);
+				netdev_info(dev, "link up, %uMbps, %s-duplex\n",
+					    ethtool_cmd_speed(&ecmd),
+					    (ecmd.duplex == DUPLEX_FULL)
+					    ? "full" : "half");
+			}
+			bcr9 = lp->a->read_bcr(dev->base_addr, 9);
+			if ((bcr9 & (1 << 0)) != lp->mii_if.full_duplex) {
+				if (lp->mii_if.full_duplex)
+					bcr9 |= (1 << 0);
+				else
+					bcr9 &= ~(1 << 0);
+				lp->a->write_bcr(dev->base_addr, 9, bcr9);
+			}
+		} else {
+			netif_info(lp, link, dev, "link up\n");
+		}
+	}
+}
+
+/*
+ * Check for loss of link and link establishment.
+ * Can not use mii_check_media because it does nothing if mode is forced.
+ */
+
+static void pcnet32_watchdog(struct net_device *dev)
+{
+	struct pcnet32_private *lp = netdev_priv(dev);
+	unsigned long flags;
+
+	/* Print the link status if it has changed */
+	spin_lock_irqsave(&lp->lock, flags);
+	pcnet32_check_media(dev, 0);
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	mod_timer(&lp->watchdog_timer, round_jiffies(PCNET32_WATCHDOG_TIMEOUT));
+}
+
+static int pcnet32_pm_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	if (netif_running(dev)) {
+		netif_device_detach(dev);
+		pcnet32_close(dev);
+	}
+	pci_save_state(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	return 0;
+}
+
+static int pcnet32_pm_resume(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+
+	if (netif_running(dev)) {
+		pcnet32_open(dev);
+		netif_device_attach(dev);
+	}
+	return 0;
+}
+
+static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	if (dev) {
+		struct pcnet32_private *lp = netdev_priv(dev);
+
+		unregister_netdev(dev);
+		pcnet32_free_ring(dev);
+		release_region(dev->base_addr, PCNET32_TOTAL_SIZE);
+		pci_free_consistent(lp->pci_dev, sizeof(*lp->init_block),
+				    lp->init_block, lp->init_dma_addr);
+		free_netdev(dev);
+		pci_disable_device(pdev);
+		pci_set_drvdata(pdev, NULL);
+	}
+}
+
+static struct pci_driver pcnet32_driver = {
+	.name = DRV_NAME,
+	.probe = pcnet32_probe_pci,
+	.remove = __devexit_p(pcnet32_remove_one),
+	.id_table = pcnet32_pci_tbl,
+	.suspend = pcnet32_pm_suspend,
+	.resume = pcnet32_pm_resume,
+};
+
+/* An additional parameter that may be passed in... */
+static int debug = -1;
+static int tx_start_pt = -1;
+static int pcnet32_have_pci;
+
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, DRV_NAME " debug level");
+module_param(max_interrupt_work, int, 0);
+MODULE_PARM_DESC(max_interrupt_work,
+		 DRV_NAME " maximum events handled per interrupt");
+module_param(rx_copybreak, int, 0);
+MODULE_PARM_DESC(rx_copybreak,
+		 DRV_NAME " copy breakpoint for copy-only-tiny-frames");
+module_param(tx_start_pt, int, 0);
+MODULE_PARM_DESC(tx_start_pt, DRV_NAME " transmit start point (0-3)");
+module_param(pcnet32vlb, int, 0);
+MODULE_PARM_DESC(pcnet32vlb, DRV_NAME " Vesa local bus (VLB) support (0/1)");
+module_param_array(options, int, NULL, 0);
+MODULE_PARM_DESC(options, DRV_NAME " initial option setting(s) (0-15)");
+module_param_array(full_duplex, int, NULL, 0);
+MODULE_PARM_DESC(full_duplex, DRV_NAME " full duplex setting(s) (1)");
+/* Module Parameter for HomePNA cards added by Patrick Simmons, 2004 */
+module_param_array(homepna, int, NULL, 0);
+MODULE_PARM_DESC(homepna,
+		 DRV_NAME
+		 " mode for 79C978 cards (1 for HomePNA, 0 for Ethernet, default Ethernet");
+
+MODULE_AUTHOR("Thomas Bogendoerfer");
+MODULE_DESCRIPTION("Driver for PCnet32 and PCnetPCI based ethercards");
+MODULE_LICENSE("GPL");
+
+#define PCNET32_MSG_DEFAULT (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
+
+static int __init pcnet32_init_module(void)
+{
+	pr_info("%s", version);
+
+	pcnet32_debug = netif_msg_init(debug, PCNET32_MSG_DEFAULT);
+
+	if ((tx_start_pt >= 0) && (tx_start_pt <= 3))
+		tx_start = tx_start_pt;
+
+	/* find the PCI devices */
+	if (!pci_register_driver(&pcnet32_driver))
+		pcnet32_have_pci = 1;
+
+	/* should we find any remaining VLbus devices ? */
+	if (pcnet32vlb)
+		pcnet32_probe_vlbus(pcnet32_portlist);
+
+	if (cards_found && (pcnet32_debug & NETIF_MSG_PROBE))
+		pr_info("%d cards_found\n", cards_found);
+
+	return (pcnet32_have_pci + cards_found) ? 0 : -ENODEV;
+}
+
+static void __exit pcnet32_cleanup_module(void)
+{
+	struct net_device *next_dev;
+
+	while (pcnet32_dev) {
+		struct pcnet32_private *lp = netdev_priv(pcnet32_dev);
+		next_dev = lp->next;
+		unregister_netdev(pcnet32_dev);
+		pcnet32_free_ring(pcnet32_dev);
+		release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE);
+		pci_free_consistent(lp->pci_dev, sizeof(*lp->init_block),
+				    lp->init_block, lp->init_dma_addr);
+		free_netdev(pcnet32_dev);
+		pcnet32_dev = next_dev;
+	}
+
+	if (pcnet32_have_pci)
+		pci_unregister_driver(&pcnet32_driver);
+}
+
+module_init(pcnet32_init_module);
+module_exit(pcnet32_cleanup_module);
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  tab-width: 8
+ * End:
+ */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/sun3lance.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/sun3lance.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/sun3lance.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/sun3lance.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,961 @@
+/* sun3lance.c: Ethernet driver for SUN3 Lance chip */
+/*
+
+  Sun3 Lance ethernet driver, by Sam Creasey (sammy@users.qual.net).
+  This driver is a part of the linux kernel, and is thus distributed
+  under the GNU General Public License.
+
+  The values used in LANCE_OBIO and LANCE_IRQ seem to be empirically
+  true for the correct IRQ and address of the lance registers.  They
+  have not been widely tested, however.  What we probably need is a
+  "proper" way to search for a device in the sun3's prom, but, alas,
+  linux has no such thing.
+
+  This driver is largely based on atarilance.c, by Roman Hodek.  Other
+  sources of inspiration were the NetBSD sun3 am7990 driver, and the
+  linux sparc lance driver (sunlance.c).
+
+  There are more assumptions made throughout this driver, it almost
+  certainly still needs work, but it does work at least for RARP/BOOTP and
+  mounting the root NFS filesystem.
+
+*/
+
+static char *version = "sun3lance.c: v1.2 1/12/2001  Sam Creasey (sammy@sammy.net)\n";
+
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/bitops.h>
+
+#include <asm/cacheflush.h>
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/dvma.h>
+#include <asm/idprom.h>
+#include <asm/machines.h>
+
+#ifdef CONFIG_SUN3
+#include <asm/sun3mmu.h>
+#else
+#include <asm/sun3xprom.h>
+#endif
+
+/* sun3/60 addr/irq for the lance chip.  If your sun is different,
+   change this. */
+#define LANCE_OBIO 0x120000
+#define LANCE_IRQ IRQ_AUTO_3
+
+/* Debug level:
+ *  0 = silent, print only serious errors
+ *  1 = normal, print error messages
+ *  2 = debug, print debug infos
+ *  3 = debug, print even more debug infos (packet data)
+ */
+
+#define	LANCE_DEBUG	0
+
+#ifdef LANCE_DEBUG
+static int lance_debug = LANCE_DEBUG;
+#else
+static int lance_debug = 1;
+#endif
+module_param(lance_debug, int, 0);
+MODULE_PARM_DESC(lance_debug, "SUN3 Lance debug level (0-3)");
+MODULE_LICENSE("GPL");
+
+#define	DPRINTK(n,a) \
+	do {  \
+		if (lance_debug >= n)  \
+			printk a; \
+	} while( 0 )
+
+
+/* we're only using 32k of memory, so we use 4 TX
+   buffers and 16 RX buffers.  These values are expressed as log2. */
+
+#define TX_LOG_RING_SIZE			3
+#define RX_LOG_RING_SIZE			5
+
+/* These are the derived values */
+
+#define TX_RING_SIZE			(1 << TX_LOG_RING_SIZE)
+#define TX_RING_LEN_BITS		(TX_LOG_RING_SIZE << 5)
+#define	TX_RING_MOD_MASK		(TX_RING_SIZE - 1)
+
+#define RX_RING_SIZE			(1 << RX_LOG_RING_SIZE)
+#define RX_RING_LEN_BITS		(RX_LOG_RING_SIZE << 5)
+#define	RX_RING_MOD_MASK		(RX_RING_SIZE - 1)
+
+/* Definitions for packet buffer access: */
+#define PKT_BUF_SZ		1544
+
+/* Get the address of a packet buffer corresponding to a given buffer head */
+#define	PKTBUF_ADDR(head)	(void *)((unsigned long)(MEM) | (head)->base)
+
+
+/* The LANCE Rx and Tx ring descriptors. */
+struct lance_rx_head {
+	unsigned short	base;		/* Low word of base addr */
+	volatile unsigned char	flag;
+	unsigned char  base_hi;	/* High word of base addr (unused) */
+	short buf_length;	/* This length is 2s complement! */
+	volatile short msg_length;	/* This length is "normal". */
+};
+
+struct lance_tx_head {
+	unsigned short base;		/* Low word of base addr */
+	volatile unsigned char	flag;
+	unsigned char base_hi;	/* High word of base addr (unused) */
+	short length;		/* Length is 2s complement! */
+	volatile short misc;
+};
+
+/* The LANCE initialization block, described in databook. */
+struct lance_init_block {
+	unsigned short	mode;		/* Pre-set mode */
+	unsigned char	hwaddr[6];	/* Physical ethernet address */
+	unsigned int    filter[2];	/* Multicast filter (unused). */
+	/* Receive and transmit ring base, along with length bits. */
+	unsigned short rdra;
+	unsigned short rlen;
+	unsigned short tdra;
+	unsigned short tlen;
+	unsigned short pad[4]; /* is thie needed? */
+};
+
+/* The whole layout of the Lance shared memory */
+struct lance_memory {
+	struct lance_init_block	init;
+	struct lance_tx_head	tx_head[TX_RING_SIZE];
+	struct lance_rx_head	rx_head[RX_RING_SIZE];
+	char   rx_data[RX_RING_SIZE][PKT_BUF_SZ];
+	char   tx_data[TX_RING_SIZE][PKT_BUF_SZ];
+};
+
+/* The driver's private device structure */
+
+struct lance_private {
+	volatile unsigned short	*iobase;
+	struct lance_memory	*mem;
+     	int new_rx, new_tx;	/* The next free ring entry */
+	int old_tx, old_rx;     /* ring entry to be processed */
+/* These two must be longs for set_bit() */
+	long	    tx_full;
+	long	    lock;
+};
+
+/* I/O register access macros */
+
+#define	MEM	lp->mem
+#define	DREG	lp->iobase[0]
+#define	AREG	lp->iobase[1]
+#define	REGA(a)	(*( AREG = (a), &DREG ))
+
+/* Definitions for the Lance */
+
+/* tx_head flags */
+#define TMD1_ENP		0x01	/* end of packet */
+#define TMD1_STP		0x02	/* start of packet */
+#define TMD1_DEF		0x04	/* deferred */
+#define TMD1_ONE		0x08	/* one retry needed */
+#define TMD1_MORE		0x10	/* more than one retry needed */
+#define TMD1_ERR		0x40	/* error summary */
+#define TMD1_OWN 		0x80	/* ownership (set: chip owns) */
+
+#define TMD1_OWN_CHIP	TMD1_OWN
+#define TMD1_OWN_HOST	0
+
+/* tx_head misc field */
+#define TMD3_TDR		0x03FF	/* Time Domain Reflectometry counter */
+#define TMD3_RTRY		0x0400	/* failed after 16 retries */
+#define TMD3_LCAR		0x0800	/* carrier lost */
+#define TMD3_LCOL		0x1000	/* late collision */
+#define TMD3_UFLO		0x4000	/* underflow (late memory) */
+#define TMD3_BUFF		0x8000	/* buffering error (no ENP) */
+
+/* rx_head flags */
+#define RMD1_ENP		0x01	/* end of packet */
+#define RMD1_STP		0x02	/* start of packet */
+#define RMD1_BUFF		0x04	/* buffer error */
+#define RMD1_CRC		0x08	/* CRC error */
+#define RMD1_OFLO		0x10	/* overflow */
+#define RMD1_FRAM		0x20	/* framing error */
+#define RMD1_ERR		0x40	/* error summary */
+#define RMD1_OWN 		0x80	/* ownership (set: ship owns) */
+
+#define RMD1_OWN_CHIP	RMD1_OWN
+#define RMD1_OWN_HOST	0
+
+/* register names */
+#define CSR0	0		/* mode/status */
+#define CSR1	1		/* init block addr (low) */
+#define CSR2	2		/* init block addr (high) */
+#define CSR3	3		/* misc */
+#define CSR8	8	  	/* address filter */
+#define CSR15	15		/* promiscuous mode */
+
+/* CSR0 */
+/* (R=readable, W=writeable, S=set on write, C=clear on write) */
+#define CSR0_INIT	0x0001		/* initialize (RS) */
+#define CSR0_STRT	0x0002		/* start (RS) */
+#define CSR0_STOP	0x0004		/* stop (RS) */
+#define CSR0_TDMD	0x0008		/* transmit demand (RS) */
+#define CSR0_TXON	0x0010		/* transmitter on (R) */
+#define CSR0_RXON	0x0020		/* receiver on (R) */
+#define CSR0_INEA	0x0040		/* interrupt enable (RW) */
+#define CSR0_INTR	0x0080		/* interrupt active (R) */
+#define CSR0_IDON	0x0100		/* initialization done (RC) */
+#define CSR0_TINT	0x0200		/* transmitter interrupt (RC) */
+#define CSR0_RINT	0x0400		/* receiver interrupt (RC) */
+#define CSR0_MERR	0x0800		/* memory error (RC) */
+#define CSR0_MISS	0x1000		/* missed frame (RC) */
+#define CSR0_CERR	0x2000		/* carrier error (no heartbeat :-) (RC) */
+#define CSR0_BABL	0x4000		/* babble: tx-ed too many bits (RC) */
+#define CSR0_ERR	0x8000		/* error (RC) */
+
+/* CSR3 */
+#define CSR3_BCON	0x0001		/* byte control */
+#define CSR3_ACON	0x0002		/* ALE control */
+#define CSR3_BSWP	0x0004		/* byte swap (1=big endian) */
+
+/***************************** Prototypes *****************************/
+
+static int lance_probe( struct net_device *dev);
+static int lance_open( struct net_device *dev );
+static void lance_init_ring( struct net_device *dev );
+static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev );
+static irqreturn_t lance_interrupt( int irq, void *dev_id);
+static int lance_rx( struct net_device *dev );
+static int lance_close( struct net_device *dev );
+static void set_multicast_list( struct net_device *dev );
+
+/************************* End of Prototypes **************************/
+
+struct net_device * __init sun3lance_probe(int unit)
+{
+	struct net_device *dev;
+	static int found;
+	int err = -ENODEV;
+
+	if (!MACH_IS_SUN3 && !MACH_IS_SUN3X)
+		return ERR_PTR(-ENODEV);
+
+	/* check that this machine has an onboard lance */
+	switch(idprom->id_machtype) {
+	case SM_SUN3|SM_3_50:
+	case SM_SUN3|SM_3_60:
+	case SM_SUN3X|SM_3_80:
+		/* these machines have lance */
+		break;
+
+	default:
+		return ERR_PTR(-ENODEV);
+	}
+
+	if (found)
+		return ERR_PTR(-ENODEV);
+
+	dev = alloc_etherdev(sizeof(struct lance_private));
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+	if (unit >= 0) {
+		sprintf(dev->name, "eth%d", unit);
+		netdev_boot_setup_check(dev);
+	}
+
+	if (!lance_probe(dev))
+		goto out;
+
+	err = register_netdev(dev);
+	if (err)
+		goto out1;
+	found = 1;
+	return dev;
+
+out1:
+#ifdef CONFIG_SUN3
+	iounmap((void __iomem *)dev->base_addr);
+#endif
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+
+static const struct net_device_ops lance_netdev_ops = {
+	.ndo_open		= lance_open,
+	.ndo_stop		= lance_close,
+	.ndo_start_xmit		= lance_start_xmit,
+	.ndo_set_rx_mode	= set_multicast_list,
+	.ndo_set_mac_address	= NULL,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+static int __init lance_probe( struct net_device *dev)
+{
+	unsigned long ioaddr;
+
+	struct lance_private	*lp;
+	int 			i;
+	static int 		did_version;
+	volatile unsigned short *ioaddr_probe;
+	unsigned short tmp1, tmp2;
+
+#ifdef CONFIG_SUN3
+	ioaddr = (unsigned long)ioremap(LANCE_OBIO, PAGE_SIZE);
+	if (!ioaddr)
+		return 0;
+#else
+	ioaddr = SUN3X_LANCE;
+#endif
+
+	/* test to see if there's really a lance here */
+	/* (CSRO_INIT shouldn't be readable) */
+
+	ioaddr_probe = (volatile unsigned short *)ioaddr;
+	tmp1 = ioaddr_probe[0];
+	tmp2 = ioaddr_probe[1];
+
+	ioaddr_probe[1] = CSR0;
+	ioaddr_probe[0] = CSR0_INIT | CSR0_STOP;
+
+	if(ioaddr_probe[0] != CSR0_STOP) {
+		ioaddr_probe[0] = tmp1;
+		ioaddr_probe[1] = tmp2;
+
+#ifdef CONFIG_SUN3
+		iounmap((void __iomem *)ioaddr);
+#endif
+		return 0;
+	}
+
+	lp = netdev_priv(dev);
+
+	/* XXX - leak? */
+	MEM = dvma_malloc_align(sizeof(struct lance_memory), 0x10000);
+	if (MEM == NULL) {
+#ifdef CONFIG_SUN3
+		iounmap((void __iomem *)ioaddr);
+#endif
+		printk(KERN_WARNING "SUN3 Lance couldn't allocate DVMA memory\n");
+		return 0;
+	}
+
+	lp->iobase = (volatile unsigned short *)ioaddr;
+	dev->base_addr = (unsigned long)ioaddr; /* informational only */
+
+	REGA(CSR0) = CSR0_STOP;
+
+	if (request_irq(LANCE_IRQ, lance_interrupt, IRQF_DISABLED, "SUN3 Lance", dev) < 0) {
+#ifdef CONFIG_SUN3
+		iounmap((void __iomem *)ioaddr);
+#endif
+		dvma_free((void *)MEM);
+		printk(KERN_WARNING "SUN3 Lance unable to allocate IRQ\n");
+		return 0;
+	}
+	dev->irq = (unsigned short)LANCE_IRQ;
+
+
+	printk("%s: SUN3 Lance at io %#lx, mem %#lx, irq %d, hwaddr ",
+		   dev->name,
+		   (unsigned long)ioaddr,
+		   (unsigned long)MEM,
+		   dev->irq);
+
+	/* copy in the ethernet address from the prom */
+	for(i = 0; i < 6 ; i++)
+	     dev->dev_addr[i] = idprom->id_ethaddr[i];
+
+	/* tell the card it's ether address, bytes swapped */
+	MEM->init.hwaddr[0] = dev->dev_addr[1];
+	MEM->init.hwaddr[1] = dev->dev_addr[0];
+	MEM->init.hwaddr[2] = dev->dev_addr[3];
+	MEM->init.hwaddr[3] = dev->dev_addr[2];
+	MEM->init.hwaddr[4] = dev->dev_addr[5];
+	MEM->init.hwaddr[5] = dev->dev_addr[4];
+
+	printk("%pM\n", dev->dev_addr);
+
+	MEM->init.mode = 0x0000;
+	MEM->init.filter[0] = 0x00000000;
+	MEM->init.filter[1] = 0x00000000;
+	MEM->init.rdra = dvma_vtob(MEM->rx_head);
+	MEM->init.rlen    = (RX_LOG_RING_SIZE << 13) |
+		(dvma_vtob(MEM->rx_head) >> 16);
+	MEM->init.tdra = dvma_vtob(MEM->tx_head);
+	MEM->init.tlen    = (TX_LOG_RING_SIZE << 13) |
+		(dvma_vtob(MEM->tx_head) >> 16);
+
+	DPRINTK(2, ("initaddr: %08lx rx_ring: %08lx tx_ring: %08lx\n",
+	       dvma_vtob(&(MEM->init)), dvma_vtob(MEM->rx_head),
+	       (dvma_vtob(MEM->tx_head))));
+
+	if (did_version++ == 0)
+		printk( version );
+
+	dev->netdev_ops = &lance_netdev_ops;
+//	KLUDGE -- REMOVE ME
+	set_bit(__LINK_STATE_PRESENT, &dev->state);
+
+
+	return 1;
+}
+
+static int lance_open( struct net_device *dev )
+{
+	struct lance_private *lp = netdev_priv(dev);
+	int i;
+
+	DPRINTK( 2, ( "%s: lance_open()\n", dev->name ));
+
+	REGA(CSR0) = CSR0_STOP;
+
+	lance_init_ring(dev);
+
+	/* From now on, AREG is kept to point to CSR0 */
+	REGA(CSR0) = CSR0_INIT;
+
+	i = 1000000;
+	while (--i > 0)
+		if (DREG & CSR0_IDON)
+			break;
+	if (i <= 0 || (DREG & CSR0_ERR)) {
+		DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n",
+					  dev->name, i, DREG ));
+		DREG = CSR0_STOP;
+		return -EIO;
+	}
+
+	DREG = CSR0_IDON | CSR0_STRT | CSR0_INEA;
+
+	netif_start_queue(dev);
+
+	DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG ));
+
+	return 0;
+}
+
+
+/* Initialize the LANCE Rx and Tx rings. */
+
+static void lance_init_ring( struct net_device *dev )
+{
+	struct lance_private *lp = netdev_priv(dev);
+	int i;
+
+	lp->lock = 0;
+	lp->tx_full = 0;
+	lp->new_rx = lp->new_tx = 0;
+	lp->old_rx = lp->old_tx = 0;
+
+	for( i = 0; i < TX_RING_SIZE; i++ ) {
+		MEM->tx_head[i].base = dvma_vtob(MEM->tx_data[i]);
+		MEM->tx_head[i].flag = 0;
+ 		MEM->tx_head[i].base_hi =
+			(dvma_vtob(MEM->tx_data[i])) >>16;
+		MEM->tx_head[i].length = 0;
+		MEM->tx_head[i].misc = 0;
+	}
+
+	for( i = 0; i < RX_RING_SIZE; i++ ) {
+		MEM->rx_head[i].base = dvma_vtob(MEM->rx_data[i]);
+		MEM->rx_head[i].flag = RMD1_OWN_CHIP;
+		MEM->rx_head[i].base_hi =
+			(dvma_vtob(MEM->rx_data[i])) >> 16;
+		MEM->rx_head[i].buf_length = -PKT_BUF_SZ | 0xf000;
+		MEM->rx_head[i].msg_length = 0;
+	}
+
+	/* tell the card it's ether address, bytes swapped */
+	MEM->init.hwaddr[0] = dev->dev_addr[1];
+	MEM->init.hwaddr[1] = dev->dev_addr[0];
+	MEM->init.hwaddr[2] = dev->dev_addr[3];
+	MEM->init.hwaddr[3] = dev->dev_addr[2];
+	MEM->init.hwaddr[4] = dev->dev_addr[5];
+	MEM->init.hwaddr[5] = dev->dev_addr[4];
+
+	MEM->init.mode = 0x0000;
+	MEM->init.filter[0] = 0x00000000;
+	MEM->init.filter[1] = 0x00000000;
+	MEM->init.rdra = dvma_vtob(MEM->rx_head);
+	MEM->init.rlen    = (RX_LOG_RING_SIZE << 13) |
+		(dvma_vtob(MEM->rx_head) >> 16);
+	MEM->init.tdra = dvma_vtob(MEM->tx_head);
+	MEM->init.tlen    = (TX_LOG_RING_SIZE << 13) |
+		(dvma_vtob(MEM->tx_head) >> 16);
+
+
+	/* tell the lance the address of its init block */
+	REGA(CSR1) = dvma_vtob(&(MEM->init));
+	REGA(CSR2) = dvma_vtob(&(MEM->init)) >> 16;
+
+#ifdef CONFIG_SUN3X
+	REGA(CSR3) = CSR3_BSWP | CSR3_ACON | CSR3_BCON;
+#else
+	REGA(CSR3) = CSR3_BSWP;
+#endif
+
+}
+
+
+static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
+{
+	struct lance_private *lp = netdev_priv(dev);
+	int entry, len;
+	struct lance_tx_head *head;
+	unsigned long flags;
+
+	DPRINTK( 1, ( "%s: transmit start.\n",
+		      dev->name));
+
+	/* Transmitter timeout, serious problems. */
+	if (netif_queue_stopped(dev)) {
+		int tickssofar = jiffies - dev_trans_start(dev);
+		if (tickssofar < HZ/5)
+			return NETDEV_TX_BUSY;
+
+		DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n",
+					  dev->name, DREG ));
+		DREG = CSR0_STOP;
+		/*
+		 * Always set BSWP after a STOP as STOP puts it back into
+		 * little endian mode.
+		 */
+		REGA(CSR3) = CSR3_BSWP;
+		dev->stats.tx_errors++;
+
+		if(lance_debug >= 2) {
+			int i;
+			printk("Ring data: old_tx %d new_tx %d%s new_rx %d\n",
+			       lp->old_tx, lp->new_tx,
+			       lp->tx_full ? " (full)" : "",
+			       lp->new_rx );
+			for( i = 0 ; i < RX_RING_SIZE; i++ )
+				printk( "rx #%d: base=%04x blen=%04x mlen=%04x\n",
+					i, MEM->rx_head[i].base,
+					-MEM->rx_head[i].buf_length,
+					MEM->rx_head[i].msg_length);
+			for( i = 0 ; i < TX_RING_SIZE; i++ )
+				printk("tx #%d: base=%04x len=%04x misc=%04x\n",
+				       i, MEM->tx_head[i].base,
+				       -MEM->tx_head[i].length,
+				       MEM->tx_head[i].misc );
+		}
+
+		lance_init_ring(dev);
+		REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT;
+
+		netif_start_queue(dev);
+
+		return NETDEV_TX_OK;
+	}
+
+
+	/* Block a timer-based transmit from overlapping.  This could better be
+	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+
+	/* Block a timer-based transmit from overlapping with us by
+	   stopping the queue for a bit... */
+
+	netif_stop_queue(dev);
+
+	if (test_and_set_bit( 0, (void*)&lp->lock ) != 0) {
+		printk( "%s: tx queue lock!.\n", dev->name);
+		/* don't clear dev->tbusy flag. */
+		return NETDEV_TX_BUSY;
+	}
+
+	AREG = CSR0;
+  	DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n",
+  				  dev->name, DREG ));
+
+#ifdef CONFIG_SUN3X
+	/* this weirdness doesn't appear on sun3... */
+	if(!(DREG & CSR0_INIT)) {
+		DPRINTK( 1, ("INIT not set, reinitializing...\n"));
+		REGA( CSR0 ) = CSR0_STOP;
+		lance_init_ring(dev);
+		REGA( CSR0 ) = CSR0_INIT | CSR0_STRT;
+	}
+#endif
+
+	/* Fill in a Tx ring entry */
+#if 0
+	if (lance_debug >= 2) {
+		printk( "%s: TX pkt %d type 0x%04x"
+			" from %s to %s"
+			" data at 0x%08x len %d\n",
+			dev->name, lp->new_tx, ((u_short *)skb->data)[6],
+			DEV_ADDR(&skb->data[6]), DEV_ADDR(skb->data),
+			(int)skb->data, (int)skb->len );
+	}
+#endif
+	/* We're not prepared for the int until the last flags are set/reset.
+	 * And the int may happen already after setting the OWN_CHIP... */
+	local_irq_save(flags);
+
+	/* Mask to ring buffer boundary. */
+	entry = lp->new_tx;
+	head  = &(MEM->tx_head[entry]);
+
+	/* Caution: the write order is important here, set the "ownership" bits
+	 * last.
+	 */
+
+	/* the sun3's lance needs it's buffer padded to the minimum
+	   size */
+	len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+
+//	head->length = -len;
+	head->length = (-len) | 0xf000;
+	head->misc = 0;
+
+	skb_copy_from_linear_data(skb, PKTBUF_ADDR(head), skb->len);
+	if (len != skb->len)
+		memset(PKTBUF_ADDR(head) + skb->len, 0, len-skb->len);
+
+	head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP;
+	lp->new_tx = (lp->new_tx + 1) & TX_RING_MOD_MASK;
+	dev->stats.tx_bytes += skb->len;
+
+	/* Trigger an immediate send poll. */
+	REGA(CSR0) = CSR0_INEA | CSR0_TDMD | CSR0_STRT;
+	AREG = CSR0;
+  	DPRINTK( 2, ( "%s: lance_start_xmit() exiting, csr0 %4.4x.\n",
+  				  dev->name, DREG ));
+	dev_kfree_skb(skb);
+
+	lp->lock = 0;
+	if ((MEM->tx_head[(entry+1) & TX_RING_MOD_MASK].flag & TMD1_OWN) ==
+	    TMD1_OWN_HOST)
+		netif_start_queue(dev);
+
+	local_irq_restore(flags);
+
+	return NETDEV_TX_OK;
+}
+
+/* The LANCE interrupt handler. */
+
+static irqreturn_t lance_interrupt( int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct lance_private *lp = netdev_priv(dev);
+	int csr0;
+	static int in_interrupt;
+
+	if (dev == NULL) {
+		DPRINTK( 1, ( "lance_interrupt(): invalid dev_id\n" ));
+		return IRQ_NONE;
+	}
+
+	if (in_interrupt)
+		DPRINTK( 2, ( "%s: Re-entering the interrupt handler.\n", dev->name ));
+	in_interrupt = 1;
+
+ still_more:
+	flush_cache_all();
+
+	AREG = CSR0;
+	csr0 = DREG;
+
+	/* ack interrupts */
+	DREG = csr0 & (CSR0_TINT | CSR0_RINT | CSR0_IDON);
+
+	/* clear errors */
+	if(csr0 & CSR0_ERR)
+		DREG = CSR0_BABL | CSR0_MERR | CSR0_CERR | CSR0_MISS;
+
+
+	DPRINTK( 2, ( "%s: interrupt  csr0=%04x new csr=%04x.\n",
+		      dev->name, csr0, DREG ));
+
+	if (csr0 & CSR0_TINT) {			/* Tx-done interrupt */
+		int old_tx = lp->old_tx;
+
+//		if(lance_debug >= 3) {
+//			int i;
+//
+//			printk("%s: tx int\n", dev->name);
+//
+//			for(i = 0; i < TX_RING_SIZE; i++)
+//				printk("ring %d flag=%04x\n", i,
+//				       MEM->tx_head[i].flag);
+//		}
+
+		while( old_tx != lp->new_tx) {
+			struct lance_tx_head *head = &(MEM->tx_head[old_tx]);
+
+			DPRINTK(3, ("on tx_ring %d\n", old_tx));
+
+			if (head->flag & TMD1_OWN_CHIP)
+				break; /* It still hasn't been Txed */
+
+			if (head->flag & TMD1_ERR) {
+				int status = head->misc;
+				dev->stats.tx_errors++;
+				if (status & TMD3_RTRY) dev->stats.tx_aborted_errors++;
+				if (status & TMD3_LCAR) dev->stats.tx_carrier_errors++;
+				if (status & TMD3_LCOL) dev->stats.tx_window_errors++;
+				if (status & (TMD3_UFLO | TMD3_BUFF)) {
+					dev->stats.tx_fifo_errors++;
+					printk("%s: Tx FIFO error\n",
+					       dev->name);
+					REGA(CSR0) = CSR0_STOP;
+					REGA(CSR3) = CSR3_BSWP;
+					lance_init_ring(dev);
+					REGA(CSR0) = CSR0_STRT | CSR0_INEA;
+					return IRQ_HANDLED;
+				}
+			} else if(head->flag & (TMD1_ENP | TMD1_STP)) {
+
+				head->flag &= ~(TMD1_ENP | TMD1_STP);
+				if(head->flag & (TMD1_ONE | TMD1_MORE))
+					dev->stats.collisions++;
+
+				dev->stats.tx_packets++;
+				DPRINTK(3, ("cleared tx ring %d\n", old_tx));
+			}
+			old_tx = (old_tx +1) & TX_RING_MOD_MASK;
+		}
+
+		lp->old_tx = old_tx;
+	}
+
+
+	if (netif_queue_stopped(dev)) {
+		/* The ring is no longer full, clear tbusy. */
+		netif_start_queue(dev);
+		netif_wake_queue(dev);
+	}
+
+	if (csr0 & CSR0_RINT)			/* Rx interrupt */
+		lance_rx( dev );
+
+	/* Log misc errors. */
+	if (csr0 & CSR0_BABL) dev->stats.tx_errors++; /* Tx babble. */
+	if (csr0 & CSR0_MISS) dev->stats.rx_errors++; /* Missed a Rx frame. */
+	if (csr0 & CSR0_MERR) {
+		DPRINTK( 1, ( "%s: Bus master arbitration failure (?!?), "
+			      "status %04x.\n", dev->name, csr0 ));
+		/* Restart the chip. */
+		REGA(CSR0) = CSR0_STOP;
+		REGA(CSR3) = CSR3_BSWP;
+		lance_init_ring(dev);
+		REGA(CSR0) = CSR0_STRT | CSR0_INEA;
+	}
+
+
+    /* Clear any other interrupt, and set interrupt enable. */
+//	DREG = CSR0_BABL | CSR0_CERR | CSR0_MISS | CSR0_MERR |
+//		   CSR0_IDON | CSR0_INEA;
+
+	REGA(CSR0) = CSR0_INEA;
+
+	if(DREG & (CSR0_RINT | CSR0_TINT)) {
+	     DPRINTK(2, ("restarting interrupt, csr0=%#04x\n", DREG));
+	     goto still_more;
+	}
+
+	DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n",
+				  dev->name, DREG ));
+	in_interrupt = 0;
+	return IRQ_HANDLED;
+}
+
+/* get packet, toss into skbuff */
+static int lance_rx( struct net_device *dev )
+{
+	struct lance_private *lp = netdev_priv(dev);
+	int entry = lp->new_rx;
+
+	/* If we own the next entry, it's a new packet. Send it up. */
+	while( (MEM->rx_head[entry].flag & RMD1_OWN) == RMD1_OWN_HOST ) {
+		struct lance_rx_head *head = &(MEM->rx_head[entry]);
+		int status = head->flag;
+
+		if (status != (RMD1_ENP|RMD1_STP)) {  /* There was an error. */
+			/* There is a tricky error noted by John Murphy,
+			   <murf@perftech.com> to Russ Nelson: Even with
+			   full-sized buffers it's possible for a jabber packet to use two
+			   buffers, with only the last correctly noting the error. */
+			if (status & RMD1_ENP)	/* Only count a general error at the */
+				dev->stats.rx_errors++; /* end of a packet.*/
+			if (status & RMD1_FRAM) dev->stats.rx_frame_errors++;
+			if (status & RMD1_OFLO) dev->stats.rx_over_errors++;
+			if (status & RMD1_CRC) dev->stats.rx_crc_errors++;
+			if (status & RMD1_BUFF) dev->stats.rx_fifo_errors++;
+			head->flag &= (RMD1_ENP|RMD1_STP);
+		} else {
+			/* Malloc up new buffer, compatible with net-3. */
+//			short pkt_len = head->msg_length;// & 0xfff;
+			short pkt_len = (head->msg_length & 0xfff) - 4;
+			struct sk_buff *skb;
+
+			if (pkt_len < 60) {
+				printk( "%s: Runt packet!\n", dev->name );
+				dev->stats.rx_errors++;
+			}
+			else {
+				skb = dev_alloc_skb( pkt_len+2 );
+				if (skb == NULL) {
+					DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n",
+						      dev->name ));
+
+					dev->stats.rx_dropped++;
+					head->msg_length = 0;
+					head->flag |= RMD1_OWN_CHIP;
+					lp->new_rx = (lp->new_rx+1) &
+					     RX_RING_MOD_MASK;
+				}
+
+#if 0
+				if (lance_debug >= 3) {
+					u_char *data = PKTBUF_ADDR(head);
+					printk("%s: RX pkt %d type 0x%04x"
+					       " from %pM to %pM",
+					       dev->name, lp->new_tx, ((u_short *)data)[6],
+					       &data[6], data);
+
+					printk(" data %02x %02x %02x %02x %02x %02x %02x %02x "
+					       "len %d at %08x\n",
+					       data[15], data[16], data[17], data[18],
+					       data[19], data[20], data[21], data[22],
+					       pkt_len, data);
+				}
+#endif
+				if (lance_debug >= 3) {
+					u_char *data = PKTBUF_ADDR(head);
+					printk( "%s: RX pkt %d type 0x%04x len %d\n ", dev->name, entry, ((u_short *)data)[6], pkt_len);
+				}
+
+
+				skb_reserve( skb, 2 );	/* 16 byte align */
+				skb_put( skb, pkt_len );	/* Make room */
+				skb_copy_to_linear_data(skb,
+						 PKTBUF_ADDR(head),
+						 pkt_len);
+
+				skb->protocol = eth_type_trans( skb, dev );
+				netif_rx( skb );
+				dev->stats.rx_packets++;
+				dev->stats.rx_bytes += pkt_len;
+			}
+		}
+
+//		head->buf_length = -PKT_BUF_SZ | 0xf000;
+		head->msg_length = 0;
+		head->flag = RMD1_OWN_CHIP;
+
+		entry = lp->new_rx = (lp->new_rx +1) & RX_RING_MOD_MASK;
+	}
+
+	/* From lance.c (Donald Becker): */
+	/* We should check that at least two ring entries are free.
+	   If not, we should free one and mark stats->rx_dropped++. */
+
+	return 0;
+}
+
+
+static int lance_close( struct net_device *dev )
+{
+	struct lance_private *lp = netdev_priv(dev);
+
+	netif_stop_queue(dev);
+
+	AREG = CSR0;
+
+	DPRINTK( 2, ( "%s: Shutting down ethercard, status was %2.2x.\n",
+				  dev->name, DREG ));
+
+	/* We stop the LANCE here -- it occasionally polls
+	   memory if we don't. */
+	DREG = CSR0_STOP;
+	return 0;
+}
+
+
+/* Set or clear the multicast filter for this adaptor.
+   num_addrs == -1		Promiscuous mode, receive all packets
+   num_addrs == 0		Normal mode, clear multicast list
+   num_addrs > 0		Multicast mode, receive normal and MC packets, and do
+						best-effort filtering.
+ */
+
+/* completely untested on a sun3 */
+static void set_multicast_list( struct net_device *dev )
+{
+	struct lance_private *lp = netdev_priv(dev);
+
+	if(netif_queue_stopped(dev))
+		/* Only possible if board is already started */
+		return;
+
+	/* We take the simple way out and always enable promiscuous mode. */
+	DREG = CSR0_STOP; /* Temporarily stop the lance. */
+
+	if (dev->flags & IFF_PROMISC) {
+		/* Log any net taps. */
+		DPRINTK( 3, ( "%s: Promiscuous mode enabled.\n", dev->name ));
+		REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */
+	} else {
+		short multicast_table[4];
+		int num_addrs = netdev_mc_count(dev);
+		int i;
+		/* We don't use the multicast table, but rely on upper-layer
+		 * filtering. */
+		memset( multicast_table, (num_addrs == 0) ? 0 : -1,
+				sizeof(multicast_table) );
+		for( i = 0; i < 4; i++ )
+			REGA( CSR8+i ) = multicast_table[i];
+		REGA( CSR15 ) = 0; /* Unset promiscuous mode */
+	}
+
+	/*
+	 * Always set BSWP after a STOP as STOP puts it back into
+	 * little endian mode.
+	 */
+	REGA( CSR3 ) = CSR3_BSWP;
+
+	/* Resume normal operation and reset AREG to CSR0 */
+	REGA( CSR0 ) = CSR0_IDON | CSR0_INEA | CSR0_STRT;
+}
+
+
+#ifdef MODULE
+
+static struct net_device *sun3lance_dev;
+
+int __init init_module(void)
+{
+	sun3lance_dev = sun3lance_probe(-1);
+	if (IS_ERR(sun3lance_dev))
+		return PTR_ERR(sun3lance_dev);
+	return 0;
+}
+
+void __exit cleanup_module(void)
+{
+	unregister_netdev(sun3lance_dev);
+#ifdef CONFIG_SUN3
+	iounmap((void __iomem *)sun3lance_dev->base_addr);
+#endif
+	free_netdev(sun3lance_dev);
+}
+
+#endif /* MODULE */
+
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/amd/sunlance.c linux-libre-3.2-gnu/drivers/net/ethernet/amd/sunlance.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/amd/sunlance.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/amd/sunlance.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1556 @@
+/* $Id: sunlance.c,v 1.112 2002/01/15 06:48:55 davem Exp $
+ * lance.c: Linux/Sparc/Lance driver
+ *
+ *	Written 1995, 1996 by Miguel de Icaza
+ * Sources:
+ *	The Linux  depca driver
+ *	The Linux  lance driver.
+ *	The Linux  skeleton driver.
+ *	The NetBSD Sparc/Lance driver.
+ *	Theo de Raadt (deraadt@openbsd.org)
+ *	NCR92C990 Lan Controller manual
+ *
+ * 1.4:
+ *	Added support to run with a ledma on the Sun4m
+ *
+ * 1.5:
+ *	Added multiple card detection.
+ *
+ *	 4/17/96: Burst sizes and tpe selection on sun4m by Eddie C. Dost
+ *		  (ecd@skynet.be)
+ *
+ *	 5/15/96: auto carrier detection on sun4m by Eddie C. Dost
+ *		  (ecd@skynet.be)
+ *
+ *	 5/17/96: lebuffer on scsi/ether cards now work David S. Miller
+ *		  (davem@caip.rutgers.edu)
+ *
+ *	 5/29/96: override option 'tpe-link-test?', if it is 'false', as
+ *		  this disables auto carrier detection on sun4m. Eddie C. Dost
+ *		  (ecd@skynet.be)
+ *
+ * 1.7:
+ *	 6/26/96: Bug fix for multiple ledmas, miguel.
+ *
+ * 1.8:
+ *		  Stole multicast code from depca.c, fixed lance_tx.
+ *
+ * 1.9:
+ *	 8/21/96: Fixed the multicast code (Pedro Roque)
+ *
+ *	 8/28/96: Send fake packet in lance_open() if auto_select is true,
+ *		  so we can detect the carrier loss condition in time.
+ *		  Eddie C. Dost (ecd@skynet.be)
+ *
+ *	 9/15/96: Align rx_buf so that eth_copy_and_sum() won't cause an
+ *		  MNA trap during chksum_partial_copy(). (ecd@skynet.be)
+ *
+ *	11/17/96: Handle LE_C0_MERR in lance_interrupt(). (ecd@skynet.be)
+ *
+ *	12/22/96: Don't loop forever in lance_rx() on incomplete packets.
+ *		  This was the sun4c killer. Shit, stupid bug.
+ *		  (ecd@skynet.be)
+ *
+ * 1.10:
+ *	 1/26/97: Modularize driver. (ecd@skynet.be)
+ *
+ * 1.11:
+ *	12/27/97: Added sun4d support. (jj@sunsite.mff.cuni.cz)
+ *
+ * 1.12:
+ * 	 11/3/99: Fixed SMP race in lance_start_xmit found by davem.
+ * 	          Anton Blanchard (anton@progsoc.uts.edu.au)
+ * 2.00: 11/9/99: Massive overhaul and port to new SBUS driver interfaces.
+ *		  David S. Miller (davem@redhat.com)
+ * 2.01:
+ *      11/08/01: Use library crc32 functions (Matt_Domsch@dell.com)
+ *
+ */
+
+#undef DEBUG_DRIVER
+
+static char lancestr[] = "LANCE";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+#include <linux/errno.h>
+#include <linux/socket.h> /* Used for the temporal inet entries and routing */
+#include <linux/route.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/gfp.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/pgtable.h>
+#include <asm/byteorder.h>	/* Used by the checksum routines */
+#include <asm/idprom.h>
+#include <asm/prom.h>
+#include <asm/auxio.h>		/* For tpe-link-test? setting */
+#include <asm/irq.h>
+
+#define DRV_NAME	"sunlance"
+#define DRV_VERSION	"2.02"
+#define DRV_RELDATE	"8/24/03"
+#define DRV_AUTHOR	"Miguel de Icaza (miguel@nuclecu.unam.mx)"
+
+static char version[] =
+	DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n";
+
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION("Sun Lance ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* Define: 2^4 Tx buffers and 2^4 Rx buffers */
+#ifndef LANCE_LOG_TX_BUFFERS
+#define LANCE_LOG_TX_BUFFERS 4
+#define LANCE_LOG_RX_BUFFERS 4
+#endif
+
+#define LE_CSR0 0
+#define LE_CSR1 1
+#define LE_CSR2 2
+#define LE_CSR3 3
+
+#define LE_MO_PROM      0x8000  /* Enable promiscuous mode */
+
+#define	LE_C0_ERR	0x8000	/* Error: set if BAB, SQE, MISS or ME is set */
+#define	LE_C0_BABL	0x4000	/* BAB:  Babble: tx timeout. */
+#define	LE_C0_CERR	0x2000	/* SQE:  Signal quality error */
+#define	LE_C0_MISS	0x1000	/* MISS: Missed a packet */
+#define	LE_C0_MERR	0x0800	/* ME:   Memory error */
+#define	LE_C0_RINT	0x0400	/* Received interrupt */
+#define	LE_C0_TINT	0x0200	/* Transmitter Interrupt */
+#define	LE_C0_IDON	0x0100	/* IFIN: Init finished. */
+#define	LE_C0_INTR	0x0080	/* Interrupt or error */
+#define	LE_C0_INEA	0x0040	/* Interrupt enable */
+#define	LE_C0_RXON	0x0020	/* Receiver on */
+#define	LE_C0_TXON	0x0010	/* Transmitter on */
+#define	LE_C0_TDMD	0x0008	/* Transmitter demand */
+#define	LE_C0_STOP	0x0004	/* Stop the card */
+#define	LE_C0_STRT	0x0002	/* Start the card */
+#define	LE_C0_INIT	0x0001	/* Init the card */
+
+#define	LE_C3_BSWP	0x4     /* SWAP */
+#define	LE_C3_ACON	0x2	/* ALE Control */
+#define	LE_C3_BCON	0x1	/* Byte control */
+
+/* Receive message descriptor 1 */
+#define LE_R1_OWN       0x80    /* Who owns the entry */
+#define LE_R1_ERR       0x40    /* Error: if FRA, OFL, CRC or BUF is set */
+#define LE_R1_FRA       0x20    /* FRA: Frame error */
+#define LE_R1_OFL       0x10    /* OFL: Frame overflow */
+#define LE_R1_CRC       0x08    /* CRC error */
+#define LE_R1_BUF       0x04    /* BUF: Buffer error */
+#define LE_R1_SOP       0x02    /* Start of packet */
+#define LE_R1_EOP       0x01    /* End of packet */
+#define LE_R1_POK       0x03    /* Packet is complete: SOP + EOP */
+
+#define LE_T1_OWN       0x80    /* Lance owns the packet */
+#define LE_T1_ERR       0x40    /* Error summary */
+#define LE_T1_EMORE     0x10    /* Error: more than one retry needed */
+#define LE_T1_EONE      0x08    /* Error: one retry needed */
+#define LE_T1_EDEF      0x04    /* Error: deferred */
+#define LE_T1_SOP       0x02    /* Start of packet */
+#define LE_T1_EOP       0x01    /* End of packet */
+#define LE_T1_POK	0x03	/* Packet is complete: SOP + EOP */
+
+#define LE_T3_BUF       0x8000  /* Buffer error */
+#define LE_T3_UFL       0x4000  /* Error underflow */
+#define LE_T3_LCOL      0x1000  /* Error late collision */
+#define LE_T3_CLOS      0x0800  /* Error carrier loss */
+#define LE_T3_RTY       0x0400  /* Error retry */
+#define LE_T3_TDR       0x03ff  /* Time Domain Reflectometry counter */
+
+#define TX_RING_SIZE			(1 << (LANCE_LOG_TX_BUFFERS))
+#define TX_RING_MOD_MASK		(TX_RING_SIZE - 1)
+#define TX_RING_LEN_BITS		((LANCE_LOG_TX_BUFFERS) << 29)
+#define TX_NEXT(__x)			(((__x)+1) & TX_RING_MOD_MASK)
+
+#define RX_RING_SIZE			(1 << (LANCE_LOG_RX_BUFFERS))
+#define RX_RING_MOD_MASK		(RX_RING_SIZE - 1)
+#define RX_RING_LEN_BITS		((LANCE_LOG_RX_BUFFERS) << 29)
+#define RX_NEXT(__x)			(((__x)+1) & RX_RING_MOD_MASK)
+
+#define PKT_BUF_SZ		1544
+#define RX_BUFF_SIZE            PKT_BUF_SZ
+#define TX_BUFF_SIZE            PKT_BUF_SZ
+
+struct lance_rx_desc {
+	u16	rmd0;		/* low address of packet */
+	u8	rmd1_bits;	/* descriptor bits */
+	u8	rmd1_hadr;	/* high address of packet */
+	s16	length;		/* This length is 2s complement (negative)!
+				 * Buffer length
+				 */
+	u16	mblength;	/* This is the actual number of bytes received */
+};
+
+struct lance_tx_desc {
+	u16	tmd0;		/* low address of packet */
+	u8 	tmd1_bits;	/* descriptor bits */
+	u8 	tmd1_hadr;	/* high address of packet */
+	s16 	length;		/* Length is 2s complement (negative)! */
+	u16 	misc;
+};
+
+/* The LANCE initialization block, described in databook. */
+/* On the Sparc, this block should be on a DMA region     */
+struct lance_init_block {
+	u16	mode;		/* Pre-set mode (reg. 15) */
+	u8	phys_addr[6];	/* Physical ethernet address */
+	u32	filter[2];	/* Multicast filter. */
+
+	/* Receive and transmit ring base, along with extra bits. */
+	u16	rx_ptr;		/* receive descriptor addr */
+	u16	rx_len;		/* receive len and high addr */
+	u16	tx_ptr;		/* transmit descriptor addr */
+	u16	tx_len;		/* transmit len and high addr */
+
+	/* The Tx and Rx ring entries must aligned on 8-byte boundaries. */
+	struct lance_rx_desc brx_ring[RX_RING_SIZE];
+	struct lance_tx_desc btx_ring[TX_RING_SIZE];
+
+	u8	tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
+	u8	pad[2];		/* align rx_buf for copy_and_sum(). */
+	u8	rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
+};
+
+#define libdesc_offset(rt, elem) \
+((__u32)(((unsigned long)(&(((struct lance_init_block *)0)->rt[elem])))))
+
+#define libbuff_offset(rt, elem) \
+((__u32)(((unsigned long)(&(((struct lance_init_block *)0)->rt[elem][0])))))
+
+struct lance_private {
+	void __iomem	*lregs;		/* Lance RAP/RDP regs.		*/
+	void __iomem	*dregs;		/* DMA controller regs.		*/
+	struct lance_init_block __iomem *init_block_iomem;
+	struct lance_init_block *init_block_mem;
+
+	spinlock_t	lock;
+
+	int		rx_new, tx_new;
+	int		rx_old, tx_old;
+
+	struct platform_device *ledma;	/* If set this points to ledma	*/
+	char		tpe;		/* cable-selection is TPE	*/
+	char		auto_select;	/* cable-selection by carrier	*/
+	char		burst_sizes;	/* ledma SBus burst sizes	*/
+	char		pio_buffer;	/* init block in PIO space?	*/
+
+	unsigned short	busmaster_regval;
+
+	void (*init_ring)(struct net_device *);
+	void (*rx)(struct net_device *);
+	void (*tx)(struct net_device *);
+
+	char	       	       *name;
+	dma_addr_t		init_block_dvma;
+	struct net_device      *dev;		  /* Backpointer	*/
+	struct platform_device       *op;
+	struct platform_device       *lebuffer;
+	struct timer_list       multicast_timer;
+};
+
+#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
+			lp->tx_old+TX_RING_MOD_MASK-lp->tx_new:\
+			lp->tx_old - lp->tx_new-1)
+
+/* Lance registers. */
+#define RDP		0x00UL		/* register data port		*/
+#define RAP		0x02UL		/* register address port	*/
+#define LANCE_REG_SIZE	0x04UL
+
+#define STOP_LANCE(__lp) \
+do {	void __iomem *__base = (__lp)->lregs; \
+	sbus_writew(LE_CSR0,	__base + RAP); \
+	sbus_writew(LE_C0_STOP,	__base + RDP); \
+} while (0)
+
+int sparc_lance_debug = 2;
+
+/* The Lance uses 24 bit addresses */
+/* On the Sun4c the DVMA will provide the remaining bytes for us */
+/* On the Sun4m we have to instruct the ledma to provide them    */
+/* Even worse, on scsi/ether SBUS cards, the init block and the
+ * transmit/receive buffers are addresses as offsets from absolute
+ * zero on the lebuffer PIO area. -DaveM
+ */
+
+#define LANCE_ADDR(x) ((long)(x) & ~0xff000000)
+
+/* Load the CSR registers */
+static void load_csrs(struct lance_private *lp)
+{
+	u32 leptr;
+
+	if (lp->pio_buffer)
+		leptr = 0;
+	else
+		leptr = LANCE_ADDR(lp->init_block_dvma);
+
+	sbus_writew(LE_CSR1,		  lp->lregs + RAP);
+	sbus_writew(leptr & 0xffff,	  lp->lregs + RDP);
+	sbus_writew(LE_CSR2,		  lp->lregs + RAP);
+	sbus_writew(leptr >> 16,	  lp->lregs + RDP);
+	sbus_writew(LE_CSR3,		  lp->lregs + RAP);
+	sbus_writew(lp->busmaster_regval, lp->lregs + RDP);
+
+	/* Point back to csr0 */
+	sbus_writew(LE_CSR0, lp->lregs + RAP);
+}
+
+/* Setup the Lance Rx and Tx rings */
+static void lance_init_ring_dvma(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	struct lance_init_block *ib = lp->init_block_mem;
+	dma_addr_t aib = lp->init_block_dvma;
+	__u32 leptr;
+	int i;
+
+	/* Lock out other processes while setting up hardware */
+	netif_stop_queue(dev);
+	lp->rx_new = lp->tx_new = 0;
+	lp->rx_old = lp->tx_old = 0;
+
+	/* Copy the ethernet address to the lance init block
+	 * Note that on the sparc you need to swap the ethernet address.
+	 */
+	ib->phys_addr [0] = dev->dev_addr [1];
+	ib->phys_addr [1] = dev->dev_addr [0];
+	ib->phys_addr [2] = dev->dev_addr [3];
+	ib->phys_addr [3] = dev->dev_addr [2];
+	ib->phys_addr [4] = dev->dev_addr [5];
+	ib->phys_addr [5] = dev->dev_addr [4];
+
+	/* Setup the Tx ring entries */
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		leptr = LANCE_ADDR(aib + libbuff_offset(tx_buf, i));
+		ib->btx_ring [i].tmd0      = leptr;
+		ib->btx_ring [i].tmd1_hadr = leptr >> 16;
+		ib->btx_ring [i].tmd1_bits = 0;
+		ib->btx_ring [i].length    = 0xf000; /* The ones required by tmd2 */
+		ib->btx_ring [i].misc      = 0;
+	}
+
+	/* Setup the Rx ring entries */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		leptr = LANCE_ADDR(aib + libbuff_offset(rx_buf, i));
+
+		ib->brx_ring [i].rmd0      = leptr;
+		ib->brx_ring [i].rmd1_hadr = leptr >> 16;
+		ib->brx_ring [i].rmd1_bits = LE_R1_OWN;
+		ib->brx_ring [i].length    = -RX_BUFF_SIZE | 0xf000;
+		ib->brx_ring [i].mblength  = 0;
+	}
+
+	/* Setup the initialization block */
+
+	/* Setup rx descriptor pointer */
+	leptr = LANCE_ADDR(aib + libdesc_offset(brx_ring, 0));
+	ib->rx_len = (LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16);
+	ib->rx_ptr = leptr;
+
+	/* Setup tx descriptor pointer */
+	leptr = LANCE_ADDR(aib + libdesc_offset(btx_ring, 0));
+	ib->tx_len = (LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16);
+	ib->tx_ptr = leptr;
+}
+
+static void lance_init_ring_pio(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	struct lance_init_block __iomem *ib = lp->init_block_iomem;
+	u32 leptr;
+	int i;
+
+	/* Lock out other processes while setting up hardware */
+	netif_stop_queue(dev);
+	lp->rx_new = lp->tx_new = 0;
+	lp->rx_old = lp->tx_old = 0;
+
+	/* Copy the ethernet address to the lance init block
+	 * Note that on the sparc you need to swap the ethernet address.
+	 */
+	sbus_writeb(dev->dev_addr[1], &ib->phys_addr[0]);
+	sbus_writeb(dev->dev_addr[0], &ib->phys_addr[1]);
+	sbus_writeb(dev->dev_addr[3], &ib->phys_addr[2]);
+	sbus_writeb(dev->dev_addr[2], &ib->phys_addr[3]);
+	sbus_writeb(dev->dev_addr[5], &ib->phys_addr[4]);
+	sbus_writeb(dev->dev_addr[4], &ib->phys_addr[5]);
+
+	/* Setup the Tx ring entries */
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		leptr = libbuff_offset(tx_buf, i);
+		sbus_writew(leptr,	&ib->btx_ring [i].tmd0);
+		sbus_writeb(leptr >> 16,&ib->btx_ring [i].tmd1_hadr);
+		sbus_writeb(0,		&ib->btx_ring [i].tmd1_bits);
+
+		/* The ones required by tmd2 */
+		sbus_writew(0xf000,	&ib->btx_ring [i].length);
+		sbus_writew(0,		&ib->btx_ring [i].misc);
+	}
+
+	/* Setup the Rx ring entries */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		leptr = libbuff_offset(rx_buf, i);
+
+		sbus_writew(leptr,	&ib->brx_ring [i].rmd0);
+		sbus_writeb(leptr >> 16,&ib->brx_ring [i].rmd1_hadr);
+		sbus_writeb(LE_R1_OWN,	&ib->brx_ring [i].rmd1_bits);
+		sbus_writew(-RX_BUFF_SIZE|0xf000,
+			    &ib->brx_ring [i].length);
+		sbus_writew(0,		&ib->brx_ring [i].mblength);
+	}
+
+	/* Setup the initialization block */
+
+	/* Setup rx descriptor pointer */
+	leptr = libdesc_offset(brx_ring, 0);
+	sbus_writew((LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16),
+		    &ib->rx_len);
+	sbus_writew(leptr, &ib->rx_ptr);
+
+	/* Setup tx descriptor pointer */
+	leptr = libdesc_offset(btx_ring, 0);
+	sbus_writew((LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16),
+		    &ib->tx_len);
+	sbus_writew(leptr, &ib->tx_ptr);
+}
+
+static void init_restart_ledma(struct lance_private *lp)
+{
+	u32 csr = sbus_readl(lp->dregs + DMA_CSR);
+
+	if (!(csr & DMA_HNDL_ERROR)) {
+		/* E-Cache draining */
+		while (sbus_readl(lp->dregs + DMA_CSR) & DMA_FIFO_ISDRAIN)
+			barrier();
+	}
+
+	csr = sbus_readl(lp->dregs + DMA_CSR);
+	csr &= ~DMA_E_BURSTS;
+	if (lp->burst_sizes & DMA_BURST32)
+		csr |= DMA_E_BURST32;
+	else
+		csr |= DMA_E_BURST16;
+
+	csr |= (DMA_DSBL_RD_DRN | DMA_DSBL_WR_INV | DMA_FIFO_INV);
+
+	if (lp->tpe)
+		csr |= DMA_EN_ENETAUI;
+	else
+		csr &= ~DMA_EN_ENETAUI;
+	udelay(20);
+	sbus_writel(csr, lp->dregs + DMA_CSR);
+	udelay(200);
+}
+
+static int init_restart_lance(struct lance_private *lp)
+{
+	u16 regval = 0;
+	int i;
+
+	if (lp->dregs)
+		init_restart_ledma(lp);
+
+	sbus_writew(LE_CSR0,	lp->lregs + RAP);
+	sbus_writew(LE_C0_INIT,	lp->lregs + RDP);
+
+	/* Wait for the lance to complete initialization */
+	for (i = 0; i < 100; i++) {
+		regval = sbus_readw(lp->lregs + RDP);
+
+		if (regval & (LE_C0_ERR | LE_C0_IDON))
+			break;
+		barrier();
+	}
+	if (i == 100 || (regval & LE_C0_ERR)) {
+		printk(KERN_ERR "LANCE unopened after %d ticks, csr0=%4.4x.\n",
+		       i, regval);
+		if (lp->dregs)
+			printk("dcsr=%8.8x\n", sbus_readl(lp->dregs + DMA_CSR));
+		return -1;
+	}
+
+	/* Clear IDON by writing a "1", enable interrupts and start lance */
+	sbus_writew(LE_C0_IDON,			lp->lregs + RDP);
+	sbus_writew(LE_C0_INEA | LE_C0_STRT,	lp->lregs + RDP);
+
+	if (lp->dregs) {
+		u32 csr = sbus_readl(lp->dregs + DMA_CSR);
+
+		csr |= DMA_INT_ENAB;
+		sbus_writel(csr, lp->dregs + DMA_CSR);
+	}
+
+	return 0;
+}
+
+static void lance_rx_dvma(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	struct lance_init_block *ib = lp->init_block_mem;
+	struct lance_rx_desc *rd;
+	u8 bits;
+	int len, entry = lp->rx_new;
+	struct sk_buff *skb;
+
+	for (rd = &ib->brx_ring [entry];
+	     !((bits = rd->rmd1_bits) & LE_R1_OWN);
+	     rd = &ib->brx_ring [entry]) {
+
+		/* We got an incomplete frame? */
+		if ((bits & LE_R1_POK) != LE_R1_POK) {
+			dev->stats.rx_over_errors++;
+			dev->stats.rx_errors++;
+		} else if (bits & LE_R1_ERR) {
+			/* Count only the end frame as a rx error,
+			 * not the beginning
+			 */
+			if (bits & LE_R1_BUF) dev->stats.rx_fifo_errors++;
+			if (bits & LE_R1_CRC) dev->stats.rx_crc_errors++;
+			if (bits & LE_R1_OFL) dev->stats.rx_over_errors++;
+			if (bits & LE_R1_FRA) dev->stats.rx_frame_errors++;
+			if (bits & LE_R1_EOP) dev->stats.rx_errors++;
+		} else {
+			len = (rd->mblength & 0xfff) - 4;
+			skb = dev_alloc_skb(len + 2);
+
+			if (skb == NULL) {
+				printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n",
+				       dev->name);
+				dev->stats.rx_dropped++;
+				rd->mblength = 0;
+				rd->rmd1_bits = LE_R1_OWN;
+				lp->rx_new = RX_NEXT(entry);
+				return;
+			}
+
+			dev->stats.rx_bytes += len;
+
+			skb_reserve(skb, 2);		/* 16 byte align */
+			skb_put(skb, len);		/* make room */
+			skb_copy_to_linear_data(skb,
+					 (unsigned char *)&(ib->rx_buf [entry][0]),
+					 len);
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+			dev->stats.rx_packets++;
+		}
+
+		/* Return the packet to the pool */
+		rd->mblength = 0;
+		rd->rmd1_bits = LE_R1_OWN;
+		entry = RX_NEXT(entry);
+	}
+
+	lp->rx_new = entry;
+}
+
+static void lance_tx_dvma(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	struct lance_init_block *ib = lp->init_block_mem;
+	int i, j;
+
+	spin_lock(&lp->lock);
+
+	j = lp->tx_old;
+	for (i = j; i != lp->tx_new; i = j) {
+		struct lance_tx_desc *td = &ib->btx_ring [i];
+		u8 bits = td->tmd1_bits;
+
+		/* If we hit a packet not owned by us, stop */
+		if (bits & LE_T1_OWN)
+			break;
+
+		if (bits & LE_T1_ERR) {
+			u16 status = td->misc;
+
+			dev->stats.tx_errors++;
+			if (status & LE_T3_RTY)  dev->stats.tx_aborted_errors++;
+			if (status & LE_T3_LCOL) dev->stats.tx_window_errors++;
+
+			if (status & LE_T3_CLOS) {
+				dev->stats.tx_carrier_errors++;
+				if (lp->auto_select) {
+					lp->tpe = 1 - lp->tpe;
+					printk(KERN_NOTICE "%s: Carrier Lost, trying %s\n",
+					       dev->name, lp->tpe?"TPE":"AUI");
+					STOP_LANCE(lp);
+					lp->init_ring(dev);
+					load_csrs(lp);
+					init_restart_lance(lp);
+					goto out;
+				}
+			}
+
+			/* Buffer errors and underflows turn off the
+			 * transmitter, restart the adapter.
+			 */
+			if (status & (LE_T3_BUF|LE_T3_UFL)) {
+				dev->stats.tx_fifo_errors++;
+
+				printk(KERN_ERR "%s: Tx: ERR_BUF|ERR_UFL, restarting\n",
+				       dev->name);
+				STOP_LANCE(lp);
+				lp->init_ring(dev);
+				load_csrs(lp);
+				init_restart_lance(lp);
+				goto out;
+			}
+		} else if ((bits & LE_T1_POK) == LE_T1_POK) {
+			/*
+			 * So we don't count the packet more than once.
+			 */
+			td->tmd1_bits = bits & ~(LE_T1_POK);
+
+			/* One collision before packet was sent. */
+			if (bits & LE_T1_EONE)
+				dev->stats.collisions++;
+
+			/* More than one collision, be optimistic. */
+			if (bits & LE_T1_EMORE)
+				dev->stats.collisions += 2;
+
+			dev->stats.tx_packets++;
+		}
+
+		j = TX_NEXT(j);
+	}
+	lp->tx_old = j;
+out:
+	if (netif_queue_stopped(dev) &&
+	    TX_BUFFS_AVAIL > 0)
+		netif_wake_queue(dev);
+
+	spin_unlock(&lp->lock);
+}
+
+static void lance_piocopy_to_skb(struct sk_buff *skb, void __iomem *piobuf, int len)
+{
+	u16 *p16 = (u16 *) skb->data;
+	u32 *p32;
+	u8 *p8;
+	void __iomem *pbuf = piobuf;
+
+	/* We know here that both src and dest are on a 16bit boundary. */
+	*p16++ = sbus_readw(pbuf);
+	p32 = (u32 *) p16;
+	pbuf += 2;
+	len -= 2;
+
+	while (len >= 4) {
+		*p32++ = sbus_readl(pbuf);
+		pbuf += 4;
+		len -= 4;
+	}
+	p8 = (u8 *) p32;
+	if (len >= 2) {
+		p16 = (u16 *) p32;
+		*p16++ = sbus_readw(pbuf);
+		pbuf += 2;
+		len -= 2;
+		p8 = (u8 *) p16;
+	}
+	if (len >= 1)
+		*p8 = sbus_readb(pbuf);
+}
+
+static void lance_rx_pio(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	struct lance_init_block __iomem *ib = lp->init_block_iomem;
+	struct lance_rx_desc __iomem *rd;
+	unsigned char bits;
+	int len, entry;
+	struct sk_buff *skb;
+
+	entry = lp->rx_new;
+	for (rd = &ib->brx_ring [entry];
+	     !((bits = sbus_readb(&rd->rmd1_bits)) & LE_R1_OWN);
+	     rd = &ib->brx_ring [entry]) {
+
+		/* We got an incomplete frame? */
+		if ((bits & LE_R1_POK) != LE_R1_POK) {
+			dev->stats.rx_over_errors++;
+			dev->stats.rx_errors++;
+		} else if (bits & LE_R1_ERR) {
+			/* Count only the end frame as a rx error,
+			 * not the beginning
+			 */
+			if (bits & LE_R1_BUF) dev->stats.rx_fifo_errors++;
+			if (bits & LE_R1_CRC) dev->stats.rx_crc_errors++;
+			if (bits & LE_R1_OFL) dev->stats.rx_over_errors++;
+			if (bits & LE_R1_FRA) dev->stats.rx_frame_errors++;
+			if (bits & LE_R1_EOP) dev->stats.rx_errors++;
+		} else {
+			len = (sbus_readw(&rd->mblength) & 0xfff) - 4;
+			skb = dev_alloc_skb(len + 2);
+
+			if (skb == NULL) {
+				printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n",
+				       dev->name);
+				dev->stats.rx_dropped++;
+				sbus_writew(0, &rd->mblength);
+				sbus_writeb(LE_R1_OWN, &rd->rmd1_bits);
+				lp->rx_new = RX_NEXT(entry);
+				return;
+			}
+
+			dev->stats.rx_bytes += len;
+
+			skb_reserve (skb, 2);		/* 16 byte align */
+			skb_put(skb, len);		/* make room */
+			lance_piocopy_to_skb(skb, &(ib->rx_buf[entry][0]), len);
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+			dev->stats.rx_packets++;
+		}
+
+		/* Return the packet to the pool */
+		sbus_writew(0, &rd->mblength);
+		sbus_writeb(LE_R1_OWN, &rd->rmd1_bits);
+		entry = RX_NEXT(entry);
+	}
+
+	lp->rx_new = entry;
+}
+
+static void lance_tx_pio(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	struct lance_init_block __iomem *ib = lp->init_block_iomem;
+	int i, j;
+
+	spin_lock(&lp->lock);
+
+	j = lp->tx_old;
+	for (i = j; i != lp->tx_new; i = j) {
+		struct lance_tx_desc __iomem *td = &ib->btx_ring [i];
+		u8 bits = sbus_readb(&td->tmd1_bits);
+
+		/* If we hit a packet not owned by us, stop */
+		if (bits & LE_T1_OWN)
+			break;
+
+		if (bits & LE_T1_ERR) {
+			u16 status = sbus_readw(&td->misc);
+
+			dev->stats.tx_errors++;
+			if (status & LE_T3_RTY)  dev->stats.tx_aborted_errors++;
+			if (status & LE_T3_LCOL) dev->stats.tx_window_errors++;
+
+			if (status & LE_T3_CLOS) {
+				dev->stats.tx_carrier_errors++;
+				if (lp->auto_select) {
+					lp->tpe = 1 - lp->tpe;
+					printk(KERN_NOTICE "%s: Carrier Lost, trying %s\n",
+					       dev->name, lp->tpe?"TPE":"AUI");
+					STOP_LANCE(lp);
+					lp->init_ring(dev);
+					load_csrs(lp);
+					init_restart_lance(lp);
+					goto out;
+				}
+			}
+
+			/* Buffer errors and underflows turn off the
+			 * transmitter, restart the adapter.
+			 */
+			if (status & (LE_T3_BUF|LE_T3_UFL)) {
+				dev->stats.tx_fifo_errors++;
+
+				printk(KERN_ERR "%s: Tx: ERR_BUF|ERR_UFL, restarting\n",
+				       dev->name);
+				STOP_LANCE(lp);
+				lp->init_ring(dev);
+				load_csrs(lp);
+				init_restart_lance(lp);
+				goto out;
+			}
+		} else if ((bits & LE_T1_POK) == LE_T1_POK) {
+			/*
+			 * So we don't count the packet more than once.
+			 */
+			sbus_writeb(bits & ~(LE_T1_POK), &td->tmd1_bits);
+
+			/* One collision before packet was sent. */
+			if (bits & LE_T1_EONE)
+				dev->stats.collisions++;
+
+			/* More than one collision, be optimistic. */
+			if (bits & LE_T1_EMORE)
+				dev->stats.collisions += 2;
+
+			dev->stats.tx_packets++;
+		}
+
+		j = TX_NEXT(j);
+	}
+	lp->tx_old = j;
+
+	if (netif_queue_stopped(dev) &&
+	    TX_BUFFS_AVAIL > 0)
+		netif_wake_queue(dev);
+out:
+	spin_unlock(&lp->lock);
+}
+
+static irqreturn_t lance_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct lance_private *lp = netdev_priv(dev);
+	int csr0;
+
+	sbus_writew(LE_CSR0, lp->lregs + RAP);
+	csr0 = sbus_readw(lp->lregs + RDP);
+
+	/* Acknowledge all the interrupt sources ASAP */
+	sbus_writew(csr0 & (LE_C0_INTR | LE_C0_TINT | LE_C0_RINT),
+		    lp->lregs + RDP);
+
+	if ((csr0 & LE_C0_ERR) != 0) {
+		/* Clear the error condition */
+		sbus_writew((LE_C0_BABL | LE_C0_ERR | LE_C0_MISS |
+			     LE_C0_CERR | LE_C0_MERR),
+			    lp->lregs + RDP);
+	}
+
+	if (csr0 & LE_C0_RINT)
+		lp->rx(dev);
+
+	if (csr0 & LE_C0_TINT)
+		lp->tx(dev);
+
+	if (csr0 & LE_C0_BABL)
+		dev->stats.tx_errors++;
+
+	if (csr0 & LE_C0_MISS)
+		dev->stats.rx_errors++;
+
+	if (csr0 & LE_C0_MERR) {
+		if (lp->dregs) {
+			u32 addr = sbus_readl(lp->dregs + DMA_ADDR);
+
+			printk(KERN_ERR "%s: Memory error, status %04x, addr %06x\n",
+			       dev->name, csr0, addr & 0xffffff);
+		} else {
+			printk(KERN_ERR "%s: Memory error, status %04x\n",
+			       dev->name, csr0);
+		}
+
+		sbus_writew(LE_C0_STOP, lp->lregs + RDP);
+
+		if (lp->dregs) {
+			u32 dma_csr = sbus_readl(lp->dregs + DMA_CSR);
+
+			dma_csr |= DMA_FIFO_INV;
+			sbus_writel(dma_csr, lp->dregs + DMA_CSR);
+		}
+
+		lp->init_ring(dev);
+		load_csrs(lp);
+		init_restart_lance(lp);
+		netif_wake_queue(dev);
+	}
+
+	sbus_writew(LE_C0_INEA, lp->lregs + RDP);
+
+	return IRQ_HANDLED;
+}
+
+/* Build a fake network packet and send it to ourselves. */
+static void build_fake_packet(struct lance_private *lp)
+{
+	struct net_device *dev = lp->dev;
+	int i, entry;
+
+	entry = lp->tx_new & TX_RING_MOD_MASK;
+	if (lp->pio_buffer) {
+		struct lance_init_block __iomem *ib = lp->init_block_iomem;
+		u16 __iomem *packet = (u16 __iomem *) &(ib->tx_buf[entry][0]);
+		struct ethhdr __iomem *eth = (struct ethhdr __iomem *) packet;
+		for (i = 0; i < (ETH_ZLEN / sizeof(u16)); i++)
+			sbus_writew(0, &packet[i]);
+		for (i = 0; i < 6; i++) {
+			sbus_writeb(dev->dev_addr[i], &eth->h_dest[i]);
+			sbus_writeb(dev->dev_addr[i], &eth->h_source[i]);
+		}
+		sbus_writew((-ETH_ZLEN) | 0xf000, &ib->btx_ring[entry].length);
+		sbus_writew(0, &ib->btx_ring[entry].misc);
+		sbus_writeb(LE_T1_POK|LE_T1_OWN, &ib->btx_ring[entry].tmd1_bits);
+	} else {
+		struct lance_init_block *ib = lp->init_block_mem;
+		u16 *packet = (u16 *) &(ib->tx_buf[entry][0]);
+		struct ethhdr *eth = (struct ethhdr *) packet;
+		memset(packet, 0, ETH_ZLEN);
+		for (i = 0; i < 6; i++) {
+			eth->h_dest[i] = dev->dev_addr[i];
+			eth->h_source[i] = dev->dev_addr[i];
+		}
+		ib->btx_ring[entry].length = (-ETH_ZLEN) | 0xf000;
+		ib->btx_ring[entry].misc = 0;
+		ib->btx_ring[entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
+	}
+	lp->tx_new = TX_NEXT(entry);
+}
+
+static int lance_open(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	int status = 0;
+
+	STOP_LANCE(lp);
+
+	if (request_irq(dev->irq, lance_interrupt, IRQF_SHARED,
+			lancestr, (void *) dev)) {
+		printk(KERN_ERR "Lance: Can't get irq %d\n", dev->irq);
+		return -EAGAIN;
+	}
+
+	/* On the 4m, setup the ledma to provide the upper bits for buffers */
+	if (lp->dregs) {
+		u32 regval = lp->init_block_dvma & 0xff000000;
+
+		sbus_writel(regval, lp->dregs + DMA_TEST);
+	}
+
+	/* Set mode and clear multicast filter only at device open,
+	 * so that lance_init_ring() called at any error will not
+	 * forget multicast filters.
+	 *
+	 * BTW it is common bug in all lance drivers! --ANK
+	 */
+	if (lp->pio_buffer) {
+		struct lance_init_block __iomem *ib = lp->init_block_iomem;
+		sbus_writew(0, &ib->mode);
+		sbus_writel(0, &ib->filter[0]);
+		sbus_writel(0, &ib->filter[1]);
+	} else {
+		struct lance_init_block *ib = lp->init_block_mem;
+		ib->mode = 0;
+		ib->filter [0] = 0;
+		ib->filter [1] = 0;
+	}
+
+	lp->init_ring(dev);
+	load_csrs(lp);
+
+	netif_start_queue(dev);
+
+	status = init_restart_lance(lp);
+	if (!status && lp->auto_select) {
+		build_fake_packet(lp);
+		sbus_writew(LE_C0_INEA | LE_C0_TDMD, lp->lregs + RDP);
+	}
+
+	return status;
+}
+
+static int lance_close(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+
+	netif_stop_queue(dev);
+	del_timer_sync(&lp->multicast_timer);
+
+	STOP_LANCE(lp);
+
+	free_irq(dev->irq, (void *) dev);
+	return 0;
+}
+
+static int lance_reset(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	int status;
+
+	STOP_LANCE(lp);
+
+	/* On the 4m, reset the dma too */
+	if (lp->dregs) {
+		u32 csr, addr;
+
+		printk(KERN_ERR "resetting ledma\n");
+		csr = sbus_readl(lp->dregs + DMA_CSR);
+		sbus_writel(csr | DMA_RST_ENET, lp->dregs + DMA_CSR);
+		udelay(200);
+		sbus_writel(csr & ~DMA_RST_ENET, lp->dregs + DMA_CSR);
+
+		addr = lp->init_block_dvma & 0xff000000;
+		sbus_writel(addr, lp->dregs + DMA_TEST);
+	}
+	lp->init_ring(dev);
+	load_csrs(lp);
+	dev->trans_start = jiffies; /* prevent tx timeout */
+	status = init_restart_lance(lp);
+	return status;
+}
+
+static void lance_piocopy_from_skb(void __iomem *dest, unsigned char *src, int len)
+{
+	void __iomem *piobuf = dest;
+	u32 *p32;
+	u16 *p16;
+	u8 *p8;
+
+	switch ((unsigned long)src & 0x3) {
+	case 0:
+		p32 = (u32 *) src;
+		while (len >= 4) {
+			sbus_writel(*p32, piobuf);
+			p32++;
+			piobuf += 4;
+			len -= 4;
+		}
+		src = (char *) p32;
+		break;
+	case 1:
+	case 3:
+		p8 = (u8 *) src;
+		while (len >= 4) {
+			u32 val;
+
+			val  = p8[0] << 24;
+			val |= p8[1] << 16;
+			val |= p8[2] << 8;
+			val |= p8[3];
+			sbus_writel(val, piobuf);
+			p8 += 4;
+			piobuf += 4;
+			len -= 4;
+		}
+		src = (char *) p8;
+		break;
+	case 2:
+		p16 = (u16 *) src;
+		while (len >= 4) {
+			u32 val = p16[0]<<16 | p16[1];
+			sbus_writel(val, piobuf);
+			p16 += 2;
+			piobuf += 4;
+			len -= 4;
+		}
+		src = (char *) p16;
+		break;
+	}
+	if (len >= 2) {
+		u16 val = src[0] << 8 | src[1];
+		sbus_writew(val, piobuf);
+		src += 2;
+		piobuf += 2;
+		len -= 2;
+	}
+	if (len >= 1)
+		sbus_writeb(src[0], piobuf);
+}
+
+static void lance_piozero(void __iomem *dest, int len)
+{
+	void __iomem *piobuf = dest;
+
+	if ((unsigned long)piobuf & 1) {
+		sbus_writeb(0, piobuf);
+		piobuf += 1;
+		len -= 1;
+		if (len == 0)
+			return;
+	}
+	if (len == 1) {
+		sbus_writeb(0, piobuf);
+		return;
+	}
+	if ((unsigned long)piobuf & 2) {
+		sbus_writew(0, piobuf);
+		piobuf += 2;
+		len -= 2;
+		if (len == 0)
+			return;
+	}
+	while (len >= 4) {
+		sbus_writel(0, piobuf);
+		piobuf += 4;
+		len -= 4;
+	}
+	if (len >= 2) {
+		sbus_writew(0, piobuf);
+		piobuf += 2;
+		len -= 2;
+	}
+	if (len >= 1)
+		sbus_writeb(0, piobuf);
+}
+
+static void lance_tx_timeout(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+
+	printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n",
+	       dev->name, sbus_readw(lp->lregs + RDP));
+	lance_reset(dev);
+	netif_wake_queue(dev);
+}
+
+static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	int entry, skblen, len;
+
+	skblen = skb->len;
+
+	len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
+
+	spin_lock_irq(&lp->lock);
+
+	dev->stats.tx_bytes += len;
+
+	entry = lp->tx_new & TX_RING_MOD_MASK;
+	if (lp->pio_buffer) {
+		struct lance_init_block __iomem *ib = lp->init_block_iomem;
+		sbus_writew((-len) | 0xf000, &ib->btx_ring[entry].length);
+		sbus_writew(0, &ib->btx_ring[entry].misc);
+		lance_piocopy_from_skb(&ib->tx_buf[entry][0], skb->data, skblen);
+		if (len != skblen)
+			lance_piozero(&ib->tx_buf[entry][skblen], len - skblen);
+		sbus_writeb(LE_T1_POK | LE_T1_OWN, &ib->btx_ring[entry].tmd1_bits);
+	} else {
+		struct lance_init_block *ib = lp->init_block_mem;
+		ib->btx_ring [entry].length = (-len) | 0xf000;
+		ib->btx_ring [entry].misc = 0;
+		skb_copy_from_linear_data(skb, &ib->tx_buf [entry][0], skblen);
+		if (len != skblen)
+			memset((char *) &ib->tx_buf [entry][skblen], 0, len - skblen);
+		ib->btx_ring [entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN);
+	}
+
+	lp->tx_new = TX_NEXT(entry);
+
+	if (TX_BUFFS_AVAIL <= 0)
+		netif_stop_queue(dev);
+
+	/* Kick the lance: transmit now */
+	sbus_writew(LE_C0_INEA | LE_C0_TDMD, lp->lregs + RDP);
+
+	/* Read back CSR to invalidate the E-Cache.
+	 * This is needed, because DMA_DSBL_WR_INV is set.
+	 */
+	if (lp->dregs)
+		sbus_readw(lp->lregs + RDP);
+
+	spin_unlock_irq(&lp->lock);
+
+	dev_kfree_skb(skb);
+
+	return NETDEV_TX_OK;
+}
+
+/* taken from the depca driver */
+static void lance_load_multicast(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	struct netdev_hw_addr *ha;
+	u32 crc;
+	u32 val;
+
+	/* set all multicast bits */
+	if (dev->flags & IFF_ALLMULTI)
+		val = ~0;
+	else
+		val = 0;
+
+	if (lp->pio_buffer) {
+		struct lance_init_block __iomem *ib = lp->init_block_iomem;
+		sbus_writel(val, &ib->filter[0]);
+		sbus_writel(val, &ib->filter[1]);
+	} else {
+		struct lance_init_block *ib = lp->init_block_mem;
+		ib->filter [0] = val;
+		ib->filter [1] = val;
+	}
+
+	if (dev->flags & IFF_ALLMULTI)
+		return;
+
+	/* Add addresses */
+	netdev_for_each_mc_addr(ha, dev) {
+		crc = ether_crc_le(6, ha->addr);
+		crc = crc >> 26;
+		if (lp->pio_buffer) {
+			struct lance_init_block __iomem *ib = lp->init_block_iomem;
+			u16 __iomem *mcast_table = (u16 __iomem *) &ib->filter;
+			u16 tmp = sbus_readw(&mcast_table[crc>>4]);
+			tmp |= 1 << (crc & 0xf);
+			sbus_writew(tmp, &mcast_table[crc>>4]);
+		} else {
+			struct lance_init_block *ib = lp->init_block_mem;
+			u16 *mcast_table = (u16 *) &ib->filter;
+			mcast_table [crc >> 4] |= 1 << (crc & 0xf);
+		}
+	}
+}
+
+static void lance_set_multicast(struct net_device *dev)
+{
+	struct lance_private *lp = netdev_priv(dev);
+	struct lance_init_block *ib_mem = lp->init_block_mem;
+	struct lance_init_block __iomem *ib_iomem = lp->init_block_iomem;
+	u16 mode;
+
+	if (!netif_running(dev))
+		return;
+
+	if (lp->tx_old != lp->tx_new) {
+		mod_timer(&lp->multicast_timer, jiffies + 4);
+		netif_wake_queue(dev);
+		return;
+	}
+
+	netif_stop_queue(dev);
+
+	STOP_LANCE(lp);
+	lp->init_ring(dev);
+
+	if (lp->pio_buffer)
+		mode = sbus_readw(&ib_iomem->mode);
+	else
+		mode = ib_mem->mode;
+	if (dev->flags & IFF_PROMISC) {
+		mode |= LE_MO_PROM;
+		if (lp->pio_buffer)
+			sbus_writew(mode, &ib_iomem->mode);
+		else
+			ib_mem->mode = mode;
+	} else {
+		mode &= ~LE_MO_PROM;
+		if (lp->pio_buffer)
+			sbus_writew(mode, &ib_iomem->mode);
+		else
+			ib_mem->mode = mode;
+		lance_load_multicast(dev);
+	}
+	load_csrs(lp);
+	init_restart_lance(lp);
+	netif_wake_queue(dev);
+}
+
+static void lance_set_multicast_retry(unsigned long _opaque)
+{
+	struct net_device *dev = (struct net_device *) _opaque;
+
+	lance_set_multicast(dev);
+}
+
+static void lance_free_hwresources(struct lance_private *lp)
+{
+	if (lp->lregs)
+		of_iounmap(&lp->op->resource[0], lp->lregs, LANCE_REG_SIZE);
+	if (lp->dregs) {
+		struct platform_device *ledma = lp->ledma;
+
+		of_iounmap(&ledma->resource[0], lp->dregs,
+			   resource_size(&ledma->resource[0]));
+	}
+	if (lp->init_block_iomem) {
+		of_iounmap(&lp->lebuffer->resource[0], lp->init_block_iomem,
+			   sizeof(struct lance_init_block));
+	} else if (lp->init_block_mem) {
+		dma_free_coherent(&lp->op->dev,
+				  sizeof(struct lance_init_block),
+				  lp->init_block_mem,
+				  lp->init_block_dvma);
+	}
+}
+
+/* Ethtool support... */
+static void sparc_lance_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, "sunlance");
+	strcpy(info->version, "2.02");
+}
+
+static const struct ethtool_ops sparc_lance_ethtool_ops = {
+	.get_drvinfo		= sparc_lance_get_drvinfo,
+	.get_link		= ethtool_op_get_link,
+};
+
+static const struct net_device_ops sparc_lance_ops = {
+	.ndo_open		= lance_open,
+	.ndo_stop		= lance_close,
+	.ndo_start_xmit		= lance_start_xmit,
+	.ndo_set_rx_mode	= lance_set_multicast,
+	.ndo_tx_timeout		= lance_tx_timeout,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+static int __devinit sparc_lance_probe_one(struct platform_device *op,
+					   struct platform_device *ledma,
+					   struct platform_device *lebuffer)
+{
+	struct device_node *dp = op->dev.of_node;
+	static unsigned version_printed;
+	struct lance_private *lp;
+	struct net_device *dev;
+	int    i;
+
+	dev = alloc_etherdev(sizeof(struct lance_private) + 8);
+	if (!dev)
+		return -ENOMEM;
+
+	lp = netdev_priv(dev);
+
+	if (sparc_lance_debug && version_printed++ == 0)
+		printk (KERN_INFO "%s", version);
+
+	spin_lock_init(&lp->lock);
+
+	/* Copy the IDPROM ethernet address to the device structure, later we
+	 * will copy the address in the device structure to the lance
+	 * initialization block.
+	 */
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = idprom->id_ethaddr[i];
+
+	/* Get the IO region */
+	lp->lregs = of_ioremap(&op->resource[0], 0,
+			       LANCE_REG_SIZE, lancestr);
+	if (!lp->lregs) {
+		printk(KERN_ERR "SunLance: Cannot map registers.\n");
+		goto fail;
+	}
+
+	lp->ledma = ledma;
+	if (lp->ledma) {
+		lp->dregs = of_ioremap(&ledma->resource[0], 0,
+				       resource_size(&ledma->resource[0]),
+				       "ledma");
+		if (!lp->dregs) {
+			printk(KERN_ERR "SunLance: Cannot map "
+			       "ledma registers.\n");
+			goto fail;
+		}
+	}
+
+	lp->op = op;
+	lp->lebuffer = lebuffer;
+	if (lebuffer) {
+		/* sanity check */
+		if (lebuffer->resource[0].start & 7) {
+			printk(KERN_ERR "SunLance: ERROR: Rx and Tx rings not on even boundary.\n");
+			goto fail;
+		}
+		lp->init_block_iomem =
+			of_ioremap(&lebuffer->resource[0], 0,
+				   sizeof(struct lance_init_block), "lebuffer");
+		if (!lp->init_block_iomem) {
+			printk(KERN_ERR "SunLance: Cannot map PIO buffer.\n");
+			goto fail;
+		}
+		lp->init_block_dvma = 0;
+		lp->pio_buffer = 1;
+		lp->init_ring = lance_init_ring_pio;
+		lp->rx = lance_rx_pio;
+		lp->tx = lance_tx_pio;
+	} else {
+		lp->init_block_mem =
+			dma_alloc_coherent(&op->dev,
+					   sizeof(struct lance_init_block),
+					   &lp->init_block_dvma, GFP_ATOMIC);
+		if (!lp->init_block_mem) {
+			printk(KERN_ERR "SunLance: Cannot allocate consistent DMA memory.\n");
+			goto fail;
+		}
+		lp->pio_buffer = 0;
+		lp->init_ring = lance_init_ring_dvma;
+		lp->rx = lance_rx_dvma;
+		lp->tx = lance_tx_dvma;
+	}
+	lp->busmaster_regval = of_getintprop_default(dp,  "busmaster-regval",
+						     (LE_C3_BSWP |
+						      LE_C3_ACON |
+						      LE_C3_BCON));
+
+	lp->name = lancestr;
+
+	lp->burst_sizes = 0;
+	if (lp->ledma) {
+		struct device_node *ledma_dp = ledma->dev.of_node;
+		struct device_node *sbus_dp;
+		unsigned int sbmask;
+		const char *prop;
+		u32 csr;
+
+		/* Find burst-size property for ledma */
+		lp->burst_sizes = of_getintprop_default(ledma_dp,
+							"burst-sizes", 0);
+
+		/* ledma may be capable of fast bursts, but sbus may not. */
+		sbus_dp = ledma_dp->parent;
+		sbmask = of_getintprop_default(sbus_dp, "burst-sizes",
+					       DMA_BURSTBITS);
+		lp->burst_sizes &= sbmask;
+
+		/* Get the cable-selection property */
+		prop = of_get_property(ledma_dp, "cable-selection", NULL);
+		if (!prop || prop[0] == '\0') {
+			struct device_node *nd;
+
+			printk(KERN_INFO "SunLance: using "
+			       "auto-carrier-detection.\n");
+
+			nd = of_find_node_by_path("/options");
+			if (!nd)
+				goto no_link_test;
+
+			prop = of_get_property(nd, "tpe-link-test?", NULL);
+			if (!prop)
+				goto no_link_test;
+
+			if (strcmp(prop, "true")) {
+				printk(KERN_NOTICE "SunLance: warning: overriding option "
+				       "'tpe-link-test?'\n");
+				printk(KERN_NOTICE "SunLance: warning: mail any problems "
+				       "to ecd@skynet.be\n");
+				auxio_set_lte(AUXIO_LTE_ON);
+			}
+no_link_test:
+			lp->auto_select = 1;
+			lp->tpe = 0;
+		} else if (!strcmp(prop, "aui")) {
+			lp->auto_select = 0;
+			lp->tpe = 0;
+		} else {
+			lp->auto_select = 0;
+			lp->tpe = 1;
+		}
+
+		/* Reset ledma */
+		csr = sbus_readl(lp->dregs + DMA_CSR);
+		sbus_writel(csr | DMA_RST_ENET, lp->dregs + DMA_CSR);
+		udelay(200);
+		sbus_writel(csr & ~DMA_RST_ENET, lp->dregs + DMA_CSR);
+	} else
+		lp->dregs = NULL;
+
+	lp->dev = dev;
+	SET_NETDEV_DEV(dev, &op->dev);
+	dev->watchdog_timeo = 5*HZ;
+	dev->ethtool_ops = &sparc_lance_ethtool_ops;
+	dev->netdev_ops = &sparc_lance_ops;
+
+	dev->irq = op->archdata.irqs[0];
+
+	/* We cannot sleep if the chip is busy during a
+	 * multicast list update event, because such events
+	 * can occur from interrupts (ex. IPv6).  So we
+	 * use a timer to try again later when necessary. -DaveM
+	 */
+	init_timer(&lp->multicast_timer);
+	lp->multicast_timer.data = (unsigned long) dev;
+	lp->multicast_timer.function = lance_set_multicast_retry;
+
+	if (register_netdev(dev)) {
+		printk(KERN_ERR "SunLance: Cannot register device.\n");
+		goto fail;
+	}
+
+	dev_set_drvdata(&op->dev, lp);
+
+	printk(KERN_INFO "%s: LANCE %pM\n",
+	       dev->name, dev->dev_addr);
+
+	return 0;
+
+fail:
+	lance_free_hwresources(lp);
+	free_netdev(dev);
+	return -ENODEV;
+}
+
+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;
+	int err;
+
+	if (!strcmp(parent_dp->name, "ledma")) {
+		err = sparc_lance_probe_one(op, parent, NULL);
+	} else if (!strcmp(parent_dp->name, "lebuffer")) {
+		err = sparc_lance_probe_one(op, NULL, parent);
+	} else
+		err = sparc_lance_probe_one(op, NULL, NULL);
+
+	return err;
+}
+
+static int __devexit sunlance_sbus_remove(struct platform_device *op)
+{
+	struct lance_private *lp = dev_get_drvdata(&op->dev);
+	struct net_device *net_dev = lp->dev;
+
+	unregister_netdev(net_dev);
+
+	lance_free_hwresources(lp);
+
+	free_netdev(net_dev);
+
+	dev_set_drvdata(&op->dev, NULL);
+
+	return 0;
+}
+
+static const struct of_device_id sunlance_sbus_match[] = {
+	{
+		.name = "le",
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, sunlance_sbus_match);
+
+static struct platform_driver sunlance_sbus_driver = {
+	.driver = {
+		.name = "sunlance",
+		.owner = THIS_MODULE,
+		.of_match_table = sunlance_sbus_match,
+	},
+	.probe		= sunlance_sbus_probe,
+	.remove		= __devexit_p(sunlance_sbus_remove),
+};
+
+
+/* Find all the lance cards on the system and initialize them */
+static int __init sparc_lance_init(void)
+{
+	return platform_driver_register(&sunlance_sbus_driver);
+}
+
+static void __exit sparc_lance_exit(void)
+{
+	platform_driver_unregister(&sunlance_sbus_driver);
+}
+
+module_init(sparc_lance_init);
+module_exit(sparc_lance_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/apple/bmac.c linux-libre-3.2-gnu/drivers/net/ethernet/apple/bmac.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/apple/bmac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/apple/bmac.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1685 @@
+/*
+ * Network device driver for the BMAC ethernet controller on
+ * Apple Powermacs.  Assumes it's under a DBDMA controller.
+ *
+ * Copyright (C) 1998 Randy Gobbel.
+ *
+ * May 1999, Al Viro: proper release of /proc/net/bmac entry, switched to
+ * dynamic procfs inode.
+ */
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/crc32.h>
+#include <linux/bitrev.h>
+#include <linux/ethtool.h>
+#include <linux/slab.h>
+#include <asm/prom.h>
+#include <asm/dbdma.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/macio.h>
+#include <asm/irq.h>
+
+#include "bmac.h"
+
+#define trunc_page(x)	((void *)(((unsigned long)(x)) & ~((unsigned long)(PAGE_SIZE - 1))))
+#define round_page(x)	trunc_page(((unsigned long)(x)) + ((unsigned long)(PAGE_SIZE - 1)))
+
+/*
+ * CRC polynomial - used in working out multicast filter bits.
+ */
+#define ENET_CRCPOLY 0x04c11db7
+
+/* switch to use multicast code lifted from sunhme driver */
+#define SUNHME_MULTICAST
+
+#define N_RX_RING	64
+#define N_TX_RING	32
+#define MAX_TX_ACTIVE	1
+#define ETHERCRC	4
+#define ETHERMINPACKET	64
+#define ETHERMTU	1500
+#define RX_BUFLEN	(ETHERMTU + 14 + ETHERCRC + 2)
+#define TX_TIMEOUT	HZ	/* 1 second */
+
+/* Bits in transmit DMA status */
+#define TX_DMA_ERR	0x80
+
+#define XXDEBUG(args)
+
+struct bmac_data {
+	/* volatile struct bmac *bmac; */
+	struct sk_buff_head *queue;
+	volatile struct dbdma_regs __iomem *tx_dma;
+	int tx_dma_intr;
+	volatile struct dbdma_regs __iomem *rx_dma;
+	int rx_dma_intr;
+	volatile struct dbdma_cmd *tx_cmds;	/* xmit dma command list */
+	volatile struct dbdma_cmd *rx_cmds;	/* recv dma command list */
+	struct macio_dev *mdev;
+	int is_bmac_plus;
+	struct sk_buff *rx_bufs[N_RX_RING];
+	int rx_fill;
+	int rx_empty;
+	struct sk_buff *tx_bufs[N_TX_RING];
+	int tx_fill;
+	int tx_empty;
+	unsigned char tx_fullup;
+	struct timer_list tx_timeout;
+	int timeout_active;
+	int sleeping;
+	int opened;
+	unsigned short hash_use_count[64];
+	unsigned short hash_table_mask[4];
+	spinlock_t lock;
+};
+
+#if 0 /* Move that to ethtool */
+
+typedef struct bmac_reg_entry {
+	char *name;
+	unsigned short reg_offset;
+} bmac_reg_entry_t;
+
+#define N_REG_ENTRIES 31
+
+static bmac_reg_entry_t reg_entries[N_REG_ENTRIES] = {
+	{"MEMADD", MEMADD},
+	{"MEMDATAHI", MEMDATAHI},
+	{"MEMDATALO", MEMDATALO},
+	{"TXPNTR", TXPNTR},
+	{"RXPNTR", RXPNTR},
+	{"IPG1", IPG1},
+	{"IPG2", IPG2},
+	{"ALIMIT", ALIMIT},
+	{"SLOT", SLOT},
+	{"PALEN", PALEN},
+	{"PAPAT", PAPAT},
+	{"TXSFD", TXSFD},
+	{"JAM", JAM},
+	{"TXCFG", TXCFG},
+	{"TXMAX", TXMAX},
+	{"TXMIN", TXMIN},
+	{"PAREG", PAREG},
+	{"DCNT", DCNT},
+	{"NCCNT", NCCNT},
+	{"NTCNT", NTCNT},
+	{"EXCNT", EXCNT},
+	{"LTCNT", LTCNT},
+	{"TXSM", TXSM},
+	{"RXCFG", RXCFG},
+	{"RXMAX", RXMAX},
+	{"RXMIN", RXMIN},
+	{"FRCNT", FRCNT},
+	{"AECNT", AECNT},
+	{"FECNT", FECNT},
+	{"RXSM", RXSM},
+	{"RXCV", RXCV}
+};
+
+#endif
+
+static unsigned char *bmac_emergency_rxbuf;
+
+/*
+ * Number of bytes of private data per BMAC: allow enough for
+ * the rx and tx dma commands plus a branch dma command each,
+ * and another 16 bytes to allow us to align the dma command
+ * buffers on a 16 byte boundary.
+ */
+#define PRIV_BYTES	(sizeof(struct bmac_data) \
+	+ (N_RX_RING + N_TX_RING + 4) * sizeof(struct dbdma_cmd) \
+	+ sizeof(struct sk_buff_head))
+
+static int bmac_open(struct net_device *dev);
+static int bmac_close(struct net_device *dev);
+static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev);
+static void bmac_set_multicast(struct net_device *dev);
+static void bmac_reset_and_enable(struct net_device *dev);
+static void bmac_start_chip(struct net_device *dev);
+static void bmac_init_chip(struct net_device *dev);
+static void bmac_init_registers(struct net_device *dev);
+static void bmac_enable_and_reset_chip(struct net_device *dev);
+static int bmac_set_address(struct net_device *dev, void *addr);
+static irqreturn_t bmac_misc_intr(int irq, void *dev_id);
+static irqreturn_t bmac_txdma_intr(int irq, void *dev_id);
+static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id);
+static void bmac_set_timeout(struct net_device *dev);
+static void bmac_tx_timeout(unsigned long data);
+static int bmac_output(struct sk_buff *skb, struct net_device *dev);
+static void bmac_start(struct net_device *dev);
+
+#define	DBDMA_SET(x)	( ((x) | (x) << 16) )
+#define	DBDMA_CLEAR(x)	( (x) << 16)
+
+static inline void
+dbdma_st32(volatile __u32 __iomem *a, unsigned long x)
+{
+	__asm__ volatile( "stwbrx %0,0,%1" : : "r" (x), "r" (a) : "memory");
+}
+
+static inline unsigned long
+dbdma_ld32(volatile __u32 __iomem *a)
+{
+	__u32 swap;
+	__asm__ volatile ("lwbrx %0,0,%1" :  "=r" (swap) : "r" (a));
+	return swap;
+}
+
+static void
+dbdma_continue(volatile struct dbdma_regs __iomem *dmap)
+{
+	dbdma_st32(&dmap->control,
+		   DBDMA_SET(RUN|WAKE) | DBDMA_CLEAR(PAUSE|DEAD));
+	eieio();
+}
+
+static void
+dbdma_reset(volatile struct dbdma_regs __iomem *dmap)
+{
+	dbdma_st32(&dmap->control,
+		   DBDMA_CLEAR(ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN));
+	eieio();
+	while (dbdma_ld32(&dmap->status) & RUN)
+		eieio();
+}
+
+static void
+dbdma_setcmd(volatile struct dbdma_cmd *cp,
+	     unsigned short cmd, unsigned count, unsigned long addr,
+	     unsigned long cmd_dep)
+{
+	out_le16(&cp->command, cmd);
+	out_le16(&cp->req_count, count);
+	out_le32(&cp->phy_addr, addr);
+	out_le32(&cp->cmd_dep, cmd_dep);
+	out_le16(&cp->xfer_status, 0);
+	out_le16(&cp->res_count, 0);
+}
+
+static inline
+void bmwrite(struct net_device *dev, unsigned long reg_offset, unsigned data )
+{
+	out_le16((void __iomem *)dev->base_addr + reg_offset, data);
+}
+
+
+static inline
+unsigned short bmread(struct net_device *dev, unsigned long reg_offset )
+{
+	return in_le16((void __iomem *)dev->base_addr + reg_offset);
+}
+
+static void
+bmac_enable_and_reset_chip(struct net_device *dev)
+{
+	struct bmac_data *bp = netdev_priv(dev);
+	volatile struct dbdma_regs __iomem *rd = bp->rx_dma;
+	volatile struct dbdma_regs __iomem *td = bp->tx_dma;
+
+	if (rd)
+		dbdma_reset(rd);
+	if (td)
+		dbdma_reset(td);
+
+	pmac_call_feature(PMAC_FTR_BMAC_ENABLE, macio_get_of_node(bp->mdev), 0, 1);
+}
+
+#define MIFDELAY	udelay(10)
+
+static unsigned int
+bmac_mif_readbits(struct net_device *dev, int nb)
+{
+	unsigned int val = 0;
+
+	while (--nb >= 0) {
+		bmwrite(dev, MIFCSR, 0);
+		MIFDELAY;
+		if (bmread(dev, MIFCSR) & 8)
+			val |= 1 << nb;
+		bmwrite(dev, MIFCSR, 1);
+		MIFDELAY;
+	}
+	bmwrite(dev, MIFCSR, 0);
+	MIFDELAY;
+	bmwrite(dev, MIFCSR, 1);
+	MIFDELAY;
+	return val;
+}
+
+static void
+bmac_mif_writebits(struct net_device *dev, unsigned int val, int nb)
+{
+	int b;
+
+	while (--nb >= 0) {
+		b = (val & (1 << nb))? 6: 4;
+		bmwrite(dev, MIFCSR, b);
+		MIFDELAY;
+		bmwrite(dev, MIFCSR, b|1);
+		MIFDELAY;
+	}
+}
+
+static unsigned int
+bmac_mif_read(struct net_device *dev, unsigned int addr)
+{
+	unsigned int val;
+
+	bmwrite(dev, MIFCSR, 4);
+	MIFDELAY;
+	bmac_mif_writebits(dev, ~0U, 32);
+	bmac_mif_writebits(dev, 6, 4);
+	bmac_mif_writebits(dev, addr, 10);
+	bmwrite(dev, MIFCSR, 2);
+	MIFDELAY;
+	bmwrite(dev, MIFCSR, 1);
+	MIFDELAY;
+	val = bmac_mif_readbits(dev, 17);
+	bmwrite(dev, MIFCSR, 4);
+	MIFDELAY;
+	return val;
+}
+
+static void
+bmac_mif_write(struct net_device *dev, unsigned int addr, unsigned int val)
+{
+	bmwrite(dev, MIFCSR, 4);
+	MIFDELAY;
+	bmac_mif_writebits(dev, ~0U, 32);
+	bmac_mif_writebits(dev, 5, 4);
+	bmac_mif_writebits(dev, addr, 10);
+	bmac_mif_writebits(dev, 2, 2);
+	bmac_mif_writebits(dev, val, 16);
+	bmac_mif_writebits(dev, 3, 2);
+}
+
+static void
+bmac_init_registers(struct net_device *dev)
+{
+	struct bmac_data *bp = netdev_priv(dev);
+	volatile unsigned short regValue;
+	unsigned short *pWord16;
+	int i;
+
+	/* XXDEBUG(("bmac: enter init_registers\n")); */
+
+	bmwrite(dev, RXRST, RxResetValue);
+	bmwrite(dev, TXRST, TxResetBit);
+
+	i = 100;
+	do {
+		--i;
+		udelay(10000);
+		regValue = bmread(dev, TXRST); /* wait for reset to clear..acknowledge */
+	} while ((regValue & TxResetBit) && i > 0);
+
+	if (!bp->is_bmac_plus) {
+		regValue = bmread(dev, XCVRIF);
+		regValue |= ClkBit | SerialMode | COLActiveLow;
+		bmwrite(dev, XCVRIF, regValue);
+		udelay(10000);
+	}
+
+	bmwrite(dev, RSEED, (unsigned short)0x1968);
+
+	regValue = bmread(dev, XIFC);
+	regValue |= TxOutputEnable;
+	bmwrite(dev, XIFC, regValue);
+
+	bmread(dev, PAREG);
+
+	/* set collision counters to 0 */
+	bmwrite(dev, NCCNT, 0);
+	bmwrite(dev, NTCNT, 0);
+	bmwrite(dev, EXCNT, 0);
+	bmwrite(dev, LTCNT, 0);
+
+	/* set rx counters to 0 */
+	bmwrite(dev, FRCNT, 0);
+	bmwrite(dev, LECNT, 0);
+	bmwrite(dev, AECNT, 0);
+	bmwrite(dev, FECNT, 0);
+	bmwrite(dev, RXCV, 0);
+
+	/* set tx fifo information */
+	bmwrite(dev, TXTH, 4);	/* 4 octets before tx starts */
+
+	bmwrite(dev, TXFIFOCSR, 0);	/* first disable txFIFO */
+	bmwrite(dev, TXFIFOCSR, TxFIFOEnable );
+
+	/* set rx fifo information */
+	bmwrite(dev, RXFIFOCSR, 0);	/* first disable rxFIFO */
+	bmwrite(dev, RXFIFOCSR, RxFIFOEnable );
+
+	//bmwrite(dev, TXCFG, TxMACEnable);	       	/* TxNeverGiveUp maybe later */
+	bmread(dev, STATUS);		/* read it just to clear it */
+
+	/* zero out the chip Hash Filter registers */
+	for (i=0; i<4; i++) bp->hash_table_mask[i] = 0;
+	bmwrite(dev, BHASH3, bp->hash_table_mask[0]); 	/* bits 15 - 0 */
+	bmwrite(dev, BHASH2, bp->hash_table_mask[1]); 	/* bits 31 - 16 */
+	bmwrite(dev, BHASH1, bp->hash_table_mask[2]); 	/* bits 47 - 32 */
+	bmwrite(dev, BHASH0, bp->hash_table_mask[3]); 	/* bits 63 - 48 */
+
+	pWord16 = (unsigned short *)dev->dev_addr;
+	bmwrite(dev, MADD0, *pWord16++);
+	bmwrite(dev, MADD1, *pWord16++);
+	bmwrite(dev, MADD2, *pWord16);
+
+	bmwrite(dev, RXCFG, RxCRCNoStrip | RxHashFilterEnable | RxRejectOwnPackets);
+
+	bmwrite(dev, INTDISABLE, EnableNormal);
+}
+
+#if 0
+static void
+bmac_disable_interrupts(struct net_device *dev)
+{
+	bmwrite(dev, INTDISABLE, DisableAll);
+}
+
+static void
+bmac_enable_interrupts(struct net_device *dev)
+{
+	bmwrite(dev, INTDISABLE, EnableNormal);
+}
+#endif
+
+
+static void
+bmac_start_chip(struct net_device *dev)
+{
+	struct bmac_data *bp = netdev_priv(dev);
+	volatile struct dbdma_regs __iomem *rd = bp->rx_dma;
+	unsigned short	oldConfig;
+
+	/* enable rx dma channel */
+	dbdma_continue(rd);
+
+	oldConfig = bmread(dev, TXCFG);
+	bmwrite(dev, TXCFG, oldConfig | TxMACEnable );
+
+	/* turn on rx plus any other bits already on (promiscuous possibly) */
+	oldConfig = bmread(dev, RXCFG);
+	bmwrite(dev, RXCFG, oldConfig | RxMACEnable );
+	udelay(20000);
+}
+
+static void
+bmac_init_phy(struct net_device *dev)
+{
+	unsigned int addr;
+	struct bmac_data *bp = netdev_priv(dev);
+
+	printk(KERN_DEBUG "phy registers:");
+	for (addr = 0; addr < 32; ++addr) {
+		if ((addr & 7) == 0)
+			printk(KERN_DEBUG);
+		printk(KERN_CONT " %.4x", bmac_mif_read(dev, addr));
+	}
+	printk(KERN_CONT "\n");
+
+	if (bp->is_bmac_plus) {
+		unsigned int capable, ctrl;
+
+		ctrl = bmac_mif_read(dev, 0);
+		capable = ((bmac_mif_read(dev, 1) & 0xf800) >> 6) | 1;
+		if (bmac_mif_read(dev, 4) != capable ||
+		    (ctrl & 0x1000) == 0) {
+			bmac_mif_write(dev, 4, capable);
+			bmac_mif_write(dev, 0, 0x1200);
+		} else
+			bmac_mif_write(dev, 0, 0x1000);
+	}
+}
+
+static void bmac_init_chip(struct net_device *dev)
+{
+	bmac_init_phy(dev);
+	bmac_init_registers(dev);
+}
+
+#ifdef CONFIG_PM
+static int bmac_suspend(struct macio_dev *mdev, pm_message_t state)
+{
+	struct net_device* dev = macio_get_drvdata(mdev);
+	struct bmac_data *bp = netdev_priv(dev);
+	unsigned long flags;
+	unsigned short config;
+	int i;
+
+	netif_device_detach(dev);
+	/* prolly should wait for dma to finish & turn off the chip */
+	spin_lock_irqsave(&bp->lock, flags);
+	if (bp->timeout_active) {
+		del_timer(&bp->tx_timeout);
+		bp->timeout_active = 0;
+	}
+	disable_irq(dev->irq);
+	disable_irq(bp->tx_dma_intr);
+	disable_irq(bp->rx_dma_intr);
+	bp->sleeping = 1;
+	spin_unlock_irqrestore(&bp->lock, flags);
+	if (bp->opened) {
+		volatile struct dbdma_regs __iomem *rd = bp->rx_dma;
+		volatile struct dbdma_regs __iomem *td = bp->tx_dma;
+
+		config = bmread(dev, RXCFG);
+		bmwrite(dev, RXCFG, (config & ~RxMACEnable));
+		config = bmread(dev, TXCFG);
+       		bmwrite(dev, TXCFG, (config & ~TxMACEnable));
+		bmwrite(dev, INTDISABLE, DisableAll); /* disable all intrs */
+       		/* disable rx and tx dma */
+       		st_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE));	/* clear run bit */
+       		st_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE));	/* clear run bit */
+       		/* free some skb's */
+       		for (i=0; i<N_RX_RING; i++) {
+       			if (bp->rx_bufs[i] != NULL) {
+       				dev_kfree_skb(bp->rx_bufs[i]);
+       				bp->rx_bufs[i] = NULL;
+       			}
+       		}
+       		for (i = 0; i<N_TX_RING; i++) {
+			if (bp->tx_bufs[i] != NULL) {
+		       		dev_kfree_skb(bp->tx_bufs[i]);
+	       			bp->tx_bufs[i] = NULL;
+		       	}
+		}
+	}
+       	pmac_call_feature(PMAC_FTR_BMAC_ENABLE, macio_get_of_node(bp->mdev), 0, 0);
+	return 0;
+}
+
+static int bmac_resume(struct macio_dev *mdev)
+{
+	struct net_device* dev = macio_get_drvdata(mdev);
+	struct bmac_data *bp = netdev_priv(dev);
+
+	/* see if this is enough */
+	if (bp->opened)
+		bmac_reset_and_enable(dev);
+
+	enable_irq(dev->irq);
+       	enable_irq(bp->tx_dma_intr);
+       	enable_irq(bp->rx_dma_intr);
+       	netif_device_attach(dev);
+
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+static int bmac_set_address(struct net_device *dev, void *addr)
+{
+	struct bmac_data *bp = netdev_priv(dev);
+	unsigned char *p = addr;
+	unsigned short *pWord16;
+	unsigned long flags;
+	int i;
+
+	XXDEBUG(("bmac: enter set_address\n"));
+	spin_lock_irqsave(&bp->lock, flags);
+
+	for (i = 0; i < 6; ++i) {
+		dev->dev_addr[i] = p[i];
+	}
+	/* load up the hardware address */
+	pWord16  = (unsigned short *)dev->dev_addr;
+	bmwrite(dev, MADD0, *pWord16++);
+	bmwrite(dev, MADD1, *pWord16++);
+	bmwrite(dev, MADD2, *pWord16);
+
+	spin_unlock_irqrestore(&bp->lock, flags);
+	XXDEBUG(("bmac: exit set_address\n"));
+	return 0;
+}
+
+static inline void bmac_set_timeout(struct net_device *dev)
+{
+	struct bmac_data *bp = netdev_priv(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&bp->lock, flags);
+	if (bp->timeout_active)
+		del_timer(&bp->tx_timeout);
+	bp->tx_timeout.expires = jiffies + TX_TIMEOUT;
+	bp->tx_timeout.function = bmac_tx_timeout;
+	bp->tx_timeout.data = (unsigned long) dev;
+	add_timer(&bp->tx_timeout);
+	bp->timeout_active = 1;
+	spin_unlock_irqrestore(&bp->lock, flags);
+}
+
+static void
+bmac_construct_xmt(struct sk_buff *skb, volatile struct dbdma_cmd *cp)
+{
+	void *vaddr;
+	unsigned long baddr;
+	unsigned long len;
+
+	len = skb->len;
+	vaddr = skb->data;
+	baddr = virt_to_bus(vaddr);
+
+	dbdma_setcmd(cp, (OUTPUT_LAST | INTR_ALWAYS | WAIT_IFCLR), len, baddr, 0);
+}
+
+static void
+bmac_construct_rxbuff(struct sk_buff *skb, volatile struct dbdma_cmd *cp)
+{
+	unsigned char *addr = skb? skb->data: bmac_emergency_rxbuf;
+
+	dbdma_setcmd(cp, (INPUT_LAST | INTR_ALWAYS), RX_BUFLEN,
+		     virt_to_bus(addr), 0);
+}
+
+static void
+bmac_init_tx_ring(struct bmac_data *bp)
+{
+	volatile struct dbdma_regs __iomem *td = bp->tx_dma;
+
+	memset((char *)bp->tx_cmds, 0, (N_TX_RING+1) * sizeof(struct dbdma_cmd));
+
+	bp->tx_empty = 0;
+	bp->tx_fill = 0;
+	bp->tx_fullup = 0;
+
+	/* put a branch at the end of the tx command list */
+	dbdma_setcmd(&bp->tx_cmds[N_TX_RING],
+		     (DBDMA_NOP | BR_ALWAYS), 0, 0, virt_to_bus(bp->tx_cmds));
+
+	/* reset tx dma */
+	dbdma_reset(td);
+	out_le32(&td->wait_sel, 0x00200020);
+	out_le32(&td->cmdptr, virt_to_bus(bp->tx_cmds));
+}
+
+static int
+bmac_init_rx_ring(struct bmac_data *bp)
+{
+	volatile struct dbdma_regs __iomem *rd = bp->rx_dma;
+	int i;
+	struct sk_buff *skb;
+
+	/* initialize list of sk_buffs for receiving and set up recv dma */
+	memset((char *)bp->rx_cmds, 0,
+	       (N_RX_RING + 1) * sizeof(struct dbdma_cmd));
+	for (i = 0; i < N_RX_RING; i++) {
+		if ((skb = bp->rx_bufs[i]) == NULL) {
+			bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2);
+			if (skb != NULL)
+				skb_reserve(skb, 2);
+		}
+		bmac_construct_rxbuff(skb, &bp->rx_cmds[i]);
+	}
+
+	bp->rx_empty = 0;
+	bp->rx_fill = i;
+
+	/* Put a branch back to the beginning of the receive command list */
+	dbdma_setcmd(&bp->rx_cmds[N_RX_RING],
+		     (DBDMA_NOP | BR_ALWAYS), 0, 0, virt_to_bus(bp->rx_cmds));
+
+	/* start rx dma */
+	dbdma_reset(rd);
+	out_le32(&rd->cmdptr, virt_to_bus(bp->rx_cmds));
+
+	return 1;
+}
+
+
+static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev)
+{
+	struct bmac_data *bp = netdev_priv(dev);
+	volatile struct dbdma_regs __iomem *td = bp->tx_dma;
+	int i;
+
+	/* see if there's a free slot in the tx ring */
+	/* XXDEBUG(("bmac_xmit_start: empty=%d fill=%d\n", */
+	/* 	     bp->tx_empty, bp->tx_fill)); */
+	i = bp->tx_fill + 1;
+	if (i >= N_TX_RING)
+		i = 0;
+	if (i == bp->tx_empty) {
+		netif_stop_queue(dev);
+		bp->tx_fullup = 1;
+		XXDEBUG(("bmac_transmit_packet: tx ring full\n"));
+		return -1;		/* can't take it at the moment */
+	}
+
+	dbdma_setcmd(&bp->tx_cmds[i], DBDMA_STOP, 0, 0, 0);
+
+	bmac_construct_xmt(skb, &bp->tx_cmds[bp->tx_fill]);
+
+	bp->tx_bufs[bp->tx_fill] = skb;
+	bp->tx_fill = i;
+
+	dev->stats.tx_bytes += skb->len;
+
+	dbdma_continue(td);
+
+	return 0;
+}
+
+static int rxintcount;
+
+static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct bmac_data *bp = netdev_priv(dev);
+	volatile struct dbdma_regs __iomem *rd = bp->rx_dma;
+	volatile struct dbdma_cmd *cp;
+	int i, nb, stat;
+	struct sk_buff *skb;
+	unsigned int residual;
+	int last;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bp->lock, flags);
+
+	if (++rxintcount < 10) {
+		XXDEBUG(("bmac_rxdma_intr\n"));
+	}
+
+	last = -1;
+	i = bp->rx_empty;
+
+	while (1) {
+		cp = &bp->rx_cmds[i];
+		stat = ld_le16(&cp->xfer_status);
+		residual = ld_le16(&cp->res_count);
+		if ((stat & ACTIVE) == 0)
+			break;
+		nb = RX_BUFLEN - residual - 2;
+		if (nb < (ETHERMINPACKET - ETHERCRC)) {
+			skb = NULL;
+			dev->stats.rx_length_errors++;
+			dev->stats.rx_errors++;
+		} else {
+			skb = bp->rx_bufs[i];
+			bp->rx_bufs[i] = NULL;
+		}
+		if (skb != NULL) {
+			nb -= ETHERCRC;
+			skb_put(skb, nb);
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+			++dev->stats.rx_packets;
+			dev->stats.rx_bytes += nb;
+		} else {
+			++dev->stats.rx_dropped;
+		}
+		if ((skb = bp->rx_bufs[i]) == NULL) {
+			bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2);
+			if (skb != NULL)
+				skb_reserve(bp->rx_bufs[i], 2);
+		}
+		bmac_construct_rxbuff(skb, &bp->rx_cmds[i]);
+		st_le16(&cp->res_count, 0);
+		st_le16(&cp->xfer_status, 0);
+		last = i;
+		if (++i >= N_RX_RING) i = 0;
+	}
+
+	if (last != -1) {
+		bp->rx_fill = last;
+		bp->rx_empty = i;
+	}
+
+	dbdma_continue(rd);
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	if (rxintcount < 10) {
+		XXDEBUG(("bmac_rxdma_intr done\n"));
+	}
+	return IRQ_HANDLED;
+}
+
+static int txintcount;
+
+static irqreturn_t bmac_txdma_intr(int irq, void *dev_id)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct bmac_data *bp = netdev_priv(dev);
+	volatile struct dbdma_cmd *cp;
+	int stat;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bp->lock, flags);
+
+	if (txintcount++ < 10) {
+		XXDEBUG(("bmac_txdma_intr\n"));
+	}
+
+	/*     del_timer(&bp->tx_timeout); */
+	/*     bp->timeout_active = 0; */
+
+	while (1) {
+		cp = &bp->tx_cmds[bp->tx_empty];
+		stat = ld_le16(&cp->xfer_status);
+		if (txintcount < 10) {
+			XXDEBUG(("bmac_txdma_xfer_stat=%#0x\n", stat));
+		}
+		if (!(stat & ACTIVE)) {
+			/*
+			 * status field might not have been filled by DBDMA
+			 */
+			if (cp == bus_to_virt(in_le32(&bp->tx_dma->cmdptr)))
+				break;
+		}
+
+		if (bp->tx_bufs[bp->tx_empty]) {
+			++dev->stats.tx_packets;
+			dev_kfree_skb_irq(bp->tx_bufs[bp->tx_empty]);
+		}
+		bp->tx_bufs[bp->tx_empty] = NULL;
+		bp->tx_fullup = 0;
+		netif_wake_queue(dev);
+		if (++bp->tx_empty >= N_TX_RING)
+			bp->tx_empty = 0;
+		if (bp->tx_empty == bp->tx_fill)
+			break;
+	}
+
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	if (txintcount < 10) {
+		XXDEBUG(("bmac_txdma_intr done->bmac_start\n"));
+	}
+
+	bmac_start(dev);
+	return IRQ_HANDLED;
+}
+
+#ifndef SUNHME_MULTICAST
+/* Real fast bit-reversal algorithm, 6-bit values */
+static int reverse6[64] = {
+	0x0,0x20,0x10,0x30,0x8,0x28,0x18,0x38,
+	0x4,0x24,0x14,0x34,0xc,0x2c,0x1c,0x3c,
+	0x2,0x22,0x12,0x32,0xa,0x2a,0x1a,0x3a,
+	0x6,0x26,0x16,0x36,0xe,0x2e,0x1e,0x3e,
+	0x1,0x21,0x11,0x31,0x9,0x29,0x19,0x39,
+	0x5,0x25,0x15,0x35,0xd,0x2d,0x1d,0x3d,
+	0x3,0x23,0x13,0x33,0xb,0x2b,0x1b,0x3b,
+	0x7,0x27,0x17,0x37,0xf,0x2f,0x1f,0x3f
+};
+
+static unsigned int
+crc416(unsigned int curval, unsigned short nxtval)
+{
+	register unsigned int counter, cur = curval, next = nxtval;
+	register int high_crc_set, low_data_set;
+
+	/* Swap bytes */
+	next = ((next & 0x00FF) << 8) | (next >> 8);
+
+	/* Compute bit-by-bit */
+	for (counter = 0; counter < 16; ++counter) {
+		/* is high CRC bit set? */
+		if ((cur & 0x80000000) == 0) high_crc_set = 0;
+		else high_crc_set = 1;
+
+		cur = cur << 1;
+
+		if ((next & 0x0001) == 0) low_data_set = 0;
+		else low_data_set = 1;
+
+		next = next >> 1;
+
+		/* do the XOR */
+		if (high_crc_set ^ low_data_set) cur = cur ^ ENET_CRCPOLY;
+	}
+	return cur;
+}
+
+static unsigned int
+bmac_crc(unsigned short *address)
+{
+	unsigned int newcrc;
+
+	XXDEBUG(("bmac_crc: addr=%#04x, %#04x, %#04x\n", *address, address[1], address[2]));
+	newcrc = crc416(0xffffffff, *address);	/* address bits 47 - 32 */
+	newcrc = crc416(newcrc, address[1]);	/* address bits 31 - 16 */
+	newcrc = crc416(newcrc, address[2]);	/* address bits 15 - 0  */
+
+	return(newcrc);
+}
+
+/*
+ * Add requested mcast addr to BMac's hash table filter.
+ *
+ */
+
+static void
+bmac_addhash(struct bmac_data *bp, unsigned char *addr)
+{
+	unsigned int	 crc;
+	unsigned short	 mask;
+
+	if (!(*addr)) return;
+	crc = bmac_crc((unsigned short *)addr) & 0x3f; /* Big-endian alert! */
+	crc = reverse6[crc];	/* Hyperfast bit-reversing algorithm */
+	if (bp->hash_use_count[crc]++) return; /* This bit is already set */
+	mask = crc % 16;
+	mask = (unsigned char)1 << mask;
+	bp->hash_use_count[crc/16] |= mask;
+}
+
+static void
+bmac_removehash(struct bmac_data *bp, unsigned char *addr)
+{
+	unsigned int crc;
+	unsigned char mask;
+
+	/* Now, delete the address from the filter copy, as indicated */
+	crc = bmac_crc((unsigned short *)addr) & 0x3f; /* Big-endian alert! */
+	crc = reverse6[crc];	/* Hyperfast bit-reversing algorithm */
+	if (bp->hash_use_count[crc] == 0) return; /* That bit wasn't in use! */
+	if (--bp->hash_use_count[crc]) return; /* That bit is still in use */
+	mask = crc % 16;
+	mask = ((unsigned char)1 << mask) ^ 0xffff; /* To turn off bit */
+	bp->hash_table_mask[crc/16] &= mask;
+}
+
+/*
+ * Sync the adapter with the software copy of the multicast mask
+ *  (logical address filter).
+ */
+
+static void
+bmac_rx_off(struct net_device *dev)
+{
+	unsigned short rx_cfg;
+
+	rx_cfg = bmread(dev, RXCFG);
+	rx_cfg &= ~RxMACEnable;
+	bmwrite(dev, RXCFG, rx_cfg);
+	do {
+		rx_cfg = bmread(dev, RXCFG);
+	}  while (rx_cfg & RxMACEnable);
+}
+
+unsigned short
+bmac_rx_on(struct net_device *dev, int hash_enable, int promisc_enable)
+{
+	unsigned short rx_cfg;
+
+	rx_cfg = bmread(dev, RXCFG);
+	rx_cfg |= RxMACEnable;
+	if (hash_enable) rx_cfg |= RxHashFilterEnable;
+	else rx_cfg &= ~RxHashFilterEnable;
+	if (promisc_enable) rx_cfg |= RxPromiscEnable;
+	else rx_cfg &= ~RxPromiscEnable;
+	bmwrite(dev, RXRST, RxResetValue);
+	bmwrite(dev, RXFIFOCSR, 0);	/* first disable rxFIFO */
+	bmwrite(dev, RXFIFOCSR, RxFIFOEnable );
+	bmwrite(dev, RXCFG, rx_cfg );
+	return rx_cfg;
+}
+
+static void
+bmac_update_hash_table_mask(struct net_device *dev, struct bmac_data *bp)
+{
+	bmwrite(dev, BHASH3, bp->hash_table_mask[0]); /* bits 15 - 0 */
+	bmwrite(dev, BHASH2, bp->hash_table_mask[1]); /* bits 31 - 16 */
+	bmwrite(dev, BHASH1, bp->hash_table_mask[2]); /* bits 47 - 32 */
+	bmwrite(dev, BHASH0, bp->hash_table_mask[3]); /* bits 63 - 48 */
+}
+
+#if 0
+static void
+bmac_add_multi(struct net_device *dev,
+	       struct bmac_data *bp, unsigned char *addr)
+{
+	/* XXDEBUG(("bmac: enter bmac_add_multi\n")); */
+	bmac_addhash(bp, addr);
+	bmac_rx_off(dev);
+	bmac_update_hash_table_mask(dev, bp);
+	bmac_rx_on(dev, 1, (dev->flags & IFF_PROMISC)? 1 : 0);
+	/* XXDEBUG(("bmac: exit bmac_add_multi\n")); */
+}
+
+static void
+bmac_remove_multi(struct net_device *dev,
+		  struct bmac_data *bp, unsigned char *addr)
+{
+	bmac_removehash(bp, addr);
+	bmac_rx_off(dev);
+	bmac_update_hash_table_mask(dev, bp);
+	bmac_rx_on(dev, 1, (dev->flags & IFF_PROMISC)? 1 : 0);
+}
+#endif
+
+/* Set or clear the multicast filter for this adaptor.
+    num_addrs == -1	Promiscuous mode, receive all packets
+    num_addrs == 0	Normal mode, clear multicast list
+    num_addrs > 0	Multicast mode, receive normal and MC packets, and do
+			best-effort filtering.
+ */
+static void bmac_set_multicast(struct net_device *dev)
+{
+	struct netdev_hw_addr *ha;
+	struct bmac_data *bp = netdev_priv(dev);
+	int num_addrs = netdev_mc_count(dev);
+	unsigned short rx_cfg;
+	int i;
+
+	if (bp->sleeping)
+		return;
+
+	XXDEBUG(("bmac: enter bmac_set_multicast, n_addrs=%d\n", num_addrs));
+
+	if((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > 64)) {
+		for (i=0; i<4; i++) bp->hash_table_mask[i] = 0xffff;
+		bmac_update_hash_table_mask(dev, bp);
+		rx_cfg = bmac_rx_on(dev, 1, 0);
+		XXDEBUG(("bmac: all multi, rx_cfg=%#08x\n"));
+	} else if ((dev->flags & IFF_PROMISC) || (num_addrs < 0)) {
+		rx_cfg = bmread(dev, RXCFG);
+		rx_cfg |= RxPromiscEnable;
+		bmwrite(dev, RXCFG, rx_cfg);
+		rx_cfg = bmac_rx_on(dev, 0, 1);
+		XXDEBUG(("bmac: promisc mode enabled, rx_cfg=%#08x\n", rx_cfg));
+	} else {
+		for (i=0; i<4; i++) bp->hash_table_mask[i] = 0;
+		for (i=0; i<64; i++) bp->hash_use_count[i] = 0;
+		if (num_addrs == 0) {
+			rx_cfg = bmac_rx_on(dev, 0, 0);
+			XXDEBUG(("bmac: multi disabled, rx_cfg=%#08x\n", rx_cfg));
+		} else {
+			netdev_for_each_mc_addr(ha, dev)
+				bmac_addhash(bp, ha->addr);
+			bmac_update_hash_table_mask(dev, bp);
+			rx_cfg = bmac_rx_on(dev, 1, 0);
+			XXDEBUG(("bmac: multi enabled, rx_cfg=%#08x\n", rx_cfg));
+		}
+	}
+	/* XXDEBUG(("bmac: exit bmac_set_multicast\n")); */
+}
+#else /* ifdef SUNHME_MULTICAST */
+
+/* The version of set_multicast below was lifted from sunhme.c */
+
+static void bmac_set_multicast(struct net_device *dev)
+{
+	struct netdev_hw_addr *ha;
+	int i;
+	unsigned short rx_cfg;
+	u32 crc;
+
+	if((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > 64)) {
+		bmwrite(dev, BHASH0, 0xffff);
+		bmwrite(dev, BHASH1, 0xffff);
+		bmwrite(dev, BHASH2, 0xffff);
+		bmwrite(dev, BHASH3, 0xffff);
+	} else if(dev->flags & IFF_PROMISC) {
+		rx_cfg = bmread(dev, RXCFG);
+		rx_cfg |= RxPromiscEnable;
+		bmwrite(dev, RXCFG, rx_cfg);
+	} else {
+		u16 hash_table[4];
+
+		rx_cfg = bmread(dev, RXCFG);
+		rx_cfg &= ~RxPromiscEnable;
+		bmwrite(dev, RXCFG, rx_cfg);
+
+		for(i = 0; i < 4; i++) hash_table[i] = 0;
+
+		netdev_for_each_mc_addr(ha, dev) {
+			crc = ether_crc_le(6, ha->addr);
+			crc >>= 26;
+			hash_table[crc >> 4] |= 1 << (crc & 0xf);
+		}
+		bmwrite(dev, BHASH0, hash_table[0]);
+		bmwrite(dev, BHASH1, hash_table[1]);
+		bmwrite(dev, BHASH2, hash_table[2]);
+		bmwrite(dev, BHASH3, hash_table[3]);
+	}
+}
+#endif /* SUNHME_MULTICAST */
+
+static int miscintcount;
+
+static irqreturn_t bmac_misc_intr(int irq, void *dev_id)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	unsigned int status = bmread(dev, STATUS);
+	if (miscintcount++ < 10) {
+		XXDEBUG(("bmac_misc_intr\n"));
+	}
+	/* XXDEBUG(("bmac_misc_intr, status=%#08x\n", status)); */
+	/*     bmac_txdma_intr_inner(irq, dev_id); */
+	/*   if (status & FrameReceived) dev->stats.rx_dropped++; */
+	if (status & RxErrorMask) dev->stats.rx_errors++;
+	if (status & RxCRCCntExp) dev->stats.rx_crc_errors++;
+	if (status & RxLenCntExp) dev->stats.rx_length_errors++;
+	if (status & RxOverFlow) dev->stats.rx_over_errors++;
+	if (status & RxAlignCntExp) dev->stats.rx_frame_errors++;
+
+	/*   if (status & FrameSent) dev->stats.tx_dropped++; */
+	if (status & TxErrorMask) dev->stats.tx_errors++;
+	if (status & TxUnderrun) dev->stats.tx_fifo_errors++;
+	if (status & TxNormalCollExp) dev->stats.collisions++;
+	return IRQ_HANDLED;
+}
+
+/*
+ * Procedure for reading EEPROM
+ */
+#define SROMAddressLength	5
+#define DataInOn		0x0008
+#define DataInOff		0x0000
+#define Clk			0x0002
+#define ChipSelect		0x0001
+#define SDIShiftCount		3
+#define SD0ShiftCount		2
+#define	DelayValue		1000	/* number of microseconds */
+#define SROMStartOffset		10	/* this is in words */
+#define SROMReadCount		3	/* number of words to read from SROM */
+#define SROMAddressBits		6
+#define EnetAddressOffset	20
+
+static unsigned char
+bmac_clock_out_bit(struct net_device *dev)
+{
+	unsigned short         data;
+	unsigned short         val;
+
+	bmwrite(dev, SROMCSR, ChipSelect | Clk);
+	udelay(DelayValue);
+
+	data = bmread(dev, SROMCSR);
+	udelay(DelayValue);
+	val = (data >> SD0ShiftCount) & 1;
+
+	bmwrite(dev, SROMCSR, ChipSelect);
+	udelay(DelayValue);
+
+	return val;
+}
+
+static void
+bmac_clock_in_bit(struct net_device *dev, unsigned int val)
+{
+	unsigned short data;
+
+	if (val != 0 && val != 1) return;
+
+	data = (val << SDIShiftCount);
+	bmwrite(dev, SROMCSR, data | ChipSelect  );
+	udelay(DelayValue);
+
+	bmwrite(dev, SROMCSR, data | ChipSelect | Clk );
+	udelay(DelayValue);
+
+	bmwrite(dev, SROMCSR, data | ChipSelect);
+	udelay(DelayValue);
+}
+
+static void
+reset_and_select_srom(struct net_device *dev)
+{
+	/* first reset */
+	bmwrite(dev, SROMCSR, 0);
+	udelay(DelayValue);
+
+	/* send it the read command (110) */
+	bmac_clock_in_bit(dev, 1);
+	bmac_clock_in_bit(dev, 1);
+	bmac_clock_in_bit(dev, 0);
+}
+
+static unsigned short
+read_srom(struct net_device *dev, unsigned int addr, unsigned int addr_len)
+{
+	unsigned short data, val;
+	int i;
+
+	/* send out the address we want to read from */
+	for (i = 0; i < addr_len; i++)	{
+		val = addr >> (addr_len-i-1);
+		bmac_clock_in_bit(dev, val & 1);
+	}
+
+	/* Now read in the 16-bit data */
+	data = 0;
+	for (i = 0; i < 16; i++)	{
+		val = bmac_clock_out_bit(dev);
+		data <<= 1;
+		data |= val;
+	}
+	bmwrite(dev, SROMCSR, 0);
+
+	return data;
+}
+
+/*
+ * It looks like Cogent and SMC use different methods for calculating
+ * checksums. What a pain..
+ */
+
+static int
+bmac_verify_checksum(struct net_device *dev)
+{
+	unsigned short data, storedCS;
+
+	reset_and_select_srom(dev);
+	data = read_srom(dev, 3, SROMAddressBits);
+	storedCS = ((data >> 8) & 0x0ff) | ((data << 8) & 0xff00);
+
+	return 0;
+}
+
+
+static void
+bmac_get_station_address(struct net_device *dev, unsigned char *ea)
+{
+	int i;
+	unsigned short data;
+
+	for (i = 0; i < 6; i++)
+		{
+			reset_and_select_srom(dev);
+			data = read_srom(dev, i + EnetAddressOffset/2, SROMAddressBits);
+			ea[2*i]   = bitrev8(data & 0x0ff);
+			ea[2*i+1] = bitrev8((data >> 8) & 0x0ff);
+		}
+}
+
+static void bmac_reset_and_enable(struct net_device *dev)
+{
+	struct bmac_data *bp = netdev_priv(dev);
+	unsigned long flags;
+	struct sk_buff *skb;
+	unsigned char *data;
+
+	spin_lock_irqsave(&bp->lock, flags);
+	bmac_enable_and_reset_chip(dev);
+	bmac_init_tx_ring(bp);
+	bmac_init_rx_ring(bp);
+	bmac_init_chip(dev);
+	bmac_start_chip(dev);
+	bmwrite(dev, INTDISABLE, EnableNormal);
+	bp->sleeping = 0;
+
+	/*
+	 * It seems that the bmac can't receive until it's transmitted
+	 * a packet.  So we give it a dummy packet to transmit.
+	 */
+	skb = dev_alloc_skb(ETHERMINPACKET);
+	if (skb != NULL) {
+		data = skb_put(skb, ETHERMINPACKET);
+		memset(data, 0, ETHERMINPACKET);
+		memcpy(data, dev->dev_addr, 6);
+		memcpy(data+6, dev->dev_addr, 6);
+		bmac_transmit_packet(skb, dev);
+	}
+	spin_unlock_irqrestore(&bp->lock, flags);
+}
+
+static const struct ethtool_ops bmac_ethtool_ops = {
+	.get_link		= ethtool_op_get_link,
+};
+
+static const struct net_device_ops bmac_netdev_ops = {
+	.ndo_open		= bmac_open,
+	.ndo_stop		= bmac_close,
+	.ndo_start_xmit		= bmac_output,
+	.ndo_set_rx_mode	= bmac_set_multicast,
+	.ndo_set_mac_address	= bmac_set_address,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_id *match)
+{
+	int j, rev, ret;
+	struct bmac_data *bp;
+	const unsigned char *prop_addr;
+	unsigned char addr[6];
+	struct net_device *dev;
+	int is_bmac_plus = ((int)match->data) != 0;
+
+	if (macio_resource_count(mdev) != 3 || macio_irq_count(mdev) != 3) {
+		printk(KERN_ERR "BMAC: can't use, need 3 addrs and 3 intrs\n");
+		return -ENODEV;
+	}
+	prop_addr = of_get_property(macio_get_of_node(mdev),
+			"mac-address", NULL);
+	if (prop_addr == NULL) {
+		prop_addr = of_get_property(macio_get_of_node(mdev),
+				"local-mac-address", NULL);
+		if (prop_addr == NULL) {
+			printk(KERN_ERR "BMAC: Can't get mac-address\n");
+			return -ENODEV;
+		}
+	}
+	memcpy(addr, prop_addr, sizeof(addr));
+
+	dev = alloc_etherdev(PRIV_BYTES);
+	if (!dev) {
+		printk(KERN_ERR "BMAC: alloc_etherdev failed, out of memory\n");
+		return -ENOMEM;
+	}
+
+	bp = netdev_priv(dev);
+	SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
+	macio_set_drvdata(mdev, dev);
+
+	bp->mdev = mdev;
+	spin_lock_init(&bp->lock);
+
+	if (macio_request_resources(mdev, "bmac")) {
+		printk(KERN_ERR "BMAC: can't request IO resource !\n");
+		goto out_free;
+	}
+
+	dev->base_addr = (unsigned long)
+		ioremap(macio_resource_start(mdev, 0), macio_resource_len(mdev, 0));
+	if (dev->base_addr == 0)
+		goto out_release;
+
+	dev->irq = macio_irq(mdev, 0);
+
+	bmac_enable_and_reset_chip(dev);
+	bmwrite(dev, INTDISABLE, DisableAll);
+
+	rev = addr[0] == 0 && addr[1] == 0xA0;
+	for (j = 0; j < 6; ++j)
+		dev->dev_addr[j] = rev ? bitrev8(addr[j]): addr[j];
+
+	/* Enable chip without interrupts for now */
+	bmac_enable_and_reset_chip(dev);
+	bmwrite(dev, INTDISABLE, DisableAll);
+
+	dev->netdev_ops = &bmac_netdev_ops;
+	dev->ethtool_ops = &bmac_ethtool_ops;
+
+	bmac_get_station_address(dev, addr);
+	if (bmac_verify_checksum(dev) != 0)
+		goto err_out_iounmap;
+
+	bp->is_bmac_plus = is_bmac_plus;
+	bp->tx_dma = ioremap(macio_resource_start(mdev, 1), macio_resource_len(mdev, 1));
+	if (!bp->tx_dma)
+		goto err_out_iounmap;
+	bp->tx_dma_intr = macio_irq(mdev, 1);
+	bp->rx_dma = ioremap(macio_resource_start(mdev, 2), macio_resource_len(mdev, 2));
+	if (!bp->rx_dma)
+		goto err_out_iounmap_tx;
+	bp->rx_dma_intr = macio_irq(mdev, 2);
+
+	bp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(bp + 1);
+	bp->rx_cmds = bp->tx_cmds + N_TX_RING + 1;
+
+	bp->queue = (struct sk_buff_head *)(bp->rx_cmds + N_RX_RING + 1);
+	skb_queue_head_init(bp->queue);
+
+	init_timer(&bp->tx_timeout);
+
+	ret = request_irq(dev->irq, bmac_misc_intr, 0, "BMAC-misc", dev);
+	if (ret) {
+		printk(KERN_ERR "BMAC: can't get irq %d\n", dev->irq);
+		goto err_out_iounmap_rx;
+	}
+	ret = request_irq(bp->tx_dma_intr, bmac_txdma_intr, 0, "BMAC-txdma", dev);
+	if (ret) {
+		printk(KERN_ERR "BMAC: can't get irq %d\n", bp->tx_dma_intr);
+		goto err_out_irq0;
+	}
+	ret = request_irq(bp->rx_dma_intr, bmac_rxdma_intr, 0, "BMAC-rxdma", dev);
+	if (ret) {
+		printk(KERN_ERR "BMAC: can't get irq %d\n", bp->rx_dma_intr);
+		goto err_out_irq1;
+	}
+
+	/* Mask chip interrupts and disable chip, will be
+	 * re-enabled on open()
+	 */
+	disable_irq(dev->irq);
+	pmac_call_feature(PMAC_FTR_BMAC_ENABLE, macio_get_of_node(bp->mdev), 0, 0);
+
+	if (register_netdev(dev) != 0) {
+		printk(KERN_ERR "BMAC: Ethernet registration failed\n");
+		goto err_out_irq2;
+	}
+
+	printk(KERN_INFO "%s: BMAC%s at %pM",
+	       dev->name, (is_bmac_plus ? "+" : ""), dev->dev_addr);
+	XXDEBUG((", base_addr=%#0lx", dev->base_addr));
+	printk("\n");
+
+	return 0;
+
+err_out_irq2:
+	free_irq(bp->rx_dma_intr, dev);
+err_out_irq1:
+	free_irq(bp->tx_dma_intr, dev);
+err_out_irq0:
+	free_irq(dev->irq, dev);
+err_out_iounmap_rx:
+	iounmap(bp->rx_dma);
+err_out_iounmap_tx:
+	iounmap(bp->tx_dma);
+err_out_iounmap:
+	iounmap((void __iomem *)dev->base_addr);
+out_release:
+	macio_release_resources(mdev);
+out_free:
+	pmac_call_feature(PMAC_FTR_BMAC_ENABLE, macio_get_of_node(bp->mdev), 0, 0);
+	free_netdev(dev);
+
+	return -ENODEV;
+}
+
+static int bmac_open(struct net_device *dev)
+{
+	struct bmac_data *bp = netdev_priv(dev);
+	/* XXDEBUG(("bmac: enter open\n")); */
+	/* reset the chip */
+	bp->opened = 1;
+	bmac_reset_and_enable(dev);
+	enable_irq(dev->irq);
+	return 0;
+}
+
+static int bmac_close(struct net_device *dev)
+{
+	struct bmac_data *bp = netdev_priv(dev);
+	volatile struct dbdma_regs __iomem *rd = bp->rx_dma;
+	volatile struct dbdma_regs __iomem *td = bp->tx_dma;
+	unsigned short config;
+	int i;
+
+	bp->sleeping = 1;
+
+	/* disable rx and tx */
+	config = bmread(dev, RXCFG);
+	bmwrite(dev, RXCFG, (config & ~RxMACEnable));
+
+	config = bmread(dev, TXCFG);
+	bmwrite(dev, TXCFG, (config & ~TxMACEnable));
+
+	bmwrite(dev, INTDISABLE, DisableAll); /* disable all intrs */
+
+	/* disable rx and tx dma */
+	st_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE));	/* clear run bit */
+	st_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE));	/* clear run bit */
+
+	/* free some skb's */
+	XXDEBUG(("bmac: free rx bufs\n"));
+	for (i=0; i<N_RX_RING; i++) {
+		if (bp->rx_bufs[i] != NULL) {
+			dev_kfree_skb(bp->rx_bufs[i]);
+			bp->rx_bufs[i] = NULL;
+		}
+	}
+	XXDEBUG(("bmac: free tx bufs\n"));
+	for (i = 0; i<N_TX_RING; i++) {
+		if (bp->tx_bufs[i] != NULL) {
+			dev_kfree_skb(bp->tx_bufs[i]);
+			bp->tx_bufs[i] = NULL;
+		}
+	}
+	XXDEBUG(("bmac: all bufs freed\n"));
+
+	bp->opened = 0;
+	disable_irq(dev->irq);
+	pmac_call_feature(PMAC_FTR_BMAC_ENABLE, macio_get_of_node(bp->mdev), 0, 0);
+
+	return 0;
+}
+
+static void
+bmac_start(struct net_device *dev)
+{
+	struct bmac_data *bp = netdev_priv(dev);
+	int i;
+	struct sk_buff *skb;
+	unsigned long flags;
+
+	if (bp->sleeping)
+		return;
+
+	spin_lock_irqsave(&bp->lock, flags);
+	while (1) {
+		i = bp->tx_fill + 1;
+		if (i >= N_TX_RING)
+			i = 0;
+		if (i == bp->tx_empty)
+			break;
+		skb = skb_dequeue(bp->queue);
+		if (skb == NULL)
+			break;
+		bmac_transmit_packet(skb, dev);
+	}
+	spin_unlock_irqrestore(&bp->lock, flags);
+}
+
+static int
+bmac_output(struct sk_buff *skb, struct net_device *dev)
+{
+	struct bmac_data *bp = netdev_priv(dev);
+	skb_queue_tail(bp->queue, skb);
+	bmac_start(dev);
+	return NETDEV_TX_OK;
+}
+
+static void bmac_tx_timeout(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *) data;
+	struct bmac_data *bp = netdev_priv(dev);
+	volatile struct dbdma_regs __iomem *td = bp->tx_dma;
+	volatile struct dbdma_regs __iomem *rd = bp->rx_dma;
+	volatile struct dbdma_cmd *cp;
+	unsigned long flags;
+	unsigned short config, oldConfig;
+	int i;
+
+	XXDEBUG(("bmac: tx_timeout called\n"));
+	spin_lock_irqsave(&bp->lock, flags);
+	bp->timeout_active = 0;
+
+	/* update various counters */
+/*     	bmac_handle_misc_intrs(bp, 0); */
+
+	cp = &bp->tx_cmds[bp->tx_empty];
+/*	XXDEBUG((KERN_DEBUG "bmac: tx dmastat=%x %x runt=%d pr=%x fs=%x fc=%x\n", */
+/* 	   ld_le32(&td->status), ld_le16(&cp->xfer_status), bp->tx_bad_runt, */
+/* 	   mb->pr, mb->xmtfs, mb->fifofc)); */
+
+	/* turn off both tx and rx and reset the chip */
+	config = bmread(dev, RXCFG);
+	bmwrite(dev, RXCFG, (config & ~RxMACEnable));
+	config = bmread(dev, TXCFG);
+	bmwrite(dev, TXCFG, (config & ~TxMACEnable));
+	out_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE|ACTIVE|DEAD));
+	printk(KERN_ERR "bmac: transmit timeout - resetting\n");
+	bmac_enable_and_reset_chip(dev);
+
+	/* restart rx dma */
+	cp = bus_to_virt(ld_le32(&rd->cmdptr));
+	out_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE|ACTIVE|DEAD));
+	out_le16(&cp->xfer_status, 0);
+	out_le32(&rd->cmdptr, virt_to_bus(cp));
+	out_le32(&rd->control, DBDMA_SET(RUN|WAKE));
+
+	/* fix up the transmit side */
+	XXDEBUG((KERN_DEBUG "bmac: tx empty=%d fill=%d fullup=%d\n",
+		 bp->tx_empty, bp->tx_fill, bp->tx_fullup));
+	i = bp->tx_empty;
+	++dev->stats.tx_errors;
+	if (i != bp->tx_fill) {
+		dev_kfree_skb(bp->tx_bufs[i]);
+		bp->tx_bufs[i] = NULL;
+		if (++i >= N_TX_RING) i = 0;
+		bp->tx_empty = i;
+	}
+	bp->tx_fullup = 0;
+	netif_wake_queue(dev);
+	if (i != bp->tx_fill) {
+		cp = &bp->tx_cmds[i];
+		out_le16(&cp->xfer_status, 0);
+		out_le16(&cp->command, OUTPUT_LAST);
+		out_le32(&td->cmdptr, virt_to_bus(cp));
+		out_le32(&td->control, DBDMA_SET(RUN));
+		/* 	bmac_set_timeout(dev); */
+		XXDEBUG((KERN_DEBUG "bmac: starting %d\n", i));
+	}
+
+	/* turn it back on */
+	oldConfig = bmread(dev, RXCFG);
+	bmwrite(dev, RXCFG, oldConfig | RxMACEnable );
+	oldConfig = bmread(dev, TXCFG);
+	bmwrite(dev, TXCFG, oldConfig | TxMACEnable );
+
+	spin_unlock_irqrestore(&bp->lock, flags);
+}
+
+#if 0
+static void dump_dbdma(volatile struct dbdma_cmd *cp,int count)
+{
+	int i,*ip;
+
+	for (i=0;i< count;i++) {
+		ip = (int*)(cp+i);
+
+		printk("dbdma req 0x%x addr 0x%x baddr 0x%x xfer/res 0x%x\n",
+		       ld_le32(ip+0),
+		       ld_le32(ip+1),
+		       ld_le32(ip+2),
+		       ld_le32(ip+3));
+	}
+
+}
+#endif
+
+#if 0
+static int
+bmac_proc_info(char *buffer, char **start, off_t offset, int length)
+{
+	int len = 0;
+	off_t pos   = 0;
+	off_t begin = 0;
+	int i;
+
+	if (bmac_devs == NULL)
+		return -ENOSYS;
+
+	len += sprintf(buffer, "BMAC counters & registers\n");
+
+	for (i = 0; i<N_REG_ENTRIES; i++) {
+		len += sprintf(buffer + len, "%s: %#08x\n",
+			       reg_entries[i].name,
+			       bmread(bmac_devs, reg_entries[i].reg_offset));
+		pos = begin + len;
+
+		if (pos < offset) {
+			len = 0;
+			begin = pos;
+		}
+
+		if (pos > offset+length) break;
+	}
+
+	*start = buffer + (offset - begin);
+	len -= (offset - begin);
+
+	if (len > length) len = length;
+
+	return len;
+}
+#endif
+
+static int __devexit bmac_remove(struct macio_dev *mdev)
+{
+	struct net_device *dev = macio_get_drvdata(mdev);
+	struct bmac_data *bp = netdev_priv(dev);
+
+	unregister_netdev(dev);
+
+       	free_irq(dev->irq, dev);
+	free_irq(bp->tx_dma_intr, dev);
+	free_irq(bp->rx_dma_intr, dev);
+
+	iounmap((void __iomem *)dev->base_addr);
+	iounmap(bp->tx_dma);
+	iounmap(bp->rx_dma);
+
+	macio_release_resources(mdev);
+
+	free_netdev(dev);
+
+	return 0;
+}
+
+static struct of_device_id bmac_match[] =
+{
+	{
+	.name 		= "bmac",
+	.data		= (void *)0,
+	},
+	{
+	.type		= "network",
+	.compatible	= "bmac+",
+	.data		= (void *)1,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE (of, bmac_match);
+
+static struct macio_driver bmac_driver =
+{
+	.driver = {
+		.name 		= "bmac",
+		.owner		= THIS_MODULE,
+		.of_match_table	= bmac_match,
+	},
+	.probe		= bmac_probe,
+	.remove		= bmac_remove,
+#ifdef CONFIG_PM
+	.suspend	= bmac_suspend,
+	.resume		= bmac_resume,
+#endif
+};
+
+
+static int __init bmac_init(void)
+{
+	if (bmac_emergency_rxbuf == NULL) {
+		bmac_emergency_rxbuf = kmalloc(RX_BUFLEN, GFP_KERNEL);
+		if (bmac_emergency_rxbuf == NULL) {
+			printk(KERN_ERR "BMAC: can't allocate emergency RX buffer\n");
+			return -ENOMEM;
+		}
+	}
+
+	return macio_register_driver(&bmac_driver);
+}
+
+static void __exit bmac_exit(void)
+{
+	macio_unregister_driver(&bmac_driver);
+
+	kfree(bmac_emergency_rxbuf);
+	bmac_emergency_rxbuf = NULL;
+}
+
+MODULE_AUTHOR("Randy Gobbel/Paul Mackerras");
+MODULE_DESCRIPTION("PowerMac BMAC ethernet driver.");
+MODULE_LICENSE("GPL");
+
+module_init(bmac_init);
+module_exit(bmac_exit);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/apple/bmac.h linux-libre-3.2-gnu/drivers/net/ethernet/apple/bmac.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/apple/bmac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/apple/bmac.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,164 @@
+/*
+ * mace.h - definitions for the registers in the "Big Mac"
+ *  Ethernet controller found in PowerMac G3 models.
+ *
+ * Copyright (C) 1998 Randy Gobbel.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/* The "Big MAC" appears to have some parts in common with the Sun "Happy Meal"
+ * (HME) controller.  See sunhme.h
+ */
+
+
+/* register offsets */
+
+/* global status and control */
+#define	XIFC		0x000   /* low-level interface control */
+#	define	TxOutputEnable	0x0001 /* output driver enable */
+#	define	XIFLoopback	0x0002 /* Loopback-mode XIF enable */
+#	define	MIILoopback	0x0004 /* Loopback-mode MII enable */
+#	define	MIILoopbackBits	0x0006
+#	define	MIIBuffDisable	0x0008 /* MII receive buffer disable */
+#	define	SQETestEnable	0x0010 /* SQE test enable */
+#	define	SQETimeWindow	0x03e0 /* SQE time window */
+#	define	XIFLanceMode	0x0010 /* Lance mode enable */
+#	define	XIFLanceIPG0	0x03e0 /* Lance mode IPG0 */
+#define	TXFIFOCSR	0x100   /* transmit FIFO control */
+#	define	TxFIFOEnable	0x0001
+#define	TXTH		0x110   /* transmit threshold */
+#	define	TxThreshold	0x0004
+#define RXFIFOCSR	0x120   /* receive FIFO control */
+#	define	RxFIFOEnable	0x0001
+#define MEMADD		0x130   /* memory address, unknown function */
+#define MEMDATAHI	0x140   /* memory data high, presently unused in driver */
+#define MEMDATALO	0x150   /* memory data low, presently unused in driver */
+#define XCVRIF		0x160   /* transceiver interface control */
+#	define	COLActiveLow	0x0002
+#	define	SerialMode	0x0004
+#	define	ClkBit		0x0008
+#	define	LinkStatus	0x0100
+#define CHIPID          0x170   /* chip ID */
+#define	MIFCSR		0x180   /* ??? */
+#define	SROMCSR		0x190   /* SROM control */
+#	define	ChipSelect	0x0001
+#	define	Clk		0x0002
+#define TXPNTR		0x1a0   /* transmit pointer */
+#define	RXPNTR		0x1b0   /* receive pointer */
+#define	STATUS		0x200   /* status--reading this clears it */
+#define	INTDISABLE	0x210   /* interrupt enable/disable control */
+/* bits below are the same in both STATUS and INTDISABLE registers */
+#	define	FrameReceived	0x00000001 /* Received a frame */
+#	define	RxFrameCntExp	0x00000002 /* Receive frame counter expired */
+#	define	RxAlignCntExp	0x00000004 /* Align-error counter expired */
+#	define	RxCRCCntExp	0x00000008 /* CRC-error counter expired */
+#	define	RxLenCntExp	0x00000010 /* Length-error counter expired */
+#	define	RxOverFlow	0x00000020 /* Receive FIFO overflow */
+#	define	RxCodeViolation	0x00000040 /* Code-violation counter expired */
+#	define	SQETestError	0x00000080 /* Test error in XIF for SQE */
+#	define	FrameSent	0x00000100 /* Transmitted a frame */
+#	define	TxUnderrun	0x00000200 /* Transmit FIFO underrun */
+#	define	TxMaxSizeError	0x00000400 /* Max-packet size error */
+#	define	TxNormalCollExp	0x00000800 /* Normal-collision counter expired */
+#	define	TxExcessCollExp	0x00001000 /* Excess-collision counter expired */
+#	define	TxLateCollExp	0x00002000 /* Late-collision counter expired */
+#	define	TxNetworkCollExp 0x00004000 /* First-collision counter expired */
+#	define	TxDeferTimerExp	0x00008000 /* Defer-timer expired */
+#	define	RxFIFOToHost	0x00010000 /* Data moved from FIFO to host */
+#	define	RxNoDescriptors	0x00020000 /* No more receive descriptors */
+#	define	RxDMAError	0x00040000 /* Error during receive DMA */
+#	define	RxDMALateErr	0x00080000 /* Receive DMA, data late */
+#	define	RxParityErr	0x00100000 /* Parity error during receive DMA */
+#	define	RxTagError	0x00200000 /* Tag error during receive DMA */
+#	define	TxEOPError	0x00400000 /* Tx descriptor did not have EOP set */
+#	define	MIFIntrEvent	0x00800000 /* MIF is signaling an interrupt */
+#	define	TxHostToFIFO	0x01000000 /* Data moved from host to FIFO  */
+#	define	TxFIFOAllSent	0x02000000 /* Transmitted all packets in FIFO */
+#	define	TxDMAError	0x04000000 /* Error during transmit DMA */
+#	define	TxDMALateError	0x08000000 /* Late error during transmit DMA */
+#	define	TxParityError	0x10000000 /* Parity error during transmit DMA */
+#	define	TxTagError	0x20000000 /* Tag error during transmit DMA */
+#	define	PIOError	0x40000000 /* PIO access got an error */
+#	define	PIOParityError	0x80000000 /* PIO access got a parity error  */
+#	define	DisableAll	0xffffffff
+#	define	EnableAll	0x00000000
+/* #	define	NormalIntEvents	~(FrameReceived | FrameSent | TxUnderrun) */
+#	define	EnableNormal	~(FrameReceived | FrameSent)
+#	define	EnableErrors	(FrameReceived | FrameSent)
+#	define	RxErrorMask	(RxFrameCntExp | RxAlignCntExp | RxCRCCntExp | \
+				 RxLenCntExp | RxOverFlow | RxCodeViolation)
+#	define	TxErrorMask	(TxUnderrun | TxMaxSizeError | TxExcessCollExp | \
+				 TxLateCollExp | TxNetworkCollExp | TxDeferTimerExp)
+
+/* transmit control */
+#define	TXRST		0x420   /* transmit reset */
+#	define	TxResetBit	0x0001
+#define	TXCFG		0x430   /* transmit configuration control*/
+#	define	TxMACEnable	0x0001 /* output driver enable */
+#	define	TxSlowMode	0x0020 /* enable slow mode */
+#	define	TxIgnoreColl	0x0040 /* ignore transmit collisions */
+#	define	TxNoFCS		0x0080 /* do not emit FCS */
+#	define	TxNoBackoff	0x0100 /* no backoff in case of collisions */
+#	define	TxFullDuplex	0x0200 /* enable full-duplex */
+#	define	TxNeverGiveUp	0x0400 /* don't give up on transmits */
+#define IPG1		0x440   /* Inter-packet gap 1 */
+#define IPG2		0x450   /* Inter-packet gap 2 */
+#define ALIMIT		0x460   /* Transmit attempt limit */
+#define SLOT		0x470   /* Transmit slot time */
+#define PALEN		0x480   /* Size of transmit preamble */
+#define PAPAT		0x490   /* Pattern for transmit preamble */
+#define TXSFD		0x4a0   /* Transmit frame delimiter */
+#define JAM		0x4b0   /* Jam size */
+#define TXMAX		0x4c0   /* Transmit max pkt size */
+#define TXMIN		0x4d0   /* Transmit min pkt size */
+#define PAREG		0x4e0   /* Count of transmit peak attempts */
+#define DCNT		0x4f0   /* Transmit defer timer */
+#define NCCNT		0x500   /* Transmit normal-collision counter */
+#define NTCNT		0x510   /* Transmit first-collision counter */
+#define EXCNT		0x520   /* Transmit excess-collision counter */
+#define LTCNT		0x530   /* Transmit late-collision counter */
+#define RSEED		0x540   /* Transmit random number seed */
+#define TXSM		0x550   /* Transmit state machine */
+
+/* receive control */
+#define RXRST		0x620   /* receive reset */
+#	define	RxResetValue	0x0000
+#define RXCFG		0x630   /* receive configuration control */
+#	define	RxMACEnable	0x0001 /* receiver overall enable */
+#	define	RxCFGReserved	0x0004
+#	define	RxPadStripEnab	0x0020 /* enable pad byte stripping */
+#	define	RxPromiscEnable	0x0040 /* turn on promiscuous mode */
+#	define	RxNoErrCheck	0x0080 /* disable receive error checking */
+#	define	RxCRCNoStrip	0x0100 /* disable auto-CRC-stripping */
+#	define	RxRejectOwnPackets 0x0200 /* don't receive our own packets */
+#	define	RxGrpPromisck	0x0400 /* enable group promiscuous mode */
+#	define	RxHashFilterEnable 0x0800 /* enable hash filter */
+#	define	RxAddrFilterEnable 0x1000 /* enable address filter */
+#define RXMAX		0x640   /* Max receive packet size */
+#define RXMIN		0x650   /* Min receive packet size */
+#define MADD2		0x660   /* our enet address, high part */
+#define MADD1		0x670   /* our enet address, middle part */
+#define MADD0		0x680   /* our enet address, low part */
+#define FRCNT		0x690   /* receive frame counter */
+#define LECNT		0x6a0   /* Receive excess length error counter */
+#define AECNT		0x6b0   /* Receive misaligned error counter */
+#define FECNT		0x6c0   /* Receive CRC error counter */
+#define RXSM		0x6d0   /* Receive state machine */
+#define RXCV		0x6e0   /* Receive code violation */
+
+#define BHASH3		0x700   /* multicast hash register */
+#define BHASH2		0x710   /* multicast hash register */
+#define BHASH1		0x720   /* multicast hash register */
+#define BHASH0		0x730   /* multicast hash register */
+
+#define AFR2		0x740   /* address filtering setup? */
+#define AFR1		0x750   /* address filtering setup? */
+#define AFR0		0x760   /* address filtering setup? */
+#define AFCR		0x770   /* address filter compare register? */
+#	define	EnableAllCompares 0x0fff
+
+/* bits in XIFC */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/apple/Kconfig linux-libre-3.2-gnu/drivers/net/ethernet/apple/Kconfig
--- linux-libre-3.1-gnu/drivers/net/ethernet/apple/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/apple/Kconfig	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,65 @@
+#
+# Apple device configuration
+#
+
+config NET_VENDOR_APPLE
+	bool "Apple devices"
+	default y
+	depends on (PPC_PMAC && PPC32) || MAC
+	---help---
+	  If you have a network (Ethernet) card belonging to this class, say Y
+	  and read the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  Note that the answer to this question doesn't directly affect the
+	  kernel: saying N will just cause the configurator to skip all
+	  the questions about IBM devices. If you say Y, you will be asked for
+	  your specific card in the following questions.
+
+if NET_VENDOR_APPLE
+
+config MACE
+	tristate "MACE (Power Mac ethernet) support"
+	depends on PPC_PMAC && PPC32
+	select CRC32
+	---help---
+	  Power Macintoshes and clones with Ethernet built-in on the
+	  motherboard will usually use a MACE (Medium Access Control for
+	  Ethernet) interface. Say Y to include support for the MACE chip.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called mace.
+
+config MACE_AAUI_PORT
+	bool "Use AAUI port instead of TP by default"
+	depends on MACE
+	---help---
+	  Some Apple machines (notably the Apple Network Server) which use the
+	  MACE ethernet chip have an Apple AUI port (small 15-pin connector),
+	  instead of an 8-pin RJ45 connector for twisted-pair ethernet.  Say
+	  Y here if you have such a machine.  If unsure, say N.
+	  The driver will default to AAUI on ANS anyway, and if you use it as
+	  a module, you can provide the port_aaui=0|1 to force the driver.
+
+config BMAC
+	tristate "BMAC (G3 ethernet) support"
+	depends on PPC_PMAC && PPC32
+	select CRC32
+	---help---
+	  Say Y for support of BMAC Ethernet interfaces. These are used on G3
+	  computers.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called bmac.
+
+config MACMACE
+	bool "Macintosh (AV) onboard MACE ethernet"
+	depends on MAC
+	select CRC32
+	---help---
+	  Support for the onboard AMD 79C940 MACE Ethernet controller used in
+	  the 660AV and 840AV Macintosh.  If you have one of these Macintoshes
+	  say Y and read the Ethernet-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+endif # NET_VENDOR_APPLE
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/apple/mace.c linux-libre-3.2-gnu/drivers/net/ethernet/apple/mace.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/apple/mace.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/apple/mace.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,1031 @@
+/*
+ * Network device driver for the MACE ethernet controller on
+ * Apple Powermacs.  Assumes it's under a DBDMA controller.
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/crc32.h>
+#include <linux/spinlock.h>
+#include <linux/bitrev.h>
+#include <linux/slab.h>
+#include <asm/prom.h>
+#include <asm/dbdma.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/macio.h>
+
+#include "mace.h"
+
+static int port_aaui = -1;
+
+#define N_RX_RING	8
+#define N_TX_RING	6
+#define MAX_TX_ACTIVE	1
+#define NCMDS_TX	1	/* dma commands per element in tx ring */
+#define RX_BUFLEN	(ETH_FRAME_LEN + 8)
+#define TX_TIMEOUT	HZ	/* 1 second */
+
+/* Chip rev needs workaround on HW & multicast addr change */
+#define BROKEN_ADDRCHG_REV	0x0941
+
+/* Bits in transmit DMA status */
+#define TX_DMA_ERR	0x80
+
+struct mace_data {
+    volatile struct mace __iomem *mace;
+    volatile struct dbdma_regs __iomem *tx_dma;
+    int tx_dma_intr;
+    volatile struct dbdma_regs __iomem *rx_dma;
+    int rx_dma_intr;
+    volatile struct dbdma_cmd *tx_cmds;	/* xmit dma command list */
+    volatile struct dbdma_cmd *rx_cmds;	/* recv dma command list */
+    struct sk_buff *rx_bufs[N_RX_RING];
+    int rx_fill;
+    int rx_empty;
+    struct sk_buff *tx_bufs[N_TX_RING];
+    int tx_fill;
+    int tx_empty;
+    unsigned char maccc;
+    unsigned char tx_fullup;
+    unsigned char tx_active;
+    unsigned char tx_bad_runt;
+    struct timer_list tx_timeout;
+    int timeout_active;
+    int port_aaui;
+    int chipid;
+    struct macio_dev *mdev;
+    spinlock_t lock;
+};
+
+/*
+ * Number of bytes of private data per MACE: allow enough for
+ * the rx and tx dma commands plus a branch dma command each,
+ * and another 16 bytes to allow us to align the dma command
+ * buffers on a 16 byte boundary.
+ */
+#define PRIV_BYTES	(sizeof(struct mace_data) \
+	+ (N_RX_RING + NCMDS_TX * N_TX_RING + 3) * sizeof(struct dbdma_cmd))
+
+static int mace_open(struct net_device *dev);
+static int mace_close(struct net_device *dev);
+static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
+static void mace_set_multicast(struct net_device *dev);
+static void mace_reset(struct net_device *dev);
+static int mace_set_address(struct net_device *dev, void *addr);
+static irqreturn_t mace_interrupt(int irq, void *dev_id);
+static irqreturn_t mace_txdma_intr(int irq, void *dev_id);
+static irqreturn_t mace_rxdma_intr(int irq, void *dev_id);
+static void mace_set_timeout(struct net_device *dev);
+static void mace_tx_timeout(unsigned long data);
+static inline void dbdma_reset(volatile struct dbdma_regs __iomem *dma);
+static inline void mace_clean_rings(struct mace_data *mp);
+static void __mace_set_address(struct net_device *dev, void *addr);
+
+/*
+ * If we can't get a skbuff when we need it, we use this area for DMA.
+ */
+static unsigned char *dummy_buf;
+
+static const struct net_device_ops mace_netdev_ops = {
+	.ndo_open		= mace_open,
+	.ndo_stop		= mace_close,
+	.ndo_start_xmit		= mace_xmit_start,
+	.ndo_set_rx_mode	= mace_set_multicast,
+	.ndo_set_mac_address	= mace_set_address,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_id *match)
+{
+	struct device_node *mace = macio_get_of_node(mdev);
+	struct net_device *dev;
+	struct mace_data *mp;
+	const unsigned char *addr;
+	int j, rev, rc = -EBUSY;
+
+	if (macio_resource_count(mdev) != 3 || macio_irq_count(mdev) != 3) {
+		printk(KERN_ERR "can't use MACE %s: need 3 addrs and 3 irqs\n",
+		       mace->full_name);
+		return -ENODEV;
+	}
+
+	addr = of_get_property(mace, "mac-address", NULL);
+	if (addr == NULL) {
+		addr = of_get_property(mace, "local-mac-address", NULL);
+		if (addr == NULL) {
+			printk(KERN_ERR "Can't get mac-address for MACE %s\n",
+			       mace->full_name);
+			return -ENODEV;
+		}
+	}
+
+	/*
+	 * lazy allocate the driver-wide dummy buffer. (Note that we
+	 * never have more than one MACE in the system anyway)
+	 */
+	if (dummy_buf == NULL) {
+		dummy_buf = kmalloc(RX_BUFLEN+2, GFP_KERNEL);
+		if (dummy_buf == NULL) {
+			printk(KERN_ERR "MACE: couldn't allocate dummy buffer\n");
+			return -ENOMEM;
+		}
+	}
+
+	if (macio_request_resources(mdev, "mace")) {
+		printk(KERN_ERR "MACE: can't request IO resources !\n");
+		return -EBUSY;
+	}
+
+	dev = alloc_etherdev(PRIV_BYTES);
+	if (!dev) {
+		printk(KERN_ERR "MACE: can't allocate ethernet device !\n");
+		rc = -ENOMEM;
+		goto err_release;
+	}
+	SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
+
+	mp = netdev_priv(dev);
+	mp->mdev = mdev;
+	macio_set_drvdata(mdev, dev);
+
+	dev->base_addr = macio_resource_start(mdev, 0);
+	mp->mace = ioremap(dev->base_addr, 0x1000);
+	if (mp->mace == NULL) {
+		printk(KERN_ERR "MACE: can't map IO resources !\n");
+		rc = -ENOMEM;
+		goto err_free;
+	}
+	dev->irq = macio_irq(mdev, 0);
+
+	rev = addr[0] == 0 && addr[1] == 0xA0;
+	for (j = 0; j < 6; ++j) {
+		dev->dev_addr[j] = rev ? bitrev8(addr[j]): addr[j];
+	}
+	mp->chipid = (in_8(&mp->mace->chipid_hi) << 8) |
+			in_8(&mp->mace->chipid_lo);
+
+
+	mp = netdev_priv(dev);
+	mp->maccc = ENXMT | ENRCV;
+
+	mp->tx_dma = ioremap(macio_resource_start(mdev, 1), 0x1000);
+	if (mp->tx_dma == NULL) {
+		printk(KERN_ERR "MACE: can't map TX DMA resources !\n");
+		rc = -ENOMEM;
+		goto err_unmap_io;
+	}
+	mp->tx_dma_intr = macio_irq(mdev, 1);
+
+	mp->rx_dma = ioremap(macio_resource_start(mdev, 2), 0x1000);
+	if (mp->rx_dma == NULL) {
+		printk(KERN_ERR "MACE: can't map RX DMA resources !\n");
+		rc = -ENOMEM;
+		goto err_unmap_tx_dma;
+	}
+	mp->rx_dma_intr = macio_irq(mdev, 2);
+
+	mp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(mp + 1);
+	mp->rx_cmds = mp->tx_cmds + NCMDS_TX * N_TX_RING + 1;
+
+	memset((char *) mp->tx_cmds, 0,
+	       (NCMDS_TX*N_TX_RING + N_RX_RING + 2) * sizeof(struct dbdma_cmd));
+	init_timer(&mp->tx_timeout);
+	spin_lock_init(&mp->lock);
+	mp->timeout_active = 0;
+
+	if (port_aaui >= 0)
+		mp->port_aaui = port_aaui;
+	else {
+		/* Apple Network Server uses the AAUI port */
+		if (of_machine_is_compatible("AAPL,ShinerESB"))
+			mp->port_aaui = 1;
+		else {
+#ifdef CONFIG_MACE_AAUI_PORT
+			mp->port_aaui = 1;
+#else
+			mp->port_aaui = 0;
+#endif
+		}
+	}
+
+	dev->netdev_ops = &mace_netdev_ops;
+
+	/*
+	 * Most of what is below could be moved to mace_open()
+	 */
+	mace_reset(dev);
+
+	rc = request_irq(dev->irq, mace_interrupt, 0, "MACE", dev);
+	if (rc) {
+		printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq);
+		goto err_unmap_rx_dma;
+	}
+	rc = request_irq(mp->tx_dma_intr, mace_txdma_intr, 0, "MACE-txdma", dev);
+	if (rc) {
+		printk(KERN_ERR "MACE: can't get irq %d\n", mp->tx_dma_intr);
+		goto err_free_irq;
+	}
+	rc = request_irq(mp->rx_dma_intr, mace_rxdma_intr, 0, "MACE-rxdma", dev);
+	if (rc) {
+		printk(KERN_ERR "MACE: can't get irq %d\n", mp->rx_dma_intr);
+		goto err_free_tx_irq;
+	}
+
+	rc = register_netdev(dev);
+	if (rc) {
+		printk(KERN_ERR "MACE: Cannot register net device, aborting.\n");
+		goto err_free_rx_irq;
+	}
+
+	printk(KERN_INFO "%s: MACE at %pM, chip revision %d.%d\n",
+	       dev->name, dev->dev_addr,
+	       mp->chipid >> 8, mp->chipid & 0xff);
+
+	return 0;
+
+ err_free_rx_irq:
+	free_irq(macio_irq(mdev, 2), dev);
+ err_free_tx_irq:
+	free_irq(macio_irq(mdev, 1), dev);
+ err_free_irq:
+	free_irq(macio_irq(mdev, 0), dev);
+ err_unmap_rx_dma:
+	iounmap(mp->rx_dma);
+ err_unmap_tx_dma:
+	iounmap(mp->tx_dma);
+ err_unmap_io:
+	iounmap(mp->mace);
+ err_free:
+	free_netdev(dev);
+ err_release:
+	macio_release_resources(mdev);
+
+	return rc;
+}
+
+static int __devexit mace_remove(struct macio_dev *mdev)
+{
+	struct net_device *dev = macio_get_drvdata(mdev);
+	struct mace_data *mp;
+
+	BUG_ON(dev == NULL);
+
+	macio_set_drvdata(mdev, NULL);
+
+	mp = netdev_priv(dev);
+
+	unregister_netdev(dev);
+
+	free_irq(dev->irq, dev);
+	free_irq(mp->tx_dma_intr, dev);
+	free_irq(mp->rx_dma_intr, dev);
+
+	iounmap(mp->rx_dma);
+	iounmap(mp->tx_dma);
+	iounmap(mp->mace);
+
+	free_netdev(dev);
+
+	macio_release_resources(mdev);
+
+	return 0;
+}
+
+static void dbdma_reset(volatile struct dbdma_regs __iomem *dma)
+{
+    int i;
+
+    out_le32(&dma->control, (WAKE|FLUSH|PAUSE|RUN) << 16);
+
+    /*
+     * Yes this looks peculiar, but apparently it needs to be this
+     * way on some machines.
+     */
+    for (i = 200; i > 0; --i)
+	if (ld_le32(&dma->control) & RUN)
+	    udelay(1);
+}
+
+static void mace_reset(struct net_device *dev)
+{
+    struct mace_data *mp = netdev_priv(dev);
+    volatile struct mace __iomem *mb = mp->mace;
+    int i;
+
+    /* soft-reset the chip */
+    i = 200;
+    while (--i) {
+	out_8(&mb->biucc, SWRST);
+	if (in_8(&mb->biucc) & SWRST) {
+	    udelay(10);
+	    continue;
+	}
+	break;
+    }
+    if (!i) {
+	printk(KERN_ERR "mace: cannot reset chip!\n");
+	return;
+    }
+
+    out_8(&mb->imr, 0xff);	/* disable all intrs for now */
+    i = in_8(&mb->ir);
+    out_8(&mb->maccc, 0);	/* turn off tx, rx */
+
+    out_8(&mb->biucc, XMTSP_64);
+    out_8(&mb->utr, RTRD);
+    out_8(&mb->fifocc, RCVFW_32 | XMTFW_16 | XMTFWU | RCVFWU | XMTBRST);
+    out_8(&mb->xmtfc, AUTO_PAD_XMIT); /* auto-pad short frames */
+    out_8(&mb->rcvfc, 0);
+
+    /* load up the hardware address */
+    __mace_set_address(dev, dev->dev_addr);
+
+    /* clear the multicast filter */
+    if (mp->chipid == BROKEN_ADDRCHG_REV)
+	out_8(&mb->iac, LOGADDR);
+    else {
+	out_8(&mb->iac, ADDRCHG | LOGADDR);
+	while ((in_8(&mb->iac) & ADDRCHG) != 0)
+		;
+    }
+    for (i = 0; i < 8; ++i)
+	out_8(&mb->ladrf, 0);
+
+    /* done changing address */
+    if (mp->chipid != BROKEN_ADDRCHG_REV)
+	out_8(&mb->iac, 0);
+
+    if (mp->port_aaui)
+    	out_8(&mb->plscc, PORTSEL_AUI + ENPLSIO);
+    else
+    	out_8(&mb->plscc, PORTSEL_GPSI + ENPLSIO);
+}
+
+static void __mace_set_address(struct net_device *dev, void *addr)
+{
+    struct mace_data *mp = netdev_priv(dev);
+    volatile struct mace __iomem *mb = mp->mace;
+    unsigned char *p = addr;
+    int i;
+
+    /* load up the hardware address */
+    if (mp->chipid == BROKEN_ADDRCHG_REV)
+    	out_8(&mb->iac, PHYADDR);
+    else {
+    	out_8(&mb->iac, ADDRCHG | PHYADDR);
+	while ((in_8(&mb->iac) & ADDRCHG) != 0)
+	    ;
+    }
+    for (i = 0; i < 6; ++i)
+	out_8(&mb->padr, dev->dev_addr[i] = p[i]);
+    if (mp->chipid != BROKEN_ADDRCHG_REV)
+        out_8(&mb->iac, 0);
+}
+
+static int mace_set_address(struct net_device *dev, void *addr)
+{
+    struct mace_data *mp = netdev_priv(dev);
+    volatile struct mace __iomem *mb = mp->mace;
+    unsigned long flags;
+
+    spin_lock_irqsave(&mp->lock, flags);
+
+    __mace_set_address(dev, addr);
+
+    /* note: setting ADDRCHG clears ENRCV */
+    out_8(&mb->maccc, mp->maccc);
+
+    spin_unlock_irqrestore(&mp->lock, flags);
+    return 0;
+}
+
+static inline void mace_clean_rings(struct mace_data *mp)
+{
+    int i;
+
+    /* free some skb's */
+    for (i = 0; i < N_RX_RING; ++i) {
+	if (mp->rx_bufs[i] != NULL) {
+	    dev_kfree_skb(mp->rx_bufs[i]);
+	    mp->rx_bufs[i] = NULL;
+	}
+    }
+    for (i = mp->tx_empty; i != mp->tx_fill; ) {
+	dev_kfree_skb(mp->tx_bufs[i]);
+	if (++i >= N_TX_RING)
+	    i = 0;
+    }
+}
+
+static int mace_open(struct net_device *dev)
+{
+    struct mace_data *mp = netdev_priv(dev);
+    volatile struct mace __iomem *mb = mp->mace;
+    volatile struct dbdma_regs __iomem *rd = mp->rx_dma;
+    volatile struct dbdma_regs __iomem *td = mp->tx_dma;
+    volatile struct dbdma_cmd *cp;
+    int i;
+    struct sk_buff *skb;
+    unsigned char *data;
+
+    /* reset the chip */
+    mace_reset(dev);
+
+    /* initialize list of sk_buffs for receiving and set up recv dma */
+    mace_clean_rings(mp);
+    memset((char *)mp->rx_cmds, 0, N_RX_RING * sizeof(struct dbdma_cmd));
+    cp = mp->rx_cmds;
+    for (i = 0; i < N_RX_RING - 1; ++i) {
+	skb = dev_alloc_skb(RX_BUFLEN + 2);
+	if (!skb) {
+	    data = dummy_buf;
+	} else {
+	    skb_reserve(skb, 2);	/* so IP header lands on 4-byte bdry */
+	    data = skb->data;
+	}
+	mp->rx_bufs[i] = skb;
+	st_le16(&cp->req_count, RX_BUFLEN);
+	st_le16(&cp->command, INPUT_LAST + INTR_ALWAYS);
+	st_le32(&cp->phy_addr, virt_to_bus(data));
+	cp->xfer_status = 0;
+	++cp;
+    }
+    mp->rx_bufs[i] = NULL;
+    st_le16(&cp->command, DBDMA_STOP);
+    mp->rx_fill = i;
+    mp->rx_empty = 0;
+
+    /* Put a branch back to the beginning of the receive command list */
+    ++cp;
+    st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS);
+    st_le32(&cp->cmd_dep, virt_to_bus(mp->rx_cmds));
+
+    /* start rx dma */
+    out_le32(&rd->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */
+    out_le32(&rd->cmdptr, virt_to_bus(mp->rx_cmds));
+    out_le32(&rd->control, (RUN << 16) | RUN);
+
+    /* put a branch at the end of the tx command list */
+    cp = mp->tx_cmds + NCMDS_TX * N_TX_RING;
+    st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS);
+    st_le32(&cp->cmd_dep, virt_to_bus(mp->tx_cmds));
+
+    /* reset tx dma */
+    out_le32(&td->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
+    out_le32(&td->cmdptr, virt_to_bus(mp->tx_cmds));
+    mp->tx_fill = 0;
+    mp->tx_empty = 0;
+    mp->tx_fullup = 0;
+    mp->tx_active = 0;
+    mp->tx_bad_runt = 0;
+
+    /* turn it on! */
+    out_8(&mb->maccc, mp->maccc);
+    /* enable all interrupts except receive interrupts */
+    out_8(&mb->imr, RCVINT);
+
+    return 0;
+}
+
+static int mace_close(struct net_device *dev)
+{
+    struct mace_data *mp = netdev_priv(dev);
+    volatile struct mace __iomem *mb = mp->mace;
+    volatile struct dbdma_regs __iomem *rd = mp->rx_dma;
+    volatile struct dbdma_regs __iomem *td = mp->tx_dma;
+
+    /* disable rx and tx */
+    out_8(&mb->maccc, 0);
+    out_8(&mb->imr, 0xff);		/* disable all intrs */
+
+    /* disable rx and tx dma */
+    st_le32(&rd->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */
+    st_le32(&td->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */
+
+    mace_clean_rings(mp);
+
+    return 0;
+}
+
+static inline void mace_set_timeout(struct net_device *dev)
+{
+    struct mace_data *mp = netdev_priv(dev);
+
+    if (mp->timeout_active)
+	del_timer(&mp->tx_timeout);
+    mp->tx_timeout.expires = jiffies + TX_TIMEOUT;
+    mp->tx_timeout.function = mace_tx_timeout;
+    mp->tx_timeout.data = (unsigned long) dev;
+    add_timer(&mp->tx_timeout);
+    mp->timeout_active = 1;
+}
+
+static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
+{
+    struct mace_data *mp = netdev_priv(dev);
+    volatile struct dbdma_regs __iomem *td = mp->tx_dma;
+    volatile struct dbdma_cmd *cp, *np;
+    unsigned long flags;
+    int fill, next, len;
+
+    /* see if there's a free slot in the tx ring */
+    spin_lock_irqsave(&mp->lock, flags);
+    fill = mp->tx_fill;
+    next = fill + 1;
+    if (next >= N_TX_RING)
+	next = 0;
+    if (next == mp->tx_empty) {
+	netif_stop_queue(dev);
+	mp->tx_fullup = 1;
+	spin_unlock_irqrestore(&mp->lock, flags);
+	return NETDEV_TX_BUSY;		/* can't take it at the moment */
+    }
+    spin_unlock_irqrestore(&mp->lock, flags);
+
+    /* partially fill in the dma command block */
+    len = skb->len;
+    if (len > ETH_FRAME_LEN) {
+	printk(KERN_DEBUG "mace: xmit frame too long (%d)\n", len);
+	len = ETH_FRAME_LEN;
+    }
+    mp->tx_bufs[fill] = skb;
+    cp = mp->tx_cmds + NCMDS_TX * fill;
+    st_le16(&cp->req_count, len);
+    st_le32(&cp->phy_addr, virt_to_bus(skb->data));
+
+    np = mp->tx_cmds + NCMDS_TX * next;
+    out_le16(&np->command, DBDMA_STOP);
+
+    /* poke the tx dma channel */
+    spin_lock_irqsave(&mp->lock, flags);
+    mp->tx_fill = next;
+    if (!mp->tx_bad_runt && mp->tx_active < MAX_TX_ACTIVE) {
+	out_le16(&cp->xfer_status, 0);
+	out_le16(&cp->command, OUTPUT_LAST);
+	out_le32(&td->control, ((RUN|WAKE) << 16) + (RUN|WAKE));
+	++mp->tx_active;
+	mace_set_timeout(dev);
+    }
+    if (++next >= N_TX_RING)
+	next = 0;
+    if (next == mp->tx_empty)
+	netif_stop_queue(dev);
+    spin_unlock_irqrestore(&mp->lock, flags);
+
+    return NETDEV_TX_OK;
+}
+
+static void mace_set_multicast(struct net_device *dev)
+{
+    struct mace_data *mp = netdev_priv(dev);
+    volatile struct mace __iomem *mb = mp->mace;
+    int i;
+    u32 crc;
+    unsigned long flags;
+
+    spin_lock_irqsave(&mp->lock, flags);
+    mp->maccc &= ~PROM;
+    if (dev->flags & IFF_PROMISC) {
+	mp->maccc |= PROM;
+    } else {
+	unsigned char multicast_filter[8];
+	struct netdev_hw_addr *ha;
+
+	if (dev->flags & IFF_ALLMULTI) {
+	    for (i = 0; i < 8; i++)
+		multicast_filter[i] = 0xff;
+	} else {
+	    for (i = 0; i < 8; i++)
+		multicast_filter[i] = 0;
+	    netdev_for_each_mc_addr(ha, dev) {
+	        crc = ether_crc_le(6, ha->addr);
+		i = crc >> 26;	/* bit number in multicast_filter */
+		multicast_filter[i >> 3] |= 1 << (i & 7);
+	    }
+	}
+#if 0
+	printk("Multicast filter :");
+	for (i = 0; i < 8; i++)
+	    printk("%02x ", multicast_filter[i]);
+	printk("\n");
+#endif
+
+	if (mp->chipid == BROKEN_ADDRCHG_REV)
+	    out_8(&mb->iac, LOGADDR);
+	else {
+	    out_8(&mb->iac, ADDRCHG | LOGADDR);
+	    while ((in_8(&mb->iac) & ADDRCHG) != 0)
+		;
+	}
+	for (i = 0; i < 8; ++i)
+	    out_8(&mb->ladrf, multicast_filter[i]);
+	if (mp->chipid != BROKEN_ADDRCHG_REV)
+	    out_8(&mb->iac, 0);
+    }
+    /* reset maccc */
+    out_8(&mb->maccc, mp->maccc);
+    spin_unlock_irqrestore(&mp->lock, flags);
+}
+
+static void mace_handle_misc_intrs(struct mace_data *mp, int intr, struct net_device *dev)
+{
+    volatile struct mace __iomem *mb = mp->mace;
+    static int mace_babbles, mace_jabbers;
+
+    if (intr & MPCO)
+	dev->stats.rx_missed_errors += 256;
+    dev->stats.rx_missed_errors += in_8(&mb->mpc);   /* reading clears it */
+    if (intr & RNTPCO)
+	dev->stats.rx_length_errors += 256;
+    dev->stats.rx_length_errors += in_8(&mb->rntpc); /* reading clears it */
+    if (intr & CERR)
+	++dev->stats.tx_heartbeat_errors;
+    if (intr & BABBLE)
+	if (mace_babbles++ < 4)
+	    printk(KERN_DEBUG "mace: babbling transmitter\n");
+    if (intr & JABBER)
+	if (mace_jabbers++ < 4)
+	    printk(KERN_DEBUG "mace: jabbering transceiver\n");
+}
+
+static irqreturn_t mace_interrupt(int irq, void *dev_id)
+{
+    struct net_device *dev = (struct net_device *) dev_id;
+    struct mace_data *mp = netdev_priv(dev);
+    volatile struct mace __iomem *mb = mp->mace;
+    volatile struct dbdma_regs __iomem *td = mp->tx_dma;
+    volatile struct dbdma_cmd *cp;
+    int intr, fs, i, stat, x;
+    int xcount, dstat;
+    unsigned long flags;
+    /* static int mace_last_fs, mace_last_xcount; */
+
+    spin_lock_irqsave(&mp->lock, flags);
+    intr = in_8(&mb->ir);		/* read interrupt register */
+    in_8(&mb->xmtrc);			/* get retries */
+    mace_handle_misc_intrs(mp, intr, dev);
+
+    i = mp->tx_empty;
+    while (in_8(&mb->pr) & XMTSV) {
+	del_timer(&mp->tx_timeout);
+	mp->timeout_active = 0;
+	/*
+	 * Clear any interrupt indication associated with this status
+	 * word.  This appears to unlatch any error indication from
+	 * the DMA controller.
+	 */
+	intr = in_8(&mb->ir);
+	if (intr != 0)
+	    mace_handle_misc_intrs(mp, intr, dev);
+	if (mp->tx_bad_runt) {
+	    fs = in_8(&mb->xmtfs);
+	    mp->tx_bad_runt = 0;
+	    out_8(&mb->xmtfc, AUTO_PAD_XMIT);
+	    continue;
+	}
+	dstat = ld_le32(&td->status);
+	/* stop DMA controller */
+	out_le32(&td->control, RUN << 16);
+	/*
+	 * xcount is the number of complete frames which have been
+	 * written to the fifo but for which status has not been read.
+	 */
+	xcount = (in_8(&mb->fifofc) >> XMTFC_SH) & XMTFC_MASK;
+	if (xcount == 0 || (dstat & DEAD)) {
+	    /*
+	     * If a packet was aborted before the DMA controller has
+	     * finished transferring it, it seems that there are 2 bytes
+	     * which are stuck in some buffer somewhere.  These will get
+	     * transmitted as soon as we read the frame status (which
+	     * reenables the transmit data transfer request).  Turning
+	     * off the DMA controller and/or resetting the MACE doesn't
+	     * help.  So we disable auto-padding and FCS transmission
+	     * so the two bytes will only be a runt packet which should
+	     * be ignored by other stations.
+	     */
+	    out_8(&mb->xmtfc, DXMTFCS);
+	}
+	fs = in_8(&mb->xmtfs);
+	if ((fs & XMTSV) == 0) {
+	    printk(KERN_ERR "mace: xmtfs not valid! (fs=%x xc=%d ds=%x)\n",
+		   fs, xcount, dstat);
+	    mace_reset(dev);
+		/*
+		 * XXX mace likes to hang the machine after a xmtfs error.
+		 * This is hard to reproduce, reseting *may* help
+		 */
+	}
+	cp = mp->tx_cmds + NCMDS_TX * i;
+	stat = ld_le16(&cp->xfer_status);
+	if ((fs & (UFLO|LCOL|LCAR|RTRY)) || (dstat & DEAD) || xcount == 0) {
+	    /*
+	     * Check whether there were in fact 2 bytes written to
+	     * the transmit FIFO.
+	     */
+	    udelay(1);
+	    x = (in_8(&mb->fifofc) >> XMTFC_SH) & XMTFC_MASK;
+	    if (x != 0) {
+		/* there were two bytes with an end-of-packet indication */
+		mp->tx_bad_runt = 1;
+		mace_set_timeout(dev);
+	    } else {
+		/*
+		 * Either there weren't the two bytes buffered up, or they
+		 * didn't have an end-of-packet indication.
+		 * We flush the transmit FIFO just in case (by setting the
+		 * XMTFWU bit with the transmitter disabled).
+		 */
+		out_8(&mb->maccc, in_8(&mb->maccc) & ~ENXMT);
+		out_8(&mb->fifocc, in_8(&mb->fifocc) | XMTFWU);
+		udelay(1);
+		out_8(&mb->maccc, in_8(&mb->maccc) | ENXMT);
+		out_8(&mb->xmtfc, AUTO_PAD_XMIT);
+	    }
+	}
+	/* dma should have finished */
+	if (i == mp->tx_fill) {
+	    printk(KERN_DEBUG "mace: tx ring ran out? (fs=%x xc=%d ds=%x)\n",
+		   fs, xcount, dstat);
+	    continue;
+	}
+	/* Update stats */
+	if (fs & (UFLO|LCOL|LCAR|RTRY)) {
+	    ++dev->stats.tx_errors;
+	    if (fs & LCAR)
+		++dev->stats.tx_carrier_errors;
+	    if (fs & (UFLO|LCOL|RTRY))
+		++dev->stats.tx_aborted_errors;
+	} else {
+	    dev->stats.tx_bytes += mp->tx_bufs[i]->len;
+	    ++dev->stats.tx_packets;
+	}
+	dev_kfree_skb_irq(mp->tx_bufs[i]);
+	--mp->tx_active;
+	if (++i >= N_TX_RING)
+	    i = 0;
+#if 0
+	mace_last_fs = fs;
+	mace_last_xcount = xcount;
+#endif
+    }
+
+    if (i != mp->tx_empty) {
+	mp->tx_fullup = 0;
+	netif_wake_queue(dev);
+    }
+    mp->tx_empty = i;
+    i += mp->tx_active;
+    if (i >= N_TX_RING)
+	i -= N_TX_RING;
+    if (!mp->tx_bad_runt && i != mp->tx_fill && mp->tx_active < MAX_TX_ACTIVE) {
+	do {
+	    /* set up the next one */
+	    cp = mp->tx_cmds + NCMDS_TX * i;
+	    out_le16(&cp->xfer_status, 0);
+	    out_le16(&cp->command, OUTPUT_LAST);
+	    ++mp->tx_active;
+	    if (++i >= N_TX_RING)
+		i = 0;
+	} while (i != mp->tx_fill && mp->tx_active < MAX_TX_ACTIVE);
+	out_le32(&td->control, ((RUN|WAKE) << 16) + (RUN|WAKE));
+	mace_set_timeout(dev);
+    }
+    spin_unlock_irqrestore(&mp->lock, flags);
+    return IRQ_HANDLED;
+}
+
+static void mace_tx_timeout(unsigned long data)
+{
+    struct net_device *dev = (struct net_device *) data;
+    struct mace_data *mp = netdev_priv(dev);
+    volatile struct mace __iomem *mb = mp->mace;
+    volatile struct dbdma_regs __iomem *td = mp->tx_dma;
+    volatile struct dbdma_regs __iomem *rd = mp->rx_dma;
+    volatile struct dbdma_cmd *cp;
+    unsigned long flags;
+    int i;
+
+    spin_lock_irqsave(&mp->lock, flags);
+    mp->timeout_active = 0;
+    if (mp->tx_active == 0 && !mp->tx_bad_runt)
+	goto out;
+
+    /* update various counters */
+    mace_handle_misc_intrs(mp, in_8(&mb->ir), dev);
+
+    cp = mp->tx_cmds + NCMDS_TX * mp->tx_empty;
+
+    /* turn off both tx and rx and reset the chip */
+    out_8(&mb->maccc, 0);
+    printk(KERN_ERR "mace: transmit timeout - resetting\n");
+    dbdma_reset(td);
+    mace_reset(dev);
+
+    /* restart rx dma */
+    cp = bus_to_virt(ld_le32(&rd->cmdptr));
+    dbdma_reset(rd);
+    out_le16(&cp->xfer_status, 0);
+    out_le32(&rd->cmdptr, virt_to_bus(cp));
+    out_le32(&rd->control, (RUN << 16) | RUN);
+
+    /* fix up the transmit side */
+    i = mp->tx_empty;
+    mp->tx_active = 0;
+    ++dev->stats.tx_errors;
+    if (mp->tx_bad_runt) {
+	mp->tx_bad_runt = 0;
+    } else if (i != mp->tx_fill) {
+	dev_kfree_skb(mp->tx_bufs[i]);
+	if (++i >= N_TX_RING)
+	    i = 0;
+	mp->tx_empty = i;
+    }
+    mp->tx_fullup = 0;
+    netif_wake_queue(dev);
+    if (i != mp->tx_fill) {
+	cp = mp->tx_cmds + NCMDS_TX * i;
+	out_le16(&cp->xfer_status, 0);
+	out_le16(&cp->command, OUTPUT_LAST);
+	out_le32(&td->cmdptr, virt_to_bus(cp));
+	out_le32(&td->control, (RUN << 16) | RUN);
+	++mp->tx_active;
+	mace_set_timeout(dev);
+    }
+
+    /* turn it back on */
+    out_8(&mb->imr, RCVINT);
+    out_8(&mb->maccc, mp->maccc);
+
+out:
+    spin_unlock_irqrestore(&mp->lock, flags);
+}
+
+static irqreturn_t mace_txdma_intr(int irq, void *dev_id)
+{
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t mace_rxdma_intr(int irq, void *dev_id)
+{
+    struct net_device *dev = (struct net_device *) dev_id;
+    struct mace_data *mp = netdev_priv(dev);
+    volatile struct dbdma_regs __iomem *rd = mp->rx_dma;
+    volatile struct dbdma_cmd *cp, *np;
+    int i, nb, stat, next;
+    struct sk_buff *skb;
+    unsigned frame_status;
+    static int mace_lost_status;
+    unsigned char *data;
+    unsigned long flags;
+
+    spin_lock_irqsave(&mp->lock, flags);
+    for (i = mp->rx_empty; i != mp->rx_fill; ) {
+	cp = mp->rx_cmds + i;
+	stat = ld_le16(&cp->xfer_status);
+	if ((stat & ACTIVE) == 0) {
+	    next = i + 1;
+	    if (next >= N_RX_RING)
+		next = 0;
+	    np = mp->rx_cmds + next;
+	    if (next != mp->rx_fill &&
+		(ld_le16(&np->xfer_status) & ACTIVE) != 0) {
+		printk(KERN_DEBUG "mace: lost a status word\n");
+		++mace_lost_status;
+	    } else
+		break;
+	}
+	nb = ld_le16(&cp->req_count) - ld_le16(&cp->res_count);
+	out_le16(&cp->command, DBDMA_STOP);
+	/* got a packet, have a look at it */
+	skb = mp->rx_bufs[i];
+	if (!skb) {
+	    ++dev->stats.rx_dropped;
+	} else if (nb > 8) {
+	    data = skb->data;
+	    frame_status = (data[nb-3] << 8) + data[nb-4];
+	    if (frame_status & (RS_OFLO|RS_CLSN|RS_FRAMERR|RS_FCSERR)) {
+		++dev->stats.rx_errors;
+		if (frame_status & RS_OFLO)
+		    ++dev->stats.rx_over_errors;
+		if (frame_status & RS_FRAMERR)
+		    ++dev->stats.rx_frame_errors;
+		if (frame_status & RS_FCSERR)
+		    ++dev->stats.rx_crc_errors;
+	    } else {
+		/* Mace feature AUTO_STRIP_RCV is on by default, dropping the
+		 * FCS on frames with 802.3 headers. This means that Ethernet
+		 * frames have 8 extra octets at the end, while 802.3 frames
+		 * have only 4. We need to correctly account for this. */
+		if (*(unsigned short *)(data+12) < 1536) /* 802.3 header */
+		    nb -= 4;
+		else	/* Ethernet header; mace includes FCS */
+		    nb -= 8;
+		skb_put(skb, nb);
+		skb->protocol = eth_type_trans(skb, dev);
+		dev->stats.rx_bytes += skb->len;
+		netif_rx(skb);
+		mp->rx_bufs[i] = NULL;
+		++dev->stats.rx_packets;
+	    }
+	} else {
+	    ++dev->stats.rx_errors;
+	    ++dev->stats.rx_length_errors;
+	}
+
+	/* advance to next */
+	if (++i >= N_RX_RING)
+	    i = 0;
+    }
+    mp->rx_empty = i;
+
+    i = mp->rx_fill;
+    for (;;) {
+	next = i + 1;
+	if (next >= N_RX_RING)
+	    next = 0;
+	if (next == mp->rx_empty)
+	    break;
+	cp = mp->rx_cmds + i;
+	skb = mp->rx_bufs[i];
+	if (!skb) {
+	    skb = dev_alloc_skb(RX_BUFLEN + 2);
+	    if (skb) {
+		skb_reserve(skb, 2);
+		mp->rx_bufs[i] = skb;
+	    }
+	}
+	st_le16(&cp->req_count, RX_BUFLEN);
+	data = skb? skb->data: dummy_buf;
+	st_le32(&cp->phy_addr, virt_to_bus(data));
+	out_le16(&cp->xfer_status, 0);
+	out_le16(&cp->command, INPUT_LAST + INTR_ALWAYS);
+#if 0
+	if ((ld_le32(&rd->status) & ACTIVE) != 0) {
+	    out_le32(&rd->control, (PAUSE << 16) | PAUSE);
+	    while ((in_le32(&rd->status) & ACTIVE) != 0)
+		;
+	}
+#endif
+	i = next;
+    }
+    if (i != mp->rx_fill) {
+	out_le32(&rd->control, ((RUN|WAKE) << 16) | (RUN|WAKE));
+	mp->rx_fill = i;
+    }
+    spin_unlock_irqrestore(&mp->lock, flags);
+    return IRQ_HANDLED;
+}
+
+static struct of_device_id mace_match[] =
+{
+	{
+	.name 		= "mace",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE (of, mace_match);
+
+static struct macio_driver mace_driver =
+{
+	.driver = {
+		.name 		= "mace",
+		.owner		= THIS_MODULE,
+		.of_match_table	= mace_match,
+	},
+	.probe		= mace_probe,
+	.remove		= mace_remove,
+};
+
+
+static int __init mace_init(void)
+{
+	return macio_register_driver(&mace_driver);
+}
+
+static void __exit mace_cleanup(void)
+{
+	macio_unregister_driver(&mace_driver);
+
+	kfree(dummy_buf);
+	dummy_buf = NULL;
+}
+
+MODULE_AUTHOR("Paul Mackerras");
+MODULE_DESCRIPTION("PowerMac MACE driver.");
+module_param(port_aaui, int, 0);
+MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)");
+MODULE_LICENSE("GPL");
+
+module_init(mace_init);
+module_exit(mace_cleanup);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/apple/mace.h linux-libre-3.2-gnu/drivers/net/ethernet/apple/mace.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/apple/mace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/apple/mace.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,173 @@
+/*
+ * mace.h - definitions for the registers in the Am79C940 MACE
+ * (Medium Access Control for Ethernet) controller.
+ *
+ * Copyright (C) 1996 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.
+ */
+
+#define REG(x)	volatile unsigned char x; char x ## _pad[15]
+
+struct mace {
+	REG(rcvfifo);		/* receive FIFO */
+	REG(xmtfifo);		/* transmit FIFO */
+	REG(xmtfc);		/* transmit frame control */
+	REG(xmtfs);		/* transmit frame status */
+	REG(xmtrc);		/* transmit retry count */
+	REG(rcvfc);		/* receive frame control */
+	REG(rcvfs);		/* receive frame status (4 bytes) */
+	REG(fifofc);		/* FIFO frame count */
+	REG(ir);		/* interrupt register */
+	REG(imr);		/* interrupt mask register */
+	REG(pr);		/* poll register */
+	REG(biucc);		/* bus interface unit config control */
+	REG(fifocc);		/* FIFO configuration control */
+	REG(maccc);		/* medium access control config control */
+	REG(plscc);		/* phys layer signalling config control */
+	REG(phycc);		/* physical configuration control */
+	REG(chipid_lo);		/* chip ID, lsb */
+	REG(chipid_hi);		/* chip ID, msb */
+	REG(iac);		/* internal address config */
+	REG(reg19);
+	REG(ladrf);		/* logical address filter (8 bytes) */
+	REG(padr);		/* physical address (6 bytes) */
+	REG(reg22);
+	REG(reg23);
+	REG(mpc);		/* missed packet count (clears when read) */
+	REG(reg25);
+	REG(rntpc);		/* runt packet count (clears when read) */
+	REG(rcvcc);		/* recv collision count (clears when read) */
+	REG(reg28);
+	REG(utr);		/* user test reg */
+	REG(reg30);
+	REG(reg31);
+};
+
+/* Bits in XMTFC */
+#define DRTRY		0x80	/* don't retry transmission after collision */
+#define DXMTFCS		0x08	/* don't append FCS to transmitted frame */
+#define AUTO_PAD_XMIT	0x01	/* auto-pad short packets on transmission */
+
+/* Bits in XMTFS: only valid when XMTSV is set in PR and XMTFS */
+#define XMTSV		0x80	/* transmit status (i.e. XMTFS) valid */
+#define UFLO		0x40	/* underflow - xmit fifo ran dry */
+#define LCOL		0x20	/* late collision (transmission aborted) */
+#define MORE		0x10	/* 2 or more retries needed to xmit frame */
+#define ONE		0x08	/* 1 retry needed to xmit frame */
+#define DEFER		0x04	/* MACE had to defer xmission (enet busy) */
+#define LCAR		0x02	/* loss of carrier (transmission aborted) */
+#define RTRY		0x01	/* too many retries (transmission aborted) */
+
+/* Bits in XMTRC: only valid when XMTSV is set in PR (and XMTFS) */
+#define EXDEF		0x80	/* had to defer for excessive time */
+#define RETRY_MASK	0x0f	/* number of retries (0 - 15) */
+
+/* Bits in RCVFC */
+#define LLRCV		0x08	/* low latency receive: early DMA request */
+#define M_RBAR		0x04	/* sets function of EAM/R pin */
+#define AUTO_STRIP_RCV	0x01	/* auto-strip short LLC frames on recv */
+
+/*
+ * Bits in RCVFS.  After a frame is received, four bytes of status
+ * are automatically read from this register and appended to the frame
+ * data in memory.  These are:
+ * Byte 0 and 1: message byte count and frame status
+ * Byte 2: runt packet count
+ * Byte 3: receive collision count
+ */
+#define RS_OFLO		0x8000	/* receive FIFO overflowed */
+#define RS_CLSN		0x4000	/* received frame suffered (late) collision */
+#define RS_FRAMERR	0x2000	/* framing error flag */
+#define RS_FCSERR	0x1000	/* frame had FCS error */
+#define RS_COUNT	0x0fff	/* mask for byte count field */
+
+/* Bits (fields) in FIFOFC */
+#define RCVFC_SH	4	/* receive frame count in FIFO */
+#define RCVFC_MASK	0x0f
+#define XMTFC_SH	0	/* transmit frame count in FIFO */
+#define XMTFC_MASK	0x0f
+
+/*
+ * Bits in IR and IMR.  The IR clears itself when read.
+ * Setting a bit in the IMR will disable the corresponding interrupt.
+ */
+#define JABBER		0x80	/* jabber error - 10baseT xmission too long */
+#define BABBLE		0x40	/* babble - xmitter xmitting for too long */
+#define CERR		0x20	/* collision err - no SQE test (heartbeat) */
+#define RCVCCO		0x10	/* RCVCC overflow */
+#define RNTPCO		0x08	/* RNTPC overflow */
+#define MPCO		0x04	/* MPC overflow */
+#define RCVINT		0x02	/* receive interrupt */
+#define XMTINT		0x01	/* transmitter interrupt */
+
+/* Bits in PR */
+#define XMTSV		0x80	/* XMTFS valid (same as in XMTFS) */
+#define TDTREQ		0x40	/* set when xmit fifo is requesting data */
+#define RDTREQ		0x20	/* set when recv fifo requests data xfer */
+
+/* Bits in BIUCC */
+#define BSWP		0x40	/* byte swap, i.e. big-endian bus */
+#define XMTSP_4		0x00	/* start xmitting when 4 bytes in FIFO */
+#define XMTSP_16	0x10	/* start xmitting when 16 bytes in FIFO */
+#define XMTSP_64	0x20	/* start xmitting when 64 bytes in FIFO */
+#define XMTSP_112	0x30	/* start xmitting when 112 bytes in FIFO */
+#define SWRST		0x01	/* software reset */
+
+/* Bits in FIFOCC */
+#define XMTFW_8		0x00	/* xmit fifo watermark = 8 words free */
+#define XMTFW_16	0x40	/*  16 words free */
+#define XMTFW_32	0x80	/*  32 words free */
+#define RCVFW_16	0x00	/* recv fifo watermark = 16 bytes avail */
+#define RCVFW_32	0x10	/*  32 bytes avail */
+#define RCVFW_64	0x20	/*  64 bytes avail */
+#define XMTFWU		0x08	/* xmit fifo watermark update enable */
+#define RCVFWU		0x04	/* recv fifo watermark update enable */
+#define XMTBRST		0x02	/* enable transmit burst mode */
+#define RCVBRST		0x01	/* enable receive burst mode */
+
+/* Bits in MACCC */
+#define PROM		0x80	/* promiscuous mode */
+#define DXMT2PD		0x40	/* disable xmit two-part deferral algorithm */
+#define EMBA		0x20	/* enable modified backoff algorithm */
+#define DRCVPA		0x08	/* disable receiving physical address */
+#define DRCVBC		0x04	/* disable receiving broadcasts */
+#define ENXMT		0x02	/* enable transmitter */
+#define ENRCV		0x01	/* enable receiver */
+
+/* Bits in PLSCC */
+#define XMTSEL		0x08	/* select DO+/DO- state when idle */
+#define PORTSEL_AUI	0x00	/* select AUI port */
+#define PORTSEL_10T	0x02	/* select 10Base-T port */
+#define PORTSEL_DAI	0x04	/* select DAI port */
+#define PORTSEL_GPSI	0x06	/* select GPSI port */
+#define ENPLSIO		0x01	/* enable optional PLS I/O pins */
+
+/* Bits in PHYCC */
+#define LNKFL		0x80	/* reports 10Base-T link failure */
+#define DLNKTST		0x40	/* disable 10Base-T link test */
+#define REVPOL		0x20	/* 10Base-T receiver polarity reversed */
+#define DAPC		0x10	/* disable auto receiver polarity correction */
+#define LRT		0x08	/* low receive threshold for long links */
+#define ASEL		0x04	/* auto-select AUI or 10Base-T port */
+#define RWAKE		0x02	/* remote wake function */
+#define AWAKE		0x01	/* auto wake function */
+
+/* Bits in IAC */
+#define ADDRCHG		0x80	/* request address change */
+#define PHYADDR		0x04	/* access physical address */
+#define LOGADDR		0x02	/* access multicast filter */
+
+/* Bits in UTR */
+#define RTRE		0x80	/* reserved test register enable. DON'T SET. */
+#define RTRD		0x40	/* reserved test register disable.  Sticky */
+#define RPAC		0x20	/* accept runt packets */
+#define FCOLL		0x10	/* force collision */
+#define RCVFCSE		0x08	/* receive FCS enable */
+#define LOOP_NONE	0x00	/* no loopback */
+#define LOOP_EXT	0x02	/* external loopback */
+#define LOOP_INT	0x04	/* internal loopback, excludes MENDEC */
+#define LOOP_MENDEC	0x06	/* internal loopback, includes MENDEC */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/apple/macmace.c linux-libre-3.2-gnu/drivers/net/ethernet/apple/macmace.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/apple/macmace.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/apple/macmace.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,792 @@
+/*
+ *	Driver for the Macintosh 68K onboard MACE controller with PSC
+ *	driven DMA. The MACE driver code is derived from mace.c. The
+ *	Mac68k theory of operation is courtesy of the MacBSD wizards.
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ *	Copyright (C) 1996 Paul Mackerras.
+ *	Copyright (C) 1998 Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ *	Modified heavily by Joshua M. Thompson based on Dave Huang's NetBSD driver
+ *
+ *	Copyright (C) 2007 Finn Thain
+ *
+ *	Converted to DMA API, converted to unified driver model,
+ *	sync'd some routines with mace.c and fixed various bugs.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/crc32.h>
+#include <linux/bitrev.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/gfp.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <asm/macints.h>
+#include <asm/mac_psc.h>
+#include <asm/page.h>
+#include "mace.h"
+
+static char mac_mace_string[] = "macmace";
+
+#define N_TX_BUFF_ORDER	0
+#define N_TX_RING	(1 << N_TX_BUFF_ORDER)
+#define N_RX_BUFF_ORDER	3
+#define N_RX_RING	(1 << N_RX_BUFF_ORDER)
+
+#define TX_TIMEOUT	HZ
+
+#define MACE_BUFF_SIZE	0x800
+
+/* Chip rev needs workaround on HW & multicast addr change */
+#define BROKEN_ADDRCHG_REV	0x0941
+
+/* The MACE is simply wired down on a Mac68K box */
+
+#define MACE_BASE	(void *)(0x50F1C000)
+#define MACE_PROM	(void *)(0x50F08001)
+
+struct mace_data {
+	volatile struct mace *mace;
+	unsigned char *tx_ring;
+	dma_addr_t tx_ring_phys;
+	unsigned char *rx_ring;
+	dma_addr_t rx_ring_phys;
+	int dma_intr;
+	int rx_slot, rx_tail;
+	int tx_slot, tx_sloti, tx_count;
+	int chipid;
+	struct device *device;
+};
+
+struct mace_frame {
+	u8	rcvcnt;
+	u8	pad1;
+	u8	rcvsts;
+	u8	pad2;
+	u8	rntpc;
+	u8	pad3;
+	u8	rcvcc;
+	u8	pad4;
+	u32	pad5;
+	u32	pad6;
+	u8	data[1];
+	/* And frame continues.. */
+};
+
+#define PRIV_BYTES	sizeof(struct mace_data)
+
+static int mace_open(struct net_device *dev);
+static int mace_close(struct net_device *dev);
+static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
+static void mace_set_multicast(struct net_device *dev);
+static int mace_set_address(struct net_device *dev, void *addr);
+static void mace_reset(struct net_device *dev);
+static irqreturn_t mace_interrupt(int irq, void *dev_id);
+static irqreturn_t mace_dma_intr(int irq, void *dev_id);
+static void mace_tx_timeout(struct net_device *dev);
+static void __mace_set_address(struct net_device *dev, void *addr);
+
+/*
+ * Load a receive DMA channel with a base address and ring length
+ */
+
+static void mace_load_rxdma_base(struct net_device *dev, int set)
+{
+	struct mace_data *mp = netdev_priv(dev);
+
+	psc_write_word(PSC_ENETRD_CMD + set, 0x0100);
+	psc_write_long(PSC_ENETRD_ADDR + set, (u32) mp->rx_ring_phys);
+	psc_write_long(PSC_ENETRD_LEN + set, N_RX_RING);
+	psc_write_word(PSC_ENETRD_CMD + set, 0x9800);
+	mp->rx_tail = 0;
+}
+
+/*
+ * Reset the receive DMA subsystem
+ */
+
+static void mace_rxdma_reset(struct net_device *dev)
+{
+	struct mace_data *mp = netdev_priv(dev);
+	volatile struct mace *mace = mp->mace;
+	u8 maccc = mace->maccc;
+
+	mace->maccc = maccc & ~ENRCV;
+
+	psc_write_word(PSC_ENETRD_CTL, 0x8800);
+	mace_load_rxdma_base(dev, 0x00);
+	psc_write_word(PSC_ENETRD_CTL, 0x0400);
+
+	psc_write_word(PSC_ENETRD_CTL, 0x8800);
+	mace_load_rxdma_base(dev, 0x10);
+	psc_write_word(PSC_ENETRD_CTL, 0x0400);
+
+	mace->maccc = maccc;
+	mp->rx_slot = 0;
+
+	psc_write_word(PSC_ENETRD_CMD + PSC_SET0, 0x9800);
+	psc_write_word(PSC_ENETRD_CMD + PSC_SET1, 0x9800);
+}
+
+/*
+ * Reset the transmit DMA subsystem
+ */
+
+static void mace_txdma_reset(struct net_device *dev)
+{
+	struct mace_data *mp = netdev_priv(dev);
+	volatile struct mace *mace = mp->mace;
+	u8 maccc;
+
+	psc_write_word(PSC_ENETWR_CTL, 0x8800);
+
+	maccc = mace->maccc;
+	mace->maccc = maccc & ~ENXMT;
+
+	mp->tx_slot = mp->tx_sloti = 0;
+	mp->tx_count = N_TX_RING;
+
+	psc_write_word(PSC_ENETWR_CTL, 0x0400);
+	mace->maccc = maccc;
+}
+
+/*
+ * Disable DMA
+ */
+
+static void mace_dma_off(struct net_device *dev)
+{
+	psc_write_word(PSC_ENETRD_CTL, 0x8800);
+	psc_write_word(PSC_ENETRD_CTL, 0x1000);
+	psc_write_word(PSC_ENETRD_CMD + PSC_SET0, 0x1100);
+	psc_write_word(PSC_ENETRD_CMD + PSC_SET1, 0x1100);
+
+	psc_write_word(PSC_ENETWR_CTL, 0x8800);
+	psc_write_word(PSC_ENETWR_CTL, 0x1000);
+	psc_write_word(PSC_ENETWR_CMD + PSC_SET0, 0x1100);
+	psc_write_word(PSC_ENETWR_CMD + PSC_SET1, 0x1100);
+}
+
+static const struct net_device_ops mace_netdev_ops = {
+	.ndo_open		= mace_open,
+	.ndo_stop		= mace_close,
+	.ndo_start_xmit		= mace_xmit_start,
+	.ndo_tx_timeout		= mace_tx_timeout,
+	.ndo_set_rx_mode	= mace_set_multicast,
+	.ndo_set_mac_address	= mace_set_address,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+/*
+ * Not really much of a probe. The hardware table tells us if this
+ * model of Macintrash has a MACE (AV macintoshes)
+ */
+
+static int __devinit mace_probe(struct platform_device *pdev)
+{
+	int j;
+	struct mace_data *mp;
+	unsigned char *addr;
+	struct net_device *dev;
+	unsigned char checksum = 0;
+	int err;
+
+	dev = alloc_etherdev(PRIV_BYTES);
+	if (!dev)
+		return -ENOMEM;
+
+	mp = netdev_priv(dev);
+
+	mp->device = &pdev->dev;
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	dev->base_addr = (u32)MACE_BASE;
+	mp->mace = MACE_BASE;
+
+	dev->irq = IRQ_MAC_MACE;
+	mp->dma_intr = IRQ_MAC_MACE_DMA;
+
+	mp->chipid = mp->mace->chipid_hi << 8 | mp->mace->chipid_lo;
+
+	/*
+	 * The PROM contains 8 bytes which total 0xFF when XOR'd
+	 * together. Due to the usual peculiar apple brain damage
+	 * the bytes are spaced out in a strange boundary and the
+	 * bits are reversed.
+	 */
+
+	addr = (void *)MACE_PROM;
+
+	for (j = 0; j < 6; ++j) {
+		u8 v = bitrev8(addr[j<<4]);
+		checksum ^= v;
+		dev->dev_addr[j] = v;
+	}
+	for (; j < 8; ++j) {
+		checksum ^= bitrev8(addr[j<<4]);
+	}
+
+	if (checksum != 0xFF) {
+		free_netdev(dev);
+		return -ENODEV;
+	}
+
+	dev->netdev_ops		= &mace_netdev_ops;
+	dev->watchdog_timeo	= TX_TIMEOUT;
+
+	printk(KERN_INFO "%s: 68K MACE, hardware address %pM\n",
+	       dev->name, dev->dev_addr);
+
+	err = register_netdev(dev);
+	if (!err)
+		return 0;
+
+	free_netdev(dev);
+	return err;
+}
+
+/*
+ * Reset the chip.
+ */
+
+static void mace_reset(struct net_device *dev)
+{
+	struct mace_data *mp = netdev_priv(dev);
+	volatile struct mace *mb = mp->mace;
+	int i;
+
+	/* soft-reset the chip */
+	i = 200;
+	while (--i) {
+		mb->biucc = SWRST;
+		if (mb->biucc & SWRST) {
+			udelay(10);
+			continue;
+		}
+		break;
+	}
+	if (!i) {
+		printk(KERN_ERR "macmace: cannot reset chip!\n");
+		return;
+	}
+
+	mb->maccc = 0;	/* turn off tx, rx */
+	mb->imr = 0xFF;	/* disable all intrs for now */
+	i = mb->ir;
+
+	mb->biucc = XMTSP_64;
+	mb->utr = RTRD;
+	mb->fifocc = XMTFW_8 | RCVFW_64 | XMTFWU | RCVFWU;
+
+	mb->xmtfc = AUTO_PAD_XMIT; /* auto-pad short frames */
+	mb->rcvfc = 0;
+
+	/* load up the hardware address */
+	__mace_set_address(dev, dev->dev_addr);
+
+	/* clear the multicast filter */
+	if (mp->chipid == BROKEN_ADDRCHG_REV)
+		mb->iac = LOGADDR;
+	else {
+		mb->iac = ADDRCHG | LOGADDR;
+		while ((mb->iac & ADDRCHG) != 0)
+			;
+	}
+	for (i = 0; i < 8; ++i)
+		mb->ladrf = 0;
+
+	/* done changing address */
+	if (mp->chipid != BROKEN_ADDRCHG_REV)
+		mb->iac = 0;
+
+	mb->plscc = PORTSEL_AUI;
+}
+
+/*
+ * Load the address on a mace controller.
+ */
+
+static void __mace_set_address(struct net_device *dev, void *addr)
+{
+	struct mace_data *mp = netdev_priv(dev);
+	volatile struct mace *mb = mp->mace;
+	unsigned char *p = addr;
+	int i;
+
+	/* load up the hardware address */
+	if (mp->chipid == BROKEN_ADDRCHG_REV)
+		mb->iac = PHYADDR;
+	else {
+		mb->iac = ADDRCHG | PHYADDR;
+		while ((mb->iac & ADDRCHG) != 0)
+			;
+	}
+	for (i = 0; i < 6; ++i)
+		mb->padr = dev->dev_addr[i] = p[i];
+	if (mp->chipid != BROKEN_ADDRCHG_REV)
+		mb->iac = 0;
+}
+
+static int mace_set_address(struct net_device *dev, void *addr)
+{
+	struct mace_data *mp = netdev_priv(dev);
+	volatile struct mace *mb = mp->mace;
+	unsigned long flags;
+	u8 maccc;
+
+	local_irq_save(flags);
+
+	maccc = mb->maccc;
+
+	__mace_set_address(dev, addr);
+
+	mb->maccc = maccc;
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+/*
+ * Open the Macintosh MACE. Most of this is playing with the DMA
+ * engine. The ethernet chip is quite friendly.
+ */
+
+static int mace_open(struct net_device *dev)
+{
+	struct mace_data *mp = netdev_priv(dev);
+	volatile struct mace *mb = mp->mace;
+
+	/* reset the chip */
+	mace_reset(dev);
+
+	if (request_irq(dev->irq, mace_interrupt, 0, dev->name, dev)) {
+		printk(KERN_ERR "%s: can't get irq %d\n", dev->name, dev->irq);
+		return -EAGAIN;
+	}
+	if (request_irq(mp->dma_intr, mace_dma_intr, 0, dev->name, dev)) {
+		printk(KERN_ERR "%s: can't get irq %d\n", dev->name, mp->dma_intr);
+		free_irq(dev->irq, dev);
+		return -EAGAIN;
+	}
+
+	/* Allocate the DMA ring buffers */
+
+	mp->tx_ring = dma_alloc_coherent(mp->device,
+			N_TX_RING * MACE_BUFF_SIZE,
+			&mp->tx_ring_phys, GFP_KERNEL);
+	if (mp->tx_ring == NULL) {
+		printk(KERN_ERR "%s: unable to allocate DMA tx buffers\n", dev->name);
+		goto out1;
+	}
+
+	mp->rx_ring = dma_alloc_coherent(mp->device,
+			N_RX_RING * MACE_BUFF_SIZE,
+			&mp->rx_ring_phys, GFP_KERNEL);
+	if (mp->rx_ring == NULL) {
+		printk(KERN_ERR "%s: unable to allocate DMA rx buffers\n", dev->name);
+		goto out2;
+	}
+
+	mace_dma_off(dev);
+
+	/* Not sure what these do */
+
+	psc_write_word(PSC_ENETWR_CTL, 0x9000);
+	psc_write_word(PSC_ENETRD_CTL, 0x9000);
+	psc_write_word(PSC_ENETWR_CTL, 0x0400);
+	psc_write_word(PSC_ENETRD_CTL, 0x0400);
+
+	mace_rxdma_reset(dev);
+	mace_txdma_reset(dev);
+
+	/* turn it on! */
+	mb->maccc = ENXMT | ENRCV;
+	/* enable all interrupts except receive interrupts */
+	mb->imr = RCVINT;
+	return 0;
+
+out2:
+	dma_free_coherent(mp->device, N_TX_RING * MACE_BUFF_SIZE,
+	                  mp->tx_ring, mp->tx_ring_phys);
+out1:
+	free_irq(dev->irq, dev);
+	free_irq(mp->dma_intr, dev);
+	return -ENOMEM;
+}
+
+/*
+ * Shut down the mace and its interrupt channel
+ */
+
+static int mace_close(struct net_device *dev)
+{
+	struct mace_data *mp = netdev_priv(dev);
+	volatile struct mace *mb = mp->mace;
+
+	mb->maccc = 0;		/* disable rx and tx	 */
+	mb->imr = 0xFF;		/* disable all irqs	 */
+	mace_dma_off(dev);	/* disable rx and tx dma */
+
+	return 0;
+}
+
+/*
+ * Transmit a frame
+ */
+
+static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
+{
+	struct mace_data *mp = netdev_priv(dev);
+	unsigned long flags;
+
+	/* Stop the queue since there's only the one buffer */
+
+	local_irq_save(flags);
+	netif_stop_queue(dev);
+	if (!mp->tx_count) {
+		printk(KERN_ERR "macmace: tx queue running but no free buffers.\n");
+		local_irq_restore(flags);
+		return NETDEV_TX_BUSY;
+	}
+	mp->tx_count--;
+	local_irq_restore(flags);
+
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
+
+	/* We need to copy into our xmit buffer to take care of alignment and caching issues */
+	skb_copy_from_linear_data(skb, mp->tx_ring, skb->len);
+
+	/* load the Tx DMA and fire it off */
+
+	psc_write_long(PSC_ENETWR_ADDR + mp->tx_slot, (u32)  mp->tx_ring_phys);
+	psc_write_long(PSC_ENETWR_LEN + mp->tx_slot, skb->len);
+	psc_write_word(PSC_ENETWR_CMD + mp->tx_slot, 0x9800);
+
+	mp->tx_slot ^= 0x10;
+
+	dev_kfree_skb(skb);
+
+	return NETDEV_TX_OK;
+}
+
+static void mace_set_multicast(struct net_device *dev)
+{
+	struct mace_data *mp = netdev_priv(dev);
+	volatile struct mace *mb = mp->mace;
+	int i;
+	u32 crc;
+	u8 maccc;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	maccc = mb->maccc;
+	mb->maccc &= ~PROM;
+
+	if (dev->flags & IFF_PROMISC) {
+		mb->maccc |= PROM;
+	} else {
+		unsigned char multicast_filter[8];
+		struct netdev_hw_addr *ha;
+
+		if (dev->flags & IFF_ALLMULTI) {
+			for (i = 0; i < 8; i++) {
+				multicast_filter[i] = 0xFF;
+			}
+		} else {
+			for (i = 0; i < 8; i++)
+				multicast_filter[i] = 0;
+			netdev_for_each_mc_addr(ha, dev) {
+				crc = ether_crc_le(6, ha->addr);
+				/* bit number in multicast_filter */
+				i = crc >> 26;
+				multicast_filter[i >> 3] |= 1 << (i & 7);
+			}
+		}
+
+		if (mp->chipid == BROKEN_ADDRCHG_REV)
+			mb->iac = LOGADDR;
+		else {
+			mb->iac = ADDRCHG | LOGADDR;
+			while ((mb->iac & ADDRCHG) != 0)
+				;
+		}
+		for (i = 0; i < 8; ++i)
+			mb->ladrf = multicast_filter[i];
+		if (mp->chipid != BROKEN_ADDRCHG_REV)
+			mb->iac = 0;
+	}
+
+	mb->maccc = maccc;
+	local_irq_restore(flags);
+}
+
+static void mace_handle_misc_intrs(struct net_device *dev, int intr)
+{
+	struct mace_data *mp = netdev_priv(dev);
+	volatile struct mace *mb = mp->mace;
+	static int mace_babbles, mace_jabbers;
+
+	if (intr & MPCO)
+		dev->stats.rx_missed_errors += 256;
+	dev->stats.rx_missed_errors += mb->mpc;   /* reading clears it */
+	if (intr & RNTPCO)
+		dev->stats.rx_length_errors += 256;
+	dev->stats.rx_length_errors += mb->rntpc; /* reading clears it */
+	if (intr & CERR)
+		++dev->stats.tx_heartbeat_errors;
+	if (intr & BABBLE)
+		if (mace_babbles++ < 4)
+			printk(KERN_DEBUG "macmace: babbling transmitter\n");
+	if (intr & JABBER)
+		if (mace_jabbers++ < 4)
+			printk(KERN_DEBUG "macmace: jabbering transceiver\n");
+}
+
+static irqreturn_t mace_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct mace_data *mp = netdev_priv(dev);
+	volatile struct mace *mb = mp->mace;
+	int intr, fs;
+	unsigned long flags;
+
+	/* don't want the dma interrupt handler to fire */
+	local_irq_save(flags);
+
+	intr = mb->ir; /* read interrupt register */
+	mace_handle_misc_intrs(dev, intr);
+
+	if (intr & XMTINT) {
+		fs = mb->xmtfs;
+		if ((fs & XMTSV) == 0) {
+			printk(KERN_ERR "macmace: xmtfs not valid! (fs=%x)\n", fs);
+			mace_reset(dev);
+			/*
+			 * XXX mace likes to hang the machine after a xmtfs error.
+			 * This is hard to reproduce, reseting *may* help
+			 */
+		}
+		/* dma should have finished */
+		if (!mp->tx_count) {
+			printk(KERN_DEBUG "macmace: tx ring ran out? (fs=%x)\n", fs);
+		}
+		/* Update stats */
+		if (fs & (UFLO|LCOL|LCAR|RTRY)) {
+			++dev->stats.tx_errors;
+			if (fs & LCAR)
+				++dev->stats.tx_carrier_errors;
+			else if (fs & (UFLO|LCOL|RTRY)) {
+				++dev->stats.tx_aborted_errors;
+				if (mb->xmtfs & UFLO) {
+					printk(KERN_ERR "%s: DMA underrun.\n", dev->name);
+					dev->stats.tx_fifo_errors++;
+					mace_txdma_reset(dev);
+				}
+			}
+		}
+	}
+
+	if (mp->tx_count)
+		netif_wake_queue(dev);
+
+	local_irq_restore(flags);
+
+	return IRQ_HANDLED;
+}
+
+static void mace_tx_timeout(struct net_device *dev)
+{
+	struct mace_data *mp = netdev_priv(dev);
+	volatile struct mace *mb = mp->mace;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/* turn off both tx and rx and reset the chip */
+	mb->maccc = 0;
+	printk(KERN_ERR "macmace: transmit timeout - resetting\n");
+	mace_txdma_reset(dev);
+	mace_reset(dev);
+
+	/* restart rx dma */
+	mace_rxdma_reset(dev);
+
+	mp->tx_count = N_TX_RING;
+	netif_wake_queue(dev);
+
+	/* turn it on! */
+	mb->maccc = ENXMT | ENRCV;
+	/* enable all interrupts except receive interrupts */
+	mb->imr = RCVINT;
+
+	local_irq_restore(flags);
+}
+
+/*
+ * Handle a newly arrived frame
+ */
+
+static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf)
+{
+	struct sk_buff *skb;
+	unsigned int frame_status = mf->rcvsts;
+
+	if (frame_status & (RS_OFLO | RS_CLSN | RS_FRAMERR | RS_FCSERR)) {
+		dev->stats.rx_errors++;
+		if (frame_status & RS_OFLO) {
+			printk(KERN_DEBUG "%s: fifo overflow.\n", dev->name);
+			dev->stats.rx_fifo_errors++;
+		}
+		if (frame_status & RS_CLSN)
+			dev->stats.collisions++;
+		if (frame_status & RS_FRAMERR)
+			dev->stats.rx_frame_errors++;
+		if (frame_status & RS_FCSERR)
+			dev->stats.rx_crc_errors++;
+	} else {
+		unsigned int frame_length = mf->rcvcnt + ((frame_status & 0x0F) << 8 );
+
+		skb = dev_alloc_skb(frame_length + 2);
+		if (!skb) {
+			dev->stats.rx_dropped++;
+			return;
+		}
+		skb_reserve(skb, 2);
+		memcpy(skb_put(skb, frame_length), mf->data, frame_length);
+
+		skb->protocol = eth_type_trans(skb, dev);
+		netif_rx(skb);
+		dev->stats.rx_packets++;
+		dev->stats.rx_bytes += frame_length;
+	}
+}
+
+/*
+ * The PSC has passed us a DMA interrupt event.
+ */
+
+static irqreturn_t mace_dma_intr(int irq, void *dev_id)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct mace_data *mp = netdev_priv(dev);
+	int left, head;
+	u16 status;
+	u32 baka;
+
+	/* Not sure what this does */
+
+	while ((baka = psc_read_long(PSC_MYSTERY)) != psc_read_long(PSC_MYSTERY));
+	if (!(baka & 0x60000000)) return IRQ_NONE;
+
+	/*
+	 * Process the read queue
+	 */
+
+	status = psc_read_word(PSC_ENETRD_CTL);
+
+	if (status & 0x2000) {
+		mace_rxdma_reset(dev);
+	} else if (status & 0x0100) {
+		psc_write_word(PSC_ENETRD_CMD + mp->rx_slot, 0x1100);
+
+		left = psc_read_long(PSC_ENETRD_LEN + mp->rx_slot);
+		head = N_RX_RING - left;
+
+		/* Loop through the ring buffer and process new packages */
+
+		while (mp->rx_tail < head) {
+			mace_dma_rx_frame(dev, (struct mace_frame*) (mp->rx_ring
+				+ (mp->rx_tail * MACE_BUFF_SIZE)));
+			mp->rx_tail++;
+		}
+
+		/* If we're out of buffers in this ring then switch to */
+		/* the other set, otherwise just reactivate this one.  */
+
+		if (!left) {
+			mace_load_rxdma_base(dev, mp->rx_slot);
+			mp->rx_slot ^= 0x10;
+		} else {
+			psc_write_word(PSC_ENETRD_CMD + mp->rx_slot, 0x9800);
+		}
+	}
+
+	/*
+	 * Process the write queue
+	 */
+
+	status = psc_read_word(PSC_ENETWR_CTL);
+
+	if (status & 0x2000) {
+		mace_txdma_reset(dev);
+	} else if (status & 0x0100) {
+		psc_write_word(PSC_ENETWR_CMD + mp->tx_sloti, 0x0100);
+		mp->tx_sloti ^= 0x10;
+		mp->tx_count++;
+	}
+	return IRQ_HANDLED;
+}
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Macintosh MACE ethernet driver");
+MODULE_ALIAS("platform:macmace");
+
+static int __devexit mac_mace_device_remove (struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct mace_data *mp = netdev_priv(dev);
+
+	unregister_netdev(dev);
+
+	free_irq(dev->irq, dev);
+	free_irq(IRQ_MAC_MACE_DMA, dev);
+
+	dma_free_coherent(mp->device, N_RX_RING * MACE_BUFF_SIZE,
+	                  mp->rx_ring, mp->rx_ring_phys);
+	dma_free_coherent(mp->device, N_TX_RING * MACE_BUFF_SIZE,
+	                  mp->tx_ring, mp->tx_ring_phys);
+
+	free_netdev(dev);
+
+	return 0;
+}
+
+static struct platform_driver mac_mace_driver = {
+	.probe  = mace_probe,
+	.remove = __devexit_p(mac_mace_device_remove),
+	.driver	= {
+		.name	= mac_mace_string,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init mac_mace_init_module(void)
+{
+	if (!MACH_IS_MAC)
+		return -ENODEV;
+
+	return platform_driver_register(&mac_mace_driver);
+}
+
+static void __exit mac_mace_cleanup_module(void)
+{
+	platform_driver_unregister(&mac_mace_driver);
+}
+
+module_init(mac_mace_init_module);
+module_exit(mac_mace_cleanup_module);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/apple/Makefile linux-libre-3.2-gnu/drivers/net/ethernet/apple/Makefile
--- linux-libre-3.1-gnu/drivers/net/ethernet/apple/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/apple/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,7 @@
+#
+# Makefile for the Apple network device drivers.
+#
+
+obj-$(CONFIG_MACE) += mace.o
+obj-$(CONFIG_BMAC) += bmac.o
+obj-$(CONFIG_MACMACE) += macmace.o
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,311 @@
+/*
+ * Copyright(c) 2009 - 2009 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You 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/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/slab.h>
+
+#include "atl1c.h"
+
+static int atl1c_get_settings(struct net_device *netdev,
+			      struct ethtool_cmd *ecmd)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct atl1c_hw *hw = &adapter->hw;
+
+	ecmd->supported = (SUPPORTED_10baseT_Half  |
+			   SUPPORTED_10baseT_Full  |
+			   SUPPORTED_100baseT_Half |
+			   SUPPORTED_100baseT_Full |
+			   SUPPORTED_Autoneg       |
+			   SUPPORTED_TP);
+	if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M)
+		ecmd->supported |= SUPPORTED_1000baseT_Full;
+
+	ecmd->advertising = ADVERTISED_TP;
+
+	ecmd->advertising |= hw->autoneg_advertised;
+
+	ecmd->port = PORT_TP;
+	ecmd->phy_address = 0;
+	ecmd->transceiver = XCVR_INTERNAL;
+
+	if (adapter->link_speed != SPEED_0) {
+		ethtool_cmd_speed_set(ecmd, adapter->link_speed);
+		if (adapter->link_duplex == FULL_DUPLEX)
+			ecmd->duplex = DUPLEX_FULL;
+		else
+			ecmd->duplex = DUPLEX_HALF;
+	} else {
+		ethtool_cmd_speed_set(ecmd, -1);
+		ecmd->duplex = -1;
+	}
+
+	ecmd->autoneg = AUTONEG_ENABLE;
+	return 0;
+}
+
+static int atl1c_set_settings(struct net_device *netdev,
+			      struct ethtool_cmd *ecmd)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct atl1c_hw *hw = &adapter->hw;
+	u16  autoneg_advertised;
+
+	while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+		msleep(1);
+
+	if (ecmd->autoneg == AUTONEG_ENABLE) {
+		autoneg_advertised = ADVERTISED_Autoneg;
+	} else {
+		u32 speed = ethtool_cmd_speed(ecmd);
+		if (speed == SPEED_1000) {
+			if (ecmd->duplex != DUPLEX_FULL) {
+				if (netif_msg_link(adapter))
+					dev_warn(&adapter->pdev->dev,
+						"1000M half is invalid\n");
+				clear_bit(__AT_RESETTING, &adapter->flags);
+				return -EINVAL;
+			}
+			autoneg_advertised = ADVERTISED_1000baseT_Full;
+		} else if (speed == SPEED_100) {
+			if (ecmd->duplex == DUPLEX_FULL)
+				autoneg_advertised = ADVERTISED_100baseT_Full;
+			else
+				autoneg_advertised = ADVERTISED_100baseT_Half;
+		} else {
+			if (ecmd->duplex == DUPLEX_FULL)
+				autoneg_advertised = ADVERTISED_10baseT_Full;
+			else
+				autoneg_advertised = ADVERTISED_10baseT_Half;
+		}
+	}
+
+	if (hw->autoneg_advertised != autoneg_advertised) {
+		hw->autoneg_advertised = autoneg_advertised;
+		if (atl1c_restart_autoneg(hw) != 0) {
+			if (netif_msg_link(adapter))
+				dev_warn(&adapter->pdev->dev,
+					"ethtool speed/duplex setting failed\n");
+			clear_bit(__AT_RESETTING, &adapter->flags);
+			return -EINVAL;
+		}
+	}
+	clear_bit(__AT_RESETTING, &adapter->flags);
+	return 0;
+}
+
+static u32 atl1c_get_msglevel(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	return adapter->msg_enable;
+}
+
+static void atl1c_set_msglevel(struct net_device *netdev, u32 data)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	adapter->msg_enable = data;
+}
+
+static int atl1c_get_regs_len(struct net_device *netdev)
+{
+	return AT_REGS_LEN;
+}
+
+static void atl1c_get_regs(struct net_device *netdev,
+			   struct ethtool_regs *regs, void *p)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct atl1c_hw *hw = &adapter->hw;
+	u32 *regs_buff = p;
+	u16 phy_data;
+
+	memset(p, 0, AT_REGS_LEN);
+
+	regs->version = 0;
+	AT_READ_REG(hw, REG_VPD_CAP, 		  p++);
+	AT_READ_REG(hw, REG_PM_CTRL, 		  p++);
+	AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL,  p++);
+	AT_READ_REG(hw, REG_TWSI_CTRL, 		  p++);
+	AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL,   p++);
+	AT_READ_REG(hw, REG_MASTER_CTRL, 	  p++);
+	AT_READ_REG(hw, REG_MANUAL_TIMER_INIT,    p++);
+	AT_READ_REG(hw, REG_IRQ_MODRT_TIMER_INIT, p++);
+	AT_READ_REG(hw, REG_GPHY_CTRL, 		  p++);
+	AT_READ_REG(hw, REG_LINK_CTRL, 		  p++);
+	AT_READ_REG(hw, REG_IDLE_STATUS, 	  p++);
+	AT_READ_REG(hw, REG_MDIO_CTRL, 		  p++);
+	AT_READ_REG(hw, REG_SERDES_LOCK, 	  p++);
+	AT_READ_REG(hw, REG_MAC_CTRL, 		  p++);
+	AT_READ_REG(hw, REG_MAC_IPG_IFG, 	  p++);
+	AT_READ_REG(hw, REG_MAC_STA_ADDR, 	  p++);
+	AT_READ_REG(hw, REG_MAC_STA_ADDR+4, 	  p++);
+	AT_READ_REG(hw, REG_RX_HASH_TABLE, 	  p++);
+	AT_READ_REG(hw, REG_RX_HASH_TABLE+4, 	  p++);
+	AT_READ_REG(hw, REG_RXQ_CTRL, 		  p++);
+	AT_READ_REG(hw, REG_TXQ_CTRL, 		  p++);
+	AT_READ_REG(hw, REG_MTU, 		  p++);
+	AT_READ_REG(hw, REG_WOL_CTRL, 		  p++);
+
+	atl1c_read_phy_reg(hw, MII_BMCR, &phy_data);
+	regs_buff[73] =	(u32) phy_data;
+	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
+	regs_buff[74] = (u32) phy_data;
+}
+
+static int atl1c_get_eeprom_len(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	if (atl1c_check_eeprom_exist(&adapter->hw))
+		return AT_EEPROM_LEN;
+	else
+		return 0;
+}
+
+static int atl1c_get_eeprom(struct net_device *netdev,
+		struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct atl1c_hw *hw = &adapter->hw;
+	u32 *eeprom_buff;
+	int first_dword, last_dword;
+	int ret_val = 0;
+	int i;
+
+	if (eeprom->len == 0)
+		return -EINVAL;
+
+	if (!atl1c_check_eeprom_exist(hw)) /* not exist */
+		return -EINVAL;
+
+	eeprom->magic = adapter->pdev->vendor |
+			(adapter->pdev->device << 16);
+
+	first_dword = eeprom->offset >> 2;
+	last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
+
+	eeprom_buff = kmalloc(sizeof(u32) *
+			(last_dword - first_dword + 1), GFP_KERNEL);
+	if (eeprom_buff == NULL)
+		return -ENOMEM;
+
+	for (i = first_dword; i < last_dword; i++) {
+		if (!atl1c_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) {
+			kfree(eeprom_buff);
+			return -EIO;
+		}
+	}
+
+	memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3),
+			eeprom->len);
+	kfree(eeprom_buff);
+
+	return ret_val;
+	return 0;
+}
+
+static void atl1c_get_drvinfo(struct net_device *netdev,
+		struct ethtool_drvinfo *drvinfo)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	strlcpy(drvinfo->driver,  atl1c_driver_name, sizeof(drvinfo->driver));
+	strlcpy(drvinfo->version, atl1c_driver_version,
+		sizeof(drvinfo->version));
+	strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+	strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+		sizeof(drvinfo->bus_info));
+	drvinfo->n_stats = 0;
+	drvinfo->testinfo_len = 0;
+	drvinfo->regdump_len = atl1c_get_regs_len(netdev);
+	drvinfo->eedump_len = atl1c_get_eeprom_len(netdev);
+}
+
+static void atl1c_get_wol(struct net_device *netdev,
+			  struct ethtool_wolinfo *wol)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	wol->supported = WAKE_MAGIC | WAKE_PHY;
+	wol->wolopts = 0;
+
+	if (adapter->wol & AT_WUFC_EX)
+		wol->wolopts |= WAKE_UCAST;
+	if (adapter->wol & AT_WUFC_MC)
+		wol->wolopts |= WAKE_MCAST;
+	if (adapter->wol & AT_WUFC_BC)
+		wol->wolopts |= WAKE_BCAST;
+	if (adapter->wol & AT_WUFC_MAG)
+		wol->wolopts |= WAKE_MAGIC;
+	if (adapter->wol & AT_WUFC_LNKC)
+		wol->wolopts |= WAKE_PHY;
+}
+
+static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE |
+			    WAKE_UCAST | WAKE_BCAST | WAKE_MCAST))
+		return -EOPNOTSUPP;
+	/* these settings will always override what we currently have */
+	adapter->wol = 0;
+
+	if (wol->wolopts & WAKE_MAGIC)
+		adapter->wol |= AT_WUFC_MAG;
+	if (wol->wolopts & WAKE_PHY)
+		adapter->wol |= AT_WUFC_LNKC;
+
+	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
+	return 0;
+}
+
+static int atl1c_nway_reset(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	if (netif_running(netdev))
+		atl1c_reinit_locked(adapter);
+	return 0;
+}
+
+static const struct ethtool_ops atl1c_ethtool_ops = {
+	.get_settings           = atl1c_get_settings,
+	.set_settings           = atl1c_set_settings,
+	.get_drvinfo            = atl1c_get_drvinfo,
+	.get_regs_len           = atl1c_get_regs_len,
+	.get_regs               = atl1c_get_regs,
+	.get_wol                = atl1c_get_wol,
+	.set_wol                = atl1c_set_wol,
+	.get_msglevel           = atl1c_get_msglevel,
+	.set_msglevel           = atl1c_set_msglevel,
+	.nway_reset             = atl1c_nway_reset,
+	.get_link               = ethtool_op_get_link,
+	.get_eeprom_len         = atl1c_get_eeprom_len,
+	.get_eeprom             = atl1c_get_eeprom,
+};
+
+void atl1c_set_ethtool_ops(struct net_device *netdev)
+{
+	SET_ETHTOOL_OPS(netdev, &atl1c_ethtool_ops);
+}
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1c/atl1c.h linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1c/atl1c.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1c/atl1c.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1c/atl1c.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,636 @@
+/*
+ * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You 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 _ATL1C_H_
+#define _ATL1C_H_
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/udp.h>
+#include <linux/mii.h>
+#include <linux/io.h>
+#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
+#include <linux/tcp.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/workqueue.h>
+#include <net/checksum.h>
+#include <net/ip6_checksum.h>
+
+#include "atl1c_hw.h"
+
+/* Wake Up Filter Control */
+#define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
+#define AT_WUFC_MAG  0x00000002 /* Magic Packet Wakeup Enable */
+#define AT_WUFC_EX   0x00000004 /* Directed Exact Wakeup Enable */
+#define AT_WUFC_MC   0x00000008 /* Multicast Wakeup Enable */
+#define AT_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */
+
+#define AT_VLAN_TO_TAG(_vlan, _tag)	   \
+	_tag =  ((((_vlan) >> 8) & 0xFF)  |\
+		 (((_vlan) & 0xFF) << 8))
+
+#define AT_TAG_TO_VLAN(_tag, _vlan) 	 \
+	_vlan = ((((_tag) >> 8) & 0xFF) |\
+		(((_tag) & 0xFF) << 8))
+
+#define SPEED_0		   0xffff
+#define HALF_DUPLEX        1
+#define FULL_DUPLEX        2
+
+#define AT_RX_BUF_SIZE		(ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN)
+#define MAX_JUMBO_FRAME_SIZE	(6*1024)
+#define MAX_TSO_FRAME_SIZE      (7*1024)
+#define MAX_TX_OFFLOAD_THRESH	(9*1024)
+
+#define AT_MAX_RECEIVE_QUEUE    4
+#define AT_DEF_RECEIVE_QUEUE	1
+#define AT_MAX_TRANSMIT_QUEUE	2
+
+#define AT_DMA_HI_ADDR_MASK     0xffffffff00000000ULL
+#define AT_DMA_LO_ADDR_MASK     0x00000000ffffffffULL
+
+#define AT_TX_WATCHDOG  (5 * HZ)
+#define AT_MAX_INT_WORK		5
+#define AT_TWSI_EEPROM_TIMEOUT 	100
+#define AT_HW_MAX_IDLE_DELAY 	10
+#define AT_SUSPEND_LINK_TIMEOUT 100
+
+#define AT_ASPM_L0S_TIMER	6
+#define AT_ASPM_L1_TIMER	12
+#define AT_LCKDET_TIMER		12
+
+#define ATL1C_PCIE_L0S_L1_DISABLE 	0x01
+#define ATL1C_PCIE_PHY_RESET		0x02
+
+#define ATL1C_ASPM_L0s_ENABLE		0x0001
+#define ATL1C_ASPM_L1_ENABLE		0x0002
+
+#define AT_REGS_LEN	(75 * sizeof(u32))
+#define AT_EEPROM_LEN 	512
+
+#define ATL1C_GET_DESC(R, i, type)	(&(((type *)((R)->desc))[i]))
+#define ATL1C_RFD_DESC(R, i)	ATL1C_GET_DESC(R, i, struct atl1c_rx_free_desc)
+#define ATL1C_TPD_DESC(R, i)	ATL1C_GET_DESC(R, i, struct atl1c_tpd_desc)
+#define ATL1C_RRD_DESC(R, i)	ATL1C_GET_DESC(R, i, struct atl1c_recv_ret_status)
+
+/* tpd word 1 bit 0:7 General Checksum task offload */
+#define TPD_L4HDR_OFFSET_MASK	0x00FF
+#define TPD_L4HDR_OFFSET_SHIFT	0
+
+/* tpd word 1 bit 0:7 Large Send task offload (IPv4/IPV6) */
+#define TPD_TCPHDR_OFFSET_MASK	0x00FF
+#define TPD_TCPHDR_OFFSET_SHIFT	0
+
+/* tpd word 1 bit 0:7 Custom Checksum task offload */
+#define TPD_PLOADOFFSET_MASK	0x00FF
+#define TPD_PLOADOFFSET_SHIFT	0
+
+/* tpd word 1 bit 8:17 */
+#define TPD_CCSUM_EN_MASK	0x0001
+#define TPD_CCSUM_EN_SHIFT	8
+#define TPD_IP_CSUM_MASK	0x0001
+#define TPD_IP_CSUM_SHIFT	9
+#define TPD_TCP_CSUM_MASK	0x0001
+#define TPD_TCP_CSUM_SHIFT	10
+#define TPD_UDP_CSUM_MASK	0x0001
+#define TPD_UDP_CSUM_SHIFT	11
+#define TPD_LSO_EN_MASK		0x0001	/* TCP Large Send Offload */
+#define TPD_LSO_EN_SHIFT	12
+#define TPD_LSO_VER_MASK	0x0001
+#define TPD_LSO_VER_SHIFT	13 	/* 0 : ipv4; 1 : ipv4/ipv6 */
+#define TPD_CON_VTAG_MASK	0x0001
+#define TPD_CON_VTAG_SHIFT	14
+#define TPD_INS_VTAG_MASK	0x0001
+#define TPD_INS_VTAG_SHIFT	15
+#define TPD_IPV4_PACKET_MASK	0x0001  /* valid when LSO VER  is 1 */
+#define TPD_IPV4_PACKET_SHIFT	16
+#define TPD_ETH_TYPE_MASK	0x0001
+#define TPD_ETH_TYPE_SHIFT	17	/* 0 : 802.3 frame; 1 : Ethernet */
+
+/* tpd word 18:25 Custom Checksum task offload */
+#define TPD_CCSUM_OFFSET_MASK	0x00FF
+#define TPD_CCSUM_OFFSET_SHIFT	18
+#define TPD_CCSUM_EPAD_MASK	0x0001
+#define TPD_CCSUM_EPAD_SHIFT	30
+
+/* tpd word 18:30 Large Send task offload (IPv4/IPV6) */
+#define TPD_MSS_MASK            0x1FFF
+#define TPD_MSS_SHIFT		18
+
+#define TPD_EOP_MASK		0x0001
+#define TPD_EOP_SHIFT		31
+
+struct atl1c_tpd_desc {
+	__le16	buffer_len; /* include 4-byte CRC */
+	__le16	vlan_tag;
+	__le32	word1;
+	__le64	buffer_addr;
+};
+
+struct atl1c_tpd_ext_desc {
+	u32 reservd_0;
+	__le32 word1;
+	__le32 pkt_len;
+	u32 reservd_1;
+};
+/* rrs word 0 bit 0:31 */
+#define RRS_RX_CSUM_MASK	0xFFFF
+#define RRS_RX_CSUM_SHIFT	0
+#define RRS_RX_RFD_CNT_MASK	0x000F
+#define RRS_RX_RFD_CNT_SHIFT	16
+#define RRS_RX_RFD_INDEX_MASK	0x0FFF
+#define RRS_RX_RFD_INDEX_SHIFT	20
+
+/* rrs flag bit 0:16 */
+#define RRS_HEAD_LEN_MASK	0x00FF
+#define RRS_HEAD_LEN_SHIFT	0
+#define RRS_HDS_TYPE_MASK	0x0003
+#define RRS_HDS_TYPE_SHIFT	8
+#define RRS_CPU_NUM_MASK	0x0003
+#define	RRS_CPU_NUM_SHIFT	10
+#define RRS_HASH_FLG_MASK	0x000F
+#define RRS_HASH_FLG_SHIFT	12
+
+#define RRS_HDS_TYPE_HEAD	1
+#define RRS_HDS_TYPE_DATA	2
+
+#define RRS_IS_NO_HDS_TYPE(flag) \
+	((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == 0)
+
+#define RRS_IS_HDS_HEAD(flag) \
+	((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \
+			RRS_HDS_TYPE_HEAD)
+
+#define RRS_IS_HDS_DATA(flag) \
+	((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \
+			RRS_HDS_TYPE_DATA)
+
+/* rrs word 3 bit 0:31 */
+#define RRS_PKT_SIZE_MASK	0x3FFF
+#define RRS_PKT_SIZE_SHIFT	0
+#define RRS_ERR_L4_CSUM_MASK	0x0001
+#define RRS_ERR_L4_CSUM_SHIFT	14
+#define RRS_ERR_IP_CSUM_MASK	0x0001
+#define RRS_ERR_IP_CSUM_SHIFT	15
+#define RRS_VLAN_INS_MASK	0x0001
+#define RRS_VLAN_INS_SHIFT	16
+#define RRS_PROT_ID_MASK	0x0007
+#define RRS_PROT_ID_SHIFT	17
+#define RRS_RX_ERR_SUM_MASK	0x0001
+#define RRS_RX_ERR_SUM_SHIFT	20
+#define RRS_RX_ERR_CRC_MASK	0x0001
+#define RRS_RX_ERR_CRC_SHIFT	21
+#define RRS_RX_ERR_FAE_MASK	0x0001
+#define RRS_RX_ERR_FAE_SHIFT	22
+#define RRS_RX_ERR_TRUNC_MASK	0x0001
+#define RRS_RX_ERR_TRUNC_SHIFT	23
+#define RRS_RX_ERR_RUNC_MASK	0x0001
+#define RRS_RX_ERR_RUNC_SHIFT	24
+#define RRS_RX_ERR_ICMP_MASK	0x0001
+#define RRS_RX_ERR_ICMP_SHIFT	25
+#define RRS_PACKET_BCAST_MASK	0x0001
+#define RRS_PACKET_BCAST_SHIFT	26
+#define RRS_PACKET_MCAST_MASK	0x0001
+#define RRS_PACKET_MCAST_SHIFT	27
+#define RRS_PACKET_TYPE_MASK	0x0001
+#define RRS_PACKET_TYPE_SHIFT	28
+#define RRS_FIFO_FULL_MASK	0x0001
+#define RRS_FIFO_FULL_SHIFT	29
+#define RRS_802_3_LEN_ERR_MASK 	0x0001
+#define RRS_802_3_LEN_ERR_SHIFT 30
+#define RRS_RXD_UPDATED_MASK	0x0001
+#define RRS_RXD_UPDATED_SHIFT	31
+
+#define RRS_ERR_L4_CSUM         0x00004000
+#define RRS_ERR_IP_CSUM         0x00008000
+#define RRS_VLAN_INS            0x00010000
+#define RRS_RX_ERR_SUM          0x00100000
+#define RRS_RX_ERR_CRC          0x00200000
+#define RRS_802_3_LEN_ERR	0x40000000
+#define RRS_RXD_UPDATED		0x80000000
+
+#define RRS_PACKET_TYPE_802_3  	1
+#define RRS_PACKET_TYPE_ETH	0
+#define RRS_PACKET_IS_ETH(word) \
+	((((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK) == \
+			RRS_PACKET_TYPE_ETH)
+#define RRS_RXD_IS_VALID(word) \
+	((((word) >> RRS_RXD_UPDATED_SHIFT) & RRS_RXD_UPDATED_MASK) == 1)
+
+#define RRS_PACKET_PROT_IS_IPV4_ONLY(word) \
+	((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 1)
+#define RRS_PACKET_PROT_IS_IPV6_ONLY(word) \
+	((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 6)
+
+struct atl1c_recv_ret_status {
+	__le32  word0;
+	__le32	rss_hash;
+	__le16	vlan_tag;
+	__le16	flag;
+	__le32	word3;
+};
+
+/* RFD descriptor */
+struct atl1c_rx_free_desc {
+	__le64	buffer_addr;
+};
+
+/* DMA Order Settings */
+enum atl1c_dma_order {
+	atl1c_dma_ord_in = 1,
+	atl1c_dma_ord_enh = 2,
+	atl1c_dma_ord_out = 4
+};
+
+enum atl1c_dma_rcb {
+	atl1c_rcb_64 = 0,
+	atl1c_rcb_128 = 1
+};
+
+enum atl1c_mac_speed {
+	atl1c_mac_speed_0 = 0,
+	atl1c_mac_speed_10_100 = 1,
+	atl1c_mac_speed_1000 = 2
+};
+
+enum atl1c_dma_req_block {
+	atl1c_dma_req_128 = 0,
+	atl1c_dma_req_256 = 1,
+	atl1c_dma_req_512 = 2,
+	atl1c_dma_req_1024 = 3,
+	atl1c_dma_req_2048 = 4,
+	atl1c_dma_req_4096 = 5
+};
+
+enum atl1c_rss_mode {
+	atl1c_rss_mode_disable = 0,
+	atl1c_rss_sig_que = 1,
+	atl1c_rss_mul_que_sig_int = 2,
+	atl1c_rss_mul_que_mul_int = 4,
+};
+
+enum atl1c_rss_type {
+	atl1c_rss_disable = 0,
+	atl1c_rss_ipv4 = 1,
+	atl1c_rss_ipv4_tcp = 2,
+	atl1c_rss_ipv6 = 4,
+	atl1c_rss_ipv6_tcp = 8
+};
+
+enum atl1c_nic_type {
+	athr_l1c = 0,
+	athr_l2c = 1,
+	athr_l2c_b,
+	athr_l2c_b2,
+	athr_l1d,
+	athr_l1d_2,
+};
+
+enum atl1c_trans_queue {
+	atl1c_trans_normal = 0,
+	atl1c_trans_high = 1
+};
+
+struct atl1c_hw_stats {
+	/* rx */
+	unsigned long rx_ok;		/* The number of good packet received. */
+	unsigned long rx_bcast;		/* The number of good broadcast packet received. */
+	unsigned long rx_mcast;		/* The number of good multicast packet received. */
+	unsigned long rx_pause;		/* The number of Pause packet received. */
+	unsigned long rx_ctrl;		/* The number of Control packet received other than Pause frame. */
+	unsigned long rx_fcs_err;	/* The number of packets with bad FCS. */
+	unsigned long rx_len_err;	/* The number of packets with mismatch of length field and actual size. */
+	unsigned long rx_byte_cnt;	/* The number of bytes of good packet received. FCS is NOT included. */
+	unsigned long rx_runt;		/* The number of packets received that are less than 64 byte long and with good FCS. */
+	unsigned long rx_frag;		/* The number of packets received that are less than 64 byte long and with bad FCS. */
+	unsigned long rx_sz_64;		/* The number of good and bad packets received that are 64 byte long. */
+	unsigned long rx_sz_65_127;	/* The number of good and bad packets received that are between 65 and 127-byte long. */
+	unsigned long rx_sz_128_255;	/* The number of good and bad packets received that are between 128 and 255-byte long. */
+	unsigned long rx_sz_256_511;	/* The number of good and bad packets received that are between 256 and 511-byte long. */
+	unsigned long rx_sz_512_1023;	/* The number of good and bad packets received that are between 512 and 1023-byte long. */
+	unsigned long rx_sz_1024_1518;	/* The number of good and bad packets received that are between 1024 and 1518-byte long. */
+	unsigned long rx_sz_1519_max;	/* The number of good and bad packets received that are between 1519-byte and MTU. */
+	unsigned long rx_sz_ov;		/* The number of good and bad packets received that are more than MTU size truncated by Selene. */
+	unsigned long rx_rxf_ov;	/* The number of frame dropped due to occurrence of RX FIFO overflow. */
+	unsigned long rx_rrd_ov;	/* The number of frame dropped due to occurrence of RRD overflow. */
+	unsigned long rx_align_err;	/* Alignment Error */
+	unsigned long rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */
+	unsigned long rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */
+	unsigned long rx_err_addr;	/* The number of packets dropped due to address filtering. */
+
+	/* tx */
+	unsigned long tx_ok;		/* The number of good packet transmitted. */
+	unsigned long tx_bcast;		/* The number of good broadcast packet transmitted. */
+	unsigned long tx_mcast;		/* The number of good multicast packet transmitted. */
+	unsigned long tx_pause;		/* The number of Pause packet transmitted. */
+	unsigned long tx_exc_defer;	/* The number of packets transmitted with excessive deferral. */
+	unsigned long tx_ctrl;		/* The number of packets transmitted is a control frame, excluding Pause frame. */
+	unsigned long tx_defer;		/* The number of packets transmitted that is deferred. */
+	unsigned long tx_byte_cnt;	/* The number of bytes of data transmitted. FCS is NOT included. */
+	unsigned long tx_sz_64;		/* The number of good and bad packets transmitted that are 64 byte long. */
+	unsigned long tx_sz_65_127;	/* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
+	unsigned long tx_sz_128_255;	/* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
+	unsigned long tx_sz_256_511;	/* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
+	unsigned long tx_sz_512_1023;	/* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
+	unsigned long tx_sz_1024_1518;	/* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
+	unsigned long tx_sz_1519_max;	/* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
+	unsigned long tx_1_col;		/* The number of packets subsequently transmitted successfully with a single prior collision. */
+	unsigned long tx_2_col;		/* The number of packets subsequently transmitted successfully with multiple prior collisions. */
+	unsigned long tx_late_col;	/* The number of packets transmitted with late collisions. */
+	unsigned long tx_abort_col;	/* The number of transmit packets aborted due to excessive collisions. */
+	unsigned long tx_underrun;	/* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
+	unsigned long tx_rd_eop;	/* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
+	unsigned long tx_len_err;	/* The number of transmit packets with length field does NOT match the actual frame size. */
+	unsigned long tx_trunc;		/* The number of transmit packets truncated due to size exceeding MTU. */
+	unsigned long tx_bcast_byte;	/* The byte count of broadcast packet transmitted, excluding FCS. */
+	unsigned long tx_mcast_byte;	/* The byte count of multicast packet transmitted, excluding FCS. */
+};
+
+struct atl1c_hw {
+	u8 __iomem      *hw_addr;            /* inner register address */
+	struct atl1c_adapter *adapter;
+	enum atl1c_nic_type  nic_type;
+	enum atl1c_dma_order dma_order;
+	enum atl1c_dma_rcb   rcb_value;
+	enum atl1c_dma_req_block dmar_block;
+	enum atl1c_dma_req_block dmaw_block;
+
+	u16 device_id;
+	u16 vendor_id;
+	u16 subsystem_id;
+	u16 subsystem_vendor_id;
+	u8 revision_id;
+	u16 phy_id1;
+	u16 phy_id2;
+
+	u32 intr_mask;
+	u8 dmaw_dly_cnt;
+	u8 dmar_dly_cnt;
+
+	u8 preamble_len;
+	u16 max_frame_size;
+	u16 min_frame_size;
+
+	enum atl1c_mac_speed mac_speed;
+	bool mac_duplex;
+	bool hibernate;
+	u16 media_type;
+#define MEDIA_TYPE_AUTO_SENSOR  0
+#define MEDIA_TYPE_100M_FULL    1
+#define MEDIA_TYPE_100M_HALF    2
+#define MEDIA_TYPE_10M_FULL     3
+#define MEDIA_TYPE_10M_HALF     4
+
+	u16 autoneg_advertised;
+	u16 mii_autoneg_adv_reg;
+	u16 mii_1000t_ctrl_reg;
+
+	u16 tx_imt;	/* TX Interrupt Moderator timer ( 2us resolution) */
+	u16 rx_imt;	/* RX Interrupt Moderator timer ( 2us resolution) */
+	u16 ict;        /* Interrupt Clear timer (2us resolution) */
+	u16 ctrl_flags;
+#define ATL1C_INTR_CLEAR_ON_READ	0x0001
+#define ATL1C_INTR_MODRT_ENABLE	 	0x0002
+#define ATL1C_CMB_ENABLE		0x0004
+#define ATL1C_SMB_ENABLE		0x0010
+#define ATL1C_TXQ_MODE_ENHANCE		0x0020
+#define ATL1C_RX_IPV6_CHKSUM		0x0040
+#define ATL1C_ASPM_L0S_SUPPORT		0x0080
+#define ATL1C_ASPM_L1_SUPPORT		0x0100
+#define ATL1C_ASPM_CTRL_MON		0x0200
+#define ATL1C_HIB_DISABLE		0x0400
+#define ATL1C_APS_MODE_ENABLE           0x0800
+#define ATL1C_LINK_EXT_SYNC             0x1000
+#define ATL1C_CLK_GATING_EN             0x2000
+#define ATL1C_FPGA_VERSION              0x8000
+	u16 link_cap_flags;
+#define ATL1C_LINK_CAP_1000M		0x0001
+	u16 cmb_tpd;
+	u16 cmb_rrd;
+	u16 cmb_rx_timer; /* 2us resolution */
+	u16 cmb_tx_timer;
+	u32 smb_timer;
+
+	u16 rrd_thresh; /* Threshold of number of RRD produced to trigger
+			  interrupt request */
+	u16 tpd_thresh;
+	u8 tpd_burst;   /* Number of TPD to prefetch in cache-aligned burst. */
+	u8 rfd_burst;
+	enum atl1c_rss_type rss_type;
+	enum atl1c_rss_mode rss_mode;
+	u8 rss_hash_bits;
+	u32 base_cpu;
+	u32 indirect_tab;
+	u8 mac_addr[ETH_ALEN];
+	u8 perm_mac_addr[ETH_ALEN];
+
+	bool phy_configured;
+	bool re_autoneg;
+	bool emi_ca;
+};
+
+/*
+ * atl1c_ring_header represents a single, contiguous block of DMA space
+ * mapped for the three descriptor rings (tpd, rfd, rrd) and the two
+ * message blocks (cmb, smb) described below
+ */
+struct atl1c_ring_header {
+	void *desc;		/* virtual address */
+	dma_addr_t dma;		/* physical address*/
+	unsigned int size;	/* length in bytes */
+};
+
+/*
+ * atl1c_buffer is wrapper around a pointer to a socket buffer
+ * so a DMA handle can be stored along with the skb
+ */
+struct atl1c_buffer {
+	struct sk_buff *skb;	/* socket buffer */
+	u16 length;		/* rx buffer length */
+	u16 flags;		/* information of buffer */
+#define ATL1C_BUFFER_FREE		0x0001
+#define ATL1C_BUFFER_BUSY		0x0002
+#define ATL1C_BUFFER_STATE_MASK		0x0003
+
+#define ATL1C_PCIMAP_SINGLE		0x0004
+#define ATL1C_PCIMAP_PAGE		0x0008
+#define ATL1C_PCIMAP_TYPE_MASK		0x000C
+
+#define ATL1C_PCIMAP_TODEVICE		0x0010
+#define ATL1C_PCIMAP_FROMDEVICE		0x0020
+#define ATL1C_PCIMAP_DIRECTION_MASK	0x0030
+	dma_addr_t dma;
+};
+
+#define ATL1C_SET_BUFFER_STATE(buff, state) do {	\
+	((buff)->flags) &= ~ATL1C_BUFFER_STATE_MASK;	\
+	((buff)->flags) |= (state);			\
+	} while (0)
+
+#define ATL1C_SET_PCIMAP_TYPE(buff, type, direction) do {	\
+	((buff)->flags) &= ~ATL1C_PCIMAP_TYPE_MASK;		\
+	((buff)->flags) |= (type);				\
+	((buff)->flags) &= ~ATL1C_PCIMAP_DIRECTION_MASK;	\
+	((buff)->flags) |= (direction);				\
+	} while (0)
+
+/* transimit packet descriptor (tpd) ring */
+struct atl1c_tpd_ring {
+	void *desc;		/* descriptor ring virtual address */
+	dma_addr_t dma;		/* descriptor ring physical address */
+	u16 size;		/* descriptor ring length in bytes */
+	u16 count;		/* number of descriptors in the ring */
+	u16 next_to_use; 	/* this is protectd by adapter->tx_lock */
+	atomic_t next_to_clean;
+	struct atl1c_buffer *buffer_info;
+};
+
+/* receive free descriptor (rfd) ring */
+struct atl1c_rfd_ring {
+	void *desc;		/* descriptor ring virtual address */
+	dma_addr_t dma;		/* descriptor ring physical address */
+	u16 size;		/* descriptor ring length in bytes */
+	u16 count;		/* number of descriptors in the ring */
+	u16 next_to_use;
+	u16 next_to_clean;
+	struct atl1c_buffer *buffer_info;
+};
+
+/* receive return descriptor (rrd) ring */
+struct atl1c_rrd_ring {
+	void *desc;		/* descriptor ring virtual address */
+	dma_addr_t dma;		/* descriptor ring physical address */
+	u16 size;		/* descriptor ring length in bytes */
+	u16 count;		/* number of descriptors in the ring */
+	u16 next_to_use;
+	u16 next_to_clean;
+};
+
+struct atl1c_cmb {
+	void *cmb;
+	dma_addr_t dma;
+};
+
+struct atl1c_smb {
+	void *smb;
+	dma_addr_t dma;
+};
+
+/* board specific private data structure */
+struct atl1c_adapter {
+	struct net_device   *netdev;
+	struct pci_dev      *pdev;
+	struct napi_struct  napi;
+	struct atl1c_hw        hw;
+	struct atl1c_hw_stats  hw_stats;
+	struct mii_if_info  mii;    /* MII interface info */
+	u16 rx_buffer_len;
+
+	unsigned long flags;
+#define __AT_TESTING        0x0001
+#define __AT_RESETTING      0x0002
+#define __AT_DOWN           0x0003
+	unsigned long work_event;
+#define	ATL1C_WORK_EVENT_RESET		0
+#define	ATL1C_WORK_EVENT_LINK_CHANGE	1
+	u32 msg_enable;
+
+	bool have_msi;
+	u32 wol;
+	u16 link_speed;
+	u16 link_duplex;
+
+	spinlock_t mdio_lock;
+	spinlock_t tx_lock;
+	atomic_t irq_sem;
+
+	struct work_struct common_task;
+	struct timer_list watchdog_timer;
+	struct timer_list phy_config_timer;
+
+	/* All Descriptor memory */
+	struct atl1c_ring_header ring_header;
+	struct atl1c_tpd_ring tpd_ring[AT_MAX_TRANSMIT_QUEUE];
+	struct atl1c_rfd_ring rfd_ring[AT_MAX_RECEIVE_QUEUE];
+	struct atl1c_rrd_ring rrd_ring[AT_MAX_RECEIVE_QUEUE];
+	struct atl1c_cmb cmb;
+	struct atl1c_smb smb;
+	int num_rx_queues;
+	u32 bd_number;     /* board number;*/
+};
+
+#define AT_WRITE_REG(a, reg, value) ( \
+		writel((value), ((a)->hw_addr + reg)))
+
+#define AT_WRITE_FLUSH(a) (\
+		readl((a)->hw_addr))
+
+#define AT_READ_REG(a, reg, pdata) do {					\
+		if (unlikely((a)->hibernate)) {				\
+			readl((a)->hw_addr + reg);			\
+			*(u32 *)pdata = readl((a)->hw_addr + reg);	\
+		} else {						\
+			*(u32 *)pdata = readl((a)->hw_addr + reg);	\
+		}							\
+	} while (0)
+
+#define AT_WRITE_REGB(a, reg, value) (\
+		writeb((value), ((a)->hw_addr + reg)))
+
+#define AT_READ_REGB(a, reg) (\
+		readb((a)->hw_addr + reg))
+
+#define AT_WRITE_REGW(a, reg, value) (\
+		writew((value), ((a)->hw_addr + reg)))
+
+#define AT_READ_REGW(a, reg) (\
+		readw((a)->hw_addr + reg))
+
+#define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \
+		writel((value), (((a)->hw_addr + reg) + ((offset) << 2))))
+
+#define AT_READ_REG_ARRAY(a, reg, offset) ( \
+		readl(((a)->hw_addr + reg) + ((offset) << 2)))
+
+extern char atl1c_driver_name[];
+extern char atl1c_driver_version[];
+
+extern void atl1c_reinit_locked(struct atl1c_adapter *adapter);
+extern s32 atl1c_reset_hw(struct atl1c_hw *hw);
+extern void atl1c_set_ethtool_ops(struct net_device *netdev);
+#endif /* _ATL1C_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,662 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You 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/pci.h>
+#include <linux/delay.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+
+#include "atl1c.h"
+
+/*
+ * check_eeprom_exist
+ * return 1 if eeprom exist
+ */
+int atl1c_check_eeprom_exist(struct atl1c_hw *hw)
+{
+	u32 data;
+
+	AT_READ_REG(hw, REG_TWSI_DEBUG, &data);
+	if (data & TWSI_DEBUG_DEV_EXIST)
+		return 1;
+
+	AT_READ_REG(hw, REG_MASTER_CTRL, &data);
+	if (data & MASTER_CTRL_OTP_SEL)
+		return 1;
+	return 0;
+}
+
+void atl1c_hw_set_mac_addr(struct atl1c_hw *hw)
+{
+	u32 value;
+	/*
+	 * 00-0B-6A-F6-00-DC
+	 * 0:  6AF600DC 1: 000B
+	 * low dword
+	 */
+	value = (((u32)hw->mac_addr[2]) << 24) |
+		(((u32)hw->mac_addr[3]) << 16) |
+		(((u32)hw->mac_addr[4]) << 8)  |
+		(((u32)hw->mac_addr[5])) ;
+	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
+	/* hight dword */
+	value = (((u32)hw->mac_addr[0]) << 8) |
+		(((u32)hw->mac_addr[1])) ;
+	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
+}
+
+/*
+ * atl1c_get_permanent_address
+ * return 0 if get valid mac address,
+ */
+static int atl1c_get_permanent_address(struct atl1c_hw *hw)
+{
+	u32 addr[2];
+	u32 i;
+	u32 otp_ctrl_data;
+	u32 twsi_ctrl_data;
+	u32 ltssm_ctrl_data;
+	u32 wol_data;
+	u8  eth_addr[ETH_ALEN];
+	u16 phy_data;
+	bool raise_vol = false;
+
+	/* init */
+	addr[0] = addr[1] = 0;
+	AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
+	if (atl1c_check_eeprom_exist(hw)) {
+		if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) {
+			/* Enable OTP CLK */
+			if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) {
+				otp_ctrl_data |= OTP_CTRL_CLK_EN;
+				AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
+				AT_WRITE_FLUSH(hw);
+				msleep(1);
+			}
+		}
+
+		if (hw->nic_type == athr_l2c_b ||
+		    hw->nic_type == athr_l2c_b2 ||
+		    hw->nic_type == athr_l1d) {
+			atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00);
+			if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
+				goto out;
+			phy_data &= 0xFF7F;
+			atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
+
+			atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
+			if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
+				goto out;
+			phy_data |= 0x8;
+			atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
+			udelay(20);
+			raise_vol = true;
+		}
+		/* close open bit of ReadOnly*/
+		AT_READ_REG(hw, REG_LTSSM_ID_CTRL, &ltssm_ctrl_data);
+		ltssm_ctrl_data &= ~LTSSM_ID_EN_WRO;
+		AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, ltssm_ctrl_data);
+
+		/* clear any WOL settings */
+		AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+		AT_READ_REG(hw, REG_WOL_CTRL, &wol_data);
+
+
+		AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
+		twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
+		AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
+		for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
+			msleep(10);
+			AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
+			if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
+				break;
+		}
+		if (i >= AT_TWSI_EEPROM_TIMEOUT)
+			return -1;
+	}
+	/* Disable OTP_CLK */
+	if ((hw->nic_type == athr_l1c || hw->nic_type == athr_l2c)) {
+		otp_ctrl_data &= ~OTP_CTRL_CLK_EN;
+		AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
+		msleep(1);
+	}
+	if (raise_vol) {
+		if (hw->nic_type == athr_l2c_b ||
+		    hw->nic_type == athr_l2c_b2 ||
+		    hw->nic_type == athr_l1d ||
+		    hw->nic_type == athr_l1d_2) {
+			atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00);
+			if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
+				goto out;
+			phy_data |= 0x80;
+			atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
+
+			atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
+			if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
+				goto out;
+			phy_data &= 0xFFF7;
+			atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
+			udelay(20);
+		}
+	}
+
+	/* maybe MAC-address is from BIOS */
+	AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]);
+	AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]);
+	*(u32 *) &eth_addr[2] = swab32(addr[0]);
+	*(u16 *) &eth_addr[0] = swab16(*(u16 *)&addr[1]);
+
+	if (is_valid_ether_addr(eth_addr)) {
+		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+		return 0;
+	}
+
+out:
+	return -1;
+}
+
+bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value)
+{
+	int i;
+	int ret = false;
+	u32 otp_ctrl_data;
+	u32 control;
+	u32 data;
+
+	if (offset & 3)
+		return ret; /* address do not align */
+
+	AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
+	if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))
+		AT_WRITE_REG(hw, REG_OTP_CTRL,
+				(otp_ctrl_data | OTP_CTRL_CLK_EN));
+
+	AT_WRITE_REG(hw, REG_EEPROM_DATA_LO, 0);
+	control = (offset & EEPROM_CTRL_ADDR_MASK) << EEPROM_CTRL_ADDR_SHIFT;
+	AT_WRITE_REG(hw, REG_EEPROM_CTRL, control);
+
+	for (i = 0; i < 10; i++) {
+		udelay(100);
+		AT_READ_REG(hw, REG_EEPROM_CTRL, &control);
+		if (control & EEPROM_CTRL_RW)
+			break;
+	}
+	if (control & EEPROM_CTRL_RW) {
+		AT_READ_REG(hw, REG_EEPROM_CTRL, &data);
+		AT_READ_REG(hw, REG_EEPROM_DATA_LO, p_value);
+		data = data & 0xFFFF;
+		*p_value = swab32((data << 16) | (*p_value >> 16));
+		ret = true;
+	}
+	if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))
+		AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
+
+	return ret;
+}
+/*
+ * Reads the adapter's MAC address from the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+int atl1c_read_mac_addr(struct atl1c_hw *hw)
+{
+	int err = 0;
+
+	err = atl1c_get_permanent_address(hw);
+	if (err)
+		random_ether_addr(hw->perm_mac_addr);
+
+	memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
+	return 0;
+}
+
+/*
+ * atl1c_hash_mc_addr
+ *  purpose
+ *      set hash value for a multicast address
+ *      hash calcu processing :
+ *          1. calcu 32bit CRC for multicast address
+ *          2. reverse crc with MSB to LSB
+ */
+u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr)
+{
+	u32 crc32;
+	u32 value = 0;
+	int i;
+
+	crc32 = ether_crc_le(6, mc_addr);
+	for (i = 0; i < 32; i++)
+		value |= (((crc32 >> i) & 1) << (31 - i));
+
+	return value;
+}
+
+/*
+ * Sets the bit in the multicast table corresponding to the hash value.
+ * hw - Struct containing variables accessed by shared code
+ * hash_value - Multicast address hash value
+ */
+void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value)
+{
+	u32 hash_bit, hash_reg;
+	u32 mta;
+
+	/*
+	 * The HASH Table  is a register array of 2 32-bit registers.
+	 * It is treated like an array of 64 bits.  We want to set
+	 * bit BitArray[hash_value]. So we figure out what register
+	 * the bit is in, read it, OR in the new bit, then write
+	 * back the new value.  The register is determined by the
+	 * upper bit of the hash value and the bit within that
+	 * register are determined by the lower 5 bits of the value.
+	 */
+	hash_reg = (hash_value >> 31) & 0x1;
+	hash_bit = (hash_value >> 26) & 0x1F;
+
+	mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);
+
+	mta |= (1 << hash_bit);
+
+	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
+}
+
+/*
+ * Reads the value from a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ */
+int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+	u32 val;
+	int i;
+
+	val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
+		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
+		MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+
+	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+		udelay(2);
+		AT_READ_REG(hw, REG_MDIO_CTRL, &val);
+		if (!(val & (MDIO_START | MDIO_BUSY)))
+			break;
+	}
+	if (!(val & (MDIO_START | MDIO_BUSY))) {
+		*phy_data = (u16)val;
+		return 0;
+	}
+
+	return -1;
+}
+
+/*
+ * Writes a value to a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ */
+int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data)
+{
+	int i;
+	u32 val;
+
+	val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT   |
+	       (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
+	       MDIO_SUP_PREAMBLE | MDIO_START |
+	       MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+
+	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+		udelay(2);
+		AT_READ_REG(hw, REG_MDIO_CTRL, &val);
+		if (!(val & (MDIO_START | MDIO_BUSY)))
+			break;
+	}
+
+	if (!(val & (MDIO_START | MDIO_BUSY)))
+		return 0;
+
+	return -1;
+}
+
+/*
+ * Configures PHY autoneg and flow control advertisement settings
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+static int atl1c_phy_setup_adv(struct atl1c_hw *hw)
+{
+	u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_ALL;
+	u16 mii_giga_ctrl_data = GIGA_CR_1000T_DEFAULT_CAP &
+				~GIGA_CR_1000T_SPEED_MASK;
+
+	if (hw->autoneg_advertised & ADVERTISED_10baseT_Half)
+		mii_adv_data |= ADVERTISE_10HALF;
+	if (hw->autoneg_advertised & ADVERTISED_10baseT_Full)
+		mii_adv_data |= ADVERTISE_10FULL;
+	if (hw->autoneg_advertised & ADVERTISED_100baseT_Half)
+		mii_adv_data |= ADVERTISE_100HALF;
+	if (hw->autoneg_advertised & ADVERTISED_100baseT_Full)
+		mii_adv_data |= ADVERTISE_100FULL;
+
+	if (hw->autoneg_advertised & ADVERTISED_Autoneg)
+		mii_adv_data |= ADVERTISE_10HALF  | ADVERTISE_10FULL |
+				ADVERTISE_100HALF | ADVERTISE_100FULL;
+
+	if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M) {
+		if (hw->autoneg_advertised & ADVERTISED_1000baseT_Half)
+			mii_giga_ctrl_data |= ADVERTISE_1000HALF;
+		if (hw->autoneg_advertised & ADVERTISED_1000baseT_Full)
+			mii_giga_ctrl_data |= ADVERTISE_1000FULL;
+		if (hw->autoneg_advertised & ADVERTISED_Autoneg)
+			mii_giga_ctrl_data |= ADVERTISE_1000HALF |
+					ADVERTISE_1000FULL;
+	}
+
+	if (atl1c_write_phy_reg(hw, MII_ADVERTISE, mii_adv_data) != 0 ||
+	    atl1c_write_phy_reg(hw, MII_CTRL1000, mii_giga_ctrl_data) != 0)
+		return -1;
+	return 0;
+}
+
+void atl1c_phy_disable(struct atl1c_hw *hw)
+{
+	AT_WRITE_REGW(hw, REG_GPHY_CTRL,
+			GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
+}
+
+static void atl1c_phy_magic_data(struct atl1c_hw *hw)
+{
+	u16 data;
+
+	data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE |
+		((1 & ANA_INTERVAL_SEL_TIMER_MASK) <<
+		ANA_INTERVAL_SEL_TIMER_SHIFT);
+
+	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_18);
+	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+	data = (2 & ANA_SERDES_CDR_BW_MASK) | ANA_MS_PAD_DBG |
+		ANA_SERDES_EN_DEEM | ANA_SERDES_SEL_HSP | ANA_SERDES_EN_PLL |
+		ANA_SERDES_EN_LCKDT;
+
+	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_5);
+	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+	data = (44 & ANA_LONG_CABLE_TH_100_MASK) |
+		((33 & ANA_SHORT_CABLE_TH_100_MASK) <<
+		ANA_SHORT_CABLE_TH_100_SHIFT) | ANA_BP_BAD_LINK_ACCUM |
+		ANA_BP_SMALL_BW;
+
+	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_54);
+	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+	data = (11 & ANA_IECHO_ADJ_MASK) | ((11 & ANA_IECHO_ADJ_MASK) <<
+		ANA_IECHO_ADJ_2_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
+		ANA_IECHO_ADJ_1_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
+		ANA_IECHO_ADJ_0_SHIFT);
+
+	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_4);
+	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+	data = ANA_RESTART_CAL | ((7 & ANA_MANUL_SWICH_ON_MASK) <<
+		ANA_MANUL_SWICH_ON_SHIFT) | ANA_MAN_ENABLE |
+		ANA_SEL_HSP | ANA_EN_HB | ANA_OEN_125M;
+
+	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_0);
+	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+	if (hw->ctrl_flags & ATL1C_HIB_DISABLE) {
+		atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_41);
+		if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
+			return;
+		data &= ~ANA_TOP_PS_EN;
+		atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+		atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_11);
+		if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
+			return;
+		data &= ~ANA_PS_HIB_EN;
+		atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+	}
+}
+
+int atl1c_phy_reset(struct atl1c_hw *hw)
+{
+	struct atl1c_adapter *adapter = hw->adapter;
+	struct pci_dev *pdev = adapter->pdev;
+	u16 phy_data;
+	u32 phy_ctrl_data = GPHY_CTRL_DEFAULT;
+	u32 mii_ier_data = IER_LINK_UP | IER_LINK_DOWN;
+	int err;
+
+	if (hw->ctrl_flags & ATL1C_HIB_DISABLE)
+		phy_ctrl_data &= ~GPHY_CTRL_HIB_EN;
+
+	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
+	AT_WRITE_FLUSH(hw);
+	msleep(40);
+	phy_ctrl_data |= GPHY_CTRL_EXT_RESET;
+	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
+	AT_WRITE_FLUSH(hw);
+	msleep(10);
+
+	if (hw->nic_type == athr_l2c_b) {
+		atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x0A);
+		atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data);
+		atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xDFFF);
+	}
+
+	if (hw->nic_type == athr_l2c_b ||
+	    hw->nic_type == athr_l2c_b2 ||
+	    hw->nic_type == athr_l1d ||
+	    hw->nic_type == athr_l1d_2) {
+		atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
+		atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data);
+		atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xFFF7);
+		msleep(20);
+	}
+	if (hw->nic_type == athr_l1d) {
+		atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
+		atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x929D);
+	}
+	if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b2
+		|| hw->nic_type == athr_l2c) {
+		atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
+		atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD);
+	}
+	err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data);
+	if (err) {
+		if (netif_msg_hw(adapter))
+			dev_err(&pdev->dev,
+				"Error enable PHY linkChange Interrupt\n");
+		return err;
+	}
+	if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))
+		atl1c_phy_magic_data(hw);
+	return 0;
+}
+
+int atl1c_phy_init(struct atl1c_hw *hw)
+{
+	struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
+	struct pci_dev *pdev = adapter->pdev;
+	int ret_val;
+	u16 mii_bmcr_data = BMCR_RESET;
+
+	if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &hw->phy_id1) != 0) ||
+		(atl1c_read_phy_reg(hw, MII_PHYSID2, &hw->phy_id2) != 0)) {
+		dev_err(&pdev->dev, "Error get phy ID\n");
+		return -1;
+	}
+	switch (hw->media_type) {
+	case MEDIA_TYPE_AUTO_SENSOR:
+		ret_val = atl1c_phy_setup_adv(hw);
+		if (ret_val) {
+			if (netif_msg_link(adapter))
+				dev_err(&pdev->dev,
+					"Error Setting up Auto-Negotiation\n");
+			return ret_val;
+		}
+		mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART;
+		break;
+	case MEDIA_TYPE_100M_FULL:
+		mii_bmcr_data |= BMCR_SPEED100 | BMCR_FULLDPLX;
+		break;
+	case MEDIA_TYPE_100M_HALF:
+		mii_bmcr_data |= BMCR_SPEED100;
+		break;
+	case MEDIA_TYPE_10M_FULL:
+		mii_bmcr_data |= BMCR_FULLDPLX;
+		break;
+	case MEDIA_TYPE_10M_HALF:
+		break;
+	default:
+		if (netif_msg_link(adapter))
+			dev_err(&pdev->dev, "Wrong Media type %d\n",
+				hw->media_type);
+		return -1;
+		break;
+	}
+
+	ret_val = atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
+	if (ret_val)
+		return ret_val;
+	hw->phy_configured = true;
+
+	return 0;
+}
+
+/*
+ * Detects the current speed and duplex settings of the hardware.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ */
+int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex)
+{
+	int err;
+	u16 phy_data;
+
+	/* Read   PHY Specific Status Register (17) */
+	err = atl1c_read_phy_reg(hw, MII_GIGA_PSSR, &phy_data);
+	if (err)
+		return err;
+
+	if (!(phy_data & GIGA_PSSR_SPD_DPLX_RESOLVED))
+		return -1;
+
+	switch (phy_data & GIGA_PSSR_SPEED) {
+	case GIGA_PSSR_1000MBS:
+		*speed = SPEED_1000;
+		break;
+	case GIGA_PSSR_100MBS:
+		*speed = SPEED_100;
+		break;
+	case  GIGA_PSSR_10MBS:
+		*speed = SPEED_10;
+		break;
+	default:
+		return -1;
+		break;
+	}
+
+	if (phy_data & GIGA_PSSR_DPLX)
+		*duplex = FULL_DUPLEX;
+	else
+		*duplex = HALF_DUPLEX;
+
+	return 0;
+}
+
+int atl1c_phy_power_saving(struct atl1c_hw *hw)
+{
+	struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
+	struct pci_dev *pdev = adapter->pdev;
+	int ret = 0;
+	u16 autoneg_advertised = ADVERTISED_10baseT_Half;
+	u16 save_autoneg_advertised;
+	u16 phy_data;
+	u16 mii_lpa_data;
+	u16 speed = SPEED_0;
+	u16 duplex = FULL_DUPLEX;
+	int i;
+
+	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
+	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
+	if (phy_data & BMSR_LSTATUS) {
+		atl1c_read_phy_reg(hw, MII_LPA, &mii_lpa_data);
+		if (mii_lpa_data & LPA_10FULL)
+			autoneg_advertised = ADVERTISED_10baseT_Full;
+		else if (mii_lpa_data & LPA_10HALF)
+			autoneg_advertised = ADVERTISED_10baseT_Half;
+		else if (mii_lpa_data & LPA_100HALF)
+			autoneg_advertised = ADVERTISED_100baseT_Half;
+		else if (mii_lpa_data & LPA_100FULL)
+			autoneg_advertised = ADVERTISED_100baseT_Full;
+
+		save_autoneg_advertised = hw->autoneg_advertised;
+		hw->phy_configured = false;
+		hw->autoneg_advertised = autoneg_advertised;
+		if (atl1c_restart_autoneg(hw) != 0) {
+			dev_dbg(&pdev->dev, "phy autoneg failed\n");
+			ret = -1;
+		}
+		hw->autoneg_advertised = save_autoneg_advertised;
+
+		if (mii_lpa_data) {
+			for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) {
+				mdelay(100);
+				atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
+				atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
+				if (phy_data & BMSR_LSTATUS) {
+					if (atl1c_get_speed_and_duplex(hw, &speed,
+									&duplex) != 0)
+						dev_dbg(&pdev->dev,
+							"get speed and duplex failed\n");
+					break;
+				}
+			}
+		}
+	} else {
+		speed = SPEED_10;
+		duplex = HALF_DUPLEX;
+	}
+	adapter->link_speed = speed;
+	adapter->link_duplex = duplex;
+
+	return ret;
+}
+
+int atl1c_restart_autoneg(struct atl1c_hw *hw)
+{
+	int err = 0;
+	u16 mii_bmcr_data = BMCR_RESET;
+
+	err = atl1c_phy_setup_adv(hw);
+	if (err)
+		return err;
+	mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART;
+
+	return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
+}
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,868 @@
+/*
+ * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You 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 _ATL1C_HW_H_
+#define _ATL1C_HW_H_
+
+#include <linux/types.h>
+#include <linux/mii.h>
+
+struct atl1c_adapter;
+struct atl1c_hw;
+
+/* function prototype */
+void atl1c_phy_disable(struct atl1c_hw *hw);
+void atl1c_hw_set_mac_addr(struct atl1c_hw *hw);
+int atl1c_phy_reset(struct atl1c_hw *hw);
+int atl1c_read_mac_addr(struct atl1c_hw *hw);
+int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex);
+u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr);
+void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value);
+int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data);
+int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data);
+bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value);
+int atl1c_phy_init(struct atl1c_hw *hw);
+int atl1c_check_eeprom_exist(struct atl1c_hw *hw);
+int atl1c_restart_autoneg(struct atl1c_hw *hw);
+int atl1c_phy_power_saving(struct atl1c_hw *hw);
+/* register definition */
+#define REG_DEVICE_CAP              	0x5C
+#define DEVICE_CAP_MAX_PAYLOAD_MASK     0x7
+#define DEVICE_CAP_MAX_PAYLOAD_SHIFT    0
+
+#define REG_DEVICE_CTRL			0x60
+#define DEVICE_CTRL_MAX_PAYLOAD_MASK    0x7
+#define DEVICE_CTRL_MAX_PAYLOAD_SHIFT   5
+#define DEVICE_CTRL_MAX_RREQ_SZ_MASK    0x7
+#define DEVICE_CTRL_MAX_RREQ_SZ_SHIFT   12
+
+#define REG_LINK_CTRL			0x68
+#define LINK_CTRL_L0S_EN		0x01
+#define LINK_CTRL_L1_EN			0x02
+#define LINK_CTRL_EXT_SYNC		0x80
+
+#define REG_VPD_CAP			0x6C
+#define VPD_CAP_ID_MASK                 0xff
+#define VPD_CAP_ID_SHIFT                0
+#define VPD_CAP_NEXT_PTR_MASK           0xFF
+#define VPD_CAP_NEXT_PTR_SHIFT          8
+#define VPD_CAP_VPD_ADDR_MASK           0x7FFF
+#define VPD_CAP_VPD_ADDR_SHIFT          16
+#define VPD_CAP_VPD_FLAG                0x80000000
+
+#define REG_VPD_DATA                	0x70
+
+#define REG_PCIE_UC_SEVERITY		0x10C
+#define PCIE_UC_SERVRITY_TRN		0x00000001
+#define PCIE_UC_SERVRITY_DLP		0x00000010
+#define PCIE_UC_SERVRITY_PSN_TLP	0x00001000
+#define PCIE_UC_SERVRITY_FCP		0x00002000
+#define PCIE_UC_SERVRITY_CPL_TO		0x00004000
+#define PCIE_UC_SERVRITY_CA		0x00008000
+#define PCIE_UC_SERVRITY_UC		0x00010000
+#define PCIE_UC_SERVRITY_ROV		0x00020000
+#define PCIE_UC_SERVRITY_MLFP		0x00040000
+#define PCIE_UC_SERVRITY_ECRC		0x00080000
+#define PCIE_UC_SERVRITY_UR		0x00100000
+
+#define REG_DEV_SERIALNUM_CTRL		0x200
+#define REG_DEV_MAC_SEL_MASK		0x0 /* 0:EUI; 1:MAC */
+#define REG_DEV_MAC_SEL_SHIFT		0
+#define REG_DEV_SERIAL_NUM_EN_MASK	0x1
+#define REG_DEV_SERIAL_NUM_EN_SHIFT	1
+
+#define REG_TWSI_CTRL               	0x218
+#define TWSI_CTRL_LD_OFFSET_MASK        0xFF
+#define TWSI_CTRL_LD_OFFSET_SHIFT       0
+#define TWSI_CTRL_LD_SLV_ADDR_MASK      0x7
+#define TWSI_CTRL_LD_SLV_ADDR_SHIFT     8
+#define TWSI_CTRL_SW_LDSTART            0x800
+#define TWSI_CTRL_HW_LDSTART            0x1000
+#define TWSI_CTRL_SMB_SLV_ADDR_MASK     0x7F
+#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT    15
+#define TWSI_CTRL_LD_EXIST              0x400000
+#define TWSI_CTRL_READ_FREQ_SEL_MASK    0x3
+#define TWSI_CTRL_READ_FREQ_SEL_SHIFT   23
+#define TWSI_CTRL_FREQ_SEL_100K         0
+#define TWSI_CTRL_FREQ_SEL_200K         1
+#define TWSI_CTRL_FREQ_SEL_300K         2
+#define TWSI_CTRL_FREQ_SEL_400K         3
+#define TWSI_CTRL_SMB_SLV_ADDR
+#define TWSI_CTRL_WRITE_FREQ_SEL_MASK   0x3
+#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT  24
+
+
+#define REG_PCIE_DEV_MISC_CTRL      	0x21C
+#define PCIE_DEV_MISC_EXT_PIPE     	0x2
+#define PCIE_DEV_MISC_RETRY_BUFDIS 	0x1
+#define PCIE_DEV_MISC_SPIROM_EXIST 	0x4
+#define PCIE_DEV_MISC_SERDES_ENDIAN    	0x8
+#define PCIE_DEV_MISC_SERDES_SEL_DIN   	0x10
+
+#define REG_PCIE_PHYMISC	    	0x1000
+#define PCIE_PHYMISC_FORCE_RCV_DET	0x4
+
+#define REG_PCIE_PHYMISC2		0x1004
+#define PCIE_PHYMISC2_SERDES_CDR_MASK	0x3
+#define PCIE_PHYMISC2_SERDES_CDR_SHIFT	16
+#define PCIE_PHYMISC2_SERDES_TH_MASK	0x3
+#define PCIE_PHYMISC2_SERDES_TH_SHIFT	18
+
+#define REG_TWSI_DEBUG			0x1108
+#define TWSI_DEBUG_DEV_EXIST		0x20000000
+
+#define REG_EEPROM_CTRL			0x12C0
+#define EEPROM_CTRL_DATA_HI_MASK	0xFFFF
+#define EEPROM_CTRL_DATA_HI_SHIFT	0
+#define EEPROM_CTRL_ADDR_MASK		0x3FF
+#define EEPROM_CTRL_ADDR_SHIFT		16
+#define EEPROM_CTRL_ACK			0x40000000
+#define EEPROM_CTRL_RW			0x80000000
+
+#define REG_EEPROM_DATA_LO		0x12C4
+
+#define REG_OTP_CTRL			0x12F0
+#define OTP_CTRL_CLK_EN			0x0002
+
+#define REG_PM_CTRL			0x12F8
+#define PM_CTRL_SDES_EN			0x00000001
+#define PM_CTRL_RBER_EN			0x00000002
+#define PM_CTRL_CLK_REQ_EN		0x00000004
+#define PM_CTRL_ASPM_L1_EN		0x00000008
+#define PM_CTRL_SERDES_L1_EN		0x00000010
+#define PM_CTRL_SERDES_PLL_L1_EN	0x00000020
+#define PM_CTRL_SERDES_PD_EX_L1		0x00000040
+#define PM_CTRL_SERDES_BUDS_RX_L1_EN	0x00000080
+#define PM_CTRL_L0S_ENTRY_TIMER_MASK	0xF
+#define PM_CTRL_L0S_ENTRY_TIMER_SHIFT	8
+#define PM_CTRL_ASPM_L0S_EN		0x00001000
+#define PM_CTRL_CLK_SWH_L1		0x00002000
+#define PM_CTRL_CLK_PWM_VER1_1		0x00004000
+#define PM_CTRL_RCVR_WT_TIMER		0x00008000
+#define PM_CTRL_L1_ENTRY_TIMER_MASK	0xF
+#define PM_CTRL_L1_ENTRY_TIMER_SHIFT	16
+#define PM_CTRL_PM_REQ_TIMER_MASK	0xF
+#define PM_CTRL_PM_REQ_TIMER_SHIFT	20
+#define PM_CTRL_LCKDET_TIMER_MASK	0xF
+#define PM_CTRL_LCKDET_TIMER_SHIFT	24
+#define PM_CTRL_EN_BUFS_RX_L0S		0x10000000
+#define PM_CTRL_SA_DLY_EN		0x20000000
+#define PM_CTRL_MAC_ASPM_CHK		0x40000000
+#define PM_CTRL_HOTRST			0x80000000
+
+#define REG_LTSSM_ID_CTRL		0x12FC
+#define LTSSM_ID_EN_WRO			0x1000
+/* Selene Master Control Register */
+#define REG_MASTER_CTRL			0x1400
+#define MASTER_CTRL_SOFT_RST            0x1
+#define MASTER_CTRL_TEST_MODE_MASK	0x3
+#define MASTER_CTRL_TEST_MODE_SHIFT	2
+#define MASTER_CTRL_BERT_START		0x10
+#define MASTER_CTRL_OOB_DIS_OFF		0x40
+#define MASTER_CTRL_SA_TIMER_EN		0x80
+#define MASTER_CTRL_MTIMER_EN           0x100
+#define MASTER_CTRL_MANUAL_INT          0x200
+#define MASTER_CTRL_TX_ITIMER_EN	0x400
+#define MASTER_CTRL_RX_ITIMER_EN	0x800
+#define MASTER_CTRL_CLK_SEL_DIS		0x1000
+#define MASTER_CTRL_CLK_SWH_MODE	0x2000
+#define MASTER_CTRL_INT_RDCLR		0x4000
+#define MASTER_CTRL_REV_NUM_SHIFT	16
+#define MASTER_CTRL_REV_NUM_MASK	0xff
+#define MASTER_CTRL_DEV_ID_SHIFT	24
+#define MASTER_CTRL_DEV_ID_MASK		0x7f
+#define MASTER_CTRL_OTP_SEL		0x80000000
+
+/* Timer Initial Value Register */
+#define REG_MANUAL_TIMER_INIT       	0x1404
+
+/* IRQ ModeratorTimer Initial Value Register */
+#define REG_IRQ_MODRT_TIMER_INIT     	0x1408
+#define IRQ_MODRT_TIMER_MASK		0xffff
+#define IRQ_MODRT_TX_TIMER_SHIFT    	0
+#define IRQ_MODRT_RX_TIMER_SHIFT	16
+
+#define REG_GPHY_CTRL               	0x140C
+#define GPHY_CTRL_EXT_RESET         	0x1
+#define GPHY_CTRL_RTL_MODE		0x2
+#define GPHY_CTRL_LED_MODE		0x4
+#define GPHY_CTRL_ANEG_NOW		0x8
+#define GPHY_CTRL_REV_ANEG		0x10
+#define GPHY_CTRL_GATE_25M_EN       	0x20
+#define GPHY_CTRL_LPW_EXIT          	0x40
+#define GPHY_CTRL_PHY_IDDQ          	0x80
+#define GPHY_CTRL_PHY_IDDQ_DIS      	0x100
+#define GPHY_CTRL_GIGA_DIS		0x200
+#define GPHY_CTRL_HIB_EN            	0x400
+#define GPHY_CTRL_HIB_PULSE         	0x800
+#define GPHY_CTRL_SEL_ANA_RST       	0x1000
+#define GPHY_CTRL_PHY_PLL_ON        	0x2000
+#define GPHY_CTRL_PWDOWN_HW		0x4000
+#define GPHY_CTRL_PHY_PLL_BYPASS	0x8000
+
+#define GPHY_CTRL_DEFAULT (		 \
+		GPHY_CTRL_SEL_ANA_RST	|\
+		GPHY_CTRL_HIB_PULSE	|\
+		GPHY_CTRL_HIB_EN)
+
+#define GPHY_CTRL_PW_WOL_DIS (		 \
+		GPHY_CTRL_SEL_ANA_RST	|\
+		GPHY_CTRL_HIB_PULSE	|\
+		GPHY_CTRL_HIB_EN	|\
+		GPHY_CTRL_PWDOWN_HW	|\
+		GPHY_CTRL_PHY_IDDQ)
+
+#define GPHY_CTRL_POWER_SAVING (	\
+		GPHY_CTRL_SEL_ANA_RST	|\
+		GPHY_CTRL_HIB_EN	|\
+		GPHY_CTRL_HIB_PULSE	|\
+		GPHY_CTRL_PWDOWN_HW	|\
+		GPHY_CTRL_PHY_IDDQ)
+/* Block IDLE Status Register */
+#define REG_IDLE_STATUS  		0x1410
+#define IDLE_STATUS_MASK		0x00FF
+#define IDLE_STATUS_RXMAC_NO_IDLE      	0x1
+#define IDLE_STATUS_TXMAC_NO_IDLE      	0x2
+#define IDLE_STATUS_RXQ_NO_IDLE        	0x4
+#define IDLE_STATUS_TXQ_NO_IDLE        	0x8
+#define IDLE_STATUS_DMAR_NO_IDLE       	0x10
+#define IDLE_STATUS_DMAW_NO_IDLE       	0x20
+#define IDLE_STATUS_SMB_NO_IDLE        	0x40
+#define IDLE_STATUS_CMB_NO_IDLE        	0x80
+
+/* MDIO Control Register */
+#define REG_MDIO_CTRL           	0x1414
+#define MDIO_DATA_MASK          	0xffff  /* On MDIO write, the 16-bit
+						 * control data to write to PHY
+						 * MII management register */
+#define MDIO_DATA_SHIFT         	0       /* On MDIO read, the 16-bit
+						 * status data that was read
+						 * from the PHY MII management register */
+#define MDIO_REG_ADDR_MASK      	0x1f    /* MDIO register address */
+#define MDIO_REG_ADDR_SHIFT     	16
+#define MDIO_RW                 	0x200000  /* 1: read, 0: write */
+#define MDIO_SUP_PREAMBLE       	0x400000  /* Suppress preamble */
+#define MDIO_START              	0x800000  /* Write 1 to initiate the MDIO
+						   * master. And this bit is self
+						   * cleared after one cycle */
+#define MDIO_CLK_SEL_SHIFT      	24
+#define MDIO_CLK_25_4           	0
+#define MDIO_CLK_25_6           	2
+#define MDIO_CLK_25_8           	3
+#define MDIO_CLK_25_10          	4
+#define MDIO_CLK_25_14          	5
+#define MDIO_CLK_25_20          	6
+#define MDIO_CLK_25_28          	7
+#define MDIO_BUSY               	0x8000000
+#define MDIO_AP_EN              	0x10000000
+#define MDIO_WAIT_TIMES         	10
+
+/* MII PHY Status Register */
+#define REG_PHY_STATUS           	0x1418
+#define PHY_GENERAL_STATUS_MASK		0xFFFF
+#define PHY_STATUS_RECV_ENABLE		0x0001
+#define PHY_OE_PWSP_STATUS_MASK		0x07FF
+#define PHY_OE_PWSP_STATUS_SHIFT	16
+#define PHY_STATUS_LPW_STATE		0x80000000
+/* BIST Control and Status Register0 (for the Packet Memory) */
+#define REG_BIST0_CTRL              	0x141c
+#define BIST0_NOW                   	0x1
+#define BIST0_SRAM_FAIL             	0x2 /* 1: The SRAM failure is
+					     * un-repairable  because
+					     * it has address decoder
+					     * failure or more than 1 cell
+					     * stuck-to-x failure */
+#define BIST0_FUSE_FLAG             	0x4
+
+/* BIST Control and Status Register1(for the retry buffer of PCI Express) */
+#define REG_BIST1_CTRL			0x1420
+#define BIST1_NOW                   	0x1
+#define BIST1_SRAM_FAIL             	0x2
+#define BIST1_FUSE_FLAG             	0x4
+
+/* SerDes Lock Detect Control and Status Register */
+#define REG_SERDES_LOCK            	0x1424
+#define SERDES_LOCK_DETECT          	0x1  /* SerDes lock detected. This signal
+					      * comes from Analog SerDes */
+#define SERDES_LOCK_DETECT_EN       	0x2  /* 1: Enable SerDes Lock detect function */
+#define SERDES_LOCK_STS_SELFB_PLL_SHIFT 0xE
+#define SERDES_LOCK_STS_SELFB_PLL_MASK  0x3
+#define SERDES_OVCLK_18_25		0x0
+#define SERDES_OVCLK_12_18		0x1
+#define SERDES_OVCLK_0_4		0x2
+#define SERDES_OVCLK_4_12		0x3
+#define SERDES_MAC_CLK_SLOWDOWN		0x20000
+#define SERDES_PYH_CLK_SLOWDOWN		0x40000
+
+/* MAC Control Register  */
+#define REG_MAC_CTRL         		0x1480
+#define MAC_CTRL_TX_EN			0x1
+#define MAC_CTRL_RX_EN			0x2
+#define MAC_CTRL_TX_FLOW		0x4
+#define MAC_CTRL_RX_FLOW            	0x8
+#define MAC_CTRL_LOOPBACK          	0x10
+#define MAC_CTRL_DUPLX              	0x20
+#define MAC_CTRL_ADD_CRC            	0x40
+#define MAC_CTRL_PAD                	0x80
+#define MAC_CTRL_LENCHK             	0x100
+#define MAC_CTRL_HUGE_EN            	0x200
+#define MAC_CTRL_PRMLEN_SHIFT       	10
+#define MAC_CTRL_PRMLEN_MASK        	0xf
+#define MAC_CTRL_RMV_VLAN           	0x4000
+#define MAC_CTRL_PROMIS_EN          	0x8000
+#define MAC_CTRL_TX_PAUSE           	0x10000
+#define MAC_CTRL_SCNT               	0x20000
+#define MAC_CTRL_SRST_TX            	0x40000
+#define MAC_CTRL_TX_SIMURST         	0x80000
+#define MAC_CTRL_SPEED_SHIFT        	20
+#define MAC_CTRL_SPEED_MASK         	0x3
+#define MAC_CTRL_DBG_TX_BKPRESURE   	0x400000
+#define MAC_CTRL_TX_HUGE            	0x800000
+#define MAC_CTRL_RX_CHKSUM_EN       	0x1000000
+#define MAC_CTRL_MC_ALL_EN          	0x2000000
+#define MAC_CTRL_BC_EN              	0x4000000
+#define MAC_CTRL_DBG                	0x8000000
+#define MAC_CTRL_SINGLE_PAUSE_EN	0x10000000
+#define MAC_CTRL_HASH_ALG_CRC32		0x20000000
+#define MAC_CTRL_SPEED_MODE_SW		0x40000000
+
+/* MAC IPG/IFG Control Register  */
+#define REG_MAC_IPG_IFG             	0x1484
+#define MAC_IPG_IFG_IPGT_SHIFT      	0 	/* Desired back to back
+						 * inter-packet gap. The
+						 * default is 96-bit time */
+#define MAC_IPG_IFG_IPGT_MASK       	0x7f
+#define MAC_IPG_IFG_MIFG_SHIFT      	8       /* Minimum number of IFG to
+						 * enforce in between RX frames */
+#define MAC_IPG_IFG_MIFG_MASK       	0xff  	/* Frame gap below such IFP is dropped */
+#define MAC_IPG_IFG_IPGR1_SHIFT     	16   	/* 64bit Carrier-Sense window */
+#define MAC_IPG_IFG_IPGR1_MASK      	0x7f
+#define MAC_IPG_IFG_IPGR2_SHIFT     	24    	/* 96-bit IPG window */
+#define MAC_IPG_IFG_IPGR2_MASK      	0x7f
+
+/* MAC STATION ADDRESS  */
+#define REG_MAC_STA_ADDR		0x1488
+
+/* Hash table for multicast address */
+#define REG_RX_HASH_TABLE		0x1490
+
+/* MAC Half-Duplex Control Register */
+#define REG_MAC_HALF_DUPLX_CTRL     	0x1498
+#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT  0      /* Collision Window */
+#define MAC_HALF_DUPLX_CTRL_LCOL_MASK   0x3ff
+#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12
+#define MAC_HALF_DUPLX_CTRL_RETRY_MASK  0xf
+#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN  0x10000
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_C   0x20000
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_P   0x40000 /* No back-off on backpressure,
+						 * immediately start the
+						 * transmission after back pressure */
+#define MAC_HALF_DUPLX_CTRL_ABEBE        0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */
+#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT  20      /* Maximum binary exponential number */
+#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK   0xf
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24      /* IPG to start JAM for collision based flow control in half-duplex */
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK  0xf     /* mode. In unit of 8-bit time */
+
+/* Maximum Frame Length Control Register   */
+#define REG_MTU                     	0x149c
+
+/* Wake-On-Lan control register */
+#define REG_WOL_CTRL                	0x14a0
+#define WOL_PATTERN_EN              	0x00000001
+#define WOL_PATTERN_PME_EN              0x00000002
+#define WOL_MAGIC_EN                    0x00000004
+#define WOL_MAGIC_PME_EN                0x00000008
+#define WOL_LINK_CHG_EN                 0x00000010
+#define WOL_LINK_CHG_PME_EN             0x00000020
+#define WOL_PATTERN_ST                  0x00000100
+#define WOL_MAGIC_ST                    0x00000200
+#define WOL_LINKCHG_ST                  0x00000400
+#define WOL_CLK_SWITCH_EN               0x00008000
+#define WOL_PT0_EN                      0x00010000
+#define WOL_PT1_EN                      0x00020000
+#define WOL_PT2_EN                      0x00040000
+#define WOL_PT3_EN                      0x00080000
+#define WOL_PT4_EN                      0x00100000
+#define WOL_PT5_EN                      0x00200000
+#define WOL_PT6_EN                      0x00400000
+
+/* WOL Length ( 2 DWORD ) */
+#define REG_WOL_PATTERN_LEN         	0x14a4
+#define WOL_PT_LEN_MASK                 0x7f
+#define WOL_PT0_LEN_SHIFT               0
+#define WOL_PT1_LEN_SHIFT               8
+#define WOL_PT2_LEN_SHIFT               16
+#define WOL_PT3_LEN_SHIFT               24
+#define WOL_PT4_LEN_SHIFT               0
+#define WOL_PT5_LEN_SHIFT               8
+#define WOL_PT6_LEN_SHIFT               16
+
+/* Internal SRAM Partition Register */
+#define RFDX_HEAD_ADDR_MASK		0x03FF
+#define RFDX_HARD_ADDR_SHIFT		0
+#define RFDX_TAIL_ADDR_MASK		0x03FF
+#define RFDX_TAIL_ADDR_SHIFT            16
+
+#define REG_SRAM_RFD0_INFO		0x1500
+#define REG_SRAM_RFD1_INFO		0x1504
+#define REG_SRAM_RFD2_INFO		0x1508
+#define	REG_SRAM_RFD3_INFO		0x150C
+
+#define REG_RFD_NIC_LEN			0x1510 /* In 8-bytes */
+#define RFD_NIC_LEN_MASK		0x03FF
+
+#define REG_SRAM_TRD_ADDR           	0x1518
+#define TPD_HEAD_ADDR_MASK		0x03FF
+#define TPD_HEAD_ADDR_SHIFT		0
+#define TPD_TAIL_ADDR_MASK		0x03FF
+#define TPD_TAIL_ADDR_SHIFT		16
+
+#define REG_SRAM_TRD_LEN            	0x151C /* In 8-bytes */
+#define TPD_NIC_LEN_MASK		0x03FF
+
+#define REG_SRAM_RXF_ADDR          	0x1520
+#define REG_SRAM_RXF_LEN            	0x1524
+#define REG_SRAM_TXF_ADDR           	0x1528
+#define REG_SRAM_TXF_LEN            	0x152C
+#define REG_SRAM_TCPH_ADDR          	0x1530
+#define REG_SRAM_PKTH_ADDR          	0x1532
+
+/*
+ * Load Ptr Register
+ * Software sets this bit after the initialization of the head and tail */
+#define REG_LOAD_PTR                	0x1534
+
+/*
+ * addresses of all descriptors, as well as the following descriptor
+ * control register, which triggers each function block to load the head
+ * pointer to prepare for the operation. This bit is then self-cleared
+ * after one cycle.
+ */
+#define REG_RX_BASE_ADDR_HI		0x1540
+#define REG_TX_BASE_ADDR_HI		0x1544
+#define REG_SMB_BASE_ADDR_HI		0x1548
+#define REG_SMB_BASE_ADDR_LO		0x154C
+#define REG_RFD0_HEAD_ADDR_LO		0x1550
+#define REG_RFD1_HEAD_ADDR_LO		0x1554
+#define REG_RFD2_HEAD_ADDR_LO		0x1558
+#define REG_RFD3_HEAD_ADDR_LO		0x155C
+#define REG_RFD_RING_SIZE		0x1560
+#define RFD_RING_SIZE_MASK		0x0FFF
+#define REG_RX_BUF_SIZE			0x1564
+#define RX_BUF_SIZE_MASK		0xFFFF
+#define REG_RRD0_HEAD_ADDR_LO		0x1568
+#define REG_RRD1_HEAD_ADDR_LO		0x156C
+#define REG_RRD2_HEAD_ADDR_LO		0x1570
+#define REG_RRD3_HEAD_ADDR_LO		0x1574
+#define REG_RRD_RING_SIZE		0x1578
+#define RRD_RING_SIZE_MASK		0x0FFF
+#define REG_HTPD_HEAD_ADDR_LO		0x157C
+#define REG_NTPD_HEAD_ADDR_LO		0x1580
+#define REG_TPD_RING_SIZE		0x1584
+#define TPD_RING_SIZE_MASK		0xFFFF
+#define REG_CMB_BASE_ADDR_LO		0x1588
+
+/* RSS about */
+#define REG_RSS_KEY0                    0x14B0
+#define REG_RSS_KEY1                    0x14B4
+#define REG_RSS_KEY2                    0x14B8
+#define REG_RSS_KEY3                    0x14BC
+#define REG_RSS_KEY4                    0x14C0
+#define REG_RSS_KEY5                    0x14C4
+#define REG_RSS_KEY6                    0x14C8
+#define REG_RSS_KEY7                    0x14CC
+#define REG_RSS_KEY8                    0x14D0
+#define REG_RSS_KEY9                    0x14D4
+#define REG_IDT_TABLE0                	0x14E0
+#define REG_IDT_TABLE1                  0x14E4
+#define REG_IDT_TABLE2                  0x14E8
+#define REG_IDT_TABLE3                  0x14EC
+#define REG_IDT_TABLE4                  0x14F0
+#define REG_IDT_TABLE5                  0x14F4
+#define REG_IDT_TABLE6                  0x14F8
+#define REG_IDT_TABLE7                  0x14FC
+#define REG_IDT_TABLE                   REG_IDT_TABLE0
+#define REG_RSS_HASH_VALUE              0x15B0
+#define REG_RSS_HASH_FLAG               0x15B4
+#define REG_BASE_CPU_NUMBER             0x15B8
+
+/* TXQ Control Register */
+#define REG_TXQ_CTRL                	0x1590
+#define	TXQ_NUM_TPD_BURST_MASK     	0xF
+#define TXQ_NUM_TPD_BURST_SHIFT    	0
+#define TXQ_CTRL_IP_OPTION_EN		0x10
+#define TXQ_CTRL_EN                     0x20
+#define TXQ_CTRL_ENH_MODE               0x40
+#define TXQ_CTRL_LS_8023_EN		0x80
+#define TXQ_TXF_BURST_NUM_SHIFT    	16
+#define TXQ_TXF_BURST_NUM_MASK     	0xFFFF
+
+/* Jumbo packet Threshold for task offload */
+#define REG_TX_TSO_OFFLOAD_THRESH	0x1594 /* In 8-bytes */
+#define TX_TSO_OFFLOAD_THRESH_MASK	0x07FF
+
+#define	REG_TXF_WATER_MARK		0x1598 /* In 8-bytes */
+#define TXF_WATER_MARK_MASK		0x0FFF
+#define TXF_LOW_WATER_MARK_SHIFT	0
+#define TXF_HIGH_WATER_MARK_SHIFT 	16
+#define TXQ_CTRL_BURST_MODE_EN		0x80000000
+
+#define REG_THRUPUT_MON_CTRL		0x159C
+#define THRUPUT_MON_RATE_MASK		0x3
+#define THRUPUT_MON_RATE_SHIFT		0
+#define THRUPUT_MON_EN			0x80
+
+/* RXQ Control Register */
+#define REG_RXQ_CTRL                	0x15A0
+#define ASPM_THRUPUT_LIMIT_MASK		0x3
+#define ASPM_THRUPUT_LIMIT_SHIFT	0
+#define ASPM_THRUPUT_LIMIT_NO		0x00
+#define ASPM_THRUPUT_LIMIT_1M		0x01
+#define ASPM_THRUPUT_LIMIT_10M		0x02
+#define ASPM_THRUPUT_LIMIT_100M		0x04
+#define RXQ1_CTRL_EN			0x10
+#define RXQ2_CTRL_EN			0x20
+#define RXQ3_CTRL_EN			0x40
+#define IPV6_CHKSUM_CTRL_EN		0x80
+#define RSS_HASH_BITS_MASK		0x00FF
+#define RSS_HASH_BITS_SHIFT		8
+#define RSS_HASH_IPV4			0x10000
+#define RSS_HASH_IPV4_TCP		0x20000
+#define RSS_HASH_IPV6			0x40000
+#define RSS_HASH_IPV6_TCP		0x80000
+#define RXQ_RFD_BURST_NUM_MASK		0x003F
+#define RXQ_RFD_BURST_NUM_SHIFT		20
+#define RSS_MODE_MASK			0x0003
+#define RSS_MODE_SHIFT			26
+#define RSS_NIP_QUEUE_SEL_MASK		0x1
+#define RSS_NIP_QUEUE_SEL_SHIFT		28
+#define RRS_HASH_CTRL_EN		0x20000000
+#define RX_CUT_THRU_EN			0x40000000
+#define RXQ_CTRL_EN			0x80000000
+
+#define REG_RFD_FREE_THRESH		0x15A4
+#define RFD_FREE_THRESH_MASK		0x003F
+#define RFD_FREE_HI_THRESH_SHIFT	0
+#define RFD_FREE_LO_THRESH_SHIFT	6
+
+/* RXF flow control register */
+#define REG_RXQ_RXF_PAUSE_THRESH    	0x15A8
+#define RXQ_RXF_PAUSE_TH_HI_SHIFT       0
+#define RXQ_RXF_PAUSE_TH_HI_MASK        0x0FFF
+#define RXQ_RXF_PAUSE_TH_LO_SHIFT       16
+#define RXQ_RXF_PAUSE_TH_LO_MASK        0x0FFF
+
+#define REG_RXD_DMA_CTRL		0x15AC
+#define RXD_DMA_THRESH_MASK		0x0FFF	/* In 8-bytes */
+#define RXD_DMA_THRESH_SHIFT		0
+#define RXD_DMA_DOWN_TIMER_MASK		0xFFFF
+#define RXD_DMA_DOWN_TIMER_SHIFT	16
+
+/* DMA Engine Control Register */
+#define REG_DMA_CTRL                	0x15C0
+#define DMA_CTRL_DMAR_IN_ORDER          0x1
+#define DMA_CTRL_DMAR_ENH_ORDER         0x2
+#define DMA_CTRL_DMAR_OUT_ORDER         0x4
+#define DMA_CTRL_RCB_VALUE              0x8
+#define DMA_CTRL_DMAR_BURST_LEN_MASK    0x0007
+#define DMA_CTRL_DMAR_BURST_LEN_SHIFT   4
+#define DMA_CTRL_DMAW_BURST_LEN_MASK    0x0007
+#define DMA_CTRL_DMAW_BURST_LEN_SHIFT   7
+#define DMA_CTRL_DMAR_REQ_PRI           0x400
+#define DMA_CTRL_DMAR_DLY_CNT_MASK      0x001F
+#define DMA_CTRL_DMAR_DLY_CNT_SHIFT     11
+#define DMA_CTRL_DMAW_DLY_CNT_MASK      0x000F
+#define DMA_CTRL_DMAW_DLY_CNT_SHIFT     16
+#define DMA_CTRL_CMB_EN               	0x100000
+#define DMA_CTRL_SMB_EN			0x200000
+#define DMA_CTRL_CMB_NOW		0x400000
+#define MAC_CTRL_SMB_DIS		0x1000000
+#define DMA_CTRL_SMB_NOW		0x80000000
+
+/* CMB/SMB Control Register */
+#define REG_SMB_STAT_TIMER		0x15C4	/* 2us resolution */
+#define SMB_STAT_TIMER_MASK		0xFFFFFF
+#define REG_CMB_TPD_THRESH		0x15C8
+#define CMB_TPD_THRESH_MASK		0xFFFF
+#define REG_CMB_TX_TIMER		0x15CC	/* 2us resolution */
+#define CMB_TX_TIMER_MASK		0xFFFF
+
+/* Mail box */
+#define MB_RFDX_PROD_IDX_MASK		0xFFFF
+#define REG_MB_RFD0_PROD_IDX		0x15E0
+#define REG_MB_RFD1_PROD_IDX		0x15E4
+#define REG_MB_RFD2_PROD_IDX		0x15E8
+#define REG_MB_RFD3_PROD_IDX		0x15EC
+
+#define MB_PRIO_PROD_IDX_MASK		0xFFFF
+#define REG_MB_PRIO_PROD_IDX		0x15F0
+#define MB_HTPD_PROD_IDX_SHIFT		0
+#define MB_NTPD_PROD_IDX_SHIFT		16
+
+#define MB_PRIO_CONS_IDX_MASK		0xFFFF
+#define REG_MB_PRIO_CONS_IDX		0x15F4
+#define MB_HTPD_CONS_IDX_SHIFT		0
+#define MB_NTPD_CONS_IDX_SHIFT		16
+
+#define REG_MB_RFD01_CONS_IDX		0x15F8
+#define MB_RFD0_CONS_IDX_MASK		0x0000FFFF
+#define MB_RFD1_CONS_IDX_MASK		0xFFFF0000
+#define REG_MB_RFD23_CONS_IDX		0x15FC
+#define MB_RFD2_CONS_IDX_MASK		0x0000FFFF
+#define MB_RFD3_CONS_IDX_MASK		0xFFFF0000
+
+/* Interrupt Status Register */
+#define REG_ISR    			0x1600
+#define ISR_SMB				0x00000001
+#define ISR_TIMER			0x00000002
+/*
+ * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set
+ * in Table 51 Selene Master Control Register (Offset 0x1400).
+ */
+#define ISR_MANUAL         		0x00000004
+#define ISR_HW_RXF_OV          		0x00000008 /* RXF overflow interrupt */
+#define ISR_RFD0_UR			0x00000010 /* RFD0 under run */
+#define ISR_RFD1_UR			0x00000020
+#define ISR_RFD2_UR			0x00000040
+#define ISR_RFD3_UR			0x00000080
+#define ISR_TXF_UR			0x00000100
+#define ISR_DMAR_TO_RST			0x00000200
+#define ISR_DMAW_TO_RST			0x00000400
+#define ISR_TX_CREDIT			0x00000800
+#define ISR_GPHY			0x00001000
+/* GPHY low power state interrupt */
+#define ISR_GPHY_LPW           		0x00002000
+#define ISR_TXQ_TO_RST			0x00004000
+#define ISR_TX_PKT			0x00008000
+#define ISR_RX_PKT_0			0x00010000
+#define ISR_RX_PKT_1			0x00020000
+#define ISR_RX_PKT_2			0x00040000
+#define ISR_RX_PKT_3			0x00080000
+#define ISR_MAC_RX			0x00100000
+#define ISR_MAC_TX			0x00200000
+#define ISR_UR_DETECTED			0x00400000
+#define ISR_FERR_DETECTED		0x00800000
+#define ISR_NFERR_DETECTED		0x01000000
+#define ISR_CERR_DETECTED		0x02000000
+#define ISR_PHY_LINKDOWN		0x04000000
+#define ISR_DIS_INT			0x80000000
+
+/* Interrupt Mask Register */
+#define REG_IMR				0x1604
+
+#define IMR_NORMAL_MASK		(\
+		ISR_MANUAL	|\
+		ISR_HW_RXF_OV	|\
+		ISR_RFD0_UR	|\
+		ISR_TXF_UR	|\
+		ISR_DMAR_TO_RST	|\
+		ISR_TXQ_TO_RST  |\
+		ISR_DMAW_TO_RST	|\
+		ISR_GPHY	|\
+		ISR_TX_PKT	|\
+		ISR_RX_PKT_0	|\
+		ISR_GPHY_LPW    |\
+		ISR_PHY_LINKDOWN)
+
+#define ISR_RX_PKT 	(\
+	ISR_RX_PKT_0    |\
+	ISR_RX_PKT_1    |\
+	ISR_RX_PKT_2    |\
+	ISR_RX_PKT_3)
+
+#define ISR_OVER	(\
+	ISR_RFD0_UR 	|\
+	ISR_RFD1_UR	|\
+	ISR_RFD2_UR	|\
+	ISR_RFD3_UR	|\
+	ISR_HW_RXF_OV	|\
+	ISR_TXF_UR)
+
+#define ISR_ERROR	(\
+	ISR_DMAR_TO_RST	|\
+	ISR_TXQ_TO_RST  |\
+	ISR_DMAW_TO_RST	|\
+	ISR_PHY_LINKDOWN)
+
+#define REG_INT_RETRIG_TIMER		0x1608
+#define INT_RETRIG_TIMER_MASK		0xFFFF
+
+#define REG_HDS_CTRL			0x160C
+#define HDS_CTRL_EN			0x0001
+#define HDS_CTRL_BACKFILLSIZE_SHIFT	8
+#define HDS_CTRL_BACKFILLSIZE_MASK	0x0FFF
+#define HDS_CTRL_MAX_HDRSIZE_SHIFT	20
+#define HDS_CTRL_MAC_HDRSIZE_MASK	0x0FFF
+
+#define REG_MAC_RX_STATUS_BIN 		0x1700
+#define REG_MAC_RX_STATUS_END 		0x175c
+#define REG_MAC_TX_STATUS_BIN 		0x1760
+#define REG_MAC_TX_STATUS_END 		0x17c0
+
+#define REG_CLK_GATING_CTRL		0x1814
+#define CLK_GATING_DMAW_EN		0x0001
+#define CLK_GATING_DMAR_EN		0x0002
+#define CLK_GATING_TXQ_EN		0x0004
+#define CLK_GATING_RXQ_EN		0x0008
+#define CLK_GATING_TXMAC_EN		0x0010
+#define CLK_GATING_RXMAC_EN		0x0020
+
+#define CLK_GATING_EN_ALL	(CLK_GATING_DMAW_EN |\
+				 CLK_GATING_DMAR_EN |\
+				 CLK_GATING_TXQ_EN  |\
+				 CLK_GATING_RXQ_EN  |\
+				 CLK_GATING_TXMAC_EN|\
+				 CLK_GATING_RXMAC_EN)
+
+/* DEBUG ADDR */
+#define REG_DEBUG_DATA0 		0x1900
+#define REG_DEBUG_DATA1 		0x1904
+
+#define L1D_MPW_PHYID1			0xD01C  /* V7 */
+#define L1D_MPW_PHYID2			0xD01D  /* V1-V6 */
+#define L1D_MPW_PHYID3			0xD01E  /* V8 */
+
+
+/* Autoneg Advertisement Register */
+#define ADVERTISE_DEFAULT_CAP \
+	(ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)
+
+/* 1000BASE-T Control Register */
+#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 */
+#define GIGA_CR_1000T_MS_ENABLE		0x1000  /* 1=Master/Slave manual config value 0=Automatic Master/Slave config */
+#define GIGA_CR_1000T_TEST_MODE_NORMAL	0x0000  /* Normal Operation */
+#define GIGA_CR_1000T_TEST_MODE_1	0x2000  /* Transmit Waveform test */
+#define GIGA_CR_1000T_TEST_MODE_2	0x4000  /* Master Transmit Jitter test */
+#define GIGA_CR_1000T_TEST_MODE_3	0x6000  /* Slave Transmit Jitter test */
+#define GIGA_CR_1000T_TEST_MODE_4	0x8000	/* Transmitter Distortion test */
+#define GIGA_CR_1000T_SPEED_MASK	0x0300
+#define GIGA_CR_1000T_DEFAULT_CAP	0x0300
+
+/* PHY Specific Status Register */
+#define MII_GIGA_PSSR			0x11
+#define GIGA_PSSR_SPD_DPLX_RESOLVED	0x0800  /* 1=Speed & Duplex resolved */
+#define GIGA_PSSR_DPLX			0x2000  /* 1=Duplex 0=Half Duplex */
+#define GIGA_PSSR_SPEED			0xC000  /* Speed, bits 14:15 */
+#define GIGA_PSSR_10MBS			0x0000  /* 00=10Mbs */
+#define GIGA_PSSR_100MBS		0x4000  /* 01=100Mbs */
+#define GIGA_PSSR_1000MBS		0x8000  /* 10=1000Mbs */
+
+/* PHY Interrupt Enable Register */
+#define MII_IER				0x12
+#define IER_LINK_UP			0x0400
+#define IER_LINK_DOWN			0x0800
+
+/* PHY Interrupt Status Register */
+#define MII_ISR				0x13
+#define ISR_LINK_UP			0x0400
+#define ISR_LINK_DOWN			0x0800
+
+/* Cable-Detect-Test Control Register */
+#define MII_CDTC			0x16
+#define CDTC_EN_OFF			0   /* sc */
+#define CDTC_EN_BITS			1
+#define CDTC_PAIR_OFF			8
+#define CDTC_PAIR_BIT			2
+
+/* Cable-Detect-Test Status Register */
+#define MII_CDTS			0x1C
+#define CDTS_STATUS_OFF			8
+#define CDTS_STATUS_BITS		2
+#define CDTS_STATUS_NORMAL		0
+#define CDTS_STATUS_SHORT		1
+#define CDTS_STATUS_OPEN		2
+#define CDTS_STATUS_INVALID		3
+
+#define MII_DBG_ADDR			0x1D
+#define MII_DBG_DATA			0x1E
+
+#define MII_ANA_CTRL_0			0x0
+#define ANA_RESTART_CAL			0x0001
+#define ANA_MANUL_SWICH_ON_SHIFT	0x1
+#define ANA_MANUL_SWICH_ON_MASK		0xF
+#define ANA_MAN_ENABLE			0x0020
+#define ANA_SEL_HSP			0x0040
+#define ANA_EN_HB			0x0080
+#define ANA_EN_HBIAS			0x0100
+#define ANA_OEN_125M			0x0200
+#define ANA_EN_LCKDT			0x0400
+#define ANA_LCKDT_PHY			0x0800
+#define ANA_AFE_MODE			0x1000
+#define ANA_VCO_SLOW			0x2000
+#define ANA_VCO_FAST			0x4000
+#define ANA_SEL_CLK125M_DSP		0x8000
+
+#define MII_ANA_CTRL_4			0x4
+#define ANA_IECHO_ADJ_MASK		0xF
+#define ANA_IECHO_ADJ_3_SHIFT		0
+#define ANA_IECHO_ADJ_2_SHIFT		4
+#define ANA_IECHO_ADJ_1_SHIFT		8
+#define ANA_IECHO_ADJ_0_SHIFT		12
+
+#define MII_ANA_CTRL_5			0x5
+#define ANA_SERDES_CDR_BW_SHIFT		0
+#define ANA_SERDES_CDR_BW_MASK		0x3
+#define ANA_MS_PAD_DBG			0x0004
+#define ANA_SPEEDUP_DBG			0x0008
+#define ANA_SERDES_TH_LOS_SHIFT		4
+#define ANA_SERDES_TH_LOS_MASK		0x3
+#define ANA_SERDES_EN_DEEM		0x0040
+#define ANA_SERDES_TXELECIDLE		0x0080
+#define ANA_SERDES_BEACON		0x0100
+#define ANA_SERDES_HALFTXDR		0x0200
+#define ANA_SERDES_SEL_HSP		0x0400
+#define ANA_SERDES_EN_PLL		0x0800
+#define ANA_SERDES_EN			0x1000
+#define ANA_SERDES_EN_LCKDT		0x2000
+
+#define MII_ANA_CTRL_11			0xB
+#define ANA_PS_HIB_EN			0x8000
+
+#define MII_ANA_CTRL_18			0x12
+#define ANA_TEST_MODE_10BT_01SHIFT	0
+#define ANA_TEST_MODE_10BT_01MASK	0x3
+#define ANA_LOOP_SEL_10BT		0x0004
+#define ANA_RGMII_MODE_SW		0x0008
+#define ANA_EN_LONGECABLE		0x0010
+#define ANA_TEST_MODE_10BT_2		0x0020
+#define ANA_EN_10BT_IDLE		0x0400
+#define ANA_EN_MASK_TB			0x0800
+#define ANA_TRIGGER_SEL_TIMER_SHIFT	12
+#define ANA_TRIGGER_SEL_TIMER_MASK	0x3
+#define ANA_INTERVAL_SEL_TIMER_SHIFT	14
+#define ANA_INTERVAL_SEL_TIMER_MASK	0x3
+
+#define MII_ANA_CTRL_41			0x29
+#define ANA_TOP_PS_EN			0x8000
+
+#define MII_ANA_CTRL_54			0x36
+#define ANA_LONG_CABLE_TH_100_SHIFT	0
+#define ANA_LONG_CABLE_TH_100_MASK	0x3F
+#define ANA_DESERVED			0x0040
+#define ANA_EN_LIT_CH			0x0080
+#define ANA_SHORT_CABLE_TH_100_SHIFT	8
+#define ANA_SHORT_CABLE_TH_100_MASK	0x3F
+#define ANA_BP_BAD_LINK_ACCUM		0x4000
+#define ANA_BP_SMALL_BW			0x8000
+
+#endif /*_ATL1C_HW_H_*/
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_main.c linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_main.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_main.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2933 @@
+/*
+ * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You 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 "atl1c.h"
+
+#define ATL1C_DRV_VERSION "1.0.1.0-NAPI"
+char atl1c_driver_name[] = "atl1c";
+char atl1c_driver_version[] = ATL1C_DRV_VERSION;
+#define PCI_DEVICE_ID_ATTANSIC_L2C      0x1062
+#define PCI_DEVICE_ID_ATTANSIC_L1C      0x1063
+#define PCI_DEVICE_ID_ATHEROS_L2C_B	0x2060 /* AR8152 v1.1 Fast 10/100 */
+#define PCI_DEVICE_ID_ATHEROS_L2C_B2	0x2062 /* AR8152 v2.0 Fast 10/100 */
+#define PCI_DEVICE_ID_ATHEROS_L1D	0x1073 /* AR8151 v1.0 Gigabit 1000 */
+#define PCI_DEVICE_ID_ATHEROS_L1D_2_0	0x1083 /* AR8151 v2.0 Gigabit 1000 */
+#define L2CB_V10			0xc0
+#define L2CB_V11			0xc1
+
+/*
+ * atl1c_pci_tbl - PCI Device ID Table
+ *
+ * Wildcard entries (PCI_ANY_ID) should come last
+ * Last entry must be all 0s
+ *
+ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
+ *   Class, Class Mask, private data (not used) }
+ */
+static DEFINE_PCI_DEVICE_TABLE(atl1c_pci_tbl) = {
+	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1C)},
+	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2C)},
+	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B)},
+	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B2)},
+	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L1D)},
+	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L1D_2_0)},
+	/* required last entry */
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, atl1c_pci_tbl);
+
+MODULE_AUTHOR("Jie Yang <jie.yang@atheros.com>");
+MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(ATL1C_DRV_VERSION);
+
+static int atl1c_stop_mac(struct atl1c_hw *hw);
+static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw);
+static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw);
+static void atl1c_disable_l0s_l1(struct atl1c_hw *hw);
+static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup);
+static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter);
+static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que,
+		   int *work_done, int work_to_do);
+static int atl1c_up(struct atl1c_adapter *adapter);
+static void atl1c_down(struct atl1c_adapter *adapter);
+
+static const u16 atl1c_pay_load_size[] = {
+	128, 256, 512, 1024, 2048, 4096,
+};
+
+static const u16 atl1c_rfd_prod_idx_regs[AT_MAX_RECEIVE_QUEUE] =
+{
+	REG_MB_RFD0_PROD_IDX,
+	REG_MB_RFD1_PROD_IDX,
+	REG_MB_RFD2_PROD_IDX,
+	REG_MB_RFD3_PROD_IDX
+};
+
+static const u16 atl1c_rfd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] =
+{
+	REG_RFD0_HEAD_ADDR_LO,
+	REG_RFD1_HEAD_ADDR_LO,
+	REG_RFD2_HEAD_ADDR_LO,
+	REG_RFD3_HEAD_ADDR_LO
+};
+
+static const u16 atl1c_rrd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] =
+{
+	REG_RRD0_HEAD_ADDR_LO,
+	REG_RRD1_HEAD_ADDR_LO,
+	REG_RRD2_HEAD_ADDR_LO,
+	REG_RRD3_HEAD_ADDR_LO
+};
+
+static const u32 atl1c_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
+	NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP;
+static void atl1c_pcie_patch(struct atl1c_hw *hw)
+{
+	u32 data;
+
+	AT_READ_REG(hw, REG_PCIE_PHYMISC, &data);
+	data |= PCIE_PHYMISC_FORCE_RCV_DET;
+	AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data);
+
+	if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) {
+		AT_READ_REG(hw, REG_PCIE_PHYMISC2, &data);
+
+		data &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK <<
+			PCIE_PHYMISC2_SERDES_CDR_SHIFT);
+		data |= 3 << PCIE_PHYMISC2_SERDES_CDR_SHIFT;
+		data &= ~(PCIE_PHYMISC2_SERDES_TH_MASK <<
+			PCIE_PHYMISC2_SERDES_TH_SHIFT);
+		data |= 3 << PCIE_PHYMISC2_SERDES_TH_SHIFT;
+		AT_WRITE_REG(hw, REG_PCIE_PHYMISC2, data);
+	}
+}
+
+/* FIXME: no need any more ? */
+/*
+ * atl1c_init_pcie - init PCIE module
+ */
+static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
+{
+	u32 data;
+	u32 pci_cmd;
+	struct pci_dev *pdev = hw->adapter->pdev;
+
+	AT_READ_REG(hw, PCI_COMMAND, &pci_cmd);
+	pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
+	pci_cmd |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+		PCI_COMMAND_IO);
+	AT_WRITE_REG(hw, PCI_COMMAND, pci_cmd);
+
+	/*
+	 * Clear any PowerSaveing Settings
+	 */
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_enable_wake(pdev, PCI_D3cold, 0);
+
+	/*
+	 * Mask some pcie error bits
+	 */
+	AT_READ_REG(hw, REG_PCIE_UC_SEVERITY, &data);
+	data &= ~PCIE_UC_SERVRITY_DLP;
+	data &= ~PCIE_UC_SERVRITY_FCP;
+	AT_WRITE_REG(hw, REG_PCIE_UC_SEVERITY, data);
+
+	AT_READ_REG(hw, REG_LTSSM_ID_CTRL, &data);
+	data &= ~LTSSM_ID_EN_WRO;
+	AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, data);
+
+	atl1c_pcie_patch(hw);
+	if (flag & ATL1C_PCIE_L0S_L1_DISABLE)
+		atl1c_disable_l0s_l1(hw);
+	if (flag & ATL1C_PCIE_PHY_RESET)
+		AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT);
+	else
+		AT_WRITE_REG(hw, REG_GPHY_CTRL,
+			GPHY_CTRL_DEFAULT | GPHY_CTRL_EXT_RESET);
+
+	msleep(5);
+}
+
+/*
+ * atl1c_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ */
+static inline void atl1c_irq_enable(struct atl1c_adapter *adapter)
+{
+	if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
+		AT_WRITE_REG(&adapter->hw, REG_ISR, 0x7FFFFFFF);
+		AT_WRITE_REG(&adapter->hw, REG_IMR, adapter->hw.intr_mask);
+		AT_WRITE_FLUSH(&adapter->hw);
+	}
+}
+
+/*
+ * atl1c_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1c_irq_disable(struct atl1c_adapter *adapter)
+{
+	atomic_inc(&adapter->irq_sem);
+	AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
+	AT_WRITE_REG(&adapter->hw, REG_ISR, ISR_DIS_INT);
+	AT_WRITE_FLUSH(&adapter->hw);
+	synchronize_irq(adapter->pdev->irq);
+}
+
+/*
+ * atl1c_irq_reset - reset interrupt confiure on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1c_irq_reset(struct atl1c_adapter *adapter)
+{
+	atomic_set(&adapter->irq_sem, 1);
+	atl1c_irq_enable(adapter);
+}
+
+/*
+ * atl1c_wait_until_idle - wait up to AT_HW_MAX_IDLE_DELAY reads
+ * of the idle status register until the device is actually idle
+ */
+static u32 atl1c_wait_until_idle(struct atl1c_hw *hw)
+{
+	int timeout;
+	u32 data;
+
+	for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
+		AT_READ_REG(hw, REG_IDLE_STATUS, &data);
+		if ((data & IDLE_STATUS_MASK) == 0)
+			return 0;
+		msleep(1);
+	}
+	return data;
+}
+
+/*
+ * atl1c_phy_config - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1c_phy_config(unsigned long data)
+{
+	struct atl1c_adapter *adapter = (struct atl1c_adapter *) data;
+	struct atl1c_hw *hw = &adapter->hw;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->mdio_lock, flags);
+	atl1c_restart_autoneg(hw);
+	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+}
+
+void atl1c_reinit_locked(struct atl1c_adapter *adapter)
+{
+	WARN_ON(in_interrupt());
+	atl1c_down(adapter);
+	atl1c_up(adapter);
+	clear_bit(__AT_RESETTING, &adapter->flags);
+}
+
+static void atl1c_check_link_status(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev    *pdev   = adapter->pdev;
+	int err;
+	unsigned long flags;
+	u16 speed, duplex, phy_data;
+
+	spin_lock_irqsave(&adapter->mdio_lock, flags);
+	/* MII_BMSR must read twise */
+	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
+	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
+	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+
+	if ((phy_data & BMSR_LSTATUS) == 0) {
+		/* link down */
+		hw->hibernate = true;
+		if (atl1c_stop_mac(hw) != 0)
+			if (netif_msg_hw(adapter))
+				dev_warn(&pdev->dev, "stop mac failed\n");
+		atl1c_set_aspm(hw, false);
+		netif_carrier_off(netdev);
+		netif_stop_queue(netdev);
+		atl1c_phy_reset(hw);
+		atl1c_phy_init(&adapter->hw);
+	} else {
+		/* Link Up */
+		hw->hibernate = false;
+		spin_lock_irqsave(&adapter->mdio_lock, flags);
+		err = atl1c_get_speed_and_duplex(hw, &speed, &duplex);
+		spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+		if (unlikely(err))
+			return;
+		/* link result is our setting */
+		if (adapter->link_speed != speed ||
+		    adapter->link_duplex != duplex) {
+			adapter->link_speed  = speed;
+			adapter->link_duplex = duplex;
+			atl1c_set_aspm(hw, true);
+			atl1c_enable_tx_ctrl(hw);
+			atl1c_enable_rx_ctrl(hw);
+			atl1c_setup_mac_ctrl(adapter);
+			if (netif_msg_link(adapter))
+				dev_info(&pdev->dev,
+					"%s: %s NIC Link is Up<%d Mbps %s>\n",
+					atl1c_driver_name, netdev->name,
+					adapter->link_speed,
+					adapter->link_duplex == FULL_DUPLEX ?
+					"Full Duplex" : "Half Duplex");
+		}
+		if (!netif_carrier_ok(netdev))
+			netif_carrier_on(netdev);
+	}
+}
+
+static void atl1c_link_chg_event(struct atl1c_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev    *pdev   = adapter->pdev;
+	u16 phy_data;
+	u16 link_up;
+
+	spin_lock(&adapter->mdio_lock);
+	atl1c_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+	atl1c_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+	spin_unlock(&adapter->mdio_lock);
+	link_up = phy_data & BMSR_LSTATUS;
+	/* notify upper layer link down ASAP */
+	if (!link_up) {
+		if (netif_carrier_ok(netdev)) {
+			/* old link state: Up */
+			netif_carrier_off(netdev);
+			if (netif_msg_link(adapter))
+				dev_info(&pdev->dev,
+					"%s: %s NIC Link is Down\n",
+					atl1c_driver_name, netdev->name);
+			adapter->link_speed = SPEED_0;
+		}
+	}
+
+	set_bit(ATL1C_WORK_EVENT_LINK_CHANGE, &adapter->work_event);
+	schedule_work(&adapter->common_task);
+}
+
+static void atl1c_common_task(struct work_struct *work)
+{
+	struct atl1c_adapter *adapter;
+	struct net_device *netdev;
+
+	adapter = container_of(work, struct atl1c_adapter, common_task);
+	netdev = adapter->netdev;
+
+	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);
+	}
+
+	if (test_and_clear_bit(ATL1C_WORK_EVENT_LINK_CHANGE,
+		&adapter->work_event))
+		atl1c_check_link_status(adapter);
+}
+
+
+static void atl1c_del_timer(struct atl1c_adapter *adapter)
+{
+	del_timer_sync(&adapter->phy_config_timer);
+}
+
+
+/*
+ * atl1c_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ */
+static void atl1c_tx_timeout(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	/* Do the reset outside of interrupt context */
+	set_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event);
+	schedule_work(&adapter->common_task);
+}
+
+/*
+ * atl1c_set_multi - Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated.  This routine is
+ * responsible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ */
+static void atl1c_set_multi(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct atl1c_hw *hw = &adapter->hw;
+	struct netdev_hw_addr *ha;
+	u32 mac_ctrl_data;
+	u32 hash_value;
+
+	/* Check for Promiscuous and All Multicast modes */
+	AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data);
+
+	if (netdev->flags & IFF_PROMISC) {
+		mac_ctrl_data |= MAC_CTRL_PROMIS_EN;
+	} else if (netdev->flags & IFF_ALLMULTI) {
+		mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;
+		mac_ctrl_data &= ~MAC_CTRL_PROMIS_EN;
+	} else {
+		mac_ctrl_data &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+	}
+
+	AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+
+	/* clear the old settings from the multicast hash table */
+	AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+	/* comoute mc addresses' hash value ,and put it into hash table */
+	netdev_for_each_mc_addr(ha, netdev) {
+		hash_value = atl1c_hash_mc_addr(hw, ha->addr);
+		atl1c_hash_set(hw, hash_value);
+	}
+}
+
+static void __atl1c_vlan_mode(u32 features, u32 *mac_ctrl_data)
+{
+	if (features & NETIF_F_HW_VLAN_RX) {
+		/* enable VLAN tag insert/strip */
+		*mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+	} else {
+		/* disable VLAN tag insert/strip */
+		*mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN;
+	}
+}
+
+static void atl1c_vlan_mode(struct net_device *netdev, u32 features)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct pci_dev *pdev = adapter->pdev;
+	u32 mac_ctrl_data = 0;
+
+	if (netif_msg_pktdata(adapter))
+		dev_dbg(&pdev->dev, "atl1c_vlan_mode\n");
+
+	atl1c_irq_disable(adapter);
+	AT_READ_REG(&adapter->hw, REG_MAC_CTRL, &mac_ctrl_data);
+	__atl1c_vlan_mode(features, &mac_ctrl_data);
+	AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data);
+	atl1c_irq_enable(adapter);
+}
+
+static void atl1c_restore_vlan(struct atl1c_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	if (netif_msg_pktdata(adapter))
+		dev_dbg(&pdev->dev, "atl1c_restore_vlan\n");
+	atl1c_vlan_mode(adapter->netdev, adapter->netdev->features);
+}
+
+/*
+ * atl1c_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1c_set_mac_addr(struct net_device *netdev, void *p)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	if (netif_running(netdev))
+		return -EBUSY;
+
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+
+	atl1c_hw_set_mac_addr(&adapter->hw);
+
+	return 0;
+}
+
+static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter,
+				struct net_device *dev)
+{
+	int mtu = dev->mtu;
+
+	adapter->rx_buffer_len = mtu > AT_RX_BUF_SIZE ?
+		roundup(mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN, 8) : AT_RX_BUF_SIZE;
+}
+
+static u32 atl1c_fix_features(struct net_device *netdev, u32 features)
+{
+	/*
+	 * Since there is no support for separate rx/tx vlan accel
+	 * enable/disable make sure tx flag is always in same state as rx.
+	 */
+	if (features & NETIF_F_HW_VLAN_RX)
+		features |= NETIF_F_HW_VLAN_TX;
+	else
+		features &= ~NETIF_F_HW_VLAN_TX;
+
+	if (netdev->mtu > MAX_TSO_FRAME_SIZE)
+		features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+
+	return features;
+}
+
+static int atl1c_set_features(struct net_device *netdev, u32 features)
+{
+	u32 changed = netdev->features ^ features;
+
+	if (changed & NETIF_F_HW_VLAN_RX)
+		atl1c_vlan_mode(netdev, features);
+
+	return 0;
+}
+
+/*
+ * atl1c_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1c_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	int old_mtu   = netdev->mtu;
+	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+
+	if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
+			(max_frame > MAX_JUMBO_FRAME_SIZE)) {
+		if (netif_msg_link(adapter))
+			dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
+		return -EINVAL;
+	}
+	/* set MTU */
+	if (old_mtu != new_mtu && netif_running(netdev)) {
+		while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+			msleep(1);
+		netdev->mtu = new_mtu;
+		adapter->hw.max_frame_size = new_mtu;
+		atl1c_set_rxbufsize(adapter, netdev);
+		atl1c_down(adapter);
+		netdev_update_features(netdev);
+		atl1c_up(adapter);
+		clear_bit(__AT_RESETTING, &adapter->flags);
+		if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) {
+			u32 phy_data;
+
+			AT_READ_REG(&adapter->hw, 0x1414, &phy_data);
+			phy_data |= 0x10000000;
+			AT_WRITE_REG(&adapter->hw, 0x1414, phy_data);
+		}
+
+	}
+	return 0;
+}
+
+/*
+ *  caller should hold mdio_lock
+ */
+static int atl1c_mdio_read(struct net_device *netdev, int phy_id, int reg_num)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	u16 result;
+
+	atl1c_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result);
+	return result;
+}
+
+static void atl1c_mdio_write(struct net_device *netdev, int phy_id,
+			     int reg_num, int val)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	atl1c_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val);
+}
+
+/*
+ * atl1c_mii_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1c_mii_ioctl(struct net_device *netdev,
+			   struct ifreq *ifr, int cmd)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct pci_dev *pdev = adapter->pdev;
+	struct mii_ioctl_data *data = if_mii(ifr);
+	unsigned long flags;
+	int retval = 0;
+
+	if (!netif_running(netdev))
+		return -EINVAL;
+
+	spin_lock_irqsave(&adapter->mdio_lock, flags);
+	switch (cmd) {
+	case SIOCGMIIPHY:
+		data->phy_id = 0;
+		break;
+
+	case SIOCGMIIREG:
+		if (atl1c_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+				    &data->val_out)) {
+			retval = -EIO;
+			goto out;
+		}
+		break;
+
+	case SIOCSMIIREG:
+		if (data->reg_num & ~(0x1F)) {
+			retval = -EFAULT;
+			goto out;
+		}
+
+		dev_dbg(&pdev->dev, "<atl1c_mii_ioctl> write %x %x",
+				data->reg_num, data->val_in);
+		if (atl1c_write_phy_reg(&adapter->hw,
+				     data->reg_num, data->val_in)) {
+			retval = -EIO;
+			goto out;
+		}
+		break;
+
+	default:
+		retval = -EOPNOTSUPP;
+		break;
+	}
+out:
+	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+	return retval;
+}
+
+/*
+ * atl1c_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1c_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	switch (cmd) {
+	case SIOCGMIIPHY:
+	case SIOCGMIIREG:
+	case SIOCSMIIREG:
+		return atl1c_mii_ioctl(netdev, ifr, cmd);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+/*
+ * atl1c_alloc_queues - Allocate memory for all rings
+ * @adapter: board private structure to initialize
+ *
+ */
+static int __devinit atl1c_alloc_queues(struct atl1c_adapter *adapter)
+{
+	return 0;
+}
+
+static void atl1c_set_mac_type(struct atl1c_hw *hw)
+{
+	switch (hw->device_id) {
+	case PCI_DEVICE_ID_ATTANSIC_L2C:
+		hw->nic_type = athr_l2c;
+		break;
+	case PCI_DEVICE_ID_ATTANSIC_L1C:
+		hw->nic_type = athr_l1c;
+		break;
+	case PCI_DEVICE_ID_ATHEROS_L2C_B:
+		hw->nic_type = athr_l2c_b;
+		break;
+	case PCI_DEVICE_ID_ATHEROS_L2C_B2:
+		hw->nic_type = athr_l2c_b2;
+		break;
+	case PCI_DEVICE_ID_ATHEROS_L1D:
+		hw->nic_type = athr_l1d;
+		break;
+	case PCI_DEVICE_ID_ATHEROS_L1D_2_0:
+		hw->nic_type = athr_l1d_2;
+		break;
+	default:
+		break;
+	}
+}
+
+static int atl1c_setup_mac_funcs(struct atl1c_hw *hw)
+{
+	u32 phy_status_data;
+	u32 link_ctrl_data;
+
+	atl1c_set_mac_type(hw);
+	AT_READ_REG(hw, REG_PHY_STATUS, &phy_status_data);
+	AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data);
+
+	hw->ctrl_flags = ATL1C_INTR_MODRT_ENABLE  |
+			 ATL1C_TXQ_MODE_ENHANCE;
+	if (link_ctrl_data & LINK_CTRL_L0S_EN)
+		hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT;
+	if (link_ctrl_data & LINK_CTRL_L1_EN)
+		hw->ctrl_flags |= ATL1C_ASPM_L1_SUPPORT;
+	if (link_ctrl_data & LINK_CTRL_EXT_SYNC)
+		hw->ctrl_flags |= ATL1C_LINK_EXT_SYNC;
+	hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON;
+
+	if (hw->nic_type == athr_l1c ||
+	    hw->nic_type == athr_l1d ||
+	    hw->nic_type == athr_l1d_2)
+		hw->link_cap_flags |= ATL1C_LINK_CAP_1000M;
+	return 0;
+}
+/*
+ * atl1c_sw_init - Initialize general software structures (struct atl1c_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * atl1c_sw_init initializes the Adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ */
+static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw   = &adapter->hw;
+	struct pci_dev	*pdev = adapter->pdev;
+	u32 revision;
+
+
+	adapter->wol = 0;
+	device_set_wakeup_enable(&pdev->dev, false);
+	adapter->link_speed = SPEED_0;
+	adapter->link_duplex = FULL_DUPLEX;
+	adapter->num_rx_queues = AT_DEF_RECEIVE_QUEUE;
+	adapter->tpd_ring[0].count = 1024;
+	adapter->rfd_ring[0].count = 512;
+
+	hw->vendor_id = pdev->vendor;
+	hw->device_id = pdev->device;
+	hw->subsystem_vendor_id = pdev->subsystem_vendor;
+	hw->subsystem_id = pdev->subsystem_device;
+	AT_READ_REG(hw, PCI_CLASS_REVISION, &revision);
+	hw->revision_id = revision & 0xFF;
+	/* before link up, we assume hibernate is true */
+	hw->hibernate = true;
+	hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
+	if (atl1c_setup_mac_funcs(hw) != 0) {
+		dev_err(&pdev->dev, "set mac function pointers failed\n");
+		return -1;
+	}
+	hw->intr_mask = IMR_NORMAL_MASK;
+	hw->phy_configured = false;
+	hw->preamble_len = 7;
+	hw->max_frame_size = adapter->netdev->mtu;
+	if (adapter->num_rx_queues < 2) {
+		hw->rss_type = atl1c_rss_disable;
+		hw->rss_mode = atl1c_rss_mode_disable;
+	} else {
+		hw->rss_type = atl1c_rss_ipv4;
+		hw->rss_mode = atl1c_rss_mul_que_mul_int;
+		hw->rss_hash_bits = 16;
+	}
+	hw->autoneg_advertised = ADVERTISED_Autoneg;
+	hw->indirect_tab = 0xE4E4E4E4;
+	hw->base_cpu = 0;
+
+	hw->ict = 50000;		/* 100ms */
+	hw->smb_timer = 200000;	  	/* 400ms */
+	hw->cmb_tpd = 4;
+	hw->cmb_tx_timer = 1;		/* 2 us  */
+	hw->rx_imt = 200;
+	hw->tx_imt = 1000;
+
+	hw->tpd_burst = 5;
+	hw->rfd_burst = 8;
+	hw->dma_order = atl1c_dma_ord_out;
+	hw->dmar_block = atl1c_dma_req_1024;
+	hw->dmaw_block = atl1c_dma_req_1024;
+	hw->dmar_dly_cnt = 15;
+	hw->dmaw_dly_cnt = 4;
+
+	if (atl1c_alloc_queues(adapter)) {
+		dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
+		return -ENOMEM;
+	}
+	/* TODO */
+	atl1c_set_rxbufsize(adapter, adapter->netdev);
+	atomic_set(&adapter->irq_sem, 1);
+	spin_lock_init(&adapter->mdio_lock);
+	spin_lock_init(&adapter->tx_lock);
+	set_bit(__AT_DOWN, &adapter->flags);
+
+	return 0;
+}
+
+static inline void atl1c_clean_buffer(struct pci_dev *pdev,
+				struct atl1c_buffer *buffer_info, int in_irq)
+{
+	u16 pci_driection;
+	if (buffer_info->flags & ATL1C_BUFFER_FREE)
+		return;
+	if (buffer_info->dma) {
+		if (buffer_info->flags & ATL1C_PCIMAP_FROMDEVICE)
+			pci_driection = PCI_DMA_FROMDEVICE;
+		else
+			pci_driection = PCI_DMA_TODEVICE;
+
+		if (buffer_info->flags & ATL1C_PCIMAP_SINGLE)
+			pci_unmap_single(pdev, buffer_info->dma,
+					buffer_info->length, pci_driection);
+		else if (buffer_info->flags & ATL1C_PCIMAP_PAGE)
+			pci_unmap_page(pdev, buffer_info->dma,
+					buffer_info->length, pci_driection);
+	}
+	if (buffer_info->skb) {
+		if (in_irq)
+			dev_kfree_skb_irq(buffer_info->skb);
+		else
+			dev_kfree_skb(buffer_info->skb);
+	}
+	buffer_info->dma = 0;
+	buffer_info->skb = NULL;
+	ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE);
+}
+/*
+ * atl1c_clean_tx_ring - Free Tx-skb
+ * @adapter: board private structure
+ */
+static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter,
+				enum atl1c_trans_queue type)
+{
+	struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
+	struct atl1c_buffer *buffer_info;
+	struct pci_dev *pdev = adapter->pdev;
+	u16 index, ring_count;
+
+	ring_count = tpd_ring->count;
+	for (index = 0; index < ring_count; index++) {
+		buffer_info = &tpd_ring->buffer_info[index];
+		atl1c_clean_buffer(pdev, buffer_info, 0);
+	}
+
+	/* Zero out Tx-buffers */
+	memset(tpd_ring->desc, 0, sizeof(struct atl1c_tpd_desc) *
+		ring_count);
+	atomic_set(&tpd_ring->next_to_clean, 0);
+	tpd_ring->next_to_use = 0;
+}
+
+/*
+ * atl1c_clean_rx_ring - Free rx-reservation skbs
+ * @adapter: board private structure
+ */
+static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter)
+{
+	struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
+	struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
+	struct atl1c_buffer *buffer_info;
+	struct pci_dev *pdev = adapter->pdev;
+	int i, j;
+
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		for (j = 0; j < rfd_ring[i].count; j++) {
+			buffer_info = &rfd_ring[i].buffer_info[j];
+			atl1c_clean_buffer(pdev, buffer_info, 0);
+		}
+		/* zero out the descriptor ring */
+		memset(rfd_ring[i].desc, 0, rfd_ring[i].size);
+		rfd_ring[i].next_to_clean = 0;
+		rfd_ring[i].next_to_use = 0;
+		rrd_ring[i].next_to_use = 0;
+		rrd_ring[i].next_to_clean = 0;
+	}
+}
+
+/*
+ * Read / Write Ptr Initialize:
+ */
+static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter)
+{
+	struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring;
+	struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
+	struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
+	struct atl1c_buffer *buffer_info;
+	int i, j;
+
+	for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) {
+		tpd_ring[i].next_to_use = 0;
+		atomic_set(&tpd_ring[i].next_to_clean, 0);
+		buffer_info = tpd_ring[i].buffer_info;
+		for (j = 0; j < tpd_ring->count; j++)
+			ATL1C_SET_BUFFER_STATE(&buffer_info[i],
+					ATL1C_BUFFER_FREE);
+	}
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		rfd_ring[i].next_to_use = 0;
+		rfd_ring[i].next_to_clean = 0;
+		rrd_ring[i].next_to_use = 0;
+		rrd_ring[i].next_to_clean = 0;
+		for (j = 0; j < rfd_ring[i].count; j++) {
+			buffer_info = &rfd_ring[i].buffer_info[j];
+			ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE);
+		}
+	}
+}
+
+/*
+ * atl1c_free_ring_resources - Free Tx / RX descriptor Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ */
+static void atl1c_free_ring_resources(struct atl1c_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	pci_free_consistent(pdev, adapter->ring_header.size,
+					adapter->ring_header.desc,
+					adapter->ring_header.dma);
+	adapter->ring_header.desc = NULL;
+
+	/* Note: just free tdp_ring.buffer_info,
+	*  it contain rfd_ring.buffer_info, do not double free */
+	if (adapter->tpd_ring[0].buffer_info) {
+		kfree(adapter->tpd_ring[0].buffer_info);
+		adapter->tpd_ring[0].buffer_info = NULL;
+	}
+}
+
+/*
+ * atl1c_setup_mem_resources - allocate Tx / RX descriptor resources
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ */
+static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring;
+	struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
+	struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
+	struct atl1c_ring_header *ring_header = &adapter->ring_header;
+	int num_rx_queues = adapter->num_rx_queues;
+	int size;
+	int i;
+	int count = 0;
+	int rx_desc_count = 0;
+	u32 offset = 0;
+
+	rrd_ring[0].count = rfd_ring[0].count;
+	for (i = 1; i < AT_MAX_TRANSMIT_QUEUE; i++)
+		tpd_ring[i].count = tpd_ring[0].count;
+
+	for (i = 1; i < adapter->num_rx_queues; i++)
+		rfd_ring[i].count = rrd_ring[i].count = rfd_ring[0].count;
+
+	/* 2 tpd queue, one high priority queue,
+	 * another normal priority queue */
+	size = sizeof(struct atl1c_buffer) * (tpd_ring->count * 2 +
+		rfd_ring->count * num_rx_queues);
+	tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
+	if (unlikely(!tpd_ring->buffer_info)) {
+		dev_err(&pdev->dev, "kzalloc failed, size = %d\n",
+			size);
+		goto err_nomem;
+	}
+	for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) {
+		tpd_ring[i].buffer_info =
+			(struct atl1c_buffer *) (tpd_ring->buffer_info + count);
+		count += tpd_ring[i].count;
+	}
+
+	for (i = 0; i < num_rx_queues; i++) {
+		rfd_ring[i].buffer_info =
+			(struct atl1c_buffer *) (tpd_ring->buffer_info + count);
+		count += rfd_ring[i].count;
+		rx_desc_count += rfd_ring[i].count;
+	}
+	/*
+	 * real ring DMA buffer
+	 * each ring/block may need up to 8 bytes for alignment, hence the
+	 * additional bytes tacked onto the end.
+	 */
+	ring_header->size = size =
+		sizeof(struct atl1c_tpd_desc) * tpd_ring->count * 2 +
+		sizeof(struct atl1c_rx_free_desc) * rx_desc_count +
+		sizeof(struct atl1c_recv_ret_status) * rx_desc_count +
+		sizeof(struct atl1c_hw_stats) +
+		8 * 4 + 8 * 2 * num_rx_queues;
+
+	ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
+				&ring_header->dma);
+	if (unlikely(!ring_header->desc)) {
+		dev_err(&pdev->dev, "pci_alloc_consistend failed\n");
+		goto err_nomem;
+	}
+	memset(ring_header->desc, 0, ring_header->size);
+	/* init TPD ring */
+
+	tpd_ring[0].dma = roundup(ring_header->dma, 8);
+	offset = tpd_ring[0].dma - ring_header->dma;
+	for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) {
+		tpd_ring[i].dma = ring_header->dma + offset;
+		tpd_ring[i].desc = (u8 *) ring_header->desc + offset;
+		tpd_ring[i].size =
+			sizeof(struct atl1c_tpd_desc) * tpd_ring[i].count;
+		offset += roundup(tpd_ring[i].size, 8);
+	}
+	/* init RFD ring */
+	for (i = 0; i < num_rx_queues; i++) {
+		rfd_ring[i].dma = ring_header->dma + offset;
+		rfd_ring[i].desc = (u8 *) ring_header->desc + offset;
+		rfd_ring[i].size = sizeof(struct atl1c_rx_free_desc) *
+				rfd_ring[i].count;
+		offset += roundup(rfd_ring[i].size, 8);
+	}
+
+	/* init RRD ring */
+	for (i = 0; i < num_rx_queues; i++) {
+		rrd_ring[i].dma = ring_header->dma + offset;
+		rrd_ring[i].desc = (u8 *) ring_header->desc + offset;
+		rrd_ring[i].size = sizeof(struct atl1c_recv_ret_status) *
+				rrd_ring[i].count;
+		offset += roundup(rrd_ring[i].size, 8);
+	}
+
+	adapter->smb.dma = ring_header->dma + offset;
+	adapter->smb.smb = (u8 *)ring_header->desc + offset;
+	return 0;
+
+err_nomem:
+	kfree(tpd_ring->buffer_info);
+	return -ENOMEM;
+}
+
+static void atl1c_configure_des_ring(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw = &adapter->hw;
+	struct atl1c_rfd_ring *rfd_ring = (struct atl1c_rfd_ring *)
+				adapter->rfd_ring;
+	struct atl1c_rrd_ring *rrd_ring = (struct atl1c_rrd_ring *)
+				adapter->rrd_ring;
+	struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *)
+				adapter->tpd_ring;
+	struct atl1c_cmb *cmb = (struct atl1c_cmb *) &adapter->cmb;
+	struct atl1c_smb *smb = (struct atl1c_smb *) &adapter->smb;
+	int i;
+	u32 data;
+
+	/* TPD */
+	AT_WRITE_REG(hw, REG_TX_BASE_ADDR_HI,
+			(u32)((tpd_ring[atl1c_trans_normal].dma &
+				AT_DMA_HI_ADDR_MASK) >> 32));
+	/* just enable normal priority TX queue */
+	AT_WRITE_REG(hw, REG_NTPD_HEAD_ADDR_LO,
+			(u32)(tpd_ring[atl1c_trans_normal].dma &
+				AT_DMA_LO_ADDR_MASK));
+	AT_WRITE_REG(hw, REG_HTPD_HEAD_ADDR_LO,
+			(u32)(tpd_ring[atl1c_trans_high].dma &
+				AT_DMA_LO_ADDR_MASK));
+	AT_WRITE_REG(hw, REG_TPD_RING_SIZE,
+			(u32)(tpd_ring[0].count & TPD_RING_SIZE_MASK));
+
+
+	/* RFD */
+	AT_WRITE_REG(hw, REG_RX_BASE_ADDR_HI,
+			(u32)((rfd_ring[0].dma & AT_DMA_HI_ADDR_MASK) >> 32));
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		AT_WRITE_REG(hw, atl1c_rfd_addr_lo_regs[i],
+			(u32)(rfd_ring[i].dma & AT_DMA_LO_ADDR_MASK));
+
+	AT_WRITE_REG(hw, REG_RFD_RING_SIZE,
+			rfd_ring[0].count & RFD_RING_SIZE_MASK);
+	AT_WRITE_REG(hw, REG_RX_BUF_SIZE,
+			adapter->rx_buffer_len & RX_BUF_SIZE_MASK);
+
+	/* RRD */
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		AT_WRITE_REG(hw, atl1c_rrd_addr_lo_regs[i],
+			(u32)(rrd_ring[i].dma & AT_DMA_LO_ADDR_MASK));
+	AT_WRITE_REG(hw, REG_RRD_RING_SIZE,
+			(rrd_ring[0].count & RRD_RING_SIZE_MASK));
+
+	/* CMB */
+	AT_WRITE_REG(hw, REG_CMB_BASE_ADDR_LO, cmb->dma & AT_DMA_LO_ADDR_MASK);
+
+	/* SMB */
+	AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_HI,
+			(u32)((smb->dma & AT_DMA_HI_ADDR_MASK) >> 32));
+	AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_LO,
+			(u32)(smb->dma & AT_DMA_LO_ADDR_MASK));
+	if (hw->nic_type == athr_l2c_b) {
+		AT_WRITE_REG(hw, REG_SRAM_RXF_LEN, 0x02a0L);
+		AT_WRITE_REG(hw, REG_SRAM_TXF_LEN, 0x0100L);
+		AT_WRITE_REG(hw, REG_SRAM_RXF_ADDR, 0x029f0000L);
+		AT_WRITE_REG(hw, REG_SRAM_RFD0_INFO, 0x02bf02a0L);
+		AT_WRITE_REG(hw, REG_SRAM_TXF_ADDR, 0x03bf02c0L);
+		AT_WRITE_REG(hw, REG_SRAM_TRD_ADDR, 0x03df03c0L);
+		AT_WRITE_REG(hw, REG_TXF_WATER_MARK, 0);	/* TX watermark, to enter l1 state.*/
+		AT_WRITE_REG(hw, REG_RXD_DMA_CTRL, 0);		/* RXD threshold.*/
+	}
+	if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d_2) {
+			/* Power Saving for L2c_B */
+		AT_READ_REG(hw, REG_SERDES_LOCK, &data);
+		data |= SERDES_MAC_CLK_SLOWDOWN;
+		data |= SERDES_PYH_CLK_SLOWDOWN;
+		AT_WRITE_REG(hw, REG_SERDES_LOCK, data);
+	}
+	/* Load all of base address above */
+	AT_WRITE_REG(hw, REG_LOAD_PTR, 1);
+}
+
+static void atl1c_configure_tx(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw = &adapter->hw;
+	u32 dev_ctrl_data;
+	u32 max_pay_load;
+	u16 tx_offload_thresh;
+	u32 txq_ctrl_data;
+	u32 max_pay_load_data;
+
+	tx_offload_thresh = MAX_TX_OFFLOAD_THRESH;
+	AT_WRITE_REG(hw, REG_TX_TSO_OFFLOAD_THRESH,
+		(tx_offload_thresh >> 3) & TX_TSO_OFFLOAD_THRESH_MASK);
+	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_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_t(u32, max_pay_load, hw->dmar_block);
+
+	txq_ctrl_data = (hw->tpd_burst & TXQ_NUM_TPD_BURST_MASK) <<
+			TXQ_NUM_TPD_BURST_SHIFT;
+	if (hw->ctrl_flags & ATL1C_TXQ_MODE_ENHANCE)
+		txq_ctrl_data |= TXQ_CTRL_ENH_MODE;
+	max_pay_load_data = (atl1c_pay_load_size[hw->dmar_block] &
+			TXQ_TXF_BURST_NUM_MASK) << TXQ_TXF_BURST_NUM_SHIFT;
+	if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2)
+		max_pay_load_data >>= 1;
+	txq_ctrl_data |= max_pay_load_data;
+
+	AT_WRITE_REG(hw, REG_TXQ_CTRL, txq_ctrl_data);
+}
+
+static void atl1c_configure_rx(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw = &adapter->hw;
+	u32 rxq_ctrl_data;
+
+	rxq_ctrl_data = (hw->rfd_burst & RXQ_RFD_BURST_NUM_MASK) <<
+			RXQ_RFD_BURST_NUM_SHIFT;
+
+	if (hw->ctrl_flags & ATL1C_RX_IPV6_CHKSUM)
+		rxq_ctrl_data |= IPV6_CHKSUM_CTRL_EN;
+	if (hw->rss_type == atl1c_rss_ipv4)
+		rxq_ctrl_data |= RSS_HASH_IPV4;
+	if (hw->rss_type == atl1c_rss_ipv4_tcp)
+		rxq_ctrl_data |= RSS_HASH_IPV4_TCP;
+	if (hw->rss_type == atl1c_rss_ipv6)
+		rxq_ctrl_data |= RSS_HASH_IPV6;
+	if (hw->rss_type == atl1c_rss_ipv6_tcp)
+		rxq_ctrl_data |= RSS_HASH_IPV6_TCP;
+	if (hw->rss_type != atl1c_rss_disable)
+		rxq_ctrl_data |= RRS_HASH_CTRL_EN;
+
+	rxq_ctrl_data |= (hw->rss_mode & RSS_MODE_MASK) <<
+			RSS_MODE_SHIFT;
+	rxq_ctrl_data |= (hw->rss_hash_bits & RSS_HASH_BITS_MASK) <<
+			RSS_HASH_BITS_SHIFT;
+	if (hw->ctrl_flags & ATL1C_ASPM_CTRL_MON)
+		rxq_ctrl_data |= (ASPM_THRUPUT_LIMIT_1M &
+			ASPM_THRUPUT_LIMIT_MASK) << ASPM_THRUPUT_LIMIT_SHIFT;
+
+	AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data);
+}
+
+static void atl1c_configure_rss(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw = &adapter->hw;
+
+	AT_WRITE_REG(hw, REG_IDT_TABLE, hw->indirect_tab);
+	AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, hw->base_cpu);
+}
+
+static void atl1c_configure_dma(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw = &adapter->hw;
+	u32 dma_ctrl_data;
+
+	dma_ctrl_data = DMA_CTRL_DMAR_REQ_PRI;
+	if (hw->ctrl_flags & ATL1C_CMB_ENABLE)
+		dma_ctrl_data |= DMA_CTRL_CMB_EN;
+	if (hw->ctrl_flags & ATL1C_SMB_ENABLE)
+		dma_ctrl_data |= DMA_CTRL_SMB_EN;
+	else
+		dma_ctrl_data |= MAC_CTRL_SMB_DIS;
+
+	switch (hw->dma_order) {
+	case atl1c_dma_ord_in:
+		dma_ctrl_data |= DMA_CTRL_DMAR_IN_ORDER;
+		break;
+	case atl1c_dma_ord_enh:
+		dma_ctrl_data |= DMA_CTRL_DMAR_ENH_ORDER;
+		break;
+	case atl1c_dma_ord_out:
+		dma_ctrl_data |= DMA_CTRL_DMAR_OUT_ORDER;
+		break;
+	default:
+		break;
+	}
+
+	dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+		<< DMA_CTRL_DMAR_BURST_LEN_SHIFT;
+	dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
+		<< DMA_CTRL_DMAW_BURST_LEN_SHIFT;
+	dma_ctrl_data |= (((u32)hw->dmar_dly_cnt) & DMA_CTRL_DMAR_DLY_CNT_MASK)
+		<< DMA_CTRL_DMAR_DLY_CNT_SHIFT;
+	dma_ctrl_data |= (((u32)hw->dmaw_dly_cnt) & DMA_CTRL_DMAW_DLY_CNT_MASK)
+		<< DMA_CTRL_DMAW_DLY_CNT_SHIFT;
+
+	AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data);
+}
+
+/*
+ * Stop the mac, transmit and receive units
+ * hw - Struct containing variables accessed by shared code
+ * return : 0  or  idle status (if error)
+ */
+static int atl1c_stop_mac(struct atl1c_hw *hw)
+{
+	u32 data;
+
+	AT_READ_REG(hw, REG_RXQ_CTRL, &data);
+	data &= ~(RXQ1_CTRL_EN | RXQ2_CTRL_EN |
+		  RXQ3_CTRL_EN | RXQ_CTRL_EN);
+	AT_WRITE_REG(hw, REG_RXQ_CTRL, data);
+
+	AT_READ_REG(hw, REG_TXQ_CTRL, &data);
+	data &= ~TXQ_CTRL_EN;
+	AT_WRITE_REG(hw, REG_TWSI_CTRL, data);
+
+	atl1c_wait_until_idle(hw);
+
+	AT_READ_REG(hw, REG_MAC_CTRL, &data);
+	data &= ~(MAC_CTRL_TX_EN | MAC_CTRL_RX_EN);
+	AT_WRITE_REG(hw, REG_MAC_CTRL, data);
+
+	return (int)atl1c_wait_until_idle(hw);
+}
+
+static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw)
+{
+	u32 data;
+
+	AT_READ_REG(hw, REG_RXQ_CTRL, &data);
+	switch (hw->adapter->num_rx_queues) {
+	case 4:
+		data |= (RXQ3_CTRL_EN | RXQ2_CTRL_EN | RXQ1_CTRL_EN);
+		break;
+	case 3:
+		data |= (RXQ2_CTRL_EN | RXQ1_CTRL_EN);
+		break;
+	case 2:
+		data |= RXQ1_CTRL_EN;
+		break;
+	default:
+		break;
+	}
+	data |= RXQ_CTRL_EN;
+	AT_WRITE_REG(hw, REG_RXQ_CTRL, data);
+}
+
+static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw)
+{
+	u32 data;
+
+	AT_READ_REG(hw, REG_TXQ_CTRL, &data);
+	data |= TXQ_CTRL_EN;
+	AT_WRITE_REG(hw, REG_TXQ_CTRL, data);
+}
+
+/*
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ * hw - Struct containing variables accessed by shared code
+ * return : 0  or  idle status (if error)
+ */
+static int atl1c_reset_mac(struct atl1c_hw *hw)
+{
+	struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
+	struct pci_dev *pdev = adapter->pdev;
+	u32 master_ctrl_data = 0;
+
+	AT_WRITE_REG(hw, REG_IMR, 0);
+	AT_WRITE_REG(hw, REG_ISR, ISR_DIS_INT);
+
+	atl1c_stop_mac(hw);
+	/*
+	 * Issue Soft Reset to the MAC.  This will reset the chip's
+	 * transmit, receive, DMA.  It will not effect
+	 * the current PCI configuration.  The global reset bit is self-
+	 * clearing, and should clear within a microsecond.
+	 */
+	AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
+	master_ctrl_data |= MASTER_CTRL_OOB_DIS_OFF;
+	AT_WRITE_REGW(hw, REG_MASTER_CTRL, ((master_ctrl_data | MASTER_CTRL_SOFT_RST)
+			& 0xFFFF));
+
+	AT_WRITE_FLUSH(hw);
+	msleep(10);
+	/* Wait at least 10ms for All module to be Idle */
+
+	if (atl1c_wait_until_idle(hw)) {
+		dev_err(&pdev->dev,
+			"MAC state machine can't be idle since"
+			" disabled for 10ms second\n");
+		return -1;
+	}
+	return 0;
+}
+
+static void atl1c_disable_l0s_l1(struct atl1c_hw *hw)
+{
+	u32 pm_ctrl_data;
+
+	AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data);
+	pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
+			PM_CTRL_L1_ENTRY_TIMER_SHIFT);
+	pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1;
+	pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
+	pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
+	pm_ctrl_data &= ~PM_CTRL_MAC_ASPM_CHK;
+	pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1;
+
+	pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN;
+	pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN;
+	pm_ctrl_data |=	PM_CTRL_SERDES_L1_EN;
+	AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data);
+}
+
+/*
+ * Set ASPM state.
+ * Enable/disable L0s/L1 depend on link state.
+ */
+static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup)
+{
+	u32 pm_ctrl_data;
+	u32 link_ctrl_data;
+	u32 link_l1_timer = 0xF;
+
+	AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data);
+	AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data);
+
+	pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1;
+	pm_ctrl_data &=  ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
+			PM_CTRL_L1_ENTRY_TIMER_SHIFT);
+	pm_ctrl_data &= ~(PM_CTRL_LCKDET_TIMER_MASK <<
+			PM_CTRL_LCKDET_TIMER_SHIFT);
+	pm_ctrl_data |= AT_LCKDET_TIMER	<< PM_CTRL_LCKDET_TIMER_SHIFT;
+
+	if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d ||
+		hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) {
+		link_ctrl_data &= ~LINK_CTRL_EXT_SYNC;
+		if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) {
+			if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10)
+				link_ctrl_data |= LINK_CTRL_EXT_SYNC;
+		}
+
+		AT_WRITE_REG(hw, REG_LINK_CTRL, link_ctrl_data);
+
+		pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER;
+		pm_ctrl_data &= ~(PM_CTRL_PM_REQ_TIMER_MASK <<
+			PM_CTRL_PM_REQ_TIMER_SHIFT);
+		pm_ctrl_data |= AT_ASPM_L1_TIMER <<
+			PM_CTRL_PM_REQ_TIMER_SHIFT;
+		pm_ctrl_data &= ~PM_CTRL_SA_DLY_EN;
+		pm_ctrl_data &= ~PM_CTRL_HOTRST;
+		pm_ctrl_data |= 1 << PM_CTRL_L1_ENTRY_TIMER_SHIFT;
+		pm_ctrl_data |= PM_CTRL_SERDES_PD_EX_L1;
+	}
+	pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK;
+	if (linkup) {
+		pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
+		pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
+		if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT)
+			pm_ctrl_data |= PM_CTRL_ASPM_L1_EN;
+		if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT)
+			pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN;
+
+		if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d ||
+			hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) {
+			if (hw->nic_type == athr_l2c_b)
+				if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE))
+					pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
+			pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN;
+			pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN;
+			pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN;
+			pm_ctrl_data |= PM_CTRL_CLK_SWH_L1;
+		if (hw->adapter->link_speed == SPEED_100 ||
+				hw->adapter->link_speed == SPEED_1000) {
+				pm_ctrl_data &=  ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
+					PM_CTRL_L1_ENTRY_TIMER_SHIFT);
+				if (hw->nic_type == athr_l2c_b)
+					link_l1_timer = 7;
+				else if (hw->nic_type == athr_l2c_b2 ||
+					hw->nic_type == athr_l1d_2)
+					link_l1_timer = 4;
+				pm_ctrl_data |= link_l1_timer <<
+					PM_CTRL_L1_ENTRY_TIMER_SHIFT;
+			}
+		} else {
+			pm_ctrl_data |= PM_CTRL_SERDES_L1_EN;
+			pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN;
+			pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN;
+			pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1;
+			pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
+			pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
+
+		}
+	} else {
+		pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN;
+		pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
+		pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN;
+		pm_ctrl_data |= PM_CTRL_CLK_SWH_L1;
+
+		if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT)
+			pm_ctrl_data |= PM_CTRL_ASPM_L1_EN;
+		else
+			pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
+	}
+	AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data);
+
+	return;
+}
+
+static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	u32 mac_ctrl_data;
+
+	mac_ctrl_data = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
+	mac_ctrl_data |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+
+	if (adapter->link_duplex == FULL_DUPLEX) {
+		hw->mac_duplex = true;
+		mac_ctrl_data |= MAC_CTRL_DUPLX;
+	}
+
+	if (adapter->link_speed == SPEED_1000)
+		hw->mac_speed = atl1c_mac_speed_1000;
+	else
+		hw->mac_speed = atl1c_mac_speed_10_100;
+
+	mac_ctrl_data |= (hw->mac_speed & MAC_CTRL_SPEED_MASK) <<
+			MAC_CTRL_SPEED_SHIFT;
+
+	mac_ctrl_data |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+	mac_ctrl_data |= ((hw->preamble_len & MAC_CTRL_PRMLEN_MASK) <<
+			MAC_CTRL_PRMLEN_SHIFT);
+
+	__atl1c_vlan_mode(netdev->features, &mac_ctrl_data);
+
+	mac_ctrl_data |= MAC_CTRL_BC_EN;
+	if (netdev->flags & IFF_PROMISC)
+		mac_ctrl_data |= MAC_CTRL_PROMIS_EN;
+	if (netdev->flags & IFF_ALLMULTI)
+		mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;
+
+	mac_ctrl_data |= MAC_CTRL_SINGLE_PAUSE_EN;
+	if (hw->nic_type == athr_l1d || hw->nic_type == athr_l2c_b2 ||
+	    hw->nic_type == athr_l1d_2) {
+		mac_ctrl_data |= MAC_CTRL_SPEED_MODE_SW;
+		mac_ctrl_data |= MAC_CTRL_HASH_ALG_CRC32;
+	}
+	AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+}
+
+/*
+ * atl1c_configure - Configure Transmit&Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx /Rx unit of the MAC after a reset.
+ */
+static int atl1c_configure(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw = &adapter->hw;
+	u32 master_ctrl_data = 0;
+	u32 intr_modrt_data;
+	u32 data;
+
+	/* clear interrupt status */
+	AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF);
+	/*  Clear any WOL status */
+	AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+	/* set Interrupt Clear Timer
+	 * HW will enable self to assert interrupt event to system after
+	 * waiting x-time for software to notify it accept interrupt.
+	 */
+
+	data = CLK_GATING_EN_ALL;
+	if (hw->ctrl_flags & ATL1C_CLK_GATING_EN) {
+		if (hw->nic_type == athr_l2c_b)
+			data &= ~CLK_GATING_RXMAC_EN;
+	} else
+		data = 0;
+	AT_WRITE_REG(hw, REG_CLK_GATING_CTRL, data);
+
+	AT_WRITE_REG(hw, REG_INT_RETRIG_TIMER,
+		hw->ict & INT_RETRIG_TIMER_MASK);
+
+	atl1c_configure_des_ring(adapter);
+
+	if (hw->ctrl_flags & ATL1C_INTR_MODRT_ENABLE) {
+		intr_modrt_data = (hw->tx_imt & IRQ_MODRT_TIMER_MASK) <<
+					IRQ_MODRT_TX_TIMER_SHIFT;
+		intr_modrt_data |= (hw->rx_imt & IRQ_MODRT_TIMER_MASK) <<
+					IRQ_MODRT_RX_TIMER_SHIFT;
+		AT_WRITE_REG(hw, REG_IRQ_MODRT_TIMER_INIT, intr_modrt_data);
+		master_ctrl_data |=
+			MASTER_CTRL_TX_ITIMER_EN | MASTER_CTRL_RX_ITIMER_EN;
+	}
+
+	if (hw->ctrl_flags & ATL1C_INTR_CLEAR_ON_READ)
+		master_ctrl_data |= MASTER_CTRL_INT_RDCLR;
+
+	master_ctrl_data |= MASTER_CTRL_SA_TIMER_EN;
+	AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
+
+	if (hw->ctrl_flags & ATL1C_CMB_ENABLE) {
+		AT_WRITE_REG(hw, REG_CMB_TPD_THRESH,
+			hw->cmb_tpd & CMB_TPD_THRESH_MASK);
+		AT_WRITE_REG(hw, REG_CMB_TX_TIMER,
+			hw->cmb_tx_timer & CMB_TX_TIMER_MASK);
+	}
+
+	if (hw->ctrl_flags & ATL1C_SMB_ENABLE)
+		AT_WRITE_REG(hw, REG_SMB_STAT_TIMER,
+			hw->smb_timer & SMB_STAT_TIMER_MASK);
+	/* set MTU */
+	AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN +
+			VLAN_HLEN + ETH_FCS_LEN);
+	/* HDS, disable */
+	AT_WRITE_REG(hw, REG_HDS_CTRL, 0);
+
+	atl1c_configure_tx(adapter);
+	atl1c_configure_rx(adapter);
+	atl1c_configure_rss(adapter);
+	atl1c_configure_dma(adapter);
+
+	return 0;
+}
+
+static void atl1c_update_hw_stats(struct atl1c_adapter *adapter)
+{
+	u16 hw_reg_addr = 0;
+	unsigned long *stats_item = NULL;
+	u32 data;
+
+	/* update rx status */
+	hw_reg_addr = REG_MAC_RX_STATUS_BIN;
+	stats_item  = &adapter->hw_stats.rx_ok;
+	while (hw_reg_addr <= REG_MAC_RX_STATUS_END) {
+		AT_READ_REG(&adapter->hw, hw_reg_addr, &data);
+		*stats_item += data;
+		stats_item++;
+		hw_reg_addr += 4;
+	}
+/* update tx status */
+	hw_reg_addr = REG_MAC_TX_STATUS_BIN;
+	stats_item  = &adapter->hw_stats.tx_ok;
+	while (hw_reg_addr <= REG_MAC_TX_STATUS_END) {
+		AT_READ_REG(&adapter->hw, hw_reg_addr, &data);
+		*stats_item += data;
+		stats_item++;
+		hw_reg_addr += 4;
+	}
+}
+
+/*
+ * atl1c_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ *
+ * Returns the address of the device statistics structure.
+ * The statistics are actually updated from the timer callback.
+ */
+static struct net_device_stats *atl1c_get_stats(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct atl1c_hw_stats  *hw_stats = &adapter->hw_stats;
+	struct net_device_stats *net_stats = &netdev->stats;
+
+	atl1c_update_hw_stats(adapter);
+	net_stats->rx_packets = hw_stats->rx_ok;
+	net_stats->tx_packets = hw_stats->tx_ok;
+	net_stats->rx_bytes   = hw_stats->rx_byte_cnt;
+	net_stats->tx_bytes   = hw_stats->tx_byte_cnt;
+	net_stats->multicast  = hw_stats->rx_mcast;
+	net_stats->collisions = hw_stats->tx_1_col +
+				hw_stats->tx_2_col * 2 +
+				hw_stats->tx_late_col + hw_stats->tx_abort_col;
+	net_stats->rx_errors  = hw_stats->rx_frag + hw_stats->rx_fcs_err +
+				hw_stats->rx_len_err + hw_stats->rx_sz_ov +
+				hw_stats->rx_rrd_ov + hw_stats->rx_align_err;
+	net_stats->rx_fifo_errors   = hw_stats->rx_rxf_ov;
+	net_stats->rx_length_errors = hw_stats->rx_len_err;
+	net_stats->rx_crc_errors    = hw_stats->rx_fcs_err;
+	net_stats->rx_frame_errors  = hw_stats->rx_align_err;
+	net_stats->rx_over_errors   = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov;
+
+	net_stats->rx_missed_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov;
+
+	net_stats->tx_errors = hw_stats->tx_late_col + hw_stats->tx_abort_col +
+				hw_stats->tx_underrun + hw_stats->tx_trunc;
+	net_stats->tx_fifo_errors    = hw_stats->tx_underrun;
+	net_stats->tx_aborted_errors = hw_stats->tx_abort_col;
+	net_stats->tx_window_errors  = hw_stats->tx_late_col;
+
+	return net_stats;
+}
+
+static inline void atl1c_clear_phy_int(struct atl1c_adapter *adapter)
+{
+	u16 phy_data;
+
+	spin_lock(&adapter->mdio_lock);
+	atl1c_read_phy_reg(&adapter->hw, MII_ISR, &phy_data);
+	spin_unlock(&adapter->mdio_lock);
+}
+
+static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter,
+				enum atl1c_trans_queue type)
+{
+	struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *)
+				&adapter->tpd_ring[type];
+	struct atl1c_buffer *buffer_info;
+	struct pci_dev *pdev = adapter->pdev;
+	u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+	u16 hw_next_to_clean;
+	u16 shift;
+	u32 data;
+
+	if (type == atl1c_trans_high)
+		shift = MB_HTPD_CONS_IDX_SHIFT;
+	else
+		shift = MB_NTPD_CONS_IDX_SHIFT;
+
+	AT_READ_REG(&adapter->hw, REG_MB_PRIO_CONS_IDX, &data);
+	hw_next_to_clean = (data >> shift) & MB_PRIO_PROD_IDX_MASK;
+
+	while (next_to_clean != hw_next_to_clean) {
+		buffer_info = &tpd_ring->buffer_info[next_to_clean];
+		atl1c_clean_buffer(pdev, buffer_info, 1);
+		if (++next_to_clean == tpd_ring->count)
+			next_to_clean = 0;
+		atomic_set(&tpd_ring->next_to_clean, next_to_clean);
+	}
+
+	if (netif_queue_stopped(adapter->netdev) &&
+			netif_carrier_ok(adapter->netdev)) {
+		netif_wake_queue(adapter->netdev);
+	}
+
+	return true;
+}
+
+/*
+ * atl1c_intr - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
+ */
+static irqreturn_t atl1c_intr(int irq, void *data)
+{
+	struct net_device *netdev  = data;
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct pci_dev *pdev = adapter->pdev;
+	struct atl1c_hw *hw = &adapter->hw;
+	int max_ints = AT_MAX_INT_WORK;
+	int handled = IRQ_NONE;
+	u32 status;
+	u32 reg_data;
+
+	do {
+		AT_READ_REG(hw, REG_ISR, &reg_data);
+		status = reg_data & hw->intr_mask;
+
+		if (status == 0 || (status & ISR_DIS_INT) != 0) {
+			if (max_ints != AT_MAX_INT_WORK)
+				handled = IRQ_HANDLED;
+			break;
+		}
+		/* link event */
+		if (status & ISR_GPHY)
+			atl1c_clear_phy_int(adapter);
+		/* Ack ISR */
+		AT_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT);
+		if (status & ISR_RX_PKT) {
+			if (likely(napi_schedule_prep(&adapter->napi))) {
+				hw->intr_mask &= ~ISR_RX_PKT;
+				AT_WRITE_REG(hw, REG_IMR, hw->intr_mask);
+				__napi_schedule(&adapter->napi);
+			}
+		}
+		if (status & ISR_TX_PKT)
+			atl1c_clean_tx_irq(adapter, atl1c_trans_normal);
+
+		handled = IRQ_HANDLED;
+		/* check if PCIE PHY Link down */
+		if (status & ISR_ERROR) {
+			if (netif_msg_hw(adapter))
+				dev_err(&pdev->dev,
+					"atl1c hardware error (status = 0x%x)\n",
+					status & ISR_ERROR);
+			/* reset MAC */
+			adapter->work_event |= ATL1C_WORK_EVENT_RESET;
+			schedule_work(&adapter->common_task);
+			return IRQ_HANDLED;
+		}
+
+		if (status & ISR_OVER)
+			if (netif_msg_intr(adapter))
+				dev_warn(&pdev->dev,
+					"TX/RX overflow (status = 0x%x)\n",
+					status & ISR_OVER);
+
+		/* link event */
+		if (status & (ISR_GPHY | ISR_MANUAL)) {
+			netdev->stats.tx_carrier_errors++;
+			atl1c_link_chg_event(adapter);
+			break;
+		}
+
+	} while (--max_ints > 0);
+	/* re-enable Interrupt*/
+	AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+	return handled;
+}
+
+static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter,
+		  struct sk_buff *skb, struct atl1c_recv_ret_status *prrs)
+{
+	/*
+	 * The pid field in RRS in not correct sometimes, so we
+	 * cannot figure out if the packet is fragmented or not,
+	 * so we tell the KERNEL CHECKSUM_NONE
+	 */
+	skb_checksum_none_assert(skb);
+}
+
+static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid)
+{
+	struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[ringid];
+	struct pci_dev *pdev = adapter->pdev;
+	struct atl1c_buffer *buffer_info, *next_info;
+	struct sk_buff *skb;
+	void *vir_addr = NULL;
+	u16 num_alloc = 0;
+	u16 rfd_next_to_use, next_next;
+	struct atl1c_rx_free_desc *rfd_desc;
+
+	next_next = rfd_next_to_use = rfd_ring->next_to_use;
+	if (++next_next == rfd_ring->count)
+		next_next = 0;
+	buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+	next_info = &rfd_ring->buffer_info[next_next];
+
+	while (next_info->flags & ATL1C_BUFFER_FREE) {
+		rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use);
+
+		skb = dev_alloc_skb(adapter->rx_buffer_len);
+		if (unlikely(!skb)) {
+			if (netif_msg_rx_err(adapter))
+				dev_warn(&pdev->dev, "alloc rx buffer failed\n");
+			break;
+		}
+
+		/*
+		 * Make buffer alignment 2 beyond a 16 byte boundary
+		 * this will result in a 16 byte aligned IP header after
+		 * the 14 byte MAC header is removed
+		 */
+		vir_addr = skb->data;
+		ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
+		buffer_info->skb = skb;
+		buffer_info->length = adapter->rx_buffer_len;
+		buffer_info->dma = pci_map_single(pdev, vir_addr,
+						buffer_info->length,
+						PCI_DMA_FROMDEVICE);
+		ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
+			ATL1C_PCIMAP_FROMDEVICE);
+		rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+		rfd_next_to_use = next_next;
+		if (++next_next == rfd_ring->count)
+			next_next = 0;
+		buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+		next_info = &rfd_ring->buffer_info[next_next];
+		num_alloc++;
+	}
+
+	if (num_alloc) {
+		/* TODO: update mailbox here */
+		wmb();
+		rfd_ring->next_to_use = rfd_next_to_use;
+		AT_WRITE_REG(&adapter->hw, atl1c_rfd_prod_idx_regs[ringid],
+			rfd_ring->next_to_use & MB_RFDX_PROD_IDX_MASK);
+	}
+
+	return num_alloc;
+}
+
+static void atl1c_clean_rrd(struct atl1c_rrd_ring *rrd_ring,
+			struct	atl1c_recv_ret_status *rrs, u16 num)
+{
+	u16 i;
+	/* the relationship between rrd and rfd is one map one */
+	for (i = 0; i < num; i++, rrs = ATL1C_RRD_DESC(rrd_ring,
+					rrd_ring->next_to_clean)) {
+		rrs->word3 &= ~RRS_RXD_UPDATED;
+		if (++rrd_ring->next_to_clean == rrd_ring->count)
+			rrd_ring->next_to_clean = 0;
+	}
+}
+
+static void atl1c_clean_rfd(struct atl1c_rfd_ring *rfd_ring,
+	struct atl1c_recv_ret_status *rrs, u16 num)
+{
+	u16 i;
+	u16 rfd_index;
+	struct atl1c_buffer *buffer_info = rfd_ring->buffer_info;
+
+	rfd_index = (rrs->word0 >> RRS_RX_RFD_INDEX_SHIFT) &
+			RRS_RX_RFD_INDEX_MASK;
+	for (i = 0; i < num; i++) {
+		buffer_info[rfd_index].skb = NULL;
+		ATL1C_SET_BUFFER_STATE(&buffer_info[rfd_index],
+					ATL1C_BUFFER_FREE);
+		if (++rfd_index == rfd_ring->count)
+			rfd_index = 0;
+	}
+	rfd_ring->next_to_clean = rfd_index;
+}
+
+static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que,
+		   int *work_done, int work_to_do)
+{
+	u16 rfd_num, rfd_index;
+	u16 count = 0;
+	u16 length;
+	struct pci_dev *pdev = adapter->pdev;
+	struct net_device *netdev  = adapter->netdev;
+	struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[que];
+	struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring[que];
+	struct sk_buff *skb;
+	struct atl1c_recv_ret_status *rrs;
+	struct atl1c_buffer *buffer_info;
+
+	while (1) {
+		if (*work_done >= work_to_do)
+			break;
+		rrs = ATL1C_RRD_DESC(rrd_ring, rrd_ring->next_to_clean);
+		if (likely(RRS_RXD_IS_VALID(rrs->word3))) {
+			rfd_num = (rrs->word0 >> RRS_RX_RFD_CNT_SHIFT) &
+				RRS_RX_RFD_CNT_MASK;
+			if (unlikely(rfd_num != 1))
+				/* TODO support mul rfd*/
+				if (netif_msg_rx_err(adapter))
+					dev_warn(&pdev->dev,
+						"Multi rfd not support yet!\n");
+			goto rrs_checked;
+		} else {
+			break;
+		}
+rrs_checked:
+		atl1c_clean_rrd(rrd_ring, rrs, rfd_num);
+		if (rrs->word3 & (RRS_RX_ERR_SUM | RRS_802_3_LEN_ERR)) {
+			atl1c_clean_rfd(rfd_ring, rrs, rfd_num);
+				if (netif_msg_rx_err(adapter))
+					dev_warn(&pdev->dev,
+						"wrong packet! rrs word3 is %x\n",
+						rrs->word3);
+			continue;
+		}
+
+		length = le16_to_cpu((rrs->word3 >> RRS_PKT_SIZE_SHIFT) &
+				RRS_PKT_SIZE_MASK);
+		/* Good Receive */
+		if (likely(rfd_num == 1)) {
+			rfd_index = (rrs->word0 >> RRS_RX_RFD_INDEX_SHIFT) &
+					RRS_RX_RFD_INDEX_MASK;
+			buffer_info = &rfd_ring->buffer_info[rfd_index];
+			pci_unmap_single(pdev, buffer_info->dma,
+				buffer_info->length, PCI_DMA_FROMDEVICE);
+			skb = buffer_info->skb;
+		} else {
+			/* TODO */
+			if (netif_msg_rx_err(adapter))
+				dev_warn(&pdev->dev,
+					"Multi rfd not support yet!\n");
+			break;
+		}
+		atl1c_clean_rfd(rfd_ring, rrs, rfd_num);
+		skb_put(skb, length - ETH_FCS_LEN);
+		skb->protocol = eth_type_trans(skb, netdev);
+		atl1c_rx_checksum(adapter, skb, rrs);
+		if (rrs->word3 & RRS_VLAN_INS) {
+			u16 vlan;
+
+			AT_TAG_TO_VLAN(rrs->vlan_tag, vlan);
+			vlan = le16_to_cpu(vlan);
+			__vlan_hwaccel_put_tag(skb, vlan);
+		}
+		netif_receive_skb(skb);
+
+		(*work_done)++;
+		count++;
+	}
+	if (count)
+		atl1c_alloc_rx_buffer(adapter, que);
+}
+
+/*
+ * atl1c_clean - NAPI Rx polling callback
+ * @adapter: board private structure
+ */
+static int atl1c_clean(struct napi_struct *napi, int budget)
+{
+	struct atl1c_adapter *adapter =
+			container_of(napi, struct atl1c_adapter, napi);
+	int work_done = 0;
+
+	/* Keep link state information with original netdev */
+	if (!netif_carrier_ok(adapter->netdev))
+		goto quit_polling;
+	/* just enable one RXQ */
+	atl1c_clean_rx_irq(adapter, 0, &work_done, budget);
+
+	if (work_done < budget) {
+quit_polling:
+		napi_complete(napi);
+		adapter->hw.intr_mask |= ISR_RX_PKT;
+		AT_WRITE_REG(&adapter->hw, REG_IMR, adapter->hw.intr_mask);
+	}
+	return work_done;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+static void atl1c_netpoll(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	disable_irq(adapter->pdev->irq);
+	atl1c_intr(adapter->pdev->irq, netdev);
+	enable_irq(adapter->pdev->irq);
+}
+#endif
+
+static inline u16 atl1c_tpd_avail(struct atl1c_adapter *adapter, enum atl1c_trans_queue type)
+{
+	struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
+	u16 next_to_use = 0;
+	u16 next_to_clean = 0;
+
+	next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+	next_to_use   = tpd_ring->next_to_use;
+
+	return (u16)(next_to_clean > next_to_use) ?
+		(next_to_clean - next_to_use - 1) :
+		(tpd_ring->count + next_to_clean - next_to_use - 1);
+}
+
+/*
+ * get next usable tpd
+ * Note: should call atl1c_tdp_avail to make sure
+ * there is enough tpd to use
+ */
+static struct atl1c_tpd_desc *atl1c_get_tpd(struct atl1c_adapter *adapter,
+	enum atl1c_trans_queue type)
+{
+	struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
+	struct atl1c_tpd_desc *tpd_desc;
+	u16 next_to_use = 0;
+
+	next_to_use = tpd_ring->next_to_use;
+	if (++tpd_ring->next_to_use == tpd_ring->count)
+		tpd_ring->next_to_use = 0;
+	tpd_desc = ATL1C_TPD_DESC(tpd_ring, next_to_use);
+	memset(tpd_desc, 0, sizeof(struct atl1c_tpd_desc));
+	return	tpd_desc;
+}
+
+static struct atl1c_buffer *
+atl1c_get_tx_buffer(struct atl1c_adapter *adapter, struct atl1c_tpd_desc *tpd)
+{
+	struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring;
+
+	return &tpd_ring->buffer_info[tpd -
+			(struct atl1c_tpd_desc *)tpd_ring->desc];
+}
+
+/* Calculate the transmit packet descript needed*/
+static u16 atl1c_cal_tpd_req(const struct sk_buff *skb)
+{
+	u16 tpd_req;
+	u16 proto_hdr_len = 0;
+
+	tpd_req = skb_shinfo(skb)->nr_frags + 1;
+
+	if (skb_is_gso(skb)) {
+		proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+		if (proto_hdr_len < skb_headlen(skb))
+			tpd_req++;
+		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+			tpd_req++;
+	}
+	return tpd_req;
+}
+
+static int atl1c_tso_csum(struct atl1c_adapter *adapter,
+			  struct sk_buff *skb,
+			  struct atl1c_tpd_desc **tpd,
+			  enum atl1c_trans_queue type)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	u8 hdr_len;
+	u32 real_len;
+	unsigned short offload_type;
+	int err;
+
+	if (skb_is_gso(skb)) {
+		if (skb_header_cloned(skb)) {
+			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+			if (unlikely(err))
+				return -1;
+		}
+		offload_type = skb_shinfo(skb)->gso_type;
+
+		if (offload_type & SKB_GSO_TCPV4) {
+			real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
+					+ ntohs(ip_hdr(skb)->tot_len));
+
+			if (real_len < skb->len)
+				pskb_trim(skb, real_len);
+
+			hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
+			if (unlikely(skb->len == hdr_len)) {
+				/* only xsum need */
+				if (netif_msg_tx_queued(adapter))
+					dev_warn(&pdev->dev,
+						"IPV4 tso with zero data??\n");
+				goto check_sum;
+			} else {
+				ip_hdr(skb)->check = 0;
+				tcp_hdr(skb)->check = ~csum_tcpudp_magic(
+							ip_hdr(skb)->saddr,
+							ip_hdr(skb)->daddr,
+							0, IPPROTO_TCP, 0);
+				(*tpd)->word1 |= 1 << TPD_IPV4_PACKET_SHIFT;
+			}
+		}
+
+		if (offload_type & SKB_GSO_TCPV6) {
+			struct atl1c_tpd_ext_desc *etpd =
+				*(struct atl1c_tpd_ext_desc **)(tpd);
+
+			memset(etpd, 0, sizeof(struct atl1c_tpd_ext_desc));
+			*tpd = atl1c_get_tpd(adapter, type);
+			ipv6_hdr(skb)->payload_len = 0;
+			/* check payload == 0 byte ? */
+			hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
+			if (unlikely(skb->len == hdr_len)) {
+				/* only xsum need */
+				if (netif_msg_tx_queued(adapter))
+					dev_warn(&pdev->dev,
+						"IPV6 tso with zero data??\n");
+				goto check_sum;
+			} else
+				tcp_hdr(skb)->check = ~csum_ipv6_magic(
+						&ipv6_hdr(skb)->saddr,
+						&ipv6_hdr(skb)->daddr,
+						0, IPPROTO_TCP, 0);
+			etpd->word1 |= 1 << TPD_LSO_EN_SHIFT;
+			etpd->word1 |= 1 << TPD_LSO_VER_SHIFT;
+			etpd->pkt_len = cpu_to_le32(skb->len);
+			(*tpd)->word1 |= 1 << TPD_LSO_VER_SHIFT;
+		}
+
+		(*tpd)->word1 |= 1 << TPD_LSO_EN_SHIFT;
+		(*tpd)->word1 |= (skb_transport_offset(skb) & TPD_TCPHDR_OFFSET_MASK) <<
+				TPD_TCPHDR_OFFSET_SHIFT;
+		(*tpd)->word1 |= (skb_shinfo(skb)->gso_size & TPD_MSS_MASK) <<
+				TPD_MSS_SHIFT;
+		return 0;
+	}
+
+check_sum:
+	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+		u8 css, cso;
+		cso = skb_checksum_start_offset(skb);
+
+		if (unlikely(cso & 0x1)) {
+			if (netif_msg_tx_err(adapter))
+				dev_err(&adapter->pdev->dev,
+					"payload offset should not an event number\n");
+			return -1;
+		} else {
+			css = cso + skb->csum_offset;
+
+			(*tpd)->word1 |= ((cso >> 1) & TPD_PLOADOFFSET_MASK) <<
+					TPD_PLOADOFFSET_SHIFT;
+			(*tpd)->word1 |= ((css >> 1) & TPD_CCSUM_OFFSET_MASK) <<
+					TPD_CCSUM_OFFSET_SHIFT;
+			(*tpd)->word1 |= 1 << TPD_CCSUM_EN_SHIFT;
+		}
+	}
+	return 0;
+}
+
+static void atl1c_tx_map(struct atl1c_adapter *adapter,
+		      struct sk_buff *skb, struct atl1c_tpd_desc *tpd,
+			enum atl1c_trans_queue type)
+{
+	struct atl1c_tpd_desc *use_tpd = NULL;
+	struct atl1c_buffer *buffer_info = NULL;
+	u16 buf_len = skb_headlen(skb);
+	u16 map_len = 0;
+	u16 mapped_len = 0;
+	u16 hdr_len = 0;
+	u16 nr_frags;
+	u16 f;
+	int tso;
+
+	nr_frags = skb_shinfo(skb)->nr_frags;
+	tso = (tpd->word1 >> TPD_LSO_EN_SHIFT) & TPD_LSO_EN_MASK;
+	if (tso) {
+		/* TSO */
+		map_len = hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+		use_tpd = tpd;
+
+		buffer_info = atl1c_get_tx_buffer(adapter, use_tpd);
+		buffer_info->length = map_len;
+		buffer_info->dma = pci_map_single(adapter->pdev,
+					skb->data, hdr_len, PCI_DMA_TODEVICE);
+		ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
+		ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
+			ATL1C_PCIMAP_TODEVICE);
+		mapped_len += map_len;
+		use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
+		use_tpd->buffer_len = cpu_to_le16(buffer_info->length);
+	}
+
+	if (mapped_len < buf_len) {
+		/* mapped_len == 0, means we should use the first tpd,
+		   which is given by caller  */
+		if (mapped_len == 0)
+			use_tpd = tpd;
+		else {
+			use_tpd = atl1c_get_tpd(adapter, type);
+			memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc));
+		}
+		buffer_info = atl1c_get_tx_buffer(adapter, use_tpd);
+		buffer_info->length = buf_len - mapped_len;
+		buffer_info->dma =
+			pci_map_single(adapter->pdev, skb->data + mapped_len,
+					buffer_info->length, PCI_DMA_TODEVICE);
+		ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
+		ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
+			ATL1C_PCIMAP_TODEVICE);
+		use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
+		use_tpd->buffer_len  = cpu_to_le16(buffer_info->length);
+	}
+
+	for (f = 0; f < nr_frags; f++) {
+		struct skb_frag_struct *frag;
+
+		frag = &skb_shinfo(skb)->frags[f];
+
+		use_tpd = atl1c_get_tpd(adapter, type);
+		memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc));
+
+		buffer_info = atl1c_get_tx_buffer(adapter, use_tpd);
+		buffer_info->length = skb_frag_size(frag);
+		buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev,
+						    frag, 0,
+						    buffer_info->length,
+						    DMA_TO_DEVICE);
+		ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
+		ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE,
+			ATL1C_PCIMAP_TODEVICE);
+		use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
+		use_tpd->buffer_len  = cpu_to_le16(buffer_info->length);
+	}
+
+	/* The last tpd */
+	use_tpd->word1 |= 1 << TPD_EOP_SHIFT;
+	/* The last buffer info contain the skb address,
+	   so it will be free after unmap */
+	buffer_info->skb = skb;
+}
+
+static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb,
+			   struct atl1c_tpd_desc *tpd, enum atl1c_trans_queue type)
+{
+	struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
+	u32 prod_data;
+
+	AT_READ_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, &prod_data);
+	switch (type) {
+	case atl1c_trans_high:
+		prod_data &= 0xFFFF0000;
+		prod_data |= tpd_ring->next_to_use & 0xFFFF;
+		break;
+	case atl1c_trans_normal:
+		prod_data &= 0x0000FFFF;
+		prod_data |= (tpd_ring->next_to_use & 0xFFFF) << 16;
+		break;
+	default:
+		break;
+	}
+	wmb();
+	AT_WRITE_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, prod_data);
+}
+
+static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb,
+					  struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
+	u16 tpd_req = 1;
+	struct atl1c_tpd_desc *tpd;
+	enum atl1c_trans_queue type = atl1c_trans_normal;
+
+	if (test_bit(__AT_DOWN, &adapter->flags)) {
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
+	tpd_req = atl1c_cal_tpd_req(skb);
+	if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) {
+		if (netif_msg_pktdata(adapter))
+			dev_info(&adapter->pdev->dev, "tx locked\n");
+		return NETDEV_TX_LOCKED;
+	}
+	if (skb->mark == 0x01)
+		type = atl1c_trans_high;
+	else
+		type = atl1c_trans_normal;
+
+	if (atl1c_tpd_avail(adapter, type) < tpd_req) {
+		/* no enough descriptor, just stop queue */
+		netif_stop_queue(netdev);
+		spin_unlock_irqrestore(&adapter->tx_lock, flags);
+		return NETDEV_TX_BUSY;
+	}
+
+	tpd = atl1c_get_tpd(adapter, type);
+
+	/* do TSO and check sum */
+	if (atl1c_tso_csum(adapter, skb, &tpd, type) != 0) {
+		spin_unlock_irqrestore(&adapter->tx_lock, flags);
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
+	if (unlikely(vlan_tx_tag_present(skb))) {
+		u16 vlan = vlan_tx_tag_get(skb);
+		__le16 tag;
+
+		vlan = cpu_to_le16(vlan);
+		AT_VLAN_TO_TAG(vlan, tag);
+		tpd->word1 |= 1 << TPD_INS_VTAG_SHIFT;
+		tpd->vlan_tag = tag;
+	}
+
+	if (skb_network_offset(skb) != ETH_HLEN)
+		tpd->word1 |= 1 << TPD_ETH_TYPE_SHIFT; /* Ethernet frame */
+
+	atl1c_tx_map(adapter, skb, tpd, type);
+	atl1c_tx_queue(adapter, skb, tpd, type);
+
+	spin_unlock_irqrestore(&adapter->tx_lock, flags);
+	return NETDEV_TX_OK;
+}
+
+static void atl1c_free_irq(struct atl1c_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	free_irq(adapter->pdev->irq, netdev);
+
+	if (adapter->have_msi)
+		pci_disable_msi(adapter->pdev);
+}
+
+static int atl1c_request_irq(struct atl1c_adapter *adapter)
+{
+	struct pci_dev    *pdev   = adapter->pdev;
+	struct net_device *netdev = adapter->netdev;
+	int flags = 0;
+	int err = 0;
+
+	adapter->have_msi = true;
+	err = pci_enable_msi(adapter->pdev);
+	if (err) {
+		if (netif_msg_ifup(adapter))
+			dev_err(&pdev->dev,
+				"Unable to allocate MSI interrupt Error: %d\n",
+				err);
+		adapter->have_msi = false;
+	} else
+		netdev->irq = pdev->irq;
+
+	if (!adapter->have_msi)
+		flags |= IRQF_SHARED;
+	err = request_irq(adapter->pdev->irq, atl1c_intr, flags,
+			netdev->name, netdev);
+	if (err) {
+		if (netif_msg_ifup(adapter))
+			dev_err(&pdev->dev,
+				"Unable to allocate interrupt Error: %d\n",
+				err);
+		if (adapter->have_msi)
+			pci_disable_msi(adapter->pdev);
+		return err;
+	}
+	if (netif_msg_ifup(adapter))
+		dev_dbg(&pdev->dev, "atl1c_request_irq OK\n");
+	return err;
+}
+
+static int atl1c_up(struct atl1c_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	int num;
+	int err;
+	int i;
+
+	netif_carrier_off(netdev);
+	atl1c_init_ring_ptrs(adapter);
+	atl1c_set_multi(netdev);
+	atl1c_restore_vlan(adapter);
+
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		num = atl1c_alloc_rx_buffer(adapter, i);
+		if (unlikely(num == 0)) {
+			err = -ENOMEM;
+			goto err_alloc_rx;
+		}
+	}
+
+	if (atl1c_configure(adapter)) {
+		err = -EIO;
+		goto err_up;
+	}
+
+	err = atl1c_request_irq(adapter);
+	if (unlikely(err))
+		goto err_up;
+
+	clear_bit(__AT_DOWN, &adapter->flags);
+	napi_enable(&adapter->napi);
+	atl1c_irq_enable(adapter);
+	atl1c_check_link_status(adapter);
+	netif_start_queue(netdev);
+	return err;
+
+err_up:
+err_alloc_rx:
+	atl1c_clean_rx_ring(adapter);
+	return err;
+}
+
+static void atl1c_down(struct atl1c_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	atl1c_del_timer(adapter);
+	adapter->work_event = 0; /* clear all event */
+	/* signal that we're down so the interrupt handler does not
+	 * reschedule our watchdog timer */
+	set_bit(__AT_DOWN, &adapter->flags);
+	netif_carrier_off(netdev);
+	napi_disable(&adapter->napi);
+	atl1c_irq_disable(adapter);
+	atl1c_free_irq(adapter);
+	/* reset MAC to disable all RX/TX */
+	atl1c_reset_mac(&adapter->hw);
+	msleep(1);
+
+	adapter->link_speed = SPEED_0;
+	adapter->link_duplex = -1;
+	atl1c_clean_tx_ring(adapter, atl1c_trans_normal);
+	atl1c_clean_tx_ring(adapter, atl1c_trans_high);
+	atl1c_clean_rx_ring(adapter);
+}
+
+/*
+ * atl1c_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * 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.
+ */
+static int atl1c_open(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	int err;
+
+	/* disallow open during test */
+	if (test_bit(__AT_TESTING, &adapter->flags))
+		return -EBUSY;
+
+	/* allocate rx/tx dma buffer & descriptors */
+	err = atl1c_setup_ring_resources(adapter);
+	if (unlikely(err))
+		return err;
+
+	err = atl1c_up(adapter);
+	if (unlikely(err))
+		goto err_up;
+
+	if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) {
+		u32 phy_data;
+
+		AT_READ_REG(&adapter->hw, REG_MDIO_CTRL, &phy_data);
+		phy_data |= MDIO_AP_EN;
+		AT_WRITE_REG(&adapter->hw, REG_MDIO_CTRL, phy_data);
+	}
+	return 0;
+
+err_up:
+	atl1c_free_irq(adapter);
+	atl1c_free_ring_resources(adapter);
+	atl1c_reset_mac(&adapter->hw);
+	return err;
+}
+
+/*
+ * atl1c_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * 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.
+ */
+static int atl1c_close(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
+	atl1c_down(adapter);
+	atl1c_free_ring_resources(adapter);
+	return 0;
+}
+
+static int atl1c_suspend(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct atl1c_hw *hw = &adapter->hw;
+	u32 mac_ctrl_data = 0;
+	u32 master_ctrl_data = 0;
+	u32 wol_ctrl_data = 0;
+	u16 mii_intr_status_data = 0;
+	u32 wufc = adapter->wol;
+
+	atl1c_disable_l0s_l1(hw);
+	if (netif_running(netdev)) {
+		WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
+		atl1c_down(adapter);
+	}
+	netif_device_detach(netdev);
+
+	if (wufc)
+		if (atl1c_phy_power_saving(hw) != 0)
+			dev_dbg(&pdev->dev, "phy power saving failed");
+
+	AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
+	AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data);
+
+	master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS;
+	mac_ctrl_data &= ~(MAC_CTRL_PRMLEN_MASK << MAC_CTRL_PRMLEN_SHIFT);
+	mac_ctrl_data |= (((u32)adapter->hw.preamble_len &
+			MAC_CTRL_PRMLEN_MASK) <<
+			MAC_CTRL_PRMLEN_SHIFT);
+	mac_ctrl_data &= ~(MAC_CTRL_SPEED_MASK << MAC_CTRL_SPEED_SHIFT);
+	mac_ctrl_data &= ~MAC_CTRL_DUPLX;
+
+	if (wufc) {
+		mac_ctrl_data |= MAC_CTRL_RX_EN;
+		if (adapter->link_speed == SPEED_1000 ||
+			adapter->link_speed == SPEED_0) {
+			mac_ctrl_data |= atl1c_mac_speed_1000 <<
+					MAC_CTRL_SPEED_SHIFT;
+			mac_ctrl_data |= MAC_CTRL_DUPLX;
+		} else
+			mac_ctrl_data |= atl1c_mac_speed_10_100 <<
+					MAC_CTRL_SPEED_SHIFT;
+
+		if (adapter->link_duplex == DUPLEX_FULL)
+			mac_ctrl_data |= MAC_CTRL_DUPLX;
+
+		/* turn on magic packet wol */
+		if (wufc & AT_WUFC_MAG)
+			wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
+
+		if (wufc & AT_WUFC_LNKC) {
+			wol_ctrl_data |=  WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
+			/* only link up can wake up */
+			if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) {
+				dev_dbg(&pdev->dev, "%s: read write phy "
+						  "register failed.\n",
+						  atl1c_driver_name);
+			}
+		}
+		/* clear phy interrupt */
+		atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data);
+		/* Config MAC Ctrl register */
+		__atl1c_vlan_mode(netdev->features, &mac_ctrl_data);
+
+		/* magic packet maybe Broadcast&multicast&Unicast frame */
+		if (wufc & AT_WUFC_MAG)
+			mac_ctrl_data |= MAC_CTRL_BC_EN;
+
+		dev_dbg(&pdev->dev,
+			"%s: suspend MAC=0x%x\n",
+			atl1c_driver_name, mac_ctrl_data);
+		AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
+		AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);
+		AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+
+		AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |
+			GPHY_CTRL_EXT_RESET);
+	} else {
+		AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_POWER_SAVING);
+		master_ctrl_data |= MASTER_CTRL_CLK_SEL_DIS;
+		mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT;
+		mac_ctrl_data |= MAC_CTRL_DUPLX;
+		AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
+		AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+		AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+		hw->phy_configured = false; /* re-init PHY when resume */
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int atl1c_resume(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
+	atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE |
+			ATL1C_PCIE_PHY_RESET);
+
+	atl1c_phy_reset(&adapter->hw);
+	atl1c_reset_mac(&adapter->hw);
+	atl1c_phy_init(&adapter->hw);
+
+#if 0
+	AT_READ_REG(&adapter->hw, REG_PM_CTRLSTAT, &pm_data);
+	pm_data &= ~PM_CTRLSTAT_PME_EN;
+	AT_WRITE_REG(&adapter->hw, REG_PM_CTRLSTAT, pm_data);
+#endif
+
+	netif_device_attach(netdev);
+	if (netif_running(netdev))
+		atl1c_up(adapter);
+
+	return 0;
+}
+#endif
+
+static void atl1c_shutdown(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	atl1c_suspend(&pdev->dev);
+	pci_wake_from_d3(pdev, adapter->wol);
+	pci_set_power_state(pdev, PCI_D3hot);
+}
+
+static const struct net_device_ops atl1c_netdev_ops = {
+	.ndo_open		= atl1c_open,
+	.ndo_stop		= atl1c_close,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_start_xmit		= atl1c_xmit_frame,
+	.ndo_set_mac_address	= atl1c_set_mac_addr,
+	.ndo_set_rx_mode	= atl1c_set_multi,
+	.ndo_change_mtu		= atl1c_change_mtu,
+	.ndo_fix_features	= atl1c_fix_features,
+	.ndo_set_features	= atl1c_set_features,
+	.ndo_do_ioctl		= atl1c_ioctl,
+	.ndo_tx_timeout		= atl1c_tx_timeout,
+	.ndo_get_stats		= atl1c_get_stats,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= atl1c_netpoll,
+#endif
+};
+
+static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
+{
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+	pci_set_drvdata(pdev, netdev);
+
+	netdev->irq  = pdev->irq;
+	netdev->netdev_ops = &atl1c_netdev_ops;
+	netdev->watchdog_timeo = AT_TX_WATCHDOG;
+	atl1c_set_ethtool_ops(netdev);
+
+	/* TODO: add when ready */
+	netdev->hw_features =	NETIF_F_SG	   |
+				NETIF_F_HW_CSUM	   |
+				NETIF_F_HW_VLAN_RX |
+				NETIF_F_TSO	   |
+				NETIF_F_TSO6;
+	netdev->features =	netdev->hw_features |
+				NETIF_F_HW_VLAN_TX;
+	return 0;
+}
+
+/*
+ * atl1c_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in atl1c_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * atl1c_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ */
+static int __devinit atl1c_probe(struct pci_dev *pdev,
+				 const struct pci_device_id *ent)
+{
+	struct net_device *netdev;
+	struct atl1c_adapter *adapter;
+	static int cards_found;
+
+	int err = 0;
+
+	/* enable device (incl. PCI PM wakeup and hotplug setup) */
+	err = pci_enable_device_mem(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "cannot enable PCI device\n");
+		return err;
+	}
+
+	/*
+	 * The atl1c chip can DMA to 64-bit addresses, but it uses a single
+	 * shared register for the high 32 bits, so only a single, aligned,
+	 * 4 GB physical address range can be used at a time.
+	 *
+	 * Supporting 64-bit DMA on this hardware is more trouble than it's
+	 * worth.  It is far easier to limit to 32-bit DMA than update
+	 * various kernel subsystems to support the mechanics required by a
+	 * fixed-high-32-bit system.
+	 */
+	if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) ||
+	    (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)) {
+		dev_err(&pdev->dev, "No usable DMA configuration,aborting\n");
+		goto err_dma;
+	}
+
+	err = pci_request_regions(pdev, atl1c_driver_name);
+	if (err) {
+		dev_err(&pdev->dev, "cannot obtain PCI resources\n");
+		goto err_pci_reg;
+	}
+
+	pci_set_master(pdev);
+
+	netdev = alloc_etherdev(sizeof(struct atl1c_adapter));
+	if (netdev == NULL) {
+		err = -ENOMEM;
+		dev_err(&pdev->dev, "etherdev alloc failed\n");
+		goto err_alloc_etherdev;
+	}
+
+	err = atl1c_init_netdev(netdev, pdev);
+	if (err) {
+		dev_err(&pdev->dev, "init netdevice failed\n");
+		goto err_init_netdev;
+	}
+	adapter = netdev_priv(netdev);
+	adapter->bd_number = cards_found;
+	adapter->netdev = netdev;
+	adapter->pdev = pdev;
+	adapter->hw.adapter = adapter;
+	adapter->msg_enable = netif_msg_init(-1, atl1c_default_msg);
+	adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+	if (!adapter->hw.hw_addr) {
+		err = -EIO;
+		dev_err(&pdev->dev, "cannot map device registers\n");
+		goto err_ioremap;
+	}
+	netdev->base_addr = (unsigned long)adapter->hw.hw_addr;
+
+	/* init mii data */
+	adapter->mii.dev = netdev;
+	adapter->mii.mdio_read  = atl1c_mdio_read;
+	adapter->mii.mdio_write = atl1c_mdio_write;
+	adapter->mii.phy_id_mask = 0x1f;
+	adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK;
+	netif_napi_add(netdev, &adapter->napi, atl1c_clean, 64);
+	setup_timer(&adapter->phy_config_timer, atl1c_phy_config,
+			(unsigned long)adapter);
+	/* setup the private structure */
+	err = atl1c_sw_init(adapter);
+	if (err) {
+		dev_err(&pdev->dev, "net device private data init failed\n");
+		goto err_sw_init;
+	}
+	atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE |
+			ATL1C_PCIE_PHY_RESET);
+
+	/* Init GPHY as early as possible due to power saving issue  */
+	atl1c_phy_reset(&adapter->hw);
+
+	err = atl1c_reset_mac(&adapter->hw);
+	if (err) {
+		err = -EIO;
+		goto err_reset;
+	}
+
+	/* reset the controller to
+	 * put the device in a known good starting state */
+	err = atl1c_phy_init(&adapter->hw);
+	if (err) {
+		err = -EIO;
+		goto err_reset;
+	}
+	if (atl1c_read_mac_addr(&adapter->hw) != 0) {
+		err = -EIO;
+		dev_err(&pdev->dev, "get mac address failed\n");
+		goto err_eeprom;
+	}
+	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+	memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
+	if (netif_msg_probe(adapter))
+		dev_dbg(&pdev->dev, "mac address : %pM\n",
+			adapter->hw.mac_addr);
+
+	atl1c_hw_set_mac_addr(&adapter->hw);
+	INIT_WORK(&adapter->common_task, atl1c_common_task);
+	adapter->work_event = 0;
+	err = register_netdev(netdev);
+	if (err) {
+		dev_err(&pdev->dev, "register netdevice failed\n");
+		goto err_register;
+	}
+
+	if (netif_msg_probe(adapter))
+		dev_info(&pdev->dev, "version %s\n", ATL1C_DRV_VERSION);
+	cards_found++;
+	return 0;
+
+err_reset:
+err_register:
+err_sw_init:
+err_eeprom:
+	iounmap(adapter->hw.hw_addr);
+err_init_netdev:
+err_ioremap:
+	free_netdev(netdev);
+err_alloc_etherdev:
+	pci_release_regions(pdev);
+err_pci_reg:
+err_dma:
+	pci_disable_device(pdev);
+	return err;
+}
+
+/*
+ * atl1c_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * atl1c_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.  The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ */
+static void __devexit atl1c_remove(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	unregister_netdev(netdev);
+	atl1c_phy_disable(&adapter->hw);
+
+	iounmap(adapter->hw.hw_addr);
+
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	free_netdev(netdev);
+}
+
+/*
+ * atl1c_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci connection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t atl1c_io_error_detected(struct pci_dev *pdev,
+						pci_channel_state_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	netif_device_detach(netdev);
+
+	if (state == pci_channel_io_perm_failure)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	if (netif_running(netdev))
+		atl1c_down(adapter);
+
+	pci_disable_device(pdev);
+
+	/* Request a slot slot reset. */
+	return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/*
+ * atl1c_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot. Implementation
+ * resembles the first-half of the e1000_resume routine.
+ */
+static pci_ers_result_t atl1c_io_slot_reset(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	if (pci_enable_device(pdev)) {
+		if (netif_msg_hw(adapter))
+			dev_err(&pdev->dev,
+				"Cannot re-enable PCI device after reset\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+	pci_set_master(pdev);
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_enable_wake(pdev, PCI_D3cold, 0);
+
+	atl1c_reset_mac(&adapter->hw);
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+/*
+ * atl1c_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells us that
+ * its OK to resume normal operation. Implementation resembles the
+ * second-half of the atl1c_resume routine.
+ */
+static void atl1c_io_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	if (netif_running(netdev)) {
+		if (atl1c_up(adapter)) {
+			if (netif_msg_hw(adapter))
+				dev_err(&pdev->dev,
+					"Cannot bring device back up after reset\n");
+			return;
+		}
+	}
+
+	netif_device_attach(netdev);
+}
+
+static struct pci_error_handlers atl1c_err_handler = {
+	.error_detected = atl1c_io_error_detected,
+	.slot_reset = atl1c_io_slot_reset,
+	.resume = atl1c_io_resume,
+};
+
+static SIMPLE_DEV_PM_OPS(atl1c_pm_ops, atl1c_suspend, atl1c_resume);
+
+static struct pci_driver atl1c_driver = {
+	.name     = atl1c_driver_name,
+	.id_table = atl1c_pci_tbl,
+	.probe    = atl1c_probe,
+	.remove   = __devexit_p(atl1c_remove),
+	.shutdown = atl1c_shutdown,
+	.err_handler = &atl1c_err_handler,
+	.driver.pm = &atl1c_pm_ops,
+};
+
+/*
+ * atl1c_init_module - Driver Registration Routine
+ *
+ * atl1c_init_module is the first routine called when the driver is
+ * loaded. All it does is register with the PCI subsystem.
+ */
+static int __init atl1c_init_module(void)
+{
+	return pci_register_driver(&atl1c_driver);
+}
+
+/*
+ * atl1c_exit_module - Driver Exit Cleanup Routine
+ *
+ * atl1c_exit_module is called just before the driver is removed
+ * from memory.
+ */
+static void __exit atl1c_exit_module(void)
+{
+	pci_unregister_driver(&atl1c_driver);
+}
+
+module_init(atl1c_init_module);
+module_exit(atl1c_exit_module);
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1c/Makefile linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1c/Makefile
--- linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1c/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1c/Makefile	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ATL1C) += atl1c.o
+atl1c-objs := atl1c_main.o atl1c_hw.o atl1c_ethtool.o
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,390 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You 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/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/slab.h>
+
+#include "atl1e.h"
+
+static int atl1e_get_settings(struct net_device *netdev,
+			      struct ethtool_cmd *ecmd)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct atl1e_hw *hw = &adapter->hw;
+
+	ecmd->supported = (SUPPORTED_10baseT_Half  |
+			   SUPPORTED_10baseT_Full  |
+			   SUPPORTED_100baseT_Half |
+			   SUPPORTED_100baseT_Full |
+			   SUPPORTED_Autoneg       |
+			   SUPPORTED_TP);
+	if (hw->nic_type == athr_l1e)
+		ecmd->supported |= SUPPORTED_1000baseT_Full;
+
+	ecmd->advertising = ADVERTISED_TP;
+
+	ecmd->advertising |= ADVERTISED_Autoneg;
+	ecmd->advertising |= hw->autoneg_advertised;
+
+	ecmd->port = PORT_TP;
+	ecmd->phy_address = 0;
+	ecmd->transceiver = XCVR_INTERNAL;
+
+	if (adapter->link_speed != SPEED_0) {
+		ethtool_cmd_speed_set(ecmd, adapter->link_speed);
+		if (adapter->link_duplex == FULL_DUPLEX)
+			ecmd->duplex = DUPLEX_FULL;
+		else
+			ecmd->duplex = DUPLEX_HALF;
+	} else {
+		ethtool_cmd_speed_set(ecmd, -1);
+		ecmd->duplex = -1;
+	}
+
+	ecmd->autoneg = AUTONEG_ENABLE;
+	return 0;
+}
+
+static int atl1e_set_settings(struct net_device *netdev,
+			      struct ethtool_cmd *ecmd)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct atl1e_hw *hw = &adapter->hw;
+
+	while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+		msleep(1);
+
+	if (ecmd->autoneg == AUTONEG_ENABLE) {
+		u16 adv4, adv9;
+
+		if ((ecmd->advertising&ADVERTISE_1000_FULL)) {
+			if (hw->nic_type == athr_l1e) {
+				hw->autoneg_advertised =
+					ecmd->advertising & AT_ADV_MASK;
+			} else {
+				clear_bit(__AT_RESETTING, &adapter->flags);
+				return -EINVAL;
+			}
+		} else if (ecmd->advertising&ADVERTISE_1000_HALF) {
+			clear_bit(__AT_RESETTING, &adapter->flags);
+			return -EINVAL;
+		} else {
+			hw->autoneg_advertised =
+				ecmd->advertising & AT_ADV_MASK;
+		}
+		ecmd->advertising = hw->autoneg_advertised |
+				    ADVERTISED_TP | ADVERTISED_Autoneg;
+
+		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 |= ADVERTISE_10HALF;
+		if (hw->autoneg_advertised & ADVERTISE_10_FULL)
+			adv4 |= ADVERTISE_10FULL;
+		if (hw->autoneg_advertised & ADVERTISE_100_HALF)
+			adv4 |= ADVERTISE_100HALF;
+		if (hw->autoneg_advertised & ADVERTISE_100_FULL)
+			adv4 |= ADVERTISE_100FULL;
+		if (hw->autoneg_advertised & ADVERTISE_1000_FULL)
+			adv9 |= ADVERTISE_1000FULL;
+
+		if (adv4 != hw->mii_autoneg_adv_reg ||
+				adv9 != hw->mii_1000t_ctrl_reg) {
+			hw->mii_autoneg_adv_reg = adv4;
+			hw->mii_1000t_ctrl_reg = adv9;
+			hw->re_autoneg = true;
+		}
+
+	} else {
+		clear_bit(__AT_RESETTING, &adapter->flags);
+		return -EINVAL;
+	}
+
+	/* reset the link */
+
+	if (netif_running(adapter->netdev)) {
+		atl1e_down(adapter);
+		atl1e_up(adapter);
+	} else
+		atl1e_reset_hw(&adapter->hw);
+
+	clear_bit(__AT_RESETTING, &adapter->flags);
+	return 0;
+}
+
+static u32 atl1e_get_msglevel(struct net_device *netdev)
+{
+#ifdef DBG
+	return 1;
+#else
+	return 0;
+#endif
+}
+
+static int atl1e_get_regs_len(struct net_device *netdev)
+{
+	return AT_REGS_LEN * sizeof(u32);
+}
+
+static void atl1e_get_regs(struct net_device *netdev,
+			   struct ethtool_regs *regs, void *p)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct atl1e_hw *hw = &adapter->hw;
+	u32 *regs_buff = p;
+	u16 phy_data;
+
+	memset(p, 0, AT_REGS_LEN * sizeof(u32));
+
+	regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
+
+	regs_buff[0]  = AT_READ_REG(hw, REG_VPD_CAP);
+	regs_buff[1]  = AT_READ_REG(hw, REG_SPI_FLASH_CTRL);
+	regs_buff[2]  = AT_READ_REG(hw, REG_SPI_FLASH_CONFIG);
+	regs_buff[3]  = AT_READ_REG(hw, REG_TWSI_CTRL);
+	regs_buff[4]  = AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL);
+	regs_buff[5]  = AT_READ_REG(hw, REG_MASTER_CTRL);
+	regs_buff[6]  = AT_READ_REG(hw, REG_MANUAL_TIMER_INIT);
+	regs_buff[7]  = AT_READ_REG(hw, REG_IRQ_MODU_TIMER_INIT);
+	regs_buff[8]  = AT_READ_REG(hw, REG_GPHY_CTRL);
+	regs_buff[9]  = AT_READ_REG(hw, REG_CMBDISDMA_TIMER);
+	regs_buff[10] = AT_READ_REG(hw, REG_IDLE_STATUS);
+	regs_buff[11] = AT_READ_REG(hw, REG_MDIO_CTRL);
+	regs_buff[12] = AT_READ_REG(hw, REG_SERDES_LOCK);
+	regs_buff[13] = AT_READ_REG(hw, REG_MAC_CTRL);
+	regs_buff[14] = AT_READ_REG(hw, REG_MAC_IPG_IFG);
+	regs_buff[15] = AT_READ_REG(hw, REG_MAC_STA_ADDR);
+	regs_buff[16] = AT_READ_REG(hw, REG_MAC_STA_ADDR+4);
+	regs_buff[17] = AT_READ_REG(hw, REG_RX_HASH_TABLE);
+	regs_buff[18] = AT_READ_REG(hw, REG_RX_HASH_TABLE+4);
+	regs_buff[19] = AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL);
+	regs_buff[20] = AT_READ_REG(hw, REG_MTU);
+	regs_buff[21] = AT_READ_REG(hw, REG_WOL_CTRL);
+	regs_buff[22] = AT_READ_REG(hw, REG_SRAM_TRD_ADDR);
+	regs_buff[23] = AT_READ_REG(hw, REG_SRAM_TRD_LEN);
+	regs_buff[24] = AT_READ_REG(hw, REG_SRAM_RXF_ADDR);
+	regs_buff[25] = AT_READ_REG(hw, REG_SRAM_RXF_LEN);
+	regs_buff[26] = AT_READ_REG(hw, REG_SRAM_TXF_ADDR);
+	regs_buff[27] = AT_READ_REG(hw, REG_SRAM_TXF_LEN);
+	regs_buff[28] = AT_READ_REG(hw, REG_SRAM_TCPH_ADDR);
+	regs_buff[29] = AT_READ_REG(hw, REG_SRAM_PKTH_ADDR);
+
+	atl1e_read_phy_reg(hw, MII_BMCR, &phy_data);
+	regs_buff[73] = (u32)phy_data;
+	atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
+	regs_buff[74] = (u32)phy_data;
+}
+
+static int atl1e_get_eeprom_len(struct net_device *netdev)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+	if (!atl1e_check_eeprom_exist(&adapter->hw))
+		return AT_EEPROM_LEN;
+	else
+		return 0;
+}
+
+static int atl1e_get_eeprom(struct net_device *netdev,
+		struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct atl1e_hw *hw = &adapter->hw;
+	u32 *eeprom_buff;
+	int first_dword, last_dword;
+	int ret_val = 0;
+	int i;
+
+	if (eeprom->len == 0)
+		return -EINVAL;
+
+	if (atl1e_check_eeprom_exist(hw)) /* not exist */
+		return -EINVAL;
+
+	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
+
+	first_dword = eeprom->offset >> 2;
+	last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
+
+	eeprom_buff = kmalloc(sizeof(u32) *
+			(last_dword - first_dword + 1), GFP_KERNEL);
+	if (eeprom_buff == NULL)
+		return -ENOMEM;
+
+	for (i = first_dword; i < last_dword; i++) {
+		if (!atl1e_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) {
+			kfree(eeprom_buff);
+			return -EIO;
+		}
+	}
+
+	memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3),
+			eeprom->len);
+	kfree(eeprom_buff);
+
+	return ret_val;
+}
+
+static int atl1e_set_eeprom(struct net_device *netdev,
+			    struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct atl1e_hw *hw = &adapter->hw;
+	u32 *eeprom_buff;
+	u32 *ptr;
+	int first_dword, last_dword;
+	int ret_val = 0;
+	int i;
+
+	if (eeprom->len == 0)
+		return -EOPNOTSUPP;
+
+	if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
+		return -EINVAL;
+
+	first_dword = eeprom->offset >> 2;
+	last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
+	eeprom_buff = kmalloc(AT_EEPROM_LEN, GFP_KERNEL);
+	if (eeprom_buff == NULL)
+		return -ENOMEM;
+
+	ptr = (u32 *)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 (!atl1e_read_eeprom(hw, first_dword * 4, &(eeprom_buff[0]))) {
+			ret_val = -EIO;
+			goto out;
+		}
+		ptr++;
+	}
+	if (((eeprom->offset + eeprom->len) & 3)) {
+		/* need read/modify/write of last changed EEPROM word */
+		/* only the first byte of the word is being modified */
+
+		if (!atl1e_read_eeprom(hw, last_dword * 4,
+				&(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 (!atl1e_write_eeprom(hw, ((first_dword + i) * 4),
+				  eeprom_buff[i])) {
+			ret_val = -EIO;
+			goto out;
+		}
+	}
+out:
+	kfree(eeprom_buff);
+	return ret_val;
+}
+
+static void atl1e_get_drvinfo(struct net_device *netdev,
+		struct ethtool_drvinfo *drvinfo)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+	strncpy(drvinfo->driver,  atl1e_driver_name, 32);
+	strncpy(drvinfo->version, atl1e_driver_version, 32);
+	strncpy(drvinfo->fw_version, "L1e", 32);
+	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+	drvinfo->n_stats = 0;
+	drvinfo->testinfo_len = 0;
+	drvinfo->regdump_len = atl1e_get_regs_len(netdev);
+	drvinfo->eedump_len = atl1e_get_eeprom_len(netdev);
+}
+
+static void atl1e_get_wol(struct net_device *netdev,
+			  struct ethtool_wolinfo *wol)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+	wol->supported = WAKE_MAGIC | WAKE_PHY;
+	wol->wolopts = 0;
+
+	if (adapter->wol & AT_WUFC_EX)
+		wol->wolopts |= WAKE_UCAST;
+	if (adapter->wol & AT_WUFC_MC)
+		wol->wolopts |= WAKE_MCAST;
+	if (adapter->wol & AT_WUFC_BC)
+		wol->wolopts |= WAKE_BCAST;
+	if (adapter->wol & AT_WUFC_MAG)
+		wol->wolopts |= WAKE_MAGIC;
+	if (adapter->wol & AT_WUFC_LNKC)
+		wol->wolopts |= WAKE_PHY;
+}
+
+static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+	if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE |
+			    WAKE_UCAST | WAKE_MCAST | WAKE_BCAST))
+		return -EOPNOTSUPP;
+	/* these settings will always override what we currently have */
+	adapter->wol = 0;
+
+	if (wol->wolopts & WAKE_MAGIC)
+		adapter->wol |= AT_WUFC_MAG;
+	if (wol->wolopts & WAKE_PHY)
+		adapter->wol |= AT_WUFC_LNKC;
+
+	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
+	return 0;
+}
+
+static int atl1e_nway_reset(struct net_device *netdev)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	if (netif_running(netdev))
+		atl1e_reinit_locked(adapter);
+	return 0;
+}
+
+static const struct ethtool_ops atl1e_ethtool_ops = {
+	.get_settings           = atl1e_get_settings,
+	.set_settings           = atl1e_set_settings,
+	.get_drvinfo            = atl1e_get_drvinfo,
+	.get_regs_len           = atl1e_get_regs_len,
+	.get_regs               = atl1e_get_regs,
+	.get_wol                = atl1e_get_wol,
+	.set_wol                = atl1e_set_wol,
+	.get_msglevel           = atl1e_get_msglevel,
+	.nway_reset             = atl1e_nway_reset,
+	.get_link               = ethtool_op_get_link,
+	.get_eeprom_len         = atl1e_get_eeprom_len,
+	.get_eeprom             = atl1e_get_eeprom,
+	.set_eeprom             = atl1e_set_eeprom,
+};
+
+void atl1e_set_ethtool_ops(struct net_device *netdev)
+{
+	SET_ETHTOOL_OPS(netdev, &atl1e_ethtool_ops);
+}
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1e/atl1e.h linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1e/atl1e.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1e/atl1e.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1e/atl1e.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,509 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ * Copyright(c) 2007 xiong huang <xiong.huang@atheros.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You 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 _ATL1E_H_
+#define _ATL1E_H_
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/udp.h>
+#include <linux/mii.h>
+#include <linux/io.h>
+#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
+#include <linux/tcp.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/workqueue.h>
+#include <net/checksum.h>
+#include <net/ip6_checksum.h>
+
+#include "atl1e_hw.h"
+
+#define PCI_REG_COMMAND	 0x04    /* PCI Command Register */
+#define CMD_IO_SPACE	 0x0001
+#define CMD_MEMORY_SPACE 0x0002
+#define CMD_BUS_MASTER   0x0004
+
+#define BAR_0   0
+#define BAR_1   1
+#define BAR_5   5
+
+/* Wake Up Filter Control */
+#define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
+#define AT_WUFC_MAG  0x00000002 /* Magic Packet Wakeup Enable */
+#define AT_WUFC_EX   0x00000004 /* Directed Exact Wakeup Enable */
+#define AT_WUFC_MC   0x00000008 /* Multicast Wakeup Enable */
+#define AT_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */
+
+#define SPEED_0		   0xffff
+#define HALF_DUPLEX        1
+#define FULL_DUPLEX        2
+
+/* Error Codes */
+#define AT_ERR_EEPROM      1
+#define AT_ERR_PHY         2
+#define AT_ERR_CONFIG      3
+#define AT_ERR_PARAM       4
+#define AT_ERR_MAC_TYPE    5
+#define AT_ERR_PHY_TYPE    6
+#define AT_ERR_PHY_SPEED   7
+#define AT_ERR_PHY_RES     8
+#define AT_ERR_TIMEOUT     9
+
+#define MAX_JUMBO_FRAME_SIZE 0x2000
+
+#define AT_VLAN_TAG_TO_TPD_TAG(_vlan, _tpd)    \
+	_tpd = (((_vlan) << (4)) | (((_vlan) >> 13) & 7) |\
+		 (((_vlan) >> 9) & 8))
+
+#define AT_TPD_TAG_TO_VLAN_TAG(_tpd, _vlan)    \
+	_vlan = (((_tpd) >> 8) | (((_tpd) & 0x77) << 9) |\
+		   (((_tdp) & 0x88) << 5))
+
+#define AT_MAX_RECEIVE_QUEUE    4
+#define AT_PAGE_NUM_PER_QUEUE   2
+
+#define AT_DMA_HI_ADDR_MASK     0xffffffff00000000ULL
+#define AT_DMA_LO_ADDR_MASK     0x00000000ffffffffULL
+
+#define AT_TX_WATCHDOG  (5 * HZ)
+#define AT_MAX_INT_WORK		10
+#define AT_TWSI_EEPROM_TIMEOUT 	100
+#define AT_HW_MAX_IDLE_DELAY 	10
+#define AT_SUSPEND_LINK_TIMEOUT 28
+
+#define AT_REGS_LEN	75
+#define AT_EEPROM_LEN 	512
+#define AT_ADV_MASK	(ADVERTISE_10_HALF  |\
+			 ADVERTISE_10_FULL  |\
+			 ADVERTISE_100_HALF |\
+			 ADVERTISE_100_FULL |\
+			 ADVERTISE_1000_FULL)
+
+/* tpd word 2 */
+#define TPD_BUFLEN_MASK 	0x3FFF
+#define TPD_BUFLEN_SHIFT        0
+#define TPD_DMAINT_MASK		0x0001
+#define TPD_DMAINT_SHIFT        14
+#define TPD_PKTNT_MASK          0x0001
+#define TPD_PKTINT_SHIFT        15
+#define TPD_VLANTAG_MASK        0xFFFF
+#define TPD_VLAN_SHIFT          16
+
+/* tpd word 3 bits 0:4 */
+#define TPD_EOP_MASK            0x0001
+#define TPD_EOP_SHIFT           0
+#define TPD_IP_VERSION_MASK	0x0001
+#define TPD_IP_VERSION_SHIFT	1	/* 0 : IPV4, 1 : IPV6 */
+#define TPD_INS_VL_TAG_MASK	0x0001
+#define TPD_INS_VL_TAG_SHIFT	2
+#define TPD_CC_SEGMENT_EN_MASK	0x0001
+#define TPD_CC_SEGMENT_EN_SHIFT	3
+#define TPD_SEGMENT_EN_MASK     0x0001
+#define TPD_SEGMENT_EN_SHIFT    4
+
+/* tdp word 3 bits 5:7 if ip version is 0 */
+#define TPD_IP_CSUM_MASK        0x0001
+#define TPD_IP_CSUM_SHIFT       5
+#define TPD_TCP_CSUM_MASK       0x0001
+#define TPD_TCP_CSUM_SHIFT      6
+#define TPD_UDP_CSUM_MASK       0x0001
+#define TPD_UDP_CSUM_SHIFT      7
+
+/* tdp word 3 bits 5:7 if ip version is 1 */
+#define TPD_V6_IPHLLO_MASK	0x0007
+#define TPD_V6_IPHLLO_SHIFT	7
+
+/* tpd word 3 bits 8:9 bit */
+#define TPD_VL_TAGGED_MASK      0x0001
+#define TPD_VL_TAGGED_SHIFT     8
+#define TPD_ETHTYPE_MASK        0x0001
+#define TPD_ETHTYPE_SHIFT       9
+
+/* tdp word 3 bits 10:13 if ip version is 0 */
+#define TDP_V4_IPHL_MASK	0x000F
+#define TPD_V4_IPHL_SHIFT	10
+
+/* tdp word 3 bits 10:13 if ip version is 1 */
+#define TPD_V6_IPHLHI_MASK	0x000F
+#define TPD_V6_IPHLHI_SHIFT	10
+
+/* tpd word 3 bit 14:31 if segment enabled */
+#define TPD_TCPHDRLEN_MASK      0x000F
+#define TPD_TCPHDRLEN_SHIFT     14
+#define TPD_HDRFLAG_MASK        0x0001
+#define TPD_HDRFLAG_SHIFT       18
+#define TPD_MSS_MASK            0x1FFF
+#define TPD_MSS_SHIFT           19
+
+/* tdp word 3 bit 16:31 if custom csum enabled */
+#define TPD_PLOADOFFSET_MASK    0x00FF
+#define TPD_PLOADOFFSET_SHIFT   16
+#define TPD_CCSUMOFFSET_MASK    0x00FF
+#define TPD_CCSUMOFFSET_SHIFT   24
+
+struct atl1e_tpd_desc {
+	__le64 buffer_addr;
+	__le32 word2;
+	__le32 word3;
+};
+
+/* how about 0x2000 */
+#define MAX_TX_BUF_LEN      0x2000
+#define MAX_TX_BUF_SHIFT    13
+/*#define MAX_TX_BUF_LEN  0x3000 */
+
+/* rrs word 1 bit 0:31 */
+#define RRS_RX_CSUM_MASK	0xFFFF
+#define RRS_RX_CSUM_SHIFT	0
+#define RRS_PKT_SIZE_MASK	0x3FFF
+#define RRS_PKT_SIZE_SHIFT	16
+#define RRS_CPU_NUM_MASK	0x0003
+#define	RRS_CPU_NUM_SHIFT	30
+
+#define	RRS_IS_RSS_IPV4		0x0001
+#define RRS_IS_RSS_IPV4_TCP	0x0002
+#define RRS_IS_RSS_IPV6		0x0004
+#define RRS_IS_RSS_IPV6_TCP	0x0008
+#define RRS_IS_IPV6		0x0010
+#define RRS_IS_IP_FRAG		0x0020
+#define RRS_IS_IP_DF		0x0040
+#define RRS_IS_802_3		0x0080
+#define RRS_IS_VLAN_TAG		0x0100
+#define RRS_IS_ERR_FRAME	0x0200
+#define RRS_IS_IPV4		0x0400
+#define RRS_IS_UDP		0x0800
+#define RRS_IS_TCP		0x1000
+#define RRS_IS_BCAST		0x2000
+#define RRS_IS_MCAST		0x4000
+#define RRS_IS_PAUSE		0x8000
+
+#define RRS_ERR_BAD_CRC		0x0001
+#define RRS_ERR_CODE		0x0002
+#define RRS_ERR_DRIBBLE		0x0004
+#define RRS_ERR_RUNT		0x0008
+#define RRS_ERR_RX_OVERFLOW	0x0010
+#define RRS_ERR_TRUNC		0x0020
+#define RRS_ERR_IP_CSUM		0x0040
+#define RRS_ERR_L4_CSUM		0x0080
+#define RRS_ERR_LENGTH		0x0100
+#define RRS_ERR_DES_ADDR	0x0200
+
+struct atl1e_recv_ret_status {
+	u16 seq_num;
+	u16 hash_lo;
+	__le32	word1;
+	u16 pkt_flag;
+	u16 err_flag;
+	u16 hash_hi;
+	u16 vtag;
+};
+
+enum atl1e_dma_req_block {
+	atl1e_dma_req_128 = 0,
+	atl1e_dma_req_256 = 1,
+	atl1e_dma_req_512 = 2,
+	atl1e_dma_req_1024 = 3,
+	atl1e_dma_req_2048 = 4,
+	atl1e_dma_req_4096 = 5
+};
+
+enum atl1e_rrs_type {
+	atl1e_rrs_disable = 0,
+	atl1e_rrs_ipv4 = 1,
+	atl1e_rrs_ipv4_tcp = 2,
+	atl1e_rrs_ipv6 = 4,
+	atl1e_rrs_ipv6_tcp = 8
+};
+
+enum atl1e_nic_type {
+	athr_l1e = 0,
+	athr_l2e_revA = 1,
+	athr_l2e_revB = 2
+};
+
+struct atl1e_hw_stats {
+	/* rx */
+	unsigned long rx_ok;	      /* The number of good packet received. */
+	unsigned long rx_bcast;       /* The number of good broadcast packet received. */
+	unsigned long rx_mcast;       /* The number of good multicast packet received. */
+	unsigned long rx_pause;       /* The number of Pause packet received. */
+	unsigned long rx_ctrl;        /* The number of Control packet received other than Pause frame. */
+	unsigned long rx_fcs_err;     /* The number of packets with bad FCS. */
+	unsigned long rx_len_err;     /* The number of packets with mismatch of length field and actual size. */
+	unsigned long rx_byte_cnt;    /* The number of bytes of good packet received. FCS is NOT included. */
+	unsigned long rx_runt;        /* The number of packets received that are less than 64 byte long and with good FCS. */
+	unsigned long rx_frag;        /* The number of packets received that are less than 64 byte long and with bad FCS. */
+	unsigned long rx_sz_64;       /* The number of good and bad packets received that are 64 byte long. */
+	unsigned long rx_sz_65_127;   /* The number of good and bad packets received that are between 65 and 127-byte long. */
+	unsigned long rx_sz_128_255;  /* The number of good and bad packets received that are between 128 and 255-byte long. */
+	unsigned long rx_sz_256_511;  /* The number of good and bad packets received that are between 256 and 511-byte long. */
+	unsigned long rx_sz_512_1023; /* The number of good and bad packets received that are between 512 and 1023-byte long. */
+	unsigned long rx_sz_1024_1518;    /* The number of good and bad packets received that are between 1024 and 1518-byte long. */
+	unsigned long rx_sz_1519_max; /* The number of good and bad packets received that are between 1519-byte and MTU. */
+	unsigned long rx_sz_ov;       /* The number of good and bad packets received that are more than MTU size truncated by Selene. */
+	unsigned long rx_rxf_ov;      /* The number of frame dropped due to occurrence of RX FIFO overflow. */
+	unsigned long rx_rrd_ov;      /* The number of frame dropped due to occurrence of RRD overflow. */
+	unsigned long rx_align_err;   /* Alignment Error */
+	unsigned long rx_bcast_byte_cnt;  /* The byte count of broadcast packet received, excluding FCS. */
+	unsigned long rx_mcast_byte_cnt;  /* The byte count of multicast packet received, excluding FCS. */
+	unsigned long rx_err_addr;    /* The number of packets dropped due to address filtering. */
+
+	/* tx */
+	unsigned long tx_ok;      /* The number of good packet transmitted. */
+	unsigned long tx_bcast;       /* The number of good broadcast packet transmitted. */
+	unsigned long tx_mcast;       /* The number of good multicast packet transmitted. */
+	unsigned long tx_pause;       /* The number of Pause packet transmitted. */
+	unsigned long tx_exc_defer;   /* The number of packets transmitted with excessive deferral. */
+	unsigned long tx_ctrl;        /* The number of packets transmitted is a control frame, excluding Pause frame. */
+	unsigned long tx_defer;       /* The number of packets transmitted that is deferred. */
+	unsigned long tx_byte_cnt;    /* The number of bytes of data transmitted. FCS is NOT included. */
+	unsigned long tx_sz_64;       /* The number of good and bad packets transmitted that are 64 byte long. */
+	unsigned long tx_sz_65_127;   /* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
+	unsigned long tx_sz_128_255;  /* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
+	unsigned long tx_sz_256_511;  /* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
+	unsigned long tx_sz_512_1023; /* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
+	unsigned long tx_sz_1024_1518;    /* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
+	unsigned long tx_sz_1519_max; /* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
+	unsigned long tx_1_col;       /* The number of packets subsequently transmitted successfully with a single prior collision. */
+	unsigned long tx_2_col;       /* The number of packets subsequently transmitted successfully with multiple prior collisions. */
+	unsigned long tx_late_col;    /* The number of packets transmitted with late collisions. */
+	unsigned long tx_abort_col;   /* The number of transmit packets aborted due to excessive collisions. */
+	unsigned long tx_underrun;    /* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
+	unsigned long tx_rd_eop;      /* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
+	unsigned long tx_len_err;     /* The number of transmit packets with length field does NOT match the actual frame size. */
+	unsigned long tx_trunc;       /* The number of transmit packets truncated due to size exceeding MTU. */
+	unsigned long tx_bcast_byte;  /* The byte count of broadcast packet transmitted, excluding FCS. */
+	unsigned long tx_mcast_byte;  /* The byte count of multicast packet transmitted, excluding FCS. */
+};
+
+struct atl1e_hw {
+	u8 __iomem      *hw_addr;            /* inner register address */
+	resource_size_t mem_rang;
+	struct atl1e_adapter *adapter;
+	enum atl1e_nic_type  nic_type;
+	u16 device_id;
+	u16 vendor_id;
+	u16 subsystem_id;
+	u16 subsystem_vendor_id;
+	u8  revision_id;
+	u16 pci_cmd_word;
+	u8 mac_addr[ETH_ALEN];
+	u8 perm_mac_addr[ETH_ALEN];
+	u8 preamble_len;
+	u16 max_frame_size;
+	u16 rx_jumbo_th;
+	u16 tx_jumbo_th;
+
+	u16 media_type;
+#define MEDIA_TYPE_AUTO_SENSOR  0
+#define MEDIA_TYPE_100M_FULL    1
+#define MEDIA_TYPE_100M_HALF    2
+#define MEDIA_TYPE_10M_FULL     3
+#define MEDIA_TYPE_10M_HALF     4
+
+	u16 autoneg_advertised;
+#define ADVERTISE_10_HALF               0x0001
+#define ADVERTISE_10_FULL               0x0002
+#define ADVERTISE_100_HALF              0x0004
+#define ADVERTISE_100_FULL              0x0008
+#define ADVERTISE_1000_HALF             0x0010 /* Not used, just FYI */
+#define ADVERTISE_1000_FULL             0x0020
+	u16 mii_autoneg_adv_reg;
+	u16 mii_1000t_ctrl_reg;
+
+	u16 imt;        /* Interrupt Moderator timer ( 2us resolution) */
+	u16 ict;        /* Interrupt Clear timer (2us resolution) */
+	u32 smb_timer;
+	u16 rrd_thresh; /* Threshold of number of RRD produced to trigger
+			  interrupt request */
+	u16 tpd_thresh;
+	u16 rx_count_down; /* 2us resolution */
+	u16 tx_count_down;
+
+	u8 tpd_burst;   /* Number of TPD to prefetch in cache-aligned burst. */
+	enum atl1e_rrs_type rrs_type;
+	u32 base_cpu;
+	u32 indirect_tab;
+
+	enum atl1e_dma_req_block dmar_block;
+	enum atl1e_dma_req_block dmaw_block;
+	u8 dmaw_dly_cnt;
+	u8 dmar_dly_cnt;
+
+	bool phy_configured;
+	bool re_autoneg;
+	bool emi_ca;
+};
+
+/*
+ * wrapper around a pointer to a socket buffer,
+ * so a DMA handle can be stored along with the buffer
+ */
+struct atl1e_tx_buffer {
+	struct sk_buff *skb;
+	u16 flags;
+#define ATL1E_TX_PCIMAP_SINGLE		0x0001
+#define ATL1E_TX_PCIMAP_PAGE		0x0002
+#define ATL1E_TX_PCIMAP_TYPE_MASK	0x0003
+	u16 length;
+	dma_addr_t dma;
+};
+
+#define ATL1E_SET_PCIMAP_TYPE(tx_buff, type) do {		\
+	((tx_buff)->flags) &= ~ATL1E_TX_PCIMAP_TYPE_MASK;	\
+	((tx_buff)->flags) |= (type);				\
+	} while (0)
+
+struct atl1e_rx_page {
+	dma_addr_t	dma;    /* receive rage DMA address */
+	u8		*addr;   /* receive rage virtual address */
+	dma_addr_t	write_offset_dma;  /* the DMA address which contain the
+					      receive data offset in the page */
+	u32		*write_offset_addr; /* the virtaul address which contain
+					     the receive data offset in the page */
+	u32		read_offset;       /* the offset where we have read */
+};
+
+struct atl1e_rx_page_desc {
+	struct atl1e_rx_page   rx_page[AT_PAGE_NUM_PER_QUEUE];
+	u8  rx_using;
+	u16 rx_nxseq;
+};
+
+/* transmit packet descriptor (tpd) ring */
+struct atl1e_tx_ring {
+	struct atl1e_tpd_desc *desc;  /* descriptor ring virtual address  */
+	dma_addr_t	   dma;    /* descriptor ring physical address */
+	u16       	   count;  /* the count of transmit rings  */
+	rwlock_t	   tx_lock;
+	u16		   next_to_use;
+	atomic_t	   next_to_clean;
+	struct atl1e_tx_buffer *tx_buffer;
+	dma_addr_t	   cmb_dma;
+	u32		   *cmb;
+};
+
+/* receive packet descriptor ring */
+struct atl1e_rx_ring {
+	void        	*desc;
+	dma_addr_t  	dma;
+	int         	size;
+	u32	    	page_size; /* bytes length of rxf page */
+	u32		real_page_size; /* real_page_size = page_size + jumbo + aliagn */
+	struct atl1e_rx_page_desc	rx_page_desc[AT_MAX_RECEIVE_QUEUE];
+};
+
+/* board specific private data structure */
+struct atl1e_adapter {
+	struct net_device   *netdev;
+	struct pci_dev      *pdev;
+	struct napi_struct  napi;
+	struct mii_if_info  mii;    /* MII interface info */
+	struct atl1e_hw        hw;
+	struct atl1e_hw_stats  hw_stats;
+
+	bool have_msi;
+	u32 wol;
+	u16 link_speed;
+	u16 link_duplex;
+
+	spinlock_t mdio_lock;
+	spinlock_t tx_lock;
+	atomic_t irq_sem;
+
+	struct work_struct reset_task;
+	struct work_struct link_chg_task;
+	struct timer_list watchdog_timer;
+	struct timer_list phy_config_timer;
+
+	/* All Descriptor memory */
+	dma_addr_t  	ring_dma;
+	void     	*ring_vir_addr;
+	u32             ring_size;
+
+	struct atl1e_tx_ring tx_ring;
+	struct atl1e_rx_ring rx_ring;
+	int num_rx_queues;
+	unsigned long flags;
+#define __AT_TESTING        0x0001
+#define __AT_RESETTING      0x0002
+#define __AT_DOWN           0x0003
+
+	u32 bd_number;     /* board number;*/
+	u32 pci_state[16];
+	u32 *config_space;
+};
+
+#define AT_WRITE_REG(a, reg, value) ( \
+		writel((value), ((a)->hw_addr + reg)))
+
+#define AT_WRITE_FLUSH(a) (\
+		readl((a)->hw_addr))
+
+#define AT_READ_REG(a, reg) ( \
+		readl((a)->hw_addr + reg))
+
+#define AT_WRITE_REGB(a, reg, value) (\
+		writeb((value), ((a)->hw_addr + reg)))
+
+#define AT_READ_REGB(a, reg) (\
+		readb((a)->hw_addr + reg))
+
+#define AT_WRITE_REGW(a, reg, value) (\
+		writew((value), ((a)->hw_addr + reg)))
+
+#define AT_READ_REGW(a, reg) (\
+		readw((a)->hw_addr + reg))
+
+#define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \
+		writel((value), (((a)->hw_addr + reg) + ((offset) << 2))))
+
+#define AT_READ_REG_ARRAY(a, reg, offset) ( \
+		readl(((a)->hw_addr + reg) + ((offset) << 2)))
+
+extern char atl1e_driver_name[];
+extern char atl1e_driver_version[];
+
+extern void atl1e_check_options(struct atl1e_adapter *adapter);
+extern int atl1e_up(struct atl1e_adapter *adapter);
+extern void atl1e_down(struct atl1e_adapter *adapter);
+extern void atl1e_reinit_locked(struct atl1e_adapter *adapter);
+extern s32 atl1e_reset_hw(struct atl1e_hw *hw);
+extern void atl1e_set_ethtool_ops(struct net_device *netdev);
+#endif /* _ATL1_E_H_ */
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_hw.c linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_hw.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_hw.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_hw.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,651 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You 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/pci.h>
+#include <linux/delay.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+
+#include "atl1e.h"
+
+/*
+ * check_eeprom_exist
+ * return 0 if eeprom exist
+ */
+int atl1e_check_eeprom_exist(struct atl1e_hw *hw)
+{
+	u32 value;
+
+	value = AT_READ_REG(hw, REG_SPI_FLASH_CTRL);
+	if (value & SPI_FLASH_CTRL_EN_VPD) {
+		value &= ~SPI_FLASH_CTRL_EN_VPD;
+		AT_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);
+	}
+	value = AT_READ_REGW(hw, REG_PCIE_CAP_LIST);
+	return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
+}
+
+void atl1e_hw_set_mac_addr(struct atl1e_hw *hw)
+{
+	u32 value;
+	/*
+	 * 00-0B-6A-F6-00-DC
+	 * 0:  6AF600DC 1: 000B
+	 * low dword
+	 */
+	value = (((u32)hw->mac_addr[2]) << 24) |
+		(((u32)hw->mac_addr[3]) << 16) |
+		(((u32)hw->mac_addr[4]) << 8)  |
+		(((u32)hw->mac_addr[5])) ;
+	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
+	/* hight dword */
+	value = (((u32)hw->mac_addr[0]) << 8) |
+		(((u32)hw->mac_addr[1])) ;
+	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
+}
+
+/*
+ * atl1e_get_permanent_address
+ * return 0 if get valid mac address,
+ */
+static int atl1e_get_permanent_address(struct atl1e_hw *hw)
+{
+	u32 addr[2];
+	u32 i;
+	u32 twsi_ctrl_data;
+	u8  eth_addr[ETH_ALEN];
+
+	if (is_valid_ether_addr(hw->perm_mac_addr))
+		return 0;
+
+	/* init */
+	addr[0] = addr[1] = 0;
+
+	if (!atl1e_check_eeprom_exist(hw)) {
+		/* eeprom exist */
+		twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
+		twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
+		AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
+		for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
+			msleep(10);
+			twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
+			if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
+				break;
+		}
+		if (i >= AT_TWSI_EEPROM_TIMEOUT)
+			return AT_ERR_TIMEOUT;
+	}
+
+	/* maybe MAC-address is from BIOS */
+	addr[0] = AT_READ_REG(hw, REG_MAC_STA_ADDR);
+	addr[1] = AT_READ_REG(hw, REG_MAC_STA_ADDR + 4);
+	*(u32 *) &eth_addr[2] = swab32(addr[0]);
+	*(u16 *) &eth_addr[0] = swab16(*(u16 *)&addr[1]);
+
+	if (is_valid_ether_addr(eth_addr)) {
+		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+		return 0;
+	}
+
+	return AT_ERR_EEPROM;
+}
+
+bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value)
+{
+	return true;
+}
+
+bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value)
+{
+	int i;
+	u32 control;
+
+	if (offset & 3)
+		return false; /* address do not align */
+
+	AT_WRITE_REG(hw, REG_VPD_DATA, 0);
+	control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
+	AT_WRITE_REG(hw, REG_VPD_CAP, control);
+
+	for (i = 0; i < 10; i++) {
+		msleep(2);
+		control = AT_READ_REG(hw, REG_VPD_CAP);
+		if (control & VPD_CAP_VPD_FLAG)
+			break;
+	}
+	if (control & VPD_CAP_VPD_FLAG) {
+		*p_value = AT_READ_REG(hw, REG_VPD_DATA);
+		return true;
+	}
+	return false; /* timeout */
+}
+
+void atl1e_force_ps(struct atl1e_hw *hw)
+{
+	AT_WRITE_REGW(hw, REG_GPHY_CTRL,
+			GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
+}
+
+/*
+ * Reads the adapter's MAC address from the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+int atl1e_read_mac_addr(struct atl1e_hw *hw)
+{
+	int err = 0;
+
+	err = atl1e_get_permanent_address(hw);
+	if (err)
+		return AT_ERR_EEPROM;
+	memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
+	return 0;
+}
+
+/*
+ * atl1e_hash_mc_addr
+ *  purpose
+ *      set hash value for a multicast address
+ */
+u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr)
+{
+	u32 crc32;
+	u32 value = 0;
+	int i;
+
+	crc32 = ether_crc_le(6, mc_addr);
+	for (i = 0; i < 32; i++)
+		value |= (((crc32 >> i) & 1) << (31 - i));
+
+	return value;
+}
+
+/*
+ * Sets the bit in the multicast table corresponding to the hash value.
+ * hw - Struct containing variables accessed by shared code
+ * hash_value - Multicast address hash value
+ */
+void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value)
+{
+	u32 hash_bit, hash_reg;
+	u32 mta;
+
+	/*
+	 * The HASH Table  is a register array of 2 32-bit registers.
+	 * It is treated like an array of 64 bits.  We want to set
+	 * bit BitArray[hash_value]. So we figure out what register
+	 * the bit is in, read it, OR in the new bit, then write
+	 * back the new value.  The register is determined by the
+	 * upper 7 bits of the hash value and the bit within that
+	 * register are determined by the lower 5 bits of the value.
+	 */
+	hash_reg = (hash_value >> 31) & 0x1;
+	hash_bit = (hash_value >> 26) & 0x1F;
+
+	mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);
+
+	mta |= (1 << hash_bit);
+
+	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
+}
+/*
+ * Reads the value from a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ */
+int atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+	u32 val;
+	int i;
+
+	val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
+		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
+		MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+
+	wmb();
+
+	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+		udelay(2);
+		val = AT_READ_REG(hw, REG_MDIO_CTRL);
+		if (!(val & (MDIO_START | MDIO_BUSY)))
+			break;
+		wmb();
+	}
+	if (!(val & (MDIO_START | MDIO_BUSY))) {
+		*phy_data = (u16)val;
+		return 0;
+	}
+
+	return AT_ERR_PHY;
+}
+
+/*
+ * Writes a value to a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ */
+int atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data)
+{
+	int i;
+	u32 val;
+
+	val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
+	       (reg_addr&MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
+	       MDIO_SUP_PREAMBLE |
+	       MDIO_START |
+	       MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+	wmb();
+
+	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+		udelay(2);
+		val = AT_READ_REG(hw, REG_MDIO_CTRL);
+		if (!(val & (MDIO_START | MDIO_BUSY)))
+			break;
+		wmb();
+	}
+
+	if (!(val & (MDIO_START | MDIO_BUSY)))
+		return 0;
+
+	return AT_ERR_PHY;
+}
+
+/*
+ * atl1e_init_pcie - init PCIE module
+ */
+static void atl1e_init_pcie(struct atl1e_hw *hw)
+{
+	u32 value;
+	/* comment 2lines below to save more power when sususpend
+	   value = LTSSM_TEST_MODE_DEF;
+	   AT_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value);
+	 */
+
+	/* pcie flow control mode change */
+	value = AT_READ_REG(hw, 0x1008);
+	value |= 0x8000;
+	AT_WRITE_REG(hw, 0x1008, value);
+}
+/*
+ * Configures PHY autoneg and flow control advertisement settings
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw)
+{
+	s32 ret_val;
+	u16 mii_autoneg_adv_reg;
+	u16 mii_1000t_ctrl_reg;
+
+	if (0 != hw->mii_autoneg_adv_reg)
+		return 0;
+	/* Read the MII Auto-Neg Advertisement Register (Address 4/9). */
+	mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
+	mii_1000t_ctrl_reg  = MII_AT001_CR_1000T_DEFAULT_CAP_MASK;
+
+	/*
+	 * Need to parse autoneg_advertised  and set up
+	 * the appropriate PHY registers.  First we will parse for
+	 * autoneg_advertised software override.  Since we can advertise
+	 * a plethora of combinations, we need to check each bit
+	 * individually.
+	 */
+
+	/*
+	 * First we clear all the 10/100 mb speed bits in the Auto-Neg
+	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
+	 * the  1000Base-T control Register (Address 9).
+	 */
+	mii_autoneg_adv_reg &= ~ADVERTISE_ALL;
+	mii_1000t_ctrl_reg  &= ~MII_AT001_CR_1000T_SPEED_MASK;
+
+	/*
+	 * Need to parse MediaType and setup the
+	 * appropriate PHY registers.
+	 */
+	switch (hw->media_type) {
+	case MEDIA_TYPE_AUTO_SENSOR:
+		mii_autoneg_adv_reg |= ADVERTISE_ALL;
+		hw->autoneg_advertised = ADVERTISE_ALL;
+		if (hw->nic_type == athr_l1e) {
+			mii_1000t_ctrl_reg |= ADVERTISE_1000FULL;
+			hw->autoneg_advertised |= ADVERTISE_1000_FULL;
+		}
+		break;
+
+	case MEDIA_TYPE_100M_FULL:
+		mii_autoneg_adv_reg   |= ADVERTISE_100FULL;
+		hw->autoneg_advertised = ADVERTISE_100_FULL;
+		break;
+
+	case MEDIA_TYPE_100M_HALF:
+		mii_autoneg_adv_reg   |= ADVERTISE_100_HALF;
+		hw->autoneg_advertised = ADVERTISE_100_HALF;
+		break;
+
+	case MEDIA_TYPE_10M_FULL:
+		mii_autoneg_adv_reg   |= ADVERTISE_10_FULL;
+		hw->autoneg_advertised = ADVERTISE_10_FULL;
+		break;
+
+	default:
+		mii_autoneg_adv_reg   |= ADVERTISE_10_HALF;
+		hw->autoneg_advertised = ADVERTISE_10_HALF;
+		break;
+	}
+
+	/* flow control fixed to enable all */
+	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;
+
+	ret_val = atl1e_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
+	if (ret_val)
+		return ret_val;
+
+	if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
+		ret_val = atl1e_write_phy_reg(hw, MII_CTRL1000,
+					   mii_1000t_ctrl_reg);
+		if (ret_val)
+			return ret_val;
+	}
+
+	return 0;
+}
+
+
+/*
+ * Resets the PHY and make all config validate
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Sets bit 15 and 12 of the MII control regiser (for F001 bug)
+ */
+int atl1e_phy_commit(struct atl1e_hw *hw)
+{
+	struct atl1e_adapter *adapter = hw->adapter;
+	int ret_val;
+	u16 phy_data;
+
+	phy_data = BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART;
+
+	ret_val = atl1e_write_phy_reg(hw, MII_BMCR, phy_data);
+	if (ret_val) {
+		u32 val;
+		int i;
+		/**************************************
+		 * pcie serdes link may be down !
+		 **************************************/
+		for (i = 0; i < 25; i++) {
+			msleep(1);
+			val = AT_READ_REG(hw, REG_MDIO_CTRL);
+			if (!(val & (MDIO_START | MDIO_BUSY)))
+				break;
+		}
+
+		if (0 != (val & (MDIO_START | MDIO_BUSY))) {
+			netdev_err(adapter->netdev,
+				   "pcie linkdown at least for 25ms\n");
+			return ret_val;
+		}
+
+		netdev_err(adapter->netdev, "pcie linkup after %d ms\n", i);
+	}
+	return 0;
+}
+
+int atl1e_phy_init(struct atl1e_hw *hw)
+{
+	struct atl1e_adapter *adapter = hw->adapter;
+	s32 ret_val;
+	u16 phy_val;
+
+	if (hw->phy_configured) {
+		if (hw->re_autoneg) {
+			hw->re_autoneg = false;
+			return atl1e_restart_autoneg(hw);
+		}
+		return 0;
+	}
+
+	/* RESET GPHY Core */
+	AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT);
+	msleep(2);
+	AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |
+		      GPHY_CTRL_EXT_RESET);
+	msleep(2);
+
+	/* patches */
+	/* p1. eable hibernation mode */
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0xB);
+	if (ret_val)
+		return ret_val;
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0xBC00);
+	if (ret_val)
+		return ret_val;
+	/* p2. set Class A/B for all modes */
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0);
+	if (ret_val)
+		return ret_val;
+	phy_val = 0x02ef;
+	/* remove Class AB */
+	/* phy_val = hw->emi_ca ? 0x02ef : 0x02df; */
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, phy_val);
+	if (ret_val)
+		return ret_val;
+	/* p3. 10B ??? */
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x12);
+	if (ret_val)
+		return ret_val;
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x4C04);
+	if (ret_val)
+		return ret_val;
+	/* p4. 1000T power */
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x4);
+	if (ret_val)
+		return ret_val;
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x8BBB);
+	if (ret_val)
+		return ret_val;
+
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x5);
+	if (ret_val)
+		return ret_val;
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x2C46);
+	if (ret_val)
+		return ret_val;
+
+	msleep(1);
+
+	/*Enable PHY LinkChange Interrupt */
+	ret_val = atl1e_write_phy_reg(hw, MII_INT_CTRL, 0xC00);
+	if (ret_val) {
+		netdev_err(adapter->netdev,
+			   "Error enable PHY linkChange Interrupt\n");
+		return ret_val;
+	}
+	/* setup AutoNeg parameters */
+	ret_val = atl1e_phy_setup_autoneg_adv(hw);
+	if (ret_val) {
+		netdev_err(adapter->netdev,
+			   "Error Setting up Auto-Negotiation\n");
+		return ret_val;
+	}
+	/* SW.Reset & En-Auto-Neg to restart Auto-Neg*/
+	netdev_dbg(adapter->netdev, "Restarting Auto-Negotiation\n");
+	ret_val = atl1e_phy_commit(hw);
+	if (ret_val) {
+		netdev_err(adapter->netdev, "Error resetting the phy\n");
+		return ret_val;
+	}
+
+	hw->phy_configured = true;
+
+	return 0;
+}
+
+/*
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ * hw - Struct containing variables accessed by shared code
+ * return : 0  or  idle status (if error)
+ */
+int atl1e_reset_hw(struct atl1e_hw *hw)
+{
+	struct atl1e_adapter *adapter = hw->adapter;
+	struct pci_dev *pdev = adapter->pdev;
+
+	u32 idle_status_data = 0;
+	u16 pci_cfg_cmd_word = 0;
+	int timeout = 0;
+
+	/* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */
+	pci_read_config_word(pdev, PCI_REG_COMMAND, &pci_cfg_cmd_word);
+	if ((pci_cfg_cmd_word & (CMD_IO_SPACE |
+				CMD_MEMORY_SPACE | CMD_BUS_MASTER))
+			!= (CMD_IO_SPACE | CMD_MEMORY_SPACE | CMD_BUS_MASTER)) {
+		pci_cfg_cmd_word |= (CMD_IO_SPACE |
+				     CMD_MEMORY_SPACE | CMD_BUS_MASTER);
+		pci_write_config_word(pdev, PCI_REG_COMMAND, pci_cfg_cmd_word);
+	}
+
+	/*
+	 * Issue Soft Reset to the MAC.  This will reset the chip's
+	 * transmit, receive, DMA.  It will not effect
+	 * the current PCI configuration.  The global reset bit is self-
+	 * clearing, and should clear within a microsecond.
+	 */
+	AT_WRITE_REG(hw, REG_MASTER_CTRL,
+			MASTER_CTRL_LED_MODE | MASTER_CTRL_SOFT_RST);
+	wmb();
+	msleep(1);
+
+	/* Wait at least 10ms for All module to be Idle */
+	for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
+		idle_status_data = AT_READ_REG(hw, REG_IDLE_STATUS);
+		if (idle_status_data == 0)
+			break;
+		msleep(1);
+		cpu_relax();
+	}
+
+	if (timeout >= AT_HW_MAX_IDLE_DELAY) {
+		netdev_err(adapter->netdev,
+			   "MAC state machine can't be idle since disabled for 10ms second\n");
+		return AT_ERR_TIMEOUT;
+	}
+
+	return 0;
+}
+
+
+/*
+ * Performs basic configuration of the adapter.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * Assumes that the controller has previously been reset and is in a
+ * post-reset uninitialized state. Initializes multicast table,
+ * and  Calls routines to setup link
+ * Leaves the transmit and receive units disabled and uninitialized.
+ */
+int atl1e_init_hw(struct atl1e_hw *hw)
+{
+	s32 ret_val = 0;
+
+	atl1e_init_pcie(hw);
+
+	/* Zero out the Multicast HASH table */
+	/* clear the old settings from the multicast hash table */
+	AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+	ret_val = atl1e_phy_init(hw);
+
+	return ret_val;
+}
+
+/*
+ * Detects the current speed and duplex settings of the hardware.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ */
+int atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex)
+{
+	int err;
+	u16 phy_data;
+
+	/* Read   PHY Specific Status Register (17) */
+	err = atl1e_read_phy_reg(hw, MII_AT001_PSSR, &phy_data);
+	if (err)
+		return err;
+
+	if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED))
+		return AT_ERR_PHY_RES;
+
+	switch (phy_data & MII_AT001_PSSR_SPEED) {
+	case MII_AT001_PSSR_1000MBS:
+		*speed = SPEED_1000;
+		break;
+	case MII_AT001_PSSR_100MBS:
+		*speed = SPEED_100;
+		break;
+	case MII_AT001_PSSR_10MBS:
+		*speed = SPEED_10;
+		break;
+	default:
+		return AT_ERR_PHY_SPEED;
+		break;
+	}
+
+	if (phy_data & MII_AT001_PSSR_DPLX)
+		*duplex = FULL_DUPLEX;
+	else
+		*duplex = HALF_DUPLEX;
+
+	return 0;
+}
+
+int atl1e_restart_autoneg(struct atl1e_hw *hw)
+{
+	int err = 0;
+
+	err = atl1e_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
+	if (err)
+		return err;
+
+	if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
+		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,
+			BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART);
+	return err;
+}
+
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_hw.h linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_hw.h
--- linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_hw.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_hw.h	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,690 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You 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 _ATHL1E_HW_H_
+#define _ATHL1E_HW_H_
+
+#include <linux/types.h>
+#include <linux/mii.h>
+
+struct atl1e_adapter;
+struct atl1e_hw;
+
+/* function prototype */
+s32 atl1e_reset_hw(struct atl1e_hw *hw);
+s32 atl1e_read_mac_addr(struct atl1e_hw *hw);
+s32 atl1e_init_hw(struct atl1e_hw *hw);
+s32 atl1e_phy_commit(struct atl1e_hw *hw);
+s32 atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex);
+u32 atl1e_auto_get_fc(struct atl1e_adapter *adapter, u16 duplex);
+u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr);
+void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value);
+s32 atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data);
+s32 atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data);
+s32 atl1e_validate_mdi_setting(struct atl1e_hw *hw);
+void atl1e_hw_set_mac_addr(struct atl1e_hw *hw);
+bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value);
+bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value);
+s32 atl1e_phy_enter_power_saving(struct atl1e_hw *hw);
+s32 atl1e_phy_leave_power_saving(struct atl1e_hw *hw);
+s32 atl1e_phy_init(struct atl1e_hw *hw);
+int atl1e_check_eeprom_exist(struct atl1e_hw *hw);
+void atl1e_force_ps(struct atl1e_hw *hw);
+s32 atl1e_restart_autoneg(struct atl1e_hw *hw);
+
+/* register definition */
+#define REG_PM_CTRLSTAT             0x44
+
+#define REG_PCIE_CAP_LIST           0x58
+
+#define REG_DEVICE_CAP              0x5C
+#define     DEVICE_CAP_MAX_PAYLOAD_MASK     0x7
+#define     DEVICE_CAP_MAX_PAYLOAD_SHIFT    0
+
+#define REG_DEVICE_CTRL             0x60
+#define     DEVICE_CTRL_MAX_PAYLOAD_MASK    0x7
+#define     DEVICE_CTRL_MAX_PAYLOAD_SHIFT   5
+#define     DEVICE_CTRL_MAX_RREQ_SZ_MASK    0x7
+#define     DEVICE_CTRL_MAX_RREQ_SZ_SHIFT   12
+
+#define REG_VPD_CAP                 0x6C
+#define     VPD_CAP_ID_MASK                 0xff
+#define     VPD_CAP_ID_SHIFT                0
+#define     VPD_CAP_NEXT_PTR_MASK           0xFF
+#define     VPD_CAP_NEXT_PTR_SHIFT          8
+#define     VPD_CAP_VPD_ADDR_MASK           0x7FFF
+#define     VPD_CAP_VPD_ADDR_SHIFT          16
+#define     VPD_CAP_VPD_FLAG                0x80000000
+
+#define REG_VPD_DATA                0x70
+
+#define REG_SPI_FLASH_CTRL          0x200
+#define     SPI_FLASH_CTRL_STS_NON_RDY      0x1
+#define     SPI_FLASH_CTRL_STS_WEN          0x2
+#define     SPI_FLASH_CTRL_STS_WPEN         0x80
+#define     SPI_FLASH_CTRL_DEV_STS_MASK     0xFF
+#define     SPI_FLASH_CTRL_DEV_STS_SHIFT    0
+#define     SPI_FLASH_CTRL_INS_MASK         0x7
+#define     SPI_FLASH_CTRL_INS_SHIFT        8
+#define     SPI_FLASH_CTRL_START            0x800
+#define     SPI_FLASH_CTRL_EN_VPD           0x2000
+#define     SPI_FLASH_CTRL_LDSTART          0x8000
+#define     SPI_FLASH_CTRL_CS_HI_MASK       0x3
+#define     SPI_FLASH_CTRL_CS_HI_SHIFT      16
+#define     SPI_FLASH_CTRL_CS_HOLD_MASK     0x3
+#define     SPI_FLASH_CTRL_CS_HOLD_SHIFT    18
+#define     SPI_FLASH_CTRL_CLK_LO_MASK      0x3
+#define     SPI_FLASH_CTRL_CLK_LO_SHIFT     20
+#define     SPI_FLASH_CTRL_CLK_HI_MASK      0x3
+#define     SPI_FLASH_CTRL_CLK_HI_SHIFT     22
+#define     SPI_FLASH_CTRL_CS_SETUP_MASK    0x3
+#define     SPI_FLASH_CTRL_CS_SETUP_SHIFT   24
+#define     SPI_FLASH_CTRL_EROM_PGSZ_MASK   0x3
+#define     SPI_FLASH_CTRL_EROM_PGSZ_SHIFT  26
+#define     SPI_FLASH_CTRL_WAIT_READY       0x10000000
+
+#define REG_SPI_ADDR                0x204
+
+#define REG_SPI_DATA                0x208
+
+#define REG_SPI_FLASH_CONFIG        0x20C
+#define     SPI_FLASH_CONFIG_LD_ADDR_MASK   0xFFFFFF
+#define     SPI_FLASH_CONFIG_LD_ADDR_SHIFT  0
+#define     SPI_FLASH_CONFIG_VPD_ADDR_MASK  0x3
+#define     SPI_FLASH_CONFIG_VPD_ADDR_SHIFT 24
+#define     SPI_FLASH_CONFIG_LD_EXIST       0x4000000
+
+
+#define REG_SPI_FLASH_OP_PROGRAM    0x210
+#define REG_SPI_FLASH_OP_SC_ERASE   0x211
+#define REG_SPI_FLASH_OP_CHIP_ERASE 0x212
+#define REG_SPI_FLASH_OP_RDID       0x213
+#define REG_SPI_FLASH_OP_WREN       0x214
+#define REG_SPI_FLASH_OP_RDSR       0x215
+#define REG_SPI_FLASH_OP_WRSR       0x216
+#define REG_SPI_FLASH_OP_READ       0x217
+
+#define REG_TWSI_CTRL               0x218
+#define     TWSI_CTRL_LD_OFFSET_MASK        0xFF
+#define     TWSI_CTRL_LD_OFFSET_SHIFT       0
+#define     TWSI_CTRL_LD_SLV_ADDR_MASK      0x7
+#define     TWSI_CTRL_LD_SLV_ADDR_SHIFT     8
+#define     TWSI_CTRL_SW_LDSTART            0x800
+#define     TWSI_CTRL_HW_LDSTART            0x1000
+#define     TWSI_CTRL_SMB_SLV_ADDR_MASK     0x0x7F
+#define     TWSI_CTRL_SMB_SLV_ADDR_SHIFT    15
+#define     TWSI_CTRL_LD_EXIST              0x400000
+#define     TWSI_CTRL_READ_FREQ_SEL_MASK    0x3
+#define     TWSI_CTRL_READ_FREQ_SEL_SHIFT   23
+#define     TWSI_CTRL_FREQ_SEL_100K         0
+#define     TWSI_CTRL_FREQ_SEL_200K         1
+#define     TWSI_CTRL_FREQ_SEL_300K         2
+#define     TWSI_CTRL_FREQ_SEL_400K         3
+#define     TWSI_CTRL_SMB_SLV_ADDR
+#define     TWSI_CTRL_WRITE_FREQ_SEL_MASK   0x3
+#define     TWSI_CTRL_WRITE_FREQ_SEL_SHIFT  24
+
+
+#define REG_PCIE_DEV_MISC_CTRL      0x21C
+#define     PCIE_DEV_MISC_CTRL_EXT_PIPE     0x2
+#define     PCIE_DEV_MISC_CTRL_RETRY_BUFDIS 0x1
+#define     PCIE_DEV_MISC_CTRL_SPIROM_EXIST 0x4
+#define     PCIE_DEV_MISC_CTRL_SERDES_ENDIAN    0x8
+#define     PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN   0x10
+
+#define REG_PCIE_PHYMISC	    0x1000
+#define PCIE_PHYMISC_FORCE_RCV_DET	0x4
+
+#define REG_LTSSM_TEST_MODE         0x12FC
+#define         LTSSM_TEST_MODE_DEF     0xE000
+
+/* Selene Master Control Register */
+#define REG_MASTER_CTRL             0x1400
+#define     MASTER_CTRL_SOFT_RST            0x1
+#define     MASTER_CTRL_MTIMER_EN           0x2
+#define     MASTER_CTRL_ITIMER_EN           0x4
+#define     MASTER_CTRL_MANUAL_INT          0x8
+#define     MASTER_CTRL_ITIMER2_EN          0x20
+#define     MASTER_CTRL_INT_RDCLR           0x40
+#define     MASTER_CTRL_LED_MODE	    0x200
+#define     MASTER_CTRL_REV_NUM_SHIFT       16
+#define     MASTER_CTRL_REV_NUM_MASK        0xff
+#define     MASTER_CTRL_DEV_ID_SHIFT        24
+#define     MASTER_CTRL_DEV_ID_MASK         0xff
+
+/* Timer Initial Value Register */
+#define REG_MANUAL_TIMER_INIT       0x1404
+
+
+/* IRQ ModeratorTimer Initial Value Register */
+#define REG_IRQ_MODU_TIMER_INIT     0x1408   /* w */
+#define REG_IRQ_MODU_TIMER2_INIT    0x140A   /* w */
+
+
+#define REG_GPHY_CTRL               0x140C
+#define     GPHY_CTRL_EXT_RESET         1
+#define     GPHY_CTRL_PIPE_MOD          2
+#define     GPHY_CTRL_TEST_MODE_MASK    3
+#define     GPHY_CTRL_TEST_MODE_SHIFT   2
+#define     GPHY_CTRL_BERT_START        0x10
+#define     GPHY_CTRL_GATE_25M_EN       0x20
+#define     GPHY_CTRL_LPW_EXIT          0x40
+#define     GPHY_CTRL_PHY_IDDQ          0x80
+#define     GPHY_CTRL_PHY_IDDQ_DIS      0x100
+#define     GPHY_CTRL_PCLK_SEL_DIS      0x200
+#define     GPHY_CTRL_HIB_EN            0x400
+#define     GPHY_CTRL_HIB_PULSE         0x800
+#define     GPHY_CTRL_SEL_ANA_RST       0x1000
+#define     GPHY_CTRL_PHY_PLL_ON        0x2000
+#define     GPHY_CTRL_PWDOWN_HW		0x4000
+#define     GPHY_CTRL_DEFAULT (\
+		GPHY_CTRL_PHY_PLL_ON	|\
+		GPHY_CTRL_SEL_ANA_RST	|\
+		GPHY_CTRL_HIB_PULSE	|\
+		GPHY_CTRL_HIB_EN)
+
+#define     GPHY_CTRL_PW_WOL_DIS (\
+		GPHY_CTRL_PHY_PLL_ON	|\
+		GPHY_CTRL_SEL_ANA_RST	|\
+		GPHY_CTRL_HIB_PULSE	|\
+		GPHY_CTRL_HIB_EN	|\
+		GPHY_CTRL_PWDOWN_HW	|\
+		GPHY_CTRL_PCLK_SEL_DIS	|\
+		GPHY_CTRL_PHY_IDDQ)
+
+/* IRQ Anti-Lost Timer Initial Value Register */
+#define REG_CMBDISDMA_TIMER         0x140E
+
+
+/* Block IDLE Status Register */
+#define REG_IDLE_STATUS  	0x1410
+#define     IDLE_STATUS_RXMAC       1    /* 1: RXMAC state machine is in non-IDLE state. 0: RXMAC is idling */
+#define     IDLE_STATUS_TXMAC       2    /* 1: TXMAC state machine is in non-IDLE state. 0: TXMAC is idling */
+#define     IDLE_STATUS_RXQ         4    /* 1: RXQ state machine is in non-IDLE state.   0: RXQ is idling   */
+#define     IDLE_STATUS_TXQ         8    /* 1: TXQ state machine is in non-IDLE state.   0: TXQ is idling   */
+#define     IDLE_STATUS_DMAR        0x10 /* 1: DMAR state machine is in non-IDLE state.  0: DMAR is idling  */
+#define     IDLE_STATUS_DMAW        0x20 /* 1: DMAW state machine is in non-IDLE state.  0: DMAW is idling  */
+#define     IDLE_STATUS_SMB         0x40 /* 1: SMB state machine is in non-IDLE state.   0: SMB is idling   */
+#define     IDLE_STATUS_CMB         0x80 /* 1: CMB state machine is in non-IDLE state.   0: CMB is idling   */
+
+/* MDIO Control Register */
+#define REG_MDIO_CTRL           0x1414
+#define     MDIO_DATA_MASK          0xffff  /* On MDIO write, the 16-bit control data to write to PHY MII management register */
+#define     MDIO_DATA_SHIFT         0       /* On MDIO read, the 16-bit status data that was read from the PHY MII management register*/
+#define     MDIO_REG_ADDR_MASK      0x1f    /* MDIO register address */
+#define     MDIO_REG_ADDR_SHIFT     16
+#define     MDIO_RW                 0x200000      /* 1: read, 0: write */
+#define     MDIO_SUP_PREAMBLE       0x400000      /* Suppress preamble */
+#define     MDIO_START              0x800000      /* Write 1 to initiate the MDIO master. And this bit is self cleared after one cycle*/
+#define     MDIO_CLK_SEL_SHIFT      24
+#define     MDIO_CLK_25_4           0
+#define     MDIO_CLK_25_6           2
+#define     MDIO_CLK_25_8           3
+#define     MDIO_CLK_25_10          4
+#define     MDIO_CLK_25_14          5
+#define     MDIO_CLK_25_20          6
+#define     MDIO_CLK_25_28          7
+#define     MDIO_BUSY               0x8000000
+#define     MDIO_AP_EN              0x10000000
+#define MDIO_WAIT_TIMES         10
+
+/* MII PHY Status Register */
+#define REG_PHY_STATUS           0x1418
+#define     PHY_STATUS_100M	      0x20000
+#define     PHY_STATUS_EMI_CA	      0x40000
+
+/* BIST Control and Status Register0 (for the Packet Memory) */
+#define REG_BIST0_CTRL              0x141c
+#define     BIST0_NOW                   0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */
+/* BIST process and reset to zero when BIST is done */
+#define     BIST0_SRAM_FAIL             0x2 /* 1: The SRAM failure is un-repairable because it has address */
+/* decoder failure or more than 1 cell stuck-to-x failure */
+#define     BIST0_FUSE_FLAG             0x4 /* 1: Indicating one cell has been fixed */
+
+/* BIST Control and Status Register1(for the retry buffer of PCI Express) */
+#define REG_BIST1_CTRL              0x1420
+#define     BIST1_NOW                   0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */
+/* BIST process and reset to zero when BIST is done */
+#define     BIST1_SRAM_FAIL             0x2 /* 1: The SRAM failure is un-repairable because it has address */
+/* decoder failure or more than 1 cell stuck-to-x failure.*/
+#define     BIST1_FUSE_FLAG             0x4
+
+/* SerDes Lock Detect Control and Status Register */
+#define REG_SERDES_LOCK             0x1424
+#define     SERDES_LOCK_DETECT          1  /* 1: SerDes lock detected . This signal comes from Analog SerDes */
+#define     SERDES_LOCK_DETECT_EN       2  /* 1: Enable SerDes Lock detect function */
+
+/* MAC Control Register  */
+#define REG_MAC_CTRL                0x1480
+#define     MAC_CTRL_TX_EN              1  /* 1: Transmit Enable */
+#define     MAC_CTRL_RX_EN              2  /* 1: Receive Enable */
+#define     MAC_CTRL_TX_FLOW            4  /* 1: Transmit Flow Control Enable */
+#define     MAC_CTRL_RX_FLOW            8  /* 1: Receive Flow Control Enable */
+#define     MAC_CTRL_LOOPBACK           0x10      /* 1: Loop back at G/MII Interface */
+#define     MAC_CTRL_DUPLX              0x20      /* 1: Full-duplex mode  0: Half-duplex mode */
+#define     MAC_CTRL_ADD_CRC            0x40      /* 1: Instruct MAC to attach CRC on all egress Ethernet frames */
+#define     MAC_CTRL_PAD                0x80      /* 1: Instruct MAC to pad short frames to 60-bytes, and then attach CRC. This bit has higher priority over CRC_EN */
+#define     MAC_CTRL_LENCHK             0x100     /* 1: Instruct MAC to check if length field matches the real packet length */
+#define     MAC_CTRL_HUGE_EN            0x200     /* 1: receive Jumbo frame enable */
+#define     MAC_CTRL_PRMLEN_SHIFT       10        /* Preamble length */
+#define     MAC_CTRL_PRMLEN_MASK        0xf
+#define     MAC_CTRL_RMV_VLAN           0x4000    /* 1: to remove VLAN Tag automatically from all receive packets */
+#define     MAC_CTRL_PROMIS_EN          0x8000    /* 1: Promiscuous Mode Enable */
+#define     MAC_CTRL_TX_PAUSE           0x10000   /* 1: transmit test pause */
+#define     MAC_CTRL_SCNT               0x20000   /* 1: shortcut slot time counter */
+#define     MAC_CTRL_SRST_TX            0x40000   /* 1: synchronized reset Transmit MAC module */
+#define     MAC_CTRL_TX_SIMURST         0x80000   /* 1: transmit simulation reset */
+#define     MAC_CTRL_SPEED_SHIFT        20        /* 10: gigabit 01:10M/100M */
+#define     MAC_CTRL_SPEED_MASK         0x300000
+#define     MAC_CTRL_SPEED_1000         2
+#define     MAC_CTRL_SPEED_10_100       1
+#define     MAC_CTRL_DBG_TX_BKPRESURE   0x400000  /* 1: transmit maximum backoff (half-duplex test bit) */
+#define     MAC_CTRL_TX_HUGE            0x800000  /* 1: transmit huge enable */
+#define     MAC_CTRL_RX_CHKSUM_EN       0x1000000 /* 1: RX checksum enable */
+#define     MAC_CTRL_MC_ALL_EN          0x2000000 /* 1: upload all multicast frame without error to system */
+#define     MAC_CTRL_BC_EN              0x4000000 /* 1: upload all broadcast frame without error to system */
+#define     MAC_CTRL_DBG                0x8000000 /* 1: upload all received frame to system (Debug Mode) */
+
+/* MAC IPG/IFG Control Register  */
+#define REG_MAC_IPG_IFG             0x1484
+#define     MAC_IPG_IFG_IPGT_SHIFT      0     /* Desired back to back inter-packet gap. The default is 96-bit time */
+#define     MAC_IPG_IFG_IPGT_MASK       0x7f
+#define     MAC_IPG_IFG_MIFG_SHIFT      8     /* Minimum number of IFG to enforce in between RX frames */
+#define     MAC_IPG_IFG_MIFG_MASK       0xff  /* Frame gap below such IFP is dropped */
+#define     MAC_IPG_IFG_IPGR1_SHIFT     16    /* 64bit Carrier-Sense window */
+#define     MAC_IPG_IFG_IPGR1_MASK      0x7f
+#define     MAC_IPG_IFG_IPGR2_SHIFT     24    /* 96-bit IPG window */
+#define     MAC_IPG_IFG_IPGR2_MASK      0x7f
+
+/* MAC STATION ADDRESS  */
+#define REG_MAC_STA_ADDR            0x1488
+
+/* Hash table for multicast address */
+#define REG_RX_HASH_TABLE           0x1490
+
+
+/* MAC Half-Duplex Control Register */
+#define REG_MAC_HALF_DUPLX_CTRL     0x1498
+#define     MAC_HALF_DUPLX_CTRL_LCOL_SHIFT   0      /* Collision Window */
+#define     MAC_HALF_DUPLX_CTRL_LCOL_MASK    0x3ff
+#define     MAC_HALF_DUPLX_CTRL_RETRY_SHIFT  12     /* Retransmission maximum, afterwards the packet will be discarded */
+#define     MAC_HALF_DUPLX_CTRL_RETRY_MASK   0xf
+#define     MAC_HALF_DUPLX_CTRL_EXC_DEF_EN   0x10000 /* 1: Allow the transmission of a packet which has been excessively deferred */
+#define     MAC_HALF_DUPLX_CTRL_NO_BACK_C    0x20000 /* 1: No back-off on collision, immediately start the retransmission */
+#define     MAC_HALF_DUPLX_CTRL_NO_BACK_P    0x40000 /* 1: No back-off on backpressure, immediately start the transmission after back pressure */
+#define     MAC_HALF_DUPLX_CTRL_ABEBE        0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */
+#define     MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT  20      /* Maximum binary exponential number */
+#define     MAC_HALF_DUPLX_CTRL_ABEBT_MASK   0xf
+#define     MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24      /* IPG to start JAM for collision based flow control in half-duplex */
+#define     MAC_HALF_DUPLX_CTRL_JAMIPG_MASK  0xf     /* mode. In unit of 8-bit time */
+
+/* Maximum Frame Length Control Register   */
+#define REG_MTU                     0x149c
+
+/* Wake-On-Lan control register */
+#define REG_WOL_CTRL                0x14a0
+#define     WOL_PATTERN_EN                  0x00000001
+#define     WOL_PATTERN_PME_EN              0x00000002
+#define     WOL_MAGIC_EN                    0x00000004
+#define     WOL_MAGIC_PME_EN                0x00000008
+#define     WOL_LINK_CHG_EN                 0x00000010
+#define     WOL_LINK_CHG_PME_EN             0x00000020
+#define     WOL_PATTERN_ST                  0x00000100
+#define     WOL_MAGIC_ST                    0x00000200
+#define     WOL_LINKCHG_ST                  0x00000400
+#define     WOL_CLK_SWITCH_EN               0x00008000
+#define     WOL_PT0_EN                      0x00010000
+#define     WOL_PT1_EN                      0x00020000
+#define     WOL_PT2_EN                      0x00040000
+#define     WOL_PT3_EN                      0x00080000
+#define     WOL_PT4_EN                      0x00100000
+#define     WOL_PT5_EN                      0x00200000
+#define     WOL_PT6_EN                      0x00400000
+/* WOL Length ( 2 DWORD ) */
+#define REG_WOL_PATTERN_LEN         0x14a4
+#define     WOL_PT_LEN_MASK                 0x7f
+#define     WOL_PT0_LEN_SHIFT               0
+#define     WOL_PT1_LEN_SHIFT               8
+#define     WOL_PT2_LEN_SHIFT               16
+#define     WOL_PT3_LEN_SHIFT               24
+#define     WOL_PT4_LEN_SHIFT               0
+#define     WOL_PT5_LEN_SHIFT               8
+#define     WOL_PT6_LEN_SHIFT               16
+
+/* Internal SRAM Partition Register */
+#define REG_SRAM_TRD_ADDR           0x1518
+#define REG_SRAM_TRD_LEN            0x151C
+#define REG_SRAM_RXF_ADDR           0x1520
+#define REG_SRAM_RXF_LEN            0x1524
+#define REG_SRAM_TXF_ADDR           0x1528
+#define REG_SRAM_TXF_LEN            0x152C
+#define REG_SRAM_TCPH_ADDR          0x1530
+#define REG_SRAM_PKTH_ADDR          0x1532
+
+/* Load Ptr Register */
+#define REG_LOAD_PTR                0x1534  /* Software sets this bit after the initialization of the head and tail */
+
+/*
+ * addresses of all descriptors, as well as the following descriptor
+ * control register, which triggers each function block to load the head
+ * pointer to prepare for the operation. This bit is then self-cleared
+ * after one cycle.
+ */
+
+/* Descriptor Control register  */
+#define REG_RXF3_BASE_ADDR_HI           0x153C
+#define REG_DESC_BASE_ADDR_HI           0x1540
+#define REG_RXF0_BASE_ADDR_HI           0x1540 /* share with DESC BASE ADDR HI */
+#define REG_HOST_RXF0_PAGE0_LO          0x1544
+#define REG_HOST_RXF0_PAGE1_LO          0x1548
+#define REG_TPD_BASE_ADDR_LO            0x154C
+#define REG_RXF1_BASE_ADDR_HI           0x1550
+#define REG_RXF2_BASE_ADDR_HI           0x1554
+#define REG_HOST_RXFPAGE_SIZE           0x1558
+#define REG_TPD_RING_SIZE               0x155C
+/* RSS about */
+#define REG_RSS_KEY0                    0x14B0
+#define REG_RSS_KEY1                    0x14B4
+#define REG_RSS_KEY2                    0x14B8
+#define REG_RSS_KEY3                    0x14BC
+#define REG_RSS_KEY4                    0x14C0
+#define REG_RSS_KEY5                    0x14C4
+#define REG_RSS_KEY6                    0x14C8
+#define REG_RSS_KEY7                    0x14CC
+#define REG_RSS_KEY8                    0x14D0
+#define REG_RSS_KEY9                    0x14D4
+#define REG_IDT_TABLE4                  0x14E0
+#define REG_IDT_TABLE5                  0x14E4
+#define REG_IDT_TABLE6                  0x14E8
+#define REG_IDT_TABLE7                  0x14EC
+#define REG_IDT_TABLE0                  0x1560
+#define REG_IDT_TABLE1                  0x1564
+#define REG_IDT_TABLE2                  0x1568
+#define REG_IDT_TABLE3                  0x156C
+#define REG_IDT_TABLE                   REG_IDT_TABLE0
+#define REG_RSS_HASH_VALUE              0x1570
+#define REG_RSS_HASH_FLAG               0x1574
+#define REG_BASE_CPU_NUMBER             0x157C
+
+
+/* TXQ Control Register */
+#define REG_TXQ_CTRL                0x1580
+#define     TXQ_CTRL_NUM_TPD_BURST_MASK     0xF
+#define     TXQ_CTRL_NUM_TPD_BURST_SHIFT    0
+#define     TXQ_CTRL_EN                     0x20  /* 1: Enable TXQ */
+#define     TXQ_CTRL_ENH_MODE               0x40  /* Performance enhancement mode, in which up to two back-to-back DMA read commands might be dispatched. */
+#define     TXQ_CTRL_TXF_BURST_NUM_SHIFT    16    /* Number of data byte to read in a cache-aligned burst. Each SRAM entry is 8-byte in length. */
+#define     TXQ_CTRL_TXF_BURST_NUM_MASK     0xffff
+
+/* Jumbo packet Threshold for task offload */
+#define REG_TX_EARLY_TH                     0x1584 /* Jumbo frame threshold in QWORD unit. Packet greater than */
+/* JUMBO_TASK_OFFLOAD_THRESHOLD will not be task offloaded. */
+#define     TX_TX_EARLY_TH_MASK             0x7ff
+#define     TX_TX_EARLY_TH_SHIFT            0
+
+
+/* RXQ Control Register */
+#define REG_RXQ_CTRL                0x15A0
+#define         RXQ_CTRL_PBA_ALIGN_32                   0   /* rx-packet alignment */
+#define         RXQ_CTRL_PBA_ALIGN_64                   1
+#define         RXQ_CTRL_PBA_ALIGN_128                  2
+#define         RXQ_CTRL_PBA_ALIGN_256                  3
+#define         RXQ_CTRL_Q1_EN				0x10
+#define         RXQ_CTRL_Q2_EN				0x20
+#define         RXQ_CTRL_Q3_EN				0x40
+#define         RXQ_CTRL_IPV6_XSUM_VERIFY_EN		0x80
+#define         RXQ_CTRL_HASH_TLEN_SHIFT                8
+#define         RXQ_CTRL_HASH_TLEN_MASK                 0xFF
+#define         RXQ_CTRL_HASH_TYPE_IPV4                 0x10000
+#define         RXQ_CTRL_HASH_TYPE_IPV4_TCP             0x20000
+#define         RXQ_CTRL_HASH_TYPE_IPV6                 0x40000
+#define         RXQ_CTRL_HASH_TYPE_IPV6_TCP             0x80000
+#define         RXQ_CTRL_RSS_MODE_DISABLE               0
+#define         RXQ_CTRL_RSS_MODE_SQSINT                0x4000000
+#define         RXQ_CTRL_RSS_MODE_MQUESINT              0x8000000
+#define         RXQ_CTRL_RSS_MODE_MQUEMINT              0xC000000
+#define         RXQ_CTRL_NIP_QUEUE_SEL_TBL              0x10000000
+#define         RXQ_CTRL_HASH_ENABLE                    0x20000000
+#define         RXQ_CTRL_CUT_THRU_EN                    0x40000000
+#define         RXQ_CTRL_EN                             0x80000000
+
+/* Rx jumbo packet threshold and rrd  retirement timer  */
+#define REG_RXQ_JMBOSZ_RRDTIM       0x15A4
+/*
+ * Jumbo packet threshold for non-VLAN packet, in QWORD (64-bit) unit.
+ * When the packet length greater than or equal to this value, RXQ
+ * shall start cut-through forwarding of the received packet.
+ */
+#define         RXQ_JMBOSZ_TH_MASK      0x7ff
+#define         RXQ_JMBOSZ_TH_SHIFT         0  /* RRD retirement timer. Decrement by 1 after every 512ns passes*/
+#define         RXQ_JMBO_LKAH_MASK          0xf
+#define         RXQ_JMBO_LKAH_SHIFT         11
+
+/* RXF flow control register */
+#define REG_RXQ_RXF_PAUSE_THRESH    0x15A8
+#define     RXQ_RXF_PAUSE_TH_HI_SHIFT       0
+#define     RXQ_RXF_PAUSE_TH_HI_MASK        0xfff
+#define     RXQ_RXF_PAUSE_TH_LO_SHIFT       16
+#define     RXQ_RXF_PAUSE_TH_LO_MASK        0xfff
+
+
+/* DMA Engine Control Register */
+#define REG_DMA_CTRL                0x15C0
+#define     DMA_CTRL_DMAR_IN_ORDER          0x1
+#define     DMA_CTRL_DMAR_ENH_ORDER         0x2
+#define     DMA_CTRL_DMAR_OUT_ORDER         0x4
+#define     DMA_CTRL_RCB_VALUE              0x8
+#define     DMA_CTRL_DMAR_BURST_LEN_SHIFT   4
+#define     DMA_CTRL_DMAR_BURST_LEN_MASK    7
+#define     DMA_CTRL_DMAW_BURST_LEN_SHIFT   7
+#define     DMA_CTRL_DMAW_BURST_LEN_MASK    7
+#define     DMA_CTRL_DMAR_REQ_PRI           0x400
+#define     DMA_CTRL_DMAR_DLY_CNT_MASK      0x1F
+#define     DMA_CTRL_DMAR_DLY_CNT_SHIFT     11
+#define     DMA_CTRL_DMAW_DLY_CNT_MASK      0xF
+#define     DMA_CTRL_DMAW_DLY_CNT_SHIFT     16
+#define     DMA_CTRL_TXCMB_EN               0x100000
+#define     DMA_CTRL_RXCMB_EN				0x200000
+
+
+/* CMB/SMB Control Register */
+#define REG_SMB_STAT_TIMER                      0x15C4
+#define REG_TRIG_RRD_THRESH                     0x15CA
+#define REG_TRIG_TPD_THRESH                     0x15C8
+#define REG_TRIG_TXTIMER                        0x15CC
+#define REG_TRIG_RXTIMER                        0x15CE
+
+/* HOST RXF Page 1,2,3 address */
+#define REG_HOST_RXF1_PAGE0_LO                  0x15D0
+#define REG_HOST_RXF1_PAGE1_LO                  0x15D4
+#define REG_HOST_RXF2_PAGE0_LO                  0x15D8
+#define REG_HOST_RXF2_PAGE1_LO                  0x15DC
+#define REG_HOST_RXF3_PAGE0_LO                  0x15E0
+#define REG_HOST_RXF3_PAGE1_LO                  0x15E4
+
+/* Mail box */
+#define REG_MB_RXF1_RADDR                       0x15B4
+#define REG_MB_RXF2_RADDR                       0x15B8
+#define REG_MB_RXF3_RADDR                       0x15BC
+#define REG_MB_TPD_PROD_IDX                     0x15F0
+
+/* RXF-Page 0-3  PageNo & Valid bit */
+#define REG_HOST_RXF0_PAGE0_VLD     0x15F4
+#define     HOST_RXF_VALID              1
+#define     HOST_RXF_PAGENO_SHIFT       1
+#define     HOST_RXF_PAGENO_MASK        0x7F
+#define REG_HOST_RXF0_PAGE1_VLD     0x15F5
+#define REG_HOST_RXF1_PAGE0_VLD     0x15F6
+#define REG_HOST_RXF1_PAGE1_VLD     0x15F7
+#define REG_HOST_RXF2_PAGE0_VLD     0x15F8
+#define REG_HOST_RXF2_PAGE1_VLD     0x15F9
+#define REG_HOST_RXF3_PAGE0_VLD     0x15FA
+#define REG_HOST_RXF3_PAGE1_VLD     0x15FB
+
+/* Interrupt Status Register */
+#define REG_ISR    0x1600
+#define  ISR_SMB   		1
+#define  ISR_TIMER		2       /* Interrupt when Timer is counted down to zero */
+/*
+ * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set
+ * in Table 51 Selene Master Control Register (Offset 0x1400).
+ */
+#define  ISR_MANUAL         	4
+#define  ISR_HW_RXF_OV          8        /* RXF overflow interrupt */
+#define  ISR_HOST_RXF0_OV       0x10
+#define  ISR_HOST_RXF1_OV       0x20
+#define  ISR_HOST_RXF2_OV       0x40
+#define  ISR_HOST_RXF3_OV       0x80
+#define  ISR_TXF_UN             0x100
+#define  ISR_RX0_PAGE_FULL      0x200
+#define  ISR_DMAR_TO_RST        0x400
+#define  ISR_DMAW_TO_RST        0x800
+#define  ISR_GPHY               0x1000
+#define  ISR_TX_CREDIT          0x2000
+#define  ISR_GPHY_LPW           0x4000    /* GPHY low power state interrupt */
+#define  ISR_RX_PKT             0x10000   /* One packet received, triggered by RFD */
+#define  ISR_TX_PKT             0x20000   /* One packet transmitted, triggered by TPD */
+#define  ISR_TX_DMA             0x40000
+#define  ISR_RX_PKT_1           0x80000
+#define  ISR_RX_PKT_2           0x100000
+#define  ISR_RX_PKT_3           0x200000
+#define  ISR_MAC_RX             0x400000
+#define  ISR_MAC_TX             0x800000
+#define  ISR_UR_DETECTED        0x1000000
+#define  ISR_FERR_DETECTED      0x2000000
+#define  ISR_NFERR_DETECTED     0x4000000
+#define  ISR_CERR_DETECTED      0x8000000
+#define  ISR_PHY_LINKDOWN       0x10000000
+#define  ISR_DIS_INT            0x80000000
+
+
+/* Interrupt Mask Register */
+#define REG_IMR 0x1604
+
+
+#define IMR_NORMAL_MASK (\
+		ISR_SMB	        |\
+		ISR_TXF_UN      |\
+		ISR_HW_RXF_OV   |\
+		ISR_HOST_RXF0_OV|\
+		ISR_MANUAL      |\
+		ISR_GPHY        |\
+		ISR_GPHY_LPW    |\
+		ISR_DMAR_TO_RST |\
+		ISR_DMAW_TO_RST |\
+		ISR_PHY_LINKDOWN|\
+		ISR_RX_PKT      |\
+		ISR_TX_PKT)
+
+#define ISR_TX_EVENT (ISR_TXF_UN | ISR_TX_PKT)
+#define ISR_RX_EVENT (ISR_HOST_RXF0_OV | ISR_HW_RXF_OV | ISR_RX_PKT)
+
+#define REG_MAC_RX_STATUS_BIN 0x1700
+#define REG_MAC_RX_STATUS_END 0x175c
+#define REG_MAC_TX_STATUS_BIN 0x1760
+#define REG_MAC_TX_STATUS_END 0x17c0
+
+/* Hardware Offset Register */
+#define REG_HOST_RXF0_PAGEOFF 0x1800
+#define REG_TPD_CONS_IDX      0x1804
+#define REG_HOST_RXF1_PAGEOFF 0x1808
+#define REG_HOST_RXF2_PAGEOFF 0x180C
+#define REG_HOST_RXF3_PAGEOFF 0x1810
+
+/* RXF-Page 0-3 Offset DMA Address */
+#define REG_HOST_RXF0_MB0_LO  0x1820
+#define REG_HOST_RXF0_MB1_LO  0x1824
+#define REG_HOST_RXF1_MB0_LO  0x1828
+#define REG_HOST_RXF1_MB1_LO  0x182C
+#define REG_HOST_RXF2_MB0_LO  0x1830
+#define REG_HOST_RXF2_MB1_LO  0x1834
+#define REG_HOST_RXF3_MB0_LO  0x1838
+#define REG_HOST_RXF3_MB1_LO  0x183C
+
+/* Tpd CMB DMA Address */
+#define REG_HOST_TX_CMB_LO    0x1840
+#define REG_HOST_SMB_ADDR_LO  0x1844
+
+/* DEBUG ADDR */
+#define REG_DEBUG_DATA0 0x1900
+#define REG_DEBUG_DATA1 0x1904
+
+/***************************** MII definition ***************************************/
+/* PHY Common Register */
+#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_LBRERROR                    0x18
+#define MII_RESV2                       0x1a
+
+#define MII_DBG_ADDR			0x1D
+#define MII_DBG_DATA			0x1E
+
+/* Autoneg Advertisement Register */
+#define MII_AR_DEFAULT_CAP_MASK                 0
+
+/* 1000BASE-T Control Register */
+#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 */
+#define MII_AT001_PSCR_POLARITY_REVERSAL        0x0002  /* 1=Polarity Reversal enabled */
+#define MII_AT001_PSCR_SQE_TEST                 0x0004  /* 1=SQE Test enabled */
+#define MII_AT001_PSCR_MAC_POWERDOWN            0x0008
+#define MII_AT001_PSCR_CLK125_DISABLE           0x0010  /* 1=CLK125 low,
+							 * 0=CLK125 toggling
+							 */
+#define MII_AT001_PSCR_MDI_MANUAL_MODE          0x0000  /* MDI Crossover Mode bits 6:5 */
+/* Manual MDI configuration */
+#define MII_AT001_PSCR_MDIX_MANUAL_MODE         0x0020  /* Manual MDIX configuration */
+#define MII_AT001_PSCR_AUTO_X_1000T             0x0040  /* 1000BASE-T: Auto crossover,
+							 *  100BASE-TX/10BASE-T:
+							 *  MDI Mode
+							 */
+#define MII_AT001_PSCR_AUTO_X_MODE              0x0060  /* Auto crossover enabled
+							 * all speeds.
+							 */
+#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE     0x0080
+/* 1=Enable Extended 10BASE-T distance
+ * (Lower 10BASE-T RX Threshold)
+ * 0=Normal 10BASE-T RX Threshold */
+#define MII_AT001_PSCR_MII_5BIT_ENABLE          0x0100
+/* 1=5-Bit interface in 100BASE-TX
+ * 0=MII interface in 100BASE-TX */
+#define MII_AT001_PSCR_SCRAMBLER_DISABLE        0x0200  /* 1=Scrambler disable */
+#define MII_AT001_PSCR_FORCE_LINK_GOOD          0x0400  /* 1=Force link good */
+#define MII_AT001_PSCR_ASSERT_CRS_ON_TX         0x0800  /* 1=Assert CRS on Transmit */
+#define MII_AT001_PSCR_POLARITY_REVERSAL_SHIFT    1
+#define MII_AT001_PSCR_AUTO_X_MODE_SHIFT          5
+#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
+/* AT001 PHY Specific Status Register */
+#define MII_AT001_PSSR_SPD_DPLX_RESOLVED        0x0800  /* 1=Speed & Duplex resolved */
+#define MII_AT001_PSSR_DPLX                     0x2000  /* 1=Duplex 0=Half Duplex */
+#define MII_AT001_PSSR_SPEED                    0xC000  /* Speed, bits 14:15 */
+#define MII_AT001_PSSR_10MBS                    0x0000  /* 00=10Mbs */
+#define MII_AT001_PSSR_100MBS                   0x4000  /* 01=100Mbs */
+#define MII_AT001_PSSR_1000MBS                  0x8000  /* 10=1000Mbs */
+
+#endif /*_ATHL1E_HW_H_*/
diff -druN linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_main.c linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
--- linux-libre-3.1-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_main.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-3.2-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_main.c	2012-01-04 18:55:44.000000000 -0500
@@ -0,0 +1,2557 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You 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 "atl1e.h"
+
+#define DRV_VERSION "1.0.0.7-NAPI"
+
+char atl1e_driver_name[] = "ATL1E";
+char atl1e_driver_version[] = DRV_VERSION;
+#define PCI_DEVICE_ID_ATTANSIC_L1E      0x1026
+/*
+ * atl1e_pci_tbl - PCI Device ID Table
+ *
+ * Wildcard entries (PCI_ANY_ID) should come last
+ * Last entry must be all 0s
+ *
+ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
+ *   Class, Class Mask, private data (not used) }
+ */
+static DEFINE_PCI_DEVICE_TABLE(atl1e_pci_tbl) = {
+	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1E)},
+	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, 0x1066)},
+	/* required last entry */
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, atl1e_pci_tbl);
+
+MODULE_AUTHOR("Atheros Corporation, <xiong.huang@atheros.com>, Jie Yang <jie.yang@atheros.com>");
+MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter);
+
+static const u16
+atl1e_rx_page_vld_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] =
+{
+	{REG_HOST_RXF0_PAGE0_VLD, REG_HOST_RXF0_PAGE1_VLD},
+	{REG_HOST_RXF1_PAGE0_VLD, REG_HOST_RXF1_PAGE1_VLD},
+	{REG_HOST_RXF2_PAGE0_VLD, REG_HOST_RXF2_PAGE1_VLD},
+	{REG_HOST_RXF3_PAGE0_VLD, REG_HOST_RXF3_PAGE1_VLD}
+};
+
+static const u16 atl1e_rx_page_hi_addr_regs[AT_MAX_RECEIVE_QUEUE] =
+{
+	REG_RXF0_BASE_ADDR_HI,
+	REG_RXF1_BASE_ADDR_HI,
+	REG_RXF2_BASE_ADDR_HI,
+	REG_RXF3_BASE_ADDR_HI
+};
+
+static const u16
+atl1e_rx_page_lo_addr_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] =
+{
+	{REG_HOST_RXF0_PAGE0_LO, REG_HOST_RXF0_PAGE1_LO},
+	{REG_HOST_RXF1_PAGE0_LO, REG_HOST_RXF1_PAGE1_LO},
+	{REG_HOST_RXF2_PAGE0_LO, REG_HOST_RXF2_PAGE1_LO},
+	{REG_HOST_RXF3_PAGE0_LO, REG_HOST_RXF3_PAGE1_LO}
+};
+
+static const u16
+atl1e_rx_page_write_offset_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] =
+{
+	{REG_HOST_RXF0_MB0_LO,  REG_HOST_RXF0_MB1_LO},
+	{REG_HOST_RXF1_MB0_LO,  REG_HOST_RXF1_MB1_LO},
+	{REG_HOST_RXF2_MB0_LO,  REG_HOST_RXF2_MB1_LO},
+	{REG_HOST_RXF3_MB0_LO,  REG_HOST_RXF3_MB1_LO}
+};
+
+static const u16 atl1e_pay_load_size[] = {
+	128, 256, 512, 1024, 2048, 4096,
+};
+
+/*
+ * atl1e_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_enable(struct atl1e_adapter *adapter)
+{
+	if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
+		AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+		AT_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK);
+		AT_WRITE_FLUSH(&adapter->hw);
+	}
+}
+
+/*
+ * atl1e_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_disable(struct atl1e_adapter *adapter)
+{
+	atomic_inc(&adapter->irq_sem);
+	AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
+	AT_WRITE_FLUSH(&adapter->hw);
+	synchronize_irq(adapter->pdev->irq);
+}
+
+/*
+ * atl1e_irq_reset - reset interrupt confiure on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_reset(struct atl1e_adapter *adapter)
+{
+	atomic_set(&adapter->irq_sem, 0);
+	AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+	AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
+	AT_WRITE_FLUSH(&adapter->hw);
+}
+
+/*
+ * atl1e_phy_config - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1e_phy_config(unsigned long data)
+{
+	struct atl1e_adapter *adapter = (struct atl1e_adapter *) data;
+	struct atl1e_hw *hw = &adapter->hw;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->mdio_lock, flags);
+	atl1e_restart_autoneg(hw);
+	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+}
+
+void atl1e_reinit_locked(struct atl1e_adapter *adapter)
+{
+
+	WARN_ON(in_interrupt());
+	while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+		msleep(1);
+	atl1e_down(adapter);
+	atl1e_up(adapter);
+	clear_bit(__AT_RESETTING, &adapter->flags);
+}
+
+static void atl1e_reset_task(struct work_struct *work)
+{
+	struct atl1e_adapter *adapter;
+	adapter = container_of(work, struct atl1e_adapter, reset_task);
+
+	atl1e_reinit_locked(adapter);
+}
+
+static int atl1e_check_link(struct atl1e_adapter *adapter)
+{
+	struct atl1e_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	int err = 0;
+	u16 speed, duplex, phy_data;
+
+	/* MII_BMSR must read twice */
+	atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
+	atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
+	if ((phy_data & BMSR_LSTATUS) == 0) {
+		/* link down */
+		if (netif_carrier_ok(netdev)) { /* old link state: Up */
+			u32 value;
+			/* disable rx */
+			value = AT_READ_REG(hw, REG_MAC_CTRL);
+			value &= ~MAC_CTRL_RX_EN;
+			AT_WRITE_REG(hw, REG_MAC_CTRL, value);
+			adapter->link_speed = SPEED_0;
+			netif_carrier_off(netdev);
+			netif_stop_queue(netdev);
+		}
+	} else {
+		/* Link Up */
+		err = atl1e_get_speed_and_duplex(hw, &speed, &duplex);
+		if (unlikely(err))
+			return err;
+
+		/* link result is our setting */
+		if (adapter->link_speed != speed ||
+		    adapter->link_duplex != duplex) {
+			adapter->link_speed  = speed;
+			adapter->link_duplex = duplex;
+			atl1e_setup_mac_ctrl(adapter);
+			netdev_info(netdev,
+				    "NIC Link is Up <%d Mbps %s Duplex>\n",
+				    adapter->link_speed,
+				    adapter->link_duplex == FULL_DUPLEX ?
+				    "Full" : "Half");
+		}
+
+		if (!netif_carrier_ok(netdev)) {
+			/* Link down -> Up */
+			netif_carrier_on(netdev);
+			netif_wake_queue(netdev);
+		}
+	}
+	return 0;
+}
+
+/*
+ * atl1e_link_chg_task - deal with link change event Out of interrupt context
+ * @netdev: network interface device structure
+ */
+static void atl1e_link_chg_task(struct work_struct *work)
+{
+	struct atl1e_adapter *adapter;
+	unsigned long flags;
+
+	adapter = container_of(work, struct atl1e_adapter, link_chg_task);
+	spin_lock_irqsave(&adapter->mdio_lock, flags);
+	atl1e_check_link(adapter);
+	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+}
+
+static void atl1e_link_chg_event(struct atl1e_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	u16 phy_data = 0;
+	u16 link_up = 0;
+
+	spin_lock(&adapter->mdio_lock);
+	atl1e_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+	atl1e_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+	spin_unlock(&adapter->mdio_lock);
+	link_up = phy_data & BMSR_LSTATUS;
+	/* notify upper layer link down ASAP */
+	if (!link_up) {
+		if (netif_carrier_ok(netdev)) {
+			/* old link state: Up */
+			netdev_info(netdev, "NIC Link is Down\n");
+			adapter->link_speed = SPEED_0;
+			netif_stop_queue(netdev);
+		}
+	}
+	schedule_work(&adapter->link_chg_task);
+}
+
+static void atl1e_del_timer(struct atl1e_adapter *adapter)
+{
+	del_timer_sync(&adapter->phy_config_timer);
+}
+
+static void atl1e_cancel_work(struct atl1e_adapter *adapter)
+{
+	cancel_work_sync(&adapter->reset_task);
+	cancel_work_sync(&adapter->link_chg_task);
+}
+
+/*
+ * atl1e_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ */
+static void atl1e_tx_timeout(struct net_device *netdev)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+	/* Do the reset outside of interrupt context */
+	schedule_work(&adapter->reset_task);
+}
+
+/*
+ * atl1e_set_multi - Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated.  This routine is
+ * responsible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ */
+static void atl1e_set_multi(struct net_device *netdev)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct atl1e_hw *hw = &adapter->hw;
+	struct netdev_hw_addr *ha;
+	u32 mac_ctrl_data = 0;
+	u32 hash_value;
+
+	/* Check for Promiscuous and All Multicast modes */
+	mac_ctrl_data = AT_READ_REG(hw, REG_MAC_CTRL);
+
+	if (netdev->flags & IFF_PROMISC) {
+		mac_ctrl_data |= MAC_CTRL_PROMIS_EN;
+	} else if (netdev->flags & IFF_ALLMULTI) {
+		mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;
+		mac_ctrl_data &= ~MAC_CTRL_PROMIS_EN;
+	} else {
+		mac_ctrl_data &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+	}
+
+	AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+
+	/* clear the old settings from the multicast hash table */
+	AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+	/* comoute mc addresses' hash value ,and put it into hash table */
+	netdev_for_each_mc_addr(ha, netdev) {
+		hash_value = atl1e_hash_mc_addr(hw, ha->addr);
+		atl1e_hash_set(hw, hash_value);
+	}
+}
+
+static void __atl1e_vlan_mode(u32 features, u32 *mac_ctrl_data)
+{
+	if (features & NETIF_F_HW_VLAN_RX) {
+		/* enable VLAN tag insert/strip */
+		*mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+	} else {
+		/* disable VLAN tag insert/strip */
+		*mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN;
+	}
+}
+
+static void atl1e_vlan_mode(struct net_device *netdev, u32 features)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	u32 mac_ctrl_data = 0;
+
+	netdev_dbg(adapter->netdev, "%s\n", __func__);
+
+	atl1e_irq_disable(adapter);
+	mac_ctrl_data = AT_READ_REG(&adapter->hw, REG_MAC_CTRL);
+	__atl1e_vlan_mode(features, &mac_ctrl_data);
+	AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data);
+	atl1e_irq_enable(adapter);
+}
+
+static void atl1e_restore_vlan(struct atl1e_adapter *adapter)
+{
+	netdev_dbg(adapter->netdev, "%s\n", __func__);
+	atl1e_vlan_mode(adapter->netdev, adapter->netdev->features);
+}
+
+/*
+ * atl1e_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1e_set_mac_addr(struct net_device *netdev, void *p)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	if (netif_running(netdev))
+		return -EBUSY;
+
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+
+	atl1e_hw_set_mac_addr(&adapter->hw);
+
+	return 0;
+}
+
+static u32 atl1e_fix_features(struct net_device *netdev, u32 features)
+{
+	/*
+	 * Since there is no support for separate rx/tx vlan accel
+	 * enable/disable make sure tx flag is always in same state as rx.
+	 */
+	if (features & NETIF_F_HW_VLAN_RX)
+		features |= NETIF_F_HW_VLAN_TX;
+	else
+		features &= ~NETIF_F_HW_VLAN_TX;
+
+	return features;
+}
+
+static int atl1e_set_features(struct net_device *netdev, u32 features)
+{
+	u32 changed = netdev->features ^ features;
+
+	if (changed & NETIF_F_HW_VLAN_RX)
+		atl1e_vlan_mode(netdev, features);
+
+	return 0;
+}
+
+/*
+ * atl1e_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1e_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	int old_mtu   = netdev->mtu;
+	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+
+	if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
+			(max_frame > MAX_JUMBO_FRAME_SIZE)) {
+		netdev_warn(adapter->netdev, "invalid MTU setting\n");
+		return -EINVAL;
+	}
+	/* set MTU */
+	if (old_mtu != new_mtu && netif_running(netdev)) {
+		while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+			msleep(1);
+		netdev->mtu = new_mtu;
+		adapter->hw.max_frame_size = new_mtu;
+		adapter->hw.rx_jumbo_th = (max_frame + 7) >> 3;
+		atl1e_down(adapter);
+		atl1e_up(adapter);
+		clear_bit(__AT_RESETTING, &adapter->flags);
+	}
+	return 0;
+}
+
+/*
+ *  caller should hold mdio_lock
+ */
+static int atl1e_mdio_read(struct net_device *netdev, int phy_id, int reg_num)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	u16 result;
+
+	atl1e_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result);
+	return result;
+}
+
+static void atl1e_mdio_write(struct net_device *netdev, int phy_id,
+			     int reg_num, int val)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+	atl1e_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val);
+}
+
+/*
+ * atl1e_mii_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1e_mii_ioctl(struct net_device *netdev,
+			   struct ifreq *ifr, int cmd)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct mii_ioctl_data *data = if_mii(ifr);
+	unsigned long flags;
+	int retval = 0;
+
+	if (!netif_running(netdev))
+		return -EINVAL;
+
+	spin_lock_irqsave(&adapter->mdio_lock, flags);
+	switch (cmd) {
+	case SIOCGMIIPHY:
+		data->phy_id = 0;
+		break;
+
+	case SIOCGMIIREG:
+		if (atl1e_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+				    &data->val_out)) {
+			retval = -EIO;
+			goto out;
+		}
+		break;
+
+	case SIOCSMIIREG:
+		if (data->reg_num & ~(0x1F)) {
+			retval = -EFAULT;
+			goto out;
+		}
+
+		netdev_dbg(adapter->netdev, "<atl1e_mii_ioctl> write %x %x\n",
+			   data->reg_num, data->val_in);
+		if (atl1e_write_phy_reg(&adapter->hw,
+				     data->reg_num, data->val_in)) {
+			retval = -EIO;
+			goto out;
+		}
+		break;
+
+	default:
+		retval = -EOPNOTSUPP;
+		break;
+	}
+out:
+	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+	return retval;
+
+}
+
+/*
+ * atl1e_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	switch (cmd) {
+	case SIOCGMIIPHY:
+	case SIOCGMIIREG:
+	case SIOCSMIIREG:
+		return atl1e_mii_ioctl(netdev, ifr, cmd);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void atl1e_setup_pcicmd(struct pci_dev *pdev)
+{
+	u16 cmd;
+
+	pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+	cmd &= ~(PCI_COMMAND_INTX_DISABLE | PCI_COMMAND_IO);
+	cmd |=  (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+	pci_write_config_word(pdev, PCI_COMMAND, cmd);
+
+	/*
+	 * some motherboards BIOS(PXE/EFI) driver may set PME
+	 * while they transfer control to OS (Windows/Linux)
+	 * so we should clear this bit before NIC work normally
+	 */
+	pci_write_config_dword(pdev, REG_PM_CTRLSTAT, 0);
+	msleep(1);
+}
+
+/*
+ * atl1e_alloc_queues - Allocate memory for all rings
+ * @adapter: board private structure to initialize
+ *
+ */
+static int __devinit atl1e_alloc_queues(struct atl1e_adapter *adapter)
+{
+	return 0;
+}
+
+/*
+ * atl1e_sw_init - Initialize general software structures (struct atl1e_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * atl1e_sw_init initializes the Adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ */
+static int __devinit atl1e_sw_init(struct atl1e_adapter *adapter)
+{
+	struct atl1e_hw *hw   = &adapter->hw;
+	struct pci_dev	*pdev = adapter->pdev;
+	u32 phy_status_data = 0;
+
+	adapter->wol = 0;
+	adapter->link_speed = SPEED_0;   /* hardware init */
+	adapter->link_duplex = FULL_DUPLEX;
+	adapter->num_rx_queues = 1;
+
+	/* PCI config space info */
+	hw->vendor_id = pdev->vendor;
+	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_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
+
+	phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS);
+	/* nic type */
+	if (hw->revision_id >= 0xF0) {
+		hw->nic_type = athr_l2e_revB;
+	} else {
+		if (phy_status_data & PHY_STATUS_100M)
+			hw->nic_type = athr_l1e;
+		else
+			hw->nic_type = athr_l2e_revA;
+	}
+
+	phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS);
+
+	if (phy_status_data & PHY_STATUS_EMI_CA)
+		hw->emi_ca = true;
+	else
+		hw->emi_ca = false;
+
+	hw->phy_configured = false;
+	hw->preamble_len = 7;
+	hw->max_frame_size = adapter->netdev->mtu;
+	hw->rx_jumbo_th = (hw->max_frame_size + ETH_HLEN +
+				VLAN_HLEN + ETH_FCS_LEN + 7) >> 3;
+
+	hw->rrs_type = atl1e_rrs_disable;
+	hw->indirect_tab = 0;
+	hw->base_cpu = 0;
+
+	/* need confirm */
+
+	hw->ict = 50000;                 /* 100ms */
+	hw->smb_timer = 200000;          /* 200ms  */
+	hw->tpd_burst = 5;
+	hw->rrd_thresh = 1;
+	hw->tpd_thresh = adapter->tx_ring.count / 2;
+	hw->rx_count_down = 4;  /* 2us resolution */
+	hw->tx_count_down = hw->imt * 4 / 3;
+	hw->dmar_block = atl1e_dma_req_1024;
+	hw->dmaw_block = atl1e_dma_req_1024;
+	hw->dmar_dly_cnt = 15;
+	hw->dmaw_dly_cnt = 4;
+
+	if (atl1e_alloc_queues(adapter)) {
+		netdev_err(adapter->netdev, "Unable to allocate memory for queues\n");
+		return -ENOMEM;
+	}
+
+	atomic_set(&adapter->irq_sem, 1);
+	spin_lock_init(&adapter->mdio_lock);
+	spin_lock_init(&adapter->tx_lock);
+
+	set_bit(__AT_DOWN, &adapter->flags);
+
+	return 0;
+}
+
+/*
+ * atl1e_clean_tx_ring - Free Tx-skb
+ * @adapter: board private structure
+ */
+static void atl1e_clean_tx_ring(struct atl1e_adapter *adapter)
+{
+	struct atl1e_tx_ring *tx_ring = (struct atl1e_tx_ring *)
+				&adapter->tx_ring;
+	struct atl1e_tx_buffer *tx_buffer = NULL;
+	struct pci_dev *pdev = adapter->pdev;
+	u16 index, ring_count;
+
+	if (tx_ring->desc == NULL || tx_ring->tx_buffer == NULL)
+		return;
+
+	ring_count = tx_ring->count;
+	/* first unmmap dma */
+	for (index = 0; index < ring_count; index++) {
+		tx_buffer = &tx_ring->tx_buffer[index];
+		if (tx_buffer->dma) {
+			if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE)
+				pci_unmap_single(pdev, tx_buffer->dma,
+					tx_buffer->length, PCI_DMA_TODEVICE);
+			else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE)
+				pci_unmap_page(pdev, tx_buffer->dma,
+					tx_buffer->length, PCI_DMA_TODEVICE);
+			tx_buffer->dma = 0;
+		}
+	}
+	/* second free skb */
+	for (index = 0; index < ring_count; index++) {
+		tx_buffer = &tx_ring->tx_buffer[index];
+		if (tx_buffer->skb) {
+			dev_kfree_skb_any(tx_buffer->skb);
+			tx_buffer->skb = NULL;
+		}
+	}
+	/* Zero out Tx-buffers */
+	memset(tx_ring->desc, 0, sizeof(struct atl1e_tpd_desc) *
+				ring_count);
+	memset(tx_ring->tx_buffer, 0, sizeof(struct atl1e_tx_buffer) *
+				ring_count);
+}
+
+/*
+ * atl1e_clean_rx_ring - Free rx-reservation skbs
+ * @adapter: board private structure
+ */
+static void atl1e_clean_rx_ring(struct atl1e_adapter *adapter)
+{
+	struct atl1e_rx_ring *rx_ring =
+		(struct atl1e_rx_ring *)&adapter->rx_ring;
+	struct atl1e_rx_page_desc *rx_page_desc = rx_ring->rx_page_desc;
+	u16 i, j;
+
+
+	if (adapter->ring_vir_addr == NULL)
+		return;
+	/* Zero out the descriptor ring */
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+			if (rx_page_desc[i].rx_page[j].addr != NULL) {
+				memset(rx_page_desc[i].rx_page[j].addr, 0,
+						rx_ring->real_page_size);
+			}
+		}
+	}
+}
+
+static void atl1e_cal_ring_size(struct atl1e_adapter *adapter, u32 *ring_size)
+{
+	*ring_size = ((u32)(adapter->tx_ring.count *
+		     sizeof(struct atl1e_tpd_desc) + 7
+			/* tx ring, qword align */
+		     + adapter->rx_ring.real_page_size * AT_PAGE_NUM_PER_QUEUE *
+			adapter->num_rx_queues + 31
+			/* rx ring,  32 bytes align */
+		     + (1 + AT_PAGE_NUM_PER_QUEUE * adapter->num_rx_queues) *
+			sizeof(u32) + 3));
+			/* tx, rx cmd, dword align   */
+}
+
+static void atl1e_init_ring_resources(struct atl1e_adapter *adapter)
+{
+	struct atl1e_rx_ring *rx_ring = NULL;
+
+	rx_ring = &adapter->rx_ring;
+
+	rx_ring->real_page_size = adapter->rx_ring.page_size
+				 + adapter->hw.max_frame_size
+				 + ETH_HLEN + VLAN_HLEN
+				 + ETH_FCS_LEN;
+	rx_ring->real_page_size = roundup(rx_ring->real_page_size, 32);
+	atl1e_cal_ring_size(adapter, &adapter->ring_size);
+
+	adapter->ring_vir_addr = NULL;
+	adapter->rx_ring.desc = NULL;
+	rwlock_init(&adapter->tx_ring.tx_lock);
+}
+
+/*
+ * Read / Write Ptr Initialize:
+ */
+static void atl1e_init_ring_ptrs(struct atl1e_adapter *adapter)
+{
+	struct atl1e_tx_ring *tx_ring = NULL;
+	struct atl1e_rx_ring *rx_ring = NULL;
+	struct atl1e_rx_page_desc *rx_page_desc = NULL;
+	int i, j;
+
+	tx_ring = &adapter->tx_ring;
+	rx_ring = &adapter->rx_ring;
+	rx_page_desc = rx_ring->rx_page_desc;
+
+	tx_ring->next_to_use = 0;
+	atomic_set(&tx_ring->next_to_clean, 0);
+
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		rx_page_desc[i].rx_using  = 0;
+		rx_page_desc[i].rx_nxseq = 0;
+		for (j = 0; j 